Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

* master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog:
  [WATCHDOG] Documentation/watchdog update
  [WATCHDOG] convert AT91RM9200 watchdog to platform driver
  [WATCHDOG] add WDIOC_GETTIMELEFT ioctl
  [WATCHDOG] Pre-Timeout flags
diff --git a/CREDITS b/CREDITS
index 9bf714a..85c7c70b7 100644
--- a/CREDITS
+++ b/CREDITS
@@ -24,6 +24,11 @@
 S: Iasi 6600
 S: Romania
 
+N: Mark Adler
+E: madler@alumni.caltech.edu
+W: http://alumnus.caltech.edu/~madler/
+D: zlib decompression
+
 N: Monalisa Agrawal
 E: magrawal@nortelnetworks.com
 D: Basic Interphase 5575 driver with UBR and ABR support.
@@ -1573,12 +1578,8 @@
 S: Czech Republic
 
 N: Niels Kristian Bech Jensen
-E: nkbj@image.dk
-W: http://www.image.dk/~nkbj
+E: nkbj1970@hotmail.com
 D: Miscellaneous kernel updates and fixes.
-S: Dr. Holsts Vej 34, lejl. 164
-S: DK-8230 Åbyhøj
-S: Denmark
 
 N: Michael K. Johnson
 E: johnsonm@redhat.com
diff --git a/Documentation/ABI/README b/Documentation/ABI/README
new file mode 100644
index 0000000..9feaf16
--- /dev/null
+++ b/Documentation/ABI/README
@@ -0,0 +1,77 @@
+This directory attempts to document the ABI between the Linux kernel and
+userspace, and the relative stability of these interfaces.  Due to the
+everchanging nature of Linux, and the differing maturity levels, these
+interfaces should be used by userspace programs in different ways.
+
+We have four different levels of ABI stability, as shown by the four
+different subdirectories in this location.  Interfaces may change levels
+of stability according to the rules described below.
+
+The different levels of stability are:
+
+  stable/
+	This directory documents the interfaces that the developer has
+	defined to be stable.  Userspace programs are free to use these
+	interfaces with no restrictions, and backward compatibility for
+	them will be guaranteed for at least 2 years.  Most interfaces
+	(like syscalls) are expected to never change and always be
+	available.
+
+  testing/
+	This directory documents interfaces that are felt to be stable,
+	as the main development of this interface has been completed.
+	The interface can be changed to add new features, but the
+	current interface will not break by doing this, unless grave
+	errors or security problems are found in them.  Userspace
+	programs can start to rely on these interfaces, but they must be
+	aware of changes that can occur before these interfaces move to
+	be marked stable.  Programs that use these interfaces are
+	strongly encouraged to add their name to the description of
+	these interfaces, so that the kernel developers can easily
+	notify them if any changes occur (see the description of the
+	layout of the files below for details on how to do this.)
+
+  obsolete/
+  	This directory documents interfaces that are still remaining in
+	the kernel, but are marked to be removed at some later point in
+	time.  The description of the interface will document the reason
+	why it is obsolete and when it can be expected to be removed.
+	The file Documentation/feature-removal-schedule.txt may describe
+	some of these interfaces, giving a schedule for when they will
+	be removed.
+
+  removed/
+	This directory contains a list of the old interfaces that have
+	been removed from the kernel.
+
+Every file in these directories will contain the following information:
+
+What:		Short description of the interface
+Date:		Date created
+KernelVersion:	Kernel version this feature first showed up in.
+Contact:	Primary contact for this interface (may be a mailing list)
+Description:	Long description of the interface and how to use it.
+Users:		All users of this interface who wish to be notified when
+		it changes.  This is very important for interfaces in
+		the "testing" stage, so that kernel developers can work
+		with userspace developers to ensure that things do not
+		break in ways that are unacceptable.  It is also
+		important to get feedback for these interfaces to make
+		sure they are working in a proper way and do not need to
+		be changed further.
+
+
+How things move between levels:
+
+Interfaces in stable may move to obsolete, as long as the proper
+notification is given.
+
+Interfaces may be removed from obsolete and the kernel as long as the
+documented amount of time has gone by.
+
+Interfaces in the testing state can move to the stable state when the
+developers feel they are finished.  They cannot be removed from the
+kernel tree without going through the obsolete state first.
+
+It's up to the developer to place their interfaces in the category they
+wish for it to start out in.
diff --git a/Documentation/ABI/obsolete/devfs b/Documentation/ABI/obsolete/devfs
new file mode 100644
index 0000000..b8b8739
--- /dev/null
+++ b/Documentation/ABI/obsolete/devfs
@@ -0,0 +1,13 @@
+What:		devfs
+Date:		July 2005
+Contact:	Greg Kroah-Hartman <gregkh@suse.de>
+Description:
+	devfs has been unmaintained for a number of years, has unfixable
+	races, contains a naming policy within the kernel that is
+	against the LSB, and can be replaced by using udev.
+	The files fs/devfs/*, include/linux/devfs_fs*.h will be removed,
+	along with the the assorted devfs function calls throughout the
+	kernel tree.
+
+Users:
+
diff --git a/Documentation/ABI/stable/syscalls b/Documentation/ABI/stable/syscalls
new file mode 100644
index 0000000..c3ae3e7
--- /dev/null
+++ b/Documentation/ABI/stable/syscalls
@@ -0,0 +1,10 @@
+What:		The kernel syscall interface
+Description:
+	This interface matches much of the POSIX interface and is based
+	on it and other Unix based interfaces.  It will only be added to
+	over time, and not have things removed from it.
+
+	Note that this interface is different for every architecture
+	that Linux supports.  Please see the architecture-specific
+	documentation for details on the syscall numbers that are to be
+	mapped to each syscall.
diff --git a/Documentation/ABI/stable/sysfs-module b/Documentation/ABI/stable/sysfs-module
new file mode 100644
index 0000000..75be431
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-module
@@ -0,0 +1,30 @@
+What:		/sys/module
+Description:
+	The /sys/module tree consists of the following structure:
+
+	/sys/module/MODULENAME
+		The name of the module that is in the kernel.  This
+		module name will show up either if the module is built
+		directly into the kernel, or if it is loaded as a
+		dyanmic module.
+
+	/sys/module/MODULENAME/parameters
+		This directory contains individual files that are each
+		individual parameters of the module that are able to be
+		changed at runtime.  See the individual module
+		documentation as to the contents of these parameters and
+		what they accomplish.
+
+		Note: The individual parameter names and values are not
+		considered stable, only the fact that they will be
+		placed in this location within sysfs.  See the
+		individual driver documentation for details as to the
+		stability of the different parameters.
+
+	/sys/module/MODULENAME/refcnt
+		If the module is able to be unloaded from the kernel, this file
+		will contain the current reference count of the module.
+
+		Note: If the module is built into the kernel, or if the
+		CONFIG_MODULE_UNLOAD kernel configuration value is not enabled,
+		this file will not be present.
diff --git a/Documentation/ABI/testing/sysfs-class b/Documentation/ABI/testing/sysfs-class
new file mode 100644
index 0000000..4b0cb89
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class
@@ -0,0 +1,16 @@
+What:		/sys/class/
+Date:		Febuary 2006
+Contact:	Greg Kroah-Hartman <gregkh@suse.de>
+Description:
+		The /sys/class directory will consist of a group of
+		subdirectories describing individual classes of devices
+		in the kernel.  The individual directories will consist
+		of either subdirectories, or symlinks to other
+		directories.
+
+		All programs that use this directory tree must be able
+		to handle both subdirectories or symlinks in order to
+		work properly.
+
+Users:
+	udev <linux-hotplug-devel@lists.sourceforge.net>
diff --git a/Documentation/ABI/testing/sysfs-devices b/Documentation/ABI/testing/sysfs-devices
new file mode 100644
index 0000000..6a25671
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-devices
@@ -0,0 +1,25 @@
+What:		/sys/devices
+Date:		February 2006
+Contact:	Greg Kroah-Hartman <gregkh@suse.de>
+Description:
+		The /sys/devices tree contains a snapshot of the
+		internal state of the kernel device tree.  Devices will
+		be added and removed dynamically as the machine runs,
+		and between different kernel versions, the layout of the
+		devices within this tree will change.
+
+		Please do not rely on the format of this tree because of
+		this.  If a program wishes to find different things in
+		the tree, please use the /sys/class structure and rely
+		on the symlinks there to point to the proper location
+		within the /sys/devices tree of the individual devices.
+		Or rely on the uevent messages to notify programs of
+		devices being added and removed from this tree to find
+		the location of those devices.
+
+		Note that sometimes not all devices along the directory
+		chain will have emitted uevent messages, so userspace
+		programs must be able to handle such occurrences.
+
+Users:
+	udev <linux-hotplug-devel@lists.sourceforge.net>
diff --git a/Documentation/CodingStyle b/Documentation/CodingStyle
index ce5d2c0..6d2412e 100644
--- a/Documentation/CodingStyle
+++ b/Documentation/CodingStyle
@@ -155,7 +155,83 @@
 See next chapter.
 
 
-		Chapter 5: Functions
+		Chapter 5: Typedefs
+
+Please don't use things like "vps_t".
+
+It's a _mistake_ to use typedef for structures and pointers. When you see a
+
+	vps_t a;
+
+in the source, what does it mean?
+
+In contrast, if it says
+
+	struct virtual_container *a;
+
+you can actually tell what "a" is.
+
+Lots of people think that typedefs "help readability". Not so. They are
+useful only for:
+
+ (a) totally opaque objects (where the typedef is actively used to _hide_
+     what the object is).
+
+     Example: "pte_t" etc. opaque objects that you can only access using
+     the proper accessor functions.
+
+     NOTE! Opaqueness and "accessor functions" are not good in themselves.
+     The reason we have them for things like pte_t etc. is that there
+     really is absolutely _zero_ portably accessible information there.
+
+ (b) Clear integer types, where the abstraction _helps_ avoid confusion
+     whether it is "int" or "long".
+
+     u8/u16/u32 are perfectly fine typedefs, although they fit into
+     category (d) better than here.
+
+     NOTE! Again - there needs to be a _reason_ for this. If something is
+     "unsigned long", then there's no reason to do
+
+	typedef unsigned long myflags_t;
+
+     but if there is a clear reason for why it under certain circumstances
+     might be an "unsigned int" and under other configurations might be
+     "unsigned long", then by all means go ahead and use a typedef.
+
+ (c) when you use sparse to literally create a _new_ type for
+     type-checking.
+
+ (d) New types which are identical to standard C99 types, in certain
+     exceptional circumstances.
+
+     Although it would only take a short amount of time for the eyes and
+     brain to become accustomed to the standard types like 'uint32_t',
+     some people object to their use anyway.
+
+     Therefore, the Linux-specific 'u8/u16/u32/u64' types and their
+     signed equivalents which are identical to standard types are
+     permitted -- although they are not mandatory in new code of your
+     own.
+
+     When editing existing code which already uses one or the other set
+     of types, you should conform to the existing choices in that code.
+
+ (e) Types safe for use in userspace.
+
+     In certain structures which are visible to userspace, we cannot
+     require C99 types and cannot use the 'u32' form above. Thus, we
+     use __u32 and similar types in all structures which are shared
+     with userspace.
+
+Maybe there are other cases too, but the rule should basically be to NEVER
+EVER use a typedef unless you can clearly match one of those rules.
+
+In general, a pointer, or a struct that has elements that can reasonably
+be directly accessed should _never_ be a typedef.
+
+
+		Chapter 6: Functions
 
 Functions should be short and sweet, and do just one thing.  They should
 fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
@@ -183,7 +259,7 @@
 to understand what you did 2 weeks from now.
 
 
-		Chapter 6: Centralized exiting of functions
+		Chapter 7: Centralized exiting of functions
 
 Albeit deprecated by some people, the equivalent of the goto statement is
 used frequently by compilers in form of the unconditional jump instruction.
@@ -220,7 +296,7 @@
 	return result;
 }
 
-		Chapter 7: Commenting
+		Chapter 8: Commenting
 
 Comments are good, but there is also a danger of over-commenting.  NEVER
 try to explain HOW your code works in a comment: it's much better to
@@ -240,7 +316,7 @@
 See the files Documentation/kernel-doc-nano-HOWTO.txt and scripts/kernel-doc
 for details.
 
-		Chapter 8: You've made a mess of it
+		Chapter 9: You've made a mess of it
 
 That's OK, we all do.  You've probably been told by your long-time Unix
 user helper that "GNU emacs" automatically formats the C sources for
@@ -288,7 +364,7 @@
 remember: "indent" is not a fix for bad programming.
 
 
-		Chapter 9: Configuration-files
+		Chapter 10: Configuration-files
 
 For configuration options (arch/xxx/Kconfig, and all the Kconfig files),
 somewhat different indentation is used.
@@ -313,7 +389,7 @@
 experimental options should be denoted (EXPERIMENTAL).
 
 
-		Chapter 10: Data structures
+		Chapter 11: Data structures
 
 Data structures that have visibility outside the single-threaded
 environment they are created and destroyed in should always have
@@ -344,7 +420,7 @@
 have a reference count on it, you almost certainly have a bug.
 
 
-		Chapter 11: Macros, Enums and RTL
+		Chapter 12: Macros, Enums and RTL
 
 Names of macros defining constants and labels in enums are capitalized.
 
@@ -399,7 +475,7 @@
 covers RTL which is used frequently with assembly language in the kernel.
 
 
-		Chapter 12: Printing kernel messages
+		Chapter 13: Printing kernel messages
 
 Kernel developers like to be seen as literate. Do mind the spelling
 of kernel messages to make a good impression. Do not use crippled
@@ -410,7 +486,7 @@
 Printing numbers in parentheses (%d) adds no value and should be avoided.
 
 
-		Chapter 13: Allocating memory
+		Chapter 14: Allocating memory
 
 The kernel provides the following general purpose memory allocators:
 kmalloc(), kzalloc(), kcalloc(), and vmalloc().  Please refer to the API
@@ -429,7 +505,7 @@
 language.
 
 
-		Chapter 14: The inline disease
+		Chapter 15: The inline disease
 
 There appears to be a common misperception that gcc has a magic "make me
 faster" speedup option called "inline". While the use of inlines can be
@@ -457,7 +533,7 @@
 
 
 
-		Chapter 15: References
+		Appendix I: References
 
 The C Programming Language, Second Edition
 by Brian W. Kernighan and Dennis M. Ritchie.
@@ -481,4 +557,4 @@
 http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
 
 --
-Last updated on 30 December 2005 by a community effort on LKML.
+Last updated on 30 April 2006.
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index ca02e04..3630a0d 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -62,6 +62,8 @@
      <sect1><title>Internal Functions</title>
 !Ikernel/exit.c
 !Ikernel/signal.c
+!Iinclude/linux/kthread.h
+!Ekernel/kthread.c
      </sect1>
 
      <sect1><title>Kernel objects manipulation</title>
@@ -114,9 +116,33 @@
      </sect1>
   </chapter>
 
+  <chapter id="kernel-lib">
+     <title>Basic Kernel Library Functions</title>
+
+     <para>
+       The Linux kernel provides more basic utility functions.
+     </para>
+
+     <sect1><title>Bitmap Operations</title>
+!Elib/bitmap.c
+!Ilib/bitmap.c
+     </sect1>
+
+     <sect1><title>Command-line Parsing</title>
+!Elib/cmdline.c
+     </sect1>
+
+     <sect1><title>CRC Functions</title>
+!Elib/crc16.c
+!Elib/crc32.c
+!Elib/crc-ccitt.c
+     </sect1>
+  </chapter>
+
   <chapter id="mm">
      <title>Memory Management in Linux</title>
      <sect1><title>The Slab Cache</title>
+!Iinclude/linux/slab.h
 !Emm/slab.c
      </sect1>
      <sect1><title>User Space Memory Access</title>
@@ -280,12 +306,13 @@
      <sect1><title>MTRR Handling</title>
 !Earch/i386/kernel/cpu/mtrr/main.c
      </sect1>
+
      <sect1><title>PCI Support Library</title>
 !Edrivers/pci/pci.c
 !Edrivers/pci/pci-driver.c
 !Edrivers/pci/remove.c
 !Edrivers/pci/pci-acpi.c
-<!-- kerneldoc does not understand to __devinit
+<!-- kerneldoc does not understand __devinit
 X!Edrivers/pci/search.c
  -->
 !Edrivers/pci/msi.c
@@ -314,6 +341,13 @@
      </sect1>
   </chapter>
 
+  <chapter id="firmware">
+     <title>Firmware Interfaces</title>
+     <sect1><title>DMI Interfaces</title>
+!Edrivers/firmware/dmi_scan.c
+     </sect1>
+  </chapter>
+
   <chapter id="devfs">
      <title>The Device File System</title>
 !Efs/devfs/base.c
@@ -331,6 +365,18 @@
 !Esecurity/security.c
   </chapter>
 
+  <chapter id="audit">
+     <title>Audit Interfaces</title>
+!Ekernel/audit.c
+!Ikernel/auditsc.c
+!Ikernel/auditfilter.c
+  </chapter>
+
+  <chapter id="accounting">
+     <title>Accounting Framework</title>
+!Ikernel/acct.c
+  </chapter>
+
   <chapter id="pmfuncs">
      <title>Power Management</title>
 !Ekernel/power/pm.c
@@ -390,7 +436,6 @@
      </sect1>
   </chapter>
 
-
   <chapter id="blkdev">
      <title>Block Devices</title>
 !Eblock/ll_rw_blk.c
@@ -401,6 +446,14 @@
 !Edrivers/char/misc.c
   </chapter>
 
+  <chapter id="parportdev">
+     <title>Parallel Port Devices</title>
+!Iinclude/linux/parport.h
+!Edrivers/parport/ieee1284.c
+!Edrivers/parport/share.c
+!Idrivers/parport/daisy.c
+  </chapter>
+
   <chapter id="viddev">
      <title>Video4Linux</title>
 !Edrivers/media/video/videodev.c
diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl
index 158ffe9..644c388 100644
--- a/Documentation/DocBook/kernel-locking.tmpl
+++ b/Documentation/DocBook/kernel-locking.tmpl
@@ -1590,7 +1590,7 @@
     <para>
       Our final dilemma is this: when can we actually destroy the
       removed element?  Remember, a reader might be stepping through
-      this element in the list right now: it we free this element and
+      this element in the list right now: if we free this element and
       the <symbol>next</symbol> pointer changes, the reader will jump
       off into garbage and crash.  We need to wait until we know that
       all the readers who were traversing the list when we deleted the
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index f869b03..e97c323 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -169,6 +169,22 @@
 
 	</sect2>
 
+	<sect2><title>PIO data read/write</title>
+	<programlisting>
+void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
+	</programlisting>
+
+	<para>
+All bmdma-style drivers must implement this hook.  This is the low-level
+operation that actually copies the data bytes during a PIO data
+transfer.
+Typically the driver
+will choose one of ata_pio_data_xfer_noirq(), ata_pio_data_xfer(), or
+ata_mmio_data_xfer().
+	</para>
+
+	</sect2>
+
 	<sect2><title>ATA command execute</title>
 	<programlisting>
 void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
@@ -204,11 +220,10 @@
 	<programlisting>
 u8   (*check_status)(struct ata_port *ap);
 u8   (*check_altstatus)(struct ata_port *ap);
-u8   (*check_err)(struct ata_port *ap);
 	</programlisting>
 
 	<para>
-	Reads the Status/AltStatus/Error ATA shadow register from
+	Reads the Status/AltStatus ATA shadow register from
 	hardware.  On some hardware, reading the Status register has
 	the side effect of clearing the interrupt condition.
 	Most drivers for taskfile-based hardware use
@@ -269,23 +284,6 @@
 
 	</sect2>
 
-	<sect2><title>Reset ATA bus</title>
-	<programlisting>
-void (*phy_reset) (struct ata_port *ap);
-	</programlisting>
-
-	<para>
-	The very first step in the probe phase.  Actions vary depending
-	on the bus type, typically.  After waking up the device and probing
-	for device presence (PATA and SATA), typically a soft reset
-	(SRST) will be performed.  Drivers typically use the helper
-	functions ata_bus_reset() or sata_phy_reset() for this hook.
-	Many SATA drivers use sata_phy_reset() or call it from within
-	their own phy_reset() functions.
-	</para>
-
-	</sect2>
-
 	<sect2><title>Control PCI IDE BMDMA engine</title>
 	<programlisting>
 void (*bmdma_setup) (struct ata_queued_cmd *qc);
@@ -354,16 +352,74 @@
 
 	</sect2>
 
-	<sect2><title>Timeout (error) handling</title>
+	<sect2><title>Exception and probe handling (EH)</title>
 	<programlisting>
 void (*eng_timeout) (struct ata_port *ap);
+void (*phy_reset) (struct ata_port *ap);
 	</programlisting>
 
 	<para>
-This is a high level error handling function, called from the
-error handling thread, when a command times out.  Most newer
-hardware will implement its own error handling code here.  IDE BMDMA
-drivers may use the helper function ata_eng_timeout().
+Deprecated.  Use ->error_handler() instead.
+	</para>
+
+	<programlisting>
+void (*freeze) (struct ata_port *ap);
+void (*thaw) (struct ata_port *ap);
+	</programlisting>
+
+	<para>
+ata_port_freeze() is called when HSM violations or some other
+condition disrupts normal operation of the port.  A frozen port
+is not allowed to perform any operation until the port is
+thawed, which usually follows a successful reset.
+	</para>
+
+	<para>
+The optional ->freeze() callback can be used for freezing the port
+hardware-wise (e.g. mask interrupt and stop DMA engine).  If a
+port cannot be frozen hardware-wise, the interrupt handler
+must ack and clear interrupts unconditionally while the port
+is frozen.
+	</para>
+	<para>
+The optional ->thaw() callback is called to perform the opposite of ->freeze():
+prepare the port for normal operation once again.  Unmask interrupts,
+start DMA engine, etc.
+	</para>
+
+	<programlisting>
+void (*error_handler) (struct ata_port *ap);
+	</programlisting>
+
+	<para>
+->error_handler() is a driver's hook into probe, hotplug, and recovery
+and other exceptional conditions.  The primary responsibility of an
+implementation is to call ata_do_eh() or ata_bmdma_drive_eh() with a set
+of EH hooks as arguments:
+	</para>
+
+	<para>
+'prereset' hook (may be NULL) is called during an EH reset, before any other actions
+are taken.
+	</para>
+
+	<para>
+'postreset' hook (may be NULL) is called after the EH reset is performed.  Based on
+existing conditions, severity of the problem, and hardware capabilities,
+	</para>
+
+	<para>
+Either 'softreset' (may be NULL) or 'hardreset' (may be NULL) will be
+called to perform the low-level EH reset.
+	</para>
+
+	<programlisting>
+void (*post_internal_cmd) (struct ata_queued_cmd *qc);
+	</programlisting>
+
+	<para>
+Perform any hardware-specific actions necessary to finish processing
+after executing a probe-time or EH-time command via ata_exec_internal().
 	</para>
 
 	</sect2>
diff --git a/Documentation/RCU/checklist.txt b/Documentation/RCU/checklist.txt
index 49e27cc..1d50cf0 100644
--- a/Documentation/RCU/checklist.txt
+++ b/Documentation/RCU/checklist.txt
@@ -144,9 +144,47 @@
 	whether the increased speed is worth it.
 
 8.	Although synchronize_rcu() is a bit slower than is call_rcu(),
-	it usually results in simpler code.  So, unless update performance
-	is important or the updaters cannot block, synchronize_rcu()
-	should be used in preference to call_rcu().
+	it usually results in simpler code.  So, unless update
+	performance is critically important or the updaters cannot block,
+	synchronize_rcu() should be used in preference to call_rcu().
+
+	An especially important property of the synchronize_rcu()
+	primitive is that it automatically self-limits: if grace periods
+	are delayed for whatever reason, then the synchronize_rcu()
+	primitive will correspondingly delay updates.  In contrast,
+	code using call_rcu() should explicitly limit update rate in
+	cases where grace periods are delayed, as failing to do so can
+	result in excessive realtime latencies or even OOM conditions.
+
+	Ways of gaining this self-limiting property when using call_rcu()
+	include:
+
+	a.	Keeping a count of the number of data-structure elements
+		used by the RCU-protected data structure, including those
+		waiting for a grace period to elapse.  Enforce a limit
+		on this number, stalling updates as needed to allow
+		previously deferred frees to complete.
+
+		Alternatively, limit only the number awaiting deferred
+		free rather than the total number of elements.
+
+	b.	Limiting update rate.  For example, if updates occur only
+		once per hour, then no explicit rate limiting is required,
+		unless your system is already badly broken.  The dcache
+		subsystem takes this approach -- updates are guarded
+		by a global lock, limiting their rate.
+
+	c.	Trusted update -- if updates can only be done manually by
+		superuser or some other trusted user, then it might not
+		be necessary to automatically limit them.  The theory
+		here is that superuser already has lots of ways to crash
+		the machine.
+
+	d.	Use call_rcu_bh() rather than call_rcu(), in order to take
+		advantage of call_rcu_bh()'s faster grace periods.
+
+	e.	Periodically invoke synchronize_rcu(), permitting a limited
+		number of updates per grace period.
 
 9.	All RCU list-traversal primitives, which include
 	list_for_each_rcu(), list_for_each_entry_rcu(),
diff --git a/Documentation/RCU/torture.txt b/Documentation/RCU/torture.txt
index e4c3815..a494859 100644
--- a/Documentation/RCU/torture.txt
+++ b/Documentation/RCU/torture.txt
@@ -7,7 +7,7 @@
 implementations.  It creates an rcutorture kernel module that can
 be loaded to run a torture test.  The test periodically outputs
 status messages via printk(), which can be examined via the dmesg
-command (perhaps grepping for "rcutorture").  The test is started
+command (perhaps grepping for "torture").  The test is started
 when the module is loaded, and stops when the module is unloaded.
 
 However, actually setting this config option to "y" results in the system
@@ -35,6 +35,19 @@
 		be printed -only- when the module is unloaded, and this
 		is the default.
 
+shuffle_interval
+		The number of seconds to keep the test threads affinitied
+		to a particular subset of the CPUs.  Used in conjunction
+		with test_no_idle_hz.
+
+test_no_idle_hz	Whether or not to test the ability of RCU to operate in
+		a kernel that disables the scheduling-clock interrupt to
+		idle CPUs.  Boolean parameter, "1" to test, "0" otherwise.
+
+torture_type	The type of RCU to test: "rcu" for the rcu_read_lock()
+		API, "rcu_bh" for the rcu_read_lock_bh() API, and "srcu"
+		for the "srcu_read_lock()" API.
+
 verbose		Enable debug printk()s.  Default is disabled.
 
 
@@ -42,14 +55,14 @@
 
 The statistics output is as follows:
 
-	rcutorture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
-	rcutorture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
-	rcutorture: Reader Pipe:  1466408 9747 0 0 0 0 0 0 0 0 0
-	rcutorture: Reader Batch:  1464477 11678 0 0 0 0 0 0 0 0
-	rcutorture: Free-Block Circulation:  1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
-	rcutorture: --- End of test
+	rcu-torture: --- Start of test: nreaders=16 stat_interval=0 verbose=0
+	rcu-torture: rtc: 0000000000000000 ver: 1916 tfle: 0 rta: 1916 rtaf: 0 rtf: 1915
+	rcu-torture: Reader Pipe:  1466408 9747 0 0 0 0 0 0 0 0 0
+	rcu-torture: Reader Batch:  1464477 11678 0 0 0 0 0 0 0 0
+	rcu-torture: Free-Block Circulation:  1915 1915 1915 1915 1915 1915 1915 1915 1915 1915 0
+	rcu-torture: --- End of test
 
-The command "dmesg | grep rcutorture:" will extract this information on
+The command "dmesg | grep torture:" will extract this information on
 most systems.  On more esoteric configurations, it may be necessary to
 use other commands to access the output of the printk()s used by
 the RCU torture test.  The printk()s use KERN_ALERT, so they should
@@ -115,8 +128,9 @@
 	modprobe rcutorture
 	sleep 100
 	rmmod rcutorture
-	dmesg | grep rcutorture:
+	dmesg | grep torture:
 
 The output can be manually inspected for the error flag of "!!!".
 One could of course create a more elaborate script that automatically
-checked for such errors.
+checked for such errors.  The "rmmod" command forces a "SUCCESS" or
+"FAILURE" indication to be printk()ed.
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 07cb93b..4f41a60 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -184,7 +184,17 @@
 	blocking, it registers a function and argument which are invoked
 	after all ongoing RCU read-side critical sections have completed.
 	This callback variant is particularly useful in situations where
-	it is illegal to block.
+	it is illegal to block or where update-side performance is
+	critically important.
+
+	However, the call_rcu() API should not be used lightly, as use
+	of the synchronize_rcu() API generally results in simpler code.
+	In addition, the synchronize_rcu() API has the nice property
+	of automatically limiting update rate should grace periods
+	be delayed.  This property results in system resilience in face
+	of denial-of-service attacks.  Code using call_rcu() should limit
+	update rate in order to gain this same sort of resilience.  See
+	checklist.txt for some approaches to limiting the update rate.
 
 rcu_assign_pointer()
 
@@ -790,7 +800,6 @@
 
 RCU grace period:
 
-	synchronize_kernel (deprecated)
 	synchronize_net
 	synchronize_sched
 	synchronize_rcu
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
new file mode 100644
index 0000000..8230098
--- /dev/null
+++ b/Documentation/SubmitChecklist
@@ -0,0 +1,57 @@
+Linux Kernel patch sumbittal checklist
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Here are some basic things that developers should do if they
+want to see their kernel patch submittals accepted quicker.
+
+These are all above and beyond the documentation that is provided
+in Documentation/SubmittingPatches and elsewhere about submitting
+Linux kernel patches.
+
+
+
+- Builds cleanly with applicable or modified CONFIG options =y, =m, and =n.
+  No gcc warnings/errors, no linker warnings/errors.
+
+- Passes allnoconfig, allmodconfig
+
+- Builds on multiple CPU arch-es by using local cross-compile tools
+  or something like PLM at OSDL.
+
+- ppc64 is a good architecture for cross-compilation checking because it
+  tends to use `unsigned long' for 64-bit quantities.
+
+- Matches kernel coding style(!)
+
+- Any new or modified CONFIG options don't muck up the config menu.
+
+- All new Kconfig options have help text.
+
+- Has been carefully reviewed with respect to relevant Kconfig
+  combinations.  This is very hard to get right with testing --
+  brainpower pays off here.
+
+- Check cleanly with sparse.
+
+- Use 'make checkstack' and 'make namespacecheck' and fix any
+  problems that they find.  Note:  checkstack does not point out
+  problems explicitly, but any one function that uses more than
+  512 bytes on the stack is a candidate for change.
+
+- Include kernel-doc to document global kernel APIs.  (Not required
+  for static functions, but OK there also.)  Use 'make htmldocs'
+  or 'make mandocs' to check the kernel-doc and fix any issues.
+
+- Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
+  CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
+  CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP all simultaneously
+  enabled.
+
+- Has been build- and runtime tested with and without CONFIG_SMP and
+  CONFIG_PREEMPT.
+
+- If the patch affects IO/Disk, etc: has been tested with and without
+  CONFIG_LBD.
+
+
+2006-APR-27
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
index 8c6ee68..3e46d2a 100644
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt
@@ -7,11 +7,13 @@
 ------------
 
   The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
-  by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and
-  the S3C2440 are supported CPUs.
+  by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
+  S3C2440 and S3C2442 devices are supported.
 
   Support for the S3C2400 series is in progress.
 
+  Support for the S3C2412 and S3C2413 CPUs is being merged.
+
 
 Configuration
 -------------
@@ -43,9 +45,18 @@
 
     Samsung's own development board, geared for PDA work.
 
+  Samsung/Aiji SMDK2412
+
+    The S3C2412 version of the SMDK2440.
+
+  Samsung/Aiji SMDK2413
+
+    The S3C2412 version of the SMDK2440.
+
   Samsung/Meritech SMDK2440
 
-    The S3C2440 compatible version of the SMDK2440
+    The S3C2440 compatible version of the SMDK2440, which has the
+    option of an S3C2440 or S3C2442 CPU module.
 
   Thorcom VR1000
 
@@ -211,24 +222,6 @@
   Lucas Correia Villa Real (S3C2400 port)
 
 
-Document Changes
-----------------
-
-  05 Sep 2004 - BJD - Added Document Changes section
-  05 Sep 2004 - BJD - Added Klaus Fetscher to list of contributors
-  25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors
-  25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge
-  21 Jan 2005 - BJD - Added rx3715, added Shannon to contributors
-  10 Feb 2005 - BJD - Added Guillaume Gourat to contributors
-  02 Mar 2005 - BJD - Added SMDK2440 to list of machines
-  06 Mar 2005 - BJD - Added Christer Weinigel
-  08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
-  08 Mar 2005 - BJD - Added section on adding machines
-  09 Sep 2005 - BJD - Added section on platform data
-  11 Feb 2006 - BJD - Added I2C, RTC and Watchdog sections
-  11 Feb 2006 - BJD - Added Osiris machine, and S3C2400 information
-
-
 Document Author
 ---------------
 
diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2412.txt b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt
new file mode 100644
index 0000000..cb82a7f
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt
@@ -0,0 +1,120 @@
+		S3C2412 ARM Linux Overview
+		==========================
+
+Introduction
+------------
+
+  The S3C2412 is part of the S3C24XX range of ARM9 System-on-Chip CPUs
+  from Samsung. This part has an ARM926-EJS core, capable of running up
+  to 266MHz (see data-sheet for more information)
+
+
+Clock
+-----
+
+  The core clock code provides a set of clocks to the drivers, and allows
+  for source selection and a number of other features.
+
+
+Power
+-----
+
+  No support for suspend/resume to RAM in the current system.
+
+
+DMA
+---
+
+  No current support for DMA.
+
+
+GPIO
+----
+
+  There is support for setting the GPIO to input/output/special function
+  and reading or writing to them.
+
+
+UART
+----
+
+  The UART hardware is similar to the S3C2440, and is supported by the
+  s3c2410 driver in the drivers/serial directory.
+
+
+NAND
+----
+
+  The NAND hardware is similar to the S3C2440, and is supported by the
+  s3c2410 driver in the drivers/mtd/nand directory.
+
+
+USB Host
+--------
+
+  The USB hardware is similar to the S3C2410, with extended clock source
+  control. The OHCI portion is supported by the ohci-s3c2410 driver, and
+  the clock control selection is supported by the core clock code.
+
+
+USB Device
+----------
+
+  No current support in the kernel
+
+
+IRQs
+----
+
+  All the standard, and external interrupt sources are supported. The
+  extra sub-sources are not yet supported.
+
+
+RTC
+---
+
+  The RTC hardware is similar to the S3C2410, and is supported by the
+  s3c2410-rtc driver.
+
+
+Watchdog
+--------
+
+  The watchdog harware is the same as the S3C2410, and is supported by
+  the s3c2410_wdt driver.
+
+
+MMC/SD/SDIO
+-----------
+
+  No current support for the MMC/SD/SDIO block.
+
+IIC
+---
+
+  The IIC hardware is the same as the S3C2410, and is supported by the
+  i2c-s3c24xx driver.
+
+
+IIS
+---
+
+  No current support for the IIS interface.
+
+
+SPI
+---
+
+  No current support for the SPI interfaces.
+
+
+ATA
+---
+
+  No current support for the on-board ATA block.
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2006 Simtec Electronics
diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2413.txt b/Documentation/arm/Samsung-S3C24XX/S3C2413.txt
new file mode 100644
index 0000000..ab2a888
--- /dev/null
+++ b/Documentation/arm/Samsung-S3C24XX/S3C2413.txt
@@ -0,0 +1,21 @@
+		S3C2413 ARM Linux Overview
+		==========================
+
+Introduction
+------------
+
+  The S3C2413 is an extended version of the S3C2412, with an camera
+  interface and mobile DDR memory support. See the S3C2412 support
+  documentation for more information.
+
+
+Camera Interface
+---------------
+
+  This block is currently not supported.
+
+
+Document Author
+---------------
+
+Ben Dooks, (c) 2006 Simtec Electronics
diff --git a/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
new file mode 100644
index 0000000..1e6a23f
--- /dev/null
+++ b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
@@ -0,0 +1,61 @@
+README on the ADC/Touchscreen Controller
+========================================
+
+The LH79524 and LH7A404 include a built-in Analog to Digital
+controller (ADC) that is used to process input from a touchscreen.
+The driver only implements a four-wire touch panel protocol.
+
+The touchscreen driver is maintenance free except for the pen-down or
+touch threshold.  Some resistive displays and board combinations may
+require tuning of this threshold.  The driver exposes some of it's
+internal state in the sys filesystem.  If the kernel is configured
+with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a
+directory
+
+  /sys/devices/platform/adc-lh7.0
+
+containing these files.
+
+  -r--r--r--    1 root     root         4096 Jan  1 00:00 samples
+  -rw-r--r--    1 root     root         4096 Jan  1 00:00 threshold
+  -r--r--r--    1 root     root         4096 Jan  1 00:00 threshold_range
+
+The threshold is the current touch threshold.  It defaults to 750 on
+most targets.
+
+  # cat threshold
+ 750
+
+The threshold_range contains the range of valid values for the
+threshold.  Values outside of this range will be silently ignored.
+
+  # cat threshold_range
+  0 1023
+
+To change the threshold, write a value to the threshold file.
+
+  # echo 500 > threshold
+  # cat threshold
+  500
+
+The samples file contains the most recently sampled values from the
+ADC.  There are 12.  Below are typical of the last sampled values when
+the pen has been released.  The first two and last two samples are for
+detecting whether or not the pen is down.  The third through sixth are
+X coordinate samples.  The seventh through tenth are Y coordinate
+samples.
+
+  # cat samples
+  1023 1023 0 0 0 0 530 529 530 529 1023 1023
+
+To determine a reasonable threshold, press on the touch panel with an
+appropriate stylus and read the values from samples.
+
+  # cat samples
+  1023 676 92 103 101 102 855 919 922 922 1023 679
+
+The first and eleventh samples are discarded.  Thus, the important
+values are the second and twelfth which are used to determine if the
+pen is down.  When both are below the threshold, the driver registers
+that the pen is down.  When either is above the threshold, it
+registers then pen is up.
diff --git a/Documentation/arm/Sharp-LH/LCDPanels b/Documentation/arm/Sharp-LH/LCDPanels
new file mode 100644
index 0000000..fb1b21c
--- /dev/null
+++ b/Documentation/arm/Sharp-LH/LCDPanels
@@ -0,0 +1,59 @@
+README on the LCD Panels
+========================
+
+Configuration options for several LCD panels, available from Logic PD,
+are included in the kernel source.  This README will help you
+understand the configuration data and give you some guidance for
+adding support for other panels if you wish.
+
+
+lcd-panels.h
+------------
+
+There is no way, at present, to detect which panel is attached to the
+system at runtime.  Thus the kernel configuration is static.  The file
+arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the
+panel specific parameters.
+
+It should be possible for this data to be shared among several device
+families.  The current layout may be insufficiently general, but it is
+amenable to improvement.
+
+
+PIXEL_CLOCK
+-----------
+
+The panel data sheets will give a range of acceptable pixel clocks.
+The fundamental LCDCLK input frequency is divided down by a PCD
+constant in field '.tim2'.  It may happen that it is impossible to set
+the pixel clock within this range.  A clock which is too slow will
+tend to flicker.  For the highest quality image, set the clock as high
+as possible.
+
+
+MARGINS
+-------
+
+These values may be difficult to glean from the panel data sheet.  In
+the case of the Sharp panels, the upper margin is explicitly called
+out as a specific number of lines from the top of the frame.  The
+other values may not matter as much as the panels tend to
+automatically center the image.
+
+
+Sync Sense
+----------
+
+The sense of the hsync and vsync pulses may be called out in the data
+sheet.  On one panel, the sense of these pulses determine the height
+of the visible region on the panel.  Most of the Sharp panels use
+negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in
+'.tim2'.
+
+
+Pel Layout
+----------
+
+The Sharp color TFT panels are all configured for 16 bit direct color
+modes.  The amba-lcd driver sets the pel mode to 565 for 5 bits of
+each red and blue and 6 bits of green.
diff --git a/Documentation/atomic_ops.txt b/Documentation/atomic_ops.txt
index 23a1c24..2a63d56 100644
--- a/Documentation/atomic_ops.txt
+++ b/Documentation/atomic_ops.txt
@@ -157,13 +157,13 @@
 	smp_mb__before_atomic_dec();
 	atomic_dec(&obj->ref_count);
 
-It makes sure that all memory operations preceeding the atomic_dec()
+It makes sure that all memory operations preceding the atomic_dec()
 call are strongly ordered with respect to the atomic counter
-operation.  In the above example, it guarentees that the assignment of
+operation.  In the above example, it guarantees that the assignment of
 "1" to obj->dead will be globally visible to other cpus before the
 atomic counter decrement.
 
-Without the explicitl smp_mb__before_atomic_dec() call, the
+Without the explicit smp_mb__before_atomic_dec() call, the
 implementation could legally allow the atomic counter update visible
 to other cpus before the "obj->dead = 1;" assignment.
 
@@ -173,11 +173,11 @@
 (smp_mb__{before,after}_atomic_inc()).
 
 A missing memory barrier in the cases where they are required by the
-atomic_t implementation above can have disasterous results.  Here is
-an example, which follows a pattern occuring frequently in the Linux
+atomic_t implementation above can have disastrous results.  Here is
+an example, which follows a pattern occurring frequently in the Linux
 kernel.  It is the use of atomic counters to implement reference
 counting, and it works such that once the counter falls to zero it can
-be guarenteed that no other entity can be accessing the object:
+be guaranteed that no other entity can be accessing the object:
 
 static void obj_list_add(struct obj *obj)
 {
@@ -291,9 +291,9 @@
 size.  The endianness of the bits within each "unsigned long" are the
 native endianness of the cpu.
 
-	void set_bit(unsigned long nr, volatils unsigned long *addr);
-	void clear_bit(unsigned long nr, volatils unsigned long *addr);
-	void change_bit(unsigned long nr, volatils unsigned long *addr);
+	void set_bit(unsigned long nr, volatile unsigned long *addr);
+	void clear_bit(unsigned long nr, volatile unsigned long *addr);
+	void change_bit(unsigned long nr, volatile unsigned long *addr);
 
 These routines set, clear, and change, respectively, the bit number
 indicated by "nr" on the bit mask pointed to by "ADDR".
@@ -301,9 +301,9 @@
 They must execute atomically, yet there are no implicit memory barrier
 semantics required of these interfaces.
 
-	int test_and_set_bit(unsigned long nr, volatils unsigned long *addr);
-	int test_and_clear_bit(unsigned long nr, volatils unsigned long *addr);
-	int test_and_change_bit(unsigned long nr, volatils unsigned long *addr);
+	int test_and_set_bit(unsigned long nr, volatile unsigned long *addr);
+	int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr);
+	int test_and_change_bit(unsigned long nr, volatile unsigned long *addr);
 
 Like the above, except that these routines return a boolean which
 indicates whether the changed bit was set _BEFORE_ the atomic bit
@@ -335,7 +335,7 @@
 		/* ... */;
 	obj->killed = 1;
 
-The implementation of test_and_set_bit() must guarentee that
+The implementation of test_and_set_bit() must guarantee that
 "obj->dead = 1;" is visible to cpus before the atomic memory operation
 done by test_and_set_bit() becomes visible.  Likewise, the atomic
 memory operation done by test_and_set_bit() must become visible before
@@ -474,7 +474,7 @@
 strictly orders all subsequent memory operations (including
 the cas()) with respect to itself, things will be fine.
 
-Said another way, _atomic_dec_and_lock() must guarentee that
+Said another way, _atomic_dec_and_lock() must guarantee that
 a counter dropping to zero is never made visible before the
 spinlock being acquired.
 
diff --git a/Documentation/console/console.txt b/Documentation/console/console.txt
new file mode 100644
index 0000000..d3e1744
--- /dev/null
+++ b/Documentation/console/console.txt
@@ -0,0 +1,144 @@
+Console Drivers
+===============
+
+The linux kernel has 2 general types of console drivers.  The first type is
+assigned by the kernel to all the virtual consoles during the boot process.
+This type will be called 'system driver', and only one system driver is allowed
+to exist. The system driver is persistent and it can never be unloaded, though
+it may become inactive.
+
+The second type has to be explicitly loaded and unloaded. This will be called
+'modular driver' by this document. Multiple modular drivers can coexist at
+any time with each driver sharing the console with other drivers including
+the system driver. However, modular drivers cannot take over the console
+that is currently occupied by another modular driver. (Exception: Drivers that
+call take_over_console() will succeed in the takeover regardless of the type
+of driver occupying the consoles.) They can only take over the console that is
+occupied by the system driver. In the same token, if the modular driver is
+released by the console, the system driver will take over.
+
+Modular drivers, from the programmer's point of view, has to call:
+
+	 take_over_console() - load and bind driver to console layer
+	 give_up_console() - unbind and unload driver
+
+In newer kernels, the following are also available:
+
+	 register_con_driver()
+	 unregister_con_driver()
+
+If sysfs is enabled, the contents of /sys/class/vtconsole can be
+examined. This shows the console backends currently registered by the
+system which are named vtcon<n> where <n> is an integer fro 0 to 15. Thus:
+
+       ls /sys/class/vtconsole
+       .  ..  vtcon0  vtcon1
+
+Each directory in /sys/class/vtconsole has 3 files:
+
+     ls /sys/class/vtconsole/vtcon0
+     .  ..  bind  name  uevent
+
+What do these files signify?
+
+     1. bind - this is a read/write file. It shows the status of the driver if
+        read, or acts to bind or unbind the driver to the virtual consoles
+        when written to. The possible values are:
+
+	0 - means the driver is not bound and if echo'ed, commands the driver
+	    to unbind
+
+        1 - means the driver is bound and if echo'ed, commands the driver to
+	    bind
+
+     2. name - read-only file. Shows the name of the driver in this format:
+
+	cat /sys/class/vtconsole/vtcon0/name
+	(S) VGA+
+
+	    '(S)' stands for a (S)ystem driver, ie, it cannot be directly
+	    commanded to bind or unbind
+
+	    'VGA+' is the name of the driver
+
+	cat /sys/class/vtconsole/vtcon1/name
+	(M) frame buffer device
+
+	    In this case, '(M)' stands for a (M)odular driver, one that can be
+	    directly commanded to bind or unbind.
+
+     3. uevent - ignore this file
+
+When unbinding, the modular driver is detached first, and then the system
+driver takes over the consoles vacated by the driver. Binding, on the other
+hand, will bind the driver to the consoles that are currently occupied by a
+system driver.
+
+NOTE1: Binding and binding must be selected in Kconfig. It's under:
+
+Device Drivers -> Character devices -> Support for binding and unbinding
+console drivers
+
+NOTE2: If any of the virtual consoles are in KD_GRAPHICS mode, then binding or
+unbinding will not succeed. An example of an application that sets the console
+to KD_GRAPHICS is X.
+
+How useful is this feature? This is very useful for console driver
+developers. By unbinding the driver from the console layer, one can unload the
+driver, make changes, recompile, reload and rebind the driver without any need
+for rebooting the kernel. For regular users who may want to switch from
+framebuffer console to VGA console and vice versa, this feature also makes
+this possible. (NOTE NOTE NOTE: Please read fbcon.txt under Documentation/fb
+for more details).
+
+Notes for developers:
+=====================
+
+take_over_console() is now broken up into:
+
+     register_con_driver()
+     bind_con_driver() - private function
+
+give_up_console() is a wrapper to unregister_con_driver(), and a driver must
+be fully unbound for this call to succeed. con_is_bound() will check if the
+driver is bound or not.
+
+Guidelines for console driver writers:
+=====================================
+
+In order for binding to and unbinding from the console to properly work,
+console drivers must follow these guidelines:
+
+1. All drivers, except system drivers, must call either register_con_driver()
+   or take_over_console(). register_con_driver() will just add the driver to
+   the console's internal list. It won't take over the
+   console. take_over_console(), as it name implies, will also take over (or
+   bind to) the console.
+
+2. All resources allocated during con->con_init() must be released in
+   con->con_deinit().
+
+3. All resources allocated in con->con_startup() must be released when the
+   driver, which was previously bound, becomes unbound.  The console layer
+   does not have a complementary call to con->con_startup() so it's up to the
+   driver to check when it's legal to release these resources. Calling
+   con_is_bound() in con->con_deinit() will help.  If the call returned
+   false(), then it's safe to release the resources.  This balance has to be
+   ensured because con->con_startup() can be called again when a request to
+   rebind the driver to the console arrives.
+
+4. Upon exit of the driver, ensure that the driver is totally unbound. If the
+   condition is satisfied, then the driver must call unregister_con_driver()
+   or give_up_console().
+
+5. unregister_con_driver() can also be called on conditions which make it
+   impossible for the driver to service console requests.  This can happen
+   with the framebuffer console that suddenly lost all of its drivers.
+
+The current crop of console drivers should still work correctly, but binding
+and unbinding them may cause problems. With minimal fixes, these drivers can
+be made to work correctly.
+
+==========================
+Antonino Daplas <adaplas@pol.net>
+
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index b369a8c..4aaf68f 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -3,7 +3,7 @@
 
 	     Maintained by Torben Mathiasen <device@lanana.org>
 
-		      Last revised: 25 January 2005
+		      Last revised: 15 May 2006
 
 This list is the Linux Device List, the official registry of allocated
 device numbers and /dev directory nodes for the Linux operating
@@ -94,7 +94,6 @@
 		  9 = /dev/urandom	Faster, less secure random number gen.
 		 10 = /dev/aio		Asyncronous I/O notification interface
 		 11 = /dev/kmsg		Writes to this come out as printk's
-		 12 = /dev/oldmem	Access to crash dump from kexec kernel
   1 block	RAM disk
 		  0 = /dev/ram0		First RAM disk
 		  1 = /dev/ram1		Second RAM disk
@@ -262,13 +261,13 @@
 		NOTE: These devices permit both read and write access.
 
   7 block	Loopback devices
-		  0 = /dev/loop0	First loopback device
-		  1 = /dev/loop1	Second loopback device
+		  0 = /dev/loop0	First loop device
+		  1 = /dev/loop1	Second loop device
 		    ...
 
-		The loopback devices are used to mount filesystems not
+		The loop devices are used to mount filesystems not
 		associated with block devices.	The binding to the
-		loopback devices is handled by mount(8) or losetup(8).
+		loop devices is handled by mount(8) or losetup(8).
 
   8 block	SCSI disk devices (0-15)
 		  0 = /dev/sda		First SCSI disk whole disk
@@ -943,7 +942,7 @@
 		240 = /dev/ftlp		FTL on 16th Memory Technology Device 
 
 		Partitions are handled in the same way as for IDE
-		disks (see major number 3) expect that the partition
+		disks (see major number 3) except that the partition
 		limit is 15 rather than 63 per disk (same as SCSI.)
 
  45 char	isdn4linux ISDN BRI driver
@@ -1168,7 +1167,7 @@
 		The filename of the encrypted container and the passwords
 		are sent via ioctls (using the sdmount tool) to the master
 		node which then activates them via one of the
-		/dev/scramdisk/x nodes for loopback mounting (all handled
+		/dev/scramdisk/x nodes for loop mounting (all handled
 		through the sdmount tool).
 
 		Requested by: andy@scramdisklinux.org
@@ -2538,18 +2537,32 @@
 		  0 = /dev/usb/lp0	First USB printer
 		    ...
 		 15 = /dev/usb/lp15	16th USB printer
-		 16 = /dev/usb/mouse0	First USB mouse
-		    ...
-		 31 = /dev/usb/mouse15	16th USB mouse
-		 32 = /dev/usb/ez0	First USB firmware loader
-		    ...
-		 47 = /dev/usb/ez15	16th USB firmware loader
 		 48 = /dev/usb/scanner0	First USB scanner
 		    ...
 		 63 = /dev/usb/scanner15 16th USB scanner
 		 64 = /dev/usb/rio500	Diamond Rio 500
 		 65 = /dev/usb/usblcd	USBLCD Interface (info@usblcd.de)
 		 66 = /dev/usb/cpad0	Synaptics cPad (mouse/LCD)
+		 96 = /dev/usb/hiddev0	1st USB HID device
+		    ...
+		111 = /dev/usb/hiddev15	16th USB HID device
+		112 = /dev/usb/auer0	1st auerswald ISDN device
+		    ...
+		127 = /dev/usb/auer15	16th auerswald ISDN device
+		128 = /dev/usb/brlvgr0	First Braille Voyager device
+		    ...
+		131 = /dev/usb/brlvgr3	Fourth Braille Voyager device
+		132 = /dev/usb/idmouse	ID Mouse (fingerprint scanner) device
+		133 = /dev/usb/sisusbvga1	First SiSUSB VGA device
+		    ...
+		140 = /dev/usb/sisusbvga8	Eigth SISUSB VGA device
+		144 = /dev/usb/lcd	USB LCD device
+		160 = /dev/usb/legousbtower0	1st USB Legotower device
+		    ...
+		175 = /dev/usb/legousbtower15	16th USB Legotower device
+		240 = /dev/usb/dabusb0	First daubusb device
+		    ...
+		243 = /dev/usb/dabusb3	Fourth dabusb device
 
 180 block	USB block devices
 		0 = /dev/uba		First USB block device
@@ -2710,6 +2723,17 @@
 		  1 = /dev/cpu/1/msr		MSRs on CPU 1
 		    ...
 
+202 block	Xen Virtual Block Device
+		  0 = /dev/xvda       First Xen VBD whole disk
+		  16 = /dev/xvdb      Second Xen VBD whole disk
+		  32 = /dev/xvdc      Third Xen VBD whole disk
+		    ...
+		  240 = /dev/xvdp     Sixteenth Xen VBD whole disk
+
+                Partitions are handled in the same way as for IDE
+                disks (see major number 3) except that the limit on
+                partitions is 15.
+
 203 char	CPU CPUID information
 		  0 = /dev/cpu/0/cpuid		CPUID on CPU 0
 		  1 = /dev/cpu/1/cpuid		CPUID on CPU 1
@@ -2747,11 +2771,27 @@
 		 46 = /dev/ttyCPM0		PPC CPM (SCC or SMC) - port 0
 		    ...
 		 47 = /dev/ttyCPM5		PPC CPM (SCC or SMC) - port 5
-		 50 = /dev/ttyIOC40		Altix serial card
+		 50 = /dev/ttyIOC0		Altix serial card
 		    ...
-		 81 = /dev/ttyIOC431		Altix serial card
-		 82 = /dev/ttyVR0               NEC VR4100 series SIU
-		 83 = /dev/ttyVR1               NEC VR4100 series DSIU
+		 81 = /dev/ttyIOC31		Altix serial card
+		 82 = /dev/ttyVR0		NEC VR4100 series SIU
+		 83 = /dev/ttyVR1		NEC VR4100 series DSIU
+		 84 = /dev/ttyIOC84		Altix ioc4 serial card
+		    ...
+		 115 = /dev/ttyIOC115		Altix ioc4 serial card
+		 116 = /dev/ttySIOC0		Altix ioc3 serial card
+		    ...
+		 147 = /dev/ttySIOC31		Altix ioc3 serial card
+		 148 = /dev/ttyPSC0		PPC PSC - port 0
+		    ...
+		 153 = /dev/ttyPSC5		PPC PSC - port 5
+		 154 = /dev/ttyAT0		ATMEL serial port 0
+		    ...
+		 169 = /dev/ttyAT15		ATMEL serial port 15
+		 170 = /dev/ttyNX0		Hilscher netX serial port 0
+		    ...
+		 185 = /dev/ttyNX15		Hilscher netX serial port 15
+		 186 = /dev/ttyJ0		JTAG1 DCC protocol based serial port emulation
 
 205 char	Low-density serial ports (alternate device)
 		  0 = /dev/culu0		Callout device for ttyLU0
@@ -2786,8 +2826,8 @@
 		 50 = /dev/cuioc40		Callout device for ttyIOC40
 		    ...
 		 81 = /dev/cuioc431		Callout device for ttyIOC431
-		 82 = /dev/cuvr0                Callout device for ttyVR0
-		 83 = /dev/cuvr1                Callout device for ttyVR1
+		 82 = /dev/cuvr0		Callout device for ttyVR0
+		 83 = /dev/cuvr1		Callout device for ttyVR1
 
 
 206 char	OnStream SC-x0 tape devices
@@ -2897,7 +2937,6 @@
 		    ...
 		196 = /dev/dvb/adapter3/video0    first video decoder of fourth card
 
-
 216 char	Bluetooth RFCOMM TTY devices
 		  0 = /dev/rfcomm0		First Bluetooth RFCOMM TTY device
 		  1 = /dev/rfcomm1		Second Bluetooth RFCOMM TTY device
@@ -3002,12 +3041,43 @@
 		ioctl()'s can be used to rewind the tape regardless of
 		the device used to access it.
 
-231 char	InfiniBand MAD
+231 char	InfiniBand
 		0 = /dev/infiniband/umad0
 		1 = /dev/infiniband/umad1
-		 ...
+		  ...
+		63 = /dev/infiniband/umad63    63rd InfiniBandMad device
+		64 = /dev/infiniband/issm0     First InfiniBand IsSM device
+		65 = /dev/infiniband/issm1     Second InfiniBand IsSM device
+		  ...
+		127 = /dev/infiniband/issm63    63rd InfiniBand IsSM device
+		128 = /dev/infiniband/uverbs0   First InfiniBand verbs device
+		129 = /dev/infiniband/uverbs1   Second InfiniBand verbs device
+		  ...
+		159 = /dev/infiniband/uverbs31  31st InfiniBand verbs device
 
-232-239		UNASSIGNED
+232 char	Biometric Devices
+		0 = /dev/biometric/sensor0/fingerprint	first fingerprint sensor on first device
+		1 = /dev/biometric/sensor0/iris		first iris sensor on first device
+		2 = /dev/biometric/sensor0/retina	first retina sensor on first device
+		3 = /dev/biometric/sensor0/voiceprint	first voiceprint sensor on first device
+		4 = /dev/biometric/sensor0/facial	first facial sensor on first device
+		5 = /dev/biometric/sensor0/hand		first hand sensor on first device
+		  ...
+		10 = /dev/biometric/sensor1/fingerprint	first fingerprint sensor on second device
+		  ...
+		20 = /dev/biometric/sensor2/fingerprint	first fingerprint sensor on third device
+		  ...
+
+233 char	PathScale InfiniPath interconnect
+		0 = /dev/ipath        Primary device for programs (any unit)
+		1 = /dev/ipath0       Access specifically to unit 0
+		2 = /dev/ipath1       Access specifically to unit 1
+		  ...
+		4 = /dev/ipath3       Access specifically to unit 3
+		129 = /dev/ipath_sma    Device used by Subnet Management Agent
+		130 = /dev/ipath_diag   Device used by diagnostics programs
+
+234-239		UNASSIGNED
 
 240-254 char	LOCAL/EXPERIMENTAL USE
 240-254 block	LOCAL/EXPERIMENTAL USE
@@ -3021,6 +3091,28 @@
 		This major is reserved to assist the expansion to a
 		larger number space.  No device nodes with this major
 		should ever be created on the filesystem.
+		(This is probaly not true anymore, but I'll leave it
+		for now /Torben)
+
+---LARGE MAJORS!!!!!---
+
+256 char	Equinox SST multi-port serial boards
+		   0 = /dev/ttyEQ0	First serial port on first Equinox SST board
+		 127 = /dev/ttyEQ127	Last serial port on first Equinox SST board
+		 128 = /dev/ttyEQ128	First serial port on second Equinox SST board
+		  ...
+		1027 = /dev/ttyEQ1027	Last serial port on eighth Equinox SST board
+
+256 block	Resident Flash Disk Flash Translation Layer
+		  0 = /dev/rfda		First RFD FTL layer
+		 16 = /dev/rfdb		Second RFD FTL layer
+		  ...
+		240 = /dev/rfdp		16th RFD FTL layer
+
+257 char	Phoenix Technologies Cryptographic Services Driver
+		  0 = /dev/ptlsec	Crypto Services Driver
+
+
 
  ****	ADDITIONAL /dev DIRECTORY ENTRIES
 
diff --git a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt
index ac4a7a7..2050c9f 100644
--- a/Documentation/driver-model/overview.txt
+++ b/Documentation/driver-model/overview.txt
@@ -18,7 +18,7 @@
 (sometimes just a list) for the devices they control. There wasn't any
 uniformity across the different bus types.
 
-The current driver model provides a comon, uniform data model for describing
+The current driver model provides a common, uniform data model for describing
 a bus and the devices that can appear under the bus. The unified bus
 model includes a set of common attributes which all busses carry, and a set
 of common callbacks, such as device discovery during bus probing, bus
diff --git a/Documentation/fb/fbcon.txt b/Documentation/fb/fbcon.txt
index 08dce0f..f373df1 100644
--- a/Documentation/fb/fbcon.txt
+++ b/Documentation/fb/fbcon.txt
@@ -135,10 +135,10 @@
 
 	The angle can be changed anytime afterwards by 'echoing' the same
 	numbers to any one of the 2 attributes found in
-	/sys/class/graphics/fb{x}
+	 /sys/class/graphics/fbcon
 
-		con_rotate     - rotate the display of the active console
-		con_rotate_all - rotate the display of all consoles
+		rotate     - rotate the display of the active console
+		rotate_all - rotate the display of all consoles
 
 	Console rotation will only become available if Console Rotation
 	Support is compiled in your kernel.
@@ -148,5 +148,177 @@
 	Actually, the underlying fb driver is totally ignorant of console
 	rotation.
 
----
+C. Attaching, Detaching and Unloading
+
+Before going on on how to attach, detach and unload the framebuffer console, an
+illustration of the dependencies may help.
+
+The console layer, as with most subsystems, needs a driver that interfaces with
+the hardware. Thus, in a VGA console:
+
+console ---> VGA driver ---> hardware.
+
+Assuming the VGA driver can be unloaded, one must first unbind the VGA driver
+from the console layer before unloading the driver.  The VGA driver cannot be
+unloaded if it is still bound to the console layer. (See
+Documentation/console/console.txt for more information).
+
+This is more complicated in the case of the the framebuffer console (fbcon),
+because fbcon is an intermediate layer between the console and the drivers:
+
+console ---> fbcon ---> fbdev drivers ---> hardware
+
+The fbdev drivers cannot be unloaded if it's bound to fbcon, and fbcon cannot
+be unloaded if it's bound to the console layer.
+
+So to unload the fbdev drivers, one must first unbind fbcon from the console,
+then unbind the fbdev drivers from fbcon.  Fortunately, unbinding fbcon from
+the console layer will automatically unbind framebuffer drivers from
+fbcon. Thus, there is no need to explicitly unbind the fbdev drivers from
+fbcon.
+
+So, how do we unbind fbcon from the console? Part of the answer is in
+Documentation/console/console.txt. To summarize:
+
+Echo a value to the bind file that represents the framebuffer console
+driver. So assuming vtcon1 represents fbcon, then:
+
+echo 1 > sys/class/vtconsole/vtcon1/bind - attach framebuffer console to
+                                           console layer
+echo 0 > sys/class/vtconsole/vtcon1/bind - detach framebuffer console from
+                                           console layer
+
+If fbcon is detached from the console layer, your boot console driver (which is
+usually VGA text mode) will take over.  A few drivers (rivafb and i810fb) will
+restore VGA text mode for you.  With the rest, before detaching fbcon, you
+must take a few additional steps to make sure that your VGA text mode is
+restored properly. The following is one of the several methods that you can do:
+
+1. Download or install vbetool.  This utility is included with most
+   distributions nowadays, and is usually part of the suspend/resume tool.
+
+2. In your kernel configuration, ensure that CONFIG_FRAMEBUFFER_CONSOLE is set
+   to 'y' or 'm'. Enable one or more of your favorite framebuffer drivers.
+
+3. Boot into text mode and as root run:
+
+	vbetool vbestate save > <vga state file>
+
+	The above command saves the register contents of your graphics
+	hardware to <vga state file>.  You need to do this step only once as
+	the state file can be reused.
+
+4. If fbcon is compiled as a module, load fbcon by doing:
+
+       modprobe fbcon
+
+5. Now to detach fbcon:
+
+       vbetool vbestate restore < <vga state file> && \
+       echo 0 > /sys/class/vtconsole/vtcon1/bind
+
+6. That's it, you're back to VGA mode. And if you compiled fbcon as a module,
+   you can unload it by 'rmmod fbcon'
+
+7. To reattach fbcon:
+
+       echo 1 > /sys/class/vtconsole/vtcon1/bind
+
+8. Once fbcon is unbound, all drivers registered to the system will also
+become unbound.  This means that fbcon and individual framebuffer drivers
+can be unloaded or reloaded at will. Reloading the drivers or fbcon will
+automatically bind the console, fbcon and the drivers together. Unloading
+all the drivers without unloading fbcon will make it impossible for the
+console to bind fbcon.
+
+Notes for vesafb users:
+=======================
+
+Unfortunately, if your bootline includes a vga=xxx parameter that sets the
+hardware in graphics mode, such as when loading vesafb, vgacon will not load.
+Instead, vgacon will replace the default boot console with dummycon, and you
+won't get any display after detaching fbcon. Your machine is still alive, so
+you can reattach vesafb. However, to reattach vesafb, you need to do one of
+the following:
+
+Variation 1:
+
+    a. Before detaching fbcon, do
+
+       vbetool vbemode save > <vesa state file> # do once for each vesafb mode,
+						# the file can be reused
+
+    b. Detach fbcon as in step 5.
+
+    c. Attach fbcon
+
+        vbetool vbestate restore < <vesa state file> && \
+	echo 1 > /sys/class/vtconsole/vtcon1/bind
+
+Variation 2:
+
+    a. Before detaching fbcon, do:
+	echo <ID> > /sys/class/tty/console/bind
+
+
+       vbetool vbemode get
+
+    b. Take note of the mode number
+
+    b. Detach fbcon as in step 5.
+
+    c. Attach fbcon:
+
+       vbetool vbemode set <mode number> && \
+       echo 1 > /sys/class/vtconsole/vtcon1/bind
+
+Samples:
+========
+
+Here are 2 sample bash scripts that you can use to bind or unbind the
+framebuffer console driver if you are in an X86 box:
+
+---------------------------------------------------------------------------
+#!/bin/bash
+# Unbind fbcon
+
+# Change this to where your actual vgastate file is located
+# Or Use VGASTATE=$1 to indicate the state file at runtime
+VGASTATE=/tmp/vgastate
+
+# path to vbetool
+VBETOOL=/usr/local/bin
+
+
+for (( i = 0; i < 16; i++))
+do
+  if test -x /sys/class/vtconsole/vtcon$i; then
+      if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \
+           = 1 ]; then
+	    if test -x $VBETOOL/vbetool; then
+	       echo Unbinding vtcon$i
+	       $VBETOOL/vbetool vbestate restore < $VGASTATE
+	       echo 0 > /sys/class/vtconsole/vtcon$i/bind
+	    fi
+      fi
+  fi
+done
+
+---------------------------------------------------------------------------
+#!/bin/bash
+# Bind fbcon
+
+for (( i = 0; i < 16; i++))
+do
+  if test -x /sys/class/vtconsole/vtcon$i; then
+      if [ `cat /sys/class/vtconsole/vtcon$i/name | grep -c "frame buffer"` \
+           = 1 ]; then
+	  echo Unbinding vtcon$i
+	  echo 1 > /sys/class/vtconsole/vtcon$i/bind
+      fi
+  fi
+done
+---------------------------------------------------------------------------
+
+--
 Antonino Daplas <adaplas@pol.net>
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 43ab119..033ac91 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -33,27 +33,12 @@
 
 ---------------------------
 
-What:	RCU API moves to EXPORT_SYMBOL_GPL
-When:	April 2006
-Files:	include/linux/rcupdate.h, kernel/rcupdate.c
-Why:	Outside of Linux, the only implementations of anything even
-	vaguely resembling RCU that I am aware of are in DYNIX/ptx,
-	VM/XA, Tornado, and K42.  I do not expect anyone to port binary
-	drivers or kernel modules from any of these, since the first two
-	are owned by IBM and the last two are open-source research OSes.
-	So these will move to GPL after a grace period to allow
-	people, who might be using implementations that I am not aware
-	of, to adjust to this upcoming change.
-Who:	Paul E. McKenney <paulmck@us.ibm.com>
-
----------------------------
-
 What:	raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
-When:	November 2005
+When:	November 2006
 Why:	Deprecated in favour of the new ioctl-based rawiso interface, which is
 	more efficient.  You should really be using libraw1394 for raw1394
 	access anyway.
-Who:	Jody McIntyre <scjody@steamballoon.com>
+Who:	Jody McIntyre <scjody@modernduck.com>
 
 ---------------------------
 
@@ -192,6 +177,16 @@
 
 ---------------------------
 
+What:	Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
+	(temporary transition config option provided until then)
+	The transition config option will also be removed at the same time.
+When:	before 2.6.19
+Why:	Unused symbols are both increasing the size of the kernel binary
+	and are often a sign of "wrong API"
+Who:	Arjan van de Ven <arjan@linux.intel.com>
+
+---------------------------
+
 What:	remove EXPORT_SYMBOL(tasklist_lock)
 When:	August 2006
 Files:	kernel/fork.c
@@ -212,15 +207,6 @@
 
 ---------------------------
 
-What:	Support for NEC DDB5074 and DDB5476 evaluation boards.
-When:	June 2006
-Why:	Board specific code doesn't build anymore since ~2.6.0 and no
-	users have complained indicating there is no more need for these
-	boards.  This should really be considered a last call.
-Who:	Ralf Baechle <ralf@linux-mips.org>
-
----------------------------
-
 What:	USB driver API moves to EXPORT_SYMBOL_GPL
 When:	Febuary 2008
 Files:	include/linux/usb.h, drivers/usb/core/driver.c
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 1045da5..d31efbb 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -99,7 +99,7 @@
 	int (*sync_fs)(struct super_block *sb, int wait);
 	void (*write_super_lockfs) (struct super_block *);
 	void (*unlockfs) (struct super_block *);
-	int (*statfs) (struct super_block *, struct kstatfs *);
+	int (*statfs) (struct dentry *, struct kstatfs *);
 	int (*remount_fs) (struct super_block *, int *, char *);
 	void (*clear_inode) (struct inode *);
 	void (*umount_begin) (struct super_block *);
@@ -142,15 +142,16 @@
 
 --------------------------- file_system_type ---------------------------
 prototypes:
-	struct super_block *(*get_sb) (struct file_system_type *, int,
-			const char *, void *);
+	struct int (*get_sb) (struct file_system_type *, int,
+			const char *, void *, struct vfsmount *);
 	void (*kill_sb) (struct super_block *);
 locking rules:
 		may block	BKL
 get_sb		yes		yes
 kill_sb		yes		yes
 
-->get_sb() returns error or a locked superblock (exclusive on ->s_umount).
+->get_sb() returns error or 0 with locked superblock attached to the vfsmount
+(exclusive on ->s_umount).
 ->kill_sb() takes a write-locked superblock, does all shutdown work on it,
 unlocks and drops the reference.
 
diff --git a/Documentation/filesystems/automount-support.txt b/Documentation/filesystems/automount-support.txt
index 58c65a1..7cac200 100644
--- a/Documentation/filesystems/automount-support.txt
+++ b/Documentation/filesystems/automount-support.txt
@@ -19,7 +19,7 @@
 
  (2) Have the follow_link() op do the following steps:
 
-     (a) Call do_kern_mount() to call the appropriate filesystem to set up a
+     (a) Call vfs_kern_mount() to call the appropriate filesystem to set up a
          superblock and gain a vfsmount structure representing it.
 
      (b) Copy the nameidata provided as an argument and substitute the dentry
diff --git a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt
index afb1335..4aecc9b 100644
--- a/Documentation/filesystems/ext3.txt
+++ b/Documentation/filesystems/ext3.txt
@@ -113,6 +113,14 @@
 grpquota
 usrquota
 
+bh		(*)	ext3 associates buffer heads to data pages to
+nobh			(a) cache disk block mapping information
+			(b) link pages into transaction to provide
+			    ordering guarantees.
+			"bh" option forces use of buffer heads.
+			"nobh" option tries to avoid associating buffer
+			heads (supported only for "writeback" mode).
+
 
 Specification
 =============
diff --git a/Documentation/filesystems/fuse.txt b/Documentation/filesystems/fuse.txt
index 33f7431..a584f05 100644
--- a/Documentation/filesystems/fuse.txt
+++ b/Documentation/filesystems/fuse.txt
@@ -18,6 +18,14 @@
   user.  NOTE: this is not the same as mounts allowed with the "user"
   option in /etc/fstab, which is not discussed here.
 
+Filesystem connection:
+
+  A connection between the filesystem daemon and the kernel.  The
+  connection exists until either the daemon dies, or the filesystem is
+  umounted.  Note that detaching (or lazy umounting) the filesystem
+  does _not_ break the connection, in this case it will exist until
+  the last reference to the filesystem is released.
+
 Mount owner:
 
   The user who does the mounting.
@@ -86,16 +94,20 @@
   The default is infinite.  Note that the size of read requests is
   limited anyway to 32 pages (which is 128kbyte on i386).
 
-Sysfs
-~~~~~
+Control filesystem
+~~~~~~~~~~~~~~~~~~
 
-FUSE sets up the following hierarchy in sysfs:
+There's a control filesystem for FUSE, which can be mounted by:
 
-  /sys/fs/fuse/connections/N/
+  mount -t fusectl none /sys/fs/fuse/connections
 
-where N is an increasing number allocated to each new connection.
+Mounting it under the '/sys/fs/fuse/connections' directory makes it
+backwards compatible with earlier versions.
 
-For each connection the following attributes are defined:
+Under the fuse control filesystem each connection has a directory
+named by a unique number.
+
+For each connection the following files exist within this directory:
 
  'waiting'
 
@@ -110,7 +122,47 @@
   connection.  This means that all waiting requests will be aborted an
   error returned for all aborted and new requests.
 
-Only a privileged user may read or write these attributes.
+Only the owner of the mount may read or write these files.
+
+Interrupting filesystem operations
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If a process issuing a FUSE filesystem request is interrupted, the
+following will happen:
+
+  1) If the request is not yet sent to userspace AND the signal is
+     fatal (SIGKILL or unhandled fatal signal), then the request is
+     dequeued and returns immediately.
+
+  2) If the request is not yet sent to userspace AND the signal is not
+     fatal, then an 'interrupted' flag is set for the request.  When
+     the request has been successfully transfered to userspace and
+     this flag is set, an INTERRUPT request is queued.
+
+  3) If the request is already sent to userspace, then an INTERRUPT
+     request is queued.
+
+INTERRUPT requests take precedence over other requests, so the
+userspace filesystem will receive queued INTERRUPTs before any others.
+
+The userspace filesystem may ignore the INTERRUPT requests entirely,
+or may honor them by sending a reply to the _original_ request, with
+the error set to EINTR.
+
+It is also possible that there's a race between processing the
+original request and it's INTERRUPT request.  There are two possibilities:
+
+  1) The INTERRUPT request is processed before the original request is
+     processed
+
+  2) The INTERRUPT request is processed after the original request has
+     been answered
+
+If the filesystem cannot find the original request, it should wait for
+some timeout and/or a number of new requests to arrive, after which it
+should reply to the INTERRUPT request with an EAGAIN error.  In case
+1) the INTERRUPT request will be requeued.  In case 2) the INTERRUPT
+reply will be ignored.
 
 Aborting a filesystem connection
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -139,8 +191,8 @@
   - Use forced umount (umount -f).  Works in all cases but only if
     filesystem is still attached (it hasn't been lazy unmounted)
 
-  - Abort filesystem through the sysfs interface.  Most powerful
-    method, always works.
+  - Abort filesystem through the FUSE control filesystem.  Most
+    powerful method, always works.
 
 How do non-privileged mounts work?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -304,25 +356,7 @@
  |                                    |     for "file"]
  |                                    |    *DEADLOCK*
 
-The solution for this is to allow requests to be interrupted while
-they are in userspace:
-
- |      [interrupted by signal]       |
- |    <fuse_unlink()                  |
- |    [release semaphore]             |    [semaphore acquired]
- |  <sys_unlink()                     |
- |                                    |    >fuse_unlink()
- |                                    |      [queue req on fc->pending]
- |                                    |      [wake up fc->waitq]
- |                                    |      [sleep on req->waitq]
-
-If the filesystem daemon was single threaded, this will stop here,
-since there's no other thread to dequeue and execute the request.
-In this case the solution is to kill the FUSE daemon as well.  If
-there are multiple serving threads, you just have to kill them as
-long as any remain.
-
-Moral: a filesystem which deadlocks, can soon find itself dead.
+The solution for this is to allow the filesystem to be aborted.
 
 Scenario 2 - Tricky deadlock
 ----------------------------
@@ -355,24 +389,14 @@
  |                                    |           [lock page]
  |                                    |           * DEADLOCK *
 
-Solution is again to let the the request be interrupted (not
-elaborated further).
+Solution is basically the same as above.
 
-An additional problem is that while the write buffer is being
-copied to the request, the request must not be interrupted.  This
-is because the destination address of the copy may not be valid
-after the request is interrupted.
+An additional problem is that while the write buffer is being copied
+to the request, the request must not be interrupted/aborted.  This is
+because the destination address of the copy may not be valid after the
+request has returned.
 
-This is solved with doing the copy atomically, and allowing
-interruption while the page(s) belonging to the write buffer are
-faulted with get_user_pages().  The 'req->locked' flag indicates
-when the copy is taking place, and interruption is delayed until
-this flag is unset.
-
-Scenario 3 - Tricky deadlock with asynchronous read
----------------------------------------------------
-
-The same situation as above, except thread-1 will wait on page lock
-and hence it will be uninterruptible as well.  The solution is to
-abort the connection with forced umount (if mount is attached) or
-through the abort attribute in sysfs.
+This is solved with doing the copy atomically, and allowing abort
+while the page(s) belonging to the write buffer are faulted with
+get_user_pages().  The 'req->locked' flag indicates when the copy is
+taking place, and abort is delayed until this flag is unset.
diff --git a/Documentation/filesystems/inotify.txt b/Documentation/filesystems/inotify.txt
index 6d50190..59a919f 100644
--- a/Documentation/filesystems/inotify.txt
+++ b/Documentation/filesystems/inotify.txt
@@ -69,17 +69,135 @@
 	int inotify_rm_watch (int fd, __u32 mask);
 
 
-(iii) Internal Kernel Implementation
+(iii) Kernel Interface
 
-Each inotify instance is associated with an inotify_device structure.
+Inotify's kernel API consists a set of functions for managing watches and an
+event callback.
+
+To use the kernel API, you must first initialize an inotify instance with a set
+of inotify_operations.  You are given an opaque inotify_handle, which you use
+for any further calls to inotify.
+
+    struct inotify_handle *ih = inotify_init(my_event_handler);
+
+You must provide a function for processing events and a function for destroying
+the inotify watch.
+
+    void handle_event(struct inotify_watch *watch, u32 wd, u32 mask,
+    	              u32 cookie, const char *name, struct inode *inode)
+
+	watch - the pointer to the inotify_watch that triggered this call
+	wd - the watch descriptor
+	mask - describes the event that occurred
+	cookie - an identifier for synchronizing events
+	name - the dentry name for affected files in a directory-based event
+	inode - the affected inode in a directory-based event
+
+    void destroy_watch(struct inotify_watch *watch)
+
+You may add watches by providing a pre-allocated and initialized inotify_watch
+structure and specifying the inode to watch along with an inotify event mask.
+You must pin the inode during the call.  You will likely wish to embed the
+inotify_watch structure in a structure of your own which contains other
+information about the watch.  Once you add an inotify watch, it is immediately
+subject to removal depending on filesystem events.  You must grab a reference if
+you depend on the watch hanging around after the call.
+
+    inotify_init_watch(&my_watch->iwatch);
+    inotify_get_watch(&my_watch->iwatch);	// optional
+    s32 wd = inotify_add_watch(ih, &my_watch->iwatch, inode, mask);
+    inotify_put_watch(&my_watch->iwatch);	// optional
+
+You may use the watch descriptor (wd) or the address of the inotify_watch for
+other inotify operations.  You must not directly read or manipulate data in the
+inotify_watch.  Additionally, you must not call inotify_add_watch() more than
+once for a given inotify_watch structure, unless you have first called either
+inotify_rm_watch() or inotify_rm_wd().
+
+To determine if you have already registered a watch for a given inode, you may
+call inotify_find_watch(), which gives you both the wd and the watch pointer for
+the inotify_watch, or an error if the watch does not exist.
+
+    wd = inotify_find_watch(ih, inode, &watchp);
+
+You may use container_of() on the watch pointer to access your own data
+associated with a given watch.  When an existing watch is found,
+inotify_find_watch() bumps the refcount before releasing its locks.  You must
+put that reference with:
+
+    put_inotify_watch(watchp);
+
+Call inotify_find_update_watch() to update the event mask for an existing watch.
+inotify_find_update_watch() returns the wd of the updated watch, or an error if
+the watch does not exist.
+
+    wd = inotify_find_update_watch(ih, inode, mask);
+
+An existing watch may be removed by calling either inotify_rm_watch() or
+inotify_rm_wd().
+
+    int ret = inotify_rm_watch(ih, &my_watch->iwatch);
+    int ret = inotify_rm_wd(ih, wd);
+
+A watch may be removed while executing your event handler with the following:
+
+    inotify_remove_watch_locked(ih, iwatch);
+
+Call inotify_destroy() to remove all watches from your inotify instance and
+release it.  If there are no outstanding references, inotify_destroy() will call
+your destroy_watch op for each watch.
+
+    inotify_destroy(ih);
+
+When inotify removes a watch, it sends an IN_IGNORED event to your callback.
+You may use this event as an indication to free the watch memory.  Note that
+inotify may remove a watch due to filesystem events, as well as by your request.
+If you use IN_ONESHOT, inotify will remove the watch after the first event, at
+which point you may call the final inotify_put_watch.
+
+(iv) Kernel Interface Prototypes
+
+	struct inotify_handle *inotify_init(struct inotify_operations *ops);
+
+	inotify_init_watch(struct inotify_watch *watch);
+
+	s32 inotify_add_watch(struct inotify_handle *ih,
+		              struct inotify_watch *watch,
+			      struct inode *inode, u32 mask);
+
+	s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode,
+			       struct inotify_watch **watchp);
+
+	s32 inotify_find_update_watch(struct inotify_handle *ih,
+				      struct inode *inode, u32 mask);
+
+	int inotify_rm_wd(struct inotify_handle *ih, u32 wd);
+
+	int inotify_rm_watch(struct inotify_handle *ih,
+			     struct inotify_watch *watch);
+
+	void inotify_remove_watch_locked(struct inotify_handle *ih,
+					 struct inotify_watch *watch);
+
+	void inotify_destroy(struct inotify_handle *ih);
+
+	void get_inotify_watch(struct inotify_watch *watch);
+	void put_inotify_watch(struct inotify_watch *watch);
+
+
+(v) Internal Kernel Implementation
+
+Each inotify instance is represented by an inotify_handle structure.
+Inotify's userspace consumers also have an inotify_device which is
+associated with the inotify_handle, and on which events are queued.
 
 Each watch is associated with an inotify_watch structure.  Watches are chained
-off of each associated device and each associated inode.
+off of each associated inotify_handle and each associated inode.
 
-See fs/inotify.c for the locking and lifetime rules.
+See fs/inotify.c and fs/inotify_user.c for the locking and lifetime rules.
 
 
-(iv) Rationale
+(vi) Rationale
 
 Q: What is the design decision behind not tying the watch to the open fd of
    the watched object?
@@ -145,7 +263,7 @@
    file descriptor-based one that allows basic file I/O and poll/select.
    Obtaining the fd and managing the watches could have been done either via a
    device file or a family of new system calls.  We decided to implement a
-   family of system calls because that is the preffered approach for new kernel
+   family of system calls because that is the preferred approach for new kernel
    interfaces.  The only real difference was whether we wanted to use open(2)
    and ioctl(2) or a couple of new system calls.  System calls beat ioctls.
 
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
index 2f38846..5531694 100644
--- a/Documentation/filesystems/porting
+++ b/Documentation/filesystems/porting
@@ -50,10 +50,11 @@
 success and negative number in case of error (-EINVAL unless you have more
 informative error value to report).  Call it foo_fill_super().  Now declare
 
-struct super_block foo_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+int foo_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, foo_fill_super,
+			   mnt);
 }
 
 (or similar with s/bdev/nodev/ or s/bdev/single/, depending on the kind of
diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
index 60ab61e..25981e2 100644
--- a/Documentation/filesystems/ramfs-rootfs-initramfs.txt
+++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
@@ -70,11 +70,13 @@
 What is rootfs?
 ---------------
 
-Rootfs is a special instance of ramfs, which is always present in 2.6 systems.
-(It's used internally as the starting and stopping point for searches of the
-kernel's doubly-linked list of mount points.)
+Rootfs is a special instance of ramfs (or tmpfs, if that's enabled), which is
+always present in 2.6 systems.  You can't unmount rootfs for approximately the
+same reason you can't kill the init process; rather than having special code
+to check for and handle an empty list, it's smaller and simpler for the kernel
+to just make sure certain lists can't become empty.
 
-Most systems just mount another filesystem over it and ignore it.  The
+Most systems just mount another filesystem over rootfs and ignore it.  The
 amount of space an empty instance of ramfs takes up is tiny.
 
 What is initramfs?
@@ -92,14 +94,16 @@
 
 All this differs from the old initrd in several ways:
 
-  - The old initrd was a separate file, while the initramfs archive is linked
-    into the linux kernel image.  (The directory linux-*/usr is devoted to
-    generating this archive during the build.)
+  - The old initrd was always a separate file, while the initramfs archive is
+    linked into the linux kernel image.  (The directory linux-*/usr is devoted
+    to generating this archive during the build.)
 
   - The old initrd file was a gzipped filesystem image (in some file format,
-    such as ext2, that had to be built into the kernel), while the new
+    such as ext2, that needed a driver built into the kernel), while the new
     initramfs archive is a gzipped cpio archive (like tar only simpler,
-    see cpio(1) and Documentation/early-userspace/buffer-format.txt).
+    see cpio(1) and Documentation/early-userspace/buffer-format.txt).  The
+    kernel's cpio extraction code is not only extremely small, it's also
+    __init data that can be discarded during the boot process.
 
   - The program run by the old initrd (which was called /initrd, not /init) did
     some setup and then returned to the kernel, while the init program from
@@ -124,13 +128,14 @@
 
 The 2.6 kernel build process always creates a gzipped cpio format initramfs
 archive and links it into the resulting kernel binary.  By default, this
-archive is empty (consuming 134 bytes on x86).  The config option
-CONFIG_INITRAMFS_SOURCE (for some reason buried under devices->block devices
-in menuconfig, and living in usr/Kconfig) can be used to specify a source for
-the initramfs archive, which will automatically be incorporated into the
-resulting binary.  This option can point to an existing gzipped cpio archive, a
-directory containing files to be archived, or a text file specification such
-as the following example:
+archive is empty (consuming 134 bytes on x86).
+
+The config option CONFIG_INITRAMFS_SOURCE (for some reason buried under
+devices->block devices in menuconfig, and living in usr/Kconfig) can be used
+to specify a source for the initramfs archive, which will automatically be
+incorporated into the resulting binary.  This option can point to an existing
+gzipped cpio archive, a directory containing files to be archived, or a text
+file specification such as the following example:
 
   dir /dev 755 0 0
   nod /dev/console 644 0 0 c 5 1
@@ -146,23 +151,84 @@
 Run "usr/gen_init_cpio" (after the kernel build) to get a usage message
 documenting the above file format.
 
-One advantage of the text file is that root access is not required to
+One advantage of the configuration file is that root access is not required to
 set permissions or create device nodes in the new archive.  (Note that those
 two example "file" entries expect to find files named "init.sh" and "busybox" in
 a directory called "initramfs", under the linux-2.6.* directory.  See
 Documentation/early-userspace/README for more details.)
 
-The kernel does not depend on external cpio tools, gen_init_cpio is created
-from usr/gen_init_cpio.c which is entirely self-contained, and the kernel's
-boot-time extractor is also (obviously) self-contained.  However, if you _do_
-happen to have cpio installed, the following command line can extract the
-generated cpio image back into its component files:
+The kernel does not depend on external cpio tools.  If you specify a
+directory instead of a configuration file, the kernel's build infrastructure
+creates a configuration file from that directory (usr/Makefile calls
+scripts/gen_initramfs_list.sh), and proceeds to package up that directory
+using the config file (by feeding it to usr/gen_init_cpio, which is created
+from usr/gen_init_cpio.c).  The kernel's build-time cpio creation code is
+entirely self-contained, and the kernel's boot-time extractor is also
+(obviously) self-contained.
+
+The one thing you might need external cpio utilities installed for is creating
+or extracting your own preprepared cpio files to feed to the kernel build
+(instead of a config file or directory).
+
+The following command line can extract a cpio image (either by the above script
+or by the kernel build) back into its component files:
 
   cpio -i -d -H newc -F initramfs_data.cpio --no-absolute-filenames
 
+The following shell script can create a prebuilt cpio archive you can
+use in place of the above config file:
+
+  #!/bin/sh
+
+  # Copyright 2006 Rob Landley <rob@landley.net> and TimeSys Corporation.
+  # Licensed under GPL version 2
+
+  if [ $# -ne 2 ]
+  then
+    echo "usage: mkinitramfs directory imagename.cpio.gz"
+    exit 1
+  fi
+
+  if [ -d "$1" ]
+  then
+    echo "creating $2 from $1"
+    (cd "$1"; find . | cpio -o -H newc | gzip) > "$2"
+  else
+    echo "First argument must be a directory"
+    exit 1
+  fi
+
+Note: The cpio man page contains some bad advice that will break your initramfs
+archive if you follow it.  It says "A typical way to generate the list
+of filenames is with the find command; you should give find the -depth option
+to minimize problems with permissions on directories that are unwritable or not
+searchable."  Don't do this when creating initramfs.cpio.gz images, it won't
+work.  The Linux kernel cpio extractor won't create files in a directory that
+doesn't exist, so the directory entries must go before the files that go in
+those directories.  The above script gets them in the right order.
+
+External initramfs images:
+--------------------------
+
+If the kernel has initrd support enabled, an external cpio.gz archive can also
+be passed into a 2.6 kernel in place of an initrd.  In this case, the kernel
+will autodetect the type (initramfs, not initrd) and extract the external cpio
+archive into rootfs before trying to run /init.
+
+This has the memory efficiency advantages of initramfs (no ramdisk block
+device) but the separate packaging of initrd (which is nice if you have
+non-GPL code you'd like to run from initramfs, without conflating it with
+the GPL licensed Linux kernel binary).
+
+It can also be used to supplement the kernel's built-in initamfs image.  The
+files in the external archive will overwrite any conflicting files in
+the built-in initramfs archive.  Some distributors also prefer to customize
+a single kernel image with task-specific initramfs images, without recompiling.
+
 Contents of initramfs:
 ----------------------
 
+An initramfs archive is a complete self-contained root filesystem for Linux.
 If you don't already understand what shared libraries, devices, and paths
 you need to get a minimal root filesystem up and running, here are some
 references:
@@ -176,13 +242,36 @@
 
 I use uClibc (http://www.uclibc.org) and busybox (http://www.busybox.net)
 myself.  These are LGPL and GPL, respectively.  (A self-contained initramfs
-package is planned for the busybox 1.2 release.)
+package is planned for the busybox 1.3 release.)
 
 In theory you could use glibc, but that's not well suited for small embedded
 uses like this.  (A "hello world" program statically linked against glibc is
 over 400k.  With uClibc it's 7k.  Also note that glibc dlopens libnss to do
 name lookups, even when otherwise statically linked.)
 
+A good first step is to get initramfs to run a statically linked "hello world"
+program as init, and test it under an emulator like qemu (www.qemu.org) or
+User Mode Linux, like so:
+
+  cat > hello.c << EOF
+  #include <stdio.h>
+  #include <unistd.h>
+
+  int main(int argc, char *argv[])
+  {
+    printf("Hello world!\n");
+    sleep(999999999);
+  }
+  EOF
+  gcc -static hello2.c -o init
+  echo init | cpio -o -H newc | gzip > test.cpio.gz
+  # Testing external initramfs using the initrd loading mechanism.
+  qemu -kernel /boot/vmlinuz -initrd test.cpio.gz /dev/zero
+
+When debugging a normal root filesystem, it's nice to be able to boot with
+"init=/bin/sh".  The initramfs equivalent is "rdinit=/bin/sh", and it's
+just as useful.
+
 Why cpio rather than tar?
 -------------------------
 
@@ -241,7 +330,7 @@
 Future directions:
 ------------------
 
-Today (2.6.14), initramfs is always compiled in, but not always used.  The
+Today (2.6.16), initramfs is always compiled in, but not always used.  The
 kernel falls back to legacy boot code that is reached only if initramfs does
 not contain an /init program.  The fallback is legacy code, there to ensure a
 smooth transition and allowing early boot functionality to gradually move to
@@ -258,8 +347,9 @@
 
 This kind of complexity (which inevitably includes policy) is rightly handled
 in userspace.  Both klibc and busybox/uClibc are working on simple initramfs
-packages to drop into a kernel build, and when standard solutions are ready
-and widely deployed, the kernel's legacy early boot code will become obsolete
-and a candidate for the feature removal schedule.
+packages to drop into a kernel build.
 
-But that's a while off yet.
+The klibc package has now been accepted into Andrew Morton's 2.6.17-mm tree.
+The kernel's current early boot code (partition detection, etc) will probably
+be migrated into a default initramfs, automatically created and used by the
+kernel build.
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index 3a2e552..9d3aed6 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -113,8 +113,8 @@
 struct file_system_type {
 	const char *name;
 	int fs_flags;
-        struct super_block *(*get_sb) (struct file_system_type *, int,
-                                       const char *, void *);
+        struct int (*get_sb) (struct file_system_type *, int,
+                              const char *, void *, struct vfsmount *);
         void (*kill_sb) (struct super_block *);
         struct module *owner;
         struct file_system_type * next;
@@ -211,7 +211,7 @@
         int (*sync_fs)(struct super_block *sb, int wait);
         void (*write_super_lockfs) (struct super_block *);
         void (*unlockfs) (struct super_block *);
-        int (*statfs) (struct super_block *, struct kstatfs *);
+        int (*statfs) (struct dentry *, struct kstatfs *);
         int (*remount_fs) (struct super_block *, int *, char *);
         void (*clear_inode) (struct inode *);
         void (*umount_begin) (struct super_block *);
diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru
new file mode 100644
index 0000000..69cdb52
--- /dev/null
+++ b/Documentation/hwmon/abituguru
@@ -0,0 +1,59 @@
+Kernel driver abituguru
+=======================
+
+Supported chips:
+  * Abit uGuru (Hardware Monitor part only)
+    Prefix: 'abituguru'
+    Addresses scanned: ISA 0x0E0
+    Datasheet: Not available, this driver is based on reverse engineering.
+	A "Datasheet" has been written based on the reverse engineering it
+	should be available in the same dir as this file under the name
+	abituguru-datasheet.
+
+Authors:
+	Hans de Goede <j.w.r.degoede@hhs.nl>,
+	(Initial reverse engineering done by Olle Sandberg
+	 <ollebull@gmail.com>)
+
+
+Module Parameters
+-----------------
+
+* force: bool		Force detection. Note this parameter only causes the
+			detection to be skipped, if the uGuru can't be read
+			the module initialization (insmod) will still fail.
+* fan_sensors: int	Tell the driver how many fan speed sensors there are
+			on your motherboard. Default: 0 (autodetect).
+* pwms: int		Tell the driver how many fan speed controls (fan
+			pwms) your motherboard has. Default: 0 (autodetect).
+* verbose: int		How verbose should the driver be? (0-3):
+			   0 normal output
+			   1 + verbose error reporting
+			   2 + sensors type probing info\n"
+			   3 + retryable error reporting
+			Default: 2 (the driver is still in the testing phase)
+
+Notice if you need any of the first three options above please insmod the
+driver with verbose set to 3 and mail me <j.w.r.degoede@hhs.nl> the output of:
+dmesg | grep abituguru
+
+
+Description
+-----------
+
+This driver supports the hardware monitoring features of the Abit uGuru chip
+found on Abit uGuru featuring motherboards (most modern Abit motherboards).
+
+The uGuru chip in reality is a Winbond W83L950D in disguise (despite Abit
+claiming it is "a new microprocessor designed by the ABIT Engineers").
+Unfortunatly this doesn't help since the W83L950D is a generic
+microcontroller with a custom Abit application running on it.
+
+Despite Abit not releasing any information regarding the uGuru, Olle
+Sandberg <ollebull@gmail.com> has managed to reverse engineer the sensor part
+of the uGuru. Without his work this driver would not have been possible.
+
+Known Issues
+------------
+
+The voltage and frequency control parts of the Abit uGuru are not supported.
diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet
new file mode 100644
index 0000000..aef5a9b
--- /dev/null
+++ b/Documentation/hwmon/abituguru-datasheet
@@ -0,0 +1,312 @@
+uGuru datasheet
+===============
+
+First of all, what I know about uGuru is no fact based on any help, hints or
+datasheet from Abit. The data I have got on uGuru have I assembled through
+my weak knowledge in "backwards engineering".
+And just for the record, you may have noticed uGuru isn't a chip developed by
+Abit, as they claim it to be. It's realy just an microprocessor (uC) created by
+Winbond (W83L950D). And no, reading the manual for this specific uC or
+mailing  Windbond for help won't give any usefull data about uGuru, as it is
+the program inside the uC that is responding to calls.
+
+Olle Sandberg <ollebull@gmail.com>, 2005-05-25
+
+
+Original version by Olle Sandberg who did the heavy lifting of the initial
+reverse engineering. This version has been almost fully rewritten for clarity
+and extended with write support and info on more databanks, the write support
+is once again reverse engineered by Olle the additional databanks have been
+reverse engineered by me. I would like to express my thanks to Olle, this
+document and the Linux driver could not have been written without his efforts.
+
+Note: because of the lack of specs only the sensors part of the uGuru is
+described here and not the CPU / RAM / etc voltage & frequency control.
+
+Hans de Goede <j.w.r.degoede@hhs.nl>, 28-01-2006
+
+
+Detection
+=========
+
+As far as known the uGuru is always placed at and using the (ISA) I/O-ports
+0xE0 and 0xE4, so we don't have to scan any port-range, just check what the two
+ports are holding for detection. We will refer to 0xE0 as CMD (command-port)
+and 0xE4 as DATA because Abit refers to them with these names.
+
+If DATA holds 0x00 or 0x08 and CMD holds 0x00 or 0xAC an uGuru could be
+present. We have to check for two different values at data-port, because
+after a reboot uGuru will hold 0x00 here, but if the driver is removed and
+later on attached again data-port will hold 0x08, more about this later.
+
+After wider testing of the Linux kernel driver some variants of the uGuru have
+turned up which will hold 0x00 instead of 0xAC at the CMD port, thus we also
+have to test CMD for two different values. On these uGuru's DATA will initally
+hold 0x09 and will only hold 0x08 after reading CMD first, so CMD must be read
+first!
+
+To be really sure an uGuru is present a test read of one or more register
+sets should be done.
+
+
+Reading / Writing
+=================
+
+Addressing
+----------
+
+The uGuru has a number of different addressing levels. The first addressing
+level we will call banks. A bank holds data for one or more sensors. The data
+in a bank for a sensor is one or more bytes large.
+
+The number of bytes is fixed for a given bank, you should always read or write
+that many bytes, reading / writing more will fail, the results when writing
+less then the number of bytes for a given bank are undetermined.
+
+See below for all known bank addresses, numbers of sensors in that bank,
+number of bytes data per sensor and contents/meaning of those bytes.
+
+Although both this document and the kernel driver have kept the sensor
+terminoligy for the addressing within a bank this is not 100% correct, in
+bank 0x24 for example the addressing within the bank selects a PWM output not
+a sensor.
+
+Notice that some banks have both a read and a write address this is how the
+uGuru determines if a read from or a write to the bank is taking place, thus
+when reading you should always use the read address and when writing the
+write address. The write address is always one (1) more then the read address.
+
+
+uGuru ready
+-----------
+
+Before you can read from or write to the uGuru you must first put the uGuru
+in "ready" mode.
+
+To put the uGuru in ready mode first write 0x00 to DATA and then wait for DATA
+to hold 0x09, DATA should read 0x09 within 250 read cycles.
+
+Next CMD _must_ be read and should hold 0xAC, usually CMD will hold 0xAC the
+first read but sometimes it takes a while before CMD holds 0xAC and thus it
+has to be read a number of times (max 50).
+
+After reading CMD, DATA should hold 0x08 which means that the uGuru is ready
+for input. As above DATA will usually hold 0x08 the first read but not always.
+This step can be skipped, but it is undetermined what happens if the uGuru has
+not yet reported 0x08 at DATA and you proceed with writing a bank address.
+
+
+Sending bank and sensor addresses to the uGuru
+----------------------------------------------
+
+First the uGuru must be in "ready" mode as described above, DATA should hold
+0x08 indicating that the uGuru wants input, in this case the bank address.
+
+Next write the bank address to DATA. After the bank address has been written
+wait for to DATA to hold 0x08 again indicating that it wants / is ready for
+more input (max 250 reads).
+
+Once DATA holds 0x08 again write the sensor address to CMD.
+
+
+Reading
+-------
+
+First send the bank and sensor addresses as described above.
+Then for each byte of data you want to read wait for DATA to hold 0x01
+which indicates that the uGuru is ready to be read (max 250 reads) and once
+DATA holds 0x01 read the byte from CMD.
+
+Once all bytes have been read data will hold 0x09, but there is no reason to
+test for this. Notice that the number of bytes is bank address dependent see
+above and below.
+
+After completing a successfull read it is advised to put the uGuru back in
+ready mode, so that it is ready for the next read / write cycle. This way
+if your program / driver is unloaded and later loaded again the detection
+algorithm described above will still work.
+
+
+
+Writing
+-------
+
+First send the bank and sensor addresses as described above.
+Then for each byte of data you want to write wait for DATA to hold 0x00
+which indicates that the uGuru is ready to be written (max 250 reads) and
+once DATA holds 0x00 write the byte to CMD.
+
+Once all bytes have been written wait for DATA to hold 0x01 (max 250 reads)
+don't ask why this is the way it is.
+
+Once DATA holds 0x01 read CMD it should hold 0xAC now.
+
+After completing a successfull write it is advised to put the uGuru back in
+ready mode, so that it is ready for the next read / write cycle. This way
+if your program / driver is unloaded and later loaded again the detection
+algorithm described above will still work.
+
+
+Gotchas
+-------
+
+After wider testing of the Linux kernel driver some variants of the uGuru have
+turned up which do not hold 0x08 at DATA within 250 reads after writing the
+bank address. With these versions this happens quite frequent, using larger
+timeouts doesn't help, they just go offline for a second or 2, doing some
+internal callibration or whatever. Your code should be prepared to handle
+this and in case of no response in this specific case just goto sleep for a
+while and then retry.
+
+
+Address Map
+===========
+
+Bank 0x20 Alarms (R)
+--------------------
+This bank contains 0 sensors, iow the sensor address is ignored (but must be
+written) just use 0. Bank 0x20 contains 3 bytes:
+
+Byte 0:
+This byte holds the alarm flags for sensor 0-7 of Sensor Bank1, with bit 0
+corresponding to sensor 0, 1 to 1, etc.
+
+Byte 1:
+This byte holds the alarm flags for sensor 8-15 of Sensor Bank1, with bit 0
+corresponding to sensor 8, 1 to 9, etc.
+
+Byte 2:
+This byte holds the alarm flags for sensor 0-5 of Sensor Bank2, with bit 0
+corresponding to sensor 0, 1 to 1, etc.
+
+
+Bank 0x21 Sensor Bank1 Values / Readings (R)
+--------------------------------------------
+This bank contains 16 sensors, for each sensor it contains 1 byte.
+So far the following sensors are known to be available on all motherboards:
+Sensor  0 CPU temp
+Sensor  1 SYS temp
+Sensor  3 CPU core volt
+Sensor  4 DDR volt
+Sensor 10 DDR Vtt volt
+Sensor 15 PWM temp
+
+Byte 0:
+This byte holds the reading from the sensor. Sensors in Bank1 can be both
+volt and temp sensors, this is motherboard specific. The uGuru however does
+seem to know (be programmed with) what kindoff sensor is attached see Sensor
+Bank1 Settings description.
+
+Volt sensors use a linear scale, a reading 0 corresponds with 0 volt and a
+reading of 255 with 3494 mV. The sensors for higher voltages however are
+connected through a division circuit. The currently known division circuits
+in use result in ranges of: 0-4361mV, 0-6248mV or 0-14510mV. 3.3 volt sources
+use the 0-4361mV range, 5 volt the 0-6248mV and 12 volt the 0-14510mV .
+
+Temp sensors also use a linear scale, a reading of 0 corresponds with 0 degree
+Celsius and a reading of 255 with a reading of 255 degrees Celsius.
+
+
+Bank 0x22 Sensor Bank1 Settings (R)
+Bank 0x23 Sensor Bank1 Settings (W)
+-----------------------------------
+
+This bank contains 16 sensors, for each sensor it contains 3 bytes. Each
+set of 3 bytes contains the settings for the sensor with the same sensor
+address in Bank 0x21 .
+
+Byte 0:
+Alarm behaviour for the selected sensor. A 1 enables the described behaviour.
+Bit 0: Give an alarm if measured temp is over the warning threshold	(RW) *
+Bit 1: Give an alarm if measured volt is over the max threshold		(RW) **
+Bit 2: Give an alarm if measured volt is under the min threshold	(RW) **
+Bit 3: Beep if alarm							(RW)
+Bit 4: 1 if alarm cause measured temp is over the warning threshold	(R)
+Bit 5: 1 if alarm cause measured volt is over the max threshold		(R)
+Bit 6: 1 if alarm cause measured volt is under the min threshold	(R)
+Bit 7: Volt sensor: Shutdown if alarm persist for more then 4 seconds	(RW)
+       Temp sensor: Shutdown if temp is over the shutdown threshold	(RW)
+
+*  This bit is only honored/used by the uGuru if a temp sensor is connected
+** This bit is only honored/used by the uGuru if a volt sensor is connected
+Note with some trickery this can be used to find out what kinda sensor is
+detected see the Linux kernel driver for an example with many comments on
+how todo this.
+
+Byte 1:
+Temp sensor: warning threshold  (scale as bank 0x21)
+Volt sensor: min threshold      (scale as bank 0x21)
+
+Byte 2:
+Temp sensor: shutdown threshold (scale as bank 0x21)
+Volt sensor: max threshold      (scale as bank 0x21)
+
+
+Bank 0x24 PWM outputs for FAN's (R)
+Bank 0x25 PWM outputs for FAN's (W)
+-----------------------------------
+
+This bank contains 3 "sensors", for each sensor it contains 5 bytes.
+Sensor 0 usually controls the CPU fan
+Sensor 1 usually controls the NB (or chipset for single chip) fan
+Sensor 2 usually controls the System fan
+
+Byte 0:
+Flag 0x80 to enable control, Fan runs at 100% when disabled.
+low nibble (temp)sensor address at bank 0x21 used for control.
+
+Byte 1:
+0-255 = 0-12v (linear), specify voltage at which fan will rotate when under
+low threshold temp (specified in byte 3)
+
+Byte 2:
+0-255 = 0-12v (linear), specify voltage at which fan will rotate when above
+high threshold temp (specified in byte 4)
+
+Byte 3:
+Low threshold temp  (scale as bank 0x21)
+
+byte 4:
+High threshold temp (scale as bank 0x21)
+
+
+Bank 0x26 Sensors Bank2 Values / Readings (R)
+---------------------------------------------
+
+This bank contains 6 sensors (AFAIK), for each sensor it contains 1 byte.
+So far the following sensors are known to be available on all motherboards:
+Sensor 0: CPU fan speed
+Sensor 1: NB (or chipset for single chip) fan speed
+Sensor 2: SYS fan speed
+
+Byte 0:
+This byte holds the reading from the sensor. 0-255 = 0-15300 (linear)
+
+
+Bank 0x27 Sensors Bank2 Settings (R)
+Bank 0x28 Sensors Bank2 Settings (W)
+------------------------------------
+
+This bank contains 6 sensors (AFAIK), for each sensor it contains 2 bytes.
+
+Byte 0:
+Alarm behaviour for the selected sensor. A 1 enables the described behaviour.
+Bit 0: Give an alarm if measured rpm is under the min threshold	(RW)
+Bit 3: Beep if alarm						(RW)
+Bit 7: Shutdown if alarm persist for more then 4 seconds	(RW)
+
+Byte 1:
+min threshold (scale as bank 0x26)
+
+
+Warning for the adventerous
+===========================
+
+A word of caution to those who want to experiment and see if they can figure
+the voltage / clock programming out, I tried reading and only reading banks
+0-0x30 with the reading code used for the sensor banks (0x20-0x28) and this
+resulted in a _permanent_ reprogramming of the voltages, luckily I had the
+sensors part configured so that it would shutdown my system on any out of spec
+voltages which proprably safed my computer (after a reboot I managed to
+immediatly enter the bios and reload the defaults). This probably means that
+the read/write cycle for the non sensor part is different from the sensor part.
diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70
new file mode 100644
index 0000000..2bdd3fe
--- /dev/null
+++ b/Documentation/hwmon/lm70
@@ -0,0 +1,31 @@
+Kernel driver lm70
+==================
+
+Supported chip:
+  * National Semiconductor LM70
+    Datasheet: http://www.national.com/pf/LM/LM70.html
+
+Author:
+        Kaiwan N Billimoria <kaiwan@designergraphix.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM70
+temperature sensor.
+
+The LM70 temperature sensor chip supports a single temperature sensor.
+It communicates with a host processor (or microcontroller) via an
+SPI/Microwire Bus interface.
+
+Communication with the LM70 is simple: when the temperature is to be sensed,
+the driver accesses the LM70 using SPI communication: 16 SCLK cycles
+comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's
+complement digital temperature (sent via the SIO line), is available in the
+driver for interpretation. This driver makes use of the kernel's in-core
+SPI support.
+
+Thanks to
+---------
+Jean Delvare <khali@linux-fr.org> for mentoring the hwmon-side driver
+development.
diff --git a/Documentation/hwmon/lm83 b/Documentation/hwmon/lm83
index 061d9ed..f7aad14 100644
--- a/Documentation/hwmon/lm83
+++ b/Documentation/hwmon/lm83
@@ -7,6 +7,10 @@
     Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/pf/LM/LM83.html
+  * National Semiconductor LM82
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM82.html
 
 
 Author: Jean Delvare <khali@linux-fr.org>
@@ -15,10 +19,11 @@
 -----------
 
 The LM83 is a digital temperature sensor. It senses its own temperature as
-well as the temperature of up to three external diodes. It is compatible
-with many other devices such as the LM84 and all other ADM1021 clones.
-The main difference between the LM83 and the LM84 in that the later can
-only sense the temperature of one external diode.
+well as the temperature of up to three external diodes. The LM82 is
+a stripped down version of the LM83 that only supports one external diode.
+Both are compatible with many other devices such as the LM84 and all
+other ADM1021 clones. The main difference between the LM83 and the LM84
+in that the later can only sense the temperature of one external diode.
 
 Using the adm1021 driver for a LM83 should work, but only two temperatures
 will be reported instead of four.
@@ -30,12 +35,16 @@
 
 Confirmed motherboards:
     SBS         P014
+    SBS         PSL09
 
 Unconfirmed motherboards:
     Gigabyte    GA-8IK1100
     Iwill       MPX2
     Soltek      SL-75DRV5
 
+The LM82 is confirmed to have been found on most AMD Geode reference
+designs and test platforms.
+
 The driver has been successfully tested by Magnus Forsström, who I'd
 like to thank here. More testers will be of course welcome.
 
diff --git a/Documentation/hwmon/smsc47m192 b/Documentation/hwmon/smsc47m192
new file mode 100644
index 0000000..45d6453
--- /dev/null
+++ b/Documentation/hwmon/smsc47m192
@@ -0,0 +1,102 @@
+Kernel driver smsc47m192
+========================
+
+Supported chips:
+  * SMSC LPC47M192 and LPC47M997
+    Prefix: 'smsc47m192'
+    Addresses scanned: I2C 0x2c - 0x2d
+    Datasheet: The datasheet for LPC47M192 is publicly available from
+               http://www.smsc.com/
+               The LPC47M997 is compatible for hardware monitoring.
+
+Author: Hartmut Rick <linux@rick.claranet.de>
+        Special thanks to Jean Delvare for careful checking
+        of the code and many helpful comments and suggestions.
+
+
+Description
+-----------
+
+This driver implements support for the hardware sensor capabilities
+of the SMSC LPC47M192 and LPC47M997 Super-I/O chips.
+
+These chips support 3 temperature channels and 8 voltage inputs
+as well as CPU voltage VID input.
+
+They do also have fan monitoring and control capabilities, but the
+these features are accessed via ISA bus and are not supported by this
+driver. Use the 'smsc47m1' driver for fan monitoring and control.
+
+Voltages and temperatures are measured by an 8-bit ADC, the resolution
+of the temperatures is 1 bit per degree C.
+Voltages are scaled such that the nominal voltage corresponds to
+192 counts, i.e. 3/4 of the full range. Thus the available range for
+each voltage channel is 0V ... 255/192*(nominal voltage), the resolution
+is 1 bit per (nominal voltage)/192.
+Both voltage and temperature values are scaled by 1000, the sys files
+show voltages in mV and temperatures in units of 0.001 degC.
+
+The +12V analog voltage input channel (in4_input) is multiplexed with
+bit 4 of the encoded CPU voltage. This means that you either get
+a +12V voltage measurement or a 5 bit CPU VID, but not both.
+The default setting is to use the pin as 12V input, and use only 4 bit VID.
+This driver assumes that the information in the configuration register
+is correct, i.e. that the BIOS has updated the configuration if
+the motherboard has this input wired to VID4.
+
+The temperature and voltage readings are updated once every 1.5 seconds.
+Reading them more often repeats the same values.
+
+
+sysfs interface
+---------------
+
+in0_input	- +2.5V voltage input
+in1_input	- CPU voltage input (nominal 2.25V)
+in2_input	- +3.3V voltage input
+in3_input	- +5V voltage input
+in4_input	- +12V voltage input (may be missing if used as VID4)
+in5_input	- Vcc voltage input (nominal 3.3V)
+		  This is the supply voltage of the sensor chip itself.
+in6_input	- +1.5V voltage input
+in7_input	- +1.8V voltage input
+
+in[0-7]_min,
+in[0-7]_max	- lower and upper alarm thresholds for in[0-7]_input reading
+
+		  All voltages are read and written in mV.
+
+in[0-7]_alarm	- alarm flags for voltage inputs
+		  These files read '1' in case of alarm, '0' otherwise.
+
+temp1_input	- chip temperature measured by on-chip diode
+temp[2-3]_input	- temperature measured by external diodes (one of these would
+		  typically be wired to the diode inside the CPU)
+
+temp[1-3]_min,
+temp[1-3]_max	- lower and upper alarm thresholds for temperatures
+
+temp[1-3]_offset - temperature offset registers
+		  The chip adds the offsets stored in these registers to
+		  the corresponding temperature readings.
+		  Note that temp1 and temp2 offsets share the same register,
+		  they cannot both be different from zero at the same time.
+		  Writing a non-zero number to one of them will reset the other
+		  offset to zero.
+
+		  All temperatures and offsets are read and written in
+		  units of 0.001 degC.
+
+temp[1-3]_alarm - alarm flags for temperature inputs, '1' in case of alarm,
+		  '0' otherwise.
+temp[2-3]_input_fault - diode fault flags for temperature inputs 2 and 3.
+		  A fault is detected if the two pins for the corresponding
+		  sensor are open or shorted, or any of the two is shorted
+		  to ground or Vcc. '1' indicates a diode fault.
+
+cpu0_vid	- CPU voltage as received from the CPU
+
+vrm		- CPU VID standard used for decoding CPU voltage
+
+		  The *_min, *_max, *_offset and vrm files can be read and
+		  written, all others are read-only.
diff --git a/Documentation/hwmon/sysfs-interface b/Documentation/hwmon/sysfs-interface
index a0d0ab2..d1d390a 100644
--- a/Documentation/hwmon/sysfs-interface
+++ b/Documentation/hwmon/sysfs-interface
@@ -3,15 +3,15 @@
 
 The libsensors library offers an interface to the raw sensors data
 through the sysfs interface. See libsensors documentation and source for
-more further information. As of writing this document, libsensors
-(from lm_sensors 2.8.3) is heavily chip-dependant. Adding or updating
+further information. As of writing this document, libsensors
+(from lm_sensors 2.8.3) is heavily chip-dependent. Adding or updating
 support for any given chip requires modifying the library's code.
 This is because libsensors was written for the procfs interface
 older kernel modules were using, which wasn't standardized enough.
 Recent versions of libsensors (from lm_sensors 2.8.2 and later) have
 support for the sysfs interface, though.
 
-The new sysfs interface was designed to be as chip-independant as
+The new sysfs interface was designed to be as chip-independent as
 possible.
 
 Note that motherboards vary widely in the connections to sensor chips.
@@ -24,7 +24,7 @@
 can change from motherboard to motherboard, the conversions cannot be
 hard coded into the driver and have to be done in user space.
 
-For this reason, even if we aim at a chip-independant libsensors, it will
+For this reason, even if we aim at a chip-independent libsensors, it will
 still require a configuration file (e.g. /etc/sensors.conf) for proper
 values conversion, labeling of inputs and hiding of unused inputs.
 
@@ -39,15 +39,16 @@
 this standard.
 
 Note that this standard isn't completely established yet, so it is subject
-to changes, even important ones. One more reason to use the library instead
-of accessing sysfs files directly.
+to changes. If you are writing a new hardware monitoring driver those
+features can't seem to fit in this interface, please contact us with your
+extension proposal. Keep in mind that backward compatibility must be
+preserved.
 
 Each chip gets its own directory in the sysfs /sys/devices tree.  To
-find all sensor chips, it is easier to follow the symlinks from
-/sys/i2c/devices/
+find all sensor chips, it is easier to follow the device symlinks from
+/sys/class/hwmon/hwmon*.
 
-All sysfs values are fixed point numbers.  To get the true value of some
-of the values, you should divide by the specified value.
+All sysfs values are fixed point numbers.
 
 There is only one value per file, unlike the older /proc specification.
 The common scheme for files naming is: <type><number>_<item>. Usual
@@ -69,28 +70,40 @@
 
 -------------------------------------------------------------------------
 
+[0-*]	denotes any positive number starting from 0
+[1-*]	denotes any positive number starting from 1
+RO	read only value
+RW	read/write value
+
+Read/write values may be read-only for some chips, depending on the
+hardware implementation.
+
+All entries are optional, and should only be created in a given driver
+if the chip has the feature.
+
 ************
 * Voltages *
 ************
 
-in[0-8]_min	Voltage min value.
+in[0-*]_min	Voltage min value.
 		Unit: millivolt
-		Read/Write
+		RW
 		
-in[0-8]_max	Voltage max value.
+in[0-*]_max	Voltage max value.
 		Unit: millivolt
-		Read/Write
+		RW
 		
-in[0-8]_input	Voltage input value.
+in[0-*]_input	Voltage input value.
 		Unit: millivolt
-		Read only
+		RO
+		Voltage measured on the chip pin.
 		Actual voltage depends on the scaling resistors on the
 		motherboard, as recommended in the chip datasheet.
 		This varies by chip and by motherboard.
 		Because of this variation, values are generally NOT scaled
 		by the chip driver, and must be done by the application.
 		However, some drivers (notably lm87 and via686a)
-		do scale, with various degrees of success.
+		do scale, because of internal resistors built into a chip.
 		These drivers will output the actual voltage.
 
 		Typical usage:
@@ -104,58 +117,72 @@
 			in7_*	varies
 			in8_*	varies
 
-cpu[0-1]_vid	CPU core reference voltage.
+cpu[0-*]_vid	CPU core reference voltage.
 		Unit: millivolt
-		Read only.
+		RO
 		Not always correct.
 
 vrm		Voltage Regulator Module version number. 
-		Read only.
-		Two digit number, first is major version, second is
-		minor version.
+		RW (but changing it should no more be necessary)
+		Originally the VRM standard version multiplied by 10, but now
+		an arbitrary number, as not all standards have a version
+		number.
 		Affects the way the driver calculates the CPU core reference
 		voltage from the vid pins.
 
+Also see the Alarms section for status flags associated with voltages.
+
 
 ********
 * Fans *
 ********
 
-fan[1-3]_min	Fan minimum value
+fan[1-*]_min	Fan minimum value
 		Unit: revolution/min (RPM)
-		Read/Write.
+		RW
 
-fan[1-3]_input	Fan input value.
+fan[1-*]_input	Fan input value.
 		Unit: revolution/min (RPM)
-		Read only.
+		RO
 
-fan[1-3]_div	Fan divisor.
+fan[1-*]_div	Fan divisor.
 		Integer value in powers of two (1, 2, 4, 8, 16, 32, 64, 128).
+		RW
 		Some chips only support values 1, 2, 4 and 8.
 		Note that this is actually an internal clock divisor, which
 		affects the measurable speed range, not the read value.
 
+Also see the Alarms section for status flags associated with fans.
+
+
 *******
 * PWM *
 *******
 
-pwm[1-3]	Pulse width modulation fan control.
+pwm[1-*]	Pulse width modulation fan control.
 		Integer value in the range 0 to 255
-		Read/Write
+		RW
 		255 is max or 100%.
 
-pwm[1-3]_enable
+pwm[1-*]_enable
 		Switch PWM on and off.
 		Not always present even if fan*_pwm is.
-		0 to turn off
-		1 to turn on in manual mode
-		2 to turn on in automatic mode
-		Read/Write
+		0: turn off
+		1: turn on in manual mode
+		2+: turn on in automatic mode
+		Check individual chip documentation files for automatic mode details.
+		RW
+
+pwm[1-*]_mode
+		0: DC mode
+		1: PWM mode
+		RW
 
 pwm[1-*]_auto_channels_temp
 		Select which temperature channels affect this PWM output in
 		auto mode. Bitfield, 1 is temp1, 2 is temp2, 4 is temp3 etc...
 		Which values are possible depend on the chip used.
+		RW
 
 pwm[1-*]_auto_point[1-*]_pwm
 pwm[1-*]_auto_point[1-*]_temp
@@ -163,6 +190,7 @@
 		Define the PWM vs temperature curve. Number of trip points is
 		chip-dependent. Use this for chips which associate trip points
 		to PWM output channels.
+		RW
 
 OR
 
@@ -172,50 +200,57 @@
 		Define the PWM vs temperature curve. Number of trip points is
 		chip-dependent. Use this for chips which associate trip points
 		to temperature channels.
+		RW
 
 
 ****************
 * Temperatures *
 ****************
 
-temp[1-3]_type	Sensor type selection.
+temp[1-*]_type	Sensor type selection.
 		Integers 1 to 4 or thermistor Beta value (typically 3435)
-		Read/Write.
+		RW
 		1: PII/Celeron Diode
 		2: 3904 transistor
 		3: thermal diode
 		4: thermistor (default/unknown Beta)
 		Not all types are supported by all chips
 
-temp[1-4]_max	Temperature max value.
-		Unit: millidegree Celcius
-		Read/Write value.
+temp[1-*]_max	Temperature max value.
+		Unit: millidegree Celsius (or millivolt, see below)
+		RW
 
-temp[1-3]_min	Temperature min value.
-		Unit: millidegree Celcius
-		Read/Write value.
+temp[1-*]_min	Temperature min value.
+		Unit: millidegree Celsius
+		RW
 
-temp[1-3]_max_hyst
+temp[1-*]_max_hyst
 		Temperature hysteresis value for max limit.
-		Unit: millidegree Celcius
+		Unit: millidegree Celsius
 		Must be reported as an absolute temperature, NOT a delta
 		from the max value.
-		Read/Write value.
+		RW
 
-temp[1-4]_input Temperature input value.
-		Unit: millidegree Celcius
-		Read only value.
+temp[1-*]_input Temperature input value.
+		Unit: millidegree Celsius
+		RO
 
-temp[1-4]_crit	Temperature critical value, typically greater than
+temp[1-*]_crit	Temperature critical value, typically greater than
 		corresponding temp_max values.
-		Unit: millidegree Celcius
-		Read/Write value.
+		Unit: millidegree Celsius
+		RW
 
-temp[1-2]_crit_hyst
+temp[1-*]_crit_hyst
 		Temperature hysteresis value for critical limit.
-		Unit: millidegree Celcius
+		Unit: millidegree Celsius
 		Must be reported as an absolute temperature, NOT a delta
 		from the critical value.
+		RW
+
+temp[1-4]_offset
+		Temperature offset which is added to the temperature reading
+		by the chip.
+		Unit: millidegree Celsius
 		Read/Write value.
 
 		If there are multiple temperature sensors, temp1_* is
@@ -225,6 +260,17 @@
 		itself, for example the thermal diode inside the CPU or
 		a thermistor nearby.
 
+Some chips measure temperature using external thermistors and an ADC, and
+report the temperature measurement as a voltage. Converting this voltage
+back to a temperature (or the other way around for limits) requires
+mathematical functions not available in the kernel, so the conversion
+must occur in user space. For these chips, all temp* files described
+above should contain values expressed in millivolt instead of millidegree
+Celsius. In other words, such temperature channels are handled as voltage
+channels by the driver.
+
+Also see the Alarms section for status flags associated with temperatures.
+
 
 ************
 * Currents *
@@ -233,25 +279,88 @@
 Note that no known chip provides current measurements as of writing,
 so this part is theoretical, so to say.
 
-curr[1-n]_max	Current max value
+curr[1-*]_max	Current max value
 		Unit: milliampere
-		Read/Write.
+		RW
 
-curr[1-n]_min	Current min value.
+curr[1-*]_min	Current min value.
 		Unit: milliampere
-		Read/Write.
+		RW
 
-curr[1-n]_input	Current input value
+curr[1-*]_input	Current input value
 		Unit: milliampere
-		Read only.
+		RO
 
 
-*********
-* Other *
-*********
+**********
+* Alarms *
+**********
+
+Each channel or limit may have an associated alarm file, containing a
+boolean value. 1 means than an alarm condition exists, 0 means no alarm.
+
+Usually a given chip will either use channel-related alarms, or
+limit-related alarms, not both. The driver should just reflect the hardware
+implementation.
+
+in[0-*]_alarm
+fan[1-*]_alarm
+temp[1-*]_alarm
+		Channel alarm
+		0: no alarm
+		1: alarm
+		RO
+
+OR
+
+in[0-*]_min_alarm
+in[0-*]_max_alarm
+fan[1-*]_min_alarm
+temp[1-*]_min_alarm
+temp[1-*]_max_alarm
+temp[1-*]_crit_alarm
+		Limit alarm
+		0: no alarm
+		1: alarm
+		RO
+
+Each input channel may have an associated fault file. This can be used
+to notify open diodes, unconnected fans etc. where the hardware
+supports it. When this boolean has value 1, the measurement for that
+channel should not be trusted.
+
+in[0-*]_input_fault
+fan[1-*]_input_fault
+temp[1-*]_input_fault
+		Input fault condition
+		0: no fault occured
+		1: fault condition
+		RO
+
+Some chips also offer the possibility to get beeped when an alarm occurs:
+
+beep_enable	Master beep enable
+		0: no beeps
+		1: beeps
+		RW
+
+in[0-*]_beep
+fan[1-*]_beep
+temp[1-*]_beep
+		Channel beep
+		0: disable
+		1: enable
+		RW
+
+In theory, a chip could provide per-limit beep masking, but no such chip
+was seen so far.
+
+Old drivers provided a different, non-standard interface to alarms and
+beeps. These interface files are deprecated, but will be kept around
+for compatibility reasons:
 
 alarms		Alarm bitmask.
-		Read only.
+		RO
 		Integer representation of one to four bytes.
 		A '1' bit means an alarm.
 		Chips should be programmed for 'comparator' mode so that
@@ -259,35 +368,26 @@
 		if it is still valid.
 		Generally a direct representation of a chip's internal
 		alarm registers; there is no standard for the position
-		of individual bits.
+		of individual bits. For this reason, the use of this
+		interface file for new drivers is discouraged. Use
+		individual *_alarm and *_fault files instead.
 		Bits are defined in kernel/include/sensors.h.
 
-alarms_in	Alarm bitmask relative to in (voltage) channels
-		Read only
-		A '1' bit means an alarm, LSB corresponds to in0 and so on
-		Prefered to 'alarms' for newer chips
-
-alarms_fan	Alarm bitmask relative to fan channels
-		Read only
-		A '1' bit means an alarm, LSB corresponds to fan1 and so on
-		Prefered to 'alarms' for newer chips
-
-alarms_temp	Alarm bitmask relative to temp (temperature) channels
-		Read only
-		A '1' bit means an alarm, LSB corresponds to temp1 and so on
-		Prefered to 'alarms' for newer chips
-
-beep_enable	Beep/interrupt enable
-		0 to disable.
-		1 to enable.
-		Read/Write
-
 beep_mask	Bitmask for beep.
-		Same format as 'alarms' with the same bit locations.
-		Read/Write
+		Same format as 'alarms' with the same bit locations,
+		use discouraged for the same reason. Use individual
+		*_beep files instead.
+		RW
+
+
+*********
+* Other *
+*********
 
 eeprom		Raw EEPROM data in binary form.
-		Read only.
+		RO
 
 pec		Enable or disable PEC (SMBus only)
-		Read/Write
+		0: disable
+		1: enable
+		RW
diff --git a/Documentation/hwmon/userspace-tools b/Documentation/hwmon/userspace-tools
index 2622aac..19900a8 100644
--- a/Documentation/hwmon/userspace-tools
+++ b/Documentation/hwmon/userspace-tools
@@ -6,31 +6,32 @@
 are also connected directly through the ISA bus.
 
 The kernel drivers make the data from the sensor chips available in the /sys
-virtual filesystem. Userspace tools are then used to display or set or the
-data in a more friendly manner.
+virtual filesystem. Userspace tools are then used to display the measured
+values or configure the chips in a more friendly manner.
 
 Lm-sensors
 ----------
 
-Core set of utilites that will allow you to obtain health information,
+Core set of utilities that will allow you to obtain health information,
 setup monitoring limits etc. You can get them on their homepage
 http://www.lm-sensors.nu/ or as a package from your Linux distribution.
 
 If from website:
-Get lmsensors from project web site. Please note, you need only userspace
-part, so compile with "make user_install" target.
+Get lm-sensors from project web site. Please note, you need only userspace
+part, so compile with "make user" and install with "make user_install".
 
 General hints to get things working:
 
 0) get lm-sensors userspace utils
-1) compile all drivers in I2C section as modules in your kernel
+1) compile all drivers in I2C and Hardware Monitoring sections as modules
+   in your kernel
 2) run sensors-detect script, it will tell you what modules you need to load.
 3) load them and run "sensors" command, you should see some results.
 4) fix sensors.conf, labels, limits, fan divisors
 5) if any more problems consult FAQ, or documentation
 
-Other utilites
---------------
+Other utilities
+---------------
 
 If you want some graphical indicators of system health look for applications
 like: gkrellm, ksensors, xsensors, wmtemp, wmsensors, wmgtemp, ksysguardd,
diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d
new file mode 100644
index 0000000..83a3836
--- /dev/null
+++ b/Documentation/hwmon/w83791d
@@ -0,0 +1,113 @@
+Kernel driver w83791d
+=====================
+
+Supported chips:
+  * Winbond W83791D
+    Prefix: 'w83791d'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf
+
+Author: Charles Spirakis <bezaur@gmail.com>
+
+This driver was derived from the w83781d.c and w83792d.c source files.
+
+Credits:
+  w83781d.c:
+    Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>,
+    and Mark Studebaker <mdsxyz123@yahoo.com>
+  w83792d.c:
+    Chunhao Huang <DZShen@Winbond.com.tw>,
+    Rudolf Marek <r.marek@sh.cvut.cz>
+
+Module Parameters
+-----------------
+
+* init boolean
+  (default 0)
+  Use 'init=1' to have the driver do extra software initializations.
+  The default behavior is to do the minimum initialization possible
+  and depend on the BIOS to properly setup the chip. If you know you
+  have a w83791d and you're having problems, try init=1 before trying
+  reset=1.
+
+* reset boolean
+  (default 0)
+  Use 'reset=1' to reset the chip (via index 0x40, bit 7). The default
+  behavior is no chip reset to preserve BIOS settings.
+
+* force_subclients=bus,caddr,saddr,saddr
+  This is used to force the i2c addresses for subclients of
+  a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
+  to force the subclients of chip 0x2f on bus 0 to i2c addresses
+  0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for the Winbond W83791D chip.
+
+Detection of the chip can sometimes be foiled because it can be in an
+internal state that allows no clean access (Bank with ID register is not
+currently selected). If you know the address of the chip, use a 'force'
+parameter; this will put it into a more well-behaved state first.
+
+The driver implements three temperature sensors, five fan rotation speed
+sensors, and ten voltage sensors.
+
+Temperatures are measured in degrees Celsius and measurement resolution is 1
+degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
+the temperature gets higher than the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3
+and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more
+range or accuracy.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+Alarms are provided as output from a "realtime status register". The
+following bits are defined:
+
+bit - alarm on:
+0  - Vcore
+1  - VINR0
+2  - +3.3VIN
+3  - 5VDD
+4  - temp1
+5  - temp2
+6  - fan1
+7  - fan2
+8  - +12VIN
+9  - -12VIN
+10 - -5VIN
+11 - fan3
+12 - chassis
+13 - temp3
+14 - VINR1
+15 - reserved
+16 - tart1
+17 - tart2
+18 - tart3
+19 - VSB
+20 - VBAT
+21 - fan4
+22 - fan5
+23 - reserved
+
+When an alarm goes off, you can be warned by a beeping signal through your
+computer speaker. It is possible to enable all beeping globally, or only
+the beeping for some alarms.
+
+The driver only reads the chip values each 3 seconds; reading them more
+often will do no harm, but will return 'old' values.
+
+W83791D TODO:
+---------------
+Provide a patch for per-file alarms as discussed on the mailing list
+Provide a patch for smart-fan control (still need appropriate motherboard/fans)
diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
index fd4b271..e46c234 100644
--- a/Documentation/i2c/busses/i2c-i801
+++ b/Documentation/i2c/busses/i2c-i801
@@ -21,8 +21,7 @@
 Module Parameters
 -----------------
 
-* force_addr: int
-  Forcibly enable the ICH at the given address. EXTREMELY DANGEROUS!
+None.
 
 
 Description
diff --git a/Documentation/i2c/busses/i2c-nforce2 b/Documentation/i2c/busses/i2c-nforce2
index d751282..cd49c42 100644
--- a/Documentation/i2c/busses/i2c-nforce2
+++ b/Documentation/i2c/busses/i2c-nforce2
@@ -7,6 +7,8 @@
   * nForce3 250Gb MCP          10de:00E4 
   * nForce4 MCP                10de:0052
   * nForce4 MCP-04             10de:0034
+  * nForce4 MCP51              10de:0264
+  * nForce4 MCP55              10de:0368
 
 Datasheet: not publically available, but seems to be similar to the
            AMD-8111 SMBus 2.0 adapter.
diff --git a/Documentation/i2c/busses/i2c-ocores b/Documentation/i2c/busses/i2c-ocores
new file mode 100644
index 0000000..cfcebb1
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-ocores
@@ -0,0 +1,51 @@
+Kernel driver i2c-ocores
+
+Supported adapters:
+  * OpenCores.org I2C controller by Richard Herveille (see datasheet link)
+    Datasheet: http://www.opencores.org/projects.cgi/web/i2c/overview
+
+Author: Peter Korsgaard <jacmet@sunsite.dk>
+
+Description
+-----------
+
+i2c-ocores is an i2c bus driver for the OpenCores.org I2C controller
+IP core by Richard Herveille.
+
+Usage
+-----
+
+i2c-ocores uses the platform bus, so you need to provide a struct
+platform_device with the base address and interrupt number. The
+dev.platform_data of the device should also point to a struct
+ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the
+distance between registers and the input clock speed.
+
+E.G. something like:
+
+static struct resource ocores_resources[] = {
+	[0] = {
+		.start	= MYI2C_BASEADDR,
+		.end	= MYI2C_BASEADDR + 8,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MYI2C_IRQ,
+		.end	= MYI2C_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct ocores_i2c_platform_data myi2c_data = {
+	.regstep	= 2,		/* two bytes between registers */
+	.clock_khz	= 50000,	/* input clock of 50MHz */
+};
+
+static struct platform_device myi2c = {
+	.name			= "ocores-i2c",
+	.dev = {
+		.platform_data	= &myi2c_data,
+	},
+	.num_resources		= ARRAY_SIZE(ocores_resources),
+	.resource		= ocores_resources,
+};
diff --git a/Documentation/i2c/busses/i2c-piix4 b/Documentation/i2c/busses/i2c-piix4
index a1c8f58..9214763 100644
--- a/Documentation/i2c/busses/i2c-piix4
+++ b/Documentation/i2c/busses/i2c-piix4
@@ -6,6 +6,8 @@
     Datasheet: Publicly available at the Intel website
   * ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
     Datasheet: Only available via NDA from ServerWorks
+  * ATI IXP southbridges IXP200, IXP300, IXP400
+    Datasheet: Not publicly available
   * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
     Datasheet: Publicly available at the SMSC website http://www.smsc.com
 
@@ -21,8 +23,6 @@
   Forcibly enable the PIIX4. DANGEROUS!
 * force_addr: int
   Forcibly enable the PIIX4 at the given address. EXTREMELY DANGEROUS!
-* fix_hstcfg: int
-  Fix config register. Needed on some boards (Force CPCI735).
 
 
 Description
@@ -63,10 +63,36 @@
 The PIIX/PIIX3 does not implement an SMBus or I2C bus, so you can't use
 this driver on those mainboards.
 
-The ServerWorks Southbridges, the Intel 440MX, and the Victory766 are
+The ServerWorks Southbridges, the Intel 440MX, and the Victory66 are
 identical to the PIIX4 in I2C/SMBus support.
 
-A few OSB4 southbridges are known to be misconfigured by the BIOS. In this
-case, you have you use the fix_hstcfg module parameter. Do not use it
-unless you know you have to, because in some cases it also breaks
-configuration on southbridges that don't need it.
+If you own Force CPCI735 motherboard or other OSB4 based systems you may need
+to change the SMBus Interrupt Select register so the SMBus controller uses
+the SMI mode.
+
+1) Use lspci command and locate the PCI device with the SMBus controller:
+   00:0f.0 ISA bridge: ServerWorks OSB4 South Bridge (rev 4f)
+   The line may vary for different chipsets. Please consult the driver source
+   for all possible PCI ids (and lspci -n to match them). Lets assume the
+   device is located at 00:0f.0.
+2) Now you just need to change the value in 0xD2 register. Get it first with
+   command: lspci -xxx -s 00:0f.0
+   If the value is 0x3 then you need to change it to 0x1
+   setpci  -s 00:0f.0 d2.b=1
+
+Please note that you don't need to do that in all cases, just when the SMBus is
+not working properly.
+
+
+Hardware-specific issues
+------------------------
+
+This driver will refuse to load on IBM systems with an Intel PIIX4 SMBus.
+Some of these machines have an RFID EEPROM (24RF08) connected to the SMBus,
+which can easily get corrupted due to a state machine bug. These are mostly
+Thinkpad laptops, but desktop systems may also be affected. We have no list
+of all affected systems, so the only safe solution was to prevent access to
+the SMBus on all IBM systems (detected using DMI data.)
+
+For additional information, read:
+http://www2.lm-sensors.nu/~lm78/cvs/lm_sensors2/README.thinkpad
diff --git a/Documentation/i2c/busses/scx200_acb b/Documentation/i2c/busses/scx200_acb
index f50e699..7c07883d 100644
--- a/Documentation/i2c/busses/scx200_acb
+++ b/Documentation/i2c/busses/scx200_acb
@@ -2,14 +2,31 @@
 
 Author: Christer Weinigel <wingel@nano-system.com>
 
+The driver supersedes the older, never merged driver named i2c-nscacb.
+
 Module Parameters
 -----------------
 
-* base: int
+* base: up to 4 ints
   Base addresses for the ACCESS.bus controllers on SCx200 and SC1100 devices
 
+  By default the driver uses two base addresses 0x820 and 0x840.
+  If you want only one base address, specify the second as 0 so as to
+  override this default.
+
 Description
 -----------
 
 Enable the use of the ACCESS.bus controller on the Geode SCx200 and
 SC1100 processors and the CS5535 and CS5536 Geode companion devices.
+
+Device-specific notes
+---------------------
+
+The SC1100 WRAP boards are known to use base addresses 0x810 and 0x820.
+If the scx200_acb driver is built into the kernel, add the following
+parameter to your boot command line:
+  scx200_acb.base=0x810,0x820
+If the scx200_acb driver is built as a module, add the following line to
+the file /etc/modprobe.conf instead:
+  options scx200_acb base=0x810,0x820
diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt
new file mode 100644
index 0000000..38f9a52
--- /dev/null
+++ b/Documentation/ia64/aliasing.txt
@@ -0,0 +1,208 @@
+	         MEMORY ATTRIBUTE ALIASING ON IA-64
+
+			   Bjorn Helgaas
+		       <bjorn.helgaas@hp.com>
+			    May 4, 2006
+
+
+MEMORY ATTRIBUTES
+
+    Itanium supports several attributes for virtual memory references.
+    The attribute is part of the virtual translation, i.e., it is
+    contained in the TLB entry.  The ones of most interest to the Linux
+    kernel are:
+
+	WB		Write-back (cacheable)
+	UC		Uncacheable
+	WC		Write-coalescing
+
+    System memory typically uses the WB attribute.  The UC attribute is
+    used for memory-mapped I/O devices.  The WC attribute is uncacheable
+    like UC is, but writes may be delayed and combined to increase
+    performance for things like frame buffers.
+
+    The Itanium architecture requires that we avoid accessing the same
+    page with both a cacheable mapping and an uncacheable mapping[1].
+
+    The design of the chipset determines which attributes are supported
+    on which regions of the address space.  For example, some chipsets
+    support either WB or UC access to main memory, while others support
+    only WB access.
+
+MEMORY MAP
+
+    Platform firmware describes the physical memory map and the
+    supported attributes for each region.  At boot-time, the kernel uses
+    the EFI GetMemoryMap() interface.  ACPI can also describe memory
+    devices and the attributes they support, but Linux/ia64 currently
+    doesn't use this information.
+
+    The kernel uses the efi_memmap table returned from GetMemoryMap() to
+    learn the attributes supported by each region of physical address
+    space.  Unfortunately, this table does not completely describe the
+    address space because some machines omit some or all of the MMIO
+    regions from the map.
+
+    The kernel maintains another table, kern_memmap, which describes the
+    memory Linux is actually using and the attribute for each region.
+    This contains only system memory; it does not contain MMIO space.
+
+    The kern_memmap table typically contains only a subset of the system
+    memory described by the efi_memmap.  Linux/ia64 can't use all memory
+    in the system because of constraints imposed by the identity mapping
+    scheme.
+
+    The efi_memmap table is preserved unmodified because the original
+    boot-time information is required for kexec.
+
+KERNEL IDENTITY MAPPINGS
+
+    Linux/ia64 identity mappings are done with large pages, currently
+    either 16MB or 64MB, referred to as "granules."  Cacheable mappings
+    are speculative[2], so the processor can read any location in the
+    page at any time, independent of the programmer's intentions.  This
+    means that to avoid attribute aliasing, Linux can create a cacheable
+    identity mapping only when the entire granule supports cacheable
+    access.
+
+    Therefore, kern_memmap contains only full granule-sized regions that
+    can referenced safely by an identity mapping.
+
+    Uncacheable mappings are not speculative, so the processor will
+    generate UC accesses only to locations explicitly referenced by
+    software.  This allows UC identity mappings to cover granules that
+    are only partially populated, or populated with a combination of UC
+    and WB regions.
+
+USER MAPPINGS
+
+    User mappings are typically done with 16K or 64K pages.  The smaller
+    page size allows more flexibility because only 16K or 64K has to be
+    homogeneous with respect to memory attributes.
+
+POTENTIAL ATTRIBUTE ALIASING CASES
+
+    There are several ways the kernel creates new mappings:
+
+    mmap of /dev/mem
+
+	This uses remap_pfn_range(), which creates user mappings.  These
+	mappings may be either WB or UC.  If the region being mapped
+	happens to be in kern_memmap, meaning that it may also be mapped
+	by a kernel identity mapping, the user mapping must use the same
+	attribute as the kernel mapping.
+
+	If the region is not in kern_memmap, the user mapping should use
+	an attribute reported as being supported in the EFI memory map.
+
+	Since the EFI memory map does not describe MMIO on some
+	machines, this should use an uncacheable mapping as a fallback.
+
+    mmap of /sys/class/pci_bus/.../legacy_mem
+
+	This is very similar to mmap of /dev/mem, except that legacy_mem
+	only allows mmap of the one megabyte "legacy MMIO" area for a
+	specific PCI bus.  Typically this is the first megabyte of
+	physical address space, but it may be different on machines with
+	several VGA devices.
+
+	"X" uses this to access VGA frame buffers.  Using legacy_mem
+	rather than /dev/mem allows multiple instances of X to talk to
+	different VGA cards.
+
+	The /dev/mem mmap constraints apply.
+
+	However, since this is for mapping legacy MMIO space, WB access
+	does not make sense.  This matters on machines without legacy
+	VGA support: these machines may have WB memory for the entire
+	first megabyte (or even the entire first granule).
+
+	On these machines, we could mmap legacy_mem as WB, which would
+	be safe in terms of attribute aliasing, but X has no way of
+	knowing that it is accessing regular memory, not a frame buffer,
+	so the kernel should fail the mmap rather than doing it with WB.
+
+    read/write of /dev/mem
+
+	This uses copy_from_user(), which implicitly uses a kernel
+	identity mapping.  This is obviously safe for things in
+	kern_memmap.
+
+	There may be corner cases of things that are not in kern_memmap,
+	but could be accessed this way.  For example, registers in MMIO
+	space are not in kern_memmap, but could be accessed with a UC
+	mapping.  This would not cause attribute aliasing.  But
+	registers typically can be accessed only with four-byte or
+	eight-byte accesses, and the copy_from_user() path doesn't allow
+	any control over the access size, so this would be dangerous.
+
+    ioremap()
+
+	This returns a kernel identity mapping for use inside the
+	kernel.
+
+	If the region is in kern_memmap, we should use the attribute
+	specified there.  Otherwise, if the EFI memory map reports that
+	the entire granule supports WB, we should use that (granules
+	that are partially reserved or occupied by firmware do not appear
+	in kern_memmap).  Otherwise, we should use a UC mapping.
+
+PAST PROBLEM CASES
+
+    mmap of various MMIO regions from /dev/mem by "X" on Intel platforms
+
+      The EFI memory map may not report these MMIO regions.
+
+      These must be allowed so that X will work.  This means that
+      when the EFI memory map is incomplete, every /dev/mem mmap must
+      succeed.  It may create either WB or UC user mappings, depending
+      on whether the region is in kern_memmap or the EFI memory map.
+
+    mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled
+
+      See https://bugzilla.novell.com/show_bug.cgi?id=140858.
+
+      The EFI memory map reports the following attributes:
+        0x00000-0x9FFFF WB only
+        0xA0000-0xBFFFF UC only (VGA frame buffer)
+        0xC0000-0xFFFFF WB only
+
+      This mmap is done with user pages, not kernel identity mappings,
+      so it is safe to use WB mappings.
+
+      The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000,
+      which will use a granule-sized UC mapping covering 0-0xFFFFF.  This
+      granule covers some WB-only memory, but since UC is non-speculative,
+      the processor will never generate an uncacheable reference to the
+      WB-only areas unless the driver explicitly touches them.
+
+    mmap of 0x0-0xFFFFF legacy_mem by "X"
+
+      If the EFI memory map reports this entire range as WB, there
+      is no VGA MMIO hole, and the mmap should fail or be done with
+      a WB mapping.
+
+      There's no easy way for X to determine whether the 0xA0000-0xBFFFF
+      region is a frame buffer or just memory, so I think it's best to
+      just fail this mmap request rather than using a WB mapping.  As
+      far as I know, there's no need to map legacy_mem with WB
+      mappings.
+
+      Otherwise, a UC mapping of the entire region is probably safe.
+      The VGA hole means the region will not be in kern_memmap.  The
+      HP sx1000 chipset doesn't support UC access to the memory surrounding
+      the VGA hole, but X doesn't need that area anyway and should not
+      reference it.
+
+    mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled
+
+      The EFI memory map reports the following attributes:
+        0x00000-0xFFFFF WB only (no VGA MMIO hole)
+
+      This is a special case of the previous case, and the mmap should
+      fail for the same reason as above.
+
+NOTES
+
+    [1] SDM rev 2.2, vol 2, sec 4.4.1.
+    [2] SDM rev 2.2, vol 2, sec 4.4.6.
diff --git a/Documentation/infiniband/ipoib.txt b/Documentation/infiniband/ipoib.txt
index 5c5a4cc..1870355 100644
--- a/Documentation/infiniband/ipoib.txt
+++ b/Documentation/infiniband/ipoib.txt
@@ -1,10 +1,10 @@
 IP OVER INFINIBAND
 
   The ib_ipoib driver is an implementation of the IP over InfiniBand
-  protocol as specified by the latest Internet-Drafts issued by the
-  IETF ipoib working group.  It is a "native" implementation in the
-  sense of setting the interface type to ARPHRD_INFINIBAND and the
-  hardware address length to 20 (earlier proprietary implementations
+  protocol as specified by RFC 4391 and 4392, issued by the IETF ipoib
+  working group.  It is a "native" implementation in the sense of
+  setting the interface type to ARPHRD_INFINIBAND and the hardware
+  address length to 20 (earlier proprietary implementations
   masqueraded to the kernel as ethernet interfaces).
 
 Partitions and P_Keys
@@ -53,3 +53,7 @@
 
   IETF IP over InfiniBand (ipoib) Working Group
     http://ietf.org/html.charters/ipoib-charter.html
+  Transmission of IP over InfiniBand (IPoIB) (RFC 4391)
+    http://ietf.org/rfc/rfc4391.txt 
+  IP over InfiniBand (IPoIB) Architecture (RFC 4392)
+    http://ietf.org/rfc/rfc4392.txt 
diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
index 171a44e..1543802 100644
--- a/Documentation/ioctl-number.txt
+++ b/Documentation/ioctl-number.txt
@@ -85,7 +85,9 @@
 					<mailto:maassen@uni-freiburg.de>
 'C'	all	linux/soundcard.h
 'D'	all	asm-s390/dasd.h
+'E'	all	linux/input.h
 'F'	all	linux/fb.h
+'H'	all	linux/hiddev.h
 'I'	all	linux/isdn.h
 'J'	00-1F	drivers/scsi/gdth_ioctl.h
 'K'	all	linux/kd.h
diff --git a/Documentation/isdn/README.gigaset b/Documentation/isdn/README.gigaset
index 85a64de..fa0d4cc 100644
--- a/Documentation/isdn/README.gigaset
+++ b/Documentation/isdn/README.gigaset
@@ -124,7 +124,8 @@
 
      You can use some configuration tool of your distribution to configure this
      "modem" or configure pppd/wvdial manually. There are some example ppp
-     configuration files and chat scripts in the gigaset-VERSION/ppp directory.
+     configuration files and chat scripts in the gigaset-VERSION/ppp directory
+     in the driver packages from http://sourceforge.net/projects/gigaset307x/.
      Please note that the USB drivers are not able to change the state of the
      control lines (the M105 driver can be configured to use some undocumented
      control requests, if you really need the control lines, though). This means
@@ -164,8 +165,8 @@
 
      If you want both of these at once, you are out of luck.
 
-     You can also use /sys/module/<name>/parameters/cidmode for changing
-     the CID mode setting (<name> is usb_gigaset or bas_gigaset).
+     You can also use /sys/class/tty/ttyGxy/cidmode for changing the CID mode
+     setting (ttyGxy is ttyGU0 or ttyGB0).
 
 
 3.   Troubleshooting
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index a9c00fa..14ef3868 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1123,6 +1123,14 @@
 	$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE).  The user may
 	override this value on the command line if desired.
 
+    INSTALL_MOD_STRIP
+
+	If this variable is specified, will cause modules to be stripped
+	after they are installed.  If INSTALL_MOD_STRIP is '1', then the
+	default option --strip-debug will be used.  Otherwise,
+	INSTALL_MOD_STRIP will used as the option(s) to the strip command.
+
+
 === 8 Makefile language
 
 The kernel Makefiles are designed to run with GNU Make.  The Makefiles
diff --git a/Documentation/kdump/gdbmacros.txt b/Documentation/kdump/gdbmacros.txt
index dcf5580..9b9b454 100644
--- a/Documentation/kdump/gdbmacros.txt
+++ b/Documentation/kdump/gdbmacros.txt
@@ -175,7 +175,7 @@
 document trapinfo
 	Run info threads and lookup pid of thread #1
 	'trapinfo <pid>' will tell you by which trap & possibly
-	addresthe kernel paniced.
+	address the kernel panicked.
 end
 
 
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 212cf3c..08bafa8 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -1,155 +1,325 @@
-Documentation for kdump - the kexec-based crash dumping solution
+================================================================
+Documentation for Kdump - The kexec-based Crash Dumping Solution
 ================================================================
 
-DESIGN
-======
+This document includes overview, setup and installation, and analysis
+information.
 
-Kdump uses kexec to reboot to a second kernel whenever a dump needs to be
-taken. This second kernel is booted with very little memory. The first kernel
-reserves the section of memory that the second kernel uses. This ensures that
-on-going DMA from the first kernel does not corrupt the second kernel.
+Overview
+========
 
-All the necessary information about Core image is encoded in ELF format and
-stored in reserved area of memory before crash. Physical address of start of
-ELF header is passed to new kernel through command line parameter elfcorehdr=.
+Kdump uses kexec to quickly boot to a dump-capture kernel whenever a
+dump of the system kernel's memory needs to be taken (for example, when
+the system panics). The system kernel's memory image is preserved across
+the reboot and is accessible to the dump-capture kernel.
 
-On i386, the first 640 KB of physical memory is needed to boot, irrespective
-of where the kernel loads. Hence, this region is backed up by kexec just before
-rebooting into the new kernel.
+You can use common Linux commands, such as cp and scp, to copy the
+memory image to a dump file on the local disk, or across the network to
+a remote system.
 
-In the second kernel, "old memory" can be accessed in two ways.
+Kdump and kexec are currently supported on the x86, x86_64, and ppc64
+architectures.
 
-- The first one is through a /dev/oldmem device interface. A capture utility
-  can read the device file and write out the memory in raw format. This is raw
-  dump of memory and analysis/capture tool should be intelligent enough to
-  determine where to look for the right information. ELF headers (elfcorehdr=)
-  can become handy here.
+When the system kernel boots, it reserves a small section of memory for
+the dump-capture kernel. This ensures that ongoing Direct Memory Access
+(DMA) from the system kernel does not corrupt the dump-capture kernel.
+The kexec -p command loads the dump-capture kernel into this reserved
+memory.
 
-- The second interface is through /proc/vmcore. This exports the dump as an ELF
-  format file which can be written out using any file copy command
-  (cp, scp, etc). Further, gdb can be used to perform limited debugging on
-  the dump file. This method ensures methods ensure that there is correct
-  ordering of the dump pages (corresponding to the first 640 KB that has been
-  relocated).
+On x86 machines, the first 640 KB of physical memory is needed to boot,
+regardless of where the kernel loads. Therefore, kexec backs up this
+region just before rebooting into the dump-capture kernel.
 
-SETUP
-=====
+All of the necessary information about the system kernel's core image is
+encoded in the ELF format, and stored in a reserved area of memory
+before a crash. The physical address of the start of the ELF header is
+passed to the dump-capture kernel through the elfcorehdr= boot
+parameter.
 
-1) Download the upstream kexec-tools userspace package from
-   http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz.
+With the dump-capture kernel, you can access the memory image, or "old
+memory," in two ways:
 
-   Apply the latest consolidated kdump patch on top of kexec-tools-1.101
-   from http://lse.sourceforge.net/kdump/. This arrangment has been made
-   till all the userspace patches supporting kdump are integrated with
-   upstream kexec-tools userspace.
+- Through a /dev/oldmem device interface. A capture utility can read the
+  device file and write out the memory in raw format. This is a raw dump
+  of memory. Analysis and capture tools must be intelligent enough to
+  determine where to look for the right information.
 
-2) Download and build the appropriate (2.6.13-rc1 onwards) vanilla kernels.
-   Two kernels need to be built in order to get this feature working.
-   Following are the steps to properly configure the two kernels specific
-   to kexec and kdump features:
-
-  A) First kernel or regular kernel:
-  ----------------------------------
-   a) Enable "kexec system call" feature (in Processor type and features).
-      CONFIG_KEXEC=y
-   b) Enable "sysfs file system support" (in Pseudo filesystems).
-      CONFIG_SYSFS=y
-   c) make
-   d) Boot into first kernel with the command line parameter "crashkernel=Y@X".
-      Use appropriate values for X and Y. Y denotes how much memory to reserve
-      for the second kernel, and X denotes at what physical address the
-      reserved memory section starts. For example: "crashkernel=64M@16M".
+- Through /proc/vmcore. This exports the dump as an ELF-format file that
+  you can write out using file copy commands such as cp or scp. Further,
+  you can use analysis tools such as the GNU Debugger (GDB) and the Crash
+  tool to debug the dump file. This method ensures that the dump pages are
+  correctly ordered.
 
 
-  B) Second kernel or dump capture kernel:
-  ---------------------------------------
-   a) For i386 architecture enable Highmem support
-      CONFIG_HIGHMEM=y
-   b) Enable "kernel crash dumps" feature (under "Processor type and features")
-      CONFIG_CRASH_DUMP=y
-   c) Make sure a suitable value for "Physical address where the kernel is
-      loaded" (under "Processor type and features"). By default this value
-      is 0x1000000 (16MB) and it should be same as X (See option d above),
-      e.g., 16 MB or 0x1000000.
-      CONFIG_PHYSICAL_START=0x1000000
-   d) Enable "/proc/vmcore support" (Optional, under "Pseudo filesystems").
-      CONFIG_PROC_VMCORE=y
+Setup and Installation
+======================
 
-3) After booting to regular kernel or first kernel, load the second kernel
-   using the following command:
+Install kexec-tools and the Kdump patch
+---------------------------------------
 
-   kexec -p <second-kernel> --args-linux --elf32-core-headers
-   --append="root=<root-dev> init 1 irqpoll maxcpus=1"
+1) Login as the root user.
 
-   Notes:
-   ======
-     i) <second-kernel> has to be a vmlinux image ie uncompressed elf image.
-        bzImage will not work, as of now.
-    ii) --args-linux has to be speicfied as if kexec it loading an elf image,
-        it needs to know that the arguments supplied are of linux type.
-   iii) By default ELF headers are stored in ELF64 format to support systems
-        with more than 4GB memory. Option --elf32-core-headers forces generation
-        of ELF32 headers. The reason for this option being, as of now gdb can
-        not open vmcore file with ELF64 headers on a 32 bit systems. So ELF32
-        headers can be used if one has non-PAE systems and hence memory less
-        than 4GB.
-    iv) Specify "irqpoll" as command line parameter. This reduces driver
-         initialization failures in second kernel due to shared interrupts.
-     v) <root-dev> needs to be specified in a format corresponding to the root
-        device name in the output of mount command.
-    vi) If you have built the drivers required to mount root file system as
-        modules in <second-kernel>, then, specify
-        --initrd=<initrd-for-second-kernel>.
-   vii) Specify maxcpus=1 as, if during first kernel run, if panic happens on
-        non-boot cpus, second kernel doesn't seem to be boot up all the cpus.
-        The other option is to always built the second kernel without SMP
-        support ie CONFIG_SMP=n
+2) Download the kexec-tools user-space package from the following URL:
 
-4) After successfully loading the second kernel as above, if a panic occurs
-   system reboots into the second kernel. A module can be written to force
-   the panic or "ALT-SysRq-c" can be used initiate a crash dump for testing
-   purposes.
+   http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
 
-5) Once the second kernel has booted, write out the dump file using
+3) Unpack the tarball with the tar command, as follows:
+
+   tar xvpzf kexec-tools-1.101.tar.gz
+
+4) Download the latest consolidated Kdump patch from the following URL:
+
+   http://lse.sourceforge.net/kdump/
+
+   (This location is being used until all the user-space Kdump patches
+   are integrated with the kexec-tools package.)
+
+5) Change to the kexec-tools-1.101 directory, as follows:
+
+   cd kexec-tools-1.101
+
+6) Apply the consolidated patch to the kexec-tools-1.101 source tree
+   with the patch command, as follows. (Modify the path to the downloaded
+   patch as necessary.)
+
+   patch -p1 < /path-to-kdump-patch/kexec-tools-1.101-kdump.patch
+
+7) Configure the package, as follows:
+
+   ./configure
+
+8) Compile the package, as follows:
+
+   make
+
+9) Install the package, as follows:
+
+   make install
+
+
+Download and build the system and dump-capture kernels
+------------------------------------------------------
+
+Download the mainline (vanilla) kernel source code (2.6.13-rc1 or newer)
+from http://www.kernel.org. Two kernels must be built: a system kernel
+and a dump-capture kernel. Use the following steps to configure these
+kernels with the necessary kexec and Kdump features:
+
+System kernel
+-------------
+
+1) Enable "kexec system call" in "Processor type and features."
+
+   CONFIG_KEXEC=y
+
+2) Enable "sysfs file system support" in "Filesystem" -> "Pseudo
+   filesystems." This is usually enabled by default.
+
+   CONFIG_SYSFS=y
+
+   Note that "sysfs file system support" might not appear in the "Pseudo
+   filesystems" menu if "Configure standard kernel features (for small
+   systems)" is not enabled in "General Setup." In this case, check the
+   .config file itself to ensure that sysfs is turned on, as follows:
+
+   grep 'CONFIG_SYSFS' .config
+
+3) Enable "Compile the kernel with debug info" in "Kernel hacking."
+
+   CONFIG_DEBUG_INFO=Y
+
+   This causes the kernel to be built with debug symbols. The dump
+   analysis tools require a vmlinux with debug symbols in order to read
+   and analyze a dump file.
+
+4) Make and install the kernel and its modules. Update the boot loader
+   (such as grub, yaboot, or lilo) configuration files as necessary.
+
+5) Boot the system kernel with the boot parameter "crashkernel=Y@X",
+   where Y specifies how much memory to reserve for the dump-capture kernel
+   and X specifies the beginning of this reserved memory. For example,
+   "crashkernel=64M@16M" tells the system kernel to reserve 64 MB of memory
+   starting at physical address 0x01000000 for the dump-capture kernel.
+
+   On x86 and x86_64, use "crashkernel=64M@16M".
+
+   On ppc64, use "crashkernel=128M@32M".
+
+
+The dump-capture kernel
+-----------------------
+
+1) Under "General setup," append "-kdump" to the current string in
+   "Local version."
+
+2) On x86, enable high memory support under "Processor type and
+   features":
+
+   CONFIG_HIGHMEM64G=y
+   or
+   CONFIG_HIGHMEM4G
+
+3) On x86 and x86_64, disable symmetric multi-processing support
+   under "Processor type and features":
+
+   CONFIG_SMP=n
+   (If CONFIG_SMP=y, then specify maxcpus=1 on the kernel command line
+   when loading the dump-capture kernel, see section "Load the Dump-capture
+   Kernel".)
+
+4) On ppc64, disable NUMA support and enable EMBEDDED support:
+
+   CONFIG_NUMA=n
+   CONFIG_EMBEDDED=y
+   CONFIG_EEH=N for the dump-capture kernel
+
+5) Enable "kernel crash dumps" support under "Processor type and
+   features":
+
+   CONFIG_CRASH_DUMP=y
+
+6) Use a suitable value for "Physical address where the kernel is
+   loaded" (under "Processor type and features"). This only appears when
+   "kernel crash dumps" is enabled. By default this value is 0x1000000
+   (16MB). It should be the same as X in the "crashkernel=Y@X" boot
+   parameter discussed above.
+
+   On x86 and x86_64, use "CONFIG_PHYSICAL_START=0x1000000".
+
+   On ppc64 the value is automatically set at 32MB when
+   CONFIG_CRASH_DUMP is set.
+
+6) Optionally enable "/proc/vmcore support" under "Filesystems" ->
+   "Pseudo filesystems".
+
+   CONFIG_PROC_VMCORE=y
+   (CONFIG_PROC_VMCORE is set by default when CONFIG_CRASH_DUMP is selected.)
+
+7) Make and install the kernel and its modules. DO NOT add this kernel
+   to the boot loader configuration files.
+
+
+Load the Dump-capture Kernel
+============================
+
+After booting to the system kernel, load the dump-capture kernel using
+the following command:
+
+   kexec -p <dump-capture-kernel> \
+   --initrd=<initrd-for-dump-capture-kernel> --args-linux \
+   --append="root=<root-dev> init 1 irqpoll"
+
+
+Notes on loading the dump-capture kernel:
+
+* <dump-capture-kernel> must be a vmlinux image (that is, an
+  uncompressed ELF image). bzImage does not work at this time.
+
+* By default, the ELF headers are stored in ELF64 format to support
+  systems with more than 4GB memory. The --elf32-core-headers option can
+  be used to force the generation of ELF32 headers. This is necessary
+  because GDB currently cannot open vmcore files with ELF64 headers on
+  32-bit systems. ELF32 headers can be used on non-PAE systems (that is,
+  less than 4GB of memory).
+
+* The "irqpoll" boot parameter reduces driver initialization failures
+  due to shared interrupts in the dump-capture kernel.
+
+* You must specify <root-dev> in the format corresponding to the root
+  device name in the output of mount command.
+
+* "init 1" boots the dump-capture kernel into single-user mode without
+  networking. If you want networking, use "init 3."
+
+
+Kernel Panic
+============
+
+After successfully loading the dump-capture kernel as previously
+described, the system will reboot into the dump-capture kernel if a
+system crash is triggered.  Trigger points are located in panic(),
+die(), die_nmi() and in the sysrq handler (ALT-SysRq-c).
+
+The following conditions will execute a crash trigger point:
+
+If a hard lockup is detected and "NMI watchdog" is configured, the system
+will boot into the dump-capture kernel ( die_nmi() ).
+
+If die() is called, and it happens to be a thread with pid 0 or 1, or die()
+is called inside interrupt context or die() is called and panic_on_oops is set,
+the system will boot into the dump-capture kernel.
+
+On powererpc systems when a soft-reset is generated, die() is called by all cpus and the system system will boot into the dump-capture kernel.
+
+For testing purposes, you can trigger a crash by using "ALT-SysRq-c",
+"echo c > /proc/sysrq-trigger or write a module to force the panic.
+
+Write Out the Dump File
+=======================
+
+After the dump-capture kernel is booted, write out the dump file with
+the following command:
 
    cp /proc/vmcore <dump-file>
 
-   Dump memory can also be accessed as a /dev/oldmem device for a linear/raw
-   view.  To create the device, type:
+You can also access dumped memory as a /dev/oldmem device for a linear
+and raw view. To create the device, use the following command:
 
-   mknod /dev/oldmem c 1 12
+    mknod /dev/oldmem c 1 12
 
-   Use "dd" with suitable options for count, bs and skip to access specific
-   portions of the dump.
+Use the dd command with suitable options for count, bs, and skip to
+access specific portions of the dump.
 
-   Entire memory:  dd if=/dev/oldmem of=oldmem.001
+To see the entire memory, use the following command:
+
+   dd if=/dev/oldmem of=oldmem.001
 
 
-ANALYSIS
+Analysis
 ========
-Limited analysis can be done using gdb on the dump file copied out of
-/proc/vmcore. Use vmlinux built with -g and run
 
-  gdb vmlinux <dump-file>
+Before analyzing the dump image, you should reboot into a stable kernel.
 
-Stack trace for the task on processor 0, register display, memory display
-work fine.
+You can do limited analysis using GDB on the dump file copied out of
+/proc/vmcore. Use the debug vmlinux built with -g and run the following
+command:
 
-Note: gdb cannot analyse core files generated in ELF64 format for i386.
+   gdb vmlinux <dump-file>
 
-Latest "crash" (crash-4.0-2.18) as available on Dave Anderson's site
-http://people.redhat.com/~anderson/ works well with kdump format.
+Stack trace for the task on processor 0, register display, and memory
+display work fine.
+
+Note: GDB cannot analyze core files generated in ELF64 format for x86.
+On systems with a maximum of 4GB of memory, you can generate
+ELF32-format headers using the --elf32-core-headers kernel option on the
+dump kernel.
+
+You can also use the Crash utility to analyze dump files in Kdump
+format. Crash is available on Dave Anderson's site at the following URL:
+
+   http://people.redhat.com/~anderson/
 
 
-TODO
-====
-1) Provide a kernel pages filtering mechanism so that core file size is not
-   insane on systems having huge memory banks.
-2) Relocatable kernel can help in maintaining multiple kernels for crashdump
-   and same kernel as the first kernel can be used to capture the dump.
+To Do
+=====
+
+1) Provide a kernel pages filtering mechanism, so core file size is not
+   extreme on systems with huge memory banks.
+
+2) Relocatable kernel can help in maintaining multiple kernels for
+   crash_dump, and the same kernel as the system kernel can be used to
+   capture the dump.
 
 
-CONTACT
+Contact
 =======
+
 Vivek Goyal (vgoyal@in.ibm.com)
 Maneesh Soni (maneesh@in.ibm.com)
+
+
+Trademark
+=========
+
+Linux is a trademark of Linus Torvalds in the United States, other
+countries, or both.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b3a6187..0d189c9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -61,6 +61,7 @@
 	MTD	MTD support is enabled.
 	NET	Appropriate network support is enabled.
 	NUMA	NUMA support is enabled.
+	GENERIC_TIME The generic timeofday code is enabled.
 	NFS	Appropriate NFS support is enabled.
 	OSS	OSS sound support is enabled.
 	PARIDE	The ParIDE subsystem is enabled.
@@ -147,6 +148,9 @@
 	acpi_irq_isa=	[HW,ACPI] If irq_balance, mark listed IRQs used by ISA
 			Format: <irq>,<irq>...
 
+	acpi_os_name=	[HW,ACPI] Tell ACPI BIOS the name of the OS
+			Format: To spoof as Windows 98: ="Microsoft Windows"
+
 	acpi_osi=	[HW,ACPI] empty param disables _OSI
 
 	acpi_serialize	[HW,ACPI] force serialization of AML methods
@@ -176,6 +180,11 @@
 			override platform specific driver.
 			See also Documentation/acpi-hotkey.txt.
 
+	acpi_pm_good	[IA-32,X86-64]
+			Override the pmtimer bug detection: force the kernel
+			to assume that this machine's pmtimer latches its value
+			and always returns good values.
+
 	enable_timer_pin_1 [i386,x86-64]
 			Enable PIN 1 of APIC timer
 			Can be useful to work around chipset bugs
@@ -338,10 +347,11 @@
 			Value can be changed at runtime via
 				/selinux/checkreqprot.
 
- 	clock=		[BUGS=IA-32,HW] gettimeofday timesource override.
-			Forces specified timesource (if avaliable) to be used
-			when calculating gettimeofday(). If specicified
-			timesource is not avalible, it defaults to PIT.
+	clock=		[BUGS=IA-32, HW] gettimeofday clocksource override.
+			[Deprecated]
+			Forces specified clocksource (if avaliable) to be used
+			when calculating gettimeofday(). If specified
+			clocksource is not avalible, it defaults to PIT.
 			Format: { pit | tsc | cyclone | pmtmr }
 
 	disable_8254_timer
@@ -1402,6 +1412,15 @@
 			If enabled at boot time, /selinux/disable can be used
 			later to disable prior to initial policy load.
 
+	selinux_compat_net =
+			[SELINUX] Set initial selinux_compat_net flag value.
+                        Format: { "0" | "1" }
+                        0 -- use new secmark-based packet controls
+                        1 -- use legacy packet controls
+                        Default value is 0 (preferred).
+                        Value can be changed at runtime via
+                        /selinux/compat_net.
+
 	serialnumber	[BUGS=IA-32]
 
 	sg_def_reserved_size=	[SCSI]
@@ -1605,6 +1624,10 @@
 
 	time		Show timing data prefixed to each printk message line
 
+	clocksource=	[GENERIC_TIME] Override the default clocksource
+			Override the default clocksource and use the clocksource
+			with the name specified.
+
 	tipar.timeout=	[HW,PPT]
 			Set communications timeout in tenths of a second
 			(default 15).
@@ -1646,6 +1669,10 @@
 	usbhid.mousepoll=
 			[USBHID] The interval which mice are to be polled at.
 
+	vdso=		[IA-32]
+			vdso=1: enable VDSO (default)
+			vdso=0: disable VDSO mapping
+
 	video=		[FB] Frame buffer configuration
 			See Documentation/fb/modedb.txt.
 
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index aaa01b0..61c0fad 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -19,6 +19,7 @@
 	- Key overview
 	- Key service overview
 	- Key access permissions
+	- SELinux support
 	- New procfs files
 	- Userspace system call interface
 	- Kernel services
@@ -232,6 +233,39 @@
 the key or having the sysadmin capability is sufficient.
 
 
+===============
+SELINUX SUPPORT
+===============
+
+The security class "key" has been added to SELinux so that mandatory access
+controls can be applied to keys created within various contexts.  This support
+is preliminary, and is likely to change quite significantly in the near future.
+Currently, all of the basic permissions explained above are provided in SELinux
+as well; SELinux is simply invoked after all basic permission checks have been
+performed.
+
+The value of the file /proc/self/attr/keycreate influences the labeling of
+newly-created keys.  If the contents of that file correspond to an SELinux
+security context, then the key will be assigned that context.  Otherwise, the
+key will be assigned the current context of the task that invoked the key
+creation request.  Tasks must be granted explicit permission to assign a
+particular context to newly-created keys, using the "create" permission in the
+key security class.
+
+The default keyrings associated with users will be labeled with the default
+context of the user if and only if the login programs have been instrumented to
+properly initialize keycreate during the login process.  Otherwise, they will
+be labeled with the context of the login program itself.
+
+Note, however, that the default keyrings associated with the root user are
+labeled with the default kernel context, since they are created early in the
+boot process, before root has a chance to log in.
+
+The keyrings associated with new threads are each labeled with the context of
+their associated thread, and both session and process keyrings are handled
+similarly.
+
+
 ================
 NEW PROCFS FILES
 ================
@@ -241,9 +275,17 @@
 
  (*) /proc/keys
 
-     This lists all the keys on the system, giving information about their
-     type, description and permissions. The payload of the key is not available
-     this way:
+     This lists the keys that are currently viewable by the task reading the
+     file, giving information about their type, description and permissions.
+     It is not possible to view the payload of the key this way, though some
+     information about it may be given.
+
+     The only keys included in the list are those that grant View permission to
+     the reading process whether or not it possesses them.  Note that LSM
+     security checks are still performed, and may further filter out keys that
+     the current process is not authorised to view.
+
+     The contents of the file look like this:
 
 	SERIAL   FLAGS  USAGE EXPY PERM     UID   GID   TYPE      DESCRIPTION: SUMMARY
 	00000001 I-----    39 perm 1f3f0000     0     0 keyring   _uid_ses.0: 1/4
@@ -271,7 +313,7 @@
  (*) /proc/key-users
 
      This file lists the tracking data for each user that has at least one key
-     on the system. Such data includes quota information and statistics:
+     on the system.  Such data includes quota information and statistics:
 
 	[root@andromeda root]# cat /proc/key-users
 	0:     46 45/45 1/100 13/10000
@@ -935,6 +977,16 @@
      It is not safe to sleep in this method; the caller may hold spinlocks.
 
 
+ (*) void (*revoke)(struct key *key);
+
+     This method is optional.  It is called to discard part of the payload
+     data upon a key being revoked.  The caller will have the key semaphore
+     write-locked.
+
+     It is safe to sleep in this method, though care should be taken to avoid
+     a deadlock against the key semaphore.
+
+
  (*) void (*destroy)(struct key *key);
 
      This method is optional. It is called to discard the payload data on a key
diff --git a/Documentation/md.txt b/Documentation/md.txt
index 03a13c4..0668f9d 100644
--- a/Documentation/md.txt
+++ b/Documentation/md.txt
@@ -200,6 +200,17 @@
      This can be written only while the array is being assembled, not
      after it is started.
 
+  layout
+     The "layout" for the array for the particular level.  This is
+     simply a number that is interpretted differently by different
+     levels.  It can be written while assembling an array.
+
+  resync_start
+     The point at which resync should start.  If no resync is needed,
+     this will be a very large number.  At array creation it will
+     default to 0, though starting the array as 'clean' will
+     set it much larger.
+
    new_dev
      This file can be written but not read.  The value written should
      be a block device number as major:minor.  e.g. 8:0
@@ -207,6 +218,54 @@
      available.  It will then appear at md/dev-XXX (depending on the
      name of the device) and further configuration is then possible.
 
+   safe_mode_delay
+     When an md array has seen no write requests for a certain period
+     of time, it will be marked as 'clean'.  When another write
+     request arrive, the array is marked as 'dirty' before the write
+     commenses.  This is known as 'safe_mode'.
+     The 'certain period' is controlled by this file which stores the
+     period as a number of seconds.  The default is 200msec (0.200).
+     Writing a value of 0 disables safemode.
+
+   array_state
+     This file contains a single word which describes the current
+     state of the array.  In many cases, the state can be set by
+     writing the word for the desired state, however some states
+     cannot be explicitly set, and some transitions are not allowed.
+
+     clear
+         No devices, no size, no level
+         Writing is equivalent to STOP_ARRAY ioctl
+     inactive
+         May have some settings, but array is not active
+            all IO results in error
+         When written, doesn't tear down array, but just stops it
+     suspended (not supported yet)
+         All IO requests will block. The array can be reconfigured.
+         Writing this, if accepted, will block until array is quiessent
+     readonly
+         no resync can happen.  no superblocks get written.
+         write requests fail
+     read-auto
+         like readonly, but behaves like 'clean' on a write request.
+
+     clean - no pending writes, but otherwise active.
+         When written to inactive array, starts without resync
+         If a write request arrives then
+           if metadata is known, mark 'dirty' and switch to 'active'.
+           if not known, block and switch to write-pending
+         If written to an active array that has pending writes, then fails.
+     active
+         fully active: IO and resync can be happening.
+         When written to inactive array, starts with resync
+
+     write-pending
+         clean, but writes are blocked waiting for 'active' to be written.
+
+     active-idle
+         like active, but no writes have been seen for a while (safe_mode_delay).
+
+
    sync_speed_min
    sync_speed_max
      This are similar to /proc/sys/dev/raid/speed_limit_{min,max}
@@ -250,10 +309,18 @@
 	      faulty   - device has been kicked from active use due to
                          a detected fault
 	      in_sync  - device is a fully in-sync member of the array
+	      writemostly - device will only be subject to read
+		         requests if there are no other options.
+			 This applies only to raid1 arrays.
 	      spare    - device is working, but not a full member.
 			 This includes spares that are in the process
 			 of being recoverred to
 	This list make grow in future.
+	This can be written to.
+	Writing "faulty"  simulates a failure on the device.
+	Writing "remove" removes the device from the array.
+	Writing "writemostly" sets the writemostly flag.
+	Writing "-writemostly" clears the writemostly flag.
 
       errors
 	An approximate count of read errors that have been detected on
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 4710845..cf0d541 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -262,9 +262,14 @@
 CPU to restrict the order.
 
 Memory barriers are such interventions.  They impose a perceived partial
-ordering between the memory operations specified on either side of the barrier.
-They request that the sequence of memory events generated appears to other
-parts of the system as if the barrier is effective on that CPU.
+ordering over the memory operations on either side of the barrier.
+
+Such enforcement is important because the CPUs and other devices in a system
+can use a variety of tricks to improve performance - including reordering,
+deferral and combination of memory operations; speculative loads; speculative
+branch prediction and various types of caching.  Memory barriers are used to
+override or suppress these tricks, allowing the code to sanely control the
+interaction of multiple CPUs and/or devices.
 
 
 VARIETIES OF MEMORY BARRIER
@@ -282,7 +287,7 @@
      A write barrier is a partial ordering on stores only; it is not required
      to have any effect on loads.
 
-     A CPU can be viewed as as commiting a sequence of store operations to the
+     A CPU can be viewed as committing a sequence of store operations to the
      memory system as time progresses.  All stores before a write barrier will
      occur in the sequence _before_ all the stores after the write barrier.
 
@@ -413,7 +418,7 @@
      indirect effect will be the order in which the second CPU sees the effects
      of the first CPU's accesses occur, but see the next point:
 
- (*) There is no guarantee that the a CPU will see the correct order of effects
+ (*) There is no guarantee that a CPU will see the correct order of effects
      from a second CPU's accesses, even _if_ the second CPU uses a memory
      barrier, unless the first CPU _also_ uses a matching memory barrier (see
      the subsection on "SMP Barrier Pairing").
@@ -461,8 +466,8 @@
 isn't, and this behaviour can be observed on certain real CPUs (such as the DEC
 Alpha).
 
-To deal with this, a data dependency barrier must be inserted between the
-address load and the data load:
+To deal with this, a data dependency barrier or better must be inserted
+between the address load and the data load:
 
 	CPU 1		CPU 2
 	===============	===============
@@ -484,7 +489,7 @@
 variable B might be stored in an even-numbered cache line.  Then, if the
 even-numbered bank of the reading CPU's cache is extremely busy while the
 odd-numbered bank is idle, one can see the new value of the pointer P (&B),
-but the old value of the variable B (1).
+but the old value of the variable B (2).
 
 
 Another example of where data dependency barriers might by required is where a
@@ -744,7 +749,7 @@
 	                                        :       :
 
 
-If, however, a read barrier were to be placed between the load of E and the
+If, however, a read barrier were to be placed between the load of B and the
 load of A on CPU 2:
 
 	CPU 1			CPU 2
@@ -1461,9 +1466,8 @@
 
 On a UP system - where this wouldn't be a problem - the smp_mb() is just a
 compiler barrier, thus making sure the compiler emits the instructions in the
-right order without actually intervening in the CPU.  Since there there's only
-one CPU, that CPU's dependency ordering logic will take care of everything
-else.
+right order without actually intervening in the CPU.  Since there's only one
+CPU, that CPU's dependency ordering logic will take care of everything else.
 
 
 ATOMIC OPERATIONS
@@ -1640,9 +1644,9 @@
 
      The PCI bus, amongst others, defines an I/O space concept - which on such
      CPUs as i386 and x86_64 cpus readily maps to the CPU's concept of I/O
-     space.  However, it may also mapped as a virtual I/O space in the CPU's
-     memory map, particularly on those CPUs that don't support alternate
-     I/O spaces.
+     space.  However, it may also be mapped as a virtual I/O space in the CPU's
+     memory map, particularly on those CPUs that don't support alternate I/O
+     spaces.
 
      Accesses to this space may be fully synchronous (as on i386), but
      intermediary bridges (such as the PCI host bridge) may not fully honour
diff --git a/Documentation/networking/README.ipw2200 b/Documentation/networking/README.ipw2200
index acb30c5..4f2a40f 100644
--- a/Documentation/networking/README.ipw2200
+++ b/Documentation/networking/README.ipw2200
@@ -14,8 +14,8 @@
 
 README.ipw2200
 
-Version: 1.0.8
-Date   : October 20, 2005
+Version: 1.1.2
+Date   : March 30, 2006
 
 
 Index
@@ -103,7 +103,7 @@
 
 1.1. Overview of Features
 -----------------------------------------------
-The current release (1.0.8) supports the following features:
+The current release (1.1.2) supports the following features:
 
 + BSS mode (Infrastructure, Managed)
 + IBSS mode (Ad-Hoc)
@@ -247,8 +247,8 @@
 % cat /sys/bus/pci/drivers/ipw2200/debug_level
 
 Will report the current debug level of the driver's logging subsystem 
-(only available if CONFIG_IPW_DEBUG was configured when the driver was 
-built).
+(only available if CONFIG_IPW2200_DEBUG was configured when the driver
+was built).
 
 You can set the debug level via:
 
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 8d8b4e5..afac780 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -1,7 +1,7 @@
 
 		Linux Ethernet Bonding Driver HOWTO
 
-		Latest update: 21 June 2005
+		Latest update: 24 April 2006
 
 Initial release : Thomas Davis <tadavis at lbl.gov>
 Corrections, HA extensions : 2000/10/03-15 :
@@ -12,6 +12,8 @@
   - Jay Vosburgh <fubar at us dot ibm dot com>
 
 Reorganized and updated Feb 2005 by Jay Vosburgh
+Added Sysfs information: 2006/04/24
+  - Mitch Williams <mitch.a.williams at intel.com>
 
 Introduction
 ============
@@ -38,61 +40,62 @@
 2. Bonding Driver Options
 
 3. Configuring Bonding Devices
-3.1	Configuration with sysconfig support
-3.1.1		Using DHCP with sysconfig
-3.1.2		Configuring Multiple Bonds with sysconfig
-3.2	Configuration with initscripts support
-3.2.1		Using DHCP with initscripts
-3.2.2		Configuring Multiple Bonds with initscripts
-3.3	Configuring Bonding Manually
+3.1	Configuration with Sysconfig Support
+3.1.1		Using DHCP with Sysconfig
+3.1.2		Configuring Multiple Bonds with Sysconfig
+3.2	Configuration with Initscripts Support
+3.2.1		Using DHCP with Initscripts
+3.2.2		Configuring Multiple Bonds with Initscripts
+3.3	Configuring Bonding Manually with Ifenslave
 3.3.1		Configuring Multiple Bonds Manually
+3.4	Configuring Bonding Manually via Sysfs
 
-5. Querying Bonding Configuration
-5.1	Bonding Configuration
-5.2	Network Configuration
+4. Querying Bonding Configuration
+4.1	Bonding Configuration
+4.2	Network Configuration
 
-6. Switch Configuration
+5. Switch Configuration
 
-7. 802.1q VLAN Support
+6. 802.1q VLAN Support
 
-8. Link Monitoring
-8.1	ARP Monitor Operation
-8.2	Configuring Multiple ARP Targets
-8.3	MII Monitor Operation
+7. Link Monitoring
+7.1	ARP Monitor Operation
+7.2	Configuring Multiple ARP Targets
+7.3	MII Monitor Operation
 
-9. Potential Trouble Sources
-9.1	Adventures in Routing
-9.2	Ethernet Device Renaming
-9.3	Painfully Slow Or No Failed Link Detection By Miimon
+8. Potential Trouble Sources
+8.1	Adventures in Routing
+8.2	Ethernet Device Renaming
+8.3	Painfully Slow Or No Failed Link Detection By Miimon
 
-10. SNMP agents
+9. SNMP agents
 
-11. Promiscuous mode
+10. Promiscuous mode
 
-12. Configuring Bonding for High Availability
-12.1	High Availability in a Single Switch Topology
-12.2	High Availability in a Multiple Switch Topology
-12.2.1		HA Bonding Mode Selection for Multiple Switch Topology
-12.2.2		HA Link Monitoring for Multiple Switch Topology
+11. Configuring Bonding for High Availability
+11.1	High Availability in a Single Switch Topology
+11.2	High Availability in a Multiple Switch Topology
+11.2.1		HA Bonding Mode Selection for Multiple Switch Topology
+11.2.2		HA Link Monitoring for Multiple Switch Topology
 
-13. Configuring Bonding for Maximum Throughput
-13.1	Maximum Throughput in a Single Switch Topology
-13.1.1		MT Bonding Mode Selection for Single Switch Topology
-13.1.2		MT Link Monitoring for Single Switch Topology
-13.2	Maximum Throughput in a Multiple Switch Topology
-13.2.1		MT Bonding Mode Selection for Multiple Switch Topology
-13.2.2		MT Link Monitoring for Multiple Switch Topology
+12. Configuring Bonding for Maximum Throughput
+12.1	Maximum Throughput in a Single Switch Topology
+12.1.1		MT Bonding Mode Selection for Single Switch Topology
+12.1.2		MT Link Monitoring for Single Switch Topology
+12.2	Maximum Throughput in a Multiple Switch Topology
+12.2.1		MT Bonding Mode Selection for Multiple Switch Topology
+12.2.2		MT Link Monitoring for Multiple Switch Topology
 
-14. Switch Behavior Issues
-14.1	Link Establishment and Failover Delays
-14.2	Duplicated Incoming Packets
+13. Switch Behavior Issues
+13.1	Link Establishment and Failover Delays
+13.2	Duplicated Incoming Packets
 
-15. Hardware Specific Considerations
-15.1	IBM BladeCenter
+14. Hardware Specific Considerations
+14.1	IBM BladeCenter
 
-16. Frequently Asked Questions
+15. Frequently Asked Questions
 
-17. Resources and Links
+16. Resources and Links
 
 
 1. Bonding Driver Installation
@@ -156,6 +159,9 @@
 onwards) do not have /usr/include/linux symbolically linked to the
 default kernel source include directory.
 
+SECOND IMPORTANT NOTE:
+	If you plan to configure bonding using sysfs, you do not need
+to use ifenslave.
 
 2. Bonding Driver Options
 =========================
@@ -270,7 +276,7 @@
 		In bonding version 2.6.2 or later, when a failover
 		occurs in active-backup mode, bonding will issue one
 		or more gratuitous ARPs on the newly active slave.
-		One gratutious ARP is issued for the bonding master
+		One gratuitous ARP is issued for the bonding master
 		interface and each VLAN interfaces configured above
 		it, provided that the interface has at least one IP
 		address configured.  Gratuitous ARPs issued for VLAN
@@ -377,7 +383,7 @@
 		When a link is reconnected or a new slave joins the
 		bond the receive traffic is redistributed among all
 		active slaves in the bond by initiating ARP Replies
-		with the selected mac address to each of the
+		with the selected MAC address to each of the
 		clients. The updelay parameter (detailed below) must
 		be set to a value equal or greater than the switch's
 		forwarding delay so that the ARP Replies sent to the
@@ -498,11 +504,12 @@
 3. Configuring Bonding Devices
 ==============================
 
-	There are, essentially, two methods for configuring bonding:
-with support from the distro's network initialization scripts, and
-without.  Distros generally use one of two packages for the network
-initialization scripts: initscripts or sysconfig.  Recent versions of
-these packages have support for bonding, while older versions do not.
+	You can configure bonding using either your distro's network
+initialization scripts, or manually using either ifenslave or the
+sysfs interface.  Distros generally use one of two packages for the
+network initialization scripts: initscripts or sysconfig.  Recent
+versions of these packages have support for bonding, while older
+versions do not.
 
 	We will first describe the options for configuring bonding for
 distros using versions of initscripts and sysconfig with full or
@@ -530,7 +537,7 @@
 	If this returns any matches, then your initscripts or
 sysconfig has support for bonding.
 
-3.1 Configuration with sysconfig support
+3.1 Configuration with Sysconfig Support
 ----------------------------------------
 
 	This section applies to distros using a version of sysconfig
@@ -538,7 +545,7 @@
 
 	SuSE SLES 9's networking configuration system does support
 bonding, however, at this writing, the YaST system configuration
-frontend does not provide any means to work with bonding devices.
+front end does not provide any means to work with bonding devices.
 Bonding devices can be managed by hand, however, as follows.
 
 	First, if they have not already been configured, configure the
@@ -660,7 +667,7 @@
 	Note that the template does not document the various BONDING_
 settings described above, but does describe many of the other options.
 
-3.1.1 Using DHCP with sysconfig
+3.1.1 Using DHCP with Sysconfig
 -------------------------------
 
 	Under sysconfig, configuring a device with BOOTPROTO='dhcp'
@@ -670,7 +677,7 @@
 the slave devices.  Without active slaves, the DHCP requests are not
 sent to the network.
 
-3.1.2 Configuring Multiple Bonds with sysconfig
+3.1.2 Configuring Multiple Bonds with Sysconfig
 -----------------------------------------------
 
 	The sysconfig network initialization system is capable of
@@ -685,7 +692,7 @@
 options in the ifcfg-bondX file, it is not necessary to add them to
 the system /etc/modules.conf or /etc/modprobe.conf configuration file.
 
-3.2 Configuration with initscripts support
+3.2 Configuration with Initscripts Support
 ------------------------------------------
 
 	This section applies to distros using a version of initscripts
@@ -756,7 +763,7 @@
 will restart the networking subsystem and your bond link should be now
 up and running.
 
-3.2.1 Using DHCP with initscripts
+3.2.1 Using DHCP with Initscripts
 ---------------------------------
 
 	Recent versions of initscripts (the version supplied with
@@ -768,7 +775,7 @@
 and add a line consisting of "TYPE=Bonding".  Note that the TYPE value
 is case sensitive.
 
-3.2.2 Configuring Multiple Bonds with initscripts
+3.2.2 Configuring Multiple Bonds with Initscripts
 -------------------------------------------------
 
 	At this writing, the initscripts package does not directly
@@ -784,8 +791,8 @@
 exhibiting this problem, it will be impossible to configure multiple
 bonds with differing parameters.
 
-3.3 Configuring Bonding Manually
---------------------------------
+3.3 Configuring Bonding Manually with Ifenslave
+-----------------------------------------------
 
 	This section applies to distros whose network initialization
 scripts (the sysconfig or initscripts package) do not have specific
@@ -889,11 +896,139 @@
 	This may be repeated any number of times, specifying a new and
 unique name in place of bond1 for each subsequent instance.
 
+3.4 Configuring Bonding Manually via Sysfs
+------------------------------------------
 
-5. Querying Bonding Configuration 
+	Starting with version 3.0, Channel Bonding may be configured
+via the sysfs interface.  This interface allows dynamic configuration
+of all bonds in the system without unloading the module.  It also
+allows for adding and removing bonds at runtime.  Ifenslave is no
+longer required, though it is still supported.
+
+	Use of the sysfs interface allows you to use multiple bonds
+with different configurations without having to reload the module.
+It also allows you to use multiple, differently configured bonds when
+bonding is compiled into the kernel.
+
+	You must have the sysfs filesystem mounted to configure
+bonding this way.  The examples in this document assume that you
+are using the standard mount point for sysfs, e.g. /sys.  If your
+sysfs filesystem is mounted elsewhere, you will need to adjust the
+example paths accordingly.
+
+Creating and Destroying Bonds
+-----------------------------
+To add a new bond foo:
+# echo +foo > /sys/class/net/bonding_masters
+
+To remove an existing bond bar:
+# echo -bar > /sys/class/net/bonding_masters
+
+To show all existing bonds:
+# cat /sys/class/net/bonding_masters
+
+NOTE: due to 4K size limitation of sysfs files, this list may be
+truncated if you have more than a few hundred bonds.  This is unlikely
+to occur under normal operating conditions.
+
+Adding and Removing Slaves
+--------------------------
+	Interfaces may be enslaved to a bond using the file
+/sys/class/net/<bond>/bonding/slaves.  The semantics for this file
+are the same as for the bonding_masters file.
+
+To enslave interface eth0 to bond bond0:
+# ifconfig bond0 up
+# echo +eth0 > /sys/class/net/bond0/bonding/slaves
+
+To free slave eth0 from bond bond0:
+# echo -eth0 > /sys/class/net/bond0/bonding/slaves
+
+	NOTE: The bond must be up before slaves can be added.  All
+slaves are freed when the interface is brought down.
+
+	When an interface is enslaved to a bond, symlinks between the
+two are created in the sysfs filesystem.  In this case, you would get
+/sys/class/net/bond0/slave_eth0 pointing to /sys/class/net/eth0, and
+/sys/class/net/eth0/master pointing to /sys/class/net/bond0.
+
+	This means that you can tell quickly whether or not an
+interface is enslaved by looking for the master symlink.  Thus:
+# echo -eth0 > /sys/class/net/eth0/master/bonding/slaves
+will free eth0 from whatever bond it is enslaved to, regardless of
+the name of the bond interface.
+
+Changing a Bond's Configuration
+-------------------------------
+	Each bond may be configured individually by manipulating the
+files located in /sys/class/net/<bond name>/bonding
+
+	The names of these files correspond directly with the command-
+line parameters described elsewhere in in this file, and, with the
+exception of arp_ip_target, they accept the same values.  To see the
+current setting, simply cat the appropriate file.
+
+	A few examples will be given here; for specific usage
+guidelines for each parameter, see the appropriate section in this
+document.
+
+To configure bond0 for balance-alb mode:
+# ifconfig bond0 down
+# echo 6 > /sys/class/net/bond0/bonding/mode
+ - or -
+# echo balance-alb > /sys/class/net/bond0/bonding/mode
+	NOTE: The bond interface must be down before the mode can be
+changed.
+
+To enable MII monitoring on bond0 with a 1 second interval:
+# echo 1000 > /sys/class/net/bond0/bonding/miimon
+	NOTE: If ARP monitoring is enabled, it will disabled when MII
+monitoring is enabled, and vice-versa.
+
+To add ARP targets:
+# echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
+# echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_target
+	NOTE:  up to 10 target addresses may be specified.
+
+To remove an ARP target:
+# echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
+
+Example Configuration
+---------------------
+	We begin with the same example that is shown in section 3.3,
+executed with sysfs, and without using ifenslave.
+
+	To make a simple bond of two e100 devices (presumed to be eth0
+and eth1), and have it persist across reboots, edit the appropriate
+file (/etc/init.d/boot.local or /etc/rc.d/rc.local), and add the
+following:
+
+modprobe bonding
+modprobe e100
+echo balance-alb > /sys/class/net/bond0/bonding/mode
+ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
+echo 100 > /sys/class/net/bond0/bonding/miimon
+echo +eth0 > /sys/class/net/bond0/bonding/slaves
+echo +eth1 > /sys/class/net/bond0/bonding/slaves
+
+	To add a second bond, with two e1000 interfaces in
+active-backup mode, using ARP monitoring, add the following lines to
+your init script:
+
+modprobe e1000
+echo +bond1 > /sys/class/net/bonding_masters
+echo active-backup > /sys/class/net/bond1/bonding/mode
+ifconfig bond1 192.168.2.1 netmask 255.255.255.0 up
+echo +192.168.2.100 /sys/class/net/bond1/bonding/arp_ip_target
+echo 2000 > /sys/class/net/bond1/bonding/arp_interval
+echo +eth2 > /sys/class/net/bond1/bonding/slaves
+echo +eth3 > /sys/class/net/bond1/bonding/slaves
+
+
+4. Querying Bonding Configuration 
 =================================
 
-5.1 Bonding Configuration
+4.1 Bonding Configuration
 -------------------------
 
 	Each bonding device has a read-only file residing in the
@@ -923,7 +1058,7 @@
 	The precise format and contents will change depending upon the
 bonding configuration, state, and version of the bonding driver.
 
-5.2 Network configuration
+4.2 Network configuration
 -------------------------
 
 	The network configuration can be inspected using the ifconfig
@@ -958,7 +1093,7 @@
           collisions:0 txqueuelen:100
           Interrupt:9 Base address:0x1400
 
-6. Switch Configuration
+5. Switch Configuration
 =======================
 
 	For this section, "switch" refers to whatever system the
@@ -991,7 +1126,7 @@
 with another EtherChannel group.
 
 
-7. 802.1q VLAN Support
+6. 802.1q VLAN Support
 ======================
 
 	It is possible to configure VLAN devices over a bond interface
@@ -1042,7 +1177,7 @@
 mode, which might not be what you want.
 
 
-8. Link Monitoring
+7. Link Monitoring
 ==================
 
 	The bonding driver at present supports two schemes for
@@ -1053,7 +1188,7 @@
 bonding driver itself, it is not possible to enable both ARP and MII
 monitoring simultaneously.
 
-8.1 ARP Monitor Operation
+7.1 ARP Monitor Operation
 -------------------------
 
 	The ARP monitor operates as its name suggests: it sends ARP
@@ -1071,7 +1206,7 @@
 shows the ARP requests and replies on the network, then it may be that
 your device driver is not updating last_rx and trans_start.
 
-8.2 Configuring Multiple ARP Targets
+7.2 Configuring Multiple ARP Targets
 ------------------------------------
 
 	While ARP monitoring can be done with just one target, it can
@@ -1094,7 +1229,7 @@
 options bond0 arp_interval=60 arp_ip_target=192.168.0.100
 
 
-8.3 MII Monitor Operation
+7.3 MII Monitor Operation
 -------------------------
 
 	The MII monitor monitors only the carrier state of the local
@@ -1120,14 +1255,14 @@
 and ethtool requests), then the MII monitor will assume the link is
 up.
 
-9. Potential Sources of Trouble
+8. Potential Sources of Trouble
 ===============================
 
-9.1 Adventures in Routing
+8.1 Adventures in Routing
 -------------------------
 
 	When bonding is configured, it is important that the slave
-devices not have routes that supercede routes of the master (or,
+devices not have routes that supersede routes of the master (or,
 generally, not have routes at all).  For example, suppose the bonding
 device bond0 has two slaves, eth0 and eth1, and the routing table is
 as follows:
@@ -1154,11 +1289,11 @@
 
 	The solution here is simply to insure that slaves do not have
 routes of their own, and if for some reason they must, those routes do
-not supercede routes of their master.  This should generally be the
+not supersede routes of their master.  This should generally be the
 case, but unusual configurations or errant manual or automatic static
 route additions may cause trouble.
 
-9.2 Ethernet Device Renaming
+8.2 Ethernet Device Renaming
 ----------------------------
 
 	On systems with network configuration scripts that do not
@@ -1207,7 +1342,7 @@
 place.  Full documentation on this can be found in the modprobe.conf
 and modprobe manual pages.
 
-9.3. Painfully Slow Or No Failed Link Detection By Miimon
+8.3. Painfully Slow Or No Failed Link Detection By Miimon
 ---------------------------------------------------------
 
 	By default, bonding enables the use_carrier option, which
@@ -1235,7 +1370,7 @@
 beyond other ports of a switch, or if a switch is refusing to pass
 traffic while still maintaining carrier on.
 
-10. SNMP agents
+9. SNMP agents
 ===============
 
 	If running SNMP agents, the bonding driver should be loaded
@@ -1281,7 +1416,7 @@
 and SNMP functions such as Interface_Scan_Next will report that
 association.
 
-11. Promiscuous mode
+10. Promiscuous mode
 ====================
 
 	When running network monitoring tools, e.g., tcpdump, it is
@@ -1308,7 +1443,7 @@
 the active slave changes (e.g., due to a link failure), the
 promiscuous setting will be propagated to the new active slave.
 
-12. Configuring Bonding for High Availability
+11. Configuring Bonding for High Availability
 =============================================
 
 	High Availability refers to configurations that provide
@@ -1318,7 +1453,7 @@
 (i.e., the network always works), even though other configurations
 could provide higher throughput.
 
-12.1 High Availability in a Single Switch Topology
+11.1 High Availability in a Single Switch Topology
 --------------------------------------------------
 
 	If two hosts (or a host and a single switch) are directly
@@ -1332,7 +1467,7 @@
 	See Section 13, "Configuring Bonding for Maximum Throughput"
 for information on configuring bonding with one peer device.
 
-12.2 High Availability in a Multiple Switch Topology
+11.2 High Availability in a Multiple Switch Topology
 ----------------------------------------------------
 
 	With multiple switches, the configuration of bonding and the
@@ -1359,7 +1494,7 @@
 the outside world ("port3" on each switch).  There is no technical
 reason that this could not be extended to a third switch.
 
-12.2.1 HA Bonding Mode Selection for Multiple Switch Topology
+11.2.1 HA Bonding Mode Selection for Multiple Switch Topology
 -------------------------------------------------------------
 
 	In a topology such as the example above, the active-backup and
@@ -1381,7 +1516,7 @@
 	necessary for some specific one-way traffic to reach both
 	independent networks, then the broadcast mode may be suitable.
 
-12.2.2 HA Link Monitoring Selection for Multiple Switch Topology
+11.2.2 HA Link Monitoring Selection for Multiple Switch Topology
 ----------------------------------------------------------------
 
 	The choice of link monitoring ultimately depends upon your
@@ -1402,10 +1537,10 @@
 target to query.
 
 
-13. Configuring Bonding for Maximum Throughput
+12. Configuring Bonding for Maximum Throughput
 ==============================================
 
-13.1 Maximizing Throughput in a Single Switch Topology
+12.1 Maximizing Throughput in a Single Switch Topology
 ------------------------------------------------------
 
 	In a single switch configuration, the best method to maximize
@@ -1476,7 +1611,7 @@
 mode is described below.
 
 
-13.1.1 MT Bonding Mode Selection for Single Switch Topology
+12.1.1 MT Bonding Mode Selection for Single Switch Topology
 -----------------------------------------------------------
 
 	This configuration is the easiest to set up and to understand,
@@ -1607,7 +1742,7 @@
 	device driver must support changing the hardware address while
 	the device is open.
 
-13.1.2 MT Link Monitoring for Single Switch Topology
+12.1.2 MT Link Monitoring for Single Switch Topology
 ----------------------------------------------------
 
 	The choice of link monitoring may largely depend upon which
@@ -1616,7 +1751,7 @@
 the MII monitor (which does not provide as high a level of end to end
 assurance as the ARP monitor).
 
-13.2 Maximum Throughput in a Multiple Switch Topology
+12.2 Maximum Throughput in a Multiple Switch Topology
 -----------------------------------------------------
 
 	Multiple switches may be utilized to optimize for throughput
@@ -1651,7 +1786,7 @@
 can be equipped with an additional network device connected to an
 external network; this host then additionally acts as a gateway.
 
-13.2.1 MT Bonding Mode Selection for Multiple Switch Topology
+12.2.1 MT Bonding Mode Selection for Multiple Switch Topology
 -------------------------------------------------------------
 
 	In actual practice, the bonding mode typically employed in
@@ -1664,7 +1799,7 @@
 mode allows individual connections between two hosts to effectively
 utilize greater than one interface's bandwidth.
 
-13.2.2 MT Link Monitoring for Multiple Switch Topology
+12.2.2 MT Link Monitoring for Multiple Switch Topology
 ------------------------------------------------------
 
 	Again, in actual practice, the MII monitor is most often used
@@ -1674,10 +1809,10 @@
 needed as the number of systems involved grows (remember that each
 host in the network is configured with bonding).
 
-14. Switch Behavior Issues
+13. Switch Behavior Issues
 ==========================
 
-14.1 Link Establishment and Failover Delays
+13.1 Link Establishment and Failover Delays
 -------------------------------------------
 
 	Some switches exhibit undesirable behavior with regard to the
@@ -1712,7 +1847,7 @@
 to not activate a backup interface immediately after a link goes down.
 Failover may be delayed via the downdelay bonding module option.
 
-14.2 Duplicated Incoming Packets
+13.2 Duplicated Incoming Packets
 --------------------------------
 
 	It is not uncommon to observe a short burst of duplicated
@@ -1751,14 +1886,14 @@
 most Cisco switches, the privileged command "clear mac address-table
 dynamic" will accomplish this).
 
-15. Hardware Specific Considerations
+14. Hardware Specific Considerations
 ====================================
 
 	This section contains additional information for configuring
 bonding on specific hardware platforms, or for interfacing bonding
 with particular switches or other devices.
 
-15.1 IBM BladeCenter
+14.1 IBM BladeCenter
 --------------------
 
 	This applies to the JS20 and similar systems.
@@ -1861,7 +1996,7 @@
 avoid fail-over delay issues when using bonding.
 
 	
-16. Frequently Asked Questions
+15. Frequently Asked Questions
 ==============================
 
 1.  Is it SMP safe?
@@ -1925,7 +2060,7 @@
 support specific features (described in the appropriate section under
 module parameters, above).
 
-	In 802.3ad mode, it works with with systems that support IEEE
+	In 802.3ad mode, it works with systems that support IEEE
 802.3ad Dynamic Link Aggregation.  Most managed and many unmanaged
 switches currently available support 802.3ad.
 
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index f12007b..d46338a 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -362,6 +362,13 @@
 	not receive a window scaling option from them.
 	Default: 0
 
+tcp_slow_start_after_idle - BOOLEAN
+	If set, provide RFC2861 behavior and time out the congestion
+	window after an idle period.  An idle period is defined at
+	the current RTO.  If unset, the congestion window will not
+	be timed out after an idle period.
+	Default: 1
+
 IP Variables:
 
 ip_local_port_range - 2 INTEGERS
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index 3c0a5ba..847cedb 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -42,9 +42,9 @@
 	Context: nominally process, but don't sleep inside an rwlock
 
 dev->hard_start_xmit:
-	Synchronization: dev->xmit_lock spinlock.
+	Synchronization: netif_tx_lock spinlock.
 	When the driver sets NETIF_F_LLTX in dev->features this will be
-	called without holding xmit_lock. In this case the driver 
+	called without holding netif_tx_lock. In this case the driver
 	has to lock by itself when needed. It is recommended to use a try lock
 	for this and return -1 when the spin lock fails. 
 	The locking there should also properly protect against 
@@ -62,12 +62,12 @@
 	  Only valid when NETIF_F_LLTX is set.
 
 dev->tx_timeout:
-	Synchronization: dev->xmit_lock spinlock.
+	Synchronization: netif_tx_lock spinlock.
 	Context: BHs disabled
 	Notes: netif_queue_stopped() is guaranteed true
 
 dev->set_multicast_list:
-	Synchronization: dev->xmit_lock spinlock.
+	Synchronization: netif_tx_lock spinlock.
 	Context: BHs disabled
 
 dev->poll:
diff --git a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt
index 76750fb..839cbb7 100644
--- a/Documentation/networking/tuntap.txt
+++ b/Documentation/networking/tuntap.txt
@@ -39,10 +39,13 @@
      mknod /dev/net/tun c 10 200
   
   Set permissions:
-     e.g. chmod 0700 /dev/net/tun
-     if you want the device only accessible by root. Giving regular users the
-     right to assign network devices is NOT a good idea. Users could assign
-     bogus network interfaces to trick firewalls or administrators.
+     e.g. chmod 0666 /dev/net/tun
+     There's no harm in allowing the device to be accessible by non-root users,
+     since CAP_NET_ADMIN is required for creating network devices or for 
+     connecting to network devices which aren't owned by the user in question.
+     If you want to create persistent devices and give ownership of them to 
+     unprivileged users, then you need the /dev/net/tun device to be usable by
+     those users.
 
   Driver module autoloading
 
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 66bbbf1..3242e5c 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -213,9 +213,17 @@
 
    See Documentation/IO-mapping.txt for how to access device memory.
 
-   You still need to call request_region() for I/O regions and
-request_mem_region() for memory regions to make sure nobody else is using the
-same device.
+   The device driver needs to call pci_request_region() to make sure
+no other device is already using the same resource. The driver is expected
+to determine MMIO and IO Port resource availability _before_ calling
+pci_enable_device().  Conversely, drivers should call pci_release_region()
+_after_ calling pci_disable_device(). The idea is to prevent two devices
+colliding on the same address range.
+
+Generic flavors of pci_request_region() are request_mem_region()
+(for MMIO ranges) and request_region() (for IO Port ranges).
+Use these for address resources that are not described by "normal" PCI
+interfaces (e.g. BAR).
 
    All interrupt handlers should be registered with SA_SHIRQ and use the devid
 to map IRQs to devices (remember that all PCI interrupts are shared).
diff --git a/Documentation/pi-futex.txt b/Documentation/pi-futex.txt
new file mode 100644
index 0000000..5d61dac
--- /dev/null
+++ b/Documentation/pi-futex.txt
@@ -0,0 +1,121 @@
+Lightweight PI-futexes
+----------------------
+
+We are calling them lightweight for 3 reasons:
+
+ - in the user-space fastpath a PI-enabled futex involves no kernel work
+   (or any other PI complexity) at all. No registration, no extra kernel
+   calls - just pure fast atomic ops in userspace.
+
+ - even in the slowpath, the system call and scheduling pattern is very
+   similar to normal futexes.
+
+ - the in-kernel PI implementation is streamlined around the mutex
+   abstraction, with strict rules that keep the implementation
+   relatively simple: only a single owner may own a lock (i.e. no
+   read-write lock support), only the owner may unlock a lock, no
+   recursive locking, etc.
+
+Priority Inheritance - why?
+---------------------------
+
+The short reply: user-space PI helps achieving/improving determinism for
+user-space applications. In the best-case, it can help achieve
+determinism and well-bound latencies. Even in the worst-case, PI will
+improve the statistical distribution of locking related application
+delays.
+
+The longer reply:
+-----------------
+
+Firstly, sharing locks between multiple tasks is a common programming
+technique that often cannot be replaced with lockless algorithms. As we
+can see it in the kernel [which is a quite complex program in itself],
+lockless structures are rather the exception than the norm - the current
+ratio of lockless vs. locky code for shared data structures is somewhere
+between 1:10 and 1:100. Lockless is hard, and the complexity of lockless
+algorithms often endangers to ability to do robust reviews of said code.
+I.e. critical RT apps often choose lock structures to protect critical
+data structures, instead of lockless algorithms. Furthermore, there are
+cases (like shared hardware, or other resource limits) where lockless
+access is mathematically impossible.
+
+Media players (such as Jack) are an example of reasonable application
+design with multiple tasks (with multiple priority levels) sharing
+short-held locks: for example, a highprio audio playback thread is
+combined with medium-prio construct-audio-data threads and low-prio
+display-colory-stuff threads. Add video and decoding to the mix and
+we've got even more priority levels.
+
+So once we accept that synchronization objects (locks) are an
+unavoidable fact of life, and once we accept that multi-task userspace
+apps have a very fair expectation of being able to use locks, we've got
+to think about how to offer the option of a deterministic locking
+implementation to user-space.
+
+Most of the technical counter-arguments against doing priority
+inheritance only apply to kernel-space locks. But user-space locks are
+different, there we cannot disable interrupts or make the task
+non-preemptible in a critical section, so the 'use spinlocks' argument
+does not apply (user-space spinlocks have the same priority inversion
+problems as other user-space locking constructs). Fact is, pretty much
+the only technique that currently enables good determinism for userspace
+locks (such as futex-based pthread mutexes) is priority inheritance:
+
+Currently (without PI), if a high-prio and a low-prio task shares a lock
+[this is a quite common scenario for most non-trivial RT applications],
+even if all critical sections are coded carefully to be deterministic
+(i.e. all critical sections are short in duration and only execute a
+limited number of instructions), the kernel cannot guarantee any
+deterministic execution of the high-prio task: any medium-priority task
+could preempt the low-prio task while it holds the shared lock and
+executes the critical section, and could delay it indefinitely.
+
+Implementation:
+---------------
+
+As mentioned before, the userspace fastpath of PI-enabled pthread
+mutexes involves no kernel work at all - they behave quite similarly to
+normal futex-based locks: a 0 value means unlocked, and a value==TID
+means locked. (This is the same method as used by list-based robust
+futexes.) Userspace uses atomic ops to lock/unlock these mutexes without
+entering the kernel.
+
+To handle the slowpath, we have added two new futex ops:
+
+  FUTEX_LOCK_PI
+  FUTEX_UNLOCK_PI
+
+If the lock-acquire fastpath fails, [i.e. an atomic transition from 0 to
+TID fails], then FUTEX_LOCK_PI is called. The kernel does all the
+remaining work: if there is no futex-queue attached to the futex address
+yet then the code looks up the task that owns the futex [it has put its
+own TID into the futex value], and attaches a 'PI state' structure to
+the futex-queue. The pi_state includes an rt-mutex, which is a PI-aware,
+kernel-based synchronization object. The 'other' task is made the owner
+of the rt-mutex, and the FUTEX_WAITERS bit is atomically set in the
+futex value. Then this task tries to lock the rt-mutex, on which it
+blocks. Once it returns, it has the mutex acquired, and it sets the
+futex value to its own TID and returns. Userspace has no other work to
+perform - it now owns the lock, and futex value contains
+FUTEX_WAITERS|TID.
+
+If the unlock side fastpath succeeds, [i.e. userspace manages to do a
+TID -> 0 atomic transition of the futex value], then no kernel work is
+triggered.
+
+If the unlock fastpath fails (because the FUTEX_WAITERS bit is set),
+then FUTEX_UNLOCK_PI is called, and the kernel unlocks the futex on the
+behalf of userspace - and it also unlocks the attached
+pi_state->rt_mutex and thus wakes up any potential waiters.
+
+Note that under this approach, contrary to previous PI-futex approaches,
+there is no prior 'registration' of a PI-futex. [which is not quite
+possible anyway, due to existing ABI properties of pthread mutexes.]
+
+Also, under this scheme, 'robustness' and 'PI' are two orthogonal
+properties of futexes, and all four combinations are possible: futex,
+robust-futex, PI-futex, robust+PI-futex.
+
+More details about priority inheritance can be found in
+Documentation/rtmutex.txt.
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index f987afe..fba1e05 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -135,96 +135,6 @@
 
 FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from
 scratch. That probably means stop accepting upstream requests, the
-actual policy of what to do with them beeing specific to a given
-driver. It's acceptable for a network driver to just drop packets
-while a block driver is expected to block the queue so no request is
-lost. (Use IDE as an example on how to do that). FREEZE requires no
-power state change, and it's expected for drivers to be able to
-quickly transition back to operating state.
-
-SUSPEND -- like FREEZE, but also put hardware into low-power state. If
-there's need to distinguish several levels of sleep, additional flag
-is probably best way to do that.
-
-Transitions are only from a resumed state to a suspended state, never
-between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen,
-FREEZE -> SUSPEND or SUSPEND -> FREEZE can not).
-
-All events are:
-
-[NOTE NOTE NOTE: If you are driver author, you should not care; you
-should only look at event, and ignore flags.]
-
-#Prepare for suspend -- userland is still running but we are going to
-#enter suspend state. This gives drivers chance to load firmware from
-#disk and store it in memory, or do other activities taht require
-#operating userland, ability to kmalloc GFP_KERNEL, etc... All of these
-#are forbiden once the suspend dance is started.. event = ON, flags =
-#PREPARE_TO_SUSPEND
-
-Apm standby -- prepare for APM event. Quiesce devices to make life
-easier for APM BIOS. event = FREEZE, flags = APM_STANDBY
-
-Apm suspend -- same as APM_STANDBY, but it we should probably avoid
-spinning down disks. event = FREEZE, flags = APM_SUSPEND
-
-System halt, reboot -- quiesce devices to make life easier for BIOS. event
-= FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT
-
-System shutdown -- at least disks need to be spun down, or data may be
-lost. Quiesce devices, just to make life easier for BIOS. event =
-FREEZE, flags = SYSTEM_SHUTDOWN
-
-Kexec    -- turn off DMAs and put hardware into some state where new
-kernel can take over. event = FREEZE, flags = KEXEC
-
-Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake
-may need to be enabled on some devices. This actually has at least 3
-subtypes, system can reboot, enter S4 and enter S5 at the end of
-swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT,
-SYSTEM_SHUTDOWN, SYSTEM_S4
-
-Suspend to ram  -- put devices into low power state. event = SUSPEND,
-flags = SUSPEND_TO_RAM
-
-Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put
-devices into low power mode, but you must be able to reinitialize
-device from scratch in resume method. This has two flavors, its done
-once on suspending kernel, once on resuming kernel. event = FREEZE,
-flags = DURING_SUSPEND or DURING_RESUME
-
-Device detach requested from /sys -- deinitialize device; proably same as
-SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
-= FREEZE, flags = DEV_DETACH.
-
-#These are not really events sent:
-#
-#System fully on -- device is working normally; this is probably never
-#passed to suspend() method... event = ON, flags = 0
-#
-#Ready after resume -- userland is now running, again. Time to free any
-#memory you ate during prepare to suspend... event = ON, flags =
-#READY_AFTER_RESUME
-#
-
-
-pm_message_t meaning
-
-pm_message_t has two fields. event ("major"), and flags.  If driver
-does not know event code, it aborts the request, returning error. Some
-drivers may need to deal with special cases based on the actual type
-of suspend operation being done at the system level. This is why
-there are flags.
-
-Event codes are:
-
-ON -- no need to do anything except special cases like broken
-HW.
-
-# NOTIFICATION -- pretty much same as ON?
-
-FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from
-scratch. That probably means stop accepting upstream requests, the
 actual policy of what to do with them being specific to a given
 driver. It's acceptable for a network driver to just drop packets
 while a block driver is expected to block the queue so no request is
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index d7814a11..823b2cf 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -18,10 +18,11 @@
  *
  * (*) suspend/resume support is needed to make it safe.
  *
- * If you have any filesystems on USB devices mounted before suspend,
+ * If you have any filesystems on USB devices mounted before software suspend,
  * they won't be accessible after resume and you may lose data, as though
- * you have unplugged the USB devices with mounted filesystems on them
- * (see the FAQ below for details).
+ * you have unplugged the USB devices with mounted filesystems on them;
+ * see the FAQ below for details.  (This is not true for more traditional
+ * power states like "standby", which normally don't turn USB off.)
 
 You need to append resume=/dev/your_swap_partition to kernel command
 line. Then you suspend by
@@ -204,7 +205,7 @@
 distinctions between SUSPEND and FREEZE.
 
 A: Doing SUSPEND when you are asked to do FREEZE is always correct,
-but it may be unneccessarily slow. If you want USB to stay simple,
+but it may be unneccessarily slow. If you want your driver to stay simple,
 slowness may not matter to you. It can always be fixed later.
 
 For devices like disk it does matter, you do not want to spindown for
@@ -349,25 +350,72 @@
 
 A: If you want to see any non-error kernel messages on the virtual
 terminal the kernel switches to during suspend, you have to set the
-kernel console loglevel to at least 5, for example by doing
+kernel console loglevel to at least 4 (KERN_WARNING), for example by
+doing
 
-	echo 5 > /proc/sys/kernel/printk
+	# save the old loglevel
+	read LOGLEVEL DUMMY < /proc/sys/kernel/printk
+	# set the loglevel so we see the progress bar.
+	# if the level is higher than needed, we leave it alone.
+	if [ $LOGLEVEL -lt 5 ]; then
+	        echo 5 > /proc/sys/kernel/printk
+		fi
+
+        IMG_SZ=0
+        read IMG_SZ < /sys/power/image_size
+        echo -n disk > /sys/power/state
+        RET=$?
+        #
+        # the logic here is:
+        # if image_size > 0 (without kernel support, IMG_SZ will be zero),
+        # then try again with image_size set to zero.
+	if [ $RET -ne 0 -a $IMG_SZ -ne 0 ]; then # try again with minimal image size
+                echo 0 > /sys/power/image_size
+                echo -n disk > /sys/power/state
+                RET=$?
+        fi
+
+	# restore previous loglevel
+	echo $LOGLEVEL > /proc/sys/kernel/printk
+	exit $RET
 
 Q: Is this true that if I have a mounted filesystem on a USB device and
 I suspend to disk, I can lose data unless the filesystem has been mounted
 with "sync"?
 
-A: That's right.  It depends on your hardware, and it could be true even for
-suspend-to-RAM.  In fact, even with "-o sync" you can lose data if your
-programs have information in buffers they haven't written out to disk.
+A: That's right ... if you disconnect that device, you may lose data.
+In fact, even with "-o sync" you can lose data if your programs have
+information in buffers they haven't written out to a disk you disconnect,
+or if you disconnect before the device finished saving data you wrote.
 
-If you're lucky, your hardware will support low-power modes for USB
-controllers while the system is asleep.  Lots of hardware doesn't,
-however.  Shutting off the power to a USB controller is equivalent to
-unplugging all the attached devices.
+Software suspend normally powers down USB controllers, which is equivalent
+to disconnecting all USB devices attached to your system.
+
+Your system might well support low-power modes for its USB controllers
+while the system is asleep, maintaining the connection, using true sleep
+modes like "suspend-to-RAM" or "standby".  (Don't write "disk" to the
+/sys/power/state file; write "standby" or "mem".)  We've not seen any
+hardware that can use these modes through software suspend, although in
+theory some systems might support "platform" or "firmware" modes that
+won't break the USB connections.
 
 Remember that it's always a bad idea to unplug a disk drive containing a
-mounted filesystem.  With USB that's true even when your system is asleep!
-The safest thing is to unmount all USB-based filesystems before suspending
-and remount them after resuming.
+mounted filesystem.  That's true even when your system is asleep!  The
+safest thing is to unmount all filesystems on removable media (such USB,
+Firewire, CompactFlash, MMC, external SATA, or even IDE hotplug bays)
+before suspending; then remount them after resuming.
 
+Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were
+compiled with the similar configuration files. Anyway I found that
+suspend to disk (and resume) is much slower on 2.6.16 compared to
+2.6.15. Any idea for why that might happen or how can I speed it up?
+
+A: This is because the size of the suspend image is now greater than
+for 2.6.15 (by saving more data we can get more responsive system
+after resume).
+
+There's the /sys/power/image_size knob that controls the size of the
+image.  If you set it to 0 (eg. by echo 0 > /sys/power/image_size as
+root), the 2.6.15 behavior should be restored.  If it is still too
+slow, take a look at suspend.sf.net -- userland suspend is faster and
+supports LZF compression to speed it up further.
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index 43a889f..d859faa 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -90,6 +90,7 @@
 Model                           hack (or "how to do it")
 ------------------------------------------------------------------------------
 Acer Aspire 1406LC		ole's late BIOS init (7), turn off DRI
+Acer TM 230			s3_bios (2)
 Acer TM 242FX			vbetool (6)
 Acer TM C110			video_post (8)
 Acer TM C300                    vga=normal (only suspend on console, not in X), vbetool (6) or video_post (8)
@@ -115,6 +116,7 @@
 Dell Inspiron 4000		??? (*)
 Dell Inspiron 500m		??? (*)
 Dell Inspiron 510m		???
+Dell Inspiron 5150		vbetool needed (6)
 Dell Inspiron 600m		??? (*)
 Dell Inspiron 8200		??? (*)
 Dell Inspiron 8500		??? (*)
@@ -125,6 +127,7 @@
 HP Pavilion ZD7000		vbetool post needed, need open-source nv driver for X
 HP Omnibook XE3	athlon version	none (1)
 HP Omnibook XE3GC		none (1), video is S3 Savage/IX-MV
+HP Omnibook XE3L-GF		vbetool (6)
 HP Omnibook 5150		none (1), (S1 also works OK)
 IBM TP T20, model 2647-44G	none (1), video is S3 Inc. 86C270-294 Savage/IX-MV, vesafb gets "interesting" but X work.
 IBM TP A31 / Type 2652-M5G      s3_mode (3) [works ok with BIOS 1.04 2002-08-23, but not at all with BIOS 1.11 2004-11-05 :-(]
@@ -157,6 +160,7 @@
 Sony Vaio vgn-S580BH		vga=normal, but suspend from X. Console will be blank unless you return to X.
 Sony Vaio vgn-FS115B		s3_bios (2),s3_mode (4)
 Toshiba Libretto L5		none (1)
+Toshiba Libretto 100CT/110CT    vbetool (6)
 Toshiba Portege 3020CT		s3_mode (3)
 Toshiba Satellite 4030CDT	s3_mode (3) (S1 also works OK)
 Toshiba Satellite 4080XCDT      s3_mode (3) (S1 also works OK)
diff --git a/Documentation/robust-futexes.txt b/Documentation/robust-futexes.txt
index df82d75..76e8064 100644
--- a/Documentation/robust-futexes.txt
+++ b/Documentation/robust-futexes.txt
@@ -95,7 +95,7 @@
 is empty. If the thread/process crashed or terminated in some incorrect
 way then the list might be non-empty: in this case the kernel carefully
 walks the list [not trusting it], and marks all locks that are owned by
-this thread with the FUTEX_OWNER_DEAD bit, and wakes up one waiter (if
+this thread with the FUTEX_OWNER_DIED bit, and wakes up one waiter (if
 any).
 
 The list is guaranteed to be private and per-thread at do_exit() time,
diff --git a/Documentation/rt-mutex-design.txt b/Documentation/rt-mutex-design.txt
new file mode 100644
index 0000000..c472ffa
--- /dev/null
+++ b/Documentation/rt-mutex-design.txt
@@ -0,0 +1,781 @@
+#
+# Copyright (c) 2006 Steven Rostedt
+# Licensed under the GNU Free Documentation License, Version 1.2
+#
+
+RT-mutex implementation design
+------------------------------
+
+This document tries to describe the design of the rtmutex.c implementation.
+It doesn't describe the reasons why rtmutex.c exists. For that please see
+Documentation/rt-mutex.txt.  Although this document does explain problems
+that happen without this code, but that is in the concept to understand
+what the code actually is doing.
+
+The goal of this document is to help others understand the priority
+inheritance (PI) algorithm that is used, as well as reasons for the
+decisions that were made to implement PI in the manner that was done.
+
+
+Unbounded Priority Inversion
+----------------------------
+
+Priority inversion is when a lower priority process executes while a higher
+priority process wants to run.  This happens for several reasons, and
+most of the time it can't be helped.  Anytime a high priority process wants
+to use a resource that a lower priority process has (a mutex for example),
+the high priority process must wait until the lower priority process is done
+with the resource.  This is a priority inversion.  What we want to prevent
+is something called unbounded priority inversion.  That is when the high
+priority process is prevented from running by a lower priority process for
+an undetermined amount of time.
+
+The classic example of unbounded priority inversion is were you have three
+processes, let's call them processes A, B, and C, where A is the highest
+priority process, C is the lowest, and B is in between. A tries to grab a lock
+that C owns and must wait and lets C run to release the lock. But in the
+meantime, B executes, and since B is of a higher priority than C, it preempts C,
+but by doing so, it is in fact preempting A which is a higher priority process.
+Now there's no way of knowing how long A will be sleeping waiting for C
+to release the lock, because for all we know, B is a CPU hog and will
+never give C a chance to release the lock.  This is called unbounded priority
+inversion.
+
+Here's a little ASCII art to show the problem.
+
+   grab lock L1 (owned by C)
+     |
+A ---+
+        C preempted by B
+          |
+C    +----+
+
+B         +-------->
+                B now keeps A from running.
+
+
+Priority Inheritance (PI)
+-------------------------
+
+There are several ways to solve this issue, but other ways are out of scope
+for this document.  Here we only discuss PI.
+
+PI is where a process inherits the priority of another process if the other
+process blocks on a lock owned by the current process.  To make this easier
+to understand, let's use the previous example, with processes A, B, and C again.
+
+This time, when A blocks on the lock owned by C, C would inherit the priority
+of A.  So now if B becomes runnable, it would not preempt C, since C now has
+the high priority of A.  As soon as C releases the lock, it loses its
+inherited priority, and A then can continue with the resource that C had.
+
+Terminology
+-----------
+
+Here I explain some terminology that is used in this document to help describe
+the design that is used to implement PI.
+
+PI chain - The PI chain is an ordered series of locks and processes that cause
+           processes to inherit priorities from a previous process that is
+           blocked on one of its locks.  This is described in more detail
+           later in this document.
+
+mutex    - In this document, to differentiate from locks that implement
+           PI and spin locks that are used in the PI code, from now on
+           the PI locks will be called a mutex.
+
+lock     - In this document from now on, I will use the term lock when
+           referring to spin locks that are used to protect parts of the PI
+           algorithm.  These locks disable preemption for UP (when
+           CONFIG_PREEMPT is enabled) and on SMP prevents multiple CPUs from
+           entering critical sections simultaneously.
+
+spin lock - Same as lock above.
+
+waiter   - A waiter is a struct that is stored on the stack of a blocked
+           process.  Since the scope of the waiter is within the code for
+           a process being blocked on the mutex, it is fine to allocate
+           the waiter on the process's stack (local variable).  This
+           structure holds a pointer to the task, as well as the mutex that
+           the task is blocked on.  It also has the plist node structures to
+           place the task in the waiter_list of a mutex as well as the
+           pi_list of a mutex owner task (described below).
+
+           waiter is sometimes used in reference to the task that is waiting
+           on a mutex. This is the same as waiter->task.
+
+waiters  - A list of processes that are blocked on a mutex.
+
+top waiter - The highest priority process waiting on a specific mutex.
+
+top pi waiter - The highest priority process waiting on one of the mutexes
+                that a specific process owns.
+
+Note:  task and process are used interchangeably in this document, mostly to
+       differentiate between two processes that are being described together.
+
+
+PI chain
+--------
+
+The PI chain is a list of processes and mutexes that may cause priority
+inheritance to take place.  Multiple chains may converge, but a chain
+would never diverge, since a process can't be blocked on more than one
+mutex at a time.
+
+Example:
+
+   Process:  A, B, C, D, E
+   Mutexes:  L1, L2, L3, L4
+
+   A owns: L1
+           B blocked on L1
+           B owns L2
+                  C blocked on L2
+                  C owns L3
+                         D blocked on L3
+                         D owns L4
+                                E blocked on L4
+
+The chain would be:
+
+   E->L4->D->L3->C->L2->B->L1->A
+
+To show where two chains merge, we could add another process F and
+another mutex L5 where B owns L5 and F is blocked on mutex L5.
+
+The chain for F would be:
+
+   F->L5->B->L1->A
+
+Since a process may own more than one mutex, but never be blocked on more than
+one, the chains merge.
+
+Here we show both chains:
+
+   E->L4->D->L3->C->L2-+
+                       |
+                       +->B->L1->A
+                       |
+                 F->L5-+
+
+For PI to work, the processes at the right end of these chains (or we may
+also call it the Top of the chain) must be equal to or higher in priority
+than the processes to the left or below in the chain.
+
+Also since a mutex may have more than one process blocked on it, we can
+have multiple chains merge at mutexes.  If we add another process G that is
+blocked on mutex L2:
+
+  G->L2->B->L1->A
+
+And once again, to show how this can grow I will show the merging chains
+again.
+
+   E->L4->D->L3->C-+
+                   +->L2-+
+                   |     |
+                 G-+     +->B->L1->A
+                         |
+                   F->L5-+
+
+
+Plist
+-----
+
+Before I go further and talk about how the PI chain is stored through lists
+on both mutexes and processes, I'll explain the plist.  This is similar to
+the struct list_head functionality that is already in the kernel.
+The implementation of plist is out of scope for this document, but it is
+very important to understand what it does.
+
+There are a few differences between plist and list, the most important one
+being that plist is a priority sorted linked list.  This means that the
+priorities of the plist are sorted, such that it takes O(1) to retrieve the
+highest priority item in the list.  Obviously this is useful to store processes
+based on their priorities.
+
+Another difference, which is important for implementation, is that, unlike
+list, the head of the list is a different element than the nodes of a list.
+So the head of the list is declared as struct plist_head and nodes that will
+be added to the list are declared as struct plist_node.
+
+
+Mutex Waiter List
+-----------------
+
+Every mutex keeps track of all the waiters that are blocked on itself. The mutex
+has a plist to store these waiters by priority.  This list is protected by
+a spin lock that is located in the struct of the mutex. This lock is called
+wait_lock.  Since the modification of the waiter list is never done in
+interrupt context, the wait_lock can be taken without disabling interrupts.
+
+
+Task PI List
+------------
+
+To keep track of the PI chains, each process has its own PI list.  This is
+a list of all top waiters of the mutexes that are owned by the process.
+Note that this list only holds the top waiters and not all waiters that are
+blocked on mutexes owned by the process.
+
+The top of the task's PI list is always the highest priority task that
+is waiting on a mutex that is owned by the task.  So if the task has
+inherited a priority, it will always be the priority of the task that is
+at the top of this list.
+
+This list is stored in the task structure of a process as a plist called
+pi_list.  This list is protected by a spin lock also in the task structure,
+called pi_lock.  This lock may also be taken in interrupt context, so when
+locking the pi_lock, interrupts must be disabled.
+
+
+Depth of the PI Chain
+---------------------
+
+The maximum depth of the PI chain is not dynamic, and could actually be
+defined.  But is very complex to figure it out, since it depends on all
+the nesting of mutexes.  Let's look at the example where we have 3 mutexes,
+L1, L2, and L3, and four separate functions func1, func2, func3 and func4.
+The following shows a locking order of L1->L2->L3, but may not actually
+be directly nested that way.
+
+void func1(void)
+{
+	mutex_lock(L1);
+
+	/* do anything */
+
+	mutex_unlock(L1);
+}
+
+void func2(void)
+{
+	mutex_lock(L1);
+	mutex_lock(L2);
+
+	/* do something */
+
+	mutex_unlock(L2);
+	mutex_unlock(L1);
+}
+
+void func3(void)
+{
+	mutex_lock(L2);
+	mutex_lock(L3);
+
+	/* do something else */
+
+	mutex_unlock(L3);
+	mutex_unlock(L2);
+}
+
+void func4(void)
+{
+	mutex_lock(L3);
+
+	/* do something again */
+
+	mutex_unlock(L3);
+}
+
+Now we add 4 processes that run each of these functions separately.
+Processes A, B, C, and D which run functions func1, func2, func3 and func4
+respectively, and such that D runs first and A last.  With D being preempted
+in func4 in the "do something again" area, we have a locking that follows:
+
+D owns L3
+       C blocked on L3
+       C owns L2
+              B blocked on L2
+              B owns L1
+                     A blocked on L1
+
+And thus we have the chain A->L1->B->L2->C->L3->D.
+
+This gives us a PI depth of 4 (four processes), but looking at any of the
+functions individually, it seems as though they only have at most a locking
+depth of two.  So, although the locking depth is defined at compile time,
+it still is very difficult to find the possibilities of that depth.
+
+Now since mutexes can be defined by user-land applications, we don't want a DOS
+type of application that nests large amounts of mutexes to create a large
+PI chain, and have the code holding spin locks while looking at a large
+amount of data.  So to prevent this, the implementation not only implements
+a maximum lock depth, but also only holds at most two different locks at a
+time, as it walks the PI chain.  More about this below.
+
+
+Mutex owner and flags
+---------------------
+
+The mutex structure contains a pointer to the owner of the mutex.  If the
+mutex is not owned, this owner is set to NULL.  Since all architectures
+have the task structure on at least a four byte alignment (and if this is
+not true, the rtmutex.c code will be broken!), this allows for the two
+least significant bits to be used as flags.  This part is also described
+in Documentation/rt-mutex.txt, but will also be briefly described here.
+
+Bit 0 is used as the "Pending Owner" flag.  This is described later.
+Bit 1 is used as the "Has Waiters" flags.  This is also described later
+  in more detail, but is set whenever there are waiters on a mutex.
+
+
+cmpxchg Tricks
+--------------
+
+Some architectures implement an atomic cmpxchg (Compare and Exchange).  This
+is used (when applicable) to keep the fast path of grabbing and releasing
+mutexes short.
+
+cmpxchg is basically the following function performed atomically:
+
+unsigned long _cmpxchg(unsigned long *A, unsigned long *B, unsigned long *C)
+{
+        unsigned long T = *A;
+        if (*A == *B) {
+                *A = *C;
+        }
+        return T;
+}
+#define cmpxchg(a,b,c) _cmpxchg(&a,&b,&c)
+
+This is really nice to have, since it allows you to only update a variable
+if the variable is what you expect it to be.  You know if it succeeded if
+the return value (the old value of A) is equal to B.
+
+The macro rt_mutex_cmpxchg is used to try to lock and unlock mutexes. If
+the architecture does not support CMPXCHG, then this macro is simply set
+to fail every time.  But if CMPXCHG is supported, then this will
+help out extremely to keep the fast path short.
+
+The use of rt_mutex_cmpxchg with the flags in the owner field help optimize
+the system for architectures that support it.  This will also be explained
+later in this document.
+
+
+Priority adjustments
+--------------------
+
+The implementation of the PI code in rtmutex.c has several places that a
+process must adjust its priority.  With the help of the pi_list of a
+process this is rather easy to know what needs to be adjusted.
+
+The functions implementing the task adjustments are rt_mutex_adjust_prio,
+__rt_mutex_adjust_prio (same as the former, but expects the task pi_lock
+to already be taken), rt_mutex_get_prio, and rt_mutex_setprio.
+
+rt_mutex_getprio and rt_mutex_setprio are only used in __rt_mutex_adjust_prio.
+
+rt_mutex_getprio returns the priority that the task should have.  Either the
+task's own normal priority, or if a process of a higher priority is waiting on
+a mutex owned by the task, then that higher priority should be returned.
+Since the pi_list of a task holds an order by priority list of all the top
+waiters of all the mutexes that the task owns, rt_mutex_getprio simply needs
+to compare the top pi waiter to its own normal priority, and return the higher
+priority back.
+
+(Note:  if looking at the code, you will notice that the lower number of
+        prio is returned.  This is because the prio field in the task structure
+        is an inverse order of the actual priority.  So a "prio" of 5 is
+        of higher priority than a "prio" of 10.)
+
+__rt_mutex_adjust_prio examines the result of rt_mutex_getprio, and if the
+result does not equal the task's current priority, then rt_mutex_setprio
+is called to adjust the priority of the task to the new priority.
+Note that rt_mutex_setprio is defined in kernel/sched.c to implement the
+actual change in priority.
+
+It is interesting to note that __rt_mutex_adjust_prio can either increase
+or decrease the priority of the task.  In the case that a higher priority
+process has just blocked on a mutex owned by the task, __rt_mutex_adjust_prio
+would increase/boost the task's priority.  But if a higher priority task
+were for some reason to leave the mutex (timeout or signal), this same function
+would decrease/unboost the priority of the task.  That is because the pi_list
+always contains the highest priority task that is waiting on a mutex owned
+by the task, so we only need to compare the priority of that top pi waiter
+to the normal priority of the given task.
+
+
+High level overview of the PI chain walk
+----------------------------------------
+
+The PI chain walk is implemented by the function rt_mutex_adjust_prio_chain.
+
+The implementation has gone through several iterations, and has ended up
+with what we believe is the best.  It walks the PI chain by only grabbing
+at most two locks at a time, and is very efficient.
+
+The rt_mutex_adjust_prio_chain can be used either to boost or lower process
+priorities.
+
+rt_mutex_adjust_prio_chain is called with a task to be checked for PI
+(de)boosting (the owner of a mutex that a process is blocking on), a flag to
+check for deadlocking, the mutex that the task owns, and a pointer to a waiter
+that is the process's waiter struct that is blocked on the mutex (although this
+parameter may be NULL for deboosting).
+
+For this explanation, I will not mention deadlock detection. This explanation
+will try to stay at a high level.
+
+When this function is called, there are no locks held.  That also means
+that the state of the owner and lock can change when entered into this function.
+
+Before this function is called, the task has already had rt_mutex_adjust_prio
+performed on it.  This means that the task is set to the priority that it
+should be at, but the plist nodes of the task's waiter have not been updated
+with the new priorities, and that this task may not be in the proper locations
+in the pi_lists and wait_lists that the task is blocked on.  This function
+solves all that.
+
+A loop is entered, where task is the owner to be checked for PI changes that
+was passed by parameter (for the first iteration).  The pi_lock of this task is
+taken to prevent any more changes to the pi_list of the task.  This also
+prevents new tasks from completing the blocking on a mutex that is owned by this
+task.
+
+If the task is not blocked on a mutex then the loop is exited.  We are at
+the top of the PI chain.
+
+A check is now done to see if the original waiter (the process that is blocked
+on the current mutex) is the top pi waiter of the task.  That is, is this
+waiter on the top of the task's pi_list.  If it is not, it either means that
+there is another process higher in priority that is blocked on one of the
+mutexes that the task owns, or that the waiter has just woken up via a signal
+or timeout and has left the PI chain.  In either case, the loop is exited, since
+we don't need to do any more changes to the priority of the current task, or any
+task that owns a mutex that this current task is waiting on.  A priority chain
+walk is only needed when a new top pi waiter is made to a task.
+
+The next check sees if the task's waiter plist node has the priority equal to
+the priority the task is set at.  If they are equal, then we are done with
+the loop.  Remember that the function started with the priority of the
+task adjusted, but the plist nodes that hold the task in other processes
+pi_lists have not been adjusted.
+
+Next, we look at the mutex that the task is blocked on. The mutex's wait_lock
+is taken.  This is done by a spin_trylock, because the locking order of the
+pi_lock and wait_lock goes in the opposite direction. If we fail to grab the
+lock, the pi_lock is released, and we restart the loop.
+
+Now that we have both the pi_lock of the task as well as the wait_lock of
+the mutex the task is blocked on, we update the task's waiter's plist node
+that is located on the mutex's wait_list.
+
+Now we release the pi_lock of the task.
+
+Next the owner of the mutex has its pi_lock taken, so we can update the
+task's entry in the owner's pi_list.  If the task is the highest priority
+process on the mutex's wait_list, then we remove the previous top waiter
+from the owner's pi_list, and replace it with the task.
+
+Note: It is possible that the task was the current top waiter on the mutex,
+      in which case the task is not yet on the pi_list of the waiter.  This
+      is OK, since plist_del does nothing if the plist node is not on any
+      list.
+
+If the task was not the top waiter of the mutex, but it was before we
+did the priority updates, that means we are deboosting/lowering the
+task.  In this case, the task is removed from the pi_list of the owner,
+and the new top waiter is added.
+
+Lastly, we unlock both the pi_lock of the task, as well as the mutex's
+wait_lock, and continue the loop again.  On the next iteration of the
+loop, the previous owner of the mutex will be the task that will be
+processed.
+
+Note: One might think that the owner of this mutex might have changed
+      since we just grab the mutex's wait_lock. And one could be right.
+      The important thing to remember is that the owner could not have
+      become the task that is being processed in the PI chain, since
+      we have taken that task's pi_lock at the beginning of the loop.
+      So as long as there is an owner of this mutex that is not the same
+      process as the tasked being worked on, we are OK.
+
+      Looking closely at the code, one might be confused.  The check for the
+      end of the PI chain is when the task isn't blocked on anything or the
+      task's waiter structure "task" element is NULL.  This check is
+      protected only by the task's pi_lock.  But the code to unlock the mutex
+      sets the task's waiter structure "task" element to NULL with only
+      the protection of the mutex's wait_lock, which was not taken yet.
+      Isn't this a race condition if the task becomes the new owner?
+
+      The answer is No!  The trick is the spin_trylock of the mutex's
+      wait_lock.  If we fail that lock, we release the pi_lock of the
+      task and continue the loop, doing the end of PI chain check again.
+
+      In the code to release the lock, the wait_lock of the mutex is held
+      the entire time, and it is not let go when we grab the pi_lock of the
+      new owner of the mutex.  So if the switch of a new owner were to happen
+      after the check for end of the PI chain and the grabbing of the
+      wait_lock, the unlocking code would spin on the new owner's pi_lock
+      but never give up the wait_lock.  So the PI chain loop is guaranteed to
+      fail the spin_trylock on the wait_lock, release the pi_lock, and
+      try again.
+
+      If you don't quite understand the above, that's OK. You don't have to,
+      unless you really want to make a proof out of it ;)
+
+
+Pending Owners and Lock stealing
+--------------------------------
+
+One of the flags in the owner field of the mutex structure is "Pending Owner".
+What this means is that an owner was chosen by the process releasing the
+mutex, but that owner has yet to wake up and actually take the mutex.
+
+Why is this important?  Why can't we just give the mutex to another process
+and be done with it?
+
+The PI code is to help with real-time processes, and to let the highest
+priority process run as long as possible with little latencies and delays.
+If a high priority process owns a mutex that a lower priority process is
+blocked on, when the mutex is released it would be given to the lower priority
+process.  What if the higher priority process wants to take that mutex again.
+The high priority process would fail to take that mutex that it just gave up
+and it would need to boost the lower priority process to run with full
+latency of that critical section (since the low priority process just entered
+it).
+
+There's no reason a high priority process that gives up a mutex should be
+penalized if it tries to take that mutex again.  If the new owner of the
+mutex has not woken up yet, there's no reason that the higher priority process
+could not take that mutex away.
+
+To solve this, we introduced Pending Ownership and Lock Stealing.  When a
+new process is given a mutex that it was blocked on, it is only given
+pending ownership.  This means that it's the new owner, unless a higher
+priority process comes in and tries to grab that mutex.  If a higher priority
+process does come along and wants that mutex, we let the higher priority
+process "steal" the mutex from the pending owner (only if it is still pending)
+and continue with the mutex.
+
+
+Taking of a mutex (The walk through)
+------------------------------------
+
+OK, now let's take a look at the detailed walk through of what happens when
+taking a mutex.
+
+The first thing that is tried is the fast taking of the mutex.  This is
+done when we have CMPXCHG enabled (otherwise the fast taking automatically
+fails).  Only when the owner field of the mutex is NULL can the lock be
+taken with the CMPXCHG and nothing else needs to be done.
+
+If there is contention on the lock, whether it is owned or pending owner
+we go about the slow path (rt_mutex_slowlock).
+
+The slow path function is where the task's waiter structure is created on
+the stack.  This is because the waiter structure is only needed for the
+scope of this function.  The waiter structure holds the nodes to store
+the task on the wait_list of the mutex, and if need be, the pi_list of
+the owner.
+
+The wait_lock of the mutex is taken since the slow path of unlocking the
+mutex also takes this lock.
+
+We then call try_to_take_rt_mutex.  This is where the architecture that
+does not implement CMPXCHG would always grab the lock (if there's no
+contention).
+
+try_to_take_rt_mutex is used every time the task tries to grab a mutex in the
+slow path.  The first thing that is done here is an atomic setting of
+the "Has Waiters" flag of the mutex's owner field.  Yes, this could really
+be false, because if the the mutex has no owner, there are no waiters and
+the current task also won't have any waiters.  But we don't have the lock
+yet, so we assume we are going to be a waiter.  The reason for this is to
+play nice for those architectures that do have CMPXCHG.  By setting this flag
+now, the owner of the mutex can't release the mutex without going into the
+slow unlock path, and it would then need to grab the wait_lock, which this
+code currently holds.  So setting the "Has Waiters" flag forces the owner
+to synchronize with this code.
+
+Now that we know that we can't have any races with the owner releasing the
+mutex, we check to see if we can take the ownership.  This is done if the
+mutex doesn't have a owner, or if we can steal the mutex from a pending
+owner.  Let's look at the situations we have here.
+
+  1) Has owner that is pending
+  ----------------------------
+
+  The mutex has a owner, but it hasn't woken up and the mutex flag
+  "Pending Owner" is set.  The first check is to see if the owner isn't the
+  current task.  This is because this function is also used for the pending
+  owner to grab the mutex.  When a pending owner wakes up, it checks to see
+  if it can take the mutex, and this is done if the owner is already set to
+  itself.  If so, we succeed and leave the function, clearing the "Pending
+  Owner" bit.
+
+  If the pending owner is not current, we check to see if the current priority is
+  higher than the pending owner.  If not, we fail the function and return.
+
+  There's also something special about a pending owner.  That is a pending owner
+  is never blocked on a mutex.  So there is no PI chain to worry about.  It also
+  means that if the mutex doesn't have any waiters, there's no accounting needed
+  to update the pending owner's pi_list, since we only worry about processes
+  blocked on the current mutex.
+
+  If there are waiters on this mutex, and we just stole the ownership, we need
+  to take the top waiter, remove it from the pi_list of the pending owner, and
+  add it to the current pi_list.  Note that at this moment, the pending owner
+  is no longer on the list of waiters.  This is fine, since the pending owner
+  would add itself back when it realizes that it had the ownership stolen
+  from itself.  When the pending owner tries to grab the mutex, it will fail
+  in try_to_take_rt_mutex if the owner field points to another process.
+
+  2) No owner
+  -----------
+
+  If there is no owner (or we successfully stole the lock), we set the owner
+  of the mutex to current, and set the flag of "Has Waiters" if the current
+  mutex actually has waiters, or we clear the flag if it doesn't.  See, it was
+  OK that we set that flag early, since now it is cleared.
+
+  3) Failed to grab ownership
+  ---------------------------
+
+  The most interesting case is when we fail to take ownership. This means that
+  there exists an owner, or there's a pending owner with equal or higher
+  priority than the current task.
+
+We'll continue on the failed case.
+
+If the mutex has a timeout, we set up a timer to go off to break us out
+of this mutex if we failed to get it after a specified amount of time.
+
+Now we enter a loop that will continue to try to take ownership of the mutex, or
+fail from a timeout or signal.
+
+Once again we try to take the mutex.  This will usually fail the first time
+in the loop, since it had just failed to get the mutex.  But the second time
+in the loop, this would likely succeed, since the task would likely be
+the pending owner.
+
+If the mutex is TASK_INTERRUPTIBLE a check for signals and timeout is done
+here.
+
+The waiter structure has a "task" field that points to the task that is blocked
+on the mutex.  This field can be NULL the first time it goes through the loop
+or if the task is a pending owner and had it's mutex stolen.  If the "task"
+field is NULL then we need to set up the accounting for it.
+
+Task blocks on mutex
+--------------------
+
+The accounting of a mutex and process is done with the waiter structure of
+the process.  The "task" field is set to the process, and the "lock" field
+to the mutex.  The plist nodes are initialized to the processes current
+priority.
+
+Since the wait_lock was taken at the entry of the slow lock, we can safely
+add the waiter to the wait_list.  If the current process is the highest
+priority process currently waiting on this mutex, then we remove the
+previous top waiter process (if it exists) from the pi_list of the owner,
+and add the current process to that list.  Since the pi_list of the owner
+has changed, we call rt_mutex_adjust_prio on the owner to see if the owner
+should adjust its priority accordingly.
+
+If the owner is also blocked on a lock, and had its pi_list changed
+(or deadlock checking is on), we unlock the wait_lock of the mutex and go ahead
+and run rt_mutex_adjust_prio_chain on the owner, as described earlier.
+
+Now all locks are released, and if the current process is still blocked on a
+mutex (waiter "task" field is not NULL), then we go to sleep (call schedule).
+
+Waking up in the loop
+---------------------
+
+The schedule can then wake up for a few reasons.
+  1) we were given pending ownership of the mutex.
+  2) we received a signal and was TASK_INTERRUPTIBLE
+  3) we had a timeout and was TASK_INTERRUPTIBLE
+
+In any of these cases, we continue the loop and once again try to grab the
+ownership of the mutex.  If we succeed, we exit the loop, otherwise we continue
+and on signal and timeout, will exit the loop, or if we had the mutex stolen
+we just simply add ourselves back on the lists and go back to sleep.
+
+Note: For various reasons, because of timeout and signals, the steal mutex
+      algorithm needs to be careful. This is because the current process is
+      still on the wait_list. And because of dynamic changing of priorities,
+      especially on SCHED_OTHER tasks, the current process can be the
+      highest priority task on the wait_list.
+
+Failed to get mutex on Timeout or Signal
+----------------------------------------
+
+If a timeout or signal occurred, the waiter's "task" field would not be
+NULL and the task needs to be taken off the wait_list of the mutex and perhaps
+pi_list of the owner.  If this process was a high priority process, then
+the rt_mutex_adjust_prio_chain needs to be executed again on the owner,
+but this time it will be lowering the priorities.
+
+
+Unlocking the Mutex
+-------------------
+
+The unlocking of a mutex also has a fast path for those architectures with
+CMPXCHG.  Since the taking of a mutex on contention always sets the
+"Has Waiters" flag of the mutex's owner, we use this to know if we need to
+take the slow path when unlocking the mutex.  If the mutex doesn't have any
+waiters, the owner field of the mutex would equal the current process and
+the mutex can be unlocked by just replacing the owner field with NULL.
+
+If the owner field has the "Has Waiters" bit set (or CMPXCHG is not available),
+the slow unlock path is taken.
+
+The first thing done in the slow unlock path is to take the wait_lock of the
+mutex.  This synchronizes the locking and unlocking of the mutex.
+
+A check is made to see if the mutex has waiters or not.  On architectures that
+do not have CMPXCHG, this is the location that the owner of the mutex will
+determine if a waiter needs to be awoken or not.  On architectures that
+do have CMPXCHG, that check is done in the fast path, but it is still needed
+in the slow path too.  If a waiter of a mutex woke up because of a signal
+or timeout between the time the owner failed the fast path CMPXCHG check and
+the grabbing of the wait_lock, the mutex may not have any waiters, thus the
+owner still needs to make this check. If there are no waiters than the mutex
+owner field is set to NULL, the wait_lock is released and nothing more is
+needed.
+
+If there are waiters, then we need to wake one up and give that waiter
+pending ownership.
+
+On the wake up code, the pi_lock of the current owner is taken.  The top
+waiter of the lock is found and removed from the wait_list of the mutex
+as well as the pi_list of the current owner.  The task field of the new
+pending owner's waiter structure is set to NULL, and the owner field of the
+mutex is set to the new owner with the "Pending Owner" bit set, as well
+as the "Has Waiters" bit if there still are other processes blocked on the
+mutex.
+
+The pi_lock of the previous owner is released, and the new pending owner's
+pi_lock is taken.  Remember that this is the trick to prevent the race
+condition in rt_mutex_adjust_prio_chain from adding itself as a waiter
+on the mutex.
+
+We now clear the "pi_blocked_on" field of the new pending owner, and if
+the mutex still has waiters pending, we add the new top waiter to the pi_list
+of the pending owner.
+
+Finally we unlock the pi_lock of the pending owner and wake it up.
+
+
+Contact
+-------
+
+For updates on this document, please email Steven Rostedt <rostedt@goodmis.org>
+
+
+Credits
+-------
+
+Author:  Steven Rostedt <rostedt@goodmis.org>
+
+Reviewers:  Ingo Molnar, Thomas Gleixner, Thomas Duetsch, and Randy Dunlap
+
+Updates
+-------
+
+This document was originally written for 2.6.17-rc3-mm1
diff --git a/Documentation/rt-mutex.txt b/Documentation/rt-mutex.txt
new file mode 100644
index 0000000..243393d
--- /dev/null
+++ b/Documentation/rt-mutex.txt
@@ -0,0 +1,79 @@
+RT-mutex subsystem with PI support
+----------------------------------
+
+RT-mutexes with priority inheritance are used to support PI-futexes,
+which enable pthread_mutex_t priority inheritance attributes
+(PTHREAD_PRIO_INHERIT). [See Documentation/pi-futex.txt for more details
+about PI-futexes.]
+
+This technology was developed in the -rt tree and streamlined for
+pthread_mutex support.
+
+Basic principles:
+-----------------
+
+RT-mutexes extend the semantics of simple mutexes by the priority
+inheritance protocol.
+
+A low priority owner of a rt-mutex inherits the priority of a higher
+priority waiter until the rt-mutex is released. If the temporarily
+boosted owner blocks on a rt-mutex itself it propagates the priority
+boosting to the owner of the other rt_mutex it gets blocked on. The
+priority boosting is immediately removed once the rt_mutex has been
+unlocked.
+
+This approach allows us to shorten the block of high-prio tasks on
+mutexes which protect shared resources. Priority inheritance is not a
+magic bullet for poorly designed applications, but it allows
+well-designed applications to use userspace locks in critical parts of
+an high priority thread, without losing determinism.
+
+The enqueueing of the waiters into the rtmutex waiter list is done in
+priority order. For same priorities FIFO order is chosen. For each
+rtmutex, only the top priority waiter is enqueued into the owner's
+priority waiters list. This list too queues in priority order. Whenever
+the top priority waiter of a task changes (for example it timed out or
+got a signal), the priority of the owner task is readjusted. [The
+priority enqueueing is handled by "plists", see include/linux/plist.h
+for more details.]
+
+RT-mutexes are optimized for fastpath operations and have no internal
+locking overhead when locking an uncontended mutex or unlocking a mutex
+without waiters. The optimized fastpath operations require cmpxchg
+support. [If that is not available then the rt-mutex internal spinlock
+is used]
+
+The state of the rt-mutex is tracked via the owner field of the rt-mutex
+structure:
+
+rt_mutex->owner holds the task_struct pointer of the owner. Bit 0 and 1
+are used to keep track of the "owner is pending" and "rtmutex has
+waiters" state.
+
+ owner		bit1	bit0
+ NULL		0	0	mutex is free (fast acquire possible)
+ NULL		0	1	invalid state
+ NULL		1	0	Transitional state*
+ NULL		1	1	invalid state
+ taskpointer	0	0	mutex is held (fast release possible)
+ taskpointer	0	1	task is pending owner
+ taskpointer	1	0	mutex is held and has waiters
+ taskpointer	1	1	task is pending owner and mutex has waiters
+
+Pending-ownership handling is a performance optimization:
+pending-ownership is assigned to the first (highest priority) waiter of
+the mutex, when the mutex is released. The thread is woken up and once
+it starts executing it can acquire the mutex. Until the mutex is taken
+by it (bit 0 is cleared) a competing higher priority thread can "steal"
+the mutex which puts the woken up thread back on the waiters list.
+
+The pending-ownership optimization is especially important for the
+uninterrupted workflow of high-prio tasks which repeatedly
+takes/releases locks that have lower-prio waiters. Without this
+optimization the higher-prio thread would ping-pong to the lower-prio
+task [because at unlock time we always assign a new owner].
+
+(*) The "mutex has waiters" bit gets set to take the lock. If the lock
+doesn't already have an owner, this bit is quickly cleared if there are
+no waiters.  So this is a transitional state to synchronize with looking
+at the owner field of the mutex and the mutex owner releasing the lock.
diff --git a/Documentation/rtc.txt b/Documentation/rtc.txt
index 95d17b3..2a58f98 100644
--- a/Documentation/rtc.txt
+++ b/Documentation/rtc.txt
@@ -44,8 +44,10 @@
 Programming and/or enabling interrupt frequencies greater than 64Hz is
 only allowed by root. This is perhaps a bit conservative, but we don't want
 an evil user generating lots of IRQs on a slow 386sx-16, where it might have
-a negative impact on performance.  Note that the interrupt handler is only
-a few lines of code to minimize any possibility of this effect.
+a negative impact on performance. This 64Hz limit can be changed by writing
+a different value to /proc/sys/dev/rtc/max-user-freq. Note that the
+interrupt handler is only a few lines of code to minimize any possibility
+of this effect.
 
 Also, if the kernel time is synchronized with an external source, the 
 kernel will write the time back to the CMOS clock every 11 minutes. In 
@@ -81,6 +83,7 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <linux/rtc.h>
 #include <sys/ioctl.h>
 #include <sys/time.h>
diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX
index e7da8c3a..1235483 100644
--- a/Documentation/scsi/00-INDEX
+++ b/Documentation/scsi/00-INDEX
@@ -30,8 +30,6 @@
 	- info on driver for Adaptec controllers
 aic7xxx_old.txt
 	- info on driver for Adaptec controllers, old generation
-cpqfc.txt
-	- info on driver for Compaq Tachyon TS adapters
 dpti.txt
 	- info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters
 dtc3x80.txt
diff --git a/Documentation/scsi/ChangeLog.megaraid_sas b/Documentation/scsi/ChangeLog.megaraid_sas
index 2dafa63..0a85a7e 100644
--- a/Documentation/scsi/ChangeLog.megaraid_sas
+++ b/Documentation/scsi/ChangeLog.megaraid_sas
@@ -1,3 +1,16 @@
+
+1 Release Date    : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
+2 Current Version : 00.00.02.04
+3 Older Version   : 00.00.02.04 
+
+i.	Remove superflous instance_lock
+
+	gets rid of the otherwise superflous instance_lock and avoids an unsave 
+	unsynchronized access in the error handler.
+
+		- Christoph Hellwig <hch@lst.de>
+
+
 1 Release Date    : Wed Feb 03 14:31:44 PST 2006 - Sumant Patro <Sumant.Patro@lsil.com>
 2 Current Version : 00.00.02.04
 3 Older Version   : 00.00.02.04 
diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
index 820fd07..be55670 100644
--- a/Documentation/scsi/aacraid.txt
+++ b/Documentation/scsi/aacraid.txt
@@ -24,10 +24,10 @@
 	9005:0285:9005:0296	Adaptec	2240S (SabreExpress)
 	9005:0285:9005:0290	Adaptec	2410SA (Jaguar)
 	9005:0285:9005:0293	Adaptec 21610SA (Corsair-16)
-	9005:0285:103c:3227	Adaptec 2610SA (Bearcat)
+	9005:0285:103c:3227	Adaptec 2610SA (Bearcat HP release)
 	9005:0285:9005:0292	Adaptec	2810SA (Corsair-8)
 	9005:0285:9005:0294	Adaptec	Prowler
-	9005:0286:9005:029d	Adaptec	2420SA (Intruder)
+	9005:0286:9005:029d	Adaptec	2420SA (Intruder HP release)
 	9005:0286:9005:029c	Adaptec	2620SA (Intruder)
 	9005:0286:9005:029b	Adaptec	2820SA (Intruder)
 	9005:0286:9005:02a7	Adaptec	2830SA (Skyray)
@@ -38,7 +38,7 @@
 	9005:0285:9005:0297	Adaptec	4005SAS (AvonPark)
 	9005:0285:9005:0299	Adaptec	4800SAS (Marauder-X)
 	9005:0285:9005:029a	Adaptec	4805SAS (Marauder-E)
-	9005:0286:9005:02a2	Adaptec	4810SAS (Hurricane)
+	9005:0286:9005:02a2	Adaptec	3800SAS (Hurricane44)
 	1011:0046:9005:0364	Adaptec	5400S (Mustang)
 	1011:0046:9005:0365	Adaptec	5400S (Mustang)
 	9005:0283:9005:0283	Adaptec	Catapult (3210S with arc firmware)
@@ -72,7 +72,7 @@
 	9005:0286:9005:02a1	ICP	ICP9087MA (Lancer)
 	9005:0286:9005:02a4	ICP	ICP9085LI (Marauder-X)
 	9005:0286:9005:02a5	ICP	ICP5085BR (Marauder-E)
-	9005:0286:9005:02a3	ICP	ICP5085AU (Hurricane)
+	9005:0286:9005:02a3	ICP	ICP5445AU (Hurricane44)
 	9005:0286:9005:02a6	ICP	ICP9067MA (Intruder-6)
 	9005:0286:9005:02a9	ICP	ICP5087AU (Skyray)
 	9005:0286:9005:02aa	ICP	ICP5047AU (Skyray)
diff --git a/Documentation/scsi/cpqfc.txt b/Documentation/scsi/cpqfc.txt
deleted file mode 100644
index dd33e61..0000000
--- a/Documentation/scsi/cpqfc.txt
+++ /dev/null
@@ -1,272 +0,0 @@
-Notes for CPQFCTS driver for Compaq Tachyon TS
-Fibre Channel Host Bus Adapter, PCI 64-bit, 66MHz
-for Linux (RH 6.1, 6.2 kernel 2.2.12-32, 2.2.14-5)
-SMP tested
-Tested in single and dual HBA configuration, 32 and 64bit busses,
-33 and 66MHz.  Only supports FC-AL.
-SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc() 
-	max of 128k bytes contiguous.
-
-Ver 2.5.4  Oct 03, 2002
-   * fixed memcpy of sense buffer in ioctl to copy the smaller defined size
-Ver 2.5.3  Aug 01, 2002
-   * fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer
-Ver 2.5.1  Jul 30, 2002
-   * fix ioctl to pay attention to the specified LUN.
-Ver 2.5.0  Nov 29, 2001
-   * eliminated io_request_lock.  This change makes the driver specific
-     to the 2.5.x kernels.
-   * silenced excessively noisy printks.
-
-Ver 2.1.2  July 23, 2002
-   * initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index)
-
-Ver 2.1.1  Oct 18, 2001
-   * reinitialize Cmnd->SCp.sent_command (used to identify commands as
-     passthrus) on calling scsi_done, since the scsi mid layer does not
-     use (or reinitialize) this field to prevent subsequent comands from
-     having it set incorrectly. 
-
-Ver 2.1.0  Aug 27, 2001
-   * Revise driver to use new kernel 2.4.x PCI DMA API, instead of 
-     virt_to_bus().  (enables driver to work w/ ia64 systems with >2Gb RAM.)
-     Rework main scatter-gather code to handle cases where SG element
-     lengths are larger than 0x7FFFF bytes and use as many scatter 
-     gather pages as necessary. (Steve Cameron)
-   * Makefile changes to bring cpqfc into line w/ rest of SCSI drivers
-     (thanks to Keith Owens)
-
-Ver 2.0.5  Aug 06, 2001
-   * Reject non-existent luns in the driver rather than letting the 
-     hardware do it.  (some HW behaves differently than others in this area.)
-   * Changed Makefile to rely on "make dep" instead of explicit dependencies
-   * ifdef'ed out fibre channel analyzer triggering debug code
-   * fixed a jiffies wrapping issue
-
-Ver 2.0.4  Aug 01, 2001
-   * Incorporated fix for target device reset from Steeleye
-   * Fixed passthrough ioctl so it doesn't hang.
-   * Fixed hang in launch_FCworker_thread() that occurred on some machines.
-   * Avoid problem when number of volumes in a single cabinet > 8
-
-Ver 2.0.2  July 23, 2001
-   Changed the semiphore changes so the driver would compile in 2.4.7. 
-   This version is for 2.4.7 and beyond. 
- 
-Ver 2.0.1  May 	7, 2001
-   Merged version 1.3.6 fixes into version 2.0.0.   
-
-Ver 2.0.0  May   7, 2001
-  Fixed problem so spinlock is being initialized to UNLOCKED. 
-  Fixed updated driver so it compiles in the 2.4 tree. 
- 
- Ver 1.3.6  Feb  27, 2001
-   Added Target_Device_Reset function for SCSI error handling
-   Fixed problem with not reseting addressing mode after implicit logout
- 
-
-Ver 1.3.4  Sep   7, 2000
-  Added Modinfo information
-  Fixed problem with statically linking the driver
-
-Ver 1.3.3, Aug  23, 2000
-  Fixed device/function number in ioctl
-
-Ver 1.3.2, July 27, 2000
-  Add include for Alpha compile on 2.2.14 kernel (cpq*i2c.c)
-  Change logic for different FCP-RSP sense_buffer location for HSG80 target
-  And search for Agilent Tachyon XL2 HBAs (not finished! - in test)
-
-Tested with 
-(storage):
-           Compaq RA-4x000, RAID firmware ver 2.40 - 2.54
-           Seagate FC drives model ST39102FC, rev 0006
-           Hitachi DK31CJ-72FC rev J8A8
-           IBM DDYF-T18350R rev F60K
-           Compaq FC-SCSI bridge w/ DLT 35/70 Gb DLT (tape)
-(servers):
-           Compaq PL-1850R
-           Compaq PL-6500 Xeon (400MHz)
-	   Compaq PL-8500 (500MHz, 66MHz, 64bit PCI)
-           Compaq Alpha DS20 (RH 6.1)
-(hubs):
-           Vixel Rapport 1000 (7-port "dumb")
-	   Gadzoox Gibralter (12-port "dumb")
-	   Gadzoox Capellix 2000, 3000 
-(switches):
-           Brocade 2010, 2400, 2800, rev 2.0.3a (& later)
-           Gadzoox 3210 (Fabric blade beta)
-           Vixel 7100 (Fabric beta firmare - known hot plug issues)
-using "qa_test" (esp. io_test script) suite modified from Unix tests.
-	
-Installation:
-make menuconfig
-  (select SCSI low-level, Compaq FC HBA)
-make modules
-make modules_install
-
-e.g. insmod -f cpqfc
-
-Due to Fabric/switch delays, driver requires 4 seconds 
-to initialize.  If adapters are found, there will be a entries at
-/proc/scsi/cpqfcTS/*
-
-sample contents of startup messages
-
-*************************
- scsi_register allocating 3596 bytes for CPQFCHBA
- ioremap'd Membase: c887e600
-  HBA Tachyon RevId 1.2
-Allocating 119808 for 576 Exchanges @ c0dc0000
-Allocating 112904 for LinkQ @ c0c20000 (576 elements)
-Allocating 110600 for TachSEST for 512 Exchanges
-  cpqfcTS: writing IMQ BASE 7C0000h    PI 7C4000h
-  cpqfcTS: SEST c0e40000(virt): Wrote base E40000h @ c887e740
-cpqfcTS: New FC port 0000E8h WWN: 500507650642499D SCSI Chan/Trgt 0/0
-cpqfcTS: New FC port 0000EFh WWN: 50000E100000D5A6 SCSI Chan/Trgt 0/1
-cpqfcTS: New FC port 0000E4h WWN: 21000020370097BB SCSI Chan/Trgt 0/2
-cpqfcTS: New FC port 0000E2h WWN: 2100002037009946 SCSI Chan/Trgt 0/3
-cpqfcTS: New FC port 0000E1h WWN: 21000020370098FE SCSI Chan/Trgt 0/4
-cpqfcTS: New FC port 0000E0h WWN: 21000020370097B2 SCSI Chan/Trgt 0/5
-cpqfcTS: New FC port 0000DCh WWN: 2100002037006CC1 SCSI Chan/Trgt 0/6
-cpqfcTS: New FC port 0000DAh WWN: 21000020370059F6 SCSI Chan/Trgt 0/7
-cpqfcTS: New FC port 00000Fh WWN: 500805F1FADB0E20 SCSI Chan/Trgt 0/8
-cpqfcTS: New FC port 000008h WWN: 500805F1FADB0EBA SCSI Chan/Trgt 0/9
-cpqfcTS: New FC port 000004h WWN: 500805F1FADB1EB9 SCSI Chan/Trgt 0/10
-cpqfcTS: New FC port 000002h WWN: 500805F1FADB1ADE SCSI Chan/Trgt 0/11
-cpqfcTS: New FC port 000001h WWN: 500805F1FADBA2CA SCSI Chan/Trgt 0/12
-scsi4 : Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2: WWN 500508B200193F50
- on PCI bus 0 device 0xa0fc irq 5 IObaseL 0x3400, MEMBASE 0xc6ef8600
-PCI bus width 32 bits, bus speed 33 MHz
-FCP-SCSI Driver v1.3.0
-GBIC detected: Short-wave.  LPSM 0h Monitor
-scsi : 5 hosts.
-  Vendor: IBM       Model: DDYF-T18350R      Rev: F60K
-  Type:   Direct-Access                      ANSI SCSI revision: 03
-Detected scsi disk sdb at scsi4, channel 0, id 0, lun 0
-  Vendor: HITACHI   Model: DK31CJ-72FC       Rev: J8A8
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdc at scsi4, channel 0, id 1, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdd at scsi4, channel 0, id 2, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sde at scsi4, channel 0, id 3, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdf at scsi4, channel 0, id 4, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdg at scsi4, channel 0, id 5, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdh at scsi4, channel 0, id 6, lun 0
-  Vendor: SEAGATE   Model: ST39102FC         Rev: 0006
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdi at scsi4, channel 0, id 7, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.48
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdj at scsi4, channel 0, id 8, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.48
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdk at scsi4, channel 0, id 8, lun 1
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.40
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdl at scsi4, channel 0, id 9, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.40
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdm at scsi4, channel 0, id 9, lun 1
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdn at scsi4, channel 0, id 10, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdo at scsi4, channel 0, id 11, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdp at scsi4, channel 0, id 11, lun 1
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdq at scsi4, channel 0, id 12, lun 0
-  Vendor: COMPAQ    Model: LOGICAL VOLUME    Rev: 2.54
-  Type:   Direct-Access                      ANSI SCSI revision: 02
-Detected scsi disk sdr at scsi4, channel 0, id 12, lun 1
-resize_dma_pool: unknown device type 12
-resize_dma_pool: unknown device type 12
-SCSI device sdb: hdwr sector= 512 bytes. Sectors= 35843670 [17501 MB] [17.5 GB]
- sdb: sdb1
-SCSI device sdc: hdwr sector= 512 bytes. Sectors= 144410880 [70513 MB] [70.5 GB]
- sdc: sdc1
-SCSI device sdd: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdd: sdd1
-SCSI device sde: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sde: sde1
-SCSI device sdf: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdf: sdf1
-SCSI device sdg: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdg: sdg1
-SCSI device sdh: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdh: sdh1
-SCSI device sdi: hdwr sector= 512 bytes. Sectors= 17783240 [8683 MB] [8.7 GB]
- sdi: sdi1
-SCSI device sdj: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB]
- sdj: sdj1
-SCSI device sdk: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB]
- sdk: sdk1
-SCSI device sdl: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdl: sdl1
-SCSI device sdm: hdwr sector= 512 bytes. Sectors= 8380320 [4091 MB] [4.1 GB]
- sdm: sdm1
-SCSI device sdn: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdn: sdn1
-SCSI device sdo: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdo: sdo1
-SCSI device sdp: hdwr sector= 512 bytes. Sectors= 17764320 [8673 MB] [8.7 GB]
- sdp: sdp1
-SCSI device sdq: hdwr sector= 512 bytes. Sectors= 2056160 [1003 MB] [1.0 GB]
- sdq: sdq1
-SCSI device sdr: hdwr sector= 512 bytes. Sectors= 2052736 [1002 MB] [1.0 GB]
- sdr: sdr1
-
-*************************
-
-If a GBIC of type Short-wave, Long-wave, or Copper is detected, it will
-print out; otherwise, "none" is displayed.  If the cabling is correct
-and a loop circuit is completed, you should see "Monitor"; otherwise, 
-"LoopFail" (on open circuit) or some LPSM number/state with bit 3 set.
-
-
-ERRATA:
-1. Normally, Linux Scsi queries FC devices with INQUIRY strings.  All LUNs
-found according to INQUIRY should get READ commands at sector 0 to find
-partition table, etc.  Older kernels only query the first 4 devices.  Some
-Linux kernels only look for one LUN per target (i.e. FC device).
-
-2. Physically removing a device, or a malfunctioning system which hides a
-device, leads to a 30-second timeout and subsequent _abort call.  
-In some process contexts, this will hang the kernel (crashing the system).
-Single bit errors in frames and virtually all hot plugging events are 
-gracefully handled with internal driver timer and Abort processing.
-
-3. Some SCSI drives with error conditions will not handle the 7 second timeout
-in this software driver, leading to infinite retries on timed out SCSI commands.
-The 7 secs balances the need to quickly recover from lost frames (esp. on sequence
-initiatives) and time needed by older/slower/error-state drives in responding.
-This can be easily changed in "Exchanges[].timeOut".
-
-4. Due to the nature of FC soft addressing, there is no assurance that the 
-same LUNs (drives) will have the same path (e.g. /dev/sdb1) from one boot to
-next.  Dynamic soft address changes (i.e. 24-bit FC port_id) are
-supported during run time (e.g. due to hot plug event) by the use of WWN to
-SCSI Nexus (channel/target/LUN) mapping.
-
-5. Compaq RA4x00 firmware version 2.54 and later supports SSP (Selective 
-Storage Presentation), which maps LUNs to a WWN.  If RA4x00 firmware prior
-2.54 (e.g. older controller) is used, or the FC HBA is replaced (another WWN
-is used), logical volumes on the RA4x00 will no longer be visible.
-
-
-Send questions/comments to:
-Amy Vanzant-Hodge (fibrechannel@compaq.com)
-
diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.txt
new file mode 100644
index 0000000..d28a312
--- /dev/null
+++ b/Documentation/scsi/hptiop.txt
@@ -0,0 +1,92 @@
+HIGHPOINT ROCKETRAID 3xxx RAID DRIVER (hptiop)
+
+Controller Register Map
+-------------------------
+
+The controller IOP is accessed via PCI BAR0.
+
+     BAR0 offset    Register
+            0x10    Inbound Message Register 0
+            0x14    Inbound Message Register 1
+            0x18    Outbound Message Register 0
+            0x1C    Outbound Message Register 1
+            0x20    Inbound Doorbell Register
+            0x24    Inbound Interrupt Status Register
+            0x28    Inbound Interrupt Mask Register
+            0x30    Outbound Interrupt Status Register
+            0x34    Outbound Interrupt Mask Register
+            0x40    Inbound Queue Port
+            0x44    Outbound Queue Port
+
+
+I/O Request Workflow
+----------------------
+
+All queued requests are handled via inbound/outbound queue port.
+A request packet can be allocated in either IOP or host memory.
+
+To send a request to the controller:
+
+    - Get a free request packet by reading the inbound queue port or
+      allocate a free request in host DMA coherent memory.
+
+      The value returned from the inbound queue port is an offset
+      relative to the IOP BAR0.
+
+      Requests allocated in host memory must be aligned on 32-bytes boundary.
+
+    - Fill the packet.
+
+    - Post the packet to IOP by writing it to inbound queue. For requests
+      allocated in IOP memory, write the offset to inbound queue port. For
+      requests allocated in host memory, write (0x80000000|(bus_addr>>5))
+      to the inbound queue port.
+
+    - The IOP process the request. When the request is completed, it
+      will be put into outbound queue. An outbound interrupt will be
+      generated.
+
+      For requests allocated in IOP memory, the request offset is posted to
+      outbound queue.
+
+      For requests allocated in host memory, (0x80000000|(bus_addr>>5))
+      is posted to the outbound queue. If IOP_REQUEST_FLAG_OUTPUT_CONTEXT
+      flag is set in the request, the low 32-bit context value will be
+      posted instead.
+
+    - The host read the outbound queue and complete the request.
+
+      For requests allocated in IOP memory, the host driver free the request
+      by writing it to the outbound queue.
+
+Non-queued requests (reset/flush etc) can be sent via inbound message
+register 0. An outbound message with the same value indicates the completion
+of an inbound message.
+
+
+User-level Interface
+---------------------
+
+The driver exposes following sysfs attributes:
+
+     NAME                 R/W    Description
+     driver-version        R     driver version string
+     firmware-version      R     firmware version string
+
+The driver registers char device "hptiop" to communicate with HighPoint RAID
+management software. Its ioctl routine acts as a general binary interface 
+between the IOP firmware and HighPoint RAID management software. New management
+functions can be implemented in application/firmware without modification
+in driver code.
+
+
+-----------------------------------------------------------------------------
+Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved.
+
+  This file is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  linux@highpoint-tech.com
+  http://www.highpoint-tech.com
diff --git a/Documentation/scsi/ppa.txt b/Documentation/scsi/ppa.txt
index 0dac88d..5d9223b 100644
--- a/Documentation/scsi/ppa.txt
+++ b/Documentation/scsi/ppa.txt
@@ -12,5 +12,3 @@
 Email list for Linux Parport
 linux-parport@torque.net
 
-Email for problems with ZIP or ZIP Plus drivers
-campbell@torque.net
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 0ee2c7d..87d76a5 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -366,7 +366,9 @@
 
     Module for C-Media CMI8338 and 8738 PCI sound cards.
 
-    mpu_port	- 0x300,0x310,0x320,0x330, 0 = disable (default)
+    mpu_port	- 0x300,0x310,0x320,0x330 = legacy port,
+		  1 = integrated PCI port,
+		  0 = disable (default)
     fm_port     - 0x388 (default), 0 = disable (default)
     soft_ac3    - Software-conversion of raw SPDIF packets (model 033 only)
                   (default = 1)
@@ -468,7 +470,7 @@
 
     Module for multifunction CS5535 companion PCI device
 
-    This module supports multiple cards.
+    The power-management is supported.
 
   Module snd-dt019x
   -----------------
@@ -707,8 +709,10 @@
   Module snd-hda-intel
   --------------------
 
-    Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450,
-	       VIA VT8251/VT8237A
+    Module for Intel HD Audio (ICH6, ICH6M, ESB2, ICH7, ICH8),
+		ATI SB450, SB600, RS600,
+		VIA VT8251/VT8237A,
+		SIS966, ULI M5461
 
     model	- force the model name
     position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size)
@@ -778,6 +782,7 @@
 	AD1981
 	  basic		3-jack (default)
 	  hp		HP nx6320
+	  thinkpad	Lenovo Thinkpad T60/X60/Z60
 
 	AD1986A
 	  6stack	6-jack, separate surrounds (default)
@@ -1633,9 +1638,7 @@
 
     About capture IBL, see the description of snd-vx222 module.
 
-    Note: the driver is build only when CONFIG_ISA is set.
-    
-    Note2: snd-vxp440 driver is merged to snd-vxpocket driver since
+    Note: snd-vxp440 driver is merged to snd-vxpocket driver since
            ALSA 1.0.10.
 
     The power-management is supported.
@@ -1662,8 +1665,6 @@
 
     Module for Sound Core PDAudioCF sound card.
 
-    Note: the driver is build only when CONFIG_ISA is set.
-
     The power-management is supported.
 
 
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index 1faf763..635cbb9 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -4215,7 +4215,7 @@
           <programlisting>
 <![CDATA[
   struct snd_rawmidi *rmidi;
-  snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, integrated,
+  snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port, info_flags,
                       irq, irq_flags, &rmidi);
 ]]>
           </programlisting>
@@ -4242,15 +4242,36 @@
       </para>
 
       <para>
+	The 5th argument is bitflags for additional information.
         When the i/o port address above is a part of the PCI i/o
       region, the MPU401 i/o port might have been already allocated
-      (reserved) by the driver itself. In such a case, pass non-zero
-      to the 5th argument
-      (<parameter>integrated</parameter>). Otherwise, pass 0 to it,
+      (reserved) by the driver itself. In such a case, pass a bit flag
+      <constant>MPU401_INFO_INTEGRATED</constant>,
       and 
       the mpu401-uart layer will allocate the i/o ports by itself. 
       </para>
 
+	<para>
+	When the controller supports only the input or output MIDI stream,
+	pass <constant>MPU401_INFO_INPUT</constant> or
+	<constant>MPU401_INFO_OUTPUT</constant> bitflag, respectively.
+	Then the rawmidi instance is created as a single stream.
+	</para>
+
+	<para>
+	<constant>MPU401_INFO_MMIO</constant> bitflag is used to change
+	the access method to MMIO (via readb and writeb) instead of
+	iob and outb.  In this case, you have to pass the iomapped address
+	to <function>snd_mpu401_uart_new()</function>.
+	</para>
+
+	<para>
+	When <constant>MPU401_INFO_TX_IRQ</constant> is set, the output
+	stream isn't checked in the default interrupt handler.  The driver
+	needs to call <function>snd_mpu401_uart_interrupt_tx()</function>
+	by itself to start processing the output stream in irq handler.
+	</para>
+
       <para>
         Usually, the port address corresponds to the command port and
         port + 1 corresponds to the data port. If not, you may change
@@ -5333,7 +5354,7 @@
       <informalexample>
         <programlisting>
 <![CDATA[
-  snd_info_set_text_ops(entry, chip, read_size, my_proc_read);
+  snd_info_set_text_ops(entry, chip, my_proc_read);
 ]]>
         </programlisting>
       </informalexample>
@@ -5394,7 +5415,6 @@
       <informalexample>
         <programlisting>
 <![CDATA[
-  entry->c.text.write_size = 256;
   entry->c.text.write = my_proc_write;
 ]]>
         </programlisting>
@@ -5402,22 +5422,6 @@
     </para>
 
     <para>
-    The buffer size for read is set to 1024 implicitly by
-    <function>snd_info_set_text_ops()</function>.  It should suffice
-    in most cases (the size will be aligned to
-    <constant>PAGE_SIZE</constant> anyway), but if you need to handle
-    very large text files, you can set it explicitly, too.
-
-      <informalexample>
-        <programlisting>
-<![CDATA[
-  entry->c.text.read_size = 65536;
-]]>
-        </programlisting>
-      </informalexample>
-    </para>
-
-    <para>
       For the write callback, you can use
     <function>snd_info_get_line()</function> to get a text line, and
     <function>snd_info_get_str()</function> to retrieve a string from
@@ -5562,7 +5566,7 @@
 	  power status.</para></listitem>
         <listitem><para>Call <function>snd_pcm_suspend_all()</function> to suspend the running PCM streams.</para></listitem>
 	<listitem><para>If AC97 codecs are used, call
-	<function>snd_ac97_resume()</function> for each codec.</para></listitem>
+	<function>snd_ac97_suspend()</function> for each codec.</para></listitem>
         <listitem><para>Save the register values if necessary.</para></listitem>
         <listitem><para>Stop the hardware if necessary.</para></listitem>
         <listitem><para>Disable the PCI device by calling
diff --git a/Documentation/sparc/sbus_drivers.txt b/Documentation/sparc/sbus_drivers.txt
index 876195d..4b93516 100644
--- a/Documentation/sparc/sbus_drivers.txt
+++ b/Documentation/sparc/sbus_drivers.txt
@@ -25,42 +25,84 @@
 used members of this structure, and their typical usage,
 will be detailed below.
 
-	Here is how probing is performed by an SBUS driver
-under Linux:
+	Here is a piece of skeleton code for perofming a device
+probe in an SBUS driverunder Linux:
 
-	static void init_one_mydevice(struct sbus_dev *sdev)
+	static int __devinit mydevice_probe_one(struct sbus_dev *sdev)
 	{
+		struct mysdevice *mp = kzalloc(sizeof(*mp), GFP_KERNEL);
+
+		if (!mp)
+			return -ENODEV;
+
+		...
+		dev_set_drvdata(&sdev->ofdev.dev, mp);
+		return 0;
 		...
 	}
 
-	static int mydevice_match(struct sbus_dev *sdev)
+	static int __devinit mydevice_probe(struct of_device *dev,
+				            const struct of_device_id *match)
 	{
-		if (some_criteria(sdev))
-			return 1;
-		return 0;
+		struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+
+		return mydevice_probe_one(sdev);
 	}
 
-	static void mydevice_probe(void)
+	static int __devexit mydevice_remove(struct of_device *dev)
 	{
-		struct sbus_bus *sbus;
-		struct sbus_dev *sdev;
+		struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+		struct mydevice *mp = dev_get_drvdata(&dev->dev);
 
-		for_each_sbus(sbus) {
-			for_each_sbusdev(sdev, sbus) {
-				if (mydevice_match(sdev))
-					init_one_mydevice(sdev);
-			}
-		}
+		return mydevice_remove_one(sdev, mp);
 	}
 
-	All this does is walk through all SBUS devices in the
-system, checks each to see if it is of the type which
-your driver is written for, and if so it calls the init
-routine to attach the device and prepare to drive it.
+	static struct of_device_id mydevice_match[] = {
+		{
+			.name = "mydevice",
+		},
+		{},
+	};
 
-	"init_one_mydevice" might do things like allocate software
-state structures, map in I/O registers, place the hardware
-into an initialized state, etc.
+	MODULE_DEVICE_TABLE(of, mydevice_match);
+
+	static struct of_platform_driver mydevice_driver = {
+		.name		= "mydevice",
+		.match_table	= mydevice_match,
+		.probe		= mydevice_probe,
+		.remove		= __devexit_p(mydevice_remove),
+	};
+
+	static int __init mydevice_init(void)
+	{
+		return of_register_driver(&mydevice_driver, &sbus_bus_type);
+	}
+
+	static void __exit mydevice_exit(void)
+	{
+		of_unregister_driver(&mydevice_driver);
+	}
+
+	module_init(mydevice_init);
+	module_exit(mydevice_exit);
+
+	The mydevice_match table is a series of entries which
+describes what SBUS devices your driver is meant for.  In the
+simplest case you specify a string for the 'name' field.  Every
+SBUS device with a 'name' property matching your string will
+be passed one-by-one to your .probe method.
+
+	You should store away your device private state structure
+pointer in the drvdata area so that you can retrieve it later on
+in your .remove method.
+
+	Any memory allocated, registers mapped, IRQs registered,
+etc. must be undone by your .remove method so that all resources
+of your device are relased by the time it returns.
+
+	You should _NOT_ use the for_each_sbus(), for_each_sbusdev(),
+and for_all_sbusdev() interfaces.  They are deprecated, will be
+removed, and no new driver should reference them ever.
 
 		Mapping and Accessing I/O Registers
 
@@ -263,10 +305,3 @@
 	Lance driver abuses consistent mappings for data transfer.
 It is a nifty trick which we do not particularly recommend...
 Just check it out and know that it's legal.
-
-			Bad examples, do NOT use
-
-	drivers/video/cgsix.c
-	This one uses result of sbus_ioremap as if it is an address.
-This does NOT work on sparc64 and therefore is broken. We will
-convert it at a later date.
diff --git a/Documentation/sparse.txt b/Documentation/sparse.txt
index 3f1c546..5a311c3 100644
--- a/Documentation/sparse.txt
+++ b/Documentation/sparse.txt
@@ -1,5 +1,6 @@
 Copyright 2004 Linus Torvalds
 Copyright 2004 Pavel Machek <pavel@suse.cz>
+Copyright 2006 Bob Copeland <me@bobcopeland.com>
 
 Using sparse for typechecking
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -41,15 +42,8 @@
 vs cpu-endian vs whatever), and there the constant "0" really _is_
 special.
 
-Use
-
-	make C=[12] CF=-Wbitwise
-
-or you don't get any checking at all.
-
-
-Where to get sparse
-~~~~~~~~~~~~~~~~~~~
+Getting sparse
+~~~~~~~~~~~~~~
 
 With git, you can just get it from
 
@@ -57,7 +51,7 @@
 
 and DaveJ has tar-balls at
 
-	http://www.codemonkey.org.uk/projects/git-snapshots/sparse/
+        http://www.codemonkey.org.uk/projects/git-snapshots/sparse/
 
 
 Once you have it, just do
@@ -65,8 +59,20 @@
         make
         make install
 
-as your regular user, and it will install sparse in your ~/bin directory.
-After that, doing a kernel make with "make C=1" will run sparse on all the
-C files that get recompiled, or with "make C=2" will run sparse on the
-files whether they need to be recompiled or not (ie the latter is fast way
-to check the whole tree if you have already built it).
+as a regular user, and it will install sparse in your ~/bin directory.
+
+Using sparse
+~~~~~~~~~~~~
+
+Do a kernel make with "make C=1" to run sparse on all the C files that get
+recompiled, or use "make C=2" to run sparse on the files whether they need to
+be recompiled or not.  The latter is a fast way to check the whole tree if you
+have already built it.
+
+The optional make variable CF can be used to pass arguments to sparse.  The
+build system passes -Wbitwise to sparse automatically.  To perform endianness
+checks, you may define __CHECK_ENDIAN__:
+
+        make C=2 CF="-D__CHECK_ENDIAN__"
+
+These checks are disabled by default as they generate a host of warnings.
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index a46c10f..2dc246a 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -29,6 +29,7 @@
 - drop-caches
 - zone_reclaim_mode
 - zone_reclaim_interval
+- panic_on_oom
 
 ==============================================================
 
@@ -178,3 +179,15 @@
 Reduce the interval if undesired off node allocations occur. However, too
 frequent scans will have a negative impact onoff node allocation performance.
 
+=============================================================
+
+panic_on_oom
+
+This enables or disables panic on out-of-memory feature.  If this is set to 1,
+the kernel panics when out-of-memory happens.  If this is set to 0, the kernel
+will kill some rogue process, called oom_killer.  Usually, oom_killer can kill
+rogue processes and system will survive.  If you want to panic the system
+rather than killing rogue processes, set this to 1.
+
+The default value is 0.
+
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index ad0bedf..e0188a2 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -115,8 +115,9 @@
 when you would try to login. It will kill all programs on given console
 and thus letting you make sure that the login prompt you see is actually
 the one from init, not some trojan program.
-IMPORTANT:In its true form it is not a true SAK like the one in   :IMPORTANT
-IMPORTANT:c2 compliant systems, and it should be mistook as such. :IMPORTANT
+IMPORTANT: In its true form it is not a true SAK like the one in a :IMPORTANT
+IMPORTANT: c2 compliant system, and it should not be mistaken as   :IMPORTANT
+IMPORTANT: such.                                                   :IMPORTANT
        It seems other find it useful as (System Attention Key) which is
 useful when you want to exit a program that will not let you switch consoles.
 (For example, X or a svgalib program.)
diff --git a/Documentation/tty.txt b/Documentation/tty.txt
index 8ff7bc2..dab5660 100644
--- a/Documentation/tty.txt
+++ b/Documentation/tty.txt
@@ -80,13 +80,6 @@
 			for processing. Semantics currently rather
 			mysterious 8(
 
-receive_room()	-	Can be called by the driver layer at any time when
-			the ldisc is opened. The ldisc must be able to
-			handle the reported amount of data at that instant.
-			Synchronization between active receive_buf and
-			receive_room calls is down to the driver not the
-			ldisc. Must not sleep.
-
 write_wakeup()	-	May be called at any point between open and close.
 			The TTY_DO_WRITE_WAKEUP flag indicates if a call
 			is needed but always races versus calls. Thus the
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index 63cb7ed..e65ec82 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -29,14 +29,13 @@
 
 # mount -t debugfs none_debugs /sys/kernel/debug
 # modprobe usbmon
+#
 
 Verify that bus sockets are present.
 
-[root@lembas zaitcev]# ls /sys/kernel/debug/usbmon
+# ls /sys/kernel/debug/usbmon
 1s  1t  2s  2t  3s  3t  4s  4t
-[root@lembas zaitcev]#
-
-# ls /sys/kernel
+#
 
 2. Find which bus connects to the desired device
 
@@ -76,7 +75,7 @@
 
 * Raw text data format
 
-The '0t' type data consists of a stream of events, such as URB submission,
+The '1t' type data consists of a stream of events, such as URB submission,
 URB callback, submission error. Every event is a text line, which consists
 of whitespace separated words. The number of position of words may depend
 on the event type, but there is a set of words, common for all types.
@@ -97,20 +96,25 @@
     Zi Zo   Isochronous input and output
     Ii Io   Interrupt input and output
     Bi Bo   Bulk input and output
-  Device address and Endpoint number are decimal numbers with leading zeroes
-  or 3 and 2 positions, correspondingly.
-- URB Status. This field makes no sense for submissions, but is present
-  to help scripts with parsing. In error case, it contains the error code.
-  In case of a setup packet, it contains a Setup Tag. If scripts read a number
-  in this field, they proceed to read Data Length. Otherwise, they read
-  the setup packet before reading the Data Length.
+  Device address and Endpoint number are 3-digit and 2-digit (respectively)
+  decimal numbers, with leading zeroes.
+- URB Status. In most cases, this field contains a number, sometimes negative,
+  which represents a "status" field of the URB. This field makes no sense for
+  submissions, but is present anyway to help scripts with parsing. When an
+  error occurs, the field contains the error code. In case of a submission of
+  a Control packet, this field contains a Setup Tag instead of an error code.
+  It is easy to tell whether the Setup Tag is present because it is never a
+  number. Thus if scripts find a number in this field, they proceed to read
+  Data Length. If they find something else, like a letter, they read the setup
+  packet before reading the Data Length.
 - Setup packet, if present, consists of 5 words: one of each for bmRequestType,
   bRequest, wValue, wIndex, wLength, as specified by the USB Specification 2.0.
   These words are safe to decode if Setup Tag was 's'. Otherwise, the setup
   packet was present, but not captured, and the fields contain filler.
-- Data Length. This is the actual length in the URB.
+- Data Length. For submissions, this is the requested length. For callbacks,
+  this is the actual length.
 - Data tag. The usbmon may not always capture data, even if length is nonzero.
-  Only if tag is '=', the data words are present.
+  The data words are present only if this tag is '='.
 - Data words follow, in big endian hexadecimal format. Notice that they are
   not machine words, but really just a byte stream split into words to make
   it easier to read. Thus, the last word may contain from one to four bytes.
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index b72706c..4efa464 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -87,7 +87,7 @@
  86 -> Osprey 101/151 w/ svid
  87 -> Osprey 200/201/250/251
  88 -> Osprey 200/250                                      [0070:ff01]
- 89 -> Osprey 210/220
+ 89 -> Osprey 210/220/230
  90 -> Osprey 500                                          [0070:ff02]
  91 -> Osprey 540                                          [0070:ff04]
  92 -> Osprey 2000                                         [0070:ff03]
@@ -111,7 +111,7 @@
 110 -> IVC-100                                             [ff00:a132]
 111 -> IVC-120G                                            [ff00:a182,ff01:a182,ff02:a182,ff03:a182,ff04:a182,ff05:a182,ff06:a182,ff07:a182,ff08:a182,ff09:a182,ff0a:a182,ff0b:a182,ff0c:a182,ff0d:a182,ff0e:a182,ff0f:a182]
 112 -> pcHDTV HD-2000 TV                                   [7063:2000]
-113 -> Twinhan DST + clones                                [11bd:0026,1822:0001,270f:fc00]
+113 -> Twinhan DST + clones                                [11bd:0026,1822:0001,270f:fc00,1822:0026]
 114 -> Winfast VC100                                       [107d:6607]
 115 -> Teppro TEV-560/InterVision IV-560
 116 -> SIMUS GVC1100                                       [aa6a:82b2]
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
index 3b39a91..6cb63dd 100644
--- a/Documentation/video4linux/CARDLIST.cx88
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -15,7 +15,7 @@
  14 -> KWorld/VStream XPert DVB-T                          [17de:08a6]
  15 -> DViCO FusionHDTV DVB-T1                             [18ac:db00]
  16 -> KWorld LTV883RF
- 17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810]
+ 17 -> DViCO FusionHDTV 3 Gold-Q                           [18ac:d810,18ac:d800]
  18 -> Hauppauge Nova-T DVB-T                              [0070:9002,0070:9001]
  19 -> Conexant DVB-T reference design                     [14f1:0187]
  20 -> Provideo PV259                                      [1540:2580]
@@ -40,8 +40,13 @@
  39 -> KWorld DVB-S 100                                    [17de:08b2]
  40 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid                [0070:9400,0070:9402]
  41 -> Hauppauge WinTV-HVR1100 DVB-T/Hybrid (Low Profile)  [0070:9800,0070:9802]
- 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025]
+ 42 -> digitalnow DNTV Live! DVB-T Pro                     [1822:0025,1822:0019]
  43 -> KWorld/VStream XPert DVB-T with cx22702             [17de:08a1]
  44 -> DViCO FusionHDTV DVB-T Dual Digital                 [18ac:db50,18ac:db54]
  45 -> KWorld HardwareMpegTV XPert                         [17de:0840]
  46 -> DViCO FusionHDTV DVB-T Hybrid                       [18ac:db40,18ac:db44]
+ 47 -> pcHDTV HD5500 HDTV                                  [7063:5500]
+ 48 -> Kworld MCE 200 Deluxe                               [17de:0841]
+ 49 -> PixelView PlayTV P7000                              [1554:4813]
+ 50 -> NPG Tech Real TV FM Top 10                          [14f1:0842]
+ 51 -> WinFast DTV2000 H                                   [107d:665e]
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index bca5090..9068b66 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -93,3 +93,4 @@
  92 -> AVerMedia A169 B1                        [1461:6360]
  93 -> Medion 7134 Bridge #2                    [16be:0005]
  94 -> LifeView FlyDVB-T Hybrid Cardbus         [5168:3306,5168:3502]
+ 95 -> LifeView FlyVIDEO3000 (NTSC)             [5169:0138]
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index 1bcdac6..44134f0 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -62,7 +62,7 @@
 tuner=61 - Tena TNF9533-D/IF/TNF9533-B/DF
 tuner=62 - Philips TEA5767HN FM Radio
 tuner=63 - Philips FMD1216ME MK3 Hybrid Tuner
-tuner=64 - LG TDVS-H062F/TUA6034
+tuner=64 - LG TDVS-H06xF
 tuner=65 - Ymec TVF66T5-B/DFF
 tuner=66 - LG TALN series
 tuner=67 - Philips TD1316 Hybrid Tuner
@@ -71,3 +71,4 @@
 tuner=70 - Samsung TCPN 2121P30A
 tuner=71 - Xceive xc3028
 tuner=72 - Thomson FE6600
+tuner=73 - Samsung TCPG 6121P30A
diff --git a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt
index 464e4ce..ade8651 100644
--- a/Documentation/video4linux/CQcam.txt
+++ b/Documentation/video4linux/CQcam.txt
@@ -185,207 +185,10 @@
 
 9.0 --- A sample program using v4lgrabber,
 
-This program is a simple image grabber that will copy a frame from the
+v4lgrab is a simple image grabber that will copy a frame from the
 first video device, /dev/video0 to standard output in portable pixmap
-format (.ppm)  Using this like: 'v4lgrab | convert - c-qcam.jpg'
-produced this picture of me at
-    http://mug.sys.virginia.edu/~drf5n/extras/c-qcam.jpg
-
--------------------- 8< ---------------- 8< -----------------------------
-
-/* Simple Video4Linux image grabber. */
-/*
- *	Video4Linux Driver Test/Example Framegrabbing Program
- *
- *	Compile with:
- *		gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
- *      Use as:
- *              v4lgrab >image.ppm
- *
- *	Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
- *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
- *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
- *
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/ioctl.h>
-#include <stdlib.h>
-
-#include <linux/types.h>
-#include <linux/videodev.h>
-
-#define FILE "/dev/video0"
-
-/* Stole this from tvset.c */
-
-#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
-{                                                                       \
-	switch (format)                                                 \
-	{                                                               \
-		case VIDEO_PALETTE_GREY:                                \
-			switch (depth)                                  \
-			{                                               \
-				case 4:                                 \
-				case 6:                                 \
-				case 8:                                 \
-					(r) = (g) = (b) = (*buf++ << 8);\
-					break;                          \
-									\
-				case 16:                                \
-					(r) = (g) = (b) =               \
-						*((unsigned short *) buf);      \
-					buf += 2;                       \
-					break;                          \
-			}                                               \
-			break;                                          \
-									\
-									\
-		case VIDEO_PALETTE_RGB565:                              \
-		{                                                       \
-			unsigned short tmp = *(unsigned short *)buf;    \
-			(r) = tmp&0xF800;                               \
-			(g) = (tmp<<5)&0xFC00;                          \
-			(b) = (tmp<<11)&0xF800;                         \
-			buf += 2;                                       \
-		}                                                       \
-		break;                                                  \
-									\
-		case VIDEO_PALETTE_RGB555:                              \
-			(r) = (buf[0]&0xF8)<<8;                         \
-			(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
-			(b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
-			buf += 2;                                       \
-			break;                                          \
-									\
-		case VIDEO_PALETTE_RGB24:                               \
-			(r) = buf[0] << 8; (g) = buf[1] << 8;           \
-			(b) = buf[2] << 8;                              \
-			buf += 3;                                       \
-			break;                                          \
-									\
-		default:                                                \
-			fprintf(stderr,                                 \
-				"Format %d not yet supported\n",        \
-				format);                                \
-	}                                                               \
-}
-
-int get_brightness_adj(unsigned char *image, long size, int *brightness) {
-  long i, tot = 0;
-  for (i=0;i<size*3;i++)
-    tot += image[i];
-  *brightness = (128 - tot/(size*3))/3;
-  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
-}
-
-int main(int argc, char ** argv)
-{
-  int fd = open(FILE, O_RDONLY), f;
-  struct video_capability cap;
-  struct video_window win;
-  struct video_picture vpic;
-
-  unsigned char *buffer, *src;
-  int bpp = 24, r, g, b;
-  unsigned int i, src_depth;
-
-  if (fd < 0) {
-    perror(FILE);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
-    perror("VIDIOGCAP");
-    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
-    perror("VIDIOCGWIN");
-    close(fd);
-    exit(1);
-  }
-
-  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
-    perror("VIDIOCGPICT");
-    close(fd);
-    exit(1);
-  }
-
-  if (cap.type & VID_TYPE_MONOCHROME) {
-    vpic.depth=8;
-    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.depth=6;
-      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-	vpic.depth=4;
-	if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-	  fprintf(stderr, "Unable to find a supported capture format.\n");
-	  close(fd);
-	  exit(1);
-	}
-      }
-    }
-  } else {
-    vpic.depth=24;
-    vpic.palette=VIDEO_PALETTE_RGB24;
-
-    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
-      vpic.palette=VIDEO_PALETTE_RGB565;
-      vpic.depth=16;
-
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	vpic.palette=VIDEO_PALETTE_RGB555;
-	vpic.depth=15;
-
-	if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	  fprintf(stderr, "Unable to find a supported capture format.\n");
-	  return -1;
-	}
-      }
-    }
-  }
-
-  buffer = malloc(win.width * win.height * bpp);
-  if (!buffer) {
-    fprintf(stderr, "Out of memory.\n");
-    exit(1);
-  }
-
-  do {
-    int newbright;
-    read(fd, buffer, win.width * win.height * bpp);
-    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
-    if (f) {
-      vpic.brightness += (newbright << 8);
-      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
-	perror("VIDIOSPICT");
-	break;
-      }
-    }
-  } while (f);
-
-  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
-
-  src = buffer;
-
-  for (i = 0; i < win.width * win.height; i++) {
-    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
-    fputc(r>>8, stdout);
-    fputc(g>>8, stdout);
-    fputc(b>>8, stdout);
-  }
-
-  close(fd);
-  return 0;
-}
--------------------- 8< ---------------- 8< -----------------------------
+format (.ppm)  To produce .jpg output, you can use it like this:
+'v4lgrab | convert - c-qcam.jpg'
 
 
 10.0 --- Other Information
diff --git a/Documentation/video4linux/README.pvrusb2 b/Documentation/video4linux/README.pvrusb2
new file mode 100644
index 0000000..c73a32c
--- /dev/null
+++ b/Documentation/video4linux/README.pvrusb2
@@ -0,0 +1,212 @@
+
+$Id$
+Mike Isely <isely@pobox.com>
+
+			    pvrusb2 driver
+
+Background:
+
+  This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which
+  is a USB 2.0 hosted TV Tuner.  This driver is a work in progress.
+  Its history started with the reverse-engineering effort by Björn
+  Danielsson <pvrusb2@dax.nu> whose web page can be found here:
+
+    http://pvrusb2.dax.nu/
+
+  From there Aurelien Alleaume <slts@free.fr> began an effort to
+  create a video4linux compatible driver.  I began with Aurelien's
+  last known snapshot and evolved the driver to the state it is in
+  here.
+
+  More information on this driver can be found at:
+
+    http://www.isely.net/pvrusb2.html
+
+
+  This driver has a strong separation of layers.  They are very
+  roughly:
+
+  1a. Low level wire-protocol implementation with the device.
+
+  1b. I2C adaptor implementation and corresponding I2C client drivers
+      implemented elsewhere in V4L.
+
+  1c. High level hardware driver implementation which coordinates all
+      activities that ensure correct operation of the device.
+
+  2.  A "context" layer which manages instancing of driver, setup,
+      tear-down, arbitration, and interaction with high level
+      interfaces appropriately as devices are hotplugged in the
+      system.
+
+  3.  High level interfaces which glue the driver to various published
+      Linux APIs (V4L, sysfs, maybe DVB in the future).
+
+  The most important shearing layer is between the top 2 layers.  A
+  lot of work went into the driver to ensure that any kind of
+  conceivable API can be laid on top of the core driver.  (Yes, the
+  driver internally leverages V4L to do its work but that really has
+  nothing to do with the API published by the driver to the outside
+  world.)  The architecture allows for different APIs to
+  simultaneously access the driver.  I have a strong sense of fairness
+  about APIs and also feel that it is a good design principle to keep
+  implementation and interface isolated from each other.  Thus while
+  right now the V4L high level interface is the most complete, the
+  sysfs high level interface will work equally well for similar
+  functions, and there's no reason I see right now why it shouldn't be
+  possible to produce a DVB high level interface that can sit right
+  alongside V4L.
+
+  NOTE: Complete documentation on the pvrusb2 driver is contained in
+  the html files within the doc directory; these are exactly the same
+  as what is on the web site at the time.  Browse those files
+  (especially the FAQ) before asking questions.
+
+
+Building
+
+  To build these modules essentially amounts to just running "Make",
+  but you need the kernel source tree nearby and you will likely also
+  want to set a few controlling environment variables first in order
+  to link things up with that source tree.  Please see the Makefile
+  here for comments that explain how to do that.
+
+
+Source file list / functional overview:
+
+  (Note: The term "module" used below generally refers to loosely
+  defined functional units within the pvrusb2 driver and bears no
+  relation to the Linux kernel's concept of a loadable module.)
+
+  pvrusb2-audio.[ch] - This is glue logic that resides between this
+    driver and the msp3400.ko I2C client driver (which is found
+    elsewhere in V4L).
+
+  pvrusb2-context.[ch] - This module implements the context for an
+    instance of the driver.  Everything else eventually ties back to
+    or is otherwise instanced within the data structures implemented
+    here.  Hotplugging is ultimately coordinated here.  All high level
+    interfaces tie into the driver through this module.  This module
+    helps arbitrate each interface's access to the actual driver core,
+    and is designed to allow concurrent access through multiple
+    instances of multiple interfaces (thus you can for example change
+    the tuner's frequency through sysfs while simultaneously streaming
+    video through V4L out to an instance of mplayer).
+
+  pvrusb2-debug.h - This header defines a printk() wrapper and a mask
+    of debugging bit definitions for the various kinds of debug
+    messages that can be enabled within the driver.
+
+  pvrusb2-debugifc.[ch] - This module implements a crude command line
+    oriented debug interface into the driver.  Aside from being part
+    of the process for implementing manual firmware extraction (see
+    the pvrusb2 web site mentioned earlier), probably I'm the only one
+    who has ever used this.  It is mainly a debugging aid.
+
+  pvrusb2-eeprom.[ch] - This is glue logic that resides between this
+    driver the tveeprom.ko module, which is itself implemented
+    elsewhere in V4L.
+
+  pvrusb2-encoder.[ch] - This module implements all protocol needed to
+    interact with the Conexant mpeg2 encoder chip within the pvrusb2
+    device.  It is a crude echo of corresponding logic in ivtv,
+    however the design goals (strict isolation) and physical layer
+    (proxy through USB instead of PCI) are enough different that this
+    implementation had to be completely different.
+
+  pvrusb2-hdw-internal.h - This header defines the core data structure
+    in the driver used to track ALL internal state related to control
+    of the hardware.  Nobody outside of the core hardware-handling
+    modules should have any business using this header.  All external
+    access to the driver should be through one of the high level
+    interfaces (e.g. V4L, sysfs, etc), and in fact even those high
+    level interfaces are restricted to the API defined in
+    pvrusb2-hdw.h and NOT this header.
+
+  pvrusb2-hdw.h - This header defines the full internal API for
+    controlling the hardware.  High level interfaces (e.g. V4L, sysfs)
+    will work through here.
+
+  pvrusb2-hdw.c - This module implements all the various bits of logic
+    that handle overall control of a specific pvrusb2 device.
+    (Policy, instantiation, and arbitration of pvrusb2 devices fall
+    within the jurisdiction of pvrusb-context not here).
+
+  pvrusb2-i2c-chips-*.c - These modules implement the glue logic to
+    tie together and configure various I2C modules as they attach to
+    the I2C bus.  There are two versions of this file.  The "v4l2"
+    version is intended to be used in-tree alongside V4L, where we
+    implement just the logic that makes sense for a pure V4L
+    environment.  The "all" version is intended for use outside of
+    V4L, where we might encounter other possibly "challenging" modules
+    from ivtv or older kernel snapshots (or even the support modules
+    in the standalone snapshot).
+
+  pvrusb2-i2c-cmd-v4l1.[ch] - This module implements generic V4L1
+    compatible commands to the I2C modules.  It is here where state
+    changes inside the pvrusb2 driver are translated into V4L1
+    commands that are in turn send to the various I2C modules.
+
+  pvrusb2-i2c-cmd-v4l2.[ch] - This module implements generic V4L2
+    compatible commands to the I2C modules.  It is here where state
+    changes inside the pvrusb2 driver are translated into V4L2
+    commands that are in turn send to the various I2C modules.
+
+  pvrusb2-i2c-core.[ch] - This module provides an implementation of a
+    kernel-friendly I2C adaptor driver, through which other external
+    I2C client drivers (e.g. msp3400, tuner, lirc) may connect and
+    operate corresponding chips within the the pvrusb2 device.  It is
+    through here that other V4L modules can reach into this driver to
+    operate specific pieces (and those modules are in turn driven by
+    glue logic which is coordinated by pvrusb2-hdw, doled out by
+    pvrusb2-context, and then ultimately made available to users
+    through one of the high level interfaces).
+
+  pvrusb2-io.[ch] - This module implements a very low level ring of
+    transfer buffers, required in order to stream data from the
+    device.  This module is *very* low level.  It only operates the
+    buffers and makes no attempt to define any policy or mechanism for
+    how such buffers might be used.
+
+  pvrusb2-ioread.[ch] - This module layers on top of pvrusb2-io.[ch]
+    to provide a streaming API usable by a read() system call style of
+    I/O.  Right now this is the only layer on top of pvrusb2-io.[ch],
+    however the underlying architecture here was intended to allow for
+    other styles of I/O to be implemented with additonal modules, like
+    mmap()'ed buffers or something even more exotic.
+
+  pvrusb2-main.c - This is the top level of the driver.  Module level
+    and USB core entry points are here.  This is our "main".
+
+  pvrusb2-sysfs.[ch] - This is the high level interface which ties the
+    pvrusb2 driver into sysfs.  Through this interface you can do
+    everything with the driver except actually stream data.
+
+  pvrusb2-tuner.[ch] - This is glue logic that resides between this
+    driver and the tuner.ko I2C client driver (which is found
+    elsewhere in V4L).
+
+  pvrusb2-util.h - This header defines some common macros used
+    throughout the driver.  These macros are not really specific to
+    the driver, but they had to go somewhere.
+
+  pvrusb2-v4l2.[ch] - This is the high level interface which ties the
+    pvrusb2 driver into video4linux.  It is through here that V4L
+    applications can open and operate the driver in the usual V4L
+    ways.  Note that **ALL** V4L functionality is published only
+    through here and nowhere else.
+
+  pvrusb2-video-*.[ch] - This is glue logic that resides between this
+    driver and the saa711x.ko I2C client driver (which is found
+    elsewhere in V4L).  Note that saa711x.ko used to be known as
+    saa7115.ko in ivtv.  There are two versions of this; one is
+    selected depending on the particular saa711[5x].ko that is found.
+
+  pvrusb2.h - This header contains compile time tunable parameters
+    (and at the moment the driver has very little that needs to be
+    tuned).
+
+
+  -Mike Isely
+  isely@pobox.com
+
diff --git a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran
index be9f21b..040a2c8 100644
--- a/Documentation/video4linux/Zoran
+++ b/Documentation/video4linux/Zoran
@@ -33,6 +33,21 @@
 Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
 Card number: 7
 
+AverMedia 6 Eyes AVS6EYES:
+* Zoran zr36067 PCI controller
+* Zoran zr36060 MJPEG codec
+* Samsung ks0127 TV decoder
+* Conexant bt866  TV encoder
+Drivers to use: videodev, i2c-core, i2c-algo-bit,
+		videocodec, ks0127, bt866, zr36060, zr36067
+Inputs/outputs: Six physical inputs. 1-6 are composite,
+		1-2, 3-4, 5-6 doubles as S-video,
+		1-3 triples as component.
+		One composite output.
+Norms: PAL, SECAM (720x576 @ 25 fps), NTSC (720x480 @ 29.97 fps)
+Card number: 8
+Not autodetected, card=8 is necessary.
+
 Linux Media Labs LML33:
 * Zoran zr36067 PCI controller
 * Zoran zr36060 MJPEG codec
@@ -192,6 +207,10 @@
 was introduced in 1996, is used in the DC30 and DC30+ and
 can handle: PAL B/G/H/I, PAL N, PAL M, NTSC M, NTSC 44, PAL 60, SECAM,NTSC Comb
 
+Samsung ks0127 TV decoder
+is used in the AVS6EYES card and
+can handle: NTSC-M/N/44, PAL-M/N/B/G/H/I/D/K/L and SECAM
+
 ===========================
 
 1.2 What the TV encoder can do an what not
@@ -221,6 +240,10 @@
 was introduced in 1991, is used in the DC10 old
 can generate: PAL , NTSC , SECAM
 
+Conexant bt866 TV encoder
+is used in AVS6EYES, and
+can generate: NTSC/PAL, PAL­M, PAL­N
+
 The adv717x, should be able to produce PAL N. But you find nothing PAL N
 specific in the registers. Seem that you have to reuse a other standard
 to generate PAL N, maybe it would work if you use the PAL M settings.
diff --git a/Documentation/video4linux/bttv/CONTRIBUTORS b/Documentation/video4linux/bttv/CONTRIBUTORS
index aef49db..8aad6dd 100644
--- a/Documentation/video4linux/bttv/CONTRIBUTORS
+++ b/Documentation/video4linux/bttv/CONTRIBUTORS
@@ -1,4 +1,4 @@
-Contributors to bttv: 
+Contributors to bttv:
 
 Michael Chu <mmchu@pobox.com>
   AverMedia fix and more flexible card recognition
@@ -8,8 +8,8 @@
 
 Chris Kleitsch
   Hardware I2C
-  
-Gerd Knorr <kraxel@cs.tu-berlin.de> 
+
+Gerd Knorr <kraxel@cs.tu-berlin.de>
   Radio card (ITT sound processor)
 
 bigfoot <bigfoot@net-way.net>
@@ -18,7 +18,7 @@
 
 
 + many more (please mail me if you are missing in this list and would
-             like to be mentioned)
+	     like to be mentioned)
 
 
 
diff --git a/Documentation/video4linux/cx2341x/fw-calling.txt b/Documentation/video4linux/cx2341x/fw-calling.txt
new file mode 100644
index 0000000..8d21181
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-calling.txt
@@ -0,0 +1,69 @@
+This page describes how to make calls to the firmware api.
+
+How to call
+===========
+
+The preferred calling convention is known as the firmware mailbox. The
+mailboxes are basically a fixed length array that serves as the call-stack.
+
+Firmware mailboxes can be located by searching the encoder and decoder memory
+for a 16 byte signature. That signature will be located on a 256-byte boundary.
+
+Signature:
+0x78, 0x56, 0x34, 0x12, 0x12, 0x78, 0x56, 0x34,
+0x34, 0x12, 0x78, 0x56, 0x56, 0x34, 0x12, 0x78
+
+The firmware implements 20 mailboxes of 20 32-bit words. The first 10 are
+reserved for API calls. The second 10 are used by the firmware for event
+notification.
+
+  Index  Name
+  -----  ----
+  0      Flags
+  1      Command
+  2      Return value
+  3      Timeout
+  4-19   Parameter/Result
+
+
+The flags are defined in the following table. The direction is from the
+perspective of the firmware.
+
+  Bit  Direction  Purpose
+  ---  ---------  -------
+  2    O          Firmware has processed the command.
+  1    I          Driver has finished setting the parameters.
+  0    I          Driver is using this mailbox.
+
+
+The command is a 32-bit enumerator. The API specifics may be found in the
+fw-*-api.txt documents.
+
+The return value is a 32-bit enumerator. Only two values are currently defined:
+0=success and -1=command undefined.
+
+There are 16 parameters/results 32-bit fields. The driver populates these fields
+with values for all the parameters required by the call. The driver overwrites
+these fields with result values returned by the call. The API specifics may be
+found in the fw-*-api.txt documents.
+
+The timeout value protects the card from a hung driver thread. If the driver
+doesn't handle the completed call within the timeout specified, the firmware
+will reset that mailbox.
+
+To make an API call, the driver iterates over each mailbox looking for the
+first one available (bit 0 has been cleared). The driver sets that bit, fills
+in the command enumerator, the timeout value and any required parameters. The
+driver then sets the parameter ready bit (bit 1). The firmware scans the
+mailboxes for pending commands, processes them, sets the result code, populates
+the result value array with that call's return values and sets the call
+complete bit (bit 2). Once bit 2 is set, the driver should retrieve the results
+and clear all the flags. If the driver does not perform this task within the
+time set in the timeout register, the firmware will reset that mailbox.
+
+Event notifications are sent from the firmware to the host. The host tells the
+firmware which events it is interested in via an API call. That call tells the
+firmware which notification mailbox to use. The firmware signals the host via
+an interrupt. Only the 16 Results fields are used, the Flags, Command, Return
+value and Timeout words are not used.
+
diff --git a/Documentation/video4linux/cx2341x/fw-decoder-api.txt b/Documentation/video4linux/cx2341x/fw-decoder-api.txt
new file mode 100644
index 0000000..9df4fb3
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-decoder-api.txt
@@ -0,0 +1,319 @@
+Decoder firmware API description
+================================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_PING_FW
+Enum 	0/0x00
+Description
+	This API call does nothing. It may be used to check if the firmware
+	is responding.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_START_PLAYBACK
+Enum 	1/0x01
+Description
+	Begin or resume playback.
+Param[0]
+	0 based frame number in GOP to begin playback from.
+Param[1]
+	Specifies the number of muted audio frames to play before normal
+	audio resumes.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_STOP_PLAYBACK
+Enum 	2/0x02
+Description
+	Ends playback and clears all decoder buffers. If PTS is not zero,
+	playback stops at specified PTS.
+Param[0]
+	Display 0=last frame, 1=black
+Param[1]
+	PTS low
+Param[2]
+	PTS high
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_PLAYBACK_SPEED
+Enum 	3/0x03
+Description
+	Playback stream at speed other than normal. There are two modes of
+	operation:
+	    Smooth: host transfers entire stream and firmware drops unused
+		    frames.
+	    Coarse: host drops frames based on indexing as required to achieve
+		    desired speed.
+Param[0]
+	Bitmap:
+	    0:7  0 normal
+		 1 fast only "1.5 times"
+		 n nX fast, 1/nX slow
+	    30   Framedrop:
+		     '0' during 1.5 times play, every other B frame is dropped
+		     '1' during 1.5 times play, stream is unchanged (bitrate
+			 must not exceed 8mbps)
+	    31   Speed:
+		     '0' slow
+		     '1' fast
+Param[1]
+	Direction: 0=forward, 1=reverse
+Param[2]
+	Picture mask:
+	    1=I frames
+	    3=I, P frames
+	    7=I, P, B frames
+Param[3]
+	B frames per GOP (for reverse play only)
+Param[4]
+	Mute audio: 0=disable, 1=enable
+Param[5]
+	Display 0=frame, 1=field
+Param[6]
+	Specifies the number of muted audio frames to play before normal audio
+	resumes.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_STEP_VIDEO
+Enum 	5/0x05
+Description
+	Each call to this API steps the playback to the next unit defined below
+	in the current playback direction.
+Param[0]
+	0=frame, 1=top field, 2=bottom field
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_DMA_BLOCK_SIZE
+Enum 	8/0x08
+Description
+	Set DMA transfer block size. Counterpart to API 0xC9
+Param[0]
+	DMA transfer block size in bytes. A different size may be specified
+	when issuing the DMA transfer command.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_XFER_INFO
+Enum 	9/0x09
+Description
+	This API call may be used to detect an end of stream condtion.
+Result[0]
+	Stream type
+Result[1]
+	Address offset
+Result[2]
+	Maximum bytes to transfer
+Result[3]
+	Buffer fullness
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_DMA_STATUS
+Enum 	10/0x0A
+Description
+	Status of the last DMA transfer
+Result[0]
+	Bit 1 set means transfer complete
+	Bit 2 set means DMA error
+	Bit 3 set means linked list error
+Result[1]
+	DMA type: 0=MPEG, 1=OSD, 2=YUV
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SCHED_DMA_FROM_HOST
+Enum 	11/0x0B
+Description
+	Setup DMA from host operation. Counterpart to API 0xCC
+Param[0]
+	Memory address of link list
+Param[1]
+	Total # of bytes to transfer
+Param[2]
+	DMA type (0=MPEG, 1=OSD, 2=YUV)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_PAUSE_PLAYBACK
+Enum 	13/0x0D
+Description
+	Freeze playback immediately. In this mode, when internal buffers are
+	full, no more data will be accepted and data request IRQs will be
+	masked.
+Param[0]
+	Display: 0=last frame, 1=black
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_HALT_FW
+Enum 	14/0x0E
+Description
+	The firmware is halted and no further API calls are serviced until
+	the firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_STANDARD
+Enum 	16/0x10
+Description
+	Selects display standard
+Param[0]
+	0=NTSC, 1=PAL
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_VERSION
+Enum 	17/0x11
+Description
+	Returns decoder firmware version information
+Result[0]
+	Version bitmask:
+	    Bits  0:15 build
+	    Bits 16:23 minor
+	    Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_STREAM_INPUT
+Enum 	20/0x14
+Description
+	Select decoder stream input port
+Param[0]
+	0=memory (default), 1=streaming
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_GET_TIMING_INFO
+Enum 	21/0x15
+Description
+	Returns timing information from start of playback
+Result[0]
+	Frame count by decode order
+Result[1]
+	Video PTS bits 0:31 by display order
+Result[2]
+	Video PTS bit 32 by display order
+Result[3]
+	SCR bits 0:31 by display order
+Result[4]
+	SCR bit 32 by display order
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_AUDIO_MODE
+Enum 	22/0x16
+Description
+	Select audio mode
+Param[0]
+	Dual mono mode action
+Param[1]
+	Stereo mode action:
+	    0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_EVENT_NOTIFICATION
+Enum 	23/0x17
+Description
+	Setup firmware to notify the host about a particular event.
+	Counterpart to API 0xD5
+Param[0]
+	Event: 0=Audio mode change between stereo and dual channel
+Param[1]
+	Notification 0=disabled, 1=enabled
+Param[2]
+	Interrupt bit
+Param[3]
+	Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_DISPLAY_BUFFERS
+Enum 	24/0x18
+Description
+	Number of display buffers. To decode all frames in reverse playback you
+	must use nine buffers.
+Param[0]
+	0=six buffers, 1=nine buffers
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_EXTRACT_VBI
+Enum 	25/0x19
+Description
+	Extracts VBI data
+Param[0]
+	0=extract from extension & user data, 1=extract from private packets
+Result[0]
+	VBI table location
+Result[1]
+	VBI table size
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_DECODER_SOURCE
+Enum 	26/0x1A
+Description
+	Selects decoder source. Ensure that the parameters passed to this
+	API match the encoder settings.
+Param[0]
+	Mode: 0=MPEG from host, 1=YUV from encoder, 2=YUV from host
+Param[1]
+	YUV picture width
+Param[2]
+	YUV picture height
+Param[3]
+	Bitmap: see Param[0] of API 0xBD
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_AUDIO_OUTPUT
+Enum 	27/0x1B
+Description
+	Select audio output format
+Param[0]
+	Bitmask:
+	     0:1  Data size:
+		      '00' 16 bit
+		      '01' 20 bit
+		      '10' 24 bit
+	     2:7  Unused
+	     8:9  Mode:
+		      '00' 2 channels
+		      '01' 4 channels
+		      '10' 6 channels
+		      '11' 6 channels with one line data mode
+			   (for left justified MSB first mode, 20 bit only)
+	    10:11 Unused
+	    12:13 Channel format:
+		      '00' right justified MSB first mode
+		      '01' left justified MSB first mode
+		      '10' I2S mode
+	    14:15 Unused
+	    16:21 Right justify bit count
+	    22:31 Unused
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_AV_DELAY
+Enum 	28/0x1C
+Description
+	Set audio/video delay in 90Khz ticks
+Param[0]
+	0=A/V in sync, negative=audio lags, positive=video lags
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_DEC_SET_PREBUFFERING
+Enum 	30/0x1E
+Description
+	Decoder prebuffering, when enabled up to 128KB are buffered for
+	streams <8mpbs or 640KB for streams >8mbps
+Param[0]
+	0=off, 1=on
diff --git a/Documentation/video4linux/cx2341x/fw-dma.txt b/Documentation/video4linux/cx2341x/fw-dma.txt
new file mode 100644
index 0000000..8123e26
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-dma.txt
@@ -0,0 +1,94 @@
+This page describes the structures and procedures used by the cx2341x DMA
+engine.
+
+Introduction
+============
+
+The cx2341x PCI interface is busmaster capable. This means it has a DMA
+engine to efficiently transfer large volumes of data between the card and main
+memory without requiring help from a CPU. Like most hardware, it must operate
+on contiguous physical memory. This is difficult to come by in large quantities
+on virtual memory machines.
+
+Therefore, it also supports a technique called "scatter-gather". The card can
+transfer multiple buffers in one operation. Instead of allocating one large
+contiguous buffer, the driver can allocate several smaller buffers.
+
+In practice, I've seen the average transfer to be roughly 80K, but transfers
+above 128K were not uncommon, particularly at startup. The 128K figure is
+important, because that is the largest block that the kernel can normally
+allocate. Even still, 128K blocks are hard to come by, so the driver writer is
+urged to choose a smaller block size and learn the scatter-gather technique.
+
+Mailbox #10 is reserved for DMA transfer information.
+
+Flow
+====
+
+This section describes, in general, the order of events when handling DMA
+transfers. Detailed information follows this section.
+
+- The card raises the Encoder interrupt.
+- The driver reads the transfer type, offset and size from Mailbox #10.
+- The driver constructs the scatter-gather array from enough free dma buffers
+  to cover the size.
+- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call.
+- The card raises the DMA Complete interrupt.
+- The driver checks the DMA status register for any errors.
+- The driver post-processes the newly transferred buffers.
+
+NOTE! It is possible that the Encoder and DMA Complete interrupts get raised
+simultaneously. (End of the last, start of the next, etc.)
+
+Mailbox #10
+===========
+
+The Flags, Command, Return Value and Timeout fields are ignored.
+
+Name:       Mailbox #10
+Results[0]: Type: 0: MPEG.
+Results[1]: Offset: The position relative to the card's memory space.
+Results[2]: Size: The exact number of bytes to transfer.
+
+My speculation is that since the StartCapture API has a capture type of "RAW"
+available, that the type field will have other values that correspond to YUV
+and PCM data.
+
+Scatter-Gather Array
+====================
+
+The scatter-gather array is a contiguously allocated block of memory that
+tells the card the source and destination of each data-block to transfer.
+Card "addresses" are derived from the offset supplied by Mailbox #10. Host
+addresses are the physical memory location of the target DMA buffer.
+
+Each S-G array element is a struct of three 32-bit words. The first word is
+the source address, the second is the destination address. Both take up the
+entire 32 bits. The lowest 16 bits of the third word is the transfer byte
+count. The high-bit of the third word is the "last" flag. The last-flag tells
+the card to raise the DMA_DONE interrupt. From hard personal experience, if
+you forget to set this bit, the card will still "work" but the stream will
+most likely get corrupted.
+
+The transfer count must be a multiple of 256. Therefore, the driver will need
+to track how much data in the target buffer is valid and deal with it
+accordingly.
+
+Array Element:
+
+- 32-bit Source Address
+- 32-bit Destination Address
+- 16-bit reserved (high bit is the last flag)
+- 16-bit byte count
+
+DMA Transfer Status
+===================
+
+Register 0x0004 holds the DMA Transfer Status:
+
+Bit
+4   Scatter-Gather array error
+3   DMA write error
+2   DMA read error
+1   write completed
+0   read completed
diff --git a/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/Documentation/video4linux/cx2341x/fw-encoder-api.txt
new file mode 100644
index 0000000..001c686
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-encoder-api.txt
@@ -0,0 +1,694 @@
+Encoder firmware API description
+================================
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_PING_FW
+Enum 	128/0x80
+Description
+	Does nothing. Can be used to check if the firmware is responding.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_START_CAPTURE
+Enum 	129/0x81
+Description
+	Commences the capture of video, audio and/or VBI data. All encoding
+	parameters must be initialized prior to this API call. Captures frames
+	continuously or until a predefined number of frames have been captured.
+Param[0]
+	Capture stream type:
+	    0=MPEG
+	    1=Raw
+	    2=Raw passthrough
+	    3=VBI
+
+Param[1]
+	Bitmask:
+	    Bit 0 when set, captures YUV
+	    Bit 1 when set, captures PCM audio
+	    Bit 2 when set, captures VBI (same as param[0]=3)
+	    Bit 3 when set, the capture destination is the decoder
+		(same as param[0]=2)
+	    Bit 4 when set, the capture destination is the host
+	Note: this parameter is only meaningful for RAW capture type.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_STOP_CAPTURE
+Enum 	130/0x82
+Description
+	Ends a capture in progress
+Param[0]
+	0=stop at end of GOP (generates IRQ)
+	1=stop immediate (no IRQ)
+Param[1]
+	Stream type to stop, see param[0] of API 0x81
+Param[2]
+	Subtype, see param[1] of API 0x81
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_AUDIO_ID
+Enum 	137/0x89
+Description
+	Assigns the transport stream ID of the encoded audio stream
+Param[0]
+	Audio Stream ID
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_VIDEO_ID
+Enum 	139/0x8B
+Description
+	Set video transport stream ID
+Param[0]
+	Video stream ID
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_PCR_ID
+Enum 	141/0x8D
+Description
+	Assigns the transport stream ID for PCR packets
+Param[0]
+	PCR Stream ID
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_FRAME_RATE
+Enum 	143/0x8F
+Description
+	Set video frames per second. Change occurs at start of new GOP.
+Param[0]
+	0=30fps
+	1=25fps
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_FRAME_SIZE
+Enum 	145/0x91
+Description
+	Select video stream encoding resolution.
+Param[0]
+	Height in lines. Default 480
+Param[1]
+	Width in pixels. Default 720
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_BIT_RATE
+Enum 	149/0x95
+Description
+	Assign average video stream bitrate. Note on the last three params:
+	Param[3] and [4] seem to be always 0, param [5] doesn't seem to be used.
+Param[0]
+	0=variable bitrate, 1=constant bitrate
+Param[1]
+	bitrate in bits per second
+Param[2]
+	peak bitrate in bits per second, divided by 400
+Param[3]
+	Mux bitrate in bits per second, divided by 400. May be 0 (default).
+Param[4]
+	Rate Control VBR Padding
+Param[5]
+	VBV Buffer used by encoder
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_GOP_PROPERTIES
+Enum 	151/0x97
+Description
+	Setup the GOP structure
+Param[0]
+	GOP size (maximum is 34)
+Param[1]
+	Number of B frames between the I and P frame, plus 1.
+	For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3
+	Note that GOP size must be a multiple of (B-frames + 1).
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_ASPECT_RATIO
+Enum 	153/0x99
+Description
+	Sets the encoding aspect ratio. Changes in the aspect ratio take effect
+	at the start of the next GOP.
+Param[0]
+	'0000' forbidden
+	'0001' 1:1 square
+	'0010' 4:3
+	'0011' 16:9
+	'0100' 2.21:1
+	'0101' reserved
+	 ....
+	'1111' reserved
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_DNR_FILTER_MODE
+Enum 	155/0x9B
+Description
+	Assign Dynamic Noise Reduction operating mode
+Param[0]
+	Bit0: Spatial filter, set=auto, clear=manual
+	Bit1: Temporal filter, set=auto, clear=manual
+Param[1]
+	Median filter:
+	    0=Disabled
+	    1=Horizontal
+	    2=Vertical
+	    3=Horiz/Vert
+	    4=Diagonal
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_DNR_FILTER_PROPS
+Enum 	157/0x9D
+Description
+	These Dynamic Noise Reduction filter values are only meaningful when
+	the respective filter is set to "manual" (See API 0x9B)
+Param[0]
+	Spatial filter: default 0, range 0:15
+Param[1]
+	Temporal filter: default 0, range 0:31
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_CORING_LEVELS
+Enum 	159/0x9F
+Description
+	Assign Dynamic Noise Reduction median filter properties.
+Param[0]
+	Threshold above which the luminance median filter is enabled.
+	Default: 0, range 0:255
+Param[1]
+	Threshold below which the luminance median filter is enabled.
+	Default: 255, range 0:255
+Param[2]
+	Threshold above which the chrominance median filter is enabled.
+	Default: 0, range 0:255
+Param[3]
+	Threshold below which the chrominance median filter is enabled.
+	Default: 255, range 0:255
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_SPATIAL_FILTER_TYPE
+Enum 	161/0xA1
+Description
+	Assign spatial prefilter parameters
+Param[0]
+	Luminance filter
+	    0=Off
+	    1=1D Horizontal
+	    2=1D Vertical
+	    3=2D H/V Separable (default)
+	    4=2D Symmetric non-separable
+Param[1]
+	Chrominance filter
+	    0=Off
+	    1=1D Horizontal (default)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_3_2_PULLDOWN
+Enum 	177/0xB1
+Description
+	3:2 pulldown properties
+Param[0]
+	0=enabled
+	1=disabled
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_VBI_LINE
+Enum 	183/0xB7
+Description
+	Selects VBI line number.
+Param[0]
+	Bits 0:4 	line number
+	Bit  31		0=top_field, 1=bottom_field
+	Bits 0:31 	all set specifies "all lines"
+Param[1]
+	VBI line information features: 0=disabled, 1=enabled
+Param[2]
+	Slicing: 0=None, 1=Closed Caption
+	Almost certainly not implemented. Set to 0.
+Param[3]
+	Luminance samples in this line.
+	Almost certainly not implemented. Set to 0.
+Param[4]
+	Chrominance samples in this line
+	Almost certainly not implemented. Set to 0.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_STREAM_TYPE
+Enum 	185/0xB9
+Description
+	Assign stream type
+	Note: Transport stream is not working in recent firmwares.
+	And in older firmwares the timestamps in the TS seem to be
+	unreliable.
+Param[0]
+	 0=Program stream
+	 1=Transport stream
+	 2=MPEG1 stream
+	 3=PES A/V stream
+	 5=PES Video stream
+	 7=PES Audio stream
+	10=DVD stream
+	11=VCD stream
+	12=SVCD stream
+	13=DVD_S1 stream
+	14=DVD_S2 stream
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_OUTPUT_PORT
+Enum 	187/0xBB
+Description
+	Assign stream output port. Normally 0 when the data is copied through
+	the PCI bus (DMA), and 1 when the data is streamed to another chip
+	(pvrusb and cx88-blackbird).
+Param[0]
+	0=Memory (default)
+	1=Streaming
+	2=Serial
+Param[1]
+	Unknown, but leaving this to 0 seems to work best. Indications are that
+	this might have to do with USB support, although passing anything but 0
+	onl breaks things.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_AUDIO_PROPERTIES
+Enum 	189/0xBD
+Description
+	Set audio stream properties, may be called while encoding is in progress.
+	Note: all bitfields are consistent with ISO11172 documentation except
+	bits 2:3 which ISO docs define as:
+		'11' Layer I
+		'10' Layer II
+		'01' Layer III
+		'00' Undefined
+	This discrepancy may indicate a possible error in the documentation.
+	Testing indicated that only Layer II is actually working, and that
+	the minimum bitrate should be 192 kbps.
+Param[0]
+	Bitmask:
+	   0:1  '00' 44.1Khz
+		'01' 48Khz
+		'10' 32Khz
+		'11' reserved
+
+	   2:3  '01'=Layer I
+		'10'=Layer II
+
+	   4:7  Bitrate:
+		     Index | Layer I     | Layer II
+		     ------+-------------+------------
+		    '0000' | free format | free format
+		    '0001' |  32 kbit/s  |  32 kbit/s
+		    '0010' |  64 kbit/s  |  48 kbit/s
+		    '0011' |  96 kbit/s  |  56 kbit/s
+		    '0100' | 128 kbit/s  |  64 kbit/s
+		    '0101' | 160 kbit/s  |  80 kbit/s
+		    '0110' | 192 kbit/s  |  96 kbit/s
+		    '0111' | 224 kbit/s  | 112 kbit/s
+		    '1000' | 256 kbit/s  | 128 kbit/s
+		    '1001' | 288 kbit/s  | 160 kbit/s
+		    '1010' | 320 kbit/s  | 192 kbit/s
+		    '1011' | 352 kbit/s  | 224 kbit/s
+		    '1100' | 384 kbit/s  | 256 kbit/s
+		    '1101' | 416 kbit/s  | 320 kbit/s
+		    '1110' | 448 kbit/s  | 384 kbit/s
+		Note: For Layer II, not all combinations of total bitrate
+		and mode are allowed. See ISO11172-3 3-Annex B, Table 3-B.2
+
+	   8:9  '00'=Stereo
+		'01'=JointStereo
+		'10'=Dual
+		'11'=Mono
+		Note: testing seems to indicate that Mono and possibly
+		JointStereo are not working (default to stereo).
+		Dual does work, though.
+
+	  10:11 Mode Extension used in joint_stereo mode.
+		In Layer I and II they indicate which subbands are in
+		intensity_stereo. All other subbands are coded in stereo.
+		    '00' subbands 4-31 in intensity_stereo, bound==4
+		    '01' subbands 8-31 in intensity_stereo, bound==8
+		    '10' subbands 12-31 in intensity_stereo, bound==12
+		    '11' subbands 16-31 in intensity_stereo, bound==16
+
+	  12:13 Emphasis:
+		    '00' None
+		    '01' 50/15uS
+		    '10' reserved
+		    '11' CCITT J.17
+
+	  14 	CRC:
+		    '0' off
+		    '1' on
+
+	  15    Copyright:
+		    '0' off
+		    '1' on
+
+	  16    Generation:
+		    '0' copy
+		    '1' original
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_HALT_FW
+Enum 	195/0xC3
+Description
+	The firmware is halted and no further API calls are serviced until the
+	firmware is uploaded again.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_VERSION
+Enum 	196/0xC4
+Description
+	Returns the version of the encoder firmware.
+Result[0]
+	Version bitmask:
+	    Bits  0:15 build
+	    Bits 16:23 minor
+	    Bits 24:31 major
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_GOP_CLOSURE
+Enum 	197/0xC5
+Description
+	Assigns the GOP open/close property.
+Param[0]
+	0=Open
+	1=Closed
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_SEQ_END
+Enum 	198/0xC6
+Description
+	Obtains the sequence end code of the encoder's buffer. When a capture
+	is started a number of interrupts are still generated, the last of
+	which will have Result[0] set to 1 and Result[1] will contain the size
+	of the buffer.
+Result[0]
+	State of the transfer (1 if last buffer)
+Result[1]
+	If Result[0] is 1, this contains the size of the last buffer, undefined
+	otherwise.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_PGM_INDEX_INFO
+Enum 	199/0xC7
+Description
+	Sets the Program Index Information.
+Param[0]
+	Picture Mask:
+	    0=No index capture
+	    1=I frames
+	    3=I,P frames
+	    7=I,P,B frames
+Param[1]
+	Elements requested (up to 400)
+Result[0]
+	Offset in SDF memory of the table.
+Result[1]
+	Number of allocated elements up to a maximum of Param[1]
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_VBI_CONFIG
+Enum 	200/0xC8
+Description
+	Configure VBI settings
+Param[0]
+	Bitmap:
+	    0    Mode '0' Sliced, '1' Raw
+	    1:3  Insertion:
+		     '000' insert in extension & user data
+		     '001' insert in private packets
+		     '010' separate stream and user data
+		     '111' separate stream and private data
+	    8:15 Stream ID (normally 0xBD)
+Param[1]
+	Frames per interrupt (max 8). Only valid in raw mode.
+Param[2]
+	Total raw VBI frames. Only valid in raw mode.
+Param[3]
+	Start codes
+Param[4]
+	Stop codes
+Param[5]
+	Lines per frame
+Param[6]
+	Byte per line
+Result[0]
+	Observed frames per interrupt in raw mode only. Rage 1 to Param[1]
+Result[1]
+	Observed number of frames in raw mode. Range 1 to Param[2]
+Result[2]
+	Memory offset to start or raw VBI data
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_DMA_BLOCK_SIZE
+Enum 	201/0xC9
+Description
+	Set DMA transfer block size
+Param[0]
+	DMA transfer block size in bytes or frames. When unit is bytes,
+	supported block sizes are 2^7, 2^8 and 2^9 bytes.
+Param[1]
+	Unit: 0=bytes, 1=frames
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_PREV_DMA_INFO_MB_10
+Enum 	202/0xCA
+Description
+	Returns information on the previous DMA transfer in conjunction with
+	bit 27 of the interrupt mask. Uses mailbox 10.
+Result[0]
+	Type of stream
+Result[1]
+	Address Offset
+Result[2]
+	Maximum size of transfer
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_GET_PREV_DMA_INFO_MB_9
+Enum 	203/0xCB
+Description
+	Returns information on the previous DMA transfer in conjunction with
+	bit 27 of the interrupt mask. Uses mailbox 9.
+Result[0]
+	Status bits:
+	    Bit 0 set indicates transfer complete
+	    Bit 2 set indicates transfer error
+	    Bit 4 set indicates linked list error
+Result[1]
+	DMA type
+Result[2]
+	Presentation Time Stamp bits 0..31
+Result[3]
+	Presentation Time Stamp bit 32
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SCHED_DMA_TO_HOST
+Enum 	204/0xCC
+Description
+	Setup DMA to host operation
+Param[0]
+	Memory address of link list
+Param[1]
+	Length of link list (wtf: what units ???)
+Param[2]
+	DMA type (0=MPEG)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_INITIALIZE_INPUT
+Enum 	205/0xCD
+Description
+	Initializes the video input
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_FRAME_DROP_RATE
+Enum 	208/0xD0
+Description
+	For each frame captured, skip specified number of frames.
+Param[0]
+	Number of frames to skip
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_PAUSE_ENCODER
+Enum 	210/0xD2
+Description
+	During a pause condition, all frames are dropped instead of being encoded.
+Param[0]
+	0=Pause encoding
+	1=Continue encoding
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_REFRESH_INPUT
+Enum 	211/0xD3
+Description
+	Refreshes the video input
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_COPYRIGHT
+Enum 	212/0xD4
+Description
+	Sets stream copyright property
+Param[0]
+	0=Stream is not copyrighted
+	1=Stream is copyrighted
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_EVENT_NOTIFICATION
+Enum 	213/0xD5
+Description
+	Setup firmware to notify the host about a particular event. Host must
+	unmask the interrupt bit.
+Param[0]
+	Event (0=refresh encoder input)
+Param[1]
+	Notification 0=disabled 1=enabled
+Param[2]
+	Interrupt bit
+Param[3]
+	Mailbox slot, -1 if no mailbox required.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_NUM_VSYNC_LINES
+Enum 	214/0xD6
+Description
+	Depending on the analog video decoder used, this assigns the number
+	of lines for field 1 and 2.
+Param[0]
+	Field 1 number of lines:
+	    0x00EF for SAA7114
+	    0x00F0 for SAA7115
+	    0x0105 for Micronas
+Param[1]
+	Field 2 number of lines:
+	    0x00EF for SAA7114
+	    0x00F0 for SAA7115
+	    0x0106 for Micronas
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_SET_PLACEHOLDER
+Enum 	215/0xD7
+Description
+	Provides a mechanism of inserting custom user data in the MPEG stream.
+Param[0]
+	0=extension & user data
+	1=private packet with stream ID 0xBD
+Param[1]
+	Rate at which to insert data, in units of frames (for private packet)
+	or GOPs (for ext. & user data)
+Param[2]
+	Number of data DWORDs (below) to insert
+Param[3]
+	Custom data 0
+Param[4]
+	Custom data 1
+Param[5]
+	Custom data 2
+Param[6]
+	Custom data 3
+Param[7]
+	Custom data 4
+Param[8]
+	Custom data 5
+Param[9]
+	Custom data 6
+Param[10]
+	Custom data 7
+Param[11]
+	Custom data 8
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_MUTE_VIDEO
+Enum 	217/0xD9
+Description
+	Video muting
+Param[0]
+	Bit usage:
+	 0    	'0'=video not muted
+		'1'=video muted, creates frames with the YUV color defined below
+	 1:7  	Unused
+	 8:15 	V chrominance information
+	16:23 	U chrominance information
+	24:31 	Y luminance information
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_MUTE_AUDIO
+Enum 	218/0xDA
+Description
+	Audio muting
+Param[0]
+	0=audio not muted
+	1=audio muted (produces silent mpeg audio stream)
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_UNKNOWN
+Enum 	219/0xDB
+Description
+	Unknown API, it's used by Hauppauge though.
+Param[0]
+	0 This is the value Hauppauge uses, Unknown what it means.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_ENC_MISC
+Enum 	220/0xDC
+Description
+	Miscellaneous actions. Not known for 100% what it does. It's really a
+	sort of ioctl call. The first parameter is a command number, the second
+	the value.
+Param[0]
+	Command number:
+	 1=set initial SCR value when starting encoding.
+	 2=set quality mode (apparently some test setting).
+	 3=setup advanced VIM protection handling (supposedly only for the cx23416
+	   for raw YUV).
+	   Actually it looks like this should be 0 for saa7114/5 based card and 1
+	   for cx25840 based cards.
+	 4=generate artificial PTS timestamps
+	 5=USB flush mode
+	 6=something to do with the quantization matrix
+	 7=set navigation pack insertion for DVD
+	 8=enable scene change detection (seems to be a failure)
+	 9=set history parameters of the video input module
+	10=set input field order of VIM
+	11=set quantization matrix
+	12=reset audio interface
+	13=set audio volume delay
+	14=set audio delay
+
+Param[1]
+	Command value.
diff --git a/Documentation/video4linux/cx2341x/fw-memory.txt b/Documentation/video4linux/cx2341x/fw-memory.txt
new file mode 100644
index 0000000..ef0aad3
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-memory.txt
@@ -0,0 +1,141 @@
+This document describes the cx2341x memory map and documents some of the register
+space.
+
+Warning! This information was figured out from searching through the memory and
+registers, this information may not be correct and is certainly not complete, and
+was not derived from anything more than searching through the memory space with
+commands like:
+
+	ivtvctl -O min=0x02000000,max=0x020000ff
+
+So take this as is, I'm always searching for more stuff, it's a large
+register space :-).
+
+Memory Map
+==========
+
+The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0
+(Base Address Register 0). The addresses here are offsets relative to the
+address held in BAR0.
+
+0x00000000-0x00ffffff Encoder memory space
+0x00000000-0x0003ffff Encode.rom
+      ???-???         MPEG buffer(s)
+      ???-???         Raw video capture buffer(s)
+      ???-???         Raw audio capture buffer(s)
+      ???-???         Display buffers (6 or 9)
+
+0x01000000-0x01ffffff Decoder memory space
+0x01000000-0x0103ffff Decode.rom
+      ???-???         MPEG buffers(s)
+0x0114b000-0x0115afff Audio.rom (deprecated?)
+
+0x02000000-0x0200ffff Register Space
+
+Registers
+=========
+
+The registers occupy the 64k space starting at the 0x02000000 offset from BAR0.
+All of these registers are 32 bits wide.
+
+DMA Registers 0x000-0xff:
+
+ 0x00 - Control:
+	0=reset/cancel, 1=read, 2=write, 4=stop
+ 0x04 - DMA status:
+	1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error
+ 0x08 - pci DMA pointer for read link list
+ 0x0c - pci DMA pointer for write link list
+ 0x10 - read/write DMA enable:
+	1=read enable, 2=write enable
+ 0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes
+ 0x18 - ??
+ 0x1c - always 0x20 or 32, smaller values slow down DMA transactions
+ 0x20 - always value of 0x780a010a
+ 0x24-0x3c - usually just random values???
+ 0x40 - Interrupt status
+ 0x44 - Write a bit here and shows up in Interrupt status 0x40
+ 0x48 - Interrupt Mask
+ 0x4C - always value of 0xfffdffff,
+	if changed to 0xffffffff DMA write interrupts break.
+ 0x50 - always 0xffffffff
+ 0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are
+	3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the
+	interrupt masks???).
+ 0x60-0x7C - random values
+ 0x80 - first write linked list reg, for Encoder Memory addr
+ 0x84 - first write linked list reg, for pci memory addr
+ 0x88 - first write linked list reg, for length of buffer in memory addr
+	(|0x80000000 or this for last link)
+ 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here
+	from linked list addr in reg 0x0c, firmware must push through or
+	something.
+ 0xe0 - first (and only) read linked list reg, for pci memory addr
+ 0xe4 - first (and only) read linked list reg, for Decoder memory addr
+ 0xe8 - first (and only) read linked list reg, for length of buffer
+ 0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000.
+
+Memory locations for Encoder Buffers 0x700-0x7ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for encoding, have to shift them by <<1 first.
+
+0x07F8: Encoder SDRAM refresh
+0x07FC: Encoder SDRAM pre-charge
+
+Memory locations for Decoder Buffers 0x800-0x8ff:
+
+These registers show offsets of memory locations pertaining to each
+buffer area used for decoding, have to shift them by <<1 first.
+
+0x08F8: Decoder SDRAM refresh
+0x08FC: Decoder SDRAM pre-charge
+
+Other memory locations:
+
+0x2800: Video Display Module control
+0x2D00: AO (audio output?) control
+0x2D24: Bytes Flushed
+0x7000: LSB I2C write clock bit (inverted)
+0x7004: LSB I2C write data bit (inverted)
+0x7008: LSB I2C read clock bit
+0x700c: LSB I2C read data bit
+0x9008: GPIO get input state
+0x900c: GPIO set output state
+0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output)
+0x9050: SPU control
+0x9054: Reset HW blocks
+0x9058: VPU control
+0xA018: Bit6: interrupt pending?
+0xA064: APU command
+
+
+Interrupt Status Register
+=========================
+
+The definition of the bits in the interrupt status register 0x0040, and the
+interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to
+execute.
+
+Bit
+31 Encoder Start Capture
+30 Encoder EOS
+29 Encoder VBI capture
+28 Encoder Video Input Module reset event
+27 Encoder DMA complete
+26
+25 Decoder copy protect detection event
+24 Decoder audio mode change detection event
+23
+22 Decoder data request
+21 Decoder I-Frame? done
+20 Decoder DMA complete
+19 Decoder VBI re-insertion
+18 Decoder DMA err (linked-list bad)
+
+Missing
+Encoder API call completed
+Decoder API call completed
+Encoder API post(?)
+Decoder API post(?)
+Decoder VTRACE event
diff --git a/Documentation/video4linux/cx2341x/fw-osd-api.txt b/Documentation/video4linux/cx2341x/fw-osd-api.txt
new file mode 100644
index 0000000..da98ae3
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-osd-api.txt
@@ -0,0 +1,342 @@
+OSD firmware API description
+============================
+
+Note: this API is part of the decoder firmware, so it's cx23415 only.
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_FRAMEBUFFER
+Enum 	65/0x41
+Description
+	Return base and length of contiguous OSD memory.
+Result[0]
+	OSD base address
+Result[1]
+	OSD length
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_PIXEL_FORMAT
+Enum 	66/0x42
+Description
+	Query OSD format
+Result[0]
+	0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_PIXEL_FORMAT
+Enum 	67/0x43
+Description
+	Assign pixel format
+Param[0]
+	0=8bit index, 4=AlphaRGB 8:8:8:8
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_STATE
+Enum 	68/0x44
+Description
+	Query OSD state
+Result[0]
+	Bit  0   0=off, 1=on
+	Bits 1:2 alpha control
+	Bits 3:5 pixel format
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_STATE
+Enum 	69/0x45
+Description
+	OSD switch
+Param[0]
+	0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_OSD_COORDS
+Enum 	70/0x46
+Description
+	Retrieve coordinates of OSD area blended with video
+Result[0]
+	OSD buffer address
+Result[1]
+	Stride in pixels
+Result[2]
+	Lines in OSD buffer
+Result[3]
+	Horizontal offset in buffer
+Result[4]
+	Vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_OSD_COORDS
+Enum 	71/0x47
+Description
+	Assign the coordinates of the OSD area to blend with video
+Param[0]
+	buffer address
+Param[1]
+	buffer stride in pixels
+Param[2]
+	lines in buffer
+Param[3]
+	horizontal offset
+Param[4]
+	vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_SCREEN_COORDS
+Enum 	72/0x48
+Description
+	Retrieve OSD screen area coordinates
+Result[0]
+	top left horizontal offset
+Result[1]
+	top left vertical offset
+Result[2]
+	bottom right hotizontal offset
+Result[3]
+	bottom right vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_SCREEN_COORDS
+Enum 	73/0x49
+Description
+	Assign the coordinates of the screen area to blend with video
+Param[0]
+	top left horizontal offset
+Param[1]
+	top left vertical offset
+Param[2]
+	bottom left horizontal offset
+Param[3]
+	bottom left vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_GLOBAL_ALPHA
+Enum 	74/0x4A
+Description
+	Retrieve OSD global alpha
+Result[0]
+	global alpha: 0=off, 1=on
+Result[1]
+	bits 0:7 global alpha
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_GLOBAL_ALPHA
+Enum 	75/0x4B
+Description
+	Update global alpha
+Param[0]
+	global alpha: 0=off, 1=on
+Param[1]
+	global alpha (8 bits)
+Param[2]
+	local alpha: 0=on, 1=off
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_BLEND_COORDS
+Enum 	78/0x4C
+Description
+	Move start of blending area within display buffer
+Param[0]
+	horizontal offset in buffer
+Param[1]
+	vertical offset in buffer
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_FLICKER_STATE
+Enum 	79/0x4F
+Description
+	Retrieve flicker reduction module state
+Result[0]
+	flicker state: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_FLICKER_STATE
+Enum 	80/0x50
+Description
+	Set flicker reduction module state
+Param[0]
+	State: 0=off, 1=on
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_BLT_COPY
+Enum 	82/0x52
+Description
+	BLT copy
+Param[0]
+'0000'  zero
+'0001' ~destination AND ~source
+'0010' ~destination AND  source
+'0011' ~destination
+'0100'  destination AND ~source
+'0101'                  ~source
+'0110'  destination XOR  source
+'0111' ~destination OR  ~source
+'1000' ~destination AND ~source
+'1001'  destination XNOR source
+'1010'                   source
+'1011' ~destination OR   source
+'1100'  destination
+'1101'  destination OR  ~source
+'1110'  destination OR   source
+'1111'  one
+
+Param[1]
+	Resulting alpha blending
+	    '01' source_alpha
+	    '10' destination_alpha
+	    '11' source_alpha*destination_alpha+1
+		 (zero if both source and destination alpha are zero)
+Param[2]
+	'00' output_pixel = source_pixel
+
+	'01' if source_alpha=0:
+		 output_pixel = destination_pixel
+	     if 256 > source_alpha > 1:
+		 output_pixel = ((source_alpha + 1)*source_pixel +
+				 (255 - source_alpha)*destination_pixel)/256
+
+	'10' if destination_alpha=0:
+		 output_pixel = source_pixel
+	      if 255 > destination_alpha > 0:
+		 output_pixel = ((255 - destination_alpha)*source_pixel +
+				 (destination_alpha + 1)*destination_pixel)/256
+
+	'11' if source_alpha=0:
+		 source_temp = 0
+	     if source_alpha=255:
+		 source_temp = source_pixel*256
+	     if 255 > source_alpha > 0:
+		 source_temp = source_pixel*(source_alpha + 1)
+	     if destination_alpha=0:
+		 destination_temp = 0
+	     if destination_alpha=255:
+		 destination_temp = destination_pixel*256
+	     if 255 > destination_alpha > 0:
+		 destination_temp = destination_pixel*(destination_alpha + 1)
+	     output_pixel = (source_temp + destination_temp)/256
+Param[3]
+	width
+Param[4]
+	height
+Param[5]
+	destination pixel mask
+Param[6]
+	destination rectangle start address
+Param[7]
+	destination stride in dwords
+Param[8]
+	source stride in dwords
+Param[9]
+	source rectangle start address
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_BLT_FILL
+Enum 	83/0x53
+Description
+	BLT fill color
+Param[0]
+	Same as Param[0] on API 0x52
+Param[1]
+	Same as Param[1] on API 0x52
+Param[2]
+	Same as Param[2] on API 0x52
+Param[3]
+	width
+Param[4]
+	height
+Param[5]
+	destination pixel mask
+Param[6]
+	destination rectangle start address
+Param[7]
+	destination stride in dwords
+Param[8]
+	color fill value
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_BLT_TEXT
+Enum 	84/0x54
+Description
+	BLT for 8 bit alpha text source
+Param[0]
+	Same as Param[0] on API 0x52
+Param[1]
+	Same as Param[1] on API 0x52
+Param[2]
+	Same as Param[2] on API 0x52
+Param[3]
+	width
+Param[4]
+	height
+Param[5]
+	destination pixel mask
+Param[6]
+	destination rectangle start address
+Param[7]
+	destination stride in dwords
+Param[8]
+	source stride in dwords
+Param[9]
+	source rectangle start address
+Param[10]
+	color fill value
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_FRAMEBUFFER_WINDOW
+Enum 	86/0x56
+Description
+	Positions the main output window on the screen. The coordinates must be
+	such that the entire window fits on the screen.
+Param[0]
+	window width
+Param[1]
+	window height
+Param[2]
+	top left window corner horizontal offset
+Param[3]
+	top left window corner vertical offset
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_CHROMA_KEY
+Enum 	96/0x60
+Description
+	Chroma key switch and color
+Param[0]
+	state: 0=off, 1=on
+Param[1]
+	color
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_GET_ALPHA_CONTENT_INDEX
+Enum 	97/0x61
+Description
+	Retrieve alpha content index
+Result[0]
+	alpha content index, Range 0:15
+
+-------------------------------------------------------------------------------
+
+Name 	CX2341X_OSD_SET_ALPHA_CONTENT_INDEX
+Enum 	98/0x62
+Description
+	Assign alpha content index
+Param[0]
+	alpha content index, range 0:15
diff --git a/Documentation/video4linux/cx2341x/fw-upload.txt b/Documentation/video4linux/cx2341x/fw-upload.txt
new file mode 100644
index 0000000..60c502c
--- /dev/null
+++ b/Documentation/video4linux/cx2341x/fw-upload.txt
@@ -0,0 +1,49 @@
+This document describes how to upload the cx2341x firmware to the card.
+
+How to find
+===========
+
+See the web pages of the various projects that uses this chip for information
+on how to obtain the firmware.
+
+The firmware stored in a Windows driver can be detected as follows:
+
+- Each firmware image is 256k bytes.
+- The 1st 32-bit word of the Encoder image is 0x0000da7
+- The 1st 32-bit word of the Decoder image is 0x00003a7
+- The 2nd 32-bit word of both images is 0xaa55bb66
+
+How to load
+===========
+
+- Issue the FWapi command to stop the encoder if it is running. Wait for the
+  command to complete.
+- Issue the FWapi command to stop the decoder if it is running. Wait for the
+  command to complete.
+- Issue the I2C command to the digitizer to stop emitting VSYNC events.
+- Issue the FWapi command to halt the encoder's firmware.
+- Sleep for 10ms.
+- Issue the FWapi command to halt the decoder's firmware.
+- Sleep for 10ms.
+- Write 0x00000000 to register 0x2800 to stop the Video Display Module.
+- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?).
+- Write 0x00000000 to register 0xA064 to ping? the APU.
+- Write 0xFFFFFFFE to register 0x9058 to stop the VPU.
+- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks.
+- Write 0x00000001 to register 0x9050 to stop the SPU.
+- Sleep for 10ms.
+- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us.
+- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge.
+- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us.
+- Sleep for 512ms. (600ms is recommended)
+- Transfer the encoder's firmware image to offset 0 in Encoder memory space.
+- Transfer the decoder's firmware image to offset 0 in Decoder memory space.
+- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to
+  re-enable the SPU.
+- Sleep for 1 second.
+- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058
+  to re-enable the VPU.
+- Sleep for 1 second.
+- Issue status API commands to both firmware images to verify.
+
diff --git a/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt
new file mode 100644
index 0000000..93fec32
--- /dev/null
+++ b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt
@@ -0,0 +1,54 @@
+The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting.
+
+GPIO0  GPIO1
+  0        0    TV Audio
+  1        0    FM radio
+  0        1    Line-In
+  1        1    Mono tuner bypass or CD passthru (tuner specific)
+
+GPIO 16(i believe) is tied to the IR port (if present).
+
+------------------------------------------------------------------------------------
+
+>From the data sheet:
+ Register 24'h20004  PCI Interrupt Status
+  bit [18]  IR_SMP_INT Set when 32 input samples have been collected over
+  gpio[16] pin into GP_SAMPLE register.
+
+What's missing from the data sheet:
+
+Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5
+compat remote)
+set register 0x35C050 to  0xa80a80
+
+enable sampling
+set register 0x35C054 to 0x5
+
+Of course, enable the IRQ bit 18 in the interrupt mask register .(and
+provide for a handler)
+
+GP_SAMPLE register is at 0x35C058
+
+Bits are then right shifted into the GP_SAMPLE register at the specified
+rate; you get an interrupt when a full DWORD is recieved.
+You need to recover the actual RC5 bits out of the (oversampled) IR sensor
+bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data)  An
+actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment.
+
+I'm pretty sure when no IR signal is present the receiver is always in a
+marking state(1); but stray light, etc can cause intermittent noise values
+as well.  Remember, this is a free running sample of the IR receiver state
+over time, so don't assume any sample starts at any particular place.
+
+http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf
+This data sheet (google search) seems to have a lovely description of the
+RC5 basics
+
+http://users.pandora.be/nenya/electronics/rc5/  and more data
+
+http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt
+and even a reference to how to decode a bi-phase data stream.
+
+http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm
+still more info
+
diff --git a/Documentation/video4linux/et61x251.txt b/Documentation/video4linux/et61x251.txt
index 2934028..cd584f2 100644
--- a/Documentation/video4linux/et61x251.txt
+++ b/Documentation/video4linux/et61x251.txt
@@ -1,9 +1,9 @@
 
-                       ET61X[12]51 PC Camera Controllers
-                                Driver for Linux
-                       =================================
+		       ET61X[12]51 PC Camera Controllers
+				Driver for Linux
+		       =================================
 
-                               - Documentation -
+			       - Documentation -
 
 
 Index
@@ -156,46 +156,46 @@
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                registered camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 64 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		registered camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+		before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+		all the applications support this feature. This parameter is
+		specific for each detected camera.
+		0 = do not force memory unmapping
+		1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		specific for each detected camera. This parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           ushort
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used at the same time. It also shows some more informations
-                about the hardware being detected. This module parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = more verbose messages
+		Level 3 is useful for testing only, when only one device
+		is used at the same time. It also shows some more informations
+		about the hardware being detected. This module parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
diff --git a/Documentation/video4linux/ibmcam.txt b/Documentation/video4linux/ibmcam.txt
index 4a40a2e..397a94e 100644
--- a/Documentation/video4linux/ibmcam.txt
+++ b/Documentation/video4linux/ibmcam.txt
@@ -21,7 +21,7 @@
 Supported controls:
 - by V4L: Contrast,  Brightness, Color, Hue
 - by driver options: frame rate, lighting conditions, video format,
-                     default picture settings, sharpness.
+		     default picture settings, sharpness.
 
 SUPPORTED CAMERAS:
 
@@ -191,66 +191,66 @@
 init_model2_yb  Integer         0..255 [0xa0]   init_model2_yb=200
 
 debug           You don't need this option unless you are a developer.
-                If you are a developer then you will see in the code
-                what values do what. 0=off.
+		If you are a developer then you will see in the code
+		what values do what. 0=off.
 
 flags           This is a bit mask, and you can combine any number of
-                bits to produce what you want. Usually you don't want
-                any of extra features this option provides:
+		bits to produce what you want. Usually you don't want
+		any of extra features this option provides:
 
-                FLAGS_RETRY_VIDIOCSYNC  1  This bit allows to retry failed
-                                           VIDIOCSYNC ioctls without failing.
-                                           Will work with xawtv, will not
-                                           with xrealproducer. Default is
-                                           not set.
-                FLAGS_MONOCHROME        2  Activates monochrome (b/w) mode.
-                FLAGS_DISPLAY_HINTS     4  Shows colored pixels which have
-                                           magic meaning to developers.
-                FLAGS_OVERLAY_STATS     8  Shows tiny numbers on screen,
-                                           useful only for debugging.
-                FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
-                FLAGS_SEPARATE_FRAMES   32 Shows each frame separately, as
-                                           it was received from the camera.
-                                           Default (not set) is to mix the
-                                           preceding frame in to compensate
-                                           for occasional loss of Isoc data
-                                           on high frame rates.
-                FLAGS_CLEAN_FRAMES      64 Forces "cleanup" of each frame
-                                           prior to use; relevant only if
-                                           FLAGS_SEPARATE_FRAMES is set.
-                                           Default is not to clean frames,
-                                           this is a little faster but may
-                                           produce flicker if frame rate is
-                                           too high and Isoc data gets lost.
-                FLAGS_NO_DECODING      128 This flag turns the video stream
-                                           decoder off, and dumps the raw
-                                           Isoc data from the camera into
-                                           the reading process. Useful to
-                                           developers, but not to users.
+		FLAGS_RETRY_VIDIOCSYNC  1  This bit allows to retry failed
+					   VIDIOCSYNC ioctls without failing.
+					   Will work with xawtv, will not
+					   with xrealproducer. Default is
+					   not set.
+		FLAGS_MONOCHROME        2  Activates monochrome (b/w) mode.
+		FLAGS_DISPLAY_HINTS     4  Shows colored pixels which have
+					   magic meaning to developers.
+		FLAGS_OVERLAY_STATS     8  Shows tiny numbers on screen,
+					   useful only for debugging.
+		FLAGS_FORCE_TESTPATTERN 16 Shows blue screen with numbers.
+		FLAGS_SEPARATE_FRAMES   32 Shows each frame separately, as
+					   it was received from the camera.
+					   Default (not set) is to mix the
+					   preceding frame in to compensate
+					   for occasional loss of Isoc data
+					   on high frame rates.
+		FLAGS_CLEAN_FRAMES      64 Forces "cleanup" of each frame
+					   prior to use; relevant only if
+					   FLAGS_SEPARATE_FRAMES is set.
+					   Default is not to clean frames,
+					   this is a little faster but may
+					   produce flicker if frame rate is
+					   too high and Isoc data gets lost.
+		FLAGS_NO_DECODING      128 This flag turns the video stream
+					   decoder off, and dumps the raw
+					   Isoc data from the camera into
+					   the reading process. Useful to
+					   developers, but not to users.
 
 framerate       This setting controls frame rate of the camera. This is
-                an approximate setting (in terms of "worst" ... "best")
-                because camera changes frame rate depending on amount
-                of light available. Setting 0 is slowest, 6 is fastest.
-                Beware - fast settings are very demanding and may not
-                work well with all video sizes. Be conservative.
+		an approximate setting (in terms of "worst" ... "best")
+		because camera changes frame rate depending on amount
+		of light available. Setting 0 is slowest, 6 is fastest.
+		Beware - fast settings are very demanding and may not
+		work well with all video sizes. Be conservative.
 
 hue_correction  This highly optional setting allows to adjust the
-                hue of the image in a way slightly different from
-                what usual "hue" control does. Both controls affect
-                YUV colorspace: regular "hue" control adjusts only
-                U component, and this "hue_correction" option similarly
-                adjusts only V component. However usually it is enough
-                to tweak only U or V to compensate for colored light or
-                color temperature; this option simply allows more
-                complicated correction when and if it is necessary.
+		hue of the image in a way slightly different from
+		what usual "hue" control does. Both controls affect
+		YUV colorspace: regular "hue" control adjusts only
+		U component, and this "hue_correction" option similarly
+		adjusts only V component. However usually it is enough
+		to tweak only U or V to compensate for colored light or
+		color temperature; this option simply allows more
+		complicated correction when and if it is necessary.
 
 init_brightness These settings specify _initial_ values which will be
 init_contrast   used to set up the camera. If your V4L application has
 init_color      its own controls to adjust the picture then these
 init_hue        controls will be used too. These options allow you to
-                preconfigure the camera when it gets connected, before
-                any V4L application connects to it. Good for webcams.
+		preconfigure the camera when it gets connected, before
+		any V4L application connects to it. Good for webcams.
 
 init_model2_rg  These initial settings alter color balance of the
 init_model2_rg2 camera on hardware level. All four settings may be used
@@ -258,47 +258,47 @@
 init_model2_yb  settings only apply to Model 2 cameras.
 
 lighting        This option selects one of three hardware-defined
-                photosensitivity settings of the camera. 0=bright light,
-                1=Medium (default), 2=Low light. This setting affects
-                frame rate: the dimmer the lighting the lower the frame
-                rate (because longer exposition time is needed). The
-                Model 2 cameras allow values more than 2 for this option,
-                thus enabling extremely high sensitivity at cost of frame
-                rate, color saturation and imaging sensor noise.
+		photosensitivity settings of the camera. 0=bright light,
+		1=Medium (default), 2=Low light. This setting affects
+		frame rate: the dimmer the lighting the lower the frame
+		rate (because longer exposition time is needed). The
+		Model 2 cameras allow values more than 2 for this option,
+		thus enabling extremely high sensitivity at cost of frame
+		rate, color saturation and imaging sensor noise.
 
 sharpness       This option controls smoothing (noise reduction)
-                made by camera. Setting 0 is most smooth, setting 6
-                is most sharp. Be aware that CMOS sensor used in the
-                camera is pretty noisy, so if you choose 6 you will
-                be greeted with "snowy" image. Default is 4. Model 2
-                cameras do not support this feature.
+		made by camera. Setting 0 is most smooth, setting 6
+		is most sharp. Be aware that CMOS sensor used in the
+		camera is pretty noisy, so if you choose 6 you will
+		be greeted with "snowy" image. Default is 4. Model 2
+		cameras do not support this feature.
 
 size            This setting chooses one of several image sizes that are
-                supported by this driver. Cameras may support more, but
-                it's difficult to reverse-engineer all formats.
-                Following video sizes are supported:
+		supported by this driver. Cameras may support more, but
+		it's difficult to reverse-engineer all formats.
+		Following video sizes are supported:
 
-                size=0     128x96  (Model 1 only)
-                size=1     160x120
-                size=2     176x144
-                size=3     320x240 (Model 2 only)
-                size=4     352x240 (Model 2 only)
-                size=5     352x288
-                size=6     640x480 (Model 3 only)
+		size=0     128x96  (Model 1 only)
+		size=1     160x120
+		size=2     176x144
+		size=3     320x240 (Model 2 only)
+		size=4     352x240 (Model 2 only)
+		size=5     352x288
+		size=6     640x480 (Model 3 only)
 
-                The 352x288 is the native size of the Model 1 sensor
-                array, so it's the best resolution the camera can
-                yield. The best resolution of Model 2 is 176x144, and
-                larger images are produced by stretching the bitmap.
-                Model 3 has sensor with 640x480 grid, and it works too,
-                but the frame rate will be exceptionally low (1-2 FPS);
-                it may be still OK for some applications, like security.
-                Choose the image size you need. The smaller image can
-                support faster frame rate. Default is 352x288.
+		The 352x288 is the native size of the Model 1 sensor
+		array, so it's the best resolution the camera can
+		yield. The best resolution of Model 2 is 176x144, and
+		larger images are produced by stretching the bitmap.
+		Model 3 has sensor with 640x480 grid, and it works too,
+		but the frame rate will be exceptionally low (1-2 FPS);
+		it may be still OK for some applications, like security.
+		Choose the image size you need. The smaller image can
+		support faster frame rate. Default is 352x288.
 
 For more information and the Troubleshooting FAQ visit this URL:
 
-                http://www.linux-usb.org/ibmcam/
+		http://www.linux-usb.org/ibmcam/
 
 WHAT NEEDS TO BE DONE:
 
diff --git a/Documentation/video4linux/ov511.txt b/Documentation/video4linux/ov511.txt
index 142741e..79af610 100644
--- a/Documentation/video4linux/ov511.txt
+++ b/Documentation/video4linux/ov511.txt
@@ -81,7 +81,7 @@
   TYPE: integer (Boolean)
   DEFAULT: 1
   DESC: Brightness is normally under automatic control and can't be set
-        manually by the video app. Set to 0 for manual control.
+	manually by the video app. Set to 0 for manual control.
 
   NAME: autogain
   TYPE: integer (Boolean)
@@ -97,13 +97,13 @@
   TYPE: integer (0-6)
   DEFAULT: 3
   DESC: Sets the threshold for printing debug messages. The higher the value,
-        the more is printed. The levels are cumulative, and are as follows:
-          0=no debug messages
-          1=init/detection/unload and other significant messages
-          2=some warning messages
-          3=config/control function calls
-          4=most function calls and data parsing messages
-          5=highly repetitive mesgs
+	the more is printed. The levels are cumulative, and are as follows:
+	  0=no debug messages
+	  1=init/detection/unload and other significant messages
+	  2=some warning messages
+	  3=config/control function calls
+	  4=most function calls and data parsing messages
+	  5=highly repetitive mesgs
 
   NAME: snapshot
   TYPE: integer (Boolean)
@@ -116,24 +116,24 @@
   TYPE: integer (1-4 for OV511, 1-31 for OV511+)
   DEFAULT: 1
   DESC: Number of cameras allowed to stream simultaneously on a single bus.
-        Values higher than 1 reduce the data rate of each camera, allowing two
-        or more to be used at once. If you have a complicated setup involving
-        both OV511 and OV511+ cameras, trial-and-error may be necessary for
-        finding the optimum setting.
+	Values higher than 1 reduce the data rate of each camera, allowing two
+	or more to be used at once. If you have a complicated setup involving
+	both OV511 and OV511+ cameras, trial-and-error may be necessary for
+	finding the optimum setting.
 
   NAME: compress
   TYPE: integer (Boolean)
   DEFAULT: 0
   DESC: Set this to 1 to turn on the camera's compression engine. This can
-        potentially increase the frame rate at the expense of quality, if you
-        have a fast CPU. You must load the proper compression module for your
-        camera before starting your application (ov511_decomp or ov518_decomp).
+	potentially increase the frame rate at the expense of quality, if you
+	have a fast CPU. You must load the proper compression module for your
+	camera before starting your application (ov511_decomp or ov518_decomp).
 
   NAME: testpat
   TYPE: integer (Boolean)
   DEFAULT: 0
   DESC: This configures the camera's sensor to transmit a colored test-pattern
-        instead of an image. This does not work correctly yet.
+	instead of an image. This does not work correctly yet.
 
   NAME: dumppix
   TYPE: integer (0-2)
diff --git a/Documentation/video4linux/sn9c102.txt b/Documentation/video4linux/sn9c102.txt
index 142920b..1d20895 100644
--- a/Documentation/video4linux/sn9c102.txt
+++ b/Documentation/video4linux/sn9c102.txt
@@ -1,9 +1,9 @@
 
-                         SN9C10x PC Camera Controllers
-                                Driver for Linux
-                         =============================
+			 SN9C10x PC Camera Controllers
+				Driver for Linux
+			 =============================
 
-                               - Documentation -
+			       - Documentation -
 
 
 Index
@@ -176,46 +176,46 @@
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                recognized camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 64 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		recognized camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+		before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+		all the applications support this feature. This parameter is
+		specific for each detected camera.
+		0 = do not force memory unmapping
+		1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		specific for each detected camera. This parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           ushort
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used. It also shows some more informations about the
-                hardware being detected. This parameter can be changed at
-                runtime thanks to the /sys filesystem interface.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = more verbose messages
+		Level 3 is useful for testing only, when only one device
+		is used. It also shows some more informations about the
+		hardware being detected. This parameter can be changed at
+		runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
@@ -280,24 +280,24 @@
 0x04    0xC4          Frame synchronisation pattern.
 0x05    0x96          Frame synchronisation pattern.
 0x06    0xXX          Unknown meaning. The exact value depends on the chip;
-                      possible values are 0x00, 0x01 and 0x20.
+		      possible values are 0x00, 0x01 and 0x20.
 0x07    0xXX          Variable value, whose bits are ff00uzzc, where ff is a
-                      frame counter, u is unknown, zz is a size indicator
-                      (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
-                      "compression enabled" (1 = yes, 0 = no).
+		      frame counter, u is unknown, zz is a size indicator
+		      (00 = VGA, 01 = SIF, 10 = QSIF) and c stands for
+		      "compression enabled" (1 = yes, 0 = no).
 0x08    0xXX          Brightness sum inside Auto-Exposure area (low-byte).
 0x09    0xXX          Brightness sum inside Auto-Exposure area (high-byte).
-                      For a pure white image, this number will be equal to 500
-                      times the area of the specified AE area. For images
-                      that are not pure white, the value scales down according
-                      to relative whiteness.
+		      For a pure white image, this number will be equal to 500
+		      times the area of the specified AE area. For images
+		      that are not pure white, the value scales down according
+		      to relative whiteness.
 0x0A    0xXX          Brightness sum outside Auto-Exposure area (low-byte).
 0x0B    0xXX          Brightness sum outside Auto-Exposure area (high-byte).
-                      For a pure white image, this number will be equal to 125
-                      times the area outside of the specified AE area. For
-                      images that are not pure white, the value scales down
-                      according to relative whiteness.
-                      according to relative whiteness.
+		      For a pure white image, this number will be equal to 125
+		      times the area outside of the specified AE area. For
+		      images that are not pure white, the value scales down
+		      according to relative whiteness.
+		      according to relative whiteness.
 
 The following bytes are used by the SN9C103 bridge only:
 
diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c
new file mode 100644
index 0000000..079b628
--- /dev/null
+++ b/Documentation/video4linux/v4lgrab.c
@@ -0,0 +1,192 @@
+/* Simple Video4Linux image grabber. */
+/*
+ *	Video4Linux Driver Test/Example Framegrabbing Program
+ *
+ *	Compile with:
+ *		gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab
+ *      Use as:
+ *              v4lgrab >image.ppm
+ *
+ *	Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org>
+ *      Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c
+ *      with minor modifications (Dave Forrest, drf5n@virginia.edu).
+ *
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+#define FILE "/dev/video0"
+
+/* Stole this from tvset.c */
+
+#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b)                   \
+{                                                                       \
+	switch (format)                                                 \
+	{                                                               \
+		case VIDEO_PALETTE_GREY:                                \
+			switch (depth)                                  \
+			{                                               \
+				case 4:                                 \
+				case 6:                                 \
+				case 8:                                 \
+					(r) = (g) = (b) = (*buf++ << 8);\
+					break;                          \
+									\
+				case 16:                                \
+					(r) = (g) = (b) =               \
+						*((unsigned short *) buf);      \
+					buf += 2;                       \
+					break;                          \
+			}                                               \
+			break;                                          \
+									\
+									\
+		case VIDEO_PALETTE_RGB565:                              \
+		{                                                       \
+			unsigned short tmp = *(unsigned short *)buf;    \
+			(r) = tmp&0xF800;                               \
+			(g) = (tmp<<5)&0xFC00;                          \
+			(b) = (tmp<<11)&0xF800;                         \
+			buf += 2;                                       \
+		}                                                       \
+		break;                                                  \
+									\
+		case VIDEO_PALETTE_RGB555:                              \
+			(r) = (buf[0]&0xF8)<<8;                         \
+			(g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8;    \
+			(b) = ((buf[1] << 2 ) & 0xF8)<<8;               \
+			buf += 2;                                       \
+			break;                                          \
+									\
+		case VIDEO_PALETTE_RGB24:                               \
+			(r) = buf[0] << 8; (g) = buf[1] << 8;           \
+			(b) = buf[2] << 8;                              \
+			buf += 3;                                       \
+			break;                                          \
+									\
+		default:                                                \
+			fprintf(stderr,                                 \
+				"Format %d not yet supported\n",        \
+				format);                                \
+	}                                                               \
+}
+
+int get_brightness_adj(unsigned char *image, long size, int *brightness) {
+  long i, tot = 0;
+  for (i=0;i<size*3;i++)
+    tot += image[i];
+  *brightness = (128 - tot/(size*3))/3;
+  return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130);
+}
+
+int main(int argc, char ** argv)
+{
+  int fd = open(FILE, O_RDONLY), f;
+  struct video_capability cap;
+  struct video_window win;
+  struct video_picture vpic;
+
+  unsigned char *buffer, *src;
+  int bpp = 24, r, g, b;
+  unsigned int i, src_depth;
+
+  if (fd < 0) {
+    perror(FILE);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGCAP, &cap) < 0) {
+    perror("VIDIOGCAP");
+    fprintf(stderr, "(" FILE " not a video4linux device?)\n");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGWIN, &win) < 0) {
+    perror("VIDIOCGWIN");
+    close(fd);
+    exit(1);
+  }
+
+  if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) {
+    perror("VIDIOCGPICT");
+    close(fd);
+    exit(1);
+  }
+
+  if (cap.type & VID_TYPE_MONOCHROME) {
+    vpic.depth=8;
+    vpic.palette=VIDEO_PALETTE_GREY;    /* 8bit grey */
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.depth=6;
+      if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+	vpic.depth=4;
+	if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+	  fprintf(stderr, "Unable to find a supported capture format.\n");
+	  close(fd);
+	  exit(1);
+	}
+      }
+    }
+  } else {
+    vpic.depth=24;
+    vpic.palette=VIDEO_PALETTE_RGB24;
+
+    if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) {
+      vpic.palette=VIDEO_PALETTE_RGB565;
+      vpic.depth=16;
+
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+	vpic.palette=VIDEO_PALETTE_RGB555;
+	vpic.depth=15;
+
+	if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+	  fprintf(stderr, "Unable to find a supported capture format.\n");
+	  return -1;
+	}
+      }
+    }
+  }
+
+  buffer = malloc(win.width * win.height * bpp);
+  if (!buffer) {
+    fprintf(stderr, "Out of memory.\n");
+    exit(1);
+  }
+
+  do {
+    int newbright;
+    read(fd, buffer, win.width * win.height * bpp);
+    f = get_brightness_adj(buffer, win.width * win.height, &newbright);
+    if (f) {
+      vpic.brightness += (newbright << 8);
+      if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) {
+	perror("VIDIOSPICT");
+	break;
+      }
+    }
+  } while (f);
+
+  fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height);
+
+  src = buffer;
+
+  for (i = 0; i < win.width * win.height; i++) {
+    READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b);
+    fputc(r>>8, stdout);
+    fputc(g>>8, stdout);
+    fputc(b>>8, stdout);
+  }
+
+  close(fd);
+  return 0;
+}
diff --git a/Documentation/video4linux/w9968cf.txt b/Documentation/video4linux/w9968cf.txt
index 3b704f2..0d53ce7 100644
--- a/Documentation/video4linux/w9968cf.txt
+++ b/Documentation/video4linux/w9968cf.txt
@@ -1,9 +1,9 @@
 
-                   W996[87]CF JPEG USB Dual Mode Camera Chip
-                     Driver for Linux 2.6 (basic version)
-                   =========================================
+		   W996[87]CF JPEG USB Dual Mode Camera Chip
+		     Driver for Linux 2.6 (basic version)
+		   =========================================
 
-                               - Documentation -
+			       - Documentation -
 
 
 Index
@@ -188,57 +188,57 @@
 Type:            bool
 Syntax:          <0|1>
 Description:     Automatic 'ovcamchip' module loading: 0 disabled, 1 enabled.
-                 If enabled, 'insmod' searches for the required 'ovcamchip'
-                 module in the system, according to its configuration, and
-                 loads that module automatically. This action is performed as
-                 once soon as the 'w9968cf' module is loaded into memory.
+		 If enabled, 'insmod' searches for the required 'ovcamchip'
+		 module in the system, according to its configuration, and
+		 loads that module automatically. This action is performed as
+		 once soon as the 'w9968cf' module is loaded into memory.
 Default:         1
 Note:            The kernel must be compiled with the CONFIG_KMOD option
-                 enabled for the 'ovcamchip' module to be loaded and for
-                 this parameter to be present.
+		 enabled for the 'ovcamchip' module to be loaded and for
+		 this parameter to be present.
 -------------------------------------------------------------------------------
 Name:           simcams
 Type:           int
 Syntax:         <n>
 Description:    Number of cameras allowed to stream simultaneously.
-                n may vary from 0 to 32.
+		n may vary from 0 to 32.
 Default:        32
 -------------------------------------------------------------------------------
 Name:           video_nr
 Type:           int array (min = 0, max = 32)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L minor mode number.
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 32 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                recognized camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 32 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		recognized camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           packet_size
 Type:           int array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Description:    Specify the maximum data payload size in bytes for alternate
-                settings, for each device. n is scaled between 63 and 1023.
+		settings, for each device. n is scaled between 63 and 1023.
 Default:        1023
 -------------------------------------------------------------------------------
 Name:           max_buffers
 Type:           int array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Description:    For advanced users.
-                Specify the maximum number of video frame buffers to allocate
-                for each device, from 2 to 32.
+		Specify the maximum number of video frame buffers to allocate
+		for each device, from 2 to 32.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           double_buffer
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Hardware double buffering: 0 disabled, 1 enabled.
-                It should be enabled if you want smooth video output: if you
-                obtain out of sync. video, disable it, or try to
-                decrease the 'clockdiv' module parameter value.
+		It should be enabled if you want smooth video output: if you
+		obtain out of sync. video, disable it, or try to
+		decrease the 'clockdiv' module parameter value.
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           clamping
@@ -251,9 +251,9 @@
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|1|2[,...]>
 Description:    Video filter type.
-                0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
-                The filter is used to reduce noise and aliasing artifacts
-                produced by the CCD or CMOS image sensor.
+		0 none, 1 (1-2-1) 3-tap filter, 2 (2-3-6-3-2) 5-tap filter.
+		The filter is used to reduce noise and aliasing artifacts
+		produced by the CCD or CMOS image sensor.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           largeview
@@ -266,9 +266,9 @@
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Software scaling (for non-compressed video only):
-                0 disabled, 1 enabled.
-                Disable it if you have a slow CPU or you don't have enough
-                memory.
+		0 disabled, 1 enabled.
+		Disable it if you have a slow CPU or you don't have enough
+		memory.
 Default:        0 for every device.
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 0.
 -------------------------------------------------------------------------------
@@ -276,36 +276,36 @@
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|1|2[,...]>
 Description:    Software video decompression:
-                0 = disables decompression
-                    (doesn't allow formats needing decompression).
-                1 = forces decompression
-                    (allows formats needing decompression only).
-                2 = allows any permitted formats.
-                Formats supporting (de)compressed video are YUV422P and
-                YUV420P/YUV420 in any resolutions where width and height are
-                multiples of 16.
+		0 = disables decompression
+		    (doesn't allow formats needing decompression).
+		1 = forces decompression
+		    (allows formats needing decompression only).
+		2 = allows any permitted formats.
+		Formats supporting (de)compressed video are YUV422P and
+		YUV420P/YUV420 in any resolutions where width and height are
+		multiples of 16.
 Default:        2 for every device.
 Note:           If 'w9968cf-vpp' is not present, forcing decompression is not
-                allowed; in this case this parameter is set to 2.
+		allowed; in this case this parameter is set to 2.
 -------------------------------------------------------------------------------
 Name:           force_palette
 Type:           int array (min = 0, max = 32)
 Syntax:         <0|9|10|13|15|8|7|1|6|3|4|5[,...]>
 Description:    Force picture palette.
-                In order:
-                 0 = Off - allows any of the following formats:
-                 9 = UYVY    16 bpp - Original video, compression disabled
-                10 = YUV420  12 bpp - Original video, compression enabled
-                13 = YUV422P 16 bpp - Original video, compression enabled
-                15 = YUV420P 12 bpp - Original video, compression enabled
-                 8 = YUVY    16 bpp - Software conversion from UYVY
-                 7 = YUV422  16 bpp - Software conversion from UYVY
-                 1 = GREY     8 bpp - Software conversion from UYVY
-                 6 = RGB555  16 bpp - Software conversion from UYVY
-                 3 = RGB565  16 bpp - Software conversion from UYVY
-                 4 = RGB24   24 bpp - Software conversion from UYVY
-                 5 = RGB32   32 bpp - Software conversion from UYVY
-                When not 0, this parameter will override 'decompression'.
+		In order:
+		 0 = Off - allows any of the following formats:
+		 9 = UYVY    16 bpp - Original video, compression disabled
+		10 = YUV420  12 bpp - Original video, compression enabled
+		13 = YUV422P 16 bpp - Original video, compression enabled
+		15 = YUV420P 12 bpp - Original video, compression enabled
+		 8 = YUVY    16 bpp - Software conversion from UYVY
+		 7 = YUV422  16 bpp - Software conversion from UYVY
+		 1 = GREY     8 bpp - Software conversion from UYVY
+		 6 = RGB555  16 bpp - Software conversion from UYVY
+		 3 = RGB565  16 bpp - Software conversion from UYVY
+		 4 = RGB24   24 bpp - Software conversion from UYVY
+		 5 = RGB32   32 bpp - Software conversion from UYVY
+		When not 0, this parameter will override 'decompression'.
 Default:        0 for every device. Initial palette is 9 (UYVY).
 Note:           If 'w9968cf-vpp' is not present, this parameter is set to 9.
 -------------------------------------------------------------------------------
@@ -313,77 +313,77 @@
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Read RGB video data instead of BGR:
-                1 = use RGB component ordering.
-                0 = use BGR component ordering.
-                This parameter has effect when using RGBX palettes only.
+		1 = use RGB component ordering.
+		0 = use BGR component ordering.
+		This parameter has effect when using RGBX palettes only.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           autobright
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Image sensor automatically changes brightness:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           autoexp
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Image sensor automatically changes exposure:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        1 for every device.
 -------------------------------------------------------------------------------
 Name:           lightfreq
 Type:           int array (min = 0, max = 32)
 Syntax:         <50|60[,...]>
 Description:    Light frequency in Hz:
-                50 for European and Asian lighting, 60 for American lighting.
+		50 for European and Asian lighting, 60 for American lighting.
 Default:        50 for every device.
 -------------------------------------------------------------------------------
 Name:           bandingfilter
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Banding filter to reduce effects of fluorescent
-                lighting:
-                0 disabled, 1 enabled.
-                This filter tries to reduce the pattern of horizontal
-                light/dark bands caused by some (usually fluorescent) lighting.
+		lighting:
+		0 disabled, 1 enabled.
+		This filter tries to reduce the pattern of horizontal
+		light/dark bands caused by some (usually fluorescent) lighting.
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           clockdiv
 Type:           int array (min = 0, max = 32)
 Syntax:         <-1|n[,...]>
 Description:    Force pixel clock divisor to a specific value (for experts):
-                n may vary from 0 to 127.
-                -1 for automatic value.
-                See also the 'double_buffer' module parameter.
+		n may vary from 0 to 127.
+		-1 for automatic value.
+		See also the 'double_buffer' module parameter.
 Default:        -1 for every device.
 -------------------------------------------------------------------------------
 Name:           backlight
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Objects are lit from behind:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           mirror
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    Reverse image horizontally:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           monochrome
 Type:           bool array (min = 0, max = 32)
 Syntax:         <0|1[,...]>
 Description:    The image sensor is monochrome:
-                0 = no, 1 = yes
+		0 = no, 1 = yes
 Default:        0 for every device.
 -------------------------------------------------------------------------------
 Name:           brightness
 Type:           long array (min = 0, max = 32)
 Syntax:         <n[,...]>
 Description:    Set picture brightness (0-65535).
-                This parameter has no effect if 'autobright' is enabled.
+		This parameter has no effect if 'autobright' is enabled.
 Default:        31000 for every device.
 -------------------------------------------------------------------------------
 Name:           hue
@@ -414,23 +414,23 @@
 Type:           int
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 6:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = configuration or general messages
-                4 = warnings
-                5 = called functions
-                6 = function internals
-                Level 5 and 6 are useful for testing only, when only one
-                device is used.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = configuration or general messages
+		4 = warnings
+		5 = called functions
+		6 = function internals
+		Level 5 and 6 are useful for testing only, when only one
+		device is used.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           specific_debug
 Type:           bool
 Syntax:         <0|1>
 Description:    Enable or disable specific debugging messages:
-                0 = print messages concerning every level <= 'debug' level.
-                1 = print messages concerning the level indicated by 'debug'.
+		0 = print messages concerning every level <= 'debug' level.
+		1 = print messages concerning the level indicated by 'debug'.
 Default:        0
 -------------------------------------------------------------------------------
 
diff --git a/Documentation/video4linux/zc0301.txt b/Documentation/video4linux/zc0301.txt
index f55262c..f406f5e 100644
--- a/Documentation/video4linux/zc0301.txt
+++ b/Documentation/video4linux/zc0301.txt
@@ -1,9 +1,9 @@
 
-                    ZC0301 Image Processor and Control Chip
-                                Driver for Linux
-                    =======================================
+	      ZC0301 and ZC0301P Image Processor and Control Chip
+				Driver for Linux
+	      ===================================================
 
-                               - Documentation -
+			       - Documentation -
 
 
 Index
@@ -51,13 +51,13 @@
 
 4. Overview and features
 ========================
-This driver supports the video interface of the devices mounting the ZC0301
-Image Processor and Control Chip.
+This driver supports the video interface of the devices mounting the ZC0301 or
+ZC0301P Image Processors and Control Chips.
 
 The driver relies on the Video4Linux2 and USB core modules. It has been
 designed to run properly on SMP systems as well.
 
-The latest version of the ZC0301 driver can be found at the following URL:
+The latest version of the ZC0301[P] driver can be found at the following URL:
 http://www.linux-projects.org/
 
 Some of the features of the driver are:
@@ -117,7 +117,7 @@
 
 And finally:
 
-	# USB Multimedia devices
+	# V4L USB devices
 	#
 	CONFIG_USB_ZC0301=m
 
@@ -146,46 +146,46 @@
 Type:           short array (min = 0, max = 64)
 Syntax:         <-1|n[,...]>
 Description:    Specify V4L2 minor mode number:
-                -1 = use next available
-                 n = use minor number n
-                You can specify up to 64 cameras this way.
-                For example:
-                video_nr=-1,2,-1 would assign minor number 2 to the second
-                registered camera and use auto for the first one and for every
-                other camera.
+		-1 = use next available
+		 n = use minor number n
+		You can specify up to 64 cameras this way.
+		For example:
+		video_nr=-1,2,-1 would assign minor number 2 to the second
+		registered camera and use auto for the first one and for every
+		other camera.
 Default:        -1
 -------------------------------------------------------------------------------
 Name:           force_munmap
 Type:           bool array (min = 0, max = 64)
 Syntax:         <0|1[,...]>
 Description:    Force the application to unmap previously mapped buffer memory
-                before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
-                all the applications support this feature. This parameter is
-                specific for each detected camera.
-                0 = do not force memory unmapping
-                1 = force memory unmapping (save memory)
+		before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
+		all the applications support this feature. This parameter is
+		specific for each detected camera.
+		0 = do not force memory unmapping
+		1 = force memory unmapping (save memory)
 Default:        0
 -------------------------------------------------------------------------------
 Name:           frame_timeout
 Type:           uint array (min = 0, max = 64)
 Syntax:         <n[,...]>
 Description:    Timeout for a video frame in seconds. This parameter is
-                specific for each detected camera. This parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		specific for each detected camera. This parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 Name:           debug
 Type:           ushort
 Syntax:         <n>
 Description:    Debugging information level, from 0 to 3:
-                0 = none (use carefully)
-                1 = critical errors
-                2 = significant informations
-                3 = more verbose messages
-                Level 3 is useful for testing only, when only one device
-                is used at the same time. It also shows some more informations
-                about the hardware being detected. This module parameter can be
-                changed at runtime thanks to the /sys filesystem interface.
+		0 = none (use carefully)
+		1 = critical errors
+		2 = significant informations
+		3 = more verbose messages
+		Level 3 is useful for testing only, when only one device
+		is used at the same time. It also shows some more informations
+		about the hardware being detected. This module parameter can be
+		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
 -------------------------------------------------------------------------------
 
@@ -204,11 +204,25 @@
 0x041e     0x4017
 0x041e     0x401c
 0x041e     0x401e
+0x041e     0x401f
+0x041e     0x4022
 0x041e     0x4034
 0x041e     0x4035
+0x041e     0x4036
+0x041e     0x403a
+0x0458     0x7007
+0x0458     0x700C
+0x0458     0x700f
+0x046d     0x08ae
+0x055f     0xd003
+0x055f     0xd004
 0x046d     0x08ae
 0x0ac8     0x0301
+0x0ac8     0x301b
+0x0ac8     0x303b
+0x10fd     0x0128
 0x10fd     0x8050
+0x10fd     0x804e
 
 The list above does not imply that all those devices work with this driver: up
 until now only the ones that mount the following image sensors are supported;
@@ -217,6 +231,7 @@
 Model       Manufacturer
 -----       ------------
 PAS202BCB   PixArt Imaging, Inc.
+PB-0330     Photobit Corporation
 
 
 9. Notes for V4L2 application developers
@@ -250,5 +265,6 @@
   been taken from the documentation of the ZC030x Video4Linux1 driver written
   by Andrew Birkett <andy@nobugs.org>;
 - The initialization values of the ZC0301 controller connected to the PAS202BCB
-  image sensor have been taken from the SPCA5XX driver maintained by
-  Michel Xhaard <mxhaard@magic.fr>.
+  and PB-0330 image sensors have been taken from the SPCA5XX driver maintained
+  by Michel Xhaard <mxhaard@magic.fr>;
+- Stanislav Lechev donated one camera.
diff --git a/Documentation/vm/page_migration b/Documentation/vm/page_migration
index 0dd4ef3..99f89aa 100644
--- a/Documentation/vm/page_migration
+++ b/Documentation/vm/page_migration
@@ -26,8 +26,13 @@
 Manual migration is useful if for example the scheduler has relocated
 a process to a processor on a distant node. A batch scheduler or an
 administrator may detect the situation and move the pages of the process
-nearer to the new processor. At some point in the future we may have
-some mechanism in the scheduler that will automatically move the pages.
+nearer to the new processor. The kernel itself does only provide
+manual page migration support. Automatic page migration may be implemented
+through user space processes that move pages. A special function call
+"move_pages" allows the moving of individual pages within a process.
+A NUMA profiler may f.e. obtain a log showing frequent off node
+accesses and may use the result to move pages to more advantageous
+locations.
 
 Larger installations usually partition the system using cpusets into
 sections of nodes. Paul Jackson has equipped cpusets with the ability to
@@ -62,22 +67,14 @@
    It also prevents the swapper or other scans to encounter
    the page.
 
-2. Generate a list of newly allocates page. These pages will contain the
-   contents of the pages from the first list after page migration is
-   complete.
+2. We need to have a function of type new_page_t that can be
+   passed to migrate_pages(). This function should figure out
+   how to allocate the correct new page given the old page.
 
 3. The migrate_pages() function is called which attempts
-   to do the migration. It returns the moved pages in the
-   list specified as the third parameter and the failed
-   migrations in the fourth parameter. The first parameter
-   will contain the pages that could still be retried.
-
-4. The leftover pages of various types are returned
-   to the LRU using putback_to_lru_pages() or otherwise
-   disposed of. The pages will still have the refcount as
-   increased by isolate_lru_pages() if putback_to_lru_pages() is not
-   used! The kernel may want to handle the various cases of failures in
-   different ways.
+   to do the migration. It will call the function to allocate
+   the new page for each page that is considered for
+   moving.
 
 B. How migrate_pages() works
 ----------------------------
@@ -93,83 +90,58 @@
 
 2. Insure that writeback is complete.
 
-3. Make sure that the page has assigned swap cache entry if
-   it is an anonyous page. The swap cache reference is necessary
-   to preserve the information contain in the page table maps while
-   page migration occurs.
-
-4. Prep the new page that we want to move to. It is locked
+3. Prep the new page that we want to move to. It is locked
    and set to not being uptodate so that all accesses to the new
    page immediately lock while the move is in progress.
 
-5. All the page table references to the page are either dropped (file
-   backed pages) or converted to swap references (anonymous pages).
-   This should decrease the reference count.
+4. The new page is prepped with some settings from the old page so that
+   accesses to the new page will discover a page with the correct settings.
+
+5. All the page table references to the page are converted
+   to migration entries or dropped (nonlinear vmas).
+   This decrease the mapcount of a page. If the resulting
+   mapcount is not zero then we do not migrate the page.
+   All user space processes that attempt to access the page
+   will now wait on the page lock.
 
 6. The radix tree lock is taken. This will cause all processes trying
-   to reestablish a pte to block on the radix tree spinlock.
+   to access the page via the mapping to block on the radix tree spinlock.
 
 7. The refcount of the page is examined and we back out if references remain
    otherwise we know that we are the only one referencing this page.
 
 8. The radix tree is checked and if it does not contain the pointer to this
-   page then we back out because someone else modified the mapping first.
+   page then we back out because someone else modified the radix tree.
 
-9. The mapping is checked. If the mapping is gone then a truncate action may
-   be in progress and we back out.
+9. The radix tree is changed to point to the new page.
 
-10. The new page is prepped with some settings from the old page so that
-   accesses to the new page will be discovered to have the correct settings.
+10. The reference count of the old page is dropped because the radix tree
+    reference is gone. A reference to the new page is established because
+    the new page is referenced to by the radix tree.
 
-11. The radix tree is changed to point to the new page.
+11. The radix tree lock is dropped. With that lookups in the mapping
+    become possible again. Processes will move from spinning on the tree_lock
+    to sleeping on the locked new page.
 
-12. The reference count of the old page is dropped because the radix tree
-    reference is gone.
+12. The page contents are copied to the new page.
 
-13. The radix tree lock is dropped. With that lookups become possible again
-    and other processes will move from spinning on the tree lock to sleeping on
-    the locked new page.
+13. The remaining page flags are copied to the new page.
 
-14. The page contents are copied to the new page.
+14. The old page flags are cleared to indicate that the page does
+    not provide any information anymore.
 
-15. The remaining page flags are copied to the new page.
+15. Queued up writeback on the new page is triggered.
 
-16. The old page flags are cleared to indicate that the page does
-    not use any information anymore.
-
-17. Queued up writeback on the new page is triggered.
-
-18. If swap pte's were generated for the page then replace them with real
-    ptes. This will reenable access for processes not blocked by the page lock.
+16. If migration entries were page then replace them with real ptes. Doing
+    so will enable access for user space processes not already waiting for
+    the page lock.
 
 19. The page locks are dropped from the old and new page.
-    Processes waiting on the page lock can continue.
+    Processes waiting on the page lock will redo their page faults
+    and will reach the new page.
 
 20. The new page is moved to the LRU and can be scanned by the swapper
     etc again.
 
-TODO list
----------
-
-- Page migration requires the use of swap handles to preserve the
-  information of the anonymous page table entries. This means that swap
-  space is reserved but never used. The maximum number of swap handles used
-  is determined by CHUNK_SIZE (see mm/mempolicy.c) per ongoing migration.
-  Reservation of pages could be avoided by having a special type of swap
-  handle that does not require swap space and that would only track the page
-  references. Something like that was proposed by Marcelo Tosatti in the
-  past (search for migration cache on lkml or linux-mm@kvack.org).
-
-- Page migration unmaps ptes for file backed pages and requires page
-  faults to reestablish these ptes. This could be optimized by somehow
-  recording the references before migration and then reestablish them later.
-  However, there are several locking challenges that have to be overcome
-  before this is possible.
-
-- Page migration generates read ptes for anonymous pages. Dirty page
-  faults are required to make the pages writable again. It may be possible
-  to generate a pte marked dirty if it is known that the page is dirty and
-  that this process has the only reference to that page.
-
-Christoph Lameter, March 8, 2006.
+Christoph Lameter, May 8, 2006.
 
diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490
new file mode 100644
index 0000000..44a4918
--- /dev/null
+++ b/Documentation/w1/masters/ds2490
@@ -0,0 +1,18 @@
+Kernel driver ds2490
+====================
+
+Supported chips:
+  * Maxim DS2490 based
+
+Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+
+
+Description
+-----------
+
+The Maixm/Dallas Semiconductor DS2490 is a chip
+which allows to build USB <-> W1 bridges.
+
+DS9490(R) is a USB <-> W1 bus master device
+which has 0x81 family ID integrated chip and DS2490
+low-level operational chip.
diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic
index f937fbe..4c6509d 100644
--- a/Documentation/w1/w1.generic
+++ b/Documentation/w1/w1.generic
@@ -27,8 +27,19 @@
 
 When a device is found on the bus, w1 core checks if driver for it's family is
 loaded. If so, the family driver is attached to the slave.
-If there is no driver for the family, a simple sysfs entry is created
-for the slave device.
+If there is no driver for the family, default one is assigned, which allows to perform
+almost any kind of operations. Each logical operation is a transaction
+in nature, which can contain several (two or one) low-level operations.
+Let's see how one can read EEPROM context:
+1. one must write control buffer, i.e. buffer containing command byte
+and two byte address. At this step bus is reset and appropriate device
+is selected using either W1_SKIP_ROM or W1_MATCH_ROM command.
+Then provided control buffer is being written to the wire.
+2. reading. This will issue reading eeprom response.
+
+It is possible that between 1. and 2. w1 master thread will reset bus for searching
+and slave device will be even removed, but in this case 0xff will
+be read, since no device was selected.
 
 
 W1 device families
@@ -89,4 +100,5 @@
 name               - the device name, usually the same as the directory name
 w1_slave           - (optional) a binary file whose meaning depends on the
                      family driver
-
+rw		   - (optional) created for slave devices which do not have
+		     appropriate family driver. Allows to read/write binary data.
diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink
new file mode 100644
index 0000000..3640c7c8
--- /dev/null
+++ b/Documentation/w1/w1.netlink
@@ -0,0 +1,98 @@
+Userspace communication protocol over connector [1].
+
+
+Message types.
+=============
+
+There are three types of messages between w1 core and userspace:
+1. Events. They are generated each time new master or slave device found
+	either due to automatic or requested search.
+2. Userspace commands. Includes read/write and search/alarm search comamnds.
+3. Replies to userspace commands.
+
+
+Protocol.
+========
+
+[struct cn_msg] - connector header. It's length field is equal to size of the attached data.
+[struct w1_netlink_msg] - w1 netlink header.
+	__u8 type 	- message type.
+			W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events.
+			W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events.
+			W1_MASTER_CMD - userspace command for bus master device (search/alarm search).
+			W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search
+					for bus master device where given slave device found).
+	__u8 res	- reserved
+	__u16 len	- size of attached to this header data.
+	union {
+		__u8 id;			 - slave unique device id
+		struct w1_mst {
+			__u32		id;	 - master's id.
+			__u32		res;	 - reserved
+		} mst;
+	} id;
+
+[strucrt w1_netlink_cmd] - command for gived master or slave device.
+	__u8 cmd	- command opcode.
+			W1_CMD_READ 	- read command.
+			W1_CMD_WRITE	- write command.
+			W1_CMD_SEARCH	- search command.
+			W1_CMD_ALARM_SEARCH - alarm search command.
+	__u8 res	- reserved
+	__u16 len	- length of data for this command.
+			For read command data must be allocated like for write command.
+	__u8 data[0]	- data for this command.
+
+
+Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages.
+
+For event messages there are no w1_netlink_cmd embedded structures, only connector header
+and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types)
+and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned
+to bus master device when it is added to w1 core.
+
+Currently replies to userspace commands are only generated for read command request.
+One reply is generated exactly for one w1_netlink_cmd read request.
+Replies are not combined when sent - i.e. typical reply messages looks like the following:
+[cn_msg][w1_netlink_msg][w1_netlink_cmd]
+cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
+w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len;
+w1_netlink_cmd.len = cmd->len;
+
+
+Operation steps in w1 core when new command is received.
+=======================================================
+
+When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request,
+according to w1_netlink_msg.type field.
+Then master or slave device is searched for.
+When found, master device (requested or those one on where slave device is found) is locked.
+If slave command is requested, then reset/select procedure is started to select given device.
+
+Then all requested in w1_netlink_msg operations are performed one by one.
+If command requires reply (like read command) it is sent on command completion.
+
+When all commands (w1_netlink_cmd) are processed muster device is unlocked
+and next w1_netlink_msg header processing started.
+
+
+Connector [1] specific documentation.
+====================================
+
+Each connector message includes two u32 fields as "address".
+w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header.
+Each message also includes sequence and acknowledge numbers.
+Sequence number for event messages is appropriate bus master sequence number increased with
+each event message sent "through" this master.
+Sequence number for userspace requests is set by userspace application.
+Sequence number for reply is the same as was in request, and
+acknowledge number is set to seq+1.
+
+
+Additional documantion, source code examples.
+============================================
+
+1. Documentation/connector
+2. http://tservice.net.ru/~s0mbre/archive/w1
+This archive includes userspace application w1d.c which
+uses read/write/search commands for all master/slave devices found on the bus.
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index f2cd6ef..6887d44 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -205,6 +205,27 @@
   pages  Prereserve that many 128K pages for the software IO bounce buffering.
   force  Force all IO through the software TLB.
 
+  calgary=[64k,128k,256k,512k,1M,2M,4M,8M]
+  calgary=[translate_empty_slots]
+  calgary=[disable=<PCI bus number>]
+
+    64k,...,8M - Set the size of each PCI slot's translation table
+    when using the Calgary IOMMU. This is the size of the translation
+    table itself in main memory. The smallest table, 64k, covers an IO
+    space of 32MB; the largest, 8MB table, can cover an IO space of
+    4GB. Normally the kernel will make the right choice by itself.
+
+    translate_empty_slots - Enable translation even on slots that have
+    no devices attached to them, in case a device will be hotplugged
+    in the future.
+
+    disable=<PCI bus number> - Disable translation on a given PHB. For
+    example, the built-in graphics adapter resides on the first bridge
+    (PCI bus number 0); if translation (isolation) is enabled on this
+    bridge, X servers that access the hardware directly from user
+    space might stop working. Use this option if you have devices that
+    are accessed from userspace directly on some PCI host bridge.
+
 Debugging
 
   oops=panic Always panic on oopses. Default is to just kill the process,
diff --git a/MAINTAINERS b/MAINTAINERS
index c3c5842..31a1372 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -181,6 +181,12 @@
 L:	linux-aio@kvack.org
 S:	Supported
 
+ABIT UGURU HARDWARE MONITOR DRIVER
+P:	Hans de Goede
+M:	j.w.r.degoede@hhs.nl
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 ACENIC DRIVER
 P:	Jes Sorensen
 M:	jes@trained-monkey.org
@@ -568,6 +574,12 @@
 W:	http://www.penguinppc.org/ppc64/
 S:	Supported
 
+BROADCOM B44 10/100 ETHERNET DRIVER
+P:	Gary Zambrano
+M:	zambrano@broadcom.com
+L:	netdev@vger.kernel.org
+S:	Supported
+
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
 P:	Michael Chan
 M:	mchan@broadcom.com
@@ -1106,6 +1118,11 @@
 W:	http://www.lm-sensors.nu/
 S:	Maintained
 
+HARDWARE RANDOM NUMBER GENERATOR CORE
+P:	Michael Buesch
+M:	mb@bu3sch.de
+S:	Maintained
+
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 P:	Robert Love
 M:	rlove@rlove.org
@@ -1147,6 +1164,12 @@
 W:	http://www.nt.tuwien.ac.at/~kkudielk/Linux/
 S:	Maintained
 
+HIGHPOINT ROCKETRAID 3xxx RAID DRIVER
+P:	HighPoint Linux Team
+M:	linux@highpoint-tech.com
+W:	http://www.highpoint-tech.com
+S:	Supported
+
 HIPPI
 P:	Jes Sorensen
 M:	jes@trained-monkey.org
@@ -1378,7 +1401,8 @@
 
 INPUT (KEYBOARD, MOUSE, JOYSTICK) DRIVERS
 P:	Dmitry Torokhov
-M:	dtor_core@ameritech.net
+M:	dmitry.torokhov@gmail.com
+M:	dtor@mail.ru
 L:	linux-input@atrey.karlin.mff.cuni.cz
 L:	linux-joystick@atrey.karlin.mff.cuni.cz
 T:	git kernel.org:/pub/scm/linux/kernel/git/dtor/input.git
@@ -1418,6 +1442,11 @@
 M:	tigran@veritas.com
 S:	Maintained
 
+INTEL IXP4XX RANDOM NUMBER GENERATOR SUPPORT
+P:	Deepak Saxena
+M:	dsaxena@plexity.net
+S:	Maintained
+
 INTEL PRO/100 ETHERNET SUPPORT
 P:	John Ronciak
 M:	john.ronciak@intel.com
@@ -1425,6 +1454,8 @@
 M:	jesse.brandeburg@intel.com
 P:	Jeff Kirsher
 M:	jeffrey.t.kirsher@intel.com
+P:	Auke Kok
+M:	auke-jan.h.kok@intel.com
 W:	http://sourceforge.net/projects/e1000/
 S:	Supported
 
@@ -1437,6 +1468,8 @@
 M:	jesse.brandeburg@intel.com
 P:	Jeff Kirsher
 M:	jeffrey.t.kirsher@intel.com
+P:	Auke Kok
+M:	auke-jan.h.kok@intel.com
 W:	http://sourceforge.net/projects/e1000/
 S:	Supported
 
@@ -1449,6 +1482,8 @@
 M:	john.ronciak@intel.com
 P:	Jesse Brandeburg
 M:	jesse.brandeburg@intel.com
+P:	Auke Kok
+M:	auke-jan.h.kok@intel.com
 W:	http://sourceforge.net/projects/e1000/
 S:	Supported
 
@@ -1837,12 +1872,12 @@
 W:     http://megaraid.lsilogic.com
 S:     Maintained
 
-MEMORY TECHNOLOGY DEVICES
+MEMORY TECHNOLOGY DEVICES (MTD)
 P:	David Woodhouse
 M:	dwmw2@infradead.org
 W:	http://www.linux-mtd.infradead.org/
 L:	linux-mtd@lists.infradead.org
-T:	git kernel.org:/pub/scm/linux/kernel/git/tglx/mtd-2.6.git
+T:	git git://git.infradead.org/mtd-2.6.git
 S:	Maintained
 
 MICROTEK X6 SCANNER
@@ -1889,7 +1924,7 @@
 W:	http://www.atnf.csiro.au/~rgooch/linux/kernel-patches.html
 S:	Maintained
 
-MULTIMEDIA CARD SUBSYSTEM
+MULTIMEDIA CARD (MMC) SUBSYSTEM
 P:	Russell King
 M:	rmk+mmc@arm.linux.org.uk
 S:	Maintained
@@ -2045,6 +2080,12 @@
 L:      linux-fbdev-devel@lists.sourceforge.net
 S:      Maintained
 
+OPENCORES I2C BUS DRIVER
+P:	Peter Korsgaard
+M:	jacmet@sunsite.dk
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+
 ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
 P:	Mark Fasheh
 M:	mark.fasheh@oracle.com
@@ -2516,12 +2557,6 @@
 W:	http://www.winischhofer.at/linuxsisusbvga.shtml
 S:	Maintained
 
-SMSC47M1 HARDWARE MONITOR DRIVER
-P:	Jean Delvare
-M:	khali@linux-fr.org
-L:	lm-sensors@lm-sensors.org
-S:	Odd Fixes
-
 SMB FILESYSTEM
 P:	Urban Widmark
 M:	urban@teststation.com
@@ -2701,6 +2736,11 @@
 M:	hch@infradead.org
 S:	Maintained
 
+TI OMAP RANDOM NUMBER GENERATOR SUPPORT
+P:	Deepak Saxena
+M:	dsaxena@plexity.net
+S:	Maintained
+
 TI PARALLEL LINK CABLE DRIVER
 P:     Romain Lievin
 M:     roms@lpg.ticalc.org
@@ -3134,12 +3174,6 @@
 W:	http://projects.drzeus.cx/wbsd
 S:	Maintained
 
-W83L785TS HARDWARE MONITOR DRIVER
-P:	Jean Delvare
-M:	khali@linux-fr.org
-L:	lm-sensors@lm-sensors.org
-S:	Odd Fixes
-
 WATCHDOG DEVICE DRIVERS
 P:	Wim Van Sebroeck
 M:	wim@iguana.be
@@ -3179,7 +3213,7 @@
 P:	Silicon Graphics Inc
 M:	xfs-masters@oss.sgi.com
 M:	nathans@sgi.com
-L:	linux-xfs@oss.sgi.com
+L:	xfs@oss.sgi.com
 W:	http://oss.sgi.com/projects/xfs
 S:	Supported
 
diff --git a/Makefile b/Makefile
index 1700d3f..e9560c6f 100644
--- a/Makefile
+++ b/Makefile
@@ -71,7 +71,7 @@
 # In both cases the working directory must be the root of the kernel src.
 # 1) O=
 # Use "make O=dir/to/store/output/files/"
-# 
+#
 # 2) Set KBUILD_OUTPUT
 # Set the environment variable KBUILD_OUTPUT to point to the directory
 # where the output files shall be placed.
@@ -178,18 +178,20 @@
 # Architecture as present in compile.h
 UTS_MACHINE := $(ARCH)
 
+KCONFIG_CONFIG	?= .config
+
 # SHELL used by kbuild
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 	  else if [ -x /bin/bash ]; then echo /bin/bash; \
 	  else echo sh; fi ; fi)
 
-HOSTCC  	= gcc
-HOSTCXX  	= g++
-HOSTCFLAGS	= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
-HOSTCXXFLAGS	= -O2
+HOSTCC       = gcc
+HOSTCXX      = g++
+HOSTCFLAGS   = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+HOSTCXXFLAGS = -O2
 
-# 	Decide whether to build built-in, modular, or both.
-#	Normally, just do built-in.
+# Decide whether to build built-in, modular, or both.
+# Normally, just do built-in.
 
 KBUILD_MODULES :=
 KBUILD_BUILTIN := 1
@@ -197,7 +199,7 @@
 #	If we have only "make modules", don't compile built-in objects.
 #	When we're building modules with modversions, we need to consider
 #	the built-in objects during the descend as well, in order to
-#	make sure the checksums are uptodate before we record them.
+#	make sure the checksums are up to date before we record them.
 
 ifeq ($(MAKECMDGOALS),modules)
   KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
@@ -230,7 +232,7 @@
 #
 # If $(quiet) is empty, the whole command will be printed.
 # If it is set to "quiet_", only the short version will be printed. 
-# If it is set to "silent_", nothing wil be printed at all, since
+# If it is set to "silent_", nothing will be printed at all, since
 # the variable $(silent_cmd_cc_o_c) doesn't exist.
 #
 # A simple variant is to prefix commands with $(Q) - that's useful
@@ -265,10 +267,9 @@
 # We need some generic definitions
 include  $(srctree)/scripts/Kbuild.include
 
-# For maximum performance (+ possibly random breakage, uncomment
-# the following)
-
-#MAKEFLAGS += -rR
+# Do not use make's built-in rules and variables
+# This increases performance and avoid hard-to-debug behavour
+MAKEFLAGS += -rR
 
 # Make variables (CC, etc...)
 
@@ -305,21 +306,21 @@
 
 CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
 
-CFLAGS 		:= -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
-	  	   -fno-strict-aliasing -fno-common
-AFLAGS		:= -D__ASSEMBLY__
+CFLAGS          := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \
+                   -fno-strict-aliasing -fno-common
+AFLAGS          := -D__ASSEMBLY__
 
-# Read KERNELRELEASE from .kernelrelease (if it exists)
-KERNELRELEASE = $(shell cat .kernelrelease 2> /dev/null)
+# Read KERNELRELEASE from include/config/kernel.release (if it exists)
+KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
-export	VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION \
-	ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
-	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
-	HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
+export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
+export ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC
+export CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE
+export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
 
 export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
-export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
+export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE
 export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
 
 # When compiling out-of-tree modules, put MODVERDIR in the module
@@ -357,12 +358,13 @@
 # catch them early, and hand them over to scripts/kconfig/Makefile
 # It is allowed to specify more targets when calling make, including
 # mixing *config targets and build targets.
-# For example 'make oldconfig all'. 
+# For example 'make oldconfig all'.
 # Detect when mixed targets is specified, and make a second invocation
 # of make so .config is not included in this case either (for *config).
 
 no-dot-config-targets := clean mrproper distclean \
-			 cscope TAGS tags help %docs check%
+			 cscope TAGS tags help %docs check% \
+			 kernelrelease kernelversion
 
 config-targets := 0
 mixed-targets  := 0
@@ -404,9 +406,8 @@
 export KBUILD_DEFCONFIG
 
 config %config: scripts_basic outputmakefile FORCE
-	$(Q)mkdir -p include/linux
+	$(Q)mkdir -p include/linux include/config
 	$(Q)$(MAKE) $(build)=scripts/kconfig $@
-	$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
 
 else
 # ===========================================================================
@@ -416,13 +417,11 @@
 ifeq ($(KBUILD_EXTMOD),)
 # Additional helpers built in scripts/
 # Carefully list dependencies so we do not try to build scripts twice
-# in parrallel
+# in parallel
 PHONY += scripts
-scripts: scripts_basic include/config/MARKER
+scripts: scripts_basic include/config/auto.conf
 	$(Q)$(MAKE) $(build)=$(@)
 
-scripts_basic: include/linux/autoconf.h
-
 # Objects we will link into vmlinux / subdirs we need to visit
 init-y		:= init/
 drivers-y	:= drivers/ sound/
@@ -436,31 +435,32 @@
 
 # Read in dependencies to all Kconfig* files, make sure to run
 # oldconfig if changes are detected.
--include .kconfig.d
+-include include/config/auto.conf.cmd
+-include include/config/auto.conf
 
-include .config
-
-# If .config needs to be updated, it will be done via the dependency
-# that autoconf has on .config.
 # To avoid any implicit rule to kick in, define an empty command
-.config .kconfig.d: ;
+$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
 
-# If .config is newer than include/linux/autoconf.h, someone tinkered
+# If .config is newer than include/config/auto.conf, someone tinkered
 # with it and forgot to run make oldconfig.
-# If kconfig.d is missing then we are probarly in a cleaned tree so
+# if auto.conf.cmd is missing then we are probably in a cleaned tree so
 # we execute the config step to be sure to catch updated Kconfig files
-include/linux/autoconf.h: .kconfig.d .config
-	$(Q)mkdir -p include/linux
+include/config/auto.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+ifeq ($(KBUILD_EXTMOD),)
 	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
 else
+	$(error kernel configuration not valid - run 'make prepare' in $(srctree) to update it)
+endif
+
+else
 # Dummy target needed, because used as prerequisite
-include/linux/autoconf.h: ;
+include/config/auto.conf: ;
 endif
 
 # The all: target is the default when no target is given on the
 # command line.
 # This allow a user to issue only 'make' to build a kernel including modules
-# Defaults vmlinux but it is usually overriden in the arch makefile
+# Defaults vmlinux but it is usually overridden in the arch makefile
 all: vmlinux
 
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
@@ -492,11 +492,11 @@
 # warn about C99 declaration after statement
 CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
 
-# disable pointer signedness warnings in gcc 4.0
+# disable pointer signed / unsigned warnings in gcc 4.0
 CFLAGS += $(call cc-option,-Wno-pointer-sign,)
 
 # Default kernel image to build when no specific target is given.
-# KBUILD_IMAGE may be overruled on the commandline or
+# KBUILD_IMAGE may be overruled on the command line or
 # set in the environment
 # Also any assignments in arch/$(ARCH)/Makefile take precedence over
 # this default value
@@ -510,12 +510,29 @@
 #
 # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
 # relocations required by build roots.  This is not defined in the
-# makefile but the arguement can be passed to make if needed.
+# makefile but the argument can be passed to make if needed.
 #
 
 MODLIB	= $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
 export MODLIB
 
+#
+#  INSTALL_MOD_STRIP, if defined, will cause modules to be
+#  stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
+#  the default option --strip-debug will be used.  Otherwise,
+#  INSTALL_MOD_STRIP will used as the options to the strip command.
+
+ifdef INSTALL_MOD_STRIP
+ifeq ($(INSTALL_MOD_STRIP),1)
+mod_strip_cmd = $STRIP) --strip-debug
+else
+mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP)
+endif # INSTALL_MOD_STRIP=1
+else
+mod_strip_cmd = true
+endif # INSTALL_MOD_STRIP
+export mod_strip_cmd
+
 
 ifeq ($(KBUILD_EXTMOD),)
 core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
@@ -539,7 +556,7 @@
 
 # Build vmlinux
 # ---------------------------------------------------------------------------
-# vmlinux is build from the objects selected by $(vmlinux-init) and
+# vmlinux is built from the objects selected by $(vmlinux-init) and
 # $(vmlinux-main). Most are built-in.o files from top-level directories
 # in the kernel tree, others are specified in arch/$(ARCH)Makefile.
 # Ordering when linking is important, and $(vmlinux-init) must be first.
@@ -590,7 +607,7 @@
 	$(MAKE) $(build)=init
 
 # Generate System.map
-quiet_cmd_sysmap = SYSMAP 
+quiet_cmd_sysmap = SYSMAP
       cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
 
 # Link of vmlinux
@@ -719,7 +736,7 @@
 	$(Q)$(MAKE) $(build)=$@
 
 # Build the kernel release string
-# The KERNELRELEASE is stored in a file named .kernelrelease
+# The KERNELRELEASE is stored in a file named include/config/kernel.release
 # to be used when executing for example make install or make modules_install
 #
 # Take the contents of any files called localversion* and the config
@@ -737,10 +754,10 @@
 localver = $(subst $(space),, \
 	   $(shell cat /dev/null $(_localver)) \
 	   $(patsubst "%",%,$(CONFIG_LOCALVERSION)))
-	       
+
 # If CONFIG_LOCALVERSION_AUTO is set scripts/setlocalversion is called
 # and if the SCM is know a tag from the SCM is appended.
-# The appended tag is determinded by the SCM used.
+# The appended tag is determined by the SCM used.
 #
 # Currently, only git is supported.
 # Other SCMs can edit scripts/setlocalversion and add the appropriate
@@ -753,9 +770,9 @@
 
 localver-full = $(localver)$(localver-auto)
 
-# Store (new) KERNELRELASE string in .kernelrelease
+# Store (new) KERNELRELASE string in include/config/kernel.release
 kernelrelease = $(KERNELVERSION)$(localver-full)
-.kernelrelease: FORCE
+include/config/kernel.release: include/config/auto.conf FORCE
 	$(Q)rm -f $@
 	$(Q)echo $(kernelrelease) > $@
 
@@ -776,10 +793,10 @@
 # and if so do:
 # 1) Check that make has not been executed in the kernel src $(srctree)
 # 2) Create the include2 directory, used for the second asm symlink
-prepare3: .kernelrelease
+prepare3: include/config/kernel.release
 ifneq ($(KBUILD_SRC),)
 	@echo '  Using $(srctree) as source for kernel'
-	$(Q)if [ -f $(srctree)/.config ]; then \
+	$(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
 		echo "  $(srctree) is not clean, please run 'make mrproper'";\
 		echo "  in the '$(srctree)' directory.";\
 		/bin/false; \
@@ -792,7 +809,7 @@
 prepare2: prepare3 outputmakefile
 
 prepare1: prepare2 include/linux/version.h include/asm \
-                   include/config/MARKER
+                   include/config/auto.conf
 ifneq ($(KBUILD_MODULES),)
 	$(Q)mkdir -p $(MODVERDIR)
 	$(Q)rm -f $(MODVERDIR)/*
@@ -806,27 +823,20 @@
 # All the preparing..
 prepare prepare-all: prepare0
 
-#	Leave this as default for preprocessing vmlinux.lds.S, which is now
-#	done in arch/$(ARCH)/kernel/Makefile
+# Leave this as default for preprocessing vmlinux.lds.S, which is now
+# done in arch/$(ARCH)/kernel/Makefile
 
 export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
 
-# 	FIXME: The asm symlink changes when $(ARCH) changes. That's
-#	hard to detect, but I suppose "make mrproper" is a good idea
-#	before switching between archs anyway.
+# FIXME: The asm symlink changes when $(ARCH) changes. That's
+# hard to detect, but I suppose "make mrproper" is a good idea
+# before switching between archs anyway.
 
 include/asm:
 	@echo '  SYMLINK $@ -> include/asm-$(ARCH)'
 	$(Q)if [ ! -d include ]; then mkdir -p include; fi;
 	@ln -fsn asm-$(ARCH) $@
 
-# 	Split autoconf.h into include/linux/config/*
-
-include/config/MARKER: scripts/basic/split-include include/linux/autoconf.h
-	@echo '  SPLIT   include/linux/autoconf.h -> include/config/*'
-	@scripts/basic/split-include include/linux/autoconf.h include/config
-	@touch $@
-
 # Generate some files
 # ---------------------------------------------------------------------------
 
@@ -846,7 +856,7 @@
 	)
 endef
 
-include/linux/version.h: $(srctree)/Makefile .config .kernelrelease FORCE
+include/linux/version.h: $(srctree)/Makefile include/config/kernel.release FORCE
 	$(call filechk,version.h)
 
 # ---------------------------------------------------------------------------
@@ -860,7 +870,7 @@
 
 ifdef CONFIG_MODULES
 
-# 	By default, build modules as well
+# By default, build modules as well
 
 all: modules
 
@@ -942,7 +952,7 @@
 MRPROPER_DIRS  += include/config include2
 MRPROPER_FILES += .config .config.old include/asm .version .old_version \
                   include/linux/autoconf.h include/linux/version.h \
-		  .kernelrelease Module.symvers tags TAGS cscope*
+		  Module.symvers tags TAGS cscope*
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -958,8 +968,9 @@
 	$(call cmd,rmdirs)
 	$(call cmd,rmfiles)
 	@find . $(RCS_FIND_IGNORE) \
-	 	\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
-		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
+		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
+		-o -name '*.symtypes' \) \
 		-type f -print | xargs rm -f
 
 # mrproper - Delete all generated files, including .config
@@ -982,9 +993,9 @@
 
 distclean: mrproper
 	@find $(srctree) $(RCS_FIND_IGNORE) \
-	 	\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
+		\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
 		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-	 	-o -name '.*.rej' -o -size 0 \
+		-o -name '.*.rej' -o -size 0 \
 		-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
 		-type f -print | xargs rm -f
 
@@ -994,9 +1005,9 @@
 # rpm target kept for backward compatibility
 package-dir	:= $(srctree)/scripts/package
 
-%pkg: FORCE
+%pkg: include/config/kernel.release FORCE
 	$(Q)$(MAKE) $(build)=$(package-dir) $@
-rpm: FORCE
+rpm: include/config/kernel.release FORCE
 	$(Q)$(MAKE) $(build)=$(package-dir) $@
 
 
@@ -1077,7 +1088,7 @@
 # make M=dir modules   Make all modules in specified dir
 # make M=dir	       Same as 'make M=dir modules'
 # make M=dir modules_install
-#                      Install the modules build in the module directory
+#                      Install the modules built in the module directory
 #                      Assumes install directory is already created
 
 # We are always building modules
@@ -1136,7 +1147,7 @@
 clean: $(clean-dirs)
 	$(call cmd,rmdirs)
 	@find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
-	 	\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+		\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
 		-type f -print | xargs rm -f
 
@@ -1175,31 +1186,41 @@
 ALLINCLUDE_ARCHS := $(ARCH)
 endif
 else
-#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behaviour.
+#Allow user to specify only ALLSOURCE_PATHS on the command line, keeping existing behavour.
 ALLINCLUDE_ARCHS := $(ALLSOURCE_ARCHS)
 endif
 
 ALLSOURCE_ARCHS := $(ARCH)
 
-define all-sources
-	( find $(__srctree) $(RCS_FIND_IGNORE) \
+define find-sources
+        ( find $(__srctree) $(RCS_FIND_IGNORE) \
 	       \( -name include -o -name arch \) -prune -o \
-	       -name '*.[chS]' -print; \
+	       -name $1 -print; \
 	  for ARCH in $(ALLSOURCE_ARCHS) ; do \
 	       find $(__srctree)arch/$${ARCH} $(RCS_FIND_IGNORE) \
-	            -name '*.[chS]' -print; \
+	            -name $1 -print; \
 	  done ; \
 	  find $(__srctree)security/selinux/include $(RCS_FIND_IGNORE) \
-	       -name '*.[chS]' -print; \
+	       -name $1 -print; \
 	  find $(__srctree)include $(RCS_FIND_IGNORE) \
 	       \( -name config -o -name 'asm-*' \) -prune \
-	       -o -name '*.[chS]' -print; \
+	       -o -name $1 -print; \
 	  for ARCH in $(ALLINCLUDE_ARCHS) ; do \
 	       find $(__srctree)include/asm-$${ARCH} $(RCS_FIND_IGNORE) \
-	            -name '*.[chS]' -print; \
+	            -name $1 -print; \
 	  done ; \
 	  find $(__srctree)include/asm-generic $(RCS_FIND_IGNORE) \
-	       -name '*.[chS]' -print )
+	       -name $1 -print )
+endef
+
+define all-sources
+	$(call find-sources,'*.[chS]')
+endef
+define all-kconfigs
+	$(call find-sources,'Kconfig*')
+endef
+define all-defconfigs
+	$(call find-sources,'defconfig')
 endef
 
 quiet_cmd_cscope-file = FILELST cscope.files
@@ -1219,7 +1240,13 @@
                 echo "-I __initdata,__exitdata,__acquires,__releases  \
                       -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL              \
                       --extra=+f --c-kinds=+px"`;                     \
-                $(all-sources) | xargs etags $$ETAGSF -a
+                $(all-sources) | xargs etags $$ETAGSF -a;             \
+	if test "x$$ETAGSF" = x; then                                 \
+		$(all-kconfigs) | xargs etags -a                      \
+		--regex='/^config[ \t]+\([a-zA-Z0-9_]+\)/\1/';        \
+		$(all-defconfigs) | xargs etags -a                    \
+		--regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/';     \
+	fi
 endef
 
 TAGS: FORCE
@@ -1259,14 +1286,14 @@
 endif #ifeq ($(config-targets),1)
 endif #ifeq ($(mixed-targets),1)
 
-PHONY += checkstack
+PHONY += checkstack kernelrelease kernelversion
 checkstack:
 	$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
 	$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
 
 kernelrelease:
-	$(if $(wildcard .kernelrelease), $(Q)echo $(KERNELRELEASE), \
-	$(error kernelrelease not valid - run 'make *config' to update it))
+	$(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
+	$(error kernelrelease not valid - run 'make prepare' to update it))
 kernelversion:
 	@echo $(KERNELVERSION)
 
@@ -1301,6 +1328,8 @@
 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 %.o: %.S prepare scripts FORCE
 	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.symtypes: %.c prepare scripts FORCE
+	$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 
 # Modules
 / %/: prepare scripts FORCE
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index 2b245ad..d3848c5 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -53,10 +53,6 @@
 extern void __remqu (void);
 
 EXPORT_SYMBOL(alpha_mv);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(disable_irq_nosync);
-EXPORT_SYMBOL(probe_irq_mask);
 EXPORT_SYMBOL(screen_info);
 EXPORT_SYMBOL(perf_irq);
 EXPORT_SYMBOL(callback_getenv);
@@ -68,19 +64,13 @@
 
 /* platform dependent support */
 EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(__memsetw);
@@ -122,11 +112,9 @@
 
 /* In-kernel system calls.  */
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(sys_open);
 EXPORT_SYMBOL(sys_dup);
 EXPORT_SYMBOL(sys_exit);
 EXPORT_SYMBOL(sys_write);
-EXPORT_SYMBOL(sys_read);
 EXPORT_SYMBOL(sys_lseek);
 EXPORT_SYMBOL(execve);
 EXPORT_SYMBOL(sys_setsid);
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 31afe3d..e15dcf4 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -244,7 +244,7 @@
 	      unsigned long bufsiz)
 {
 	struct kstatfs linux_stat;
-	int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat);
+	int error = vfs_statfs(dentry, &linux_stat);
 	if (!error)
 		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
 	return error;	
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index 558b833..254c507 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -481,7 +481,7 @@
 		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
 		if (!p)
 			return -ENOMEM;
-		register_cpu(p, i, NULL);
+		register_cpu(p, i);
 	}
 	return 0;
 }
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 2e45e86..741da09 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -375,7 +375,7 @@
 static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void __user *)((sp - frame_size) & -32ul);
diff --git a/arch/alpha/oprofile/common.c b/arch/alpha/oprofile/common.c
index ba788cf..9fc0eeb 100644
--- a/arch/alpha/oprofile/common.c
+++ b/arch/alpha/oprofile/common.c
@@ -112,7 +112,7 @@
 
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry *dir;
-		char buf[3];
+		char buf[4];
 
 		snprintf(buf, sizeof buf, "%d", i);
 		dir = oprofilefs_mkdir(sb, root, buf);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 08b7cc9..3d1a3fb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -93,15 +93,49 @@
 	prompt "ARM system type"
 	default ARCH_VERSATILE
 
+config ARCH_AAEC2000
+	bool "Agilent AAEC-2000 based"
+	select ARM_AMBA
+	help
+	  This enables support for systems based on the Agilent AAEC-2000
+
+config ARCH_INTEGRATOR
+	bool "ARM Ltd. Integrator family"
+	select ARM_AMBA
+	select ICST525
+	help
+	  Support for ARM's Integrator platform.
+
+config ARCH_REALVIEW
+	bool "ARM Ltd. RealView family"
+	select ARM_AMBA
+	select ICST307
+	help
+	  This enables support for ARM Ltd RealView boards.
+
+config ARCH_VERSATILE
+	bool "ARM Ltd. Versatile family"
+	select ARM_AMBA
+	select ARM_VIC
+	select ICST307
+	help
+	  This enables support for ARM Ltd Versatile board.
+
+config ARCH_AT91RM9200
+	bool "Atmel AT91RM9200"
+	help
+	  Say Y here if you intend to run this kernel on an Atmel
+	  AT91RM9200-based board.
+
 config ARCH_CLPS7500
-	bool "Cirrus-CL-PS7500FE"
+	bool "Cirrus CL-PS7500FE"
 	select TIMER_ACORN
 	select ISA
 	help
 	  Support for the Cirrus Logic PS7500FE system-on-a-chip.
 
 config ARCH_CLPS711X
-	bool "CLPS711x/EP721x-based"
+	bool "Cirrus Logic CLPS711x/EP721x-based"
 	help
 	  Support for Cirrus Logic 711x/721x based boards.
 
@@ -135,12 +169,22 @@
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
 
-config ARCH_INTEGRATOR
-	bool "Integrator"
-	select ARM_AMBA
-	select ICST525
+config ARCH_NETX
+	bool "Hilscher NetX based"
+	select ARM_VIC
 	help
-	  Support for ARM's Integrator platform.
+	  This enables support for systems based on the Hilscher NetX Soc
+
+config ARCH_H720X
+	bool "Hynix HMS720x-based"
+	select ISA_DMA_API
+	help
+	  This enables support for systems based on the Hynix HMS720x
+
+config ARCH_IMX
+	bool "IMX"
+	help
+	  Support for Motorola's i.MX family of processors (MX1, MXL).
 
 config ARCH_IOP3XX
 	bool "IOP3xx-based"
@@ -178,6 +222,11 @@
 	  If you have any questions or comments about the Linux kernel port
 	  to this board, send e-mail to <sjhill@cotw.com>.
 
+config ARCH_PNX4008
+	bool "Philips Nexperia PNX4008 Mobile"
+	help
+	  This enables support for Philips PNX4008 mobile platform.
+
 config ARCH_PXA
 	bool "PXA2xx-based"
 	select ARCH_MTD_XIP
@@ -204,7 +253,7 @@
 	  Support for StrongARM 11x0 based boards.
 
 config ARCH_S3C2410
-	bool "Samsung S3C2410"
+	bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442"
 	help
 	  Samsung S3C2410X CPU based systems, such as the Simtec Electronics
 	  BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@@ -232,44 +281,6 @@
 	help
 	  Support for TI's OMAP platform (OMAP1 and OMAP2).
 
-config ARCH_VERSATILE
-	bool "Versatile"
-	select ARM_AMBA
-	select ARM_VIC
-	select ICST307
-	help
-	  This enables support for ARM Ltd Versatile board.
-
-config ARCH_REALVIEW
-	bool "RealView"
-	select ARM_AMBA
-	select ICST307
-	help
-	  This enables support for ARM Ltd RealView boards.
-
-config ARCH_IMX
-	bool "IMX"
-	help
-	  Support for Motorola's i.MX family of processors (MX1, MXL).
-
-config ARCH_H720X
-	bool "Hynix-HMS720x-based"
-	select ISA_DMA_API
-	help
-	  This enables support for systems based on the Hynix HMS720x
-
-config ARCH_AAEC2000
-	bool "Agilent AAEC-2000 based"
-	select ARM_AMBA
-	help
-	  This enables support for systems based on the Agilent AAEC-2000
-
-config ARCH_AT91RM9200
-	bool "AT91RM9200"
-	help
-	  Say Y here if you intend to run this kernel on an Atmel
-	  AT91RM9200-based board.
-
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -314,6 +325,8 @@
 
 source "arch/arm/mach-at91rm9200/Kconfig"
 
+source "arch/arm/mach-netx/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
@@ -359,7 +372,7 @@
 	bool
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
+	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX
 	help
 	  Find out whether you have a PCI motherboard. PCI is the name of a
 	  bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 6f8e84c..a3bbaaf 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -116,6 +116,8 @@
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
  machine-$(CONFIG_ARCH_AT91RM9200) := at91rm9200
  machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
+ machine-$(CONFIG_ARCH_PNX4008)    := pnx4008
+ machine-$(CONFIG_ARCH_NETX)       := netx
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
@@ -175,7 +177,7 @@
 #	them changed.  We use .arch to indicate when they were updated
 #	last, otherwise make uses the target directory mtime.
 
-include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/MARKER
+include/asm-arm/.arch: $(wildcard include/config/arch/*.h) include/config/auto.conf
 	@echo '  SYMLINK include/asm-arm/arch -> include/asm-arm/$(INCDIR)'
 ifneq ($(KBUILD_SRC),)
 	$(Q)mkdir -p include/asm-arm
diff --git a/arch/arm/boot/compressed/head-at91rm9200.S b/arch/arm/boot/compressed/head-at91rm9200.S
index 2119ea6..d68b9ac 100644
--- a/arch/arm/boot/compressed/head-at91rm9200.S
+++ b/arch/arm/boot/compressed/head-at91rm9200.S
@@ -49,6 +49,24 @@
 		cmp	r7, r3
 		beq	99f
 
+		@ Embest ATEB9200 : 923
+		mov	r3,	#(MACH_TYPE_ATEB9200 & 0xff)
+		orr	r3, r3,	#(MACH_TYPE_ATEB9200 & 0xff00)
+		cmp	r7, r3
+		beq	99f
+
+		@ Sperry-Sun KAFA : 662
+		mov	r3,	#(MACH_TYPE_KAFA & 0xff)
+		orr	r3, r3,	#(MACH_TYPE_KAFA & 0xff00)
+		cmp	r7, r3
+		beq	99f
+
+		@ Ajeco 1ARM : 1075
+		mov	r3,	#(MACH_TYPE_ONEARM & 0xff)
+		orr	r3, r3, #(MACH_TYPE_ONEARM & 0xff00)
+		cmp	r7, r3
+		beq	99f
+
 		@ Unknown board, use the AT91RM9200DK board
 		@ mov	r7, #MACH_TYPE_AT91RM9200
 		mov	r7,	#(MACH_TYPE_AT91RM9200DK & 0xff)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index b56f5e6..23016f6 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -605,8 +605,8 @@
 		b	__armv4_mmu_cache_off
 		b	__armv4_mmu_cache_flush
 
-		.word	0x00070000		@ ARMv6
-		.word	0x000f0000
+		.word	0x0007b000		@ ARMv6
+		.word	0x0007f000
 		b	__armv4_mmu_cache_on
 		b	__armv4_mmu_cache_off
 		b	__armv6_mmu_cache_flush
diff --git a/arch/arm/boot/compressed/ll_char_wr.S b/arch/arm/boot/compressed/ll_char_wr.S
index d7bbd9d..8517c86 100644
--- a/arch/arm/boot/compressed/ll_char_wr.S
+++ b/arch/arm/boot/compressed/ll_char_wr.S
@@ -77,7 +77,7 @@
 	subne	r1, r1, #1
 	ldrneb	r7, [r6, r1]
 	bne	Lrow4bpplp
-	LOADREGS(fd, sp!, {r4 - r7, pc})
+	ldmfd	sp!, {r4 - r7, pc}
 
 @
 @ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
@@ -105,7 +105,7 @@
 	subne	r1, r1, #1
 	ldrneb	r7, [r6, r1]
 	bne	Lrow8bpplp
-	LOADREGS(fd, sp!, {r4 - r7, pc})
+	ldmfd	sp!, {r4 - r7, pc}
 
 @
 @ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc)
@@ -127,7 +127,7 @@
 	strb	r7, [r0], r5
 	mov	r7, r7, lsr #8
 	strb	r7, [r0], r5
-	LOADREGS(fd, sp!, {r4 - r7, pc})
+	ldmfd	sp!, {r4 - r7, pc}
 
 	.bss
 ENTRY(con_charconvtable)
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 847e3e6..e1289a2 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -16,3 +16,4 @@
 obj-$(CONFIG_SHARPSL_PM)	+= sharpsl_pm.o
 obj-$(CONFIG_SHARP_SCOOP)	+= scoop.o
 obj-$(CONFIG_ARCH_IXP2000)	+= uengine.o
+obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 7971d0d..5b7c263 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -77,6 +77,8 @@
 #endif
 	struct dmabounce_pool	small;
 	struct dmabounce_pool	large;
+
+	rwlock_t lock;
 };
 
 static LIST_HEAD(dmabounce_devs);
@@ -116,6 +118,7 @@
 	struct safe_buffer *buf;
 	struct dmabounce_pool *pool;
 	struct device *dev = device_info->dev;
+	unsigned long flags;
 
 	dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n",
 		__func__, ptr, size, dir);
@@ -163,8 +166,12 @@
 		print_alloc_stats(device_info);
 #endif
 
+	write_lock_irqsave(&device_info->lock, flags);
+
 	list_add(&buf->node, &device_info->safe_buffers);
 
+	write_unlock_irqrestore(&device_info->lock, flags);
+
 	return buf;
 }
 
@@ -172,22 +179,32 @@
 static inline struct safe_buffer *
 find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
 {
-	struct safe_buffer *b;
+	struct safe_buffer *b = NULL;
+	unsigned long flags;
+
+	read_lock_irqsave(&device_info->lock, flags);
 
 	list_for_each_entry(b, &device_info->safe_buffers, node)
 		if (b->safe_dma_addr == safe_dma_addr)
-			return b;
+			break;
 
-	return NULL;
+	read_unlock_irqrestore(&device_info->lock, flags);
+	return b;
 }
 
 static inline void
 free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf)
 {
+	unsigned long flags;
+
 	dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf);
 
+	write_lock_irqsave(&device_info->lock, flags);
+
 	list_del(&buf->node);
 
+	write_unlock_irqrestore(&device_info->lock, flags);
+
 	if (buf->pool)
 		dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr);
 	else
@@ -396,7 +413,6 @@
 dma_map_single(struct device *dev, void *ptr, size_t size,
 		enum dma_data_direction dir)
 {
-	unsigned long flags;
 	dma_addr_t dma_addr;
 
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -404,12 +420,8 @@
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	dma_addr = map_single(dev, ptr, size, dir);
 
-	local_irq_restore(flags);
-
 	return dma_addr;
 }
 
@@ -424,25 +436,18 @@
 dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 			enum dma_data_direction dir)
 {
-	unsigned long flags;
-
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 		__func__, (void *) dma_addr, size, dir);
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	unmap_single(dev, dma_addr, size, dir);
-
-	local_irq_restore(flags);
 }
 
 int
 dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -450,8 +455,6 @@
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		struct page *page = sg->page;
 		unsigned int offset = sg->offset;
@@ -462,8 +465,6 @@
 			map_single(dev, ptr, length, dir);
 	}
 
-	local_irq_restore(flags);
-
 	return nents;
 }
 
@@ -471,7 +472,6 @@
 dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
 		enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -479,55 +479,38 @@
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		dma_addr_t dma_addr = sg->dma_address;
 		unsigned int length = sg->length;
 
 		unmap_single(dev, dma_addr, length, dir);
 	}
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size,
 				enum dma_data_direction dir)
 {
-	unsigned long flags;
-
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 		__func__, (void *) dma_addr, size, dir);
 
-	local_irq_save(flags);
-
 	sync_single(dev, dma_addr, size, dir);
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
 				enum dma_data_direction dir)
 {
-	unsigned long flags;
-
 	dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 		__func__, (void *) dma_addr, size, dir);
 
-	local_irq_save(flags);
-
 	sync_single(dev, dma_addr, size, dir);
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
 			enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -535,23 +518,18 @@
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		dma_addr_t dma_addr = sg->dma_address;
 		unsigned int length = sg->length;
 
 		sync_single(dev, dma_addr, length, dir);
 	}
-
-	local_irq_restore(flags);
 }
 
 void
 dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
 			enum dma_data_direction dir)
 {
-	unsigned long flags;
 	int i;
 
 	dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
@@ -559,16 +537,12 @@
 
 	BUG_ON(dir == DMA_NONE);
 
-	local_irq_save(flags);
-
 	for (i = 0; i < nents; i++, sg++) {
 		dma_addr_t dma_addr = sg->dma_address;
 		unsigned int length = sg->length;
 
 		sync_single(dev, dma_addr, length, dir);
 	}
-
-	local_irq_restore(flags);
 }
 
 static int
@@ -622,6 +596,7 @@
 
 	device_info->dev = dev;
 	INIT_LIST_HEAD(&device_info->safe_buffers);
+	rwlock_init(&device_info->lock);
 
 #ifdef STATS
 	device_info->total_allocs = 0;
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index a7dc137..0dafba3 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -629,21 +629,6 @@
 #endif
 
 
-#define LCM_ALC_EN	0x8000
-
-void frontlight_set(struct locomo *lchip, int duty, int vr, int bpwf)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&lchip->lock, flags);
-	locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
-	udelay(100);
-	locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
-	locomo_writel(bpwf | LCM_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
-	spin_unlock_irqrestore(&lchip->lock, flags);
-}
-
-
 /**
  *	locomo_probe - probe for a single LoCoMo chip.
  *	@phys_addr: physical address of device.
@@ -698,14 +683,10 @@
 			, lchip->base + LOCOMO_GPD);
 	locomo_writel(0, lchip->base + LOCOMO_GIE);
 
-	/* FrontLight */
+	/* Frontlight */
 	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
 	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
 
-	/* Same constants can be used for collie and poodle
-	   (depending on CONFIG options in original sharp code)? */
-	frontlight_set(lchip, 163, 0, 148);
-
 	/* Longtime timer */
 	locomo_writel(0, lchip->base + LOCOMO_LTINT);
 	/* SPI */
@@ -1063,6 +1044,30 @@
 }
 
 /*
+ *	Frontlight control
+ */
+
+static struct locomo *locomo_chip_driver(struct locomo_dev *ldev);
+
+void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf)
+{
+	unsigned long flags;
+	struct locomo *lchip = locomo_chip_driver(dev);
+
+	if (vr)
+		locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 1);
+	else
+		locomo_gpio_write(dev, LOCOMO_GPIO_FL_VR, 0);
+
+	spin_lock_irqsave(&lchip->lock, flags);
+	locomo_writel(bpwf, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+	udelay(100);
+	locomo_writel(duty, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
+	locomo_writel(bpwf | LOCOMO_ALC_EN, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+	spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
+/*
  *	LoCoMo "Register Access Bus."
  *
  *	We model this as a regular bus type, and hang devices directly
diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c
index 3cd8c9e..045e37e 100644
--- a/arch/arm/common/sharpsl_pm.c
+++ b/arch/arm/common/sharpsl_pm.c
@@ -49,13 +49,6 @@
 #define SHARPSL_CHARGE_CO_CHECK_TIME           5   /* 5 msec */
 #define SHARPSL_CHARGE_RETRY_CNT               1   /* eqv. 10 min */
 
-#define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
-#define SHARPSL_CHARGE_ON_TEMP         0xe0  /* 2.9V */
-#define SHARPSL_CHARGE_ON_ACIN_HIGH    0x9b  /* 6V */
-#define SHARPSL_CHARGE_ON_ACIN_LOW     0x34  /* 2V */
-#define SHARPSL_FATAL_ACIN_VOLT        182   /* 3.45V */
-#define SHARPSL_FATAL_NOACIN_VOLT      170   /* 3.40V */
-
 /*
  * Prototypes
  */
@@ -82,12 +75,13 @@
 static int get_percentage(int voltage)
 {
 	int i = sharpsl_pm.machinfo->bat_levels - 1;
+	int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0;
 	struct battery_thresh *thresh;
 
 	if (sharpsl_pm.charge_mode == CHRG_ON)
-		thresh=sharpsl_pm.machinfo->bat_levels_acin;
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin;
 	else
-		thresh=sharpsl_pm.machinfo->bat_levels_noac;
+		thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac;
 
 	while (i > 0 && (voltage > thresh[i].voltage))
 		i--;
@@ -131,7 +125,7 @@
 	sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE);
 
 	/* Corgi cannot confirm when battery fully charged so periodically kick! */
-	if (machine_is_corgi() && (sharpsl_pm.charge_mode == CHRG_ON)
+	if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON)
 			&& time_after(jiffies, sharpsl_pm.charge_start_time +  SHARPSL_CHARGE_ON_TIME_INTERVAL))
 		schedule_work(&toggle_charger);
 
@@ -166,11 +160,11 @@
 			&& ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) ||
 			(sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) {
 		if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) {
-			corgibl_limit_intensity(1);
+			sharpsl_pm.machinfo->backlight_limit(1);
 			sharpsl_pm.flags |= SHARPSL_BL_LIMIT;
 		}
 	} else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) {
-		corgibl_limit_intensity(0);
+		sharpsl_pm.machinfo->backlight_limit(0);
 		sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT;
 	}
 
@@ -418,7 +412,7 @@
 	val = get_select_val(buff);
 
 	dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val);
-	if (val > SHARPSL_CHARGE_ON_TEMP)
+	if (val > sharpsl_pm.machinfo->charge_on_temp)
 		return -1;
 
 	return 0;
@@ -450,7 +444,7 @@
 	val = get_select_val(buff);
 	dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val);
 
-	if (val < SHARPSL_CHARGE_ON_VOLT)
+	if (val < sharpsl_pm.machinfo->charge_on_volt)
 		return -1;
 
 	return 0;
@@ -468,7 +462,7 @@
 	temp = get_select_val(buff);
 	dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp);
 
-	if ((temp > SHARPSL_CHARGE_ON_ACIN_HIGH) || (temp < SHARPSL_CHARGE_ON_ACIN_LOW)) {
+	if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) {
 		dev_err(sharpsl_pm.dev, "Error: AC check failed.\n");
 		return -1;
 	}
@@ -627,8 +621,8 @@
 	temp = get_select_val(buff);
 	dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %d\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT));
 
-	if ((acin && (temp < SHARPSL_FATAL_ACIN_VOLT)) ||
-			(!acin && (temp < SHARPSL_FATAL_NOACIN_VOLT)))
+	if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) ||
+			(!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt)))
 		return -1;
 	return 0;
 }
diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c
index a1310b7..dfca596 100644
--- a/arch/arm/common/uengine.c
+++ b/arch/arm/common/uengine.c
@@ -18,10 +18,26 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <asm/hardware.h>
-#include <asm/arch/ixp2000-regs.h>
+#include <asm/arch/hardware.h>
 #include <asm/hardware/uengine.h>
 #include <asm/io.h>
 
+#if defined(CONFIG_ARCH_IXP2000)
+#define IXP_UENGINE_CSR_VIRT_BASE	IXP2000_UENGINE_CSR_VIRT_BASE
+#define IXP_PRODUCT_ID			IXP2000_PRODUCT_ID
+#define IXP_MISC_CONTROL		IXP2000_MISC_CONTROL
+#define IXP_RESET1			IXP2000_RESET1
+#else
+#if defined(CONFIG_ARCH_IXP23XX)
+#define IXP_UENGINE_CSR_VIRT_BASE	IXP23XX_UENGINE_CSR_VIRT_BASE
+#define IXP_PRODUCT_ID			IXP23XX_PRODUCT_ID
+#define IXP_MISC_CONTROL		IXP23XX_MISC_CONTROL
+#define IXP_RESET1			IXP23XX_RESET1
+#else
+#error unknown platform
+#endif
+#endif
+
 #define USTORE_ADDRESS			0x000
 #define USTORE_DATA_LOWER		0x004
 #define USTORE_DATA_UPPER		0x008
@@ -43,7 +59,7 @@
 
 static void *ixp2000_uengine_csr_area(int uengine)
 {
-	return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
+	return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
 }
 
 /*
@@ -91,8 +107,13 @@
 
 void ixp2000_uengine_reset(u32 uengine_mask)
 {
-	ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask);
-	ixp2000_reg_wrb(IXP2000_RESET1, 0);
+	u32 value;
+
+	value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask;
+
+	uengine_mask &= ixp2000_uengine_mask;
+	ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask);
+	ixp2000_reg_wrb(IXP_RESET1, value);
 }
 EXPORT_SYMBOL(ixp2000_uengine_reset);
 
@@ -235,11 +256,12 @@
 	u32 product_id;
 	u32 rev;
 
-	product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID);
+	product_id = ixp2000_reg_read(IXP_PRODUCT_ID);
 	if (((product_id >> 16) & 0x1f) != 0)
 		return 0;
 
 	switch ((product_id >> 8) & 0xff) {
+#ifdef CONFIG_ARCH_IXP2000
 	case 0:		/* IXP2800 */
 		if (!(c->cpu_model_bitmask & 4))
 			return 0;
@@ -254,6 +276,14 @@
 		if (!(c->cpu_model_bitmask & 2))
 			return 0;
 		break;
+#endif
+
+#ifdef CONFIG_ARCH_IXP23XX
+	case 4:		/* IXP23xx */
+		if (!(c->cpu_model_bitmask & 0x3f0))
+			return 0;
+		break;
+#endif
 
 	default:
 		return 0;
@@ -432,7 +462,8 @@
 	/*
 	 * Determine number of microengines present.
 	 */
-	switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) {
+	switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) {
+#ifdef CONFIG_ARCH_IXP2000
 	case 0:		/* IXP2800 */
 	case 1:		/* IXP2850 */
 		ixp2000_uengine_mask = 0x00ff00ff;
@@ -441,10 +472,17 @@
 	case 2:		/* IXP2400 */
 		ixp2000_uengine_mask = 0x000f000f;
 		break;
+#endif
+
+#ifdef CONFIG_ARCH_IXP23XX
+	case 4:		/* IXP23xx */
+		ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf;
+		break;
+#endif
 
 	default:
 		printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
-			(unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID));
+			(unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID));
 		ixp2000_uengine_mask = 0x00000000;
 		break;
 	}
@@ -457,15 +495,15 @@
 	/*
 	 * Synchronise timestamp counters across all microengines.
 	 */
-	value = ixp2000_reg_read(IXP2000_MISC_CONTROL);
-	ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80);
+	value = ixp2000_reg_read(IXP_MISC_CONTROL);
+	ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80);
 	for (uengine = 0; uengine < 32; uengine++) {
 		if (ixp2000_uengine_mask & (1 << uengine)) {
 			ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
 			ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
 		}
 	}
-	ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80);
+	ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80);
 
 	return 0;
 }
diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig
new file mode 100644
index 0000000..69c39e0
--- /dev/null
+++ b/arch/arm/configs/ateb9200_defconfig
@@ -0,0 +1,1312 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Sun May  7 16:53:18 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+CONFIG_MACH_ATEB9200=y
+# CONFIG_MACH_KAFA is not set
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=m
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+CONFIG_NO_IDLE_HZ=y
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+CONFIG_IEEE80211_CRYPT_WEP=m
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+CONFIG_MTD_BLOCK_RO=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+# CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_PCMCIA_NETWAVE is not set
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+# CONFIG_PCMCIA_RAYCS is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_WL3501 is not set
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_PPP_MPPE is not set
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=m
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+CONFIG_HID_FF=y
+CONFIG_HID_PID=y
+CONFIG_LOGITECH_FF=y
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=y
+CONFIG_USB_NET_CDCETHER=y
+CONFIG_USB_NET_GL620A=y
+CONFIG_USB_NET_NET1080=y
+CONFIG_USB_NET_PLUSB=y
+CONFIG_USB_NET_RNDIS_HOST=y
+CONFIG_USB_NET_CDC_SUBSET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_NET_ZAURUS=y
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CP2101=m
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_FUNSOFT is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=m
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_AT91RM9200=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=m
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=m
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=m
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_AES=m
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_MICHAEL_MIC=m
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig
new file mode 100644
index 0000000..5ccd29a
--- /dev/null
+++ b/arch/arm/configs/carmeva_defconfig
@@ -0,0 +1,723 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc4
+# Tue Jun 14 12:05:24 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+CONFIG_MACH_CARMEVA=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_DISCONTIGMEM is not set
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+CONFIG_ARM_AT91_ETHER_RMII=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=m
+CONFIG_SERIO_SERPORT=m
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+CONFIG_MMC_DEBUG=y
+CONFIG_MMC_BLOCK=m
+CONFIG_MMC_AT91RM9200=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_NAND=y
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig
new file mode 100644
index 0000000..51ded20
--- /dev/null
+++ b/arch/arm/configs/kafa_defconfig
@@ -0,0 +1,884 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Sun May  7 16:54:53 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+CONFIG_MACH_KAFA=y
+
+#
+# AT91 Feature Selections
+#
+# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+# CONFIG_LEDS_TIMER is not set
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20800000,10M root=/dev/ram0 rw"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+# CONFIG_MTD_BLOCK is not set
+CONFIG_MTD_BLOCK_RO=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_AT91_DATAFLASH=y
+# CONFIG_MTD_AT91_DATAFLASH_CARD is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+CONFIG_DAVICOM_PHY=y
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=32
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_AT91_SPI=y
+CONFIG_AT91_SPIDEV=y
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_AT91=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_HCTOSYS is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_AT91=y
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig
new file mode 100644
index 0000000..fee4f56
--- /dev/null
+++ b/arch/arm/configs/kb9202_defconfig
@@ -0,0 +1,780 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-rc2
+# Sun Aug 14 19:26:59 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+# CONFIG_EXPERIMENTAL is not set
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+CONFIG_ARCH_AT91RM9200=y
+
+#
+# AT91RM9200 Implementations
+#
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+CONFIG_MACH_KB9200=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+CONFIG_ISA_DMA_API=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_LEDS is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x10000000
+CONFIG_ZBOOT_ROM_BSS=0x20040000
+CONFIG_ZBOOT_ROM=y
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933"
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+CONFIG_DEBUG_DRIVER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_AT91_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_AT91_SPI is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_DEVPTS_FS_XATTR=y
+# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig
new file mode 100644
index 0000000..d08bbe5
--- /dev/null
+++ b/arch/arm/configs/lpd270_defconfig
@@ -0,0 +1,963 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-git2
+# Wed Jun 21 22:20:18 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+CONFIG_MACH_LOGICPD_PXA270=y
+# CONFIG_MACH_MAINSTONE is not set
+# CONFIG_ARCH_PXA_IDP is not set
+# CONFIG_PXA_SHARPSL is not set
+CONFIG_PXA27x=y
+CONFIG_IWMMXT=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_PM_LEGACY is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_SHARP_SL is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
+# CONFIG_SMC911X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_PXA2XX_PCM=y
+CONFIG_SND_PXA2XX_AC97=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/lpd7a400_defconfig b/arch/arm/configs/lpd7a400_defconfig
index 67eaa26..bf9cf9c 100644
--- a/arch/arm/configs/lpd7a400_defconfig
+++ b/arch/arm/configs/lpd7a400_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:06:33 2005
+# Linux kernel version: 2.6.12
+# Thu Nov  3 14:15:32 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -17,6 +17,7 @@
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -36,6 +37,8 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
@@ -71,6 +74,7 @@
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7952X is not set
 CONFIG_ARCH_LH7A40X=y
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE is not set
@@ -84,6 +88,7 @@
 CONFIG_MACH_LPD7A400=y
 # CONFIG_MACH_LPD7A404 is not set
 CONFIG_ARCH_LH7A400=y
+CONFIG_LPD7A40X_CPLD_SSP=y
 # CONFIG_LH7A40X_CONTIGMEM is not set
 # CONFIG_LH7A40X_ONE_BANK_PER_NODE is not set
 
@@ -110,6 +115,8 @@
 #
 # Bus support
 #
+CONFIG_ARM_AMBA=y
+CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -119,6 +126,7 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 CONFIG_PREEMPT=y
 CONFIG_DISCONTIGMEM=y
 CONFIG_ALIGNMENT_TRAP=y
@@ -175,7 +183,7 @@
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
 
 #
@@ -217,7 +225,10 @@
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
 # CONFIG_MTD_ARM_INTEGRATOR is not set
 # CONFIG_MTD_EDB7312 is not set
 
@@ -254,7 +265,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -288,13 +298,15 @@
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_POLL=y
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
+CONFIG_IDE_ARM=y
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -302,7 +314,37 @@
 #
 # SCSI device support
 #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -331,7 +373,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -438,13 +479,10 @@
 #
 # Userland interfaces
 #
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
@@ -453,7 +491,13 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_ADS7843_LH7=y
+CONFIG_HAS_TOUCHSCREEN_ADS7843_LH7=y
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -461,7 +505,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -479,6 +522,8 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_LH7A40X=y
@@ -510,7 +555,6 @@
 #
 # TPM devices
 #
-# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -534,18 +578,73 @@
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y
+# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_AC97_CODEC=y
+
+#
+# ALSA ARM devices
+#
+CONFIG_SND_LH7A40X_AC97=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
diff --git a/arch/arm/configs/lpd7a404_defconfig b/arch/arm/configs/lpd7a404_defconfig
index 208d591..3a57be32 100644
--- a/arch/arm/configs/lpd7a404_defconfig
+++ b/arch/arm/configs/lpd7a404_defconfig
@@ -1,52 +1,58 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:14:08 2005
+# Linux kernel version: 2.6.16
+# Thu Mar 23 17:50:31 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 # CONFIG_EPOLL is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
@@ -54,6 +60,23 @@
 # CONFIG_MODULES is not set
 
 #
+# Block layer
+#
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+
+#
 # System Type
 #
 # CONFIG_ARCH_CLPS7500 is not set
@@ -71,11 +94,15 @@
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7952X is not set
 CONFIG_ARCH_LH7A40X=y
 # CONFIG_ARCH_OMAP is not set
 # CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
 
 #
 # LH7A40X Implementations
@@ -110,6 +137,7 @@
 #
 # Bus support
 #
+CONFIG_ARM_AMBA=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -120,7 +148,18 @@
 # Kernel Features
 #
 CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+# CONFIG_AEABI is not set
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+# CONFIG_FLATMEM_MANUAL is not set
+CONFIG_DISCONTIGMEM_MANUAL=y
+# CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_DISCONTIGMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_NEED_MULTIPLE_NODES=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -154,6 +193,84 @@
 # Power management options
 #
 # CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -168,6 +285,11 @@
 # CONFIG_DEBUG_DRIVER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
@@ -175,7 +297,7 @@
 # CONFIG_MTD_CONCAT is not set
 CONFIG_MTD_PARTITIONS=y
 # CONFIG_MTD_REDBOOT_PARTS is not set
-# CONFIG_MTD_CMDLINE_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
 # CONFIG_MTD_AFS_PARTS is not set
 
 #
@@ -186,6 +308,7 @@
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -211,15 +334,18 @@
 # CONFIG_MTD_RAM is not set
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x00000000
+CONFIG_MTD_PHYSMAP_LEN=0x04000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
 # CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_PLATRAM is not set
 
 #
 # Self-contained MTD device drivers
@@ -243,6 +369,11 @@
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -254,7 +385,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
@@ -262,16 +392,7 @@
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
 CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -291,12 +412,13 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_POLL=y
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
-# CONFIG_IDE_ARM is not set
+CONFIG_IDE_ARM=y
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -304,6 +426,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 
@@ -315,6 +438,7 @@
 # CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -329,10 +453,12 @@
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
+# CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
 
@@ -344,6 +470,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -354,70 +481,8 @@
 #
 
 #
-# Networking support
+# Network device support
 #
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -425,11 +490,17 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
 CONFIG_SMC91X=y
+# CONFIG_DM9000 is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -456,6 +527,8 @@
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -470,10 +543,13 @@
 #
 # Userland interfaces
 #
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 
 #
@@ -482,7 +558,13 @@
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_TOUCHSCREEN_ADC_LH7=y
+CONFIG_HAS_TOUCHSCREEN_ADC_LH7=y
 # CONFIG_INPUT_MISC is not set
 
 #
@@ -490,7 +572,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -508,6 +589,8 @@
 #
 # Non-8250 serial port support
 #
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_LH7A40X=y
@@ -533,13 +616,13 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
@@ -547,10 +630,33 @@
 # CONFIG_I2C is not set
 
 #
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
 # Misc devices
 #
 
 #
+# Multimedia Capabilities Port drivers
+#
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -563,18 +669,83 @@
 #
 # Graphics support
 #
-# CONFIG_FB is not set
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT=y
+# CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ64D343 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ10D368 is not set
+# CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 is not set
+# CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE is not set
+# CONFIG_FB_ARMCLCD_HITACHI is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
 
 #
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_RTCTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_BUS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# ALSA ARM devices
+#
+# CONFIG_SND_ARMAACI is not set
+CONFIG_SND_LH7A40X_AC97=y
+
+#
+# USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
 
 #
 # USB support
@@ -595,6 +766,7 @@
 #
 # USB Host Controller Drivers
 #
+# CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
@@ -603,16 +775,19 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_USB_BLUETOOTH_TTY is not set
+# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
 #
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DEBUG=y
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 CONFIG_USB_STORAGE_DATAFAB=y
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -621,22 +796,32 @@
 # CONFIG_USB_STORAGE_SDDR09 is not set
 # CONFIG_USB_STORAGE_SDDR55 is not set
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
 
 #
 # USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
 # CONFIG_HID_FF is not set
 # CONFIG_USB_HIDDEV is not set
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
 # CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
 
 #
 # USB Imaging devices
@@ -686,16 +871,33 @@
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
 #
-# USB ATM/DSL drivers
+# USB DSL modem support
 #
 
 #
 # USB Gadget Support
 #
-# CONFIG_USB_GADGET is not set
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+CONFIG_USB_GADGET_LH7=y
+CONFIG_USB_LH7=y
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+CONFIG_USB_ZERO=y
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
 
 #
 # MMC/SD Card support
@@ -707,6 +909,7 @@
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -716,17 +919,17 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-
-#
-# XFS support
-#
+# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -749,12 +952,11 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -769,8 +971,8 @@
 # CONFIG_JFFS_FS is not set
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
-# CONFIG_JFFS2_FS_NAND is not set
-# CONFIG_JFFS2_FS_NOR_ECC is not set
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -787,12 +989,14 @@
 #
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -801,6 +1005,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -820,6 +1025,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
 
 #
@@ -875,19 +1081,24 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
-CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_WAITQ is not set
 CONFIG_DEBUG_ERRORS=y
@@ -912,6 +1123,7 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig
new file mode 100644
index 0000000..61115a7
--- /dev/null
+++ b/arch/arm/configs/netx_defconfig
@@ -0,0 +1,926 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc6
+# Tue Jun  6 15:26:53 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_NETX=y
+
+#
+# NetX Implementations
+#
+CONFIG_MACH_NXDKN=y
+CONFIG_MACH_NXDB500=y
+CONFIG_MACH_NXEB500HMI=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_VIC=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttySMX0,115200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+CONFIG_MTD_PLATRAM=y
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_NET_NETX=y
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_NETX=y
+CONFIG_SERIAL_NETX_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_NVRAM=m
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=m
+CONFIG_RTC_INTF_PROC=m
+CONFIG_RTC_INTF_DEV=m
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_M48T86 is not set
+CONFIG_RTC_DRV_NETX=m
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=17
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_ARC4=m
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig
new file mode 100644
index 0000000..5401c01
--- /dev/null
+++ b/arch/arm/configs/onearm_defconfig
@@ -0,0 +1,1053 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-git10
+# Mon Jun 26 13:45:44 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+CONFIG_ARCH_AT91RM9200=y
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+
+#
+# AT91RM9200 Implementations
+#
+
+#
+# AT91RM9200 Board Type
+#
+CONFIG_MACH_ONEARM=y
+# CONFIG_ARCH_AT91RM9200DK is not set
+# CONFIG_MACH_AT91RM9200EK is not set
+# CONFIG_MACH_CSB337 is not set
+# CONFIG_MACH_CSB637 is not set
+# CONFIG_MACH_CARMEVA is not set
+# CONFIG_MACH_KB9200 is not set
+# CONFIG_MACH_ATEB9200 is not set
+# CONFIG_MACH_KAFA is not set
+
+#
+# AT91RM9200 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+CONFIG_AT91_CF=y
+
+#
+# Kernel Features
+#
+# CONFIG_PREEMPT is not set
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+# CONFIG_APM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x0
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_ARM_AT91_ETHER=y
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_AT91=y
+CONFIG_SERIAL_AT91_CONSOLE=y
+# CONFIG_SERIAL_AT91_TTYAT is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91_WATCHDOG=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_TOUCHSCREEN is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=y
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+CONFIG_USB_GADGET_AT91=y
+CONFIG_USB_AT91=y
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+# CONFIG_USB_GADGET_DUALSPEED is not set
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_ETH is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_AT91RM9200=y
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig
new file mode 100644
index 0000000..8a078d4
--- /dev/null
+++ b/arch/arm/configs/pnx4008_defconfig
@@ -0,0 +1,2072 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc1
+# Thu Apr  6 17:05:58 2006
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+CONFIG_AUDIT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=m
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_AT91RM9200 is not set
+CONFIG_ARCH_PNX4008=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+
+#
+# Bus support
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=m
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=m
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+
+#
+# PC-card bridges
+#
+
+#
+# Kernel Features
+#
+CONFIG_PREEMPT=y
+# CONFIG_NO_IDLE_HZ is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200"
+# CONFIG_XIP_KERNEL is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=m
+CONFIG_BINFMT_MISC=m
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_APM=m
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=m
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=m
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+CONFIG_NET_KEY=m
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_XFRM_TUNNEL=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+CONFIG_IP_VS=m
+# CONFIG_IP_VS_DEBUG is not set
+CONFIG_IP_VS_TAB_BITS=12
+
+#
+# IPVS transport protocol load balancing support
+#
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+
+#
+# IPVS scheduler
+#
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+
+#
+# IPVS application helper
+#
+CONFIG_IP_VS_FTP=m
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_XFRM_TUNNEL=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+# CONFIG_IP_NF_H323 is not set
+CONFIG_IP_NF_QUEUE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+
+#
+# DECnet: Netfilter Configuration
+#
+CONFIG_DECNET_NF_GRABULATOR=m
+
+#
+# Bridge: Netfilter Configuration
+#
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+# CONFIG_BRIDGE_EBT_ULOG is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+CONFIG_ATM=y
+CONFIG_ATM_CLIP=y
+# CONFIG_ATM_CLIP_NO_ICMP is not set
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+# CONFIG_ATM_BR2684_IPFILTER is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_DECNET=m
+# CONFIG_DECNET_ROUTER is not set
+CONFIG_LLC=m
+CONFIG_LLC2=m
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+CONFIG_ATALK=m
+CONFIG_DEV_APPLETALK=y
+CONFIG_IPDDP=m
+CONFIG_IPDDP_ENCAP=y
+CONFIG_IPDDP_DECAP=y
+CONFIG_X25=m
+CONFIG_LAPB=m
+# CONFIG_NET_DIVERT is not set
+CONFIG_ECONET=m
+CONFIG_ECONET_AUNUDP=y
+CONFIG_ECONET_NATIVE=y
+CONFIG_WAN_ROUTER=m
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+# CONFIG_NET_CLS_BASIC is not set
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# Network testing
+#
+CONFIG_NET_PKTGEN=m
+CONFIG_HAMRADIO=y
+
+#
+# Packet Radio protocols
+#
+CONFIG_AX25=m
+# CONFIG_AX25_DAMA_SLAVE is not set
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+
+#
+# AX.25 network device drivers
+#
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_BAYCOM_PAR=m
+CONFIG_BAYCOM_EPP=m
+CONFIG_YAM=m
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRNET=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+CONFIG_IRDA_FAST_RR=y
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+CONFIG_DONGLE=y
+CONFIG_ESI_DONGLE=m
+CONFIG_ACTISYS_DONGLE=m
+CONFIG_TEKRAM_DONGLE=m
+# CONFIG_TOIM3232_DONGLE is not set
+CONFIG_LITELINK_DONGLE=m
+CONFIG_MA600_DONGLE=m
+CONFIG_GIRBIL_DONGLE=m
+CONFIG_MCP2120_DONGLE=m
+CONFIG_OLD_BELKIN_DONGLE=m
+CONFIG_ACT200L_DONGLE=m
+
+#
+# Old SIR device drivers
+#
+CONFIG_IRPORT_SIR=m
+
+#
+# Old Serial dongle support
+#
+# CONFIG_DONGLE_OLD is not set
+
+#
+# FIR device drivers
+#
+CONFIG_USB_IRDA=m
+CONFIG_SIGMATEL_FIR=m
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_CMTP=m
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIUSB=m
+CONFIG_BT_HCIUSB_SCO=y
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIBCM203X=m
+# CONFIG_BT_HCIBPA10X is not set
+CONFIG_BT_HCIBFUSB=m
+CONFIG_BT_HCIDTL1=m
+CONFIG_BT_HCIBT3C=m
+CONFIG_BT_HCIBLUECARD=m
+CONFIG_BT_HCIBTUART=m
+CONFIG_BT_HCIVHCI=m
+CONFIG_IEEE80211=m
+# CONFIG_IEEE80211_DEBUG is not set
+# CONFIG_IEEE80211_CRYPT_WEP is not set
+CONFIG_IEEE80211_CRYPT_CCMP=m
+CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=m
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_FTL=m
+CONFIG_NFTL=m
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=m
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=m
+CONFIG_MTD_CFI_AMDSTD=m
+CONFIG_MTD_CFI_STAA=m
+CONFIG_MTD_CFI_UTIL=m
+CONFIG_MTD_RAM=m
+CONFIG_MTD_ROM=m
+CONFIG_MTD_ABSENT=m
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x4000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_IMPA7 is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=m
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_MTDRAM=m
+CONFIG_MTDRAM_TOTAL_SIZE=4096
+CONFIG_MTDRAM_ERASE_SIZE=128
+CONFIG_MTD_BLKMTD=m
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+CONFIG_MTD_DOC2000=m
+CONFIG_MTD_DOC2001=m
+CONFIG_MTD_DOC2001PLUS=m
+CONFIG_MTD_DOCPROBE=m
+CONFIG_MTD_DOCECC=m
+# CONFIG_MTD_DOCPROBE_ADVANCED is not set
+CONFIG_MTD_DOCPROBE_ADDRESS=0
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+CONFIG_MTD_NAND_IDS=m
+CONFIG_MTD_NAND_DISKONCHIP=m
+# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set
+CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0
+# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_PC_SUPERIO is not set
+CONFIG_PARPORT_PC_PCMCIA=m
+CONFIG_PARPORT_NOT_PC=y
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_GSC is not set
+CONFIG_PARPORT_1284=y
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+CONFIG_PARIDE=m
+CONFIG_PARIDE_PARPORT=m
+
+#
+# Parallel IDE high-level drivers
+#
+CONFIG_PARIDE_PD=m
+CONFIG_PARIDE_PCD=m
+CONFIG_PARIDE_PF=m
+CONFIG_PARIDE_PT=m
+CONFIG_PARIDE_PG=m
+
+#
+# Parallel IDE protocol modules
+#
+CONFIG_PARIDE_ATEN=m
+CONFIG_PARIDE_BPCK=m
+CONFIG_PARIDE_BPCK6=m
+CONFIG_PARIDE_COMM=m
+CONFIG_PARIDE_DSTR=m
+CONFIG_PARIDE_FIT2=m
+CONFIG_PARIDE_FIT3=m
+CONFIG_PARIDE_EPAT=m
+# CONFIG_PARIDE_EPATC8 is not set
+CONFIG_PARIDE_EPIA=m
+CONFIG_PARIDE_FRIQ=m
+CONFIG_PARIDE_FRPW=m
+CONFIG_PARIDE_KBIC=m
+CONFIG_PARIDE_KTTI=m
+CONFIG_PARIDE_ON20=m
+CONFIG_PARIDE_ON26=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=m
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=m
+CONFIG_BLK_DEV_IDECD=m
+CONFIG_BLK_DEV_IDETAPE=m
+CONFIG_BLK_DEV_IDEFLOPPY=m
+CONFIG_BLK_DEV_IDESCSI=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+CONFIG_CHR_DEV_ST=m
+CONFIG_CHR_DEV_OSST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+CONFIG_SCSI_SATA=m
+CONFIG_SCSI_PPA=m
+CONFIG_SCSI_IMM=m
+# CONFIG_SCSI_IZIP_EPP16 is not set
+# CONFIG_SCSI_IZIP_SLOW_CTR is not set
+CONFIG_SCSI_DEBUG=m
+
+#
+# PCMCIA SCSI adapter support
+#
+CONFIG_PCMCIA_AHA152X=m
+CONFIG_PCMCIA_FDOMAIN=m
+CONFIG_PCMCIA_NINJA_SCSI=m
+CONFIG_PCMCIA_QLOGIC=m
+CONFIG_PCMCIA_SYM53C500=m
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID5=m
+# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
+CONFIG_TUN=m
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+CONFIG_NET_POCKET=y
+CONFIG_DE600=m
+CONFIG_DE620=m
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=m
+CONFIG_PCMCIA_WAVELAN=m
+CONFIG_PCMCIA_NETWAVE=m
+
+#
+# Wireless 802.11 Frequency Hopping cards support
+#
+CONFIG_PCMCIA_RAYCS=m
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+CONFIG_ATMEL=m
+
+#
+# Wireless 802.11b Pcmcia/Cardbus cards support
+#
+CONFIG_PCMCIA_HERMES=m
+# CONFIG_PCMCIA_SPECTRUM is not set
+CONFIG_AIRO_CS=m
+CONFIG_PCMCIA_ATMEL=m
+CONFIG_PCMCIA_WL3501=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# PCMCIA network device support
+#
+CONFIG_NET_PCMCIA=y
+CONFIG_PCMCIA_3C589=m
+CONFIG_PCMCIA_3C574=m
+CONFIG_PCMCIA_FMVJ18X=m
+CONFIG_PCMCIA_PCNET=m
+CONFIG_PCMCIA_NMCLAN=m
+CONFIG_PCMCIA_SMC91C92=m
+CONFIG_PCMCIA_XIRC2PS=m
+CONFIG_PCMCIA_AXNET=m
+
+#
+# Wan interfaces
+#
+CONFIG_WAN=y
+CONFIG_SYNCLINK_SYNCPPP=m
+CONFIG_HDLC=m
+CONFIG_HDLC_RAW=y
+CONFIG_HDLC_RAW_ETH=y
+CONFIG_HDLC_CISCO=y
+CONFIG_HDLC_FR=y
+CONFIG_HDLC_PPP=y
+CONFIG_HDLC_X25=y
+CONFIG_DLCI=m
+CONFIG_DLCI_COUNT=24
+CONFIG_DLCI_MAX=8
+CONFIG_WAN_ROUTER_DRIVERS=y
+CONFIG_LAPBETHER=m
+CONFIG_X25_ASY=m
+
+#
+# ATM drivers
+#
+# CONFIG_ATM_DUMMY is not set
+CONFIG_ATM_TCP=m
+CONFIG_PLIP=m
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_MPPE=m
+CONFIG_PPPOE=m
+CONFIG_PPPOATM=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_SHAPER=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+
+#
+# ISDN subsystem
+#
+CONFIG_ISDN=m
+
+#
+# Old ISDN4Linux
+#
+CONFIG_ISDN_I4L=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_IPPP_FILTER=y
+CONFIG_ISDN_PPP_BSDCOMP=m
+CONFIG_ISDN_AUDIO=y
+CONFIG_ISDN_TTY_FAX=y
+CONFIG_ISDN_X25=y
+
+#
+# ISDN feature submodules
+#
+CONFIG_ISDN_DRV_LOOP=m
+CONFIG_ISDN_DIVERSION=m
+
+#
+# ISDN4Linux hardware drivers
+#
+
+#
+# Passive cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+# D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+# CONFIG_HISAX_NO_SENDCOMPLETE is not set
+# CONFIG_HISAX_NO_LLC is not set
+# CONFIG_HISAX_NO_KEYPAD is not set
+CONFIG_HISAX_1TR6=y
+CONFIG_HISAX_NI1=y
+CONFIG_HISAX_MAX_CARDS=8
+
+#
+# HiSax supported cards
+#
+CONFIG_HISAX_16_3=y
+CONFIG_HISAX_S0BOX=y
+CONFIG_HISAX_FRITZPCI=y
+CONFIG_HISAX_AVM_A1_PCMCIA=y
+CONFIG_HISAX_ELSA=y
+CONFIG_HISAX_DIEHLDIVA=y
+CONFIG_HISAX_SEDLBAUER=y
+CONFIG_HISAX_NICCY=y
+CONFIG_HISAX_GAZEL=y
+CONFIG_HISAX_HFC_SX=y
+# CONFIG_HISAX_DEBUG is not set
+
+#
+# HiSax PCMCIA card service modules
+#
+CONFIG_HISAX_SEDLBAUER_CS=m
+CONFIG_HISAX_ELSA_CS=m
+CONFIG_HISAX_AVM_A1_CS=m
+CONFIG_HISAX_TELES_CS=m
+
+#
+# HiSax sub driver modules
+#
+CONFIG_HISAX_ST5481=m
+CONFIG_HISAX_HFCUSB=m
+# CONFIG_HISAX_HFC4S8S is not set
+CONFIG_HISAX_HDLC=y
+
+#
+# Active cards
+#
+
+#
+# Siemens Gigaset
+#
+# CONFIG_ISDN_DRV_GIGASET is not set
+
+#
+# CAPI subsystem
+#
+CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y
+CONFIG_ISDN_CAPI_MIDDLEWARE=y
+CONFIG_ISDN_CAPI_CAPI20=m
+CONFIG_ISDN_CAPI_CAPIFS_BOOL=y
+CONFIG_ISDN_CAPI_CAPIFS=m
+CONFIG_ISDN_CAPI_CAPIDRV=m
+
+#
+# CAPI hardware drivers
+#
+
+#
+# Active AVM cards
+#
+CONFIG_CAPI_AVM=y
+CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m
+CONFIG_ISDN_DRV_AVMB1_AVM_CS=m
+
+#
+# Active Eicon DIVA Server cards
+#
+CONFIG_CAPI_EICON=y
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_TSDEV=m
+CONFIG_INPUT_TSDEV_SCREEN_X=240
+CONFIG_INPUT_TSDEV_SCREEN_Y=320
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+CONFIG_KEYBOARD_SUNKBD=m
+CONFIG_KEYBOARD_LKKBD=m
+CONFIG_KEYBOARD_XTKBD=m
+CONFIG_KEYBOARD_NEWTON=m
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_SERIAL=m
+CONFIG_MOUSE_VSXXXAA=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_ANALOG=m
+CONFIG_JOYSTICK_A3D=m
+CONFIG_JOYSTICK_ADI=m
+CONFIG_JOYSTICK_COBRA=m
+CONFIG_JOYSTICK_GF2K=m
+CONFIG_JOYSTICK_GRIP=m
+CONFIG_JOYSTICK_GRIP_MP=m
+CONFIG_JOYSTICK_GUILLEMOT=m
+CONFIG_JOYSTICK_INTERACT=m
+CONFIG_JOYSTICK_SIDEWINDER=m
+CONFIG_JOYSTICK_TMDC=m
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=y
+CONFIG_JOYSTICK_IFORCE_232=y
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+# CONFIG_JOYSTICK_TWIDJOY is not set
+CONFIG_JOYSTICK_DB9=m
+CONFIG_JOYSTICK_GAMECON=m
+CONFIG_JOYSTICK_TURBOGRAFX=m
+CONFIG_JOYSTICK_JOYDUMP=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_GUNZE=m
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=m
+CONFIG_SERIO_PARKBD=m
+CONFIG_SERIO_LIBPS2=y
+CONFIG_SERIO_RAW=m
+CONFIG_GAMEPORT=m
+CONFIG_GAMEPORT_NS558=m
+CONFIG_GAMEPORT_L4=m
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_SERIAL_NONSTANDARD=y
+CONFIG_COMPUTONE=m
+CONFIG_ROCKETPORT=m
+CONFIG_CYCLADES=m
+# CONFIG_CYZ_INTR is not set
+CONFIG_DIGIEPCA=m
+CONFIG_MOXA_INTELLIO=m
+CONFIG_MOXA_SMARTIO=m
+# CONFIG_ISI is not set
+CONFIG_SYNCLINKMP=m
+CONFIG_N_HDLC=m
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+CONFIG_SX=m
+CONFIG_RIO=m
+CONFIG_RIO_OLDPCI=y
+CONFIG_STALDRV=y
+CONFIG_STALLION=m
+CONFIG_ISTALLION=m
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_CS=m
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+CONFIG_PPDEV=m
+CONFIG_TIPAR=m
+
+#
+# IPMI
+#
+CONFIG_IPMI_HANDLER=m
+# CONFIG_IPMI_PANIC_EVENT is not set
+CONFIG_IPMI_DEVICE_INTERFACE=m
+CONFIG_IPMI_SI=m
+CONFIG_IPMI_WATCHDOG=m
+CONFIG_IPMI_POWEROFF=m
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+CONFIG_USBPCWATCHDOG=m
+CONFIG_NVRAM=m
+CONFIG_DTLK=m
+CONFIG_R3964=m
+
+#
+# Ftape, the floppy tape device driver
+#
+
+#
+# PCMCIA character devices
+#
+CONFIG_SYNCLINK_CS=m
+# CONFIG_CARDMAN_4000 is not set
+# CONFIG_CARDMAN_4040 is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=m
+CONFIG_I2C_ALGOPCF=m
+CONFIG_I2C_ALGOPCA=m
+
+#
+# I2C Hardware Bus support
+#
+CONFIG_I2C_ISA=m
+CONFIG_I2C_PARPORT=m
+CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_STUB=m
+CONFIG_I2C_PCA_ISA=m
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=m
+CONFIG_SENSORS_PCF8574=m
+# CONFIG_SENSORS_PCA9539 is not set
+CONFIG_SENSORS_PCF8591=m
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+CONFIG_W1=m
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS9490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+# CONFIG_W1_SLAVE_SMEM is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+CONFIG_HWMON_VID=m
+CONFIG_SENSORS_ADM1021=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1031=m
+# CONFIG_SENSORS_ADM9240 is not set
+CONFIG_SENSORS_ASB100=m
+# CONFIG_SENSORS_ATXP1 is not set
+CONFIG_SENSORS_DS1621=m
+# CONFIG_SENSORS_F71805F is not set
+CONFIG_SENSORS_FSCHER=m
+# CONFIG_SENSORS_FSCPOS is not set
+CONFIG_SENSORS_GL518SM=m
+# CONFIG_SENSORS_GL520SM is not set
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+# CONFIG_SENSORS_LM92 is not set
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_SMSC47M1=m
+# CONFIG_SENSORS_SMSC47B397 is not set
+CONFIG_SENSORS_W83781D=m
+# CONFIG_SENSORS_W83792D is not set
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83627HF=m
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+CONFIG_DVB=y
+CONFIG_DVB_CORE=m
+
+#
+# Supported USB Adapters
+#
+# CONFIG_DVB_USB is not set
+CONFIG_DVB_TTUSB_BUDGET=m
+CONFIG_DVB_TTUSB_DEC=m
+CONFIG_DVB_CINERGYT2=m
+CONFIG_DVB_CINERGYT2_TUNING=y
+CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32
+CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512
+CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250
+CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y
+CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100
+
+#
+# Supported FlexCopII (B2C2) Adapters
+#
+# CONFIG_DVB_B2C2_FLEXCOP is not set
+
+#
+# Supported DVB Frontends
+#
+
+#
+# Customise DVB Frontends
+#
+
+#
+# DVB-S (satellite) frontends
+#
+CONFIG_DVB_STV0299=m
+CONFIG_DVB_CX24110=m
+# CONFIG_DVB_CX24123 is not set
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_MT312=m
+CONFIG_DVB_VES1X93=m
+# CONFIG_DVB_S5H1420 is not set
+
+#
+# DVB-T (terrestrial) frontends
+#
+CONFIG_DVB_SP8870=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_CX22702=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_TDA1004X=m
+CONFIG_DVB_NXT6000=m
+CONFIG_DVB_MT352=m
+# CONFIG_DVB_ZL10353 is not set
+CONFIG_DVB_DIB3000MB=m
+CONFIG_DVB_DIB3000MC=m
+
+#
+# DVB-C (cable) frontends
+#
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_STV0297=m
+
+#
+# ATSC (North American/Korean Terresterial DTV) frontends
+#
+# CONFIG_DVB_NXT200X is not set
+# CONFIG_DVB_OR51211 is not set
+# CONFIG_DVB_OR51132 is not set
+# CONFIG_DVB_BCM3510 is not set
+# CONFIG_DVB_LGDT330X is not set
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+
+#
+# ALSA ARM devices
+#
+
+#
+# USB devices
+#
+CONFIG_SND_USB_AUDIO=m
+
+#
+# PCMCIA devices
+#
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_TVMIXER=m
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_BANDWIDTH=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_SL811_HCD=m
+# CONFIG_USB_SL811_CS is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+CONFIG_USB_AIPTEK=m
+CONFIG_USB_WACOM=m
+# CONFIG_USB_ACECAD is not set
+CONFIG_USB_KBTAB=m
+CONFIG_USB_POWERMATE=m
+CONFIG_USB_MTOUCH=m
+# CONFIG_USB_ITMTOUCH is not set
+CONFIG_USB_EGALAX=m
+# CONFIG_USB_YEALINK is not set
+CONFIG_USB_XPAD=m
+CONFIG_USB_ATI_REMOTE=m
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+# CONFIG_USB_NET_GL620A is not set
+CONFIG_USB_NET_NET1080=m
+# CONFIG_USB_NET_PLUSB is not set
+# CONFIG_USB_NET_RNDIS_HOST is not set
+# CONFIG_USB_NET_CDC_SUBSET is not set
+CONFIG_USB_NET_ZAURUS=m
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+CONFIG_USB_USS720=m
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_ANYDATA is not set
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+# CONFIG_USB_SERIAL_GARMIN is not set
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_NAVMAN is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+CONFIG_USB_SERIAL_SAFE=m
+# CONFIG_USB_SERIAL_SAFE_PADDED is not set
+# CONFIG_USB_SERIAL_TI is not set
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_EZUSB=y
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+CONFIG_USB_AUERSWALD=m
+CONFIG_USB_RIO500=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_PHIDGETKIT=m
+CONFIG_USB_PHIDGETSERVO=m
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_LD is not set
+CONFIG_USB_TEST=m
+
+#
+# USB DSL modem support
+#
+CONFIG_USB_ATM=m
+CONFIG_USB_SPEEDTOUCH=m
+# CONFIG_USB_CXACRU is not set
+# CONFIG_USB_UEAGLEATM is not set
+# CONFIG_USB_XUSBATM is not set
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_AT91 is not set
+CONFIG_USB_GADGET_DUMMY_HCD=y
+CONFIG_USB_DUMMY_HCD=m
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+
+#
+# MMC/SD Card support
+#
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+CONFIG_MMC_BLOCK=m
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+# CONFIG_JFS_SECURITY is not set
+# CONFIG_JFS_DEBUG is not set
+CONFIG_JFS_STATISTICS=y
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+CONFIG_XFS_QUOTA=y
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
+CONFIG_XFS_RT=y
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V1=m
+CONFIG_QFMT_V2=m
+CONFIG_QUOTACTL=y
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+CONFIG_ADFS_FS=m
+# CONFIG_ADFS_FS_RW is not set
+CONFIG_AFFS_FS=m
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
+CONFIG_BEFS_FS=m
+# CONFIG_BEFS_DEBUG is not set
+CONFIG_BFS_FS=m
+CONFIG_EFS_FS=m
+CONFIG_JFFS_FS=m
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+CONFIG_VXFS_FS=m
+CONFIG_HPFS_FS=m
+CONFIG_QNX4FS_FS=m
+CONFIG_SYSV_FS=m
+CONFIG_UFS_FS=m
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_RPCSEC_GSS_SPKM3=m
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+CONFIG_NCP_FS=m
+CONFIG_NCPFS_PACKET_SIGNING=y
+CONFIG_NCPFS_IOCTL_LOCKING=y
+CONFIG_NCPFS_STRONG=y
+CONFIG_NCPFS_NFS_NS=y
+CONFIG_NCPFS_OS2_NS=y
+# CONFIG_NCPFS_SMALLDOS is not set
+CONFIG_NCPFS_NLS=y
+CONFIG_NCPFS_EXTRAS=y
+CONFIG_CODA_FS=m
+# CONFIG_CODA_FS_OLD_API is not set
+CONFIG_AFS_FS=m
+CONFIG_RXRPC=m
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+# CONFIG_ACORN_PARTITION_CUMANA is not set
+# CONFIG_ACORN_PARTITION_EESOX is not set
+CONFIG_ACORN_PARTITION_ICS=y
+# CONFIG_ACORN_PARTITION_ADFS is not set
+# CONFIG_ACORN_PARTITION_POWERTEC is not set
+CONFIG_ACORN_PARTITION_RISCIX=y
+CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_ATARI_PARTITION=y
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_MINIX_SUBPARTITION=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_UNIXWARE_DISKLABEL=y
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_ULTRIX_PARTITION=y
+CONFIG_SUN_PARTITION=y
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUG_USER is not set
+# CONFIG_DEBUG_WAITQ is not set
+# CONFIG_DEBUG_ERRORS is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=m
+CONFIG_SECURITY_ROOTPLUG=m
+CONFIG_SECURITY_SECLVL=m
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_REED_SOLOMON=m
+CONFIG_REED_SOLOMON_DEC16=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 3cec29d..f20814e 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,12 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Mon Mar 20 20:36:02 2006
+# Linux kernel version: 2.6.17-git9
+# Sun Jun 25 23:56:32 2006
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_VECTORS_BASE=0xffff0000
 
 #
 # Code maturity level options
@@ -27,6 +29,7 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -42,22 +45,16 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
-CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
 #
 CONFIG_MODULES=y
 # CONFIG_MODULE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -65,6 +62,7 @@
 #
 # Block layer
 #
+# CONFIG_BLK_DEV_IO_TRACE is not set
 
 #
 # IO Schedulers
@@ -82,17 +80,26 @@
 #
 # System Type
 #
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91RM9200 is not set
 # CONFIG_ARCH_CLPS7500 is not set
 # CONFIG_ARCH_CLPS711X is not set
 # CONFIG_ARCH_CO285 is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_IOP3XX is not set
 # CONFIG_ARCH_IXP4XX is not set
 # CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
@@ -100,12 +107,6 @@
 # CONFIG_ARCH_SHARK is not set
 # CONFIG_ARCH_LH7A40X is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_REALVIEW is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_AAEC2000 is not set
-# CONFIG_ARCH_AT91RM9200 is not set
 
 #
 # S3C24XX Implementations
@@ -116,14 +117,22 @@
 CONFIG_BAST_PC104_IRQ=y
 CONFIG_ARCH_H1940=y
 CONFIG_MACH_N30=y
+CONFIG_MACH_SMDK=y
 CONFIG_ARCH_SMDK2410=y
 CONFIG_ARCH_S3C2440=y
+CONFIG_SMDK2440_CPU2440=y
+CONFIG_SMDK2440_CPU2442=y
+CONFIG_MACH_SMDK2413=y
 CONFIG_MACH_VR1000=y
 CONFIG_MACH_RX3715=y
 CONFIG_MACH_OTOM=y
 CONFIG_MACH_NEXCODER_2440=y
+CONFIG_S3C2410_CLOCK=y
 CONFIG_CPU_S3C2410=y
+CONFIG_CPU_S3C2412=y
+CONFIG_CPU_S3C244X=y
 CONFIG_CPU_S3C2440=y
+CONFIG_CPU_S3C2442=y
 
 #
 # S3C2410 Boot
@@ -146,8 +155,11 @@
 #
 CONFIG_CPU_32=y
 CONFIG_CPU_ARM920T=y
+CONFIG_CPU_ARM926T=y
 CONFIG_CPU_32v4=y
+CONFIG_CPU_32v5=y
 CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_ABRT_EV5TJ=y
 CONFIG_CPU_CACHE_V4WT=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_COPY_V4WB=y
@@ -160,6 +172,7 @@
 # CONFIG_CPU_ICACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
 
 #
 # Bus support
@@ -207,6 +220,7 @@
 CONFIG_FPE_NWFPE=y
 # CONFIG_FPE_NWFPE_XP is not set
 # CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
 
 #
 # Userspace binary formats
@@ -235,6 +249,8 @@
 # CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
@@ -251,12 +267,18 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -311,6 +333,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -360,7 +383,6 @@
 # CONFIG_MTD_CFI_I8 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
 CONFIG_MTD_CFI_UTIL=y
 # CONFIG_MTD_RAM is not set
@@ -385,7 +407,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -400,10 +421,12 @@
 #
 CONFIG_MTD_NAND=y
 # CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
 CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_NAND_S3C2410=y
 # CONFIG_MTD_NAND_S3C2410_DEBUG is not set
 # CONFIG_MTD_NAND_S3C2410_HWECC is not set
+# CONFIG_MTD_NAND_S3C2410_CLKSTOP is not set
 # CONFIG_MTD_NAND_DISKONCHIP is not set
 # CONFIG_MTD_NAND_NANDSIM is not set
 
@@ -417,8 +440,8 @@
 #
 CONFIG_PARPORT=y
 # CONFIG_PARPORT_PC is not set
-# CONFIG_PARPORT_ARC is not set
 # CONFIG_PARPORT_GSC is not set
+# CONFIG_PARPORT_AX88796 is not set
 CONFIG_PARPORT_1284=y
 
 #
@@ -694,7 +717,6 @@
 #
 # CONFIG_USBPCWATCHDOG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
 CONFIG_S3C2410_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -728,6 +750,7 @@
 #
 # CONFIG_I2C_ELEKTOR is not set
 CONFIG_I2C_ISA=m
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 CONFIG_I2C_S3C2410=y
@@ -743,9 +766,7 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -760,13 +781,13 @@
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
 CONFIG_HWMON_VID=m
+# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -794,8 +815,10 @@
 # CONFIG_SENSORS_MAX1619 is not set
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
@@ -807,18 +830,29 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
 #
 
 #
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -828,6 +862,8 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_MACMODES is not set
+CONFIG_FB_FIRMWARE_EDID=y
+# CONFIG_FB_BACKLIGHT is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_S1D13XXX is not set
@@ -863,6 +899,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -915,9 +952,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -931,15 +966,6 @@
 # CONFIG_USB_MDC800 is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -969,10 +995,12 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
@@ -984,17 +1012,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_PXA2XX is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-# CONFIG_USB_ZERO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
 
 #
 # MMC/SD Card support
@@ -1002,6 +1019,12 @@
 # CONFIG_MMC is not set
 
 #
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1022,6 +1045,7 @@
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
@@ -1052,7 +1076,6 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1193,6 +1216,7 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_VM is not set
 CONFIG_FRAME_POINTER=y
+# CONFIG_UNWIND_INFO is not set
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_USER=y
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index de606df..302fc14 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -702,7 +702,6 @@
 	/*
 	 * Mark this as IO
 	 */
-	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 	if (remap_pfn_range(vma, vma->vm_start, phys,
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index ab8e600..86c9252 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -20,6 +20,7 @@
 #include <asm/glue.h>
 #include <asm/vfpmacros.h>
 #include <asm/arch/entry-macro.S>
+#include <asm/thread_notify.h>
 
 #include "entry-header.S"
 
@@ -560,10 +561,8 @@
 	add	ip, r1, #TI_CPU_SAVE
 	ldr	r3, [r2, #TI_TP_VALUE]
 	stmia	ip!, {r4 - sl, fp, sp, lr}	@ Store most regs on stack
-#ifndef CONFIG_MMU
-	add	r2, r2, #TI_CPU_DOMAIN
-#else
-	ldr	r6, [r2, #TI_CPU_DOMAIN]!
+#ifdef CONFIG_MMU
+	ldr	r6, [r2, #TI_CPU_DOMAIN]
 #endif
 #if __LINUX_ARM_ARCH__ >= 6
 #ifdef CONFIG_CPU_32v6K
@@ -585,21 +584,20 @@
 #ifdef CONFIG_MMU
 	mcr	p15, 0, r6, c3, c0, 0		@ Set domain register
 #endif
-#ifdef CONFIG_VFP
-	@ Always disable VFP so we can lazily save/restore the old
-	@ state. This occurs in the context of the previous thread.
-	VFPFMRX	r4, FPEXC
-	bic	r4, r4, #FPEXC_ENABLE
-	VFPFMXR	FPEXC, r4
-#endif
 #if defined(CONFIG_IWMMXT)
 	bl	iwmmxt_task_switch
 #elif defined(CONFIG_CPU_XSCALE)
-	add	r4, r2, #40			@ cpu_context_save->extra
+	add	r4, r2, #TI_CPU_DOMAIN + 40	@ cpu_context_save->extra
 	ldmib	r4, {r4, r5}
 	mar	acc0, r4, r5
 #endif
-	ldmib	r2, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
+	mov	r5, r0
+	add	r4, r2, #TI_CPU_SAVE
+	ldr	r0, =thread_notify_head
+	mov	r1, #THREAD_NOTIFY_SWITCH
+	bl	atomic_notifier_call_chain
+	mov	r0, r5
+	ldmia	r4, {r4 - sl, fp, sp, pc}	@ Load all regs saved previously
 
 	__INIT
 
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index dbcb11a..75af6d6 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -271,7 +271,7 @@
 @ r8 = syscall table
 		.type	sys_syscall, #function
 sys_syscall:
-		eor	scno, r0, #__NR_OABI_SYSCALL_BASE
+		bic	scno, r0, #__NR_OABI_SYSCALL_BASE
 		cmp	scno, #__NR_syscall - __NR_SYSCALL_BASE
 		cmpne	scno, #NR_syscalls	@ check range
 		stmloia	sp, {r5, r6}		@ shuffle args
@@ -340,7 +340,7 @@
 		streq	r5, [sp, #4]
 		beq	do_mmap2
 		mov	r0, #-EINVAL
-		RETINSTR(mov,pc, lr)
+		mov	pc, lr
 #else
 		str	r5, [sp, #4]
 		b	do_mmap2
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index adf62e5e..2af7e44 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -39,7 +39,7 @@
 	__INIT
 	.type	stext, %function
 ENTRY(stext)
-	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
+	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
 						@ and irqs disabled
 	mrc	p15, 0, r9, c0, c0		@ get processor id
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 04f7344..330b947 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -71,7 +71,7 @@
 	__INIT
 	.type	stext, %function
 ENTRY(stext)
-	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC @ ensure svc mode
+	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE @ ensure svc mode
 						@ and irqs disabled
 	mrc	p15, 0, r9, c0, c0		@ get processor id
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
@@ -104,7 +104,7 @@
 	 * the processor type - there is no need to check the machine type
 	 * as it has already been validated by the primary processor.
 	 */
-	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
+	msr	cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
 	mrc	p15, 0, r9, c0, c0		@ get processor id
 	bl	__lookup_processor_type
 	movs	r10, r5				@ invalid processor?
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 2d5896b..ec20f89 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -52,7 +52,7 @@
  */
 #define MAX_IRQ_CNT	100000
 
-static int noirqdebug;
+static int noirqdebug __read_mostly;
 static volatile unsigned long irq_err_count;
 static DEFINE_SPINLOCK(irq_controller_lock);
 static LIST_HEAD(irq_pending);
@@ -81,7 +81,7 @@
 
 void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
 {
-	irq_err_count += 1;
+	irq_err_count++;
 	printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
 }
 
@@ -342,10 +342,10 @@
 
 #ifdef CONFIG_NO_IDLE_HZ
 	if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
-		write_seqlock(&xtime_lock);
+		spin_lock(&system_timer->dyn_tick->lock);
 		if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
 			system_timer->dyn_tick->handler(irq, 0, regs);
-		write_sequnlock(&xtime_lock);
+		spin_unlock(&system_timer->dyn_tick->lock);
 	}
 #endif
 
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index 24c7b04..a3bae95 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -273,7 +273,7 @@
  *
  * r0 = previous task_struct pointer (must be preserved)
  * r1 = previous thread_info pointer
- * r2 = next thread_info.cpu_domain pointer (must be preserved)
+ * r2 = next thread_info pointer (must be preserved)
  *
  * Called only from __switch_to with task preemption disabled.
  * No need to care about preserving r4 and above.
@@ -285,7 +285,7 @@
 	bne	1f				@ yes: block them for next task
 
 	ldr	r5, =concan_owner
-	add	r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area
+	add	r6, r2, #TI_IWMMXT_STATE	@ get next task Concan save area
 	ldr	r5, [r5]			@ get current Concan owner
 	teq	r5, r6				@ next task owns it?
 	movne	pc, lr				@ no: leave Concan disabled
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 7df6e1a..e1c77ee 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -28,10 +28,12 @@
 #include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/elfcore.h>
+#include <linux/pm.h>
 
 #include <asm/leds.h>
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/thread_notify.h>
 #include <asm/uaccess.h>
 #include <asm/mach/time.h>
 
@@ -71,8 +73,36 @@
 __setup("nohlt", nohlt_setup);
 __setup("hlt", hlt_setup);
 
+void arm_machine_restart(char mode)
+{
+	/*
+	 * Clean and disable cache, and turn off interrupts
+	 */
+	cpu_proc_fin();
+
+	/*
+	 * Tell the mm system that we are going to reboot -
+	 * we may need it to insert some 1:1 mappings so that
+	 * soft boot works.
+	 */
+	setup_mm_for_reboot(mode);
+
+	/*
+	 * Now call the architecture specific reboot code.
+	 */
+	arch_reset(mode);
+
+	/*
+	 * Whoops - the architecture was unable to reboot.
+	 * Tell the user!
+	 */
+	mdelay(1000);
+	printk("Reboot failed -- System halted\n");
+	while (1);
+}
+
 /*
- * The following aren't currently used.
+ * Function pointers to optional machine specific functions
  */
 void (*pm_idle)(void);
 EXPORT_SYMBOL(pm_idle);
@@ -80,6 +110,10 @@
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
+void (*arm_pm_restart)(char str) = arm_machine_restart;
+EXPORT_SYMBOL_GPL(arm_pm_restart);
+
+
 /*
  * This is our default idle handler.  We need to disable
  * interrupts here to ensure we don't miss a wakeup call.
@@ -151,33 +185,9 @@
 		pm_power_off();
 }
 
-
 void machine_restart(char * __unused)
 {
-	/*
-	 * Clean and disable cache, and turn off interrupts
-	 */
-	cpu_proc_fin();
-
-	/*
-	 * Tell the mm system that we are going to reboot -
-	 * we may need it to insert some 1:1 mappings so that
-	 * soft boot works.
-	 */
-	setup_mm_for_reboot(reboot_mode);
-
-	/*
-	 * Now call the architecture specific reboot code.
-	 */
-	arch_reset(reboot_mode);
-
-	/*
-	 * Whoops - the architecture was unable to reboot.
-	 * Tell the user!
-	 */
-	mdelay(1000);
-	printk("Reboot failed -- System halted\n");
-	while (1);
+	arm_pm_restart(reboot_mode);
 }
 
 void __show_regs(struct pt_regs *regs)
@@ -329,13 +339,9 @@
 {
 }
 
-static void default_fp_init(union fp_state *fp)
-{
-	memset(fp, 0, sizeof(union fp_state));
-}
+ATOMIC_NOTIFIER_HEAD(thread_notify_head);
 
-void (*fp_init)(union fp_state *) = default_fp_init;
-EXPORT_SYMBOL(fp_init);
+EXPORT_SYMBOL_GPL(thread_notify_head);
 
 void flush_thread(void)
 {
@@ -344,22 +350,21 @@
 
 	memset(thread->used_cp, 0, sizeof(thread->used_cp));
 	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+	memset(&thread->fpstate, 0, sizeof(union fp_state));
+
+	thread_notify(THREAD_NOTIFY_FLUSH, thread);
 #if defined(CONFIG_IWMMXT)
 	iwmmxt_task_release(thread);
 #endif
-	fp_init(&thread->fpstate);
-#if defined(CONFIG_VFP)
-	vfp_flush_thread(&thread->vfpstate);
-#endif
 }
 
 void release_thread(struct task_struct *dead_task)
 {
-#if defined(CONFIG_VFP)
-	vfp_release_thread(&task_thread_info(dead_task)->vfpstate);
-#endif
+	struct thread_info *thread = task_thread_info(dead_task);
+
+	thread_notify(THREAD_NOTIFY_RELEASE, thread);
 #if defined(CONFIG_IWMMXT)
-	iwmmxt_task_release(task_thread_info(dead_task));
+	iwmmxt_task_release(thread);
 #endif
 }
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 9fc9af8..093ccba 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -808,7 +808,7 @@
 	int cpu;
 
 	for_each_possible_cpu(cpu)
-		register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
+		register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu);
 
 	return 0;
 }
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index a0cd0a9..1ce05ec 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -134,17 +134,6 @@
 
 #ifdef CONFIG_IWMMXT
 
-/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
-#define IWMMXT_STORAGE_SIZE	(0x98 + 8)
-#define IWMMXT_MAGIC0		0x12ef842a
-#define IWMMXT_MAGIC1		0x1c07ca71
-
-struct iwmmxt_sigframe {
-	unsigned long	magic0;
-	unsigned long	magic1;
-	unsigned long	storage[0x98/4];
-};
-
 static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 {
 	char kbuf[sizeof(*frame) + 8];
@@ -152,8 +141,8 @@
 
 	/* the iWMMXt context must be 64 bit aligned */
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
-	kframe->magic0 = IWMMXT_MAGIC0;
-	kframe->magic1 = IWMMXT_MAGIC1;
+	kframe->magic = IWMMXT_MAGIC;
+	kframe->size = IWMMXT_STORAGE_SIZE;
 	iwmmxt_task_copy(current_thread_info(), &kframe->storage);
 	return __copy_to_user(frame, kframe, sizeof(*frame));
 }
@@ -167,8 +156,8 @@
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
 	if (__copy_from_user(kframe, frame, sizeof(*frame)))
 		return -1;
-	if (kframe->magic0 != IWMMXT_MAGIC0 ||
-	    kframe->magic1 != IWMMXT_MAGIC1)
+	if (kframe->magic != IWMMXT_MAGIC ||
+	    kframe->size != IWMMXT_STORAGE_SIZE)
 		return -1;
 	iwmmxt_task_restore(current_thread_info(), &kframe->storage);
 	return 0;
@@ -177,70 +166,61 @@
 #endif
 
 /*
- * Auxiliary signal frame.  This saves stuff like FP state.
- * The layout of this structure is not part of the user ABI.
- */
-struct aux_sigframe {
-#ifdef CONFIG_IWMMXT
-	struct iwmmxt_sigframe	iwmmxt;
-#endif
-#ifdef CONFIG_VFP
-	union vfp_state		vfp;
-#endif
-};
-
-/*
  * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
  */
 struct sigframe {
-	struct sigcontext sc;
-	unsigned long extramask[_NSIG_WORDS-1];
+	struct ucontext uc;
 	unsigned long retcode[2];
-	struct aux_sigframe aux __attribute__((aligned(8)));
 };
 
 struct rt_sigframe {
-	struct siginfo __user *pinfo;
-	void __user *puc;
 	struct siginfo info;
-	struct ucontext uc;
-	unsigned long retcode[2];
-	struct aux_sigframe aux __attribute__((aligned(8)));
+	struct sigframe sig;
 };
 
-static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
-		   struct aux_sigframe __user *aux)
+static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
 {
-	int err = 0;
+	struct aux_sigframe __user *aux;
+	sigset_t set;
+	int err;
 
-	__get_user_error(regs->ARM_r0, &sc->arm_r0, err);
-	__get_user_error(regs->ARM_r1, &sc->arm_r1, err);
-	__get_user_error(regs->ARM_r2, &sc->arm_r2, err);
-	__get_user_error(regs->ARM_r3, &sc->arm_r3, err);
-	__get_user_error(regs->ARM_r4, &sc->arm_r4, err);
-	__get_user_error(regs->ARM_r5, &sc->arm_r5, err);
-	__get_user_error(regs->ARM_r6, &sc->arm_r6, err);
-	__get_user_error(regs->ARM_r7, &sc->arm_r7, err);
-	__get_user_error(regs->ARM_r8, &sc->arm_r8, err);
-	__get_user_error(regs->ARM_r9, &sc->arm_r9, err);
-	__get_user_error(regs->ARM_r10, &sc->arm_r10, err);
-	__get_user_error(regs->ARM_fp, &sc->arm_fp, err);
-	__get_user_error(regs->ARM_ip, &sc->arm_ip, err);
-	__get_user_error(regs->ARM_sp, &sc->arm_sp, err);
-	__get_user_error(regs->ARM_lr, &sc->arm_lr, err);
-	__get_user_error(regs->ARM_pc, &sc->arm_pc, err);
-	__get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0) {
+		sigdelsetmask(&set, ~_BLOCKABLE);
+		spin_lock_irq(&current->sighand->siglock);
+		current->blocked = set;
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+
+	__get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
+	__get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
+	__get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
+	__get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
+	__get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
+	__get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
+	__get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
+	__get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
+	__get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
+	__get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
+	__get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
+	__get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
+	__get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
+	__get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
 
 	err |= !valid_user_regs(regs);
 
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 		err |= restore_iwmmxt_context(&aux->iwmmxt);
 #endif
 #ifdef CONFIG_VFP
 //	if (err == 0)
-//		err |= vfp_restore_state(&aux->vfp);
+//		err |= vfp_restore_state(&sf->aux.vfp);
 #endif
 
 	return err;
@@ -249,7 +229,6 @@
 asmlinkage int sys_sigreturn(struct pt_regs *regs)
 {
 	struct sigframe __user *frame;
-	sigset_t set;
 
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -266,19 +245,8 @@
 
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 		goto badframe;
-	if (__get_user(set.sig[0], &frame->sc.oldmask)
-	    || (_NSIG_WORDS > 1
-	        && __copy_from_user(&set.sig[1], &frame->extramask,
-				    sizeof(frame->extramask))))
-		goto badframe;
 
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (restore_sigcontext(regs, &frame->sc, &frame->aux))
+	if (restore_sigframe(regs, frame))
 		goto badframe;
 
 	/* Send SIGTRAP if we're single-stepping */
@@ -297,7 +265,6 @@
 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame;
-	sigset_t set;
 
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -314,19 +281,11 @@
 
 	if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
 		goto badframe;
-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+
+	if (restore_sigframe(regs, &frame->sig))
 		goto badframe;
 
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
-		goto badframe;
-
-	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
+	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
 		goto badframe;
 
 	/* Send SIGTRAP if we're single-stepping */
@@ -343,42 +302,46 @@
 }
 
 static int
-setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux,
-		 struct pt_regs *regs, unsigned long mask)
+setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
 {
+	struct aux_sigframe __user *aux;
 	int err = 0;
 
-	__put_user_error(regs->ARM_r0, &sc->arm_r0, err);
-	__put_user_error(regs->ARM_r1, &sc->arm_r1, err);
-	__put_user_error(regs->ARM_r2, &sc->arm_r2, err);
-	__put_user_error(regs->ARM_r3, &sc->arm_r3, err);
-	__put_user_error(regs->ARM_r4, &sc->arm_r4, err);
-	__put_user_error(regs->ARM_r5, &sc->arm_r5, err);
-	__put_user_error(regs->ARM_r6, &sc->arm_r6, err);
-	__put_user_error(regs->ARM_r7, &sc->arm_r7, err);
-	__put_user_error(regs->ARM_r8, &sc->arm_r8, err);
-	__put_user_error(regs->ARM_r9, &sc->arm_r9, err);
-	__put_user_error(regs->ARM_r10, &sc->arm_r10, err);
-	__put_user_error(regs->ARM_fp, &sc->arm_fp, err);
-	__put_user_error(regs->ARM_ip, &sc->arm_ip, err);
-	__put_user_error(regs->ARM_sp, &sc->arm_sp, err);
-	__put_user_error(regs->ARM_lr, &sc->arm_lr, err);
-	__put_user_error(regs->ARM_pc, &sc->arm_pc, err);
-	__put_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err);
+	__put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
+	__put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
+	__put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
+	__put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
+	__put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
+	__put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
+	__put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
+	__put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
+	__put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
+	__put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
+	__put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
+	__put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
+	__put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
+	__put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
+	__put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
+	__put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
+	__put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
 
-	__put_user_error(current->thread.trap_no, &sc->trap_no, err);
-	__put_user_error(current->thread.error_code, &sc->error_code, err);
-	__put_user_error(current->thread.address, &sc->fault_address, err);
-	__put_user_error(mask, &sc->oldmask, err);
+	__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);
+	__put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);
+	__put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);
+	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
 
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
 		err |= preserve_iwmmxt_context(&aux->iwmmxt);
 #endif
 #ifdef CONFIG_VFP
 //	if (err == 0)
-//		err |= vfp_save_state(&aux->vfp);
+//		err |= vfp_save_state(&sf->aux.vfp);
 #endif
+	__put_user_error(0, &aux->end_magic, err);
 
 	return err;
 }
@@ -487,13 +450,12 @@
 	if (!frame)
 		return 1;
 
-	err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]);
+	/*
+	 * Set uc.uc_flags to a value which sc.trap_no would never have.
+	 */
+	__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
 
-	if (_NSIG_WORDS > 1) {
-		err |= __copy_to_user(frame->extramask, &set->sig[1],
-				      sizeof(frame->extramask));
-	}
-
+	err |= setup_sigframe(frame, regs, set);
 	if (err == 0)
 		err = setup_return(regs, ka, frame->retcode, frame, usig);
 
@@ -511,25 +473,20 @@
 	if (!frame)
 		return 1;
 
-	__put_user_error(&frame->info, &frame->pinfo, err);
-	__put_user_error(&frame->uc, &frame->puc, err);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
-	__put_user_error(0, &frame->uc.uc_flags, err);
-	__put_user_error(NULL, &frame->uc.uc_link, err);
+	__put_user_error(0, &frame->sig.uc.uc_flags, err);
+	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
 
 	memset(&stack, 0, sizeof(stack));
 	stack.ss_sp = (void __user *)current->sas_ss_sp;
 	stack.ss_flags = sas_ss_flags(regs->ARM_sp);
 	stack.ss_size = current->sas_ss_size;
-	err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
+	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
 
-	err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux,
-				regs, set->sig[0]);
-	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
+	err |= setup_sigframe(&frame->sig, regs, set);
 	if (err == 0)
-		err = setup_return(regs, ka, frame->retcode, frame, usig);
+		err = setup_return(regs, ka, frame->sig.retcode, frame, usig);
 
 	if (err == 0) {
 		/*
@@ -538,7 +495,7 @@
 		 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
 		 */
 		regs->ARM_r1 = (unsigned long)&frame->info;
-		regs->ARM_r2 = (unsigned long)&frame->uc;
+		regs->ARM_r2 = (unsigned long)&frame->sig.uc;
 	}
 
 	return err;
@@ -665,17 +622,33 @@
 	if (syscall) {
 		if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {
 			if (thumb_mode(regs)) {
-				regs->ARM_r7 = __NR_restart_syscall;
+				regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
 				regs->ARM_pc -= 2;
 			} else {
+#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
+				regs->ARM_r7 = __NR_restart_syscall;
+				regs->ARM_pc -= 4;
+#else
 				u32 __user *usp;
+				u32 swival = __NR_restart_syscall;
 
 				regs->ARM_sp -= 12;
 				usp = (u32 __user *)regs->ARM_sp;
 
+				/*
+				 * Either we supports OABI only, or we have
+				 * EABI with the OABI compat layer enabled.
+				 * In the later case we don't know if user
+				 * space is EABI or not, and if not we must
+				 * not clobber r7.  Always using the OABI
+				 * syscall solves that issue and works for
+				 * all those cases.
+				 */
+				swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE;
+
 				put_user(regs->ARM_pc, &usp[0]);
 				/* swi __NR_restart_syscall */
-				put_user(0xef000000 | __NR_restart_syscall, &usp[1]);
+				put_user(0xef000000 | swival, &usp[1]);
 				/* ldr	pc, [sp], #12 */
 				put_user(0xe49df00c, &usp[2]);
 
@@ -683,6 +656,7 @@
 						   (unsigned long)(usp + 3));
 
 				regs->ARM_pc = regs->ARM_sp + 4;
+#endif
 			}
 		}
 		if (regs->ARM_r0 == -ERESTARTNOHAND ||
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index d6bd435..9c12d4f 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -379,7 +379,7 @@
 	int ret = -ENODEV;
 
 	if (dyn_tick) {
-		write_seqlock_irqsave(&xtime_lock, flags);
+		spin_lock_irqsave(&dyn_tick->lock, flags);
 		ret = 0;
 		if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
 			ret = dyn_tick->enable();
@@ -387,7 +387,7 @@
 			if (ret == 0)
 				dyn_tick->state |= DYN_TICK_ENABLED;
 		}
-		write_sequnlock_irqrestore(&xtime_lock, flags);
+		spin_unlock_irqrestore(&dyn_tick->lock, flags);
 	}
 
 	return ret;
@@ -400,7 +400,7 @@
 	int ret = -ENODEV;
 
 	if (dyn_tick) {
-		write_seqlock_irqsave(&xtime_lock, flags);
+		spin_lock_irqsave(&dyn_tick->lock, flags);
 		ret = 0;
 		if (dyn_tick->state & DYN_TICK_ENABLED) {
 			ret = dyn_tick->disable();
@@ -408,7 +408,7 @@
 			if (ret == 0)
 				dyn_tick->state &= ~DYN_TICK_ENABLED;
 		}
-		write_sequnlock_irqrestore(&xtime_lock, flags);
+		spin_unlock_irqrestore(&dyn_tick->lock, flags);
 	}
 
 	return ret;
@@ -422,15 +422,20 @@
 void timer_dyn_reprogram(void)
 {
 	struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
-	unsigned long next, seq;
+	unsigned long next, seq, flags;
 
-	if (dyn_tick && (dyn_tick->state & DYN_TICK_ENABLED)) {
+	if (!dyn_tick)
+		return;
+
+	spin_lock_irqsave(&dyn_tick->lock, flags);
+	if (dyn_tick->state & DYN_TICK_ENABLED) {
 		next = next_timer_interrupt();
 		do {
 			seq = read_seqbegin(&xtime_lock);
-			dyn_tick->reprogram(next_timer_interrupt() - jiffies);
+			dyn_tick->reprogram(next - jiffies);
 		} while (read_seqretry(&xtime_lock, seq));
 	}
+	spin_unlock_irqrestore(&dyn_tick->lock, flags);
 }
 
 static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
@@ -499,5 +504,10 @@
 	if (system_timer->offset == NULL)
 		system_timer->offset = dummy_gettimeoffset;
 	system_timer->init();
+
+#ifdef CONFIG_NO_IDLE_HZ
+	if (system_timer->dyn_tick)
+		system_timer->dyn_tick->lock = SPIN_LOCK_UNLOCKED;
+#endif
 }
 
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 16153c8..058b80d 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -41,7 +41,7 @@
 		movne	r0, #0
 		movs	frame, r0
 1:		moveq	r0, #-2
-		LOADREGS(eqfd, sp!, {r4 - r8, pc})
+		ldmeqfd	sp!, {r4 - r8, pc}
 
 2:		stmfd	sp!, {pc}		@ calculate offset of PC in STMIA instruction
 		ldr	r0, [sp], #4
@@ -85,7 +85,7 @@
 		 * A zero next framepointer means we're done.
 		 */
 		teq	next, #0
-		LOADREGS(eqfd, sp!, {r4 - r8, pc})
+		ldmeqfd	sp!, {r4 - r8, pc}
 
 		/*
 		 * The next framepointer must be above the
@@ -104,7 +104,7 @@
 1007:		ldr	r0, =.Lbad
 		mov	r1, frame
 		bl	printk
-		LOADREGS(fd, sp!, {r4 - r8, pc})
+		ldmfd	sp!, {r4 - r8, pc}
 		.ltorg
 		.previous
 		
@@ -145,7 +145,7 @@
 		adrne	r0, .Lcr
 		blne	printk
 		mov	r0, stack
-		LOADREGS(fd, sp!, {instr, reg, stack, r7, r8, pc})
+		ldmfd	sp!, {instr, reg, stack, r7, r8, pc}
 
 .Lfp:		.asciz	" r%d = %08X%c"
 .Lcr:		.asciz	"\n"
diff --git a/arch/arm/lib/clear_user.S b/arch/arm/lib/clear_user.S
index 7ff9f83..ea435ae 100644
--- a/arch/arm/lib/clear_user.S
+++ b/arch/arm/lib/clear_user.S
@@ -43,10 +43,10 @@
 		tst	r1, #1			@ x1 x0 x1 x0 x1 x0 x1
 USER(		strnebt	r2, [r0], #1)
 		mov	r0, #0
-		LOADREGS(fd,sp!, {r1, pc})
+		ldmfd	sp!, {r1, pc}
 
 		.section .fixup,"ax"
 		.align	0
-9001:		LOADREGS(fd,sp!, {r0, pc})
+9001:		ldmfd	sp!, {r0, pc}
 		.previous
 
diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S
index 6811796..666c99c 100644
--- a/arch/arm/lib/copy_page.S
+++ b/arch/arm/lib/copy_page.S
@@ -43,4 +43,4 @@
 		bgt	1b				@	1
 	PLD(	ldmeqia r1!, {r3, r4, ip, lr}	)
 	PLD(	beq	2b			)
-		LOADREGS(fd, sp!, {r4, pc})		@	3
+		ldmfd	sp!, {r4, pc}			@	3
diff --git a/arch/arm/lib/csumipv6.S b/arch/arm/lib/csumipv6.S
index 7065a20..9621469 100644
--- a/arch/arm/lib/csumipv6.S
+++ b/arch/arm/lib/csumipv6.S
@@ -28,5 +28,5 @@
 		adcs	r0, r0, r3
 		adcs	r0, r0, r2
 		adcs	r0, r0, #0
-		LOADREGS(fd, sp!, {pc})
+		ldmfd	sp!, {pc}
 
diff --git a/arch/arm/lib/delay.S b/arch/arm/lib/delay.S
index 9183b06..930a702 100644
--- a/arch/arm/lib/delay.S
+++ b/arch/arm/lib/delay.S
@@ -31,7 +31,7 @@
 		mov	r2, r2, lsr #10		@ max = 0x00007fff
 		mul	r0, r2, r0		@ max = 2^32-1
 		movs	r0, r0, lsr #6
-		RETINSTR(moveq,pc,lr)
+		moveq	pc, lr
 
 /*
  * loops = r0 * HZ * loops_per_jiffy / 1000000
@@ -43,20 +43,20 @@
 ENTRY(__delay)
 		subs	r0, r0, #1
 #if 0
-		RETINSTR(movls,pc,lr)
+		movls	pc, lr
 		subs	r0, r0, #1
-		RETINSTR(movls,pc,lr)
+		movls	pc, lr
 		subs	r0, r0, #1
-		RETINSTR(movls,pc,lr)
+		movls	pc, lr
 		subs	r0, r0, #1
-		RETINSTR(movls,pc,lr)
+		movls	pc, lr
 		subs	r0, r0, #1
-		RETINSTR(movls,pc,lr)
+		movls	pc, lr
 		subs	r0, r0, #1
-		RETINSTR(movls,pc,lr)
+		movls	pc, lr
 		subs	r0, r0, #1
-		RETINSTR(movls,pc,lr)
+		movls	pc, lr
 		subs	r0, r0, #1
 #endif
 		bhi	__delay
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
diff --git a/arch/arm/lib/ecard.S b/arch/arm/lib/ecard.S
index fb7b602a..c55aaa2 100644
--- a/arch/arm/lib/ecard.S
+++ b/arch/arm/lib/ecard.S
@@ -29,7 +29,7 @@
 		CPSR2SPSR(r0)
 		mov	lr, pc
 		mov	pc, r2
-		LOADREGS(fd, sp!, {r4 - r12, pc})
+		ldmfd	sp!, {r4 - r12, pc}
 
 @ Purpose: call an expansion card loader to reset the card
 @ Proto  : void read_loader(int card_base, char *loader);
@@ -41,5 +41,5 @@
 		CPSR2SPSR(r0)
 		mov	lr, pc
 		add	pc, r1, #8
-		LOADREGS(fd, sp!, {r4 - r12, pc})
+		ldmfd	sp!, {r4 - r12, pc}
 
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 6f8e27a..a5ca024 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -32,7 +32,7 @@
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
 
 /*
  * Purpose  : Find next 'zero' bit
@@ -66,7 +66,7 @@
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
 
 /*
  * Purpose  : Find next 'one' bit
@@ -98,7 +98,7 @@
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
 
 ENTRY(_find_next_zero_bit_be)
 		teq	r1, #0
@@ -126,7 +126,7 @@
 2:		cmp	r2, r1			@ any more?
 		blo	1b
 3:		mov	r0, r1			@ no free bits
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
 
 ENTRY(_find_next_bit_be)
 		teq	r1, #0
@@ -164,5 +164,5 @@
 		addeq	r2, r2, #1
 		mov	r0, r2
 #endif
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
 
diff --git a/arch/arm/lib/io-readsb.S b/arch/arm/lib/io-readsb.S
index d3d8de7..fb966ad 100644
--- a/arch/arm/lib/io-readsb.S
+++ b/arch/arm/lib/io-readsb.S
@@ -72,7 +72,7 @@
 		bpl	.Linsb_16_lp
 
 		tst	r2, #15
-		LOADREGS(eqfd, sp!, {r4 - r6, pc})
+		ldmeqfd	sp!, {r4 - r6, pc}
 
 .Linsb_no_16:	tst	r2, #8
 		beq	.Linsb_no_8
@@ -109,7 +109,7 @@
 		str	r3, [r1], #4
 
 .Linsb_no_4:	ands	r2, r2, #3
-		LOADREGS(eqfd, sp!, {r4 - r6, pc})
+		ldmeqfd	sp!, {r4 - r6, pc}
 
 		cmp	r2, #2
 		ldrb	r3, [r0]
@@ -119,4 +119,4 @@
 		ldrgtb	r3, [r0]
 		strgtb	r3, [r1]
 
-		LOADREGS(fd, sp!, {r4 - r6, pc})
+		ldmfd	sp!, {r4 - r6, pc}
diff --git a/arch/arm/lib/io-readsw-armv3.S b/arch/arm/lib/io-readsw-armv3.S
index 146d47c..4ef9041 100644
--- a/arch/arm/lib/io-readsw-armv3.S
+++ b/arch/arm/lib/io-readsw-armv3.S
@@ -28,7 +28,7 @@
 		strb	r3, [r1], #1
 
 		subs	r2, r2, #1
-		RETINSTR(moveq, pc, lr)
+		moveq	pc, lr
 
 ENTRY(__raw_readsw)
 		teq	r2, #0		@ do we have to check for the zero len?
@@ -69,7 +69,7 @@
 		bpl	.Linsw_8_lp
 
 		tst	r2, #7
-		LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+		ldmeqfd	sp!, {r4, r5, r6, pc}
 
 .Lno_insw_8:	tst	r2, #4
 		beq	.Lno_insw_4
@@ -102,6 +102,6 @@
 		movne	r3, r3, lsr #8
 		strneb	r3, [r1]
 
-		LOADREGS(fd, sp!, {r4, r5, r6, pc})
+		ldmfd	sp!, {r4, r5, r6, pc}
 
 
diff --git a/arch/arm/lib/io-writesb.S b/arch/arm/lib/io-writesb.S
index 08209fc..7eba2b6 100644
--- a/arch/arm/lib/io-writesb.S
+++ b/arch/arm/lib/io-writesb.S
@@ -64,7 +64,7 @@
 		bpl	.Loutsb_16_lp
 
 		tst	r2, #15
-		LOADREGS(eqfd, sp!, {r4, r5, pc})
+		ldmeqfd	sp!, {r4, r5, pc}
 
 .Loutsb_no_16:	tst	r2, #8
 		beq	.Loutsb_no_8
@@ -80,7 +80,7 @@
 		outword	r3
 
 .Loutsb_no_4:	ands	r2, r2, #3
-		LOADREGS(eqfd, sp!, {r4, r5, pc})
+		ldmeqfd	sp!, {r4, r5, pc}
 
 		cmp	r2, #2
 		ldrb	r3, [r1], #1
@@ -90,4 +90,4 @@
 		ldrgtb	r3, [r1]
 		strgtb	r3, [r0]
 
-		LOADREGS(fd, sp!, {r4, r5, pc})
+		ldmfd	sp!, {r4, r5, pc}
diff --git a/arch/arm/lib/io-writesw-armv3.S b/arch/arm/lib/io-writesw-armv3.S
index 52d62b4..1607a29f 100644
--- a/arch/arm/lib/io-writesw-armv3.S
+++ b/arch/arm/lib/io-writesw-armv3.S
@@ -29,7 +29,7 @@
 		orr	r3, r3, r3, lsl #16
 		str	r3, [r0]
 		subs	r2, r2, #1
-		RETINSTR(moveq, pc, lr)
+		moveq	pc, lr
 
 ENTRY(__raw_writesw)
 		teq	r2, #0		@ do we have to check for the zero len?
@@ -80,7 +80,7 @@
 		bpl	.Loutsw_8_lp
 
 		tst	r2, #7
-		LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
+		ldmeqfd	sp!, {r4, r5, r6, pc}
 
 .Lno_outsw_8:	tst	r2, #4
 		beq	.Lno_outsw_4
@@ -124,4 +124,4 @@
 		orrne	ip, ip, ip, lsr #16
 		strne	ip, [r0]
 
-		LOADREGS(fd, sp!, {r4, r5, r6, pc})
+		ldmfd	sp!, {r4, r5, r6, pc}
diff --git a/arch/arm/lib/memchr.S b/arch/arm/lib/memchr.S
index ac34fe5..e7ab1ea 100644
--- a/arch/arm/lib/memchr.S
+++ b/arch/arm/lib/memchr.S
@@ -22,4 +22,4 @@
 	bne	1b
 	sub	r0, r0, #1
 2:	movne	r0, #0
-	RETINSTR(mov,pc,lr)
+	mov	pc, lr
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S
index a1795f59..95b110b 100644
--- a/arch/arm/lib/memset.S
+++ b/arch/arm/lib/memset.S
@@ -53,7 +53,7 @@
 	stmgeia	r0!, {r1, r3, ip, lr}
 	stmgeia	r0!, {r1, r3, ip, lr}
 	bgt	2b
-	LOADREGS(eqfd, sp!, {pc})	@ Now <64 bytes to go.
+	ldmeqfd	sp!, {pc}		@ Now <64 bytes to go.
 /*
  * No need to correct the count; we're only testing bits from now on
  */
@@ -77,4 +77,4 @@
 	strneb	r1, [r0], #1
 	tst	r2, #1
 	strneb	r1, [r0], #1
-	RETINSTR(mov,pc,lr)
+	mov	pc, lr
diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S
index 51ccc60..abf2508e 100644
--- a/arch/arm/lib/memzero.S
+++ b/arch/arm/lib/memzero.S
@@ -53,7 +53,7 @@
 	stmgeia	r0!, {r2, r3, ip, lr}	@ 4
 	stmgeia	r0!, {r2, r3, ip, lr}	@ 4
 	bgt	3b			@ 1
-	LOADREGS(eqfd, sp!, {pc})	@ 1/2 quick exit
+	ldmeqfd	sp!, {pc}		@ 1/2 quick exit
 /*
  * No need to correct the count; we're only testing bits from now on
  */
@@ -77,4 +77,4 @@
 	strneb	r2, [r0], #1		@ 1
 	tst	r1, #1			@ 1 a byte left over
 	strneb	r2, [r0], #1		@ 1
-	RETINSTR(mov,pc,lr)		@ 1
+	mov	pc, lr			@ 1
diff --git a/arch/arm/lib/strchr.S b/arch/arm/lib/strchr.S
index 5b9b493..9f18d6f 100644
--- a/arch/arm/lib/strchr.S
+++ b/arch/arm/lib/strchr.S
@@ -23,4 +23,4 @@
 		teq	r2, r1
 		movne	r0, #0
 		subeq	r0, r0, #1
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
diff --git a/arch/arm/lib/strncpy_from_user.S b/arch/arm/lib/strncpy_from_user.S
index 629cc87..35649f0 100644
--- a/arch/arm/lib/strncpy_from_user.S
+++ b/arch/arm/lib/strncpy_from_user.S
@@ -21,7 +21,6 @@
  *  -EFAULT on exception, or "len" if we fill the whole buffer
  */
 ENTRY(__arch_strncpy_from_user)
-	save_lr
 	mov	ip, r1
 1:	subs	r2, r2, #1
 USER(	ldrplbt	r3, [r1], #1)
@@ -31,13 +30,13 @@
 	bne	1b
 	sub	r1, r1, #1	@ take NUL character out of count
 2:	sub	r0, r1, ip
-	restore_pc
+	mov	pc, lr
 
 	.section .fixup,"ax"
 	.align	0
 9001:	mov	r3, #0
 	strb	r3, [r0, #0]	@ null terminate
 	mov	r0, #-EFAULT
-	restore_pc
+	mov	pc, lr
 	.previous
 
diff --git a/arch/arm/lib/strnlen_user.S b/arch/arm/lib/strnlen_user.S
index 67bcd82..3668a15 100644
--- a/arch/arm/lib/strnlen_user.S
+++ b/arch/arm/lib/strnlen_user.S
@@ -21,7 +21,6 @@
  *	      or zero on exception, or n + 1 if too long
  */
 ENTRY(__arch_strnlen_user)
-	save_lr
 	mov	r2, r0
 1:
 USER(	ldrbt	r3, [r0], #1)
@@ -31,10 +30,10 @@
 	bne	1b
 	add	r0, r0, #1
 2:	sub	r0, r0, r2
-	restore_pc
+	mov	pc, lr
 
 	.section .fixup,"ax"
 	.align	0
 9001:	mov	r0, #0
-	restore_pc
+	mov	pc, lr
 	.previous
diff --git a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S
index fa923f0..538df22 100644
--- a/arch/arm/lib/strrchr.S
+++ b/arch/arm/lib/strrchr.S
@@ -22,4 +22,4 @@
 		teq	r2, #0
 		bne	1b
 		mov	r0, r3
-		RETINSTR(mov,pc,lr)
+		mov	pc, lr
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
index 0cc450f..1f1545d 100644
--- a/arch/arm/lib/uaccess.S
+++ b/arch/arm/lib/uaccess.S
@@ -105,7 +105,7 @@
 		movs	ip, r2
 		bne	.Lc2u_nowords
 .Lc2u_finished:	mov	r0, #0
-		LOADREGS(fd,sp!,{r2, r4 - r7, pc})
+		ldmfd	sp!, {r2, r4 - r7, pc}
 
 .Lc2u_src_not_aligned:
 		bic	r1, r1, #3
@@ -280,7 +280,7 @@
 
 		.section .fixup,"ax"
 		.align	0
-9001:		LOADREGS(fd,sp!, {r0, r4 - r7, pc})
+9001:		ldmfd	sp!, {r0, r4 - r7, pc}
 		.previous
 
 /* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
@@ -369,7 +369,7 @@
 		bne	.Lcfu_nowords
 .Lcfu_finished:	mov	r0, #0
 		add	sp, sp, #8
-		LOADREGS(fd,sp!,{r4 - r7, pc})
+		ldmfd	sp!, {r4 - r7, pc}
 
 .Lcfu_src_not_aligned:
 		bic	r1, r1, #3
@@ -556,6 +556,6 @@
 		movne	r1, r4
 		blne	__memzero
 		mov	r0, r4
-		LOADREGS(fd,sp!, {r4 - r7, pc})
+		ldmfd	sp!, {r4 - r7, pc}
 		.previous
 
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig
index 4b7218f..70d402f 100644
--- a/arch/arm/mach-at91rm9200/Kconfig
+++ b/arch/arm/mach-at91rm9200/Kconfig
@@ -4,6 +4,12 @@
 
 comment "AT91RM9200 Board Type"
 
+config MACH_ONEARM
+	bool "Ajeco 1ARM Single Board Computer"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Ajeco's 1ARM Single Board Computer
+
 config ARCH_AT91RM9200DK
 	bool "Atmel AT91RM9200-DK Development board"
 	depends on ARCH_AT91RM9200
@@ -40,6 +46,18 @@
 	help
 	  Select this if you are using KwikByte's KB920x board
 
+config MACH_ATEB9200
+	bool "Embest's ATEB9200"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Embest's ATEB9200 board
+
+config MACH_KAFA
+	bool "Sperry-Sun KAFA board"
+	depends on ARCH_AT91RM9200
+	help
+	  Select this if you are using Sperry-Sun's KAFA board
+
 
 comment "AT91RM9200 Feature Selections"
 
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile
index ef88c41..82db957 100644
--- a/arch/arm/mach-at91rm9200/Makefile
+++ b/arch/arm/mach-at91rm9200/Makefile
@@ -7,22 +7,32 @@
 obj-n		:=
 obj-		:=
 
+obj-$(CONFIG_PM)		+= pm.o
+
 # Board-specific support
+obj-$(CONFIG_MACH_ONEARM)	+= board-1arm.o
 obj-$(CONFIG_ARCH_AT91RM9200DK)	+= board-dk.o
 obj-$(CONFIG_MACH_AT91RM9200EK)	+= board-ek.o
 obj-$(CONFIG_MACH_CSB337)	+= board-csb337.o
 obj-$(CONFIG_MACH_CSB637)	+= board-csb637.o
-#obj-$(CONFIG_MACH_CARMEVA)	+= board-carmeva.o
-#obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
+obj-$(CONFIG_MACH_CARMEVA)	+= board-carmeva.o
+obj-$(CONFIG_MACH_KB9200)	+= board-kb9202.o
+obj-$(CONFIG_MACH_ATEB9200)	+= board-eb9200.o
+obj-$(CONFIG_MACH_KAFA)		+= board-kafa.o
 
 # LEDs support
 led-$(CONFIG_ARCH_AT91RM9200DK)	+= leds.o
 led-$(CONFIG_MACH_AT91RM9200EK)	+= leds.o
 led-$(CONFIG_MACH_CSB337)	+= leds.o
 led-$(CONFIG_MACH_CSB637)	+= leds.o
-#led-$(CONFIG_MACH_KB9200)	+= leds.o
-#led-$(CONFIG_MACH_KAFA)	+= leds.o
+led-$(CONFIG_MACH_KB9200)	+= leds.o
+led-$(CONFIG_MACH_KAFA)		+= leds.o
 obj-$(CONFIG_LEDS) += $(led-y)
 
 # VGA support
 #obj-$(CONFIG_FB_S1D13XXX)	+= ics1523.o
+
+
+ifeq ($(CONFIG_PM_DEBUG),y)
+CFLAGS_pm.o += -DDEBUG
+endif
diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91rm9200/board-1arm.c
new file mode 100644
index 0000000..dc79e09
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-1arm.c
@@ -0,0 +1,109 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-1arm.c
+ *
+ *  Copyright (C) 2005 SAN People
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init onearm_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata onearm_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 3,
+	.tty_map	= { 4, 0, 1, -1, -1 },		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init onearm_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 18.432 MHz crystal */
+	at91_clock_init(18432000);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&onearm_uart_config);
+}
+
+static struct at91_eth_data __initdata onearm_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata onearm_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata onearm_udc_data = {
+	.vbus_pin	= AT91_PIN_PC2,
+	.pullup_pin	= AT91_PIN_PC3,
+};
+
+static void __init onearm_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&onearm_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&onearm_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&onearm_udc_data);
+}
+
+MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
+	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= onearm_map_io,
+	.init_irq	= onearm_init_irq,
+	.init_machine	= onearm_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c
new file mode 100644
index 0000000..2c138b5
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-carmeva.c
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-carmeva.c
+ *
+ *  Copyright (c) 2005 Peer Georgi
+ *  		       Conitec Datasystems
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init carmeva_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata carmeva_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init carmeva_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 20.000 MHz crystal */
+	at91_clock_init(20000000);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&carmeva_uart_config);
+}
+
+static struct at91_eth_data __initdata carmeva_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata carmeva_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata carmeva_udc_data = {
+	.vbus_pin	= AT91_PIN_PD12,
+	.pullup_pin	= AT91_PIN_PD9,
+};
+
+/* FIXME: user dependend */
+// static struct at91_cf_data __initdata carmeva_cf_data = {
+//	.det_pin	= AT91_PIN_PB0,
+//	.rst_pin	= AT91_PIN_PC5,
+	// .irq_pin	= ... not connected
+	// .vcc_pin	= ... always powered
+// };
+
+static struct at91_mmc_data __initdata carmeva_mmc_data = {
+	.is_b		= 0,
+	.wire4		= 1,
+};
+
+static void __init carmeva_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&carmeva_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&carmeva_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&carmeva_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* Compact Flash */
+//	at91_add_device_cf(&carmeva_cf_data);
+	/* SPI */
+//	at91_add_device_spi(NULL, 0);
+	/* MMC */
+	at91_add_device_mmc(&carmeva_mmc_data);
+}
+
+MACHINE_START(CARMEVA, "Carmeva")
+	/* Maintainer: Conitec Datasystems */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= carmeva_map_io,
+	.init_irq	= carmeva_init_irq,
+	.init_machine	= carmeva_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c
index f45104c..e94645d 100644
--- a/arch/arm/mach-at91rm9200/board-csb337.c
+++ b/arch/arm/mach-at91rm9200/board-csb337.c
@@ -24,6 +24,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -34,9 +35,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -54,32 +55,24 @@
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define CSB337_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define CSB337_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata csb337_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init csb337_map_io(void)
 {
-	int serial[AT91_NR_UART] = CSB337_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 3.6864 MHz crystal */
 	at91_clock_init(3686400);
 
 	/* Setup the LEDs */
-	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
+	at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1);
 
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = CSB337_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (serial[i] >= 0)
-			at91_register_uart(i, serial[i]);
-	}
-#endif
+	/* Setup the serial ports and console */
+	at91_init_serial(&csb337_uart_config);
 }
 
 static struct at91_eth_data __initdata csb337_eth_data = {
@@ -118,17 +111,31 @@
 	.wp_pin		= AT91_PIN_PD6,
 };
 
+static struct spi_board_info csb337_spi_devices[] = {
+	{	/* CAN controller */
+		.modalias	= "sak82c900",
+		.chip_select	= 0,
+		.max_speed_hz	= 6 * 1000 * 1000,
+	},
+};
+
 static void __init csb337_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&csb337_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&csb337_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&csb337_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
 	/* Compact Flash */
 	at91_set_gpio_input(AT91_PIN_PB22, 1);		/* IOIS16 */
 	at91_add_device_cf(&csb337_cf_data);
+	/* SPI */
+	at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices));
 	/* MMC */
 	at91_add_device_mmc(&csb337_mmc_data);
 }
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c
index f2c2d6e..67d5f77 100644
--- a/arch/arm/mach-at91rm9200/board-csb637.c
+++ b/arch/arm/mach-at91rm9200/board-csb637.c
@@ -34,9 +34,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -54,14 +54,14 @@
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define CSB637_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define CSB637_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata csb637_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init csb637_map_io(void)
 {
-	int serial[AT91_NR_UART] = CSB637_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 3.6864 MHz crystal */
@@ -70,16 +70,8 @@
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
 
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = CSB637_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (serial[i] >= 0)
-			at91_register_uart(i, serial[i]);
-	}
-#endif
+	/* Setup the serial ports and console */
+	at91_init_serial(&csb637_uart_config);
 }
 
 static struct at91_eth_data __initdata csb637_eth_data = {
@@ -98,12 +90,18 @@
 
 static void __init csb637_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&csb637_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&csb637_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&csb637_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
 }
 
 MACHINE_START(CSB637, "Cogent CSB637")
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c
index 2d7200e..48d7390 100644
--- a/arch/arm/mach-at91rm9200/board-dk.c
+++ b/arch/arm/mach-at91rm9200/board-dk.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -37,9 +38,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -57,14 +58,14 @@
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define DK_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define DK_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata dk_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init dk_map_io(void)
 {
-	int serial[AT91_NR_UART] = DK_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 18.432 MHz crystal */
@@ -73,16 +74,8 @@
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2);
 
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = DK_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (at91_serial_map[i] >= 0)
-			at91_register_uart(i, at91_serial_map[i]);
-	}
-#endif
+	/* Setup the serial ports and console */
+	at91_init_serial(&dk_uart_config);
 }
 
 static struct at91_eth_data __initdata dk_eth_data = {
@@ -111,16 +104,48 @@
 	.wire4		= 1,
 };
 
+static struct spi_board_info dk_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+	{	/* UR6HCPS2-SP40 PS2-to-SPI adapter */
+		.modalias	= "ur6hcps2",
+		.chip_select	= 1,
+		.max_speed_hz	= 250 *  1000,
+	},
+	{	/* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */
+		.modalias	= "tlv1504",
+		.chip_select	= 2,
+		.max_speed_hz	= 20 * 1000 * 1000,
+	},
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 3,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	}
+#endif
+};
+
 static void __init dk_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&dk_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&dk_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&dk_udc_data);
+	at91_set_multi_drive(dk_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
 	/* Compact Flash */
 	at91_add_device_cf(&dk_cf_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices));
 #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
 	/* DataFlash card */
 	at91_set_gpio_output(AT91_PIN_PB7, 0);
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c
new file mode 100644
index 0000000..a3e2df9
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-eb9200.c
@@ -0,0 +1,130 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-eb9200.c
+ *
+ *  Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest
+ *  by Andrew Patrikalakis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init eb9200_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(BGA_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata eb9200_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init eb9200_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 18.432 MHz crystal */
+	at91_clock_init(18432000);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&eb9200_uart_config);
+}
+
+static struct at91_eth_data __initdata eb9200_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 1,
+};
+
+static struct at91_usbh_data __initdata eb9200_usbh_data = {
+	.ports		= 2,
+};
+
+static struct at91_udc_data __initdata eb9200_udc_data = {
+	.vbus_pin	= AT91_PIN_PD4,
+	.pullup_pin	= AT91_PIN_PD5,
+};
+
+static struct at91_cf_data __initdata eb9200_cf_data = {
+	.det_pin	= AT91_PIN_PB0,
+	.rst_pin	= AT91_PIN_PC5,
+	// .irq_pin	= ... not connected
+	// .vcc_pin	= ... always powered
+};
+
+static struct at91_mmc_data __initdata eb9200_mmc_data = {
+	.is_b		= 0,
+	.wire4		= 1,
+};
+
+static void __init eb9200_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&eb9200_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&eb9200_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&eb9200_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* Compact Flash */
+	at91_add_device_cf(&eb9200_cf_data);
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+	/* MMC */
+	/* only supports 1 or 4 bit interface, not wired through to SPI */
+	at91_add_device_mmc(&eb9200_mmc_data);
+}
+
+MACHINE_START(ATEB9200, "Embest ATEB9200")
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= eb9200_map_io,
+	.init_irq	= eb9200_init_irq,
+	.init_machine	= eb9200_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c
index 80d90f5..72202ed 100644
--- a/arch/arm/mach-at91rm9200/board-ek.c
+++ b/arch/arm/mach-at91rm9200/board-ek.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/spi/spi.h>
 
 #include <asm/hardware.h>
 #include <asm/setup.h>
@@ -37,9 +38,9 @@
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
 
 #include "generic.h"
 
@@ -57,14 +58,14 @@
  *    0 .. 3 = USART0 .. USART3
  *    4      = DBGU
  */
-#define EK_UART_MAP		{ 4, 1, -1, -1, -1 }	/* ttyS0, ..., ttyS4 */
-#define EK_SERIAL_CONSOLE	0			/* ttyS0 */
+static struct at91_uart_config __initdata ek_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 1, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
 
 static void __init ek_map_io(void)
 {
-	int serial[AT91_NR_UART] = EK_UART_MAP;
-	int i;
-
 	at91rm9200_map_io();
 
 	/* Initialize clocks: 18.432 MHz crystal */
@@ -73,16 +74,8 @@
 	/* Setup the LEDs */
 	at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2);
 
-#ifdef CONFIG_SERIAL_AT91
-	at91_console_port = EK_SERIAL_CONSOLE;
-	memcpy(at91_serial_map, serial, sizeof(serial));
-
-	/* Register UARTs */
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (serial[i] >= 0)
-			at91_register_uart(i, serial[i]);
-	}
-#endif
+	/* Setup the serial ports and console */
+	at91_init_serial(&ek_uart_config);
 }
 
 static struct at91_eth_data __initdata ek_eth_data = {
@@ -106,14 +99,36 @@
 	.wp_pin		= AT91_PIN_PA17,
 };
 
+static struct spi_board_info ek_spi_devices[] = {
+	{	/* DataFlash chip */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 0,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+#ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
+	{	/* DataFlash card */
+		.modalias	= "mtd_dataflash",
+		.chip_select	= 3,
+		.max_speed_hz	= 15 * 1000 * 1000,
+	},
+#endif
+};
+
 static void __init ek_board_init(void)
 {
+	/* Serial */
+	at91_add_device_serial();
 	/* Ethernet */
 	at91_add_device_eth(&ek_eth_data);
 	/* USB Host */
 	at91_add_device_usbh(&ek_usbh_data);
 	/* USB Device */
 	at91_add_device_udc(&ek_udc_data);
+	at91_set_multi_drive(ek_udc_data.pullup_pin, 1);	/* pullup_pin is connected to reset */
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
 #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD
 	/* DataFlash card */
 	at91_set_gpio_output(AT91_PIN_PB22, 0);
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c
new file mode 100644
index 0000000..bf760c5
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-kafa.c
@@ -0,0 +1,116 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-kafa.c
+ *
+ *  Copyright (C) 2006 Sperry-Sun
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init kafa_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kafa_uart_config = {
+	.console_tty	= 0,				/* ttyS0 */
+	.nr_tty		= 2,
+	.tty_map	= { 4, 0, -1, -1, -1 }		/* ttyS0, ..., ttyS4 */
+};
+
+static void __init kafa_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 18.432 MHz crystal */
+	at91_clock_init(18432000);
+
+	/* Set up the LEDs */
+	at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&kafa_uart_config);
+}
+
+static struct at91_eth_data __initdata kafa_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PC4,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata kafa_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata kafa_udc_data = {
+	.vbus_pin	= AT91_PIN_PB6,
+	.pullup_pin	= AT91_PIN_PB7,
+};
+
+static void __init kafa_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&kafa_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&kafa_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&kafa_udc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KAFA, "Sperry-Sun KAFA")
+	/* Maintainer: Sergei Sharonov */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= kafa_map_io,
+	.init_irq	= kafa_init_irq,
+	.init_machine	= kafa_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c
new file mode 100644
index 0000000..f06d2b5
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/board-kb9202.c
@@ -0,0 +1,125 @@
+/*
+ * linux/arch/arm/mach-at91rm9200/board-kb9202.c
+ *
+ *  Copyright (c) 2005 kb_admin
+ *  		       KwikByte, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/board.h>
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+static void __init kb9202_init_irq(void)
+{
+	/* Initialize AIC controller */
+	at91rm9200_init_irq(NULL);
+
+	/* Set up the GPIO interrupts */
+	at91_gpio_irq_setup(PQFP_GPIO_BANKS);
+}
+
+/*
+ * Serial port configuration.
+ *    0 .. 3 = USART0 .. USART3
+ *    4      = DBGU
+ */
+static struct at91_uart_config __initdata kb9202_uart_config = {
+	.console_tty	= 0,					/* ttyS0 */
+	.nr_tty		= 3,
+	.tty_map	= { 4, 0, 1, -1, -1 }			/* ttyS0, ..., ttyS4 */
+};
+
+static void __init kb9202_map_io(void)
+{
+	at91rm9200_map_io();
+
+	/* Initialize clocks: 10 MHz crystal */
+	at91_clock_init(10000000);
+
+	/* Set up the LEDs */
+	at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18);
+
+	/* Setup the serial ports and console */
+	at91_init_serial(&kb9202_uart_config);
+}
+
+static struct at91_eth_data __initdata kb9202_eth_data = {
+	.phy_irq_pin	= AT91_PIN_PB29,
+	.is_rmii	= 0,
+};
+
+static struct at91_usbh_data __initdata kb9202_usbh_data = {
+	.ports		= 1,
+};
+
+static struct at91_udc_data __initdata kb9202_udc_data = {
+	.vbus_pin	= AT91_PIN_PB24,
+	.pullup_pin	= AT91_PIN_PB22,
+};
+
+static struct at91_mmc_data __initdata kb9202_mmc_data = {
+	.det_pin	= AT91_PIN_PB2,
+	.is_b		= 0,
+	.wire4		= 1,
+};
+
+static void __init kb9202_board_init(void)
+{
+	/* Serial */
+	at91_add_device_serial();
+	/* Ethernet */
+	at91_add_device_eth(&kb9202_eth_data);
+	/* USB Host */
+	at91_add_device_usbh(&kb9202_usbh_data);
+	/* USB Device */
+	at91_add_device_udc(&kb9202_udc_data);
+	/* MMC */
+	at91_add_device_mmc(&kb9202_mmc_data);
+	/* I2C */
+	at91_add_device_i2c();
+	/* SPI */
+	at91_add_device_spi(NULL, 0);
+}
+
+MACHINE_START(KB9200, "KB920x")
+	/* Maintainer: KwikByte, Inc. */
+	.phys_io	= AT91_BASE_SYS,
+	.io_pg_offst	= (AT91_VA_BASE_SYS >> 18) & 0xfffc,
+	.boot_params	= AT91_SDRAM_BASE + 0x100,
+	.timer		= &at91rm9200_timer,
+	.map_io		= kb9202_map_io,
+	.init_irq	= kb9202_init_irq,
+	.init_machine	= kb9202_board_init,
+MACHINE_END
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c
index 8b95467..edc2cc8 100644
--- a/arch/arm/mach-at91rm9200/clock.c
+++ b/arch/arm/mach-at91rm9200/clock.c
@@ -27,12 +27,10 @@
 #include <asm/io.h>
 #include <asm/mach-types.h>
 
-#include <asm/arch/hardware.h>
-#include <asm/arch/board.h>		/* for master clock global */
+#include <asm/hardware.h>
 
 #include "generic.h"
 
-#undef	DEBUG
 
 /*
  * There's a lot more which can be done with clocks, including cpufreq
@@ -41,7 +39,9 @@
  */
 
 struct clk {
-	const char	*name;
+	const char	*name;		/* unique clock name */
+	const char	*function;	/* function of the clock */
+	struct device	*dev;		/* device associated with function */
 	unsigned long	rate_hz;
 	struct clk	*parent;
 	u32		pmc_mask;
@@ -71,15 +71,14 @@
 };
 static struct clk main_clk = {
 	.name		= "main",
-	.pmc_mask	= 1 << 0,	/* in PMC_SR */
-	.users		= 1,
+	.pmc_mask	= AT91_PMC_MOSCS,	/* in PMC_SR */
 	.id		= 1,
 	.primary	= 1,
 };
 static struct clk plla = {
 	.name		= "plla",
 	.parent		= &main_clk,
-	.pmc_mask	= 1 << 1,	/* in PMC_SR */
+	.pmc_mask	= AT91_PMC_LOCKA,	/* in PMC_SR */
 	.id		= 2,
 	.primary	= 1,
 	.pll		= 1,
@@ -105,7 +104,7 @@
 static struct clk pllb = {
 	.name		= "pllb",
 	.parent		= &main_clk,
-	.pmc_mask	= 1 << 2,	/* in PMC_SR */
+	.pmc_mask	= AT91_PMC_LOCKB,	/* in PMC_SR */
 	.mode		= pllb_mode,
 	.id		= 3,
 	.primary	= 1,
@@ -177,8 +176,7 @@
  */
 static struct clk mck = {
 	.name		= "mck",
-	.pmc_mask	= 1 << 3,	/* in PMC_SR */
-	.users		= 1,		/* (must be) always on */
+	.pmc_mask	= AT91_PMC_MCKRDY,	/* in PMC_SR */
 };
 
 static void pmc_periph_mode(struct clk *clk, int is_on)
@@ -249,6 +247,30 @@
 	.pmc_mask	= 1 << AT91_ID_SPI,
 	.mode		= pmc_periph_mode,
 };
+static struct clk pioA_clk = {
+	.name		= "pioA_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOA,
+	.mode		= pmc_periph_mode,
+};
+static struct clk pioB_clk = {
+	.name		= "pioB_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOB,
+	.mode		= pmc_periph_mode,
+};
+static struct clk pioC_clk = {
+	.name		= "pioC_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOC,
+	.mode		= pmc_periph_mode,
+};
+static struct clk pioD_clk = {
+	.name		= "pioD_clk",
+	.parent		= &mck,
+	.pmc_mask	= 1 << AT91_ID_PIOD,
+	.mode		= pmc_periph_mode,
+};
 
 static struct clk *const clock_list[] = {
 	/* four primary clocks -- MUST BE FIRST! */
@@ -279,21 +301,46 @@
 	&udc_clk,
 	&twi_clk,
 	&spi_clk,
+	&pioA_clk,
+	&pioB_clk,
+	&pioC_clk,
+	&pioD_clk,
 	// ssc0..ssc2
 	// tc0..tc5
+	// irq0..irq6
 	&ohci_clk,
 	&ether_clk,
 };
 
 
+/*
+ * Associate a particular clock with a function (eg, "uart") and device.
+ * The drivers can then request the same 'function' with several different
+ * devices and not care about which clock name to use.
+ */
+void __init at91_clock_associate(const char *id, struct device *dev, const char *func)
+{
+	struct clk *clk = clk_get(NULL, id);
+
+	if (!dev || !clk || !IS_ERR(clk_get(dev, func)))
+		return;
+
+	clk->function = func;
+	clk->dev = dev;
+}
+
 /* clocks are all static for now; no refcounting necessary */
 struct clk *clk_get(struct device *dev, const char *id)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
-		if (strcmp(id, clock_list[i]->name) == 0)
-			return clock_list[i];
+		struct clk *clk = clock_list[i];
+
+		if (strcmp(id, clk->name) == 0)
+			return clk;
+		if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0)
+			return clk;
 	}
 
 	return ERR_PTR(-ENOENT);
@@ -593,6 +640,30 @@
 	return 0;
 }
 
+
+/*
+ * Several unused clocks may be active.  Turn them off.
+ */
+static void at91_periphclk_reset(void)
+{
+	unsigned long reg;
+	int i;
+
+	reg = at91_sys_read(AT91_PMC_PCSR);
+
+	for (i = 0; i < ARRAY_SIZE(clock_list); i++) {
+		struct clk	*clk = clock_list[i];
+
+		if (clk->mode != pmc_periph_mode)
+			continue;
+
+		if (clk->users > 0)
+			reg &= ~clk->pmc_mask;
+	}
+
+	at91_sys_write(AT91_PMC_PCDR, reg);
+}
+
 int __init at91_clock_init(unsigned long main_clock)
 {
 	unsigned tmp, freq, mckr;
@@ -626,7 +697,6 @@
 	 */
 	at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M;
 	pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init);
-	at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP));
 	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP);
 	at91_sys_write(AT91_CKGR_PLLBR, 0);
 	at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP);
@@ -640,19 +710,18 @@
 	 */
 	mckr = at91_sys_read(AT91_PMC_MCKR);
 	mck.parent = clock_list[mckr & AT91_PMC_CSS];
-	mck.parent->users++;
 	freq = mck.parent->rate_hz;
 	freq /= (1 << ((mckr >> 2) & 3));		/* prescale */
 	mck.rate_hz = freq / (1 + ((mckr >> 8) & 3));	/* mdiv */
 
+	/* MCK and CPU clock are "always on" */
+	clk_enable(&mck);
+
 	printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n",
 		freq / 1000000, (unsigned) mck.rate_hz / 1000000,
 		(unsigned) main_clock / 1000000,
 		((unsigned) main_clock % 1000000) / 1000);
 
-	/* FIXME get rid of master_clock global */
-	at91_master_clock = mck.rate_hz;
-
 #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
 	/* establish PCK0..PCK3 parentage */
 	for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) {
@@ -663,19 +732,28 @@
 			continue;
 
 		pckr = at91_sys_read(AT91_PMC_PCKR(clk->id));
-		parent = clock_list[pckr & 3];
+		parent = clock_list[pckr & AT91_PMC_CSS];
 		clk->parent = parent;
 		clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3));
+
+		if (clk->users == 0) {
+			/* not being used, so switch it off */
+			at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask);
+		}
 	}
 #else
-	/* disable unused clocks */
+	/* disable all programmable clocks */
 	at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3);
-#endif	/* CONFIG_AT91_PROGRAMMABLE_CLOCKS */
+#endif
 
-	/* FIXME several unused clocks may still be active...  provide
-	 * a CONFIG option to turn off all unused clocks at some point
-	 * before driver init starts.
-	 */
+	/* enable the PIO clocks */
+	clk_enable(&pioA_clk);
+	clk_enable(&pioB_clk);
+	clk_enable(&pioC_clk);
+	clk_enable(&pioD_clk);
+
+	/* disable all other unused peripheral clocks */
+	at91_periphclk_reset();
 
 	return 0;
 }
diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c
index 3848fd2..e836f85 100644
--- a/arch/arm/mach-at91rm9200/common.c
+++ b/arch/arm/mach-at91rm9200/common.c
@@ -16,7 +16,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
+#include "generic.h"
 
 static struct map_desc at91rm9200_io_desc[] __initdata = {
 	{
@@ -94,6 +95,11 @@
 		.pfn		= __phys_to_pfn(AT91_BASE_TCB0),
 		.length		= SZ_16K,
 		.type		= MT_DEVICE,
+	}, {
+		.virtual	= AT91_SRAM_VIRT_BASE,
+		.pfn		= __phys_to_pfn(AT91_SRAM_BASE),
+		.length		= AT91_SRAM_SIZE,
+		.type		= MT_DEVICE,
 	},
 };
 
@@ -102,14 +108,3 @@
 	iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc));
 }
 
-
-unsigned long at91_master_clock;
-
-EXPORT_SYMBOL(at91_master_clock);
-
-
-int at91_serial_map[AT91_NR_UART];
-int at91_console_port;
-
-EXPORT_SYMBOL(at91_serial_map);
-EXPORT_SYMBOL(at91_console_port);
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c
index bfe47bd..1cf85d2 100644
--- a/arch/arm/mach-at91rm9200/devices.c
+++ b/arch/arm/mach-at91rm9200/devices.c
@@ -16,9 +16,15 @@
 #include <linux/config.h>
 #include <linux/platform_device.h>
 
+#include <asm/hardware.h>
 #include <asm/arch/board.h>
-#include <asm/arch/pio.h>
+#include <asm/arch/gpio.h>
 
+#include "generic.h"
+
+#define SZ_512	0x00000200
+#define SZ_256	0x00000100
+#define SZ_16	0x00000010
 
 /* --------------------------------------------------------------------
  *  USB Host
@@ -28,7 +34,7 @@
 static u64 ohci_dmamask = 0xffffffffUL;
 static struct at91_usbh_data usbh_data;
 
-static struct resource at91_usbh_resource[] = {
+static struct resource at91_usbh_resources[] = {
 	[0] = {
 		.start	= AT91_UHP_BASE,
 		.end	= AT91_UHP_BASE + SZ_1M - 1,
@@ -42,15 +48,15 @@
 };
 
 static struct platform_device at91rm9200_usbh_device = {
-	.name		= "at91rm9200-ohci",
+	.name		= "at91_ohci",
 	.id		= -1,
 	.dev		= {
 				.dma_mask		= &ohci_dmamask,
 				.coherent_dma_mask	= 0xffffffff,
 				.platform_data		= &usbh_data,
 	},
-	.resource	= at91_usbh_resource,
-	.num_resources	= ARRAY_SIZE(at91_usbh_resource),
+	.resource	= at91_usbh_resources,
+	.num_resources	= ARRAY_SIZE(at91_usbh_resources),
 };
 
 void __init at91_add_device_usbh(struct at91_usbh_data *data)
@@ -74,11 +80,16 @@
 static struct at91_udc_data udc_data;
 
 static struct resource at91_udc_resources[] = {
-	{
+	[0] = {
 		.start	= AT91_BASE_UDP,
 		.end	= AT91_BASE_UDP + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
-	}
+	},
+	[1] = {
+		.start	= AT91_ID_UDP,
+		.end	= AT91_ID_UDP,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 static struct platform_device at91rm9200_udc_device = {
@@ -100,10 +111,8 @@
 		at91_set_gpio_input(data->vbus_pin, 0);
 		at91_set_deglitch(data->vbus_pin, 1);
 	}
-	if (data->pullup_pin) {
+	if (data->pullup_pin)
 		at91_set_gpio_output(data->pullup_pin, 0);
-		at91_set_multi_drive(data->pullup_pin, 1);
-	}
 
 	udc_data = *data;
 	platform_device_register(&at91rm9200_udc_device);
@@ -197,7 +206,7 @@
 static struct resource at91_cf_resources[] = {
 	[0] = {
 		.start	= AT91_CF_BASE,
-		/* ties up CS4, CS5, and CS6 */
+		/* ties up CS4, CS5 and CS6 */
 		.end	= AT91_CF_BASE + (0x30000000 - 1),
 		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
 	},
@@ -231,6 +240,12 @@
 		at91_set_gpio_output(data->vcc_pin, 0);
 	at91_set_gpio_output(data->rst_pin, 0);
 
+	/* force poweron defaults for these pins ... */
+	at91_set_A_periph(AT91_PIN_PC9, 0);	/* A25/CFRNW */
+	at91_set_A_periph(AT91_PIN_PC10, 0);	/* NCS4/CFCS */
+	at91_set_A_periph(AT91_PIN_PC11, 0);	/* NCS5/CFCE1 */
+	at91_set_A_periph(AT91_PIN_PC12, 0);	/* NCS6/CFCE2 */
+
 	cf_data = *data;
 	platform_device_register(&at91rm9200_cf_device);
 }
@@ -319,6 +334,7 @@
 void __init at91_add_device_mmc(struct at91_mmc_data *data) {}
 #endif
 
+
 /* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
@@ -400,22 +416,110 @@
 
 
 /* --------------------------------------------------------------------
+ *  SPI
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE)
+static u64 spi_dmamask = 0xffffffffUL;
+
+static struct resource at91_spi_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_SPI,
+		.end	= AT91_BASE_SPI + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SPI,
+		.end	= AT91_ID_SPI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device at91rm9200_spi_device = {
+	.name		= "at91_spi",
+	.id		= 0,
+	.dev		= {
+		.dma_mask		= &spi_dmamask,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.resource	= at91_spi_resources,
+	.num_resources	= ARRAY_SIZE(at91_spi_resources),
+};
+
+static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 };
+
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+{
+	int i;
+	unsigned long cs_pin;
+
+	at91_set_A_periph(AT91_PIN_PA0, 0);	/* MISO */
+	at91_set_A_periph(AT91_PIN_PA1, 0);	/* MOSI */
+	at91_set_A_periph(AT91_PIN_PA2, 0);	/* SPCK */
+
+	/* Enable SPI chip-selects */
+	for (i = 0; i < nr_devices; i++) {
+		if (devices[i].controller_data)
+			cs_pin = (unsigned long) devices[i].controller_data;
+		else
+			cs_pin = at91_spi_standard_cs[devices[i].chip_select];
+
+#ifdef CONFIG_SPI_AT91_MANUAL_CS
+		at91_set_gpio_output(cs_pin, 1);
+#else
+		at91_set_A_periph(cs_pin, 0);
+#endif
+
+		/* pass chip-select pin to driver */
+		devices[i].controller_data = (void *) cs_pin;
+	}
+
+	spi_register_board_info(devices, nr_devices);
+	at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi");
+	platform_device_register(&at91rm9200_spi_device);
+}
+#else
+void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {}
+#endif
+
+
+/* --------------------------------------------------------------------
  *  RTC
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE)
+#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE)
 static struct platform_device at91rm9200_rtc_device = {
 	.name		= "at91_rtc",
 	.id		= -1,
 	.num_resources	= 0,
 };
 
-void __init at91_add_device_rtc(void)
+static void __init at91_add_device_rtc(void)
 {
 	platform_device_register(&at91rm9200_rtc_device);
 }
 #else
-void __init at91_add_device_rtc(void) {}
+static void __init at91_add_device_rtc(void) {}
+#endif
+
+
+/* --------------------------------------------------------------------
+ *  Watchdog
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE)
+static struct platform_device at91rm9200_wdt_device = {
+	.name		= "at91_wdt",
+	.id		= -1,
+	.num_resources	= 0,
+};
+
+static void __init at91_add_device_watchdog(void)
+{
+	platform_device_register(&at91rm9200_wdt_device);
+}
+#else
+static void __init at91_add_device_watchdog(void) {}
 #endif
 
 
@@ -429,13 +533,281 @@
 
 void __init at91_init_leds(u8 cpu_led, u8 timer_led)
 {
-	at91_leds_cpu   = cpu_led;
-	at91_leds_timer = timer_led;
+	at91_leds_cpu	= cpu_led;
+	at91_leds_timer	= timer_led;
 }
-
 #else
 void __init at91_init_leds(u8 cpu_led, u8 timer_led) {}
 #endif
 
 
+/* --------------------------------------------------------------------
+ *  UART
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_SERIAL_AT91)
+static struct resource dbgu_resources[] = {
+	[0] = {
+		.start	= AT91_VA_BASE_SYS + AT91_DBGU,
+		.end	= AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_SYS,
+		.end	= AT91_ID_SYS,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data dbgu_data = {
+	.use_dma_tx	= 0,
+	.use_dma_rx	= 0,		/* DBGU not capable of receive DMA */
+};
+
+static struct platform_device at91rm9200_dbgu_device = {
+	.name		= "at91_usart",
+	.id		= 0,
+	.dev		= {
+				.platform_data	= &dbgu_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= dbgu_resources,
+	.num_resources	= ARRAY_SIZE(dbgu_resources),
+};
+
+static inline void configure_dbgu_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA30, 0);		/* DRXD */
+	at91_set_A_periph(AT91_PIN_PA31, 1);		/* DTXD */
+}
+
+static struct resource uart0_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US0,
+		.end	= AT91_BASE_US0 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US0,
+		.end	= AT91_ID_US0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart0_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart0_device = {
+	.name		= "at91_usart",
+	.id		= 1,
+	.dev		= {
+				.platform_data	= &uart0_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart0_resources,
+	.num_resources	= ARRAY_SIZE(uart0_resources),
+};
+
+static inline void configure_usart0_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA17, 1);		/* TXD0 */
+	at91_set_A_periph(AT91_PIN_PA18, 0);		/* RXD0 */
+	at91_set_A_periph(AT91_PIN_PA20, 0);		/* CTS0 */
+
+	/*
+	 * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21.
+	 *  We need to drive the pin manually.  Default is off (RTS is active low).
+	 */
+	at91_set_gpio_output(AT91_PIN_PA21, 1);
+}
+
+static struct resource uart1_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US1,
+		.end	= AT91_BASE_US1 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US1,
+		.end	= AT91_ID_US1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart1_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart1_device = {
+	.name		= "at91_usart",
+	.id		= 2,
+	.dev		= {
+				.platform_data	= &uart1_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart1_resources,
+	.num_resources	= ARRAY_SIZE(uart1_resources),
+};
+
+static inline void configure_usart1_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PB18, 0);		/* RI1 */
+	at91_set_A_periph(AT91_PIN_PB19, 0);		/* DTR1 */
+	at91_set_A_periph(AT91_PIN_PB20, 1);		/* TXD1 */
+	at91_set_A_periph(AT91_PIN_PB21, 0);		/* RXD1 */
+	at91_set_A_periph(AT91_PIN_PB23, 0);		/* DCD1 */
+	at91_set_A_periph(AT91_PIN_PB24, 0);		/* CTS1 */
+	at91_set_A_periph(AT91_PIN_PB25, 0);		/* DSR1 */
+	at91_set_A_periph(AT91_PIN_PB26, 0);		/* RTS1 */
+}
+
+static struct resource uart2_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US2,
+		.end	= AT91_BASE_US2 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US2,
+		.end	= AT91_ID_US2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart2_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart2_device = {
+	.name		= "at91_usart",
+	.id		= 3,
+	.dev		= {
+				.platform_data	= &uart2_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart2_resources,
+	.num_resources	= ARRAY_SIZE(uart2_resources),
+};
+
+static inline void configure_usart2_pins(void)
+{
+	at91_set_A_periph(AT91_PIN_PA22, 0);		/* RXD2 */
+	at91_set_A_periph(AT91_PIN_PA23, 1);		/* TXD2 */
+}
+
+static struct resource uart3_resources[] = {
+	[0] = {
+		.start	= AT91_BASE_US3,
+		.end	= AT91_BASE_US3 + SZ_16K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= AT91_ID_US3,
+		.end	= AT91_ID_US3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct at91_uart_data uart3_data = {
+	.use_dma_tx	= 1,
+	.use_dma_rx	= 1,
+};
+
+static struct platform_device at91rm9200_uart3_device = {
+	.name		= "at91_usart",
+	.id		= 4,
+	.dev		= {
+				.platform_data	= &uart3_data,
+				.coherent_dma_mask = 0xffffffff,
+	},
+	.resource	= uart3_resources,
+	.num_resources	= ARRAY_SIZE(uart3_resources),
+};
+
+static inline void configure_usart3_pins(void)
+{
+	at91_set_B_periph(AT91_PIN_PA5, 1);		/* TXD3 */
+	at91_set_B_periph(AT91_PIN_PA6, 0);		/* RXD3 */
+}
+
+struct platform_device *at91_uarts[AT91_NR_UART];	/* the UARTs to use */
+struct platform_device *at91_default_console_device;	/* the serial console device */
+
+void __init at91_init_serial(struct at91_uart_config *config)
+{
+	int i;
+
+	/* Fill in list of supported UARTs */
+	for (i = 0; i < config->nr_tty; i++) {
+		switch (config->tty_map[i]) {
+			case 0:
+				configure_usart0_pins();
+				at91_uarts[i] = &at91rm9200_uart0_device;
+				at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart");
+				break;
+			case 1:
+				configure_usart1_pins();
+				at91_uarts[i] = &at91rm9200_uart1_device;
+				at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart");
+				break;
+			case 2:
+				configure_usart2_pins();
+				at91_uarts[i] = &at91rm9200_uart2_device;
+				at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart");
+				break;
+			case 3:
+				configure_usart3_pins();
+				at91_uarts[i] = &at91rm9200_uart3_device;
+				at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart");
+				break;
+			case 4:
+				configure_dbgu_pins();
+				at91_uarts[i] = &at91rm9200_dbgu_device;
+				at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart");
+				break;
+			default:
+				continue;
+		}
+		at91_uarts[i]->id = i;		/* update ID number to mapped ID */
+	}
+
+	/* Set serial console device */
+	if (config->console_tty < AT91_NR_UART)
+		at91_default_console_device = at91_uarts[config->console_tty];
+	if (!at91_default_console_device)
+		printk(KERN_INFO "AT91: No default serial console defined.\n");
+}
+
+void __init at91_add_device_serial(void)
+{
+	int i;
+
+	for (i = 0; i < AT91_NR_UART; i++) {
+		if (at91_uarts[i])
+			platform_device_register(at91_uarts[i]);
+	}
+}
+#else
+void __init at91_init_serial(struct at91_uart_config *config) {}
+void __init at91_add_device_serial(void) {}
+#endif
+
+
 /* -------------------------------------------------------------------- */
+
+/*
+ * These devices are always present and don't need any board-specific
+ * setup.
+ */
+static int __init at91_add_standard_devices(void)
+{
+	at91_add_device_rtc();
+	at91_add_device_watchdog();
+	return 0;
+}
+
+arch_initcall(at91_add_standard_devices);
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h
index 9bd541e..f0d969d 100644
--- a/arch/arm/mach-at91rm9200/generic.h
+++ b/arch/arm/mach-at91rm9200/generic.h
@@ -16,3 +16,10 @@
 extern void __init at91rm9200_map_io(void);
 
 extern int __init at91_clock_init(unsigned long main_clock);
+struct device;
+extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func);
+
+ /* Power Management */
+extern void at91_irq_suspend(void);
+extern void at91_irq_resume(void);
+
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c
index 5ab4627..83c3474 100644
--- a/arch/arm/mach-at91rm9200/gpio.c
+++ b/arch/arm/mach-at91rm9200/gpio.c
@@ -16,7 +16,7 @@
 
 #include <asm/io.h>
 #include <asm/mach/irq.h>
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 #include <asm/arch/gpio.h>
 
 static const u32 pio_controller_offset[4] = {
@@ -213,6 +213,84 @@
 
 /*--------------------------------------------------------------------------*/
 
+#ifdef CONFIG_PM
+
+static u32 wakeups[BGA_GPIO_BANKS];
+static u32 backups[BGA_GPIO_BANKS];
+
+static int gpio_irq_set_wake(unsigned pin, unsigned state)
+{
+	unsigned	mask = pin_to_mask(pin);
+
+	pin -= PIN_BASE;
+	pin /= 32;
+
+	if (unlikely(pin >= BGA_GPIO_BANKS))
+		return -EINVAL;
+
+	if (state)
+		wakeups[pin] |= mask;
+	else
+		wakeups[pin] &= ~mask;
+
+	return 0;
+}
+
+void at91_gpio_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < BGA_GPIO_BANKS; i++) {
+		u32 pio = pio_controller_offset[i];
+
+		/*
+		 * Note: drivers should have disabled GPIO interrupts that
+		 * aren't supposed to be wakeup sources.
+		 * But that is not much good on ARM.....  disable_irq() does
+		 * not update the hardware immediately, so the hardware mask
+		 * (IMR) has the wrong value (not current, too much is
+		 * permitted).
+		 *
+		 * Our workaround is to disable all non-wakeup IRQs ...
+		 * which is exactly what correct drivers asked for in the
+		 * first place!
+		 */
+		backups[i] = at91_sys_read(pio + PIO_IMR);
+		at91_sys_write(pio_controller_offset[i] + PIO_IDR, backups[i]);
+		at91_sys_write(pio_controller_offset[i] + PIO_IER, wakeups[i]);
+
+		if (!wakeups[i]) {
+			disable_irq_wake(AT91_ID_PIOA + i);
+			at91_sys_write(AT91_PMC_PCDR, 1 << (AT91_ID_PIOA + i));
+		} else {
+			enable_irq_wake(AT91_ID_PIOA + i);
+#ifdef CONFIG_PM_DEBUG
+			printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]);
+#endif
+		}
+	}
+}
+
+void at91_gpio_resume(void)
+{
+	int i;
+
+	for (i = 0; i < BGA_GPIO_BANKS; i++) {
+		at91_sys_write(pio_controller_offset[i] + PIO_IDR, wakeups[i]);
+		at91_sys_write(pio_controller_offset[i] + PIO_IER, backups[i]);
+	}
+
+	at91_sys_write(AT91_PMC_PCER,
+			  (1 << AT91_ID_PIOA)
+			| (1 << AT91_ID_PIOB)
+			| (1 << AT91_ID_PIOC)
+			| (1 << AT91_ID_PIOD));
+}
+
+#else
+#define gpio_irq_set_wake	NULL
+#endif
+
 
 /* Several AIC controller irqs are dispatched through this GPIO handler.
  * To use any AT91_PIN_* as an externally triggered IRQ, first call
@@ -252,6 +330,7 @@
 	.mask		= gpio_irq_mask,
 	.unmask		= gpio_irq_unmask,
 	.set_type	= gpio_irq_type,
+	.set_wake	= gpio_irq_set_wake,
 };
 
 static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs)
@@ -266,6 +345,7 @@
 	/* temporarily mask (level sensitive) parent IRQ */
 	desc->chip->ack(irq);
 	for (;;) {
+		/* reading ISR acks the pending (edge triggered) GPIO interrupt */
 		isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
 		if (!isr)
 			break;
@@ -315,15 +395,16 @@
 		set_irq_chipdata(id, controller);
 
 		for (i = 0; i < 32; i++, pin++) {
+			/*
+			 * Can use the "simple" and not "edge" handler since it's
+			 * shorter, and the AIC handles interupts sanely.
+			 */
 			set_irq_chip(pin, &gpio_irqchip);
 			set_irq_handler(pin, do_simple_IRQ);
 			set_irq_flags(pin, IRQF_VALID);
 		}
 
 		set_irq_chained_handler(id, gpio_irq_handler);
-
-		/* enable the PIO peripheral clock */
-		at91_sys_write(AT91_PMC_PCER, 1 << id);
 	}
 	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks);
 }
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c
index cb62bc8..70f4d7a 100644
--- a/arch/arm/mach-at91rm9200/irq.c
+++ b/arch/arm/mach-at91rm9200/irq.c
@@ -92,10 +92,6 @@
 {
 	unsigned int smr, srctype;
 
-	/* change triggering only for FIQ and external IRQ0..IRQ6 */
-	if ((irq < AT91_ID_IRQ0) && (irq != AT91_ID_FIQ))
-		return -EINVAL;
-
 	switch (type) {
 	case IRQT_HIGH:
 		srctype = AT91_AIC_SRCTYPE_HIGH;
@@ -104,9 +100,13 @@
 		srctype = AT91_AIC_SRCTYPE_RISING;
 		break;
 	case IRQT_LOW:
+		if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))	/* only supported on external interrupts */
+			return -EINVAL;
 		srctype = AT91_AIC_SRCTYPE_LOW;
 		break;
 	case IRQT_FALLING:
+		if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0))	/* only supported on external interrupts */
+			return -EINVAL;
 		srctype = AT91_AIC_SRCTYPE_FALLING;
 		break;
 	default:
@@ -118,11 +118,47 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+
+static u32 wakeups;
+static u32 backups;
+
+static int at91rm9200_irq_set_wake(unsigned irq, unsigned value)
+{
+	if (unlikely(irq >= 32))
+		return -EINVAL;
+
+	if (value)
+		wakeups |= (1 << irq);
+	else
+		wakeups &= ~(1 << irq);
+
+	return 0;
+}
+
+void at91_irq_suspend(void)
+{
+	backups = at91_sys_read(AT91_AIC_IMR);
+	at91_sys_write(AT91_AIC_IDCR, backups);
+	at91_sys_write(AT91_AIC_IECR, wakeups);
+}
+
+void at91_irq_resume(void)
+{
+	at91_sys_write(AT91_AIC_IDCR, wakeups);
+	at91_sys_write(AT91_AIC_IECR, backups);
+}
+
+#else
+#define at91rm9200_irq_set_wake	NULL
+#endif
+
 static struct irqchip at91rm9200_irq_chip = {
 	.ack		= at91rm9200_mask_irq,
 	.mask		= at91rm9200_mask_irq,
 	.unmask		= at91rm9200_unmask_irq,
 	.set_type	= at91rm9200_irq_type,
+	.set_wake	= at91rm9200_irq_set_wake,
 };
 
 /*
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c
new file mode 100644
index 0000000..47e5480
--- /dev/null
+++ b/arch/arm/mach-at91rm9200/pm.c
@@ -0,0 +1,225 @@
+/*
+ * arch/arm/mach-at91rm9200/pm.c
+ * AT91 Power Management
+ *
+ * Copyright (C) 2005 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/pm.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/mach/time.h>
+#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+
+#include "generic.h"
+
+
+static int at91_pm_valid_state(suspend_state_t state)
+{
+	switch (state) {
+		case PM_SUSPEND_ON:
+		case PM_SUSPEND_STANDBY:
+		case PM_SUSPEND_MEM:
+			return 1;
+
+		default:
+			return 0;
+	}
+}
+
+
+static suspend_state_t target_state;
+
+/*
+ * Called after processes are frozen, but before we shutdown devices.
+ */
+static int at91_pm_prepare(suspend_state_t state)
+{
+	target_state = state;
+	return 0;
+}
+
+/*
+ * Verify that all the clocks are correct before entering
+ * slow-clock mode.
+ */
+static int at91_pm_verify_clocks(void)
+{
+	unsigned long scsr;
+	int i;
+
+	scsr = at91_sys_read(AT91_PMC_SCSR);
+
+	/* USB must not be using PLLB */
+	if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) {
+		pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n");
+		return 0;
+	}
+
+#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS
+	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
+	for (i = 0; i < 4; i++) {
+		u32 css;
+
+		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
+			continue;
+
+		css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+		if (css != AT91_PMC_CSS_SLOW) {
+			pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
+			return 0;
+		}
+	}
+#endif
+
+	return 1;
+}
+
+/*
+ * Call this from platform driver suspend() to see how deeply to suspend.
+ * For example, some controllers (like OHCI) need one of the PLL clocks
+ * in order to act as a wakeup source, and those are not available when
+ * going into slow clock mode.
+ *
+ * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
+ * the very same problem (but not using at91 main_clk), and it'd be better
+ * to add one generic API rather than lots of platform-specific ones.
+ */
+int at91_suspend_entering_slow_clock(void)
+{
+	return (target_state == PM_SUSPEND_MEM);
+}
+EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+
+
+static void (*slow_clock)(void);
+
+
+
+static int at91_pm_enter(suspend_state_t state)
+{
+	at91_gpio_suspend();
+	at91_irq_suspend();
+
+	pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
+			/* remember all the always-wake irqs */
+			(at91_sys_read(AT91_PMC_PCSR)
+					| (1 << AT91_ID_FIQ)
+					| (1 << AT91_ID_SYS)
+					| (1 << AT91_ID_IRQ0)
+					| (1 << AT91_ID_IRQ1)
+					| (1 << AT91_ID_IRQ2)
+					| (1 << AT91_ID_IRQ3)
+					| (1 << AT91_ID_IRQ4)
+					| (1 << AT91_ID_IRQ5)
+					| (1 << AT91_ID_IRQ6))
+				& at91_sys_read(AT91_AIC_IMR),
+			state);
+
+	switch (state) {
+		/*
+		 * Suspend-to-RAM is like STANDBY plus slow clock mode, so
+		 * drivers must suspend more deeply:  only the master clock
+		 * controller may be using the main oscillator.
+		 */
+		case PM_SUSPEND_MEM:
+			/*
+			 * Ensure that clocks are in a valid state.
+			 */
+			if (!at91_pm_verify_clocks())
+				goto error;
+
+			/*
+			 * Enter slow clock mode by switching over to clk32k and
+			 * turning off the main oscillator; reverse on wakeup.
+			 */
+			if (slow_clock) {
+				slow_clock();
+				break;
+			} else {
+				/* DEVELOPMENT ONLY */
+				pr_info("AT91: PM - no slow clock mode yet ...\n");
+				/* FALLTHROUGH leaving master clock alone */
+			}
+
+		/*
+		 * STANDBY mode has *all* drivers suspended; ignores irqs not
+		 * marked as 'wakeup' event sources; and reduces DRAM power.
+		 * But otherwise it's identical to PM_SUSPEND_ON:  cpu idle, and
+		 * nothing fancy done with main or cpu clocks.
+		 */
+		case PM_SUSPEND_STANDBY:
+			/*
+			 * NOTE: the Wait-for-Interrupt instruction needs to be
+			 * in icache so the SDRAM stays in self-refresh mode until
+			 * the wakeup IRQ occurs.
+			 */
+			asm("b 1f; .align 5; 1:");
+			asm("mcr p15, 0, r0, c7, c10, 4");	/* drain write buffer */
+			at91_sys_write(AT91_SDRAMC_SRR, 1);	/* self-refresh mode */
+			/* fall though to next state */
+
+		case PM_SUSPEND_ON:
+			asm("mcr p15, 0, r0, c7, c0, 4");	/* wait for interrupt */
+			break;
+
+		default:
+			pr_debug("AT91: PM - bogus suspend state %d\n", state);
+			goto error;
+	}
+
+	pr_debug("AT91: PM - wakeup %08x\n",
+			at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR));
+
+error:
+	target_state = PM_SUSPEND_ON;
+	at91_irq_resume();
+	at91_gpio_resume();
+	return 0;
+}
+
+
+static struct pm_ops at91_pm_ops ={
+	.pm_disk_mode	= 0,
+	.valid		= at91_pm_valid_state,
+	.prepare	= at91_pm_prepare,
+	.enter		= at91_pm_enter,
+};
+
+static int __init at91_pm_init(void)
+{
+	printk("AT91: Power Management\n");
+
+#ifdef CONFIG_AT91_PM_SLOW_CLOCK
+	/* REVISIT allocations of SRAM should be dynamically managed.
+	 * FIQ handlers and other components will want SRAM/TCM too...
+	 */
+	slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K));
+	memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz);
+#endif
+
+	/* Disable SDRAM low-power mode.  Cannot be used with self-refresh. */
+	at91_sys_write(AT91_SDRAMC_LPR, 0);
+
+	pm_set_ops(&at91_pm_ops);
+
+	return 0;
+}
+arch_initcall(at91_pm_init);
diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c
index 7ffcf44..fc2d7d5 100644
--- a/arch/arm/mach-at91rm9200/time.c
+++ b/arch/arm/mach-at91rm9200/time.c
@@ -31,6 +31,8 @@
 #include <asm/irq.h>
 #include <asm/mach/time.h>
 
+static unsigned long last_crtr;
+
 /*
  * The ST_CRTR is updated asynchronously to the master clock.  It is therefore
  *  necessary to read it twice (with the same value) to ensure accuracy.
@@ -56,7 +58,7 @@
 {
 	unsigned long elapsed;
 
-	elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV;
+	elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV;
 
 	return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH;
 }
@@ -66,15 +68,12 @@
  */
 static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	unsigned long rtar;
-
 	if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) {	/* This is a shared interrupt */
 		write_seqlock(&xtime_lock);
 
-		while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH) {
+		while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) {
 			timer_tick(regs);
-			rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV;
-			at91_sys_write(AT91_ST_RTAR, rtar);
+			last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV;
 		}
 
 		write_sequnlock(&xtime_lock);
@@ -87,10 +86,24 @@
 
 static struct irqaction at91rm9200_timer_irq = {
 	.name		= "at91_tick",
-	.flags		= SA_SHIRQ | SA_INTERRUPT,
+	.flags		= SA_SHIRQ | SA_INTERRUPT | SA_TIMER,
 	.handler	= at91rm9200_timer_interrupt
 };
 
+void at91rm9200_timer_reset(void)
+{
+	last_crtr = 0;
+
+	/* Real time counter incremented every 30.51758 microseconds */
+	at91_sys_write(AT91_ST_RTMR, 1);
+
+	/* Set Period Interval timer */
+	at91_sys_write(AT91_ST_PIMR, LATCH);
+
+	/* Enable Period Interval Timer interrupt */
+	at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+}
+
 /*
  * Set up timer interrupt.
  */
@@ -100,28 +113,30 @@
 	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS);
 	(void) at91_sys_read(AT91_ST_SR);	/* Clear any pending interrupts */
 
-	/*
-	 * Make IRQs happen for the system timer.
-	 */
+	/* Make IRQs happen for the system timer */
 	setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
 
-	/* Set initial alarm to 0 */
-	at91_sys_write(AT91_ST_RTAR, 0);
-
-	/* Real time counter incremented every 30.51758 microseconds */
-	at91_sys_write(AT91_ST_RTMR, 1);
-
-	/* Set Period Interval timer */
-	at91_sys_write(AT91_ST_PIMR, LATCH);
-
 	/* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */
 	tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE;
 
-	/* Enable Period Interval Timer interrupt */
-	at91_sys_write(AT91_ST_IER, AT91_ST_PITS);
+	/* Initialize and enable the timer interrupt */
+	at91rm9200_timer_reset();
 }
 
+#ifdef CONFIG_PM
+static void at91rm9200_timer_suspend(void)
+{
+	/* disable Period Interval Timer interrupt */
+	at91_sys_write(AT91_ST_IDR, AT91_ST_PITS);
+}
+#else
+#define at91rm9200_timer_suspend	NULL
+#endif
+
 struct sys_timer at91rm9200_timer = {
 	.init		= at91rm9200_timer_init,
 	.offset		= at91rm9200_gettimeoffset,
+	.suspend	= at91rm9200_timer_suspend,
+	.resume		= at91rm9200_timer_reset,
 };
+
diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
index 5393af9..05a48a2 100644
--- a/arch/arm/mach-ep93xx/Makefile
+++ b/arch/arm/mach-ep93xx/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for the linux kernel.
 #
-obj-y			:= core.o
+obj-y			:= core.o clock.o
 obj-m			:=
 obj-n			:=
 obj-			:=
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
new file mode 100644
index 0000000..08ad782
--- /dev/null
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -0,0 +1,156 @@
+/*
+ * arch/arm/mach-ep93xx/clock.c
+ * Clock control for Cirrus EP93xx chips.
+ *
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <asm/div64.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+struct clk {
+	char		*name;
+	unsigned long	rate;
+	int		users;
+	u32		enable_reg;
+	u32		enable_mask;
+};
+
+static struct clk clk_pll1 = {
+	.name		= "pll1",
+};
+static struct clk clk_f = {
+	.name		= "fclk",
+};
+static struct clk clk_h = {
+	.name		= "hclk",
+};
+static struct clk clk_p = {
+	.name		= "pclk",
+};
+static struct clk clk_pll2 = {
+	.name		= "pll2",
+};
+static struct clk clk_usb_host = {
+	.name		= "usb_host",
+	.enable_reg	= EP93XX_SYSCON_CLOCK_CONTROL,
+	.enable_mask	= EP93XX_SYSCON_CLOCK_USH_EN,
+};
+
+
+static struct clk *clocks[] = {
+	&clk_pll1,
+	&clk_f,
+	&clk_h,
+	&clk_p,
+	&clk_pll2,
+	&clk_usb_host,
+};
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clocks); i++) {
+		if (!strcmp(clocks[i]->name, id))
+			return clocks[i];
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+
+int clk_enable(struct clk *clk)
+{
+	if (!clk->users++ && clk->enable_reg) {
+		u32 value;
+
+		value = __raw_readl(clk->enable_reg);
+		__raw_writel(value | clk->enable_mask, clk->enable_reg);
+	}
+
+	return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+	if (!--clk->users && clk->enable_reg) {
+		u32 value;
+
+		value = __raw_readl(clk->enable_reg);
+		__raw_writel(value & ~clk->enable_mask, clk->enable_reg);
+	}
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return clk->rate;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+
+
+static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
+static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
+static char pclk_divisors[] = { 1, 2, 4, 8 };
+
+/*
+ * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
+ */
+static unsigned long calc_pll_rate(u32 config_word)
+{
+	unsigned long long rate;
+	int i;
+
+	rate = 14745600;
+	rate *= ((config_word >> 11) & 0x1f) + 1;		/* X1FBD */
+	rate *= ((config_word >> 5) & 0x3f) + 1;		/* X2FBD */
+	do_div(rate, (config_word & 0x1f) + 1);			/* X2IPD */
+	for (i = 0; i < ((config_word >> 16) & 3); i++)		/* PS */
+		rate >>= 1;
+
+	return (unsigned long)rate;
+}
+
+void ep93xx_clock_init(void)
+{
+	u32 value;
+
+	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1);
+	if (!(value & 0x00800000)) {			/* PLL1 bypassed?  */
+		clk_pll1.rate = 14745600;
+	} else {
+		clk_pll1.rate = calc_pll_rate(value);
+	}
+	clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7];
+	clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7];
+	clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3];
+
+	value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2);
+	if (!(value & 0x00080000)) {			/* PLL2 bypassed?  */
+		clk_pll2.rate = 14745600;
+	} else if (value & 0x00040000) {		/* PLL2 enabled?  */
+		clk_pll2.rate = calc_pll_rate(value);
+	} else {
+		clk_pll2.rate = 0;
+	}
+	clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1);
+
+	printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
+		clk_pll1.rate / 1000000, clk_pll2.rate / 1000000);
+	printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
+		clk_f.rate / 1000000, clk_h.rate / 1000000,
+		clk_p.rate / 1000000);
+}
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index dcd4176..1fe73c0 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -103,7 +103,8 @@
 	write_seqlock(&xtime_lock);
 
 	__raw_writel(1, EP93XX_TIMER1_CLEAR);
-	while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time
+	while ((signed long)
+		(__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)
 						>= TIMER4_TICKS_PER_JIFFY) {
 		last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
 		timer_tick(regs);
@@ -124,7 +125,7 @@
 {
 	/* Enable periodic HZ timer.  */
 	__raw_writel(0x48, EP93XX_TIMER1_CONTROL);
-	__raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD);
+	__raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD);
 	__raw_writel(0xc8, EP93XX_TIMER1_CONTROL);
 
 	/* Enable lost jiffy timer.  */
@@ -432,10 +433,37 @@
 };
 
 
+static struct resource ep93xx_ohci_resources[] = {
+	[0] = {
+		.start	= EP93XX_USB_PHYS_BASE,
+		.end	= EP93XX_USB_PHYS_BASE + 0x0fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EP93XX_USB,
+		.end	= IRQ_EP93XX_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ep93xx_ohci_device = {
+	.name		= "ep93xx-ohci",
+	.id		= -1,
+	.dev		= {
+		.dma_mask		= (void *)0xffffffff,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(ep93xx_ohci_resources),
+	.resource	= ep93xx_ohci_resources,
+};
+
+
 void __init ep93xx_init_devices(void)
 {
 	unsigned int v;
 
+	ep93xx_clock_init();
+
 	/*
 	 * Disallow access to MaverickCrunch initially.
 	 */
@@ -449,4 +477,5 @@
 	amba_device_register(&uart3_device, &iomem_resource);
 
 	platform_device_register(&ep93xx_rtc_device);
+	platform_device_register(&ep93xx_ohci_device);
 }
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index d18fcb1..47cc6c8 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -16,16 +16,38 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
 #include <asm/io.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
+static struct physmap_flash_data gesbc9312_flash_data = {
+	.width		= 4,
+};
+
+static struct resource gesbc9312_flash_resource = {
+	.start		= 0x60000000,
+	.end		= 0x60800000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device gesbc9312_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &gesbc9312_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &gesbc9312_flash_resource,
+};
+
 static void __init gesbc9312_init_machine(void)
 {
 	ep93xx_init_devices();
-	physmap_configure(0x60000000, 0x00800000, 4, NULL);
+	platform_device_register(&gesbc9312_flash);
 }
 
 MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index e24566b..6e5a56c 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -16,6 +16,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/ioport.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
 #include <linux/m48t86.h>
@@ -111,6 +112,26 @@
 	}
 }
 
+static struct physmap_flash_data ts72xx_flash_data = {
+	.width		= 1,
+};
+
+static struct resource ts72xx_flash_resource = {
+	.start		= TS72XX_NOR_PHYS_BASE,
+	.end		= TS72XX_NOR_PHYS_BASE + 0x01000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ts72xx_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ts72xx_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ts72xx_flash_resource,
+};
+
 static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
 {
 	__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
@@ -141,7 +162,7 @@
 {
 	ep93xx_init_devices();
 	if (board_is_ts7200())
-		physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL);
+		platform_device_register(&ts72xx_flash);
 	platform_device_register(&ts72xx_rtc_device);
 }
 
diff --git a/arch/arm/mach-imx/dma.c b/arch/arm/mach-imx/dma.c
index 4ca51dc..3657887 100644
--- a/arch/arm/mach-imx/dma.c
+++ b/arch/arm/mach-imx/dma.c
@@ -15,6 +15,9 @@
  *             Changed to support scatter gather DMA
  *             by taking Russell's code from RiscPC
  *
+ *  2006-05-31 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *             Corrected error handling code.
+ *
  */
 
 #undef DEBUG
@@ -277,7 +280,7 @@
 int
 imx_dma_setup_handlers(imx_dmach_t dma_ch,
 		       void (*irq_handler) (int, void *, struct pt_regs *),
-		       void (*err_handler) (int, void *, struct pt_regs *),
+		       void (*err_handler) (int, void *, struct pt_regs *, int),
 		       void *data)
 {
 	struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
@@ -463,43 +466,53 @@
 	int i, disr = DISR;
 	struct imx_dma_channel *channel;
 	unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
+	int errcode;
 
-	DISR = disr;
+	DISR = disr & err_mask;
 	for (i = 0; i < IMX_DMA_CHANNELS; i++) {
+		if(!(err_mask & (1 << i)))
+			continue;
 		channel = &imx_dma_channels[i];
+		errcode = 0;
 
-		if ((err_mask & 1 << i) && channel->name
-		    && channel->err_handler) {
-			channel->err_handler(i, channel->data, regs);
+		if (DBTOSR & (1 << i)) {
+			DBTOSR = (1 << i);
+			errcode |= IMX_DMA_ERR_BURST;
+		}
+		if (DRTOSR & (1 << i)) {
+			DRTOSR = (1 << i);
+			errcode |= IMX_DMA_ERR_REQUEST;
+		}
+		if (DSESR & (1 << i)) {
+			DSESR = (1 << i);
+			errcode |= IMX_DMA_ERR_TRANSFER;
+		}
+		if (DBOSR & (1 << i)) {
+			DBOSR = (1 << i);
+			errcode |= IMX_DMA_ERR_BUFFER;
+		}
+
+		/*
+		 * The cleaning of @sg field would be questionable
+		 * there, because its value can help to compute
+		 * remaining/transfered bytes count in the handler
+		 */
+		/*imx_dma_channels[i].sg = NULL;*/
+
+		if (channel->name && channel->err_handler) {
+			channel->err_handler(i, channel->data, regs, errcode);
 			continue;
 		}
 
 		imx_dma_channels[i].sg = NULL;
 
-		if (DBTOSR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Burst timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DBTOSR |= (1 << i);
-		}
-		if (DRTOSR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Request timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DRTOSR |= (1 << i);
-		}
-		if (DSESR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Transfer timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DSESR |= (1 << i);
-		}
-		if (DBOSR & (1 << i)) {
-			printk(KERN_WARNING
-			       "Buffer overflow timeout on channel %d (%s)\n",
-			       i, channel->name);
-			DBOSR |= (1 << i);
-		}
+		printk(KERN_WARNING
+		       "DMA timeout on channel %d (%s) -%s%s%s%s\n",
+		       i, channel->name,
+		       errcode&IMX_DMA_ERR_BURST?    " burst":"",
+		       errcode&IMX_DMA_ERR_REQUEST?  " request":"",
+		       errcode&IMX_DMA_ERR_TRANSFER? " transfer":"",
+		       errcode&IMX_DMA_ERR_BUFFER?   " buffer":"");
 	}
 	return IRQ_HANDLED;
 }
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 6e8d504..ebe4391 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -211,7 +211,8 @@
 	/* clear timer 1 */
 	ixp2000_reg_wrb(IXP2000_T1_CLR, 1);
 
-	while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
+	while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr)
+							>= ticks_per_jiffy) {
 		timer_tick(regs);
 		next_jiffy_time -= ticks_per_jiffy;
 	}
@@ -301,6 +302,7 @@
 	}
 	local_irq_restore(flags);
 }
+EXPORT_SYMBOL(gpio_line_config);
 
 
 /*************************************************************************
diff --git a/arch/arm/mach-ixp23xx/core.c b/arch/arm/mach-ixp23xx/core.c
index affd1d5..051e3d7 100644
--- a/arch/arm/mach-ixp23xx/core.c
+++ b/arch/arm/mach-ixp23xx/core.c
@@ -334,7 +334,7 @@
 /*************************************************************************
  * Timer-tick functions for IXP23xx
  *************************************************************************/
-#define CLOCK_TICKS_PER_USEC	CLOCK_TICK_RATE / (USEC_PER_SEC)
+#define CLOCK_TICKS_PER_USEC	(CLOCK_TICK_RATE / USEC_PER_SEC)
 
 static unsigned long next_jiffy_time;
 
@@ -353,7 +353,7 @@
 {
 	/* Clear Pending Interrupt by writing '1' to it */
 	*IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
-	while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) {
+	while ((signed long)(*IXP23XX_TIMER_CONT - next_jiffy_time) >= LATCH) {
 		timer_tick(regs);
 		next_jiffy_time += LATCH;
 	}
@@ -439,5 +439,6 @@
 
 void __init ixp23xx_sys_init(void)
 {
+	*IXP23XX_EXP_UNIT_FUSE |= 0xf;
 	platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices));
 }
diff --git a/arch/arm/mach-ixp23xx/espresso.c b/arch/arm/mach-ixp23xx/espresso.c
index bf688c1..dc5e489 100644
--- a/arch/arm/mach-ixp23xx/espresso.c
+++ b/arch/arm/mach-ixp23xx/espresso.c
@@ -53,9 +53,29 @@
 };
 subsys_initcall(espresso_pci_init);
 
+static struct physmap_flash_data espresso_flash_data = {
+	.width		= 2,
+};
+
+static struct resource espresso_flash_resource = {
+	.start		= 0x90000000,
+	.end		= 0x92000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device espresso_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &espresso_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &espresso_flash_resource,
+};
+
 static void __init espresso_init(void)
 {
-	physmap_configure(0x90000000, 0x02000000, 2, NULL);
+	platform_device_register(&espresso_flash);
 
 	/*
 	 * Mark flash as writeable.
diff --git a/arch/arm/mach-ixp23xx/ixdp2351.c b/arch/arm/mach-ixp23xx/ixdp2351.c
index 00146c3..535b334 100644
--- a/arch/arm/mach-ixp23xx/ixdp2351.c
+++ b/arch/arm/mach-ixp23xx/ixdp2351.c
@@ -298,9 +298,29 @@
 	iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc));
 }
 
+static struct physmap_flash_data ixdp2351_flash_data = {
+	.width		= 1,
+};
+
+static struct resource ixdp2351_flash_resource = {
+	.start		= 0x90000000,
+	.end		= 0x94000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device ixdp2351_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &ixdp2351_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &ixdp2351_flash_resource,
+};
+
 static void __init ixdp2351_init(void)
 {
-	physmap_configure(0x90000000, 0x04000000, 1, NULL);
+	platform_device_register(&ixdp2351_flash);
 
 	/*
 	 * Mark flash as writeable
diff --git a/arch/arm/mach-ixp23xx/roadrunner.c b/arch/arm/mach-ixp23xx/roadrunner.c
index 43c14e7..b9f5d13 100644
--- a/arch/arm/mach-ixp23xx/roadrunner.c
+++ b/arch/arm/mach-ixp23xx/roadrunner.c
@@ -137,9 +137,29 @@
 
 subsys_initcall(roadrunner_pci_init);
 
+static struct physmap_flash_data roadrunner_flash_data = {
+	.width		= 2,
+};
+
+static struct resource roadrunner_flash_resource = {
+	.start		= 0x90000000,
+	.end		= 0x94000000,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device roadrunner_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &roadrunner_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &roadrunner_flash_resource,
+};
+
 static void __init roadrunner_init(void)
 {
-	physmap_configure(0x90000000, 0x04000000, 2, NULL);
+	platform_device_register(&roadrunner_flash);
 
 	/*
 	 * Mark flash as writeable
diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
index 3b23f43..57f23b4 100644
--- a/arch/arm/mach-ixp4xx/Kconfig
+++ b/arch/arm/mach-ixp4xx/Kconfig
@@ -35,7 +35,6 @@
 
 config ARCH_IXDP425
 	bool "IXDP425"
-	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Intel's 
 	  IXDP425 Development Platform (Also known as Richfield).  
@@ -43,7 +42,6 @@
 
 config MACH_IXDPG425
 	bool "IXDPG425"
-	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Intel's
 	  IXDPG425 Development Platform (Also known as Montajade).
@@ -51,7 +49,6 @@
 
 config MACH_IXDP465
 	bool "IXDP465"
-	select PCI
 	help
 	  Say 'Y' here if you want your kernel to support Intel's
 	  IXDP465 Development Platform (Also known as BMP).
diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
index 5a4aaa0..640315d 100644
--- a/arch/arm/mach-ixp4xx/Makefile
+++ b/arch/arm/mach-ixp4xx/Makefile
@@ -2,13 +2,23 @@
 # Makefile for the linux kernel.
 #
 
+obj-pci-y	:=
+obj-pci-n	:=
+
+obj-pci-$(CONFIG_ARCH_IXDP4XX)		+= ixdp425-pci.o
+obj-pci-$(CONFIG_MACH_IXDPG425)		+= ixdpg425-pci.o
+obj-pci-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o
+obj-pci-$(CONFIG_MACH_GTWX5715)		+= gtwx5715-pci.o
+obj-pci-$(CONFIG_MACH_NSLU2)		+= nslu2-pci.o
+obj-pci-$(CONFIG_MACH_NAS100D)		+= nas100d-pci.o
+
 obj-y	+= common.o
 
-obj-$(CONFIG_PCI)		+= common-pci.o
-obj-$(CONFIG_ARCH_IXDP4XX)	+= ixdp425-pci.o ixdp425-setup.o
-obj-$(CONFIG_MACH_IXDPG425)	+= ixdpg425-pci.o coyote-setup.o
-obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o coyote-setup.o
-obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-pci.o gtwx5715-setup.o
-obj-$(CONFIG_MACH_NSLU2)	+= nslu2-pci.o nslu2-setup.o nslu2-power.o
-obj-$(CONFIG_MACH_NAS100D)	+= nas100d-pci.o nas100d-setup.o nas100d-power.o
+obj-$(CONFIG_ARCH_IXDP4XX)	+= ixdp425-setup.o
+obj-$(CONFIG_MACH_IXDPG425)	+= coyote-setup.o
+obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-setup.o
+obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-setup.o
+obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o nslu2-power.o
+obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o nas100d-power.o
 
+obj-$(CONFIG_PCI)		+= $(obj-pci-$(CONFIG_PCI)) common-pci.o
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 00b761f..bf25a76 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -276,7 +276,7 @@
 	/*
 	 * Catch up with the real idea of time
 	 */
-	while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) {
+	while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
 		timer_tick(regs);
 		last_jiffy_time += LATCH;
 	}
diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c
index 99d333d..a3745ed 100644
--- a/arch/arm/mach-ixp4xx/nas100d-power.c
+++ b/arch/arm/mach-ixp4xx/nas100d-power.c
@@ -20,11 +20,10 @@
 #include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
+#include <linux/reboot.h>
 
 #include <asm/mach-types.h>
 
-extern void ctrl_alt_del(void);
-
 static irqreturn_t nas100d_reset_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* Signal init to do the ctrlaltdel action, this will bypass init if
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index a3b4c6a..9a31444 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/leds.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -37,6 +38,36 @@
 	.resource		= &nas100d_flash_resource,
 };
 
+#ifdef CONFIG_LEDS_IXP4XX
+static struct resource nas100d_led_resources[] = {
+	{
+		.name		= "wlan",   /* green led */
+		.start		= 0,
+		.end		= 0,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+	{
+		.name		= "ready",  /* blue power led (off is flashing!) */
+		.start		= 15,
+		.end		= 15,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+	{
+		.name		= "disk",   /* yellow led */
+		.start		= 3,
+		.end		= 3,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+};
+
+static struct platform_device nas100d_leds = {
+	.name			= "IXP4XX-GPIO-LED",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(nas100d_led_resources),
+	.resource		= nas100d_led_resources,
+};
+#endif
+
 static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = {
 	.sda_pin		= NAS100D_SDA_PIN,
 	.scl_pin		= NAS100D_SCL_PIN,
@@ -95,7 +126,9 @@
 static struct platform_device *nas100d_devices[] __initdata = {
 	&nas100d_i2c_controller,
 	&nas100d_flash,
-	&nas100d_uart,
+#ifdef CONFIG_LEDS_IXP4XX
+	&nas100d_leds,
+#endif
 };
 
 static void nas100d_power_off(void)
@@ -122,6 +155,12 @@
 
 	pm_power_off = nas100d_power_off;
 
+	/* This is only useful on a modified machine, but it is valuable
+	 * to have it first in order to see debug messages, and so that
+	 * it does *not* get removed if platform_add_devices fails!
+	 */
+	(void)platform_device_register(&nas100d_uart);
+
 	platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
 }
 
diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
index d80c362..6d38e97 100644
--- a/arch/arm/mach-ixp4xx/nslu2-power.c
+++ b/arch/arm/mach-ixp4xx/nslu2-power.c
@@ -20,11 +20,10 @@
 #include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
+#include <linux/reboot.h>
 
 #include <asm/mach-types.h>
 
-extern void ctrl_alt_del(void);
-
 static irqreturn_t nslu2_power_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 	/* Signal init to do the ctrlaltdel action, this will bypass init if
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index 55411f2..749a337 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -7,6 +7,7 @@
  *      Copyright (C) 2003-2004 MontaVista Software, Inc.
  *
  * Author: Mark Rakes <mrakes at mac.com>
+ * Author: Rod Whitby <rod@whitby.id.au>
  * Maintainers: http://www.nslu2-linux.org/
  *
  * Fixed missing init_time in MACHINE_START kas11 10/22/04
@@ -16,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/serial.h>
 #include <linux/serial_8250.h>
+#include <linux/leds.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -43,6 +45,42 @@
 	.scl_pin		= NSLU2_SCL_PIN,
 };
 
+#ifdef CONFIG_LEDS_IXP4XX
+static struct resource nslu2_led_resources[] = {
+	{
+		.name		= "ready",  /* green led */
+		.start		= NSLU2_LED_GRN,
+		.end		= NSLU2_LED_GRN,
+		.flags		= IXP4XX_GPIO_HIGH,
+	},
+	{
+		.name		= "status", /* red led */
+		.start		= NSLU2_LED_RED,
+		.end		= NSLU2_LED_RED,
+		.flags		= IXP4XX_GPIO_HIGH,
+	},
+	{
+		.name		= "disk-1",
+		.start		= NSLU2_LED_DISK1,
+		.end		= NSLU2_LED_DISK1,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+	{
+		.name		= "disk-2",
+		.start		= NSLU2_LED_DISK2,
+		.end		= NSLU2_LED_DISK2,
+		.flags		= IXP4XX_GPIO_LOW,
+	},
+};
+
+static struct platform_device nslu2_leds = {
+	.name			= "IXP4XX-GPIO-LED",
+	.id			= -1,
+	.num_resources		= ARRAY_SIZE(nslu2_led_resources),
+	.resource		= nslu2_led_resources,
+};
+#endif
+
 static struct platform_device nslu2_i2c_controller = {
 	.name			= "IXP4XX-I2C",
 	.id			= 0,
@@ -102,8 +140,10 @@
 static struct platform_device *nslu2_devices[] __initdata = {
 	&nslu2_i2c_controller,
 	&nslu2_flash,
-	&nslu2_uart,
 	&nslu2_beeper,
+#ifdef CONFIG_LEDS_IXP4XX
+	&nslu2_leds,
+#endif
 };
 
 static void nslu2_power_off(void)
@@ -127,6 +167,12 @@
 
 	pm_power_off = nslu2_power_off;
 
+	/* This is only useful on a modified machine, but it is valuable
+	 * to have it first in order to see debug messages, and so that
+	 * it does *not* get removed if platform_add_devices fails!
+	 */
+	(void)platform_device_register(&nslu2_uart);
+
 	platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
 }
 
diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig
index 8a17867a..558a34f 100644
--- a/arch/arm/mach-lh7a40x/Kconfig
+++ b/arch/arm/mach-lh7a40x/Kconfig
@@ -14,6 +14,7 @@
 	bool "LPD7A400 Card Engine"
 	select ARCH_LH7A400
 #	select IDE_POLL
+	select HAS_TOUCHSCREEN_ADS7843_LH7
 	help
 	  Say Y here if you are using Logic Product Development's
 	  LPD7A400 CardEngine.  For the time being, the LPD7A400 and
@@ -23,6 +24,7 @@
 	bool "LPD7A404 Card Engine"
 	select ARCH_LH7A404
 #	select IDE_POLL
+	select HAS_TOUCHSCREEN_ADC_LH7
 	help
 	  Say Y here if you are using Logic Product Development's
 	  LPD7A404 CardEngine. For the time being, the LPD7A400 and
@@ -34,6 +36,9 @@
 config ARCH_LH7A404
 	bool
 
+config LPD7A40X_CPLD_SSP
+	bool
+
 config LH7A40X_CONTIGMEM
 	bool "Disable NUMA Support"
 	depends on ARCH_LH7A40X
diff --git a/arch/arm/mach-lh7a40x/Makefile b/arch/arm/mach-lh7a40x/Makefile
index e90512d..94b8615 100644
--- a/arch/arm/mach-lh7a40x/Makefile
+++ b/arch/arm/mach-lh7a40x/Makefile
@@ -4,11 +4,14 @@
 
 # Object file lists.
 
-obj-y			:= time.o
-obj-$(CONFIG_MACH_KEV7A400) += arch-kev7a400.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A400) += arch-lpd7a40x.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A404) += arch-lpd7a40x.o irq-lh7a404.o
+obj-y				:= time.o clocks.o
+obj-m				:=
+obj-n				:=
+obj-				:=
 
-obj-m			:=
-obj-n			:=
-obj-			:=
+obj-$(CONFIG_MACH_KEV7A400)	+= arch-kev7a400.o irq-lh7a400.o
+obj-$(CONFIG_MACH_LPD7A400)	+= arch-lpd7a40x.o irq-lh7a400.o
+obj-$(CONFIG_MACH_LPD7A404)	+= arch-lpd7a40x.o irq-lh7a404.o
+obj-$(CONFIG_LPD7A40X_CPLD_SSP)	+= ssp-cpld.o
+obj-$(CONFIG_FB_ARMCLCD)	+= clcd.o
+
diff --git a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
index 12e2327..c0e6854 100644
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
@@ -23,6 +23,28 @@
 
 #include "common.h"
 
+#define CPLD_INT_NETHERNET	(1<<0)
+#define CPLD_INTMASK_ETHERNET	(1<<2)
+#if defined (CONFIG_MACH_LPD7A400)
+# define CPLD_INT_NTOUCH		(1<<1)
+# define CPLD_INTMASK_TOUCH	(1<<3)
+# define CPLD_INT_PEN		(1<<4)
+# define CPLD_INTMASK_PEN	(1<<4)
+# define CPLD_INT_PIRQ		(1<<4)
+#endif
+#define CPLD_INTMASK_CPLD	(1<<7)
+#define CPLD_INT_CPLD		(1<<6)
+
+#define CPLD_CONTROL_SWINT		(1<<7) /* Disable all CPLD IRQs */
+#define CPLD_CONTROL_OCMSK		(1<<6) /* Mask USB1 connect IRQ */
+#define CPLD_CONTROL_PDRV		(1<<5) /* PCC_nDRV high */
+#define CPLD_CONTROL_USB1C		(1<<4) /* USB1 connect IRQ active */
+#define CPLD_CONTROL_USB1P		(1<<3) /* USB1 power disable */
+#define CPLD_CONTROL_AWKP		(1<<2) /* Auto-wakeup disabled  */
+#define CPLD_CONTROL_LCD_ENABLE		(1<<1) /* LCD Vee enable */
+#define CPLD_CONTROL_WRLAN_NENABLE	(1<<0) /* SMC91x power disable */
+
+
 static struct resource smc91x_resources[] = {
 	[0] = {
 		.start	= CPLD00_PHYS,
@@ -48,12 +70,12 @@
 static struct resource lh7a40x_usbclient_resources[] = {
 	[0] = {
 		.start	= USB_PHYS,
-		.end	= (USB_PHYS + 0xFF),
+		.end	= (USB_PHYS + PAGE_SIZE),
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= IRQ_USBINTR,
-		.end	= IRQ_USBINTR,
+		.start	= IRQ_USB,
+		.end	= IRQ_USB,
 		.flags	= IORESOURCE_IRQ,
 	},
 };
@@ -61,7 +83,8 @@
 static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
 
 static struct platform_device lh7a40x_usbclient_device = {
-	.name		= "lh7a40x_udc",
+//	.name		= "lh7a40x_udc",
+	.name		= "lh7-udc",
 	.id		= 0,
 	.dev		= {
 		.dma_mask = &lh7a40x_usbclient_dma_mask,
@@ -101,7 +124,7 @@
 
 #endif
 
-static struct platform_device *lpd7a40x_devs[] __initdata = {
+static struct platform_device* lpd7a40x_devs[] __initdata = {
 	&smc91x_device,
 	&lh7a40x_usbclient_device,
 #if defined (CONFIG_ARCH_LH7A404)
@@ -113,29 +136,52 @@
 
 static void __init lpd7a40x_init (void)
 {
-	CPLD_CONTROL |=     (1<<6); /* Mask USB1 connection IRQ */
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_CONTROL |= 0
+		| CPLD_CONTROL_SWINT /* Disable software interrupt */
+		| CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */
 	CPLD_CONTROL &= ~(0
-			  | (1<<1) /* Disable LCD */
-			  | (1<<0) /* Enable WLAN */
+			  | CPLD_CONTROL_LCD_ENABLE	/* Disable LCD */
+			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
 		);
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+	CPLD_CONTROL &= ~(0
+			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
+		);
+#endif
 
 	platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
+#if defined (CONFIG_FB_ARMCLCD)
+        lh7a40x_clcd_init ();
+#endif
 }
 
 static void lh7a40x_ack_cpld_irq (u32 irq)
 {
-	/* CPLD doesn't have ack capability */
+	/* CPLD doesn't have ack capability, but some devices may */
+
+#if defined (CPLD_INTMASK_TOUCH)
+	/* The touch control *must* mask the the interrupt because the
+	 * interrupt bit is read by the driver to determine if the pen
+	 * is still down. */
+	if (irq == IRQ_TOUCH)
+		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
+#endif
 }
 
 static void lh7a40x_mask_cpld_irq (u32 irq)
 {
 	switch (irq) {
 	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
+		CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
 		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
+#if defined (IRQ_TOUCH)
+	case IRQ_TOUCH:
+		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
 		break;
+#endif
 	}
 }
 
@@ -143,11 +189,13 @@
 {
 	switch (irq) {
 	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
+		CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
 		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
+#if defined (IRQ_TOUCH)
+	case IRQ_TOUCH:
+		CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH;
 		break;
+#endif
 	}
 }
 
@@ -164,11 +212,13 @@
 
 	desc->chip->ack (irq);
 
-	if ((mask & 0x1) == 0)	/* WLAN */
+	if ((mask & (1<<0)) == 0)	/* WLAN */
 		IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT);
 
-	if ((mask & 0x2) == 0)	/* Touch */
-		IRQ_DISPATCH (IRQ_LPD7A400_TS);
+#if defined (IRQ_TOUCH)
+	if ((mask & (1<<1)) == 0)	/* Touch */
+		IRQ_DISPATCH (IRQ_TOUCH);
+#endif
 
 	desc->chip->unmask (irq); /* Level-triggered need this */
 }
@@ -204,9 +254,21 @@
 
 		/* Then, configure CPLD interrupt */
 
-	CPLD_INTERRUPTS	=   0x9c; /* Disable all CPLD interrupts */
+			/* Disable all CPLD interrupts */
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_INTERRUPTS	= CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN
+		| CPLD_INTMASK_ETHERNET;
+	/* *** FIXME: don't know why we need 7 and 4. 7 is way wrong
+               and 4 is uncefined. */
+	// (1<<7)|(1<<4)|(1<<3)|(1<<2);
+#endif
+#if defined (CONFIG_MACH_LPD7A404)
+	CPLD_INTERRUPTS	= CPLD_INTMASK_ETHERNET;
+	/* *** FIXME: don't know why we need 6 and 5, neither is defined. */
+	// (1<<6)|(1<<5)|(1<<3);
+#endif
 	GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */
-	GPIO_INTTYPE1	|=  (1 << pinCPLD); /* Edge triggered */
+	GPIO_INTTYPE1	&= ~(1 << pinCPLD); /* Level triggered */
 	GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */
 	barrier ();
 	GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */
@@ -216,7 +278,7 @@
 	for (irq = IRQ_BOARD_START;
 	     irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
 		set_irq_chip (irq, &lpd7a40x_cpld_chip);
-		set_irq_handler (irq, do_edge_IRQ);
+		set_irq_handler (irq, do_level_IRQ);
 		set_irq_flags (irq, IRQF_VALID);
 	}
 
@@ -226,91 +288,109 @@
 				 lpd7a40x_cpld_handler);
 }
 
-static struct map_desc lpd7a400_io_desc[] __initdata = {
+static struct map_desc lpd7a40x_io_desc[] __initdata = {
 	{
-		.virtual	=     IO_VIRT,
+		.virtual	= IO_VIRT,
 		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= 	    IO_SIZE,
+		.length		= IO_SIZE,
 		.type		= MT_DEVICE
-	}, {	/* Mapping added to work around chip select problems */
+	},
+	{	/* Mapping added to work around chip select problems */
 		.virtual	= IOBARRIER_VIRT,
 		.pfn		= __phys_to_pfn(IOBARRIER_PHYS),
 		.length		= IOBARRIER_SIZE,
 		.type		= MT_DEVICE
-	}, {
+	},
+	{
 		.virtual	= CF_VIRT,
 		.pfn		= __phys_to_pfn(CF_PHYS),
-		.length		= 	CF_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD02_VIRT,
-		.pfn		= __phys_to_pfn(CPLD02_PHYS),
-		.length		= 	CPLD02_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD06_VIRT,
-		.pfn		= __phys_to_pfn(CPLD06_PHYS),
-		.length		= 	CPLD06_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD08_VIRT,
-		.pfn		= __phys_to_pfn(CPLD08_PHYS),
-		.length		= 	CPLD08_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD0C_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0C_PHYS),
-		.length		= 	CPLD0C_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD0E_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0E_PHYS),
-		.length		= 	CPLD0E_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD10_VIRT,
-		.pfn		= __phys_to_pfn(CPLD10_PHYS),
-		.length		= 	CPLD10_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD12_VIRT,
-		.pfn		= __phys_to_pfn(CPLD12_PHYS),
-		.length		= 	CPLD12_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD14_VIRT,
-		.pfn		= __phys_to_pfn(CPLD14_PHYS),
-		.length		= 	CPLD14_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD16_VIRT,
-		.pfn		= __phys_to_pfn(CPLD16_PHYS),
-		.length		= 	CPLD16_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD18_VIRT,
-		.pfn		= __phys_to_pfn(CPLD18_PHYS),
-		.length		= 	CPLD18_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD1A_VIRT,
-		.pfn		= __phys_to_pfn(CPLD1A_PHYS),
-		.length		= 	CPLD1A_SIZE,
+		.length		= CF_SIZE,
 		.type		= MT_DEVICE
 	},
-	/* This mapping is redundant since the smc driver performs another. */
-/*	{ CPLD00_VIRT,  CPLD00_PHYS,	CPLD00_SIZE,	MT_DEVICE }, */
+	{
+		.virtual	= CPLD02_VIRT,
+		.pfn		= __phys_to_pfn(CPLD02_PHYS),
+		.length		= CPLD02_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD06_VIRT,
+		.pfn		= __phys_to_pfn(CPLD06_PHYS),
+		.length		= CPLD06_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD08_VIRT,
+		.pfn		= __phys_to_pfn(CPLD08_PHYS),
+		.length		= CPLD08_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD08_VIRT,
+		.pfn		= __phys_to_pfn(CPLD08_PHYS),
+		.length		= CPLD08_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD0A_VIRT,
+		.pfn		= __phys_to_pfn(CPLD0A_PHYS),
+		.length		= CPLD0A_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD0C_VIRT,
+		.pfn		= __phys_to_pfn(CPLD0C_PHYS),
+		.length		= CPLD0C_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD0E_VIRT,
+		.pfn		= __phys_to_pfn(CPLD0E_PHYS),
+		.length		= CPLD0E_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD10_VIRT,
+		.pfn		= __phys_to_pfn(CPLD10_PHYS),
+		.length		= CPLD10_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD12_VIRT,
+		.pfn		= __phys_to_pfn(CPLD12_PHYS),
+		.length		= CPLD12_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD14_VIRT,
+		.pfn		= __phys_to_pfn(CPLD14_PHYS),
+		.length		= CPLD14_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD16_VIRT,
+		.pfn		= __phys_to_pfn(CPLD16_PHYS),
+		.length		= CPLD16_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD18_VIRT,
+		.pfn		= __phys_to_pfn(CPLD18_PHYS),
+		.length		= CPLD18_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= CPLD1A_VIRT,
+		.pfn		= __phys_to_pfn(CPLD1A_PHYS),
+		.length		= CPLD1A_SIZE,
+		.type		= MT_DEVICE
+	},
 };
 
 void __init
-lpd7a400_map_io(void)
+lpd7a40x_map_io(void)
 {
-	iotable_init (lpd7a400_io_desc, ARRAY_SIZE (lpd7a400_io_desc));
-
-		/* Fixup (improve) Static Memory Controller settings */
-	SMC_BCR0 = 0x200039af;	/* Boot Flash */
-	SMC_BCR6 = 0x1000fbe0;	/* CPLD */
-	SMC_BCR7 = 0x1000b2c2;	/* Compact Flash */
+	iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc));
 }
 
 #ifdef CONFIG_MACH_LPD7A400
@@ -320,7 +400,7 @@
 	.phys_io	= 0x80000000,
 	.io_pg_offst	= ((io_p2v (0x80000000))>>18) & 0xfffc,
 	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a400_map_io,
+	.map_io		= lpd7a40x_map_io,
 	.init_irq	= lh7a400_init_irq,
 	.timer		= &lh7a40x_timer,
 	.init_machine	= lpd7a40x_init,
@@ -335,7 +415,7 @@
 	.phys_io	= 0x80000000,
 	.io_pg_offst	= ((io_p2v (0x80000000))>>18) & 0xfffc,
 	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a400_map_io,
+	.map_io		= lpd7a40x_map_io,
 	.init_irq	= lh7a404_init_irq,
 	.timer		= &lh7a40x_timer,
 	.init_machine	= lpd7a40x_init,
diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c
new file mode 100644
index 0000000..93751fe
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/clcd.c
@@ -0,0 +1,241 @@
+/*
+ *  arch/arm/mach-lh7a40x/clcd.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+
+//#include <linux/module.h>
+//#include <linux/time.h>
+//#include <asm/hardware.h>
+
+//#include <asm/mach/time.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#define HRTFTC_HRSETUP		__REG(HRTFTC_PHYS + 0x00)
+#define HRTFTC_HRCON		__REG(HRTFTC_PHYS + 0x04)
+#define HRTFTC_HRTIMING1	__REG(HRTFTC_PHYS + 0x08)
+#define HRTFTC_HRTIMING2	__REG(HRTFTC_PHYS + 0x0c)
+
+#define ALI_SETUP		__REG(ALI_PHYS + 0x00)
+#define ALI_CONTROL		__REG(ALI_PHYS + 0x04)
+#define ALI_TIMING1		__REG(ALI_PHYS + 0x08)
+#define ALI_TIMING2		__REG(ALI_PHYS + 0x0c)
+
+#include "lcd-panel.h"
+
+static void lh7a40x_clcd_disable (struct clcd_fb *fb)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_CONTROL &= ~(1<<1);	/* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+	GPIO_PCD  &= ~(1<<3);		/* Disable LCD Vee */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+	HRTFTC_HRSETUP &= ~(1<<13);	/* Disable HRTFT controller */
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+	ALI_SETUP &= ~(1<<13);		/* Disable ALI */
+#endif
+}
+
+static void lh7a40x_clcd_enable (struct clcd_fb *fb)
+{
+	struct clcd_panel_extra* extra
+		= (struct clcd_panel_extra*) fb->board_data;
+
+#if defined (CONFIG_MACH_LPD7A400)
+	CPLD_CONTROL |= (1<<1);		/* Enable LCD Vee */
+#endif
+
+#if defined (CONFIG_MACH_LPD7A404)
+	GPIO_PCDD &= ~(1<<3);		/* Enable LCD Vee */
+	GPIO_PCD  |=  (1<<3);
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+
+	if (extra) {
+		HRTFTC_HRSETUP
+			= (1 << 13)
+			| ((fb->fb.var.xres - 1) << 4)
+			| 0xc
+			| (extra->hrmode ? 1 : 0);
+		HRTFTC_HRCON
+			= ((extra->clsen ? 1 : 0) << 1)
+			| ((extra->spsen ? 1 : 0) << 0);
+		HRTFTC_HRTIMING1
+			= (extra->pcdel << 8)
+			| (extra->revdel << 4)
+			| (extra->lpdel << 0);
+		HRTFTC_HRTIMING2
+			= (extra->spldel << 9)
+			| (extra->pc2del << 0);
+	}
+	else
+		HRTFTC_HRSETUP
+			= (1 << 13)
+			| 0xc;
+#endif
+
+#if defined (CONFIG_ARCH_LH7A404)
+
+	if (extra) {
+		ALI_SETUP
+			= (1 << 13)
+			| ((fb->fb.var.xres - 1) << 4)
+			| 0xc
+			| (extra->hrmode ? 1 : 0);
+		ALI_CONTROL
+			= ((extra->clsen ? 1 : 0) << 1)
+			| ((extra->spsen ? 1 : 0) << 0);
+		ALI_TIMING1
+			= (extra->pcdel << 8)
+			| (extra->revdel << 4)
+			| (extra->lpdel << 0);
+		ALI_TIMING2
+			= (extra->spldel << 9)
+			| (extra->pc2del << 0);
+	}
+	else
+		ALI_SETUP
+			= (1 << 13)
+			| 0xc;
+#endif
+
+}
+
+#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
+
+static int lh7a40x_clcd_setup (struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+	u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
+			     *(lcd_panel.bpp/8));
+
+	fb->panel = &lcd_panel;
+
+		/* Enforce the sync polarity defaults */
+	if (!(fb->panel->tim2 & TIM2_IHS))
+		fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (!(fb->panel->tim2 & TIM2_IVS))
+		fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
+
+#if defined (HAS_LCD_PANEL_EXTRA)
+	fb->board_data = &lcd_panel_extra;
+#endif
+
+	fb->fb.screen_base
+		= dma_alloc_writecombine (&fb->dev->dev, len,
+					  &dma, GFP_KERNEL);
+	printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
+		fb->fb.screen_base, (void*) dma, len,
+		(void*) io_p2v (CLCDC_PHYS));
+	printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
+
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+#if defined (USE_RGB555)
+	fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
+#endif
+
+	fb->fb.fix.smem_start = dma;
+	fb->fb.fix.smem_len = len;
+
+		/* Drive PE4 high to prevent CPLD crash */
+	GPIO_PEDD |= (1<<4);
+	GPIO_PED  |= (1<<4);
+
+	GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
+
+//	fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
+//	fb->fb.fbops->fb_set_par (&fb->fb);
+
+	return 0;
+}
+
+static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+				     fb->fb.screen_base,
+				     fb->fb.fix.smem_start,
+				     fb->fb.fix.smem_len);
+}
+
+static void lh7a40x_clcd_remove (struct clcd_fb *fb)
+{
+	dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
+			       fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+static struct clcd_board clcd_platform_data = {
+	.name		= "lh7a40x FB",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.enable		= lh7a40x_clcd_enable,
+	.setup		= lh7a40x_clcd_setup,
+	.mmap		= lh7a40x_clcd_mmap,
+	.remove		= lh7a40x_clcd_remove,
+	.disable	= lh7a40x_clcd_disable,
+};
+
+#define IRQ_CLCDC (IRQ_LCDINTR)
+
+#define AMBA_DEVICE(name,busid,base,plat,pid)			\
+static struct amba_device name##_device = {			\
+	.dev = {						\
+		.coherent_dma_mask = ~0,			\
+		.bus_id	= busid,				\
+		.platform_data = plat,				\
+		},						\
+	.res = {						\
+		.start	= base##_PHYS,				\
+		.end	= (base##_PHYS) + (4*1024) - 1,		\
+		.flags	= IORESOURCE_MEM,			\
+		},						\
+	.dma_mask	= ~0,					\
+	.irq		= { IRQ_##base, },			\
+	/* .dma		= base##_DMA,*/				\
+	.periphid = pid,					\
+}
+
+AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
+
+static struct amba_device *amba_devs[] __initdata = {
+	&clcd_device,
+};
+
+void __init lh7a40x_clcd_init (void)
+{
+	int i;
+	int result;
+	printk ("CLCD: registering amba devices\n");
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		result = amba_device_register(d, &iomem_resource);
+		printk ("  %d -> %d\n", i ,result);
+	}
+}
diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c
new file mode 100644
index 0000000..2291afe9
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/clocks.c
@@ -0,0 +1,199 @@
+/* arch/arm/mach-lh7a40x/clocks.c
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/cpufreq.h>
+#include <asm/hardware.h>
+#include <asm/arch/clocks.h>
+#include <linux/err.h>
+
+struct module;
+struct icst525_params;
+
+struct clk {
+	struct list_head node;
+	unsigned long rate;
+	struct module *owner;
+	const char *name;
+//	void *data;
+//	const struct icst525_params *params;
+//	void (*setvco)(struct clk *, struct icst525_vco vco);
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+/* ----- */
+
+#define MAINDIV1(c)	(((c) >>  7) & 0x0f)
+#define MAINDIV2(c)	(((c) >> 11) & 0x1f)
+#define PS(c)		(((c) >> 18) & 0x03)
+#define PREDIV(c)	(((c) >>  2) & 0x1f)
+#define HCLKDIV(c)	(((c) >>  0) & 0x02)
+#define PCLKDIV(c)	(((c) >> 16) & 0x03)
+
+unsigned int cpufreq_get (unsigned int cpu) /* in kHz */
+{
+	return fclkfreq_get ()/1000;
+}
+EXPORT_SYMBOL(cpufreq_get);
+
+unsigned int fclkfreq_get (void)
+{
+	unsigned int clkset = CSC_CLKSET;
+	unsigned int gclk
+		= XTAL_IN
+		/ (1 << PS(clkset))
+		* (MAINDIV1(clkset) + 2)
+		/ (PREDIV(clkset)   + 2)
+		* (MAINDIV2(clkset) + 2)
+		;
+	return gclk;
+}
+
+unsigned int hclkfreq_get (void)
+{
+	unsigned int clkset = CSC_CLKSET;
+	unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
+
+	return hclk;
+}
+
+unsigned int pclkfreq_get (void)
+{
+	unsigned int clkset = CSC_CLKSET;
+	int pclkdiv = PCLKDIV(clkset);
+	unsigned int pclk;
+	if (pclkdiv == 0x3)
+		pclkdiv = 0x2;
+	pclk = hclkfreq_get () / (1 << pclkdiv);
+
+	return pclk;
+}
+
+/* ----- */
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+
+struct clk *clk_get (struct device *dev, const char *id)
+{
+	struct clk *p;
+	struct clk *clk = ERR_PTR(-ENOENT);
+
+	down (&clocks_sem);
+	list_for_each_entry (p, &clocks, node) {
+		if (strcmp (id, p->name) == 0
+		    && try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+	up (&clocks_sem);
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put (struct clk *clk)
+{
+	module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable (struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+int clk_use (struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_use);
+
+void clk_unuse (struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_unuse);
+
+unsigned long clk_get_rate (struct clk *clk)
+{
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate (struct clk *clk, unsigned long rate)
+{
+	return rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate (struct clk *clk, unsigned long rate)
+{
+	int ret = -EIO;
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+#if 0
+/*
+ * These are fixed clocks.
+ */
+static struct clk kmi_clk = {
+	.name	= "KMIREFCLK",
+	.rate	= 24000000,
+};
+
+static struct clk uart_clk = {
+	.name	= "UARTCLK",
+	.rate	= 24000000,
+};
+
+static struct clk mmci_clk = {
+	.name	= "MCLK",
+	.rate	= 33000000,
+};
+#endif
+
+static struct clk clcd_clk = {
+	.name	= "CLCDCLK",
+	.rate	= 0,
+};
+
+int clk_register (struct clk *clk)
+{
+	down (&clocks_sem);
+	list_add (&clk->node, &clocks);
+	up (&clocks_sem);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister (struct clk *clk)
+{
+	down (&clocks_sem);
+	list_del (&clk->node);
+	up (&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init (void)
+{
+	clk_register(&clcd_clk);
+	return 0;
+}
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
index ea8de7e..18e8bb4 100644
--- a/arch/arm/mach-lh7a40x/common.h
+++ b/arch/arm/mach-lh7a40x/common.h
@@ -12,6 +12,7 @@
 
 extern void lh7a400_init_irq (void);
 extern void lh7a404_init_irq (void);
+extern void lh7a40x_clcd_init (void);
 extern void lh7a40x_init_board_irq (void);
 
 #define IRQ_DISPATCH(irq) desc_handle_irq((irq),(irq_desc + irq), regs)
diff --git a/arch/arm/mach-lh7a40x/irq-lh7a404.c b/arch/arm/mach-lh7a40x/irq-lh7a404.c
index e902e3d..2685a81 100644
--- a/arch/arm/mach-lh7a40x/irq-lh7a404.c
+++ b/arch/arm/mach-lh7a40x/irq-lh7a404.c
@@ -28,13 +28,17 @@
 
 static unsigned char irq_pri_vic1[] = {
 #if defined (USE_PRIORITIES)
-IRQ_GPIO3INTR,
+	IRQ_GPIO3INTR,			/* CPLD */
+	IRQ_DMAM2P4, IRQ_DMAM2P5,	/* AC97 */
 #endif
 };
 static unsigned char irq_pri_vic2[] = {
 #if defined (USE_PRIORITIES)
-	IRQ_T3UI, IRQ_GPIO7INTR,
+	IRQ_T3UI,			/* Timer */
+	IRQ_GPIO7INTR,			/* CPLD */
 	IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
+	IRQ_LCDINTR,			/* LCD */
+	IRQ_TSCINTR,			/* ADC/Touchscreen */
 #endif
 };
 
@@ -98,10 +102,19 @@
 
   /* IRQ initialization */
 
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+extern void* branch_irq_lh7a400;
+#endif
+
 void __init lh7a404_init_irq (void)
 {
 	int irq;
 
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+#define NOP 0xe1a00000			/* mov r0, r0 */
+	branch_irq_lh7a400 = NOP;
+#endif
+
 	VIC1_INTENCLR = 0xffffffff;
 	VIC2_INTENCLR = 0xffffffff;
 	VIC1_INTSEL = 0;		/* All IRQs */
diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h
new file mode 100644
index 0000000..4fb2efc
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/lcd-panel.h
@@ -0,0 +1,346 @@
+/* lcd-panel.h
+     $Id$
+
+   written by Marc Singer
+   18 Jul 2005
+
+   Copyright (C) 2005 Marc Singer
+
+   -----------
+   DESCRIPTION
+   -----------
+
+   Only one panel may be defined at a time.
+
+   The pixel clock is calculated to be no greater than the target.
+
+   Each timing value is accompanied by a specification comment.
+
+     UNITS/MIN/TYP/MAX
+
+   Most of the units will be in clocks.
+
+   USE_RGB555
+
+     Define this macro to configure the AMBA LCD controller to use an
+     RGB555 encoding for the pels instead of the normal RGB565.
+
+   LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
+
+     These boards are best approximated by 555 for all panels.  Some
+     can use an extra low-order bit of blue in bit 16 of the color
+     value, but we don't have a way to communicate this non-linear
+     mapping to the kernel.
+
+*/
+
+#if !defined (__LCD_PANEL_H__)
+#    define   __LCD_PANEL_H__
+
+#if defined (MACH_LPD79520)\
+ || defined (MACH_LPD79524)\
+ || defined (MACH_LPD7A400)\
+ || defined (MACH_LPD7A404)
+# define USE_RGB555
+#endif
+
+struct clcd_panel_extra {
+	unsigned int hrmode;
+	unsigned int clsen;
+	unsigned int spsen;
+	unsigned int pcdel;
+	unsigned int revdel;
+	unsigned int lpdel;
+	unsigned int spldel;
+	unsigned int pc2del;
+};
+
+#define NS_TO_CLOCK(ns,c)	((((ns)*((c)/1000) + (1000000 - 1))/1000000))
+#define CLOCK_TO_DIV(e,c)	(((c) + (e) - 1)/(e))
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
+
+	/* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
+	/* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
+
+#define PIX_CLOCK_TARGET	(6800000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "3.5in QVGA (LQ035Q7DB02)",
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 16,
+		.right_margin	= 21,
+		.upper_margin	= 8,			// line/8/8/8
+		.lower_margin	= 5,
+		.hsync_len	= 61,
+		.vsync_len	= NS_TO_CLOCK (60, PIX_CLOCK),
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#define HAS_LCD_PANEL_EXTRA
+
+static struct clcd_panel_extra lcd_panel_extra = {
+	.hrmode = 1,
+	.clsen = 1,
+	.spsen = 1,
+	.pcdel = 8,
+	.revdel = 7,
+	.lpdel = 13,
+	.spldel = 77,
+	.pc2del = 208,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
+
+	/* Logic Product Development LCD 5.7" QVGA -10 */
+	/* Sharp PN LQ057Q3DC02 */
+	/* QVGA mode, V/Q=LOW */
+
+/* From Sharp on 2006.1.3.  I believe some of the values are incorrect
+ * based on the datasheet.
+
+    Timing0	TIMING1		TIMING2		CONTROL
+    0x140A0C4C	0x080504EF	0x013F380D	0x00000829
+    HBP= 20	VBP=  8		BCD=  0
+    HFP= 10	VFP=  5		CPL=319
+    HSW= 12	VSW=  1		IOE=  0
+    PPL= 19	LPP=239		IPC=  1
+				IHS=  1
+				IVS=  1
+				ACB=  0
+				CSEL= 0
+				PCD= 13
+
+ */
+
+/* The full horozontal cycle (Th) is clock/360/400/450. */
+/* The full vertical   cycle (Tv) is line/251/262/280. */
+
+#define PIX_CLOCK_TARGET	(6300000) /* -/6.3/7 MHz */
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "5.7in QVGA (LQ057Q3DC02)",
+		.xres		= 320,
+		.yres		= 240,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 11,
+		.right_margin	= 400-11-320-2,
+		.upper_margin	= 7,			// line/7/7/7
+		.lower_margin	= 262-7-240-2,
+		.hsync_len	= 2,			// clk/2/96/200
+		.vsync_len	= 2,			// line/2/-/34
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
+
+	/* Logic Product Development LCD 6.4" VGA -10 */
+	/* Sharp PN LQ64D343 */
+
+/* The full horozontal cycle (Th) is clock/750/800/900. */
+/* The full vertical   cycle (Tv) is line/515/525/560. */
+
+#define PIX_CLOCK_TARGET	(28330000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "6.4in QVGA (LQ64D343)",
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 32,
+		.right_margin	= 800-32-640-96,
+		.upper_margin	= 32,			// line/34/34/34
+		.lower_margin	= 540-32-480-2,
+		.hsync_len	= 96,			// clk/2/96/200
+		.vsync_len	= 2,			// line/2/-/34
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
+
+	/* Logic Product Development LCD 10.4" VGA -10 */
+	/* Sharp PN LQ10D368 */
+
+#define PIX_CLOCK_TARGET	(28330000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "10.4in VGA (LQ10D368)",
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 21,
+		.right_margin	= 15,
+		.upper_margin	= 34,
+		.lower_margin	= 5,
+		.hsync_len	= 96,
+		.vsync_len	= 16,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
+
+	/* Logic Product Development LCD 12.1" SVGA -10 */
+	/* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
+
+/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
+ * target clock frequency range of 35MHz to 42MHz. */
+
+/* If the target pixel clock is substantially lower than the panel
+ * spec, this is done to prevent the LCD display from glitching when
+ * the CPU is under load.  A pixel clock higher than 25MHz
+ * (empirically determined) will compete with the CPU for bus cycles
+ * for the Ethernet chip.  However, even a pixel clock of 10MHz
+ * competes with Compact Flash interface during some operations
+ * (fdisk, e2fsck).  And, at that speed the display may have a visible
+ * flicker. */
+
+/* The full horozontal cycle (Th) is clock/832/1056/1395. */
+
+#define PIX_CLOCK_TARGET	(20000000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "12.1in SVGA (LQ121S1DG41)",
+		.xres		= 800,
+		.yres		= 600,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 89,		// ns/5/-/(1/PIX_CLOCK)-10
+		.right_margin	= 1056-800-89-128,
+		.upper_margin	= 23,		// line/23/23/23
+		.lower_margin	= 44,
+		.hsync_len	= 128,		// clk/2/128/200
+		.vsync_len	= 4,		// line/2/4/6
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#if defined CONFIG_FB_ARMCLCD_HITACHI
+
+	/* Hitachi*/
+	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET	(49000000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "Hitachi 800x480",
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 128,
+		.vsync_len	= 2,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+
+#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
+
+	/* AU Optotronics  A070VW01 7.0 Wide Screen color Display*/
+	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
+
+#define PIX_CLOCK_TARGET	(10000000)
+#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
+#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
+
+static struct clcd_panel lcd_panel = {
+	.mode	= {
+		.name		= "7.0in Wide (A070VW01)",
+		.xres		= 480,
+		.yres		= 234,
+		.pixclock	= PIX_CLOCK,
+		.left_margin	= 30,
+		.right_margin	= 25,
+		.upper_margin	= 14,
+		.lower_margin	= 12,
+		.hsync_len	= 100,
+		.vsync_len	= 1,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
+			| (PIX_CLOCK_DIVIDER - 2),
+	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
+	.bpp		= 16,
+};
+
+#endif
+
+#undef NS_TO_CLOCK
+#undef CLOCK_TO_DIV
+
+#endif  /* __LCD_PANEL_H__ */
diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c
new file mode 100644
index 0000000..a108301
--- /dev/null
+++ b/arch/arm/mach-lh7a40x/ssp-cpld.c
@@ -0,0 +1,343 @@
+/* arch/arm/mach-lh7a40x/ssp-cpld.c
+ *
+ *  Copyright (C) 2004,2005 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ * SSP/SPI driver for the CardEngine CPLD.
+ *
+ */
+
+/* NOTES
+   -----
+
+   o *** This driver is cribbed from the 7952x implementation.
+	 Some comments may not apply.
+
+   o This driver contains sufficient logic to control either the
+     serial EEPROMs or the audio codec.  It is included in the kernel
+     to support the codec.  The EEPROMs are really the responsibility
+     of the boot loader and should probably be left alone.
+
+   o The code must be augmented to cope with multiple, simultaneous
+     clients.
+     o The audio codec writes to the codec chip whenever playback
+       starts.
+     o The touchscreen driver writes to the ads chip every time it
+       samples.
+     o The audio codec must write 16 bits, but the touch chip writes
+       are 8 bits long.
+     o We need to be able to keep these configurations separate while
+       simultaneously active.
+
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+//#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+//#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+
+#include <asm/arch/ssp.h>
+
+//#define TALK
+
+#if defined (TALK)
+#define PRINTK(f...)		printk (f)
+#else
+#define PRINTK(f...)		do {} while (0)
+#endif
+
+#if defined (CONFIG_ARCH_LH7A400)
+# define CPLD_SPID		__REGP16(CPLD06_VIRT) /* SPI data */
+# define CPLD_SPIC		__REGP16(CPLD08_VIRT) /* SPI control */
+# define CPLD_SPIC_CS_CODEC	(1<<0)
+# define CPLD_SPIC_CS_TOUCH	(1<<1)
+# define CPLD_SPIC_WRITE	(0<<2)
+# define CPLD_SPIC_READ		(1<<2)
+# define CPLD_SPIC_DONE		(1<<3) /* r/o */
+# define CPLD_SPIC_LOAD		(1<<4)
+# define CPLD_SPIC_START	(1<<4)
+# define CPLD_SPIC_LOADED	(1<<5) /* r/o */
+#endif
+
+#define CPLD_SPI		__REGP16(CPLD0A_VIRT) /* SPI operation */
+#define CPLD_SPI_CS_EEPROM	(1<<3)
+#define CPLD_SPI_SCLK		(1<<2)
+#define CPLD_SPI_TX_SHIFT	(1)
+#define CPLD_SPI_TX		(1<<CPLD_SPI_TX_SHIFT)
+#define CPLD_SPI_RX_SHIFT	(0)
+#define CPLD_SPI_RX		(1<<CPLD_SPI_RX_SHIFT)
+
+/* *** FIXME: these timing values are substantially larger than the
+   *** chip requires. We may implement an nsleep () function. */
+#define T_SKH	1		/* Clock time high (us) */
+#define T_SKL	1		/* Clock time low (us) */
+#define T_CS	1		/* Minimum chip select low time (us)  */
+#define T_CSS	1		/* Minimum chip select setup time (us)  */
+#define T_DIS	1		/* Data setup time (us) */
+
+	 /* EEPROM SPI bits */
+#define P_START		(1<<9)
+#define P_WRITE		(1<<7)
+#define P_READ		(2<<7)
+#define P_ERASE		(3<<7)
+#define P_EWDS		(0<<7)
+#define P_WRAL		(0<<7)
+#define P_ERAL		(0<<7)
+#define P_EWEN		(0<<7)
+#define P_A_EWDS	(0<<5)
+#define P_A_WRAL	(1<<5)
+#define P_A_ERAL	(2<<5)
+#define P_A_EWEN	(3<<5)
+
+struct ssp_configuration {
+	int device;
+	int mode;
+	int speed;
+	int frame_size_write;
+	int frame_size_read;
+};
+
+static struct ssp_configuration ssp_configuration;
+static spinlock_t ssp_lock;
+
+static void enable_cs (void)
+{
+	switch (ssp_configuration.device) {
+	case DEVICE_EEPROM:
+		CPLD_SPI |= CPLD_SPI_CS_EEPROM;
+		break;
+	}
+	udelay (T_CSS);
+}
+
+static void disable_cs (void)
+{
+	switch (ssp_configuration.device) {
+	case DEVICE_EEPROM:
+		CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
+		break;
+	}
+	udelay (T_CS);
+}
+
+static void pulse_clock (void)
+{
+	CPLD_SPI |=  CPLD_SPI_SCLK;
+	udelay (T_SKH);
+	CPLD_SPI &= ~CPLD_SPI_SCLK;
+	udelay (T_SKL);
+}
+
+
+/* execute_spi_command
+
+   sends an spi command to a device.  It first sends cwrite bits from
+   v.  If cread is greater than zero it will read cread bits
+   (discarding the leading 0 bit) and return them.  If cread is less
+   than zero it will check for completetion status and return 0 on
+   success or -1 on timeout.  If cread is zero it does nothing other
+   than sending the command.
+
+   On the LPD7A400, we can only read or write multiples of 8 bits on
+   the codec and the touch screen device.  Here, we round up.
+
+*/
+
+static int execute_spi_command (int v, int cwrite, int cread)
+{
+	unsigned long l = 0;
+
+#if defined (CONFIG_MACH_LPD7A400)
+	/* The codec and touch devices cannot be bit-banged.  Instead,
+	 * the CPLD provides an eight-bit shift register and a crude
+	 * interface.  */
+	if (   ssp_configuration.device == DEVICE_CODEC
+	    || ssp_configuration.device == DEVICE_TOUCH) {
+		int select = 0;
+
+		PRINTK ("spi(%d %d.%d) 0x%04x",
+			ssp_configuration.device, cwrite, cread,
+			v);
+#if defined (TALK)
+		if (ssp_configuration.device == DEVICE_CODEC)
+			PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
+#endif
+		PRINTK ("\n");
+
+		if (ssp_configuration.device == DEVICE_CODEC)
+			select = CPLD_SPIC_CS_CODEC;
+		if (ssp_configuration.device == DEVICE_TOUCH)
+			select = CPLD_SPIC_CS_TOUCH;
+		if (cwrite) {
+			for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
+				CPLD_SPID = (v >> (8*cwrite)) & 0xff;
+				CPLD_SPIC = select | CPLD_SPIC_LOAD;
+				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+					;
+				CPLD_SPIC = select;
+				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+					;
+			}
+			v = 0;
+		}
+		if (cread) {
+			mdelay (2);	/* *** FIXME: required by ads7843? */
+			v = 0;
+			for (cread = (cread + 7)/8; cread-- > 0;) {
+				CPLD_SPID = 0;
+				CPLD_SPIC = select | CPLD_SPIC_READ
+					| CPLD_SPIC_START;
+				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
+					;
+				CPLD_SPIC = select | CPLD_SPIC_READ;
+				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
+					;
+				v = (v << 8) | CPLD_SPID;
+			}
+		}
+		return v;
+	}
+#endif
+
+	PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
+		v & 0x1ff, (v >> 9) & 0x7f);
+
+	enable_cs ();
+
+	v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
+	while (cwrite--) {
+		CPLD_SPI
+			= (CPLD_SPI & ~CPLD_SPI_TX)
+			| ((v >> cwrite) & CPLD_SPI_TX);
+		udelay (T_DIS);
+		pulse_clock ();
+	}
+
+	if (cread < 0) {
+		int delay = 10;
+		disable_cs ();
+		udelay (1);
+		enable_cs ();
+
+		l = -1;
+		do {
+			if (CPLD_SPI & CPLD_SPI_RX) {
+				l = 0;
+				break;
+			}
+		} while (udelay (1), --delay);
+	}
+	else
+	/* We pulse the clock before the data to skip the leading zero. */
+		while (cread-- > 0) {
+			pulse_clock ();
+			l = (l<<1)
+				| (((CPLD_SPI & CPLD_SPI_RX)
+				    >> CPLD_SPI_RX_SHIFT) & 0x1);
+		}
+
+	disable_cs ();
+	return l;
+}
+
+static int ssp_init (void)
+{
+	spin_lock_init (&ssp_lock);
+	memset (&ssp_configuration, 0, sizeof (ssp_configuration));
+	return 0;
+}
+
+
+/* ssp_chip_select
+
+   drops the chip select line for the CPLD shift-register controlled
+   devices.  It doesn't enable chip
+
+*/
+
+static void ssp_chip_select (int enable)
+{
+#if defined (CONFIG_MACH_LPD7A400)
+	int select;
+
+	if (ssp_configuration.device == DEVICE_CODEC)
+		select = CPLD_SPIC_CS_CODEC;
+	else if (ssp_configuration.device == DEVICE_TOUCH)
+		select = CPLD_SPIC_CS_TOUCH;
+	else
+		return;
+
+	if (enable)
+		CPLD_SPIC = select;
+	else
+		CPLD_SPIC = 0;
+#endif
+}
+
+static void ssp_acquire (void)
+{
+	spin_lock (&ssp_lock);
+}
+
+static void ssp_release (void)
+{
+	ssp_chip_select (0);	/* just in case */
+	spin_unlock (&ssp_lock);
+}
+
+static int ssp_configure (int device, int mode, int speed,
+			   int frame_size_write, int frame_size_read)
+{
+	ssp_configuration.device		= device;
+	ssp_configuration.mode			= mode;
+	ssp_configuration.speed			= speed;
+	ssp_configuration.frame_size_write	= frame_size_write;
+	ssp_configuration.frame_size_read	= frame_size_read;
+
+	return 0;
+}
+
+static int ssp_read (void)
+{
+	return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
+}
+
+static int ssp_write (u16 data)
+{
+	execute_spi_command (data, ssp_configuration.frame_size_write, 0);
+	return 0;
+}
+
+static int ssp_write_read (u16 data)
+{
+	return execute_spi_command (data, ssp_configuration.frame_size_write,
+				    ssp_configuration.frame_size_read);
+}
+
+struct ssp_driver lh7a40x_cpld_ssp_driver = {
+	.init		= ssp_init,
+	.acquire	= ssp_acquire,
+	.release	= ssp_release,
+	.configure	= ssp_configure,
+	.chip_select	= ssp_chip_select,
+	.read		= ssp_read,
+	.write		= ssp_write,
+	.write_read	= ssp_write_read,
+};
+
+
+MODULE_AUTHOR("Marc Singer");
+MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
index be377e3..ef9af37 100644
--- a/arch/arm/mach-lh7a40x/time.c
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -1,4 +1,4 @@
-/* 
+/*
  *  arch/arm/mach-lh7a40x/time.c
  *
  *  Copyright (C) 2004 Logic Product Development
@@ -57,7 +57,7 @@
 	.handler	= lh7a40x_timer_interrupt,
 };
 
-static void __init lh7a40x_timer_init(void)
+static void __init lh7a40x_timer_init (void)
 {
 				/* Stop/disable all timers */
 	TIMER_CONTROL1 = 0;
diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig
new file mode 100644
index 0000000..3d90ef1
--- /dev/null
+++ b/arch/arm/mach-netx/Kconfig
@@ -0,0 +1,24 @@
+menu "NetX Implementations"
+	depends on ARCH_NETX
+
+config MACH_NXDKN
+	bool "Enable Hilscher nxdkn Eval Board support"
+	depends on ARCH_NETX
+	help
+	  Board support for the Hilscher NetX Eval Board
+
+config MACH_NXDB500
+	bool "Enable Hilscher nxdb500 Eval Board support"
+	depends on ARCH_NETX
+	select ARM_AMBA
+	help
+	  Board support for the Hilscher nxdb500 Eval Board
+
+config MACH_NXEB500HMI
+	bool "Enable Hilscher nxeb500hmi Eval Board support"
+	depends on ARCH_NETX
+	select ARM_AMBA
+	help
+	  Board support for the Hilscher nxeb500hmi Eval Board
+
+endmenu
diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile
new file mode 100644
index 0000000..18785ff
--- /dev/null
+++ b/arch/arm/mach-netx/Makefile
@@ -0,0 +1,15 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+
+# Object file lists.
+
+obj-y			+= time.o generic.o pfifo.o xc.o
+
+# Specific board support
+obj-$(CONFIG_MACH_NXDKN) += nxdkn.o
+obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o
+obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o
diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot
new file mode 100644
index 0000000..b81cf6a
--- /dev/null
+++ b/arch/arm/mach-netx/Makefile.boot
@@ -0,0 +1,2 @@
+    zreladdr-y			:= 0x80008000
+
diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c
new file mode 100644
index 0000000..ef0ab61
--- /dev/null
+++ b/arch/arm/mach-netx/fb.c
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-netx/fb.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/arch/netx-regs.h>
+#include <asm/hardware.h>
+
+struct clk {};
+
+static struct clk fb_clk;
+
+static struct clcd_panel *netx_panel;
+
+void netx_clcd_enable(struct clcd_fb *fb)
+{
+}
+
+int netx_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->panel = netx_panel;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 1024*1024,
+						    &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start	= dma;
+	fb->fb.fix.smem_len	= 1024*1024;
+
+	return 0;
+}
+
+int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+				     fb->fb.screen_base,
+				     fb->fb.fix.smem_start,
+				     fb->fb.fix.smem_len);
+}
+
+void netx_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			      fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+void clk_disable(struct clk *clk)
+{
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	return &fb_clk;
+}
+
+void clk_put(struct clk *clk)
+{
+}
+
+static struct amba_device fb_device = {
+	.dev		= {
+		.bus_id	= "fb",
+		.coherent_dma_mask = ~0,
+	},
+	.res		= {
+		.start	= 0x00104000,
+		.end	= 0x00104fff,
+		.flags	= IORESOURCE_MEM,
+	},
+	.irq		= { NETX_IRQ_LCD, NO_IRQ },
+	.periphid	= 0x10112400,
+};
+
+int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel)
+{
+	netx_panel = panel;
+	fb_device.dev.platform_data = board;
+	return amba_device_register(&fb_device, &iomem_resource);
+}
diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h
new file mode 100644
index 0000000..4919cf3
--- /dev/null
+++ b/arch/arm/mach-netx/fb.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-netx/fb.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+void netx_clcd_enable(struct clcd_fb *fb);
+int netx_clcd_setup(struct clcd_fb *fb);
+int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma);
+void netx_clcd_remove(struct clcd_fb *fb);
+int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel);
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
new file mode 100644
index 0000000..af0b135
--- /dev/null
+++ b/arch/arm/mach-netx/generic.c
@@ -0,0 +1,193 @@
+/*
+ * arch/arm/mach-netx/generic.c
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <asm/hardware.h>
+#include <asm/mach/map.h>
+#include <asm/hardware/vic.h>
+#include <asm/io.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/mach/irq.h>
+
+static struct map_desc netx_io_desc[] __initdata = {
+	{
+		.virtual        = NETX_IO_VIRT,
+		.pfn            = __phys_to_pfn(NETX_IO_PHYS),
+		.length         = NETX_IO_SIZE,
+		.type           = MT_DEVICE
+	}
+};
+
+void __init netx_map_io(void)
+{
+	iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc));
+}
+
+static struct resource netx_rtc_resources[] = {
+	[0] = {
+		.start	= 0x00101200,
+		.end	= 0x00101220,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device netx_rtc_device = {
+	.name		= "netx-rtc",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_rtc_resources),
+	.resource	= netx_rtc_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&netx_rtc_device,
+};
+
+#if 0
+#define DEBUG_IRQ(fmt...)	printk(fmt)
+#else
+#define DEBUG_IRQ(fmt...)	while (0) {}
+#endif
+
+static void
+netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc,
+			struct pt_regs *regs)
+{
+	unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
+	unsigned int stat;
+
+	stat = ((readl(NETX_DPMAS_INT_EN) &
+		readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f;
+
+	desc = irq_desc + NETX_IRQ_HIF_CHAINED(0);
+
+	while (stat) {
+		if (stat & 1) {
+			DEBUG_IRQ("handling irq %d\n", irq);
+			desc_handle_irq(irq, desc, regs);
+		}
+		irq++;
+		desc++;
+		stat >>= 1;
+	}
+}
+
+static int
+netx_hif_irq_type(unsigned int _irq, unsigned int type)
+{
+	unsigned int val, irq;
+
+	val = readl(NETX_DPMAS_IF_CONF1);
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+
+	if (type & __IRQT_RISEDGE) {
+		DEBUG_IRQ("rising edges\n");
+		val |= (1 << 26) << irq;
+	}
+	if (type & __IRQT_FALEDGE) {
+		DEBUG_IRQ("falling edges\n");
+		val &= ~((1 << 26) << irq);
+	}
+	if (type & __IRQT_LOWLVL) {
+		DEBUG_IRQ("low level\n");
+		val &= ~((1 << 26) << irq);
+	}
+	if (type & __IRQT_HIGHLVL) {
+		DEBUG_IRQ("high level\n");
+		val |= (1 << 26) << irq;
+	}
+
+	writel(val, NETX_DPMAS_IF_CONF1);
+
+	return 0;
+}
+
+static void
+netx_hif_ack_irq(unsigned int _irq)
+{
+	unsigned int val, irq;
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	writel((1 << 24) << irq, NETX_DPMAS_INT_STAT);
+
+	val = readl(NETX_DPMAS_INT_EN);
+	val &= ~((1 << 24) << irq);
+	writel(val, NETX_DPMAS_INT_EN);
+
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static void
+netx_hif_mask_irq(unsigned int _irq)
+{
+	unsigned int val, irq;
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	val = readl(NETX_DPMAS_INT_EN);
+	val &= ~((1 << 24) << irq);
+	writel(val, NETX_DPMAS_INT_EN);
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static void
+netx_hif_unmask_irq(unsigned int _irq)
+{
+	unsigned int val, irq;
+
+	irq = _irq - NETX_IRQ_HIF_CHAINED(0);
+	val = readl(NETX_DPMAS_INT_EN);
+	val |= (1 << 24) << irq;
+	writel(val, NETX_DPMAS_INT_EN);
+	DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq);
+}
+
+static struct irqchip netx_hif_chip = {
+	.ack = netx_hif_ack_irq,
+	.mask = netx_hif_mask_irq,
+	.unmask = netx_hif_unmask_irq,
+	.set_type = netx_hif_irq_type,
+};
+
+void __init netx_init_irq(void)
+{
+	int irq;
+
+	vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0);
+
+	for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
+		set_irq_chip(irq, &netx_hif_chip);
+		set_irq_handler(irq, do_level_IRQ);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+
+	writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
+	set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
+}
+
+static int __init netx_init(void)
+{
+	return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+subsys_initcall(netx_init);
+
diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h
new file mode 100644
index 0000000..ede2d35
--- /dev/null
+++ b/arch/arm/mach-netx/generic.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-netx/generic.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+extern void __init netx_map_io(void);
+extern void __init netx_init_irq(void);
+
+struct sys_timer;
+extern struct sys_timer netx_timer;
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
new file mode 100644
index 0000000..e4a133d
--- /dev/null
+++ b/arch/arm/mach-netx/nxdb500.c
@@ -0,0 +1,210 @@
+/*
+ * arch/arm/mach-netx/nxdb500.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+#include "fb.h"
+
+static struct clcd_panel qvga = {
+	.mode		= {
+		.name		= "QVGA",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 187617,
+		.left_margin	= 6,
+		.right_margin	= 26,
+		.upper_margin	= 0,
+		.lower_margin	= 6,
+		.hsync_len	= 6,
+		.vsync_len	= 1,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		=  16,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+	var->green.length = 5;
+	var->green.msb_right = 0;
+
+	return clcdfb_check(fb, var);
+}
+
+static int nxdb500_clcd_setup(struct clcd_fb *fb)
+{
+	unsigned int val;
+
+	fb->fb.var.green.length = 5;
+	fb->fb.var.green.msb_right = 0;
+
+	/* enable asic control */
+	val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+	writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+	writel(3, NETX_SYSTEM_IOC_CR);
+
+	val = readl(NETX_PIO_OUTPIO);
+	writel(val | 1, NETX_PIO_OUTPIO);
+
+	val = readl(NETX_PIO_OEPIO);
+	writel(val | 1, NETX_PIO_OEPIO);
+	return netx_clcd_setup(fb);
+}
+
+static struct clcd_board clcd_data = {
+	.name		= "netX",
+	.check		= nxdb500_check,
+	.decode		= clcdfb_decode,
+	.enable		= netx_clcd_enable,
+	.setup		= nxdb500_clcd_setup,
+	.mmap		= netx_clcd_mmap,
+	.remove		= netx_clcd_remove,
+};
+
+static struct netxeth_platform_data eth0_platform_data = {
+	.xcno = 0,
+};
+
+static struct platform_device netx_eth0_device = {
+	.name		= "netx-eth",
+	.id		= 0,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth0_platform_data,
+	}
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+	.xcno = 1,
+};
+
+static struct platform_device netx_eth1_device = {
+	.name		= "netx-eth",
+	.id		= 1,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth1_platform_data,
+	}
+};
+
+static struct resource netx_uart0_resources[] = {
+	[0] = {
+		.start	= 0x00100A00,
+		.end	= 0x00100A3F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART0),
+		.end	= (NETX_IRQ_UART0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart0_device = {
+	.name		= "netx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_uart0_resources),
+	.resource	= netx_uart0_resources,
+};
+
+static struct resource netx_uart1_resources[] = {
+	[0] = {
+		.start	= 0x00100A40,
+		.end	= 0x00100A7F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART1),
+		.end	= (NETX_IRQ_UART1),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart1_device = {
+	.name		= "netx-uart",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(netx_uart1_resources),
+	.resource	= netx_uart1_resources,
+};
+
+static struct resource netx_uart2_resources[] = {
+	[0] = {
+		.start	= 0x00100A80,
+		.end	= 0x00100ABF,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART2),
+		.end	= (NETX_IRQ_UART2),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart2_device = {
+	.name		= "netx-uart",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(netx_uart2_resources),
+	.resource	= netx_uart2_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&netx_eth0_device,
+	&netx_eth1_device,
+	&netx_uart0_device,
+	&netx_uart1_device,
+	&netx_uart2_device,
+};
+
+static void __init nxdb500_init(void)
+{
+	netx_fb_init(&clcd_data, &qvga);
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXDB500, "Hilscher nxdb500")
+	.phys_io	= 0x00100000,
+	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= netx_map_io,
+	.init_irq	= netx_init_irq,
+	.timer		= &netx_timer,
+	.init_machine	= nxdb500_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
new file mode 100644
index 0000000..7e26c42
--- /dev/null
+++ b/arch/arm/mach-netx/nxdkn.c
@@ -0,0 +1,103 @@
+/*
+ * arch/arm/mach-netx/nxdkn.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+
+static struct netxeth_platform_data eth0_platform_data = {
+	.xcno = 0,
+};
+
+static struct platform_device nxdkn_eth0_device = {
+	.name		= "netx-eth",
+	.id		= 0,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth0_platform_data,
+	}
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+	.xcno = 1,
+};
+
+static struct platform_device nxdkn_eth1_device = {
+	.name		= "netx-eth",
+	.id		= 1,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth1_platform_data,
+	}
+};
+
+static struct resource netx_uart0_resources[] = {
+	[0] = {
+		.start	= 0x00100A00,
+		.end	= 0x00100A3F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART0),
+		.end	= (NETX_IRQ_UART0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart0_device = {
+	.name		= "netx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_uart0_resources),
+	.resource	= netx_uart0_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&nxdkn_eth0_device,
+	&nxdkn_eth1_device,
+	&netx_uart0_device,
+};
+
+static void __init nxdkn_init(void)
+{
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXDKN, "Hilscher nxdkn")
+	.phys_io	= 0x00100000,
+	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= netx_map_io,
+	.init_irq	= netx_init_irq,
+	.timer		= &netx_timer,
+	.init_machine	= nxdkn_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
new file mode 100644
index 0000000..53e10a9
--- /dev/null
+++ b/arch/arm/mach-netx/nxeb500hmi.c
@@ -0,0 +1,187 @@
+/*
+ * arch/arm/mach-netx/nxeb500hmi.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/plat-ram.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/eth.h>
+
+#include "generic.h"
+#include "fb.h"
+
+static struct clcd_panel qvga = {
+	.mode		= {
+		.name		= "QVGA",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 187617,
+		.left_margin	= 6,
+		.right_margin	= 26,
+		.upper_margin	= 0,
+		.lower_margin	= 6,
+		.hsync_len	= 6,
+		.vsync_len	= 1,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		=  16,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR,
+	.bpp		= 16,
+	.grayscale	= 0,
+};
+
+static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var)
+{
+	var->green.length = 5;
+	var->green.msb_right = 0;
+
+	return clcdfb_check(fb, var);
+}
+
+static int nxeb500hmi_clcd_setup(struct clcd_fb *fb)
+{
+	unsigned int val;
+
+	fb->fb.var.green.length = 5;
+	fb->fb.var.green.msb_right = 0;
+
+	/* enable asic control */
+	val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+	writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+	writel(3, NETX_SYSTEM_IOC_CR);
+
+	/* GPIO 14 is used for display enable on newer boards */
+	writel(9, NETX_GPIO_CFG(14));
+
+	val = readl(NETX_PIO_OUTPIO);
+	writel(val | 1, NETX_PIO_OUTPIO);
+
+	val = readl(NETX_PIO_OEPIO);
+	writel(val | 1, NETX_PIO_OEPIO);
+	return netx_clcd_setup(fb);
+}
+
+static struct clcd_board clcd_data = {
+	.name		= "netX",
+	.check		= nxeb500hmi_check,
+	.decode		= clcdfb_decode,
+	.enable		= netx_clcd_enable,
+	.setup		= nxeb500hmi_clcd_setup,
+	.mmap		= netx_clcd_mmap,
+	.remove		= netx_clcd_remove,
+};
+
+static struct netxeth_platform_data eth0_platform_data = {
+	.xcno = 0,
+};
+
+static struct platform_device netx_eth0_device = {
+	.name		= "netx-eth",
+	.id		= 0,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth0_platform_data,
+	}
+};
+
+static struct netxeth_platform_data eth1_platform_data = {
+	.xcno = 1,
+};
+
+static struct platform_device netx_eth1_device = {
+	.name		= "netx-eth",
+	.id		= 1,
+	.num_resources	= 0,
+	.resource	= NULL,
+	.dev = {
+		.platform_data = &eth1_platform_data,
+	}
+};
+
+static struct resource netx_cf_resources[] = {
+	[0] = {
+		.start	= 0x20000000,
+		.end	= 0x25ffffff,
+		.flags	= IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+	},
+};
+
+static struct platform_device netx_cf_device = {
+	.name		= "netx-cf",
+	.id		= 0,
+	.resource	= netx_cf_resources,
+	.num_resources	= ARRAY_SIZE(netx_cf_resources),
+};
+
+static struct resource netx_uart0_resources[] = {
+	[0] = {
+		.start	= 0x00100A00,
+		.end	= 0x00100A3F,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= (NETX_IRQ_UART0),
+		.end	= (NETX_IRQ_UART0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device netx_uart0_device = {
+	.name		= "netx-uart",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(netx_uart0_resources),
+	.resource	= netx_uart0_resources,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&netx_eth0_device,
+	&netx_eth1_device,
+	&netx_cf_device,
+	&netx_uart0_device,
+};
+
+static void __init nxeb500hmi_init(void)
+{
+	netx_fb_init(&clcd_data, &qvga);
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi")
+	.phys_io	= 0x00100000,
+	.io_pg_offst	= (io_p2v(0x00100000) >> 18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= netx_map_io,
+	.init_irq	= netx_init_irq,
+	.timer		= &netx_timer,
+	.init_machine	= nxeb500hmi_init,
+MACHINE_END
diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c
new file mode 100644
index 0000000..44dea61
--- /dev/null
+++ b/arch/arm/mach-netx/pfifo.c
@@ -0,0 +1,68 @@
+/*
+ * arch/arm/mach-netx/pfifo.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/pfifo.h>
+
+static DEFINE_MUTEX(pfifo_lock);
+
+static unsigned int pfifo_used = 0;
+
+int pfifo_request(unsigned int pfifo_mask)
+{
+	int err = 0;
+	unsigned int val;
+
+	mutex_lock(&pfifo_lock);
+
+	if (pfifo_mask & pfifo_used) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	pfifo_used |= pfifo_mask;
+
+	val = readl(NETX_PFIFO_RESET);
+	writel(val | pfifo_mask, NETX_PFIFO_RESET);
+	writel(val, NETX_PFIFO_RESET);
+
+out:
+	mutex_unlock(&pfifo_lock);
+	return err;
+}
+
+void pfifo_free(unsigned int pfifo_mask)
+{
+	mutex_lock(&pfifo_lock);
+	pfifo_used &= ~pfifo_mask;
+	mutex_unlock(&pfifo_lock);
+}
+
+EXPORT_SYMBOL(pfifo_push);
+EXPORT_SYMBOL(pfifo_pop);
+EXPORT_SYMBOL(pfifo_fill_level);
+EXPORT_SYMBOL(pfifo_empty);
+EXPORT_SYMBOL(pfifo_request);
+EXPORT_SYMBOL(pfifo_free);
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
new file mode 100644
index 0000000..edfbdf4
--- /dev/null
+++ b/arch/arm/mach-netx/time.c
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-netx/time.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/time.h>
+#include <asm/arch/netx-regs.h>
+
+/*
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long netx_gettimeoffset(void)
+{
+	return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100;
+}
+
+/*
+ * IRQ handler for the timer
+ */
+static irqreturn_t
+netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	write_seqlock(&xtime_lock);
+
+	timer_tick(regs);
+	write_sequnlock(&xtime_lock);
+
+	/* acknowledge interrupt */
+	writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
+
+	return IRQ_HANDLED;
+}
+
+
+static struct irqaction netx_timer_irq = {
+	.name           = "NetX Timer Tick",
+	.flags          = SA_INTERRUPT | SA_TIMER,
+	.handler        = netx_timer_interrupt,
+};
+
+/*
+ * Set up timer interrupt
+ */
+static void __init netx_timer_init(void)
+{
+	/* disable timer initially */
+	writel(0, NETX_GPIO_COUNTER_CTRL(0));
+
+	/* Reset the timer value to zero */
+	writel(0, NETX_GPIO_COUNTER_CURRENT(0));
+
+	writel(LATCH, NETX_GPIO_COUNTER_MAX(0));
+
+	/* acknowledge interrupt */
+	writel(COUNTER_BIT(0), NETX_GPIO_IRQ);
+
+	/* Enable the interrupt in the specific timer register and start timer */
+	writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE);
+	writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN,
+		NETX_GPIO_COUNTER_CTRL(0));
+
+	setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq);
+}
+
+struct sys_timer netx_timer = {
+	.init           = netx_timer_init,
+	.offset         = netx_gettimeoffset,
+};
diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c
new file mode 100644
index 0000000..172a058
--- /dev/null
+++ b/arch/arm/mach-netx/xc.c
@@ -0,0 +1,255 @@
+/*
+ * arch/arm/mach-netx/xc.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/mutex.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+
+#include <asm/arch/xc.h>
+
+static DEFINE_MUTEX(xc_lock);
+
+static int xc_in_use = 0;
+
+struct fw_desc {
+	unsigned int ofs;
+	unsigned int size;
+	unsigned int patch_ofs;
+	unsigned int patch_entries;
+};
+
+struct fw_header {
+	unsigned int magic;
+	unsigned int type;
+	unsigned int version;
+	unsigned int reserved[5];
+	struct fw_desc fw_desc[3];
+} __attribute__ ((packed));
+
+int xc_stop(struct xc *x)
+{
+	writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
+	writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
+	writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
+	return 0;
+}
+
+int xc_start(struct xc *x)
+{
+	writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS);
+	writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS);
+	writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS);
+	return 0;
+}
+
+int xc_running(struct xc *x)
+{
+	return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC)
+	    || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC)
+	    || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ?
+		0 : 1;
+}
+
+int xc_reset(struct xc *x)
+{
+	writel(0, x->xpec_base + NETX_XPEC_PC_OFS);
+	return 0;
+}
+
+static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size)
+{
+	if (adr >= NETX_PA_XMAC(x->no) &&
+	    adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE)
+		return 0;
+
+	if (adr >= NETX_PA_XPEC(x->no) &&
+	    adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE)
+		return 0;
+
+	dev_err(x->dev, "Illegal pointer in firmware found. aborting\n");
+
+	return -1;
+}
+
+static int xc_patch(struct xc *x, void *patch, int count)
+{
+	unsigned int val, adr;
+	unsigned int *data = patch;
+
+	int i;
+	for (i = 0; i < count; i++) {
+		adr = *data++;
+		val = *data++;
+		if (xc_check_ptr(x, adr, 4) < 0)
+			return -EINVAL;
+
+		writel(val, (void __iomem *)io_p2v(adr));
+	}
+	return 0;
+}
+
+int xc_request_firmware(struct xc *x)
+{
+	int ret;
+	char name[16];
+	const struct firmware *fw;
+	struct fw_header *head;
+	unsigned int size;
+	int i;
+	void *src;
+	unsigned long dst;
+
+	sprintf(name, "xc%d.bin", x->no);
+
+	ret = request_firmware(&fw, name, x->dev);
+
+	if (ret < 0) {
+		dev_err(x->dev, "request_firmware failed\n");
+		return ret;
+	}
+
+	head = (struct fw_header *)fw->data;
+	if (head->magic != 0x4e657458) {
+		if (head->magic == 0x5874654e) {
+			dev_err(x->dev,
+			    "firmware magic is 'XteN'. Endianess problems?\n");
+			ret = -ENODEV;
+			goto exit_release_firmware;
+		}
+		dev_err(x->dev, "unrecognized firmware magic 0x%08x\n",
+			head->magic);
+		ret = -ENODEV;
+		goto exit_release_firmware;
+	}
+
+	x->type = head->type;
+	x->version = head->version;
+
+	ret = -EINVAL;
+
+	for (i = 0; i < 3; i++) {
+		src = fw->data + head->fw_desc[i].ofs;
+		dst = *(unsigned int *)src;
+		src += sizeof (unsigned int);
+		size = head->fw_desc[i].size - sizeof (unsigned int);
+
+		if (xc_check_ptr(x, dst, size))
+			goto exit_release_firmware;
+
+		memcpy((void *)io_p2v(dst), src, size);
+
+		src = fw->data + head->fw_desc[i].patch_ofs;
+		size = head->fw_desc[i].patch_entries;
+		ret = xc_patch(x, src, size);
+		if (ret < 0)
+			goto exit_release_firmware;
+	}
+
+	ret = 0;
+
+      exit_release_firmware:
+	release_firmware(fw);
+
+	return ret;
+}
+
+struct xc *request_xc(int xcno, struct device *dev)
+{
+	struct xc *x = NULL;
+
+	mutex_lock(&xc_lock);
+
+	if (xcno > 3)
+		goto exit;
+	if (xc_in_use & (1 << xcno))
+		goto exit;
+
+	x = kmalloc(sizeof (struct xc), GFP_KERNEL);
+	if (!x)
+		goto exit;
+
+	if (!request_mem_region
+	    (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, dev->kobj.name))
+		goto exit_free;
+
+	if (!request_mem_region
+	    (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, dev->kobj.name))
+		goto exit_release_1;
+
+	if (!request_mem_region
+	    (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, dev->kobj.name))
+		goto exit_release_2;
+
+	x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno));
+	x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno));
+	x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+	if (!x->sram_base)
+		goto exit_release_3;
+
+	x->irq = NETX_IRQ_XPEC(xcno);
+
+	x->no = xcno;
+	x->dev = dev;
+
+	xc_in_use |= (1 << xcno);
+
+	goto exit;
+
+      exit_release_3:
+	release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+      exit_release_2:
+	release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
+      exit_release_1:
+	release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
+      exit_free:
+	kfree(x);
+	x = NULL;
+      exit:
+	mutex_unlock(&xc_lock);
+	return x;
+}
+
+void free_xc(struct xc *x)
+{
+	int xcno = x->no;
+
+	mutex_lock(&xc_lock);
+
+	iounmap(x->sram_base);
+	release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE);
+	release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE);
+	release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE);
+	xc_in_use &= ~(1 << x->no);
+	kfree(x);
+
+	mutex_unlock(&xc_lock);
+}
+
+EXPORT_SYMBOL(free_xc);
+EXPORT_SYMBOL(request_xc);
+EXPORT_SYMBOL(xc_request_firmware);
+EXPORT_SYMBOL(xc_reset);
+EXPORT_SYMBOL(xc_running);
+EXPORT_SYMBOL(xc_start);
+EXPORT_SYMBOL(xc_stop);
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 6178f04..73df32a 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -84,6 +84,15 @@
 	{ OMAP_TAG_UART,	&ams_delta_uart_config },
 };
 
+static struct platform_device ams_delta_led_device = {
+	.name	= "ams-delta-led",
+	.id	= -1
+};
+
+static struct platform_device *ams_delta_devices[] __initdata = {
+	&ams_delta_led_device,
+};
+
 static void __init ams_delta_init(void)
 {
 	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
@@ -94,6 +103,8 @@
 
 	/* Clear latch2 (NAND, LCD, modem enable) */
 	ams_delta_latch2_write(~0, 0);
+
+	platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 }
 
 static void __init ams_delta_map_io(void)
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
new file mode 100644
index 0000000..b457ca0
--- /dev/null
+++ b/arch/arm/mach-pnx4008/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y			:= core.o irq.o time.o clock.o gpio.o serial.o dma.o
+obj-m			:=
+obj-n			:=
+obj-			:=
+
+# Power Management
+obj-$(CONFIG_PM) += pm.o sleep.o
+
diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot
new file mode 100644
index 0000000..44c7117
--- /dev/null
+++ b/arch/arm/mach-pnx4008/Makefile.boot
@@ -0,0 +1,4 @@
+   zreladdr-y		:= 0x80008000
+params_phys-y		:= 0x80000100
+initrd_phys-y		:= 0x80800000
+
diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c
new file mode 100644
index 0000000..f582ed2
--- /dev/null
+++ b/arch/arm/mach-pnx4008/clock.c
@@ -0,0 +1,983 @@
+/*
+ * arch/arm/mach-pnx4008/clock.c
+ *
+ * Clock control driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ * Generic clock management functions are partially based on:
+ *  linux/arch/arm/mach-omap/clock.c
+ *
+ * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+#include <asm/semaphore.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+#include "clock.h"
+
+/*forward declaration*/
+static struct clk per_ck;
+static struct clk hclk_ck;
+static struct clk ck_1MHz;
+static struct clk ck_13MHz;
+static struct clk ck_pll1;
+static int local_set_rate(struct clk *clk, u32 rate);
+
+static inline void clock_lock(void)
+{
+	local_irq_disable();
+}
+
+static inline void clock_unlock(void)
+{
+	local_irq_enable();
+}
+
+static void propagate_rate(struct clk *clk)
+{
+	struct clk *tmp_clk;
+
+	tmp_clk = clk;
+	while (tmp_clk->propagate_next) {
+		tmp_clk = tmp_clk->propagate_next;
+		local_set_rate(tmp_clk, tmp_clk->user_rate);
+	}
+}
+
+static inline void clk_reg_disable(struct clk *clk)
+{
+	if (clk->enable_reg)
+		__raw_writel(__raw_readl(clk->enable_reg) &
+			     ~(1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_enable(struct clk *clk)
+{
+	if (clk->enable_reg)
+		__raw_writel(__raw_readl(clk->enable_reg) |
+			     (1 << clk->enable_shift), clk->enable_reg);
+}
+
+static inline void clk_reg_disable1(struct clk *clk)
+{
+	if (clk->enable_reg1)
+		__raw_writel(__raw_readl(clk->enable_reg1) &
+			     ~(1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static inline void clk_reg_enable1(struct clk *clk)
+{
+	if (clk->enable_reg1)
+		__raw_writel(__raw_readl(clk->enable_reg1) |
+			     (1 << clk->enable_shift1), clk->enable_reg1);
+}
+
+static int clk_wait_for_pll_lock(struct clk *clk)
+{
+	int i;
+	i = 0;
+	while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ;	/*wait for PLL to lock */
+
+	if (!(__raw_readl(clk->scale_reg) & 1)) {
+		printk(KERN_ERR
+		       "%s ERROR: failed to lock, scale reg data: %x\n",
+		       clk->name, __raw_readl(clk->scale_reg));
+		return -1;
+	}
+	return 0;
+}
+
+static int switch_to_dirty_13mhz(struct clk *clk)
+{
+	int i;
+	int ret;
+	u32 tmp_reg;
+
+	ret = 0;
+
+	if (!clk->rate)
+		clk_reg_enable1(clk);
+
+	tmp_reg = __raw_readl(clk->parent_switch_reg);
+	/*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */
+	if (!(tmp_reg & 1)) {
+		tmp_reg |= (1 << 1);	/* Trigger switch to 13'MHz (dirty) clock */
+		__raw_writel(tmp_reg, clk->parent_switch_reg);
+		i = 0;
+		while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ;	/*wait for 13'MHz selection status */
+
+		if (!(__raw_readl(clk->parent_switch_reg) & 1)) {
+			printk(KERN_ERR
+			       "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n",
+			       clk->name, __raw_readl(clk->parent_switch_reg));
+			ret = -1;
+		}
+	}
+
+	if (!clk->rate)
+		clk_reg_disable1(clk);
+
+	return ret;
+}
+
+static int switch_to_clean_13mhz(struct clk *clk)
+{
+	int i;
+	int ret;
+	u32 tmp_reg;
+
+	ret = 0;
+
+	if (!clk->rate)
+		clk_reg_enable1(clk);
+
+	tmp_reg = __raw_readl(clk->parent_switch_reg);
+	/*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */
+	if (tmp_reg & 1) {
+		tmp_reg &= ~(1 << 1);	/* Trigger switch to 13MHz (clean) clock */
+		__raw_writel(tmp_reg, clk->parent_switch_reg);
+		i = 0;
+		while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ;	/*wait for 13MHz selection status */
+
+		if (__raw_readl(clk->parent_switch_reg) & 1) {
+			printk(KERN_ERR
+			       "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n",
+			       clk->name, __raw_readl(clk->parent_switch_reg));
+			ret = -1;
+		}
+	}
+
+	if (!clk->rate)
+		clk_reg_disable1(clk);
+
+	return ret;
+}
+
+static int set_13MHz_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -EINVAL;
+
+	if (parent == &ck_13MHz)
+		ret = switch_to_clean_13mhz(clk);
+	else if (parent == &ck_pll1)
+		ret = switch_to_dirty_13mhz(clk);
+
+	return ret;
+}
+
+#define PLL160_MIN_FCCO 156000
+#define PLL160_MAX_FCCO 320000
+
+/*
+ * Calculate pll160 settings.
+ * Possible input: up to 320MHz with step of clk->parent->rate.
+ * In PNX4008 parent rate for pll160s may be either 1 or 13MHz.
+ * Ignored paths: "feedback" (bit 13 set), "div-by-N".
+ * Setting ARM PLL4 rate to 0 will put CPU into direct run mode.
+ * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input.
+ * Please refer to PNX4008 IC manual for details.
+ */
+
+static int pll160_set_rate(struct clk *clk, u32 rate)
+{
+	u32 tmp_reg, tmp_m, tmp_2p, i;
+	u32 parent_rate;
+	int ret = -EINVAL;
+
+	parent_rate = clk->parent->rate;
+
+	if (!parent_rate)
+		goto out;
+
+	/* set direct run for ARM or disable output for others  */
+	clk_reg_disable(clk);
+
+	/* disable source input as well (ignored for ARM) */
+	clk_reg_disable1(clk);
+
+	tmp_reg = __raw_readl(clk->scale_reg);
+	tmp_reg &= ~0x1ffff;	/*clear all settings, power down */
+	__raw_writel(tmp_reg, clk->scale_reg);
+
+	rate -= rate % parent_rate;	/*round down the input */
+
+	if (rate > PLL160_MAX_FCCO)
+		rate = PLL160_MAX_FCCO;
+
+	if (!rate) {
+		clk->rate = 0;
+		ret = 0;
+		goto out;
+	}
+
+	clk_reg_enable1(clk);
+	tmp_reg = __raw_readl(clk->scale_reg);
+
+	if (rate == parent_rate) {
+		/*enter direct bypass mode */
+		tmp_reg |= ((1 << 14) | (1 << 15));
+		__raw_writel(tmp_reg, clk->scale_reg);
+		clk->rate = parent_rate;
+		clk_reg_enable(clk);
+		ret = 0;
+		goto out;
+	}
+
+	i = 0;
+	for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) {
+		if (rate * tmp_2p >= PLL160_MIN_FCCO)
+			break;
+		i++;
+	}
+
+	if (tmp_2p > 1)
+		tmp_reg |= ((i - 1) << 11);
+	else
+		tmp_reg |= (1 << 14);	/*direct mode, no divide */
+
+	tmp_m = rate * tmp_2p;
+	tmp_m /= parent_rate;
+
+	tmp_reg |= (tmp_m - 1) << 1;	/*calculate M */
+	tmp_reg |= (1 << 16);	/*power up PLL */
+	__raw_writel(tmp_reg, clk->scale_reg);
+
+	if (clk_wait_for_pll_lock(clk) < 0) {
+		clk_reg_disable(clk);
+		clk_reg_disable1(clk);
+
+		tmp_reg = __raw_readl(clk->scale_reg);
+		tmp_reg &= ~0x1ffff;	/*clear all settings, power down */
+		__raw_writel(tmp_reg, clk->scale_reg);
+		clk->rate = 0;
+		ret = -EFAULT;
+		goto out;
+	}
+
+	clk->rate = (tmp_m * parent_rate) / tmp_2p;
+
+	if (clk->flags & RATE_PROPAGATES)
+		propagate_rate(clk);
+
+	clk_reg_enable(clk);
+	ret = 0;
+
+out:
+	return ret;
+}
+
+/*configure PER_CLK*/
+static int per_clk_set_rate(struct clk *clk, u32 rate)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(clk->scale_reg);
+	tmp &= ~(0x1f << 2);
+	tmp |= ((clk->parent->rate / clk->rate) - 1) << 2;
+	__raw_writel(tmp, clk->scale_reg);
+	clk->rate = rate;
+	return 0;
+}
+
+/*configure HCLK*/
+static int hclk_set_rate(struct clk *clk, u32 rate)
+{
+	u32 tmp;
+	tmp = __raw_readl(clk->scale_reg);
+	tmp = tmp & ~0x3;
+	switch (rate) {
+	case 1:
+		break;
+	case 2:
+		tmp |= 1;
+		break;
+	case 4:
+		tmp |= 2;
+		break;
+	}
+
+	__raw_writel(tmp, clk->scale_reg);
+	clk->rate = rate;
+	return 0;
+}
+
+static u32 hclk_round_rate(struct clk *clk, u32 rate)
+{
+	switch (rate) {
+	case 1:
+	case 4:
+		return rate;
+	}
+	return 2;
+}
+
+static u32 per_clk_round_rate(struct clk *clk, u32 rate)
+{
+	return CLK_RATE_13MHZ;
+}
+
+static int on_off_set_rate(struct clk *clk, u32 rate)
+{
+	if (rate) {
+		clk_reg_enable(clk);
+		clk->rate = 1;
+	} else {
+		clk_reg_disable(clk);
+		clk->rate = 0;
+	}
+	return 0;
+}
+
+static int on_off_inv_set_rate(struct clk *clk, u32 rate)
+{
+	if (rate) {
+		clk_reg_disable(clk);	/*enable bit is inverted */
+		clk->rate = 1;
+	} else {
+		clk_reg_enable(clk);
+		clk->rate = 0;
+	}
+	return 0;
+}
+
+static u32 on_off_round_rate(struct clk *clk, u32 rate)
+{
+	return (rate ? 1 : 0);
+}
+
+static u32 pll4_round_rate(struct clk *clk, u32 rate)
+{
+	if (rate > CLK_RATE_208MHZ)
+		rate = CLK_RATE_208MHZ;
+	if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1)
+		rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ;
+	return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ)));
+}
+
+static u32 pll3_round_rate(struct clk *clk, u32 rate)
+{
+	if (rate > CLK_RATE_208MHZ)
+		rate = CLK_RATE_208MHZ;
+	return (rate - rate % CLK_RATE_13MHZ);
+}
+
+static u32 pll5_round_rate(struct clk *clk, u32 rate)
+{
+	return (rate ? CLK_RATE_48MHZ : 0);
+}
+
+static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate)
+{
+	return (rate ? CLK_RATE_13MHZ : 0);
+}
+
+static int ck_13MHz_set_rate(struct clk *clk, u32 rate)
+{
+	if (rate) {
+		clk_reg_disable(clk);	/*enable bit is inverted */
+		udelay(500);
+		clk->rate = CLK_RATE_13MHZ;
+		ck_1MHz.rate = CLK_RATE_1MHZ;
+	} else {
+		clk_reg_enable(clk);
+		clk->rate = 0;
+		ck_1MHz.rate = 0;
+	}
+	return 0;
+}
+
+static int pll1_set_rate(struct clk *clk, u32 rate)
+{
+#if 0 /* doesn't work on some boards, probably a HW BUG */
+	if (rate) {
+		clk_reg_disable(clk);	/*enable bit is inverted */
+		if (!clk_wait_for_pll_lock(clk)) {
+			clk->rate = CLK_RATE_13MHZ;
+		} else {
+			clk_reg_enable(clk);
+			clk->rate = 0;
+		}
+
+	} else {
+		clk_reg_enable(clk);
+		clk->rate = 0;
+	}
+#endif
+	return 0;
+}
+
+/* Clock sources */
+
+static struct clk osc_13MHz = {
+	.name = "osc_13MHz",
+	.flags = FIXED_RATE,
+	.rate = CLK_RATE_13MHZ,
+};
+
+static struct clk ck_13MHz = {
+	.name = "ck_13MHz",
+	.parent = &osc_13MHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &ck_13MHz_round_rate,
+	.set_rate = &ck_13MHz_set_rate,
+	.enable_reg = OSC13CTRL_REG,
+	.enable_shift = 0,
+	.rate = CLK_RATE_13MHZ,
+};
+
+static struct clk osc_32KHz = {
+	.name = "osc_32KHz",
+	.flags = FIXED_RATE,
+	.rate = CLK_RATE_32KHZ,
+};
+
+/*attached to PLL5*/
+static struct clk ck_1MHz = {
+	.name = "ck_1MHz",
+	.flags = FIXED_RATE | PARENT_SET_RATE,
+	.parent = &ck_13MHz,
+};
+
+/* PLL1 (397) - provides 13' MHz clock */
+static struct clk ck_pll1 = {
+	.name = "ck_pll1",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &ck_13MHz_round_rate,
+	.set_rate = &pll1_set_rate,
+	.enable_reg = PLLCTRL_REG,
+	.enable_shift = 1,
+	.scale_reg = PLLCTRL_REG,
+	.rate = CLK_RATE_13MHZ,
+};
+
+/* CPU/Bus PLL */
+static struct clk ck_pll4 = {
+	.name = "ck_pll4",
+	.parent = &ck_pll1,
+	.flags = RATE_PROPAGATES | NEEDS_INITIALIZATION,
+	.propagate_next = &per_ck,
+	.round_rate = &pll4_round_rate,
+	.set_rate = &pll160_set_rate,
+	.rate = CLK_RATE_208MHZ,
+	.scale_reg = HCLKPLLCTRL_REG,
+	.enable_reg = PWRCTRL_REG,
+	.enable_shift = 2,
+	.parent_switch_reg = SYSCLKCTRL_REG,
+	.set_parent = &set_13MHz_parent,
+};
+
+/* USB PLL */
+static struct clk ck_pll5 = {
+	.name = "ck_pll5",
+	.parent = &ck_1MHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &pll5_round_rate,
+	.set_rate = &pll160_set_rate,
+	.scale_reg = USBCTRL_REG,
+	.enable_reg = USBCTRL_REG,
+	.enable_shift = 18,
+	.enable_reg1 = USBCTRL_REG,
+	.enable_shift1 = 17,
+};
+
+/* XPERTTeak DSP PLL */
+static struct clk ck_pll3 = {
+	.name = "ck_pll3",
+	.parent = &ck_pll1,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &pll3_round_rate,
+	.set_rate = &pll160_set_rate,
+	.scale_reg = DSPPLLCTRL_REG,
+	.enable_reg = DSPCLKCTRL_REG,
+	.enable_shift = 3,
+	.enable_reg1 = DSPCLKCTRL_REG,
+	.enable_shift1 = 2,
+	.parent_switch_reg = DSPCLKCTRL_REG,
+	.set_parent = &set_13MHz_parent,
+};
+
+static struct clk hclk_ck = {
+	.name = "hclk_ck",
+	.parent = &ck_pll4,
+	.flags = PARENT_SET_RATE,
+	.set_rate = &hclk_set_rate,
+	.round_rate = &hclk_round_rate,
+	.scale_reg = HCLKDIVCTRL_REG,
+	.rate = 2,
+	.user_rate = 2,
+};
+
+static struct clk per_ck = {
+	.name = "per_ck",
+	.parent = &ck_pll4,
+	.flags = FIXED_RATE,
+	.propagate_next = &hclk_ck,
+	.set_rate = &per_clk_set_rate,
+	.round_rate = &per_clk_round_rate,
+	.scale_reg = HCLKDIVCTRL_REG,
+	.rate = CLK_RATE_13MHZ,
+	.user_rate = CLK_RATE_13MHZ,
+};
+
+static struct clk m2hclk_ck = {
+	.name = "m2hclk_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_inv_set_rate,
+	.rate = 1,
+	.enable_shift = 6,
+	.enable_reg = PWRCTRL_REG,
+};
+
+static struct clk vfp9_ck = {
+	.name = "vfp9_ck",
+	.parent = &ck_pll4,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.rate = 1,
+	.enable_shift = 4,
+	.enable_reg = VFP9CLKCTRL_REG,
+};
+
+static struct clk keyscan_ck = {
+	.name = "keyscan_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = KEYCLKCTRL_REG,
+};
+
+static struct clk touch_ck = {
+	.name = "touch_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = TSCLKCTRL_REG,
+};
+
+static struct clk pwm1_ck = {
+	.name = "pwm1_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk pwm2_ck = {
+	.name = "pwm2_ck",
+	.parent = &osc_32KHz,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 2,
+	.enable_reg = PWMCLKCTRL_REG,
+};
+
+static struct clk jpeg_ck = {
+	.name = "jpeg_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = JPEGCLKCTRL_REG,
+};
+
+static struct clk ms_ck = {
+	.name = "ms_ck",
+	.parent = &ck_pll4,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 5,
+	.enable_reg = MSCTRL_REG,
+};
+
+static struct clk dum_ck = {
+	.name = "dum_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = DUMCLKCTRL_REG,
+};
+
+static struct clk flash_ck = {
+	.name = "flash_ck",
+	.parent = &hclk_ck,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 1,	/* Only MLC clock supported */
+	.enable_reg = FLASHCLKCTRL_REG,
+};
+
+static struct clk i2c0_ck = {
+	.name = "i2c0_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c1_ck = {
+	.name = "i2c1_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 1,
+	.enable_reg = I2CCLKCTRL_REG,
+};
+
+static struct clk i2c2_ck = {
+	.name = "i2c2_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 2,
+	.enable_reg = USB_OTG_CLKCTRL_REG,
+};
+
+static struct clk spi0_ck = {
+	.name = "spi0_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = SPICTRL_REG,
+};
+
+static struct clk spi1_ck = {
+	.name = "spi1_ck",
+	.parent = &hclk_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 4,
+	.enable_reg = SPICTRL_REG,
+};
+
+static struct clk dma_ck = {
+	.name = "dma_ck",
+	.parent = &hclk_ck,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 0,
+	.enable_reg = DMACLKCTRL_REG,
+};
+
+static struct clk uart3_ck = {
+	.name = "uart3_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.rate = 1,
+	.enable_shift = 0,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart4_ck = {
+	.name = "uart4_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 1,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart5_ck = {
+	.name = "uart5_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.rate = 1,
+	.enable_shift = 2,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+static struct clk uart6_ck = {
+	.name = "uart6_ck",
+	.parent = &per_ck,
+	.flags = NEEDS_INITIALIZATION,
+	.round_rate = &on_off_round_rate,
+	.set_rate = &on_off_set_rate,
+	.enable_shift = 3,
+	.enable_reg = UARTCLKCTRL_REG,
+};
+
+/* These clocks are visible outside this module
+ * and can be initialized
+ */
+static struct clk *onchip_clks[] = {
+	&ck_13MHz,
+	&ck_pll1,
+	&ck_pll4,
+	&ck_pll5,
+	&ck_pll3,
+	&vfp9_ck,
+	&m2hclk_ck,
+	&hclk_ck,
+	&dma_ck,
+	&flash_ck,
+	&dum_ck,
+	&keyscan_ck,
+	&pwm1_ck,
+	&pwm2_ck,
+	&jpeg_ck,
+	&ms_ck,
+	&touch_ck,
+	&i2c0_ck,
+	&i2c1_ck,
+	&i2c2_ck,
+	&spi0_ck,
+	&spi1_ck,
+	&uart3_ck,
+	&uart4_ck,
+	&uart5_ck,
+	&uart6_ck,
+};
+
+static int local_clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
+	    && clk->user_rate)
+		ret = clk->set_rate(clk, clk->user_rate);
+	return ret;
+}
+
+static void local_clk_disable(struct clk *clk)
+{
+	if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
+		clk->set_rate(clk, 0);
+}
+
+static void local_clk_unuse(struct clk *clk)
+{
+	if (clk->usecount > 0 && !(--clk->usecount)) {
+		local_clk_disable(clk);
+		if (clk->parent)
+			local_clk_unuse(clk->parent);
+	}
+}
+
+static int local_clk_use(struct clk *clk)
+{
+	int ret = 0;
+	if (clk->usecount++ == 0) {
+		if (clk->parent)
+			ret = local_clk_use(clk->parent);
+
+		if (ret != 0) {
+			clk->usecount--;
+			goto out;
+		}
+
+		ret = local_clk_enable(clk);
+
+		if (ret != 0 && clk->parent) {
+			local_clk_unuse(clk->parent);
+			clk->usecount--;
+		}
+	}
+out:
+	return ret;
+}
+
+static int local_set_rate(struct clk *clk, u32 rate)
+{
+	int ret = -EINVAL;
+	if (clk->set_rate) {
+
+		if (clk->user_rate == clk->rate && clk->parent->rate) {
+			/* if clock enabled or rate not set */
+			clk->user_rate = clk->round_rate(clk, rate);
+			ret = clk->set_rate(clk, clk->user_rate);
+		} else
+			clk->user_rate = clk->round_rate(clk, rate);
+		ret = 0;
+	}
+	return ret;
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EINVAL;
+
+	if (clk->flags & FIXED_RATE)
+		goto out;
+
+	clock_lock();
+	if ((clk->flags & PARENT_SET_RATE) && clk->parent) {
+
+		clk->user_rate = clk->round_rate(clk, rate);
+		/* parent clock needs to be refreshed
+		   for the setting to take effect */
+	} else {
+		ret = local_set_rate(clk, rate);
+	}
+	ret = 0;
+	clock_unlock();
+
+out:
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_set_rate);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *clk = ERR_PTR(-ENOENT);
+	struct clk **clkp;
+
+	clock_lock();
+	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+	     clkp++) {
+		if (strcmp(id, (*clkp)->name) == 0
+		    && try_module_get((*clkp)->owner)) {
+			clk = (*clkp);
+			break;
+		}
+	}
+	clock_unlock();
+
+	return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+	clock_lock();
+	if (clk && !IS_ERR(clk))
+		module_put(clk->owner);
+	clock_unlock();
+}
+EXPORT_SYMBOL(clk_put);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long ret;
+	clock_lock();
+	ret = clk->rate;
+	clock_unlock();
+	return ret;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+int clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	clock_lock();
+	ret = local_clk_use(clk);
+	clock_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	clock_lock();
+	local_clk_unuse(clk);
+	clock_unlock();
+}
+
+EXPORT_SYMBOL(clk_disable);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	long ret;
+	clock_lock();
+	if (clk->round_rate)
+		ret = clk->round_rate(clk, rate);
+	else
+		ret = clk->rate;
+	clock_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = -ENODEV;
+	if (!clk->set_parent)
+		goto out;
+
+	clock_lock();
+	ret = clk->set_parent(clk, parent);
+	if (!ret)
+		clk->parent = parent;
+	clock_unlock();
+
+out:
+	return ret;
+}
+
+EXPORT_SYMBOL(clk_set_parent);
+
+static int __init clk_init(void)
+{
+	struct clk **clkp;
+
+	/* Disable autoclocking, as it doesn't seem to work */
+	__raw_writel(0xff, AUTOCLK_CTRL);
+
+	for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks);
+	     clkp++) {
+		if (((*clkp)->flags & NEEDS_INITIALIZATION)
+		    && ((*clkp)->set_rate)) {
+			(*clkp)->user_rate = (*clkp)->rate;
+			local_set_rate((*clkp), (*clkp)->user_rate);
+			if ((*clkp)->set_parent)
+				(*clkp)->set_parent((*clkp), (*clkp)->parent);
+		}
+		pr_debug("%s: clock %s, rate %ld\n",
+			__FUNCTION__, (*clkp)->name, (*clkp)->rate);
+	}
+
+	local_clk_use(&ck_pll4);
+
+	/* if ck_13MHz is not used, disable it. */
+	if (ck_13MHz.usecount == 0)
+		local_clk_disable(&ck_13MHz);
+
+	/* Disable autoclocking */
+	__raw_writeb(0xff, AUTOCLK_CTRL);
+
+	return 0;
+}
+
+arch_initcall(clk_init);
diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h
new file mode 100644
index 0000000..cd58f37
--- /dev/null
+++ b/arch/arm/mach-pnx4008/clock.h
@@ -0,0 +1,43 @@
+/*
+ * arch/arm/mach-pnx4008/clock.h
+ *
+ * Clock control driver for PNX4008 - internal header file
+ *
+ * Author: Vitaly Wool <source@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ARCH_ARM_PNX4008_CLOCK_H__
+#define __ARCH_ARM_PNX4008_CLOCK_H__
+
+struct clk {
+	struct list_head node;
+	struct module *owner;
+	const char *name;
+	struct clk *parent;
+	struct clk *propagate_next;
+	u32 rate;
+	u32 user_rate;
+	s8 usecount;
+	u32 flags;
+	u32 scale_reg;
+	u8 enable_shift;
+	u32 enable_reg;
+	u8 enable_shift1;
+	u32 enable_reg1;
+	u32 parent_switch_reg;
+	 u32(*round_rate) (struct clk *, u32);
+	int (*set_rate) (struct clk *, u32);
+	int (*set_parent) (struct clk * clk, struct clk * parent);
+};
+
+/* Flags */
+#define RATE_PROPAGATES      (1<<0)
+#define NEEDS_INITIALIZATION (1<<1)
+#define PARENT_SET_RATE      (1<<2)
+#define FIXED_RATE           (1<<3)
+
+#endif
diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c
new file mode 100644
index 0000000..ba91daa
--- /dev/null
+++ b/arch/arm/mach-pnx4008/core.c
@@ -0,0 +1,207 @@
+/*
+ * arch/arm/mach-pnx4008/core.c
+ *
+ * PNX4008 core startup code
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev,
+ * Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/serial_8250.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+
+#include <asm/arch/irq.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/dma.h>
+
+struct resource spipnx_0_resources[] = {
+	{
+		.start = PNX4008_SPI1_BASE,
+		.end = PNX4008_SPI1_BASE + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = PER_SPI1_REC_XMIT,
+		.flags = IORESOURCE_DMA,
+	}, {
+		.start = SPI1_INT,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.flags = 0,
+	},
+};
+
+struct resource spipnx_1_resources[] = {
+	{
+		.start = PNX4008_SPI2_BASE,
+		.end = PNX4008_SPI2_BASE + SZ_4K,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = PER_SPI2_REC_XMIT,
+		.flags = IORESOURCE_DMA,
+	}, {
+		.start = SPI2_INT,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.flags = 0,
+	}
+};
+
+static struct spi_board_info spi_board_info[] __initdata = {
+	{
+		.modalias	= "m25p80",
+		.max_speed_hz	= 1000000,
+		.bus_num	= 1,
+		.chip_select	= 0,
+	},
+};
+
+static struct platform_device spipnx_1 = {
+	.name = "spipnx",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(spipnx_0_resources),
+	.resource = spipnx_0_resources,
+	.dev = {
+		.coherent_dma_mask = 0xFFFFFFFF,
+		},
+};
+
+static struct platform_device spipnx_2 = {
+	.name = "spipnx",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(spipnx_1_resources),
+	.resource = spipnx_1_resources,
+	.dev = {
+		.coherent_dma_mask = 0xFFFFFFFF,
+		},
+};
+
+static struct plat_serial8250_port platform_serial_ports[] = {
+	{
+		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)),
+		.mapbase = (unsigned long)PNX4008_UART5_BASE,
+		.irq = IIR5_INT,
+		.uartclk = PNX4008_UART_CLK,
+		.regshift = 2,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+	},
+	{
+		.membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)),
+		.mapbase = (unsigned long)PNX4008_UART3_BASE,
+		.irq = IIR3_INT,
+		.uartclk = PNX4008_UART_CLK,
+		.regshift = 2,
+		.iotype = UPIO_MEM,
+		.flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST,
+	 },
+	{}
+};
+
+static struct platform_device serial_device = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data = &platform_serial_ports,
+	},
+};
+
+static struct platform_device *devices[] __initdata = {
+	&spipnx_1,
+	&spipnx_2,
+	&serial_device,
+};
+
+
+extern void pnx4008_uart_init(void);
+
+static void __init pnx4008_init(void)
+{
+	/*disable all START interrupt sources,
+	   and clear all START interrupt flags */
+	__raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT));
+	__raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT));
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+	/* Switch on the UART clocks */
+	pnx4008_uart_init();
+}
+
+static struct map_desc pnx4008_io_desc[] __initdata = {
+	{
+		.virtual 	= IO_ADDRESS(PNX4008_IRAM_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_IRAM_BASE),
+		.length		= SZ_64K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_NDF_FLASH_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_NDF_FLASH_BASE),
+		.length		= SZ_1M - SZ_128K,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE),
+		.length		= SZ_128K * 3,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_DMA_CONFIG_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_DMA_CONFIG_BASE),
+		.length		= SZ_1M,
+		.type 		= MT_DEVICE,
+	}, {
+		.virtual 	= IO_ADDRESS(PNX4008_AHB2FAB_BASE),
+		.pfn 		= __phys_to_pfn(PNX4008_AHB2FAB_BASE),
+		.length		= SZ_1M,
+		.type 		= MT_DEVICE,
+	},
+};
+
+void __init pnx4008_map_io(void)
+{
+	iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc));
+}
+
+extern struct sys_timer pnx4008_timer;
+
+MACHINE_START(PNX4008, "Philips PNX4008")
+	/* Maintainer: MontaVista Software Inc. */
+	.phys_io 		= 0x40090000,
+	.io_pg_offst 		= (0xf4090000 >> 18) & 0xfffc,
+	.boot_params		= 0x80000100,
+	.map_io 		= pnx4008_map_io,
+	.init_irq 		= pnx4008_init_irq,
+	.init_machine 		= pnx4008_init,
+	.timer 			= &pnx4008_timer,
+MACHINE_END
diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c
new file mode 100644
index 0000000..981aa9d
--- /dev/null
+++ b/arch/arm/mach-pnx4008/dma.c
@@ -0,0 +1,1109 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/dma.c
+ *
+ *  PNX4008 DMA registration and IRQ dispatching
+ *
+ *  Author:	Vitaly Wool
+ *  Copyright:	MontaVista Software Inc. (c) 2005
+ *
+ *  Based on the code from Nicolas Pitre
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/dma.h>
+#include <asm/dma-mapping.h>
+#include <asm/io.h>
+#include <asm/mach/dma.h>
+#include <asm/arch/clock.h>
+
+static struct dma_channel {
+	char *name;
+	void (*irq_handler) (int, int, void *, struct pt_regs *);
+	void *data;
+	struct pnx4008_dma_ll *ll;
+	u32 ll_dma;
+	void *target_addr;
+	int target_id;
+} dma_channels[MAX_DMA_CHANNELS];
+
+static struct ll_pool {
+	void *vaddr;
+	void *cur;
+	dma_addr_t dma_addr;
+	int count;
+} ll_pool;
+
+static spinlock_t ll_lock = SPIN_LOCK_UNLOCKED;
+
+struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t * ll_dma)
+{
+	struct pnx4008_dma_ll *ll = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ll_lock, flags);
+	if (ll_pool.count > 4) { /* can give one more */
+		ll = *(struct pnx4008_dma_ll **) ll_pool.cur;
+		*ll_dma = ll_pool.dma_addr + ((void *)ll - ll_pool.vaddr);
+		*(void **)ll_pool.cur = **(void ***)ll_pool.cur;
+		memset(ll, 0, sizeof(*ll));
+		ll_pool.count--;
+	}
+	spin_unlock_irqrestore(&ll_lock, flags);
+
+	return ll;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_alloc_ll_entry);
+
+void pnx4008_free_ll_entry(struct pnx4008_dma_ll * ll, dma_addr_t ll_dma)
+{
+	unsigned long flags;
+
+	if (ll) {
+		if ((unsigned long)((long)ll - (long)ll_pool.vaddr) > 0x4000) {
+			printk(KERN_ERR "Trying to free entry not allocated by DMA\n");
+			BUG();
+		}
+
+		if (ll->flags & DMA_BUFFER_ALLOCATED)
+			ll->free(ll->alloc_data);
+
+		spin_lock_irqsave(&ll_lock, flags);
+		*(long *)ll = *(long *)ll_pool.cur;
+		*(long *)ll_pool.cur = (long)ll;
+		ll_pool.count++;
+		spin_unlock_irqrestore(&ll_lock, flags);
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll_entry);
+
+void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll * ll)
+{
+	struct pnx4008_dma_ll *ptr;
+	u32 dma;
+
+	while (ll) {
+		dma = ll->next_dma;
+		ptr = ll->next;
+		pnx4008_free_ll_entry(ll, ll_dma);
+
+		ll_dma = dma;
+		ll = ptr;
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_ll);
+
+static int dma_channels_requested = 0;
+
+static inline void dma_increment_usage(void)
+{
+	if (!dma_channels_requested++) {
+		struct clk *clk = clk_get(0, "dma_ck");
+		if (!IS_ERR(clk)) {
+			clk_set_rate(clk, 1);
+			clk_put(clk);
+		}
+		pnx4008_config_dma(-1, -1, 1);
+	}
+}
+static inline void dma_decrement_usage(void)
+{
+	if (!--dma_channels_requested) {
+		struct clk *clk = clk_get(0, "dma_ck");
+		if (!IS_ERR(clk)) {
+			clk_set_rate(clk, 0);
+			clk_put(clk);
+		}
+		pnx4008_config_dma(-1, -1, 0);
+
+	}
+}
+
+static spinlock_t dma_lock = SPIN_LOCK_UNLOCKED;
+
+static inline void pnx4008_dma_lock(void)
+{
+	spin_lock_irq(&dma_lock);
+}
+
+static inline void pnx4008_dma_unlock(void)
+{
+	spin_unlock_irq(&dma_lock);
+}
+
+#define VALID_CHANNEL(c)	(((c) >= 0) && ((c) < MAX_DMA_CHANNELS))
+
+int pnx4008_request_channel(char *name, int ch,
+			    void (*irq_handler) (int, int, void *,
+						 struct pt_regs *), void *data)
+{
+	int i, found = 0;
+
+	/* basic sanity checks */
+	if (!name || (ch != -1 && !VALID_CHANNEL(ch)))
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+
+	/* try grabbing a DMA channel with the requested priority */
+	for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+		if (!dma_channels[i].name && (ch == -1 || ch == i)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		dma_increment_usage();
+		dma_channels[i].name = name;
+		dma_channels[i].irq_handler = irq_handler;
+		dma_channels[i].data = data;
+		dma_channels[i].ll = NULL;
+		dma_channels[i].ll_dma = 0;
+	} else {
+		printk(KERN_WARNING "No more available DMA channels for %s\n",
+		       name);
+		i = -ENODEV;
+	}
+
+	pnx4008_dma_unlock();
+	return i;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_request_channel);
+
+void pnx4008_free_channel(int ch)
+{
+	if (!dma_channels[ch].name) {
+		printk(KERN_CRIT
+		       "%s: trying to free channel %d which is already freed\n",
+		       __FUNCTION__, ch);
+		return;
+	}
+
+	pnx4008_dma_lock();
+	pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll);
+	dma_channels[ch].ll = NULL;
+	dma_decrement_usage();
+
+	dma_channels[ch].name = NULL;
+	pnx4008_dma_unlock();
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_free_channel);
+
+int pnx4008_config_dma(int ahb_m1_be, int ahb_m2_be, int enable)
+{
+	unsigned long dma_cfg = __raw_readl(DMAC_CONFIG);
+
+	switch (ahb_m1_be) {
+	case 0:
+		dma_cfg &= ~(1 << 1);
+		break;
+	case 1:
+		dma_cfg |= (1 << 1);
+		break;
+	default:
+		break;
+	}
+
+	switch (ahb_m2_be) {
+	case 0:
+		dma_cfg &= ~(1 << 2);
+		break;
+	case 1:
+		dma_cfg |= (1 << 2);
+		break;
+	default:
+		break;
+	}
+
+	switch (enable) {
+	case 0:
+		dma_cfg &= ~(1 << 0);
+		break;
+	case 1:
+		dma_cfg |= (1 << 0);
+		break;
+	default:
+		break;
+	}
+
+	pnx4008_dma_lock();
+	__raw_writel(dma_cfg, DMAC_CONFIG);
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_dma);
+
+int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl * ch_ctrl,
+			     unsigned long *ctrl)
+{
+	int i = 0, dbsize, sbsize, err = 0;
+
+	if (!ctrl || !ch_ctrl) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	*ctrl = 0;
+
+	switch (ch_ctrl->tc_mask) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 31);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+
+	switch (ch_ctrl->cacheable) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 30);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->bufferable) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 29);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->priv_mode) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 28);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->di) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 27);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->si) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 26);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->dest_ahb1) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 25);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->src_ahb1) {
+	case 0:
+		break;
+	case 1:
+		*ctrl |= (1 << 24);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->dwidth) {
+	case WIDTH_BYTE:
+		*ctrl &= ~(7 << 21);
+		break;
+	case WIDTH_HWORD:
+		*ctrl &= ~(7 << 21);
+		*ctrl |= (1 << 21);
+		break;
+	case WIDTH_WORD:
+		*ctrl &= ~(7 << 21);
+		*ctrl |= (2 << 21);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_ctrl->swidth) {
+	case WIDTH_BYTE:
+		*ctrl &= ~(7 << 18);
+		break;
+	case WIDTH_HWORD:
+		*ctrl &= ~(7 << 18);
+		*ctrl |= (1 << 18);
+		break;
+	case WIDTH_WORD:
+		*ctrl &= ~(7 << 18);
+		*ctrl |= (2 << 18);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	dbsize = ch_ctrl->dbsize;
+	while (!(dbsize & 1)) {
+		i++;
+		dbsize >>= 1;
+	}
+	if (ch_ctrl->dbsize != 1 || i > 8 || i == 1) {
+		err = -EINVAL;
+		goto out;
+	} else if (i > 1)
+		i--;
+	*ctrl &= ~(7 << 15);
+	*ctrl |= (i << 15);
+
+	sbsize = ch_ctrl->sbsize;
+	while (!(sbsize & 1)) {
+		i++;
+		sbsize >>= 1;
+	}
+	if (ch_ctrl->sbsize != 1 || i > 8 || i == 1) {
+		err = -EINVAL;
+		goto out;
+	} else if (i > 1)
+		i--;
+	*ctrl &= ~(7 << 12);
+	*ctrl |= (i << 12);
+
+	if (ch_ctrl->tr_size > 0x7ff) {
+		err = -E2BIG;
+		goto out;
+	}
+	*ctrl &= ~0x7ff;
+	*ctrl |= ch_ctrl->tr_size & 0x7ff;
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_control);
+
+int pnx4008_dma_parse_control(unsigned long ctrl,
+			      struct pnx4008_dma_ch_ctrl * ch_ctrl)
+{
+	int err = 0;
+
+	if (!ch_ctrl) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	ch_ctrl->tr_size = ctrl & 0x7ff;
+	ctrl >>= 12;
+
+	ch_ctrl->sbsize = 1 << (ctrl & 7);
+	if (ch_ctrl->sbsize > 1)
+		ch_ctrl->sbsize <<= 1;
+	ctrl >>= 3;
+
+	ch_ctrl->dbsize = 1 << (ctrl & 7);
+	if (ch_ctrl->dbsize > 1)
+		ch_ctrl->dbsize <<= 1;
+	ctrl >>= 3;
+
+	switch (ctrl & 7) {
+	case 0:
+		ch_ctrl->swidth = WIDTH_BYTE;
+		break;
+	case 1:
+		ch_ctrl->swidth = WIDTH_HWORD;
+		break;
+	case 2:
+		ch_ctrl->swidth = WIDTH_WORD;
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	ctrl >>= 3;
+
+	switch (ctrl & 7) {
+	case 0:
+		ch_ctrl->dwidth = WIDTH_BYTE;
+		break;
+	case 1:
+		ch_ctrl->dwidth = WIDTH_HWORD;
+		break;
+	case 2:
+		ch_ctrl->dwidth = WIDTH_WORD;
+		break;
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	ctrl >>= 3;
+
+	ch_ctrl->src_ahb1 = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->dest_ahb1 = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->si = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->di = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->priv_mode = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->bufferable = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->cacheable = ctrl & 1;
+	ctrl >>= 1;
+
+	ch_ctrl->tc_mask = ctrl & 1;
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_control);
+
+int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config * ch_cfg,
+			    unsigned long *cfg)
+{
+	int err = 0;
+
+	if (!cfg || !ch_cfg) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	*cfg = 0;
+
+	switch (ch_cfg->halt) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 18);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->active) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 17);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->lock) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 16);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->itc) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 15);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->ie) {
+	case 0:
+		break;
+	case 1:
+		*cfg |= (1 << 14);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	switch (ch_cfg->flow_cntrl) {
+	case FC_MEM2MEM_DMA:
+		*cfg &= ~(7 << 11);
+		break;
+	case FC_MEM2PER_DMA:
+		*cfg &= ~(7 << 11);
+		*cfg |= (1 << 11);
+		break;
+	case FC_PER2MEM_DMA:
+		*cfg &= ~(7 << 11);
+		*cfg |= (2 << 11);
+		break;
+	case FC_PER2PER_DMA:
+		*cfg &= ~(7 << 11);
+		*cfg |= (3 << 11);
+		break;
+	case FC_PER2PER_DPER:
+		*cfg &= ~(7 << 11);
+		*cfg |= (4 << 11);
+		break;
+	case FC_MEM2PER_PER:
+		*cfg &= ~(7 << 11);
+		*cfg |= (5 << 11);
+		break;
+	case FC_PER2MEM_PER:
+		*cfg &= ~(7 << 11);
+		*cfg |= (6 << 11);
+		break;
+	case FC_PER2PER_SPER:
+		*cfg |= (7 << 11);
+		break;
+
+	default:
+		err = -EINVAL;
+		goto out;
+	}
+	*cfg &= ~(0x1f << 6);
+	*cfg |= ((ch_cfg->dest_per & 0x1f) << 6);
+
+	*cfg &= ~(0x1f << 1);
+	*cfg |= ((ch_cfg->src_per & 0x1f) << 1);
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_pack_config);
+
+int pnx4008_dma_parse_config(unsigned long cfg,
+			     struct pnx4008_dma_ch_config * ch_cfg)
+{
+	int err = 0;
+
+	if (!ch_cfg) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	cfg >>= 1;
+
+	ch_cfg->src_per = cfg & 0x1f;
+	cfg >>= 5;
+
+	ch_cfg->dest_per = cfg & 0x1f;
+	cfg >>= 5;
+
+	switch (cfg & 7) {
+	case 0:
+		ch_cfg->flow_cntrl = FC_MEM2MEM_DMA;
+		break;
+	case 1:
+		ch_cfg->flow_cntrl = FC_MEM2PER_DMA;
+		break;
+	case 2:
+		ch_cfg->flow_cntrl = FC_PER2MEM_DMA;
+		break;
+	case 3:
+		ch_cfg->flow_cntrl = FC_PER2PER_DMA;
+		break;
+	case 4:
+		ch_cfg->flow_cntrl = FC_PER2PER_DPER;
+		break;
+	case 5:
+		ch_cfg->flow_cntrl = FC_MEM2PER_PER;
+		break;
+	case 6:
+		ch_cfg->flow_cntrl = FC_PER2MEM_PER;
+		break;
+	case 7:
+		ch_cfg->flow_cntrl = FC_PER2PER_SPER;
+	}
+	cfg >>= 3;
+
+	ch_cfg->ie = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->itc = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->lock = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->active = cfg & 1;
+	cfg >>= 1;
+
+	ch_cfg->halt = cfg & 1;
+
+out:
+	return err;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_parse_config);
+
+void pnx4008_dma_split_head_entry(struct pnx4008_dma_config * config,
+				  struct pnx4008_dma_ch_ctrl * ctrl)
+{
+	int new_len = ctrl->tr_size, num_entries = 0;
+	int old_len = new_len;
+	int src_width, dest_width, count = 1;
+
+	switch (ctrl->swidth) {
+	case WIDTH_BYTE:
+		src_width = 1;
+		break;
+	case WIDTH_HWORD:
+		src_width = 2;
+		break;
+	case WIDTH_WORD:
+		src_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	switch (ctrl->dwidth) {
+	case WIDTH_BYTE:
+		dest_width = 1;
+		break;
+	case WIDTH_HWORD:
+		dest_width = 2;
+		break;
+	case WIDTH_WORD:
+		dest_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	while (new_len > 0x7FF) {
+		num_entries++;
+		new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+	}
+	if (num_entries != 0) {
+		struct pnx4008_dma_ll *ll = NULL;
+		config->ch_ctrl &= ~0x7ff;
+		config->ch_ctrl |= new_len;
+		if (!config->is_ll) {
+			config->is_ll = 1;
+			while (num_entries) {
+				if (!ll) {
+					config->ll =
+					    pnx4008_alloc_ll_entry(&config->
+								   ll_dma);
+					ll = config->ll;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    config->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = config->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    config->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = config->dest_addr;
+				ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+		} else {
+			struct pnx4008_dma_ll *ll_old = config->ll;
+			unsigned long ll_dma_old = config->ll_dma;
+			while (num_entries) {
+				if (!ll) {
+					config->ll =
+					    pnx4008_alloc_ll_entry(&config->
+								   ll_dma);
+					ll = config->ll;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    config->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = config->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    config->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = config->dest_addr;
+				ll->ch_ctrl = config->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+			ll->next_dma = ll_dma_old;
+			ll->next = ll_old;
+		}
+		/* adjust last length/tc */
+		ll->ch_ctrl = config->ch_ctrl & (~0x7ff);
+		ll->ch_ctrl |= old_len - new_len * (count - 1);
+		config->ch_ctrl &= 0x7fffffff;
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_head_entry);
+
+void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll * cur_ll,
+				struct pnx4008_dma_ch_ctrl * ctrl)
+{
+	int new_len = ctrl->tr_size, num_entries = 0;
+	int old_len = new_len;
+	int src_width, dest_width, count = 1;
+
+	switch (ctrl->swidth) {
+	case WIDTH_BYTE:
+		src_width = 1;
+		break;
+	case WIDTH_HWORD:
+		src_width = 2;
+		break;
+	case WIDTH_WORD:
+		src_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	switch (ctrl->dwidth) {
+	case WIDTH_BYTE:
+		dest_width = 1;
+		break;
+	case WIDTH_HWORD:
+		dest_width = 2;
+		break;
+	case WIDTH_WORD:
+		dest_width = 4;
+		break;
+	default:
+		return;
+	}
+
+	while (new_len > 0x7FF) {
+		num_entries++;
+		new_len = (ctrl->tr_size + num_entries) / (num_entries + 1);
+	}
+	if (num_entries != 0) {
+		struct pnx4008_dma_ll *ll = NULL;
+		cur_ll->ch_ctrl &= ~0x7ff;
+		cur_ll->ch_ctrl |= new_len;
+		if (!cur_ll->next) {
+			while (num_entries) {
+				if (!ll) {
+					cur_ll->next =
+					    pnx4008_alloc_ll_entry(&cur_ll->
+								   next_dma);
+					ll = cur_ll->next;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    cur_ll->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = cur_ll->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    cur_ll->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = cur_ll->dest_addr;
+				ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+		} else {
+			struct pnx4008_dma_ll *ll_old = cur_ll->next;
+			unsigned long ll_dma_old = cur_ll->next_dma;
+			while (num_entries) {
+				if (!ll) {
+					cur_ll->next =
+					    pnx4008_alloc_ll_entry(&cur_ll->
+								   next_dma);
+					ll = cur_ll->next;
+				} else {
+					ll->next =
+					    pnx4008_alloc_ll_entry(&ll->
+								   next_dma);
+					ll = ll->next;
+				}
+
+				if (ctrl->si)
+					ll->src_addr =
+					    cur_ll->src_addr +
+					    src_width * new_len * count;
+				else
+					ll->src_addr = cur_ll->src_addr;
+				if (ctrl->di)
+					ll->dest_addr =
+					    cur_ll->dest_addr +
+					    dest_width * new_len * count;
+				else
+					ll->dest_addr = cur_ll->dest_addr;
+				ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff;
+				ll->next_dma = 0;
+				ll->next = NULL;
+				num_entries--;
+				count++;
+			}
+
+			ll->next_dma = ll_dma_old;
+			ll->next = ll_old;
+		}
+		/* adjust last length/tc */
+		ll->ch_ctrl = cur_ll->ch_ctrl & (~0x7ff);
+		ll->ch_ctrl |= old_len - new_len * (count - 1);
+		cur_ll->ch_ctrl &= 0x7fffffff;
+	}
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_split_ll_entry);
+
+int pnx4008_config_channel(int ch, struct pnx4008_dma_config * config)
+{
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	__raw_writel(config->src_addr, DMAC_Cx_SRC_ADDR(ch));
+	__raw_writel(config->dest_addr, DMAC_Cx_DEST_ADDR(ch));
+
+	if (config->is_ll)
+		__raw_writel(config->ll_dma, DMAC_Cx_LLI(ch));
+	else
+		__raw_writel(0, DMAC_Cx_LLI(ch));
+
+	__raw_writel(config->ch_ctrl, DMAC_Cx_CONTROL(ch));
+	__raw_writel(config->ch_cfg, DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_config_channel);
+
+int pnx4008_channel_get_config(int ch, struct pnx4008_dma_config * config)
+{
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name || !config)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	config->ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	config->ch_ctrl = __raw_readl(DMAC_Cx_CONTROL(ch));
+
+	config->ll_dma = __raw_readl(DMAC_Cx_LLI(ch));
+	config->is_ll = config->ll_dma ? 1 : 0;
+
+	config->src_addr = __raw_readl(DMAC_Cx_SRC_ADDR(ch));
+	config->dest_addr = __raw_readl(DMAC_Cx_DEST_ADDR(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_channel_get_config);
+
+int pnx4008_dma_ch_enable(int ch)
+{
+	unsigned long ch_cfg;
+
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	ch_cfg |= 1;
+	__raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enable);
+
+int pnx4008_dma_ch_disable(int ch)
+{
+	unsigned long ch_cfg;
+
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	ch_cfg &= ~1;
+	__raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_disable);
+
+int pnx4008_dma_ch_enabled(int ch)
+{
+	unsigned long ch_cfg;
+
+	if (!VALID_CHANNEL(ch) || !dma_channels[ch].name)
+		return -EINVAL;
+
+	pnx4008_dma_lock();
+	ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch));
+	pnx4008_dma_unlock();
+
+	return ch_cfg & 1;
+}
+
+EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled);
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int i;
+	unsigned long dint = __raw_readl(DMAC_INT_STAT);
+	unsigned long tcint = __raw_readl(DMAC_INT_TC_STAT);
+	unsigned long eint = __raw_readl(DMAC_INT_ERR_STAT);
+	unsigned long i_bit;
+
+	for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) {
+		i_bit = 1 << i;
+		if (dint & i_bit) {
+			struct dma_channel *channel = &dma_channels[i];
+
+			if (channel->name && channel->irq_handler) {
+				int cause = 0;
+
+				if (eint & i_bit)
+					cause |= DMA_ERR_INT;
+				if (tcint & i_bit)
+					cause |= DMA_TC_INT;
+				channel->irq_handler(i, cause, channel->data,
+						     regs);
+			} else {
+				/*
+				 * IRQ for an unregistered DMA channel
+				 */
+				printk(KERN_WARNING
+				       "spurious IRQ for DMA channel %d\n", i);
+			}
+			if (tcint & i_bit)
+				__raw_writel(i_bit, DMAC_INT_TC_CLEAR);
+			if (eint & i_bit)
+				__raw_writel(i_bit, DMAC_INT_ERR_CLEAR);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __init pnx4008_dma_init(void)
+{
+	int ret, i;
+
+	ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Wow!  Can't register IRQ for DMA\n");
+		goto out;
+	}
+
+	ll_pool.count = 0x4000 / sizeof(struct pnx4008_dma_ll);
+	ll_pool.cur = ll_pool.vaddr =
+	    dma_alloc_coherent(NULL, ll_pool.count * sizeof(struct pnx4008_dma_ll),
+			       &ll_pool.dma_addr, GFP_KERNEL);
+
+	if (!ll_pool.vaddr) {
+		ret = -ENOMEM;
+		free_irq(DMA_INT, NULL);
+		goto out;
+	}
+
+	for (i = 0; i < ll_pool.count - 1; i++) {
+		void **addr = ll_pool.vaddr + i * sizeof(struct pnx4008_dma_ll);
+		*addr = (void *)addr + sizeof(struct pnx4008_dma_ll);
+	}
+	*(long *)(ll_pool.vaddr +
+		  (ll_pool.count - 1) * sizeof(struct pnx4008_dma_ll)) =
+	    (long)ll_pool.vaddr;
+
+	__raw_writel(1, DMAC_CONFIG);
+
+out:
+	return ret;
+}
+arch_initcall(pnx4008_dma_init);
diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c
new file mode 100644
index 0000000..e1ce050
--- /dev/null
+++ b/arch/arm/mach-pnx4008/gpio.c
@@ -0,0 +1,330 @@
+/*
+ * arch/arm/mach-pnx4008/gpio.c
+ *
+ * PNX4008 GPIO driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/semaphore.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+#include <asm/arch/gpio.h>
+
+/* register definitions */
+#define PIO_VA_BASE	IO_ADDRESS(PNX4008_PIO_BASE)
+
+#define PIO_INP_STATE	(0x00U)
+#define PIO_OUTP_SET	(0x04U)
+#define PIO_OUTP_CLR	(0x08U)
+#define PIO_OUTP_STATE	(0x0CU)
+#define PIO_DRV_SET	(0x10U)
+#define PIO_DRV_CLR	(0x14U)
+#define PIO_DRV_STATE	(0x18U)
+#define PIO_SDINP_STATE	(0x1CU)
+#define PIO_SDOUTP_SET	(0x20U)
+#define PIO_SDOUTP_CLR	(0x24U)
+#define PIO_MUX_SET	(0x28U)
+#define PIO_MUX_CLR	(0x2CU)
+#define PIO_MUX_STATE	(0x30U)
+
+static inline void gpio_lock(void)
+{
+	local_irq_disable();
+}
+
+static inline void gpio_unlock(void)
+{
+	local_irq_enable();
+}
+
+/* Inline functions */
+static inline int gpio_read_bit(u32 reg, int gpio)
+{
+	u32 bit, val;
+	int ret = -EFAULT;
+
+	if (gpio < 0)
+		goto out;
+
+	bit = GPIO_BIT(gpio);
+	if (bit) {
+		val = __raw_readl(PIO_VA_BASE + reg);
+		ret = (val & bit) ? 1 : 0;
+	}
+out:
+	return ret;
+}
+
+static inline int gpio_set_bit(u32 reg, int gpio)
+{
+	u32 bit, val;
+	int ret = -EFAULT;
+
+	if (gpio < 0)
+		goto out;
+
+	bit = GPIO_BIT(gpio);
+	if (bit) {
+		val = __raw_readl(PIO_VA_BASE + reg);
+		val |= bit;
+		__raw_writel(val, PIO_VA_BASE + reg);
+		ret = 0;
+	}
+out:
+	return ret;
+}
+
+/* Very simple access control, bitmap for allocated/free */
+static unsigned long access_map[4];
+#define INP_INDEX	0
+#define OUTP_INDEX	1
+#define GPIO_INDEX	2
+#define MUX_INDEX	3
+
+/*GPIO to Input Mapping */
+static short gpio_to_inp_map[32] = {
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 24, -1
+};
+
+/*GPIO to Mux Mapping */
+static short gpio_to_mux_map[32] = {
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, 0, 1, 4, 5, -1
+};
+
+/*Output to Mux Mapping */
+static short outp_to_mux_map[32] = {
+	-1, -1, -1, 6, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, 2, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1
+};
+
+int pnx4008_gpio_register_pin(unsigned short pin)
+{
+	unsigned long bit = GPIO_BIT(pin);
+	int ret = -EBUSY;	/* Already in use */
+
+	gpio_lock();
+
+	if (GPIO_ISBID(pin)) {
+		if (access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] |= bit;
+
+	} else if (GPIO_ISRAM(pin)) {
+		if (access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] |= bit;
+
+	} else if (GPIO_ISMUX(pin)) {
+		if (access_map[MUX_INDEX] & bit)
+			goto out;
+		access_map[MUX_INDEX] |= bit;
+
+	} else if (GPIO_ISOUT(pin)) {
+		if (access_map[OUTP_INDEX] & bit)
+			goto out;
+		access_map[OUTP_INDEX] |= bit;
+
+	} else if (GPIO_ISIN(pin)) {
+		if (access_map[INP_INDEX] & bit)
+			goto out;
+		access_map[INP_INDEX] |= bit;
+	} else
+		goto out;
+	ret = 0;
+
+out:
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_register_pin);
+
+int pnx4008_gpio_unregister_pin(unsigned short pin)
+{
+	unsigned long bit = GPIO_BIT(pin);
+	int ret = -EFAULT;	/* Not registered */
+
+	gpio_lock();
+
+	if (GPIO_ISBID(pin)) {
+		if (~access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] &= ~bit;
+	} else if (GPIO_ISRAM(pin)) {
+		if (~access_map[GPIO_INDEX] & bit)
+			goto out;
+		access_map[GPIO_INDEX] &= ~bit;
+	} else if (GPIO_ISMUX(pin)) {
+		if (~access_map[MUX_INDEX] & bit)
+			goto out;
+		access_map[MUX_INDEX] &= ~bit;
+	} else if (GPIO_ISOUT(pin)) {
+		if (~access_map[OUTP_INDEX] & bit)
+			goto out;
+		access_map[OUTP_INDEX] &= ~bit;
+	} else if (GPIO_ISIN(pin)) {
+		if (~access_map[INP_INDEX] & bit)
+			goto out;
+		access_map[INP_INDEX] &= ~bit;
+	} else
+		goto out;
+	ret = 0;
+
+out:
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_unregister_pin);
+
+unsigned long pnx4008_gpio_read_pin(unsigned short pin)
+{
+	unsigned long ret = -EFAULT;
+	int gpio = GPIO_BIT_MASK(pin);
+	gpio_lock();
+	if (GPIO_ISOUT(pin)) {
+		ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+	} else if (GPIO_ISRAM(pin)) {
+		if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) {
+			ret = gpio_read_bit(PIO_SDINP_STATE, gpio);
+		}
+	} else if (GPIO_ISBID(pin)) {
+		ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+		if (ret > 0)
+			ret = gpio_read_bit(PIO_OUTP_STATE, gpio);
+		else if (ret == 0)
+			ret =
+			    gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]);
+	} else if (GPIO_ISIN(pin)) {
+		ret = gpio_read_bit(PIO_INP_STATE, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin);
+
+/* Write Value to output */
+int pnx4008_gpio_write_pin(unsigned short pin, int output)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISOUT(pin)) {
+		printk( "writing '%x' to '%x'\n",
+				gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR );
+		ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio);
+	} else if (GPIO_ISRAM(pin)) {
+		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+			ret = gpio_set_bit(output ? PIO_SDOUTP_SET :
+					   PIO_SDOUTP_CLR, gpio);
+	} else if (GPIO_ISBID(pin)) {
+		if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0)
+			ret = gpio_set_bit(output ? PIO_OUTP_SET :
+					   PIO_OUTP_CLR, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_write_pin);
+
+/* Value = 1 : Set GPIO pin as output */
+/* Value = 0 : Set GPIO pin as input */
+int pnx4008_gpio_set_pin_direction(unsigned short pin, int output)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+		ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction);
+
+/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/
+int pnx4008_gpio_read_pin_direction(unsigned short pin)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) {
+		ret = gpio_read_bit(PIO_DRV_STATE, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction);
+
+/* Value = 1 : Set pin to muxed function  */
+/* Value = 0 : Set pin as GPIO */
+int pnx4008_gpio_set_pin_mux(unsigned short pin, int output)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin)) {
+		ret =
+		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+				 gpio_to_mux_map[gpio]);
+	} else if (GPIO_ISOUT(pin)) {
+		ret =
+		    gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR,
+				 outp_to_mux_map[gpio]);
+	} else if (GPIO_ISMUX(pin)) {
+		ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux);
+
+/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/
+int pnx4008_gpio_read_pin_mux(unsigned short pin)
+{
+	int gpio = GPIO_BIT_MASK(pin);
+	int ret = -EFAULT;
+
+	gpio_lock();
+	if (GPIO_ISBID(pin)) {
+		ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]);
+	} else if (GPIO_ISOUT(pin)) {
+		ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]);
+	} else if (GPIO_ISMUX(pin)) {
+		ret = gpio_read_bit(PIO_MUX_STATE, gpio);
+	}
+	gpio_unlock();
+	return ret;
+}
+
+EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux);
diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c
new file mode 100644
index 0000000..9b0a8e0
--- /dev/null
+++ b/arch/arm/mach-pnx4008/irq.c
@@ -0,0 +1,121 @@
+/*
+ * arch/arm/mach-pnx4008/irq.c
+ *
+ * PNX4008 IRQ controller driver
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/map.h>
+#include <asm/arch/irq.h>
+
+static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES;
+
+static void pnx4008_mask_irq(unsigned int irq)
+{
+	__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq));	/* mask interrupt */
+}
+
+static void pnx4008_unmask_irq(unsigned int irq)
+{
+	__raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq));	/* unmask interrupt */
+}
+
+static void pnx4008_mask_ack_irq(unsigned int irq)
+{
+	__raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq));	/* mask interrupt */
+	__raw_writel(INTC_BIT(irq), INTC_SR(irq));	/* clear interrupt status */
+}
+
+static int pnx4008_set_irq_type(unsigned int irq, unsigned int type)
+{
+	switch (type) {
+	case IRQT_RISING:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));	/*edge sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));	/*rising edge */
+		set_irq_handler(irq, do_edge_IRQ);
+		break;
+	case IRQT_FALLING:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq));	/*edge sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));	/*falling edge */
+		set_irq_handler(irq, do_edge_IRQ);
+		break;
+	case IRQT_LOW:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));	/*level sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq));	/*low level */
+		set_irq_handler(irq, do_level_IRQ);
+		break;
+	case IRQT_HIGH:
+		__raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq));	/*level sensitive */
+		__raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq));	/* high level */
+		set_irq_handler(irq, do_level_IRQ);
+		break;
+
+	/* IRQT_BOTHEDGE is not supported */
+	default:
+		printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type);
+		return -1;
+	}
+	return 0;
+}
+
+static struct irqchip pnx4008_irq_chip = {
+	.ack = pnx4008_mask_ack_irq,
+	.mask = pnx4008_mask_irq,
+	.unmask = pnx4008_unmask_irq,
+	.set_type = pnx4008_set_irq_type,
+};
+
+void __init pnx4008_init_irq(void)
+{
+	unsigned int i;
+
+	/* configure and enable IRQ 0,1,30,31 (cascade interrupts) mask all others */
+	pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]);
+	pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]);
+	pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]);
+	pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]);
+
+	__raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) |
+			(1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N),
+		INTC_ER(MAIN_BASE_INT));
+	__raw_writel(0, INTC_ER(SIC1_BASE_INT));
+	__raw_writel(0, INTC_ER(SIC2_BASE_INT));
+
+	/* configure all other IRQ's */
+	for (i = 0; i < NR_IRQS; i++) {
+		if (i == SUB2_FIQ_N || i == SUB1_FIQ_N ||
+			i == SUB2_IRQ_N || i == SUB1_IRQ_N)
+			continue;
+		set_irq_flags(i, IRQF_VALID);
+		set_irq_chip(i, &pnx4008_irq_chip);
+		pnx4008_set_irq_type(i, pnx4008_irq_type[i]);
+	}
+}
+
diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c
new file mode 100644
index 0000000..3649cd3
--- /dev/null
+++ b/arch/arm/mach-pnx4008/pm.c
@@ -0,0 +1,184 @@
+/*
+ * arch/arm/mach-pnx4008/pm.c
+ *
+ * Power Management driver for PNX4008
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/pm.h>
+#include <linux/rtc.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/arch/pm.h>
+#include <asm/arch/clock.h>
+
+#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE)
+
+static void *saved_sram;
+
+static struct clk *pll4_clk;
+
+static inline void pnx4008_standby(void)
+{
+	void (*pnx4008_cpu_standby_ptr) (void);
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	clk_disable(pll4_clk);
+
+	/*saving portion of SRAM to be used by suspend function. */
+	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz);
+
+	/*make sure SRAM copy gets physically written into SDRAM.
+	   SDRAM will be placed into self-refresh during power down */
+	flush_cache_all();
+
+	/*copy suspend function into SRAM */
+	memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz);
+
+	/*do suspend */
+	pnx4008_cpu_standby_ptr = (void *)SRAM_VA;
+	pnx4008_cpu_standby_ptr();
+
+	/*restoring portion of SRAM that was used by suspend function */
+	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz);
+
+	clk_enable(pll4_clk);
+
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static inline void pnx4008_suspend(void)
+{
+	void (*pnx4008_cpu_suspend_ptr) (void);
+
+	local_irq_disable();
+	local_fiq_disable();
+
+	clk_disable(pll4_clk);
+
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT));
+	__raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT));
+
+	/*saving portion of SRAM to be used by suspend function. */
+	memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz);
+
+	/*make sure SRAM copy gets physically written into SDRAM.
+	   SDRAM will be placed into self-refresh during power down */
+	flush_cache_all();
+
+	/*copy suspend function into SRAM */
+	memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz);
+
+	/*do suspend */
+	pnx4008_cpu_suspend_ptr = (void *)SRAM_VA;
+	pnx4008_cpu_suspend_ptr();
+
+	/*restoring portion of SRAM that was used by suspend function */
+	memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz);
+
+	clk_enable(pll4_clk);
+
+	local_fiq_enable();
+	local_irq_enable();
+}
+
+static int pnx4008_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		pnx4008_standby();
+		break;
+	case PM_SUSPEND_MEM:
+		pnx4008_suspend();
+		break;
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int pnx4008_pm_prepare(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+	case PM_SUSPEND_MEM:
+		break;
+
+	case PM_SUSPEND_DISK:
+		return -ENOTSUPP;
+		break;
+
+	default:
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static int pnx4008_pm_finish(suspend_state_t state)
+{
+	return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops pnx4008_pm_ops = {
+	.prepare = pnx4008_pm_prepare,
+	.enter = pnx4008_pm_enter,
+	.finish = pnx4008_pm_finish,
+};
+
+static int __init pnx4008_pm_init(void)
+{
+	u32 sram_size_to_allocate;
+
+	pll4_clk = clk_get(0, "ck_pll4");
+	if (IS_ERR(pll4_clk)) {
+		printk(KERN_ERR
+		       "PM Suspend cannot acquire ARM(PLL4) clock control\n");
+		return PTR_ERR(pll4_clk);
+	}
+
+	if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz)
+		sram_size_to_allocate = pnx4008_cpu_standby_sz;
+	else
+		sram_size_to_allocate = pnx4008_cpu_suspend_sz;
+
+	saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC);
+	if (!saved_sram) {
+		printk(KERN_ERR
+		       "PM Suspend: cannot allocate memory to save portion of SRAM\n");
+		clk_put(pll4_clk);
+		return -ENOMEM;
+	}
+
+	pm_set_ops(&pnx4008_pm_ops);
+	return 0;
+}
+
+late_initcall(pnx4008_pm_init);
diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c
new file mode 100644
index 0000000..95a1b3f9
--- /dev/null
+++ b/arch/arm/mach-pnx4008/serial.c
@@ -0,0 +1,69 @@
+/*
+ *  linux/arch/arm/mach-pnx4008/serial.c
+ *
+ *  PNX4008 UART initialization
+ *
+ *  Copyright:	MontaVista Software Inc. (c) 2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/platform.h>
+#include <asm/hardware.h>
+
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <asm/arch/gpio.h>
+
+#include <asm/arch/clock.h>
+
+#define UART_3		0
+#define UART_4		1
+#define UART_5		2
+#define UART_6		3
+#define UART_UNKNOWN	(-1)
+
+#define UART3_BASE_VA	IO_ADDRESS(PNX4008_UART3_BASE)
+#define UART4_BASE_VA	IO_ADDRESS(PNX4008_UART4_BASE)
+#define UART5_BASE_VA	IO_ADDRESS(PNX4008_UART5_BASE)
+#define UART6_BASE_VA	IO_ADDRESS(PNX4008_UART6_BASE)
+
+#define UART_FCR_OFFSET		8
+#define UART_FIFO_SIZE		64
+
+void pnx4008_uart_init(void)
+{
+	u32 tmp;
+	int i = UART_FIFO_SIZE;
+
+	__raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET);
+	__raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET);
+
+	/* Send a NULL to fix the UART HW bug */
+	__raw_writel(0x00, UART5_BASE_VA);
+	__raw_writel(0x00, UART3_BASE_VA);
+
+	while (i--) {
+		tmp = __raw_readl(UART5_BASE_VA);
+		tmp = __raw_readl(UART3_BASE_VA);
+	}
+	__raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET);
+	__raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET);
+
+	/* setup wakeup interrupt */
+	start_int_set_rising_edge(SE_U3_RX_INT);
+	start_int_ack(SE_U3_RX_INT);
+	start_int_umask(SE_U3_RX_INT);
+
+	start_int_set_rising_edge(SE_U5_RX_INT);
+	start_int_ack(SE_U5_RX_INT);
+	start_int_umask(SE_U5_RX_INT);
+}
+
diff --git a/arch/arm/mach-pnx4008/sleep.S b/arch/arm/mach-pnx4008/sleep.S
new file mode 100644
index 0000000..93c802b
--- /dev/null
+++ b/arch/arm/mach-pnx4008/sleep.S
@@ -0,0 +1,196 @@
+/*
+ * linux/arch/arm/mach-pnx4008/sleep.S
+ *
+ * PNX4008 support for STOP mode and SDRAM self-refresh
+ *
+ * Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE)
+#define PWR_CTRL_REG_OFFS 0x44
+
+#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE)
+#define MPMC_STATUS_REG_OFFS 0x4
+
+		.text
+
+ENTRY(pnx4008_cpu_suspend)
+	@this function should be entered in Direct run mode.
+
+	@ save registers on stack
+	stmfd	sp!, {r0 - r6, lr}
+
+	@ setup Power Manager base address in r4
+	@ and put it's value in r5
+	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ setup SDRAM controller base address in r2
+	@ and put it's value in r3
+	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ do save current bit settings in r1
+	mov	r1, r5
+
+	@ set SDRAM self-refresh bit
+	orr	r5, r5, #(1 << 9)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ set SDRAM self-refresh bit latch
+	orr	r5, r5, #(1 << 8)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get into self-refresh mode
+2:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #(1 << 2)
+	beq	2b
+
+	@ to prepare SDRAM to get out of self-refresh mode after wakeup
+	orr	r5, r5, #(1 << 7)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ do enter stop mode
+	orr	r5, r5, #(1 << 0)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	@ sleeping now...
+
+	@ coming out of STOP mode into Direct Run mode
+	@ clear STOP mode and SDRAM self-refresh bits
+	str	r1, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get out self-refresh mode
+3:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #5
+	bne	3b
+
+	@ restore regs and return
+	ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_suspend_sz)
+	.word	. - pnx4008_cpu_suspend
+
+ENTRY(pnx4008_cpu_standby)
+	@ save registers on stack
+	stmfd	sp!, {r0 - r6, lr}
+
+	@ setup Power Manager base address in r4
+	@ and put it's value in r5
+	mov	r4, #(PWRMAN_VA_BASE & 0xff000000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00)
+	orr	r4, r4, #(PWRMAN_VA_BASE & 0x000000ff)
+	ldr	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ setup SDRAM controller base address in r2
+	@ and put it's value in r3
+	mov	r2, #(SDRAM_CFG_VA_BASE & 0xff000000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00)
+	orr	r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff)
+	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ do save current bit settings in r1
+	mov	r1, r5
+
+	@ set SDRAM self-refresh bit
+	orr	r5, r5, #(1 << 9)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ set SDRAM self-refresh bit latch
+	orr	r5, r5, #(1 << 8)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit
+	and	r5, r5, #(~(1 << 9))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get into self-refresh mode
+2:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #(1 << 2)
+	beq	2b
+
+	@ set 'get out of self-refresh mode after wakeup' bit
+	orr	r5, r5, #(1 << 7)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	mcr     p15, 0, r0, c7, c0, 4	@ kinda sleeping now...
+
+	@ set SDRAM self-refresh bit latch
+	orr	r5, r5, #(1 << 8)
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ clear SDRAM self-refresh bit latch
+	and	r5, r5, #(~(1 << 8))
+	str	r5, [r4, #PWR_CTRL_REG_OFFS]
+
+	@ wait for SDRAM to get out self-refresh mode
+3:	ldr	r3, [r2, #MPMC_STATUS_REG_OFFS]
+	tst	r3, #5
+	bne	3b
+
+	@ restore regs and return
+	ldmfd   sp!, {r0 - r6, pc}
+
+ENTRY(pnx4008_cpu_standby_sz)
+	.word	. - pnx4008_cpu_standby
+
+ENTRY(pnx4008_cache_clean_invalidate)
+	stmfd	sp!, {r0 - r6, lr}
+#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+	mcr	p15, 0, ip, c7, c6, 0		@ invalidate D cache
+#else
+1:	mrc	p15, 0, r15, c7, c14, 3		@ test,clean,invalidate
+	bne     1b
+#endif
+	ldmfd   sp!, {r0 - r6, pc}
diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c
new file mode 100644
index 0000000..4ce6806
--- /dev/null
+++ b/arch/arm/mach-pnx4008/time.c
@@ -0,0 +1,141 @@
+/*
+ * arch/arm/mach-pnx4008/time.c
+ *
+ * PNX4008 Timers
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+#include <asm/system.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/leds.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <asm/errno.h>
+
+/*! Note: all timers are UPCOUNTING */
+
+/*!
+ * Returns number of us since last clock interrupt.  Note that interrupts
+ * will have been disabled by do_gettimeoffset()
+ */
+static unsigned long pnx4008_gettimeoffset(void)
+{
+	u32 ticks_to_match =
+	    __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER);
+	u32 elapsed = LATCH - ticks_to_match;
+	return (elapsed * (tick_nsec / 1000)) / LATCH;
+}
+
+/*!
+ * IRQ handler for the timer
+ */
+static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id,
+					   struct pt_regs *regs)
+{
+	if (__raw_readl(HSTIM_INT) & MATCH0_INT) {
+
+		write_seqlock(&xtime_lock);
+
+		do {
+			timer_tick(regs);
+
+			/*
+			 * this algorithm takes care of possible delay
+			 * for this interrupt handling longer than a normal
+			 * timer period
+			 */
+			__raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH,
+				     HSTIM_MATCH0);
+			__raw_writel(MATCH0_INT, HSTIM_INT);	/* clear interrupt */
+
+			/*
+			 * The goal is to keep incrementing HSTIM_MATCH0
+			 * register until HSTIM_MATCH0 indicates time after
+			 * what HSTIM_COUNTER indicates.
+			 */
+		} while ((signed)
+			 (__raw_readl(HSTIM_MATCH0) -
+			  __raw_readl(HSTIM_COUNTER)) < 0);
+
+		write_sequnlock(&xtime_lock);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction pnx4008_timer_irq = {
+	.name = "PNX4008 Tick Timer",
+	.flags = SA_INTERRUPT | SA_TIMER,
+	.handler = pnx4008_timer_interrupt
+};
+
+/*!
+ * Set up timer and timer interrupt.
+ */
+static __init void pnx4008_setup_timer(void)
+{
+	__raw_writel(RESET_COUNT, MSTIM_CTRL);
+	while (__raw_readl(MSTIM_COUNTER)) ;	/* wait for reset to complete. 100% guarantee event */
+	__raw_writel(0, MSTIM_CTRL);	/* stop the timer */
+	__raw_writel(0, MSTIM_MCTRL);
+
+	__raw_writel(RESET_COUNT, HSTIM_CTRL);
+	while (__raw_readl(HSTIM_COUNTER)) ;	/* wait for reset to complete. 100% guarantee event */
+	__raw_writel(0, HSTIM_CTRL);
+	__raw_writel(0, HSTIM_MCTRL);
+	__raw_writel(0, HSTIM_CCR);
+	__raw_writel(12, HSTIM_PMATCH);	/* scale down to 1 MHZ */
+	__raw_writel(LATCH, HSTIM_MATCH0);
+	__raw_writel(MR0_INT, HSTIM_MCTRL);
+
+	setup_irq(HSTIMER_INT, &pnx4008_timer_irq);
+
+	__raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL);	/*start timer, stop when JTAG active */
+}
+
+/* Timer Clock Control in PM register */
+#define TIMCLK_CTRL_REG  IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC))
+#define WATCHDOG_CLK_EN                   1
+#define TIMER_CLK_EN                      2	/* HS and MS timers? */
+
+static u32 timclk_ctrl_reg_save;
+
+void pnx4008_timer_suspend(void)
+{
+	timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG);
+	__raw_writel(0, TIMCLK_CTRL_REG);	/* disable timers */
+}
+
+void pnx4008_timer_resume(void)
+{
+	__raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG);	/* enable timers */
+}
+
+struct sys_timer pnx4008_timer = {
+	.init = pnx4008_setup_timer,
+	.offset = pnx4008_gettimeoffset,
+	.suspend = pnx4008_timer_suspend,
+	.resume = pnx4008_timer_resume,
+};
+
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 0104fd1..ea5137f 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -61,6 +61,7 @@
 	bool "Enable Sharp SL-5600 (Poodle) Support"
 	depends PXA_SHARPSL_25x
 	select SHARP_LOCOMO
+	select PXA_SSP
 
 config MACH_CORGI
 	bool "Enable Sharp SL-C700 (Corgi) Support"
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 4e8a983..1610690 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -15,7 +15,7 @@
 obj-$(CONFIG_PXA_SHARP_C7xx)	+= corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o
 obj-$(CONFIG_PXA_SHARP_Cxx00)	+= spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o
 obj-$(CONFIG_MACH_AKITA)	+= akita-ioexp.o
-obj-$(CONFIG_MACH_POODLE)	+= poodle.o
+obj-$(CONFIG_MACH_POODLE)	+= poodle.o corgi_ssp.o
 obj-$(CONFIG_MACH_TOSA)         += tosa.o
 
 # Support for blinky lights
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index d6d7260..bf6648a 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -19,6 +19,7 @@
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/host.h>
+#include <linux/pm.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -26,6 +27,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -310,8 +312,31 @@
 	&corgiled_device,
 };
 
+static void corgi_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	if (!machine_is_corgi())
+		/* Green LED off tells the bootloader to halt */
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+	arm_machine_restart('h');
+}
+
+static void corgi_restart(char mode)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	if (!machine_is_corgi())
+		/* Green LED on tells the bootloader to reboot */
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
+	arm_machine_restart('h');
+}
+
 static void __init corgi_init(void)
 {
+	pm_power_off = corgi_poweroff;
+	arm_pm_restart = corgi_restart;
+
 	/* setup sleep mode values */
 	PWER  = 0x00000002;
 	PFER  = 0x00000000;
diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c
index 7a1ab73..4c3de40 100644
--- a/arch/arm/mach-pxa/corgi_pm.c
+++ b/arch/arm/mach-pxa/corgi_pm.c
@@ -27,6 +27,13 @@
 #include <asm/arch/pxa-regs.h>
 #include "sharpsl.h"
 
+#define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
+#define SHARPSL_CHARGE_ON_TEMP         0xe0  /* 2.9V */
+#define SHARPSL_CHARGE_ON_ACIN_HIGH    0x9b  /* 6V */
+#define SHARPSL_CHARGE_ON_ACIN_LOW     0x34  /* 2V */
+#define SHARPSL_FATAL_ACIN_VOLT        182   /* 3.45V */
+#define SHARPSL_FATAL_NOACIN_VOLT      170   /* 3.40V */
+
 static void corgi_charger_init(void)
 {
 	pxa_gpio_mode(CORGI_GPIO_ADC_TEMP_ON | GPIO_OUT);
@@ -195,9 +202,16 @@
 	.read_devdata    = corgipm_read_devdata,
 	.charger_wakeup  = corgi_charger_wakeup,
 	.should_wakeup   = corgi_should_wakeup,
-	.bat_levels      = 40,
-	.bat_levels_noac = spitz_battery_levels_noac,
-	.bat_levels_acin = spitz_battery_levels_acin,
+	.backlight_limit = corgibl_limit_intensity,
+	.charge_on_volt	  = SHARPSL_CHARGE_ON_VOLT,
+	.charge_on_temp	  = SHARPSL_CHARGE_ON_TEMP,
+	.charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH,
+	.charge_acin_low  = SHARPSL_CHARGE_ON_ACIN_LOW,
+	.fatal_acin_volt  = SHARPSL_FATAL_ACIN_VOLT,
+	.fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT,
+	.bat_levels       = 40,
+	.bat_levels_noac  = spitz_battery_levels_noac,
+	.bat_levels_acin  = spitz_battery_levels_acin,
 	.status_high_acin = 188,
 	.status_low_acin  = 178,
 	.status_high_noac = 185,
@@ -214,6 +228,9 @@
 	if (!corgipm_device)
 		return -ENOMEM;
 
+	if (!machine_is_corgi())
+	    corgi_pm_machinfo.batfull_irq = 1;
+
 	corgipm_device->dev.platform_data = &corgi_pm_machinfo;
 	ret = platform_device_add(corgipm_device);
 
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index 8a25a1c..f942131 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -50,12 +50,14 @@
 	unsigned long ret,flag;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
-	GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 
 	ssp_write_word(&corgi_ssp_dev,data);
 	ret = ssp_read_word(&corgi_ssp_dev);
 
-	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
 
 	return ret;
@@ -68,12 +70,14 @@
 void corgi_ssp_ads7846_lock(void)
 {
 	spin_lock(&corgi_ssp_lock);
-	GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPCR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 }
 
 void corgi_ssp_ads7846_unlock(void)
 {
-	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);
 	spin_unlock(&corgi_ssp_lock);
 }
 
@@ -110,11 +114,13 @@
 	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), sscr1, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_lcdcon));
 	ssp_enable(&corgi_ssp_dev);
 
-	GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		GPCR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 	ssp_write_word(&corgi_ssp_dev,data);
 	/* Read null data back from device to prevent SSP overflow */
 	ssp_read_word(&corgi_ssp_dev);
-	GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);
 
 	ssp_disable(&corgi_ssp_dev);
 	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
@@ -147,7 +153,8 @@
 	int voltage,voltage1,voltage2;
 
 	spin_lock_irqsave(&corgi_ssp_lock, flag);
-	GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
+	if (ssp_machinfo->cs_max1111 >= 0)
+		GPCR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
 	ssp_disable(&corgi_ssp_dev);
 	ssp_config(&corgi_ssp_dev, (SSCR0_Motorola | (SSCR0_DSS & 0x07 )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_max1111));
 	ssp_enable(&corgi_ssp_dev);
@@ -169,7 +176,8 @@
 	ssp_disable(&corgi_ssp_dev);
 	ssp_config(&corgi_ssp_dev, (SSCR0_National | (SSCR0_DSS & 0x0b )), 0, 0, SSCR0_SerClkDiv(ssp_machinfo->clk_ads7846));
 	ssp_enable(&corgi_ssp_dev);
-	GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
+	if (ssp_machinfo->cs_max1111 >= 0)
+		GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);
 	spin_unlock_irqrestore(&corgi_ssp_lock, flag);
 
 	if (voltage1 & 0xc0 || voltage2 & 0x3f)
@@ -196,9 +204,12 @@
 	int ret;
 
 	/* Chip Select - Disable All */
-	pxa_gpio_mode(ssp_machinfo->cs_lcdcon  | GPIO_OUT | GPIO_DFLT_HIGH);
-        pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
-        pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		pxa_gpio_mode(ssp_machinfo->cs_lcdcon  | GPIO_OUT | GPIO_DFLT_HIGH);
+	if (ssp_machinfo->cs_max1111 >= 0)
+	        pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
+	if (ssp_machinfo->cs_ads7846 >= 0)
+        	pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
 
 	ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
 
@@ -229,9 +240,12 @@
 
 static int corgi_ssp_resume(struct platform_device *dev)
 {
-	GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
-	GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
-	GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
+	if (ssp_machinfo->cs_lcdcon >= 0)
+		GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
+	if (ssp_machinfo->cs_max1111 >= 0)
+		GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
+	if (ssp_machinfo->cs_ads7846 >= 0)
+		GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
 	ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
 	ssp_enable(&corgi_ssp_dev);
 
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 3e26d7c..1ab26c6 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -22,6 +22,10 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <asm/arch/pxa2xx_spi.h>
+
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/mach-types.h>
@@ -196,6 +200,78 @@
 	},
 };
 
+/* ADS7846 is connected through SSP ... and if your board has J5 populated,
+ * you can select it to replace the ucb1400 by switching the touchscreen cable
+ * (to J5) and poking board registers (as done below).  Else it's only useful
+ * for the temperature sensors.
+ */
+static struct resource pxa_ssp_resources[] = {
+	[0] = {
+		.start	= __PREG(SSCR0_P(1)),
+		.end	= __PREG(SSCR0_P(1)) + 0x14,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SSP,
+		.end	= IRQ_SSP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct pxa2xx_spi_master pxa_ssp_master_info = {
+	.ssp_type	= PXA25x_SSP,
+	.clock_enable	= CKEN3_SSP,
+	.num_chipselect	= 0,
+};
+
+static struct platform_device pxa_ssp = {
+	.name		= "pxa2xx-spi",
+	.id		= 1,
+	.resource	= pxa_ssp_resources,
+	.num_resources	= ARRAY_SIZE(pxa_ssp_resources),
+	.dev = {
+		.platform_data	= &pxa_ssp_master_info,
+	},
+};
+
+static int lubbock_ads7846_pendown_state(void)
+{
+	/* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */
+	return 0;
+}
+
+static struct ads7846_platform_data ads_info = {
+	.model			= 7846,
+	.vref_delay_usecs	= 100,		/* internal, no cap */
+	.get_pendown_state	= lubbock_ads7846_pendown_state,
+	// .x_plate_ohms		= 500,	/* GUESS! */
+	// .y_plate_ohms		= 500,	/* GUESS! */
+};
+
+static void ads7846_cs(u32 command)
+{
+	static const unsigned	TS_nCS = 1 << 11;
+	lubbock_set_misc_wr(TS_nCS, (command == PXA2XX_CS_ASSERT) ? 0 : TS_nCS);
+}
+
+static struct pxa2xx_spi_chip ads_hw = {
+	.tx_threshold		= 1,
+	.rx_threshold		= 2,
+	.cs_control		= ads7846_cs,
+};
+
+static struct spi_board_info spi_board_info[] __initdata = { {
+	.modalias	= "ads7846",
+	.platform_data	= &ads_info,
+	.controller_data = &ads_hw,
+	.irq		= LUBBOCK_BB_IRQ,
+	.max_speed_hz	= 120000 /* max sample rate at 3V */
+				* 26 /* command + data + overhead */,
+	.bus_num	= 1,
+	.chip_select	= 0,
+},
+};
+
 static struct platform_device smc91x_device = {
 	.name		= "smc91x",
 	.id		= -1,
@@ -272,6 +348,7 @@
 	&smc91x_device,
 	&lubbock_flash_device[0],
 	&lubbock_flash_device[1],
+	&pxa_ssp,
 };
 
 static struct pxafb_mach_info sharp_lm8v31 __initdata = {
@@ -400,6 +477,8 @@
 	lubbock_flash_data[flashboot^1].name = "application-flash";
 	lubbock_flash_data[flashboot].name = "boot-rom";
 	(void) platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
 }
 
 static struct map_desc lubbock_io_desc[] __initdata = {
@@ -416,6 +495,11 @@
 	pxa_map_io();
 	iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc));
 
+	/* SSP data pins */
+	pxa_gpio_mode(GPIO23_SCLK_MD);
+	pxa_gpio_mode(GPIO25_STXD_MD);
+	pxa_gpio_mode(GPIO26_SRXD_MD);
+
 	/* This enables the BTUART */
 	pxa_gpio_mode(GPIO42_BTRXD_MD);
 	pxa_gpio_mode(GPIO43_BTTXD_MD);
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index a042473..9a9fa87 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -18,11 +18,14 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/fb.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
 
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
+#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -34,12 +37,15 @@
 #include <asm/arch/irda.h>
 #include <asm/arch/poodle.h>
 #include <asm/arch/pxafb.h>
+#include <asm/arch/sharpsl.h>
+#include <asm/arch/ssp.h>
 
 #include <asm/hardware/scoop.h>
 #include <asm/hardware/locomo.h>
 #include <asm/mach/sharpsl_param.h>
 
 #include "generic.h"
+#include "sharpsl.h"
 
 static struct resource poodle_scoop_resources[] = {
 	[0] = {
@@ -117,13 +123,71 @@
 	},
 };
 
-static struct platform_device locomo_device = {
+struct platform_device poodle_locomo_device = {
 	.name		= "locomo",
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(locomo_resources),
 	.resource	= locomo_resources,
 };
 
+EXPORT_SYMBOL(poodle_locomo_device);
+
+/*
+ * Poodle SSP Device
+ */
+
+struct platform_device poodle_ssp_device = {
+	.name		= "corgi-ssp",
+	.id		= -1,
+};
+
+struct corgissp_machinfo poodle_ssp_machinfo = {
+	.port		= 1,
+	.cs_lcdcon	= -1,
+	.cs_ads7846	= -1,
+	.cs_max1111	= -1,
+	.clk_lcdcon	= 2,
+	.clk_ads7846	= 36,
+	.clk_max1111	= 2,
+};
+
+
+/*
+ * Poodle Touch Screen Device
+ */
+static struct resource poodlets_resources[] = {
+	[0] = {
+		.start		= POODLE_IRQ_GPIO_TP_INT,
+		.end		= POODLE_IRQ_GPIO_TP_INT,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static unsigned long poodle_get_hsync_len(void)
+{
+	return 0;
+}
+
+static void poodle_null_hsync(void)
+{
+}
+
+static struct corgits_machinfo  poodle_ts_machinfo = {
+	.get_hsync_len   = poodle_get_hsync_len,
+	.put_hsync       = poodle_null_hsync,
+	.wait_hsync      = poodle_null_hsync,
+};
+
+static struct platform_device poodle_ts_device = {
+	.name		= "corgi-ts",
+	.dev		= {
+		.platform_data	= &poodle_ts_machinfo,
+	},
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(poodlets_resources),
+	.resource	= poodlets_resources,
+};
+
 
 /*
  * MMC/SD Device
@@ -141,7 +205,9 @@
 	pxa_gpio_mode(GPIO6_MMCCLK_MD);
 	pxa_gpio_mode(GPIO8_MMCCS0_MD);
 	pxa_gpio_mode(POODLE_GPIO_nSD_DETECT | GPIO_IN);
+	pxa_gpio_mode(POODLE_GPIO_nSD_WP | GPIO_IN);
 	pxa_gpio_mode(POODLE_GPIO_SD_PWR | GPIO_OUT);
+	pxa_gpio_mode(POODLE_GPIO_SD_PWR1 | GPIO_OUT);
 
 	poodle_mci_platform_data.detect_delay = msecs_to_jiffies(250);
 
@@ -160,12 +226,22 @@
 {
 	struct pxamci_platform_data* p_d = dev->platform_data;
 
-	if (( 1 << vdd) & p_d->ocr_mask)
-		GPSR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
-	else
-		GPCR1 = GPIO_bit(POODLE_GPIO_SD_PWR);
+	if (( 1 << vdd) & p_d->ocr_mask) {
+		GPSR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR);
+		mdelay(2);
+		GPSR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1);
+	} else {
+		GPCR(POODLE_GPIO_SD_PWR1) = GPIO_bit(POODLE_GPIO_SD_PWR1);
+		GPCR(POODLE_GPIO_SD_PWR) = GPIO_bit(POODLE_GPIO_SD_PWR);
+	}
 }
 
+static int poodle_mci_get_ro(struct device *dev)
+{
+	return GPLR(POODLE_GPIO_nSD_WP) & GPIO_bit(POODLE_GPIO_nSD_WP);
+}
+
+
 static void poodle_mci_exit(struct device *dev, void *data)
 {
 	free_irq(POODLE_IRQ_GPIO_nSD_DETECT, data);
@@ -174,6 +250,7 @@
 static struct pxamci_platform_data poodle_mci_platform_data = {
 	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
 	.init 		= poodle_mci_init,
+	.get_ro		= poodle_mci_get_ro,
 	.setpower 	= poodle_mci_setpower,
 	.exit		= poodle_mci_exit,
 };
@@ -243,14 +320,31 @@
 };
 
 static struct platform_device *devices[] __initdata = {
-	&locomo_device,
+	&poodle_locomo_device,
 	&poodle_scoop_device,
+	&poodle_ssp_device,
+	&poodle_ts_device,
 };
 
+static void poodle_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+	arm_machine_restart('h');
+}
+
+static void poodle_restart(char mode)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+	arm_machine_restart('h');
+}
+
 static void __init poodle_init(void)
 {
 	int ret = 0;
 
+	pm_power_off = poodle_poweroff;
+	arm_pm_restart = poodle_restart;
+
 	/* setup sleep mode values */
 	PWER  = 0x00000002;
 	PFER  = 0x00000000;
@@ -288,6 +382,7 @@
   	GPSR1 = 0x00000000;
         GPSR2 = 0x00000000;
 
+	set_pxa_fb_parent(&poodle_locomo_device.dev);
 	set_pxa_fb_info(&poodle_fb_info);
 	pxa_gpio_mode(POODLE_GPIO_USB_PULLUP | GPIO_OUT);
 	pxa_gpio_mode(POODLE_GPIO_IR_ON | GPIO_OUT);
@@ -301,6 +396,7 @@
 	if (ret) {
 		printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
 	}
+	corgi_ssp_set_machinfo(&poodle_ssp_machinfo);
 }
 
 static void __init fixup_poodle(struct machine_desc *desc,
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 6d402b2..0f16487 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -128,6 +128,9 @@
  */
 int sharpsl_pm_pxa_read_max1111(int channel)
 {
+	if (machine_is_tosa()) // Ugly, better move this function into another module
+	    return 0;
+
 	return corgi_ssp_max1111_get((channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1
 			| MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR);
 }
@@ -156,7 +159,7 @@
 		else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQT_FALLING);
 	}
 
-	if (!machine_is_corgi())
+	if (sharpsl_pm.machinfo->batfull_irq)
 	{
 		/* Register interrupt handler. */
 		if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, SA_INTERRUPT, "CO", sharpsl_chrg_full_isr)) {
@@ -174,6 +177,6 @@
 	if (sharpsl_pm.machinfo->gpio_fatal)
 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr);
 
-	if (!machine_is_corgi())
+	if (sharpsl_pm.machinfo->batfull_irq)
 		free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr);
 }
diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
index c986268..0650bed 100644
--- a/arch/arm/mach-pxa/sleep.S
+++ b/arch/arm/mach-pxa/sleep.S
@@ -189,7 +189,7 @@
 	.data
 	.align 5
 ENTRY(pxa_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC	@ set SVC, irqs off
+	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
 	msr	cpsr_c, r0
 
 	ldr	r0, sleep_save_sp		@ stack phys addr
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 44bcb80..eb9937f 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -20,6 +20,7 @@
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/host.h>
+#include <linux/pm.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -27,6 +28,7 @@
 #include <asm/hardware.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/system.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -432,8 +434,31 @@
 	&spitzled_device,
 };
 
+static void spitz_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	pxa_gpio_mode(SPITZ_GPIO_ON_RESET | GPIO_OUT);
+	GPSR(SPITZ_GPIO_ON_RESET) = GPIO_bit(SPITZ_GPIO_ON_RESET);
+
+	mdelay(1000);
+	arm_machine_restart('h');
+}
+
+static void spitz_restart(char mode)
+{
+	/* Bootloader magic for a reboot */
+	if((MSC0 & 0xffff0000) == 0x7ff00000)
+		MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+
+	spitz_poweroff();
+}
+
 static void __init common_init(void)
 {
+	pm_power_off = spitz_poweroff;
+	arm_pm_restart = spitz_restart;
+
 	PMCR = 0x00;
 
 	/* setup sleep mode values */
diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c
index 5e5bdc8..40be833 100644
--- a/arch/arm/mach-pxa/spitz_pm.c
+++ b/arch/arm/mach-pxa/spitz_pm.c
@@ -27,6 +27,13 @@
 #include <asm/arch/pxa-regs.h>
 #include "sharpsl.h"
 
+#define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
+#define SHARPSL_CHARGE_ON_TEMP         0xe0  /* 2.9V */
+#define SHARPSL_CHARGE_ON_ACIN_HIGH    0x9b  /* 6V */
+#define SHARPSL_CHARGE_ON_ACIN_LOW     0x34  /* 2V */
+#define SHARPSL_FATAL_ACIN_VOLT        182   /* 3.45V */
+#define SHARPSL_FATAL_NOACIN_VOLT      170   /* 3.40V */
+
 static int spitz_last_ac_status;
 
 static void spitz_charger_init(void)
@@ -190,6 +197,7 @@
 	.gpio_batlock     = SPITZ_GPIO_BAT_COVER,
 	.gpio_acin        = SPITZ_GPIO_AC_IN,
 	.gpio_batfull     = SPITZ_GPIO_CHRG_FULL,
+	.batfull_irq	  = 1,
 	.gpio_fatal       = SPITZ_GPIO_FATAL_BAT,
 	.discharge        = spitz_discharge,
 	.discharge1       = spitz_discharge1,
@@ -200,6 +208,13 @@
 	.read_devdata     = spitzpm_read_devdata,
 	.charger_wakeup   = spitz_charger_wakeup,
 	.should_wakeup    = spitz_should_wakeup,
+        .backlight_limit  = corgibl_limit_intensity,
+	.charge_on_volt	  = SHARPSL_CHARGE_ON_VOLT,
+	.charge_on_temp	  = SHARPSL_CHARGE_ON_TEMP,
+	.charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH,
+	.charge_acin_low  = SHARPSL_CHARGE_ON_ACIN_LOW,
+	.fatal_acin_volt  = SHARPSL_FATAL_ACIN_VOLT,
+	.fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT,
 	.bat_levels       = 40,
 	.bat_levels_noac  = spitz_battery_levels_noac,
 	.bat_levels_acin  = spitz_battery_levels_acin,
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 76c0e7f..7152bc1 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -19,12 +19,15 @@
 #include <linux/fs.h>
 #include <linux/interrupt.h>
 #include <linux/mmc/host.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
 #include <asm/mach-types.h>
 #include <asm/hardware.h>
 #include <asm/irq.h>
+#include <asm/system.h>
 #include <asm/arch/irda.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/udc.h>
@@ -266,8 +269,31 @@
 	&tosaled_device,
 };
 
+static void tosa_poweroff(void)
+{
+	RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR;
+
+	pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_OUT);
+	GPSR(TOSA_GPIO_ON_RESET) = GPIO_bit(TOSA_GPIO_ON_RESET);
+
+	mdelay(1000);
+	arm_machine_restart('h');
+}
+
+static void tosa_restart(char mode)
+{
+	/* Bootloader magic for a reboot */
+	if((MSC0 & 0xffff0000) == 0x7ff00000)
+		MSC0 = (MSC0 & 0xffff) | 0x7ee00000;
+
+	tosa_poweroff();
+}
+
 static void __init tosa_init(void)
 {
+	pm_power_off = tosa_poweroff;
+	arm_pm_restart = tosa_restart;
+
 	pxa_gpio_mode(TOSA_GPIO_ON_RESET | GPIO_IN);
 	pxa_gpio_mode(TOSA_GPIO_TC6393_INT | GPIO_IN);
 	pxa_gpio_mode(TOSA_GPIO_USB_IN | GPIO_IN);
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 970f98d..b4171dd 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/arch/arm/mach-s3c2410/Kconfig
@@ -70,6 +70,24 @@
 	help
 	  Say Y here if you are using the SMDK2440.
 
+config SMDK2440_CPU2440
+	bool "SMDK2440 with S3C2440 CPU module"
+	depends on ARCH_S3C2440
+	default y if ARCH_S3C2440
+	select CPU_S3C2440
+
+config SMDK2440_CPU2442
+	bool "SMDM2440 with S3C2442 CPU module"
+	depends on ARCH_S3C2440
+	select CPU_S3C2442
+
+config MACH_SMDK2413
+	bool "SMDK2413"
+	select CPU_S3C2412
+	select MACH_SMDK
+	help
+	  Say Y here if you are using an SMDK2413
+
 config MACH_VR1000
 	bool "Thorcom VR1000"
 	select CPU_S3C2410
@@ -102,19 +120,55 @@
 
 endmenu
 
+config S3C2410_CLOCK
+	bool
+	help
+	  Clock code for the S3C2410, and similar processors
+
 config CPU_S3C2410
 	bool
 	depends on ARCH_S3C2410
+	select S3C2410_CLOCK
 	help
 	  Support for S3C2410 and S3C2410A family from the S3C24XX line
 	  of Samsung Mobile CPUs.
 
-config CPU_S3C2440
+# internal node to signify if we are only dealing with an S3C2412
+
+config CPU_S3C2412_ONLY
+	bool
+	depends on ARCH_S3C2410 && !CPU_S3C2400 && !CPU_S3C2410 && \
+		   !CPU_S3C2440 && !CPU_S3C2442 && CPU_S3C2412
+	default y if CPU_S3C2412
+
+config CPU_S3C2412
 	bool
 	depends on ARCH_S3C2410
 	help
+	  Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
+
+config CPU_S3C244X
+	bool
+	depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
+	help
+	  Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
+
+config CPU_S3C2440
+	bool
+	depends on ARCH_S3C2410
+	select S3C2410_CLOCK
+	select CPU_S3C244X
+	help
 	  Support for S3C2440 Samsung Mobile CPU based systems.
 
+config CPU_S3C2442
+	bool
+	depends on ARCH_S3C2420
+	select S3C2410_CLOCK
+	select CPU_S3C244X
+	help
+	  Support for S3C2442 Samsung Mobile CPU based systems.
+
 comment "S3C2410 Boot"
 
 config S3C2410_BOOT_WATCHDOG
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 3e5712d..0c79386 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -24,6 +24,20 @@
 obj-$(CONFIG_PM)	   += pm.o sleep.o
 obj-$(CONFIG_PM_SIMTEC)	   += pm-simtec.o
 
+# S3C2412 support
+obj-$(CONFIG_CPU_S3C2412)  += s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)  += s3c2412-clock.o
+
+#
+# S3C244X support
+
+obj-$(CONFIG_CPU_S3C244X)  += s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)  += s3c244x-irq.o
+
+# Clock control
+
+obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
+
 # S3C2440 support
 
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440.o s3c2440-dsc.o
@@ -31,6 +45,11 @@
 obj-$(CONFIG_CPU_S3C2440)  += s3c2440-clock.o
 obj-$(CONFIG_CPU_S3C2440)  += s3c2410-gpio.o
 
+# S3C2442 support
+
+obj-$(CONFIG_CPU_S3C2442)  += s3c2442.o
+obj-$(CONFIG_CPU_S3C2442)  += s3c2442-clock.o
+
 # bast extras
 
 obj-$(CONFIG_BAST_PC104_IRQ)	+= bast-irq.o
@@ -43,6 +62,7 @@
 obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
 obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
+obj-$(CONFIG_MACH_SMDK2413)	+= mach-smdk2413.o
 obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
 obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index 6de713a..e13fb67 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -3,7 +3,7 @@
  * Copyright (c) 2004-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
- * S3C2410 Clock control support
+ * S3C24XX Core clock control support
  *
  * Based on, and code from linux/arch/arm/mach-versatile/clock.c
  **
@@ -56,25 +56,6 @@
 
 DEFINE_MUTEX(clocks_mutex);
 
-/* old functions */
-
-void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
-{
-	unsigned long clkcon;
-
-	clkcon = __raw_readl(S3C2410_CLKCON);
-
-	if (enable)
-		clkcon |= clocks;
-	else
-		clkcon &= ~clocks;
-
-	/* ensure none of the special function bits set */
-	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
-
-	__raw_writel(clkcon, S3C2410_CLKCON);
-}
-
 /* enable and disable calls for use with the clk struct */
 
 static int clk_null_enable(struct clk *clk, int enable)
@@ -82,12 +63,6 @@
 	return 0;
 }
 
-int s3c24xx_clkcon_enable(struct clk *clk, int enable)
-{
-	s3c24xx_clk_enable(clk->ctrlbit, enable);
-	return 0;
-}
-
 /* Clock API calls */
 
 struct clk *clk_get(struct device *dev, const char *id)
@@ -173,8 +148,11 @@
 	if (clk->rate != 0)
 		return clk->rate;
 
-	while (clk->parent != NULL && clk->rate == 0)
-		clk = clk->parent;
+	if (clk->get_rate != NULL)
+		return (clk->get_rate)(clk);
+
+	if (clk->parent != NULL)
+		return clk_get_rate(clk->parent);
 
 	return clk->rate;
 }
@@ -233,31 +211,9 @@
 EXPORT_SYMBOL(clk_get_parent);
 EXPORT_SYMBOL(clk_set_parent);
 
-/* base clock enable */
-
-static int s3c24xx_upll_enable(struct clk *clk, int enable)
-{
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	unsigned long orig = clkslow;
-
-	if (enable)
-		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
-	else
-		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
-
-	__raw_writel(clkslow, S3C2410_CLKSLOW);
-
-	/* if we started the UPLL, then allow to settle */
-
-	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
-		udelay(200);
-
-	return 0;
-}
-
 /* base clocks */
 
-static struct clk clk_xtal = {
+struct clk clk_xtal = {
 	.name		= "xtal",
 	.id		= -1,
 	.rate		= 0,
@@ -265,23 +221,27 @@
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_upll = {
+struct clk clk_mpll = {
+	.name		= "mpll",
+	.id		= -1,
+};
+
+struct clk clk_upll = {
 	.name		= "upll",
 	.id		= -1,
 	.parent		= NULL,
-	.enable		= s3c24xx_upll_enable,
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_f = {
+struct clk clk_f = {
 	.name		= "fclk",
 	.id		= -1,
 	.rate		= 0,
-	.parent		= NULL,
+	.parent		= &clk_mpll,
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_h = {
+struct clk clk_h = {
 	.name		= "hclk",
 	.id		= -1,
 	.rate		= 0,
@@ -289,7 +249,7 @@
 	.ctrlbit	= 0,
 };
 
-static struct clk clk_p = {
+struct clk clk_p = {
 	.name		= "pclk",
 	.id		= -1,
 	.rate		= 0,
@@ -308,14 +268,14 @@
 
 static int s3c24xx_dclk_enable(struct clk *clk, int enable)
 {
-	unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON);
+	unsigned long dclkcon = __raw_readl(S3C24XX_DCLKCON);
 
 	if (enable)
 		dclkcon |= clk->ctrlbit;
 	else
 		dclkcon &= ~clk->ctrlbit;
 
-	__raw_writel(dclkcon, S3C2410_DCLKCON);
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
 
 	return 0;
 }
@@ -334,7 +294,7 @@
 
 	clk->parent = parent;
 
-	dclkcon = __raw_readl(S3C2410_DCLKCON);
+	dclkcon = __raw_readl(S3C24XX_DCLKCON);
 
 	if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) {
 		if (uclk)
@@ -348,7 +308,7 @@
 			dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK;
 	}
 
-	__raw_writel(dclkcon, S3C2410_DCLKCON);
+	__raw_writel(dclkcon, S3C24XX_DCLKCON);
 
 	return 0;
 }
@@ -426,108 +386,6 @@
 	.id		= -1,
 };
 
-
-/* standard clock definitions */
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "nand",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_NAND,
-	}, {
-		.name		= "lcd",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_LCDC,
-	}, {
-		.name		= "usb-host",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBH,
-	}, {
-		.name		= "usb-device",
-		.id		= -1,
-		.parent		= &clk_h,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_USBD,
-	}, {
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_PWMT,
-	}, {
-		.name		= "sdi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SDI,
-	}, {
-		.name		= "uart",
-		.id		= 0,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART0,
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART1,
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_UART2,
-	}, {
-		.name		= "gpio",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_GPIO,
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_RTC,
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_ADC,
-	}, {
-		.name		= "i2c",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIC,
-	}, {
-		.name		= "iis",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_IIS,
-	}, {
-		.name		= "spi",
-		.id		= -1,
-		.parent		= &clk_p,
-		.enable		= s3c24xx_clkcon_enable,
-		.ctrlbit	= S3C2410_CLKCON_SPI,
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.parent		= &clk_p,
-		.ctrlbit	= 0,
-	}
-};
-
 /* initialise the clock system */
 
 int s3c24xx_register_clock(struct clk *clk)
@@ -537,14 +395,6 @@
 	if (clk->enable == NULL)
 		clk->enable = clk_null_enable;
 
-	/* if this is a standard clock, set the usage state */
-
-	if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) {
-		unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
-
-		clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0;
-	}
-
 	/* add to the list of available clocks */
 
 	mutex_lock(&clocks_mutex);
@@ -561,44 +411,18 @@
 				unsigned long hclk,
 				unsigned long pclk)
 {
-	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
-	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
-	struct clk *clkp = init_clocks;
-	int ptr;
-	int ret;
-
-	printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n");
+	printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
 
 	/* initialise the main system clocks */
 
 	clk_xtal.rate = xtal;
-	clk_upll.rate = s3c2410_get_pll(upllcon, xtal);
+	clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
 
+	clk_mpll.rate = fclk;
 	clk_h.rate = hclk;
 	clk_p.rate = pclk;
 	clk_f.rate = fclk;
 
-	/* We must be careful disabling the clocks we are not intending to
-	 * be using at boot time, as subsytems such as the LCD which do
-	 * their own DMA requests to the bus can cause the system to lockup
-	 * if they where in the middle of requesting bus access.
-	 *
-	 * Disabling the LCD clock if the LCD is active is very dangerous,
-	 * and therefore the bootloader should be  careful to not enable
-	 * the LCD clock if it is not needed.
-	*/
-
-	mutex_lock(&clocks_mutex);
-
-	s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_ADC, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0);
-	s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0);
-
-	mutex_unlock(&clocks_mutex);
-
 	/* assume uart clocks are correctly setup */
 
 	/* register our clocks */
@@ -606,6 +430,9 @@
 	if (s3c24xx_register_clock(&clk_xtal) < 0)
 		printk(KERN_ERR "failed to register master xtal\n");
 
+	if (s3c24xx_register_clock(&clk_mpll) < 0)
+		printk(KERN_ERR "failed to register mpll clock\n");
+
 	if (s3c24xx_register_clock(&clk_upll) < 0)
 		printk(KERN_ERR "failed to register upll clock\n");
 
@@ -618,27 +445,5 @@
 	if (s3c24xx_register_clock(&clk_p) < 0)
 		printk(KERN_ERR "failed to register cpu pclk\n");
 
-
-	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
-		printk(KERN_ERR "failed to register usb bus clock\n");
-
-	/* register clocks from clock array */
-
-	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
-		ret = s3c24xx_register_clock(clkp);
-		if (ret < 0) {
-			printk(KERN_ERR "Failed to register clock %s (%d)\n",
-			       clkp->name, ret);
-		}
-	}
-
-	/* show the clock-slow value */
-
-	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
-	       print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
-	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
-	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
-	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
-
 	return 0;
 }
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
index 01bb458..7f0ea03 100644
--- a/arch/arm/mach-s3c2410/clock.h
+++ b/arch/arm/mach-s3c2410/clock.h
@@ -22,6 +22,7 @@
 
 	int		    (*enable)(struct clk *, int enable);
 	int		    (*set_rate)(struct clk *c, unsigned long rate);
+	unsigned long	    (*get_rate)(struct clk *c);
 	unsigned long	    (*round_rate)(struct clk *c, unsigned long rate);
 	int		    (*set_parent)(struct clk *c, struct clk *parent);
 };
@@ -36,6 +37,15 @@
 
 extern struct clk clk_usb_bus;
 
+/* core clock support */
+
+extern struct clk clk_f;
+extern struct clk clk_h;
+extern struct clk clk_p;
+extern struct clk clk_mpll;
+extern struct clk clk_upll;
+extern struct clk clk_xtal;
+
 /* exports for arch/arm/mach-s3c2410
  *
  * Please DO NOT use these outside of arch/arm/mach-s3c2410
@@ -43,7 +53,8 @@
 
 extern struct mutex clocks_mutex;
 
-extern int s3c24xx_clkcon_enable(struct clk *clk, int enable);
+extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
+
 extern int s3c24xx_register_clock(struct clk *clk);
 
 extern int s3c24xx_setup_clocks(unsigned long xtal,
diff --git a/arch/arm/mach-s3c2410/common-smdk.c b/arch/arm/mach-s3c2410/common-smdk.c
index c940890..a40eaa6 100644
--- a/arch/arm/mach-s3c2410/common-smdk.c
+++ b/arch/arm/mach-s3c2410/common-smdk.c
@@ -34,6 +34,7 @@
 #include <asm/irq.h>
 
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/leds-gpio.h>
 
 #include <asm/arch/nand.h>
 
@@ -41,6 +42,66 @@
 #include "devs.h"
 #include "pm.h"
 
+/* LED devices */
+
+static struct s3c24xx_led_platdata smdk_pdata_led4 = {
+	.gpio		= S3C2410_GPF4,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led4",
+	.def_trigger	= "timer",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led5 = {
+	.gpio		= S3C2410_GPF5,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led5",
+	.def_trigger	= "nand-disk",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led6 = {
+	.gpio		= S3C2410_GPF6,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led6",
+};
+
+static struct s3c24xx_led_platdata smdk_pdata_led7 = {
+	.gpio		= S3C2410_GPF7,
+	.flags		= S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
+	.name		= "led7",
+};
+
+static struct platform_device smdk_led4 = {
+	.name		= "s3c24xx_led",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &smdk_pdata_led4,
+	},
+};
+
+static struct platform_device smdk_led5 = {
+	.name		= "s3c24xx_led",
+	.id		= 1,
+	.dev		= {
+		.platform_data = &smdk_pdata_led5,
+	},
+};
+
+static struct platform_device smdk_led6 = {
+	.name		= "s3c24xx_led",
+	.id		= 2,
+	.dev		= {
+		.platform_data = &smdk_pdata_led6,
+	},
+};
+
+static struct platform_device smdk_led7 = {
+	.name		= "s3c24xx_led",
+	.id		= 3,
+	.dev		= {
+		.platform_data = &smdk_pdata_led7,
+	},
+};
+
 /* NAND parititon from 2.4.18-swl5 */
 
 static struct mtd_partition smdk_default_nand_part[] = {
@@ -111,6 +172,10 @@
 
 static struct platform_device __initdata *smdk_devs[] = {
 	&s3c_device_nand,
+	&smdk_led4,
+	&smdk_led5,
+	&smdk_led6,
+	&smdk_led7,
 };
 
 void __init smdk_machine_init(void)
diff --git a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
index 70c34fc..1c3c6ad 100644
--- a/arch/arm/mach-s3c2410/cpu.c
+++ b/arch/arm/mach-s3c2410/cpu.c
@@ -37,12 +37,17 @@
 #include <asm/mach/map.h>
 
 #include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-serial.h>
 
 #include "cpu.h"
+#include "devs.h"
 #include "clock.h"
 #include "s3c2400.h"
 #include "s3c2410.h"
+#include "s3c2412.h"
+#include "s3c244x.h"
 #include "s3c2440.h"
+#include "s3c2442.h"
 
 struct cpu_table {
 	unsigned long	idcode;
@@ -58,7 +63,9 @@
 
 static const char name_s3c2400[]  = "S3C2400";
 static const char name_s3c2410[]  = "S3C2410";
+static const char name_s3c2412[]  = "S3C2412";
 static const char name_s3c2440[]  = "S3C2440";
+static const char name_s3c2442[]  = "S3C2442";
 static const char name_s3c2410a[] = "S3C2410A";
 static const char name_s3c2440a[] = "S3C2440A";
 
@@ -84,22 +91,40 @@
 	{
 		.idcode		= 0x32440000,
 		.idmask		= 0xffffffff,
-		.map_io		= s3c2440_map_io,
-		.init_clocks	= s3c2440_init_clocks,
-		.init_uarts	= s3c2440_init_uarts,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
 		.init		= s3c2440_init,
 		.name		= name_s3c2440
 	},
 	{
 		.idcode		= 0x32440001,
 		.idmask		= 0xffffffff,
-		.map_io		= s3c2440_map_io,
-		.init_clocks	= s3c2440_init_clocks,
-		.init_uarts	= s3c2440_init_uarts,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
 		.init		= s3c2440_init,
 		.name		= name_s3c2440a
 	},
 	{
+		.idcode		= 0x32440aaa,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c244x_map_io,
+		.init_clocks	= s3c244x_init_clocks,
+		.init_uarts	= s3c244x_init_uarts,
+		.init		= s3c2442_init,
+		.name		= name_s3c2442
+	},
+	{
+		.idcode		= 0x32412001,
+		.idmask		= 0xffffffff,
+		.map_io		= s3c2412_map_io,
+		.init_clocks	= s3c2412_init_clocks,
+		.init_uarts	= s3c2412_init_uarts,
+		.init		= s3c2412_init,
+		.name		= name_s3c2412,
+	},
+	{
 		.idcode		= 0x0,   /* S3C2400 doesn't have an idcode */
 		.idmask		= 0xffffffff,
 		.map_io		= s3c2400_map_io,
@@ -157,6 +182,24 @@
 
 static struct cpu_table *cpu;
 
+static unsigned long s3c24xx_read_idcode_v5(void)
+{
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+	return __raw_readl(S3C2412_GSTATUS1);
+#else
+	return 1UL;	/* don't look like an 2400 */
+#endif
+}
+
+static unsigned long s3c24xx_read_idcode_v4(void)
+{
+#ifndef CONFIG_CPU_S3C2400
+	return __raw_readl(S3C2410_GSTATUS1);
+#else
+	return 0UL;
+#endif
+}
+
 void __init s3c24xx_init_io(struct map_desc *mach_desc, int size)
 {
 	unsigned long idcode = 0x0;
@@ -164,9 +207,11 @@
 	/* initialise the io descriptors we need for initialisation */
 	iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc));
 
-#ifndef CONFIG_CPU_S3C2400
-	idcode = __raw_readl(S3C2410_GSTATUS1);
-#endif
+	if (cpu_architecture() >= CPU_ARCH_ARMv5) {
+		idcode = s3c24xx_read_idcode_v5();
+	} else {
+		idcode = s3c24xx_read_idcode_v4();
+	}
 
 	cpu = s3c_lookup_cpu(idcode);
 
@@ -175,13 +220,13 @@
 		panic("Unknown S3C24XX CPU");
 	}
 
+	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
+
 	if (cpu->map_io == NULL || cpu->init == NULL) {
 		printk(KERN_ERR "CPU %s support not enabled\n", cpu->name);
 		panic("Unsupported S3C24XX CPU");
 	}
 
-	printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
-
 	(cpu->map_io)(mach_desc, size);
 }
 
@@ -208,6 +253,49 @@
 		(cpu->init_clocks)(xtal);
 }
 
+/* uart management */
+
+static int nr_uarts __initdata = 0;
+
+static struct s3c2410_uartcfg uart_cfgs[3];
+
+/* s3c24xx_init_uartdevs
+ *
+ * copy the specified platform data and configuration into our central
+ * set of devices, before the data is thrown away after the init process.
+ *
+ * This also fills in the array passed to the serial driver for the
+ * early initialisation of the console.
+*/
+
+void __init s3c24xx_init_uartdevs(char *name,
+				  struct s3c24xx_uart_resources *res,
+				  struct s3c2410_uartcfg *cfg, int no)
+{
+	struct platform_device *platdev;
+	struct s3c2410_uartcfg *cfgptr = uart_cfgs;
+	struct s3c24xx_uart_resources *resp;
+	int uart;
+
+	memcpy(cfgptr, cfg, sizeof(struct s3c2410_uartcfg) * no);
+
+	for (uart = 0; uart < no; uart++, cfg++, cfgptr++) {
+		platdev = s3c24xx_uart_src[cfgptr->hwport];
+
+		resp = res + cfgptr->hwport;
+
+		s3c24xx_uart_devs[uart] = platdev;
+
+		platdev->name = name;
+		platdev->resource = resp->resources;
+		platdev->num_resources = resp->nr_resources;
+
+		platdev->dev.platform_data = cfgptr;
+	}
+
+	nr_uarts = no;
+}
+
 void __init s3c24xx_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
 	if (cpu == NULL)
@@ -232,6 +320,10 @@
 	if (ret != 0)
 		return ret;
 
+	ret = platform_add_devices(s3c24xx_uart_devs, nr_uarts);
+	if (ret != 0)
+		return ret;
+
 	if (board != NULL) {
 		struct platform_device **ptr = board->devices;
 		int i;
diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
index fc10677..b0ed9d2 100644
--- a/arch/arm/mach-s3c2410/cpu.h
+++ b/arch/arm/mach-s3c2410/cpu.h
@@ -31,6 +31,8 @@
 #define print_mhz(m) ((m) / MHZ), ((m / 1000) % 1000)
 
 /* forward declaration */
+struct s3c24xx_uart_resources;
+struct platform_device;
 struct s3c2410_uartcfg;
 struct map_desc;
 
@@ -44,6 +46,10 @@
 
 extern void s3c24xx_init_clocks(int xtal);
 
+extern void s3c24xx_init_uartdevs(char *name,
+				  struct s3c24xx_uart_resources *res,
+				  struct s3c2410_uartcfg *cfg, int no);
+
 /* the board structure is used at first initialsation time
  * to get info such as the devices to register for this
  * board. This is done because platfrom_add_devices() cannot
@@ -67,4 +73,7 @@
 
 /* system device classes */
 
+extern struct sysdev_class s3c2410_sysclass;
+extern struct sysdev_class s3c2412_sysclass;
 extern struct sysdev_class s3c2440_sysclass;
+extern struct sysdev_class s3c2442_sysclass;
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index ca09ba5..ad3845e 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -38,10 +38,86 @@
 #include <asm/arch/regs-serial.h>
 
 #include "devs.h"
+#include "cpu.h"
 
 /* Serial port registrations */
 
-struct platform_device *s3c24xx_uart_devs[3];
+static struct resource s3c2410_uart0_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART0,
+		.end   = S3C2410_PA_UART0 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX0,
+		.end   = IRQ_S3CUART_ERR0,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart1_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART1,
+		.end   = S3C2410_PA_UART1 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX1,
+		.end   = IRQ_S3CUART_ERR1,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct resource s3c2410_uart2_resource[] = {
+	[0] = {
+		.start = S3C2410_PA_UART2,
+		.end   = S3C2410_PA_UART2 + 0x3fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_S3CUART_RX2,
+		.end   = IRQ_S3CUART_ERR2,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+struct s3c24xx_uart_resources s3c2410_uart_resources[] __initdata = {
+	[0] = {
+		.resources	= s3c2410_uart0_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart0_resource),
+	},
+	[1] = {
+		.resources	= s3c2410_uart1_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart1_resource),
+	},
+	[2] = {
+		.resources	= s3c2410_uart2_resource,
+		.nr_resources	= ARRAY_SIZE(s3c2410_uart2_resource),
+	},
+};
+
+/* yart devices */
+
+static struct platform_device s3c24xx_uart_device0 = {
+	.id		= 0,
+};
+
+static struct platform_device s3c24xx_uart_device1 = {
+	.id		= 1,
+};
+
+static struct platform_device s3c24xx_uart_device2 = {
+	.id		= 2,
+};
+
+struct platform_device *s3c24xx_uart_src[3] = {
+	&s3c24xx_uart_device0,
+	&s3c24xx_uart_device1,
+	&s3c24xx_uart_device2,
+};
+
+struct platform_device *s3c24xx_uart_devs[3] = {
+};
 
 /* USB Host Controller */
 
diff --git a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
index 52c4bab..fa124ed 100644
--- a/arch/arm/mach-s3c2410/devs.h
+++ b/arch/arm/mach-s3c2410/devs.h
@@ -17,7 +17,15 @@
 #include <linux/config.h>
 #include <linux/platform_device.h>
 
+struct s3c24xx_uart_resources {
+	struct resource		*resources;
+	unsigned long		 nr_resources;
+};
+
+extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
+
 extern struct platform_device *s3c24xx_uart_devs[];
+extern struct platform_device *s3c24xx_uart_src[];
 
 extern struct platform_device s3c_device_usb;
 extern struct platform_device s3c_device_lcd;
diff --git a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
index 66d8c06..6822dc7 100644
--- a/arch/arm/mach-s3c2410/irq.c
+++ b/arch/arm/mach-s3c2410/irq.c
@@ -191,13 +191,9 @@
 	.ack	   = s3c_irq_ack,
 	.mask	   = s3c_irq_mask,
 	.unmask	   = s3c_irq_unmask,
-	.set_wake	   = s3c_irq_wake
+	.set_wake  = s3c_irq_wake
 };
 
-/* S3C2410_EINTMASK
- * S3C2410_EINTPEND
- */
-
 static void
 s3c_irqext_mask(unsigned int irqno)
 {
@@ -205,9 +201,9 @@
 
 	irqno -= EXTINT_OFF;
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 	mask |= ( 1UL << irqno);
-	__raw_writel(mask, S3C2410_EINTMASK);
+	__raw_writel(mask, S3C24XX_EINTMASK);
 
 	if (irqno <= (IRQ_EINT7 - EXTINT_OFF)) {
 		/* check to see if all need masking */
@@ -232,11 +228,11 @@
 	bit = 1UL << (irqno - EXTINT_OFF);
 
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 
-	__raw_writel(bit, S3C2410_EINTPEND);
+	__raw_writel(bit, S3C24XX_EINTPEND);
 
-	req = __raw_readl(S3C2410_EINTPEND);
+	req = __raw_readl(S3C24XX_EINTPEND);
 	req &= ~mask;
 
 	/* not sure if we should be acking the parent irq... */
@@ -257,9 +253,9 @@
 
 	irqno -= EXTINT_OFF;
 
-	mask = __raw_readl(S3C2410_EINTMASK);
+	mask = __raw_readl(S3C24XX_EINTMASK);
 	mask &= ~( 1UL << irqno);
-	__raw_writel(mask, S3C2410_EINTMASK);
+	__raw_writel(mask, S3C24XX_EINTMASK);
 
 	s3c_irq_unmask((irqno <= (IRQ_EINT7 - EXTINT_OFF)) ? IRQ_EINT4t7 : IRQ_EINT8t23);
 }
@@ -275,28 +271,28 @@
 	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
 	{
 		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C2410_EXTINT0;
+		extint_reg = S3C24XX_EXTINT0;
 		gpcon_offset = (irq - IRQ_EINT0) * 2;
 		extint_offset = (irq - IRQ_EINT0) * 4;
 	}
 	else if ((irq >= IRQ_EINT4) && (irq <= IRQ_EINT7))
 	{
 		gpcon_reg = S3C2410_GPFCON;
-		extint_reg = S3C2410_EXTINT0;
+		extint_reg = S3C24XX_EXTINT0;
 		gpcon_offset = (irq - (EXTINT_OFF)) * 2;
 		extint_offset = (irq - (EXTINT_OFF)) * 4;
 	}
 	else if ((irq >= IRQ_EINT8) && (irq <= IRQ_EINT15))
 	{
 		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C2410_EXTINT1;
+		extint_reg = S3C24XX_EXTINT1;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		extint_offset = (irq - IRQ_EINT8) * 4;
 	}
 	else if ((irq >= IRQ_EINT16) && (irq <= IRQ_EINT23))
 	{
 		gpcon_reg = S3C2410_GPGCON;
-		extint_reg = S3C2410_EXTINT2;
+		extint_reg = S3C24XX_EXTINT2;
 		gpcon_offset = (irq - IRQ_EINT8) * 2;
 		extint_offset = (irq - IRQ_EINT16) * 4;
 	} else
@@ -572,6 +568,23 @@
 	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 }
 
+static void
+s3c_irq_demux_extint(unsigned int irq,
+		     struct irqdesc *desc,
+		     struct pt_regs *regs)
+{
+	unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);
+	unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);
+
+	eintpnd &= ~eintmsk;
+
+	if (eintpnd) {
+		irq = fls(eintpnd);
+		irq += (IRQ_EINT4 - (4 + 1));
+
+		desc_handle_irq(irq, irq_desc + irq, regs);
+	}
+}
 
 /* s3c24xx_init_irq
  *
@@ -591,12 +604,12 @@
 
 	last = 0;
 	for (i = 0; i < 4; i++) {
-		pend = __raw_readl(S3C2410_EINTPEND);
+		pend = __raw_readl(S3C24XX_EINTPEND);
 
 		if (pend == 0 || pend == last)
 			break;
 
-		__raw_writel(pend, S3C2410_EINTPEND);
+		__raw_writel(pend, S3C24XX_EINTPEND);
 		printk("irq: clearing pending ext status %08x\n", (int)pend);
 		last = pend;
 	}
@@ -630,12 +643,14 @@
 
 	irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n");
 
-	for (irqno = IRQ_BATT_FLT; irqno <= IRQ_ADCPARENT; irqno++) {
+	for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) {
 		/* set all the s3c2410 internal irqs */
 
 		switch (irqno) {
 			/* deal with the special IRQs (cascaded) */
 
+		case IRQ_EINT4t7:
+		case IRQ_EINT8t23:
 		case IRQ_UART0:
 		case IRQ_UART1:
 		case IRQ_UART2:
@@ -659,12 +674,14 @@
 
 	/* setup the cascade irq handlers */
 
+	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint);
+	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint);
+
 	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
 	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
 	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
 	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
-
 	/* external interrupts */
 
 	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
diff --git a/arch/arm/mach-s3c2410/mach-anubis.c b/arch/arm/mach-s3c2410/mach-anubis.c
index cc97fbf..4a92d6f 100644
--- a/arch/arm/mach-s3c2410/mach-anubis.c
+++ b/arch/arm/mach-s3c2410/mach-anubis.c
@@ -131,7 +131,7 @@
 };
 
 
-static struct s3c2410_uartcfg anubis_uartcfgs[] = {
+static struct s3c2410_uartcfg anubis_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
@@ -239,6 +239,54 @@
 	.select_chip	= anubis_nand_select,
 };
 
+/* IDE channels */
+
+static struct resource anubis_ide0_resource[] = {
+	{
+		.start	= S3C2410_CS3,
+		.end	= S3C2410_CS3 + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= S3C2410_CS3 + (1<<26),
+		.end	= S3C2410_CS3 + (1<<26) + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_IDE0,
+		.end	= IRQ_IDE0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device anubis_device_ide0 = {
+	.name		= "simtec-ide",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(anubis_ide0_resource),
+	.resource	= anubis_ide0_resource,
+};
+
+static struct resource anubis_ide1_resource[] = {
+	{
+		.start	= S3C2410_CS4,
+		.end	= S3C2410_CS4 + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= S3C2410_CS4 + (1<<26),
+		.end	= S3C2410_CS4 + (1<<26) + (8*32) - 1,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= IRQ_IDE0,
+		.end	= IRQ_IDE0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+static struct platform_device anubis_device_ide1 = {
+	.name		= "simtec-ide",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(anubis_ide1_resource),
+	.resource	= anubis_ide1_resource,
+};
 
 /* Standard Anubis devices */
 
@@ -249,6 +297,8 @@
 	&s3c_device_i2c,
  	&s3c_device_rtc,
 	&s3c_device_nand,
+	&anubis_device_ide0,
+	&anubis_device_ide1,
 };
 
 static struct clk *anubis_clocks[] = {
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 995bb8a..947234d 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -208,7 +208,7 @@
 };
 
 
-static struct s3c2410_uartcfg bast_uartcfgs[] = {
+static struct s3c2410_uartcfg bast_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
index 646a3a5..aec431b 100644
--- a/arch/arm/mach-s3c2410/mach-h1940.c
+++ b/arch/arm/mach-s3c2410/mach-h1940.c
@@ -72,7 +72,7 @@
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg h1940_uartcfgs[] = {
+static struct s3c2410_uartcfg h1940_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-nexcoder.c b/arch/arm/mach-s3c2410/mach-nexcoder.c
index 07d0950..065a1d4 100644
--- a/arch/arm/mach-s3c2410/mach-nexcoder.c
+++ b/arch/arm/mach-s3c2410/mach-nexcoder.c
@@ -51,7 +51,7 @@
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg nexcoder_uartcfgs[] = {
+static struct s3c2410_uartcfg nexcoder_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c
index ae07875..858fd03 100644
--- a/arch/arm/mach-s3c2410/mach-osiris.c
+++ b/arch/arm/mach-s3c2410/mach-osiris.c
@@ -95,8 +95,7 @@
 	}
 };
 
-
-static struct s3c2410_uartcfg osiris_uartcfgs[] = {
+static struct s3c2410_uartcfg osiris_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
@@ -107,7 +106,7 @@
 		.clocks_size = ARRAY_SIZE(osiris_serial_clocks)
 	},
 	[1] = {
-		.hwport	     = 2,
+		.hwport	     = 1,
 		.flags	     = 0,
 		.ucon	     = UCON,
 		.ulcon	     = ULCON,
diff --git a/arch/arm/mach-s3c2410/mach-otom.c b/arch/arm/mach-s3c2410/mach-otom.c
index b39daed..c71673f 100644
--- a/arch/arm/mach-s3c2410/mach-otom.c
+++ b/arch/arm/mach-s3c2410/mach-otom.c
@@ -45,7 +45,7 @@
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG12 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg otom11_uartcfgs[] = {
+static struct s3c2410_uartcfg otom11_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
index 2db932d..25f7e9f 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c
@@ -65,7 +65,7 @@
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg smdk2410_uartcfgs[] = {
+static struct s3c2410_uartcfg smdk2410_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c
new file mode 100644
index 0000000..b7ef7d3
--- /dev/null
+++ b/arch/arm/mach-s3c2410/mach-smdk2413.c
@@ -0,0 +1,126 @@
+/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the
+ * loans of SMDK2413 to work with.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-lcd.h>
+
+#include <asm/arch/idle.h>
+#include <asm/arch/fb.h>
+
+#include "s3c2410.h"
+#include "s3c2412.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+#include "common-smdk.h"
+
+static struct map_desc smdk2413_iodesc[] __initdata = {
+};
+
+static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+static struct platform_device *smdk2413_devices[] __initdata = {
+	&s3c_device_usb,
+	//&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c24xx_board smdk2413_board __initdata = {
+	.devices       = smdk2413_devices,
+	.devices_count = ARRAY_SIZE(smdk2413_devices)
+};
+
+static void __init smdk2413_fixup(struct machine_desc *desc,
+				  struct tag *tags, char **cmdline,
+				  struct meminfo *mi)
+{
+	if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) {
+		mi->nr_banks=1;
+		mi->bank[0].start = 0x30000000;
+		mi->bank[0].size = SZ_64M;
+		mi->bank[0].node = 0;
+	}
+}
+
+static void __init smdk2413_map_io(void)
+{
+	s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
+	s3c24xx_init_clocks(12000000);
+	s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
+	s3c24xx_set_board(&smdk2413_board);
+}
+
+static void __init smdk2413_machine_init(void)
+{
+	smdk_machine_init();
+}
+
+MACHINE_START(S3C2413, "SMDK2413")
+	/* Maintainer: Ben Dooks <ben@fluff.org> */
+	.phys_io	= S3C2410_PA_UART,
+	.io_pg_offst	= (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
+	.boot_params	= S3C2410_SDRAM_PA + 0x100,
+
+	.fixup		= smdk2413_fixup,
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2413_map_io,
+	.init_machine	= smdk2413_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
index 5fffd1d..d661c6b 100644
--- a/arch/arm/mach-s3c2410/mach-smdk2440.c
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c
@@ -86,7 +86,7 @@
 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
 
-static struct s3c2410_uartcfg smdk2440_uartcfgs[] = {
+static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 785fc9c..d18efb2 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -166,7 +166,7 @@
 	}
 };
 
-static struct s3c2410_uartcfg vr1000_uartcfgs[] = {
+static struct s3c2410_uartcfg vr1000_uartcfgs[] __initdata = {
 	[0] = {
 		.hwport	     = 0,
 		.flags	     = 0,
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
index 4c7ccef..7b24456 100644
--- a/arch/arm/mach-s3c2410/pm-simtec.c
+++ b/arch/arm/mach-s3c2410/pm-simtec.c
@@ -48,7 +48,8 @@
 
 	/* check which machine we are running on */
 
-	if (!machine_is_bast() && !machine_is_vr1000() && !machine_is_anubis())
+	if (!machine_is_bast() && !machine_is_vr1000() &&
+	    !machine_is_anubis() && !machine_is_osiris())
 		return 0;
 
 	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
diff --git a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
index fe57d96..43e9a55 100644
--- a/arch/arm/mach-s3c2410/pm.c
+++ b/arch/arm/mach-s3c2410/pm.c
@@ -58,7 +58,11 @@
 
 /* cache functions from arch/arm/mm/proc-arm920.S */
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 extern void arm920_flush_kern_cache_all(void);
+#else
+static void arm920_flush_kern_cache_all(void) { }
+#endif
 
 #define PFX "s3c24xx-pm: "
 
diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c
new file mode 100644
index 0000000..9971866
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2410-clock.c
@@ -0,0 +1,271 @@
+/* linux/arch/arm/mach-s3c2410/clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2410,S3C2440,S3C2442 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+int s3c2410_clkcon_enable(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2410_CLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	/* ensure none of the special function bits set */
+	clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
+
+	return 0;
+}
+
+static int s3c2410_upll_enable(struct clk *clk, int enable)
+{
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long orig = clkslow;
+
+	if (enable)
+		clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
+	else
+		clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
+
+	__raw_writel(clkslow, S3C2410_CLKSLOW);
+
+	/* if we started the UPLL, then allow to settle */
+
+	if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
+		udelay(200);
+
+	return 0;
+}
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2410_clkcon_enable,
+		.ctrlbit	= S3C2410_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+	},
+};
+
+/* s3c2410_baseclk_add()
+ *
+ * Add all the clocks used by the s3c2410 or compatible CPUs
+ * such as the S3C2440 and S3C2442.
+ *
+ * We cannot use a system device as we are needed before any
+ * of the init-calls that initialise the devices are actually
+ * done.
+*/
+
+int __init s3c2410_baseclk_add(void)
+{
+	unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	struct clk *xtal;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2410_upll_enable;
+
+	if (s3c24xx_register_clock(&clk_usb_bus) < 0)
+		printk(KERN_ERR "failed to register usb bus clock\n");
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
+
+	/* install (and disable) the clocks we do not need immediately */
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		s3c2410_clkcon_enable(clkp, 0);
+	}
+
+	/* show the clock-slow value */
+
+	xtal = clk_get(NULL, "xtal");
+
+	printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
+	       print_mhz(clk_get_rate(xtal) /
+			 ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
+	       (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
+	       (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
+	       (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c2410-gpio.c b/arch/arm/mach-s3c2410/s3c2410-gpio.c
index d5e1cae..471a714 100644
--- a/arch/arm/mach-s3c2410/s3c2410-gpio.c
+++ b/arch/arm/mach-s3c2410/s3c2410-gpio.c
@@ -18,9 +18,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Changelog
- *	15-Jan-2006  LCVR  Splitted from gpio.c
  */
 
 #include <linux/kernel.h>
@@ -38,7 +35,7 @@
 int s3c2410_gpio_irqfilter(unsigned int pin, unsigned int on,
 			   unsigned int config)
 {
-	void __iomem *reg = S3C2410_EINFLT0;
+	void __iomem *reg = S3C24XX_EINFLT0;
 	unsigned long flags;
 	unsigned long val;
 
@@ -47,7 +44,7 @@
 
 	config &= 0xff;
 
-	pin -= S3C2410_GPG8_EINT16;
+	pin -= S3C2410_GPG8;
 	reg += pin & ~3;
 
 	local_irq_save(flags);
@@ -61,10 +58,10 @@
 
 	/* update filter enable */
 
-	val = __raw_readl(S3C2410_EXTINT2);
+	val = __raw_readl(S3C24XX_EXTINT2);
 	val &= ~(1 << ((pin * 4) + 3));
 	val |= on << ((pin * 4) + 3);
-	__raw_writel(val, S3C2410_EXTINT2);
+	__raw_writel(val, S3C24XX_EXTINT2);
 
 	local_irq_restore(flags);
 
@@ -75,7 +72,7 @@
 
 int s3c2410_gpio_getirq(unsigned int pin)
 {
-	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15_EINT23)
+	if (pin < S3C2410_GPF0 || pin > S3C2410_GPG15)
 		return -1;	/* not valid interrupts */
 
 	if (pin < S3C2410_GPG0 && pin > S3C2410_GPF7)
diff --git a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
index 0a2013a..a110cff 100644
--- a/arch/arm/mach-s3c2410/s3c2410.c
+++ b/arch/arm/mach-s3c2410/s3c2410.c
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/sysdev.h>
 #include <linux/platform_device.h>
 
 #include <asm/mach/arch.h>
@@ -42,6 +43,7 @@
 
 #include "s3c2410.h"
 #include "cpu.h"
+#include "devs.h"
 #include "clock.h"
 
 /* Initial IO mappings */
@@ -55,93 +57,13 @@
 	IODESC_ENT(WATCHDOG),
 };
 
-static struct resource s3c_uart0_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART0,
-		.end   = S3C2410_PA_UART0 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX0,
-		.end   = IRQ_S3CUART_ERR0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static struct resource s3c_uart1_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART1,
-		.end   = S3C2410_PA_UART1 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX1,
-		.end   = IRQ_S3CUART_ERR1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c_uart2_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART2,
-		.end   = S3C2410_PA_UART2 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX2,
-		.end   = IRQ_S3CUART_ERR2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
 /* our uart devices */
 
-static struct platform_device s3c_uart0 = {
-	.name		  = "s3c2410-uart",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_uart0_resource),
-	.resource	  = s3c_uart0_resource,
-};
-
-
-static struct platform_device s3c_uart1 = {
-	.name		  = "s3c2410-uart",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_uart1_resource),
-	.resource	  = s3c_uart1_resource,
-};
-
-static struct platform_device s3c_uart2 = {
-	.name		  = "s3c2410-uart",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s3c_uart2_resource),
-	.resource	  = s3c_uart2_resource,
-};
-
-static struct platform_device *uart_devices[] __initdata = {
-	&s3c_uart0,
-	&s3c_uart1,
-	&s3c_uart2
-};
-
-static int s3c2410_uart_count = 0;
-
 /* uart registration process */
 
 void __init s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no)
 {
-	struct platform_device *platdev;
-	int uart;
-
-	for (uart = 0; uart < no; uart++, cfg++) {
-		platdev = uart_devices[cfg->hwport];
-
-		s3c24xx_uart_devs[uart] = platdev;
-		platdev->dev.platform_data = cfg;
-	}
-
-	s3c2410_uart_count = uart;
+	s3c24xx_init_uartdevs("s3c2410-uart", s3c2410_uart_resources, cfg, no);
 }
 
 /* s3c2410_map_io
@@ -187,11 +109,33 @@
 	 */
 
 	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2410_baseclk_add();
 }
 
+struct sysdev_class s3c2410_sysclass = {
+	set_kset_name("s3c2410-core"),
+};
+
+static struct sys_device s3c2410_sysdev = {
+	.cls		= &s3c2410_sysclass,
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2410_core_init(void)
+{
+	return sysdev_class_register(&s3c2410_sysclass);
+}
+
+core_initcall(s3c2410_core_init);
+
 int __init s3c2410_init(void)
 {
 	printk("S3C2410: Initialising architecture\n");
 
-	return platform_add_devices(s3c24xx_uart_devs, s3c2410_uart_count);
+	return sysdev_register(&s3c2410_sysdev);
 }
diff --git a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h
index 4d5312a..73f1a24 100644
--- a/arch/arm/mach-s3c2410/s3c2410.h
+++ b/arch/arm/mach-s3c2410/s3c2410.h
@@ -29,6 +29,8 @@
 
 extern void s3c2410_init_clocks(int xtal);
 
+extern  int s3c2410_baseclk_add(void);
+
 #else
 #define s3c2410_init_clocks NULL
 #define s3c2410_init_uarts NULL
diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c
new file mode 100644
index 0000000..c95ed3e
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412-clock.c
@@ -0,0 +1,711 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2412,S3C2413 Clock control support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* We currently have to assume that the system is running
+ * from the XTPll input, and that all ***REFCLKs are being
+ * fed from it, as we cannot read the state of OM[4] from
+ * software.
+ *
+ * It would be possible for each board initialisation to
+ * set the correct muxing at initialisation
+*/
+
+int s3c2412_clkcon_enable(struct clk *clk, int enable)
+{
+	unsigned int clocks = clk->ctrlbit;
+	unsigned long clkcon;
+
+	clkcon = __raw_readl(S3C2410_CLKCON);
+
+	if (enable)
+		clkcon |= clocks;
+	else
+		clkcon &= ~clocks;
+
+	__raw_writel(clkcon, S3C2410_CLKCON);
+
+	return 0;
+}
+
+static int s3c2412_upll_enable(struct clk *clk, int enable)
+{
+	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+	unsigned long orig = upllcon;
+
+	if (!enable)
+		upllcon |= S3C2412_PLLCON_OFF;
+	else
+		upllcon &= ~S3C2412_PLLCON_OFF;
+
+	__raw_writel(upllcon, S3C2410_UPLLCON);
+
+	/* allow ~150uS for the PLL to settle and lock */
+
+	if (enable && (orig & S3C2412_PLLCON_OFF))
+		udelay(150);
+
+	return 0;
+}
+
+/* clock selections */
+
+/* CPU EXTCLK input */
+static struct clk clk_ext = {
+	.name		= "extclk",
+	.id		= -1,
+};
+
+static struct clk clk_erefclk = {
+	.name		= "erefclk",
+	.id		= -1,
+};
+
+static struct clk clk_urefclk = {
+	.name		= "urefclk",
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_urefclk)
+		clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_usysclk = {
+	.name		= "usysclk",
+	.id		= -1,
+	.parent		= &clk_xtal,
+	.set_parent	= s3c2412_setparent_usysclk,
+};
+
+static struct clk clk_mrefclk = {
+	.name		= "mrefclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static struct clk clk_mdivclk = {
+	.name		= "mdivclk",
+	.parent		= &clk_xtal,
+	.id		= -1,
+};
+
+static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_USBCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+	if (div > 2)
+		div = 2;
+
+	return parent_rate / div;
+}
+
+static unsigned long s3c2412_getrate_usbsrc(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1);
+}
+
+static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_usbsrc(clk, rate);
+
+	if ((parent_rate / rate) == 2)
+		clkdivn |= S3C2412_CLKDIVN_USB48DIV;
+	else
+		clkdivn &= ~S3C2412_CLKDIVN_USB48DIV;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_usbsrc = {
+	.name		= "usbsrc",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_usbsrc,
+	.set_rate	= s3c2412_setrate_usbsrc,
+	.round_rate	= s3c2412_roundrate_usbsrc,
+	.set_parent	= s3c2412_setparent_usbsrc,
+};
+
+static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_mdivclk)
+		clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else if (parent == &clk_upll)
+		clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static struct clk clk_msysclk = {
+	.name		= "msysclk",
+	.id		= -1,
+	.set_parent	= s3c2412_setparent_msysclk,
+};
+
+/* these next clocks have an divider immediately after them,
+ * so we can register them with their divider and leave out the
+ * intermediate clock stage
+*/
+static unsigned long s3c2412_roundrate_clksrc(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	/* note, we remove the +/- 1 calculations as they cancel out */
+
+	div = (rate / parent_rate);
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / div;
+}
+
+static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_uart(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_UARTDIV_MASK;
+	div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_uart = {
+	.name		= "uartclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_uart,
+	.set_rate	= s3c2412_setrate_uart,
+	.set_parent	= s3c2412_setparent_uart,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_erefclk)
+		clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL;
+	else if (parent == &clk_mpll)
+		clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+
+static unsigned long s3c2412_getrate_i2s(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_I2SDIV_MASK;
+	div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_i2s = {
+	.name		= "i2sclk",
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_i2s,
+	.set_rate	= s3c2412_setrate_i2s,
+	.set_parent	= s3c2412_setparent_i2s,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+
+	if (parent == &clk_usysclk)
+		clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK;
+	else if (parent == &clk_h)
+		clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK;
+	else
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	__raw_writel(clksrc, S3C2412_CLKSRC);
+	return 0;
+}
+static unsigned long s3c2412_getrate_cam(struct clk *clk)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long div = __raw_readl(S3C2410_CLKDIVN);
+
+	div &= S3C2412_CLKDIVN_CAMDIV_MASK;
+	div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	return parent_rate / (div + 1);
+}
+
+static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN);
+
+	rate = s3c2412_roundrate_clksrc(clk, rate);
+
+	clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK;
+	clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT;
+
+	__raw_writel(clkdivn, S3C2410_CLKDIVN);
+	return 0;
+}
+
+static struct clk clk_cam = {
+	.name		= "camif-upll",	/* same as 2440 name */
+	.id		= -1,
+	.get_rate	= s3c2412_getrate_cam,
+	.set_rate	= s3c2412_setrate_cam,
+	.set_parent	= s3c2412_setparent_cam,
+	.round_rate	= s3c2412_roundrate_clksrc,
+};
+
+/* standard clock definitions */
+
+static struct clk init_clocks_disable[] = {
+	{
+		.name		= "nand",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_NAND,
+	}, {
+		.name		= "sdi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SDI,
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_ADC,
+	}, {
+		.name		= "i2c",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIC,
+	}, {
+		.name		= "iis",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_IIS,
+	}, {
+		.name		= "spi",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_SPI,
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "dma",
+		.id		= 0,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA0,
+	}, {
+		.name		= "dma",
+		.id		= 1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA1,
+	}, {
+		.name		= "dma",
+		.id		= 2,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA2,
+	}, {
+		.name		= "dma",
+		.id		= 3,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_DMA3,
+	}, {
+		.name		= "lcd",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_LCDC,
+	}, {
+		.name		= "gpio",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_GPIO,
+	}, {
+		.name		= "usb-host",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBH,
+	}, {
+		.name		= "usb-device",
+		.id		= -1,
+		.parent		= &clk_h,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USBD,
+	}, {
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_PWMT,
+	}, {
+		.name		= "uart",
+		.id		= 0,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART0,
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART1,
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_UART2,
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.parent		= &clk_p,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_RTC,
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_p,
+		.ctrlbit	= 0,
+	}, {
+		.name		= "usb-bus-gadget",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_DEV48,
+	}, {
+		.name		= "usb-bus-host",
+		.id		= -1,
+		.parent		= &clk_usb_bus,
+		.enable		= s3c2412_clkcon_enable,
+		.ctrlbit	= S3C2412_CLKCON_USB_HOST48,
+	}
+};
+
+/* clocks to add where we need to check their parentage */
+
+struct clk_init {
+	struct clk	*clk;
+	unsigned int	 bit;
+	struct clk	*src_0;
+	struct clk	*src_1;
+};
+
+struct clk_init clks_src[] __initdata = {
+	{
+		.clk	= &clk_usysclk,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_urefclk,
+		.src_1	= &clk_upll,
+	}, {
+		.clk	= &clk_i2s,
+		.bit	= S3C2412_CLKSRC_I2SCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_cam,
+		.bit	= S3C2412_CLKSRC_CAMCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	}, {
+		.clk	= &clk_msysclk,
+		.bit	= S3C2412_CLKSRC_MSYSCLK_MPLL,
+		.src_0	= &clk_mdivclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_uart,
+		.bit	= S3C2412_CLKSRC_UARTCLK_MPLL,
+		.src_0	= &clk_erefclk,
+		.src_1	= &clk_mpll,
+	}, {
+		.clk	= &clk_usbsrc,
+		.bit	= S3C2412_CLKSRC_USBCLK_HCLK,
+		.src_0	= &clk_usysclk,
+		.src_1	= &clk_h,
+	},
+};
+
+/* s3c2412_clk_initparents
+ *
+ * Initialise the parents for the clocks that we get at start-time
+*/
+
+static void __init s3c2412_clk_initparents(void)
+{
+	unsigned long clksrc = __raw_readl(S3C2412_CLKSRC);
+	struct clk_init *cip = clks_src;
+	struct clk *src;
+	int ptr;
+	int ret;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) {
+		ret = s3c24xx_register_clock(cip->clk);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       cip->clk->name, ret);
+		}
+
+		src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0;
+
+		printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name);
+		clk_set_parent(cip->clk, src);
+	}
+}
+
+/* clocks to add straight away */
+
+struct clk *clks[] __initdata = {
+	&clk_ext,
+	&clk_usb_bus,
+	&clk_erefclk,
+	&clk_urefclk,
+	&clk_mrefclk,
+};
+
+int __init s3c2412_baseclk_add(void)
+{
+	unsigned long clkcon  = __raw_readl(S3C2410_CLKCON);
+	struct clk *clkp;
+	int ret;
+	int ptr;
+
+	clk_upll.enable = s3c2412_upll_enable;
+	clk_usb_bus.parent = &clk_usbsrc;
+	clk_usb_bus.rate = 0x0;
+
+	s3c2412_clk_initparents();
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) {
+		clkp = clks[ptr];
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* ensure usb bus clock is within correct rate of 48MHz */
+
+	if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) {
+		printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n");
+
+		/* for the moment, let's use the UPLL, and see if we can
+		 * get 48MHz */
+
+		clk_set_parent(&clk_usysclk, &clk_upll);
+		clk_set_parent(&clk_usbsrc, &clk_usysclk);
+		clk_set_rate(&clk_usbsrc, 48*1000*1000);
+	}
+
+	printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n",
+	       (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on",
+	       print_mhz(clk_get_rate(&clk_upll)),
+	       print_mhz(clk_get_rate(&clk_usb_bus)));
+
+	/* register clocks from clock array */
+
+	clkp = init_clocks;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
+		/* ensure that we note the clock state */
+
+		clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+	}
+
+	/* We must be careful disabling the clocks we are not intending to
+	 * be using at boot time, as subsytems such as the LCD which do
+	 * their own DMA requests to the bus can cause the system to lockup
+	 * if they where in the middle of requesting bus access.
+	 *
+	 * Disabling the LCD clock if the LCD is active is very dangerous,
+	 * and therefore the bootloader should be careful to not enable
+	 * the LCD clock if it is not needed.
+	*/
+
+	/* install (and disable) the clocks we do not need immediately */
+
+	clkp = init_clocks_disable;
+	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
+
+		ret = s3c24xx_register_clock(clkp);
+		if (ret < 0) {
+			printk(KERN_ERR "Failed to register clock %s (%d)\n",
+			       clkp->name, ret);
+		}
+
+		s3c2412_clkcon_enable(clkp, 0);
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c
new file mode 100644
index 0000000..e24ffd5
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412.c
@@ -0,0 +1,195 @@
+/* linux/arch/arm/mach-s3c2410/s3c2412.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Modifications:
+ *     16-May-2003 BJD  Created initial version
+ *     16-Aug-2003 BJD  Fixed header files and copyright, added URL
+ *     05-Sep-2003 BJD  Moved to kernel v2.6
+ *     18-Jan-2004 BJD  Added serial port configuration
+ *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
+ *     28-Sep-2004 BJD  Updates for new serial port bits
+ *     04-Nov-2004 BJD  Updated UART configuration process
+ *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
+ *     13-Aug-2005 DA   Removed UART from initial I/O mappings
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2412.h"
+#include "cpu.h"
+#include "devs.h"
+#include "clock.h"
+#include "pm.h"
+
+#ifndef CONFIG_CPU_S3C2412_ONLY
+void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO;
+#endif
+
+/* Initial IO mappings */
+
+static struct map_desc s3c2412_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(LCD),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(ADC),
+	IODESC_ENT(WATCHDOG),
+};
+
+/* uart registration process */
+
+void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no);
+
+	/* rename devices that are s3c2412/s3c2413 specific */
+	s3c_device_sdi.name  = "s3c2412-sdi";
+	s3c_device_nand.name = "s3c2412-nand";
+}
+
+/* s3c2412_map_io
+ *
+ * register the standard cpu IO areas, and any passed in from the
+ * machine specific initialisation.
+*/
+
+void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size)
+{
+	/* move base of IO */
+
+	s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10;
+
+	/* register our io-tables */
+
+	iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc));
+	iotable_init(mach_desc, mach_size);
+}
+
+void __init s3c2412_init_clocks(int xtal)
+{
+	unsigned long tmp;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long pclk;
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2);
+
+	tmp = __raw_readl(S3C2410_CLKDIVN);
+
+	/* work out clock scalings */
+
+	hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1);
+	hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1);
+	pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1);
+
+	/* print brieft summary of clocks, etc */
+
+	printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them
+	 */
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2412_baseclk_add();
+}
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2412 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+#ifdef CONFIG_PM
+static struct sleep_save s3c2412_sleep[] = {
+	SAVE_ITEM(S3C2412_DSC0),
+	SAVE_ITEM(S3C2412_DSC1),
+	SAVE_ITEM(S3C2413_GPJDAT),
+	SAVE_ITEM(S3C2413_GPJCON),
+	SAVE_ITEM(S3C2413_GPJUP),
+
+	/* save the sleep configuration anyway, just in case these
+	 * get damaged during wakeup */
+
+	SAVE_ITEM(S3C2412_GPBSLPCON),
+	SAVE_ITEM(S3C2412_GPCSLPCON),
+	SAVE_ITEM(S3C2412_GPDSLPCON),
+	SAVE_ITEM(S3C2412_GPESLPCON),
+	SAVE_ITEM(S3C2412_GPFSLPCON),
+	SAVE_ITEM(S3C2412_GPGSLPCON),
+	SAVE_ITEM(S3C2412_GPHSLPCON),
+	SAVE_ITEM(S3C2413_GPJSLPCON),
+};
+
+static int s3c2412_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+static int s3c2412_resume(struct sys_device *dev)
+{
+	s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
+	return 0;
+}
+
+#else
+#define s3c2412_suspend NULL
+#define s3c2412_resume  NULL
+#endif
+
+struct sysdev_class s3c2412_sysclass = {
+	set_kset_name("s3c2412-core"),
+	.suspend	= s3c2412_suspend,
+	.resume		= s3c2412_resume
+};
+
+static int __init s3c2412_core_init(void)
+{
+	return sysdev_class_register(&s3c2412_sysclass);
+}
+
+core_initcall(s3c2412_core_init);
+
+static struct sys_device s3c2412_sysdev = {
+	.cls		= &s3c2412_sysclass,
+};
+
+int __init s3c2412_init(void)
+{
+	printk("S3C2412: Initialising architecture\n");
+
+	return sysdev_register(&s3c2412_sysdev);
+}
diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h
new file mode 100644
index 0000000..c6e5603
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2412.h
@@ -0,0 +1,29 @@
+/* arch/arm/mach-s3c2410/s3c2412.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2412 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2412
+
+extern  int s3c2412_init(void);
+
+extern void s3c2412_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c2412_init_clocks(int xtal);
+
+extern  int s3c2412_baseclk_add(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c
index d7a30ed..1579686 100644
--- a/arch/arm/mach-s3c2410/s3c2440-clock.c
+++ b/arch/arm/mach-s3c2410/s3c2440-clock.c
@@ -91,7 +91,7 @@
 static struct clk s3c2440_clk_cam = {
 	.name		= "camif",
 	.id		= -1,
-	.enable		= s3c24xx_clkcon_enable,
+	.enable		= s3c2410_clkcon_enable,
 	.ctrlbit	= S3C2440_CLKCON_CAMERA,
 };
 
@@ -105,7 +105,7 @@
 static struct clk s3c2440_clk_ac97 = {
 	.name		= "ac97",
 	.id		= -1,
-	.enable		= s3c24xx_clkcon_enable,
+	.enable		= s3c2410_clkcon_enable,
 	.ctrlbit	= S3C2440_CLKCON_CAMERA,
 };
 
diff --git a/arch/arm/mach-s3c2410/s3c2440-irq.c b/arch/arm/mach-s3c2410/s3c2440-irq.c
index 278d004..acfe387 100644
--- a/arch/arm/mach-s3c2410/s3c2440-irq.c
+++ b/arch/arm/mach-s3c2410/s3c2440-irq.c
@@ -100,73 +100,12 @@
 	.ack	    = s3c_irq_wdtac97_ack,
 };
 
-/* camera irq */
-
-static void s3c_irq_demux_cam(unsigned int irq,
-			      struct irqdesc *desc,
-			      struct pt_regs *regs)
-{
-	unsigned int subsrc, submsk;
-	struct irqdesc *mydesc;
-
-	/* read the current pending interrupts, and the mask
-	 * for what it is available */
-
-	subsrc = __raw_readl(S3C2410_SUBSRCPND);
-	submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-	subsrc &= ~submsk;
-	subsrc >>= 11;
-	subsrc &= 3;
-
-	if (subsrc != 0) {
-		if (subsrc & 1) {
-			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
-			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
-		}
-		if (subsrc & 2) {
-			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
-			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
-		}
-	}
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-
-static void
-s3c_irq_cam_mask(unsigned int irqno)
-{
-	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
-}
-
-static void
-s3c_irq_cam_unmask(unsigned int irqno)
-{
-	s3c_irqsub_unmask(irqno, INTMSK_CAM);
-}
-
-static void
-s3c_irq_cam_ack(unsigned int irqno)
-{
-	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
-}
-
-static struct irqchip s3c_irq_cam = {
-	.mask	    = s3c_irq_cam_mask,
-	.unmask	    = s3c_irq_cam_unmask,
-	.ack	    = s3c_irq_cam_ack,
-};
-
 static int s3c2440_irq_add(struct sys_device *sysdev)
 {
 	unsigned int irqno;
 
 	printk("S3C2440: IRQ Support\n");
 
-	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_NFCON, do_level_IRQ);
-	set_irq_flags(IRQ_NFCON, IRQF_VALID);
-
 	/* add new chained handler for wdt, ac7 */
 
 	set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
@@ -179,18 +118,6 @@
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
-	/* add chained handler for camera */
-
-	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_CAM, do_level_IRQ);
-	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
-
-	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
-		set_irq_chip(irqno, &s3c_irq_cam);
-		set_irq_handler(irqno, do_level_IRQ);
-		set_irq_flags(irqno, IRQF_VALID);
-	}
-
 	return 0;
 }
 
@@ -198,10 +125,10 @@
 	.add	= s3c2440_irq_add,
 };
 
-static int s3c24xx_irq_driver(void)
+static int s3c2440_irq_init(void)
 {
 	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
 }
 
-arch_initcall(s3c24xx_irq_driver);
+arch_initcall(s3c2440_irq_init);
 
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
index b7fe6d9..0ab50f4 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2410/s3c2440.c
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/s3c2440.c
  *
- * Copyright (c) 2004-2005 Simtec Electronics
+ * Copyright (c) 2004-2006 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * Samsung S3C2440 Mobile CPU support
@@ -8,16 +8,6 @@
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
- *
- * Modifications:
- *	24-Aug-2004 BJD  Start of s3c2440 support
- *	12-Oct-2004 BJD	 Moved clock info out to clock.c
- *	01-Nov-2004 BJD  Fixed clock build code
- *	09-Nov-2004 BJD  Added sysdev for power management
- *	04-Nov-2004 BJD  New serial registration
- *	15-Nov-2004 BJD  Rename the i2c device for the s3c2440
- *	14-Jan-2005 BJD  Moved clock init code into seperate function
- *	14-Jan-2005 BJD  Removed un-used clock bits
 */
 
 #include <linux/kernel.h>
@@ -50,234 +40,20 @@
 #include "cpu.h"
 #include "pm.h"
 
-
-static struct map_desc s3c2440_iodesc[] __initdata = {
-	IODESC_ENT(USBHOST),
-	IODESC_ENT(CLKPWR),
-	IODESC_ENT(LCD),
-	IODESC_ENT(TIMER),
-	IODESC_ENT(ADC),
-	IODESC_ENT(WATCHDOG),
-};
-
-static struct resource s3c_uart0_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART0,
-		.end   = S3C2410_PA_UART0 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX0,
-		.end   = IRQ_S3CUART_ERR0,
-		.flags = IORESOURCE_IRQ,
-	}
-
-};
-
-static struct resource s3c_uart1_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART1,
-		.end   = S3C2410_PA_UART1 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX1,
-		.end   = IRQ_S3CUART_ERR1,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct resource s3c_uart2_resource[] = {
-	[0] = {
-		.start = S3C2410_PA_UART2,
-		.end   = S3C2410_PA_UART2 + 0x3fff,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = {
-		.start = IRQ_S3CUART_RX2,
-		.end   = IRQ_S3CUART_ERR2,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-/* our uart devices */
-
-static struct platform_device s3c_uart0 = {
-	.name		  = "s3c2440-uart",
-	.id		  = 0,
-	.num_resources	  = ARRAY_SIZE(s3c_uart0_resource),
-	.resource	  = s3c_uart0_resource,
-};
-
-static struct platform_device s3c_uart1 = {
-	.name		  = "s3c2440-uart",
-	.id		  = 1,
-	.num_resources	  = ARRAY_SIZE(s3c_uart1_resource),
-	.resource	  = s3c_uart1_resource,
-};
-
-static struct platform_device s3c_uart2 = {
-	.name		  = "s3c2440-uart",
-	.id		  = 2,
-	.num_resources	  = ARRAY_SIZE(s3c_uart2_resource),
-	.resource	  = s3c_uart2_resource,
-};
-
-static struct platform_device *uart_devices[] __initdata = {
-	&s3c_uart0,
-	&s3c_uart1,
-	&s3c_uart2
-};
-
-/* uart initialisation */
-
-static int __initdata s3c2440_uart_count;
-
-void __init s3c2440_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	struct platform_device *platdev;
-	int uart;
-
-	for (uart = 0; uart < no; uart++, cfg++) {
-		platdev = uart_devices[cfg->hwport];
-
-		s3c24xx_uart_devs[uart] = platdev;
-		platdev->dev.platform_data = cfg;
-	}
-
-	s3c2440_uart_count = uart;
-}
-
-
-#ifdef CONFIG_PM
-
-static struct sleep_save s3c2440_sleep[] = {
-	SAVE_ITEM(S3C2440_DSC0),
-	SAVE_ITEM(S3C2440_DSC1),
-	SAVE_ITEM(S3C2440_GPJDAT),
-	SAVE_ITEM(S3C2440_GPJCON),
-	SAVE_ITEM(S3C2440_GPJUP)
-};
-
-static int s3c2440_suspend(struct sys_device *dev, pm_message_t state)
-{
-	s3c2410_pm_do_save(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
-	return 0;
-}
-
-static int s3c2440_resume(struct sys_device *dev)
-{
-	s3c2410_pm_do_restore(s3c2440_sleep, ARRAY_SIZE(s3c2440_sleep));
-	return 0;
-}
-
-#else
-#define s3c2440_suspend NULL
-#define s3c2440_resume  NULL
-#endif
-
-struct sysdev_class s3c2440_sysclass = {
-	set_kset_name("s3c2440-core"),
-	.suspend	= s3c2440_suspend,
-	.resume		= s3c2440_resume
-};
-
 static struct sys_device s3c2440_sysdev = {
 	.cls		= &s3c2440_sysclass,
 };
 
-void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
+int __init s3c2440_init(void)
 {
-	/* register our io-tables */
-
-	iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
-	iotable_init(mach_desc, size);
-
-	/* rename any peripherals used differing from the s3c2410 */
-
-	s3c_device_i2c.name  = "s3c2440-i2c";
-	s3c_device_nand.name = "s3c2440-nand";
+	printk("S3C2440: Initialising architecture\n");
 
 	/* change irq for watchdog */
 
 	s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
 	s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
-}
 
-void __init s3c2440_init_clocks(int xtal)
-{
-	unsigned long clkdiv;
-	unsigned long camdiv;
-	unsigned long hclk, fclk, pclk;
-	int hdiv = 1;
+	/* register our system device for everything else */
 
-	/* now we've got our machine bits initialised, work out what
-	 * clocks we've got */
-
-	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
-
-	clkdiv = __raw_readl(S3C2410_CLKDIVN);
-	camdiv = __raw_readl(S3C2440_CAMDIVN);
-
-	/* work out clock scalings */
-
-	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
-	case S3C2440_CLKDIVN_HDIVN_1:
-		hdiv = 1;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_2:
-		hdiv = 2;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_4_8:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
-		break;
-
-	case S3C2440_CLKDIVN_HDIVN_3_6:
-		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
-		break;
-	}
-
-	hclk = fclk / hdiv;
-	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
-
-	/* print brief summary of clocks, etc */
-
-	printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
-
-	/* initialise the clocks here, to allow other things like the
-	 * console to use them, and to add new ones after the initialisation
-	 */
-
-	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
-}
-
-/* need to register class before we actually register the device, and
- * we also need to ensure that it has been initialised before any of the
- * drivers even try to use it (even if not on an s3c2440 based system)
- * as a driver which may support both 2410 and 2440 may try and use it.
-*/
-
-static int __init s3c2440_core_init(void)
-{
-	return sysdev_class_register(&s3c2440_sysclass);
-}
-
-core_initcall(s3c2440_core_init);
-
-int __init s3c2440_init(void)
-{
-	int ret;
-
-	printk("S3C2440: Initialising architecture\n");
-
-	ret = sysdev_register(&s3c2440_sysdev);
-	if (ret != 0)
-		printk(KERN_ERR "failed to register sysdev for s3c2440\n");
-	else
-		ret = platform_add_devices(s3c24xx_uart_devs, s3c2440_uart_count);
-
-	return ret;
+	return sysdev_register(&s3c2440_sysdev);
 }
diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c
new file mode 100644
index 0000000..d9f54b5
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2442-clock.c
@@ -0,0 +1,171 @@
+/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://armlinux.simtec.co.uk/
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * S3C2442 Clock support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+
+#include <asm/hardware.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/arch/regs-clock.h>
+
+#include "clock.h"
+#include "cpu.h"
+
+/* S3C2442 extended clock support */
+
+static unsigned long s3c2442_camif_upll_round(struct clk *clk,
+					      unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	int div;
+
+	if (rate > parent_rate)
+		return parent_rate;
+
+	div = parent_rate / rate;
+
+	if (div == 3)
+		return parent_rate / 3;
+
+	/* note, we remove the +/- 1 calculations for the divisor */
+
+	div /= 2;
+
+	if (div < 1)
+		div = 1;
+	else if (div > 16)
+		div = 16;
+
+	return parent_rate / (div * 2);
+}
+
+static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(clk->parent);
+	unsigned long camdivn =  __raw_readl(S3C2440_CAMDIVN);
+
+	rate = s3c2442_camif_upll_round(clk, rate);
+
+	camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3;
+
+	if (rate == parent_rate) {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL;
+	} else if ((parent_rate / rate) == 3) {
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3;
+	} else {
+		camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK;
+		camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL;
+		camdivn |= (((parent_rate / rate) / 2) - 1);
+	}
+
+	__raw_writel(camdivn, S3C2440_CAMDIVN);
+
+	return 0;
+}
+
+/* Extra S3C2442 clocks */
+
+static struct clk s3c2442_clk_cam = {
+	.name		= "camif",
+	.id		= -1,
+	.enable		= s3c2410_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2442_clk_cam_upll = {
+	.name		= "camif-upll",
+	.id		= -1,
+	.set_rate	= s3c2442_camif_upll_setrate,
+	.round_rate	= s3c2442_camif_upll_round,
+};
+
+static int s3c2442_clk_add(struct sys_device *sysdev)
+{
+	unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN);
+	unsigned long clkdivn;
+	struct clk *clk_h;
+	struct clk *clk_p;
+	struct clk *clk_upll;
+
+	printk("S3C2442: Clock Support, DVS %s\n",
+	       (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off");
+
+	clk_p = clk_get(NULL, "pclk");
+	clk_h = clk_get(NULL, "hclk");
+	clk_upll = clk_get(NULL, "upll");
+
+	if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) {
+		printk(KERN_ERR "S3C2442: Failed to get parent clocks\n");
+		return -EINVAL;
+	}
+
+	/* check rate of UPLL, and if it is near 96MHz, then change
+	 * to using half the UPLL rate for the system */
+
+	if (clk_get_rate(clk_upll) > (94 * MHZ)) {
+		clk_usb_bus.rate = clk_get_rate(clk_upll) / 2;
+
+		mutex_lock(&clocks_mutex);
+
+		clkdivn = __raw_readl(S3C2410_CLKDIVN);
+		clkdivn |= S3C2440_CLKDIVN_UCLK;
+		__raw_writel(clkdivn, S3C2410_CLKDIVN);
+
+		mutex_unlock(&clocks_mutex);
+	}
+
+	s3c2442_clk_cam.parent = clk_h;
+	s3c2442_clk_cam_upll.parent = clk_upll;
+
+	s3c24xx_register_clock(&s3c2442_clk_cam);
+	s3c24xx_register_clock(&s3c2442_clk_cam_upll);
+
+	clk_disable(&s3c2442_clk_cam);
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2442_clk_driver = {
+	.add	= s3c2442_clk_add,
+};
+
+static __init int s3c2442_clk_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver);
+}
+
+arch_initcall(s3c2442_clk_init);
diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c
new file mode 100644
index 0000000..debae24
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2442.c
@@ -0,0 +1,52 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440.c
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2442.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct sys_device s3c2442_sysdev = {
+	.cls		= &s3c2442_sysclass,
+};
+
+int __init s3c2442_init(void)
+{
+	printk("S3C2442: Initialising architecture\n");
+
+	return sysdev_register(&s3c2442_sysdev);
+}
diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h
new file mode 100644
index 0000000..0ae37d2
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c2442.h
@@ -0,0 +1,17 @@
+/* arch/arm/mach-s3c2410/s3c2442.h
+ *
+ * Copyright (c) 2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for s3c2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#ifdef CONFIG_CPU_S3C2442
+extern  int s3c2442_init(void);
+#else
+#define s3c2442_init NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c
new file mode 100644
index 0000000..2aadca1
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c244x-irq.c
@@ -0,0 +1,142 @@
+/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c
+ *
+ * Copyright (c) 2003,2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Changelog:
+ *	25-Jul-2005 BJD		Split from irq.c
+ *
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/ptrace.h>
+#include <linux/sysdev.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-irq.h>
+#include <asm/arch/regs-gpio.h>
+
+#include "cpu.h"
+#include "pm.h"
+#include "irq.h"
+
+/* camera irq */
+
+static void s3c_irq_demux_cam(unsigned int irq,
+			      struct irqdesc *desc,
+			      struct pt_regs *regs)
+{
+	unsigned int subsrc, submsk;
+	struct irqdesc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= 11;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
+			desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
+			desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs);
+		}
+	}
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+
+static void
+s3c_irq_cam_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+}
+
+static void
+s3c_irq_cam_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void
+s3c_irq_cam_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+}
+
+static struct irqchip s3c_irq_cam = {
+	.mask	    = s3c_irq_cam_mask,
+	.unmask	    = s3c_irq_cam_unmask,
+	.ack	    = s3c_irq_cam_ack,
+};
+
+static int s3c244x_irq_add(struct sys_device *sysdev)
+{
+	unsigned int irqno;
+
+	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_NFCON, do_level_IRQ);
+	set_irq_flags(IRQ_NFCON, IRQF_VALID);
+
+	/* add chained handler for camera */
+
+	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_CAM, do_level_IRQ);
+	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+
+	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
+		set_irq_chip(irqno, &s3c_irq_cam);
+		set_irq_handler(irqno, do_level_IRQ);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c244x_irq_driver = {
+	.add	= s3c244x_irq_add,
+};
+
+static int s3c2440_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c244x_irq_driver);
+}
+
+arch_initcall(s3c2440_irq_init);
+
+
+static int s3c2442_irq_init(void)
+{
+	return sysdev_driver_register(&s3c2442_sysclass, &s3c244x_irq_driver);
+}
+
+arch_initcall(s3c2442_irq_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c
new file mode 100644
index 0000000..838bc52
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c244x.c
@@ -0,0 +1,184 @@
+/* linux/arch/arm/mach-s3c2410/s3c244x.c
+ *
+ * Copyright (c) 2004-2006 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Samsung S3C2440 and S3C2442 Mobile CPU support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/clk.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/regs-clock.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-gpioj.h>
+#include <asm/arch/regs-dsc.h>
+
+#include "s3c2410.h"
+#include "s3c2440.h"
+#include "s3c244x.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct map_desc s3c244x_iodesc[] __initdata = {
+	IODESC_ENT(CLKPWR),
+	IODESC_ENT(TIMER),
+	IODESC_ENT(WATCHDOG),
+	IODESC_ENT(LCD),
+	IODESC_ENT(ADC),
+	IODESC_ENT(USBHOST),
+};
+
+/* uart initialisation */
+
+void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
+}
+
+void __init s3c244x_map_io(struct map_desc *mach_desc, int size)
+{
+	/* register our io-tables */
+
+	iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc));
+	iotable_init(mach_desc, size);
+
+	/* rename any peripherals used differing from the s3c2410 */
+
+	s3c_device_i2c.name  = "s3c2440-i2c";
+	s3c_device_nand.name = "s3c2440-nand";
+}
+
+void __init s3c244x_init_clocks(int xtal)
+{
+	unsigned long clkdiv;
+	unsigned long camdiv;
+	unsigned long hclk, fclk, pclk;
+	int hdiv = 1;
+
+	/* now we've got our machine bits initialised, work out what
+	 * clocks we've got */
+
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
+
+	clkdiv = __raw_readl(S3C2410_CLKDIVN);
+	camdiv = __raw_readl(S3C2440_CAMDIVN);
+
+	/* work out clock scalings */
+
+	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
+	case S3C2440_CLKDIVN_HDIVN_1:
+		hdiv = 1;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_2:
+		hdiv = 2;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_4_8:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+		break;
+
+	case S3C2440_CLKDIVN_HDIVN_3_6:
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+		break;
+	}
+
+	hclk = fclk / hdiv;
+	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+
+	/* print brief summary of clocks, etc */
+
+	printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
+
+	/* initialise the clocks here, to allow other things like the
+	 * console to use them, and to add new ones after the initialisation
+	 */
+
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+	s3c2410_baseclk_add();
+}
+
+#ifdef CONFIG_PM
+
+static struct sleep_save s3c244x_sleep[] = {
+	SAVE_ITEM(S3C2440_DSC0),
+	SAVE_ITEM(S3C2440_DSC1),
+	SAVE_ITEM(S3C2440_GPJDAT),
+	SAVE_ITEM(S3C2440_GPJCON),
+	SAVE_ITEM(S3C2440_GPJUP)
+};
+
+static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
+{
+	s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+static int s3c244x_resume(struct sys_device *dev)
+{
+	s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
+	return 0;
+}
+
+#else
+#define s3c244x_suspend NULL
+#define s3c244x_resume  NULL
+#endif
+
+/* Since the S3C2442 and S3C2440 share  items, put both sysclasses here */
+
+struct sysdev_class s3c2440_sysclass = {
+	set_kset_name("s3c2440-core"),
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+struct sysdev_class s3c2442_sysclass = {
+	set_kset_name("s3c2442-core"),
+	.suspend	= s3c244x_suspend,
+	.resume		= s3c244x_resume
+};
+
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
+
+static int __init s3c2440_core_init(void)
+{
+	return sysdev_class_register(&s3c2440_sysclass);
+}
+
+core_initcall(s3c2440_core_init);
+
+static int __init s3c2442_core_init(void)
+{
+	return sysdev_class_register(&s3c2442_sysclass);
+}
+
+core_initcall(s3c2442_core_init);
diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/mach-s3c2410/s3c244x.h
new file mode 100644
index 0000000..3e7f5f7
--- /dev/null
+++ b/arch/arm/mach-s3c2410/s3c244x.h
@@ -0,0 +1,25 @@
+/* arch/arm/mach-s3c2410/s3c2440.h
+ *
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for S3C2440 and S3C2442 cpu support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
+
+extern void s3c244x_map_io(struct map_desc *mach_desc, int size);
+
+extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+
+extern void s3c244x_init_clocks(int xtal);
+
+#else
+#define s3c244x_init_clocks NULL
+#define s3c244x_init_uarts NULL
+#define s3c244x_map_io NULL
+#endif
diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S
index 73de2ea..dc27167 100644
--- a/arch/arm/mach-s3c2410/sleep.S
+++ b/arch/arm/mach-s3c2410/sleep.S
@@ -66,7 +66,9 @@
 	@@ flush the caches to ensure everything is back out to
 	@@ SDRAM before the core powers down
 
+#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 	bl	arm920_flush_kern_cache_all
+#endif
 
 	@@ prepare cpu to sleep
 
@@ -126,7 +128,7 @@
 	*/
 
 ENTRY(s3c2410_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | MODE_SVC
+	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
 	msr	cpsr_c, r0
 
 	@@ load UART to allow us to print the two characters for
diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S
index 2fa1e28..5a84062 100644
--- a/arch/arm/mach-sa1100/sleep.S
+++ b/arch/arm/mach-sa1100/sleep.S
@@ -177,7 +177,7 @@
 	.data
 	.align 5
 ENTRY(sa1100_cpu_resume)
-	mov	r0, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
+	mov	r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
 	msr	cpsr_c, r0			@ set SVC, irqs off
 
 	ldr	r0, sleep_save_sp		@ stack phys addr
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c55b739..ecf5e23 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -61,9 +61,9 @@
 
 # ARM920T
 config CPU_ARM920T
-	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_EP93XX || ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
-	default y if ARCH_S3C2410 || ARCH_AT91RM9200
+	bool "Support ARM920T processor"
+	depends on ARCH_EP93XX || ARCH_INTEGRATOR || CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_IMX || ARCH_AAEC2000 || ARCH_AT91RM9200
+	default y if CPU_S3C2410 || CPU_S3C2440 || CPU_S3C2442 || ARCH_AT91RM9200
 	select CPU_32v4
 	select CPU_ABRT_EV4T
 	select CPU_CACHE_V4WT
@@ -121,8 +121,8 @@
 # ARM926T
 config CPU_ARM926T
 	bool "Support ARM926T processor"
-	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB
-	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX
+	depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
+	default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412
 	select CPU_32v5
 	select CPU_ABRT_EV5TJ
 	select CPU_CACHE_VIVT
diff --git a/arch/arm/mm/copypage-v3.S b/arch/arm/mm/copypage-v3.S
index 3c58ebb..2ee394b 100644
--- a/arch/arm/mm/copypage-v3.S
+++ b/arch/arm/mm/copypage-v3.S
@@ -35,7 +35,7 @@
 	stmia	r0!, {r3, r4, ip, lr}		@	4
 	ldmneia	r1!, {r3, r4, ip, lr}		@	4
 	bne	1b				@	1
-	LOADREGS(fd, sp!, {r4, pc})		@	3
+	ldmfd	sp!, {r4, pc}			@	3
 
 	.align	5
 /*
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index ee6f152..09b1a41 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -29,38 +29,6 @@
 #define TTB_RGN_WT	(2 << 3)
 #define TTB_RGN_WB	(3 << 3)
 
-	.macro	cpsie, flags
-	.ifc \flags, f
-	.long	0xf1080040
-	.exitm
-	.endif
-	.ifc \flags, i
-	.long	0xf1080080
-	.exitm
-	.endif
-	.ifc \flags, if
-	.long	0xf10800c0
-	.exitm
-	.endif
-	.err
-	.endm
-
-	.macro	cpsid, flags
-	.ifc \flags, f
-	.long	0xf10c0040
-	.exitm
-	.endif
-	.ifc \flags, i
-	.long	0xf10c0080
-	.exitm
-	.endif
-	.ifc \flags, if
-	.long	0xf10c00c0
-	.exitm
-	.endif
-	.err
-	.endm
-
 ENTRY(cpu_v6_proc_init)
 	mov	pc, lr
 
diff --git a/arch/arm/nwfpe/entry26.S b/arch/arm/nwfpe/entry26.S
index 51940a9..3e6fb5d 100644
--- a/arch/arm/nwfpe/entry26.S
+++ b/arch/arm/nwfpe/entry26.S
@@ -26,7 +26,7 @@
 It is called from the kernel with code similar to this:
 
 	mov	fp, #0
-	teqp	pc, #PSR_I_BIT | MODE_SVC
+	teqp	pc, #PSR_I_BIT | SVC_MODE
 	ldr	r4, .LC2
 	ldr	pc, [r4]		@ Call FP module USR entry point
 
diff --git a/arch/arm/nwfpe/fpmodule.c b/arch/arm/nwfpe/fpmodule.c
index 2dfe1ac..7d977d2 100644
--- a/arch/arm/nwfpe/fpmodule.c
+++ b/arch/arm/nwfpe/fpmodule.c
@@ -33,7 +33,8 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-/* XXX */
+
+#include <asm/thread_notify.h>
 
 #include "softfloat.h"
 #include "fpopcode.h"
@@ -56,16 +57,28 @@
 extern char fpe_type[];
 #endif
 
+static int nwfpe_notify(struct notifier_block *self, unsigned long cmd, void *v)
+{
+	struct thread_info *thread = v;
+
+	if (cmd == THREAD_NOTIFY_FLUSH)
+		nwfpe_init_fpa(&thread->fpstate);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block nwfpe_notifier_block = {
+	.notifier_call = nwfpe_notify,
+};
+
 /* kernel function prototypes required */
 void fp_setup(void);
 
 /* external declarations for saved kernel symbols */
 extern void (*kern_fp_enter)(void);
-extern void (*fp_init)(union fp_state *);
 
 /* Original value of fp_enter from kernel before patched by fpe_init. */
 static void (*orig_fp_enter)(void);
-static void (*orig_fp_init)(union fp_state *);
 
 /* forward declarations */
 extern void nwfpe_enter(void);
@@ -88,20 +101,20 @@
 	printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 ("
 	       NWFPE_BITS " precision)\n");
 
+	thread_register_notifier(&nwfpe_notifier_block);
+
 	/* Save pointer to the old FP handler and then patch ourselves in */
 	orig_fp_enter = kern_fp_enter;
-	orig_fp_init = fp_init;
 	kern_fp_enter = nwfpe_enter;
-	fp_init = nwfpe_init_fpa;
 
 	return 0;
 }
 
 static void __exit fpe_exit(void)
 {
+	thread_unregister_notifier(&nwfpe_notifier_block);
 	/* Restore the values we saved earlier. */
 	kern_fp_enter = orig_fp_enter;
-	fp_init = orig_fp_init;
 }
 
 /*
diff --git a/arch/arm/plat-omap/timer32k.c b/arch/arm/plat-omap/timer32k.c
index b2a943b..3461a6c 100644
--- a/arch/arm/plat-omap/timer32k.c
+++ b/arch/arm/plat-omap/timer32k.c
@@ -210,7 +210,8 @@
 
 	now = omap_32k_sync_timer_read();
 
-	while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+	while ((signed long)(now - omap_32k_last_tick)
+						>= OMAP_32K_TICKS_PER_HZ) {
 		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
 		timer_tick(regs);
 	}
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 6d7de9c..e1372a2 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon May 8 20:11:05 2006
+# Last update: Mon Jun 26 22:26:08 2006
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -566,8 +566,8 @@
 ens_cmu			MACH_ENS_CMU		ENS_CMU			550
 mm6_sdb			MACH_MM6_SDB		MM6_SDB			551
 saturn			MACH_SATURN		SATURN			552
-i30030evb		MACH_ARGONPLUSEVB	ARGONPLUSEVB		553
-mxc27530evb		MACH_SCMA11EVB		SCMA11EVB		554
+i30030evb		MACH_I30030EVB		I30030EVB		553
+mxc27530evb		MACH_MXC27530EVB	MXC27530EVB		554
 smdk2800		MACH_SMDK2800		SMDK2800		555
 mtwilson		MACH_MTWILSON		MTWILSON		556
 ziti			MACH_ZITI		ZITI			557
@@ -647,7 +647,7 @@
 mx2jazz			MACH_MX2JAZZ		MX2JAZZ			631
 multiio			MACH_MULTIIO		MULTIIO			632
 hrdisplay		MACH_HRDISPLAY		HRDISPLAY		633
-mxc27530ads		MACH_SCMA11BB		SCMA11BB		634
+mxc27530ads		MACH_MXC27530ADS	MXC27530ADS		634
 trizeps3		MACH_TRIZEPS3		TRIZEPS3		635
 zefeerdza		MACH_ZEFEERDZA		ZEFEERDZA		636
 zefeerdzb		MACH_ZEFEERDZB		ZEFEERDZB		637
@@ -721,7 +721,7 @@
 gem			MACH_GEM		GEM			707
 i858			MACH_I858		I858			708
 hx2750			MACH_HX2750		HX2750			709
-mxc91131evb		MACH_ZEUSEVB		ZEUSEVB			710
+mxc91131evb		MACH_MXC91131EVB	MXC91131EVB		710
 p700			MACH_P700		P700			711
 cpe			MACH_CPE		CPE			712
 spitz			MACH_SPITZ		SPITZ			713
@@ -802,7 +802,7 @@
 rea9200			MACH_REA9200		REA9200			788
 acts_pune_sa1110	MACH_ACTS_PUNE_SA1110	ACTS_PUNE_SA1110	789
 ixp425			MACH_IXP425		IXP425			790
-i30030ads		MACH_ARGONPLUSODYSSEY	ARGONPLUSODYSSEY	791
+i30030ads		MACH_I30030ADS		I30030ADS		791
 perch			MACH_PERCH		PERCH			792
 eis05r1			MACH_EIS05R1		EIS05R1			793
 pepperpad		MACH_PEPPERPAD		PEPPERPAD		794
@@ -930,7 +930,7 @@
 xscale_palmtt5		MACH_XSCALE_PALMTT5	XSCALE_PALMTT5		917
 xscale_palmtc		MACH_OMAP_PALMTC	OMAP_PALMTC		918
 omap_apollon		MACH_OMAP_APOLLON	OMAP_APOLLON		919
-mxc30030evb		MACH_ARGONLVEVB		ARGONLVEVB		920
+mxc30030evb		MACH_MXC30030EVB	MXC30030EVB		920
 rea_2d			MACH_REA_2D		REA_2D			921
 eti3e524		MACH_TI3E524		TI3E524			922
 ateb9200		MACH_ATEB9200		ATEB9200		923
@@ -986,7 +986,7 @@
 mysh_ep9315_1		MACH_MYSH_EP9315_1	MYSH_EP9315_1		973
 tpf106			MACH_TPF106		TPF106			974
 at91rm9200kg		MACH_AT91RM9200KG	AT91RM9200KG		975
-racemt2			MACH_SLEDB		SLEDB			976
+rcmt2			MACH_SLEDB		SLEDB			976
 ontrack			MACH_ONTRACK		ONTRACK			977
 pm1200			MACH_PM1200		PM1200			978
 ess24562		MACH_ESS24XXX		ESS24XXX		979
@@ -1022,7 +1022,7 @@
 smdk2412		MACH_SMDK2412		SMDK2412		1009
 webbox			MACH_WEBBOX		WEBBOX			1010
 cwwndp			MACH_CWWNDP		CWWNDP			1011
-dragon			MACH_DRAGON		DRAGON			1012
+i839			MACH_DRAGON		DRAGON			1012
 opendo_cpu_board	MACH_OPENDO_CPU_BOARD	OPENDO_CPU_BOARD	1013
 ccm2200			MACH_CCM2200		CCM2200			1014
 etwarm			MACH_ETWARM		ETWARM			1015
@@ -1040,3 +1040,56 @@
 ai2410			MACH_AI2410		AI2410			1027
 ixp465			MACH_IXP465		IXP465			1028
 balloon3		MACH_BALLOON3		BALLOON3		1029
+heins			MACH_HEINS		HEINS			1030
+mpluseva		MACH_MPLUSEVA		MPLUSEVA		1031
+rt042			MACH_RT042		RT042			1032
+cwiem			MACH_CWIEM		CWIEM			1033
+cm_x270			MACH_CM_X270		CM_X270			1034
+cm_x255			MACH_CM_X255		CM_X255			1035
+esh_at91		MACH_ESH_AT91		ESH_AT91		1036
+sandgate3		MACH_SANDGATE3		SANDGATE3		1037
+primo			MACH_PRIMO		PRIMO			1038
+gemstone		MACH_GEMSTONE		GEMSTONE		1039
+pronghorn_metro		MACH_PRONGHORNMETRO	PRONGHORNMETRO		1040
+sidewinder		MACH_SIDEWINDER		SIDEWINDER		1041
+picomod1		MACH_PICOMOD1		PICOMOD1		1042
+sg590			MACH_SG590		SG590			1043
+akai9307		MACH_AKAI9307		AKAI9307		1044
+fontaine		MACH_FONTAINE		FONTAINE		1045
+wombat			MACH_WOMBAT		WOMBAT			1046
+acq300			MACH_ACQ300		ACQ300			1047
+mod_270			MACH_MOD_270		MOD_270			1048
+vmc_vc0820		MACH_VC0820		VC0820			1049
+ani_aim			MACH_ANI_AIM		ANI_AIM			1050
+jellyfish		MACH_JELLYFISH		JELLYFISH		1051
+amanita			MACH_AMANITA		AMANITA			1052
+vlink			MACH_VLINK		VLINK			1053
+dexflex			MACH_DEXFLEX		DEXFLEX			1054
+eigen_ttq		MACH_EIGEN_TTQ		EIGEN_TTQ		1055
+arcom_titan		MACH_ARCOM_TITAN	ARCOM_TITAN		1056
+tabla			MACH_TABLA		TABLA			1057
+mdirac3			MACH_MDIRAC3		MDIRAC3			1058
+mrhfbp2			MACH_MRHFBP2		MRHFBP2			1059
+at91rm9200rb		MACH_AT91RM9200RB	AT91RM9200RB		1060
+ani_apm			MACH_ANI_APM		ANI_APM			1061
+ella1			MACH_ELLA1		ELLA1			1062
+inhand_pxa27x		MACH_INHAND_PXA27X	INHAND_PXA27X		1063
+inhand_pxa25x		MACH_INHAND_PXA25X	INHAND_PXA25X		1064
+empos_xm		MACH_EMPOS_XM		EMPOS_XM		1065
+empos			MACH_EMPOS		EMPOS			1066
+empos_tiny		MACH_EMPOS_TINY		EMPOS_TINY		1067
+empos_sm		MACH_EMPOS_SM		EMPOS_SM		1068
+egret			MACH_EGRET		EGRET			1069
+ostrich			MACH_OSTRICH		OSTRICH			1070
+n50			MACH_N50		N50			1071
+ecbat91			MACH_ECBAT91		ECBAT91			1072
+stareast		MACH_STAREAST		STAREAST		1073
+dspg_dw			MACH_DSPG_DW		DSPG_DW			1074
+onearm			MACH_ONEARM		ONEARM			1075
+mrg110_6		MACH_MRG110_6		MRG110_6		1076
+wrt300nv2		MACH_WRT300NV2		WRT300NV2		1077
+xm_bulverde		MACH_XM_BULVERDE	XM_BULVERDE		1078
+msm6100			MACH_MSM6100		MSM6100			1079
+eti_b1			MACH_ETI_B1		ETI_B1			1080
+za9l_series		MACH_ZILOG_ZA9L		ZILOG_ZA9L		1081
+bit2440			MACH_BIT2440		BIT2440			1082
diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile
index afabac3..7e136e7 100644
--- a/arch/arm/vfp/Makefile
+++ b/arch/arm/vfp/Makefile
@@ -7,6 +7,9 @@
 # EXTRA_CFLAGS := -DDEBUG
 # EXTRA_AFLAGS := -DDEBUG
 
+AFLAGS		:=$(AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
+LDFLAGS		+=--no-warn-mismatch
+
 obj-y			+= vfp.o
 
-vfp-$(CONFIG_VFP)	+= entry.o vfpmodule.o vfphw.o vfpsingle.o vfpdouble.o
+vfp-$(CONFIG_VFP)	+= vfpmodule.o entry.o vfphw.o vfpsingle.o vfpdouble.o
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index a3f65b4..eb683cd 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -192,7 +192,7 @@
 	add	pc, pc, r0, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	mrrc	p11, 1, r0, r1, c\dr	@ fmrrd	r0, r1, d\dr
+	fmrrd	r0, r1, d\dr
 	mov	pc, lr
 	.endr
 
@@ -206,6 +206,6 @@
 	add	pc, pc, r0, lsl #3
 	mov	r0, r0
 	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
-	mcrr	p11, 1, r1, r2, c\dr	@ fmdrr	r1, r2, d\dr
+	fmdrr	d\dr, r1, r2
 	mov	pc, lr
 	.endr
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 03486be..2476f4c 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -15,6 +15,8 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/init.h>
+
+#include <asm/thread_notify.h>
 #include <asm/vfp.h>
 
 #include "vfpinstr.h"
@@ -36,37 +38,54 @@
  */
 unsigned int VFP_arch;
 
-/*
- * Per-thread VFP initialisation.
- */
-void vfp_flush_thread(union vfp_state *vfp)
+static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
-	memset(vfp, 0, sizeof(union vfp_state));
+	struct thread_info *thread = v;
+	union vfp_state *vfp = &thread->vfpstate;
 
-	vfp->hard.fpexc = FPEXC_ENABLE;
-	vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
+	switch (cmd) {
+	case THREAD_NOTIFY_FLUSH:
+		/*
+		 * Per-thread VFP initialisation.
+		 */
+		memset(vfp, 0, sizeof(union vfp_state));
 
-	/*
-	 * Disable VFP to ensure we initialise it first.
-	 */
-	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+		vfp->hard.fpexc = FPEXC_ENABLE;
+		vfp->hard.fpscr = FPSCR_ROUND_NEAREST;
 
-	/*
-	 * Ensure we don't try to overwrite our newly initialised
-	 * state information on the first fault.
-	 */
-	if (last_VFP_context == vfp)
-		last_VFP_context = NULL;
+		/*
+		 * Disable VFP to ensure we initialise it first.
+		 */
+		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+
+		/*
+		 * FALLTHROUGH: Ensure we don't try to overwrite our newly
+		 * initialised state information on the first fault.
+		 */
+
+	case THREAD_NOTIFY_RELEASE:
+		/*
+		 * Per-thread VFP cleanup.
+		 */
+		if (last_VFP_context == vfp)
+			last_VFP_context = NULL;
+		break;
+
+	case THREAD_NOTIFY_SWITCH:
+		/*
+		 * Always disable VFP so we can lazily save/restore the
+		 * old state.
+		 */
+		fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
+		break;
+	}
+
+	return NOTIFY_DONE;
 }
 
-/*
- * Per-thread VFP cleanup.
- */
-void vfp_release_thread(union vfp_state *vfp)
-{
-	if (last_VFP_context == vfp)
-		last_VFP_context = NULL;
-}
+static struct notifier_block vfp_notifier_block = {
+	.notifier_call	= vfp_notifier,
+};
 
 /*
  * Raise a SIGFPE for the current process.
@@ -281,6 +300,8 @@
 			(vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT,
 			(vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT);
 		vfp_vector = vfp_support_entry;
+
+		thread_register_notifier(&vfp_notifier_block);
 	}
 	return 0;
 }
diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
index 24bc149..1e9d062 100644
--- a/arch/cris/arch-v32/drivers/pci/bios.c
+++ b/arch/cris/arch-v32/drivers/pci/bios.c
@@ -27,8 +27,6 @@
 	/* Leave vm_pgoff as-is, the PCI space address is the physical
 	 * address on this platform.
 	 */
-	vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
-
 	prot = pgprot_val(vma->vm_page_prot);
 	vma->vm_page_prot = __pgprot(prot);
 
diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
index a9b5952..81d94e4 100644
--- a/arch/frv/kernel/entry.S
+++ b/arch/frv/kernel/entry.S
@@ -1474,7 +1474,7 @@
 	.long sys_mknodat
 	.long sys_fchownat
 	.long sys_futimesat
-	.long sys_newfstatat		/* 300 */
+	.long sys_fstatat64		/* 300 */
 	.long sys_unlinkat
 	.long sys_renameat
 	.long sys_linkat
diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c
index 0f273a7..dee637f 100644
--- a/arch/frv/kernel/frv_ksyms.c
+++ b/arch/frv/kernel/frv_ksyms.c
@@ -26,16 +26,6 @@
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
 
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
-EXPORT_SYMBOL(strncpy);
-
 EXPORT_SYMBOL(ip_fast_csum);
 
 #if 0
@@ -44,8 +34,6 @@
 #endif
 EXPORT_SYMBOL(kernel_thread);
 
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(__res_bus_clock_speed_HZ);
 EXPORT_SYMBOL(__page_offset);
 EXPORT_SYMBOL(__memcpy_user);
@@ -62,18 +50,12 @@
 
 EXPORT_SYMBOL(__debug_bug_trap);
 
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy);
-
 /* The following are special because they're not called
    explicitly (the C compiler generates them).  Fortunately,
    their interface isn't gonna change any time soon now, so
    it's OK to leave it out of version control.  */
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
-EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(__outsl_ns);
 EXPORT_SYMBOL(__insl_ns);
diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c
index d4776d1..b90b70a 100644
--- a/arch/frv/kernel/irq-routing.c
+++ b/arch/frv/kernel/irq-routing.c
@@ -112,7 +112,7 @@
 #define __CPUUART(X, A)						\
 	[X] = {							\
 		.muxname	= "uart",			\
-		.muxdata	= (volatile void __iomem *) A,	\
+		.muxdata	= (volatile void __iomem *)(unsigned long)A,\
 		.irqmask	= 1 << IRQ_CPU_UART##X,		\
 		.doirq		= frv_cpuuart_doirq,		\
 	}
@@ -136,7 +136,7 @@
 #define __CPUDMA(X, A)						\
 	[X] = {							\
 		.muxname	= "dma",			\
-		.muxdata	= (volatile void __iomem *) A,	\
+		.muxdata	= (volatile void __iomem *)(unsigned long)A,\
 		.irqmask	= 1 << IRQ_CPU_DMA##X,		\
 		.doirq		= frv_cpudma_doirq,		\
 	}
@@ -164,7 +164,7 @@
 #define __CPUTIMER(X)						\
 	[X] = {							\
 		.muxname	= "timer",			\
-		.muxdata	= 0,				\
+		.muxdata	= NULL,				\
 		.irqmask	= 1 << IRQ_CPU_TIMER##X,	\
 		.doirq		= frv_cputimer_doirq,		\
 	}
@@ -187,7 +187,7 @@
 #define __CPUEXTERNAL(X)					\
 	[X] = {							\
 		.muxname	= "ext",			\
-		.muxdata	= 0,				\
+		.muxdata	= NULL,				\
 		.irqmask	= 1 << IRQ_CPU_EXTERNAL##X,	\
 		.doirq		= frv_cpuexternal_doirq,	\
 	}
diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c
index 11fa326..8b112b3 100644
--- a/arch/frv/kernel/irq.c
+++ b/arch/frv/kernel/irq.c
@@ -625,7 +625,7 @@
 
 #define HEX_DIGITS 8
 
-static unsigned int parse_hex_value (const char *buffer,
+static unsigned int parse_hex_value (const char __user *buffer,
 				     unsigned long count, unsigned long *ret)
 {
 	unsigned char hexnum [HEX_DIGITS];
@@ -672,7 +672,7 @@
 	return sprintf (page, "%08lx\n", *mask);
 }
 
-static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
+static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer,
 					unsigned long count, void *data)
 {
 	unsigned long *mask = (unsigned long *) data, full_count = count, err;
@@ -711,7 +711,7 @@
 	int i;
 
 	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", 0);
+	root_irq_dir = proc_mkdir("irq", NULL);
 
 	/* create /proc/irq/prof_cpu_mask */
 	entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c
index f0b8fff..43ce28a13 100644
--- a/arch/frv/kernel/pm.c
+++ b/arch/frv/kernel/pm.c
@@ -137,7 +137,7 @@
 #define CTL_PM_P0 4
 #define CTL_PM_CM 5
 
-static int user_atoi(char *ubuf, size_t len)
+static int user_atoi(char __user *ubuf, size_t len)
 {
 	char buf[16];
 	unsigned long ret;
@@ -159,7 +159,7 @@
  * Send us to sleep.
  */
 static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp,
-				void *buffer, size_t *lenp, loff_t *fpos)
+				void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int retval, mode;
 
@@ -215,7 +215,7 @@
 
 
 static int cmode_procctl(ctl_table *ctl, int write, struct file *filp,
-			 void *buffer, size_t *lenp, loff_t *fpos)
+			 void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int new_cmode;
 
@@ -227,9 +227,9 @@
 	return try_set_cmode(new_cmode)?:*lenp;
 }
 
-static int cmode_sysctl(ctl_table *table, int *name, int nlen,
-			void *oldval, size_t *oldlenp,
-			void *newval, size_t newlen, void **context)
+static int cmode_sysctl(ctl_table *table, int __user *name, int nlen,
+			void __user *oldval, size_t __user *oldlenp,
+			void __user *newval, size_t newlen, void **context)
 {
 	if (oldval && oldlenp) {
 		size_t oldlen;
@@ -240,7 +240,7 @@
 		if (oldlen != sizeof(int))
 			return -EINVAL;
 
-		if (put_user(clock_cmode_current, (unsigned int *)oldval) ||
+		if (put_user(clock_cmode_current, (unsigned __user *)oldval) ||
 		    put_user(sizeof(int), oldlenp))
 			return -EFAULT;
 	}
@@ -250,7 +250,7 @@
 		if (newlen != sizeof(int))
 			return -EINVAL;
 
-		if (get_user(new_cmode, (int *)newval))
+		if (get_user(new_cmode, (int __user *)newval))
 			return -EFAULT;
 
 		return try_set_cmode(new_cmode)?:1;
@@ -318,7 +318,7 @@
 }
 
 static int p0_procctl(ctl_table *ctl, int write, struct file *filp,
-		      void *buffer, size_t *lenp, loff_t *fpos)
+		      void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int new_p0;
 
@@ -330,9 +330,9 @@
 	return try_set_p0(new_p0)?:*lenp;
 }
 
-static int p0_sysctl(ctl_table *table, int *name, int nlen,
-		     void *oldval, size_t *oldlenp,
-		     void *newval, size_t newlen, void **context)
+static int p0_sysctl(ctl_table *table, int __user *name, int nlen,
+		     void __user *oldval, size_t __user *oldlenp,
+		     void __user *newval, size_t newlen, void **context)
 {
 	if (oldval && oldlenp) {
 		size_t oldlen;
@@ -343,7 +343,7 @@
 		if (oldlen != sizeof(int))
 			return -EINVAL;
 
-		if (put_user(clock_p0_current, (unsigned int *)oldval) ||
+		if (put_user(clock_p0_current, (unsigned __user *)oldval) ||
 		    put_user(sizeof(int), oldlenp))
 			return -EFAULT;
 	}
@@ -353,7 +353,7 @@
 		if (newlen != sizeof(int))
 			return -EINVAL;
 
-		if (get_user(new_p0, (int *)newval))
+		if (get_user(new_p0, (int __user *)newval))
 			return -EFAULT;
 
 		return try_set_p0(new_p0)?:1;
@@ -362,7 +362,7 @@
 }
 
 static int cm_procctl(ctl_table *ctl, int write, struct file *filp,
-		      void *buffer, size_t *lenp, loff_t *fpos)
+		      void __user *buffer, size_t *lenp, loff_t *fpos)
 {
 	int new_cm;
 
@@ -374,9 +374,9 @@
 	return try_set_cm(new_cm)?:*lenp;
 }
 
-static int cm_sysctl(ctl_table *table, int *name, int nlen,
-		     void *oldval, size_t *oldlenp,
-		     void *newval, size_t newlen, void **context)
+static int cm_sysctl(ctl_table *table, int __user *name, int nlen,
+		     void __user *oldval, size_t __user *oldlenp,
+		     void __user *newval, size_t newlen, void **context)
 {
 	if (oldval && oldlenp) {
 		size_t oldlen;
@@ -387,7 +387,7 @@
 		if (oldlen != sizeof(int))
 			return -EINVAL;
 
-		if (put_user(clock_cm_current, (unsigned int *)oldval) ||
+		if (put_user(clock_cm_current, (unsigned __user *)oldval) ||
 		    put_user(sizeof(int), oldlenp))
 			return -EFAULT;
 	}
@@ -397,7 +397,7 @@
 		if (newlen != sizeof(int))
 			return -EINVAL;
 
-		if (get_user(new_cm, (int *)newval))
+		if (get_user(new_cm, (int __user *)newval))
 			return -EFAULT;
 
 		return try_set_cm(new_cm)?:1;
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 0fff8a6..489e6c4 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -246,7 +246,7 @@
 /*
  * sys_execve() executes a new program.
  */
-asmlinkage int sys_execve(char *name, char **argv, char **envp)
+asmlinkage int sys_execve(char __user *name, char __user * __user *argv, char __user * __user *envp)
 {
 	int error;
 	char * filename;
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index 5908dea..1f7d65f 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -814,7 +814,7 @@
 	 * - by now the stack is part of the init task */
 	printk("Memory %08lx-%08lx\n", memory_start, memory_end);
 
-	if (memory_start == memory_end) BUG();
+	BUG_ON(memory_start == memory_end);
 
 	init_mm.start_code = (unsigned long) &_stext;
 	init_mm.end_code = (unsigned long) &_etext;
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index 679c1d5..b8a5882 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -98,7 +98,7 @@
 
 struct sigframe
 {
-	void (*pretcode)(void);
+	__sigrestore_t pretcode;
 	int sig;
 	struct sigcontext sc;
 	unsigned long extramask[_NSIG_WORDS-1];
@@ -107,10 +107,10 @@
 
 struct rt_sigframe
 {
-	void (*pretcode)(void);
+	__sigrestore_t pretcode;
 	int sig;
-	struct siginfo *pinfo;
-	void *puc;
+	struct siginfo __user *pinfo;
+	void __user *puc;
 	struct siginfo info;
 	struct ucontext uc;
 	uint32_t retcode[2];
@@ -233,7 +233,7 @@
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (! on_sig_stack(sp))
+		if (! sas_ss_flags(sp))
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
@@ -284,7 +284,7 @@
 		 *	setlos	#__NR_sigreturn,gr7
 		 *	tira	gr0,0
 		 */
-		if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+		if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 		    __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
 		    __put_user(0xc0700000, &frame->retcode[1]))
 			goto give_sigsegv;
@@ -300,7 +300,7 @@
 
 	if (get_personality & FDPIC_FUNCPTRS) {
 		struct fdpic_func_descriptor __user *funcptr =
-			(struct fdpic_func_descriptor *) ka->sa.sa_handler;
+			(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
 		__get_user(__frame->pc, &funcptr->text);
 		__get_user(__frame->gr15, &funcptr->GOT);
 	} else {
@@ -359,8 +359,8 @@
 
 	/* Create the ucontext.  */
 	if (__put_user(0, &frame->uc.uc_flags) ||
-	    __put_user(0, &frame->uc.uc_link) ||
-	    __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
+	    __put_user(NULL, &frame->uc.uc_link) ||
+	    __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) ||
 	    __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) ||
 	    __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size))
 		goto give_sigsegv;
@@ -382,7 +382,7 @@
 		 *	setlos	#__NR_sigreturn,gr7
 		 *	tira	gr0,0
 		 */
-		if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) ||
+		if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
 		    __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
 		    __put_user(0xc0700000, &frame->retcode[1]))
 			goto give_sigsegv;
@@ -398,7 +398,7 @@
 	__frame->gr9 = (unsigned long) &frame->info;
 
 	if (get_personality & FDPIC_FUNCPTRS) {
-		struct fdpic_func_descriptor *funcptr =
+		struct fdpic_func_descriptor __user *funcptr =
 			(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
 		__get_user(__frame->pc, &funcptr->text);
 		__get_user(__frame->gr15, &funcptr->GOT);
diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c
index 931aa6d..c4d4348 100644
--- a/arch/frv/kernel/sys_frv.c
+++ b/arch/frv/kernel/sys_frv.c
@@ -32,7 +32,7 @@
  * sys_pipe() is the normal C calling standard for creating
  * a pipe. It's not the way unix traditionally does this, though.
  */
-asmlinkage long sys_pipe(unsigned long * fildes)
+asmlinkage long sys_pipe(unsigned long __user * fildes)
 {
 	int fd[2];
 	int error;
diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c
index 408b0f3..b908863 100644
--- a/arch/frv/kernel/sysctl.c
+++ b/arch/frv/kernel/sysctl.c
@@ -49,7 +49,7 @@
  * handle requests to dynamically switch the write caching mode delivered by /proc
  */
 static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp,
-				 void *buffer, size_t *lenp, loff_t *ppos)
+				 void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	unsigned long hsr0;
 	char buff[8];
@@ -123,7 +123,7 @@
  */
 #ifdef CONFIG_MMU
 static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp,
-				void *buffer, size_t *lenp, loff_t *ppos)
+				void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	pid_t pid;
 	char buff[16], *p;
diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c
index 9b751c0..9fb771a 100644
--- a/arch/frv/kernel/uaccess.c
+++ b/arch/frv/kernel/uaccess.c
@@ -17,7 +17,7 @@
 /*
  * copy a null terminated string from userspace
  */
-long strncpy_from_user(char *dst, const char *src, long count)
+long strncpy_from_user(char *dst, const char __user *src, long count)
 {
 	unsigned long max;
 	char *p, ch;
@@ -70,9 +70,9 @@
  *
  * Return 0 on exception, a value greater than N if too long
  */
-long strnlen_user(const char *src, long count)
+long strnlen_user(const char __user *src, long count)
 {
-	const char *p;
+	const char __user *p;
 	long err = 0;
 	char ch;
 
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index c4a1144..45ae39d 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -32,11 +32,11 @@
  */
 
 static const uint8_t __initdata pci_bus0_irq_routing[32][4] = {
-	[0 ] {	IRQ_FPGA_MB86943_PCI_INTA },
-	[16] {	IRQ_FPGA_RTL8029_INTA },
-	[17] {	IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB },
-	[18] {	IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA },
-	[19] {	IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD },
+	[0 ] = { IRQ_FPGA_MB86943_PCI_INTA },
+	[16] = { IRQ_FPGA_RTL8029_INTA },
+	[17] = { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB },
+	[18] = { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA },
+	[19] = { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD },
 };
 
 void __init pcibios_irq_init(void)
diff --git a/arch/frv/mm/kmap.c b/arch/frv/mm/kmap.c
index c54f18e..40b62c5 100644
--- a/arch/frv/mm/kmap.c
+++ b/arch/frv/mm/kmap.c
@@ -31,15 +31,15 @@
  * Map some physical address range into the kernel address space.
  */
 
-void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
+void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
 {
-	return (void *)physaddr;
+	return (void __iomem *)physaddr;
 }
 
 /*
  * Unmap a ioremap()ed region again
  */
-void iounmap(void *addr)
+void iounmap(void volatile __iomem *addr)
 {
 }
 
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index f13d5e8..7787f70 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -307,7 +307,7 @@
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(usp))
+		if (!sas_ss_flags(usp))
 			usp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	return (void *)((usp - frame_size) & -8UL);
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index 8dfa305..3bb221d 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -14,6 +14,10 @@
 	  486, 586, Pentiums, and various instruction-set-compatible chips by
 	  AMD, Cyrix, and others.
 
+config GENERIC_TIME
+	bool
+	default y
+
 config SEMAPHORE_SLEEPERS
 	bool
 	default y
@@ -173,6 +177,12 @@
 	bool
 	default y
 	depends on NUMA && (X86_SUMMIT || X86_GENERICARCH)
+	select ACPI_NUMA
+
+config HAVE_ARCH_PARSE_SRAT
+       bool
+       default y
+       depends on ACPI_SRAT
 
 config X86_SUMMIT_NUMA
 	bool
@@ -223,8 +233,7 @@
 
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
-	depends on SMP
-	default off
+	depends on X86_HT
 	help
 	  SMT scheduler support improves the CPU scheduler's decision making
 	  when dealing with Intel Pentium 4 chips with HyperThreading at a
@@ -233,7 +242,7 @@
 
 config SCHED_MC
 	bool "Multi-core scheduler support"
-	depends on SMP
+	depends on X86_HT
 	default y
 	help
 	  Multi-core scheduler support improves the CPU scheduler's decision
@@ -319,6 +328,15 @@
 	  Enabling this feature will cause a message to be printed when the P4
 	  enters thermal throttling.
 
+config VM86
+	default y
+	bool "Enable VM86 support" if EMBEDDED
+	help
+          This option is required by programs like DOSEMU to run 16-bit legacy
+	  code on X86 processors. It also may be needed by software like
+          XFree86 to initialize some video cards via BIOS. Disabling this
+          option saves about 6k.
+
 config TOSHIBA
 	tristate "Toshiba Laptop support"
 	---help---
@@ -716,7 +734,7 @@
 	help
 	  kexec is a system call that implements the ability to shutdown your
 	  current kernel, and to start another kernel.  It is like a reboot
-	  but it is indepedent of the system firmware.   And like a reboot
+	  but it is independent of the system firmware.   And like a reboot
 	  you can start any kernel with it, not just Linux.
 
 	  The name comes from the similiarity to the exec system call.
@@ -762,6 +780,17 @@
 	  enable suspend on SMP systems. CPUs can be controlled through
 	  /sys/devices/system/cpu.
 
+config COMPAT_VDSO
+	bool "Compat VDSO support"
+	default y
+	help
+	  Map the VDSO to the predictable old-style address too.
+	---help---
+	  Say N here if you are running a sufficiently recent glibc
+	  version (2.3.3 or later), to remove the high-mapped
+	  VDSO mapping and to exclusively use the randomized VDSO.
+
+	  If unsure, say Y.
 
 endmenu
 
@@ -1041,13 +1070,27 @@
 	tristate "NatSemi SCx200 support"
 	depends on !X86_VOYAGER
 	help
-	  This provides basic support for the National Semiconductor SCx200
-	  processor.  Right now this is just a driver for the GPIO pins.
+	  This provides basic support for National Semiconductor's
+	  (now AMD's) Geode processors.  The driver probes for the
+	  PCI-IDs of several on-chip devices, so its a good dependency
+	  for other scx200_* drivers.
 
-	  If you don't know what to do here, say N.
+	  If compiled as a module, the driver is named scx200.
 
-	  This support is also available as a module.  If compiled as a
-	  module, it will be called scx200.
+config SCx200HR_TIMER
+	tristate "NatSemi SCx200 27MHz High-Resolution Timer Support"
+	depends on SCx200 && GENERIC_TIME
+	default y
+	help
+	  This driver provides a clocksource built upon the on-chip
+	  27MHz high-resolution timer.  Its also a workaround for
+	  NSC Geode SC-1100's buggy TSC, which loses time when the
+	  processor goes idle (as is done by the scheduler).  The
+	  other workaround is idle=poll boot option.
+
+config K8_NB
+	def_bool y
+	depends on AGP_AMD64
 
 source "drivers/pcmcia/Kconfig"
 
diff --git a/arch/i386/Kconfig.cpu b/arch/i386/Kconfig.cpu
index eb130482..21c9a4e 100644
--- a/arch/i386/Kconfig.cpu
+++ b/arch/i386/Kconfig.cpu
@@ -41,7 +41,7 @@
 	  - "GeodeGX1" for Geode GX1 (Cyrix MediaGX).
 	  - "Geode GX/LX" For AMD Geode GX and LX processors.
 	  - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
-	  - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
+	  - "VIA C3-2" for VIA C3-2 "Nehemiah" (model 9 and above).
 
 	  If you don't know what to do, choose "386".
 
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index 33e5547..e979466 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -109,8 +109,13 @@
 isoimage: $(BOOTIMAGE)
 	-rm -rf $(obj)/isoimage
 	mkdir $(obj)/isoimage
-	cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \
-		$(obj)/isoimage
+	for i in lib lib64 share end ; do \
+		if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
+			cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
+			break ; \
+		fi ; \
+		if [ $$i = end ] ; then exit 1 ; fi ; \
+	done
 	cp $(BOOTIMAGE) $(obj)/isoimage/linux
 	echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
 	if [ -f '$(FDINITRD)' ] ; then \
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index f19f3a7..b2ccd54 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -24,14 +24,6 @@
 
 #undef memset
 #undef memcpy
-
-/*
- * Why do we do this? Don't ask me..
- *
- * Incomprehensible are the ways of bootloaders.
- */
-static void* memset(void *, int, size_t);
-static void* memcpy(void *, __const void *, size_t);
 #define memzero(s, n)     memset ((s), 0, (n))
 
 typedef unsigned char  uch;
@@ -93,7 +85,7 @@
 #endif
 #define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
 
-extern char input_data[];
+extern unsigned char input_data[];
 extern int input_len;
 
 static long bytes_out = 0;
@@ -103,6 +95,9 @@
 static void *malloc(int size);
 static void free(void *where);
 
+static void *memset(void *s, int c, unsigned n);
+static void *memcpy(void *dest, const void *src, unsigned n);
+
 static void putstr(const char *);
 
 extern int end;
@@ -205,7 +200,7 @@
 	outb_p(0xff & (pos >> 1), vidport+1);
 }
 
-static void* memset(void* s, int c, size_t n)
+static void* memset(void* s, int c, unsigned n)
 {
 	int i;
 	char *ss = (char*)s;
@@ -214,14 +209,13 @@
 	return s;
 }
 
-static void* memcpy(void* __dest, __const void* __src,
-			    size_t __n)
+static void* memcpy(void* dest, const void* src, unsigned n)
 {
 	int i;
-	char *d = (char *)__dest, *s = (char *)__src;
+	char *d = (char *)dest, *s = (char *)src;
 
-	for (i=0;i<__n;i++) d[i] = s[i];
-	return __dest;
+	for (i=0;i<n;i++) d[i] = s[i];
+	return dest;
 }
 
 /* ===========================================================================
@@ -309,7 +303,7 @@
 #else
 	if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory");
 #endif
-	output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
+	output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
 	free_mem_end_ptr = (long)real_mode;
 }
 
@@ -324,11 +318,9 @@
 #ifdef STANDARD_MEMORY_BIOS_CALL
 	if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
 #else
-	if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) <
-			(3*1024))
-		error("Less than 4MB of memory");
+	if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
 #endif	
-	mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+	mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
 	low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
 	  ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
 	low_buffer_size = low_buffer_end - LOW_BUFFER_START;
diff --git a/arch/i386/boot/video.S b/arch/i386/boot/video.S
index c9343c3a..8c2a6fa 100644
--- a/arch/i386/boot/video.S
+++ b/arch/i386/boot/video.S
@@ -1929,7 +1929,7 @@
 	ret
 
 store_edid:
-#ifdef CONFIG_FB_FIRMWARE_EDID
+#ifdef CONFIG_FIRMWARE_EDID
 	pushw	%es				# just save all registers
 	pushw	%ax
 	pushw	%bx
@@ -1947,6 +1947,22 @@
 	rep
 	stosl
 
+	pushw   %es				# save ES
+	xorw    %di, %di                        # Report Capability
+	pushw   %di
+	popw    %es                             # ES:DI must be 0:0
+	movw	$0x4f15, %ax
+	xorw	%bx, %bx
+	xorw	%cx, %cx
+	int	$0x10
+	popw    %es                             # restore ES
+
+	cmpb    $0x00, %ah                      # call successful
+	jne     no_edid
+
+	cmpb    $0x4f, %al                      # function supported
+	jne     no_edid
+
 	movw	$0x4f15, %ax                    # do VBE/DDC
 	movw	$0x01, %bx
 	movw	$0x00, %cx
@@ -1954,6 +1970,7 @@
 	movw	$0x140, %di
 	int	$0x10
 
+no_edid:
 	popw	%di				# restore all registers
 	popw	%dx
 	popw	%cx
diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S
index 911b153..f942f0c 100644
--- a/arch/i386/crypto/aes-i586-asm.S
+++ b/arch/i386/crypto/aes-i586-asm.S
@@ -36,22 +36,19 @@
 .file "aes-i586-asm.S"
 .text
 
-// aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
-// aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1])//
-	
+#include <asm/asm-offsets.h>
+
 #define tlen 1024   // length of each of 4 'xor' arrays (256 32-bit words)
 
-// offsets to parameters with one register pushed onto stack
+/* offsets to parameters with one register pushed onto stack */
+#define tfm 8
+#define out_blk 12
+#define in_blk 16
 
-#define in_blk    8  // input byte array address parameter
-#define out_blk  12  // output byte array address parameter
-#define ctx      16  // AES context structure
-
-// offsets in context structure
-
-#define ekey     0   // encryption key schedule base address
-#define nrnd   256   // number of rounds
-#define dkey   260   // decryption key schedule base address
+/* offsets in crypto_tfm structure */
+#define ekey (crypto_tfm_ctx_offset + 0)
+#define nrnd (crypto_tfm_ctx_offset + 256)
+#define dkey (crypto_tfm_ctx_offset + 260)
 
 // register mapping for encrypt and decrypt subroutines
 
@@ -220,6 +217,7 @@
 	do_col (table, r5,r0,r1,r4, r2,r3);		/* idx=r5 */
 
 // AES (Rijndael) Encryption Subroutine
+/* void aes_enc_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
 
 .global  aes_enc_blk
 
@@ -230,7 +228,7 @@
 
 aes_enc_blk:
 	push    %ebp
-	mov     ctx(%esp),%ebp      // pointer to context
+	mov     tfm(%esp),%ebp
 
 // CAUTION: the order and the values used in these assigns 
 // rely on the register mappings
@@ -295,6 +293,7 @@
 	ret
 
 // AES (Rijndael) Decryption Subroutine
+/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out_blk, const u8 *in_blk) */
 
 .global  aes_dec_blk
 
@@ -305,7 +304,7 @@
 
 aes_dec_blk:
 	push    %ebp
-	mov     ctx(%esp),%ebp       // pointer to context
+	mov     tfm(%esp),%ebp
 
 // CAUTION: the order and the values used in these assigns 
 // rely on the register mappings
diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c
index a50397b1..d3806da 100644
--- a/arch/i386/crypto/aes.c
+++ b/arch/i386/crypto/aes.c
@@ -45,8 +45,8 @@
 #include <linux/crypto.h>
 #include <linux/linkage.h>
 
-asmlinkage void aes_enc_blk(const u8 *src, u8 *dst, void *ctx);
-asmlinkage void aes_dec_blk(const u8 *src, u8 *dst, void *ctx);
+asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 
 #define AES_MIN_KEY_SIZE	16
 #define AES_MAX_KEY_SIZE	32
@@ -378,12 +378,12 @@
 	k[8*(i)+11] = ss[3];						\
 }
 
-static int
-aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len, u32 *flags)
 {
 	int i;
 	u32 ss[8];
-	struct aes_ctx *ctx = ctx_arg;
+	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *key = (const __le32 *)in_key;
 
 	/* encryption schedule */
@@ -464,15 +464,15 @@
 	return 0;
 }
 
-static inline void aes_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	aes_enc_blk(src, dst, ctx);
-}
-static inline void aes_decrypt(void *ctx, u8 *dst, const u8 *src)
-{
-	aes_dec_blk(src, dst, ctx);
+	aes_enc_blk(tfm, dst, src);
 }
 
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	aes_dec_blk(tfm, dst, src);
+}
 
 static struct crypto_alg aes_alg = {
 	.cra_name		=	"aes",
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 96fb8a0..5e70c2f 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -7,10 +7,9 @@
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_i386.o \
 		pci-dma.o i386_ksyms.o i387.o bootflag.o \
-		quirks.o i8237.o topology.o alternative.o
+		quirks.o i8237.o topology.o alternative.o i8253.o tsc.o
 
 obj-y				+= cpu/
-obj-y				+= timers/
 obj-y				+= acpi/
 obj-$(CONFIG_X86_BIOS_REBOOT)	+= reboot.o
 obj-$(CONFIG_MCA)		+= mca.o
@@ -37,6 +36,8 @@
 obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault.o
 obj-$(CONFIG_VM86)		+= vm86.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_HPET_TIMER) 	+= hpet.o
+obj-$(CONFIG_K8_NB)		+= k8.o
 
 EXTRA_AFLAGS   := -traditional
 
@@ -76,3 +77,6 @@
 $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
 			$(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
 	$(call if_changed,syscall)
+
+k8-y                      += ../../x86_64/kernel/k8.o
+
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 40e5aba..97ca171 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -202,6 +202,8 @@
 		if (mcfg->config[i].base_reserved) {
 			printk(KERN_ERR PREFIX
 			       "MMCONFIG not in low 4GB of memory\n");
+			kfree(pci_mmcfg_config);
+			pci_mmcfg_config_num = 0;
 			return -ENODEV;
 		}
 	}
@@ -215,7 +217,7 @@
 {
 	struct acpi_table_madt *madt = NULL;
 
-	if (!phys_addr || !size)
+	if (!phys_addr || !size || !cpu_has_apic)
 		return -EINVAL;
 
 	madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
@@ -621,9 +623,9 @@
 
 static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
 {
-	struct fadt_descriptor_rev2 *fadt = NULL;
+	struct fadt_descriptor *fadt = NULL;
 
-	fadt = (struct fadt_descriptor_rev2 *)__acpi_map_table(phys, size);
+	fadt = (struct fadt_descriptor *)__acpi_map_table(phys, size);
 	if (!fadt) {
 		printk(KERN_WARNING PREFIX "Unable to map FADT\n");
 		return 0;
@@ -754,7 +756,7 @@
 		return -ENODEV;
 	}
 
-	if (!cpu_has_apic)
+	if (!cpu_has_apic) 
 		return -ENODEV;
 
 	/*
diff --git a/arch/i386/kernel/acpi/processor.c b/arch/i386/kernel/acpi/processor.c
index 9f4cc02..b54fded 100644
--- a/arch/i386/kernel/acpi/processor.c
+++ b/arch/i386/kernel/acpi/processor.c
@@ -47,7 +47,7 @@
 	buf[2] = ACPI_PDC_C_CAPABILITY_SMP;
 
 	if (cpu_has(c, X86_FEATURE_EST))
-		buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP;
+		buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
 
 	obj->type = ACPI_TYPE_BUFFER;
 	obj->buffer.length = 12;
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index 1cb2b18..4ee8357 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -8,30 +8,17 @@
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
 #include <linux/dmi.h>
+#include <linux/cpumask.h>
+
 #include <asm/smp.h>
-#include <asm/tlbflush.h>
 
 /* address in low memory of the wakeup routine. */
 unsigned long acpi_wakeup_address = 0;
 unsigned long acpi_video_flags;
 extern char wakeup_start, wakeup_end;
 
-extern void zap_low_mappings(void);
-
 extern unsigned long FASTCALL(acpi_copy_wakeup_routine(unsigned long));
 
-static void init_low_mapping(pgd_t * pgd, int pgd_limit)
-{
-	int pgd_ofs = 0;
-
-	while ((pgd_ofs < pgd_limit)
-	       && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) {
-		set_pgd(pgd, *(pgd + USER_PTRS_PER_PGD));
-		pgd_ofs++, pgd++;
-	}
-	flush_tlb_all();
-}
-
 /**
  * acpi_save_state_mem - save kernel state
  *
@@ -42,7 +29,6 @@
 {
 	if (!acpi_wakeup_address)
 		return 1;
-	init_low_mapping(swapper_pg_dir, USER_PTRS_PER_PGD);
 	memcpy((void *)acpi_wakeup_address, &wakeup_start,
 	       &wakeup_end - &wakeup_start);
 	acpi_copy_wakeup_routine(acpi_wakeup_address);
@@ -55,7 +41,6 @@
  */
 void acpi_restore_state_mem(void)
 {
-	zap_low_mappings();
 }
 
 /**
diff --git a/arch/i386/kernel/acpi/wakeup.S b/arch/i386/kernel/acpi/wakeup.S
index 7c74fe0..9f408ee 100644
--- a/arch/i386/kernel/acpi/wakeup.S
+++ b/arch/i386/kernel/acpi/wakeup.S
@@ -56,7 +56,7 @@
 1:
 
 	# set up page table
-	movl	$swapper_pg_dir-__PAGE_OFFSET, %eax
+	movl	$swsusp_pg_dir-__PAGE_OFFSET, %eax
 	movl	%eax, %cr3
 
 	testl	$1, real_efer_save_restore - wakeup_code
@@ -265,11 +265,6 @@
 	movl	$0x12345678, saved_magic
 	ret
 
-.data
-ALIGN
-ENTRY(saved_magic)	.long	0
-ENTRY(saved_eip)	.long	0
-
 save_registers:
 	leal	4(%esp), %eax
 	movl	%eax, saved_context_esp
@@ -304,7 +299,11 @@
 	call	restore_processor_state
 	ret
 
+.data
 ALIGN
+ENTRY(saved_magic)	.long	0
+ENTRY(saved_eip)	.long	0
+
 # saved registers
 saved_gdt:	.long	0,0
 saved_idt:	.long	0,0
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c
index 5cbd6f9..50eb0e0 100644
--- a/arch/i386/kernel/alternative.c
+++ b/arch/i386/kernel/alternative.c
@@ -4,27 +4,41 @@
 #include <asm/alternative.h>
 #include <asm/sections.h>
 
-#define DEBUG 0
-#if DEBUG
-# define DPRINTK(fmt, args...) printk(fmt, args)
-#else
-# define DPRINTK(fmt, args...)
-#endif
+static int no_replacement    = 0;
+static int smp_alt_once      = 0;
+static int debug_alternative = 0;
 
+static int __init noreplacement_setup(char *s)
+{
+	no_replacement = 1;
+	return 1;
+}
+static int __init bootonly(char *str)
+{
+	smp_alt_once = 1;
+	return 1;
+}
+static int __init debug_alt(char *str)
+{
+	debug_alternative = 1;
+	return 1;
+}
+
+__setup("noreplacement", noreplacement_setup);
+__setup("smp-alt-boot", bootonly);
+__setup("debug-alternative", debug_alt);
+
+#define DPRINTK(fmt, args...) if (debug_alternative) \
+	printk(KERN_DEBUG fmt, args)
+
+#ifdef GENERIC_NOP1
 /* Use inline assembly to define this because the nops are defined
    as inline assembly strings in the include files and we cannot
    get them easily into strings. */
 asm("\t.data\nintelnops: "
 	GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
 	GENERIC_NOP7 GENERIC_NOP8);
-asm("\t.data\nk8nops: "
-	K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
-	K8_NOP7 K8_NOP8);
-asm("\t.data\nk7nops: "
-	K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
-	K7_NOP7 K7_NOP8);
-
-extern unsigned char intelnops[], k8nops[], k7nops[];
+extern unsigned char intelnops[];
 static unsigned char *intel_nops[ASM_NOP_MAX+1] = {
 	NULL,
 	intelnops,
@@ -36,6 +50,13 @@
 	intelnops + 1 + 2 + 3 + 4 + 5 + 6,
 	intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
 };
+#endif
+
+#ifdef K8_NOP1
+asm("\t.data\nk8nops: "
+	K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
+	K8_NOP7 K8_NOP8);
+extern unsigned char k8nops[];
 static unsigned char *k8_nops[ASM_NOP_MAX+1] = {
 	NULL,
 	k8nops,
@@ -47,6 +68,13 @@
 	k8nops + 1 + 2 + 3 + 4 + 5 + 6,
 	k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
 };
+#endif
+
+#ifdef K7_NOP1
+asm("\t.data\nk7nops: "
+	K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
+	K7_NOP7 K7_NOP8);
+extern unsigned char k7nops[];
 static unsigned char *k7_nops[ASM_NOP_MAX+1] = {
 	NULL,
 	k7nops,
@@ -58,6 +86,18 @@
 	k7nops + 1 + 2 + 3 + 4 + 5 + 6,
 	k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
 };
+#endif
+
+#ifdef CONFIG_X86_64
+
+extern char __vsyscall_0;
+static inline unsigned char** find_nop_table(void)
+{
+	return k8_nops;
+}
+
+#else /* CONFIG_X86_64 */
+
 static struct nop {
 	int cpuid;
 	unsigned char **noptable;
@@ -67,14 +107,6 @@
 	{ -1, NULL }
 };
 
-
-extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
-extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
-extern u8 *__smp_locks[], *__smp_locks_end[];
-
-extern u8 __smp_alt_begin[], __smp_alt_end[];
-
-
 static unsigned char** find_nop_table(void)
 {
 	unsigned char **noptable = intel_nops;
@@ -89,6 +121,14 @@
 	return noptable;
 }
 
+#endif /* CONFIG_X86_64 */
+
+extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+extern struct alt_instr __smp_alt_instructions[], __smp_alt_instructions_end[];
+extern u8 *__smp_locks[], *__smp_locks_end[];
+
+extern u8 __smp_alt_begin[], __smp_alt_end[];
+
 /* Replace instructions with better alternatives for this CPU type.
    This runs before SMP is initialized to avoid SMP problems with
    self modifying code. This implies that assymetric systems where
@@ -99,6 +139,7 @@
 {
 	unsigned char **noptable = find_nop_table();
 	struct alt_instr *a;
+	u8 *instr;
 	int diff, i, k;
 
 	DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
@@ -106,7 +147,16 @@
 		BUG_ON(a->replacementlen > a->instrlen);
 		if (!boot_cpu_has(a->cpuid))
 			continue;
-		memcpy(a->instr, a->replacement, a->replacementlen);
+		instr = a->instr;
+#ifdef CONFIG_X86_64
+		/* vsyscall code is not mapped yet. resolve it manually. */
+		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END) {
+			instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
+			DPRINTK("%s: vsyscall fixup: %p => %p\n",
+				__FUNCTION__, a->instr, instr);
+		}
+#endif
+		memcpy(instr, a->replacement, a->replacementlen);
 		diff = a->instrlen - a->replacementlen;
 		/* Pad the rest with nops */
 		for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
@@ -186,14 +236,6 @@
 static LIST_HEAD(smp_alt_modules);
 static DEFINE_SPINLOCK(smp_alt);
 
-static int smp_alt_once = 0;
-static int __init bootonly(char *str)
-{
-	smp_alt_once = 1;
-	return 1;
-}
-__setup("smp-alt-boot", bootonly);
-
 void alternatives_smp_module_add(struct module *mod, char *name,
 				 void *locks, void *locks_end,
 				 void *text,  void *text_end)
@@ -201,6 +243,9 @@
 	struct smp_alt_module *smp;
 	unsigned long flags;
 
+	if (no_replacement)
+		return;
+
 	if (smp_alt_once) {
 		if (boot_cpu_has(X86_FEATURE_UP))
 			alternatives_smp_unlock(locks, locks_end,
@@ -235,7 +280,7 @@
 	struct smp_alt_module *item;
 	unsigned long flags;
 
-	if (smp_alt_once)
+	if (no_replacement || smp_alt_once)
 		return;
 
 	spin_lock_irqsave(&smp_alt, flags);
@@ -256,7 +301,7 @@
 	struct smp_alt_module *mod;
 	unsigned long flags;
 
-	if (smp_alt_once)
+	if (no_replacement || smp_alt_once)
 		return;
 	BUG_ON(!smp && (num_online_cpus() > 1));
 
@@ -285,6 +330,13 @@
 
 void __init alternative_instructions(void)
 {
+	if (no_replacement) {
+		printk(KERN_INFO "(SMP-)alternatives turned off\n");
+		free_init_pages("SMP alternatives",
+				(unsigned long)__smp_alt_begin,
+				(unsigned long)__smp_alt_end);
+		return;
+	}
 	apply_alternatives(__alt_instructions, __alt_instructions_end);
 
 	/* switch to patch-once-at-boottime-only mode and free the
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 3d4b2f3..7ce0949 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -36,6 +36,7 @@
 #include <asm/arch_hooks.h>
 #include <asm/hpet.h>
 #include <asm/i8253.h>
+#include <asm/nmi.h>
 
 #include <mach_apic.h>
 #include <mach_apicdef.h>
@@ -62,7 +63,7 @@
 
 static void apic_pm_activate(void);
 
-int modern_apic(void)
+static int modern_apic(void)
 {
 	unsigned int lvr, version;
 	/* AMD systems use old APIC versions, so check the CPU */
@@ -113,7 +114,7 @@
 }
 
 /* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer = 0;
+int using_apic_timer __read_mostly = 0;
 
 static int enabled_via_apicbase;
 
@@ -156,7 +157,7 @@
 	maxlvt = get_maxlvt();
 
 	/*
-	 * Masking an LVT entry on a P6 can trigger a local APIC error
+	 * Masking an LVT entry can trigger a local APIC error
 	 * if the vector is zero. Mask LVTERR first to prevent this.
 	 */
 	if (maxlvt >= 3) {
@@ -1117,7 +1118,18 @@
 		unsigned long v;
 
 		v = apic_read(APIC_LVTT);
-		apic_write_around(APIC_LVTT, v | APIC_LVT_MASKED);
+		/*
+		 * When an illegal vector value (0-15) is written to an LVT
+		 * entry and delivery mode is Fixed, the APIC may signal an
+		 * illegal vector error, with out regard to whether the mask
+		 * bit is set or whether an interrupt is actually seen on input.
+		 *
+		 * Boot sequence might call this function when the LVTT has
+		 * '0' vector value. So make sure vector field is set to
+		 * valid value.
+		 */
+		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+		apic_write_around(APIC_LVTT, v);
 	}
 }
 
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index df0e174..7c5729d 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -374,14 +374,14 @@
 	unsigned short	segment;
 }				apm_bios_entry;
 static int			clock_slowed;
-static int			idle_threshold = DEFAULT_IDLE_THRESHOLD;
-static int			idle_period = DEFAULT_IDLE_PERIOD;
+static int			idle_threshold __read_mostly = DEFAULT_IDLE_THRESHOLD;
+static int			idle_period __read_mostly = DEFAULT_IDLE_PERIOD;
 static int			set_pm_idle;
 static int			suspends_pending;
 static int			standbys_pending;
 static int			ignore_sys_suspend;
 static int			ignore_normal_resume;
-static int			bounce_interval = DEFAULT_BOUNCE_INTERVAL;
+static int			bounce_interval __read_mostly = DEFAULT_BOUNCE_INTERVAL;
 
 #ifdef CONFIG_APM_RTC_IS_GMT
 #	define	clock_cmos_diff	0
@@ -390,8 +390,8 @@
 static long			clock_cmos_diff;
 static int			got_clock_diff;
 #endif
-static int			debug;
-static int			smp;
+static int			debug __read_mostly;
+static int			smp __read_mostly;
 static int			apm_disabled = -1;
 #ifdef CONFIG_SMP
 static int			power_off;
@@ -403,8 +403,8 @@
 #else
 static int			realmode_power_off;
 #endif
-static int			exit_kapmd;
-static int			kapmd_running;
+static int			exit_kapmd __read_mostly;
+static int			kapmd_running __read_mostly;
 #ifdef CONFIG_APM_ALLOW_INTS
 static int			allow_ints = 1;
 #else
@@ -416,15 +416,15 @@
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
 static DEFINE_SPINLOCK(user_list_lock);
-static struct desc_struct	bad_bios_desc = { 0, 0x00409200 };
+static const struct desc_struct	bad_bios_desc = { 0, 0x00409200 };
 
-static char			driver_version[] = "1.16ac";	/* no spaces */
+static const char		driver_version[] = "1.16ac";	/* no spaces */
 
 /*
  *	APM event names taken from the APM 1.2 specification. These are
  *	the message codes that the BIOS uses to tell us about events
  */
-static char *	apm_event_name[] = {
+static const char *	const apm_event_name[] = {
 	"system standby",
 	"system suspend",
 	"normal resume",
@@ -616,7 +616,7 @@
  *	@ecx_in: ECX register value for BIOS call
  *	@eax: EAX register on return from the BIOS call
  *
- *	Make a BIOS call that does only returns one value, or just status.
+ *	Make a BIOS call that returns one value only, or just status.
  *	If there is an error, then the error code is returned in AH
  *	(bits 8-15 of eax) and this function returns non-zero. This is
  *	used for simpler BIOS operations. This call may hold interrupts
@@ -764,9 +764,9 @@
 	int	idled = 0;
 	int	polling;
 
-	polling = test_thread_flag(TIF_POLLING_NRFLAG);
+	polling = !!(current_thread_info()->status & TS_POLLING);
 	if (polling) {
-		clear_thread_flag(TIF_POLLING_NRFLAG);
+		current_thread_info()->status &= ~TS_POLLING;
 		smp_mb__after_clear_bit();
 	}
 	if (!need_resched()) {
@@ -774,7 +774,7 @@
 		ret = apm_bios_call_simple(APM_FUNC_IDLE, 0, 0, &eax);
 	}
 	if (polling)
-		set_thread_flag(TIF_POLLING_NRFLAG);
+		current_thread_info()->status |= TS_POLLING;
 
 	if (!idled)
 		return 0;
@@ -822,7 +822,7 @@
 #define IDLE_CALC_LIMIT   (HZ * 100)
 #define IDLE_LEAKY_MAX    16
 
-static void (*original_pm_idle)(void);
+static void (*original_pm_idle)(void) __read_mostly;
 
 /**
  * apm_cpu_idle		-	cpu idling for APM capable Linux
@@ -1063,7 +1063,8 @@
  
 static int apm_console_blank(int blank)
 {
-	int error, i;
+	int error = APM_NOT_ENGAGED; /* silence gcc */
+	int i;
 	u_short state;
 	static const u_short dev[3] = { 0x100, 0x1FF, 0x101 };
 
@@ -1104,7 +1105,8 @@
 
 static apm_event_t get_queued_event(struct apm_user *as)
 {
-	as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+	if (++as->event_tail >= APM_MAX_EVENTS)
+		as->event_tail = 0;
 	return as->events[as->event_tail];
 }
 
@@ -1118,13 +1120,16 @@
 	for (as = user_list; as != NULL; as = as->next) {
 		if ((as == sender) || (!as->reader))
 			continue;
-		as->event_head = (as->event_head + 1) % APM_MAX_EVENTS;
+		if (++as->event_head >= APM_MAX_EVENTS)
+			as->event_head = 0;
+
 		if (as->event_head == as->event_tail) {
 			static int notified;
 
 			if (notified++ == 0)
 			    printk(KERN_ERR "apm: an event queue overflowed\n");
-			as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
+			if (++as->event_tail >= APM_MAX_EVENTS)
+				as->event_tail = 0;
 		}
 		as->events[as->event_head] = event;
 		if ((!as->suser) || (!as->writer))
@@ -1282,7 +1287,7 @@
 static apm_event_t get_event(void)
 {
 	int		error;
-	apm_event_t	event;
+	apm_event_t	event = APM_NO_EVENTS; /* silence gcc */
 	apm_eventinfo_t	info;
 
 	static int notified;
diff --git a/arch/i386/kernel/asm-offsets.c b/arch/i386/kernel/asm-offsets.c
index 36d66e2..c80271f 100644
--- a/arch/i386/kernel/asm-offsets.c
+++ b/arch/i386/kernel/asm-offsets.c
@@ -4,6 +4,7 @@
  * to extract and format the required data.
  */
 
+#include <linux/crypto.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/personality.h>
@@ -13,6 +14,7 @@
 #include <asm/fixmap.h>
 #include <asm/processor.h>
 #include <asm/thread_info.h>
+#include <asm/elf.h>
 
 #define DEFINE(sym, val) \
         asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -53,6 +55,7 @@
 	OFFSET(TI_preempt_count, thread_info, preempt_count);
 	OFFSET(TI_addr_limit, thread_info, addr_limit);
 	OFFSET(TI_restart_block, thread_info, restart_block);
+	OFFSET(TI_sysenter_return, thread_info, sysenter_return);
 	BLANK();
 
 	OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
@@ -68,5 +71,7 @@
 		 sizeof(struct tss_struct));
 
 	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
-	DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
+	DEFINE(VDSO_PRELINK, VDSO_PRELINK);
+
+	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
 }
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 786d1a5..e6a2d6b 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -224,22 +224,26 @@
 
 #ifdef CONFIG_X86_HT
 	/*
-	 * On a AMD dual core setup the lower bits of the APIC id
-	 * distingush the cores.  Assumes number of cores is a power
-	 * of two.
+	 * On a AMD multi core setup the lower bits of the APIC id
+	 * distingush the cores.
 	 */
 	if (c->x86_max_cores > 1) {
 		int cpu = smp_processor_id();
-		unsigned bits = 0;
-		while ((1 << bits) < c->x86_max_cores)
-			bits++;
-		cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
-		phys_proc_id[cpu] >>= bits;
+		unsigned bits = (cpuid_ecx(0x80000008) >> 12) & 0xf;
+
+		if (bits == 0) {
+			while ((1 << bits) < c->x86_max_cores)
+				bits++;
+		}
+		c->cpu_core_id = c->phys_proc_id & ((1<<bits)-1);
+		c->phys_proc_id >>= bits;
 		printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
-		       cpu, c->x86_max_cores, cpu_core_id[cpu]);
+		       cpu, c->x86_max_cores, c->cpu_core_id);
 	}
 #endif
 
+	if (cpuid_eax(0x80000000) >= 0x80000006)
+		num_cache_leaves = 3;
 }
 
 static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index a06a490..70c87de 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -11,6 +11,8 @@
 #include <asm/msr.h>
 #include <asm/io.h>
 #include <asm/mmu_context.h>
+#include <asm/mtrr.h>
+#include <asm/mce.h>
 #ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/mpspec.h>
 #include <asm/apic.h>
@@ -292,7 +294,7 @@
 			if (c->x86 >= 0x6)
 				c->x86_model += ((tfms >> 16) & 0xF) << 4;
 			c->x86_mask = tfms & 15;
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_HT
 			c->apicid = phys_pkg_id((ebx >> 24) & 0xFF, 0);
 #else
 			c->apicid = (ebx >> 24) & 0xFF;
@@ -317,7 +319,7 @@
 	early_intel_workaround(c);
 
 #ifdef CONFIG_X86_HT
-	phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
 #endif
 }
 
@@ -475,11 +477,9 @@
 {
 	u32 	eax, ebx, ecx, edx;
 	int 	index_msb, core_bits;
-	int 	cpu = smp_processor_id();
 
 	cpuid(1, &eax, &ebx, &ecx, &edx);
 
-
 	if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
 		return;
 
@@ -490,16 +490,17 @@
 	} else if (smp_num_siblings > 1 ) {
 
 		if (smp_num_siblings > NR_CPUS) {
-			printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
+			printk(KERN_WARNING "CPU: Unsupported number of the "
+					"siblings %d", smp_num_siblings);
 			smp_num_siblings = 1;
 			return;
 		}
 
 		index_msb = get_count_order(smp_num_siblings);
-		phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
+		c->phys_proc_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb);
 
 		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
-		       phys_proc_id[cpu]);
+		       c->phys_proc_id);
 
 		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
 
@@ -507,12 +508,12 @@
 
 		core_bits = get_count_order(c->x86_max_cores);
 
-		cpu_core_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
+		c->cpu_core_id = phys_pkg_id((ebx >> 24) & 0xFF, index_msb) &
 					       ((1 << core_bits) - 1);
 
 		if (c->x86_max_cores > 1)
 			printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
-			       cpu_core_id[cpu]);
+			       c->cpu_core_id);
 	}
 }
 #endif
@@ -611,6 +612,12 @@
 		set_in_cr4(X86_CR4_TSD);
 	}
 
+	/* The CPU hotplug case */
+	if (cpu_gdt_descr->address) {
+		gdt = (struct desc_struct *)cpu_gdt_descr->address;
+		memset(gdt, 0, PAGE_SIZE);
+		goto old_gdt;
+	}
 	/*
 	 * This is a horrible hack to allocate the GDT.  The problem
 	 * is that cpu_init() is called really early for the boot CPU
@@ -629,7 +636,7 @@
 				local_irq_enable();
 		}
 	}
-
+old_gdt:
 	/*
 	 * Initialize the per-CPU GDT with the boot GDT,
 	 * and set up the GDT descriptor:
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
index 3852d0a..5fd6532 100644
--- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
+++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -48,12 +48,13 @@
 
 
 struct cpufreq_acpi_io {
-	struct acpi_processor_performance	acpi_data;
+	struct acpi_processor_performance	*acpi_data;
 	struct cpufreq_frequency_table		*freq_table;
 	unsigned int				resume;
 };
 
 static struct cpufreq_acpi_io	*acpi_io_data[NR_CPUS];
+static struct acpi_processor_performance	*acpi_perf_data[NR_CPUS];
 
 static struct cpufreq_driver acpi_cpufreq_driver;
 
@@ -104,64 +105,43 @@
 {
 	u16			port = 0;
 	u8			bit_width = 0;
+	int			i = 0;
 	int			ret = 0;
 	u32			value = 0;
-	int			i = 0;
-	struct cpufreq_freqs    cpufreq_freqs;
-	cpumask_t		saved_mask;
 	int			retval;
+	struct acpi_processor_performance	*perf;
 
 	dprintk("acpi_processor_set_performance\n");
 
-	/*
-	 * TBD: Use something other than set_cpus_allowed.
-	 * As set_cpus_allowed is a bit racy, 
-	 * with any other set_cpus_allowed for this process.
-	 */
-	saved_mask = current->cpus_allowed;
-	set_cpus_allowed(current, cpumask_of_cpu(cpu));
-	if (smp_processor_id() != cpu) {
-		return (-EAGAIN);
-	}
-	
-	if (state == data->acpi_data.state) {
+	retval = 0;
+	perf = data->acpi_data;	
+	if (state == perf->state) {
 		if (unlikely(data->resume)) {
 			dprintk("Called after resume, resetting to P%d\n", state);
 			data->resume = 0;
 		} else {
 			dprintk("Already at target state (P%d)\n", state);
-			retval = 0;
-			goto migrate_end;
+			return (retval);
 		}
 	}
 
-	dprintk("Transitioning from P%d to P%d\n",
-		data->acpi_data.state, state);
-
-	/* cpufreq frequency struct */
-	cpufreq_freqs.cpu = cpu;
-	cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency;
-	cpufreq_freqs.new = data->freq_table[state].frequency;
-
-	/* notify cpufreq */
-	cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
+	dprintk("Transitioning from P%d to P%d\n", perf->state, state);
 
 	/*
 	 * First we write the target state's 'control' value to the
 	 * control_register.
 	 */
 
-	port = data->acpi_data.control_register.address;
-	bit_width = data->acpi_data.control_register.bit_width;
-	value = (u32) data->acpi_data.states[state].control;
+	port = perf->control_register.address;
+	bit_width = perf->control_register.bit_width;
+	value = (u32) perf->states[state].control;
 
 	dprintk("Writing 0x%08x to port 0x%04x\n", value, port);
 
 	ret = acpi_processor_write_port(port, bit_width, value);
 	if (ret) {
 		dprintk("Invalid port width 0x%04x\n", bit_width);
-		retval = ret;
-		goto migrate_end;
+		return (ret);
 	}
 
 	/*
@@ -177,49 +157,35 @@
 		 * before giving up.
 		 */
 
-		port = data->acpi_data.status_register.address;
-		bit_width = data->acpi_data.status_register.bit_width;
+		port = perf->status_register.address;
+		bit_width = perf->status_register.bit_width;
 
 		dprintk("Looking for 0x%08x from port 0x%04x\n",
-			(u32) data->acpi_data.states[state].status, port);
+			(u32) perf->states[state].status, port);
 
-		for (i=0; i<100; i++) {
+		for (i = 0; i < 100; i++) {
 			ret = acpi_processor_read_port(port, bit_width, &value);
 			if (ret) {	
 				dprintk("Invalid port width 0x%04x\n", bit_width);
-				retval = ret;
-				goto migrate_end;
+				return (ret);
 			}
-			if (value == (u32) data->acpi_data.states[state].status)
+			if (value == (u32) perf->states[state].status)
 				break;
 			udelay(10);
 		}
 	} else {
-		i = 0;
-		value = (u32) data->acpi_data.states[state].status;
+		value = (u32) perf->states[state].status;
 	}
 
-	/* notify cpufreq */
-	cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
-
-	if (unlikely(value != (u32) data->acpi_data.states[state].status)) {
-		unsigned int tmp = cpufreq_freqs.new;
-		cpufreq_freqs.new = cpufreq_freqs.old;
-		cpufreq_freqs.old = tmp;
-		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE);
-		cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE);
+	if (unlikely(value != (u32) perf->states[state].status)) {
 		printk(KERN_WARNING "acpi-cpufreq: Transition failed\n");
 		retval = -ENODEV;
-		goto migrate_end;
+		return (retval);
 	}
 
 	dprintk("Transition successful after %d microseconds\n", i * 10);
 
-	data->acpi_data.state = state;
-
-	retval = 0;
-migrate_end:
-	set_cpus_allowed(current, saved_mask);
+	perf->state = state;
 	return (retval);
 }
 
@@ -231,8 +197,17 @@
 	unsigned int relation)
 {
 	struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
+	struct acpi_processor_performance *perf;
+	struct cpufreq_freqs freqs;
+	cpumask_t online_policy_cpus;
+	cpumask_t saved_mask;
+	cpumask_t set_mask;
+	cpumask_t covered_cpus;
+	unsigned int cur_state = 0;
 	unsigned int next_state = 0;
 	unsigned int result = 0;
+	unsigned int j;
+	unsigned int tmp;
 
 	dprintk("acpi_cpufreq_setpolicy\n");
 
@@ -241,11 +216,95 @@
 			target_freq,
 			relation,
 			&next_state);
-	if (result)
+	if (unlikely(result))
 		return (result);
 
-	result = acpi_processor_set_performance (data, policy->cpu, next_state);
+	perf = data->acpi_data;
+	cur_state = perf->state;
+	freqs.old = data->freq_table[cur_state].frequency;
+	freqs.new = data->freq_table[next_state].frequency;
 
+#ifdef CONFIG_HOTPLUG_CPU
+	/* cpufreq holds the hotplug lock, so we are safe from here on */
+	cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
+#else
+	online_policy_cpus = policy->cpus;
+#endif
+
+	for_each_cpu_mask(j, online_policy_cpus) {
+		freqs.cpu = j;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	}
+
+	/*
+	 * We need to call driver->target() on all or any CPU in
+	 * policy->cpus, depending on policy->shared_type.
+	 */
+	saved_mask = current->cpus_allowed;
+	cpus_clear(covered_cpus);
+	for_each_cpu_mask(j, online_policy_cpus) {
+		/*
+		 * Support for SMP systems.
+		 * Make sure we are running on CPU that wants to change freq
+		 */
+		cpus_clear(set_mask);
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			cpus_or(set_mask, set_mask, online_policy_cpus);
+		else
+			cpu_set(j, set_mask);
+
+		set_cpus_allowed(current, set_mask);
+		if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
+			dprintk("couldn't limit to CPUs in this domain\n");
+			result = -EAGAIN;
+			break;
+		}
+
+		result = acpi_processor_set_performance (data, j, next_state);
+		if (result) {
+			result = -EAGAIN;
+			break;
+		}
+
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			break;
+ 
+		cpu_set(j, covered_cpus);
+	}
+
+	for_each_cpu_mask(j, online_policy_cpus) {
+		freqs.cpu = j;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
+
+	if (unlikely(result)) {
+		/*
+		 * We have failed halfway through the frequency change.
+		 * We have sent callbacks to online_policy_cpus and
+		 * acpi_processor_set_performance() has been called on 
+		 * coverd_cpus. Best effort undo..
+		 */
+
+		if (!cpus_empty(covered_cpus)) {
+			for_each_cpu_mask(j, covered_cpus) {
+				policy->cpu = j;
+				acpi_processor_set_performance (data, 
+						j, 
+						cur_state);
+			}
+		}
+
+		tmp = freqs.new;
+		freqs.new = freqs.old;
+		freqs.old = tmp;
+		for_each_cpu_mask(j, online_policy_cpus) {
+			freqs.cpu = j;
+			cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+		}
+	}
+
+	set_cpus_allowed(current, saved_mask);
 	return (result);
 }
 
@@ -271,30 +330,65 @@
 	struct cpufreq_acpi_io	*data,
 	unsigned int		cpu)
 {
+	struct acpi_processor_performance	*perf = data->acpi_data;
+
 	if (cpu_khz) {
 		/* search the closest match to cpu_khz */
 		unsigned int i;
 		unsigned long freq;
-		unsigned long freqn = data->acpi_data.states[0].core_frequency * 1000;
+		unsigned long freqn = perf->states[0].core_frequency * 1000;
 
-		for (i=0; i < (data->acpi_data.state_count - 1); i++) {
+		for (i = 0; i < (perf->state_count - 1); i++) {
 			freq = freqn;
-			freqn = data->acpi_data.states[i+1].core_frequency * 1000;
+			freqn = perf->states[i+1].core_frequency * 1000;
 			if ((2 * cpu_khz) > (freqn + freq)) {
-				data->acpi_data.state = i;
+				perf->state = i;
 				return (freq);
 			}
 		}
-		data->acpi_data.state = data->acpi_data.state_count - 1;
+		perf->state = perf->state_count - 1;
 		return (freqn);
-	} else
+	} else {
 		/* assume CPU is at P0... */
-		data->acpi_data.state = 0;
-		return data->acpi_data.states[0].core_frequency * 1000;
-	
+		perf->state = 0;
+		return perf->states[0].core_frequency * 1000;
+	}
 }
 
 
+/*
+ * acpi_cpufreq_early_init - initialize ACPI P-States library
+ *
+ * Initialize the ACPI P-States library (drivers/acpi/processor_perflib.c)
+ * in order to determine correct frequency and voltage pairings. We can
+ * do _PDC and _PSD and find out the processor dependency for the
+ * actual init that will happen later...
+ */
+static int acpi_cpufreq_early_init_acpi(void)
+{
+	struct acpi_processor_performance	*data;
+	unsigned int				i, j;
+
+	dprintk("acpi_cpufreq_early_init\n");
+
+	for_each_possible_cpu(i) {
+		data = kzalloc(sizeof(struct acpi_processor_performance), 
+			GFP_KERNEL);
+		if (!data) {
+			for_each_possible_cpu(j) {
+				kfree(acpi_perf_data[j]);
+				acpi_perf_data[j] = NULL;
+			}
+			return (-ENOMEM);
+		}
+		acpi_perf_data[i] = data;
+	}
+
+	/* Do initialization in ACPI core */
+	acpi_processor_preregister_performance(acpi_perf_data);
+	return 0;
+}
+
 static int
 acpi_cpufreq_cpu_init (
 	struct cpufreq_policy   *policy)
@@ -304,41 +398,51 @@
 	struct cpufreq_acpi_io	*data;
 	unsigned int		result = 0;
 	struct cpuinfo_x86 *c = &cpu_data[policy->cpu];
+	struct acpi_processor_performance	*perf;
 
 	dprintk("acpi_cpufreq_cpu_init\n");
 
+	if (!acpi_perf_data[cpu])
+		return (-ENODEV);
+
 	data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
 	if (!data)
 		return (-ENOMEM);
 
+	data->acpi_data = acpi_perf_data[cpu];
 	acpi_io_data[cpu] = data;
 
-	result = acpi_processor_register_performance(&data->acpi_data, cpu);
+	result = acpi_processor_register_performance(data->acpi_data, cpu);
 
 	if (result)
 		goto err_free;
 
+	perf = data->acpi_data;
+	policy->cpus = perf->shared_cpu_map;
+	policy->shared_type = perf->shared_type;
+
 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
 		acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS;
 	}
 
 	/* capability check */
-	if (data->acpi_data.state_count <= 1) {
+	if (perf->state_count <= 1) {
 		dprintk("No P-States\n");
 		result = -ENODEV;
 		goto err_unreg;
 	}
-	if ((data->acpi_data.control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
-	    (data->acpi_data.status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+
+	if ((perf->control_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO) ||
+	    (perf->status_register.space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
 		dprintk("Unsupported address space [%d, %d]\n",
-			(u32) (data->acpi_data.control_register.space_id),
-			(u32) (data->acpi_data.status_register.space_id));
+			(u32) (perf->control_register.space_id),
+			(u32) (perf->status_register.space_id));
 		result = -ENODEV;
 		goto err_unreg;
 	}
 
 	/* alloc freq_table */
-	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (data->acpi_data.state_count + 1), GFP_KERNEL);
+	data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * (perf->state_count + 1), GFP_KERNEL);
 	if (!data->freq_table) {
 		result = -ENOMEM;
 		goto err_unreg;
@@ -346,9 +450,9 @@
 
 	/* detect transition latency */
 	policy->cpuinfo.transition_latency = 0;
-	for (i=0; i<data->acpi_data.state_count; i++) {
-		if ((data->acpi_data.states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
-			policy->cpuinfo.transition_latency = data->acpi_data.states[i].transition_latency * 1000;
+	for (i=0; i<perf->state_count; i++) {
+		if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency)
+			policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000;
 	}
 	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
 
@@ -356,11 +460,11 @@
 	policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
 
 	/* table init */
-	for (i=0; i<=data->acpi_data.state_count; i++)
+	for (i=0; i<=perf->state_count; i++)
 	{
 		data->freq_table[i].index = i;
-		if (i<data->acpi_data.state_count)
-			data->freq_table[i].frequency = data->acpi_data.states[i].core_frequency * 1000;
+		if (i<perf->state_count)
+			data->freq_table[i].frequency = perf->states[i].core_frequency * 1000;
 		else
 			data->freq_table[i].frequency = CPUFREQ_TABLE_END;
 	}
@@ -375,12 +479,12 @@
 
 	printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management activated.\n",
 	       cpu);
-	for (i = 0; i < data->acpi_data.state_count; i++)
+	for (i = 0; i < perf->state_count; i++)
 		dprintk("     %cP%d: %d MHz, %d mW, %d uS\n",
-			(i == data->acpi_data.state?'*':' '), i,
-			(u32) data->acpi_data.states[i].core_frequency,
-			(u32) data->acpi_data.states[i].power,
-			(u32) data->acpi_data.states[i].transition_latency);
+			(i == perf->state?'*':' '), i,
+			(u32) perf->states[i].core_frequency,
+			(u32) perf->states[i].power,
+			(u32) perf->states[i].transition_latency);
 
 	cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
 	
@@ -395,7 +499,7 @@
  err_freqfree:
 	kfree(data->freq_table);
  err_unreg:
-	acpi_processor_unregister_performance(&data->acpi_data, cpu);
+	acpi_processor_unregister_performance(perf, cpu);
  err_free:
 	kfree(data);
 	acpi_io_data[cpu] = NULL;
@@ -416,7 +520,7 @@
 	if (data) {
 		cpufreq_frequency_table_put_attr(policy->cpu);
 		acpi_io_data[policy->cpu] = NULL;
-		acpi_processor_unregister_performance(&data->acpi_data, policy->cpu);
+		acpi_processor_unregister_performance(data->acpi_data, policy->cpu);
 		kfree(data);
 	}
 
@@ -444,14 +548,15 @@
 };
 
 static struct cpufreq_driver acpi_cpufreq_driver = {
-	.verify 	= acpi_cpufreq_verify,
-	.target 	= acpi_cpufreq_target,
-	.init		= acpi_cpufreq_cpu_init,
-	.exit		= acpi_cpufreq_cpu_exit,
-	.resume		= acpi_cpufreq_resume,
-	.name		= "acpi-cpufreq",
-	.owner		= THIS_MODULE,
-	.attr           = acpi_cpufreq_attr,
+	.verify	= acpi_cpufreq_verify,
+	.target	= acpi_cpufreq_target,
+	.init	= acpi_cpufreq_cpu_init,
+	.exit	= acpi_cpufreq_cpu_exit,
+	.resume	= acpi_cpufreq_resume,
+	.name	= "acpi-cpufreq",
+	.owner	= THIS_MODULE,
+	.attr	= acpi_cpufreq_attr,
+	.flags	= CPUFREQ_STICKY,
 };
 
 
@@ -462,7 +567,10 @@
 
 	dprintk("acpi_cpufreq_init\n");
 
- 	result = cpufreq_register_driver(&acpi_cpufreq_driver);
+	result = acpi_cpufreq_early_init_acpi();
+
+	if (!result)
+ 		result = cpufreq_register_driver(&acpi_cpufreq_driver);
 	
 	return (result);
 }
@@ -471,10 +579,15 @@
 static void __exit
 acpi_cpufreq_exit (void)
 {
+	unsigned int	i;
 	dprintk("acpi_cpufreq_exit\n");
 
 	cpufreq_unregister_driver(&acpi_cpufreq_driver);
 
+	for_each_possible_cpu(i) {
+		kfree(acpi_perf_data[i]);
+		acpi_perf_data[i] = NULL;
+	}
 	return;
 }
 
diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
index f275e0d..0d49d73 100644
--- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
+++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c
@@ -1,5 +1,5 @@
 /*
- * (C) 2004  Sebastian Witt <se.witt@gmx.net>
+ * (C) 2004-2006  Sebastian Witt <se.witt@gmx.net>
  *
  *  Licensed under the terms of the GNU GPL License version 2.
  *  Based upon reverse engineered information
@@ -90,7 +90,7 @@
 
 	/* Try to calculate multiplier and divider up to 4 times */
 	while (((mul == 0) || (div == 0)) && (tried <= 3)) {
-		for (xdiv = 1; xdiv <= 0x80; xdiv++)
+		for (xdiv = 2; xdiv <= 0x80; xdiv++)
 			for (xmul = 1; xmul <= 0xfe; xmul++)
 				if (nforce2_calc_fsb(NFORCE2_PLL(xmul, xdiv)) ==
 				    fsb + tried) {
@@ -117,8 +117,7 @@
 	int temp;
 
 	/* Set the pll addr. to 0x00 */
-	temp = 0x00;
-	pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, temp);
+	pci_write_config_dword(nforce2_chipset_dev, NFORCE2_PLLADR, 0);
 
 	/* Now write the value in all 64 registers */
 	for (temp = 0; temp <= 0x3f; temp++)
@@ -266,7 +265,7 @@
 	if (freqs.old == freqs.new)
 		return 0;
 
-	dprintk(KERN_INFO "cpufreq: Old CPU frequency %d kHz, new %d kHz\n",
+	dprintk("Old CPU frequency %d kHz, new %d kHz\n",
 	       freqs.old, freqs.new);
 
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -278,7 +277,7 @@
 		printk(KERN_ERR "cpufreq: Changing FSB to %d failed\n",
                        target_fsb);
 	else
-		dprintk(KERN_INFO "cpufreq: Changed FSB successfully to %d\n",
+		dprintk("Changed FSB successfully to %d\n",
                        target_fsb);
 
 	/* Enable IRQs */
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index 8ef3854..146f607 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -77,13 +77,17 @@
 
 static char *print_speed(int speed)
 {
-	if (speed > 1000) {
-		if (speed%1000 == 0)
-			sprintf (speedbuffer, "%dGHz", speed/1000);
-		else
-			sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100);
-	} else
-		sprintf (speedbuffer, "%dMHz", speed);
+	if (speed < 1000) {
+		snprintf(speedbuffer, sizeof(speedbuffer),"%dMHz", speed);
+		return speedbuffer;
+	}
+
+	if (speed%1000 == 0)
+		snprintf(speedbuffer, sizeof(speedbuffer),
+			"%dGHz", speed/1000);
+	else
+		snprintf(speedbuffer, sizeof(speedbuffer),
+			"%d.%dGHz", speed/1000, (speed%1000)/100);
 
 	return speedbuffer;
 }
@@ -675,7 +679,7 @@
 
 static void __exit longhaul_exit(void)
 {
-	int i=0;
+	int i;
 
 	for (i=0; i < numscales; i++) {
 		if (clock_ratio[i] == maxmult) {
diff --git a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c
index e3868de..b268951 100644
--- a/arch/i386/kernel/cpu/cpufreq/longrun.c
+++ b/arch/i386/kernel/cpu/cpufreq/longrun.c
@@ -223,7 +223,6 @@
 		/* set to 0 to try_hi perf_pctg */
 		msr_lo &= 0xFFFFFF80;
 		msr_hi &= 0xFFFFFF80;
-		msr_lo |= 0;
 		msr_hi |= try_hi;
 		wrmsr(MSR_TMTA_LONGRUN_CTRL, msr_lo, msr_hi);
 
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 2bf4237..694d479 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -452,23 +452,23 @@
 
 			pst = (struct pst_s *) p;
 
-			for (i = 0 ; i <psb->numpst; i++) {
+			for (j=0; j<psb->numpst; j++) {
 				pst = (struct pst_s *) p;
 				number_scales = pst->numpstates;
 
 				if ((etuple == pst->cpuid) && check_fsb(pst->fsbspeed) &&
 				    (maxfid==pst->maxfid) && (startvid==pst->startvid))
 				{
-					dprintk ("PST:%d (@%p)\n", i, pst);
+					dprintk ("PST:%d (@%p)\n", j, pst);
 					dprintk (" cpuid: 0x%x  fsb: %d  maxFID: 0x%x  startvid: 0x%x\n",
 						 pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
 
 					ret = get_ranges ((char *) pst + sizeof (struct pst_s));
 					return ret;
-
 				} else {
+					unsigned int k;
 					p = (char *) pst + sizeof (struct pst_s);
-					for (j=0 ; j < number_scales; j++)
+					for (k=0; k<number_scales; k++)
 						p+=2;
 				}
 			}
@@ -581,10 +581,7 @@
 
 	rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
 
-	/* recalibrate cpu_khz */
-	result = recalibrate_cpu_khz();
-	if (result)
-		return result;
+	recalibrate_cpu_khz();
 
 	fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
 	if (!fsb) {
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 71fffa1..2d64916 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -1,5 +1,5 @@
 /*
- *   (c) 2003, 2004, 2005 Advanced Micro Devices, Inc.
+ *   (c) 2003-2006 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
@@ -14,13 +14,13 @@
  *  Based upon datasheets & sample CPUs kindly provided by AMD.
  *
  *  Valuable input gratefully received from Dave Jones, Pavel Machek,
- *  Dominik Brodowski, and others.
+ *  Dominik Brodowski, Jacob Shin, and others.
  *  Originally developed by Paul Devriendt.
  *  Processor information obtained from Chapter 9 (Power and Thermal Management)
  *  of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
  *  Opteron Processors" available for download from www.amd.com
  *
- *  Tables for specific CPUs can be infrerred from
+ *  Tables for specific CPUs can be inferred from
  *     http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
  */
 
@@ -46,7 +46,7 @@
 
 #define PFX "powernow-k8: "
 #define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.2"
+#define VERSION "version 2.00.00"
 #include "powernow-k8.h"
 
 /* serialize freq changes  */
@@ -54,6 +54,8 @@
 
 static struct powernow_k8_data *powernow_data[NR_CPUS];
 
+static int cpu_family = CPU_OPTERON;
+
 #ifndef CONFIG_SMP
 static cpumask_t cpu_core_map[1];
 #endif
@@ -64,16 +66,36 @@
 	return 800 + (fid * 100);
 }
 
+
 /* Return a frequency in KHz, given an input fid */
 static u32 find_khz_freq_from_fid(u32 fid)
 {
 	return 1000 * find_freq_from_fid(fid);
 }
 
-/* Return a voltage in miliVolts, given an input vid */
-static u32 find_millivolts_from_vid(struct powernow_k8_data *data, u32 vid)
+/* Return a frequency in MHz, given an input fid and did */
+static u32 find_freq_from_fiddid(u32 fid, u32 did)
 {
-	return 1550-vid*25;
+	return 100 * (fid + 0x10) >> did;
+}
+
+static u32 find_khz_freq_from_fiddid(u32 fid, u32 did)
+{
+	return 1000 * find_freq_from_fiddid(fid, did);
+}
+
+static u32 find_fid_from_pstate(u32 pstate)
+{
+	u32 hi, lo;
+	rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
+	return lo & HW_PSTATE_FID_MASK;
+}
+
+static u32 find_did_from_pstate(u32 pstate)
+{
+	u32 hi, lo;
+	rdmsr(MSR_PSTATE_DEF_BASE + pstate, lo, hi);
+	return (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
 }
 
 /* Return the vco fid for an input fid
@@ -98,6 +120,9 @@
 {
 	u32 lo, hi;
 
+	if (cpu_family == CPU_HW_PSTATE)
+		return 0;
+
 	rdmsr(MSR_FIDVID_STATUS, lo, hi);
 	return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
 }
@@ -111,6 +136,14 @@
 	u32 lo, hi;
 	u32 i = 0;
 
+	if (cpu_family == CPU_HW_PSTATE) {
+		rdmsr(MSR_PSTATE_STATUS, lo, hi);
+		i = lo & HW_PSTATE_MASK;
+		rdmsr(MSR_PSTATE_DEF_BASE + i, lo, hi);
+		data->currfid = lo & HW_PSTATE_FID_MASK;
+		data->currdid = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
+		return 0;
+	}
 	do {
 		if (i++ > 10000) {
 			dprintk("detected change pending stuck\n");
@@ -175,7 +208,7 @@
 	do {
 		wrmsr(MSR_FIDVID_CTL, lo, data->plllock * PLL_LOCK_CONVERSION);
 		if (i++ > 100) {
-			printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n");
+			printk(KERN_ERR PFX "Hardware error - pending bit very stuck - no further pstate changes possible\n");
 			return 1;
 		}
 	} while (query_current_values_with_pending_wait(data));
@@ -255,7 +288,15 @@
 	return 0;
 }
 
-/* Change the fid and vid, by the 3 phases. */
+/* Change hardware pstate by single MSR write */
+static int transition_pstate(struct powernow_k8_data *data, u32 pstate)
+{
+	wrmsr(MSR_PSTATE_CTRL, pstate, 0);
+	data->currfid = find_fid_from_pstate(pstate);
+	return 0;
+}
+
+/* Change Opteron/Athlon64 fid and vid, by the 3 phases. */
 static int transition_fid_vid(struct powernow_k8_data *data, u32 reqfid, u32 reqvid)
 {
 	if (core_voltage_pre_transition(data, reqvid))
@@ -474,26 +515,35 @@
 		goto out;
 
 	eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
-	if ((eax & CPUID_XFAM) != CPUID_XFAM_K8)
+	if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) &&
+	    ((eax & CPUID_XFAM) < CPUID_XFAM_10H))
 		goto out;
 
-	if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
-	    ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
-		printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
-		goto out;
-	}
+	if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) {
+		if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
+		    ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) {
+			printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
+			goto out;
+		}
 
-	eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
-	if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
-		printk(KERN_INFO PFX
-		       "No frequency change capabilities detected\n");
-		goto out;
-	}
+		eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
+		if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
+			printk(KERN_INFO PFX
+			       "No frequency change capabilities detected\n");
+			goto out;
+		}
 
-	cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
-	if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
-		printk(KERN_INFO PFX "Power state transitions not supported\n");
-		goto out;
+		cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
+		if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
+			printk(KERN_INFO PFX "Power state transitions not supported\n");
+			goto out;
+		}
+	} else { /* must be a HW Pstate capable processor */
+		cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
+		if ((edx & USE_HW_PSTATE) == USE_HW_PSTATE)
+			cpu_family = CPU_HW_PSTATE;
+		else
+			goto out;
 	}
 
 	rc = 1;
@@ -547,12 +597,18 @@
 {
 	int j;
 	for (j = 0; j < data->numps; j++) {
-		if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID)
-			printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x (%d mV)\n", j,
+		if (data->powernow_table[j].frequency != CPUFREQ_ENTRY_INVALID) {
+			if (cpu_family == CPU_HW_PSTATE) {
+			printk(KERN_INFO PFX "   %d : fid 0x%x gid 0x%x (%d MHz)\n", j, (data->powernow_table[j].index & 0xff00) >> 8,
+				(data->powernow_table[j].index & 0xff0000) >> 16,
+				data->powernow_table[j].frequency/1000);
+			} else {
+			printk(KERN_INFO PFX "   %d : fid 0x%x (%d MHz), vid 0x%x\n", j,
 				data->powernow_table[j].index & 0xff,
 				data->powernow_table[j].frequency/1000,
-				data->powernow_table[j].index >> 8,
-				find_millivolts_from_vid(data, data->powernow_table[j].index >> 8));
+				data->powernow_table[j].index >> 8);
+			}
+		}
 	}
 	if (data->batps)
 		printk(KERN_INFO PFX "Only %d pstates on battery\n", data->batps);
@@ -702,7 +758,7 @@
 #ifdef CONFIG_X86_POWERNOW_K8_ACPI
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index)
 {
-	if (!data->acpi_data.state_count)
+	if (!data->acpi_data.state_count || (cpu_family == CPU_HW_PSTATE))
 		return;
 
 	data->irt = (data->acpi_data.states[index].control >> IRT_SHIFT) & IRT_MASK;
@@ -715,9 +771,8 @@
 
 static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
 {
-	int i;
-	int cntlofreq = 0;
 	struct cpufreq_frequency_table *powernow_table;
+	int ret_val;
 
 	if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
 		dprintk("register performance failed: bad ACPI data\n");
@@ -746,13 +801,92 @@
 		goto err_out;
 	}
 
+	if (cpu_family == CPU_HW_PSTATE)
+		ret_val = fill_powernow_table_pstate(data, powernow_table);
+	else
+		ret_val = fill_powernow_table_fidvid(data, powernow_table);
+	if (ret_val)
+		goto err_out_mem;
+
+	powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
+	powernow_table[data->acpi_data.state_count].index = 0;
+	data->powernow_table = powernow_table;
+
+	/* fill in data */
+	data->numps = data->acpi_data.state_count;
+	print_basics(data);
+	powernow_k8_acpi_pst_values(data, 0);
+
+	/* notify BIOS that we exist */
+	acpi_processor_notify_smm(THIS_MODULE);
+
+	return 0;
+
+err_out_mem:
+	kfree(powernow_table);
+
+err_out:
+	acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
+
+	/* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
+	data->acpi_data.state_count = 0;
+
+	return -ENODEV;
+}
+
+static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
+{
+	int i;
+
+	for (i = 0; i < data->acpi_data.state_count; i++) {
+		u32 index;
+		u32 hi = 0, lo = 0;
+		u32 fid;
+		u32 did;
+
+		index = data->acpi_data.states[i].control & HW_PSTATE_MASK;
+		if (index > MAX_HW_PSTATE) {
+			printk(KERN_ERR PFX "invalid pstate %d - bad value %d.\n", i, index);
+			printk(KERN_ERR PFX "Please report to BIOS manufacturer\n");
+		}
+		rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
+		if (!(hi & HW_PSTATE_VALID_MASK)) {
+			dprintk("invalid pstate %d, ignoring\n", index);
+			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+			continue;
+		}
+
+		fid = lo & HW_PSTATE_FID_MASK;
+		did = (lo & HW_PSTATE_DID_MASK) >> HW_PSTATE_DID_SHIFT;
+
+		dprintk("   %d : fid 0x%x, did 0x%x\n", index, fid, did);
+
+		powernow_table[i].index = index | (fid << HW_FID_INDEX_SHIFT) | (did << HW_DID_INDEX_SHIFT);
+
+		powernow_table[i].frequency = find_khz_freq_from_fiddid(fid, did);
+
+		if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
+			printk(KERN_INFO PFX "invalid freq entries %u kHz vs. %u kHz\n",
+				powernow_table[i].frequency,
+				(unsigned int) (data->acpi_data.states[i].core_frequency * 1000));
+			powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+			continue;
+		}
+	}
+	return 0;
+}
+
+static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table)
+{
+	int i;
+	int cntlofreq = 0;
 	for (i = 0; i < data->acpi_data.state_count; i++) {
 		u32 fid;
 		u32 vid;
 
 		if (data->exttype) {
-			fid = data->acpi_data.states[i].status & FID_MASK;
-			vid = (data->acpi_data.states[i].status >> VID_SHIFT) & VID_MASK;
+			fid = data->acpi_data.states[i].status & EXT_FID_MASK;
+			vid = (data->acpi_data.states[i].status >> VID_SHIFT) & EXT_VID_MASK;
 		} else {
 			fid = data->acpi_data.states[i].control & FID_MASK;
 			vid = (data->acpi_data.states[i].control >> VID_SHIFT) & VID_MASK;
@@ -786,7 +920,7 @@
 				if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
 				    (powernow_table[i].index != powernow_table[cntlofreq].index)) {
 					printk(KERN_ERR PFX "Too many lo freq table entries\n");
-					goto err_out_mem;
+					return 1;
 				}
 
 				dprintk("double low frequency table entry, ignoring it.\n");
@@ -804,31 +938,7 @@
 			continue;
 		}
 	}
-
-	powernow_table[data->acpi_data.state_count].frequency = CPUFREQ_TABLE_END;
-	powernow_table[data->acpi_data.state_count].index = 0;
-	data->powernow_table = powernow_table;
-
-	/* fill in data */
-	data->numps = data->acpi_data.state_count;
-	print_basics(data);
-	powernow_k8_acpi_pst_values(data, 0);
-
-	/* notify BIOS that we exist */
-	acpi_processor_notify_smm(THIS_MODULE);
-
 	return 0;
-
-err_out_mem:
-	kfree(powernow_table);
-
-err_out:
-	acpi_processor_unregister_performance(&data->acpi_data, data->cpu);
-
-	/* data->acpi_data.state_count informs us at ->exit() whether ACPI was used */
-	data->acpi_data.state_count = 0;
-
-	return -ENODEV;
 }
 
 static void powernow_k8_cpu_exit_acpi(struct powernow_k8_data *data)
@@ -844,20 +954,20 @@
 #endif /* CONFIG_X86_POWERNOW_K8_ACPI */
 
 /* Take a frequency, and issue the fid/vid transition command */
-static int transition_frequency(struct powernow_k8_data *data, unsigned int index)
+static int transition_frequency_fidvid(struct powernow_k8_data *data, unsigned int index)
 {
-	u32 fid;
-	u32 vid;
+	u32 fid = 0;
+	u32 vid = 0;
 	int res, i;
 	struct cpufreq_freqs freqs;
 
 	dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
 
+	/* fid/vid correctness check for k8 */
 	/* fid are the lower 8 bits of the index we stored into
-	 * the cpufreq frequency table in find_psb_table, vid are
-	 * the upper 8 bits.
+	 * the cpufreq frequency table in find_psb_table, vid
+	 * are the upper 8 bits.
 	 */
-
 	fid = data->powernow_table[index].index & 0xFF;
 	vid = (data->powernow_table[index].index & 0xFF00) >> 8;
 
@@ -881,22 +991,58 @@
 
 	dprintk("cpu %d, changing to fid 0x%x, vid 0x%x\n",
 		smp_processor_id(), fid, vid);
-
-	freqs.cpu = data->cpu;
 	freqs.old = find_khz_freq_from_fid(data->currfid);
 	freqs.new = find_khz_freq_from_fid(fid);
-	for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+
+	for_each_cpu_mask(i, *(data->available_cores)) {
 		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	}
 
 	res = transition_fid_vid(data, fid, vid);
-
 	freqs.new = find_khz_freq_from_fid(data->currfid);
-	for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+
+	for_each_cpu_mask(i, *(data->available_cores)) {
 		freqs.cpu = i;
 		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-        }
+	}
+	return res;
+}
+
+/* Take a frequency, and issue the hardware pstate transition command */
+static int transition_frequency_pstate(struct powernow_k8_data *data, unsigned int index)
+{
+	u32 fid = 0;
+	u32 did = 0;
+	u32 pstate = 0;
+	int res, i;
+	struct cpufreq_freqs freqs;
+
+	dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
+
+	/* get fid did for hardware pstate transition */
+	pstate = index & HW_PSTATE_MASK;
+	if (pstate > MAX_HW_PSTATE)
+		return 0;
+	fid = (index & HW_FID_INDEX_MASK) >> HW_FID_INDEX_SHIFT;
+	did = (index & HW_DID_INDEX_MASK) >> HW_DID_INDEX_SHIFT;
+	freqs.old = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+	freqs.new = find_khz_freq_from_fiddid(fid, did);
+
+	for_each_cpu_mask(i, *(data->available_cores)) {
+		freqs.cpu = i;
+		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+	}
+
+	res = transition_pstate(data, pstate);
+	data->currfid = find_fid_from_pstate(pstate);
+	data->currdid = find_did_from_pstate(pstate);
+	freqs.new = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+
+	for_each_cpu_mask(i, *(data->available_cores)) {
+		freqs.cpu = i;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+	}
 	return res;
 }
 
@@ -933,18 +1079,21 @@
 	dprintk("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
 		pol->cpu, targfreq, pol->min, pol->max, relation);
 
-	if (query_current_values_with_pending_wait(data)) {
-		ret = -EIO;
+	if (query_current_values_with_pending_wait(data))
 		goto err_out;
-	}
 
-	dprintk("targ: curr fid 0x%x, vid 0x%x\n",
+	if (cpu_family == CPU_HW_PSTATE)
+		dprintk("targ: curr fid 0x%x, did 0x%x\n",
+			data->currfid, data->currvid);
+	else {
+		dprintk("targ: curr fid 0x%x, vid 0x%x\n",
 		data->currfid, data->currvid);
 
-	if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
-		printk(KERN_INFO PFX
-			"error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
-			checkfid, data->currfid, checkvid, data->currvid);
+		if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
+			printk(KERN_INFO PFX
+				"error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
+				checkfid, data->currfid, checkvid, data->currvid);
+		}
 	}
 
 	if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
@@ -954,7 +1103,11 @@
 
 	powernow_k8_acpi_pst_values(data, newstate);
 
-	if (transition_frequency(data, newstate)) {
+	if (cpu_family == CPU_HW_PSTATE)
+		ret = transition_frequency_pstate(data, newstate);
+	else
+		ret = transition_frequency_fidvid(data, newstate);
+	if (ret) {
 		printk(KERN_ERR PFX "transition frequency failed\n");
 		ret = 1;
 		mutex_unlock(&fidvid_mutex);
@@ -962,7 +1115,10 @@
 	}
 	mutex_unlock(&fidvid_mutex);
 
-	pol->cur = find_khz_freq_from_fid(data->currfid);
+	if (cpu_family == CPU_HW_PSTATE)
+		pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+	else
+		pol->cur = find_khz_freq_from_fid(data->currfid);
 	ret = 0;
 
 err_out:
@@ -1007,14 +1163,13 @@
 		 * Use the PSB BIOS structure. This is only availabe on
 		 * an UP version, and is deprecated by AMD.
 		 */
-
-		if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
+		if (num_online_cpus() != 1) {
 			printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
 			kfree(data);
 			return -ENODEV;
 		}
 		if (pol->cpu != 0) {
-			printk(KERN_ERR PFX "init not cpu 0\n");
+			printk(KERN_ERR PFX "No _PSS objects for CPU other than CPU0\n");
 			kfree(data);
 			return -ENODEV;
 		}
@@ -1042,20 +1197,28 @@
 	if (query_current_values_with_pending_wait(data))
 		goto err_out;
 
-	fidvid_msr_init();
+	if (cpu_family == CPU_OPTERON)
+		fidvid_msr_init();
 
 	/* run on any CPU again */
 	set_cpus_allowed(current, oldmask);
 
 	pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
-	pol->cpus = cpu_core_map[pol->cpu];
+	if (cpu_family == CPU_HW_PSTATE)
+		pol->cpus = cpumask_of_cpu(pol->cpu);
+	else
+		pol->cpus = cpu_core_map[pol->cpu];
+	data->available_cores = &(pol->cpus);
 
 	/* Take a crude guess here.
 	 * That guess was in microseconds, so multiply with 1000 */
 	pol->cpuinfo.transition_latency = (((data->rvo + 8) * data->vstable * VST_UNITS_20US)
 	    + (3 * (1 << data->irt) * 10)) * 1000;
 
-	pol->cur = find_khz_freq_from_fid(data->currfid);
+	if (cpu_family == CPU_HW_PSTATE)
+		pol->cur = find_khz_freq_from_fiddid(data->currfid, data->currdid);
+	else
+		pol->cur = find_khz_freq_from_fid(data->currfid);
 	dprintk("policy current frequency %d kHz\n", pol->cur);
 
 	/* min/max the cpu is capable of */
@@ -1069,8 +1232,12 @@
 
 	cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
 
-	printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
-	       data->currfid, data->currvid);
+	if (cpu_family == CPU_HW_PSTATE)
+		dprintk("cpu_init done, current fid 0x%x, did 0x%x\n",
+			data->currfid, data->currdid);
+	else
+		dprintk("cpu_init done, current fid 0x%x, vid 0x%x\n",
+			data->currfid, data->currvid);
 
 	powernow_data[pol->cpu] = data;
 
@@ -1156,8 +1323,9 @@
 	}
 
 	if (supported_cpus == num_online_cpus()) {
-		printk(KERN_INFO PFX "Found %d AMD Athlon 64 / Opteron "
-			"processors (" VERSION ")\n", supported_cpus);
+		printk(KERN_INFO PFX "Found %d %s "
+			"processors (" VERSION ")\n", supported_cpus,
+			boot_cpu_data.x86_model_id);
 		return cpufreq_register_driver(&cpufreq_amd64_driver);
 	}
 
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 79a7c5c..0fb2a30 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -1,5 +1,5 @@
 /*
- *  (c) 2003, 2004, 2005 Advanced Micro Devices, Inc.
+ *  (c) 2003-2006 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
@@ -21,8 +21,8 @@
 	u32 plllock; /* pll lock time, units 1 us */
         u32 exttype; /* extended interface = 1 */
 
-	/* keep track of the current fid / vid */
-	u32 currvid, currfid;
+	/* keep track of the current fid / vid or did */
+	u32 currvid, currfid, currdid;
 
 	/* the powernow_table includes all frequency and vid/fid pairings:
 	 * fid are the lower 8 bits of the index, vid are the upper 8 bits.
@@ -34,6 +34,10 @@
 	 * used to determine valid frequency/vid/fid states */
 	struct acpi_processor_performance acpi_data;
 #endif
+	/* we need to keep track of associated cores, but let cpufreq
+	 * handle hotplug events - so just point at cpufreq pol->cpus
+	 * structure */
+	cpumask_t *available_cores;
 };
 
 
@@ -43,6 +47,7 @@
 #define CPUID_XFAM_K8			0
 #define CPUID_XMOD			0x000f0000	/* extended model */
 #define CPUID_XMOD_REV_G		0x00060000
+#define CPUID_XFAM_10H 			0x00100000	/* family 0x10 */
 #define CPUID_USE_XFAM_XMOD		0x00000f00
 #define CPUID_GET_MAX_CAPABILITIES	0x80000000
 #define CPUID_FREQ_VOLT_CAPABILITIES	0x80000007
@@ -79,6 +84,32 @@
 #define MSR_S_HI_CURRENT_VID      0x0000003f
 #define MSR_C_HI_STP_GNT_BENIGN	  0x00000001
 
+
+/* Hardware Pstate _PSS and MSR definitions */
+#define USE_HW_PSTATE		0x00000080
+#define HW_PSTATE_FID_MASK 	0x0000003f
+#define HW_PSTATE_DID_MASK 	0x000001c0
+#define HW_PSTATE_DID_SHIFT 	6
+#define HW_PSTATE_MASK 		0x00000007
+#define HW_PSTATE_VALID_MASK 	0x80000000
+#define HW_FID_INDEX_SHIFT	8
+#define HW_FID_INDEX_MASK	0x0000ff00
+#define HW_DID_INDEX_SHIFT	16
+#define HW_DID_INDEX_MASK	0x00ff0000
+#define HW_WATTS_MASK		0xff
+#define HW_PWR_DVR_MASK		0x300
+#define HW_PWR_DVR_SHIFT	8
+#define HW_PWR_MAX_MULT		3
+#define MAX_HW_PSTATE		8	/* hw pstate supports up to 8 */
+#define MSR_PSTATE_DEF_BASE 	0xc0010064 /* base of Pstate MSRs */
+#define MSR_PSTATE_STATUS 	0xc0010063 /* Pstate Status MSR */
+#define MSR_PSTATE_CTRL 	0xc0010062 /* Pstate control MSR */
+
+/* define the two driver architectures */
+#define CPU_OPTERON 0
+#define CPU_HW_PSTATE 1
+
+
 /*
  * There are restrictions frequencies have to follow:
  * - only 1 entry in the low fid table ( <=1.4GHz )
@@ -138,7 +169,9 @@
 #define MVS_MASK        3
 #define VST_MASK     0x7f
 #define VID_MASK     0x1f
-#define FID_MASK     0x3f
+#define FID_MASK     0x1f
+#define EXT_VID_MASK 0x3f
+#define EXT_FID_MASK 0x3f
 
 
 /*
@@ -182,6 +215,9 @@
 
 static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
 
+static int fill_powernow_table_pstate(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
+static int fill_powernow_table_fidvid(struct powernow_k8_data *data, struct cpufreq_frequency_table *powernow_table);
+
 #ifdef CONFIG_SMP
 static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
 {
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index b0ff907..f7e4356 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -2,19 +2,15 @@
  * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium
  * M (part of the Centrino chipset).
  *
+ * Since the original Pentium M, most new Intel CPUs support Enhanced
+ * SpeedStep.
+ *
  * Despite the "SpeedStep" in the name, this is almost entirely unlike
  * traditional SpeedStep.
  *
  * Modelled on speedstep.c
  *
  * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org>
- *
- * WARNING WARNING WARNING
- *
- * This driver manipulates the PERF_CTL MSR, which is only somewhat
- * documented.  While it seems to work on my laptop, it has not been
- * tested anywhere else, and it may not work for you, do strange
- * things or simply crash.
  */
 
 #include <linux/kernel.h>
@@ -36,7 +32,7 @@
 #include <asm/cpufeature.h>
 
 #define PFX		"speedstep-centrino: "
-#define MAINTAINER	"Jeremy Fitzhardinge <jeremy@goop.org>"
+#define MAINTAINER	"cpufreq@lists.linux.org.uk"
 
 #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)
 
@@ -250,7 +246,7 @@
 
 	if (model->cpu_id == NULL) {
 		/* No match at all */
-		dprintk(KERN_INFO PFX "no support for CPU model \"%s\": "
+		dprintk("no support for CPU model \"%s\": "
 		       "send /proc/cpuinfo to " MAINTAINER "\n",
 		       cpu->x86_model_id);
 		return -ENOENT;
@@ -258,10 +254,10 @@
 
 	if (model->op_points == NULL) {
 		/* Matched a non-match */
-		dprintk(KERN_INFO PFX "no table support for CPU model \"%s\"\n",
+		dprintk("no table support for CPU model \"%s\"\n",
 		       cpu->x86_model_id);
 #ifndef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
-		dprintk(KERN_INFO PFX "try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
+		dprintk("try compiling with CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI enabled\n");
 #endif
 		return -ENOENT;
 	}
@@ -351,7 +347,36 @@
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
 
-static struct acpi_processor_performance p;
+static struct acpi_processor_performance *acpi_perf_data[NR_CPUS];
+
+/*
+ * centrino_cpu_early_init_acpi - Do the preregistering with ACPI P-States
+ * library
+ *
+ * Before doing the actual init, we need to do _PSD related setup whenever
+ * supported by the BIOS. These are handled by this early_init routine.
+ */
+static int centrino_cpu_early_init_acpi(void)
+{
+	unsigned int	i, j;
+	struct acpi_processor_performance	*data;
+
+	for_each_possible_cpu(i) {
+		data = kzalloc(sizeof(struct acpi_processor_performance), 
+				GFP_KERNEL);
+		if (!data) {
+			for_each_possible_cpu(j) {
+				kfree(acpi_perf_data[j]);
+				acpi_perf_data[j] = NULL;
+			}
+			return (-ENOMEM);
+		}
+		acpi_perf_data[i] = data;
+	}
+
+	acpi_processor_preregister_performance(acpi_perf_data);
+	return 0;
+}
 
 /*
  * centrino_cpu_init_acpi - register with ACPI P-States library
@@ -365,46 +390,51 @@
 	unsigned long			cur_freq;
 	int				result = 0, i;
 	unsigned int			cpu = policy->cpu;
+	struct acpi_processor_performance	*p;
+
+	p = acpi_perf_data[cpu];
 
 	/* register with ACPI core */
-	if (acpi_processor_register_performance(&p, cpu)) {
-		dprintk(KERN_INFO PFX "obtaining ACPI data failed\n");
+	if (acpi_processor_register_performance(p, cpu)) {
+		dprintk(PFX "obtaining ACPI data failed\n");
 		return -EIO;
 	}
+	policy->cpus = p->shared_cpu_map;
+	policy->shared_type = p->shared_type;
 
 	/* verify the acpi_data */
-	if (p.state_count <= 1) {
+	if (p->state_count <= 1) {
 		dprintk("No P-States\n");
 		result = -ENODEV;
 		goto err_unreg;
 	}
 
-	if ((p.control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
-	    (p.status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
+	if ((p->control_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) ||
+	    (p->status_register.space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) {
 		dprintk("Invalid control/status registers (%x - %x)\n",
-			p.control_register.space_id, p.status_register.space_id);
+			p->control_register.space_id, p->status_register.space_id);
 		result = -EIO;
 		goto err_unreg;
 	}
 
-	for (i=0; i<p.state_count; i++) {
-		if (p.states[i].control != p.states[i].status) {
+	for (i=0; i<p->state_count; i++) {
+		if (p->states[i].control != p->states[i].status) {
 			dprintk("Different control (%llu) and status values (%llu)\n",
-				p.states[i].control, p.states[i].status);
+				p->states[i].control, p->states[i].status);
 			result = -EINVAL;
 			goto err_unreg;
 		}
 
-		if (!p.states[i].core_frequency) {
+		if (!p->states[i].core_frequency) {
 			dprintk("Zero core frequency for state %u\n", i);
 			result = -EINVAL;
 			goto err_unreg;
 		}
 
-		if (p.states[i].core_frequency > p.states[0].core_frequency) {
+		if (p->states[i].core_frequency > p->states[0].core_frequency) {
 			dprintk("P%u has larger frequency (%llu) than P0 (%llu), skipping\n", i,
-				p.states[i].core_frequency, p.states[0].core_frequency);
-			p.states[i].core_frequency = 0;
+				p->states[i].core_frequency, p->states[0].core_frequency);
+			p->states[i].core_frequency = 0;
 			continue;
 		}
 	}
@@ -416,26 +446,26 @@
 	}
 
 	centrino_model[cpu]->model_name=NULL;
-	centrino_model[cpu]->max_freq = p.states[0].core_frequency * 1000;
+	centrino_model[cpu]->max_freq = p->states[0].core_frequency * 1000;
 	centrino_model[cpu]->op_points =  kmalloc(sizeof(struct cpufreq_frequency_table) *
-					     (p.state_count + 1), GFP_KERNEL);
+					     (p->state_count + 1), GFP_KERNEL);
         if (!centrino_model[cpu]->op_points) {
                 result = -ENOMEM;
                 goto err_kfree;
         }
 
-        for (i=0; i<p.state_count; i++) {
-		centrino_model[cpu]->op_points[i].index = p.states[i].control;
-		centrino_model[cpu]->op_points[i].frequency = p.states[i].core_frequency * 1000;
+        for (i=0; i<p->state_count; i++) {
+		centrino_model[cpu]->op_points[i].index = p->states[i].control;
+		centrino_model[cpu]->op_points[i].frequency = p->states[i].core_frequency * 1000;
 		dprintk("adding state %i with frequency %u and control value %04x\n", 
 			i, centrino_model[cpu]->op_points[i].frequency, centrino_model[cpu]->op_points[i].index);
 	}
-	centrino_model[cpu]->op_points[p.state_count].frequency = CPUFREQ_TABLE_END;
+	centrino_model[cpu]->op_points[p->state_count].frequency = CPUFREQ_TABLE_END;
 
 	cur_freq = get_cur_freq(cpu);
 
-	for (i=0; i<p.state_count; i++) {
-		if (!p.states[i].core_frequency) {
+	for (i=0; i<p->state_count; i++) {
+		if (!p->states[i].core_frequency) {
 			dprintk("skipping state %u\n", i);
 			centrino_model[cpu]->op_points[i].frequency = CPUFREQ_ENTRY_INVALID;
 			continue;
@@ -451,7 +481,7 @@
 		}
 
 		if (cur_freq == centrino_model[cpu]->op_points[i].frequency)
-			p.state = i;
+			p->state = i;
 	}
 
 	/* notify BIOS that we exist */
@@ -464,12 +494,13 @@
  err_kfree:
 	kfree(centrino_model[cpu]);
  err_unreg:
-	acpi_processor_unregister_performance(&p, cpu);
-	dprintk(KERN_INFO PFX "invalid ACPI data\n");
+	acpi_processor_unregister_performance(p, cpu);
+	dprintk(PFX "invalid ACPI data\n");
 	return (result);
 }
 #else
 static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
+static inline int centrino_cpu_early_init_acpi(void) { return 0; }
 #endif
 
 static int centrino_cpu_init(struct cpufreq_policy *policy)
@@ -499,7 +530,7 @@
 			centrino_cpu[policy->cpu] = &cpu_ids[i];
 
 		if (!centrino_cpu[policy->cpu]) {
-			dprintk(KERN_INFO PFX "found unsupported CPU with "
+			dprintk("found unsupported CPU with "
 			"Enhanced SpeedStep: send /proc/cpuinfo to "
 			MAINTAINER "\n");
 			return -ENODEV;
@@ -555,10 +586,15 @@
 
 #ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
 	if (!centrino_model[cpu]->model_name) {
-		dprintk("unregistering and freeing ACPI data\n");
-		acpi_processor_unregister_performance(&p, cpu);
-		kfree(centrino_model[cpu]->op_points);
-		kfree(centrino_model[cpu]);
+		static struct acpi_processor_performance *p;
+
+		if (acpi_perf_data[cpu]) {
+			p = acpi_perf_data[cpu];
+			dprintk("unregistering and freeing ACPI data\n");
+			acpi_processor_unregister_performance(p, cpu);
+			kfree(centrino_model[cpu]->op_points);
+			kfree(centrino_model[cpu]);
+		}
 	}
 #endif
 
@@ -592,63 +628,128 @@
 			    unsigned int relation)
 {
 	unsigned int    newstate = 0;
-	unsigned int	msr, oldmsr, h, cpu = policy->cpu;
+	unsigned int	msr, oldmsr = 0, h = 0, cpu = policy->cpu;
 	struct cpufreq_freqs	freqs;
+	cpumask_t		online_policy_cpus;
 	cpumask_t		saved_mask;
-	int			retval;
+	cpumask_t		set_mask;
+	cpumask_t		covered_cpus;
+	int			retval = 0;
+	unsigned int		j, k, first_cpu, tmp;
 
-	if (centrino_model[cpu] == NULL)
+	if (unlikely(centrino_model[cpu] == NULL))
 		return -ENODEV;
 
-	/*
-	 * Support for SMP systems.
-	 * Make sure we are running on the CPU that wants to change frequency
-	 */
+	if (unlikely(cpufreq_frequency_table_target(policy,
+			centrino_model[cpu]->op_points,
+			target_freq,
+			relation,
+			&newstate))) {
+		return -EINVAL;
+	}
+
+#ifdef CONFIG_HOTPLUG_CPU
+	/* cpufreq holds the hotplug lock, so we are safe from here on */
+	cpus_and(online_policy_cpus, cpu_online_map, policy->cpus);
+#else
+	online_policy_cpus = policy->cpus;
+#endif
+
 	saved_mask = current->cpus_allowed;
-	set_cpus_allowed(current, policy->cpus);
-	if (!cpu_isset(smp_processor_id(), policy->cpus)) {
-		dprintk("couldn't limit to CPUs in this domain\n");
-		return(-EAGAIN);
+	first_cpu = 1;
+	cpus_clear(covered_cpus);
+	for_each_cpu_mask(j, online_policy_cpus) {
+		/*
+		 * Support for SMP systems.
+		 * Make sure we are running on CPU that wants to change freq
+		 */
+		cpus_clear(set_mask);
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			cpus_or(set_mask, set_mask, online_policy_cpus);
+		else
+			cpu_set(j, set_mask);
+
+		set_cpus_allowed(current, set_mask);
+		if (unlikely(!cpu_isset(smp_processor_id(), set_mask))) {
+			dprintk("couldn't limit to CPUs in this domain\n");
+			retval = -EAGAIN;
+			if (first_cpu) {
+				/* We haven't started the transition yet. */
+				goto migrate_end;
+			}
+			break;
+		}
+
+		msr = centrino_model[cpu]->op_points[newstate].index;
+
+		if (first_cpu) {
+			rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+			if (msr == (oldmsr & 0xffff)) {
+				dprintk("no change needed - msr was and needs "
+					"to be %x\n", oldmsr);
+				retval = 0;
+				goto migrate_end;
+			}
+
+			freqs.old = extract_clock(oldmsr, cpu, 0);
+			freqs.new = extract_clock(msr, cpu, 0);
+
+			dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
+				target_freq, freqs.old, freqs.new, msr);
+
+			for_each_cpu_mask(k, online_policy_cpus) {
+				freqs.cpu = k;
+				cpufreq_notify_transition(&freqs,
+					CPUFREQ_PRECHANGE);
+			}
+
+			first_cpu = 0;
+			/* all but 16 LSB are reserved, treat them with care */
+			oldmsr &= ~0xffff;
+			msr &= 0xffff;
+			oldmsr |= msr;
+		}
+
+		wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+		if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
+			break;
+
+		cpu_set(j, covered_cpus);
 	}
 
-	if (cpufreq_frequency_table_target(policy, centrino_model[cpu]->op_points, target_freq,
-					   relation, &newstate)) {
-		retval = -EINVAL;
-		goto migrate_end;
+	for_each_cpu_mask(k, online_policy_cpus) {
+		freqs.cpu = k;
+		cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	}
 
-	msr = centrino_model[cpu]->op_points[newstate].index;
-	rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+	if (unlikely(retval)) {
+		/*
+		 * We have failed halfway through the frequency change.
+		 * We have sent callbacks to policy->cpus and
+		 * MSRs have already been written on coverd_cpus.
+		 * Best effort undo..
+		 */
 
-	if (msr == (oldmsr & 0xffff)) {
-		retval = 0;
-		dprintk("no change needed - msr was and needs to be %x\n", oldmsr);
-		goto migrate_end;
+		if (!cpus_empty(covered_cpus)) {
+			for_each_cpu_mask(j, covered_cpus) {
+				set_cpus_allowed(current, cpumask_of_cpu(j));
+				wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+			}
+		}
+
+		tmp = freqs.new;
+		freqs.new = freqs.old;
+		freqs.old = tmp;
+		for_each_cpu_mask(j, online_policy_cpus) {
+			freqs.cpu = j;
+			cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+			cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+		}
 	}
 
-	freqs.cpu = cpu;
-	freqs.old = extract_clock(oldmsr, cpu, 0);
-	freqs.new = extract_clock(msr, cpu, 0);
-
-	dprintk("target=%dkHz old=%d new=%d msr=%04x\n",
-		target_freq, freqs.old, freqs.new, msr);
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	/* all but 16 LSB are "reserved", so treat them with
-	   care */
-	oldmsr &= ~0xffff;
-	msr &= 0xffff;
-	oldmsr |= msr;
-
-	wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	retval = 0;
 migrate_end:
 	set_cpus_allowed(current, saved_mask);
-	return (retval);
+	return 0;
 }
 
 static struct freq_attr* centrino_attr[] = {
@@ -690,12 +791,25 @@
 	if (!cpu_has(cpu, X86_FEATURE_EST))
 		return -ENODEV;
 
+	centrino_cpu_early_init_acpi();
+
 	return cpufreq_register_driver(&centrino_driver);
 }
 
 static void __exit centrino_exit(void)
 {
+#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
+	unsigned int j;
+#endif
+	
 	cpufreq_unregister_driver(&centrino_driver);
+
+#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI
+	for_each_possible_cpu(j) {
+		kfree(acpi_perf_data[j]);
+		acpi_perf_data[j] = NULL;
+	}
+#endif
 }
 
 MODULE_AUTHOR ("Jeremy Fitzhardinge <jeremy@goop.org>");
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c
index 00f2e05..f03b7f94 100644
--- a/arch/i386/kernel/cpu/cyrix.c
+++ b/arch/i386/kernel/cpu/cyrix.c
@@ -184,7 +184,7 @@
 
 
 #ifdef CONFIG_PCI
-static struct pci_device_id cyrix_55x0[] = {
+static struct pci_device_id __initdata cyrix_55x0[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5510) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520) },
 	{ },
@@ -272,14 +272,15 @@
 
 		printk(KERN_INFO "Working around Cyrix MediaGX virtual DMA bugs.\n");
 		isa_dma_bridge_buggy = 2;
-#endif		
-		c->x86_cache_size=16;	/* Yep 16K integrated cache thats it */
- 
+
+
 		/*
 		 *  The 5510/5520 companion chips have a funky PIT.
 		 */  
 		if (pci_dev_present(cyrix_55x0))
 			pit_latch_buggy = 1;
+#endif
+		c->x86_cache_size=16;	/* Yep 16K integrated cache thats it */
 
 		/* GXm supports extended cpuid levels 'ala' AMD */
 		if (c->cpuid_level == 2) {
@@ -353,7 +354,7 @@
 	 * This function only handles the GX processor, and kicks every
 	 * thing else to the Cyrix init function above - that should
 	 * cover any processors that might have been branded differently
-	 * after NSC aquired Cyrix.
+	 * after NSC acquired Cyrix.
 	 *
 	 * If this breaks your GX1 horribly, please e-mail
 	 * info-linux@ldcmail.amd.com to tell us.
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 5386b29..10afc64 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -122,6 +122,12 @@
 
 	select_idle_routine(c);
 	l2 = init_intel_cacheinfo(c);
+	if (c->cpuid_level > 9 ) {
+		unsigned eax = cpuid_eax(10);
+		/* Check for version and the number of counters */
+		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+			set_bit(X86_FEATURE_ARCH_PERFMON, c->x86_capability);
+	}
 
 	/* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it until model 3 mask 3 */
 	if ((c->x86<<8 | c->x86_model<<4 | c->x86_mask) < 0x633)
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index c8547a6..e9f0b92 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -4,6 +4,7 @@
  *      Changes:
  *      Venkatesh Pallipadi	: Adding cache identification through cpuid(4)
  *		Ashok Raj <ashok.raj@intel.com>: Work with CPU hotplug infrastructure.
+ *	Andi Kleen		: CPUID4 emulation on AMD.
  */
 
 #include <linux/init.h>
@@ -130,25 +131,111 @@
 	cpumask_t shared_cpu_map;
 };
 
-static unsigned short			num_cache_leaves;
+unsigned short			num_cache_leaves;
+
+/* AMD doesn't have CPUID4. Emulate it here to report the same
+   information to the user.  This makes some assumptions about the machine:
+   No L3, L2 not shared, no SMT etc. that is currently true on AMD CPUs.
+
+   In theory the TLBs could be reported as fake type (they are in "dummy").
+   Maybe later */
+union l1_cache {
+	struct {
+		unsigned line_size : 8;
+		unsigned lines_per_tag : 8;
+		unsigned assoc : 8;
+		unsigned size_in_kb : 8;
+	};
+	unsigned val;
+};
+
+union l2_cache {
+	struct {
+		unsigned line_size : 8;
+		unsigned lines_per_tag : 4;
+		unsigned assoc : 4;
+		unsigned size_in_kb : 16;
+	};
+	unsigned val;
+};
+
+static const unsigned short assocs[] = {
+	[1] = 1, [2] = 2, [4] = 4, [6] = 8,
+	[8] = 16,
+	[0xf] = 0xffff // ??
+	};
+static const unsigned char levels[] = { 1, 1, 2 };
+static const unsigned char types[] = { 1, 2, 3 };
+
+static void __cpuinit amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,
+		       union _cpuid4_leaf_ebx *ebx,
+		       union _cpuid4_leaf_ecx *ecx)
+{
+	unsigned dummy;
+	unsigned line_size, lines_per_tag, assoc, size_in_kb;
+	union l1_cache l1i, l1d;
+	union l2_cache l2;
+
+	eax->full = 0;
+	ebx->full = 0;
+	ecx->full = 0;
+
+	cpuid(0x80000005, &dummy, &dummy, &l1d.val, &l1i.val);
+	cpuid(0x80000006, &dummy, &dummy, &l2.val, &dummy);
+
+	if (leaf > 2 || !l1d.val || !l1i.val || !l2.val)
+		return;
+
+	eax->split.is_self_initializing = 1;
+	eax->split.type = types[leaf];
+	eax->split.level = levels[leaf];
+	eax->split.num_threads_sharing = 0;
+	eax->split.num_cores_on_die = current_cpu_data.x86_max_cores - 1;
+
+	if (leaf <= 1) {
+		union l1_cache *l1 = leaf == 0 ? &l1d : &l1i;
+		assoc = l1->assoc;
+		line_size = l1->line_size;
+		lines_per_tag = l1->lines_per_tag;
+		size_in_kb = l1->size_in_kb;
+	} else {
+		assoc = l2.assoc;
+		line_size = l2.line_size;
+		lines_per_tag = l2.lines_per_tag;
+		/* cpu_data has errata corrections for K7 applied */
+		size_in_kb = current_cpu_data.x86_cache_size;
+	}
+
+	if (assoc == 0xf)
+		eax->split.is_fully_associative = 1;
+	ebx->split.coherency_line_size = line_size - 1;
+	ebx->split.ways_of_associativity = assocs[assoc] - 1;
+	ebx->split.physical_line_partition = lines_per_tag - 1;
+	ecx->split.number_of_sets = (size_in_kb * 1024) / line_size /
+		(ebx->split.ways_of_associativity + 1) - 1;
+}
 
 static int __cpuinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
 {
-	unsigned int		eax, ebx, ecx, edx;
-	union _cpuid4_leaf_eax	cache_eax;
+	union _cpuid4_leaf_eax 	eax;
+	union _cpuid4_leaf_ebx 	ebx;
+	union _cpuid4_leaf_ecx 	ecx;
+	unsigned		edx;
 
-	cpuid_count(4, index, &eax, &ebx, &ecx, &edx);
-	cache_eax.full = eax;
-	if (cache_eax.split.type == CACHE_TYPE_NULL)
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+		amd_cpuid4(index, &eax, &ebx, &ecx);
+	else
+		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full,  &edx);
+	if (eax.split.type == CACHE_TYPE_NULL)
 		return -EIO; /* better error ? */
 
-	this_leaf->eax.full = eax;
-	this_leaf->ebx.full = ebx;
-	this_leaf->ecx.full = ecx;
-	this_leaf->size = (this_leaf->ecx.split.number_of_sets + 1) *
-		(this_leaf->ebx.split.coherency_line_size + 1) *
-		(this_leaf->ebx.split.physical_line_partition + 1) *
-		(this_leaf->ebx.split.ways_of_associativity + 1);
+	this_leaf->eax = eax;
+	this_leaf->ebx = ebx;
+	this_leaf->ecx = ecx;
+	this_leaf->size = (ecx.split.number_of_sets + 1) *
+		(ebx.split.coherency_line_size + 1) *
+		(ebx.split.physical_line_partition + 1) *
+		(ebx.split.ways_of_associativity + 1);
 	return 0;
 }
 
@@ -174,7 +261,7 @@
 	unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
 	unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
 	unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_HT
 	unsigned int cpu = (c == &boot_cpu_data) ? 0 : (c - cpu_data);
 #endif
 
@@ -296,14 +383,14 @@
 
 	if (new_l2) {
 		l2 = new_l2;
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_HT
 		cpu_llc_id[cpu] = l2_id;
 #endif
 	}
 
 	if (new_l3) {
 		l3 = new_l3;
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_HT
 		cpu_llc_id[cpu] = l3_id;
 #endif
 	}
@@ -642,7 +729,7 @@
 	return;
 }
 
-static int cacheinfo_cpu_callback(struct notifier_block *nfb,
+static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb,
 					unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
@@ -660,7 +747,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block cacheinfo_cpu_notifier =
+static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier =
 {
     .notifier_call = cacheinfo_cpu_callback,
 };
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index f94cdb7..f54a152 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -18,7 +18,7 @@
 	 * applications want to get the raw CPUID data, they should access
 	 * /dev/cpu/<cpu_nr>/cpuid instead.
 	 */
-	static char *x86_cap_flags[] = {
+	static const char * const x86_cap_flags[] = {
 		/* Intel-defined */
 	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
 	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
@@ -52,7 +52,7 @@
 
 		/* VIA/Cyrix/Centaur-defined */
 		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
@@ -62,7 +62,7 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 	};
-	static char *x86_power_flags[] = {
+	static const char * const x86_power_flags[] = {
 		"ts",	/* temperature sensor */
 		"fid",  /* frequency id control */
 		"vid",  /* voltage id control */
@@ -109,9 +109,9 @@
 		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
 #ifdef CONFIG_X86_HT
 	if (c->x86_max_cores * smp_num_siblings > 1) {
-		seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
+		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
 		seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n]));
-		seq_printf(m, "core id\t\t: %d\n", cpu_core_id[n]);
+		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
 		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
 	}
 #endif
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 1d9a4ab..f6dfa9f 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -183,7 +183,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block cpuid_class_cpu_notifier =
+static struct notifier_block __cpuinitdata cpuid_class_cpu_notifier =
 {
 	.notifier_call = cpuid_class_cpu_callback,
 };
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index 2b0cfce..48f0f62 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -114,19 +114,15 @@
 	atomic_dec(&waiting_for_crash_ipi);
 	/* Assume hlt works */
 	halt();
-	for(;;);
+	for (;;)
+		cpu_relax();
 
 	return 1;
 }
 
-/*
- * By using the NMI code instead of a vector we just sneak thru the
- * word generator coming out with just what we want.  AND it does
- * not matter if clustered_apic_mode is set or not.
- */
 static void smp_send_nmi_allbutself(void)
 {
-	send_IPI_allbutself(APIC_DM_NMI);
+	send_IPI_allbutself(NMI_VECTOR);
 }
 
 static void nmi_shootdown_cpus(void)
@@ -162,7 +158,7 @@
 void machine_crash_shutdown(struct pt_regs *regs)
 {
 	/* This function is only called after the system
-	 * has paniced or is otherwise in a critical state.
+	 * has panicked or is otherwise in a critical state.
 	 * The minimum amount of code to allow a kexec'd kernel
 	 * to run successfully needs to happen here.
 	 *
diff --git a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c
index 5edb1d3..b4d14c2 100644
--- a/arch/i386/kernel/doublefault.c
+++ b/arch/i386/kernel/doublefault.c
@@ -44,7 +44,8 @@
 		}
 	}
 
-	for (;;) /* nothing */;
+	for (;;)
+		cpu_relax();
 }
 
 struct tss_struct doublefault_tss __cacheline_aligned = {
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index cfc683f..fbdb933 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -48,6 +48,7 @@
 #include <asm/smp.h>
 #include <asm/page.h>
 #include <asm/desc.h>
+#include <asm/dwarf2.h>
 #include "irq_vectors.h"
 
 #define nr_syscalls ((syscall_table_size)/4)
@@ -82,34 +83,76 @@
 #define resume_kernel		restore_nocheck
 #endif
 
+#ifdef CONFIG_VM86
+#define resume_userspace_sig	check_userspace
+#else
+#define resume_userspace_sig	resume_userspace
+#endif
+
 #define SAVE_ALL \
 	cld; \
 	pushl %es; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	/*CFI_REL_OFFSET es, 0;*/\
 	pushl %ds; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	/*CFI_REL_OFFSET ds, 0;*/\
 	pushl %eax; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	CFI_REL_OFFSET eax, 0;\
 	pushl %ebp; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	CFI_REL_OFFSET ebp, 0;\
 	pushl %edi; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	CFI_REL_OFFSET edi, 0;\
 	pushl %esi; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	CFI_REL_OFFSET esi, 0;\
 	pushl %edx; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	CFI_REL_OFFSET edx, 0;\
 	pushl %ecx; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	CFI_REL_OFFSET ecx, 0;\
 	pushl %ebx; \
+	CFI_ADJUST_CFA_OFFSET 4;\
+	CFI_REL_OFFSET ebx, 0;\
 	movl $(__USER_DS), %edx; \
 	movl %edx, %ds; \
 	movl %edx, %es;
 
 #define RESTORE_INT_REGS \
 	popl %ebx;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	CFI_RESTORE ebx;\
 	popl %ecx;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	CFI_RESTORE ecx;\
 	popl %edx;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	CFI_RESTORE edx;\
 	popl %esi;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	CFI_RESTORE esi;\
 	popl %edi;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	CFI_RESTORE edi;\
 	popl %ebp;	\
-	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4;\
+	CFI_RESTORE ebp;\
+	popl %eax;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	CFI_RESTORE eax
 
 #define RESTORE_REGS	\
 	RESTORE_INT_REGS; \
 1:	popl %ds;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	/*CFI_RESTORE ds;*/\
 2:	popl %es;	\
+	CFI_ADJUST_CFA_OFFSET -4;\
+	/*CFI_RESTORE es;*/\
 .section .fixup,"ax";	\
 3:	movl $0,(%esp);	\
 	jmp 1b;		\
@@ -122,13 +165,43 @@
 	.long 2b,4b;	\
 .previous
 
+#define RING0_INT_FRAME \
+	CFI_STARTPROC simple;\
+	CFI_DEF_CFA esp, 3*4;\
+	/*CFI_OFFSET cs, -2*4;*/\
+	CFI_OFFSET eip, -3*4
+
+#define RING0_EC_FRAME \
+	CFI_STARTPROC simple;\
+	CFI_DEF_CFA esp, 4*4;\
+	/*CFI_OFFSET cs, -2*4;*/\
+	CFI_OFFSET eip, -3*4
+
+#define RING0_PTREGS_FRAME \
+	CFI_STARTPROC simple;\
+	CFI_DEF_CFA esp, OLDESP-EBX;\
+	/*CFI_OFFSET cs, CS-OLDESP;*/\
+	CFI_OFFSET eip, EIP-OLDESP;\
+	/*CFI_OFFSET es, ES-OLDESP;*/\
+	/*CFI_OFFSET ds, DS-OLDESP;*/\
+	CFI_OFFSET eax, EAX-OLDESP;\
+	CFI_OFFSET ebp, EBP-OLDESP;\
+	CFI_OFFSET edi, EDI-OLDESP;\
+	CFI_OFFSET esi, ESI-OLDESP;\
+	CFI_OFFSET edx, EDX-OLDESP;\
+	CFI_OFFSET ecx, ECX-OLDESP;\
+	CFI_OFFSET ebx, EBX-OLDESP
 
 ENTRY(ret_from_fork)
+	CFI_STARTPROC
 	pushl %eax
+	CFI_ADJUST_CFA_OFFSET -4
 	call schedule_tail
 	GET_THREAD_INFO(%ebp)
 	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4
 	jmp syscall_exit
+	CFI_ENDPROC
 
 /*
  * Return to user mode is not as complex as all this looks,
@@ -139,10 +212,12 @@
 
 	# userspace resumption stub bypassing syscall exit tracing
 	ALIGN
+	RING0_PTREGS_FRAME
 ret_from_exception:
 	preempt_stop
 ret_from_intr:
 	GET_THREAD_INFO(%ebp)
+check_userspace:
 	movl EFLAGS(%esp), %eax		# mix EFLAGS and CS
 	movb CS(%esp), %al
 	testl $(VM_MASK | 3), %eax
@@ -171,20 +246,38 @@
 	call preempt_schedule_irq
 	jmp need_resched
 #endif
+	CFI_ENDPROC
 
 /* SYSENTER_RETURN points to after the "sysenter" instruction in
    the vsyscall page.  See vsyscall-sysentry.S, which defines the symbol.  */
 
 	# sysenter call handler stub
 ENTRY(sysenter_entry)
+	CFI_STARTPROC simple
+	CFI_DEF_CFA esp, 0
+	CFI_REGISTER esp, ebp
 	movl TSS_sysenter_esp0(%esp),%esp
 sysenter_past_esp:
 	sti
 	pushl $(__USER_DS)
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET ss, 0*/
 	pushl %ebp
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET esp, 0
 	pushfl
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $(__USER_CS)
-	pushl $SYSENTER_RETURN
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET cs, 0*/
+	/*
+	 * Push current_thread_info()->sysenter_return to the stack.
+	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
+	 */
+	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET eip, 0
 
 /*
  * Load the potential sixth argument from user stack.
@@ -199,6 +292,7 @@
 .previous
 
 	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 
@@ -219,11 +313,14 @@
 	xorl %ebp,%ebp
 	sti
 	sysexit
+	CFI_ENDPROC
 
 
 	# system call handler stub
 ENTRY(system_call)
+	RING0_INT_FRAME			# can't unwind into user space anyway
 	pushl %eax			# save orig_eax
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 	testl $TF_MASK,EFLAGS(%esp)
@@ -256,10 +353,12 @@
 	movb CS(%esp), %al
 	andl $(VM_MASK | (4 << 8) | 3), %eax
 	cmpl $((4 << 8) | 3), %eax
+	CFI_REMEMBER_STATE
 	je ldt_ss			# returning to user-space with LDT SS
 restore_nocheck:
 	RESTORE_REGS
 	addl $4, %esp
+	CFI_ADJUST_CFA_OFFSET -4
 1:	iret
 .section .fixup,"ax"
 iret_exc:
@@ -273,6 +372,7 @@
 	.long 1b,iret_exc
 .previous
 
+	CFI_RESTORE_STATE
 ldt_ss:
 	larl OLDSS(%esp), %eax
 	jnz restore_nocheck
@@ -285,11 +385,13 @@
 	 * CPUs, which we can try to work around to make
 	 * dosemu and wine happy. */
 	subl $8, %esp		# reserve space for switch16 pointer
+	CFI_ADJUST_CFA_OFFSET 8
 	cli
 	movl %esp, %eax
 	/* Set up the 16bit stack frame with switch32 pointer on top,
 	 * and a switch16 pointer on top of the current frame. */
 	call setup_x86_bogus_stack
+	CFI_ADJUST_CFA_OFFSET -8	# frame has moved
 	RESTORE_REGS
 	lss 20+4(%esp), %esp	# switch to 16bit stack
 1:	iret
@@ -297,9 +399,11 @@
 	.align 4
 	.long 1b,iret_exc
 .previous
+	CFI_ENDPROC
 
 	# perform work that needs to be done immediately before resumption
 	ALIGN
+	RING0_PTREGS_FRAME		# can't unwind into user space anyway
 work_pending:
 	testb $_TIF_NEED_RESCHED, %cl
 	jz work_notifysig
@@ -323,18 +427,20 @@
 					# vm86-space
 	xorl %edx, %edx
 	call do_notify_resume
-	jmp resume_userspace
+	jmp resume_userspace_sig
 
 	ALIGN
 work_notifysig_v86:
 #ifdef CONFIG_VM86
 	pushl %ecx			# save ti_flags for do_notify_resume
+	CFI_ADJUST_CFA_OFFSET 4
 	call save_v86_state		# %eax contains pt_regs pointer
 	popl %ecx
+	CFI_ADJUST_CFA_OFFSET -4
 	movl %eax, %esp
 	xorl %edx, %edx
 	call do_notify_resume
-	jmp resume_userspace
+	jmp resume_userspace_sig
 #endif
 
 	# perform syscall exit tracing
@@ -363,19 +469,21 @@
 	movl $1, %edx
 	call do_syscall_trace
 	jmp resume_userspace
+	CFI_ENDPROC
 
-	ALIGN
+	RING0_INT_FRAME			# can't unwind into user space anyway
 syscall_fault:
 	pushl %eax			# save orig_eax
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 	movl $-EFAULT,EAX(%esp)
 	jmp resume_userspace
 
-	ALIGN
 syscall_badsys:
 	movl $-ENOSYS,EAX(%esp)
 	jmp resume_userspace
+	CFI_ENDPROC
 
 #define FIXUP_ESPFIX_STACK \
 	movl %esp, %eax; \
@@ -387,16 +495,21 @@
 	movl %eax, %esp;
 #define UNWIND_ESPFIX_STACK \
 	pushl %eax; \
+	CFI_ADJUST_CFA_OFFSET 4; \
 	movl %ss, %eax; \
 	/* see if on 16bit stack */ \
 	cmpw $__ESPFIX_SS, %ax; \
-	jne 28f; \
-	movl $__KERNEL_DS, %edx; \
-	movl %edx, %ds; \
-	movl %edx, %es; \
+	je 28f; \
+27:	popl %eax; \
+	CFI_ADJUST_CFA_OFFSET -4; \
+.section .fixup,"ax"; \
+28:	movl $__KERNEL_DS, %eax; \
+	movl %eax, %ds; \
+	movl %eax, %es; \
 	/* switch to 32bit stack */ \
-	FIXUP_ESPFIX_STACK \
-28:	popl %eax;
+	FIXUP_ESPFIX_STACK; \
+	jmp 27b; \
+.previous
 
 /*
  * Build the entry stubs and pointer table with
@@ -408,9 +521,14 @@
 
 vector=0
 ENTRY(irq_entries_start)
+	RING0_INT_FRAME
 .rept NR_IRQS
 	ALIGN
-1:	pushl $vector-256
+ .if vector
+	CFI_ADJUST_CFA_OFFSET -4
+ .endif
+1:	pushl $~(vector)
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp common_interrupt
 .data
 	.long 1b
@@ -424,60 +542,99 @@
 	movl %esp,%eax
 	call do_IRQ
 	jmp ret_from_intr
+	CFI_ENDPROC
 
 #define BUILD_INTERRUPT(name, nr)	\
 ENTRY(name)				\
-	pushl $nr-256;			\
-	SAVE_ALL			\
+	RING0_INT_FRAME;		\
+	pushl $~(nr);			\
+	CFI_ADJUST_CFA_OFFSET 4;	\
+	SAVE_ALL;			\
 	movl %esp,%eax;			\
 	call smp_/**/name;		\
-	jmp ret_from_intr;
+	jmp ret_from_intr;	\
+	CFI_ENDPROC
 
 /* The include is where all of the SMP etc. interrupts come from */
 #include "entry_arch.h"
 
 ENTRY(divide_error)
+	RING0_INT_FRAME
 	pushl $0			# no error code
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_divide_error
+	CFI_ADJUST_CFA_OFFSET 4
 	ALIGN
 error_code:
 	pushl %ds
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET ds, 0*/
 	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET eax, 0
 	xorl %eax, %eax
 	pushl %ebp
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ebp, 0
 	pushl %edi
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET edi, 0
 	pushl %esi
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET esi, 0
 	pushl %edx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET edx, 0
 	decl %eax			# eax = -1
 	pushl %ecx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ecx, 0
 	pushl %ebx
+	CFI_ADJUST_CFA_OFFSET 4
+	CFI_REL_OFFSET ebx, 0
 	cld
 	pushl %es
+	CFI_ADJUST_CFA_OFFSET 4
+	/*CFI_REL_OFFSET es, 0*/
 	UNWIND_ESPFIX_STACK
 	popl %ecx
+	CFI_ADJUST_CFA_OFFSET -4
+	/*CFI_REGISTER es, ecx*/
 	movl ES(%esp), %edi		# get the function address
 	movl ORIG_EAX(%esp), %edx	# get the error code
 	movl %eax, ORIG_EAX(%esp)
 	movl %ecx, ES(%esp)
+	/*CFI_REL_OFFSET es, ES*/
 	movl $(__USER_DS), %ecx
 	movl %ecx, %ds
 	movl %ecx, %es
 	movl %esp,%eax			# pt_regs pointer
 	call *%edi
 	jmp ret_from_exception
+	CFI_ENDPROC
 
 ENTRY(coprocessor_error)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_coprocessor_error
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(simd_coprocessor_error)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_simd_coprocessor_error
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(device_not_available)
+	RING0_INT_FRAME
 	pushl $-1			# mark this as an int
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	movl %cr0, %eax
 	testl $0x4, %eax		# EM (math emulation bit)
@@ -487,9 +644,12 @@
 	jmp ret_from_exception
 device_not_available_emulate:
 	pushl $0			# temporary storage for ORIG_EIP
+	CFI_ADJUST_CFA_OFFSET 4
 	call math_emulate
 	addl $4, %esp
+	CFI_ADJUST_CFA_OFFSET -4
 	jmp ret_from_exception
+	CFI_ENDPROC
 
 /*
  * Debug traps and NMI can happen at the one SYSENTER instruction
@@ -514,16 +674,19 @@
 	pushl $sysenter_past_esp
 
 KPROBE_ENTRY(debug)
+	RING0_INT_FRAME
 	cmpl $sysenter_entry,(%esp)
 	jne debug_stack_correct
 	FIX_STACK(12, debug_stack_correct, debug_esp_fix_insn)
 debug_stack_correct:
 	pushl $-1			# mark this as an int
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	xorl %edx,%edx			# error code 0
 	movl %esp,%eax			# pt_regs pointer
 	call do_debug
 	jmp ret_from_exception
+	CFI_ENDPROC
 	.previous .text
 /*
  * NMI is doubly nasty. It can happen _while_ we're handling
@@ -534,14 +697,18 @@
  * fault happened on the sysenter path.
  */
 ENTRY(nmi)
+	RING0_INT_FRAME
 	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
 	movl %ss, %eax
 	cmpw $__ESPFIX_SS, %ax
 	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4
 	je nmi_16bit_stack
 	cmpl $sysenter_entry,(%esp)
 	je nmi_stack_fixup
 	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
 	movl %esp,%eax
 	/* Do not access memory above the end of our stack page,
 	 * it might not exist.
@@ -549,16 +716,19 @@
 	andl $(THREAD_SIZE-1),%eax
 	cmpl $(THREAD_SIZE-20),%eax
 	popl %eax
+	CFI_ADJUST_CFA_OFFSET -4
 	jae nmi_stack_correct
 	cmpl $sysenter_entry,12(%esp)
 	je nmi_debug_stack_check
 nmi_stack_correct:
 	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	xorl %edx,%edx		# zero error code
 	movl %esp,%eax		# pt_regs pointer
 	call do_nmi
 	jmp restore_all
+	CFI_ENDPROC
 
 nmi_stack_fixup:
 	FIX_STACK(12,nmi_stack_correct, 1)
@@ -574,94 +744,177 @@
 	jmp nmi_stack_correct
 
 nmi_16bit_stack:
+	RING0_INT_FRAME
 	/* create the pointer to lss back */
 	pushl %ss
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl %esp
+	CFI_ADJUST_CFA_OFFSET 4
 	movzwl %sp, %esp
 	addw $4, (%esp)
 	/* copy the iret frame of 12 bytes */
 	.rept 3
 	pushl 16(%esp)
+	CFI_ADJUST_CFA_OFFSET 4
 	.endr
 	pushl %eax
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	FIXUP_ESPFIX_STACK		# %eax == %esp
+	CFI_ADJUST_CFA_OFFSET -20	# the frame has now moved
 	xorl %edx,%edx			# zero error code
 	call do_nmi
 	RESTORE_REGS
 	lss 12+4(%esp), %esp		# back to 16bit stack
 1:	iret
+	CFI_ENDPROC
 .section __ex_table,"a"
 	.align 4
 	.long 1b,iret_exc
 .previous
 
 KPROBE_ENTRY(int3)
+	RING0_INT_FRAME
 	pushl $-1			# mark this as an int
+	CFI_ADJUST_CFA_OFFSET 4
 	SAVE_ALL
 	xorl %edx,%edx		# zero error code
 	movl %esp,%eax		# pt_regs pointer
 	call do_int3
 	jmp ret_from_exception
+	CFI_ENDPROC
 	.previous .text
 
 ENTRY(overflow)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_overflow
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(bounds)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_bounds
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(invalid_op)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_invalid_op
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(coprocessor_segment_overrun)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_coprocessor_segment_overrun
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(invalid_TSS)
+	RING0_EC_FRAME
 	pushl $do_invalid_TSS
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(segment_not_present)
+	RING0_EC_FRAME
 	pushl $do_segment_not_present
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 ENTRY(stack_segment)
+	RING0_EC_FRAME
 	pushl $do_stack_segment
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 KPROBE_ENTRY(general_protection)
+	RING0_EC_FRAME
 	pushl $do_general_protection
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 	.previous .text
 
 ENTRY(alignment_check)
+	RING0_EC_FRAME
 	pushl $do_alignment_check
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 
 KPROBE_ENTRY(page_fault)
+	RING0_EC_FRAME
 	pushl $do_page_fault
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 	.previous .text
 
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl machine_check_vector
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
 #endif
 
 ENTRY(spurious_interrupt_bug)
+	RING0_INT_FRAME
 	pushl $0
+	CFI_ADJUST_CFA_OFFSET 4
 	pushl $do_spurious_interrupt_bug
+	CFI_ADJUST_CFA_OFFSET 4
 	jmp error_code
+	CFI_ENDPROC
+
+#ifdef CONFIG_STACK_UNWIND
+ENTRY(arch_unwind_init_running)
+	CFI_STARTPROC
+	movl	4(%esp), %edx
+	movl	(%esp), %ecx
+	leal	4(%esp), %eax
+	movl	%ebx, EBX(%edx)
+	xorl	%ebx, %ebx
+	movl	%ebx, ECX(%edx)
+	movl	%ebx, EDX(%edx)
+	movl	%esi, ESI(%edx)
+	movl	%edi, EDI(%edx)
+	movl	%ebp, EBP(%edx)
+	movl	%ebx, EAX(%edx)
+	movl	$__USER_DS, DS(%edx)
+	movl	$__USER_DS, ES(%edx)
+	movl	%ebx, ORIG_EAX(%edx)
+	movl	%ecx, EIP(%edx)
+	movl	12(%esp), %ecx
+	movl	$__KERNEL_CS, CS(%edx)
+	movl	%ebx, EFLAGS(%edx)
+	movl	%eax, OLDESP(%edx)
+	movl	8(%esp), %eax
+	movl	%ecx, 8(%esp)
+	movl	EBX(%edx), %ebx
+	movl	$__KERNEL_DS, OLDSS(%edx)
+	jmpl	*%eax
+	CFI_ENDPROC
+ENDPROC(arch_unwind_init_running)
+#endif
 
 .section .rodata,"a"
 #include "syscall_table.S"
diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c
new file mode 100644
index 0000000..c6737c3
--- /dev/null
+++ b/arch/i386/kernel/hpet.c
@@ -0,0 +1,67 @@
+#include <linux/clocksource.h>
+#include <linux/errno.h>
+#include <linux/hpet.h>
+#include <linux/init.h>
+
+#include <asm/hpet.h>
+#include <asm/io.h>
+
+#define HPET_MASK	CLOCKSOURCE_MASK(32)
+#define HPET_SHIFT	22
+
+/* FSEC = 10^-15 NSEC = 10^-9 */
+#define FSEC_PER_NSEC	1000000
+
+static void *hpet_ptr;
+
+static cycle_t read_hpet(void)
+{
+	return (cycle_t)readl(hpet_ptr);
+}
+
+static struct clocksource clocksource_hpet = {
+	.name		= "hpet",
+	.rating		= 250,
+	.read		= read_hpet,
+	.mask		= HPET_MASK,
+	.mult		= 0, /* set below */
+	.shift		= HPET_SHIFT,
+	.is_continuous	= 1,
+};
+
+static int __init init_hpet_clocksource(void)
+{
+	unsigned long hpet_period;
+	void __iomem* hpet_base;
+	u64 tmp;
+
+	if (!hpet_address)
+		return -ENODEV;
+
+	/* calculate the hpet address: */
+	hpet_base =
+		(void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
+	hpet_ptr = hpet_base + HPET_COUNTER;
+
+	/* calculate the frequency: */
+	hpet_period = readl(hpet_base + HPET_PERIOD);
+
+	/*
+	 * hpet period is in femto seconds per cycle
+	 * so we need to convert this to ns/cyc units
+	 * aproximated by mult/2^shift
+	 *
+	 *  fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
+	 *  fsec/cyc * 1ns/1000000fsec * 2^shift = mult
+	 *  fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
+	 *  (fsec/cyc << shift)/1000000 = mult
+	 *  (hpet_period << shift)/FSEC_PER_NSEC = mult
+	 */
+	tmp = (u64)hpet_period << HPET_SHIFT;
+	do_div(tmp, FSEC_PER_NSEC);
+	clocksource_hpet.mult = (u32)tmp;
+
+	return clocksource_register(&clocksource_hpet);
+}
+
+module_init(init_hpet_clocksource);
diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
index d755247..c435197 100644
--- a/arch/i386/kernel/i387.c
+++ b/arch/i386/kernel/i387.c
@@ -25,7 +25,7 @@
 #define HAVE_HWFP 1
 #endif
 
-static unsigned long mxcsr_feature_mask = 0xffffffff;
+static unsigned long mxcsr_feature_mask __read_mostly = 0xffffffff;
 
 void mxcsr_feature_mask_init(void)
 {
diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c
new file mode 100644
index 0000000..477b24d
--- /dev/null
+++ b/arch/i386/kernel/i8253.c
@@ -0,0 +1,118 @@
+/*
+ * i8253.c  8253/PIT functions
+ *
+ */
+#include <linux/clocksource.h>
+#include <linux/spinlock.h>
+#include <linux/jiffies.h>
+#include <linux/sysdev.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/smp.h>
+#include <asm/delay.h>
+#include <asm/i8253.h>
+#include <asm/io.h>
+
+#include "io_ports.h"
+
+DEFINE_SPINLOCK(i8253_lock);
+EXPORT_SYMBOL(i8253_lock);
+
+void setup_pit_timer(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+	outb_p(0x34,PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
+	udelay(10);
+	outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
+	udelay(10);
+	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
+	spin_unlock_irqrestore(&i8253_lock, flags);
+}
+
+/*
+ * Since the PIT overflows every tick, its not very useful
+ * to just read by itself. So use jiffies to emulate a free
+ * running counter:
+ */
+static cycle_t pit_read(void)
+{
+	unsigned long flags;
+	int count;
+	u32 jifs;
+	static int old_count;
+	static u32 old_jifs;
+
+	spin_lock_irqsave(&i8253_lock, flags);
+        /*
+	 * Although our caller may have the read side of xtime_lock,
+	 * this is now a seqlock, and we are cheating in this routine
+	 * by having side effects on state that we cannot undo if
+	 * there is a collision on the seqlock and our caller has to
+	 * retry.  (Namely, old_jifs and old_count.)  So we must treat
+	 * jiffies as volatile despite the lock.  We read jiffies
+	 * before latching the timer count to guarantee that although
+	 * the jiffies value might be older than the count (that is,
+	 * the counter may underflow between the last point where
+	 * jiffies was incremented and the point where we latch the
+	 * count), it cannot be newer.
+	 */
+	jifs = jiffies;
+	outb_p(0x00, PIT_MODE);	/* latch the count ASAP */
+	count = inb_p(PIT_CH0);	/* read the latched count */
+	count |= inb_p(PIT_CH0) << 8;
+
+	/* VIA686a test code... reset the latch if count > max + 1 */
+	if (count > LATCH) {
+		outb_p(0x34, PIT_MODE);
+		outb_p(LATCH & 0xff, PIT_CH0);
+		outb(LATCH >> 8, PIT_CH0);
+		count = LATCH - 1;
+	}
+
+	/*
+	 * It's possible for count to appear to go the wrong way for a
+	 * couple of reasons:
+	 *
+	 *  1. The timer counter underflows, but we haven't handled the
+	 *     resulting interrupt and incremented jiffies yet.
+	 *  2. Hardware problem with the timer, not giving us continuous time,
+	 *     the counter does small "jumps" upwards on some Pentium systems,
+	 *     (see c't 95/10 page 335 for Neptun bug.)
+	 *
+	 * Previous attempts to handle these cases intelligently were
+	 * buggy, so we just do the simple thing now.
+	 */
+	if (count > old_count && jifs == old_jifs) {
+		count = old_count;
+	}
+	old_count = count;
+	old_jifs = jifs;
+
+	spin_unlock_irqrestore(&i8253_lock, flags);
+
+	count = (LATCH - 1) - count;
+
+	return (cycle_t)(jifs * LATCH) + count;
+}
+
+static struct clocksource clocksource_pit = {
+	.name	= "pit",
+	.rating = 110,
+	.read	= pit_read,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.mult	= 0,
+	.shift	= 20,
+};
+
+static int __init init_pit_clocksource(void)
+{
+	if (num_possible_cpus() > 4) /* PIT does not scale! */
+		return 0;
+
+	clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20);
+	return clocksource_register(&clocksource_pit);
+}
+module_init(init_pit_clocksource);
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 323ef8a..c1a42fe 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -175,7 +175,7 @@
 	 * Lightweight spurious IRQ detection. We do not want
 	 * to overdo spurious IRQ handling - it's usually a sign
 	 * of hardware problems, so we only do the checks we can
-	 * do without slowing down good hardware unnecesserily.
+	 * do without slowing down good hardware unnecessarily.
 	 *
 	 * Note that IRQ7 and IRQ15 (the two spurious IRQs
 	 * usually resulting from the 8259A-1|2 PICs) occur
@@ -271,8 +271,8 @@
 	 * the kernel initialization code can get it
 	 * out of.
 	 */
-	outb(0xff, 0x21);	/* mask all of 8259A-1 */
-	outb(0xff, 0xA1);	/* mask all of 8259A-1 */
+	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
+	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-1 */
 	return 0;
 }
 
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index d70f2ad..72ae414 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -38,6 +38,7 @@
 #include <asm/desc.h>
 #include <asm/timer.h>
 #include <asm/i8259.h>
+#include <asm/nmi.h>
 
 #include <mach_apic.h>
 
@@ -50,6 +51,7 @@
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
 static DEFINE_SPINLOCK(ioapic_lock);
+static DEFINE_SPINLOCK(vector_lock);
 
 int timer_over_8254 __initdata = 1;
 
@@ -267,7 +269,7 @@
 # include <linux/slab.h>		/* kmalloc() */
 # include <linux/timer.h>	/* time_after() */
  
-# ifdef CONFIG_BALANCED_IRQ_DEBUG
+#ifdef CONFIG_BALANCED_IRQ_DEBUG
 #  define TDprintk(x...) do { printk("<%ld:%s:%d>: ", jiffies, __FILE__, __LINE__); printk(x); } while (0)
 #  define Dprintk(x...) do { TDprintk(x); } while (0)
 # else
@@ -275,10 +277,15 @@
 #  define Dprintk(x...) 
 # endif
 
-
 #define IRQBALANCE_CHECK_ARCH -999
-static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH;
-static int physical_balance = 0;
+#define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
+#define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
+#define BALANCED_IRQ_MORE_DELTA		(HZ/10)
+#define BALANCED_IRQ_LESS_DELTA		(HZ)
+
+static int irqbalance_disabled __read_mostly = IRQBALANCE_CHECK_ARCH;
+static int physical_balance __read_mostly;
+static long balanced_irq_interval __read_mostly = MAX_BALANCED_IRQ_INTERVAL;
 
 static struct irq_cpu_info {
 	unsigned long * last_irq;
@@ -297,12 +304,14 @@
 
 #define CPU_TO_PACKAGEINDEX(i) (first_cpu(cpu_sibling_map[i]))
 
-#define MAX_BALANCED_IRQ_INTERVAL	(5*HZ)
-#define MIN_BALANCED_IRQ_INTERVAL	(HZ/2)
-#define BALANCED_IRQ_MORE_DELTA		(HZ/10)
-#define BALANCED_IRQ_LESS_DELTA		(HZ)
+static cpumask_t balance_irq_affinity[NR_IRQS] = {
+	[0 ... NR_IRQS-1] = CPU_MASK_ALL
+};
 
-static long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL;
+void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
+{
+	balance_irq_affinity[irq] = mask;
+}
 
 static unsigned long move(int curr_cpu, cpumask_t allowed_mask,
 			unsigned long now, int direction)
@@ -340,7 +349,7 @@
 	if (irqbalance_disabled)
 		return; 
 
-	cpus_and(allowed_mask, cpu_online_map, irq_affinity[irq]);
+	cpus_and(allowed_mask, cpu_online_map, balance_irq_affinity[irq]);
 	new_cpu = move(cpu, allowed_mask, now, 1);
 	if (cpu != new_cpu) {
 		set_pending_irq(irq, cpumask_of_cpu(new_cpu));
@@ -529,7 +538,9 @@
 		}
 	}
 
-	cpus_and(allowed_mask, cpu_online_map, irq_affinity[selected_irq]);
+	cpus_and(allowed_mask,
+		cpu_online_map,
+		balance_irq_affinity[selected_irq]);
 	target_cpu_mask = cpumask_of_cpu(min_loaded);
 	cpus_and(tmp, target_cpu_mask, allowed_mask);
 
@@ -1152,10 +1163,17 @@
 int assign_irq_vector(int irq)
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+	unsigned long flags;
+	int vector;
 
-	BUG_ON(irq >= NR_IRQ_VECTORS);
-	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
+	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
+
+	spin_lock_irqsave(&vector_lock, flags);
+
+	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
+		spin_unlock_irqrestore(&vector_lock, flags);
 		return IO_APIC_VECTOR(irq);
+	}
 next:
 	current_vector += 8;
 	if (current_vector == SYSCALL_VECTOR)
@@ -1163,16 +1181,21 @@
 
 	if (current_vector >= FIRST_SYSTEM_VECTOR) {
 		offset++;
-		if (!(offset%8))
+		if (!(offset%8)) {
+			spin_unlock_irqrestore(&vector_lock, flags);
 			return -ENOSPC;
+		}
 		current_vector = FIRST_DEVICE_VECTOR + offset;
 	}
 
-	vector_irq[current_vector] = irq;
+	vector = current_vector;
+	vector_irq[vector] = irq;
 	if (irq != AUTO_ASSIGN)
-		IO_APIC_VECTOR(irq) = current_vector;
+		IO_APIC_VECTOR(irq) = vector;
 
-	return current_vector;
+	spin_unlock_irqrestore(&vector_lock, flags);
+
+	return vector;
 }
 
 static struct hw_interrupt_type ioapic_level_type;
@@ -1184,21 +1207,14 @@
 
 static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
 {
-	if (use_pci_vector() && !platform_legacy_irq(irq)) {
-		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-				trigger == IOAPIC_LEVEL)
-			irq_desc[vector].handler = &ioapic_level_type;
-		else
-			irq_desc[vector].handler = &ioapic_edge_type;
-		set_intr_gate(vector, interrupt[vector]);
-	} else	{
-		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-				trigger == IOAPIC_LEVEL)
-			irq_desc[irq].handler = &ioapic_level_type;
-		else
-			irq_desc[irq].handler = &ioapic_edge_type;
-		set_intr_gate(vector, interrupt[irq]);
-	}
+	unsigned idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
+
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+			trigger == IOAPIC_LEVEL)
+		irq_desc[idx].handler = &ioapic_level_type;
+	else
+		irq_desc[idx].handler = &ioapic_edge_type;
+	set_intr_gate(vector, interrupt[idx]);
 }
 
 static void __init setup_IO_APIC_irqs(void)
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index f3a9c78..9eec943 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -42,8 +42,8 @@
 	u32                     stack[THREAD_SIZE/sizeof(u32)];
 };
 
-static union irq_ctx *hardirq_ctx[NR_CPUS];
-static union irq_ctx *softirq_ctx[NR_CPUS];
+static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
+static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
 #endif
 
 /*
@@ -53,13 +53,19 @@
  */
 fastcall unsigned int do_IRQ(struct pt_regs *regs)
 {	
-	/* high bits used in ret_from_ code */
-	int irq = regs->orig_eax & 0xff;
+	/* high bit used in ret_from_ code */
+	int irq = ~regs->orig_eax;
 #ifdef CONFIG_4KSTACKS
 	union irq_ctx *curctx, *irqctx;
 	u32 *isp;
 #endif
 
+	if (unlikely((unsigned)irq >= NR_IRQS)) {
+		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+					__FUNCTION__, irq);
+		BUG();
+	}
+
 	irq_enter();
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 	/* Debugging check for stack overflow: is there less than 1KB free? */
@@ -95,6 +101,14 @@
 		irqctx->tinfo.task = curctx->tinfo.task;
 		irqctx->tinfo.previous_esp = current_stack_pointer;
 
+		/*
+		 * Copy the softirq bits in preempt_count so that the
+		 * softirq checks work in the hardirq context.
+		 */
+		irqctx->tinfo.preempt_count =
+			(irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
+			(curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+
 		asm volatile(
 			"       xchgl   %%ebx,%%esp      \n"
 			"       call    __do_IRQ         \n"
@@ -219,7 +233,7 @@
 	if (i == 0) {
 		seq_printf(p, "           ");
 		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
+			seq_printf(p, "CPU%-8d",j);
 		seq_putc(p, '\n');
 	}
 
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 38806f4..727e419 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -57,34 +57,85 @@
 /*
  * returns non-zero if opcodes can be boosted.
  */
-static __always_inline int can_boost(kprobe_opcode_t opcode)
+static __always_inline int can_boost(kprobe_opcode_t *opcodes)
 {
-	switch (opcode & 0xf0 ) {
+#define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf)		      \
+	(((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
+	  (b4##UL << 0x4)|(b5##UL << 0x5)|(b6##UL << 0x6)|(b7##UL << 0x7) |   \
+	  (b8##UL << 0x8)|(b9##UL << 0x9)|(ba##UL << 0xa)|(bb##UL << 0xb) |   \
+	  (bc##UL << 0xc)|(bd##UL << 0xd)|(be##UL << 0xe)|(bf##UL << 0xf))    \
+	 << (row % 32))
+	/*
+	 * Undefined/reserved opcodes, conditional jump, Opcode Extension
+	 * Groups, and some special opcodes can not be boost.
+	 */
+	static const unsigned long twobyte_is_boostable[256 / 32] = {
+		/*      0 1 2 3 4 5 6 7 8 9 a b c d e f         */
+		/*      -------------------------------         */
+		W(0x00, 0,0,1,1,0,0,1,0,1,1,0,0,0,0,0,0)| /* 00 */
+		W(0x10, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 10 */
+		W(0x20, 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0)| /* 20 */
+		W(0x30, 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 30 */
+		W(0x40, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)| /* 40 */
+		W(0x50, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), /* 50 */
+		W(0x60, 1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1)| /* 60 */
+		W(0x70, 0,0,0,0,1,1,1,1,0,0,0,0,0,0,1,1), /* 70 */
+		W(0x80, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)| /* 80 */
+		W(0x90, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1), /* 90 */
+		W(0xa0, 1,1,0,1,1,1,0,0,1,1,0,1,1,1,0,1)| /* a0 */
+		W(0xb0, 1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1), /* b0 */
+		W(0xc0, 1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1)| /* c0 */
+		W(0xd0, 0,1,1,1,0,1,0,0,1,1,0,1,1,1,0,1), /* d0 */
+		W(0xe0, 0,1,1,0,0,1,0,0,1,1,0,1,1,1,0,1)| /* e0 */
+		W(0xf0, 0,1,1,1,0,1,0,0,1,1,1,0,1,1,1,0)  /* f0 */
+		/*      -------------------------------         */
+		/*      0 1 2 3 4 5 6 7 8 9 a b c d e f         */
+	};
+#undef W
+	kprobe_opcode_t opcode;
+	kprobe_opcode_t *orig_opcodes = opcodes;
+retry:
+	if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
+		return 0;
+	opcode = *(opcodes++);
+
+	/* 2nd-byte opcode */
+	if (opcode == 0x0f) {
+		if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
+			return 0;
+		return test_bit(*opcodes, twobyte_is_boostable);
+	}
+
+	switch (opcode & 0xf0) {
+	case 0x60:
+		if (0x63 < opcode && opcode < 0x67)
+			goto retry; /* prefixes */
+		/* can't boost Address-size override and bound */
+		return (opcode != 0x62 && opcode != 0x67);
 	case 0x70:
 		return 0; /* can't boost conditional jump */
-	case 0x90:
-		/* can't boost call and pushf */
-		return opcode != 0x9a && opcode != 0x9c;
 	case 0xc0:
-		/* can't boost undefined opcodes and soft-interruptions */
-		return (0xc1 < opcode && opcode < 0xc6) ||
-			(0xc7 < opcode && opcode < 0xcc) || opcode == 0xcf;
+		/* can't boost software-interruptions */
+		return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
 	case 0xd0:
 		/* can boost AA* and XLAT */
 		return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
 	case 0xe0:
-		/* can boost in/out and (may be) jmps */
-		return (0xe3 < opcode && opcode != 0xe8);
+		/* can boost in/out and absolute jmps */
+		return ((opcode & 0x04) || opcode == 0xea);
 	case 0xf0:
+		if ((opcode & 0x0c) == 0 && opcode != 0xf1)
+			goto retry; /* lock/rep(ne) prefix */
 		/* clear and set flags can be boost */
 		return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
 	default:
-		/* currently, can't boost 2 bytes opcodes */
-		return opcode != 0x0f;
+		if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
+			goto retry; /* prefixes */
+		/* can't boost CS override and call */
+		return (opcode != 0x2e && opcode != 0x9a);
 	}
 }
 
-
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
@@ -109,7 +160,7 @@
 
 	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
 	p->opcode = *p->addr;
-	if (can_boost(p->opcode)) {
+	if (can_boost(p->addr)) {
 		p->ainsn.boostable = 0;
 	} else {
 		p->ainsn.boostable = -1;
@@ -208,7 +259,9 @@
 	struct kprobe_ctlblk *kcb;
 #ifdef CONFIG_PREEMPT
 	unsigned pre_preempt_count = preempt_count();
-#endif /* CONFIG_PREEMPT */
+#else
+	unsigned pre_preempt_count = 1;
+#endif
 
 	addr = (kprobe_opcode_t *)(regs->eip - sizeof(kprobe_opcode_t));
 
@@ -285,22 +338,14 @@
 		/* handler has already set things up, so skip ss setup */
 		return 1;
 
-	if (p->ainsn.boostable == 1 &&
-#ifdef CONFIG_PREEMPT
-	    !(pre_preempt_count) && /*
-				       * This enables booster when the direct
-				       * execution path aren't preempted.
-				       */
-#endif /* CONFIG_PREEMPT */
-	    !p->post_handler && !p->break_handler ) {
+ss_probe:
+	if (pre_preempt_count && p->ainsn.boostable == 1 && !p->post_handler){
 		/* Boost up -- we can execute copied instructions directly */
 		reset_current_kprobe();
 		regs->eip = (unsigned long)p->ainsn.insn;
 		preempt_enable_no_resched();
 		return 1;
 	}
-
-ss_probe:
 	prepare_singlestep(p, regs);
 	kcb->kprobe_status = KPROBE_HIT_SS;
 	return 1;
@@ -607,7 +652,7 @@
 	struct die_args *args = (struct die_args *)data;
 	int ret = NOTIFY_DONE;
 
-	if (args->regs && user_mode(args->regs))
+	if (args->regs && user_mode_vm(args->regs))
 		return ret;
 
 	switch (val) {
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
index f73d737..511abe5 100644
--- a/arch/i386/kernel/machine_kexec.c
+++ b/arch/i386/kernel/machine_kexec.c
@@ -133,9 +133,9 @@
 					unsigned long start_address,
 					unsigned int has_pae) ATTRIB_NORET;
 
-const extern unsigned char relocate_new_kernel[];
+extern const unsigned char relocate_new_kernel[];
 extern void relocate_new_kernel_end(void);
-const extern unsigned int relocate_new_kernel_size;
+extern const unsigned int relocate_new_kernel_size;
 
 /*
  * A architecture hook called to validate the
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index e7c138f..0a86588 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -91,7 +91,10 @@
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
 MODULE_LICENSE("GPL");
 
-#define MICROCODE_VERSION 	"1.14"
+static int verbose;
+module_param(verbose, int, 0644);
+
+#define MICROCODE_VERSION 	"1.14a"
 
 #define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
 #define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
@@ -122,14 +125,15 @@
 
 typedef enum mc_error_code {
 	MC_SUCCESS 	= 0,
-	MC_NOTFOUND 	= 1,
-	MC_MARKED 	= 2,
-	MC_ALLOCATED 	= 3,
+	MC_IGNORED 	= 1,
+	MC_NOTFOUND 	= 2,
+	MC_MARKED 	= 3,
+	MC_ALLOCATED 	= 4,
 } mc_error_code_t;
 
 static struct ucode_cpu_info {
 	unsigned int sig;
-	unsigned int pf;
+	unsigned int pf, orig_pf;
 	unsigned int rev;
 	unsigned int cksum;
 	mc_error_code_t err;
@@ -164,6 +168,7 @@
 			rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
 			uci->pf = 1 << ((val[1] >> 18) & 7);
 		}
+		uci->orig_pf = uci->pf;
 	}
 
 	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -197,21 +202,34 @@
 	pr_debug("   Checksum 0x%x\n", cksum);
 
 	if (mc_header->rev < uci->rev) {
-		printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision"
-		       " 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
-		goto out;
+		if (uci->err == MC_NOTFOUND) {
+			uci->err = MC_IGNORED;
+			uci->cksum = mc_header->rev;
+		} else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
+			uci->cksum = mc_header->rev;
 	} else if (mc_header->rev == uci->rev) {
-		/* notify the caller of success on this cpu */
-		uci->err = MC_SUCCESS;
-		goto out;
+		if (uci->err < MC_MARKED) {
+			/* notify the caller of success on this cpu */
+			uci->err = MC_SUCCESS;
+		}
+	} else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
+		pr_debug("microcode: CPU%d found a matching microcode update with "
+			" revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
+		uci->cksum = cksum;
+		uci->pf = pf; /* keep the original mc pf for cksum calculation */
+		uci->err = MC_MARKED; /* found the match */
+		for_each_online_cpu(cpu_num) {
+			if (ucode_cpu_info + cpu_num != uci
+			    && ucode_cpu_info[cpu_num].mc == uci->mc) {
+				uci->mc = NULL;
+				break;
+			}
+		}
+		if (uci->mc != NULL) {
+			vfree(uci->mc);
+			uci->mc = NULL;
+		}
 	}
-
-	pr_debug("microcode: CPU%d found a matching microcode update with "
-		" revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
-	uci->cksum = cksum;
-	uci->pf = pf; /* keep the original mc pf for cksum calculation */
-	uci->err = MC_MARKED; /* found the match */
-out:
 	return;
 }
 
@@ -253,10 +271,8 @@
 
 		for_each_online_cpu(cpu_num) {
 			struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-			if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/
-				continue;
 
-			if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->pf))
+			if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf))
 				mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);
 		}
 
@@ -295,9 +311,8 @@
 				}
 				for_each_online_cpu(cpu_num) {
 					struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-					if (uci->err != MC_NOTFOUND) /* already found a match or not an online cpu*/
-						continue;
-					if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->pf)) {
+
+					if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
 						mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
 					}
 				}
@@ -368,6 +383,13 @@
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
 	if (uci->mc == NULL) {
+		if (verbose) {
+			if (uci->err == MC_SUCCESS)
+				printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
+					cpu_num, uci->rev);
+			else
+				printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
+		}
 		return;
 	}
 
@@ -426,6 +448,9 @@
 					ucode_cpu_info[j].mc = NULL;
 			}
 		}
+		if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
+			printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
+			       " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
 	}
 out:
 	return error;
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 7a32823..d022cb8 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -266,7 +266,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block msr_class_cpu_notifier =
+static struct notifier_block __cpuinitdata msr_class_cpu_notifier =
 {
 	.notifier_call = msr_class_cpu_callback,
 };
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index d43b498..a76e931 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -14,21 +14,17 @@
  */
 
 #include <linux/config.h>
-#include <linux/mm.h>
 #include <linux/delay.h>
-#include <linux/bootmem.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
-#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/nmi.h>
 #include <linux/sysdev.h>
 #include <linux/sysctl.h>
+#include <linux/percpu.h>
 
 #include <asm/smp.h>
-#include <asm/div64.h>
 #include <asm/nmi.h>
+#include <asm/intel_arch_perfmon.h>
 
 #include "mach_traps.h"
 
@@ -100,6 +96,9 @@
 	(P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|	\
 	 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
 
+#define ARCH_PERFMON_NMI_EVENT_SEL	ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
+#define ARCH_PERFMON_NMI_EVENT_UMASK	ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+
 #ifdef CONFIG_SMP
 /* The performance counters used by NMI_LOCAL_APIC don't trigger when
  * the CPU is idle. To make sure the NMI watchdog really ticks on all
@@ -212,6 +211,8 @@
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
+static void disable_intel_arch_watchdog(void);
+
 static void disable_lapic_nmi_watchdog(void)
 {
 	if (nmi_active <= 0)
@@ -221,6 +222,10 @@
 		wrmsr(MSR_K7_EVNTSEL0, 0, 0);
 		break;
 	case X86_VENDOR_INTEL:
+		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+			disable_intel_arch_watchdog();
+			break;
+		}
 		switch (boot_cpu_data.x86) {
 		case 6:
 			if (boot_cpu_data.x86_model > 0xd)
@@ -449,6 +454,53 @@
 	return 1;
 }
 
+static void disable_intel_arch_watchdog(void)
+{
+	unsigned ebx;
+
+	/*
+	 * Check whether the Architectural PerfMon supports
+	 * Unhalted Core Cycles Event or not.
+	 * NOTE: Corresponding bit = 0 in ebp indicates event present.
+	 */
+	ebx = cpuid_ebx(10);
+	if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+		wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0);
+}
+
+static int setup_intel_arch_watchdog(void)
+{
+	unsigned int evntsel;
+	unsigned ebx;
+
+	/*
+	 * Check whether the Architectural PerfMon supports
+	 * Unhalted Core Cycles Event or not.
+	 * NOTE: Corresponding bit = 0 in ebp indicates event present.
+	 */
+	ebx = cpuid_ebx(10);
+	if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+		return 0;
+
+	nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+
+	clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2);
+	clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2);
+
+	evntsel = ARCH_PERFMON_EVENTSEL_INT
+		| ARCH_PERFMON_EVENTSEL_OS
+		| ARCH_PERFMON_EVENTSEL_USR
+		| ARCH_PERFMON_NMI_EVENT_SEL
+		| ARCH_PERFMON_NMI_EVENT_UMASK;
+
+	wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+	write_watchdog_counter("INTEL_ARCH_PERFCTR0");
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+	evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+	wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+	return 1;
+}
+
 void setup_apic_nmi_watchdog (void)
 {
 	switch (boot_cpu_data.x86_vendor) {
@@ -458,6 +510,11 @@
 		setup_k7_watchdog();
 		break;
 	case X86_VENDOR_INTEL:
+		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+			if (!setup_intel_arch_watchdog())
+				return;
+			break;
+		}
 		switch (boot_cpu_data.x86) {
 		case 6:
 			if (boot_cpu_data.x86_model > 0xd)
@@ -561,7 +618,8 @@
 			wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
 			apic_write(APIC_LVTPC, APIC_DM_NMI);
 		}
-		else if (nmi_perfctr_msr == MSR_P6_PERFCTR0) {
+		else if (nmi_perfctr_msr == MSR_P6_PERFCTR0 ||
+		         nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
 			/* Only P6 based Pentium M need to re-unmask
 			 * the apic vector but it doesn't hurt
 			 * other P6 variant */
diff --git a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c
index 5f5b075..0caf146 100644
--- a/arch/i386/kernel/numaq.c
+++ b/arch/i386/kernel/numaq.c
@@ -79,10 +79,12 @@
 	return 1;
 }
 
-static int __init numaq_dsc_disable(void)
+static int __init numaq_tsc_disable(void)
 {
-	printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
-	tsc_disable = 1;
+	if (num_online_nodes() > 1) {
+		printk(KERN_DEBUG "NUMAQ: disabling TSC\n");
+		tsc_disable = 1;
+	}
 	return 0;
 }
-core_initcall(numaq_dsc_disable);
+arch_initcall(numaq_tsc_disable);
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 6259afe..6946b06 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -102,7 +102,7 @@
 	local_irq_enable();
 
 	if (!hlt_counter && boot_cpu_data.hlt_works_ok) {
-		clear_thread_flag(TIF_POLLING_NRFLAG);
+		current_thread_info()->status &= ~TS_POLLING;
 		smp_mb__after_clear_bit();
 		while (!need_resched()) {
 			local_irq_disable();
@@ -111,7 +111,7 @@
 			else
 				local_irq_enable();
 		}
-		set_thread_flag(TIF_POLLING_NRFLAG);
+		current_thread_info()->status |= TS_POLLING;
 	} else {
 		while (!need_resched())
 			cpu_relax();
@@ -174,7 +174,7 @@
 {
 	int cpu = smp_processor_id();
 
-	set_thread_flag(TIF_POLLING_NRFLAG);
+	current_thread_info()->status |= TS_POLLING;
 
 	/* endless idle loop with no priority at all */
 	while (1) {
@@ -312,7 +312,7 @@
 	cr3 = read_cr3();
 	cr4 = read_cr4_safe();
 	printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4);
-	show_trace(NULL, &regs->esp);
+	show_trace(NULL, regs, &regs->esp);
 }
 
 /*
diff --git a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c
index 321f5fd..9bf590c 100644
--- a/arch/i386/kernel/scx200.c
+++ b/arch/i386/kernel/scx200.c
@@ -9,6 +9,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
 #include <linux/pci.h>
 
 #include <linux/scx200.h>
@@ -45,11 +46,19 @@
 	.probe = scx200_probe,
 };
 
-static DEFINE_SPINLOCK(scx200_gpio_config_lock);
+static DEFINE_MUTEX(scx200_gpio_config_lock);
+
+static void __devinit scx200_init_shadow(void)
+{
+	int bank;
+
+	/* read the current values driven on the GPIO signals */
+	for (bank = 0; bank < 2; ++bank)
+		scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
+}
 
 static int __devinit scx200_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	int bank;
 	unsigned base;
 
 	if (pdev->device == PCI_DEVICE_ID_NS_SCx200_BRIDGE ||
@@ -63,10 +72,7 @@
 		}
 
 		scx200_gpio_base = base;
-
-		/* read the current values driven on the GPIO signals */
-		for (bank = 0; bank < 2; ++bank)
-			scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
+		scx200_init_shadow();
 
 	} else {
 		/* find the base of the Configuration Block */
@@ -87,12 +93,11 @@
 	return 0;
 }
 
-u32 scx200_gpio_configure(int index, u32 mask, u32 bits)
+u32 scx200_gpio_configure(unsigned index, u32 mask, u32 bits)
 {
 	u32 config, new_config;
-	unsigned long flags;
 
-	spin_lock_irqsave(&scx200_gpio_config_lock, flags);
+	mutex_lock(&scx200_gpio_config_lock);
 
 	outl(index, scx200_gpio_base + 0x20);
 	config = inl(scx200_gpio_base + 0x24);
@@ -100,45 +105,11 @@
 	new_config = (config & mask) | bits;
 	outl(new_config, scx200_gpio_base + 0x24);
 
-	spin_unlock_irqrestore(&scx200_gpio_config_lock, flags);
+	mutex_unlock(&scx200_gpio_config_lock);
 
 	return config;
 }
 
-#if 0
-void scx200_gpio_dump(unsigned index)
-{
-	u32 config = scx200_gpio_configure(index, ~0, 0);
-	printk(KERN_DEBUG "GPIO%02u: 0x%08lx", index, (unsigned long)config);
-	
-	if (config & 1) 
-		printk(" OE"); /* output enabled */
-	else
-		printk(" TS"); /* tristate */
-	if (config & 2) 
-		printk(" PP"); /* push pull */
-	else
-		printk(" OD"); /* open drain */
-	if (config & 4) 
-		printk(" PUE"); /* pull up enabled */
-	else
-		printk(" PUD"); /* pull up disabled */
-	if (config & 8) 
-		printk(" LOCKED"); /* locked */
-	if (config & 16) 
-		printk(" LEVEL"); /* level input */
-	else
-		printk(" EDGE"); /* edge input */
-	if (config & 32) 
-		printk(" HI"); /* trigger on rising edge */
-	else
-		printk(" LO"); /* trigger on falling edge */
-	if (config & 64) 
-		printk(" DEBOUNCE"); /* debounce */
-	printk("\n");
-}
-#endif  /*  0  */
-
 static int __init scx200_init(void)
 {
 	printk(KERN_INFO NAME ": NatSemi SCx200 Driver\n");
@@ -159,10 +130,3 @@
 EXPORT_SYMBOL(scx200_gpio_shadow);
 EXPORT_SYMBOL(scx200_gpio_configure);
 EXPORT_SYMBOL(scx200_cb_base);
-
-/*
-    Local variables:
-        compile-command: "make -k -C ../../.. SUBDIRS=arch/i386/kernel modules"
-        c-basic-offset: 8
-    End:
-*/
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index dd6b0e3..4a65040 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -60,7 +60,7 @@
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/io.h>
-#include "setup_arch_pre.h"
+#include <setup_arch.h>
 #include <bios_ebda.h>
 
 /* Forward Declaration. */
@@ -410,8 +410,8 @@
 	}
 }
 
-static void __init add_memory_region(unsigned long long start,
-                                  unsigned long long size, int type)
+void __init add_memory_region(unsigned long long start,
+			      unsigned long long size, int type)
 {
 	int x;
 
@@ -474,7 +474,7 @@
 static struct e820entry *overlap_list[E820MAX] __initdata;
 static struct e820entry new_bios[E820MAX] __initdata;
 
-static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
 {
 	struct change_member *change_tmp;
 	unsigned long current_type, last_type;
@@ -643,7 +643,7 @@
  * thinkpad 560x, for example, does not cooperate with the memory
  * detection code.)
  */
-static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
+int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
 {
 	/* Only one memory region (or negative)? Ignore it */
 	if (nr_map < 2)
@@ -701,12 +701,6 @@
 }
 #endif
 
-/*
- * Do NOT EVER look at the BIOS memory size location.
- * It does not work on many machines.
- */
-#define LOWMEMSIZE()	(0x9f000)
-
 static void __init parse_cmdline_early (char ** cmdline_p)
 {
 	char c = ' ', *to = command_line, *from = saved_command_line;
@@ -1423,8 +1417,6 @@
 		pci_mem_start, gapstart, gapsize);
 }
 
-static char * __init machine_specific_memory_setup(void);
-
 #ifdef CONFIG_MCA
 static void set_mca_bus(int x)
 {
@@ -1583,6 +1575,7 @@
 	conswitchp = &dummy_con;
 #endif
 #endif
+	tsc_init();
 }
 
 static __init int add_pcspkr(void)
@@ -1602,7 +1595,6 @@
 }
 device_initcall(add_pcspkr);
 
-#include "setup_arch_post.h"
 /*
  * Local Variables:
  * mode:c
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 5c352c3..43002cf 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -351,7 +351,7 @@
 			goto give_sigsegv;
 	}
 
-	restorer = &__kernel_sigreturn;
+	restorer = (void *)VDSO_SYM(&__kernel_sigreturn);
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 
@@ -447,7 +447,7 @@
 		goto give_sigsegv;
 
 	/* Set up to return from userspace.  */
-	restorer = &__kernel_rt_sigreturn;
+	restorer = (void *)VDSO_SYM(&__kernel_rt_sigreturn);
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 	err |= __put_user(restorer, &frame->pretcode);
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index d134e96..c10789d 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -114,7 +114,17 @@
 
 static inline int __prepare_ICR (unsigned int shortcut, int vector)
 {
-	return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL;
+	unsigned int icr = shortcut | APIC_DEST_LOGICAL;
+
+	switch (vector) {
+	default:
+		icr |= APIC_DM_FIXED | vector;
+		break;
+	case NMI_VECTOR:
+		icr |= APIC_DM_NMI;
+		break;
+	}
+	return icr;
 }
 
 static inline int __prepare_ICR2 (unsigned int mask)
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 825b2b4..89e7315 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -52,6 +52,7 @@
 #include <asm/tlbflush.h>
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
+#include <asm/nmi.h>
 
 #include <mach_apic.h>
 #include <mach_wakecpu.h>
@@ -66,12 +67,6 @@
 EXPORT_SYMBOL(smp_num_siblings);
 #endif
 
-/* Package ID of each logical CPU */
-int phys_proc_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
-
-/* Core ID of each logical CPU */
-int cpu_core_id[NR_CPUS] __read_mostly = {[0 ... NR_CPUS-1] = BAD_APICID};
-
 /* Last level cache ID of each logical CPU */
 int cpu_llc_id[NR_CPUS] __cpuinitdata = {[0 ... NR_CPUS-1] = BAD_APICID};
 
@@ -257,7 +252,7 @@
 		 * all APs synchronize but they loop on '== num_cpus'
 		 */
 		while (atomic_read(&tsc_count_start) != num_booting_cpus()-1)
-			mb();
+			cpu_relax();
 		atomic_set(&tsc_count_stop, 0);
 		wmb();
 		/*
@@ -276,7 +271,7 @@
 		 * Wait for all APs to leave the synchronization point:
 		 */
 		while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1)
-			mb();
+			cpu_relax();
 		atomic_set(&tsc_count_start, 0);
 		wmb();
 		atomic_inc(&tsc_count_stop);
@@ -333,19 +328,21 @@
 	 * this gets called, so we first wait for the BP to
 	 * finish SMP initialization:
 	 */
-	while (!atomic_read(&tsc_start_flag)) mb();
+	while (!atomic_read(&tsc_start_flag))
+		cpu_relax();
 
 	for (i = 0; i < NR_LOOPS; i++) {
 		atomic_inc(&tsc_count_start);
 		while (atomic_read(&tsc_count_start) != num_booting_cpus())
-			mb();
+			cpu_relax();
 
 		rdtscll(tsc_values[smp_processor_id()]);
 		if (i == NR_LOOPS-1)
 			write_tsc(0, 0);
 
 		atomic_inc(&tsc_count_stop);
-		while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb();
+		while (atomic_read(&tsc_count_stop) != num_booting_cpus())
+			cpu_relax();
 	}
 }
 #undef NR_LOOPS
@@ -451,10 +448,12 @@
 	struct cpuinfo_x86 *c = cpu_data + cpu;
 	/*
 	 * For perf, we return last level cache shared map.
-	 * TBD: when power saving sched policy is added, we will return
-	 *      cpu_core_map when power saving policy is enabled
+	 * And for power savings, we return cpu_core_map
 	 */
-	return c->llc_shared_map;
+	if (sched_mc_power_savings || sched_smt_power_savings)
+		return cpu_core_map[cpu];
+	else
+		return c->llc_shared_map;
 }
 
 /* representing cpus for which sibling maps can be computed */
@@ -470,8 +469,8 @@
 
 	if (smp_num_siblings > 1) {
 		for_each_cpu_mask(i, cpu_sibling_setup_map) {
-			if (phys_proc_id[cpu] == phys_proc_id[i] &&
-			    cpu_core_id[cpu] == cpu_core_id[i]) {
+			if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
+			    c[cpu].cpu_core_id == c[i].cpu_core_id) {
 				cpu_set(i, cpu_sibling_map[cpu]);
 				cpu_set(cpu, cpu_sibling_map[i]);
 				cpu_set(i, cpu_core_map[cpu]);
@@ -498,7 +497,7 @@
 			cpu_set(i, c[cpu].llc_shared_map);
 			cpu_set(cpu, c[i].llc_shared_map);
 		}
-		if (phys_proc_id[cpu] == phys_proc_id[i]) {
+		if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
 			cpu_set(i, cpu_core_map[cpu]);
 			cpu_set(cpu, cpu_core_map[i]);
 			/*
@@ -1053,6 +1052,7 @@
 	struct warm_boot_cpu_info info;
 	struct work_struct task;
 	int	apicid, ret;
+	struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
 
 	apicid = x86_cpu_to_apicid[cpu];
 	if (apicid == BAD_APICID) {
@@ -1060,6 +1060,18 @@
 		goto exit;
 	}
 
+	/*
+	 * the CPU isn't initialized at boot time, allocate gdt table here.
+	 * cpu_init will initialize it
+	 */
+	if (!cpu_gdt_descr->address) {
+		cpu_gdt_descr->address = get_zeroed_page(GFP_KERNEL);
+		if (!cpu_gdt_descr->address)
+			printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
+			ret = -ENOMEM;
+			goto exit;
+	}
+
 	info.complete = &done;
 	info.apicid = apicid;
 	info.cpu = cpu;
@@ -1337,8 +1349,8 @@
 		cpu_clear(cpu, cpu_sibling_map[sibling]);
 	cpus_clear(cpu_sibling_map[cpu]);
 	cpus_clear(cpu_core_map[cpu]);
-	phys_proc_id[cpu] = BAD_APICID;
-	cpu_core_id[cpu] = BAD_APICID;
+	c[cpu].phys_proc_id = 0;
+	c[cpu].cpu_core_id = 0;
 	cpu_clear(cpu, cpu_sibling_setup_map);
 }
 
@@ -1433,7 +1445,7 @@
 	/* Unleash the CPU! */
 	cpu_set(cpu, smp_commenced_mask);
 	while (!cpu_isset(cpu, cpu_online_map))
-		mb();
+		cpu_relax();
 	return 0;
 }
 
diff --git a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
index 52b3ed5..989c852 100644
--- a/arch/i386/kernel/srat.c
+++ b/arch/i386/kernel/srat.c
@@ -39,7 +39,6 @@
 #define NODE_ARRAY_OFFSET(x)	((x) % 8)	/* 8 bits/char */
 #define BMAP_SET(bmap, bit)	((bmap)[NODE_ARRAY_INDEX(bit)] |= 1 << NODE_ARRAY_OFFSET(bit))
 #define BMAP_TEST(bmap, bit)	((bmap)[NODE_ARRAY_INDEX(bit)] & (1 << NODE_ARRAY_OFFSET(bit)))
-#define MAX_PXM_DOMAINS		256	/* 1 byte and no promises about values */
 /* bitmap length; _PXM is at most 255 */
 #define PXM_BITMAP_LEN (MAX_PXM_DOMAINS / 8) 
 static u8 pxm_bitmap[PXM_BITMAP_LEN];	/* bitmap of proximity domains */
@@ -213,19 +212,11 @@
 		node_end_pfn[nid] = memory_chunk->end_pfn;
 }
 
-static u8 pxm_to_nid_map[MAX_PXM_DOMAINS];/* _PXM to logical node ID map */
-
-int pxm_to_node(int pxm)
-{
-	return pxm_to_nid_map[pxm];
-}
-
 /* Parse the ACPI Static Resource Affinity Table */
 static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 {
 	u8 *start, *end, *p;
 	int i, j, nid;
-	u8 nid_to_pxm_map[MAX_NUMNODES];/* logical node ID to _PXM map */
 
 	start = (u8 *)(&(sratp->reserved) + 1);	/* skip header */
 	p = start;
@@ -235,10 +226,6 @@
 	memset(node_memory_chunk, 0, sizeof(node_memory_chunk));
 	memset(zholes_size, 0, sizeof(zholes_size));
 
-	/* -1 in these maps means not available */
-	memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
-	memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
-
 	num_memory_chunks = 0;
 	while (p < end) {
 		switch (*p) {
@@ -278,9 +265,7 @@
 	nodes_clear(node_online_map);
 	for (i = 0; i < MAX_PXM_DOMAINS; i++) {
 		if (BMAP_TEST(pxm_bitmap, i)) {
-			nid = num_online_nodes();
-			pxm_to_nid_map[i] = nid;
-			nid_to_pxm_map[nid] = i;
+			int nid = acpi_map_pxm_to_node(i);
 			node_set_online(nid);
 		}
 	}
@@ -288,7 +273,7 @@
 
 	/* set cnode id in memory chunk structure */
 	for (i = 0; i < num_memory_chunks; i++)
-		node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm];
+		node_memory_chunk[i].nid = pxm_to_node(node_memory_chunk[i].pxm);
 
 	printk("pxm bitmap: ");
 	for (i = 0; i < sizeof(pxm_bitmap); i++) {
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index af56987..dd63d47 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -316,3 +316,4 @@
 	.long sys_sync_file_range
 	.long sys_tee			/* 315 */
 	.long sys_vmsplice
+	.long sys_move_pages
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
index 0bada18..713ba39 100644
--- a/arch/i386/kernel/sysenter.c
+++ b/arch/i386/kernel/sysenter.c
@@ -2,6 +2,8 @@
  * linux/arch/i386/kernel/sysenter.c
  *
  * (C) Copyright 2002 Linus Torvalds
+ * Portions based on the vdso-randomization code from exec-shield:
+ * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
  *
  * This file contains the needed initializations to support sysenter.
  */
@@ -13,12 +15,31 @@
 #include <linux/gfp.h>
 #include <linux/string.h>
 #include <linux/elf.h>
+#include <linux/mm.h>
+#include <linux/module.h>
 
 #include <asm/cpufeature.h>
 #include <asm/msr.h>
 #include <asm/pgtable.h>
 #include <asm/unistd.h>
 
+/*
+ * Should the kernel map a VDSO page into processes and pass its
+ * address down to glibc upon exec()?
+ */
+unsigned int __read_mostly vdso_enabled = 1;
+
+EXPORT_SYMBOL_GPL(vdso_enabled);
+
+static int __init vdso_setup(char *s)
+{
+	vdso_enabled = simple_strtoul(s, NULL, 0);
+
+	return 1;
+}
+
+__setup("vdso=", vdso_setup);
+
 extern asmlinkage void sysenter_entry(void);
 
 void enable_sep_cpu(void)
@@ -45,23 +66,120 @@
  */
 extern const char vsyscall_int80_start, vsyscall_int80_end;
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
+static void *syscall_page;
 
 int __init sysenter_setup(void)
 {
-	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
+	syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
 
-	__set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
+#ifdef CONFIG_COMPAT_VDSO
+	__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_READONLY);
+	printk("Compat vDSO mapped to %08lx.\n", __fix_to_virt(FIX_VDSO));
+#else
+	/*
+	 * In the non-compat case the ELF coredumping code needs the fixmap:
+	 */
+	__set_fixmap(FIX_VDSO, __pa(syscall_page), PAGE_KERNEL_RO);
+#endif
 
 	if (!boot_cpu_has(X86_FEATURE_SEP)) {
-		memcpy(page,
+		memcpy(syscall_page,
 		       &vsyscall_int80_start,
 		       &vsyscall_int80_end - &vsyscall_int80_start);
 		return 0;
 	}
 
-	memcpy(page,
+	memcpy(syscall_page,
 	       &vsyscall_sysenter_start,
 	       &vsyscall_sysenter_end - &vsyscall_sysenter_start);
 
 	return 0;
 }
+
+static struct page *syscall_nopage(struct vm_area_struct *vma,
+				unsigned long adr, int *type)
+{
+	struct page *p = virt_to_page(adr - vma->vm_start + syscall_page);
+	get_page(p);
+	return p;
+}
+
+/* Prevent VMA merging */
+static void syscall_vma_close(struct vm_area_struct *vma)
+{
+}
+
+static struct vm_operations_struct syscall_vm_ops = {
+	.close = syscall_vma_close,
+	.nopage = syscall_nopage,
+};
+
+/* Defined in vsyscall-sysenter.S */
+extern void SYSENTER_RETURN;
+
+/* Setup a VMA at program startup for the vsyscall page */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long addr;
+	int ret;
+
+	down_write(&mm->mmap_sem);
+	addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+	if (IS_ERR_VALUE(addr)) {
+		ret = addr;
+		goto up_fail;
+	}
+
+	vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+	if (!vma) {
+		ret = -ENOMEM;
+		goto up_fail;
+	}
+
+	vma->vm_start = addr;
+	vma->vm_end = addr + PAGE_SIZE;
+	/* MAYWRITE to allow gdb to COW and set breakpoints */
+	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+	vma->vm_flags |= mm->def_flags;
+	vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+	vma->vm_ops = &syscall_vm_ops;
+	vma->vm_mm = mm;
+
+	ret = insert_vm_struct(mm, vma);
+	if (unlikely(ret)) {
+		kmem_cache_free(vm_area_cachep, vma);
+		goto up_fail;
+	}
+
+	current->mm->context.vdso = (void *)addr;
+	current_thread_info()->sysenter_return =
+				    (void *)VDSO_SYM(&SYSENTER_RETURN);
+	mm->total_vm++;
+up_fail:
+	up_write(&mm->mmap_sem);
+	return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+		return "[vdso]";
+	return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+{
+	return NULL;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long addr)
+{
+	return 0;
+}
+
+int in_gate_area_no_task(unsigned long addr)
+{
+	return 0;
+}
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index 9d30747..5f43d04 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -82,13 +82,6 @@
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
-#include <asm/i8253.h>
-
-DEFINE_SPINLOCK(i8253_lock);
-EXPORT_SYMBOL(i8253_lock);
-
-struct timer_opts *cur_timer __read_mostly = &timer_none;
-
 /*
  * This is a special lock that is owned by the CPU and holds the index
  * register we are working with.  It is required for NMI access to the
@@ -118,99 +111,19 @@
 }
 EXPORT_SYMBOL(rtc_cmos_write);
 
-/*
- * This version of gettimeofday has microsecond resolution
- * and better than microsecond precision on fast x86 machines with TSC.
- */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long seq;
-	unsigned long usec, sec;
-	unsigned long max_ntp_tick;
-
-	do {
-		unsigned long lost;
-
-		seq = read_seqbegin(&xtime_lock);
-
-		usec = cur_timer->get_offset();
-		lost = jiffies - wall_jiffies;
-
-		/*
-		 * If time_adjust is negative then NTP is slowing the clock
-		 * so make sure not to go into next possible interval.
-		 * Better to lose some accuracy than have time go backwards..
-		 */
-		if (unlikely(time_adjust < 0)) {
-			max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj;
-			usec = min(usec, max_ntp_tick);
-
-			if (lost)
-				usec += lost * max_ntp_tick;
-		}
-		else if (unlikely(lost))
-			usec += lost * (USEC_PER_SEC / HZ);
-
-		sec = xtime.tv_sec;
-		usec += (xtime.tv_nsec / 1000);
-	} while (read_seqretry(&xtime_lock, seq));
-
-	while (usec >= 1000000) {
-		usec -= 1000000;
-		sec++;
-	}
-
-	tv->tv_sec = sec;
-	tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
-{
-	time_t wtm_sec, sec = tv->tv_sec;
-	long wtm_nsec, nsec = tv->tv_nsec;
-
-	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-		return -EINVAL;
-
-	write_seqlock_irq(&xtime_lock);
-	/*
-	 * This is revolting. We need to set "xtime" correctly. However, the
-	 * value in this location is the value at the most recent update of
-	 * wall time.  Discover what correction gettimeofday() would have
-	 * made, and then undo it!
-	 */
-	nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
-	nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
-
-	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
-
-	set_normalized_timespec(&xtime, sec, nsec);
-	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
-
-	ntp_clear();
-	write_sequnlock_irq(&xtime_lock);
-	clock_was_set();
-	return 0;
-}
-
-EXPORT_SYMBOL(do_settimeofday);
-
 static int set_rtc_mmss(unsigned long nowtime)
 {
 	int retval;
-
-	WARN_ON(irqs_disabled());
+	unsigned long flags;
 
 	/* gets recalled with irq locally disabled */
-	spin_lock_irq(&rtc_lock);
+	/* XXX - does irqsave resolve this? -johnstul */
+	spin_lock_irqsave(&rtc_lock, flags);
 	if (efi_enabled)
 		retval = efi_set_rtc_mmss(nowtime);
 	else
 		retval = mach_set_rtc_mmss(nowtime);
-	spin_unlock_irq(&rtc_lock);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return retval;
 }
@@ -218,16 +131,6 @@
 
 int timer_ack;
 
-/* monotonic_clock(): returns # of nanoseconds passed since time_init()
- *		Note: This function is required to return accurate
- *		time even in the absence of multiple timer ticks.
- */
-unsigned long long monotonic_clock(void)
-{
-	return cur_timer->monotonic_clock();
-}
-EXPORT_SYMBOL(monotonic_clock);
-
 #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
 unsigned long profile_pc(struct pt_regs *regs)
 {
@@ -242,11 +145,21 @@
 #endif
 
 /*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * This is the same as the above, except we _also_ save the current
+ * Time Stamp Counter value at the time of the timer interrupt, so that
+ * we later on can estimate the time of day more exactly.
  */
-static inline void do_timer_interrupt(int irq, struct pt_regs *regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	/*
+	 * Here we are in the timer irq handler. We just have irqs locally
+	 * disabled but we don't know if the timer_bh is running on the other
+	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
+	 * the irq version of write_lock because as just said we have irq
+	 * locally disabled. -arca
+	 */
+	write_seqlock(&xtime_lock);
+
 #ifdef CONFIG_X86_IO_APIC
 	if (timer_ack) {
 		/*
@@ -279,27 +192,6 @@
 		irq = inb_p( 0x61 );	/* read the current state */
 		outb_p( irq|0x80, 0x61 );	/* reset the IRQ */
 	}
-}
-
-/*
- * This is the same as the above, except we _also_ save the current
- * Time Stamp Counter value at the time of the timer interrupt, so that
- * we later on can estimate the time of day more exactly.
- */
-irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	/*
-	 * Here we are in the timer irq handler. We just have irqs locally
-	 * disabled but we don't know if the timer_bh is running on the other
-	 * CPU. We need to avoid to SMP race with it. NOTE: we don' t need
-	 * the irq version of write_lock because as just said we have irq
-	 * locally disabled. -arca
-	 */
-	write_seqlock(&xtime_lock);
-
-	cur_timer->mark_offset();
- 
-	do_timer_interrupt(irq, regs);
 
 	write_sequnlock(&xtime_lock);
 
@@ -380,7 +272,6 @@
 
 static long clock_cmos_diff, sleep_start;
 
-static struct timer_opts *last_timer;
 static int timer_suspend(struct sys_device *dev, pm_message_t state)
 {
 	/*
@@ -389,10 +280,6 @@
 	clock_cmos_diff = -get_cmos_time();
 	clock_cmos_diff += get_seconds();
 	sleep_start = get_cmos_time();
-	last_timer = cur_timer;
-	cur_timer = &timer_none;
-	if (last_timer->suspend)
-		last_timer->suspend(state);
 	return 0;
 }
 
@@ -415,10 +302,6 @@
 	jiffies_64 += sleep_length;
 	wall_jiffies += sleep_length;
 	write_sequnlock_irqrestore(&xtime_lock, flags);
-	if (last_timer->resume)
-		last_timer->resume();
-	cur_timer = last_timer;
-	last_timer = NULL;
 	touch_softlockup_watchdog();
 	return 0;
 }
@@ -460,9 +343,6 @@
 		printk("Using HPET for base-timer\n");
 	}
 
-	cur_timer = select_timer();
-	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
-
 	time_init_hook();
 }
 #endif
@@ -484,8 +364,5 @@
 	set_normalized_timespec(&wall_to_monotonic,
 		-xtime.tv_sec, -xtime.tv_nsec);
 
-	cur_timer = select_timer();
-	printk(KERN_INFO "Using %s for high-res timesource\n",cur_timer->name);
-
 	time_init_hook();
 }
diff --git a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile
deleted file mode 100644
index 8fa12be..0000000
--- a/arch/i386/kernel/timers/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for x86 timers
-#
-
-obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o common.o
-
-obj-$(CONFIG_X86_CYCLONE_TIMER)	+= timer_cyclone.o
-obj-$(CONFIG_HPET_TIMER)	+= timer_hpet.o
-obj-$(CONFIG_X86_PM_TIMER)	+= timer_pm.o
diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c
deleted file mode 100644
index 8163fe0..0000000
--- a/arch/i386/kernel/timers/common.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- *	Common functions used across the timers go here
- */
-
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <linux/errno.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/timer.h>
-#include <asm/hpet.h>
-
-#include "mach_timer.h"
-
-/* ------ Calibrate the TSC -------
- * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
- * Too much 64-bit arithmetic here to do this cleanly in C, and for
- * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
- * output busy loop as low as possible. We avoid reading the CTC registers
- * directly because of the awkward 8-bit access mechanism of the 82C54
- * device.
- */
-
-#define CALIBRATE_TIME	(5 * 1000020/HZ)
-
-unsigned long calibrate_tsc(void)
-{
-	mach_prepare_counter();
-
-	{
-		unsigned long startlow, starthigh;
-		unsigned long endlow, endhigh;
-		unsigned long count;
-
-		rdtsc(startlow,starthigh);
-		mach_countup(&count);
-		rdtsc(endlow,endhigh);
-
-
-		/* Error: ECTCNEVERSET */
-		if (count <= 1)
-			goto bad_ctc;
-
-		/* 64-bit subtract - gcc just messes up with long longs */
-		__asm__("subl %2,%0\n\t"
-			"sbbl %3,%1"
-			:"=a" (endlow), "=d" (endhigh)
-			:"g" (startlow), "g" (starthigh),
-			 "0" (endlow), "1" (endhigh));
-
-		/* Error: ECPUTOOFAST */
-		if (endhigh)
-			goto bad_ctc;
-
-		/* Error: ECPUTOOSLOW */
-		if (endlow <= CALIBRATE_TIME)
-			goto bad_ctc;
-
-		__asm__("divl %2"
-			:"=a" (endlow), "=d" (endhigh)
-			:"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
-
-		return endlow;
-	}
-
-	/*
-	 * The CTC wasn't reliable: we got a hit on the very first read,
-	 * or the CPU was so fast/slow that the quotient wouldn't fit in
-	 * 32 bits..
-	 */
-bad_ctc:
-	return 0;
-}
-
-#ifdef CONFIG_HPET_TIMER
-/* ------ Calibrate the TSC using HPET -------
- * Return 2^32 * (1 / (TSC clocks per usec)) for getting the CPU freq.
- * Second output is parameter 1 (when non NULL)
- * Set 2^32 * (1 / (tsc per HPET clk)) for delay_hpet().
- * calibrate_tsc() calibrates the processor TSC by comparing
- * it to the HPET timer of known frequency.
- * Too much 64-bit arithmetic here to do this cleanly in C
- */
-#define CALIBRATE_CNT_HPET 	(5 * hpet_tick)
-#define CALIBRATE_TIME_HPET 	(5 * KERNEL_TICK_USEC)
-
-unsigned long __devinit calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr)
-{
-	unsigned long tsc_startlow, tsc_starthigh;
-	unsigned long tsc_endlow, tsc_endhigh;
-	unsigned long hpet_start, hpet_end;
-	unsigned long result, remain;
-
-	hpet_start = hpet_readl(HPET_COUNTER);
-	rdtsc(tsc_startlow, tsc_starthigh);
-	do {
-		hpet_end = hpet_readl(HPET_COUNTER);
-	} while ((hpet_end - hpet_start) < CALIBRATE_CNT_HPET);
-	rdtsc(tsc_endlow, tsc_endhigh);
-
-	/* 64-bit subtract - gcc just messes up with long longs */
-	__asm__("subl %2,%0\n\t"
-		"sbbl %3,%1"
-		:"=a" (tsc_endlow), "=d" (tsc_endhigh)
-		:"g" (tsc_startlow), "g" (tsc_starthigh),
-		 "0" (tsc_endlow), "1" (tsc_endhigh));
-
-	/* Error: ECPUTOOFAST */
-	if (tsc_endhigh)
-		goto bad_calibration;
-
-	/* Error: ECPUTOOSLOW */
-	if (tsc_endlow <= CALIBRATE_TIME_HPET)
-		goto bad_calibration;
-
-	ASM_DIV64_REG(result, remain, tsc_endlow, 0, CALIBRATE_TIME_HPET);
-	if (remain > (tsc_endlow >> 1))
-		result++; /* rounding the result */
-
-	if (tsc_hpet_quotient_ptr) {
-		unsigned long tsc_hpet_quotient;
-
-		ASM_DIV64_REG(tsc_hpet_quotient, remain, tsc_endlow, 0,
-			CALIBRATE_CNT_HPET);
-		if (remain > (tsc_endlow >> 1))
-			tsc_hpet_quotient++; /* rounding the result */
-		*tsc_hpet_quotient_ptr = tsc_hpet_quotient;
-	}
-
-	return result;
-bad_calibration:
-	/*
-	 * the CPU was so fast/slow that the quotient wouldn't fit in
-	 * 32 bits..
-	 */
-	return 0;
-}
-#endif
-
-
-unsigned long read_timer_tsc(void)
-{
-	unsigned long retval;
-	rdtscl(retval);
-	return retval;
-}
-
-
-/* calculate cpu_khz */
-void init_cpu_khz(void)
-{
-	if (cpu_has_tsc) {
-		unsigned long tsc_quotient = calibrate_tsc();
-		if (tsc_quotient) {
-			/* report CPU clock rate in Hz.
-			 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
-			 * clock/second. Our precision is about 100 ppm.
-			 */
-			{	unsigned long eax=0, edx=1000;
-				__asm__("divl %2"
-		       		:"=a" (cpu_khz), "=d" (edx)
-        	       		:"r" (tsc_quotient),
-	                	"0" (eax), "1" (edx));
-				printk("Detected %u.%03u MHz processor.\n",
-					cpu_khz / 1000, cpu_khz % 1000);
-			}
-		}
-	}
-}
-
diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
deleted file mode 100644
index 7e39ed8..0000000
--- a/arch/i386/kernel/timers/timer.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <asm/timer.h>
-
-#ifdef CONFIG_HPET_TIMER
-/*
- * HPET memory read is slower than tsc reads, but is more dependable as it
- * always runs at constant frequency and reduces complexity due to
- * cpufreq. So, we prefer HPET timer to tsc based one. Also, we cannot use
- * timer_pit when HPET is active. So, we default to timer_tsc.
- */
-#endif
-/* list of timers, ordered by preference, NULL terminated */
-static struct init_timer_opts* __initdata timers[] = {
-#ifdef CONFIG_X86_CYCLONE_TIMER
-	&timer_cyclone_init,
-#endif
-#ifdef CONFIG_HPET_TIMER
-	&timer_hpet_init,
-#endif
-#ifdef CONFIG_X86_PM_TIMER
-	&timer_pmtmr_init,
-#endif
-	&timer_tsc_init,
-	&timer_pit_init,
-	NULL,
-};
-
-static char clock_override[10] __initdata;
-
-static int __init clock_setup(char* str)
-{
-	if (str)
-		strlcpy(clock_override, str, sizeof(clock_override));
-	return 1;
-}
-__setup("clock=", clock_setup);
-
-
-/* The chosen timesource has been found to be bad.
- * Fall back to a known good timesource (the PIT)
- */
-void clock_fallback(void)
-{
-	cur_timer = &timer_pit;
-}
-
-/* iterates through the list of timers, returning the first 
- * one that initializes successfully.
- */
-struct timer_opts* __init select_timer(void)
-{
-	int i = 0;
-	
-	/* find most preferred working timer */
-	while (timers[i]) {
-		if (timers[i]->init)
-			if (timers[i]->init(clock_override) == 0)
-				return timers[i]->opts;
-		++i;
-	}
-		
-	panic("select_timer: Cannot find a suitable timer\n");
-	return NULL;
-}
-
-int read_current_timer(unsigned long *timer_val)
-{
-	if (cur_timer->read_timer) {
-		*timer_val = cur_timer->read_timer();
-		return 0;
-	}
-	return -1;
-}
diff --git a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
deleted file mode 100644
index 13892a6..0000000
--- a/arch/i386/kernel/timers/timer_cyclone.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*	Cyclone-timer: 
- *		This code implements timer_ops for the cyclone counter found
- *		on IBM x440, x360, and other Summit based systems.
- *
- *	Copyright (C) 2002 IBM, John Stultz (johnstul@us.ibm.com)
- */
-
-
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/jiffies.h>
-
-#include <asm/timer.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/fixmap.h>
-#include <asm/i8253.h>
-
-#include "io_ports.h"
-
-/* Number of usecs that the last interrupt was delayed */
-static int delay_at_last_interrupt;
-
-#define CYCLONE_CBAR_ADDR 0xFEB00CD0
-#define CYCLONE_PMCC_OFFSET 0x51A0
-#define CYCLONE_MPMC_OFFSET 0x51D0
-#define CYCLONE_MPCS_OFFSET 0x51A8
-#define CYCLONE_TIMER_FREQ 100000000
-#define CYCLONE_TIMER_MASK (((u64)1<<40)-1) /* 40 bit mask */
-int use_cyclone = 0;
-
-static u32* volatile cyclone_timer;	/* Cyclone MPMC0 register */
-static u32 last_cyclone_low;
-static u32 last_cyclone_high;
-static unsigned long long monotonic_base;
-static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
-
-/* helper macro to atomically read both cyclone counter registers */
-#define read_cyclone_counter(low,high) \
-	do{ \
-		high = cyclone_timer[1]; low = cyclone_timer[0]; \
-	} while (high != cyclone_timer[1]);
-
-
-static void mark_offset_cyclone(void)
-{
-	unsigned long lost, delay;
-	unsigned long delta = last_cyclone_low;
-	int count;
-	unsigned long long this_offset, last_offset;
-
-	write_seqlock(&monotonic_lock);
-	last_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low;
-	
-	spin_lock(&i8253_lock);
-	read_cyclone_counter(last_cyclone_low,last_cyclone_high);
-
-	/* read values for delay_at_last_interrupt */
-	outb_p(0x00, 0x43);     /* latch the count ASAP */
-
-	count = inb_p(0x40);    /* read the latched count */
-	count |= inb(0x40) << 8;
-
-	/*
-	 * VIA686a test code... reset the latch if count > max + 1
-	 * from timer_pit.c - cjb
-	 */
-	if (count > LATCH) {
-		outb_p(0x34, PIT_MODE);
-		outb_p(LATCH & 0xff, PIT_CH0);
-		outb(LATCH >> 8, PIT_CH0);
-		count = LATCH - 1;
-	}
-	spin_unlock(&i8253_lock);
-
-	/* lost tick compensation */
-	delta = last_cyclone_low - delta;	
-	delta /= (CYCLONE_TIMER_FREQ/1000000);
-	delta += delay_at_last_interrupt;
-	lost = delta/(1000000/HZ);
-	delay = delta%(1000000/HZ);
-	if (lost >= 2)
-		jiffies_64 += lost-1;
-	
-	/* update the monotonic base value */
-	this_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low;
-	monotonic_base += (this_offset - last_offset) & CYCLONE_TIMER_MASK;
-	write_sequnlock(&monotonic_lock);
-
-	/* calculate delay_at_last_interrupt */
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
-
-
-	/* catch corner case where tick rollover occured 
-	 * between cyclone and pit reads (as noted when 
-	 * usec delta is > 90% # of usecs/tick)
-	 */
-	if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
-		jiffies_64++;
-}
-
-static unsigned long get_offset_cyclone(void)
-{
-	u32 offset;
-
-	if(!cyclone_timer)
-		return delay_at_last_interrupt;
-
-	/* Read the cyclone timer */
-	offset = cyclone_timer[0];
-
-	/* .. relative to previous jiffy */
-	offset = offset - last_cyclone_low;
-
-	/* convert cyclone ticks to microseconds */	
-	/* XXX slow, can we speed this up? */
-	offset = offset/(CYCLONE_TIMER_FREQ/1000000);
-
-	/* our adjusted time offset in microseconds */
-	return delay_at_last_interrupt + offset;
-}
-
-static unsigned long long monotonic_clock_cyclone(void)
-{
-	u32 now_low, now_high;
-	unsigned long long last_offset, this_offset, base;
-	unsigned long long ret;
-	unsigned seq;
-
-	/* atomically read monotonic base & last_offset */
-	do {
-		seq = read_seqbegin(&monotonic_lock);
-		last_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low;
-		base = monotonic_base;
-	} while (read_seqretry(&monotonic_lock, seq));
-
-
-	/* Read the cyclone counter */
-	read_cyclone_counter(now_low,now_high);
-	this_offset = ((unsigned long long)now_high<<32)|now_low;
-
-	/* convert to nanoseconds */
-	ret = base + ((this_offset - last_offset)&CYCLONE_TIMER_MASK);
-	return ret * (1000000000 / CYCLONE_TIMER_FREQ);
-}
-
-static int __init init_cyclone(char* override)
-{
-	u32* reg;	
-	u32 base;		/* saved cyclone base address */
-	u32 pageaddr;	/* page that contains cyclone_timer register */
-	u32 offset;		/* offset from pageaddr to cyclone_timer register */
-	int i;
-	
-	/* check clock override */
-	if (override[0] && strncmp(override,"cyclone",7))
-			return -ENODEV;
-
-	/*make sure we're on a summit box*/
-	if(!use_cyclone) return -ENODEV; 
-	
-	printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
-
-	/* find base address */
-	pageaddr = (CYCLONE_CBAR_ADDR)&PAGE_MASK;
-	offset = (CYCLONE_CBAR_ADDR)&(~PAGE_MASK);
-	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
-	reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
-	if(!reg){
-		printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
-		return -ENODEV;
-	}
-	base = *reg;	
-	if(!base){
-		printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
-		return -ENODEV;
-	}
-	
-	/* setup PMCC */
-	pageaddr = (base + CYCLONE_PMCC_OFFSET)&PAGE_MASK;
-	offset = (base + CYCLONE_PMCC_OFFSET)&(~PAGE_MASK);
-	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
-	reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
-	if(!reg){
-		printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
-		return -ENODEV;
-	}
-	reg[0] = 0x00000001;
-
-	/* setup MPCS */
-	pageaddr = (base + CYCLONE_MPCS_OFFSET)&PAGE_MASK;
-	offset = (base + CYCLONE_MPCS_OFFSET)&(~PAGE_MASK);
-	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
-	reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
-	if(!reg){
-		printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
-		return -ENODEV;
-	}
-	reg[0] = 0x00000001;
-
-	/* map in cyclone_timer */
-	pageaddr = (base + CYCLONE_MPMC_OFFSET)&PAGE_MASK;
-	offset = (base + CYCLONE_MPMC_OFFSET)&(~PAGE_MASK);
-	set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
-	cyclone_timer = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
-	if(!cyclone_timer){
-		printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
-		return -ENODEV;
-	}
-
-	/*quick test to make sure its ticking*/
-	for(i=0; i<3; i++){
-		u32 old = cyclone_timer[0];
-		int stall = 100;
-		while(stall--) barrier();
-		if(cyclone_timer[0] == old){
-			printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
-			cyclone_timer = 0;
-			return -ENODEV;
-		}
-	}
-
-	init_cpu_khz();
-
-	/* Everything looks good! */
-	return 0;
-}
-
-
-static void delay_cyclone(unsigned long loops)
-{
-	unsigned long bclock, now;
-	if(!cyclone_timer)
-		return;
-	bclock = cyclone_timer[0];
-	do {
-		rep_nop();
-		now = cyclone_timer[0];
-	} while ((now-bclock) < loops);
-}
-/************************************************************/
-
-/* cyclone timer_opts struct */
-static struct timer_opts timer_cyclone = {
-	.name = "cyclone",
-	.mark_offset = mark_offset_cyclone, 
-	.get_offset = get_offset_cyclone,
-	.monotonic_clock =	monotonic_clock_cyclone,
-	.delay = delay_cyclone,
-};
-
-struct init_timer_opts __initdata timer_cyclone_init = {
-	.init = init_cyclone,
-	.opts = &timer_cyclone,
-};
diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
deleted file mode 100644
index 17a6fe7..0000000
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * This code largely moved from arch/i386/kernel/time.c.
- * See comments there for proper credits.
- */
-
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/jiffies.h>
-
-#include <asm/timer.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-
-#include "io_ports.h"
-#include "mach_timer.h"
-#include <asm/hpet.h>
-
-static unsigned long hpet_usec_quotient __read_mostly;	/* convert hpet clks to usec */
-static unsigned long tsc_hpet_quotient __read_mostly;	/* convert tsc to hpet clks */
-static unsigned long hpet_last; 	/* hpet counter value at last tick*/
-static unsigned long last_tsc_low;	/* lsb 32 bits of Time Stamp Counter */
-static unsigned long last_tsc_high; 	/* msb 32 bits of Time Stamp Counter */
-static unsigned long long monotonic_base;
-static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
-
-/* convert from cycles(64bits) => nanoseconds (64bits)
- *  basic equation:
- *		ns = cycles / (freq / ns_per_sec)
- *		ns = cycles * (ns_per_sec / freq)
- *		ns = cycles * (10^9 / (cpu_khz * 10^3))
- *		ns = cycles * (10^6 / cpu_khz)
- *
- *	Then we use scaling math (suggested by george@mvista.com) to get:
- *		ns = cycles * (10^6 * SC / cpu_khz) / SC
- *		ns = cycles * cyc2ns_scale / SC
- *
- *	And since SC is a constant power of two, we can convert the div
- *  into a shift.
- *
- *  We can use khz divisor instead of mhz to keep a better percision, since
- *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
- *  (mathieu.desnoyers@polymtl.ca)
- *
- *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
- */
-static unsigned long cyc2ns_scale __read_mostly;
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
-	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
-	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
-}
-
-static unsigned long long monotonic_clock_hpet(void)
-{
-	unsigned long long last_offset, this_offset, base;
-	unsigned seq;
-
-	/* atomically read monotonic base & last_offset */
-	do {
-		seq = read_seqbegin(&monotonic_lock);
-		last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-		base = monotonic_base;
-	} while (read_seqretry(&monotonic_lock, seq));
-
-	/* Read the Time Stamp Counter */
-	rdtscll(this_offset);
-
-	/* return the value in ns */
-	return base + cycles_2_ns(this_offset - last_offset);
-}
-
-static unsigned long get_offset_hpet(void)
-{
-	register unsigned long eax, edx;
-
-	eax = hpet_readl(HPET_COUNTER);
-	eax -= hpet_last;	/* hpet delta */
-	eax = min(hpet_tick, eax);
-	/*
-         * Time offset = (hpet delta) * ( usecs per HPET clock )
-	 *             = (hpet delta) * ( usecs per tick / HPET clocks per tick)
-	 *             = (hpet delta) * ( hpet_usec_quotient ) / (2^32)
-	 *
-	 * Where,
-	 * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick
-	 *
-	 * Using a mull instead of a divl saves some cycles in critical path.
-         */
-	ASM_MUL64_REG(eax, edx, hpet_usec_quotient, eax);
-
-	/* our adjusted time offset in microseconds */
-	return edx;
-}
-
-static void mark_offset_hpet(void)
-{
-	unsigned long long this_offset, last_offset;
-	unsigned long offset;
-
-	write_seqlock(&monotonic_lock);
-	last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-	rdtsc(last_tsc_low, last_tsc_high);
-
-	if (hpet_use_timer)
-		offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-	else
-		offset = hpet_readl(HPET_COUNTER);
-	if (unlikely(((offset - hpet_last) >= (2*hpet_tick)) && (hpet_last != 0))) {
-		int lost_ticks = ((offset - hpet_last) / hpet_tick) - 1;
-		jiffies_64 += lost_ticks;
-	}
-	hpet_last = offset;
-
-	/* update the monotonic base value */
-	this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-	monotonic_base += cycles_2_ns(this_offset - last_offset);
-	write_sequnlock(&monotonic_lock);
-}
-
-static void delay_hpet(unsigned long loops)
-{
-	unsigned long hpet_start, hpet_end;
-	unsigned long eax;
-
-	/* loops is the number of cpu cycles. Convert it to hpet clocks */
-	ASM_MUL64_REG(eax, loops, tsc_hpet_quotient, loops);
-
-	hpet_start = hpet_readl(HPET_COUNTER);
-	do {
-		rep_nop();
-		hpet_end = hpet_readl(HPET_COUNTER);
-	} while ((hpet_end - hpet_start) < (loops));
-}
-
-static struct timer_opts timer_hpet;
-
-static int __init init_hpet(char* override)
-{
-	unsigned long result, remain;
-
-	/* check clock override */
-	if (override[0] && strncmp(override,"hpet",4))
-		return -ENODEV;
-
-	if (!is_hpet_enabled())
-		return -ENODEV;
-
-	printk("Using HPET for gettimeofday\n");
-	if (cpu_has_tsc) {
-		unsigned long tsc_quotient = calibrate_tsc_hpet(&tsc_hpet_quotient);
-		if (tsc_quotient) {
-			/* report CPU clock rate in Hz.
-			 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
-			 * clock/second. Our precision is about 100 ppm.
-			 */
-			{	unsigned long eax=0, edx=1000;
-				ASM_DIV64_REG(cpu_khz, edx, tsc_quotient,
-						eax, edx);
-				printk("Detected %u.%03u MHz processor.\n",
-					cpu_khz / 1000, cpu_khz % 1000);
-			}
-			set_cyc2ns_scale(cpu_khz);
-		}
-		/* set this only when cpu_has_tsc */
-		timer_hpet.read_timer = read_timer_tsc;
-	}
-
-	/*
-	 * Math to calculate hpet to usec multiplier
-	 * Look for the comments at get_offset_hpet()
-	 */
-	ASM_DIV64_REG(result, remain, hpet_tick, 0, KERNEL_TICK_USEC);
-	if (remain > (hpet_tick >> 1))
-		result++; /* rounding the result */
-	hpet_usec_quotient = result;
-
-	return 0;
-}
-
-static int hpet_resume(void)
-{
-	write_seqlock(&monotonic_lock);
-	/* Assume this is the last mark offset time */
-	rdtsc(last_tsc_low, last_tsc_high);
-
-	if (hpet_use_timer)
-		hpet_last = hpet_readl(HPET_T0_CMP) - hpet_tick;
-	else
-		hpet_last = hpet_readl(HPET_COUNTER);
-	write_sequnlock(&monotonic_lock);
-	return 0;
-}
-/************************************************************/
-
-/* tsc timer_opts struct */
-static struct timer_opts timer_hpet __read_mostly = {
-	.name = 		"hpet",
-	.mark_offset =		mark_offset_hpet,
-	.get_offset =		get_offset_hpet,
-	.monotonic_clock =	monotonic_clock_hpet,
-	.delay = 		delay_hpet,
-	.resume	=		hpet_resume,
-};
-
-struct init_timer_opts __initdata timer_hpet_init = {
-	.init =	init_hpet,
-	.opts = &timer_hpet,
-};
diff --git a/arch/i386/kernel/timers/timer_none.c b/arch/i386/kernel/timers/timer_none.c
deleted file mode 100644
index 4ea2f41..0000000
--- a/arch/i386/kernel/timers/timer_none.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <linux/init.h>
-#include <asm/timer.h>
-
-static void mark_offset_none(void)
-{
-	/* nothing needed */
-}
-
-static unsigned long get_offset_none(void)
-{
-	return 0;
-}
-
-static unsigned long long monotonic_clock_none(void)
-{
-	return 0;
-}
-
-static void delay_none(unsigned long loops)
-{
-	int d0;
-	__asm__ __volatile__(
-		"\tjmp 1f\n"
-		".align 16\n"
-		"1:\tjmp 2f\n"
-		".align 16\n"
-		"2:\tdecl %0\n\tjns 2b"
-		:"=&a" (d0)
-		:"0" (loops));
-}
-
-/* none timer_opts struct */
-struct timer_opts timer_none = {
-	.name = 	"none",
-	.mark_offset =	mark_offset_none, 
-	.get_offset =	get_offset_none,
-	.monotonic_clock =	monotonic_clock_none,
-	.delay = delay_none,
-};
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
deleted file mode 100644
index b9b6bd5..0000000
--- a/arch/i386/kernel/timers/timer_pit.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * This code largely moved from arch/i386/kernel/time.c.
- * See comments there for proper credits.
- */
-
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/sysdev.h>
-#include <linux/timex.h>
-#include <asm/delay.h>
-#include <asm/mpspec.h>
-#include <asm/timer.h>
-#include <asm/smp.h>
-#include <asm/io.h>
-#include <asm/arch_hooks.h>
-#include <asm/i8253.h>
-
-#include "do_timer.h"
-#include "io_ports.h"
-
-static int count_p; /* counter in get_offset_pit() */
-
-static int __init init_pit(char* override)
-{
- 	/* check clock override */
- 	if (override[0] && strncmp(override,"pit",3))
- 		printk(KERN_ERR "Warning: clock= override failed. Defaulting "
-				"to PIT\n");
- 	init_cpu_khz();
-	count_p = LATCH;
-	return 0;
-}
-
-static void mark_offset_pit(void)
-{
-	/* nothing needed */
-}
-
-static unsigned long long monotonic_clock_pit(void)
-{
-	return 0;
-}
-
-static void delay_pit(unsigned long loops)
-{
-	int d0;
-	__asm__ __volatile__(
-		"\tjmp 1f\n"
-		".align 16\n"
-		"1:\tjmp 2f\n"
-		".align 16\n"
-		"2:\tdecl %0\n\tjns 2b"
-		:"=&a" (d0)
-		:"0" (loops));
-}
-
-
-/* This function must be called with xtime_lock held.
- * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
- * 
- * However, the pc-audio speaker driver changes the divisor so that
- * it gets interrupted rather more often - it loads 64 into the
- * counter rather than 11932! This has an adverse impact on
- * do_gettimeoffset() -- it stops working! What is also not
- * good is that the interval that our timer function gets called
- * is no longer 10.0002 ms, but 9.9767 ms. To get around this
- * would require using a different timing source. Maybe someone
- * could use the RTC - I know that this can interrupt at frequencies
- * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
- * it so that at startup, the timer code in sched.c would select
- * using either the RTC or the 8253 timer. The decision would be
- * based on whether there was any other device around that needed
- * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
- * and then do some jiggery to have a version of do_timer that 
- * advanced the clock by 1/1024 s. Every time that reached over 1/100
- * of a second, then do all the old code. If the time was kept correct
- * then do_gettimeoffset could just return 0 - there is no low order
- * divider that can be accessed.
- *
- * Ideally, you would be able to use the RTC for the speaker driver,
- * but it appears that the speaker driver really needs interrupt more
- * often than every 120 us or so.
- *
- * Anyway, this needs more thought....		pjsg (1993-08-28)
- * 
- * If you are really that interested, you should be reading
- * comp.protocols.time.ntp!
- */
-
-static unsigned long get_offset_pit(void)
-{
-	int count;
-	unsigned long flags;
-	static unsigned long jiffies_p = 0;
-
-	/*
-	 * cache volatile jiffies temporarily; we have xtime_lock. 
-	 */
-	unsigned long jiffies_t;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-	/* timer count may underflow right here */
-	outb_p(0x00, PIT_MODE);	/* latch the count ASAP */
-
-	count = inb_p(PIT_CH0);	/* read the latched count */
-
-	/*
-	 * We do this guaranteed double memory access instead of a _p 
-	 * postfix in the previous port access. Wheee, hackady hack
-	 */
- 	jiffies_t = jiffies;
-
-	count |= inb_p(PIT_CH0) << 8;
-	
-        /* VIA686a test code... reset the latch if count > max + 1 */
-        if (count > LATCH) {
-                outb_p(0x34, PIT_MODE);
-                outb_p(LATCH & 0xff, PIT_CH0);
-                outb(LATCH >> 8, PIT_CH0);
-                count = LATCH - 1;
-        }
-	
-	/*
-	 * avoiding timer inconsistencies (they are rare, but they happen)...
-	 * there are two kinds of problems that must be avoided here:
-	 *  1. the timer counter underflows
-	 *  2. hardware problem with the timer, not giving us continuous time,
-	 *     the counter does small "jumps" upwards on some Pentium systems,
-	 *     (see c't 95/10 page 335 for Neptun bug.)
-	 */
-
-	if( jiffies_t == jiffies_p ) {
-		if( count > count_p ) {
-			/* the nutcase */
-			count = do_timer_overflow(count);
-		}
-	} else
-		jiffies_p = jiffies_t;
-
-	count_p = count;
-
-	spin_unlock_irqrestore(&i8253_lock, flags);
-
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	count = (count + LATCH/2) / LATCH;
-
-	return count;
-}
-
-
-/* tsc timer_opts struct */
-struct timer_opts timer_pit = {
-	.name = "pit",
-	.mark_offset = mark_offset_pit, 
-	.get_offset = get_offset_pit,
-	.monotonic_clock = monotonic_clock_pit,
-	.delay = delay_pit,
-};
-
-struct init_timer_opts __initdata timer_pit_init = {
-	.init = init_pit, 
-	.opts = &timer_pit,
-};
-
-void setup_pit_timer(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&i8253_lock, flags);
-	outb_p(0x34,PIT_MODE);		/* binary, mode 2, LSB/MSB, ch 0 */
-	udelay(10);
-	outb_p(LATCH & 0xff , PIT_CH0);	/* LSB */
-	udelay(10);
-	outb(LATCH >> 8 , PIT_CH0);	/* MSB */
-	spin_unlock_irqrestore(&i8253_lock, flags);
-}
diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
deleted file mode 100644
index 144e94a0..0000000
--- a/arch/i386/kernel/timers/timer_pm.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * (C) Dominik Brodowski <linux@brodo.de> 2003
- *
- * Driver to use the Power Management Timer (PMTMR) available in some
- * southbridges as primary timing source for the Linux kernel.
- *
- * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
- * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
- *
- * This file is licensed under the GPL v2.
- */
-
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <asm/types.h>
-#include <asm/timer.h>
-#include <asm/smp.h>
-#include <asm/io.h>
-#include <asm/arch_hooks.h>
-
-#include <linux/timex.h>
-#include "mach_timer.h"
-
-/* Number of PMTMR ticks expected during calibration run */
-#define PMTMR_TICKS_PER_SEC 3579545
-#define PMTMR_EXPECTED_RATE \
-  ((CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (CLOCK_TICK_RATE>>10))
-
-
-/* The I/O port the PMTMR resides at.
- * The location is detected during setup_arch(),
- * in arch/i386/acpi/boot.c */
-u32 pmtmr_ioport = 0;
-
-
-/* value of the Power timer at last timer interrupt */
-static u32 offset_tick;
-static u32 offset_delay;
-
-static unsigned long long monotonic_base;
-static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
-
-#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
-
-static int pmtmr_need_workaround __read_mostly = 1;
-
-/*helper function to safely read acpi pm timesource*/
-static inline u32 read_pmtmr(void)
-{
-	if (pmtmr_need_workaround) {
-		u32 v1, v2, v3;
-
-		/* It has been reported that because of various broken
-		 * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time
-		 * source is not latched, so you must read it multiple
-		 * times to insure a safe value is read.
-		 */
-		do {
-			v1 = inl(pmtmr_ioport);
-			v2 = inl(pmtmr_ioport);
-			v3 = inl(pmtmr_ioport);
-		} while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
-			 || (v3 > v1 && v3 < v2));
-
-		/* mask the output to 24 bits */
-		return v2 & ACPI_PM_MASK;
-	}
-
-	return inl(pmtmr_ioport) & ACPI_PM_MASK;
-}
-
-
-/*
- * Some boards have the PMTMR running way too fast. We check
- * the PMTMR rate against PIT channel 2 to catch these cases.
- */
-static int verify_pmtmr_rate(void)
-{
-	u32 value1, value2;
-	unsigned long count, delta;
-
-	mach_prepare_counter();
-	value1 = read_pmtmr();
-	mach_countup(&count);
-	value2 = read_pmtmr();
-	delta = (value2 - value1) & ACPI_PM_MASK;
-
-	/* Check that the PMTMR delta is within 5% of what we expect */
-	if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
-	    delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
-		printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% of normal - aborting.\n", 100UL * delta / PMTMR_EXPECTED_RATE);
-		return -1;
-	}
-
-	return 0;
-}
-
-
-static int init_pmtmr(char* override)
-{
-	u32 value1, value2;
-	unsigned int i;
-
- 	if (override[0] && strncmp(override,"pmtmr",5))
-		return -ENODEV;
-
-	if (!pmtmr_ioport)
-		return -ENODEV;
-
-	/* we use the TSC for delay_pmtmr, so make sure it exists */
-	if (!cpu_has_tsc)
-		return -ENODEV;
-
-	/* "verify" this timing source */
-	value1 = read_pmtmr();
-	for (i = 0; i < 10000; i++) {
-		value2 = read_pmtmr();
-		if (value2 == value1)
-			continue;
-		if (value2 > value1)
-			goto pm_good;
-		if ((value2 < value1) && ((value2) < 0xFFF))
-			goto pm_good;
-		printk(KERN_INFO "PM-Timer had inconsistent results: 0x%#x, 0x%#x - aborting.\n", value1, value2);
-		return -EINVAL;
-	}
-	printk(KERN_INFO "PM-Timer had no reasonable result: 0x%#x - aborting.\n", value1);
-	return -ENODEV;
-
-pm_good:
-	if (verify_pmtmr_rate() != 0)
-		return -ENODEV;
-
-	init_cpu_khz();
-	return 0;
-}
-
-static inline u32 cyc2us(u32 cycles)
-{
-	/* The Power Management Timer ticks at 3.579545 ticks per microsecond.
-	 * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
-	 *
-	 * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
-	 * easily be multiplied with 286 (=0x11E) without having to fear
-	 * u32 overflows.
-	 */
-	cycles *= 286;
-	return (cycles >> 10);
-}
-
-/*
- * this gets called during each timer interrupt
- *   - Called while holding the writer xtime_lock
- */
-static void mark_offset_pmtmr(void)
-{
-	u32 lost, delta, last_offset;
-	static int first_run = 1;
-	last_offset = offset_tick;
-
-	write_seqlock(&monotonic_lock);
-
-	offset_tick = read_pmtmr();
-
-	/* calculate tick interval */
-	delta = (offset_tick - last_offset) & ACPI_PM_MASK;
-
-	/* convert to usecs */
-	delta = cyc2us(delta);
-
-	/* update the monotonic base value */
-	monotonic_base += delta * NSEC_PER_USEC;
-	write_sequnlock(&monotonic_lock);
-
-	/* convert to ticks */
-	delta += offset_delay;
-	lost = delta / (USEC_PER_SEC / HZ);
-	offset_delay = delta % (USEC_PER_SEC / HZ);
-
-
-	/* compensate for lost ticks */
-	if (lost >= 2)
-		jiffies_64 += lost - 1;
-
-	/* don't calculate delay for first run,
-	   or if we've got less then a tick */
-	if (first_run || (lost < 1)) {
-		first_run = 0;
-		offset_delay = 0;
-	}
-}
-
-static int pmtmr_resume(void)
-{
-	write_seqlock(&monotonic_lock);
-	/* Assume this is the last mark offset time */
-	offset_tick = read_pmtmr();
-	write_sequnlock(&monotonic_lock);
-	return 0;
-}
-
-static unsigned long long monotonic_clock_pmtmr(void)
-{
-	u32 last_offset, this_offset;
-	unsigned long long base, ret;
-	unsigned seq;
-
-
-	/* atomically read monotonic base & last_offset */
-	do {
-		seq = read_seqbegin(&monotonic_lock);
-		last_offset = offset_tick;
-		base = monotonic_base;
-	} while (read_seqretry(&monotonic_lock, seq));
-
-	/* Read the pmtmr */
-	this_offset =  read_pmtmr();
-
-	/* convert to nanoseconds */
-	ret = (this_offset - last_offset) & ACPI_PM_MASK;
-	ret = base + (cyc2us(ret) * NSEC_PER_USEC);
-	return ret;
-}
-
-static void delay_pmtmr(unsigned long loops)
-{
-	unsigned long bclock, now;
-
-	rdtscl(bclock);
-	do
-	{
-		rep_nop();
-		rdtscl(now);
-	} while ((now-bclock) < loops);
-}
-
-
-/*
- * get the offset (in microseconds) from the last call to mark_offset()
- *	- Called holding a reader xtime_lock
- */
-static unsigned long get_offset_pmtmr(void)
-{
-	u32 now, offset, delta = 0;
-
-	offset = offset_tick;
-	now = read_pmtmr();
-	delta = (now - offset)&ACPI_PM_MASK;
-
-	return (unsigned long) offset_delay + cyc2us(delta);
-}
-
-
-/* acpi timer_opts struct */
-static struct timer_opts timer_pmtmr = {
-	.name			= "pmtmr",
-	.mark_offset		= mark_offset_pmtmr,
-	.get_offset		= get_offset_pmtmr,
-	.monotonic_clock 	= monotonic_clock_pmtmr,
-	.delay 			= delay_pmtmr,
-	.read_timer 		= read_timer_tsc,
-	.resume			= pmtmr_resume,
-};
-
-struct init_timer_opts __initdata timer_pmtmr_init = {
-	.init = init_pmtmr,
-	.opts = &timer_pmtmr,
-};
-
-#ifdef CONFIG_PCI
-/*
- * PIIX4 Errata:
- *
- * The power management timer may return improper results when read.
- * Although the timer value settles properly after incrementing,
- * while incrementing there is a 3 ns window every 69.8 ns where the
- * timer value is indeterminate (a 4.2% chance that the data will be
- * incorrect when read). As a result, the ACPI free running count up
- * timer specification is violated due to erroneous reads.
- */
-static int __init pmtmr_bug_check(void)
-{
-	static struct pci_device_id gray_list[] __initdata = {
-		/* these chipsets may have bug. */
-		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
-				PCI_DEVICE_ID_INTEL_82801DB_0) },
-		{ },
-	};
-	struct pci_dev *dev;
-	int pmtmr_has_bug = 0;
-	u8 rev;
-
-	if (cur_timer != &timer_pmtmr || !pmtmr_need_workaround)
-		return 0;
-
-	dev = pci_get_device(PCI_VENDOR_ID_INTEL,
-			     PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
-	if (dev) {
-		pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
-		/* the bug has been fixed in PIIX4M */
-		if (rev < 3) {
-			printk(KERN_WARNING "* Found PM-Timer Bug on this "
-				"chipset. Due to workarounds for a bug,\n"
-				"* this time source is slow.  Consider trying "
-				"other time sources (clock=)\n");
-			pmtmr_has_bug = 1;
-		}
-		pci_dev_put(dev);
-	}
-
-	if (pci_dev_present(gray_list)) {
-		printk(KERN_WARNING "* This chipset may have PM-Timer Bug.  Due"
-			" to workarounds for a bug,\n"
-			"* this time source is slow. If you are sure your timer"
-			" does not have\n"
-			"* this bug, please use \"pmtmr_good\" to disable the "
-			"workaround\n");
-		pmtmr_has_bug = 1;
-	}
-
-	if (!pmtmr_has_bug)
-		pmtmr_need_workaround = 0;
-
-	return 0;
-}
-device_initcall(pmtmr_bug_check);
-#endif
-
-static int __init pmtr_good_setup(char *__str)
-{
-	pmtmr_need_workaround = 0;
-	return 1;
-}
-__setup("pmtmr_good", pmtr_good_setup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
-MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86");
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
deleted file mode 100644
index f1187dd..0000000
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * This code largely moved from arch/i386/kernel/time.c.
- * See comments there for proper credits.
- *
- * 2004-06-25    Jesper Juhl
- *      moved mark_offset_tsc below cpufreq_delayed_get to avoid gcc 3.4
- *      failing to inline.
- */
-
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/timex.h>
-#include <linux/errno.h>
-#include <linux/cpufreq.h>
-#include <linux/string.h>
-#include <linux/jiffies.h>
-
-#include <asm/timer.h>
-#include <asm/io.h>
-/* processor.h for distable_tsc flag */
-#include <asm/processor.h>
-
-#include "io_ports.h"
-#include "mach_timer.h"
-
-#include <asm/hpet.h>
-#include <asm/i8253.h>
-
-#ifdef CONFIG_HPET_TIMER
-static unsigned long hpet_usec_quotient;
-static unsigned long hpet_last;
-static struct timer_opts timer_tsc;
-#endif
-
-static inline void cpufreq_delayed_get(void);
-
-int tsc_disable __devinitdata = 0;
-
-static int use_tsc;
-/* Number of usecs that the last interrupt was delayed */
-static int delay_at_last_interrupt;
-
-static unsigned long last_tsc_low; /* lsb 32 bits of Time Stamp Counter */
-static unsigned long last_tsc_high; /* msb 32 bits of Time Stamp Counter */
-static unsigned long long monotonic_base;
-static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
-
-/* Avoid compensating for lost ticks before TSCs are synched */
-static int detect_lost_ticks;
-static int __init start_lost_tick_compensation(void)
-{
-	detect_lost_ticks = 1;
-	return 0;
-}
-late_initcall(start_lost_tick_compensation);
-
-/* convert from cycles(64bits) => nanoseconds (64bits)
- *  basic equation:
- *		ns = cycles / (freq / ns_per_sec)
- *		ns = cycles * (ns_per_sec / freq)
- *		ns = cycles * (10^9 / (cpu_khz * 10^3))
- *		ns = cycles * (10^6 / cpu_khz)
- *
- *	Then we use scaling math (suggested by george@mvista.com) to get:
- *		ns = cycles * (10^6 * SC / cpu_khz) / SC
- *		ns = cycles * cyc2ns_scale / SC
- *
- *	And since SC is a constant power of two, we can convert the div
- *  into a shift.
- *
- *  We can use khz divisor instead of mhz to keep a better percision, since
- *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
- *  (mathieu.desnoyers@polymtl.ca)
- *
- *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
- */
-static unsigned long cyc2ns_scale __read_mostly;
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-
-static inline void set_cyc2ns_scale(unsigned long cpu_khz)
-{
-	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
-}
-
-static inline unsigned long long cycles_2_ns(unsigned long long cyc)
-{
-	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
-}
-
-static int count2; /* counter for mark_offset_tsc() */
-
-/* Cached *multiplier* to convert TSC counts to microseconds.
- * (see the equation below).
- * Equal to 2^32 * (1 / (clocks per usec) ).
- * Initialized in time_init.
- */
-static unsigned long fast_gettimeoffset_quotient;
-
-static unsigned long get_offset_tsc(void)
-{
-	register unsigned long eax, edx;
-
-	/* Read the Time Stamp Counter */
-
-	rdtsc(eax,edx);
-
-	/* .. relative to previous jiffy (32 bits is enough) */
-	eax -= last_tsc_low;	/* tsc_low delta */
-
-	/*
-         * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
-         *             = (tsc_low delta) * (usecs_per_clock)
-         *             = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
-	 *
-	 * Using a mull instead of a divl saves up to 31 clock cycles
-	 * in the critical path.
-         */
-
-	__asm__("mull %2"
-		:"=a" (eax), "=d" (edx)
-		:"rm" (fast_gettimeoffset_quotient),
-		 "0" (eax));
-
-	/* our adjusted time offset in microseconds */
-	return delay_at_last_interrupt + edx;
-}
-
-static unsigned long long monotonic_clock_tsc(void)
-{
-	unsigned long long last_offset, this_offset, base;
-	unsigned seq;
-	
-	/* atomically read monotonic base & last_offset */
-	do {
-		seq = read_seqbegin(&monotonic_lock);
-		last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-		base = monotonic_base;
-	} while (read_seqretry(&monotonic_lock, seq));
-
-	/* Read the Time Stamp Counter */
-	rdtscll(this_offset);
-
-	/* return the value in ns */
-	return base + cycles_2_ns(this_offset - last_offset);
-}
-
-/*
- * Scheduler clock - returns current time in nanosec units.
- */
-unsigned long long sched_clock(void)
-{
-	unsigned long long this_offset;
-
-	/*
-	 * In the NUMA case we dont use the TSC as they are not
-	 * synchronized across all CPUs.
-	 */
-#ifndef CONFIG_NUMA
-	if (!use_tsc)
-#endif
-		/* no locking but a rare wrong value is not a big deal */
-		return jiffies_64 * (1000000000 / HZ);
-
-	/* Read the Time Stamp Counter */
-	rdtscll(this_offset);
-
-	/* return the value in ns */
-	return cycles_2_ns(this_offset);
-}
-
-static void delay_tsc(unsigned long loops)
-{
-	unsigned long bclock, now;
-	
-	rdtscl(bclock);
-	do
-	{
-		rep_nop();
-		rdtscl(now);
-	} while ((now-bclock) < loops);
-}
-
-#ifdef CONFIG_HPET_TIMER
-static void mark_offset_tsc_hpet(void)
-{
-	unsigned long long this_offset, last_offset;
- 	unsigned long offset, temp, hpet_current;
-
-	write_seqlock(&monotonic_lock);
-	last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-	/*
-	 * It is important that these two operations happen almost at
-	 * the same time. We do the RDTSC stuff first, since it's
-	 * faster. To avoid any inconsistencies, we need interrupts
-	 * disabled locally.
-	 */
-	/*
-	 * Interrupts are just disabled locally since the timer irq
-	 * has the SA_INTERRUPT flag set. -arca
-	 */
-	/* read Pentium cycle counter */
-
-	hpet_current = hpet_readl(HPET_COUNTER);
-	rdtsc(last_tsc_low, last_tsc_high);
-
-	/* lost tick compensation */
-	offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
-	if (unlikely(((offset - hpet_last) > hpet_tick) && (hpet_last != 0))
-					&& detect_lost_ticks) {
-		int lost_ticks = (offset - hpet_last) / hpet_tick;
-		jiffies_64 += lost_ticks;
-	}
-	hpet_last = hpet_current;
-
-	/* update the monotonic base value */
-	this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-	monotonic_base += cycles_2_ns(this_offset - last_offset);
-	write_sequnlock(&monotonic_lock);
-
-	/* calculate delay_at_last_interrupt */
-	/*
-	 * Time offset = (hpet delta) * ( usecs per HPET clock )
-	 *             = (hpet delta) * ( usecs per tick / HPET clocks per tick)
-	 *             = (hpet delta) * ( hpet_usec_quotient ) / (2^32)
-	 * Where,
-	 * hpet_usec_quotient = (2^32 * usecs per tick)/HPET clocks per tick
-	 */
-	delay_at_last_interrupt = hpet_current - offset;
-	ASM_MUL64_REG(temp, delay_at_last_interrupt,
-			hpet_usec_quotient, delay_at_last_interrupt);
-}
-#endif
-
-
-#ifdef CONFIG_CPU_FREQ
-#include <linux/workqueue.h>
-
-static unsigned int cpufreq_delayed_issched = 0;
-static unsigned int cpufreq_init = 0;
-static struct work_struct cpufreq_delayed_get_work;
-
-static void handle_cpufreq_delayed_get(void *v)
-{
-	unsigned int cpu;
-	for_each_online_cpu(cpu) {
-		cpufreq_get(cpu);
-	}
-	cpufreq_delayed_issched = 0;
-}
-
-/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries
- * to verify the CPU frequency the timing core thinks the CPU is running
- * at is still correct.
- */
-static inline void cpufreq_delayed_get(void) 
-{
-	if (cpufreq_init && !cpufreq_delayed_issched) {
-		cpufreq_delayed_issched = 1;
-		printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n");
-		schedule_work(&cpufreq_delayed_get_work);
-	}
-}
-
-/* If the CPU frequency is scaled, TSC-based delays will need a different
- * loops_per_jiffy value to function properly.
- */
-
-static unsigned int  ref_freq = 0;
-static unsigned long loops_per_jiffy_ref = 0;
-
-#ifndef CONFIG_SMP
-static unsigned long fast_gettimeoffset_ref = 0;
-static unsigned int cpu_khz_ref = 0;
-#endif
-
-static int
-time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
-		       void *data)
-{
-	struct cpufreq_freqs *freq = data;
-
-	if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
-		write_seqlock_irq(&xtime_lock);
-	if (!ref_freq) {
-		if (!freq->old){
-			ref_freq = freq->new;
-			goto end;
-		}
-		ref_freq = freq->old;
-		loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
-#ifndef CONFIG_SMP
-		fast_gettimeoffset_ref = fast_gettimeoffset_quotient;
-		cpu_khz_ref = cpu_khz;
-#endif
-	}
-
-	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
-	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
-	    (val == CPUFREQ_RESUMECHANGE)) {
-		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-			cpu_data[freq->cpu].loops_per_jiffy = cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
-#ifndef CONFIG_SMP
-		if (cpu_khz)
-			cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
-		if (use_tsc) {
-			if (!(freq->flags & CPUFREQ_CONST_LOOPS)) {
-				fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq);
-				set_cyc2ns_scale(cpu_khz);
-			}
-		}
-#endif
-	}
-
-end:
-	if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
-		write_sequnlock_irq(&xtime_lock);
-
-	return 0;
-}
-
-static struct notifier_block time_cpufreq_notifier_block = {
-	.notifier_call	= time_cpufreq_notifier
-};
-
-
-static int __init cpufreq_tsc(void)
-{
-	int ret;
-	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
-	ret = cpufreq_register_notifier(&time_cpufreq_notifier_block,
-					CPUFREQ_TRANSITION_NOTIFIER);
-	if (!ret)
-		cpufreq_init = 1;
-	return ret;
-}
-core_initcall(cpufreq_tsc);
-
-#else /* CONFIG_CPU_FREQ */
-static inline void cpufreq_delayed_get(void) { return; }
-#endif 
-
-int recalibrate_cpu_khz(void)
-{
-#ifndef CONFIG_SMP
-	unsigned int cpu_khz_old = cpu_khz;
-
-	if (cpu_has_tsc) {
-		local_irq_disable();
-		init_cpu_khz();
-		local_irq_enable();
-		cpu_data[0].loops_per_jiffy =
-		    cpufreq_scale(cpu_data[0].loops_per_jiffy,
-			          cpu_khz_old,
-				  cpu_khz);
-		return 0;
-	} else
-		return -ENODEV;
-#else
-	return -ENODEV;
-#endif
-}
-EXPORT_SYMBOL(recalibrate_cpu_khz);
-
-static void mark_offset_tsc(void)
-{
-	unsigned long lost,delay;
-	unsigned long delta = last_tsc_low;
-	int count;
-	int countmp;
-	static int count1 = 0;
-	unsigned long long this_offset, last_offset;
-	static int lost_count = 0;
-
-	write_seqlock(&monotonic_lock);
-	last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-	/*
-	 * It is important that these two operations happen almost at
-	 * the same time. We do the RDTSC stuff first, since it's
-	 * faster. To avoid any inconsistencies, we need interrupts
-	 * disabled locally.
-	 */
-
-	/*
-	 * Interrupts are just disabled locally since the timer irq
-	 * has the SA_INTERRUPT flag set. -arca
-	 */
-
-	/* read Pentium cycle counter */
-
-	rdtsc(last_tsc_low, last_tsc_high);
-
-	spin_lock(&i8253_lock);
-	outb_p(0x00, PIT_MODE);     /* latch the count ASAP */
-
-	count = inb_p(PIT_CH0);    /* read the latched count */
-	count |= inb(PIT_CH0) << 8;
-
-	/*
-	 * VIA686a test code... reset the latch if count > max + 1
-	 * from timer_pit.c - cjb
-	 */
-	if (count > LATCH) {
-		outb_p(0x34, PIT_MODE);
-		outb_p(LATCH & 0xff, PIT_CH0);
-		outb(LATCH >> 8, PIT_CH0);
-		count = LATCH - 1;
-	}
-
-	spin_unlock(&i8253_lock);
-
-	if (pit_latch_buggy) {
-		/* get center value of last 3 time lutch */
-		if ((count2 >= count && count >= count1)
-		    || (count1 >= count && count >= count2)) {
-			count2 = count1; count1 = count;
-		} else if ((count1 >= count2 && count2 >= count)
-			   || (count >= count2 && count2 >= count1)) {
-			countmp = count;count = count2;
-			count2 = count1;count1 = countmp;
-		} else {
-			count2 = count1; count1 = count; count = count1;
-		}
-	}
-
-	/* lost tick compensation */
-	delta = last_tsc_low - delta;
-	{
-		register unsigned long eax, edx;
-		eax = delta;
-		__asm__("mull %2"
-		:"=a" (eax), "=d" (edx)
-		:"rm" (fast_gettimeoffset_quotient),
-		 "0" (eax));
-		delta = edx;
-	}
-	delta += delay_at_last_interrupt;
-	lost = delta/(1000000/HZ);
-	delay = delta%(1000000/HZ);
-	if (lost >= 2 && detect_lost_ticks) {
-		jiffies_64 += lost-1;
-
-		/* sanity check to ensure we're not always losing ticks */
-		if (lost_count++ > 100) {
-			printk(KERN_WARNING "Losing too many ticks!\n");
-			printk(KERN_WARNING "TSC cannot be used as a timesource.  \n");
-			printk(KERN_WARNING "Possible reasons for this are:\n");
-			printk(KERN_WARNING "  You're running with Speedstep,\n");
-			printk(KERN_WARNING "  You don't have DMA enabled for your hard disk (see hdparm),\n");
-			printk(KERN_WARNING "  Incorrect TSC synchronization on an SMP system (see dmesg).\n");
-			printk(KERN_WARNING "Falling back to a sane timesource now.\n");
-
-			clock_fallback();
-		}
-		/* ... but give the TSC a fair chance */
-		if (lost_count > 25)
-			cpufreq_delayed_get();
-	} else
-		lost_count = 0;
-	/* update the monotonic base value */
-	this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
-	monotonic_base += cycles_2_ns(this_offset - last_offset);
-	write_sequnlock(&monotonic_lock);
-
-	/* calculate delay_at_last_interrupt */
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
-
-	/* catch corner case where tick rollover occured
-	 * between tsc and pit reads (as noted when
-	 * usec delta is > 90% # of usecs/tick)
-	 */
-	if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
-		jiffies_64++;
-}
-
-static int __init init_tsc(char* override)
-{
-
-	/* check clock override */
-	if (override[0] && strncmp(override,"tsc",3)) {
-#ifdef CONFIG_HPET_TIMER
-		if (is_hpet_enabled()) {
-			printk(KERN_ERR "Warning: clock= override failed. Defaulting to tsc\n");
-		} else
-#endif
-		{
-			return -ENODEV;
-		}
-	}
-
-	/*
-	 * If we have APM enabled or the CPU clock speed is variable
-	 * (CPU stops clock on HLT or slows clock to save power)
-	 * then the TSC timestamps may diverge by up to 1 jiffy from
-	 * 'real time' but nothing will break.
-	 * The most frequent case is that the CPU is "woken" from a halt
-	 * state by the timer interrupt itself, so we get 0 error. In the
-	 * rare cases where a driver would "wake" the CPU and request a
-	 * timestamp, the maximum error is < 1 jiffy. But timestamps are
-	 * still perfectly ordered.
-	 * Note that the TSC counter will be reset if APM suspends
-	 * to disk; this won't break the kernel, though, 'cuz we're
-	 * smart.  See arch/i386/kernel/apm.c.
-	 */
- 	/*
- 	 *	Firstly we have to do a CPU check for chips with
- 	 * 	a potentially buggy TSC. At this point we haven't run
- 	 *	the ident/bugs checks so we must run this hook as it
- 	 *	may turn off the TSC flag.
- 	 *
- 	 *	NOTE: this doesn't yet handle SMP 486 machines where only
- 	 *	some CPU's have a TSC. Thats never worked and nobody has
- 	 *	moaned if you have the only one in the world - you fix it!
- 	 */
-
-	count2 = LATCH; /* initialize counter for mark_offset_tsc() */
-
-	if (cpu_has_tsc) {
-		unsigned long tsc_quotient;
-#ifdef CONFIG_HPET_TIMER
-		if (is_hpet_enabled() && hpet_use_timer) {
-			unsigned long result, remain;
-			printk("Using TSC for gettimeofday\n");
-			tsc_quotient = calibrate_tsc_hpet(NULL);
-			timer_tsc.mark_offset = &mark_offset_tsc_hpet;
-			/*
-			 * Math to calculate hpet to usec multiplier
-			 * Look for the comments at get_offset_tsc_hpet()
-			 */
-			ASM_DIV64_REG(result, remain, hpet_tick,
-					0, KERNEL_TICK_USEC);
-			if (remain > (hpet_tick >> 1))
-				result++; /* rounding the result */
-
-			hpet_usec_quotient = result;
-		} else
-#endif
-		{
-			tsc_quotient = calibrate_tsc();
-		}
-
-		if (tsc_quotient) {
-			fast_gettimeoffset_quotient = tsc_quotient;
-			use_tsc = 1;
-			/*
-			 *	We could be more selective here I suspect
-			 *	and just enable this for the next intel chips ?
-			 */
-			/* report CPU clock rate in Hz.
-			 * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
-			 * clock/second. Our precision is about 100 ppm.
-			 */
-			{	unsigned long eax=0, edx=1000;
-				__asm__("divl %2"
-		       		:"=a" (cpu_khz), "=d" (edx)
-        	       		:"r" (tsc_quotient),
-	                	"0" (eax), "1" (edx));
-				printk("Detected %u.%03u MHz processor.\n",
-					cpu_khz / 1000, cpu_khz % 1000);
-			}
-			set_cyc2ns_scale(cpu_khz);
-			return 0;
-		}
-	}
-	return -ENODEV;
-}
-
-static int tsc_resume(void)
-{
-	write_seqlock(&monotonic_lock);
-	/* Assume this is the last mark offset time */
-	rdtsc(last_tsc_low, last_tsc_high);
-#ifdef CONFIG_HPET_TIMER
-	if (is_hpet_enabled() && hpet_use_timer)
-		hpet_last = hpet_readl(HPET_COUNTER);
-#endif
-	write_sequnlock(&monotonic_lock);
-	return 0;
-}
-
-#ifndef CONFIG_X86_TSC
-/* disable flag for tsc.  Takes effect by clearing the TSC cpu flag
- * in cpu/common.c */
-static int __init tsc_setup(char *str)
-{
-	tsc_disable = 1;
-	return 1;
-}
-#else
-static int __init tsc_setup(char *str)
-{
-	printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, "
-				"cannot disable TSC.\n");
-	return 1;
-}
-#endif
-__setup("notsc", tsc_setup);
-
-
-
-/************************************************************/
-
-/* tsc timer_opts struct */
-static struct timer_opts timer_tsc = {
-	.name = "tsc",
-	.mark_offset = mark_offset_tsc, 
-	.get_offset = get_offset_tsc,
-	.monotonic_clock = monotonic_clock_tsc,
-	.delay = delay_tsc,
-	.read_timer = read_timer_tsc,
-	.resume	= tsc_resume,
-};
-
-struct init_timer_opts __initdata timer_tsc_init = {
-	.init = init_tsc,
-	.opts = &timer_tsc,
-};
diff --git a/arch/i386/kernel/topology.c b/arch/i386/kernel/topology.c
index 2963552..e2e281d 100644
--- a/arch/i386/kernel/topology.c
+++ b/arch/i386/kernel/topology.c
@@ -32,15 +32,8 @@
 
 static struct i386_cpu cpu_devices[NR_CPUS];
 
-int arch_register_cpu(int num){
-	struct node *parent = NULL;
-
-#ifdef CONFIG_NUMA
-	int node = cpu_to_node(num);
-	if (node_online(node))
-		parent = &node_devices[node].node;
-#endif /* CONFIG_NUMA */
-
+int arch_register_cpu(int num)
+{
 	/*
 	 * CPU0 cannot be offlined due to several
 	 * restrictions and assumptions in kernel. This basically
@@ -50,21 +43,13 @@
 	if (!num)
 		cpu_devices[num].cpu.no_control = 1;
 
-	return register_cpu(&cpu_devices[num].cpu, num, parent);
+	return register_cpu(&cpu_devices[num].cpu, num);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 
 void arch_unregister_cpu(int num) {
-	struct node *parent = NULL;
-
-#ifdef CONFIG_NUMA
-	int node = cpu_to_node(num);
-	if (node_online(node))
-		parent = &node_devices[node].node;
-#endif /* CONFIG_NUMA */
-
-	return unregister_cpu(&cpu_devices[num].cpu, parent);
+	return unregister_cpu(&cpu_devices[num].cpu);
 }
 EXPORT_SYMBOL(arch_register_cpu);
 EXPORT_SYMBOL(arch_unregister_cpu);
@@ -74,16 +59,13 @@
 
 #ifdef CONFIG_NUMA
 #include <linux/mmzone.h>
-#include <asm/node.h>
-
-struct i386_node node_devices[MAX_NUMNODES];
 
 static int __init topology_init(void)
 {
 	int i;
 
 	for_each_online_node(i)
-		arch_register_node(i);
+		register_one_node(i);
 
 	for_each_present_cpu(i)
 		arch_register_cpu(i);
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 0e49836..7846409 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -28,6 +28,7 @@
 #include <linux/utsname.h>
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
+#include <linux/unwind.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -47,7 +48,7 @@
 #include <asm/desc.h>
 #include <asm/i387.h>
 #include <asm/nmi.h>
-
+#include <asm/unwind.h>
 #include <asm/smp.h>
 #include <asm/arch_hooks.h>
 #include <asm/kdebug.h>
@@ -92,6 +93,7 @@
 asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
+static int call_trace = 1;
 ATOMIC_NOTIFIER_HEAD(i386die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
@@ -149,6 +151,12 @@
 	while (valid_stack_ptr(tinfo, (void *)ebp)) {
 		addr = *(unsigned long *)(ebp + 4);
 		printed = print_addr_and_symbol(addr, log_lvl, printed);
+		/*
+		 * break out of recursive entries (such as
+		 * end_of_stack_stop_unwind_function):
+	 	 */
+		if (ebp == *(unsigned long *)ebp)
+			break;
 		ebp = *(unsigned long *)ebp;
 	}
 #else
@@ -164,7 +172,23 @@
 	return ebp;
 }
 
-static void show_trace_log_lvl(struct task_struct *task,
+static asmlinkage int show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
+{
+	int n = 0;
+	int printed = 0; /* nr of entries already printed on current line */
+
+	while (unwind(info) == 0 && UNW_PC(info)) {
+		++n;
+		printed = print_addr_and_symbol(UNW_PC(info), log_lvl, printed);
+		if (arch_unw_user_mode(info))
+			break;
+	}
+	if (printed)
+		printk("\n");
+	return n;
+}
+
+static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
 			       unsigned long *stack, char *log_lvl)
 {
 	unsigned long ebp;
@@ -172,6 +196,26 @@
 	if (!task)
 		task = current;
 
+	if (call_trace >= 0) {
+		int unw_ret = 0;
+		struct unwind_frame_info info;
+
+		if (regs) {
+			if (unwind_init_frame_info(&info, task, regs) == 0)
+				unw_ret = show_trace_unwind(&info, log_lvl);
+		} else if (task == current)
+			unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
+		else {
+			if (unwind_init_blocked(&info, task) == 0)
+				unw_ret = show_trace_unwind(&info, log_lvl);
+		}
+		if (unw_ret > 0) {
+			if (call_trace > 0)
+				return;
+			printk("%sLegacy call trace:\n", log_lvl);
+		}
+	}
+
 	if (task == current) {
 		/* Grab ebp right from our regs */
 		asm ("movl %%ebp, %0" : "=r" (ebp) : );
@@ -192,13 +236,13 @@
 	}
 }
 
-void show_trace(struct task_struct *task, unsigned long * stack)
+void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long * stack)
 {
-	show_trace_log_lvl(task, stack, "");
+	show_trace_log_lvl(task, regs, stack, "");
 }
 
-static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp,
-			       char *log_lvl)
+static void show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
+			       unsigned long *esp, char *log_lvl)
 {
 	unsigned long *stack;
 	int i;
@@ -219,13 +263,13 @@
 		printk("%08lx ", *stack++);
 	}
 	printk("\n%sCall Trace:\n", log_lvl);
-	show_trace_log_lvl(task, esp, log_lvl);
+	show_trace_log_lvl(task, regs, esp, log_lvl);
 }
 
 void show_stack(struct task_struct *task, unsigned long *esp)
 {
 	printk("       ");
-	show_stack_log_lvl(task, esp, "");
+	show_stack_log_lvl(task, NULL, esp, "");
 }
 
 /*
@@ -235,7 +279,7 @@
 {
 	unsigned long stack;
 
-	show_trace(current, &stack);
+	show_trace(current, NULL, &stack);
 }
 
 EXPORT_SYMBOL(dump_stack);
@@ -268,8 +312,9 @@
 		regs->esi, regs->edi, regs->ebp, esp);
 	printk(KERN_EMERG "ds: %04x   es: %04x   ss: %04x\n",
 		regs->xds & 0xffff, regs->xes & 0xffff, ss);
-	printk(KERN_EMERG "Process %s (pid: %d, threadinfo=%p task=%p)",
-		current->comm, current->pid, current_thread_info(), current);
+	printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)",
+		TASK_COMM_LEN, current->comm, current->pid,
+		current_thread_info(), current, current->thread_info);
 	/*
 	 * When in-kernel, we also print out the stack and code at the
 	 * time of the fault..
@@ -278,7 +323,7 @@
 		u8 __user *eip;
 
 		printk("\n" KERN_EMERG "Stack: ");
-		show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG);
+		show_stack_log_lvl(NULL, regs, (unsigned long *)esp, KERN_EMERG);
 
 		printk(KERN_EMERG "Code: ");
 
@@ -1208,3 +1253,15 @@
 	return 1;
 }
 __setup("kstack=", kstack_setup);
+
+static int __init call_trace_setup(char *s)
+{
+	if (strcmp(s, "old") == 0)
+		call_trace = -1;
+	else if (strcmp(s, "both") == 0)
+		call_trace = 0;
+	else if (strcmp(s, "new") == 0)
+		call_trace = 1;
+	return 1;
+}
+__setup("call_trace=", call_trace_setup);
diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c
new file mode 100644
index 0000000..7e0d8da
--- /dev/null
+++ b/arch/i386/kernel/tsc.c
@@ -0,0 +1,478 @@
+/*
+ * This code largely moved from arch/i386/kernel/timer/timer_tsc.c
+ * which was originally moved from arch/i386/kernel/time.c.
+ * See comments there for proper credits.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/workqueue.h>
+#include <linux/cpufreq.h>
+#include <linux/jiffies.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+
+#include <asm/delay.h>
+#include <asm/tsc.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+
+#include "mach_timer.h"
+
+/*
+ * On some systems the TSC frequency does not
+ * change with the cpu frequency. So we need
+ * an extra value to store the TSC freq
+ */
+unsigned int tsc_khz;
+
+int tsc_disable __cpuinitdata = 0;
+
+#ifdef CONFIG_X86_TSC
+static int __init tsc_setup(char *str)
+{
+	printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, "
+				"cannot disable TSC.\n");
+	return 1;
+}
+#else
+/*
+ * disable flag for tsc. Takes effect by clearing the TSC cpu flag
+ * in cpu/common.c
+ */
+static int __init tsc_setup(char *str)
+{
+	tsc_disable = 1;
+
+	return 1;
+}
+#endif
+
+__setup("notsc", tsc_setup);
+
+/*
+ * code to mark and check if the TSC is unstable
+ * due to cpufreq or due to unsynced TSCs
+ */
+static int tsc_unstable;
+
+static inline int check_tsc_unstable(void)
+{
+	return tsc_unstable;
+}
+
+void mark_tsc_unstable(void)
+{
+	tsc_unstable = 1;
+}
+EXPORT_SYMBOL_GPL(mark_tsc_unstable);
+
+/* Accellerators for sched_clock()
+ * convert from cycles(64bits) => nanoseconds (64bits)
+ *  basic equation:
+ *		ns = cycles / (freq / ns_per_sec)
+ *		ns = cycles * (ns_per_sec / freq)
+ *		ns = cycles * (10^9 / (cpu_khz * 10^3))
+ *		ns = cycles * (10^6 / cpu_khz)
+ *
+ *	Then we use scaling math (suggested by george@mvista.com) to get:
+ *		ns = cycles * (10^6 * SC / cpu_khz) / SC
+ *		ns = cycles * cyc2ns_scale / SC
+ *
+ *	And since SC is a constant power of two, we can convert the div
+ *  into a shift.
+ *
+ *  We can use khz divisor instead of mhz to keep a better percision, since
+ *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
+ *  (mathieu.desnoyers@polymtl.ca)
+ *
+ *			-johnstul@us.ibm.com "math is hard, lets go shopping!"
+ */
+static unsigned long cyc2ns_scale __read_mostly;
+
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
+{
+	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
+}
+
+static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+}
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	unsigned long long this_offset;
+
+	/*
+	 * in the NUMA case we dont use the TSC as they are not
+	 * synchronized across all CPUs.
+	 */
+#ifndef CONFIG_NUMA
+	if (!cpu_khz || check_tsc_unstable())
+#endif
+		/* no locking but a rare wrong value is not a big deal */
+		return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
+
+	/* read the Time Stamp Counter: */
+	rdtscll(this_offset);
+
+	/* return the value in ns */
+	return cycles_2_ns(this_offset);
+}
+
+static unsigned long calculate_cpu_khz(void)
+{
+	unsigned long long start, end;
+	unsigned long count;
+	u64 delta64;
+	int i;
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	/* run 3 times to ensure the cache is warm */
+	for (i = 0; i < 3; i++) {
+		mach_prepare_counter();
+		rdtscll(start);
+		mach_countup(&count);
+		rdtscll(end);
+	}
+	/*
+	 * Error: ECTCNEVERSET
+	 * The CTC wasn't reliable: we got a hit on the very first read,
+	 * or the CPU was so fast/slow that the quotient wouldn't fit in
+	 * 32 bits..
+	 */
+	if (count <= 1)
+		goto err;
+
+	delta64 = end - start;
+
+	/* cpu freq too fast: */
+	if (delta64 > (1ULL<<32))
+		goto err;
+
+	/* cpu freq too slow: */
+	if (delta64 <= CALIBRATE_TIME_MSEC)
+		goto err;
+
+	delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */
+	do_div(delta64,CALIBRATE_TIME_MSEC);
+
+	local_irq_restore(flags);
+	return (unsigned long)delta64;
+err:
+	local_irq_restore(flags);
+	return 0;
+}
+
+int recalibrate_cpu_khz(void)
+{
+#ifndef CONFIG_SMP
+	unsigned long cpu_khz_old = cpu_khz;
+
+	if (cpu_has_tsc) {
+		cpu_khz = calculate_cpu_khz();
+		tsc_khz = cpu_khz;
+		cpu_data[0].loops_per_jiffy =
+			cpufreq_scale(cpu_data[0].loops_per_jiffy,
+					cpu_khz_old, cpu_khz);
+		return 0;
+	} else
+		return -ENODEV;
+#else
+	return -ENODEV;
+#endif
+}
+
+EXPORT_SYMBOL(recalibrate_cpu_khz);
+
+void tsc_init(void)
+{
+	if (!cpu_has_tsc || tsc_disable)
+		return;
+
+	cpu_khz = calculate_cpu_khz();
+	tsc_khz = cpu_khz;
+
+	if (!cpu_khz)
+		return;
+
+	printk("Detected %lu.%03lu MHz processor.\n",
+				(unsigned long)cpu_khz / 1000,
+				(unsigned long)cpu_khz % 1000);
+
+	set_cyc2ns_scale(cpu_khz);
+	use_tsc_delay();
+}
+
+#ifdef CONFIG_CPU_FREQ
+
+static unsigned int cpufreq_delayed_issched = 0;
+static unsigned int cpufreq_init = 0;
+static struct work_struct cpufreq_delayed_get_work;
+
+static void handle_cpufreq_delayed_get(void *v)
+{
+	unsigned int cpu;
+
+	for_each_online_cpu(cpu)
+		cpufreq_get(cpu);
+
+	cpufreq_delayed_issched = 0;
+}
+
+/*
+ * if we notice cpufreq oddness, schedule a call to cpufreq_get() as it tries
+ * to verify the CPU frequency the timing core thinks the CPU is running
+ * at is still correct.
+ */
+static inline void cpufreq_delayed_get(void)
+{
+	if (cpufreq_init && !cpufreq_delayed_issched) {
+		cpufreq_delayed_issched = 1;
+		printk(KERN_DEBUG "Checking if CPU frequency changed.\n");
+		schedule_work(&cpufreq_delayed_get_work);
+	}
+}
+
+/*
+ * if the CPU frequency is scaled, TSC-based delays will need a different
+ * loops_per_jiffy value to function properly.
+ */
+static unsigned int ref_freq = 0;
+static unsigned long loops_per_jiffy_ref = 0;
+static unsigned long cpu_khz_ref = 0;
+
+static int
+time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
+{
+	struct cpufreq_freqs *freq = data;
+
+	if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
+		write_seqlock_irq(&xtime_lock);
+
+	if (!ref_freq) {
+		if (!freq->old){
+			ref_freq = freq->new;
+			goto end;
+		}
+		ref_freq = freq->old;
+		loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
+		cpu_khz_ref = cpu_khz;
+	}
+
+	if ((val == CPUFREQ_PRECHANGE  && freq->old < freq->new) ||
+	    (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
+	    (val == CPUFREQ_RESUMECHANGE)) {
+		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
+			cpu_data[freq->cpu].loops_per_jiffy =
+				cpufreq_scale(loops_per_jiffy_ref,
+						ref_freq, freq->new);
+
+		if (cpu_khz) {
+
+			if (num_online_cpus() == 1)
+				cpu_khz = cpufreq_scale(cpu_khz_ref,
+						ref_freq, freq->new);
+			if (!(freq->flags & CPUFREQ_CONST_LOOPS)) {
+				tsc_khz = cpu_khz;
+				set_cyc2ns_scale(cpu_khz);
+				/*
+				 * TSC based sched_clock turns
+				 * to junk w/ cpufreq
+				 */
+				mark_tsc_unstable();
+			}
+		}
+	}
+end:
+	if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
+		write_sequnlock_irq(&xtime_lock);
+
+	return 0;
+}
+
+static struct notifier_block time_cpufreq_notifier_block = {
+	.notifier_call	= time_cpufreq_notifier
+};
+
+static int __init cpufreq_tsc(void)
+{
+	int ret;
+
+	INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
+	ret = cpufreq_register_notifier(&time_cpufreq_notifier_block,
+					CPUFREQ_TRANSITION_NOTIFIER);
+	if (!ret)
+		cpufreq_init = 1;
+
+	return ret;
+}
+
+core_initcall(cpufreq_tsc);
+
+#endif
+
+/* clock source code */
+
+static unsigned long current_tsc_khz = 0;
+static int tsc_update_callback(void);
+
+static cycle_t read_tsc(void)
+{
+	cycle_t ret;
+
+	rdtscll(ret);
+
+	return ret;
+}
+
+static struct clocksource clocksource_tsc = {
+	.name			= "tsc",
+	.rating			= 300,
+	.read			= read_tsc,
+	.mask			= CLOCKSOURCE_MASK(64),
+	.mult			= 0, /* to be set */
+	.shift			= 22,
+	.update_callback	= tsc_update_callback,
+	.is_continuous		= 1,
+};
+
+static int tsc_update_callback(void)
+{
+	int change = 0;
+
+	/* check to see if we should switch to the safe clocksource: */
+	if (clocksource_tsc.rating != 50 && check_tsc_unstable()) {
+		clocksource_tsc.rating = 50;
+		clocksource_reselect();
+		change = 1;
+	}
+
+	/* only update if tsc_khz has changed: */
+	if (current_tsc_khz != tsc_khz) {
+		current_tsc_khz = tsc_khz;
+		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
+							clocksource_tsc.shift);
+		change = 1;
+	}
+
+	return change;
+}
+
+static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d)
+{
+	printk(KERN_NOTICE "%s detected: marking TSC unstable.\n",
+		       d->ident);
+	mark_tsc_unstable();
+	return 0;
+}
+
+/* List of systems that have known TSC problems */
+static struct dmi_system_id __initdata bad_tsc_dmi_table[] = {
+	{
+	 .callback = dmi_mark_tsc_unstable,
+	 .ident = "IBM Thinkpad 380XD",
+	 .matches = {
+		     DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+		     DMI_MATCH(DMI_BOARD_NAME, "2635FA0"),
+		     },
+	 },
+	 {}
+};
+
+#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */
+static struct timer_list verify_tsc_freq_timer;
+
+/* XXX - Probably should add locking */
+static void verify_tsc_freq(unsigned long unused)
+{
+	static u64 last_tsc;
+	static unsigned long last_jiffies;
+
+	u64 now_tsc, interval_tsc;
+	unsigned long now_jiffies, interval_jiffies;
+
+
+	if (check_tsc_unstable())
+		return;
+
+	rdtscll(now_tsc);
+	now_jiffies = jiffies;
+
+	if (!last_jiffies) {
+		goto out;
+	}
+
+	interval_jiffies = now_jiffies - last_jiffies;
+	interval_tsc = now_tsc - last_tsc;
+	interval_tsc *= HZ;
+	do_div(interval_tsc, cpu_khz*1000);
+
+	if (interval_tsc < (interval_jiffies * 3 / 4)) {
+		printk("TSC appears to be running slowly. "
+			"Marking it as unstable\n");
+		mark_tsc_unstable();
+		return;
+	}
+
+out:
+	last_tsc = now_tsc;
+	last_jiffies = now_jiffies;
+	/* set us up to go off on the next interval: */
+	mod_timer(&verify_tsc_freq_timer,
+		jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL));
+}
+
+/*
+ * Make an educated guess if the TSC is trustworthy and synchronized
+ * over all CPUs.
+ */
+static __init int unsynchronized_tsc(void)
+{
+	/*
+	 * Intel systems are normally all synchronized.
+	 * Exceptions must mark TSC as unstable:
+	 */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ 		return 0;
+
+	/* assume multi socket systems are not synchronized: */
+ 	return num_possible_cpus() > 1;
+}
+
+static int __init init_tsc_clocksource(void)
+{
+
+	if (cpu_has_tsc && tsc_khz && !tsc_disable) {
+		/* check blacklist */
+		dmi_check_system(bad_tsc_dmi_table);
+
+		if (unsynchronized_tsc()) /* mark unstable if unsynced */
+			mark_tsc_unstable();
+		current_tsc_khz = tsc_khz;
+		clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz,
+							clocksource_tsc.shift);
+		/* lower the rating if we already know its unstable: */
+		if (check_tsc_unstable())
+			clocksource_tsc.rating = 50;
+
+		init_timer(&verify_tsc_freq_timer);
+		verify_tsc_freq_timer.function = verify_tsc_freq;
+		verify_tsc_freq_timer.expires =
+			jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL);
+		add_timer(&verify_tsc_freq_timer);
+
+		return clocksource_register(&clocksource_tsc);
+	}
+
+	return 0;
+}
+
+module_init(init_tsc_clocksource);
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 8831303..2d4f138 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -37,6 +37,13 @@
 
   RODATA
 
+  . = ALIGN(4);
+  __tracedata_start = .;
+  .tracedata : AT(ADDR(.tracedata) - LOAD_OFFSET) {
+	*(.tracedata)
+  }
+  __tracedata_end = .;
+
   /* writeable */
   .data : AT(ADDR(.data) - LOAD_OFFSET) {	/* Data */
 	*(.data)
@@ -64,6 +71,15 @@
   .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
   _edata = .;			/* End of data section */
 
+#ifdef CONFIG_STACK_UNWIND
+  . = ALIGN(4);
+  .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {
+	__start_unwind = .;
+  	*(.eh_frame)
+	__end_unwind = .;
+  }
+#endif
+
   . = ALIGN(THREAD_SIZE);	/* init_task */
   .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
 	*(.data.init_task)
diff --git a/arch/i386/kernel/vsyscall-sysenter.S b/arch/i386/kernel/vsyscall-sysenter.S
index 3b62baa..1a36d26 100644
--- a/arch/i386/kernel/vsyscall-sysenter.S
+++ b/arch/i386/kernel/vsyscall-sysenter.S
@@ -42,10 +42,10 @@
 	/* 7: align return point with nop's to make disassembly easier */
 	.space 7,0x90
 
-	/* 14: System call restart point is here! (SYSENTER_RETURN - 2) */
+	/* 14: System call restart point is here! (SYSENTER_RETURN-2) */
 	jmp .Lenter_kernel
 	/* 16: System call normal return point is here! */
-	.globl SYSENTER_RETURN	/* Symbol used by entry.S.  */
+	.globl SYSENTER_RETURN	/* Symbol used by sysenter.c  */
 SYSENTER_RETURN:
 	pop %ebp
 .Lpop_ebp:
diff --git a/arch/i386/kernel/vsyscall.lds.S b/arch/i386/kernel/vsyscall.lds.S
index 98699ca..e26975f 100644
--- a/arch/i386/kernel/vsyscall.lds.S
+++ b/arch/i386/kernel/vsyscall.lds.S
@@ -7,7 +7,7 @@
 
 SECTIONS
 {
-  . = VSYSCALL_BASE + SIZEOF_HEADERS;
+  . = VDSO_PRELINK + SIZEOF_HEADERS;
 
   .hash           : { *(.hash) }		:text
   .dynsym         : { *(.dynsym) }
@@ -20,7 +20,7 @@
      For the layouts to match, we need to skip more than enough
      space for the dynamic symbol table et al.  If this amount
      is insufficient, ld -shared will barf.  Just increase it here.  */
-  . = VSYSCALL_BASE + 0x400;
+  . = VDSO_PRELINK + 0x400;
 
   .text           : { *(.text) }		:text =0x90909090
   .note		  : { *(.note.*) }		:text :note
diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
index c49a6ac..3c0714c 100644
--- a/arch/i386/lib/delay.c
+++ b/arch/i386/lib/delay.c
@@ -10,43 +10,92 @@
  *	we have to worry about.
  */
 
+#include <linux/module.h>
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
-#include <linux/module.h>
+
 #include <asm/processor.h>
 #include <asm/delay.h>
 #include <asm/timer.h>
 
 #ifdef CONFIG_SMP
-#include <asm/smp.h>
+# include <asm/smp.h>
 #endif
 
-extern struct timer_opts* timer;
+/* simple loop based delay: */
+static void delay_loop(unsigned long loops)
+{
+	int d0;
+
+	__asm__ __volatile__(
+		"\tjmp 1f\n"
+		".align 16\n"
+		"1:\tjmp 2f\n"
+		".align 16\n"
+		"2:\tdecl %0\n\tjns 2b"
+		:"=&a" (d0)
+		:"0" (loops));
+}
+
+/* TSC based delay: */
+static void delay_tsc(unsigned long loops)
+{
+	unsigned long bclock, now;
+
+	rdtscl(bclock);
+	do {
+		rep_nop();
+		rdtscl(now);
+	} while ((now-bclock) < loops);
+}
+
+/*
+ * Since we calibrate only once at boot, this
+ * function should be set once at boot and not changed
+ */
+static void (*delay_fn)(unsigned long) = delay_loop;
+
+void use_tsc_delay(void)
+{
+	delay_fn = delay_tsc;
+}
+
+int read_current_timer(unsigned long *timer_val)
+{
+	if (delay_fn == delay_tsc) {
+		rdtscl(*timer_val);
+		return 0;
+	}
+	return -1;
+}
 
 void __delay(unsigned long loops)
 {
-	cur_timer->delay(loops);
+	delay_fn(loops);
 }
 
 inline void __const_udelay(unsigned long xloops)
 {
 	int d0;
+
 	xloops *= 4;
 	__asm__("mull %0"
 		:"=d" (xloops), "=&a" (d0)
-		:"1" (xloops),"0" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
-        __delay(++xloops);
+		:"1" (xloops), "0"
+		(cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
+
+	__delay(++xloops);
 }
 
 void __udelay(unsigned long usecs)
 {
-	__const_udelay(usecs * 0x000010c7);  /* 2**32 / 1000000 (rounded up) */
+	__const_udelay(usecs * 0x000010c7); /* 2**32 / 1000000 (rounded up) */
 }
 
 void __ndelay(unsigned long nsecs)
 {
-	__const_udelay(nsecs * 0x00005);  /* 2**32 / 1000000000 (rounded up) */
+	__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
 }
 
 EXPORT_SYMBOL(__delay);
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index 4cf981d..c5aa65f 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -425,15 +425,212 @@
 		       : "eax", "edx", "memory");
 	return size;
 }
+
+/*
+ * Non Temporal Hint version of __copy_user_zeroing_intel.  It is cache aware.
+ * hyoshiok@miraclelinux.com
+ */
+
+static unsigned long __copy_user_zeroing_intel_nocache(void *to,
+				const void __user *from, unsigned long size)
+{
+        int d0, d1;
+
+	__asm__ __volatile__(
+	       "        .align 2,0x90\n"
+	       "0:      movl 32(%4), %%eax\n"
+	       "        cmpl $67, %0\n"
+	       "        jbe 2f\n"
+	       "1:      movl 64(%4), %%eax\n"
+	       "        .align 2,0x90\n"
+	       "2:      movl 0(%4), %%eax\n"
+	       "21:     movl 4(%4), %%edx\n"
+	       "        movnti %%eax, 0(%3)\n"
+	       "        movnti %%edx, 4(%3)\n"
+	       "3:      movl 8(%4), %%eax\n"
+	       "31:     movl 12(%4),%%edx\n"
+	       "        movnti %%eax, 8(%3)\n"
+	       "        movnti %%edx, 12(%3)\n"
+	       "4:      movl 16(%4), %%eax\n"
+	       "41:     movl 20(%4), %%edx\n"
+	       "        movnti %%eax, 16(%3)\n"
+	       "        movnti %%edx, 20(%3)\n"
+	       "10:     movl 24(%4), %%eax\n"
+	       "51:     movl 28(%4), %%edx\n"
+	       "        movnti %%eax, 24(%3)\n"
+	       "        movnti %%edx, 28(%3)\n"
+	       "11:     movl 32(%4), %%eax\n"
+	       "61:     movl 36(%4), %%edx\n"
+	       "        movnti %%eax, 32(%3)\n"
+	       "        movnti %%edx, 36(%3)\n"
+	       "12:     movl 40(%4), %%eax\n"
+	       "71:     movl 44(%4), %%edx\n"
+	       "        movnti %%eax, 40(%3)\n"
+	       "        movnti %%edx, 44(%3)\n"
+	       "13:     movl 48(%4), %%eax\n"
+	       "81:     movl 52(%4), %%edx\n"
+	       "        movnti %%eax, 48(%3)\n"
+	       "        movnti %%edx, 52(%3)\n"
+	       "14:     movl 56(%4), %%eax\n"
+	       "91:     movl 60(%4), %%edx\n"
+	       "        movnti %%eax, 56(%3)\n"
+	       "        movnti %%edx, 60(%3)\n"
+	       "        addl $-64, %0\n"
+	       "        addl $64, %4\n"
+	       "        addl $64, %3\n"
+	       "        cmpl $63, %0\n"
+	       "        ja  0b\n"
+	       "        sfence \n"
+	       "5:      movl  %0, %%eax\n"
+	       "        shrl  $2, %0\n"
+	       "        andl $3, %%eax\n"
+	       "        cld\n"
+	       "6:      rep; movsl\n"
+	       "        movl %%eax,%0\n"
+	       "7:      rep; movsb\n"
+	       "8:\n"
+	       ".section .fixup,\"ax\"\n"
+	       "9:      lea 0(%%eax,%0,4),%0\n"
+	       "16:     pushl %0\n"
+	       "        pushl %%eax\n"
+	       "        xorl %%eax,%%eax\n"
+	       "        rep; stosb\n"
+	       "        popl %%eax\n"
+	       "        popl %0\n"
+	       "        jmp 8b\n"
+	       ".previous\n"
+	       ".section __ex_table,\"a\"\n"
+	       "	.align 4\n"
+	       "	.long 0b,16b\n"
+	       "	.long 1b,16b\n"
+	       "	.long 2b,16b\n"
+	       "	.long 21b,16b\n"
+	       "	.long 3b,16b\n"
+	       "	.long 31b,16b\n"
+	       "	.long 4b,16b\n"
+	       "	.long 41b,16b\n"
+	       "	.long 10b,16b\n"
+	       "	.long 51b,16b\n"
+	       "	.long 11b,16b\n"
+	       "	.long 61b,16b\n"
+	       "	.long 12b,16b\n"
+	       "	.long 71b,16b\n"
+	       "	.long 13b,16b\n"
+	       "	.long 81b,16b\n"
+	       "	.long 14b,16b\n"
+	       "	.long 91b,16b\n"
+	       "	.long 6b,9b\n"
+	       "        .long 7b,16b\n"
+	       ".previous"
+	       : "=&c"(size), "=&D" (d0), "=&S" (d1)
+	       :  "1"(to), "2"(from), "0"(size)
+	       : "eax", "edx", "memory");
+	return size;
+}
+
+static unsigned long __copy_user_intel_nocache(void *to,
+				const void __user *from, unsigned long size)
+{
+        int d0, d1;
+
+	__asm__ __volatile__(
+	       "        .align 2,0x90\n"
+	       "0:      movl 32(%4), %%eax\n"
+	       "        cmpl $67, %0\n"
+	       "        jbe 2f\n"
+	       "1:      movl 64(%4), %%eax\n"
+	       "        .align 2,0x90\n"
+	       "2:      movl 0(%4), %%eax\n"
+	       "21:     movl 4(%4), %%edx\n"
+	       "        movnti %%eax, 0(%3)\n"
+	       "        movnti %%edx, 4(%3)\n"
+	       "3:      movl 8(%4), %%eax\n"
+	       "31:     movl 12(%4),%%edx\n"
+	       "        movnti %%eax, 8(%3)\n"
+	       "        movnti %%edx, 12(%3)\n"
+	       "4:      movl 16(%4), %%eax\n"
+	       "41:     movl 20(%4), %%edx\n"
+	       "        movnti %%eax, 16(%3)\n"
+	       "        movnti %%edx, 20(%3)\n"
+	       "10:     movl 24(%4), %%eax\n"
+	       "51:     movl 28(%4), %%edx\n"
+	       "        movnti %%eax, 24(%3)\n"
+	       "        movnti %%edx, 28(%3)\n"
+	       "11:     movl 32(%4), %%eax\n"
+	       "61:     movl 36(%4), %%edx\n"
+	       "        movnti %%eax, 32(%3)\n"
+	       "        movnti %%edx, 36(%3)\n"
+	       "12:     movl 40(%4), %%eax\n"
+	       "71:     movl 44(%4), %%edx\n"
+	       "        movnti %%eax, 40(%3)\n"
+	       "        movnti %%edx, 44(%3)\n"
+	       "13:     movl 48(%4), %%eax\n"
+	       "81:     movl 52(%4), %%edx\n"
+	       "        movnti %%eax, 48(%3)\n"
+	       "        movnti %%edx, 52(%3)\n"
+	       "14:     movl 56(%4), %%eax\n"
+	       "91:     movl 60(%4), %%edx\n"
+	       "        movnti %%eax, 56(%3)\n"
+	       "        movnti %%edx, 60(%3)\n"
+	       "        addl $-64, %0\n"
+	       "        addl $64, %4\n"
+	       "        addl $64, %3\n"
+	       "        cmpl $63, %0\n"
+	       "        ja  0b\n"
+	       "        sfence \n"
+	       "5:      movl  %0, %%eax\n"
+	       "        shrl  $2, %0\n"
+	       "        andl $3, %%eax\n"
+	       "        cld\n"
+	       "6:      rep; movsl\n"
+	       "        movl %%eax,%0\n"
+	       "7:      rep; movsb\n"
+	       "8:\n"
+	       ".section .fixup,\"ax\"\n"
+	       "9:      lea 0(%%eax,%0,4),%0\n"
+	       "16:     jmp 8b\n"
+	       ".previous\n"
+	       ".section __ex_table,\"a\"\n"
+	       "	.align 4\n"
+	       "	.long 0b,16b\n"
+	       "	.long 1b,16b\n"
+	       "	.long 2b,16b\n"
+	       "	.long 21b,16b\n"
+	       "	.long 3b,16b\n"
+	       "	.long 31b,16b\n"
+	       "	.long 4b,16b\n"
+	       "	.long 41b,16b\n"
+	       "	.long 10b,16b\n"
+	       "	.long 51b,16b\n"
+	       "	.long 11b,16b\n"
+	       "	.long 61b,16b\n"
+	       "	.long 12b,16b\n"
+	       "	.long 71b,16b\n"
+	       "	.long 13b,16b\n"
+	       "	.long 81b,16b\n"
+	       "	.long 14b,16b\n"
+	       "	.long 91b,16b\n"
+	       "	.long 6b,9b\n"
+	       "        .long 7b,16b\n"
+	       ".previous"
+	       : "=&c"(size), "=&D" (d0), "=&S" (d1)
+	       :  "1"(to), "2"(from), "0"(size)
+	       : "eax", "edx", "memory");
+	return size;
+}
+
 #else
+
 /*
  * Leave these declared but undefined.  They should not be any references to
  * them
  */
-unsigned long
-__copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size);
-unsigned long
-__copy_user_intel(void __user *to, const void *from, unsigned long size);
+unsigned long __copy_user_zeroing_intel(void *to, const void __user *from,
+					unsigned long size);
+unsigned long __copy_user_intel(void __user *to, const void *from,
+					unsigned long size);
+unsigned long __copy_user_zeroing_intel_nocache(void *to,
+				const void __user *from, unsigned long size);
 #endif /* CONFIG_X86_INTEL_USERCOPY */
 
 /* Generic arbitrary sized copy.  */
@@ -515,8 +712,8 @@
 		: "memory");						\
 } while (0)
 
-
-unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n)
+unsigned long __copy_to_user_ll(void __user *to, const void *from,
+				unsigned long n)
 {
 	BUG_ON((long) n < 0);
 #ifndef CONFIG_X86_WP_WORKS_OK
@@ -576,8 +773,8 @@
 }
 EXPORT_SYMBOL(__copy_to_user_ll);
 
-unsigned long
-__copy_from_user_ll(void *to, const void __user *from, unsigned long n)
+unsigned long __copy_from_user_ll(void *to, const void __user *from,
+					unsigned long n)
 {
 	BUG_ON((long)n < 0);
 	if (movsl_is_ok(to, from, n))
@@ -588,6 +785,49 @@
 }
 EXPORT_SYMBOL(__copy_from_user_ll);
 
+unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from,
+					 unsigned long n)
+{
+	BUG_ON((long)n < 0);
+	if (movsl_is_ok(to, from, n))
+		__copy_user(to, from, n);
+	else
+		n = __copy_user_intel((void __user *)to,
+				      (const void *)from, n);
+	return n;
+}
+EXPORT_SYMBOL(__copy_from_user_ll_nozero);
+
+unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
+					unsigned long n)
+{
+	BUG_ON((long)n < 0);
+#ifdef CONFIG_X86_INTEL_USERCOPY
+	if ( n > 64 && cpu_has_xmm2)
+                n = __copy_user_zeroing_intel_nocache(to, from, n);
+	else
+		__copy_user_zeroing(to, from, n);
+#else
+        __copy_user_zeroing(to, from, n);
+#endif
+	return n;
+}
+
+unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
+					unsigned long n)
+{
+	BUG_ON((long)n < 0);
+#ifdef CONFIG_X86_INTEL_USERCOPY
+	if ( n > 64 && cpu_has_xmm2)
+                n = __copy_user_intel_nocache(to, from, n);
+	else
+		__copy_user(to, from, n);
+#else
+        __copy_user(to, from, n);
+#endif
+	return n;
+}
+
 /**
  * copy_to_user: - Copy a block of data into user space.
  * @to:   Destination address, in user space.
diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c
index b4a7455..004837c 100644
--- a/arch/i386/mach-default/setup.c
+++ b/arch/i386/mach-default/setup.c
@@ -8,6 +8,8 @@
 #include <linux/interrupt.h>
 #include <asm/acpi.h>
 #include <asm/arch_hooks.h>
+#include <asm/e820.h>
+#include <asm/setup.h>
 
 #ifdef CONFIG_HOTPLUG_CPU
 #define DEFAULT_SEND_IPI	(1)
@@ -130,3 +132,44 @@
 }
 
 late_initcall(print_ipi_mode);
+
+/**
+ * machine_specific_memory_setup - Hook for machine specific memory setup.
+ *
+ * Description:
+ *	This is included late in kernel/setup.c so that it can make
+ *	use of all of the static functions.
+ **/
+
+char * __init machine_specific_memory_setup(void)
+{
+	char *who;
+
+
+	who = "BIOS-e820";
+
+	/*
+	 * Try to copy the BIOS-supplied E820-map.
+	 *
+	 * Otherwise fake a memory map; one section from 0k->640k,
+	 * the next section from 1mb->appropriate_mem_k
+	 */
+	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
+	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+		unsigned long mem_size;
+
+		/* compare results from other methods and take the greater */
+		if (ALT_MEM_K < EXT_MEM_K) {
+			mem_size = EXT_MEM_K;
+			who = "BIOS-88";
+		} else {
+			mem_size = ALT_MEM_K;
+			who = "BIOS-e801";
+		}
+
+		e820.nr_map = 0;
+		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+  	}
+	return who;
+}
diff --git a/arch/i386/mach-visws/setup.c b/arch/i386/mach-visws/setup.c
index 07fac7e..8a9e1a6 100644
--- a/arch/i386/mach-visws/setup.c
+++ b/arch/i386/mach-visws/setup.c
@@ -10,6 +10,8 @@
 #include <asm/fixmap.h>
 #include <asm/arch_hooks.h>
 #include <asm/io.h>
+#include <asm/e820.h>
+#include <asm/setup.h>
 #include "cobalt.h"
 #include "piix4.h"
 
@@ -133,3 +135,50 @@
 	/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
 	setup_irq(0, &irq0);
 }
+
+/* Hook for machine specific memory setup. */
+
+#define MB (1024 * 1024)
+
+static unsigned long sgivwfb_mem_phys;
+static unsigned long sgivwfb_mem_size;
+
+long long mem_size __initdata = 0;
+
+char * __init machine_specific_memory_setup(void)
+{
+	long long gfx_mem_size = 8 * MB;
+
+	mem_size = ALT_MEM_K;
+
+	if (!mem_size) {
+		printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n");
+		mem_size = 128 * MB;
+	}
+
+	/*
+	 * this hardcodes the graphics memory to 8 MB
+	 * it really should be sized dynamically (or at least
+	 * set as a boot param)
+	 */
+	if (!sgivwfb_mem_size) {
+		printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n");
+		sgivwfb_mem_size = 8 * MB;
+	}
+
+	/*
+	 * Trim to nearest MB
+	 */
+	sgivwfb_mem_size &= ~((1 << 20) - 1);
+	sgivwfb_mem_phys = mem_size - gfx_mem_size;
+
+	add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+	add_memory_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM);
+	add_memory_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED);
+
+	return "PROM";
+
+	/* Remove gcc warnings */
+	(void) sanitize_e820_map(NULL, NULL);
+	(void) copy_e820_map(NULL, 0);
+}
diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c
index 7d8a3ac..defc6eb 100644
--- a/arch/i386/mach-voyager/setup.c
+++ b/arch/i386/mach-voyager/setup.c
@@ -5,8 +5,11 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <asm/acpi.h>
 #include <asm/arch_hooks.h>
+#include <asm/voyager.h>
+#include <asm/e820.h>
+#include <asm/io.h>
+#include <asm/setup.h>
 
 void __init pre_intr_init_hook(void)
 {
@@ -24,8 +27,7 @@
 	smp_intr_init();
 #endif
 
-	if (!acpi_ioapic)
-		setup_irq(2, &irq2);
+	setup_irq(2, &irq2);
 }
 
 void __init pre_setup_arch_hook(void)
@@ -45,3 +47,74 @@
 {
 	setup_irq(0, &irq0);
 }
+
+/* Hook for machine specific memory setup. */
+
+char * __init machine_specific_memory_setup(void)
+{
+	char *who;
+
+	who = "NOT VOYAGER";
+
+	if(voyager_level == 5) {
+		__u32 addr, length;
+		int i;
+
+		who = "Voyager-SUS";
+
+		e820.nr_map = 0;
+		for(i=0; voyager_memory_detect(i, &addr, &length); i++) {
+			add_memory_region(addr, length, E820_RAM);
+		}
+		return who;
+	} else if(voyager_level == 4) {
+		__u32 tom;
+		__u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT)<<8;
+		/* select the DINO config space */
+		outb(VOYAGER_DINO, VOYAGER_CAT_CONFIG_PORT);
+		/* Read DINO top of memory register */
+		tom = ((inb(catbase + 0x4) & 0xf0) << 16)
+			+ ((inb(catbase + 0x5) & 0x7f) << 24);
+
+		if(inb(catbase) != VOYAGER_DINO) {
+			printk(KERN_ERR "Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K\n");
+			tom = (EXT_MEM_K)<<10;
+		}
+		who = "Voyager-TOM";
+		add_memory_region(0, 0x9f000, E820_RAM);
+		/* map from 1M to top of memory */
+		add_memory_region(1*1024*1024, tom - 1*1024*1024, E820_RAM);
+		/* FIXME: Should check the ASICs to see if I need to
+		 * take out the 8M window.  Just do it at the moment
+		 * */
+		add_memory_region(8*1024*1024, 8*1024*1024, E820_RESERVED);
+		return who;
+	}
+
+	who = "BIOS-e820";
+
+	/*
+	 * Try to copy the BIOS-supplied E820-map.
+	 *
+	 * Otherwise fake a memory map; one section from 0k->640k,
+	 * the next section from 1mb->appropriate_mem_k
+	 */
+	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
+	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
+		unsigned long mem_size;
+
+		/* compare results from other methods and take the greater */
+		if (ALT_MEM_K < EXT_MEM_K) {
+			mem_size = EXT_MEM_K;
+			who = "BIOS-88";
+		} else {
+			mem_size = ALT_MEM_K;
+			who = "BIOS-e801";
+		}
+
+		e820.nr_map = 0;
+		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
+		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
+  	}
+	return who;
+}
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 70e560a..8242af9 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -661,6 +661,7 @@
 		print_cpu_info(&cpu_data[cpu]);
 		wmb();
 		cpu_set(cpu, cpu_callout_map);
+		cpu_set(cpu, cpu_present_map);
 	}
 	else {
 		printk("CPU%d FAILED TO BOOT: ", cpu);
@@ -1912,6 +1913,7 @@
 	cpu_set(smp_processor_id(), cpu_online_map);
 	cpu_set(smp_processor_id(), cpu_callout_map);
 	cpu_set(smp_processor_id(), cpu_possible_map);
+	cpu_set(smp_processor_id(), cpu_present_map);
 }
 
 int __devinit
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index 7f0fcf2..6ee7faa 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -30,6 +30,40 @@
 
 extern void die(const char *,struct pt_regs *,long);
 
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+int register_page_fault_notifier(struct notifier_block *nb)
+{
+	vmalloc_sync_all();
+	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+}
+
+int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+}
+
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	struct die_args args = {
+		.regs = regs,
+		.str = str,
+		.err = err,
+		.trapnr = trap,
+		.signr = sig
+	};
+	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	return NOTIFY_DONE;
+}
+#endif
+
+
 /*
  * Unlock any spinlocks which will prevent us from getting the
  * message out 
@@ -77,12 +111,15 @@
 	unsigned seg = regs->xcs & 0xffff;
 	u32 seg_ar, seg_limit, base, *desc;
 
+	/* Unlikely, but must come before segment checks. */
+	if (unlikely(regs->eflags & VM_MASK)) {
+		base = seg << 4;
+		*eip_limit = base + 0xffff;
+		return base + (eip & 0xffff);
+	}
+
 	/* The standard kernel/user address space limit. */
 	*eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg;
-
-	/* Unlikely, but must come before segment checks. */
-	if (unlikely((regs->eflags & VM_MASK) != 0))
-		return eip + (seg << 4);
 	
 	/* By far the most common cases. */
 	if (likely(seg == __USER_CS || seg == __KERNEL_CS))
@@ -321,7 +358,7 @@
 	if (unlikely(address >= TASK_SIZE)) {
 		if (!(error_code & 0x0000000d) && vmalloc_fault(address) >= 0)
 			return;
-		if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
 						SIGSEGV) == NOTIFY_STOP)
 			return;
 		/*
@@ -331,7 +368,7 @@
 		goto bad_area_nosemaphore;
 	}
 
-	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
 					SIGSEGV) == NOTIFY_STOP)
 		return;
 
@@ -380,12 +417,12 @@
 		goto bad_area;
 	if (error_code & 4) {
 		/*
-		 * accessing the stack below %esp is always a bug.
-		 * The "+ 32" is there due to some instructions (like
-		 * pusha) doing post-decrement on the stack and that
-		 * doesn't show up until later..
+		 * Accessing the stack below %esp is always a bug.
+		 * The large cushion allows instructions like enter
+		 * and pusha to work.  ("enter $65535,$31" pushes
+		 * 32 pointers and then decrements %esp by 65535.)
 		 */
-		if (address + 32 < regs->esp)
+		if (address + 65536 + 32 * sizeof(unsigned long) < regs->esp)
 			goto bad_area;
 	}
 	if (expand_stack(vma, address))
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 3df1371..f84b16e 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -23,12 +23,14 @@
 #include <linux/init.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/poison.h>
 #include <linux/bootmem.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/efi.h>
 #include <linux/memory_hotplug.h>
 #include <linux/initrd.h>
+#include <linux/cpumask.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -384,7 +386,7 @@
 #endif
 }
 
-#ifdef CONFIG_SOFTWARE_SUSPEND
+#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_ACPI_SLEEP)
 /*
  * Swap suspend & friends need this for resume because things like the intel-agp
  * driver might have split up a kernel 4MB mapping.
@@ -653,7 +655,7 @@
  */
 #ifdef CONFIG_MEMORY_HOTPLUG
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-int add_memory(u64 start, u64 size)
+int arch_add_memory(int nid, u64 start, u64 size)
 {
 	struct pglist_data *pgdata = &contig_page_data;
 	struct zone *zone = pgdata->node_zones + MAX_NR_ZONES-1;
@@ -752,7 +754,7 @@
 	for (addr = begin; addr < end; addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
-		memset((void *)addr, 0xcc, PAGE_SIZE);
+		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
 		free_page(addr);
 		totalram_pages++;
 	}
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 92c3d9f..353a836 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -209,19 +209,19 @@
 }
 
 void global_flush_tlb(void)
-{ 
-	LIST_HEAD(l);
+{
+	struct list_head l;
 	struct page *pg, *next;
 
 	BUG_ON(irqs_disabled());
 
 	spin_lock_irq(&cpa_lock);
-	list_splice_init(&df_list, &l);
+	list_replace_init(&df_list, &l);
 	spin_unlock_irq(&cpa_lock);
 	flush_map();
 	list_for_each_entry_safe(pg, next, &l, lru)
 		__free_page(pg);
-} 
+}
 
 #ifdef CONFIG_DEBUG_PAGEALLOC
 void kernel_map_pages(struct page *page, int numpages, int enable)
@@ -229,8 +229,8 @@
 	if (PageHighMem(page))
 		return;
 	if (!enable)
-		mutex_debug_check_no_locks_freed(page_address(page),
-						 numpages * PAGE_SIZE);
+		debug_check_no_locks_freed(page_address(page),
+					   numpages * PAGE_SIZE);
 
 	/* the return value is ignored - the calls cannot fail,
 	 * large pages are disabled at boot time.
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index ec0fd3c..fa8a37b 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -281,9 +281,9 @@
 
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry * dir;
-		char buf[2];
+		char buf[4];
  
-		snprintf(buf, 2, "%d", i);
+		snprintf(buf,  sizeof(buf), "%d", i);
 		dir = oprofilefs_mkdir(sb, root, buf);
 		oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled); 
 		oprofilefs_create_ulong(sb, dir, "event", &counter_config[i].event); 
diff --git a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
index 3ad9a72..693bdea 100644
--- a/arch/i386/oprofile/op_model_athlon.c
+++ b/arch/i386/oprofile/op_model_athlon.c
@@ -13,6 +13,7 @@
 #include <linux/oprofile.h>
 #include <asm/ptrace.h>
 #include <asm/msr.h>
+#include <asm/nmi.h>
  
 #include "op_x86_model.h"
 #include "op_counter.h"
diff --git a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c
index ac8a066..7c61d35 100644
--- a/arch/i386/oprofile/op_model_p4.c
+++ b/arch/i386/oprofile/op_model_p4.c
@@ -14,6 +14,7 @@
 #include <asm/ptrace.h>
 #include <asm/fixmap.h>
 #include <asm/apic.h>
+#include <asm/nmi.h>
 
 #include "op_x86_model.h"
 #include "op_counter.h"
diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
index d719015..5c3ab4b 100644
--- a/arch/i386/oprofile/op_model_ppro.c
+++ b/arch/i386/oprofile/op_model_ppro.c
@@ -14,6 +14,7 @@
 #include <asm/ptrace.h>
 #include <asm/msr.h>
 #include <asm/apic.h>
+#include <asm/nmi.h>
  
 #include "op_x86_model.h"
 #include "op_counter.h"
diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c
index dbece77..c624b61 100644
--- a/arch/i386/pci/common.c
+++ b/arch/i386/pci/common.c
@@ -288,6 +288,7 @@
 
 void pcibios_disable_device (struct pci_dev *dev)
 {
+	pcibios_disable_resources(dev);
 	if (pcibios_disable_irq)
 		pcibios_disable_irq(dev);
 }
diff --git a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c
index ed2c8c8..a151f7a 100644
--- a/arch/i386/pci/i386.c
+++ b/arch/i386/pci/i386.c
@@ -242,6 +242,15 @@
 	return 0;
 }
 
+void pcibios_disable_resources(struct pci_dev *dev)
+{
+	u16 cmd;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+}
+
 /*
  *  If we set up a device for bus mastering, we need to check the latency
  *  timer as certain crappy BIOSes forget to set it properly.
@@ -276,8 +285,6 @@
 	/* Leave vm_pgoff as-is, the PCI space address is the physical
 	 * address on this platform.
 	 */
-	vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
-
 	prot = pgprot_val(vma->vm_page_prot);
 	if (boot_cpu_data.x86 > 3)
 		prot |= _PAGE_PCD | _PAGE_PWT;
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 06dab00..8ce6950 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -198,14 +198,14 @@
  */
 static int pirq_ali_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	static unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
+	static const unsigned char irqmap[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 1, 11, 0, 12, 0, 14, 0, 15 };
 
 	return irqmap[read_config_nybble(router, 0x48, pirq-1)];
 }
 
 static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	static unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
+	static const unsigned char irqmap[16] = { 0, 8, 0, 2, 4, 5, 7, 6, 0, 1, 3, 9, 11, 0, 13, 15 };
 	unsigned int val = irqmap[irq];
 		
 	if (val) {
@@ -256,13 +256,13 @@
  */
 static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+	static const unsigned int pirqmap[4] = { 3, 2, 5, 1 };
 	return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
 }
 
 static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
 {
-	static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+	static const unsigned int pirqmap[4] = { 3, 2, 5, 1 };
 	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
 	return 1;
 }
@@ -274,13 +274,13 @@
  */
 static int pirq_ite_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-	static unsigned char pirqmap[4] = { 1, 0, 2, 3 };
+	static const 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 };
+	static const unsigned char pirqmap[4] = { 1, 0, 2, 3 };
 	write_config_nybble(router, 0x43, pirqmap[pirq-1], irq);
 	return 1;
 }
@@ -505,7 +505,7 @@
 
 static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
 {
-	static struct pci_device_id pirq_440gx[] = {
+	static struct pci_device_id __initdata pirq_440gx[] = {
 		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
 		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
 		{ },
@@ -880,6 +880,7 @@
 	((!(pci_probe & PCI_USE_PIRQ_MASK)) || ((1 << irq) & mask)) ) {
 		DBG(" -> got IRQ %d\n", irq);
 		msg = "Found";
+		eisa_set_level_irq(irq);
 	} else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
 		DBG(" -> assigning IRQ %d", newirq);
 		if (r->set(pirq_router_dev, dev, pirq, newirq)) {
diff --git a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
index 6b1ea0c..e545b09 100644
--- a/arch/i386/pci/mmconfig.c
+++ b/arch/i386/pci/mmconfig.c
@@ -15,7 +15,9 @@
 #include <asm/e820.h>
 #include "pci.h"
 
-#define MMCONFIG_APER_SIZE (256*1024*1024)
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN	(2 * 1024*1024)
+#define MMCONFIG_APER_MAX	(256 * 1024*1024)
 
 /* Assume systems with more busses have correct MCFG */
 #define MAX_CHECK_BUS 16
@@ -197,9 +199,10 @@
 		return;
 
 	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-			pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
 			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
+				pci_mmcfg_config[0].base_address);
 		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
 		return;
 	}
diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
index 1eec086..ed1512a 100644
--- a/arch/i386/pci/pcbios.c
+++ b/arch/i386/pci/pcbios.c
@@ -371,8 +371,7 @@
 			list_for_each(ln, &pci_devices) {
 				d = pci_dev_g(ln);
 				if (d->bus->number == bus && d->devfn == devfn) {
-					list_del(&d->global_list);
-					list_add_tail(&d->global_list, &sorted_devices);
+					list_move_tail(&d->global_list, &sorted_devices);
 					if (d == dev)
 						found = 1;
 					break;
@@ -390,8 +389,7 @@
 		if (!found) {
 			printk(KERN_WARNING "PCI: Device %s not found by BIOS\n",
 				pci_name(dev));
-			list_del(&dev->global_list);
-			list_add_tail(&dev->global_list, &sorted_devices);
+			list_move_tail(&dev->global_list, &sorted_devices);
 		}
 	}
 	list_splice(&sorted_devices, &pci_devices);
diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h
index 12035e2..12bf3d8 100644
--- a/arch/i386/pci/pci.h
+++ b/arch/i386/pci/pci.h
@@ -35,6 +35,7 @@
 
 void pcibios_resource_survey(void);
 int pcibios_enable_resources(struct pci_dev *, int);
+void pcibios_disable_resources(struct pci_dev *);
 
 /* pci-pc.c */
 
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index 79b2370..e651791 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -10,6 +10,8 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/suspend.h>
+#include <asm/mtrr.h>
+#include <asm/mce.h>
 
 static struct saved_context saved_context;
 
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 0f3076a..a56df7b 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -77,6 +77,7 @@
 config IA64_GENERIC
 	bool "generic"
 	select ACPI
+	select PCI
 	select NUMA
 	select ACPI_NUMA
 	help
@@ -273,7 +274,6 @@
 config SCHED_SMT
 	bool "SMT scheduler support"
 	depends on SMP
-	default off
 	help
 	  Improves the CPU scheduler's decision making when dealing with
 	  Intel IA64 chips with MultiThreading at a cost of slightly increased
@@ -374,6 +374,10 @@
 	def_bool y
 	depends on NEED_MULTIPLE_NODES
 
+config HAVE_ARCH_NODEDATA_EXTENSION
+	def_bool y
+	depends on NUMA
+
 config IA32_SUPPORT
 	bool "Support for Linux/x86 binaries"
 	help
@@ -449,6 +453,8 @@
 	bool
 	default PCI
 
+source "drivers/pci/pcie/Kconfig"
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile
index 80ea750..21033ed 100644
--- a/arch/ia64/Makefile
+++ b/arch/ia64/Makefile
@@ -71,6 +71,8 @@
 
 compressed: vmlinux.gz
 
+vmlinuz: vmlinux.gz
+
 vmlinux.gz: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $@
 
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 766bf49..9d1cffb 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -114,7 +114,7 @@
 CONFIG_IOSAPIC=y
 CONFIG_FORCE_MAX_ZONEORDER=17
 CONFIG_SMP=y
-CONFIG_NR_CPUS=4
+CONFIG_NR_CPUS=16
 CONFIG_HOTPLUG_CPU=y
 CONFIG_PERMIT_BSP_REMOVE=y
 CONFIG_FORCE_CPEI_RETARGET=y
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index bdccd0b..5825dde 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1958,7 +1958,7 @@
 	if (pxm < 0)
 		return;
 
-	node = pxm_to_nid_map[pxm];
+	node = pxm_to_node(pxm);
 
 	if (node >= MAX_NUMNODES || !node_online(node))
 		return;
@@ -1999,7 +1999,7 @@
 		if (!iovp_shift)
 			iovp_shift = min(PAGE_SHIFT, 16);
 	}
-	ACPI_MEM_FREE(dev_info);
+	kfree(dev_info);
 
 	/*
 	 * default anything not caught above or specified on cmdline to 4k
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 58c93a3..ca16d95 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -68,8 +68,6 @@
 unsigned char acpi_kbd_controller_present = 1;
 unsigned char acpi_legacy_devices;
 
-static unsigned int __initdata acpi_madt_rev;
-
 unsigned int acpi_cpei_override;
 unsigned int acpi_cpei_phys_cpuid;
 
@@ -243,6 +241,8 @@
 	return iosapic_init(iosapic->address, iosapic->global_irq_base);
 }
 
+static unsigned int __initdata acpi_madt_rev;
+
 static int __init
 acpi_parse_plat_int_src(acpi_table_entry_header * header,
 			const unsigned long end)
@@ -415,9 +415,6 @@
 static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
 #define pxm_bit_set(bit)	(set_bit(bit,(void *)pxm_flag))
 #define pxm_bit_test(bit)	(test_bit(bit,(void *)pxm_flag))
-/* maps to convert between proximity domain and logical node ID */
-int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS];
-int __initdata nid_to_pxm_map[MAX_NUMNODES];
 static struct acpi_table_slit __initdata *slit_table;
 
 static int get_processor_proximity_domain(struct acpi_table_processor_affinity *pa)
@@ -533,22 +530,17 @@
 	 * MCD - This can probably be dropped now.  No need for pxm ID to node ID
 	 * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES.
 	 */
-	/* calculate total number of nodes in system from PXM bitmap */
-	memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
-	memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
 	nodes_clear(node_online_map);
 	for (i = 0; i < MAX_PXM_DOMAINS; i++) {
 		if (pxm_bit_test(i)) {
-			int nid = num_online_nodes();
-			pxm_to_nid_map[i] = nid;
-			nid_to_pxm_map[nid] = i;
+			int nid = acpi_map_pxm_to_node(i);
 			node_set_online(nid);
 		}
 	}
 
 	/* set logical node id in memory chunk structure */
 	for (i = 0; i < num_node_memblks; i++)
-		node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];
+		node_memblk[i].nid = pxm_to_node(node_memblk[i].nid);
 
 	/* assign memory bank numbers for each chunk on each node */
 	for_each_online_node(i) {
@@ -562,7 +554,7 @@
 
 	/* set logical node id in cpu structure */
 	for (i = 0; i < srat_num_cpus; i++)
-		node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
+		node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid);
 
 	printk(KERN_INFO "Number of logical nodes in system = %d\n",
 	       num_online_nodes());
@@ -575,11 +567,11 @@
 	for (i = 0; i < slit_table->localities; i++) {
 		if (!pxm_bit_test(i))
 			continue;
-		node_from = pxm_to_nid_map[i];
+		node_from = pxm_to_node(i);
 		for (j = 0; j < slit_table->localities; j++) {
 			if (!pxm_bit_test(j))
 				continue;
-			node_to = pxm_to_nid_map[j];
+			node_to = pxm_to_node(j);
 			node_distance(node_from, node_to) =
 			    slit_table->entry[i * slit_table->localities + j];
 		}
@@ -626,7 +618,7 @@
 static int __init acpi_parse_fadt(unsigned long phys_addr, unsigned long size)
 {
 	struct acpi_table_header *fadt_header;
-	struct fadt_descriptor_rev2 *fadt;
+	struct fadt_descriptor *fadt;
 
 	if (!phys_addr || !size)
 		return -EINVAL;
@@ -635,7 +627,7 @@
 	if (fadt_header->revision != 3)
 		return -ENODEV;	/* Only deal with ACPI 2.0 FADT */
 
-	fadt = (struct fadt_descriptor_rev2 *)fadt_header;
+	fadt = (struct fadt_descriptor *)fadt_header;
 
 	if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
 		acpi_kbd_controller_present = 0;
@@ -785,9 +777,9 @@
 
 	/*
 	 * Assuming that the container driver would have set the proximity
-	 * domain and would have initialized pxm_to_nid_map[pxm_id] && pxm_flag
+	 * domain and would have initialized pxm_to_node(pxm_id) && pxm_flag
 	 */
-	node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_nid_map[pxm_id];
+	node_cpuid[cpu].nid = (pxm_id < 0) ? 0 : pxm_to_node(pxm_id);
 
 	node_cpuid[cpu].phys_id = physid;
 #endif
@@ -966,7 +958,7 @@
 	if (pxm < 0)
 		return AE_OK;
 
-	node = pxm_to_nid_map[pxm];
+	node = pxm_to_node(pxm);
 
 	if (node >= MAX_NUMNODES || !node_online(node) ||
 	    cpus_empty(node_to_cpumask(node)))
diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c
index 7722565..16e7b66 100644
--- a/arch/ia64/kernel/asm-offsets.c
+++ b/arch/ia64/kernel/asm-offsets.c
@@ -217,16 +217,24 @@
 	DEFINE(IA64_MCA_CPU_INIT_STACK_OFFSET,
 	       offsetof (struct ia64_mca_cpu, init_stack));
 	BLANK();
-	DEFINE(IA64_SAL_OS_STATE_COMMON_OFFSET,
-	       offsetof (struct ia64_sal_os_state, sal_ra));
 	DEFINE(IA64_SAL_OS_STATE_OS_GP_OFFSET,
 	       offsetof (struct ia64_sal_os_state, os_gp));
-	DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET,
-	       offsetof (struct ia64_sal_os_state, pal_min_state));
 	DEFINE(IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET,
 	       offsetof (struct ia64_sal_os_state, proc_state_param));
+	DEFINE(IA64_SAL_OS_STATE_SAL_RA_OFFSET,
+	       offsetof (struct ia64_sal_os_state, sal_ra));
+	DEFINE(IA64_SAL_OS_STATE_SAL_GP_OFFSET,
+	       offsetof (struct ia64_sal_os_state, sal_gp));
+	DEFINE(IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET,
+	       offsetof (struct ia64_sal_os_state, pal_min_state));
+	DEFINE(IA64_SAL_OS_STATE_OS_STATUS_OFFSET,
+	       offsetof (struct ia64_sal_os_state, os_status));
+	DEFINE(IA64_SAL_OS_STATE_CONTEXT_OFFSET,
+	       offsetof (struct ia64_sal_os_state, context));
 	DEFINE(IA64_SAL_OS_STATE_SIZE,
 	       sizeof (struct ia64_sal_os_state));
+	BLANK();
+
 	DEFINE(IA64_PMSA_GR_OFFSET,
 	       offsetof (struct pal_min_state_area_s, pmsa_gr));
 	DEFINE(IA64_PMSA_BANK1_GR_OFFSET,
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 12cfedc..c33d0ba 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -8,6 +8,8 @@
  * Copyright (C) 1999-2003 Hewlett-Packard Co.
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  *	Stephane Eranian <eranian@hpl.hp.com>
+ * (c) Copyright 2006 Hewlett-Packard Development Company, L.P.
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  *
  * All EFI Runtime Services are not implemented yet as EFI only
  * supports physical mode addressing on SoftSDV. This is to be fixed
@@ -622,6 +624,18 @@
 	return 0;
 }
 
+static struct kern_memdesc *
+kern_memory_descriptor (unsigned long phys_addr)
+{
+	struct kern_memdesc *md;
+
+	for (md = kern_memmap; md->start != ~0UL; md++) {
+		if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT))
+			 return md;
+	}
+	return 0;
+}
+
 static efi_memory_desc_t *
 efi_memory_descriptor (unsigned long phys_addr)
 {
@@ -642,26 +656,6 @@
 	return 0;
 }
 
-static int
-efi_memmap_has_mmio (void)
-{
-	void *efi_map_start, *efi_map_end, *p;
-	efi_memory_desc_t *md;
-	u64 efi_desc_size;
-
-	efi_map_start = __va(ia64_boot_param->efi_memmap);
-	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
-	efi_desc_size = ia64_boot_param->efi_memdesc_size;
-
-	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
-		md = p;
-
-		if (md->type == EFI_MEMORY_MAPPED_IO)
-			return 1;
-	}
-	return 0;
-}
-
 u32
 efi_mem_type (unsigned long phys_addr)
 {
@@ -683,71 +677,125 @@
 }
 EXPORT_SYMBOL(efi_mem_attributes);
 
-/*
- * Determines whether the memory at phys_addr supports the desired
- * attribute (WB, UC, etc).  If this returns 1, the caller can safely
- * access size bytes at phys_addr with the specified attribute.
- */
-int
-efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, u64 attr)
+u64
+efi_mem_attribute (unsigned long phys_addr, unsigned long size)
 {
 	unsigned long end = phys_addr + size;
 	efi_memory_desc_t *md = efi_memory_descriptor(phys_addr);
+	u64 attr;
+
+	if (!md)
+		return 0;
 
 	/*
-	 * Some firmware doesn't report MMIO regions in the EFI memory
-	 * map.  The Intel BigSur (a.k.a. HP i2000) has this problem.
-	 * On those platforms, we have to assume UC is valid everywhere.
+	 * EFI_MEMORY_RUNTIME is not a memory attribute; it just tells
+	 * the kernel that firmware needs this region mapped.
 	 */
-	if (!md || (md->attribute & attr) != attr) {
-		if (attr == EFI_MEMORY_UC && !efi_memmap_has_mmio())
-			return 1;
-		return 0;
-	}
-
+	attr = md->attribute & ~EFI_MEMORY_RUNTIME;
 	do {
 		unsigned long md_end = efi_md_end(md);
 
 		if (end <= md_end)
-			return 1;
+			return attr;
 
 		md = efi_memory_descriptor(md_end);
-		if (!md || (md->attribute & attr) != attr)
+		if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr)
 			return 0;
 	} while (md);
 	return 0;
 }
 
-/*
- * For /dev/mem, we only allow read & write system calls to access
- * write-back memory, because read & write don't allow the user to
- * control access size.
- */
+u64
+kern_mem_attribute (unsigned long phys_addr, unsigned long size)
+{
+	unsigned long end = phys_addr + size;
+	struct kern_memdesc *md;
+	u64 attr;
+
+	/*
+	 * This is a hack for ioremap calls before we set up kern_memmap.
+	 * Maybe we should do efi_memmap_init() earlier instead.
+	 */
+	if (!kern_memmap) {
+		attr = efi_mem_attribute(phys_addr, size);
+		if (attr & EFI_MEMORY_WB)
+			return EFI_MEMORY_WB;
+		return 0;
+	}
+
+	md = kern_memory_descriptor(phys_addr);
+	if (!md)
+		return 0;
+
+	attr = md->attribute;
+	do {
+		unsigned long md_end = kmd_end(md);
+
+		if (end <= md_end)
+			return attr;
+
+		md = kern_memory_descriptor(md_end);
+		if (!md || md->attribute != attr)
+			return 0;
+	} while (md);
+	return 0;
+}
+EXPORT_SYMBOL(kern_mem_attribute);
+
 int
 valid_phys_addr_range (unsigned long phys_addr, unsigned long size)
 {
-	return efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB);
+	u64 attr;
+
+	/*
+	 * /dev/mem reads and writes use copy_to_user(), which implicitly
+	 * uses a granule-sized kernel identity mapping.  It's really
+	 * only safe to do this for regions in kern_memmap.  For more
+	 * details, see Documentation/ia64/aliasing.txt.
+	 */
+	attr = kern_mem_attribute(phys_addr, size);
+	if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC)
+		return 1;
+	return 0;
 }
 
-/*
- * We allow mmap of anything in the EFI memory map that supports
- * either write-back or uncacheable access.  For uncacheable regions,
- * the supported access sizes are system-dependent, and the user is
- * responsible for using the correct size.
- *
- * Note that this doesn't currently allow access to hot-added memory,
- * because that doesn't appear in the boot-time EFI memory map.
- */
 int
 valid_mmap_phys_addr_range (unsigned long phys_addr, unsigned long size)
 {
-	if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_WB))
-		return 1;
+	/*
+	 * MMIO regions are often missing from the EFI memory map.
+	 * We must allow mmap of them for programs like X, so we
+	 * currently can't do any useful validation.
+	 */
+	return 1;
+}
 
-	if (efi_mem_attribute_range(phys_addr, size, EFI_MEMORY_UC))
-		return 1;
+pgprot_t
+phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size,
+		     pgprot_t vma_prot)
+{
+	unsigned long phys_addr = pfn << PAGE_SHIFT;
+	u64 attr;
 
-	return 0;
+	/*
+	 * For /dev/mem mmap, we use user mappings, but if the region is
+	 * in kern_memmap (and hence may be covered by a kernel mapping),
+	 * we must use the same attribute as the kernel mapping.
+	 */
+	attr = kern_mem_attribute(phys_addr, size);
+	if (attr & EFI_MEMORY_WB)
+		return pgprot_cacheable(vma_prot);
+	else if (attr & EFI_MEMORY_UC)
+		return pgprot_noncached(vma_prot);
+
+	/*
+	 * Some chipsets don't support UC access to memory.  If
+	 * WB is supported, we prefer that.
+	 */
+	if (efi_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
+		return pgprot_cacheable(vma_prot);
+
+	return pgprot_noncached(vma_prot);
 }
 
 int __init
diff --git a/arch/ia64/kernel/efi_stub.S b/arch/ia64/kernel/efi_stub.S
index 5a7fe70..a56e161 100644
--- a/arch/ia64/kernel/efi_stub.S
+++ b/arch/ia64/kernel/efi_stub.S
@@ -61,7 +61,7 @@
 	or loc3=loc3,r17
 	mov b6=r2
 	;;
-	andcm r16=loc3,r16		// get psr with IT, DT, and RT bits cleared
+	andcm r16=loc3,r16	// get psr with IT, DT, and RT bits cleared
 	br.call.sptk.many rp=ia64_switch_mode_phys
 .ret0:	mov out4=in5
 	mov out0=in1
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index bcb80ca..32c999f 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1584,7 +1584,7 @@
 	data8 sys_keyctl
 	data8 sys_ioprio_set
 	data8 sys_ioprio_get			// 1275
-	data8 sys_ni_syscall
+	data8 sys_move_pages
 	data8 sys_inotify_init
 	data8 sys_inotify_add_watch
 	data8 sys_inotify_rm_watch
diff --git a/arch/ia64/kernel/entry.h b/arch/ia64/kernel/entry.h
index 78eeb07..ebc3dfb 100644
--- a/arch/ia64/kernel/entry.h
+++ b/arch/ia64/kernel/entry.h
@@ -23,6 +23,7 @@
 
 #define PT(f)		(IA64_PT_REGS_##f##_OFFSET)
 #define SW(f)		(IA64_SWITCH_STACK_##f##_OFFSET)
+#define SOS(f)		(IA64_SAL_OS_STATE_##f##_OFFSET)
 
 #define PT_REGS_SAVES(off)			\
 	.unwabi 3, 'i';				\
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 6c4d59f..ef9a2b4 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -46,6 +46,10 @@
 
 #define IRQ_DEBUG	0
 
+/* These can be overridden in platform_irq_init */
+int ia64_first_device_vector = IA64_DEF_FIRST_DEVICE_VECTOR;
+int ia64_last_device_vector = IA64_DEF_LAST_DEVICE_VECTOR;
+
 /* default base addr of IPI table */
 void __iomem *ipi_base_addr = ((void __iomem *)
 			       (__IA64_UNCACHED_OFFSET | IA64_IPI_DEFAULT_BASE_ADDR));
@@ -60,7 +64,7 @@
 };
 EXPORT_SYMBOL(isa_irq_to_vector_map);
 
-static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
+static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_MAX_DEVICE_VECTORS)];
 
 int
 assign_irq_vector (int irq)
@@ -89,6 +93,19 @@
 		printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
 }
 
+int
+reserve_irq_vector (int vector)
+{
+	int pos;
+
+	if (vector < IA64_FIRST_DEVICE_VECTOR ||
+	    vector > IA64_LAST_DEVICE_VECTOR)
+		return -EINVAL;
+
+	pos = vector - IA64_FIRST_DEVICE_VECTOR;
+	return test_and_set_bit(pos, ia64_vector_mask);
+}
+
 #ifdef CONFIG_SMP
 #	define IS_RESCHEDULE(vec)	(vec == IA64_IPI_RESCHEDULE)
 #else
diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
index 6dff024..c1bd1fe 100644
--- a/arch/ia64/kernel/mca_asm.S
+++ b/arch/ia64/kernel/mca_asm.S
@@ -159,7 +159,7 @@
 	GET_IA64_MCA_DATA(r2)
 	// Using MCA stack, struct ia64_sal_os_state, variable proc_state_param
 	;;
-	add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PROC_STATE_PARAM_OFFSET, r2
+	add r3=IA64_MCA_CPU_MCA_STACK_OFFSET+MCA_SOS_OFFSET+SOS(PROC_STATE_PARAM), r2
 	;;
 	ld8 r18=[r3]				// Get processor state parameter on existing PALE_CHECK.
 	;;
@@ -479,9 +479,11 @@
 	st8 [temp2]=r11,16	// rv_rc
 	mov r11=cr.iipa
 	;;
-	st8 [temp1]=r18,16	// proc_state_param
-	st8 [temp2]=r19,16	// monarch
+	st8 [temp1]=r18		// proc_state_param
+	st8 [temp2]=r19		// monarch
 	mov r6=IA64_KR(CURRENT)
+	add temp1=SOS(SAL_RA), regs
+	add temp2=SOS(SAL_GP), regs
 	;;
 	st8 [temp1]=r12,16	// sal_ra
 	st8 [temp2]=r10,16	// sal_gp
@@ -503,12 +505,14 @@
 	st8 [temp2]=r11,16	// cr.iipa
 	mov r12=cr.iim
 	;;
-	st8 [temp1]=r12,16	// cr.iim
+	st8 [temp1]=r12		// cr.iim
 (p1)	mov r12=IA64_MCA_COLD_BOOT
 (p2)	mov r12=IA64_INIT_WARM_BOOT
 	mov r6=cr.iha
+	add temp1=SOS(OS_STATUS), regs
 	;;
-	st8 [temp2]=r6,16	// cr.iha
+	st8 [temp2]=r6		// cr.iha
+	add temp2=SOS(CONTEXT), regs
 	st8 [temp1]=r12		// os_status, default is cold boot
 	mov r6=IA64_MCA_SAME_CONTEXT
 	;;
@@ -820,8 +824,8 @@
 	// Restore the SAL to OS state. The previous code left regs at pt_regs.
 	add regs=MCA_SOS_OFFSET-MCA_PT_REGS_OFFSET, regs
 	;;
-	add temp1=IA64_SAL_OS_STATE_COMMON_OFFSET, regs
-	add temp2=IA64_SAL_OS_STATE_COMMON_OFFSET+8, regs
+	add temp1=SOS(SAL_RA), regs
+	add temp2=SOS(SAL_GP), regs
 	;;
 	ld8 r12=[temp1],16	// sal_ra
 	ld8 r9=[temp2],16	// sal_gp
@@ -842,8 +846,10 @@
 	;;
 	mov cr.itir=temp3
 	mov cr.iipa=temp4
-	ld8 temp3=[temp1],16	// cr.iim
-	ld8 temp4=[temp2],16	// cr.iha
+	ld8 temp3=[temp1]	// cr.iim
+	ld8 temp4=[temp2]		// cr.iha
+	add temp1=SOS(OS_STATUS), regs
+	add temp2=SOS(CONTEXT), regs
 	;;
 	mov cr.iim=temp3
 	mov cr.iha=temp4
@@ -916,7 +922,7 @@
 
 ia64_new_stack:
 	add regs=MCA_PT_REGS_OFFSET, r3
-	add temp2=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_PAL_MIN_STATE_OFFSET, r3
+	add temp2=MCA_SOS_OFFSET+SOS(PAL_MIN_STATE), r3
 	mov b0=r2			// save return address
 	GET_IA64_MCA_DATA(temp1)
 	invala
@@ -1020,7 +1026,7 @@
 
 ia64_set_kernel_registers:
 	add temp3=MCA_SP_OFFSET, r3
-	add temp4=MCA_SOS_OFFSET+IA64_SAL_OS_STATE_OS_GP_OFFSET, r3
+	add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3
 	mov b0=r2		// save return address
 	GET_IA64_MCA_DATA(temp1)
 	;;
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 859fb37..8a12084 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -959,7 +959,7 @@
 	}
 }
 
-static int palinfo_cpu_callback(struct notifier_block *nfb,
+static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
 								unsigned long action,
 								void *hcpu)
 {
@@ -978,7 +978,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block palinfo_cpu_notifier =
+static struct notifier_block __cpuinitdata palinfo_cpu_notifier =
 {
 	.notifier_call = palinfo_cpu_callback,
 	.priority = 0,
@@ -998,7 +998,7 @@
 	}
 
 	/* Register for future delivery via notify registration */
-	register_cpu_notifier(&palinfo_cpu_notifier);
+	register_hotcpu_notifier(&palinfo_cpu_notifier);
 
 	return 0;
 }
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 077f212..6d7bc8f 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -532,7 +532,6 @@
 static struct ctl_table_header *pfm_sysctl_header;
 
 static int pfm_context_unload(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
-static int pfm_flush(struct file *filp);
 
 #define pfm_get_cpu_var(v)		__ia64_per_cpu_var(v)
 #define pfm_get_cpu_data(a,b)		per_cpu(a, b)
@@ -595,10 +594,11 @@
 }
 
 
-static struct super_block *
-pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
+static int
+pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data,
+	     struct vfsmount *mnt)
 {
-	return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC);
+	return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC, mnt);
 }
 
 static struct file_system_type pfm_fs_type = {
@@ -1773,7 +1773,7 @@
  * When caller is self-monitoring, the context is unloaded.
  */
 static int
-pfm_flush(struct file *filp)
+pfm_flush(struct file *filp, fl_owner_t id)
 {
 	pfm_context_t *ctx;
 	struct task_struct *task;
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 355d579..b045c27 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -272,9 +272,9 @@
 	/* endless idle loop with no priority at all */
 	while (1) {
 		if (can_do_pal_halt)
-			clear_thread_flag(TIF_POLLING_NRFLAG);
+			current_thread_info()->status &= ~TS_POLLING;
 		else
-			set_thread_flag(TIF_POLLING_NRFLAG);
+			current_thread_info()->status |= TS_POLLING;
 
 		if (!need_resched()) {
 			void (*idle)(void);
diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
index 056f7a6..77fa659 100644
--- a/arch/ia64/kernel/sal.c
+++ b/arch/ia64/kernel/sal.c
@@ -227,7 +227,7 @@
 static void __init
 check_sal_cache_flush (void)
 {
-	unsigned long flags, itv;
+	unsigned long flags;
 	int cpu;
 	u64 vector;
 
@@ -238,9 +238,6 @@
 	 * Schedule a timer interrupt, wait until it's reported, and see if
 	 * SAL_CACHE_FLUSH drops it.
 	 */
-	itv = ia64_get_itv();
-	BUG_ON((itv & (1 << 16)) == 0);
-
 	ia64_set_itv(IA64_TIMER_VECTOR);
 	ia64_set_itm(ia64_get_itc() + 1000);
 
@@ -260,7 +257,6 @@
 		ia64_eoi();
 	}
 
-	ia64_set_itv(itv);
 	local_irq_restore(flags);
 	put_cpu();
 }
diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c
index 663a186..9065f0f 100644
--- a/arch/ia64/kernel/salinfo.c
+++ b/arch/ia64/kernel/salinfo.c
@@ -572,7 +572,7 @@
 };
 
 #ifdef	CONFIG_HOTPLUG_CPU
-static int
+static int __devinit
 salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
 {
 	unsigned int i, cpu = (unsigned long)hcpu;
@@ -673,9 +673,7 @@
 	salinfo_timer.function = &salinfo_timeout;
 	add_timer(&salinfo_timer);
 
-#ifdef	CONFIG_HOTPLUG_CPU
-	register_cpu_notifier(&salinfo_cpu_notifier);
-#endif
+	register_hotcpu_notifier(&salinfo_cpu_notifier);
 
 	return 0;
 }
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index e4dfda1..6dba2d6 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -260,6 +260,7 @@
 	n++;
 
 	num_rsvd_regions = n;
+	BUG_ON(IA64_MAX_RSVD_REGIONS + 1 < n);
 
 	sort_regions(rsvd_region, num_rsvd_regions);
 }
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 4f3a16b..5511d9c 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -26,19 +26,10 @@
 #include <asm/numa.h>
 #include <asm/cpu.h>
 
-#ifdef CONFIG_NUMA
-static struct node *sysfs_nodes;
-#endif
 static struct ia64_cpu *sysfs_cpus;
 
 int arch_register_cpu(int num)
 {
-	struct node *parent = NULL;
-	
-#ifdef CONFIG_NUMA
-	parent = &sysfs_nodes[cpu_to_node(num)];
-#endif /* CONFIG_NUMA */
-
 #if defined (CONFIG_ACPI) && defined (CONFIG_HOTPLUG_CPU)
 	/*
 	 * If CPEI cannot be re-targetted, and this is
@@ -48,21 +39,14 @@
 		sysfs_cpus[num].cpu.no_control = 1;
 #endif
 
-	return register_cpu(&sysfs_cpus[num].cpu, num, parent);
+	return register_cpu(&sysfs_cpus[num].cpu, num);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 
 void arch_unregister_cpu(int num)
 {
-	struct node *parent = NULL;
-
-#ifdef CONFIG_NUMA
-	int node = cpu_to_node(num);
-	parent = &sysfs_nodes[node];
-#endif /* CONFIG_NUMA */
-
-	return unregister_cpu(&sysfs_cpus[num].cpu, parent);
+	return unregister_cpu(&sysfs_cpus[num].cpu);
 }
 EXPORT_SYMBOL(arch_register_cpu);
 EXPORT_SYMBOL(arch_unregister_cpu);
@@ -74,17 +58,11 @@
 	int i, err = 0;
 
 #ifdef CONFIG_NUMA
-	sysfs_nodes = kzalloc(sizeof(struct node) * MAX_NUMNODES, GFP_KERNEL);
-	if (!sysfs_nodes) {
-		err = -ENOMEM;
-		goto out;
-	}
-
 	/*
 	 * MCD - Do we want to register all ONLINE nodes, or all POSSIBLE nodes?
 	 */
 	for_each_online_node(i) {
-		if ((err = register_node(&sysfs_nodes[i], i, 0)))
+		if ((err = register_one_node(i)))
 			goto out;
 	}
 #endif
@@ -166,7 +144,7 @@
 
 	num_shared = (int) csi.num_shared;
 	do {
-		for_each_cpu(j)
+		for_each_possible_cpu(j)
 			if (cpu_data(cpu)->socket_id == cpu_data(j)->socket_id
 				&& cpu_data(j)->core_id == csi.log1_cid
 				&& cpu_data(j)->thread_id == csi.log1_tid)
@@ -426,7 +404,7 @@
  * When a cpu is hot-plugged, do a check and initiate
  * cache kobject if necessary
  */
-static int cache_cpu_callback(struct notifier_block *nfb,
+static int __cpuinit cache_cpu_callback(struct notifier_block *nfb,
 		unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
@@ -444,7 +422,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block cache_cpu_notifier =
+static struct notifier_block __cpuinitdata cache_cpu_notifier =
 {
 	.notifier_call = cache_cpu_callback
 };
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
index fcd2bad..5f03b9e 100644
--- a/arch/ia64/kernel/uncached.c
+++ b/arch/ia64/kernel/uncached.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2001-2005 Silicon Graphics, Inc.  All rights reserved.
+ * Copyright (C) 2001-2006 Silicon Graphics, Inc.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -29,15 +29,8 @@
 #include <asm/tlbflush.h>
 #include <asm/sn/arch.h>
 
-#define DEBUG	0
 
-#if DEBUG
-#define dprintk			printk
-#else
-#define dprintk(x...)		do { } while (0)
-#endif
-
-void __init efi_memmap_walk_uc (efi_freemem_callback_t callback);
+extern void __init efi_memmap_walk_uc(efi_freemem_callback_t, void *);
 
 #define MAX_UNCACHED_GRANULES	5
 static int allocated_granules;
@@ -60,6 +53,7 @@
 static void uncached_ipi_mc_drain(void *data)
 {
 	int status;
+
 	status = ia64_pal_mc_drain();
 	if (status)
 		printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on "
@@ -67,30 +61,35 @@
 }
 
 
-static unsigned long
-uncached_get_new_chunk(struct gen_pool *poolp)
+/*
+ * Add a new chunk of uncached memory pages to the specified pool.
+ *
+ * @pool: pool to add new chunk of uncached memory to
+ * @nid: node id of node to allocate memory from, or -1
+ *
+ * This is accomplished by first allocating a granule of cached memory pages
+ * and then converting them to uncached memory pages.
+ */
+static int uncached_add_chunk(struct gen_pool *pool, int nid)
 {
 	struct page *page;
-	void *tmp;
 	int status, i;
-	unsigned long addr, node;
+	unsigned long c_addr, uc_addr;
 
 	if (allocated_granules >= MAX_UNCACHED_GRANULES)
-		return 0;
+		return -1;
 
-	node = poolp->private;
-	page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO,
+	/* attempt to allocate a granule's worth of cached memory pages */
+
+	page = alloc_pages_node(nid, GFP_KERNEL | __GFP_ZERO,
 				IA64_GRANULE_SHIFT-PAGE_SHIFT);
-
-	dprintk(KERN_INFO "get_new_chunk page %p, addr %lx\n",
-		page, (unsigned long)(page-vmem_map) << PAGE_SHIFT);
-
-	/*
-	 * Do magic if no mem on local node! XXX
-	 */
 	if (!page)
-		return 0;
-	tmp = page_address(page);
+		return -1;
+
+	/* convert the memory pages from cached to uncached */
+
+	c_addr = (unsigned long)page_address(page);
+	uc_addr = c_addr - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
 
 	/*
 	 * There's a small race here where it's possible for someone to
@@ -100,76 +99,90 @@
 	for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
 		SetPageUncached(&page[i]);
 
-	flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE);
+	flush_tlb_kernel_range(uc_addr, uc_adddr + IA64_GRANULE_SIZE);
 
 	status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
-
-	dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n",
-		status, raw_smp_processor_id());
-
 	if (!status) {
 		status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1);
 		if (status)
-			printk(KERN_WARNING "smp_call_function failed for "
-			       "uncached_ipi_visibility! (%i)\n", status);
+			goto failed;
 	}
 
+	preempt_disable();
+
 	if (ia64_platform_is("sn2"))
-		sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE);
+		sn_flush_all_caches(uc_addr, IA64_GRANULE_SIZE);
 	else
-		flush_icache_range((unsigned long)tmp,
-				   (unsigned long)tmp+IA64_GRANULE_SIZE);
+		flush_icache_range(uc_addr, uc_addr + IA64_GRANULE_SIZE);
+
+	/* flush the just introduced uncached translation from the TLB */
+	local_flush_tlb_all();
+
+	preempt_enable();
 
 	ia64_pal_mc_drain();
 	status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1);
 	if (status)
-		printk(KERN_WARNING "smp_call_function failed for "
-		       "uncached_ipi_mc_drain! (%i)\n", status);
+		goto failed;
 
-	addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
+	/*
+	 * The chunk of memory pages has been converted to uncached so now we
+	 * can add it to the pool.
+	 */
+	status = gen_pool_add(pool, uc_addr, IA64_GRANULE_SIZE, nid);
+	if (status)
+		goto failed;
 
 	allocated_granules++;
-	return addr;
+	return 0;
+
+	/* failed to convert or add the chunk so give it back to the kernel */
+failed:
+	for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
+		ClearPageUncached(&page[i]);
+
+	free_pages(c_addr, IA64_GRANULE_SHIFT-PAGE_SHIFT);
+	return -1;
 }
 
 
 /*
  * uncached_alloc_page
  *
+ * @starting_nid: node id of node to start with, or -1
+ *
  * Allocate 1 uncached page. Allocates on the requested node. If no
  * uncached pages are available on the requested node, roundrobin starting
- * with higher nodes.
+ * with the next higher node.
  */
-unsigned long
-uncached_alloc_page(int nid)
+unsigned long uncached_alloc_page(int starting_nid)
 {
-	unsigned long maddr;
+	unsigned long uc_addr;
+	struct gen_pool *pool;
+	int nid;
 
-	maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE);
+	if (unlikely(starting_nid >= MAX_NUMNODES))
+		return 0;
 
-	dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n",
-		maddr, nid);
+	if (starting_nid < 0)
+		starting_nid = numa_node_id();
+	nid = starting_nid;
 
-	/*
-	 * If no memory is availble on our local node, try the
-	 * remaining nodes in the system.
-	 */
-	if (!maddr) {
-		int i;
+	do {
+		if (!node_online(nid))
+			continue;
+		pool = uncached_pool[nid];
+		if (pool == NULL)
+			continue;
+		do {
+			uc_addr = gen_pool_alloc(pool, PAGE_SIZE);
+			if (uc_addr != 0)
+				return uc_addr;
+		} while (uncached_add_chunk(pool, nid) == 0);
 
-		for (i = MAX_NUMNODES - 1; i >= 0; i--) {
-			if (i == nid || !node_online(i))
-				continue;
-			maddr = gen_pool_alloc(uncached_pool[i], PAGE_SIZE);
-			dprintk(KERN_DEBUG "uncached_alloc_page alternate search "
-				"returns %lx on node %i\n", maddr, i);
-			if (maddr) {
-				break;
-			}
-		}
-	}
+	} while ((nid = (nid + 1) % MAX_NUMNODES) != starting_nid);
 
-	return maddr;
+	return 0;
 }
 EXPORT_SYMBOL(uncached_alloc_page);
 
@@ -177,21 +190,22 @@
 /*
  * uncached_free_page
  *
+ * @uc_addr: uncached address of page to free
+ *
  * Free a single uncached page.
  */
-void
-uncached_free_page(unsigned long maddr)
+void uncached_free_page(unsigned long uc_addr)
 {
-	int node;
+	int nid = paddr_to_nid(uc_addr - __IA64_UNCACHED_OFFSET);
+	struct gen_pool *pool = uncached_pool[nid];
 
-	node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET);
+	if (unlikely(pool == NULL))
+		return;
 
-	dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node);
+	if ((uc_addr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
+		panic("uncached_free_page invalid address %lx\n", uc_addr);
 
-	if ((maddr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
-		panic("uncached_free_page invalid address %lx\n", maddr);
-
-	gen_pool_free(uncached_pool[node], maddr, PAGE_SIZE);
+	gen_pool_free(pool, uc_addr, PAGE_SIZE);
 }
 EXPORT_SYMBOL(uncached_free_page);
 
@@ -199,43 +213,39 @@
 /*
  * uncached_build_memmap,
  *
+ * @uc_start: uncached starting address of a chunk of uncached memory
+ * @uc_end: uncached ending address of a chunk of uncached memory
+ * @arg: ignored, (NULL argument passed in on call to efi_memmap_walk_uc())
+ *
  * Called at boot time to build a map of pages that can be used for
  * memory special operations.
  */
-static int __init
-uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
+static int __init uncached_build_memmap(unsigned long uc_start,
+					unsigned long uc_end, void *arg)
 {
-	long length = end - start;
-	int node;
-
-	dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
+	int nid = paddr_to_nid(uc_start - __IA64_UNCACHED_OFFSET);
+	struct gen_pool *pool = uncached_pool[nid];
+	size_t size = uc_end - uc_start;
 
 	touch_softlockup_watchdog();
-	memset((char *)start, 0, length);
 
-	node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET);
-
-	for (; start < end ; start += PAGE_SIZE) {
-		dprintk(KERN_INFO "sticking %lx into the pool!\n", start);
-		gen_pool_free(uncached_pool[node], start, PAGE_SIZE);
+	if (pool != NULL) {
+		memset((char *)uc_start, 0, size);
+		(void) gen_pool_add(pool, uc_start, size, nid);
 	}
-
 	return 0;
 }
 
 
-static int __init uncached_init(void) {
-	int i;
+static int __init uncached_init(void)
+{
+	int nid;
 
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		if (!node_online(i))
-			continue;
-		uncached_pool[i] = gen_pool_create(0, IA64_GRANULE_SHIFT,
-						   &uncached_get_new_chunk, i);
+	for_each_online_node(nid) {
+		uncached_pool[nid] = gen_pool_create(PAGE_SHIFT, nid);
 	}
 
-	efi_memmap_walk_uc(uncached_build_memmap);
-
+	efi_memmap_walk_uc(uncached_build_memmap, NULL);
 	return 0;
 }
 
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index b6bcc9f..525b082 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -33,7 +33,6 @@
  */
 struct early_node_data {
 	struct ia64_node_data *node_data;
-	pg_data_t *pgdat;
 	unsigned long pernode_addr;
 	unsigned long pernode_size;
 	struct bootmem_data bootmem_data;
@@ -46,6 +45,8 @@
 static struct early_node_data mem_data[MAX_NUMNODES] __initdata;
 static nodemask_t memory_less_mask __initdata;
 
+static pg_data_t *pgdat_list[MAX_NUMNODES];
+
 /*
  * To prevent cache aliasing effects, align per-node structures so that they
  * start at addresses that are strided by node number.
@@ -99,7 +100,7 @@
  * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been
  * called yet.  Note that node 0 will also count all non-existent cpus.
  */
-static int __init early_nr_cpus_node(int node)
+static int __meminit early_nr_cpus_node(int node)
 {
 	int cpu, n = 0;
 
@@ -114,7 +115,7 @@
  * compute_pernodesize - compute size of pernode data
  * @node: the node id.
  */
-static unsigned long __init compute_pernodesize(int node)
+static unsigned long __meminit compute_pernodesize(int node)
 {
 	unsigned long pernodesize = 0, cpus;
 
@@ -175,13 +176,13 @@
 	pernode += PERCPU_PAGE_SIZE * cpus;
 	pernode += node * L1_CACHE_BYTES;
 
-	mem_data[node].pgdat = __va(pernode);
+	pgdat_list[node] = __va(pernode);
 	pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
 
 	mem_data[node].node_data = __va(pernode);
 	pernode += L1_CACHE_ALIGN(sizeof(struct ia64_node_data));
 
-	mem_data[node].pgdat->bdata = bdp;
+	pgdat_list[node]->bdata = bdp;
 	pernode += L1_CACHE_ALIGN(sizeof(pg_data_t));
 
 	cpu_data = per_cpu_node_setup(cpu_data, node);
@@ -268,7 +269,7 @@
 static int __init free_node_bootmem(unsigned long start, unsigned long len,
 				    int node)
 {
-	free_bootmem_node(mem_data[node].pgdat, start, len);
+	free_bootmem_node(pgdat_list[node], start, len);
 
 	return 0;
 }
@@ -287,7 +288,7 @@
 	int node;
 
 	for_each_online_node(node) {
-		pg_data_t *pdp = mem_data[node].pgdat;
+		pg_data_t *pdp = pgdat_list[node];
 
 		if (node_isset(node, memory_less_mask))
 			continue;
@@ -307,6 +308,17 @@
 	}
 }
 
+static void __meminit scatter_node_data(void)
+{
+	pg_data_t **dst;
+	int node;
+
+	for_each_online_node(node) {
+		dst = LOCAL_DATA_ADDR(pgdat_list[node])->pg_data_ptrs;
+		memcpy(dst, pgdat_list, sizeof(pgdat_list));
+	}
+}
+
 /**
  * initialize_pernode_data - fixup per-cpu & per-node pointers
  *
@@ -317,17 +329,10 @@
  */
 static void __init initialize_pernode_data(void)
 {
-	pg_data_t *pgdat_list[MAX_NUMNODES];
 	int cpu, node;
 
-	for_each_online_node(node)
-		pgdat_list[node] = mem_data[node].pgdat;
+	scatter_node_data();
 
-	/* Copy the pg_data_t list to each node and init the node field */
-	for_each_online_node(node) {
-		memcpy(mem_data[node].node_data->pg_data_ptrs, pgdat_list,
-		       sizeof(pgdat_list));
-	}
 #ifdef CONFIG_SMP
 	/* Set the node_data pointer for each per-cpu struct */
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
@@ -372,7 +377,7 @@
 	if (bestnode == -1)
 		bestnode = anynode;
 
-	ptr = __alloc_bootmem_node(mem_data[bestnode].pgdat, pernodesize,
+	ptr = __alloc_bootmem_node(pgdat_list[bestnode], pernodesize,
 		PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
 
 	return ptr;
@@ -476,7 +481,7 @@
 		pernodesize = mem_data[node].pernode_size;
 		map = pernode + pernodesize;
 
-		init_bootmem_node(mem_data[node].pgdat,
+		init_bootmem_node(pgdat_list[node],
 				  map>>PAGE_SHIFT,
 				  bdp->node_boot_start>>PAGE_SHIFT,
 				  bdp->node_low_pfn);
@@ -786,3 +791,21 @@
 
 	zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
+
+pg_data_t *arch_alloc_nodedata(int nid)
+{
+	unsigned long size = compute_pernodesize(nid);
+
+	return kzalloc(size, GFP_KERNEL);
+}
+
+void arch_free_nodedata(pg_data_t *pgdat)
+{
+	kfree(pgdat);
+}
+
+void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat)
+{
+	pgdat_list[update_node] = update_pgdat;
+	scatter_node_data();
+}
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index d98ec49..14ef7cc 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -19,6 +19,40 @@
 
 extern void die (char *, struct pt_regs *, long);
 
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
+/* Hook to register for page fault notifications */
+int register_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+}
+
+int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+}
+
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	struct die_args args = {
+		.regs = regs,
+		.str = str,
+		.err = err,
+		.trapnr = trap,
+		.signr = sig
+	};
+	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	return NOTIFY_DONE;
+}
+#endif
+
 /*
  * Return TRUE if ADDRESS points at a page in the kernel's mapped segment
  * (inside region 5, on ia64) and that page is present.
@@ -84,7 +118,7 @@
 	/*
 	 * This is to handle the kprobes on user space access instructions
 	 */
-	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT,
+	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT,
 					SIGSEGV) == NOTIFY_STOP)
 		return;
 
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index cafa877..38306e9 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -652,7 +652,7 @@
 	num_physpages++;
 }
 
-int add_memory(u64 start, u64 size)
+int arch_add_memory(int nid, u64 start, u64 size)
 {
 	pg_data_t *pgdat;
 	struct zone *zone;
@@ -660,7 +660,7 @@
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 	int ret;
 
-	pgdat = NODE_DATA(0);
+	pgdat = NODE_DATA(nid);
 
 	zone = pgdat->node_zones + ZONE_NORMAL;
 	ret = __add_pages(zone, start_pfn, nr_pages);
@@ -676,4 +676,5 @@
 {
 	return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(remove_memory);
 #endif
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 643ccc6..07bd02b 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/efi.h>
 #include <asm/io.h>
+#include <asm/meminit.h>
 
 static inline void __iomem *
 __ioremap (unsigned long offset, unsigned long size)
@@ -21,16 +22,29 @@
 void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
-	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_WB))
-		return phys_to_virt(offset);
+	u64 attr;
+	unsigned long gran_base, gran_size;
 
-	if (efi_mem_attribute_range(offset, size, EFI_MEMORY_UC))
+	/*
+	 * For things in kern_memmap, we must use the same attribute
+	 * as the rest of the kernel.  For more details, see
+	 * Documentation/ia64/aliasing.txt.
+	 */
+	attr = kern_mem_attribute(offset, size);
+	if (attr & EFI_MEMORY_WB)
+		return phys_to_virt(offset);
+	else if (attr & EFI_MEMORY_UC)
 		return __ioremap(offset, size);
 
 	/*
-	 * Someday this should check ACPI resources so we
-	 * can do the right thing for hot-plugged regions.
+	 * Some chipsets don't support UC access to memory.  If
+	 * WB is supported for the whole granule, we prefer that.
 	 */
+	gran_base = GRANULEROUNDDOWN(offset);
+	gran_size = GRANULEROUNDUP(offset + size) - gran_base;
+	if (efi_mem_attribute(gran_base, gran_size) & EFI_MEMORY_WB)
+		return phys_to_virt(offset);
+
 	return __ioremap(offset, size);
 }
 EXPORT_SYMBOL(ioremap);
@@ -38,6 +52,9 @@
 void __iomem *
 ioremap_nocache (unsigned long offset, unsigned long size)
 {
+	if (kern_mem_attribute(offset, size) & EFI_MEMORY_WB)
+		return 0;
+
 	return __ioremap(offset, size);
 }
 EXPORT_SYMBOL(ioremap_nocache);
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index ab829a2..77375a5 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -352,7 +352,7 @@
 	pxm = acpi_get_pxm(controller->acpi_handle);
 #ifdef CONFIG_NUMA
 	if (pxm >= 0)
-		controller->node = pxm_to_nid_map[pxm];
+		controller->node = pxm_to_node(pxm);
 #endif
 
 	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
@@ -602,8 +602,6 @@
 	 * Leave vm_pgoff as-is, the PCI space address is the physical
 	 * address on this platform.
 	 */
-	vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
-
 	if (write_combine && efi_range_is_wc(vma->vm_start,
 					     vma->vm_end - vma->vm_start))
 		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
@@ -645,18 +643,30 @@
 int
 pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma)
 {
+	unsigned long size = vma->vm_end - vma->vm_start;
+	pgprot_t prot;
 	char *addr;
 
+	/*
+	 * Avoid attribute aliasing.  See Documentation/ia64/aliasing.txt
+	 * for more details.
+	 */
+	if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, size))
+		return -EINVAL;
+	prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
+				    vma->vm_page_prot);
+	if (pgprot_val(prot) != pgprot_val(pgprot_noncached(vma->vm_page_prot)))
+		return -EINVAL;
+
 	addr = pci_get_legacy_mem(bus);
 	if (IS_ERR(addr))
 		return PTR_ERR(addr);
 
 	vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT;
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-	vma->vm_flags |= (VM_SHM | VM_RESERVED | VM_IO);
+	vma->vm_page_prot = prot;
 
 	if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-			    vma->vm_end - vma->vm_start, vma->vm_page_prot))
+			    size, vma->vm_page_prot))
 		return -EAGAIN;
 
 	return 0;
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 5101ac4..dc09a6a 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -58,7 +58,7 @@
  */
 
 static dma_addr_t
-sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size)
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
 {
 	return 0;
 }
@@ -457,13 +457,6 @@
 		pcidev_info->pdi_sn_irq_info = NULL;
 		kfree(sn_irq_info);
 	}
-
-	/*
-	 * MSI currently not supported on altix.  Remove this when
-	 * the MSI abstraction patches are integrated into the kernel
-	 * (sometime after 2.6.16 releases)
-	 */
-	dev->no_msi = 1;
 }
 
 /*
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index c265e02..677c6c0 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -26,11 +26,11 @@
 
 int sn_force_interrupt_flag = 1;
 extern int sn_ioif_inited;
-static struct list_head **sn_irq_lh;
-static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */
+struct list_head **sn_irq_lh;
+static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */
 
-static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
-				     u64 sn_irq_info,
+u64 sn_intr_alloc(nasid_t local_nasid, int local_widget,
+				     struct sn_irq_info *sn_irq_info,
 				     int req_irq, nasid_t req_nasid,
 				     int req_slice)
 {
@@ -40,12 +40,13 @@
 
 	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
 			(u64) SAL_INTR_ALLOC, (u64) local_nasid,
-			(u64) local_widget, (u64) sn_irq_info, (u64) req_irq,
+			(u64) local_widget, __pa(sn_irq_info), (u64) req_irq,
 			(u64) req_nasid, (u64) req_slice);
+
 	return ret_stuff.status;
 }
 
-static inline void sn_intr_free(nasid_t local_nasid, int local_widget,
+void sn_intr_free(nasid_t local_nasid, int local_widget,
 				struct sn_irq_info *sn_irq_info)
 {
 	struct ia64_sal_retval ret_stuff;
@@ -112,73 +113,91 @@
 
 static void sn_irq_info_free(struct rcu_head *head);
 
+struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
+				       nasid_t nasid, int slice)
+{
+	int vector;
+	int cpuphys;
+	int64_t bridge;
+	int local_widget, status;
+	nasid_t local_nasid;
+	struct sn_irq_info *new_irq_info;
+	struct sn_pcibus_provider *pci_provider;
+
+	new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
+	if (new_irq_info == NULL)
+		return NULL;
+
+	memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
+
+	bridge = (u64) new_irq_info->irq_bridge;
+	if (!bridge) {
+		kfree(new_irq_info);
+		return NULL; /* irq is not a device interrupt */
+	}
+
+	local_nasid = NASID_GET(bridge);
+
+	if (local_nasid & 1)
+		local_widget = TIO_SWIN_WIDGETNUM(bridge);
+	else
+		local_widget = SWIN_WIDGETNUM(bridge);
+
+	vector = sn_irq_info->irq_irq;
+	/* Free the old PROM new_irq_info structure */
+	sn_intr_free(local_nasid, local_widget, new_irq_info);
+	/* Update kernels new_irq_info with new target info */
+	unregister_intr_pda(new_irq_info);
+
+	/* allocate a new PROM new_irq_info struct */
+	status = sn_intr_alloc(local_nasid, local_widget,
+			       new_irq_info, vector,
+			       nasid, slice);
+
+	/* SAL call failed */
+	if (status) {
+		kfree(new_irq_info);
+		return NULL;
+	}
+
+	cpuphys = nasid_slice_to_cpuid(nasid, slice);
+	new_irq_info->irq_cpuid = cpuphys;
+	register_intr_pda(new_irq_info);
+
+	pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
+
+	/*
+	 * If this represents a line interrupt, target it.  If it's
+	 * an msi (irq_int_bit < 0), it's already targeted.
+	 */
+	if (new_irq_info->irq_int_bit >= 0 &&
+	    pci_provider && pci_provider->target_interrupt)
+		(pci_provider->target_interrupt)(new_irq_info);
+
+	spin_lock(&sn_irq_info_lock);
+	list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
+	spin_unlock(&sn_irq_info_lock);
+	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
+
+#ifdef CONFIG_SMP
+	set_irq_affinity_info((vector & 0xff), cpuphys, 0);
+#endif
+
+	return new_irq_info;
+}
+
 static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
 {
 	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
-	int cpuid, cpuphys;
+	nasid_t nasid;
+	int slice;
 
-	cpuid = first_cpu(mask);
-	cpuphys = cpu_physical_id(cpuid);
+	nasid = cpuid_to_nasid(first_cpu(mask));
+	slice = cpuid_to_slice(first_cpu(mask));
 
 	list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
-				 sn_irq_lh[irq], list) {
-		u64 bridge;
-		int local_widget, status;
-		nasid_t local_nasid;
-		struct sn_irq_info *new_irq_info;
-		struct sn_pcibus_provider *pci_provider;
-
-		new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
-		if (new_irq_info == NULL)
-			break;
-		memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
-
-		bridge = (u64) new_irq_info->irq_bridge;
-		if (!bridge) {
-			kfree(new_irq_info);
-			break; /* irq is not a device interrupt */
-		}
-
-		local_nasid = NASID_GET(bridge);
-
-		if (local_nasid & 1)
-			local_widget = TIO_SWIN_WIDGETNUM(bridge);
-		else
-			local_widget = SWIN_WIDGETNUM(bridge);
-
-		/* Free the old PROM new_irq_info structure */
-		sn_intr_free(local_nasid, local_widget, new_irq_info);
-		/* Update kernels new_irq_info with new target info */
-		unregister_intr_pda(new_irq_info);
-
-		/* allocate a new PROM new_irq_info struct */
-		status = sn_intr_alloc(local_nasid, local_widget,
-				       __pa(new_irq_info), irq,
-				       cpuid_to_nasid(cpuid),
-				       cpuid_to_slice(cpuid));
-
-		/* SAL call failed */
-		if (status) {
-			kfree(new_irq_info);
-			break;
-		}
-
-		new_irq_info->irq_cpuid = cpuid;
-		register_intr_pda(new_irq_info);
-
-		pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
-		if (pci_provider && pci_provider->target_interrupt)
-			(pci_provider->target_interrupt)(new_irq_info);
-
-		spin_lock(&sn_irq_info_lock);
-		list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
-		spin_unlock(&sn_irq_info_lock);
-		call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
-
-#ifdef CONFIG_SMP
-		set_irq_affinity_info((irq & 0xff), cpuphys, 0);
-#endif
-	}
+				 sn_irq_lh[irq], list)
+		(void)sn_retarget_vector(sn_irq_info, nasid, slice);
 }
 
 struct hw_interrupt_type irq_type_sn = {
@@ -202,6 +221,9 @@
 	int i;
 	irq_desc_t *base_desc = irq_desc;
 
+	ia64_first_device_vector = IA64_SN2_FIRST_DEVICE_VECTOR;
+	ia64_last_device_vector = IA64_SN2_LAST_DEVICE_VECTOR;
+
 	for (i = 0; i < NR_IRQS; i++) {
 		if (base_desc[i].handler == &no_irq_type) {
 			base_desc[i].handler = &irq_type_sn;
@@ -285,6 +307,7 @@
 	/* link it into the sn_irq[irq] list */
 	spin_lock(&sn_irq_info_lock);
 	list_add_rcu(&sn_irq_info->list, sn_irq_lh[sn_irq_info->irq_irq]);
+	reserve_irq_vector(sn_irq_info->irq_irq);
 	spin_unlock(&sn_irq_info_lock);
 
 	register_intr_pda(sn_irq_info);
@@ -310,8 +333,11 @@
 	spin_lock(&sn_irq_info_lock);
 	list_del_rcu(&sn_irq_info->list);
 	spin_unlock(&sn_irq_info_lock);
+	if (list_empty(sn_irq_lh[sn_irq_info->irq_irq]))
+		free_irq_vector(sn_irq_info->irq_irq);
 	call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
 	pci_dev_put(pci_dev);
+
 }
 
 static inline void
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 30988df..3bfccf3 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -139,7 +139,7 @@
 	int i;
 	int nid;
 
-	nid = pxm_to_nid_map[pxm];
+	nid = pxm_to_node(pxm);
 	for (i = 0; i < num_node_memblks; i++) {
 		if (node_memblk[i].nid == nid) {
 			return NASID_GET(node_memblk[i].start_paddr);
@@ -458,7 +458,7 @@
 	 * support here so we don't have to listen to failed keyboard probe
 	 * messages.
 	 */
-	if (version <= 0x0209 && acpi_kbd_controller_present) {
+	if (is_shub1() && version <= 0x0209 && acpi_kbd_controller_present) {
 		printk(KERN_INFO "Disabling legacy keyboard support as prom "
 		       "is too old and doesn't provide FADT\n");
 		acpi_kbd_controller_present = 0;
@@ -577,7 +577,8 @@
 	int i;
 	static int wars_have_been_checked;
 
-	if (smp_processor_id() == 0 && IS_MEDUSA()) {
+	cpuid = smp_processor_id();
+	if (cpuid == 0 && IS_MEDUSA()) {
 		if (ia64_sn_is_fake_prom())
 			sn_prom_type = 2;
 		else
@@ -597,6 +598,12 @@
 	sn_hub_info->as_shift = sn_hub_info->nasid_shift - 2;
 
 	/*
+	 * Don't check status. The SAL call is not supported on all PROMs
+	 * but a failure is harmless.
+	 */
+	(void) ia64_sn_set_cpu_number(cpuid);
+
+	/*
 	 * The boot cpu makes this call again after platform initialization is
 	 * complete.
 	 */
@@ -607,7 +614,6 @@
 		if (ia64_sn_get_prom_feature_set(i, &sn_prom_features[i]) != 0)
 			break;
 
-	cpuid = smp_processor_id();
 	cpuphyid = get_sapicid();
 
 	if (ia64_sn_get_sapic_info(cpuphyid, &nasid, &subnode, &slice))
@@ -704,7 +710,7 @@
 	 * cnode == node for all C & M bricks.
 	 */
 	for_each_online_node(node) {
-		nasid = pxm_to_nasid(nid_to_pxm_map[node]);
+		nasid = pxm_to_nasid(node_to_pxm(node));
 		sn_cnodeid_to_nasid[node] = nasid;
 		physical_node_map[nasid] = node;
 	}
diff --git a/arch/ia64/sn/kernel/sn2/cache.c b/arch/ia64/sn/kernel/sn2/cache.c
index bc3cfa1..2862cb3 100644
--- a/arch/ia64/sn/kernel/sn2/cache.c
+++ b/arch/ia64/sn/kernel/sn2/cache.c
@@ -3,11 +3,12 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  * 
- * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001-2003, 2006 Silicon Graphics, Inc. All rights reserved.
  *
  */
 #include <linux/module.h>
 #include <asm/pgalloc.h>
+#include <asm/sn/arch.h>
 
 /**
  * sn_flush_all_caches - flush a range of address from all caches (incl. L4)
@@ -17,18 +18,24 @@
  * Flush a range of addresses from all caches including L4. 
  * All addresses fully or partially contained within 
  * @flush_addr to @flush_addr + @bytes are flushed
- * from the all caches.
+ * from all caches.
  */
 void
 sn_flush_all_caches(long flush_addr, long bytes)
 {
-	flush_icache_range(flush_addr, flush_addr+bytes);
+	unsigned long addr = flush_addr;
+
+	/* SHub1 requires a cached address */
+	if (is_shub1() && (addr & RGN_BITS) == RGN_BASE(RGN_UNCACHED))
+		addr = (addr - RGN_BASE(RGN_UNCACHED)) + RGN_BASE(RGN_KERNEL);
+
+	flush_icache_range(addr, addr + bytes);
 	/*
 	 * The last call may have returned before the caches
 	 * were actually flushed, so we call it again to make
 	 * sure.
 	 */
-	flush_icache_range(flush_addr, flush_addr+bytes);
+	flush_icache_range(addr, addr + bytes);
 	mb();
 }
 EXPORT_SYMBOL(sn_flush_all_caches);
diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
index 739c948..9a8a293 100644
--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
@@ -51,6 +51,8 @@
 static int sn_hwperf_init(void);
 static DECLARE_MUTEX(sn_hwperf_init_mutex);
 
+#define cnode_possible(n)	((n) < num_cnodes)
+
 static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret)
 {
 	int e;
@@ -127,14 +129,14 @@
 		}
 	}
 
-	return node_possible(cnode) ? cnode : -1;
+	return cnode_possible(cnode) ? cnode : -1;
 }
 
 static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj)
 {
 	if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
 		BUG();
-	if (!obj->sn_hwp_this_part)
+	if (SN_HWPERF_FOREIGN(obj))
 		return -1;
 	return sn_hwperf_geoid_to_cnode(obj->location);
 }
@@ -199,12 +201,12 @@
 
 static inline int sn_hwperf_has_cpus(cnodeid_t node)
 {
-	return node_online(node) && nr_cpus_node(node);
+	return node < MAX_NUMNODES && node_online(node) && nr_cpus_node(node);
 }
 
 static inline int sn_hwperf_has_mem(cnodeid_t node)
 {
-	return node_online(node) && NODE_DATA(node)->node_present_pages;
+	return node < MAX_NUMNODES && node_online(node) && NODE_DATA(node)->node_present_pages;
 }
 
 static struct sn_hwperf_object_info *
@@ -237,7 +239,7 @@
 	int found_mem = 0;
 	int found_cpu = 0;
 
-	if (!node_possible(node))
+	if (!cnode_possible(node))
 		return -EINVAL;
 
 	if (sn_hwperf_has_cpus(node)) {
@@ -442,7 +444,7 @@
 	seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location,
 		obj->sn_hwp_this_part ? "local" : "shared", obj->name);
 
-	if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj))
+	if (ordinal < 0 || (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)))
 		seq_putc(s, '\n');
 	else {
 		cnodeid_t near_mem = -1;
@@ -468,22 +470,24 @@
 		/*
 		 * CPUs on this node, if any
 		 */
-		cpumask = node_to_cpumask(ordinal);
-		for_each_online_cpu(i) {
-			if (cpu_isset(i, cpumask)) {
-				slice = 'a' + cpuid_to_slice(i);
-				c = cpu_data(i);
-				seq_printf(s, "cpu %d %s%c local"
-					" freq %luMHz, arch ia64",
-					i, obj->location, slice,
-					c->proc_freq / 1000000);
-				for_each_online_cpu(j) {
-					seq_printf(s, j ? ":%d" : ", dist %d",
-						node_distance(
-						    cpu_to_node(i),
-						    cpu_to_node(j)));
+		if (!SN_HWPERF_IS_IONODE(obj)) {
+			cpumask = node_to_cpumask(ordinal);
+			for_each_online_cpu(i) {
+				if (cpu_isset(i, cpumask)) {
+					slice = 'a' + cpuid_to_slice(i);
+					c = cpu_data(i);
+					seq_printf(s, "cpu %d %s%c local"
+						" freq %luMHz, arch ia64",
+						i, obj->location, slice,
+						c->proc_freq / 1000000);
+					for_each_online_cpu(j) {
+						seq_printf(s, j ? ":%d" : ", dist %d",
+							node_distance(
+						    	cpu_to_node(i),
+						    	cpu_to_node(j)));
+					}
+					seq_putc(s, '\n');
 				}
-				seq_putc(s, '\n');
 			}
 		}
 	}
@@ -523,7 +527,7 @@
 			if (obj->sn_hwp_this_part && p->sn_hwp_this_part)
 				/* both ends local to this partition */
 				seq_puts(s, " local");
-			else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part)
+			else if (SN_HWPERF_FOREIGN(p))
 				/* both ends of the link in foreign partiton */
 				seq_puts(s, " foreign");
 			else
@@ -776,7 +780,7 @@
 
 	case SN_HWPERF_GET_NODE_NASID:
 		if (a.sz != sizeof(u64) ||
-		   (node = a.arg) < 0 || !node_possible(node)) {
+		   (node = a.arg) < 0 || !cnode_possible(node)) {
 			r = -EINVAL;
 			goto error;
 		}
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index b4b84c2..7a291a2 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -11,7 +11,7 @@
 
 #include <linux/module.h>
 #include <asm/dma.h>
-#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/intr.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
 #include <asm/sn/sn_sal.h>
@@ -113,7 +113,8 @@
 	 * resources.
 	 */
 
-	*dma_handle = provider->dma_map_consistent(pdev, phys_addr, size);
+	*dma_handle = provider->dma_map_consistent(pdev, phys_addr, size,
+						   SN_DMA_ADDR_PHYS);
 	if (!*dma_handle) {
 		printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
 		free_pages((unsigned long)cpuaddr, get_order(size));
@@ -176,7 +177,7 @@
 	BUG_ON(dev->bus != &pci_bus_type);
 
 	phys_addr = __pa(cpu_addr);
-	dma_addr = provider->dma_map(pdev, phys_addr, size);
+	dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS);
 	if (!dma_addr) {
 		printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
 		return 0;
@@ -260,7 +261,8 @@
 	for (i = 0; i < nhwentries; i++, sg++) {
 		phys_addr = SG_ENT_PHYS_ADDRESS(sg);
 		sg->dma_address = provider->dma_map(pdev,
-						    phys_addr, sg->length);
+						    phys_addr, sg->length,
+						    SN_DMA_ADDR_PHYS);
 
 		if (!sg->dma_address) {
 			printk(KERN_ERR "%s: out of ATEs\n", __FUNCTION__);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
index 9f86bb6..a86c7b9 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c
@@ -41,7 +41,7 @@
 
 static dma_addr_t
 pcibr_dmamap_ate32(struct pcidev_info *info,
-		   u64 paddr, size_t req_size, u64 flags)
+		   u64 paddr, size_t req_size, u64 flags, int dma_flags)
 {
 
 	struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
@@ -81,9 +81,12 @@
 	if (IS_PCIX(pcibus_info))
 		ate_flags &= ~(PCI32_ATE_PREF);
 
-	xio_addr =
-	    IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
-	    PHYS_TO_TIODMA(paddr);
+	if (SN_DMA_ADDRTYPE(dma_flags == SN_DMA_ADDR_PHYS))
+		xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+	    					      PHYS_TO_TIODMA(paddr);
+	else
+		xio_addr = paddr;
+
 	offset = IOPGOFF(xio_addr);
 	ate = ate_flags | (xio_addr - offset);
 
@@ -91,6 +94,13 @@
 	if (IS_PIC_SOFT(pcibus_info)) {
 		ate |= (pcibus_info->pbi_hub_xid << PIC_ATE_TARGETID_SHFT);
 	}
+
+	/*
+	 * If we're mapping for MSI, set the MSI bit in the ATE
+	 */
+	if (dma_flags & SN_DMA_MSI)
+		ate |= PCI32_ATE_MSI;
+
 	ate_write(pcibus_info, ate_index, ate_count, ate);
 
 	/*
@@ -105,20 +115,27 @@
 	if (pcibus_info->pbi_devreg[internal_device] & PCIBR_DEV_SWAP_DIR)
 		ATE_SWAP_ON(pci_addr);
 
+
 	return pci_addr;
 }
 
 static dma_addr_t
 pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr,
-			u64 dma_attributes)
+			u64 dma_attributes, int dma_flags)
 {
 	struct pcibus_info *pcibus_info = (struct pcibus_info *)
 	    ((info->pdi_host_pcidev_info)->pdi_pcibus_info);
 	u64 pci_addr;
 
 	/* Translate to Crosstalk View of Physical Address */
-	pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
-		    PHYS_TO_TIODMA(paddr)) | dma_attributes;
+	if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+		pci_addr = IS_PIC_SOFT(pcibus_info) ?
+				PHYS_TO_DMA(paddr) :
+		    		PHYS_TO_TIODMA(paddr) | dma_attributes;
+	else
+		pci_addr = IS_PIC_SOFT(pcibus_info) ?
+				paddr :
+				paddr | dma_attributes;
 
 	/* Handle Bus mode */
 	if (IS_PCIX(pcibus_info))
@@ -130,7 +147,9 @@
 		    ((u64) pcibus_info->
 		     pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT);
 	} else
-		pci_addr |= TIOCP_PCI64_CMDTYPE_MEM;
+		pci_addr |= (dma_flags & SN_DMA_MSI) ?
+				TIOCP_PCI64_CMDTYPE_MSI :
+				TIOCP_PCI64_CMDTYPE_MEM;
 
 	/* If PCI mode, func zero uses VCHAN0, every other func uses VCHAN1 */
 	if (!IS_PCIX(pcibus_info) && PCI_FUNC(info->pdi_linux_pcidev->devfn))
@@ -141,7 +160,7 @@
 
 static dma_addr_t
 pcibr_dmatrans_direct32(struct pcidev_info * info,
-			u64 paddr, size_t req_size, u64 flags)
+			u64 paddr, size_t req_size, u64 flags, int dma_flags)
 {
 	struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info;
 	struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info->
@@ -156,8 +175,14 @@
 		return 0;
 	}
 
-	xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
-	    PHYS_TO_TIODMA(paddr);
+	if (dma_flags & SN_DMA_MSI)
+		return 0;
+
+	if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+		xio_addr = IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) :
+	    					      PHYS_TO_TIODMA(paddr);
+	else
+		xio_addr = paddr;
 
 	xio_base = pcibus_info->pbi_dir_xbase;
 	offset = xio_addr - xio_base;
@@ -327,7 +352,7 @@
  */
 
 dma_addr_t
-pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size)
+pcibr_dma_map(struct pci_dev * hwdev, unsigned long phys_addr, size_t size, int dma_flags)
 {
 	dma_addr_t dma_handle;
 	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
@@ -344,11 +369,11 @@
 		 */
 
 		dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-						     PCI64_ATTR_PREF);
+						     PCI64_ATTR_PREF, dma_flags);
 	} else {
 		/* Handle 32-63 bit cards via direct mapping */
 		dma_handle = pcibr_dmatrans_direct32(pcidev_info, phys_addr,
-						     size, 0);
+						     size, 0, dma_flags);
 		if (!dma_handle) {
 			/*
 			 * It is a 32 bit card and we cannot do direct mapping,
@@ -356,7 +381,8 @@
 			 */
 
 			dma_handle = pcibr_dmamap_ate32(pcidev_info, phys_addr,
-							size, PCI32_ATE_PREF);
+							size, PCI32_ATE_PREF,
+							dma_flags);
 		}
 	}
 
@@ -365,18 +391,18 @@
 
 dma_addr_t
 pcibr_dma_map_consistent(struct pci_dev * hwdev, unsigned long phys_addr,
-			 size_t size)
+			 size_t size, int dma_flags)
 {
 	dma_addr_t dma_handle;
 	struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(hwdev);
 
 	if (hwdev->dev.coherent_dma_mask == ~0UL) {
 		dma_handle = pcibr_dmatrans_direct64(pcidev_info, phys_addr,
-					    PCI64_ATTR_BAR);
+					    PCI64_ATTR_BAR, dma_flags);
 	} else {
 		dma_handle = (dma_addr_t) pcibr_dmamap_ate32(pcidev_info,
 						    phys_addr, size,
-						    PCI32_ATE_BAR);
+						    PCI32_ATE_BAR, dma_flags);
 	}
 
 	return dma_handle;
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index be01769..e4aa839 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -515,11 +515,17 @@
  * use the GART mapped mode.
  */
 static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
 {
 	u64 mapaddr;
 
 	/*
+	 * Not supported for now ...
+	 */
+	if (dma_flags & SN_DMA_MSI)
+		return 0;
+
+	/*
 	 * If card is 64 or 48 bit addresable, use a direct mapping.  32
 	 * bit direct is so restrictive w.r.t. where the memory resides that
 	 * we don't use it even though CA has some support.
@@ -589,7 +595,7 @@
 
 	/* sanity check prom rev */
 
-	if (sn_sal_rev() < 0x0406) {
+	if (is_shub1() && sn_sal_rev() < 0x0406) {
 		printk
 		    (KERN_ERR "%s:  SGI prom rev 4.06 or greater required "
 		     "for tioca support\n", __FUNCTION__);
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index 8332956..2d79485 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (C) 2003-2006 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
 #include <linux/types.h>
@@ -170,7 +170,8 @@
 	(ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1)
 
 #define ATE_VALID(ate)	((ate) & (1UL << 63))
-#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63))
+#define ATE_MAKE(addr, ps, msi) \
+	(((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63) | ((msi)?(1UL << 62):0))
 
 /*
  * Flavors of ate-based mapping supported by tioce_alloc_map()
@@ -196,15 +197,17 @@
  *
  * 63    - must be 1 to indicate d64 mode to CE hardware
  * 62    - barrier bit ... controlled with tioce_dma_barrier()
- * 61    - 0 since this is not an MSI transaction
+ * 61    - msi bit ... specified through dma_flags
  * 60:54 - reserved, MBZ
  */
 static u64
-tioce_dma_d64(unsigned long ct_addr)
+tioce_dma_d64(unsigned long ct_addr, int dma_flags)
 {
 	u64 bus_addr;
 
 	bus_addr = ct_addr | (1UL << 63);
+	if (dma_flags & SN_DMA_MSI)
+		bus_addr |= (1UL << 61);
 
 	return bus_addr;
 }
@@ -261,7 +264,7 @@
  */
 static u64
 tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port,
-		u64 ct_addr, int len)
+		u64 ct_addr, int len, int dma_flags)
 {
 	int i;
 	int j;
@@ -270,6 +273,7 @@
 	int entries;
 	int nates;
 	u64 pagesize;
+	int msi_capable, msi_wanted;
 	u64 *ate_shadow;
 	u64 *ate_reg;
 	u64 addr;
@@ -291,6 +295,7 @@
 		ate_reg = ce_mmr->ce_ure_ate3240;
 		pagesize = ce_kern->ce_ate3240_pagesize;
 		bus_base = TIOCE_M32_MIN;
+		msi_capable = 1;
 		break;
 	case TIOCE_ATE_M40:
 		first = 0;
@@ -299,6 +304,7 @@
 		ate_reg = ce_mmr->ce_ure_ate40;
 		pagesize = MB(64);
 		bus_base = TIOCE_M40_MIN;
+		msi_capable = 0;
 		break;
 	case TIOCE_ATE_M40S:
 		/*
@@ -311,11 +317,16 @@
 		ate_reg = ce_mmr->ce_ure_ate3240;
 		pagesize = GB(16);
 		bus_base = TIOCE_M40S_MIN;
+		msi_capable = 0;
 		break;
 	default:
 		return 0;
 	}
 
+	msi_wanted = dma_flags & SN_DMA_MSI;
+	if (msi_wanted && !msi_capable)
+		return 0;
+
 	nates = ATE_NPAGES(ct_addr, len, pagesize);
 	if (nates > entries)
 		return 0;
@@ -344,7 +355,7 @@
 	for (j = 0; j < nates; j++) {
 		u64 ate;
 
-		ate = ATE_MAKE(addr, pagesize);
+		ate = ATE_MAKE(addr, pagesize, msi_wanted);
 		ate_shadow[i + j] = ate;
 		tioce_mmr_storei(ce_kern, &ate_reg[i + j], ate);
 		addr += pagesize;
@@ -371,7 +382,7 @@
  * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info.
  */
 static u64
-tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr)
+tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr, int dma_flags)
 {
 	int dma_ok;
 	int port;
@@ -381,6 +392,9 @@
 	u64 ct_lower;
 	dma_addr_t bus_addr;
 
+	if (dma_flags & SN_DMA_MSI)
+		return 0;
+
 	ct_upper = ct_addr & ~0x3fffffffUL;
 	ct_lower = ct_addr & 0x3fffffffUL;
 
@@ -507,7 +521,7 @@
  */
 static u64
 tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count,
-		 int barrier)
+		 int barrier, int dma_flags)
 {
 	unsigned long flags;
 	u64 ct_addr;
@@ -523,15 +537,18 @@
 	if (dma_mask < 0x7fffffffUL)
 		return 0;
 
-	ct_addr = PHYS_TO_TIODMA(paddr);
+	if (SN_DMA_ADDRTYPE(dma_flags) == SN_DMA_ADDR_PHYS)
+		ct_addr = PHYS_TO_TIODMA(paddr);
+	else
+		ct_addr = paddr;
 
 	/*
 	 * If the device can generate 64 bit addresses, create a D64 map.
-	 * Since this should never fail, bypass the rest of the checks.
 	 */
 	if (dma_mask == ~0UL) {
-		mapaddr = tioce_dma_d64(ct_addr);
-		goto dma_map_done;
+		mapaddr = tioce_dma_d64(ct_addr, dma_flags);
+		if (mapaddr)
+			goto dma_map_done;
 	}
 
 	pcidev_to_tioce(pdev, NULL, &ce_kern, &port);
@@ -574,18 +591,22 @@
 
 		if (byte_count > MB(64)) {
 			mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
-						  port, ct_addr, byte_count);
+						  port, ct_addr, byte_count,
+						  dma_flags);
 			if (!mapaddr)
 				mapaddr =
 				    tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
-						    ct_addr, byte_count);
+						    ct_addr, byte_count,
+						    dma_flags);
 		} else {
 			mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1,
-						  ct_addr, byte_count);
+						  ct_addr, byte_count,
+						  dma_flags);
 			if (!mapaddr)
 				mapaddr =
 				    tioce_alloc_map(ce_kern, TIOCE_ATE_M40S,
-						    port, ct_addr, byte_count);
+						    port, ct_addr, byte_count,
+						    dma_flags);
 		}
 	}
 
@@ -593,7 +614,7 @@
 	 * 32-bit direct is the next mode to try
 	 */
 	if (!mapaddr && dma_mask >= 0xffffffffUL)
-		mapaddr = tioce_dma_d32(pdev, ct_addr);
+		mapaddr = tioce_dma_d32(pdev, ct_addr, dma_flags);
 
 	/*
 	 * Last resort, try 32-bit ATE-based map.
@@ -601,7 +622,7 @@
 	if (!mapaddr)
 		mapaddr =
 		    tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr,
-				    byte_count);
+				    byte_count, dma_flags);
 
 	spin_unlock_irqrestore(&ce_kern->ce_lock, flags);
 
@@ -622,9 +643,9 @@
  * in the address.
  */
 static u64
-tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
 {
-	return tioce_do_dma_map(pdev, paddr, byte_count, 0);
+	return tioce_do_dma_map(pdev, paddr, byte_count, 0, dma_flags);
 }
 
 /**
@@ -636,9 +657,9 @@
  * Simply call tioce_do_dma_map() to create a map with the barrier bit set
  * in the address.
  */ static u64
-tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count)
+tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
 {
-	return tioce_do_dma_map(pdev, paddr, byte_count, 1);
+	return tioce_do_dma_map(pdev, paddr, byte_count, 1, dma_flags);
 }
 
 /**
@@ -696,7 +717,7 @@
 	while (ate_index <= last_ate) {
 		u64 ate;
 
-		ate = ATE_MAKE(0xdeadbeef, ps);
+		ate = ATE_MAKE(0xdeadbeef, ps, 0);
 		ce_kern->ce_ate3240_shadow[ate_index] = ate;
 		tioce_mmr_storei(ce_kern, &ce_mmr->ce_ure_ate3240[ate_index],
 				 ate);
@@ -1002,7 +1023,7 @@
 	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_int_status_alias, ~0ULL);
 	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_adm_error_summary_alias,
 		       ~0ULL);
-	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, ~0ULL);
+	tioce_mmr_seti(tioce_kern, &tioce_mmr->ce_dre_comp_err_addr, 0ULL);
 
 	if (request_irq(SGI_PCIASIC_ERROR,
 			tioce_error_intr_handler,
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 3cd3c29..1ff483c 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -275,7 +275,7 @@
 	int i;
 
 	for_each_present_cpu(i)
-		register_cpu(&cpu_devices[i], i, NULL);
+		register_cpu(&cpu_devices[i], i);
 
 	return 0;
 }
diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
index b7bd84c..8f2e058 100644
--- a/arch/m68k/amiga/amiga_ksyms.c
+++ b/arch/m68k/amiga/amiga_ksyms.c
@@ -23,8 +23,6 @@
 EXPORT_SYMBOL(amiga_chip_size);
 EXPORT_SYMBOL(amiga_audio_period);
 EXPORT_SYMBOL(amiga_audio_min_period);
-EXPORT_SYMBOL(amiga_do_irq);
-EXPORT_SYMBOL(amiga_do_irq_list);
 
 #ifdef CONFIG_AMIGA_PCMCIA
   EXPORT_SYMBOL(pcmcia_reset);
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index b0aa61b..f9403f4 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -35,60 +35,29 @@
  *           /Jes
  */
 
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/errno.h>
-#include <linux/seq_file.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/amipcmcia.h>
 
-extern int cia_request_irq(struct ciabase *base,int irq,
-                           irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                           unsigned long flags, const char *devname, void *dev_id);
-extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
-extern void cia_init_IRQ(struct ciabase *base);
-extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p);
+static void amiga_enable_irq(unsigned int irq);
+static void amiga_disable_irq(unsigned int irq);
+static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp);
+static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp);
 
-/* irq node variables for amiga interrupt sources */
-static irq_node_t *ami_irq_list[AMI_STD_IRQS];
-
-static unsigned short amiga_intena_vals[AMI_STD_IRQS] = {
-	[IRQ_AMIGA_VERTB]	= IF_VERTB,
-	[IRQ_AMIGA_COPPER]	= IF_COPER,
-	[IRQ_AMIGA_AUD0]	= IF_AUD0,
-	[IRQ_AMIGA_AUD1]	= IF_AUD1,
-	[IRQ_AMIGA_AUD2]	= IF_AUD2,
-	[IRQ_AMIGA_AUD3]	= IF_AUD3,
-	[IRQ_AMIGA_BLIT]	= IF_BLIT,
-	[IRQ_AMIGA_DSKSYN]	= IF_DSKSYN,
-	[IRQ_AMIGA_DSKBLK]	= IF_DSKBLK,
-	[IRQ_AMIGA_RBF]		= IF_RBF,
-	[IRQ_AMIGA_TBE]		= IF_TBE,
-	[IRQ_AMIGA_SOFT]	= IF_SOFT,
-	[IRQ_AMIGA_PORTS]	= IF_PORTS,
-	[IRQ_AMIGA_EXTER]	= IF_EXTER
+static struct irq_controller amiga_irq_controller = {
+	.name		= "amiga",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.enable		= amiga_enable_irq,
+	.disable	= amiga_disable_irq,
 };
-static const unsigned char ami_servers[AMI_STD_IRQS] = {
-	[IRQ_AMIGA_VERTB]	= 1,
-	[IRQ_AMIGA_PORTS]	= 1,
-	[IRQ_AMIGA_EXTER]	= 1
-};
-
-static short ami_ablecount[AMI_IRQS];
-
-static irqreturn_t ami_badint(int irq, void *dev_id, struct pt_regs *fp)
-{
-	num_spurious += 1;
-	return IRQ_NONE;
-}
 
 /*
  * void amiga_init_IRQ(void)
@@ -103,23 +72,12 @@
 
 void __init amiga_init_IRQ(void)
 {
-	int i;
+	request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL);
+	request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL);
+	request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL);
+	request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL);
 
-	/* initialize handlers */
-	for (i = 0; i < AMI_STD_IRQS; i++) {
-		if (ami_servers[i]) {
-			ami_irq_list[i] = NULL;
-		} else {
-			ami_irq_list[i] = new_irq_node();
-			ami_irq_list[i]->handler = ami_badint;
-			ami_irq_list[i]->flags   = 0;
-			ami_irq_list[i]->dev_id  = NULL;
-			ami_irq_list[i]->devname = NULL;
-			ami_irq_list[i]->next    = NULL;
-		}
-	}
-	for (i = 0; i < AMI_IRQS; i++)
-		ami_ablecount[i] = 0;
+	m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
 
 	/* turn off PCMCIA interrupts */
 	if (AMIGAHW_PRESENT(PCMCIA))
@@ -134,249 +92,21 @@
 	cia_init_IRQ(&ciab_base);
 }
 
-static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node)
-{
-	unsigned long flags;
-	irq_node_t *cur;
-
-	if (!node->dev_id)
-		printk("%s: Warning: dev_id of %s is zero\n",
-		       __FUNCTION__, node->devname);
-
-	local_irq_save(flags);
-
-	cur = *list;
-
-	if (node->flags & SA_INTERRUPT) {
-		if (node->flags & SA_SHIRQ)
-			return -EBUSY;
-		/*
-		 * There should never be more than one
-		 */
-		while (cur && cur->flags & SA_INTERRUPT) {
-			list = &cur->next;
-			cur = cur->next;
-		}
-	} else {
-		while (cur) {
-			list = &cur->next;
-			cur = cur->next;
-		}
-	}
-
-	node->next = cur;
-	*list = node;
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
-{
-	unsigned long flags;
-	irq_node_t *node;
-
-	local_irq_save(flags);
-
-	for (node = *list; node; list = &node->next, node = *list) {
-		if (node->dev_id == dev_id) {
-			*list = node->next;
-			/* Mark it as free. */
-			node->handler = NULL;
-			local_irq_restore(flags);
-			return;
-		}
-	}
-	local_irq_restore(flags);
-	printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
-}
-
-/*
- * amiga_request_irq : add an interrupt service routine for a particular
- *                     machine specific interrupt source.
- *                     If the addition was successful, it returns 0.
- */
-
-int amiga_request_irq(unsigned int irq,
-		      irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                      unsigned long flags, const char *devname, void *dev_id)
-{
-	irq_node_t *node;
-	int error = 0;
-
-	if (irq >= AMI_IRQS) {
-		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__,
-			irq, devname);
-		return -ENXIO;
-	}
-
-	if (irq >= IRQ_AMIGA_AUTO)
-		return cpu_request_irq(irq - IRQ_AMIGA_AUTO, handler,
-		                       flags, devname, dev_id);
-
-	if (irq >= IRQ_AMIGA_CIAB)
-		return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
-		                       handler, flags, devname, dev_id);
-
-	if (irq >= IRQ_AMIGA_CIAA)
-		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
-		                       handler, flags, devname, dev_id);
-
-	/*
-	 * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared,
-	 * we could add a check here for the SA_SHIRQ flag but all drivers
-	 * should be aware of sharing anyway.
-	 */
-	if (ami_servers[irq]) {
-		if (!(node = new_irq_node()))
-			return -ENOMEM;
-		node->handler = handler;
-		node->flags   = flags;
-		node->dev_id  = dev_id;
-		node->devname = devname;
-		node->next    = NULL;
-		error = amiga_insert_irq(&ami_irq_list[irq], node);
-	} else {
-		ami_irq_list[irq]->handler = handler;
-		ami_irq_list[irq]->flags   = flags;
-		ami_irq_list[irq]->dev_id  = dev_id;
-		ami_irq_list[irq]->devname = devname;
-	}
-
-	/* enable the interrupt */
-	if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
-		amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
-
-	return error;
-}
-
-void amiga_free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq >= AMI_IRQS) {
-		printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
-		return;
-	}
-
-	if (irq >= IRQ_AMIGA_AUTO)
-		cpu_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
-
-	if (irq >= IRQ_AMIGA_CIAB) {
-		cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
-		return;
-	}
-
-	if (irq >= IRQ_AMIGA_CIAA) {
-		cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
-		return;
-	}
-
-	if (ami_servers[irq]) {
-		amiga_delete_irq(&ami_irq_list[irq], dev_id);
-		/* if server list empty, disable the interrupt */
-		if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
-			amiga_custom.intena = amiga_intena_vals[irq];
-	} else {
-		if (ami_irq_list[irq]->dev_id != dev_id)
-			printk("%s: removing probably wrong IRQ %d from %s\n",
-			       __FUNCTION__, irq, ami_irq_list[irq]->devname);
-		ami_irq_list[irq]->handler = ami_badint;
-		ami_irq_list[irq]->flags   = 0;
-		ami_irq_list[irq]->dev_id  = NULL;
-		ami_irq_list[irq]->devname = NULL;
-		amiga_custom.intena = amiga_intena_vals[irq];
-	}
-}
-
 /*
  * Enable/disable a particular machine specific interrupt source.
  * Note that this may affect other interrupts in case of a shared interrupt.
  * This function should only be called for a _very_ short time to change some
  * internal data, that may not be changed by the interrupt at the same time.
- * ami_(enable|disable)_irq calls may also be nested.
  */
 
-void amiga_enable_irq(unsigned int irq)
+static void amiga_enable_irq(unsigned int irq)
 {
-	if (irq >= AMI_IRQS) {
-		printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
-		return;
-	}
-
-	if (--ami_ablecount[irq])
-		return;
-
-	/* No action for auto-vector interrupts */
-	if (irq >= IRQ_AMIGA_AUTO){
-		printk("%s: Trying to enable auto-vector IRQ %i\n",
-		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
-		return;
-	}
-
-	if (irq >= IRQ_AMIGA_CIAB) {
-		cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB)));
-		cia_able_irq(&ciab_base, CIA_ICR_SETCLR |
-		             (1 << (irq - IRQ_AMIGA_CIAB)));
-		return;
-	}
-
-	if (irq >= IRQ_AMIGA_CIAA) {
-		cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA)));
-		cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
-		             (1 << (irq - IRQ_AMIGA_CIAA)));
-		return;
-	}
-
-	/* enable the interrupt */
-	amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq];
+	amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER));
 }
 
-void amiga_disable_irq(unsigned int irq)
+static void amiga_disable_irq(unsigned int irq)
 {
-	if (irq >= AMI_IRQS) {
-		printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
-		return;
-	}
-
-	if (ami_ablecount[irq]++)
-		return;
-
-	/* No action for auto-vector interrupts */
-	if (irq >= IRQ_AMIGA_AUTO) {
-		printk("%s: Trying to disable auto-vector IRQ %i\n",
-		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
-		return;
-	}
-
-	if (irq >= IRQ_AMIGA_CIAB) {
-		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
-		return;
-	}
-
-	if (irq >= IRQ_AMIGA_CIAA) {
-		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
-		return;
-	}
-
-	/* disable the interrupt */
-	amiga_custom.intena = amiga_intena_vals[irq];
-}
-
-inline void amiga_do_irq(int irq, struct pt_regs *fp)
-{
-	kstat_cpu(0).irqs[SYS_IRQS + irq]++;
-	ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
-}
-
-void amiga_do_irq_list(int irq, struct pt_regs *fp)
-{
-	irq_node_t *node;
-
-	kstat_cpu(0).irqs[SYS_IRQS + irq]++;
-
-	amiga_custom.intreq = amiga_intena_vals[irq];
-
-	for (node = ami_irq_list[irq]; node; node = node->next)
-		node->handler(irq, node->dev_id, fp);
+	amiga_custom.intena = 1 << (irq - IRQ_USER);
 }
 
 /*
@@ -390,19 +120,19 @@
 	/* if serial transmit buffer empty, interrupt */
 	if (ints & IF_TBE) {
 		amiga_custom.intreq = IF_TBE;
-		amiga_do_irq(IRQ_AMIGA_TBE, fp);
+		m68k_handle_int(IRQ_AMIGA_TBE, fp);
 	}
 
 	/* if floppy disk transfer complete, interrupt */
 	if (ints & IF_DSKBLK) {
 		amiga_custom.intreq = IF_DSKBLK;
-		amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
+		m68k_handle_int(IRQ_AMIGA_DSKBLK, fp);
 	}
 
 	/* if software interrupt set, interrupt */
 	if (ints & IF_SOFT) {
 		amiga_custom.intreq = IF_SOFT;
-		amiga_do_irq(IRQ_AMIGA_SOFT, fp);
+		m68k_handle_int(IRQ_AMIGA_SOFT, fp);
 	}
 	return IRQ_HANDLED;
 }
@@ -414,18 +144,20 @@
 	/* if a blitter interrupt */
 	if (ints & IF_BLIT) {
 		amiga_custom.intreq = IF_BLIT;
-		amiga_do_irq(IRQ_AMIGA_BLIT, fp);
+		m68k_handle_int(IRQ_AMIGA_BLIT, fp);
 	}
 
 	/* if a copper interrupt */
 	if (ints & IF_COPER) {
 		amiga_custom.intreq = IF_COPER;
-		amiga_do_irq(IRQ_AMIGA_COPPER, fp);
+		m68k_handle_int(IRQ_AMIGA_COPPER, fp);
 	}
 
 	/* if a vertical blank interrupt */
-	if (ints & IF_VERTB)
-		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp);
+	if (ints & IF_VERTB) {
+		amiga_custom.intreq = IF_VERTB;
+		m68k_handle_int(IRQ_AMIGA_VERTB, fp);
+	}
 	return IRQ_HANDLED;
 }
 
@@ -436,25 +168,25 @@
 	/* if audio 0 interrupt */
 	if (ints & IF_AUD0) {
 		amiga_custom.intreq = IF_AUD0;
-		amiga_do_irq(IRQ_AMIGA_AUD0, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD0, fp);
 	}
 
 	/* if audio 1 interrupt */
 	if (ints & IF_AUD1) {
 		amiga_custom.intreq = IF_AUD1;
-		amiga_do_irq(IRQ_AMIGA_AUD1, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD1, fp);
 	}
 
 	/* if audio 2 interrupt */
 	if (ints & IF_AUD2) {
 		amiga_custom.intreq = IF_AUD2;
-		amiga_do_irq(IRQ_AMIGA_AUD2, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD2, fp);
 	}
 
 	/* if audio 3 interrupt */
 	if (ints & IF_AUD3) {
 		amiga_custom.intreq = IF_AUD3;
-		amiga_do_irq(IRQ_AMIGA_AUD3, fp);
+		m68k_handle_int(IRQ_AMIGA_AUD3, fp);
 	}
 	return IRQ_HANDLED;
 }
@@ -466,55 +198,13 @@
 	/* if serial receive buffer full interrupt */
 	if (ints & IF_RBF) {
 		/* acknowledge of IF_RBF must be done by the serial interrupt */
-		amiga_do_irq(IRQ_AMIGA_RBF, fp);
+		m68k_handle_int(IRQ_AMIGA_RBF, fp);
 	}
 
 	/* if a disk sync interrupt */
 	if (ints & IF_DSKSYN) {
 		amiga_custom.intreq = IF_DSKSYN;
-		amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
+		m68k_handle_int(IRQ_AMIGA_DSKSYN, fp);
 	}
 	return IRQ_HANDLED;
 }
-
-static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp)
-{
-	panic ("level 7 interrupt received\n");
-}
-
-irqreturn_t (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	[0] = ami_badint,
-	[1] = ami_int1,
-	[2] = ami_badint,
-	[3] = ami_int3,
-	[4] = ami_int4,
-	[5] = ami_int5,
-	[6] = ami_badint,
-	[7] = ami_int7
-};
-
-int show_amiga_interrupts(struct seq_file *p, void *v)
-{
-	int i;
-	irq_node_t *node;
-
-	for (i = 0; i < AMI_STD_IRQS; i++) {
-		if (!(node = ami_irq_list[i]))
-			continue;
-		seq_printf(p, "ami  %2d: %10u ", i,
-		               kstat_cpu(0).irqs[SYS_IRQS + i]);
-		do {
-			if (node->flags & SA_INTERRUPT)
-				seq_puts(p, "F ");
-			else
-				seq_puts(p, "  ");
-			seq_printf(p, "%s\n", node->devname);
-			if ((node = node->next))
-				seq_puts(p, "                    ");
-		} while (node);
-	}
-
-	cia_get_irq_list(&ciaa_base, p);
-	cia_get_irq_list(&ciab_base, p);
-	return 0;
-}
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index 9476eb9..0956e45 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -29,21 +29,18 @@
 	unsigned short int_mask;
 	int handler_irq, cia_irq, server_irq;
 	char *name;
-	irq_handler_t irq_list[CIA_IRQS];
 } ciaa_base = {
 	.cia		= &ciaa,
 	.int_mask	= IF_PORTS,
-	.handler_irq	= IRQ_AMIGA_AUTO_2,
+	.handler_irq	= IRQ_AMIGA_PORTS,
 	.cia_irq	= IRQ_AMIGA_CIAA,
-	.server_irq	= IRQ_AMIGA_PORTS,
-	.name		= "CIAA handler"
+	.name		= "CIAA"
 }, ciab_base = {
 	.cia		= &ciab,
 	.int_mask	= IF_EXTER,
-	.handler_irq	= IRQ_AMIGA_AUTO_6,
+	.handler_irq	= IRQ_AMIGA_EXTER,
 	.cia_irq	= IRQ_AMIGA_CIAB,
-	.server_irq	= IRQ_AMIGA_EXTER,
-	.name		= "CIAB handler"
+	.name		= "CIAB"
 };
 
 /*
@@ -66,13 +63,11 @@
 
 /*
  *  Enable or disable CIA interrupts, return old interrupt mask,
- *  interrupts will only be enabled if a handler exists
  */
 
 unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
 {
-	unsigned char old, tmp;
-	int i;
+	unsigned char old;
 
 	old = base->icr_mask;
 	base->icr_data |= base->cia->icr;
@@ -82,99 +77,104 @@
 	else
 		base->icr_mask &= ~mask;
 	base->icr_mask &= CIA_ICR_ALL;
-	for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) {
-		if ((tmp & base->icr_mask) && !base->irq_list[i].handler) {
-			base->icr_mask &= ~tmp;
-			base->cia->icr = tmp;
-		}
-	}
 	if (base->icr_data & base->icr_mask)
 		amiga_custom.intreq = IF_SETCLR | base->int_mask;
 	return old;
 }
 
-int cia_request_irq(struct ciabase *base, unsigned int irq,
-                    irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                    unsigned long flags, const char *devname, void *dev_id)
-{
-	unsigned char mask;
-
-	base->irq_list[irq].handler = handler;
-	base->irq_list[irq].flags   = flags;
-	base->irq_list[irq].dev_id  = dev_id;
-	base->irq_list[irq].devname = devname;
-
-	/* enable the interrupt */
-	mask = 1 << irq;
-	cia_set_irq(base, mask);
-	cia_able_irq(base, CIA_ICR_SETCLR | mask);
-	return 0;
-}
-
-void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id)
-{
-	if (base->irq_list[irq].dev_id != dev_id)
-		printk("%s: removing probably wrong IRQ %i from %s\n",
-		       __FUNCTION__, base->cia_irq + irq,
-		       base->irq_list[irq].devname);
-
-	base->irq_list[irq].handler = NULL;
-	base->irq_list[irq].flags   = 0;
-
-	cia_able_irq(base, 1 << irq);
-}
-
 static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp)
 {
 	struct ciabase *base = (struct ciabase *)dev_id;
-	int mach_irq, i;
+	int mach_irq;
 	unsigned char ints;
 
 	mach_irq = base->cia_irq;
-	irq = SYS_IRQS + mach_irq;
 	ints = cia_set_irq(base, CIA_ICR_ALL);
 	amiga_custom.intreq = base->int_mask;
-	for (i = 0; i < CIA_IRQS; i++, irq++, mach_irq++) {
-		if (ints & 1) {
-			kstat_cpu(0).irqs[irq]++;
-			base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp);
-		}
-		ints >>= 1;
+	for (; ints; mach_irq++, ints >>= 1) {
+		if (ints & 1)
+			m68k_handle_int(mach_irq, fp);
 	}
-	amiga_do_irq_list(base->server_irq, fp);
 	return IRQ_HANDLED;
 }
 
+static void cia_enable_irq(unsigned int irq)
+{
+	unsigned char mask;
+
+	if (irq >= IRQ_AMIGA_CIAB) {
+		mask = 1 << (irq - IRQ_AMIGA_CIAB);
+		cia_set_irq(&ciab_base, mask);
+		cia_able_irq(&ciab_base, CIA_ICR_SETCLR | mask);
+	} else {
+		mask = 1 << (irq - IRQ_AMIGA_CIAA);
+		cia_set_irq(&ciaa_base, mask);
+		cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | mask);
+	}
+}
+
+static void cia_disable_irq(unsigned int irq)
+{
+	if (irq >= IRQ_AMIGA_CIAB)
+		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
+	else
+		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
+}
+
+static struct irq_controller cia_irq_controller = {
+	.name		= "cia",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.enable		= cia_enable_irq,
+	.disable	= cia_disable_irq,
+};
+
+/*
+ * Override auto irq 2 & 6 and use them as general chain
+ * for external interrupts, we link the CIA interrupt sources
+ * into this chain.
+ */
+
+static void auto_enable_irq(unsigned int irq)
+{
+	switch (irq) {
+	case IRQ_AUTO_2:
+		amiga_custom.intena = IF_SETCLR | IF_PORTS;
+		break;
+	case IRQ_AUTO_6:
+		amiga_custom.intena = IF_SETCLR | IF_EXTER;
+		break;
+	}
+}
+
+static void auto_disable_irq(unsigned int irq)
+{
+	switch (irq) {
+	case IRQ_AUTO_2:
+		amiga_custom.intena = IF_PORTS;
+		break;
+	case IRQ_AUTO_6:
+		amiga_custom.intena = IF_EXTER;
+		break;
+	}
+}
+
+static struct irq_controller auto_irq_controller = {
+	.name		= "auto",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.enable		= auto_enable_irq,
+	.disable	= auto_disable_irq,
+};
+
 void __init cia_init_IRQ(struct ciabase *base)
 {
-	int i;
-
-	/* init isr handlers */
-	for (i = 0; i < CIA_IRQS; i++) {
-		base->irq_list[i].handler = NULL;
-		base->irq_list[i].flags   = 0;
-	}
+	m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS);
 
 	/* clear any pending interrupt and turn off all interrupts */
 	cia_set_irq(base, CIA_ICR_ALL);
 	cia_able_irq(base, CIA_ICR_ALL);
 
-	/* install CIA handler */
-	request_irq(base->handler_irq, cia_handler, 0, base->name, base);
-
-	amiga_custom.intena = IF_SETCLR | base->int_mask;
-}
-
-int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
-{
-	int i, j;
-
-	j = base->cia_irq;
-	for (i = 0; i < CIA_IRQS; i++) {
-		seq_printf(p, "cia  %2d: %10d ", j + i,
-			       kstat_cpu(0).irqs[SYS_IRQS + j + i]);
-		seq_puts(p, "  ");
-		seq_printf(p, "%s\n", base->irq_list[i].devname);
-	}
-	return 0;
+	/* override auto int and install CIA handler */
+	m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
+	m68k_irq_startup(base->handler_irq);
+	request_irq(base->handler_irq, cia_handler, SA_SHIRQ, base->name, base);
 }
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 12e3706..b5b8a41 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -87,17 +87,8 @@
 static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 /* amiga specific irq functions */
 extern void amiga_init_IRQ (void);
-extern irqreturn_t (*amiga_default_handler[]) (int, void *, struct pt_regs *);
-extern int amiga_request_irq (unsigned int irq,
-			      irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                              unsigned long flags, const char *devname,
-			      void *dev_id);
-extern void amiga_free_irq (unsigned int irq, void *dev_id);
-extern void amiga_enable_irq (unsigned int);
-extern void amiga_disable_irq (unsigned int);
 static void amiga_get_model(char *model);
 static int amiga_get_hardware_list(char *buffer);
-extern int show_amiga_interrupts (struct seq_file *, void *);
 /* amiga specific timer functions */
 static unsigned long amiga_gettimeoffset (void);
 static int a3000_hwclk (int, struct rtc_time *);
@@ -392,14 +383,8 @@
 
   mach_sched_init      = amiga_sched_init;
   mach_init_IRQ        = amiga_init_IRQ;
-  mach_default_handler = &amiga_default_handler;
-  mach_request_irq     = amiga_request_irq;
-  mach_free_irq        = amiga_free_irq;
-  enable_irq           = amiga_enable_irq;
-  disable_irq          = amiga_disable_irq;
   mach_get_model       = amiga_get_model;
   mach_get_hardware_list = amiga_get_hardware_list;
-  mach_get_irq_list    = show_amiga_interrupts;
   mach_gettimeoffset   = amiga_gettimeoffset;
   if (AMIGAHW_PRESENT(A3000_CLK)){
     mach_hwclk         = a3000_hwclk;
diff --git a/arch/m68k/apollo/Makefile b/arch/m68k/apollo/Makefile
index 39264f3..76a0579 100644
--- a/arch/m68k/apollo/Makefile
+++ b/arch/m68k/apollo/Makefile
@@ -2,4 +2,4 @@
 # Makefile for Linux arch/m68k/amiga source directory
 #
 
-obj-y		:= config.o dn_ints.o dma.o
+obj-y		:= config.o dn_ints.o
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index d401962..99c7097 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -28,11 +28,6 @@
 
 extern void dn_sched_init(irqreturn_t (*handler)(int,void *,struct pt_regs *));
 extern void dn_init_IRQ(void);
-extern int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
-extern void dn_free_irq(unsigned int irq, void *dev_id);
-extern void dn_enable_irq(unsigned int);
-extern void dn_disable_irq(unsigned int);
-extern int show_dn_interrupts(struct seq_file *, void *);
 extern unsigned long dn_gettimeoffset(void);
 extern int dn_dummy_hwclk(int, struct rtc_time *);
 extern int dn_dummy_set_clock_mmss(unsigned long);
@@ -40,13 +35,11 @@
 extern void dn_dummy_waitbut(void);
 extern struct fb_info *dn_fb_init(long *);
 extern void dn_dummy_debug_init(void);
-extern void dn_dummy_video_setup(char *,int *);
 extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
 #ifdef CONFIG_HEARTBEAT
 static void dn_heartbeat(int on);
 #endif
 static irqreturn_t dn_timer_int(int irq,void *, struct pt_regs *);
-static irqreturn_t (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL;
 static void dn_get_model(char *model);
 static const char *apollo_models[] = {
 	[APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)",
@@ -164,17 +157,10 @@
 
 	mach_sched_init=dn_sched_init; /* */
 	mach_init_IRQ=dn_init_IRQ;
-	mach_default_handler=NULL;
-	mach_request_irq     = dn_request_irq;
-	mach_free_irq        = dn_free_irq;
-	enable_irq      = dn_enable_irq;
-	disable_irq     = dn_disable_irq;
-	mach_get_irq_list    = show_dn_interrupts;
 	mach_gettimeoffset   = dn_gettimeoffset;
 	mach_max_dma_address = 0xffffffff;
 	mach_hwclk           = dn_dummy_hwclk; /* */
 	mach_set_clock_mmss  = dn_dummy_set_clock_mmss; /* */
-	mach_process_int     = dn_process_int;
 	mach_reset	     = dn_dummy_reset;  /* */
 #ifdef CONFIG_HEARTBEAT
 	mach_heartbeat = dn_heartbeat;
@@ -189,11 +175,13 @@
 
 }
 
-irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp) {
+irqreturn_t dn_timer_int(int irq, void *dev_id, struct pt_regs *fp)
+{
+	irqreturn_t (*timer_handler)(int, void *, struct pt_regs *) = dev_id;
 
 	volatile unsigned char x;
 
-	sched_timer_handler(irq,dev_id,fp);
+	timer_handler(irq, dev_id, fp);
 
 	x=*(volatile unsigned char *)(timer+3);
 	x=*(volatile unsigned char *)(timer+5);
@@ -217,9 +205,7 @@
 	printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
 #endif
 
-	sched_timer_handler=timer_routine;
-	request_irq(0,dn_timer_int,0,NULL,NULL);
-
+	request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine);
 }
 
 unsigned long dn_gettimeoffset(void) {
diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c
index a312593..9fe0780 100644
--- a/arch/m68k/apollo/dn_ints.c
+++ b/arch/m68k/apollo/dn_ints.c
@@ -1,125 +1,44 @@
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/kernel_stat.h>
-#include <linux/timer.h>
+#include <linux/interrupt.h>
 
-#include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
-#include <asm/page.h>
-#include <asm/machdep.h>
 #include <asm/apollohw.h>
-#include <asm/errno.h>
 
-static irq_handler_t dn_irqs[16];
-
-irqreturn_t dn_process_int(int irq, struct pt_regs *fp)
+void dn_process_int(unsigned int irq, struct pt_regs *fp)
 {
-  irqreturn_t res = IRQ_NONE;
+	m68k_handle_int(irq, fp);
 
-  if(dn_irqs[irq-160].handler) {
-    res = dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
-  } else {
-    printk("spurious irq %d occurred\n",irq);
-  }
-
-  *(volatile unsigned char *)(pica)=0x20;
-  *(volatile unsigned char *)(picb)=0x20;
-
-  return res;
+	*(volatile unsigned char *)(pica)=0x20;
+	*(volatile unsigned char *)(picb)=0x20;
 }
 
-void dn_init_IRQ(void) {
-
-  int i;
-
-  for(i=0;i<16;i++) {
-    dn_irqs[i].handler=NULL;
-    dn_irqs[i].flags=IRQ_FLG_STD;
-    dn_irqs[i].dev_id=NULL;
-    dn_irqs[i].devname=NULL;
-  }
-
+int apollo_irq_startup(unsigned int irq)
+{
+	if (irq < 8)
+		*(volatile unsigned char *)(pica+1) &= ~(1 << irq);
+	else
+		*(volatile unsigned char *)(picb+1) &= ~(1 << (irq - 8));
+	return 0;
 }
 
-int dn_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) {
-
-  if((irq<0) || (irq>15)) {
-    printk("Trying to request invalid IRQ\n");
-    return -ENXIO;
-  }
-
-  if(!dn_irqs[irq].handler) {
-    dn_irqs[irq].handler=handler;
-    dn_irqs[irq].flags=IRQ_FLG_STD;
-    dn_irqs[irq].dev_id=dev_id;
-    dn_irqs[irq].devname=devname;
-    if(irq<8)
-      *(volatile unsigned char *)(pica+1)&=~(1<<irq);
-    else
-      *(volatile unsigned char *)(picb+1)&=~(1<<(irq-8));
-
-    return 0;
-  }
-  else {
-    printk("Trying to request already assigned irq %d\n",irq);
-    return -ENXIO;
-  }
-
+void apollo_irq_shutdown(unsigned int irq)
+{
+	if (irq < 8)
+		*(volatile unsigned char *)(pica+1) |= (1 << irq);
+	else
+		*(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
 }
 
-void dn_free_irq(unsigned int irq, void *dev_id) {
+static struct irq_controller apollo_irq_controller = {
+	.name           = "apollo",
+	.lock           = SPIN_LOCK_UNLOCKED,
+	.startup        = apollo_irq_startup,
+	.shutdown       = apollo_irq_shutdown,
+};
 
-  if((irq<0) || (irq>15)) {
-    printk("Trying to free invalid IRQ\n");
-    return ;
-  }
 
-  if(irq<8)
-    *(volatile unsigned char *)(pica+1)|=(1<<irq);
-  else
-    *(volatile unsigned char *)(picb+1)|=(1<<(irq-8));
-
-  dn_irqs[irq].handler=NULL;
-  dn_irqs[irq].flags=IRQ_FLG_STD;
-  dn_irqs[irq].dev_id=NULL;
-  dn_irqs[irq].devname=NULL;
-
-  return ;
-
-}
-
-void dn_enable_irq(unsigned int irq) {
-
-  printk("dn enable irq\n");
-
-}
-
-void dn_disable_irq(unsigned int irq) {
-
-  printk("dn disable irq\n");
-
-}
-
-int show_dn_interrupts(struct seq_file *p, void *v) {
-
-  printk("dn get irq list\n");
-
-  return 0;
-
-}
-
-struct fb_info *dn_dummy_fb_init(long *mem_start) {
-
-  printk("fb init\n");
-
-  return NULL;
-
-}
-
-void dn_dummy_video_setup(char *options,int *ints) {
-
-  printk("no video yet\n");
-
+void dn_init_IRQ(void)
+{
+	m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
+	m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
 }
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 076f479..ece13cb 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -104,6 +104,7 @@
  * the sr copy in the frame.
  */
 
+#if 0
 
 #define	NUM_INT_SOURCES	(8 + NUM_ATARI_SOURCES)
 
@@ -133,13 +134,6 @@
  */
 static struct irqparam irq_param[NUM_INT_SOURCES];
 
-/*
- * Bitmap for free interrupt vector numbers
- * (new vectors starting from 0x70 can be allocated by
- * atari_register_vme_int())
- */
-static int free_vme_vec_bitmap;
-
 /* check for valid int number (complex, sigh...) */
 #define	IS_VALID_INTNO(n)											\
 	((n) > 0 &&														\
@@ -301,6 +295,14 @@
 );
 	for (;;);
 }
+#endif
+
+/*
+ * Bitmap for free interrupt vector numbers
+ * (new vectors starting from 0x70 can be allocated by
+ * atari_register_vme_int())
+ */
+static int free_vme_vec_bitmap;
 
 /* GK:
  * HBL IRQ handler for Falcon. Nobody needs it :-)
@@ -313,13 +315,34 @@
 	"orw	#0x200,%sp@\n\t"	/* set saved ipl to 2 */
 	"rte");
 
-/* Defined in entry.S; only increments 'num_spurious' */
-asmlinkage void bad_interrupt(void);
-
-extern void atari_microwire_cmd( int cmd );
+extern void atari_microwire_cmd(int cmd);
 
 extern int atari_SCC_reset_done;
 
+static int atari_startup_irq(unsigned int irq)
+{
+	m68k_irq_startup(irq);
+	atari_turnon_irq(irq);
+	atari_enable_irq(irq);
+	return 0;
+}
+
+static void atari_shutdown_irq(unsigned int irq)
+{
+	atari_disable_irq(irq);
+	atari_turnoff_irq(irq);
+	m68k_irq_shutdown(irq);
+}
+
+static struct irq_controller atari_irq_controller = {
+	.name		= "atari",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.startup	= atari_startup_irq,
+	.shutdown	= atari_shutdown_irq,
+	.enable		= atari_enable_irq,
+	.disable	= atari_disable_irq,
+};
+
 /*
  * void atari_init_IRQ (void)
  *
@@ -333,12 +356,8 @@
 
 void __init atari_init_IRQ(void)
 {
-	int i;
-
-	/* initialize the vector table */
-	for (i = 0; i < NUM_INT_SOURCES; ++i) {
-		vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt;
-	}
+	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+	m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
 
 	/* Initialize the MFP(s) */
 
@@ -378,8 +397,7 @@
 									 * enabled in VME mask
 									 */
 		tt_scu.vme_mask = 0x60;		/* enable MFP and SCC ints */
-	}
-	else {
+	} else {
 		/* If no SCU and no Hades, the HSYNC interrupt needs to be
 		 * disabled this way. (Else _inthandler in kernel/sys_call.S
 		 * gets overruns)
@@ -404,184 +422,6 @@
 }
 
 
-static irqreturn_t atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp )
-{
-	irq_node_t *node;
-
-	for (node = (irq_node_t *)dev_id; node; node = node->next)
-		node->handler(irq, node->dev_id, fp);
-	return IRQ_HANDLED;
-}
-
-
-/*
- * atari_request_irq : add an interrupt service routine for a particular
- *                     machine specific interrupt source.
- *                     If the addition was successful, it returns 0.
- */
-
-int atari_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                      unsigned long flags, const char *devname, void *dev_id)
-{
-	int vector;
-	unsigned long oflags = flags;
-
-	/*
-	 * The following is a hack to make some PCI card drivers work,
-	 * which set the SA_SHIRQ flag.
-	 */
-
-	flags &= ~SA_SHIRQ;
-
-	if (flags == SA_INTERRUPT) {
-		printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n",
-			__FUNCTION__, devname);
-		flags = IRQ_TYPE_SLOW;
-	}
-	if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
-		printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n",
-		        __FUNCTION__, flags, oflags, devname);
-		return -EINVAL;
-	}
-	if (!IS_VALID_INTNO(irq)) {
-		printk ("%s: Unknown irq %d requested from %s\n",
-		        __FUNCTION__, irq, devname);
-		return -ENXIO;
-	}
-	vector = IRQ_SOURCE_TO_VECTOR(irq);
-
-	/*
-	 * Check type/source combination: slow ints are (currently)
-	 * only possible for MFP-interrupts.
-	 */
-	if (flags == IRQ_TYPE_SLOW &&
-		(irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) {
-		printk ("%s: Slow irq requested for non-MFP source %d from %s\n",
-		        __FUNCTION__, irq, devname);
-		return -EINVAL;
-	}
-
-	if (vectors[vector] == bad_interrupt) {
-		/* int has no handler yet */
-		irq_handler[irq].handler = handler;
-		irq_handler[irq].dev_id  = dev_id;
-		irq_param[irq].flags   = flags;
-		irq_param[irq].devname = devname;
-		vectors[vector] =
-			(flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] :
-			(flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler :
-			                          atari_prio_irq_handler;
-		/* If MFP int, also enable and umask it */
-		atari_turnon_irq(irq);
-		atari_enable_irq(irq);
-
-		return 0;
-	}
-	else if (irq_param[irq].flags == flags) {
-		/* old handler is of same type -> handlers can be chained */
-		irq_node_t *node;
-		unsigned long flags;
-
-		local_irq_save(flags);
-
-		if (irq_handler[irq].handler != atari_call_irq_list) {
-			/* Only one handler yet, make a node for this first one */
-			if (!(node = new_irq_node()))
-				return -ENOMEM;
-			node->handler = irq_handler[irq].handler;
-			node->dev_id  = irq_handler[irq].dev_id;
-			node->devname = irq_param[irq].devname;
-			node->next = NULL;
-
-			irq_handler[irq].handler = atari_call_irq_list;
-			irq_handler[irq].dev_id  = node;
-			irq_param[irq].devname   = "chained";
-		}
-
-		if (!(node = new_irq_node()))
-			return -ENOMEM;
-		node->handler = handler;
-		node->dev_id  = dev_id;
-		node->devname = devname;
-		/* new handlers are put in front of the queue */
-		node->next = irq_handler[irq].dev_id;
-		irq_handler[irq].dev_id = node;
-
-		local_irq_restore(flags);
-		return 0;
-	} else {
-		printk ("%s: Irq %d allocated by other type int (call from %s)\n",
-		        __FUNCTION__, irq, devname);
-		return -EBUSY;
-	}
-}
-
-void atari_free_irq(unsigned int irq, void *dev_id)
-{
-	unsigned long flags;
-	int vector;
-	irq_node_t **list, *node;
-
-	if (!IS_VALID_INTNO(irq)) {
-		printk("%s: Unknown irq %d\n", __FUNCTION__, irq);
-		return;
-	}
-
-	vector = IRQ_SOURCE_TO_VECTOR(irq);
-	if (vectors[vector] == bad_interrupt)
-		goto not_found;
-
-	local_irq_save(flags);
-
-	if (irq_handler[irq].handler != atari_call_irq_list) {
-		/* It's the only handler for the interrupt */
-		if (irq_handler[irq].dev_id != dev_id) {
-			local_irq_restore(flags);
-			goto not_found;
-		}
-		irq_handler[irq].handler = NULL;
-		irq_handler[irq].dev_id  = NULL;
-		irq_param[irq].devname   = NULL;
-		vectors[vector] = bad_interrupt;
-		/* If MFP int, also disable it */
-		atari_disable_irq(irq);
-		atari_turnoff_irq(irq);
-
-		local_irq_restore(flags);
-		return;
-	}
-
-	/* The interrupt is chained, find the irq on the list */
-	for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) {
-		if ((*list)->dev_id == dev_id) break;
-	}
-	if (!*list) {
-		local_irq_restore(flags);
-		goto not_found;
-	}
-
-	(*list)->handler = NULL; /* Mark it as free for reallocation */
-	*list = (*list)->next;
-
-	/* If there's now only one handler, unchain the interrupt, i.e. plug in
-	 * the handler directly again and omit atari_call_irq_list */
-	node = (irq_node_t *)irq_handler[irq].dev_id;
-	if (node && !node->next) {
-		irq_handler[irq].handler = node->handler;
-		irq_handler[irq].dev_id  = node->dev_id;
-		irq_param[irq].devname   = node->devname;
-		node->handler = NULL; /* Mark it as free for reallocation */
-	}
-
-	local_irq_restore(flags);
-	return;
-
-not_found:
-	printk("%s: tried to remove invalid irq\n", __FUNCTION__);
-	return;
-}
-
-
 /*
  * atari_register_vme_int() returns the number of a free interrupt vector for
  * hardware with a programmable int vector (probably a VME board).
@@ -591,58 +431,24 @@
 {
 	int i;
 
-	for(i = 0; i < 32; i++)
-		if((free_vme_vec_bitmap & (1 << i)) == 0)
+	for (i = 0; i < 32; i++)
+		if ((free_vme_vec_bitmap & (1 << i)) == 0)
 			break;
 
-	if(i == 16)
+	if (i == 16)
 		return 0;
 
 	free_vme_vec_bitmap |= 1 << i;
-	return (VME_SOURCE_BASE + i);
+	return VME_SOURCE_BASE + i;
 }
 
 
 void atari_unregister_vme_int(unsigned long irq)
 {
-	if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
+	if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) {
 		irq -= VME_SOURCE_BASE;
 		free_vme_vec_bitmap &= ~(1 << irq);
 	}
 }
 
 
-int show_atari_interrupts(struct seq_file *p, void *v)
-{
-	int i;
-
-	for (i = 0; i < NUM_INT_SOURCES; ++i) {
-		if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
-			continue;
-		if (i < STMFP_SOURCE_BASE)
-			seq_printf(p, "auto %2d: %10u ",
-				       i, kstat_cpu(0).irqs[i]);
-		else
-			seq_printf(p, "vec $%02x: %10u ",
-				       IRQ_SOURCE_TO_VECTOR(i),
-				       kstat_cpu(0).irqs[i]);
-
-		if (irq_handler[i].handler != atari_call_irq_list) {
-			seq_printf(p, "%s\n", irq_param[i].devname);
-		}
-		else {
-			irq_node_t *n;
-			for( n = (irq_node_t *)irq_handler[i].dev_id; n; n = n->next ) {
-				seq_printf(p, "%s\n", n->devname);
-				if (n->next)
-					seq_puts(p, "                    " );
-			}
-		}
-	}
-	if (num_spurious)
-		seq_printf(p, "spurio.: %10u\n", num_spurious);
-
-	return 0;
-}
-
-
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 1012b08e5..727289a 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -57,12 +57,6 @@
 
 /* atari specific irq functions */
 extern void atari_init_IRQ (void);
-extern int atari_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                              unsigned long flags, const char *devname, void *dev_id);
-extern void atari_free_irq (unsigned int irq, void *dev_id);
-extern void atari_enable_irq (unsigned int);
-extern void atari_disable_irq (unsigned int);
-extern int show_atari_interrupts (struct seq_file *, void *);
 extern void atari_mksound( unsigned int count, unsigned int ticks );
 #ifdef CONFIG_HEARTBEAT
 static void atari_heartbeat( int on );
@@ -232,13 +226,8 @@
 
     mach_sched_init      = atari_sched_init;
     mach_init_IRQ        = atari_init_IRQ;
-    mach_request_irq     = atari_request_irq;
-    mach_free_irq        = atari_free_irq;
-    enable_irq           = atari_enable_irq;
-    disable_irq          = atari_disable_irq;
     mach_get_model	 = atari_get_model;
     mach_get_hardware_list = atari_get_hardware_list;
-    mach_get_irq_list	 = show_atari_interrupts;
     mach_gettimeoffset   = atari_gettimeoffset;
     mach_reset           = atari_reset;
     mach_max_dma_address = 0xffffff;
diff --git a/arch/m68k/bvme6000/Makefile b/arch/m68k/bvme6000/Makefile
index 2348e6c..d817400 100644
--- a/arch/m68k/bvme6000/Makefile
+++ b/arch/m68k/bvme6000/Makefile
@@ -2,4 +2,4 @@
 # Makefile for Linux arch/m68k/bvme6000 source directory
 #
 
-obj-y		:= config.o bvmeints.o rtc.o
+obj-y		:= config.o rtc.o
diff --git a/arch/m68k/bvme6000/bvmeints.c b/arch/m68k/bvme6000/bvmeints.c
deleted file mode 100644
index 298a8df..0000000
--- a/arch/m68k/bvme6000/bvmeints.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * arch/m68k/bvme6000/bvmeints.c
- *
- * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * based on amiints.c -- Amiga Linux interrupt handling code
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/seq_file.h>
-
-#include <asm/ptrace.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/traps.h>
-
-static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp);
-
-/*
- * This should ideally be 4 elements only, for speed.
- */
-
-static struct {
-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
-	unsigned long	flags;
-	void		*dev_id;
-	const char	*devname;
-	unsigned	count;
-} irq_tab[256];
-
-/*
- * void bvme6000_init_IRQ (void)
- *
- * Parameters:	None
- *
- * Returns:	Nothing
- *
- * This function is called during kernel startup to initialize
- * the bvme6000 IRQ handling routines.
- */
-
-void bvme6000_init_IRQ (void)
-{
-	int i;
-
-	for (i = 0; i < 256; i++) {
-		irq_tab[i].handler = bvme6000_defhand;
-		irq_tab[i].flags = IRQ_FLG_STD;
-		irq_tab[i].dev_id = NULL;
-		irq_tab[i].devname = NULL;
-		irq_tab[i].count = 0;
-	}
-}
-
-int bvme6000_request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                unsigned long flags, const char *devname, void *dev_id)
-{
-	if (irq > 255) {
-		printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
-		return -ENXIO;
-	}
-#if 0
-	/* Nothing special about auto-vectored devices for the BVME6000,
-	 * but treat it specially to avoid changes elsewhere.
-	 */
-
-	if (irq >= VEC_INT1 && irq <= VEC_INT7)
-		return cpu_request_irq(irq - VEC_SPUR, handler, flags,
-						devname, dev_id);
-#endif
-	if (!(irq_tab[irq].flags & IRQ_FLG_STD)) {
-		if (irq_tab[irq].flags & IRQ_FLG_LOCK) {
-			printk("%s: IRQ %d from %s is not replaceable\n",
-			       __FUNCTION__, irq, irq_tab[irq].devname);
-			return -EBUSY;
-		}
-		if (flags & IRQ_FLG_REPLACE) {
-			printk("%s: %s can't replace IRQ %d from %s\n",
-			       __FUNCTION__, devname, irq, irq_tab[irq].devname);
-			return -EBUSY;
-		}
-	}
-	irq_tab[irq].handler = handler;
-	irq_tab[irq].flags   = flags;
-	irq_tab[irq].dev_id  = dev_id;
-	irq_tab[irq].devname = devname;
-	return 0;
-}
-
-void bvme6000_free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq > 255) {
-		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
-		return;
-	}
-#if 0
-	if (irq >= VEC_INT1 && irq <= VEC_INT7) {
-		cpu_free_irq(irq - VEC_SPUR, dev_id);
-		return;
-	}
-#endif
-	if (irq_tab[irq].dev_id != dev_id)
-		printk("%s: Removing probably wrong IRQ %d from %s\n",
-		       __FUNCTION__, irq, irq_tab[irq].devname);
-
-	irq_tab[irq].handler = bvme6000_defhand;
-	irq_tab[irq].flags   = IRQ_FLG_STD;
-	irq_tab[irq].dev_id  = NULL;
-	irq_tab[irq].devname = NULL;
-}
-
-irqreturn_t bvme6000_process_int (unsigned long vec, struct pt_regs *fp)
-{
-	if (vec > 255) {
-		printk ("bvme6000_process_int: Illegal vector %ld", vec);
-		return IRQ_NONE;
-	} else {
-		irq_tab[vec].count++;
-		irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
-		return IRQ_HANDLED;
-	}
-}
-
-int show_bvme6000_interrupts(struct seq_file *p, void *v)
-{
-	int i;
-
-	for (i = 0; i < 256; i++) {
-		if (irq_tab[i].count)
-			seq_printf(p, "Vec 0x%02x: %8d  %s\n",
-			    i, irq_tab[i].count,
-			    irq_tab[i].devname ? irq_tab[i].devname : "free");
-	}
-	return 0;
-}
-
-
-static irqreturn_t bvme6000_defhand (int irq, void *dev_id, struct pt_regs *fp)
-{
-	printk ("Unknown interrupt 0x%02x\n", irq);
-	return IRQ_NONE;
-}
-
-void bvme6000_enable_irq (unsigned int irq)
-{
-}
-
-
-void bvme6000_disable_irq (unsigned int irq)
-{
-}
-
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index c90cb5f..d1e916a 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -36,15 +36,8 @@
 #include <asm/machdep.h>
 #include <asm/bvme6000hw.h>
 
-extern irqreturn_t bvme6000_process_int (int level, struct pt_regs *regs);
-extern void bvme6000_init_IRQ (void);
-extern void bvme6000_free_irq (unsigned int, void *);
-extern int  show_bvme6000_interrupts(struct seq_file *, void *);
-extern void bvme6000_enable_irq (unsigned int);
-extern void bvme6000_disable_irq (unsigned int);
 static void bvme6000_get_model(char *model);
 static int  bvme6000_get_hardware_list(char *buffer);
-extern int  bvme6000_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
 extern void bvme6000_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern unsigned long bvme6000_gettimeoffset (void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
@@ -100,6 +93,14 @@
     return 0;
 }
 
+/*
+ * This function is called during kernel startup to initialize
+ * the bvme6000 IRQ handling routines.
+ */
+static void bvme6000_init_IRQ(void)
+{
+	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+}
 
 void __init config_bvme6000(void)
 {
@@ -127,12 +128,6 @@
     mach_hwclk           = bvme6000_hwclk;
     mach_set_clock_mmss	 = bvme6000_set_clock_mmss;
     mach_reset		 = bvme6000_reset;
-    mach_free_irq	 = bvme6000_free_irq;
-    mach_process_int	 = bvme6000_process_int;
-    mach_get_irq_list	 = show_bvme6000_interrupts;
-    mach_request_irq	 = bvme6000_request_irq;
-    enable_irq		 = bvme6000_enable_irq;
-    disable_irq          = bvme6000_disable_irq;
     mach_get_model       = bvme6000_get_model;
     mach_get_hardware_list = bvme6000_get_hardware_list;
 
diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
index 89b6317..288b9c6 100644
--- a/arch/m68k/hp300/Makefile
+++ b/arch/m68k/hp300/Makefile
@@ -2,4 +2,4 @@
 # Makefile for Linux arch/m68k/hp300 source directory
 #
 
-obj-y		:= ksyms.o config.o ints.o time.o reboot.o
+obj-y		:= ksyms.o config.o time.o reboot.o
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index 6d129ee..2ef271c 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -21,7 +21,6 @@
 #include <asm/hp300hw.h>
 #include <asm/rtc.h>
 
-#include "ints.h"
 #include "time.h"
 
 unsigned long hp300_model;
@@ -64,8 +63,6 @@
 static char hp300_model_name[13] = "HP9000/";
 
 extern void hp300_reset(void);
-extern irqreturn_t (*hp300_default_handler[])(int, void *, struct pt_regs *);
-extern int show_hp300_interrupts(struct seq_file *, void *);
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 extern int hp300_setup_serial_console(void) __init;
 #endif
@@ -245,16 +242,16 @@
 		hp300_rtc_read(RTC_REG_SEC2);
 }
 
+static void __init hp300_init_IRQ(void)
+{
+}
+
 void __init config_hp300(void)
 {
 	mach_sched_init      = hp300_sched_init;
 	mach_init_IRQ        = hp300_init_IRQ;
-	mach_request_irq     = hp300_request_irq;
-	mach_free_irq        = hp300_free_irq;
 	mach_get_model       = hp300_get_model;
-	mach_get_irq_list    = show_hp300_interrupts;
 	mach_gettimeoffset   = hp300_gettimeoffset;
-	mach_default_handler = &hp300_default_handler;
 	mach_hwclk	     = hp300_hwclk;
 	mach_get_ss	     = hp300_get_ss;
 	mach_reset           = hp300_reset;
diff --git a/arch/m68k/hp300/ints.c b/arch/m68k/hp300/ints.c
deleted file mode 100644
index 0c5bb40..0000000
--- a/arch/m68k/hp300/ints.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- *  linux/arch/m68k/hp300/ints.c
- *
- *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
- *
- *  This file contains the HP300-specific interrupt handling.
- *  We only use the autovector interrupts, and therefore we need to
- *  maintain lists of devices sharing each ipl.
- *  [ipl list code added by Peter Maydell <pmaydell@chiark.greenend.org.uk> 06/1998]
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/traps.h>
-#include <asm/ptrace.h>
-#include <asm/errno.h>
-#include "ints.h"
-
-/* Each ipl has a linked list of interrupt service routines.
- * Service routines are added via hp300_request_irq() and removed
- * via hp300_free_irq(). The device driver should set IRQ_FLG_FAST
- * if it needs to be serviced early (eg FIFOless UARTs); this will
- * cause it to be added at the front of the queue rather than
- * the back.
- * Currently IRQ_FLG_SLOW and flags=0 are treated identically; if
- * we needed three levels of priority we could distinguish them
- * but this strikes me as mildly ugly...
- */
-
-/* we start with no entries in any list */
-static irq_node_t *hp300_irq_list[HP300_NUM_IRQS];
-
-static spinlock_t irqlist_lock;
-
-/* This handler receives all interrupts, dispatching them to the registered handlers */
-static irqreturn_t hp300_int_handler(int irq, void *dev_id, struct pt_regs *fp)
-{
-        irq_node_t *t;
-        /* We just give every handler on the chain an opportunity to handle
-         * the interrupt, in priority order.
-         */
-        for(t = hp300_irq_list[irq]; t; t=t->next)
-                t->handler(irq, t->dev_id, fp);
-        /* We could put in some accounting routines, checks for stray interrupts,
-         * etc, in here. Note that currently we can't tell whether or not
-         * a handler handles the interrupt, though.
-         */
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t hp300_badint(int irq, void *dev_id, struct pt_regs *fp)
-{
-	num_spurious += 1;
-	return IRQ_NONE;
-}
-
-irqreturn_t (*hp300_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	[0] = hp300_badint,
-	[1] = hp300_int_handler,
-	[2] = hp300_int_handler,
-	[3] = hp300_int_handler,
-	[4] = hp300_int_handler,
-	[5] = hp300_int_handler,
-	[6] = hp300_int_handler,
-	[7] = hp300_int_handler
-};
-
-/* dev_id had better be unique to each handler because it's the only way we have
- * to distinguish handlers when removing them...
- *
- * It would be pretty easy to support IRQ_FLG_LOCK (handler is not replacable)
- * and IRQ_FLG_REPLACE (handler replaces existing one with this dev_id)
- * if we wanted to. IRQ_FLG_FAST is needed for devices where interrupt latency
- * matters (eg the dreaded FIFOless UART...)
- */
-int hp300_request_irq(unsigned int irq,
-                      irqreturn_t (*handler) (int, void *, struct pt_regs *),
-                      unsigned long flags, const char *devname, void *dev_id)
-{
-        irq_node_t *t, *n = new_irq_node();
-
-        if (!n)                                   /* oops, no free nodes */
-                return -ENOMEM;
-
-	spin_lock_irqsave(&irqlist_lock, flags);
-
-        if (!hp300_irq_list[irq]) {
-                /* no list yet */
-                hp300_irq_list[irq] = n;
-                n->next = NULL;
-        } else if (flags & IRQ_FLG_FAST) {
-                /* insert at head of list */
-                n->next = hp300_irq_list[irq];
-                hp300_irq_list[irq] = n;
-        } else {
-                /* insert at end of list */
-                for(t = hp300_irq_list[irq]; t->next; t = t->next)
-                        /* do nothing */;
-                n->next = NULL;
-                t->next = n;
-        }
-
-        /* Fill in n appropriately */
-        n->handler = handler;
-        n->flags = flags;
-        n->dev_id = dev_id;
-        n->devname = devname;
-	spin_unlock_irqrestore(&irqlist_lock, flags);
-	return 0;
-}
-
-void hp300_free_irq(unsigned int irq, void *dev_id)
-{
-        irq_node_t *t;
-        unsigned long flags;
-
-        spin_lock_irqsave(&irqlist_lock, flags);
-
-        t = hp300_irq_list[irq];
-        if (!t)                                   /* no handlers at all for that IRQ */
-        {
-                printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq);
-                spin_unlock_irqrestore(&irqlist_lock, flags);
-		return;
-        }
-
-        if (t->dev_id == dev_id)
-        {                                         /* removing first handler on chain */
-                t->flags = IRQ_FLG_STD;           /* we probably don't really need these */
-                t->dev_id = NULL;
-                t->devname = NULL;
-                t->handler = NULL;                /* frees this irq_node_t */
-                hp300_irq_list[irq] = t->next;
-		spin_unlock_irqrestore(&irqlist_lock, flags);
-		return;
-        }
-
-        /* OK, must be removing from middle of the chain */
-
-        for (t = hp300_irq_list[irq]; t->next && t->next->dev_id != dev_id; t = t->next)
-                /* do nothing */;
-        if (!t->next)
-        {
-                printk(KERN_ERR "hp300_free_irq: attempt to remove nonexistent handler for IRQ %d\n", irq);
-		spin_unlock_irqrestore(&irqlist_lock, flags);
-		return;
-        }
-        /* remove the entry after t: */
-        t->next->flags = IRQ_FLG_STD;
-        t->next->dev_id = NULL;
-	t->next->devname = NULL;
-	t->next->handler = NULL;
-        t->next = t->next->next;
-
-	spin_unlock_irqrestore(&irqlist_lock, flags);
-}
-
-int show_hp300_interrupts(struct seq_file *p, void *v)
-{
-	return 0;
-}
-
-void __init hp300_init_IRQ(void)
-{
-	spin_lock_init(&irqlist_lock);
-}
diff --git a/arch/m68k/hp300/ints.h b/arch/m68k/hp300/ints.h
deleted file mode 100644
index 8cfabe2..0000000
--- a/arch/m68k/hp300/ints.h
+++ /dev/null
@@ -1,9 +0,0 @@
-extern void hp300_init_IRQ(void);
-extern void (*hp300_handlers[8])(int, void *, struct pt_regs *);
-extern void hp300_free_irq(unsigned int irq, void *dev_id);
-extern int hp300_request_irq(unsigned int irq,
-		irqreturn_t (*handler) (int, void *, struct pt_regs *),
-		unsigned long flags, const char *devname, void *dev_id);
-
-/* number of interrupts, includes 0 (what's that?) */
-#define HP300_NUM_IRQS 8
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 8da5b1b..7df0566 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -18,7 +18,6 @@
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/blinken.h>
-#include "ints.h"
 
 /* Clock hardware definitions */
 
@@ -71,7 +70,7 @@
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  cpu_request_irq(6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
+  request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
 
   out_8(CLOCKBASE + CLKCR2, 0x1);		/* select CR1 */
   out_8(CLOCKBASE + CLKCR1, 0x40);		/* enable irq */
diff --git a/arch/m68k/kernel/Makefile b/arch/m68k/kernel/Makefile
index 458925c..dae6097 100644
--- a/arch/m68k/kernel/Makefile
+++ b/arch/m68k/kernel/Makefile
@@ -9,8 +9,8 @@
 endif
 extra-y	+= vmlinux.lds
 
-obj-y		:= entry.o process.o traps.o ints.o signal.o ptrace.o \
-			sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
+obj-y	:= entry.o process.o traps.o ints.o dma.o signal.o ptrace.o \
+	   sys_m68k.o time.o semaphore.o setup.o m68k_ksyms.o
 
 obj-$(CONFIG_PCI)	+= bios32.o
 obj-$(CONFIG_MODULES)	+= module.o
diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c
new file mode 100644
index 0000000..fc449f8
--- /dev/null
+++ b/arch/m68k/kernel/dma.c
@@ -0,0 +1,129 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#undef DEBUG
+
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+
+#include <asm/pgalloc.h>
+#include <asm/scatterlist.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *handle, int flag)
+{
+	struct page *page, **map;
+	pgprot_t pgprot;
+	void *addr;
+	int i, order;
+
+	pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	page = alloc_pages(flag, order);
+	if (!page)
+		return NULL;
+
+	*handle = page_to_phys(page);
+	map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
+	if (!map) {
+		__free_pages(page, order);
+		return NULL;
+	}
+	split_page(page, order);
+
+	order = 1 << order;
+	size >>= PAGE_SHIFT;
+	map[0] = page;
+	for (i = 1; i < size; i++)
+		map[i] = page + i;
+	for (; i < order; i++)
+		__free_page(page + i);
+	pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+	if (CPU_IS_040_OR_060)
+		pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
+	else
+		pgprot_val(pgprot) |= _PAGE_NOCACHE030;
+	addr = vmap(map, size, flag, pgprot);
+	kfree(map);
+
+	return addr;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size,
+		       void *addr, dma_addr_t handle)
+{
+	pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
+	vfree(addr);
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
+				       enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_TO_DEVICE:
+		cache_push(handle, size);
+		break;
+	case DMA_FROM_DEVICE:
+		cache_clear(handle, size);
+		break;
+	default:
+		if (printk_ratelimit())
+			printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
+		break;
+	}
+}
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
+			    enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nents; sg++, i++)
+		dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
+			  enum dma_data_direction dir)
+{
+	dma_addr_t handle = virt_to_bus(addr);
+
+	dma_sync_single_for_device(dev, handle, size, dir);
+	return handle;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+			unsigned long offset, size_t size,
+			enum dma_data_direction dir)
+{
+	dma_addr_t handle = page_to_phys(page) + offset;
+
+	dma_sync_single_for_device(dev, handle, size, dir);
+	return handle;
+}
+EXPORT_SYMBOL(dma_map_page);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	       enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nents; sg++, i++) {
+		sg->dma_address = page_to_phys(sg->page) + sg->offset;
+		dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+	}
+	return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 320fde0..449b62b 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -45,9 +45,11 @@
 #include <asm/asm-offsets.h>
 
 .globl system_call, buserr, trap, resume
-.globl inthandler, sys_call_table
+.globl sys_call_table
 .globl sys_fork, sys_clone, sys_vfork
 .globl ret_from_interrupt, bad_interrupt
+.globl auto_irqhandler_fixup
+.globl user_irqvec_fixup, user_irqhandler_fixup
 
 .text
 ENTRY(buserr)
@@ -191,65 +193,29 @@
 	jbra	resume_userspace
 
 
-#if 0
-#ifdef CONFIG_AMIGA
-ami_inthandler:
-	addql	#1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT
+/* This is the main interrupt handler for autovector interrupts */
+
+ENTRY(auto_inthandler)
 	SAVE_ALL_INT
 	GET_CURRENT(%d0)
-
-	bfextu	%sp@(PT_VECTOR){#4,#12},%d0
-	movel	%d0,%a0
-	addql	#1,%a0@(kstat+STAT_IRQ-VECOFF(VEC_SPUR))
-	movel	%a0@(autoirq_list-VECOFF(VEC_SPUR)),%a0
-
-| amiga vector int handler get the req mask instead of irq vector
-	lea	CUSTOMBASE,%a1
-	movew	%a1@(C_INTREQR),%d0
-	andw	%a1@(C_INTENAR),%d0
-
-| prepare stack (push frame pointer, dev_id & req mask)
-	pea	%sp@
-	movel	%a0@(IRQ_DEVID),%sp@-
-	movel	%d0,%sp@-
-	pea	%pc@(ret_from_interrupt:w)
-	jbra	@(IRQ_HANDLER,%a0)@(0)
-
-ENTRY(nmi_handler)
-	rte
-#endif
-#endif
-
-/*
-** This is the main interrupt handler, responsible for calling process_int()
-*/
-inthandler:
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
+	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
 					|  put exception # in d0
-	bfextu %sp@(PT_VECTOR){#4,#10},%d0
+	bfextu	%sp@(PT_VECTOR){#4,#10},%d0
+	subw	#VEC_SPUR,%d0
 
 	movel	%sp,%sp@-
 	movel	%d0,%sp@-		|  put vector # on stack
-#if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD)
-	btstb	#4,0xff000000		| Q40 floppy needs very special treatment ...
-	jbeq	1f
-	btstb	#3,0xff000004
-	jbeq	1f
-	jbsr	floppy_hardint
-	jbra	3f
-1:
-#endif
-	jbsr	process_int		|  process the IRQ
-3:	addql	#8,%sp			|  pop parameters off stack
+auto_irqhandler_fixup = . + 2
+	jsr	m68k_handle_int		|  process the IRQ
+	addql	#8,%sp			|  pop parameters off stack
 
 ret_from_interrupt:
-	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+2)
-	jeq	1f
-2:
-	RESTORE_ALL
-1:
+	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+	jeq	ret_from_last_interrupt
+2:	RESTORE_ALL
+
+	ALIGN
+ret_from_last_interrupt:
 	moveq	#(~ALLOWINT>>8)&0xff,%d0
 	andb	%sp@(PT_SR),%d0
 	jne	2b
@@ -260,12 +226,42 @@
 	pea	ret_from_exception
 	jra	do_softirq
 
+/* Handler for user defined interrupt vectors */
+
+ENTRY(user_inthandler)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+					|  put exception # in d0
+	bfextu	%sp@(PT_VECTOR){#4,#10},%d0
+user_irqvec_fixup = . + 2
+	subw	#VEC_USER,%d0
+
+	movel	%sp,%sp@-
+	movel	%d0,%sp@-		|  put vector # on stack
+user_irqhandler_fixup = . + 2
+	jsr	m68k_handle_int		|  process the IRQ
+	addql	#8,%sp			|  pop parameters off stack
+
+	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+	jeq	ret_from_last_interrupt
+	RESTORE_ALL
 
 /* Handler for uninitialized and spurious interrupts */
 
-bad_interrupt:
-	addql	#1,num_spurious
-	rte
+ENTRY(bad_inthandler)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+
+	movel	%sp,%sp@-
+	jsr	handle_badint
+	addql	#4,%sp
+
+	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+	jeq	ret_from_last_interrupt
+	RESTORE_ALL
+
 
 ENTRY(sys_fork)
 	SAVE_SWITCH_STACK
diff --git a/arch/m68k/kernel/ints.c b/arch/m68k/kernel/ints.c
index 514d323..5a8344b 100644
--- a/arch/m68k/kernel/ints.c
+++ b/arch/m68k/kernel/ints.c
@@ -39,47 +39,40 @@
 #include <asm/traps.h>
 #include <asm/page.h>
 #include <asm/machdep.h>
+#include <asm/cacheflush.h>
 
 #ifdef CONFIG_Q40
 #include <asm/q40ints.h>
 #endif
 
-/* table for system interrupt handlers */
-static irq_handler_t irq_list[SYS_IRQS];
+extern u32 auto_irqhandler_fixup[];
+extern u32 user_irqhandler_fixup[];
+extern u16 user_irqvec_fixup[];
 
-static const char *default_names[SYS_IRQS] = {
-	[0] = "spurious int",
-	[1] = "int1 handler",
-	[2] = "int2 handler",
-	[3] = "int3 handler",
-	[4] = "int4 handler",
-	[5] = "int5 handler",
-	[6] = "int6 handler",
-	[7] = "int7 handler"
+/* table for system interrupt handlers */
+static struct irq_node *irq_list[NR_IRQS];
+static struct irq_controller *irq_controller[NR_IRQS];
+static int irq_depth[NR_IRQS];
+
+static int m68k_first_user_vec;
+
+static struct irq_controller auto_irq_controller = {
+	.name		= "auto",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.startup	= m68k_irq_startup,
+	.shutdown	= m68k_irq_shutdown,
 };
 
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
+static struct irq_controller user_irq_controller = {
+	.name		= "user",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.startup	= m68k_irq_startup,
+	.shutdown	= m68k_irq_shutdown,
+};
 
 #define NUM_IRQ_NODES 100
 static irq_node_t nodes[NUM_IRQ_NODES];
 
-static void dummy_enable_irq(unsigned int irq);
-static void dummy_disable_irq(unsigned int irq);
-static int dummy_request_irq(unsigned int irq,
-		irqreturn_t (*handler) (int, void *, struct pt_regs *),
-		unsigned long flags, const char *devname, void *dev_id);
-static void dummy_free_irq(unsigned int irq, void *dev_id);
-
-void (*enable_irq) (unsigned int) = dummy_enable_irq;
-void (*disable_irq) (unsigned int) = dummy_disable_irq;
-
-int (*mach_request_irq) (unsigned int, irqreturn_t (*)(int, void *, struct pt_regs *),
-                      unsigned long, const char *, void *) = dummy_request_irq;
-void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq;
-
-void init_irq_proc(void);
-
 /*
  * void init_IRQ(void)
  *
@@ -95,18 +88,76 @@
 {
 	int i;
 
-	for (i = 0; i < SYS_IRQS; i++) {
-		if (mach_default_handler)
-			irq_list[i].handler = (*mach_default_handler)[i];
-		irq_list[i].flags   = 0;
-		irq_list[i].dev_id  = NULL;
-		irq_list[i].devname = default_names[i];
+	/* assembly irq entry code relies on this... */
+	if (HARDIRQ_MASK != 0x00ff0000) {
+		extern void hardirq_mask_is_broken(void);
+		hardirq_mask_is_broken();
 	}
 
-	for (i = 0; i < NUM_IRQ_NODES; i++)
-		nodes[i].handler = NULL;
+	for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
+		irq_controller[i] = &auto_irq_controller;
 
-	mach_init_IRQ ();
+	mach_init_IRQ();
+}
+
+/**
+ * m68k_setup_auto_interrupt
+ * @handler: called from auto vector interrupts
+ *
+ * setup the handler to be called from auto vector interrupts instead of the
+ * standard m68k_handle_int(), it will be called with irq numbers in the range
+ * from IRQ_AUTO_1 - IRQ_AUTO_7.
+ */
+void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
+{
+	if (handler)
+		*auto_irqhandler_fixup = (u32)handler;
+	flush_icache();
+}
+
+/**
+ * m68k_setup_user_interrupt
+ * @vec: first user vector interrupt to handle
+ * @cnt: number of active user vector interrupts
+ * @handler: called from user vector interrupts
+ *
+ * setup user vector interrupts, this includes activating the specified range
+ * of interrupts, only then these interrupts can be requested (note: this is
+ * different from auto vector interrupts). An optional handler can be installed
+ * to be called instead of the default m68k_handle_int(), it will be called
+ * with irq numbers starting from IRQ_USER.
+ */
+void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
+				      void (*handler)(unsigned int, struct pt_regs *))
+{
+	int i;
+
+	m68k_first_user_vec = vec;
+	for (i = 0; i < cnt; i++)
+		irq_controller[IRQ_USER + i] = &user_irq_controller;
+	*user_irqvec_fixup = vec - IRQ_USER;
+	if (handler)
+		*user_irqhandler_fixup = (u32)handler;
+	flush_icache();
+}
+
+/**
+ * m68k_setup_irq_controller
+ * @contr: irq controller which controls specified irq
+ * @irq: first irq to be managed by the controller
+ *
+ * Change the controller for the specified range of irq, which will be used to
+ * manage these irq. auto/user irq already have a default controller, which can
+ * be changed as well, but the controller probably should use m68k_irq_startup/
+ * m68k_irq_shutdown.
+ */
+void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
+			       unsigned int cnt)
+{
+	int i;
+
+	for (i = 0; i < cnt; i++)
+		irq_controller[irq + i] = contr;
 }
 
 irq_node_t *new_irq_node(void)
@@ -114,84 +165,183 @@
 	irq_node_t *node;
 	short i;
 
-	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
-		if (!node->handler)
+	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
+		if (!node->handler) {
+			memset(node, 0, sizeof(*node));
 			return node;
+		}
+	}
 
 	printk ("new_irq_node: out of nodes\n");
 	return NULL;
 }
 
-/*
- * We will keep these functions until I have convinced Linus to move
- * the declaration of them from include/linux/sched.h to
- * include/asm/irq.h.
- */
+int setup_irq(unsigned int irq, struct irq_node *node)
+{
+	struct irq_controller *contr;
+	struct irq_node **prev;
+	unsigned long flags;
+
+	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+		printk("%s: Incorrect IRQ %d from %s\n",
+		       __FUNCTION__, irq, node->devname);
+		return -ENXIO;
+	}
+
+	spin_lock_irqsave(&contr->lock, flags);
+
+	prev = irq_list + irq;
+	if (*prev) {
+		/* Can't share interrupts unless both agree to */
+		if (!((*prev)->flags & node->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&contr->lock, flags);
+			return -EBUSY;
+		}
+		while (*prev)
+			prev = &(*prev)->next;
+	}
+
+	if (!irq_list[irq]) {
+		if (contr->startup)
+			contr->startup(irq);
+		else
+			contr->enable(irq);
+	}
+	node->next = NULL;
+	*prev = node;
+
+	spin_unlock_irqrestore(&contr->lock, flags);
+
+	return 0;
+}
+
 int request_irq(unsigned int irq,
 		irqreturn_t (*handler) (int, void *, struct pt_regs *),
 		unsigned long flags, const char *devname, void *dev_id)
 {
-	return mach_request_irq(irq, handler, flags, devname, dev_id);
+	struct irq_node *node;
+	int res;
+
+	node = new_irq_node();
+	if (!node)
+		return -ENOMEM;
+
+	node->handler = handler;
+	node->flags   = flags;
+	node->dev_id  = dev_id;
+	node->devname = devname;
+
+	res = setup_irq(irq, node);
+	if (res)
+		node->handler = NULL;
+
+	return res;
 }
 
 EXPORT_SYMBOL(request_irq);
 
 void free_irq(unsigned int irq, void *dev_id)
 {
-	mach_free_irq(irq, dev_id);
-}
+	struct irq_controller *contr;
+	struct irq_node **p, *node;
+	unsigned long flags;
 
-EXPORT_SYMBOL(free_irq);
-
-int cpu_request_irq(unsigned int irq,
-                    irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                    unsigned long flags, const char *devname, void *dev_id)
-{
-	if (irq < IRQ1 || irq > IRQ7) {
-		printk("%s: Incorrect IRQ %d from %s\n",
-		       __FUNCTION__, irq, devname);
-		return -ENXIO;
-	}
-
-#if 0
-	if (!(irq_list[irq].flags & IRQ_FLG_STD)) {
-		if (irq_list[irq].flags & IRQ_FLG_LOCK) {
-			printk("%s: IRQ %d from %s is not replaceable\n",
-			       __FUNCTION__, irq, irq_list[irq].devname);
-			return -EBUSY;
-		}
-		if (!(flags & IRQ_FLG_REPLACE)) {
-			printk("%s: %s can't replace IRQ %d from %s\n",
-			       __FUNCTION__, devname, irq, irq_list[irq].devname);
-			return -EBUSY;
-		}
-	}
-#endif
-
-	irq_list[irq].handler = handler;
-	irq_list[irq].flags   = flags;
-	irq_list[irq].dev_id  = dev_id;
-	irq_list[irq].devname = devname;
-	return 0;
-}
-
-void cpu_free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq < IRQ1 || irq > IRQ7) {
+	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
 		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
 		return;
 	}
 
-	if (irq_list[irq].dev_id != dev_id)
-		printk("%s: Removing probably wrong IRQ %d from %s\n",
-		       __FUNCTION__, irq, irq_list[irq].devname);
+	spin_lock_irqsave(&contr->lock, flags);
 
-	irq_list[irq].handler = (*mach_default_handler)[irq];
-	irq_list[irq].flags   = 0;
-	irq_list[irq].dev_id  = NULL;
-	irq_list[irq].devname = default_names[irq];
+	p = irq_list + irq;
+	while ((node = *p)) {
+		if (node->dev_id == dev_id)
+			break;
+		p = &node->next;
+	}
+
+	if (node) {
+		*p = node->next;
+		node->handler = NULL;
+	} else
+		printk("%s: Removing probably wrong IRQ %d\n",
+		       __FUNCTION__, irq);
+
+	if (!irq_list[irq]) {
+		if (contr->shutdown)
+			contr->shutdown(irq);
+		else
+			contr->disable(irq);
+	}
+
+	spin_unlock_irqrestore(&contr->lock, flags);
 }
 
+EXPORT_SYMBOL(free_irq);
+
+void enable_irq(unsigned int irq)
+{
+	struct irq_controller *contr;
+	unsigned long flags;
+
+	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+		printk("%s: Incorrect IRQ %d\n",
+		       __FUNCTION__, irq);
+		return;
+	}
+
+	spin_lock_irqsave(&contr->lock, flags);
+	if (irq_depth[irq]) {
+		if (!--irq_depth[irq]) {
+			if (contr->enable)
+				contr->enable(irq);
+		}
+	} else
+		WARN_ON(1);
+	spin_unlock_irqrestore(&contr->lock, flags);
+}
+
+EXPORT_SYMBOL(enable_irq);
+
+void disable_irq(unsigned int irq)
+{
+	struct irq_controller *contr;
+	unsigned long flags;
+
+	if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
+		printk("%s: Incorrect IRQ %d\n",
+		       __FUNCTION__, irq);
+		return;
+	}
+
+	spin_lock_irqsave(&contr->lock, flags);
+	if (!irq_depth[irq]++) {
+		if (contr->disable)
+			contr->disable(irq);
+	}
+	spin_unlock_irqrestore(&contr->lock, flags);
+}
+
+EXPORT_SYMBOL(disable_irq);
+
+int m68k_irq_startup(unsigned int irq)
+{
+	if (irq <= IRQ_AUTO_7)
+		vectors[VEC_SPUR + irq] = auto_inthandler;
+	else
+		vectors[m68k_first_user_vec + irq - IRQ_USER] = user_inthandler;
+	return 0;
+}
+
+void m68k_irq_shutdown(unsigned int irq)
+{
+	if (irq <= IRQ_AUTO_7)
+		vectors[VEC_SPUR + irq] = bad_inthandler;
+	else
+		vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
+}
+
+
 /*
  * Do we need these probe functions on the m68k?
  *
@@ -219,58 +369,50 @@
 
 EXPORT_SYMBOL(probe_irq_off);
 
-static void dummy_enable_irq(unsigned int irq)
+unsigned int irq_canonicalize(unsigned int irq)
 {
-	printk("calling uninitialized enable_irq()\n");
+#ifdef CONFIG_Q40
+	if (MACH_IS_Q40 && irq == 11)
+		irq = 10;
+#endif
+	return irq;
 }
 
-static void dummy_disable_irq(unsigned int irq)
+EXPORT_SYMBOL(irq_canonicalize);
+
+asmlinkage void m68k_handle_int(unsigned int irq, struct pt_regs *regs)
 {
-	printk("calling uninitialized disable_irq()\n");
+	struct irq_node *node;
+
+	kstat_cpu(0).irqs[irq]++;
+	node = irq_list[irq];
+	do {
+		node->handler(irq, node->dev_id, regs);
+		node = node->next;
+	} while (node);
 }
 
-static int dummy_request_irq(unsigned int irq,
-		irqreturn_t (*handler) (int, void *, struct pt_regs *),
-		unsigned long flags, const char *devname, void *dev_id)
+asmlinkage void handle_badint(struct pt_regs *regs)
 {
-	printk("calling uninitialized request_irq()\n");
-	return 0;
-}
-
-static void dummy_free_irq(unsigned int irq, void *dev_id)
-{
-	printk("calling uninitialized disable_irq()\n");
-}
-
-asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
-{
-	if (vec >= VEC_INT1 && vec <= VEC_INT7 && !MACH_IS_BVME6000) {
-		vec -= VEC_SPUR;
-		kstat_cpu(0).irqs[vec]++;
-		irq_list[vec].handler(vec, irq_list[vec].dev_id, fp);
-	} else {
-		if (mach_process_int)
-			mach_process_int(vec, fp);
-		else
-			panic("Can't process interrupt vector %ld\n", vec);
-		return;
-	}
+	kstat_cpu(0).irqs[0]++;
+	printk("unexpected interrupt from %u\n", regs->vector);
 }
 
 int show_interrupts(struct seq_file *p, void *v)
 {
+	struct irq_controller *contr;
+	struct irq_node *node;
 	int i = *(loff_t *) v;
 
 	/* autovector interrupts */
-	if (i < SYS_IRQS) {
-		if (mach_default_handler) {
-			seq_printf(p, "auto %2d: %10u ", i,
-			               i ? kstat_cpu(0).irqs[i] : num_spurious);
-			seq_puts(p, "  ");
-			seq_printf(p, "%s\n", irq_list[i].devname);
-		}
-	} else if (i == SYS_IRQS)
-		mach_get_irq_list(p, v);
+	if (irq_list[i]) {
+		contr = irq_controller[i];
+		node = irq_list[i];
+		seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
+		while ((node = node->next))
+			seq_printf(p, ", %s", node->devname);
+		seq_puts(p, "\n");
+	}
 	return 0;
 }
 
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 5b7952e..1f5e1b5 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -57,8 +57,6 @@
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_thread);
 #ifdef CONFIG_VME
 EXPORT_SYMBOL(vme_brdtype);
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index 750d5b3..214a95f 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -68,11 +68,8 @@
 void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
 /* machine dependent irq functions */
 void (*mach_init_IRQ) (void) __initdata = NULL;
-irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
 void (*mach_get_model) (char *model);
 int (*mach_get_hardware_list) (char *buffer);
-int (*mach_get_irq_list) (struct seq_file *, void *);
-irqreturn_t (*mach_process_int) (int, struct pt_regs *);
 /* machine dependent timer functions */
 unsigned long (*mach_gettimeoffset) (void);
 int (*mach_hwclk) (int, struct rtc_time*);
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 866917b..f9af893 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -763,7 +763,7 @@
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(usp))
+		if (!sas_ss_flags(usp))
 			usp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	return (void __user *)((usp - frame_size) & -8UL);
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index cdf58fb..e86de7b 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -45,7 +45,6 @@
 asmlinkage void system_call(void);
 asmlinkage void buserr(void);
 asmlinkage void trap(void);
-asmlinkage void inthandler(void);
 asmlinkage void nmihandler(void);
 #ifdef CONFIG_M68KFPU_EMU
 asmlinkage void fpu_emu(void);
@@ -53,51 +52,7 @@
 
 e_vector vectors[256] = {
 	[VEC_BUSERR]	= buserr,
-	[VEC_ADDRERR]	= trap,
-	[VEC_ILLEGAL]	= trap,
-	[VEC_ZERODIV]	= trap,
-	[VEC_CHK]	= trap,
-	[VEC_TRAP]	= trap,
-	[VEC_PRIV]	= trap,
-	[VEC_TRACE]	= trap,
-	[VEC_LINE10]	= trap,
-	[VEC_LINE11]	= trap,
-	[VEC_RESV12]	= trap,
-	[VEC_COPROC]	= trap,
-	[VEC_FORMAT]	= trap,
-	[VEC_UNINT]	= trap,
-	[VEC_RESV16]	= trap,
-	[VEC_RESV17]	= trap,
-	[VEC_RESV18]	= trap,
-	[VEC_RESV19]	= trap,
-	[VEC_RESV20]	= trap,
-	[VEC_RESV21]	= trap,
-	[VEC_RESV22]	= trap,
-	[VEC_RESV23]	= trap,
-	[VEC_SPUR]	= inthandler,
-	[VEC_INT1]	= inthandler,
-	[VEC_INT2]	= inthandler,
-	[VEC_INT3]	= inthandler,
-	[VEC_INT4]	= inthandler,
-	[VEC_INT5]	= inthandler,
-	[VEC_INT6]	= inthandler,
-	[VEC_INT7]	= inthandler,
 	[VEC_SYS]	= system_call,
-	[VEC_TRAP1]	= trap,
-	[VEC_TRAP2]	= trap,
-	[VEC_TRAP3]	= trap,
-	[VEC_TRAP4]	= trap,
-	[VEC_TRAP5]	= trap,
-	[VEC_TRAP6]	= trap,
-	[VEC_TRAP7]	= trap,
-	[VEC_TRAP8]	= trap,
-	[VEC_TRAP9]	= trap,
-	[VEC_TRAP10]	= trap,
-	[VEC_TRAP11]	= trap,
-	[VEC_TRAP12]	= trap,
-	[VEC_TRAP13]	= trap,
-	[VEC_TRAP14]	= trap,
-	[VEC_TRAP15]	= trap,
 };
 
 /* nmi handler for the Amiga */
@@ -114,7 +69,7 @@
 	if(MACH_IS_SUN3X) {
 		extern e_vector *sun3x_prom_vbr;
 
-		__asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr));
+		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
 	}
 
 	/* setup the exception vector table */
@@ -132,12 +87,15 @@
 {
 	int i;
 
-	for (i = 48; i < 64; i++)
+	for (i = VEC_SPUR; i <= VEC_INT7; i++)
+		vectors[i] = bad_inthandler;
+
+	for (i = 0; i < VEC_USER; i++)
 		if (!vectors[i])
 			vectors[i] = trap;
 
-	for (i = 64; i < 256; i++)
-		vectors[i] = inthandler;
+	for (i = VEC_USER; i < 256; i++)
+		vectors[i] = bad_inthandler;
 
 #ifdef CONFIG_M68KFPU_EMU
 	if (FPU_IS_EMU)
@@ -927,71 +885,94 @@
 void show_registers(struct pt_regs *regs)
 {
 	struct frame *fp = (struct frame *)regs;
+	mm_segment_t old_fs = get_fs();
+	u16 c, *cp;
 	unsigned long addr;
 	int i;
 
+	print_modules();
+	printk("PC: [<%08lx>]",regs->pc);
+	print_symbol(" %s", regs->pc);
+	printk("\nSR: %04x  SP: %p  a2: %08lx\n",
+	       regs->sr, regs, regs->a2);
+	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
+	       regs->d0, regs->d1, regs->d2, regs->d3);
+	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
+	       regs->d4, regs->d5, regs->a0, regs->a1);
+
+	printk("Process %s (pid: %d, task=%p)\n",
+		current->comm, current->pid, current);
 	addr = (unsigned long)&fp->un;
-	printk("Frame format=%X ", fp->ptregs.format);
-	switch (fp->ptregs.format) {
+	printk("Frame format=%X ", regs->format);
+	switch (regs->format) {
 	case 0x2:
-	    printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
-	    addr += sizeof(fp->un.fmt2);
-	    break;
+		printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
+		addr += sizeof(fp->un.fmt2);
+		break;
 	case 0x3:
-	    printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
-	    addr += sizeof(fp->un.fmt3);
-	    break;
+		printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
+		addr += sizeof(fp->un.fmt3);
+		break;
 	case 0x4:
-	    printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
-		    : "eff addr=%08lx pc=%08lx\n"),
-		   fp->un.fmt4.effaddr, fp->un.fmt4.pc);
-	    addr += sizeof(fp->un.fmt4);
-	    break;
+		printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
+			: "eff addr=%08lx pc=%08lx\n"),
+			fp->un.fmt4.effaddr, fp->un.fmt4.pc);
+		addr += sizeof(fp->un.fmt4);
+		break;
 	case 0x7:
-	    printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
-		   fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
-	    printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
-		   fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
-	    printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
-		   fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
-	    printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
-		   fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
-	    printk("push data: %08lx %08lx %08lx %08lx\n",
-		   fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
-		   fp->un.fmt7.pd3);
-	    addr += sizeof(fp->un.fmt7);
-	    break;
+		printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
+			fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
+		printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
+		printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
+		printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
+		printk("push data: %08lx %08lx %08lx %08lx\n",
+			fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
+			fp->un.fmt7.pd3);
+		addr += sizeof(fp->un.fmt7);
+		break;
 	case 0x9:
-	    printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
-	    addr += sizeof(fp->un.fmt9);
-	    break;
+		printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
+		addr += sizeof(fp->un.fmt9);
+		break;
 	case 0xa:
-	    printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
-		   fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
-		   fp->un.fmta.daddr, fp->un.fmta.dobuf);
-	    addr += sizeof(fp->un.fmta);
-	    break;
+		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+			fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
+			fp->un.fmta.daddr, fp->un.fmta.dobuf);
+		addr += sizeof(fp->un.fmta);
+		break;
 	case 0xb:
-	    printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
-		   fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
-		   fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
-	    printk("baddr=%08lx dibuf=%08lx ver=%x\n",
-		   fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
-	    addr += sizeof(fp->un.fmtb);
-	    break;
+		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+			fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
+			fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
+		printk("baddr=%08lx dibuf=%08lx ver=%x\n",
+			fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
+		addr += sizeof(fp->un.fmtb);
+		break;
 	default:
-	    printk("\n");
+		printk("\n");
 	}
 	show_stack(NULL, (unsigned long *)addr);
 
-	printk("Code: ");
-	for (i = 0; i < 10; i++)
-		printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
+	printk("Code:");
+	set_fs(KERNEL_DS);
+	cp = (u16 *)regs->pc;
+	for (i = -8; i < 16; i++) {
+		if (get_user(c, cp + i) && i >= 0) {
+			printk(" Bad PC value.");
+			break;
+		}
+		printk(i ? " %04x" : " <%04x>", c);
+	}
+	set_fs(old_fs);
 	printk ("\n");
 }
 
 void show_stack(struct task_struct *task, unsigned long *stack)
 {
+	unsigned long *p;
 	unsigned long *endstack;
 	int i;
 
@@ -1004,12 +985,13 @@
 	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
 
 	printk("Stack from %08lx:", (unsigned long)stack);
+	p = stack;
 	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (stack + 1 > endstack)
+		if (p + 1 > endstack)
 			break;
 		if (i % 8 == 0)
 			printk("\n       ");
-		printk(" %08lx", *stack++);
+		printk(" %08lx", *p++);
 	}
 	printk("\n");
 	show_trace(stack);
@@ -1188,19 +1170,7 @@
 
 	console_verbose();
 	printk("%s: %08x\n",str,nr);
-	print_modules();
-	printk("PC: [<%08lx>]",fp->pc);
-	print_symbol(" %s\n", fp->pc);
-	printk("\nSR: %04x  SP: %p  a2: %08lx\n",
-	       fp->sr, fp, fp->a2);
-	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
-	       fp->d0, fp->d1, fp->d2, fp->d3);
-	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
-	       fp->d4, fp->d5, fp->a0, fp->a1);
-
-	printk("Process %s (pid: %d, stackpage=%08lx)\n",
-		current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
-	show_stack(NULL, (unsigned long *)fp);
+	show_registers(fp);
 	do_exit(SIGSEGV);
 }
 
diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile
index ebe51a5..6bbf19f 100644
--- a/arch/m68k/lib/Makefile
+++ b/arch/m68k/lib/Makefile
@@ -4,5 +4,5 @@
 
 EXTRA_AFLAGS := -traditional
 
-lib-y		:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
-			checksum.o string.o semaphore.o
+lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+	   checksum.o string.o semaphore.o uaccess.o
diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c
new file mode 100644
index 0000000..1bc188c
--- /dev/null
+++ b/arch/m68k/lib/uaccess.c
@@ -0,0 +1,222 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+unsigned long __generic_copy_from_user(void *to, const void __user *from,
+				       unsigned long n)
+{
+	unsigned long tmp, res;
+
+	asm volatile ("\n"
+		"	tst.l	%0\n"
+		"	jeq	2f\n"
+		"1:	moves.l	(%1)+,%3\n"
+		"	move.l	%3,(%2)+\n"
+		"	subq.l	#1,%0\n"
+		"	jne	1b\n"
+		"2:	btst	#1,%5\n"
+		"	jeq	4f\n"
+		"3:	moves.w	(%1)+,%3\n"
+		"	move.w	%3,(%2)+\n"
+		"4:	btst	#0,%5\n"
+		"	jeq	6f\n"
+		"5:	moves.b	(%1)+,%3\n"
+		"	move.b  %3,(%2)+\n"
+		"6:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"10:	move.l	%0,%3\n"
+		"7:	clr.l	(%2)+\n"
+		"	subq.l	#1,%3\n"
+		"	jne	7b\n"
+		"	lsl.l	#2,%0\n"
+		"	btst	#1,%5\n"
+		"	jeq	8f\n"
+		"30:	clr.w	(%2)+\n"
+		"	addq.l	#2,%0\n"
+		"8:	btst	#0,%5\n"
+		"	jeq	6b\n"
+		"50:	clr.b	(%2)+\n"
+		"	addq.l	#1,%0\n"
+		"	jra	6b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	1b,10b\n"
+		"	.long	3b,30b\n"
+		"	.long	5b,50b\n"
+		"	.previous"
+		: "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
+		: "0" (n / 4), "d" (n & 3));
+
+	return res;
+}
+EXPORT_SYMBOL(__generic_copy_from_user);
+
+unsigned long __generic_copy_to_user(void __user *to, const void *from,
+				     unsigned long n)
+{
+	unsigned long tmp, res;
+
+	asm volatile ("\n"
+		"	tst.l	%0\n"
+		"	jeq	4f\n"
+		"1:	move.l	(%1)+,%3\n"
+		"2:	moves.l	%3,(%2)+\n"
+		"3:	subq.l	#1,%0\n"
+		"	jne	1b\n"
+		"4:	btst	#1,%5\n"
+		"	jeq	6f\n"
+		"	move.w	(%1)+,%3\n"
+		"5:	moves.w	%3,(%2)+\n"
+		"6:	btst	#0,%5\n"
+		"	jeq	8f\n"
+		"	move.b	(%1)+,%3\n"
+		"7:	moves.b  %3,(%2)+\n"
+		"8:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"20:	lsl.l	#2,%0\n"
+		"50:	add.l	%5,%0\n"
+		"	jra	7b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	2b,20b\n"
+		"	.long	3b,20b\n"
+		"	.long	5b,50b\n"
+		"	.long	6b,50b\n"
+		"	.long	7b,50b\n"
+		"	.long	8b,50b\n"
+		"	.previous"
+		: "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp)
+		: "0" (n / 4), "d" (n & 3));
+
+	return res;
+}
+EXPORT_SYMBOL(__generic_copy_to_user);
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+long strncpy_from_user(char *dst, const char __user *src, long count)
+{
+	long res;
+	char c;
+
+	if (count <= 0)
+		return count;
+
+	asm volatile ("\n"
+		"1:	moves.b	(%2)+,%4\n"
+		"	move.b	%4,(%1)+\n"
+		"	jeq	2f\n"
+		"	subq.l	#1,%3\n"
+		"	jne	1b\n"
+		"2:	sub.l	%3,%0\n"
+		"3:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"10:	move.l	%5,%0\n"
+		"	jra	3b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	1b,10b\n"
+		"	.previous"
+		: "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c)
+		: "i" (-EFAULT), "0" (count));
+
+	return res;
+}
+EXPORT_SYMBOL(strncpy_from_user);
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 on exception, a value greater than N if too long
+ */
+long strnlen_user(const char __user *src, long n)
+{
+	char c;
+	long res;
+
+	asm volatile ("\n"
+		"1:	subq.l	#1,%1\n"
+		"	jmi	3f\n"
+		"2:	moves.b	(%0)+,%2\n"
+		"	tst.b	%2\n"
+		"	jne	1b\n"
+		"	jra	4f\n"
+		"\n"
+		"3:	addq.l	#1,%0\n"
+		"4:	sub.l	%4,%0\n"
+		"5:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"20:	sub.l	%0,%0\n"
+		"	jra	5b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	2b,20b\n"
+		"	.previous\n"
+		: "=&a" (res), "+d" (n), "=&d" (c)
+		: "0" (src), "r" (src));
+
+	return res;
+}
+EXPORT_SYMBOL(strnlen_user);
+
+/*
+ * Zero Userspace
+ */
+
+unsigned long clear_user(void __user *to, unsigned long n)
+{
+	unsigned long res;
+
+	asm volatile ("\n"
+		"	tst.l	%0\n"
+		"	jeq	3f\n"
+		"1:	moves.l	%2,(%1)+\n"
+		"2:	subq.l	#1,%0\n"
+		"	jne	1b\n"
+		"3:	btst	#1,%4\n"
+		"	jeq	5f\n"
+		"4:	moves.w	%2,(%1)+\n"
+		"5:	btst	#0,%4\n"
+		"	jeq	7f\n"
+		"6:	moves.b	%2,(%1)\n"
+		"7:\n"
+		"	.section .fixup,\"ax\"\n"
+		"	.even\n"
+		"10:	lsl.l	#2,%0\n"
+		"40:	add.l	%4,%0\n"
+		"	jra	7b\n"
+		"	.previous\n"
+		"\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.align	4\n"
+		"	.long	1b,10b\n"
+		"	.long	2b,10b\n"
+		"	.long	4b,40b\n"
+		"	.long	5b,40b\n"
+		"	.long	6b,40b\n"
+		"	.long	7b,40b\n"
+		"	.previous"
+		: "=d" (res), "+a" (to)
+		: "r" (0), "0" (n / 4), "d" (n & 3));
+
+    return res;
+}
+EXPORT_SYMBOL(clear_user);
diff --git a/arch/m68k/mac/baboon.c b/arch/m68k/mac/baboon.c
index b19b7dd..6eaa881 100644
--- a/arch/m68k/mac/baboon.c
+++ b/arch/m68k/mac/baboon.c
@@ -81,7 +81,7 @@
 	for (i = 0, irq_bit = 1 ; i < 3 ; i++, irq_bit <<= 1) {
 	        if (events & irq_bit/* & baboon_active*/) {
 			baboon_active &= ~irq_bit;
-			mac_do_irq_list(IRQ_BABOON_0 + i, regs);
+			m68k_handle_int(IRQ_BABOON_0 + i, regs);
 			baboon_active |= irq_bit;
 			baboon->mb_ifr &= ~irq_bit;
 		}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 14f8d3f4..5a9990e 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -89,38 +89,11 @@
 
 static void mac_get_model(char *str);
 
-void mac_bang(int irq, void *vector, struct pt_regs *p)
-{
-	printk(KERN_INFO "Resetting ...\n");
-	mac_reset();
-}
-
 static void mac_sched_init(irqreturn_t (*vector)(int, void *, struct pt_regs *))
 {
 	via_init_clock(vector);
 }
 
-#if 0
-void mac_waitbut (void)
-{
-	;
-}
-#endif
-
-extern irqreturn_t mac_default_handler(int, void *, struct pt_regs *);
-
-irqreturn_t (*mac_handlers[8])(int, void *, struct pt_regs *)=
-{
-	mac_default_handler,
-	mac_default_handler,
-	mac_default_handler,
-	mac_default_handler,
-	mac_default_handler,
-	mac_default_handler,
-	mac_default_handler,
-	mac_default_handler
-};
-
 /*
  * Parse a Macintosh-specific record in the bootinfo
  */
@@ -196,13 +169,7 @@
 
 	mach_sched_init      = mac_sched_init;
 	mach_init_IRQ        = mac_init_IRQ;
-	mach_request_irq     = mac_request_irq;
-	mach_free_irq        = mac_free_irq;
-	enable_irq           = mac_enable_irq;
-	disable_irq          = mac_disable_irq;
 	mach_get_model	 = mac_get_model;
-	mach_default_handler = &mac_handlers;
-	mach_get_irq_list    = show_mac_interrupts;
 	mach_gettimeoffset   = mac_gettimeoffset;
 #warning move to adb/via init
 #if 0
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 9179a37..4c8ece7 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -317,7 +317,7 @@
 {
 	if (iop_ism_present) {
 		if (oss_present) {
-			cpu_request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
+			request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
 					IRQ_FLG_LOCK, "ISM IOP",
 					(void *) IOP_NUM_ISM);
 			oss_irq_enable(IRQ_MAC_ADB);
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 1809601..694b14b 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -137,14 +137,6 @@
 #define DEBUG_SPURIOUS
 #define SHUTUP_SONIC
 
-/*
- * The mac_irq_list array is an array of linked lists of irq_node_t nodes.
- * Each node contains one handler to be called whenever the interrupt
- * occurs, with fast handlers listed before slow handlers.
- */
-
-irq_node_t *mac_irq_list[NUM_MAC_SOURCES];
-
 /* SCC interrupt mask */
 
 static int scc_mask;
@@ -209,34 +201,37 @@
  * SCC interrupt routines
  */
 
-static void scc_irq_enable(int);
-static void scc_irq_disable(int);
+static void scc_irq_enable(unsigned int);
+static void scc_irq_disable(unsigned int);
 
 /*
  * console_loglevel determines NMI handler function
  */
 
-extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
 irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *);
 irqreturn_t mac_debug_handler(int, void *, struct pt_regs *);
 
 /* #define DEBUG_MACINTS */
 
+static void mac_enable_irq(unsigned int irq);
+static void mac_disable_irq(unsigned int irq);
+
+static struct irq_controller mac_irq_controller = {
+	.name		= "mac",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.enable		= mac_enable_irq,
+	.disable	= mac_disable_irq,
+};
+
 void mac_init_IRQ(void)
 {
-        int i;
-
 #ifdef DEBUG_MACINTS
 	printk("mac_init_IRQ(): Setting things up...\n");
 #endif
-	/* Initialize the IRQ handler lists. Initially each list is empty, */
-
-	for (i = 0; i < NUM_MAC_SOURCES; i++) {
-		mac_irq_list[i] = NULL;
-	}
-
 	scc_mask = 0;
 
+	m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
+				  NUM_MAC_SOURCES - IRQ_USER);
 	/* Make sure the SONIC interrupt is cleared or things get ugly */
 #ifdef SHUTUP_SONIC
 	printk("Killing onboard sonic... ");
@@ -253,15 +248,16 @@
 	 * at levels 1-7. Most of the work is done elsewhere.
 	 */
 
-	if (oss_present) {
+	if (oss_present)
 		oss_register_interrupts();
-	} else {
+	else
 		via_register_interrupts();
-	}
-	if (psc_present) psc_register_interrupts();
-	if (baboon_present) baboon_register_interrupts();
+	if (psc_present)
+		psc_register_interrupts();
+	if (baboon_present)
+		baboon_register_interrupts();
 	iop_register_interrupts();
-	cpu_request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI",
+	request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
 			mac_nmi_handler);
 #ifdef DEBUG_MACINTS
 	printk("mac_init_IRQ(): Done!\n");
@@ -269,104 +265,6 @@
 }
 
 /*
- * Routines to work with irq_node_t's on linked lists lifted from
- * the Amiga code written by Roman Zippel.
- */
-
-static inline void mac_insert_irq(irq_node_t **list, irq_node_t *node)
-{
-	unsigned long flags;
-	irq_node_t *cur;
-
-	if (!node->dev_id)
-		printk("%s: Warning: dev_id of %s is zero\n",
-		       __FUNCTION__, node->devname);
-
-	local_irq_save(flags);
-
-	cur = *list;
-
-	if (node->flags & IRQ_FLG_FAST) {
-		node->flags &= ~IRQ_FLG_SLOW;
-		while (cur && cur->flags & IRQ_FLG_FAST) {
-			list = &cur->next;
-			cur = cur->next;
-		}
-	} else if (node->flags & IRQ_FLG_SLOW) {
-		while (cur) {
-			list = &cur->next;
-			cur = cur->next;
-		}
-	} else {
-		while (cur && !(cur->flags & IRQ_FLG_SLOW)) {
-			list = &cur->next;
-			cur = cur->next;
-		}
-	}
-
-	node->next = cur;
-	*list = node;
-
-	local_irq_restore(flags);
-}
-
-static inline void mac_delete_irq(irq_node_t **list, void *dev_id)
-{
-	unsigned long flags;
-	irq_node_t *node;
-
-	local_irq_save(flags);
-
-	for (node = *list; node; list = &node->next, node = *list) {
-		if (node->dev_id == dev_id) {
-			*list = node->next;
-			/* Mark it as free. */
-			node->handler = NULL;
-			local_irq_restore(flags);
-			return;
-		}
-	}
-	local_irq_restore(flags);
-	printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
-}
-
-/*
- * Call all the handlers for a given interrupt. Fast handlers are called
- * first followed by slow handlers.
- *
- * This code taken from the original Amiga code written by Roman Zippel.
- */
-
-void mac_do_irq_list(int irq, struct pt_regs *fp)
-{
-	irq_node_t *node, *slow_nodes;
-	unsigned long flags;
-
-	kstat_cpu(0).irqs[irq]++;
-
-#ifdef DEBUG_SPURIOUS
-	if (!mac_irq_list[irq] && (console_loglevel > 7)) {
-		printk("mac_do_irq_list: spurious interrupt %d!\n", irq);
-		return;
-	}
-#endif
-
-	/* serve first fast and normal handlers */
-	for (node = mac_irq_list[irq];
-	     node && (!(node->flags & IRQ_FLG_SLOW));
-	     node = node->next)
-		node->handler(irq, node->dev_id, fp);
-	if (!node) return;
-	local_save_flags(flags);
-	local_irq_restore((flags & ~0x0700) | (fp->sr & 0x0700));
-	/* if slow handlers exists, serve them now */
-	slow_nodes = node;
-	for (; node; node = node->next) {
-		node->handler(irq, node->dev_id, fp);
-	}
-}
-
-/*
  *  mac_enable_irq - enable an interrupt source
  * mac_disable_irq - disable an interrupt source
  *   mac_clear_irq - clears a pending interrupt
@@ -375,276 +273,124 @@
  * These routines are just dispatchers to the VIA/OSS/PSC routines.
  */
 
-void mac_enable_irq (unsigned int irq)
+static void mac_enable_irq(unsigned int irq)
 {
-	int irq_src	= IRQ_SRC(irq);
+	int irq_src = IRQ_SRC(irq);
 
 	switch(irq_src) {
-		case 1: via_irq_enable(irq);
-			break;
-		case 2:
-		case 7: if (oss_present) {
-				oss_irq_enable(irq);
-			} else {
-				via_irq_enable(irq);
-			}
-			break;
-		case 3:
-		case 4:
-		case 5:
-		case 6: if (psc_present) {
-				psc_irq_enable(irq);
-			} else if (oss_present) {
-				oss_irq_enable(irq);
-			} else if (irq_src == 4) {
-				scc_irq_enable(irq);
-			}
-			break;
-		case 8: if (baboon_present) {
-				baboon_irq_enable(irq);
-			}
-			break;
+	case 1:
+		via_irq_enable(irq);
+		break;
+	case 2:
+	case 7:
+		if (oss_present)
+			oss_irq_enable(irq);
+		else
+			via_irq_enable(irq);
+		break;
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		if (psc_present)
+			psc_irq_enable(irq);
+		else if (oss_present)
+			oss_irq_enable(irq);
+		else if (irq_src == 4)
+			scc_irq_enable(irq);
+		break;
+	case 8:
+		if (baboon_present)
+			baboon_irq_enable(irq);
+		break;
 	}
 }
 
-void mac_disable_irq (unsigned int irq)
+static void mac_disable_irq(unsigned int irq)
 {
-	int irq_src	= IRQ_SRC(irq);
+	int irq_src = IRQ_SRC(irq);
 
 	switch(irq_src) {
-		case 1: via_irq_disable(irq);
-			break;
-		case 2:
-		case 7: if (oss_present) {
-				oss_irq_disable(irq);
-			} else {
-				via_irq_disable(irq);
-			}
-			break;
-		case 3:
-		case 4:
-		case 5:
-		case 6: if (psc_present) {
-				psc_irq_disable(irq);
-			} else if (oss_present) {
-				oss_irq_disable(irq);
-			} else if (irq_src == 4) {
-				scc_irq_disable(irq);
-			}
-			break;
-		case 8: if (baboon_present) {
-				baboon_irq_disable(irq);
-			}
-			break;
+	case 1:
+		via_irq_disable(irq);
+		break;
+	case 2:
+	case 7:
+		if (oss_present)
+			oss_irq_disable(irq);
+		else
+			via_irq_disable(irq);
+		break;
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		if (psc_present)
+			psc_irq_disable(irq);
+		else if (oss_present)
+			oss_irq_disable(irq);
+		else if (irq_src == 4)
+			scc_irq_disable(irq);
+		break;
+	case 8:
+		if (baboon_present)
+			baboon_irq_disable(irq);
+		break;
 	}
 }
 
-void mac_clear_irq( unsigned int irq )
+void mac_clear_irq(unsigned int irq)
 {
 	switch(IRQ_SRC(irq)) {
-		case 1: via_irq_clear(irq);
-			break;
-		case 2:
-		case 7: if (oss_present) {
-				oss_irq_clear(irq);
-			} else {
-				via_irq_clear(irq);
-			}
-			break;
-		case 3:
-		case 4:
-		case 5:
-		case 6: if (psc_present) {
-				psc_irq_clear(irq);
-			} else if (oss_present) {
-				oss_irq_clear(irq);
-			}
-			break;
-		case 8: if (baboon_present) {
-				baboon_irq_clear(irq);
-			}
-			break;
+	case 1:
+		via_irq_clear(irq);
+		break;
+	case 2:
+	case 7:
+		if (oss_present)
+			oss_irq_clear(irq);
+		else
+			via_irq_clear(irq);
+		break;
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		if (psc_present)
+			psc_irq_clear(irq);
+		else if (oss_present)
+			oss_irq_clear(irq);
+		break;
+	case 8:
+		if (baboon_present)
+			baboon_irq_clear(irq);
+		break;
 	}
 }
 
-int mac_irq_pending( unsigned int irq )
+int mac_irq_pending(unsigned int irq)
 {
 	switch(IRQ_SRC(irq)) {
-		case 1: return via_irq_pending(irq);
-		case 2:
-		case 7: if (oss_present) {
-				return oss_irq_pending(irq);
-			} else {
-				return via_irq_pending(irq);
-			}
-		case 3:
-		case 4:
-		case 5:
-		case 6: if (psc_present) {
-				return psc_irq_pending(irq);
-			} else if (oss_present) {
-				return oss_irq_pending(irq);
-			}
+	case 1:
+		return via_irq_pending(irq);
+	case 2:
+	case 7:
+		if (oss_present)
+			return oss_irq_pending(irq);
+		else
+			return via_irq_pending(irq);
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		if (psc_present)
+			return psc_irq_pending(irq);
+		else if (oss_present)
+			return oss_irq_pending(irq);
 	}
 	return 0;
 }
 
-/*
- * Add an interrupt service routine to an interrupt source.
- * Returns 0 on success.
- *
- * FIXME: You can register interrupts on nonexistent source (ie PSC4 on a
- *        non-PSC machine). We should return -EINVAL in those cases.
- */
-
-int mac_request_irq(unsigned int irq,
-		    irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		    unsigned long flags, const char *devname, void *dev_id)
-{
-	irq_node_t *node;
-
-#ifdef DEBUG_MACINTS
-	printk ("%s: irq %d requested for %s\n", __FUNCTION__, irq, devname);
-#endif
-
-	if (irq < VIA1_SOURCE_BASE) {
-		return cpu_request_irq(irq, handler, flags, devname, dev_id);
-	}
-
-	if (irq >= NUM_MAC_SOURCES) {
-		printk ("%s: unknown irq %d requested by %s\n",
-		        __FUNCTION__, irq, devname);
-	}
-
-	/* Get a node and stick it onto the right list */
-
-	if (!(node = new_irq_node())) return -ENOMEM;
-
-	node->handler	= handler;
-	node->flags	= flags;
-	node->dev_id	= dev_id;
-	node->devname	= devname;
-	node->next	= NULL;
-	mac_insert_irq(&mac_irq_list[irq], node);
-
-	/* Now enable the IRQ source */
-
-	mac_enable_irq(irq);
-
-	return 0;
-}
-
-/*
- * Removes an interrupt service routine from an interrupt source.
- */
-
-void mac_free_irq(unsigned int irq, void *dev_id)
-{
-#ifdef DEBUG_MACINTS
-	printk ("%s: irq %d freed by %p\n", __FUNCTION__, irq, dev_id);
-#endif
-
-	if (irq < VIA1_SOURCE_BASE) {
-		cpu_free_irq(irq, dev_id);
-		return;
-	}
-
-	if (irq >= NUM_MAC_SOURCES) {
-		printk ("%s: unknown irq %d freed\n",
-		        __FUNCTION__, irq);
-		return;
-	}
-
-	mac_delete_irq(&mac_irq_list[irq], dev_id);
-
-	/* If the list for this interrupt is */
-	/* empty then disable the source.    */
-
-	if (!mac_irq_list[irq]) {
-		mac_disable_irq(irq);
-	}
-}
-
-/*
- * Generate a pretty listing for /proc/interrupts
- *
- * By the time we're called the autovector interrupt list has already been
- * generated, so we just need to do the machspec interrupts.
- *
- * 990506 (jmt) - rewritten to handle chained machspec interrupt handlers.
- *                Also removed display of num_spurious it is already
- *		  displayed for us as autovector irq 0.
- */
-
-int show_mac_interrupts(struct seq_file *p, void *v)
-{
-	int i;
-	irq_node_t *node;
-	char *base;
-
-	/* Don't do Nubus interrupts in this loop; we do them separately  */
-	/* below so that we can print slot numbers instead of IRQ numbers */
-
-	for (i = VIA1_SOURCE_BASE ; i < NUM_MAC_SOURCES ; ++i) {
-
-		/* Nonexistant interrupt or nothing registered; skip it. */
-
-		if ((node = mac_irq_list[i]) == NULL) continue;
-		if (node->flags & IRQ_FLG_STD) continue;
-
-		base = "";
-		switch(IRQ_SRC(i)) {
-			case 1: base = "via1";
-				break;
-			case 2: if (oss_present) {
-					base = "oss";
-				} else {
-					base = "via2";
-				}
-				break;
-			case 3:
-			case 4:
-			case 5:
-			case 6: if (psc_present) {
-					base = "psc";
-				} else if (oss_present) {
-					base = "oss";
-				} else {
-					if (IRQ_SRC(i) == 4) base = "scc";
-				}
-				break;
-			case 7: base = "nbus";
-				break;
-			case 8: base = "bbn";
-				break;
-		}
-		seq_printf(p, "%4s %2d: %10u ", base, i, kstat_cpu(0).irqs[i]);
-
-		do {
-			if (node->flags & IRQ_FLG_FAST) {
-				seq_puts(p, "F ");
-			} else if (node->flags & IRQ_FLG_SLOW) {
-				seq_puts(p, "S ");
-			} else {
-				seq_puts(p, "  ");
-			}
-			seq_printf(p, "%s\n", node->devname);
-			if ((node = node->next)) {
-				seq_puts(p, "                    ");
-			}
-		} while(node);
-
-	}
-	return 0;
-}
-
-void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
-{
-#ifdef DEBUG_SPURIOUS
-	printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
-#endif
-}
-
 static int num_debug[8];
 
 irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs)
@@ -684,7 +430,7 @@
 	while (nmi_hold == 1)
 		udelay(1000);
 
-	if ( console_loglevel >= 8 ) {
+	if (console_loglevel >= 8) {
 #if 0
 		show_state();
 		printk("PC: %08lx\nSR: %04x  SP: %p\n", fp->pc, fp->sr, fp);
@@ -713,14 +459,16 @@
  * done in hardware (only the PSC can do that.)
  */
 
-static void scc_irq_enable(int irq) {
-	int irq_idx     = IRQ_IDX(irq);
+static void scc_irq_enable(unsigned int irq)
+{
+	int irq_idx = IRQ_IDX(irq);
 
 	scc_mask |= (1 << irq_idx);
 }
 
-static void scc_irq_disable(int irq) {
-	int irq_idx     = IRQ_IDX(irq);
+static void scc_irq_disable(unsigned int irq)
+{
+	int irq_idx = IRQ_IDX(irq);
 
 	scc_mask &= ~(1 << irq_idx);
 }
@@ -755,6 +503,8 @@
 	/* and since they're autovector interrupts they */
 	/* pretty much kill the system.                 */
 
-	if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs);
-	if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs);
+	if (reg & 0x38)
+		m68k_handle_int(IRQ_SCCA, regs);
+	if (reg & 0x07)
+		m68k_handle_int(IRQ_SCCB, regs);
 }
diff --git a/arch/m68k/mac/oss.c b/arch/m68k/mac/oss.c
index 3335476..63e0436 100644
--- a/arch/m68k/mac/oss.c
+++ b/arch/m68k/mac/oss.c
@@ -67,15 +67,15 @@
 
 void __init oss_register_interrupts(void)
 {
-	cpu_request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
+	request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
 			"scsi", (void *) oss);
-	cpu_request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
+	request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
 			"scc", mac_scc_dispatch);
-	cpu_request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
+	request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
 			"nubus", (void *) oss);
-	cpu_request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
+	request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
 			"sound", (void *) oss);
-	cpu_request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
+	request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
 			"via1", (void *) via1);
 }
 
@@ -113,7 +113,7 @@
 		oss->irq_pending &= ~OSS_IP_SOUND;
 	} else if (events & OSS_IP_SCSI) {
 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_DISABLED;
-		mac_do_irq_list(IRQ_MAC_SCSI, regs);
+		m68k_handle_int(IRQ_MAC_SCSI, regs);
 		oss->irq_pending &= ~OSS_IP_SCSI;
 		oss->irq_level[OSS_SCSI] = OSS_IRQLEV_SCSI;
 	} else {
@@ -146,7 +146,7 @@
 	for (i = 0, irq_bit = 1 ; i < 6 ; i++, irq_bit <<= 1) {
 		if (events & irq_bit) {
 			oss->irq_level[i] = OSS_IRQLEV_DISABLED;
-			mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
+			m68k_handle_int(NUBUS_SOURCE_BASE + i, regs);
 			oss->irq_pending &= ~irq_bit;
 			oss->irq_level[i] = OSS_IRQLEV_NUBUS;
 		}
diff --git a/arch/m68k/mac/psc.c b/arch/m68k/mac/psc.c
index e72384e..e262180 100644
--- a/arch/m68k/mac/psc.c
+++ b/arch/m68k/mac/psc.c
@@ -117,10 +117,10 @@
 
 void __init psc_register_interrupts(void)
 {
-	cpu_request_irq(3, psc_irq, IRQ_FLG_LOCK, "psc3", (void *) 0x30);
-	cpu_request_irq(4, psc_irq, IRQ_FLG_LOCK, "psc4", (void *) 0x40);
-	cpu_request_irq(5, psc_irq, IRQ_FLG_LOCK, "psc5", (void *) 0x50);
-	cpu_request_irq(6, psc_irq, IRQ_FLG_LOCK, "psc6", (void *) 0x60);
+	request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30);
+	request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40);
+	request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50);
+	request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60);
 }
 
 /*
@@ -149,7 +149,7 @@
 	for (i = 0, irq_bit = 1 ; i < 4 ; i++, irq_bit <<= 1) {
 	        if (events & irq_bit) {
 			psc_write_byte(pIER, irq_bit);
-			mac_do_irq_list(base_irq + i, regs);
+			m68k_handle_int(base_irq + i, regs);
 			psc_write_byte(pIFR, irq_bit);
 			psc_write_byte(pIER, irq_bit | 0x80);
 		}
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index cd528bf..c4aa345 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -25,7 +25,6 @@
 #include <linux/init.h>
 #include <linux/ide.h>
 
-#include <asm/traps.h>
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 #include <asm/macints.h>
@@ -71,7 +70,6 @@
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
 
-extern irqreturn_t mac_bang(int, void *, struct pt_regs *);
 extern irqreturn_t mac_scc_dispatch(int, void *, struct pt_regs *);
 extern int oss_present;
 
@@ -212,11 +210,6 @@
 			break;
 	}
 #else
-	/* The alernate IRQ mapping seems to just not work. Anyone with a   */
-	/* supported machine is welcome to take a stab at fixing it. It     */
-	/* _should_ work on the following Quadras: 610,650,700,800,900,950  */
-	/*                                               - 1999-06-12 (jmt) */
-
 	via_alt_mapping = 0;
 #endif
 
@@ -260,27 +253,21 @@
 void __init via_register_interrupts(void)
 {
 	if (via_alt_mapping) {
-		cpu_request_irq(IRQ_AUTO_1, via1_irq,
+		request_irq(IRQ_AUTO_1, via1_irq,
 				IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
 				(void *) via1);
-		cpu_request_irq(IRQ_AUTO_6, via1_irq,
+		request_irq(IRQ_AUTO_6, via1_irq,
 				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
 				(void *) via1);
 	} else {
-		cpu_request_irq(IRQ_AUTO_1, via1_irq,
+		request_irq(IRQ_AUTO_1, via1_irq,
 				IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
 				(void *) via1);
-#if 0 /* interferes with serial on some machines */
-		if (!psc_present) {
-			cpu_request_irq(IRQ_AUTO_6, mac_bang, IRQ_FLG_LOCK,
-					"Off Switch", mac_bang);
-		}
-#endif
 	}
-	cpu_request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+	request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
 			"via2", (void *) via2);
 	if (!psc_present) {
-		cpu_request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
+		request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
 				"scc", mac_scc_dispatch);
 	}
 	request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
@@ -437,7 +424,7 @@
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
 		if (events & irq_bit) {
 			via1[vIER] = irq_bit;
-			mac_do_irq_list(VIA1_SOURCE_BASE + i, regs);
+			m68k_handle_int(VIA1_SOURCE_BASE + i, regs);
 			via1[vIFR] = irq_bit;
 			via1[vIER] = irq_bit | 0x80;
 		}
@@ -452,7 +439,7 @@
 		/* No, it won't be set. that's why we're doing this. */
 		via_irq_disable(IRQ_MAC_NUBUS);
 		via_irq_clear(IRQ_MAC_NUBUS);
-		mac_do_irq_list(IRQ_MAC_NUBUS, regs);
+		m68k_handle_int(IRQ_MAC_NUBUS, regs);
 		via_irq_enable(IRQ_MAC_NUBUS);
 	}
 #endif
@@ -471,8 +458,8 @@
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1)
 		if (events & irq_bit) {
 			via2[gIER] = irq_bit;
-			mac_do_irq_list(VIA2_SOURCE_BASE + i, regs);
 			via2[gIFR] = irq_bit | rbv_clear;
+			m68k_handle_int(VIA2_SOURCE_BASE + i, regs);
 			via2[gIER] = irq_bit | 0x80;
 		}
 	return IRQ_HANDLED;
@@ -494,7 +481,7 @@
 	for (i = 0, irq_bit = 1 ; i < 7 ; i++, irq_bit <<= 1) {
 		if (events & irq_bit) {
 			via_irq_disable(NUBUS_SOURCE_BASE + i);
-			mac_do_irq_list(NUBUS_SOURCE_BASE + i, regs);
+			m68k_handle_int(NUBUS_SOURCE_BASE + i, regs);
 			via_irq_enable(NUBUS_SOURCE_BASE + i);
 		}
 	}
@@ -529,6 +516,7 @@
 		}
 		via2[gIER] = irq_bit | 0x80;
 	} else if (irq_src == 7) {
+		nubus_active |= irq_bit;
 		if (rbv_present) {
 			/* enable the slot interrupt. SIER works like IER. */
 			via2[rSIER] = IER_SET_BIT(irq_idx);
@@ -550,7 +538,6 @@
 				}
 			}
 		}
-		nubus_active |= irq_bit;
 	}
 }
 
diff --git a/arch/m68k/mm/kmap.c b/arch/m68k/mm/kmap.c
index 85ad19a..43ffab0 100644
--- a/arch/m68k/mm/kmap.c
+++ b/arch/m68k/mm/kmap.c
@@ -259,13 +259,15 @@
 
 		if (CPU_IS_020_OR_030) {
 			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
+			int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
 
-			if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
+			if (pmd_type == _PAGE_PRESENT) {
 				pmd_dir->pmd[pmd_off] = 0;
 				virtaddr += PTRTREESIZE;
 				size -= PTRTREESIZE;
 				continue;
-			}
+			} else if (pmd_type == 0)
+				continue;
 		}
 
 		if (pmd_bad(*pmd_dir)) {
diff --git a/arch/m68k/mm/memory.c b/arch/m68k/mm/memory.c
index d6d582a..a226668 100644
--- a/arch/m68k/mm/memory.c
+++ b/arch/m68k/mm/memory.c
@@ -94,8 +94,7 @@
 	PD_MARKBITS(dp) = mask & ~tmp;
 	if (!PD_MARKBITS(dp)) {
 		/* move to end of list */
-		list_del(dp);
-		list_add_tail(dp, &ptable_list);
+		list_move_tail(dp, &ptable_list);
 	}
 	return (pmd_t *) (page_address(PD_PAGE(dp)) + off);
 }
@@ -123,8 +122,7 @@
 		 * move this descriptor to the front of the list, since
 		 * it has one or more free tables.
 		 */
-		list_del(dp);
-		list_add(dp, &ptable_list);
+		list_move(dp, &ptable_list);
 	}
 	return 0;
 }
diff --git a/arch/m68k/mm/motorola.c b/arch/m68k/mm/motorola.c
index afb57ee..bdb1110 100644
--- a/arch/m68k/mm/motorola.c
+++ b/arch/m68k/mm/motorola.c
@@ -203,7 +203,7 @@
 {
 	int chunk;
 	unsigned long mem_avail = 0;
-	unsigned long zones_size[3] = { 0, };
+	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
 
 #ifdef DEBUG
 	{
@@ -257,12 +257,12 @@
 #ifdef DEBUG
 	printk ("before free_area_init\n");
 #endif
-	zones_size[0] = (mach_max_dma_address < (unsigned long)high_memory ?
-			 (mach_max_dma_address+1) : (unsigned long)high_memory);
-	zones_size[1] = (unsigned long)high_memory - zones_size[0];
+	zones_size[ZONE_DMA] = (mach_max_dma_address < (unsigned long)high_memory ?
+				(mach_max_dma_address+1) : (unsigned long)high_memory);
+	zones_size[ZONE_NORMAL] = (unsigned long)high_memory - zones_size[0];
 
-	zones_size[0] = (zones_size[0] - PAGE_OFFSET) >> PAGE_SHIFT;
-	zones_size[1] >>= PAGE_SHIFT;
+	zones_size[ZONE_DMA] = (zones_size[ZONE_DMA] - PAGE_OFFSET) >> PAGE_SHIFT;
+	zones_size[ZONE_NORMAL] >>= PAGE_SHIFT;
 
 	free_area_init(zones_size);
 }
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index a47be19..ac6640ad 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -46,7 +46,7 @@
 	unsigned long address;
 	unsigned long next_pgtable;
 	unsigned long bootmem_end;
-	unsigned long zones_size[3] = {0, 0, 0};
+	unsigned long zones_size[MAX_NR_ZONES] = { 0, };
 	unsigned long size;
 
 
@@ -92,8 +92,7 @@
 	current->mm = NULL;
 
 	/* memory sizing is a hack stolen from motorola.c..  hope it works for us */
-	zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
-	zones_size[1] = 0;
+	zones_size[ZONE_DMA] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
 
 	free_area_init(zones_size);
 
diff --git a/arch/m68k/mvme147/147ints.c b/arch/m68k/mvme147/147ints.c
deleted file mode 100644
index 69a744e..0000000
--- a/arch/m68k/mvme147/147ints.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * arch/m68k/mvme147/147ints.c
- *
- * Copyright (C) 1997 Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * based on amiints.c -- Amiga Linux interrupt handling code
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/seq_file.h>
-
-#include <asm/ptrace.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/traps.h>
-
-static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp);
-
-/*
- * This should ideally be 4 elements only, for speed.
- */
-
-static struct {
-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
-	unsigned long	flags;
-	void		*dev_id;
-	const char	*devname;
-	unsigned	count;
-} irq_tab[256];
-
-/*
- * void mvme147_init_IRQ (void)
- *
- * Parameters:	None
- *
- * Returns:	Nothing
- *
- * This function is called during kernel startup to initialize
- * the mvme147 IRQ handling routines.
- */
-
-void mvme147_init_IRQ (void)
-{
-	int i;
-
-	for (i = 0; i < 256; i++) {
-		irq_tab[i].handler = mvme147_defhand;
-		irq_tab[i].flags = IRQ_FLG_STD;
-		irq_tab[i].dev_id = NULL;
-		irq_tab[i].devname = NULL;
-		irq_tab[i].count = 0;
-	}
-}
-
-int mvme147_request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                unsigned long flags, const char *devname, void *dev_id)
-{
-	if (irq > 255) {
-		printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
-		return -ENXIO;
-	}
-	if (!(irq_tab[irq].flags & IRQ_FLG_STD)) {
-		if (irq_tab[irq].flags & IRQ_FLG_LOCK) {
-			printk("%s: IRQ %d from %s is not replaceable\n",
-			       __FUNCTION__, irq, irq_tab[irq].devname);
-			return -EBUSY;
-		}
-		if (flags & IRQ_FLG_REPLACE) {
-			printk("%s: %s can't replace IRQ %d from %s\n",
-			       __FUNCTION__, devname, irq, irq_tab[irq].devname);
-			return -EBUSY;
-		}
-	}
-	irq_tab[irq].handler = handler;
-	irq_tab[irq].flags   = flags;
-	irq_tab[irq].dev_id  = dev_id;
-	irq_tab[irq].devname = devname;
-	return 0;
-}
-
-void mvme147_free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq > 255) {
-		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
-		return;
-	}
-	if (irq_tab[irq].dev_id != dev_id)
-		printk("%s: Removing probably wrong IRQ %d from %s\n",
-		       __FUNCTION__, irq, irq_tab[irq].devname);
-
-	irq_tab[irq].handler = mvme147_defhand;
-	irq_tab[irq].flags   = IRQ_FLG_STD;
-	irq_tab[irq].dev_id  = NULL;
-	irq_tab[irq].devname = NULL;
-}
-
-irqreturn_t mvme147_process_int (unsigned long vec, struct pt_regs *fp)
-{
-	if (vec > 255) {
-		printk ("mvme147_process_int: Illegal vector %ld\n", vec);
-		return IRQ_NONE;
-	} else {
-		irq_tab[vec].count++;
-		irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
-		return IRQ_HANDLED;
-	}
-}
-
-int show_mvme147_interrupts (struct seq_file *p, void *v)
-{
-	int i;
-
-	for (i = 0; i < 256; i++) {
-		if (irq_tab[i].count)
-			seq_printf(p, "Vec 0x%02x: %8d  %s\n",
-			    i, irq_tab[i].count,
-			    irq_tab[i].devname ? irq_tab[i].devname : "free");
-	}
-	return 0;
-}
-
-
-static irqreturn_t mvme147_defhand (int irq, void *dev_id, struct pt_regs *fp)
-{
-	printk ("Unknown interrupt 0x%02x\n", irq);
-	return IRQ_NONE;
-}
-
-void mvme147_enable_irq (unsigned int irq)
-{
-}
-
-
-void mvme147_disable_irq (unsigned int irq)
-{
-}
-
diff --git a/arch/m68k/mvme147/Makefile b/arch/m68k/mvme147/Makefile
index f0153ed..a36d38d 100644
--- a/arch/m68k/mvme147/Makefile
+++ b/arch/m68k/mvme147/Makefile
@@ -2,4 +2,4 @@
 # Makefile for Linux arch/m68k/mvme147 source directory
 #
 
-obj-y		:= config.o 147ints.o
+obj-y		:= config.o
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 0fcf972..0cd0e5b 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -36,15 +36,8 @@
 #include <asm/mvme147hw.h>
 
 
-extern irqreturn_t mvme147_process_int (int level, struct pt_regs *regs);
-extern void mvme147_init_IRQ (void);
-extern void mvme147_free_irq (unsigned int, void *);
-extern int  show_mvme147_interrupts (struct seq_file *, void *);
-extern void mvme147_enable_irq (unsigned int);
-extern void mvme147_disable_irq (unsigned int);
 static void mvme147_get_model(char *model);
 static int  mvme147_get_hardware_list(char *buffer);
-extern int mvme147_request_irq (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
 extern void mvme147_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern unsigned long mvme147_gettimeoffset (void);
 extern int mvme147_hwclk (int, struct rtc_time *);
@@ -91,6 +84,15 @@
 	return 0;
 }
 
+/*
+ * This function is called during kernel startup to initialize
+ * the mvme147 IRQ handling routines.
+ */
+
+void mvme147_init_IRQ(void)
+{
+	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+}
 
 void __init config_mvme147(void)
 {
@@ -101,12 +103,6 @@
 	mach_hwclk		= mvme147_hwclk;
 	mach_set_clock_mmss	= mvme147_set_clock_mmss;
 	mach_reset		= mvme147_reset;
-	mach_free_irq		= mvme147_free_irq;
-	mach_process_int	= mvme147_process_int;
-	mach_get_irq_list	= show_mvme147_interrupts;
-	mach_request_irq	= mvme147_request_irq;
-	enable_irq		= mvme147_enable_irq;
-	disable_irq		= mvme147_disable_irq;
 	mach_get_model		= mvme147_get_model;
 	mach_get_hardware_list	= mvme147_get_hardware_list;
 
diff --git a/arch/m68k/mvme16x/16xints.c b/arch/m68k/mvme16x/16xints.c
deleted file mode 100644
index 793ef73..0000000
--- a/arch/m68k/mvme16x/16xints.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * arch/m68k/mvme16x/16xints.c
- *
- * Copyright (C) 1995 Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * based on amiints.c -- Amiga Linux interrupt handling code
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/seq_file.h>
-
-#include <asm/system.h>
-#include <asm/ptrace.h>
-#include <asm/irq.h>
-
-static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp);
-
-/*
- * This should ideally be 4 elements only, for speed.
- */
-
-static struct {
-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
-	unsigned long	flags;
-	void		*dev_id;
-	const char	*devname;
-	unsigned	count;
-} irq_tab[192];
-
-/*
- * void mvme16x_init_IRQ (void)
- *
- * Parameters:	None
- *
- * Returns:	Nothing
- *
- * This function is called during kernel startup to initialize
- * the mvme16x IRQ handling routines.  Should probably ensure
- * that the base vectors for the VMEChip2 and PCCChip2 are valid.
- */
-
-void mvme16x_init_IRQ (void)
-{
-	int i;
-
-	for (i = 0; i < 192; i++) {
-		irq_tab[i].handler = mvme16x_defhand;
-		irq_tab[i].flags = IRQ_FLG_STD;
-		irq_tab[i].dev_id = NULL;
-		irq_tab[i].devname = NULL;
-		irq_tab[i].count = 0;
-	}
-}
-
-int mvme16x_request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                unsigned long flags, const char *devname, void *dev_id)
-{
-	if (irq < 64 || irq > 255) {
-		printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
-		return -ENXIO;
-	}
-
-	if (!(irq_tab[irq-64].flags & IRQ_FLG_STD)) {
-		if (irq_tab[irq-64].flags & IRQ_FLG_LOCK) {
-			printk("%s: IRQ %d from %s is not replaceable\n",
-			       __FUNCTION__, irq, irq_tab[irq-64].devname);
-			return -EBUSY;
-		}
-		if (flags & IRQ_FLG_REPLACE) {
-			printk("%s: %s can't replace IRQ %d from %s\n",
-			       __FUNCTION__, devname, irq, irq_tab[irq-64].devname);
-			return -EBUSY;
-		}
-	}
-	irq_tab[irq-64].handler = handler;
-	irq_tab[irq-64].flags   = flags;
-	irq_tab[irq-64].dev_id  = dev_id;
-	irq_tab[irq-64].devname = devname;
-	return 0;
-}
-
-void mvme16x_free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq < 64 || irq > 255) {
-		printk("%s: Incorrect IRQ %d\n", __FUNCTION__, irq);
-		return;
-	}
-
-	if (irq_tab[irq-64].dev_id != dev_id)
-		printk("%s: Removing probably wrong IRQ %d from %s\n",
-		       __FUNCTION__, irq, irq_tab[irq-64].devname);
-
-	irq_tab[irq-64].handler = mvme16x_defhand;
-	irq_tab[irq-64].flags   = IRQ_FLG_STD;
-	irq_tab[irq-64].dev_id  = NULL;
-	irq_tab[irq-64].devname = NULL;
-}
-
-irqreturn_t mvme16x_process_int (unsigned long vec, struct pt_regs *fp)
-{
-	if (vec < 64 || vec > 255) {
-		printk ("mvme16x_process_int: Illegal vector %ld", vec);
-		return IRQ_NONE;
-	} else {
-		irq_tab[vec-64].count++;
-		irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp);
-		return IRQ_HANDLED;
-	}
-}
-
-int show_mvme16x_interrupts (struct seq_file *p, void *v)
-{
-	int i;
-
-	for (i = 0; i < 192; i++) {
-		if (irq_tab[i].count)
-			seq_printf(p, "Vec 0x%02x: %8d  %s\n",
-			    i+64, irq_tab[i].count,
-			    irq_tab[i].devname ? irq_tab[i].devname : "free");
-	}
-	return 0;
-}
-
-
-static irqreturn_t mvme16x_defhand (int irq, void *dev_id, struct pt_regs *fp)
-{
-	printk ("Unknown interrupt 0x%02x\n", irq);
-	return IRQ_NONE;
-}
-
-
-void mvme16x_enable_irq (unsigned int irq)
-{
-}
-
-
-void mvme16x_disable_irq (unsigned int irq)
-{
-}
-
-
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index 5129f56..950e82f 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -2,4 +2,4 @@
 # Makefile for Linux arch/m68k/mvme16x source directory
 #
 
-obj-y		:= config.o 16xints.o rtc.o mvme16x_ksyms.o
+obj-y		:= config.o rtc.o mvme16x_ksyms.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 26ce81c..ce2727e 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -40,15 +40,8 @@
 
 static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
 
-extern irqreturn_t mvme16x_process_int (int level, struct pt_regs *regs);
-extern void mvme16x_init_IRQ (void);
-extern void mvme16x_free_irq (unsigned int, void *);
-extern int show_mvme16x_interrupts (struct seq_file *, void *);
-extern void mvme16x_enable_irq (unsigned int);
-extern void mvme16x_disable_irq (unsigned int);
 static void mvme16x_get_model(char *model);
 static int  mvme16x_get_hardware_list(char *buffer);
-extern int  mvme16x_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
 extern void mvme16x_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern unsigned long mvme16x_gettimeoffset (void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
@@ -120,6 +113,16 @@
     return (len);
 }
 
+/*
+ * This function is called during kernel startup to initialize
+ * the mvme16x IRQ handling routines.  Should probably ensure
+ * that the base vectors for the VMEChip2 and PCCChip2 are valid.
+ */
+
+static void mvme16x_init_IRQ (void)
+{
+	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+}
 
 #define pcc2chip	((volatile u_char *)0xfff42000)
 #define PccSCCMICR	0x1d
@@ -138,12 +141,6 @@
     mach_hwclk           = mvme16x_hwclk;
     mach_set_clock_mmss	 = mvme16x_set_clock_mmss;
     mach_reset		 = mvme16x_reset;
-    mach_free_irq	 = mvme16x_free_irq;
-    mach_process_int	 = mvme16x_process_int;
-    mach_get_irq_list	 = show_mvme16x_interrupts;
-    mach_request_irq	 = mvme16x_request_irq;
-    enable_irq           = mvme16x_enable_irq;
-    disable_irq          = mvme16x_disable_irq;
     mach_get_model       = mvme16x_get_model;
     mach_get_hardware_list = mvme16x_get_hardware_list;
 
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 5e0f9b0..efa52d3 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -37,15 +37,9 @@
 #include <asm/q40_master.h>
 
 extern irqreturn_t q40_process_int (int level, struct pt_regs *regs);
-extern irqreturn_t (*q40_default_handler[]) (int, void *, struct pt_regs *);  /* added just for debugging */
 extern void q40_init_IRQ (void);
-extern void q40_free_irq (unsigned int, void *);
-extern int  show_q40_interrupts (struct seq_file *, void *);
-extern void q40_enable_irq (unsigned int);
-extern void q40_disable_irq (unsigned int);
 static void q40_get_model(char *model);
 static int  q40_get_hardware_list(char *buffer);
-extern int  q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
 extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 
 extern unsigned long q40_gettimeoffset (void);
@@ -175,13 +169,6 @@
     mach_set_clock_mmss	 = q40_set_clock_mmss;
 
     mach_reset		 = q40_reset;
-    mach_free_irq	 = q40_free_irq;
-    mach_process_int	 = q40_process_int;
-    mach_get_irq_list	 = show_q40_interrupts;
-    mach_request_irq	 = q40_request_irq;
-    enable_irq		 = q40_enable_irq;
-    disable_irq          = q40_disable_irq;
-    mach_default_handler = &q40_default_handler;
     mach_get_model       = q40_get_model;
     mach_get_hardware_list = q40_get_hardware_list;
 
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index f8ecc26..472f41c 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -14,13 +14,8 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
 #include <linux/interrupt.h>
-#include <linux/hardirq.h>
 
-#include <asm/rtc.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -39,29 +34,37 @@
  *
 */
 
-extern int ints_inited;
+static void q40_irq_handler(unsigned int, struct pt_regs *fp);
+static void q40_enable_irq(unsigned int);
+static void q40_disable_irq(unsigned int);
 
+unsigned short q40_ablecount[35];
+unsigned short q40_state[35];
 
-irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp);
+static int q40_irq_startup(unsigned int irq)
+{
+	/* test for ISA ints not implemented by HW */
+	switch (irq) {
+	case 1: case 2: case 8: case 9:
+	case 11: case 12: case 13:
+		printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq);
+		return -ENXIO;
+	}
+	return 0;
+}
 
+static void q40_irq_shutdown(unsigned int irq)
+{
+}
 
-static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
-static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs);
-
-
-#define DEVNAME_SIZE 24
-
-static struct q40_irq_node {
-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
-	unsigned long	flags;
-	void		*dev_id;
-  /*        struct q40_irq_node *next;*/
-        char	        devname[DEVNAME_SIZE];
-	unsigned	count;
-        unsigned short  state;
-} irq_tab[Q40_IRQ_MAX+1];
-
-short unsigned q40_ablecount[Q40_IRQ_MAX+1];
+static struct irq_controller q40_irq_controller = {
+	.name		= "q40",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.startup	= q40_irq_startup,
+	.shutdown	= q40_irq_shutdown,
+	.enable		= q40_enable_irq,
+	.disable	= q40_disable_irq,
+};
 
 /*
  * void q40_init_IRQ (void)
@@ -74,139 +77,29 @@
  * the q40 IRQ handling routines.
  */
 
-static int disabled=0;
+static int disabled;
 
-void q40_init_IRQ (void)
+void q40_init_IRQ(void)
 {
-	int i;
-
-	disabled=0;
-	for (i = 0; i <= Q40_IRQ_MAX; i++) {
-		irq_tab[i].handler = q40_defhand;
-		irq_tab[i].flags = 0;
-		irq_tab[i].dev_id = NULL;
-		/*		irq_tab[i].next = NULL;*/
-		irq_tab[i].devname[0] = 0;
-		irq_tab[i].count = 0;
-		irq_tab[i].state =0;
-		q40_ablecount[i]=0;   /* all enabled */
-	}
+	m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
 
 	/* setup handler for ISA ints */
-	cpu_request_irq(IRQ2, q40_irq2_handler, 0, "q40 ISA and master chip",
-			NULL);
+	m68k_setup_auto_interrupt(q40_irq_handler);
+
+	m68k_irq_startup(IRQ_AUTO_2);
+	m68k_irq_startup(IRQ_AUTO_4);
 
 	/* now enable some ints.. */
-	master_outb(1,EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
+	master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
 
 	/* make sure keyboard IRQ is disabled */
-	master_outb(0,KEY_IRQ_ENABLE_REG);
+	master_outb(0, KEY_IRQ_ENABLE_REG);
 }
 
-int q40_request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                unsigned long flags, const char *devname, void *dev_id)
-{
-  /*printk("q40_request_irq %d, %s\n",irq,devname);*/
-
-	if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
-		printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname);
-		return -ENXIO;
-	}
-
-	/* test for ISA ints not implemented by HW */
-	switch (irq)
-	  {
-	  case 1: case 2: case 8: case 9:
-	  case 12: case 13:
-	    printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname);
-	    return -ENXIO;
-	  case 11:
-	    printk("warning IRQ 10 and 11 not distinguishable\n");
-	    irq=10;
-	  default:
-	    ;
-	  }
-
-	if (irq<Q40_IRQ_SAMPLE)
-	  {
-	    if (irq_tab[irq].dev_id != NULL)
-		  {
-		    printk("%s: IRQ %d from %s is not replaceable\n",
-			   __FUNCTION__, irq, irq_tab[irq].devname);
-		    return -EBUSY;
-		  }
-	    /*printk("IRQ %d set to handler %p\n",irq,handler);*/
-	    if (dev_id==NULL)
-		  {
-		printk("WARNING: dev_id == NULL in request_irq\n");
-		dev_id=(void*)1;
-	      }
-	    irq_tab[irq].handler = handler;
-	    irq_tab[irq].flags   = flags;
-	    irq_tab[irq].dev_id  = dev_id;
-	    strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname));
-	    irq_tab[irq].state = 0;
-	    return 0;
-	  }
-	else {
-	  /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/
-	  cpu_request_irq(4, handler, flags, devname, dev_id);
-	  cpu_request_irq(6, handler, flags, devname, dev_id);
-	  return 0;
-	}
-}
-
-void q40_free_irq(unsigned int irq, void *dev_id)
-{
-	if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) {
-		printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id);
-		return;
-	}
-
-	/* test for ISA ints not implemented by HW */
-	switch (irq)
-	  {
-	  case 1: case 2: case 8: case 9:
-	  case 12: case 13:
-	    printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id);
-	    return;
-	  case 11: irq=10;
-	  default:
-	    ;
-	  }
-
-	if (irq<Q40_IRQ_SAMPLE)
-	  {
-	    if (irq_tab[irq].dev_id != dev_id)
-	      printk("%s: Removing probably wrong IRQ %d from %s\n",
-		     __FUNCTION__, irq, irq_tab[irq].devname);
-
-	    irq_tab[irq].handler = q40_defhand;
-	    irq_tab[irq].flags   = 0;
-	    irq_tab[irq].dev_id  = NULL;
-	    /* irq_tab[irq].devname = NULL; */
-	    /* do not reset state !! */
-	  }
-	else
-	  { /* == Q40_IRQ_SAMPLE */
-	    cpu_free_irq(4, dev_id);
-	    cpu_free_irq(6, dev_id);
-	  }
-}
-
-
-irqreturn_t q40_process_int (int level, struct pt_regs *fp)
-{
-  printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n",
-          level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2);
-  printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG));
-  return IRQ_HANDLED;
-}
 
 /*
  * this stuff doesn't really belong here..
-*/
+ */
 
 int ql_ticks;              /* 200Hz ticks since last jiffie */
 static int sound_ticks;
@@ -215,54 +108,53 @@
 
 void q40_mksound(unsigned int hz, unsigned int ticks)
 {
-  /* for now ignore hz, except that hz==0 switches off sound */
-  /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
-  if (hz==0)
-    {
-      if (sound_ticks)
-	sound_ticks=1;
+	/* for now ignore hz, except that hz==0 switches off sound */
+	/* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
+	if (hz == 0) {
+		if (sound_ticks)
+			sound_ticks = 1;
 
-      *DAC_LEFT=128;
-      *DAC_RIGHT=128;
+		*DAC_LEFT = 128;
+		*DAC_RIGHT = 128;
 
-      return;
-    }
-  /* sound itself is done in q40_timer_int */
-  if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
-  sound_ticks=ticks<<1;
+		return;
+	}
+	/* sound itself is done in q40_timer_int */
+	if (sound_ticks == 0)
+		sound_ticks = 1000; /* pretty long beep */
+	sound_ticks = ticks << 1;
 }
 
 static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *);
 
 static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs)
 {
-    ql_ticks = ql_ticks ? 0 : 1;
-    if (sound_ticks)
-      {
-	unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
-	sound_ticks--;
-	*DAC_LEFT=sval;
-	*DAC_RIGHT=sval;
-      }
+	ql_ticks = ql_ticks ? 0 : 1;
+	if (sound_ticks) {
+		unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
+		sound_ticks--;
+		*DAC_LEFT=sval;
+		*DAC_RIGHT=sval;
+	}
 
-    if (!ql_ticks)
-	q40_timer_routine(irq, dev, regs);
-    return IRQ_HANDLED;
+	if (!ql_ticks)
+		q40_timer_routine(irq, dev, regs);
+	return IRQ_HANDLED;
 }
 
 void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *))
 {
-    int timer_irq;
+	int timer_irq;
 
-    q40_timer_routine = timer_routine;
-    timer_irq=Q40_IRQ_FRAME;
+	q40_timer_routine = timer_routine;
+	timer_irq = Q40_IRQ_FRAME;
 
-    if (request_irq(timer_irq, q40_timer_int, 0,
+	if (request_irq(timer_irq, q40_timer_int, 0,
 				"timer", q40_timer_int))
-	panic ("Couldn't register timer int");
+		panic("Couldn't register timer int");
 
-    master_outb(-1,FRAME_CLEAR_REG);
-    master_outb( 1,FRAME_RATE_REG);
+	master_outb(-1, FRAME_CLEAR_REG);
+	master_outb( 1, FRAME_RATE_REG);
 }
 
 
@@ -308,169 +200,132 @@
 static int aliased_irq=0;  /* how many times inside handler ?*/
 
 
-/* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */
-irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
+/* got interrupt, dispatch to ISA or keyboard/timer IRQs */
+static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
 {
-  unsigned mir, mer;
-  int irq,i;
+	unsigned mir, mer;
+	int i;
 
 //repeat:
-  mir=master_inb(IIRQ_REG);
-  if (mir&Q40_IRQ_FRAME_MASK) {
-	  irq_tab[Q40_IRQ_FRAME].count++;
-	  irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);
-	  master_outb(-1,FRAME_CLEAR_REG);
-  }
-  if ((mir&Q40_IRQ_SER_MASK) || (mir&Q40_IRQ_EXT_MASK)) {
-	  mer=master_inb(EIRQ_REG);
-	  for (i=0; eirqs[i].mask; i++) {
-		  if (mer&(eirqs[i].mask)) {
-			  irq=eirqs[i].irq;
+	mir = master_inb(IIRQ_REG);
+#ifdef CONFIG_BLK_DEV_FD
+	if ((mir & Q40_IRQ_EXT_MASK) &&
+	    (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) {
+		floppy_hardint();
+		return;
+	}
+#endif
+	switch (irq) {
+	case 4:
+	case 6:
+		m68k_handle_int(Q40_IRQ_SAMPLE, fp);
+		return;
+	}
+	if (mir & Q40_IRQ_FRAME_MASK) {
+		m68k_handle_int(Q40_IRQ_FRAME, fp);
+		master_outb(-1, FRAME_CLEAR_REG);
+	}
+	if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
+		mer = master_inb(EIRQ_REG);
+		for (i = 0; eirqs[i].mask; i++) {
+			if (mer & eirqs[i].mask) {
+				irq = eirqs[i].irq;
 /*
  * There is a little mess wrt which IRQ really caused this irq request. The
  * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
  * are read - which is long after the request came in. In theory IRQs should
  * not just go away but they occassionally do
  */
-			  if (irq>4 && irq<=15 && mext_disabled) {
-				  /*aliased_irq++;*/
-				  goto iirq;
-			  }
-			  if (irq_tab[irq].handler == q40_defhand ) {
-				  printk("handler for IRQ %d not defined\n",irq);
-				  continue; /* ignore uninited INTs :-( */
-			  }
-			  if ( irq_tab[irq].state & IRQ_INPROGRESS ) {
-				  /* some handlers do local_irq_enable() for irq latency reasons, */
-				  /* however reentering an active irq handler is not permitted */
+				if (irq > 4 && irq <= 15 && mext_disabled) {
+					/*aliased_irq++;*/
+					goto iirq;
+				}
+				if (q40_state[irq] & IRQ_INPROGRESS) {
+					/* some handlers do local_irq_enable() for irq latency reasons, */
+					/* however reentering an active irq handler is not permitted */
 #ifdef IP_USE_DISABLE
-				  /* in theory this is the better way to do it because it still */
-				  /* lets through eg the serial irqs, unfortunately it crashes */
-				  disable_irq(irq);
-				  disabled=1;
+					/* in theory this is the better way to do it because it still */
+					/* lets through eg the serial irqs, unfortunately it crashes */
+					disable_irq(irq);
+					disabled = 1;
 #else
-				  /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */
-				  fp->sr = (((fp->sr) & (~0x700))+0x200);
-				  disabled=1;
+					/*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",
+						irq, disabled ? "already" : "not yet"); */
+					fp->sr = (((fp->sr) & (~0x700))+0x200);
+					disabled = 1;
 #endif
-				  goto iirq;
-			  }
-			  irq_tab[irq].count++;
-			  irq_tab[irq].state |= IRQ_INPROGRESS;
-			  irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp);
-			  irq_tab[irq].state &= ~IRQ_INPROGRESS;
+					goto iirq;
+				}
+				q40_state[irq] |= IRQ_INPROGRESS;
+				m68k_handle_int(irq, fp);
+				q40_state[irq] &= ~IRQ_INPROGRESS;
 
-			  /* naively enable everything, if that fails than    */
-			  /* this function will be reentered immediately thus */
-			  /* getting another chance to disable the IRQ        */
+				/* naively enable everything, if that fails than    */
+				/* this function will be reentered immediately thus */
+				/* getting another chance to disable the IRQ        */
 
-			  if ( disabled ) {
+				if (disabled) {
 #ifdef IP_USE_DISABLE
-				  if (irq>4){
-					  disabled=0;
-					  enable_irq(irq);}
+					if (irq > 4) {
+						disabled = 0;
+						enable_irq(irq);
+					}
 #else
-				  disabled=0;
-				  /*printk("reenabling irq %d\n",irq); */
+					disabled = 0;
+					/*printk("reenabling irq %d\n", irq); */
 #endif
-			  }
+				}
 // used to do 'goto repeat;' here, this delayed bh processing too long
-			  return IRQ_HANDLED;
-		  }
-	  }
-	  if (mer && ccleirq>0 && !aliased_irq)
-		  printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
-  }
- iirq:
-  mir=master_inb(IIRQ_REG);
-  /* should test whether keyboard irq is really enabled, doing it in defhand */
-  if (mir&Q40_IRQ_KEYB_MASK) {
-	  irq_tab[Q40_IRQ_KEYBOARD].count++;
-	  irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
-  }
-  return IRQ_HANDLED;
-}
-
-int show_q40_interrupts (struct seq_file *p, void *v)
-{
-	int i;
-
-	for (i = 0; i <= Q40_IRQ_MAX; i++) {
-		if (irq_tab[i].count)
-		      seq_printf(p, "%sIRQ %02d: %8d  %s%s\n",
-			      (i<=15) ? "ISA-" : "    " ,
-			    i, irq_tab[i].count,
-			    irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
-			    irq_tab[i].handler == q40_defhand ?
-					" (now unassigned)" : "");
+				return;
+			}
+		}
+		if (mer && ccleirq > 0 && !aliased_irq) {
+			printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer);
+			ccleirq--;
+		}
 	}
-	return 0;
+ iirq:
+	mir = master_inb(IIRQ_REG);
+	/* should test whether keyboard irq is really enabled, doing it in defhand */
+	if (mir & Q40_IRQ_KEYB_MASK)
+		m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
+
+	return;
 }
 
-
-static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp)
+void q40_enable_irq(unsigned int irq)
 {
-        if (irq!=Q40_IRQ_KEYBOARD)
-	     printk ("Unknown q40 interrupt %d\n", irq);
-	else master_outb(-1,KEYBOARD_UNLOCK_REG);
-	return IRQ_NONE;
+	if (irq >= 5 && irq <= 15) {
+		mext_disabled--;
+		if (mext_disabled > 0)
+			printk("q40_enable_irq : nested disable/enable\n");
+		if (mext_disabled == 0)
+			master_outb(1, EXT_ENABLE_REG);
+	}
 }
-static irqreturn_t default_handler(int lev, void *dev_id, struct pt_regs *regs)
+
+
+void q40_disable_irq(unsigned int irq)
 {
-	printk ("Uninitialised interrupt level %d\n", lev);
-	return IRQ_NONE;
+	/* disable ISA iqs : only do something if the driver has been
+	 * verified to be Q40 "compatible" - right now IDE, NE2K
+	 * Any driver should not attempt to sleep across disable_irq !!
+	 */
+
+	if (irq >= 5 && irq <= 15) {
+		master_outb(0, EXT_ENABLE_REG);
+		mext_disabled++;
+		if (mext_disabled > 1)
+			printk("disable_irq nesting count %d\n",mext_disabled);
+	}
 }
 
-irqreturn_t (*q40_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	 [0] = default_handler,
-	 [1] = default_handler,
-	 [2] = default_handler,
-	 [3] = default_handler,
-	 [4] = default_handler,
-	 [5] = default_handler,
-	 [6] = default_handler,
-	 [7] = default_handler
-};
-
-
-void q40_enable_irq (unsigned int irq)
+unsigned long q40_probe_irq_on(void)
 {
-  if ( irq>=5 && irq<=15 )
-  {
-    mext_disabled--;
-    if (mext_disabled>0)
-	  printk("q40_enable_irq : nested disable/enable\n");
-    if (mext_disabled==0)
-    master_outb(1,EXT_ENABLE_REG);
-    }
+	printk("irq probing not working - reconfigure the driver to avoid this\n");
+	return -1;
 }
-
-
-void q40_disable_irq (unsigned int irq)
+int q40_probe_irq_off(unsigned long irqs)
 {
-  /* disable ISA iqs : only do something if the driver has been
-   * verified to be Q40 "compatible" - right now IDE, NE2K
-   * Any driver should not attempt to sleep across disable_irq !!
-   */
-
-  if ( irq>=5 && irq<=15 ) {
-    master_outb(0,EXT_ENABLE_REG);
-    mext_disabled++;
-    if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled);
-  }
+	return -1;
 }
-
-unsigned long q40_probe_irq_on (void)
-{
-  printk("irq probing not working - reconfigure the driver to avoid this\n");
-  return -1;
-}
-int q40_probe_irq_off (unsigned long irqs)
-{
-  return -1;
-}
-/*
- * Local variables:
- * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040   -c -o q40ints.o q40ints.c"
- * End:
- */
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index f1ca0df..553c304 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -36,7 +36,6 @@
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
 extern unsigned long sun3_gettimeoffset(void);
-extern int show_sun3_interrupts (struct seq_file *, void *);
 extern void sun3_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
 extern void sun3_get_model (char* model);
 extern void idprom_init (void);
@@ -147,13 +146,6 @@
 
         mach_sched_init      =  sun3_sched_init;
         mach_init_IRQ        =  sun3_init_IRQ;
-        mach_default_handler = &sun3_default_handler;
-        mach_request_irq     =  sun3_request_irq;
-        mach_free_irq        =  sun3_free_irq;
-	enable_irq	     =  sun3_enable_irq;
-        disable_irq	     =  sun3_disable_irq;
-	mach_process_int     =  sun3_process_int;
-        mach_get_irq_list    =  show_sun3_interrupts;
         mach_reset           =  sun3_reboot;
 	mach_gettimeoffset   =  sun3_gettimeoffset;
 	mach_get_model	     =  sun3_get_model;
diff --git a/arch/m68k/sun3/sun3dvma.c b/arch/m68k/sun3/sun3dvma.c
index f04a1d2..97c7bfd 100644
--- a/arch/m68k/sun3/sun3dvma.c
+++ b/arch/m68k/sun3/sun3dvma.c
@@ -119,8 +119,7 @@
 		if(hole->end == prev->start) {
 			hole->size += prev->size;
 			hole->end = prev->end;
-			list_del(&(prev->list));
-			list_add(&(prev->list), &hole_cache);
+			list_move(&(prev->list), &hole_cache);
 			ret++;
 		}
 
@@ -182,8 +181,7 @@
 #endif
 			return hole->end;
 		} else if(hole->size == newlen) {
-			list_del(&(hole->list));
-			list_add(&(hole->list), &hole_cache);
+			list_move(&(hole->list), &hole_cache);
 			dvma_entry_use(hole->start) = newlen;
 #ifdef DVMA_DEBUG
 			dvma_allocs++;
diff --git a/arch/m68k/sun3/sun3ints.c b/arch/m68k/sun3/sun3ints.c
index e62a033..0912435 100644
--- a/arch/m68k/sun3/sun3ints.c
+++ b/arch/m68k/sun3/sun3ints.c
@@ -19,7 +19,6 @@
 #include <linux/seq_file.h>
 
 extern void sun3_leds (unsigned char);
-static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp);
 
 void sun3_disable_interrupts(void)
 {
@@ -40,48 +39,30 @@
 
 volatile unsigned char* sun3_intreg;
 
-void sun3_insert_irq(irq_node_t **list, irq_node_t *node)
-{
-}
-
-void sun3_delete_irq(irq_node_t **list, void *dev_id)
-{
-}
-
 void sun3_enable_irq(unsigned int irq)
 {
-	*sun3_intreg |=  (1<<irq);
+	*sun3_intreg |=  (1 << irq);
 }
 
 void sun3_disable_irq(unsigned int irq)
 {
-	*sun3_intreg &= ~(1<<irq);
-}
-
-inline void sun3_do_irq(int irq, struct pt_regs *fp)
-{
-	kstat_cpu(0).irqs[SYS_IRQS + irq]++;
-	*sun3_intreg &= ~(1<<irq);
-	*sun3_intreg |=  (1<<irq);
+	*sun3_intreg &= ~(1 << irq);
 }
 
 static irqreturn_t sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
 {
-	sun3_do_irq(irq,fp);
-	if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 2000))
-		sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%16000)
-			  /2000]);
+	*sun3_intreg |=  (1 << irq);
+	if (!(kstat_cpu(0).irqs[irq] % 2000))
+		sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]);
 	return IRQ_HANDLED;
 }
 
 static irqreturn_t sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
 {
-        kstat_cpu(0).irqs[SYS_IRQS + irq]++;
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
-        *sun3_intreg &= ~(1<<irq);
-        *sun3_intreg |=  (1<<irq);
+        *sun3_intreg |=  (1 << irq);
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
@@ -89,65 +70,8 @@
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(fp));
 #endif
-        if(!(kstat_cpu(0).irqs[SYS_IRQS + irq] % 20))
-                sun3_leds(led_pattern[(kstat_cpu(0).irqs[SYS_IRQS+irq]%160)
-                /20]);
-	return IRQ_HANDLED;
-}
-
-/* handle requested ints, excepting 5 and 7, which always do the same
-   thing */
-irqreturn_t (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	[0] = sun3_inthandle,
-	[1] = sun3_inthandle,
-	[2] = sun3_inthandle,
-	[3] = sun3_inthandle,
-	[4] = sun3_inthandle,
-	[5] = sun3_int5,
-	[6] = sun3_inthandle,
-	[7] = sun3_int7
-};
-
-static const char *dev_names[SYS_IRQS] = {
-	[5] = "timer",
-	[7] = "int7 handler"
-};
-static void *dev_ids[SYS_IRQS];
-static irqreturn_t (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-	[5] = sun3_int5,
-	[7] = sun3_int7
-};
-static irqreturn_t (*sun3_vechandler[SUN3_INT_VECS])(int, void *, struct pt_regs *);
-static void *vec_ids[SUN3_INT_VECS];
-static const char *vec_names[SUN3_INT_VECS];
-static int vec_ints[SUN3_INT_VECS];
-
-
-int show_sun3_interrupts(struct seq_file *p, void *v)
-{
-	int i;
-
-	for(i = 0; i < (SUN3_INT_VECS-1); i++) {
-		if(sun3_vechandler[i] != NULL) {
-			seq_printf(p, "vec %3d: %10u %s\n", i+64,
-				   vec_ints[i],
-				   (vec_names[i]) ? vec_names[i] :
-				   "sun3_vechandler");
-		}
-	}
-
-	return 0;
-}
-
-static irqreturn_t sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
-{
-	if(sun3_inthandler[irq] == NULL)
-		panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
-
-        kstat_cpu(0).irqs[SYS_IRQS + irq]++;
-        *sun3_intreg &= ~(1<<irq);
-
-	sun3_inthandler[irq](irq, dev_ids[irq], fp);
+        if (!(kstat_cpu(0).irqs[irq] % 20))
+                sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
 	return IRQ_HANDLED;
 }
 
@@ -157,109 +81,31 @@
 	return IRQ_HANDLED;
 }
 
+static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
+{
+        *sun3_intreg &= ~(1 << irq);
+
+	m68k_handle_int(irq, fp);
+}
+
+static struct irq_controller sun3_irq_controller = {
+	.name		= "sun3",
+	.lock		= SPIN_LOCK_UNLOCKED,
+	.startup	= m68k_irq_startup,
+	.shutdown	= m68k_irq_shutdown,
+	.enable		= sun3_enable_irq,
+	.disable	= sun3_disable_irq,
+};
+
 void sun3_init_IRQ(void)
 {
-	int i;
-
 	*sun3_intreg = 1;
 
-	for(i = 0; i < SYS_IRQS; i++)
-	{
-		if(dev_names[i])
-			cpu_request_irq(i, sun3_default_handler[i], 0,
-					dev_names[i], NULL);
-	}
+	m68k_setup_auto_interrupt(sun3_inthandle);
+	m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
+	m68k_setup_user_interrupt(VEC_USER, 192, NULL);
 
-	for(i = 0; i < 192; i++)
-		sun3_vechandler[i] = NULL;
-
-	sun3_vechandler[191] = sun3_vec255;
-}
-
-int sun3_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                      unsigned long flags, const char *devname, void *dev_id)
-{
-
-	if(irq < SYS_IRQS) {
-		if(sun3_inthandler[irq] != NULL) {
-			printk("sun3_request_irq: request for irq %d -- already taken!\n", irq);
-			return 1;
-		}
-
-		sun3_inthandler[irq] = handler;
-		dev_ids[irq] = dev_id;
-		dev_names[irq] = devname;
-
-		/* setting devname would be nice */
-		cpu_request_irq(irq, sun3_default_handler[irq], 0, devname,
-				NULL);
-
-		return 0;
-	} else {
-		if((irq >= 64) && (irq <= 255)) {
-		        int vec;
-
-			vec = irq - 64;
-			if(sun3_vechandler[vec] != NULL) {
-				printk("sun3_request_irq: request for vec %d -- already taken!\n", irq);
-				return 1;
-			}
-
-			sun3_vechandler[vec] = handler;
-			vec_ids[vec] = dev_id;
-			vec_names[vec] = devname;
-			vec_ints[vec] = 0;
-
-			return 0;
-		}
-	}
-
-	printk("sun3_request_irq: invalid irq %d\n", irq);
-	return 1;
-
-}
-
-void sun3_free_irq(unsigned int irq, void *dev_id)
-{
-
-	if(irq < SYS_IRQS) {
-		if(sun3_inthandler[irq] == NULL)
-			panic("sun3_free_int: attempt to free unused irq %d\n", irq);
-		if(dev_ids[irq] != dev_id)
-			panic("sun3_free_int: incorrect dev_id for irq %d\n", irq);
-
-		sun3_inthandler[irq] = NULL;
-		return;
-	} else if((irq >= 64) && (irq <= 255)) {
-		int vec;
-
-		vec = irq - 64;
-		if(sun3_vechandler[vec] == NULL)
-			panic("sun3_free_int: attempt to free unused vector %d\n", irq);
-		if(vec_ids[irq] != dev_id)
-			panic("sun3_free_int: incorrect dev_id for vec %d\n", irq);
-
-		sun3_vechandler[vec] = NULL;
-		return;
-	} else {
-		panic("sun3_free_irq: invalid irq %d\n", irq);
-	}
-}
-
-irqreturn_t sun3_process_int(int irq, struct pt_regs *regs)
-{
-
-	if((irq >= 64) && (irq <= 255)) {
-		int vec;
-
-		vec = irq - 64;
-		if(sun3_vechandler[vec] == NULL)
-			panic ("bad interrupt vector %d received\n",irq);
-
-		vec_ints[vec]++;
-		return sun3_vechandler[vec](irq, vec_ids[vec], regs);
-	} else {
-		panic("sun3_process_int: unable to handle interrupt vector %d\n",
-		      irq);
-	}
+	request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
+	request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
+	request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL);
 }
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index 0920f5d..52fb174 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -52,17 +52,10 @@
 
 	sun3x_prom_init();
 
-	mach_get_irq_list	 = show_sun3_interrupts;
 	mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
 
-	mach_default_handler = &sun3_default_handler;
 	mach_sched_init      = sun3x_sched_init;
 	mach_init_IRQ        = sun3_init_IRQ;
-	enable_irq           = sun3_enable_irq;
-	disable_irq          = sun3_disable_irq;
-	mach_request_irq     = sun3_request_irq;
-	mach_free_irq        = sun3_free_irq;
-	mach_process_int     = sun3_process_int;
 
 	mach_gettimeoffset   = sun3x_gettimeoffset;
 	mach_reset           = sun3x_reboot;
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 3cde682..e767f2d 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -5,7 +5,7 @@
 
 mainmenu "uClinux/68k (w/o MMU) Kernel Configuration"
 
-config M68KNOMMU
+config M68K
 	bool
 	default y
 
@@ -119,6 +119,11 @@
 	help
 	  Motorola ColdFire 5307 processor support.
 
+config M532x
+	bool "MCF532x"
+	help
+	  Freescale (Motorola) ColdFire 532x processor support.
+
 config M5407
 	bool "MCF5407"
 	help
@@ -133,125 +138,43 @@
 
 config COLDFIRE
 	bool
-	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407)
+	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407)
 	default y
 
-choice
-	prompt "CPU CLOCK Frequency"
-	default AUTO
-
-config CLOCK_AUTO
-	bool "AUTO"
-	---help---
-	  Define the CPU clock frequency in use. On many boards you don't
-	  really need to know, so you can select the AUTO option. On some
-	  boards you need to know the real clock frequency to determine other
-	  system timing (for example baud rate dividors, etc). Some processors
-	  have an internal PLL and you can select a frequency to run at.
-	  You need to know a little about the internals of your processor to
-	  set this. If in doubt choose the AUTO option.
-
-config CLOCK_11MHz
-	bool "11MHz"
+config CLOCK_SET
+	bool "Enable setting the CPU clock frequency"
+	default n
 	help
-	  Select a 11MHz CPU clock frequency.
+	  On some CPU's you do not need to know what the core CPU clock
+	  frequency is. On these you can disable clock setting. On some
+	  traditional 68K parts, and on all ColdFire parts you need to set
+	  the appropriate CPU clock frequency. On these devices many of the
+	  onboard peripherals derive their timing from the master CPU clock
+	  frequency.
 
-config CLOCK_16MHz
-	bool "16MHz"
+config CLOCK_FREQ
+	int "Set the core clock frequency"
+	default "66666666"
+	depends on CLOCK_SET
 	help
-	  Select a 16MHz CPU clock frequency.
+	  Define the CPU clock frequency in use. This is the core clock
+	  frequency, it may or may not be the same as the external clock
+	  crystal fitted to your board. Some processors have an internal
+	  PLL and can have their frequency programmed at run time, others
+	  use internal dividers. In gernal the kernel won't setup a PLL
+	  if it is fitted (there are some expections). This value will be
+	  specific to the exact CPU that you are using.
 
-config CLOCK_20MHz
-	bool "20MHz"
+config CLOCK_DIV
+	int "Set the core/bus clock divide ratio"
+	default "1"
+	depends on CLOCK_SET
 	help
-	  Select a 20MHz CPU clock frequency.
-
-config CLOCK_24MHz
-	bool "24MHz"
-	help
-	  Select a 24MHz CPU clock frequency.
-
-config CLOCK_25MHz
-	bool "25MHz"
-	help
-	  Select a 25MHz CPU clock frequency.
-
-config CLOCK_33MHz
-	bool "33MHz"
-	help
-	  Select a 33MHz CPU clock frequency.
-
-config CLOCK_40MHz
-	bool "40MHz"
-	help
-	  Select a 40MHz CPU clock frequency.
-
-config CLOCK_45MHz
-	bool "45MHz"
-	help
-	  Select a 45MHz CPU clock frequency.
-
-config CLOCK_48MHz
-	bool "48MHz"
-	help
-	  Select a 48MHz CPU clock frequency.
-
-config CLOCK_50MHz
-	bool "50MHz"
-	help
-	  Select a 50MHz CPU clock frequency.
-
-config CLOCK_54MHz
-	bool "54MHz"
-	help
-	  Select a 54MHz CPU clock frequency.
-
-config CLOCK_60MHz
-	bool "60MHz"
-	help
-	  Select a 60MHz CPU clock frequency.
-
-config CLOCK_62_5MHz
-	bool "62.5MHz"
-	help
-	  Select a 62.5MHz CPU clock frequency.
-
-config CLOCK_64MHz
-	bool "64MHz"
-	help
-	  Select a 64MHz CPU clock frequency.
-
-config CLOCK_66MHz
-	bool "66MHz"
-	help
-	  Select a 66MHz CPU clock frequency.
-
-config CLOCK_70MHz
-	bool "70MHz"
-	help
-	  Select a 70MHz CPU clock frequency.
-
-config CLOCK_100MHz
-	bool "100MHz"
-	help
-	  Select a 100MHz CPU clock frequency.
-
-config CLOCK_140MHz
-	bool "140MHz"
-	help
-	  Select a 140MHz CPU clock frequency.
-
-config CLOCK_150MHz
-	bool "150MHz"
-	help
-	  Select a 150MHz CPU clock frequency.
-
-config CLOCK_166MHz
-	bool "166MHz"
-	help
-	  Select a 166MHz CPU clock frequency.
-
-endchoice
+	  On many SoC style CPUs the master CPU clock is also used to drive 
+	  on-chip peripherals. The clock that is distributed to these
+	  peripherals is sometimes a fixed ratio of the master clock
+	  frequency. If so then set this to the divider ration of the
+	  master clock to the peripheral clock. If not sure then select 1.
 
 config OLDMASK
 	bool "Old mask 5307 (1H55J) silicon"
@@ -377,6 +300,12 @@
 	help
 	  Support for the senTec COBRA5272 board.
 
+config AVNET5282
+	bool "Avnet 5282 board support"
+	depends on M528x
+	help
+	  Support for the Avnet 5282 board.  
+	  
 config M5282EVB
 	bool "Motorola M5282EVB board support"
 	depends on M528x
@@ -419,6 +348,18 @@
 	help
 	  Support for the SnapGear SecureEdge/MP3 platform.
 
+config M5329EVB
+	bool "Freescale (Motorola) M5329EVB board support"
+	depends on M532x
+	help
+	  Support for the Freescale (Motorola) M5329EVB board.
+
+config COBRA5329
+	bool "senTec COBRA5329 board support"
+	depends on M532x
+	help
+	  Support for the senTec COBRA5329 board.
+
 config M5407C3
 	bool "Motorola M5407C3 board support"
 	depends on M5407
@@ -487,7 +428,7 @@
 config FREESCALE
 	bool
 	default y
-	depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3)
+	depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5329EVB || M5407C3)
 
 config HW_FEITH
 	bool
@@ -508,6 +449,11 @@
         bool
 	default y
 	depends on CPU16B
+	
+config AVNET
+	bool
+	default y
+	depends on (AVNET5282)
 
 config LARGE_ALLOCS
 	bool "Allow allocating large blocks (> 1MB) of memory"
@@ -526,38 +472,46 @@
 	  running more threads on a system and also reduces the pressure
 	  on the VM subsystem for higher order allocations.
 
-choice
-	prompt "RAM size"
-	default AUTO
+comment "RAM configuration"
 
-config RAMAUTO
-	bool "AUTO"
-	---help---
-	  Configure the RAM size on your platform. Many platforms can auto
-	  detect this, on those choose the AUTO option. Otherwise set the
-	  RAM size you intend using.
-
-config RAM4MB
-	bool "4MiB"
+config RAMBASE
+	hex "Address of the base of RAM"
+	default "0"
 	help
-	  Set RAM size to be 4MiB.
+	  Define the address that RAM starts at. On many platforms this is
+	  0, the base of the address space. And this is the default. Some
+	  platforms choose to setup their RAM at other addresses within the
+	  processor address space.
 
-config RAM8MB
-	bool "8MiB"
+config RAMSIZE
+	hex "Size of RAM (in bytes)"
+	default "0x400000"
 	help
-	  Set RAM size to be 8MiB.
+	  Define the size of the system RAM. If you select 0 then the
+	  kernel will try to probe the RAM size at runtime. This is not
+	  supported on all CPU types.
 
-config RAM16MB
-	bool "16MiB"
+config VECTORBASE
+	hex "Address of the base of system vectors"
+	default "0"
 	help
-	  Set RAM size to be 16MiB.
+	  Define the address of the the system vectors. Commonly this is
+	  put at the start of RAM, but it doesn't have to be. On ColdFire
+	  platforms this address is programmed into the VBR register, thus
+	  actually setting the address to use.
 
-config RAM32MB
-	bool "32MiB"
+config KERNELBASE
+	hex "Address of the base of kernel code"
+	default "0x400"
 	help
-	  Set RAM size to be 32MiB.
-
-endchoice
+	  Typically on m68k systems the kernel will not start at the base
+	  of RAM, but usually some small offset from it. Define the start
+	  address of the kernel here. The most common setup will have the
+	  processor vectors at the base of RAM and then the start of the
+	  kernel. On some platforms some RAM is reserved for boot loaders
+	  and the kernel starts after that. The 0x400 default was based on
+	  a system with the RAM based at address 0, and leaving enough room
+	  for the theoretical maximum number of 256 vectors.
 
 choice
 	prompt "RAM bus width"
@@ -565,7 +519,7 @@
 
 config RAMAUTOBIT
 	bool "AUTO"
-	---help---
+	help
 	  Select the physical RAM data bus size. Not needed on most platforms,
 	  so you can generally choose AUTO.
 
@@ -586,6 +540,59 @@
 
 endchoice
 
+comment "ROM configuration"
+
+config ROM
+	bool "Specify ROM linker regions"
+	default n
+	help
+	  Define a ROM region for the linker script. This creates a kernel
+	  that can be stored in flash, with possibly the text, and data
+	  regions being copied out to RAM at startup.
+
+config ROMBASE
+	hex "Address of the base of ROM device"
+	default "0"
+	depends on ROM
+	help
+	  Define the address that the ROM region starts at. Some platforms
+	  use this to set their chip select region accordingly for the boot
+	  device.
+
+config ROMVEC
+	hex "Address of the base of the ROM vectors"
+	default "0"
+	depends on ROM
+	help
+	  This is almost always the same as the base of the ROM. Since on all
+	  68000 type varients the vectors are at the base of the boot device
+	  on system startup.
+
+config ROMVECSIZE
+	hex "Size of ROM vector region (in bytes)"
+	default "0x400"
+	depends on ROM
+	help
+	  Define the size of the vector region in ROM. For most 68000
+	  varients this would be 0x400 bytes in size. Set to 0 if you do
+	  not want a vector region at the start of the ROM.
+
+config ROMSTART
+	hex "Address of the base of system image in ROM"
+	default "0x400"
+	depends on ROM
+	help
+	  Define the start address of the system image in ROM. Commonly this
+	  is strait after the ROM vectors.
+
+config ROMSIZE
+	hex "Size of the ROM device"
+	default "0x100000"
+	depends on ROM
+	help
+	  Size of the ROM device. On some platforms this is used to setup
+	  the chip select that controls the boot ROM device.
+
 choice
 	prompt "Kernel executes from"
 	---help---
@@ -599,7 +606,9 @@
 config ROMKERNEL
 	bool "ROM"
 	help
-	  The kernel will be resident in FLASH/ROM when running.
+	  The kernel will be resident in FLASH/ROM when running. This is
+	  often referred to as Execute-in-Place (XIP), since the kernel
+	  code executes from the position it is stored in the FLASH/ROM.
 
 endchoice
 
diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
index 6f880cb..8951793 100644
--- a/arch/m68knommu/Makefile
+++ b/arch/m68knommu/Makefile
@@ -21,6 +21,7 @@
 platform-$(CONFIG_M5272)	:= 5272
 platform-$(CONFIG_M528x)	:= 528x
 platform-$(CONFIG_M5307)	:= 5307
+platform-$(CONFIG_M532x)	:= 532x
 platform-$(CONFIG_M5407)	:= 5407
 PLATFORM := $(platform-y)
 
@@ -44,6 +45,7 @@
 board-$(CONFIG_SNEHA) 	        := SNEHA
 board-$(CONFIG_M5208EVB)	:= M5208EVB
 board-$(CONFIG_MOD5272)		:= MOD5272
+board-$(CONFIG_AVNET)           := AVNET
 BOARD := $(board-y)
 
 model-$(CONFIG_RAMKERNEL)	:= ram
@@ -65,6 +67,7 @@
 cpuclass-$(CONFIG_M5272)	:= 5307
 cpuclass-$(CONFIG_M528x)	:= 5307
 cpuclass-$(CONFIG_M5307)	:= 5307
+cpuclass-$(CONFIG_M532x)	:= 5307
 cpuclass-$(CONFIG_M5407)	:= 5307
 cpuclass-$(CONFIG_M68328)	:= 68328
 cpuclass-$(CONFIG_M68EZ328)	:= 68328
@@ -81,16 +84,17 @@
 #
 # Some CFLAG additions based on specific CPU type.
 #
-cflags-$(CONFIG_M5206)		:= -m5200 -Wa,-S -Wa,-m5200
-cflags-$(CONFIG_M5206e)		:= -m5200 -Wa,-S -Wa,-m5200
-cflags-$(CONFIG_M520x)		:= -m5307 -Wa,-S -Wa,-m5307
-cflags-$(CONFIG_M523x)		:= -m5307 -Wa,-S -Wa,-m5307
-cflags-$(CONFIG_M5249)		:= -m5200 -Wa,-S -Wa,-m5200
-cflags-$(CONFIG_M527x)		:= -m5307 -Wa,-S -Wa,-m5307
-cflags-$(CONFIG_M5272)		:= -m5307 -Wa,-S -Wa,-m5307
-cflags-$(CONFIG_M528x)		:= -m5307 -Wa,-S -Wa,-m5307
-cflags-$(CONFIG_M5307)		:= -m5307 -Wa,-S -Wa,-m5307
-cflags-$(CONFIG_M5407)		:= -m5200 -Wa,-S -Wa,-m5200
+cflags-$(CONFIG_M5206)		:= -m5200
+cflags-$(CONFIG_M5206e)		:= -m5200
+cflags-$(CONFIG_M520x)		:= -m5307
+cflags-$(CONFIG_M523x)		:= -m5307
+cflags-$(CONFIG_M5249)		:= -m5200
+cflags-$(CONFIG_M527x)		:= -m5307
+cflags-$(CONFIG_M5272)		:= -m5307
+cflags-$(CONFIG_M528x)		:= -m5307
+cflags-$(CONFIG_M5307)		:= -m5307
+cflags-$(CONFIG_M532x)		:= -m5307
+cflags-$(CONFIG_M5407)		:= -m5200
 cflags-$(CONFIG_M68328)		:= -m68000
 cflags-$(CONFIG_M68EZ328)	:= -m68000
 cflags-$(CONFIG_M68VZ328)	:= -m68000
diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
index 2d59ba1..3891de0 100644
--- a/arch/m68knommu/defconfig
+++ b/arch/m68knommu/defconfig
@@ -1,21 +1,22 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.13-uc0
-# Wed Aug 31 15:03:26 2005
+# Linux kernel version: 2.6.17
+# Tue Jun 27 12:57:06 2006
 #
-CONFIG_M68KNOMMU=y
+CONFIG_M68K=y
 # CONFIG_MMU is not set
 # CONFIG_FPU is not set
-CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_TIME_LOW_RES=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
@@ -23,26 +24,30 @@
 # General setup
 #
 CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_SYSCTL is not set
 # CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_KOBJECT_UEVENT is not set
 # CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
+CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
 CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -50,6 +55,24 @@
 # CONFIG_MODULES is not set
 
 #
+# Block layer
+#
+# CONFIG_BLK_DEV_IO_TRACE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+
+#
 # Processor type and features
 #
 # CONFIG_M68328 is not set
@@ -58,6 +81,7 @@
 # CONFIG_M68360 is not set
 # CONFIG_M5206 is not set
 # CONFIG_M5206e is not set
+# CONFIG_M520x is not set
 # CONFIG_M523x is not set
 # CONFIG_M5249 is not set
 # CONFIG_M5271 is not set
@@ -65,29 +89,12 @@
 # CONFIG_M5275 is not set
 # CONFIG_M528x is not set
 # CONFIG_M5307 is not set
+# CONFIG_M532x is not set
 # CONFIG_M5407 is not set
 CONFIG_COLDFIRE=y
-# CONFIG_CLOCK_AUTO is not set
-# CONFIG_CLOCK_11MHz is not set
-# CONFIG_CLOCK_16MHz is not set
-# CONFIG_CLOCK_20MHz is not set
-# CONFIG_CLOCK_24MHz is not set
-# CONFIG_CLOCK_25MHz is not set
-# CONFIG_CLOCK_33MHz is not set
-# CONFIG_CLOCK_40MHz is not set
-# CONFIG_CLOCK_45MHz is not set
-# CONFIG_CLOCK_48MHz is not set
-# CONFIG_CLOCK_50MHz is not set
-# CONFIG_CLOCK_54MHz is not set
-# CONFIG_CLOCK_60MHz is not set
-# CONFIG_CLOCK_62_5MHz is not set
-# CONFIG_CLOCK_64MHz is not set
-CONFIG_CLOCK_66MHz=y
-# CONFIG_CLOCK_70MHz is not set
-# CONFIG_CLOCK_100MHz is not set
-# CONFIG_CLOCK_140MHz is not set
-# CONFIG_CLOCK_150MHz is not set
-# CONFIG_CLOCK_166MHz is not set
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=66666666
+CONFIG_CLOCK_DIV=1
 
 #
 # Platform
@@ -102,11 +109,14 @@
 CONFIG_FREESCALE=y
 # CONFIG_LARGE_ALLOCS is not set
 CONFIG_4KSTACKS=y
-CONFIG_RAMAUTO=y
-# CONFIG_RAM4MB is not set
-# CONFIG_RAM8MB is not set
-# CONFIG_RAM16MB is not set
-# CONFIG_RAM32MB is not set
+
+#
+# RAM configuration
+#
+CONFIG_RAMBASE=0x0
+CONFIG_RAMSIZE=0x800000
+CONFIG_VECTORBASE=0x0
+CONFIG_KERNELBASE=0x20000
 CONFIG_RAMAUTOBIT=y
 # CONFIG_RAM8BIT is not set
 # CONFIG_RAM16BIT is not set
@@ -119,6 +129,8 @@
 # CONFIG_SPARSEMEM_MANUAL is not set
 CONFIG_FLATMEM=y
 CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -140,6 +152,7 @@
 CONFIG_BINFMT_FLAT=y
 # CONFIG_BINFMT_ZFLAT is not set
 # CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_AOUT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
@@ -155,6 +168,7 @@
 #
 # Networking options
 #
+# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -171,18 +185,30 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
-# CONFIG_IP_TCPDIAG is not set
-# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_INET_DIAG is not set
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 # CONFIG_NETFILTER is not set
 
 #
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
 # SCTP Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
@@ -195,8 +221,11 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -205,6 +234,7 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -218,6 +248,11 @@
 # CONFIG_FW_LOADER is not set
 
 #
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
 # Memory Technology Devices (MTD)
 #
 CONFIG_MTD=y
@@ -235,6 +270,7 @@
 # CONFIG_FTL is not set
 # CONFIG_NFTL is not set
 # CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
 
 #
 # RAM/ROM/Flash chip drivers
@@ -254,13 +290,13 @@
 CONFIG_MTD_RAM=y
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 CONFIG_MTD_UCLINUX=y
-# CONFIG_MTD_SNAPGEARuC is not set
 # CONFIG_MTD_PLATRAM is not set
 
 #
@@ -269,7 +305,6 @@
 # CONFIG_MTD_SLRAM is not set
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLKMTD is not set
 # CONFIG_MTD_BLOCK2MTD is not set
 
 #
@@ -285,6 +320,11 @@
 # CONFIG_MTD_NAND is not set
 
 #
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
 # Parallel port support
 #
 # CONFIG_PARPORT is not set
@@ -296,7 +336,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -304,16 +343,7 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CDROM_PKTCDVD is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
 # CONFIG_ATA_OVER_ETH is not set
 
 #
@@ -324,6 +354,7 @@
 #
 # SCSI device support
 #
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -354,13 +385,15 @@
 # CONFIG_TUN is not set
 
 #
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NE2000 is not set
-# CONFIG_NET_PCI is not set
 CONFIG_FEC=y
 # CONFIG_FEC2 is not set
 
@@ -392,6 +425,7 @@
 # CONFIG_PPP_SYNC_TTY is not set
 # CONFIG_PPP_DEFLATE is not set
 # CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
 # CONFIG_PPPOE is not set
 # CONFIG_SLIP is not set
 # CONFIG_SHAPER is not set
@@ -425,8 +459,6 @@
 #
 # CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_LEDMAN is not set
-# CONFIG_RESETSWITCH is not set
 
 #
 # Serial drivers
@@ -450,8 +482,6 @@
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_MCFWATCHDOG is not set
-# CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -464,14 +494,19 @@
 #
 # TPM devices
 #
-# CONFIG_MCF_QSPI is not set
-# CONFIG_M41T11M6 is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
 
 #
 # I2C support
 #
 # CONFIG_I2C is not set
-# CONFIG_I2C_SENSOR is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
 
 #
 # Dallas's 1-wire bus
@@ -482,6 +517,7 @@
 # Hardware Monitoring support
 #
 # CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
 
 #
 # Misc devices
@@ -491,6 +527,7 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -503,11 +540,6 @@
 # CONFIG_FB is not set
 
 #
-# SPI support
-#
-# CONFIG_SPI is not set
-
-#
 # Sound
 #
 # CONFIG_SOUND is not set
@@ -517,6 +549,11 @@
 #
 # CONFIG_USB_ARCH_HAS_HCD is not set
 # CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
 
 #
 # USB Gadget Support
@@ -529,29 +566,43 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
 # CONFIG_EXT2_FS_XIP is not set
 # CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 # CONFIG_FS_POSIX_ACL is not set
-
-#
-# XFS support
-#
 # CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
 # CONFIG_INOTIFY is not set
@@ -559,6 +610,7 @@
 # CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -581,6 +633,7 @@
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -611,6 +664,7 @@
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -627,8 +681,12 @@
 # Kernel hacking
 #
 # CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_UNWIND_INFO is not set
 # CONFIG_FULLDEBUG is not set
 # CONFIG_HIGHPROFILE is not set
 # CONFIG_BOOTPARAM is not set
@@ -655,5 +713,6 @@
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
 # CONFIG_CRC32 is not set
 # CONFIG_LIBCRC32C is not set
diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
index 93120b9..99d038e 100644
--- a/arch/m68knommu/kernel/setup.c
+++ b/arch/m68knommu/kernel/setup.c
@@ -42,7 +42,6 @@
 #include <asm/pgtable.h>
 #endif
 
-unsigned long rom_length;
 unsigned long memory_start;
 unsigned long memory_end;
 
@@ -56,29 +55,29 @@
 {
 }
 
-void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *)) = NULL;
-void (*mach_tick)( void ) = NULL;
+void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *));
+void (*mach_tick)( void );
 /* machine dependent keyboard functions */
-int (*mach_keyb_init) (void) = NULL;
-int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
-void (*mach_kbd_leds) (unsigned int) = NULL;
+int (*mach_keyb_init) (void);
+int (*mach_kbdrate) (struct kbd_repeat *);
+void (*mach_kbd_leds) (unsigned int);
 /* machine dependent irq functions */
-void (*mach_init_IRQ) (void) = NULL;
-irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
-int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
-void (*mach_process_int) (int irq, struct pt_regs *fp) = NULL;
+void (*mach_init_IRQ) (void);
+irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
+int (*mach_get_irq_list) (struct seq_file *, void *);
+void (*mach_process_int) (int irq, struct pt_regs *fp);
 void (*mach_trap_init) (void);
 /* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void) = NULL;
-void (*mach_gettod) (int*, int*, int*, int*, int*, int*) = NULL;
-int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
-int (*mach_set_clock_mmss) (unsigned long) = NULL;
-void (*mach_mksound)( unsigned int count, unsigned int ticks ) = NULL;
-void (*mach_reset)( void ) = NULL;
+unsigned long (*mach_gettimeoffset) (void);
+void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
+int (*mach_hwclk) (int, struct hwclk_time*);
+int (*mach_set_clock_mmss) (unsigned long);
+void (*mach_mksound)( unsigned int count, unsigned int ticks );
+void (*mach_reset)( void );
 void (*waitbut)(void) = dummy_waitbut;
-void (*mach_debug_init)(void) = NULL;
-void (*mach_halt)( void ) = NULL;
-void (*mach_power_off)( void ) = NULL;
+void (*mach_debug_init)(void);
+void (*mach_halt)( void );
+void (*mach_power_off)( void );
 
 
 #ifdef CONFIG_M68000
@@ -129,6 +128,9 @@
 #if defined(CONFIG_M5307)
 	#define	CPU "COLDFIRE(m5307)"
 #endif
+#if defined(CONFIG_M532x)
+	#define	CPU "COLDFIRE(m532x)"
+#endif
 #if defined(CONFIG_M5407)
 	#define	CPU "COLDFIRE(m5407)"
 #endif
@@ -267,34 +269,6 @@
 	paging_init();
 }
 
-int get_cpuinfo(char * buffer)
-{
-    char *cpu, *mmu, *fpu;
-    u_long clockfreq;
-
-    cpu = CPU;
-    mmu = "none";
-    fpu = "none";
-
-#ifdef CONFIG_COLDFIRE
-    clockfreq = (loops_per_jiffy*HZ)*3;
-#else
-    clockfreq = (loops_per_jiffy*HZ)*16;
-#endif
-
-    return(sprintf(buffer, "CPU:\t\t%s\n"
-		   "MMU:\t\t%s\n"
-		   "FPU:\t\t%s\n"
-		   "Clocking:\t%lu.%1luMHz\n"
-		   "BogoMips:\t%lu.%02lu\n"
-		   "Calibration:\t%lu loops\n",
-		   cpu, mmu, fpu,
-		   clockfreq/1000000,(clockfreq/100000)%10,
-		   (loops_per_jiffy*HZ)/500000,((loops_per_jiffy*HZ)/5000)%100,
-		   (loops_per_jiffy*HZ)));
-
-}
-
 /*
  *	Get CPU information for use by the procfs.
  */
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index e1b3aa3..437f8c6 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -553,7 +553,7 @@
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(usp))
+		if (!sas_ss_flags(usp))
 			usp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	return (void *)((usp - frame_size) & -8UL);
@@ -608,7 +608,7 @@
 	if (regs->stkadj) {
 		struct pt_regs *tregs =
 			(struct pt_regs *)((ulong)regs + regs->stkadj);
-#if DEBUG
+#if defined(DEBUG)
 		printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
 #endif
 		/* This must be copied with decreasing addresses to
@@ -678,7 +678,7 @@
 	if (regs->stkadj) {
 		struct pt_regs *tregs =
 			(struct pt_regs *)((ulong)regs + regs->stkadj);
-#if DEBUG
+#if defined(DEBUG)
 		printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
 #endif
 		/* This must be copied with decreasing addresses to
diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c
index 5bc0684..44ff74e 100644
--- a/arch/m68knommu/kernel/traps.c
+++ b/arch/m68knommu/kernel/traps.c
@@ -93,12 +93,12 @@
 	if (user_mode(&fp->ptregs))
 		current->thread.esp0 = (unsigned long) fp;
 
-#if DEBUG
+#if defined(DEBUG)
 	printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
 #endif
 
 	die_if_kernel("bad frame format",&fp->ptregs,0);
-#if DEBUG
+#if defined(DEBUG)
 	printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
 #endif
 	force_sig(SIGSEGV, current);
diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S
index a331cc90..59ced83 100644
--- a/arch/m68knommu/kernel/vmlinux.lds.S
+++ b/arch/m68knommu/kernel/vmlinux.lds.S
@@ -1,205 +1,30 @@
 /*
  *	vmlinux.lds.S -- master linker script for m68knommu arch
  *
- *	(C) Copyright 2002-2004, Greg Ungerer <gerg@snapgear.com>
+ *	(C) Copyright 2002-2006, Greg Ungerer <gerg@snapgear.com>
  *
- *	This ends up looking compilcated, because of the number of
- *	address variations for ram and rom/flash layouts. The real
- *	work of the linker script is all at the end, and reasonably
- *	strait forward.
+ *	This linker script is equiped to build either ROM loaded or RAM
+ *	run kernels.
  */
 
 #include <linux/config.h>
 #include <asm-generic/vmlinux.lds.h>
 
-/*
- *	Original Palm pilot (same for Xcopilot).
- *	There is really only a rom target for this.
- */
-#ifdef CONFIG_PILOT3
-#define	ROMVEC_START	0x10c00000
-#define	ROMVEC_LENGTH	0x10400
-#define	ROM_START	0x10c10400
-#define	ROM_LENGTH	0xfec00
-#define	ROM_END		0x10d00000
-#define	RAMVEC_START	0x00000000
-#define	RAMVEC_LENGTH	0x400
-#define	RAM_START	0x10000400
-#define	RAM_LENGTH	0xffc00
-#define	RAM_END		0x10100000
-#define _ramend	_ram_end_notused
-#define	DATA_ADDR	RAM_START
-#endif
-
-/*
- *	Same setup on both the uCsimm and uCdimm.
- */
-#if defined(CONFIG_UCSIMM) || defined(CONFIG_UCDIMM)
-#ifdef CONFIG_RAMKERNEL
-#define	ROMVEC_START	0x10c10000
-#define	ROMVEC_LENGTH	0x400
-#define	ROM_START	0x10c10400
-#define	ROM_LENGTH	0x1efc00
-#define	ROM_END		0x10e00000
-#define	RAMVEC_START	0x00000000
-#define	RAMVEC_LENGTH	0x400
-#define	RAM_START	0x00020400
-#define	RAM_LENGTH	0x7dfc00
-#define	RAM_END		0x00800000
-#endif
-#ifdef CONFIG_ROMKERNEL
-#define	ROMVEC_START	0x10c10000
-#define	ROMVEC_LENGTH	0x400
-#define	ROM_START	0x10c10400
-#define	ROM_LENGTH	0x1efc00
-#define	ROM_END		0x10e00000
-#define	RAMVEC_START	0x00000000
-#define	RAMVEC_LENGTH	0x400
-#define	RAM_START	0x00020000
-#define	RAM_LENGTH	0x600000
-#define	RAM_END		0x00800000
-#endif
-#ifdef CONFIG_HIMEMKERNEL
-#define	ROMVEC_START	0x00600000
-#define	ROMVEC_LENGTH	0x400
-#define	ROM_START	0x00600400
-#define	ROM_LENGTH	0x1efc00
-#define	ROM_END		0x007f0000
-#define	RAMVEC_START	0x00000000
-#define	RAMVEC_LENGTH	0x400
-#define	RAM_START	0x00020000
-#define	RAM_LENGTH	0x5e0000
-#define	RAM_END		0x00600000
-#endif
-#endif
-
-#ifdef CONFIG_DRAGEN2
-#define	RAM_START	0x10000
-#define	RAM_LENGTH	0x7f0000
-#endif
-
-#ifdef CONFIG_UCQUICC
-#define	ROMVEC_START	0x00000000
-#define	ROMVEC_LENGTH	0x404
-#define	ROM_START	0x00000404
-#define	ROM_LENGTH	0x1ff6fc
-#define	ROM_END		0x00200000
-#define	RAMVEC_START	0x00200000
-#define	RAMVEC_LENGTH	0x404
-#define	RAM_START	0x00200404
-#define	RAM_LENGTH	0x1ff6fc
-#define	RAM_END		0x00400000
-#endif
-
-/*
- *	The standard Arnewsh 5206 board only has 1MiB of ram. Not normally
- *	enough to be useful. Assume the user has fitted something larger,
- *	at least 4MiB in size. No point in not letting the kernel completely
- *	link, it will be obvious if it is too big when they go to load it.
- */
-#if defined(CONFIG_ARN5206)
-#define	RAM_START	0x10000
-#define	RAM_LENGTH	0x3f0000
-#endif
-
-/*
- *	The Motorola 5206eLITE board only has 1MiB of static RAM.
- */
-#if defined(CONFIG_ELITE)
-#define	RAM_START	0x30020000
-#define	RAM_LENGTH	0xe0000
-#endif
-
-/*
- *	All the Motorola eval boards have the same basic arrangement.
- *	The end of RAM will vary depending on how much ram is fitted,
- *	but this isn't important here, we assume at least 4MiB.
- */
-#if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \
-    defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \
-    defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \
-    defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) || \
-    defined(CONFIG_M5235EVB)
-#define	RAM_START	0x20000
-#define	RAM_LENGTH	0x3e0000
-#endif
-
-/*
- *	The Freescale 5208EVB board has 32MB of RAM.
- */
-#if defined(CONFIG_M5208EVB)
-#define	RAM_START	0x40020000
-#define	RAM_LENGTH	0x01fe0000
-#endif
-
-/*
- *	The senTec COBRA5272 board has nearly the same memory layout as 
- *	the M5272C3. We assume 16MiB ram.
- */
-#if defined(CONFIG_COBRA5272)
-#define RAM_START   0x20000
-#define RAM_LENGTH  0xfe0000
-#endif
-
-#if defined(CONFIG_M5282EVB)
-#define	RAM_START	0x10000
-#define	RAM_LENGTH	0x3f0000
-#endif
-
-/*
- *	The senTec COBRA5282 board has the same memory layout as the M5282EVB.
- */
-#if defined(CONFIG_COBRA5282)
-#define  RAM_START   0x10000
-#define  RAM_LENGTH  0x3f0000
-#endif
-
-
-/*
- *	The EMAC SoM-5282EM module.
- */
-#if defined(CONFIG_SOM5282EM)
-#define  RAM_START   0x10000
-#define  RAM_LENGTH  0xff0000
-#endif
-
-
-/*
- *	These flash boot boards use all of ram for operation. Again the
- *	actual memory size is not important here, assume at least 4MiB.
- *	They currently have no support for running in flash.
- */
-#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \
-    defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \
-    defined(CONFIG_HW_FEITH)
-#define	RAM_START	0x400
-#define	RAM_LENGTH	0x3ffc00
-#endif
-
-/*
- *	Sneha Boards mimimun memory
- *	The end of RAM will vary depending on how much ram is fitted,
- *	but this isn't important here, we assume at least 4MiB.
- */
-#if defined(CONFIG_CPU16B)   
-#define	RAM_START	0x20000
-#define	RAM_LENGTH	0x3e0000
-#endif
-
-#if defined(CONFIG_MOD5272)
-#define RAM_START	0x02000000
-#define RAM_LENGTH	0x00800000
-#define RAMVEC_START	0x20000000
-#define RAMVEC_LENGTH	0x00000400
-#endif
-
 #if defined(CONFIG_RAMKERNEL)
+#define	RAM_START	CONFIG_KERNELBASE
+#define	RAM_LENGTH	(CONFIG_RAMBASE + CONFIG_RAMSIZE - CONFIG_KERNELBASE)
 #define	TEXT		ram
 #define	DATA		ram
 #define	INIT		ram
 #define	BSS		ram
 #endif
 #if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL)
+#define	RAM_START	CONFIG_RAMBASE
+#define	RAM_LENGTH	CONFIG_RAMSIZE
+#define	ROMVEC_START	CONFIG_ROMVEC
+#define	ROMVEC_LENGTH	CONFIG_ROMVECSIZE
+#define	ROM_START	CONFIG_ROMSTART
+#define	ROM_LENGTH	CONFIG_ROMSIZE
 #define	TEXT		rom
 #define	DATA		ram
 #define	INIT		ram
@@ -215,17 +40,10 @@
 ENTRY(_start)
 
 MEMORY {
-#ifdef RAMVEC_START
-	ramvec	: ORIGIN = RAMVEC_START, LENGTH = RAMVEC_LENGTH
-#endif
 	ram	: ORIGIN = RAM_START, LENGTH = RAM_LENGTH
-#ifdef RAM_END
-	eram	: ORIGIN = RAM_END, LENGTH = 0
-#endif
 #ifdef ROM_START
 	romvec	: ORIGIN = ROMVEC_START, LENGTH = ROMVEC_LENGTH
 	rom	: ORIGIN = ROM_START, LENGTH = ROM_LENGTH
-	erom	: ORIGIN = ROM_END, LENGTH = 0
 #endif
 }
 
@@ -302,19 +120,6 @@
 		_etext = . ;
 	} > TEXT
 
-#ifdef ROM_END
-	. = ROM_END ;
-	.erom : {
-		__rom_end = . ;
-	} > erom
-#endif
-#ifdef RAMVEC_START
-	. = RAMVEC_START ;
-	.ramvec : {
-		__ramvec = .;
-	} > ramvec
-#endif
-
 	.data DATA_ADDR : {
 		. = ALIGN(4);
 		_sdata = . ;
@@ -373,12 +178,5 @@
 		_ebss = . ;
 	} > BSS
 
-#ifdef RAM_END
-	. = RAM_END ;
-	.eram : {
-		__ramend = . ;
-		_ramend = . ;
-	} > eram
-#endif
 }
 
diff --git a/arch/m68knommu/mm/init.c b/arch/m68knommu/mm/init.c
index d79503f..70d1653 100644
--- a/arch/m68knommu/mm/init.c
+++ b/arch/m68knommu/mm/init.c
@@ -63,8 +63,6 @@
 
 unsigned long empty_zero_page;
 
-extern unsigned long rom_length;
-
 void show_mem(void)
 {
     unsigned long i;
@@ -178,11 +176,9 @@
 	initk = (&__init_begin - &__init_end) >> 10;
 
 	tmp = nr_free_pages() << PAGE_SHIFT;
-	printk(KERN_INFO "Memory available: %luk/%luk RAM, %luk/%luk ROM (%dk kernel code, %dk data)\n",
+	printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
 	       tmp >> 10,
 	       len >> 10,
-	       (rom_length > 0) ? ((rom_length >> 10) - codek) : 0,
-	       rom_length >> 10,
 	       codek,
 	       datak
 	       );
diff --git a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile
index 8d1619d..2fd37dcc 100644
--- a/arch/m68knommu/platform/5307/Makefile
+++ b/arch/m68knommu/platform/5307/Makefile
@@ -25,6 +25,7 @@
 obj-$(CONFIG_M527x)     += pit.o
 obj-$(CONFIG_M5272)	+= timers.o
 obj-$(CONFIG_M5307)	+= config.o timers.o
+obj-$(CONFIG_M532x)	+= timers.o
 obj-$(CONFIG_M528x)     += pit.o
 obj-$(CONFIG_M5407)	+= timers.o
 
diff --git a/arch/m68knommu/platform/5307/entry.S b/arch/m68knommu/platform/5307/entry.S
index 89b180d..9ddf547 100644
--- a/arch/m68knommu/platform/5307/entry.S
+++ b/arch/m68knommu/platform/5307/entry.S
@@ -4,8 +4,8 @@
  *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
  *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
  *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 2000  Lineo Inc. (www.lineo.com) 
- *  Copyright (C) 2004  Macq Electronique SA. (www.macqel.com)
+ *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)
+ *  Copyright (C) 2004-2006  Macq Electronique SA. (www.macqel.com)
  *
  * Based on:
  *
@@ -56,32 +56,27 @@
 .globl inthandler
 .globl fasthandler
 
+enosys:
+	mov.l	#sys_ni_syscall,%d3
+	bra	1f
+
 ENTRY(system_call)
 	SAVE_ALL
 	move	#0x2000,%sr		/* enable intrs again */
 
-	movel	#-LENOSYS,%d2
-	movel	%d2,PT_D0(%sp)		/* default return value in d0 */
-					/* original D0 is in orig_d0 */
-	movel	%d0,%d2
-
-	/* save top of frame */
-	pea	%sp@
-	jbsr	set_esp0
-	addql	#4,%sp
-
-	cmpl	#NR_syscalls,%d2
-	jcc	ret_from_exception
+	cmpl	#NR_syscalls,%d0
+	jcc	enosys
 	lea	sys_call_table,%a0
-	lsll	#2,%d2			/* movel %a0@(%d2:l:4),%d3 */
-	movel	%a0@(%d2),%d3
-	jeq	ret_from_exception
-	lsrl	#2,%d2
+	lsll	#2,%d0			/* movel %a0@(%d0:l:4),%d3 */
+	movel	%a0@(%d0),%d3
+	jeq	enosys
 
+1:
 	movel	%sp,%d2			/* get thread_info pointer */
 	andl	#-THREAD_SIZE,%d2	/* at start of kernel stack */
 	movel	%d2,%a0
-	btst	#TIF_SYSCALL_TRACE,%a0@(TI_FLAGS)
+	movel	%sp,%a0@(THREAD_ESP0)	/* save top of frame */
+	btst	#(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
 	bnes	1f
 
 	movel	%d3,%a0
@@ -126,8 +121,8 @@
 	jne	Lwork_to_do		/* still work to do */
 
 Lreturn:
-	move    #0x2700,%sr		/* disable intrs */
-	movel   sw_usp,%a0		/* get usp */
+	move	#0x2700,%sr		/* disable intrs */
+	movel	sw_usp,%a0		/* get usp */
 	movel	%sp@(PT_PC),%a0@-	/* copy exception program counter */
 	movel	%sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */
 	moveml	%sp@,%d1-%d5/%a0-%a2
@@ -170,7 +165,7 @@
 	movel	%d0,%sp@(PT_ORIG_D0)
 	addql	#1,local_irq_count
 
-	movew   %sp@(PT_FORMATVEC),%d0	/* put exception # in d0 */
+	movew	%sp@(PT_FORMATVEC),%d0	/* put exception # in d0 */
 	andl	#0x03fc,%d0		/* mask out vector only */
 
 	leal	per_cpu__kstat+STAT_IRQ,%a0
@@ -184,7 +179,7 @@
 
 	movel	%sp,%sp@-		/* push regs arg onto stack */
 	movel	%a0@(8),%sp@-		/* push devid arg */
-	movel	%d0,%sp@- 		/* push vector # on stack */
+	movel	%d0,%sp@-		/* push vector # on stack */
 
 	movel	%a0@,%a0		/* get function to call */
 	jbsr	%a0@			/* call vector handler */
@@ -201,7 +196,7 @@
 ENTRY(fasthandler)
 	SAVE_LOCAL
 
-	movew   %sp@(PT_FORMATVEC),%d0
+	movew	%sp@(PT_FORMATVEC),%d0
 	andl	#0x03fc,%d0		/* mask out vector only */
 
 	leal	per_cpu__kstat+STAT_IRQ,%a0
@@ -210,7 +205,7 @@
 	movel	%sp,%sp@-		/* push regs arg onto stack */
 	clrl	%sp@-			/* push devid arg */
 	lsrl	#2,%d0			/* calculate real vector # */
-	movel	%d0,%sp@- 		/* push vector # on stack */
+	movel	%d0,%sp@-		/* push vector # on stack */
 
 	lsll	#4,%d0			/* adjust for array offset */
 	lea	irq_list,%a0
@@ -265,4 +260,3 @@
 	movew	%a1@(TASK_THREAD+THREAD_SR),%d0	/* restore thread status reg */
 	movew	%d0, %sr
 	rts
-
diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S
index c30c462..1d9eb30 100644
--- a/arch/m68knommu/platform/5307/head.S
+++ b/arch/m68knommu/platform/5307/head.S
@@ -3,7 +3,7 @@
 /*
  *	head.S -- common startup code for ColdFire CPUs.
  *
- *	(C) Copyright 1999-2004, Greg Ungerer (gerg@snapgear.com).
+ *	(C) Copyright 1999-2006, Greg Ungerer <gerg@snapgear.com>.
  */
 
 /*****************************************************************************/
@@ -19,47 +19,15 @@
 /*****************************************************************************/
 
 /*
- *	Define fixed memory sizes. Configuration of a fixed memory size
- *	overrides everything else. If the user defined a size we just
- *	blindly use it (they know what they are doing right :-)
- */
-#if defined(CONFIG_RAM32MB)
-#define MEM_SIZE	0x02000000	/* memory size 32Mb */
-#elif defined(CONFIG_RAM16MB)
-#define MEM_SIZE	0x01000000	/* memory size 16Mb */
-#elif defined(CONFIG_RAM8MB)
-#define MEM_SIZE	0x00800000	/* memory size 8Mb */
-#elif defined(CONFIG_RAM4MB)
-#define MEM_SIZE	0x00400000	/* memory size 4Mb */
-#elif defined(CONFIG_RAM1MB)
-#define MEM_SIZE	0x00100000	/* memory size 1Mb */
-#endif
-
-/*
- *	Memory size exceptions for special cases. Some boards may be set
- *	for auto memory sizing, but we can't do it that way for some reason.
- *	For example the 5206eLITE board has static RAM, and auto-detecting
- *	the SDRAM will do you no good at all. Same goes for the MOD5272.
- */
-#ifdef CONFIG_RAMAUTO
-#if defined(CONFIG_M5206eLITE)
-#define	MEM_SIZE	0x00100000	/* 1MiB default memory */
-#endif
-#if defined(CONFIG_MOD5272)
-#define MEM_SIZE	0x00800000	/* 8MiB default memory */
-#endif
-#endif /* CONFIG_RAMAUTO */
-
-
-/*
- *	If we don't have a fixed memory size now, then lets build in code
+ *	If we don't have a fixed memory size, then lets build in code
  *	to auto detect the DRAM size. Obviously this is the prefered
- *	method, and should work for most boards (it won't work for those
- *	that do not have their RAM starting at address 0).
+ *	method, and should work for most boards. It won't work for those
+ *	that do not have their RAM starting at address 0, and it only
+ *	works on SDRAM (not boards fitted with SRAM).
  */
-#if defined(MEM_SIZE)
+#if CONFIG_RAMSIZE != 0
 .macro GET_MEM_SIZE
-	movel	#MEM_SIZE,%d0		/* hard coded memory size */
+	movel	#CONFIG_RAMSIZE,%d0	/* hard coded memory size */
 .endm
 
 #elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
@@ -98,37 +66,7 @@
 .endm
 
 #else
-#error "ERROR: I don't know how to determine your boards memory size?"
-#endif
-
-
-/*
- *	Most ColdFire boards have their DRAM starting at address 0.
- *	Notable exception is the 5206eLITE board, another is the MOD5272.
- */
-#if defined(CONFIG_M5206eLITE)
-#define	MEM_BASE	0x30000000
-#endif
-#if defined(CONFIG_MOD5272)
-#define MEM_BASE	0x02000000
-#define VBR_BASE	0x20000000	/* vectors in SRAM */
-#endif
-#if defined(CONFIG_M5208EVB)
-#define MEM_BASE	0x40000000
-#endif
-
-#ifndef MEM_BASE
-#define	MEM_BASE	0x00000000	/* memory base at address 0 */
-#endif
-
-/*
- *	The default location for the vectors is at the base of RAM.
- *	Some boards might like to use internal SRAM or something like
- *	that. If no board specific header defines an alternative then
- *	use the base of RAM.
- */
-#ifndef	VBR_BASE
-#define	VBR_BASE	MEM_BASE	/* vector address */
+#error "ERROR: I don't know how to probe your boards memory size?"
 #endif
 
 /*****************************************************************************/
@@ -191,11 +129,11 @@
 	 *	Create basic memory configuration. Set VBR accordingly,
 	 *	and size memory.
 	 */
-	movel	#VBR_BASE,%a7
+	movel	#CONFIG_VECTORBASE,%a7
 	movec   %a7,%VBR			/* set vectors addr */
 	movel	%a7,_ramvec
 
-	movel	#MEM_BASE,%a7			/* mark the base of RAM */
+	movel	#CONFIG_RAMBASE,%a7		/* mark the base of RAM */
 	movel	%a7,_rambase
 
 	GET_MEM_SIZE				/* macro code determines size */
diff --git a/arch/m68knommu/platform/5307/pit.c b/arch/m68knommu/platform/5307/pit.c
index 323f267..ef17474 100644
--- a/arch/m68knommu/platform/5307/pit.c
+++ b/arch/m68knommu/platform/5307/pit.c
@@ -1,11 +1,11 @@
 /***************************************************************************/
 
 /*
- *	pit.c -- Motorola ColdFire PIT timer. Currently this type of
- *	         hardware timer only exists in the Motorola ColdFire
+ *	pit.c -- Freescale ColdFire PIT timer. Currently this type of
+ *	         hardware timer only exists in the Freescale ColdFire
  *		 5270/5271, 5282 and other CPUs.
  *
- *	Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 1999-2006, Greg Ungerer (gerg@snapgear.com)
  *	Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
  *
  */
@@ -18,6 +18,7 @@
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/coldfire.h>
 #include <asm/mcfpit.h>
@@ -25,13 +26,20 @@
 
 /***************************************************************************/
 
+/*
+ *	By default use timer1 as the system clock timer.
+ */
+#define	TA(a)	(MCF_IPSBAR + MCFPIT_BASE1 + (a))
+
+/***************************************************************************/
+
 void coldfire_pit_tick(void)
 {
-	volatile struct mcfpit *tp;
+	unsigned short pcsr;
 
 	/* Reset the ColdFire timer */
-	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
-	tp->pcsr |= MCFPIT_PCSR_PIF;
+	pcsr = __raw_readw(TA(MCFPIT_PCSR));
+	__raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
 }
 
 /***************************************************************************/
@@ -40,7 +48,6 @@
 {
 	volatile unsigned char *icrp;
 	volatile unsigned long *imrp;
-	volatile struct mcfpit *tp;
 
 	request_irq(MCFINT_VECBASE + MCFINT_PIT1, handler, SA_INTERRUPT,
 		"ColdFire Timer", NULL);
@@ -53,27 +60,23 @@
 	*imrp &= ~MCFPIT_IMR_IBIT;
 
 	/* Set up PIT timer 1 as poll clock */
-	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
-	tp->pcsr = MCFPIT_PCSR_DISABLE;
-
-	tp->pmr = ((MCF_CLK / 2) / 64) / HZ;
-	tp->pcsr = MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
-		MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64;
+	__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+	__raw_writew(((MCF_CLK / 2) / 64) / HZ, TA(MCFPIT_PMR));
+	__raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | MCFPIT_PCSR_OVW |
+		MCFPIT_PCSR_RLD | MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
 }
 
 /***************************************************************************/
 
 unsigned long coldfire_pit_offset(void)
 {
-	volatile struct mcfpit *tp;
 	volatile unsigned long *ipr;
 	unsigned long pmr, pcntr, offset;
 
-	tp = (volatile struct mcfpit *) (MCF_IPSBAR + MCFPIT_BASE1);
 	ipr = (volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFPIT_IMR);
 
-	pmr = *(&tp->pmr);
-	pcntr = *(&tp->pcntr);
+	pmr = __raw_readw(TA(MCFPIT_PMR));
+	pcntr = __raw_readw(TA(MCFPIT_PCNTR));
 
 	/*
 	 * If we are still in the first half of the upcount and a
diff --git a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c
index ef49596..83b8b89 100644
--- a/arch/m68knommu/platform/5307/timers.c
+++ b/arch/m68knommu/platform/5307/timers.c
@@ -14,6 +14,7 @@
 #include <linux/param.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/machdep.h>
@@ -24,6 +25,11 @@
 /***************************************************************************/
 
 /*
+ *	By default use timer1 as the system clock timer.
+ */
+#define	TA(a)	(MCF_MBAR + MCFTIMER_BASE1 + (a))
+
+/*
  *	Default the timer and vector to use for ColdFire. Some ColdFire
  *	CPU's and some boards may want different. Their sub-architecture
  *	startup code (in config.c) can change these if they want.
@@ -32,8 +38,6 @@
 unsigned int	mcf_profilevector = 31;
 unsigned int	mcf_timerlevel = 5;
 
-static volatile struct mcftimer *mcf_timerp;
-
 /*
  *	These provide the underlying interrupt vector support.
  *	Unfortunately it is a little different on each ColdFire.
@@ -46,20 +50,17 @@
 void coldfire_tick(void)
 {
 	/* Reset the ColdFire timer */
-	mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+	__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER));
 }
 
 /***************************************************************************/
 
 void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *))
 {
-	/* Set up an internal TIMER as poll clock */
-	mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1);
-	mcf_timerp->tmr = MCFTIMER_TMR_DISABLE;
-
-	mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ);
-	mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+	__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
+	__raw_writew(((MCF_BUSCLK / 16) / HZ), TA(MCFTIMER_TRR));
+	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
 
 	request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL);
 	mcf_settimericr(1, mcf_timerlevel);
@@ -75,13 +76,8 @@
 {
 	unsigned long trr, tcn, offset;
 
-	/*
-	 * The change to pointer and de-reference is to force the compiler
-	 * to read the registers with a single 16bit access. Otherwise it
-	 * does some crazy 8bit read combining.
-	 */
-	tcn = *(&mcf_timerp->tcn);
-	trr = *(&mcf_timerp->trr);
+	tcn = __raw_readw(TA(MCFTIMER_TCN));
+	trr = __raw_readw(TA(MCFTIMER_TRR));
 	offset = (tcn * (1000000 / HZ)) / trr;
 
 	/* Check if we just wrapped the counters and maybe missed a tick */
@@ -95,21 +91,23 @@
 /***************************************************************************/
 
 /*
+ *	By default use timer2 as the profiler clock timer.
+ */
+#define	PA(a)	(MCF_MBAR + MCFTIMER_BASE2 + (a))
+
+/*
  *	Choose a reasonably fast profile timer. Make it an odd value to
  *	try and get good coverage of kernal operations.
  */
 #define	PROFILEHZ	1013
 
-static volatile struct mcftimer *mcf_proftp;
-
 /*
  *	Use the other timer to provide high accuracy profiling info.
  */
-
 void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs)
 {
 	/* Reset ColdFire timer2 */
-	mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF;
+	__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
 	if (current->pid)
 		profile_tick(CPU_PROFILING, regs);
 }
@@ -121,12 +119,11 @@
 	printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ);
 
 	/* Set up TIMER 2 as high speed profile clock */
-	mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2);
-	mcf_proftp->tmr = MCFTIMER_TMR_DISABLE;
+	__raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR));
 
-	mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ);
-	mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE;
+	__raw_writew(((MCF_CLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
+	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR));
 
 	request_irq(mcf_profilevector, coldfire_profile_tick,
 		(SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL);
diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile
new file mode 100644
index 0000000..1230180
--- /dev/null
+++ b/arch/m68knommu/platform/532x/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+ifdef CONFIG_FULLDEBUG
+AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1
+endif
+
+#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
+obj-y := config.o
diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c
new file mode 100644
index 0000000..ceef9bc
--- /dev/null
+++ b/arch/m68knommu/platform/532x/config.c
@@ -0,0 +1,486 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/532x/config.c
+ *
+ *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2000, Lineo (www.lineo.com)
+ *	Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
+ *	Copyright Freescale Semiconductor, Inc 2006
+ *	Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+/***************************************************************************/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+#include <asm/mcfwdebug.h>
+
+/***************************************************************************/
+
+void coldfire_tick(void);
+void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *));
+unsigned long coldfire_timer_offset(void);
+void coldfire_trap_init(void);
+void coldfire_reset(void);
+
+extern unsigned int mcf_timervector;
+extern unsigned int mcf_profilevector;
+extern unsigned int mcf_timerlevel;
+
+/***************************************************************************/
+
+/*
+ *	DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { };
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
+
+void mcf_settimericr(unsigned int timer, unsigned int level)
+{
+	volatile unsigned char *icrp;
+	unsigned int icr;
+	unsigned char irq;
+
+	if (timer <= 2) {
+		switch (timer) {
+		case 2:  irq = 33; icr = MCFSIM_ICR_TIMER2; break;
+		default: irq = 32; icr = MCFSIM_ICR_TIMER1; break;
+		}
+		
+		icrp = (volatile unsigned char *) (MCF_MBAR + icr);
+		*icrp = level;
+		mcf_enable_irq0(irq);
+	}
+}
+
+/***************************************************************************/
+
+int mcf_timerirqpending(int timer)
+{
+	unsigned int imr = 0;
+
+	switch (timer) {
+	case 1:  imr = 0x1; break;
+	case 2:  imr = 0x2; break;
+	default: break;
+	}
+	return (mcf_getiprh() & imr);
+}
+
+/***************************************************************************/
+
+void config_BSP(char *commandp, int size)
+{
+	mcf_setimr(MCFSIM_IMR_MASKALL);
+
+#if defined(CONFIG_BOOTPARAM)
+	strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
+	commandp[size-1] = 0;
+#else
+	/* Copy command line from FLASH to local buffer... */
+	memcpy(commandp, (char *) 0x4000, 4);
+	if(strncmp(commandp, "kcl ", 4) == 0){
+		memcpy(commandp, (char *) 0x4004, size);
+		commandp[size-1] = 0;
+	} else {
+		memset(commandp, 0, size);
+	}
+#endif
+
+	mcf_timervector = 64+32;
+	mcf_profilevector = 64+33;
+	mach_sched_init = coldfire_timer_init;
+	mach_tick = coldfire_tick;
+	mach_gettimeoffset = coldfire_timer_offset;
+	mach_trap_init = coldfire_trap_init;
+	mach_reset = coldfire_reset;
+
+#ifdef MCF_BDM_DISABLE
+	/*
+	 * Disable the BDM clocking.  This also turns off most of the rest of
+	 * the BDM device.  This is good for EMC reasons. This option is not
+	 * incompatible with the memory protection option.
+	 */
+	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
+#endif
+}
+
+/***************************************************************************/
+/* Board initialization */
+
+/********************************************************************/
+/* 
+ * PLL min/max specifications
+ */
+#define MAX_FVCO	500000	/* KHz */
+#define MAX_FSYS	80000 	/* KHz */
+#define MIN_FSYS	58333 	/* KHz */
+#define FREF		16000   /* KHz */
+
+
+#define MAX_MFD		135     /* Multiplier */
+#define MIN_MFD		88      /* Multiplier */
+#define BUSDIV		6       /* Divider */
+
+/*
+ * Low Power Divider specifications
+ */
+#define MIN_LPD		(1 << 0)    /* Divider (not encoded) */
+#define MAX_LPD		(1 << 15)   /* Divider (not encoded) */
+#define DEFAULT_LPD	(1 << 1)	/* Divider (not encoded) */
+
+#define SYS_CLK_KHZ	80000
+#define SYSTEM_PERIOD	12.5
+/*
+ *  SDRAM Timing Parameters
+ */  
+#define SDRAM_BL	8	/* # of beats in a burst */
+#define SDRAM_TWR	2	/* in clocks */
+#define SDRAM_CASL	2.5	/* CASL in clocks */
+#define SDRAM_TRCD	2	/* in clocks */
+#define SDRAM_TRP	2	/* in clocks */
+#define SDRAM_TRFC	7	/* in clocks */
+#define SDRAM_TREFI	7800	/* in ns */
+
+#define EXT_SRAM_ADDRESS	(0xC0000000)
+#define FLASH_ADDRESS		(0x00000000)
+#define SDRAM_ADDRESS		(0x40000000)
+
+#define NAND_FLASH_ADDRESS	(0xD0000000)
+
+int sys_clk_khz = 0;
+int sys_clk_mhz = 0;
+
+void wtm_init(void);
+void scm_init(void);
+void gpio_init(void);
+void fbcs_init(void);
+void sdramc_init(void);
+int  clock_pll (int fsys, int flags);
+int  clock_limp (int);
+int  clock_exit_limp (void);
+int  get_sys_clock (void);
+
+asmlinkage void __init sysinit(void)
+{
+	sys_clk_khz = clock_pll(0, 0);
+	sys_clk_mhz = sys_clk_khz/1000;
+	
+	wtm_init();
+	scm_init();
+	gpio_init();
+	fbcs_init();
+	sdramc_init();
+}
+
+void wtm_init(void)
+{
+	/* Disable watchdog timer */
+	MCF_WTM_WCR = 0;
+}
+
+#define MCF_SCM_BCR_GBW		(0x00000100)
+#define MCF_SCM_BCR_GBR		(0x00000200)
+
+void scm_init(void)
+{
+	/* All masters are trusted */
+	MCF_SCM_MPR = 0x77777777;
+    
+	/* Allow supervisor/user, read/write, and trusted/untrusted
+	   access to all slaves */
+	MCF_SCM_PACRA = 0;
+	MCF_SCM_PACRB = 0;
+	MCF_SCM_PACRC = 0;
+	MCF_SCM_PACRD = 0;
+	MCF_SCM_PACRE = 0;
+	MCF_SCM_PACRF = 0;
+
+	/* Enable bursts */
+	MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
+}
+
+
+void fbcs_init(void)
+{
+	MCF_GPIO_PAR_CS = 0x0000003E;
+
+	/* Latch chip select */
+	MCF_FBCS1_CSAR = 0x10080000;
+
+	MCF_FBCS1_CSCR = 0x002A3780;
+	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
+
+	/* Initialize latch to drive signals to inactive states */
+	*((u16 *)(0x10080000)) = 0xFFFF;
+
+	/* External SRAM */
+	MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
+	MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
+			| MCF_FBCS_CSCR_AA
+			| MCF_FBCS_CSCR_SBM
+			| MCF_FBCS_CSCR_WS(1));
+	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
+			| MCF_FBCS_CSMR_V);
+
+	/* Boot Flash connected to FBCS0 */
+	MCF_FBCS0_CSAR = FLASH_ADDRESS;
+	MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
+			| MCF_FBCS_CSCR_BEM
+			| MCF_FBCS_CSCR_AA
+			| MCF_FBCS_CSCR_SBM
+			| MCF_FBCS_CSCR_WS(7));
+	MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
+			| MCF_FBCS_CSMR_V);
+}
+
+void sdramc_init(void)
+{
+	/*
+	 * Check to see if the SDRAM has already been initialized
+	 * by a run control tool
+	 */
+	if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
+		/* SDRAM chip select initialization */
+		
+		/* Initialize SDRAM chip select */
+		MCF_SDRAMC_SDCS0 = (0
+			| MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
+			| MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
+
+	/*
+	 * Basic configuration and initialization
+	 */
+	MCF_SDRAMC_SDCFG1 = (0
+		| MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
+		| MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
+		| MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
+		| MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
+		| MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
+		| MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
+		| MCF_SDRAMC_SDCFG1_WTLAT(3));
+	MCF_SDRAMC_SDCFG2 = (0
+		| MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
+		| MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
+		| MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
+		| MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
+
+            
+	/*
+	 * Precharge and enable write to SDMR
+	 */
+        MCF_SDRAMC_SDCR = (0
+		| MCF_SDRAMC_SDCR_MODE_EN
+		| MCF_SDRAMC_SDCR_CKE
+		| MCF_SDRAMC_SDCR_DDR
+		| MCF_SDRAMC_SDCR_MUX(1)
+		| MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
+		| MCF_SDRAMC_SDCR_PS_16
+		| MCF_SDRAMC_SDCR_IPALL);            
+
+	/*
+	 * Write extended mode register
+	 */
+	MCF_SDRAMC_SDMR = (0
+		| MCF_SDRAMC_SDMR_BNKAD_LEMR
+		| MCF_SDRAMC_SDMR_AD(0x0)
+		| MCF_SDRAMC_SDMR_CMD);
+
+	/*
+	 * Write mode register and reset DLL
+	 */
+	MCF_SDRAMC_SDMR = (0
+		| MCF_SDRAMC_SDMR_BNKAD_LMR
+		| MCF_SDRAMC_SDMR_AD(0x163)
+		| MCF_SDRAMC_SDMR_CMD);
+
+	/*
+	 * Execute a PALL command
+	 */
+	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
+
+	/*
+	 * Perform two REF cycles
+	 */
+	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+
+	/*
+	 * Write mode register and clear reset DLL
+	 */
+	MCF_SDRAMC_SDMR = (0
+		| MCF_SDRAMC_SDMR_BNKAD_LMR
+		| MCF_SDRAMC_SDMR_AD(0x063)
+		| MCF_SDRAMC_SDMR_CMD);
+				
+	/*
+	 * Enable auto refresh and lock SDMR
+	 */
+	MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
+	MCF_SDRAMC_SDCR |= (0
+		| MCF_SDRAMC_SDCR_REF
+		| MCF_SDRAMC_SDCR_DQS_OE(0xC));
+	}
+}
+
+void gpio_init(void)
+{
+	/* Enable UART0 pins */
+	MCF_GPIO_PAR_UART = ( 0
+		| MCF_GPIO_PAR_UART_PAR_URXD0
+		| MCF_GPIO_PAR_UART_PAR_UTXD0);
+
+	/* Initialize TIN3 as a GPIO output to enable the write
+	   half of the latch */
+	MCF_GPIO_PAR_TIMER = 0x00;
+	MCF_GPIO_PDDR_TIMER = 0x08;
+	MCF_GPIO_PCLRR_TIMER = 0x0;
+
+}
+
+int clock_pll(int fsys, int flags)
+{
+	int fref, temp, fout, mfd;
+	u32 i;
+
+	fref = FREF;
+        
+	if (fsys == 0) {
+		/* Return current PLL output */
+		mfd = MCF_PLL_PFDR;
+
+		return (fref * mfd / (BUSDIV * 4));
+	}
+
+	/* Check bounds of requested system clock */
+	if (fsys > MAX_FSYS)
+		fsys = MAX_FSYS;
+	if (fsys < MIN_FSYS)
+		fsys = MIN_FSYS;
+
+	/* Multiplying by 100 when calculating the temp value,
+	   and then dividing by 100 to calculate the mfd allows
+	   for exact values without needing to include floating
+	   point libraries. */
+	temp = 100 * fsys / fref;
+	mfd = 4 * BUSDIV * temp / 100;
+    	    	    	
+	/* Determine the output frequency for selected values */
+	fout = (fref * mfd / (BUSDIV * 4));
+
+	/*
+	 * Check to see if the SDRAM has already been initialized.
+	 * If it has then the SDRAM needs to be put into self refresh
+	 * mode before reprogramming the PLL.
+	 */
+	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+		/* Put SDRAM into self refresh mode */
+		MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
+
+	/*
+	 * Initialize the PLL to generate the new system clock frequency.
+	 * The device must be put into LIMP mode to reprogram the PLL.
+	 */
+
+	/* Enter LIMP mode */
+	clock_limp(DEFAULT_LPD);
+     					
+	/* Reprogram PLL for desired fsys */
+	MCF_PLL_PODR = (0
+		| MCF_PLL_PODR_CPUDIV(BUSDIV/3)
+		| MCF_PLL_PODR_BUSDIV(BUSDIV));
+						
+	MCF_PLL_PFDR = mfd;
+		
+	/* Exit LIMP mode */
+	clock_exit_limp();
+	
+	/*
+	 * Return the SDRAM to normal operation if it is in use.
+	 */
+	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+		/* Exit self refresh mode */
+		MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
+
+	/* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
+	MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
+
+	/* wait for DQS logic to relock */
+	for (i = 0; i < 0x200; i++)
+		;
+
+	return fout;
+}
+
+int clock_limp(int div)
+{
+	u32 temp;
+
+	/* Check bounds of divider */
+	if (div < MIN_LPD)
+		div = MIN_LPD;
+	if (div > MAX_LPD)
+		div = MAX_LPD;
+    
+	/* Save of the current value of the SSIDIV so we don't
+	   overwrite the value*/
+	temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
+      
+	/* Apply the divider to the system clock */
+	MCF_CCM_CDR = ( 0
+		| MCF_CCM_CDR_LPDIV(div)
+		| MCF_CCM_CDR_SSIDIV(temp));
+    
+	MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
+    
+	return (FREF/(3*(1 << div)));
+}
+
+int clock_exit_limp(void)
+{
+	int fout;
+	
+	/* Exit LIMP mode */
+	MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
+
+	/* Wait for PLL to lock */
+	while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
+		;
+	
+	fout = get_sys_clock();
+
+	return fout;
+}
+
+int get_sys_clock(void)
+{
+	int divider;
+	
+	/* Test to see if device is in LIMP mode */
+	if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
+		divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
+		return (FREF/(2 << divider));
+	}
+	else
+		return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
+}
diff --git a/arch/m68knommu/platform/68328/Makefile b/arch/m68knommu/platform/68328/Makefile
index 1b3b719..5e54355 100644
--- a/arch/m68knommu/platform/68328/Makefile
+++ b/arch/m68knommu/platform/68328/Makefile
@@ -8,6 +8,7 @@
 
 obj-y			+= entry.o ints.o timers.o
 obj-$(CONFIG_M68328)	+= config.o
+obj-$(CONFIG_ROM)	+= romvec.o
 
 extra-y			:= head.o
 extra-$(CONFIG_M68328)	+= bootlogo.rh head.o
diff --git a/arch/m68knommu/platform/68328/head-pilot.S b/arch/m68knommu/platform/68328/head-pilot.S
index c46775f..46b3604 100644
--- a/arch/m68knommu/platform/68328/head-pilot.S
+++ b/arch/m68knommu/platform/68328/head-pilot.S
@@ -21,7 +21,6 @@
 .global _start
 
 .global _rambase
-.global __ramvec
 .global _ramvec
 .global _ramstart
 .global _ramend
@@ -121,7 +120,7 @@
 	DBG_PUTC('B')
 
 	/* Copy command line from beginning of RAM (+16) to end of bss */
-	movel	#__ramvec, %d7
+	movel	#CONFIG_VECTORBASE, %d7
 	addl	#16, %d7
 	moveal	%d7, %a0
 	moveal	#_ebss, %a1
diff --git a/arch/m68knommu/platform/68328/head-ram.S b/arch/m68knommu/platform/68328/head-ram.S
index 6bdc9bc..e8dc924 100644
--- a/arch/m68knommu/platform/68328/head-ram.S
+++ b/arch/m68knommu/platform/68328/head-ram.S
@@ -1,10 +1,7 @@
 #include <linux/config.h>
 
 	.global __main
-	.global __ram_start
-	.global __ram_end
 	.global __rom_start
-	.global __rom_end
 
         .global _rambase
         .global _ramstart
@@ -12,6 +9,7 @@
 	.global splash_bits
 	.global _start
 	.global _stext
+	.global _edata
 
 #define DEBUG
 #define ROM_OFFSET 0x10C00000
@@ -73,7 +71,7 @@
 #ifdef CONFIG_RELOCATE
 	/* Copy me to RAM */
 	moveal	#__rom_start, %a0
-	moveal	#__ram_start, %a1
+	moveal	#_stext, %a1
 	moveal	#_edata, %a2
 
 	/* Copy %a0 to %a1 until %a1 == %a2 */
diff --git a/arch/m68knommu/platform/68328/head-rom.S b/arch/m68knommu/platform/68328/head-rom.S
index 2b448a2..234430b 100644
--- a/arch/m68knommu/platform/68328/head-rom.S
+++ b/arch/m68knommu/platform/68328/head-rom.S
@@ -28,6 +28,8 @@
 _ramend:
 .long   0
 
+#define	RAMEND	(CONFIG_RAMBASE + CONFIG_RAMSIZE)
+
 #ifdef CONFIG_INIT_LCD
 splash_bits:
 #include "bootlogo.rh"
@@ -48,7 +50,7 @@
 	moveb	#0x81,   0xfffffA27	/* LCKCON */
 	movew	#0xff00, 0xfffff412	/* LCD pins */
 #endif
-	moveal  #__ramend-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp
+	moveal  #RAMEND-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp
 	movew	#32767, %d0  /* PLL settle wait loop */
 1:	subq	#1, %d0
 	bne	1b
@@ -73,13 +75,13 @@
 	bhi	1b
 
         movel   #_sdata, %d0    
-        movel   %d0,    _rambase        
-        movel   #_ebss,  %d0
-        movel   %d0,    _ramstart
-	movel	#__ramend-CONFIG_MEMORY_RESERVE*0x100000, %d0
-	movel	%d0,	_ramend
-	movel	#__ramvec,	%d0
-	movel	%d0,	_ramvec
+        movel   %d0, _rambase        
+        movel   #_ebss, %d0
+        movel   %d0, _ramstart
+	movel	#RAMEND-CONFIG_MEMORY_RESERVE*0x100000, %d0
+	movel	%d0, _ramend
+	movel	#CONFIG_VECTORBASE,	%d0
+	movel	%d0, _ramvec
 	
 /*
  * load the current task pointer and stack
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
index 7437217..2dda733 100644
--- a/arch/m68knommu/platform/68328/ints.c
+++ b/arch/m68knommu/platform/68328/ints.c
@@ -18,6 +18,7 @@
 
 #include <asm/system.h>
 #include <asm/irq.h>
+#include <asm/irqnode.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
@@ -82,25 +83,6 @@
 /* irq node variables for the 32 (potential) on chip sources */
 static irq_node_t int_irq_list[NR_IRQS];
 
-#if !defined(CONFIG_DRAGEN2)
-asm (".global _start, __ramend/n/t"
-     ".section .romvec/n"
-     "e_vectors:\n\t"
-     ".long __ramend-4, _start, buserr, trap, trap, trap, trap, trap\n\t"
-     ".long trap, trap, trap, trap, trap, trap, trap, trap\n\t"
-     ".long trap, trap, trap, trap, trap, trap, trap, trap\n\t"
-     ".long trap, trap, trap, trap\n\t"
-     ".long trap, trap, trap, trap\n\t"
-	/*.long inthandler, inthandler, inthandler, inthandler
-	.long inthandler4, inthandler, inthandler, inthandler   */
-	/* TRAP #0-15 */
-     ".long system_call, trap, trap, trap, trap, trap, trap, trap\n\t"
-     ".long trap, trap, trap, trap, trap, trap, trap, trap\n\t"
-     ".long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n\t"
-     ".text\n"
-     "ignore: rte");
-#endif
-
 /*
  * This function should be called during kernel startup to initialize
  * the IRQ handling routines.
diff --git a/arch/m68knommu/platform/68328/romvec.S b/arch/m68knommu/platform/68328/romvec.S
new file mode 100644
index 0000000..3e7fe1e
--- /dev/null
+++ b/arch/m68knommu/platform/68328/romvec.S
@@ -0,0 +1,37 @@
+/*
+ * linux/arch/m68knommu/platform/68328/romvec.S
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * Copyright 1996 Roman Zippel
+ * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
+ * Copyright 2006 Greg Ungerer <gerg@snapgear.com>
+ */
+
+#include <linux/config.h>
+
+.global _start
+.global _buserr
+.global trap
+.global system_call
+
+.section .romvec
+
+e_vectors:
+.long CONFIG_RAMBASE+CONFIG_RAMSIZE-4, _start, buserr, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+/* TRAP #0-15 */
+.long system_call, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
diff --git a/arch/m68knommu/platform/68360/config.c b/arch/m68knommu/platform/68360/config.c
index 3db2446..69c670d 100644
--- a/arch/m68knommu/platform/68360/config.c
+++ b/arch/m68knommu/platform/68360/config.c
@@ -141,13 +141,13 @@
 void BSP_reset (void)
 {
   local_irq_disable();
-  asm volatile ("
-    moveal #_start, %a0;
-    moveb #0, 0xFFFFF300;
-    moveal 0(%a0), %sp;
-    moveal 4(%a0), %a0;
-    jmp (%a0);
-    ");
+  asm volatile (
+    "moveal #_start, %a0;\n"
+    "moveb #0, 0xFFFFF300;\n"
+    "moveal 0(%a0), %sp;\n"
+    "moveal 4(%a0), %a0;\n"
+    "jmp (%a0);\n"
+    );
 }
 
 unsigned char *scc1_hwaddr;
diff --git a/arch/m68knommu/platform/68360/head-ram.S b/arch/m68knommu/platform/68360/head-ram.S
index a5c639a..f497713 100644
--- a/arch/m68knommu/platform/68360/head-ram.S
+++ b/arch/m68knommu/platform/68360/head-ram.S
@@ -18,7 +18,6 @@
 .global _start
 
 .global _rambase
-.global __ramvec
 .global _ramvec
 .global _ramstart
 .global _ramend
@@ -26,6 +25,8 @@
 .global _quicc_base
 .global _periph_base
 
+#define	RAMEND                      (CONFIG_RAMBASE + CONFIG_RAMSIZE)
+
 #define REGB                        0x1000
 #define PEPAR                       (_dprbase + REGB + 0x0016)
 #define GMR                         (_dprbase + REGB + 0x0040)
@@ -103,7 +104,7 @@
 	nop
 	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
 	/* We should not need to setup the boot stack the reset should do it. */
-	movea.l	#__ramend, %sp			/*set up stack at the end of DRAM:*/
+	movea.l	#RAMEND, %sp			/*set up stack at the end of DRAM:*/
 
 set_mbar_register:
 	moveq.l	#0x07, %d1			/* Setup MBAR */
@@ -163,7 +164,7 @@
 	move.l	%d0, GMR
 
 configure_chip_select_0:
-	move.l	#__ramend, %d0
+	move.l	#RAMEND, %d0
 	subi.l	#__ramstart, %d0
 	subq.l	#0x01, %d0
 	eori.l	#SIM_OR_MASK, %d0
@@ -234,16 +235,10 @@
 	/* Set ram size information */
 	move.l	#_sdata, _rambase
 	move.l	#_ebss, _ramstart
-	move.l	#__ramend, %d0
+	move.l	#RAMEND, %d0
 	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
-	move.l	%d0, _ramend			/* Different from __ramend.*/
+	move.l	%d0, _ramend			/* Different from RAMEND.*/
 
-store_flash_size:
-	/* Set rom size information */
-	move.l	#__rom_end, %d0
-	sub.l	#__rom_start, %d0
-	move.l	%d0, rom_length
-    
 	pea	0
 	pea	env
 	pea	%sp@(4)
@@ -286,7 +281,7 @@
      */
  
 .section ".data.initvect","awx"
-    .long   __ramend	/* Reset: Initial Stack Pointer                 - 0.  */
+    .long   RAMEND	/* Reset: Initial Stack Pointer                 - 0.  */
     .long   _start      /* Reset: Initial Program Counter               - 1.  */
     .long   buserr      /* Bus Error                                    - 2.  */
     .long   trap        /* Address Error                                - 3.  */
diff --git a/arch/m68knommu/platform/68360/head-rom.S b/arch/m68knommu/platform/68360/head-rom.S
index 0da357a..2d28c3e 100644
--- a/arch/m68knommu/platform/68360/head-rom.S
+++ b/arch/m68knommu/platform/68360/head-rom.S
@@ -18,7 +18,6 @@
 .global _start
 
 .global _rambase
-.global __ramvec
 .global _ramvec
 .global _ramstart
 .global _ramend
@@ -26,6 +25,8 @@
 .global _quicc_base
 .global _periph_base
 
+#define	RAMEND                      (CONFIG_RAMBASE + CONFIG_RAMSIZE)
+
 #define REGB                        0x1000
 #define PEPAR                       (_dprbase + REGB + 0x0016)
 #define GMR                         (_dprbase + REGB + 0x0040)
@@ -115,7 +116,7 @@
 	nop
 	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
 	/* We should not need to setup the boot stack the reset should do it. */
-	movea.l	#__ramend, %sp		/* set up stack at the end of DRAM:*/
+	movea.l	#RAMEND, %sp		/* set up stack at the end of DRAM:*/
 
 
 set_mbar_register:
@@ -245,16 +246,10 @@
 	/* Set ram size information */
 	move.l	#_sdata, _rambase
 	move.l	#_ebss, _ramstart
-	move.l	#__ramend, %d0
+	move.l	#RAMEND, %d0
 	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
-	move.l	%d0, _ramend			/* Different from __ramend.*/
+	move.l	%d0, _ramend			/* Different from RAMEND.*/
 
-store_flash_size:
-	/* Set rom size information */
-	move.l	#__rom_end, %d0
-	sub.l	#__rom_start, %d0
-	move.l	%d0, rom_length
-    
 	pea	0
 	pea	env
 	pea	%sp@(4)
@@ -298,7 +293,7 @@
      */
  
 .section ".data.initvect","awx"
-    .long   __ramend	/* Reset: Initial Stack Pointer                 - 0.  */
+    .long   RAMEND	/* Reset: Initial Stack Pointer                 - 0.  */
     .long   _start      /* Reset: Initial Program Counter               - 1.  */
     .long   buserr      /* Bus Error                                    - 2.  */
     .long   trap        /* Address Error                                - 3.  */
diff --git a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c
index ba184db..0245fc4 100644
--- a/arch/m68knommu/platform/68360/ints.c
+++ b/arch/m68knommu/platform/68360/ints.c
@@ -20,6 +20,7 @@
 
 #include <asm/system.h>
 #include <asm/irq.h>
+#include <asm/irqnode.h>
 #include <asm/traps.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
diff --git a/arch/m68knommu/platform/68EZ328/config.c b/arch/m68knommu/platform/68EZ328/config.c
index d8d56e5..15a14a6 100644
--- a/arch/m68knommu/platform/68EZ328/config.c
+++ b/arch/m68knommu/platform/68EZ328/config.c
@@ -42,13 +42,13 @@
 void m68ez328_reset(void)
 {
   local_irq_disable();
-  asm volatile ("
-    moveal #0x10c00000, %a0;
-    moveb #0, 0xFFFFF300;
-    moveal 0(%a0), %sp;
-    moveal 4(%a0), %a0;
-    jmp (%a0);
-    ");
+  asm volatile (
+    "moveal #0x10c00000, %a0;\n"
+    "moveb #0, 0xFFFFF300;\n"
+    "moveal 0(%a0), %sp;\n"
+    "moveal 4(%a0), %a0;\n"
+    "jmp (%a0);\n"
+    );
 }
 
 /***************************************************************************/
diff --git a/arch/m68knommu/platform/68VZ328/config.c b/arch/m68knommu/platform/68VZ328/config.c
index d926524..4058de5 100644
--- a/arch/m68knommu/platform/68VZ328/config.c
+++ b/arch/m68knommu/platform/68VZ328/config.c
@@ -141,13 +141,13 @@
 static void m68vz328_reset(void)
 {
 	local_irq_disable();
-	asm volatile ("
-		moveal #0x10c00000, %a0;
-		moveb #0, 0xFFFFF300;
-		moveal 0(%a0), %sp;
-		moveal 4(%a0), %a0;
-		jmp (%a0);
-	");
+	asm volatile (
+		"moveal #0x10c00000, %a0;\n\t"
+		"moveb #0, 0xFFFFF300;\n\t"
+		"moveal 0(%a0), %sp;\n\t"
+		"moveal 4(%a0), %a0;\n\t"
+		"jmp (%a0);\n"
+	);
 }
 
 unsigned char *cs8900a_hwaddr;
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e8ff09f..35e038a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -119,6 +119,32 @@
 	select SYS_HAS_CPU_MIPS32_R1
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
+config BASLER_EXCITE
+	bool "Basler eXcite smart camera support"
+	select DMA_COHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select IRQ_CPU_RM7K
+	select IRQ_CPU_RM9K
+	select SERIAL_RM9000
+	select SYS_HAS_CPU_RM9000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	help
+	  The eXcite is a smart camera platform manufactured by
+	  Basler Vision Technologies AG
+
+config BASLER_EXCITE_PROTOTYPE
+	bool "Support for pre-release units"
+	depends on BASLER_EXCITE
+	default n
+	help
+	  Pre-series (prototype) units are different from later ones in
+	  some ways. Select this option if you have one of these. Please
+	  note that a kernel built with this option selected will not be
+	  able to run on normal units.
+
 config MIPS_COBALT
 	bool "Cobalt Server"
 	select DMA_NONCOHERENT
@@ -142,6 +168,9 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_SUPPORTS_128HZ
+	select SYS_SUPPORTS_256HZ
+	select SYS_SUPPORTS_1024HZ
 	help
 	  This enables support for DEC's MIPS based workstations.  For details
 	  see the Linux/MIPS FAQ on <http://www.linux-mips.org/> and the
@@ -239,6 +268,7 @@
 	select SYS_HAS_CPU_R4X00
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
+	select SYS_SUPPORTS_100HZ
 	help
 	 This a family of machines based on the MIPS R4030 chipset which was
 	 used by several vendors to build RISC/os and Windows NT workstations.
@@ -327,6 +357,27 @@
 	  This enables support for the MIPS Technologies SEAD evaluation
 	  board.
 
+config WR_PPMC
+	bool "Support for Wind River PPMC board"
+	select IRQ_CPU
+	select BOOT_ELF32
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_GT64120
+	select SWAP_IO_SPACE
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_HAS_CPU_MIPS32_R2
+	select SYS_HAS_CPU_MIPS64_R1
+	select SYS_HAS_CPU_NEVADA
+	select SYS_HAS_CPU_RM7000
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_64BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	help
+	  This enables support for the Wind River MIPS32 4KC PPMC evaluation
+	  board, which is based on GT64120 bridge chip.
+
 config MIPS_SIM
 	bool 'MIPS simulator (MIPSsim)'
 	select DMA_NONCOHERENT
@@ -438,53 +489,16 @@
 
 config PNX8550_V2PCI
 	bool "Philips PNX8550 based Viper2-PCI board"
+	depends on BROKEN
 	select PNX8550
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config PNX8550_JBS
 	bool "Philips PNX8550 based JBS board"
+	depends on BROKEN
 	select PNX8550
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
-config DDB5074
-	bool "NEC DDB Vrc-5074 (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	select DDB5XXX_COMMON
-	select DMA_NONCOHERENT
-	select HAVE_STD_PC_SERIAL_PORT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select I8259
-	select ISA
-	select SYS_HAS_CPU_R5000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-	help
-	  This enables support for the VR5000-based NEC DDB Vrc-5074
-	  evaluation board.
-
-config DDB5476
-	bool "NEC DDB Vrc-5476"
-	select DDB5XXX_COMMON
-	select DMA_NONCOHERENT
-	select HAVE_STD_PC_SERIAL_PORT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select I8259
-	select ISA
-	select SYS_HAS_CPU_R5432
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-	help
-	  This enables support for the R5432-based NEC DDB Vrc-5476
-	  evaluation board.
-
-	  Features : kernel debugging, serial terminal, NFS root fs, on-board
-	  ether port USB, AC97, PCI, PCI VGA card & framebuffer console,
-	  IDE controller, PS2 keyboard, PS2 mouse, etc.
-
 config DDB5477
 	bool "NEC DDB Vrc-5477"
 	select DDB5XXX_COMMON
@@ -546,6 +560,20 @@
 	  simulate actual MIPS hardware platforms.  More information on Qemu
 	  can be found at http://www.linux-mips.org/wiki/Qemu.
 
+config MARKEINS
+	bool "Support for NEC EMMA2RH Mark-eins"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select IRQ_CPU
+	select SWAP_IO_SPACE
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+	select SYS_HAS_CPU_R5000
+	help
+	  This enables support for the R5432-based NEC Mark-eins
+	  boards with R5500 CPU.
+
 config SGI_IP22
 	bool "SGI IP22 (Indy/Indigo2)"
 	select ARC
@@ -555,6 +583,7 @@
 	select HW_HAS_EISA
 	select IP22_CPU_SCACHE
 	select IRQ_CPU
+	select NO_ISA if ISA
 	select SWAP_IO_SPACE
 	select SYS_HAS_CPU_R4X00
 	select SYS_HAS_CPU_R5000
@@ -577,6 +606,7 @@
 	select SYS_HAS_CPU_R10000
 	select SYS_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_NUMA
 	help
 	  This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics
 	  workstations.  To compile a Linux kernel that runs on these, say Y
@@ -707,8 +737,8 @@
 
 config SNI_RM200_PCI
 	bool "SNI RM200 PCI"
-	select ARC
-	select ARC32
+	select ARC if CPU_LITTLE_ENDIAN
+	select ARC32 if CPU_LITTLE_ENDIAN
 	select ARCH_MAY_HAVE_PC_FDC
 	select BOOT_ELF32
 	select DMA_NONCOHERENT
@@ -719,10 +749,13 @@
 	select I8253
 	select I8259
 	select ISA
+	select SWAP_IO_SPACE if CPU_BIG_ENDIAN
 	select SYS_HAS_CPU_R4X00
+	select SYS_HAS_CPU_R5000
+	select R5000_CPU_SCACHE
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-	select SYS_SUPPORTS_BIG_ENDIAN if EXPERIMENTAL
+	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_HIGHMEM
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	help
@@ -979,6 +1012,11 @@
 config SWAP_IO_SPACE
 	bool
 
+config EMMA2RH
+	bool
+	depends on MARKEINS
+	default y
+
 #
 # Unfortunately not all GT64120 systems run the chip at the same clock.
 # As the user for the clock rate and try to minimize the available options.
@@ -1607,6 +1645,28 @@
 	def_bool y
 	depends on !NUMA
 
+config ARCH_DISCONTIGMEM_ENABLE
+	bool
+	default y if SGI_IP27
+	help
+	  Say Y to upport efficient handling of discontiguous physical memory,
+	  for architectures which are either NUMA (Non-Uniform Memory Access)
+	  or have huge holes in the physical address space for other reasons.
+	  See <file:Documentation/vm/numa> for more.
+
+config NUMA
+	bool "NUMA Support"
+	depends on SYS_SUPPORTS_NUMA
+	help
+	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
+	  Access).  This option improves performance on systems with more
+	  than two nodes; on two node systems it is generally better to
+	  leave it disabled; on single node systems disable this option
+	  disabled.
+
+config SYS_SUPPORTS_NUMA
+	bool
+
 config NODES_SHIFT
 	int
 	default "6"
@@ -1651,6 +1711,77 @@
 	  This is purely to save memory - each supported CPU adds
 	  approximately eight kilobytes to the kernel image.
 
+#
+# Timer Interrupt Frequency Configuration
+#
+
+choice
+	prompt "Timer frequency"
+	default HZ_250
+	help
+	 Allows the configuration of the timer frequency.
+
+	config HZ_48
+		bool "48 HZ" if SYS_SUPPORTS_48HZ
+
+	config HZ_100
+		bool "100 HZ" if SYS_SUPPORTS_100HZ || SYS_SUPPORTS_ARBIT_HZ
+
+	config HZ_128
+		bool "128 HZ" if SYS_SUPPORTS_128HZ || SYS_SUPPORTS_ARBIT_HZ
+
+	config HZ_250
+		bool "250 HZ" if SYS_SUPPORTS_250HZ || SYS_SUPPORTS_ARBIT_HZ
+
+	config HZ_256
+		bool "256 HZ" if SYS_SUPPORTS_256HZ || SYS_SUPPORTS_ARBIT_HZ
+
+	config HZ_1000
+		bool "1000 HZ" if SYS_SUPPORTS_1000HZ || SYS_SUPPORTS_ARBIT_HZ
+
+	config HZ_1024
+		bool "1024 HZ" if SYS_SUPPORTS_1024HZ || SYS_SUPPORTS_ARBIT_HZ
+
+endchoice
+
+config SYS_SUPPORTS_48HZ
+	bool
+
+config SYS_SUPPORTS_100HZ
+	bool
+
+config SYS_SUPPORTS_128HZ
+	bool
+
+config SYS_SUPPORTS_250HZ
+	bool
+
+config SYS_SUPPORTS_256HZ
+	bool
+
+config SYS_SUPPORTS_1000HZ
+	bool
+
+config SYS_SUPPORTS_1024HZ
+	bool
+
+config SYS_SUPPORTS_ARBIT_HZ
+	bool
+	default y if !SYS_SUPPORTS_48HZ && !SYS_SUPPORTS_100HZ && \
+		     !SYS_SUPPORTS_128HZ && !SYS_SUPPORTS_250HZ && \
+		     !SYS_SUPPORTS_256HZ && !SYS_SUPPORTS_1000HZ && \
+		     !SYS_SUPPORTS_1024HZ
+
+config HZ
+	int
+	default 48 if HZ_48
+	default 100 if HZ_100
+	default 128 if HZ_128
+	default 250 if HZ_250
+	default 256 if HZ_256
+	default 1000 if HZ_1000
+	default 1024 if HZ_1024
+
 source "kernel/Kconfig.preempt"
 
 config RTC_DS1742
@@ -1710,6 +1841,9 @@
 config ISA
 	bool
 
+config NO_ISA
+	bool
+
 config EISA
 	bool "EISA support"
 	depends on HW_HAS_EISA
@@ -1840,6 +1974,32 @@
 	bool "Power Management support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && SOC_AU1X00
 
+config APM
+        tristate "Advanced Power Management Emulation"
+	depends on PM
+        ---help---
+	  APM is a BIOS specification for saving power using several different
+	  techniques. This is mostly useful for battery powered systems with
+	  APM compliant BIOSes. If you say Y here, the system time will be
+	  reset after a RESUME operation, the /proc/apm device will provide
+	  battery status information, and user-space programs will receive
+	  notification of APM "events" (e.g. battery status change).
+
+	  In order to use APM, you will need supporting software. For location
+	  and more information, read <file:Documentation/pm.txt> and the
+	  Battery Powered Linux mini-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  This driver does not spin down disk drives (see the hdparm(8)
+	  manpage ("man 8 hdparm") for that), and it doesn't turn off
+	  VESA-compliant "green" monitors.
+
+	  Generally, if you don't have a battery in your machine, there isn't
+	  much point in using this driver and you should say N. If you get
+	  random kernel OOPSes or reboots that don't seem to be related to
+	  anything, try disabling/enabling this option (or disabling/enabling
+	  APM in your BIOS).
+
 endmenu
 
 source "net/Kconfig"
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 133900a..d593014 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -83,6 +83,8 @@
 LDFLAGS_vmlinux			+= -G 0 -static -n -nostdlib
 MODFLAGS			+= -mlong-calls
 
+cflags-y += -ffreestanding
+
 #
 # We explicitly add the endianness specifier if needed, this allows
 # to compile kernels with a toolchain for the other endianness. We
@@ -285,6 +287,13 @@
 load-$(CONFIG_MIPS_EV96100)	+= 0xffffffff80100000
 
 #
+# Wind River PPMC Board (4KC + GT64120)
+#
+core-$(CONFIG_WR_PPMC)		+= arch/mips/gt64120/wrppmc/
+cflags-$(CONFIG_WR_PPMC)		+= -Iinclude/asm-mips/mach-wrppmc
+load-$(CONFIG_WR_PPMC)		+= 0xffffffff80100000
+
+#
 # Globespan IVR eval board with QED 5231 CPU
 #
 core-$(CONFIG_ITE_BOARD_GEN)	+= arch/mips/ite-boards/generic/
@@ -379,6 +388,13 @@
 load-$(CONFIG_MOMENCO_OCELOT_3) 	+= 0xffffffff80100000
 
 #
+# Basler eXcite
+#
+core-$(CONFIG_BASLER_EXCITE)	+= arch/mips/basler/excite/
+cflags-$(CONFIG_BASLER_EXCITE)	+= -Iinclude/asm-mips/mach-excite
+load-$(CONFIG_BASLER_EXCITE)	+= 0x80100000
+
+#
 # Momentum Jaguar ATX
 #
 core-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= arch/mips/momentum/jaguar_atx/
@@ -395,18 +411,6 @@
 core-$(CONFIG_DDB5XXX_COMMON)	+= arch/mips/ddb5xxx/common/
 
 #
-# NEC DDB Vrc-5074
-#
-core-$(CONFIG_DDB5074)		+= arch/mips/ddb5xxx/ddb5074/
-load-$(CONFIG_DDB5074)		+= 0xffffffff80080000
-
-#
-# NEC DDB Vrc-5476
-#
-core-$(CONFIG_DDB5476)		+= arch/mips/ddb5xxx/ddb5476/
-load-$(CONFIG_DDB5476)		+= 0xffffffff80080000
-
-#
 # NEC DDB Vrc-5477
 #
 core-$(CONFIG_DDB5477)		+= arch/mips/ddb5xxx/ddb5477/
@@ -468,6 +472,15 @@
 #cflags-$(CONFIG_PNX8550_JBS)	+= -Iinclude/asm-mips/mach-pnx8550
 load-$(CONFIG_PNX8550_JBS)	+= 0xffffffff80060000
 
+# NEC EMMA2RH boards
+#
+core-$(CONFIG_EMMA2RH)          += arch/mips/emma2rh/common/
+cflags-$(CONFIG_EMMA2RH)        += -Iinclude/asm-mips/mach-emma2rh
+
+# NEC EMMA2RH Mark-eins
+core-$(CONFIG_MARKEINS)         += arch/mips/emma2rh/markeins/
+load-$(CONFIG_MARKEINS)         += 0xffffffff88100000
+
 #
 # SGI IP22 (Indy/Indigo2)
 #
diff --git a/arch/mips/au1000/common/au1xxx_irqmap.c b/arch/mips/au1000/common/au1xxx_irqmap.c
index 0b2c03c..5a1e368 100644
--- a/arch/mips/au1000/common/au1xxx_irqmap.c
+++ b/arch/mips/au1000/common/au1xxx_irqmap.c
@@ -55,7 +55,7 @@
  * Careful if you change match 2 request!
  * The interrupt handler is called directly from the low level dispatch code.
  */
-au1xxx_irq_map_t au1xxx_ic0_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_ic0_map[] = {
 
 #if defined(CONFIG_SOC_AU1000)
 	{ AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0},
@@ -220,5 +220,5 @@
 
 };
 
-int au1xxx_ic0_nr_irqs = sizeof(au1xxx_ic0_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map);
 
diff --git a/arch/mips/au1000/common/pci.c b/arch/mips/au1000/common/pci.c
index 4e5a6e1..b1392ab 100644
--- a/arch/mips/au1000/common/pci.c
+++ b/arch/mips/au1000/common/pci.c
@@ -40,17 +40,17 @@
 
 /* TBD */
 static struct resource pci_io_resource = {
-	"pci IO space",
-	(u32)PCI_IO_START,
-	(u32)PCI_IO_END,
-	IORESOURCE_IO
+	.start	= PCI_IO_START,
+	.end	= PCI_IO_END,
+	.name	= "PCI IO space",
+	.flags	= IORESOURCE_IO
 };
 
 static struct resource pci_mem_resource = {
-	"pci memory space",
-	(u32)PCI_MEM_START,
-	(u32)PCI_MEM_END,
-	IORESOURCE_MEM
+	.start	= PCI_MEM_START,
+	.end	= PCI_MEM_END,
+	.name	= "PCI memory space",
+	.flags	= IORESOURCE_MEM
 };
 
 extern struct pci_ops au1x_pci_ops;
diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c
index 307e98c..97165b6 100644
--- a/arch/mips/au1000/common/setup.c
+++ b/arch/mips/au1000/common/setup.c
@@ -49,17 +49,13 @@
 extern void au1000_restart(char *);
 extern void au1000_halt(void);
 extern void au1000_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-extern void (*board_time_init)(void);
 extern void au1x_time_init(void);
-extern void (*board_timer_setup)(struct irqaction *irq);
 extern void au1x_timer_setup(struct irqaction *irq);
 extern void au1xxx_time_init(void);
 extern void au1xxx_timer_setup(struct irqaction *irq);
 extern void set_cpuspec(void);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	struct	cpu_spec *sp;
 	char *argptr;
diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c
index f74d66a..842e1b5 100644
--- a/arch/mips/au1000/common/time.c
+++ b/arch/mips/au1000/common/time.c
@@ -50,10 +50,6 @@
 #include <linux/mc146818rtc.h>
 #include <linux/timex.h>
 
-extern void do_softirq(void);
-extern volatile unsigned long wall_jiffies;
-unsigned long missed_heart_beats = 0;
-
 static unsigned long r4k_offset; /* Amount to increment compare reg each time */
 static unsigned long r4k_cur;    /* What counter should be at next timer irq */
 int	no_au1xxx_32khz;
@@ -388,10 +384,9 @@
 }
 #endif
 
-void au1xxx_timer_setup(struct irqaction *irq)
+void __init au1xxx_timer_setup(struct irqaction *irq)
 {
-        unsigned int est_freq;
-	extern unsigned long (*do_gettimeoffset)(void);
+	unsigned int est_freq;
 
 	printk("calculating r4koff... ");
 	r4k_offset = cal_r4koff();
diff --git a/arch/mips/au1000/csb250/irqmap.c b/arch/mips/au1000/csb250/irqmap.c
index 5cb1166..57d6040 100644
--- a/arch/mips/au1000/csb250/irqmap.c
+++ b/arch/mips/au1000/csb250/irqmap.c
@@ -47,7 +47,7 @@
 #include <asm/system.h>
 #include <asm/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 
 	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
@@ -57,4 +57,4 @@
 	{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/db1x00/irqmap.c b/arch/mips/au1000/db1x00/irqmap.c
index f63024a..0138c5b 100644
--- a/arch/mips/au1000/db1x00/irqmap.c
+++ b/arch/mips/au1000/db1x00/irqmap.c
@@ -80,7 +80,7 @@
 #endif
 
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 
 #ifndef CONFIG_MIPS_MIRAGE
 #ifdef CONFIG_MIPS_DB1550
@@ -101,4 +101,4 @@
 
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/hydrogen3/irqmap.c b/arch/mips/au1000/hydrogen3/irqmap.c
index 6eacaa0..14e1ed3 100644
--- a/arch/mips/au1000/hydrogen3/irqmap.c
+++ b/arch/mips/au1000/hydrogen3/irqmap.c
@@ -47,10 +47,10 @@
 #include <asm/system.h>
 #include <asm/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 
 	/* { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, */
 	{ AU1000_GPIO_21, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/mtx-1/irqmap.c b/arch/mips/au1000/mtx-1/irqmap.c
index f9a0a8b..4693a4e 100644
--- a/arch/mips/au1000/mtx-1/irqmap.c
+++ b/arch/mips/au1000/mtx-1/irqmap.c
@@ -58,7 +58,7 @@
  [7] = { -1, INTD, INTC, INTX, INTX},   /* IDSEL 07 - AdapterD-Slot1 (bottom) */
 };
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
        { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
        { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
        { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
@@ -66,4 +66,4 @@
        { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/pb1000/irqmap.c b/arch/mips/au1000/pb1000/irqmap.c
index a3c460e..156500b 100644
--- a/arch/mips/au1000/pb1000/irqmap.c
+++ b/arch/mips/au1000/pb1000/irqmap.c
@@ -47,8 +47,8 @@
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 	{ AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/pb1100/irqmap.c b/arch/mips/au1000/pb1100/irqmap.c
index 43be715..d986916 100644
--- a/arch/mips/au1000/pb1100/irqmap.c
+++ b/arch/mips/au1000/pb1100/irqmap.c
@@ -47,11 +47,11 @@
 #include <asm/system.h>
 #include <asm/mach-au1x00/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 	{ AU1000_GPIO_9, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card Fully_Interted#
 	{ AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card STSCHG#
 	{ AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, // PCMCIA Card IRQ#
 	{ AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, // DC_IRQ#
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c
index 59e70e5..bacc0c6 100644
--- a/arch/mips/au1000/pb1200/irqmap.c
+++ b/arch/mips/au1000/pb1200/irqmap.c
@@ -55,11 +55,11 @@
 #define PB1200_INT_END DB1200_INT_END
 #endif
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 	{ AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 }, // This is exteranl interrupt cascade
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
 
 /*
  *	Support for External interrupts on the PbAu1200 Development platform.
diff --git a/arch/mips/au1000/pb1500/irqmap.c b/arch/mips/au1000/pb1500/irqmap.c
index 8cb76c2..409d161 100644
--- a/arch/mips/au1000/pb1500/irqmap.c
+++ b/arch/mips/au1000/pb1500/irqmap.c
@@ -52,7 +52,7 @@
  [13] = { -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot */
 };
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
 	{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
@@ -60,4 +60,4 @@
 	{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/pb1550/irqmap.c b/arch/mips/au1000/pb1550/irqmap.c
index 47c7a1c..24a9d18 100644
--- a/arch/mips/au1000/pb1550/irqmap.c
+++ b/arch/mips/au1000/pb1550/irqmap.c
@@ -52,9 +52,9 @@
  [13] =	{ -1, INTA, INTB, INTC, INTD},   /* IDSEL 13 - PCI slot 1 (right) */
 };
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 	{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
 	{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/au1000/xxs1500/irqmap.c b/arch/mips/au1000/xxs1500/irqmap.c
index 52f2f7d..3844c64 100644
--- a/arch/mips/au1000/xxs1500/irqmap.c
+++ b/arch/mips/au1000/xxs1500/irqmap.c
@@ -47,7 +47,7 @@
 #include <asm/system.h>
 #include <asm/au1000.h>
 
-au1xxx_irq_map_t au1xxx_irq_map[] = {
+au1xxx_irq_map_t __initdata au1xxx_irq_map[] = {
 	{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0},
 	{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
 	{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
@@ -63,4 +63,4 @@
 	{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
 };
 
-int au1xxx_nr_irqs = sizeof(au1xxx_irq_map)/sizeof(au1xxx_irq_map_t);
+int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile
new file mode 100644
index 0000000..519142c
--- /dev/null
+++ b/arch/mips/basler/excite/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for Basler eXcite
+#
+
+obj-$(CONFIG_BASLER_EXCITE)	+= excite_irq.o excite_prom.o excite_setup.o \
+				   excite_device.o excite_procfs.o
+
+obj-$(CONFIG_KGDB)		+= excite_dbg_io.o
+obj-m				+= excite_iodev.o
diff --git a/arch/mips/basler/excite/excite_dbg_io.c b/arch/mips/basler/excite/excite_dbg_io.c
new file mode 100644
index 0000000..83f6bdd
--- /dev/null
+++ b/arch/mips/basler/excite/excite_dbg_io.c
@@ -0,0 +1,122 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/gdb-stub.h>
+#include <asm/rm9k-ocd.h>
+#include <excite.h>
+
+#if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1
+#error Debug port used by serial driver
+#endif
+
+#define UART_CLK		25000000
+#define BASE_BAUD		(UART_CLK / 16)
+#define REGISTER_BASE_0		0x0208UL
+#define REGISTER_BASE_1		0x0238UL
+
+#define REGISTER_BASE_DBG	REGISTER_BASE_1
+
+#define CPRR	0x0004
+#define UACFG	0x0200
+#define UAINTS	0x0204
+#define UARBR	(REGISTER_BASE_DBG + 0x0000)
+#define UATHR	(REGISTER_BASE_DBG + 0x0004)
+#define UADLL	(REGISTER_BASE_DBG + 0x0008)
+#define UAIER	(REGISTER_BASE_DBG + 0x000c)
+#define UADLH	(REGISTER_BASE_DBG + 0x0010)
+#define UAIIR	(REGISTER_BASE_DBG + 0x0014)
+#define UAFCR	(REGISTER_BASE_DBG + 0x0018)
+#define UALCR	(REGISTER_BASE_DBG + 0x001c)
+#define UAMCR	(REGISTER_BASE_DBG + 0x0020)
+#define UALSR	(REGISTER_BASE_DBG + 0x0024)
+#define UAMSR	(REGISTER_BASE_DBG + 0x0028)
+#define UASCR	(REGISTER_BASE_DBG + 0x002c)
+
+#define	PARITY_NONE	0
+#define	PARITY_ODD	0x08
+#define	PARITY_EVEN	0x18
+#define	PARITY_MARK	0x28
+#define	PARITY_SPACE	0x38
+
+#define	DATA_5BIT	0x0
+#define	DATA_6BIT	0x1
+#define	DATA_7BIT	0x2
+#define	DATA_8BIT	0x3
+
+#define	STOP_1BIT	0x0
+#define	STOP_2BIT	0x4
+
+#define BAUD_DBG	57600
+#define	PARITY_DBG	PARITY_NONE
+#define	DATA_DBG	DATA_8BIT
+#define	STOP_DBG	STOP_1BIT
+
+/* Initialize the serial port for KGDB debugging */
+void __init excite_kgdb_init(void)
+{
+	const u32 divisor = BASE_BAUD / BAUD_DBG;
+
+	/* Take the UART out of reset */
+	titan_writel(0x00ff1cff, CPRR);
+	titan_writel(0x00000000, UACFG);
+	titan_writel(0x00000002, UACFG);
+
+	titan_writel(0x0, UALCR);
+	titan_writel(0x0, UAIER);
+
+	/* Disable FIFOs */
+	titan_writel(0x00, UAFCR);
+
+	titan_writel(0x80, UALCR);
+	titan_writel(divisor & 0xff, UADLL);
+	titan_writel((divisor & 0xff00) >> 8, UADLH);
+	titan_writel(0x0, UALCR);
+
+	titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR);
+
+	/* Enable receiver interrupt */
+	titan_readl(UARBR);
+	titan_writel(0x1, UAIER);
+}
+
+int getDebugChar(void)
+{
+	while (!(titan_readl(UALSR) & 0x1));
+	return titan_readl(UARBR);
+}
+
+int putDebugChar(int data)
+{
+	while (!(titan_readl(UALSR) & 0x20));
+	titan_writel(data, UATHR);
+	return 1;
+}
+
+/* KGDB interrupt handler */
+asmlinkage void excite_kgdb_inthdl(struct pt_regs *regs)
+{
+	if (unlikely(
+		((titan_readl(UAIIR) & 0x7) == 4)
+		&& ((titan_readl(UARBR) & 0xff) == 0x3)))
+			set_async_breakpoint(&regs->cp0_epc);
+}
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
new file mode 100644
index 0000000..34ec767
--- /dev/null
+++ b/arch/mips/basler/excite/excite_device.c
@@ -0,0 +1,404 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/sched.h>
+#include <asm/types.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+#include <rm9k_eth.h>
+#include <rm9k_wdt.h>
+#include <rm9k_xicap.h>
+#include <excite_nandflash.h>
+
+#include "excite_iodev.h"
+
+#define RM9K_GE_UNIT	0
+#define XICAP_UNIT	0
+#define NAND_UNIT	0
+
+#define DLL_TIMEOUT	3		/* seconds */
+
+
+#define RINIT(__start__, __end__, __name__, __parent__) {	\
+	.name	= __name__ "_0",				\
+	.start	= (__start__),					\
+	.end	= (__end__),					\
+	.flags	= 0,						\
+	.parent	= (__parent__)					\
+}
+
+#define RINIT_IRQ(__irq__, __name__) {	\
+	.name	= __name__ "_0",	\
+	.start	= (__irq__),		\
+	.end	= (__irq__),		\
+	.flags	= IORESOURCE_IRQ,	\
+	.parent	= NULL			\
+}
+
+
+
+enum {
+	slice_xicap,
+	slice_eth
+};
+
+
+
+static struct resource
+	excite_ctr_resource = {
+		.name		= "GPI counters",
+		.start		= 0,
+		.end		= 5,
+		.flags		= 0,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	},
+	excite_gpislice_resource = {
+		.name		= "GPI slices",
+		.start		= 0,
+		.end		= 1,
+		.flags		= 0,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	},
+	excite_mdio_channel_resource = {
+		.name		= "MDIO channels",
+		.start		= 0,
+		.end		= 1,
+		.flags		= 0,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	},
+	excite_fifomem_resource = {
+		.name		= "FIFO memory",
+		.start		= 0,
+		.end		= 767,
+		.flags		= 0,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	},
+	excite_scram_resource = {
+		.name		= "Scratch RAM",
+		.start		= EXCITE_PHYS_SCRAM,
+		.end		= EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
+		.flags		= IORESOURCE_MEM,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	},
+	excite_fpga_resource = {
+		.name		= "System FPGA",
+		.start		= EXCITE_PHYS_FPGA,
+		.end		= EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
+		.flags		= IORESOURCE_MEM,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	},
+	excite_nand_resource = {
+		.name		= "NAND flash control",
+		.start		= EXCITE_PHYS_NAND,
+		.end		= EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
+		.flags		= IORESOURCE_MEM,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	},
+	excite_titan_resource = {
+		.name		= "TITAN registers",
+		.start		= EXCITE_PHYS_TITAN,
+		.end		= EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
+		.flags		= IORESOURCE_MEM,
+		.parent		= NULL,
+		.sibling	= NULL,
+		.child		= NULL
+	};
+
+
+
+static void adjust_resources(struct resource *res, unsigned int n)
+{
+	struct resource *p;
+	const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM
+				   | IORESOURCE_IRQ | IORESOURCE_DMA;
+
+	for (p = res; p < res + n; p++) {
+		const struct resource * const parent = p->parent;
+		if (parent) {
+			p->start += parent->start;
+			p->end   += parent->start;
+			p->flags =  parent->flags & mask;
+		}
+	}
+}
+
+
+
+#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE)
+static struct resource xicap_rsrc[] = {
+	RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource),
+	RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource),
+	RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource),
+	RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource),
+	RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource),
+	RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource),
+	RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
+	RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource),
+	RINIT_IRQ(TITAN_IRQ,  XICAP_RESOURCE_IRQ)
+};
+
+static struct platform_device xicap_pdev = {
+	.name		= XICAP_NAME,
+	.id		= XICAP_UNIT,
+	.num_resources	= ARRAY_SIZE(xicap_rsrc),
+	.resource	= xicap_rsrc
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init xicap_devinit(void)
+{
+	unsigned long tend;
+	u32 reg;
+	int retval;
+
+	adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc));
+
+	/* Power up the slice and configure it. */
+	reg = titan_readl(CPTC1R);
+	reg &= ~(0x11100 << slice_xicap);
+	titan_writel(reg, CPTC1R);
+
+	/* Enable slice & DLL. */
+	reg= titan_readl(CPRR);
+	reg &= ~(0x00030003 << (slice_xicap * 2));
+	titan_writel(reg, CPRR);
+
+	/* Wait for DLLs to lock */
+	tend = jiffies + DLL_TIMEOUT * HZ;
+	while (time_before(jiffies, tend)) {
+		if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))))
+			break;
+		yield();
+	}
+
+	if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) {
+		printk(KERN_ERR "%s: DLL not locked after %u seconds\n",
+		       xicap_pdev.name, DLL_TIMEOUT);
+		retval = -ETIME;
+	} else {
+		/* Register platform device */
+		retval = platform_device_register(&xicap_pdev);
+	}
+
+	return retval;
+}
+
+device_initcall(xicap_devinit);
+#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */
+
+
+
+#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE)
+static struct resource wdt_rsrc[] = {
+	RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource),
+	RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource),
+	RINIT_IRQ(TITAN_IRQ,  WDT_RESOURCE_IRQ)
+};
+
+static struct platform_device wdt_pdev = {
+	.name		= WDT_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(wdt_rsrc),
+	.resource	= wdt_rsrc
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init wdt_devinit(void)
+{
+	adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc));
+	return platform_device_register(&wdt_pdev);
+}
+
+device_initcall(wdt_devinit);
+#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */
+
+
+
+static struct resource excite_nandflash_rsrc[] = {
+ 	RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS,  &excite_nand_resource)
+};
+
+static struct platform_device excite_nandflash_pdev = {
+	.name		= "excite_nand",
+	.id		= NAND_UNIT,
+	.num_resources	= ARRAY_SIZE(excite_nandflash_rsrc),
+	.resource	= excite_nandflash_rsrc
+};
+
+/*
+ * Create a platform device for the access to the nand-flash
+ * port
+ */
+static int __init excite_nandflash_devinit(void)
+{
+	adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc));
+
+        /* nothing to be done here */
+
+        /* Register platform device */
+	return platform_device_register(&excite_nandflash_pdev);
+}
+
+device_initcall(excite_nandflash_devinit);
+
+
+
+static struct resource iodev_rsrc[] = {
+	RINIT_IRQ(FPGA1_IRQ,  IODEV_RESOURCE_IRQ)
+};
+
+static struct platform_device io_pdev = {
+	.name		= IODEV_NAME,
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(iodev_rsrc),
+	.resource	= iodev_rsrc
+};
+
+/*
+ * Create a platform device for the external I/O ports.
+ */
+static int __init io_devinit(void)
+{
+	adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc));
+	return platform_device_register(&io_pdev);
+}
+
+device_initcall(io_devinit);
+
+
+
+
+#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE)
+static struct resource rm9k_ge_rsrc[] = {
+	RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource),
+	RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource),
+	RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource),
+	RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource),
+	RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource),
+	RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource),
+	RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource),
+	RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource),
+	RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource),
+	RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource),
+	RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource),
+	RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource),
+	RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource),
+	RINIT_IRQ(TITAN_IRQ,  RM9K_GE_RESOURCE_IRQ_MAIN),
+	RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY)
+};
+
+static struct platform_device rm9k_ge_pdev = {
+	.name		= RM9K_GE_NAME,
+	.id		= RM9K_GE_UNIT,
+	.num_resources	= ARRAY_SIZE(rm9k_ge_rsrc),
+	.resource	= rm9k_ge_rsrc
+};
+
+
+
+/*
+ * Create a platform device for the Ethernet port.
+ */
+static int __init rm9k_ge_devinit(void)
+{
+	u32 reg;
+
+	adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc));
+
+	/* Power up the slice and configure it. */
+	reg = titan_readl(CPTC1R);
+	reg &= ~(0x11000 << slice_eth);
+	reg |= 0x100 << slice_eth;
+	titan_writel(reg, CPTC1R);
+
+	/* Take the MAC out of reset, reset the DLLs. */
+	reg = titan_readl(CPRR);
+	reg &= ~(0x00030000 << (slice_eth * 2));
+	reg |= 0x3 << (slice_eth * 2);
+	titan_writel(reg, CPRR);
+
+	return platform_device_register(&rm9k_ge_pdev);
+}
+
+device_initcall(rm9k_ge_devinit);
+#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */
+
+
+
+static int __init excite_setup_devs(void)
+{
+	int res;
+	u32 reg;
+
+	/* Enable xdma and fifo interrupts */
+	reg = titan_readl(0x0050);
+	titan_writel(reg | 0x18000000, 0x0050);
+
+	res = request_resource(&iomem_resource, &excite_titan_resource);
+	if (res)
+		return res;
+	res = request_resource(&iomem_resource, &excite_scram_resource);
+	if (res)
+		return res;
+	res = request_resource(&iomem_resource, &excite_fpga_resource);
+	if (res)
+		return res;
+	res = request_resource(&iomem_resource, &excite_nand_resource);
+	if (res)
+		return res;
+	excite_fpga_resource.flags = excite_fpga_resource.parent->flags &
+				   ( IORESOURCE_IO | IORESOURCE_MEM
+				   | IORESOURCE_IRQ | IORESOURCE_DMA);
+	excite_nand_resource.flags = excite_nand_resource.parent->flags &
+				   ( IORESOURCE_IO | IORESOURCE_MEM
+				   | IORESOURCE_IRQ | IORESOURCE_DMA);
+
+	return 0;
+}
+
+arch_initcall(excite_setup_devs);
+
diff --git a/arch/mips/basler/excite/excite_flashtest.c b/arch/mips/basler/excite/excite_flashtest.c
new file mode 100644
index 0000000..f0024a8
--- /dev/null
+++ b/arch/mips/basler/excite/excite_flashtest.c
@@ -0,0 +1,294 @@
+/*
+*  Copyright (C) 2005 by Basler Vision Technologies AG
+*  Author: Thies Moeller <thies.moeller@baslerweb.com>
+*
+*  This program is free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  This program is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+
+#include <excite.h>
+
+#include <asm/io.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <asm/rm9k-ocd.h> // for ocd_write
+#include <linux/workqueue.h> // for queue
+
+#include "excite_nandflash.h"
+#include "nandflash.h"
+
+#define PFX "excite flashtest: "
+typedef void __iomem *io_reg_t;
+
+#define io_readb(__a__)		__raw_readb((__a__))
+#define io_writeb(__v__, __a__)	__raw_writeb((__v__), (__a__))
+
+
+
+static inline const struct resource *excite_nandflash_get_resource(
+	struct platform_device *d, unsigned long flags, const char *basename)
+{
+	const char fmt[] = "%s_%u";
+	char buf[80];
+
+	if (unlikely(snprintf(buf, sizeof buf, fmt, basename, d->id) >= sizeof buf))
+		return NULL;
+
+	return platform_get_resource_byname(d, flags, buf);
+}
+
+static inline io_reg_t
+excite_nandflash_map_regs(struct platform_device *d, const char *basename)
+{
+	void *result = NULL;
+	const struct resource *const r =
+	    excite_nandflash_get_resource(d, IORESOURCE_MEM, basename);
+	if (r)
+	   result = ioremap_nocache(r->start, r->end + 1 - r->start);
+	return result;
+}
+
+/* controller and mtd information */
+
+struct excite_nandflash_drvdata {
+	struct mtd_info board_mtd;
+	struct nand_chip board_chip;
+	io_reg_t regs;
+};
+
+
+/* command and control functions */
+static void excite_nandflash_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+	struct nand_chip *this = mtd->priv;
+	io_reg_t regs = container_of(mtd,struct excite_nandflash_drvdata,board_mtd)->regs;
+
+	switch (cmd) {
+	/* Select the command latch */
+	case NAND_CTL_SETCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_CMD;
+		break;
+	/* Deselect the command latch */
+	case NAND_CTL_CLRCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA;
+		break;
+	/* Select the address latch */
+	case NAND_CTL_SETALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_ADDR;
+		break;
+	/* Deselect the address latch */
+	case NAND_CTL_CLRALE: this->IO_ADDR_W = regs  + EXCITE_NANDFLASH_DATA;
+		break;
+	/* Select the chip  -- not used */
+	case NAND_CTL_SETNCE:
+		break;
+	/* Deselect the chip -- not used */
+	case NAND_CTL_CLRNCE:
+		break;
+	}
+
+	this->IO_ADDR_R = this->IO_ADDR_W;
+}
+
+/* excite_nandflash_devready()
+ *
+ * returns 0 if the nand is busy, 1 if it is ready
+ */
+static int excite_nandflash_devready(struct mtd_info *mtd)
+{
+	struct excite_nandflash_drvdata *drvdata =
+	    container_of(mtd, struct excite_nandflash_drvdata, board_mtd);
+
+	return io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+}
+
+/* device management functions */
+
+/* excite_nandflash_remove
+ *
+ * called by device layer to remove the driver
+ * the binding to the mtd and all allocated
+ * resources are released
+ */
+static int excite_nandflash_remove(struct device *dev)
+{
+	struct excite_nandflash_drvdata *this = dev_get_drvdata(dev);
+
+	pr_info(PFX "remove");
+
+	dev_set_drvdata(dev, NULL);
+
+	if (this == NULL) {
+		pr_debug(PFX "call remove without private data!!");
+		return 0;
+	}
+
+
+	/* free the common resources */
+	if (this->regs != NULL) {
+		iounmap(this->regs);
+		this->regs = NULL;
+	}
+
+	kfree(this);
+
+	return 0;
+}
+
+static int elapsed;
+
+void my_workqueue_handler(void *arg)
+{
+	elapsed = 1;
+}
+
+DECLARE_WORK(sigElapsed, my_workqueue_handler, 0);
+
+
+/* excite_nandflash_probe
+ *
+ * called by device layer when it finds a device matching
+ * one our driver can handled. This code checks to see if
+ * it can allocate all necessary resources then calls the
+ * nand layer to look for devices
+*/
+static int excite_nandflash_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+
+	struct excite_nandflash_drvdata *drvdata;	    /* private driver data     */
+	struct nand_chip              *board_chip;  /* private flash chip data */
+	struct mtd_info               *board_mtd;   /* mtd info for this board */
+
+	int err      = 0;
+	int count    = 0;
+	struct timeval tv,endtv;
+	unsigned int dt;
+
+	pr_info(PFX "probe dev: (%p)\n", dev);
+
+	pr_info(PFX "adjust LB timing\n");
+	ocd_writel(0x00000330, LDP2);
+
+	drvdata = kmalloc(sizeof(*drvdata), GFP_KERNEL);
+	if (unlikely(!drvdata)) {
+		printk(KERN_ERR PFX "no memory for drvdata\n");
+		err = -ENOMEM;
+		goto mem_error;
+	}
+
+	/* Initialize structures */
+	memset(drvdata, 0, sizeof(*drvdata));
+
+	/* bind private data into driver */
+	dev_set_drvdata(dev, drvdata);
+
+	/* allocate and map the resource */
+	drvdata->regs =
+	    excite_nandflash_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS);
+
+	if (unlikely(!drvdata->regs)) {
+		printk(KERN_ERR PFX "cannot reserve register region\n");
+		err = -ENXIO;
+		goto io_error;
+	}
+
+	/* initialise our chip */
+	board_chip = &drvdata->board_chip;
+
+	board_chip->IO_ADDR_R = drvdata->regs + EXCITE_NANDFLASH_DATA;
+	board_chip->IO_ADDR_W = drvdata->regs + EXCITE_NANDFLASH_DATA;
+
+	board_chip->hwcontrol = excite_nandflash_hwcontrol;
+	board_chip->dev_ready = excite_nandflash_devready;
+
+	board_chip->chip_delay = 25;
+	#if 0
+	/* TODO: speedup the initial scan */
+	board_chip->options = NAND_USE_FLASH_BBT;
+	#endif
+	board_chip->eccmode = NAND_ECC_SOFT;
+
+	/* link chip to mtd */
+	board_mtd = &drvdata->board_mtd;
+	board_mtd->priv = board_chip;
+
+
+	pr_info(PFX "FlashTest\n");
+	elapsed = 0;
+/*	schedule_delayed_work(&sigElapsed, 1*HZ);
+	while (!elapsed) {
+		io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+		count++;
+	}
+	pr_info(PFX "reads in 1 sec --> %d\n",count);
+*/
+	do_gettimeofday(&tv);
+	for (count = 0 ; count < 1000000; count ++) {
+		io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS);
+	}
+	do_gettimeofday(&endtv);
+	dt = (endtv.tv_sec - tv.tv_sec) * 1000000 + endtv.tv_usec  - tv.tv_usec;
+	pr_info(PFX "%8d us timeval\n",dt);
+	pr_info(PFX "EndFlashTest\n");
+
+/*      return with error to unload everything
+*/
+io_error:
+	iounmap(drvdata->regs);
+
+mem_error:
+	kfree(drvdata);
+
+	if (err == 0)
+		err = -EINVAL;
+	return err;
+}
+
+static struct device_driver excite_nandflash_driver = {
+	.name = "excite_nand",
+	.bus = &platform_bus_type,
+	.probe = excite_nandflash_probe,
+	.remove = excite_nandflash_remove,
+};
+
+static int __init excite_nandflash_init(void)
+{
+	pr_info(PFX "register Driver (Rev: $Revision:$)\n");
+	return driver_register(&excite_nandflash_driver);
+}
+
+static void __exit excite_nandflash_exit(void)
+{
+	driver_unregister(&excite_nandflash_driver);
+	pr_info(PFX "Driver unregistered");
+}
+
+module_init(excite_nandflash_init);
+module_exit(excite_nandflash_exit);
+
+MODULE_AUTHOR("Thies Moeller <thies.moeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h
new file mode 100644
index 0000000..38fcda7
--- /dev/null
+++ b/arch/mips/basler/excite/excite_fpga.h
@@ -0,0 +1,80 @@
+#ifndef EXCITE_FPGA_H_INCLUDED
+#define EXCITE_FPGA_H_INCLUDED
+
+
+/**
+ * Adress alignment of the individual FPGA bytes.
+ * The address arrangement of the individual bytes of the FPGA is two
+ * byte aligned at the embedded MK2 platform.
+ */
+#ifdef EXCITE_CCI_FPGA_MK2
+typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2)));
+#else
+typedef unsigned char excite_cci_fpga_align_t;
+#endif
+
+
+/**
+ * Size of Dual Ported RAM.
+ */
+#define EXCITE_DPR_SIZE 263
+
+
+/**
+ * Size of Reserved Status Fields in Dual Ported RAM.
+ */
+#define EXCITE_DPR_STATUS_SIZE 7
+
+
+
+/**
+ * FPGA.
+ * Hardware register layout of the FPGA interface. The FPGA must accessed
+ * byte wise solely.
+ * @see EXCITE_CCI_DPR_MK2
+ */
+typedef struct excite_fpga {
+
+	/**
+	 * Dual Ported RAM.
+	 */
+	excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE];
+
+	/**
+	 * Status.
+	 */
+	excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE];
+
+#ifdef EXCITE_CCI_FPGA_MK2
+	/**
+	 * RM9000 Interrupt.
+	 * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite.
+	 */
+	excite_cci_fpga_align_t rm9k_int;
+#else
+	/**
+	 * MK2 Interrupt.
+	 * Write access initiates interrupt at the ARM processor of the MK2.
+	 */
+	excite_cci_fpga_align_t mk2_int;
+
+	excite_cci_fpga_align_t gap[0x1000-0x10f];
+
+	/**
+	 * IRQ Source/Acknowledge.
+	 */
+	excite_cci_fpga_align_t rm9k_irq_src;
+
+	/**
+	 * IRQ Mask.
+	 * Set bits enable the related interrupt.
+	 */
+	excite_cci_fpga_align_t rm9k_irq_mask;
+#endif
+
+
+} excite_fpga;
+
+
+
+#endif	/* ndef EXCITE_FPGA_H_INCLUDED */
diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c
new file mode 100644
index 0000000..91121e5
--- /dev/null
+++ b/arch/mips/basler/excite/excite_iodev.c
@@ -0,0 +1,183 @@
+/*
+ *  Copyright (C) 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+
+#include "excite_iodev.h"
+
+
+
+static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int);
+static int __init iodev_probe(struct device *);
+static int __exit iodev_remove(struct device *);
+static int iodev_open(struct inode *, struct file *);
+static int iodev_release(struct inode *, struct file *);
+static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *);
+static unsigned int iodev_poll(struct file *, struct poll_table_struct *);
+static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *);
+
+
+
+static const char iodev_name[] = "iodev";
+static unsigned int iodev_irq;
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+
+
+static struct file_operations fops =
+{
+	.owner		= THIS_MODULE,
+	.open		= iodev_open,
+	.release	= iodev_release,
+	.read		= iodev_read,
+	.poll		= iodev_poll
+};
+
+static struct miscdevice miscdev =
+{
+	.minor		= MISC_DYNAMIC_MINOR,
+	.name		= iodev_name,
+	.fops		= &fops
+};
+
+static struct device_driver iodev_driver =
+{
+	.name		= (char *) iodev_name,
+	.bus		= &platform_bus_type,
+	.owner		= THIS_MODULE,
+	.probe		= iodev_probe,
+	.remove		= __exit_p(iodev_remove)
+};
+
+
+
+static const struct resource *
+iodev_get_resource(struct platform_device *pdv, const char *name,
+		     unsigned int type)
+{
+	char buf[80];
+	if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf)
+		return NULL;
+	return platform_get_resource_byname(pdv, type, buf);
+}
+
+
+
+/* No hotplugging on the platform bus - use __init */
+static int __init iodev_probe(struct device *dev)
+{
+	struct platform_device * const pdv = to_platform_device(dev);
+	const struct resource * const ri =
+		iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ);
+
+	if (unlikely(!ri))
+		return -ENXIO;
+
+	iodev_irq = ri->start;
+	return misc_register(&miscdev);
+}
+
+
+
+static int __exit iodev_remove(struct device *dev)
+{
+	return misc_deregister(&miscdev);
+}
+
+
+
+static int iodev_open(struct inode *i, struct file *f)
+{
+	return request_irq(iodev_irq, iodev_irqhdl, SA_INTERRUPT,
+			   iodev_name, &miscdev);
+}
+
+
+
+static int iodev_release(struct inode *i, struct file *f)
+{
+	free_irq(iodev_irq, &miscdev);
+	return 0;
+}
+
+
+
+
+static ssize_t
+iodev_read(struct file *f, char __user *d, size_t s, loff_t *o)
+{
+	ssize_t ret;
+	DEFINE_WAIT(w);
+
+	prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE);
+	if (!signal_pending(current))
+		schedule();
+	ret = signal_pending(current) ? -ERESTARTSYS : 0;
+	finish_wait(&wq, &w);
+	return ret;
+}
+
+
+static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p)
+{
+	poll_wait(f, &wq, p);
+	return POLLOUT | POLLWRNORM;
+}
+
+
+
+
+static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs)
+{
+	wake_up(&wq);
+	return IRQ_HANDLED;
+}
+
+
+
+static int __init iodev_init_module(void)
+{
+	return driver_register(&iodev_driver);
+}
+
+
+
+static void __exit iodev_cleanup_module(void)
+{
+	driver_unregister(&iodev_driver);
+}
+
+module_init(iodev_init_module);
+module_exit(iodev_cleanup_module);
+
+
+
+MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>");
+MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler");
+MODULE_VERSION("0.0");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h
new file mode 100644
index 0000000..cbfbb5d
--- /dev/null
+++ b/arch/mips/basler/excite/excite_iodev.h
@@ -0,0 +1,10 @@
+#ifndef __EXCITE_IODEV_H__
+#define __EXCITE_IODEV_H__
+
+/* Device name */
+#define IODEV_NAME		"iodev"
+
+/* Resource names */
+#define IODEV_RESOURCE_IRQ	"excite_iodev_irq"
+
+#endif /* __EXCITE_IODEV_H__ */
diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c
new file mode 100644
index 0000000..511ad87
--- /dev/null
+++ b/arch/mips/basler/excite/excite_irq.c
@@ -0,0 +1,129 @@
+/*
+ *  Copyright (C) by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslereb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+extern asmlinkage void excite_handle_int(void);
+
+/*
+ * Initialize the interrupt handler
+ */
+void __init arch_init_irq(void)
+{
+	mips_cpu_irq_init(0);
+	rm7k_cpu_irq_init(8);
+	rm9k_cpu_irq_init(12);
+
+#ifdef CONFIG_KGDB
+	excite_kgdb_init();
+#endif
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	const u32
+		interrupts = read_c0_cause() >> 8,
+		mask = ((read_c0_status() >> 8) & 0x000000ff) |
+		       (read_c0_intcontrol() & 0x0000ff00),
+		pending = interrupts & mask;
+	u32 msgintflags, msgintmask, msgint;
+
+	/* process timer interrupt */
+	if (pending & (1 << TIMER_IRQ)) {
+		do_IRQ(TIMER_IRQ, regs);
+		return;
+	}
+
+	/* Process PCI interrupts */
+#if USB_IRQ < 10
+	msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10));
+	msgintmask  = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10));
+	msgint	    = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20));
+	if ((pending & (1 << USB_IRQ)) && msgint) {
+#else
+	if (pending & (1 << USB_IRQ)) {
+#endif
+		do_IRQ(USB_IRQ, regs);
+		return;
+	}
+
+	/* Process TITAN interrupts */
+	msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10));
+	msgintmask  = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10));
+	msgint	    = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20));
+	if ((pending & (1 << TITAN_IRQ)) && msgint) {
+		ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10));
+#if defined(CONFIG_KGDB)
+		excite_kgdb_inthdl(regs);
+#endif
+		do_IRQ(TITAN_IRQ, regs);
+		return;
+	}
+
+	/* Process FPGA line #0 interrupts */
+	msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10));
+	msgintmask  = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10));
+	msgint	    = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20));
+	if ((pending & (1 << FPGA0_IRQ)) && msgint) {
+		do_IRQ(FPGA0_IRQ, regs);
+		return;
+	}
+
+	/* Process FPGA line #1 interrupts */
+	msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10));
+	msgintmask  = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10));
+	msgint	    = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20));
+	if ((pending & (1 << FPGA1_IRQ)) && msgint) {
+		do_IRQ(FPGA1_IRQ, regs);
+		return;
+	}
+
+	/* Process PHY interrupts */
+	msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10));
+	msgintmask  = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10));
+	msgint	    = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20));
+	if ((pending & (1 << PHY_IRQ)) && msgint) {
+		do_IRQ(PHY_IRQ, regs);
+		return;
+	}
+
+	/* Process spurious interrupts */
+	spurious_interrupt(regs);
+}
diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c
new file mode 100644
index 0000000..c62be03
--- /dev/null
+++ b/arch/mips/basler/excite/excite_procfs.c
@@ -0,0 +1,81 @@
+/*
+ *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  Procfs support for Basler eXcite
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size)
+{
+	const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id);
+	const int w = len - offs;
+	*addr = buf + offs;
+	return w < size ? w : size;
+}
+
+static int
+excite_bootrom_read(char *page, char **start, off_t off, int count,
+		  int *eof, void *data)
+{
+	void __iomem * src;
+
+	if (off >= EXCITE_SIZE_BOOTROM) {
+		*eof = 1;
+		return 0;
+	}
+
+	if ((off + count) > EXCITE_SIZE_BOOTROM)
+		count = EXCITE_SIZE_BOOTROM - off;
+
+	src = ioremap(EXCITE_PHYS_BOOTROM + off, count);
+	if (src) {
+		memcpy_fromio(page, src, count);
+		iounmap(src);
+		*start = page;
+	} else {
+		count = -ENOMEM;
+	}
+
+	return count;
+}
+
+void excite_procfs_init(void)
+{
+	/* Create & populate /proc/excite */
+	struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root);
+	if (pdir) {
+		struct proc_dir_entry * e;
+
+		e = create_proc_info_entry("unit_id", S_IRUGO, pdir,
+					   excite_get_unit_id);
+		if (e) e->size = 6;
+
+		e = create_proc_read_entry("bootrom", S_IRUGO, pdir,
+					   excite_bootrom_read, NULL);
+		if (e) e->size = EXCITE_SIZE_BOOTROM;
+	}
+}
diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c
new file mode 100644
index 0000000..84724b2
--- /dev/null
+++ b/arch/mips/basler/excite/excite_prom.c
@@ -0,0 +1,148 @@
+/*
+ *  Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com)
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
+ *  Manish Lachwani.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/bootinfo.h>
+#include <asm/string.h>
+
+#include <excite.h>
+
+/* This struct is used by Redboot to pass arguments to the kernel */
+typedef struct
+{
+	char *name;
+	char *val;
+} t_env_var;
+
+struct parmblock {
+	t_env_var memsize;
+	t_env_var modetty0;
+	t_env_var ethaddr;
+	t_env_var env_end;
+	char *argv[2];
+	char text[0];
+};
+
+static unsigned int prom_argc;
+static const char ** prom_argv;
+static const t_env_var * prom_env;
+
+static void prom_halt(void) __attribute__((noreturn));
+static void prom_exit(void) __attribute__((noreturn));
+
+
+
+const char *get_system_type(void)
+{
+	return "Basler eXcite";
+}
+
+/*
+ * Halt the system
+ */
+static void prom_halt(void)
+{
+	printk(KERN_NOTICE "\n** System halted.\n");
+	while (1)
+		asm volatile (
+			"\t.set\tmips3\n"
+			"\twait\n"
+			"\t.set\tmips0\n"
+		);
+}
+
+/*
+ * Reset the CPU and re-enter Redboot
+ */
+static void prom_exit(void)
+{
+	unsigned int i;
+	volatile unsigned char * const flg =
+		(volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR);
+
+	/* Clear the watchdog reset flag, set the reboot flag */
+	*flg &= ~0x01;
+	*flg |= 0x80;
+
+	for (i = 0; i < 10; i++) {
+		*(volatile unsigned char *)  (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02;
+		iob();
+		mdelay(1000);
+	}
+
+	printk(KERN_NOTICE "Reset failed\n");
+	prom_halt();
+}
+
+static const char __init *prom_getenv(char *name)
+{
+	const t_env_var * p;
+	for (p = prom_env; p->name != NULL; p++)
+		if(strcmp(name, p->name) == 0)
+			break;
+	return p->val;
+}
+
+/*
+ * Init routine which accepts the variables from Redboot
+ */
+void __init prom_init(void)
+{
+	const struct parmblock * const pb = (struct parmblock *) fw_arg2;
+
+	prom_argc = fw_arg0;
+	prom_argv = (const char **) fw_arg1;
+	prom_env = &pb->memsize;
+
+	/* Callbacks for halt, restart */
+	_machine_restart = (void (*)(char *)) prom_exit;
+	_machine_halt = prom_halt;
+
+#ifdef CONFIG_32BIT
+	/* copy command line */
+	strcpy(arcs_cmdline, prom_argv[1]);
+	memsize = simple_strtol(prom_getenv("memsize"), NULL, 16);
+	strcpy(modetty, prom_getenv("modetty0"));
+#endif /* CONFIG_32BIT */
+
+#ifdef CONFIG_64BIT
+#	error 64 bit support not implemented
+#endif /* CONFIG_64BIT */
+
+	mips_machgroup = MACH_GROUP_TITAN;
+	mips_machtype = MACH_TITAN_EXCITE;
+}
+
+/* This is called from free_initmem(), so we need to provide it */
+void __init prom_free_prom_memory(void)
+{
+	/* Nothing to do */
+}
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
new file mode 100644
index 0000000..005b025
--- /dev/null
+++ b/arch/mips/basler/excite/excite_setup.c
@@ -0,0 +1,307 @@
+/*
+ *  Copyright (C) 2004, 2005 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle and
+ *  Manish Lachwani.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable-32.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/rm9k-ocd.h>
+
+#include <excite.h>
+
+#define TITAN_UART_CLK	25000000
+
+#if 1
+/* normal serial port assignment */
+#define REGBASE_SER0	0x0208
+#define REGBASE_SER1	0x0238
+#define MASK_SER0	0x1
+#define MASK_SER1	0x2
+#else
+/* serial ports swapped */
+#define REGBASE_SER0	0x0238
+#define REGBASE_SER1	0x0208
+#define MASK_SER0	0x2
+#define MASK_SER1	0x1
+#endif
+
+unsigned long memsize;
+char modetty[30];
+unsigned int titan_irq = TITAN_IRQ;
+static void __iomem * ctl_regs;
+u32 unit_id;
+
+volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD);
+volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN);
+
+/* Protect access to shared GPI registers */
+spinlock_t titan_lock = SPIN_LOCK_UNLOCKED;
+int titan_irqflags;
+
+
+static void excite_timer_init(void)
+{
+	const u32 modebit5 = ocd_readl(0x00e4);
+	unsigned int
+		mult = ((modebit5 >> 11) & 0x1f) + 2,
+		div = ((modebit5 >> 16) & 0x1f) + 2;
+
+	if (div == 33) div = 1;
+	mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2;
+}
+
+static void excite_timer_setup(struct irqaction *irq)
+{
+	/* The eXcite platform uses the alternate timer interrupt */
+	set_c0_intcontrol(0x80);
+	setup_irq(TIMER_IRQ, irq);
+}
+
+static int __init excite_init_console(void)
+{
+#if defined(CONFIG_SERIAL_8250)
+	static __initdata char serr[] =
+		KERN_ERR "Serial port #%u setup failed\n";
+	struct uart_port up;
+
+	/* Take the DUART out of reset */
+	titan_writel(0x00ff1cff, CPRR);
+
+#if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1)
+	/* Enable both ports */
+	titan_writel(MASK_SER0 | MASK_SER1, UACFG);
+#else
+	/* Enable port #0 only */
+	titan_writel(MASK_SER0, UACFG);
+#endif	/* defined(CONFIG_KGDB) */
+
+ 	/*
+	 * Set up serial port #0. Do not use autodetection; the result is
+	 * not what we want.
+ 	 */
+	memset(&up, 0, sizeof(up));
+	up.membase	= (char *) titan_addr(REGBASE_SER0);
+	up.irq		= TITAN_IRQ;
+	up.uartclk	= TITAN_UART_CLK;
+	up.regshift	= 0;
+	up.iotype	= UPIO_MEM32;
+	up.type		= PORT_RM9000;
+	up.flags	= UPF_SHARE_IRQ;
+	up.line		= 0;
+	if (early_serial_setup(&up))
+		printk(serr, up.line);
+
+#if CONFIG_SERIAL_8250_NR_UARTS > 1
+	/* And now for port #1. */
+	up.membase	= (char *) titan_addr(REGBASE_SER1);
+	up.line		= 1;
+ 	if (early_serial_setup(&up))
+		printk(serr, up.line);
+#endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */
+#else
+	/* Leave the DUART in reset */
+	titan_writel(0x00ff3cff, CPRR);
+#endif  /* defined(CONFIG_SERIAL_8250) */
+
+	return 0;
+}
+
+static int __init excite_platform_init(void)
+{
+	unsigned int i;
+	unsigned char buf[3];
+	u8 reg;
+	void __iomem * dpr;
+
+	/* BIU buffer allocations */
+	ocd_writel(8, CPURSLMT);	/* CPU */
+	titan_writel(4, CPGRWL);	/* GPI / Ethernet */
+
+	/* Map control registers located in FPGA */
+	ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16);
+	if (!ctl_regs)
+		panic("eXcite: failed to map platform control registers\n");
+	memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf));
+	unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16);
+
+	/* Clear the reboot flag */
+	dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1);
+	reg = __raw_readb(dpr);
+	__raw_writeb(reg & 0x7f, dpr);
+	iounmap(dpr);
+
+	/* Interrupt controller setup */
+	for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) {
+		ocd_writel(0x00000000, i + 0x04);
+		ocd_writel(0xffffffff, i + 0x0c);
+	}
+	ocd_writel(0x2, NMICONFIG);
+
+	ocd_writel(0x1 << (TITAN_MSGINT % 0x20),
+		   INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20)));
+	ocd_writel((0x1 << (FPGA0_MSGINT % 0x20))
+		   | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))),
+		   INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20)));
+	ocd_writel((0x1 << (FPGA1_MSGINT % 0x20))
+		   | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))),
+		   INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20)));
+	ocd_writel((0x1 << (PHY_MSGINT % 0x20))
+		   | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))),
+		   INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20)));
+#if USB_IRQ < 10
+	ocd_writel((0x1 << (USB_MSGINT % 0x20))
+		   | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))),
+		   INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20)));
+#endif
+	/* Enable the packet FIFO, XDMA and XDMA arbiter */
+	titan_writel(0x00ff18ff, CPRR);
+
+	/*
+	 * Set up the PADMUX. Power down all ethernet slices,
+	 * they will be powered up and configured at device startup.
+	 */
+	titan_writel(0x00878206, CPTC1R);
+	titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */
+
+	/* Reset and enable the FIFO block */
+	titan_writel(0x00000001, SDRXFCIE);
+	titan_writel(0x00000001, SDTXFCIE);
+	titan_writel(0x00000100, SDRXFCIE);
+	titan_writel(0x00000000, SDTXFCIE);
+
+	/*
+	 * Initialize the common interrupt shared by all components of
+	 * the GPI/Ethernet subsystem.
+	 */
+	titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0);
+	titan_writel(TITAN_MSGINT, CPCFG1);
+
+	/*
+	 * XDMA configuration.
+	 * In order for the XDMA to be sharable among multiple drivers,
+	 * the setup must be done here in the platform. The reason is that
+	 * this setup can only be done while the XDMA is in reset. If this
+	 * were done in a driver, it would interrupt all other drivers
+	 * using the XDMA.
+	 */
+	titan_writel(0x80021dff, GXCFG);	/* XDMA reset */
+	titan_writel(0x00000000, CPXCISRA);
+	titan_writel(0x00000000, CPXCISRB);	/* clear pending interrupts */
+#if defined (CONFIG_HIGHMEM)
+#	error change for HIGHMEM support!
+#else
+	titan_writel(0x00000000, GXDMADRPFX);	/* buffer address prefix */
+#endif
+	titan_writel(0, GXDMA_DESCADR);
+
+	for (i = 0x5040; i <= 0x5300; i += 0x0040)
+		titan_writel(0x80080000, i);	/* reset channel */
+
+	titan_writel((0x1 << 29)			/* no sparse tx descr. */
+		     | (0x1 << 28)			/* no sparse rx descr. */
+		     | (0x1 << 23) | (0x1 << 24)	/* descriptor coherency */
+		     | (0x1 << 21) | (0x1 << 22)	/* data coherency */
+		     | (0x1 << 17)
+		     | 0x1dff,
+		     GXCFG);
+
+#if defined(CONFIG_SMP)
+#	error No SMP support
+#else
+	/* All interrupts go to core #0 only. */
+	titan_writel(0x1f007fff, CPDST0A);
+	titan_writel(0x00000000, CPDST0B);
+	titan_writel(0x0000ff3f, CPDST1A);
+	titan_writel(0x00000000, CPDST1B);
+	titan_writel(0x00ffffff, CPXDSTA);
+	titan_writel(0x00000000, CPXDSTB);
+#endif
+
+	/* Enable DUART interrupts, disable everything else. */
+	titan_writel(0x04000000, CPGIG0ER);
+	titan_writel(0x000000c0, CPGIG1ER);
+
+	excite_procfs_init();
+	return 0;
+}
+
+void __init plat_setup(void)
+{
+	volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000;
+
+	/* Announce RAM to system */
+	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
+
+	/* Set up timer initialization hooks */
+	board_time_init = excite_timer_init;
+	board_timer_setup = excite_timer_setup;
+
+	/* Set up the peripheral address map */
+	*(boot_ocd_base + (LKB9 / sizeof (u32))) = 0;
+	*(boot_ocd_base + (LKB10 / sizeof (u32))) = 0;
+	*(boot_ocd_base + (LKB11 / sizeof (u32))) = 0;
+	*(boot_ocd_base + (LKB12 / sizeof (u32))) = 0;
+	wmb();
+	*(boot_ocd_base + (LKB0 / sizeof (u32))) = EXCITE_PHYS_OCD >> 4;
+	wmb();
+
+	ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5);
+	ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5);
+	ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13);
+	ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13);
+
+	/* Local bus slot #0 */
+	ocd_writel(0x00040510, LDP0);
+	ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9);
+	ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9);
+
+	/* Local bus slot #2 */
+	ocd_writel(0x00000330, LDP2);
+	ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11);
+	ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11);
+
+	/* Local bus slot #3 */
+	ocd_writel(0x00123413, LDP3);
+	ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12);
+	ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12);
+}
+
+
+
+console_initcall(excite_init_console);
+arch_initcall(excite_platform_init);
+
+EXPORT_SYMBOL(titan_lock);
+EXPORT_SYMBOL(titan_irqflags);
+EXPORT_SYMBOL(titan_irq);
+EXPORT_SYMBOL(ocd_base);
+EXPORT_SYMBOL(titan_base);
diff --git a/arch/mips/cobalt/console.c b/arch/mips/cobalt/console.c
index 45c2d27..300797d 100644
--- a/arch/mips/cobalt/console.c
+++ b/arch/mips/cobalt/console.c
@@ -41,3 +41,8 @@
 
 	printk("Cobalt: early console registered\n");
 }
+
+void __init disable_early_printk(void)
+{
+	unregister_console(&cons_info);
+}
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index 4f9ea12..ca719d6 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -68,19 +68,46 @@
 extern struct pci_ops gt64111_pci_ops;
 
 static struct resource cobalt_mem_resource = {
-	"PCI memory", GT64111_MEM_BASE, GT64111_MEM_END, IORESOURCE_MEM
+	.start	= GT64111_MEM_BASE,
+	.end	= GT64111_MEM_END,
+	.name	= "PCI memory",
+	.flags	= IORESOURCE_MEM
 };
 
 static struct resource cobalt_io_resource = {
-	"PCI I/O", 0x1000, 0xffff, IORESOURCE_IO
+	.start	= 0x1000,
+	.end	= 0xffff,
+	.name	= "PCI I/O",
+	.flags	= IORESOURCE_IO
 };
 
 static struct resource cobalt_io_resources[] = {
-	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
-	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+	{
+		.start	= 0x00,
+		.end	= 0x1f,
+		.name	= "dma1",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x40,
+		.end	= 0x5f,
+		.name	= "timer",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x60,
+		.end	= 0x6f,
+		.name	= "keyboard",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x80,
+		.end	= 0x8f,
+		.name	= "dma page reg",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0xc0,
+		.end	= 0xdf,
+		.name	= "dma2",
+		.flags	= IORESOURCE_BUSY
+	},
 };
 
 #define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource))
@@ -93,7 +120,7 @@
 	.io_offset	= 0 - GT64111_IO_BASE
 };
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	static struct uart_port uart;
 	unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
diff --git a/arch/mips/configs/atlas_defconfig b/arch/mips/configs/atlas_defconfig
index 4b080bc..0cc1b3c 100644
--- a/arch/mips/configs/atlas_defconfig
+++ b/arch/mips/configs/atlas_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -143,6 +141,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig
index d85cda5..dabf90a 100644
--- a/arch/mips/configs/bigsur_defconfig
+++ b/arch/mips/configs/bigsur_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -145,6 +143,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_PREEMPT_NONE=y
diff --git a/arch/mips/configs/capcella_defconfig b/arch/mips/configs/capcella_defconfig
index ca0af16..aeb7be8 100644
--- a/arch/mips/configs/capcella_defconfig
+++ b/arch/mips/configs/capcella_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index 7d269e6..d680d3e 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -129,6 +127,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 579b665..6a7aa40 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index e5eb538..5c2da56 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index a43fb23..85ef90c 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index ad632d8..6f757d8 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 8130e23..da4c7e8 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/ddb5476_defconfig b/arch/mips/configs/ddb5476_defconfig
deleted file mode 100644
index 8d88ac1..0000000
--- a/arch/mips/configs/ddb5476_defconfig
+++ /dev/null
@@ -1,917 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc2
-# Mon Apr 24 14:51:00 2006
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_V2PCI is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-CONFIG_DDB5476=y
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_I8259=y
-# CONFIG_CPU_BIG_ENDIAN is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
-CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_DDB5XXX_COMMON=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-CONFIG_HAVE_STD_PC_SERIAL_PORT=y
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-CONFIG_CPU_R5432=y
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5432=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-# CONFIG_MIPS_MT is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
-CONFIG_RELAY=y
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# Block layer
-#
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_ISA=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-# CONFIG_IPV6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-# CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_IDE_SATA is not set
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEPCI is not set
-# CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=y
-# CONFIG_SCSI is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_DM9000 is not set
-# CONFIG_NET_VENDOR_RACAL is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
-# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
-# CONFIG_NET_PCI is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-# CONFIG_TCG_TPM is not set
-# CONFIG_TELCLOCK is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CFB_FILLRECT is not set
-# CONFIG_FB_CFB_COPYAREA is not set
-# CONFIG_FB_CFB_IMAGEBLIT is not set
-# CONFIG_FB_MACMODES is not set
-CONFIG_FB_FIRMWARE_EDID=y
-# CONFIG_FB_MODE_HELPERS is not set
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_SMIVGX is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-# CONFIG_RTC_CLASS is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-# CONFIG_9P_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-# CONFIG_PROFILING is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
-# CONFIG_UNWIND_INFO is not set
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="ip=any"
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/ddb5477_defconfig b/arch/mips/configs/ddb5477_defconfig
index 8c911b6..c1c6bfe 100644
--- a/arch/mips/configs/ddb5477_defconfig
+++ b/arch/mips/configs/ddb5477_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 CONFIG_DDB5477=y
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -129,6 +127,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/decstation_defconfig b/arch/mips/configs/decstation_defconfig
index d838496..d5d0d3f 100644
--- a/arch/mips/configs/decstation_defconfig
+++ b/arch/mips/configs/decstation_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -128,6 +126,17 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_128=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_128HZ=y
+CONFIG_SYS_SUPPORTS_256HZ=y
+CONFIG_SYS_SUPPORTS_1024HZ=y
+CONFIG_HZ=128
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/e55_defconfig b/arch/mips/configs/e55_defconfig
index 0760f43..439677b 100644
--- a/arch/mips/configs/e55_defconfig
+++ b/arch/mips/configs/e55_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig
new file mode 100644
index 0000000..01f29f4
--- /dev/null
+++ b/arch/mips/configs/emma2rh_defconfig
@@ -0,0 +1,1207 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Sun Jun 18 13:46:53 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_WR_PPMC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+CONFIG_MARKEINS=y
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_EMMA2RH=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_R5000=y
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_R5000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x1e000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+CONFIG_NATSEMI=y
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=m
+CONFIG_GEN_RTC=m
+CONFIG_GEN_RTC_X=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+CONFIG_I2C_DEBUG_CORE=y
+# CONFIG_I2C_DEBUG_ALGO is not set
+CONFIG_I2C_DEBUG_BUS=y
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=m
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFS_DIRECTIO=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT=""
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_FS is not set
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200 mem=192m ip=bootp root=/dev/nfs rw"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/ev64120_defconfig b/arch/mips/configs/ev64120_defconfig
index 7067f60..5248a1d 100644
--- a/arch/mips/configs/ev64120_defconfig
+++ b/arch/mips/configs/ev64120_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/ev96100_defconfig b/arch/mips/configs/ev96100_defconfig
index 00b56ed..4858491 100644
--- a/arch/mips/configs/ev96100_defconfig
+++ b/arch/mips/configs/ev96100_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -135,6 +133,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig
new file mode 100644
index 0000000..f2ce64c
--- /dev/null
+++ b/arch/mips/configs/excite_defconfig
@@ -0,0 +1,1220 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16-rc4
+# Thu Feb 23 13:15:27 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+CONFIG_BASLER_EXCITE=y
+# CONFIG_BASLER_EXCITE_PROTOTYPE is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_COHERENT=y
+CONFIG_SERIAL_RM9000=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_IRQ_CPU_RM7K=y
+CONFIG_IRQ_CPU_RM9K=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+CONFIG_CPU_RM9000=y
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_RM9000=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_BASLER_EXCITE=y
+# CONFIG_MTD_NAND_BASLER_EXCITE_RDNBY is not set
+# CONFIG_MTD_NAND_BASLER_EXCITE_PERF is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+
+#
+# Ethernet (10 or 100Mbit)
+#
+# CONFIG_NET_ETHERNET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_TITAN_GE is not set
+CONFIG_RM9K_GE=m
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+# CONFIG_SERIAL_8250_MANY_PORTS is not set
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_WDT_RM9K_GPI=m
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON_OLD is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_SMIVGX is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+CONFIG_FB_DD=y
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=m
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+CONFIG_USB_ARTTFT=m
+# CONFIG_USB_ARTTOUCH is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# EDAC - error detection and reporting (RAS)
+#
+
+#
+# eXcite frame capture support
+#
+CONFIG_EXCITE_FCAP=m
+CONFIG_EXCITE_FCAP_GPI=m
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=m
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=m
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE=""
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig
index 607e298..879ba1a 100644
--- a/arch/mips/configs/ip22_defconfig
+++ b/arch/mips/configs/ip22_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index f724b4b..bb14268 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -63,7 +61,7 @@
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
-# CONFIG_SGI_SN0_N_MODE is not set
+# CONFIG_SGI_SN_N_MODE is not set
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_NUMA=y
 # CONFIG_MAPPED_KERNEL is not set
@@ -135,6 +133,15 @@
 CONFIG_NEED_MULTIPLE_NODES=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_MIGRATION=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=64
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig
index 8f11d35..31b3c92 100644
--- a/arch/mips/configs/ip32_defconfig
+++ b/arch/mips/configs/ip32_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/it8172_defconfig b/arch/mips/configs/it8172_defconfig
index 757adf2..809bae9 100644
--- a/arch/mips/configs/it8172_defconfig
+++ b/arch/mips/configs/it8172_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/ivr_defconfig b/arch/mips/configs/ivr_defconfig
index 021761a..55108fd 100644
--- a/arch/mips/configs/ivr_defconfig
+++ b/arch/mips/configs/ivr_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -127,6 +125,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
index 08f6c30..ef28434 100644
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ b/arch/mips/configs/jaguar-atx_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_SMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 38b1e02..5ef5a08 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -125,6 +123,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/lasat200_defconfig b/arch/mips/configs/lasat200_defconfig
index 4d25990..eabcff2 100644
--- a/arch/mips/configs/lasat200_defconfig
+++ b/arch/mips/configs/lasat200_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index 977f52b..b73cff0 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -154,6 +152,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/mipssim_defconfig b/arch/mips/configs/mipssim_defconfig
index 00560e0..8dd27b5 100644
--- a/arch/mips/configs/mipssim_defconfig
+++ b/arch/mips/configs/mipssim_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -138,6 +136,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index 286a018..5d6ff3c 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/ocelot_3_defconfig b/arch/mips/configs/ocelot_3_defconfig
index 1ce4310..fe5e3dd 100644
--- a/arch/mips/configs/ocelot_3_defconfig
+++ b/arch/mips/configs/ocelot_3_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_SMP is not set
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
diff --git a/arch/mips/configs/ocelot_c_defconfig b/arch/mips/configs/ocelot_c_defconfig
index 8a6aa50..f4a33ce 100644
--- a/arch/mips/configs/ocelot_c_defconfig
+++ b/arch/mips/configs/ocelot_c_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -133,6 +131,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/ocelot_defconfig b/arch/mips/configs/ocelot_defconfig
index f9ee35e..21dea95 100644
--- a/arch/mips/configs/ocelot_defconfig
+++ b/arch/mips/configs/ocelot_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -137,6 +135,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/ocelot_g_defconfig
index b48bdee..c63b1ca 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/ocelot_g_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 01aac40..6f5c726 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -132,6 +130,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 398c3c2..5676f37 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index ea282a5..a1c479f 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -131,6 +129,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/pnx8550-jbs_defconfig b/arch/mips/configs/pnx8550-jbs_defconfig
index 4c57e56..b2d991b 100644
--- a/arch/mips/configs/pnx8550-jbs_defconfig
+++ b/arch/mips/configs/pnx8550-jbs_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 CONFIG_PNX8550_JBS=y
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/pnx8550-v2pci_defconfig b/arch/mips/configs/pnx8550-v2pci_defconfig
index 3c8f351..fe092ac 100644
--- a/arch/mips/configs/pnx8550-v2pci_defconfig
+++ b/arch/mips/configs/pnx8550-v2pci_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 CONFIG_PNX8550_V2PCI=y
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/qemu_defconfig b/arch/mips/configs/qemu_defconfig
index 4bcc01d..db87013 100644
--- a/arch/mips/configs/qemu_defconfig
+++ b/arch/mips/configs/qemu_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -128,6 +126,15 @@
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_SMP is not set
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 3d44193..b16731f 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -138,6 +136,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index edfb967..8b0dd86 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -138,6 +136,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/sb1250-swarm_defconfig b/arch/mips/configs/sb1250-swarm_defconfig
index e388a3d..ff34ed66 100644
--- a/arch/mips/configs/sb1250-swarm_defconfig
+++ b/arch/mips/configs/sb1250-swarm_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -149,6 +147,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PREEMPT_NONE=y
diff --git a/arch/mips/configs/sead_defconfig b/arch/mips/configs/sead_defconfig
index 6b8a6a41..77edeae 100644
--- a/arch/mips/configs/sead_defconfig
+++ b/arch/mips/configs/sead_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index dba0bdc..6aa229d 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0229_defconfig
index 5a924c1..a187b1f 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0229_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -134,6 +132,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
index 9f215ea..258457f 100644
--- a/arch/mips/configs/tb0287_defconfig
+++ b/arch/mips/configs/tb0287_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -135,6 +133,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/workpad_defconfig b/arch/mips/configs/workpad_defconfig
index ac7765e..68af54f 100644
--- a/arch/mips/configs/workpad_defconfig
+++ b/arch/mips/configs/workpad_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 CONFIG_MACH_VR41XX=y
 # CONFIG_PMC_YOSEMITE is not set
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig
new file mode 100644
index 0000000..40572a3
--- /dev/null
+++ b/arch/mips/configs/wrppmc_defconfig
@@ -0,0 +1,808 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16.11
+# Fri May  5 17:11:22 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+CONFIG_WR_PPMC=y
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5477 is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_GT64120=y
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_MIPS32_R1=y
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_VR41XX is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_CPU_MIPS64_R1=y
+CONFIG_SYS_HAS_CPU_NEVADA=y
+CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPSR1=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_CPU_HAS_PREFETCH=y
+# CONFIG_MIPS_MT is not set
+# CONFIG_64BIT_PHYS_ADDR is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_ARPD=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_LAN_SAA9730 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_RTC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="console=ttyS0,115200n8"
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/mips/configs/yosemite_defconfig b/arch/mips/configs/yosemite_defconfig
index b52d709..7ece2c0 100644
--- a/arch/mips/configs/yosemite_defconfig
+++ b/arch/mips/configs/yosemite_defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 CONFIG_PMC_YOSEMITE=y
@@ -130,6 +128,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_PREEMPT_NONE=y
diff --git a/arch/mips/ddb5xxx/common/prom.c b/arch/mips/ddb5xxx/common/prom.c
index b8d1f74..00c62c1 100644
--- a/arch/mips/ddb5xxx/common/prom.c
+++ b/arch/mips/ddb5xxx/common/prom.c
@@ -56,13 +56,7 @@
 
 	mips_machgroup = MACH_GROUP_NEC_DDB;
 
-#if defined(CONFIG_DDB5074)
-	mips_machtype = MACH_NEC_DDB5074;
-	add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
-#elif defined(CONFIG_DDB5476)
-	mips_machtype = MACH_NEC_DDB5476;
-	add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM);
-#elif defined(CONFIG_DDB5477)
+#if defined(CONFIG_DDB5477)
 	ddb5477_runtime_detection();
 	add_memory_region(0, board_ram_size, BOOT_MEM_RAM);
 #endif
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
deleted file mode 100644
index 304c021..0000000
--- a/arch/mips/ddb5xxx/ddb5074/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines
-# under Linux.
-#
-
-obj-y			+= setup.o irq.o nile4_pic.o
-
-EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
deleted file mode 100644
index 60c087b..0000000
--- a/arch/mips/ddb5xxx/ddb5074/irq.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *  arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/i8259.h>
-#include <asm/io.h>
-#include <asm/irq_cpu.h>
-#include <asm/ptrace.h>
-#include <asm/nile4.h>
-#include <asm/ddb5xxx/ddb5xxx.h>
-#include <asm/ddb5xxx/ddb5074.h>
-
-
-static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
-
-#define M1543_PNP_CONFIG	0x03f0	/* PnP Config Port */
-#define M1543_PNP_INDEX		0x03f0	/* PnP Index Port */
-#define M1543_PNP_DATA		0x03f1	/* PnP Data Port */
-
-#define M1543_PNP_ALT_CONFIG	0x0370	/* Alternative PnP Config Port */
-#define M1543_PNP_ALT_INDEX	0x0370	/* Alternative PnP Index Port */
-#define M1543_PNP_ALT_DATA	0x0371	/* Alternative PnP Data Port */
-
-#define M1543_INT1_MASTER_CTRL	0x0020	/* INT_1 (master) Control Register */
-#define M1543_INT1_MASTER_MASK	0x0021	/* INT_1 (master) Mask Register */
-
-#define M1543_INT1_SLAVE_CTRL	0x00a0	/* INT_1 (slave) Control Register */
-#define M1543_INT1_SLAVE_MASK	0x00a1	/* INT_1 (slave) Mask Register */
-
-#define M1543_INT1_MASTER_ELCR	0x04d0	/* INT_1 (master) Edge/Level Control */
-#define M1543_INT1_SLAVE_ELCR	0x04d1	/* INT_1 (slave) Edge/Level Control */
-
-
-static void m1543_irq_setup(void)
-{
-	/*
-	 *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
-	 *  the possible IO sources in the M1543 are in use by us.  We will
-	 *  use the following mapping:
-	 *
-	 *      IRQ1  - keyboard (default set by M1543)
-	 *      IRQ3  - reserved for UART B (default set by M1543) (note that
-	 *              the schematics for the DDB Vrc-5074 board seem to
-	 *              indicate that IRQ3 is connected to the DS1386
-	 *              watchdog timer interrupt output so we might have
-	 *              a conflict)
-	 *      IRQ4  - reserved for UART A (default set by M1543)
-	 *      IRQ5  - parallel (default set by M1543)
-	 *      IRQ8  - DS1386 time of day (RTC) interrupt
-	 *      IRQ12 - mouse
-	 */
-
-	/*
-	 *  Assing mouse interrupt to IRQ12
-	 */
-
-	/* Enter configuration mode */
-	outb(0x51, M1543_PNP_CONFIG);
-	outb(0x23, M1543_PNP_CONFIG);
-
-	/* Select logical device 7 (Keyboard) */
-	outb(0x07, M1543_PNP_INDEX);
-	outb(0x07, M1543_PNP_DATA);
-
-	/* Select IRQ12 */
-	outb(0x72, M1543_PNP_INDEX);
-	outb(0x0c, M1543_PNP_DATA);
-
-	outb(0x30, M1543_PNP_INDEX);
-	printk("device 7, 0x30: %02x\n",inb(M1543_PNP_DATA));
-
-	outb(0x70, M1543_PNP_INDEX);
-	printk("device 7, 0x70: %02x\n",inb(M1543_PNP_DATA));
-
-	/* Leave configration mode */
-	outb(0xbb, M1543_PNP_CONFIG);
-
-
-}
-
-static void ddb_local0_irqdispatch(struct pt_regs *regs)
-{
-	u32 mask;
-	int nile4_irq;
-
-	mask = nile4_get_irq_stat(0);
-
-	/* Handle the timer interrupt first */
-#if 0
-	if (mask & (1 << NILE4_INT_GPT)) {
-		do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs);
-		mask &= ~(1 << NILE4_INT_GPT);
-	}
-#endif
-	for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1)
-		if (mask & 1) {
-			if (nile4_irq == NILE4_INT_INTE) {
-				int i8259_irq;
-
-				nile4_clear_irq(NILE4_INT_INTE);
-				i8259_irq = nile4_i8259_iack();
-				do_IRQ(i8259_irq, regs);
-			} else
-				do_IRQ(nile4_to_irq(nile4_irq), regs);
-
-		}
-}
-
-static void ddb_local1_irqdispatch(void)
-{
-	printk("ddb_local1_irqdispatch called\n");
-}
-
-static void ddb_buserror_irq(void)
-{
-	printk("ddb_buserror_irq called\n");
-}
-
-static void ddb_8254timer_irq(void)
-{
-	printk("ddb_8254timer_irq called\n");
-}
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status();
-
-	if (pending & CAUSEF_IP2)
-		ddb_local0_irqdispatch(regs);
-	else if (pending & CAUSEF_IP3)
-		ddb_local1_irqdispatch();
-	else if (pending & CAUSEF_IP6)
-		ddb_buserror_irq();
-	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
-		ddb_8254timer_irq();
-}
-
-void __init arch_init_irq(void)
-{
-	/* setup cascade interrupts */
-	setup_irq(NILE4_IRQ_BASE  + NILE4_INT_INTE, &irq_cascade);
-	setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
-
-	nile4_irq_setup(NILE4_IRQ_BASE);
-	m1543_irq_setup();
-	init_i8259_irqs();
-
-
-	printk("CPU_IRQ_BASE: %d\n",CPU_IRQ_BASE);
-
-	mips_cpu_irq_init(CPU_IRQ_BASE);
-
-	printk("enabling 8259 cascade\n");
-
-	ddb5074_led_hex(0);
-
-	/* Enable the interrupt cascade */
-	nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE);
-}
diff --git a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
deleted file mode 100644
index 8743ffc..0000000
--- a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- *  arch/mips/ddb5476/nile4.c --
- *  	low-level PIC code for NEC Vrc-5476 (Nile 4)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  Copyright 2001 MontaVista Software Inc.
- *  Author: jsun@mvista.com or jsun@junsun.net
- *
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-
-#include <asm/addrspace.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static int irq_base;
-
-/*
- *  Interrupt Programming
- */
-void nile4_map_irq(int nile4_irq, int cpu_irq)
-{
-	u32 offset, t;
-
-	offset = DDB_INTCTRL;
-	if (nile4_irq >= 8) {
-		offset += 4;
-		nile4_irq -= 8;
-	}
-	t = ddb_in32(offset);
-	t &= ~(7 << (nile4_irq * 4));
-	t |= cpu_irq << (nile4_irq * 4);
-	ddb_out32(offset, t);
-}
-
-void nile4_map_irq_all(int cpu_irq)
-{
-	u32 all, t;
-
-	all = cpu_irq;
-	all |= all << 4;
-	all |= all << 8;
-	all |= all << 16;
-	t = ddb_in32(DDB_INTCTRL);
-	t &= 0x88888888;
-	t |= all;
-	ddb_out32(DDB_INTCTRL, t);
-	t = ddb_in32(DDB_INTCTRL + 4);
-	t &= 0x88888888;
-	t |= all;
-	ddb_out32(DDB_INTCTRL + 4, t);
-}
-
-void nile4_enable_irq(unsigned int nile4_irq)
-{
-	u32 offset, t;
-
-	nile4_irq-=irq_base;
-
-	ddb5074_led_hex(8);
-
-	offset = DDB_INTCTRL;
-	if (nile4_irq >= 8) {
-		offset += 4;
-		nile4_irq -= 8;
-	}
-	ddb5074_led_hex(9);
-	t = ddb_in32(offset);
-	ddb5074_led_hex(0xa);
-	t |= 8 << (nile4_irq * 4);
-	ddb_out32(offset, t);
-	ddb5074_led_hex(0xb);
-}
-
-void nile4_disable_irq(unsigned int nile4_irq)
-{
-	u32 offset, t;
-
-	nile4_irq-=irq_base;
-
-	offset = DDB_INTCTRL;
-	if (nile4_irq >= 8) {
-		offset += 4;
-		nile4_irq -= 8;
-	}
-	t = ddb_in32(offset);
-	t &= ~(8 << (nile4_irq * 4));
-	ddb_out32(offset, t);
-}
-
-void nile4_disable_irq_all(void)
-{
-	ddb_out32(DDB_INTCTRL, 0);
-	ddb_out32(DDB_INTCTRL + 4, 0);
-}
-
-u16 nile4_get_irq_stat(int cpu_irq)
-{
-	return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
-}
-
-void nile4_enable_irq_output(int cpu_irq)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTSTAT1 + 4);
-	t |= 1 << (16 + cpu_irq);
-	ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_disable_irq_output(int cpu_irq)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTSTAT1 + 4);
-	t &= ~(1 << (16 + cpu_irq));
-	ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_set_pci_irq_polarity(int pci_irq, int high)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTPPES);
-	if (high)
-		t &= ~(1 << (pci_irq * 2));
-	else
-		t |= 1 << (pci_irq * 2);
-	ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTPPES);
-	if (level)
-		t |= 2 << (pci_irq * 2);
-	else
-		t &= ~(2 << (pci_irq * 2));
-	ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_clear_irq(int nile4_irq)
-{
-	nile4_irq-=irq_base;
-	ddb_out32(DDB_INTCLR, 1 << nile4_irq);
-}
-
-void nile4_clear_irq_mask(u32 mask)
-{
-	ddb_out32(DDB_INTCLR, mask);
-}
-
-u8 nile4_i8259_iack(void)
-{
-	u8 irq;
-	u32 reg;
-
-	/* Set window 0 for interrupt acknowledge */
-	reg = ddb_in32(DDB_PCIINIT0);
-
-	ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
-	irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
-	/* restore window 0 for PCI I/O space */
-	// ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
-	ddb_out32(DDB_PCIINIT0, reg);
-
-	/* i8269.c set the base vector to be 0x0 */
-	return irq ;
-}
-
-static unsigned int nile4_irq_startup(unsigned int irq) {
-
-	nile4_enable_irq(irq);
-	return 0;
-
-}
-
-static void nile4_ack_irq(unsigned int irq) {
-
-    ddb5074_led_hex(4);
-
-	nile4_clear_irq(irq);
-    ddb5074_led_hex(2);
-	nile4_disable_irq(irq);
-
-    ddb5074_led_hex(0);
-}
-
-static void nile4_irq_end(unsigned int irq) {
-
-	ddb5074_led_hex(3);
-	if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-	ddb5074_led_hex(5);
-		nile4_enable_irq(irq);
-	ddb5074_led_hex(7);
-	}
-
-	ddb5074_led_hex(1);
-}
-
-#define nile4_irq_shutdown nile4_disable_irq
-
-static hw_irq_controller nile4_irq_controller = {
-	.typename = "nile4",
-	.startup = nile4_irq_startup,
-	.shutdown = nile4_irq_shutdown,
-	.enable = nile4_enable_irq,
-	.disable = nile4_disable_irq,
-	.ack = nile4_ack_irq,
-	.end = nile4_irq_end,
-};
-
-void nile4_irq_setup(u32 base) {
-
-	int i;
-
-	irq_base=base;
-
-	/* Map all interrupts to CPU int #0 */
-	nile4_map_irq_all(0);
-
-	/* PCI INTA#-E# must be level triggered */
-	nile4_set_pci_irq_level_or_edge(0, 1);
-	nile4_set_pci_irq_level_or_edge(1, 1);
-	nile4_set_pci_irq_level_or_edge(2, 1);
-	nile4_set_pci_irq_level_or_edge(3, 1);
-	nile4_set_pci_irq_level_or_edge(4, 1);
-
-	/* PCI INTA#-D# must be active low, INTE# must be active high */
-	nile4_set_pci_irq_polarity(0, 0);
-	nile4_set_pci_irq_polarity(1, 0);
-	nile4_set_pci_irq_polarity(2, 0);
-	nile4_set_pci_irq_polarity(3, 0);
-	nile4_set_pci_irq_polarity(4, 1);
-
-
-	for (i = 0; i < 16; i++) {
-		nile4_clear_irq(i);
-		nile4_disable_irq(i);
-	}
-
-	/* Enable CPU int #0 */
-	nile4_enable_irq_output(0);
-
-	for (i= base; i< base + NUM_NILE4_INTERRUPTS; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = NULL;
-		irq_desc[i].depth = 1;
-		irq_desc[i].handler = &nile4_irq_controller;
-	}
-}
-
-#if defined(CONFIG_RUNTIME_DEBUG)
-void nile4_dump_irq_status(void)
-{
-	printk(KERN_DEBUG "
-	       CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
-	       (void *) ddb_in32(DDB_CPUSTAT));
-	printk(KERN_DEBUG "
-	       INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
-	       (void *) ddb_in32(DDB_INTCTRL));
-	printk(KERN_DEBUG
-	       "INTSTAT0 = %p:%p\n",
-	       (void *) ddb_in32(DDB_INTSTAT0 + 4),
-	       (void *) ddb_in32(DDB_INTSTAT0));
-	printk(KERN_DEBUG
-	       "INTSTAT1 = %p:%p\n",
-	       (void *) ddb_in32(DDB_INTSTAT1 + 4),
-	       (void *) ddb_in32(DDB_INTSTAT1));
-	printk(KERN_DEBUG
-	       "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
-	       (void *) ddb_in32(DDB_INTCLR));
-	printk(KERN_DEBUG
-	       "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
-	       (void *) ddb_in32(DDB_INTPPES));
-}
-
-#endif
diff --git a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c
deleted file mode 100644
index 91456b0..0000000
--- a/arch/mips/ddb5xxx/ddb5074/setup.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- *  arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/kernel.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-
-#include <asm/addrspace.h>
-#include <asm/bcache.h>
-#include <asm/irq.h>
-#include <asm/reboot.h>
-#include <asm/gdb-stub.h>
-#include <asm/time.h>
-#include <asm/nile4.h>
-#include <asm/ddb5xxx/ddb5074.h>
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
-
-static void ddb_machine_restart(char *command)
-{
-	u32 t;
-
-	/* PCI cold reset */
-	t = nile4_in32(NILE4_PCICTRL + 4);
-	t |= 0x40000000;
-	nile4_out32(NILE4_PCICTRL + 4, t);
-	/* CPU cold reset */
-	t = nile4_in32(NILE4_CPUSTAT);
-	t |= 1;
-	nile4_out32(NILE4_CPUSTAT, t);
-	/* Call the PROM */
-	back_to_prom();
-}
-
-static void ddb_machine_halt(void)
-{
-	printk("DDB Vrc-5074 halted.\n");
-	do {
-	} while (1);
-}
-
-static void ddb_machine_power_off(void)
-{
-	printk("DDB Vrc-5074 halted. Please turn off the power.\n");
-	do {
-	} while (1);
-}
-
-extern void rtc_ds1386_init(unsigned long base);
-
-extern void (*board_timer_setup) (struct irqaction * irq);
-
-static void __init ddb_timer_init(struct irqaction *irq)
-{
-	/* set the clock to 1 Hz */
-	nile4_out32(NILE4_T2CTRL, 1000000);
-	/* enable the General-Purpose Timer */
-	nile4_out32(NILE4_T2CTRL + 4, 0x00000001);
-	/* reset timer */
-	nile4_out32(NILE4_T2CNTR, 0);
-	/* enable interrupt */
-	setup_irq(nile4_to_irq(NILE4_INT_GPT), irq);
-	nile4_enable_irq(nile4_to_irq(NILE4_INT_GPT));
-	change_c0_status(ST0_IM,
-		          IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
-
-}
-
-static void __init ddb_time_init(void)
-{
-	/* we have ds1396 RTC chip */
-	rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
-}
-
-
-
-void __init plat_setup(void)
-{
-	set_io_port_base(NILE4_PCI_IO_BASE);
-	isa_slot_offset = NILE4_PCI_MEM_BASE;
-	board_timer_setup = ddb_timer_init;
-	board_time_init = ddb_time_init;
-
-
-	_machine_restart = ddb_machine_restart;
-	_machine_halt = ddb_machine_halt;
-	pm_power_off = ddb_machine_power_off;
-
-	ddb_out32(DDB_BAR0, 0);
-
-	ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10);
-	ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10);
-
-	/* Reboot on panic */
-	panic_timeout = 180;
-}
-
-#define USE_NILE4_SERIAL	0
-
-#if USE_NILE4_SERIAL
-#define ns16550_in(reg)		nile4_in8((reg)*8)
-#define ns16550_out(reg, val)	nile4_out8((reg)*8, (val))
-#else
-#define NS16550_BASE		(NILE4_PCI_IO_BASE+0x03f8)
-static inline u8 ns16550_in(u32 reg)
-{
-	return *(volatile u8 *) (NS16550_BASE + reg);
-}
-
-static inline void ns16550_out(u32 reg, u8 val)
-{
-	*(volatile u8 *) (NS16550_BASE + reg) = val;
-}
-#endif
-
-#define NS16550_RBR		0
-#define NS16550_THR		0
-#define NS16550_DLL		0
-#define NS16550_IER		1
-#define NS16550_DLM		1
-#define NS16550_FCR		2
-#define NS16550_IIR		2
-#define NS16550_LCR		3
-#define NS16550_MCR		4
-#define NS16550_LSR		5
-#define NS16550_MSR		6
-#define NS16550_SCR		7
-
-#define NS16550_LSR_DR		0x01	/* Data ready */
-#define NS16550_LSR_OE		0x02	/* Overrun */
-#define NS16550_LSR_PE		0x04	/* Parity error */
-#define NS16550_LSR_FE		0x08	/* Framing error */
-#define NS16550_LSR_BI		0x10	/* Break */
-#define NS16550_LSR_THRE	0x20	/* Xmit holding register empty */
-#define NS16550_LSR_TEMT	0x40	/* Xmitter empty */
-#define NS16550_LSR_ERR		0x80	/* Error */
-
-
-void _serinit(void)
-{
-#if USE_NILE4_SERIAL
-	ns16550_out(NS16550_LCR, 0x80);
-	ns16550_out(NS16550_DLM, 0x00);
-	ns16550_out(NS16550_DLL, 0x36);	/* 9600 baud */
-	ns16550_out(NS16550_LCR, 0x00);
-	ns16550_out(NS16550_LCR, 0x03);
-	ns16550_out(NS16550_FCR, 0x47);
-#else
-	/* done by PMON */
-#endif
-}
-
-void _putc(char c)
-{
-	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-	ns16550_out(NS16550_THR, c);
-	if (c == '\n') {
-		while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE));
-		ns16550_out(NS16550_THR, '\r');
-	}
-}
-
-void _puts(const char *s)
-{
-	char c;
-	while ((c = *s++))
-		_putc(c);
-}
-
-char _getc(void)
-{
-	while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR));
-	return ns16550_in(NS16550_RBR);
-}
-
-int _testc(void)
-{
-	return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0;
-}
-
-
-/*
- *  Hexadecimal 7-segment LED
- */
-void ddb5074_led_hex(int hex)
-{
-	outb(hex, 0x80);
-}
-
-
-/*
- *  LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543
- */
-struct pci_dev *pci_pmu = NULL;
-
-void ddb5074_led_d2(int on)
-{
-	u8 t;
-
-	if (pci_pmu) {
-		pci_read_config_byte(pci_pmu, 0x7e, &t);
-		if (on)
-			t &= 0x7f;
-		else
-			t |= 0x80;
-		pci_write_config_byte(pci_pmu, 0x7e, t);
-	}
-}
-
-void ddb5074_led_d3(int on)
-{
-	u8 t;
-
-	if (pci_pmu) {
-		pci_read_config_byte(pci_pmu, 0x7e, &t);
-		if (on)
-			t &= 0xbf;
-		else
-			t |= 0x40;
-		pci_write_config_byte(pci_pmu, 0x7e, t);
-	}
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
deleted file mode 100644
index ab0312c..0000000
--- a/arch/mips/ddb5xxx/ddb5476/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the NEC DDB Vrc-5476 specific kernel interface routines
-# under Linux.
-#
-
-obj-y			+= setup.o irq.o nile4_pic.o vrc5476_irq.o
-obj-$(CONFIG_KGDB)	+= dbg_io.o
-
-EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/dbg_io.c b/arch/mips/ddb5xxx/ddb5476/dbg_io.c
deleted file mode 100644
index f2296a9..0000000
--- a/arch/mips/ddb5xxx/ddb5476/dbg_io.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * kgdb io functions for DDB5476.  We use the second serial port.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-/* ======================= CONFIG ======================== */
-
-/* [jsun] we use the second serial port for kdb */
-#define         BASE                    0xa60002f8
-#define         MAX_BAUD                115200
-
-/* distance in bytes between two serial registers */
-#define         REG_OFFSET              1
-
-/*
- * 0 - kgdb does serial init
- * 1 - kgdb skip serial init
- */
-static int remoteDebugInitialized = 0;
-
-/*
- * the default baud rate *if* kgdb does serial init
- */
-#define		BAUD_DEFAULT		UART16550_BAUD_38400
-
-/* ======================= END OF CONFIG ======================== */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-#define         UART16550_BAUD_2400             2400
-#define         UART16550_BAUD_4800             4800
-#define         UART16550_BAUD_9600             9600
-#define         UART16550_BAUD_19200            19200
-#define         UART16550_BAUD_38400            38400
-#define         UART16550_BAUD_57600            57600
-#define         UART16550_BAUD_115200           115200
-
-#define         UART16550_PARITY_NONE           0
-#define         UART16550_PARITY_ODD            0x08
-#define         UART16550_PARITY_EVEN           0x18
-#define         UART16550_PARITY_MARK           0x28
-#define         UART16550_PARITY_SPACE          0x38
-
-#define         UART16550_DATA_5BIT             0x0
-#define         UART16550_DATA_6BIT             0x1
-#define         UART16550_DATA_7BIT             0x2
-#define         UART16550_DATA_8BIT             0x3
-
-#define         UART16550_STOP_1BIT             0x0
-#define         UART16550_STOP_2BIT             0x4
-
-/* register offset */
-#define         OFS_RCV_BUFFER          0
-#define         OFS_TRANS_HOLD          0
-#define         OFS_SEND_BUFFER         0
-#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
-#define         OFS_INTR_ID             (2*REG_OFFSET)
-#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
-#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
-#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
-#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
-#define         OFS_LINE_STATUS         (5*REG_OFFSET)
-#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
-#define         OFS_RS232_INPUT         (6*REG_OFFSET)
-#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
-
-#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
-#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
-#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
-        /* disable interrupts */
-        UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
-        /* set up baud rate */
-        {
-                uint32 divisor;
-
-                /* set DIAB bit */
-                UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
-                /* set divisor */
-                divisor = MAX_BAUD / baud;
-                UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
-                UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
-                /* clear DIAB bit */
-                UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-        }
-
-        /* set data format */
-        UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-
-uint8 getDebugChar(void)
-{
-        if (!remoteDebugInitialized) {
-                remoteDebugInitialized = 1;
-                debugInit(BAUD_DEFAULT,
-                          UART16550_DATA_8BIT,
-                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-        }
-
-        while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
-        return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
-        if (!remoteDebugInitialized) {
-                remoteDebugInitialized = 1;
-                debugInit(BAUD_DEFAULT,
-                          UART16550_DATA_8BIT,
-                          UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-        }
-
-        while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
-        UART16550_WRITE(OFS_SEND_BUFFER, byte);
-        return 1;
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
deleted file mode 100644
index 7583a1f..0000000
--- a/arch/mips/ddb5xxx/ddb5476/irq.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- *  arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- * Re-write the whole thing to use new irq.c file.
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- */
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-
-#include <asm/i8259.h>
-#include <asm/io.h>
-#include <asm/ptrace.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-#define M1543_PNP_CONFIG	0x03f0	/* PnP Config Port */
-#define M1543_PNP_INDEX		0x03f0	/* PnP Index Port */
-#define M1543_PNP_DATA		0x03f1	/* PnP Data Port */
-
-#define M1543_PNP_ALT_CONFIG	0x0370	/* Alternative PnP Config Port */
-#define M1543_PNP_ALT_INDEX	0x0370	/* Alternative PnP Index Port */
-#define M1543_PNP_ALT_DATA	0x0371	/* Alternative PnP Data Port */
-
-#define M1543_INT1_MASTER_CTRL	0x0020	/* INT_1 (master) Control Register */
-#define M1543_INT1_MASTER_MASK	0x0021	/* INT_1 (master) Mask Register */
-
-#define M1543_INT1_SLAVE_CTRL	0x00a0	/* INT_1 (slave) Control Register */
-#define M1543_INT1_SLAVE_MASK	0x00a1	/* INT_1 (slave) Mask Register */
-
-#define M1543_INT1_MASTER_ELCR	0x04d0	/* INT_1 (master) Edge/Level Control */
-#define M1543_INT1_SLAVE_ELCR	0x04d1	/* INT_1 (slave) Edge/Level Control */
-
-static void m1543_irq_setup(void)
-{
-	/*
-	 *  The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13.  Not all
-	 *  the possible IO sources in the M1543 are in use by us.  We will
-	 *  use the following mapping:
-	 *
-	 *      IRQ1  - keyboard (default set by M1543)
-	 *      IRQ3  - reserved for UART B (default set by M1543) (note that
-	 *              the schematics for the DDB Vrc-5476 board seem to
-	 *              indicate that IRQ3 is connected to the DS1386
-	 *              watchdog timer interrupt output so we might have
-	 *              a conflict)
-	 *      IRQ4  - reserved for UART A (default set by M1543)
-	 *      IRQ5  - parallel (default set by M1543)
-	 *      IRQ8  - DS1386 time of day (RTC) interrupt
-	 *      IRQ9  - USB (hardwired in ddb_setup)
-	 *      IRQ10 - PMU (hardwired in ddb_setup)
-	 *      IRQ12 - mouse
-	 *      IRQ14,15 - IDE controller (need to be confirmed, jsun)
-	 */
-
-	/*
-	 *  Assing mouse interrupt to IRQ12
-	 */
-
-	/* Enter configuration mode */
-	outb(0x51, M1543_PNP_CONFIG);
-	outb(0x23, M1543_PNP_CONFIG);
-
-	/* Select logical device 7 (Keyboard) */
-	outb(0x07, M1543_PNP_INDEX);
-	outb(0x07, M1543_PNP_DATA);
-
-	/* Select IRQ12 */
-	outb(0x72, M1543_PNP_INDEX);
-	outb(0x0c, M1543_PNP_DATA);
-
-	/* Leave configration mode */
-	outb(0xbb, M1543_PNP_CONFIG);
-}
-
-static void nile4_irq_setup(void)
-{
-	int i;
-
-	/* Map all interrupts to CPU int #0 (IP2) */
-	nile4_map_irq_all(0);
-
-	/* PCI INTA#-E# must be level triggered */
-	nile4_set_pci_irq_level_or_edge(0, 1);
-	nile4_set_pci_irq_level_or_edge(1, 1);
-	nile4_set_pci_irq_level_or_edge(2, 1);
-	nile4_set_pci_irq_level_or_edge(3, 1);
-
-	/* PCI INTA#, B#, D# must be active low, INTC# must be active high */
-	nile4_set_pci_irq_polarity(0, 0);
-	nile4_set_pci_irq_polarity(1, 0);
-	nile4_set_pci_irq_polarity(2, 1);
-	nile4_set_pci_irq_polarity(3, 0);
-
-	for (i = 0; i < 16; i++)
-		nile4_clear_irq(i);
-
-	/* Enable CPU int #0 */
-	nile4_enable_irq_output(0);
-
-	/* memory resource acquire in ddb_setup */
-}
-
-static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
-static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
-
-extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-extern void mips_cpu_irq_init(u32 irq_base);
-extern void vrc5476_irq_init(u32 irq_base);
-
-extern void vrc5476_irq_dispatch(struct pt_regs *regs);
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status();
-
-	if (pending & STATUSF_IP7)
-		do_IRQ(CPU_IRQ_BASE + 7, regs);
-	else if (pending & STATUSF_IP2)
-		vrc5476_irq_dispatch(regs);
-	else if (pending & STATUSF_IP3)
-		do_IRQ(CPU_IRQ_BASE + 3, regs);
-	else if (pending & STATUSF_IP4)
-		do_IRQ(CPU_IRQ_BASE + 4, regs);
-	else if (pending & STATUSF_IP5)
-		do_IRQ(CPU_IRQ_BASE + 5, regs);
-	else if (pending & STATUSF_IP6)
-		do_IRQ(CPU_IRQ_BASE + 6, regs);
-	else if (pending & STATUSF_IP0)
-		do_IRQ(CPU_IRQ_BASE, regs);
-	else if (pending & STATUSF_IP1)
-		do_IRQ(CPU_IRQ_BASE + 1, regs);
-
-	vrc5476_irq_dispatch(regs);
-}
-
-void __init arch_init_irq(void)
-{
-	/* hardware initialization */
-	nile4_irq_setup();
-	m1543_irq_setup();
-
-	/* controller setup */
-	init_i8259_irqs();
-	vrc5476_irq_init(VRC5476_IRQ_BASE);
-	mips_cpu_irq_init(CPU_IRQ_BASE);
-
-	/* setup cascade interrupts */
-	setup_irq(VRC5476_IRQ_BASE + VRC5476_I8259_CASCADE, &irq_cascade);
-	setup_irq(CPU_IRQ_BASE + CPU_VRC5476_CASCADE, &irq_cascade);
-
-	/* setup error interrupts for debugging */
-	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CPCE, &irq_error);
-	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CNTD, &irq_error);
-	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_MCE, &irq_error);
-	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
-	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
-	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c
deleted file mode 100644
index e930cee..0000000
--- a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- *  arch/mips/ddb5476/nile4.c --
- *  	low-level PIC code for NEC Vrc-5476 (Nile 4)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- *
- *  Copyright 2001 MontaVista Software Inc.
- *  Author: jsun@mvista.com or jsun@junsun.net
- *
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-
-/*
- *  Interrupt Programming
- */
-void nile4_map_irq(int nile4_irq, int cpu_irq)
-{
-	u32 offset, t;
-
-	offset = DDB_INTCTRL;
-	if (nile4_irq >= 8) {
-		offset += 4;
-		nile4_irq -= 8;
-	}
-	t = ddb_in32(offset);
-	t &= ~(7 << (nile4_irq * 4));
-	t |= cpu_irq << (nile4_irq * 4);
-	ddb_out32(offset, t);
-}
-
-void nile4_map_irq_all(int cpu_irq)
-{
-	u32 all, t;
-
-	all = cpu_irq;
-	all |= all << 4;
-	all |= all << 8;
-	all |= all << 16;
-	t = ddb_in32(DDB_INTCTRL);
-	t &= 0x88888888;
-	t |= all;
-	ddb_out32(DDB_INTCTRL, t);
-	t = ddb_in32(DDB_INTCTRL + 4);
-	t &= 0x88888888;
-	t |= all;
-	ddb_out32(DDB_INTCTRL + 4, t);
-}
-
-void nile4_enable_irq(int nile4_irq)
-{
-	u32 offset, t;
-
-	offset = DDB_INTCTRL;
-	if (nile4_irq >= 8) {
-		offset += 4;
-		nile4_irq -= 8;
-	}
-	t = ddb_in32(offset);
-	t |= 8 << (nile4_irq * 4);
-	ddb_out32(offset, t);
-}
-
-void nile4_disable_irq(int nile4_irq)
-{
-	u32 offset, t;
-
-	offset = DDB_INTCTRL;
-	if (nile4_irq >= 8) {
-		offset += 4;
-		nile4_irq -= 8;
-	}
-	t = ddb_in32(offset);
-	t &= ~(8 << (nile4_irq * 4));
-	ddb_out32(offset, t);
-}
-
-void nile4_disable_irq_all(void)
-{
-	ddb_out32(DDB_INTCTRL, 0);
-	ddb_out32(DDB_INTCTRL + 4, 0);
-}
-
-u16 nile4_get_irq_stat(int cpu_irq)
-{
-	return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2);
-}
-
-void nile4_enable_irq_output(int cpu_irq)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTSTAT1 + 4);
-	t |= 1 << (16 + cpu_irq);
-	ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_disable_irq_output(int cpu_irq)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTSTAT1 + 4);
-	t &= ~(1 << (16 + cpu_irq));
-	ddb_out32(DDB_INTSTAT1, t);
-}
-
-void nile4_set_pci_irq_polarity(int pci_irq, int high)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTPPES);
-	if (high)
-		t &= ~(1 << (pci_irq * 2));
-	else
-		t |= 1 << (pci_irq * 2);
-	ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_set_pci_irq_level_or_edge(int pci_irq, int level)
-{
-	u32 t;
-
-	t = ddb_in32(DDB_INTPPES);
-	if (level)
-		t |= 2 << (pci_irq * 2);
-	else
-		t &= ~(2 << (pci_irq * 2));
-	ddb_out32(DDB_INTPPES, t);
-}
-
-void nile4_clear_irq(int nile4_irq)
-{
-	ddb_out32(DDB_INTCLR, 1 << nile4_irq);
-}
-
-void nile4_clear_irq_mask(u32 mask)
-{
-	ddb_out32(DDB_INTCLR, mask);
-}
-
-u8 nile4_i8259_iack(void)
-{
-	u8 irq;
-	u32 reg;
-
-	/* Set window 0 for interrupt acknowledge */
-	reg = ddb_in32(DDB_PCIINIT0);
-
-	ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32);
-	irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE);
-	/* restore window 0 for PCI I/O space */
-	// ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
-	ddb_out32(DDB_PCIINIT0, reg);
-
-	/* i8269.c set the base vector to be 0x0 */
-	return irq + I8259_IRQ_BASE;
-}
-
-#if defined(CONFIG_RUNTIME_DEBUG)
-void nile4_dump_irq_status(void)
-{
-	printk(KERN_DEBUG "
-	       CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4),
-	       (void *) ddb_in32(DDB_CPUSTAT));
-	printk(KERN_DEBUG "
-	       INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4),
-	       (void *) ddb_in32(DDB_INTCTRL));
-	printk(KERN_DEBUG
-	       "INTSTAT0 = %p:%p\n",
-	       (void *) ddb_in32(DDB_INTSTAT0 + 4),
-	       (void *) ddb_in32(DDB_INTSTAT0));
-	printk(KERN_DEBUG
-	       "INTSTAT1 = %p:%p\n",
-	       (void *) ddb_in32(DDB_INTSTAT1 + 4),
-	       (void *) ddb_in32(DDB_INTSTAT1));
-	printk(KERN_DEBUG
-	       "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4),
-	       (void *) ddb_in32(DDB_INTCLR));
-	printk(KERN_DEBUG
-	       "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4),
-	       (void *) ddb_in32(DDB_INTPPES));
-}
-#endif
diff --git a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c
deleted file mode 100644
index c902ade..0000000
--- a/arch/mips/ddb5xxx/ddb5476/setup.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- *  arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <linux/init.h>
-#include <linux/kbd_ll.h>
-#include <linux/kernel.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-
-#include <asm/addrspace.h>
-#include <asm/bcache.h>
-#include <asm/irq.h>
-#include <asm/reboot.h>
-#include <asm/gdb-stub.h>
-#include <asm/time.h>
-#include <asm/debug.h>
-#include <asm/traps.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-// #define USE_CPU_COUNTER_TIMER	/* whether we use cpu counter */
-
-#ifdef USE_CPU_COUNTER_TIMER
-
-#define CPU_COUNTER_FREQUENCY           83000000
-#else
-/* otherwise we use general purpose timer */
-#define TIMER_FREQUENCY			83000000
-#define TIMER_BASE			DDB_T2CTRL
-#define TIMER_IRQ			(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT)
-#endif
-
-static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000;
-
-static void ddb_machine_restart(char *command)
-{
-	u32 t;
-
-	/* PCI cold reset */
-	t = ddb_in32(DDB_PCICTRL + 4);
-	t |= 0x40000000;
-	ddb_out32(DDB_PCICTRL + 4, t);
-	/* CPU cold reset */
-	t = ddb_in32(DDB_CPUSTAT);
-	t |= 1;
-	ddb_out32(DDB_CPUSTAT, t);
-	/* Call the PROM */
-	back_to_prom();
-}
-
-static void ddb_machine_halt(void)
-{
-	printk(KERN_NOTICE "DDB Vrc-5476 halted.\n");
-	while (1);
-}
-
-static void ddb_machine_power_off(void)
-{
-	printk(KERN_NOTICE "DDB Vrc-5476 halted. Please turn off the power.\n");
-	while (1);
-}
-
-extern void rtc_ds1386_init(unsigned long base);
-
-static void __init ddb_time_init(void)
-{
-#if defined(USE_CPU_COUNTER_TIMER)
-	mips_hpt_frequency = CPU_COUNTER_FREQUENCY;
-#endif
-
-	/* we have ds1396 RTC chip */
-	rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE));
-}
-
-
-extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
-static void __init ddb_timer_setup(struct irqaction *irq)
-{
-#if defined(USE_CPU_COUNTER_TIMER)
-
-	unsigned int count;
-
-	/* we are using the cpu counter for timer interrupts */
-	setup_irq(CPU_IRQ_BASE + 7, irq);
-
-	/* to generate the first timer interrupt */
-	count = read_c0_count();
-	write_c0_compare(count + 1000);
-
-#else
-
-	ddb_out32(TIMER_BASE, TIMER_FREQUENCY/HZ);
-	ddb_out32(TIMER_BASE+4, 0x1);	/* enable timer */
-	setup_irq(TIMER_IRQ, irq);
-#endif
-}
-
-static struct {
-	struct resource dma1;
-	struct resource timer;
-	struct resource rtc;
-	struct resource dma_page_reg;
-	struct resource dma2;
-} ddb5476_ioport = {
-	{
-	"dma1", 0x00, 0x1f, IORESOURCE_BUSY}, {
-	"timer", 0x40, 0x5f, IORESOURCE_BUSY}, {
-	"rtc", 0x70, 0x7f, IORESOURCE_BUSY}, {
-	"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, {
-	"dma2", 0xc0, 0xdf, IORESOURCE_BUSY}
-};
-
-static struct {
-	struct resource nile4;
-} ddb5476_iomem = {
-	{ "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY}
-};
-
-
-static void ddb5476_board_init(void);
-
-void __init plat_setup(void)
-{
-	set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE));
-
-	board_time_init = ddb_time_init;
-	board_timer_setup = ddb_timer_setup;
-
-	_machine_restart = ddb_machine_restart;
-	_machine_halt = ddb_machine_halt;
-	pm_power_off = ddb_machine_power_off;
-
-	/* request io port/mem resources  */
-	if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) ||
-	    request_resource(&ioport_resource, &ddb5476_ioport.timer) ||
-	    request_resource(&ioport_resource, &ddb5476_ioport.rtc) ||
-	    request_resource(&ioport_resource,
-			     &ddb5476_ioport.dma_page_reg)
-	    || request_resource(&ioport_resource, &ddb5476_ioport.dma2)
-	    || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) {
-		printk
-		    ("ddb_setup - requesting oo port resources failed.\n");
-		for (;;);
-	}
-
-	/* Reboot on panic */
-	panic_timeout = 180;
-
-	/* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */
-	/* *(long*)0xbfa00218 = 0x8; */
-
-	/* board initialization stuff */
-	ddb5476_board_init();
-}
-
-/*
- * We don't trust bios.  We essentially does hardware re-initialization
- * as complete as possible, as far as we know we can safely do.
- */
-static void ddb5476_board_init(void)
-{
-	/* ----------- setup PDARs ------------ */
-	/* check SDRAM0, whether we are on MEM bus does not matter */
-	db_assert((ddb_in32(DDB_SDRAM0) & 0xffffffef) ==
-		  ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1));
-
-	/* SDRAM1 should be turned off.  What is this for anyway ? */
-	db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0);
-
-	/* flash 1&2, DDB status, DDB control */
-	ddb_set_pdar(DDB_DCS2, DDB_DCS2_BASE, DDB_DCS2_SIZE, 16, 0, 0);
-	ddb_set_pdar(DDB_DCS3, DDB_DCS3_BASE, DDB_DCS3_SIZE, 16, 0, 0);
-	ddb_set_pdar(DDB_DCS4, DDB_DCS4_BASE, DDB_DCS4_SIZE, 8, 0, 0);
-	ddb_set_pdar(DDB_DCS5, DDB_DCS5_BASE, DDB_DCS5_SIZE, 8, 0, 0);
-
-	/* shut off other pdar so they don't accidentally get into the way */
-	ddb_set_pdar(DDB_DCS6, 0xffffffff, 0, 32, 0, 0);
-	ddb_set_pdar(DDB_DCS7, 0xffffffff, 0, 32, 0, 0);
-	ddb_set_pdar(DDB_DCS8, 0xffffffff, 0, 32, 0, 0);
-
-	/* verify VRC5477 base addr */
-	/* don't care about some details */
-	db_assert((ddb_in32(DDB_INTCS) & 0xffffff0f) ==
-		  ddb_calc_pdar(DDB_INTCS_BASE, DDB_INTCS_SIZE, 8, 0, 0));
-
-	/* verify BOOT ROM addr */
-	/* don't care about some details */
-	db_assert((ddb_in32(DDB_BOOTCS) & 0xffffff0f) ==
-		  ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0));
-
-	/* setup PCI windows - window1 for MEM/config, window0 for IO */
-	ddb_set_pdar(DDB_PCIW0, DDB_PCI_IO_BASE, DDB_PCI_IO_SIZE, 32, 0, 1);
-	ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32);
-
-	ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
-	ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
-
-	/* ----------- setup PDARs ------------ */
-	/* this is problematic - it will reset Aladin which cause we loose
-	 * serial port, and we don't know how to set up Aladin chip again.
-	 */
-	// ddb_pci_reset_bus();
-
-	ddb_out32(DDB_BAR0, 0x00000008);
-
-	ddb_out32(DDB_BARC, 0xffffffff);
-	ddb_out32(DDB_BARB, 0xffffffff);
-	ddb_out32(DDB_BAR1, 0xffffffff);
-	ddb_out32(DDB_BAR2, 0xffffffff);
-	ddb_out32(DDB_BAR3, 0xffffffff);
-	ddb_out32(DDB_BAR4, 0xffffffff);
-	ddb_out32(DDB_BAR5, 0xffffffff);
-	ddb_out32(DDB_BAR6, 0xffffffff);
-	ddb_out32(DDB_BAR7, 0xffffffff);
-	ddb_out32(DDB_BAR8, 0xffffffff);
-
-	/* ----------- switch PCI1 to PCI CONFIG space  ------------ */
-	ddb_set_pdar(DDB_PCIW1, DDB_PCI_CONFIG_BASE, DDB_PCI_CONFIG_SIZE, 32, 0, 1);
-	ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_CFG, 0x0, DDB_PCI_ACCESS_32);
-
-	/* ----- M1543 PCI setup ------ */
-
-	/* we know M1543 PCI-ISA controller is at addr:18 */
-	/* xxxx1010 makes USB at addr:13 and PMU at addr:14 */
-	*(volatile unsigned char *) 0xa8040072 &= 0xf0;
-	*(volatile unsigned char *) 0xa8040072 |= 0xa;
-
-	/* setup USB interrupt to IRQ 9, (bit 0:3 - 0001)
-	 * no IOCHRDY signal, (bit 7 - 1)
-	 * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1)
-	 * Make USB Master INTAJ level to edge conversion (bit 4 - 1)
-	 */
-	*(unsigned char *) 0xa8040074 = 0xd1;
-
-	/* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011)
-	 * SCI routing to IRQ 13 disabled (bit 7 - 1)
-	 * SCI interrupt level to edge conversion bypassed (bit 4 - 0)
-	 */
-	*(unsigned char *) 0xa8040076 = 0x83;
-
-	/* setup IDE controller
-	 * enable IDE controller (bit 6 - 1)
-	 * IDE IDSEL to be addr:24 (bit 4:5 - 11)
-	 * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0)
-	 * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0)
-	 * primary IRQ is 14, secondary is 15 (bit 1:0 - 01
-	 */
-	// *(unsigned char*)0xa8040058 = 0x71;
-	// *(unsigned char*)0xa8040058 = 0x79;
-	// *(unsigned char*)0xa8040058 = 0x74;              // use SIRQ, primary tri-state
-	*(unsigned char *) 0xa8040058 = 0x75;	// primary tri-state
-
-#if 0
-	/* this is not necessary if M5229 does not use SIRQ */
-	*(unsigned char *) 0xa8040044 = 0x0d;	// primary to IRQ 14
-	*(unsigned char *) 0xa8040075 = 0x0d;	// secondary to IRQ 14
-#endif
-
-	/* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */
-	/* M5229 IDSEL is addr:24; see above setting */
-	*(unsigned char *) 0xa9000050 |= 0x1;
-
-	/* enable bus master (bit 2)  and IO decoding  (bit 0) */
-	*(unsigned char *) 0xa9000004 |= 0x5;
-
-	/* enable native, copied from arch/ppc/k2boot/head.S */
-	/* TODO - need volatile, need to be portable */
-	*(unsigned char *) 0xa9000009 = 0xff;
-
-	/* ----- end of M1543 PCI setup ------ */
-
-	/* ----- reset on-board ether chip  ------ */
-	*((volatile u32 *) 0xa8020004) |= 1;	/* decode I/O */
-	*((volatile u32 *) 0xa8020010) = 0;	/* set BAR address */
-
-	/* send reset command */
-	*((volatile u32 *) 0xa6000000) = 1;	/* do a soft reset */
-
-	/* disable ether chip */
-	*((volatile u32 *) 0xa8020004) = 0;	/* disable any decoding */
-
-	/* put it into sleep */
-	*((volatile u32 *) 0xa8020040) = 0x80000000;
-
-	/* ----- end of reset on-board ether chip  ------ */
-
-	/* ----------- switch PCI1 back to PCI MEM space  ------------ */
-	ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1);
-	ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32);
-}
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
deleted file mode 100644
index a3c5e7b..0000000
--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * The irq controller for vrc5476.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-
-#include <asm/system.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static int irq_base;
-
-static void vrc5476_irq_enable(uint irq)
-{
-	nile4_enable_irq(irq - irq_base);
-}
-
-static void vrc5476_irq_disable(uint irq)
-{
-	nile4_disable_irq(irq - irq_base);
-}
-
-static unsigned int vrc5476_irq_startup(uint irq)
-{
-	nile4_enable_irq(irq - irq_base);
-	return 0;
-}
-
-#define vrc5476_irq_shutdown	vrc5476_irq_disable
-
-static void vrc5476_irq_ack(uint irq)
-{
-	nile4_clear_irq(irq - irq_base);
-	nile4_disable_irq(irq - irq_base);
-}
-
-static void vrc5476_irq_end(uint irq)
-{
-	if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		vrc5476_irq_enable(irq);
-}
-
-static hw_irq_controller vrc5476_irq_controller = {
-	.typename = "vrc5476",
-	.startup = vrc5476_irq_startup,
-	.shutdown = vrc5476_irq_shutdown,
-	.enable = vrc5476_irq_enable,
-	.disable = vrc5476_irq_disable,
-	.ack = vrc5476_irq_ack,
-	.end = vrc5476_irq_end
-};
-
-void __init
-vrc5476_irq_init(u32 base)
-{
-	u32 i;
-
-	irq_base = base;
-	for (i= base; i< base + NUM_VRC5476_IRQ; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		irq_desc[i].action = NULL;
-		irq_desc[i].depth = 1;
-		irq_desc[i].handler = &vrc5476_irq_controller;
-	}
-}
-
-
-void
-vrc5476_irq_dispatch(struct pt_regs *regs)
-{
-	u32 mask;
-	int nile4_irq;
-
-	mask = nile4_get_irq_stat(0);
-
-	/* quick check for possible time interrupt */
-	if (mask & (1 << VRC5476_IRQ_GPT)) {
-		do_IRQ(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT, regs);
-		return;
-	}
-
-	/* check for i8259 interrupts */
-	if (mask & (1 << VRC5476_I8259_CASCADE)) {
-		int i8259_irq = nile4_i8259_iack();
-		do_IRQ(I8259_IRQ_BASE + i8259_irq, regs);
-		return;
-	}
-
-	/* regular nile4 interrupts (we should not really have any */
-	for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) {
-		if (mask & 1) {
-			do_IRQ(VRC5476_IRQ_BASE + nile4_irq, regs);
-			return;
-		}
-	}
-	spurious_interrupt(regs);
-}
diff --git a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c
index 2f56603..93167ec 100644
--- a/arch/mips/ddb5xxx/ddb5477/setup.c
+++ b/arch/mips/ddb5xxx/ddb5477/setup.c
@@ -171,7 +171,7 @@
 extern struct pci_controller ddb5477_ext_controller;
 extern struct pci_controller ddb5477_io_controller;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	/* initialize board - we don't trust the loader */
         ddb5477_board_init();
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
index ad5d436..9c707b9 100644
--- a/arch/mips/dec/setup.c
+++ b/arch/mips/dec/setup.c
@@ -147,7 +147,7 @@
 extern void dec_time_init(void);
 extern void dec_timer_setup(struct irqaction *);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	board_be_init = dec_be_init;
 	board_time_init = dec_time_init;
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index 74cb055..76e4d09 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -181,7 +181,7 @@
 	}
 
 	/* Set up the rate of periodic DS1287 interrupts.  */
-	CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A);
+	CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A);
 }
 
 EXPORT_SYMBOL(do_settimeofday);
diff --git a/arch/mips/defconfig b/arch/mips/defconfig
index 607e298..879ba1a 100644
--- a/arch/mips/defconfig
+++ b/arch/mips/defconfig
@@ -41,8 +41,6 @@
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_V2PCI is not set
 # CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5074 is not set
-# CONFIG_DDB5476 is not set
 # CONFIG_DDB5477 is not set
 # CONFIG_MACH_VR41XX is not set
 # CONFIG_PMC_YOSEMITE is not set
@@ -136,6 +134,15 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_HZ_48 is not set
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+CONFIG_HZ_1000=y
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=1000
 # CONFIG_PREEMPT_NONE is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
diff --git a/arch/mips/emma2rh/common/Makefile b/arch/mips/emma2rh/common/Makefile
new file mode 100644
index 0000000..859121b
--- /dev/null
+++ b/arch/mips/emma2rh/common/Makefile
@@ -0,0 +1,13 @@
+#
+#  arch/mips/emma2rh/common/Makefile
+#       Makefile for the common code of NEC EMMA2RH based board.
+#
+#  Copyright (C) NEC Electronics Corporation 2005-2006
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+
+obj-$(CONFIG_MARKEINS)	+= irq.o irq_emma2rh.o prom.o
diff --git a/arch/mips/emma2rh/common/irq.c b/arch/mips/emma2rh/common/irq.c
new file mode 100644
index 0000000..b075281
--- /dev/null
+++ b/arch/mips/emma2rh/common/irq.c
@@ -0,0 +1,108 @@
+/*
+ *  arch/mips/emma2rh/common/irq.c
+ *      This file is common irq dispatcher.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+
+#include <asm/i8259.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/*
+ * the first level int-handler will jump here if it is a emma2rh irq
+ */
+asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs)
+{
+	u32 intStatus;
+	u32 bitmask;
+	u32 i;
+
+	intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0)
+	    & emma2rh_in32(EMMA2RH_BHIF_INT_EN_0);
+
+#ifdef EMMA2RH_SW_CASCADE
+	if (intStatus &
+	    (1 << ((EMMA2RH_SW_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+		u32 swIntStatus;
+		swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT)
+		    & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+		for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+			if (swIntStatus & bitmask) {
+				do_IRQ(EMMA2RH_SW_IRQ_BASE + i, regs);
+				return;
+			}
+		}
+	}
+#endif
+
+	for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+		if (intStatus & bitmask) {
+			do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+			return;
+		}
+	}
+
+	intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1)
+	    & emma2rh_in32(EMMA2RH_BHIF_INT_EN_1);
+
+#ifdef EMMA2RH_GPIO_CASCADE
+	if (intStatus &
+	    (1 << ((EMMA2RH_GPIO_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) {
+		u32 gpioIntStatus;
+		gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST)
+		    & emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+		for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
+			if (gpioIntStatus & bitmask) {
+				do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i, regs);
+				return;
+			}
+		}
+	}
+#endif
+
+	for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
+		if (intStatus & bitmask) {
+			do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+			return;
+		}
+	}
+
+	intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2)
+	    & emma2rh_in32(EMMA2RH_BHIF_INT_EN_2);
+
+	for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) {
+		if (intStatus & bitmask) {
+			do_IRQ(EMMA2RH_IRQ_BASE + i, regs);
+			return;
+		}
+	}
+}
diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c
new file mode 100644
index 0000000..b886aa9
--- /dev/null
+++ b/arch/mips/emma2rh/common/irq_emma2rh.c
@@ -0,0 +1,134 @@
+/*
+ *  arch/mips/emma2rh/common/irq_emma2rh.c
+ *      This file defines the irq handler for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * EMMA2RH defines 64 IRQs.
+ *
+ * This file exports one function:
+ *	emma2rh_irq_init(u32 irq_base);
+ */
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/* number of total irqs supported by EMMA2RH */
+#define	NUM_EMMA2RH_IRQ		96
+
+static int emma2rh_irq_base = -1;
+
+void ll_emma2rh_irq_enable(int);
+void ll_emma2rh_irq_disable(int);
+
+static void emma2rh_irq_enable(unsigned int irq)
+{
+	ll_emma2rh_irq_enable(irq - emma2rh_irq_base);
+}
+
+static void emma2rh_irq_disable(unsigned int irq)
+{
+	ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
+}
+
+static unsigned int emma2rh_irq_startup(unsigned int irq)
+{
+	emma2rh_irq_enable(irq);
+	return 0;
+}
+
+#define	emma2rh_irq_shutdown	emma2rh_irq_disable
+
+static void emma2rh_irq_ack(unsigned int irq)
+{
+	/* disable interrupt - some handler will re-enable the irq
+	 * and if the interrupt is leveled, we will have infinite loop
+	 */
+	ll_emma2rh_irq_disable(irq - emma2rh_irq_base);
+}
+
+static void emma2rh_irq_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ll_emma2rh_irq_enable(irq - emma2rh_irq_base);
+}
+
+hw_irq_controller emma2rh_irq_controller = {
+	.typename = "emma2rh_irq",
+	.startup = emma2rh_irq_startup,
+	.shutdown = emma2rh_irq_shutdown,
+	.enable = emma2rh_irq_enable,
+	.disable = emma2rh_irq_disable,
+	.ack = emma2rh_irq_ack,
+	.end = emma2rh_irq_end,
+	.set_affinity = NULL	/* no affinity stuff for UP */
+};
+
+void emma2rh_irq_init(u32 irq_base)
+{
+	u32 i;
+
+	for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &emma2rh_irq_controller;
+	}
+
+	emma2rh_irq_base = irq_base;
+}
+
+void ll_emma2rh_irq_enable(int emma2rh_irq)
+{
+	u32 reg_value;
+	u32 reg_bitmask;
+	u32 reg_index;
+
+	reg_index = EMMA2RH_BHIF_INT_EN_0
+	    + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0)
+	    * (emma2rh_irq / 32);
+	reg_value = emma2rh_in32(reg_index);
+	reg_bitmask = 0x1 << (emma2rh_irq % 32);
+	db_assert((reg_value & reg_bitmask) == 0);
+	emma2rh_out32(reg_index, reg_value | reg_bitmask);
+}
+
+void ll_emma2rh_irq_disable(int emma2rh_irq)
+{
+	u32 reg_value;
+	u32 reg_bitmask;
+	u32 reg_index;
+
+	reg_index = EMMA2RH_BHIF_INT_EN_0
+	    + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0)
+	    * (emma2rh_irq / 32);
+	reg_value = emma2rh_in32(reg_index);
+	reg_bitmask = 0x1 << (emma2rh_irq % 32);
+	db_assert((reg_value & reg_bitmask) != 0);
+	emma2rh_out32(reg_index, reg_value & ~reg_bitmask);
+}
diff --git a/arch/mips/emma2rh/common/prom.c b/arch/mips/emma2rh/common/prom.c
new file mode 100644
index 0000000..8bba0b0
--- /dev/null
+++ b/arch/mips/emma2rh/common/prom.c
@@ -0,0 +1,77 @@
+/*
+ *  arch/mips/emma2rh/common/prom.c
+ *      This file is prom file.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/common/prom.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/bootmem.h>
+
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+#include <asm/emma2rh/emma2rh.h>
+#include <asm/debug.h>
+
+const char *get_system_type(void)
+{
+	switch (mips_machtype) {
+	case MACH_NEC_MARKEINS:
+		return "NEC EMMA2RH Mark-eins";
+	default:
+		return "Unknown NEC board";
+	}
+}
+
+/* [jsun@junsun.net] PMON passes arguments in C main() style */
+void __init prom_init(void)
+{
+	int argc = fw_arg0;
+	char **arg = (char **)fw_arg1;
+	int i;
+
+	/* if user passes kernel args, ignore the default one */
+	if (argc > 1)
+		arcs_cmdline[0] = '\0';
+
+	/* arg[0] is "g", the rest is boot parameters */
+	for (i = 1; i < argc; i++) {
+		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+		    >= sizeof(arcs_cmdline))
+			break;
+		strcat(arcs_cmdline, arg[i]);
+		strcat(arcs_cmdline, " ");
+	}
+
+	mips_machgroup = MACH_GROUP_NEC_EMMA2RH;
+
+#if defined(CONFIG_MARKEINS)
+	mips_machtype = MACH_NEC_MARKEINS;
+	add_memory_region(0, EMMA2RH_RAM_SIZE, BOOT_MEM_RAM);
+#endif
+
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/emma2rh/markeins/Makefile b/arch/mips/emma2rh/markeins/Makefile
new file mode 100644
index 0000000..14fc268
--- /dev/null
+++ b/arch/mips/emma2rh/markeins/Makefile
@@ -0,0 +1,13 @@
+#
+#  arch/mips/emma2rh/markeins/Makefile
+#       Makefile for the common code of NEC EMMA2RH based board.
+#
+#  Copyright (C) NEC Electronics Corporation 2005-2006
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+
+obj-$(CONFIG_MARKEINS) += irq.o irq_markeins.o setup.o led.o platform.o
diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c
new file mode 100644
index 0000000..76dc3fa
--- /dev/null
+++ b/arch/mips/emma2rh/markeins/irq.c
@@ -0,0 +1,134 @@
+/*
+ *  arch/mips/emma2rh/markeins/irq.c
+ *      This file defines the irq handler for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/delay.h>
+
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+#include <asm/debug.h>
+#include <asm/addrspace.h>
+#include <asm/bootinfo.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+/*
+ * IRQ mapping
+ *
+ *  0-7: 8 CPU interrupts
+ *	0 -	software interrupt 0
+ *	1 - 	software interrupt 1
+ *	2 - 	most Vrc5477 interrupts are routed to this pin
+ *	3 - 	(optional) some other interrupts routed to this pin for debugg
+ *	4 - 	not used
+ *	5 - 	not used
+ *	6 - 	not used
+ *	7 - 	cpu timer (used by default)
+ *
+ */
+
+extern void emma2rh_sw_irq_init(u32 base);
+extern void emma2rh_gpio_irq_init(u32 base);
+extern void emma2rh_irq_init(u32 base);
+extern asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs);
+
+static struct irqaction irq_cascade = {
+	   .handler = no_action,
+	   .flags = 0,
+	   .mask = CPU_MASK_NONE,
+	   .name = "cascade",
+	   .dev_id = NULL,
+	   .next = NULL,
+};
+
+void __init arch_init_irq(void)
+{
+	u32 reg;
+
+	db_run(printk("markeins_irq_setup invoked.\n"));
+
+	/* by default, interrupts are disabled. */
+	emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0);
+	emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0);
+	emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0);
+	emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0);
+	emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0);
+	emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0);
+	emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0);
+
+	clear_c0_status(0xff00);
+	set_c0_status(0x0400);
+
+#define GPIO_PCI (0xf<<15)
+	/* setup GPIO interrupt for PCI interface */
+	/* direction input */
+	reg = emma2rh_in32(EMMA2RH_GPIO_DIR);
+	emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI);
+	/* disable interrupt */
+	reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+	emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI);
+	/* level triggerd */
+	reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE);
+	emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI);
+	reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A);
+	emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI));
+	/* interrupt clear */
+	emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI);
+
+	/* init all controllers */
+	emma2rh_irq_init(EMMA2RH_IRQ_BASE);
+	emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE);
+	emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE);
+	mips_cpu_irq_init(CPU_IRQ_BASE);
+
+	/* setup cascade interrupts */
+	setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
+	setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade);
+	setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade);
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+        unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(CPU_IRQ_BASE + 7, regs);
+	else if (pending & STATUSF_IP2)
+		emma2rh_irq_dispatch(regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(CPU_IRQ_BASE + 1, regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(CPU_IRQ_BASE + 0, regs);
+	else
+		spurious_interrupt(regs);
+}
+
+
diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c
new file mode 100644
index 0000000..1783fda
--- /dev/null
+++ b/arch/mips/emma2rh/markeins/irq_markeins.c
@@ -0,0 +1,197 @@
+/*
+ *  arch/mips/emma2rh/markeins/irq_markeins.c
+ *      This file defines the irq handler for Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+#include <asm/debug.h>
+#include <asm/emma2rh/emma2rh.h>
+
+static int emma2rh_sw_irq_base = -1;
+static int emma2rh_gpio_irq_base = -1;
+
+void ll_emma2rh_sw_irq_enable(int reg);
+void ll_emma2rh_sw_irq_disable(int reg);
+void ll_emma2rh_gpio_irq_enable(int reg);
+void ll_emma2rh_gpio_irq_disable(int reg);
+
+static void emma2rh_sw_irq_enable(unsigned int irq)
+{
+	ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
+}
+
+static void emma2rh_sw_irq_disable(unsigned int irq)
+{
+	ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
+}
+
+static unsigned int emma2rh_sw_irq_startup(unsigned int irq)
+{
+	emma2rh_sw_irq_enable(irq);
+	return 0;
+}
+
+#define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable
+
+static void emma2rh_sw_irq_ack(unsigned int irq)
+{
+	ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base);
+}
+
+static void emma2rh_sw_irq_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base);
+}
+
+hw_irq_controller emma2rh_sw_irq_controller = {
+	.typename = "emma2rh_sw_irq",
+	.startup = emma2rh_sw_irq_startup,
+	.shutdown = emma2rh_sw_irq_shutdown,
+	.enable = emma2rh_sw_irq_enable,
+	.disable = emma2rh_sw_irq_disable,
+	.ack = emma2rh_sw_irq_ack,
+	.end = emma2rh_sw_irq_end,
+	.set_affinity = NULL,
+};
+
+void emma2rh_sw_irq_init(u32 irq_base)
+{
+	u32 i;
+
+	for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 2;
+		irq_desc[i].handler = &emma2rh_sw_irq_controller;
+	}
+
+	emma2rh_sw_irq_base = irq_base;
+}
+
+void ll_emma2rh_sw_irq_enable(int irq)
+{
+	u32 reg;
+
+	db_assert(irq >= 0);
+	db_assert(irq < NUM_EMMA2RH_IRQ_SW);
+
+	reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+	reg |= 1 << irq;
+	emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
+}
+
+void ll_emma2rh_sw_irq_disable(int irq)
+{
+	u32 reg;
+
+	db_assert(irq >= 0);
+	db_assert(irq < 32);
+
+	reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
+	reg &= ~(1 << irq);
+	emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
+}
+
+static void emma2rh_gpio_irq_enable(unsigned int irq)
+{
+	ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
+}
+
+static void emma2rh_gpio_irq_disable(unsigned int irq)
+{
+	ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base);
+}
+
+static unsigned int emma2rh_gpio_irq_startup(unsigned int irq)
+{
+	emma2rh_gpio_irq_enable(irq);
+	return 0;
+}
+
+#define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable
+
+static void emma2rh_gpio_irq_ack(unsigned int irq)
+{
+	irq -= emma2rh_gpio_irq_base;
+	emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
+	ll_emma2rh_gpio_irq_disable(irq);
+}
+
+static void emma2rh_gpio_irq_end(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base);
+}
+
+hw_irq_controller emma2rh_gpio_irq_controller = {
+	.typename = "emma2rh_gpio_irq",
+	.startup = emma2rh_gpio_irq_startup,
+	.shutdown = emma2rh_gpio_irq_shutdown,
+	.enable = emma2rh_gpio_irq_enable,
+	.disable = emma2rh_gpio_irq_disable,
+	.ack = emma2rh_gpio_irq_ack,
+	.end = emma2rh_gpio_irq_end,
+	.set_affinity = NULL,
+};
+
+void emma2rh_gpio_irq_init(u32 irq_base)
+{
+	u32 i;
+
+	for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = NULL;
+		irq_desc[i].depth = 2;
+		irq_desc[i].handler = &emma2rh_gpio_irq_controller;
+	}
+
+	emma2rh_gpio_irq_base = irq_base;
+}
+
+void ll_emma2rh_gpio_irq_enable(int irq)
+{
+	u32 reg;
+
+	db_assert(irq >= 0);
+	db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
+
+	reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+	reg |= 1 << irq;
+	emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
+}
+
+void ll_emma2rh_gpio_irq_disable(int irq)
+{
+	u32 reg;
+
+	db_assert(irq >= 0);
+	db_assert(irq < NUM_EMMA2RH_IRQ_GPIO);
+
+	reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
+	reg &= ~(1 << irq);
+	emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
+}
diff --git a/arch/mips/emma2rh/markeins/led.c b/arch/mips/emma2rh/markeins/led.c
new file mode 100644
index 0000000..b65254c
--- /dev/null
+++ b/arch/mips/emma2rh/markeins/led.c
@@ -0,0 +1,60 @@
+/*
+ *  arch/mips/emma2rh/markeins/led.c
+ *      This file defines the led display for Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <asm/emma2rh/emma2rh.h>
+
+const unsigned long clear = 0x20202020;
+
+#define LED_BASE 0xb1400038
+
+void markeins_led_clear(void)
+{
+	emma2rh_out32(LED_BASE, clear);
+	emma2rh_out32(LED_BASE + 4, clear);
+}
+
+void markeins_led(const char *str)
+{
+	int i;
+	int len = strlen(str);
+
+	markeins_led_clear();
+	if (len > 8)
+		len = 8;
+
+	if (emma2rh_in32(0xb0000800) & (0x1 << 18))
+		for (i = 0; i < len; i++)
+			emma2rh_out8(LED_BASE + i, str[i]);
+	else
+		for (i = 0; i < len; i++)
+			emma2rh_out8(LED_BASE + (i & 4) + (3 - (i & 3)),
+				     str[i]);
+}
+
+void markeins_led_hex(u32 val)
+{
+	char str[10];
+
+	sprintf(str, "%08x", val);
+	markeins_led(str);
+}
diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c
new file mode 100644
index 0000000..6c1eeae
--- /dev/null
+++ b/arch/mips/emma2rh/markeins/platform.c
@@ -0,0 +1,170 @@
+/*
+ *  arch/mips/emma2rh/markeins/platofrm.c
+ *      This file sets up platform devices for EMMA2RH Mark-eins.
+ *
+ *  Copyright(C) MontaVista Software Inc, 2006
+ *
+ *  Author: dmitry pervushin <dpervushin@ru.mvista.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/serial_8250.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/traps.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+
+#define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */
+
+static struct resource i2c_emma_resources_0[] = {
+	{ NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ },
+	{ NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 },
+};
+
+struct resource i2c_emma_resources_1[] = {
+	{ NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ },
+	{ NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 },
+};
+
+struct resource i2c_emma_resources_2[] = {
+	{ NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ },
+	{ NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 },
+};
+
+struct platform_device i2c_emma_devices[] = {
+	[0] = {
+		.name = I2C_EMMA2RH,
+		.id = 0,
+		.resource = i2c_emma_resources_0,
+		.num_resources = ARRAY_SIZE(i2c_emma_resources_0),
+	},
+	[1] = {
+		.name = I2C_EMMA2RH,
+		.id = 1,
+		.resource = i2c_emma_resources_1,
+		.num_resources = ARRAY_SIZE(i2c_emma_resources_1),
+	},
+	[2] = {
+		.name = I2C_EMMA2RH,
+		.id = 2,
+		.resource = i2c_emma_resources_2,
+		.num_resources = ARRAY_SIZE(i2c_emma_resources_2),
+	},
+};
+
+#define EMMA2RH_SERIAL_CLOCK 18544000
+#define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST
+
+static struct  plat_serial8250_port platform_serial_ports[] = {
+       [0] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR0,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [1] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR1,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [2] = {
+         .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3),
+         .irq = EMMA2RH_IRQ_PFUR2,
+         .uartclk = EMMA2RH_SERIAL_CLOCK,
+         .regshift = 4,
+         .iotype = UPIO_MEM,
+         .flags = EMMA2RH_SERIAL_FLAGS,
+       },
+       [3] = {
+	 .flags = 0,
+       },
+};
+
+static struct  platform_device serial_emma = {
+	.name = "serial8250",
+	.dev = {
+		.platform_data = &platform_serial_ports,
+	},
+};
+
+static struct platform_device *devices[] = {
+	&i2c_emma_devices[0],
+	&i2c_emma_devices[1],
+	&i2c_emma_devices[2],
+	&serial_emma,
+};
+
+static struct mtd_partition markeins_parts[] = {
+	[0] = {
+		.name = "RootFS",
+		.offset = 0x00000000,
+		.size = 0x00c00000,
+	},
+	[1] = {
+		.name = "boot code area",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0x00100000,
+	},
+	[2] = {
+		.name = "kernel image",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0x00300000,
+	},
+	[3] = {
+		.name = "RootFS2",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0x00c00000,
+	},
+	[4] = {
+		.name = "boot code area2",
+		.offset = MTDPART_OFS_APPEND,
+		.size = 0x00100000,
+	},
+	[5] = {
+		.name = "kernel image2",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+	},
+};
+
+static int __init platform_devices_setup(void)
+{
+	physmap_set_partitions(markeins_parts, ARRAY_SIZE(markeins_parts));
+	return platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+arch_initcall(platform_devices_setup);
+
diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c
new file mode 100644
index 0000000..7d98fdb
--- /dev/null
+++ b/arch/mips/emma2rh/markeins/setup.c
@@ -0,0 +1,182 @@
+/*
+ *  arch/mips/emma2rh/markeins/setup.c
+ *      This file is setup for EMMA2RH Mark-eins.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/setup.c.
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/initrd.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/param.h>	/* for HZ */
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/bcache.h>
+#include <asm/irq.h>
+#include <asm/reboot.h>
+#include <asm/gdb-stub.h>
+#include <asm/traps.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define	USE_CPU_COUNTER_TIMER	/* whether we use cpu counter */
+
+extern void markeins_led(const char *);
+
+static int bus_frequency = 0;
+
+static void markeins_machine_restart(char *command)
+{
+	static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000;
+
+	printk("cannot EMMA2RH Mark-eins restart.\n");
+	markeins_led("restart.");
+	back_to_prom();
+}
+
+static void markeins_machine_halt(void)
+{
+	printk("EMMA2RH Mark-eins halted.\n");
+	markeins_led("halted.");
+	while (1) ;
+}
+
+static void markeins_machine_power_off(void)
+{
+	printk("EMMA2RH Mark-eins halted. Please turn off the power.\n");
+	markeins_led("poweroff.");
+	while (1) ;
+}
+
+static unsigned long clock[4] = { 166500000, 187312500, 199800000, 210600000 };
+
+static unsigned int __init detect_bus_frequency(unsigned long rtc_base)
+{
+	u32 reg;
+
+	/* detect from boot strap */
+	reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0);
+	reg = (reg >> 4) & 0x3;
+	return clock[reg];
+}
+
+static void __init emma2rh_time_init(void)
+{
+	u32 reg;
+	if (bus_frequency == 0)
+		bus_frequency = detect_bus_frequency(0);
+
+	reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0);
+	if ((reg & 0x3) == 0)
+		reg = (reg >> 6) & 0x3;
+	else {
+		reg = emma2rh_in32(EMMA2RH_BHIF_MAIN_CTRL);
+		reg = (reg >> 4) & 0x3;
+	}
+	mips_hpt_frequency = (bus_frequency * (4 + reg)) / 4 / 2;
+}
+
+static void __init emma2rh_timer_setup(struct irqaction *irq)
+{
+	/* we are using the cpu counter for timer interrupts */
+	setup_irq(CPU_IRQ_BASE + 7, irq);
+}
+
+static void markeins_board_init(void);
+extern void markeins_irq_setup(void);
+
+static void inline __init markeins_sio_setup(void)
+{
+#ifdef CONFIG_KGDB_8250
+	struct uart_port emma_port;
+
+	memset(&emma_port, 0, sizeof(emma_port));
+
+	emma_port.flags =
+	    UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	emma_port.iotype = UPIO_MEM;
+	emma_port.regshift = 4;	/* I/O addresses are every 8 bytes */
+	emma_port.uartclk = 18544000;	/* Clock rate of the chip */
+
+	emma_port.line = 0;
+	emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3);
+	emma_port.membase = (u8*)emma_port.mapbase;
+	early_serial_setup(&emma_port);
+
+	emma_port.line = 1;
+	emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3);
+	emma_port.membase = (u8*)emma_port.mapbase;
+	early_serial_setup(&emma_port);
+
+	emma_port.irq = EMMA2RH_IRQ_PFUR1;
+	kgdb8250_add_port(1, &emma_port);
+#endif
+}
+
+void __init plat_mem_setup(void)
+{
+	/* initialize board - we don't trust the loader */
+	markeins_board_init();
+
+	set_io_port_base(KSEG1ADDR(EMMA2RH_PCI_IO_BASE));
+
+	board_time_init = emma2rh_time_init;
+	board_timer_setup = emma2rh_timer_setup;
+
+	_machine_restart = markeins_machine_restart;
+	_machine_halt = markeins_machine_halt;
+	pm_power_off = markeins_machine_power_off;
+
+	/* setup resource limits */
+	ioport_resource.start = EMMA2RH_PCI_IO_BASE;
+	ioport_resource.end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1;
+	iomem_resource.start = EMMA2RH_IO_BASE;
+	iomem_resource.end = EMMA2RH_ROM_BASE - 1;
+
+	/* Reboot on panic */
+	panic_timeout = 180;
+
+	markeins_sio_setup();
+}
+
+static void __init markeins_board_init(void)
+{
+	u32 val;
+
+	val = emma2rh_in32(EMMA2RH_PBRD_INT_EN);	/* open serial interrupts. */
+	emma2rh_out32(EMMA2RH_PBRD_INT_EN, val | 0xaa);
+	val = emma2rh_in32(EMMA2RH_PBRD_CLKSEL);	/* set serial clocks. */
+	emma2rh_out32(EMMA2RH_PBRD_CLKSEL, val | 0x5);	/* 18MHz */
+	emma2rh_out32(EMMA2RH_PCI_CONTROL, 0);
+
+	markeins_led("MVL E2RH");
+}
diff --git a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c
index 78dbb18..a04aea6 100644
--- a/arch/mips/galileo-boards/ev96100/setup.c
+++ b/arch/mips/galileo-boards/ev96100/setup.c
@@ -55,7 +55,7 @@
 
 unsigned char mac_0_1[12];
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	unsigned int config = read_c0_config();
 	unsigned int status = read_c0_status();
diff --git a/arch/mips/gt64120/ev64120/setup.c b/arch/mips/gt64120/ev64120/setup.c
index 6d859d1..4236da3 100644
--- a/arch/mips/gt64120/ev64120/setup.c
+++ b/arch/mips/gt64120/ev64120/setup.c
@@ -71,7 +71,7 @@
  */
 extern void gt64120_time_init(void);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	_machine_restart = galileo_machine_restart;
 	_machine_halt = galileo_machine_halt;
diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c
index 20b65d3..1193a22 100644
--- a/arch/mips/gt64120/momenco_ocelot/setup.c
+++ b/arch/mips/gt64120/momenco_ocelot/setup.c
@@ -152,7 +152,7 @@
 	gt64120_base = 0xe0000000;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache);
 	unsigned int tmpword;
diff --git a/arch/mips/gt64120/wrppmc/Makefile b/arch/mips/gt64120/wrppmc/Makefile
new file mode 100644
index 0000000..72606b9
--- /dev/null
+++ b/arch/mips/gt64120/wrppmc/Makefile
@@ -0,0 +1,14 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright 2006 Wind River System, Inc.
+# Author: Rongkai.Zhan <rongkai.zhan@windriver.com>
+#
+# Makefile for the Wind River MIPS 4KC PPMC Eval Board
+#
+
+obj-y	+= int-handler.o irq.o reset.o setup.o time.o pci.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/wrppmc/int-handler.S b/arch/mips/gt64120/wrppmc/int-handler.S
new file mode 100644
index 0000000..edee7b3
--- /dev/null
+++ b/arch/mips/gt64120/wrppmc/int-handler.S
@@ -0,0 +1,59 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
+ * Copyright (C) Wind River System Inc. Rongkai.Zhan <rongkai.zhan@windriver.com>
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/mach-wrppmc/mach-gt64120.h>
+
+	.align	5
+	.set	noat
+NESTED(handle_IRQ, PT_SIZE, sp)
+	SAVE_ALL
+	CLI				# Important: mark KERNEL mode !
+	.set	at
+
+	mfc0	t0, CP0_CAUSE		# get pending interrupts
+	mfc0	t1, CP0_STATUS		# get enabled interrupts
+	and	t0, t0, t1		# get allowed interrupts
+	andi	t0, t0, 0xFF00
+	beqz	t0, 1f
+	move	a1, sp			# Prepare 'struct pt_regs *regs' pointer
+
+	andi	t1, t0, CAUSEF_IP7	# CPU Compare/Count internal timer
+	bnez	t1, handle_cputimer_irq
+	andi	t1, t0, CAUSEF_IP6	# UART 16550 port
+	bnez	t1, handle_uart_irq
+	andi	t1, t0, CAUSEF_IP3	# PCI INT_A
+	bnez	t1, handle_pci_intA_irq
+
+	/* wrong alarm or masked ... */
+1:	j	spurious_interrupt
+	nop
+END(handle_IRQ)
+
+	.align	5
+handle_cputimer_irq:
+	li	a0, WRPPMC_MIPS_TIMER_IRQ
+	jal	do_IRQ
+	j	ret_from_irq
+
+	.align	5
+handle_uart_irq:
+	li	a0, WRPPMC_UART16550_IRQ
+	jal	do_IRQ
+	j	ret_from_irq
+
+	.align	5
+handle_pci_intA_irq:
+	li	a0, WRPPMC_PCI_INTA_IRQ
+	jal	do_IRQ
+	j	ret_from_irq
+
diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c
new file mode 100644
index 0000000..8605687
--- /dev/null
+++ b/arch/mips/gt64120/wrppmc/irq.c
@@ -0,0 +1,63 @@
+/*
+ * irq.c: GT64120 Interrupt Controller
+ *
+ * Copyright (C) 2006, Wind River System Inc.
+ * Author: Rongkai.Zhan, <rongkai.zhan@windriver.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+#include <linux/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/irq_cpu.h>
+#include <asm/gt64120.h>
+
+extern asmlinkage void handle_IRQ(void);
+
+/**
+ * Initialize GT64120 Interrupt Controller
+ */
+void gt64120_init_pic(void)
+{
+	/* clear CPU Interrupt Cause Registers */
+	GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21));
+	GT_WRITE(GT_HINTRCAUSE_OFS, 0x00);
+
+	/* Disable all interrupts from GT64120 bridge chip */
+	GT_WRITE(GT_INTRMASK_OFS, 0x00);
+	GT_WRITE(GT_HINTRMASK_OFS, 0x00);
+	GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00);
+	GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00);
+}
+
+void __init arch_init_irq(void)
+{
+	/* enable all CPU interrupt bits. */
+	set_c0_status(ST0_IM);	/* IE bit is still 0 */
+
+	/* Install MIPS Interrupt Trap Vector */
+	set_except_vector(0, handle_IRQ);
+
+	/* IRQ 0 - 7 are for MIPS common irq_cpu controller */
+	mips_cpu_irq_init(0);
+
+	gt64120_init_pic();
+}
diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c
new file mode 100644
index 0000000..2fbe934
--- /dev/null
+++ b/arch/mips/gt64120/wrppmc/pci.c
@@ -0,0 +1,53 @@
+/*
+ * pci.c: GT64120 PCI support.
+ *
+ * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan <rongkai.zhan@windriver.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/gt64120.h>
+
+extern struct pci_ops gt64120_pci_ops;
+
+static struct resource pci0_io_resource = {
+	.name  = "pci_0 io",
+	.start = GT_PCI_IO_BASE,
+	.end   = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1,
+	.flags = IORESOURCE_IO,
+};
+
+static struct resource pci0_mem_resource = {
+	.name  = "pci_0 memory",
+	.start = GT_PCI_MEM_BASE,
+	.end   = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+static struct pci_controller hose_0 = {
+	.pci_ops	= &gt64120_pci_ops,
+	.io_resource	= &pci0_io_resource,
+	.mem_resource	= &pci0_mem_resource,
+};
+
+static int __init gt64120_pci_init(void)
+{
+	u32 tmp;
+
+	tmp = GT_READ(GT_PCI0_CMD_OFS);		/* Huh??? -- Ralf  */
+	tmp = GT_READ(GT_PCI0_BARE_OFS);
+
+	/* reset the whole PCI I/O space range */
+	ioport_resource.start = GT_PCI_IO_BASE;
+	ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+
+	register_pci_controller(&hose_0);
+	return 0;
+}
+
+arch_initcall(gt64120_pci_init);
diff --git a/arch/mips/gt64120/wrppmc/reset.c b/arch/mips/gt64120/wrppmc/reset.c
new file mode 100644
index 0000000..b97039c
--- /dev/null
+++ b/arch/mips/gt64120/wrppmc/reset.c
@@ -0,0 +1,50 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1997 Ralf Baechle
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+
+void wrppmc_machine_restart(char *command)
+{
+	/*
+	 * Ouch, we're still alive ... This time we take the silver bullet ...
+	 * ... and find that we leave the hardware in a state in which the
+	 * kernel in the flush locks up somewhen during of after the PCI
+	 * detection stuff.
+	 */
+	local_irq_disable();
+	set_c0_status(ST0_BEV | ST0_ERL);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_c0_wired(0);
+	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
+}
+
+void wrppmc_machine_halt(void)
+{
+	local_irq_disable();
+
+	printk(KERN_NOTICE "You can safely turn off the power\n");
+	while (1) {
+		__asm__(
+			".set\tmips3\n\t"
+			"wait\n\t"
+			".set\tmips0"
+		);
+	}
+}
+
+void wrppmc_machine_power_off(void)
+{
+	wrppmc_machine_halt();
+}
diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c
new file mode 100644
index 0000000..20c591e
--- /dev/null
+++ b/arch/mips/gt64120/wrppmc/setup.c
@@ -0,0 +1,173 @@
+/*
+ * setup.c: Setup pointers to hardware dependent routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan <rongkai.zhan@windriver.com>
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/pm.h>
+
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/gt64120.h>
+
+unsigned long gt64120_base = KSEG1ADDR(0x14000000);
+
+#ifdef WRPPMC_EARLY_DEBUG
+
+static volatile unsigned char * wrppmc_led = \
+	(volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE);
+
+/*
+ * PPMC LED control register:
+ * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON)
+ * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON)
+ * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON)
+ */
+void wrppmc_led_on(int mask)
+{
+	unsigned char value = *wrppmc_led;
+
+	value &= (0xF8 | mask);
+	*wrppmc_led = value;
+}
+
+/* If mask = 0, turn off all LEDs */
+void wrppmc_led_off(int mask)
+{
+	unsigned char value = *wrppmc_led;
+
+	value |= (0x7 & mask);
+	*wrppmc_led = value;
+}
+
+/*
+ * We assume that bootloader has initialized UART16550 correctly
+ */
+void __init wrppmc_early_putc(char ch)
+{
+	static volatile unsigned char *wrppmc_uart = \
+		(volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE);
+	unsigned char value;
+
+	/* Wait until Transmit-Holding-Register is empty */
+	while (1) {
+		value = *(wrppmc_uart + 5);
+		if (value & 0x20)
+			break;
+	}
+
+	*wrppmc_uart = ch;
+}
+
+void __init wrppmc_early_printk(const char *fmt, ...)
+{
+	static char pbuf[256] = {'\0', };
+	char *ch = pbuf;
+	va_list args;
+	unsigned int i;
+
+	memset(pbuf, 0, 256);
+	va_start(args, fmt);
+	i = vsprintf(pbuf, fmt, args);
+	va_end(args);
+
+	/* Print the string */
+	while (*ch != '\0') {
+		wrppmc_early_putc(*ch);
+		/* if print '\n', also print '\r' */
+		if (*ch++ == '\n')
+			wrppmc_early_putc('\r');
+	}
+}
+#endif /* WRPPMC_EARLY_DEBUG */
+
+unsigned long __init prom_free_prom_memory(void)
+{
+	return 0;
+}
+
+#ifdef CONFIG_SERIAL_8250
+static void wrppmc_setup_serial(void)
+{
+	struct uart_port up;
+
+	memset(&up, 0x00, sizeof(struct uart_port));
+
+	/*
+	 * A note about mapbase/membase
+	 * -) mapbase is the physical address of the IO port.
+	 * -) membase is an 'ioremapped' cookie.
+	 */
+	up.line = 0;
+	up.type = PORT_16550;
+	up.iotype = UPIO_MEM;
+	up.mapbase = WRPPMC_UART16550_BASE;
+	up.membase = ioremap(up.mapbase, 8);
+	up.irq = WRPPMC_UART16550_IRQ;
+	up.uartclk = WRPPMC_UART16550_CLOCK;
+	up.flags = UPF_SKIP_TEST/* | UPF_BOOT_AUTOCONF */;
+	up.regshift = 0;
+
+	early_serial_setup(&up);
+}
+#endif
+
+void __init plat_setup(void)
+{
+	extern void wrppmc_time_init(void);
+	extern void wrppmc_timer_setup(struct irqaction *);
+	extern void wrppmc_machine_restart(char *command);
+	extern void wrppmc_machine_halt(void);
+	extern void wrppmc_machine_power_off(void);
+
+	_machine_restart = wrppmc_machine_restart;
+	_machine_halt	 = wrppmc_machine_halt;
+	pm_power_off	 = wrppmc_machine_power_off;
+
+	/* Use MIPS Count/Compare Timer */
+	board_time_init   = wrppmc_time_init;
+	board_timer_setup = wrppmc_timer_setup;
+
+	/* This makes the operations of 'in/out[bwl]' to the
+	 * physical address ( < KSEG0) can work via KSEG1
+	 */
+	set_io_port_base(KSEG1);
+
+#ifdef CONFIG_SERIAL_8250
+	wrppmc_setup_serial();
+#endif
+}
+
+const char *get_system_type(void)
+{
+	return "Wind River PPMC (GT64120)";
+}
+
+/*
+ * Initializes basic routines and structures pointers, memory size (as
+ * given by the bios and saves the command line.
+ */
+void __init prom_init(void)
+{
+	mips_machgroup = MACH_GROUP_GALILEO;
+	mips_machtype = MACH_EV64120A;
+
+	add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM);
+	add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA);
+
+	wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n",
+			WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE));
+}
diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c
new file mode 100644
index 0000000..175d22a
--- /dev/null
+++ b/arch/mips/gt64120/wrppmc/time.c
@@ -0,0 +1,57 @@
+/*
+ * time.c: MIPS CPU Count/Compare timer hookup
+ *
+ * Author: Mark.Zhan, <rongkai.zhan@windriver.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006, Wind River System Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/param.h>	/* for HZ */
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+
+#include <asm/reboot.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/gt64120.h>
+
+#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */
+
+void __init wrppmc_timer_setup(struct irqaction *irq)
+{
+	/* Install ISR for timer interrupt */
+	setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq);
+
+	/* to generate the first timer interrupt */
+	write_c0_compare(mips_hpt_frequency/HZ);
+	write_c0_count(0);
+}
+
+/*
+ * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
+ *
+ * NOTE: We disable all GT64120 timers, and use MIPS processor internal
+ * timer as the source of kernel clock tick.
+ */
+void __init wrppmc_time_init(void)
+{
+	/* Disable GT64120 timers */
+	GT_WRITE(GT_TC_CONTROL_OFS, 0x00);
+	GT_WRITE(GT_TC0_OFS, 0x00);
+	GT_WRITE(GT_TC1_OFS, 0x00);
+	GT_WRITE(GT_TC2_OFS, 0x00);
+	GT_WRITE(GT_TC3_OFS, 0x00);
+
+	/* Use MIPS compare/count internal timer */
+	mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ;
+}
diff --git a/arch/mips/ite-boards/generic/it8172_setup.c b/arch/mips/ite-boards/generic/it8172_setup.c
index fc73c8d..da6ae09 100644
--- a/arch/mips/ite-boards/generic/it8172_setup.c
+++ b/arch/mips/ite-boards/generic/it8172_setup.c
@@ -72,11 +72,29 @@
     struct resource flash;
     struct resource boot;
 } it8172_resources = {
-    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
-    { "PCI Mem",       0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
-    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
-    { "Flash",         0x08000000, 0x0CFFFFFF                 },
-    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+	{
+		.start	= 0,				/* to be initted */
+		.end	= 0,
+		.name	= "RAM",
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= 0x10000000,
+		.end	= 0x13FFFFFF,
+		.name	= "PCI Mem",
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= 0x14000000,
+		.end	= 0x17FFFFFF
+		.name	= "PCI I/O",
+	}, {
+		.start	= 0x08000000,
+		.end	= 0x0CFFFFFF
+		.name	= "Flash",
+	}, {
+		.start	= 0x1FC00000,
+		.end	= 0x1FFFFFFF
+		.name	= "Boot ROM",
+	}
 };
 #else
 struct {
@@ -89,14 +107,44 @@
     struct resource flash;
     struct resource boot;
 } it8172_resources = {
-    { "RAM",           0,          0,          IORESOURCE_MEM }, /* to be initted */
-    { "PCI Mem0",      0x0C000000, 0x0FFFFFFF, IORESOURCE_MEM },
-    { "PCI Mem1",      0x10000000, 0x13FFFFFF, IORESOURCE_MEM },
-    { "PCI I/O",       0x14000000, 0x17FFFFFF                 },
-    { "PCI Mem2",      0x1A000000, 0x1BFFFFFF, IORESOURCE_MEM },
-    { "PCI Mem3",      0x1C000000, 0x1FBFFFFF, IORESOURCE_MEM },
-    { "Flash",         0x08000000, 0x0CFFFFFF                 },
-    { "Boot ROM",      0x1FC00000, 0x1FFFFFFF                 }
+	{
+		.start	= 0,				/* to be initted */
+		.end	= 0,
+		.name	= "RAM",
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= 0x0C000000,
+		.end	= 0x0FFFFFFF,
+		.name	= "PCI Mem0",
+		.flags	= IORESOURCE_MEM
+	 }, {
+		.start	= 0x10000000,
+		.end	= 0x13FFFFFF,
+		.name	= "PCI Mem1",
+		.flags	= IORESOURCE_MEM
+	 }, {
+		.start	= 0x14000000,
+		.end	= 0x17FFFFFF
+		.name	= "PCI I/O",
+	}, {
+		.start	= 0x1A000000,
+		.end	= 0x1BFFFFFF,
+		.name	= "PCI Mem2",
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= 0x1C000000,
+		.end	= 0x1FBFFFFF,
+		.name	= "PCI Mem3",
+		.flags	= IORESOURCE_MEM
+	}, {
+		.start	= 0x08000000,
+		.end	= 0x0CFFFFFF
+		.name	= "Flash",
+	}, {
+		.start	= 0x1FC00000,
+		.end	= 0x1FFFFFFF
+		.name	= "Boot ROM",
+	}
 };
 #endif
 
@@ -106,7 +154,7 @@
 	it8172_resources.ram.end = memsize;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	unsigned short dsr;
 	char *argptr;
diff --git a/arch/mips/jazz/setup.c b/arch/mips/jazz/setup.c
index 4036dc4..c8d0df7 100644
--- a/arch/mips/jazz/setup.c
+++ b/arch/mips/jazz/setup.c
@@ -52,7 +52,7 @@
 	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
 };
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	int i;
 
diff --git a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c
index 9359cc4..308e6cd 100644
--- a/arch/mips/jmr3927/rbhma3100/setup.c
+++ b/arch/mips/jmr3927/rbhma3100/setup.c
@@ -82,17 +82,54 @@
     struct resource sio0;
     struct resource sio1;
 } jmr3927_resources = {
-    { "RAM0",           0,         0x01FFFFFF,  IORESOURCE_MEM },
-    { "RAM1",          0x02000000, 0x03FFFFFF,  IORESOURCE_MEM },
-    { "PCIMEM",        0x08000000, 0x07FFFFFF,  IORESOURCE_MEM },
-    { "IOB",           0x10000000, 0x13FFFFFF                  },
-    { "IOC",           0x14000000, 0x14FFFFFF                  },
-    { "PCIIO",         0x15000000, 0x15FFFFFF                  },
-    { "JMY1394",       0x1D000000, 0x1D3FFFFF                  },
-    { "ROM1",          0x1E000000, 0x1E3FFFFF                  },
-    { "ROM0",          0x1FC00000, 0x1FFFFFFF                  },
-    { "SIO0",          0xFFFEF300, 0xFFFEF3FF                  },
-    { "SIO1",          0xFFFEF400, 0xFFFEF4FF                  },
+	{
+		.start	= 0,
+		.end	= 0x01FFFFFF,
+		.name	= "RAM0",
+		.flags = IORESOURCE_MEM
+	}, {
+		.start	= 0x02000000,
+		.end	= 0x03FFFFFF,
+		.name	= "RAM1",
+		.flags = IORESOURCE_MEM
+	}, {
+		.start	= 0x08000000,
+		.end	= 0x07FFFFFF,
+		.name	= "PCIMEM",
+		.flags = IORESOURCE_MEM
+	}, {
+		.start	= 0x10000000,
+		.end	= 0x13FFFFFF,
+		.name	= "IOB"
+	}, {
+		.start	= 0x14000000,
+		.end	= 0x14FFFFFF,
+		.name	= "IOC"
+	}, {
+		.start	= 0x15000000,
+		.end	= 0x15FFFFFF,
+		.name	= "PCIIO"
+	}, {
+		.start	= 0x1D000000,
+		.end	= 0x1D3FFFFF,
+		.name	= "JMY1394"
+	}, {
+		.start	= 0x1E000000,
+		.end	= 0x1E3FFFFF,
+		.name	= "ROM1"
+	}, {
+		.start	= 0x1FC00000,
+		.end	= 0x1FFFFFFF,
+		.name	= "ROM0"
+	}, {
+		.start	= 0xFFFEF300,
+		.end	= 0xFFFEF3FF,
+		.name	= "SIO0"
+	}, {
+		.start	= 0xFFFEF400,
+		.end	= 0xFFFEF4FF,
+		.name	= "SIO1"
+	},
 };
 
 /* don't enable - see errata */
@@ -201,7 +238,7 @@
 extern struct resource pci_io_resource;
 extern struct resource pci_mem_resource;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	char *argptr;
 
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 34e8a25..881c467 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -13,6 +13,8 @@
 
 obj-$(CONFIG_MODULES)		+= mips_ksyms.o module.o
 
+obj-$(CONFIG_APM)		+= apm.o
+
 obj-$(CONFIG_CPU_R3000)		+= r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX39XX)	+= r2300_fpu.o r2300_switch.o
 obj-$(CONFIG_CPU_TX49XX)	+= r4k_fpu.o r4k_switch.o
diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c
new file mode 100644
index 0000000..15f46b4
--- /dev/null
+++ b/arch/mips/kernel/apm.c
@@ -0,0 +1,605 @@
+/*
+ * bios-less APM driver for MIPS Linux
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+
+#include <asm/apm.h> /* apm_power_info */
+#include <asm/system.h>
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV	134
+
+/*
+ * See Documentation/Config.help for the configuration options.
+ *
+ * Various options can be changed at boot time as follows:
+ * (We allow underscores for compatibility with the modules code)
+ *	apm=on/off			enable/disable APM
+ */
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS		16
+
+struct apm_queue {
+	unsigned int		event_head;
+	unsigned int		event_tail;
+	apm_event_t		events[APM_MAX_EVENTS];
+};
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+	struct list_head	list;
+
+	unsigned int		suser: 1;
+	unsigned int		writer: 1;
+	unsigned int		reader: 1;
+
+	int			suspend_result;
+	unsigned int		suspend_state;
+#define SUSPEND_NONE	0		/* no suspend pending */
+#define SUSPEND_PENDING	1		/* suspend pending read */
+#define SUSPEND_READ	2		/* suspend read, pending ack */
+#define SUSPEND_ACKED	3		/* suspend acked */
+#define SUSPEND_DONE	4		/* suspend completed */
+
+	struct apm_queue	queue;
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+static int apm_disabled;
+static int mips_apm_active;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static DECLARE_RWSEM(user_list_lock);
+static LIST_HEAD(apm_user_list);
+
+/*
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
+static DECLARE_COMPLETION(kapmd_exit);
+static DEFINE_SPINLOCK(kapmd_queue_lock);
+static struct apm_queue kapmd_queue;
+
+
+static const char driver_version[] = "1.13";	/* no spaces */
+
+
+
+/*
+ * Compatibility cruft until the IPAQ people move over to the new
+ * interface.
+ */
+static void __apm_get_power_status(struct apm_power_info *info)
+{
+}
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status;
+EXPORT_SYMBOL(apm_get_power_status);
+
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
+{
+	return q->event_head == q->event_tail;
+}
+
+static inline apm_event_t queue_get_event(struct apm_queue *q)
+{
+	q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+	return q->events[q->event_tail];
+}
+
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
+{
+	q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+	if (q->event_head == q->event_tail) {
+		static int notified;
+
+		if (notified++ == 0)
+		    printk(KERN_ERR "apm: an event queue overflowed\n");
+		q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+	}
+	q->events[q->event_head] = event;
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+	if (as->suser && as->writer) {
+		switch (event) {
+		case APM_SYS_SUSPEND:
+		case APM_USER_SUSPEND:
+			/*
+			 * If this user already has a suspend pending,
+			 * don't queue another one.
+			 */
+			if (as->suspend_state != SUSPEND_NONE)
+				return;
+
+			as->suspend_state = SUSPEND_PENDING;
+			suspends_pending++;
+			break;
+		}
+	}
+	queue_add_event(&as->queue, event);
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+	struct apm_user *as;
+
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
+		if (as != sender && as->reader)
+			queue_event_one_user(as, event);
+	}
+	up_read(&user_list_lock);
+	wake_up_interruptible(&apm_waitqueue);
+}
+
+static void apm_suspend(void)
+{
+	struct apm_user *as;
+	int err = pm_suspend(PM_SUSPEND_MEM);
+
+	/*
+	 * Anyone on the APM queues will think we're still suspended.
+	 * Send a message so everyone knows we're now awake again.
+	 */
+	queue_event(APM_NORMAL_RESUME, NULL);
+
+	/*
+	 * Finally, wake up anyone who is sleeping on the suspend.
+	 */
+	down_read(&user_list_lock);
+	list_for_each_entry(as, &apm_user_list, list) {
+		as->suspend_result = err;
+		as->suspend_state = SUSPEND_DONE;
+	}
+	up_read(&user_list_lock);
+
+	wake_up(&apm_suspend_waitqueue);
+}
+
+static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos)
+{
+	struct apm_user *as = fp->private_data;
+	apm_event_t event;
+	int i = count, ret = 0;
+
+	if (count < sizeof(apm_event_t))
+		return -EINVAL;
+
+	if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
+		return -EAGAIN;
+
+	wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
+
+	while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+		event = queue_get_event(&as->queue);
+
+		ret = -EFAULT;
+		if (copy_to_user(buf, &event, sizeof(event)))
+			break;
+
+		if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+			as->suspend_state = SUSPEND_READ;
+
+		buf += sizeof(event);
+		i -= sizeof(event);
+	}
+
+	if (i < count)
+		ret = count - i;
+
+	return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+	struct apm_user *as = fp->private_data;
+
+	poll_wait(fp, &apm_waitqueue, wait);
+	return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+	struct apm_user *as = filp->private_data;
+	unsigned long flags;
+	int err = -EINVAL;
+
+	if (!as->suser || !as->writer)
+		return -EPERM;
+
+	switch (cmd) {
+	case APM_IOC_SUSPEND:
+		as->suspend_result = -EINTR;
+
+		if (as->suspend_state == SUSPEND_READ) {
+			/*
+			 * If we read a suspend command from /dev/apm_bios,
+			 * then the corresponding APM_IOC_SUSPEND ioctl is
+			 * interpreted as an acknowledge.
+			 */
+			as->suspend_state = SUSPEND_ACKED;
+			suspends_pending--;
+		} else {
+			/*
+			 * Otherwise it is a request to suspend the system.
+			 * Queue an event for all readers, and expect an
+			 * acknowledge from all writers who haven't already
+			 * acknowledged.
+			 */
+			queue_event(APM_USER_SUSPEND, as);
+		}
+
+		/*
+		 * If there are no further acknowledges required, suspend
+		 * the system.
+		 */
+		if (suspends_pending == 0)
+			apm_suspend();
+
+		/*
+		 * Wait for the suspend/resume to complete.  If there are
+		 * pending acknowledges, we wait here for them.
+		 *
+		 * Note that we need to ensure that the PM subsystem does
+		 * not kick us out of the wait when it suspends the threads.
+		 */
+		flags = current->flags;
+		current->flags |= PF_NOFREEZE;
+
+		/*
+		 * Note: do not allow a thread which is acking the suspend
+		 * to escape until the resume is complete.
+		 */
+		if (as->suspend_state == SUSPEND_ACKED)
+			wait_event(apm_suspend_waitqueue,
+					 as->suspend_state == SUSPEND_DONE);
+		else
+			wait_event_interruptible(apm_suspend_waitqueue,
+					 as->suspend_state == SUSPEND_DONE);
+
+		current->flags = flags;
+		err = as->suspend_result;
+		as->suspend_state = SUSPEND_NONE;
+		break;
+	}
+
+	return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as = filp->private_data;
+	filp->private_data = NULL;
+
+	down_write(&user_list_lock);
+	list_del(&as->list);
+	up_write(&user_list_lock);
+
+	/*
+	 * We are now unhooked from the chain.  As far as new
+	 * events are concerned, we no longer exist.  However, we
+	 * need to balance suspends_pending, which means the
+	 * possibility of sleeping.
+	 */
+	if (as->suspend_state != SUSPEND_NONE) {
+		suspends_pending -= 1;
+		if (suspends_pending == 0)
+			apm_suspend();
+	}
+
+	kfree(as);
+	return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+	struct apm_user *as;
+
+	as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL);
+	if (as) {
+		/*
+		 * XXX - this is a tiny bit broken, when we consider BSD
+		 * process accounting. If the device is opened by root, we
+		 * instantly flag that we used superuser privs. Who knows,
+		 * we might close the device immediately without doing a
+		 * privileged operation -- cevans
+		 */
+		as->suser = capable(CAP_SYS_ADMIN);
+		as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+		as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+		down_write(&user_list_lock);
+		list_add(&as->list, &apm_user_list);
+		up_write(&user_list_lock);
+
+		filp->private_data = as;
+	}
+
+	return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+	.owner		= THIS_MODULE,
+	.read		= apm_read,
+	.poll		= apm_poll,
+	.ioctl		= apm_ioctl,
+	.open		= apm_open,
+	.release	= apm_release,
+};
+
+static struct miscdevice apm_device = {
+	.minor		= APM_MINOR_DEV,
+	.name		= "apm_bios",
+	.fops		= &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   0) Linux driver version (this will change if format changes)
+ *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
+ *   2) APM flags from APM Installation Check (0x00):
+ *	bit 0: APM_16_BIT_SUPPORT
+ *	bit 1: APM_32_BIT_SUPPORT
+ *	bit 2: APM_IDLE_SLOWS_CLOCK
+ *	bit 3: APM_BIOS_DISABLED
+ *	bit 4: APM_BIOS_DISENGAGED
+ *   3) AC line status
+ *	0x00: Off-line
+ *	0x01: On-line
+ *	0x02: On backup power (BIOS >= 1.1 only)
+ *	0xff: Unknown
+ *   4) Battery status
+ *	0x00: High
+ *	0x01: Low
+ *	0x02: Critical
+ *	0x03: Charging
+ *	0x04: Selected battery not present (BIOS >= 1.2 only)
+ *	0xff: Unknown
+ *   5) Battery flag
+ *	bit 0: High
+ *	bit 1: Low
+ *	bit 2: Critical
+ *	bit 3: Charging
+ *	bit 7: No system battery
+ *	0xff: Unknown
+ *   6) Remaining battery life (percentage of charge):
+ *	0-100: valid
+ *	-1: Unknown
+ *   7) Remaining battery life (time units):
+ *	Number of remaining minutes or seconds
+ *	-1: Unknown
+ *   8) min = minutes; sec = seconds
+ */
+static int apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+	struct apm_power_info info;
+	char *units;
+	int ret;
+
+	info.ac_line_status = 0xff;
+	info.battery_status = 0xff;
+	info.battery_flag   = 0xff;
+	info.battery_life   = -1;
+	info.time	    = -1;
+	info.units	    = -1;
+
+	if (apm_get_power_status)
+		apm_get_power_status(&info);
+
+	switch (info.units) {
+	default:	units = "?";	break;
+	case 0: 	units = "min";	break;
+	case 1: 	units = "sec";	break;
+	}
+
+	ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+		     driver_version, APM_32_BIT_SUPPORT,
+		     info.ac_line_status, info.battery_status,
+		     info.battery_flag, info.battery_life,
+		     info.time, units);
+
+ 	return ret;
+}
+#endif
+
+static int kapmd(void *arg)
+{
+	daemonize("kapmd");
+	current->flags |= PF_NOFREEZE;
+
+	do {
+		apm_event_t event;
+
+		wait_event_interruptible(kapmd_wait,
+				!queue_empty(&kapmd_queue) || !mips_apm_active);
+
+		if (!mips_apm_active)
+			break;
+
+		spin_lock_irq(&kapmd_queue_lock);
+		event = 0;
+		if (!queue_empty(&kapmd_queue))
+			event = queue_get_event(&kapmd_queue);
+		spin_unlock_irq(&kapmd_queue_lock);
+
+		switch (event) {
+		case 0:
+			break;
+
+		case APM_LOW_BATTERY:
+		case APM_POWER_STATUS_CHANGE:
+			queue_event(event, NULL);
+			break;
+
+		case APM_USER_SUSPEND:
+		case APM_SYS_SUSPEND:
+			queue_event(event, NULL);
+			if (suspends_pending == 0)
+				apm_suspend();
+			break;
+
+		case APM_CRITICAL_SUSPEND:
+			apm_suspend();
+			break;
+		}
+	} while (1);
+
+	complete_and_exit(&kapmd_exit, 0);
+}
+
+static int __init apm_init(void)
+{
+	int ret;
+
+	if (apm_disabled) {
+		printk(KERN_NOTICE "apm: disabled on user request.\n");
+		return -ENODEV;
+	}
+
+	mips_apm_active = 1;
+
+	ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+	if (ret < 0) {
+		mips_apm_active = 0;
+		return ret;
+	}
+
+#ifdef CONFIG_PROC_FS
+	create_proc_info_entry("apm", 0, NULL, apm_get_info);
+#endif
+
+	ret = misc_register(&apm_device);
+	if (ret != 0) {
+		remove_proc_entry("apm", NULL);
+
+		mips_apm_active = 0;
+		wake_up(&kapmd_wait);
+		wait_for_completion(&kapmd_exit);
+	}
+
+	return ret;
+}
+
+static void __exit apm_exit(void)
+{
+	misc_deregister(&apm_device);
+	remove_proc_entry("apm", NULL);
+
+	mips_apm_active = 0;
+	wake_up(&kapmd_wait);
+	wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
+
+#ifndef MODULE
+static int __init apm_setup(char *str)
+{
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "off", 3) == 0)
+			apm_disabled = 1;
+		if (strncmp(str, "on", 2) == 0)
+			apm_disabled = 0;
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+	return 1;
+}
+
+__setup("apm=", apm_setup);
+#endif
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&kapmd_queue_lock, flags);
+	queue_add_event(&kapmd_queue, event);
+	spin_unlock_irqrestore(&kapmd_queue_lock, flags);
+
+	wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index 0facfaf..f1bb6a2 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -141,72 +141,72 @@
 void output_thread_fpu_defines(void)
 {
 	offset("#define THREAD_FPR0    ",
-	       struct task_struct, thread.fpu.hard.fpr[0]);
+	       struct task_struct, thread.fpu.fpr[0]);
 	offset("#define THREAD_FPR1    ",
-	       struct task_struct, thread.fpu.hard.fpr[1]);
+	       struct task_struct, thread.fpu.fpr[1]);
 	offset("#define THREAD_FPR2    ",
-	       struct task_struct, thread.fpu.hard.fpr[2]);
+	       struct task_struct, thread.fpu.fpr[2]);
 	offset("#define THREAD_FPR3    ",
-	       struct task_struct, thread.fpu.hard.fpr[3]);
+	       struct task_struct, thread.fpu.fpr[3]);
 	offset("#define THREAD_FPR4    ",
-	       struct task_struct, thread.fpu.hard.fpr[4]);
+	       struct task_struct, thread.fpu.fpr[4]);
 	offset("#define THREAD_FPR5    ",
-	       struct task_struct, thread.fpu.hard.fpr[5]);
+	       struct task_struct, thread.fpu.fpr[5]);
 	offset("#define THREAD_FPR6    ",
-	       struct task_struct, thread.fpu.hard.fpr[6]);
+	       struct task_struct, thread.fpu.fpr[6]);
 	offset("#define THREAD_FPR7    ",
-	       struct task_struct, thread.fpu.hard.fpr[7]);
+	       struct task_struct, thread.fpu.fpr[7]);
 	offset("#define THREAD_FPR8    ",
-	       struct task_struct, thread.fpu.hard.fpr[8]);
+	       struct task_struct, thread.fpu.fpr[8]);
 	offset("#define THREAD_FPR9    ",
-	       struct task_struct, thread.fpu.hard.fpr[9]);
+	       struct task_struct, thread.fpu.fpr[9]);
 	offset("#define THREAD_FPR10   ",
-	       struct task_struct, thread.fpu.hard.fpr[10]);
+	       struct task_struct, thread.fpu.fpr[10]);
 	offset("#define THREAD_FPR11   ",
-	       struct task_struct, thread.fpu.hard.fpr[11]);
+	       struct task_struct, thread.fpu.fpr[11]);
 	offset("#define THREAD_FPR12   ",
-	       struct task_struct, thread.fpu.hard.fpr[12]);
+	       struct task_struct, thread.fpu.fpr[12]);
 	offset("#define THREAD_FPR13   ",
-	       struct task_struct, thread.fpu.hard.fpr[13]);
+	       struct task_struct, thread.fpu.fpr[13]);
 	offset("#define THREAD_FPR14   ",
-	       struct task_struct, thread.fpu.hard.fpr[14]);
+	       struct task_struct, thread.fpu.fpr[14]);
 	offset("#define THREAD_FPR15   ",
-	       struct task_struct, thread.fpu.hard.fpr[15]);
+	       struct task_struct, thread.fpu.fpr[15]);
 	offset("#define THREAD_FPR16   ",
-	       struct task_struct, thread.fpu.hard.fpr[16]);
+	       struct task_struct, thread.fpu.fpr[16]);
 	offset("#define THREAD_FPR17   ",
-	       struct task_struct, thread.fpu.hard.fpr[17]);
+	       struct task_struct, thread.fpu.fpr[17]);
 	offset("#define THREAD_FPR18   ",
-	       struct task_struct, thread.fpu.hard.fpr[18]);
+	       struct task_struct, thread.fpu.fpr[18]);
 	offset("#define THREAD_FPR19   ",
-	       struct task_struct, thread.fpu.hard.fpr[19]);
+	       struct task_struct, thread.fpu.fpr[19]);
 	offset("#define THREAD_FPR20   ",
-	       struct task_struct, thread.fpu.hard.fpr[20]);
+	       struct task_struct, thread.fpu.fpr[20]);
 	offset("#define THREAD_FPR21   ",
-	       struct task_struct, thread.fpu.hard.fpr[21]);
+	       struct task_struct, thread.fpu.fpr[21]);
 	offset("#define THREAD_FPR22   ",
-	       struct task_struct, thread.fpu.hard.fpr[22]);
+	       struct task_struct, thread.fpu.fpr[22]);
 	offset("#define THREAD_FPR23   ",
-	       struct task_struct, thread.fpu.hard.fpr[23]);
+	       struct task_struct, thread.fpu.fpr[23]);
 	offset("#define THREAD_FPR24   ",
-	       struct task_struct, thread.fpu.hard.fpr[24]);
+	       struct task_struct, thread.fpu.fpr[24]);
 	offset("#define THREAD_FPR25   ",
-	       struct task_struct, thread.fpu.hard.fpr[25]);
+	       struct task_struct, thread.fpu.fpr[25]);
 	offset("#define THREAD_FPR26   ",
-	       struct task_struct, thread.fpu.hard.fpr[26]);
+	       struct task_struct, thread.fpu.fpr[26]);
 	offset("#define THREAD_FPR27   ",
-	       struct task_struct, thread.fpu.hard.fpr[27]);
+	       struct task_struct, thread.fpu.fpr[27]);
 	offset("#define THREAD_FPR28   ",
-	       struct task_struct, thread.fpu.hard.fpr[28]);
+	       struct task_struct, thread.fpu.fpr[28]);
 	offset("#define THREAD_FPR29   ",
-	       struct task_struct, thread.fpu.hard.fpr[29]);
+	       struct task_struct, thread.fpu.fpr[29]);
 	offset("#define THREAD_FPR30   ",
-	       struct task_struct, thread.fpu.hard.fpr[30]);
+	       struct task_struct, thread.fpu.fpr[30]);
 	offset("#define THREAD_FPR31   ",
-	       struct task_struct, thread.fpu.hard.fpr[31]);
+	       struct task_struct, thread.fpu.fpr[31]);
 
 	offset("#define THREAD_FCR31   ",
-	       struct task_struct, thread.fpu.hard.fcr31);
+	       struct task_struct, thread.fpu.fcr31);
 	linefeed;
 }
 
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index b6232d9..76fd3f2 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -178,7 +178,7 @@
 		if (is_fpu_owner())
 			asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
 		else
-			fcr31 = current->thread.fpu.hard.fcr31;
+			fcr31 = current->thread.fpu.fcr31;
 		preempt_enable();
 
 		bit = (insn.i_format.rt >> 2);
diff --git a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c
index 2125ba5..0cb8ed5 100644
--- a/arch/mips/kernel/i8259.c
+++ b/arch/mips/kernel/i8259.c
@@ -302,11 +302,11 @@
 };
 
 static struct resource pic1_io_resource = {
-	"pic1", 0x20, 0x3f, IORESOURCE_BUSY
+	.name = "pic1", .start = 0x20, .end = 0x3f, .flags = IORESOURCE_BUSY
 };
 
 static struct resource pic2_io_resource = {
-	"pic2", 0xa0, 0xbf, IORESOURCE_BUSY
+	.name = "pic2", .start = 0xa0, .end = 0xbf, .flags = IORESOURCE_BUSY
 };
 
 /*
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 8150f07..676e868 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -13,6 +13,7 @@
 #include <linux/smp_lock.h>
 #include <linux/time.h>
 #include <linux/ptrace.h>
+#include <linux/resource.h>
 
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
@@ -260,7 +261,7 @@
 
 		for(i = 0; i < 32; i++)
 			error |= __get_user(fregs[i], &context->fpregs[i]);
-		error |= __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr);
+		error |= __get_user(current->thread.fpu.fcr31, &context->fpcsr);
 	}
 
 	/* XXX do sigstack crapola here... XXX */
@@ -540,8 +541,6 @@
 #define IRIX_P_PGID   2
 #define IRIX_P_ALL    7
 
-extern int getrusage(struct task_struct *, int, struct rusage __user *);
-
 #define W_EXITED     1
 #define W_TRAPPED    2
 #define W_STOPPED    4
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 9b4733c..1d44025 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -120,11 +120,11 @@
 			__put_user ((__u64) -1, i + (__u64 __user *) data);
 	}
 
+	__put_user (child->thread.fpu.fcr31, data + 64);
+
 	if (cpu_has_fpu) {
 		unsigned int flags, tmp;
 
-		__put_user (child->thread.fpu.hard.fcr31, data + 64);
-
 		preempt_disable();
 		if (cpu_has_mipsmt) {
 			unsigned int vpflags = dvpe();
@@ -142,7 +142,6 @@
 		preempt_enable();
 		__put_user (tmp, data + 65);
 	} else {
-		__put_user (child->thread.fpu.soft.fcr31, data + 64);
 		__put_user ((__u32) 0, data + 65);
 	}
 
@@ -162,10 +161,7 @@
 	for (i = 0; i < 32; i++)
 		__get_user (fregs[i], i + (__u64 __user *) data);
 
-	if (cpu_has_fpu)
-		__get_user (child->thread.fpu.hard.fcr31, data + 64);
-	else
-		__get_user (child->thread.fpu.soft.fcr31, data + 64);
+	__get_user (child->thread.fpu.fcr31, data + 64);
 
 	/* FIR may not be written.  */
 
@@ -241,10 +237,7 @@
 			tmp = regs->lo;
 			break;
 		case FPC_CSR:
-			if (cpu_has_fpu)
-				tmp = child->thread.fpu.hard.fcr31;
-			else
-				tmp = child->thread.fpu.soft.fcr31;
+			tmp = child->thread.fpu.fcr31;
 			break;
 		case FPC_EIR: {	/* implementation / version register */
 			unsigned int flags;
@@ -336,9 +329,9 @@
 
 			if (!tsk_used_math(child)) {
 				/* FP not yet used  */
-				memset(&child->thread.fpu.hard, ~0,
-				       sizeof(child->thread.fpu.hard));
-				child->thread.fpu.hard.fcr31 = 0;
+				memset(&child->thread.fpu, ~0,
+				       sizeof(child->thread.fpu));
+				child->thread.fpu.fcr31 = 0;
 			}
 #ifdef CONFIG_32BIT
 			/*
@@ -369,10 +362,7 @@
 			regs->lo = data;
 			break;
 		case FPC_CSR:
-			if (cpu_has_fpu)
-				child->thread.fpu.hard.fcr31 = data;
-			else
-				child->thread.fpu.soft.fcr31 = data;
+			child->thread.fpu.fcr31 = data;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index 8704dc0..f40ecd8 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -166,10 +166,7 @@
 			tmp = regs->lo;
 			break;
 		case FPC_CSR:
-			if (cpu_has_fpu)
-				tmp = child->thread.fpu.hard.fcr31;
-			else
-				tmp = child->thread.fpu.soft.fcr31;
+			tmp = child->thread.fpu.fcr31;
 			break;
 		case FPC_EIR: {	/* implementation / version register */
 			unsigned int flags;
@@ -288,9 +285,9 @@
 
 			if (!tsk_used_math(child)) {
 				/* FP not yet used  */
-				memset(&child->thread.fpu.hard, ~0,
-				       sizeof(child->thread.fpu.hard));
-				child->thread.fpu.hard.fcr31 = 0;
+				memset(&child->thread.fpu, ~0,
+				       sizeof(child->thread.fpu));
+				child->thread.fpu.fcr31 = 0;
 			}
 			/*
 			 * The odd registers are actually the high order bits
@@ -318,10 +315,7 @@
 			regs->lo = data;
 			break;
 		case FPC_CSR:
-			if (cpu_has_fpu)
-				child->thread.fpu.hard.fcr31 = data;
-			else
-				child->thread.fpu.soft.fcr31 = data;
+			child->thread.fpu.fcr31 = data;
 			break;
 		case DSP_BASE ... DSP_BASE + 5: {
 			dspreg_t *dregs;
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 0b1b54a..db94e55 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -75,8 +75,8 @@
 	and	t0, t0, t1
 	LONG_S	t0, ST_OFF(t3)
 
-	fpu_save_double a0 t1 t0 t2		# c0_status passed in t1
-						# clobbers t0 and t2
+	fpu_save_double a0 t0 t1		# c0_status passed in t0
+						# clobbers t1
 1:
 
 	/*
@@ -129,9 +129,9 @@
  */
 LEAF(_save_fp)
 #ifdef CONFIG_64BIT
-	mfc0	t1, CP0_STATUS
+	mfc0	t0, CP0_STATUS
 #endif
-	fpu_save_double a0 t1 t0 t2		# clobbers t1
+	fpu_save_double a0 t0 t1		# clobbers t1
 	jr	ra
 	END(_save_fp)
 
@@ -139,7 +139,10 @@
  * Restore a thread's fp context.
  */
 LEAF(_restore_fp)
-	fpu_restore_double a0, t1		# clobbers t1
+#ifdef CONFIG_64BIT
+	mfc0	t0, CP0_STATUS
+#endif
+	fpu_restore_double a0 t0 t1		# clobbers t1
 	jr	ra
 	END(_restore_fp)
 
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a0ac0e5..2d2fdf7 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -497,7 +497,7 @@
 	sys	sys_sched_get_priority_min 1
 	sys	sys_sched_rr_get_interval 2	/* 4165 */
 	sys	sys_nanosleep,		2
-	sys	sys_mremap,		4
+	sys	sys_mremap,		5
 	sys	sys_accept		3
 	sys	sys_bind		3
 	sys	sys_connect		3	/* 4170 */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 397a70e..bfcec8d 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -442,6 +442,48 @@
 #endif /* CONFIG_BLK_DEV_INITRD  */
 }
 
+/*
+ * arch_mem_init - initialize memory managment subsystem
+ *
+ *  o plat_mem_setup() detects the memory configuration and will record detected
+ *    memory areas using add_memory_region.
+ *  o parse_cmdline_early() parses the command line for mem= options which,
+ *    iff detected, will override the results of the automatic detection.
+ *
+ * At this stage the memory configuration of the system is known to the
+ * kernel but generic memory managment system is still entirely uninitialized.
+ *
+ *  o bootmem_init()
+ *  o sparse_init()
+ *  o paging_init()
+ *
+ * At this stage the bootmem allocator is ready to use.
+ *
+ * NOTE: historically plat_mem_setup did the entire platform initialization.
+ *       This was rather impractical because it meant plat_mem_setup had to
+ * get away without any kind of memory allocator.  To keep old code from
+ * breaking plat_setup was just renamed to plat_setup and a second platform
+ * initialization hook for anything else was introduced.
+ */
+
+extern void plat_mem_setup(void);
+
+static void __init arch_mem_init(char **cmdline_p)
+{
+	/* call board setup routine */
+	plat_mem_setup();
+
+	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
+	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+
+	*cmdline_p = command_line;
+
+	parse_cmdline_early();
+	bootmem_init();
+	sparse_init();
+	paging_init();
+}
+
 static inline void resource_init(void)
 {
 	int i;
@@ -495,8 +537,6 @@
 #undef MAXMEM
 #undef MAXMEM_PFN
 
-extern void plat_setup(void);
-
 void __init setup_arch(char **cmdline_p)
 {
 	cpu_probe();
@@ -511,18 +551,8 @@
 #endif
 #endif
 
-	/* call board setup routine */
-	plat_setup();
+	arch_mem_init(cmdline_p);
 
-	strlcpy(command_line, arcs_cmdline, sizeof(command_line));
-	strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-
-	*cmdline_p = command_line;
-
-	parse_cmdline_early();
-	bootmem_init();
-	sparse_init();
-	paging_init();
 	resource_init();
 #ifdef CONFIG_SMP
 	plat_smp_setup();
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 298f82f..9096a5e 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -446,7 +446,7 @@
 	int ret;
 
 	for_each_present_cpu(cpu) {
-		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
+		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu);
 		if (ret)
 			printk(KERN_WARNING "topology_init: register_cpu %d "
 			       "failed (%d)\n", cpu, ret);
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 2e8e52c..70cf09a 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -367,7 +367,7 @@
 	dvpe();
 	dmt();
 
-	freeIPIq.lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&freeIPIq.lock);
 
 	/*
 	 * We probably don't have as many VPEs as we do SMP "CPUs",
@@ -375,7 +375,7 @@
 	 */
 	for (i=0; i<NR_CPUS; i++) {
 		IPIQ[i].head = IPIQ[i].tail = NULL;
-		IPIQ[i].lock = SPIN_LOCK_UNLOCKED;
+		spin_lock_init(&IPIQ[i].lock);
 		IPIQ[i].depth = 0;
 		ipi_timer_latch[i] = 0;
 	}
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 5407b78..1137dd6 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -31,6 +31,7 @@
 #include <linux/socket.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/resource.h>
 
 #include <asm/ptrace.h>
 #include <asm/page.h>
@@ -235,7 +236,6 @@
 #undef DEBUG_PROCGRPS
 
 extern unsigned long irix_mapelf(int fd, struct elf_phdr __user *user_phdrp, int cnt);
-extern int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
 extern char *prom_getenv(char *name);
 extern long prom_setenv(char *name, char *value);
 
@@ -694,7 +694,7 @@
 	if (error)
 		goto out;
 
-	error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(nd.dentry, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -732,7 +732,7 @@
 		goto out;
 	}
 
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(file->f_dentry, &kbuf);
 	if (error)
 		goto out_f;
 
@@ -1360,7 +1360,7 @@
 	error = user_path_walk(fname, &nd);
 	if (error)
 		goto out;
-	error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(nd.dentry, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -1406,7 +1406,7 @@
 		error = -EBADF;
 		goto out;
 	}
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(file->f_dentry, &kbuf);
 	if (error)
 		goto out_f;
 
@@ -1611,7 +1611,7 @@
 	error = user_path_walk(fname, &nd);
 	if (error)
 		goto out;
-	error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(nd.dentry, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -1658,7 +1658,7 @@
 		error = -EBADF;
 		goto out;
 	}
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
+	error = vfs_statfs(file->f_dentry, &kbuf);
 	if (error)
 		goto out_f;
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index a7564b0..ad16ece 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -65,7 +65,7 @@
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-	struct mips_fpu_soft_struct *ctx);
+	struct mips_fpu_struct *ctx);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -600,8 +600,7 @@
 		preempt_enable();
 
 		/* Run the emulator */
-		sig = fpu_emulator_cop1Handler (regs,
-			&current->thread.fpu.soft);
+		sig = fpu_emulator_cop1Handler (regs, &current->thread.fpu);
 
 		preempt_disable();
 
@@ -610,7 +609,7 @@
 		 * We can't allow the emulated instruction to leave any of
 		 * the cause bit set in $fcr31.
 		 */
-		current->thread.fpu.soft.fcr31 &= ~FPU_CSR_ALL_X;
+		current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
 
 		/* Restore the hardware register state */
 		restore_fp(current);
@@ -755,7 +754,7 @@
 
 		if (!cpu_has_fpu) {
 			int sig = fpu_emulator_cop1Handler(regs,
-						&current->thread.fpu.soft);
+						&current->thread.fpu);
 			if (sig)
 				force_sig(sig, current);
 #ifdef CONFIG_MIPS_MT_FPAFF
diff --git a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c
index bb70a82..3f64277 100644
--- a/arch/mips/lasat/setup.c
+++ b/arch/mips/lasat/setup.c
@@ -155,7 +155,7 @@
 }
 #endif
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	int i;
 	lasat_misc  = &lasat_misc_info[mips_machtype];
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index cf12caf..b225543 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -7,4 +7,7 @@
 
 obj-y	+= iomap.o
 
+# libgcc-style stuff needed in the kernel
+lib-y += ashldi3.o ashrdi3.o lshrdi3.o
+
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
new file mode 100644
index 0000000..beb80f31
--- /dev/null
+++ b/arch/mips/lib/ashldi3.c
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashldi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		w.s.low = 0;
+		w.s.high = (unsigned int) uu.s.low << -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+		w.s.low = (unsigned int) uu.s.low << b;
+		w.s.high = ((unsigned int) uu.s.high << b) | carries;
+	}
+
+	return w.ll;
+}
+
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
new file mode 100644
index 0000000..c884a91
--- /dev/null
+++ b/arch/mips/lib/ashrdi3.c
@@ -0,0 +1,31 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashrdi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high =
+		    uu.s.high >> 31;
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h
new file mode 100644
index 0000000..3f19d1c
--- /dev/null
+++ b/arch/mips/lib/libgcc.h
@@ -0,0 +1,26 @@
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+	int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+	int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union
+{
+	struct DWstruct s;
+	long long ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
new file mode 100644
index 0000000..dcf8d68
--- /dev/null
+++ b/arch/mips/lib/lshrdi3.c
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __lshrdi3(long long u, word_type b)
+{
+	DWunion uu, w;
+	word_type bm;
+
+	if (b == 0)
+		return u;
+
+	uu.ll = u;
+	bm = 32 - b;
+
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (unsigned int) uu.s.high >> -bm;
+	} else {
+		const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+		w.s.high = (unsigned int) uu.s.high >> b;
+		w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+	}
+
+	return w.ll;
+}
+
+EXPORT_SYMBOL(__lshrdi3);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index aa5818a..3f0d5d2 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -60,15 +60,15 @@
 
 /* Function which emulates a floating point instruction. */
 
-static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
 	mips_instruction);
 
 #if __mips >= 4 && __mips != 32
 static int fpux_emu(struct pt_regs *,
-	struct mips_fpu_soft_struct *, mips_instruction);
+	struct mips_fpu_struct *, mips_instruction);
 #endif
 
-/* Further private data for which no space exists in mips_fpu_soft_struct */
+/* Further private data for which no space exists in mips_fpu_struct */
 
 struct mips_fpu_emulator_stats fpuemustats;
 
@@ -203,7 +203,7 @@
  * Two instructions if the instruction is in a branch delay slot.
  */
 
-static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx)
+static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 {
 	mips_instruction ir;
 	void * emulpc, *contpc;
@@ -595,7 +595,7 @@
 DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
 
-static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	mips_instruction ir)
 {
 	unsigned rcsr = 0;	/* resulting csr */
@@ -759,7 +759,7 @@
 /*
  * Emulate a single COP1 arithmetic instruction.
  */
-static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 	mips_instruction ir)
 {
 	int rfmt;		/* resulting format */
@@ -1233,8 +1233,7 @@
 	return 0;
 }
 
-int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-	struct mips_fpu_soft_struct *ctx)
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 {
 	unsigned long oldepc, prevepc;
 	mips_instruction insn;
diff --git a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h
index 171f177..dd91733 100644
--- a/arch/mips/math-emu/ieee754.h
+++ b/arch/mips/math-emu/ieee754.h
@@ -329,7 +329,7 @@
 	unsigned pad0:7;
 #endif
 };
-#define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.soft.fcr31))
+#define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.fcr31))
 
 static inline unsigned ieee754_getrm(void)
 {
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c
index d187ab7..56ca0c6 100644
--- a/arch/mips/math-emu/kernel_linkage.c
+++ b/arch/mips/math-emu/kernel_linkage.c
@@ -39,9 +39,9 @@
 		printk("Algorithmics/MIPS FPU Emulator v1.5\n");
 	}
 
-	current->thread.fpu.soft.fcr31 = 0;
+	current->thread.fpu.fcr31 = 0;
 	for (i = 0; i < 32; i++) {
-		current->thread.fpu.soft.fpr[i] = SIGNALLING_NAN;
+		current->thread.fpu.fpr[i] = SIGNALLING_NAN;
 	}
 }
 
@@ -59,10 +59,9 @@
 
 	for (i = 0; i < 32; i++) {
 		err |=
-		    __put_user(current->thread.fpu.soft.fpr[i],
-			       &sc->sc_fpregs[i]);
+		    __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
 	}
-	err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
 	return err;
 }
@@ -74,10 +73,9 @@
 
 	for (i = 0; i < 32; i++) {
 		err |=
-		    __get_user(current->thread.fpu.soft.fpr[i],
-			       &sc->sc_fpregs[i]);
+		    __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
 	}
-	err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
 	return err;
 }
@@ -94,10 +92,9 @@
 
 	for (i = 0; i < 32; i+=2) {
 		err |=
-		    __put_user(current->thread.fpu.soft.fpr[i],
-			       &sc->sc_fpregs[i]);
+		    __put_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
 	}
-	err |= __put_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+	err |= __put_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
 	return err;
 }
@@ -109,10 +106,9 @@
 
 	for (i = 0; i < 32; i+=2) {
 		err |=
-		    __get_user(current->thread.fpu.soft.fpr[i],
-			       &sc->sc_fpregs[i]);
+		    __get_user(current->thread.fpu.fpr[i], &sc->sc_fpregs[i]);
 	}
-	err |= __get_user(current->thread.fpu.soft.fcr31, &sc->sc_fpc_csr);
+	err |= __get_user(current->thread.fpu.fcr31, &sc->sc_fpc_csr);
 
 	return err;
 }
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
index c20d401..8cc9eff 100644
--- a/arch/mips/mips-boards/atlas/atlas_setup.c
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -50,7 +50,7 @@
 	return "MIPS Atlas";
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	mips_pcibios_init();
 
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index bc4d093..fd49256 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -76,6 +76,15 @@
 			memsize = simple_strtol(memsize_str, NULL, 0);
 		}
 	}
+
+#ifdef CONFIG_CPU_BIG_ENDIAN
+	/*
+	 * SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
+	 * word of physical memory
+	 */
+	memsize -= PAGE_SIZE;
+#endif
+
 	memset(mdesc, 0, sizeof(mdesc));
 
 	mdesc[0].type = yamon_dontuse;
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
index b8488aa..0766e43 100644
--- a/arch/mips/mips-boards/malta/malta_setup.c
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -53,11 +53,11 @@
 #endif
 
 struct resource standard_io_resources[] = {
-	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
-	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+	{ .name = "dma1", .start = 0x00, .end = 0x1f, .flags = IORESOURCE_BUSY },
+	{ .name = "timer", .start = 0x40, .end = 0x5f, .flags = IORESOURCE_BUSY },
+	{ .name = "keyboard", .start = 0x60, .end = 0x6f, .flags = IORESOURCE_BUSY },
+	{ .name = "dma page reg", .start = 0x80, .end = 0x8f, .flags = IORESOURCE_BUSY },
+	{ .name = "dma2", .start = 0xc0, .end = 0xdf, .flags = IORESOURCE_BUSY },
 };
 
 #ifdef CONFIG_MTD
@@ -111,7 +111,7 @@
 }
 #endif
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	unsigned int i;
 
diff --git a/arch/mips/mips-boards/malta/malta_smp.c b/arch/mips/mips-boards/malta/malta_smp.c
index 6c6c8ee..cf96717 100644
--- a/arch/mips/mips-boards/malta/malta_smp.c
+++ b/arch/mips/mips-boards/malta/malta_smp.c
@@ -34,25 +34,6 @@
 }
 
 /*
- * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
- */
-
-void __init prom_build_cpu_map(void)
-{
-	int nextslot;
-
-	/*
-	 * As of November, 2004, MIPSsim only simulates one core
-	 * at a time.  However, that core may be a MIPS MT core
-	 * with multiple virtual processors and thread contexts.
-	 */
-
-	if (read_c0_config3() & (1<<2)) {
-		nextslot = mipsmt_build_cpu_map(1);
-	}
-}
-
-/*
  * Platform "CPU" startup hook
  */
 
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
index 4266ce4..6430f11 100644
--- a/arch/mips/mips-boards/sead/sead_setup.c
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -45,7 +45,7 @@
 	return "MIPS SEAD";
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	ioport_resource.end = 0x7fffffff;
 
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c
index a2fd629..15a5dac 100644
--- a/arch/mips/mips-boards/sim/sim_setup.c
+++ b/arch/mips/mips-boards/sim/sim_setup.c
@@ -50,7 +50,7 @@
 	return "MIPSsim";
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	set_io_port_base(0xbfd00000);
 
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mips-boards/sim/sim_smp.c
index b7084e7..0040709 100644
--- a/arch/mips/mips-boards/sim/sim_smp.c
+++ b/arch/mips/mips-boards/sim/sim_smp.c
@@ -51,27 +51,6 @@
 }
 
 /*
- * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
- */
-
-void __init prom_build_cpu_map(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-	int nextslot;
-
-	/*
-	 * As of November, 2004, MIPSsim only simulates one core
-	 * at a time.  However, that core may be a MIPS MT core
-	 * with multiple virtual processors and thread contexts.
-	 */
-
-	if (read_c0_config3() & (1<<2)) {
-		nextslot = mipsmt_build_cpu_map(1);
-	}
-#endif /* CONFIG_MIPS_MT_SMTC */
-}
-
-/*
  * Platform "CPU" startup hook
  */
 
diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c
index 9dca099..965cb4c 100644
--- a/arch/mips/mm/tlb-r4k.c
+++ b/arch/mips/mm/tlb-r4k.c
@@ -413,7 +413,6 @@
 	return ret;
 }
 
-extern void __init sanitize_tlb_entries(void);
 static void __init probe_tlb(unsigned long config)
 {
 	struct cpuinfo_mips *c = &current_cpu_data;
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
index 1379c76..df14855 100644
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ b/arch/mips/momentum/jaguar_atx/setup.c
@@ -359,7 +359,7 @@
 
 arch_initcall(ja_pci_init);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	unsigned int tmpword;
 
diff --git a/arch/mips/momentum/ocelot_3/setup.c b/arch/mips/momentum/ocelot_3/setup.c
index c691952..8c53490 100644
--- a/arch/mips/momentum/ocelot_3/setup.c
+++ b/arch/mips/momentum/ocelot_3/setup.c
@@ -313,7 +313,7 @@
 
 arch_initcall(ja_pci_init);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	unsigned int tmpword;
 
diff --git a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c
index a3e6f55..257e1d1 100644
--- a/arch/mips/momentum/ocelot_c/setup.c
+++ b/arch/mips/momentum/ocelot_c/setup.c
@@ -231,7 +231,7 @@
 	rtc_mips_set_time = m48t37y_set_time;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	unsigned int tmpword;
 
diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c
index e5eceed..8bd9b84 100644
--- a/arch/mips/momentum/ocelot_g/gt-irq.c
+++ b/arch/mips/momentum/ocelot_g/gt-irq.c
@@ -59,7 +59,7 @@
  * bit_num   - Indicates which bit number in the cause register
  *
  * Outputs :
- * 1 if succesful, 0 if failure
+ * 1 if successful, 0 if failure
  */
 int enable_galileo_irq(int int_cause, int bit_num)
 {
@@ -83,7 +83,7 @@
  * bit_num   - Indicates which bit number in the cause register
  *
  * Outputs :
- * 1 if succesful, 0 if failure
+ * 1 if successful, 0 if failure
  */
 int disable_galileo_irq(int int_cause, int bit_num)
 {
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
index fed4e8e..72143ab 100644
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ b/arch/mips/momentum/ocelot_g/setup.c
@@ -162,7 +162,7 @@
 	printk("Done\n");
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache);
 	unsigned int tmpword;
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index c31e4cf..65eb5540 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -38,7 +38,7 @@
 
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry *dir;
-		char buf[3];
+		char buf[4];
 
 		snprintf(buf, sizeof buf, "%d", i);
 		dir = oprofilefs_mkdir(sb, root, buf);
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 16205b5..465778c 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -18,12 +18,12 @@
 obj-$(CONFIG_MIPS_TX3927)	+= ops-tx3927.o
 obj-$(CONFIG_PCI_VR41XX)	+= ops-vr41xx.o pci-vr41xx.o
 obj-$(CONFIG_NEC_CMBVR4133)	+= fixup-vr4133.o
+obj-$(CONFIG_MARKEINS)		+= ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o
 
 #
 # These are still pretty much in the old state, watch, go blind.
 #
-obj-$(CONFIG_DDB5074)		+= fixup-ddb5074.o pci-ddb5074.o ops-ddb5074.o
-obj-$(CONFIG_DDB5476)		+= ops-ddb5476.o pci-ddb5476.o
+obj-$(CONFIG_BASLER_EXCITE)	= ops-titan.o pci-excite.o fixup-excite.o
 obj-$(CONFIG_DDB5477)		+= fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
 obj-$(CONFIG_LASAT)		+= pci-lasat.o
 obj-$(CONFIG_MIPS_ATLAS)	+= fixup-atlas.o
@@ -43,7 +43,7 @@
 obj-$(CONFIG_MOMENCO_OCELOT_G)	+= fixup-ocelot-g.o pci-ocelot-g.o
 obj-$(CONFIG_PMC_YOSEMITE)	+= fixup-yosemite.o ops-titan.o ops-titan-ht.o \
 				   pci-yosemite.o
-obj-$(CONFIG_SGI_IP27)		+= pci-ip27.o
+obj-$(CONFIG_SGI_IP27)		+= ops-bridge.o pci-ip27.o
 obj-$(CONFIG_SGI_IP32)		+= fixup-ip32.o ops-mace.o pci-ip32.o
 obj-$(CONFIG_SIBYTE_SB1250)	+= fixup-sb1250.o pci-sb1250.o
 obj-$(CONFIG_SIBYTE_BCM112X)	+= fixup-sb1250.o pci-sb1250.o
@@ -57,3 +57,4 @@
 obj-$(CONFIG_TOSHIBA_RBTX4938)	+= fixup-tx4938.o ops-tx4938.o
 obj-$(CONFIG_VICTOR_MPC30X)	+= fixup-mpc30x.o
 obj-$(CONFIG_ZAO_CAPCELLA)	+= fixup-capcella.o
+obj-$(CONFIG_WR_PPMC)		+= fixup-wrppmc.o
diff --git a/arch/mips/pci/fixup-ddb5074.c b/arch/mips/pci/fixup-ddb5074.c
deleted file mode 100644
index 5a4a7c2..0000000
--- a/arch/mips/pci/fixup-ddb5074.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * It's nice to have the LEDs on the GPIO pins available for debugging
- */
-static void ddb5074_fixup(struct pci_dev *dev)
-{
-	extern struct pci_dev *pci_pmu;
-	u8 t8;
-
-	pci_pmu = dev;  /* for LEDs D2 and D3 */
-	/* Program the lines for LEDs D2 and D3 to output */
-	pci_read_config_byte(dev, 0x7d, &t8);
-	t8 |= 0xc0;
-	pci_write_config_byte(dev, 0x7d, t8);
-	/* Turn LEDs D2 and D3 off */
-	pci_read_config_byte(dev, 0x7e, &t8);
-	t8 |= 0xc0;
-	pci_write_config_byte(dev, 0x7e, t8);
-}
-
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
-	  ddb5074_fixup);
diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c
new file mode 100644
index 0000000..3a34cd0
--- /dev/null
+++ b/arch/mips/pci/fixup-emma2rh.c
@@ -0,0 +1,102 @@
+/*
+ *  arch/mips/pci/fixup-emma2rh.c
+ *      This file defines the PCI configration.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define EMMA2RH_PCI_HOST_SLOT 0x09
+#define EMMA2RH_USB_SLOT 0x03
+#define PCI_DEVICE_ID_NEC_EMMA2RH      0x014b /* EMMA2RH PCI Host */
+
+/*
+ * we fix up irqs based on the slot number.
+ * The first entry is at AD:11.
+ * Fortunately this works because, although we have two pci buses,
+ * they all have different slot numbers (except for rockhopper slot 20
+ * which is handled below).
+ *
+ */
+
+#define	MAX_SLOT_NUM 10
+static unsigned char irq_map[][5] __initdata = {
+	[3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC,
+	       MARKEINS_PCI_IRQ_INTD, 0,},
+	[4] = {0, MARKEINS_PCI_IRQ_INTA, 0, 0, 0,},
+	[5] = {0, 0, 0, 0, 0,},
+	[6] = {0, MARKEINS_PCI_IRQ_INTC, MARKEINS_PCI_IRQ_INTD,
+	       MARKEINS_PCI_IRQ_INTA, MARKEINS_PCI_IRQ_INTB,},
+};
+
+static void __devinit nec_usb_controller_fixup(struct pci_dev *dev)
+{
+	if (PCI_SLOT(dev->devfn) == EMMA2RH_USB_SLOT)
+		/* on board USB controller configuration */
+		pci_write_config_dword(dev, 0xe4, 1 << 5);
+}
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
+			nec_usb_controller_fixup);
+
+/*
+ * Prevent the PCI layer from seeing the resources allocated to this device
+ * if it is the host bridge by marking it as such.  These resources are of
+ * no consequence to the PCI layer (they are handled elsewhere).
+ */
+static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev)
+{
+	int i;
+
+	if (PCI_SLOT(dev->devfn) == EMMA2RH_PCI_HOST_SLOT) {
+		dev->class &= 0xff;
+		dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			dev->resource[i].start = 0;
+			dev->resource[i].end = 0;
+			dev->resource[i].flags = 0;
+		}
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH,
+			 emma2rh_pci_host_fixup);
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irq_map[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c
new file mode 100644
index 0000000..1da696d
--- /dev/null
+++ b/arch/mips/pci/fixup-excite.c
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <excite.h>
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (pin == 0)
+		return -1;
+
+	return USB_IRQ;		/* USB controller is the only PCI device */
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c
new file mode 100644
index 0000000..3357c13
--- /dev/null
+++ b/arch/mips/pci/fixup-wrppmc.c
@@ -0,0 +1,37 @@
+/*
+ * fixup-wrppmc.c: PPMC board specific PCI fixup
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006, Wind River Inc. Rongkai.zhan (rongkai.zhan@windriver.com)
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/gt64120.h>
+
+/* PCI interrupt pins */
+#define PCI_INTA		1
+#define PCI_INTB		2
+#define PCI_INTC		3
+#define PCI_INTD		4
+
+#define PCI_SLOT_MAXNR	32 /* Each PCI bus has 32 physical slots */
+
+static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = {
+	/* 0    INTA   INTB   INTC   INTD */
+	[0] = {0, 0, 0, 0, 0},		/* Slot 0: GT64120 PCI bridge */
+	[6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0},
+};
+
+int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return pci_irq_tab[slot][pin];
+}
+
+/* Do platform specific device initialization at pci_enable_device() time */
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+	return 0;
+}
diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c
new file mode 100644
index 0000000..1fa0992
--- /dev/null
+++ b/arch/mips/pci/ops-bridge.c
@@ -0,0 +1,306 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/pci.h>
+#include <asm/paccess.h>
+#include <asm/pci/bridge.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/sn0/hub.h>
+
+/*
+ * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
+ * not really documented, so right now I can't write code which uses it.
+ * Therefore we use type 0 accesses for now even though they won't work
+ * correcly for PCI-to-PCI bridges.
+ *
+ * The function is complicated by the ultimate brokeness of the IOC3 chip
+ * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
+ * accesses and does only decode parts of it's address space.
+ */
+
+static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 * value)
+{
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+	bridge_t *bridge = bc->base;
+	int slot = PCI_SLOT(devfn);
+	int fn = PCI_FUNC(devfn);
+	volatile void *addr;
+	u32 cf, shift, mask;
+	int res;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at it for real ...
+	 */
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+		goto oh_my_gawd;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+	if (size == 1)
+		res = get_dbe(*value, (u8 *) addr);
+	else if (size == 2)
+		res = get_dbe(*value, (u16 *) addr);
+	else
+		res = get_dbe(*value, (u32 *) addr);
+
+	return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at the wrong register.
+	 */
+	if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
+	 * anything but 32-bit words ...
+	 */
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	shift = ((where & 3) << 3);
+	mask = (0xffffffffU >> ((4 - size) << 3));
+	*value = (cf >> shift) & mask;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
+				 int where, int size, u32 * value)
+{
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+	bridge_t *bridge = bc->base;
+	int busno = bus->number;
+	int slot = PCI_SLOT(devfn);
+	int fn = PCI_FUNC(devfn);
+	volatile void *addr;
+	u32 cf, shift, mask;
+	int res;
+
+	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+	addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at it for real ...
+	 */
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+		goto oh_my_gawd;
+
+	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+	addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+	if (size == 1)
+		res = get_dbe(*value, (u8 *) addr);
+	else if (size == 2)
+		res = get_dbe(*value, (u16 *) addr);
+	else
+		res = get_dbe(*value, (u32 *) addr);
+
+	return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at the wrong register.
+	 */
+	if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
+		*value = 0;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
+	 * anything but 32-bit words ...
+	 */
+	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+	addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
+
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	shift = ((where & 3) << 3);
+	mask = (0xffffffffU >> ((4 - size) << 3));
+	*value = (cf >> shift) & mask;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
+			   int where, int size, u32 * value)
+{
+	if (bus->number > 0)
+		return pci_conf1_read_config(bus, devfn, where, size, value);
+
+	return pci_conf0_read_config(bus, devfn, where, size, value);
+}
+
+static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 value)
+{
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+	bridge_t *bridge = bc->base;
+	int slot = PCI_SLOT(devfn);
+	int fn = PCI_FUNC(devfn);
+	volatile void *addr;
+	u32 cf, shift, mask, smask;
+	int res;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at it for real ...
+	 */
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+		goto oh_my_gawd;
+
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
+
+	if (size == 1) {
+		res = put_dbe(value, (u8 *) addr);
+	} else if (size == 2) {
+		res = put_dbe(value, (u16 *) addr);
+	} else {
+		res = put_dbe(value, (u32 *) addr);
+	}
+
+	if (res)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to touch the wrong register.
+	 */
+	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+		return PCIBIOS_SUCCESSFUL;
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
+	 * anything but 32-bit words ...
+	 */
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	shift = ((where & 3) << 3);
+	mask = (0xffffffffU >> ((4 - size) << 3));
+	smask = mask << shift;
+
+	cf = (cf & ~smask) | ((value & mask) << shift);
+	if (put_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
+				  int where, int size, u32 value)
+{
+	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
+	bridge_t *bridge = bc->base;
+	int slot = PCI_SLOT(devfn);
+	int fn = PCI_FUNC(devfn);
+	int busno = bus->number;
+	volatile void *addr;
+	u32 cf, shift, mask, smask;
+	int res;
+
+	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
+	addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to look at it for real ...
+	 */
+	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
+		goto oh_my_gawd;
+
+	addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
+
+	if (size == 1) {
+		res = put_dbe(value, (u8 *) addr);
+	} else if (size == 2) {
+		res = put_dbe(value, (u16 *) addr);
+	} else {
+		res = put_dbe(value, (u32 *) addr);
+	}
+
+	if (res)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+
+oh_my_gawd:
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
+	 * generic PCI code a chance to touch the wrong register.
+	 */
+	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
+		return PCIBIOS_SUCCESSFUL;
+
+	/*
+	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
+	 * anything but 32-bit words ...
+	 */
+	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
+
+	if (get_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	shift = ((where & 3) << 3);
+	mask = (0xffffffffU >> ((4 - size) << 3));
+	smask = mask << shift;
+
+	cf = (cf & ~smask) | ((value & mask) << shift);
+	if (put_dbe(cf, (u32 *) addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
+	int where, int size, u32 value)
+{
+	if (bus->number > 0)
+		return pci_conf1_write_config(bus, devfn, where, size, value);
+
+	return pci_conf0_write_config(bus, devfn, where, size, value);
+}
+
+struct pci_ops bridge_pci_ops = {
+	.read	= pci_read_config,
+	.write	= pci_write_config,
+};
diff --git a/arch/mips/pci/ops-ddb5074.c b/arch/mips/pci/ops-ddb5074.c
deleted file mode 100644
index 89f97bef4..0000000
--- a/arch/mips/pci/ops-ddb5074.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/ddb5xxx/ddb5476/pci_ops.c
- *     Define the pci_ops for DB5477.
- *
- * Much of the code is derived from the original DDB5074 port by
- * Geert Uytterhoeven <geert@sonycom.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-/*
- * config_swap structure records what set of pdar/pmr are used
- * to access pci config space.  It also provides a place hold the
- * original values for future restoring.
- */
-struct pci_config_swap {
-	u32 pdar;
-	u32 pmr;
-	u32 config_base;
-	u32 config_size;
-	u32 pdar_backup;
-	u32 pmr_backup;
-};
-
-/*
- * On DDB5476, we have one set of swap registers
- */
-struct pci_config_swap ext_pci_swap = {
-	DDB_PCIW0,
-	DDB_PCIINIT0,
-	DDB_PCI_CONFIG_BASE,
-	DDB_PCI_CONFIG_SIZE
-};
-
-static int pci_config_workaround = 1;
-
-/*
- * access config space
- */
-static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus,	/* 0 means top level bus */
-					 u32 slot_num)
-{
-	u32 pci_addr = 0;
-	u32 pciinit_offset = 0;
-	u32 virt_addr = swap->config_base;
-	u32 option;
-
-	if (pci_config_workaround) {
-		if (slot_num == 5)
-			slot_num = 14;
-	} else {
-		if (slot_num == 5)
-			return DDB_BASE + DDB_PCI_BASE;
-	}
-
-	/* minimum pdar (window) size is 2MB */
-	db_assert(swap->config_size >= (2 << 20));
-
-	db_assert(slot_num < (1 << 5));
-	db_assert(bus < (1 << 8));
-
-	/* backup registers */
-	swap->pdar_backup = ddb_in32(swap->pdar);
-	swap->pmr_backup = ddb_in32(swap->pmr);
-
-	/* set the pdar (pci window) register */
-	ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32,	/* 32 bit wide */
-		     0,		/* not on local memory bus */
-		     0);	/* not visible from PCI bus (N/A) */
-
-	/*
-	 * calcuate the absolute pci config addr;
-	 * according to the spec, we start scanning from adr:11 (0x800)
-	 */
-	if (bus == 0) {
-		/* type 0 config */
-		pci_addr = 0x00040000 << slot_num;
-	} else {
-		/* type 1 config */
-		pci_addr = 0x00040000 << slot_num;
-		panic
-		    ("ddb_access_config_base: we don't support type 1 config Yet");
-	}
-
-	/*
-	 * if pci_addr is less than pci config window size,  we set
-	 * pciinit_offset to 0 and adjust the virt_address.
-	 * Otherwise we will try to adjust pciinit_offset.
-	 */
-	if (pci_addr < swap->config_size) {
-		virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
-		pciinit_offset = 0;
-	} else {
-		db_assert((pci_addr & (swap->config_size - 1)) == 0);
-		virt_addr = KSEG1ADDR(swap->config_base);
-		pciinit_offset = pci_addr;
-	}
-
-	/* set the pmr register */
-	option = DDB_PCI_ACCESS_32;
-	if (bus != 0)
-		option |= DDB_PCI_CFGTYPE1;
-	ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
-
-	return virt_addr;
-}
-
-static inline void ddb_close_config_base(struct pci_config_swap *swap)
-{
-	ddb_out32(swap->pdar, swap->pdar_backup);
-	ddb_out32(swap->pmr, swap->pmr_backup);
-}
-
-static int read_config_dword(struct pci_config_swap *swap,
-			     struct pci_dev *dev, u32 where, u32 * val)
-{
-	u32 bus, slot_num, func_num;
-	u32 base;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	slot_num = PCI_SLOT(dev->devfn);
-	func_num = PCI_FUNC(dev->devfn);
-	base = ddb_access_config_base(swap, bus, slot_num);
-	*val = *(volatile u32 *) (base + (func_num << 8) + where);
-	ddb_close_config_base(swap);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int read_config_word(struct pci_config_swap *swap,
-			    struct pci_dev *dev, u32 where, u16 * val)
-{
-	int status;
-	u32 result;
-
-	db_assert((where & 1) == 0);
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (where & 2)
-		result >>= 16;
-	*val = result & 0xffff;
-	return status;
-}
-
-static int read_config_byte(struct pci_config_swap *swap,
-			    struct pci_dev *dev, u32 where, u8 * val)
-{
-	int status;
-	u32 result;
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (where & 1)
-		result >>= 8;
-	if (where & 2)
-		result >>= 16;
-	*val = result & 0xff;
-	return status;
-}
-
-static int write_config_dword(struct pci_config_swap *swap,
-			      struct pci_dev *dev, u32 where, u32 val)
-{
-	u32 bus, slot_num, func_num;
-	u32 base;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	slot_num = PCI_SLOT(dev->devfn);
-	func_num = PCI_FUNC(dev->devfn);
-	base = ddb_access_config_base(swap, bus, slot_num);
-	*(volatile u32 *) (base + (func_num << 8) + where) = val;
-	ddb_close_config_base(swap);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_config_swap *swap,
-			     struct pci_dev *dev, u32 where, u16 val)
-{
-	int status, shift = 0;
-	u32 result;
-
-	db_assert((where & 1) == 0);
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (status != PCIBIOS_SUCCESSFUL)
-		return status;
-
-	if (where & 2)
-		shift += 16;
-	result &= ~(0xffff << shift);
-	result |= val << shift;
-	return write_config_dword(swap, dev, where & ~3, result);
-}
-
-static int write_config_byte(struct pci_config_swap *swap,
-			     struct pci_dev *dev, u32 where, u8 val)
-{
-	int status, shift = 0;
-	u32 result;
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (status != PCIBIOS_SUCCESSFUL)
-		return status;
-
-	if (where & 2)
-		shift += 16;
-	if (where & 1)
-		shift += 8;
-	result &= ~(0xff << shift);
-	result |= val << shift;
-	return write_config_dword(swap, dev, where & ~3, result);
-}
-
-#define	MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
-static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
-{ \
-     return rw##_config_##unitname(pciswap, \
-                                   dev, \
-                                   where, \
-                                   val); \
-}
-
-MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
-
-    MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
-
-struct pci_ops ddb5476_ext_pci_ops = {
-	extpci_read_config_byte,
-	extpci_read_config_word,
-	extpci_read_config_dword,
-	extpci_write_config_byte,
-	extpci_write_config_word,
-	extpci_write_config_dword
-};
diff --git a/arch/mips/pci/ops-ddb5476.c b/arch/mips/pci/ops-ddb5476.c
deleted file mode 100644
index 12da58e..0000000
--- a/arch/mips/pci/ops-ddb5476.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * arch/mips/ddb5xxx/ddb5476/pci_ops.c
- *     Define the pci_ops for DB5477.
- *
- * Much of the code is derived from the original DDB5074 port by
- * Geert Uytterhoeven <geert@sonycom.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-
-#include <asm/addrspace.h>
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-/*
- * config_swap structure records what set of pdar/pmr are used
- * to access pci config space.  It also provides a place hold the
- * original values for future restoring.
- */
-struct pci_config_swap {
-	u32 pdar;
-	u32 pmr;
-	u32 config_base;
-	u32 config_size;
-	u32 pdar_backup;
-	u32 pmr_backup;
-};
-
-/*
- * On DDB5476, we have one set of swap registers
- */
-struct pci_config_swap ext_pci_swap = {
-	DDB_PCIW0,
-	DDB_PCIINIT0,
-	DDB_PCI_CONFIG_BASE,
-	DDB_PCI_CONFIG_SIZE
-};
-
-static int pci_config_workaround = 1;
-
-/*
- * access config space
- */
-static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus,	/* 0 means top level bus */
-					 u32 slot_num)
-{
-	u32 pci_addr = 0;
-	u32 pciinit_offset = 0;
-	u32 virt_addr = swap->config_base;
-	u32 option;
-
-	if (pci_config_workaround) {
-		/* [jsun] work around Vrc5476 controller itself, returnning
-		 * slot 0 essentially makes vrc5476 invisible
-		 */
-		if (slot_num == 12)
-			slot_num = 0;
-
-#if 0
-		/* BUG : skip P2P bridge for now */
-		if (slot_num == 5)
-			slot_num = 0;
-#endif
-
-	} else {
-		/* now we have to be hornest, returning the true
-		 * PCI config headers for vrc5476
-		 */
-		if (slot_num == 12) {
-			swap->pdar_backup = ddb_in32(swap->pdar);
-			swap->pmr_backup = ddb_in32(swap->pmr);
-			return DDB_BASE + DDB_PCI_BASE;
-		}
-	}
-
-	/* minimum pdar (window) size is 2MB */
-	db_assert(swap->config_size >= (2 << 20));
-
-	db_assert(slot_num < (1 << 5));
-	db_assert(bus < (1 << 8));
-
-	/* backup registers */
-	swap->pdar_backup = ddb_in32(swap->pdar);
-	swap->pmr_backup = ddb_in32(swap->pmr);
-
-	/* set the pdar (pci window) register */
-	ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32,	/* 32 bit wide */
-		     0,		/* not on local memory bus */
-		     0);	/* not visible from PCI bus (N/A) */
-
-	/*
-	 * calcuate the absolute pci config addr;
-	 * according to the spec, we start scanning from adr:11 (0x800)
-	 */
-	if (bus == 0) {
-		/* type 0 config */
-		pci_addr = 0x800 << slot_num;
-	} else {
-		/* type 1 config */
-		pci_addr = (bus << 16) | (slot_num << 11);
-		/* panic("ddb_access_config_base: we don't support type 1 config Yet"); */
-	}
-
-	/*
-	 * if pci_addr is less than pci config window size,  we set
-	 * pciinit_offset to 0 and adjust the virt_address.
-	 * Otherwise we will try to adjust pciinit_offset.
-	 */
-	if (pci_addr < swap->config_size) {
-		virt_addr = KSEG1ADDR(swap->config_base + pci_addr);
-		pciinit_offset = 0;
-	} else {
-		db_assert((pci_addr & (swap->config_size - 1)) == 0);
-		virt_addr = KSEG1ADDR(swap->config_base);
-		pciinit_offset = pci_addr;
-	}
-
-	/* set the pmr register */
-	option = DDB_PCI_ACCESS_32;
-	if (bus != 0)
-		option |= DDB_PCI_CFGTYPE1;
-	ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option);
-
-	return virt_addr;
-}
-
-static inline void ddb_close_config_base(struct pci_config_swap *swap)
-{
-	ddb_out32(swap->pdar, swap->pdar_backup);
-	ddb_out32(swap->pmr, swap->pmr_backup);
-}
-
-static int read_config_dword(struct pci_config_swap *swap,
-			     struct pci_dev *dev, u32 where, u32 * val)
-{
-	u32 bus, slot_num, func_num;
-	u32 base;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	slot_num = PCI_SLOT(dev->devfn);
-	func_num = PCI_FUNC(dev->devfn);
-	base = ddb_access_config_base(swap, bus, slot_num);
-	*val = *(volatile u32 *) (base + (func_num << 8) + where);
-	ddb_close_config_base(swap);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int read_config_word(struct pci_config_swap *swap,
-			    struct pci_dev *dev, u32 where, u16 * val)
-{
-	int status;
-	u32 result;
-
-	db_assert((where & 1) == 0);
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (where & 2)
-		result >>= 16;
-	*val = result & 0xffff;
-	return status;
-}
-
-static int read_config_byte(struct pci_config_swap *swap,
-			    struct pci_dev *dev, u32 where, u8 * val)
-{
-	int status;
-	u32 result;
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (where & 1)
-		result >>= 8;
-	if (where & 2)
-		result >>= 16;
-	*val = result & 0xff;
-	return status;
-}
-
-static int write_config_dword(struct pci_config_swap *swap,
-			      struct pci_dev *dev, u32 where, u32 val)
-{
-	u32 bus, slot_num, func_num;
-	u32 base;
-
-	db_assert((where & 3) == 0);
-	db_assert(where < (1 << 8));
-
-	/* check if the bus is top-level */
-	if (dev->bus->parent != NULL) {
-		bus = dev->bus->number;
-		db_assert(bus != 0);
-	} else {
-		bus = 0;
-	}
-
-	slot_num = PCI_SLOT(dev->devfn);
-	func_num = PCI_FUNC(dev->devfn);
-	base = ddb_access_config_base(swap, bus, slot_num);
-	*(volatile u32 *) (base + (func_num << 8) + where) = val;
-	ddb_close_config_base(swap);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int write_config_word(struct pci_config_swap *swap,
-			     struct pci_dev *dev, u32 where, u16 val)
-{
-	int status, shift = 0;
-	u32 result;
-
-	db_assert((where & 1) == 0);
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (status != PCIBIOS_SUCCESSFUL)
-		return status;
-
-	if (where & 2)
-		shift += 16;
-	result &= ~(0xffff << shift);
-	result |= val << shift;
-	return write_config_dword(swap, dev, where & ~3, result);
-}
-
-static int write_config_byte(struct pci_config_swap *swap,
-			     struct pci_dev *dev, u32 where, u8 val)
-{
-	int status, shift = 0;
-	u32 result;
-
-	status = read_config_dword(swap, dev, where & ~3, &result);
-	if (status != PCIBIOS_SUCCESSFUL)
-		return status;
-
-	if (where & 2)
-		shift += 16;
-	if (where & 1)
-		shift += 8;
-	result &= ~(0xff << shift);
-	result |= val << shift;
-	return write_config_dword(swap, dev, where & ~3, result);
-}
-
-#define	MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \
-static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \
-{ \
-     return rw##_config_##unitname(pciswap, \
-                                   dev, \
-                                   where, \
-                                   val); \
-}
-
-MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap)
-
-    MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap)
-    MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap)
-
-struct pci_ops ddb5476_ext_pci_ops = {
-	extpci_read_config_byte,
-	extpci_read_config_word,
-	extpci_read_config_dword,
-	extpci_write_config_byte,
-	extpci_write_config_word,
-	extpci_write_config_dword
-};
diff --git a/arch/mips/pci/ops-emma2rh.c b/arch/mips/pci/ops-emma2rh.c
new file mode 100644
index 0000000..e21b11b
--- /dev/null
+++ b/arch/mips/pci/ops-emma2rh.c
@@ -0,0 +1,186 @@
+/*
+ *  arch/mips/pci/ops-emma2rh.c
+ *      This file defines the PCI operation for EMMA2RH.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/pci/ops-vr41xx.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include <asm/addrspace.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+#define RTABORT (0x1<<9)
+#define RMABORT (0x1<<10)
+#define EMMA2RH_PCI_SLOT_NUM 9	/* 0000:09.0 is final PCI device */
+
+/*
+ * access config space
+ */
+
+static int check_args(struct pci_bus *bus, u32 devfn, u32 * bus_num)
+{
+	/* check if the bus is top-level */
+	if (bus->parent != NULL) {
+		*bus_num = bus->number;
+		db_assert(bus_num != 0);
+	} else
+		*bus_num = 0;
+
+	if (*bus_num == 0) {
+		/* Type 0 */
+		if (PCI_SLOT(devfn) >= 10)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	} else {
+		/* Type 1 */
+		if ((*bus_num >= 64) || (PCI_SLOT(devfn) >= 16))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+	return 0;
+}
+
+static inline int set_pci_configuration_address(unsigned char bus_num,
+						unsigned int devfn, int where)
+{
+	u32 config_win0;
+
+	emma2rh_out32(EMMA2RH_PCI_INT, ~RMABORT);
+	if (bus_num == 0)
+		/*
+		 * Type 0 configuration
+		 */
+		config_win0 = (1 << (22 + PCI_SLOT(devfn))) | (5 << 9);
+	else
+		/*
+		 * Type 1 configuration
+		 */
+		config_win0 = (bus_num << 26) | (PCI_SLOT(devfn) << 22) |
+		    (1 << 15) | (5 << 9);
+
+	emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, config_win0);
+
+	return 0;
+}
+
+static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where,
+			   int size, uint32_t * val)
+{
+	u32 bus_num;
+	u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE);
+	u32 backup_win0;
+	u32 data;
+
+	*val = 0xffffffffU;
+
+	if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR);
+
+	if (set_pci_configuration_address(bus_num, devfn, where) < 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	data =
+	    *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+			      (where & 0xfffffffc));
+
+	switch (size) {
+	case 1:
+		*val = (data >> ((where & 3) << 3)) & 0xffU;
+		break;
+	case 2:
+		*val = (data >> ((where & 2) << 3)) & 0xffffU;
+		break;
+	case 4:
+		*val = data;
+		break;
+	default:
+		emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+
+	emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+
+	if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where,
+			    int size, u32 val)
+{
+	u32 bus_num;
+	u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE);
+	u32 backup_win0;
+	u32 data;
+	int shift;
+
+	if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR);
+
+	if (set_pci_configuration_address(bus_num, devfn, where) < 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* read modify write */
+	data =
+	    *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+			      (where & 0xfffffffc));
+
+	switch (size) {
+	case 1:
+		shift = (where & 3) << 3;
+		data &= ~(0xffU << shift);
+		data |= ((val & 0xffU) << shift);
+		break;
+	case 2:
+		shift = (where & 2) << 3;
+		data &= ~(0xffffU << shift);
+		data |= ((val & 0xffffU) << shift);
+		break;
+	case 4:
+		data = val;
+		break;
+	default:
+		emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+		return PCIBIOS_FUNC_NOT_SUPPORTED;
+	}
+	*(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) +
+			  (where & 0xfffffffc)) = data;
+
+	emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0);
+	if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops emma2rh_pci_ops = {
+	.read = pci_config_read,
+	.write = pci_config_write,
+};
diff --git a/arch/mips/pci/ops-it8172.c b/arch/mips/pci/ops-it8172.c
index b7a8b9a..ba83285 100644
--- a/arch/mips/pci/ops-it8172.c
+++ b/arch/mips/pci/ops-it8172.c
@@ -50,30 +50,28 @@
 static struct resource pci_mem_resource_1;
 
 static struct resource pci_io_resource = {
-	"io pci IO space",
-	0x14018000,
-	0x17FFFFFF,
-	IORESOURCE_IO
+	.start	= 0x14018000,
+	.end	= 0x17FFFFFF,
+	.name	= "io pci IO space",
+	.flags	= IORESOURCE_IO
 };
 
 static struct resource pci_mem_resource_0 = {
-	"ext pci memory space 0/1",
-	0x10101000,
-	0x13FFFFFF,
-	IORESOURCE_MEM,
-	&pci_mem_resource_0,
-	NULL,
-	&pci_mem_resource_1
+	.start	= 0x10101000,
+	.end	= 0x13FFFFFF,
+	.name	= "ext pci memory space 0/1",
+	.flags	= IORESOURCE_MEM,
+	.parent	= &pci_mem_resource_0,
+	.sibling = NULL,
+	.child	= &pci_mem_resource_1
 };
 
 static struct resource pci_mem_resource_1 = {
-	"ext pci memory space 2/3",
-	0x1A000000,
-	0x1FBFFFFF,
-	IORESOURCE_MEM,
-	&pci_mem_resource_0,
-	NULL,
-	NULL
+	.start	= 0x1A000000,
+	.end	= 0x1FBFFFFF,
+	.name	= "ext pci memory space 2/3",
+	.flags	= IORESOURCE_MEM,
+	.parent	= &pci_mem_resource_0
 };
 
 extern struct pci_ops it8172_pci_ops;
diff --git a/arch/mips/pci/ops-sni.c b/arch/mips/pci/ops-sni.c
index 62bdd19..2b0ccd6 100644
--- a/arch/mips/pci/ops-sni.c
+++ b/arch/mips/pci/ops-sni.c
@@ -47,13 +47,13 @@
 
 	switch (size) {
 	case 1:
-		*val = *(volatile  u8 *) (PCIMT_CONFIG_DATA + (reg & 3));
+		*val = inb(PCIMT_CONFIG_DATA + (reg & 3));
 		break;
 	case 2:
-		*val = *(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2));
+		*val = inw(PCIMT_CONFIG_DATA + (reg & 2));
 		break;
 	case 4:
-		*val = *(volatile u32 *) PCIMT_CONFIG_DATA;
+		*val = inl(PCIMT_CONFIG_DATA);
 		break;
 	}
 
@@ -70,13 +70,13 @@
 
 	switch (size) {
 	case 1:
-		*(volatile  u8 *) (PCIMT_CONFIG_DATA + (reg & 3)) = val;
+		outb (val, PCIMT_CONFIG_DATA + (reg & 3));
 		break;
 	case 2:
-		*(volatile u16 *) (PCIMT_CONFIG_DATA + (reg & 2)) = val;
+		outw (val, PCIMT_CONFIG_DATA + (reg & 2));
 		break;
 	case 4:
-		*(volatile u32 *) PCIMT_CONFIG_DATA = val;
+		outl (val, PCIMT_CONFIG_DATA);
 		break;
 	}
 
diff --git a/arch/mips/pci/ops-titan.c b/arch/mips/pci/ops-titan.c
index 233ec6f..ebf8fc4 100644
--- a/arch/mips/pci/ops-titan.c
+++ b/arch/mips/pci/ops-titan.c
@@ -26,8 +26,19 @@
 #include <linux/pci.h>
 #include <linux/kernel.h>
 
-#include <asm/titan_dep.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#include <asm/rm9k-ocd.h>
 
+/*
+ * PCI specific defines
+ */
+#define	TITAN_PCI_0_CONFIG_ADDRESS	0x780
+#define	TITAN_PCI_0_CONFIG_DATA		0x784
+
+/*
+ * Titan PCI Config Read Byte
+ */
 static int titan_read_config(struct pci_bus *bus, unsigned int devfn, int reg,
 	int size, u32 * val)
 {
@@ -43,8 +54,8 @@
 
 
 	/* start the configuration cycle */
-	TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address);
-	tmp = TITAN_READ(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3);
+	ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS);
+	tmp = ocd_readl(TITAN_PCI_0_CONFIG_DATA) >> ((reg & 3) << 3);
 
 	switch (size) {
 	case 1:
@@ -71,20 +82,20 @@
 		(reg & 0xfc) | 0x80000000;
 
 	/* start the configuration cycle */
-	TITAN_WRITE(TITAN_PCI_0_CONFIG_ADDRESS, address);
+	ocd_writel(address, TITAN_PCI_0_CONFIG_ADDRESS);
 
 	/* write the data */
 	switch (size) {
 	case 1:
-		TITAN_WRITE_8(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3), val);
+		ocd_writeb(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x3));
 		break;
 
 	case 2:
-		TITAN_WRITE_16(TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2), val);
+		ocd_writew(val, TITAN_PCI_0_CONFIG_DATA + (~reg & 0x2));
 		break;
 
 	case 4:
-		TITAN_WRITE(TITAN_PCI_0_CONFIG_DATA, val);
+		ocd_writel(val, TITAN_PCI_0_CONFIG_DATA);
 		break;
 	}
 
diff --git a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c
deleted file mode 100644
index 73f9cee..0000000
--- a/arch/mips/pci/pci-ddb5074.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static struct resource extpci_io_resource = {
-	"pci IO space",
-	0x1000,			/* leave some room for ISA bus */
-	DDB_PCI_IO_SIZE - 1,
-	IORESOURCE_IO
-};
-
-static struct resource extpci_mem_resource = {
-	"pci memory space",
-	DDB_PCI_MEM_BASE + 0x00100000,	/* leave 1 MB for RTC */
-	DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1,
-	IORESOURCE_MEM
-};
-
-extern struct pci_ops ddb5476_ext_pci_ops;
-
-struct pci_controller ddb5476_controller = {
-	.pci_ops	= &ddb5476_ext_pci_ops,
-	.io_resource	= &extpci_io_resource,
-	.mem_resource	= &extpci_mem_resource,
-};
-
-#define     PCI_EXT_INTA        8
-#define     PCI_EXT_INTB        9
-#define     PCI_EXT_INTC        10
-#define     PCI_EXT_INTD        11
-#define     PCI_EXT_INTE        12
-
-#define     MAX_SLOT_NUM        14
-
-static unsigned char irq_map[MAX_SLOT_NUM] = {
-  [ 0] = nile4_to_irq(PCI_EXT_INTE),
-  [ 1] = nile4_to_irq(PCI_EXT_INTA),
-  [ 2] = nile4_to_irq(PCI_EXT_INTA),
-  [ 3] = nile4_to_irq(PCI_EXT_INTB),
-  [ 4] = nile4_to_irq(PCI_EXT_INTC),
-  [ 5] = nile4_to_irq(NILE4_INT_UART),
-  [10] = nile4_to_irq(PCI_EXT_INTE),
-  [13] = nile4_to_irq(PCI_EXT_INTE),
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	return irq_map[slot];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
-
-void __init ddb_pci_reset_bus(void)
-{
-	u32 temp;
-
-	/*
-	 * I am not sure about the "official" procedure, the following
-	 * steps work as far as I know:
-	 * We first set PCI cold reset bit (bit 31) in PCICTRL-H.
-	 * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
-	 * The same is true for both PCI channels.
-	 */
-	temp = ddb_in32(DDB_PCICTRL + 4);
-	temp |= 0x80000000;
-	ddb_out32(DDB_PCICTRL + 4, temp);
-	temp &= ~0xc0000000;
-	ddb_out32(DDB_PCICTRL + 4, temp);
-
-}
diff --git a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c
deleted file mode 100644
index 90dd495..0000000
--- a/arch/mips/pci/pci-ddb5476.c
+++ /dev/null
@@ -1,93 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-#include <asm/debug.h>
-
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-static struct resource extpci_io_resource = {
-	"pci IO space",
-	0x1000,			/* leave some room for ISA bus */
-	DDB_PCI_IO_SIZE - 1,
-	IORESOURCE_IO
-};
-
-static struct resource extpci_mem_resource = {
-	"pci memory space",
-	DDB_PCI_MEM_BASE + 0x00100000,	/* leave 1 MB for RTC */
-	DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1,
-	IORESOURCE_MEM
-};
-
-extern struct pci_ops ddb5476_ext_pci_ops;
-
-struct pci_controller ddb5476_controller = {
-	.pci_ops	= &ddb5476_ext_pci_ops,
-	.io_resource	= &extpci_io_resource,
-	.mem_resource	= &extpci_mem_resource
-};
-
-
-/*
- * we fix up irqs based on the slot number.
- * The first entry is at AD:11.
- *
- * This does not work for devices on sub-buses yet.
- */
-
-/*
- * temporary
- */
-
-#define		PCI_EXT_INTA		8
-#define		PCI_EXT_INTB		9
-#define		PCI_EXT_INTC		10
-#define		PCI_EXT_INTD		11
-#define		PCI_EXT_INTE		12
-
-/*
- * based on ddb5477 manual page 11
- */
-#define		MAX_SLOT_NUM		21
-static unsigned char irq_map[MAX_SLOT_NUM] = {
- [ 2] = 9,				/* AD:13	USB		*/
- [ 3] = 10,				/* AD:14	PMU		*/
- [ 5] = 0,				/* AD:16 	P2P bridge	*/
- [ 6] = nile4_to_irq(PCI_EXT_INTB),	/* AD:17			*/
- [ 7] =	nile4_to_irq(PCI_EXT_INTC),	/* AD:18			*/
- [ 8] = nile4_to_irq(PCI_EXT_INTD),	/* AD:19			*/
- [ 9] = nile4_to_irq(PCI_EXT_INTA),	/* AD:20			*/
- [13] = 14,				/* AD:24 HD controller, M5229	*/
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	return irq_map[slot];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
-
-void __init ddb_pci_reset_bus(void)
-{
-	u32 temp;
-
-	/*
-	 * I am not sure about the "official" procedure, the following
-	 * steps work as far as I know:
-	 * We first set PCI cold reset bit (bit 31) in PCICTRL-H.
-	 * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H.
-	 * The same is true for both PCI channels.
-	 */
-	temp = ddb_in32(DDB_PCICTRL + 4);
-	temp |= 0x80000000;
-	ddb_out32(DDB_PCICTRL + 4, temp);
-	temp &= ~0xc0000000;
-	ddb_out32(DDB_PCICTRL + 4, temp);
-
-}
diff --git a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c
index 826d653..d071bc3 100644
--- a/arch/mips/pci/pci-ddb5477.c
+++ b/arch/mips/pci/pci-ddb5477.c
@@ -22,31 +22,31 @@
 #include <asm/ddb5xxx/ddb5xxx.h>
 
 static struct resource extpci_io_resource = {
-	"ext pci IO space",
-	DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000,
-	DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1,
-	IORESOURCE_IO
+	.start	= DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000,
+	.end	= DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1,
+	.name	= "ext pci IO space",
+	.flags	= IORESOURCE_IO
 };
 
 static struct resource extpci_mem_resource = {
-	"ext pci memory space",
-	DDB_PCI0_MEM_BASE + 0x100000,
-	DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1,
-	IORESOURCE_MEM
+	.start	= DDB_PCI0_MEM_BASE + 0x100000,
+	.end	= DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1,
+	.name	= "ext pci memory space",
+	.flags	= IORESOURCE_MEM
 };
 
 static struct resource iopci_io_resource = {
-	"io pci IO space",
-	DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE,
-	DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1,
-	IORESOURCE_IO
+	.start	= DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE,
+	.end	= DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1,
+	.name	= "io pci IO space",
+	.flags	= IORESOURCE_IO
 };
 
 static struct resource iopci_mem_resource = {
-	"ext pci memory space",
-	DDB_PCI1_MEM_BASE,
-	DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1,
-	IORESOURCE_MEM
+	.start	= DDB_PCI1_MEM_BASE,
+	.end	= DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1,
+	.name	= "ext pci memory space",
+	.flags	= IORESOURCE_MEM
 };
 
 extern struct pci_ops ddb5477_ext_pci_ops;
diff --git a/arch/mips/pci/pci-emma2rh.c b/arch/mips/pci/pci-emma2rh.c
new file mode 100644
index 0000000..0f8b230
--- /dev/null
+++ b/arch/mips/pci/pci-emma2rh.c
@@ -0,0 +1,90 @@
+/*
+ *  arch/mips/pci/pci-emma2rh.c
+ *      This file defines the PCI configration.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2004-2006
+ *
+ *  This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c
+ *
+ *	Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootinfo.h>
+#include <asm/debug.h>
+
+#include <asm/emma2rh/emma2rh.h>
+
+static struct resource pci_io_resource = {
+	.name = "pci IO space",
+	.start = EMMA2RH_PCI_IO_BASE,
+	.end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1,
+	.flags = IORESOURCE_IO,
+};
+
+static struct resource pci_mem_resource = {
+	.name = "pci memory space",
+	.start = EMMA2RH_PCI_MEM_BASE,
+	.end = EMMA2RH_PCI_MEM_BASE + EMMA2RH_PCI_MEM_SIZE - 1,
+	.flags = IORESOURCE_MEM,
+};
+
+extern struct pci_ops emma2rh_pci_ops;
+
+static struct pci_controller emma2rh_pci_controller = {
+	.pci_ops = &emma2rh_pci_ops,
+	.mem_resource = &pci_mem_resource,
+	.io_resource = &pci_io_resource,
+	.mem_offset = -0x04000000,
+	.io_offset = 0,
+};
+
+static void __init emma2rh_pci_init(void)
+{
+	/* setup PCI interface */
+	emma2rh_out32(EMMA2RH_PCI_ARBIT_CTR, 0x70f);
+
+	emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x80000a18);
+	emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_COMMAND,
+		      PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_CAP_LIST |
+		      PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
+	emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_0, 0x10000000);
+	emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_1, 0x00000000);
+
+	emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x12000000 | 0x218);
+	emma2rh_out32(EMMA2RH_PCI_IWIN1_CTR, 0x18000000 | 0x600);
+	emma2rh_out32(EMMA2RH_PCI_INIT_ESWP, 0x00000200);
+
+	emma2rh_out32(EMMA2RH_PCI_TWIN_CTR, 0x00009200);
+	emma2rh_out32(EMMA2RH_PCI_TWIN_BADR, 0x00000000);
+	emma2rh_out32(EMMA2RH_PCI_TWIN0_DADR, 0x00000000);
+	emma2rh_out32(EMMA2RH_PCI_TWIN1_DADR, 0x00000000);
+}
+
+static int __init emma2rh_pci_setup(void)
+{
+	emma2rh_pci_init();
+	register_pci_controller(&emma2rh_pci_controller);
+	return 0;
+}
+
+arch_initcall(emma2rh_pci_setup);
diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c
new file mode 100644
index 0000000..3c86c77
--- /dev/null
+++ b/arch/mips/pci/pci-excite.c
@@ -0,0 +1,149 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *  Based on the PMC-Sierra Yosemite board support by Ralf Baechle.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <asm/rm9k-ocd.h>
+#include <excite.h>
+
+
+extern struct pci_ops titan_pci_ops;
+
+
+static struct resource
+	mem_resource = 	{
+		.name	= "PCI memory",
+		.start	= EXCITE_PHYS_PCI_MEM,
+		.end	= EXCITE_PHYS_PCI_MEM + EXCITE_SIZE_PCI_MEM - 1,
+		.flags	= IORESOURCE_MEM
+	},
+	io_resource = {
+		.name	= "PCI I/O",
+		.start	= EXCITE_PHYS_PCI_IO,
+		.end	= EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1,
+		.flags	= IORESOURCE_IO
+	};
+
+
+static struct pci_controller bx_controller = {
+	.pci_ops	= &titan_pci_ops,
+	.mem_resource	= &mem_resource,
+	.mem_offset	= 0x00000000UL,
+	.io_resource	= &io_resource,
+	.io_offset	= 0x00000000UL
+};
+
+
+static char
+	iopage_failed[] __initdata   = "Cannot allocate PCI I/O page",
+	modebits_no_pci[] __initdata = "PCI is not configured in mode bits";
+
+#define RM9000x2_OCD_HTSC	0x0604
+#define RM9000x2_OCD_HTBHL	0x060c
+#define RM9000x2_OCD_PCIHRST	0x078c
+
+#define RM9K_OCD_MODEBIT1	0x00d4 /* (MODEBIT1) Mode Bit 1 */
+#define RM9K_OCD_CPHDCR		0x00f4 /* CPU-PCI/HT Data Control. */
+
+#define PCISC_FB2B 		0x00000200
+#define PCISC_MWICG		0x00000010
+#define PCISC_EMC		0x00000004
+#define PCISC_ERMA		0x00000002
+
+
+
+static int __init basler_excite_pci_setup(void)
+{
+	const unsigned int fullbars = memsize / (256 << 20);
+	unsigned int i;
+
+	/* Check modebits to see if PCI is really enabled. */
+	if (!((ocd_readl(RM9K_OCD_MODEBIT1) >> (47-32)) & 0x1))
+		panic(modebits_no_pci);
+
+	if (NULL == request_mem_region(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO,
+				       "Memory-mapped PCI I/O page"))
+		panic(iopage_failed);
+
+	/* Enable PCI 0 as master for config cycles */
+	ocd_writel(PCISC_EMC | PCISC_ERMA, RM9000x2_OCD_HTSC);
+
+
+	/* Set up latency timer */
+	ocd_writel(0x8008, RM9000x2_OCD_HTBHL);
+
+	/*  Setup host IO and Memory space */
+	ocd_writel((EXCITE_PHYS_PCI_IO >> 4) | 1, LKB7);
+	ocd_writel(((EXCITE_SIZE_PCI_IO >> 4) & 0x7fffff00) - 0x100, LKM7);
+	ocd_writel((EXCITE_PHYS_PCI_MEM >> 4) | 1, LKB8);
+	ocd_writel(((EXCITE_SIZE_PCI_MEM >> 4) & 0x7fffff00) - 0x100, LKM8);
+
+	/* Set up PCI BARs to map all installed memory */
+	for (i = 0; i < 6; i++) {
+		const unsigned int bar = 0x610 + i * 4;
+
+	     	if (i < fullbars) {
+			ocd_writel(0x10000000 * i, bar);
+			ocd_writel(0x01000000 * i, bar + 0x140);
+			ocd_writel(0x0ffff029, bar + 0x100);
+			continue;
+		}
+
+	     	if (i == fullbars) {
+			int o;
+			u32 mask;
+
+			const unsigned long rem = memsize - i * 0x10000000;
+			if (!rem) {
+				ocd_writel(0x00000000, bar + 0x100);
+				continue;
+			}
+
+			o = ffs(rem) - 1;
+			if (rem & ~(0x1 << o))
+				o++;
+			mask = ((0x1 << o) & 0x0ffff000) - 0x1000;
+			ocd_writel(0x10000000 * i, bar);
+			ocd_writel(0x01000000 * i, bar + 0x140);
+			ocd_writel(0x00000029 | mask, bar + 0x100);
+			continue;
+		}
+
+		ocd_writel(0x00000000, bar + 0x100);
+	}
+
+	/* Finally, enable the PCI interupt */
+#if USB_IRQ > 7
+	set_c0_intcontrol(1 << USB_IRQ);
+#else
+	set_c0_status(1 << (USB_IRQ + 8));
+#endif
+
+	ioport_resource.start = EXCITE_PHYS_PCI_IO;
+	ioport_resource.end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1;
+	set_io_port_base((unsigned long) ioremap_nocache(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO));
+	register_pci_controller(&bx_controller);
+	return 0;
+}
+
+
+arch_initcall(basler_excite_pci_setup);
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c
index 6002d2a..80eb9af 100644
--- a/arch/mips/pci/pci-ip27.c
+++ b/arch/mips/pci/pci-ip27.c
@@ -40,297 +40,7 @@
 struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
 int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
 
-/*
- * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
- * not really documented, so right now I can't write code which uses it.
- * Therefore we use type 0 accesses for now even though they won't work
- * correcly for PCI-to-PCI bridges.
- *
- * The function is complicated by the ultimate brokeness of the IOC3 chip
- * which is used in SGI systems.  The IOC3 can only handle 32-bit PCI
- * accesses and does only decode parts of it's address space.
- */
-
-static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn,
-				 int where, int size, u32 * value)
-{
-	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-	bridge_t *bridge = bc->base;
-	int slot = PCI_SLOT(devfn);
-	int fn = PCI_FUNC(devfn);
-	volatile void *addr;
-	u32 cf, shift, mask;
-	int res;
-
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to look at it for real ...
-	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto oh_my_gawd;
-
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
-
-	if (size == 1)
-		res = get_dbe(*value, (u8 *) addr);
-	else if (size == 2)
-		res = get_dbe(*value, (u16 *) addr);
-	else
-		res = get_dbe(*value, (u32 *) addr);
-
-	return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to look at the wrong register.
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
-	 * anything but 32-bit words ...
-	 */
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	*value = (cf >> shift) & mask;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn,
-				 int where, int size, u32 * value)
-{
-	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-	bridge_t *bridge = bc->base;
-	int busno = bus->number;
-	int slot = PCI_SLOT(devfn);
-	int fn = PCI_FUNC(devfn);
-	volatile void *addr;
-	u32 cf, shift, mask;
-	int res;
-
-	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-	addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to look at it for real ...
-	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto oh_my_gawd;
-
-	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-	addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
-
-	if (size == 1)
-		res = get_dbe(*value, (u8 *) addr);
-	else if (size == 2)
-		res = get_dbe(*value, (u16 *) addr);
-	else
-		res = get_dbe(*value, (u32 *) addr);
-
-	return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to look at the wrong register.
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) {
-		*value = 0;
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
-	 * anything but 32-bit words ...
-	 */
-	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-	addr = &bridge->b_type1_cfg.c[(fn << 8) | where];
-
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	*value = (cf >> shift) & mask;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_read_config(struct pci_bus *bus, unsigned int devfn,
-			   int where, int size, u32 * value)
-{
-	if (bus->number > 0)
-		return pci_conf1_read_config(bus, devfn, where, size, value);
-
-	return pci_conf0_read_config(bus, devfn, where, size, value);
-}
-
-static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn,
-				  int where, int size, u32 value)
-{
-	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-	bridge_t *bridge = bc->base;
-	int slot = PCI_SLOT(devfn);
-	int fn = PCI_FUNC(devfn);
-	volatile void *addr;
-	u32 cf, shift, mask, smask;
-	int res;
-
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID];
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to look at it for real ...
-	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto oh_my_gawd;
-
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)];
-
-	if (size == 1) {
-		res = put_dbe(value, (u8 *) addr);
-	} else if (size == 2) {
-		res = put_dbe(value, (u16 *) addr);
-	} else {
-		res = put_dbe(value, (u32 *) addr);
-	}
-
-	if (res)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to touch the wrong register.
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
-		return PCIBIOS_SUCCESSFUL;
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
-	 * anything but 32-bit words ...
-	 */
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	smask = mask << shift;
-
-	cf = (cf & ~smask) | ((value & mask) << shift);
-	if (put_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn,
-				  int where, int size, u32 value)
-{
-	struct bridge_controller *bc = BRIDGE_CONTROLLER(bus);
-	bridge_t *bridge = bc->base;
-	int slot = PCI_SLOT(devfn);
-	int fn = PCI_FUNC(devfn);
-	int busno = bus->number;
-	volatile void *addr;
-	u32 cf, shift, mask, smask;
-	int res;
-
-	bridge->b_pci_cfg = (busno << 16) | (slot << 11);
-	addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID];
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to look at it for real ...
-	 */
-	if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)))
-		goto oh_my_gawd;
-
-	addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))];
-
-	if (size == 1) {
-		res = put_dbe(value, (u8 *) addr);
-	} else if (size == 2) {
-		res = put_dbe(value, (u16 *) addr);
-	} else {
-		res = put_dbe(value, (u32 *) addr);
-	}
-
-	if (res)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-
-oh_my_gawd:
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't even give the
-	 * generic PCI code a chance to touch the wrong register.
-	 */
-	if ((where >= 0x14 && where < 0x40) || (where >= 0x48))
-		return PCIBIOS_SUCCESSFUL;
-
-	/*
-	 * IOC3 is fucked fucked beyond believe ...  Don't try to access
-	 * anything but 32-bit words ...
-	 */
-	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];
-
-	if (get_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	shift = ((where & 3) << 3);
-	mask = (0xffffffffU >> ((4 - size) << 3));
-	smask = mask << shift;
-
-	cf = (cf & ~smask) | ((value & mask) << shift);
-	if (put_dbe(cf, (u32 *) addr))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_write_config(struct pci_bus *bus, unsigned int devfn,
-	int where, int size, u32 value)
-{
-	if (bus->number > 0)
-		return pci_conf1_write_config(bus, devfn, where, size, value);
-
-	return pci_conf0_write_config(bus, devfn, where, size, value);
-}
-
-static struct pci_ops bridge_pci_ops = {
-	.read = pci_read_config,
-	.write = pci_write_config,
-};
+extern struct pci_ops bridge_pci_ops;
 
 int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid)
 {
@@ -370,8 +80,7 @@
 	bc->widget_id = widget_id;
 	bc->nasid = nasid;
 
-	bc->baddr = (u64)masterwid << 60;
-	bc->baddr |= (1UL << 56);	/* Barrier set */
+	bc->baddr = (u64)masterwid << 60 | PCI64_ATTR_BAR;
 
 	/*
 	 * point to this bridge
diff --git a/arch/mips/pci/pci-jmr3927.c b/arch/mips/pci/pci-jmr3927.c
index f02ef6e..cb84f4e 100644
--- a/arch/mips/pci/pci-jmr3927.c
+++ b/arch/mips/pci/pci-jmr3927.c
@@ -35,17 +35,17 @@
 #include <asm/debug.h>
 
 struct resource pci_io_resource = {
-	"IO MEM",
-	0x1000,			/* reserve regacy I/O space */
-	0x1000 + JMR3927_PCIIO_SIZE - 1,
-	IORESOURCE_IO
+	.name	= "IO MEM",
+	.start	= 0x1000,			/* reserve regacy I/O space */
+	.end	= 0x1000 + JMR3927_PCIIO_SIZE - 1,
+	.flags	= IORESOURCE_IO
 };
 
 struct resource pci_mem_resource = {
-	"PCI MEM",
-	JMR3927_PCIMEM,
-	JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1,
-	IORESOURCE_MEM
+	.name	= "PCI MEM",
+	.start	= JMR3927_PCIMEM,
+	.end	= JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1,
+	.flags	= IORESOURCE_MEM
 };
 
 extern struct pci_ops jmr3927_pci_ops;
diff --git a/arch/mips/pci/pci-ocelot.c b/arch/mips/pci/pci-ocelot.c
index 3da8a4e..2b9495d 100644
--- a/arch/mips/pci/pci-ocelot.c
+++ b/arch/mips/pci/pci-ocelot.c
@@ -71,13 +71,13 @@
 }
 
 static struct resource ocelot_mem_resource = {
-	iomem_resource.start = GT_PCI_MEM_BASE;
-	iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
+	start	= GT_PCI_MEM_BASE;
+	end	= GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1;
 };
 
 static struct resource ocelot_io_resource = {
-	ioport_resource.start = GT_PCI_IO_BASE;
-	ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
+	start	= GT_PCI_IO_BASE;
+	end	= GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1;
 };
 
 static struct pci_controller ocelot_pci_controller = {
diff --git a/arch/mips/pci/pci-yosemite.c b/arch/mips/pci/pci-yosemite.c
index dac9ed4..0357946 100644
--- a/arch/mips/pci/pci-yosemite.c
+++ b/arch/mips/pci/pci-yosemite.c
@@ -14,7 +14,10 @@
 extern struct pci_ops titan_pci_ops;
 
 static struct resource py_mem_resource = {
-	"Titan PCI MEM", 0xe0000000UL, 0xe3ffffffUL, IORESOURCE_MEM
+	.start	= 0xe0000000UL,
+	.end	= 0xe3ffffffUL,
+	.name	= "Titan PCI MEM",
+	.flags	= IORESOURCE_MEM
 };
 
 /*
@@ -26,7 +29,10 @@
 #define TITAN_IO_BASE	0xe8000000UL
 
 static struct resource py_io_resource = {
-	"Titan IO MEM", 0x00001000UL, TITAN_IO_SIZE - 1, IORESOURCE_IO,
+	.start	= 0x00001000UL,
+	.end	= TITAN_IO_SIZE - 1,
+	.name	= "Titan IO MEM",
+	.flags	= IORESOURCE_IO,
 };
 
 static struct pci_controller py_controller = {
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 21402ff..4dfce15 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -76,11 +76,6 @@
 	res->start = start;
 }
 
-struct pci_controller * __init alloc_pci_controller(void)
-{
-	return alloc_bootmem(sizeof(struct pci_controller));
-}
-
 void __init register_pci_controller(struct pci_controller *hose)
 {
 	*hose_tail = hose;
diff --git a/arch/mips/philips/pnx8550/common/pci.c b/arch/mips/philips/pnx8550/common/pci.c
index baa6905..eee4f3d 100644
--- a/arch/mips/philips/pnx8550/common/pci.c
+++ b/arch/mips/philips/pnx8550/common/pci.c
@@ -27,17 +27,17 @@
 #include <nand.h>
 
 static struct resource pci_io_resource = {
-	"pci IO space",
-	(u32)(PNX8550_PCIIO + 0x1000),	/* reserve regacy I/O space */
-	(u32)(PNX8550_PCIIO + PNX8550_PCIIO_SIZE),
-	IORESOURCE_IO
+	.start	= PNX8550_PCIIO + 0x1000,	/* reserve regacy I/O space */
+	.end	= PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
+	.name	= "pci IO space",
+	.flags	= IORESOURCE_IO
 };
 
 static struct resource pci_mem_resource = {
-	"pci memory space",
-	(u32)(PNX8550_PCIMEM),
-	(u32)(PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1),
-	IORESOURCE_MEM
+	.start	= PNX8550_PCIMEM,
+	.end	= PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
+	.name	= "pci memory space",
+	.flags	= IORESOURCE_MEM
 };
 
 extern struct pci_ops pnx8550_pci_ops;
diff --git a/arch/mips/philips/pnx8550/common/setup.c b/arch/mips/philips/pnx8550/common/setup.c
index 0d8a776..0e791f4 100644
--- a/arch/mips/philips/pnx8550/common/setup.c
+++ b/arch/mips/philips/pnx8550/common/setup.c
@@ -58,10 +58,27 @@
 extern char *prom_getcmdline(void);
 
 struct resource standard_io_resources[] = {
-	{"dma1", 0x00, 0x1f, IORESOURCE_BUSY},
-	{"timer", 0x40, 0x5f, IORESOURCE_BUSY},
-	{"dma page reg", 0x80, 0x8f, IORESOURCE_BUSY},
-	{"dma2", 0xc0, 0xdf, IORESOURCE_BUSY},
+	{
+		.start	= .0x00,
+		.end	= 0x1f,
+		.name	= "dma1",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x40,
+		.end	= 0x5f,
+		.name	= "timer",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x80,
+		.end	= 0x8f,
+		.name	= "dma page reg",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0xc0,
+		.end	= 0xdf,
+		.name	= "dma2",
+		.flags	= IORESOURCE_BUSY
+	},
 };
 
 #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
@@ -82,7 +99,7 @@
 
 int pnx8550_console_port = -1;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	int i;
 	char* argptr;
diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c
index 3f724d6..aa0d6ff 100644
--- a/arch/mips/pmc-sierra/yosemite/setup.c
+++ b/arch/mips/pmc-sierra/yosemite/setup.c
@@ -218,7 +218,7 @@
 	py_rtc_setup();
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	board_time_init = yosemite_time_init;
 	late_time_init = py_late_time_init;
diff --git a/arch/mips/qemu/Makefile b/arch/mips/qemu/Makefile
index 730f459..078cd30 100644
--- a/arch/mips/qemu/Makefile
+++ b/arch/mips/qemu/Makefile
@@ -2,6 +2,6 @@
 # Makefile for Qemu specific kernel interface routines under Linux.
 #
 
-obj-y		= q-firmware.o q-irq.o q-mem.o q-setup.o
+obj-y		= q-firmware.o q-irq.o q-mem.o q-setup.o q-reset.o
 
 obj-$(CONFIG_SMP) += q-smp.o
diff --git a/arch/mips/qemu/q-reset.c b/arch/mips/qemu/q-reset.c
new file mode 100644
index 0000000..c04ebcf
--- /dev/null
+++ b/arch/mips/qemu/q-reset.c
@@ -0,0 +1,34 @@
+#include <linux/config.h>
+
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/cacheflush.h>
+#include <asm/qemu.h>
+
+static void qemu_machine_restart(char *command)
+{
+	volatile unsigned int *reg = (unsigned int *)QEMU_RESTART_REG;
+
+	set_c0_status(ST0_BEV | ST0_ERL);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_c0_wired(0);
+	*reg = 42;
+	while (1)
+		cpu_wait();
+}
+
+static void qemu_machine_halt(void)
+{
+	volatile unsigned int *reg = (unsigned int *)QEMU_HALT_REG;
+
+	*reg = 42;
+	while (1)
+		cpu_wait();
+}
+
+void qemu_reboot_setup(void)
+{
+	_machine_restart = qemu_machine_restart;
+	_machine_halt = qemu_machine_halt;
+}
diff --git a/arch/mips/qemu/q-setup.c b/arch/mips/qemu/q-setup.c
index 022eb1a..e100d60 100644
--- a/arch/mips/qemu/q-setup.c
+++ b/arch/mips/qemu/q-setup.c
@@ -2,6 +2,8 @@
 #include <asm/io.h>
 #include <asm/time.h>
 
+extern void qemu_reboot_setup(void);
+
 #define QEMU_PORT_BASE 0xb4000000
 
 const char *get_system_type(void)
@@ -18,8 +20,10 @@
 	setup_irq(0, irq);
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	set_io_port_base(QEMU_PORT_BASE);
 	board_timer_setup = qemu_timer_setup;
+
+	qemu_reboot_setup();
 }
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c
index a9c58e0..8134220 100644
--- a/arch/mips/sgi-ip22/ip22-reset.c
+++ b/arch/mips/sgi-ip22/ip22-reset.c
@@ -34,7 +34,7 @@
 #define POWERDOWN_TIMEOUT	120
 
 /*
- * Blink frequency during reboot grace period and when paniced.
+ * Blink frequency during reboot grace period and when panicked.
  */
 #define POWERDOWN_FREQ		(HZ / 4)
 #define PANIC_FREQ		(HZ / 8)
diff --git a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c
index 7018e18..d713890 100644
--- a/arch/mips/sgi-ip22/ip22-setup.c
+++ b/arch/mips/sgi-ip22/ip22-setup.c
@@ -53,7 +53,7 @@
 extern void ip22_be_init(void) __init;
 extern void ip22_time_init(void) __init;
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	char *ctype;
 	char *cserial;
diff --git a/arch/mips/sgi-ip27/Kconfig b/arch/mips/sgi-ip27/Kconfig
index 7b0bc44..f14ef38 100644
--- a/arch/mips/sgi-ip27/Kconfig
+++ b/arch/mips/sgi-ip27/Kconfig
@@ -4,31 +4,29 @@
 #	  This options adds support for userspace processes upto 16TB size.
 #	  Normally the limit is just .5TB.
 
-config SGI_SN0_N_MODE
+choice
+	prompt "Node addressing mode"
+	depends on SGI_IP27
+	default SGI_SN_M_MODE
+
+config SGI_SN_M_MODE
+	bool "IP27 M-Mode"
+	help
+	  The nodes of Origin, Onyx, Fuel and Tezro systems can be configured
+	  in either N-Modes which allows for more nodes or M-Mode which allows
+	  for more memory.  Your hardware is almost certainly running in
+	  M-Mode, so choose M-mode here.
+
+config SGI_SN_N_MODE
 	bool "IP27 N-Mode"
-	depends on SGI_IP27
+	depends on EXPERIMENTAL
 	help
-	  The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be
-	  configured in either N-Modes which allows for more nodes or M-Mode
-	  which allows for more memory.  Your system is most probably
-	  running in M-Mode, so you should say N here.
+	  The nodes of Origin, Onyx, Fuel and Tezro systems can be configured
+	  in either N-Modes which allows for more nodes or M-Mode which allows
+	  for more memory.  Your hardware is almost certainly running in
+	  M-Mode, so choose M-mode here.
 
-config ARCH_DISCONTIGMEM_ENABLE
-	bool
-	default y if SGI_IP27
-	help
-	  Say Y to upport efficient handling of discontiguous physical memory,
-	  for architectures which are either NUMA (Non-Uniform Memory Access)
-	  or have huge holes in the physical address space for other reasons.
-	  See <file:Documentation/vm/numa> for more.
-
-config NUMA
-	bool "NUMA Support"
-	depends on SGI_IP27
-	help
-	  Say Y to compile the kernel to support NUMA (Non-Uniform Memory
-	  Access).  This option is for configuring high-end multiprocessor
-	  server machines.  If in doubt, say N.
+endchoice
 
 config MAPPED_KERNEL
 	bool "Mapped kernel support"
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
index 8651a0e..a6b490e 100644
--- a/arch/mips/sgi-ip27/ip27-init.c
+++ b/arch/mips/sgi-ip27/ip27-init.c
@@ -196,7 +196,7 @@
 extern void ip27_time_init(void);
 extern void ip27_reboot_setup(void);
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	hubreg_t p, e, n_mode;
 	nasid_t nid;
@@ -228,7 +228,7 @@
 	 */
 	n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK;
 	printk("Machine is in %c mode.\n", n_mode ? 'N' : 'M');
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
 	if (!n_mode)
 		panic("Kernel compiled for M mode.");
 #else
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 2e643d2..0b61a39 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -360,7 +360,7 @@
 
 static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
 
-static int allocate_irqno(void)
+int allocate_irqno(void)
 {
 	int irq;
 
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index 36b662e..1fb860c 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -89,11 +89,13 @@
 }
 #endif
 
+static unsigned int rt_timer_irq;
+
 void ip27_rt_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 	int cpuA = cputoslice(cpu) == 0;
-	int irq = 9;				/* XXX Assign number */
+	unsigned int irq = rt_timer_irq;
 
 	irq_enter();
 	write_seqlock(&xtime_lock);
@@ -179,13 +181,68 @@
         return mktime(year, month, date, hour, min, sec);
 }
 
+static void startup_rt_irq(unsigned int irq)
+{
+}
+
+static void shutdown_rt_irq(unsigned int irq)
+{
+}
+
+static void enable_rt_irq(unsigned int irq)
+{
+}
+
+static void disable_rt_irq(unsigned int irq)
+{
+}
+
+static void mask_and_ack_rt(unsigned int irq)
+{
+}
+
+static void end_rt_irq(unsigned int irq)
+{
+}
+
+static struct hw_interrupt_type rt_irq_type = {
+	.typename	= "SN HUB RT timer",
+	.startup	= startup_rt_irq,
+	.shutdown	= shutdown_rt_irq,
+	.enable		= enable_rt_irq,
+	.disable	= disable_rt_irq,
+	.ack		= mask_and_ack_rt,
+	.end		= end_rt_irq,
+};
+
+static struct irqaction rt_irqaction = {
+	.handler	= ip27_rt_timer_interrupt,
+	.flags		= SA_INTERRUPT,
+	.mask		= CPU_MASK_NONE,
+	.name		= "timer"
+};
+
+extern int allocate_irqno(void);
+
 static void ip27_timer_setup(struct irqaction *irq)
 {
+	int irqno  = allocate_irqno();
+
+	if (irqno < 0)
+		panic("Can't allocate interrupt number for timer interrupt");
+
+	irq_desc[irqno].status = IRQ_DISABLED;
+	irq_desc[irqno].action = NULL;
+	irq_desc[irqno].depth = 1;
+	irq_desc[irqno].handler = &rt_irq_type;
+
 	/* over-write the handler, we use our own way */
 	irq->handler = no_action;
 
 	/* setup irqaction */
-//	setup_irq(IP27_TIMER_IRQ, irq);		/* XXX Can't do this yet.  */
+	irq_desc[irqno].status |= IRQ_PER_CPU;
+
+	rt_timer_irq = irqno;
 }
 
 void __init ip27_time_init(void)
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c
index ab9d9ce..79ddb460 100644
--- a/arch/mips/sgi-ip32/ip32-reset.c
+++ b/arch/mips/sgi-ip32/ip32-reset.c
@@ -28,13 +28,13 @@
 
 #define POWERDOWN_TIMEOUT	120
 /*
- * Blink frequency during reboot grace period and when paniced.
+ * Blink frequency during reboot grace period and when panicked.
  */
 #define POWERDOWN_FREQ		(HZ / 4)
 #define PANIC_FREQ		(HZ / 8)
 
 static struct timer_list power_timer, blink_timer, debounce_timer;
-static int has_paniced, shuting_down;
+static int has_panicked, shuting_down;
 
 static void ip32_machine_restart(char *command) __attribute__((noreturn));
 static void ip32_machine_halt(void) __attribute__((noreturn));
@@ -109,7 +109,7 @@
 	}
 	CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
 
-	if (has_paniced)
+	if (has_panicked)
 		ip32_machine_restart(NULL);
 
 	enable_irq(MACEISA_RTC_IRQ);
@@ -117,7 +117,7 @@
 
 static inline void ip32_power_button(void)
 {
-	if (has_paniced)
+	if (has_panicked)
 		return;
 
 	if (shuting_down || kill_proc(1, SIGINT, 1)) {
@@ -161,9 +161,9 @@
 {
 	unsigned long led;
 
-	if (has_paniced)
+	if (has_panicked)
 		return NOTIFY_DONE;
-	has_paniced = 1;
+	has_panicked = 1;
 
 	/* turn off the green LED */
 	led = mace->perif.ctrl.misc | MACEISA_LED_GREEN;
diff --git a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c
index a2dd8ae..acbdad0 100644
--- a/arch/mips/sgi-ip32/ip32-setup.c
+++ b/arch/mips/sgi-ip32/ip32-setup.c
@@ -87,7 +87,7 @@
 	setup_irq(IP32_R4K_TIMER_IRQ, irq);
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	board_be_init = ip32_be_init;
 
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
index e545752..efaf83e 100644
--- a/arch/mips/sibyte/bcm1480/time.c
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -110,17 +110,18 @@
 	__raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
 	      IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
 
-	/*
-	 * CPU 0 handles the global timer interrupt job
-	 */
 	if (cpu == 0) {
+		/*
+		 * CPU 0 handles the global timer interrupt job
+		 */
 		ll_timer_interrupt(irq, regs);
 	}
-
-	/*
-	 * every CPU should do profiling and process accouting
-	 */
-	ll_local_timer_interrupt(irq, regs);
+	else {
+		/*
+		 * other CPUs should just do profiling and process accounting
+		 */
+		ll_local_timer_interrupt(irq, regs);
+	}
 }
 
 /*
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 0f6e54d..f853c32 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -435,13 +435,17 @@
 	return lz;
 }
 
+extern void sb1250_timer_interrupt(struct pt_regs *regs);
+extern void sb1250_mailbox_interrupt(struct pt_regs *regs);
+extern void sb1250_kgdb_interrupt(struct pt_regs *regs);
+
 asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
 	unsigned int pending;
 
 #ifdef CONFIG_SIBYTE_SB1250_PROF
 	/* Set compare to count to silence count/compare timer interrupts */
-	write_c0_count(read_c0_count());
+	write_c0_compare(read_c0_count());
 #endif
 
 	/*
@@ -482,7 +486,7 @@
 		 * Default...we've hit an IP[2] interrupt, which means we've
 		 * got to check the 1250 interrupt registers to figure out what
 		 * to do.  Need to detect which CPU we're on, now that
-		 ~ smp_affinity is supported.
+		 * smp_affinity is supported.
 		 */
 		mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
 		                              R_IMR_INTERRUPT_STATUS_BASE)));
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 4b5f74f..f9e6949 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -72,8 +72,10 @@
 
 void __init swarm_time_init(void)
 {
+#if defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
 	/* Setup HPT */
 	sb1250_hpt_setup();
+#endif
 }
 
 void __init swarm_timer_setup(struct irqaction *irq)
@@ -103,7 +105,7 @@
 	return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 #if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
 	bcm1480_setup();
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index 9c7eaa5..a5eb0ad 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -3,5 +3,6 @@
 #
 
 obj-y	 	+= irq.o pcimt_scache.o reset.o setup.o
+obj-$(CONFIG_CPU_BIG_ENDIAN) += sniprom.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index 01ba6c5..a050bb6a 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -21,8 +21,11 @@
 #include <linux/fb.h>
 #include <linux/tty.h>
 
+#ifdef CONFIG_ARC
 #include <asm/arc/types.h>
 #include <asm/sgialib.h>
+#endif
+
 #include <asm/bcache.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
@@ -72,8 +75,7 @@
 
 static void __init sni_display_setup(void)
 {
-#ifdef CONFIG_VT
-#if defined(CONFIG_VGA_CONSOLE)
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) && defined(CONFIG_ARC)
 	struct screen_info *si = &screen_info;
 	DISPLAY_STATUS *di;
 
@@ -88,24 +90,54 @@
 		si->orig_video_points	= 16;
 	}
 #endif
-#endif
 }
 
 static struct resource sni_io_resource = {
-	"PCIMT IO MEM", 0x00001000UL, 0x03bfffffUL, IORESOURCE_IO,
+	.start	= 0x00001000UL,
+	.end	= 0x03bfffffUL,
+	.name	= "PCIMT IO MEM",
+	.flags	= IORESOURCE_IO,
 };
 
 static struct resource pcimt_io_resources[] = {
-	{ "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
-	{ "timer", 0x40, 0x5f, IORESOURCE_BUSY },
-	{ "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
-	{ "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
-	{ "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
-	{ "PCI config data", 0xcfc, 0xcff, IORESOURCE_BUSY }
+	{
+		.start	= 0x00,
+		.end	= 0x1f,
+		.name	= "dma1",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x40,
+		.end	= 0x5f,
+		.name	= "timer",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x60,
+		.end	= 0x6f,
+		.name	= "keyboard",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0x80,
+		.end	= 0x8f,
+		.name	= "dma page reg",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xc0,
+		.end	= 0xdf,
+		.name	= "dma2",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	=  0xcfc,
+		.end	= 0xcff,
+		.name	= "PCI config data",
+		.flags	= IORESOURCE_BUSY
+	}
 };
 
 static struct resource sni_mem_resource = {
-	"PCIMT PCI MEM", 0x10000000UL, 0xffffffffUL, IORESOURCE_MEM
+	.start	= 0x10000000UL,
+	.end	= 0xffffffffUL,
+	.name	= "PCIMT PCI MEM",
+	.flags	= IORESOURCE_MEM
 };
 
 /*
@@ -122,19 +154,72 @@
  * 0xa0000000 - 0xffffffff (1.5GB) PCI/EISA Bus Memory
  */
 static struct resource pcimt_mem_resources[] = {
-	{ "Video RAM area", 0x100a0000, 0x100bffff, IORESOURCE_BUSY },
-	{ "ISA Reserved", 0x100c0000, 0x100fffff, IORESOURCE_BUSY },
-	{ "PCI IO", 0x14000000, 0x17bfffff, IORESOURCE_BUSY },
-	{ "Cache Replacement Area", 0x17c00000, 0x17ffffff, IORESOURCE_BUSY},
-	{ "PCI INT Acknowledge", 0x1a000000, 0x1a000003, IORESOURCE_BUSY },
-	{ "Boot PROM", 0x1fc00000, 0x1fc7ffff, IORESOURCE_BUSY},
-	{ "Diag PROM", 0x1fc80000, 0x1fcfffff, IORESOURCE_BUSY},
-	{ "X-Bus", 0x1fd00000, 0x1fdfffff, IORESOURCE_BUSY},
-	{ "BIOS map", 0x1fe00000, 0x1fefffff, IORESOURCE_BUSY},
-	{ "NVRAM / EEPROM", 0x1ff00000, 0x1ff7ffff, IORESOURCE_BUSY},
-	{ "ASIC PCI", 0x1fff0000, 0x1fffefff, IORESOURCE_BUSY},
-	{ "MP Agent", 0x1ffff000, 0x1fffffff, IORESOURCE_BUSY},
-	{ "Main Memory", 0x20000000, 0x9fffffff, IORESOURCE_BUSY}
+	{
+		.start	= 0x100a0000,
+		.end	= 0x100bffff,
+		.name	= "Video RAM area",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x100c0000,
+		.end	= 0x100fffff,
+		.name	= "ISA Reserved",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x14000000,
+		.end	= 0x17bfffff,
+		.name	= "PCI IO",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x17c00000,
+		.end	= 0x17ffffff,
+		.name	= "Cache Replacement Area",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1a000000,
+		.end	= 0x1a000003,
+		.name	= "PCI INT Acknowledge",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fc00000,
+		.end	= 0x1fc7ffff,
+		.name	= "Boot PROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fc80000,
+		.end	= 0x1fcfffff,
+		.name	= "Diag PROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fd00000,
+		.end	= 0x1fdfffff,
+		.name	= "X-Bus",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fe00000,
+		.end	= 0x1fefffff,
+		.name	= "BIOS map",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1ff00000,
+		.end	= 0x1ff7ffff,
+		.name	= "NVRAM / EEPROM",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1fff0000,
+		.end	= 0x1fffefff,
+		.name	= "ASIC PCI",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x1ffff000,
+		.end	= 0x1fffffff,
+		.name	= "MP Agent",
+		.flags	= IORESOURCE_BUSY
+	}, {
+		.start	= 0x20000000,
+		.end	= 0x9fffffff,
+		.name	= "Main Memory",
+		.flags	= IORESOURCE_BUSY
+	}
 };
 
 static void __init sni_resource_init(void)
@@ -168,7 +253,7 @@
 	rtc_mips_set_time = mc146818_set_rtc_mmss;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	sni_pcimt_detect();
 	sni_pcimt_sc_init();
diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c
new file mode 100644
index 0000000..d1d0f1f
--- /dev/null
+++ b/arch/mips/sni/sniprom.c
@@ -0,0 +1,158 @@
+/*
+ * Big Endian PROM code for SNI RM machines
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org)
+ * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/addrspace.h>
+#include <asm/sni.h>
+#include <asm/mipsprom.h>
+#include <asm/bootinfo.h>
+
+/* special SNI prom calls */
+/*
+ * This does not exist in all proms - SINIX compares
+ * the prom env variable "version" against "2.0008"
+ * or greater. If lesser it tries to probe interesting
+ * registers
+ */
+#define PROM_GET_MEMCONF	58
+
+#define PROM_VEC		(u64 *)CKSEG1ADDR(0x1fc00000)
+#define PROM_ENTRY(x)		(PROM_VEC + (x))
+
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG_PRINTF(x...)     prom_printf(x)
+#else
+#define DBG_PRINTF(x...)
+#endif
+
+static int *(*__prom_putchar)(int)        = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR);
+static char *(*__prom_getenv)(char *)     = (char *(*)(char *))PROM_ENTRY(PROM_GETENV);
+static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF);
+
+char *prom_getenv (char *s)
+{
+	return __prom_getenv(s);
+}
+
+void prom_printf(char *fmt, ...)
+{
+	va_list args;
+	char ppbuf[1024];
+	char *bptr;
+
+	va_start(args, fmt);
+	vsprintf(ppbuf, fmt, args);
+
+	bptr = ppbuf;
+
+	while (*bptr != 0) {
+		if (*bptr == '\n')
+			__prom_putchar('\r');
+
+		__prom_putchar(*bptr++);
+	}
+	va_end(args);
+}
+
+unsigned long prom_free_prom_memory(void)
+{
+	return 0;
+}
+
+/*
+ * /proc/cpuinfo system type
+ *
+ */
+static const char *systype = "Unknown";
+const char *get_system_type(void)
+{
+	return systype;
+}
+
+#define SNI_IDPROM_BASE                0xbff00000
+#define SNI_IDPROM_MEMSIZE             (SNI_IDPROM_BASE+0x28)  /* Memsize in 16MB quantities */
+#define SNI_IDPROM_BRDTYPE             (SNI_IDPROM_BASE+0x29)  /* Board Type */
+#define SNI_IDPROM_CPUTYPE             (SNI_IDPROM_BASE+0x30)  /* CPU Type */
+
+#define SNI_IDPROM_SIZE	0x1000
+
+#ifdef DEBUG
+static void sni_idprom_dump(void)
+{
+	int	i;
+
+	prom_printf("SNI IDProm dump (first 128byte):\n");
+	for(i=0;i<128;i++) {
+		if (i%16 == 0)
+			prom_printf("%04x ", i);
+
+		prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE+i));
+
+		if (i%16 == 15)
+			prom_printf("\n");
+	}
+}
+#endif
+
+static void sni_mem_init(void )
+{
+	int i, memsize;
+	struct membank {
+	        u32		size;
+	        u32		base;
+	        u32		size2;
+	        u32		pad1;
+	        u32		pad2;
+	} memconf[8];
+
+	/* MemSIZE from prom in 16MByte chunks */
+	memsize=*((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
+
+	DBG_PRINTF("IDProm memsize: %lu MByte\n", memsize);
+
+	/* get memory bank layout from prom */
+	__prom_get_memconf(&memconf);
+
+	DBG_PRINTF("prom_get_mem_conf memory configuration:\n");
+	for(i=0;i<8 && memconf[i].size;i++) {
+		prom_printf("Bank%d: %08x @ %08x\n", i,
+			memconf[i].size, memconf[i].base);
+		add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
+	}
+}
+
+void __init prom_init(void)
+{
+	int argc = fw_arg0;
+	char **argv = (void *)fw_arg1;
+	unsigned int sni_brd_type = *(unsigned char *) SNI_IDPROM_BRDTYPE;
+	int i;
+
+	DBG_PRINTF("Found SNI brdtype %02x\n", sni_brd_type);
+
+#ifdef DEBUG
+	sni_idprom_dump();
+#endif
+	sni_mem_init();
+
+	/* copy prom cmdline parameters to kernel cmdline */
+	for (i = 1; i < argc; i++) {
+		strcat(arcs_cmdline, argv[i]);
+		if (i < (argc - 1))
+			strcat(arcs_cmdline, " ");
+	}
+}
+
diff --git a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c
index 77c3b66..81a5acf 100644
--- a/arch/mips/tx4927/common/tx4927_setup.c
+++ b/arch/mips/tx4927/common/tx4927_setup.c
@@ -64,7 +64,7 @@
 }
 
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	board_time_init = tx4927_time_init;
 	board_timer_setup = tx4927_timer_setup;
diff --git a/arch/mips/tx4938/common/setup.c b/arch/mips/tx4938/common/setup.c
index fc99295..ef59a5c 100644
--- a/arch/mips/tx4938/common/setup.c
+++ b/arch/mips/tx4938/common/setup.c
@@ -61,7 +61,7 @@
 }
 
 void __init
-plat_setup(void)
+plat_mem_setup(void)
 {
 	board_time_init = tx4938_time_init;
 	board_timer_setup = tx4938_timer_setup;
diff --git a/arch/mips/tx4938/toshiba_rbtx4938/setup.c b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
index 9166cd4..96e833c 100644
--- a/arch/mips/tx4938/toshiba_rbtx4938/setup.c
+++ b/arch/mips/tx4938/toshiba_rbtx4938/setup.c
@@ -664,7 +664,10 @@
 
 static char pcode_str[8];
 static struct resource tx4938_reg_resource = {
-	pcode_str, TX4938_REG_BASE, TX4938_REG_BASE+TX4938_REG_SIZE, IORESOURCE_MEM
+	.start	= TX4938_REG_BASE,
+	.end	= TX4938_REG_BASE + TX4938_REG_SIZE,
+	.name	= pcode_str,
+	.flags	= IORESOURCE_MEM
 };
 
 void __init tx4938_board_setup(void)
diff --git a/arch/mips/vr41xx/Kconfig b/arch/mips/vr41xx/Kconfig
index 055a2cd..6046ef2 100644
--- a/arch/mips/vr41xx/Kconfig
+++ b/arch/mips/vr41xx/Kconfig
@@ -4,7 +4,6 @@
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select ISA
-	select SYS_HAS_CPU_VR41XX
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
@@ -14,18 +13,15 @@
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select ISA
-	select SYS_HAS_CPU_VR41XX
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config NEC_CMBVR4133
 	bool "Support for NEC CMB-VR4133"
 	depends on MACH_VR41XX
-	select CPU_VR41XX
 	select DMA_NONCOHERENT
 	select IRQ_CPU
 	select HW_HAS_PCI
-	select SYS_HAS_CPU_VR41XX
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
@@ -41,7 +37,6 @@
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
-	select SYS_HAS_CPU_VR41XX
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	help
@@ -74,7 +69,6 @@
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
-	select SYS_HAS_CPU_VR41XX
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
@@ -84,7 +78,6 @@
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
 	select IRQ_CPU
-	select SYS_HAS_CPU_VR41XX
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 
diff --git a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
index 707bd09..915bfa5 100644
--- a/arch/mips/vr41xx/common/init.c
+++ b/arch/mips/vr41xx/common/init.c
@@ -58,7 +58,7 @@
 	board_timer_setup = setup_timer_irq;
 }
 
-void __init plat_setup(void)
+void __init plat_mem_setup(void)
 {
 	vr41xx_calculate_clock_frequency();
 
diff --git a/arch/parisc/hpux/sys_hpux.c b/arch/parisc/hpux/sys_hpux.c
index 05273cc..cb69727 100644
--- a/arch/parisc/hpux/sys_hpux.c
+++ b/arch/parisc/hpux/sys_hpux.c
@@ -145,7 +145,7 @@
 	s = user_get_super(dev);
 	if (s == NULL)
 		goto out;
-	err = vfs_statfs(s, &sbuf);
+	err = vfs_statfs(s->s_root, &sbuf);
 	drop_super(s);
 	if (err)
 		goto out;
@@ -186,12 +186,12 @@
      int16_t f_pad;
 };
 
-static int vfs_statfs_hpux(struct super_block *sb, struct hpux_statfs *buf)
+static int vfs_statfs_hpux(struct dentry *dentry, struct hpux_statfs *buf)
 {
 	struct kstatfs st;
 	int retval;
 	
-	retval = vfs_statfs(sb, &st);
+	retval = vfs_statfs(dentry, &st);
 	if (retval)
 		return retval;
 
@@ -219,7 +219,7 @@
 	error = user_path_walk(path, &nd);
 	if (!error) {
 		struct hpux_statfs tmp;
-		error = vfs_statfs_hpux(nd.dentry->d_inode->i_sb, &tmp);
+		error = vfs_statfs_hpux(nd.dentry, &tmp);
 		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 			error = -EFAULT;
 		path_release(&nd);
@@ -237,7 +237,7 @@
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = vfs_statfs_hpux(file->f_dentry->d_inode->i_sb, &tmp);
+	error = vfs_statfs_hpux(file->f_dentry, &tmp);
 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 		error = -EFAULT;
 	fput(file);
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 05767e8..cc38edf 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -248,7 +248,7 @@
 	DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
 			(unsigned long)ka, sp, frame_size);
 	
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp; /* Stacks grow up! */
 
 	DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
diff --git a/arch/parisc/kernel/topology.c b/arch/parisc/kernel/topology.c
index 3ba0400..068b20d 100644
--- a/arch/parisc/kernel/topology.c
+++ b/arch/parisc/kernel/topology.c
@@ -26,11 +26,10 @@
 
 static int __init topology_init(void)
 {
-	struct node *parent = NULL;
 	int num;
 
 	for_each_present_cpu(num) {
-		register_cpu(&cpu_devices[num], num, parent);
+		register_cpu(&cpu_devices[num], num);
 	}
 	return 0;
 }
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6729c98..e922a88 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -45,6 +45,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_NEXT_BIT
+	bool
+	default y
+
 config PPC
 	bool
 	default y
@@ -137,6 +141,15 @@
 	select FSL_SOC
 	select 85xx
 
+config PPC_86xx
+	bool "Freescale 86xx"
+	select 6xx
+	select FSL_SOC
+	select PPC_FPU
+	select ALTIVEC
+	help
+	  The Freescale E600 SoCs have 74xx cores.
+
 config 40x
 	bool "AMCC 40x"
 
@@ -336,7 +349,7 @@
 
 config PPC_PSERIES
 	depends on PPC_MULTIPLATFORM && PPC64
-	bool "  IBM pSeries & new (POWER5-based) iSeries"
+	bool "IBM pSeries & new (POWER5-based) iSeries"
 	select PPC_I8259
 	select PPC_RTAS
 	select RTAS_ERROR_LOGGING
@@ -344,7 +357,7 @@
 	default y
 
 config PPC_CHRP
-	bool "  Common Hardware Reference Platform (CHRP) based machines"
+	bool "Common Hardware Reference Platform (CHRP) based machines"
 	depends on PPC_MULTIPLATFORM && PPC32
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
@@ -354,7 +367,7 @@
 	default y
 
 config PPC_PMAC
-	bool "  Apple PowerMac based machines"
+	bool "Apple PowerMac based machines"
 	depends on PPC_MULTIPLATFORM
 	select PPC_INDIRECT_PCI if PPC32
 	select PPC_MPC106 if PPC32
@@ -370,7 +383,7 @@
 	default y
 
 config PPC_PREP
-	bool "  PowerPC Reference Platform (PReP) based machines"
+	bool "PowerPC Reference Platform (PReP) based machines"
 	depends on PPC_MULTIPLATFORM && PPC32 && BROKEN
 	select PPC_I8259
 	select PPC_INDIRECT_PCI
@@ -379,7 +392,7 @@
 
 config PPC_MAPLE
 	depends on PPC_MULTIPLATFORM && PPC64
-	bool "  Maple 970FX Evaluation Board"
+	bool "Maple 970FX Evaluation Board"
 	select U3_DART
 	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
@@ -391,8 +404,18 @@
 	  For more informations, refer to <http://www.970eval.com>
 
 config PPC_CELL
-	bool "  Cell Broadband Processor Architecture"
+	bool
+	default n
+
+config PPC_CELL_NATIVE
+	bool
+	select PPC_CELL
+	default n
+
+config PPC_IBM_CELL_BLADE
+	bool "  IBM Cell Blade"
 	depends on PPC_MULTIPLATFORM && PPC64
+	select PPC_CELL_NATIVE
 	select PPC_RTAS
 	select MMIO_NVRAM
 	select PPC_UDBG_16550
@@ -439,11 +462,6 @@
 	depends on PPC_MAPLE
 	default y
 
-config CELL_IIC
-	depends on PPC_CELL
-	bool
-	default y
-
 config IBMVIO
 	depends on PPC_PSERIES || PPC_ISERIES
 	bool
@@ -545,6 +563,7 @@
 source arch/powerpc/platforms/4xx/Kconfig
 source arch/powerpc/platforms/83xx/Kconfig
 source arch/powerpc/platforms/85xx/Kconfig
+source arch/powerpc/platforms/86xx/Kconfig
 source arch/powerpc/platforms/8xx/Kconfig
 source arch/powerpc/platforms/cell/Kconfig
 
@@ -699,7 +718,6 @@
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
 	depends on PPC64 && SMP
-	default off
 	help
 	  SMT scheduler support improves the CPU scheduler's decision making
 	  when dealing with POWER5 cpus at a cost of slightly increased
@@ -776,6 +794,7 @@
 
 config PPC_I8259
 	bool
+	default y if MPC8641_HPCN
 	default n
 
 config PPC_INDIRECT_PCI
@@ -798,8 +817,8 @@
 	bool
 
 config PCI
-	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
-	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx
+	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES)
+	default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx && !PPC_86xx
 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
 	help
@@ -827,12 +846,12 @@
 	default y
 
 config 8260_PCI9
-	bool "  Enable workaround for MPC826x erratum PCI 9"
+	bool "Enable workaround for MPC826x erratum PCI 9"
 	depends on PCI_8260 && !ADS8272
 	default y
 
 choice
-	prompt "  IDMA channel for PCI 9 workaround"
+	prompt "IDMA channel for PCI 9 workaround"
 	depends on 8260_PCI9
 
 config 8260_PCI9_IDMA1
@@ -849,6 +868,8 @@
 
 endchoice
 
+source "drivers/pci/pcie/Kconfig"
+
 source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index 8d48e9e..c69006a 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -110,13 +110,16 @@
 	depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \
 		PPC_GEN550 || PPC_MPC52xx
 
+config PPC_EARLY_DEBUG
+	bool "Early debugging (dangerous)"
+
 choice
-	prompt "Early debugging (dangerous)"
-	bool
-	optional
+	prompt "Early debugging console"
+	depends on PPC_EARLY_DEBUG
 	help
-	  Enable early debugging. Careful, if you enable debugging for the
-	  wrong type of machine your kernel _will not boot_.
+	  Use the selected console for early debugging. Careful, if you
+	  enable debugging for the wrong type of machine your kernel
+	  _will not boot_.
 
 config PPC_EARLY_DEBUG_LPAR
 	bool "LPAR HV Console"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index ed5b26a..01667d1 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -108,7 +108,6 @@
 CFLAGS		+= -mcpu=powerpc
 endif
 
-cpu-as-$(CONFIG_PPC64BRIDGE)	+= -Wa,-mppc64bridge
 cpu-as-$(CONFIG_4xx)		+= -Wa,-m405
 cpu-as-$(CONFIG_6xx)		+= -Wa,-maltivec
 cpu-as-$(CONFIG_POWER4)		+= -Wa,-maltivec
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 840ae59..d961bfe 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -29,8 +29,8 @@
 OBJCOPY_COFF_ARGS := -O aixcoff-rs6000 --set-start 0x500000
 OBJCOPY_MIB_ARGS  := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
 
-zlib       := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
-zlibheader := infblock.h infcodes.h inffast.h inftrees.h infutil.h
+zlib       := inffast.c inflate.c inftrees.c
+zlibheader := inffast.h inffixed.h inflate.h inftrees.h infutil.h
 zliblinuxheader := zlib.h zconf.h zutil.h
 
 $(addprefix $(obj)/,$(zlib) main.o): $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c
index 816446f..b66634c 100644
--- a/arch/powerpc/boot/main.c
+++ b/arch/powerpc/boot/main.c
@@ -33,6 +33,14 @@
 extern char _initrd_start[];
 extern char _initrd_end[];
 
+/* A buffer that may be edited by tools operating on a zImage binary so as to
+ * edit the command line passed to vmlinux (by setting /chosen/bootargs).
+ * The buffer is put in it's own section so that tools may locate it easier.
+ */
+static char builtin_cmdline[512]
+	__attribute__((section("__builtin_cmdline")));
+
+
 struct addr_range {
 	unsigned long addr;
 	unsigned long size;
@@ -204,6 +212,23 @@
 	return 1;
 }
 
+void export_cmdline(void* chosen_handle)
+{
+        int len;
+        char cmdline[2] = { 0, 0 };
+
+	if (builtin_cmdline[0] == 0)
+		return;
+
+        len = getprop(chosen_handle, "bootargs", cmdline, sizeof(cmdline));
+        if (len > 0 && cmdline[0] != 0)
+		return;
+
+	setprop(chosen_handle, "bootargs", builtin_cmdline,
+		strlen(builtin_cmdline) + 1);
+}
+
+
 void start(unsigned long a1, unsigned long a2, void *promptr, void *sp)
 {
 	int len;
@@ -289,6 +314,8 @@
 		memmove((void *)vmlinux.addr,(void *)vmlinuz.addr,vmlinuz.size);
 	}
 
+	export_cmdline(chosen_handle);
+
 	/* Skip over the ELF header */
 #ifdef DEBUG
 	printf("... skipping 0x%lx bytes of ELF header\n\r",
diff --git a/arch/powerpc/boot/prom.h b/arch/powerpc/boot/prom.h
index 3e2ddd4..a57b184 100644
--- a/arch/powerpc/boot/prom.h
+++ b/arch/powerpc/boot/prom.h
@@ -31,4 +31,11 @@
 	return call_prom("getprop", 4, 1, phandle, name, buf, buflen);
 }
 
+
+static inline int setprop(void *phandle, const char *name,
+			  void *buf, int buflen)
+{
+	return call_prom("setprop", 4, 1, phandle, name, buf, buflen);
+}
+
 #endif				/* _PPC_BOOT_PROM_H_ */
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index dbe421d..b8b8d46 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16
-# Thu Mar 23 20:48:09 2006
+# Linux kernel version: 2.6.17
+# Mon Jun 19 17:23:03 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -11,6 +11,7 @@
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -55,7 +56,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
-# CONFIG_CPUSETS is not set
+CONFIG_CPUSETS=y
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
@@ -116,13 +117,15 @@
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 CONFIG_PPC_CELL=y
+CONFIG_PPC_CELL_NATIVE=y
+CONFIG_PPC_IBM_CELL_BLADE=y
+CONFIG_PPC_SYSTEMSIM=y
 # CONFIG_U3_DART is not set
 CONFIG_PPC_RTAS=y
 # CONFIG_RTAS_ERROR_LOGGING is not set
 CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=y
 CONFIG_MMIO_NVRAM=y
-CONFIG_CELL_IIC=y
 # CONFIG_PPC_MPC106 is not set
 # CONFIG_PPC_970_NAP is not set
 # CONFIG_CPU_FREQ is not set
@@ -132,7 +135,9 @@
 # Cell Broadband Engine options
 #
 CONFIG_SPU_FS=m
+CONFIG_SPU_BASE=y
 CONFIG_SPUFS_MMAP=y
+CONFIG_CBE_RAS=y
 
 #
 # Kernel options
@@ -152,20 +157,24 @@
 CONFIG_KEXEC=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_IRQ_ALL_CPUS=y
-# CONFIG_NUMA is not set
+CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
 # CONFIG_DISCONTIGMEM_MANUAL is not set
 CONFIG_SPARSEMEM_MANUAL=y
 CONFIG_SPARSEMEM=y
+CONFIG_NEED_MULTIPLE_NODES=y
 CONFIG_HAVE_MEMORY_PRESENT=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPARSEMEM_EXTREME=y
-# CONFIG_MEMORY_HOTPLUG is not set
+CONFIG_MEMORY_HOTPLUG=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y
+CONFIG_ARCH_MEMORY_PROBE=y
 # CONFIG_PPC_64K_PAGES is not set
 CONFIG_SCHED_SMT=y
 CONFIG_PROC_DEVICETREE=y
@@ -182,6 +191,7 @@
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+CONFIG_PCIEPORTBUS=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -476,7 +486,7 @@
 #
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
+CONFIG_BONDING=y
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 
@@ -624,6 +634,7 @@
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
 # CONFIG_SX is not set
+# CONFIG_RIO is not set
 # CONFIG_STALDRV is not set
 
 #
@@ -766,6 +777,7 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1054,11 +1066,7 @@
 # CONFIG_XMON is not set
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig
new file mode 100644
index 0000000..9bb022a
--- /dev/null
+++ b/arch/powerpc/configs/mpc85xx_cds_defconfig
@@ -0,0 +1,846 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16
+# Sun Apr  2 11:23:42 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+# CONFIG_GENERIC_TBSYNC is not set
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+CONFIG_PPC_85xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_85xx=y
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_MPIC=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+
+#
+# Platform support
+#
+# CONFIG_MPC8540_ADS is not set
+CONFIG_MPC85xx_CDS=y
+CONFIG_MPC8540=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Kernel options
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_MATH_EMULATION=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+CONFIG_E1000_NAPI=y
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig
new file mode 100644
index 0000000..d7a30f9
--- /dev/null
+++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig
@@ -0,0 +1,921 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17-rc3
+# Fri Jun 16 10:47:09 2006
+#
+# CONFIG_PPC64 is not set
+CONFIG_PPC32=y
+CONFIG_PPC_MERGE=y
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PPC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_PPC_OF=y
+CONFIG_PPC_UDBG_16550=y
+CONFIG_GENERIC_TBSYNC=y
+# CONFIG_DEFAULT_UIMAGE is not set
+
+#
+# Processor support
+#
+# CONFIG_CLASSIC32 is not set
+# CONFIG_PPC_52xx is not set
+# CONFIG_PPC_82xx is not set
+# CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
+CONFIG_PPC_86xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_8xx is not set
+# CONFIG_E200 is not set
+CONFIG_6xx=y
+CONFIG_PPC_FPU=y
+CONFIG_ALTIVEC=y
+CONFIG_PPC_STD_MMU=y
+CONFIG_PPC_STD_MMU_32=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+# CONFIG_SLAB is not set
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_SLOB=y
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+CONFIG_MPIC=y
+# CONFIG_WANT_EARLY_SERIAL is not set
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Platform Support
+#
+CONFIG_MPC8641_HPCN=y
+CONFIG_MPC8641=y
+
+#
+# Kernel options
+#
+CONFIG_HIGHMEM=y
+# CONFIG_HZ_100 is not set
+# CONFIG_HZ_250 is not set
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_PREEMPT_BKL=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_IRQ_ALL_CPUS is not set
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PROC_DEVICETREE=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_PM is not set
+# CONFIG_SECCOMP is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PPC_I8259=y
+CONFIG_PPC_INDIRECT_PCI=y
+CONFIG_FSL_SOC=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+# CONFIG_WINDFARM is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+CONFIG_VITESSE_PHY=y
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+# CONFIG_I2C_CHARDEV is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+CONFIG_LDM_PARTITION=y
+# CONFIG_LDM_DEBUG is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Instrumentation Support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_UNWIND_INFO is not set
+CONFIG_FORCED_INLINING=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_DEBUGGER is not set
+# CONFIG_BDI_SWITCH is not set
+# CONFIG_BOOTX_TEXT is not set
+# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
+# CONFIG_PPC_EARLY_DEBUG_G5 is not set
+# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
+# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
+# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index 57a0279..addc793 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.16-rc6
-# Wed Mar 15 16:21:32 2006
+# Linux kernel version: 2.6.17-rc5
+# Mon May 29 14:47:49 2006
 #
 # CONFIG_PPC64 is not set
 CONFIG_PPC32=y
@@ -9,6 +9,7 @@
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
@@ -27,11 +28,11 @@
 # CONFIG_PPC_52xx is not set
 # CONFIG_PPC_82xx is not set
 # CONFIG_PPC_83xx is not set
+# CONFIG_PPC_85xx is not set
 # CONFIG_40x is not set
 # CONFIG_44x is not set
 # CONFIG_8xx is not set
 # CONFIG_E200 is not set
-# CONFIG_E500 is not set
 CONFIG_6xx=y
 CONFIG_PPC_FPU=y
 CONFIG_ALTIVEC=y
@@ -59,6 +60,7 @@
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_EMBEDDED is not set
@@ -73,10 +75,6 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_SLAB=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
@@ -88,7 +86,6 @@
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
@@ -97,6 +94,8 @@
 # Block layer
 #
 CONFIG_LBD=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+CONFIG_LSF=y
 
 #
 # IO Schedulers
@@ -124,6 +123,7 @@
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_PPC_MPC106=y
+# CONFIG_PPC_970_NAP is not set
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
 # CONFIG_CPU_FREQ_DEBUG is not set
@@ -182,7 +182,6 @@
 CONFIG_PPC_INDIRECT_PCI=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_LEGACY_PROC=y
 # CONFIG_PCI_DEBUG is not set
 
 #
@@ -239,7 +238,9 @@
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
@@ -250,9 +251,10 @@
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
 CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
@@ -264,6 +266,8 @@
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -278,12 +282,15 @@
 CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
 CONFIG_NETFILTER_XT_MATCH_COMMENT=m
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
 CONFIG_NETFILTER_XT_MATCH_HELPER=m
 CONFIG_NETFILTER_XT_MATCH_LENGTH=m
 CONFIG_NETFILTER_XT_MATCH_LIMIT=m
 CONFIG_NETFILTER_XT_MATCH_MAC=m
 CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
 CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
 CONFIG_NETFILTER_XT_MATCH_REALM=m
 CONFIG_NETFILTER_XT_MATCH_SCTP=m
@@ -305,15 +312,15 @@
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
 CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_H323=m
 # CONFIG_IP_NF_QUEUE is not set
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
 CONFIG_IP_NF_MATCH_RECENT=m
 CONFIG_IP_NF_MATCH_ECN=m
 CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_AH=m
 CONFIG_IP_NF_MATCH_TTL=m
 CONFIG_IP_NF_MATCH_OWNER=m
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
@@ -335,6 +342,7 @@
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
 CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_NAT_H323=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP_NF_TARGET_TOS=m
 CONFIG_IP_NF_TARGET_ECN=m
@@ -350,10 +358,12 @@
 #
 CONFIG_IP_DCCP=m
 CONFIG_INET_DCCP_DIAG=m
+CONFIG_IP_DCCP_ACKVEC=y
 
 #
 # DCCP CCIDs Configuration (EXPERIMENTAL)
 #
+CONFIG_IP_DCCP_CCID2=m
 CONFIG_IP_DCCP_CCID3=m
 CONFIG_IP_DCCP_TFRC_LIB=m
 
@@ -361,7 +371,6 @@
 # DCCP Kernel Hacking
 #
 # CONFIG_IP_DCCP_DEBUG is not set
-# CONFIG_IP_DCCP_UNLOAD_HACK is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -477,6 +486,8 @@
 CONFIG_IEEE80211_CRYPT_WEP=m
 CONFIG_IEEE80211_CRYPT_CCMP=m
 CONFIG_IEEE80211_CRYPT_TKIP=m
+# CONFIG_IEEE80211_SOFTMAC is not set
+CONFIG_WIRELESS_EXT=y
 
 #
 # Device Drivers
@@ -662,9 +673,8 @@
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -694,16 +704,17 @@
 CONFIG_MD_LINEAR=m
 CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
-# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=m
+CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_CRYPT=m
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 # CONFIG_DM_MULTIPATH is not set
 
 #
@@ -740,7 +751,7 @@
 CONFIG_IEEE1394_VIDEO1394=m
 CONFIG_IEEE1394_SBP2=m
 # CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
-CONFIG_IEEE1394_ETH1394=m
+# CONFIG_IEEE1394_ETH1394 is not set
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
 
@@ -769,10 +780,10 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
@@ -857,6 +868,7 @@
 # Wireless LAN (non-hamradio)
 #
 CONFIG_NET_RADIO=y
+# CONFIG_NET_WIRELESS_RTNETLINK is not set
 
 #
 # Obsolete Wireless cards support (pre-802.11)
@@ -992,6 +1004,7 @@
 # Serial drivers
 #
 CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_PCI=m
 # CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
@@ -1027,6 +1040,7 @@
 # Ftape, the floppy tape device driver
 #
 CONFIG_AGP=m
+# CONFIG_AGP_VIA is not set
 CONFIG_AGP_UNINORTH=m
 CONFIG_DRM=m
 # CONFIG_DRM_TDFX is not set
@@ -1081,7 +1095,6 @@
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
@@ -1100,10 +1113,8 @@
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCA9539 is not set
 # CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_SENSORS_M41T00 is not set
 # CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
@@ -1131,18 +1142,16 @@
 #
 
 #
-# Multimedia Capabilities Port drivers
-#
-
-#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
@@ -1152,6 +1161,7 @@
 CONFIG_FB_CFB_COPYAREA=y
 CONFIG_FB_CFB_IMAGEBLIT=y
 CONFIG_FB_MACMODES=y
+CONFIG_FB_FIRMWARE_EDID=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -1175,7 +1185,6 @@
 # CONFIG_FB_MATROX_G is not set
 # CONFIG_FB_MATROX_I2C is not set
 # CONFIG_FB_MATROX_MULTIHEAD is not set
-# CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
 CONFIG_FB_RADEON_I2C=y
 # CONFIG_FB_RADEON_DEBUG is not set
@@ -1234,9 +1243,11 @@
 CONFIG_SND_OSSEMUL=y
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
 CONFIG_SND_SEQUENCER_OSS=y
 # CONFIG_SND_DYNAMIC_MINORS is not set
 CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
 # CONFIG_SND_VERBOSE_PRINTK is not set
 # CONFIG_SND_DEBUG is not set
 
@@ -1253,6 +1264,7 @@
 # PCI devices
 #
 # CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
 # CONFIG_SND_ALS4000 is not set
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
@@ -1285,6 +1297,7 @@
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
 # CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
 # CONFIG_SND_RME32 is not set
 # CONFIG_SND_RME96 is not set
 # CONFIG_SND_RME9652 is not set
@@ -1310,6 +1323,8 @@
 #
 # PCMCIA devices
 #
+# CONFIG_SND_VXPOCKET is not set
+# CONFIG_SND_PDAUDIOCF is not set
 
 #
 # Open Sound System
@@ -1321,6 +1336,7 @@
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1336,7 +1352,9 @@
 #
 # USB Host Controller Drivers
 #
-# CONFIG_USB_EHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_SPLIT_ISO=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1347,7 +1365,6 @@
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
 
@@ -1358,7 +1375,17 @@
 #
 # may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_USB_STORAGE is not set
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -1374,9 +1401,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1391,15 +1416,6 @@
 # CONFIG_USB_MICROTEK is not set
 
 #
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-
-#
-# Video4Linux support is needed for USB Multimedia device support
-#
-
-#
 # USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
@@ -1429,6 +1445,7 @@
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_ANYDATA is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
 # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
@@ -1436,6 +1453,7 @@
 # CONFIG_USB_SERIAL_CYPRESS_M8 is not set
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_FUNSOFT is not set
 CONFIG_USB_SERIAL_VISOR=m
 CONFIG_USB_SERIAL_IPAQ=m
 # CONFIG_USB_SERIAL_IR is not set
@@ -1460,6 +1478,7 @@
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
@@ -1484,6 +1503,7 @@
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
 
@@ -1502,6 +1522,19 @@
 # CONFIG_MMC is not set
 
 #
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
@@ -1511,6 +1544,11 @@
 #
 
 #
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -1518,14 +1556,14 @@
 # CONFIG_EXT2_FS_XIP is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
 # CONFIG_EXT3_FS_SECURITY is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
@@ -1534,7 +1572,7 @@
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
+CONFIG_AUTOFS4_FS=m
 CONFIG_FUSE_FS=m
 
 #
@@ -1566,7 +1604,6 @@
 CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_RELAYFS_FS=m
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1590,17 +1627,24 @@
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V2_ACL=y
+CONFIG_NFSD_V3=y
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_ACL_SUPPORT=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
@@ -1681,7 +1725,7 @@
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 CONFIG_TEXTSEARCH=y
@@ -1735,29 +1779,29 @@
 # Cryptographic options
 #
 CONFIG_CRYPTO=y
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_NULL is not set
-# CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_WP512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_DES is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_TWOFISH is not set
-# CONFIG_CRYPTO_SERPENT is not set
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_NULL=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_DEFLATE is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_TEST is not set
 
 #
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 58e68ce..31708ad 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Wed Apr 19 11:48:00 2006
+# Linux kernel version: 2.6.17-rc4
+# Sun May 28 07:26:56 2006
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -11,6 +11,7 @@
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_PPC=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
@@ -126,8 +127,9 @@
 CONFIG_RTAS_FLASH=m
 # CONFIG_MMIO_NVRAM is not set
 CONFIG_IBMVIO=y
-# CONFIG_IBMEBUS is not set
+CONFIG_IBMEBUS=y
 # CONFIG_PPC_MPC106 is not set
+# CONFIG_PPC_970_NAP is not set
 # CONFIG_CPU_FREQ is not set
 # CONFIG_WANT_EARLY_SERIAL is not set
 
@@ -143,7 +145,7 @@
 # CONFIG_PREEMPT is not set
 # CONFIG_PREEMPT_BKL is not set
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_IOMMU_VMERGE=y
 CONFIG_HOTPLUG_CPU=y
@@ -155,6 +157,7 @@
 CONFIG_SCANLOG=m
 CONFIG_LPARCFG=y
 CONFIG_NUMA=y
+CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
 CONFIG_ARCH_SPARSEMEM_DEFAULT=y
@@ -467,7 +470,7 @@
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
-# CONFIG_SCSI_SAS_ATTRS is not set
+CONFIG_SCSI_SAS_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -499,13 +502,18 @@
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_SYM53C8XX_MMIO=y
 CONFIG_SCSI_IPR=y
 CONFIG_SCSI_IPR_TRACE=y
 CONFIG_SCSI_IPR_DUMP=y
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_QLA_FC is not set
+CONFIG_SCSI_QLA_FC=m
+CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE=y
+CONFIG_SCSI_QLA21XX=m
+CONFIG_SCSI_QLA22XX=m
+CONFIG_SCSI_QLA2300=m
+CONFIG_SCSI_QLA2322=m
+CONFIG_SCSI_QLA24XX=m
 CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
@@ -521,7 +529,7 @@
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID5_RESHAPE is not set
+CONFIG_MD_RAID5_RESHAPE=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
 CONFIG_MD_FAULTY=m
@@ -764,7 +772,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_ICOM=m
-# CONFIG_SERIAL_JSM is not set
+CONFIG_SERIAL_JSM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -773,7 +781,7 @@
 # CONFIG_TIPAR is not set
 CONFIG_HVC_DRIVER=y
 CONFIG_HVC_CONSOLE=y
-# CONFIG_HVC_RTAS is not set
+CONFIG_HVC_RTAS=y
 CONFIG_HVCS=m
 
 #
@@ -1031,9 +1039,7 @@
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1105,16 +1111,25 @@
 # CONFIG_NEW_LEDS is not set
 
 #
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
 # InfiniBand support
 #
 CONFIG_INFINIBAND=m
-# CONFIG_INFINIBAND_USER_MAD is not set
-# CONFIG_INFINIBAND_USER_ACCESS is not set
+CONFIG_INFINIBAND_USER_MAD=m
+CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_INFINIBAND_MTHCA=m
-# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_MTHCA_DEBUG=y
 CONFIG_INFINIBAND_IPOIB=m
-# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
-# CONFIG_INFINIBAND_SRP is not set
+CONFIG_INFINIBAND_IPOIB_DEBUG=y
+# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set
+CONFIG_INFINIBAND_SRP=m
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1159,15 +1174,15 @@
 CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_XFS_RT is not set
-# CONFIG_OCFS2_FS is not set
+CONFIG_OCFS2_FS=m
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
-CONFIG_AUTOFS_FS=m
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
 
 #
 # CD-ROM/DVD Filesystems
@@ -1199,7 +1214,7 @@
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
+CONFIG_CONFIGFS_FS=m
 
 #
 # Miscellaneous filesystems
@@ -1317,7 +1332,7 @@
 #
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
-# CONFIG_KPROBES is not set
+CONFIG_KPROBES=y
 
 #
 # Kernel hacking
@@ -1329,7 +1344,7 @@
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
-CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1339,17 +1354,13 @@
 CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_DEBUG_STACKOVERFLOW=y
-CONFIG_DEBUG_STACK_USAGE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 CONFIG_IRQSTACKS=y
 # CONFIG_BOOTX_TEXT is not set
-# CONFIG_PPC_EARLY_DEBUG_LPAR is not set
-# CONFIG_PPC_EARLY_DEBUG_G5 is not set
-# CONFIG_PPC_EARLY_DEBUG_RTAS is not set
-# CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
-# CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG is not set
 
 #
 # Security options
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index faaec9c..4734b5d 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -35,17 +35,19 @@
 
 #define INVALID	{ 0, 0 }
 
-#define LD	1	/* load */
-#define ST	2	/* store */
-#define	SE	4	/* sign-extend value */
-#define F	8	/* to/from fp regs */
-#define U	0x10	/* update index register */
-#define M	0x20	/* multiple load/store */
-#define SW	0x40	/* byte swap int or ... */
-#define S	0x40	/* ... single-precision fp */
-#define SX	0x40	/* byte count in XER */
+/* Bits in the flags field */
+#define LD	0	/* load */
+#define ST	1	/* store */
+#define	SE	2	/* sign-extend value */
+#define F	4	/* to/from fp regs */
+#define U	8	/* update index register */
+#define M	0x10	/* multiple load/store */
+#define SW	0x20	/* byte swap */
+#define S	0x40	/* single-precision fp or... */
+#define SX	0x40	/* ... byte count in XER */
 #define HARD	0x80	/* string, stwcx. */
 
+/* DSISR bits reported for a DCBZ instruction: */
 #define DCBZ	0x5f	/* 8xx/82xx dcbz faults when cache not enabled */
 
 #define SWAP(a, b)	(t = (a), (a) = (b), (b) = t)
@@ -256,12 +258,16 @@
 #define REG_BYTE(rp, i)		*((u8 *)(rp) + (i))
 #endif
 
+#define SWIZ_PTR(p)		((unsigned char __user *)((p) ^ swiz))
+
 static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr,
 			    unsigned int reg, unsigned int nb,
-			    unsigned int flags, unsigned int instr)
+			    unsigned int flags, unsigned int instr,
+			    unsigned long swiz)
 {
 	unsigned long *rptr;
-	unsigned int nb0, i;
+	unsigned int nb0, i, bswiz;
+	unsigned long p;
 
 	/*
 	 * We do not try to emulate 8 bytes multiple as they aren't really
@@ -280,9 +286,12 @@
 			if (nb == 0)
 				return 1;
 		} else {
-			if (__get_user(instr,
-				       (unsigned int __user *)regs->nip))
+			unsigned long pc = regs->nip ^ (swiz & 4);
+
+			if (__get_user(instr, (unsigned int __user *)pc))
 				return -EFAULT;
+			if (swiz == 0 && (flags & SW))
+				instr = cpu_to_le32(instr);
 			nb = (instr >> 11) & 0x1f;
 			if (nb == 0)
 				nb = 32;
@@ -300,7 +309,10 @@
 		return -EFAULT;	/* bad address */
 
 	rptr = &regs->gpr[reg];
-	if (flags & LD) {
+	p = (unsigned long) addr;
+	bswiz = (flags & SW)? 3: 0;
+
+	if (!(flags & ST)) {
 		/*
 		 * This zeroes the top 4 bytes of the affected registers
 		 * in 64-bit mode, and also zeroes out any remaining
@@ -311,26 +323,28 @@
 			memset(&regs->gpr[0], 0,
 			       ((nb0 + 3) / 4) * sizeof(unsigned long));
 
-		for (i = 0; i < nb; ++i)
-			if (__get_user(REG_BYTE(rptr, i), addr + i))
+		for (i = 0; i < nb; ++i, ++p)
+			if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
 				return -EFAULT;
 		if (nb0 > 0) {
 			rptr = &regs->gpr[0];
 			addr += nb;
-			for (i = 0; i < nb0; ++i)
-				if (__get_user(REG_BYTE(rptr, i), addr + i))
+			for (i = 0; i < nb0; ++i, ++p)
+				if (__get_user(REG_BYTE(rptr, i ^ bswiz),
+					       SWIZ_PTR(p)))
 					return -EFAULT;
 		}
 
 	} else {
-		for (i = 0; i < nb; ++i)
-			if (__put_user(REG_BYTE(rptr, i), addr + i))
+		for (i = 0; i < nb; ++i, ++p)
+			if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p)))
 				return -EFAULT;
 		if (nb0 > 0) {
 			rptr = &regs->gpr[0];
 			addr += nb;
-			for (i = 0; i < nb0; ++i)
-				if (__put_user(REG_BYTE(rptr, i), addr + i))
+			for (i = 0; i < nb0; ++i, ++p)
+				if (__put_user(REG_BYTE(rptr, i ^ bswiz),
+					       SWIZ_PTR(p)))
 					return -EFAULT;
 		}
 	}
@@ -352,7 +366,7 @@
 	unsigned int reg, areg;
 	unsigned int dsisr;
 	unsigned char __user *addr;
-	unsigned char __user *p;
+	unsigned long p, swiz;
 	int ret, t;
 	union {
 		u64 ll;
@@ -380,11 +394,15 @@
 	 * let's make one up from the instruction
 	 */
 	if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {
-		unsigned int real_instr;
-		if (unlikely(__get_user(real_instr,
-					(unsigned int __user *)regs->nip)))
+		unsigned long pc = regs->nip;
+
+		if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE))
+			pc ^= 4;
+		if (unlikely(__get_user(instr, (unsigned int __user *)pc)))
 			return -EFAULT;
-		dsisr = make_dsisr(real_instr);
+		if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE))
+			instr = cpu_to_le32(instr);
+		dsisr = make_dsisr(instr);
 	}
 
 	/* extract the operation and registers from the dsisr */
@@ -397,6 +415,24 @@
 	nb = aligninfo[instr].len;
 	flags = aligninfo[instr].flags;
 
+	/* Byteswap little endian loads and stores */
+	swiz = 0;
+	if (regs->msr & MSR_LE) {
+		flags ^= SW;
+		/*
+		 * So-called "PowerPC little endian" mode works by
+		 * swizzling addresses rather than by actually doing
+		 * any byte-swapping.  To emulate this, we XOR each
+		 * byte address with 7.  We also byte-swap, because
+		 * the processor's address swizzling depends on the
+		 * operand size (it xors the address with 7 for bytes,
+		 * 6 for halfwords, 4 for words, 0 for doublewords) but
+		 * we will xor with 7 and load/store each byte separately.
+		 */
+		if (cpu_has_feature(CPU_FTR_PPC_LE))
+			swiz = 7;
+	}
+
 	/* DAR has the operand effective address */
 	addr = (unsigned char __user *)regs->dar;
 
@@ -412,7 +448,8 @@
 	 * function
 	 */
 	if (flags & M)
-		return emulate_multiple(regs, addr, reg, nb, flags, instr);
+		return emulate_multiple(regs, addr, reg, nb,
+					flags, instr, swiz);
 
 	/* Verify the address of the operand */
 	if (unlikely(user_mode(regs) &&
@@ -431,51 +468,71 @@
 	/* If we are loading, get the data from user space, else
 	 * get it from register values
 	 */
-	if (flags & LD) {
+	if (!(flags & ST)) {
 		data.ll = 0;
 		ret = 0;
-		p = addr;
+		p = (unsigned long) addr;
 		switch (nb) {
 		case 8:
-			ret |= __get_user(data.v[0], p++);
-			ret |= __get_user(data.v[1], p++);
-			ret |= __get_user(data.v[2], p++);
-			ret |= __get_user(data.v[3], p++);
+			ret |= __get_user(data.v[0], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[1], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[2], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[3], SWIZ_PTR(p++));
 		case 4:
-			ret |= __get_user(data.v[4], p++);
-			ret |= __get_user(data.v[5], p++);
+			ret |= __get_user(data.v[4], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[5], SWIZ_PTR(p++));
 		case 2:
-			ret |= __get_user(data.v[6], p++);
-			ret |= __get_user(data.v[7], p++);
+			ret |= __get_user(data.v[6], SWIZ_PTR(p++));
+			ret |= __get_user(data.v[7], SWIZ_PTR(p++));
 			if (unlikely(ret))
 				return -EFAULT;
 		}
-	} else if (flags & F)
+	} else if (flags & F) {
 		data.dd = current->thread.fpr[reg];
-	else
+		if (flags & S) {
+			/* Single-precision FP store requires conversion... */
+#ifdef CONFIG_PPC_FPU
+			preempt_disable();
+			enable_kernel_fp();
+			cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
+			preempt_enable();
+#else
+			return 0;
+#endif
+		}
+	} else
 		data.ll = regs->gpr[reg];
 
-	/* Perform other misc operations like sign extension, byteswap,
+	if (flags & SW) {
+		switch (nb) {
+		case 8:
+			SWAP(data.v[0], data.v[7]);
+			SWAP(data.v[1], data.v[6]);
+			SWAP(data.v[2], data.v[5]);
+			SWAP(data.v[3], data.v[4]);
+			break;
+		case 4:
+			SWAP(data.v[4], data.v[7]);
+			SWAP(data.v[5], data.v[6]);
+			break;
+		case 2:
+			SWAP(data.v[6], data.v[7]);
+			break;
+		}
+	}
+
+	/* Perform other misc operations like sign extension
 	 * or floating point single precision conversion
 	 */
-	switch (flags & ~U) {
+	switch (flags & ~(U|SW)) {
 	case LD+SE:	/* sign extend */
 		if ( nb == 2 )
 			data.ll = data.x16.low16;
 		else	/* nb must be 4 */
 			data.ll = data.x32.low32;
 		break;
-	case LD+S:	/* byte-swap */
-	case ST+S:
-		if (nb == 2) {
-			SWAP(data.v[6], data.v[7]);
-		} else {
-			SWAP(data.v[4], data.v[7]);
-			SWAP(data.v[5], data.v[6]);
-		}
-		break;
 
-	/* Single-precision FP load and store require conversions... */
+	/* Single-precision FP load requires conversion... */
 	case LD+F+S:
 #ifdef CONFIG_PPC_FPU
 		preempt_disable();
@@ -486,34 +543,24 @@
 		return 0;
 #endif
 		break;
-	case ST+F+S:
-#ifdef CONFIG_PPC_FPU
-		preempt_disable();
-		enable_kernel_fp();
-		cvt_df(&data.dd, (float *)&data.v[4], &current->thread);
-		preempt_enable();
-#else
-		return 0;
-#endif
-		break;
 	}
 
 	/* Store result to memory or update registers */
 	if (flags & ST) {
 		ret = 0;
-		p = addr;
+		p = (unsigned long) addr;
 		switch (nb) {
 		case 8:
-			ret |= __put_user(data.v[0], p++);
-			ret |= __put_user(data.v[1], p++);
-			ret |= __put_user(data.v[2], p++);
-			ret |= __put_user(data.v[3], p++);
+			ret |= __put_user(data.v[0], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[1], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[2], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[3], SWIZ_PTR(p++));
 		case 4:
-			ret |= __put_user(data.v[4], p++);
-			ret |= __put_user(data.v[5], p++);
+			ret |= __put_user(data.v[4], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[5], SWIZ_PTR(p++));
 		case 2:
-			ret |= __put_user(data.v[6], p++);
-			ret |= __put_user(data.v[7], p++);
+			ret |= __put_user(data.v[6], SWIZ_PTR(p++));
+			ret |= __put_user(data.v[7], SWIZ_PTR(p++));
 		}
 		if (unlikely(ret))
 			return -EFAULT;
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 8f85c5e..ff29405 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -122,9 +122,8 @@
 	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
 	DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr));
 	DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
-#ifdef CONFIG_PPC_64K_PAGES
-	DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir));
-#endif
+	DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp));
+	DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp));
 #ifdef CONFIG_HUGETLB_PAGE
 	DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas));
 	DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas));
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S
index 55ed771..365381f 100644
--- a/arch/powerpc/kernel/cpu_setup_6xx.S
+++ b/arch/powerpc/kernel/cpu_setup_6xx.S
@@ -210,9 +210,11 @@
 	 * the firmware. If any, we disable NAP capability as
 	 * it's known to be bogus on rev 2.1 and earlier
 	 */
+BEGIN_FTR_SECTION
 	mfspr	r11,SPRN_L3CR
 	andis.	r11,r11,L3CR_L3E@h
 	beq	1f
+END_FTR_SECTION_IFSET(CPU_FTR_L3CR)
 	lwz	r6,CPU_SPEC_FEATURES(r5)
 	andi.	r0,r6,CPU_FTR_L3_DISABLE_NAP
 	beq	1f
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S
index b61d86e..2714183 100644
--- a/arch/powerpc/kernel/cpu_setup_power4.S
+++ b/arch/powerpc/kernel/cpu_setup_power4.S
@@ -73,23 +73,6 @@
 	isync
 	blr
 
-_GLOBAL(__setup_cpu_power4)
-	blr
-
-_GLOBAL(__setup_cpu_be)
-        /* Set large page sizes LP=0: 16MB, LP=1: 64KB */
-        addi    r3, 0,  0
-        ori     r3, r3, HID6_LB
-        sldi    r3, r3, 32
-        nor     r3, r3, r3
-        mfspr   r4, SPRN_HID6
-        and     r4, r4, r3
-        addi    r3, 0, 0x02000
-        sldi    r3, r3, 32
-        or      r4, r4, r3
-        mtspr   SPRN_HID6, r4
-	blr
-
 _GLOBAL(__setup_cpu_ppc970)
 	mfspr	r0,SPRN_HID0
 	li	r11,5			/* clear DOZE and SLEEP */
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 3f7182d..1c11488 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -30,11 +30,7 @@
  * part of the cputable though. That has to be fixed for both ppc32
  * and ppc64
  */
-#ifdef CONFIG_PPC64
-extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);
-extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
-#else
+#ifdef CONFIG_PPC32
 extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
 extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -58,7 +54,8 @@
 #define COMMON_USER_POWER5_PLUS	(COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\
 				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
 #define COMMON_USER_POWER6	(COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\
-				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP)
+				 PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \
+				 PPC_FEATURE_TRUE_LE)
 #define COMMON_USER_BOOKE	(PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \
 				 PPC_FEATURE_BOOKE)
 
@@ -78,11 +75,10 @@
 		.pvr_value		= 0x00400000,
 		.cpu_name		= "POWER3 (630)",
 		.cpu_features		= CPU_FTRS_POWER3,
-		.cpu_user_features	= COMMON_USER_PPC64,
+		.cpu_user_features	= COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/power3",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "power3",
@@ -92,11 +88,10 @@
 		.pvr_value		= 0x00410000,
 		.cpu_name		= "POWER3 (630+)",
 		.cpu_features		= CPU_FTRS_POWER3,
-		.cpu_user_features	= COMMON_USER_PPC64,
+		.cpu_user_features	= COMMON_USER_PPC64|PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/power3",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "power3",
@@ -110,7 +105,6 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -124,7 +118,6 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -138,7 +131,6 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -152,7 +144,6 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power3,
 		.oprofile_cpu_type	= "ppc64/rs64",
 		.oprofile_type		= PPC_OPROFILE_RS64,
 		.platform		= "rs64",
@@ -166,7 +157,6 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power4",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "power4",
@@ -180,7 +170,6 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 8,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power4",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "power4",
@@ -200,17 +189,11 @@
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "ppc970",
 	},
-#endif /* CONFIG_PPC64 */
-#if defined(CONFIG_PPC64) || defined(CONFIG_POWER4)
 	{	/* PPC970FX */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x003c0000,
 		.cpu_name		= "PPC970FX",
-#ifdef CONFIG_PPC32
-		.cpu_features		= CPU_FTRS_970_32,
-#else
 		.cpu_features		= CPU_FTRS_PPC970,
-#endif
 		.cpu_user_features	= COMMON_USER_POWER4 |
 			PPC_FEATURE_HAS_ALTIVEC_COMP,
 		.icache_bsize		= 128,
@@ -221,8 +204,6 @@
 		.oprofile_type		= PPC_OPROFILE_POWER4,
 		.platform		= "ppc970",
 	},
-#endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */
-#ifdef CONFIG_PPC64
 	{	/* PPC970MP */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x00440000,
@@ -232,6 +213,7 @@
 			PPC_FEATURE_HAS_ALTIVEC_COMP,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
+		.num_pmcs		= 8,
 		.cpu_setup		= __setup_cpu_ppc970,
 		.oprofile_cpu_type	= "ppc64/970",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
@@ -246,9 +228,13 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power5",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
+		/* SIHV / SIPR bits are implemented on POWER4+ (GQ)
+		 * and above but only works on POWER5 and above
+		 */
+		.oprofile_mmcra_sihv	= MMCRA_SIHV,
+		.oprofile_mmcra_sipr	= MMCRA_SIPR,
 		.platform		= "power5",
 	},
 	{	/* Power5 GS */
@@ -260,9 +246,10 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
 		.oprofile_cpu_type	= "ppc64/power5+",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
+		.oprofile_mmcra_sihv	= MMCRA_SIHV,
+		.oprofile_mmcra_sipr	= MMCRA_SIPR,
 		.platform		= "power5+",
 	},
 	{	/* Power6 */
@@ -273,10 +260,13 @@
 		.cpu_user_features	= COMMON_USER_POWER6,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
+		.num_pmcs		= 8,
 		.oprofile_cpu_type	= "ppc64/power6",
 		.oprofile_type		= PPC_OPROFILE_POWER4,
+ 		.oprofile_mmcra_sihv	= POWER6_MMCRA_SIHV,
+ 		.oprofile_mmcra_sipr	= POWER6_MMCRA_SIPR,
+ 		.oprofile_mmcra_clear	= POWER6_MMCRA_THRM |
+ 			POWER6_MMCRA_OTHER,
 		.platform		= "power6",
 	},
 	{	/* Cell Broadband Engine */
@@ -289,7 +279,6 @@
 			PPC_FEATURE_SMT,
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
-		.cpu_setup		= __setup_cpu_be,
 		.platform		= "ppc-cell-be",
 	},
 	{	/* default match */
@@ -301,7 +290,6 @@
 		.icache_bsize		= 128,
 		.dcache_bsize		= 128,
 		.num_pmcs		= 6,
-		.cpu_setup		= __setup_cpu_power4,
 		.platform		= "power4",
 	}
 #endif	/* CONFIG_PPC64 */
@@ -323,7 +311,7 @@
 		.pvr_value		= 0x00030000,
 		.cpu_name		= "603",
 		.cpu_features		= CPU_FTRS_603,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -334,7 +322,7 @@
 		.pvr_value		= 0x00060000,
 		.cpu_name		= "603e",
 		.cpu_features		= CPU_FTRS_603,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -345,7 +333,7 @@
 		.pvr_value		= 0x00070000,
 		.cpu_name		= "603ev",
 		.cpu_features		= CPU_FTRS_603,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603,
@@ -356,7 +344,7 @@
 		.pvr_value		= 0x00040000,
 		.cpu_name		= "604",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 2,
@@ -368,7 +356,7 @@
 		.pvr_value		= 0x00090000,
 		.cpu_name		= "604e",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -380,7 +368,7 @@
 		.pvr_value		= 0x00090000,
 		.cpu_name		= "604r",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -392,7 +380,7 @@
 		.pvr_value		= 0x000a0000,
 		.cpu_name		= "604ev",
 		.cpu_features		= CPU_FTRS_604,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -404,7 +392,7 @@
 		.pvr_value		= 0x00084202,
 		.cpu_name		= "740/750",
 		.cpu_features		= CPU_FTRS_740_NOTAU,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -416,7 +404,7 @@
 		.pvr_value		= 0x00080100,
 		.cpu_name		= "750CX",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -428,7 +416,7 @@
 		.pvr_value		= 0x00082200,
 		.cpu_name		= "750CX",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -440,7 +428,7 @@
 		.pvr_value		= 0x00082210,
 		.cpu_name		= "750CXe",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -452,7 +440,7 @@
 		.pvr_value		= 0x00083214,
 		.cpu_name		= "750CXe",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -464,7 +452,7 @@
 		.pvr_value		= 0x00083000,
 		.cpu_name		= "745/755",
 		.cpu_features		= CPU_FTRS_750,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -476,7 +464,7 @@
 		.pvr_value		= 0x70000100,
 		.cpu_name		= "750FX",
 		.cpu_features		= CPU_FTRS_750FX1,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -488,7 +476,7 @@
 		.pvr_value		= 0x70000200,
 		.cpu_name		= "750FX",
 		.cpu_features		= CPU_FTRS_750FX2,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -500,7 +488,7 @@
 		.pvr_value		= 0x70000000,
 		.cpu_name		= "750FX",
 		.cpu_features		= CPU_FTRS_750FX,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -512,7 +500,7 @@
 		.pvr_value		= 0x70020000,
 		.cpu_name		= "750GX",
 		.cpu_features		= CPU_FTRS_750GX,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -524,7 +512,7 @@
 		.pvr_value		= 0x00080000,
 		.cpu_name		= "740/750",
 		.cpu_features		= CPU_FTRS_740,
-		.cpu_user_features	= COMMON_USER,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -536,7 +524,8 @@
 		.pvr_value		= 0x000c1101,
 		.cpu_name		= "7400 (1.1)",
 		.cpu_features		= CPU_FTRS_7400_NOTAU,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -548,7 +537,8 @@
 		.pvr_value		= 0x000c0000,
 		.cpu_name		= "7400",
 		.cpu_features		= CPU_FTRS_7400,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -560,7 +550,8 @@
 		.pvr_value		= 0x800c0000,
 		.cpu_name		= "7410",
 		.cpu_features		= CPU_FTRS_7400,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
@@ -572,7 +563,8 @@
 		.pvr_value		= 0x80000200,
 		.cpu_name		= "7450",
 		.cpu_features		= CPU_FTRS_7450_20,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -586,7 +578,8 @@
 		.pvr_value		= 0x80000201,
 		.cpu_name		= "7450",
 		.cpu_features		= CPU_FTRS_7450_21,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -600,7 +593,8 @@
 		.pvr_value		= 0x80000000,
 		.cpu_name		= "7450",
 		.cpu_features		= CPU_FTRS_7450_23,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -614,7 +608,8 @@
 		.pvr_value		= 0x80010100,
 		.cpu_name		= "7455",
 		.cpu_features		= CPU_FTRS_7455_1,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -628,7 +623,8 @@
 		.pvr_value		= 0x80010200,
 		.cpu_name		= "7455",
 		.cpu_features		= CPU_FTRS_7455_20,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -642,7 +638,8 @@
 		.pvr_value		= 0x80010000,
 		.cpu_name		= "7455",
 		.cpu_features		= CPU_FTRS_7455,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -656,7 +653,8 @@
 		.pvr_value		= 0x80020100,
 		.cpu_name		= "7447/7457",
 		.cpu_features		= CPU_FTRS_7447_10,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -670,7 +668,8 @@
 		.pvr_value		= 0x80020101,
 		.cpu_name		= "7447/7457",
 		.cpu_features		= CPU_FTRS_7447_10,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -684,7 +683,7 @@
 		.pvr_value		= 0x80020000,
 		.cpu_name		= "7447/7457",
 		.cpu_features		= CPU_FTRS_7447,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -698,7 +697,8 @@
 		.pvr_value		= 0x80030000,
 		.cpu_name		= "7447A",
 		.cpu_features		= CPU_FTRS_7447A,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -712,7 +712,8 @@
 		.pvr_value		= 0x80040000,
 		.cpu_name		= "7448",
 		.cpu_features		= CPU_FTRS_7447A,
-		.cpu_user_features	= COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+		.cpu_user_features	= COMMON_USER |
+			PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE,
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 		.num_pmcs		= 6,
@@ -721,6 +722,18 @@
 		.oprofile_type		= PPC_OPROFILE_G4,
 		.platform		= "ppc7450",
 	},
+        {       /* 8641 */
+               .pvr_mask               = 0xffffffff,
+               .pvr_value              = 0x80040010,
+               .cpu_name               = "8641",
+               .cpu_features           = CPU_FTRS_7447A,
+               .cpu_user_features      = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+               .num_pmcs               = 6,
+               .cpu_setup              = __setup_cpu_745x
+        },
+
 	{	/* 82xx (8240, 8245, 8260 are all 603e cores) */
 		.pvr_mask		= 0x7fff0000,
 		.pvr_value		= 0x00810000,
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index 778f22f..e253a45 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -22,6 +22,7 @@
 #include <linux/elf.h>
 #include <linux/elfcore.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/types.h>
 
 #include <asm/processor.h>
@@ -174,9 +175,11 @@
 
 void default_machine_crash_shutdown(struct pt_regs *regs)
 {
+	unsigned int irq;
+
 	/*
 	 * This function is only called after the system
-	 * has paniced or is otherwise in a critical state.
+	 * has panicked or is otherwise in a critical state.
 	 * The minimum amount of code to allow a kexec'd kernel
 	 * to run successfully needs to happen here.
 	 *
@@ -186,6 +189,16 @@
 	 */
 	local_irq_disable();
 
+	for_each_irq(irq) {
+		struct irq_desc *desc = irq_descp(irq);
+
+		if (desc->status & IRQ_INPROGRESS)
+			desc->handler->end(irq);
+
+		if (!(desc->status & IRQ_DISABLED))
+			desc->handler->disable(irq);
+	}
+
 	if (ppc_md.kexec_cpu_down)
 		ppc_md.kexec_cpu_down(1, 0);
 
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c
index 764d073..371973b 100644
--- a/arch/powerpc/kernel/crash_dump.c
+++ b/arch/powerpc/kernel/crash_dump.c
@@ -25,6 +25,11 @@
 #define DBG(fmt...)
 #endif
 
+void reserve_kdump_trampoline(void)
+{
+	lmb_reserve(0, KDUMP_RESERVE_LIMIT);
+}
+
 static void __init create_trampoline(unsigned long addr)
 {
 	/* The maximum range of a single instruction branch, is the current
@@ -39,11 +44,11 @@
 	create_branch(addr + 4, addr + PHYSICAL_START, 0);
 }
 
-void __init kdump_setup(void)
+void __init setup_kdump_trampoline(void)
 {
 	unsigned long i;
 
-	DBG(" -> kdump_setup()\n");
+	DBG(" -> setup_kdump_trampoline()\n");
 
 	for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
 		create_trampoline(i);
@@ -52,7 +57,7 @@
 	create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
 	create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
 
-	DBG(" <- kdump_setup()\n");
+	DBG(" <- setup_kdump_trampoline()\n");
 }
 
 #ifdef CONFIG_PROC_VMCORE
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 19ad5c6..221062c 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -57,6 +57,7 @@
 	beq-	1f
 	ld	r1,PACAKSAVE(r13)
 1:	std	r10,0(r1)
+	crclr	so
 	std	r11,_NIP(r1)
 	std	r12,_MSR(r1)
 	std	r0,GPR0(r1)
@@ -75,7 +76,6 @@
 	std	r11,GPR11(r1)
 	std	r11,GPR12(r1)
 	std	r9,GPR13(r1)
-	crclr	so
 	mfcr	r9
 	mflr	r10
 	li	r11,0xc01
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S
index 340730f..01f7120 100644
--- a/arch/powerpc/kernel/fpu.S
+++ b/arch/powerpc/kernel/fpu.S
@@ -72,7 +72,7 @@
 	std	r12,_MSR(r1)
 #endif
 	lfd	fr0,THREAD_FPSCR(r5)
-	mtfsf	0xff,fr0
+	MTFSF_L(fr0)
 	REST_32FPRS(0, r5)
 #ifndef CONFIG_SMP
 	subi	r4,r5,THREAD
@@ -127,7 +127,7 @@
 
 _GLOBAL(cvt_fd)
 	lfd	0,THREAD_FPSCR(r5)	/* load up fpscr value */
-	mtfsf	0xff,0
+	MTFSF_L(0)
 	lfs	0,0(r3)
 	stfd	0,0(r4)
 	mffs	0
@@ -136,7 +136,7 @@
 
 _GLOBAL(cvt_df)
 	lfd	0,THREAD_FPSCR(r5)	/* load up fpscr value */
-	mtfsf	0xff,0
+	MTFSF_L(0)
 	lfd	0,0(r3)
 	stfs	0,0(r4)
 	mffs	0
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index a0579e8..b25b259 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -973,6 +973,13 @@
         b       __secondary_start
 #endif /* CONFIG_GEMINI */
 
+	.globl __secondary_start_mpc86xx
+__secondary_start_mpc86xx:
+	mfspr	r3, SPRN_PIR
+	stw	r3, __secondary_hold_acknowledge@l(0)
+	mr	r24, r3			/* cpu # */
+	b	__secondary_start
+
 	.globl	__secondary_start_pmac_0
 __secondary_start_pmac_0:
 	/* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */
@@ -1088,7 +1095,12 @@
 	LOAD_BAT(1,r3,r4,r5)
 	LOAD_BAT(2,r3,r4,r5)
 	LOAD_BAT(3,r3,r4,r5)
-
+BEGIN_FTR_SECTION
+	LOAD_BAT(4,r3,r4,r5)
+	LOAD_BAT(5,r3,r4,r5)
+	LOAD_BAT(6,r3,r4,r5)
+	LOAD_BAT(7,r3,r4,r5)
+END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS)
 	blr
 
 /*
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index b7d1404..831acbd 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -316,6 +316,21 @@
 	mtspr	SPRN_SPRG1,r13;		/* save r13 */	\
 	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
 
+#define HSTD_EXCEPTION_PSERIES(n, label)		\
+	. = n;						\
+	.globl label##_pSeries;				\
+label##_pSeries:					\
+	HMT_MEDIUM;					\
+	mtspr	SPRN_SPRG1,r20;		/* save r20 */	\
+	mfspr	r20,SPRN_HSRR0;		/* copy HSRR0 to SRR0 */ \
+	mtspr	SPRN_SRR0,r20;				\
+	mfspr	r20,SPRN_HSRR1;		/* copy HSRR0 to SRR0 */ \
+	mtspr	SPRN_SRR1,r20;				\
+	mfspr	r20,SPRN_SPRG1;		/* restore r20 */ \
+	mtspr	SPRN_SPRG1,r13;		/* save r13 */	\
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)
+
+
 #define STD_EXCEPTION_ISERIES(n, label, area)		\
 	.globl label##_iSeries;				\
 label##_iSeries:					\
@@ -544,8 +559,17 @@
 
 	STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable)
 
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)
+#endif /* CONFIG_CBE_RAS */
 	STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)
+#endif /* CONFIG_CBE_RAS */
 	STD_EXCEPTION_PSERIES(0x1700, altivec_assist)
+#ifdef CONFIG_CBE_RAS
+	HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)
+#endif /* CONFIG_CBE_RAS */
 
 	. = 0x3000
 
@@ -827,6 +851,11 @@
 #else
 	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
 #endif
+#ifdef CONFIG_CBE_RAS
+	STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
+	STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
+	STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
+#endif /* CONFIG_CBE_RAS */
 
 /*
  * Here we have detected that the kernel stack pointer is bad.
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c
index fd8214c..a13a93d 100644
--- a/arch/powerpc/kernel/iomap.c
+++ b/arch/powerpc/kernel/iomap.c
@@ -106,8 +106,6 @@
 
 void __iomem *ioport_map(unsigned long port, unsigned int len)
 {
-	if (!_IO_IS_VALID(port))
-		return NULL;
 	return (void __iomem *) (port+pci_io_base);
 }
 
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 4eba60a..7cb77c2 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -418,10 +418,11 @@
  * Build a iommu_table structure.  This contains a bit map which
  * is used to manage allocation of the tce space.
  */
-struct iommu_table *iommu_init_table(struct iommu_table *tbl)
+struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
 {
 	unsigned long sz;
 	static int welcomed = 0;
+	struct page *page;
 
 	/* Set aside 1/4 of the table for large allocations. */
 	tbl->it_halfpoint = tbl->it_size * 3 / 4;
@@ -429,10 +430,10 @@
 	/* number of bytes needed for the bitmap */
 	sz = (tbl->it_size + 7) >> 3;
 
-	tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz));
-	if (!tbl->it_map)
+	page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz));
+	if (!page)
 		panic("iommu_init_table: Can't allocate %ld bytes\n", sz);
-
+	tbl->it_map = page_address(page);
 	memset(tbl->it_map, 0, sz);
 
 	tbl->it_hint = 0;
@@ -536,11 +537,12 @@
  * to the dma address (mapping) of the first page.
  */
 void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
+		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
 {
 	void *ret = NULL;
 	dma_addr_t mapping;
 	unsigned int npages, order;
+	struct page *page;
 
 	size = PAGE_ALIGN(size);
 	npages = size >> PAGE_SHIFT;
@@ -560,9 +562,10 @@
 		return NULL;
 
 	/* Alloc enough pages (and possibly more) */
-	ret = (void *)__get_free_pages(flag, order);
-	if (!ret)
+	page = alloc_pages_node(node, flag, order);
+	if (!page)
 		return NULL;
+	ret = page_address(page);
 	memset(ret, 0, size);
 
 	/* Set up tces to cover the allocated range */
@@ -570,9 +573,9 @@
 			      mask >> PAGE_SHIFT, order);
 	if (mapping == DMA_ERROR_CODE) {
 		free_pages((unsigned long)ret, order);
-		ret = NULL;
-	} else
-		*dma_handle = mapping;
+		return NULL;
+	}
+	*dma_handle = mapping;
 	return ret;
 }
 
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 57d560c..40d4c14 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -47,6 +47,7 @@
 #include <linux/cpumask.h>
 #include <linux/profile.h>
 #include <linux/bitops.h>
+#include <linux/pci.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -379,8 +380,8 @@
 #endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_IRQSTACKS
-struct thread_info *softirq_ctx[NR_CPUS];
-struct thread_info *hardirq_ctx[NR_CPUS];
+struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
+struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly;
 
 void irq_ctx_init(void)
 {
@@ -436,6 +437,30 @@
 }
 EXPORT_SYMBOL(do_softirq);
 
+#ifdef CONFIG_PCI_MSI
+int pci_enable_msi(struct pci_dev * pdev)
+{
+	if (ppc_md.enable_msi)
+		return ppc_md.enable_msi(pdev);
+	else
+		return -1;
+}
+
+void pci_disable_msi(struct pci_dev * pdev)
+{
+	if (ppc_md.disable_msi)
+		ppc_md.disable_msi(pdev);
+}
+
+void pci_scan_msi_device(struct pci_dev *dev) {}
+int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;}
+void pci_disable_msix(struct pci_dev *dev) {}
+void msi_remove_pci_irq_vectors(struct pci_dev *dev) {}
+void disable_msi_mode(struct pci_dev *dev, int pos, int type) {}
+void pci_no_msi(void) {}
+
+#endif
+
 #ifdef CONFIG_PPC64
 static int __init setup_noirqdistrib(char *str)
 {
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c
index 2cbde86..c02deaa 100644
--- a/arch/powerpc/kernel/lparcfg.c
+++ b/arch/powerpc/kernel/lparcfg.c
@@ -521,10 +521,10 @@
 
 	current_weight = (resource >> 5 * 8) & 0xFF;
 
-	pr_debug("%s: current_entitled = %lu, current_weight = %lu\n",
+	pr_debug("%s: current_entitled = %lu, current_weight = %u\n",
 		 __FUNCTION__, current_entitled, current_weight);
 
-	pr_debug("%s: new_entitled = %lu, new_weight = %lu\n",
+	pr_debug("%s: new_entitled = %lu, new_weight = %u\n",
 		 __FUNCTION__, *new_entitled_ptr, *new_weight_ptr);
 
 	retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr,
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c
index 4436061..cbaa341 100644
--- a/arch/powerpc/kernel/machine_kexec_32.c
+++ b/arch/powerpc/kernel/machine_kexec_32.c
@@ -30,8 +30,8 @@
  */
 void default_machine_kexec(struct kimage *image)
 {
-	const extern unsigned char relocate_new_kernel[];
-	const extern unsigned int relocate_new_kernel_size;
+	extern const unsigned char relocate_new_kernel[];
+	extern const unsigned int relocate_new_kernel_size;
 	unsigned long page_list;
 	unsigned long reboot_code_buffer, reboot_code_buffer_phys;
 	relocate_new_kernel_t rnk;
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index ee166c5..a8fa04e 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -21,6 +21,7 @@
 #include <asm/machdep.h>
 #include <asm/cacheflush.h>
 #include <asm/paca.h>
+#include <asm/lmb.h>
 #include <asm/mmu.h>
 #include <asm/sections.h>	/* _end */
 #include <asm/prom.h>
@@ -335,7 +336,105 @@
 	of_node_put(node);
 }
 
+static struct property crashk_base_prop = {
+	.name = "linux,crashkernel-base",
+	.length = sizeof(unsigned long),
+	.value = (unsigned char *)&crashk_res.start,
+};
+
+static unsigned long crashk_size;
+
+static struct property crashk_size_prop = {
+	.name = "linux,crashkernel-size",
+	.length = sizeof(unsigned long),
+	.value = (unsigned char *)&crashk_size,
+};
+
+static void __init export_crashk_values(void)
+{
+	struct device_node *node;
+	struct property *prop;
+
+	node = of_find_node_by_path("/chosen");
+	if (!node)
+		return;
+
+	/* There might be existing crash kernel properties, but we can't
+	 * be sure what's in them, so remove them. */
+	prop = of_find_property(node, "linux,crashkernel-base", NULL);
+	if (prop)
+		prom_remove_property(node, prop);
+
+	prop = of_find_property(node, "linux,crashkernel-size", NULL);
+	if (prop)
+		prom_remove_property(node, prop);
+
+	if (crashk_res.start != 0) {
+		prom_add_property(node, &crashk_base_prop);
+		crashk_size = crashk_res.end - crashk_res.start + 1;
+		prom_add_property(node, &crashk_size_prop);
+	}
+
+	of_node_put(node);
+}
+
 void __init kexec_setup(void)
 {
 	export_htab_values();
+	export_crashk_values();
+}
+
+static int __init early_parse_crashk(char *p)
+{
+	unsigned long size;
+
+	if (!p)
+		return 1;
+
+	size = memparse(p, &p);
+
+	if (*p == '@')
+		crashk_res.start = memparse(p + 1, &p);
+	else
+		crashk_res.start = KDUMP_KERNELBASE;
+
+	crashk_res.end = crashk_res.start + size - 1;
+
+	return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+	unsigned long size;
+
+	if (crashk_res.start == 0)
+		return;
+
+	/* We might have got these values via the command line or the
+	 * device tree, either way sanitise them now. */
+
+	size = crashk_res.end - crashk_res.start + 1;
+
+	if (crashk_res.start != KDUMP_KERNELBASE)
+		printk("Crash kernel location must be 0x%x\n",
+				KDUMP_KERNELBASE);
+
+	crashk_res.start = KDUMP_KERNELBASE;
+	size = PAGE_ALIGN(size);
+	crashk_res.end = crashk_res.start + size - 1;
+
+	/* Crash kernel trumps memory limit */
+	if (memory_limit && memory_limit <= crashk_res.end) {
+		memory_limit = crashk_res.end + 1;
+		printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+				memory_limit);
+	}
+
+	lmb_reserve(crashk_res.start, size);
+}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+	return (start + size) > crashk_res.start && start <= crashk_res.end;
 }
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index be98202..01d3916 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -216,7 +216,7 @@
 	lwz	r4,0(r4)
 	add	r4,r4,r3
 	lwz	r5,CPU_SPEC_SETUP(r4)
-	cmpi	0,r5,0
+	cmpwi	0,r5,0
 	add	r5,r5,r3
 	beqlr
 	mtctr	r5
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 2778cce..e8883d4 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -482,7 +482,9 @@
 	sub	r0,r3,r5
 	std	r0,0(r4)
 	ld	r4,CPU_SPEC_SETUP(r3)
+	cmpdi	0,r4,0
 	add	r4,r4,r5
+	beqlr
 	ld	r4,0(r4)
 	add	r4,r4,r5
 	mtctr	r4
@@ -768,9 +770,6 @@
 
 #endif /* CONFIG_ALTIVEC */
 
-_GLOBAL(__setup_cpu_power3)
-	blr
-
 _GLOBAL(execve)
 	li	r0,__NR_execve
 	sc
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c
index ada50aa..6960f09 100644
--- a/arch/powerpc/kernel/nvram_64.c
+++ b/arch/powerpc/kernel/nvram_64.c
@@ -204,7 +204,7 @@
 	printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n");
 	list_for_each(p, &nvram_part->partition) {
 		tmp_part = list_entry(p, struct nvram_partition, partition);
-		printk(KERN_WARNING "%d    \t%02x\t%02x\t%d\t%s\n",
+		printk(KERN_WARNING "%4d    \t%02x\t%02x\t%d\t%s\n",
 		       tmp_part->index, tmp_part->header.signature,
 		       tmp_part->header.checksum, tmp_part->header.length,
 		       tmp_part->header.name);
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index b129d2e..b5431cc 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -1113,9 +1113,10 @@
 	int	i;
 	int	rc = 0;
 
-#define push_end(res, size) do { unsigned long __sz = (size) ; \
-	res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \
-    } while (0)
+#define push_end(res, mask) do {		\
+	BUG_ON((mask+1) & mask);		\
+	res->end = (res->end + mask) | mask;	\
+} while (0)
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		u16 class = dev->class >> 8;
@@ -1653,7 +1654,6 @@
 		return -EINVAL;
 
 	vma->vm_pgoff = offset >> PAGE_SHIFT;
-	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
 	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
 						  vma->vm_page_prot,
 						  mmap_state, write_combine);
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 4c4449b..247937d 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -42,14 +42,6 @@
 unsigned long pci_probe_only = 1;
 int pci_assign_all_buses = 0;
 
-/*
- * legal IO pages under MAX_ISA_PORT.  This is to ensure we don't touch
- * devices we don't have access to.
- */
-unsigned long io_page_mask;
-
-EXPORT_SYMBOL(io_page_mask);
-
 #ifdef CONFIG_PPC_MULTIPLATFORM
 static void fixup_resource(struct resource *res, struct pci_dev *dev);
 static void do_bus_setup(struct pci_bus *bus);
@@ -235,8 +227,10 @@
 	pci_setup_pci_controller(phb);
 	phb->arch_data = dev;
 	phb->is_dynamic = mem_init_done;
-	if (dev)
+	if (dev) {
+		PHB_SET_NODE(phb, of_node_to_nid(dev));
 		add_linux_pci_domain(dev, phb);
+	}
 	return phb;
 }
 
@@ -396,7 +390,7 @@
 
 	dev->current_state = 4;		/* unknown power state */
 
-	if (!strcmp(type, "pci")) {
+	if (!strcmp(type, "pci") || !strcmp(type, "pciex")) {
 		/* a PCI-PCI bridge */
 		dev->hdr_type = PCI_HEADER_TYPE_BRIDGE;
 		dev->rom_base_reg = PCI_ROM_ADDRESS1;
@@ -605,7 +599,7 @@
 	iSeries_pcibios_init(); 
 #endif
 
-	printk("PCI: Probing PCI hardware\n");
+	printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
@@ -630,14 +624,14 @@
 	/* Cache the location of the ISA bridge (if we have one) */
 	ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
 	if (ppc64_isabridge_dev != NULL)
-		printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
+		printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
 	/* map in PCI I/O space */
 	phbs_remap_io();
 #endif
 
-	printk("PCI: Probing PCI hardware done\n");
+	printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
 
 	return 0;
 }
@@ -804,7 +798,7 @@
 	else
 		prot |= _PAGE_GUARDED;
 
-	printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
+	printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start,
 	       prot);
 
 	return __pgprot(prot);
@@ -883,7 +877,6 @@
 		return -EINVAL;
 
 	vma->vm_pgoff = offset >> PAGE_SHIFT;
-	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
 	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
 						  vma->vm_page_prot,
 						  mmap_state, write_combine);
@@ -894,8 +887,8 @@
 	return ret;
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t pci_show_devspec(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pdev;
 	struct device_node *np;
@@ -907,13 +900,10 @@
 	return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_MULTIPLATFORM
 	device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
@@ -1104,8 +1094,6 @@
 			pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys,
 						hose->io_base_virt);
 			of_node_put(isa_dn);
-			/* Allow all IO */
-			io_page_mask = -1;
 		}
 	}
 
@@ -1212,7 +1200,7 @@
 		return 1;
 	if (start_phys == 0)
 		return 1;
-	printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
+	printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
 	if (__ioremap_explicit(start_phys, start_virt, size,
 			       _PAGE_NO_CACHE | _PAGE_GUARDED))
 		return 1;
@@ -1232,27 +1220,13 @@
 static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned long start, end, mask, offset;
+	unsigned long offset;
 
 	if (res->flags & IORESOURCE_IO) {
 		offset = (unsigned long)hose->io_base_virt - pci_io_base;
 
-		start = res->start += offset;
-		end = res->end += offset;
-
-		/* Need to allow IO access to pages that are in the
-		   ISA range */
-		if (start < MAX_ISA_PORT) {
-			if (end > MAX_ISA_PORT)
-				end = MAX_ISA_PORT;
-
-			start >>= PAGE_SHIFT;
-			end >>= PAGE_SHIFT;
-
-			/* get the range of pages for the map */
-			mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1);
-			io_page_mask |= mask;
-		}
+		res->start += offset;
+		res->end += offset;
 	} else if (res->flags & IORESOURCE_MEM) {
 		res->start += hose->pci_mem_offset;
 		res->end += hose->pci_mem_offset;
@@ -1442,3 +1416,12 @@
 
 	return -EOPNOTSUPP;
 }
+
+#ifdef CONFIG_NUMA
+int pcibus_to_node(struct pci_bus *bus)
+{
+	struct pci_controller *phb = pci_bus_to_host(bus);
+	return phb->node;
+}
+EXPORT_SYMBOL(pcibus_to_node);
+#endif
diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c
index e1a32f8..72ce082 100644
--- a/arch/powerpc/kernel/pci_direct_iommu.c
+++ b/arch/powerpc/kernel/pci_direct_iommu.c
@@ -82,13 +82,17 @@
 	return mask < 0x100000000ull;
 }
 
+static struct dma_mapping_ops pci_direct_ops = {
+	.alloc_coherent = pci_direct_alloc_coherent,
+	.free_coherent = pci_direct_free_coherent,
+	.map_single = pci_direct_map_single,
+	.unmap_single = pci_direct_unmap_single,
+	.map_sg = pci_direct_map_sg,
+	.unmap_sg = pci_direct_unmap_sg,
+	.dma_supported = pci_direct_dma_supported,
+};
+
 void __init pci_direct_iommu_init(void)
 {
-	pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent;
-	pci_dma_ops.free_coherent = pci_direct_free_coherent;
-	pci_dma_ops.map_single = pci_direct_map_single;
-	pci_dma_ops.unmap_single = pci_direct_unmap_single;
-	pci_dma_ops.map_sg = pci_direct_map_sg;
-	pci_dma_ops.unmap_sg = pci_direct_unmap_sg;
-	pci_dma_ops.dma_supported = pci_direct_dma_supported;
+	pci_dma_ops = pci_direct_ops;
 }
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 12c4c9e..1c18953 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -31,6 +31,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/ppc-pci.h>
+#include <asm/firmware.h>
 
 /*
  * Traverse_func that inits the PCI fields of the device node.
@@ -59,6 +60,11 @@
 		pdn->busno = (regs[0] >> 16) & 0xff;
 		pdn->devfn = (regs[0] >> 8) & 0xff;
 	}
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL);
+		if (busp)
+			pdn->bussubno = *busp;
+	}
 
 	pdn->pci_ext_config_space = (type && *type == 1);
 	return NULL;
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index c1d95e1..0688b25 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -44,16 +44,16 @@
  */
 #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
 
-static inline struct iommu_table *devnode_table(struct device *dev)
+static inline struct iommu_table *device_to_table(struct device *hwdev)
 {
 	struct pci_dev *pdev;
 
-	if (!dev) {
+	if (!hwdev) {
 		pdev = ppc64_isabridge_dev;
 		if (!pdev)
 			return NULL;
 	} else
-		pdev = to_pci_dev(dev);
+		pdev = to_pci_dev(hwdev);
 
 	return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
 }
@@ -85,14 +85,15 @@
 static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
-	return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
-			device_to_mask(hwdev), flag);
+	return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
+			device_to_mask(hwdev), flag,
+			pcibus_to_node(to_pci_dev(hwdev)->bus));
 }
 
 static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle);
+	iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle);
 }
 
 /* Creates TCEs for a user provided buffer.  The user buffer must be 
@@ -104,7 +105,7 @@
 static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 		size_t size, enum dma_data_direction direction)
 {
-	return iommu_map_single(devnode_table(hwdev), vaddr, size,
+	return iommu_map_single(device_to_table(hwdev), vaddr, size,
 			        device_to_mask(hwdev), direction);
 }
 
@@ -112,27 +113,27 @@
 static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
 		size_t size, enum dma_data_direction direction)
 {
-	iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction);
+	iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction);
 }
 
 
 static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
-	return iommu_map_sg(pdev, devnode_table(pdev), sglist,
+	return iommu_map_sg(pdev, device_to_table(pdev), sglist,
 			nelems, device_to_mask(pdev), direction);
 }
 
 static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
-	iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction);
+	iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction);
 }
 
 /* We support DMA to/from any memory page via the iommu */
 static int pci_iommu_dma_supported(struct device *dev, u64 mask)
 {
-	struct iommu_table *tbl = devnode_table(dev);
+	struct iommu_table *tbl = device_to_table(dev);
 
 	if (!tbl || tbl->it_offset > mask) {
 		printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n");
@@ -147,13 +148,17 @@
 		return 1;
 }
 
+struct dma_mapping_ops pci_iommu_ops = {
+	.alloc_coherent = pci_iommu_alloc_coherent,
+	.free_coherent = pci_iommu_free_coherent,
+	.map_single = pci_iommu_map_single,
+	.unmap_single = pci_iommu_unmap_single,
+	.map_sg = pci_iommu_map_sg,
+	.unmap_sg = pci_iommu_unmap_sg,
+	.dma_supported = pci_iommu_dma_supported,
+};
+
 void pci_iommu_init(void)
 {
-	pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent;
-	pci_dma_ops.free_coherent = pci_iommu_free_coherent;
-	pci_dma_ops.map_single = pci_iommu_map_single;
-	pci_dma_ops.unmap_single = pci_iommu_unmap_single;
-	pci_dma_ops.map_sg = pci_iommu_map_sg;
-	pci_dma_ops.unmap_sg = pci_iommu_unmap_sg;
-	pci_dma_ops.dma_supported = pci_iommu_dma_supported;
+	pci_dma_ops = pci_iommu_ops;
 }
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index 3c2cf66..2ab8f2b 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -52,7 +52,7 @@
 	if (!root)
 		return 1;
 
-	if (!machine_is(pseries) && !machine_is(cell))
+	if (!of_find_node_by_path("/rtas"))
 		return 0;
 
 	if (!proc_mkdir("rtas", root))
@@ -115,8 +115,6 @@
 {
 	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
 
-	vma->vm_flags |= VM_SHM | VM_LOCKED;
-
 	if ((vma->vm_end - vma->vm_start) > dp->size)
 		return -EINVAL;
 
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 2dd47d2d..e473245 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -708,6 +708,61 @@
 	return put_user(val, (unsigned int __user *) adr);
 }
 
+int set_endian(struct task_struct *tsk, unsigned int val)
+{
+	struct pt_regs *regs = tsk->thread.regs;
+
+	if ((val == PR_ENDIAN_LITTLE && !cpu_has_feature(CPU_FTR_REAL_LE)) ||
+	    (val == PR_ENDIAN_PPC_LITTLE && !cpu_has_feature(CPU_FTR_PPC_LE)))
+		return -EINVAL;
+
+	if (regs == NULL)
+		return -EINVAL;
+
+	if (val == PR_ENDIAN_BIG)
+		regs->msr &= ~MSR_LE;
+	else if (val == PR_ENDIAN_LITTLE || val == PR_ENDIAN_PPC_LITTLE)
+		regs->msr |= MSR_LE;
+	else
+		return -EINVAL;
+
+	return 0;
+}
+
+int get_endian(struct task_struct *tsk, unsigned long adr)
+{
+	struct pt_regs *regs = tsk->thread.regs;
+	unsigned int val;
+
+	if (!cpu_has_feature(CPU_FTR_PPC_LE) &&
+	    !cpu_has_feature(CPU_FTR_REAL_LE))
+		return -EINVAL;
+
+	if (regs == NULL)
+		return -EINVAL;
+
+	if (regs->msr & MSR_LE) {
+		if (cpu_has_feature(CPU_FTR_REAL_LE))
+			val = PR_ENDIAN_LITTLE;
+		else
+			val = PR_ENDIAN_PPC_LITTLE;
+	} else
+		val = PR_ENDIAN_BIG;
+
+	return put_user(val, (unsigned int __user *)adr);
+}
+
+int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
+{
+	tsk->thread.align_ctl = val;
+	return 0;
+}
+
+int get_unalign_ctl(struct task_struct *tsk, unsigned long adr)
+{
+	return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);
+}
+
 #define TRUNC_PTR(x)	((typeof(x))(((unsigned long)(x)) & 0xffffffff))
 
 int sys_clone(unsigned long clone_flags, unsigned long usp,
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9a07f97..483455c 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -50,6 +50,7 @@
 #include <asm/machdep.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
+#include <asm/kexec.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) printk(KERN_ERR fmt)
@@ -836,6 +837,42 @@
 	return mem;
 }
 
+static int __init early_parse_mem(char *p)
+{
+	if (!p)
+		return 1;
+
+	memory_limit = PAGE_ALIGN(memparse(p, &p));
+	DBG("memory limit = 0x%lx\n", memory_limit);
+
+	return 0;
+}
+early_param("mem", early_parse_mem);
+
+/*
+ * The device tree may be allocated below our memory limit, or inside the
+ * crash kernel region for kdump. If so, move it out now.
+ */
+static void move_device_tree(void)
+{
+	unsigned long start, size;
+	void *p;
+
+	DBG("-> move_device_tree\n");
+
+	start = __pa(initial_boot_params);
+	size = initial_boot_params->totalsize;
+
+	if ((memory_limit && (start + size) > memory_limit) ||
+			overlaps_crashkernel(start, size)) {
+		p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
+		memcpy(p, initial_boot_params, size);
+		initial_boot_params = (struct boot_param_header *)p;
+		DBG("Moved device tree to 0x%p\n", p);
+	}
+
+	DBG("<- move_device_tree\n");
+}
 
 /**
  * unflattens the device-tree passed by the firmware, creating the
@@ -911,7 +948,10 @@
 	{CPU_FTR_CTRL, 0,		0, 3, 0},
 	{CPU_FTR_NOEXECUTE, 0,		0, 6, 0},
 	{CPU_FTR_NODSISRALIGN, 0,	1, 1, 1},
+#if 0
+	/* put this back once we know how to test if firmware does 64k IO */
 	{CPU_FTR_CI_LARGE_PAGE, 0,	1, 2, 0},
+#endif
 };
 
 static void __init check_cpu_pa_features(unsigned long node)
@@ -1070,6 +1110,7 @@
 		iommu_force_on = 1;
 #endif
 
+	/* mem=x on the command line is the preferred mechanism */
  	lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
  	if (lprop)
  		memory_limit = *lprop;
@@ -1123,17 +1164,6 @@
 
 	DBG("Command line is: %s\n", cmd_line);
 
-	if (strstr(cmd_line, "mem=")) {
-		char *p, *q;
-
-		for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
-			q = p + 4;
-			if (p > cmd_line && p[-1] != ' ')
-				continue;
-			memory_limit = memparse(q, &q);
-		}
-	}
-
 	/* break now */
 	return 1;
 }
@@ -1237,9 +1267,17 @@
 {
 	u64 base, size;
 	u64 *reserve_map;
+	unsigned long self_base;
+	unsigned long self_size;
 
 	reserve_map = (u64 *)(((unsigned long)initial_boot_params) +
 					initial_boot_params->off_mem_rsvmap);
+
+	/* before we do anything, lets reserve the dt blob */
+	self_base = __pa((unsigned long)initial_boot_params);
+	self_size = initial_boot_params->totalsize;
+	lmb_reserve(self_base, self_size);
+
 #ifdef CONFIG_PPC32
 	/* 
 	 * Handle the case where we might be booting from an old kexec
@@ -1254,6 +1292,9 @@
 			size_32 = *(reserve_map_32++);
 			if (size_32 == 0)
 				break;
+			/* skip if the reservation is for the blob */
+			if (base_32 == self_base && size_32 == self_size)
+				continue;
 			DBG("reserving: %x -> %x\n", base_32, size_32);
 			lmb_reserve(base_32, size_32);
 		}
@@ -1265,6 +1306,9 @@
 		size = *(reserve_map++);
 		if (size == 0)
 			break;
+		/* skip if the reservation is for the blob */
+		if (base == self_base && size == self_size)
+			continue;
 		DBG("reserving: %llx -> %llx\n", base, size);
 		lmb_reserve(base, size);
 	}
@@ -1292,17 +1336,25 @@
 	lmb_init();
 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
 	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+	/* Save command line for /proc/cmdline and then parse parameters */
+	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+	parse_early_param();
+
+	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
+	lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
+	reserve_kdump_trampoline();
+	reserve_crashkernel();
+	early_reserve_mem();
+
 	lmb_enforce_memory_limit(memory_limit);
 	lmb_analyze();
 
 	DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
 
-	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
-	lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
-#ifdef CONFIG_CRASH_DUMP
-	lmb_reserve(0, KDUMP_RESERVE_LIMIT);
-#endif
-	early_reserve_mem();
+	/* We may need to relocate the flat tree, do it now.
+	 * FIXME .. and the initrd too? */
+	move_device_tree();
 
 	DBG("Scanning CPUs ...\n");
 
@@ -2053,29 +2105,46 @@
 	return 0;
 }
 
-#ifdef CONFIG_KEXEC
-/* We may have allocated the flat device tree inside the crash kernel region
- * in prom_init. If so we need to move it out into regular memory. */
-void kdump_move_device_tree(void)
+
+/* Find the device node for a given logical cpu number, also returns the cpu
+ * local thread number (index in ibm,interrupt-server#s) if relevant and
+ * asked for (non NULL)
+ */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
 {
-	unsigned long start, end;
-	struct boot_param_header *new;
+	int hardid;
+	struct device_node *np;
 
-	start = __pa((unsigned long)initial_boot_params);
-	end = start + initial_boot_params->totalsize;
+	hardid = get_hard_smp_processor_id(cpu);
 
-	if (end < crashk_res.start || start > crashk_res.end)
-		return;
+	for_each_node_by_type(np, "cpu") {
+		u32 *intserv;
+		unsigned int plen, t;
 
-	new = (struct boot_param_header*)
-		__va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));
-
-	memcpy(new, initial_boot_params, initial_boot_params->totalsize);
-
-	initial_boot_params = new;
-
-	DBG("Flat device tree blob moved to %p\n", initial_boot_params);
-
-	/* XXX should we unreserve the old DT? */
+		/* Check for ibm,ppc-interrupt-server#s. If it doesn't exist
+		 * fallback to "reg" property and assume no threads
+		 */
+		intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s",
+					      &plen);
+		if (intserv == NULL) {
+			u32 *reg = (u32 *)get_property(np, "reg", NULL);
+			if (reg == NULL)
+				continue;
+			if (*reg == hardid) {
+				if (thread)
+					*thread = 0;
+				return np;
+			}
+		} else {
+			plen /= sizeof(u32);
+			for (t = 0; t < plen; t++) {
+				if (hardid == intserv[t]) {
+					if (thread)
+						*thread = t;
+					return np;
+				}
+			}
+		}
+	}
+	return NULL;
 }
-#endif /* CONFIG_KEXEC */
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index f70bd09..8c28eb0 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -194,19 +194,12 @@
 
 static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
 
-static unsigned long __initdata prom_memory_limit;
-
 static unsigned long __initdata alloc_top;
 static unsigned long __initdata alloc_top_high;
 static unsigned long __initdata alloc_bottom;
 static unsigned long __initdata rmo_top;
 static unsigned long __initdata ram_top;
 
-#ifdef CONFIG_KEXEC
-static unsigned long __initdata prom_crashk_base;
-static unsigned long __initdata prom_crashk_size;
-#endif
-
 static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
 static int __initdata mem_reserve_cnt;
 
@@ -574,7 +567,7 @@
 	if ((long)_prom->chosen > 0)
 		l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
 #ifdef CONFIG_CMDLINE
-	if (l == 0) /* dbl check */
+	if (l <= 0 || p[0] == '\0') /* dbl check */
 		strlcpy(RELOC(prom_cmd_line),
 			RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
 #endif /* CONFIG_CMDLINE */
@@ -593,45 +586,6 @@
 			RELOC(iommu_force_on) = 1;
 	}
 #endif
-
-	opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
-	if (opt) {
-		opt += 4;
-		RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
-#ifdef CONFIG_PPC64
-		/* Align to 16 MB == size of ppc64 large page */
-		RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
-#endif
-	}
-
-#ifdef CONFIG_KEXEC
-	/*
-	 * crashkernel=size@addr specifies the location to reserve for
-	 * crash kernel.
-	 */
-	opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel="));
-	if (opt) {
-		opt += 12;
-		RELOC(prom_crashk_size) = 
-			prom_memparse(opt, (const char **)&opt);
-
-		if (ALIGN(RELOC(prom_crashk_size), 0x1000000) !=
-			RELOC(prom_crashk_size)) {
-			prom_printf("Warning: crashkernel size is not "
-					"aligned to 16MB\n");
-		}
-
-		/*
-		 * At present, the crash kernel always run at 32MB.
-		 * Just ignore whatever user passed.
-		 */
-		RELOC(prom_crashk_base) = 0x2000000;
-		if (*opt == '@') {
-			prom_printf("Warning: PPC64 kdump kernel always runs "
-					"at 32 MB\n");
-		}
-	}
-#endif
 }
 
 #ifdef CONFIG_PPC_PSERIES
@@ -1116,29 +1070,6 @@
 	}
 
 	/*
-	 * If prom_memory_limit is set we reduce the upper limits *except* for
-	 * alloc_top_high. This must be the real top of RAM so we can put
-	 * TCE's up there.
-	 */
-
-	RELOC(alloc_top_high) = RELOC(ram_top);
-
-	if (RELOC(prom_memory_limit)) {
-		if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
-			prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
-				RELOC(prom_memory_limit));
-			RELOC(prom_memory_limit) = 0;
-		} else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
-			prom_printf("Ignoring mem=%x >= ram_top.\n",
-				RELOC(prom_memory_limit));
-			RELOC(prom_memory_limit) = 0;
-		} else {
-			RELOC(ram_top) = RELOC(prom_memory_limit);
-			RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
-		}
-	}
-
-	/*
 	 * Setup our top alloc point, that is top of RMO or top of
 	 * segment 0 when running non-LPAR.
 	 * Some RS64 machines have buggy firmware where claims up at
@@ -1150,20 +1081,14 @@
 		RELOC(rmo_top) = RELOC(ram_top);
 	RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top));
 	RELOC(alloc_top) = RELOC(rmo_top);
+	RELOC(alloc_top_high) = RELOC(ram_top);
 
 	prom_printf("memory layout at init:\n");
-	prom_printf("  memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
 	prom_printf("  alloc_bottom : %x\n", RELOC(alloc_bottom));
 	prom_printf("  alloc_top    : %x\n", RELOC(alloc_top));
 	prom_printf("  alloc_top_hi : %x\n", RELOC(alloc_top_high));
 	prom_printf("  rmo_top      : %x\n", RELOC(rmo_top));
 	prom_printf("  ram_top      : %x\n", RELOC(ram_top));
-#ifdef CONFIG_KEXEC
-	if (RELOC(prom_crashk_base)) {
-		prom_printf("  crashk_base  : %x\n",  RELOC(prom_crashk_base));
-		prom_printf("  crashk_size  : %x\n", RELOC(prom_crashk_size));
-	}
-#endif
 }
 
 
@@ -1349,16 +1274,10 @@
 
 	reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
 
-	if (RELOC(prom_memory_limit)) {
-		/*
-		 * We align the start to a 16MB boundary so we can map
-		 * the TCE area using large pages if possible.
-		 * The end should be the top of RAM so no need to align it.
-		 */
-		RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom,
-							  0x1000000);
-		RELOC(prom_tce_alloc_end) = local_alloc_top;
-	}
+	/* These are only really needed if there is a memory limit in
+	 * effect, but we don't know so export them always. */
+	RELOC(prom_tce_alloc_start) = local_alloc_bottom;
+	RELOC(prom_tce_alloc_end) = local_alloc_top;
 
 	/* Flag the first invalid entry */
 	prom_debug("ending prom_initialize_tce_table\n");
@@ -2041,11 +1960,7 @@
 	/* Version 16 is not backward compatible */
 	hdr->last_comp_version = 0x10;
 
-	/* Reserve the whole thing and copy the reserve map in, we
-	 * also bump mem_reserve_cnt to cause further reservations to
-	 * fail since it's too late.
-	 */
-	reserve_mem(RELOC(dt_header_start), hdr->totalsize);
+	/* Copy the reserve map in */
 	memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
 
 #ifdef DEBUG_PROM
@@ -2058,6 +1973,9 @@
 				    RELOC(mem_reserve_map)[i].size);
 	}
 #endif
+	/* Bump mem_reserve_cnt to cause further reservations to fail
+	 * since it's too late.
+	 */
 	RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
 
 	prom_printf("Device tree strings 0x%x -> 0x%x\n",
@@ -2280,10 +2198,6 @@
 	 */
 	prom_init_mem();
 
-#ifdef CONFIG_KEXEC
-	if (RELOC(prom_crashk_base))
-		reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size));
-#endif
 	/*
 	 * Determine which cpu is actually running right _now_
 	 */
@@ -2317,10 +2231,6 @@
 	/*
 	 * Fill in some infos for use by the kernel later on
 	 */
-	if (RELOC(prom_memory_limit))
-		prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
-			     &RELOC(prom_memory_limit),
-			     sizeof(prom_memory_limit));
 #ifdef CONFIG_PPC64
 	if (RELOC(ppc64_iommu_off))
 		prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
@@ -2340,16 +2250,6 @@
 	}
 #endif
 
-#ifdef CONFIG_KEXEC
-	if (RELOC(prom_crashk_base)) {
-		prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base",
-			PTRRELOC(&prom_crashk_base),
-			sizeof(RELOC(prom_crashk_base)));
-		prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size",
-			PTRRELOC(&prom_crashk_size),
-			sizeof(RELOC(prom_crashk_size)));
-	}
-#endif
 	/*
 	 * Fixup any known bugs in the device-tree
 	 */
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c
index 3934c22..45df420 100644
--- a/arch/powerpc/kernel/prom_parse.c
+++ b/arch/powerpc/kernel/prom_parse.c
@@ -548,3 +548,28 @@
 	return __of_address_to_resource(dev, addrp, size, flags, r);
 }
 EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop,
+		unsigned long *busno, unsigned long *phys, unsigned long *size)
+{
+	u32 *dma_window, cells;
+	unsigned char *prop;
+
+	dma_window = (u32 *)dma_window_prop;
+
+	/* busno is always one cell */
+	*busno = *(dma_window++);
+
+	prop = get_property(dn, "ibm,#dma-address-cells", NULL);
+	if (!prop)
+		prop = get_property(dn, "#address-cells", NULL);
+
+	cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn);
+	*phys = of_read_addr(dma_window, cells);
+
+	dma_window += cells;
+
+	prop = get_property(dn, "ibm,#dma-size-cells", NULL);
+	cells = prop ? *(u32 *)prop : prom_n_size_cells(dn);
+	*size = of_read_addr(dma_window, cells);
+}
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 4a677d1..5563e2e 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -404,7 +404,6 @@
 		ret = ptrace_detach(child, data);
 		break;
 
-#ifdef CONFIG_PPC64
 	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
 		int i;
 		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
@@ -468,7 +467,6 @@
 		}
 		break;
 	}
-#endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_ALTIVEC
 	case PTRACE_GETVRREGS:
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c
index 34d073fb..77578c0 100644
--- a/arch/powerpc/kernel/rtas-rtc.c
+++ b/arch/powerpc/kernel/rtas-rtc.c
@@ -14,19 +14,20 @@
 unsigned long __init rtas_get_boot_time(void)
 {
 	int ret[8];
-	int error, wait_time;
+	int error;
+	unsigned int wait_time;
 	u64 max_wait_tb;
 
 	max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
 	do {
 		error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
-		if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
-			wait_time = rtas_extended_busy_delay_time(error);
+
+		wait_time = rtas_busy_delay_time(error);
+		if (wait_time) {
 			/* This is boot time so we spin. */
 			udelay(wait_time*1000);
-			error = RTAS_CLOCK_BUSY;
 		}
-	} while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+	} while (wait_time && (get_tb() < max_wait_tb));
 
 	if (error != 0 && printk_ratelimit()) {
 		printk(KERN_WARNING "error: reading the clock failed (%d)\n",
@@ -44,24 +45,25 @@
 void rtas_get_rtc_time(struct rtc_time *rtc_tm)
 {
         int ret[8];
-	int error, wait_time;
+	int error;
+	unsigned int wait_time;
 	u64 max_wait_tb;
 
 	max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
 	do {
 		error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);
-		if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
+
+		wait_time = rtas_busy_delay_time(error);
+		if (wait_time) {
 			if (in_interrupt() && printk_ratelimit()) {
 				memset(rtc_tm, 0, sizeof(struct rtc_time));
 				printk(KERN_WARNING "error: reading clock"
 				       " would delay interrupt\n");
 				return;	/* delay not allowed */
 			}
-			wait_time = rtas_extended_busy_delay_time(error);
 			msleep(wait_time);
-			error = RTAS_CLOCK_BUSY;
 		}
-	} while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+	} while (wait_time && (get_tb() < max_wait_tb));
 
         if (error != 0 && printk_ratelimit()) {
                 printk(KERN_WARNING "error: reading the clock failed (%d)\n",
@@ -88,14 +90,14 @@
 				  tm->tm_year + 1900, tm->tm_mon + 1,
 				  tm->tm_mday, tm->tm_hour, tm->tm_min,
 				  tm->tm_sec, 0);
-		if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) {
+
+		wait_time = rtas_busy_delay_time(error);
+		if (wait_time) {
 			if (in_interrupt())
 				return 1;	/* probably decrementer */
-			wait_time = rtas_extended_busy_delay_time(error);
 			msleep(wait_time);
-			error = RTAS_CLOCK_BUSY;
 		}
-	} while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb));
+	} while (wait_time && (get_tb() < max_wait_tb));
 
         if (error != 0 && printk_ratelimit())
                 printk(KERN_WARNING "error: setting the clock failed (%d)\n",
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 0112318..17dc791 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -370,24 +370,36 @@
 	return ret;
 }
 
-/* Given an RTAS status code of 990n compute the hinted delay of 10^n
- * (last digit) milliseconds.  For now we bound at n=5 (100 sec).
+/* For RTAS_BUSY (-2), delay for 1 millisecond.  For an extended busy status
+ * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
  */
-unsigned int rtas_extended_busy_delay_time(int status)
+unsigned int rtas_busy_delay_time(int status)
 {
-	int order = status - 9900;
-	unsigned long ms;
+	int order;
+	unsigned int ms = 0;
 
-	if (order < 0)
-		order = 0;	/* RTC depends on this for -2 clock busy */
-	else if (order > 5)
-		order = 5;	/* bound */
+	if (status == RTAS_BUSY) {
+		ms = 1;
+	} else if (status >= 9900 && status <= 9905) {
+		order = status - 9900;
+		for (ms = 1; order > 0; order--)
+			ms *= 10;
+	}
 
-	/* Use microseconds for reasonable accuracy */
-	for (ms = 1; order > 0; order--)
-		ms *= 10;
+	return ms;
+}
 
-	return ms; 
+/* For an RTAS busy status code, perform the hinted delay. */
+unsigned int rtas_busy_delay(int status)
+{
+	unsigned int ms;
+
+	might_sleep();
+	ms = rtas_busy_delay_time(status);
+	if (ms)
+		msleep(ms);
+
+	return ms;
 }
 
 int rtas_error_rc(int rtas_rc)
@@ -438,22 +450,14 @@
 int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 {
 	int token = rtas_token("set-power-level");
-	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
 		return -ENOENT;
 
-	while (1) {
+	do {
 		rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
-		if (rc == RTAS_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	if (rc < 0)
 		return rtas_error_rc(rc);
@@ -463,22 +467,14 @@
 int rtas_get_sensor(int sensor, int index, int *state)
 {
 	int token = rtas_token("get-sensor-state");
-	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
 		return -ENOENT;
 
-	while (1) {
+	do {
 		rc = rtas_call(token, 2, 2, state, sensor, index);
-		if (rc == RTAS_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	if (rc < 0)
 		return rtas_error_rc(rc);
@@ -488,23 +484,14 @@
 int rtas_set_indicator(int indicator, int index, int new_value)
 {
 	int token = rtas_token("set-indicator");
-	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
 		return -ENOENT;
 
-	while (1) {
+	do {
 		rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
-		if (rc == RTAS_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		}
-		else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	if (rc < 0)
 		return rtas_error_rc(rc);
@@ -555,13 +542,11 @@
 	do {
 		status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
 				   __pa(rtas_os_term_buf));
+	} while (rtas_busy_delay(status));
 
-		if (status == RTAS_BUSY)
-			udelay(1);
-		else if (status != 0)
-			printk(KERN_EMERG "ibm,os-term call failed %d\n",
+	if (status != 0)
+		printk(KERN_EMERG "ibm,os-term call failed %d\n",
 			       status);
-	} while (status == RTAS_BUSY);
 }
 
 static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
@@ -608,9 +593,31 @@
 static int rtas_ibm_suspend_me(struct rtas_args *args)
 {
 	int i;
+	long state;
+	long rc;
+	unsigned long dummy;
 
 	struct rtas_suspend_me_data data;
 
+	/* Make sure the state is valid */
+	rc = plpar_hcall(H_VASI_STATE,
+			 ((u64)args->args[0] << 32) | args->args[1],
+			 0, 0, 0,
+			 &state, &dummy, &dummy);
+
+	if (rc) {
+		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc);
+		return rc;
+	} else if (state == H_VASI_ENABLED) {
+		args->args[args->nargs] = RTAS_NOT_SUSPENDABLE;
+		return 0;
+	} else if (state != H_VASI_SUSPENDING) {
+		printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n",
+		       state);
+		args->args[args->nargs] = -1;
+		return 0;
+	}
+
 	data.waiting = 1;
 	data.args = args;
 
@@ -789,7 +796,8 @@
 EXPORT_SYMBOL(rtas_call);
 EXPORT_SYMBOL(rtas_data_buf);
 EXPORT_SYMBOL(rtas_data_buf_lock);
-EXPORT_SYMBOL(rtas_extended_busy_delay_time);
+EXPORT_SYMBOL(rtas_busy_delay_time);
+EXPORT_SYMBOL(rtas_busy_delay);
 EXPORT_SYMBOL(rtas_get_sensor);
 EXPORT_SYMBOL(rtas_get_power_level);
 EXPORT_SYMBOL(rtas_set_power_level);
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c
index aaf384c..1442b63 100644
--- a/arch/powerpc/kernel/rtas_flash.c
+++ b/arch/powerpc/kernel/rtas_flash.c
@@ -365,20 +365,12 @@
 
 static void manage_flash(struct rtas_manage_flash_t *args_buf)
 {
-	unsigned int wait_time;
 	s32 rc;
 
-	while (1) {
+	do {
 		rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, 
 			       1, NULL, args_buf->op);
-		if (rc == RTAS_RC_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	args_buf->status = rc;
 }
@@ -451,27 +443,18 @@
 static void validate_flash(struct rtas_validate_flash_t *args_buf)
 {
 	int token = rtas_token("ibm,validate-flash-image");
-	unsigned int wait_time;
 	int update_results;
 	s32 rc;	
 
 	rc = 0;
-	while(1) {
+	do {
 		spin_lock(&rtas_data_buf_lock);
 		memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE);
 		rc = rtas_call(token, 2, 2, &update_results, 
 			       (u32) __pa(rtas_data_buf), args_buf->buf_size);
 		memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE);
 		spin_unlock(&rtas_data_buf_lock);
-			
-		if (rc == RTAS_RC_BUSY)
-			udelay(1);
-		else if (rtas_is_extended_busy(rc)) {
-			wait_time = rtas_extended_busy_delay_time(rc);
-			udelay(wait_time * 1000);
-		} else
-			break;
-	}
+	} while (rtas_busy_delay(rc));
 
 	args_buf->status = rc;
 	args_buf->update_results = update_results;
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c
index 57b539a..6eb7e49 100644
--- a/arch/powerpc/kernel/rtas_pci.c
+++ b/arch/powerpc/kernel/rtas_pci.c
@@ -313,7 +313,9 @@
 	for (node = of_get_next_child(root, NULL);
 	     node != NULL;
 	     node = of_get_next_child(root, node)) {
-		if (node->type == NULL || strcmp(node->type, "pci") != 0)
+
+		if (node->type == NULL || (strcmp(node->type, "pci") != 0 &&
+					   strcmp(node->type, "pciex") != 0))
 			continue;
 
 		phb = pcibios_alloc_controller(node);
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 684ab1d..bd32812 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -443,6 +443,7 @@
 }
 #endif /* CONFIG_SMP */
 
+int __initdata do_early_xmon;
 #ifdef CONFIG_XMON
 static int __init early_xmon(char *p)
 {
@@ -456,7 +457,7 @@
 			return 0;
 	}
 	xmon_init(1);
-	debugger(NULL);
+	do_early_xmon = 1;
 
 	return 0;
 }
@@ -524,3 +525,20 @@
 	return ppc_md.check_legacy_ioport(base_port);
 }
 EXPORT_SYMBOL(check_legacy_ioport);
+
+static int ppc_panic_event(struct notifier_block *this,
+                             unsigned long event, void *ptr)
+{
+	ppc_md.panic(ptr);  /* May not return */
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ppc_panic_block = {
+	.notifier_call = ppc_panic_event,
+	.priority = INT_MIN /* may not return; must be done last */
+};
+
+void __init setup_panic(void)
+{
+	atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
+}
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h
index 2ebba75..4c67ad7 100644
--- a/arch/powerpc/kernel/setup.h
+++ b/arch/powerpc/kernel/setup.h
@@ -2,5 +2,8 @@
 #define _POWERPC_KERNEL_SETUP_H
 
 void check_for_initrd(void);
+void do_init_bootmem(void);
+void setup_panic(void);
+extern int do_early_xmon;
 
 #endif /* _POWERPC_KERNEL_SETUP_H */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 69ac257..0932a62 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -131,12 +131,6 @@
 	/* Do some early initialization based on the flat device tree */
 	early_init_devtree(__va(dt_ptr));
 
-	/* Check default command line */
-#ifdef CONFIG_CMDLINE
-	if (cmd_line[0] == 0)
-		strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
-#endif /* CONFIG_CMDLINE */
-
 	probe_machine();
 
 #ifdef CONFIG_6xx
@@ -221,7 +215,7 @@
 
 	/* register CPU devices */
 	for_each_possible_cpu(i)
-		register_cpu(&cpu_devices[i], i, NULL);
+		register_cpu(&cpu_devices[i], i);
 
 	/* call platform init */
 	if (ppc_md.init != NULL) {
@@ -235,7 +229,7 @@
 /* Warning, IO base is not yet inited */
 void __init setup_arch(char **cmdline_p)
 {
-	extern void do_init_bootmem(void);
+	*cmdline_p = cmd_line;
 
 	/* so udelay does something sensible, assume <= 1000 bogomips */
 	loops_per_jiffy = 500000000 / HZ;
@@ -285,16 +279,16 @@
 	/* reboot on panic */
 	panic_timeout = 180;
 
+	if (ppc_md.panic)
+		setup_panic();
+
 	init_mm.start_code = PAGE_OFFSET;
 	init_mm.end_code = (unsigned long) _etext;
 	init_mm.end_data = (unsigned long) _edata;
 	init_mm.brk = klimit;
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-	*cmdline_p = cmd_line;
-
-	parse_early_param();
+	if (do_early_xmon)
+		debugger(NULL);
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 4467c49..78f3a5f 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -100,12 +100,6 @@
 #endif /* CONFIG_MAGIC_SYSRQ */
 
 
-static int ppc64_panic_event(struct notifier_block *, unsigned long, void *);
-static struct notifier_block ppc64_panic_block = {
-	.notifier_call = ppc64_panic_event,
-	.priority = INT_MIN /* may not return; must be done last */
-};
-
 #ifdef CONFIG_SMP
 
 static int smt_enabled_cmdline;
@@ -199,9 +193,7 @@
 	/* Probe the machine type */
 	probe_machine();
 
-#ifdef CONFIG_CRASH_DUMP
-	kdump_setup();
-#endif
+	setup_kdump_trampoline();
 
 	DBG("Found, Initializing memory management...\n");
 
@@ -353,9 +345,6 @@
 {
 	DBG(" -> setup_system()\n");
 
-#ifdef CONFIG_KEXEC
-	kdump_move_device_tree();
-#endif
 	/*
 	 * Unflatten the device-tree passed by prom_init or kexec
 	 */
@@ -420,10 +409,8 @@
 	 */
 	register_early_udbg_console();
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
-	parse_early_param();
+	if (do_early_xmon)
+		debugger(NULL);
 
 	check_smt_enabled();
 	smp_setup_cpu_maps();
@@ -456,13 +443,6 @@
 	DBG(" <- setup_system()\n");
 }
 
-static int ppc64_panic_event(struct notifier_block *this,
-                             unsigned long event, void *ptr)
-{
-	ppc_md.panic((char *)ptr);  /* May not return */
-	return NOTIFY_DONE;
-}
-
 #ifdef CONFIG_IRQSTACKS
 static void __init irqstack_early_init(void)
 {
@@ -517,8 +497,6 @@
  */
 void __init setup_arch(char **cmdline_p)
 {
-	extern void do_init_bootmem(void);
-
 	ppc64_boot_msg(0x12, "Setup Arch");
 
 	*cmdline_p = cmd_line;
@@ -535,8 +513,7 @@
 	panic_timeout = 180;
 
 	if (ppc_md.panic)
-		atomic_notifier_chain_register(&panic_notifier_list,
-				&ppc64_panic_block);
+		setup_panic();
 
 	init_mm.start_code = PAGE_OFFSET;
 	init_mm.end_code = (unsigned long) _etext;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 8fdeca2..d73b25e 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -419,9 +419,7 @@
 {
 	long err;
 	unsigned int save_r2 = 0;
-#if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE)
 	unsigned long msr;
-#endif
 
 	/*
 	 * restore general registers but not including MSR or SOFTE. Also
@@ -430,11 +428,16 @@
 	if (!sig)
 		save_r2 = (unsigned int)regs->gpr[2];
 	err = restore_general_regs(regs, sr);
+	err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
 	if (!sig)
 		regs->gpr[2] = (unsigned long) save_r2;
 	if (err)
 		return 1;
 
+	/* if doing signal return, restore the previous little-endian mode */
+	if (sig)
+		regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
 	/*
 	 * Do this before updating the thread state in
 	 * current->thread.fpr/vr/evr.  That way, if we get preempted
@@ -455,7 +458,7 @@
 	/* force the process to reload the altivec registers from
 	   current->thread when it next does altivec instructions */
 	regs->msr &= ~MSR_VEC;
-	if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) {
+	if (msr & MSR_VEC) {
 		/* restore altivec registers from the stack */
 		if (__copy_from_user(current->thread.vr, &sr->mc_vregs,
 				     sizeof(sr->mc_vregs)))
@@ -472,7 +475,7 @@
 	/* force the process to reload the spe registers from
 	   current->thread when it next does spe instructions */
 	regs->msr &= ~MSR_SPE;
-	if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) {
+	if (msr & MSR_SPE) {
 		/* restore spe registers from the stack */
 		if (__copy_from_user(current->thread.evr, &sr->mc_vregs,
 				     ELF_NEVRREG * sizeof(u32)))
@@ -757,10 +760,10 @@
 
 	/* Save user registers on the stack */
 	frame = &rt_sf->uc.uc_mcontext;
-	if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+	if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
 		if (save_user_regs(regs, frame, 0))
 			goto badframe;
-		regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+		regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp;
 	} else {
 		if (save_user_regs(regs, frame, __NR_rt_sigreturn))
 			goto badframe;
@@ -777,6 +780,8 @@
 	regs->gpr[5] = (unsigned long) &rt_sf->uc;
 	regs->gpr[6] = (unsigned long) rt_sf;
 	regs->nip = (unsigned long) ka->sa.sa_handler;
+	/* enter the signal handler in big-endian mode */
+	regs->msr &= ~MSR_LE;
 	regs->trap = 0;
 	return 1;
 
@@ -1038,10 +1043,10 @@
 	    || __put_user(sig, &sc->signal))
 		goto badframe;
 
-	if (vdso32_sigtramp && current->thread.vdso_base) {
+	if (vdso32_sigtramp && current->mm->context.vdso_base) {
 		if (save_user_regs(regs, &frame->mctx, 0))
 			goto badframe;
-		regs->link = current->thread.vdso_base + vdso32_sigtramp;
+		regs->link = current->mm->context.vdso_base + vdso32_sigtramp;
 	} else {
 		if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
 			goto badframe;
@@ -1056,6 +1061,8 @@
 	regs->gpr[3] = sig;
 	regs->gpr[4] = (unsigned long) sc;
 	regs->nip = (unsigned long) ka->sa.sa_handler;
+	/* enter the signal handler in big-endian mode */
+	regs->msr &= ~MSR_LE;
 	regs->trap = 0;
 
 	return 1;
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index c2db642..6e75d7a 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -141,9 +141,7 @@
 	unsigned long err = 0;
 	unsigned long save_r13 = 0;
 	elf_greg_t *gregs = (elf_greg_t *)regs;
-#ifdef CONFIG_ALTIVEC
 	unsigned long msr;
-#endif
 	int i;
 
 	/* If this is not a signal return, we preserve the TLS in r13 */
@@ -154,7 +152,12 @@
 	err |= __copy_from_user(regs, &sc->gp_regs,
 				PT_MSR*sizeof(unsigned long));
 
-	/* skip MSR and SOFTE */
+	/* get MSR separately, transfer the LE bit if doing signal return */
+	err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
+	if (sig)
+		regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE);
+
+	/* skip SOFTE */
 	for (i = PT_MSR+1; i <= PT_RESULT; i++) {
 		if (i == PT_SOFTE)
 			continue;
@@ -179,7 +182,6 @@
 
 #ifdef CONFIG_ALTIVEC
 	err |= __get_user(v_regs, &sc->v_regs);
-	err |= __get_user(msr, &sc->gp_regs[PT_MSR]);
 	if (err)
 		return err;
 	if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128)))
@@ -396,8 +398,8 @@
 	current->thread.fpscr.val = 0;
 
 	/* Set up to return from userspace. */
-	if (vdso64_rt_sigtramp && current->thread.vdso_base) {
-		regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;
+	if (vdso64_rt_sigtramp && current->mm->context.vdso_base) {
+		regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp;
 	} else {
 		err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
 		if (err)
@@ -412,6 +414,8 @@
 
 	/* Set up "regs" so we "return" to the signal handler. */
 	err |= get_user(regs->nip, &funct_desc_ptr->entry);
+	/* enter the signal handler in big-endian mode */
+	regs->msr &= ~MSR_LE;
 	regs->gpr[1] = newsp;
 	err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
 	regs->gpr[3] = signr;
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 530f7db..c5d179d 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -492,7 +492,7 @@
 	 * -- Cort
 	 */
 	if (system_state < SYSTEM_RUNNING)
-		for (c = 5000; c && !cpu_callin_map[cpu]; c--)
+		for (c = 50000; c && !cpu_callin_map[cpu]; c--)
 			udelay(100);
 #ifdef CONFIG_HOTPLUG_CPU
 	else
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 5bc2585..4662b58 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -279,7 +279,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int sysfs_cpu_notify(struct notifier_block *self,
+static int __devinit sysfs_cpu_notify(struct notifier_block *self,
 				      unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned int)(long)hcpu;
@@ -297,30 +297,19 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block sysfs_cpu_nb = {
+static struct notifier_block __devinitdata sysfs_cpu_nb = {
 	.notifier_call	= sysfs_cpu_notify,
 };
 
 /* NUMA stuff */
 
 #ifdef CONFIG_NUMA
-static struct node node_devices[MAX_NUMNODES];
-
 static void register_nodes(void)
 {
 	int i;
 
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		if (node_online(i)) {
-			int p_node = parent_node(i);
-			struct node *parent = NULL;
-
-			if (p_node != i)
-				parent = &node_devices[p_node];
-
-			register_node(&node_devices[i], i, parent);
-		}
-	}
+	for (i = 0; i < MAX_NUMNODES; i++)
+		register_one_node(i);
 }
 
 int sysfs_add_device_to_node(struct sys_device *dev, int nid)
@@ -359,23 +348,13 @@
 static int __init topology_init(void)
 {
 	int cpu;
-	struct node *parent = NULL;
 
 	register_nodes();
-
 	register_cpu_notifier(&sysfs_cpu_nb);
 
 	for_each_possible_cpu(cpu) {
 		struct cpu *c = &per_cpu(cpu_devices, cpu);
 
-#ifdef CONFIG_NUMA
-		/* The node to which a cpu belongs can't be known
-		 * until the cpu is made present.
-		 */
-		parent = NULL;
-		if (cpu_present(cpu))
-			parent = &node_devices[cpu_to_node(cpu)];
-#endif
 		/*
 		 * For now, we just see if the system supports making
 		 * the RTAS calls for CPU hotplug.  But, there may be a
@@ -387,7 +366,7 @@
 			c->no_control = 1;
 
 		if (cpu_online(cpu) || (c->no_control == 0)) {
-			register_cpu(c, cpu, parent);
+			register_cpu(c, cpu);
 
 			sysdev_create_file(&c->sysdev, &attr_physical_id);
 		}
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S
index 26ed1f5..ee75ccf 100644
--- a/arch/powerpc/kernel/systbl.S
+++ b/arch/powerpc/kernel/systbl.S
@@ -32,6 +32,10 @@
 #define SYS32ONLY(func)		.long	sys_##func
 #define SYSX(f, f3264, f32)	.long	f32
 #endif
+#define SYSCALL_SPU(func)	SYSCALL(func)
+#define COMPAT_SYS_SPU(func)	COMPAT_SYS(func)
+#define PPC_SYS_SPU(func)	PPC_SYS(func)
+#define SYSX_SPU(f, f3264, f32)	SYSX(f, f3264, f32)
 
 #ifdef CONFIG_PPC64
 #define sys_sigpending	sys_ni_syscall
@@ -39,309 +43,4 @@
 #endif
 
 _GLOBAL(sys_call_table)
-SYSCALL(restart_syscall)
-SYSCALL(exit)
-PPC_SYS(fork)
-SYSCALL(read)
-SYSCALL(write)
-COMPAT_SYS(open)
-SYSCALL(close)
-COMPAT_SYS(waitpid)
-COMPAT_SYS(creat)
-SYSCALL(link)
-SYSCALL(unlink)
-COMPAT_SYS(execve)
-SYSCALL(chdir)
-COMPAT_SYS(time)
-SYSCALL(mknod)
-SYSCALL(chmod)
-SYSCALL(lchown)
-SYSCALL(ni_syscall)
-OLDSYS(stat)
-SYSX(sys_lseek,ppc32_lseek,sys_lseek)
-SYSCALL(getpid)
-COMPAT_SYS(mount)
-SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount)
-SYSCALL(setuid)
-SYSCALL(getuid)
-COMPAT_SYS(stime)
-COMPAT_SYS(ptrace)
-SYSCALL(alarm)
-OLDSYS(fstat)
-COMPAT_SYS(pause)
-COMPAT_SYS(utime)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(access)
-COMPAT_SYS(nice)
-SYSCALL(ni_syscall)
-SYSCALL(sync)
-COMPAT_SYS(kill)
-SYSCALL(rename)
-COMPAT_SYS(mkdir)
-SYSCALL(rmdir)
-SYSCALL(dup)
-SYSCALL(pipe)
-COMPAT_SYS(times)
-SYSCALL(ni_syscall)
-SYSCALL(brk)
-SYSCALL(setgid)
-SYSCALL(getgid)
-SYSCALL(signal)
-SYSCALL(geteuid)
-SYSCALL(getegid)
-SYSCALL(acct)
-SYSCALL(umount)
-SYSCALL(ni_syscall)
-COMPAT_SYS(ioctl)
-COMPAT_SYS(fcntl)
-SYSCALL(ni_syscall)
-COMPAT_SYS(setpgid)
-SYSCALL(ni_syscall)
-SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
-COMPAT_SYS(umask)
-SYSCALL(chroot)
-SYSCALL(ustat)
-SYSCALL(dup2)
-SYSCALL(getppid)
-SYSCALL(getpgrp)
-SYSCALL(setsid)
-SYS32ONLY(sigaction)
-SYSCALL(sgetmask)
-COMPAT_SYS(ssetmask)
-SYSCALL(setreuid)
-SYSCALL(setregid)
-SYS32ONLY(sigsuspend)
-COMPAT_SYS(sigpending)
-COMPAT_SYS(sethostname)
-COMPAT_SYS(setrlimit)
-COMPAT_SYS(old_getrlimit)
-COMPAT_SYS(getrusage)
-COMPAT_SYS(gettimeofday)
-COMPAT_SYS(settimeofday)
-COMPAT_SYS(getgroups)
-COMPAT_SYS(setgroups)
-SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select)
-SYSCALL(symlink)
-OLDSYS(lstat)
-COMPAT_SYS(readlink)
-SYSCALL(uselib)
-SYSCALL(swapon)
-SYSCALL(reboot)
-SYSX(sys_ni_syscall,old32_readdir,old_readdir)
-SYSCALL(mmap)
-SYSCALL(munmap)
-SYSCALL(truncate)
-SYSCALL(ftruncate)
-SYSCALL(fchmod)
-SYSCALL(fchown)
-COMPAT_SYS(getpriority)
-COMPAT_SYS(setpriority)
-SYSCALL(ni_syscall)
-COMPAT_SYS(statfs)
-COMPAT_SYS(fstatfs)
-SYSCALL(ni_syscall)
-COMPAT_SYS(socketcall)
-COMPAT_SYS(syslog)
-COMPAT_SYS(setitimer)
-COMPAT_SYS(getitimer)
-COMPAT_SYS(newstat)
-COMPAT_SYS(newlstat)
-COMPAT_SYS(newfstat)
-SYSX(sys_ni_syscall,sys_uname,sys_uname)
-SYSCALL(ni_syscall)
-SYSCALL(vhangup)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(wait4)
-SYSCALL(swapoff)
-COMPAT_SYS(sysinfo)
-COMPAT_SYS(ipc)
-SYSCALL(fsync)
-SYS32ONLY(sigreturn)
-PPC_SYS(clone)
-COMPAT_SYS(setdomainname)
-PPC_SYS(newuname)
-SYSCALL(ni_syscall)
-COMPAT_SYS(adjtimex)
-SYSCALL(mprotect)
-SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask)
-SYSCALL(ni_syscall)
-SYSCALL(init_module)
-SYSCALL(delete_module)
-SYSCALL(ni_syscall)
-SYSCALL(quotactl)
-COMPAT_SYS(getpgid)
-SYSCALL(fchdir)
-SYSCALL(bdflush)
-COMPAT_SYS(sysfs)
-SYSX(ppc64_personality,ppc64_personality,sys_personality)
-SYSCALL(ni_syscall)
-SYSCALL(setfsuid)
-SYSCALL(setfsgid)
-SYSCALL(llseek)
-COMPAT_SYS(getdents)
-SYSX(sys_select,ppc32_select,ppc_select)
-SYSCALL(flock)
-SYSCALL(msync)
-COMPAT_SYS(readv)
-COMPAT_SYS(writev)
-COMPAT_SYS(getsid)
-SYSCALL(fdatasync)
-COMPAT_SYS(sysctl)
-SYSCALL(mlock)
-SYSCALL(munlock)
-SYSCALL(mlockall)
-SYSCALL(munlockall)
-COMPAT_SYS(sched_setparam)
-COMPAT_SYS(sched_getparam)
-COMPAT_SYS(sched_setscheduler)
-COMPAT_SYS(sched_getscheduler)
-SYSCALL(sched_yield)
-COMPAT_SYS(sched_get_priority_max)
-COMPAT_SYS(sched_get_priority_min)
-COMPAT_SYS(sched_rr_get_interval)
-COMPAT_SYS(nanosleep)
-SYSCALL(mremap)
-SYSCALL(setresuid)
-SYSCALL(getresuid)
-SYSCALL(ni_syscall)
-SYSCALL(poll)
-COMPAT_SYS(nfsservctl)
-SYSCALL(setresgid)
-SYSCALL(getresgid)
-COMPAT_SYS(prctl)
-COMPAT_SYS(rt_sigreturn)
-COMPAT_SYS(rt_sigaction)
-COMPAT_SYS(rt_sigprocmask)
-COMPAT_SYS(rt_sigpending)
-COMPAT_SYS(rt_sigtimedwait)
-COMPAT_SYS(rt_sigqueueinfo)
-COMPAT_SYS(rt_sigsuspend)
-COMPAT_SYS(pread64)
-COMPAT_SYS(pwrite64)
-SYSCALL(chown)
-SYSCALL(getcwd)
-SYSCALL(capget)
-SYSCALL(capset)
-COMPAT_SYS(sigaltstack)
-SYSX(sys_sendfile64,compat_sys_sendfile,sys_sendfile)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-PPC_SYS(vfork)
-COMPAT_SYS(getrlimit)
-COMPAT_SYS(readahead)
-SYS32ONLY(mmap2)
-SYS32ONLY(truncate64)
-SYS32ONLY(ftruncate64)
-SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
-SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
-SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
-SYSCALL(pciconfig_read)
-SYSCALL(pciconfig_write)
-SYSCALL(pciconfig_iobase)
-SYSCALL(ni_syscall)
-SYSCALL(getdents64)
-SYSCALL(pivot_root)
-SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64)
-SYSCALL(madvise)
-SYSCALL(mincore)
-SYSCALL(gettid)
-SYSCALL(tkill)
-SYSCALL(setxattr)
-SYSCALL(lsetxattr)
-SYSCALL(fsetxattr)
-SYSCALL(getxattr)
-SYSCALL(lgetxattr)
-SYSCALL(fgetxattr)
-SYSCALL(listxattr)
-SYSCALL(llistxattr)
-SYSCALL(flistxattr)
-SYSCALL(removexattr)
-SYSCALL(lremovexattr)
-SYSCALL(fremovexattr)
-COMPAT_SYS(futex)
-COMPAT_SYS(sched_setaffinity)
-COMPAT_SYS(sched_getaffinity)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-SYS32ONLY(sendfile64)
-COMPAT_SYS(io_setup)
-SYSCALL(io_destroy)
-COMPAT_SYS(io_getevents)
-COMPAT_SYS(io_submit)
-SYSCALL(io_cancel)
-SYSCALL(set_tid_address)
-SYSX(sys_fadvise64,ppc32_fadvise64,sys_fadvise64)
-SYSCALL(exit_group)
-SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie)
-SYSCALL(epoll_create)
-SYSCALL(epoll_ctl)
-SYSCALL(epoll_wait)
-SYSCALL(remap_file_pages)
-SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create)
-COMPAT_SYS(timer_settime)
-COMPAT_SYS(timer_gettime)
-SYSCALL(timer_getoverrun)
-SYSCALL(timer_delete)
-COMPAT_SYS(clock_settime)
-COMPAT_SYS(clock_gettime)
-COMPAT_SYS(clock_getres)
-COMPAT_SYS(clock_nanosleep)
-SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
-COMPAT_SYS(tgkill)
-COMPAT_SYS(utimes)
-COMPAT_SYS(statfs64)
-COMPAT_SYS(fstatfs64)
-SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
-PPC_SYS(rtas)
-OLDSYS(debug_setcontext)
-SYSCALL(ni_syscall)
-SYSCALL(ni_syscall)
-COMPAT_SYS(mbind)
-COMPAT_SYS(get_mempolicy)
-COMPAT_SYS(set_mempolicy)
-COMPAT_SYS(mq_open)
-SYSCALL(mq_unlink)
-COMPAT_SYS(mq_timedsend)
-COMPAT_SYS(mq_timedreceive)
-COMPAT_SYS(mq_notify)
-COMPAT_SYS(mq_getsetattr)
-COMPAT_SYS(kexec_load)
-COMPAT_SYS(add_key)
-COMPAT_SYS(request_key)
-COMPAT_SYS(keyctl)
-COMPAT_SYS(waitid)
-COMPAT_SYS(ioprio_set)
-COMPAT_SYS(ioprio_get)
-SYSCALL(inotify_init)
-SYSCALL(inotify_add_watch)
-SYSCALL(inotify_rm_watch)
-SYSCALL(spu_run)
-SYSCALL(spu_create)
-COMPAT_SYS(pselect6)
-COMPAT_SYS(ppoll)
-SYSCALL(unshare)
-SYSCALL(splice)
-SYSCALL(tee)
-SYSCALL(vmsplice)
-COMPAT_SYS(openat)
-SYSCALL(mkdirat)
-SYSCALL(mknodat)
-SYSCALL(fchownat)
-COMPAT_SYS(futimesat)
-SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64)
-SYSCALL(unlinkat)
-SYSCALL(renameat)
-SYSCALL(linkat)
-SYSCALL(symlinkat)
-SYSCALL(readlinkat)
-SYSCALL(fchmodat)
-SYSCALL(faccessat)
-COMPAT_SYS(get_robust_list)
-COMPAT_SYS(set_robust_list)
-
-/*
- * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c
- * as well when appropriate.
- */
+#include <asm/systbl.h>
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 24e3ad7..7dd5dab 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -76,7 +76,6 @@
 
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
-extern int piranha_simulator;
 #ifdef CONFIG_PPC_ISERIES
 unsigned long iSeries_recal_titan = 0;
 unsigned long iSeries_recal_tb = 0; 
@@ -103,7 +102,7 @@
 u64 tb_to_xs;
 unsigned tb_to_us;
 
-#define TICKLEN_SCALE	(SHIFT_SCALE - 10)
+#define TICKLEN_SCALE	TICK_LENGTH_SHIFT
 u64 last_tick_len;	/* units are ns / 2^TICKLEN_SCALE */
 u64 ticklen_to_xs;	/* 0.64 fraction */
 
@@ -858,42 +857,50 @@
 
 EXPORT_SYMBOL(do_settimeofday);
 
-void __init generic_calibrate_decr(void)
+static int __init get_freq(char *name, int cells, unsigned long *val)
 {
 	struct device_node *cpu;
 	unsigned int *fp;
-	int node_found;
+	int found = 0;
 
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
+	/* The cpu node should have timebase and clock frequency properties */
 	cpu = of_find_node_by_type(NULL, "cpu");
 
-	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
-	node_found = 0;
 	if (cpu) {
-		fp = (unsigned int *)get_property(cpu, "timebase-frequency",
-						  NULL);
+		fp = (unsigned int *)get_property(cpu, name, NULL);
 		if (fp) {
-			node_found = 1;
-			ppc_tb_freq = *fp;
+			found = 1;
+			*val = 0;
+			while (cells--)
+				*val = (*val << 32) | *fp++;
 		}
+
+		of_node_put(cpu);
 	}
-	if (!node_found)
+
+	return found;
+}
+
+void __init generic_calibrate_decr(void)
+{
+	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
+
+	if (!get_freq("ibm,extended-timebase-frequency", 2, &ppc_tb_freq) &&
+	    !get_freq("timebase-frequency", 1, &ppc_tb_freq)) {
+
 		printk(KERN_ERR "WARNING: Estimating decrementer frequency "
 				"(not found)\n");
-
-	ppc_proc_freq = DEFAULT_PROC_FREQ;
-	node_found = 0;
-	if (cpu) {
-		fp = (unsigned int *)get_property(cpu, "clock-frequency",
-						  NULL);
-		if (fp) {
-			node_found = 1;
-			ppc_proc_freq = *fp;
-		}
 	}
+
+	ppc_proc_freq = DEFAULT_PROC_FREQ;	/* hardcoded default */
+
+	if (!get_freq("ibm,extended-clock-frequency", 2, &ppc_proc_freq) &&
+	    !get_freq("clock-frequency", 1, &ppc_proc_freq)) {
+
+		printk(KERN_ERR "WARNING: Estimating processor frequency "
+				"(not found)\n");
+	}
+
 #ifdef CONFIG_BOOKE
 	/* Set the time base to zero */
 	mtspr(SPRN_TBWL, 0);
@@ -905,11 +912,6 @@
 	/* Enable decrementer interrupt */
 	mtspr(SPRN_TCR, TCR_DIE);
 #endif
-	if (!node_found)
-		printk(KERN_ERR "WARNING: Estimating processor frequency "
-				"(not found)\n");
-
-	of_node_put(cpu);
 }
 
 unsigned long get_boot_time(void)
@@ -945,9 +947,9 @@
 	} else {
 		/* Normal PowerPC with timebase register */
 		ppc_md.calibrate_decr();
-		printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+		printk(KERN_DEBUG "time_init: decrementer frequency = %lu.%.6lu MHz\n",
 		       ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
-		printk(KERN_INFO "time_init: processor frequency   = %lu.%.6lu MHz\n",
+		printk(KERN_DEBUG "time_init: processor frequency   = %lu.%.6lu MHz\n",
 		       ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
 		tb_last_stamp = tb_last_jiffy = get_tb();
 	}
@@ -1010,10 +1012,7 @@
 	tb_to_ns_scale = scale;
 	tb_to_ns_shift = shift;
 
-#ifdef CONFIG_PPC_ISERIES
-	if (!piranha_simulator)
-#endif
-		tm = get_boot_time();
+	tm = get_boot_time();
 
 	write_seqlock_irqsave(&xtime_lock, flags);
 
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 064a525..52f5659 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
+#include <linux/backlight.h>
 
 #include <asm/kdebug.h>
 #include <asm/pgtable.h>
@@ -105,10 +106,18 @@
 	spin_lock_irq(&die_lock);
 	bust_spinlocks(1);
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (machine_is(powermac)) {
-		set_backlight_enable(1);
-		set_backlight_level(BACKLIGHT_MAX);
+	mutex_lock(&pmac_backlight_mutex);
+	if (machine_is(powermac) && pmac_backlight) {
+		struct backlight_properties *props;
+
+		down(&pmac_backlight->sem);
+		props = pmac_backlight->props;
+		props->brightness = props->max_brightness;
+		props->power = FB_BLANK_UNBLANK;
+		props->update_status(pmac_backlight);
+		up(&pmac_backlight->sem);
 	}
+	mutex_unlock(&pmac_backlight_mutex);
 #endif
 	printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
 #ifdef CONFIG_PREEMPT
@@ -658,7 +667,7 @@
 	u32 instword;
 	u32 rd;
 
-	if (!user_mode(regs))
+	if (!user_mode(regs) || (regs->msr & MSR_LE))
 		return -EINVAL;
 	CHECK_FULL_REGS(regs);
 
@@ -805,9 +814,11 @@
 
 void alignment_exception(struct pt_regs *regs)
 {
-	int fixed;
+	int fixed = 0;
 
-	fixed = fix_alignment(regs);
+	/* we don't implement logging of alignment exceptions */
+	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
+		fixed = fix_alignment(regs);
 
 	if (fixed == 1) {
 		regs->nip += 4;	/* skip over emulated instruction */
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
index 3774e80..67d9fd9 100644
--- a/arch/powerpc/kernel/udbg.c
+++ b/arch/powerpc/kernel/udbg.c
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/console.h>
+#include <linux/init.h>
 #include <asm/processor.h>
 #include <asm/udbg.h>
 
@@ -141,12 +142,14 @@
 
 void __init disable_early_printk(void)
 {
-#if 1
 	if (!early_console_initialized)
 		return;
+	if (strstr(saved_command_line, "udbg-immortal")) {
+		printk(KERN_INFO "early console immortal !\n");
+		return;
+	}
 	unregister_console(&udbg_console);
 	early_console_initialized = 0;
-#endif
 }
 
 /* called by setup_system */
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 573afb6..bc3e15b 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -223,6 +223,7 @@
 	struct vm_area_struct *vma;
 	unsigned long vdso_pages;
 	unsigned long vdso_base;
+	int rc;
 
 #ifdef CONFIG_PPC64
 	if (test_thread_flag(TIF_32BIT)) {
@@ -237,20 +238,13 @@
 	vdso_base = VDSO32_MBASE;
 #endif
 
-	current->thread.vdso_base = 0;
+	current->mm->context.vdso_base = 0;
 
 	/* vDSO has a problem and was disabled, just don't "enable" it for the
 	 * process
 	 */
 	if (vdso_pages == 0)
 		return 0;
-
-	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
-	if (vma == NULL)
-		return -ENOMEM;
-
-	memset(vma, 0, sizeof(*vma));
-
 	/* Add a page to the vdso size for the data page */
 	vdso_pages ++;
 
@@ -259,17 +253,23 @@
 	 * at vdso_base which is the "natural" base for it, but we might fail
 	 * and end up putting it elsewhere.
 	 */
+	down_write(&mm->mmap_sem);
 	vdso_base = get_unmapped_area(NULL, vdso_base,
 				      vdso_pages << PAGE_SHIFT, 0, 0);
-	if (vdso_base & ~PAGE_MASK) {
-		kmem_cache_free(vm_area_cachep, vma);
-		return (int)vdso_base;
+	if (IS_ERR_VALUE(vdso_base)) {
+		rc = vdso_base;
+		goto fail_mmapsem;
 	}
 
-	current->thread.vdso_base = vdso_base;
 
+	/* Allocate a VMA structure and fill it up */
+	vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+	if (vma == NULL) {
+		rc = -ENOMEM;
+		goto fail_mmapsem;
+	}
 	vma->vm_mm = mm;
-	vma->vm_start = current->thread.vdso_base;
+	vma->vm_start = vdso_base;
 	vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT);
 
 	/*
@@ -282,23 +282,38 @@
 	 * It's fine to use that for setting breakpoints in the vDSO code
 	 * pages though
 	 */
-	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+	vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC;
 	vma->vm_flags |= mm->def_flags;
 	vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
 	vma->vm_ops = &vdso_vmops;
 
-	down_write(&mm->mmap_sem);
-	if (insert_vm_struct(mm, vma)) {
-		up_write(&mm->mmap_sem);
-		kmem_cache_free(vm_area_cachep, vma);
-		return -ENOMEM;
-	}
+	/* Insert new VMA */
+	rc = insert_vm_struct(mm, vma);
+	if (rc)
+		goto fail_vma;
+
+	/* Put vDSO base into mm struct and account for memory usage */
+	current->mm->context.vdso_base = vdso_base;
 	mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
 	up_write(&mm->mmap_sem);
-
 	return 0;
+
+ fail_vma:
+	kmem_cache_free(vm_area_cachep, vma);
+ fail_mmapsem:
+	up_write(&mm->mmap_sem);
+	return rc;
 }
 
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base)
+		return "[vdso]";
+	return NULL;
+}
+
+
+
 static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
 				  unsigned long *size)
 {
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S
index 66b3d03..9416b4a 100644
--- a/arch/powerpc/kernel/vector.S
+++ b/arch/powerpc/kernel/vector.S
@@ -53,12 +53,12 @@
 	stfd	fr31,8(r1)
 	LDCONST(fr1, fpzero)
 	mffs	fr31
-	mtfsf	0xff,fr1
+	MTFSF_L(fr1)
 	blr
 
 fpdisable:
 	mtlr	r12
-	mtfsf	0xff,fr31
+	MTFSF_L(fr31)
 	lfd	fr31,8(r1)
 	lfd	fr1,16(r1)
 	lfd	fr0,24(r1)
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 971020c..cdf5867 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -13,27 +13,116 @@
  *      2 of the License, or (at your option) any later version.
  */
 
+#include <linux/types.h>
+#include <linux/device.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <linux/kobject.h>
+
 #include <asm/iommu.h>
 #include <asm/dma.h>
 #include <asm/vio.h>
 #include <asm/prom.h>
+#include <asm/firmware.h>
+#include <asm/tce.h>
+#include <asm/abs_addr.h>
+#include <asm/page.h>
+#include <asm/hvcall.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/iommu.h>
 
-static const struct vio_device_id *vio_match_device(
-		const struct vio_device_id *, const struct vio_dev *);
+extern struct subsystem devices_subsys; /* needed for vio_find_name() */
 
-struct vio_dev vio_bus_device  = { /* fake "parent" device */
+static struct vio_dev vio_bus_device  = { /* fake "parent" device */
 	.name = vio_bus_device.dev.bus_id,
 	.type = "",
 	.dev.bus_id = "vio",
 	.dev.bus = &vio_bus_type,
 };
 
-static struct vio_bus_ops vio_bus_ops;
+#ifdef CONFIG_PPC_ISERIES
+struct device *iSeries_vio_dev = &vio_bus_device.dev;
+EXPORT_SYMBOL(iSeries_vio_dev);
+
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+
+static void __init iommu_vio_init(void)
+{
+	iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
+	veth_iommu_table.it_size /= 2;
+	vio_iommu_table = veth_iommu_table;
+	vio_iommu_table.it_offset += veth_iommu_table.it_size;
+
+	if (!iommu_init_table(&veth_iommu_table, -1))
+		printk("Virtual Bus VETH TCE table failed.\n");
+	if (!iommu_init_table(&vio_iommu_table, -1))
+		printk("Virtual Bus VIO TCE table failed.\n");
+}
+#endif
+
+static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
+{
+#ifdef CONFIG_PPC_ISERIES
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		if (strcmp(dev->type, "network") == 0)
+			return &veth_iommu_table;
+		return &vio_iommu_table;
+	} else
+#endif
+	{
+		unsigned char *dma_window;
+		struct iommu_table *tbl;
+		unsigned long offset, size;
+
+		dma_window = get_property(dev->dev.platform_data,
+				"ibm,my-dma-window", NULL);
+		if (!dma_window)
+			return NULL;
+
+		tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
+
+		of_parse_dma_window(dev->dev.platform_data, dma_window,
+				&tbl->it_index, &offset, &size);
+
+		/* TCE table size - measured in tce entries */
+		tbl->it_size = size >> PAGE_SHIFT;
+		/* offset for VIO should always be 0 */
+		tbl->it_offset = offset >> PAGE_SHIFT;
+		tbl->it_busno = 0;
+		tbl->it_type = TCE_VB;
+
+		return iommu_init_table(tbl, -1);
+	}
+}
+
+/**
+ * vio_match_device: - Tell if a VIO device has a matching
+ *			VIO device id structure.
+ * @ids:	array of VIO device id structures to search in
+ * @dev:	the VIO device structure to match against
+ *
+ * Used by a driver to check whether a VIO device present in the
+ * system is in its list of supported devices. Returns the matching
+ * vio_device_id structure or NULL if there is no match.
+ */
+static const struct vio_device_id *vio_match_device(
+		const struct vio_device_id *ids, const struct vio_dev *dev)
+{
+	while (ids->type[0] != '\0') {
+		if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) &&
+		    device_is_compatible(dev->dev.platform_data, ids->compat))
+			return ids;
+		ids++;
+	}
+	return NULL;
+}
 
 /*
  * Convert from struct device to struct vio_dev and pass to driver.
@@ -106,35 +195,110 @@
 }
 EXPORT_SYMBOL(vio_unregister_driver);
 
-/**
- * vio_match_device: - Tell if a VIO device has a matching
- *			VIO device id structure.
- * @ids:	array of VIO device id structures to search in
- * @dev:	the VIO device structure to match against
- *
- * Used by a driver to check whether a VIO device present in the
- * system is in its list of supported devices. Returns the matching
- * vio_device_id structure or NULL if there is no match.
- */
-static const struct vio_device_id *vio_match_device(
-		const struct vio_device_id *ids, const struct vio_dev *dev)
+/* vio_dev refcount hit 0 */
+static void __devinit vio_dev_release(struct device *dev)
 {
-	while (ids->type[0] != '\0') {
-		if (vio_bus_ops.match(ids, dev))
-			return ids;
-		ids++;
+	if (dev->platform_data) {
+		/* XXX free TCE table */
+		of_node_put(dev->platform_data);
 	}
-	return NULL;
+	kfree(to_vio_dev(dev));
 }
 
 /**
+ * vio_register_device_node: - Register a new vio device.
+ * @of_node:	The OF node for this device.
+ *
+ * Creates and initializes a vio_dev structure from the data in
+ * of_node (dev.platform_data) and adds it to the list of virtual devices.
+ * Returns a pointer to the created vio_dev or NULL if node has
+ * NULL device_type or compatible fields.
+ */
+struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
+{
+	struct vio_dev *viodev;
+	unsigned int *unit_address;
+	unsigned int *irq_p;
+
+	/* we need the 'device_type' property, in order to match with drivers */
+	if (of_node->type == NULL) {
+		printk(KERN_WARNING "%s: node %s missing 'device_type'\n",
+				__FUNCTION__,
+				of_node->name ? of_node->name : "<unknown>");
+		return NULL;
+	}
+
+	unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
+	if (unit_address == NULL) {
+		printk(KERN_WARNING "%s: node %s missing 'reg'\n",
+				__FUNCTION__,
+				of_node->name ? of_node->name : "<unknown>");
+		return NULL;
+	}
+
+	/* allocate a vio_dev for this node */
+	viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL);
+	if (viodev == NULL)
+		return NULL;
+
+	viodev->dev.platform_data = of_node_get(of_node);
+
+	viodev->irq = NO_IRQ;
+	irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
+	if (irq_p) {
+		int virq = virt_irq_create_mapping(*irq_p);
+		if (virq == NO_IRQ) {
+			printk(KERN_ERR "Unable to allocate interrupt "
+			       "number for %s\n", of_node->full_name);
+		} else
+			viodev->irq = irq_offset_up(virq);
+	}
+
+	snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
+	viodev->name = of_node->name;
+	viodev->type = of_node->type;
+	viodev->unit_address = *unit_address;
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		unit_address = (unsigned int *)get_property(of_node,
+				"linux,unit_address", NULL);
+		if (unit_address != NULL)
+			viodev->unit_address = *unit_address;
+	}
+	viodev->iommu_table = vio_build_iommu_table(viodev);
+
+	/* init generic 'struct device' fields: */
+	viodev->dev.parent = &vio_bus_device.dev;
+	viodev->dev.bus = &vio_bus_type;
+	viodev->dev.release = vio_dev_release;
+
+	/* register with generic device framework */
+	if (device_register(&viodev->dev)) {
+		printk(KERN_ERR "%s: failed to register device %s\n",
+				__FUNCTION__, viodev->dev.bus_id);
+		/* XXX free TCE table */
+		kfree(viodev);
+		return NULL;
+	}
+
+	return viodev;
+}
+EXPORT_SYMBOL(vio_register_device_node);
+
+/**
  * vio_bus_init: - Initialize the virtual IO bus
  */
-int __init vio_bus_init(struct vio_bus_ops *ops)
+static int __init vio_bus_init(void)
 {
 	int err;
+	struct device_node *node_vroot;
 
-	vio_bus_ops = *ops;
+#ifdef CONFIG_PPC_ISERIES
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		iommu_vio_init();
+		vio_bus_device.iommu_table = &vio_iommu_table;
+		iSeries_vio_dev = &vio_bus_device.dev;
+	}
+#endif
 
 	err = bus_register(&vio_bus_type);
 	if (err) {
@@ -153,47 +317,48 @@
 		return err;
 	}
 
+	node_vroot = find_devices("vdevice");
+	if (node_vroot) {
+		struct device_node *of_node;
+
+		/*
+		 * Create struct vio_devices for each virtual device in
+		 * the device tree. Drivers will associate with them later.
+		 */
+		for (of_node = node_vroot->child; of_node != NULL;
+				of_node = of_node->sibling) {
+			printk(KERN_DEBUG "%s: processing %p\n",
+					__FUNCTION__, of_node);
+			vio_register_device_node(of_node);
+		}
+	}
+
 	return 0;
 }
+__initcall(vio_bus_init);
 
-/* vio_dev refcount hit 0 */
-static void __devinit vio_dev_release(struct device *dev)
-{
-	if (vio_bus_ops.release_device)
-		vio_bus_ops.release_device(dev);
-	kfree(to_vio_dev(dev));
-}
-
-static ssize_t viodev_show_name(struct device *dev,
+static ssize_t name_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
 }
-DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL);
 
-struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev)
+static ssize_t devspec_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
-	/* init generic 'struct device' fields: */
-	viodev->dev.parent = &vio_bus_device.dev;
-	viodev->dev.bus = &vio_bus_type;
-	viodev->dev.release = vio_dev_release;
+	struct device_node *of_node = dev->platform_data;
 
-	/* register with generic device framework */
-	if (device_register(&viodev->dev)) {
-		printk(KERN_ERR "%s: failed to register device %s\n",
-				__FUNCTION__, viodev->dev.bus_id);
-		return NULL;
-	}
-	device_create_file(&viodev->dev, &dev_attr_name);
-
-	return viodev;
+	return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none");
 }
 
+static struct device_attribute vio_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(devspec),
+	__ATTR_NULL
+};
+
 void __devinit vio_unregister_device(struct vio_dev *viodev)
 {
-	if (vio_bus_ops.unregister_device)
-		vio_bus_ops.unregister_device(viodev);
-	device_remove_file(&viodev->dev, &dev_attr_name);
 	device_unregister(&viodev->dev);
 }
 EXPORT_SYMBOL(vio_unregister_device);
@@ -229,7 +394,7 @@
 			   dma_addr_t *dma_handle, gfp_t flag)
 {
 	return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
-			dma_handle, ~0ul, flag);
+			dma_handle, ~0ul, flag, -1);
 }
 
 static void vio_free_coherent(struct device *dev, size_t size,
@@ -267,22 +432,23 @@
 			char *buffer, int buffer_size)
 {
 	const struct vio_dev *vio_dev = to_vio_dev(dev);
+	struct device_node *dn = dev->platform_data;
 	char *cp;
 	int length;
 
 	if (!num_envp)
 		return -ENOMEM;
 
-	if (!vio_dev->dev.platform_data)
+	if (!dn)
 		return -ENODEV;
-	cp = (char *)get_property(vio_dev->dev.platform_data, "compatible", &length);
+	cp = (char *)get_property(dn, "compatible", &length);
 	if (!cp)
 		return -ENODEV;
 
 	envp[0] = buffer;
 	length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s",
 				vio_dev->type, cp);
-	if (buffer_size - length <= 0)
+	if ((buffer_size - length) <= 0)
 		return -ENOMEM;
 	envp[1] = NULL;
 	return 0;
@@ -290,9 +456,81 @@
 
 struct bus_type vio_bus_type = {
 	.name = "vio",
+	.dev_attrs = vio_dev_attrs,
 	.uevent = vio_hotplug,
 	.match = vio_bus_match,
 	.probe = vio_bus_probe,
 	.remove = vio_bus_remove,
 	.shutdown = vio_bus_shutdown,
 };
+
+/**
+ * vio_get_attribute: - get attribute for virtual device
+ * @vdev:	The vio device to get property.
+ * @which:	The property/attribute to be extracted.
+ * @length:	Pointer to length of returned data size (unused if NULL).
+ *
+ * Calls prom.c's get_property() to return the value of the
+ * attribute specified by @which
+*/
+const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length)
+{
+	return get_property(vdev->dev.platform_data, which, length);
+}
+EXPORT_SYMBOL(vio_get_attribute);
+
+#ifdef CONFIG_PPC_PSERIES
+/* vio_find_name() - internal because only vio.c knows how we formatted the
+ * kobject name
+ * XXX once vio_bus_type.devices is actually used as a kset in
+ * drivers/base/bus.c, this function should be removed in favor of
+ * "device_find(kobj_name, &vio_bus_type)"
+ */
+static struct vio_dev *vio_find_name(const char *kobj_name)
+{
+	struct kobject *found;
+
+	found = kset_find_obj(&devices_subsys.kset, kobj_name);
+	if (!found)
+		return NULL;
+
+	return to_vio_dev(container_of(found, struct device, kobj));
+}
+
+/**
+ * vio_find_node - find an already-registered vio_dev
+ * @vnode: device_node of the virtual device we're looking for
+ */
+struct vio_dev *vio_find_node(struct device_node *vnode)
+{
+	uint32_t *unit_address;
+	char kobj_name[BUS_ID_SIZE];
+
+	/* construct the kobject name from the device node */
+	unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
+	if (!unit_address)
+		return NULL;
+	snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
+
+	return vio_find_name(kobj_name);
+}
+EXPORT_SYMBOL(vio_find_node);
+
+int vio_enable_interrupts(struct vio_dev *dev)
+{
+	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
+	if (rc != H_SUCCESS)
+		printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(vio_enable_interrupts);
+
+int vio_disable_interrupts(struct vio_dev *dev)
+{
+	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
+	if (rc != H_SUCCESS)
+		printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
+	return rc;
+}
+EXPORT_SYMBOL(vio_disable_interrupts);
+#endif /* CONFIG_PPC_PSERIES */
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fe79c258..8b25953 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -93,6 +93,11 @@
 		__ptov_table_begin = .;
 		*(.ptov_fixup);
 		__ptov_table_end = .;
+#ifdef CONFIG_PPC_ISERIES
+		__dt_strings_start = .;
+		*(.dt_strings);
+		__dt_strings_end = .;
+#endif
 	}
 
 	. = ALIGN(16);
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 34f5c2e..ff70964 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -2,12 +2,15 @@
 # Makefile for ppc-specific library files..
 #
 
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS		+= -mno-minimal-toc
+endif
+
 ifeq ($(CONFIG_PPC_MERGE),y)
 obj-y			:= string.o strcase.o
 obj-$(CONFIG_PPC32)	+= div64.o copy_32.o checksum_32.o
 endif
 
-obj-y			+= bitops.o
 obj-$(CONFIG_PPC64)	+= checksum_64.o copypage_64.o copyuser_64.o \
 			   memcpy_64.o usercopy_64.o mem_64.o string.o \
 			   strcase.o
diff --git a/arch/powerpc/lib/bitops.c b/arch/powerpc/lib/bitops.c
deleted file mode 100644
index f68ad71..0000000
--- a/arch/powerpc/lib/bitops.c
+++ /dev/null
@@ -1,150 +0,0 @@
-#include <linux/types.h>
-#include <linux/module.h>
-#include <asm/byteorder.h>
-#include <asm/bitops.h>
-
-/**
- * find_next_bit - find the next set bit in a memory region
- * @addr: The address to base the search on
- * @offset: The bitnumber to start searching at
- * @size: The maximum size to search
- */
-unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
-			    unsigned long offset)
-{
-	const unsigned long *p = addr + BITOP_WORD(offset);
-	unsigned long result = offset & ~(BITS_PER_LONG-1);
-	unsigned long tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset %= BITS_PER_LONG;
-	if (offset) {
-		tmp = *(p++);
-		tmp &= (~0UL << offset);
-		if (size < BITS_PER_LONG)
-			goto found_first;
-		if (tmp)
-			goto found_middle;
-		size -= BITS_PER_LONG;
-		result += BITS_PER_LONG;
-	}
-	while (size & ~(BITS_PER_LONG-1)) {
-		if ((tmp = *(p++)))
-			goto found_middle;
-		result += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-	}
-	if (!size)
-		return result;
-	tmp = *p;
-
-found_first:
-	tmp &= (~0UL >> (BITS_PER_LONG - size));
-	if (tmp == 0UL)		/* Are any bits set? */
-		return result + size;	/* Nope. */
-found_middle:
-	return result + __ffs(tmp);
-}
-EXPORT_SYMBOL(find_next_bit);
-
-/*
- * This implementation of find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h.
- */
-unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
-				 unsigned long offset)
-{
-	const unsigned long *p = addr + BITOP_WORD(offset);
-	unsigned long result = offset & ~(BITS_PER_LONG-1);
-	unsigned long tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset %= BITS_PER_LONG;
-	if (offset) {
-		tmp = *(p++);
-		tmp |= ~0UL >> (BITS_PER_LONG - offset);
-		if (size < BITS_PER_LONG)
-			goto found_first;
-		if (~tmp)
-			goto found_middle;
-		size -= BITS_PER_LONG;
-		result += BITS_PER_LONG;
-	}
-	while (size & ~(BITS_PER_LONG-1)) {
-		if (~(tmp = *(p++)))
-			goto found_middle;
-		result += BITS_PER_LONG;
-		size -= BITS_PER_LONG;
-	}
-	if (!size)
-		return result;
-	tmp = *p;
-
-found_first:
-	tmp |= ~0UL << size;
-	if (tmp == ~0UL)	/* Are any bits zero? */
-		return result + size;	/* Nope. */
-found_middle:
-	return result + ffz(tmp);
-}
-EXPORT_SYMBOL(find_next_zero_bit);
-
-static inline unsigned int ext2_ilog2(unsigned int x)
-{
-	int lz;
-
-	asm("cntlzw %0,%1": "=r"(lz):"r"(x));
-	return 31 - lz;
-}
-
-static inline unsigned int ext2_ffz(unsigned int x)
-{
-	u32 rc;
-	if ((x = ~x) == 0)
-		return 32;
-	rc = ext2_ilog2(x & -x);
-	return rc;
-}
-
-unsigned long find_next_zero_le_bit(const unsigned long *addr,
-				    unsigned long size, unsigned long offset)
-{
-	const unsigned int *p = ((const unsigned int *)addr) + (offset >> 5);
-	unsigned int result = offset & ~31;
-	unsigned int tmp;
-
-	if (offset >= size)
-		return size;
-	size -= result;
-	offset &= 31;
-	if (offset) {
-		tmp = cpu_to_le32p(p++);
-		tmp |= ~0U >> (32 - offset);	/* bug or feature ? */
-		if (size < 32)
-			goto found_first;
-		if (tmp != ~0)
-			goto found_middle;
-		size -= 32;
-		result += 32;
-	}
-	while (size >= 32) {
-		if ((tmp = cpu_to_le32p(p++)) != ~0)
-			goto found_middle;
-		result += 32;
-		size -= 32;
-	}
-	if (!size)
-		return result;
-	tmp = cpu_to_le32p(p);
-found_first:
-	tmp |= ~0 << size;
-	if (tmp == ~0)		/* Are any bits zero? */
-		return result + size;	/* Nope. */
-found_middle:
-	return result + ext2_ffz(tmp);
-}
-EXPORT_SYMBOL(find_next_zero_le_bit);
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index fdbba42..a0a9e1e 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -40,6 +40,40 @@
 #include <asm/kdebug.h>
 #include <asm/siginfo.h>
 
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
+/* Hook to register for page fault notifications */
+int register_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+}
+
+int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+}
+
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	struct die_args args = {
+		.regs = regs,
+		.str = str,
+		.err = err,
+		.trapnr = trap,
+		.signr = sig
+	};
+	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	return NOTIFY_DONE;
+}
+#endif
+
 /*
  * Check whether the instruction at regs->nip is a store using
  * an update addressing form which will update r1.
@@ -142,7 +176,7 @@
 	is_write = error_code & ESR_DST;
 #endif /* CONFIG_4xx || CONFIG_BOOKE */
 
-	if (notify_die(DIE_PAGE_FAULT, "page_fault", regs, error_code,
+	if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs, error_code,
 				11, SIGSEGV) == NOTIFY_STOP)
 		return 0;
 
diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S
index ea469ee..94255be 100644
--- a/arch/powerpc/mm/hash_low_32.S
+++ b/arch/powerpc/mm/hash_low_32.S
@@ -74,12 +74,6 @@
  */
 	.text
 _GLOBAL(hash_page)
-#ifdef CONFIG_PPC64BRIDGE
-	mfmsr	r0
-	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
-	MTMSRD(r0)
-	isync
-#endif
 	tophys(r7,0)			/* gets -KERNELBASE into r7 */
 #ifdef CONFIG_SMP
 	addis	r8,r7,mmu_hash_lock@h
@@ -285,7 +279,6 @@
 Hash_bits = 12				/* e.g. 256kB hash table */
 Hash_msk = (((1 << Hash_bits) - 1) * 64)
 
-#ifndef CONFIG_PPC64BRIDGE
 /* defines for the PTE format for 32-bit PPCs */
 #define PTE_SIZE	8
 #define PTEG_SIZE	64
@@ -299,21 +292,6 @@
 #define SET_V(r)	oris r,r,PTE_V@h
 #define CLR_V(r,t)	rlwinm r,r,0,1,31
 
-#else
-/* defines for the PTE format for 64-bit PPCs */
-#define PTE_SIZE	16
-#define PTEG_SIZE	128
-#define LG_PTEG_SIZE	7
-#define LDPTEu		ldu
-#define STPTE		std
-#define CMPPTE		cmpd
-#define PTE_H		2
-#define PTE_V		1
-#define TST_V(r)	andi. r,r,PTE_V
-#define SET_V(r)	ori r,r,PTE_V
-#define CLR_V(r,t)	li t,PTE_V; andc r,r,t
-#endif /* CONFIG_PPC64BRIDGE */
-
 #define HASH_LEFT	31-(LG_PTEG_SIZE+Hash_bits-1)
 #define HASH_RIGHT	31-LG_PTEG_SIZE
 
@@ -331,14 +309,8 @@
 END_FTR_SECTION_IFSET(CPU_FTR_NEED_COHERENT)
 
 	/* Construct the high word of the PPC-style PTE (r5) */
-#ifndef CONFIG_PPC64BRIDGE
 	rlwinm	r5,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
 	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
-	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
-	sldi	r5,r3,12		/* shift vsid into position */
-	rlwimi	r5,r4,16,20,24		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
 	SET_V(r5)			/* set V (valid) bit */
 
 	/* Get the address of the primary PTE group in the hash table (r3) */
@@ -516,14 +488,8 @@
 	add	r3,r3,r0		/* note code below trims to 24 bits */
 
 	/* Construct the high word of the PPC-style PTE (r11) */
-#ifndef CONFIG_PPC64BRIDGE
 	rlwinm	r11,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
 	rlwimi	r11,r4,10,26,31		/* put in API (abbrev page index) */
-#else /* CONFIG_PPC64BRIDGE */
-	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
-	sldi	r11,r3,12		/* shift vsid into position */
-	rlwimi	r11,r4,16,20,24		/* put in API (abbrev page index) */
-#endif /* CONFIG_PPC64BRIDGE */
 	SET_V(r11)			/* set V (valid) bit */
 
 #ifdef CONFIG_SMP
diff --git a/arch/powerpc/mm/hash_low_64.S b/arch/powerpc/mm/hash_low_64.S
index e0d02c4..52e9142 100644
--- a/arch/powerpc/mm/hash_low_64.S
+++ b/arch/powerpc/mm/hash_low_64.S
@@ -136,6 +136,7 @@
 	and	r0,r0,r4		/* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
 	andc	r0,r30,r0		/* r0 = pte & ~r0 */
 	rlwimi	r3,r0,32-1,31,31	/* Insert result into PP lsb */
+	ori	r3,r3,HPTE_R_C		/* Always add "C" bit for perf. */
 
 	/* We eventually do the icache sync here (maybe inline that
 	 * code rather than call a C function...) 
@@ -368,6 +369,7 @@
 	rlwinm	r30,r4,32-9+7,31-7,31-7	/* _PAGE_RW -> _PAGE_DIRTY */
 	or	r30,r30,r31
 	ori	r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE
+	oris	r30,r30,_PAGE_COMBO@h
 	/* Write the linux PTE atomically (setting busy) */
 	stdcx.	r30,0,r6
 	bne-	1b
@@ -400,6 +402,7 @@
 	and	r0,r0,r4		/* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
 	andc	r0,r30,r0		/* r0 = pte & ~r0 */
 	rlwimi	r3,r0,32-1,31,31	/* Insert result into PP lsb */
+	ori	r3,r3,HPTE_R_C		/* Always add "C" bit for perf. */
 
 	/* We eventually do the icache sync here (maybe inline that
 	 * code rather than call a C function...)
@@ -426,6 +429,14 @@
 	andi.	r0,r31,_PAGE_HASHPTE
 	li	r26,0			/* Default hidx */
 	beq	htab_insert_pte
+
+	/*
+	 * Check if the pte was already inserted into the hash table
+	 * as a 64k HW page, and invalidate the 64k HPTE if so.
+	 */
+	andis.	r0,r31,_PAGE_COMBO@h
+	beq	htab_inval_old_hpte
+
 	ld	r6,STK_PARM(r6)(r1)
 	ori	r26,r6,0x8000		/* Load the hidx mask */
 	ld	r26,0(r26)
@@ -496,6 +507,19 @@
 	/* Try all again */
 	b	htab_insert_pte
 
+	/*
+	 * Call out to C code to invalidate an 64k HW HPTE that is
+	 * useless now that the segment has been switched to 4k pages.
+	 */
+htab_inval_old_hpte:
+	mr	r3,r29			/* virtual addr */
+	mr	r4,r31			/* PTE.pte */
+	li	r5,0			/* PTE.hidx */
+	li	r6,MMU_PAGE_64K		/* psize */
+	ld	r7,STK_PARM(r8)(r1)	/* local */
+	bl	.flush_hash_page
+	b	htab_insert_pte
+	
 htab_bail_ok:
 	li	r3,0
 	b	htab_bail
@@ -636,6 +660,12 @@
 	 * is changing this PTE anyway and might hash it.
 	 */
 	bne-	ht64_bail_ok
+BEGIN_FTR_SECTION
+	/* Check if PTE has the cache-inhibit bit set */
+	andi.	r0,r31,_PAGE_NO_CACHE
+	/* If so, bail out and refault as a 4k page */
+	bne-	ht64_bail_ok
+END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE)
 	/* Prepare new PTE value (turn access RW into DIRTY, then
 	 * add BUSY,HASHPTE and ACCESSED)
 	 */
@@ -671,6 +701,7 @@
 	and	r0,r0,r4		/* _PAGE_RW & _PAGE_DIRTY ->r0 bit 30*/
 	andc	r0,r30,r0		/* r0 = pte & ~r0 */
 	rlwimi	r3,r0,32-1,31,31	/* Insert result into PP lsb */
+	ori	r3,r3,HPTE_R_C		/* Always add "C" bit for perf. */
 
 	/* We eventually do the icache sync here (maybe inline that
 	 * code rather than call a C function...)
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 994856e..a0f3cbd 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -238,7 +238,7 @@
 		DBG_LOW(" -> hit\n");
 		/* Update the HPTE */
 		hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) |
-			(newpp & (HPTE_R_PP | HPTE_R_N));
+			(newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C));
 		native_unlock_hpte(hptep);
 	}
 
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index c006d90..d03fd2b 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -92,10 +92,15 @@
 unsigned long htab_hash_mask;
 int mmu_linear_psize = MMU_PAGE_4K;
 int mmu_virtual_psize = MMU_PAGE_4K;
+int mmu_vmalloc_psize = MMU_PAGE_4K;
+int mmu_io_psize = MMU_PAGE_4K;
 #ifdef CONFIG_HUGETLB_PAGE
 int mmu_huge_psize = MMU_PAGE_16M;
 unsigned int HPAGE_SHIFT;
 #endif
+#ifdef CONFIG_PPC_64K_PAGES
+int mmu_ci_restrictions;
+#endif
 
 /* There are definitions of page sizes arrays to be used when none
  * is provided by the firmware.
@@ -308,20 +313,31 @@
 	else if (mmu_psize_defs[MMU_PAGE_1M].shift)
 		mmu_linear_psize = MMU_PAGE_1M;
 
+#ifdef CONFIG_PPC_64K_PAGES
 	/*
 	 * Pick a size for the ordinary pages. Default is 4K, we support
-	 * 64K if cache inhibited large pages are supported by the
-	 * processor
+	 * 64K for user mappings and vmalloc if supported by the processor.
+	 * We only use 64k for ioremap if the processor
+	 * (and firmware) support cache-inhibited large pages.
+	 * If not, we use 4k and set mmu_ci_restrictions so that
+	 * hash_page knows to switch processes that use cache-inhibited
+	 * mappings to 4k pages.
 	 */
-#ifdef CONFIG_PPC_64K_PAGES
-	if (mmu_psize_defs[MMU_PAGE_64K].shift &&
-	    cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
+	if (mmu_psize_defs[MMU_PAGE_64K].shift) {
 		mmu_virtual_psize = MMU_PAGE_64K;
+		mmu_vmalloc_psize = MMU_PAGE_64K;
+		if (cpu_has_feature(CPU_FTR_CI_LARGE_PAGE))
+			mmu_io_psize = MMU_PAGE_64K;
+		else
+			mmu_ci_restrictions = 1;
+	}
 #endif
 
-	printk(KERN_INFO "Page orders: linear mapping = %d, others = %d\n",
+	printk(KERN_DEBUG "Page orders: linear mapping = %d, "
+	       "virtual = %d, io = %d\n",
 	       mmu_psize_defs[mmu_linear_psize].shift,
-	       mmu_psize_defs[mmu_virtual_psize].shift);
+	       mmu_psize_defs[mmu_virtual_psize].shift,
+	       mmu_psize_defs[mmu_io_psize].shift);
 
 #ifdef CONFIG_HUGETLB_PAGE
 	/* Init large page size. Currently, we pick 16M or 1M depending
@@ -556,6 +572,7 @@
 	pte_t *ptep;
 	cpumask_t tmp;
 	int rc, user_region = 0, local = 0;
+	int psize;
 
 	DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
 		ea, access, trap);
@@ -575,10 +592,15 @@
 			return 1;
 		}
 		vsid = get_vsid(mm->context.id, ea);
+		psize = mm->context.user_psize;
 		break;
 	case VMALLOC_REGION_ID:
 		mm = &init_mm;
 		vsid = get_kernel_vsid(ea);
+		if (ea < VMALLOC_END)
+			psize = mmu_vmalloc_psize;
+		else
+			psize = mmu_io_psize;
 		break;
 	default:
 		/* Not a valid range
@@ -629,7 +651,40 @@
 #ifndef CONFIG_PPC_64K_PAGES
 	rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
 #else
-	if (mmu_virtual_psize == MMU_PAGE_64K)
+	if (mmu_ci_restrictions) {
+		/* If this PTE is non-cacheable, switch to 4k */
+		if (psize == MMU_PAGE_64K &&
+		    (pte_val(*ptep) & _PAGE_NO_CACHE)) {
+			if (user_region) {
+				psize = MMU_PAGE_4K;
+				mm->context.user_psize = MMU_PAGE_4K;
+				mm->context.sllp = SLB_VSID_USER |
+					mmu_psize_defs[MMU_PAGE_4K].sllp;
+			} else if (ea < VMALLOC_END) {
+				/*
+				 * some driver did a non-cacheable mapping
+				 * in vmalloc space, so switch vmalloc
+				 * to 4k pages
+				 */
+				printk(KERN_ALERT "Reducing vmalloc segment "
+				       "to 4kB pages because of "
+				       "non-cacheable mapping\n");
+				psize = mmu_vmalloc_psize = MMU_PAGE_4K;
+			}
+		}
+		if (user_region) {
+			if (psize != get_paca()->context.user_psize) {
+				get_paca()->context = mm->context;
+				slb_flush_and_rebolt();
+			}
+		} else if (get_paca()->vmalloc_sllp !=
+			   mmu_psize_defs[mmu_vmalloc_psize].sllp) {
+			get_paca()->vmalloc_sllp =
+				mmu_psize_defs[mmu_vmalloc_psize].sllp;
+			slb_flush_and_rebolt();
+		}
+	}
+	if (psize == MMU_PAGE_64K)
 		rc = __hash_page_64K(ea, access, vsid, ptep, trap, local);
 	else
 		rc = __hash_page_4K(ea, access, vsid, ptep, trap, local);
@@ -681,7 +736,18 @@
 #ifndef CONFIG_PPC_64K_PAGES
 	__hash_page_4K(ea, access, vsid, ptep, trap, local);
 #else
-	if (mmu_virtual_psize == MMU_PAGE_64K)
+	if (mmu_ci_restrictions) {
+		/* If this PTE is non-cacheable, switch to 4k */
+		if (mm->context.user_psize == MMU_PAGE_64K &&
+		    (pte_val(*ptep) & _PAGE_NO_CACHE)) {
+			mm->context.user_psize = MMU_PAGE_4K;
+			mm->context.sllp = SLB_VSID_USER |
+				mmu_psize_defs[MMU_PAGE_4K].sllp;
+			get_paca()->context = mm->context;
+			slb_flush_and_rebolt();
+		}
+	}
+	if (mm->context.user_psize == MMU_PAGE_64K)
 		__hash_page_64K(ea, access, vsid, ptep, trap, local);
 	else
 		__hash_page_4K(ea, access, vsid, ptep, trap, local);
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index 9e30f96..d454caa 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -41,6 +41,7 @@
 #include <linux/idr.h>
 #include <linux/nodemask.h>
 #include <linux/module.h>
+#include <linux/poison.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -90,7 +91,7 @@
 
 	addr = (unsigned long)__init_begin;
 	for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
-		memset((void *)addr, 0xcc, PAGE_SIZE);
+		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
 		free_page(addr);
diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c
index 417d585..8b6f522 100644
--- a/arch/powerpc/mm/lmb.c
+++ b/arch/powerpc/mm/lmb.c
@@ -89,18 +89,23 @@
 	return lmb_addrs_adjacent(base1, size1, base2, size2);
 }
 
+static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
+{
+	unsigned long i;
+
+	for (i = r; i < rgn->cnt - 1; i++) {
+		rgn->region[i].base = rgn->region[i + 1].base;
+		rgn->region[i].size = rgn->region[i + 1].size;
+	}
+	rgn->cnt--;
+}
+
 /* Assumption: base addr of region 1 < base addr of region 2 */
 static void __init lmb_coalesce_regions(struct lmb_region *rgn,
 		unsigned long r1, unsigned long r2)
 {
-	unsigned long i;
-
 	rgn->region[r1].size += rgn->region[r2].size;
-	for (i=r2; i < rgn->cnt-1; i++) {
-		rgn->region[i].base = rgn->region[i+1].base;
-		rgn->region[i].size = rgn->region[i+1].size;
-	}
-	rgn->cnt--;
+	lmb_remove_region(rgn, r2);
 }
 
 /* This routine called with relocation disabled. */
@@ -294,17 +299,16 @@
 	return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
 }
 
-/*
- * Truncate the lmb list to memory_limit if it's set
- * You must call lmb_analyze() after this.
- */
+/* You must call lmb_analyze() after this. */
 void __init lmb_enforce_memory_limit(unsigned long memory_limit)
 {
 	unsigned long i, limit;
+	struct lmb_property *p;
 
 	if (! memory_limit)
 		return;
 
+	/* Truncate the lmb regions to satisfy the memory limit. */
 	limit = memory_limit;
 	for (i = 0; i < lmb.memory.cnt; i++) {
 		if (limit > lmb.memory.region[i].size) {
@@ -316,4 +320,21 @@
 		lmb.memory.cnt = i + 1;
 		break;
 	}
+
+	lmb.rmo_size = lmb.memory.region[0].size;
+
+	/* And truncate any reserves above the limit also. */
+	for (i = 0; i < lmb.reserved.cnt; i++) {
+		p = &lmb.reserved.region[i];
+
+		if (p->base > memory_limit)
+			p->size = 0;
+		else if ((p->base + p->size) > memory_limit)
+			p->size = memory_limit - p->base;
+
+		if (p->size == 0) {
+			lmb_remove_region(&lmb.reserved, i);
+			i--;
+		}
+	}
 }
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 741dd88..089d939 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -114,15 +114,20 @@
 	num_physpages++;
 }
 
-int __devinit add_memory(u64 start, u64 size)
+#ifdef CONFIG_NUMA
+int memory_add_physaddr_to_nid(u64 start)
+{
+	return hot_add_scn_to_nid(start);
+}
+#endif
+
+int __devinit arch_add_memory(int nid, u64 start, u64 size)
 {
 	struct pglist_data *pgdata;
 	struct zone *zone;
-	int nid;
 	unsigned long start_pfn = start >> PAGE_SHIFT;
 	unsigned long nr_pages = size >> PAGE_SHIFT;
 
-	nid = hot_add_scn_to_nid(start);
 	pgdata = NODE_DATA(nid);
 
 	start = (unsigned long)__va(start);
@@ -299,9 +304,9 @@
 	kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
 
-	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
+	printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
-	printk(KERN_INFO "Memory hole size: %ldMB\n",
+	printk(KERN_DEBUG "Memory hole size: %ldMB\n",
 	       (top_of_ram - total_ram) >> 20);
 	/*
 	 * All pages are DMA-able so we put them all in the DMA zone.
@@ -380,7 +385,7 @@
 			totalhigh_pages++;
 		}
 		totalram_pages += totalhigh_pages;
-		printk(KERN_INFO "High memory: %luk\n",
+		printk(KERN_DEBUG "High memory: %luk\n",
 		       totalhigh_pages << (PAGE_SHIFT-10));
 	}
 #endif /* CONFIG_HIGHMEM */
diff --git a/arch/powerpc/mm/mmu_context_32.c b/arch/powerpc/mm/mmu_context_32.c
index a8816e0..e326e424 100644
--- a/arch/powerpc/mm/mmu_context_32.c
+++ b/arch/powerpc/mm/mmu_context_32.c
@@ -30,7 +30,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
-mm_context_t next_mmu_context;
+unsigned long next_mmu_context;
 unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
 #ifdef FEW_CONTEXTS
 atomic_t nr_free_contexts;
diff --git a/arch/powerpc/mm/mmu_context_64.c b/arch/powerpc/mm/mmu_context_64.c
index 714a84d..65d18dc 100644
--- a/arch/powerpc/mm/mmu_context_64.c
+++ b/arch/powerpc/mm/mmu_context_64.c
@@ -49,6 +49,9 @@
 	}
 
 	mm->context.id = index;
+	mm->context.user_psize = mmu_virtual_psize;
+	mm->context.sllp = SLB_VSID_USER |
+		mmu_psize_defs[mmu_virtual_psize].sllp;
 
 	return 0;
 }
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 092355f..fbe2393 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -334,7 +334,7 @@
 	return nid;
 }
 
-static int cpu_numa_callback(struct notifier_block *nfb,
+static int __cpuinit cpu_numa_callback(struct notifier_block *nfb,
 			     unsigned long action,
 			     void *hcpu)
 {
@@ -487,9 +487,9 @@
 	unsigned long total_ram = lmb_phys_mem_size();
 	unsigned int i;
 
-	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
+	printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
 	       top_of_ram, total_ram);
-	printk(KERN_INFO "Memory hole size: %ldMB\n",
+	printk(KERN_DEBUG "Memory hole size: %ldMB\n",
 	       (top_of_ram - total_ram) >> 20);
 
 	for (i = 0; i < lmb.memory.cnt; ++i)
@@ -507,7 +507,7 @@
 		return;
 
 	for_each_online_node(node) {
-		printk(KERN_INFO "Node %d CPUs:", node);
+		printk(KERN_DEBUG "Node %d CPUs:", node);
 
 		count = 0;
 		/*
@@ -543,7 +543,7 @@
 	for_each_online_node(node) {
 		unsigned long i;
 
-		printk(KERN_INFO "Node %d Memory:", node);
+		printk(KERN_DEBUG "Node %d Memory:", node);
 
 		count = 0;
 
@@ -609,14 +609,15 @@
 	return (void *)ret;
 }
 
+static struct notifier_block __cpuinitdata ppc64_numa_nb = {
+	.notifier_call = cpu_numa_callback,
+	.priority = 1 /* Must run before sched domains notifier. */
+};
+
 void __init do_init_bootmem(void)
 {
 	int nid;
 	unsigned int i;
-	static struct notifier_block ppc64_numa_nb = {
-		.notifier_call = cpu_numa_callback,
-		.priority = 1 /* Must run before sched domains notifier. */
-	};
 
 	min_low_pfn = 0;
 	max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index ed7fcfe..2ed43a4 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -42,18 +42,14 @@
 
 union ubat {			/* BAT register values to be loaded */
 	BAT	bat;
-#ifdef CONFIG_PPC64BRIDGE
-	u64	word[2];
-#else
 	u32	word[2];
-#endif
-} BATS[4][2];			/* 4 pairs of IBAT, DBAT */
+} BATS[8][2];			/* 8 pairs of IBAT, DBAT */
 
 struct batrange {		/* stores address ranges mapped by BATs */
 	unsigned long start;
 	unsigned long limit;
 	unsigned long phys;
-} bat_addrs[4];
+} bat_addrs[8];
 
 /*
  * Return PA for this VA if it is mapped by a BAT, or 0
@@ -190,7 +186,7 @@
 		return;
 	pmd = pmd_offset(pgd_offset(mm, ea), ea);
 	if (!pmd_none(*pmd))
-		add_hash_page(mm->context, ea, pmd_val(*pmd));
+		add_hash_page(mm->context.id, ea, pmd_val(*pmd));
 }
 
 /*
@@ -220,15 +216,9 @@
 
 	if ( ppc_md.progress ) ppc_md.progress("hash:enter", 0x105);
 
-#ifdef CONFIG_PPC64BRIDGE
-#define LG_HPTEG_SIZE	7		/* 128 bytes per HPTEG */
-#define SDR1_LOW_BITS	(lg_n_hpteg - 11)
-#define MIN_N_HPTEG	2048		/* min 256kB hash table */
-#else
 #define LG_HPTEG_SIZE	6		/* 64 bytes per HPTEG */
 #define SDR1_LOW_BITS	((n_hpteg - 1) >> 10)
 #define MIN_N_HPTEG	1024		/* min 64kB hash table */
-#endif
 
 	/*
 	 * Allow 1 HPTE (1/8 HPTEG) for each page of memory.
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
index ffc8ed4..6a8bf6c 100644
--- a/arch/powerpc/mm/slb.c
+++ b/arch/powerpc/mm/slb.c
@@ -60,19 +60,19 @@
 		     : "memory" );
 }
 
-static void slb_flush_and_rebolt(void)
+void slb_flush_and_rebolt(void)
 {
 	/* If you change this make sure you change SLB_NUM_BOLTED
 	 * appropriately too. */
-	unsigned long linear_llp, virtual_llp, lflags, vflags;
+	unsigned long linear_llp, vmalloc_llp, lflags, vflags;
 	unsigned long ksp_esid_data;
 
 	WARN_ON(!irqs_disabled());
 
 	linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
-	virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+	vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp;
 	lflags = SLB_VSID_KERNEL | linear_llp;
-	vflags = SLB_VSID_KERNEL | virtual_llp;
+	vflags = SLB_VSID_KERNEL | vmalloc_llp;
 
 	ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
 	if ((ksp_esid_data & ESID_MASK) == PAGE_OFFSET)
@@ -122,9 +122,6 @@
 
 	get_paca()->slb_cache_ptr = 0;
 	get_paca()->context = mm->context;
-#ifdef CONFIG_PPC_64K_PAGES
-	get_paca()->pgdir = mm->pgd;
-#endif /* CONFIG_PPC_64K_PAGES */
 
 	/*
 	 * preload some userspace segments into the SLB.
@@ -167,11 +164,10 @@
 
 void slb_initialize(void)
 {
-	unsigned long linear_llp, virtual_llp;
+	unsigned long linear_llp, vmalloc_llp, io_llp;
 	static int slb_encoding_inited;
 	extern unsigned int *slb_miss_kernel_load_linear;
-	extern unsigned int *slb_miss_kernel_load_virtual;
-	extern unsigned int *slb_miss_user_load_normal;
+	extern unsigned int *slb_miss_kernel_load_io;
 #ifdef CONFIG_HUGETLB_PAGE
 	extern unsigned int *slb_miss_user_load_huge;
 	unsigned long huge_llp;
@@ -181,18 +177,19 @@
 
 	/* Prepare our SLB miss handler based on our page size */
 	linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
-	virtual_llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+	io_llp = mmu_psize_defs[mmu_io_psize].sllp;
+	vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp;
+	get_paca()->vmalloc_sllp = SLB_VSID_KERNEL | vmalloc_llp;
+
 	if (!slb_encoding_inited) {
 		slb_encoding_inited = 1;
 		patch_slb_encoding(slb_miss_kernel_load_linear,
 				   SLB_VSID_KERNEL | linear_llp);
-		patch_slb_encoding(slb_miss_kernel_load_virtual,
-				   SLB_VSID_KERNEL | virtual_llp);
-		patch_slb_encoding(slb_miss_user_load_normal,
-				   SLB_VSID_USER | virtual_llp);
+		patch_slb_encoding(slb_miss_kernel_load_io,
+				   SLB_VSID_KERNEL | io_llp);
 
 		DBG("SLB: linear  LLP = %04x\n", linear_llp);
-		DBG("SLB: virtual LLP = %04x\n", virtual_llp);
+		DBG("SLB: io      LLP = %04x\n", io_llp);
 #ifdef CONFIG_HUGETLB_PAGE
 		patch_slb_encoding(slb_miss_user_load_huge,
 				   SLB_VSID_USER | huge_llp);
@@ -207,7 +204,7 @@
 	unsigned long lflags, vflags;
 
 	lflags = SLB_VSID_KERNEL | linear_llp;
-	vflags = SLB_VSID_KERNEL | virtual_llp;
+	vflags = SLB_VSID_KERNEL | vmalloc_llp;
 
 	/* Invalidate the entire SLB (even slot 0) & all the ERATS */
 	asm volatile("isync":::"memory");
@@ -215,7 +212,6 @@
 	asm volatile("isync; slbia; isync":::"memory");
 	create_slbe(PAGE_OFFSET, lflags, 0);
 
-	/* VMALLOC space has 4K pages always for now */
 	create_slbe(VMALLOC_START, vflags, 1);
 
 	/* We don't bolt the stack for the time being - we're in boot,
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S
index abfaabf6..8548dcf 100644
--- a/arch/powerpc/mm/slb_low.S
+++ b/arch/powerpc/mm/slb_low.S
@@ -59,10 +59,19 @@
 	li	r11,0
 	b	slb_finish_load
 
-1:	/* vmalloc/ioremap mapping encoding bits, the "li" instruction below
+1:	/* vmalloc/ioremap mapping encoding bits, the "li" instructions below
 	 * will be patched by the kernel at boot
 	 */
-_GLOBAL(slb_miss_kernel_load_virtual)
+BEGIN_FTR_SECTION
+	/* check whether this is in vmalloc or ioremap space */
+	clrldi	r11,r10,48
+	cmpldi	r11,(VMALLOC_SIZE >> 28) - 1
+	bgt	5f
+	lhz	r11,PACAVMALLOCSLLP(r13)
+	b	slb_finish_load
+5:
+END_FTR_SECTION_IFCLR(CPU_FTR_CI_LARGE_PAGE)
+_GLOBAL(slb_miss_kernel_load_io)
 	li	r11,0
 	b	slb_finish_load
 
@@ -96,9 +105,7 @@
 1:
 #endif /* CONFIG_HUGETLB_PAGE */
 
-_GLOBAL(slb_miss_user_load_normal)
-	li	r11,0
-
+	lhz	r11,PACACONTEXTSLLP(r13)
 2:
 	ld	r9,PACACONTEXTID(r13)
 	rldimi	r10,r9,USER_ESID_BITS,0
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 4a9291d9..691320c 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -200,10 +200,6 @@
 
 	__get_cpu_var(stab_cache_ptr) = 0;
 
-#ifdef CONFIG_PPC_64K_PAGES
-	get_paca()->pgdir = mm->pgd;
-#endif /* CONFIG_PPC_64K_PAGES */
-
 	/* Now preload some entries for the new task */
 	if (test_tsk_thread_flag(tsk, TIF_32BIT))
 		unmapped_base = TASK_UNMAPPED_BASE_USER32;
diff --git a/arch/powerpc/mm/tlb_32.c b/arch/powerpc/mm/tlb_32.c
index ad580f3..02eb23e 100644
--- a/arch/powerpc/mm/tlb_32.c
+++ b/arch/powerpc/mm/tlb_32.c
@@ -42,7 +42,7 @@
 
 	if (Hash != 0) {
 		ptephys = __pa(ptep) & PAGE_MASK;
-		flush_hash_pages(mm->context, addr, ptephys, 1);
+		flush_hash_pages(mm->context.id, addr, ptephys, 1);
 	}
 }
 
@@ -102,7 +102,7 @@
 	pmd_t *pmd;
 	unsigned long pmd_end;
 	int count;
-	unsigned int ctx = mm->context;
+	unsigned int ctx = mm->context.id;
 
 	if (Hash == 0) {
 		_tlbia();
@@ -172,7 +172,7 @@
 	mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
 	pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
 	if (!pmd_none(*pmd))
-		flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
+		flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1);
 	FINISH_FLUSH;
 }
 
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c
index f734b11..e7449b0 100644
--- a/arch/powerpc/mm/tlb_64.c
+++ b/arch/powerpc/mm/tlb_64.c
@@ -131,7 +131,7 @@
 {
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
 	unsigned long vsid;
-	unsigned int psize = mmu_virtual_psize;
+	unsigned int psize;
 	int i;
 
 	i = batch->index;
@@ -148,7 +148,8 @@
 #else
 		BUG();
 #endif
-	}
+	} else
+		psize = pte_pagesize_index(pte);
 
 	/*
 	 * This can happen when we are in the middle of a TLB batch and
diff --git a/arch/powerpc/oprofile/Kconfig b/arch/powerpc/oprofile/Kconfig
index d03c0e5..eb2dece 100644
--- a/arch/powerpc/oprofile/Kconfig
+++ b/arch/powerpc/oprofile/Kconfig
@@ -1,5 +1,4 @@
 config PROFILING
-	depends on !PPC_ISERIES
 	bool "Profiling support (EXPERIMENTAL)"
 	help
 	  Say Y here to enable the extended profiling support mechanisms used
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index f5f9859..3145d61 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -1,3 +1,7 @@
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS	+= -mno-minimal-toc
+endif
+
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
 DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c
index 5b1de7e..fd0bbbe 100644
--- a/arch/powerpc/oprofile/common.c
+++ b/arch/powerpc/oprofile/common.c
@@ -22,6 +22,7 @@
 #include <asm/pmc.h>
 #include <asm/cputable.h>
 #include <asm/oprofile_impl.h>
+#include <asm/firmware.h>
 
 static struct op_powerpc_model *model;
 
@@ -93,7 +94,7 @@
 
 	for (i = 0; i < model->num_counters; ++i) {
 		struct dentry *dir;
-		char buf[3];
+		char buf[4];
 
 		snprintf(buf, sizeof buf, "%d", i);
 		dir = oprofilefs_mkdir(sb, root, buf);
@@ -130,6 +131,9 @@
 	if (!cur_cpu_spec->oprofile_cpu_type)
 		return -ENODEV;
 
+	if (firmware_has_feature(FW_FEATURE_ISERIES))
+		return -ENODEV;
+
 	switch (cur_cpu_spec->oprofile_type) {
 #ifdef CONFIG_PPC64
 		case PPC_OPROFILE_RS64:
@@ -162,7 +166,7 @@
 	ops->stop = op_powerpc_stop;
 	ops->backtrace = op_powerpc_backtrace;
 
-	printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
+	printk(KERN_DEBUG "oprofile: using %s performance monitoring.\n",
 	       ops->cpu_type);
 
 	return 0;
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 4c2beab1..506f6b7 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -24,10 +24,6 @@
 static unsigned long reset_value[OP_MAX_COUNTER];
 
 static int oprofile_running;
-static int mmcra_has_sihv;
-/* Unfortunately these bits vary between CPUs */
-static unsigned long mmcra_sihv = MMCRA_SIHV;
-static unsigned long mmcra_sipr = MMCRA_SIPR;
 
 /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */
 static u32 mmcr0_val;
@@ -41,16 +37,6 @@
 	int i;
 
 	/*
-	 * SIHV / SIPR bits are only implemented on POWER4+ (GQ) and above.
-	 * However we disable it on all POWER4 until we verify it works
-	 * (I was seeing some strange behaviour last time I tried).
-	 *
-	 * It has been verified to work on POWER5 so we enable it there.
-	 */
-	if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
-		mmcra_has_sihv = 1;
-
-	/*
 	 * The performance counter event settings are given in the mmcr0,
 	 * mmcr1 and mmcra values passed from the user in the
 	 * op_system_config structure (sys variable).
@@ -202,18 +188,19 @@
 	unsigned long mmcra;
 
 	/* Cant do much about it */
-	if (!mmcra_has_sihv)
+	if (!cur_cpu_spec->oprofile_mmcra_sihv)
 		return pc;
 
 	mmcra = mfspr(SPRN_MMCRA);
 
 	/* Were we in the hypervisor? */
-	if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv))
+	if (firmware_has_feature(FW_FEATURE_LPAR) &&
+	    (mmcra & cur_cpu_spec->oprofile_mmcra_sihv))
 		/* function descriptor madness */
 		return *((unsigned long *)hypervisor_bucket);
 
 	/* We were in userspace, nothing to do */
-	if (mmcra & mmcra_sipr)
+	if (mmcra & cur_cpu_spec->oprofile_mmcra_sipr)
 		return pc;
 
 #ifdef CONFIG_PPC_RTAS
@@ -235,15 +222,14 @@
 	return pc;
 }
 
-static int get_kernel(unsigned long pc)
+static int get_kernel(unsigned long pc, unsigned long mmcra)
 {
 	int is_kernel;
 
-	if (!mmcra_has_sihv) {
+	if (!cur_cpu_spec->oprofile_mmcra_sihv) {
 		is_kernel = is_kernel_addr(pc);
 	} else {
-		unsigned long mmcra = mfspr(SPRN_MMCRA);
-		is_kernel = ((mmcra & mmcra_sipr) == 0);
+		is_kernel = ((mmcra & cur_cpu_spec->oprofile_mmcra_sipr) == 0);
 	}
 
 	return is_kernel;
@@ -257,9 +243,12 @@
 	int val;
 	int i;
 	unsigned int mmcr0;
+	unsigned long mmcra;
+
+	mmcra = mfspr(SPRN_MMCRA);
 
 	pc = get_pc(regs);
-	is_kernel = get_kernel(pc);
+	is_kernel = get_kernel(pc, mmcra);
 
 	/* set the PMM bit (see comment below) */
 	mtmsrd(mfmsr() | MSR_PMM);
@@ -287,6 +276,10 @@
 	 */
 	mmcr0 &= ~MMCR0_PMAO;
 
+	/* Clear the appropriate bits in the MMCRA */
+	mmcra &= ~cur_cpu_spec->oprofile_mmcra_clear;
+	mtspr(SPRN_MMCRA, mmcra);
+
 	/*
 	 * now clear the freeze bit, counting will not start until we
 	 * rfid from this exception, because only at that point will
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig
index 06e3712..454fc53 100644
--- a/arch/powerpc/platforms/85xx/Kconfig
+++ b/arch/powerpc/platforms/85xx/Kconfig
@@ -11,13 +11,20 @@
 	help
 	  This option enables support for the MPC 8540 ADS board
 
+config MPC85xx_CDS
+	bool "Freescale MPC85xx CDS"
+	select DEFAULT_UIMAGE
+	select PPC_I8259 if PCI
+	help
+	  This option enables support for the MPC85xx CDS board
+
 endchoice
 
 config MPC8540
 	bool
 	select PPC_UDBG_16550
 	select PPC_INDIRECT_PCI
-	default y if MPC8540_ADS
+	default y if MPC8540_ADS || MPC85xx_CDS
 
 config PPC_INDIRECT_PCI_BE
 	bool
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index ffc4139..7615aa5 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_PPC_85xx)	+= misc.o pci.o
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
+obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
new file mode 100644
index 0000000..18e6e11
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c
@@ -0,0 +1,359 @@
+/*
+ * MPC85xx setup and early boot code plus other random bits.
+ *
+ * Maintained by Kumar Gala (see MAINTAINERS for contact information)
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc85xx.h>
+#include <asm/irq.h>
+#include <mm/mmu_decl.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <asm/i8259.h>
+
+#include <sysdev/fsl_soc.h>
+#include "mpc85xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+static int cds_pci_slot = 2;
+static volatile u8 *cadmus;
+
+/*
+ * Internal interrupts are all Level Sensitive, and Positive Polarity
+ *
+ * Note:  Likely, this table and the following function should be
+ *        obtained and derived from the OF Device Tree.
+ */
+static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
+	MPC85XX_INTERNAL_IRQ_SENSES,
+#if defined(CONFIG_PCI)
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Ext 0: PCI slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 1: PCI slot 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 2: PCI slot 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* Ext 3: PCI slot 3 */
+#else
+	0x0,				/* External  0: */
+	0x0,				/* External  1: */
+	0x0,				/* External  2: */
+	0x0,				/* External  3: */
+#endif
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 5: PHY */
+	0x0,				/* External  6: */
+	0x0,				/* External  7: */
+	0x0,				/* External  8: */
+	0x0,				/* External  9: */
+	0x0,				/* External 10: */
+#ifdef CONFIG_PCI
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),    /* Ext 11: PCI2 slot 0 */
+#else
+	0x0,				/* External 11: */
+#endif
+};
+
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+int
+mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
+
+	if (!hose->index)
+	{
+		/* Handle PCI1 interrupts */
+		char pci_irq_table[][4] =
+			/*
+			 *      PCI IDSEL/INTPIN->INTLINE
+			 *        A      B      C      D
+			 */
+
+			/* Note IRQ assignment for slots is based on which slot the elysium is
+			 * in -- in this setup elysium is in slot #2 (this PIRQA as first
+			 * interrupt on slot */
+		{
+			{ 0, 1, 2, 3 }, /* 16 - PMC */
+			{ 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
+			{ 0, 1, 2, 3 }, /* 18 - Slot 1 */
+			{ 1, 2, 3, 0 }, /* 19 - Slot 2 */
+			{ 2, 3, 0, 1 }, /* 20 - Slot 3 */
+			{ 3, 0, 1, 2 }, /* 21 - Slot 4 */
+		};
+
+		const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4;
+		int i, j;
+
+		for (i = 0; i < 6; i++)
+			for (j = 0; j < 4; j++)
+				pci_irq_table[i][j] =
+					((pci_irq_table[i][j] + 5 -
+					  cds_pci_slot) & 0x3) + PIRQ0A;
+
+		return PCI_IRQ_TABLE_LOOKUP;
+	} else {
+		/* Handle PCI2 interrupts (if we have one) */
+		char pci_irq_table[][4] =
+		{
+			/*
+			 * We only have one slot and one interrupt
+			 * going to PIRQA - PIRQD */
+			{ PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */
+		};
+
+		const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4;
+
+		return PCI_IRQ_TABLE_LOOKUP;
+	}
+}
+
+#define ARCADIA_HOST_BRIDGE_IDSEL	17
+#define ARCADIA_2ND_BRIDGE_IDSEL	3
+
+extern int mpc85xx_pci2_busno;
+
+int
+mpc85xx_exclude_device(u_char bus, u_char devfn)
+{
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (mpc85xx_pci2_busno)
+		if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0)
+			return PCIBIOS_DEVICE_NOT_FOUND;
+	/* We explicitly do not go past the Tundra 320 Bridge */
+	if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	else
+		return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+mpc85xx_cds_pcibios_fixup(void)
+{
+	struct pci_dev *dev;
+	u_char		c;
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+		/*
+		 * U-Boot does not set the enable bits
+		 * for the IDE device. Force them on here.
+		 */
+		pci_read_config_byte(dev, 0x40, &c);
+		c |= 0x03; /* IDE: Chip Enable Bits */
+		pci_write_config_byte(dev, 0x40, c);
+
+		/*
+		 * Since only primary interface works, force the
+		 * IDE function to standard primary IDE interrupt
+		 * w/ 8259 offset
+		 */
+		dev->irq = 14;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+		pci_dev_put(dev);
+	}
+
+	/*
+	 * Force legacy USB interrupt routing
+	 */
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
+		dev->irq = 10;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
+		pci_dev_put(dev);
+	}
+
+	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+					PCI_DEVICE_ID_VIA_82C586_2, dev))) {
+		dev->irq = 11;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		pci_dev_put(dev);
+	}
+}
+#endif /* CONFIG_PCI */
+
+void __init mpc85xx_cds_pic_init(void)
+{
+	struct mpic *mpic1;
+	phys_addr_t OpenPIC_PAddr;
+
+	/* Determine the Physical Address of the OpenPIC regs */
+	OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET;
+
+	mpic1 = mpic_alloc(OpenPIC_PAddr,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250,
+			mpc85xx_cds_openpic_initsenses,
+			sizeof(mpc85xx_cds_openpic_initsenses), " OpenPIC  ");
+	BUG_ON(mpic1 == NULL);
+	mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200);
+	mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280);
+	mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300);
+	mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380);
+	mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400);
+	mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480);
+	mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500);
+	mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580);
+
+	/* dummy mappings to get to 48 */
+	mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600);
+	mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680);
+	mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700);
+	mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780);
+
+	/* External ints */
+	mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000);
+	mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080);
+	mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100);
+
+	mpic_init(mpic1);
+
+#ifdef CONFIG_PCI
+	mpic_setup_cascade(PIRQ0A, i8259_irq_cascade, NULL);
+
+	i8259_init(0,0);
+#endif
+}
+
+
+/*
+ * Setup the architecture
+ */
+static void __init
+mpc85xx_cds_setup_arch(void)
+{
+	struct device_node *cpu;
+#ifdef CONFIG_PCI
+	struct device_node *np;
+#endif
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc85xx_cds_setup_arch()", 0);
+
+	cpu = of_find_node_by_type(NULL, "cpu");
+	if (cpu != 0) {
+		unsigned int *fp;
+
+		fp = (int *)get_property(cpu, "clock-frequency", NULL);
+		if (fp != 0)
+			loops_per_jiffy = *fp / HZ;
+		else
+			loops_per_jiffy = 500000000 / HZ;
+		of_node_put(cpu);
+	}
+
+	cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE);
+	cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
+
+	if (ppc_md.progress) {
+		char buf[40];
+		snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n",
+				cadmus[CM_VER], cds_pci_slot);
+		ppc_md.progress(buf, 0);
+	}
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+
+	ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc85xx_map_irq;
+	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+#endif
+
+#ifdef  CONFIG_ROOT_NFS
+	ROOT_DEV = Root_NFS;
+#else
+	ROOT_DEV = Root_HDA1;
+#endif
+}
+
+
+void
+mpc85xx_cds_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	uint memsize = total_memory;
+
+	pvid = mfspr(SPRN_PVR);
+	svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+	seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]);
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(SPRN_HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc85xx_cds_probe(void)
+{
+	/* We always match for now, eventually we should look at
+	 * the flat dev tree to ensure this is the board we are
+	 * supposed to run on
+	 */
+	return 1;
+}
+
+define_machine(mpc85xx_cds) {
+	.name		= "MPC85xx CDS",
+	.probe		= mpc85xx_cds_probe,
+	.setup_arch	= mpc85xx_cds_setup_arch,
+	.init_IRQ	= mpc85xx_cds_pic_init,
+	.show_cpuinfo	= mpc85xx_cds_show_cpuinfo,
+	.get_irq	= mpic_get_irq,
+	.restart	= mpc85xx_restart,
+	.calibrate_decr = generic_calibrate_decr,
+	.progress	= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
new file mode 100644
index 0000000..671f54f
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h
@@ -0,0 +1,43 @@
+/*
+ * arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+ *
+ * MPC85xx CDS board definitions
+ *
+ * Maintainer: Kumar Gala <galak@kernel.crashing.org>
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __MACH_MPC85XX_CDS_H__
+#define __MACH_MPC85XX_CDS_H__
+
+/* CADMUS info */
+#define CADMUS_BASE (0xf8004000)
+#define CADMUS_SIZE (256)
+#define CM_VER	(0)
+#define CM_CSR	(1)
+#define CM_RST	(2)
+
+/* CDS NVRAM/RTC */
+#define CDS_RTC_ADDR	(0xf8000000)
+#define CDS_RTC_SIZE	(8 * 1024)
+
+/* PCI interrupt controller */
+#define PIRQ0A			MPC85xx_IRQ_EXT0
+#define PIRQ0B			MPC85xx_IRQ_EXT1
+#define PIRQ0C			MPC85xx_IRQ_EXT2
+#define PIRQ0D			MPC85xx_IRQ_EXT3
+#define PIRQ1A			MPC85xx_IRQ_EXT11
+
+#define NR_8259_INTS		16
+#define CPM_IRQ_OFFSET		NR_8259_INTS
+
+#define MPC85xx_OPENPIC_IRQ_OFFSET	80
+
+#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig
new file mode 100644
index 0000000..3a87863
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/Kconfig
@@ -0,0 +1,36 @@
+menu "Platform Support"
+	depends on PPC_86xx
+
+choice
+	prompt "Machine Type"
+	default MPC8641_HPCN
+
+config MPC8641_HPCN
+	bool "Freescale MPC8641 HPCN"
+	help
+	  This option enables support for the MPC8641 HPCN board.
+
+endchoice
+
+
+config MPC8641
+	bool
+	select PPC_INDIRECT_PCI
+	select PPC_UDBG_16550
+	default y if MPC8641_HPCN
+
+config MPIC
+	bool
+	default y
+
+config PPC_INDIRECT_PCI_BE
+	bool
+	depends on PPC_86xx
+	default y
+
+config PPC_STD_MMU
+	bool
+	depends on PPC_86xx
+	default y
+
+endmenu
diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile
new file mode 100644
index 0000000..7be796c
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the PowerPC 86xx linux kernel.
+#
+
+
+ifeq ($(CONFIG_PPC_86xx),y)
+obj-$(CONFIG_SMP)		+= mpc86xx_smp.o
+endif
+obj-$(CONFIG_MPC8641_HPCN)	+= mpc86xx_hpcn.o
+obj-$(CONFIG_PCI)		+= pci.o mpc86xx_pcie.o
diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
new file mode 100644
index 0000000..5042253
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h
@@ -0,0 +1,54 @@
+/*
+ * MPC8641 HPCN board definitions
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ * Author: Xianghua Xiao <x.xiao@freescale.com>
+ */
+
+#ifndef __MPC8641_HPCN_H__
+#define __MPC8641_HPCN_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+/* PCI interrupt controller */
+#define PIRQA		3
+#define PIRQB		4
+#define PIRQC		5
+#define PIRQD		6
+#define PIRQ7		7
+#define PIRQE		9
+#define PIRQF		10
+#define PIRQG		11
+#define PIRQH		12
+
+/* PCI-Express memory map */
+#define MPC86XX_PCIE_LOWER_IO        0x00000000
+#define MPC86XX_PCIE_UPPER_IO        0x00ffffff
+
+#define MPC86XX_PCIE_LOWER_MEM       0x80000000
+#define MPC86XX_PCIE_UPPER_MEM       0x9fffffff
+
+#define MPC86XX_PCIE_IO_BASE         0xe2000000
+#define MPC86XX_PCIE_MEM_OFFSET      0x00000000
+
+#define MPC86XX_PCIE_IO_SIZE         0x01000000
+
+#define PCIE1_CFG_ADDR_OFFSET    (0x8000)
+#define PCIE1_CFG_DATA_OFFSET    (0x8004)
+
+#define PCIE2_CFG_ADDR_OFFSET    (0x9000)
+#define PCIE2_CFG_DATA_OFFSET    (0x9004)
+
+#define MPC86xx_PCIE_OFFSET PCIE1_CFG_ADDR_OFFSET
+#define MPC86xx_PCIE_SIZE	(0x1000)
+
+#define MPC86XX_RSTCR_OFFSET	(0xe00b0)	/* Reset Control Register */
+
+#endif	/* __MPC8641_HPCN_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h
new file mode 100644
index 0000000..e3c9e4f
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __MPC86XX_H__
+#define __MPC86XX_H__
+
+/*
+ * Declaration for the various functions exported by the
+ * mpc86xx_* files. Mostly for use by mpc86xx_setup().
+ */
+
+extern int __init add_bridge(struct device_node *dev);
+
+extern void __init setup_indirect_pcie(struct pci_controller *hose,
+				       u32 cfg_addr, u32 cfg_data);
+extern void __init setup_indirect_pcie_nomap(struct pci_controller *hose,
+					     void __iomem *cfg_addr,
+					     void __iomem *cfg_data);
+
+extern void __init mpc86xx_smp_init(void);
+
+#endif	/* __MPC86XX_H__ */
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
new file mode 100644
index 0000000..483c21d
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -0,0 +1,326 @@
+/*
+ * MPC86xx HPCN board specific routines
+ *
+ * Recode: ZHANG WEI <wei.zhang@freescale.com>
+ * Initial author: Xianghua Xiao <x.xiao@freescale.com>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+
+#include <asm/system.h>
+#include <asm/time.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc86xx.h>
+#include <asm/prom.h>
+#include <mm/mmu_decl.h>
+#include <asm/udbg.h>
+#include <asm/i8259.h>
+
+#include <asm/mpic.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+unsigned long pci_dram_offset = 0;
+#endif
+
+
+/*
+ * Internal interrupts are all Level Sensitive, and Positive Polarity
+ */
+
+static u_char mpc86xx_hpcn_openpic_initsenses[] __initdata = {
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: MCM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCIE1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: PCIE2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: Reserved */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: DUART2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: TSEC 3 transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: TSEC 3 receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: TSEC 3 error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 2 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 2 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: TSEC 4 transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: TSEC 4 receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: TSEC 4 error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 2 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32: SRIO error/write-port unit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33: SRIO outbound doorbell */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34: SRIO inbound doorbell */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37: SRIO outbound message unit 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38: SRIO inbound message unit 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39: SRIO outbound message unit 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40: SRIO inbound message unit 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 47: Unused */
+	0x0,						/* External  0: */
+	0x0,						/* External  1: */
+	0x0,						/* External  2: */
+	0x0,						/* External  3: */
+	0x0,						/* External  4: */
+	0x0,						/* External  5: */
+	0x0,						/* External  6: */
+	0x0,						/* External  7: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  8: Pixis FPGA */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* External  9: ULI 8259 INTR Cascade */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 10: Quad ETH PHY */
+	0x0,						/* External 11: */
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+};
+
+
+void __init
+mpc86xx_hpcn_init_irq(void)
+{
+	struct mpic *mpic1;
+	phys_addr_t openpic_paddr;
+
+	/* Determine the Physical Address of the OpenPIC regs */
+	openpic_paddr = get_immrbase() + MPC86xx_OPENPIC_OFFSET;
+
+	/* Alloc mpic structure and per isu has 16 INT entries. */
+	mpic1 = mpic_alloc(openpic_paddr,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			16, MPC86xx_OPENPIC_IRQ_OFFSET, 0, 250,
+			mpc86xx_hpcn_openpic_initsenses,
+			sizeof(mpc86xx_hpcn_openpic_initsenses),
+			" MPIC     ");
+	BUG_ON(mpic1 == NULL);
+
+	/* 48 Internal Interrupts */
+	mpic_assign_isu(mpic1, 0, openpic_paddr + 0x10200);
+	mpic_assign_isu(mpic1, 1, openpic_paddr + 0x10400);
+	mpic_assign_isu(mpic1, 2, openpic_paddr + 0x10600);
+
+	/* 16 External interrupts */
+	mpic_assign_isu(mpic1, 3, openpic_paddr + 0x10000);
+
+	mpic_init(mpic1);
+
+#ifdef CONFIG_PCI
+	mpic_setup_cascade(MPC86xx_IRQ_EXT9, i8259_irq_cascade, NULL);
+	i8259_init(0, I8259_OFFSET);
+#endif
+}
+
+
+
+#ifdef CONFIG_PCI
+/*
+ * interrupt routing
+ */
+
+int
+mpc86xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+	static char pci_irq_table[][4] = {
+		/*
+		 *      PCI IDSEL/INTPIN->INTLINE
+		 *       A      B      C      D
+		 */
+		{PIRQA, PIRQB, PIRQC, PIRQD},   /* IDSEL 17 -- PCI Slot 1 */
+		{PIRQB, PIRQC, PIRQD, PIRQA},	/* IDSEL 18 -- PCI Slot 2 */
+		{0, 0, 0, 0},			/* IDSEL 19 */
+		{0, 0, 0, 0},			/* IDSEL 20 */
+		{0, 0, 0, 0},			/* IDSEL 21 */
+		{0, 0, 0, 0},			/* IDSEL 22 */
+		{0, 0, 0, 0},			/* IDSEL 23 */
+		{0, 0, 0, 0},			/* IDSEL 24 */
+		{0, 0, 0, 0},			/* IDSEL 25 */
+		{PIRQD, PIRQA, PIRQB, PIRQC},	/* IDSEL 26 -- PCI Bridge*/
+		{PIRQC, 0, 0, 0},		/* IDSEL 27 -- LAN */
+		{PIRQE, PIRQF, PIRQH, PIRQ7},	/* IDSEL 28 -- USB 1.1 */
+		{PIRQE, PIRQF, PIRQG, 0},	/* IDSEL 29 -- Audio & Modem */
+		{PIRQH, 0, 0, 0},		/* IDSEL 30 -- LPC & PMU*/
+		{PIRQD, 0, 0, 0},		/* IDSEL 31 -- ATA */
+	};
+
+	const long min_idsel = 17, max_idsel = 31, irqs_per_slot = 4;
+	return PCI_IRQ_TABLE_LOOKUP + I8259_OFFSET;
+}
+
+
+int
+mpc86xx_exclude_device(u_char bus, u_char devfn)
+{
+#if !defined(CONFIG_PCI)
+	if (bus == 0 && PCI_SLOT(devfn) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+
+	return PCIBIOS_SUCCESSFUL;
+}
+#endif /* CONFIG_PCI */
+
+
+static void __init
+mpc86xx_hpcn_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0);
+
+	np = of_find_node_by_type(NULL, "cpu");
+	if (np != 0) {
+		unsigned int *fp;
+
+		fp = (int *)get_property(np, "clock-frequency", NULL);
+		if (fp != 0)
+			loops_per_jiffy = *fp / HZ;
+		else
+			loops_per_jiffy = 50000000 / HZ;
+		of_node_put(np);
+	}
+
+#ifdef CONFIG_PCI
+	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
+		add_bridge(np);
+
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = mpc86xx_map_irq;
+	ppc_md.pci_exclude_device = mpc86xx_exclude_device;
+#endif
+
+	printk("MPC86xx HPCN board from Freescale Semiconductor\n");
+
+#ifdef  CONFIG_ROOT_NFS
+	ROOT_DEV = Root_NFS;
+#else
+	ROOT_DEV = Root_HDA1;
+#endif
+
+#ifdef CONFIG_SMP
+	mpc86xx_smp_init();
+#endif
+}
+
+
+void
+mpc86xx_hpcn_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	uint memsize = total_memory;
+	const char *model = "";
+	uint svid = mfspr(SPRN_SVR);
+
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "Machine\t\t: %s\n", model);
+	of_node_put(root);
+
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+}
+
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init mpc86xx_hpcn_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	if (of_flat_dt_is_compatible(root, "mpc86xx"))
+		return 1;	/* Looks good */
+
+	return 0;
+}
+
+
+void
+mpc86xx_restart(char *cmd)
+{
+	void __iomem *rstcr;
+
+	rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100);
+
+	local_irq_disable();
+
+	/* Assert reset request to Reset Control Register */
+	out_be32(rstcr, 0x2);
+
+	/* not reached */
+}
+
+
+long __init
+mpc86xx_time_init(void)
+{
+	unsigned int temp;
+
+	/* Set the time base to zero */
+	mtspr(SPRN_TBWL, 0);
+	mtspr(SPRN_TBWU, 0);
+
+	temp = mfspr(SPRN_HID0);
+	temp |= HID0_TBEN;
+	mtspr(SPRN_HID0, temp);
+	asm volatile("isync");
+
+	return 0;
+}
+
+
+define_machine(mpc86xx_hpcn) {
+	.name			= "MPC86xx HPCN",
+	.probe			= mpc86xx_hpcn_probe,
+	.setup_arch		= mpc86xx_hpcn_setup_arch,
+	.init_IRQ		= mpc86xx_hpcn_init_irq,
+	.show_cpuinfo		= mpc86xx_hpcn_show_cpuinfo,
+	.get_irq		= mpic_get_irq,
+	.restart		= mpc86xx_restart,
+	.time_init		= mpc86xx_time_init,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= udbg_progress,
+};
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c
new file mode 100644
index 0000000..a2f4f73
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c
@@ -0,0 +1,173 @@
+/*
+ * Support for indirect PCI bridges.
+ *
+ * Copyright (C) 1998 Gabriel Paubert.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * "Temporary" MPC8548 Errata file -
+ * The standard indirect_pci code should work with future silicon versions.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "mpc86xx.h"
+
+#define PCI_CFG_OUT out_be32
+
+/* ERRATA PCI-Ex 14 PCIE Controller timeout */
+#define PCIE_FIX		out_be32(hose->cfg_addr+0x4, 0x0400ffff)
+
+
+static int
+indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+		     int len, u32 *val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+	u32 temp;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Possible artifact of CDCpp50937 needs further investigation */
+	if (devfn != 0x0 && bus->number == 0xff)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	PCIE_FIX;
+	if (bus->number == 0xff) {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000000 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+	} else {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000001 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+	}
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+	cfg_data = hose->cfg_data;
+	PCIE_FIX;
+	temp = in_le32(cfg_data);
+	switch (len) {
+	case 1:
+		*val = (temp >> (((offset & 3))*8)) & 0xff;
+		break;
+	case 2:
+		*val = (temp >> (((offset & 3))*8)) & 0xffff;
+		break;
+	default:
+		*val = temp;
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset,
+		      int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	volatile void __iomem *cfg_data;
+	u32 temp;
+
+	if (ppc_md.pci_exclude_device)
+		if (ppc_md.pci_exclude_device(bus->number, devfn))
+			return PCIBIOS_DEVICE_NOT_FOUND;
+
+	/* Possible artifact of CDCpp50937 needs further investigation */
+	if (devfn != 0x0 && bus->number == 0xff)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	PCIE_FIX;
+	if (bus->number == 0xff) {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000000 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+	} else {
+		PCI_CFG_OUT(hose->cfg_addr,
+			    (0x80000001 | ((offset & 0xf00) << 16) |
+			     ((bus->number - hose->bus_offset) << 16)
+			     | (devfn << 8) | ((offset & 0xfc) )));
+        }
+
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	/* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
+	cfg_data = hose->cfg_data;
+	switch (len) {
+	case 1:
+		PCIE_FIX;
+		temp = in_le32(cfg_data);
+		temp = (temp & ~(0xff << ((offset & 3) * 8))) |
+			(val << ((offset & 3) * 8));
+		PCIE_FIX;
+		out_le32(cfg_data, temp);
+		break;
+	case 2:
+		PCIE_FIX;
+		temp = in_le32(cfg_data);
+		temp = (temp & ~(0xffff << ((offset & 3) * 8)));
+		temp |= (val << ((offset & 3) * 8)) ;
+		PCIE_FIX;
+		out_le32(cfg_data, temp);
+		break;
+	default:
+		PCIE_FIX;
+		out_le32(cfg_data, val);
+		break;
+	}
+	PCIE_FIX;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops indirect_pcie_ops = {
+	indirect_read_config_pcie,
+	indirect_write_config_pcie
+};
+
+void __init
+setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr,
+	void __iomem * cfg_data)
+{
+	hose->cfg_addr = cfg_addr;
+	hose->cfg_data = cfg_data;
+	hose->ops = &indirect_pcie_ops;
+}
+
+void __init
+setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+	unsigned long base = cfg_addr & PAGE_MASK;
+	void __iomem *mbase, *addr, *data;
+
+	mbase = ioremap(base, PAGE_SIZE);
+	addr = mbase + (cfg_addr & ~PAGE_MASK);
+	if ((cfg_data & PAGE_MASK) != base)
+		mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
+	data = mbase + (cfg_data & ~PAGE_MASK);
+	setup_indirect_pcie_nomap(hose, addr, data);
+}
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
new file mode 100644
index 0000000..944ec4b
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c
@@ -0,0 +1,117 @@
+/*
+ * Author: Xianghua Xiao <x.xiao@freescale.com>
+ *         Zhang Wei <wei.zhang@freescale.com>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/pci-bridge.h>
+#include <asm-powerpc/mpic.h>
+#include <asm/mpc86xx.h>
+#include <asm/cacheflush.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+extern void __secondary_start_mpc86xx(void);
+extern unsigned long __secondary_hold_acknowledge;
+
+
+static void __init
+smp_86xx_release_core(int nr)
+{
+	void *mcm_vaddr;
+	unsigned long vaddr, pcr;
+
+	if (nr < 0 || nr >= NR_CPUS)
+		return;
+
+	/*
+	 * Startup Core #nr.
+	 */
+	mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET,
+			    MPC86xx_MCM_SIZE);
+	vaddr = (unsigned long)mcm_vaddr +  MCM_PORT_CONFIG_OFFSET;
+	pcr = in_be32((volatile unsigned *)vaddr);
+	pcr |= 1 << (nr + 24);
+	out_be32((volatile unsigned *)vaddr, pcr);
+}
+
+
+static void __init
+smp_86xx_kick_cpu(int nr)
+{
+	unsigned int save_vector;
+	unsigned long target, flags;
+	int n = 0;
+	volatile unsigned int *vector
+		 = (volatile unsigned int *)(KERNELBASE + 0x100);
+
+	if (nr < 0 || nr >= NR_CPUS)
+		return;
+
+	pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr);
+
+	local_irq_save(flags);
+	local_irq_disable();
+
+	/* Save reset vector */
+	save_vector = *vector;
+
+	/* Setup fake reset vector to call __secondary_start_mpc86xx. */
+	target = (unsigned long) __secondary_start_mpc86xx;
+	create_branch((unsigned long)vector, target, BRANCH_SET_LINK);
+
+	/* Kick that CPU */
+	smp_86xx_release_core(nr);
+
+	/* Wait a bit for the CPU to take the exception. */
+	while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000))
+		mdelay(1);
+
+	/* Restore the exception vector */
+	*vector = save_vector;
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+
+	local_irq_restore(flags);
+
+	pr_debug("wait CPU #%d for %d msecs.\n", nr, n);
+}
+
+
+static void __init
+smp_86xx_setup_cpu(int cpu_nr)
+{
+	mpic_setup_this_cpu();
+}
+
+
+struct smp_ops_t smp_86xx_ops = {
+	.message_pass = smp_mpic_message_pass,
+	.probe = smp_mpic_probe,
+	.kick_cpu = smp_86xx_kick_cpu,
+	.setup_cpu = smp_86xx_setup_cpu,
+	.take_timebase = smp_generic_take_timebase,
+	.give_timebase = smp_generic_give_timebase,
+};
+
+
+void __init
+mpc86xx_smp_init(void)
+{
+	smp_ops = &smp_86xx_ops;
+}
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c
new file mode 100644
index 0000000..5180df7
--- /dev/null
+++ b/arch/powerpc/platforms/86xx/pci.c
@@ -0,0 +1,325 @@
+/*
+ * MPC86XX pci setup code
+ *
+ * Recode: ZHANG WEI <wei.zhang@freescale.com>
+ * Initial author: Xianghua Xiao <x.xiao@freescale.com>
+ *
+ * Copyright 2006 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/immap_86xx.h>
+#include <asm/pci-bridge.h>
+#include <sysdev/fsl_soc.h>
+
+#include "mpc86xx.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DBG(fmt, args...)
+#endif
+
+struct pcie_outbound_window_regs {
+	uint    pexotar;               /* 0x.0 - PCI Express outbound translation address register */
+	uint    pexotear;              /* 0x.4 - PCI Express outbound translation extended address register */
+	uint    pexowbar;              /* 0x.8 - PCI Express outbound window base address register */
+	char    res1[4];
+	uint    pexowar;               /* 0x.10 - PCI Express outbound window attributes register */
+	char    res2[12];
+};
+
+struct pcie_inbound_window_regs {
+	uint    pexitar;               /* 0x.0 - PCI Express inbound translation address register */
+	char    res1[4];
+	uint    pexiwbar;              /* 0x.8 - PCI Express inbound window base address register */
+	uint    pexiwbear;             /* 0x.c - PCI Express inbound window base extended address register */
+	uint    pexiwar;               /* 0x.10 - PCI Express inbound window attributes register */
+	char    res2[12];
+};
+
+static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc)
+{
+	volatile struct ccsr_pex *pcie;
+	volatile struct pcie_outbound_window_regs *pcieow;
+	volatile struct pcie_inbound_window_regs *pcieiw;
+	int i = 0;
+
+	DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start,
+			rsrc->end - rsrc->start + 1);
+	pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
+
+	/* Disable all windows (except pexowar0 since its ignored) */
+	pcie->pexowar1 = 0;
+	pcie->pexowar2 = 0;
+ 	pcie->pexowar3 = 0;
+ 	pcie->pexowar4 = 0;
+ 	pcie->pexiwar1 = 0;
+ 	pcie->pexiwar2 = 0;
+ 	pcie->pexiwar3 = 0;
+
+ 	pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1;
+ 	pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1;
+
+ 	/* Setup outbound MEM window */
+ 	for(i = 0; i < 3; i++)
+ 		if (hose->mem_resources[i].flags & IORESOURCE_MEM){
+ 			DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n",
+ 				hose->mem_resources[i].start,
+ 				hose->mem_resources[i].end
+ 				  - hose->mem_resources[i].start + 1);
+ 			pcieow->pexotar = (hose->mem_resources[i].start) >> 12
+ 				& 0x000fffff;
+ 			pcieow->pexotear = 0;
+ 			pcieow->pexowbar = (hose->mem_resources[i].start) >> 12
+ 				& 0x000fffff;
+ 			/* Enable, Mem R/W */
+ 			pcieow->pexowar = 0x80044000 |
+ 				(__ilog2(hose->mem_resources[i].end
+ 					 - hose->mem_resources[i].start + 1)
+ 				 - 1);
+ 			pcieow++;
+ 		}
+
+ 	/* Setup outbound IO window */
+ 	if (hose->io_resource.flags & IORESOURCE_IO){
+ 		DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n",
+ 			hose->io_resource.start,
+ 			hose->io_resource.end - hose->io_resource.start + 1,
+ 			hose->io_base_phys);
+ 		pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff;
+ 		pcieow->pexotear = 0;
+ 		pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff;
+ 		/* Enable, IO R/W */
+ 		pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end
+ 					- hose->io_resource.start + 1) - 1);
+ 	}
+
+ 	/* Setup 2G inbound Memory Window @ 0 */
+ 	pcieiw->pexitar = 0x00000000;
+ 	pcieiw->pexiwbar = 0x00000000;
+ 	/* Enable, Prefetch, Local Mem, Snoop R/W, 2G */
+ 	pcieiw->pexiwar = 0xa0f5501e;
+}
+
+static void __init
+mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size)
+{
+	volatile struct ccsr_pex *pcie;
+	u16 cmd;
+	unsigned int temps;
+
+	DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n",
+			pcie_offset, pcie_size);
+
+	pcie = ioremap(pcie_offset, pcie_size);
+
+	early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd);
+	cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
+	    | PCI_COMMAND_IO;
+	early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd);
+
+	early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80);
+
+	/* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */
+	early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps);
+	temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16);
+	early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps);
+}
+
+int __init add_bridge(struct device_node *dev)
+{
+	int len;
+	struct pci_controller *hose;
+	struct resource rsrc;
+	int *bus_range;
+	int has_address = 0;
+	int primary = 0;
+
+	DBG("Adding PCIE host bridge %s\n", dev->full_name);
+
+	/* Fetch host bridge registers address */
+	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0);
+
+	/* Get bus range if any */
+	bus_range = (int *) get_property(dev, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int))
+		printk(KERN_WARNING "Can't get bus-range for %s, assume"
+		       " bus 0\n", dev->full_name);
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return -ENOMEM;
+	hose->arch_data = dev;
+	hose->set_cfg_type = 1;
+
+	/* last_busno = 0xfe cause by MPC8641 PCIE bug */
+	hose->first_busno = bus_range ? bus_range[0] : 0x0;
+	hose->last_busno = bus_range ? bus_range[1] : 0xfe;
+
+	setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4);
+
+	/* Setup the PCIE host controller. */
+	mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1);
+
+	if ((rsrc.start & 0xfffff) == 0x8000)
+		primary = 1;
+
+	printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. "
+	       "Firmware bus number: %d->%d\n",
+		rsrc.start, hose->first_busno, hose->last_busno);
+
+	DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n",
+		hose, hose->cfg_addr, hose->cfg_data);
+
+	/* Interpret the "ranges" property */
+	/* This also maps the I/O region and sets isa_io/mem_base */
+	pci_process_bridge_OF_ranges(hose, dev, primary);
+
+	/* Setup PEX window registers */
+	setup_pcie_atmu(hose, &rsrc);
+
+	return 0;
+}
+
+static void __devinit quirk_ali1575(struct pci_dev *dev)
+{
+	unsigned short temp;
+
+	/*
+	 * ALI1575 interrupts route table setup:
+	 *
+	 * IRQ pin   IRQ#
+	 * PIRQA ---- 3
+	 * PIRQB ---- 4
+	 * PIRQC ---- 5
+	 * PIRQD ---- 6
+	 * PIRQE ---- 9
+	 * PIRQF ---- 10
+	 * PIRQG ---- 11
+	 * PIRQH ---- 12
+	 *
+	 * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD
+	 *                PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA
+	 */
+	pci_write_config_dword(dev, 0x48, 0xb9317542);
+
+	/* USB 1.1 OHCI controller 1, interrupt: PIRQE */
+	pci_write_config_byte(dev, 0x86, 0x0c);
+
+	/* USB 1.1 OHCI controller 2, interrupt: PIRQF */
+	pci_write_config_byte(dev, 0x87, 0x0d);
+
+	/* USB 1.1 OHCI controller 3, interrupt: PIRQH */
+	pci_write_config_byte(dev, 0x88, 0x0f);
+
+	/* USB 2.0 controller, interrupt: PIRQ7 */
+	pci_write_config_byte(dev, 0x74, 0x06);
+
+	/* Audio controller, interrupt: PIRQE */
+	pci_write_config_byte(dev, 0x8a, 0x0c);
+
+	/* Modem controller, interrupt: PIRQF */
+	pci_write_config_byte(dev, 0x8b, 0x0d);
+
+	/* HD audio controller, interrupt: PIRQG */
+	pci_write_config_byte(dev, 0x8c, 0x0e);
+
+	/* Serial ATA interrupt: PIRQD */
+	pci_write_config_byte(dev, 0x8d, 0x0b);
+
+	/* SMB interrupt: PIRQH */
+	pci_write_config_byte(dev, 0x8e, 0x0f);
+
+	/* PMU ACPI SCI interrupt: PIRQH */
+	pci_write_config_byte(dev, 0x8f, 0x0f);
+
+	/* Primary PATA IDE IRQ: 14
+	 * Secondary PATA IDE IRQ: 15
+	 */
+	pci_write_config_byte(dev, 0x44, 0x3d);
+	pci_write_config_byte(dev, 0x75, 0x0f);
+
+	/* Set IRQ14 and IRQ15 to legacy IRQs */
+	pci_read_config_word(dev, 0x46, &temp);
+	temp |= 0xc000;
+	pci_write_config_word(dev, 0x46, temp);
+
+	/* Set i8259 interrupt trigger
+	 * IRQ 3:  Level
+	 * IRQ 4:  Level
+	 * IRQ 5:  Level
+	 * IRQ 6:  Level
+	 * IRQ 7:  Level
+	 * IRQ 9:  Level
+	 * IRQ 10: Level
+	 * IRQ 11: Level
+	 * IRQ 12: Level
+	 * IRQ 14: Edge
+	 * IRQ 15: Edge
+	 */
+	outb(0xfa, 0x4d0);
+	outb(0x1e, 0x4d1);
+}
+
+static void __devinit quirk_uli5288(struct pci_dev *dev)
+{
+	unsigned char c;
+
+	pci_read_config_byte(dev,0x83,&c);
+	c |= 0x80;
+	pci_write_config_byte(dev, 0x83, c);
+
+	pci_write_config_byte(dev, 0x09, 0x01);
+	pci_write_config_byte(dev, 0x0a, 0x06);
+
+	pci_read_config_byte(dev,0x83,&c);
+	c &= 0x7f;
+	pci_write_config_byte(dev, 0x83, c);
+
+	pci_read_config_byte(dev,0x84,&c);
+	c |= 0x01;
+	pci_write_config_byte(dev, 0x84, c);
+}
+
+static void __devinit quirk_uli5229(struct pci_dev *dev)
+{
+	unsigned short temp;
+	pci_write_config_word(dev, 0x04, 0x0405);
+	pci_read_config_word(dev, 0x4a, &temp);
+	temp |= 0x1000;
+	pci_write_config_word(dev, 0x4a, temp);
+}
+
+static void __devinit early_uli5249(struct pci_dev *dev)
+{
+	unsigned char temp;
+	pci_write_config_word(dev, 0x04, 0x0007);
+	pci_read_config_byte(dev, 0x7c, &temp);
+	pci_write_config_byte(dev, 0x7c, 0x80);
+	pci_write_config_byte(dev, 0x09, 0x01);
+	pci_write_config_byte(dev, 0x7c, temp);
+	dev->class |= 0x1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_ali1575);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249);
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index c4f6b0d..2928636 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_4xx)		+= 4xx/
 obj-$(CONFIG_PPC_83xx)		+= 83xx/
 obj-$(CONFIG_PPC_85xx)		+= 85xx/
+obj-$(CONFIG_PPC_86xx)		+= 86xx/
 obj-$(CONFIG_PPC_PSERIES)	+= pseries/
 obj-$(CONFIG_PPC_ISERIES)	+= iseries/
 obj-$(CONFIG_PPC_MAPLE)		+= maple/
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 6a02d51..352bbba 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -5,15 +5,24 @@
 	tristate "SPU file system"
 	default m
 	depends on PPC_CELL
+	select SPU_BASE
 	help
 	  The SPU file system is used to access Synergistic Processing
 	  Units on machines implementing the Broadband Processor
 	  Architecture.
 
+config SPU_BASE
+	bool
+	default n
+
 config SPUFS_MMAP
 	bool
 	depends on SPU_FS && SPARSEMEM
 	select MEMORY_HOTPLUG
 	default y
 
+config CBE_RAS
+	bool "RAS features for bare metal Cell BE"
+	default y
+
 endmenu
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index e570bad..c89cdd6 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -1,16 +1,15 @@
-obj-y			+= interrupt.o iommu.o setup.o spider-pic.o
-obj-y			+= pervasive.o
+obj-$(CONFIG_PPC_CELL_NATIVE)		+= interrupt.o iommu.o setup.o \
+					   cbe_regs.o spider-pic.o pervasive.o
+obj-$(CONFIG_CBE_RAS)			+= ras.o
 
-obj-$(CONFIG_SMP)	+= smp.o
-obj-$(CONFIG_SPU_FS)	+= spu-base.o spufs/
-
-spu-base-y		+= spu_base.o spu_priv1.o
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_PPC_CELL_NATIVE)		+= smp.o
+endif
 
 # needed only when building loadable spufs.ko
-spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o
-obj-y			+= $(spufs-modular-m)
+spufs-modular-$(CONFIG_SPU_FS)		+= spu_syscalls.o
+spu-priv1-$(CONFIG_PPC_CELL_NATIVE)	+= spu_priv1_mmio.o
 
-# always needed in kernel
-spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o
-obj-y			+= $(spufs-builtin-y) $(spufs-builtin-m)
-
+obj-$(CONFIG_SPU_BASE)			+= spu_callbacks.o spu_base.o \
+					   $(spufs-modular-m) \
+					   $(spu-priv1-y) spufs/
diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c
new file mode 100644
index 0000000..ce696c1
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_regs.c
@@ -0,0 +1,128 @@
+/*
+ * cbe_regs.c
+ *
+ * Accessor routines for the various MMIO register blocks of the CBE
+ *
+ * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ */
+
+
+#include <linux/config.h>
+#include <linux/percpu.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/ptrace.h>
+
+#include "cbe_regs.h"
+
+#define MAX_CBE		2
+
+/*
+ * Current implementation uses "cpu" nodes. We build our own mapping
+ * array of cpu numbers to cpu nodes locally for now to allow interrupt
+ * time code to have a fast path rather than call of_get_cpu_node(). If
+ * we implement cpu hotplug, we'll have to install an appropriate norifier
+ * in order to release references to the cpu going away
+ */
+static struct cbe_regs_map
+{
+	struct device_node *cpu_node;
+	struct cbe_pmd_regs __iomem *pmd_regs;
+	struct cbe_iic_regs __iomem *iic_regs;
+} cbe_regs_maps[MAX_CBE];
+static int cbe_regs_map_count;
+
+static struct cbe_thread_map
+{
+	struct device_node *cpu_node;
+	struct cbe_regs_map *regs;
+} cbe_thread_map[NR_CPUS];
+
+static struct cbe_regs_map *cbe_find_map(struct device_node *np)
+{
+	int i;
+
+	for (i = 0; i < cbe_regs_map_count; i++)
+		if (cbe_regs_maps[i].cpu_node == np)
+			return &cbe_regs_maps[i];
+	return NULL;
+}
+
+struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np)
+{
+	struct cbe_regs_map *map = cbe_find_map(np);
+	if (map == NULL)
+		return NULL;
+	return map->pmd_regs;
+}
+
+struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu)
+{
+	struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+	if (map == NULL)
+		return NULL;
+	return map->pmd_regs;
+}
+
+
+struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np)
+{
+	struct cbe_regs_map *map = cbe_find_map(np);
+	if (map == NULL)
+		return NULL;
+	return map->iic_regs;
+}
+struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu)
+{
+	struct cbe_regs_map *map = cbe_thread_map[cpu].regs;
+	if (map == NULL)
+		return NULL;
+	return map->iic_regs;
+}
+
+void __init cbe_regs_init(void)
+{
+	int i;
+	struct device_node *cpu;
+
+	/* Build local fast map of CPUs */
+	for_each_possible_cpu(i)
+		cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL);
+
+	/* Find maps for each device tree CPU */
+	for_each_node_by_type(cpu, "cpu") {
+		struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++];
+
+		/* That hack must die die die ! */
+		struct address_prop {
+			unsigned long address;
+			unsigned int len;
+		} __attribute__((packed)) *prop;
+
+
+		if (cbe_regs_map_count > MAX_CBE) {
+			printk(KERN_ERR "cbe_regs: More BE chips than supported"
+			       "!\n");
+			cbe_regs_map_count--;
+			return;
+		}
+		map->cpu_node = cpu;
+		for_each_possible_cpu(i)
+			if (cbe_thread_map[i].cpu_node == cpu)
+				cbe_thread_map[i].regs = map;
+
+		prop = (struct address_prop *)get_property(cpu, "pervasive",
+							   NULL);
+		if (prop != NULL)
+			map->pmd_regs = ioremap(prop->address, prop->len);
+
+		prop = (struct address_prop *)get_property(cpu, "iic",
+							   NULL);
+		if (prop != NULL)
+			map->iic_regs = ioremap(prop->address, prop->len);
+	}
+}
+
diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h
new file mode 100644
index 0000000..e76e4a6
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_regs.h
@@ -0,0 +1,129 @@
+/*
+ * cbe_regs.h
+ *
+ * This file is intended to hold the various register definitions for CBE
+ * on-chip system devices (memory controller, IO controller, etc...)
+ *
+ * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ */
+
+#ifndef CBE_REGS_H
+#define CBE_REGS_H
+
+/*
+ *
+ * Some HID register definitions
+ *
+ */
+
+/* CBE specific HID0 bits */
+#define HID0_CBE_THERM_WAKEUP	0x0000020000000000ul
+#define HID0_CBE_SYSERR_WAKEUP	0x0000008000000000ul
+#define HID0_CBE_THERM_INT_EN	0x0000000400000000ul
+#define HID0_CBE_SYSERR_INT_EN	0x0000000200000000ul
+
+
+/*
+ *
+ * Pervasive unit register definitions
+ *
+ */
+
+struct cbe_pmd_regs {
+	u8 pad_0x0000_0x0800[0x0800 - 0x0000];			/* 0x0000 */
+
+	/* Thermal Sensor Registers */
+	u64  ts_ctsr1;						/* 0x0800 */
+	u64  ts_ctsr2;						/* 0x0808 */
+	u64  ts_mtsr1;						/* 0x0810 */
+	u64  ts_mtsr2;						/* 0x0818 */
+	u64  ts_itr1;						/* 0x0820 */
+	u64  ts_itr2;						/* 0x0828 */
+	u64  ts_gitr;						/* 0x0830 */
+	u64  ts_isr;						/* 0x0838 */
+	u64  ts_imr;						/* 0x0840 */
+	u64  tm_cr1;						/* 0x0848 */
+	u64  tm_cr2;						/* 0x0850 */
+	u64  tm_simr;						/* 0x0858 */
+	u64  tm_tpr;						/* 0x0860 */
+	u64  tm_str1;						/* 0x0868 */
+	u64  tm_str2;						/* 0x0870 */
+	u64  tm_tsr;						/* 0x0878 */
+
+	/* Power Management */
+	u64  pm_control;					/* 0x0880 */
+#define CBE_PMD_PAUSE_ZERO_CONTROL		0x10000
+	u64  pm_status;						/* 0x0888 */
+
+	/* Time Base Register */
+	u64  tbr;						/* 0x0890 */
+
+	u8   pad_0x0898_0x0c00 [0x0c00 - 0x0898];		/* 0x0898 */
+
+	/* Fault Isolation Registers */
+	u64  checkstop_fir;					/* 0x0c00 */
+	u64  recoverable_fir;
+	u64  spec_att_mchk_fir;
+	u64  fir_mode_reg;
+	u64  fir_enable_mask;
+
+	u8   pad_0x0c28_0x1000 [0x1000 - 0x0c28];		/* 0x0c28 */
+};
+
+extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np);
+extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu);
+
+/*
+ *
+ * IIC unit register definitions
+ *
+ */
+
+struct cbe_iic_pending_bits {
+	u32 data;
+	u8 flags;
+	u8 class;
+	u8 source;
+	u8 prio;
+};
+
+#define CBE_IIC_IRQ_VALID	0x80
+#define CBE_IIC_IRQ_IPI		0x40
+
+struct cbe_iic_thread_regs {
+	struct cbe_iic_pending_bits pending;
+	struct cbe_iic_pending_bits pending_destr;
+	u64 generate;
+	u64 prio;
+};
+
+struct cbe_iic_regs {
+	u8	pad_0x0000_0x0400[0x0400 - 0x0000];		/* 0x0000 */
+
+	/* IIC interrupt registers */
+	struct	cbe_iic_thread_regs thread[2];			/* 0x0400 */
+	u64     iic_ir;						/* 0x0440 */
+	u64     iic_is;						/* 0x0448 */
+
+	u8	pad_0x0450_0x0500[0x0500 - 0x0450];		/* 0x0450 */
+
+	/* IOC FIR */
+	u64	ioc_fir_reset;					/* 0x0500 */
+	u64	ioc_fir_set;
+	u64	ioc_checkstop_enable;
+	u64	ioc_fir_error_mask;
+	u64	ioc_syserr_enable;
+	u64	ioc_fir;
+
+	u8	pad_0x0530_0x1000[0x1000 - 0x0530];		/* 0x0530 */
+};
+
+extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np);
+extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu);
+
+
+/* Init this module early */
+extern void cbe_regs_init(void);
+
+
+#endif /* CBE_REGS_H */
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c
index 978be1c..1bbf822 100644
--- a/arch/powerpc/platforms/cell/interrupt.c
+++ b/arch/powerpc/platforms/cell/interrupt.c
@@ -33,29 +33,10 @@
 #include <asm/ptrace.h>
 
 #include "interrupt.h"
-
-struct iic_pending_bits {
-	u32 data;
-	u8 flags;
-	u8 class;
-	u8 source;
-	u8 prio;
-};
-
-enum iic_pending_flags {
-	IIC_VALID = 0x80,
-	IIC_IPI   = 0x40,
-};
-
-struct iic_regs {
-	struct iic_pending_bits pending;
-	struct iic_pending_bits pending_destr;
-	u64 generate;
-	u64 prio;
-};
+#include "cbe_regs.h"
 
 struct iic {
-	struct iic_regs __iomem *regs;
+	struct cbe_iic_thread_regs __iomem *regs;
 	u8 target_id;
 };
 
@@ -115,7 +96,7 @@
 	.end = iic_end,
 };
 
-static int iic_external_get_irq(struct iic_pending_bits pending)
+static int iic_external_get_irq(struct cbe_iic_pending_bits pending)
 {
 	int irq;
 	unsigned char node, unit;
@@ -136,8 +117,7 @@
 		 * One of these units can be connected
 		 * to an external interrupt controller.
 		 */
-		if (pending.prio > 0x3f ||
-		    pending.class != 2)
+		if (pending.class != 2)
 			break;
 		irq = IIC_EXT_OFFSET
 			+ spider_get_irq(node)
@@ -168,15 +148,15 @@
 {
 	struct iic *iic;
 	int irq;
-	struct iic_pending_bits pending;
+	struct cbe_iic_pending_bits pending;
 
 	iic = &__get_cpu_var(iic);
 	*(unsigned long *) &pending = 
 		in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
 
 	irq = -1;
-	if (pending.flags & IIC_VALID) {
-		if (pending.flags & IIC_IPI) {
+	if (pending.flags & CBE_IIC_IRQ_VALID) {
+		if (pending.flags & CBE_IIC_IRQ_IPI) {
 			irq = IIC_IPI_OFFSET + (pending.prio >> 4);
 /*
 			if (irq > 0x80)
@@ -200,7 +180,7 @@
 	unsigned long regs;
 	struct iic *iic;
 
-	for_each_cpu(cpu) {
+	for_each_possible_cpu(cpu) {
 		iic = &per_cpu(iic, cpu);
 		nodeid = cpu/2;
 
@@ -226,7 +206,7 @@
 			regs += 0x20;
 
 		printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
-		iic->regs = ioremap(regs, sizeof(struct iic_regs));
+		iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs));
 		iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
 	}
 
@@ -267,12 +247,12 @@
 		}
 
  		iic = &per_cpu(iic, np[0]);
- 		iic->regs = ioremap(regs[0], sizeof(struct iic_regs));
+ 		iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs));
 		iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
  		printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);
 
  		iic = &per_cpu(iic, np[1]);
- 		iic->regs = ioremap(regs[2], sizeof(struct iic_regs));
+ 		iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs));
 		iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
  		printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);
 
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index a49ceb7..a35004e 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -473,6 +473,16 @@
 	return mask < 0x100000000ull;
 }
 
+static struct dma_mapping_ops cell_iommu_ops = {
+	.alloc_coherent = cell_alloc_coherent,
+	.free_coherent = cell_free_coherent,
+	.map_single = cell_map_single,
+	.unmap_single = cell_unmap_single,
+	.map_sg = cell_map_sg,
+	.unmap_sg = cell_unmap_sg,
+	.dma_supported = cell_dma_supported,
+};
+
 void cell_init_iommu(void)
 {
 	int setup_bus = 0;
@@ -498,11 +508,5 @@
 		}
 	}
 
-	pci_dma_ops.alloc_coherent = cell_alloc_coherent;
-	pci_dma_ops.free_coherent = cell_free_coherent;
-	pci_dma_ops.map_single = cell_map_single;
-	pci_dma_ops.unmap_single = cell_unmap_single;
-	pci_dma_ops.map_sg = cell_map_sg;
-	pci_dma_ops.unmap_sg = cell_unmap_sg;
-	pci_dma_ops.dma_supported = cell_dma_supported;
+	pci_dma_ops = cell_iommu_ops;
 }
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 7eed8c6..695ac4e 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -37,36 +37,28 @@
 #include <asm/reg.h>
 
 #include "pervasive.h"
+#include "cbe_regs.h"
 
 static DEFINE_SPINLOCK(cbe_pervasive_lock);
-struct cbe_pervasive {
-	struct pmd_regs __iomem *regs;
-	unsigned int thread;
-};
-
-/* can't use per_cpu from setup_arch */
-static struct cbe_pervasive cbe_pervasive[NR_CPUS];
 
 static void __init cbe_enable_pause_zero(void)
 {
 	unsigned long thread_switch_control;
 	unsigned long temp_register;
-	struct cbe_pervasive *p;
-	int thread;
+	struct cbe_pmd_regs __iomem *pregs;
 
 	spin_lock_irq(&cbe_pervasive_lock);
-	p = &cbe_pervasive[smp_processor_id()];
-
-	if (!cbe_pervasive->regs)
+	pregs = cbe_get_cpu_pmd_regs(smp_processor_id());
+	if (pregs == NULL)
 		goto out;
 
 	pr_debug("Power Management: CPU %d\n", smp_processor_id());
 
 	 /* Enable Pause(0) control bit */
-	temp_register = in_be64(&p->regs->pm_control);
+	temp_register = in_be64(&pregs->pm_control);
 
-	out_be64(&p->regs->pm_control,
-		 temp_register|PMD_PAUSE_ZERO_CONTROL);
+	out_be64(&pregs->pm_control,
+		 temp_register | CBE_PMD_PAUSE_ZERO_CONTROL);
 
 	/* Enable DEC and EE interrupt request */
 	thread_switch_control  = mfspr(SPRN_TSC_CELL);
@@ -75,25 +67,16 @@
 	switch ((mfspr(SPRN_CTRLF) & CTRL_CT)) {
 	case CTRL_CT0:
 		thread_switch_control |= TSC_CELL_DEC_ENABLE_0;
-		thread = 0;
 		break;
 	case CTRL_CT1:
 		thread_switch_control |= TSC_CELL_DEC_ENABLE_1;
-		thread = 1;
 		break;
 	default:
 		printk(KERN_WARNING "%s: unknown configuration\n",
 			__FUNCTION__);
-		thread = -1;
 		break;
 	}
 
-	if (p->thread != thread)
-		printk(KERN_WARNING "%s: device tree inconsistant, "
-				     "cpu %i: %d/%d\n", __FUNCTION__,
-				     smp_processor_id(),
-				     p->thread, thread);
-
 	mtspr(SPRN_TSC_CELL, thread_switch_control);
 
 out:
@@ -104,6 +87,11 @@
 {
 	unsigned long ctrl;
 
+	/* Why do we do that on every idle ? Couldn't that be done once for
+	 * all or do we lose the state some way ? Also, the pm_control
+	 * register setting, that can't be set once at boot ? We really want
+	 * to move that away in order to implement a simple powersave
+	 */
 	cbe_enable_pause_zero();
 
 	while (1) {
@@ -152,8 +140,15 @@
 		timer_interrupt(regs);
 		break;
 	case SRR1_WAKEMT:
-		/* no action required */
 		break;
+#ifdef CONFIG_CBE_RAS
+	case SRR1_WAKESYSERR:
+		cbe_system_error_exception(regs);
+		break;
+	case SRR1_WAKETHERM:
+		cbe_thermal_exception(regs);
+		break;
+#endif /* CONFIG_CBE_RAS */
 	default:
 		/* do system reset */
 		return 0;
@@ -162,68 +157,11 @@
 	return 1;
 }
 
-static int __init cbe_find_pmd_mmio(int cpu, struct cbe_pervasive *p)
+void __init cbe_pervasive_init(void)
 {
-	struct device_node *node;
-	unsigned int *int_servers;
-	char *addr;
-	unsigned long real_address;
-	unsigned int size;
-
-	struct pmd_regs __iomem *pmd_mmio_area;
-	int hardid, thread;
-	int proplen;
-
-	pmd_mmio_area = NULL;
-	hardid = get_hard_smp_processor_id(cpu);
-	for (node = NULL; (node = of_find_node_by_type(node, "cpu"));) {
-		int_servers = (void *) get_property(node,
-				"ibm,ppc-interrupt-server#s", &proplen);
-		if (!int_servers) {
-			printk(KERN_WARNING "%s misses "
-				"ibm,ppc-interrupt-server#s property",
-				node->full_name);
-			continue;
-		}
-		for (thread = 0; thread < proplen / sizeof (int); thread++) {
-			if (hardid == int_servers[thread]) {
-				addr = get_property(node, "pervasive", NULL);
-				goto found;
-			}
-		}
-	}
-
-	printk(KERN_WARNING "%s: CPU %d not found\n", __FUNCTION__, cpu);
-	return -EINVAL;
-
-found:
-	real_address = *(unsigned long*) addr;
-	addr += sizeof (unsigned long);
-	size = *(unsigned int*) addr;
-
-	pr_debug("pervasive area for CPU %d at %lx, size %x\n",
-			cpu, real_address, size);
-	p->regs = ioremap(real_address, size);
-	p->thread = thread;
-	return 0;
-}
-
-void __init cell_pervasive_init(void)
-{
-	struct cbe_pervasive *p;
-	int cpu;
-	int ret;
-
 	if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
 		return;
 
-	for_each_possible_cpu(cpu) {
-		p = &cbe_pervasive[cpu];
-		ret = cbe_find_pmd_mmio(cpu, p);
-		if (ret)
-			return;
-	}
-
 	ppc_md.idle_loop = cbe_idle;
 	ppc_md.system_reset_exception = cbe_system_reset_exception;
 }
diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h
index da1fb85..7b50947 100644
--- a/arch/powerpc/platforms/cell/pervasive.h
+++ b/arch/powerpc/platforms/cell/pervasive.h
@@ -25,38 +25,9 @@
 #ifndef PERVASIVE_H
 #define PERVASIVE_H
 
-struct pmd_regs {
-	u8 pad_0x0000_0x0800[0x0800 - 0x0000];			/* 0x0000 */
-
-	/* Thermal Sensor Registers */
-	u64  ts_ctsr1;						/* 0x0800 */
-	u64  ts_ctsr2;						/* 0x0808 */
-	u64  ts_mtsr1;						/* 0x0810 */
-	u64  ts_mtsr2;						/* 0x0818 */
-	u64  ts_itr1;						/* 0x0820 */
-	u64  ts_itr2;						/* 0x0828 */
-	u64  ts_gitr;						/* 0x0830 */
-	u64  ts_isr;						/* 0x0838 */
-	u64  ts_imr;						/* 0x0840 */
-	u64  tm_cr1;						/* 0x0848 */
-	u64  tm_cr2;						/* 0x0850 */
-	u64  tm_simr;						/* 0x0858 */
-	u64  tm_tpr;						/* 0x0860 */
-	u64  tm_str1;						/* 0x0868 */
-	u64  tm_str2;						/* 0x0870 */
-	u64  tm_tsr;						/* 0x0878 */
-
-	/* Power Management */
-	u64  pm_control;					/* 0x0880 */
-#define PMD_PAUSE_ZERO_CONTROL		0x10000
-	u64  pm_status;						/* 0x0888 */
-
-	/* Time Base Register */
-	u64  tbr;						/* 0x0890 */
-
-	u8   pad_0x0898_0x1000 [0x1000 - 0x0898];		/* 0x0898 */
-};
-
-void __init cell_pervasive_init(void);
+extern void cbe_pervasive_init(void);
+extern void cbe_system_error_exception(struct pt_regs *regs);
+extern void cbe_maintenance_exception(struct pt_regs *regs);
+extern void cbe_thermal_exception(struct pt_regs *regs);
 
 #endif
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
new file mode 100644
index 0000000..033ad6e
--- /dev/null
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -0,0 +1,112 @@
+#define DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+#include "ras.h"
+#include "cbe_regs.h"
+
+
+static void dump_fir(int cpu)
+{
+	struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu);
+	struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu);
+
+	if (pregs == NULL)
+		return;
+
+	/* Todo: do some nicer parsing of bits and based on them go down
+	 * to other sub-units FIRs and not only IIC
+	 */
+	printk(KERN_ERR "Global Checkstop FIR    : 0x%016lx\n",
+	       in_be64(&pregs->checkstop_fir));
+	printk(KERN_ERR "Global Recoverable FIR  : 0x%016lx\n",
+	       in_be64(&pregs->checkstop_fir));
+	printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n",
+	       in_be64(&pregs->spec_att_mchk_fir));
+
+	if (iregs == NULL)
+		return;
+	printk(KERN_ERR "IOC FIR                 : 0x%016lx\n",
+	       in_be64(&iregs->ioc_fir));
+
+}
+
+void cbe_system_error_exception(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu);
+	dump_fir(cpu);
+	dump_stack();
+}
+
+void cbe_maintenance_exception(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	/*
+	 * Nothing implemented for the maintenance interrupt at this point
+	 */
+
+	printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu);
+	dump_stack();
+}
+
+void cbe_thermal_exception(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	/*
+	 * Nothing implemented for the thermal interrupt at this point
+	 */
+
+	printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu);
+	dump_stack();
+}
+
+static int cbe_machine_check_handler(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+
+	printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu);
+	dump_fir(cpu);
+
+	/* No recovery from this code now, lets continue */
+	return 0;
+}
+
+void __init cbe_ras_init(void)
+{
+	unsigned long hid0;
+
+	/*
+	 * Enable System Error & thermal interrupts and wakeup conditions
+	 */
+
+	hid0 = mfspr(SPRN_HID0);
+	hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP |
+		HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP;
+	mtspr(SPRN_HID0, hid0);
+	mb();
+
+	/*
+	 * Install machine check handler. Leave setting of precise mode to
+	 * what the firmware did for now
+	 */
+	ppc_md.machine_check_exception = cbe_machine_check_handler;
+	mb();
+
+	/*
+	 * For now, we assume that IOC_FIR is already set to forward some
+	 * error conditions to the System Error handler. If that is not true
+	 * then it will have to be fixed up here.
+	 */
+}
diff --git a/arch/powerpc/platforms/cell/ras.h b/arch/powerpc/platforms/cell/ras.h
new file mode 100644
index 0000000..eb7ee54
--- /dev/null
+++ b/arch/powerpc/platforms/cell/ras.h
@@ -0,0 +1,9 @@
+#ifndef RAS_H
+#define RAS_H
+
+extern void cbe_system_error_exception(struct pt_regs *regs);
+extern void cbe_maintenance_exception(struct pt_regs *regs);
+extern void cbe_thermal_exception(struct pt_regs *regs);
+extern void cbe_ras_init(void);
+
+#endif /* RAS_H */
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index fd3e560..3d1831d 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -49,10 +49,13 @@
 #include <asm/ppc-pci.h>
 #include <asm/irq.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 
 #include "interrupt.h"
 #include "iommu.h"
+#include "cbe_regs.h"
 #include "pervasive.h"
+#include "ras.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -81,6 +84,15 @@
 {
 	ppc_md.init_IRQ       = iic_init_IRQ;
 	ppc_md.get_irq        = iic_get_irq;
+#ifdef CONFIG_SPU_BASE
+	spu_priv1_ops         = &spu_priv1_mmio_ops;
+#endif
+
+	cbe_regs_init();
+
+#ifdef CONFIG_CBE_RAS
+	cbe_ras_init();
+#endif
 
 #ifdef CONFIG_SMP
 	smp_init_cell();
@@ -98,7 +110,7 @@
 	init_pci_config_tokens();
 	find_and_init_phbs();
 	spider_init_IRQ();
-	cell_pervasive_init();
+	cbe_pervasive_init();
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index ad141fe..db82f50 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -34,10 +34,15 @@
 #include <asm/prom.h>
 #include <linux/mutex.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 #include <asm/mmu_context.h>
 
 #include "interrupt.h"
 
+const struct spu_priv1_ops *spu_priv1_ops;
+
+EXPORT_SYMBOL_GPL(spu_priv1_ops);
+
 static int __spu_trap_invalid_dma(struct spu *spu)
 {
 	pr_debug("%s\n", __FUNCTION__);
@@ -71,7 +76,7 @@
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
 	struct mm_struct *mm = spu->mm;
-	u64 esid, vsid;
+	u64 esid, vsid, llp;
 
 	pr_debug("%s\n", __FUNCTION__);
 
@@ -91,9 +96,14 @@
 	}
 
 	esid = (ea & ESID_MASK) | SLB_ESID_V;
-	vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) | SLB_VSID_USER;
+#ifdef CONFIG_HUGETLB_PAGE
 	if (in_hugepage_area(mm->context, ea))
-		vsid |= SLB_VSID_L;
+		llp = mmu_psize_defs[mmu_huge_psize].sllp;
+	else
+#endif
+		llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+	vsid = (get_vsid(mm->context.id, ea) << SLB_VSID_SHIFT) |
+			SLB_VSID_USER | llp;
 
 	out_be64(&priv2->slb_index_W, spu->slb_replace);
 	out_be64(&priv2->slb_vsid_RW, vsid);
@@ -130,57 +140,7 @@
 	spu->dar = ea;
 	spu->dsisr = dsisr;
 	mb();
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_mailbox(struct spu *spu)
-{
-	if (spu->ibox_callback)
-		spu->ibox_callback(spu);
-
-	/* atomically disable SPU mailbox interrupts */
-	spin_lock(&spu->register_lock);
-	spu_int_mask_and(spu, 2, ~0x1);
-	spin_unlock(&spu->register_lock);
-	return 0;
-}
-
-static int __spu_trap_stop(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->stop_code = in_be32(&spu->problem->spu_status_R);
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_halt(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->stop_code = in_be32(&spu->problem->spu_status_R);
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_tag_group(struct spu *spu)
-{
-	pr_debug("%s\n", __FUNCTION__);
-	spu->mfc_callback(spu);
-	return 0;
-}
-
-static int __spu_trap_spubox(struct spu *spu)
-{
-	if (spu->wbox_callback)
-		spu->wbox_callback(spu);
-
-	/* atomically disable SPU mailbox interrupts */
-	spin_lock(&spu->register_lock);
-	spu_int_mask_and(spu, 2, ~0x10);
-	spin_unlock(&spu->register_lock);
+	spu->stop_callback(spu);
 	return 0;
 }
 
@@ -191,8 +151,7 @@
 
 	spu = data;
 	spu->class_0_pending = 1;
-	if (spu->stop_callback)
-		spu->stop_callback(spu);
+	spu->stop_callback(spu);
 
 	return IRQ_HANDLED;
 }
@@ -270,29 +229,38 @@
 	unsigned long mask;
 
 	spu = data;
+	spin_lock(&spu->register_lock);
 	stat = spu_int_stat_get(spu, 2);
 	mask = spu_int_mask_get(spu, 2);
+	/* ignore interrupts we're not waiting for */
+	stat &= mask;
+	/*
+	 * mailbox interrupts (0x1 and 0x10) are level triggered.
+	 * mask them now before acknowledging.
+	 */
+	if (stat & 0x11)
+		spu_int_mask_and(spu, 2, ~(stat & 0x11));
+	/* acknowledge all interrupts before the callbacks */
+	spu_int_stat_clear(spu, 2, stat);
+	spin_unlock(&spu->register_lock);
 
 	pr_debug("class 2 interrupt %d, %lx, %lx\n", irq, stat, mask);
 
-	stat &= mask;
-
 	if (stat & 1)  /* PPC core mailbox */
-		__spu_trap_mailbox(spu);
+		spu->ibox_callback(spu);
 
 	if (stat & 2) /* SPU stop-and-signal */
-		__spu_trap_stop(spu);
+		spu->stop_callback(spu);
 
 	if (stat & 4) /* SPU halted */
-		__spu_trap_halt(spu);
+		spu->stop_callback(spu);
 
 	if (stat & 8) /* DMA tag group complete */
-		__spu_trap_tag_group(spu);
+		spu->mfc_callback(spu);
 
 	if (stat & 0x10) /* SPU mailbox threshold */
-		__spu_trap_spubox(spu);
+		spu->wbox_callback(spu);
 
-	spu_int_stat_clear(spu, 2, stat);
 	return stat ? IRQ_HANDLED : IRQ_NONE;
 }
 
@@ -512,14 +480,6 @@
 	return ret;
 }
 
-void spu_irq_setaffinity(struct spu *spu, int cpu)
-{
-	u64 target = iic_get_target_id(cpu);
-	u64 route = target << 48 | target << 32 | target << 16;
-	spu_int_route_set(spu, route);
-}
-EXPORT_SYMBOL_GPL(spu_irq_setaffinity);
-
 static int __init find_spu_node_id(struct device_node *spe)
 {
 	unsigned int *id;
@@ -649,6 +609,46 @@
 	return ret;
 }
 
+struct sysdev_class spu_sysdev_class = {
+	set_kset_name("spu")
+};
+
+static ssize_t spu_show_isrc(struct sys_device *sysdev, char *buf)
+{
+	struct spu *spu = container_of(sysdev, struct spu, sysdev);
+	return sprintf(buf, "%d\n", spu->isrc);
+
+}
+static SYSDEV_ATTR(isrc, 0400, spu_show_isrc, NULL);
+
+extern int attach_sysdev_to_node(struct sys_device *dev, int nid);
+
+static int spu_create_sysdev(struct spu *spu)
+{
+	int ret;
+
+	spu->sysdev.id = spu->number;
+	spu->sysdev.cls = &spu_sysdev_class;
+	ret = sysdev_register(&spu->sysdev);
+	if (ret) {
+		printk(KERN_ERR "Can't register SPU %d with sysfs\n",
+				spu->number);
+		return ret;
+	}
+
+	sysdev_create_file(&spu->sysdev, &attr_isrc);
+	sysfs_add_device_to_node(&spu->sysdev, spu->nid);
+
+	return 0;
+}
+
+static void spu_destroy_sysdev(struct spu *spu)
+{
+	sysdev_remove_file(&spu->sysdev, &attr_isrc);
+	sysfs_remove_device_from_node(&spu->sysdev, spu->nid);
+	sysdev_unregister(&spu->sysdev);
+}
+
 static int __init create_spu(struct device_node *spe)
 {
 	struct spu *spu;
@@ -656,7 +656,7 @@
 	static int number;
 
 	ret = -ENOMEM;
-	spu = kmalloc(sizeof (*spu), GFP_KERNEL);
+	spu = kzalloc(sizeof (*spu), GFP_KERNEL);
 	if (!spu)
 		goto out;
 
@@ -668,33 +668,20 @@
 	spu->nid = of_node_to_nid(spe);
 	if (spu->nid == -1)
 		spu->nid = 0;
-
-	spu->stop_code = 0;
-	spu->slb_replace = 0;
-	spu->mm = NULL;
-	spu->ctx = NULL;
-	spu->rq = NULL;
-	spu->pid = 0;
-	spu->class_0_pending = 0;
-	spu->flags = 0UL;
-	spu->dar = 0UL;
-	spu->dsisr = 0UL;
 	spin_lock_init(&spu->register_lock);
-
 	spu_mfc_sdr_set(spu, mfspr(SPRN_SDR1));
 	spu_mfc_sr1_set(spu, 0x33);
-
-	spu->ibox_callback = NULL;
-	spu->wbox_callback = NULL;
-	spu->stop_callback = NULL;
-	spu->mfc_callback = NULL;
-
 	mutex_lock(&spu_mutex);
+
 	spu->number = number++;
 	ret = spu_request_irqs(spu);
 	if (ret)
 		goto out_unmap;
 
+	ret = spu_create_sysdev(spu);
+	if (ret)
+		goto out_free_irqs;
+
 	list_add(&spu->list, &spu_list);
 	mutex_unlock(&spu_mutex);
 
@@ -703,6 +690,9 @@
 		spu->problem, spu->priv1, spu->priv2, spu->number);
 	goto out;
 
+out_free_irqs:
+	spu_free_irqs(spu);
+
 out_unmap:
 	mutex_unlock(&spu_mutex);
 	spu_unmap(spu);
@@ -716,6 +706,7 @@
 {
 	list_del_init(&spu->list);
 
+	spu_destroy_sysdev(spu);
 	spu_free_irqs(spu);
 	spu_unmap(spu);
 	kfree(spu);
@@ -728,6 +719,7 @@
 	list_for_each_entry_safe(spu, tmp, &spu_list, list)
 		destroy_spu(spu);
 	mutex_unlock(&spu_mutex);
+	sysdev_class_unregister(&spu_sysdev_class);
 }
 module_exit(cleanup_spu_base);
 
@@ -736,6 +728,11 @@
 	struct device_node *node;
 	int ret;
 
+	/* create sysdev class for spus */
+	ret = sysdev_class_register(&spu_sysdev_class);
+	if (ret)
+		return ret;
+
 	ret = -ENODEV;
 	for (node = of_find_node_by_type(NULL, "spe");
 			node; node = of_find_node_by_type(node, "spe")) {
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c
index b47fcc5..47ec3be 100644
--- a/arch/powerpc/platforms/cell/spu_callbacks.c
+++ b/arch/powerpc/platforms/cell/spu_callbacks.c
@@ -34,307 +34,19 @@
  */
 
 void *spu_syscall_table[] = {
-	[__NR_restart_syscall]		sys_ni_syscall, /* sys_restart_syscall */
-	[__NR_exit]			sys_ni_syscall, /* sys_exit */
-	[__NR_fork]			sys_ni_syscall, /* ppc_fork */
-	[__NR_read]			sys_read,
-	[__NR_write]			sys_write,
-	[__NR_open]			sys_open,
-	[__NR_close]			sys_close,
-	[__NR_waitpid]			sys_waitpid,
-	[__NR_creat]			sys_creat,
-	[__NR_link]			sys_link,
-	[__NR_unlink]			sys_unlink,
-	[__NR_execve]			sys_ni_syscall, /* sys_execve */
-	[__NR_chdir]			sys_chdir,
-	[__NR_time]			sys_time,
-	[__NR_mknod]			sys_mknod,
-	[__NR_chmod]			sys_chmod,
-	[__NR_lchown]			sys_lchown,
-	[__NR_break]			sys_ni_syscall,
-	[__NR_oldstat]			sys_ni_syscall,
-	[__NR_lseek]			sys_lseek,
-	[__NR_getpid]			sys_getpid,
-	[__NR_mount]			sys_ni_syscall, /* sys_mount */
-	[__NR_umount]			sys_ni_syscall,
-	[__NR_setuid]			sys_setuid,
-	[__NR_getuid]			sys_getuid,
-	[__NR_stime]			sys_stime,
-	[__NR_ptrace]			sys_ni_syscall, /* sys_ptrace */
-	[__NR_alarm]			sys_alarm,
-	[__NR_oldfstat]			sys_ni_syscall,
-	[__NR_pause]			sys_ni_syscall, /* sys_pause */
-	[__NR_utime]			sys_ni_syscall, /* sys_utime */
-	[__NR_stty]			sys_ni_syscall,
-	[__NR_gtty]			sys_ni_syscall,
-	[__NR_access]			sys_access,
-	[__NR_nice]			sys_nice,
-	[__NR_ftime]			sys_ni_syscall,
-	[__NR_sync]			sys_sync,
-	[__NR_kill]			sys_kill,
-	[__NR_rename]			sys_rename,
-	[__NR_mkdir]			sys_mkdir,
-	[__NR_rmdir]			sys_rmdir,
-	[__NR_dup]			sys_dup,
-	[__NR_pipe]			sys_pipe,
-	[__NR_times]			sys_times,
-	[__NR_prof]			sys_ni_syscall,
-	[__NR_brk]			sys_brk,
-	[__NR_setgid]			sys_setgid,
-	[__NR_getgid]			sys_getgid,
-	[__NR_signal]			sys_ni_syscall, /* sys_signal */
-	[__NR_geteuid]			sys_geteuid,
-	[__NR_getegid]			sys_getegid,
-	[__NR_acct]			sys_ni_syscall, /* sys_acct */
-	[__NR_umount2]			sys_ni_syscall, /* sys_umount */
-	[__NR_lock]			sys_ni_syscall,
-	[__NR_ioctl]			sys_ioctl,
-	[__NR_fcntl]			sys_fcntl,
-	[__NR_mpx]			sys_ni_syscall,
-	[__NR_setpgid]			sys_setpgid,
-	[__NR_ulimit]			sys_ni_syscall,
-	[__NR_oldolduname]		sys_ni_syscall,
-	[__NR_umask]			sys_umask,
-	[__NR_chroot]			sys_chroot,
-	[__NR_ustat]			sys_ni_syscall, /* sys_ustat */
-	[__NR_dup2]			sys_dup2,
-	[__NR_getppid]			sys_getppid,
-	[__NR_getpgrp]			sys_getpgrp,
-	[__NR_setsid]			sys_setsid,
-	[__NR_sigaction]		sys_ni_syscall,
-	[__NR_sgetmask]			sys_sgetmask,
-	[__NR_ssetmask]			sys_ssetmask,
-	[__NR_setreuid]			sys_setreuid,
-	[__NR_setregid]			sys_setregid,
-	[__NR_sigsuspend]		sys_ni_syscall,
-	[__NR_sigpending]		sys_ni_syscall,
-	[__NR_sethostname]		sys_sethostname,
-	[__NR_setrlimit]		sys_setrlimit,
-	[__NR_getrlimit]		sys_ni_syscall,
-	[__NR_getrusage]		sys_getrusage,
-	[__NR_gettimeofday]		sys_gettimeofday,
-	[__NR_settimeofday]		sys_settimeofday,
-	[__NR_getgroups]		sys_getgroups,
-	[__NR_setgroups]		sys_setgroups,
-	[__NR_select]			sys_ni_syscall,
-	[__NR_symlink]			sys_symlink,
-	[__NR_oldlstat]			sys_ni_syscall,
-	[__NR_readlink]			sys_readlink,
-	[__NR_uselib]			sys_ni_syscall, /* sys_uselib */
-	[__NR_swapon]			sys_ni_syscall, /* sys_swapon */
-	[__NR_reboot]			sys_ni_syscall, /* sys_reboot */
-	[__NR_readdir]			sys_ni_syscall,
-	[__NR_mmap]			sys_mmap,
-	[__NR_munmap]			sys_munmap,
-	[__NR_truncate]			sys_truncate,
-	[__NR_ftruncate]		sys_ftruncate,
-	[__NR_fchmod]			sys_fchmod,
-	[__NR_fchown]			sys_fchown,
-	[__NR_getpriority]		sys_getpriority,
-	[__NR_setpriority]		sys_setpriority,
-	[__NR_profil]			sys_ni_syscall,
-	[__NR_statfs]			sys_ni_syscall, /* sys_statfs */
-	[__NR_fstatfs]			sys_ni_syscall, /* sys_fstatfs */
-	[__NR_ioperm]			sys_ni_syscall,
-	[__NR_socketcall]		sys_socketcall,
-	[__NR_syslog]			sys_syslog,
-	[__NR_setitimer]		sys_setitimer,
-	[__NR_getitimer]		sys_getitimer,
-	[__NR_stat]			sys_newstat,
-	[__NR_lstat]			sys_newlstat,
-	[__NR_fstat]			sys_newfstat,
-	[__NR_olduname]			sys_ni_syscall,
-	[__NR_iopl]			sys_ni_syscall,
-	[__NR_vhangup]			sys_vhangup,
-	[__NR_idle]			sys_ni_syscall,
-	[__NR_vm86]			sys_ni_syscall,
-	[__NR_wait4]			sys_wait4,
-	[__NR_swapoff]			sys_ni_syscall, /* sys_swapoff */
-	[__NR_sysinfo]			sys_sysinfo,
-	[__NR_ipc]			sys_ni_syscall, /* sys_ipc */
-	[__NR_fsync]			sys_fsync,
-	[__NR_sigreturn]		sys_ni_syscall,
-	[__NR_clone]			sys_ni_syscall, /* ppc_clone */
-	[__NR_setdomainname]		sys_setdomainname,
-	[__NR_uname]			ppc_newuname,
-	[__NR_modify_ldt]		sys_ni_syscall,
-	[__NR_adjtimex]			sys_adjtimex,
-	[__NR_mprotect]			sys_mprotect,
-	[__NR_sigprocmask]		sys_ni_syscall,
-	[__NR_create_module]		sys_ni_syscall,
-	[__NR_init_module]		sys_ni_syscall, /* sys_init_module */
-	[__NR_delete_module]		sys_ni_syscall, /* sys_delete_module */
-	[__NR_get_kernel_syms]		sys_ni_syscall,
-	[__NR_quotactl]			sys_ni_syscall, /* sys_quotactl */
-	[__NR_getpgid]			sys_getpgid,
-	[__NR_fchdir]			sys_fchdir,
-	[__NR_bdflush]			sys_bdflush,
-	[__NR_sysfs]			sys_ni_syscall, /* sys_sysfs */
-	[__NR_personality]		ppc64_personality,
-	[__NR_afs_syscall]		sys_ni_syscall,
-	[__NR_setfsuid]			sys_setfsuid,
-	[__NR_setfsgid]			sys_setfsgid,
-	[__NR__llseek]			sys_llseek,
-	[__NR_getdents]			sys_getdents,
-	[__NR__newselect]		sys_select,
-	[__NR_flock]			sys_flock,
-	[__NR_msync]			sys_msync,
-	[__NR_readv]			sys_readv,
-	[__NR_writev]			sys_writev,
-	[__NR_getsid]			sys_getsid,
-	[__NR_fdatasync]		sys_fdatasync,
-	[__NR__sysctl]			sys_ni_syscall, /* sys_sysctl */
-	[__NR_mlock]			sys_mlock,
-	[__NR_munlock]			sys_munlock,
-	[__NR_mlockall]			sys_mlockall,
-	[__NR_munlockall]		sys_munlockall,
-	[__NR_sched_setparam]		sys_sched_setparam,
-	[__NR_sched_getparam]		sys_sched_getparam,
-	[__NR_sched_setscheduler]	sys_sched_setscheduler,
-	[__NR_sched_getscheduler]	sys_sched_getscheduler,
-	[__NR_sched_yield]		sys_sched_yield,
-	[__NR_sched_get_priority_max]	sys_sched_get_priority_max,
-	[__NR_sched_get_priority_min]	sys_sched_get_priority_min,
-	[__NR_sched_rr_get_interval]	sys_sched_rr_get_interval,
-	[__NR_nanosleep]		sys_nanosleep,
-	[__NR_mremap]			sys_mremap,
-	[__NR_setresuid]		sys_setresuid,
-	[__NR_getresuid]		sys_getresuid,
-	[__NR_query_module]		sys_ni_syscall,
-	[__NR_poll]			sys_poll,
-	[__NR_nfsservctl]		sys_ni_syscall, /* sys_nfsservctl */
-	[__NR_setresgid]		sys_setresgid,
-	[__NR_getresgid]		sys_getresgid,
-	[__NR_prctl]			sys_prctl,
-	[__NR_rt_sigreturn]		sys_ni_syscall, /* ppc64_rt_sigreturn */
-	[__NR_rt_sigaction]		sys_ni_syscall, /* sys_rt_sigaction */
-	[__NR_rt_sigprocmask]		sys_ni_syscall, /* sys_rt_sigprocmask */
-	[__NR_rt_sigpending]		sys_ni_syscall, /* sys_rt_sigpending */
-	[__NR_rt_sigtimedwait]		sys_ni_syscall, /* sys_rt_sigtimedwait */
-	[__NR_rt_sigqueueinfo]		sys_ni_syscall, /* sys_rt_sigqueueinfo */
-	[__NR_rt_sigsuspend]		sys_ni_syscall, /* sys_rt_sigsuspend */
-	[__NR_pread64]			sys_pread64,
-	[__NR_pwrite64]			sys_pwrite64,
-	[__NR_chown]			sys_chown,
-	[__NR_getcwd]			sys_getcwd,
-	[__NR_capget]			sys_capget,
-	[__NR_capset]			sys_capset,
-	[__NR_sigaltstack]		sys_ni_syscall, /* sys_sigaltstack */
-	[__NR_sendfile]			sys_sendfile64,
-	[__NR_getpmsg]			sys_ni_syscall,
-	[__NR_putpmsg]			sys_ni_syscall,
-	[__NR_vfork]			sys_ni_syscall, /* ppc_vfork */
-	[__NR_ugetrlimit]		sys_getrlimit,
-	[__NR_readahead]		sys_readahead,
-	[192]				sys_ni_syscall,
-	[193]				sys_ni_syscall,
-	[194]				sys_ni_syscall,
-	[195]				sys_ni_syscall,
-	[196]				sys_ni_syscall,
-	[197]				sys_ni_syscall,
-	[__NR_pciconfig_read]		sys_ni_syscall, /* sys_pciconfig_read */
-	[__NR_pciconfig_write]		sys_ni_syscall, /* sys_pciconfig_write */
-	[__NR_pciconfig_iobase]		sys_ni_syscall, /* sys_pciconfig_iobase */
-	[__NR_multiplexer]		sys_ni_syscall,
-	[__NR_getdents64]		sys_getdents64,
-	[__NR_pivot_root]		sys_pivot_root,
-	[204]				sys_ni_syscall,
-	[__NR_madvise]			sys_madvise,
-	[__NR_mincore]			sys_mincore,
-	[__NR_gettid]			sys_gettid,
-	[__NR_tkill]			sys_tkill,
-	[__NR_setxattr]			sys_setxattr,
-	[__NR_lsetxattr]		sys_lsetxattr,
-	[__NR_fsetxattr]		sys_fsetxattr,
-	[__NR_getxattr]			sys_getxattr,
-	[__NR_lgetxattr]		sys_lgetxattr,
-	[__NR_fgetxattr]		sys_fgetxattr,
-	[__NR_listxattr]		sys_listxattr,
-	[__NR_llistxattr]		sys_llistxattr,
-	[__NR_flistxattr]		sys_flistxattr,
-	[__NR_removexattr]		sys_removexattr,
-	[__NR_lremovexattr]		sys_lremovexattr,
-	[__NR_fremovexattr]		sys_fremovexattr,
-	[__NR_futex]			sys_futex,
-	[__NR_sched_setaffinity]	sys_sched_setaffinity,
-	[__NR_sched_getaffinity]	sys_sched_getaffinity,
-	[224]				sys_ni_syscall,
-	[__NR_tuxcall]			sys_ni_syscall,
-	[226]				sys_ni_syscall,
-	[__NR_io_setup]			sys_io_setup,
-	[__NR_io_destroy]		sys_io_destroy,
-	[__NR_io_getevents]		sys_io_getevents,
-	[__NR_io_submit]		sys_io_submit,
-	[__NR_io_cancel]		sys_io_cancel,
-	[__NR_set_tid_address]		sys_ni_syscall, /* sys_set_tid_address */
-	[__NR_fadvise64]		sys_fadvise64,
-	[__NR_exit_group]		sys_ni_syscall, /* sys_exit_group */
-	[__NR_lookup_dcookie]		sys_ni_syscall, /* sys_lookup_dcookie */
-	[__NR_epoll_create]		sys_epoll_create,
-	[__NR_epoll_ctl]		sys_epoll_ctl,
-	[__NR_epoll_wait]		sys_epoll_wait,
-	[__NR_remap_file_pages]		sys_remap_file_pages,
-	[__NR_timer_create]		sys_timer_create,
-	[__NR_timer_settime]		sys_timer_settime,
-	[__NR_timer_gettime]		sys_timer_gettime,
-	[__NR_timer_getoverrun]		sys_timer_getoverrun,
-	[__NR_timer_delete]		sys_timer_delete,
-	[__NR_clock_settime]		sys_clock_settime,
-	[__NR_clock_gettime]		sys_clock_gettime,
-	[__NR_clock_getres]		sys_clock_getres,
-	[__NR_clock_nanosleep]		sys_clock_nanosleep,
-	[__NR_swapcontext]		sys_ni_syscall, /* ppc64_swapcontext */
-	[__NR_tgkill]			sys_tgkill,
-	[__NR_utimes]			sys_utimes,
-	[__NR_statfs64]			sys_statfs64,
-	[__NR_fstatfs64]		sys_fstatfs64,
-	[254]				sys_ni_syscall,
-	[__NR_rtas]			ppc_rtas,
-	[256]				sys_ni_syscall,
-	[257]				sys_ni_syscall,
-	[258]				sys_ni_syscall,
-	[__NR_mbind]			sys_ni_syscall, /* sys_mbind */
-	[__NR_get_mempolicy]		sys_ni_syscall, /* sys_get_mempolicy */
-	[__NR_set_mempolicy]		sys_ni_syscall, /* sys_set_mempolicy */
-	[__NR_mq_open]			sys_ni_syscall, /* sys_mq_open */
-	[__NR_mq_unlink]		sys_ni_syscall, /* sys_mq_unlink */
-	[__NR_mq_timedsend]		sys_ni_syscall, /* sys_mq_timedsend */
-	[__NR_mq_timedreceive]		sys_ni_syscall, /* sys_mq_timedreceive */
-	[__NR_mq_notify]		sys_ni_syscall, /* sys_mq_notify */
-	[__NR_mq_getsetattr]		sys_ni_syscall, /* sys_mq_getsetattr */
-	[__NR_kexec_load]		sys_ni_syscall, /* sys_kexec_load */
-	[__NR_add_key]			sys_ni_syscall, /* sys_add_key */
-	[__NR_request_key]		sys_ni_syscall, /* sys_request_key */
-	[__NR_keyctl]			sys_ni_syscall, /* sys_keyctl */
-	[__NR_waitid]			sys_ni_syscall, /* sys_waitid */
-	[__NR_ioprio_set]		sys_ni_syscall, /* sys_ioprio_set */
-	[__NR_ioprio_get]		sys_ni_syscall, /* sys_ioprio_get */
-	[__NR_inotify_init]		sys_ni_syscall, /* sys_inotify_init */
-	[__NR_inotify_add_watch]	sys_ni_syscall, /* sys_inotify_add_watch */
-	[__NR_inotify_rm_watch]		sys_ni_syscall, /* sys_inotify_rm_watch */
-	[__NR_spu_run]			sys_ni_syscall, /* sys_spu_run */
-	[__NR_spu_create]		sys_ni_syscall, /* sys_spu_create */
-	[__NR_pselect6]			sys_ni_syscall, /* sys_pselect */
-	[__NR_ppoll]			sys_ni_syscall, /* sys_ppoll */
-	[__NR_unshare]			sys_unshare,
-	[__NR_splice]			sys_splice,
-	[__NR_tee]			sys_tee,
-	[__NR_vmsplice]			sys_vmsplice,
-	[__NR_openat]			sys_openat,
-	[__NR_mkdirat]			sys_mkdirat,
-	[__NR_mknodat]			sys_mknodat,
-	[__NR_fchownat]			sys_fchownat,
-	[__NR_futimesat]		sys_futimesat,
-	[__NR_newfstatat]		sys_newfstatat,
-	[__NR_unlinkat]			sys_unlinkat,
-	[__NR_renameat]			sys_renameat,
-	[__NR_linkat]			sys_linkat,
-	[__NR_symlinkat]		sys_symlinkat,
-	[__NR_readlinkat]		sys_readlinkat,
-	[__NR_fchmodat]			sys_fchmodat,
-	[__NR_faccessat]		sys_faccessat,
-	[__NR_get_robust_list]		sys_get_robust_list,
-	[__NR_set_robust_list]		sys_set_robust_list,
+#define SYSCALL(func)		sys_ni_syscall,
+#define COMPAT_SYS(func)	sys_ni_syscall,
+#define PPC_SYS(func)		sys_ni_syscall,
+#define OLDSYS(func)		sys_ni_syscall,
+#define SYS32ONLY(func)		sys_ni_syscall,
+#define SYSX(f, f3264, f32)	sys_ni_syscall,
+
+#define SYSCALL_SPU(func)	sys_##func,
+#define COMPAT_SYS_SPU(func)	sys_##func,
+#define PPC_SYS_SPU(func)	ppc_##func,
+#define SYSX_SPU(f, f3264, f32)	f,
+
+#include <asm/systbl.h>
 };
 
 long spu_sys_callback(struct spu_syscall_block *s)
diff --git a/arch/powerpc/platforms/cell/spu_priv1.c b/arch/powerpc/platforms/cell/spu_priv1.c
deleted file mode 100644
index b265642..0000000
--- a/arch/powerpc/platforms/cell/spu_priv1.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * access to SPU privileged registers
- */
-#include <linux/module.h>
-
-#include <asm/io.h>
-#include <asm/spu.h>
-
-void spu_int_mask_and(struct spu *spu, int class, u64 mask)
-{
-	u64 old_mask;
-
-	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
-	out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_and);
-
-void spu_int_mask_or(struct spu *spu, int class, u64 mask)
-{
-	u64 old_mask;
-
-	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
-	out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_or);
-
-void spu_int_mask_set(struct spu *spu, int class, u64 mask)
-{
-	out_be64(&spu->priv1->int_mask_RW[class], mask);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_set);
-
-u64 spu_int_mask_get(struct spu *spu, int class)
-{
-	return in_be64(&spu->priv1->int_mask_RW[class]);
-}
-EXPORT_SYMBOL_GPL(spu_int_mask_get);
-
-void spu_int_stat_clear(struct spu *spu, int class, u64 stat)
-{
-	out_be64(&spu->priv1->int_stat_RW[class], stat);
-}
-EXPORT_SYMBOL_GPL(spu_int_stat_clear);
-
-u64 spu_int_stat_get(struct spu *spu, int class)
-{
-	return in_be64(&spu->priv1->int_stat_RW[class]);
-}
-EXPORT_SYMBOL_GPL(spu_int_stat_get);
-
-void spu_int_route_set(struct spu *spu, u64 route)
-{
-	out_be64(&spu->priv1->int_route_RW, route);
-}
-EXPORT_SYMBOL_GPL(spu_int_route_set);
-
-u64 spu_mfc_dar_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_dar_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dar_get);
-
-u64 spu_mfc_dsisr_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_dsisr_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_get);
-
-void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr)
-{
-	out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_dsisr_set);
-
-void spu_mfc_sdr_set(struct spu *spu, u64 sdr)
-{
-	out_be64(&spu->priv1->mfc_sdr_RW, sdr);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sdr_set);
-
-void spu_mfc_sr1_set(struct spu *spu, u64 sr1)
-{
-	out_be64(&spu->priv1->mfc_sr1_RW, sr1);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_set);
-
-u64 spu_mfc_sr1_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_sr1_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_sr1_get);
-
-void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
-{
-	out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_set);
-
-u64 spu_mfc_tclass_id_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->mfc_tclass_id_RW);
-}
-EXPORT_SYMBOL_GPL(spu_mfc_tclass_id_get);
-
-void spu_tlb_invalidate(struct spu *spu)
-{
-	out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
-}
-EXPORT_SYMBOL_GPL(spu_tlb_invalidate);
-
-void spu_resource_allocation_groupID_set(struct spu *spu, u64 id)
-{
-	out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_set);
-
-u64 spu_resource_allocation_groupID_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->resource_allocation_groupID_RW);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_groupID_get);
-
-void spu_resource_allocation_enable_set(struct spu *spu, u64 enable)
-{
-	out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_set);
-
-u64 spu_resource_allocation_enable_get(struct spu *spu)
-{
-	return in_be64(&spu->priv1->resource_allocation_enable_RW);
-}
-EXPORT_SYMBOL_GPL(spu_resource_allocation_enable_get);
diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
new file mode 100644
index 0000000..71b69f0
--- /dev/null
+++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c
@@ -0,0 +1,159 @@
+/*
+ * spu hypervisor abstraction for direct hardware access.
+ *
+ *  (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *  Copyright 2006 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/spu.h>
+#include <asm/spu_priv1.h>
+
+#include "interrupt.h"
+
+static void int_mask_and(struct spu *spu, int class, u64 mask)
+{
+	u64 old_mask;
+
+	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+	out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask);
+}
+
+static void int_mask_or(struct spu *spu, int class, u64 mask)
+{
+	u64 old_mask;
+
+	old_mask = in_be64(&spu->priv1->int_mask_RW[class]);
+	out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask);
+}
+
+static void int_mask_set(struct spu *spu, int class, u64 mask)
+{
+	out_be64(&spu->priv1->int_mask_RW[class], mask);
+}
+
+static u64 int_mask_get(struct spu *spu, int class)
+{
+	return in_be64(&spu->priv1->int_mask_RW[class]);
+}
+
+static void int_stat_clear(struct spu *spu, int class, u64 stat)
+{
+	out_be64(&spu->priv1->int_stat_RW[class], stat);
+}
+
+static u64 int_stat_get(struct spu *spu, int class)
+{
+	return in_be64(&spu->priv1->int_stat_RW[class]);
+}
+
+static void cpu_affinity_set(struct spu *spu, int cpu)
+{
+	u64 target = iic_get_target_id(cpu);
+	u64 route = target << 48 | target << 32 | target << 16;
+	out_be64(&spu->priv1->int_route_RW, route);
+}
+
+static u64 mfc_dar_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_dar_RW);
+}
+
+static u64 mfc_dsisr_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_dsisr_RW);
+}
+
+static void mfc_dsisr_set(struct spu *spu, u64 dsisr)
+{
+	out_be64(&spu->priv1->mfc_dsisr_RW, dsisr);
+}
+
+static void mfc_sdr_set(struct spu *spu, u64 sdr)
+{
+	out_be64(&spu->priv1->mfc_sdr_RW, sdr);
+}
+
+static void mfc_sr1_set(struct spu *spu, u64 sr1)
+{
+	out_be64(&spu->priv1->mfc_sr1_RW, sr1);
+}
+
+static u64 mfc_sr1_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_sr1_RW);
+}
+
+static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id)
+{
+	out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id);
+}
+
+static u64 mfc_tclass_id_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->mfc_tclass_id_RW);
+}
+
+static void tlb_invalidate(struct spu *spu)
+{
+	out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul);
+}
+
+static void resource_allocation_groupID_set(struct spu *spu, u64 id)
+{
+	out_be64(&spu->priv1->resource_allocation_groupID_RW, id);
+}
+
+static u64 resource_allocation_groupID_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->resource_allocation_groupID_RW);
+}
+
+static void resource_allocation_enable_set(struct spu *spu, u64 enable)
+{
+	out_be64(&spu->priv1->resource_allocation_enable_RW, enable);
+}
+
+static u64 resource_allocation_enable_get(struct spu *spu)
+{
+	return in_be64(&spu->priv1->resource_allocation_enable_RW);
+}
+
+const struct spu_priv1_ops spu_priv1_mmio_ops =
+{
+	.int_mask_and = int_mask_and,
+	.int_mask_or = int_mask_or,
+	.int_mask_set = int_mask_set,
+	.int_mask_get = int_mask_get,
+	.int_stat_clear = int_stat_clear,
+	.int_stat_get = int_stat_get,
+	.cpu_affinity_set = cpu_affinity_set,
+	.mfc_dar_get = mfc_dar_get,
+	.mfc_dsisr_get = mfc_dsisr_get,
+	.mfc_dsisr_set = mfc_dsisr_set,
+	.mfc_sdr_set = mfc_sdr_set,
+	.mfc_sr1_set = mfc_sr1_set,
+	.mfc_sr1_get = mfc_sr1_get,
+	.mfc_tclass_id_set = mfc_tclass_id_set,
+	.mfc_tclass_id_get = mfc_tclass_id_get,
+	.tlb_invalidate = tlb_invalidate,
+	.resource_allocation_groupID_set = resource_allocation_groupID_set,
+	.resource_allocation_groupID_get = resource_allocation_groupID_get,
+	.resource_allocation_enable_set = resource_allocation_enable_set,
+	.resource_allocation_enable_get = resource_allocation_enable_get,
+};
diff --git a/arch/powerpc/platforms/cell/spufs/Makefile b/arch/powerpc/platforms/cell/spufs/Makefile
index a7cddf4..bb5dc63 100644
--- a/arch/powerpc/platforms/cell/spufs/Makefile
+++ b/arch/powerpc/platforms/cell/spufs/Makefile
@@ -1,5 +1,7 @@
+obj-y += switch.o
+
 obj-$(CONFIG_SPU_FS) += spufs.o
-spufs-y += inode.o file.o context.o switch.o syscalls.o
+spufs-y += inode.o file.o context.o syscalls.o
 spufs-y += sched.o backing_ops.o hw_ops.o run.o
 
 # Rules to build switch.o with the help of SPU tool chain
@@ -8,11 +10,14 @@
 SPU_AS		:= $(SPU_CROSS)gcc
 SPU_LD		:= $(SPU_CROSS)ld
 SPU_OBJCOPY	:= $(SPU_CROSS)objcopy
-SPU_CFLAGS	:= -O2 -Wall -I$(srctree)/include -I$(objtree)/include2
-SPU_AFLAGS	:= -c -D__ASSEMBLY__ -I$(srctree)/include -I$(objtree)/include2
+SPU_CFLAGS	:= -O2 -Wall -I$(srctree)/include \
+		   -I$(objtree)/include2 -D__KERNEL__
+SPU_AFLAGS	:= -c -D__ASSEMBLY__ -I$(srctree)/include \
+		   -I$(objtree)/include2 -D__KERNEL__
 SPU_LDFLAGS	:= -N -Ttext=0x0
 
 $(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h
+clean-files := spu_save_dump.h spu_restore_dump.h
 
 # Compile SPU files
       cmd_spu_cc = $(SPU_CC) $(SPU_CFLAGS) -c -o $@ $<
@@ -45,7 +50,8 @@
 		echo " * Hex-dump auto generated from $*.c." ; \
 		echo " * Do not edit!" ; \
 		echo " */" ; \
-		echo "static unsigned int $*_code[] __page_aligned = {" ; \
+		echo "static unsigned int $*_code[] " \
+			"__attribute__((__aligned__(128))) = {" ; \
 		hexdump -v -e '"0x" 4/1 "%02x" "," "\n"' $< ; \
 		echo "};" ; \
 		) > $@
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 8bb33ab..36439c5 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -30,7 +30,7 @@
 struct spu_context *alloc_spu_context(void)
 {
 	struct spu_context *ctx;
-	ctx = kmalloc(sizeof *ctx, GFP_KERNEL);
+	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
 	if (!ctx)
 		goto out;
 	/* Binding to physical processor deferred
@@ -48,17 +48,7 @@
 	init_waitqueue_head(&ctx->wbox_wq);
 	init_waitqueue_head(&ctx->stop_wq);
 	init_waitqueue_head(&ctx->mfc_wq);
-	ctx->ibox_fasync = NULL;
-	ctx->wbox_fasync = NULL;
-	ctx->mfc_fasync = NULL;
-	ctx->mfc = NULL;
-	ctx->tagwait = 0;
 	ctx->state = SPU_STATE_SAVED;
-	ctx->local_store = NULL;
-	ctx->cntl = NULL;
-	ctx->signal1 = NULL;
-	ctx->signal2 = NULL;
-	ctx->spu = NULL;
 	ctx->ops = &spu_backing_ops;
 	ctx->owner = get_task_mm(current);
 	goto out;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 366185e..7854a38 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -825,6 +825,55 @@
 					spufs_signal2_type_set, "%llu");
 
 #ifdef CONFIG_SPUFS_MMAP
+static struct page *spufs_mss_mmap_nopage(struct vm_area_struct *vma,
+					   unsigned long address, int *type)
+{
+	return spufs_ps_nopage(vma, address, type, 0x0000);
+}
+
+static struct vm_operations_struct spufs_mss_mmap_vmops = {
+	.nopage = spufs_mss_mmap_nopage,
+};
+
+/*
+ * mmap support for problem state MFC DMA area [0x0000 - 0x0fff].
+ * Mapping this area requires that the application have CAP_SYS_RAWIO,
+ * as these registers require special care when read/writing.
+ */
+static int spufs_mss_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
+	vma->vm_flags |= VM_RESERVED;
+	vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
+				     | _PAGE_NO_CACHE);
+
+	vma->vm_ops = &spufs_mss_mmap_vmops;
+	return 0;
+}
+#endif
+
+static int spufs_mss_open(struct inode *inode, struct file *file)
+{
+	struct spufs_inode_info *i = SPUFS_I(inode);
+
+	file->private_data = i->i_ctx;
+	return nonseekable_open(inode, file);
+}
+
+static struct file_operations spufs_mss_fops = {
+	.open	 = spufs_mss_open,
+#ifdef CONFIG_SPUFS_MMAP
+	.mmap	 = spufs_mss_mmap,
+#endif
+};
+
+
+#ifdef CONFIG_SPUFS_MMAP
 static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma,
 					   unsigned long address, int *type)
 {
@@ -1101,7 +1150,7 @@
 	return mask;
 }
 
-static int spufs_mfc_flush(struct file *file)
+static int spufs_mfc_flush(struct file *file, fl_owner_t id)
 {
 	struct spu_context *ctx = file->private_data;
 	int ret;
@@ -1127,7 +1176,7 @@
 static int spufs_mfc_fsync(struct file *file, struct dentry *dentry,
 			   int datasync)
 {
-	return spufs_mfc_flush(file);
+	return spufs_mfc_flush(file, NULL);
 }
 
 static int spufs_mfc_fasync(int fd, struct file *file, int on)
@@ -1279,6 +1328,22 @@
 DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
 			"%llx\n")
 
+static u64 spufs_id_get(void *data)
+{
+	struct spu_context *ctx = data;
+	u64 num;
+
+	spu_acquire(ctx);
+	if (ctx->state == SPU_STATE_RUNNABLE)
+		num = ctx->spu->number;
+	else
+		num = (unsigned int)-1;
+	spu_release(ctx);
+
+	return num;
+}
+DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, 0, "0x%llx\n")
+
 struct tree_descr spufs_dir_contents[] = {
 	{ "mem",  &spufs_mem_fops,  0666, },
 	{ "regs", &spufs_regs_fops,  0666, },
@@ -1292,6 +1357,7 @@
 	{ "signal2", &spufs_signal2_fops, 0666, },
 	{ "signal1_type", &spufs_signal1_type, 0666, },
 	{ "signal2_type", &spufs_signal2_type, 0666, },
+	{ "mss", &spufs_mss_fops, 0666, },
 	{ "mfc", &spufs_mfc_fops, 0666, },
 	{ "cntl", &spufs_cntl_fops,  0666, },
 	{ "npc", &spufs_npc_ops, 0666, },
@@ -1301,5 +1367,6 @@
 	{ "spu_tag_mask", &spufs_spu_tag_mask_ops, 0666, },
 	{ "event_mask", &spufs_event_mask_ops, 0666, },
 	{ "srr0", &spufs_srr0_ops, 0666, },
+	{ "phys-id", &spufs_id_ops, 0666, },
 	{},
 };
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c
index a13a8b5..ede2cac 100644
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -32,6 +32,7 @@
 
 #include <asm/io.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 #include <asm/spu_csa.h>
 #include <asm/mmu_context.h>
 #include "spufs.h"
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index d955419..7b45728 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -157,20 +157,12 @@
 	mutex_unlock(&dir->d_inode->i_mutex);
 }
 
+/* Caller must hold root->i_mutex */
 static int spufs_rmdir(struct inode *root, struct dentry *dir_dentry)
 {
-	struct spu_context *ctx;
-
 	/* remove all entries */
-	mutex_lock(&root->i_mutex);
 	spufs_prune_dir(dir_dentry);
-	mutex_unlock(&root->i_mutex);
 
-	/* We have to give up the mm_struct */
-	ctx = SPUFS_I(dir_dentry->d_inode)->i_ctx;
-	spu_forget(ctx);
-
-	/* XXX Do we need to hold i_mutex here ? */
 	return simple_rmdir(root, dir_dentry);
 }
 
@@ -199,16 +191,23 @@
 
 static int spufs_dir_close(struct inode *inode, struct file *file)
 {
+	struct spu_context *ctx;
 	struct inode *dir;
 	struct dentry *dentry;
 	int ret;
 
 	dentry = file->f_dentry;
 	dir = dentry->d_parent->d_inode;
+	ctx = SPUFS_I(dentry->d_inode)->i_ctx;
 
+	mutex_lock(&dir->i_mutex);
 	ret = spufs_rmdir(dir, dentry);
+	mutex_unlock(&dir->i_mutex);
 	WARN_ON(ret);
 
+	/* We have to give up the mm_struct */
+	spu_forget(ctx);
+
 	return dcache_dir_close(inode, file);
 }
 
@@ -305,6 +304,10 @@
 	    nd->dentry != nd->dentry->d_sb->s_root)
 		goto out;
 
+	/* all flags are reserved */
+	if (flags)
+		goto out;
+
 	dentry = lookup_create(nd, 1);
 	ret = PTR_ERR(dentry);
 	if (IS_ERR(dentry))
@@ -324,8 +327,13 @@
 	 * in error path of *_open().
 	 */
 	ret = spufs_context_open(dget(dentry), mntget(nd->mnt));
-	if (ret < 0)
-		spufs_rmdir(nd->dentry->d_inode, dentry);
+	if (ret < 0) {
+		WARN_ON(spufs_rmdir(nd->dentry->d_inode, dentry));
+		mutex_unlock(&nd->dentry->d_inode->i_mutex);
+		spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
+		dput(dentry);
+		goto out;
+	}
 
 out_dput:
 	dput(dentry);
@@ -428,11 +436,11 @@
 	return spufs_create_root(sb, data);
 }
 
-static struct super_block *
+static int
 spufs_get_sb(struct file_system_type *fstype, int flags,
-		const char *name, void *data)
+		const char *name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fstype, flags, data, spufs_fill_super);
+	return get_sb_single(fstype, flags, data, spufs_fill_super, mnt);
 }
 
 static struct file_system_type spufs_type = {
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c
index bf652cd..3dcc5d8 100644
--- a/arch/powerpc/platforms/cell/spufs/sched.c
+++ b/arch/powerpc/platforms/cell/spufs/sched.c
@@ -43,6 +43,7 @@
 #include <asm/mmu_context.h>
 #include <asm/spu.h>
 #include <asm/spu_csa.h>
+#include <asm/spu_priv1.h>
 #include "spufs.h"
 
 #define SPU_MIN_TIMESLICE 	(100 * HZ / 1000)
@@ -363,7 +364,7 @@
 	 * We're likely to wait for interrupts on the same
 	 * CPU that we are now on, so send them here.
 	 */
-	spu_irq_setaffinity(spu, raw_smp_processor_id());
+	spu_cpu_affinity_set(spu, raw_smp_processor_id());
 	put_active_spu(spu);
 	return 0;
 }
diff --git a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
index 1b2355f..15183d2 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
+++ b/arch/powerpc/platforms/cell/spufs/spu_restore_dump.h_shipped
@@ -3,229 +3,901 @@
  * Hex-dump auto generated from spu_restore.c.
  * Do not edit!
  */
-static unsigned int spu_restore_code[] __page_aligned = {
-0x40800000, 0x409ff801, 0x24000080, 0x24fd8081,
-0x1cd80081, 0x33001180, 0x42030003, 0x33800284,
-0x1c010204, 0x40200000, 0x40200000, 0x40200000,
-0x34000190, 0x34004191, 0x34008192, 0x3400c193,
-0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffa85,
-0x3080a000, 0x3080a201, 0x3080a402, 0x3080a603,
-0x3080a804, 0x3080aa05, 0x3080ac06, 0x3080ae07,
-0x3080b008, 0x3080b209, 0x3080b40a, 0x3080b60b,
-0x3080b80c, 0x3080ba0d, 0x3080bc0e, 0x3080be0f,
-0x00003ffc, 0x00000000, 0x00000000, 0x00000000,
-0x01a00182, 0x3ec00083, 0xb0a14103, 0x01a00204,
-0x3ec10082, 0x4202800e, 0x04000703, 0xb0a14202,
-0x21a00803, 0x3fbf028d, 0x3f20068d, 0x3fbe0682,
-0x3fe30102, 0x21a00882, 0x3f82028f, 0x3fe3078f,
-0x3fbf0784, 0x3f200204, 0x3fbe0204, 0x3fe30204,
-0x04000203, 0x21a00903, 0x40848002, 0x21a00982,
-0x40800003, 0x21a00a03, 0x40802002, 0x21a00a82,
-0x21a00083, 0x40800082, 0x21a00b02, 0x10002818,
-0x40a80002, 0x32800007, 0x4207000c, 0x18008208,
-0x40a0000b, 0x4080020a, 0x40800709, 0x00200000,
-0x42070002, 0x3ac30384, 0x1cffc489, 0x00200000,
-0x18008383, 0x38830382, 0x4cffc486, 0x3ac28185,
-0xb0408584, 0x28830382, 0x1c020387, 0x38828182,
-0xb0408405, 0x1802c408, 0x28828182, 0x217ff886,
-0x04000583, 0x21a00803, 0x3fbe0682, 0x3fe30102,
-0x04000106, 0x21a00886, 0x04000603, 0x21a00903,
-0x40803c02, 0x21a00982, 0x40800003, 0x04000184,
-0x21a00a04, 0x40802202, 0x21a00a82, 0x42028005,
-0x34208702, 0x21002282, 0x21a00804, 0x21a00886,
-0x3fbf0782, 0x3f200102, 0x3fbe0102, 0x3fe30102,
-0x21a00902, 0x40804003, 0x21a00983, 0x21a00a04,
-0x40805a02, 0x21a00a82, 0x40800083, 0x21a00b83,
-0x01a00c02, 0x01a00d83, 0x3420c282, 0x21a00e02,
-0x34210283, 0x21a00f03, 0x34200284, 0x77400200,
-0x3421c282, 0x21a00702, 0x34218283, 0x21a00083,
-0x34214282, 0x21a00b02, 0x4200480c, 0x00200000,
-0x1c010286, 0x34220284, 0x34220302, 0x0f608203,
-0x5c024204, 0x3b81810b, 0x42013c02, 0x00200000,
-0x18008185, 0x38808183, 0x3b814182, 0x21004e84,
-0x4020007f, 0x35000100, 0x000004e0, 0x000002a0,
-0x000002e8, 0x00000428, 0x00000360, 0x000002e8,
-0x000004a0, 0x00000468, 0x000003c8, 0x00000360,
-0x409ffe02, 0x30801203, 0x40800204, 0x3ec40085,
-0x10009c09, 0x3ac10606, 0xb060c105, 0x4020007f,
-0x4020007f, 0x20801203, 0x38810602, 0xb0408586,
-0x28810602, 0x32004180, 0x34204702, 0x21a00382,
-0x4020007f, 0x327fdc80, 0x409ffe02, 0x30801203,
-0x40800204, 0x3ec40087, 0x40800405, 0x00200000,
-0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a,
-0xb060c107, 0x20801203, 0x41004003, 0x38810602,
-0x4020007f, 0xb0408188, 0x4020007f, 0x28810602,
-0x41201002, 0x38814603, 0x10009c09, 0xb060c109,
-0x4020007f, 0x28814603, 0x41193f83, 0x38818602,
-0x60ffc003, 0xb040818a, 0x28818602, 0x32003080,
-0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087,
-0x41201008, 0x10009c14, 0x40800405, 0x3ac10609,
-0x40800606, 0x3ac1460a, 0xb060c107, 0x3ac1860b,
-0x20801203, 0x38810602, 0xb0408409, 0x28810602,
-0x38814603, 0xb060c40a, 0x4020007f, 0x28814603,
-0x41193f83, 0x38818602, 0x60ffc003, 0xb040818b,
-0x28818602, 0x32002380, 0x409ffe02, 0x30801204,
-0x40800205, 0x3ec40083, 0x40800406, 0x3ac14607,
-0x3ac18608, 0xb0810103, 0x41004002, 0x20801204,
-0x4020007f, 0x38814603, 0x10009c0b, 0xb060c107,
-0x4020007f, 0x4020007f, 0x28814603, 0x38818602,
-0x4020007f, 0x4020007f, 0xb0408588, 0x28818602,
-0x4020007f, 0x32001780, 0x409ffe02, 0x1000640e,
-0x40800204, 0x30801203, 0x40800405, 0x3ec40087,
-0x40800606, 0x3ac10608, 0x3ac14609, 0x3ac1860a,
-0xb060c107, 0x20801203, 0x413d8003, 0x38810602,
-0x4020007f, 0x327fd780, 0x409ffe02, 0x10007f0c,
-0x40800205, 0x30801204, 0x40800406, 0x3ec40083,
-0x3ac14607, 0x3ac18608, 0xb0810103, 0x413d8002,
-0x20801204, 0x38814603, 0x4020007f, 0x327feb80,
-0x409ffe02, 0x30801203, 0x40800204, 0x3ec40087,
-0x40800405, 0x1000650a, 0x40800606, 0x3ac10608,
-0x3ac14609, 0x3ac1860a, 0xb060c107, 0x20801203,
-0x38810602, 0xb0408588, 0x4020007f, 0x327fc980,
-0x00400000, 0x40800003, 0x4020007f, 0x35000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
+static unsigned int spu_restore_code[]  __attribute__((__aligned__(128))) = {
+0x40800000,
+0x409ff801,
+0x24000080,
+0x24fd8081,
+0x1cd80081,
+0x33001180,
+0x42030003,
+0x33800284,
+0x1c010204,
+0x40200000,
+0x40200000,
+0x40200000,
+0x34000190,
+0x34004191,
+0x34008192,
+0x3400c193,
+0x141fc205,
+0x23fffd84,
+0x1c100183,
+0x217ffa85,
+0x3080a000,
+0x3080a201,
+0x3080a402,
+0x3080a603,
+0x3080a804,
+0x3080aa05,
+0x3080ac06,
+0x3080ae07,
+0x3080b008,
+0x3080b209,
+0x3080b40a,
+0x3080b60b,
+0x3080b80c,
+0x3080ba0d,
+0x3080bc0e,
+0x3080be0f,
+0x00003ffc,
+0x00000000,
+0x00000000,
+0x00000000,
+0x01a00182,
+0x3ec00083,
+0xb0a14103,
+0x01a00204,
+0x3ec10082,
+0x4202800e,
+0x04000703,
+0xb0a14202,
+0x21a00803,
+0x3fbf028d,
+0x3f20068d,
+0x3fbe0682,
+0x3fe30102,
+0x21a00882,
+0x3f82028f,
+0x3fe3078f,
+0x3fbf0784,
+0x3f200204,
+0x3fbe0204,
+0x3fe30204,
+0x04000203,
+0x21a00903,
+0x40848002,
+0x21a00982,
+0x40800003,
+0x21a00a03,
+0x40802002,
+0x21a00a82,
+0x21a00083,
+0x40800082,
+0x21a00b02,
+0x10002818,
+0x42a00002,
+0x32800007,
+0x4207000c,
+0x18008208,
+0x40a0000b,
+0x4080020a,
+0x40800709,
+0x00200000,
+0x42070002,
+0x3ac30384,
+0x1cffc489,
+0x00200000,
+0x18008383,
+0x38830382,
+0x4cffc486,
+0x3ac28185,
+0xb0408584,
+0x28830382,
+0x1c020387,
+0x38828182,
+0xb0408405,
+0x1802c408,
+0x28828182,
+0x217ff886,
+0x04000583,
+0x21a00803,
+0x3fbe0682,
+0x3fe30102,
+0x04000106,
+0x21a00886,
+0x04000603,
+0x21a00903,
+0x40803c02,
+0x21a00982,
+0x40800003,
+0x04000184,
+0x21a00a04,
+0x40802202,
+0x21a00a82,
+0x42028005,
+0x34208702,
+0x21002282,
+0x21a00804,
+0x21a00886,
+0x3fbf0782,
+0x3f200102,
+0x3fbe0102,
+0x3fe30102,
+0x21a00902,
+0x40804003,
+0x21a00983,
+0x21a00a04,
+0x40805a02,
+0x21a00a82,
+0x40800083,
+0x21a00b83,
+0x01a00c02,
+0x01a00d83,
+0x3420c282,
+0x21a00e02,
+0x34210283,
+0x21a00f03,
+0x34200284,
+0x77400200,
+0x3421c282,
+0x21a00702,
+0x34218283,
+0x21a00083,
+0x34214282,
+0x21a00b02,
+0x4200480c,
+0x00200000,
+0x1c010286,
+0x34220284,
+0x34220302,
+0x0f608203,
+0x5c024204,
+0x3b81810b,
+0x42013c02,
+0x00200000,
+0x18008185,
+0x38808183,
+0x3b814182,
+0x21004e84,
+0x4020007f,
+0x35000100,
+0x000004e0,
+0x000002a0,
+0x000002e8,
+0x00000428,
+0x00000360,
+0x000002e8,
+0x000004a0,
+0x00000468,
+0x000003c8,
+0x00000360,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40085,
+0x10009c09,
+0x3ac10606,
+0xb060c105,
+0x4020007f,
+0x4020007f,
+0x20801203,
+0x38810602,
+0xb0408586,
+0x28810602,
+0x32004180,
+0x34204702,
+0x21a00382,
+0x4020007f,
+0x327fdc80,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40087,
+0x40800405,
+0x00200000,
+0x40800606,
+0x3ac10608,
+0x3ac14609,
+0x3ac1860a,
+0xb060c107,
+0x20801203,
+0x41004003,
+0x38810602,
+0x4020007f,
+0xb0408188,
+0x4020007f,
+0x28810602,
+0x41201002,
+0x38814603,
+0x10009c09,
+0xb060c109,
+0x4020007f,
+0x28814603,
+0x41193f83,
+0x38818602,
+0x60ffc003,
+0xb040818a,
+0x28818602,
+0x32003080,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40087,
+0x41201008,
+0x10009c14,
+0x40800405,
+0x3ac10609,
+0x40800606,
+0x3ac1460a,
+0xb060c107,
+0x3ac1860b,
+0x20801203,
+0x38810602,
+0xb0408409,
+0x28810602,
+0x38814603,
+0xb060c40a,
+0x4020007f,
+0x28814603,
+0x41193f83,
+0x38818602,
+0x60ffc003,
+0xb040818b,
+0x28818602,
+0x32002380,
+0x409ffe02,
+0x30801204,
+0x40800205,
+0x3ec40083,
+0x40800406,
+0x3ac14607,
+0x3ac18608,
+0xb0810103,
+0x41004002,
+0x20801204,
+0x4020007f,
+0x38814603,
+0x10009c0b,
+0xb060c107,
+0x4020007f,
+0x4020007f,
+0x28814603,
+0x38818602,
+0x4020007f,
+0x4020007f,
+0xb0408588,
+0x28818602,
+0x4020007f,
+0x32001780,
+0x409ffe02,
+0x1000640e,
+0x40800204,
+0x30801203,
+0x40800405,
+0x3ec40087,
+0x40800606,
+0x3ac10608,
+0x3ac14609,
+0x3ac1860a,
+0xb060c107,
+0x20801203,
+0x413d8003,
+0x38810602,
+0x4020007f,
+0x327fd780,
+0x409ffe02,
+0x10007f0c,
+0x40800205,
+0x30801204,
+0x40800406,
+0x3ec40083,
+0x3ac14607,
+0x3ac18608,
+0xb0810103,
+0x413d8002,
+0x20801204,
+0x38814603,
+0x4020007f,
+0x327feb80,
+0x409ffe02,
+0x30801203,
+0x40800204,
+0x3ec40087,
+0x40800405,
+0x1000650a,
+0x40800606,
+0x3ac10608,
+0x3ac14609,
+0x3ac1860a,
+0xb060c107,
+0x20801203,
+0x38810602,
+0xb0408588,
+0x4020007f,
+0x327fc980,
+0x00400000,
+0x40800003,
+0x4020007f,
+0x35000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
index 39e5400..b9f81ac 100644
--- a/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
+++ b/arch/powerpc/platforms/cell/spufs/spu_save_dump.h_shipped
@@ -3,189 +3,741 @@
  * Hex-dump auto generated from spu_save.c.
  * Do not edit!
  */
-static unsigned int spu_save_code[] __page_aligned = {
-0x20805000, 0x20805201, 0x20805402, 0x20805603,
-0x20805804, 0x20805a05, 0x20805c06, 0x20805e07,
-0x20806008, 0x20806209, 0x2080640a, 0x2080660b,
-0x2080680c, 0x20806a0d, 0x20806c0e, 0x20806e0f,
-0x4201c003, 0x33800184, 0x1c010204, 0x40200000,
-0x24000190, 0x24004191, 0x24008192, 0x2400c193,
-0x141fc205, 0x23fffd84, 0x1c100183, 0x217ffb85,
-0x40800000, 0x409ff801, 0x24000080, 0x24fd8081,
-0x1cd80081, 0x33000180, 0x00000000, 0x00000000,
-0x01a00182, 0x3ec00083, 0xb1c38103, 0x01a00204,
-0x3ec10082, 0x4201400d, 0xb1c38202, 0x01a00583,
-0x34218682, 0x3ed80684, 0xb0408184, 0x24218682,
-0x01a00603, 0x00200000, 0x34214682, 0x3ed40684,
-0xb0408184, 0x40800003, 0x24214682, 0x21a00083,
-0x40800082, 0x21a00b02, 0x4020007f, 0x1000251e,
-0x40a80002, 0x32800008, 0x4205c00c, 0x00200000,
-0x40a0000b, 0x3f82070f, 0x4080020a, 0x40800709,
-0x3fe3078f, 0x3fbf0783, 0x3f200183, 0x3fbe0183,
-0x3fe30187, 0x18008387, 0x4205c002, 0x3ac30404,
-0x1cffc489, 0x00200000, 0x18008403, 0x38830402,
-0x4cffc486, 0x3ac28185, 0xb0408584, 0x28830402,
-0x1c020408, 0x38828182, 0xb0408385, 0x1802c387,
-0x28828182, 0x217ff886, 0x04000582, 0x32800007,
-0x21a00802, 0x3fbf0705, 0x3f200285, 0x3fbe0285,
-0x3fe30285, 0x21a00885, 0x04000603, 0x21a00903,
-0x40803c02, 0x21a00982, 0x04000386, 0x21a00a06,
-0x40801202, 0x21a00a82, 0x73000003, 0x24200683,
-0x01a00404, 0x00200000, 0x34204682, 0x3ec40683,
-0xb0408203, 0x24204682, 0x01a00783, 0x00200000,
-0x3421c682, 0x3edc0684, 0xb0408184, 0x2421c682,
-0x21a00806, 0x21a00885, 0x3fbf0784, 0x3f200204,
-0x3fbe0204, 0x3fe30204, 0x21a00904, 0x40804002,
-0x21a00982, 0x21a00a06, 0x40805a02, 0x21a00a82,
-0x04000683, 0x21a00803, 0x21a00885, 0x21a00904,
-0x40848002, 0x21a00982, 0x21a00a06, 0x40801002,
-0x21a00a82, 0x21a00a06, 0x40806602, 0x00200000,
-0x35800009, 0x21a00a82, 0x40800083, 0x21a00b83,
-0x01a00c02, 0x01a00d83, 0x00003ffb, 0x40800003,
-0x4020007f, 0x35000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000,
+static unsigned int spu_save_code[]  __attribute__((__aligned__(128))) = {
+0x20805000,
+0x20805201,
+0x20805402,
+0x20805603,
+0x20805804,
+0x20805a05,
+0x20805c06,
+0x20805e07,
+0x20806008,
+0x20806209,
+0x2080640a,
+0x2080660b,
+0x2080680c,
+0x20806a0d,
+0x20806c0e,
+0x20806e0f,
+0x4201c003,
+0x33800184,
+0x1c010204,
+0x40200000,
+0x24000190,
+0x24004191,
+0x24008192,
+0x2400c193,
+0x141fc205,
+0x23fffd84,
+0x1c100183,
+0x217ffb85,
+0x40800000,
+0x409ff801,
+0x24000080,
+0x24fd8081,
+0x1cd80081,
+0x33000180,
+0x00000000,
+0x00000000,
+0x01a00182,
+0x3ec00083,
+0xb1c38103,
+0x01a00204,
+0x3ec10082,
+0x4201400d,
+0xb1c38202,
+0x01a00583,
+0x34218682,
+0x3ed80684,
+0xb0408184,
+0x24218682,
+0x01a00603,
+0x00200000,
+0x34214682,
+0x3ed40684,
+0xb0408184,
+0x40800003,
+0x24214682,
+0x21a00083,
+0x40800082,
+0x21a00b02,
+0x4020007f,
+0x1000251e,
+0x42a00002,
+0x32800008,
+0x4205c00c,
+0x00200000,
+0x40a0000b,
+0x3f82070f,
+0x4080020a,
+0x40800709,
+0x3fe3078f,
+0x3fbf0783,
+0x3f200183,
+0x3fbe0183,
+0x3fe30187,
+0x18008387,
+0x4205c002,
+0x3ac30404,
+0x1cffc489,
+0x00200000,
+0x18008403,
+0x38830402,
+0x4cffc486,
+0x3ac28185,
+0xb0408584,
+0x28830402,
+0x1c020408,
+0x38828182,
+0xb0408385,
+0x1802c387,
+0x28828182,
+0x217ff886,
+0x04000582,
+0x32800007,
+0x21a00802,
+0x3fbf0705,
+0x3f200285,
+0x3fbe0285,
+0x3fe30285,
+0x21a00885,
+0x04000603,
+0x21a00903,
+0x40803c02,
+0x21a00982,
+0x04000386,
+0x21a00a06,
+0x40801202,
+0x21a00a82,
+0x73000003,
+0x24200683,
+0x01a00404,
+0x00200000,
+0x34204682,
+0x3ec40683,
+0xb0408203,
+0x24204682,
+0x01a00783,
+0x00200000,
+0x3421c682,
+0x3edc0684,
+0xb0408184,
+0x2421c682,
+0x21a00806,
+0x21a00885,
+0x3fbf0784,
+0x3f200204,
+0x3fbe0204,
+0x3fe30204,
+0x21a00904,
+0x40804002,
+0x21a00982,
+0x21a00a06,
+0x40805a02,
+0x21a00a82,
+0x04000683,
+0x21a00803,
+0x21a00885,
+0x21a00904,
+0x40848002,
+0x21a00982,
+0x21a00a06,
+0x40801002,
+0x21a00a82,
+0x21a00a06,
+0x40806602,
+0x00200000,
+0x35800009,
+0x21a00a82,
+0x40800083,
+0x21a00b83,
+0x01a00c02,
+0x01a00d83,
+0x00003ffb,
+0x40800003,
+0x4020007f,
+0x35000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
+0x00000000,
 };
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c
index 1726bfe..a656d81 100644
--- a/arch/powerpc/platforms/cell/spufs/switch.c
+++ b/arch/powerpc/platforms/cell/spufs/switch.c
@@ -46,6 +46,7 @@
 
 #include <asm/io.h>
 #include <asm/spu.h>
+#include <asm/spu_priv1.h>
 #include <asm/spu_csa.h>
 #include <asm/mmu_context.h>
 
@@ -622,12 +623,17 @@
 static inline void save_ch_part1(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
-	u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+	u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
 	int i;
 
 	/* Save, Step 42:
-	 *     Save the following CH: [0,1,3,4,24,25,27]
 	 */
+
+	/* Save CH 1, without channel count */
+	out_be64(&priv2->spu_chnlcntptr_RW, 1);
+	csa->spu_chnldata_RW[1] = in_be64(&priv2->spu_chnldata_RW);
+
+	/* Save the following CH: [0,3,4,24,25,27] */
 	for (i = 0; i < 7; i++) {
 		idx = ch_indices[i];
 		out_be64(&priv2->spu_chnlcntptr_RW, idx);
@@ -718,13 +724,15 @@
 
 static inline void get_kernel_slb(u64 ea, u64 slb[2])
 {
-	slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) | SLB_VSID_KERNEL;
-	slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
+	u64 llp;
 
-	/* Large pages are used for kernel text/data, but not vmalloc.  */
-	if (cpu_has_feature(CPU_FTR_16M_PAGE)
-	    && REGION_ID(ea) == KERNEL_REGION_ID)
-		slb[0] |= SLB_VSID_L;
+	if (REGION_ID(ea) == KERNEL_REGION_ID)
+		llp = mmu_psize_defs[mmu_linear_psize].sllp;
+	else
+		llp = mmu_psize_defs[mmu_virtual_psize].sllp;
+	slb[0] = (get_kernel_vsid(ea) << SLB_VSID_SHIFT) |
+		SLB_VSID_KERNEL | llp;
+	slb[1] = (ea & ESID_MASK) | SLB_ESID_V;
 }
 
 static inline void load_mfc_slb(struct spu *spu, u64 slb[2], int slbe)
@@ -1103,13 +1111,18 @@
 static inline void reset_ch_part1(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
-	u64 ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+	u64 ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
 	u64 idx;
 	int i;
 
 	/* Restore, Step 20:
-	 *     Reset the following CH: [0,1,3,4,24,25,27]
 	 */
+
+	/* Reset CH 1 */
+	out_be64(&priv2->spu_chnlcntptr_RW, 1);
+	out_be64(&priv2->spu_chnldata_RW, 0UL);
+
+	/* Reset the following CH: [0,3,4,24,25,27] */
 	for (i = 0; i < 7; i++) {
 		idx = ch_indices[i];
 		out_be64(&priv2->spu_chnlcntptr_RW, idx);
@@ -1570,12 +1583,17 @@
 static inline void restore_ch_part1(struct spu_state *csa, struct spu *spu)
 {
 	struct spu_priv2 __iomem *priv2 = spu->priv2;
-	u64 idx, ch_indices[7] = { 0UL, 1UL, 3UL, 4UL, 24UL, 25UL, 27UL };
+	u64 idx, ch_indices[7] = { 0UL, 3UL, 4UL, 24UL, 25UL, 27UL };
 	int i;
 
 	/* Restore, Step 59:
-	 *     Restore the following CH: [0,1,3,4,24,25,27]
 	 */
+
+	/* Restore CH 1 without count */
+	out_be64(&priv2->spu_chnlcntptr_RW, 1);
+	out_be64(&priv2->spu_chnldata_RW, csa->spu_chnldata_RW[1]);
+
+	/* Restore the following CH: [0,3,4,24,25,27] */
 	for (i = 0; i < 7; i++) {
 		idx = ch_indices[i];
 		out_be64(&priv2->spu_chnlcntptr_RW, idx);
@@ -2074,6 +2092,7 @@
 	}
 	return rc;
 }
+EXPORT_SYMBOL_GPL(spu_save);
 
 /**
  * spu_restore - SPU context restore, with harvest and locking.
@@ -2081,7 +2100,7 @@
  * @spu: pointer to SPU iomem structure.
  *
  * Perform harvest + restore, as we may not be coming
- * from a previous succesful save operation, and the
+ * from a previous successful save operation, and the
  * hardware state is unknown.
  */
 int spu_restore(struct spu_state *new, struct spu *spu)
@@ -2090,7 +2109,6 @@
 
 	acquire_spu_lock(spu);
 	harvest(NULL, spu);
-	spu->stop_code = 0;
 	spu->dar = 0;
 	spu->dsisr = 0;
 	spu->slb_replace = 0;
@@ -2103,6 +2121,7 @@
 	}
 	return rc;
 }
+EXPORT_SYMBOL_GPL(spu_restore);
 
 /**
  * spu_harvest - SPU harvest (reset) operation
@@ -2125,6 +2144,7 @@
 	csa->spu_chnlcnt_RW[28] = 1;
 	csa->spu_chnlcnt_RW[30] = 1;
 	csa->prob.spu_runcntl_RW = SPU_RUNCNTL_STOP;
+	csa->prob.mb_stat_R = 0x000400;
 }
 
 static void init_priv1(struct spu_state *csa)
@@ -2183,7 +2203,7 @@
 
 	memset(lscsa, 0, sizeof(struct spu_lscsa));
 	csa->lscsa = lscsa;
-	csa->register_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&csa->register_lock);
 
 	/* Set LS pages reserved to allow for user-space mapping. */
 	for (p = lscsa->ls; p < lscsa->ls + LS_SIZE; p += PAGE_SIZE)
@@ -2193,6 +2213,7 @@
 	init_priv1(csa);
 	init_priv2(csa);
 }
+EXPORT_SYMBOL_GPL(spu_init_csa);
 
 void spu_fini_csa(struct spu_state *csa)
 {
@@ -2203,3 +2224,4 @@
 
 	vfree(csa->lscsa);
 }
+EXPORT_SYMBOL_GPL(spu_fini_csa);
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index ce8c0b9..dee4eb4 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,9 +1,11 @@
 EXTRA_CFLAGS	+= -mno-minimal-toc
 
-obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \
+obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
 	hvcall.o proc.o htab.o iommu.o misc.o irq.o
 obj-$(CONFIG_PCI) += pci.o vpdinfo.o
-obj-$(CONFIG_IBMVIO) += vio.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_VIOPATH) += viopath.o
 obj-$(CONFIG_MODULES) += ksyms.o
+
+$(obj)/dt_mod.o:	$(obj)/dt.o
+	@$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o
diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
index 59d4e0a..dbdf698 100644
--- a/arch/powerpc/platforms/iseries/call_pci.h
+++ b/arch/powerpc/platforms/iseries/call_pci.h
@@ -145,6 +145,25 @@
 	return retVal.rc;
 }
 
+static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
+		u8 deviceId, u32 offset, u32 *value)
+{
+	struct HvCallPci_DsaAddr dsa;
+	struct HvCallPci_LoadReturn retVal;
+
+	*((u64*)&dsa) = 0;
+
+	dsa.busNumber = busNumber;
+	dsa.subBusNumber = subBusNumber;
+	dsa.deviceId = deviceId;
+
+	HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
+
+	*value = retVal.value;
+
+	return retVal.rc;
+}
+
 static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
 		u8 deviceId, u32 offset, u8 value)
 {
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
new file mode 100644
index 0000000..d3444aa
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -0,0 +1,615 @@
+/*
+ *    Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation
+ *
+ *    Description:
+ *      This file contains all the routines to build a flattened device
+ *      tree for a legacy iSeries machine.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/threads.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>	/* ETH_ALEN */
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/lppaca.h>
+#include <asm/cputable.h>
+#include <asm/abs_addr.h>
+#include <asm/system.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/it_exp_vpd_panel.h>
+#include <asm/udbg.h>
+
+#include "processor_vpd.h"
+#include "call_hpt.h"
+#include "call_pci.h"
+#include "pci.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+/*
+ * These are created by the linker script at the start and end
+ * of the section containing all the strings from this file.
+ */
+extern char __dt_strings_start[];
+extern char __dt_strings_end[];
+
+struct iseries_flat_dt {
+	struct boot_param_header header;
+	u64 reserve_map[2];
+};
+
+static void * __initdata dt_data;
+
+/*
+ * Putting these strings here keeps them out of the section
+ * that we rename to .dt_strings using objcopy and capture
+ * for the strings blob of the flattened device tree.
+ */
+static char __initdata device_type_cpu[] = "cpu";
+static char __initdata device_type_memory[] = "memory";
+static char __initdata device_type_serial[] = "serial";
+static char __initdata device_type_network[] = "network";
+static char __initdata device_type_block[] = "block";
+static char __initdata device_type_byte[] = "byte";
+static char __initdata device_type_pci[] = "pci";
+static char __initdata device_type_vdevice[] = "vdevice";
+static char __initdata device_type_vscsi[] = "vscsi";
+
+static struct iseries_flat_dt * __init dt_init(void)
+{
+	struct iseries_flat_dt *dt;
+	unsigned long str_len;
+
+	str_len = __dt_strings_end - __dt_strings_start;
+	dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
+	dt->header.off_mem_rsvmap =
+		offsetof(struct iseries_flat_dt, reserve_map);
+	dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
+	dt->header.off_dt_struct = dt->header.off_dt_strings
+		+ ALIGN(str_len, 8);
+	dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
+	dt->header.dt_strings_size = str_len;
+
+	/* There is no notion of hardware cpu id on iSeries */
+	dt->header.boot_cpuid_phys = smp_processor_id();
+
+	memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
+			str_len);
+
+	dt->header.magic = OF_DT_HEADER;
+	dt->header.version = 0x10;
+	dt->header.last_comp_version = 0x10;
+
+	dt->reserve_map[0] = 0;
+	dt->reserve_map[1] = 0;
+
+	return dt;
+}
+
+static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+{
+	*((u32 *)dt_data) = value;
+	dt_data += sizeof(u32);
+}
+
+#ifdef notyet
+static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+{
+	*((u64 *)dt_data) = value;
+	dt_data += sizeof(u64);
+}
+#endif
+
+static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,
+		int len)
+{
+	memcpy(dt_data, data, len);
+	dt_data += ALIGN(len, 4);
+}
+
+static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
+{
+	dt_push_u32(dt, OF_DT_BEGIN_NODE);
+	dt_push_bytes(dt, name, strlen(name) + 1);
+}
+
+#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
+
+static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
+		const void *data, int len)
+{
+	unsigned long offset;
+
+	dt_push_u32(dt, OF_DT_PROP);
+
+	/* Length of the data */
+	dt_push_u32(dt, len);
+
+	offset = name - __dt_strings_start;
+
+	/* The offset of the properties name in the string blob. */
+	dt_push_u32(dt, (u32)offset);
+
+	/* The actual data. */
+	dt_push_bytes(dt, data, len);
+}
+
+static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,
+		const char *data)
+{
+	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
+}
+
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
+		u32 data)
+{
+	dt_prop(dt, name, &data, sizeof(u32));
+}
+
+#ifdef notyet
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
+		u64 data)
+{
+	dt_prop(dt, name, &data, sizeof(u64));
+}
+#endif
+
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
+		const char *name, u64 *data, int n)
+{
+	dt_prop(dt, name, data, sizeof(u64) * n);
+}
+
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,
+		const char *name, u32 *data, int n)
+{
+	dt_prop(dt, name, data, sizeof(u32) * n);
+}
+
+#ifdef notyet
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name)
+{
+	dt_prop(dt, name, NULL, 0);
+}
+#endif
+
+static void __init dt_cpus(struct iseries_flat_dt *dt)
+{
+	unsigned char buf[32];
+	unsigned char *p;
+	unsigned int i, index;
+	struct IoHriProcessorVpd *d;
+	u32 pft_size[2];
+
+	/* yuck */
+	snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
+	p = strchr(buf, ' ');
+	if (!p) p = buf + strlen(buf);
+
+	dt_start_node(dt, "cpus");
+	dt_prop_u32(dt, "#address-cells", 1);
+	dt_prop_u32(dt, "#size-cells", 0);
+
+	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
+	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (lppaca[i].dyn_proc_status >= 2)
+			continue;
+
+		snprintf(p, 32 - (p - buf), "@%d", i);
+		dt_start_node(dt, buf);
+
+		dt_prop_str(dt, "device_type", device_type_cpu);
+
+		index = lppaca[i].dyn_hv_phys_proc_index;
+		d = &xIoHriProcessorVpd[index];
+
+		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
+		dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
+
+		dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
+		dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
+
+		/* magic conversions to Hz copied from old code */
+		dt_prop_u32(dt, "clock-frequency",
+			((1UL << 34) * 1000000) / d->xProcFreq);
+		dt_prop_u32(dt, "timebase-frequency",
+			((1UL << 32) * 1000000) / d->xTimeBaseFreq);
+
+		dt_prop_u32(dt, "reg", i);
+
+		dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
+
+		dt_end_node(dt);
+	}
+
+	dt_end_node(dt);
+}
+
+static void __init dt_model(struct iseries_flat_dt *dt)
+{
+	char buf[16] = "IBM,";
+
+	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */
+	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
+	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
+	buf[11] = '\0';
+	dt_prop_str(dt, "system-id", buf);
+
+	/* "IBM," + machineType[0:4] */
+	strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
+	buf[8] = '\0';
+	dt_prop_str(dt, "model", buf);
+
+	dt_prop_str(dt, "compatible", "IBM,iSeries");
+}
+
+static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
+		const char *name, u32 reg, int unit,
+		const char *type, const char *compat, int end)
+{
+	char buf[32];
+
+	snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));
+	dt_start_node(dt, buf);
+	dt_prop_str(dt, "device_type", type);
+	if (compat)
+		dt_prop_str(dt, "compatible", compat);
+	dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0));
+	if (unit >= 0)
+		dt_prop_u32(dt, "linux,unit_address", unit);
+	if (end)
+		dt_end_node(dt);
+}
+
+static void __init dt_vdevices(struct iseries_flat_dt *dt)
+{
+	u32 reg = 0;
+	HvLpIndexMap vlan_map;
+	int i;
+
+	dt_start_node(dt, "vdevice");
+	dt_prop_str(dt, "device_type", device_type_vdevice);
+	dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
+	dt_prop_u32(dt, "#address-cells", 1);
+	dt_prop_u32(dt, "#size-cells", 0);
+
+	dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1);
+	reg++;
+
+	dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi,
+			"IBM,v-scsi", 1);
+	reg++;
+
+	vlan_map = HvLpConfig_getVirtualLanIndexMap();
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+		unsigned char mac_addr[ETH_ALEN];
+
+		if ((vlan_map & (0x8000 >> i)) == 0)
+			continue;
+		dt_do_vdevice(dt, "l-lan", reg, i, device_type_network,
+				"IBM,iSeries-l-lan", 0);
+		mac_addr[0] = 0x02;
+		mac_addr[1] = 0x01;
+		mac_addr[2] = 0xff;
+		mac_addr[3] = i;
+		mac_addr[4] = 0xff;
+		mac_addr[5] = HvLpConfig_getLpIndex_outline();
+		dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
+		dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
+		dt_prop_u32(dt, "max-frame-size", 9000);
+		dt_prop_u32(dt, "address-bits", 48);
+
+		dt_end_node(dt);
+	}
+	reg += HVMAXARCHITECTEDVIRTUALLANS;
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
+		dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
+				"IBM,iSeries-viodasd", 1);
+	reg += HVMAXARCHITECTEDVIRTUALDISKS;
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
+		dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
+				"IBM,iSeries-viocd", 1);
+	reg += HVMAXARCHITECTEDVIRTUALCDROMS;
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
+		dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
+				"IBM,iSeries-viotape", 1);
+
+	dt_end_node(dt);
+}
+
+struct pci_class_name {
+	u16 code;
+	const char *name;
+	const char *type;
+};
+
+static struct pci_class_name __initdata pci_class_name[] = {
+	{ PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network },
+};
+
+static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
+{
+	struct pci_class_name *cp;
+
+	for (cp = pci_class_name;
+			cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
+		if (cp->code == class_code)
+			return cp;
+	return NULL;
+}
+
+/*
+ * This assumes that the node slot is always on the primary bus!
+ */
+static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
+		HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
+{
+	HvSubBusNumber sub_bus = bridge_info->subBusNumber;
+	u16 vendor_id;
+	u16 device_id;
+	u32 class_id;
+	int err;
+	char buf[32];
+	u32 reg[5];
+	int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
+	int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
+	HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+	u8 devfn;
+	struct pci_class_name *cp;
+
+	/*
+	 * Connect all functions of any device found.
+	 */
+	for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
+		for (function = 0; function < 8; function++) {
+			HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
+					function);
+			err = HvCallXm_connectBusUnit(bus, sub_bus,
+					agent_id, 0);
+			if (err) {
+				if (err != 0x302)
+					DBG("connectBusUnit(%x, %x, %x) %x\n",
+						bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_VENDOR_ID, &vendor_id);
+			if (err) {
+				DBG("ReadVendor(%x, %x, %x) %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_DEVICE_ID, &device_id);
+			if (err) {
+				DBG("ReadDevice(%x, %x, %x) %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
+					PCI_CLASS_REVISION , &class_id);
+			if (err) {
+				DBG("ReadClass(%x, %x, %x) %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
+					function);
+			cp = dt_find_pci_class_name(class_id >> 16);
+			if (cp && cp->name)
+				strncpy(buf, cp->name, sizeof(buf) - 1);
+			else
+				snprintf(buf, sizeof(buf), "pci%x,%x",
+						vendor_id, device_id);
+			buf[sizeof(buf) - 1] = '\0';
+			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+					"@%x", PCI_SLOT(devfn));
+			buf[sizeof(buf) - 1] = '\0';
+			if (function != 0)
+				snprintf(buf + strlen(buf),
+					sizeof(buf) - strlen(buf),
+					",%x", function);
+			dt_start_node(dt, buf);
+			reg[0] = (bus << 16) | (devfn << 8);
+			reg[1] = 0;
+			reg[2] = 0;
+			reg[3] = 0;
+			reg[4] = 0;
+			dt_prop_u32_list(dt, "reg", reg, 5);
+			if (cp && (cp->type || cp->name))
+				dt_prop_str(dt, "device_type",
+					cp->type ? cp->type : cp->name);
+			dt_prop_u32(dt, "vendor-id", vendor_id);
+			dt_prop_u32(dt, "device-id", device_id);
+			dt_prop_u32(dt, "class-code", class_id >> 8);
+			dt_prop_u32(dt, "revision-id", class_id & 0xff);
+			dt_prop_u32(dt, "linux,subbus", sub_bus);
+			dt_prop_u32(dt, "linux,agent-id", agent_id);
+			dt_prop_u32(dt, "linux,logical-slot-number",
+					bridge_info->logicalSlotNumber);
+			dt_end_node(dt);
+
+		}
+	}
+}
+
+static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+		HvSubBusNumber sub_bus, int id_sel)
+{
+	struct HvCallPci_BridgeInfo bridge_info;
+	HvAgentId agent_id;
+	int function;
+	int ret;
+
+	/* Note: hvSubBus and irq is always be 0 at this level! */
+	for (function = 0; function < 8; ++function) {
+		agent_id = ISERIES_PCI_AGENTID(id_sel, function);
+		ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
+		if (ret != 0) {
+			if (ret != 0xb)
+				DBG("connectBusUnit(%x, %x, %x) %x\n",
+						bus, sub_bus, agent_id, ret);
+			continue;
+		}
+		DBG("found device at bus %d idsel %d func %d (AgentId %x)\n",
+				bus, id_sel, function, agent_id);
+		ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
+				iseries_hv_addr(&bridge_info),
+				sizeof(struct HvCallPci_BridgeInfo));
+		if (ret != 0)
+			continue;
+		DBG("bridge info: type %x subbus %x "
+			"maxAgents %x maxsubbus %x logslot %x\n",
+			bridge_info.busUnitInfo.deviceType,
+			bridge_info.subBusNumber,
+			bridge_info.maxAgents,
+			bridge_info.maxSubBusNumber,
+			bridge_info.logicalSlotNumber);
+		if (bridge_info.busUnitInfo.deviceType ==
+				HvCallPci_BridgeDevice)
+			scan_bridge_slot(dt, bus, &bridge_info);
+		else
+			DBG("PCI: Invalid Bridge Configuration(0x%02X)",
+				bridge_info.busUnitInfo.deviceType);
+	}
+}
+
+static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+{
+	struct HvCallPci_DeviceInfo dev_info;
+	const HvSubBusNumber sub_bus = 0;	/* EADs is always 0. */
+	int err;
+	int id_sel;
+	const int max_agents = 8;
+
+	/*
+	 * Probe for EADs Bridges
+	 */
+	for (id_sel = 1; id_sel < max_agents; ++id_sel) {
+		err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
+				iseries_hv_addr(&dev_info),
+				sizeof(struct HvCallPci_DeviceInfo));
+		if (err) {
+			if (err != 0x302)
+				DBG("getDeviceInfo(%x, %x, %x) %x\n",
+						bus, sub_bus, id_sel, err);
+			continue;
+		}
+		if (dev_info.deviceType != HvCallPci_NodeDevice) {
+			DBG("PCI: Invalid System Configuration"
+					"(0x%02X) for bus 0x%02x id 0x%02x.\n",
+					dev_info.deviceType, bus, id_sel);
+			continue;
+		}
+		scan_bridge(dt, bus, sub_bus, id_sel);
+	}
+}
+
+static void __init dt_pci_devices(struct iseries_flat_dt *dt)
+{
+	HvBusNumber bus;
+	char buf[32];
+	u32 buses[2];
+	int phb_num = 0;
+
+	/* Check all possible buses. */
+	for (bus = 0; bus < 256; bus++) {
+		int err = HvCallXm_testBus(bus);
+
+		if (err) {
+			/*
+			 * Check for Unexpected Return code, a clue that
+			 * something has gone wrong.
+			 */
+			if (err != 0x0301)
+				DBG("Unexpected Return on Probe(0x%02X) "
+						"0x%04X\n", bus, err);
+			continue;
+		}
+		DBG("bus %d appears to exist\n", bus);
+		snprintf(buf, 32, "pci@%d", phb_num);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", device_type_pci);
+		dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
+		dt_prop_u32(dt, "#address-cells", 3);
+		dt_prop_u32(dt, "#size-cells", 2);
+		buses[0] = buses[1] = bus;
+		dt_prop_u32_list(dt, "bus-range", buses, 2);
+		scan_phb(dt, bus);
+		dt_end_node(dt);
+		phb_num++;
+	}
+}
+
+static void dt_finish(struct iseries_flat_dt *dt)
+{
+	dt_push_u32(dt, OF_DT_END);
+	dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt;
+	klimit = ALIGN((unsigned long)dt_data, 8);
+}
+
+void * __init build_flat_dt(unsigned long phys_mem_size)
+{
+	struct iseries_flat_dt *iseries_dt;
+	u64 tmp[2];
+
+	iseries_dt = dt_init();
+
+	dt_start_node(iseries_dt, "");
+
+	dt_prop_u32(iseries_dt, "#address-cells", 2);
+	dt_prop_u32(iseries_dt, "#size-cells", 2);
+	dt_model(iseries_dt);
+
+	/* /memory */
+	dt_start_node(iseries_dt, "memory@0");
+	dt_prop_str(iseries_dt, "device_type", device_type_memory);
+	tmp[0] = 0;
+	tmp[1] = phys_mem_size;
+	dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
+	dt_end_node(iseries_dt);
+
+	/* /chosen */
+	dt_start_node(iseries_dt, "chosen");
+	dt_prop_str(iseries_dt, "bootargs", cmd_line);
+	dt_end_node(iseries_dt);
+
+	dt_cpus(iseries_dt);
+
+	dt_vdevices(iseries_dt);
+	dt_pci_devices(iseries_dt);
+
+	dt_end_node(iseries_dt);
+
+	dt_finish(iseries_dt);
+
+	return iseries_dt;
+}
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index bea0b70..e3bd201 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -4,6 +4,7 @@
  * Rewrite, cleanup:
  *
  * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
  *
  * Dynamic DMA mapping support, iSeries-specific parts.
  *
@@ -31,42 +32,37 @@
 #include <asm/tce.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/iseries/hv_call_xm.h>
-
-#include "iommu.h"
-
-extern struct list_head iSeries_Global_Device_List;
-
+#include <asm/iseries/iommu.h>
 
 static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
 		unsigned long uaddr, enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce;
+	u64 tce, rpn;
 
 	index <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
 	while (npages--) {
-		tce.te_word = 0;
-		tce.te_bits.tb_rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
+		rpn = virt_to_abs(uaddr) >> TCE_SHIFT;
+		tce = (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
 		if (tbl->it_type == TCE_VB) {
 			/* Virtual Bus */
-			tce.te_bits.tb_valid = 1;
-			tce.te_bits.tb_allio = 1;
+			tce |= TCE_VALID|TCE_ALLIO;
 			if (direction != DMA_TO_DEVICE)
-				tce.te_bits.tb_rdwr = 1;
+				tce |= TCE_VB_WRITE;
 		} else {
 			/* PCI Bus */
-			tce.te_bits.tb_rdwr = 1; /* Read allowed */
+			tce |= TCE_PCI_READ; /* Read allowed */
 			if (direction != DMA_TO_DEVICE)
-				tce.te_bits.tb_pciwr = 1;
+				tce |= TCE_PCI_WRITE;
 		}
 
-		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index,
-				tce.te_word);
+		rc = HvCallXm_setTce((u64)tbl->it_index, (u64)index, tce);
 		if (rc)
 			panic("PCI_DMA: HvCallXm_setTce failed, Rc: 0x%lx\n",
 					rc);
@@ -124,7 +120,7 @@
 
 	/* itc_size is in pages worth of table, it_size is in # of entries */
 	tbl->it_size = ((parms->itc_size * TCE_PAGE_SIZE) /
-			sizeof(union tce_entry)) >> TCE_PAGE_FACTOR;
+			TCE_ENTRY_SIZE) >> TCE_PAGE_FACTOR;
 	tbl->it_busno = parms->itc_busno;
 	tbl->it_offset = parms->itc_offset >> TCE_PAGE_FACTOR;
 	tbl->it_index = parms->itc_index;
@@ -142,10 +138,15 @@
  */
 static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
 {
-	struct pci_dn *pdn;
+	struct device_node *node;
 
-	list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
-		struct iommu_table *it = pdn->iommu_table;
+	for (node = NULL; (node = of_find_all_nodes(node)); ) {
+		struct pci_dn *pdn = PCI_DN(node);
+		struct iommu_table *it;
+
+		if (pdn == NULL)
+			continue;
+		it = pdn->iommu_table;
 		if ((it != NULL) &&
 		    (it->it_type == TCE_PCI) &&
 		    (it->it_offset == tbl->it_offset) &&
@@ -161,15 +162,18 @@
 {
 	struct iommu_table *tbl;
 	struct pci_dn *pdn = PCI_DN(dn);
+	u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL);
+
+	BUG_ON(lsn == NULL);
 
 	tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-	iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl);
+	iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
 
 	/* Look for existing tce table */
 	pdn->iommu_table = iommu_table_find(tbl);
 	if (pdn->iommu_table == NULL)
-		pdn->iommu_table = iommu_init_table(tbl);
+		pdn->iommu_table = iommu_init_table(tbl, -1);
 	else
 		kfree(tbl);
 }
diff --git a/arch/powerpc/platforms/iseries/iommu.h b/arch/powerpc/platforms/iseries/iommu.h
deleted file mode 100644
index cb5658f..0000000
--- a/arch/powerpc/platforms/iseries/iommu.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef _PLATFORMS_ISERIES_IOMMU_H
-#define _PLATFORMS_ISERIES_IOMMU_H
-
-/*
- * Copyright (C) 2005  Stephen Rothwell, IBM Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the:
- * Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330,
- * Boston, MA  02111-1307  USA
- */
-
-struct device_node;
-struct iommu_table;
-
-/* Creates table for an individual device node */
-extern void iommu_devnode_init_iSeries(struct device_node *dn);
-
-/* Get table parameters from HV */
-extern void iommu_table_getparms_iSeries(unsigned long busno,
-		unsigned char slotno, unsigned char virtbus,
-		struct iommu_table *tbl);
-
-#endif /* _PLATFORMS_ISERIES_IOMMU_H */
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index be3fbfc..62bbbcf 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -42,6 +42,7 @@
 #include <asm/iseries/it_lp_queue.h>
 
 #include "irq.h"
+#include "pci.h"
 #include "call_pci.h"
 
 #if defined(CONFIG_SMP)
@@ -312,12 +313,12 @@
  * Note that sub_bus is always 0 (at the moment at least).
  */
 int __init iSeries_allocate_IRQ(HvBusNumber bus,
-		HvSubBusNumber sub_bus, HvAgentId dev_id)
+		HvSubBusNumber sub_bus, u32 bsubbus)
 {
 	int virtirq;
 	unsigned int realirq;
-	u8 idsel = (dev_id >> 4);
-	u8 function = dev_id & 7;
+	u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
+	u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
 
 	realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
 		+ function;
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index b9c801b..188aa80 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -2,7 +2,7 @@
 #define	_ISERIES_IRQ_H
 
 extern void iSeries_init_IRQ(void);
-extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
 extern void iSeries_activate_IRQs(void);
 extern int iSeries_get_irq(struct pt_regs *);
 
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c
index d771b8e..1a2c2a5 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -45,7 +45,6 @@
 
 #include "setup.h"
 
-extern int piranha_simulator;
 static int mf_initialized;
 
 /*
@@ -658,7 +657,7 @@
 
 void __init mf_display_progress(u16 value)
 {
-	if (piranha_simulator || !mf_initialized)
+	if (!mf_initialized)
 		return;
 
 	if (0xFFFF == value)
@@ -1295,9 +1294,6 @@
  */
 void iSeries_get_rtc_time(struct rtc_time *rtc_tm)
 {
-	if (piranha_simulator)
-		return;
-
 	mf_get_rtc(rtc_tm);
 	rtc_tm->tm_mon--;
 }
@@ -1316,9 +1312,6 @@
 {
 	struct rtc_time tm;
 
-	if (piranha_simulator)
-		return 0;
-
 	mf_get_boot_rtc(&tm);
 	return mktime(tm.tm_year + 1900, tm.tm_mon, tm.tm_mday,
 		      tm.tm_hour, tm.tm_min, tm.tm_sec);
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index a19833b..35bcc98 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -37,36 +37,18 @@
 
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/mf.h>
+#include <asm/iseries/iommu.h>
 
 #include <asm/ppc-pci.h>
 
 #include "irq.h"
 #include "pci.h"
 #include "call_pci.h"
-#include "iommu.h"
-
-extern unsigned long io_page_mask;
 
 /*
  * Forward declares of prototypes.
  */
 static struct device_node *find_Device_Node(int bus, int devfn);
-static void scan_PHB_slots(struct pci_controller *Phb);
-static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
-static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
-
-LIST_HEAD(iSeries_Global_Device_List);
-
-static int DeviceCount;
-
-/* Counters and control flags. */
-static long Pci_Io_Read_Count;
-static long Pci_Io_Write_Count;
-#if 0
-static long Pci_Cfg_Read_Count;
-static long Pci_Cfg_Write_Count;
-#endif
-static long Pci_Error_Count;
 
 static int Pci_Retry_Max = 3;	/* Only retry 3 times  */
 static int Pci_Error_Flag = 1;	/* Set Retry Error on. */
@@ -81,41 +63,19 @@
 #define IOMM_TABLE_ENTRY_SIZE	0x0000000000400000UL
 #define BASE_IO_MEMORY		0xE000000000000000UL
 
-static unsigned long max_io_memory = 0xE000000000000000UL;
+static unsigned long max_io_memory = BASE_IO_MEMORY;
 static long current_iomm_table_entry;
 
 /*
  * Lookup Tables.
  */
-static struct device_node **iomm_table;
-static u8 *iobar_table;
+static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
+static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
 
-/*
- * Static and Global variables
- */
-static char *pci_io_text = "iSeries PCI I/O";
+static const char pci_io_text[] = "iSeries PCI I/O";
 static DEFINE_SPINLOCK(iomm_table_lock);
 
 /*
- * iomm_table_initialize
- *
- * Allocates and initalizes the Address Translation Table and Bar
- * Tables to get them ready for use.  Must be called before any
- * I/O space is handed out to the device BARs.
- */
-static void iomm_table_initialize(void)
-{
-	spin_lock(&iomm_table_lock);
-	iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
-			GFP_KERNEL);
-	iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
-			GFP_KERNEL);
-	spin_unlock(&iomm_table_lock);
-	if ((iomm_table == NULL) || (iobar_table == NULL))
-		panic("PCI: I/O tables allocation failed.\n");
-}
-
-/*
  * iomm_table_allocate_entry
  *
  * Adds pci_dev entry in address translation table
@@ -142,9 +102,8 @@
 	 */
 	spin_lock(&iomm_table_lock);
 	bar_res->name = pci_io_text;
-	bar_res->start =
+	bar_res->start = BASE_IO_MEMORY +
 		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
-	bar_res->start += BASE_IO_MEMORY;
 	bar_res->end = bar_res->start + bar_size - 1;
 	/*
 	 * Allocate the number of table entries needed for BAR.
@@ -156,7 +115,7 @@
 		++current_iomm_table_entry;
 	}
 	max_io_memory = BASE_IO_MEMORY +
-		(IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry);
+		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
 	spin_unlock(&iomm_table_lock);
 }
 
@@ -173,13 +132,10 @@
  */
 static void allocate_device_bars(struct pci_dev *dev)
 {
-	struct resource *bar_res;
 	int bar_num;
 
-	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) {
-		bar_res = &dev->resource[bar_num];
+	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num)
 		iomm_table_allocate_entry(dev, bar_num);
-	}
 }
 
 /*
@@ -199,34 +155,7 @@
 }
 
 /*
- * build_device_node(u16 Bus, int SubBus, u8 DevFn)
- */
-static struct device_node *build_device_node(HvBusNumber Bus,
-		HvSubBusNumber SubBus, int AgentId, int Function)
-{
-	struct device_node *node;
-	struct pci_dn *pdn;
-
-	node = kmalloc(sizeof(struct device_node), GFP_KERNEL);
-	if (node == NULL)
-		return NULL;
-	memset(node, 0, sizeof(struct device_node));
-	pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
-	if (pdn == NULL) {
-		kfree(node);
-		return NULL;
-	}
-	node->data = pdn;
-	pdn->node = node;
-	list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List);
-	pdn->busno = Bus;
-	pdn->bussubno = SubBus;
-	pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
-	return node;
-}
-
-/*
- * unsigned long __init find_and_init_phbs(void)
+ * iSeries_pcibios_init
  *
  * Description:
  *   This function checks for all possible system PCI host bridges that connect
@@ -234,50 +163,42 @@
  *   ownership status.  A pci_controller is built for any bus which is partially
  *   owned or fully owned by this guest partition.
  */
-unsigned long __init find_and_init_phbs(void)
-{
-	struct pci_controller *phb;
-	HvBusNumber bus;
-
-	/* Check all possible buses. */
-	for (bus = 0; bus < 256; bus++) {
-		int ret = HvCallXm_testBus(bus);
-		if (ret == 0) {
-			printk("bus %d appears to exist\n", bus);
-
-			phb = pcibios_alloc_controller(NULL);
-			if (phb == NULL)
-				return -ENOMEM;
-
-			phb->pci_mem_offset = phb->local_number = bus;
-			phb->first_busno = bus;
-			phb->last_busno = bus;
-			phb->ops = &iSeries_pci_ops;
-
-			/* Find and connect the devices. */
-			scan_PHB_slots(phb);
-		}
-		/*
-		 * Check for Unexpected Return code, a clue that something
-		 * has gone wrong.
-		 */
-		else if (ret != 0x0301)
-			printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
-			       bus, ret);
-	}
-	return 0;
-}
-
-/*
- * iSeries_pcibios_init
- *
- * Chance to initialize and structures or variable before PCI Bus walk.
- */
 void iSeries_pcibios_init(void)
 {
-	iomm_table_initialize();
-	find_and_init_phbs();
-	io_page_mask = -1;
+	struct pci_controller *phb;
+	struct device_node *root = of_find_node_by_path("/");
+	struct device_node *node = NULL;
+
+	if (root == NULL) {
+		printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
+				"of device tree\n");
+		return;
+	}
+	while ((node = of_get_next_child(root, node)) != NULL) {
+		HvBusNumber bus;
+		u32 *busp;
+
+		if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
+			continue;
+
+		busp = (u32 *)get_property(node, "bus-range", NULL);
+		if (busp == NULL)
+			continue;
+		bus = *busp;
+		printk("bus %d appears to exist\n", bus);
+		phb = pcibios_alloc_controller(node);
+		if (phb == NULL)
+			continue;
+
+		phb->pci_mem_offset = phb->local_number = bus;
+		phb->first_busno = bus;
+		phb->last_busno = bus;
+		phb->ops = &iSeries_pci_ops;
+	}
+
+	of_node_put(root);
+
+	pci_devs_phb_init();
 }
 
 /*
@@ -299,6 +220,34 @@
 		       pdev->bus->number, pdev->devfn, node);
 
 		if (node != NULL) {
+			struct pci_dn *pdn = PCI_DN(node);
+			u32 *agent;
+
+			agent = (u32 *)get_property(node, "linux,agent-id",
+					NULL);
+			if ((pdn != NULL) && (agent != NULL)) {
+				u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
+						pdn->bussubno);
+				int err;
+
+				err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno,
+						*agent, irq);
+				if (err)
+					pci_Log_Error("Connect Bus Unit",
+						pdn->busno, pdn->bussubno, *agent, err);
+				else {
+					err = HvCallPci_configStore8(pdn->busno, pdn->bussubno,
+							*agent,
+							PCI_INTERRUPT_LINE,
+							irq);
+					if (err)
+						pci_Log_Error("PciCfgStore Irq Failed!",
+							pdn->busno, pdn->bussubno, *agent, err);
+				}
+				if (!err)
+					pdev->irq = irq;
+			}
+
 			++DeviceCount;
 			pdev->sysdata = (void *)node;
 			PCI_DN(node)->pcidev = pdev;
@@ -308,7 +257,6 @@
 		} else
 			printk("PCI: Device Tree not found for 0x%016lX\n",
 					(unsigned long)pdev);
-		pdev->irq = PCI_DN(node)->Irq;
 	}
 	iSeries_activate_IRQs();
 	mf_display_src(0xC9000200);
@@ -323,148 +271,6 @@
 }
 
 /*
- * Loop through each node function to find usable EADs bridges.
- */
-static void scan_PHB_slots(struct pci_controller *Phb)
-{
-	struct HvCallPci_DeviceInfo *DevInfo;
-	HvBusNumber bus = Phb->local_number;	/* System Bus */
-	const HvSubBusNumber SubBus = 0;	/* EADs is always 0. */
-	int HvRc = 0;
-	int IdSel;
-	const int MaxAgents = 8;
-
-	DevInfo = (struct HvCallPci_DeviceInfo*)
-		kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
-	if (DevInfo == NULL)
-		return;
-
-	/*
-	 * Probe for EADs Bridges
-	 */
-	for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
-		HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
-				iseries_hv_addr(DevInfo),
-				sizeof(struct HvCallPci_DeviceInfo));
-		if (HvRc == 0) {
-			if (DevInfo->deviceType == HvCallPci_NodeDevice)
-				scan_EADS_bridge(bus, SubBus, IdSel);
-			else
-				printk("PCI: Invalid System Configuration(0x%02X)"
-				       " for bus 0x%02x id 0x%02x.\n",
-				       DevInfo->deviceType, bus, IdSel);
-		}
-		else
-			pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
-	}
-	kfree(DevInfo);
-}
-
-static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
-		int IdSel)
-{
-	struct HvCallPci_BridgeInfo *BridgeInfo;
-	HvAgentId AgentId;
-	int Function;
-	int HvRc;
-
-	BridgeInfo = (struct HvCallPci_BridgeInfo *)
-		kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
-	if (BridgeInfo == NULL)
-		return;
-
-	/* Note: hvSubBus and irq is always be 0 at this level! */
-	for (Function = 0; Function < 8; ++Function) {
-		AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
-		HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
-		if (HvRc == 0) {
-			printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
-			       bus, IdSel, Function, AgentId);
-			/*  Connect EADs: 0x18.00.12 = 0x00 */
-			HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
-					iseries_hv_addr(BridgeInfo),
-					sizeof(struct HvCallPci_BridgeInfo));
-			if (HvRc == 0) {
-				printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
-					BridgeInfo->busUnitInfo.deviceType,
-					BridgeInfo->subBusNumber,
-					BridgeInfo->maxAgents,
-					BridgeInfo->maxSubBusNumber,
-					BridgeInfo->logicalSlotNumber);
-				if (BridgeInfo->busUnitInfo.deviceType ==
-						HvCallPci_BridgeDevice)  {
-					/* Scan_Bridge_Slot...: 0x18.00.12 */
-					scan_bridge_slot(bus, BridgeInfo);
-				} else
-					printk("PCI: Invalid Bridge Configuration(0x%02X)",
-						BridgeInfo->busUnitInfo.deviceType);
-			}
-		} else if (HvRc != 0x000B)
-			pci_Log_Error("EADs Connect",
-					bus, SubBus, AgentId, HvRc);
-	}
-	kfree(BridgeInfo);
-}
-
-/*
- * This assumes that the node slot is always on the primary bus!
- */
-static int scan_bridge_slot(HvBusNumber Bus,
-		struct HvCallPci_BridgeInfo *BridgeInfo)
-{
-	struct device_node *node;
-	HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
-	u16 VendorId = 0;
-	int HvRc = 0;
-	u8 Irq = 0;
-	int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
-	int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
-	HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
-
-	/* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
-	Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
-
-	/*
-	 * Connect all functions of any device found.
-	 */
-	for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
-		for (Function = 0; Function < 8; ++Function) {
-			HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
-			HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
-					AgentId, Irq);
-			if (HvRc != 0) {
-				pci_Log_Error("Connect Bus Unit",
-					      Bus, SubBus, AgentId, HvRc);
-				continue;
-			}
-
-			HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
-						      PCI_VENDOR_ID, &VendorId);
-			if (HvRc != 0) {
-				pci_Log_Error("Read Vendor",
-					      Bus, SubBus, AgentId, HvRc);
-				continue;
-			}
-			printk("read vendor ID: %x\n", VendorId);
-
-			/* FoundDevice: 0x18.28.10 = 0x12AE */
-			HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
-						      PCI_INTERRUPT_LINE, Irq);
-			if (HvRc != 0)
-				pci_Log_Error("PciCfgStore Irq Failed!",
-					      Bus, SubBus, AgentId, HvRc);
-
-			++DeviceCount;
-			node = build_device_node(Bus, SubBus, EADsIdSel, Function);
-			PCI_DN(node)->Irq = Irq;
-			PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber;
-
-		} /* for (Function = 0; Function < 8; ++Function) */
-	} /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
-	return HvRc;
-}
-
-/*
  * I/0 Memory copy MUST use mmio commands on iSeries
  * To do; For performance, include the hv call directly
  */
@@ -509,11 +315,13 @@
  */
 static struct device_node *find_Device_Node(int bus, int devfn)
 {
-	struct pci_dn *pdn;
+	struct device_node *node;
 
-	list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
-		if ((bus == pdn->busno) && (devfn == pdn->devfn))
-			return pdn->node;
+	for (node = NULL; (node = of_find_all_nodes(node)); ) {
+		struct pci_dn *pdn = PCI_DN(node);
+
+		if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn))
+			return node;
 	}
 	return NULL;
 }
@@ -625,7 +433,6 @@
 	if (ret != 0)  {
 		struct pci_dn *pdn = PCI_DN(DevNode);
 
-		++Pci_Error_Count;
 		(*retry)++;
 		printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
 				TextHdr, pdn->busno, pdn->devfn,
@@ -707,7 +514,6 @@
 		return 0xff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
 	} while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
 
@@ -737,7 +543,6 @@
 		return 0xffff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
 				BarOffset, 0);
 	} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
@@ -768,7 +573,6 @@
 		return 0xffffffff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
 				BarOffset, 0);
 	} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
@@ -806,7 +610,6 @@
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
 	} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
 }
@@ -834,7 +637,6 @@
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
 	} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
 }
@@ -862,7 +664,6 @@
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
 	} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
 }
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index a6fd9be..617c724 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -50,7 +50,6 @@
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/mf.h>
-#include <asm/iseries/it_exp_vpd_panel.h>
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/lpar_map.h>
 #include <asm/udbg.h>
@@ -81,9 +80,6 @@
 static void iSeries_pci_final_fixup(void) { }
 #endif
 
-/* Global Variables */
-int piranha_simulator;
-
 extern int rd_size;		/* Defined in drivers/block/rd.c */
 extern unsigned long embedded_sysmap_start;
 extern unsigned long embedded_sysmap_end;
@@ -91,8 +87,6 @@
 extern unsigned long iSeries_recal_tb;
 extern unsigned long iSeries_recal_titan;
 
-static unsigned long cmd_mem_limit;
-
 struct MemoryBlock {
 	unsigned long absStart;
 	unsigned long absEnd;
@@ -340,8 +334,6 @@
 #ifdef CONFIG_SMP
 	smp_init_iSeries();
 #endif
-	if (itLpNaca.xPirEnvironMode == 0)
-		piranha_simulator = 1;
 
 	/* Associate Lp Event Queue 0 with processor 0 */
 	HvCallEvent_setLpEventQueueInterruptProc(0, 0);
@@ -536,10 +528,10 @@
 {
 	if (get_lppaca()->shared_proc) {
 		ppc_md.idle_loop = iseries_shared_idle;
-		printk(KERN_INFO "Using shared processor idle loop\n");
+		printk(KERN_DEBUG "Using shared processor idle loop\n");
 	} else {
 		ppc_md.idle_loop = iseries_dedicated_idle;
-		printk(KERN_INFO "Using dedicated idle loop\n");
+		printk(KERN_DEBUG "Using dedicated idle loop\n");
 	}
 
 	/* Setup the Lp Event Queue */
@@ -714,243 +706,6 @@
 	/* XXX Implement enable_pmcs for iSeries */
 };
 
-struct blob {
-	unsigned char data[PAGE_SIZE];
-	unsigned long next;
-};
-
-struct iseries_flat_dt {
-	struct boot_param_header header;
-	u64 reserve_map[2];
-	struct blob dt;
-	struct blob strings;
-};
-
-struct iseries_flat_dt iseries_dt;
-
-void dt_init(struct iseries_flat_dt *dt)
-{
-	dt->header.off_mem_rsvmap =
-		offsetof(struct iseries_flat_dt, reserve_map);
-	dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
-	dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
-	dt->header.totalsize = sizeof(struct iseries_flat_dt);
-	dt->header.dt_strings_size = sizeof(struct blob);
-
-	/* There is no notion of hardware cpu id on iSeries */
-	dt->header.boot_cpuid_phys = smp_processor_id();
-
-	dt->dt.next = (unsigned long)&dt->dt.data;
-	dt->strings.next = (unsigned long)&dt->strings.data;
-
-	dt->header.magic = OF_DT_HEADER;
-	dt->header.version = 0x10;
-	dt->header.last_comp_version = 0x10;
-
-	dt->reserve_map[0] = 0;
-	dt->reserve_map[1] = 0;
-}
-
-void dt_check_blob(struct blob *b)
-{
-	if (b->next >= (unsigned long)&b->next) {
-		DBG("Ran out of space in flat device tree blob!\n");
-		BUG();
-	}
-}
-
-void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
-{
-	*((u32*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u32);
-
-	dt_check_blob(&dt->dt);
-}
-
-void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
-{
-	*((u64*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u64);
-
-	dt_check_blob(&dt->dt);
-}
-
-unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
-{
-	unsigned long start = blob->next - (unsigned long)blob->data;
-
-	memcpy((char *)blob->next, data, len);
-	blob->next = _ALIGN(blob->next + len, 4);
-
-	dt_check_blob(blob);
-
-	return start;
-}
-
-void dt_start_node(struct iseries_flat_dt *dt, char *name)
-{
-	dt_push_u32(dt, OF_DT_BEGIN_NODE);
-	dt_push_bytes(&dt->dt, name, strlen(name) + 1);
-}
-
-#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
-
-void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
-{
-	unsigned long offset;
-
-	dt_push_u32(dt, OF_DT_PROP);
-
-	/* Length of the data */
-	dt_push_u32(dt, len);
-
-	/* Put the property name in the string blob. */
-	offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
-
-	/* The offset of the properties name in the string blob. */
-	dt_push_u32(dt, (u32)offset);
-
-	/* The actual data. */
-	dt_push_bytes(&dt->dt, data, len);
-}
-
-void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
-{
-	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
-}
-
-void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
-{
-	dt_prop(dt, name, (char *)&data, sizeof(u32));
-}
-
-void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
-{
-	dt_prop(dt, name, (char *)&data, sizeof(u64));
-}
-
-void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
-{
-	dt_prop(dt, name, (char *)data, sizeof(u64) * n);
-}
-
-void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
-{
-	dt_prop(dt, name, (char *)data, sizeof(u32) * n);
-}
-
-void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
-{
-	dt_prop(dt, name, NULL, 0);
-}
-
-void dt_cpus(struct iseries_flat_dt *dt)
-{
-	unsigned char buf[32];
-	unsigned char *p;
-	unsigned int i, index;
-	struct IoHriProcessorVpd *d;
-	u32 pft_size[2];
-
-	/* yuck */
-	snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
-	p = strchr(buf, ' ');
-	if (!p) p = buf + strlen(buf);
-
-	dt_start_node(dt, "cpus");
-	dt_prop_u32(dt, "#address-cells", 1);
-	dt_prop_u32(dt, "#size-cells", 0);
-
-	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
-	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (lppaca[i].dyn_proc_status >= 2)
-			continue;
-
-		snprintf(p, 32 - (p - buf), "@%d", i);
-		dt_start_node(dt, buf);
-
-		dt_prop_str(dt, "device_type", "cpu");
-
-		index = lppaca[i].dyn_hv_phys_proc_index;
-		d = &xIoHriProcessorVpd[index];
-
-		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
-		dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
-
-		dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
-		dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
-
-		/* magic conversions to Hz copied from old code */
-		dt_prop_u32(dt, "clock-frequency",
-			((1UL << 34) * 1000000) / d->xProcFreq);
-		dt_prop_u32(dt, "timebase-frequency",
-			((1UL << 32) * 1000000) / d->xTimeBaseFreq);
-
-		dt_prop_u32(dt, "reg", i);
-
-		dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
-
-		dt_end_node(dt);
-	}
-
-	dt_end_node(dt);
-}
-
-void dt_model(struct iseries_flat_dt *dt)
-{
-	char buf[16] = "IBM,";
-
-	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */
-	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
-	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
-	buf[11] = '\0';
-	dt_prop_str(dt, "system-id", buf);
-
-	/* "IBM," + machineType[0:4] */
-	strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
-	buf[8] = '\0';
-	dt_prop_str(dt, "model", buf);
-
-	dt_prop_str(dt, "compatible", "IBM,iSeries");
-}
-
-void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
-{
-	u64 tmp[2];
-
-	dt_init(dt);
-
-	dt_start_node(dt, "");
-
-	dt_prop_u32(dt, "#address-cells", 2);
-	dt_prop_u32(dt, "#size-cells", 2);
-	dt_model(dt);
-
-	/* /memory */
-	dt_start_node(dt, "memory@0");
-	dt_prop_str(dt, "name", "memory");
-	dt_prop_str(dt, "device_type", "memory");
-	tmp[0] = 0;
-	tmp[1] = phys_mem_size;
-	dt_prop_u64_list(dt, "reg", tmp, 2);
-	dt_end_node(dt);
-
-	/* /chosen */
-	dt_start_node(dt, "chosen");
-	dt_prop_str(dt, "bootargs", cmd_line);
-	if (cmd_mem_limit)
-		dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
-	dt_end_node(dt);
-
-	dt_cpus(dt);
-
-	dt_end_node(dt);
-
-	dt_push_u32(dt, OF_DT_END);
-}
-
 void * __init iSeries_early_setup(void)
 {
 	unsigned long phys_mem_size;
@@ -965,29 +720,9 @@
 
 	iSeries_get_cmdline();
 
-	/* Save unparsed command line copy for /proc/cmdline */
-	strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
-	/* Parse early parameters, in particular mem=x */
-	parse_early_param();
-
-	build_flat_dt(&iseries_dt, phys_mem_size);
-
-	return (void *) __pa(&iseries_dt);
+	return (void *) __pa(build_flat_dt(phys_mem_size));
 }
 
-/*
- * On iSeries we just parse the mem=X option from the command line.
- * On pSeries it's a bit more complicated, see prom_init_mem()
- */
-static int __init early_parsemem(char *p)
-{
-	if (p)
-		cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
-	return 0;
-}
-early_param("mem", early_parsemem);
-
 static void hvputc(char c)
 {
 	if (c == '\n')
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
index 5213044..0a47ac5 100644
--- a/arch/powerpc/platforms/iseries/setup.h
+++ b/arch/powerpc/platforms/iseries/setup.h
@@ -21,4 +21,6 @@
 extern int iSeries_set_rtc_time(struct rtc_time *tm);
 extern void iSeries_get_rtc_time(struct rtc_time *tm);
 
+extern void *build_flat_dt(unsigned long phys_mem_size);
+
 #endif /* __ISERIES_SETUP_H__ */
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
deleted file mode 100644
index ad36ab0..0000000
--- a/arch/powerpc/platforms/iseries/vio.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * IBM PowerPC iSeries Virtual I/O Infrastructure Support.
- *
- *    Copyright (c) 2005 Stephen Rothwell, IBM Corp.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- */
-#include <linux/types.h>
-#include <linux/device.h>
-#include <linux/init.h>
-
-#include <asm/vio.h>
-#include <asm/iommu.h>
-#include <asm/tce.h>
-#include <asm/abs_addr.h>
-#include <asm/page.h>
-#include <asm/iseries/vio.h>
-#include <asm/iseries/hv_types.h>
-#include <asm/iseries/hv_lp_config.h>
-#include <asm/iseries/hv_call_xm.h>
-
-#include "iommu.h"
-
-struct device *iSeries_vio_dev = &vio_bus_device.dev;
-EXPORT_SYMBOL(iSeries_vio_dev);
-
-static struct iommu_table veth_iommu_table;
-static struct iommu_table vio_iommu_table;
-
-static void __init iommu_vio_init(void)
-{
-	iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table);
-	veth_iommu_table.it_size /= 2;
-	vio_iommu_table = veth_iommu_table;
-	vio_iommu_table.it_offset += veth_iommu_table.it_size;
-
-	if (!iommu_init_table(&veth_iommu_table))
-		printk("Virtual Bus VETH TCE table failed.\n");
-	if (!iommu_init_table(&vio_iommu_table))
-		printk("Virtual Bus VIO TCE table failed.\n");
-}
-
-/**
- * vio_register_device_iseries: - Register a new iSeries vio device.
- * @voidev:	The device to register.
- */
-static struct vio_dev *__init vio_register_device_iseries(char *type,
-		uint32_t unit_num)
-{
-	struct vio_dev *viodev;
-
-	/* allocate a vio_dev for this device */
-	viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
-	if (!viodev)
-		return NULL;
-	memset(viodev, 0, sizeof(struct vio_dev));
-
-	snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%s%d", type, unit_num);
-
-	viodev->name = viodev->dev.bus_id;
-	viodev->type = type;
-	viodev->unit_address = unit_num;
-	viodev->iommu_table = &vio_iommu_table;
-	if (vio_register_device(viodev) == NULL) {
-		kfree(viodev);
-		return NULL;
-	}
-	return viodev;
-}
-
-void __init probe_bus_iseries(void)
-{
-	HvLpIndexMap vlan_map;
-	struct vio_dev *viodev;
-	int i;
-
-	/* there is only one of each of these */
-	vio_register_device_iseries("viocons", 0);
-	vio_register_device_iseries("vscsi", 0);
-
-	vlan_map = HvLpConfig_getVirtualLanIndexMap();
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
-		if ((vlan_map & (0x8000 >> i)) == 0)
-			continue;
-		viodev = vio_register_device_iseries("vlan", i);
-		/* veth is special and has it own iommu_table */
-		viodev->iommu_table = &veth_iommu_table;
-	}
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
-		vio_register_device_iseries("viodasd", i);
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
-		vio_register_device_iseries("viocd", i);
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
-		vio_register_device_iseries("viotape", i);
-}
-
-/**
- * vio_match_device_iseries: - Tell if a iSeries VIO device matches a
- *	vio_device_id
- */
-static int vio_match_device_iseries(const struct vio_device_id *id,
-		const struct vio_dev *dev)
-{
-	return strncmp(dev->type, id->type, strlen(id->type)) == 0;
-}
-
-static struct vio_bus_ops vio_bus_ops_iseries = {
-	.match = vio_match_device_iseries,
-};
-
-/**
- * vio_bus_init_iseries: - Initialize the iSeries virtual IO bus
- */
-static int __init vio_bus_init_iseries(void)
-{
-	int err;
-
-	err = vio_bus_init(&vio_bus_ops_iseries);
-	if (err == 0) {
-		iommu_vio_init();
-		vio_bus_device.iommu_table = &vio_iommu_table;
-		iSeries_vio_dev = &vio_bus_device.dev;
-		probe_bus_iseries();
-	}
-	return err;
-}
-
-__initcall(vio_bus_init_iseries);
diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c
index 85d6c93..9a4efc0 100644
--- a/arch/powerpc/platforms/maple/pci.c
+++ b/arch/powerpc/platforms/maple/pci.c
@@ -437,9 +437,6 @@
 
 	/* Tell pci.c to not change any resource allocations.  */
 	pci_probe_only = 1;
-	
-	/* Allow all IO */
-	io_page_mask = -1;
 }
 
 int maple_pci_get_legacy_ide_irq(struct pci_dev *pdev, int channel)
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 24c0aef4..a0505ea 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -189,7 +189,7 @@
 	conswitchp = &dummy_con;
 #endif
 
-	printk(KERN_INFO "Using native/NAP idle loop\n");
+	printk(KERN_DEBUG "Using native/NAP idle loop\n");
 }
 
 /* 
diff --git a/arch/powerpc/platforms/powermac/backlight.c b/arch/powerpc/platforms/powermac/backlight.c
index 8be2f7d..c7a27ed 100644
--- a/arch/powerpc/platforms/powermac/backlight.c
+++ b/arch/powerpc/platforms/powermac/backlight.c
@@ -3,200 +3,158 @@
  * Contains support for the backlight.
  *
  *   Copyright (C) 2000 Benjamin Herrenschmidt
+ *   Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
  *
  */
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/reboot.h>
-#include <linux/nvram.h>
-#include <linux/console.h>
-#include <asm/sections.h>
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
 #include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
 #include <asm/backlight.h>
 
-#include <linux/adb.h>
-#include <linux/pmu.h>
+#define OLD_BACKLIGHT_MAX 15
 
-static struct backlight_controller *backlighter;
-static void* backlighter_data;
-static int backlight_autosave;
-static int backlight_level = BACKLIGHT_MAX;
-static int backlight_enabled = 1;
-static int backlight_req_level = -1;
-static int backlight_req_enable = -1;
+/* Protect the pmac_backlight variable */
+DEFINE_MUTEX(pmac_backlight_mutex);
 
-static void backlight_callback(void *);
-static DECLARE_WORK(backlight_work, backlight_callback, NULL);
+/* Main backlight storage
+ *
+ * Backlight drivers in this variable are required to have the "props"
+ * attribute set and to have an update_status function.
+ *
+ * We can only store one backlight here, but since Apple laptops have only one
+ * internal display, it doesn't matter. Other backlight drivers can be used
+ * independently.
+ *
+ * Lock ordering:
+ * pmac_backlight_mutex (global, main backlight)
+ *   pmac_backlight->sem (backlight class)
+ */
+struct backlight_device *pmac_backlight;
 
-void register_backlight_controller(struct backlight_controller *ctrler,
-					  void *data, char *type)
+int pmac_has_backlight_type(const char *type)
 {
-	struct device_node* bk_node;
-	char *prop;
-	int valid = 0;
+	struct device_node* bk_node = find_devices("backlight");
 
-	/* There's already a matching controller, bail out */
-	if (backlighter != NULL)
-		return;
-
-	bk_node = find_devices("backlight");
-
-#ifdef CONFIG_ADB_PMU
-	/* Special case for the old PowerBook since I can't test on it */
-	backlight_autosave = machine_is_compatible("AAPL,3400/2400")
-		|| machine_is_compatible("AAPL,3500");
-	if ((backlight_autosave
-	     || machine_is_compatible("AAPL,PowerBook1998")
-	     || machine_is_compatible("PowerBook1,1"))
-	    && !strcmp(type, "pmu"))
-		valid = 1;
-#endif
 	if (bk_node) {
-		prop = get_property(bk_node, "backlight-control", NULL);
-		if (prop && !strncmp(prop, type, strlen(type)))
-			valid = 1;
-	}
-	if (!valid)
-		return;
-	backlighter = ctrler;
-	backlighter_data = data;
-
-	if (bk_node && !backlight_autosave)
-		prop = get_property(bk_node, "bklt", NULL);
-	else
-		prop = NULL;
-	if (prop) {
-		backlight_level = ((*prop)+1) >> 1;
-		if (backlight_level > BACKLIGHT_MAX)
-			backlight_level = BACKLIGHT_MAX;
+		char *prop = get_property(bk_node, "backlight-control", NULL);
+		if (prop && strncmp(prop, type, strlen(type)) == 0)
+			return 1;
 	}
 
-#ifdef CONFIG_ADB_PMU
-	if (backlight_autosave) {
-		struct adb_request req;
-		pmu_request(&req, NULL, 2, 0xd9, 0);
-		while (!req.complete)
-			pmu_poll();
-		backlight_level = req.reply[0] >> 4;
-	}
-#endif
-	acquire_console_sem();
-	if (!backlighter->set_enable(1, backlight_level, data))
-		backlight_enabled = 1;
-	release_console_sem();
-
-	printk(KERN_INFO "Registered \"%s\" backlight controller,"
-	       "level: %d/15\n", type, backlight_level);
-}
-EXPORT_SYMBOL(register_backlight_controller);
-
-void unregister_backlight_controller(struct backlight_controller
-					    *ctrler, void *data)
-{
-	/* We keep the current backlight level (for now) */
-	if (ctrler == backlighter && data == backlighter_data)
-		backlighter = NULL;
-}
-EXPORT_SYMBOL(unregister_backlight_controller);
-
-static int __set_backlight_enable(int enable)
-{
-	int rc;
-
-	if (!backlighter)
-		return -ENODEV;
-	acquire_console_sem();
-	rc = backlighter->set_enable(enable, backlight_level,
-				     backlighter_data);
-	if (!rc)
-		backlight_enabled = enable;
-	release_console_sem();
-	return rc;
-}
-int set_backlight_enable(int enable)
-{
-	if (!backlighter)
-		return -ENODEV;
-	backlight_req_enable = enable;
-	schedule_work(&backlight_work);
 	return 0;
 }
 
-EXPORT_SYMBOL(set_backlight_enable);
-
-int get_backlight_enable(void)
+int pmac_backlight_curve_lookup(struct fb_info *info, int value)
 {
-	if (!backlighter)
-		return -ENODEV;
-	return backlight_enabled;
-}
-EXPORT_SYMBOL(get_backlight_enable);
+	int level = (FB_BACKLIGHT_LEVELS - 1);
 
-static int __set_backlight_level(int level)
-{
-	int rc = 0;
+	if (info && info->bl_dev) {
+		int i, max = 0;
 
-	if (!backlighter)
-		return -ENODEV;
-	if (level < BACKLIGHT_MIN)
-		level = BACKLIGHT_OFF;
-	if (level > BACKLIGHT_MAX)
-		level = BACKLIGHT_MAX;
-	acquire_console_sem();
-	if (backlight_enabled)
-		rc = backlighter->set_level(level, backlighter_data);
-	if (!rc)
-		backlight_level = level;
-	release_console_sem();
-	if (!rc && !backlight_autosave) {
-		level <<=1;
-		if (level & 0x10)
-			level |= 0x01;
-		// -- todo: save to property "bklt"
+		/* Look for biggest value */
+		for (i = 0; i < FB_BACKLIGHT_LEVELS; i++)
+			max = max((int)info->bl_curve[i], max);
+
+		/* Look for nearest value */
+		for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) {
+			int diff = abs(info->bl_curve[i] - value);
+			if (diff < max) {
+				max = diff;
+				level = i;
+			}
+		}
+
 	}
-	return rc;
-}
-int set_backlight_level(int level)
-{
-	if (!backlighter)
-		return -ENODEV;
-	backlight_req_level = level;
-	schedule_work(&backlight_work);
-	return 0;
+
+	return level;
 }
 
-EXPORT_SYMBOL(set_backlight_level);
-
-int get_backlight_level(void)
+static void pmac_backlight_key(int direction)
 {
-	if (!backlighter)
-		return -ENODEV;
-	return backlight_level;
+	mutex_lock(&pmac_backlight_mutex);
+	if (pmac_backlight) {
+		struct backlight_properties *props;
+		int brightness;
+
+		down(&pmac_backlight->sem);
+		props = pmac_backlight->props;
+
+		brightness = props->brightness +
+			((direction?-1:1) * (props->max_brightness / 15));
+
+		if (brightness < 0)
+			brightness = 0;
+		else if (brightness > props->max_brightness)
+			brightness = props->max_brightness;
+
+		props->brightness = brightness;
+		props->update_status(pmac_backlight);
+
+		up(&pmac_backlight->sem);
+	}
+	mutex_unlock(&pmac_backlight_mutex);
 }
-EXPORT_SYMBOL(get_backlight_level);
 
-static void backlight_callback(void *dummy)
+void pmac_backlight_key_up()
 {
-	int level, enable;
+	pmac_backlight_key(0);
+}
 
-	do {
-		level = backlight_req_level;
-		enable = backlight_req_enable;
-		mb();
+void pmac_backlight_key_down()
+{
+	pmac_backlight_key(1);
+}
 
-		if (level >= 0)
-			__set_backlight_level(level);
-		if (enable >= 0)
-			__set_backlight_enable(enable);
-	} while(cmpxchg(&backlight_req_level, level, -1) != level ||
-		cmpxchg(&backlight_req_enable, enable, -1) != enable);
+int pmac_backlight_set_legacy_brightness(int brightness)
+{
+	int error = -ENXIO;
+
+	mutex_lock(&pmac_backlight_mutex);
+	if (pmac_backlight) {
+		struct backlight_properties *props;
+
+		down(&pmac_backlight->sem);
+		props = pmac_backlight->props;
+		props->brightness = brightness *
+			(props->max_brightness + 1) /
+			(OLD_BACKLIGHT_MAX + 1);
+
+		if (props->brightness > props->max_brightness)
+			props->brightness = props->max_brightness;
+		else if (props->brightness < 0)
+			props->brightness = 0;
+
+		props->update_status(pmac_backlight);
+		up(&pmac_backlight->sem);
+
+		error = 0;
+	}
+	mutex_unlock(&pmac_backlight_mutex);
+
+	return error;
+}
+
+int pmac_backlight_get_legacy_brightness()
+{
+	int result = -ENXIO;
+
+	mutex_lock(&pmac_backlight_mutex);
+	if (pmac_backlight) {
+		struct backlight_properties *props;
+
+		down(&pmac_backlight->sem);
+		props = pmac_backlight->props;
+
+		result = props->brightness *
+			(OLD_BACKLIGHT_MAX + 1) /
+			(props->max_brightness + 1);
+
+		up(&pmac_backlight->sem);
+	}
+	mutex_unlock(&pmac_backlight_mutex);
+
+	return result;
 }
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index cfd6527..af2a8f9 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -314,7 +314,7 @@
  		_set_L3CR(save_l3cr);
 
 	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
+	set_context(current->active_mm->context.id, current->active_mm->pgd);
 
 #ifdef DEBUG_FREQ
 	printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c
index a5063cd..85e00cb 100644
--- a/arch/powerpc/platforms/powermac/feature.c
+++ b/arch/powerpc/platforms/powermac/feature.c
@@ -2510,7 +2510,7 @@
 		if (get_property(np, "flush-on-lock", NULL))
 			break;
 		powersave_nap = 1;
-		printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
+		printk(KERN_DEBUG "Processor NAP mode on idle enabled.\n");
 		break;
 	}
 
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c
index ea179af..8003585 100644
--- a/arch/powerpc/platforms/powermac/pci.c
+++ b/arch/powerpc/platforms/powermac/pci.c
@@ -1068,9 +1068,6 @@
 	/* Tell pci.c to not use the common resource allocation mechanism */
 	pci_probe_only = 1;
 
-	/* Allow all IO */
-	io_page_mask = -1;
-
 #else /* CONFIG_PPC64 */
 	init_p2pbridge();
 	fixup_nec_usb2();
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index f08173b..93e7505 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -546,7 +546,7 @@
 };
 
 static LIST_HEAD(pmf_devices);
-static spinlock_t pmf_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pmf_lock);
 static DEFINE_MUTEX(pmf_irq_mutex);
 
 static void pmf_release_device(struct kref *kref)
@@ -871,10 +871,17 @@
 	spin_unlock_irqrestore(&pmf_lock, flags);
 	if (func == NULL)
 		return -ENODEV;
+
+	/* guard against manipulations of list */
 	mutex_lock(&pmf_irq_mutex);
 	if (list_empty(&func->irq_clients))
 		func->dev->handlers->irq_enable(func);
+
+	/* guard against pmf_do_irq while changing list */
+	spin_lock_irqsave(&pmf_lock, flags);
 	list_add(&client->link, &func->irq_clients);
+	spin_unlock_irqrestore(&pmf_lock, flags);
+
 	client->func = func;
 	mutex_unlock(&pmf_irq_mutex);
 
@@ -885,12 +892,19 @@
 void pmf_unregister_irq_client(struct pmf_irq_client *client)
 {
 	struct pmf_function *func = client->func;
+	unsigned long flags;
 
 	BUG_ON(func == NULL);
 
+	/* guard against manipulations of list */
 	mutex_lock(&pmf_irq_mutex);
 	client->func = NULL;
+
+	/* guard against pmf_do_irq while changing list */
+	spin_lock_irqsave(&pmf_lock, flags);
 	list_del(&client->link);
+	spin_unlock_irqrestore(&pmf_lock, flags);
+
 	if (list_empty(&func->irq_clients))
 		func->dev->handlers->irq_disable(func);
 	mutex_unlock(&pmf_irq_mutex);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index b9200fb..9cc7db7 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -458,7 +458,7 @@
 	printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state);
 
 	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
+	set_context(current->active_mm->context.id, current->active_mm->pgd);
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index 9308986..e5e0ff4 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -1,8 +1,11 @@
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS		+= -mno-minimal-toc
+endif
+
 obj-y			:= pci.o lpar.o hvCall.o nvram.o reconfig.o \
 			   setup.o iommu.o ras.o rtasd.o pci_dlpar.o \
 			   firmware.o
 obj-$(CONFIG_SMP)	+= smp.o
-obj-$(CONFIG_IBMVIO)	+= vio.o
 obj-$(CONFIG_XICS)	+= xics.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
 obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o eeh_driver.o eeh_event.o
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c
index d4a402c..c37a849 100644
--- a/arch/powerpc/platforms/pseries/eeh_cache.c
+++ b/arch/powerpc/platforms/pseries/eeh_cache.c
@@ -287,7 +287,7 @@
  * find the pci device that corresponds to a given address.
  * This routine scans all pci busses to build the cache.
  * Must be run late in boot process, after the pci controllers
- * have been scaned for devices (after all device resources are known).
+ * have been scanned for devices (after all device resources are known).
  */
 void __init pci_addr_cache_build(void)
 {
@@ -304,6 +304,8 @@
 		pci_addr_cache_insert_device(dev);
 
 		dn = pci_device_to_OF_node(dev);
+		if (!dn)
+			continue;
 		pci_dev_get (dev);  /* matching put is in eeh_remove_device() */
 		PCI_DN(dn)->pcidev = dev;
 	}
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index 1fba695..0ec9a54 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -23,9 +23,8 @@
  *
  */
 #include <linux/delay.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/notifier.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <asm/eeh.h>
 #include <asm/eeh_event.h>
@@ -202,7 +201,11 @@
 
 static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus)
 {
-	int rc;
+	int cnt, rc;
+
+	/* pcibios will clear the counter; save the value */
+	cnt = pe_dn->eeh_freeze_count;
+
 	if (bus)
 		pcibios_remove_pci_devices(bus);
 
@@ -241,6 +244,7 @@
 		ssleep (5);
 		pcibios_add_pci_devices(bus);
 	}
+	pe_dn->eeh_freeze_count = cnt;
 
 	return 0;
 }
@@ -250,23 +254,29 @@
  */
 #define MAX_WAIT_FOR_RECOVERY 15
 
-void handle_eeh_events (struct eeh_event *event)
+struct pci_dn * handle_eeh_events (struct eeh_event *event)
 {
 	struct device_node *frozen_dn;
 	struct pci_dn *frozen_pdn;
 	struct pci_bus *frozen_bus;
 	int rc = 0;
 	enum pci_ers_result result = PCI_ERS_RESULT_NONE;
-	const char *pci_str, *drv_str;
+	const char *location, *pci_str, *drv_str;
 
 	frozen_dn = find_device_pe(event->dn);
 	frozen_bus = pcibios_find_pci_bus(frozen_dn);
 
 	if (!frozen_dn) {
-		printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n",
-		        pci_name(event->dev));
-		return;
+
+		location = (char *) get_property(event->dn, "ibm,loc-code", NULL);
+		location = location ? location : "unknown";
+		printk(KERN_ERR "EEH: Error: Cannot find partition endpoint "
+		                "for location=%s pci addr=%s\n",
+		        location, pci_name(event->dev));
+		return NULL;
 	}
+	location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL);
+	location = location ? location : "unknown";
 
 	/* There are two different styles for coming up with the PE.
 	 * In the old style, it was the highest EEH-capable device
@@ -278,9 +288,10 @@
 		frozen_bus = pcibios_find_pci_bus (frozen_dn->parent);
 
 	if (!frozen_bus) {
-		printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n",
-		        frozen_dn->full_name);
-		return;
+		printk(KERN_ERR "EEH: Cannot find PCI bus "
+		        "for location=%s dn=%s\n",
+		        location, frozen_dn->full_name);
+		return NULL;
 	}
 
 #if 0
@@ -314,8 +325,9 @@
 
 	eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
 	printk(KERN_WARNING
-	   "EEH: This PCI device has failed %d times since last reboot: %s - %s\n",
-		frozen_pdn->eeh_freeze_count, drv_str, pci_str);
+	   "EEH: This PCI device has failed %d times since last reboot: "
+		"location=%s driver=%s pci addr=%s\n",
+		frozen_pdn->eeh_freeze_count, location, drv_str, pci_str);
 
 	/* Walk the various device drivers attached to this slot through
 	 * a reset sequence, giving each an opportunity to do what it needs
@@ -355,7 +367,7 @@
 	/* Tell all device drivers that they can resume operations */
 	pci_walk_bus(frozen_bus, eeh_report_resume, NULL);
 
-	return;
+	return frozen_pdn;
 	
 excess_failures:
 	/*
@@ -364,17 +376,18 @@
 	 * due to actual, failed cards.
 	 */
 	printk(KERN_ERR
-	   "EEH: PCI device %s - %s has failed %d times \n"
-	   "and has been permanently disabled.  Please try reseating\n"
-	   "this device or replacing it.\n",
-		drv_str, pci_str, frozen_pdn->eeh_freeze_count);
+	   "EEH: PCI device at location=%s driver=%s pci addr=%s \n"
+		"has failed %d times and has been permanently disabled. \n"
+		"Please try reseating this device or replacing it.\n",
+		location, drv_str, pci_str, frozen_pdn->eeh_freeze_count);
 	goto perm_error;
 
 hard_fail:
 	printk(KERN_ERR
-	   "EEH: Unable to recover from failure of PCI device %s - %s\n"
+	   "EEH: Unable to recover from failure of PCI device "
+	   "at location=%s driver=%s pci addr=%s \n"
 	   "Please try reseating this device or replacing it.\n",
-		drv_str, pci_str);
+		location, drv_str, pci_str);
 
 perm_error:
 	eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
@@ -384,6 +397,8 @@
 
 	/* Shut down the device drivers for good. */
 	pcibios_remove_pci_devices(frozen_bus);
+
+	return NULL;
 }
 
 /* ---------- end of file ---------- */
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 40020c6..45ccc68 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -18,6 +18,7 @@
  * Copyright (c) 2005 Linas Vepstas <linas@linas.org>
  */
 
+#include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/pci.h>
@@ -34,7 +35,7 @@
  */
 
 /* EEH event workqueue setup. */
-static spinlock_t eeh_eventlist_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(eeh_eventlist_lock);
 LIST_HEAD(eeh_eventlist);
 static void eeh_thread_launcher(void *);
 DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
@@ -56,38 +57,43 @@
 {
 	unsigned long flags;
 	struct eeh_event	*event;
+	struct pci_dn *pdn;
 
 	daemonize ("eehd");
+	set_current_state(TASK_INTERRUPTIBLE);
 
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
+	spin_lock_irqsave(&eeh_eventlist_lock, flags);
+	event = NULL;
 
-		spin_lock_irqsave(&eeh_eventlist_lock, flags);
-		event = NULL;
+	/* Unqueue the event, get ready to process. */
+	if (!list_empty(&eeh_eventlist)) {
+		event = list_entry(eeh_eventlist.next, struct eeh_event, list);
+		list_del(&event->list);
+	}
+	spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
 
-		/* Unqueue the event, get ready to process. */
-		if (!list_empty(&eeh_eventlist)) {
-			event = list_entry(eeh_eventlist.next, struct eeh_event, list);
-			list_del(&event->list);
-		}
-		spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+	if (event == NULL)
+		return 0;
 
-		if (event == NULL)
-			break;
+	/* Serialize processing of EEH events */
+	mutex_lock(&eeh_event_mutex);
+	eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
 
-		/* Serialize processing of EEH events */
-		mutex_lock(&eeh_event_mutex);
-		eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
+	printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
+	       pci_name(event->dev));
 
-		printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
-		       pci_name(event->dev));
+	pdn = handle_eeh_events(event);
 
-		handle_eeh_events(event);
+	eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
+	pci_dev_put(event->dev);
+	kfree(event);
+	mutex_unlock(&eeh_event_mutex);
 
-		eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
-		pci_dev_put(event->dev);
-		kfree(event);
-		mutex_unlock(&eeh_event_mutex);
+	/* If there are no new errors after an hour, clear the counter. */
+	if (pdn && pdn->eeh_freeze_count>0) {
+		msleep_interruptible (3600*1000);
+		if (pdn->eeh_freeze_count>0)
+			pdn->eeh_freeze_count--;
 	}
 
 	return 0;
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 2643078..d03a8b0 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -1,23 +1,24 @@
 /*
  * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
  *
- * Rewrite, cleanup: 
+ * Rewrite, cleanup:
  *
  * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2006 Olof Johansson <olof@lixom.net>
  *
  * Dynamic DMA mapping support, pSeries-specific parts, both SMP and LPAR.
  *
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
@@ -49,52 +50,46 @@
 
 #define DBG(fmt...)
 
-static void tce_build_pSeries(struct iommu_table *tbl, long index, 
-			      long npages, unsigned long uaddr, 
+static void tce_build_pSeries(struct iommu_table *tbl, long index,
+			      long npages, unsigned long uaddr,
 			      enum dma_data_direction direction)
 {
-	union tce_entry t;
-	union tce_entry *tp;
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
 
 	index <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	t.te_word = 0;
-	t.te_rdwr = 1; // Read allowed 
+	proto_tce = TCE_PCI_READ; // Read allowed
 
 	if (direction != DMA_TO_DEVICE)
-		t.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
-	tp = ((union tce_entry *)tbl->it_base) + index;
+	tcep = ((u64 *)tbl->it_base) + index;
 
 	while (npages--) {
 		/* can't move this out since we might cross LMB boundary */
-		t.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	
-		tp->te_word = t.te_word;
+		rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+		*tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
 
 		uaddr += TCE_PAGE_SIZE;
-		tp++;
+		tcep++;
 	}
 }
 
 
 static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages)
 {
-	union tce_entry t;
-	union tce_entry *tp;
+	u64 *tcep;
 
 	npages <<= TCE_PAGE_FACTOR;
 	index <<= TCE_PAGE_FACTOR;
 
-	t.te_word = 0;
-	tp  = ((union tce_entry *)tbl->it_base) + index;
-		
-	while (npages--) {
-		tp->te_word = t.te_word;
-		
-		tp++;
-	}
+	tcep = ((u64 *)tbl->it_base) + index;
+
+	while (npages--)
+		*(tcep++) = 0;
 }
 
 
@@ -103,43 +98,44 @@
 				enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce;
+	u64 proto_tce, tce;
+	u64 rpn;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	tce.te_rdwr = 1;
+	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
 	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index, 
-				   (u64)tcenum << 12, 
-				   tce.te_word );
-		
+		tce = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, tce);
+
 		if (rc && printk_ratelimit()) {
 			printk("tce_build_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
+			printk("\ttce val = 0x%lx\n", tce );
 			show_stack(current, (unsigned long *)__get_SP());
 		}
-			
+
 		tcenum++;
-		tce.te_rpn++;
+		rpn++;
 	}
 }
 
-static DEFINE_PER_CPU(void *, tce_page) = NULL;
+static DEFINE_PER_CPU(u64 *, tce_page) = NULL;
 
 static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
 				     long npages, unsigned long uaddr,
 				     enum dma_data_direction direction)
 {
 	u64 rc;
-	union tce_entry tce, *tcep;
+	u64 proto_tce;
+	u64 *tcep;
+	u64 rpn;
 	long l, limit;
 
 	if (TCE_PAGE_FACTOR == 0 && npages == 1)
@@ -152,7 +148,7 @@
 	 * from iommu_alloc{,_sg}()
 	 */
 	if (!tcep) {
-		tcep = (void *)__get_free_page(GFP_ATOMIC);
+		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
 		/* If allocation fails, fall back to the loop implementation */
 		if (!tcep)
 			return tce_build_pSeriesLP(tbl, tcenum, npages,
@@ -163,11 +159,10 @@
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-	tce.te_rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
-	tce.te_rdwr = 1;
+	rpn = (virt_to_abs(uaddr)) >> TCE_SHIFT;
+	proto_tce = TCE_PCI_READ;
 	if (direction != DMA_TO_DEVICE)
-		tce.te_pciwr = 1;
+		proto_tce |= TCE_PCI_WRITE;
 
 	/* We can map max one pageful of TCEs at a time */
 	do {
@@ -175,11 +170,11 @@
 		 * Set up the page with TCE data, looping through and setting
 		 * the values.
 		 */
-		limit = min_t(long, npages, 4096/sizeof(union tce_entry));
+		limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE);
 
 		for (l = 0; l < limit; l++) {
-			tcep[l] = tce;
-			tce.te_rpn++;
+			tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT;
+			rpn++;
 		}
 
 		rc = plpar_tce_put_indirect((u64)tbl->it_index,
@@ -195,7 +190,7 @@
 		printk("tce_buildmulti_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 		printk("\tnpages  = 0x%lx\n", (u64)npages);
-		printk("\ttce[0] val = 0x%lx\n", tcep[0].te_word);
+		printk("\ttce[0] val = 0x%lx\n", tcep[0]);
 		show_stack(current, (unsigned long *)__get_SP());
 	}
 }
@@ -203,23 +198,17 @@
 static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
 {
 	u64 rc;
-	union tce_entry tce;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-
 	while (npages--) {
-		rc = plpar_tce_put((u64)tbl->it_index,
-				   (u64)tcenum << 12,
-				   tce.te_word);
+		rc = plpar_tce_put((u64)tbl->it_index, (u64)tcenum << 12, 0);
 
 		if (rc && printk_ratelimit()) {
 			printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%ld\n", rc);
 			printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 			printk("\ttcenum  = 0x%lx\n", (u64)tcenum);
-			printk("\ttce val = 0x%lx\n", tce.te_word );
 			show_stack(current, (unsigned long *)__get_SP());
 		}
 
@@ -231,31 +220,24 @@
 static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages)
 {
 	u64 rc;
-	union tce_entry tce;
 
 	tcenum <<= TCE_PAGE_FACTOR;
 	npages <<= TCE_PAGE_FACTOR;
 
-	tce.te_word = 0;
-
-	rc = plpar_tce_stuff((u64)tbl->it_index,
-			   (u64)tcenum << 12,
-			   tce.te_word,
-			   npages);
+	rc = plpar_tce_stuff((u64)tbl->it_index, (u64)tcenum << 12, 0, npages);
 
 	if (rc && printk_ratelimit()) {
 		printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n");
 		printk("\trc      = %ld\n", rc);
 		printk("\tindex   = 0x%lx\n", (u64)tbl->it_index);
 		printk("\tnpages  = 0x%lx\n", (u64)npages);
-		printk("\ttce val = 0x%lx\n", tce.te_word );
 		show_stack(current, (unsigned long *)__get_SP());
 	}
 }
 
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
-				 struct iommu_table *tbl) 
+				 struct iommu_table *tbl)
 {
 	struct device_node *node;
 	unsigned long *basep;
@@ -275,16 +257,16 @@
 	memset((void *)tbl->it_base, 0, *sizep);
 
 	tbl->it_busno = phb->bus->number;
-	
+
 	/* Units of tce entries */
 	tbl->it_offset = phb->dma_window_base_cur >> PAGE_SHIFT;
-	
+
 	/* Test if we are going over 2GB of DMA space */
 	if (phb->dma_window_base_cur + phb->dma_window_size > 0x80000000ul) {
 		udbg_printf("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
-		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n"); 
+		panic("PCI_DMA: Unexpected number of IOAs under this PHB.\n");
 	}
-	
+
 	phb->dma_window_base_cur += phb->dma_window_size;
 
 	/* Set the tce table size - measured in entries */
@@ -299,30 +281,22 @@
  * iommu_table_setparms_lpar
  *
  * Function: On pSeries LPAR systems, return TCE table info, given a pci bus.
- *
- * ToDo: properly interpret the ibm,dma-window property.  The definition is:
- *	logical-bus-number	(1 word)
- *	phys-address		(#address-cells words)
- *	size			(#cell-size words)
- *
- * Currently we hard code these sizes (more or less).
  */
 static void iommu_table_setparms_lpar(struct pci_controller *phb,
 				      struct device_node *dn,
 				      struct iommu_table *tbl,
-				      unsigned int *dma_window)
+				      unsigned char *dma_window)
 {
-	tbl->it_busno  = PCI_DN(dn)->bussubno;
+	unsigned long offset, size;
 
-	/* TODO: Parse field size properties properly. */
-	tbl->it_size   = (((unsigned long)dma_window[4] << 32) |
-			   (unsigned long)dma_window[5]) >> PAGE_SHIFT;
-	tbl->it_offset = (((unsigned long)dma_window[2] << 32) |
-			   (unsigned long)dma_window[3]) >> PAGE_SHIFT;
+	tbl->it_busno  = PCI_DN(dn)->bussubno;
+	of_parse_dma_window(dn, dma_window, &tbl->it_index, &offset, &size);
+
 	tbl->it_base   = 0;
-	tbl->it_index  = dma_window[0];
 	tbl->it_blocksize  = 16;
 	tbl->it_type = TCE_PCI;
+	tbl->it_offset = offset >> PAGE_SHIFT;
+	tbl->it_size = size >> PAGE_SHIFT;
 }
 
 static void iommu_bus_setup_pSeries(struct pci_bus *bus)
@@ -357,13 +331,9 @@
 	if (isa_dn_orig)
 		of_node_put(isa_dn_orig);
 
-	/* Count number of direct PCI children of the PHB.
-	 * All PCI device nodes have class-code property, so it's
-	 * an easy way to find them.
-	 */
+	/* Count number of direct PCI children of the PHB. */
 	for (children = 0, tmp = dn->child; tmp; tmp = tmp->sibling)
-		if (get_property(tmp, "class-code", NULL))
-			children++;
+		children++;
 
 	DBG("Children: %d\n", children);
 
@@ -394,10 +364,11 @@
 	pci->phb->dma_window_size = 0x8000000ul;
 	pci->phb->dma_window_base_cur = 0x8000000ul;
 
-	tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+	tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+			   pci->phb->node);
 
 	iommu_table_setparms(pci->phb, dn, tbl);
-	pci->iommu_table = iommu_init_table(tbl);
+	pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
 
 	/* Divide the rest (1.75GB) among the children */
 	pci->phb->dma_window_size = 0x80000000ul;
@@ -414,7 +385,7 @@
 	struct iommu_table *tbl;
 	struct device_node *dn, *pdn;
 	struct pci_dn *ppci;
-	unsigned int *dma_window = NULL;
+	unsigned char *dma_window = NULL;
 
 	DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
 
@@ -422,7 +393,7 @@
 
 	/* Find nearest ibm,dma-window, walking up the device tree */
 	for (pdn = dn; pdn != NULL; pdn = pdn->parent) {
-		dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
+		dma_window = get_property(pdn, "ibm,dma-window", NULL);
 		if (dma_window != NULL)
 			break;
 	}
@@ -440,12 +411,12 @@
 
 		ppci->bussubno = bus->number;
 
-		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
-						    GFP_KERNEL);
-	
+		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+				   ppci->phb->node);
+
 		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
 
-		ppci->iommu_table = iommu_init_table(tbl);
+		ppci->iommu_table = iommu_init_table(tbl, ppci->phb->node);
 	}
 
 	if (pdn != dn)
@@ -468,9 +439,11 @@
 	 */
 	if (!dev->bus->self) {
 		DBG(" --> first child, no bridge. Allocating iommu table.\n");
-		tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
+		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+				   PCI_DN(dn)->phb->node);
 		iommu_table_setparms(PCI_DN(dn)->phb, dn, tbl);
-		PCI_DN(mydn)->iommu_table = iommu_init_table(tbl);
+		PCI_DN(dn)->iommu_table = iommu_init_table(tbl,
+						PCI_DN(dn)->phb->node);
 
 		return;
 	}
@@ -516,7 +489,7 @@
 {
 	struct device_node *pdn, *dn;
 	struct iommu_table *tbl;
-	int *dma_window = NULL;
+	unsigned char *dma_window = NULL;
 	struct pci_dn *pci;
 
 	DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, pci_name(dev));
@@ -531,8 +504,7 @@
 
 	for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
 	     pdn = pdn->parent) {
-		dma_window = (unsigned int *)
-			get_property(pdn, "ibm,dma-window", NULL);
+		dma_window = get_property(pdn, "ibm,dma-window", NULL);
 		if (dma_window)
 			break;
 	}
@@ -553,12 +525,12 @@
 		/* iommu_table_setparms_lpar needs bussubno. */
 		pci->bussubno = pci->phb->bus->number;
 
-		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
-						    GFP_KERNEL);
+		tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
+				   pci->phb->node);
 
 		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
 
-		pci->iommu_table = iommu_init_table(tbl);
+		pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
 	}
 
 	if (pdn != dn)
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c
index e0000ce..2e4e040 100644
--- a/arch/powerpc/platforms/pseries/rtasd.c
+++ b/arch/powerpc/platforms/pseries/rtasd.c
@@ -348,7 +348,7 @@
 		return 0;
 
 	if (error == -EINVAL) {
-		printk(KERN_INFO "rtasd: surveillance not supported\n");
+		printk(KERN_DEBUG "rtasd: surveillance not supported\n");
 		return 0;
 	}
 
@@ -440,7 +440,7 @@
 		goto error;
 	}
 
-	printk(KERN_INFO "RTAS daemon started\n");
+	printk(KERN_DEBUG "RTAS daemon started\n");
 
 	DEBUG("will sleep for %d milliseconds\n", (30000/rtas_event_scan_rate));
 
@@ -487,7 +487,7 @@
 
 	/* No RTAS */
 	if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
-		printk(KERN_INFO "rtasd: no event-scan on system\n");
+		printk(KERN_DEBUG "rtasd: no event-scan on system\n");
 		return -ENODEV;
 	}
 
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c
index 5064349..77a5bb1 100644
--- a/arch/powerpc/platforms/pseries/scanlog.c
+++ b/arch/powerpc/platforms/pseries/scanlog.c
@@ -107,9 +107,9 @@
 			/* Break to sleep default time */
 			break;
 		    default:
-			if (status > 9900 && status <= 9905) {
-				wait_time = rtas_extended_busy_delay_time(status);
-			} else {
+			/* Assume extended busy */
+			wait_time = rtas_busy_delay_time(status);
+			if (!wait_time) {
 				printk(KERN_ERR "scanlog: unknown error from rtas: %d\n", status);
 				return -EIO;
 			}
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 3ba8783..1e28518 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -235,14 +235,14 @@
 	if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
 		vpa_init(boot_cpuid);
 		if (get_lppaca()->shared_proc) {
-			printk(KERN_INFO "Using shared processor idle loop\n");
+			printk(KERN_DEBUG "Using shared processor idle loop\n");
 			ppc_md.power_save = pseries_shared_idle_sleep;
 		} else {
-			printk(KERN_INFO "Using dedicated idle loop\n");
+			printk(KERN_DEBUG "Using dedicated idle loop\n");
 			ppc_md.power_save = pseries_dedicated_idle_sleep;
 		}
 	} else {
-		printk(KERN_INFO "Using default idle loop\n");
+		printk(KERN_DEBUG "Using default idle loop\n");
 	}
 
 	if (firmware_has_feature(FW_FEATURE_LPAR))
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
deleted file mode 100644
index 8e53e04..0000000
--- a/arch/powerpc/platforms/pseries/vio.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * IBM PowerPC pSeries Virtual I/O Infrastructure Support.
- *
- *    Copyright (c) 2003-2005 IBM Corp.
- *     Dave Engebretsen engebret@us.ibm.com
- *     Santiago Leon santil@us.ibm.com
- *     Hollis Blanchard <hollisb@us.ibm.com>
- *     Stephen Rothwell
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/kobject.h>
-#include <asm/iommu.h>
-#include <asm/dma.h>
-#include <asm/prom.h>
-#include <asm/vio.h>
-#include <asm/hvcall.h>
-#include <asm/tce.h>
-
-extern struct subsystem devices_subsys; /* needed for vio_find_name() */
-
-static void probe_bus_pseries(void)
-{
-	struct device_node *node_vroot, *of_node;
-
-	node_vroot = find_devices("vdevice");
-	if ((node_vroot == NULL) || (node_vroot->child == NULL))
-		/* this machine doesn't do virtual IO, and that's ok */
-		return;
-
-	/*
-	 * Create struct vio_devices for each virtual device in the device tree.
-	 * Drivers will associate with them later.
-	 */
-	for (of_node = node_vroot->child; of_node != NULL;
-			of_node = of_node->sibling) {
-		printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, of_node);
-		vio_register_device_node(of_node);
-	}
-}
-
-/**
- * vio_match_device_pseries: - Tell if a pSeries VIO device matches a
- *	vio_device_id
- */
-static int vio_match_device_pseries(const struct vio_device_id *id,
-		const struct vio_dev *dev)
-{
-	return (strncmp(dev->type, id->type, strlen(id->type)) == 0) &&
-			device_is_compatible(dev->dev.platform_data, id->compat);
-}
-
-static void vio_release_device_pseries(struct device *dev)
-{
-	/* XXX free TCE table */
-	of_node_put(dev->platform_data);
-}
-
-static ssize_t viodev_show_devspec(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct device_node *of_node = dev->platform_data;
-
-	return sprintf(buf, "%s\n", of_node->full_name);
-}
-DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
-
-static void vio_unregister_device_pseries(struct vio_dev *viodev)
-{
-	device_remove_file(&viodev->dev, &dev_attr_devspec);
-}
-
-static struct vio_bus_ops vio_bus_ops_pseries = {
-	.match = vio_match_device_pseries,
-	.unregister_device = vio_unregister_device_pseries,
-	.release_device = vio_release_device_pseries,
-};
-
-/**
- * vio_bus_init_pseries: - Initialize the pSeries virtual IO bus
- */
-static int __init vio_bus_init_pseries(void)
-{
-	int err;
-
-	err = vio_bus_init(&vio_bus_ops_pseries);
-	if (err == 0)
-		probe_bus_pseries();
-	return err;
-}
-
-__initcall(vio_bus_init_pseries);
-
-/**
- * vio_build_iommu_table: - gets the dma information from OF and
- *	builds the TCE tree.
- * @dev: the virtual device.
- *
- * Returns a pointer to the built tce tree, or NULL if it can't
- * find property.
-*/
-static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
-{
-	unsigned int *dma_window;
-	struct iommu_table *newTceTable;
-	unsigned long offset;
-	int dma_window_property_size;
-
-	dma_window = (unsigned int *) get_property(dev->dev.platform_data, "ibm,my-dma-window", &dma_window_property_size);
-	if(!dma_window) {
-		return NULL;
-	}
-
-	newTceTable = (struct iommu_table *) kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
-
-	/*  There should be some code to extract the phys-encoded offset
-		using prom_n_addr_cells(). However, according to a comment
-		on earlier versions, it's always zero, so we don't bother */
-	offset = dma_window[1] >>  PAGE_SHIFT;
-
-	/* TCE table size - measured in tce entries */
-	newTceTable->it_size		= dma_window[4] >> PAGE_SHIFT;
-	/* offset for VIO should always be 0 */
-	newTceTable->it_offset		= offset;
-	newTceTable->it_busno		= 0;
-	newTceTable->it_index		= (unsigned long)dma_window[0];
-	newTceTable->it_type		= TCE_VB;
-
-	return iommu_init_table(newTceTable);
-}
-
-/**
- * vio_register_device_node: - Register a new vio device.
- * @of_node:	The OF node for this device.
- *
- * Creates and initializes a vio_dev structure from the data in
- * of_node (dev.platform_data) and adds it to the list of virtual devices.
- * Returns a pointer to the created vio_dev or NULL if node has
- * NULL device_type or compatible fields.
- */
-struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node)
-{
-	struct vio_dev *viodev;
-	unsigned int *unit_address;
-	unsigned int *irq_p;
-
-	/* we need the 'device_type' property, in order to match with drivers */
-	if ((NULL == of_node->type)) {
-		printk(KERN_WARNING
-			"%s: node %s missing 'device_type'\n", __FUNCTION__,
-			of_node->name ? of_node->name : "<unknown>");
-		return NULL;
-	}
-
-	unit_address = (unsigned int *)get_property(of_node, "reg", NULL);
-	if (!unit_address) {
-		printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__,
-			of_node->name ? of_node->name : "<unknown>");
-		return NULL;
-	}
-
-	/* allocate a vio_dev for this node */
-	viodev = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
-	if (!viodev) {
-		return NULL;
-	}
-	memset(viodev, 0, sizeof(struct vio_dev));
-
-	viodev->dev.platform_data = of_node_get(of_node);
-
-	viodev->irq = NO_IRQ;
-	irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL);
-	if (irq_p) {
-		int virq = virt_irq_create_mapping(*irq_p);
-		if (virq == NO_IRQ) {
-			printk(KERN_ERR "Unable to allocate interrupt "
-			       "number for %s\n", of_node->full_name);
-		} else
-			viodev->irq = irq_offset_up(virq);
-	}
-
-	snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address);
-	viodev->name = of_node->name;
-	viodev->type = of_node->type;
-	viodev->unit_address = *unit_address;
-	viodev->iommu_table = vio_build_iommu_table(viodev);
-
-	/* register with generic device framework */
-	if (vio_register_device(viodev) == NULL) {
-		/* XXX free TCE table */
-		kfree(viodev);
-		return NULL;
-	}
-	device_create_file(&viodev->dev, &dev_attr_devspec);
-
-	return viodev;
-}
-EXPORT_SYMBOL(vio_register_device_node);
-
-/**
- * vio_get_attribute: - get attribute for virtual device
- * @vdev:	The vio device to get property.
- * @which:	The property/attribute to be extracted.
- * @length:	Pointer to length of returned data size (unused if NULL).
- *
- * Calls prom.c's get_property() to return the value of the
- * attribute specified by the preprocessor constant @which
-*/
-const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length)
-{
-	return get_property(vdev->dev.platform_data, (char*)which, length);
-}
-EXPORT_SYMBOL(vio_get_attribute);
-
-/* vio_find_name() - internal because only vio.c knows how we formatted the
- * kobject name
- * XXX once vio_bus_type.devices is actually used as a kset in
- * drivers/base/bus.c, this function should be removed in favor of
- * "device_find(kobj_name, &vio_bus_type)"
- */
-static struct vio_dev *vio_find_name(const char *kobj_name)
-{
-	struct kobject *found;
-
-	found = kset_find_obj(&devices_subsys.kset, kobj_name);
-	if (!found)
-		return NULL;
-
-	return to_vio_dev(container_of(found, struct device, kobj));
-}
-
-/**
- * vio_find_node - find an already-registered vio_dev
- * @vnode: device_node of the virtual device we're looking for
- */
-struct vio_dev *vio_find_node(struct device_node *vnode)
-{
-	uint32_t *unit_address;
-	char kobj_name[BUS_ID_SIZE];
-
-	/* construct the kobject name from the device node */
-	unit_address = (uint32_t *)get_property(vnode, "reg", NULL);
-	if (!unit_address)
-		return NULL;
-	snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address);
-
-	return vio_find_name(kobj_name);
-}
-EXPORT_SYMBOL(vio_find_node);
-
-int vio_enable_interrupts(struct vio_dev *dev)
-{
-	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE);
-	if (rc != H_SUCCESS)
-		printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc);
-	return rc;
-}
-EXPORT_SYMBOL(vio_enable_interrupts);
-
-int vio_disable_interrupts(struct vio_dev *dev)
-{
-	int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE);
-	if (rc != H_SUCCESS)
-		printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc);
-	return rc;
-}
-EXPORT_SYMBOL(vio_disable_interrupts);
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 2d60ea3..b14f9b5 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -522,7 +522,7 @@
 
 	np = of_find_node_by_type(NULL, "interrupt-controller");
 	if (!np) {
-		printk(KERN_WARNING "xics: no ISA interrupt controller\n");
+		printk(KERN_DEBUG "xics: no ISA interrupt controller\n");
 		xics_irq_8259_cascade_real = -1;
 		xics_irq_8259_cascade = -1;
 	} else {
@@ -641,23 +641,26 @@
 	ops->cppr_info(cpu, 0x00);
 	iosync();
 
+	/* Clear IPI */
+	ops->qirr_info(cpu, 0xff);
+
+	/*
+	 * we need to EOI the IPI if we got here from kexec down IPI
+	 *
+	 * probably need to check all the other interrupts too
+	 * should we be flagging idle loop instead?
+	 * or creating some task to be scheduled?
+	 */
+	ops->xirr_info_set(cpu, XICS_IPI);
+
 	/*
 	 * Some machines need to have at least one cpu in the GIQ,
 	 * so leave the master cpu in the group.
 	 */
-	if (secondary) {
-		/*
-		 * we need to EOI the IPI if we got here from kexec down IPI
-		 *
-		 * probably need to check all the other interrupts too
-		 * should we be flagging idle loop instead?
-		 * or creating some task to be scheduled?
-		 */
-		ops->xirr_info_set(cpu, XICS_IPI);
+	if (secondary)
 		rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
 			(1UL << interrupt_server_size) - 1 -
 			default_distrib_server, 0);
-	}
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 4c2b356..cef95b0 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -1,3 +1,7 @@
+ifeq ($(CONFIG_PPC64),y)
+EXTRA_CFLAGS			+= -mno-minimal-toc
+endif
+
 obj-$(CONFIG_MPIC)		+= mpic.o
 obj-$(CONFIG_PPC_INDIRECT_PCI)	+= indirect_pci.o
 obj-$(CONFIG_PPC_I8259)		+= i8259.o
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index 38087bd..6232091 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -246,7 +246,7 @@
 	iommu_table_dart.it_base = (unsigned long)dart_vbase;
 	iommu_table_dart.it_index = 0;
 	iommu_table_dart.it_blocksize = 1;
-	iommu_init_table(&iommu_table_dart);
+	iommu_init_table(&iommu_table_dart, -1);
 
 	/* Reserve the last page of the DART to avoid possible prefetch
 	 * past the DART mapped area
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index ceb5846..71a3275 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -372,7 +372,7 @@
 {
 	struct device_node *np;
 	unsigned int i;
-	struct platform_device *usb_dev;
+	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr = NULL;
 	int ret;
 
 	for (np = NULL, i = 0;
@@ -393,15 +393,15 @@
 		r[1].end = np->intrs[0].line;
 		r[1].flags = IORESOURCE_IRQ;
 
-		usb_dev =
-		    platform_device_register_simple("fsl-usb2-mph", i, r, 2);
-		if (IS_ERR(usb_dev)) {
-			ret = PTR_ERR(usb_dev);
+		usb_dev_mph =
+		    platform_device_register_simple("fsl-ehci", i, r, 2);
+		if (IS_ERR(usb_dev_mph)) {
+			ret = PTR_ERR(usb_dev_mph);
 			goto err;
 		}
 
-		usb_dev->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask;
+		usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
+		usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
 
 		usb_data.operating_mode = FSL_USB2_MPH_HOST;
 
@@ -417,31 +417,14 @@
 		usb_data.phy_mode = determine_usb_phy(prop);
 
 		ret =
-		    platform_device_add_data(usb_dev, &usb_data,
+		    platform_device_add_data(usb_dev_mph, &usb_data,
 					     sizeof(struct
 						    fsl_usb2_platform_data));
 		if (ret)
-			goto unreg;
+			goto unreg_mph;
 	}
 
-	return 0;
-
-unreg:
-	platform_device_unregister(usb_dev);
-err:
-	return ret;
-}
-
-arch_initcall(fsl_usb_of_init);
-
-static int __init fsl_usb_dr_of_init(void)
-{
-	struct device_node *np;
-	unsigned int i;
-	struct platform_device *usb_dev;
-	int ret;
-
-	for (np = NULL, i = 0;
+	for (np = NULL;
 	     (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL;
 	     i++) {
 		struct resource r[2];
@@ -453,21 +436,21 @@
 
 		ret = of_address_to_resource(np, 0, &r[0]);
 		if (ret)
-			goto err;
+			goto unreg_mph;
 
 		r[1].start = np->intrs[0].line;
 		r[1].end = np->intrs[0].line;
 		r[1].flags = IORESOURCE_IRQ;
 
-		usb_dev =
-		    platform_device_register_simple("fsl-usb2-dr", i, r, 2);
-		if (IS_ERR(usb_dev)) {
-			ret = PTR_ERR(usb_dev);
+		usb_dev_dr =
+		    platform_device_register_simple("fsl-ehci", i, r, 2);
+		if (IS_ERR(usb_dev_dr)) {
+			ret = PTR_ERR(usb_dev_dr);
 			goto err;
 		}
 
-		usb_dev->dev.coherent_dma_mask = 0xffffffffUL;
-		usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask;
+		usb_dev_dr->dev.coherent_dma_mask = 0xffffffffUL;
+		usb_dev_dr->dev.dma_mask = &usb_dev_dr->dev.coherent_dma_mask;
 
 		usb_data.operating_mode = FSL_USB2_DR_HOST;
 
@@ -475,19 +458,22 @@
 		usb_data.phy_mode = determine_usb_phy(prop);
 
 		ret =
-		    platform_device_add_data(usb_dev, &usb_data,
+		    platform_device_add_data(usb_dev_dr, &usb_data,
 					     sizeof(struct
 						    fsl_usb2_platform_data));
 		if (ret)
-			goto unreg;
+			goto unreg_dr;
 	}
-
 	return 0;
 
-unreg:
-	platform_device_unregister(usb_dev);
+unreg_dr:
+	if (usb_dev_dr)
+		platform_device_unregister(usb_dev_dr);
+unreg_mph:
+	if (usb_dev_mph)
+		platform_device_unregister(usb_dev_mph);
 err:
 	return ret;
 }
 
-arch_initcall(fsl_usb_dr_of_init);
+arch_initcall(fsl_usb_of_init);
diff --git a/arch/powerpc/sysdev/mmio_nvram.c b/arch/powerpc/sysdev/mmio_nvram.c
index 74e0d31..615350d 100644
--- a/arch/powerpc/sysdev/mmio_nvram.c
+++ b/arch/powerpc/sysdev/mmio_nvram.c
@@ -32,7 +32,7 @@
 
 static void __iomem *mmio_nvram_start;
 static long mmio_nvram_len;
-static spinlock_t mmio_nvram_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(mmio_nvram_lock);
 
 static ssize_t mmio_nvram_read(char *buf, size_t count, loff_t *index)
 {
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7dcdfcb..bffe50d 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -829,7 +829,27 @@
 	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0);
 }
 
+void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
+{
+	u32 v;
 
+	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
+	v &= ~MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK;
+	v |= MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(clock_ratio);
+	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
+}
+
+void __init mpic_set_serial_int(struct mpic *mpic, int enable)
+{
+	u32 v;
+
+	v = mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1);
+	if (enable)
+		v |= MPIC_GREG_GLOBAL_CONF_1_SIE;
+	else
+		v &= ~MPIC_GREG_GLOBAL_CONF_1_SIE;
+	mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_1, v);
+}
 
 void mpic_irq_set_priority(unsigned int irq, unsigned int pri)
 {
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 4735b41..0741df8 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -26,9 +26,6 @@
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/xmon.h>
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
 #include <asm/processor.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index e9a8f5d..b55de4f 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -40,6 +40,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_NEXT_BIT
+	bool
+	default y
+
 config SCHED_NO_NO_OMIT_FRAME_POINTER
 	bool
 	default y
diff --git a/arch/ppc/boot/lib/Makefile b/arch/ppc/boot/lib/Makefile
index 80c84d5..2f995f7 100644
--- a/arch/ppc/boot/lib/Makefile
+++ b/arch/ppc/boot/lib/Makefile
@@ -5,7 +5,7 @@
 CFLAGS_kbd.o	:= -Idrivers/char
 CFLAGS_vreset.o := -Iarch/ppc/boot/include
 
-zlib  := infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
+zlib  := inffast.c inflate.c inftrees.c
 	 
 lib-y += $(zlib:.c=.o) div64.o
 lib-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o
diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c
index 84d65a8..a469ba4 100644
--- a/arch/ppc/kernel/machine_kexec.c
+++ b/arch/ppc/kernel/machine_kexec.c
@@ -25,8 +25,8 @@
 				unsigned long reboot_code_buffer,
 				unsigned long start_address) ATTRIB_NORET;
 
-const extern unsigned char relocate_new_kernel[];
-const extern unsigned int relocate_new_kernel_size;
+extern const unsigned char relocate_new_kernel[];
+extern const unsigned int relocate_new_kernel_size;
 
 void machine_shutdown(void)
 {
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 809673a..d20accf 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1032,7 +1032,6 @@
 		return -EINVAL;
 
 	vma->vm_pgoff = offset >> PAGE_SHIFT;
-	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
 	vma->vm_page_prot = __pci_mmap_set_pgprot(dev, rp,
 						  vma->vm_page_prot,
 						  mmap_state, write_combine);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 1f79e84..4b4607d 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -475,7 +475,7 @@
 
 	/* register CPU devices */
 	for_each_possible_cpu(i)
-		register_cpu(&cpu_devices[i], i, NULL);
+		register_cpu(&cpu_devices[i], i);
 
 	/* call platform init */
 	if (ppc_md.init != NULL) {
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 386e000..c9bd184 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -583,7 +583,7 @@
 		mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
 		pmd = pmd_offset(pgd_offset(mm, address), address);
 		if (!pmd_none(*pmd))
-			add_hash_page(mm->context, address, pmd_val(*pmd));
+			add_hash_page(mm->context.id, address, pmd_val(*pmd));
 	}
 #endif
 }
diff --git a/arch/ppc/mm/mmu_context.c b/arch/ppc/mm/mmu_context.c
index b4a4b3f..8784f37 100644
--- a/arch/ppc/mm/mmu_context.c
+++ b/arch/ppc/mm/mmu_context.c
@@ -30,7 +30,7 @@
 #include <asm/mmu_context.h>
 #include <asm/tlbflush.h>
 
-mm_context_t next_mmu_context;
+unsigned long next_mmu_context;
 unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1];
 #ifdef FEW_CONTEXTS
 atomic_t nr_free_contexts;
diff --git a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
index 6c3dc3c..606b023 100644
--- a/arch/ppc/mm/tlb.c
+++ b/arch/ppc/mm/tlb.c
@@ -42,7 +42,7 @@
 
 	if (Hash != 0) {
 		ptephys = __pa(ptep) & PAGE_MASK;
-		flush_hash_pages(mm->context, addr, ptephys, 1);
+		flush_hash_pages(mm->context.id, addr, ptephys, 1);
 	}
 }
 
@@ -102,7 +102,7 @@
 	pmd_t *pmd;
 	unsigned long pmd_end;
 	int count;
-	unsigned int ctx = mm->context;
+	unsigned int ctx = mm->context.id;
 
 	if (Hash == 0) {
 		_tlbia();
@@ -166,7 +166,7 @@
 	mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
 	pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
 	if (!pmd_none(*pmd))
-		flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
+		flush_hash_pages(mm->context.id, vmaddr, pmd_val(*pmd), 1);
 	FINISH_FLUSH;
 }
 
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig
index 174ddbc..293bd48 100644
--- a/arch/ppc/platforms/4xx/Kconfig
+++ b/arch/ppc/platforms/4xx/Kconfig
@@ -183,7 +183,7 @@
 
 config BIOS_FIXUP
 	bool
-	depends on BUBINGA || EP405 || SYCAMORE || WALNUT
+	depends on BUBINGA || EP405 || SYCAMORE || WALNUT || CPCI405
 	default y
 
 # OAK doesn't exist but wanted to keep this around for any future 403GCX boards
diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c
index 6571e39..970b698 100644
--- a/arch/ppc/platforms/4xx/cpci405.c
+++ b/arch/ppc/platforms/4xx/cpci405.c
@@ -1,10 +1,12 @@
 /*
  * Board setup routines for the esd CPCI-405 cPCI Board.
  *
- * Author: Stefan Roese
- *         stefan.roese@esd-electronics.com
+ * Copyright 2001-2006 esd electronic system design - hannover germany
  *
- * Copyright 2001 esd electronic system design - hannover germany
+ * Authors: Matthias Fuchs
+ *          matthias.fuchs@esd-electronics.com
+ *          Stefan Roese
+ *          stefan.roese@esd-electronics.com
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -20,9 +22,17 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/todc.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
 #include <asm/ocp.h>
+#include <asm/ibm_ocp_pci.h>
+#include <platforms/4xx/ibm405gp.h>
 
+#ifdef CONFIG_GEN_RTC
 void *cpci405_nvram;
+#endif
+
+extern bd_t __res;
 
 /*
  * Some IRQs unique to CPCI-405.
@@ -36,18 +46,69 @@
 	 *      A       B       C       D
 	 */
 	{
-		{28,	28,	28,	28},	/* IDSEL 15 - cPCI slot 8 */
-		{29,	29,	29,	29},	/* IDSEL 16 - cPCI slot 7 */
-		{30,	30,	30,	30},	/* IDSEL 17 - cPCI slot 6 */
-		{27,	27,	27,	27},	/* IDSEL 18 - cPCI slot 5 */
-		{28,	28,	28,	28},	/* IDSEL 19 - cPCI slot 4 */
-		{29,	29,	29,	29},	/* IDSEL 20 - cPCI slot 3 */
-		{30,	30,	30,	30},	/* IDSEL 21 - cPCI slot 2 */
+		{28,	29,	30,	27},	/* IDSEL 15 - cPCI slot 8 */
+		{29,	30,	27,	28},	/* IDSEL 16 - cPCI slot 7 */
+		{30,	27,	28,	29},	/* IDSEL 17 - cPCI slot 6 */
+		{27,	28,	29,	30},	/* IDSEL 18 - cPCI slot 5 */
+		{28,	29,	30,	27},	/* IDSEL 19 - cPCI slot 4 */
+		{29,	30,	27,	28},	/* IDSEL 20 - cPCI slot 3 */
+		{30,	27,	28,	29},	/* IDSEL 21 - cPCI slot 2 */
         };
 	const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4;
 	return PCI_IRQ_TABLE_LOOKUP;
 };
 
+/* The serial clock for the chip is an internal clock determined by
+ * different clock speeds/dividers.
+ * Calculate the proper input baud rate and setup the serial driver.
+ */
+static void __init
+cpci405_early_serial_map(void)
+{
+	u32 uart_div;
+	int uart_clock;
+	struct uart_port port;
+
+         /* Calculate the serial clock input frequency
+          *
+          * The uart clock is the cpu frequency (provided in the board info
+          * structure) divided by the external UART Divisor.
+          */
+	uart_div = ((mfdcr(DCRN_CHCR_BASE) & CHR0_UDIV) >> 1) + 1;
+	uart_clock = __res.bi_procfreq / uart_div;
+
+	/* Setup serial port access */
+	memset(&port, 0, sizeof(port));
+#if defined(CONFIG_UART0_TTYS0)
+	port.membase = (void*)UART0_IO_BASE;
+	port.irq = UART0_INT;
+#else
+	port.membase = (void*)UART1_IO_BASE;
+	port.irq = UART1_INT;
+#endif
+	port.uartclk = uart_clock;
+	port.regshift = 0;
+	port.iotype = UPIO_MEM;
+	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+	port.line = 0;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 0 failed\n");
+	}
+#if defined(CONFIG_UART0_TTYS0)
+	port.membase = (void*)UART1_IO_BASE;
+	port.irq = UART1_INT;
+#else
+	port.membase = (void*)UART0_IO_BASE;
+	port.irq = UART0_INT;
+#endif
+	port.line = 1;
+
+	if (early_serial_setup(&port) != 0) {
+		printk("Early serial init of port 1 failed\n");
+	}
+}
+
 void __init
 cpci405_setup_arch(void)
 {
@@ -55,14 +116,68 @@
 
 	ibm_ocp_set_emac(0, 0);
 
-	TODC_INIT(TODC_TYPE_MK48T35, cpci405_nvram, cpci405_nvram, cpci405_nvram, 8);
+        cpci405_early_serial_map();
+
+#ifdef CONFIG_GEN_RTC
+	TODC_INIT(TODC_TYPE_MK48T35,
+		  cpci405_nvram, cpci405_nvram, cpci405_nvram, 8);
+#endif
+}
+
+void __init
+bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip)
+{
+	unsigned int bar_response, bar;
+
+	/* Disable region first */
+	out_le32((void *) &(pcip->pmm[0].ma), 0x00000000);
+	/* PLB starting addr, PCI: 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].la), 0x80000000);
+	/* PCI start addr, 0x80000000 */
+	out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE);
+	/* 512MB range of PLB to PCI */
+	out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000);
+	/* Enable no pre-fetch, enable region */
+	out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff -
+						(PPC405_PCI_UPPER_MEM -
+						 PPC405_PCI_MEM_BASE)) | 0x01));
+
+	/* Disable region one */
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[1].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm1ms), 0x00000001);
+
+	/* Disable region two */
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].la), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000);
+	out_le32((void *) &(pcip->pmm[2].ma), 0x00000000);
+	out_le32((void *) &(pcip->ptm2ms), 0x00000000);
+	out_le32((void *) &(pcip->ptm2la), 0x00000000);
+
+	/* Zero config bars */
+	for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) {
+		early_write_config_dword(hose, hose->first_busno,
+					 PCI_FUNC(hose->first_busno), bar,
+					 0x00000000);
+		early_read_config_dword(hose, hose->first_busno,
+					PCI_FUNC(hose->first_busno), bar,
+					&bar_response);
+	}
 }
 
 void __init
 cpci405_map_io(void)
 {
 	ppc4xx_map_io();
+
+#ifdef CONFIG_GEN_RTC
 	cpci405_nvram = ioremap(CPCI405_NVRAM_PADDR, CPCI405_NVRAM_SIZE);
+#endif
 }
 
 void __init
@@ -74,9 +189,11 @@
 	ppc_md.setup_arch = cpci405_setup_arch;
 	ppc_md.setup_io_mappings = cpci405_map_io;
 
+#ifdef CONFIG_GEN_RTC
 	ppc_md.time_init = todc_time_init;
 	ppc_md.set_rtc_time = todc_set_rtc_time;
 	ppc_md.get_rtc_time = todc_get_rtc_time;
 	ppc_md.nvram_read_val = todc_direct_read_val;
 	ppc_md.nvram_write_val = todc_direct_write_val;
+#endif
 }
diff --git a/arch/ppc/platforms/4xx/cpci405.h b/arch/ppc/platforms/4xx/cpci405.h
index e27f7cb..f5a5c0c 100644
--- a/arch/ppc/platforms/4xx/cpci405.h
+++ b/arch/ppc/platforms/4xx/cpci405.h
@@ -1,37 +1,29 @@
 /*
  * CPCI-405 board specific definitions
  *
- * Copyright (c) 2001 Stefan Roese (stefan.roese@esd-electronics.com)
+ * Copyright 2001-2006 esd electronic system design - hannover germany
+ *
+ * Authors: Matthias Fuchs
+ *          matthias.fuchs@esd-electronics.com
+ *          Stefan Roese
+ *          stefan.roese@esd-electronics.com
  */
 
 #ifdef __KERNEL__
-#ifndef __ASM_CPCI405_H__
-#define __ASM_CPCI405_H__
+#ifndef __CPCI405_H__
+#define __CPCI405_H__
 
 #include <linux/config.h>
-
-/* We have a 405GP core */
 #include <platforms/4xx/ibm405gp.h>
-
 #include <asm/ppcboot.h>
 
-#ifndef __ASSEMBLY__
-/* Some 4xx parts use a different timebase frequency from the internal clock.
-*/
-#define bi_tbfreq bi_intfreq
-
 /* Map for the NVRAM space */
 #define CPCI405_NVRAM_PADDR	((uint)0xf0200000)
 #define CPCI405_NVRAM_SIZE	((uint)32*1024)
 
-#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK
-#define BASE_BAUD		201600
-#else
-#define BASE_BAUD		691200
-#endif
+#define BASE_BAUD		0
 
-#define PPC4xx_MACHINE_NAME "esd CPCI-405"
+#define PPC4xx_MACHINE_NAME     "esd CPCI-405"
 
-#endif /* !__ASSEMBLY__ */
-#endif	/* __ASM_CPCI405_H__ */
+#endif	/* __CPCI405_H__ */
 #endif /* __KERNEL__ */
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index c9e0aee..4368dc3 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -379,13 +379,12 @@
                                         PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
                 dev->irq = 10;
                 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
-		pci_dev_put(dev);
-        }
 
-	if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
+		if ((dev = pci_get_device(PCI_VENDOR_ID_VIA,
                                         PCI_DEVICE_ID_VIA_82C586_2, dev))) {
-                dev->irq = 11;
-                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+	                dev->irq = 11;
+	                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+		}
 		pci_dev_put(dev);
         }
 }
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 1af2c00..5c4932c 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -186,7 +186,7 @@
 		},
 	},
 	[MPC83xx_USB2_DR] = {
-		.name = "fsl-usb2-dr",
+		.name = "fsl-ehci",
 		.id	= 1,
 		.num_resources	 = 2,
 		.resource = (struct resource[]) {
@@ -203,8 +203,8 @@
 		},
 	},
 	[MPC83xx_USB2_MPH] = {
-		.name = "fsl-usb2-mph",
-		.id	= 1,
+		.name = "fsl-ehci",
+		.id	= 2,
 		.num_resources	 = 2,
 		.resource = (struct resource[]) {
 			{
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 01c5c08..821a141 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -446,6 +446,14 @@
 	  The HZ timer is switched off in idle by default. That means the
 	  HZ timer is already disabled at boot time.
 
+config S390_HYPFS_FS
+	bool "s390 hypervisor file system support"
+	select SYS_HYPERVISOR
+	default y
+	help
+	  This is a virtual file system intended to provide accounting
+	  information in an s390 hypervisor environment.
+
 config KEXEC
 	bool "kexec system call (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 7bb16fb..b3791fb 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -76,7 +76,7 @@
 head-y		:= arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
 
 core-y		+= arch/$(ARCH)/mm/ arch/$(ARCH)/kernel/ arch/$(ARCH)/crypto/ \
-		   arch/$(ARCH)/appldata/
+		   arch/$(ARCH)/appldata/ arch/$(ARCH)/hypfs/
 libs-y		+= arch/$(ARCH)/lib/
 drivers-y	+= drivers/s390/
 drivers-$(CONFIG_MATHEMU) += arch/$(ARCH)/math-emu/
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 9a22434..54d35c1 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -652,7 +652,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block appldata_nb = {
+static struct notifier_block __devinitdata appldata_nb = {
 	.notifier_call = appldata_cpu_notify,
 };
 
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index c5ca2dc..5713c7e 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -37,10 +37,10 @@
 	int key_len;
 };
 
-static int aes_set_key(void *ctx, const u8 *in_key, unsigned int key_len,
-		       u32 *flags)
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len, u32 *flags)
 {
-	struct s390_aes_ctx *sctx = ctx;
+	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 
 	switch (key_len) {
 	case 16:
@@ -70,9 +70,9 @@
 	return -EINVAL;
 }
 
-static void aes_encrypt(void *ctx, u8 *out, const u8 *in)
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	const struct s390_aes_ctx *sctx = ctx;
+	const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 
 	switch (sctx->key_len) {
 	case 16:
@@ -90,9 +90,9 @@
 	}
 }
 
-static void aes_decrypt(void *ctx, u8 *out, const u8 *in)
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	const struct s390_aes_ctx *sctx = ctx;
+	const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
 
 	switch (sctx->key_len) {
 	case 16:
diff --git a/arch/s390/crypto/des_s390.c b/arch/s390/crypto/des_s390.c
index e3c37aa..b3f7496 100644
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -44,10 +44,10 @@
 	u8 key[DES3_192_KEY_SIZE];
 };
 
-static int des_setkey(void *ctx, const u8 *key, unsigned int keylen,
-		      u32 *flags)
+static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
+		      unsigned int keylen, u32 *flags)
 {
-	struct crypt_s390_des_ctx *dctx = ctx;
+	struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
 	int ret;
 
 	/* test if key is valid (not a weak key) */
@@ -57,16 +57,16 @@
 	return ret;
 }
 
-static void des_encrypt(void *ctx, u8 *out, const u8 *in)
+static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct crypt_s390_des_ctx *dctx = ctx;
+	struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
 
 	crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
 }
 
-static void des_decrypt(void *ctx, u8 *out, const u8 *in)
+static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct crypt_s390_des_ctx *dctx = ctx;
+	struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
 
 	crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
 }
@@ -166,11 +166,11 @@
  *   Implementers MUST reject keys that exhibit this property.
  *
  */
-static int des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen,
-			   u32 *flags)
+static int des3_128_setkey(struct crypto_tfm *tfm, const u8 *key,
+			   unsigned int keylen, u32 *flags)
 {
 	int i, ret;
-	struct crypt_s390_des3_128_ctx *dctx = ctx;
+	struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm);
 	const u8* temp_key = key;
 
 	if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) {
@@ -186,17 +186,17 @@
 	return 0;
 }
 
-static void des3_128_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void des3_128_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct crypt_s390_des3_128_ctx *dctx = ctx;
+	struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm);
 
 	crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src,
 		      DES3_128_BLOCK_SIZE);
 }
 
-static void des3_128_decrypt(void *ctx, u8 *dst, const u8 *src)
+static void des3_128_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct crypt_s390_des3_128_ctx *dctx = ctx;
+	struct crypt_s390_des3_128_ctx *dctx = crypto_tfm_ctx(tfm);
 
 	crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src,
 		      DES3_128_BLOCK_SIZE);
@@ -302,11 +302,11 @@
  *   property.
  *
  */
-static int des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen,
-			   u32 *flags)
+static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key,
+			   unsigned int keylen, u32 *flags)
 {
 	int i, ret;
-	struct crypt_s390_des3_192_ctx *dctx = ctx;
+	struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm);
 	const u8* temp_key = key;
 
 	if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
@@ -325,17 +325,17 @@
 	return 0;
 }
 
-static void des3_192_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct crypt_s390_des3_192_ctx *dctx = ctx;
+	struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm);
 
 	crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src,
 		      DES3_192_BLOCK_SIZE);
 }
 
-static void des3_192_decrypt(void *ctx, u8 *dst, const u8 *src)
+static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct crypt_s390_des3_192_ctx *dctx = ctx;
+	struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm);
 
 	crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src,
 		      DES3_192_BLOCK_SIZE);
diff --git a/arch/s390/crypto/sha1_s390.c b/arch/s390/crypto/sha1_s390.c
index 98c896b..9d34a35 100644
--- a/arch/s390/crypto/sha1_s390.c
+++ b/arch/s390/crypto/sha1_s390.c
@@ -40,28 +40,29 @@
 	u8 buffer[2 * SHA1_BLOCK_SIZE];
 };
 
-static void
-sha1_init(void *ctx)
+static void sha1_init(struct crypto_tfm *tfm)
 {
-	static const struct crypt_s390_sha1_ctx initstate = {
-		.state = {
-			0x67452301,
-			0xEFCDAB89,
-			0x98BADCFE,
-			0x10325476,
-			0xC3D2E1F0
-		},
+	struct crypt_s390_sha1_ctx *ctx = crypto_tfm_ctx(tfm);
+	static const u32 initstate[5] = {
+		0x67452301,
+		0xEFCDAB89,
+		0x98BADCFE,
+		0x10325476,
+		0xC3D2E1F0
 	};
-	memcpy(ctx, &initstate, sizeof(initstate));
+
+	ctx->count = 0;
+	memcpy(ctx->state, &initstate, sizeof(initstate));
+	ctx->buf_len = 0;
 }
 
-static void
-sha1_update(void *ctx, const u8 *data, unsigned int len)
+static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
+			unsigned int len)
 {
 	struct crypt_s390_sha1_ctx *sctx;
 	long imd_len;
 
-	sctx = ctx;
+	sctx = crypto_tfm_ctx(tfm);
 	sctx->count += len * 8; //message bit length
 
 	//anything in buffer yet? -> must be completed
@@ -110,10 +111,9 @@
 }
 
 /* Add padding and return the message digest. */
-static void
-sha1_final(void* ctx, u8 *out)
+static void sha1_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct crypt_s390_sha1_ctx *sctx = ctx;
+	struct crypt_s390_sha1_ctx *sctx = crypto_tfm_ctx(tfm);
 
 	//must perform manual padding
 	pad_message(sctx);
diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c
index 1ec5e92..f573df3 100644
--- a/arch/s390/crypto/sha256_s390.c
+++ b/arch/s390/crypto/sha256_s390.c
@@ -31,9 +31,9 @@
 	u8 buf[2 * SHA256_BLOCK_SIZE];
 };
 
-static void sha256_init(void *ctx)
+static void sha256_init(struct crypto_tfm *tfm)
 {
-	struct s390_sha256_ctx *sctx = ctx;
+	struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
 
 	sctx->state[0] = 0x6a09e667;
 	sctx->state[1] = 0xbb67ae85;
@@ -44,12 +44,12 @@
 	sctx->state[6] = 0x1f83d9ab;
 	sctx->state[7] = 0x5be0cd19;
 	sctx->count = 0;
-	memset(sctx->buf, 0, sizeof(sctx->buf));
 }
 
-static void sha256_update(void *ctx, const u8 *data, unsigned int len)
+static void sha256_update(struct crypto_tfm *tfm, const u8 *data,
+			  unsigned int len)
 {
-	struct s390_sha256_ctx *sctx = ctx;
+	struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
 	unsigned int index;
 	int ret;
 
@@ -108,9 +108,9 @@
 }
 
 /* Add padding and return the message digest */
-static void sha256_final(void* ctx, u8 *out)
+static void sha256_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct s390_sha256_ctx *sctx = ctx;
+	struct s390_sha256_ctx *sctx = crypto_tfm_ctx(tfm);
 
 	/* must perform manual padding */
 	pad_message(sctx);
diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile
new file mode 100644
index 0000000..f4b00cd
--- /dev/null
+++ b/arch/s390/hypfs/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the linux hypfs filesystem routines.
+#
+
+obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o
+
+s390_hypfs-objs := inode.o hypfs_diag.o
diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h
new file mode 100644
index 0000000..ea5567b
--- /dev/null
+++ b/arch/s390/hypfs/hypfs.h
@@ -0,0 +1,30 @@
+/*
+ *  fs/hypfs/hypfs.h
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#ifndef _HYPFS_H_
+#define _HYPFS_H_
+
+#include <linux/fs.h>
+#include <linux/types.h>
+
+#define REG_FILE_MODE    0440
+#define UPDATE_FILE_MODE 0220
+#define DIR_MODE         0550
+
+extern struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
+				  const char *name);
+
+extern struct dentry *hypfs_create_u64(struct super_block *sb,
+				       struct dentry *dir, const char *name,
+				       __u64 value);
+
+extern struct dentry *hypfs_create_str(struct super_block *sb,
+				       struct dentry *dir, const char *name,
+				       char *string);
+
+#endif /* _HYPFS_H_ */
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
new file mode 100644
index 0000000..efa74af
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -0,0 +1,696 @@
+/*
+ *  fs/hypfs/hypfs_diag.c
+ *    Hypervisor filesystem for Linux on s390. Diag 204 and 224
+ *    implementation.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+
+#define LPAR_NAME_LEN 8		/* lpar name len in diag 204 data */
+#define CPU_NAME_LEN 16		/* type name len of cpus in diag224 name table */
+#define TMP_SIZE 64		/* size of temporary buffers */
+
+/* diag 204 subcodes */
+enum diag204_sc {
+	SUBC_STIB4 = 4,
+	SUBC_RSI = 5,
+	SUBC_STIB6 = 6,
+	SUBC_STIB7 = 7
+};
+
+/* The two available diag 204 data formats */
+enum diag204_format {
+	INFO_SIMPLE = 0,
+	INFO_EXT = 0x00010000
+};
+
+/* bit is set in flags, when physical cpu info is included in diag 204 data */
+#define LPAR_PHYS_FLG  0x80
+
+static char *diag224_cpu_names;			/* diag 224 name table */
+static enum diag204_sc diag204_store_sc;	/* used subcode for store */
+static enum diag204_format diag204_info_type;	/* used diag 204 data format */
+
+static void *diag204_buf;		/* 4K aligned buffer for diag204 data */
+static void *diag204_buf_vmalloc;	/* vmalloc pointer for diag204 data */
+static int diag204_buf_pages;		/* number of pages for diag204 data */
+
+/*
+ * DIAG 204 data structures and member access functions.
+ *
+ * Since we have two different diag 204 data formats for old and new s390
+ * machines, we do not access the structs directly, but use getter functions for
+ * each struct member instead. This should make the code more readable.
+ */
+
+/* Time information block */
+
+struct info_blk_hdr {
+	__u8  npar;
+	__u8  flags;
+	__u16 tslice;
+	__u16 phys_cpus;
+	__u16 this_part;
+	__u64 curtod;
+} __attribute__ ((packed));
+
+struct x_info_blk_hdr {
+	__u8  npar;
+	__u8  flags;
+	__u16 tslice;
+	__u16 phys_cpus;
+	__u16 this_part;
+	__u64 curtod1;
+	__u64 curtod2;
+	char reserved[40];
+} __attribute__ ((packed));
+
+static inline int info_blk_hdr__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct info_blk_hdr);
+	else /* INFO_EXT */
+		return sizeof(struct x_info_blk_hdr);
+}
+
+static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct info_blk_hdr *)hdr)->npar;
+	else /* INFO_EXT */
+		return ((struct x_info_blk_hdr *)hdr)->npar;
+}
+
+static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct info_blk_hdr *)hdr)->flags;
+	else /* INFO_EXT */
+		return ((struct x_info_blk_hdr *)hdr)->flags;
+}
+
+static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct info_blk_hdr *)hdr)->phys_cpus;
+	else /* INFO_EXT */
+		return ((struct x_info_blk_hdr *)hdr)->phys_cpus;
+}
+
+/* Partition header */
+
+struct part_hdr {
+	__u8 pn;
+	__u8 cpus;
+	char reserved[6];
+	char part_name[LPAR_NAME_LEN];
+} __attribute__ ((packed));
+
+struct x_part_hdr {
+	__u8  pn;
+	__u8  cpus;
+	__u8  rcpus;
+	__u8  pflag;
+	__u32 mlu;
+	char  part_name[LPAR_NAME_LEN];
+	char  lpc_name[8];
+	char  os_name[8];
+	__u64 online_cs;
+	__u64 online_es;
+	__u8  upid;
+	char  reserved1[3];
+	__u32 group_mlu;
+	char  group_name[8];
+	char  reserved2[32];
+} __attribute__ ((packed));
+
+static inline int part_hdr__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct part_hdr);
+	else /* INFO_EXT */
+		return sizeof(struct x_part_hdr);
+}
+
+static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct part_hdr *)hdr)->cpus;
+	else /* INFO_EXT */
+		return ((struct x_part_hdr *)hdr)->rcpus;
+}
+
+static inline void part_hdr__part_name(enum diag204_format type, void *hdr,
+				       char *name)
+{
+	if (type == INFO_SIMPLE)
+		memcpy(name, ((struct part_hdr *)hdr)->part_name,
+		       LPAR_NAME_LEN);
+	else /* INFO_EXT */
+		memcpy(name, ((struct x_part_hdr *)hdr)->part_name,
+		       LPAR_NAME_LEN);
+	EBCASC(name, LPAR_NAME_LEN);
+	name[LPAR_NAME_LEN] = 0;
+	strstrip(name);
+}
+
+struct cpu_info {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	__u8  cflag;
+	__u16 weight;
+	__u64 acc_time;
+	__u64 lp_time;
+} __attribute__ ((packed));
+
+struct x_cpu_info {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	__u8  cflag;
+	__u16 weight;
+	__u64 acc_time;
+	__u64 lp_time;
+	__u16 min_weight;
+	__u16 cur_weight;
+	__u16 max_weight;
+	char  reseved2[2];
+	__u64 online_time;
+	__u64 wait_time;
+	__u32 pma_weight;
+	__u32 polar_weight;
+	char  reserved3[40];
+} __attribute__ ((packed));
+
+/* CPU info block */
+
+static inline int cpu_info__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct cpu_info);
+	else /* INFO_EXT */
+		return sizeof(struct x_cpu_info);
+}
+
+static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->ctidx;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->ctidx;
+}
+
+static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->cpu_addr;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->cpu_addr;
+}
+
+static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->acc_time;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->acc_time;
+}
+
+static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct cpu_info *)hdr)->lp_time;
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->lp_time;
+}
+
+static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return 0;	/* online_time not available in simple info */
+	else /* INFO_EXT */
+		return ((struct x_cpu_info *)hdr)->online_time;
+}
+
+/* Physical header */
+
+struct phys_hdr {
+	char reserved1[1];
+	__u8 cpus;
+	char reserved2[6];
+	char mgm_name[8];
+} __attribute__ ((packed));
+
+struct x_phys_hdr {
+	char reserved1[1];
+	__u8 cpus;
+	char reserved2[6];
+	char mgm_name[8];
+	char reserved3[80];
+} __attribute__ ((packed));
+
+static inline int phys_hdr__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct phys_hdr);
+	else /* INFO_EXT */
+		return sizeof(struct x_phys_hdr);
+}
+
+static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_hdr *)hdr)->cpus;
+	else /* INFO_EXT */
+		return ((struct x_phys_hdr *)hdr)->cpus;
+}
+
+/* Physical CPU info block */
+
+struct phys_cpu {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	char  reserved2[3];
+	__u64 mgm_time;
+	char  reserved3[8];
+} __attribute__ ((packed));
+
+struct x_phys_cpu {
+	__u16 cpu_addr;
+	char  reserved1[2];
+	__u8  ctidx;
+	char  reserved2[3];
+	__u64 mgm_time;
+	char  reserved3[80];
+} __attribute__ ((packed));
+
+static inline int phys_cpu__size(enum diag204_format type)
+{
+	if (type == INFO_SIMPLE)
+		return sizeof(struct phys_cpu);
+	else /* INFO_EXT */
+		return sizeof(struct x_phys_cpu);
+}
+
+static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_cpu *)hdr)->cpu_addr;
+	else /* INFO_EXT */
+		return ((struct x_phys_cpu *)hdr)->cpu_addr;
+}
+
+static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_cpu *)hdr)->mgm_time;
+	else /* INFO_EXT */
+		return ((struct x_phys_cpu *)hdr)->mgm_time;
+}
+
+static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr)
+{
+	if (type == INFO_SIMPLE)
+		return ((struct phys_cpu *)hdr)->ctidx;
+	else /* INFO_EXT */
+		return ((struct x_phys_cpu *)hdr)->ctidx;
+}
+
+/* Diagnose 204 functions */
+
+static int diag204(unsigned long subcode, unsigned long size, void *addr)
+{
+	register unsigned long _subcode asm("0") = subcode;
+	register unsigned long _size asm("1") = size;
+
+	asm volatile ("   diag    %2,%0,0x204\n"
+		      "0: \n" ".section __ex_table,\"a\"\n"
+#ifndef __s390x__
+		      "    .align 4\n"
+		      "    .long  0b,0b\n"
+#else
+		      "    .align 8\n"
+		      "    .quad  0b,0b\n"
+#endif
+		      ".previous":"+d" (_subcode), "+d"(_size)
+		      :"d"(addr)
+		      :"memory");
+	if (_subcode)
+		return -1;
+	else
+		return _size;
+}
+
+/*
+ * For the old diag subcode 4 with simple data format we have to use real
+ * memory. If we use subcode 6 or 7 with extended data format, we can (and
+ * should) use vmalloc, since we need a lot of memory in that case. Currently
+ * up to 93 pages!
+ */
+
+static void diag204_free_buffer(void)
+{
+	if (!diag204_buf)
+		return;
+	if (diag204_buf_vmalloc) {
+		vfree(diag204_buf_vmalloc);
+		diag204_buf_vmalloc = NULL;
+	} else {
+		free_pages((unsigned long) diag204_buf, 0);
+	}
+	diag204_buf_pages = 0;
+	diag204_buf = NULL;
+}
+
+static void *diag204_alloc_vbuf(int pages)
+{
+	/* The buffer has to be page aligned! */
+	diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1));
+	if (!diag204_buf_vmalloc)
+		return ERR_PTR(-ENOMEM);
+	diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc
+				& ~0xfffUL) + 0x1000;
+	diag204_buf_pages = pages;
+	return diag204_buf;
+}
+
+static void *diag204_alloc_rbuf(void)
+{
+	diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0);
+	if (diag204_buf)
+		return ERR_PTR(-ENOMEM);
+	diag204_buf_pages = 1;
+	return diag204_buf;
+}
+
+static void *diag204_get_buffer(enum diag204_format fmt, int *pages)
+{
+	if (diag204_buf) {
+		*pages = diag204_buf_pages;
+		return diag204_buf;
+	}
+	if (fmt == INFO_SIMPLE) {
+		*pages = 1;
+		return diag204_alloc_rbuf();
+	} else {/* INFO_EXT */
+		*pages = diag204(SUBC_RSI | INFO_EXT, 0, 0);
+		if (*pages <= 0)
+			return ERR_PTR(-ENOSYS);
+		else
+			return diag204_alloc_vbuf(*pages);
+	}
+}
+
+/*
+ * diag204_probe() has to find out, which type of diagnose 204 implementation
+ * we have on our machine. Currently there are three possible scanarios:
+ *   - subcode 4   + simple data format (only one page)
+ *   - subcode 4-6 + extended data format
+ *   - subcode 4-7 + extended data format
+ *
+ * Subcode 5 is used to retrieve the size of the data, provided by subcodes
+ * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition
+ * to subcode 6 it provides also information about secondary cpus.
+ * In order to get as much information as possible, we first try
+ * subcode 7, then 6 and if both fail, we use subcode 4.
+ */
+
+static int diag204_probe(void)
+{
+	void *buf;
+	int pages, rc;
+
+	buf = diag204_get_buffer(INFO_EXT, &pages);
+	if (!IS_ERR(buf)) {
+		if (diag204(SUBC_STIB7 | INFO_EXT, pages, buf) >= 0) {
+			diag204_store_sc = SUBC_STIB7;
+			diag204_info_type = INFO_EXT;
+			goto out;
+		}
+		if (diag204(SUBC_STIB6 | INFO_EXT, pages, buf) >= 0) {
+			diag204_store_sc = SUBC_STIB7;
+			diag204_info_type = INFO_EXT;
+			goto out;
+		}
+		diag204_free_buffer();
+	}
+
+	/* subcodes 6 and 7 failed, now try subcode 4 */
+
+	buf = diag204_get_buffer(INFO_SIMPLE, &pages);
+	if (IS_ERR(buf)) {
+		rc = PTR_ERR(buf);
+		goto fail_alloc;
+	}
+	if (diag204(SUBC_STIB4 | INFO_SIMPLE, pages, buf) >= 0) {
+		diag204_store_sc = SUBC_STIB4;
+		diag204_info_type = INFO_SIMPLE;
+		goto out;
+	} else {
+		rc = -ENOSYS;
+		goto fail_store;
+	}
+out:
+	rc = 0;
+fail_store:
+	diag204_free_buffer();
+fail_alloc:
+	return rc;
+}
+
+static void *diag204_store(void)
+{
+	void *buf;
+	int pages;
+
+	buf = diag204_get_buffer(diag204_info_type, &pages);
+	if (IS_ERR(buf))
+		goto out;
+	if (diag204(diag204_store_sc | diag204_info_type, pages, buf) < 0)
+		return ERR_PTR(-ENOSYS);
+out:
+	return buf;
+}
+
+/* Diagnose 224 functions */
+
+static void diag224(void *ptr)
+{
+	asm volatile("   diag    %0,%1,0x224\n"
+		     : :"d" (0), "d"(ptr) : "memory");
+}
+
+static int diag224_get_name_table(void)
+{
+	/* memory must be below 2GB */
+	diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!diag224_cpu_names)
+		return -ENOMEM;
+	diag224(diag224_cpu_names);
+	EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16);
+	return 0;
+}
+
+static void diag224_delete_name_table(void)
+{
+	kfree(diag224_cpu_names);
+}
+
+static int diag224_idx2name(int index, char *name)
+{
+	memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN),
+		CPU_NAME_LEN);
+	name[CPU_NAME_LEN] = 0;
+	strstrip(name);
+	return 0;
+}
+
+__init int hypfs_diag_init(void)
+{
+	int rc;
+
+	if (diag204_probe()) {
+		printk(KERN_ERR "hypfs: diag 204 not working.");
+		return -ENODATA;
+	}
+	rc = diag224_get_name_table();
+	if (rc) {
+		diag224_delete_name_table();
+		printk(KERN_ERR "hypfs: could not get name table.\n");
+	}
+	return rc;
+}
+
+__exit void hypfs_diag_exit(void)
+{
+	diag224_delete_name_table();
+	diag204_free_buffer();
+}
+
+/*
+ * Functions to create the directory structure
+ * *******************************************
+ */
+
+static int hypfs_create_cpu_files(struct super_block *sb,
+				  struct dentry *cpus_dir, void *cpu_info)
+{
+	struct dentry *cpu_dir;
+	char buffer[TMP_SIZE];
+	void *rc;
+
+	snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type,
+							    cpu_info));
+	cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
+	rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+			      cpu_info__acc_time(diag204_info_type, cpu_info) -
+			      cpu_info__lp_time(diag204_info_type, cpu_info));
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	rc = hypfs_create_u64(sb, cpu_dir, "cputime",
+			      cpu_info__lp_time(diag204_info_type, cpu_info));
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	if (diag204_info_type == INFO_EXT) {
+		rc = hypfs_create_u64(sb, cpu_dir, "onlinetime",
+				      cpu_info__online_time(diag204_info_type,
+							    cpu_info));
+		if (IS_ERR(rc))
+			return PTR_ERR(rc);
+	}
+	diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer);
+	rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	return 0;
+}
+
+static void *hypfs_create_lpar_files(struct super_block *sb,
+				     struct dentry *systems_dir, void *part_hdr)
+{
+	struct dentry *cpus_dir;
+	struct dentry *lpar_dir;
+	char lpar_name[LPAR_NAME_LEN + 1];
+	void *cpu_info;
+	int i;
+
+	part_hdr__part_name(diag204_info_type, part_hdr, lpar_name);
+	lpar_name[LPAR_NAME_LEN] = 0;
+	lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name);
+	if (IS_ERR(lpar_dir))
+		return lpar_dir;
+	cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus");
+	if (IS_ERR(cpus_dir))
+		return cpus_dir;
+	cpu_info = part_hdr + part_hdr__size(diag204_info_type);
+	for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) {
+		int rc;
+		rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info);
+		if (rc)
+			return ERR_PTR(rc);
+		cpu_info += cpu_info__size(diag204_info_type);
+	}
+	return cpu_info;
+}
+
+static int hypfs_create_phys_cpu_files(struct super_block *sb,
+				       struct dentry *cpus_dir, void *cpu_info)
+{
+	struct dentry *cpu_dir;
+	char buffer[TMP_SIZE];
+	void *rc;
+
+	snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type,
+							    cpu_info));
+	cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer);
+	if (IS_ERR(cpu_dir))
+		return PTR_ERR(cpu_dir);
+	rc = hypfs_create_u64(sb, cpu_dir, "mgmtime",
+			      phys_cpu__mgm_time(diag204_info_type, cpu_info));
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer);
+	rc = hypfs_create_str(sb, cpu_dir, "type", buffer);
+	if (IS_ERR(rc))
+		return PTR_ERR(rc);
+	return 0;
+}
+
+static void *hypfs_create_phys_files(struct super_block *sb,
+				     struct dentry *parent_dir, void *phys_hdr)
+{
+	int i;
+	void *cpu_info;
+	struct dentry *cpus_dir;
+
+	cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus");
+	if (IS_ERR(cpus_dir))
+		return cpus_dir;
+	cpu_info = phys_hdr + phys_hdr__size(diag204_info_type);
+	for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) {
+		int rc;
+		rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info);
+		if (rc)
+			return ERR_PTR(rc);
+		cpu_info += phys_cpu__size(diag204_info_type);
+	}
+	return cpu_info;
+}
+
+int hypfs_diag_create_files(struct super_block *sb, struct dentry *root)
+{
+	struct dentry *systems_dir, *hyp_dir;
+	void *time_hdr, *part_hdr;
+	int i, rc;
+	void *buffer, *ptr;
+
+	buffer = diag204_store();
+	if (IS_ERR(buffer))
+		return PTR_ERR(buffer);
+
+	systems_dir = hypfs_mkdir(sb, root, "systems");
+	if (IS_ERR(systems_dir)) {
+		rc = PTR_ERR(systems_dir);
+		goto err_out;
+	}
+	time_hdr = (struct x_info_blk_hdr *)buffer;
+	part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type);
+	for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) {
+		part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr);
+		if (IS_ERR(part_hdr)) {
+			rc = PTR_ERR(part_hdr);
+			goto err_out;
+		}
+	}
+	if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) {
+		ptr = hypfs_create_phys_files(sb, root, part_hdr);
+		if (IS_ERR(ptr)) {
+			rc = PTR_ERR(ptr);
+			goto err_out;
+		}
+	}
+	hyp_dir = hypfs_mkdir(sb, root, "hyp");
+	if (IS_ERR(hyp_dir)) {
+		rc = PTR_ERR(hyp_dir);
+		goto err_out;
+	}
+	ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor");
+	if (IS_ERR(ptr)) {
+		rc = PTR_ERR(ptr);
+		goto err_out;
+	}
+	rc = 0;
+
+err_out:
+	return rc;
+}
diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h
new file mode 100644
index 0000000..793dea6
--- /dev/null
+++ b/arch/s390/hypfs/hypfs_diag.h
@@ -0,0 +1,16 @@
+/*
+ *  fs/hypfs/hypfs_diag.h
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#ifndef _HYPFS_DIAG_H_
+#define _HYPFS_DIAG_H_
+
+extern int hypfs_diag_init(void);
+extern void hypfs_diag_exit(void);
+extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root);
+
+#endif /* _HYPFS_DIAG_H_ */
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
new file mode 100644
index 0000000..18c0919
--- /dev/null
+++ b/arch/s390/hypfs/inode.c
@@ -0,0 +1,491 @@
+/*
+ *  fs/hypfs/inode.c
+ *    Hypervisor filesystem for Linux on s390.
+ *
+ *    Copyright (C) IBM Corp. 2006
+ *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
+#include <linux/vfs.h>
+#include <linux/pagemap.h>
+#include <linux/gfp.h>
+#include <linux/time.h>
+#include <linux/parser.h>
+#include <linux/sysfs.h>
+#include <linux/module.h>
+#include <asm/ebcdic.h>
+#include "hypfs.h"
+#include "hypfs_diag.h"
+
+#define HYPFS_MAGIC 0x687970	/* ASCII 'hyp' */
+#define TMP_SIZE 64		/* size of temporary buffers */
+
+static struct dentry *hypfs_create_update_file(struct super_block *sb,
+					       struct dentry *dir);
+
+struct hypfs_sb_info {
+	uid_t uid;			/* uid used for files and dirs */
+	gid_t gid;			/* gid used for files and dirs */
+	struct dentry *update_file;	/* file to trigger update */
+	time_t last_update;		/* last update time in secs since 1970 */
+	struct mutex lock;		/* lock to protect update process */
+};
+
+static struct file_operations hypfs_file_ops;
+static struct file_system_type hypfs_type;
+static struct super_operations hypfs_s_ops;
+
+/* start of list of all dentries, which have to be deleted on update */
+static struct dentry *hypfs_last_dentry;
+
+static void hypfs_update_update(struct super_block *sb)
+{
+	struct hypfs_sb_info *sb_info = sb->s_fs_info;
+	struct inode *inode = sb_info->update_file->d_inode;
+
+	sb_info->last_update = get_seconds();
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
+/* directory tree removal functions */
+
+static void hypfs_add_dentry(struct dentry *dentry)
+{
+	dentry->d_fsdata = hypfs_last_dentry;
+	hypfs_last_dentry = dentry;
+}
+
+static void hypfs_remove(struct dentry *dentry)
+{
+	struct dentry *parent;
+
+	parent = dentry->d_parent;
+	if (S_ISDIR(dentry->d_inode->i_mode))
+		simple_rmdir(parent->d_inode, dentry);
+	else
+		simple_unlink(parent->d_inode, dentry);
+	d_delete(dentry);
+	dput(dentry);
+}
+
+static void hypfs_delete_tree(struct dentry *root)
+{
+	while (hypfs_last_dentry) {
+		struct dentry *next_dentry;
+		next_dentry = hypfs_last_dentry->d_fsdata;
+		hypfs_remove(hypfs_last_dentry);
+		hypfs_last_dentry = next_dentry;
+	}
+}
+
+static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
+{
+	struct inode *ret = new_inode(sb);
+
+	if (ret) {
+		struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+		ret->i_mode = mode;
+		ret->i_uid = hypfs_info->uid;
+		ret->i_gid = hypfs_info->gid;
+		ret->i_blksize = PAGE_CACHE_SIZE;
+		ret->i_blocks = 0;
+		ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
+		if (mode & S_IFDIR)
+			ret->i_nlink = 2;
+		else
+			ret->i_nlink = 1;
+	}
+	return ret;
+}
+
+static void hypfs_drop_inode(struct inode *inode)
+{
+	kfree(inode->u.generic_ip);
+	generic_delete_inode(inode);
+}
+
+static int hypfs_open(struct inode *inode, struct file *filp)
+{
+	char *data = filp->f_dentry->d_inode->u.generic_ip;
+	struct hypfs_sb_info *fs_info;
+
+	if (filp->f_mode & FMODE_WRITE) {
+		if (!(inode->i_mode & S_IWUGO))
+			return -EACCES;
+	}
+	if (filp->f_mode & FMODE_READ) {
+		if (!(inode->i_mode & S_IRUGO))
+			return -EACCES;
+	}
+
+	fs_info = inode->i_sb->s_fs_info;
+	if(data) {
+		mutex_lock(&fs_info->lock);
+		filp->private_data = kstrdup(data, GFP_KERNEL);
+		if (!filp->private_data) {
+			mutex_unlock(&fs_info->lock);
+			return -ENOMEM;
+		}
+		mutex_unlock(&fs_info->lock);
+	}
+	return 0;
+}
+
+static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf,
+			      size_t count, loff_t offset)
+{
+	char *data;
+	size_t len;
+	struct file *filp = iocb->ki_filp;
+
+	data = filp->private_data;
+	len = strlen(data);
+	if (offset > len) {
+		count = 0;
+		goto out;
+	}
+	if (count > len - offset)
+		count = len - offset;
+	if (copy_to_user(buf, data + offset, count)) {
+		count = -EFAULT;
+		goto out;
+	}
+	iocb->ki_pos += count;
+	file_accessed(filp);
+out:
+	return count;
+}
+static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf,
+			       size_t count, loff_t pos)
+{
+	int rc;
+	struct super_block *sb;
+	struct hypfs_sb_info *fs_info;
+
+	sb = iocb->ki_filp->f_dentry->d_inode->i_sb;
+	fs_info = sb->s_fs_info;
+	/*
+	 * Currently we only allow one update per second for two reasons:
+	 * 1. diag 204 is VERY expensive
+	 * 2. If several processes do updates in parallel and then read the
+	 *    hypfs data, the likelihood of collisions is reduced, if we restrict
+	 *    the minimum update interval. A collision occurs, if during the
+	 *    data gathering of one process another process triggers an update
+	 *    If the first process wants to ensure consistent data, it has
+	 *    to restart data collection in this case.
+	 */
+	mutex_lock(&fs_info->lock);
+	if (fs_info->last_update == get_seconds()) {
+		rc = -EBUSY;
+		goto out;
+	}
+	hypfs_delete_tree(sb->s_root);
+	rc = hypfs_diag_create_files(sb, sb->s_root);
+	if (rc) {
+		printk(KERN_ERR "hypfs: Update failed\n");
+		hypfs_delete_tree(sb->s_root);
+		goto out;
+	}
+	hypfs_update_update(sb);
+	rc = count;
+out:
+	mutex_unlock(&fs_info->lock);
+	return rc;
+}
+
+static int hypfs_release(struct inode *inode, struct file *filp)
+{
+	kfree(filp->private_data);
+	return 0;
+}
+
+enum { opt_uid, opt_gid, opt_err };
+
+static match_table_t hypfs_tokens = {
+	{opt_uid, "uid=%u"},
+	{opt_gid, "gid=%u"},
+	{opt_err, NULL}
+};
+
+static int hypfs_parse_options(char *options, struct super_block *sb)
+{
+	char *str;
+	substring_t args[MAX_OPT_ARGS];
+
+	if (!options)
+		return 0;
+	while ((str = strsep(&options, ",")) != NULL) {
+		int token, option;
+		struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+
+		if (!*str)
+			continue;
+		token = match_token(str, hypfs_tokens, args);
+		switch (token) {
+		case opt_uid:
+			if (match_int(&args[0], &option))
+				return -EINVAL;
+			hypfs_info->uid = option;
+			break;
+		case opt_gid:
+			if (match_int(&args[0], &option))
+				return -EINVAL;
+			hypfs_info->gid = option;
+			break;
+		case opt_err:
+		default:
+			printk(KERN_ERR "hypfs: Unrecognized mount option "
+			       "\"%s\" or missing value\n", str);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct inode *root_inode;
+	struct dentry *root_dentry;
+	int rc = 0;
+	struct hypfs_sb_info *sbi;
+
+	sbi = kzalloc(sizeof(struct hypfs_sb_info), GFP_KERNEL);
+	if (!sbi)
+		return -ENOMEM;
+	mutex_init(&sbi->lock);
+	sbi->uid = current->uid;
+	sbi->gid = current->gid;
+	sb->s_fs_info = sbi;
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = HYPFS_MAGIC;
+	sb->s_op = &hypfs_s_ops;
+	if (hypfs_parse_options(data, sb)) {
+		rc = -EINVAL;
+		goto err_alloc;
+	}
+	root_inode = hypfs_make_inode(sb, S_IFDIR | 0755);
+	if (!root_inode) {
+		rc = -ENOMEM;
+		goto err_alloc;
+	}
+	root_inode->i_op = &simple_dir_inode_operations;
+	root_inode->i_fop = &simple_dir_operations;
+	root_dentry = d_alloc_root(root_inode);
+	if (!root_dentry) {
+		iput(root_inode);
+		rc = -ENOMEM;
+		goto err_alloc;
+	}
+	rc = hypfs_diag_create_files(sb, root_dentry);
+	if (rc)
+		goto err_tree;
+	sbi->update_file = hypfs_create_update_file(sb, root_dentry);
+	if (IS_ERR(sbi->update_file)) {
+		rc = PTR_ERR(sbi->update_file);
+		goto err_tree;
+	}
+	hypfs_update_update(sb);
+	sb->s_root = root_dentry;
+	return 0;
+
+err_tree:
+	hypfs_delete_tree(root_dentry);
+	d_genocide(root_dentry);
+	dput(root_dentry);
+err_alloc:
+	kfree(sbi);
+	return rc;
+}
+
+static int hypfs_get_super(struct file_system_type *fst, int flags,
+			const char *devname, void *data, struct vfsmount *mnt)
+{
+	return get_sb_single(fst, flags, data, hypfs_fill_super, mnt);
+}
+
+static void hypfs_kill_super(struct super_block *sb)
+{
+	struct hypfs_sb_info *sb_info = sb->s_fs_info;
+
+	hypfs_delete_tree(sb->s_root);
+	hypfs_remove(sb_info->update_file);
+	kfree(sb->s_fs_info);
+	sb->s_fs_info = NULL;
+	kill_litter_super(sb);
+}
+
+static struct dentry *hypfs_create_file(struct super_block *sb,
+					struct dentry *parent, const char *name,
+					char *data, mode_t mode)
+{
+	struct dentry *dentry;
+	struct inode *inode;
+	struct qstr qname;
+
+	qname.name = name;
+	qname.len = strlen(name);
+	qname.hash = full_name_hash(name, qname.len);
+	dentry = lookup_one_len(name, parent, strlen(name));
+	if (IS_ERR(dentry))
+		return ERR_PTR(-ENOMEM);
+	inode = hypfs_make_inode(sb, mode);
+	if (!inode) {
+		dput(dentry);
+		return ERR_PTR(-ENOMEM);
+	}
+	if (mode & S_IFREG) {
+		inode->i_fop = &hypfs_file_ops;
+		if (data)
+			inode->i_size = strlen(data);
+		else
+			inode->i_size = 0;
+	} else if (mode & S_IFDIR) {
+		inode->i_op = &simple_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+		parent->d_inode->i_nlink++;
+	} else
+		BUG();
+	inode->u.generic_ip = data;
+	d_instantiate(dentry, inode);
+	dget(dentry);
+	return dentry;
+}
+
+struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
+			   const char *name)
+{
+	struct dentry *dentry;
+
+	dentry = hypfs_create_file(sb, parent, name, NULL, S_IFDIR | DIR_MODE);
+	if (IS_ERR(dentry))
+		return dentry;
+	hypfs_add_dentry(dentry);
+	parent->d_inode->i_nlink++;
+	return dentry;
+}
+
+static struct dentry *hypfs_create_update_file(struct super_block *sb,
+					       struct dentry *dir)
+{
+	struct dentry *dentry;
+
+	dentry = hypfs_create_file(sb, dir, "update", NULL,
+				   S_IFREG | UPDATE_FILE_MODE);
+	/*
+	 * We do not put the update file on the 'delete' list with
+	 * hypfs_add_dentry(), since it should not be removed when the tree
+	 * is updated.
+	 */
+	return dentry;
+}
+
+struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir,
+				const char *name, __u64 value)
+{
+	char *buffer;
+	char tmp[TMP_SIZE];
+	struct dentry *dentry;
+
+	snprintf(tmp, TMP_SIZE, "%lld\n", (unsigned long long int)value);
+	buffer = kstrdup(tmp, GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	dentry =
+	    hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+	if (IS_ERR(dentry)) {
+		kfree(buffer);
+		return ERR_PTR(-ENOMEM);
+	}
+	hypfs_add_dentry(dentry);
+	return dentry;
+}
+
+struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir,
+				const char *name, char *string)
+{
+	char *buffer;
+	struct dentry *dentry;
+
+	buffer = kmalloc(strlen(string) + 2, GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	sprintf(buffer, "%s\n", string);
+	dentry =
+	    hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE);
+	if (IS_ERR(dentry)) {
+		kfree(buffer);
+		return ERR_PTR(-ENOMEM);
+	}
+	hypfs_add_dentry(dentry);
+	return dentry;
+}
+
+static struct file_operations hypfs_file_ops = {
+	.open		= hypfs_open,
+	.release	= hypfs_release,
+	.read		= do_sync_read,
+	.write		= do_sync_write,
+	.aio_read	= hypfs_aio_read,
+	.aio_write	= hypfs_aio_write,
+};
+
+static struct file_system_type hypfs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "s390_hypfs",
+	.get_sb		= hypfs_get_super,
+	.kill_sb	= hypfs_kill_super
+};
+
+static struct super_operations hypfs_s_ops = {
+	.statfs		= simple_statfs,
+	.drop_inode	= hypfs_drop_inode,
+};
+
+static decl_subsys(s390, NULL, NULL);
+
+static int __init hypfs_init(void)
+{
+	int rc;
+
+	if (MACHINE_IS_VM)
+		return -ENODATA;
+	if (hypfs_diag_init()) {
+		rc = -ENODATA;
+		goto fail_diag;
+	}
+	kset_set_kset_s(&s390_subsys, hypervisor_subsys);
+	rc = subsystem_register(&s390_subsys);
+	if (rc)
+		goto fail_sysfs;
+	rc = register_filesystem(&hypfs_type);
+	if (rc)
+		goto fail_filesystem;
+	return 0;
+
+fail_filesystem:
+	subsystem_unregister(&s390_subsys);
+fail_sysfs:
+	hypfs_diag_exit();
+fail_diag:
+	printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc);
+	return rc;
+}
+
+static void __exit hypfs_exit(void)
+{
+	hypfs_diag_exit();
+	unregister_filesystem(&hypfs_type);
+	subsystem_unregister(&s390_subsys);
+}
+
+module_init(hypfs_init)
+module_exit(hypfs_exit)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Michael Holzheu <holzheu@de.ibm.com>");
+MODULE_DESCRIPTION("s390 Hypervisor Filesystem");
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index bad81b5..fbde6a9 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -27,8 +27,8 @@
 
 typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
 
-const extern unsigned char relocate_kernel[];
-const extern unsigned long long relocate_kernel_len;
+extern const unsigned char relocate_kernel[];
+extern const unsigned long long relocate_kernel_len;
 
 int
 machine_kexec_prepare(struct kimage *image)
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 0a04e4a..b282034 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -47,6 +47,7 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
+#include <asm/sections.h>
 
 /*
  * Machine setup..
@@ -66,11 +67,6 @@
 static unsigned long __initdata memory_end;
 
 /*
- * Setup options
- */
-extern int _text,_etext, _edata, _end;
-
-/*
  * This is set up by the setup-routine at boot-time
  * for S390 need to find out, what we have to setup
  * using address 0x10400 ...
@@ -80,15 +76,11 @@
 
 static struct resource code_resource = {
 	.name  = "Kernel code",
-	.start = (unsigned long) &_text,
-	.end = (unsigned long) &_etext - 1,
 	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
 };
 
 static struct resource data_resource = {
 	.name = "Kernel data",
-	.start = (unsigned long) &_etext,
-	.end = (unsigned long) &_edata - 1,
 	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
 };
 
@@ -422,6 +414,11 @@
 	struct resource *res;
 	int i;
 
+	code_resource.start = (unsigned long) &_text;
+	code_resource.end = (unsigned long) &_etext - 1;
+	data_resource.start = (unsigned long) &_etext;
+	data_resource.end = (unsigned long) &_edata - 1;
+
 	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
 		res = alloc_bootmem_low(sizeof(struct resource));
 		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 343120c..8e03219 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -869,7 +869,7 @@
 	int ret;
 
 	for_each_possible_cpu(cpu) {
-		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu, NULL);
+		ret = register_cpu(&per_cpu(cpu_devices, cpu), cpu);
 		if (ret)
 			printk(KERN_WARNING "topology_init: register_cpu %d "
 			       "failed (%d)\n", cpu, ret);
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index dfe6f08..1f0439d 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -356,7 +356,7 @@
 
 	set_vtimer(event->expires);
 	spin_unlock_irqrestore(&vt_list->lock, flags);
-	/* release CPU aquired in prepare_vtimer or mod_virt_timer() */
+	/* release CPU acquired in prepare_vtimer or mod_virt_timer() */
 	put_cpu();
 }
 
diff --git a/arch/sh/Makefile b/arch/sh/Makefile
index c72e17a..e467a45 100644
--- a/arch/sh/Makefile
+++ b/arch/sh/Makefile
@@ -147,7 +147,7 @@
 #	them changed.  We use .arch and .mach to indicate when they were
 #	updated last, otherwise make uses the target directory mtime.
 
-include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER
+include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
 	@echo '  SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
 	$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
 	$(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu
@@ -157,7 +157,7 @@
 #	don't, just reference the parent directory so the semantics are
 #	kept roughly the same.
 
-include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER
+include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
 	@echo -n '  SYMLINK include/asm-sh/mach -> '
 	$(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
 	$(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c
index 4354652..6bcd8d9 100644
--- a/arch/sh/kernel/machine_kexec.c
+++ b/arch/sh/kernel/machine_kexec.c
@@ -25,8 +25,8 @@
 				unsigned long start_address,
 				unsigned long vbr_reg) ATTRIB_NORET;
 
-const extern unsigned char relocate_new_kernel[];
-const extern unsigned int relocate_new_kernel_size;
+extern const unsigned char relocate_new_kernel[];
+extern const unsigned int relocate_new_kernel_size;
 extern void *gdb_vbr_vector;
 
 /*
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index bb229ef..9af22116 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -402,7 +402,7 @@
 	int cpu_id;
 
 	for_each_possible_cpu(cpu_id)
-		register_cpu(&cpu[cpu_id], cpu_id, NULL);
+		register_cpu(&cpu[cpu_id], cpu_id);
 
 	return 0;
 }
diff --git a/arch/sh/oprofile/op_model_sh7750.c b/arch/sh/oprofile/op_model_sh7750.c
index 5ec9ddc..c265185 100644
--- a/arch/sh/oprofile/op_model_sh7750.c
+++ b/arch/sh/oprofile/op_model_sh7750.c
@@ -198,7 +198,7 @@
 
 	for (i = 0; i < NR_CNTRS; i++) {
 		struct dentry *dir;
-		char buf[3];
+		char buf[4];
 
 		snprintf(buf, sizeof(buf), "%d", i);
 		dir = oprofilefs_mkdir(sb, root, buf);
diff --git a/arch/sh64/kernel/setup.c b/arch/sh64/kernel/setup.c
index d2711c9..da98d8d 100644
--- a/arch/sh64/kernel/setup.c
+++ b/arch/sh64/kernel/setup.c
@@ -309,7 +309,7 @@
 
 static int __init topology_init(void)
 {
-	return register_cpu(cpu, 0, NULL);
+	return register_cpu(cpu, 0);
 }
 
 subsys_initcall(topology_init);
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
index 3ea8929e..9e2ffc4 100644
--- a/arch/sh64/kernel/signal.c
+++ b/arch/sh64/kernel/signal.c
@@ -407,7 +407,7 @@
 static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void __user *)((sp - frame_size) & -8ul);
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 1b83e21..6616ee0 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -12,7 +12,7 @@
 	    sys_sparc.o sunos_asm.o systbls.o \
 	    time.o windows.o cpu.o devices.o sclow.o \
 	    tadpole.o tick14.o ptrace.o sys_solaris.o \
-	    unaligned.o muldiv.o semaphore.o
+	    unaligned.o muldiv.o semaphore.o prom.o of_device.o
 
 obj-$(CONFIG_PCI) += pcic.o
 obj-$(CONFIG_SUN4) += sun4setup.o
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c
index 5c3529c..a7a4892 100644
--- a/arch/sparc/kernel/ebus.c
+++ b/arch/sparc/kernel/ebus.c
@@ -20,6 +20,7 @@
 #include <asm/ebus.h>
 #include <asm/io.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/bpp.h>
 
 struct linux_ebus *ebus_chain = NULL;
@@ -83,79 +84,81 @@
 	return 0;
 }
 
-void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
-				struct linux_ebus_child *dev)
+void __init fill_ebus_child(struct device_node *dp,
+			    struct linux_ebus_child *dev)
 {
-	int regs[PROMREG_MAX];
-	int irqs[PROMREG_MAX];
-	char lbuf[128];
+	int *regs;
+	int *irqs;
 	int i, len;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", lbuf, sizeof(lbuf));
-	strcpy(dev->prom_name, lbuf);
-
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
-	if (len == -1) len = 0;
+	dev->prom_node = dp;
+	regs = of_get_property(dp, "reg", &len);
+	if (!regs)
+		len = 0;
 	dev->num_addrs = len / sizeof(regs[0]);
 
 	for (i = 0; i < dev->num_addrs; i++) {
 		if (regs[i] >= dev->parent->num_addrs) {
 			prom_printf("UGH: property for %s was %d, need < %d\n",
-				    dev->prom_name, len, dev->parent->num_addrs);
+				    dev->prom_node->name, len,
+				    dev->parent->num_addrs);
 			panic(__FUNCTION__);
 		}
-		dev->resource[i].start = dev->parent->resource[regs[i]].start; /* XXX resource */
+
+		/* XXX resource */
+		dev->resource[i].start =
+			dev->parent->resource[regs[i]].start;
 	}
 
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) {
 		dev->num_irqs = 1;
-	} else if ((len = prom_getproperty(node, "interrupts",
-	    (char *)&irqs, sizeof(irqs))) == -1 || len == 0) {
-		dev->num_irqs = 0;
-		dev->irqs[0] = 0;
-		if (dev->parent->num_irqs != 0) {
-			dev->num_irqs = 1;
-			dev->irqs[0] = dev->parent->irqs[0];
-/* P3 */ /* printk("EBUS: dev %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
-		}
 	} else {
-		dev->num_irqs = len / sizeof(irqs[0]);
-		if (irqs[0] == 0 || irqs[0] >= 8) {
-			/*
-			 * XXX Zero is a valid pin number...
-			 * This works as long as Ebus is not wired to INTA#.
-			 */
-			printk("EBUS: %s got bad irq %d from PROM\n",
-			    dev->prom_name, irqs[0]);
+		irqs = of_get_property(dp, "interrupts", &len);
+		if (!irqs) {
 			dev->num_irqs = 0;
 			dev->irqs[0] = 0;
+			if (dev->parent->num_irqs != 0) {
+				dev->num_irqs = 1;
+				dev->irqs[0] = dev->parent->irqs[0];
+			}
 		} else {
-			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+			dev->num_irqs = len / sizeof(irqs[0]);
+			if (irqs[0] == 0 || irqs[0] >= 8) {
+				/*
+				 * XXX Zero is a valid pin number...
+				 * This works as long as Ebus is not wired
+				 * to INTA#.
+				 */
+				printk("EBUS: %s got bad irq %d from PROM\n",
+				       dev->prom_node->name, irqs[0]);
+				dev->num_irqs = 0;
+				dev->irqs[0] = 0;
+			} else {
+				dev->irqs[0] =
+					pcic_pin_to_irq(irqs[0],
+							dev->prom_node->name);
+			}
 		}
 	}
 }
 
-void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
+void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev)
 {
-	struct linux_prom_registers regs[PROMREG_MAX];
+	struct linux_prom_registers *regs;
 	struct linux_ebus_child *child;
-	int irqs[PROMINTR_MAX];
-	char lbuf[128];
+	int *irqs;
 	int i, n, len;
 	unsigned long baseaddr;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", lbuf, sizeof(lbuf));
-	strcpy(dev->prom_name, lbuf);
+	dev->prom_node = dp;
 
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+	regs = of_get_property(dp, "reg", &len);
 	if (len % sizeof(struct linux_prom_registers)) {
 		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
-			    dev->prom_name, len,
+			    dev->prom_node->name, len,
 			    (int)sizeof(struct linux_prom_registers));
 		panic(__FUNCTION__);
 	}
@@ -197,7 +200,7 @@
 			if ((baseaddr = (unsigned long) ioremap(baseaddr,
 			    regs[i].reg_size)) == 0) {
 				panic("ebus: unable to remap dev %s",
-				    dev->prom_name);
+				      dev->prom_node->name);
 			}
 		}
 		dev->resource[i].start = baseaddr;	/* XXX Unaligned */
@@ -206,29 +209,43 @@
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_name)) != 0) {
+	if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) {
 		dev->num_irqs = 1;
-	} else if ((len = prom_getproperty(node, "interrupts",
-	    (char *)&irqs, sizeof(irqs))) == -1 || len == 0) {
-		dev->num_irqs = 0;
-		if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
-			 dev->num_irqs = 1;
-/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
-		}
 	} else {
-		dev->num_irqs = 1;  /* dev->num_irqs = len / sizeof(irqs[0]); */
-		if (irqs[0] == 0 || irqs[0] >= 8) {
-			/* See above for the parent. XXX */
-			printk("EBUS: %s got bad irq %d from PROM\n",
-			    dev->prom_name, irqs[0]);
+		irqs = of_get_property(dp, "interrupts", &len);
+		if (!irqs) {
 			dev->num_irqs = 0;
-			dev->irqs[0] = 0;
+			if ((dev->irqs[0] = dev->bus->self->irq) != 0) {
+				dev->num_irqs = 1;
+/* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */
+			}
 		} else {
-			dev->irqs[0] = pcic_pin_to_irq(irqs[0], dev->prom_name);
+			dev->num_irqs = 1;  /* dev->num_irqs = len / sizeof(irqs[0]); */
+			if (irqs[0] == 0 || irqs[0] >= 8) {
+				/* See above for the parent. XXX */
+				printk("EBUS: %s got bad irq %d from PROM\n",
+				       dev->prom_node->name, irqs[0]);
+				dev->num_irqs = 0;
+				dev->irqs[0] = 0;
+			} else {
+				dev->irqs[0] =
+					pcic_pin_to_irq(irqs[0],
+							dev->prom_node->name);
+			}
 		}
 	}
 
-	if ((node = prom_getchild(node))) {
+	dev->ofdev.node = dp;
+	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+	dev->ofdev.dev.bus = &ebus_bus_type;
+	strcpy(dev->ofdev.dev.bus_id, dp->path_component_name);
+
+	/* Register with core */
+	if (of_device_register(&dev->ofdev) != 0)
+		printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+		       dev->ofdev.dev.bus_id);
+
+	if ((dp = dp->child) != NULL) {
 		dev->children = (struct linux_ebus_child *)
 			ebus_alloc(sizeof(struct linux_ebus_child));
 
@@ -236,9 +253,9 @@
 		child->next = NULL;
 		child->parent = dev;
 		child->bus = dev->bus;
-		fill_ebus_child(node, &regs[0], child);
+		fill_ebus_child(dp, child);
 
-		while ((node = prom_getsibling(node)) != 0) {
+		while ((dp = dp->sibling) != NULL) {
 			child->next = (struct linux_ebus_child *)
 				ebus_alloc(sizeof(struct linux_ebus_child));
 
@@ -246,51 +263,49 @@
 			child->next = NULL;
 			child->parent = dev;
 			child->bus = dev->bus;
-			fill_ebus_child(node, &regs[0], child);
+			fill_ebus_child(dp, child);
 		}
 	}
 }
 
 void __init ebus_init(void)
 {
-	struct linux_prom_pci_registers regs[PROMREG_MAX];
+	struct linux_prom_pci_registers *regs;
 	struct linux_pbm_info *pbm;
 	struct linux_ebus_device *dev;
 	struct linux_ebus *ebus;
 	struct ebus_system_entry *sp;
 	struct pci_dev *pdev;
 	struct pcidev_cookie *cookie;
-	char lbuf[128];
+	struct device_node *dp;
 	unsigned long addr, *base;
 	unsigned short pci_command;
-	int nd, len, ebusnd;
-	int reg, nreg;
+	int len, reg, nreg;
 	int num_ebus = 0;
 
-	prom_getstring(prom_root_node, "name", lbuf, sizeof(lbuf));
+	dp = of_find_node_by_path("/");
 	for (sp = ebus_blacklist; sp->esname != NULL; sp++) {
-		if (strcmp(lbuf, sp->esname) == 0) {
+		if (strcmp(dp->name, sp->esname) == 0) {
 			ebus_blackp = sp->ipt;
 			break;
 		}
 	}
 
 	pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL);
-	if (!pdev) {
+	if (!pdev)
 		return;
-	}
+
 	cookie = pdev->sysdata;
-	ebusnd = cookie->prom_node;
+	dp = cookie->prom_node;
 
 	ebus_chain = ebus = (struct linux_ebus *)
 			ebus_alloc(sizeof(struct linux_ebus));
 	ebus->next = NULL;
 
-	while (ebusnd) {
+	while (dp) {
+		struct device_node *nd;
 
-		prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
-		ebus->prom_node = ebusnd;
-		strcpy(ebus->prom_name, lbuf);
+		ebus->prom_node = dp;
 		ebus->self = pdev;
 		ebus->parent = pbm = cookie->pbm;
 
@@ -299,9 +314,8 @@
 		pci_command |= PCI_COMMAND_MASTER;
 		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
 
-		len = prom_getproperty(ebusnd, "reg", (void *)regs,
-				       sizeof(regs));
-		if (len == 0 || len == -1) {
+		regs = of_get_property(dp, "reg", &len);
+		if (!regs) {
 			prom_printf("%s: can't find reg property\n",
 				    __FUNCTION__);
 			prom_halt();
@@ -317,7 +331,18 @@
 			*base++ = addr;
 		}
 
-		nd = prom_getchild(ebusnd);
+		ebus->ofdev.node = dp;
+		ebus->ofdev.dev.parent = &pdev->dev;
+		ebus->ofdev.dev.bus = &ebus_bus_type;
+		strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name);
+
+		/* Register with core */
+		if (of_device_register(&ebus->ofdev) != 0)
+			printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+			       ebus->ofdev.dev.bus_id);
+
+
+		nd = dp->child;
 		if (!nd)
 			goto next_ebus;
 
@@ -330,7 +355,7 @@
 		dev->bus = ebus;
 		fill_ebus_device(nd, dev);
 
-		while ((nd = prom_getsibling(nd)) != 0) {
+		while ((nd = nd->sibling) != NULL) {
 			dev->next = (struct linux_ebus_device *)
 				ebus_alloc(sizeof(struct linux_ebus_device));
 
@@ -348,7 +373,7 @@
 			break;
 
 		cookie = pdev->sysdata;
-		ebusnd = cookie->prom_node;
+		dp = cookie->prom_node;
 
 		ebus->next = (struct linux_ebus *)
 			ebus_alloc(sizeof(struct linux_ebus));
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index f9ff297..ae4c667 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -39,6 +39,8 @@
 #include <asm/io.h>
 #include <asm/vaddrs.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/sbus.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/dma.h>
@@ -224,10 +226,54 @@
 
 #ifdef CONFIG_SBUS
 
-void sbus_set_sbus64(struct sbus_dev *sdev, int x) {
+void sbus_set_sbus64(struct sbus_dev *sdev, int x)
+{
 	printk("sbus_set_sbus64: unsupported\n");
 }
 
+extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
+void __init sbus_fill_device_irq(struct sbus_dev *sdev)
+{
+	struct linux_prom_irqs irqs[PROMINTR_MAX];
+	int len;
+
+	len = prom_getproperty(sdev->prom_node, "intr",
+			       (char *)irqs, sizeof(irqs));
+	if (len != -1) {
+		sdev->num_irqs = len / 8;
+		if (sdev->num_irqs == 0) {
+			sdev->irqs[0] = 0;
+		} else if (sparc_cpu_model == sun4d) {
+			for (len = 0; len < sdev->num_irqs; len++)
+				sdev->irqs[len] =
+					sun4d_build_irq(sdev, irqs[len].pri);
+		} else {
+			for (len = 0; len < sdev->num_irqs; len++)
+				sdev->irqs[len] = irqs[len].pri;
+		}
+	} else {
+		int interrupts[PROMINTR_MAX];
+
+		/* No "intr" node found-- check for "interrupts" node.
+		 * This node contains SBus interrupt levels, not IPLs
+		 * as in "intr", and no vector values.  We convert
+		 * SBus interrupt levels to PILs (platform specific).
+		 */
+		len = prom_getproperty(sdev->prom_node, "interrupts",
+				       (char *)interrupts, sizeof(interrupts));
+		if (len == -1) {
+			sdev->irqs[0] = 0;
+			sdev->num_irqs = 0;
+		} else {
+			sdev->num_irqs = len / sizeof(int);
+			for (len = 0; len < sdev->num_irqs; len++) {
+				sdev->irqs[len] =
+					sbint_to_irq(sdev, interrupts[len]);
+			}
+		}
+	} 
+}
+
 /*
  * Allocate a chunk of memory suitable for DMA.
  * Typically devices use them for control blocks.
@@ -414,6 +460,89 @@
 {
 	printk("sbus_dma_sync_sg_for_device: not implemented yet\n");
 }
+
+/* Support code for sbus_init().  */
+/*
+ * XXX This functions appears to be a distorted version of
+ * prom_sbus_ranges_init(), with all sun4d stuff cut away.
+ * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
+ */
+/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
+void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
+{
+	int parent_node = pn->node;
+
+	if (sparc_cpu_model == sun4d) {
+		struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
+		int num_iounit_ranges, len;
+
+		len = prom_getproperty(parent_node, "ranges",
+				       (char *) iounit_ranges,
+				       sizeof (iounit_ranges));
+		if (len != -1) {
+			num_iounit_ranges =
+				(len / sizeof(struct linux_prom_ranges));
+			prom_adjust_ranges(sbus->sbus_ranges,
+					   sbus->num_sbus_ranges,
+					   iounit_ranges, num_iounit_ranges);
+		}
+	}
+}
+
+void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
+{
+	struct device_node *parent = dp->parent;
+
+	if (sparc_cpu_model != sun4d &&
+	    parent != NULL &&
+	    !strcmp(parent->name, "iommu")) {
+		extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
+
+		iommu_init(parent->node, sbus);
+	}
+
+	if (sparc_cpu_model == sun4d) {
+		extern void iounit_init(int sbi_node, int iounit_node,
+					struct sbus_bus *sbus);
+
+		iounit_init(dp->node, parent->node, sbus);
+	}
+}
+
+void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
+{
+	if (sparc_cpu_model == sun4d) {
+		struct device_node *parent = dp->parent;
+
+		sbus->devid = of_getintprop_default(parent, "device-id", 0);
+		sbus->board = of_getintprop_default(parent, "board#", 0);
+	}
+}
+
+int __init sbus_arch_preinit(void)
+{
+	extern void register_proc_sparc_ioport(void);
+
+	register_proc_sparc_ioport();
+
+#ifdef CONFIG_SUN4
+	{
+		extern void sun4_dvma_init(void);
+		sun4_dvma_init();
+	}
+	return 1;
+#else
+	return 0;
+#endif
+}
+
+void __init sbus_arch_postinit(void)
+{
+	if (sparc_cpu_model == sun4d) {
+		extern void sun4d_init_sbi_irq(void);
+		sun4d_init_sbi_irq();
+	}
+}
 #endif /* CONFIG_SBUS */
 
 #ifdef CONFIG_PCI
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
new file mode 100644
index 0000000..80a8094
--- /dev/null
+++ b/arch/sparc/kernel/of_device.c
@@ -0,0 +1,270 @@
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include <asm/errno.h>
+#include <asm/of_device.h>
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
+					const struct of_device *dev)
+{
+	if (!dev->node)
+		return NULL;
+	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+		int match = 1;
+		if (matches->name[0])
+			match &= dev->node->name
+				&& !strcmp(matches->name, dev->node->name);
+		if (matches->type[0])
+			match &= dev->node->type
+				&& !strcmp(matches->type, dev->node->type);
+		if (matches->compatible[0])
+			match &= of_device_is_compatible(dev->node,
+							 matches->compatible);
+		if (match)
+			return matches;
+		matches++;
+	}
+	return NULL;
+}
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+	const struct of_device_id * matches = of_drv->match_table;
+
+	if (!matches)
+		return 0;
+
+	return of_match_device(matches, of_dev) != NULL;
+}
+
+struct of_device *of_dev_get(struct of_device *dev)
+{
+	struct device *tmp;
+
+	if (!dev)
+		return NULL;
+	tmp = get_device(&dev->dev);
+	if (tmp)
+		return to_of_device(tmp);
+	else
+		return NULL;
+}
+
+void of_dev_put(struct of_device *dev)
+{
+	if (dev)
+		put_device(&dev->dev);
+}
+
+
+static int of_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct of_platform_driver *drv;
+	struct of_device *of_dev;
+	const struct of_device_id *match;
+
+	drv = to_of_platform_driver(dev->driver);
+	of_dev = to_of_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	of_dev_get(of_dev);
+
+	match = of_match_device(drv->match_table, of_dev);
+	if (match)
+		error = drv->probe(of_dev, match);
+	if (error)
+		of_dev_put(of_dev);
+
+	return error;
+}
+
+static int of_device_remove(struct device *dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(of_dev);
+	return 0;
+}
+
+static int of_device_suspend(struct device *dev, pm_message_t state)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->suspend)
+		error = drv->suspend(of_dev, state);
+	return error;
+}
+
+static int of_device_resume(struct device * dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->resume)
+		error = drv->resume(of_dev);
+	return error;
+}
+
+#ifdef CONFIG_PCI
+struct bus_type ebus_bus_type = {
+       .name	= "ebus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+EXPORT_SYMBOL(ebus_bus_type);
+#endif
+
+#ifdef CONFIG_SBUS
+struct bus_type sbus_bus_type = {
+       .name	= "sbus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+EXPORT_SYMBOL(sbus_bus_type);
+#endif
+
+static int __init of_bus_driver_init(void)
+{
+	int err = 0;
+
+#ifdef CONFIG_PCI
+	if (!err)
+		err = bus_register(&ebus_bus_type);
+#endif
+#ifdef CONFIG_SBUS
+	if (!err)
+		err = bus_register(&sbus_bus_type);
+#endif
+	return 0;
+}
+
+postcore_initcall(of_bus_driver_init);
+
+int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
+{
+	/* initialize common driver fields */
+	drv->driver.name = drv->name;
+	drv->driver.bus = bus;
+
+	/* register with core */
+	return driver_register(&drv->driver);
+}
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+
+
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct of_device *ofdev;
+
+	ofdev = to_of_device(dev);
+	return sprintf(buf, "%s", ofdev->node->full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+/**
+ * of_release_dev - free an of device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this of device are
+ * done.
+ */
+void of_release_dev(struct device *dev)
+{
+	struct of_device *ofdev;
+
+        ofdev = to_of_device(dev);
+
+	kfree(ofdev);
+}
+
+int of_device_register(struct of_device *ofdev)
+{
+	int rc;
+
+	BUG_ON(ofdev->node == NULL);
+
+	rc = device_register(&ofdev->dev);
+	if (rc)
+		return rc;
+
+	device_create_file(&ofdev->dev, &dev_attr_devspec);
+
+	return 0;
+}
+
+void of_device_unregister(struct of_device *ofdev)
+{
+	device_remove_file(&ofdev->dev, &dev_attr_devspec);
+	device_unregister(&ofdev->dev);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np,
+					    const char *bus_id,
+					    struct device *parent,
+					    struct bus_type *bus)
+{
+	struct of_device *dev;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
+
+	dev->dev.parent = parent;
+	dev->dev.bus = bus;
+	dev->dev.release = of_release_dev;
+
+	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+	if (of_device_register(dev) != 0) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_dev_get);
+EXPORT_SYMBOL(of_dev_put);
+EXPORT_SYMBOL(of_platform_device_create);
+EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index 42002b7..bcfdddd 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -31,6 +31,7 @@
 
 #include <asm/irq.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/pcic.h>
 #include <asm/timer.h>
 #include <asm/uaccess.h>
@@ -665,7 +666,7 @@
 		/* cookies */
 		pcp = pci_devcookie_alloc();
 		pcp->pbm = &pcic->pbm;
-		pcp->prom_node = node;
+		pcp->prom_node = of_find_node_by_phandle(node);
 		dev->sysdata = pcp;
 
 		/* fixing I/O to look like memory */
@@ -896,13 +897,6 @@
 	return 1 << irq_nr;
 }
 
-static inline char *pcic_irq_itoa(unsigned int irq)
-{
-	static char buff[16];
-	sprintf(buff, "%d", irq);
-	return buff;
-}
-
 static void pcic_disable_irq(unsigned int irq_nr)
 {
 	unsigned long mask, flags;
@@ -955,7 +949,6 @@
 	BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM);
 }
 
 int pcibios_assign_resource(struct pci_dev *pdev, int resource)
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c
new file mode 100644
index 0000000..946ce6d
--- /dev/null
+++ b/arch/sparc/kernel/prom.c
@@ -0,0 +1,544 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com 
+ *
+ *  Adapted for sparc32 by David S. Miller davem@davemloft.net
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+
+#include <asm/prom.h>
+#include <asm/oplib.h>
+
+static struct device_node *allnodes;
+
+/* use when traversing tree through the allnext, child, sibling,
+ * or parent members of struct device_node.
+ */
+static DEFINE_RWLOCK(devtree_lock);
+
+int of_device_is_compatible(struct device_node *device, const char *compat)
+{
+	const char* cp;
+	int cplen, l;
+
+	cp = (char *) of_get_property(device, "compatible", &cplen);
+	if (cp == NULL)
+		return 0;
+	while (cplen > 0) {
+		if (strncmp(cp, compat, strlen(compat)) == 0)
+			return 1;
+		l = strlen(cp) + 1;
+		cp += l;
+		cplen -= l;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(of_device_is_compatible);
+
+struct device_node *of_get_parent(const struct device_node *node)
+{
+	struct device_node *np;
+
+	if (!node)
+		return NULL;
+
+	np = node->parent;
+
+	return np;
+}
+EXPORT_SYMBOL(of_get_parent);
+
+struct device_node *of_get_next_child(const struct device_node *node,
+	struct device_node *prev)
+{
+	struct device_node *next;
+
+	next = prev ? prev->sibling : node->child;
+	for (; next != 0; next = next->sibling) {
+		break;
+	}
+
+	return next;
+}
+EXPORT_SYMBOL(of_get_next_child);
+
+struct device_node *of_find_node_by_path(const char *path)
+{
+	struct device_node *np = allnodes;
+
+	for (; np != 0; np = np->allnext) {
+		if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_path);
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->node == handle)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+struct device_node *of_find_node_by_name(struct device_node *from,
+	const char *name)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != NULL; np = np->allnext)
+		if (np->name != NULL && strcmp(np->name, name) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_name);
+
+struct device_node *of_find_node_by_type(struct device_node *from,
+	const char *type)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext)
+		if (np->type != 0 && strcmp(np->type, type) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_type);
+
+struct device_node *of_find_compatible_node(struct device_node *from,
+	const char *type, const char *compatible)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext) {
+		if (type != NULL
+		    && !(np->type != 0 && strcmp(np->type, type) == 0))
+			continue;
+		if (of_device_is_compatible(np, compatible))
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_compatible_node);
+
+struct property *of_find_property(struct device_node *np, const char *name,
+				  int *lenp)
+{
+	struct property *pp;
+
+	for (pp = np->properties; pp != 0; pp = pp->next) {
+		if (strcmp(pp->name, name) == 0) {
+			if (lenp != 0)
+				*lenp = pp->length;
+			break;
+		}
+	}
+	return pp;
+}
+EXPORT_SYMBOL(of_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+void *of_get_property(struct device_node *np, const char *name, int *lenp)
+{
+	struct property *pp = of_find_property(np,name,lenp);
+	return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(of_get_property);
+
+int of_getintprop_default(struct device_node *np, const char *name, int def)
+{
+	struct property *prop;
+	int len;
+
+	prop = of_find_property(np, name, &len);
+	if (!prop || len != 4)
+		return def;
+
+	return *(int *) prop->value;
+}
+EXPORT_SYMBOL(of_getintprop_default);
+
+int of_set_property(struct device_node *dp, const char *name, void *val, int len)
+{
+	struct property **prevp;
+	void *new_val;
+	int err;
+
+	new_val = kmalloc(len, GFP_KERNEL);
+	if (!new_val)
+		return -ENOMEM;
+
+	memcpy(new_val, val, len);
+
+	err = -ENODEV;
+
+	write_lock(&devtree_lock);
+	prevp = &dp->properties;
+	while (*prevp) {
+		struct property *prop = *prevp;
+
+		if (!strcmp(prop->name, name)) {
+			void *old_val = prop->value;
+			int ret;
+
+			ret = prom_setprop(dp->node, name, val, len);
+			err = -EINVAL;
+			if (ret >= 0) {
+				prop->value = new_val;
+				prop->length = len;
+
+				if (OF_IS_DYNAMIC(prop))
+					kfree(old_val);
+
+				OF_MARK_DYNAMIC(prop);
+
+				err = 0;
+			}
+			break;
+		}
+		prevp = &(*prevp)->next;
+	}
+	write_unlock(&devtree_lock);
+
+	/* XXX Upate procfs if necessary... */
+
+	return err;
+}
+EXPORT_SYMBOL(of_set_property);
+
+static unsigned int prom_early_allocated;
+
+static void * __init prom_early_alloc(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	prom_early_allocated += size;
+
+	return ret;
+}
+
+static int is_root_node(const struct device_node *dp)
+{
+	if (!dp)
+		return 0;
+
+	return (dp->parent == NULL);
+}
+
+/* The following routines deal with the black magic of fully naming a
+ * node.
+ *
+ * Certain well known named nodes are just the simple name string.
+ *
+ * Actual devices have an address specifier appended to the base name
+ * string, like this "foo@addr".  The "addr" can be in any number of
+ * formats, and the platform plus the type of the node determine the
+ * format and how it is constructed.
+ *
+ * For children of the ROOT node, the naming convention is fixed and
+ * determined by whether this is a sun4u or sun4v system.
+ *
+ * For children of other nodes, it is bus type specific.  So
+ * we walk up the tree until we discover a "device_type" property
+ * we recognize and we go from there.
+ */
+static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *rprop;
+
+	rprop = of_find_property(dp, "reg", NULL);
+	if (!rprop)
+		return;
+
+	regs = rprop->value;
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io, regs->phys_addr);
+}
+
+/* "name@slot,offset"  */
+static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io,
+		regs->phys_addr);
+}
+
+/* "name@devnum[,func]" */
+static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_pci_registers *regs;
+	struct property *prop;
+	unsigned int devfn;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	devfn = (regs->phys_hi >> 8) & 0xff;
+	if (devfn & 0x07) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			devfn >> 3,
+			devfn & 0x07);
+	} else {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name,
+			devfn >> 3);
+	}
+}
+
+/* "name@addrhi,addrlo" */
+static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io, regs->phys_addr);
+}
+
+static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct device_node *parent = dp->parent;
+
+	if (parent != NULL) {
+		if (!strcmp(parent->type, "pci") ||
+		    !strcmp(parent->type, "pciex"))
+			return pci_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "sbus"))
+			return sbus_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "ebus"))
+			return ebus_path_component(dp, tmp_buf);
+
+		/* "isa" is handled with platform naming */
+	}
+
+	/* Use platform naming convention.  */
+	return sparc32_path_component(dp, tmp_buf);
+}
+
+static char * __init build_path_component(struct device_node *dp)
+{
+	char tmp_buf[64], *n;
+
+	tmp_buf[0] = '\0';
+	__build_path_component(dp, tmp_buf);
+	if (tmp_buf[0] == '\0')
+		strcpy(tmp_buf, dp->name);
+
+	n = prom_early_alloc(strlen(tmp_buf) + 1);
+	strcpy(n, tmp_buf);
+
+	return n;
+}
+
+static char * __init build_full_name(struct device_node *dp)
+{
+	int len, ourlen, plen;
+	char *n;
+
+	plen = strlen(dp->parent->full_name);
+	ourlen = strlen(dp->path_component_name);
+	len = ourlen + plen + 2;
+
+	n = prom_early_alloc(len);
+	strcpy(n, dp->parent->full_name);
+	if (!is_root_node(dp->parent)) {
+		strcpy(n + plen, "/");
+		plen++;
+	}
+	strcpy(n + plen, dp->path_component_name);
+
+	return n;
+}
+
+static unsigned int unique_id;
+
+static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
+{
+	static struct property *tmp = NULL;
+	struct property *p;
+	int len;
+
+	if (tmp) {
+		p = tmp;
+		memset(p, 0, sizeof(*p) + 32);
+		tmp = NULL;
+	} else {
+		p = prom_early_alloc(sizeof(struct property) + 32);
+		p->unique_id = unique_id++;
+	}
+
+	p->name = (char *) (p + 1);
+	if (special_name) {
+		p->length = special_len;
+		p->value = prom_early_alloc(special_len);
+		memcpy(p->value, special_val, special_len);
+	} else {
+		if (prev == NULL) {
+			prom_firstprop(node, p->name);
+		} else {
+			prom_nextprop(node, prev, p->name);
+		}
+		if (strlen(p->name) == 0) {
+			tmp = p;
+			return NULL;
+		}
+		p->length = prom_getproplen(node, p->name);
+		if (p->length <= 0) {
+			p->length = 0;
+		} else {
+			p->value = prom_early_alloc(p->length + 1);
+			prom_getproperty(node, p->name, p->value, p->length);
+			((unsigned char *)p->value)[p->length] = '\0';
+		}
+	}
+	return p;
+}
+
+static struct property * __init build_prop_list(phandle node)
+{
+	struct property *head, *tail;
+
+	head = tail = build_one_prop(node, NULL,
+				     ".node", &node, sizeof(node));
+
+	tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
+	tail = tail->next;
+	while(tail) {
+		tail->next = build_one_prop(node, tail->name,
+					    NULL, NULL, 0);
+		tail = tail->next;
+	}
+
+	return head;
+}
+
+static char * __init get_one_property(phandle node, char *name)
+{
+	char *buf = "<NULL>";
+	int len;
+
+	len = prom_getproplen(node, name);
+	if (len > 0) {
+		buf = prom_early_alloc(len);
+		len = prom_getproperty(node, name, buf, len);
+	}
+
+	return buf;
+}
+
+static struct device_node * __init create_node(phandle node)
+{
+	struct device_node *dp;
+
+	if (!node)
+		return NULL;
+
+	dp = prom_early_alloc(sizeof(*dp));
+	dp->unique_id = unique_id++;
+
+	kref_init(&dp->kref);
+
+	dp->name = get_one_property(node, "name");
+	dp->type = get_one_property(node, "device_type");
+	dp->node = node;
+
+	/* Build interrupts later... */
+
+	dp->properties = build_prop_list(node);
+
+	return dp;
+}
+
+static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
+{
+	struct device_node *dp;
+
+	dp = create_node(node);
+	if (dp) {
+		*(*nextp) = dp;
+		*nextp = &dp->allnext;
+
+		dp->parent = parent;
+		dp->path_component_name = build_path_component(dp);
+		dp->full_name = build_full_name(dp);
+
+		dp->child = build_tree(dp, prom_getchild(node), nextp);
+
+		dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
+	}
+
+	return dp;
+}
+
+void __init prom_build_devicetree(void)
+{
+	struct device_node **nextp;
+
+	allnodes = create_node(prom_root_node);
+	allnodes->path_component_name = "";
+	allnodes->full_name = "/";
+
+	nextp = &allnodes->allnext;
+	allnodes->child = build_tree(allnodes,
+				     prom_getchild(allnodes->node),
+				     &nextp);
+	printk("PROM: Built device tree with %u bytes of memory.\n",
+	       prom_early_allocated);
+}
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 3509e43..a893a9c 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -31,6 +31,7 @@
 #include <linux/console.h>
 #include <linux/spinlock.h>
 #include <linux/root_dev.h>
+#include <linux/cpu.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -331,7 +332,7 @@
 	if (!root_flags)
 		root_mountflags &= ~MS_RDONLY;
 	ROOT_DEV = old_decode_dev(root_dev);
-#ifdef CONFIG_BLK_DEV_INITRD
+#ifdef CONFIG_BLK_DEV_RAM
 	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);	
@@ -348,6 +349,8 @@
 	init_mm.context = (unsigned long) NO_CONTEXT;
 	init_task.thread.kregs = &fake_swapper_regs;
 
+	smp_setup_cpu_possible_map();
+
 	paging_init();
 }
 
@@ -389,6 +392,8 @@
 extern char *sparc_cpu_type;
 extern char *sparc_fpu_type;
 
+static int ncpus_probed;
+
 static int show_cpuinfo(struct seq_file *m, void *__unused)
 {
 	seq_printf(m,
@@ -411,7 +416,7 @@
 		   romvec->pv_printrev >> 16,
 		   romvec->pv_printrev & 0xffff,
 		   &cputypval,
-		   num_possible_cpus(),
+		   ncpus_probed,
 		   num_online_cpus()
 #ifndef CONFIG_SMP
 		   , cpu_data(0).udelay_val/(500000/HZ),
@@ -471,3 +476,30 @@
 
 int serial_console = -1;
 int stop_a_enabled = 1;
+
+static int __init topology_init(void)
+{
+	int i, ncpus, err;
+
+	/* Count the number of physically present processors in
+	 * the machine, even on uniprocessor, so that /proc/cpuinfo
+	 * output is consistent with 2.4.x
+	 */
+	ncpus = 0;
+	while (!cpu_find_by_instance(ncpus, NULL, NULL))
+		ncpus++;
+	ncpus_probed = ncpus;
+
+	err = 0;
+	for_each_online_cpu(i) {
+		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
+		if (!p)
+			err = -ENOMEM;
+		else
+			register_cpu(p, i, NULL);
+	}
+
+	return err;
+}
+
+subsys_initcall(topology_init);
diff --git a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c
index 40b42c8..6135d4f 100644
--- a/arch/sparc/kernel/smp.c
+++ b/arch/sparc/kernel/smp.c
@@ -58,7 +58,7 @@
 /* Used to make bitops atomic */
 unsigned char bitops_spinlock = 0;
 
-void __init smp_store_cpu_info(int id)
+void __cpuinit smp_store_cpu_info(int id)
 {
 	int cpu_node;
 
@@ -267,22 +267,18 @@
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	extern void smp4m_boot_cpus(void);
-	int i, cpuid, ncpus, extra;
+	int i, cpuid, extra;
 
 	BUG_ON(sparc_cpu_model != sun4m);
 	printk("Entering SMP Mode...\n");
 
-	ncpus = 1;
 	extra = 0;
 	for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) {
-		if (cpuid == boot_cpu_id)
-			continue;
-		if (cpuid < NR_CPUS && ncpus++ < max_cpus)
-			cpu_set(cpuid, phys_cpu_present_map);
-		else
+		if (cpuid >= NR_CPUS)
 			extra++;
 	}
-	if (max_cpus >= NR_CPUS && extra)
+	/* i = number of cpus */
+	if (extra && max_cpus > i - extra)
 		printk("Warning: NR_CPUS is too low to start all cpus\n");
 
 	smp_store_cpu_info(boot_cpu_id);
@@ -290,7 +286,25 @@
 	smp4m_boot_cpus();
 }
 
-void __devinit smp_prepare_boot_cpu(void)
+/* Set this up early so that things like the scheduler can init
+ * properly.  We use the same cpu mask for both the present and
+ * possible cpu map.
+ */
+void __init smp_setup_cpu_possible_map(void)
+{
+	int instance, mid;
+
+	instance = 0;
+	while (!cpu_find_by_instance(instance, NULL, &mid)) {
+		if (mid < NR_CPUS) {
+			cpu_set(mid, phys_cpu_present_map);
+			cpu_set(mid, cpu_present_map);
+		}
+		instance++;
+	}
+}
+
+void __init smp_prepare_boot_cpu(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -306,7 +320,7 @@
 	cpu_set(cpuid, phys_cpu_present_map);
 }
 
-int __devinit __cpu_up(unsigned int cpu)
+int __cpuinit __cpu_up(unsigned int cpu)
 {
 	extern int smp4m_boot_one_cpu(int);
 	int ret;
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index 4b376fa..fd7deab 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -163,7 +163,6 @@
 #endif
 EXPORT_SYMBOL(BTFIXUP_CALL(enable_irq));
 EXPORT_SYMBOL(BTFIXUP_CALL(disable_irq));
-EXPORT_SYMBOL(BTFIXUP_CALL(__irq_itoa));
 EXPORT_SYMBOL(BTFIXUP_CALL(mmu_unlockarea));
 EXPORT_SYMBOL(BTFIXUP_CALL(mmu_lockarea));
 EXPORT_SYMBOL(BTFIXUP_CALL(mmu_get_scsi_sgl));
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c
index 3d6a990..0f2d8d9 100644
--- a/arch/sparc/kernel/sun4c_irq.c
+++ b/arch/sparc/kernel/sun4c_irq.c
@@ -198,8 +198,6 @@
 static void sun4c_nop(void) {}
 #endif
 
-extern char *sun4m_irq_itoa(unsigned int irq);
-
 void __init sun4c_init_IRQ(void)
 {
 	struct linux_prom_registers int_regs[2];
@@ -238,7 +236,6 @@
 	BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
-	BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
 	sparc_init_timers = sun4c_init_timers;
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index ca656d9..9c30e35 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -560,17 +560,6 @@
 	}
 }
 
-static char *sun4d_irq_itoa(unsigned int irq)
-{
-	static char buff[16];
-	
-	if (irq < (1 << 5))
-		sprintf(buff, "%d", irq);
-	else
-		sprintf(buff, "%d,%x", sbus_to_pil[(irq >> 2) & 7], irq);
-	return buff;
-}
-
 void __init sun4d_init_IRQ(void)
 {
 	local_irq_disable();
@@ -581,7 +570,6 @@
 	BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(__irq_itoa, sun4d_irq_itoa, BTFIXUPCALL_NORM);
 	sparc_init_timers = sun4d_init_timers;
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 39d712c..a296c13 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -229,13 +229,6 @@
 	sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit;
 }
 
-char *sun4m_irq_itoa(unsigned int irq)
-{
-	static char buff[16];
-	sprintf(buff, "%d", irq);
-	return buff;
-}
-
 static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *))
 {
 	int reg_count, irq, cpu;
@@ -388,7 +381,6 @@
 	BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(__irq_itoa, sun4m_irq_itoa, BTFIXUPCALL_NORM);
 	sparc_init_timers = sun4m_init_timers;
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c
index 70b375a..3b32096 100644
--- a/arch/sparc/kernel/sun4m_smp.c
+++ b/arch/sparc/kernel/sun4m_smp.c
@@ -66,7 +66,7 @@
 static void smp_setup_percpu_timer(void);
 extern void cpu_probe(void);
 
-void __init smp4m_callin(void)
+void __cpuinit smp4m_callin(void)
 {
 	int cpuid = hard_smp_processor_id();
 
@@ -112,13 +112,8 @@
 	local_irq_enable();
 
 	cpu_set(cpuid, cpu_online_map);
-	/* last one in gets all the interrupts (for testing) */
-	set_irq_udt(boot_cpu_id);
 }
 
-extern void init_IRQ(void);
-extern void cpu_panic(void);
-
 /*
  *	Cycle through the processors asking the PROM to start each one.
  */
@@ -134,7 +129,7 @@
 	local_flush_cache_all();
 }
 
-int smp4m_boot_one_cpu(int i)
+int __cpuinit smp4m_boot_one_cpu(int i)
 {
 	extern unsigned long sun4m_cpu_startup;
 	unsigned long *entry = &sun4m_cpu_startup;
diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
index fa50069..5db7e1d 100644
--- a/arch/sparc/lib/Makefile
+++ b/arch/sparc/lib/Makefile
@@ -9,3 +9,5 @@
 	 strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
 	 copy_user.o locks.o atomic.o atomic32.o bitops.o \
 	 lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o
+
+obj-y += iomap.o
diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c
new file mode 100644
index 0000000..54501c1
--- /dev/null
+++ b/arch/sparc/lib/iomap.c
@@ -0,0 +1,48 @@
+/*
+ * Implement the sparc iomap interfaces
+ */
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+/* Create a virtual mapping cookie for an IO port range */
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return (void __iomem *) (unsigned long) port;
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing to do */
+}
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM) {
+		if (flags & IORESOURCE_CACHEABLE)
+			return ioremap(start, len);
+		return ioremap_nocache(start, len);
+	}
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+	/* nothing to do */
+}
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 8986697..cfa7d34 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -31,6 +31,7 @@
 #include <asm/vaddrs.h>
 #include <asm/pgalloc.h>	/* bug in asm-generic/tlb.h: check_pgt_cache */
 #include <asm/tlb.h>
+#include <asm/prom.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
@@ -349,6 +350,7 @@
 	protection_map[14] = PAGE_SHARED;
 	protection_map[15] = PAGE_SHARED;
 	btfixup();
+	prom_build_devicetree();
 	device_scan();
 }
 
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 77840c8..7215849 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -144,8 +144,9 @@
 	unsigned long start;
 	unsigned long end;
 
-	start = (unsigned long)iopte & PAGE_MASK;
+	start = (unsigned long)iopte;
 	end = PAGE_ALIGN(start + niopte*sizeof(iopte_t));
+	start &= PAGE_MASK;
 	if (viking_mxcc_present) {
 		while(start < end) {
 			viking_mxcc_flush_page(start);
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 43a66f5..a7a111d 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -87,6 +87,10 @@
 	depends on COMPAT && SYSVIPC
 	default y
 
+config GENERIC_HARDIRQS
+	bool
+	default y
+
 menu "General machine setup"
 
 config SMP
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index f09a70b..b2f4114 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc3
-# Fri May 12 12:43:49 2006
+# Linux kernel version: 2.6.17
+# Fri Jun 23 23:17:09 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -87,6 +87,7 @@
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="anticipatory"
 CONFIG_SYSVIPC_COMPAT=y
+CONFIG_GENERIC_HARDIRQS=y
 
 #
 # General machine setup
@@ -183,6 +184,8 @@
 CONFIG_INET_IPCOMP=y
 CONFIG_INET_XFRM_TUNNEL=y
 CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 CONFIG_TCP_CONG_ADVANCED=y
@@ -198,6 +201,9 @@
 CONFIG_TCP_CONG_HYBLA=m
 CONFIG_TCP_CONG_VEGAS=m
 CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_COMPOUND=m
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -207,7 +213,10 @@
 CONFIG_INET6_IPCOMP=m
 CONFIG_INET6_XFRM_TUNNEL=m
 CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
 CONFIG_IPV6_TUNNEL=m
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -260,6 +269,7 @@
 # Network testing
 #
 CONFIG_NET_PKTGEN=m
+CONFIG_NET_TCPPROBE=m
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -276,6 +286,7 @@
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -424,6 +435,7 @@
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
 # CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_IPS is not set
@@ -562,6 +574,7 @@
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -722,6 +735,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -765,6 +779,7 @@
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
 # CONFIG_SENSORS_ADM1026 is not set
@@ -793,10 +808,12 @@
 # CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
 # CONFIG_SENSORS_W83792D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
@@ -811,6 +828,7 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -1006,6 +1024,7 @@
 CONFIG_USB_EHCI_HCD=m
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1085,10 +1104,12 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1135,6 +1156,19 @@
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # Misc Linux/SPARC drivers
 #
 CONFIG_SUN_OPENPROMIO=m
@@ -1173,6 +1207,7 @@
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 6f68164..86c9fe3 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -12,7 +12,7 @@
 		   irq.o ptrace.o time.o sys_sparc.o signal.o \
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
 		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
-		   visemul.o
+		   visemul.o prom.o of_device.o
 
 obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o \
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c
index 8852c20..c2c69c1 100644
--- a/arch/sparc64/kernel/auxio.c
+++ b/arch/sparc64/kernel/auxio.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -16,8 +17,8 @@
 #include <asm/ebus.h>
 #include <asm/auxio.h>
 
-/* This cannot be static, as it is referenced in irq.c */
 void __iomem *auxio_register = NULL;
+EXPORT_SYMBOL(auxio_register);
 
 enum auxio_type {
 	AUXIO_TYPE_NODEV,
@@ -110,43 +111,82 @@
 	}
 }
 
-void __init auxio_probe(void)
+static void __devinit auxio_report_dev(struct device_node *dp)
 {
-        struct sbus_bus *sbus;
-        struct sbus_dev *sdev = NULL;
-
-        for_each_sbus(sbus) {
-                for_each_sbusdev(sdev, sbus) {
-                        if(!strcmp(sdev->prom_name, "auxio"))
-				goto found_sdev;
-                }
-        }
-
-found_sdev:
-	if (sdev) {
-		auxio_devtype  = AUXIO_TYPE_SBUS;
-		auxio_register = sbus_ioremap(&sdev->resource[0], 0,
-					      sdev->reg_addrs[0].reg_size,
-					      "auxiliaryIO");
-	}
-#ifdef CONFIG_PCI
-	else {
-		struct linux_ebus *ebus;
-		struct linux_ebus_device *edev = NULL;
-
-		for_each_ebus(ebus) {
-			for_each_ebusdev(edev, ebus) {
-				if (!strcmp(edev->prom_name, "auxio"))
-					goto ebus_done;
-			}
-		}
-	ebus_done:
-		if (edev) {
-			auxio_devtype  = AUXIO_TYPE_EBUS;
-			auxio_register =
-				ioremap(edev->resource[0].start, sizeof(u32));
-		}
-	}
-	auxio_set_led(AUXIO_LED_ON);
-#endif
+	printk(KERN_INFO "AUXIO: Found device at %s\n",
+	       dp->full_name);
 }
+
+static struct of_device_id auxio_match[] = {
+	{
+		.name = "auxio",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, auxio_match);
+
+#ifdef CONFIG_SBUS
+static int __devinit auxio_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+
+	auxio_devtype  = AUXIO_TYPE_SBUS;
+	auxio_register = sbus_ioremap(&sdev->resource[0], 0,
+				      sdev->reg_addrs[0].reg_size,
+				      "auxiliaryIO");
+	if (!auxio_register)
+		return -ENODEV;
+
+	auxio_report_dev(dev->node);
+	return 0;
+}
+
+static struct of_platform_driver auxio_sbus_driver = {
+	.name		= "auxio",
+	.match_table	= auxio_match,
+	.probe		= auxio_sbus_probe,
+};
+#endif
+
+#ifdef CONFIG_PCI
+static int __devinit auxio_ebus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
+
+	auxio_devtype  = AUXIO_TYPE_EBUS;
+	auxio_register = ioremap(edev->resource[0].start, sizeof(u32));
+	if (!auxio_register)
+		return -ENODEV;
+
+	auxio_report_dev(dev->node);
+
+	auxio_set_led(AUXIO_LED_ON);
+
+	return 0;
+}
+
+static struct of_platform_driver auxio_ebus_driver = {
+	.name		= "auxio",
+	.match_table	= auxio_match,
+	.probe		= auxio_ebus_probe,
+};
+#endif
+
+static int __init auxio_probe(void)
+{
+#ifdef CONFIG_SBUS
+	of_register_driver(&auxio_sbus_driver, &sbus_bus_type);
+#endif
+#ifdef CONFIG_PCI
+	of_register_driver(&auxio_ebus_driver, &ebus_bus_type);
+#endif
+
+	return 0;
+}
+
+/* Must be after subsys_initcall() so that busses are probed.  Must
+ * be before device_initcall() because things like the floppy driver
+ * need to use the AUXIO register.
+ */
+fs_initcall(auxio_probe);
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c
index 3d184a7..b66336d 100644
--- a/arch/sparc64/kernel/central.c
+++ b/arch/sparc64/kernel/central.c
@@ -29,28 +29,34 @@
 	prom_halt();
 }
 
-static void central_ranges_init(int cnode, struct linux_central *central)
+static void central_ranges_init(struct linux_central *central)
 {
-	int success;
+	struct device_node *dp = central->prom_node;
+	void *pval;
+	int len;
 	
 	central->num_central_ranges = 0;
-	success = prom_getproperty(central->prom_node, "ranges",
-				   (char *) central->central_ranges,
-				   sizeof (central->central_ranges));
-	if (success != -1)
-		central->num_central_ranges = (success/sizeof(struct linux_prom_ranges));
+	pval = of_get_property(dp, "ranges", &len);
+	if (pval) {
+		memcpy(central->central_ranges, pval, len);
+		central->num_central_ranges =
+			(len / sizeof(struct linux_prom_ranges));
+	}
 }
 
-static void fhc_ranges_init(int fnode, struct linux_fhc *fhc)
+static void fhc_ranges_init(struct linux_fhc *fhc)
 {
-	int success;
+	struct device_node *dp = fhc->prom_node;
+	void *pval;
+	int len;
 	
 	fhc->num_fhc_ranges = 0;
-	success = prom_getproperty(fhc->prom_node, "ranges",
-				   (char *) fhc->fhc_ranges,
-				   sizeof (fhc->fhc_ranges));
-	if (success != -1)
-		fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges));
+	pval = of_get_property(dp, "ranges", &len);
+	if (pval) {
+		memcpy(fhc->fhc_ranges, pval, len);
+		fhc->num_fhc_ranges =
+			(len / sizeof(struct linux_prom_ranges));
+	}
 }
 
 /* Range application routines are exported to various drivers,
@@ -112,15 +118,10 @@
 
 static void probe_other_fhcs(void)
 {
-	struct linux_prom64_registers fpregs[6];
-	char namebuf[128];
-	int node;
+	struct device_node *dp;
+	struct linux_prom64_registers *fpregs;
 
-	node = prom_getchild(prom_root_node);
-	node = prom_searchsiblings(node, "fhc");
-	if (node == 0)
-		central_probe_failure(__LINE__);
-	while (node) {
+	for_each_node_by_name(dp, "fhc") {
 		struct linux_fhc *fhc;
 		int board;
 		u32 tmp;
@@ -137,14 +138,12 @@
 		/* Toplevel FHCs have no parent. */
 		fhc->parent = NULL;
 		
-		fhc->prom_node = node;
-		prom_getstring(node, "name", namebuf, sizeof(namebuf));
-		strcpy(fhc->prom_name, namebuf);
-		fhc_ranges_init(node, fhc);
+		fhc->prom_node = dp;
+		fhc_ranges_init(fhc);
 
 		/* Non-central FHC's have 64-bit OBP format registers. */
-		if (prom_getproperty(node, "reg",
-				    (char *)&fpregs[0], sizeof(fpregs)) == -1)
+		fpregs = of_get_property(dp, "reg", NULL);
+		if (!fpregs)
 			central_probe_failure(__LINE__);
 
 		/* Only central FHC needs special ranges applied. */
@@ -155,7 +154,7 @@
 		fhc->fhc_regs.uregs = fpregs[4].phys_addr;
 		fhc->fhc_regs.tregs = fpregs[5].phys_addr;
 
-		board = prom_getintdefault(node, "board#", -1);
+		board = of_getintprop_default(dp, "board#", -1);
 		fhc->board = board;
 
 		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL);
@@ -179,33 +178,33 @@
 		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 		tmp |= FHC_CONTROL_IXIST;
 		upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
-
-		/* Look for the next FHC. */
-		node = prom_getsibling(node);
-		if (node == 0)
-			break;
-		node = prom_searchsiblings(node, "fhc");
-		if (node == 0)
-			break;
 	}
 }
 
 static void probe_clock_board(struct linux_central *central,
 			      struct linux_fhc *fhc,
-			      int cnode, int fnode)
+			      struct device_node *fp)
 {
-	struct linux_prom_registers cregs[3];
-	int clknode, nslots, tmp, nregs;
+	struct device_node *dp;
+	struct linux_prom_registers cregs[3], *pr;
+	int nslots, tmp, nregs;
 
-	clknode = prom_searchsiblings(prom_getchild(fnode), "clock-board");
-	if (clknode == 0 || clknode == -1)
+	dp = fp->child;
+	while (dp) {
+		if (!strcmp(dp->name, "clock-board"))
+			break;
+		dp = dp->sibling;
+	}
+	if (!dp)
 		central_probe_failure(__LINE__);
 
-	nregs = prom_getproperty(clknode, "reg", (char *)&cregs[0], sizeof(cregs));
-	if (nregs == -1)
+	pr = of_get_property(dp, "reg", &nregs);
+	if (!pr)
 		central_probe_failure(__LINE__);
 
+	memcpy(cregs, pr, nregs);
 	nregs /= sizeof(struct linux_prom_registers);
+
 	apply_fhc_ranges(fhc, &cregs[0], nregs);
 	apply_central_ranges(central, &cregs[0], nregs);
 	central->cfreg = prom_reg_to_paddr(&cregs[0]);
@@ -296,13 +295,13 @@
 
 void central_probe(void)
 {
-	struct linux_prom_registers fpregs[6];
+	struct linux_prom_registers fpregs[6], *pr;
 	struct linux_fhc *fhc;
-	char namebuf[128];
-	int cnode, fnode, err;
+	struct device_node *dp, *fp;
+	int err;
 
-	cnode = prom_finddevice("/central");
-	if (cnode == 0 || cnode == -1) {
+	dp = of_find_node_by_name(NULL, "central");
+	if (!dp) {
 		if (this_is_starfire)
 			starfire_cpu_setup();
 		return;
@@ -321,31 +320,31 @@
 
 	/* First init central. */
 	central_bus->child = fhc;
-	central_bus->prom_node = cnode;
-
-	prom_getstring(cnode, "name", namebuf, sizeof(namebuf));
-	strcpy(central_bus->prom_name, namebuf);
-
-	central_ranges_init(cnode, central_bus);
+	central_bus->prom_node = dp;
+	central_ranges_init(central_bus);
 
 	/* And then central's FHC. */
 	fhc->next = fhc_list;
 	fhc_list = fhc;
 
 	fhc->parent = central_bus;
-	fnode = prom_searchsiblings(prom_getchild(cnode), "fhc");
-	if (fnode == 0 || fnode == -1)
+	fp = dp->child;
+	while (fp) {
+		if (!strcmp(fp->name, "fhc"))
+			break;
+		fp = fp->sibling;
+	}
+	if (!fp)
 		central_probe_failure(__LINE__);
 
-	fhc->prom_node = fnode;
-	prom_getstring(fnode, "name", namebuf, sizeof(namebuf));
-	strcpy(fhc->prom_name, namebuf);
-
-	fhc_ranges_init(fnode, fhc);
+	fhc->prom_node = fp;
+	fhc_ranges_init(fhc);
 
 	/* Now, map in FHC register set. */
-	if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1)
+	pr = of_get_property(fp, "reg", NULL);
+	if (!pr)
 		central_probe_failure(__LINE__);
+	memcpy(fpregs, pr, sizeof(fpregs));
 
 	apply_central_ranges(central_bus, &fpregs[0], 6);
 	
@@ -366,7 +365,7 @@
 	fhc->jtag_master = 0;
 
 	/* Attach the clock board registers for CENTRAL. */
-	probe_clock_board(central_bus, fhc, cnode, fnode);
+	probe_clock_board(central_bus, fhc, fp);
 
 	err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
 	printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n",
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c
index 97cf912..259f37e 100644
--- a/arch/sparc64/kernel/chmc.c
+++ b/arch/sparc64/kernel/chmc.c
@@ -17,6 +17,7 @@
 #include <asm/spitfire.h>
 #include <asm/chmctrl.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/io.h>
 
 #define CHMCTRL_NDGRPS	2
@@ -67,7 +68,6 @@
 struct mctrl_info {
 	struct list_head	list;
 	int			portid;
-	int			index;
 
 	struct obp_mem_layout	layout_prop;
 	int			layout_size;
@@ -339,12 +339,13 @@
 				 read_mcreg(mp, CHMCTRL_DECODE4));
 }
 
-static int init_one_mctrl(int node, int index)
+static int init_one_mctrl(struct device_node *dp)
 {
 	struct mctrl_info *mp = kmalloc(sizeof(*mp), GFP_KERNEL);
-	int portid = prom_getintdefault(node, "portid", -1);
-	struct linux_prom64_registers p_reg_prop;
-	int t;
+	int portid = of_getintprop_default(dp, "portid", -1);
+	struct linux_prom64_registers *regs;
+	void *pval;
+	int len;
 
 	if (!mp)
 		return -1;
@@ -353,24 +354,21 @@
 		goto fail;
 
 	mp->portid = portid;
-	mp->layout_size = prom_getproplen(node, "memory-layout");
-	if (mp->layout_size < 0)
+	pval = of_get_property(dp, "memory-layout", &len);
+	mp->layout_size = len;
+	if (!pval)
 		mp->layout_size = 0;
-	if (mp->layout_size > sizeof(mp->layout_prop))
+	else {
+		if (mp->layout_size > sizeof(mp->layout_prop))
+			goto fail;
+		memcpy(&mp->layout_prop, pval, len);
+	}
+
+	regs = of_get_property(dp, "reg", NULL);
+	if (!regs || regs->reg_size != 0x48)
 		goto fail;
 
-	if (mp->layout_size > 0)
-		prom_getproperty(node, "memory-layout",
-				 (char *) &mp->layout_prop,
-				 mp->layout_size);
-
-	t = prom_getproperty(node, "reg",
-			     (char *) &p_reg_prop,
-			     sizeof(p_reg_prop));
-	if (t < 0 || p_reg_prop.reg_size != 0x48)
-		goto fail;
-
-	mp->regs = ioremap(p_reg_prop.phys_addr, p_reg_prop.reg_size);
+	mp->regs = ioremap(regs->phys_addr, regs->reg_size);
 	if (mp->regs == NULL)
 		goto fail;
 
@@ -384,13 +382,11 @@
 
 	fetch_decode_regs(mp);
 
-	mp->index = index;
-
 	list_add(&mp->list, &mctrl_list);
 
 	/* Report the device. */
-	printk(KERN_INFO "chmc%d: US3 memory controller at %p [%s]\n",
-	       mp->index,
+	printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n",
+	       dp->full_name,
 	       mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE"));
 
 	return 0;
@@ -404,34 +400,19 @@
 	return -1;
 }
 
-static int __init probe_for_string(char *name, int index)
-{
-	int node = prom_getchild(prom_root_node);
-
-	while ((node = prom_searchsiblings(node, name)) != 0) {
-		int ret = init_one_mctrl(node, index);
-
-		if (!ret)
-			index++;
-
-		node = prom_getsibling(node);
-		if (!node)
-			break;
-	}
-
-	return index;
-}
-
 static int __init chmc_init(void)
 {
-	int index;
+	struct device_node *dp;
 
 	/* This driver is only for cheetah platforms. */
 	if (tlb_type != cheetah && tlb_type != cheetah_plus)
 		return -ENODEV;
 
-	index = probe_for_string("memory-controller", 0);
-	index = probe_for_string("mc-us3", index);
+	for_each_node_by_name(dp, "memory-controller")
+		init_one_mctrl(dp);
+
+	for_each_node_by_name(dp, "mc-us3")
+		init_one_mctrl(dp);
 
 	return 0;
 }
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index 007e892..389301c 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -33,7 +33,7 @@
 extern void central_probe(void);
 
 u32 sun4v_vdev_devhandle;
-int sun4v_vdev_root;
+struct device_node *sun4v_vdev_root;
 
 struct vdev_intmap {
 	unsigned int phys;
@@ -50,102 +50,68 @@
 
 static struct vdev_intmap *vdev_intmap;
 static int vdev_num_intmap;
-static struct vdev_intmask vdev_intmask;
+static struct vdev_intmask *vdev_intmask;
 
 static void __init sun4v_virtual_device_probe(void)
 {
-	struct linux_prom64_registers regs;
-	struct vdev_intmap *ip;
-	int node, sz, err;
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+	struct device_node *dp;
+	int sz;
 
 	if (tlb_type != hypervisor)
 		return;
 
-	node = prom_getchild(prom_root_node);
-	node = prom_searchsiblings(node, "virtual-devices");
-	if (!node) {
+	dp = of_find_node_by_name(NULL, "virtual-devices");
+	if (!dp) {
 		prom_printf("SUN4V: Fatal error, no virtual-devices node.\n");
 		prom_halt();
 	}
 
-	sun4v_vdev_root = node;
+	sun4v_vdev_root = dp;
 
-	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
-	sun4v_vdev_devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff;
+	prop = of_find_property(dp, "reg", NULL);
+	regs = prop->value;
+	sun4v_vdev_devhandle = (regs[0].phys_addr >> 32UL) & 0x0fffffff;
 
-	sz = prom_getproplen(node, "interrupt-map");
-	if (sz <= 0) {
-		prom_printf("SUN4V: Error, no vdev interrupt-map.\n");
-		prom_halt();
-	}
+	prop = of_find_property(dp, "interrupt-map", &sz);
+	vdev_intmap = prop->value;
+	vdev_num_intmap = sz / sizeof(struct vdev_intmap);
 
-	if ((sz % sizeof(*ip)) != 0) {
-		prom_printf("SUN4V: Bogus interrupt-map property size %d\n",
-			    sz);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "interrupt-map-mask", NULL);
+	vdev_intmask = prop->value;
 
-	vdev_intmap = ip = alloc_bootmem_low_pages(sz);
-	if (!vdev_intmap) {
-		prom_printf("SUN4V: Error, cannot allocate vdev_intmap.\n");
-		prom_halt();
-	}
-
-	err = prom_getproperty(node, "interrupt-map", (char *) ip, sz);
-	if (err == -1) {
-		prom_printf("SUN4V: Fatal error, no vdev interrupt-map.\n");
-		prom_halt();
-	}
-	if (err != sz) {
-		prom_printf("SUN4V: Inconsistent interrupt-map size, "
-			    "proplen(%d) vs getprop(%d).\n", sz,err);
-		prom_halt();
-	}
-
-	vdev_num_intmap = err / sizeof(*ip);
-
-	err = prom_getproperty(node, "interrupt-map-mask",
-			       (char *) &vdev_intmask,
-			       sizeof(vdev_intmask));
-	if (err <= 0) {
-		prom_printf("SUN4V: Fatal error, no vdev "
-			    "interrupt-map-mask.\n");
-		prom_halt();
-	}
-	if (err % sizeof(vdev_intmask)) {
-		prom_printf("SUN4V: Bogus interrupt-map-mask "
-			    "property size %d\n", err);
-		prom_halt();
-	}
-
-	printk("SUN4V: virtual-devices devhandle[%x]\n",
-	       sun4v_vdev_devhandle);
+	printk("%s: Virtual Device Bus devhandle[%x]\n",
+	       dp->full_name, sun4v_vdev_devhandle);
 }
 
-unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
+unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node)
 {
+	struct property *prop;
 	unsigned int irq, reg;
-	int err, i;
+	int i;
 
-	err = prom_getproperty(dev_node, "interrupts",
-			       (char *) &irq, sizeof(irq));
-	if (err <= 0) {
+	prop = of_find_property(dev_node, "interrupts", NULL);
+	if (!prop) {
 		printk("VDEV: Cannot get \"interrupts\" "
-		       "property for OBP node %x\n", dev_node);
+		       "property for OBP node %s\n",
+		       dev_node->full_name);
 		return 0;
 	}
+	irq = *(unsigned int *) prop->value;
 
-	err = prom_getproperty(dev_node, "reg",
-			       (char *) &reg, sizeof(reg));
-	if (err <= 0) {
+	prop = of_find_property(dev_node, "reg", NULL);
+	if (!prop) {
 		printk("VDEV: Cannot get \"reg\" "
-		       "property for OBP node %x\n", dev_node);
+		       "property for OBP node %s\n",
+		       dev_node->full_name);
 		return 0;
 	}
+	reg = *(unsigned int *) prop->value;
 
 	for (i = 0; i < vdev_num_intmap; i++) {
-		if (vdev_intmap[i].phys == (reg & vdev_intmask.phys) &&
-		    vdev_intmap[i].irq == (irq & vdev_intmask.interrupt)) {
+		if (vdev_intmap[i].phys == (reg & vdev_intmask->phys) &&
+		    vdev_intmap[i].irq == (irq & vdev_intmask->interrupt)) {
 			irq = vdev_intmap[i].cinterrupt;
 			break;
 		}
@@ -153,11 +119,11 @@
 
 	if (i == vdev_num_intmap) {
 		printk("VDEV: No matching interrupt map entry "
-		       "for OBP node %x\n", dev_node);
+		       "for OBP node %s\n", dev_node->full_name);
 		return 0;
 	}
 
-	return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0);
+	return sun4v_build_irq(sun4v_vdev_devhandle, irq);
 }
 
 static const char *cpu_mid_prop(void)
@@ -167,38 +133,44 @@
 	return "portid";
 }
 
-static int get_cpu_mid(int prom_node)
+static int get_cpu_mid(struct device_node *dp)
 {
+	struct property *prop;
+
 	if (tlb_type == hypervisor) {
-		struct linux_prom64_registers reg;
+		struct linux_prom64_registers *reg;
+		int len;
 
-		if (prom_getproplen(prom_node, "cpuid") == 4)
-			return prom_getintdefault(prom_node, "cpuid", 0);
+		prop = of_find_property(dp, "cpuid", &len);
+		if (prop && len == 4)
+			return *(int *) prop->value;
 
-		prom_getproperty(prom_node, "reg", (char *) &reg, sizeof(reg));
-		return (reg.phys_addr >> 32) & 0x0fffffffUL;
+		prop = of_find_property(dp, "reg", NULL);
+		reg = prop->value;
+		return (reg[0].phys_addr >> 32) & 0x0fffffffUL;
 	} else {
 		const char *prop_name = cpu_mid_prop();
 
-		return prom_getintdefault(prom_node, prop_name, 0);
+		prop = of_find_property(dp, prop_name, NULL);
+		if (prop)
+			return *(int *) prop->value;
+		return 0;
 	}
 }
 
-static int check_cpu_node(int nd, int *cur_inst,
-			  int (*compare)(int, int, void *), void *compare_arg,
-			  int *prom_node, int *mid)
+static int check_cpu_node(struct device_node *dp, int *cur_inst,
+			  int (*compare)(struct device_node *, int, void *),
+			  void *compare_arg,
+			  struct device_node **dev_node, int *mid)
 {
-	char node_str[128];
-
-	prom_getstring(nd, "device_type", node_str, sizeof(node_str));
-	if (strcmp(node_str, "cpu"))
+	if (strcmp(dp->type, "cpu"))
 		return -ENODEV;
 
-	if (!compare(nd, *cur_inst, compare_arg)) {
-		if (prom_node)
-			*prom_node = nd;
+	if (!compare(dp, *cur_inst, compare_arg)) {
+		if (dev_node)
+			*dev_node = dp;
 		if (mid)
-			*mid = get_cpu_mid(nd);
+			*mid = get_cpu_mid(dp);
 		return 0;
 	}
 
@@ -207,25 +179,18 @@
 	return -ENODEV;
 }
 
-static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
-			 int *prom_node, int *mid)
+static int __cpu_find_by(int (*compare)(struct device_node *, int, void *),
+			 void *compare_arg,
+			 struct device_node **dev_node, int *mid)
 {
-	int nd, cur_inst, err;
+	struct device_node *dp;
+	int cur_inst;
 
-	nd = prom_root_node;
 	cur_inst = 0;
-
-	err = check_cpu_node(nd, &cur_inst,
-			     compare, compare_arg,
-			     prom_node, mid);
-	if (err == 0)
-		return 0;
-
-	nd = prom_getchild(nd);
-	while ((nd = prom_getsibling(nd)) != 0) {
-		err = check_cpu_node(nd, &cur_inst,
-				     compare, compare_arg,
-				     prom_node, mid);
+	for_each_node_by_type(dp, "cpu") {
+		int err = check_cpu_node(dp, &cur_inst,
+					 compare, compare_arg,
+					 dev_node, mid);
 		if (err == 0)
 			return 0;
 	}
@@ -233,7 +198,7 @@
 	return -ENODEV;
 }
 
-static int cpu_instance_compare(int nd, int instance, void *_arg)
+static int cpu_instance_compare(struct device_node *dp, int instance, void *_arg)
 {
 	int desired_instance = (int) (long) _arg;
 
@@ -242,27 +207,27 @@
 	return -ENODEV;
 }
 
-int cpu_find_by_instance(int instance, int *prom_node, int *mid)
+int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid)
 {
 	return __cpu_find_by(cpu_instance_compare, (void *)(long)instance,
-			     prom_node, mid);
+			     dev_node, mid);
 }
 
-static int cpu_mid_compare(int nd, int instance, void *_arg)
+static int cpu_mid_compare(struct device_node *dp, int instance, void *_arg)
 {
 	int desired_mid = (int) (long) _arg;
 	int this_mid;
 
-	this_mid = get_cpu_mid(nd);
+	this_mid = get_cpu_mid(dp);
 	if (this_mid == desired_mid)
 		return 0;
 	return -ENODEV;
 }
 
-int cpu_find_by_mid(int mid, int *prom_node)
+int cpu_find_by_mid(int mid, struct device_node **dev_node)
 {
 	return __cpu_find_by(cpu_mid_compare, (void *)(long)mid,
-			     prom_node, NULL);
+			     dev_node, NULL);
 }
 
 void __init device_scan(void)
@@ -274,50 +239,47 @@
 
 #ifndef CONFIG_SMP
 	{
-		int err, cpu_node, def;
+		struct device_node *dp;
+		int err, def;
 
-		err = cpu_find_by_instance(0, &cpu_node, NULL);
+		err = cpu_find_by_instance(0, &dp, NULL);
 		if (err) {
 			prom_printf("No cpu nodes, cannot continue\n");
 			prom_halt();
 		}
-		cpu_data(0).clock_tick = prom_getintdefault(cpu_node,
-							    "clock-frequency",
-							    0);
+		cpu_data(0).clock_tick =
+			of_getintprop_default(dp, "clock-frequency", 0);
 
 		def = ((tlb_type == hypervisor) ?
 		       (8 * 1024) :
 		       (16 * 1024));
-		cpu_data(0).dcache_size = prom_getintdefault(cpu_node,
-							     "dcache-size",
-							     def);
+		cpu_data(0).dcache_size = of_getintprop_default(dp,
+								"dcache-size",
+								def);
 
 		def = 32;
 		cpu_data(0).dcache_line_size =
-			prom_getintdefault(cpu_node, "dcache-line-size",
-					   def);
+			of_getintprop_default(dp, "dcache-line-size", def);
 
 		def = 16 * 1024;
-		cpu_data(0).icache_size = prom_getintdefault(cpu_node,
-							     "icache-size",
-							     def);
+		cpu_data(0).icache_size = of_getintprop_default(dp,
+								"icache-size",
+								def);
 
 		def = 32;
 		cpu_data(0).icache_line_size =
-			prom_getintdefault(cpu_node, "icache-line-size",
-					   def);
+			of_getintprop_default(dp, "icache-line-size", def);
 
 		def = ((tlb_type == hypervisor) ?
 		       (3 * 1024 * 1024) :
 		       (4 * 1024 * 1024));
-		cpu_data(0).ecache_size = prom_getintdefault(cpu_node,
-							     "ecache-size",
-							     def);
+		cpu_data(0).ecache_size = of_getintprop_default(dp,
+								"ecache-size",
+								def);
 
 		def = 64;
 		cpu_data(0).ecache_line_size =
-			prom_getintdefault(cpu_node, "ecache-line-size",
-					   def);
+			of_getintprop_default(dp, "ecache-line-size", def);
 		printk("CPU[0]: Caches "
 		       "D[sz(%d):line_sz(%d)] "
 		       "I[sz(%d):line_sz(%d)] "
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c
index c69504a..98e0a8c 100644
--- a/arch/sparc64/kernel/ebus.c
+++ b/arch/sparc64/kernel/ebus.c
@@ -269,10 +269,6 @@
 
 struct linux_ebus *ebus_chain = NULL;
 
-#ifdef CONFIG_SUN_AUXIO
-extern void auxio_probe(void);
-#endif
-
 static inline void *ebus_alloc(size_t size)
 {
 	void *mem;
@@ -283,77 +279,55 @@
 	return mem;
 }
 
-static void __init ebus_ranges_init(struct linux_ebus *ebus)
-{
-	int success;
-
-	ebus->num_ebus_ranges = 0;
-	success = prom_getproperty(ebus->prom_node, "ranges",
-				   (char *)ebus->ebus_ranges,
-				   sizeof(ebus->ebus_ranges));
-	if (success != -1)
-		ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
-}
-
-static void __init ebus_intmap_init(struct linux_ebus *ebus)
-{
-	int success;
-
-	ebus->num_ebus_intmap = 0;
-	success = prom_getproperty(ebus->prom_node, "interrupt-map",
-				   (char *)ebus->ebus_intmap,
-				   sizeof(ebus->ebus_intmap));
-	if (success == -1)
-		return;
-
-	ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
-
-	success = prom_getproperty(ebus->prom_node, "interrupt-map-mask",
-				   (char *)&ebus->ebus_intmask,
-				   sizeof(ebus->ebus_intmask));
-	if (success == -1) {
-		prom_printf("%s: can't get interrupt-map-mask\n", __FUNCTION__);
-		prom_halt();
-	}
-}
-
 int __init ebus_intmap_match(struct linux_ebus *ebus,
 			     struct linux_prom_registers *reg,
 			     int *interrupt)
 {
+	struct linux_prom_ebus_intmap *imap;
+	struct linux_prom_ebus_intmask *imask;
 	unsigned int hi, lo, irq;
-	int i;
+	int i, len, n_imap;
 
-	if (!ebus->num_ebus_intmap)
+	imap = of_get_property(ebus->prom_node, "interrupt-map", &len);
+	if (!imap)
+		return 0;
+	n_imap = len / sizeof(imap[0]);
+
+	imask = of_get_property(ebus->prom_node, "interrupt-map-mask", NULL);
+	if (!imask)
 		return 0;
 
-	hi = reg->which_io & ebus->ebus_intmask.phys_hi;
-	lo = reg->phys_addr & ebus->ebus_intmask.phys_lo;
-	irq = *interrupt & ebus->ebus_intmask.interrupt;
-	for (i = 0; i < ebus->num_ebus_intmap; i++) {
-		if ((ebus->ebus_intmap[i].phys_hi == hi) &&
-		    (ebus->ebus_intmap[i].phys_lo == lo) &&
-		    (ebus->ebus_intmap[i].interrupt == irq)) {
-			*interrupt = ebus->ebus_intmap[i].cinterrupt;
+	hi = reg->which_io & imask->phys_hi;
+	lo = reg->phys_addr & imask->phys_lo;
+	irq = *interrupt & imask->interrupt;
+	for (i = 0; i < n_imap; i++) {
+		if ((imap[i].phys_hi == hi) &&
+		    (imap[i].phys_lo == lo) &&
+		    (imap[i].interrupt == irq)) {
+			*interrupt = imap[i].cinterrupt;
 			return 0;
 		}
 	}
 	return -1;
 }
 
-void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
-			    struct linux_ebus_child *dev, int non_standard_regs)
+void __init fill_ebus_child(struct device_node *dp,
+			    struct linux_prom_registers *preg,
+			    struct linux_ebus_child *dev,
+			    int non_standard_regs)
 {
-	int regs[PROMREG_MAX];
-	int irqs[PROMREG_MAX];
+	int *regs;
+	int *irqs;
 	int i, len;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
-	printk(" (%s)", dev->prom_name);
+	dev->prom_node = dp;
+	printk(" (%s)", dp->name);
 
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
-	dev->num_addrs = len / sizeof(regs[0]);
+	regs = of_get_property(dp, "reg", &len);
+	if (!regs)
+		dev->num_addrs = 0;
+	else
+		dev->num_addrs = len / sizeof(regs[0]);
 
 	if (non_standard_regs) {
 		/* This is to handle reg properties which are not
@@ -370,21 +344,21 @@
 			int rnum = regs[i];
 			if (rnum >= dev->parent->num_addrs) {
 				prom_printf("UGH: property for %s was %d, need < %d\n",
-					    dev->prom_name, len, dev->parent->num_addrs);
-				panic(__FUNCTION__);
+					    dp->name, len, dev->parent->num_addrs);
+				prom_halt();
 			}
 			dev->resource[i].start = dev->parent->resource[i].start;
 			dev->resource[i].end = dev->parent->resource[i].end;
 			dev->resource[i].flags = IORESOURCE_MEM;
-			dev->resource[i].name = dev->prom_name;
+			dev->resource[i].name = dp->name;
 		}
 	}
 
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
-	if ((len == -1) || (len == 0)) {
+	irqs = of_get_property(dp, "interrupts", &len);
+	if (!irqs) {
 		dev->num_irqs = 0;
 		/*
 		 * Oh, well, some PROMs don't export interrupts
@@ -392,8 +366,8 @@
 		 *
 		 * Be smart about PS/2 keyboard and mouse.
 		 */
-		if (!strcmp(dev->parent->prom_name, "8042")) {
-			if (!strcmp(dev->prom_name, "kb_ps2")) {
+		if (!strcmp(dev->parent->prom_node->name, "8042")) {
+			if (!strcmp(dev->prom_node->name, "kb_ps2")) {
 				dev->num_irqs = 1;
 				dev->irqs[0] = dev->parent->irqs[0];
 			} else {
@@ -423,32 +397,32 @@
 
 static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
 {
-	if (!strcmp(dev->prom_name, "i2c") ||
-	    !strcmp(dev->prom_name, "SUNW,lombus"))
+	if (!strcmp(dev->prom_node->name, "i2c") ||
+	    !strcmp(dev->prom_node->name, "SUNW,lombus"))
 		return 1;
 	return 0;
 }
 
-void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
+void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev)
 {
-	struct linux_prom_registers regs[PROMREG_MAX];
+	struct linux_prom_registers *regs;
 	struct linux_ebus_child *child;
-	int irqs[PROMINTR_MAX];
+	int *irqs;
 	int i, n, len;
 
-	dev->prom_node = node;
-	prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
-	printk(" [%s", dev->prom_name);
+	dev->prom_node = dp;
 
-	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
-	if (len == -1) {
+	printk(" [%s", dp->name);
+
+	regs = of_get_property(dp, "reg", &len);
+	if (!regs) {
 		dev->num_addrs = 0;
 		goto probe_interrupts;
 	}
 
 	if (len % sizeof(struct linux_prom_registers)) {
 		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
-			    dev->prom_name, len,
+			    dev->prom_node->name, len,
 			    (int)sizeof(struct linux_prom_registers));
 		prom_halt();
 	}
@@ -466,7 +440,7 @@
 		dev->resource[i].end    =
 			(dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
 		dev->resource[i].flags  = IORESOURCE_MEM;
-		dev->resource[i].name   = dev->prom_name;
+		dev->resource[i].name   = dev->prom_node->name;
 		request_resource(&dev->bus->self->resource[n],
 				 &dev->resource[i]);
 	}
@@ -475,8 +449,8 @@
 	for (i = 0; i < PROMINTR_MAX; i++)
 		dev->irqs[i] = PCI_IRQ_NONE;
 
-	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
-	if ((len == -1) || (len == 0)) {
+	irqs = of_get_property(dp, "interrupts", &len);
+	if (!irqs) {
 		dev->num_irqs = 0;
 	} else {
 		dev->num_irqs = len / sizeof(irqs[0]);
@@ -497,7 +471,18 @@
 		}
 	}
 
-	if ((node = prom_getchild(node))) {
+	dev->ofdev.node = dp;
+	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;
+	dev->ofdev.dev.bus = &ebus_bus_type;
+	strcpy(dev->ofdev.dev.bus_id, dp->path_component_name);
+
+	/* Register with core */
+	if (of_device_register(&dev->ofdev) != 0)
+		printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+		       dev->ofdev.dev.bus_id);
+
+	dp = dp->child;
+	if (dp) {
 		printk(" ->");
 		dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
 
@@ -505,18 +490,18 @@
 		child->next = NULL;
 		child->parent = dev;
 		child->bus = dev->bus;
-		fill_ebus_child(node, &regs[0],
-				child, child_regs_nonstandard(dev));
+		fill_ebus_child(dp, regs, child,
+				child_regs_nonstandard(dev));
 
-		while ((node = prom_getsibling(node)) != 0) {
+		while ((dp = dp->sibling) != NULL) {
 			child->next = ebus_alloc(sizeof(struct linux_ebus_child));
 
 			child = child->next;
 			child->next = NULL;
 			child->parent = dev;
 			child->bus = dev->bus;
-			fill_ebus_child(node, &regs[0],
-					child, child_regs_nonstandard(dev));
+			fill_ebus_child(dp, regs, child,
+					child_regs_nonstandard(dev));
 		}
 	}
 	printk("]");
@@ -543,7 +528,8 @@
 	struct linux_ebus *ebus;
 	struct pci_dev *pdev;
 	struct pcidev_cookie *cookie;
-	int nd, ebusnd, is_rio;
+	struct device_node *dp;
+	int is_rio;
 	int num_ebus = 0;
 
 	pdev = find_next_ebus(NULL, &is_rio);
@@ -553,20 +539,22 @@
 	}
 
 	cookie = pdev->sysdata;
-	ebusnd = cookie->prom_node;
+	dp = cookie->prom_node;
 
 	ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
 	ebus->next = NULL;
 	ebus->is_rio = is_rio;
 
-	while (ebusnd) {
+	while (dp) {
+		struct device_node *child;
+
 		/* SUNW,pci-qfe uses four empty ebuses on it.
 		   I think we should not consider them here,
 		   as they have half of the properties this
 		   code expects and once we do PCI hot-plug,
 		   we'd have to tweak with the ebus_chain
 		   in the runtime after initialization. -jj */
-		if (!prom_getchild (ebusnd)) {
+		if (!dp->child) {
 			pdev = find_next_ebus(pdev, &is_rio);
 			if (!pdev) {
 				if (ebus == ebus_chain) {
@@ -578,22 +566,29 @@
 			}
 			ebus->is_rio = is_rio;
 			cookie = pdev->sysdata;
-			ebusnd = cookie->prom_node;
+			dp = cookie->prom_node;
 			continue;
 		}
 		printk("ebus%d:", num_ebus);
 
-		prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
 		ebus->index = num_ebus;
-		ebus->prom_node = ebusnd;
+		ebus->prom_node = dp;
 		ebus->self = pdev;
 		ebus->parent = pbm = cookie->pbm;
 
-		ebus_ranges_init(ebus);
-		ebus_intmap_init(ebus);
+		ebus->ofdev.node = dp;
+		ebus->ofdev.dev.parent = &pdev->dev;
+		ebus->ofdev.dev.bus = &ebus_bus_type;
+		strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name);
 
-		nd = prom_getchild(ebusnd);
-		if (!nd)
+		/* Register with core */
+		if (of_device_register(&ebus->ofdev) != 0)
+			printk(KERN_DEBUG "ebus: device registration error for %s!\n",
+			       ebus->ofdev.dev.bus_id);
+
+
+		child = dp->child;
+		if (!child)
 			goto next_ebus;
 
 		ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
@@ -602,16 +597,16 @@
 		dev->next = NULL;
 		dev->children = NULL;
 		dev->bus = ebus;
-		fill_ebus_device(nd, dev);
+		fill_ebus_device(child, dev);
 
-		while ((nd = prom_getsibling(nd)) != 0) {
+		while ((child = child->sibling) != NULL) {
 			dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
 
 			dev = dev->next;
 			dev->next = NULL;
 			dev->children = NULL;
 			dev->bus = ebus;
-			fill_ebus_device(nd, dev);
+			fill_ebus_device(child, dev);
 		}
 
 	next_ebus:
@@ -622,7 +617,7 @@
 			break;
 
 		cookie = pdev->sysdata;
-		ebusnd = cookie->prom_node;
+		dp = cookie->prom_node;
 
 		ebus->next = ebus_alloc(sizeof(struct linux_ebus));
 		ebus = ebus->next;
@@ -631,8 +626,4 @@
 		++num_ebus;
 	}
 	pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */
-
-#ifdef CONFIG_SUN_AUXIO
-	auxio_probe();
-#endif
 }
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index 6d0b3ed..be85ce2 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -22,6 +22,7 @@
 #include <asm/estate.h>
 #include <asm/auxio.h>
 #include <asm/sfafsr.h>
+#include <asm/pil.h>
 
 #define curptr      g6
 
@@ -431,20 +432,16 @@
 	membar		#Sync
 
 	sethi		%hi(ivector_table), %g2
-	sllx		%g3, 5, %g3
+	sllx		%g3, 3, %g3
 	or		%g2, %lo(ivector_table), %g2
 	add		%g2, %g3, %g3
-	ldub		[%g3 + 0x04], %g4	/* pil */
-	mov		1, %g2
-	sllx		%g2, %g4, %g2
-	sllx		%g4, 2, %g4
 
 	TRAP_LOAD_IRQ_WORK(%g6, %g1)
 
-	lduw		[%g6 + %g4], %g5	/* g5 = irq_work(cpu, pil) */
+	lduw		[%g6], %g5		/* g5 = irq_work(cpu) */
 	stw		%g5, [%g3 + 0x00]	/* bucket->irq_chain = g5 */
-	stw		%g3, [%g6 + %g4]	/* irq_work(cpu, pil) = bucket */
-	wr		%g2, 0x0, %set_softint
+	stw		%g3, [%g6]		/* irq_work(cpu) = bucket */
+	wr		%g0, 1 << PIL_DEVICE_IRQ, %set_softint
 	retry
 do_ivec_xcall:
 	mov		0x50, %g1
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 11e645c..cc89b06 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -22,6 +22,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/bootmem.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -33,6 +34,7 @@
 #include <asm/iommu.h>
 #include <asm/upa.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/timer.h>
 #include <asm/smp.h>
 #include <asm/starfire.h>
@@ -42,10 +44,6 @@
 #include <asm/auxio.h>
 #include <asm/head.h>
 
-#ifdef CONFIG_SMP
-static void distribute_irqs(void);
-#endif
-
 /* UPA nodes send interrupt packet to UltraSparc with first data reg
  * value low 5 (7 on Starfire) bits holding the IRQ identifier being
  * delivered.  We must translate this into a non-vector IRQ so we can
@@ -57,10 +55,29 @@
  * The IVEC handler does not need to act atomically, the PIL dispatch
  * code uses CAS to get an atomic snapshot of the list and clear it
  * at the same time.
+ *
+ * If you make changes to ino_bucket, please update hand coded assembler
+ * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S
  */
+struct ino_bucket {
+	/* Next handler in per-CPU IRQ worklist.  We know that
+	 * bucket pointers have the high 32-bits clear, so to
+	 * save space we only store the bits we need.
+	 */
+/*0x00*/unsigned int irq_chain;
 
+	/* Virtual interrupt number assigned to this INO.  */
+/*0x04*/unsigned int virt_irq;
+};
+
+#define NUM_IVECS	(IMAP_INR + 1)
 struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES)));
 
+#define __irq_ino(irq) \
+        (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0])
+#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq))
+#define __irq(bucket) ((unsigned int)(unsigned long)(bucket))
+
 /* This has to be in the main kernel image, it cannot be
  * turned into per-cpu data.  The reason is that the main
  * kernel image is locked into the TLB and this structure
@@ -68,71 +85,82 @@
  * access to this structure takes a TLB miss it could cause
  * the 5-level sparc v9 trap stack to overflow.
  */
-struct irq_work_struct {
-	unsigned int	irq_worklists[16];
-};
-struct irq_work_struct __irq_work[NR_CPUS];
-#define irq_work(__cpu, __pil)	&(__irq_work[(__cpu)].irq_worklists[(__pil)])
+#define irq_work(__cpu)	&(trap_block[(__cpu)].irq_worklist)
 
-static struct irqaction *irq_action[NR_IRQS+1];
+static unsigned int virt_to_real_irq_table[NR_IRQS];
+static unsigned char virt_irq_cur = 1;
 
-/* This only synchronizes entities which modify IRQ handler
- * state and some selected user-level spots that want to
- * read things in the table.  IRQ handler processing orders
- * its' accesses such that no locking is needed.
- */
-static DEFINE_SPINLOCK(irq_action_lock);
+static unsigned char virt_irq_alloc(unsigned int real_irq)
+{
+	unsigned char ent;
 
-static void register_irq_proc (unsigned int irq);
+	BUILD_BUG_ON(NR_IRQS >= 256);
+
+	ent = virt_irq_cur;
+	if (ent >= NR_IRQS) {
+		printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
+		return 0;
+	}
+
+	virt_irq_cur = ent + 1;
+	virt_to_real_irq_table[ent] = real_irq;
+
+	return ent;
+}
+
+#if 0 /* Currently unused. */
+static unsigned char real_to_virt_irq(unsigned int real_irq)
+{
+	struct ino_bucket *bucket = __bucket(real_irq);
+
+	return bucket->virt_irq;
+}
+#endif
+
+static unsigned int virt_to_real_irq(unsigned char virt_irq)
+{
+	return virt_to_real_irq_table[virt_irq];
+}
 
 /*
- * Upper 2b of irqaction->flags holds the ino.
- * irqaction->mask holds the smp affinity information.
+ * /proc/interrupts printing:
  */
-#define put_ino_in_irqaction(action, irq) \
-	action->flags &= 0xffffffffffffUL; \
-	if (__bucket(irq) == &pil0_dummy_bucket) \
-		action->flags |= 0xdeadUL << 48;  \
-	else \
-		action->flags |= __irq_ino(irq) << 48;
-#define get_ino_in_irqaction(action)	(action->flags >> 48)
-
-#define put_smpaff_in_irqaction(action, smpaff)	(action)->mask = (smpaff)
-#define get_smpaff_in_irqaction(action) 	((action)->mask)
 
 int show_interrupts(struct seq_file *p, void *v)
 {
+	int i = *(loff_t *) v, j;
+	struct irqaction * action;
 	unsigned long flags;
-	int i = *(loff_t *) v;
-	struct irqaction *action;
-#ifdef CONFIG_SMP
-	int j;
-#endif
 
-	spin_lock_irqsave(&irq_action_lock, flags);
-	if (i <= NR_IRQS) {
-		if (!(action = *(i + irq_action)))
-			goto out_unlock;
-		seq_printf(p, "%3d: ", i);
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for_each_online_cpu(j)
+			seq_printf(p, "CPU%d       ",j);
+		seq_putc(p, '\n');
+	}
+
+	if (i < NR_IRQS) {
+		spin_lock_irqsave(&irq_desc[i].lock, flags);
+		action = irq_desc[i].action;
+		if (!action)
+			goto skip;
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for_each_online_cpu(j) {
-			seq_printf(p, "%10u ",
-				   kstat_cpu(j).irqs[i]);
-		}
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
-		seq_printf(p, " %s:%lx", action->name,
-			   get_ino_in_irqaction(action));
-		for (action = action->next; action; action = action->next) {
-			seq_printf(p, ", %s:%lx", action->name,
-				   get_ino_in_irqaction(action));
-		}
-		seq_putc(p, '\n');
-	}
-out_unlock:
-	spin_unlock_irqrestore(&irq_action_lock, flags);
+		seq_printf(p, " %9s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
+		for (action=action->next; action; action = action->next)
+			seq_printf(p, ", %s", action->name);
+
+		seq_putc(p, '\n');
+skip:
+		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+	}
 	return 0;
 }
 
@@ -173,27 +201,124 @@
 	return tid;
 }
 
-/* Now these are always passed a true fully specified sun4u INO. */
-void enable_irq(unsigned int irq)
+struct irq_handler_data {
+	unsigned long	iclr;
+	unsigned long	imap;
+
+	void		(*pre_handler)(unsigned int, void *, void *);
+	void		*pre_handler_arg1;
+	void		*pre_handler_arg2;
+};
+
+static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq)
 {
-	struct ino_bucket *bucket = __bucket(irq);
-	unsigned long imap, cpuid;
+	unsigned int real_irq = virt_to_real_irq(virt_irq);
+	struct ino_bucket *bucket = NULL;
 
-	imap = bucket->imap;
-	if (imap == 0UL)
-		return;
+	if (likely(real_irq))
+		bucket = __bucket(real_irq);
 
-	preempt_disable();
+	return bucket;
+}
 
-	/* This gets the physical processor ID, even on uniprocessor,
-	 * so we can always program the interrupt target correctly.
-	 */
-	cpuid = real_hard_smp_processor_id();
+#ifdef CONFIG_SMP
+static int irq_choose_cpu(unsigned int virt_irq)
+{
+	cpumask_t mask = irq_affinity[virt_irq];
+	int cpuid;
 
-	if (tlb_type == hypervisor) {
-		unsigned int ino = __irq_ino(irq);
+	if (cpus_equal(mask, CPU_MASK_ALL)) {
+		static int irq_rover;
+		static DEFINE_SPINLOCK(irq_rover_lock);
+		unsigned long flags;
+
+		/* Round-robin distribution... */
+	do_round_robin:
+		spin_lock_irqsave(&irq_rover_lock, flags);
+
+		while (!cpu_online(irq_rover)) {
+			if (++irq_rover >= NR_CPUS)
+				irq_rover = 0;
+		}
+		cpuid = irq_rover;
+		do {
+			if (++irq_rover >= NR_CPUS)
+				irq_rover = 0;
+		} while (!cpu_online(irq_rover));
+
+		spin_unlock_irqrestore(&irq_rover_lock, flags);
+	} else {
+		cpumask_t tmp;
+
+		cpus_and(tmp, cpu_online_map, mask);
+
+		if (cpus_empty(tmp))
+			goto do_round_robin;
+
+		cpuid = first_cpu(tmp);
+	}
+
+	return cpuid;
+}
+#else
+static int irq_choose_cpu(unsigned int virt_irq)
+{
+	return real_hard_smp_processor_id();
+}
+#endif
+
+static void sun4u_irq_enable(unsigned int virt_irq)
+{
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
+
+	if (likely(data)) {
+		unsigned long cpuid, imap;
+		unsigned int tid;
+
+		cpuid = irq_choose_cpu(virt_irq);
+		imap = data->imap;
+
+		tid = sun4u_compute_tid(imap, cpuid);
+
+		upa_writel(tid | IMAP_VALID, imap);
+	}
+}
+
+static void sun4u_irq_disable(unsigned int virt_irq)
+{
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
+
+	if (likely(data)) {
+		unsigned long imap = data->imap;
+		u32 tmp = upa_readl(imap);
+
+		tmp &= ~IMAP_VALID;
+		upa_writel(tmp, imap);
+	}
+}
+
+static void sun4u_irq_end(unsigned int virt_irq)
+{
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
+
+	if (likely(data))
+		upa_writel(ICLR_IDLE, data->iclr);
+}
+
+static void sun4v_irq_enable(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		unsigned long cpuid;
 		int err;
 
+		cpuid = irq_choose_cpu(virt_irq);
+
 		err = sun4v_intr_settarget(ino, cpuid);
 		if (err != HV_EOK)
 			printk("sun4v_intr_settarget(%x,%lu): err(%d)\n",
@@ -202,666 +327,242 @@
 		if (err != HV_EOK)
 			printk("sun4v_intr_setenabled(%x): err(%d)\n",
 			       ino, err);
-	} else {
-		unsigned int tid = sun4u_compute_tid(imap, cpuid);
-
-		/* NOTE NOTE NOTE, IGN and INO are read-only, IGN is a product
-		 * of this SYSIO's preconfigured IGN in the SYSIO Control
-		 * Register, the hardware just mirrors that value here.
-		 * However for Graphics and UPA Slave devices the full
-		 * IMAP_INR field can be set by the programmer here.
-		 *
-		 * Things like FFB can now be handled via the new IRQ
-		 * mechanism.
-		 */
-		upa_writel(tid | IMAP_VALID, imap);
 	}
-
-	preempt_enable();
 }
 
-/* This now gets passed true ino's as well. */
-void disable_irq(unsigned int irq)
+static void sun4v_irq_disable(unsigned int virt_irq)
 {
-	struct ino_bucket *bucket = __bucket(irq);
-	unsigned long imap;
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
 
-	imap = bucket->imap;
-	if (imap != 0UL) {
-		if (tlb_type == hypervisor) {
-			unsigned int ino = __irq_ino(irq);
-			int err;
+	if (likely(bucket)) {
+		int err;
 
-			err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
-			if (err != HV_EOK)
-				printk("sun4v_intr_setenabled(%x): "
-				       "err(%d)\n", ino, err);
-		} else {
-			u32 tmp;
-
-			/* NOTE: We do not want to futz with the IRQ clear registers
-			 *       and move the state to IDLE, the SCSI code does call
-			 *       disable_irq() to assure atomicity in the queue cmd
-			 *       SCSI adapter driver code.  Thus we'd lose interrupts.
-			 */
-			tmp = upa_readl(imap);
-			tmp &= ~IMAP_VALID;
-			upa_writel(tmp, imap);
-		}
+		err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
+		if (err != HV_EOK)
+			printk("sun4v_intr_setenabled(%x): "
+			       "err(%d)\n", ino, err);
 	}
 }
 
-/* The timer is the one "weird" interrupt which is generated by
- * the CPU %tick register and not by some normal vectored interrupt
- * source.  To handle this special case, we use this dummy INO bucket.
- */
-static struct irq_desc pil0_dummy_desc;
-static struct ino_bucket pil0_dummy_bucket = {
-	.irq_info	=	&pil0_dummy_desc,
+static void sun4v_irq_end(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = bucket - &ivector_table[0];
+
+	if (likely(bucket)) {
+		int err;
+
+		err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
+		if (err != HV_EOK)
+			printk("sun4v_intr_setstate(%x): "
+			       "err(%d)\n", ino, err);
+	}
+}
+
+static void run_pre_handler(unsigned int virt_irq)
+{
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
+
+	if (likely(data->pre_handler)) {
+		data->pre_handler(__irq_ino(__irq(bucket)),
+				  data->pre_handler_arg1,
+				  data->pre_handler_arg2);
+	}
+}
+
+static struct hw_interrupt_type sun4u_irq = {
+	.typename	= "sun4u",
+	.enable		= sun4u_irq_enable,
+	.disable	= sun4u_irq_disable,
+	.end		= sun4u_irq_end,
 };
 
-static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup,
-			    unsigned long iclr, unsigned long imap,
-			    struct ino_bucket *bucket)
+static struct hw_interrupt_type sun4u_irq_ack = {
+	.typename	= "sun4u+ack",
+	.enable		= sun4u_irq_enable,
+	.disable	= sun4u_irq_disable,
+	.ack		= run_pre_handler,
+	.end		= sun4u_irq_end,
+};
+
+static struct hw_interrupt_type sun4v_irq = {
+	.typename	= "sun4v",
+	.enable		= sun4v_irq_enable,
+	.disable	= sun4v_irq_disable,
+	.end		= sun4v_irq_end,
+};
+
+static struct hw_interrupt_type sun4v_irq_ack = {
+	.typename	= "sun4v+ack",
+	.enable		= sun4v_irq_enable,
+	.disable	= sun4v_irq_disable,
+	.ack		= run_pre_handler,
+	.end		= sun4v_irq_end,
+};
+
+void irq_install_pre_handler(int virt_irq,
+			     void (*func)(unsigned int, void *, void *),
+			     void *arg1, void *arg2)
 {
-	prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> "
-		    "(%d:%d:%016lx:%016lx), halting...\n",
-		    ino, bucket->pil, bucket->iclr, bucket->imap,
-		    pil, inofixup, iclr, imap);
-	prom_halt();
+	irq_desc_t *desc = irq_desc + virt_irq;
+	struct irq_handler_data *data = desc->handler_data;
+
+	data->pre_handler = func;
+	data->pre_handler_arg1 = arg1;
+	data->pre_handler_arg2 = arg2;
+
+	desc->handler = (desc->handler == &sun4u_irq ?
+			 &sun4u_irq_ack : &sun4v_irq_ack);
 }
 
-unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap)
+unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
 {
 	struct ino_bucket *bucket;
+	struct irq_handler_data *data;
+	irq_desc_t *desc;
 	int ino;
 
-	if (pil == 0) {
-		if (iclr != 0UL || imap != 0UL) {
-			prom_printf("Invalid dummy bucket for PIL0 (%lx:%lx)\n",
-				    iclr, imap);
-			prom_halt();
-		}
-		return __irq(&pil0_dummy_bucket);
-	}
-
 	BUG_ON(tlb_type == hypervisor);
 
-	/* RULE: Both must be specified in all other cases. */
-	if (iclr == 0UL || imap == 0UL) {
-		prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
-			    pil, inofixup, iclr, imap);
-		prom_halt();
-	}
-	
 	ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
-	if (ino > NUM_IVECS) {
-		prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
-			    ino, pil, inofixup, iclr, imap);
-		prom_halt();
-	}
-
 	bucket = &ivector_table[ino];
-	if (bucket->flags & IBF_ACTIVE)
-		build_irq_error("IRQ: Trying to build active INO bucket.\n",
-				ino, pil, inofixup, iclr, imap, bucket);
-
-	if (bucket->irq_info) {
-		if (bucket->imap != imap || bucket->iclr != iclr)
-			build_irq_error("IRQ: Trying to reinit INO bucket.\n",
-					ino, pil, inofixup, iclr, imap, bucket);
-
-		goto out;
+	if (!bucket->virt_irq) {
+		bucket->virt_irq = virt_irq_alloc(__irq(bucket));
+		irq_desc[bucket->virt_irq].handler = &sun4u_irq;
 	}
 
-	bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
-	if (!bucket->irq_info) {
-		prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
+	desc = irq_desc + bucket->virt_irq;
+	if (unlikely(desc->handler_data))
+		goto out;
+
+	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!data)) {
+		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
 		prom_halt();
 	}
+	desc->handler_data = data;
 
-	/* Ok, looks good, set it up.  Don't touch the irq_chain or
-	 * the pending flag.
-	 */
-	bucket->imap  = imap;
-	bucket->iclr  = iclr;
-	bucket->pil   = pil;
-	bucket->flags = 0;
+	data->imap  = imap;
+	data->iclr  = iclr;
 
 out:
-	return __irq(bucket);
+	return bucket->virt_irq;
 }
 
-unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags)
+unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
 {
 	struct ino_bucket *bucket;
+	struct irq_handler_data *data;
 	unsigned long sysino;
+	irq_desc_t *desc;
+
+	BUG_ON(tlb_type != hypervisor);
 
 	sysino = sun4v_devino_to_sysino(devhandle, devino);
-
 	bucket = &ivector_table[sysino];
+	if (!bucket->virt_irq) {
+		bucket->virt_irq = virt_irq_alloc(__irq(bucket));
+		irq_desc[bucket->virt_irq].handler = &sun4v_irq;
+	}
+
+	desc = irq_desc + bucket->virt_irq;
+	if (unlikely(desc->handler_data))
+		goto out;
+
+	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!data)) {
+		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
+		prom_halt();
+	}
+	desc->handler_data = data;
 
 	/* Catch accidental accesses to these things.  IMAP/ICLR handling
 	 * is done by hypervisor calls on sun4v platforms, not by direct
 	 * register accesses.
-	 *
-	 * But we need to make them look unique for the disable_irq() logic
-	 * in free_irq().
 	 */
-	bucket->imap = ~0UL - sysino;
-	bucket->iclr = ~0UL - sysino;
+	data->imap = ~0UL;
+	data->iclr = ~0UL;
 
-	bucket->pil = pil;
-	bucket->flags = flags;
-
-	bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
-	if (!bucket->irq_info) {
-		prom_printf("IRQ: Error, kmalloc(irq_desc) failed.\n");
-		prom_halt();
-	}
-
-	return __irq(bucket);
+out:
+	return bucket->virt_irq;
 }
 
-static void atomic_bucket_insert(struct ino_bucket *bucket)
+void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq)
 {
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
 	unsigned long pstate;
 	unsigned int *ent;
 
 	__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
 	__asm__ __volatile__("wrpr %0, %1, %%pstate"
 			     : : "r" (pstate), "i" (PSTATE_IE));
-	ent = irq_work(smp_processor_id(), bucket->pil);
+	ent = irq_work(smp_processor_id());
 	bucket->irq_chain = *ent;
 	*ent = __irq(bucket);
+	set_softint(1 << PIL_DEVICE_IRQ);
 	__asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate));
 }
 
-static int check_irq_sharing(int pil, unsigned long irqflags)
+void ack_bad_irq(unsigned int virt_irq)
 {
-	struct irqaction *action, *tmp;
+	struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq);
+	unsigned int ino = 0xdeadbeef;
 
-	action = *(irq_action + pil);
-	if (action) {
-		if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
-			for (tmp = action; tmp->next; tmp = tmp->next)
-				;
-		} else {
-			return -EBUSY;
-		}
-	}
-	return 0;
+	if (bucket)
+		ino = bucket - &ivector_table[0];
+
+	printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n",
+	       ino, virt_irq);
 }
 
-static void append_irq_action(int pil, struct irqaction *action)
-{
-	struct irqaction **pp = irq_action + pil;
+#ifndef CONFIG_SMP
+extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
 
-	while (*pp)
-		pp = &((*pp)->next);
-	*pp = action;
+void timer_irq(int irq, struct pt_regs *regs)
+{
+	unsigned long clr_mask = 1 << irq;
+	unsigned long tick_mask = tick_ops->softint_mask;
+
+	if (get_softint() & tick_mask) {
+		irq = 0;
+		clr_mask = tick_mask;
+	}
+	clear_softint(clr_mask);
+
+	irq_enter();
+
+	kstat_this_cpu.irqs[0]++;
+	timer_interrupt(irq, NULL, regs);
+
+	irq_exit();
 }
-
-static struct irqaction *get_action_slot(struct ino_bucket *bucket)
-{
-	struct irq_desc *desc = bucket->irq_info;
-	int max_irq, i;
-
-	max_irq = 1;
-	if (bucket->flags & IBF_PCI)
-		max_irq = MAX_IRQ_DESC_ACTION;
-	for (i = 0; i < max_irq; i++) {
-		struct irqaction *p = &desc->action[i];
-		u32 mask = (1 << i);
-
-		if (desc->action_active_mask & mask)
-			continue;
-
-		desc->action_active_mask |= mask;
-		return p;
-	}
-	return NULL;
-}
-
-int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, const char *name, void *dev_id)
-{
-	struct irqaction *action;
-	struct ino_bucket *bucket = __bucket(irq);
-	unsigned long flags;
-	int pending = 0;
-
-	if (unlikely(!handler))
-		return -EINVAL;
-
-	if (unlikely(!bucket->irq_info))
-		return -ENODEV;
-
-	if ((bucket != &pil0_dummy_bucket) && (irqflags & SA_SAMPLE_RANDOM)) {
-		/*
-	 	 * This function might sleep, we want to call it first,
-	 	 * outside of the atomic block. In SA_STATIC_ALLOC case,
-		 * random driver's kmalloc will fail, but it is safe.
-		 * If already initialized, random driver will not reinit.
-	 	 * Yes, this might clear the entropy pool if the wrong
-	 	 * driver is attempted to be loaded, without actually
-	 	 * installing a new handler, but is this really a problem,
-	 	 * only the sysadmin is able to do this.
-	 	 */
-		rand_initialize_irq(irq);
-	}
-
-	spin_lock_irqsave(&irq_action_lock, flags);
-
-	if (check_irq_sharing(bucket->pil, irqflags)) {
-		spin_unlock_irqrestore(&irq_action_lock, flags);
-		return -EBUSY;
-	}
-
-	action = get_action_slot(bucket);
-	if (!action) { 
-		spin_unlock_irqrestore(&irq_action_lock, flags);
-		return -ENOMEM;
-	}
-
-	bucket->flags |= IBF_ACTIVE;
-	pending = 0;
-	if (bucket != &pil0_dummy_bucket) {
-		pending = bucket->pending;
-		if (pending)
-			bucket->pending = 0;
-	}
-
-	action->handler = handler;
-	action->flags = irqflags;
-	action->name = name;
-	action->next = NULL;
-	action->dev_id = dev_id;
-	put_ino_in_irqaction(action, irq);
-	put_smpaff_in_irqaction(action, CPU_MASK_NONE);
-
-	append_irq_action(bucket->pil, action);
-
-	enable_irq(irq);
-
-	/* We ate the IVEC already, this makes sure it does not get lost. */
-	if (pending) {
-		atomic_bucket_insert(bucket);
-		set_softint(1 << bucket->pil);
-	}
-
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-
-	if (bucket != &pil0_dummy_bucket)
-		register_irq_proc(__irq_ino(irq));
-
-#ifdef CONFIG_SMP
-	distribute_irqs();
 #endif
-	return 0;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id)
-{
-	struct ino_bucket *bucket = __bucket(irq);
-	struct irqaction *action, **pp;
-
-	pp = irq_action + bucket->pil;
-	action = *pp;
-	if (unlikely(!action))
-		return NULL;
-
-	if (unlikely(!action->handler)) {
-		printk("Freeing free IRQ %d\n", bucket->pil);
-		return NULL;
-	}
-
-	while (action && action->dev_id != dev_id) {
-		pp = &action->next;
-		action = *pp;
-	}
-
-	if (likely(action))
-		*pp = action->next;
-
-	return action;
-}
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	struct irqaction *action;
-	struct ino_bucket *bucket;
-	unsigned long flags;
-
-	spin_lock_irqsave(&irq_action_lock, flags);
-
-	action = unlink_irq_action(irq, dev_id);
-
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-
-	if (unlikely(!action))
-		return;
-
-	synchronize_irq(irq);
-
-	spin_lock_irqsave(&irq_action_lock, flags);
-
-	bucket = __bucket(irq);
-	if (bucket != &pil0_dummy_bucket) {
-		struct irq_desc *desc = bucket->irq_info;
-		int ent, i;
-
-		for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) {
-			struct irqaction *p = &desc->action[i];
-
-			if (p == action) {
-				desc->action_active_mask &= ~(1 << i);
-				break;
-			}
-		}
-
-		if (!desc->action_active_mask) {
-			unsigned long imap = bucket->imap;
-
-			/* This unique interrupt source is now inactive. */
-			bucket->flags &= ~IBF_ACTIVE;
-
-			/* See if any other buckets share this bucket's IMAP
-			 * and are still active.
-			 */
-			for (ent = 0; ent < NUM_IVECS; ent++) {
-				struct ino_bucket *bp = &ivector_table[ent];
-				if (bp != bucket	&&
-				    bp->imap == imap	&&
-				    (bp->flags & IBF_ACTIVE) != 0)
-					break;
-			}
-
-			/* Only disable when no other sub-irq levels of
-			 * the same IMAP are active.
-			 */
-			if (ent == NUM_IVECS)
-				disable_irq(irq);
-		}
-	}
-
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-}
-
-EXPORT_SYMBOL(free_irq);
-
-#ifdef CONFIG_SMP
-void synchronize_irq(unsigned int irq)
-{
-	struct ino_bucket *bucket = __bucket(irq);
-
-#if 0
-	/* The following is how I wish I could implement this.
-	 * Unfortunately the ICLR registers are read-only, you can
-	 * only write ICLR_foo values to them.  To get the current
-	 * IRQ status you would need to get at the IRQ diag registers
-	 * in the PCI/SBUS controller and the layout of those vary
-	 * from one controller to the next, sigh... -DaveM
-	 */
-	unsigned long iclr = bucket->iclr;
-
-	while (1) {
-		u32 tmp = upa_readl(iclr);
-		
-		if (tmp == ICLR_TRANSMIT ||
-		    tmp == ICLR_PENDING) {
-			cpu_relax();
-			continue;
-		}
-		break;
-	}
-#else
-	/* So we have to do this with a INPROGRESS bit just like x86.  */
-	while (bucket->flags & IBF_INPROGRESS)
-		cpu_relax();
-#endif
-}
-#endif /* CONFIG_SMP */
-
-static void process_bucket(int irq, struct ino_bucket *bp, struct pt_regs *regs)
-{
-	struct irq_desc *desc = bp->irq_info;
-	unsigned char flags = bp->flags;
-	u32 action_mask, i;
-	int random;
-
-	bp->flags |= IBF_INPROGRESS;
-
-	if (unlikely(!(flags & IBF_ACTIVE))) {
-		bp->pending = 1;
-		goto out;
-	}
-
-	if (desc->pre_handler)
-		desc->pre_handler(bp,
-				  desc->pre_handler_arg1,
-				  desc->pre_handler_arg2);
-
-	action_mask = desc->action_active_mask;
-	random = 0;
-	for (i = 0; i < MAX_IRQ_DESC_ACTION; i++) {
-		struct irqaction *p = &desc->action[i];
-		u32 mask = (1 << i);
-
-		if (!(action_mask & mask))
-			continue;
-
-		action_mask &= ~mask;
-
-		if (p->handler(__irq(bp), p->dev_id, regs) == IRQ_HANDLED)
-			random |= p->flags;
-
-		if (!action_mask)
-			break;
-	}
-	if (bp->pil != 0) {
-		if (tlb_type == hypervisor) {
-			unsigned int ino = __irq_ino(bp);
-			int err;
-
-			err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
-			if (err != HV_EOK)
-				printk("sun4v_intr_setstate(%x): "
-				       "err(%d)\n", ino, err);
-		} else {
-			upa_writel(ICLR_IDLE, bp->iclr);
-		}
-
-		/* Test and add entropy */
-		if (random & SA_SAMPLE_RANDOM)
-			add_interrupt_randomness(irq);
-	}
-out:
-	bp->flags &= ~IBF_INPROGRESS;
-}
 
 void handler_irq(int irq, struct pt_regs *regs)
 {
-	struct ino_bucket *bp;
-	int cpu = smp_processor_id();
+	struct ino_bucket *bucket;
 
-#ifndef CONFIG_SMP
-	/*
-	 * Check for TICK_INT on level 14 softint.
-	 */
-	{
-		unsigned long clr_mask = 1 << irq;
-		unsigned long tick_mask = tick_ops->softint_mask;
-
-		if ((irq == 14) && (get_softint() & tick_mask)) {
-			irq = 0;
-			clr_mask = tick_mask;
-		}
-		clear_softint(clr_mask);
-	}
-#else
 	clear_softint(1 << irq);
-#endif
 
 	irq_enter();
-	kstat_this_cpu.irqs[irq]++;
 
 	/* Sliiiick... */
-#ifndef CONFIG_SMP
-	bp = ((irq != 0) ?
-	      __bucket(xchg32(irq_work(cpu, irq), 0)) :
-	      &pil0_dummy_bucket);
-#else
-	bp = __bucket(xchg32(irq_work(cpu, irq), 0));
-#endif
-	while (bp) {
-		struct ino_bucket *nbp = __bucket(bp->irq_chain);
+	bucket = __bucket(xchg32(irq_work(smp_processor_id()), 0));
+	while (bucket) {
+		struct ino_bucket *next = __bucket(bucket->irq_chain);
 
-		bp->irq_chain = 0;
-		process_bucket(irq, bp, regs);
-		bp = nbp;
+		bucket->irq_chain = 0;
+		__do_IRQ(bucket->virt_irq, regs);
+
+		bucket = next;
 	}
+
 	irq_exit();
 }
 
-#ifdef CONFIG_BLK_DEV_FD
-extern irqreturn_t floppy_interrupt(int, void *, struct pt_regs *);
-
-/* XXX No easy way to include asm/floppy.h XXX */
-extern unsigned char *pdma_vaddr;
-extern unsigned long pdma_size;
-extern volatile int doing_pdma;
-extern unsigned long fdc_status;
-
-irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
-{
-	if (likely(doing_pdma)) {
-		void __iomem *stat = (void __iomem *) fdc_status;
-		unsigned char *vaddr = pdma_vaddr;
-		unsigned long size = pdma_size;
-		u8 val;
-
-		while (size) {
-			val = readb(stat);
-			if (unlikely(!(val & 0x80))) {
-				pdma_vaddr = vaddr;
-				pdma_size = size;
-				return IRQ_HANDLED;
-			}
-			if (unlikely(!(val & 0x20))) {
-				pdma_vaddr = vaddr;
-				pdma_size = size;
-				doing_pdma = 0;
-				goto main_interrupt;
-			}
-			if (val & 0x40) {
-				/* read */
-				*vaddr++ = readb(stat + 1);
-			} else {
-				unsigned char data = *vaddr++;
-
-				/* write */
-				writeb(data, stat + 1);
-			}
-			size--;
-		}
-
-		pdma_vaddr = vaddr;
-		pdma_size = size;
-
-		/* Send Terminal Count pulse to floppy controller. */
-		val = readb(auxio_register);
-		val |= AUXIO_AUX1_FTCNT;
-		writeb(val, auxio_register);
-		val &= ~AUXIO_AUX1_FTCNT;
-		writeb(val, auxio_register);
-
-		doing_pdma = 0;
-	}
-
-main_interrupt:
-	return floppy_interrupt(irq, dev_cookie, regs);
-}
-EXPORT_SYMBOL(sparc_floppy_irq);
-#endif
-
-/* We really don't need these at all on the Sparc.  We only have
- * stubs here because they are exported to modules.
- */
-unsigned long probe_irq_on(void)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off(unsigned long mask)
-{
-	return 0;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-#ifdef CONFIG_SMP
-static int retarget_one_irq(struct irqaction *p, int goal_cpu)
-{
-	struct ino_bucket *bucket = get_ino_in_irqaction(p) + ivector_table;
-
-	while (!cpu_online(goal_cpu)) {
-		if (++goal_cpu >= NR_CPUS)
-			goal_cpu = 0;
-	}
-
-	if (tlb_type == hypervisor) {
-		unsigned int ino = __irq_ino(bucket);
-
-		sun4v_intr_settarget(ino, goal_cpu);
-		sun4v_intr_setenabled(ino, HV_INTR_ENABLED);
-	} else {
-		unsigned long imap = bucket->imap;
-		unsigned int tid = sun4u_compute_tid(imap, goal_cpu);
-
-		upa_writel(tid | IMAP_VALID, imap);
-	}
-
-	do {
-		if (++goal_cpu >= NR_CPUS)
-			goal_cpu = 0;
-	} while (!cpu_online(goal_cpu));
-
-	return goal_cpu;
-}
-
-/* Called from request_irq. */
-static void distribute_irqs(void)
-{
-	unsigned long flags;
-	int cpu, level;
-
-	spin_lock_irqsave(&irq_action_lock, flags);
-	cpu = 0;
-
-	/*
-	 * Skip the timer at [0], and very rare error/power intrs at [15].
-	 * Also level [12], it causes problems on Ex000 systems.
-	 */
-	for (level = 1; level < NR_IRQS; level++) {
-		struct irqaction *p = irq_action[level];
-
-		if (level == 12)
-			continue;
-
-		while(p) {
-			cpu = retarget_one_irq(p, cpu);
-			p = p->next;
-		}
-	}
-	spin_unlock_irqrestore(&irq_action_lock, flags);
-}
-#endif
-
 struct sun5_timer {
 	u64	count0;
 	u64	limit0;
@@ -874,23 +575,29 @@
 
 static void map_prom_timers(void)
 {
-	unsigned int addr[3];
-	int tnode, err;
+	struct device_node *dp;
+	unsigned int *addr;
 
 	/* PROM timer node hangs out in the top level of device siblings... */
-	tnode = prom_finddevice("/counter-timer");
+	dp = of_find_node_by_path("/");
+	dp = dp->child;
+	while (dp) {
+		if (!strcmp(dp->name, "counter-timer"))
+			break;
+		dp = dp->sibling;
+	}
 
 	/* Assume if node is not present, PROM uses different tick mechanism
 	 * which we should not care about.
 	 */
-	if (tnode == 0 || tnode == -1) {
+	if (!dp) {
 		prom_timers = (struct sun5_timer *) 0;
 		return;
 	}
 
 	/* If PROM is really using this, it must be mapped by him. */
-	err = prom_getproperty(tnode, "address", (char *)addr, sizeof(addr));
-	if (err == -1) {
+	addr = of_get_property(dp, "address", NULL);
+	if (!addr) {
 		prom_printf("PROM does not have timer mapped, trying to continue.\n");
 		prom_timers = (struct sun5_timer *) 0;
 		return;
@@ -929,7 +636,7 @@
 {
 	int cpu = hard_smp_processor_id();
 
-	memset(__irq_work + cpu, 0, sizeof(struct irq_work_struct));
+	trap_block[cpu].irq_worklist = 0;
 }
 
 static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type)
@@ -1037,6 +744,10 @@
 	}
 }
 
+static struct irqaction timer_irq_action = {
+	.name = "timer",
+};
+
 /* Only invoked on boot processor. */
 void __init init_IRQ(void)
 {
@@ -1064,109 +775,6 @@
 			     : /* No outputs */
 			     : "i" (PSTATE_IE)
 			     : "g1");
+
+	irq_desc[0].action = &timer_irq_action;
 }
-
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NUM_IVECS];
-
-#ifdef CONFIG_SMP
-
-static int irq_affinity_read_proc (char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	struct ino_bucket *bp = ivector_table + (long)data;
-	struct irq_desc *desc = bp->irq_info;
-	struct irqaction *ap = desc->action;
-	cpumask_t mask;
-	int len;
-
-	mask = get_smpaff_in_irqaction(ap);
-	if (cpus_empty(mask))
-		mask = cpu_online_map;
-
-	len = cpumask_scnprintf(page, count, mask);
-	if (count - len < 2)
-		return -EINVAL;
-	len += sprintf(page + len, "\n");
-	return len;
-}
-
-static inline void set_intr_affinity(int irq, cpumask_t hw_aff)
-{
-	struct ino_bucket *bp = ivector_table + irq;
-	struct irq_desc *desc = bp->irq_info;
-	struct irqaction *ap = desc->action;
-
-	/* Users specify affinity in terms of hw cpu ids.
-	 * As soon as we do this, handler_irq() might see and take action.
-	 */
-	put_smpaff_in_irqaction(ap, hw_aff);
-
-	/* Migration is simply done by the next cpu to service this
-	 * interrupt.
-	 */
-}
-
-static int irq_affinity_write_proc (struct file *file, const char __user *buffer,
-					unsigned long count, void *data)
-{
-	int irq = (long) data, full_count = count, err;
-	cpumask_t new_value;
-
-	err = cpumask_parse(buffer, count, new_value);
-
-	/*
-	 * Do not allow disabling IRQs completely - it's a too easy
-	 * way to make the system unusable accidentally :-) At least
-	 * one online CPU still has to be targeted.
-	 */
-	cpus_and(new_value, new_value, cpu_online_map);
-	if (cpus_empty(new_value))
-		return -EINVAL;
-
-	set_intr_affinity(irq, new_value);
-
-	return full_count;
-}
-
-#endif
-
-#define MAX_NAMELEN 10
-
-static void register_irq_proc (unsigned int irq)
-{
-	char name [MAX_NAMELEN];
-
-	if (!root_irq_dir || irq_dir[irq])
-		return;
-
-	memset(name, 0, MAX_NAMELEN);
-	sprintf(name, "%x", irq);
-
-	/* create /proc/irq/1234 */
-	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
-
-#ifdef CONFIG_SMP
-	/* XXX SMP affinity not supported on starfire yet. */
-	if (this_is_starfire == 0) {
-		struct proc_dir_entry *entry;
-
-		/* create /proc/irq/1234/smp_affinity */
-		entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
-
-		if (entry) {
-			entry->nlink = 1;
-			entry->data = (void *)(long)irq;
-			entry->read_proc = irq_affinity_read_proc;
-			entry->write_proc = irq_affinity_write_proc;
-		}
-	}
-#endif
-}
-
-void init_irq_proc (void)
-{
-	/* create /proc/irq */
-	root_irq_dir = proc_mkdir("irq", NULL);
-}
-
diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c
index 30862ab..6f16dee 100644
--- a/arch/sparc64/kernel/isa.c
+++ b/arch/sparc64/kernel/isa.c
@@ -15,23 +15,19 @@
 static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
 {
 	if (child)
-		printk(" (%s)", isa_dev->prom_name);
+		printk(" (%s)", isa_dev->prom_node->name);
 	else
-		printk(" [%s", isa_dev->prom_name);
+		printk(" [%s", isa_dev->prom_node->name);
 }
 
-static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev,
-					struct linux_prom_registers *pregs,
-					int pregs_size)
+static struct linux_prom_registers * __init
+isa_dev_get_resource(struct sparc_isa_device *isa_dev)
 {
+	struct linux_prom_registers *pregs;
 	unsigned long base, len;
 	int prop_len;
 
-	prop_len = prom_getproperty(isa_dev->prom_node, "reg",
-				    (char *) pregs, pregs_size);
-
-	if (prop_len <= 0)
-		return;
+	pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
 
 	/* Only the first one is interesting. */
 	len = pregs[0].reg_size;
@@ -42,10 +38,12 @@
 	isa_dev->resource.start = base;
 	isa_dev->resource.end   = (base + len - 1UL);
 	isa_dev->resource.flags = IORESOURCE_IO;
-	isa_dev->resource.name  = isa_dev->prom_name;
+	isa_dev->resource.name  = isa_dev->prom_node->name;
 
 	request_resource(&isa_dev->bus->parent->io_space,
 			 &isa_dev->resource);
+
+	return pregs;
 }
 
 /* I can't believe they didn't put a real INO in the isa device
@@ -74,19 +72,30 @@
 static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev,
 					     struct sparc_isa_bridge *isa_br,
 					     int *interrupt,
-					     struct linux_prom_registers *pregs)
+					     struct linux_prom_registers *reg)
 {
+	struct linux_prom_ebus_intmap *imap;
+	struct linux_prom_ebus_intmap *imask;
 	unsigned int hi, lo, irq;
-	int i;
+	int i, len, n_imap;
 
-	hi = pregs->which_io & isa_br->isa_intmask.phys_hi;
-	lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo;
-	irq = *interrupt & isa_br->isa_intmask.interrupt;
-	for (i = 0; i < isa_br->num_isa_intmap; i++) {
-		if ((isa_br->isa_intmap[i].phys_hi == hi) &&
-		    (isa_br->isa_intmap[i].phys_lo == lo) &&
-		    (isa_br->isa_intmap[i].interrupt == irq)) {
-			*interrupt = isa_br->isa_intmap[i].cinterrupt;
+	imap = of_get_property(isa_br->prom_node, "interrupt-map", &len);
+	if (!imap)
+		return 0;
+	n_imap = len / sizeof(imap[0]);
+
+	imask = of_get_property(isa_br->prom_node, "interrupt-map-mask", NULL);
+	if (!imask)
+		return 0;
+
+	hi = reg->which_io & imask->phys_hi;
+	lo = reg->phys_addr & imask->phys_lo;
+	irq = *interrupt & imask->interrupt;
+	for (i = 0; i < n_imap; i++) {
+		if ((imap[i].phys_hi == hi) &&
+		    (imap[i].phys_lo == lo) &&
+		    (imap[i].interrupt == irq)) {
+			*interrupt = imap[i].cinterrupt;
 			return 0;
 		}
 	}
@@ -98,8 +107,8 @@
 {
 	int irq_prop;
 
-	irq_prop = prom_getintdefault(isa_dev->prom_node,
-				      "interrupts", -1);
+	irq_prop = of_getintprop_default(isa_dev->prom_node,
+					 "interrupts", -1);
 	if (irq_prop <= 0) {
 		goto no_irq;
 	} else {
@@ -107,7 +116,8 @@
 		struct pci_pbm_info *pbm;
 		int i;
 
-		if (isa_dev->bus->num_isa_intmap) {
+		if (of_find_property(isa_dev->bus->prom_node,
+				     "interrupt-map", NULL)) {
 			if (!isa_dev_get_irq_using_imap(isa_dev,
 							isa_dev->bus,
 							&irq_prop,
@@ -141,16 +151,15 @@
 
 static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
 {
-	int node = prom_getchild(parent_isa_dev->prom_node);
+	struct device_node *dp = parent_isa_dev->prom_node->child;
 
-	if (node == 0)
+	if (!dp)
 		return;
 
 	printk(" ->");
-	while (node != 0) {
-		struct linux_prom_registers regs[PROMREG_MAX];
+	while (dp) {
+		struct linux_prom_registers *regs;
 		struct sparc_isa_device *isa_dev;
-		int prop_len;
 
 		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
 		if (!isa_dev) {
@@ -165,49 +174,46 @@
 		parent_isa_dev->child = isa_dev;
 
 		isa_dev->bus = parent_isa_dev->bus;
-		isa_dev->prom_node = node;
-		prop_len = prom_getproperty(node, "name",
-					    (char *) isa_dev->prom_name,
-					    sizeof(isa_dev->prom_name));
-		if (prop_len <= 0) {
-			fatal_err("cannot get child isa_dev OBP node name");
-			prom_halt();
-		}
+		isa_dev->prom_node = dp;
 
-		prop_len = prom_getproperty(node, "compatible",
-					    (char *) isa_dev->compatible,
-					    sizeof(isa_dev->compatible));
-
-		/* Not having this is OK. */
-		if (prop_len <= 0)
-			isa_dev->compatible[0] = '\0';
-
-		isa_dev_get_resource(isa_dev, regs, sizeof(regs));
+		regs = isa_dev_get_resource(isa_dev);
 		isa_dev_get_irq(isa_dev, regs);
 
 		report_dev(isa_dev, 1);
 
-		node = prom_getsibling(node);
+		dp = dp->sibling;
 	}
 }
 
 static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
 {
-	int node = prom_getchild(isa_br->prom_node);
+	struct device_node *dp = isa_br->prom_node->child;
 
-	while (node != 0) {
-		struct linux_prom_registers regs[PROMREG_MAX];
+	while (dp) {
+		struct linux_prom_registers *regs;
 		struct sparc_isa_device *isa_dev;
-		int prop_len;
 
 		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
 		if (!isa_dev) {
-			fatal_err("cannot allocate isa_dev");
-			prom_halt();
+			printk(KERN_DEBUG "ISA: cannot allocate isa_dev");
+			return;
 		}
 
 		memset(isa_dev, 0, sizeof(*isa_dev));
 
+		isa_dev->ofdev.node = dp;
+		isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;
+		isa_dev->ofdev.dev.bus = &isa_bus_type;
+		strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name);
+
+		/* Register with core */
+		if (of_device_register(&isa_dev->ofdev) != 0) {
+			printk(KERN_DEBUG "isa: device registration error for %s!\n",
+			       isa_dev->ofdev.dev.bus_id);
+			kfree(isa_dev);
+			goto next_sibling;
+		}
+
 		/* Link it in. */
 		isa_dev->next = NULL;
 		if (isa_br->devices == NULL) {
@@ -222,24 +228,9 @@
 		}
 
 		isa_dev->bus = isa_br;
-		isa_dev->prom_node = node;
-		prop_len = prom_getproperty(node, "name",
-					    (char *) isa_dev->prom_name,
-					    sizeof(isa_dev->prom_name));
-		if (prop_len <= 0) {
-			fatal_err("cannot get isa_dev OBP node name");
-			prom_halt();
-		}
+		isa_dev->prom_node = dp;
 
-		prop_len = prom_getproperty(node, "compatible",
-					    (char *) isa_dev->compatible,
-					    sizeof(isa_dev->compatible));
-
-		/* Not having this is OK. */
-		if (prop_len <= 0)
-			isa_dev->compatible[0] = '\0';
-
-		isa_dev_get_resource(isa_dev, regs, sizeof(regs));
+		regs = isa_dev_get_resource(isa_dev);
 		isa_dev_get_irq(isa_dev, regs);
 
 		report_dev(isa_dev, 0);
@@ -248,7 +239,8 @@
 
 		printk("]");
 
-		node = prom_getsibling(node);
+	next_sibling:
+		dp = dp->sibling;
 	}
 }
 
@@ -266,7 +258,7 @@
 		struct pcidev_cookie *pdev_cookie;
 		struct pci_pbm_info *pbm;
 		struct sparc_isa_bridge *isa_br;
-		int prop_len;
+		struct device_node *dp;
 
 		pdev_cookie = pdev->sysdata;
 		if (!pdev_cookie) {
@@ -275,15 +267,29 @@
 			continue;
 		}
 		pbm = pdev_cookie->pbm;
+		dp = pdev_cookie->prom_node;
 
 		isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
 		if (!isa_br) {
-			fatal_err("cannot allocate sparc_isa_bridge");
-			prom_halt();
+			printk(KERN_DEBUG "isa: cannot allocate sparc_isa_bridge");
+			return;
 		}
 
 		memset(isa_br, 0, sizeof(*isa_br));
 
+		isa_br->ofdev.node = dp;
+		isa_br->ofdev.dev.parent = &pdev->dev;
+		isa_br->ofdev.dev.bus = &isa_bus_type;
+		strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name);
+
+		/* Register with core */
+		if (of_device_register(&isa_br->ofdev) != 0) {
+			printk(KERN_DEBUG "isa: device registration error for %s!\n",
+			       isa_br->ofdev.dev.bus_id);
+			kfree(isa_br);
+			return;
+		}
+
 		/* Link it in. */
 		isa_br->next = isa_chain;
 		isa_chain = isa_br;
@@ -292,33 +298,6 @@
 		isa_br->self = pdev;
 		isa_br->index = index++;
 		isa_br->prom_node = pdev_cookie->prom_node;
-		strncpy(isa_br->prom_name, pdev_cookie->prom_name,
-			sizeof(isa_br->prom_name));
-
-		prop_len = prom_getproperty(isa_br->prom_node,
-					    "ranges",
-					    (char *) isa_br->isa_ranges,
-					    sizeof(isa_br->isa_ranges));
-		if (prop_len <= 0)
-			isa_br->num_isa_ranges = 0;
-		else
-			isa_br->num_isa_ranges =
-				(prop_len / sizeof(struct linux_prom_isa_ranges));
-
-		prop_len = prom_getproperty(isa_br->prom_node,
-					    "interrupt-map",
-					    (char *) isa_br->isa_intmap,
-					    sizeof(isa_br->isa_intmap));
-		if (prop_len <= 0)
-			isa_br->num_isa_intmap = 0;
-		else
-			isa_br->num_isa_intmap =
-				(prop_len / sizeof(struct linux_prom_isa_intmap));
-
-		prop_len = prom_getproperty(isa_br->prom_node,
-					    "interrupt-map-mask",
-					    (char *) &(isa_br->isa_intmask),
-					    sizeof(isa_br->isa_intmask));
 
 		printk("isa%d:", isa_br->index);
 
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
new file mode 100644
index 0000000..768475b
--- /dev/null
+++ b/arch/sparc64/kernel/of_device.c
@@ -0,0 +1,282 @@
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include <asm/errno.h>
+#include <asm/of_device.h>
+
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
+					const struct of_device *dev)
+{
+	if (!dev->node)
+		return NULL;
+	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
+		int match = 1;
+		if (matches->name[0])
+			match &= dev->node->name
+				&& !strcmp(matches->name, dev->node->name);
+		if (matches->type[0])
+			match &= dev->node->type
+				&& !strcmp(matches->type, dev->node->type);
+		if (matches->compatible[0])
+			match &= of_device_is_compatible(dev->node,
+							 matches->compatible);
+		if (match)
+			return matches;
+		matches++;
+	}
+	return NULL;
+}
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+	const struct of_device_id * matches = of_drv->match_table;
+
+	if (!matches)
+		return 0;
+
+	return of_match_device(matches, of_dev) != NULL;
+}
+
+struct of_device *of_dev_get(struct of_device *dev)
+{
+	struct device *tmp;
+
+	if (!dev)
+		return NULL;
+	tmp = get_device(&dev->dev);
+	if (tmp)
+		return to_of_device(tmp);
+	else
+		return NULL;
+}
+
+void of_dev_put(struct of_device *dev)
+{
+	if (dev)
+		put_device(&dev->dev);
+}
+
+
+static int of_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct of_platform_driver *drv;
+	struct of_device *of_dev;
+	const struct of_device_id *match;
+
+	drv = to_of_platform_driver(dev->driver);
+	of_dev = to_of_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	of_dev_get(of_dev);
+
+	match = of_match_device(drv->match_table, of_dev);
+	if (match)
+		error = drv->probe(of_dev, match);
+	if (error)
+		of_dev_put(of_dev);
+
+	return error;
+}
+
+static int of_device_remove(struct device *dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(of_dev);
+	return 0;
+}
+
+static int of_device_suspend(struct device *dev, pm_message_t state)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->suspend)
+		error = drv->suspend(of_dev, state);
+	return error;
+}
+
+static int of_device_resume(struct device * dev)
+{
+	struct of_device * of_dev = to_of_device(dev);
+	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+	int error = 0;
+
+	if (dev->driver && drv->resume)
+		error = drv->resume(of_dev);
+	return error;
+}
+
+#ifdef CONFIG_PCI
+struct bus_type isa_bus_type = {
+       .name	= "isa",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+EXPORT_SYMBOL(isa_bus_type);
+
+struct bus_type ebus_bus_type = {
+       .name	= "ebus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+EXPORT_SYMBOL(ebus_bus_type);
+#endif
+
+#ifdef CONFIG_SBUS
+struct bus_type sbus_bus_type = {
+       .name	= "sbus",
+       .match	= of_platform_bus_match,
+       .probe	= of_device_probe,
+       .remove	= of_device_remove,
+       .suspend	= of_device_suspend,
+       .resume	= of_device_resume,
+};
+EXPORT_SYMBOL(sbus_bus_type);
+#endif
+
+static int __init of_bus_driver_init(void)
+{
+	int err = 0;
+
+#ifdef CONFIG_PCI
+	if (!err)
+		err = bus_register(&isa_bus_type);
+	if (!err)
+		err = bus_register(&ebus_bus_type);
+#endif
+#ifdef CONFIG_SBUS
+	if (!err)
+		err = bus_register(&sbus_bus_type);
+#endif
+	return 0;
+}
+
+postcore_initcall(of_bus_driver_init);
+
+int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
+{
+	/* initialize common driver fields */
+	drv->driver.name = drv->name;
+	drv->driver.bus = bus;
+
+	/* register with core */
+	return driver_register(&drv->driver);
+}
+
+void of_unregister_driver(struct of_platform_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+
+
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct of_device *ofdev;
+
+	ofdev = to_of_device(dev);
+	return sprintf(buf, "%s", ofdev->node->full_name);
+}
+
+static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
+
+/**
+ * of_release_dev - free an of device structure when all users of it are finished.
+ * @dev: device that's been disconnected
+ *
+ * Will be called only by the device core when all users of this of device are
+ * done.
+ */
+void of_release_dev(struct device *dev)
+{
+	struct of_device *ofdev;
+
+        ofdev = to_of_device(dev);
+
+	kfree(ofdev);
+}
+
+int of_device_register(struct of_device *ofdev)
+{
+	int rc;
+
+	BUG_ON(ofdev->node == NULL);
+
+	rc = device_register(&ofdev->dev);
+	if (rc)
+		return rc;
+
+	device_create_file(&ofdev->dev, &dev_attr_devspec);
+
+	return 0;
+}
+
+void of_device_unregister(struct of_device *ofdev)
+{
+	device_remove_file(&ofdev->dev, &dev_attr_devspec);
+	device_unregister(&ofdev->dev);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np,
+					    const char *bus_id,
+					    struct device *parent,
+					    struct bus_type *bus)
+{
+	struct of_device *dev;
+
+	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
+
+	dev->dev.parent = parent;
+	dev->dev.bus = bus;
+	dev->dev.release = of_release_dev;
+
+	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+
+	if (of_device_register(dev) != 0) {
+		kfree(dev);
+		return NULL;
+	}
+
+	return dev;
+}
+
+EXPORT_SYMBOL(of_match_device);
+EXPORT_SYMBOL(of_register_driver);
+EXPORT_SYMBOL(of_unregister_driver);
+EXPORT_SYMBOL(of_device_register);
+EXPORT_SYMBOL(of_device_unregister);
+EXPORT_SYMBOL(of_dev_get);
+EXPORT_SYMBOL(of_dev_put);
+EXPORT_SYMBOL(of_platform_device_create);
+EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index f97ddeb..6c9e3e9 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -22,6 +22,7 @@
 #include <asm/irq.h>
 #include <asm/ebus.h>
 #include <asm/isa.h>
+#include <asm/prom.h>
 
 unsigned long pci_memspace_mask = 0xffffffffUL;
 
@@ -47,12 +48,6 @@
 /* Each PCI controller found gets a unique index. */
 int pci_num_controllers = 0;
 
-/* At boot time the user can give the kernel a command
- * line option which controls if and how PCI devices
- * are reordered at PCI bus probing time.
- */
-int pci_device_reorder = 0;
-
 volatile int pci_poke_in_progress;
 volatile int pci_poke_cpu = -1;
 volatile int pci_poke_faulted;
@@ -183,16 +178,16 @@
 }
 
 /* Probe for all PCI controllers in the system. */
-extern void sabre_init(int, char *);
-extern void psycho_init(int, char *);
-extern void schizo_init(int, char *);
-extern void schizo_plus_init(int, char *);
-extern void tomatillo_init(int, char *);
-extern void sun4v_pci_init(int, char *);
+extern void sabre_init(struct device_node *, const char *);
+extern void psycho_init(struct device_node *, const char *);
+extern void schizo_init(struct device_node *, const char *);
+extern void schizo_plus_init(struct device_node *, const char *);
+extern void tomatillo_init(struct device_node *, const char *);
+extern void sun4v_pci_init(struct device_node *, const char *);
 
 static struct {
 	char *model_name;
-	void (*init)(int, char *);
+	void (*init)(struct device_node *, const char *);
 } pci_controller_table[] __initdata = {
 	{ "SUNW,sabre", sabre_init },
 	{ "pci108e,a000", sabre_init },
@@ -210,7 +205,7 @@
 #define PCI_NUM_CONTROLLER_TYPES (sizeof(pci_controller_table) / \
 				  sizeof(pci_controller_table[0]))
 
-static int __init pci_controller_init(char *model_name, int namelen, int node)
+static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp)
 {
 	int i;
 
@@ -218,18 +213,15 @@
 		if (!strncmp(model_name,
 			     pci_controller_table[i].model_name,
 			     namelen)) {
-			pci_controller_table[i].init(node, model_name);
+			pci_controller_table[i].init(dp, model_name);
 			return 1;
 		}
 	}
-	printk("PCI: Warning unknown controller, model name [%s]\n",
-	       model_name);
-	printk("PCI: Ignoring controller...\n");
 
 	return 0;
 }
 
-static int __init pci_is_controller(char *model_name, int namelen, int node)
+static int __init pci_is_controller(const char *model_name, int namelen, struct device_node *dp)
 {
 	int i;
 
@@ -243,36 +235,35 @@
 	return 0;
 }
 
-static int __init pci_controller_scan(int (*handler)(char *, int, int))
+static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *))
 {
-	char namebuf[64];
-	int node;
+	struct device_node *dp;
 	int count = 0;
 
-	node = prom_getchild(prom_root_node);
-	while ((node = prom_searchsiblings(node, "pci")) != 0) {
+	for_each_node_by_name(dp, "pci") {
+		struct property *prop;
 		int len;
 
-		if ((len = prom_getproperty(node, "model", namebuf, sizeof(namebuf))) > 0 ||
-		    (len = prom_getproperty(node, "compatible", namebuf, sizeof(namebuf))) > 0) {
+		prop = of_find_property(dp, "model", &len);
+		if (!prop)
+			prop = of_find_property(dp, "compatible", &len);
+
+		if (prop) {
+			const char *model = prop->value;
 			int item_len = 0;
 
 			/* Our value may be a multi-valued string in the
 			 * case of some compatible properties. For sanity,
-			 * only try the first one. */
-
-			while (namebuf[item_len] && len) {
+			 * only try the first one.
+			 */
+			while (model[item_len] && len) {
 				len--;
 				item_len++;
 			}
 
-			if (handler(namebuf, item_len, node))
+			if (handler(model, item_len, dp))
 				count++;
 		}
-
-		node = prom_getsibling(node);
-		if (!node)
-			break;
 	}
 
 	return count;
@@ -316,27 +307,6 @@
 		p->scan_bus(p);
 }
 
-/* Reorder the pci_dev chain, so that onboard devices come first
- * and then come the pluggable cards.
- */
-static void __init pci_reorder_devs(void)
-{
-	struct list_head *pci_onboard = &pci_devices;
-	struct list_head *walk = pci_onboard->next;
-
-	while (walk != pci_onboard) {
-		struct pci_dev *pdev = pci_dev_g(walk);
-		struct list_head *walk_next = walk->next;
-
-		if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
-			list_del(walk);
-			list_add(walk, pci_onboard);
-		}
-
-		walk = walk_next;
-	}
-}
-
 extern void clock_probe(void);
 extern void power_init(void);
 
@@ -348,9 +318,6 @@
 
 	pci_scan_each_controller_bus();
 
-	if (pci_device_reorder)
-		pci_reorder_devs();
-
 	isa_init();
 	ebus_init();
 	clock_probe();
@@ -439,14 +406,12 @@
 }
 EXPORT_SYMBOL(pcibios_bus_to_resource);
 
+extern int pci_irq_verbose;
+
 char * __init pcibios_setup(char *str)
 {
-	if (!strcmp(str, "onboardfirst")) {
-		pci_device_reorder = 1;
-		return NULL;
-	}
-	if (!strcmp(str, "noreorder")) {
-		pci_device_reorder = 0;
+	if (!strcmp(str, "irq_verbose")) {
+		pci_irq_verbose = 1;
 		return NULL;
 	}
 	return str;
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 33dedb1..b06a295 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -9,6 +9,12 @@
 #include <linux/init.h>
 
 #include <asm/pbm.h>
+#include <asm/prom.h>
+
+#include "pci_impl.h"
+
+/* Pass "pci=irq_verbose" on the kernel command line to enable this.  */
+int pci_irq_verbose;
 
 /* Fix self device of BUS and hook it into BUS->self.
  * The pci_scan_bus does not do this for the host bridge.
@@ -28,16 +34,14 @@
 	prom_halt();
 }
 
-/* Find the OBP PROM device tree node for a PCI device.
- * Return zero if not found.
- */
-static int __init find_device_prom_node(struct pci_pbm_info *pbm,
-					struct pci_dev *pdev,
-					int bus_prom_node,
-					struct linux_prom_pci_registers *pregs,
-					int *nregs)
+/* Find the OBP PROM device tree node for a PCI device.  */
+static struct device_node * __init
+find_device_prom_node(struct pci_pbm_info *pbm, struct pci_dev *pdev,
+		      struct device_node *bus_node,
+		      struct linux_prom_pci_registers **pregs,
+		      int *nregs)
 {
-	int node;
+	struct device_node *dp;
 
 	*nregs = 0;
 
@@ -54,24 +58,30 @@
 	     pdev->device == PCI_DEVICE_ID_SUN_TOMATILLO ||
 	     pdev->device == PCI_DEVICE_ID_SUN_SABRE ||
 	     pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD))
-		return bus_prom_node;
+		return bus_node;
 
-	node = prom_getchild(bus_prom_node);
-	while (node != 0) {
-		int err = prom_getproperty(node, "reg",
-					   (char *)pregs,
-					   sizeof(*pregs) * PROMREG_MAX);
-		if (err == 0 || err == -1)
+	dp = bus_node->child;
+	while (dp) {
+		struct linux_prom_pci_registers *regs;
+		struct property *prop;
+		int len;
+
+		prop = of_find_property(dp, "reg", &len);
+		if (!prop)
 			goto do_next_sibling;
-		if (((pregs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
-			*nregs = err / sizeof(*pregs);
-			return node;
+
+		regs = prop->value;
+		if (((regs[0].phys_hi >> 8) & 0xff) == pdev->devfn) {
+			*pregs = regs;
+			*nregs = len / sizeof(struct linux_prom_pci_registers);
+			return dp;
 		}
 
 	do_next_sibling:
-		node = prom_getsibling(node);
+		dp = dp->sibling;
 	}
-	return 0;
+
+	return NULL;
 }
 
 /* Older versions of OBP on PCI systems encode 64-bit MEM
@@ -128,15 +138,17 @@
  */
 static void __init pdev_cookie_fillin(struct pci_pbm_info *pbm,
 				      struct pci_dev *pdev,
-				      int bus_prom_node)
+				      struct device_node *bus_node)
 {
-	struct linux_prom_pci_registers pregs[PROMREG_MAX];
+	struct linux_prom_pci_registers *pregs = NULL;
 	struct pcidev_cookie *pcp;
-	int device_prom_node, nregs, err;
+	struct device_node *dp;
+	struct property *prop;
+	int nregs, len;
 
-	device_prom_node = find_device_prom_node(pbm, pdev, bus_prom_node,
-						 pregs, &nregs);
-	if (device_prom_node == 0) {
+	dp = find_device_prom_node(pbm, pdev, bus_node,
+				   &pregs, &nregs);
+	if (!dp) {
 		/* If it is not in the OBP device tree then
 		 * there must be a damn good reason for it.
 		 *
@@ -150,45 +162,43 @@
 		return;
 	}
 
-	pcp = kmalloc(sizeof(*pcp), GFP_ATOMIC);
+	pcp = kzalloc(sizeof(*pcp), GFP_ATOMIC);
 	if (pcp == NULL) {
 		prom_printf("PCI_COOKIE: Fatal malloc error, aborting...\n");
 		prom_halt();
 	}
 	pcp->pbm = pbm;
-	pcp->prom_node = device_prom_node;
-	memcpy(pcp->prom_regs, pregs, sizeof(pcp->prom_regs));
+	pcp->prom_node = dp;
+	memcpy(pcp->prom_regs, pregs,
+	       nregs * sizeof(struct linux_prom_pci_registers));
 	pcp->num_prom_regs = nregs;
-	err = prom_getproperty(device_prom_node, "name",
-			       pcp->prom_name, sizeof(pcp->prom_name));
-	if (err > 0)
-		pcp->prom_name[err] = 0;
-	else
-		pcp->prom_name[0] = 0;
 
-	err = prom_getproperty(device_prom_node,
-			       "assigned-addresses",
-			       (char *)pcp->prom_assignments,
-			       sizeof(pcp->prom_assignments));
-	if (err == 0 || err == -1)
+	/* We can't have the pcidev_cookie assignments be just
+	 * direct pointers into the property value, since they
+	 * are potentially modified by the probing process.
+	 */
+	prop = of_find_property(dp, "assigned-addresses", &len);
+	if (!prop) {
 		pcp->num_prom_assignments = 0;
-	else
+	} else {
+		memcpy(pcp->prom_assignments, prop->value, len);
 		pcp->num_prom_assignments =
-			(err / sizeof(pcp->prom_assignments[0]));
+			(len / sizeof(pcp->prom_assignments[0]));
+	}
 
-	if (strcmp(pcp->prom_name, "ebus") == 0) {
-		struct linux_prom_ebus_ranges erng[PROM_PCIRNG_MAX];
+	if (strcmp(dp->name, "ebus") == 0) {
+		struct linux_prom_ebus_ranges *erng;
 		int iter;
 
 		/* EBUS is special... */
-		err = prom_getproperty(device_prom_node, "ranges",
-				       (char *)&erng[0], sizeof(erng));
-		if (err == 0 || err == -1) {
+		prop = of_find_property(dp, "ranges", &len);
+		if (!prop) {
 			prom_printf("EBUS: Fatal error, no range property\n");
 			prom_halt();
 		}
-		err = (err / sizeof(erng[0]));
-		for(iter = 0; iter < err; iter++) {
+		erng = prop->value;
+		len = (len / sizeof(erng[0]));
+		for (iter = 0; iter < len; iter++) {
 			struct linux_prom_ebus_ranges *ep = &erng[iter];
 			struct linux_prom_pci_registers *ap;
 
@@ -200,7 +210,7 @@
 			ap->size_hi = 0;
 			ap->size_lo = ep->size;
 		}
-		pcp->num_prom_assignments = err;
+		pcp->num_prom_assignments = len;
 	}
 
 	fixup_obp_assignments(pdev, pcp);
@@ -210,7 +220,7 @@
 
 void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
-				    int prom_node)
+				    struct device_node *dp)
 {
 	struct pci_dev *pdev, *pdev_next;
 	struct pci_bus *this_pbus, *pbus_next;
@@ -218,7 +228,7 @@
 	/* This must be _safe because the cookie fillin
 	   routine can delete devices from the tree.  */
 	list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
-		pdev_cookie_fillin(pbm, pdev, prom_node);
+		pdev_cookie_fillin(pbm, pdev, dp);
 
 	list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
 		struct pcidev_cookie *pcp = this_pbus->self->sysdata;
@@ -241,7 +251,6 @@
 	if (res)
 		prom_printf("PCI: RES[%016lx-->%016lx:(%lx)]\n",
 			    res->start, res->end, res->flags);
-	prom_printf("Please email this information to davem@redhat.com\n");
 	if (do_prom_halt)
 		prom_halt();
 }
@@ -273,8 +282,7 @@
 		return &pbm->mem_space;
 
 	default:
-		printk("PCI: What is resource space %x? "
-		       "Tell davem@redhat.com about it!\n", space);
+		printk("PCI: What is resource space %x?\n", space);
 		return NULL;
 	};
 }
@@ -556,9 +564,10 @@
 
 	ret = ((interrupt - 1 + (PCI_SLOT(pdev->devfn) & 3)) & 3) + 1;
 
-	printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n",
-	       pbm->name, pci_name(toplevel_pdev), pci_name(pdev),
-	       interrupt, PCI_SLOT(pdev->devfn), ret);
+	if (pci_irq_verbose)
+		printk("%s: %s IRQ Swivel %s [%x:%x] -> [%x]\n",
+		       pbm->name, pci_name(toplevel_pdev), pci_name(pdev),
+		       interrupt, PCI_SLOT(pdev->devfn), ret);
 
 	return ret;
 }
@@ -568,58 +577,60 @@
 					    struct pci_dev *pbus,
 					    struct pci_dev *pdev,
 					    unsigned int interrupt,
-					    unsigned int *cnode)
+					    struct device_node **cnode)
 {
-	struct linux_prom_pci_intmap imap[PROM_PCIIMAP_MAX];
-	struct linux_prom_pci_intmask imask;
+	struct linux_prom_pci_intmap *imap;
+	struct linux_prom_pci_intmask *imask;
 	struct pcidev_cookie *pbus_pcp = pbus->sysdata;
 	struct pcidev_cookie *pdev_pcp = pdev->sysdata;
 	struct linux_prom_pci_registers *pregs = pdev_pcp->prom_regs;
+	struct property *prop;
 	int plen, num_imap, i;
 	unsigned int hi, mid, lo, irq, orig_interrupt;
 
 	*cnode = pbus_pcp->prom_node;
 
-	plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map",
-				(char *) &imap[0], sizeof(imap));
-	if (plen <= 0 ||
+	prop = of_find_property(pbus_pcp->prom_node, "interrupt-map", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_intmap)) != 0) {
 		printk("%s: Device %s interrupt-map has bad len %d\n",
 		       pbm->name, pci_name(pbus), plen);
 		goto no_intmap;
 	}
+	imap = prop->value;
 	num_imap = plen / sizeof(struct linux_prom_pci_intmap);
 
-	plen = prom_getproperty(pbus_pcp->prom_node, "interrupt-map-mask",
-				(char *) &imask, sizeof(imask));
-	if (plen <= 0 ||
+	prop = of_find_property(pbus_pcp->prom_node, "interrupt-map-mask", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_intmask)) != 0) {
 		printk("%s: Device %s interrupt-map-mask has bad len %d\n",
 		       pbm->name, pci_name(pbus), plen);
 		goto no_intmap;
 	}
+	imask = prop->value;
 
 	orig_interrupt = interrupt;
 
-	hi   = pregs->phys_hi & imask.phys_hi;
-	mid  = pregs->phys_mid & imask.phys_mid;
-	lo   = pregs->phys_lo & imask.phys_lo;
-	irq  = interrupt & imask.interrupt;
+	hi   = pregs->phys_hi & imask->phys_hi;
+	mid  = pregs->phys_mid & imask->phys_mid;
+	lo   = pregs->phys_lo & imask->phys_lo;
+	irq  = interrupt & imask->interrupt;
 
 	for (i = 0; i < num_imap; i++) {
 		if (imap[i].phys_hi  == hi   &&
 		    imap[i].phys_mid == mid  &&
 		    imap[i].phys_lo  == lo   &&
 		    imap[i].interrupt == irq) {
-			*cnode = imap[i].cnode;
+			*cnode = of_find_node_by_phandle(imap[i].cnode);
 			interrupt = imap[i].cinterrupt;
 		}
 	}
 
-	printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n",
-	       pbm->name, pci_name(toplevel_pdev),
-	       pci_name(pbus), pci_name(pdev),
-	       orig_interrupt, interrupt);
+	if (pci_irq_verbose)
+		printk("%s: %s MAP BUS %s DEV %s [%x] -> [%x]\n",
+		       pbm->name, pci_name(toplevel_pdev),
+		       pci_name(pbus), pci_name(pdev),
+		       orig_interrupt, interrupt);
 
 no_intmap:
 	return interrupt;
@@ -633,21 +644,22 @@
  * all interrupt translations are complete, else we should use that node's
  * "reg" property to apply the PBM's "interrupt-{map,mask}" to the interrupt.
  */
-static unsigned int __init pci_intmap_match_to_root(struct pci_pbm_info *pbm,
-						    struct pci_dev *pdev,
-						    unsigned int *interrupt)
+static struct device_node * __init
+pci_intmap_match_to_root(struct pci_pbm_info *pbm,
+			 struct pci_dev *pdev,
+			 unsigned int *interrupt)
 {
 	struct pci_dev *toplevel_pdev = pdev;
 	struct pcidev_cookie *toplevel_pcp = toplevel_pdev->sysdata;
-	unsigned int cnode = toplevel_pcp->prom_node;
+	struct device_node *cnode = toplevel_pcp->prom_node;
 
 	while (pdev->bus->number != pbm->pci_first_busno) {
 		struct pci_dev *pbus = pdev->bus->self;
 		struct pcidev_cookie *pcp = pbus->sysdata;
-		int plen;
+		struct property *prop;
 
-		plen = prom_getproplen(pcp->prom_node, "interrupt-map");
-		if (plen <= 0) {
+		prop = of_find_property(pcp->prom_node, "interrupt-map", NULL);
+		if (!prop) {
 			*interrupt = pci_slot_swivel(pbm, toplevel_pdev,
 						     pdev, *interrupt);
 			cnode = pcp->prom_node;
@@ -675,26 +687,29 @@
 {
 	struct pcidev_cookie *dev_pcp = pdev->sysdata;
 	struct pci_pbm_info *pbm = dev_pcp->pbm;
-	struct linux_prom_pci_registers reg[PROMREG_MAX];
+	struct linux_prom_pci_registers *reg;
+	struct device_node *cnode;
+	struct property *prop;
 	unsigned int hi, mid, lo, irq;
-	int i, cnode, plen;
+	int i, plen;
 
 	cnode = pci_intmap_match_to_root(pbm, pdev, interrupt);
 	if (cnode == pbm->prom_node)
 		goto success;
 
-	plen = prom_getproperty(cnode, "reg", (char *) reg, sizeof(reg));
-	if (plen <= 0 ||
+	prop = of_find_property(cnode, "reg", &plen);
+	if (!prop ||
 	    (plen % sizeof(struct linux_prom_pci_registers)) != 0) {
-		printk("%s: OBP node %x reg property has bad len %d\n",
-		       pbm->name, cnode, plen);
+		printk("%s: OBP node %s reg property has bad len %d\n",
+		       pbm->name, cnode->full_name, plen);
 		goto fail;
 	}
+	reg = prop->value;
 
-	hi   = reg[0].phys_hi & pbm->pbm_intmask.phys_hi;
-	mid  = reg[0].phys_mid & pbm->pbm_intmask.phys_mid;
-	lo   = reg[0].phys_lo & pbm->pbm_intmask.phys_lo;
-	irq  = *interrupt & pbm->pbm_intmask.interrupt;
+	hi   = reg[0].phys_hi & pbm->pbm_intmask->phys_hi;
+	mid  = reg[0].phys_mid & pbm->pbm_intmask->phys_mid;
+	lo   = reg[0].phys_lo & pbm->pbm_intmask->phys_lo;
+	irq  = *interrupt & pbm->pbm_intmask->interrupt;
 
 	for (i = 0; i < pbm->num_pbm_intmap; i++) {
 		struct linux_prom_pci_intmap *intmap;
@@ -714,9 +729,11 @@
 	return 0;
 
 success:
-	printk("PCI-IRQ: Routing bus[%2x] slot[%2x] to INO[%02x]\n",
-	       pdev->bus->number, PCI_SLOT(pdev->devfn),
-	       *interrupt);
+	if (pci_irq_verbose)
+		printk("%s: Routing bus[%2x] slot[%2x] to INO[%02x]\n",
+		       pbm->name,
+		       pdev->bus->number, PCI_SLOT(pdev->devfn),
+		       *interrupt);
 	return 1;
 }
 
@@ -727,8 +744,8 @@
 	struct pci_controller_info *p = pbm->parent;
 	unsigned int portid = pbm->portid;
 	unsigned int prom_irq;
-	int prom_node = pcp->prom_node;
-	int err;
+	struct device_node *dp = pcp->prom_node;
+	struct property *prop;
 
 	/* If this is an empty EBUS device, sometimes OBP fails to
 	 * give it a valid fully specified interrupts property.
@@ -739,17 +756,17 @@
 	 */
 	if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    pdev->device == PCI_DEVICE_ID_SUN_EBUS &&
-	    !prom_getchild(prom_node)) {
+	    !dp->child) {
 		pdev->irq = 0;
 		return;
 	}
 
-	err = prom_getproperty(prom_node, "interrupts",
-			       (char *)&prom_irq, sizeof(prom_irq));
-	if (err == 0 || err == -1) {
+	prop = of_find_property(dp, "interrupts", NULL);
+	if (!prop) {
 		pdev->irq = 0;
 		return;
 	}
+	prom_irq = *(unsigned int *) prop->value;
 
 	if (tlb_type != hypervisor) {
 		/* Fully specified already? */
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
index 6c32059..971e2be 100644
--- a/arch/sparc64/kernel/pci_impl.h
+++ b/arch/sparc64/kernel/pci_impl.h
@@ -10,6 +10,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
+#include <asm/prom.h>
 
 extern struct pci_controller_info *pci_controller_root;
 
@@ -19,7 +20,7 @@
 extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
 extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
-				    int prom_node);
+				    struct device_node *prom_node);
 extern void pci_record_assignments(struct pci_pbm_info *pbm,
 				   struct pci_bus *pbus);
 extern void pci_assign_unassigned(struct pci_pbm_info *pbm,
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index d17878b..5b2261e 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -17,6 +17,7 @@
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/starfire.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -276,82 +277,13 @@
 	((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
 			(PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
 
-/* PCI PSYCHO INO number to Sparc PIL level. */
-static unsigned char psycho_pil_table[] = {
-/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
-/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
-/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
-/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
-/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
-/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
-/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
-/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
-/*0x20*/5,		/* SCSI				*/
-/*0x21*/5,		/* Ethernet			*/
-/*0x22*/8,		/* Parallel Port		*/
-/*0x23*/13,		/* Audio Record			*/
-/*0x24*/14,		/* Audio Playback		*/
-/*0x25*/15,		/* PowerFail			*/
-/*0x26*/5,		/* second SCSI			*/
-/*0x27*/11,		/* Floppy			*/
-/*0x28*/5,		/* Spare Hardware		*/
-/*0x29*/9,		/* Keyboard			*/
-/*0x2a*/5,		/* Mouse			*/
-/*0x2b*/12,		/* Serial			*/
-/*0x2c*/10,		/* Timer 0			*/
-/*0x2d*/11,		/* Timer 1			*/
-/*0x2e*/15,		/* Uncorrectable ECC		*/
-/*0x2f*/15,		/* Correctable ECC		*/
-/*0x30*/15,		/* PCI Bus A Error		*/
-/*0x31*/15,		/* PCI Bus B Error		*/
-/*0x32*/15,		/* Power Management		*/
-};
-
-static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
-{
-	int ret;
-
-	ret = psycho_pil_table[ino];
-	if (ret == 0 && pdev == NULL) {
-		ret = 5;
-	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			ret = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			ret = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			ret = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			ret = 10;
-			break;
-
-		default:
-			ret = 5;
-			break;
-		};
-	}
-
-	return ret;
-}
-
 static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
 				     struct pci_dev *pdev,
 				     unsigned int ino)
 {
-	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
-	int pil, inofixup = 0;
+	int inofixup = 0;
 
 	ino &= PCI_IRQ_INO;
 	if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
@@ -367,11 +299,6 @@
 	}
 
 	/* Now build the IRQ bucket. */
-	pil = psycho_ino_to_pil(pdev, ino);
-
-	if (PIL_RESERVED(pil))
-		BUG();
-
 	imap = pbm->controller_regs + imap_off;
 	imap += 4;
 
@@ -382,10 +309,7 @@
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
 
-	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
-	bucket->flags |= IBF_PCI;
-
-	return __irq(bucket);
+	return build_irq(inofixup, iclr, imap);
 }
 
 /* PSYCHO error handling support. */
@@ -1368,11 +1292,12 @@
 #define PSYCHO_MEMSPACE_SIZE	0x07fffffffUL
 
 static void psycho_pbm_init(struct pci_controller_info *p,
-			    int prom_node, int is_pbm_a)
+			    struct device_node *dp, int is_pbm_a)
 {
-	unsigned int busrange[2];
+	unsigned int *busrange;
+	struct property *prop;
 	struct pci_pbm_info *pbm;
-	int err;
+	int len;
 
 	if (is_pbm_a) {
 		pbm = &p->pbm_A;
@@ -1387,10 +1312,14 @@
 	}
 
 	pbm->chip_type = PBM_CHIP_TYPE_PSYCHO;
-	pbm->chip_version =
-		prom_getintdefault(prom_node, "version#", 0);
-	pbm->chip_revision =
-		prom_getintdefault(prom_node, "module-revision#", 0);
+	pbm->chip_version = 0;
+	prop = of_find_property(dp, "version#", NULL);
+	if (prop)
+		pbm->chip_version = *(int *) prop->value;
+	pbm->chip_revision = 0;
+	prop = of_find_property(dp, "module-revision#", NULL);
+	if (prop)
+		pbm->chip_revision = *(int *) prop->value;
 
 	pbm->io_space.end = pbm->io_space.start + PSYCHO_IOSPACE_SIZE;
 	pbm->io_space.flags = IORESOURCE_IO;
@@ -1399,45 +1328,36 @@
 	pbm_register_toplevel_resources(p, pbm);
 
 	pbm->parent = p;
-	pbm->prom_node = prom_node;
-	prom_getstring(prom_node, "name",
-		       pbm->prom_name,
-		       sizeof(pbm->prom_name));
+	pbm->prom_node = dp;
+	pbm->name = dp->full_name;
 
-	err = prom_getproperty(prom_node, "ranges",
-			       (char *)pbm->pbm_ranges,
-			       sizeof(pbm->pbm_ranges));
-	if (err != -1)
+	printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n",
+	       pbm->name,
+	       pbm->chip_version, pbm->chip_revision);
+
+	prop = of_find_property(dp, "ranges", &len);
+	if (prop) {
+		pbm->pbm_ranges = prop->value;
 		pbm->num_pbm_ranges =
-			(err / sizeof(struct linux_prom_pci_ranges));
-	else
+			(len / sizeof(struct linux_prom_pci_ranges));
+	} else {
 		pbm->num_pbm_ranges = 0;
+	}
 
-	err = prom_getproperty(prom_node, "interrupt-map",
-			       (char *)pbm->pbm_intmap,
-			       sizeof(pbm->pbm_intmap));
-	if (err != -1) {
-		pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-		err = prom_getproperty(prom_node, "interrupt-map-mask",
-				       (char *)&pbm->pbm_intmask,
-				       sizeof(pbm->pbm_intmask));
-		if (err == -1) {
-			prom_printf("PSYCHO-PBM: Fatal error, no "
-				    "interrupt-map-mask.\n");
-			prom_halt();
-		}
+	prop = of_find_property(dp, "interrupt-map", &len);
+	if (prop) {
+		pbm->pbm_intmap = prop->value;
+		pbm->num_pbm_intmap =
+			(len / sizeof(struct linux_prom_pci_intmap));
+
+		prop = of_find_property(dp, "interrupt-map-mask", NULL);
+		pbm->pbm_intmask = prop->value;
 	} else {
 		pbm->num_pbm_intmap = 0;
-		memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 	}
 
-	err = prom_getproperty(prom_node, "bus-range",
-			       (char *)&busrange[0],
-			       sizeof(busrange));
-	if (err == 0 || err == -1) {
-		prom_printf("PSYCHO-PBM: Fatal error, no bus-range.\n");
-		prom_halt();
-	}
+	prop = of_find_property(dp, "bus-range", NULL);
+	busrange = prop->value;
 	pbm->pci_first_busno = busrange[0];
 	pbm->pci_last_busno = busrange[1];
 
@@ -1446,20 +1366,24 @@
 
 #define PSYCHO_CONFIGSPACE	0x001000000UL
 
-void psycho_init(int node, char *model_name)
+void psycho_init(struct device_node *dp, char *model_name)
 {
-	struct linux_prom64_registers pr_regs[3];
+	struct linux_prom64_registers *pr_regs;
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
+	struct property *prop;
 	u32 upa_portid;
-	int is_pbm_a, err;
+	int is_pbm_a;
 
-	upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
+	upa_portid = 0xff;
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (prop)
+		upa_portid = *(u32 *) prop->value;
 
 	for(p = pci_controller_root; p; p = p->next) {
 		if (p->pbm_A.portid == upa_portid) {
-			is_pbm_a = (p->pbm_A.prom_node == 0);
-			psycho_pbm_init(p, node, is_pbm_a);
+			is_pbm_a = (p->pbm_A.prom_node == NULL);
+			psycho_pbm_init(p, dp, is_pbm_a);
 			return;
 		}
 	}
@@ -1489,23 +1413,14 @@
 	p->resource_adjust = psycho_resource_adjust;
 	p->pci_ops = &psycho_ops;
 
-	err = prom_getproperty(node, "reg",
-			       (char *)&pr_regs[0],
-			       sizeof(pr_regs));
-	if (err == 0 || err == -1) {
-		prom_printf("PSYCHO: Fatal error, no reg property.\n");
-		prom_halt();
-	}
+	prop = of_find_property(dp, "reg", NULL);
+	pr_regs = prop->value;
 
 	p->pbm_A.controller_regs = pr_regs[2].phys_addr;
 	p->pbm_B.controller_regs = pr_regs[2].phys_addr;
-	printk("PCI: Found PSYCHO, control regs at %016lx\n",
-	       p->pbm_A.controller_regs);
 
 	p->pbm_A.config_space = p->pbm_B.config_space =
 		(pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE);
-	printk("PSYCHO: Shared PCI config space at %016lx\n",
-	       p->pbm_A.config_space);
 
 	/*
 	 * Psycho's PCI MEM space is mapped to a 2GB aligned area, so
@@ -1518,5 +1433,5 @@
 	psycho_iommu_init(p);
 
 	is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
-	psycho_pbm_init(p, node, is_pbm_a);
+	psycho_pbm_init(p, dp, is_pbm_a);
 }
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index f67bb7f..26f194c 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -19,6 +19,7 @@
 #include <asm/irq.h>
 #include <asm/smp.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -523,78 +524,6 @@
 	((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) :  \
 			(SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))
 
-/* PCI SABRE INO number to Sparc PIL level. */
-static unsigned char sabre_pil_table[] = {
-/*0x00*/0, 0, 0, 0,	/* PCI A slot 0  Int A, B, C, D */
-/*0x04*/0, 0, 0, 0,	/* PCI A slot 1  Int A, B, C, D */
-/*0x08*/0, 0, 0, 0,	/* PCI A slot 2  Int A, B, C, D */
-/*0x0c*/0, 0, 0, 0,	/* PCI A slot 3  Int A, B, C, D */
-/*0x10*/0, 0, 0, 0,	/* PCI B slot 0  Int A, B, C, D */
-/*0x14*/0, 0, 0, 0,	/* PCI B slot 1  Int A, B, C, D */
-/*0x18*/0, 0, 0, 0,	/* PCI B slot 2  Int A, B, C, D */
-/*0x1c*/0, 0, 0, 0,	/* PCI B slot 3  Int A, B, C, D */
-/*0x20*/5,		/* SCSI				*/
-/*0x21*/5,		/* Ethernet			*/
-/*0x22*/8,		/* Parallel Port		*/
-/*0x23*/13,		/* Audio Record			*/
-/*0x24*/14,		/* Audio Playback		*/
-/*0x25*/15,		/* PowerFail			*/
-/*0x26*/5,		/* second SCSI			*/
-/*0x27*/11,		/* Floppy			*/
-/*0x28*/5,		/* Spare Hardware		*/
-/*0x29*/9,		/* Keyboard			*/
-/*0x2a*/5,		/* Mouse			*/
-/*0x2b*/12,		/* Serial			*/
-/*0x2c*/10,		/* Timer 0			*/
-/*0x2d*/11,		/* Timer 1			*/
-/*0x2e*/15,		/* Uncorrectable ECC		*/
-/*0x2f*/15,		/* Correctable ECC		*/
-/*0x30*/15,		/* PCI Bus A Error		*/
-/*0x31*/15,		/* PCI Bus B Error		*/
-/*0x32*/15,		/* Power Management		*/
-};
-
-static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
-{
-	int ret;
-
-	if (pdev &&
-	    pdev->vendor == PCI_VENDOR_ID_SUN &&
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
-		return 9;
-
-	ret = sabre_pil_table[ino];
-	if (ret == 0 && pdev == NULL) {
-		ret = 5;
-	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			ret = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			ret = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			ret = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			ret = 10;
-			break;
-
-		default:
-			ret = 5;
-			break;
-		};
-	}
-	return ret;
-}
-
 /* When a device lives behind a bridge deeper in the PCI bus topology
  * than APB, a special sequence must run to make sure all pending DMA
  * transfers at the time of IRQ delivery are visible in the coherency
@@ -602,7 +531,7 @@
  * side of the non-APB bridge, then perform a read of Sabre's DMA
  * write-sync register.
  */
-static void sabre_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
+static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
 {
 	struct pci_dev *pdev = _arg1;
 	unsigned long sync_reg = (unsigned long) _arg2;
@@ -616,10 +545,10 @@
 				    struct pci_dev *pdev,
 				    unsigned int ino)
 {
-	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
-	int pil, inofixup = 0;
+	int inofixup = 0;
+	int virt_irq;
 
 	ino &= PCI_IRQ_INO;
 	if (ino < SABRE_ONBOARD_IRQ_BASE) {
@@ -635,11 +564,6 @@
 	}
 
 	/* Now build the IRQ bucket. */
-	pil = sabre_ino_to_pil(pdev, ino);
-
-	if (PIL_RESERVED(pil))
-		BUG();
-
 	imap = pbm->controller_regs + imap_off;
 	imap += 4;
 
@@ -650,23 +574,23 @@
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
 
-	bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
-	bucket->flags |= IBF_PCI;
+	virt_irq = build_irq(inofixup, iclr, imap);
 
 	if (pdev) {
 		struct pcidev_cookie *pcp = pdev->sysdata;
 
 		if (pdev->bus->number != pcp->pbm->pci_first_busno) {
 			struct pci_controller_info *p = pcp->pbm->parent;
-			struct irq_desc *d = bucket->irq_info;
 
-			d->pre_handler = sabre_wsync_handler;
-			d->pre_handler_arg1 = pdev;
-			d->pre_handler_arg2 = (void *)
-				p->pbm_A.controller_regs + SABRE_WRSYNC;
+			irq_install_pre_handler(virt_irq,
+						sabre_wsync_handler,
+						pdev,
+						(void *)
+						p->pbm_A.controller_regs +
+						SABRE_WRSYNC);
 		}
 	}
-	return __irq(bucket);
+	return virt_irq;
 }
 
 /* SABRE error handling support. */
@@ -1383,34 +1307,36 @@
 					    &pbm->mem_space);
 }
 
-static void sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin)
+static void sabre_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 dma_begin)
 {
 	struct pci_pbm_info *pbm;
-	char namebuf[128];
-	u32 busrange[2];
-	int node, simbas_found;
+	struct device_node *node;
+	struct property *prop;
+	u32 *busrange;
+	int len, simbas_found;
 
 	simbas_found = 0;
-	node = prom_getchild(sabre_node);
-	while ((node = prom_searchsiblings(node, "pci")) != 0) {
-		int err;
-
-		err = prom_getproperty(node, "model", namebuf, sizeof(namebuf));
-		if ((err <= 0) || strncmp(namebuf, "SUNW,simba", err))
+	node = dp->child;
+	while (node != NULL) {
+		if (strcmp(node->name, "pci"))
 			goto next_pci;
 
-		err = prom_getproperty(node, "bus-range",
-				       (char *)&busrange[0], sizeof(busrange));
-		if (err == 0 || err == -1) {
-			prom_printf("APB: Error, cannot get PCI bus-range.\n");
-			prom_halt();
-		}
+		prop = of_find_property(node, "model", NULL);
+		if (!prop || strncmp(prop->value, "SUNW,simba", prop->length))
+			goto next_pci;
 
 		simbas_found++;
+
+		prop = of_find_property(node, "bus-range", NULL);
+		busrange = prop->value;
 		if (busrange[0] == 1)
 			pbm = &p->pbm_B;
 		else
 			pbm = &p->pbm_A;
+
+		pbm->name = node->full_name;
+		printk("%s: SABRE PCI Bus Module\n", pbm->name);
+
 		pbm->chip_type = PBM_CHIP_TYPE_SABRE;
 		pbm->parent = p;
 		pbm->prom_node = node;
@@ -1418,83 +1344,68 @@
 		pbm->pci_first_busno = busrange[0];
 		pbm->pci_last_busno = busrange[1];
 
-		prom_getstring(node, "name", pbm->prom_name, sizeof(pbm->prom_name));
-		err = prom_getproperty(node, "ranges",
-				       (char *)pbm->pbm_ranges,
-				       sizeof(pbm->pbm_ranges));
-		if (err != -1)
+		prop = of_find_property(node, "ranges", &len);
+		if (prop) {
+			pbm->pbm_ranges = prop->value;
 			pbm->num_pbm_ranges =
-				(err / sizeof(struct linux_prom_pci_ranges));
-		else
+				(len / sizeof(struct linux_prom_pci_ranges));
+		} else {
 			pbm->num_pbm_ranges = 0;
+		}
 
-		err = prom_getproperty(node, "interrupt-map",
-				       (char *)pbm->pbm_intmap,
-				       sizeof(pbm->pbm_intmap));
-		if (err != -1) {
-			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-			err = prom_getproperty(node, "interrupt-map-mask",
-					       (char *)&pbm->pbm_intmask,
-					       sizeof(pbm->pbm_intmask));
-			if (err == -1) {
-				prom_printf("APB: Fatal error, no interrupt-map-mask.\n");
-				prom_halt();
-			}
+		prop = of_find_property(node, "interrupt-map", &len);
+		if (prop) {
+			pbm->pbm_intmap = prop->value;
+			pbm->num_pbm_intmap =
+				(len / sizeof(struct linux_prom_pci_intmap));
+
+			prop = of_find_property(node, "interrupt-map-mask",
+						NULL);
+			pbm->pbm_intmask = prop->value;
 		} else {
 			pbm->num_pbm_intmap = 0;
-			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 		}
 
 		pbm_register_toplevel_resources(p, pbm);
 
 	next_pci:
-		node = prom_getsibling(node);
-		if (!node)
-			break;
+		node = node->sibling;
 	}
 	if (simbas_found == 0) {
-		int err;
-
 		/* No APBs underneath, probably this is a hummingbird
 		 * system.
 		 */
 		pbm = &p->pbm_A;
 		pbm->parent = p;
-		pbm->prom_node = sabre_node;
+		pbm->prom_node = dp;
 		pbm->pci_first_busno = p->pci_first_busno;
 		pbm->pci_last_busno = p->pci_last_busno;
 
-		prom_getstring(sabre_node, "name", pbm->prom_name, sizeof(pbm->prom_name));
-		err = prom_getproperty(sabre_node, "ranges",
-				       (char *) pbm->pbm_ranges,
-				       sizeof(pbm->pbm_ranges));
-		if (err != -1)
+		prop = of_find_property(dp, "ranges", &len);
+		if (prop) {
+			pbm->pbm_ranges = prop->value;
 			pbm->num_pbm_ranges =
-				(err / sizeof(struct linux_prom_pci_ranges));
-		else
-			pbm->num_pbm_ranges = 0;
-
-		err = prom_getproperty(sabre_node, "interrupt-map",
-				       (char *) pbm->pbm_intmap,
-				       sizeof(pbm->pbm_intmap));
-
-		if (err != -1) {
-			pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-			err = prom_getproperty(sabre_node, "interrupt-map-mask",
-					       (char *)&pbm->pbm_intmask,
-					       sizeof(pbm->pbm_intmask));
-			if (err == -1) {
-				prom_printf("Hummingbird: Fatal error, no interrupt-map-mask.\n");
-				prom_halt();
-			}
+				(len / sizeof(struct linux_prom_pci_ranges));
 		} else {
-			pbm->num_pbm_intmap = 0;
-			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
+			pbm->num_pbm_ranges = 0;
 		}
 
+		prop = of_find_property(dp, "interrupt-map", &len);
+		if (prop) {
+			pbm->pbm_intmap = prop->value;
+			pbm->num_pbm_intmap =
+				(len / sizeof(struct linux_prom_pci_intmap));
 
-		sprintf(pbm->name, "SABRE%d PBM%c", p->index,
-			(pbm == &p->pbm_A ? 'A' : 'B'));
+			prop = of_find_property(dp, "interrupt-map-mask",
+						NULL);
+			pbm->pbm_intmask = prop->value;
+		} else {
+			pbm->num_pbm_intmap = 0;
+		}
+
+		pbm->name = dp->full_name;
+		printk("%s: SABRE PCI Bus Module\n", pbm->name);
+
 		pbm->io_space.name = pbm->mem_space.name = pbm->name;
 
 		/* Hack up top-level resources. */
@@ -1520,14 +1431,15 @@
 	}
 }
 
-void sabre_init(int pnode, char *model_name)
+void sabre_init(struct device_node *dp, char *model_name)
 {
-	struct linux_prom64_registers pr_regs[2];
+	struct linux_prom64_registers *pr_regs;
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	int tsbsize, err;
-	u32 busrange[2];
-	u32 vdma[2];
+	struct property *prop;
+	int tsbsize;
+	u32 *busrange;
+	u32 *vdma;
 	u32 upa_portid, dma_mask;
 	u64 clear_irq;
 
@@ -1535,22 +1447,21 @@
 	if (!strcmp(model_name, "pci108e,a001"))
 		hummingbird_p = 1;
 	else if (!strcmp(model_name, "SUNW,sabre")) {
-		char compat[64];
+		prop = of_find_property(dp, "compatible", NULL);
+		if (prop) {
+			const char *compat = prop->value;
 
-		if (prom_getproperty(pnode, "compatible",
-				     compat, sizeof(compat)) > 0 &&
-		    !strcmp(compat, "pci108e,a001")) {
-			hummingbird_p = 1;
-		} else {
-			int cpu_node;
+			if (!strcmp(compat, "pci108e,a001"))
+				hummingbird_p = 1;
+		}
+		if (!hummingbird_p) {
+			struct device_node *dp;
 
 			/* Of course, Sun has to encode things a thousand
 			 * different ways, inconsistently.
 			 */
-			cpu_find_by_instance(0, &cpu_node, NULL);
-			if (prom_getproperty(cpu_node, "name",
-					     compat, sizeof(compat)) > 0 &&
-			    !strcmp(compat, "SUNW,UltraSPARC-IIe"))
+			cpu_find_by_instance(0, &dp, NULL);
+			if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe"))
 				hummingbird_p = 1;
 		}
 	}
@@ -1568,7 +1479,10 @@
 	}
 	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
-	upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
+	upa_portid = 0xff;
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (prop)
+		upa_portid = *(u32 *) prop->value;
 
 	p->next = pci_controller_root;
 	pci_controller_root = p;
@@ -1586,13 +1500,9 @@
 	/*
 	 * Map in SABRE register set and report the presence of this SABRE.
 	 */
-	err = prom_getproperty(pnode, "reg",
-			       (char *)&pr_regs[0], sizeof(pr_regs));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get U2P registers "
-			    "from PROM.\n");
-		prom_halt();
-	}
+	
+	prop = of_find_property(dp, "reg", NULL);
+	pr_regs = prop->value;
 
 	/*
 	 * First REG in property is base of entire SABRE register space.
@@ -1600,9 +1510,6 @@
 	p->pbm_A.controller_regs = pr_regs[0].phys_addr;
 	p->pbm_B.controller_regs = pr_regs[0].phys_addr;
 
-	printk("PCI: Found SABRE, main regs at %016lx\n",
-	       p->pbm_A.controller_regs);
-
 	/* Clear interrupts */
 
 	/* PCI first */
@@ -1621,16 +1528,9 @@
 	/* Now map in PCI config space for entire SABRE. */
 	p->pbm_A.config_space = p->pbm_B.config_space =
 		(p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
-	printk("SABRE: Shared PCI config space at %016lx\n",
-	       p->pbm_A.config_space);
 
-	err = prom_getproperty(pnode, "virtual-dma",
-			       (char *)&vdma[0], sizeof(vdma));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get virtual-dma property "
-			    "from PROM.\n");
-		prom_halt();
-	}
+	prop = of_find_property(dp, "virtual-dma", NULL);
+	vdma = prop->value;
 
 	dma_mask = vdma[0];
 	switch(vdma[1]) {
@@ -1654,21 +1554,13 @@
 
 	sabre_iommu_init(p, tsbsize, vdma[0], dma_mask);
 
-	printk("SABRE: DVMA at %08x [%08x]\n", vdma[0], vdma[1]);
-
-	err = prom_getproperty(pnode, "bus-range",
-				       (char *)&busrange[0], sizeof(busrange));
-	if(err == 0 || err == -1) {
-		prom_printf("SABRE: Error, cannot get PCI bus-range "
-			    " from PROM.\n");
-		prom_halt();
-	}
-
+	prop = of_find_property(dp, "bus-range", NULL);
+	busrange = prop->value;
 	p->pci_first_busno = busrange[0];
 	p->pci_last_busno = busrange[1];
 
 	/*
 	 * Look for APB underneath.
 	 */
-	sabre_pbm_init(p, pnode, vdma[0]);
+	sabre_pbm_init(p, dp, vdma[0]);
 }
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 7fe4de0..f16449c 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -16,6 +16,7 @@
 #include <asm/irq.h>
 #include <asm/upa.h>
 #include <asm/pstate.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -232,105 +233,10 @@
 	return SCHIZO_ICLR_BASE + (ino * 8UL);
 }
 
-/* PCI SCHIZO INO number to Sparc PIL level.  This table only matters for
- * INOs which will not have an associated PCI device struct, ie. onboard
- * EBUS devices and PCI controller internal error interrupts.
- */
-static unsigned char schizo_pil_table[] = {
-/*0x00*/0, 0, 0, 0,	/* PCI slot 0  Int A, B, C, D	*/
-/*0x04*/0, 0, 0, 0,	/* PCI slot 1  Int A, B, C, D	*/
-/*0x08*/0, 0, 0, 0,	/* PCI slot 2  Int A, B, C, D	*/
-/*0x0c*/0, 0, 0, 0,	/* PCI slot 3  Int A, B, C, D	*/
-/*0x10*/0, 0, 0, 0,	/* PCI slot 4  Int A, B, C, D	*/
-/*0x14*/0, 0, 0, 0,	/* PCI slot 5  Int A, B, C, D	*/
-/*0x18*/5,		/* SCSI				*/
-/*0x19*/5,		/* second SCSI			*/
-/*0x1a*/0,		/* UNKNOWN			*/
-/*0x1b*/0,		/* UNKNOWN			*/
-/*0x1c*/8,		/* Parallel			*/
-/*0x1d*/5,		/* Ethernet			*/
-/*0x1e*/8,		/* Firewire-1394		*/
-/*0x1f*/9,		/* USB				*/
-/*0x20*/13,		/* Audio Record			*/
-/*0x21*/14,		/* Audio Playback		*/
-/*0x22*/12,		/* Serial			*/
-/*0x23*/5,		/* EBUS I2C 			*/
-/*0x24*/10,		/* RTC Clock			*/
-/*0x25*/11,		/* Floppy			*/
-/*0x26*/0,		/* UNKNOWN			*/
-/*0x27*/0,		/* UNKNOWN			*/
-/*0x28*/0,		/* UNKNOWN			*/
-/*0x29*/0,		/* UNKNOWN			*/
-/*0x2a*/10,		/* UPA 1			*/
-/*0x2b*/10,		/* UPA 2			*/
-/*0x2c*/0,		/* UNKNOWN			*/
-/*0x2d*/0,		/* UNKNOWN			*/
-/*0x2e*/0,		/* UNKNOWN			*/
-/*0x2f*/0,		/* UNKNOWN			*/
-/*0x30*/15,		/* Uncorrectable ECC		*/
-/*0x31*/15,		/* Correctable ECC		*/
-/*0x32*/15,		/* PCI Bus A Error		*/
-/*0x33*/15,		/* PCI Bus B Error		*/
-/*0x34*/15,		/* Safari Bus Error		*/
-/*0x35*/0,		/* Reserved			*/
-/*0x36*/0,		/* Reserved			*/
-/*0x37*/0,		/* Reserved			*/
-/*0x38*/0,		/* Reserved for NewLink		*/
-/*0x39*/0,		/* Reserved for NewLink		*/
-/*0x3a*/0,		/* Reserved for NewLink		*/
-/*0x3b*/0,		/* Reserved for NewLink		*/
-/*0x3c*/0,		/* Reserved for NewLink		*/
-/*0x3d*/0,		/* Reserved for NewLink		*/
-/*0x3e*/0,		/* Reserved for NewLink		*/
-/*0x3f*/0,		/* Reserved for NewLink		*/
-};
-
-static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
-{
-	int ret;
-
-	if (pdev &&
-	    pdev->vendor == PCI_VENDOR_ID_SUN &&
-	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
-		return 9;
-
-	ret = schizo_pil_table[ino];
-	if (ret == 0 && pdev == NULL) {
-		ret = 5;
-	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			ret = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			ret = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			ret = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			ret = 10;
-			break;
-
-		default:
-			ret = 5;
-			break;
-		};
-	}
-
-	return ret;
-}
-
-static void tomatillo_wsync_handler(struct ino_bucket *bucket, void *_arg1, void *_arg2)
+static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2)
 {
 	unsigned long sync_reg = (unsigned long) _arg2;
-	u64 mask = 1UL << (__irq_ino(__irq(bucket)) & IMAP_INO);
+	u64 mask = 1UL << (ino & IMAP_INO);
 	u64 val;
 	int limit;
 
@@ -365,30 +271,33 @@
 	}
 }
 
+static unsigned long schizo_ino_to_iclr(struct pci_pbm_info *pbm,
+					unsigned int ino)
+{
+	ino &= PCI_IRQ_INO;
+	return pbm->pbm_regs + schizo_iclr_offset(ino) + 4;
+}
+
+static unsigned long schizo_ino_to_imap(struct pci_pbm_info *pbm,
+					unsigned int ino)
+{
+	ino &= PCI_IRQ_INO;
+	return pbm->pbm_regs + schizo_imap_offset(ino) + 4;
+}
+
 static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
 				     struct pci_dev *pdev,
 				     unsigned int ino)
 {
-	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
-	unsigned long imap_off, iclr_off;
-	int pil, ign_fixup;
+	int ign_fixup;
+	int virt_irq;
 
 	ino &= PCI_IRQ_INO;
-	imap_off = schizo_imap_offset(ino);
 
 	/* Now build the IRQ bucket. */
-	pil = schizo_ino_to_pil(pdev, ino);
-
-	if (PIL_RESERVED(pil))
-		BUG();
-
-	imap = pbm->pbm_regs + imap_off;
-	imap += 4;
-
-	iclr_off = schizo_iclr_offset(ino);
-	iclr = pbm->pbm_regs + iclr_off;
-	iclr += 4;
+	imap = schizo_ino_to_imap(pbm, ino);
+	iclr = schizo_ino_to_iclr(pbm, ino);
 
 	/* On Schizo, no inofixup occurs.  This is because each
 	 * INO has it's own IMAP register.  On Psycho and Sabre
@@ -405,19 +314,17 @@
 			ign_fixup = (1 << 6);
 	}
 
-	bucket = __bucket(build_irq(pil, ign_fixup, iclr, imap));
-	bucket->flags |= IBF_PCI;
+	virt_irq = build_irq(ign_fixup, iclr, imap);
 
 	if (pdev && pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) {
-		struct irq_desc *p = bucket->irq_info;
-
-		p->pre_handler = tomatillo_wsync_handler;
-		p->pre_handler_arg1 = ((pbm->chip_version <= 4) ?
-				       (void *) 1 : (void *) 0);
-		p->pre_handler_arg2 = (void *) pbm->sync_reg;
+		irq_install_pre_handler(virt_irq,
+					tomatillo_wsync_handler,
+					((pbm->chip_version <= 4) ?
+					 (void *) 1 : (void *) 0),
+					(void *) pbm->sync_reg);
 	}
 
-	return __irq(bucket);
+	return virt_irq;
 }
 
 /* SCHIZO error handling support. */
@@ -458,7 +365,6 @@
 static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
 {
 	struct pci_pbm_info *pbm;
-	struct ino_bucket *bucket;
 	unsigned long iclr;
 
 	/* Do not clear the interrupt for the other PCI bus.
@@ -476,11 +382,11 @@
 	else
 		pbm = &p->pbm_A;
 
-	irq = schizo_irq_build(pbm, NULL,
-			       (pbm->portid << 6) | (irq & IMAP_INO));
-	bucket = __bucket(irq);
-	iclr = bucket->iclr;
+	schizo_irq_build(pbm, NULL,
+			 (pbm->portid << 6) | (irq & IMAP_INO));
 
+	iclr = schizo_ino_to_iclr(pbm,
+				  (pbm->portid << 6) | (irq & IMAP_INO));
 	upa_writel(ICLR_IDLE, iclr);
 }
 
@@ -1225,7 +1131,6 @@
 {
 	struct pci_pbm_info *pbm;
 	unsigned int irq;
-	struct ino_bucket *bucket;
 	u64 tmp, err_mask, err_no_mask;
 
 	/* Build IRQs and register handlers. */
@@ -1237,8 +1142,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
@@ -1250,8 +1154,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_CE_INO) + 4));
 
@@ -1264,8 +1167,8 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_PCIERR_A_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
 
@@ -1278,8 +1181,8 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_PCIERR_B_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
 
@@ -1291,8 +1194,8 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, ((pbm->portid << 6) |
+						 SCHIZO_SERR_INO)));
 	upa_writel(tmp, (pbm->pbm_regs +
 			 schizo_imap_offset(SCHIZO_SERR_INO) + 4));
 
@@ -1363,7 +1266,6 @@
 {
 	struct pci_pbm_info *pbm;
 	unsigned int irq;
-	struct ino_bucket *bucket;
 	u64 tmp, err_mask, err_no_mask;
 
 	/* Build IRQs and register handlers. */
@@ -1375,8 +1277,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_UE_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_UE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_CE_INO);
@@ -1387,8 +1288,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_CE_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_CE_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_PCIERR_A_INO);
@@ -1399,8 +1299,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_A_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_A_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_PCIERR_B_INO);
@@ -1411,8 +1310,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_PCIERR_B_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_PCIERR_B_INO) + 4));
 
 	pbm = pbm_for_ino(p, SCHIZO_SERR_INO);
@@ -1423,8 +1321,7 @@
 			    pbm->name);
 		prom_halt();
 	}
-	bucket = __bucket(irq);
-	tmp = upa_readl(bucket->imap);
+	tmp = upa_readl(schizo_ino_to_imap(pbm, (pbm->portid << 6) | SCHIZO_SERR_INO));
 	upa_writel(tmp, (pbm->pbm_regs + schizo_imap_offset(SCHIZO_SERR_INO) + 4));
 
 	/* Enable UE and CE interrupts for controller. */
@@ -1560,10 +1457,12 @@
 
 	pbm_config_busmastering(&p->pbm_B);
 	p->pbm_B.is_66mhz_capable =
-		prom_getbool(p->pbm_B.prom_node, "66mhz-capable");
+		(of_find_property(p->pbm_B.prom_node, "66mhz-capable", NULL)
+		 != NULL);
 	pbm_config_busmastering(&p->pbm_A);
 	p->pbm_A.is_66mhz_capable =
-		prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
+		(of_find_property(p->pbm_A.prom_node, "66mhz-capable", NULL)
+		 != NULL);
 	pbm_scan_bus(p, &p->pbm_B);
 	pbm_scan_bus(p, &p->pbm_A);
 
@@ -1765,13 +1664,18 @@
 {
 	struct pci_iommu *iommu = pbm->iommu;
 	unsigned long i, tagbase, database;
+	struct property *prop;
 	u32 vdma[2], dma_mask;
 	u64 control;
-	int err, tsbsize;
+	int tsbsize;
 
-	err = prom_getproperty(pbm->prom_node, "virtual-dma",
-			       (char *)&vdma[0], sizeof(vdma));
-	if (err == 0 || err == -1) {
+	prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
+	if (prop) {
+		u32 *val = prop->value;
+
+		vdma[0] = val[0];
+		vdma[1] = val[1];
+	} else {
 		/* No property, use default values. */
 		vdma[0] = 0xc0000000;
 		vdma[1] = 0x40000000;
@@ -1882,6 +1786,7 @@
 
 static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
 {
+	struct property *prop;
 	u64 tmp;
 
 	schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5);
@@ -1895,7 +1800,8 @@
 	    pbm->chip_version >= 0x2)
 		tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
 
-	if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
+	prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL);
+	if (!prop)
 		tmp |= SCHIZO_PCICTRL_PARK;
 	else
 		tmp &= ~SCHIZO_PCICTRL_PARK;
@@ -1935,16 +1841,17 @@
 }
 
 static void schizo_pbm_init(struct pci_controller_info *p,
-			    int prom_node, u32 portid,
+			    struct device_node *dp, u32 portid,
 			    int chip_type)
 {
-	struct linux_prom64_registers pr_regs[4];
-	unsigned int busrange[2];
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+	unsigned int *busrange;
 	struct pci_pbm_info *pbm;
 	const char *chipset_name;
-	u32 ino_bitmap[2];
+	u32 *ino_bitmap;
 	int is_pbm_a;
-	int err;
+	int len;
 
 	switch (chip_type) {
 	case PBM_CHIP_TYPE_TOMATILLO:
@@ -1972,16 +1879,10 @@
 	 * 3) PBM PCI config space
 	 * 4) Ichip regs
 	 */
-	err = prom_getproperty(prom_node, "reg",
-			       (char *)&pr_regs[0],
-			       sizeof(pr_regs));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no reg property.\n",
-			    chipset_name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "reg", NULL);
+	regs = prop->value;
 
-	is_pbm_a = ((pr_regs[0].phys_addr & 0x00700000) == 0x00600000);
+	is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
 
 	if (is_pbm_a)
 		pbm = &p->pbm_A;
@@ -1990,92 +1891,62 @@
 
 	pbm->portid = portid;
 	pbm->parent = p;
-	pbm->prom_node = prom_node;
+	pbm->prom_node = dp;
 	pbm->pci_first_slot = 1;
 
 	pbm->chip_type = chip_type;
-	pbm->chip_version =
-		prom_getintdefault(prom_node, "version#", 0);
-	pbm->chip_revision =
-		prom_getintdefault(prom_node, "module-revision#", 0);
+	pbm->chip_version = 0;
+	prop = of_find_property(dp, "version#", NULL);
+	if (prop)
+		pbm->chip_version = *(int *) prop->value;
+	pbm->chip_revision = 0;
+	prop = of_find_property(dp, "module-revision#", NULL);
+	if (prop)
+		pbm->chip_revision = *(int *) prop->value;
 
-	pbm->pbm_regs = pr_regs[0].phys_addr;
-	pbm->controller_regs = pr_regs[1].phys_addr - 0x10000UL;
+	pbm->pbm_regs = regs[0].phys_addr;
+	pbm->controller_regs = regs[1].phys_addr - 0x10000UL;
 
 	if (chip_type == PBM_CHIP_TYPE_TOMATILLO)
-		pbm->sync_reg = pr_regs[3].phys_addr + 0x1a18UL;
+		pbm->sync_reg = regs[3].phys_addr + 0x1a18UL;
 
-	sprintf(pbm->name,
-		(chip_type == PBM_CHIP_TYPE_TOMATILLO ?
-		 "TOMATILLO%d PBM%c" :
-		 "SCHIZO%d PBM%c"),
-		p->index,
-		(pbm == &p->pbm_A ? 'A' : 'B'));
+	pbm->name = dp->full_name;
 
-	printk("%s: ver[%x:%x], portid %x, "
-	       "cregs[%lx] pregs[%lx]\n",
+	printk("%s: %s PCI Bus Module ver[%x:%x]\n",
 	       pbm->name,
-	       pbm->chip_version, pbm->chip_revision,
-	       pbm->portid,
-	       pbm->controller_regs,
-	       pbm->pbm_regs);
+	       (chip_type == PBM_CHIP_TYPE_TOMATILLO ?
+		"TOMATILLO" : "SCHIZO"),
+	       pbm->chip_version, pbm->chip_revision);
 
 	schizo_pbm_hw_init(pbm);
 
-	prom_getstring(prom_node, "name",
-		       pbm->prom_name,
-		       sizeof(pbm->prom_name));
-
-	err = prom_getproperty(prom_node, "ranges",
-			       (char *) pbm->pbm_ranges,
-			       sizeof(pbm->pbm_ranges));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no ranges property.\n",
-			    pbm->name);
-		prom_halt();
-	}
-
+	prop = of_find_property(dp, "ranges", &len);
+	pbm->pbm_ranges = prop->value;
 	pbm->num_pbm_ranges =
-		(err / sizeof(struct linux_prom_pci_ranges));
+		(len / sizeof(struct linux_prom_pci_ranges));
 
 	schizo_determine_mem_io_space(pbm);
 	pbm_register_toplevel_resources(p, pbm);
 
-	err = prom_getproperty(prom_node, "interrupt-map",
-			       (char *)pbm->pbm_intmap,
-			       sizeof(pbm->pbm_intmap));
-	if (err != -1) {
-		pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-		err = prom_getproperty(prom_node, "interrupt-map-mask",
-				       (char *)&pbm->pbm_intmask,
-				       sizeof(pbm->pbm_intmask));
-		if (err == -1) {
-			prom_printf("%s: Fatal error, no "
-				    "interrupt-map-mask.\n", pbm->name);
-			prom_halt();
-		}
+	prop = of_find_property(dp, "interrupt-map", &len);
+	if (prop) {
+		pbm->pbm_intmap = prop->value;
+		pbm->num_pbm_intmap =
+			(len / sizeof(struct linux_prom_pci_intmap));
+
+		prop = of_find_property(dp, "interrupt-map-mask", NULL);
+		pbm->pbm_intmask = prop->value;
 	} else {
 		pbm->num_pbm_intmap = 0;
-		memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 	}
 
-	err = prom_getproperty(prom_node, "ino-bitmap",
-			       (char *) &ino_bitmap[0],
-			       sizeof(ino_bitmap));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no ino-bitmap.\n", pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "ino-bitmap", NULL);
+	ino_bitmap = prop->value;
 	pbm->ino_bitmap = (((u64)ino_bitmap[1] << 32UL) |
 			   ((u64)ino_bitmap[0] <<  0UL));
 
-	err = prom_getproperty(prom_node, "bus-range",
-			       (char *)&busrange[0],
-			       sizeof(busrange));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "bus-range", NULL);
+	busrange = prop->value;
 	pbm->pci_first_busno = busrange[0];
 	pbm->pci_last_busno = busrange[1];
 
@@ -2093,16 +1964,20 @@
 	return (x == y);
 }
 
-static void __schizo_init(int node, char *model_name, int chip_type)
+static void __schizo_init(struct device_node *dp, char *model_name, int chip_type)
 {
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
+	struct property *prop;
 	int is_pbm_a;
 	u32 portid;
 
-	portid = prom_getintdefault(node, "portid", 0xff);
+	portid = 0xff;
+	prop = of_find_property(dp, "portid", NULL);
+	if (prop)
+		portid = *(u32 *) prop->value;
 
-	for(p = pci_controller_root; p; p = p->next) {
+	for (p = pci_controller_root; p; p = p->next) {
 		struct pci_pbm_info *pbm;
 
 		if (p->pbm_A.prom_node && p->pbm_B.prom_node)
@@ -2113,8 +1988,8 @@
 		       &p->pbm_B);
 
 		if (portid_compare(pbm->portid, portid, chip_type)) {
-			is_pbm_a = (p->pbm_A.prom_node == 0);
-			schizo_pbm_init(p, node, portid, chip_type);
+			is_pbm_a = (p->pbm_A.prom_node == NULL);
+			schizo_pbm_init(p, dp, portid, chip_type);
 			return;
 		}
 	}
@@ -2155,20 +2030,20 @@
 	/* Like PSYCHO we have a 2GB aligned area for memory space. */
 	pci_memspace_mask = 0x7fffffffUL;
 
-	schizo_pbm_init(p, node, portid, chip_type);
+	schizo_pbm_init(p, dp, portid, chip_type);
 }
 
-void schizo_init(int node, char *model_name)
+void schizo_init(struct device_node *dp, char *model_name)
 {
-	__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO);
+	__schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO);
 }
 
-void schizo_plus_init(int node, char *model_name)
+void schizo_plus_init(struct device_node *dp, char *model_name)
 {
-	__schizo_init(node, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
+	__schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS);
 }
 
-void tomatillo_init(int node, char *model_name)
+void tomatillo_init(struct device_node *dp, char *model_name)
 {
-	__schizo_init(node, model_name, PBM_CHIP_TYPE_TOMATILLO);
+	__schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO);
 }
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 0c08952..b69e227 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -18,6 +18,7 @@
 #include <asm/pstate.h>
 #include <asm/oplib.h>
 #include <asm/hypervisor.h>
+#include <asm/prom.h>
 
 #include "pci_impl.h"
 #include "iommu_common.h"
@@ -646,35 +647,37 @@
 /* Recursively descend into the OBP device tree, rooted at toplevel_node,
  * looking for a PCI device matching bus and devfn.
  */
-static int obp_find(struct linux_prom_pci_registers *pregs, int toplevel_node, unsigned int bus, unsigned int devfn)
+static int obp_find(struct device_node *toplevel_node, unsigned int bus, unsigned int devfn)
 {
-	toplevel_node = prom_getchild(toplevel_node);
+	toplevel_node = toplevel_node->child;
 
-	while (toplevel_node != 0) {
-		int ret = obp_find(pregs, toplevel_node, bus, devfn);
+	while (toplevel_node != NULL) {
+		struct linux_prom_pci_registers *regs;
+		struct property *prop;
+		int ret;
 
+		ret = obp_find(toplevel_node, bus, devfn);
 		if (ret != 0)
 			return ret;
 
-		ret = prom_getproperty(toplevel_node, "reg", (char *) pregs,
-				       sizeof(*pregs) * PROMREG_MAX);
-		if (ret == 0 || ret == -1)
+		prop = of_find_property(toplevel_node, "reg", NULL);
+		if (!prop)
 			goto next_sibling;
 
-		if (((pregs[0].phys_hi >> 16) & 0xff) == bus &&
-		    ((pregs[0].phys_hi >> 8) & 0xff) == devfn)
+		regs = prop->value;
+		if (((regs->phys_hi >> 16) & 0xff) == bus &&
+		    ((regs->phys_hi >> 8) & 0xff) == devfn)
 			break;
 
 	next_sibling:
-		toplevel_node = prom_getsibling(toplevel_node);
+		toplevel_node = toplevel_node->sibling;
 	}
 
-	return toplevel_node;
+	return toplevel_node != NULL;
 }
 
 static int pdev_htab_populate(struct pci_pbm_info *pbm)
 {
-	struct linux_prom_pci_registers pr[PROMREG_MAX];
 	u32 devhandle = pbm->devhandle;
 	unsigned int bus;
 
@@ -685,7 +688,7 @@
 			unsigned int device = PCI_SLOT(devfn);
 			unsigned int func = PCI_FUNC(devfn);
 
-			if (obp_find(pr, pbm->prom_node, bus, devfn)) {
+			if (obp_find(pbm->prom_node, bus, devfn)) {
 				int err = pdev_htab_add(devhandle, bus,
 							device, func);
 				if (err)
@@ -811,8 +814,7 @@
 	pci_fixup_host_bridge_self(pbm->pci_bus);
 	pbm->pci_bus->self->sysdata = cookie;
 #endif
-	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
-				pbm->prom_node);
+	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
 	pci_fixup_irq(pbm, pbm->pci_bus);
@@ -822,15 +824,18 @@
 
 static void pci_sun4v_scan_bus(struct pci_controller_info *p)
 {
-	if (p->pbm_A.prom_node) {
-		p->pbm_A.is_66mhz_capable =
-			prom_getbool(p->pbm_A.prom_node, "66mhz-capable");
+	struct property *prop;
+	struct device_node *dp;
+
+	if ((dp = p->pbm_A.prom_node) != NULL) {
+		prop = of_find_property(dp, "66mhz-capable", NULL);
+		p->pbm_A.is_66mhz_capable = (prop != NULL);
 
 		pbm_scan_bus(p, &p->pbm_A);
 	}
-	if (p->pbm_B.prom_node) {
-		p->pbm_B.is_66mhz_capable =
-			prom_getbool(p->pbm_B.prom_node, "66mhz-capable");
+	if ((dp = p->pbm_B.prom_node) != NULL) {
+		prop = of_find_property(dp, "66mhz-capable", NULL);
+		p->pbm_B.is_66mhz_capable = (prop != NULL);
 
 		pbm_scan_bus(p, &p->pbm_B);
 	}
@@ -843,38 +848,8 @@
 					unsigned int devino)
 {
 	u32 devhandle = pbm->devhandle;
-	int pil;
 
-	pil = 5;
-	if (pdev) {
-		switch ((pdev->class >> 16) & 0xff) {
-		case PCI_BASE_CLASS_STORAGE:
-			pil = 5;
-			break;
-
-		case PCI_BASE_CLASS_NETWORK:
-			pil = 6;
-			break;
-
-		case PCI_BASE_CLASS_DISPLAY:
-			pil = 9;
-			break;
-
-		case PCI_BASE_CLASS_MULTIMEDIA:
-		case PCI_BASE_CLASS_MEMORY:
-		case PCI_BASE_CLASS_BRIDGE:
-		case PCI_BASE_CLASS_SERIAL:
-			pil = 10;
-			break;
-
-		default:
-			pil = 5;
-			break;
-		};
-	}
-	BUG_ON(PIL_RESERVED(pil));
-
-	return sun4v_build_irq(devhandle, devino, pil, IBF_PCI);
+	return sun4v_build_irq(devhandle, devino);
 }
 
 static void pci_sun4v_base_address_update(struct pci_dev *pdev, int resource)
@@ -1012,8 +987,13 @@
 					     HV_PCI_TSBID(0, i),
 					     &io_attrs, &ra);
 		if (ret == HV_EOK) {
-			cnt++;
-			__set_bit(i, arena->map);
+			if (page_in_phys_avail(ra)) {
+				pci_sun4v_iommu_demap(devhandle,
+						      HV_PCI_TSBID(0, i), 1);
+			} else {
+				cnt++;
+				__set_bit(i, arena->map);
+			}
 		}
 	}
 
@@ -1023,13 +1003,18 @@
 static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
 {
 	struct pci_iommu *iommu = pbm->iommu;
+	struct property *prop;
 	unsigned long num_tsb_entries, sz;
 	u32 vdma[2], dma_mask, dma_offset;
-	int err, tsbsize;
+	int tsbsize;
 
-	err = prom_getproperty(pbm->prom_node, "virtual-dma",
-			       (char *)&vdma[0], sizeof(vdma));
-	if (err == 0 || err == -1) {
+	prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
+	if (prop) {
+		u32 *val = prop->value;
+
+		vdma[0] = val[0];
+		vdma[1] = val[1];
+	} else {
 		/* No property, use default values. */
 		vdma[0] = 0x80000000;
 		vdma[1] = 0x80000000;
@@ -1081,34 +1066,30 @@
 	iommu->arena.limit = num_tsb_entries;
 
 	sz = probe_existing_entries(pbm, iommu);
-
-	printk("%s: TSB entries [%lu], existing mapings [%lu]\n",
-	       pbm->name, num_tsb_entries, sz);
+	if (sz)
+		printk("%s: Imported %lu TSB entries from OBP\n",
+		       pbm->name, sz);
 }
 
 static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
 {
-	unsigned int busrange[2];
-	int prom_node = pbm->prom_node;
-	int err;
+	struct property *prop;
+	unsigned int *busrange;
 
-	err = prom_getproperty(prom_node, "bus-range",
-			       (char *)&busrange[0],
-			       sizeof(busrange));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no bus-range.\n", pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(pbm->prom_node, "bus-range", NULL);
+
+	busrange = prop->value;
 
 	pbm->pci_first_busno = busrange[0];
 	pbm->pci_last_busno = busrange[1];
 
 }
 
-static void pci_sun4v_pbm_init(struct pci_controller_info *p, int prom_node, u32 devhandle)
+static void pci_sun4v_pbm_init(struct pci_controller_info *p, struct device_node *dp, u32 devhandle)
 {
 	struct pci_pbm_info *pbm;
-	int err, i;
+	struct property *prop;
+	int len, i;
 
 	if (devhandle & 0x40)
 		pbm = &p->pbm_B;
@@ -1116,32 +1097,19 @@
 		pbm = &p->pbm_A;
 
 	pbm->parent = p;
-	pbm->prom_node = prom_node;
+	pbm->prom_node = dp;
 	pbm->pci_first_slot = 1;
 
 	pbm->devhandle = devhandle;
 
-	sprintf(pbm->name, "SUN4V-PCI%d PBM%c",
-		p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
+	pbm->name = dp->full_name;
 
-	printk("%s: devhandle[%x] prom_node[%x:%x]\n",
-	       pbm->name, pbm->devhandle,
-	       pbm->prom_node, prom_getchild(pbm->prom_node));
+	printk("%s: SUN4V PCI Bus Module\n", pbm->name);
 
-	prom_getstring(prom_node, "name",
-		       pbm->prom_name, sizeof(pbm->prom_name));
-
-	err = prom_getproperty(prom_node, "ranges",
-			       (char *) pbm->pbm_ranges,
-			       sizeof(pbm->pbm_ranges));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no ranges property.\n",
-			    pbm->name);
-		prom_halt();
-	}
-
+	prop = of_find_property(dp, "ranges", &len);
+	pbm->pbm_ranges = prop->value;
 	pbm->num_pbm_ranges =
-		(err / sizeof(struct linux_prom_pci_ranges));
+		(len / sizeof(struct linux_prom_pci_ranges));
 
 	/* Mask out the top 8 bits of the ranges, leaving the real
 	 * physical address.
@@ -1152,24 +1120,13 @@
 	pci_sun4v_determine_mem_io_space(pbm);
 	pbm_register_toplevel_resources(p, pbm);
 
-	err = prom_getproperty(prom_node, "interrupt-map",
-			       (char *)pbm->pbm_intmap,
-			       sizeof(pbm->pbm_intmap));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no interrupt-map property.\n",
-			    pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "interrupt-map", &len);
+	pbm->pbm_intmap = prop->value;
+	pbm->num_pbm_intmap =
+		(len / sizeof(struct linux_prom_pci_intmap));
 
-	pbm->num_pbm_intmap = (err / sizeof(struct linux_prom_pci_intmap));
-	err = prom_getproperty(prom_node, "interrupt-map-mask",
-			       (char *)&pbm->pbm_intmask,
-			       sizeof(pbm->pbm_intmask));
-	if (err == 0 || err == -1) {
-		prom_printf("%s: Fatal error, no interrupt-map-mask.\n",
-			    pbm->name);
-		prom_halt();
-	}
+	prop = of_find_property(dp, "interrupt-map-mask", NULL);
+	pbm->pbm_intmask = prop->value;
 
 	pci_sun4v_get_bus_range(pbm);
 	pci_sun4v_iommu_init(pbm);
@@ -1177,16 +1134,19 @@
 	pdev_htab_populate(pbm);
 }
 
-void sun4v_pci_init(int node, char *model_name)
+void sun4v_pci_init(struct device_node *dp, char *model_name)
 {
 	struct pci_controller_info *p;
 	struct pci_iommu *iommu;
-	struct linux_prom64_registers regs;
+	struct property *prop;
+	struct linux_prom64_registers *regs;
 	u32 devhandle;
 	int i;
 
-	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
-	devhandle = (regs.phys_addr >> 32UL) & 0x0fffffff;
+	prop = of_find_property(dp, "reg", NULL);
+	regs = prop->value;
+
+	devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff;
 
 	for (p = pci_controller_root; p; p = p->next) {
 		struct pci_pbm_info *pbm;
@@ -1199,7 +1159,7 @@
 		       &p->pbm_B);
 
 		if (pbm->devhandle == (devhandle ^ 0x40)) {
-			pci_sun4v_pbm_init(p, node, devhandle);
+			pci_sun4v_pbm_init(p, dp, devhandle);
 			return;
 		}
 	}
@@ -1250,7 +1210,7 @@
 	 */
 	pci_memspace_mask = 0x7fffffffUL;
 
-	pci_sun4v_pbm_init(p, node, devhandle);
+	pci_sun4v_pbm_init(p, dp, devhandle);
 	return;
 
 fatal_memory_error:
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c
index 30bcaf5..9496c77 100644
--- a/arch/sparc64/kernel/power.c
+++ b/arch/sparc64/kernel/power.c
@@ -105,76 +105,25 @@
 	return 0;
 }
 
-static int __init has_button_interrupt(unsigned int irq, int prom_node)
+static int __init has_button_interrupt(unsigned int irq, struct device_node *dp)
 {
 	if (irq == PCI_IRQ_NONE)
 		return 0;
-	if (!prom_node_has_property(prom_node, "button"))
+	if (!of_find_property(dp, "button", NULL))
 		return 0;
 
 	return 1;
 }
 
-static int __init power_probe_ebus(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
+static void __devinit power_probe_common(struct of_device *dev, struct resource *res, unsigned int irq)
 {
-	struct linux_ebus *ebus;
-	struct linux_ebus_device *edev;
-
-	for_each_ebus(ebus) {
-		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "power")) {
-				*resp = &edev->resource[0];
-				*irq_p = edev->irqs[0];
-				*prom_node_p = edev->prom_node;
-				return 0;
-			}
-		}
-	}
-	return -ENODEV;
-}
-
-static int __init power_probe_isa(struct resource **resp, unsigned int *irq_p, int *prom_node_p)
-{
-	struct sparc_isa_bridge *isa_bus;
-	struct sparc_isa_device *isa_dev;
-
-	for_each_isa(isa_bus) {
-		for_each_isadev(isa_dev, isa_bus) {
-			if (!strcmp(isa_dev->prom_name, "power")) {
-				*resp = &isa_dev->resource;
-				*irq_p = isa_dev->irq;
-				*prom_node_p = isa_dev->prom_node;
-				return 0;
-			}
-		}
-	}
-	return -ENODEV;
-}
-
-void __init power_init(void)
-{
-	struct resource *res = NULL;
-	unsigned int irq;
-	int prom_node;
-	static int invoked;
-
-	if (invoked)
-		return;
-	invoked = 1;
-
-	if (!power_probe_ebus(&res, &irq, &prom_node))
-		goto found;
-
-	if (!power_probe_isa(&res, &irq, &prom_node))
-		goto found;
-
-	return;
-
-found:
 	power_reg = ioremap(res->start, 0x4);
+
 	printk("power: Control reg at %p ... ", power_reg);
+
 	poweroff_method = machine_halt;  /* able to use the standard halt */
-	if (has_button_interrupt(irq, prom_node)) {
+
+	if (has_button_interrupt(irq, dev->node)) {
 		if (kernel_thread(powerd, NULL, CLONE_FS) < 0) {
 			printk("Failed to start power daemon.\n");
 			return;
@@ -188,4 +137,52 @@
 		printk("not using powerd.\n");
 	}
 }
+
+static struct of_device_id power_match[] = {
+	{
+		.name = "power",
+	},
+	{},
+};
+
+static int __devinit ebus_power_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
+	struct resource *res = &edev->resource[0];
+	unsigned int irq = edev->irqs[0];
+
+	power_probe_common(dev, res,irq);
+
+	return 0;
+}
+
+static struct of_platform_driver ebus_power_driver = {
+	.name		= "power",
+	.match_table	= power_match,
+	.probe		= ebus_power_probe,
+};
+
+static int __devinit isa_power_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sparc_isa_device *idev = to_isa_device(&dev->dev);
+	struct resource *res = &idev->resource;
+	unsigned int irq = idev->irq;
+
+	power_probe_common(dev, res,irq);
+
+	return 0;
+}
+
+static struct of_platform_driver isa_power_driver = {
+	.name		= "power",
+	.match_table	= power_match,
+	.probe		= isa_power_probe,
+};
+
+void __init power_init(void)
+{
+	of_register_driver(&ebus_power_driver, &ebus_bus_type);
+	of_register_driver(&isa_power_driver, &isa_bus_type);
+	return;
+}
 #endif /* CONFIG_PCI */
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
new file mode 100644
index 0000000..8e87e7e
--- /dev/null
+++ b/arch/sparc64/kernel/prom.c
@@ -0,0 +1,721 @@
+/*
+ * Procedures for creating, accessing and interpreting the device tree.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ * 
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com 
+ *
+ *  Adapted for sparc64 by David S. Miller davem@davemloft.net
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+
+#include <asm/prom.h>
+#include <asm/oplib.h>
+
+static struct device_node *allnodes;
+
+/* use when traversing tree through the allnext, child, sibling,
+ * or parent members of struct device_node.
+ */
+static DEFINE_RWLOCK(devtree_lock);
+
+int of_device_is_compatible(struct device_node *device, const char *compat)
+{
+	const char* cp;
+	int cplen, l;
+
+	cp = (char *) of_get_property(device, "compatible", &cplen);
+	if (cp == NULL)
+		return 0;
+	while (cplen > 0) {
+		if (strncmp(cp, compat, strlen(compat)) == 0)
+			return 1;
+		l = strlen(cp) + 1;
+		cp += l;
+		cplen -= l;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(of_device_is_compatible);
+
+struct device_node *of_get_parent(const struct device_node *node)
+{
+	struct device_node *np;
+
+	if (!node)
+		return NULL;
+
+	np = node->parent;
+
+	return np;
+}
+EXPORT_SYMBOL(of_get_parent);
+
+struct device_node *of_get_next_child(const struct device_node *node,
+	struct device_node *prev)
+{
+	struct device_node *next;
+
+	next = prev ? prev->sibling : node->child;
+	for (; next != 0; next = next->sibling) {
+		break;
+	}
+
+	return next;
+}
+EXPORT_SYMBOL(of_get_next_child);
+
+struct device_node *of_find_node_by_path(const char *path)
+{
+	struct device_node *np = allnodes;
+
+	for (; np != 0; np = np->allnext) {
+		if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_path);
+
+struct device_node *of_find_node_by_phandle(phandle handle)
+{
+	struct device_node *np;
+
+	for (np = allnodes; np != 0; np = np->allnext)
+		if (np->node == handle)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_phandle);
+
+struct device_node *of_find_node_by_name(struct device_node *from,
+	const char *name)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != NULL; np = np->allnext)
+		if (np->name != NULL && strcmp(np->name, name) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_name);
+
+struct device_node *of_find_node_by_type(struct device_node *from,
+	const char *type)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext)
+		if (np->type != 0 && strcmp(np->type, type) == 0)
+			break;
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_type);
+
+struct device_node *of_find_compatible_node(struct device_node *from,
+	const char *type, const char *compatible)
+{
+	struct device_node *np;
+
+	np = from ? from->allnext : allnodes;
+	for (; np != 0; np = np->allnext) {
+		if (type != NULL
+		    && !(np->type != 0 && strcmp(np->type, type) == 0))
+			continue;
+		if (of_device_is_compatible(np, compatible))
+			break;
+	}
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_compatible_node);
+
+struct property *of_find_property(struct device_node *np, const char *name,
+				  int *lenp)
+{
+	struct property *pp;
+
+	for (pp = np->properties; pp != 0; pp = pp->next) {
+		if (strcmp(pp->name, name) == 0) {
+			if (lenp != 0)
+				*lenp = pp->length;
+			break;
+		}
+	}
+	return pp;
+}
+EXPORT_SYMBOL(of_find_property);
+
+/*
+ * Find a property with a given name for a given node
+ * and return the value.
+ */
+void *of_get_property(struct device_node *np, const char *name, int *lenp)
+{
+	struct property *pp = of_find_property(np,name,lenp);
+	return pp ? pp->value : NULL;
+}
+EXPORT_SYMBOL(of_get_property);
+
+int of_getintprop_default(struct device_node *np, const char *name, int def)
+{
+	struct property *prop;
+	int len;
+
+	prop = of_find_property(np, name, &len);
+	if (!prop || len != 4)
+		return def;
+
+	return *(int *) prop->value;
+}
+EXPORT_SYMBOL(of_getintprop_default);
+
+int of_set_property(struct device_node *dp, const char *name, void *val, int len)
+{
+	struct property **prevp;
+	void *new_val;
+	int err;
+
+	new_val = kmalloc(len, GFP_KERNEL);
+	if (!new_val)
+		return -ENOMEM;
+
+	memcpy(new_val, val, len);
+
+	err = -ENODEV;
+
+	write_lock(&devtree_lock);
+	prevp = &dp->properties;
+	while (*prevp) {
+		struct property *prop = *prevp;
+
+		if (!strcmp(prop->name, name)) {
+			void *old_val = prop->value;
+			int ret;
+
+			ret = prom_setprop(dp->node, name, val, len);
+			err = -EINVAL;
+			if (ret >= 0) {
+				prop->value = new_val;
+				prop->length = len;
+
+				if (OF_IS_DYNAMIC(prop))
+					kfree(old_val);
+
+				OF_MARK_DYNAMIC(prop);
+
+				err = 0;
+			}
+			break;
+		}
+		prevp = &(*prevp)->next;
+	}
+	write_unlock(&devtree_lock);
+
+	/* XXX Upate procfs if necessary... */
+
+	return err;
+}
+EXPORT_SYMBOL(of_set_property);
+
+static unsigned int prom_early_allocated;
+
+static void * __init prom_early_alloc(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	prom_early_allocated += size;
+
+	return ret;
+}
+
+static int is_root_node(const struct device_node *dp)
+{
+	if (!dp)
+		return 0;
+
+	return (dp->parent == NULL);
+}
+
+/* The following routines deal with the black magic of fully naming a
+ * node.
+ *
+ * Certain well known named nodes are just the simple name string.
+ *
+ * Actual devices have an address specifier appended to the base name
+ * string, like this "foo@addr".  The "addr" can be in any number of
+ * formats, and the platform plus the type of the node determine the
+ * format and how it is constructed.
+ *
+ * For children of the ROOT node, the naming convention is fixed and
+ * determined by whether this is a sun4u or sun4v system.
+ *
+ * For children of other nodes, it is bus type specific.  So
+ * we walk up the tree until we discover a "device_type" property
+ * we recognize and we go from there.
+ *
+ * As an example, the boot device on my workstation has a full path:
+ *
+ *	/pci@1e,600000/ide@d/disk@0,0:c
+ */
+static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *rprop;
+	u32 high_bits, low_bits, type;
+
+	rprop = of_find_property(dp, "reg", NULL);
+	if (!rprop)
+		return;
+
+	regs = rprop->value;
+	if (!is_root_node(dp->parent)) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			(unsigned int) (regs->phys_addr >> 32UL),
+			(unsigned int) (regs->phys_addr & 0xffffffffUL));
+		return;
+	}
+
+	type = regs->phys_addr >> 60UL;
+	high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL;
+	low_bits = (regs->phys_addr & 0xffffffffUL);
+
+	if (type == 0 || type == 8) {
+		const char *prefix = (type == 0) ? "m" : "i";
+
+		if (low_bits)
+			sprintf(tmp_buf, "%s@%s%x,%x",
+				dp->name, prefix,
+				high_bits, low_bits);
+		else
+			sprintf(tmp_buf, "%s@%s%x",
+				dp->name,
+				prefix,
+				high_bits);
+	} else if (type == 12) {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name, high_bits);
+	}
+}
+
+static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	if (!is_root_node(dp->parent)) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			(unsigned int) (regs->phys_addr >> 32UL),
+			(unsigned int) (regs->phys_addr & 0xffffffffUL));
+		return;
+	}
+
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (!prop)
+		prop = of_find_property(dp, "portid", NULL);
+	if (prop) {
+		unsigned long mask = 0xffffffffUL;
+
+		if (tlb_type >= cheetah)
+			mask = 0x7fffff;
+
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			*(u32 *)prop->value,
+			(unsigned int) (regs->phys_addr & mask));
+	}
+}
+
+/* "name@slot,offset"  */
+static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		regs->which_io,
+		regs->phys_addr);
+}
+
+/* "name@devnum[,func]" */
+static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom_pci_registers *regs;
+	struct property *prop;
+	unsigned int devfn;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+	devfn = (regs->phys_hi >> 8) & 0xff;
+	if (devfn & 0x07) {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name,
+			devfn >> 3,
+			devfn & 0x07);
+	} else {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name,
+			devfn >> 3);
+	}
+}
+
+/* "name@UPA_PORTID,offset" */
+static void __init upa_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	prop = of_find_property(dp, "upa-portid", NULL);
+	if (!prop)
+		return;
+
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		*(u32 *) prop->value,
+		(unsigned int) (regs->phys_addr & 0xffffffffUL));
+}
+
+/* "name@reg" */
+static void __init vdev_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	sprintf(tmp_buf, "%s@%x", dp->name, *regs);
+}
+
+/* "name@addrhi,addrlo" */
+static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct linux_prom64_registers *regs;
+	struct property *prop;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name,
+		(unsigned int) (regs->phys_addr >> 32UL),
+		(unsigned int) (regs->phys_addr & 0xffffffffUL));
+}
+
+/* "name@bus,addr" */
+static void __init i2c_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	/* This actually isn't right... should look at the #address-cells
+	 * property of the i2c bus node etc. etc.
+	 */
+	sprintf(tmp_buf, "%s@%x,%x",
+		dp->name, regs[0], regs[1]);
+}
+
+/* "name@reg0[,reg1]" */
+static void __init usb_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	if (prop->length == sizeof(u32) || regs[1] == 1) {
+		sprintf(tmp_buf, "%s@%x",
+			dp->name, regs[0]);
+	} else {
+		sprintf(tmp_buf, "%s@%x,%x",
+			dp->name, regs[0], regs[1]);
+	}
+}
+
+/* "name@reg0reg1[,reg2reg3]" */
+static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct property *prop;
+	u32 *regs;
+
+	prop = of_find_property(dp, "reg", NULL);
+	if (!prop)
+		return;
+
+	regs = prop->value;
+
+	if (regs[2] || regs[3]) {
+		sprintf(tmp_buf, "%s@%08x%08x,%04x%08x",
+			dp->name, regs[0], regs[1], regs[2], regs[3]);
+	} else {
+		sprintf(tmp_buf, "%s@%08x%08x",
+			dp->name, regs[0], regs[1]);
+	}
+}
+
+static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
+{
+	struct device_node *parent = dp->parent;
+
+	if (parent != NULL) {
+		if (!strcmp(parent->type, "pci") ||
+		    !strcmp(parent->type, "pciex"))
+			return pci_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "sbus"))
+			return sbus_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "upa"))
+			return upa_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "ebus"))
+			return ebus_path_component(dp, tmp_buf);
+		if (!strcmp(parent->name, "usb") ||
+		    !strcmp(parent->name, "hub"))
+			return usb_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "i2c"))
+			return i2c_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "firewire"))
+			return ieee1394_path_component(dp, tmp_buf);
+		if (!strcmp(parent->type, "virtual-devices"))
+			return vdev_path_component(dp, tmp_buf);
+
+		/* "isa" is handled with platform naming */
+	}
+
+	/* Use platform naming convention.  */
+	if (tlb_type == hypervisor)
+		return sun4v_path_component(dp, tmp_buf);
+	else
+		return sun4u_path_component(dp, tmp_buf);
+}
+
+static char * __init build_path_component(struct device_node *dp)
+{
+	char tmp_buf[64], *n;
+
+	tmp_buf[0] = '\0';
+	__build_path_component(dp, tmp_buf);
+	if (tmp_buf[0] == '\0')
+		strcpy(tmp_buf, dp->name);
+
+	n = prom_early_alloc(strlen(tmp_buf) + 1);
+	strcpy(n, tmp_buf);
+
+	return n;
+}
+
+static char * __init build_full_name(struct device_node *dp)
+{
+	int len, ourlen, plen;
+	char *n;
+
+	plen = strlen(dp->parent->full_name);
+	ourlen = strlen(dp->path_component_name);
+	len = ourlen + plen + 2;
+
+	n = prom_early_alloc(len);
+	strcpy(n, dp->parent->full_name);
+	if (!is_root_node(dp->parent)) {
+		strcpy(n + plen, "/");
+		plen++;
+	}
+	strcpy(n + plen, dp->path_component_name);
+
+	return n;
+}
+
+static unsigned int unique_id;
+
+static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
+{
+	static struct property *tmp = NULL;
+	struct property *p;
+
+	if (tmp) {
+		p = tmp;
+		memset(p, 0, sizeof(*p) + 32);
+		tmp = NULL;
+	} else {
+		p = prom_early_alloc(sizeof(struct property) + 32);
+		p->unique_id = unique_id++;
+	}
+
+	p->name = (char *) (p + 1);
+	if (special_name) {
+		strcpy(p->name, special_name);
+		p->length = special_len;
+		p->value = prom_early_alloc(special_len);
+		memcpy(p->value, special_val, special_len);
+	} else {
+		if (prev == NULL) {
+			prom_firstprop(node, p->name);
+		} else {
+			prom_nextprop(node, prev, p->name);
+		}
+		if (strlen(p->name) == 0) {
+			tmp = p;
+			return NULL;
+		}
+		p->length = prom_getproplen(node, p->name);
+		if (p->length <= 0) {
+			p->length = 0;
+		} else {
+			p->value = prom_early_alloc(p->length + 1);
+			prom_getproperty(node, p->name, p->value, p->length);
+			((unsigned char *)p->value)[p->length] = '\0';
+		}
+	}
+	return p;
+}
+
+static struct property * __init build_prop_list(phandle node)
+{
+	struct property *head, *tail;
+
+	head = tail = build_one_prop(node, NULL,
+				     ".node", &node, sizeof(node));
+
+	tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
+	tail = tail->next;
+	while(tail) {
+		tail->next = build_one_prop(node, tail->name,
+					    NULL, NULL, 0);
+		tail = tail->next;
+	}
+
+	return head;
+}
+
+static char * __init get_one_property(phandle node, const char *name)
+{
+	char *buf = "<NULL>";
+	int len;
+
+	len = prom_getproplen(node, name);
+	if (len > 0) {
+		buf = prom_early_alloc(len);
+		prom_getproperty(node, name, buf, len);
+	}
+
+	return buf;
+}
+
+static struct device_node * __init create_node(phandle node)
+{
+	struct device_node *dp;
+
+	if (!node)
+		return NULL;
+
+	dp = prom_early_alloc(sizeof(*dp));
+	dp->unique_id = unique_id++;
+
+	kref_init(&dp->kref);
+
+	dp->name = get_one_property(node, "name");
+	dp->type = get_one_property(node, "device_type");
+	dp->node = node;
+
+	/* Build interrupts later... */
+
+	dp->properties = build_prop_list(node);
+
+	return dp;
+}
+
+static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
+{
+	struct device_node *dp;
+
+	dp = create_node(node);
+	if (dp) {
+		*(*nextp) = dp;
+		*nextp = &dp->allnext;
+
+		dp->parent = parent;
+		dp->path_component_name = build_path_component(dp);
+		dp->full_name = build_full_name(dp);
+
+		dp->child = build_tree(dp, prom_getchild(node), nextp);
+
+		dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
+	}
+
+	return dp;
+}
+
+void __init prom_build_devicetree(void)
+{
+	struct device_node **nextp;
+
+	allnodes = create_node(prom_root_node);
+	allnodes->path_component_name = "";
+	allnodes->full_name = "/";
+
+	nextp = &allnodes->allnext;
+	allnodes->child = build_tree(allnodes,
+				     prom_getchild(allnodes->node),
+				     &nextp);
+	printk("PROM: Built device tree with %u bytes of memory.\n",
+	       prom_early_allocated);
+}
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 1d6ffde..ac05e0f 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -19,6 +19,7 @@
 #include <asm/cache.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
+#include <asm/prom.h>
 #include <asm/starfire.h>
 
 #include "iommu_common.h"
@@ -691,36 +692,6 @@
 	upa_writeq(val, cfg_reg);
 }
 
-/* SBUS SYSIO INO number to Sparc PIL level. */
-static unsigned char sysio_ino_to_pil[] = {
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 0 */
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 1 */
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 2 */
-	0, 5, 5, 7, 5, 7, 8, 9,		/* SBUS slot 3 */
-	5, /* Onboard SCSI */
-	5, /* Onboard Ethernet */
-/*XXX*/	8, /* Onboard BPP */
-	0, /* Bogon */
-       13, /* Audio */
-/*XXX*/15, /* PowerFail */
-	0, /* Bogon */
-	0, /* Bogon */
-       12, /* Zilog Serial Channels (incl. Keyboard/Mouse lines) */
-       11, /* Floppy */
-	0, /* Spare Hardware (bogon for now) */
-	0, /* Keyboard (bogon for now) */
-	0, /* Mouse (bogon for now) */
-	0, /* Serial (bogon for now) */
-     0, 0, /* Bogon, Bogon */
-       10, /* Timer 0 */
-       11, /* Timer 1 */
-     0, 0, /* Bogon, Bogon */
-       15, /* Uncorrectable SBUS Error */
-       15, /* Correctable SBUS Error */
-       15, /* SBUS Error */
-/*XXX*/ 0, /* Power Management (bogon for now) */
-};
-
 /* INO number to IMAP register offset for SYSIO external IRQ's.
  * This should conform to both Sunfire/Wildfire server and Fusion
  * desktop designs.
@@ -812,21 +783,12 @@
 	struct sbus_iommu *iommu = sbus->iommu;
 	unsigned long reg_base = iommu->sbus_control_reg - 0x2000UL;
 	unsigned long imap, iclr;
-	int pil, sbus_level = 0;
-
-	pil = sysio_ino_to_pil[ino];
-	if (!pil) {
-		printk("sbus_irq_build: Bad SYSIO INO[%x]\n", ino);
-		panic("Bad SYSIO IRQ translations...");
-	}
-
-	if (PIL_RESERVED(pil))
-		BUG();
+	int sbus_level = 0;
 
 	imap = sysio_irq_offsets[ino];
 	if (imap == ((unsigned long)-1)) {
-		prom_printf("get_irq_translations: Bad SYSIO INO[%x] cpu[%d]\n",
-			    ino, pil);
+		prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n",
+			    ino);
 		prom_halt();
 	}
 	imap += reg_base;
@@ -860,7 +822,7 @@
 
 		iclr += ((unsigned long)sbus_level - 1UL) * 8UL;
 	}
-	return build_irq(pil, sbus_level, iclr, imap);
+	return build_irq(sbus_level, iclr, imap);
 }
 
 /* Error interrupt handling. */
@@ -1137,24 +1099,25 @@
 }
 
 /* Boot time initialization. */
-void __init sbus_iommu_init(int prom_node, struct sbus_bus *sbus)
+static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
 {
-	struct linux_prom64_registers rprop;
+	struct linux_prom64_registers *pr;
+	struct device_node *dp;
 	struct sbus_iommu *iommu;
 	unsigned long regs, tsb_base;
 	u64 control;
-	int err, i;
+	int i;
 
-	sbus->portid = prom_getintdefault(sbus->prom_node,
-					  "upa-portid", -1);
+	dp = of_find_node_by_phandle(__node);
 
-	err = prom_getproperty(prom_node, "reg",
-			       (char *)&rprop, sizeof(rprop));
-	if (err < 0) {
+	sbus->portid = of_getintprop_default(dp, "upa-portid", -1);
+
+	pr = of_get_property(dp, "reg", NULL);
+	if (!pr) {
 		prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n");
 		prom_halt();
 	}
-	regs = rprop.phys_addr;
+	regs = pr->phys_addr;
 
 	iommu = kmalloc(sizeof(*iommu) + SMP_CACHE_BYTES, GFP_ATOMIC);
 	if (iommu == NULL) {
@@ -1264,3 +1227,50 @@
 
 	sysio_register_error_handlers(sbus);
 }
+
+void sbus_fill_device_irq(struct sbus_dev *sdev)
+{
+	struct device_node *dp = of_find_node_by_phandle(sdev->prom_node);
+	struct linux_prom_irqs *irqs;
+
+	irqs = of_get_property(dp, "interrupts", NULL);
+	if (!irqs) {
+		sdev->irqs[0] = 0;
+		sdev->num_irqs = 0;
+	} else {
+		unsigned int pri = irqs[0].pri;
+
+		sdev->num_irqs = 1;
+		if (pri < 0x20)
+			pri += sdev->slot * 8;
+
+		sdev->irqs[0] =	sbus_build_irq(sdev->bus, pri);
+	}
+}
+
+void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
+{
+}
+
+void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp)
+{
+	sbus_iommu_init(dp->node, sbus);
+}
+
+void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
+{
+}
+
+int __init sbus_arch_preinit(void)
+{
+	return 0;
+}
+
+void __init sbus_arch_postinit(void)
+{
+	extern void firetruck_init(void);
+	extern void clock_probe(void);
+
+	firetruck_init();
+	clock_probe();
+}
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 9cf1c88..116d963 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -376,12 +376,12 @@
 	}
 #endif
 
-	smp_setup_cpu_possible_map();
-
 	/* Get boot processor trap_block[] setup.  */
 	init_cur_cpu_trap(current_thread_info());
 
 	paging_init();
+
+	smp_setup_cpu_possible_map();
 }
 
 static int __init set_preferred_console(void)
@@ -537,7 +537,7 @@
 	for_each_possible_cpu(i) {
 		struct cpu *p = kzalloc(sizeof(*p), GFP_KERNEL);
 		if (p) {
-			register_cpu(p, i, NULL);
+			register_cpu(p, i);
 			err = 0;
 		}
 	}
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index f03d52d..f62bf3a 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -39,6 +39,7 @@
 #include <asm/starfire.h>
 #include <asm/tlb.h>
 #include <asm/sections.h>
+#include <asm/prom.h>
 
 extern void calibrate_delay(void);
 
@@ -76,41 +77,42 @@
 
 void __init smp_store_cpu_info(int id)
 {
-	int cpu_node, def;
+	struct device_node *dp;
+	int def;
 
 	/* multiplier and counter set by
 	   smp_setup_percpu_timer()  */
 	cpu_data(id).udelay_val			= loops_per_jiffy;
 
-	cpu_find_by_mid(id, &cpu_node);
-	cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
-						     "clock-frequency", 0);
+	cpu_find_by_mid(id, &dp);
+	cpu_data(id).clock_tick =
+		of_getintprop_default(dp, "clock-frequency", 0);
 
 	def = ((tlb_type == hypervisor) ? (8 * 1024) : (16 * 1024));
-	cpu_data(id).dcache_size = prom_getintdefault(cpu_node, "dcache-size",
-						      def);
+	cpu_data(id).dcache_size =
+		of_getintprop_default(dp, "dcache-size", def);
 
 	def = 32;
 	cpu_data(id).dcache_line_size =
-		prom_getintdefault(cpu_node, "dcache-line-size", def);
+		of_getintprop_default(dp, "dcache-line-size", def);
 
 	def = 16 * 1024;
-	cpu_data(id).icache_size = prom_getintdefault(cpu_node, "icache-size",
-						      def);
+	cpu_data(id).icache_size =
+		of_getintprop_default(dp, "icache-size", def);
 
 	def = 32;
 	cpu_data(id).icache_line_size =
-		prom_getintdefault(cpu_node, "icache-line-size", def);
+		of_getintprop_default(dp, "icache-line-size", def);
 
 	def = ((tlb_type == hypervisor) ?
 	       (3 * 1024 * 1024) :
 	       (4 * 1024 * 1024));
-	cpu_data(id).ecache_size = prom_getintdefault(cpu_node, "ecache-size",
-						      def);
+	cpu_data(id).ecache_size =
+		of_getintprop_default(dp, "ecache-size", def);
 
 	def = 64;
 	cpu_data(id).ecache_line_size =
-		prom_getintdefault(cpu_node, "ecache-line-size", def);
+		of_getintprop_default(dp, "ecache-line-size", def);
 
 	printk("CPU[%d]: Caches "
 	       "D[sz(%d):line_sz(%d)] "
@@ -342,10 +344,10 @@
 
 		prom_startcpu_cpuid(cpu, entry, cookie);
 	} else {
-		int cpu_node;
+		struct device_node *dp;
 
-		cpu_find_by_mid(cpu, &cpu_node);
-		prom_startcpu(cpu_node, entry, cookie);
+		cpu_find_by_mid(cpu, &dp);
+		prom_startcpu(dp->node, entry, cookie);
 	}
 
 	for (timeout = 0; timeout < 5000000; timeout++) {
@@ -1289,7 +1291,8 @@
 
 static void __init smp_tune_scheduling(void)
 {
-	int instance, node;
+	struct device_node *dp;
+	int instance;
 	unsigned int def, smallest = ~0U;
 
 	def = ((tlb_type == hypervisor) ?
@@ -1297,10 +1300,10 @@
 	       (4 * 1024 * 1024));
 
 	instance = 0;
-	while (!cpu_find_by_instance(instance, &node, NULL)) {
+	while (!cpu_find_by_instance(instance, &dp, NULL)) {
 		unsigned int val;
 
-		val = prom_getintdefault(node, "ecache-size", def);
+		val = of_getintprop_default(dp, "ecache-size", def);
 		if (val < smallest)
 			smallest = val;
 
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 38e569f..4ac35dd 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -125,9 +125,6 @@
 EXPORT_SYMBOL(__write_unlock);
 EXPORT_SYMBOL(__write_trylock);
 
-/* Hard IRQ locking */
-EXPORT_SYMBOL(synchronize_irq);
-
 #if defined(CONFIG_MCOUNT)
 extern void _mcount(void);
 EXPORT_SYMBOL(_mcount);
@@ -175,10 +172,6 @@
 EXPORT_SYMBOL(clear_bit);
 EXPORT_SYMBOL(change_bit);
 
-EXPORT_SYMBOL(ivector_table);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-
 EXPORT_SYMBOL(__flushw_user);
 
 EXPORT_SYMBOL(tlb_type);
diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S
index b49a68b..49703c3 100644
--- a/arch/sparc64/kernel/sun4v_ivec.S
+++ b/arch/sparc64/kernel/sun4v_ivec.S
@@ -5,6 +5,7 @@
 
 #include <asm/cpudata.h>
 #include <asm/intr_queue.h>
+#include <asm/pil.h>
 
 	.text
 	.align	32
@@ -102,23 +103,17 @@
 
 	/* Get &ivector_table[IVEC] into %g4.  */
 	sethi	%hi(ivector_table), %g4
-	sllx	%g3, 5, %g3
+	sllx	%g3, 3, %g3
 	or	%g4, %lo(ivector_table), %g4
 	add	%g4, %g3, %g4
 
-	/* Load IRQ %pil into %g5.  */
-	ldub	[%g4 + 0x04], %g5
-
 	/* Insert ivector_table[] entry into __irq_work[] queue.  */
-	sllx	%g5, 2, %g3
-	lduw	[%g1 + %g3], %g2	/* g2 = irq_work(cpu, pil) */
+	lduw	[%g1], %g2		/* g2 = irq_work(cpu) */
 	stw	%g2, [%g4 + 0x00]	/* bucket->irq_chain = g2 */
-	stw	%g4, [%g1 + %g3]	/* irq_work(cpu, pil) = bucket */
+	stw	%g4, [%g1]		/* irq_work(cpu) = bucket */
 
 	/* Signal the interrupt by setting (1 << pil) in %softint.  */
-	mov	1, %g2
-	sllx	%g2, %g5, %g2
-	wr	%g2, 0x0, %set_softint
+	wr	%g0, 1 << PIL_DEVICE_IRQ, %set_softint
 
 sun4v_dev_mondo_queue_empty:
 	retry
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index e55b5c6..348b820 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -48,6 +48,7 @@
 #include <asm/sections.h>
 #include <asm/cpudata.h>
 #include <asm/uaccess.h>
+#include <asm/prom.h>
 
 DEFINE_SPINLOCK(mostek_lock);
 DEFINE_SPINLOCK(rtc_lock);
@@ -457,7 +458,7 @@
 	}
 }
 
-static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	unsigned long ticks, compare, pstate;
 
@@ -755,24 +756,200 @@
 	return -EOPNOTSUPP;
 }
 
+static int __init clock_model_matches(char *model)
+{
+	if (strcmp(model, "mk48t02") &&
+	    strcmp(model, "mk48t08") &&
+	    strcmp(model, "mk48t59") &&
+	    strcmp(model, "m5819") &&
+	    strcmp(model, "m5819p") &&
+	    strcmp(model, "m5823") &&
+	    strcmp(model, "ds1287"))
+		return 0;
+
+	return 1;
+}
+
+static void __init __clock_assign_common(void __iomem *addr, char *model)
+{
+	if (model[5] == '0' && model[6] == '2') {
+		mstk48t02_regs = addr;
+	} else if(model[5] == '0' && model[6] == '8') {
+		mstk48t08_regs = addr;
+		mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
+	} else {
+		mstk48t59_regs = addr;
+		mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
+	}
+}
+
+static void __init clock_assign_clk_reg(struct linux_prom_registers *clk_reg,
+					char *model)
+{
+	unsigned long addr;
+
+	addr = ((unsigned long) clk_reg[0].phys_addr |
+		(((unsigned long) clk_reg[0].which_io) << 32UL));
+
+	__clock_assign_common((void __iomem *) addr, model);
+}
+
+static int __init clock_probe_central(void)
+{
+	struct linux_prom_registers clk_reg[2], *pr;
+	struct device_node *dp;
+	char *model;
+
+	if (!central_bus)
+		return 0;
+
+	/* Get Central FHC's prom node.  */
+	dp = central_bus->child->prom_node;
+
+	/* Then get the first child device below it.  */
+	dp = dp->child;
+
+	while (dp) {
+		model = of_get_property(dp, "model", NULL);
+		if (!model || !clock_model_matches(model))
+			goto next_sibling;
+
+		pr = of_get_property(dp, "reg", NULL);
+		memcpy(clk_reg, pr, sizeof(clk_reg));
+
+		apply_fhc_ranges(central_bus->child, clk_reg, 1);
+		apply_central_ranges(central_bus, clk_reg, 1);
+
+		clock_assign_clk_reg(clk_reg, model);
+		return 1;
+
+	next_sibling:
+		dp = dp->sibling;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PCI
+static void __init clock_isa_ebus_assign_regs(struct resource *res, char *model)
+{
+	if (!strcmp(model, "ds1287") ||
+	    !strcmp(model, "m5819") ||
+	    !strcmp(model, "m5819p") ||
+	    !strcmp(model, "m5823")) {
+		ds1287_regs = res->start;
+	} else {
+		mstk48t59_regs = (void __iomem *) res->start;
+		mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
+	}
+}
+
+static int __init clock_probe_one_ebus_dev(struct linux_ebus_device *edev)
+{
+	struct device_node *dp = edev->prom_node;
+	char *model;
+
+	model = of_get_property(dp, "model", NULL);
+	if (!clock_model_matches(model))
+		return 0;
+
+	clock_isa_ebus_assign_regs(&edev->resource[0], model);
+
+	return 1;
+}
+
+static int __init clock_probe_ebus(void)
+{
+	struct linux_ebus *ebus;
+
+	for_each_ebus(ebus) {
+		struct linux_ebus_device *edev;
+
+		for_each_ebusdev(edev, ebus) {
+			if (clock_probe_one_ebus_dev(edev))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+static int __init clock_probe_one_isa_dev(struct sparc_isa_device *idev)
+{
+	struct device_node *dp = idev->prom_node;
+	char *model;
+
+	model = of_get_property(dp, "model", NULL);
+	if (!clock_model_matches(model))
+		return 0;
+
+	clock_isa_ebus_assign_regs(&idev->resource, model);
+
+	return 1;
+}
+
+static int __init clock_probe_isa(void)
+{
+	struct sparc_isa_bridge *isa_br;
+
+	for_each_isa(isa_br) {
+		struct sparc_isa_device *isa_dev;
+
+		for_each_isadev(isa_dev, isa_br) {
+			if (clock_probe_one_isa_dev(isa_dev))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_SBUS
+static int __init clock_probe_one_sbus_dev(struct sbus_bus *sbus, struct sbus_dev *sdev)
+{
+	struct resource *res;
+	char model[64];
+	void __iomem *addr;
+
+	prom_getstring(sdev->prom_node, "model", model, sizeof(model));
+	if (!clock_model_matches(model))
+		return 0;
+
+	res = &sdev->resource[0];
+	addr = sbus_ioremap(res, 0, 0x800UL, "eeprom");
+
+	__clock_assign_common(addr, model);
+
+	return 1;
+}
+
+static int __init clock_probe_sbus(void)
+{
+	struct sbus_bus *sbus;
+
+	for_each_sbus(sbus) {
+		struct sbus_dev *sdev;
+
+		for_each_sbusdev(sdev, sbus) {
+			if (clock_probe_one_sbus_dev(sbus, sdev))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+#endif
+
 void __init clock_probe(void)
 {
-	struct linux_prom_registers clk_reg[2];
-	char model[128];
-	int node, busnd = -1, err;
-	unsigned long flags;
-	struct linux_central *cbus;
-#ifdef CONFIG_PCI
-	struct linux_ebus *ebus = NULL;
-	struct sparc_isa_bridge *isa_br = NULL;
-#endif
 	static int invoked;
+	unsigned long flags;
 
 	if (invoked)
 		return;
 	invoked = 1;
 
-
 	if (this_is_starfire) {
 		xtime.tv_sec = starfire_get_time();
 		xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
@@ -788,182 +965,26 @@
 		return;
 	}
 
-	local_irq_save(flags);
-
-	cbus = central_bus;
-	if (cbus != NULL)
-		busnd = central_bus->child->prom_node;
-
 	/* Check FHC Central then EBUSs then ISA bridges then SBUSs.
 	 * That way we handle the presence of multiple properly.
 	 *
 	 * As a special case, machines with Central must provide the
 	 * timer chip there.
 	 */
+	if (!clock_probe_central() &&
 #ifdef CONFIG_PCI
-	if (ebus_chain != NULL) {
-		ebus = ebus_chain;
-		if (busnd == -1)
-			busnd = ebus->prom_node;
-	}
-	if (isa_chain != NULL) {
-		isa_br = isa_chain;
-		if (busnd == -1)
-			busnd = isa_br->prom_node;
-	}
+	    !clock_probe_ebus() &&
+	    !clock_probe_isa() &&
 #endif
-	if (sbus_root != NULL && busnd == -1)
-		busnd = sbus_root->prom_node;
-
-	if (busnd == -1) {
-		prom_printf("clock_probe: problem, cannot find bus to search.\n");
-		prom_halt();
+#ifdef CONFIG_SBUS
+	    !clock_probe_sbus()
+#endif
+		) {
+		printk(KERN_WARNING "No clock chip found.\n");
+		return;
 	}
 
-	node = prom_getchild(busnd);
-
-	while (1) {
-		if (!node)
-			model[0] = 0;
-		else
-			prom_getstring(node, "model", model, sizeof(model));
-		if (strcmp(model, "mk48t02") &&
-		    strcmp(model, "mk48t08") &&
-		    strcmp(model, "mk48t59") &&
-		    strcmp(model, "m5819") &&
-		    strcmp(model, "m5819p") &&
-		    strcmp(model, "m5823") &&
-		    strcmp(model, "ds1287")) {
-			if (cbus != NULL) {
-				prom_printf("clock_probe: Central bus lacks timer chip.\n");
-				prom_halt();
-			}
-
-		   	if (node != 0)
-				node = prom_getsibling(node);
-#ifdef CONFIG_PCI
-			while ((node == 0) && ebus != NULL) {
-				ebus = ebus->next;
-				if (ebus != NULL) {
-					busnd = ebus->prom_node;
-					node = prom_getchild(busnd);
-				}
-			}
-			while ((node == 0) && isa_br != NULL) {
-				isa_br = isa_br->next;
-				if (isa_br != NULL) {
-					busnd = isa_br->prom_node;
-					node = prom_getchild(busnd);
-				}
-			}
-#endif
-			if (node == 0) {
-				prom_printf("clock_probe: Cannot find timer chip\n");
-				prom_halt();
-			}
-			continue;
-		}
-
-		err = prom_getproperty(node, "reg", (char *)clk_reg,
-				       sizeof(clk_reg));
-		if(err == -1) {
-			prom_printf("clock_probe: Cannot get Mostek reg property\n");
-			prom_halt();
-		}
-
-		if (cbus != NULL) {
-			apply_fhc_ranges(central_bus->child, clk_reg, 1);
-			apply_central_ranges(central_bus, clk_reg, 1);
-		}
-#ifdef CONFIG_PCI
-		else if (ebus != NULL) {
-			struct linux_ebus_device *edev;
-
-			for_each_ebusdev(edev, ebus)
-				if (edev->prom_node == node)
-					break;
-			if (edev == NULL) {
-				if (isa_chain != NULL)
-					goto try_isa_clock;
-				prom_printf("%s: Mostek not probed by EBUS\n",
-					    __FUNCTION__);
-				prom_halt();
-			}
-
-			if (!strcmp(model, "ds1287") ||
-			    !strcmp(model, "m5819") ||
-			    !strcmp(model, "m5819p") ||
-			    !strcmp(model, "m5823")) {
-				ds1287_regs = edev->resource[0].start;
-			} else {
-				mstk48t59_regs = (void __iomem *)
-					edev->resource[0].start;
-				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
-			}
-			break;
-		}
-		else if (isa_br != NULL) {
-			struct sparc_isa_device *isadev;
-
-try_isa_clock:
-			for_each_isadev(isadev, isa_br)
-				if (isadev->prom_node == node)
-					break;
-			if (isadev == NULL) {
-				prom_printf("%s: Mostek not probed by ISA\n");
-				prom_halt();
-			}
-			if (!strcmp(model, "ds1287") ||
-			    !strcmp(model, "m5819") ||
-			    !strcmp(model, "m5819p") ||
-			    !strcmp(model, "m5823")) {
-				ds1287_regs = isadev->resource.start;
-			} else {
-				mstk48t59_regs = (void __iomem *)
-					isadev->resource.start;
-				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
-			}
-			break;
-		}
-#endif
-		else {
-			if (sbus_root->num_sbus_ranges) {
-				int nranges = sbus_root->num_sbus_ranges;
-				int rngc;
-
-				for (rngc = 0; rngc < nranges; rngc++)
-					if (clk_reg[0].which_io ==
-					    sbus_root->sbus_ranges[rngc].ot_child_space)
-						break;
-				if (rngc == nranges) {
-					prom_printf("clock_probe: Cannot find ranges for "
-						    "clock regs.\n");
-					prom_halt();
-				}
-				clk_reg[0].which_io =
-					sbus_root->sbus_ranges[rngc].ot_parent_space;
-				clk_reg[0].phys_addr +=
-					sbus_root->sbus_ranges[rngc].ot_parent_base;
-			}
-		}
-
-		if(model[5] == '0' && model[6] == '2') {
-			mstk48t02_regs = (void __iomem *)
-				(((u64)clk_reg[0].phys_addr) |
-				 (((u64)clk_reg[0].which_io)<<32UL));
-		} else if(model[5] == '0' && model[6] == '8') {
-			mstk48t08_regs = (void __iomem *)
-				(((u64)clk_reg[0].phys_addr) |
-				 (((u64)clk_reg[0].which_io)<<32UL));
-			mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
-		} else {
-			mstk48t59_regs = (void __iomem *)
-				(((u64)clk_reg[0].phys_addr) |
-				 (((u64)clk_reg[0].which_io)<<32UL));
-			mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
-		}
-		break;
-	}
+	local_irq_save(flags);
 
 	if (mstk48t02_regs != NULL) {
 		/* Report a low battery voltage condition. */
@@ -983,12 +1004,14 @@
 /* This is gets the master TICK_INT timer going. */
 static unsigned long sparc64_init_timers(void)
 {
+	struct device_node *dp;
+	struct property *prop;
 	unsigned long clock;
-	int node;
 #ifdef CONFIG_SMP
 	extern void smp_tick_init(void);
 #endif
 
+	dp = of_find_node_by_path("/");
 	if (tlb_type == spitfire) {
 		unsigned long ver, manuf, impl;
 
@@ -999,18 +1022,17 @@
 		if (manuf == 0x17 && impl == 0x13) {
 			/* Hummingbird, aka Ultra-IIe */
 			tick_ops = &hbtick_operations;
-			node = prom_root_node;
-			clock = prom_getint(node, "stick-frequency");
+			prop = of_find_property(dp, "stick-frequency", NULL);
 		} else {
 			tick_ops = &tick_operations;
-			cpu_find_by_instance(0, &node, NULL);
-			clock = prom_getint(node, "clock-frequency");
+			cpu_find_by_instance(0, &dp, NULL);
+			prop = of_find_property(dp, "clock-frequency", NULL);
 		}
 	} else {
 		tick_ops = &stick_operations;
-		node = prom_root_node;
-		clock = prom_getint(node, "stick-frequency");
+		prop = of_find_property(dp, "stick-frequency", NULL);
 	}
+	clock = *(unsigned int *) prop->value;
 	timer_tick_offset = clock / HZ;
 
 #ifdef CONFIG_SMP
@@ -1020,19 +1042,9 @@
 	return clock;
 }
 
-static void sparc64_start_timers(irqreturn_t (*cfunc)(int, void *, struct pt_regs *))
+static void sparc64_start_timers(void)
 {
 	unsigned long pstate;
-	int err;
-
-	/* Register IRQ handler. */
-	err = request_irq(build_irq(0, 0, 0UL, 0UL), cfunc, 0,
-			  "timer", NULL);
-
-	if (err) {
-		prom_printf("Serious problem, cannot register TICK_INT\n");
-		prom_halt();
-	}
 
 	/* Guarantee that the following sequences execute
 	 * uninterrupted.
@@ -1116,7 +1128,7 @@
 	/* Now that the interpolator is registered, it is
 	 * safe to start the timer ticking.
 	 */
-	sparc64_start_timers(timer_interrupt);
+	sparc64_start_timers();
 
 	timer_ticks_per_nsec_quotient =
 		(((NSEC_PER_SEC << SPARC64_NSEC_PER_CYC_SHIFT) +
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 563db52..1ff34b0 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -42,6 +42,7 @@
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
+#include <asm/prom.h>
 
 ATOMIC_NOTIFIER_HEAD(sparc64die_chain);
 
@@ -807,7 +808,8 @@
 void __init cheetah_ecache_flush_init(void)
 {
 	unsigned long largest_size, smallest_linesize, order, ver;
-	int node, i, instance;
+	struct device_node *dp;
+	int i, instance, sz;
 
 	/* Scan all cpu device tree nodes, note two values:
 	 * 1) largest E-cache size
@@ -817,14 +819,14 @@
 	smallest_linesize = ~0UL;
 
 	instance = 0;
-	while (!cpu_find_by_instance(instance, &node, NULL)) {
+	while (!cpu_find_by_instance(instance, &dp, NULL)) {
 		unsigned long val;
 
-		val = prom_getintdefault(node, "ecache-size",
-					 (2 * 1024 * 1024));
+		val = of_getintprop_default(dp, "ecache-size",
+					    (2 * 1024 * 1024));
 		if (val > largest_size)
 			largest_size = val;
-		val = prom_getintdefault(node, "ecache-line-size", 64);
+		val = of_getintprop_default(dp, "ecache-line-size", 64);
 		if (val < smallest_linesize)
 			smallest_linesize = val;
 		instance++;
@@ -849,16 +851,16 @@
 	}
 
 	/* Now allocate error trap reporting scoreboard. */
-	node = NR_CPUS * (2 * sizeof(struct cheetah_err_info));
+	sz = NR_CPUS * (2 * sizeof(struct cheetah_err_info));
 	for (order = 0; order < MAX_ORDER; order++) {
-		if ((PAGE_SIZE << order) >= node)
+		if ((PAGE_SIZE << order) >= sz)
 			break;
 	}
 	cheetah_error_log = (struct cheetah_err_info *)
 		__get_free_pages(GFP_KERNEL, order);
 	if (!cheetah_error_log) {
 		prom_printf("cheetah_ecache_flush_init: Failed to allocate "
-			    "error logging scoreboard (%d bytes).\n", node);
+			    "error logging scoreboard (%d bytes).\n", sz);
 		prom_halt();
 	}
 	memset(cheetah_error_log, 0, PAGE_SIZE << order);
@@ -2544,7 +2546,9 @@
 	    (TRAP_PER_CPU_TSB_HUGE !=
 	     offsetof(struct trap_per_cpu, tsb_huge)) ||
 	    (TRAP_PER_CPU_TSB_HUGE_TEMP !=
-	     offsetof(struct trap_per_cpu, tsb_huge_temp)))
+	     offsetof(struct trap_per_cpu, tsb_huge_temp)) ||
+	    (TRAP_PER_CPU_IRQ_WORKLIST !=
+	     offsetof(struct trap_per_cpu, irq_worklist)))
 		trap_per_cpu_offsets_are_bolixed_dave();
 
 	if ((TSB_CONFIG_TSB !=
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index 5d90151..ee45ca2 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -58,13 +58,11 @@
 tl0_irq3:	BTRAP(0x43)
 tl0_irq4:	BTRAP(0x44)
 #endif
-tl0_irq5:	TRAP_IRQ(handler_irq, 5)  TRAP_IRQ(handler_irq, 6)
-tl0_irq7:	TRAP_IRQ(handler_irq, 7)  TRAP_IRQ(handler_irq, 8)
-tl0_irq9:	TRAP_IRQ(handler_irq, 9)  TRAP_IRQ(handler_irq, 10)
-tl0_irq11:	TRAP_IRQ(handler_irq, 11) TRAP_IRQ(handler_irq, 12)
-tl0_irq13:	TRAP_IRQ(handler_irq, 13)
+tl0_irq5:	TRAP_IRQ(handler_irq, 5)
+tl0_irq6:	BTRAP(0x46) BTRAP(0x47) BTRAP(0x48) BTRAP(0x49)
+tl0_irq10:	BTRAP(0x4a) BTRAP(0x4b) BTRAP(0x4c) BTRAP(0x4d)
 #ifndef CONFIG_SMP
-tl0_irq14:	TRAP_IRQ(handler_irq, 14)
+tl0_irq14:	TRAP_IRQ(timer_irq, 14)
 #else
 tl0_irq14:	TICK_SMP_IRQ
 #endif
diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
index 001e851..bb2d685 100644
--- a/arch/sparc64/kernel/unaligned.c
+++ b/arch/sparc64/kernel/unaligned.c
@@ -279,12 +279,21 @@
 
 asmlinkage void kernel_unaligned_trap(struct pt_regs *regs, unsigned int insn)
 {
+	static unsigned long count, last_time;
 	enum direction dir = decode_direction(insn);
 	int size = decode_access_size(insn);
 
 	current_thread_info()->kern_una_regs = regs;
 	current_thread_info()->kern_una_insn = insn;
 
+	if (jiffies - last_time > 5 * HZ)
+		count = 0;
+	if (count < 5) {
+		last_time = jiffies;
+		count++;
+		printk("Kernel unaligned access at TPC[%lx]\n", regs->tpc);
+	}
+
 	if (!ok_for_kernel(insn) || dir == both) {
 		printk("Unsupported unaligned load/store trap for kernel "
 		       "at <%016lx>.\n", regs->tpc);
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index 6e002aa..1605967 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -31,6 +31,40 @@
 #include <asm/kdebug.h>
 #include <asm/mmu_context.h>
 
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
+/* Hook to register for page fault notifications */
+int register_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+}
+
+int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+}
+
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	struct die_args args = {
+		.regs = regs,
+		.str = str,
+		.err = err,
+		.trapnr = trap,
+		.signr = sig
+	};
+	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	return NOTIFY_DONE;
+}
+#endif
+
 /*
  * To debug kernel to catch accesses to certain virtual/physical addresses.
  * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints.
@@ -263,7 +297,7 @@
 
 	fault_code = get_thread_fault_code();
 
-	if (notify_die(DIE_PAGE_FAULT, "page_fault", regs,
+	if (notify_page_fault(DIE_PAGE_FAULT, "page_fault", regs,
 		       fault_code, 0, SIGSEGV) == NOTIFY_STOP)
 		return;
 
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 1539a83..cb75a27 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -18,6 +18,7 @@
 #include <linux/initrd.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
+#include <linux/poison.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/kprobes.h>
@@ -42,6 +43,7 @@
 #include <asm/sections.h>
 #include <asm/tsb.h>
 #include <asm/hypervisor.h>
+#include <asm/prom.h>
 
 extern void device_scan(void);
 
@@ -101,8 +103,6 @@
 		prom_halt();
 	}
 
-	*num_ents = ents;
-
 	/* Sanitize what we got from the firmware, by page aligning
 	 * everything.
 	 */
@@ -124,6 +124,25 @@
 		regs[i].phys_addr = base;
 		regs[i].reg_size = size;
 	}
+
+	for (i = 0; i < ents; i++) {
+		if (regs[i].reg_size == 0UL) {
+			int j;
+
+			for (j = i; j < ents - 1; j++) {
+				regs[j].phys_addr =
+					regs[j+1].phys_addr;
+				regs[j].reg_size =
+					regs[j+1].reg_size;
+			}
+
+			ents--;
+			i--;
+		}
+	}
+
+	*num_ents = ents;
+
 	sort(regs, ents, sizeof(struct linux_prom64_registers),
 	     cmp_p64, NULL);
 }
@@ -1339,6 +1358,8 @@
 
 	kernel_physical_mapping_init();
 
+	prom_build_devicetree();
+
 	{
 		unsigned long zones_size[MAX_NR_ZONES];
 		unsigned long zholes_size[MAX_NR_ZONES];
@@ -1376,7 +1397,7 @@
 		while (old_start < old_end) {
 			int n;
 
-			for (n = 0; pavail_rescan_ents; n++) {
+			for (n = 0; n < pavail_rescan_ents; n++) {
 				unsigned long new_start, new_end;
 
 				new_start = pavail_rescan[n].phys_addr;
@@ -1398,6 +1419,32 @@
 	}
 }
 
+int __init page_in_phys_avail(unsigned long paddr)
+{
+	int i;
+
+	paddr &= PAGE_MASK;
+
+	for (i = 0; i < pavail_rescan_ents; i++) {
+		unsigned long start, end;
+
+		start = pavail_rescan[i].phys_addr;
+		end = start + pavail_rescan[i].reg_size;
+
+		if (paddr >= start && paddr < end)
+			return 1;
+	}
+	if (paddr >= kern_base && paddr < (kern_base + kern_size))
+		return 1;
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (paddr >= __pa(initrd_start) &&
+	    paddr < __pa(PAGE_ALIGN(initrd_end)))
+		return 1;
+#endif
+
+	return 0;
+}
+
 void __init mem_init(void)
 {
 	unsigned long codepages, datapages, initpages;
@@ -1474,7 +1521,7 @@
 		page = (addr +
 			((unsigned long) __va(kern_base)) -
 			((unsigned long) KERNBASE));
-		memset((void *)addr, 0xcc, PAGE_SIZE);
+		memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE);
 		p = virt_to_page(page);
 
 		ClearPageReserved(p);
@@ -1522,6 +1569,7 @@
 unsigned long pg_iobits __read_mostly;
 
 unsigned long _PAGE_IE __read_mostly;
+EXPORT_SYMBOL(_PAGE_IE);
 
 unsigned long _PAGE_E __read_mostly;
 EXPORT_SYMBOL(_PAGE_E);
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
index 4885ca6..0f0eb6a 100644
--- a/arch/sparc64/solaris/fs.c
+++ b/arch/sparc64/solaris/fs.c
@@ -356,7 +356,7 @@
 	int error;
 	struct sol_statvfs __user *ss = A(buf);
 
-	error = vfs_statfs(mnt->mnt_sb, &s);
+	error = vfs_statfs(mnt->mnt_root, &s);
 	if (!error) {
 		const char *p = mnt->mnt_sb->s_type->name;
 		int i = 0;
@@ -392,7 +392,7 @@
 	int error;
 	struct sol_statvfs64 __user *ss = A(buf);
 			
-	error = vfs_statfs(mnt->mnt_sb, &s);
+	error = vfs_statfs(mnt->mnt_root, &s);
 	if (!error) {
 		const char *p = mnt->mnt_sb->s_type->name;
 		int i = 0;
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 5284996..719c909 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -23,6 +23,7 @@
 #include <asm/oplib.h>
 #include <asm/idprom.h>
 #include <asm/smp.h>
+#include <asm/prom.h>
 
 #include "conv.h"
 
@@ -194,14 +195,17 @@
 	}
 }
 
-static char *platform(char *buffer)
+static char *platform(char *buffer, int sz)
 {
+	struct device_node *dp = of_find_node_by_path("/");
 	int len;
 
 	*buffer = 0;
-	len = prom_getproperty(prom_root_node, "name", buffer, 256);
-	if(len > 0)
-		buffer[len] = 0;
+	len = strlen(dp->name);
+	if (len > sz)
+		len = sz;
+	memcpy(buffer, dp->name, len);
+	buffer[len] = 0;
 	if (*buffer) {
 		char *p;
 
@@ -213,16 +217,22 @@
 	return "sun4u";
 }
 
-static char *serial(char *buffer)
+static char *serial(char *buffer, int sz)
 {
-	int node = prom_getchild(prom_root_node);
+	struct device_node *dp = of_find_node_by_path("/options");
 	int len;
 
-	node = prom_searchsiblings(node, "options");
 	*buffer = 0;
-	len = prom_getproperty(node, "system-board-serial#", buffer, 256);
-	if(len > 0)
-		buffer[len] = 0;
+	if (dp) {
+		char *val = of_get_property(dp, "system-board-serial#", &len);
+
+		if (val && len > 0) {
+			if (len > sz)
+				len = sz;
+			memcpy(buffer, val, len);
+			buffer[len] = 0;
+		}
+	}
 	if (!*buffer)
 		return "4512348717234";
 	else
@@ -305,8 +315,8 @@
 	case SI_MACHINE: r = machine(); break;
 	case SI_ARCHITECTURE: r = "sparc"; break;
 	case SI_HW_PROVIDER: r = "Sun_Microsystems"; break;
-	case SI_HW_SERIAL: r = serial(buffer); break;
-	case SI_PLATFORM: r = platform(buffer); break;
+	case SI_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break;
+	case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break;
 	case SI_SRPC_DOMAIN: r = ""; break;
 	case SI_VERSION: r = "Generic"; break;
 	default: return -EINVAL;
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index 5681a8b..bab51d6 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -49,7 +49,6 @@
 
 config SYSCALL_DEBUG
 	bool "Enable system call debugging"
-	default N
 	depends on DEBUG_INFO
 	help
 	This adds some system debugging to UML, including keeping a ring buffer
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 6d7173f..7914931 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -300,8 +300,6 @@
 	machine_restart(NULL);
 }
 
-extern void ctrl_alt_del(void);
-
 void mconsole_cad(struct mc_request *req)
 {
 	mconsole_reply(req, "", 0, 0);
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 0897852..290cec6d 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1222,7 +1222,7 @@
 		}
 	}
 
-	/* Succesful return case! */
+	/* Successful return case! */
 	if(backing_file_out == NULL)
 		return(fd);
 
diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
index e06f83e..5e86aa0 100644
--- a/arch/um/include/sysdep-x86_64/syscalls.h
+++ b/arch/um/include/sysdep-x86_64/syscalls.h
@@ -12,8 +12,6 @@
 
 typedef long syscall_handler_t(void);
 
-extern syscall_handler_t *ia32_sys_call_table[];
-
 extern syscall_handler_t *sys_call_table[];
 
 #define EXECUTE_SYSCALL(syscall, regs) \
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index fc0f0b0..166cb09 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -69,7 +69,7 @@
 		panic("Physical remapping for %p already present",
 		      desc->virt);
 
-	rb_link_node(&desc->rb, (*n)->rb_parent, n);
+	rb_link_node(&desc->rb, rb_parent(*n), n);
 	rb_insert_color(&desc->rb, &phys_mappings);
 }
 
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 86f51d0..87cdbc5 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -87,7 +87,7 @@
 
 void time_init_kern(void)
 {
-	unsigned long long nsecs;
+	long long nsecs;
 
 	nsecs = os_nsecs();
 	set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION,
diff --git a/arch/um/sys-ppc/misc.S b/arch/um/sys-ppc/misc.S
index 11b7bd7..f0c971db 100644
--- a/arch/um/sys-ppc/misc.S
+++ b/arch/um/sys-ppc/misc.S
@@ -23,14 +23,10 @@
 #define CACHE_LINE_SIZE		16
 #define LG_CACHE_LINE_SIZE	4
 #define MAX_COPY_PREFETCH	1
-#elif !defined(CONFIG_PPC64BRIDGE)
+#else
 #define CACHE_LINE_SIZE		32
 #define LG_CACHE_LINE_SIZE	5
 #define MAX_COPY_PREFETCH	4
-#else
-#define CACHE_LINE_SIZE		128
-#define LG_CACHE_LINE_SIZE	7
-#define MAX_COPY_PREFETCH	1
 #endif /* CONFIG_4xx || CONFIG_8xx */
 
 	.text
diff --git a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c
index 633e4e1..17c2d43 100644
--- a/arch/v850/kernel/signal.c
+++ b/arch/v850/kernel/signal.c
@@ -274,7 +274,7 @@
 	/* Default to using normal stack */
 	unsigned long sp = regs->gpr[GPR_SP];
 
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void *)((sp - frame_size) & -8UL);
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 408d44a..ccc4a7f 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -299,6 +299,7 @@
        bool "ACPI NUMA detection"
        depends on NUMA
        select ACPI 
+	select PCI
        select ACPI_NUMA
        default y
        help
@@ -385,27 +386,47 @@
 	bool "Provide RTC interrupt"
 	depends on HPET_TIMER && RTC=y
 
-config GART_IOMMU
-	bool "K8 GART IOMMU support"
+# Mark as embedded because too many people got it wrong.
+# The code disables itself when not needed.
+config IOMMU
+	bool "IOMMU support" if EMBEDDED
 	default y
 	select SWIOTLB
+	select AGP
 	depends on PCI
 	help
-	  Support for hardware IOMMU in AMD's Opteron/Athlon64 Processors
-	  and for the bounce buffering software IOMMU.
-	  Needed to run systems with more than 3GB of memory properly with
-	  32-bit PCI devices that do not support DAC (Double Address Cycle).
-	  The IOMMU can be turned off at runtime with the iommu=off parameter.
-  	  Normally the kernel will take the right choice by itself.
-  	  This option includes a driver for the AMD Opteron/Athlon64 IOMMU
-  	  northbridge and a software emulation used on other systems without
-	  hardware IOMMU.  If unsure, say Y.
+	  Support for full DMA access of devices with 32bit memory access only
+	  on systems with more than 3GB. This is usually needed for USB,
+	  sound, many IDE/SATA chipsets and some other devices.
+	  Provides a driver for the AMD Athlon64/Opteron/Turion/Sempron GART
+	  based IOMMU and a software bounce buffer based IOMMU used on Intel
+	  systems and as fallback.
+	  The code is only active when needed (enough memory and limited
+	  device) unless CONFIG_IOMMU_DEBUG or iommu=force is specified
+	  too.
 
-# need this always enabled with GART_IOMMU for the VIA workaround
+config CALGARY_IOMMU
+	bool "IBM Calgary IOMMU support"
+	default y
+	select SWIOTLB
+	depends on PCI && EXPERIMENTAL
+	help
+	  Support for hardware IOMMUs in IBM's xSeries x366 and x460
+	  systems. Needed to run systems with more than 3GB of memory
+	  properly with 32-bit PCI devices that do not support DAC
+	  (Double Address Cycle). Calgary also supports bus level
+	  isolation, where all DMAs pass through the IOMMU.  This
+	  prevents them from going anywhere except their intended
+	  destination. This catches hard-to-find kernel bugs and
+	  mis-behaving drivers and devices that do not use the DMA-API
+	  properly to set up their DMA buffers.  The IOMMU can be
+	  turned off at boot time with the iommu=off parameter.
+	  Normally the kernel will make the right choice by itself.
+	  If unsure, say Y.
+
+# need this always selected by IOMMU for the VIA workaround
 config SWIOTLB
 	bool
-	default y
-	depends on GART_IOMMU
 
 config X86_MCE
 	bool "Machine check support" if EMBEDDED
@@ -501,6 +522,10 @@
          optimal TLB usage. If you have pretty much any version of binutils, 
 	 this can increase your kernel build time by roughly one minute.
 
+config K8_NB
+	def_bool y
+	depends on AGP_AMD64 || IOMMU || (PCI && NUMA)
+
 endmenu
 
 #
diff --git a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug
index ea31b4c..1d92ab5 100644
--- a/arch/x86_64/Kconfig.debug
+++ b/arch/x86_64/Kconfig.debug
@@ -13,7 +13,7 @@
 	 If in doubt, say "N".
 
 config IOMMU_DEBUG
-       depends on GART_IOMMU && DEBUG_KERNEL
+       depends on IOMMU && DEBUG_KERNEL
        bool "Enable IOMMU debugging"
        help
          Force the IOMMU to on even when you have less than 4GB of
@@ -35,6 +35,22 @@
          Add a simple leak tracer to the IOMMU code. This is useful when you
 	 are debugging a buggy device driver that leaks IOMMU mappings.
 
+config DEBUG_STACKOVERFLOW
+        bool "Check for stack overflows"
+        depends on DEBUG_KERNEL
+        help
+	  This option will cause messages to be printed if free stack space
+	  drops below a certain limit.
+
+config DEBUG_STACK_USAGE
+        bool "Stack utilization instrumentation"
+        depends on DEBUG_KERNEL
+        help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T and sysrq-P debug output.
+
+	  This option will slow down process creation somewhat.
+
 #config X86_REMOTE_DEBUG
 #       bool "kgdb debugging stub"
 
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index e573e2a..431bb4b 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -27,6 +27,7 @@
 CHECKFLAGS      += -D__x86_64__ -m64
 
 cflags-y	:=
+cflags-kernel-y	:=
 cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
 cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
 cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
@@ -35,7 +36,7 @@
 cflags-y += -mno-red-zone
 cflags-y += -mcmodel=kernel
 cflags-y += -pipe
-cflags-$(CONFIG_REORDER) += -ffunction-sections
+cflags-kernel-$(CONFIG_REORDER) += -ffunction-sections
 # this makes reading assembly source easier, but produces worse code
 # actually it makes the kernel smaller too.
 cflags-y += -fno-reorder-blocks
@@ -55,6 +56,7 @@
 cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
 
 CFLAGS += $(cflags-y)
+CFLAGS_KERNEL += $(cflags-kernel-y)
 AFLAGS += -m64
 
 head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index 43ee6c5..deb063e 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -107,8 +107,13 @@
 isoimage: $(BOOTIMAGE)
 	-rm -rf $(obj)/isoimage
 	mkdir $(obj)/isoimage
-	cp `echo /usr/lib*/syslinux/isolinux.bin | awk '{ print $1; }'` \
-		$(obj)/isoimage
+	for i in lib lib64 share end ; do \
+		if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
+			cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
+			break ; \
+		fi ; \
+		if [ $$i = end ] ; then exit 1 ; fi ; \
+	done
 	cp $(BOOTIMAGE) $(obj)/isoimage/linux
 	echo '$(image_cmdline)' > $(obj)/isoimage/isolinux.cfg
 	if [ -f '$(FDINITRD)' ] ; then \
diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c
index cf4b88c..3755b2e 100644
--- a/arch/x86_64/boot/compressed/misc.c
+++ b/arch/x86_64/boot/compressed/misc.c
@@ -77,11 +77,11 @@
  */
 static unsigned char *real_mode; /* Pointer to real-mode data */
 
-#define EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
+#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
 #ifndef STANDARD_MEMORY_BIOS_CALL
-#define ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
+#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
 #endif
-#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
 
 extern unsigned char input_data[];
 extern int input_len;
@@ -92,9 +92,9 @@
 
 static void *malloc(int size);
 static void free(void *where);
- 
-void* memset(void* s, int c, unsigned n);
-void* memcpy(void* dest, const void* src, unsigned n);
+
+static void *memset(void *s, int c, unsigned n);
+static void *memcpy(void *dest, const void *src, unsigned n);
 
 static void putstr(const char *);
 
@@ -162,8 +162,8 @@
 	int x,y,pos;
 	char c;
 
-	x = SCREEN_INFO.orig_x;
-	y = SCREEN_INFO.orig_y;
+	x = RM_SCREEN_INFO.orig_x;
+	y = RM_SCREEN_INFO.orig_y;
 
 	while ( ( c = *s++ ) != '\0' ) {
 		if ( c == '\n' ) {
@@ -184,8 +184,8 @@
 		}
 	}
 
-	SCREEN_INFO.orig_x = x;
-	SCREEN_INFO.orig_y = y;
+	RM_SCREEN_INFO.orig_x = x;
+	RM_SCREEN_INFO.orig_y = y;
 
 	pos = (x + cols * y) * 2;	/* Update cursor position */
 	outb_p(14, vidport);
@@ -194,7 +194,7 @@
 	outb_p(0xff & (pos >> 1), vidport+1);
 }
 
-void* memset(void* s, int c, unsigned n)
+static void* memset(void* s, int c, unsigned n)
 {
 	int i;
 	char *ss = (char*)s;
@@ -203,7 +203,7 @@
 	return s;
 }
 
-void* memcpy(void* dest, const void* src, unsigned n)
+static void* memcpy(void* dest, const void* src, unsigned n)
 {
 	int i;
 	char *d = (char *)dest, *s = (char *)src;
@@ -278,15 +278,15 @@
 	putstr(x);
 	putstr("\n\n -- System halted");
 
-	while(1);
+	while(1);	/* Halt */
 }
 
-void setup_normal_output_buffer(void)
+static void setup_normal_output_buffer(void)
 {
 #ifdef STANDARD_MEMORY_BIOS_CALL
-	if (EXT_MEM_K < 1024) error("Less than 2MB of memory");
+	if (RM_EXT_MEM_K < 1024) error("Less than 2MB of memory");
 #else
-	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory");
+	if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory");
 #endif
 	output_data = (unsigned char *)__PHYSICAL_START; /* Normally Points to 1M */
 	free_mem_end_ptr = (long)real_mode;
@@ -297,13 +297,13 @@
 	uch *high_buffer_start; int hcount;
 };
 
-void setup_output_buffer_if_we_run_high(struct moveparams *mv)
+static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
 {
 	high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
 #ifdef STANDARD_MEMORY_BIOS_CALL
-	if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
+	if (RM_EXT_MEM_K < (3*1024)) error("Less than 4MB of memory");
 #else
-	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
+	if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory");
 #endif	
 	mv->low_buffer_start = output_data = (unsigned char *)LOW_BUFFER_START;
 	low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
@@ -319,7 +319,7 @@
 	mv->high_buffer_start = high_buffer_start;
 }
 
-void close_output_buffer_if_we_run_high(struct moveparams *mv)
+static void close_output_buffer_if_we_run_high(struct moveparams *mv)
 {
 	if (bytes_out > low_buffer_size) {
 		mv->lcount = low_buffer_size;
@@ -335,7 +335,7 @@
 {
 	real_mode = rmode;
 
-	if (SCREEN_INFO.orig_video_mode == 7) {
+	if (RM_SCREEN_INFO.orig_video_mode == 7) {
 		vidmem = (char *) 0xb0000;
 		vidport = 0x3b4;
 	} else {
@@ -343,8 +343,8 @@
 		vidport = 0x3d4;
 	}
 
-	lines = SCREEN_INFO.orig_video_lines;
-	cols = SCREEN_INFO.orig_video_cols;
+	lines = RM_SCREEN_INFO.orig_video_lines;
+	cols = RM_SCREEN_INFO.orig_video_cols;
 
 	if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
 	else setup_output_buffer_if_we_run_high(mv);
diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c
index c44f5e2..eae8669 100644
--- a/arch/x86_64/boot/tools/build.c
+++ b/arch/x86_64/boot/tools/build.c
@@ -149,10 +149,8 @@
 	sz = sb.st_size;
 	fprintf (stderr, "System is %d kB\n", sz/1024);
 	sys_size = (sz + 15) / 16;
-	/* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */
-	if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE))
-		die("System is too big. Try using %smodules.",
-			is_big_kernel ? "" : "bzImage or ");
+	if (!is_big_kernel && sys_size > DEF_SYSSIZE)
+		die("System is too big. Try using bzImage or modules.");
 	while (sz > 0) {
 		int l, n;
 
diff --git a/arch/x86_64/boot/video.S b/arch/x86_64/boot/video.S
index 32327bb..2aa565c 100644
--- a/arch/x86_64/boot/video.S
+++ b/arch/x86_64/boot/video.S
@@ -1929,6 +1929,7 @@
 	ret
 
 store_edid:
+#ifdef CONFIG_FIRMWARE_EDID
 	pushw	%es				# just save all registers
 	pushw	%ax
 	pushw	%bx
@@ -1946,6 +1947,22 @@
 	rep
 	stosl
 
+	pushw   %es				# save ES
+	xorw    %di, %di                        # Report Capability
+	pushw   %di
+	popw    %es                             # ES:DI must be 0:0
+	movw	$0x4f15, %ax
+	xorw	%bx, %bx
+	xorw	%cx, %cx
+	int	$0x10
+	popw    %es                             # restore ES
+
+	cmpb    $0x00, %ah                      # call successful
+	jne     no_edid
+
+	cmpb    $0x4f, %al                      # function supported
+	jne     no_edid
+
 	movw	$0x4f15, %ax                    # do VBE/DDC
 	movw	$0x01, %bx
 	movw	$0x00, %cx
@@ -1953,12 +1970,14 @@
 	movw	$0x140, %di
 	int	$0x10
 
+no_edid:
 	popw	%di				# restore all registers
 	popw	%dx
 	popw	%cx
 	popw	%bx
 	popw	%ax
 	popw	%es
+#endif
 	ret
 
 # VIDEO_SELECT-only variables
diff --git a/arch/x86_64/crypto/aes-x86_64-asm.S b/arch/x86_64/crypto/aes-x86_64-asm.S
index 483cbb2..26b40de 100644
--- a/arch/x86_64/crypto/aes-x86_64-asm.S
+++ b/arch/x86_64/crypto/aes-x86_64-asm.S
@@ -15,6 +15,10 @@
 
 .text
 
+#include <asm/asm-offsets.h>
+
+#define BASE crypto_tfm_ctx_offset
+
 #define R1	%rax
 #define R1E	%eax
 #define R1X	%ax
@@ -46,19 +50,19 @@
 #define R10	%r10
 #define R11	%r11
 
-#define prologue(FUNC,BASE,B128,B192,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11) \
+#define prologue(FUNC,KEY,B128,B192,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11) \
 	.global	FUNC;			\
 	.type	FUNC,@function;		\
 	.align	8;			\
 FUNC:	movq	r1,r2;			\
 	movq	r3,r4;			\
-	leaq	BASE+52(r8),r9;		\
+	leaq	BASE+KEY+52(r8),r9;	\
 	movq	r10,r11;		\
 	movl	(r7),r5 ## E;		\
 	movl	4(r7),r1 ## E;		\
 	movl	8(r7),r6 ## E;		\
 	movl	12(r7),r7 ## E;		\
-	movl	(r8),r10 ## E;		\
+	movl	BASE(r8),r10 ## E;	\
 	xorl	-48(r9),r5 ## E;	\
 	xorl	-44(r9),r1 ## E;	\
 	xorl	-40(r9),r6 ## E;	\
@@ -128,8 +132,8 @@
 	movl	r3 ## E,r1 ## E;	\
 	movl	r4 ## E,r2 ## E;
 
-#define entry(FUNC,BASE,B128,B192) \
-	prologue(FUNC,BASE,B128,B192,R2,R8,R7,R9,R1,R3,R4,R6,R10,R5,R11)
+#define entry(FUNC,KEY,B128,B192) \
+	prologue(FUNC,KEY,B128,B192,R2,R8,R7,R9,R1,R3,R4,R6,R10,R5,R11)
 
 #define return epilogue(R8,R2,R9,R7,R5,R6,R3,R4,R11)
 
@@ -147,9 +151,9 @@
 #define decrypt_final(TAB,OFFSET) \
 	round(TAB,OFFSET,R2,R1,R4,R3,R6,R5,R7,R10,R5,R6,R3,R4)
 
-/* void aes_encrypt(void *ctx, u8 *out, const u8 *in) */
+/* void aes_enc_blk(stuct crypto_tfm *tfm, u8 *out, const u8 *in) */
 
-	entry(aes_encrypt,0,enc128,enc192)
+	entry(aes_enc_blk,0,enc128,enc192)
 	encrypt_round(aes_ft_tab,-96)
 	encrypt_round(aes_ft_tab,-80)
 enc192:	encrypt_round(aes_ft_tab,-64)
@@ -166,9 +170,9 @@
 	encrypt_final(aes_fl_tab,112)
 	return
 
-/* void aes_decrypt(void *ctx, u8 *out, const u8 *in) */
+/* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in) */
 
-	entry(aes_decrypt,240,dec128,dec192)
+	entry(aes_dec_blk,240,dec128,dec192)
 	decrypt_round(aes_it_tab,-96)
 	decrypt_round(aes_it_tab,-80)
 dec192:	decrypt_round(aes_it_tab,-64)
diff --git a/arch/x86_64/crypto/aes.c b/arch/x86_64/crypto/aes.c
index 6f77e770..68866fa 100644
--- a/arch/x86_64/crypto/aes.c
+++ b/arch/x86_64/crypto/aes.c
@@ -227,10 +227,10 @@
 	t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;	\
 }
 
-static int aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len,
-		       u32 *flags)
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len, u32 *flags)
 {
-	struct aes_ctx *ctx = ctx_arg;
+	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *key = (const __le32 *)in_key;
 	u32 i, j, t, u, v, w;
 
@@ -283,8 +283,18 @@
 	return 0;
 }
 
-extern void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in);
-extern void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in);
+asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	aes_enc_blk(tfm, dst, src);
+}
+
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
+	aes_dec_blk(tfm, dst, src);
+}
 
 static struct crypto_alg aes_alg = {
 	.cra_name		=	"aes",
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 69db0c0..e69d403 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1-git11
-# Sun Apr 16 07:22:36 2006
+# Linux kernel version: 2.6.17-git6
+# Sat Jun 24 00:52:28 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -42,7 +42,6 @@
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_UID16=y
-CONFIG_VM86=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
@@ -57,7 +56,6 @@
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
-CONFIG_DOUBLEFAULT=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -144,7 +142,8 @@
 CONFIG_HOTPLUG_CPU=y
 CONFIG_HPET_TIMER=y
 CONFIG_HPET_EMULATE_RTC=y
-CONFIG_GART_IOMMU=y
+CONFIG_IOMMU=y
+# CONFIG_CALGARY_IOMMU is not set
 CONFIG_SWIOTLB=y
 CONFIG_X86_MCE=y
 CONFIG_X86_MCE_INTEL=y
@@ -158,6 +157,7 @@
 # CONFIG_HZ_1000 is not set
 CONFIG_HZ=250
 # CONFIG_REORDER is not set
+CONFIG_K8_NB=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_ISA_DMA_API=y
@@ -293,6 +293,8 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -305,7 +307,10 @@
 # CONFIG_INET6_IPCOMP is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
 # CONFIG_IPV6_TUNNEL is not set
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -344,6 +349,7 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -360,6 +366,7 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -526,6 +533,7 @@
 # CONFIG_SCSI_SATA_MV is not set
 CONFIG_SCSI_SATA_NV=y
 # CONFIG_SCSI_PDC_ADMA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_SATA_QSTOR is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
 # CONFIG_SCSI_SATA_SX4 is not set
@@ -591,10 +599,7 @@
 #
 # Device Drivers
 #
-
-#
-# Texas Instruments PCILynx requires I2C
-#
+# CONFIG_IEEE1394_PCILYNX is not set
 CONFIG_IEEE1394_OHCI1394=y
 
 #
@@ -645,7 +650,16 @@
 #
 # Tulip family network device support
 #
-# CONFIG_NET_TULIP is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
@@ -697,6 +711,7 @@
 # CONFIG_IXGB is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -887,7 +902,56 @@
 #
 # I2C support
 #
-# CONFIG_I2C is not set
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
+CONFIG_I2C_ISA=m
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PROSAVAGE is not set
+# CONFIG_I2C_SAVAGE4 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+# CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
 
 #
 # SPI support
@@ -898,14 +962,51 @@
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
 #
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+CONFIG_SENSORS_SMSC47B397=m
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_SENSORS_HDAPS is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
@@ -918,6 +1019,7 @@
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
@@ -953,28 +1055,17 @@
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
-CONFIG_OBSOLETE_OSS_DRIVER=y
 # CONFIG_SOUND_BT878 is not set
-# CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_FUSION is not set
-# CONFIG_SOUND_CS4281 is not set
-# CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
-# CONFIG_SOUND_ESSSOLO1 is not set
-# CONFIG_SOUND_MAESTRO is not set
-# CONFIG_SOUND_MAESTRO3 is not set
 CONFIG_SOUND_ICH=y
-# CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_ALI5455 is not set
-# CONFIG_SOUND_FORTE is not set
-# CONFIG_SOUND_RME96XX is not set
-# CONFIG_SOUND_AD1980 is not set
+# CONFIG_SOUND_TVMIXER is not set
 
 #
 # USB support
@@ -1000,6 +1091,7 @@
 CONFIG_USB_EHCI_HCD=y
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_OHCI_BIG_ENDIAN is not set
@@ -1089,10 +1181,12 @@
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1141,6 +1235,19 @@
 # CONFIG_RTC_CLASS is not set
 
 #
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
 # Firmware Drivers
 #
 # CONFIG_EDD is not set
@@ -1175,6 +1282,7 @@
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
 CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
@@ -1331,7 +1439,8 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_VM is not set
 # CONFIG_FRAME_POINTER is not set
-# CONFIG_UNWIND_INFO is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_DEBUG_RODATA is not set
diff --git a/arch/x86_64/ia32/fpu32.c b/arch/x86_64/ia32/fpu32.c
index 1c23095..2c8209a 100644
--- a/arch/x86_64/ia32/fpu32.c
+++ b/arch/x86_64/ia32/fpu32.c
@@ -2,7 +2,6 @@
  * Copyright 2002 Andi Kleen, SuSE Labs.
  * FXSAVE<->i387 conversion support. Based on code by Gareth Hughes.
  * This is used for ptrace, signals and coredumps in 32bit emulation.
- * $Id: fpu32.c,v 1.1 2002/03/21 14:16:32 ak Exp $
  */ 
 
 #include <linux/sched.h>
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index e0a9243..25e5ca2 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -6,8 +6,6 @@
  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  *  2000-12-*   x86-64 compatibility mode signal handling by Andi Kleen
- * 
- *  $Id: ia32_signal.c,v 1.22 2002/07/29 10:34:03 ak Exp $
  */
 
 #include <linux/sched.h>
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 5a92fed..c536fa9 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -155,6 +155,7 @@
 	.previous
 	jmp	sysenter_do_call
 	CFI_ENDPROC
+ENDPROC(ia32_sysenter_target)
 
 /*
  * 32bit SYSCALL instruction entry.
@@ -178,7 +179,7 @@
  */ 	
 ENTRY(ia32_cstar_target)
 	CFI_STARTPROC32	simple
-	CFI_DEF_CFA	rsp,0
+	CFI_DEF_CFA	rsp,PDA_STACKOFFSET
 	CFI_REGISTER	rip,rcx
 	/*CFI_REGISTER	rflags,r11*/
 	swapgs
@@ -249,6 +250,7 @@
 	.quad 1b,ia32_badarg
 	.previous
 	jmp cstar_do_call
+END(ia32_cstar_target)
 				
 ia32_badarg:
 	movq $-EFAULT,%rax
@@ -314,16 +316,13 @@
 	LOAD_ARGS ARGOFFSET  /* reload args from stack in case ptrace changed it */
 	RESTORE_REST
 	jmp ia32_do_syscall
+END(ia32_syscall)
 
 ia32_badsys:
 	movq $0,ORIG_RAX-ARGOFFSET(%rsp)
 	movq $-ENOSYS,RAX-ARGOFFSET(%rsp)
 	jmp int_ret_from_sys_call
 
-ni_syscall:
-	movq %rax,%rdi
-	jmp  sys32_ni_syscall			
-
 quiet_ni_syscall:
 	movq $-ENOSYS,%rax
 	ret
@@ -370,10 +369,10 @@
 	RESTORE_REST
 	jmp  ia32_sysret	/* misbalances the return cache */
 	CFI_ENDPROC
+END(ia32_ptregs_common)
 
 	.section .rodata,"a"
 	.align 8
-	.globl ia32_sys_call_table
 ia32_sys_call_table:
 	.quad sys_restart_syscall
 	.quad sys_exit
@@ -696,4 +695,5 @@
 	.quad sys_sync_file_range
 	.quad sys_tee
 	.quad compat_sys_vmsplice
+	.quad compat_sys_move_pages
 ia32_syscall_end:		
diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c
index 23a4515..a590b7a 100644
--- a/arch/x86_64/ia32/ptrace32.c
+++ b/arch/x86_64/ia32/ptrace32.c
@@ -7,8 +7,6 @@
  * 
  * This allows to access 64bit processes too; but there is no way to see the extended 
  * register contents.
- *
- * $Id: ptrace32.c,v 1.16 2003/03/14 16:06:35 ak Exp $
  */ 
 
 #include <linux/kernel.h>
@@ -27,6 +25,7 @@
 #include <asm/debugreg.h>
 #include <asm/i387.h>
 #include <asm/fpu32.h>
+#include <asm/ia32.h>
 
 /*
  * Determines which flags the user has access to [1 = access, 0 = no access].
@@ -199,6 +198,24 @@
 
 #undef R32
 
+static long ptrace32_siginfo(unsigned request, u32 pid, u32 addr, u32 data)
+{
+	int ret;
+	compat_siginfo_t *si32 = (compat_siginfo_t *)compat_ptr(data);
+	siginfo_t *si = compat_alloc_user_space(sizeof(siginfo_t));
+	if (request == PTRACE_SETSIGINFO) {
+		ret = copy_siginfo_from_user32(si, si32);
+		if (ret)
+			return ret;
+	}
+	ret = sys_ptrace(request, pid, addr, (unsigned long)si);
+	if (ret)
+		return ret;
+	if (request == PTRACE_GETSIGINFO)
+		ret = copy_siginfo_to_user32(si32, si);
+	return ret;
+}
+
 asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
 {
 	struct task_struct *child;
@@ -208,9 +225,19 @@
 	__u32 val;
 
 	switch (request) { 
-	default:
+	case PTRACE_TRACEME:
+	case PTRACE_ATTACH:
+	case PTRACE_KILL:
+	case PTRACE_CONT:
+	case PTRACE_SINGLESTEP:
+	case PTRACE_DETACH:
+	case PTRACE_SYSCALL:
+	case PTRACE_SETOPTIONS:
 		return sys_ptrace(request, pid, addr, data); 
 
+	default:
+		return -EINVAL;
+
 	case PTRACE_PEEKTEXT:
 	case PTRACE_PEEKDATA:
 	case PTRACE_POKEDATA:
@@ -225,10 +252,11 @@
 	case PTRACE_GETFPXREGS:
 	case PTRACE_GETEVENTMSG:
 		break;
-	} 
 
-	if (request == PTRACE_TRACEME)
-		return ptrace_traceme();
+	case PTRACE_SETSIGINFO:
+	case PTRACE_GETSIGINFO:
+		return ptrace32_siginfo(request, pid, addr, data);
+	}
 
 	child = ptrace_get_task_struct(pid);
 	if (IS_ERR(child))
@@ -349,8 +377,7 @@
 		break;
 
 	default:
-		ret = -EINVAL;
-		break;
+		BUG();
 	}
 
  out:
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index f182b20..dc88154 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -508,19 +508,6 @@
 	return compat_sys_wait4(pid, stat_addr, options, NULL);
 }
 
-int sys32_ni_syscall(int call)
-{ 
-	struct task_struct *me = current;
-	static char lastcomm[sizeof(me->comm)];
-
-	if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) {
-		printk(KERN_INFO "IA32 syscall %d from %s not implemented\n",
-		       call, me->comm);
-		strncpy(lastcomm, me->comm, sizeof(lastcomm));
-	} 
-	return -ENOSYS;	       
-} 
-
 /* 32-bit timeval and related flotsam.  */
 
 asmlinkage long
@@ -916,7 +903,7 @@
 	struct task_struct *me = current;
 	static char lastcomm[sizeof(me->comm)];
 	if (strncmp(lastcomm, me->comm, sizeof(lastcomm))) {
-		printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n",
+		compat_printk(KERN_INFO "%s: vm86 mode not supported on 64 bit kernel\n",
 		       me->comm);
 		strncpy(lastcomm, me->comm, sizeof(lastcomm));
 	} 
@@ -929,13 +916,3 @@
 	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len);
 }
 
-static int __init ia32_init (void)
-{
-	printk("IA32 emulation $Id: sys_ia32.c,v 1.32 2002/03/24 13:02:28 ak Exp $\n");  
-	return 0;
-}
-
-__initcall(ia32_init);
-
-extern unsigned long ia32_sys_call_table[];
-EXPORT_SYMBOL(ia32_sys_call_table);
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index 059c883..aeb9c56 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -8,7 +8,7 @@
 		ptrace.o time.o ioport.o ldt.o setup.o i8259.o sys_x86_64.o \
 		x8664_ksyms.o i387.o syscall.o vsyscall.o \
 		setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \
-		pci-dma.o pci-nommu.o
+		pci-dma.o pci-nommu.o alternative.o
 
 obj-$(CONFIG_X86_MCE)         += mce.o
 obj-$(CONFIG_X86_MCE_INTEL)	+= mce_intel.o
@@ -28,11 +28,13 @@
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend_asm.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
-obj-$(CONFIG_GART_IOMMU)	+= pci-gart.o aperture.o
+obj-$(CONFIG_IOMMU)		+= pci-gart.o aperture.o
+obj-$(CONFIG_CALGARY_IOMMU)	+= pci-calgary.o tce.o
 obj-$(CONFIG_SWIOTLB)		+= pci-swiotlb.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer.o
 obj-$(CONFIG_X86_VSMP)		+= vsmp.o
+obj-$(CONFIG_K8_NB)		+= k8.o
 
 obj-$(CONFIG_MODULES)		+= module.o
 
@@ -49,3 +51,5 @@
 quirks-y			+= ../../i386/kernel/quirks.o
 i8237-y				+= ../../i386/kernel/i8237.o
 msr-$(subst m,y,$(CONFIG_X86_MSR))  += ../../i386/kernel/msr.o
+alternative-y			+= ../../i386/kernel/alternative.o
+
diff --git a/arch/x86_64/kernel/acpi/Makefile b/arch/x86_64/kernel/acpi/Makefile
index 4fe9707..080b996 100644
--- a/arch/x86_64/kernel/acpi/Makefile
+++ b/arch/x86_64/kernel/acpi/Makefile
@@ -4,5 +4,6 @@
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
 obj-y			+= processor.o
+processor-y		:= ../../../i386/kernel/acpi/processor.o ../../../i386/kernel/acpi/cstate.o
 endif
 
diff --git a/arch/x86_64/kernel/acpi/processor.c b/arch/x86_64/kernel/acpi/processor.c
deleted file mode 100644
index 3bdc2ba..0000000
--- a/arch/x86_64/kernel/acpi/processor.c
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * arch/x86_64/kernel/acpi/processor.c
- *
- * Copyright (C) 2005 Intel Corporation
- * 	Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
- * 	- Added _PDC for platforms with Intel CPUs
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-
-#include <acpi/processor.h>
-#include <asm/acpi.h>
-
-static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
-{
-	struct acpi_object_list *obj_list;
-	union acpi_object *obj;
-	u32 *buf;
-
-	/* allocate and initialize pdc. It will be used later. */
-	obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL);
-	if (!obj_list) {
-		printk(KERN_ERR "Memory allocation error\n");
-		return;
-	}
-
-	obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL);
-	if (!obj) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj_list);
-		return;
-	}
-
-	buf = kmalloc(12, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_ERR "Memory allocation error\n");
-		kfree(obj);
-		kfree(obj_list);
-		return;
-	}
-
-	buf[0] = ACPI_PDC_REVISION_ID;
-	buf[1] = 1;
-	buf[2] = ACPI_PDC_EST_CAPABILITY_SMP;
-
-	obj->type = ACPI_TYPE_BUFFER;
-	obj->buffer.length = 12;
-	obj->buffer.pointer = (u8 *) buf;
-	obj_list->count = 1;
-	obj_list->pointer = obj;
-	pr->pdc = obj_list;
-
-	return;
-}
-
-/* Initialize _PDC data based on the CPU vendor */
-void arch_acpi_processor_init_pdc(struct acpi_processor *pr)
-{
-	unsigned int cpu = pr->id;
-	struct cpuinfo_x86 *c = cpu_data + cpu;
-
-	pr->pdc = NULL;
-	if (c->x86_vendor == X86_VENDOR_INTEL && cpu_has(c, X86_FEATURE_EST))
-		init_intel_pdc(pr, c);
-
-	return;
-}
-
-EXPORT_SYMBOL(arch_acpi_processor_init_pdc);
diff --git a/arch/x86_64/kernel/acpi/sleep.c b/arch/x86_64/kernel/acpi/sleep.c
index 867a0ebe..091bc79 100644
--- a/arch/x86_64/kernel/acpi/sleep.c
+++ b/arch/x86_64/kernel/acpi/sleep.c
@@ -35,6 +35,8 @@
 #include <linux/pci.h>
 #include <linux/bootmem.h>
 #include <linux/acpi.h>
+#include <linux/cpumask.h>
+
 #include <asm/mpspec.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -66,7 +68,8 @@
 	pgd_t *slot0 = pgd_offset(current->mm, 0UL);
 	low_ptr = *slot0;
 	set_pgd(slot0, *pgd_offset(current->mm, PAGE_OFFSET));
-	flush_tlb_all();
+	WARN_ON(num_online_cpus() != 1);
+	local_flush_tlb();
 }
 
 /**
@@ -92,7 +95,7 @@
 void acpi_restore_state_mem(void)
 {
 	set_pgd(pgd_offset(current->mm, 0UL), low_ptr);
-	flush_tlb_all();
+	local_flush_tlb();
 }
 
 /**
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index 70b9d21..a195ef0 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -8,7 +8,6 @@
  * because only the bootmem allocator can allocate 32+MB. 
  * 
  * Copyright 2002 Andi Kleen, SuSE Labs.
- * $Id: aperture.c,v 1.7 2003/08/01 03:36:18 ak Exp $
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -24,6 +23,7 @@
 #include <asm/proto.h>
 #include <asm/pci-direct.h>
 #include <asm/dma.h>
+#include <asm/k8.h>
 
 int iommu_aperture;
 int iommu_aperture_disabled __initdata = 0;
@@ -37,8 +37,6 @@
 /* This code runs before the PCI subsystem is initialized, so just
    access the northbridge directly. */
 
-#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
-
 static u32 __init allocate_aperture(void) 
 {
 	pg_data_t *nd0 = NODE_DATA(0);
@@ -68,20 +66,20 @@
 	return (u32)__pa(p); 
 }
 
-static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size) 
+static int __init aperture_valid(u64 aper_base, u32 aper_size)
 { 
 	if (!aper_base) 
 		return 0;
 	if (aper_size < 64*1024*1024) { 
-		printk("Aperture from %s too small (%d MB)\n", name, aper_size>>20); 
+		printk("Aperture too small (%d MB)\n", aper_size>>20);
 		return 0;
 	}
 	if (aper_base + aper_size >= 0xffffffff) { 
-		printk("Aperture from %s beyond 4GB. Ignoring.\n",name);
+		printk("Aperture beyond 4GB. Ignoring.\n");
 		return 0; 
 	}
 	if (e820_any_mapped(aper_base, aper_base + aper_size, E820_RAM)) {
-		printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
+		printk("Aperture pointing to e820 RAM. Ignoring.\n");
 		return 0; 
 	} 
 	return 1;
@@ -140,7 +138,7 @@
 	printk("Aperture from AGP @ %Lx size %u MB (APSIZE %x)\n", 
 	       aper, 32 << *order, apsizereg);
 
-	if (!aperture_valid("AGP bridge", aper, (32*1024*1024) << *order))
+	if (!aperture_valid(aper, (32*1024*1024) << *order))
 	    return 0;
 	return (u32)aper; 
 } 
@@ -208,10 +206,10 @@
 
 	fix = 0;
 	for (num = 24; num < 32; num++) {		
-		char name[30];
-		if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
-			continue;	
+		if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
+			continue;
 
+		iommu_detected = 1;
 		iommu_aperture = 1; 
 
 		aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; 
@@ -222,9 +220,7 @@
 		printk("CPU %d: aperture @ %Lx size %u MB\n", num-24, 
 		       aper_base, aper_size>>20);
 		
-		sprintf(name, "northbridge cpu %d", num-24); 
-
-		if (!aperture_valid(name, aper_base, aper_size)) { 
+		if (!aperture_valid(aper_base, aper_size)) {
 			fix = 1; 
 			break; 
 		}
@@ -273,7 +269,7 @@
 
 	/* Fix up the north bridges */
 	for (num = 24; num < 32; num++) { 		
-		if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) 
+		if (!early_is_k8_nb(read_pci_config(0, num, 3, 0x00)))
 			continue;	
 
 		/* Don't enable translation yet. That is done later. 
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 100a30c..b2ead91 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -51,7 +51,7 @@
 static cpumask_t timer_interrupt_broadcast_ipi_mask;
 
 /* Using APIC to generate smp_local_timer_interrupt? */
-int using_apic_timer = 0;
+int using_apic_timer __read_mostly = 0;
 
 static void apic_pm_activate(void);
 
@@ -100,7 +100,7 @@
 	maxlvt = get_maxlvt();
 
 	/*
-	 * Masking an LVT entry on a P6 can trigger a local APIC error
+	 * Masking an LVT entry can trigger a local APIC error
 	 * if the vector is zero. Mask LVTERR first to prevent this.
 	 */
 	if (maxlvt >= 3) {
@@ -851,7 +851,18 @@
 		unsigned long v;
 
 		v = apic_read(APIC_LVTT);
-		apic_write(APIC_LVTT, v | APIC_LVT_MASKED);
+		/*
+		 * When an illegal vector value (0-15) is written to an LVT
+		 * entry and delivery mode is Fixed, the APIC may signal an
+		 * illegal vector error, with out regard to whether the mask
+		 * bit is set or whether an interrupt is actually seen on input.
+		 *
+		 * Boot sequence might call this function when the LVTT has
+		 * '0' vector value. So make sure vector field is set to
+		 * valid value.
+		 */
+		v |= (APIC_LVT_MASKED | LOCAL_TIMER_VECTOR);
+		apic_write(APIC_LVTT, v);
 	}
 }
 
@@ -909,15 +920,13 @@
 	return -EINVAL;
 }
 
-#ifdef CONFIG_X86_MCE_AMD
-void setup_threshold_lvt(unsigned long lvt_off)
+void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
+			    unsigned char msg_type, unsigned char mask)
 {
-	unsigned int v = 0;
-	unsigned long reg = (lvt_off << 4) + 0x500;
-	v |= THRESHOLD_APIC_VECTOR;
+	unsigned long reg = (lvt_off << 4) + K8_APIC_EXT_LVT_BASE;
+	unsigned int  v   = (mask << 16) | (msg_type << 8) | vector;
 	apic_write(reg, v);
 }
-#endif /* CONFIG_X86_MCE_AMD */
 
 #undef APIC_DIVISOR
 
@@ -983,7 +992,7 @@
 }
 
 /*
- * oem_force_hpet_timer -- force HPET mode for some boxes.
+ * apic_is_clustered_box() -- Check if we can expect good TSC
  *
  * Thus far, the major user of this is IBM's Summit2 series:
  *
@@ -991,7 +1000,7 @@
  * multi-chassis. Use available data to take a good guess.
  * If in doubt, go HPET.
  */
-__cpuinit int oem_force_hpet_timer(void)
+__cpuinit int apic_is_clustered_box(void)
 {
 	int i, clusters, zeros;
 	unsigned id;
@@ -1022,8 +1031,7 @@
 	}
 
 	/*
-	 * If clusters > 2, then should be multi-chassis.  Return 1 for HPET.
-	 * Else return 0 to use TSC.
+	 * If clusters > 2, then should be multi-chassis.
 	 * May have to revisit this when multi-core + hyperthreaded CPUs come
 	 * out, but AFAIK this will work even for them.
 	 */
diff --git a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c
index 38834bb..96687e2b 100644
--- a/arch/x86_64/kernel/asm-offsets.c
+++ b/arch/x86_64/kernel/asm-offsets.c
@@ -4,6 +4,7 @@
  * and format the required data.
  */
 
+#include <linux/crypto.h>
 #include <linux/sched.h> 
 #include <linux/stddef.h>
 #include <linux/errno.h> 
@@ -68,5 +69,7 @@
 	DEFINE(pbe_next, offsetof(struct pbe, next));
 	BLANK();
 	DEFINE(TSS_ist, offsetof(struct tss_struct, ist));
+	BLANK();
+	DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
 	return 0;
 }
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
index 4e6c3b7..d8d5750 100644
--- a/arch/x86_64/kernel/crash.c
+++ b/arch/x86_64/kernel/crash.c
@@ -111,14 +111,14 @@
 	atomic_dec(&waiting_for_crash_ipi);
 	/* Assume hlt works */
 	for(;;)
-		asm("hlt");
+		halt();
 
 	return 1;
 }
 
 static void smp_send_nmi_allbutself(void)
 {
-	send_IPI_allbutself(APIC_DM_NMI);
+	send_IPI_allbutself(NMI_VECTOR);
 }
 
 /*
@@ -161,7 +161,7 @@
 {
 	/*
 	 * This function is only called after the system
-	 * has paniced or is otherwise in a critical state.
+	 * has panicked or is otherwise in a critical state.
 	 * The minimum amount of code to allow a kexec'd kernel
 	 * to run successfully needs to happen here.
 	 *
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 1ef6028f..9e94d83 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -1,7 +1,6 @@
 /* 
  * Handle the memory map.
  * The functions here do the job until bootmem takes over.
- * $Id: e820.c,v 1.4 2002/09/19 19:25:32 ak Exp $
  *
  *  Getting sanitize_e820_map() in sync with i386 version by applying change:
  *  -  Provisions for empty E820 memory regions (reported by certain BIOSes).
@@ -621,6 +620,7 @@
 }
 
 unsigned long pci_mem_start = 0xaeedbabe;
+EXPORT_SYMBOL(pci_mem_start);
 
 /*
  * Search for the biggest gap in the low 32 bits of the e820
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 586b34c..22cac44 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -154,6 +154,7 @@
 	GET_THREAD_INFO(%rcx)	
 	jmp rff_action
 	CFI_ENDPROC
+END(ret_from_fork)
 
 /*
  * System call entry. Upto 6 arguments in registers are supported.
@@ -188,7 +189,7 @@
 
 ENTRY(system_call)
 	CFI_STARTPROC	simple
-	CFI_DEF_CFA	rsp,0
+	CFI_DEF_CFA	rsp,PDA_STACKOFFSET
 	CFI_REGISTER	rip,rcx
 	/*CFI_REGISTER	rflags,r11*/
 	swapgs
@@ -285,6 +286,7 @@
 	/* Use IRET because user could have changed frame */
 	jmp int_ret_from_sys_call
 	CFI_ENDPROC
+END(system_call)
 		
 /* 
  * Syscall return path ending with IRET.
@@ -364,6 +366,7 @@
 	cli
 	jmp int_with_check
 	CFI_ENDPROC
+END(int_ret_from_sys_call)
 		
 /* 
  * Certain special system calls that need to save a complete full stack frame.
@@ -375,6 +378,7 @@
 	leaq	\func(%rip),%rax
 	leaq    -ARGOFFSET+8(%rsp),\arg /* 8 for return address */
 	jmp	ptregscall_common
+END(\label)
 	.endm
 
 	CFI_STARTPROC
@@ -404,6 +408,7 @@
 	CFI_REL_OFFSET rip, 0
 	ret
 	CFI_ENDPROC
+END(ptregscall_common)
 	
 ENTRY(stub_execve)
 	CFI_STARTPROC
@@ -418,6 +423,7 @@
 	RESTORE_REST
 	jmp int_ret_from_sys_call
 	CFI_ENDPROC
+END(stub_execve)
 	
 /*
  * sigreturn is special because it needs to restore all registers on return.
@@ -435,6 +441,7 @@
 	RESTORE_REST
 	jmp int_ret_from_sys_call
 	CFI_ENDPROC
+END(stub_rt_sigreturn)
 
 /*
  * initial frame state for interrupts and exceptions
@@ -466,29 +473,18 @@
 /* 0(%rsp): interrupt number */ 
 	.macro interrupt func
 	cld
-#ifdef CONFIG_DEBUG_INFO
-	SAVE_ALL	
-	movq %rsp,%rdi
-	/*
-	 * Setup a stack frame pointer.  This allows gdb to trace
-	 * back to the original stack.
-	 */
-	movq %rsp,%rbp
-	CFI_DEF_CFA_REGISTER	rbp
-#else		
 	SAVE_ARGS
 	leaq -ARGOFFSET(%rsp),%rdi	# arg1 for handler
-#endif	
+	pushq %rbp
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET		rbp, 0
+	movq %rsp,%rbp
+	CFI_DEF_CFA_REGISTER	rbp
 	testl $3,CS(%rdi)
 	je 1f
 	swapgs	
 1:	incl	%gs:pda_irqcount	# RED-PEN should check preempt count
-	movq %gs:pda_irqstackptr,%rax
-	cmoveq %rax,%rsp /*todo This needs CFI annotation! */
-	pushq %rdi			# save old stack	
-#ifndef CONFIG_DEBUG_INFO
-	CFI_ADJUST_CFA_OFFSET	8
-#endif
+	cmoveq %gs:pda_irqstackptr,%rsp
 	call \func
 	.endm
 
@@ -497,17 +493,11 @@
 	interrupt do_IRQ
 	/* 0(%rsp): oldrsp-ARGOFFSET */
 ret_from_intr:
-	popq  %rdi
-#ifndef CONFIG_DEBUG_INFO
-	CFI_ADJUST_CFA_OFFSET	-8
-#endif
 	cli	
 	decl %gs:pda_irqcount
-#ifdef CONFIG_DEBUG_INFO
-	movq RBP(%rdi),%rbp
+	leaveq
 	CFI_DEF_CFA_REGISTER	rsp
-#endif
-	leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */
+	CFI_ADJUST_CFA_OFFSET	-8
 exit_intr:
 	GET_THREAD_INFO(%rcx)
 	testl $3,CS-ARGOFFSET(%rsp)
@@ -589,14 +579,16 @@
 	call preempt_schedule_irq
 	jmp exit_intr
 #endif	
+
 	CFI_ENDPROC
+END(common_interrupt)
 	
 /*
  * APIC interrupts.
  */		
 	.macro apicinterrupt num,func
 	INTR_FRAME
-	pushq $\num-256
+	pushq $~(\num)
 	CFI_ADJUST_CFA_OFFSET 8
 	interrupt \func
 	jmp ret_from_intr
@@ -605,17 +597,21 @@
 
 ENTRY(thermal_interrupt)
 	apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt
+END(thermal_interrupt)
 
 ENTRY(threshold_interrupt)
 	apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt
+END(threshold_interrupt)
 
 #ifdef CONFIG_SMP	
 ENTRY(reschedule_interrupt)
 	apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt
+END(reschedule_interrupt)
 
 	.macro INVALIDATE_ENTRY num
 ENTRY(invalidate_interrupt\num)
 	apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt	
+END(invalidate_interrupt\num)
 	.endm
 
 	INVALIDATE_ENTRY 0
@@ -629,17 +625,21 @@
 
 ENTRY(call_function_interrupt)
 	apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt
+END(call_function_interrupt)
 #endif
 
 #ifdef CONFIG_X86_LOCAL_APIC	
 ENTRY(apic_timer_interrupt)
 	apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
+END(apic_timer_interrupt)
 
 ENTRY(error_interrupt)
 	apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt
+END(error_interrupt)
 
 ENTRY(spurious_interrupt)
 	apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
+END(spurious_interrupt)
 #endif
 				
 /*
@@ -777,6 +777,7 @@
 	cmpq $gs_change,RIP(%rsp)
         je   error_swapgs
 	jmp  error_sti
+END(error_entry)
 	
        /* Reload gs selector with exception handling */
        /* edi:  new selector */ 
@@ -794,6 +795,7 @@
 	CFI_ADJUST_CFA_OFFSET -8
         ret
 	CFI_ENDPROC
+ENDPROC(load_gs_index)
        
         .section __ex_table,"a"
         .align 8
@@ -847,7 +849,7 @@
 	UNFAKE_STACK_FRAME
 	ret
 	CFI_ENDPROC
-
+ENDPROC(kernel_thread)
 	
 child_rip:
 	/*
@@ -860,6 +862,7 @@
 	# exit
 	xorl %edi, %edi
 	call do_exit
+ENDPROC(child_rip)
 
 /*
  * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
@@ -889,19 +892,24 @@
 	UNFAKE_STACK_FRAME
 	ret
 	CFI_ENDPROC
+ENDPROC(execve)
 
 KPROBE_ENTRY(page_fault)
 	errorentry do_page_fault
+END(page_fault)
 	.previous .text
 
 ENTRY(coprocessor_error)
 	zeroentry do_coprocessor_error
+END(coprocessor_error)
 
 ENTRY(simd_coprocessor_error)
 	zeroentry do_simd_coprocessor_error	
+END(simd_coprocessor_error)
 
 ENTRY(device_not_available)
 	zeroentry math_state_restore
+END(device_not_available)
 
 	/* runs on exception stack */
 KPROBE_ENTRY(debug)
@@ -911,6 +919,7 @@
 	paranoidentry do_debug, DEBUG_STACK
 	jmp paranoid_exit
 	CFI_ENDPROC
+END(debug)
 	.previous .text
 
 	/* runs on exception stack */	
@@ -961,6 +970,7 @@
 	cli
 	jmp paranoid_userspace
 	CFI_ENDPROC
+END(nmi)
 	.previous .text
 
 KPROBE_ENTRY(int3)
@@ -970,22 +980,28 @@
  	paranoidentry do_int3, DEBUG_STACK
  	jmp paranoid_exit
  	CFI_ENDPROC
+END(int3)
 	.previous .text
 
 ENTRY(overflow)
 	zeroentry do_overflow
+END(overflow)
 
 ENTRY(bounds)
 	zeroentry do_bounds
+END(bounds)
 
 ENTRY(invalid_op)
 	zeroentry do_invalid_op	
+END(invalid_op)
 
 ENTRY(coprocessor_segment_overrun)
 	zeroentry do_coprocessor_segment_overrun
+END(coprocessor_segment_overrun)
 
 ENTRY(reserved)
 	zeroentry do_reserved
+END(reserved)
 
 	/* runs on exception stack */
 ENTRY(double_fault)
@@ -993,12 +1009,15 @@
 	paranoidentry do_double_fault
 	jmp paranoid_exit
 	CFI_ENDPROC
+END(double_fault)
 
 ENTRY(invalid_TSS)
 	errorentry do_invalid_TSS
+END(invalid_TSS)
 
 ENTRY(segment_not_present)
 	errorentry do_segment_not_present
+END(segment_not_present)
 
 	/* runs on exception stack */
 ENTRY(stack_segment)
@@ -1006,19 +1025,24 @@
 	paranoidentry do_stack_segment
 	jmp paranoid_exit
 	CFI_ENDPROC
+END(stack_segment)
 
 KPROBE_ENTRY(general_protection)
 	errorentry do_general_protection
+END(general_protection)
 	.previous .text
 
 ENTRY(alignment_check)
 	errorentry do_alignment_check
+END(alignment_check)
 
 ENTRY(divide_error)
 	zeroentry do_divide_error
+END(divide_error)
 
 ENTRY(spurious_interrupt_bug)
 	zeroentry do_spurious_interrupt_bug
+END(spurious_interrupt_bug)
 
 #ifdef CONFIG_X86_MCE
 	/* runs on exception stack */
@@ -1029,6 +1053,7 @@
 	paranoidentry do_machine_check
 	jmp paranoid_exit
 	CFI_ENDPROC
+END(machine_check)
 #endif
 
 ENTRY(call_softirq)
@@ -1046,3 +1071,37 @@
 	decl %gs:pda_irqcount
 	ret
 	CFI_ENDPROC
+ENDPROC(call_softirq)
+
+#ifdef CONFIG_STACK_UNWIND
+ENTRY(arch_unwind_init_running)
+	CFI_STARTPROC
+	movq	%r15, R15(%rdi)
+	movq	%r14, R14(%rdi)
+	xchgq	%rsi, %rdx
+	movq	%r13, R13(%rdi)
+	movq	%r12, R12(%rdi)
+	xorl	%eax, %eax
+	movq	%rbp, RBP(%rdi)
+	movq	%rbx, RBX(%rdi)
+	movq	(%rsp), %rcx
+	movq	%rax, R11(%rdi)
+	movq	%rax, R10(%rdi)
+	movq	%rax, R9(%rdi)
+	movq	%rax, R8(%rdi)
+	movq	%rax, RAX(%rdi)
+	movq	%rax, RCX(%rdi)
+	movq	%rax, RDX(%rdi)
+	movq	%rax, RSI(%rdi)
+	movq	%rax, RDI(%rdi)
+	movq	%rax, ORIG_RAX(%rdi)
+	movq	%rcx, RIP(%rdi)
+	leaq	8(%rsp), %rcx
+	movq	$__KERNEL_CS, CS(%rdi)
+	movq	%rax, EFLAGS(%rdi)
+	movq	%rcx, RSP(%rdi)
+	movq	$__KERNEL_DS, SS(%rdi)
+	jmpq	*%rdx
+	CFI_ENDPROC
+ENDPROC(arch_unwind_init_running)
+#endif
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index 1a2ab825..21c7066 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -78,22 +78,29 @@
 
 static void flat_send_IPI_allbutself(int vector)
 {
-#ifndef CONFIG_HOTPLUG_CPU
-	if (((num_online_cpus()) - 1) >= 1)
-		__send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL);
+#ifdef	CONFIG_HOTPLUG_CPU
+	int hotplug = 1;
 #else
-	cpumask_t allbutme = cpu_online_map;
-
-	cpu_clear(smp_processor_id(), allbutme);
-
-	if (!cpus_empty(allbutme))
-		flat_send_IPI_mask(allbutme, vector);
+	int hotplug = 0;
 #endif
+	if (hotplug || vector == NMI_VECTOR) {
+		cpumask_t allbutme = cpu_online_map;
+
+		cpu_clear(smp_processor_id(), allbutme);
+
+		if (!cpus_empty(allbutme))
+			flat_send_IPI_mask(allbutme, vector);
+	} else if (num_online_cpus() > 1) {
+		__send_IPI_shortcut(APIC_DEST_ALLBUT, vector,APIC_DEST_LOGICAL);
+	}
 }
 
 static void flat_send_IPI_all(int vector)
 {
-	__send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
+	if (vector == NMI_VECTOR)
+		flat_send_IPI_mask(cpu_online_map, vector);
+	else
+		__send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
 }
 
 static int flat_apic_id_registered(void)
@@ -108,10 +115,7 @@
 
 static unsigned int phys_pkg_id(int index_msb)
 {
-	u32 ebx;
-
-	ebx = cpuid_ebx(1);
-	return ((ebx >> 24) & 0xFF) >> index_msb;
+	return hard_smp_processor_id() >> index_msb;
 }
 
 struct genapic apic_flat =  {
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index cea20a6..e6a71c9 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -2,8 +2,6 @@
  *  linux/arch/x86_64/kernel/head64.c -- prepare to run common code
  *
  *  Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE
- *
- *  $Id: head64.c,v 1.22 2001/07/06 14:28:20 ak Exp $
  */
 
 #include <linux/init.h>
diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c
index a5d7e16..44ddb1e 100644
--- a/arch/x86_64/kernel/i387.c
+++ b/arch/x86_64/kernel/i387.c
@@ -24,7 +24,7 @@
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
 
-unsigned int mxcsr_feature_mask = 0xffffffff;
+unsigned int mxcsr_feature_mask __read_mostly = 0xffffffff;
 
 void mxcsr_feature_mask_init(void)
 {
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 5ecd34a..86b2c1e 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -44,11 +44,11 @@
 	BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
 	BI(x,c) BI(x,d) BI(x,e) BI(x,f)
 
-#define BUILD_14_IRQS(x) \
+#define BUILD_15_IRQS(x) \
 	BI(x,0) BI(x,1) BI(x,2) BI(x,3) \
 	BI(x,4) BI(x,5) BI(x,6) BI(x,7) \
 	BI(x,8) BI(x,9) BI(x,a) BI(x,b) \
-	BI(x,c) BI(x,d)
+	BI(x,c) BI(x,d) BI(x,e)
 
 /*
  * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
@@ -73,13 +73,13 @@
 BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
 
 #ifdef CONFIG_PCI_MSI
-	BUILD_14_IRQS(0xe)
+	BUILD_15_IRQS(0xe)
 #endif
 
 #endif
 
 #undef BUILD_16_IRQS
-#undef BUILD_14_IRQS
+#undef BUILD_15_IRQS
 #undef BI
 
 
@@ -92,11 +92,11 @@
 	IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
 	IRQ(x,c), IRQ(x,d), IRQ(x,e), IRQ(x,f)
 
-#define IRQLIST_14(x) \
+#define IRQLIST_15(x) \
 	IRQ(x,0), IRQ(x,1), IRQ(x,2), IRQ(x,3), \
 	IRQ(x,4), IRQ(x,5), IRQ(x,6), IRQ(x,7), \
 	IRQ(x,8), IRQ(x,9), IRQ(x,a), IRQ(x,b), \
-	IRQ(x,c), IRQ(x,d)
+	IRQ(x,c), IRQ(x,d), IRQ(x,e)
 
 void (*interrupt[NR_IRQS])(void) = {
 	IRQLIST_16(0x0),
@@ -108,7 +108,7 @@
 	IRQLIST_16(0xc), IRQLIST_16(0xd)
 
 #ifdef CONFIG_PCI_MSI
-	, IRQLIST_14(0xe)
+	, IRQLIST_15(0xe)
 #endif
 
 #endif
@@ -278,7 +278,7 @@
 	 * Lightweight spurious IRQ detection. We do not want
 	 * to overdo spurious IRQ handling - it's usually a sign
 	 * of hardware problems, so we only do the checks we can
-	 * do without slowing down good hardware unnecesserily.
+	 * do without slowing down good hardware unnecessarily.
 	 *
 	 * Note that IRQ7 and IRQ15 (the two spurious IRQs
 	 * usually resulting from the 8259A-1|2 PICs) occur
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 9cc7031..c768d8a 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -41,6 +41,7 @@
 #include <asm/mach_apic.h>
 #include <asm/acpi.h>
 #include <asm/dma.h>
+#include <asm/nmi.h>
 
 #define __apicdebuginit  __init
 
@@ -56,6 +57,7 @@
 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 };
 
 static DEFINE_SPINLOCK(ioapic_lock);
+static DEFINE_SPINLOCK(vector_lock);
 
 /*
  * # of IRQ routing registers
@@ -317,7 +319,7 @@
 				vendor &= 0xffff;
 				switch (vendor) { 
 				case PCI_VENDOR_ID_VIA:
-#ifdef CONFIG_GART_IOMMU
+#ifdef CONFIG_IOMMU
 					if ((end_pfn > MAX_DMA32_PFN ||
 					     force_iommu) &&
 					    !iommu_aperture_allowed) {
@@ -834,10 +836,17 @@
 int assign_irq_vector(int irq)
 {
 	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
+	unsigned long flags;
+	int vector;
 
 	BUG_ON(irq != AUTO_ASSIGN && (unsigned)irq >= NR_IRQ_VECTORS);
-	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0)
+
+	spin_lock_irqsave(&vector_lock, flags);
+
+	if (irq != AUTO_ASSIGN && IO_APIC_VECTOR(irq) > 0) {
+		spin_unlock_irqrestore(&vector_lock, flags);
 		return IO_APIC_VECTOR(irq);
+	}
 next:
 	current_vector += 8;
 	if (current_vector == IA32_SYSCALL_VECTOR)
@@ -849,11 +858,14 @@
 		current_vector = FIRST_DEVICE_VECTOR + offset;
 	}
 
-	vector_irq[current_vector] = irq;
+	vector = current_vector;
+	vector_irq[vector] = irq;
 	if (irq != AUTO_ASSIGN)
-		IO_APIC_VECTOR(irq) = current_vector;
+		IO_APIC_VECTOR(irq) = vector;
 
-	return current_vector;
+	spin_unlock_irqrestore(&vector_lock, flags);
+
+	return vector;
 }
 
 extern void (*interrupt[NR_IRQS])(void);
@@ -866,21 +878,14 @@
 
 static inline void ioapic_register_intr(int irq, int vector, unsigned long trigger)
 {
-	if (use_pci_vector() && !platform_legacy_irq(irq)) {
-		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-				trigger == IOAPIC_LEVEL)
-			irq_desc[vector].handler = &ioapic_level_type;
-		else
-			irq_desc[vector].handler = &ioapic_edge_type;
-		set_intr_gate(vector, interrupt[vector]);
-	} else	{
-		if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-				trigger == IOAPIC_LEVEL)
-			irq_desc[irq].handler = &ioapic_level_type;
-		else
-			irq_desc[irq].handler = &ioapic_edge_type;
-		set_intr_gate(vector, interrupt[irq]);
-	}
+	unsigned idx = use_pci_vector() && !platform_legacy_irq(irq) ? vector : irq;
+
+	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
+			trigger == IOAPIC_LEVEL)
+		irq_desc[idx].handler = &ioapic_level_type;
+	else
+		irq_desc[idx].handler = &ioapic_edge_type;
+	set_intr_gate(vector, interrupt[idx]);
 }
 
 static void __init setup_IO_APIC_irqs(void)
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index d8bd0b3..bfa82f5 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -26,6 +26,30 @@
 #endif
 #endif
 
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+/*
+ * Probabilistic stack overflow check:
+ *
+ * Only check the stack in process context, because everything else
+ * runs on the big interrupt stacks. Checking reliably is too expensive,
+ * so we just check from interrupts.
+ */
+static inline void stack_overflow_check(struct pt_regs *regs)
+{
+	u64 curbase = (u64) current->thread_info;
+	static unsigned long warned = -60*HZ;
+
+	if (regs->rsp >= curbase && regs->rsp <= curbase + THREAD_SIZE &&
+	    regs->rsp <  curbase + sizeof(struct thread_info) + 128 &&
+	    time_after(jiffies, warned + 60*HZ)) {
+		printk("do_IRQ: %s near stack overflow (cur:%Lx,rsp:%lx)\n",
+		       current->comm, curbase, regs->rsp);
+		show_stack(NULL,NULL);
+		warned = jiffies;
+	}
+}
+#endif
+
 /*
  * Generic, controller-independent functions:
  */
@@ -39,7 +63,7 @@
 	if (i == 0) {
 		seq_printf(p, "           ");
 		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
+			seq_printf(p, "CPU%-8d",j);
 		seq_putc(p, '\n');
 	}
 
@@ -91,12 +115,20 @@
  */
 asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
 {	
-	/* high bits used in ret_from_ code  */
-	unsigned irq = regs->orig_rax & 0xff;
+	/* high bit used in ret_from_ code  */
+	unsigned irq = ~regs->orig_rax;
+
+	if (unlikely(irq >= NR_IRQS)) {
+		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
+					__FUNCTION__, irq);
+		BUG();
+	}
 
 	exit_idle();
 	irq_enter();
-
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	stack_overflow_check(regs);
+#endif
 	__do_IRQ(irq, regs);
 	irq_exit();
 
diff --git a/arch/x86_64/kernel/k8.c b/arch/x86_64/kernel/k8.c
new file mode 100644
index 0000000..6416682
--- /dev/null
+++ b/arch/x86_64/kernel/k8.c
@@ -0,0 +1,118 @@
+/*
+ * Shared support code for AMD K8 northbridges and derivates.
+ * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2.
+ */
+#include <linux/gfp.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/k8.h>
+
+int num_k8_northbridges;
+EXPORT_SYMBOL(num_k8_northbridges);
+
+static u32 *flush_words;
+
+struct pci_device_id k8_nb_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) },
+	{}
+};
+EXPORT_SYMBOL(k8_nb_ids);
+
+struct pci_dev **k8_northbridges;
+EXPORT_SYMBOL(k8_northbridges);
+
+static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
+{
+	do {
+		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+		if (!dev)
+			break;
+	} while (!pci_match_id(&k8_nb_ids[0], dev));
+	return dev;
+}
+
+int cache_k8_northbridges(void)
+{
+	int i;
+	struct pci_dev *dev;
+	if (num_k8_northbridges)
+		return 0;
+
+	num_k8_northbridges = 0;
+	dev = NULL;
+	while ((dev = next_k8_northbridge(dev)) != NULL)
+		num_k8_northbridges++;
+
+	k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *),
+				  GFP_KERNEL);
+	if (!k8_northbridges)
+		return -ENOMEM;
+
+	flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
+	if (!flush_words) {
+		kfree(k8_northbridges);
+		return -ENOMEM;
+	}
+
+	dev = NULL;
+	i = 0;
+	while ((dev = next_k8_northbridge(dev)) != NULL) {
+		k8_northbridges[i++] = dev;
+		pci_read_config_dword(dev, 0x9c, &flush_words[i]);
+	}
+	k8_northbridges[i] = NULL;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cache_k8_northbridges);
+
+/* Ignores subdevice/subvendor but as far as I can figure out
+   they're useless anyways */
+int __init early_is_k8_nb(u32 device)
+{
+	struct pci_device_id *id;
+	u32 vendor = device & 0xffff;
+	device >>= 16;
+	for (id = k8_nb_ids; id->vendor; id++)
+		if (vendor == id->vendor && device == id->device)
+			return 1;
+	return 0;
+}
+
+void k8_flush_garts(void)
+{
+	int flushed, i;
+	unsigned long flags;
+	static DEFINE_SPINLOCK(gart_lock);
+
+	/* Avoid races between AGP and IOMMU. In theory it's not needed
+	   but I'm not sure if the hardware won't lose flush requests
+	   when another is pending. This whole thing is so expensive anyways
+	   that it doesn't matter to serialize more. -AK */
+	spin_lock_irqsave(&gart_lock, flags);
+	flushed = 0;
+	for (i = 0; i < num_k8_northbridges; i++) {
+		pci_write_config_dword(k8_northbridges[i], 0x9c,
+				       flush_words[i]|1);
+		flushed++;
+	}
+	for (i = 0; i < num_k8_northbridges; i++) {
+		u32 w;
+		/* Make sure the hardware actually executed the flush*/
+		for (;;) {
+			pci_read_config_dword(k8_northbridges[i],
+					      0x9c, &w);
+			if (!(w & 1))
+				break;
+			cpu_relax();
+		}
+	}
+	spin_unlock_irqrestore(&gart_lock, flags);
+	if (!flushed)
+		printk("nothing to flush?\n");
+}
+EXPORT_SYMBOL_GPL(k8_flush_garts);
+
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
index 25ac8a3..83fb24a 100644
--- a/arch/x86_64/kernel/machine_kexec.c
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -149,8 +149,8 @@
 					unsigned long start_address,
 					unsigned long pgtable) ATTRIB_NORET;
 
-const extern unsigned char relocate_new_kernel[];
-const extern unsigned long relocate_new_kernel_size;
+extern const unsigned char relocate_new_kernel[];
+extern const unsigned long relocate_new_kernel_size;
 
 int machine_kexec_prepare(struct kimage *image)
 {
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index c69fc43..8884567 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -562,7 +562,7 @@
 	set_kset_name("machinecheck"),
 };
 
-static DEFINE_PER_CPU(struct sys_device, device_mce);
+DEFINE_PER_CPU(struct sys_device, device_mce);
 
 /* Why are there no generic functions for this? */
 #define ACCESSOR(name, var, start) \
@@ -629,7 +629,7 @@
 #endif
 
 /* Get notified when a cpu comes on/off. Be hotplug friendly. */
-static int
+static __cpuinit int
 mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
@@ -647,7 +647,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block mce_cpu_notifier = {
+static struct notifier_block __cpuinitdata mce_cpu_notifier = {
 	.notifier_call = mce_cpu_callback,
 };
 
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index d13b241..335200a 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -1,5 +1,5 @@
 /*
- *  (c) 2005 Advanced Micro Devices, Inc.
+ *  (c) 2005, 2006 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
@@ -8,9 +8,10 @@
  *
  *  Support : jacob.shin@amd.com
  *
- *  MC4_MISC0 DRAM ECC Error Threshold available under AMD K8 Rev F.
- *  MC4_MISC0 exists per physical processor.
+ *  April 2006
+ *     - added support for AMD Family 0x10 processors
  *
+ *  All MC4_MISCi registers are shared between multi-cores
  */
 
 #include <linux/cpu.h>
@@ -29,32 +30,45 @@
 #include <asm/percpu.h>
 #include <asm/idle.h>
 
-#define PFX "mce_threshold: "
-#define VERSION "version 1.00.9"
-#define NR_BANKS 5
-#define THRESHOLD_MAX 0xFFF
-#define INT_TYPE_APIC 0x00020000
-#define MASK_VALID_HI 0x80000000
-#define MASK_LVTOFF_HI 0x00F00000
-#define MASK_COUNT_EN_HI 0x00080000
-#define MASK_INT_TYPE_HI 0x00060000
-#define MASK_OVERFLOW_HI 0x00010000
+#define PFX               "mce_threshold: "
+#define VERSION           "version 1.1.1"
+#define NR_BANKS          6
+#define NR_BLOCKS         9
+#define THRESHOLD_MAX     0xFFF
+#define INT_TYPE_APIC     0x00020000
+#define MASK_VALID_HI     0x80000000
+#define MASK_LVTOFF_HI    0x00F00000
+#define MASK_COUNT_EN_HI  0x00080000
+#define MASK_INT_TYPE_HI  0x00060000
+#define MASK_OVERFLOW_HI  0x00010000
 #define MASK_ERR_COUNT_HI 0x00000FFF
-#define MASK_OVERFLOW 0x0001000000000000L
+#define MASK_BLKPTR_LO    0xFF000000
+#define MCG_XBLK_ADDR     0xC0000400
 
-struct threshold_bank {
+struct threshold_block {
+	unsigned int block;
+	unsigned int bank;
 	unsigned int cpu;
-	u8 bank;
-	u8 interrupt_enable;
+	u32 address;
+	u16 interrupt_enable;
 	u16 threshold_limit;
 	struct kobject kobj;
+	struct list_head miscj;
 };
 
-static struct threshold_bank threshold_defaults = {
+/* defaults used early on boot */
+static struct threshold_block threshold_defaults = {
 	.interrupt_enable = 0,
 	.threshold_limit = THRESHOLD_MAX,
 };
 
+struct threshold_bank {
+	struct kobject kobj;
+	struct threshold_block *blocks;
+	cpumask_t cpus;
+};
+static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]);
+
 #ifdef CONFIG_SMP
 static unsigned char shared_bank[NR_BANKS] = {
 	0, 0, 0, 0, 1
@@ -68,12 +82,12 @@
  */
 
 /* must be called with correct cpu affinity */
-static void threshold_restart_bank(struct threshold_bank *b,
+static void threshold_restart_bank(struct threshold_block *b,
 				   int reset, u16 old_limit)
 {
 	u32 mci_misc_hi, mci_misc_lo;
 
-	rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi);
+	rdmsr(b->address, mci_misc_lo, mci_misc_hi);
 
 	if (b->threshold_limit < (mci_misc_hi & THRESHOLD_MAX))
 		reset = 1;	/* limit cannot be lower than err count */
@@ -94,35 +108,57 @@
 	    (mci_misc_hi &= ~MASK_INT_TYPE_HI);
 
 	mci_misc_hi |= MASK_COUNT_EN_HI;
-	wrmsr(MSR_IA32_MC0_MISC + b->bank * 4, mci_misc_lo, mci_misc_hi);
+	wrmsr(b->address, mci_misc_lo, mci_misc_hi);
 }
 
+/* cpu init entry point, called from mce.c with preempt off */
 void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
 {
-	int bank;
-	u32 mci_misc_lo, mci_misc_hi;
+	unsigned int bank, block;
 	unsigned int cpu = smp_processor_id();
+	u32 low = 0, high = 0, address = 0;
 
 	for (bank = 0; bank < NR_BANKS; ++bank) {
-		rdmsr(MSR_IA32_MC0_MISC + bank * 4, mci_misc_lo, mci_misc_hi);
+		for (block = 0; block < NR_BLOCKS; ++block) {
+			if (block == 0)
+				address = MSR_IA32_MC0_MISC + bank * 4;
+			else if (block == 1)
+				address = MCG_XBLK_ADDR
+					+ ((low & MASK_BLKPTR_LO) >> 21);
+			else
+				++address;
 
-		/* !valid, !counter present, bios locked */
-		if (!(mci_misc_hi & MASK_VALID_HI) ||
-		    !(mci_misc_hi & MASK_VALID_HI >> 1) ||
-		    (mci_misc_hi & MASK_VALID_HI >> 2))
-			continue;
+			if (rdmsr_safe(address, &low, &high))
+				continue;
 
-		per_cpu(bank_map, cpu) |= (1 << bank);
+			if (!(high & MASK_VALID_HI)) {
+				if (block)
+					continue;
+				else
+					break;
+			}
 
+			if (!(high & MASK_VALID_HI >> 1)  ||
+			     (high & MASK_VALID_HI >> 2))
+				continue;
+
+			if (!block)
+				per_cpu(bank_map, cpu) |= (1 << bank);
 #ifdef CONFIG_SMP
-		if (shared_bank[bank] && cpu_core_id[cpu])
-			continue;
+			if (shared_bank[bank] && c->cpu_core_id)
+				break;
 #endif
+			high &= ~MASK_LVTOFF_HI;
+			high |= K8_APIC_EXT_LVT_ENTRY_THRESHOLD << 20;
+			wrmsr(address, low, high);
 
-		setup_threshold_lvt((mci_misc_hi & MASK_LVTOFF_HI) >> 20);
-		threshold_defaults.cpu = cpu;
-		threshold_defaults.bank = bank;
-		threshold_restart_bank(&threshold_defaults, 0, 0);
+			setup_APIC_extened_lvt(K8_APIC_EXT_LVT_ENTRY_THRESHOLD,
+					       THRESHOLD_APIC_VECTOR,
+					       K8_APIC_EXT_INT_MSG_FIX, 0);
+
+			threshold_defaults.address = address;
+			threshold_restart_bank(&threshold_defaults, 0, 0);
+		}
 	}
 }
 
@@ -137,8 +173,9 @@
  */
 asmlinkage void mce_threshold_interrupt(void)
 {
-	int bank;
+	unsigned int bank, block;
 	struct mce m;
+	u32 low = 0, high = 0, address = 0;
 
 	ack_APIC_irq();
 	exit_idle();
@@ -150,15 +187,42 @@
 
 	/* assume first bank caused it */
 	for (bank = 0; bank < NR_BANKS; ++bank) {
-		m.bank = MCE_THRESHOLD_BASE + bank;
-		rdmsrl(MSR_IA32_MC0_MISC + bank * 4, m.misc);
+		for (block = 0; block < NR_BLOCKS; ++block) {
+			if (block == 0)
+				address = MSR_IA32_MC0_MISC + bank * 4;
+			else if (block == 1)
+				address = MCG_XBLK_ADDR
+					+ ((low & MASK_BLKPTR_LO) >> 21);
+			else
+				++address;
 
-		if (m.misc & MASK_OVERFLOW) {
-			mce_log(&m);
-			goto out;
+			if (rdmsr_safe(address, &low, &high))
+				continue;
+
+			if (!(high & MASK_VALID_HI)) {
+				if (block)
+					continue;
+				else
+					break;
+			}
+
+			if (!(high & MASK_VALID_HI >> 1)  ||
+			     (high & MASK_VALID_HI >> 2))
+				continue;
+
+			if (high & MASK_OVERFLOW_HI) {
+				rdmsrl(address, m.misc);
+				rdmsrl(MSR_IA32_MC0_STATUS + bank * 4,
+				       m.status);
+				m.bank = K8_MCE_THRESHOLD_BASE
+				       + bank * NR_BLOCKS
+				       + block;
+				mce_log(&m);
+				goto out;
+			}
 		}
 	}
-      out:
+out:
 	irq_exit();
 }
 
@@ -166,20 +230,12 @@
  * Sysfs Interface
  */
 
-static struct sysdev_class threshold_sysclass = {
-	set_kset_name("threshold"),
-};
-
-static DEFINE_PER_CPU(struct sys_device, device_threshold);
-
 struct threshold_attr {
-        struct attribute attr;
-        ssize_t(*show) (struct threshold_bank *, char *);
-        ssize_t(*store) (struct threshold_bank *, const char *, size_t count);
+	struct attribute attr;
+	ssize_t(*show) (struct threshold_block *, char *);
+	ssize_t(*store) (struct threshold_block *, const char *, size_t count);
 };
 
-static DEFINE_PER_CPU(struct threshold_bank *, threshold_banks[NR_BANKS]);
-
 static cpumask_t affinity_set(unsigned int cpu)
 {
 	cpumask_t oldmask = current->cpus_allowed;
@@ -194,15 +250,15 @@
 	set_cpus_allowed(current, oldmask);
 }
 
-#define SHOW_FIELDS(name) \
-        static ssize_t show_ ## name(struct threshold_bank * b, char *buf) \
-        { \
-                return sprintf(buf, "%lx\n", (unsigned long) b->name); \
-        }
+#define SHOW_FIELDS(name)                                           \
+static ssize_t show_ ## name(struct threshold_block * b, char *buf) \
+{                                                                   \
+        return sprintf(buf, "%lx\n", (unsigned long) b->name);      \
+}
 SHOW_FIELDS(interrupt_enable)
 SHOW_FIELDS(threshold_limit)
 
-static ssize_t store_interrupt_enable(struct threshold_bank *b,
+static ssize_t store_interrupt_enable(struct threshold_block *b,
 				      const char *buf, size_t count)
 {
 	char *end;
@@ -219,7 +275,7 @@
 	return end - buf;
 }
 
-static ssize_t store_threshold_limit(struct threshold_bank *b,
+static ssize_t store_threshold_limit(struct threshold_block *b,
 				     const char *buf, size_t count)
 {
 	char *end;
@@ -242,18 +298,18 @@
 	return end - buf;
 }
 
-static ssize_t show_error_count(struct threshold_bank *b, char *buf)
+static ssize_t show_error_count(struct threshold_block *b, char *buf)
 {
 	u32 high, low;
 	cpumask_t oldmask;
 	oldmask = affinity_set(b->cpu);
-	rdmsr(MSR_IA32_MC0_MISC + b->bank * 4, low, high); /* ignore low 32 */
+	rdmsr(b->address, low, high);
 	affinity_restore(oldmask);
 	return sprintf(buf, "%x\n",
 		       (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit));
 }
 
-static ssize_t store_error_count(struct threshold_bank *b,
+static ssize_t store_error_count(struct threshold_block *b,
 				 const char *buf, size_t count)
 {
 	cpumask_t oldmask;
@@ -269,13 +325,13 @@
         .store = _store,                                      \
 };
 
-#define ATTR_FIELDS(name) \
-        static struct threshold_attr name = \
+#define RW_ATTR(name)                                           \
+static struct threshold_attr name =                             \
         THRESHOLD_ATTR(name, 0644, show_## name, store_## name)
 
-ATTR_FIELDS(interrupt_enable);
-ATTR_FIELDS(threshold_limit);
-ATTR_FIELDS(error_count);
+RW_ATTR(interrupt_enable);
+RW_ATTR(threshold_limit);
+RW_ATTR(error_count);
 
 static struct attribute *default_attrs[] = {
 	&interrupt_enable.attr,
@@ -284,12 +340,12 @@
 	NULL
 };
 
-#define to_bank(k) container_of(k,struct threshold_bank,kobj)
-#define to_attr(a) container_of(a,struct threshold_attr,attr)
+#define to_block(k) container_of(k, struct threshold_block, kobj)
+#define to_attr(a) container_of(a, struct threshold_attr, attr)
 
 static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 {
-	struct threshold_bank *b = to_bank(kobj);
+	struct threshold_block *b = to_block(kobj);
 	struct threshold_attr *a = to_attr(attr);
 	ssize_t ret;
 	ret = a->show ? a->show(b, buf) : -EIO;
@@ -299,7 +355,7 @@
 static ssize_t store(struct kobject *kobj, struct attribute *attr,
 		     const char *buf, size_t count)
 {
-	struct threshold_bank *b = to_bank(kobj);
+	struct threshold_block *b = to_block(kobj);
 	struct threshold_attr *a = to_attr(attr);
 	ssize_t ret;
 	ret = a->store ? a->store(b, buf, count) : -EIO;
@@ -316,69 +372,174 @@
 	.default_attrs = default_attrs,
 };
 
-/* symlinks sibling shared banks to first core.  first core owns dir/files. */
-static __cpuinit int threshold_create_bank(unsigned int cpu, int bank)
+static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
+					       unsigned int bank,
+					       unsigned int block,
+					       u32 address)
 {
-	int err = 0;
+	int err;
+	u32 low, high;
+	struct threshold_block *b = NULL;
+
+	if ((bank >= NR_BANKS) || (block >= NR_BLOCKS))
+		return 0;
+
+	if (rdmsr_safe(address, &low, &high))
+		goto recurse;
+
+	if (!(high & MASK_VALID_HI)) {
+		if (block)
+			goto recurse;
+		else
+			return 0;
+	}
+
+	if (!(high & MASK_VALID_HI >> 1)  ||
+	     (high & MASK_VALID_HI >> 2))
+		goto recurse;
+
+	b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
+	if (!b)
+		return -ENOMEM;
+	memset(b, 0, sizeof(struct threshold_block));
+
+	b->block = block;
+	b->bank = bank;
+	b->cpu = cpu;
+	b->address = address;
+	b->interrupt_enable = 0;
+	b->threshold_limit = THRESHOLD_MAX;
+
+	INIT_LIST_HEAD(&b->miscj);
+
+	if (per_cpu(threshold_banks, cpu)[bank]->blocks)
+		list_add(&b->miscj,
+			 &per_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
+	else
+		per_cpu(threshold_banks, cpu)[bank]->blocks = b;
+
+	kobject_set_name(&b->kobj, "misc%i", block);
+	b->kobj.parent = &per_cpu(threshold_banks, cpu)[bank]->kobj;
+	b->kobj.ktype = &threshold_ktype;
+	err = kobject_register(&b->kobj);
+	if (err)
+		goto out_free;
+recurse:
+	if (!block) {
+		address = (low & MASK_BLKPTR_LO) >> 21;
+		if (!address)
+			return 0;
+		address += MCG_XBLK_ADDR;
+	} else
+		++address;
+
+	err = allocate_threshold_blocks(cpu, bank, ++block, address);
+	if (err)
+		goto out_free;
+
+	return err;
+
+out_free:
+	if (b) {
+		kobject_unregister(&b->kobj);
+		kfree(b);
+	}
+	return err;
+}
+
+/* symlinks sibling shared banks to first core.  first core owns dir/files. */
+static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
+{
+	int i, err = 0;
 	struct threshold_bank *b = NULL;
+	cpumask_t oldmask = CPU_MASK_NONE;
+	char name[32];
+
+	sprintf(name, "threshold_bank%i", bank);
 
 #ifdef CONFIG_SMP
-	if (cpu_core_id[cpu] && shared_bank[bank]) {	/* symlink */
-		char name[16];
-		unsigned lcpu = first_cpu(cpu_core_map[cpu]);
-		if (cpu_core_id[lcpu])
-			goto out;	/* first core not up yet */
+	if (cpu_data[cpu].cpu_core_id && shared_bank[bank]) {	/* symlink */
+		i = first_cpu(cpu_core_map[cpu]);
 
-		b = per_cpu(threshold_banks, lcpu)[bank];
+		/* first core not up yet */
+		if (cpu_data[i].cpu_core_id)
+			goto out;
+
+		/* already linked */
+		if (per_cpu(threshold_banks, cpu)[bank])
+			goto out;
+
+		b = per_cpu(threshold_banks, i)[bank];
+
 		if (!b)
 			goto out;
-		sprintf(name, "bank%i", bank);
-		err = sysfs_create_link(&per_cpu(device_threshold, cpu).kobj,
+
+		err = sysfs_create_link(&per_cpu(device_mce, cpu).kobj,
 					&b->kobj, name);
 		if (err)
 			goto out;
+
+		b->cpus = cpu_core_map[cpu];
 		per_cpu(threshold_banks, cpu)[bank] = b;
 		goto out;
 	}
 #endif
 
-	b = kmalloc(sizeof(struct threshold_bank), GFP_KERNEL);
+	b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
 	if (!b) {
 		err = -ENOMEM;
 		goto out;
 	}
 	memset(b, 0, sizeof(struct threshold_bank));
 
-	b->cpu = cpu;
-	b->bank = bank;
-	b->interrupt_enable = 0;
-	b->threshold_limit = THRESHOLD_MAX;
-	kobject_set_name(&b->kobj, "bank%i", bank);
-	b->kobj.parent = &per_cpu(device_threshold, cpu).kobj;
-	b->kobj.ktype = &threshold_ktype;
-
+	kobject_set_name(&b->kobj, "threshold_bank%i", bank);
+	b->kobj.parent = &per_cpu(device_mce, cpu).kobj;
+#ifndef CONFIG_SMP
+	b->cpus = CPU_MASK_ALL;
+#else
+	b->cpus = cpu_core_map[cpu];
+#endif
 	err = kobject_register(&b->kobj);
-	if (err) {
-		kfree(b);
-		goto out;
-	}
+	if (err)
+		goto out_free;
+
 	per_cpu(threshold_banks, cpu)[bank] = b;
-      out:
+
+	oldmask = affinity_set(cpu);
+	err = allocate_threshold_blocks(cpu, bank, 0,
+					MSR_IA32_MC0_MISC + bank * 4);
+	affinity_restore(oldmask);
+
+	if (err)
+		goto out_free;
+
+	for_each_cpu_mask(i, b->cpus) {
+		if (i == cpu)
+			continue;
+
+		err = sysfs_create_link(&per_cpu(device_mce, i).kobj,
+					&b->kobj, name);
+		if (err)
+			goto out;
+
+		per_cpu(threshold_banks, i)[bank] = b;
+	}
+
+	goto out;
+
+out_free:
+	per_cpu(threshold_banks, cpu)[bank] = NULL;
+	kfree(b);
+out:
 	return err;
 }
 
 /* create dir/files for all valid threshold banks */
 static __cpuinit int threshold_create_device(unsigned int cpu)
 {
-	int bank;
+	unsigned int bank;
 	int err = 0;
 
-	per_cpu(device_threshold, cpu).id = cpu;
-	per_cpu(device_threshold, cpu).cls = &threshold_sysclass;
-	err = sysdev_register(&per_cpu(device_threshold, cpu));
-	if (err)
-		goto out;
-
 	for (bank = 0; bank < NR_BANKS; ++bank) {
 		if (!(per_cpu(bank_map, cpu) & 1 << bank))
 			continue;
@@ -386,7 +547,7 @@
 		if (err)
 			goto out;
 	}
-      out:
+out:
 	return err;
 }
 
@@ -397,92 +558,85 @@
  *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
  */
 
-/* cpu hotplug call removes all symlinks before first core dies */
+static __cpuinit void deallocate_threshold_block(unsigned int cpu,
+						 unsigned int bank)
+{
+	struct threshold_block *pos = NULL;
+	struct threshold_block *tmp = NULL;
+	struct threshold_bank *head = per_cpu(threshold_banks, cpu)[bank];
+
+	if (!head)
+		return;
+
+	list_for_each_entry_safe(pos, tmp, &head->blocks->miscj, miscj) {
+		kobject_unregister(&pos->kobj);
+		list_del(&pos->miscj);
+		kfree(pos);
+	}
+
+	kfree(per_cpu(threshold_banks, cpu)[bank]->blocks);
+	per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
+}
+
 static __cpuinit void threshold_remove_bank(unsigned int cpu, int bank)
 {
+	int i = 0;
 	struct threshold_bank *b;
-	char name[16];
+	char name[32];
 
 	b = per_cpu(threshold_banks, cpu)[bank];
+
 	if (!b)
 		return;
-	if (shared_bank[bank] && atomic_read(&b->kobj.kref.refcount) > 2) {
-		sprintf(name, "bank%i", bank);
-		sysfs_remove_link(&per_cpu(device_threshold, cpu).kobj, name);
-		per_cpu(threshold_banks, cpu)[bank] = NULL;
-	} else {
-		kobject_unregister(&b->kobj);
-		kfree(per_cpu(threshold_banks, cpu)[bank]);
+
+	if (!b->blocks)
+		goto free_out;
+
+	sprintf(name, "threshold_bank%i", bank);
+
+	/* sibling symlink */
+	if (shared_bank[bank] && b->blocks->cpu != cpu) {
+		sysfs_remove_link(&per_cpu(device_mce, cpu).kobj, name);
+		per_cpu(threshold_banks, i)[bank] = NULL;
+		return;
 	}
+
+	/* remove all sibling symlinks before unregistering */
+	for_each_cpu_mask(i, b->cpus) {
+		if (i == cpu)
+			continue;
+
+		sysfs_remove_link(&per_cpu(device_mce, i).kobj, name);
+		per_cpu(threshold_banks, i)[bank] = NULL;
+	}
+
+	deallocate_threshold_block(cpu, bank);
+
+free_out:
+	kobject_unregister(&b->kobj);
+	kfree(b);
+	per_cpu(threshold_banks, cpu)[bank] = NULL;
 }
 
 static __cpuinit void threshold_remove_device(unsigned int cpu)
 {
-	int bank;
+	unsigned int bank;
 
 	for (bank = 0; bank < NR_BANKS; ++bank) {
 		if (!(per_cpu(bank_map, cpu) & 1 << bank))
 			continue;
 		threshold_remove_bank(cpu, bank);
 	}
-	sysdev_unregister(&per_cpu(device_threshold, cpu));
 }
 
-/* link all existing siblings when first core comes up */
-static __cpuinit int threshold_create_symlinks(unsigned int cpu)
-{
-	int bank, err = 0;
-	unsigned int lcpu = 0;
-
-	if (cpu_core_id[cpu])
-		return 0;
-	for_each_cpu_mask(lcpu, cpu_core_map[cpu]) {
-		if (lcpu == cpu)
-			continue;
-		for (bank = 0; bank < NR_BANKS; ++bank) {
-			if (!(per_cpu(bank_map, cpu) & 1 << bank))
-				continue;
-			if (!shared_bank[bank])
-				continue;
-			err = threshold_create_bank(lcpu, bank);
-		}
-	}
-	return err;
-}
-
-/* remove all symlinks before first core dies. */
-static __cpuinit void threshold_remove_symlinks(unsigned int cpu)
-{
-	int bank;
-	unsigned int lcpu = 0;
-	if (cpu_core_id[cpu])
-		return;
-	for_each_cpu_mask(lcpu, cpu_core_map[cpu]) {
-		if (lcpu == cpu)
-			continue;
-		for (bank = 0; bank < NR_BANKS; ++bank) {
-			if (!(per_cpu(bank_map, cpu) & 1 << bank))
-				continue;
-			if (!shared_bank[bank])
-				continue;
-			threshold_remove_bank(lcpu, bank);
-		}
-	}
-}
 #else /* !CONFIG_HOTPLUG_CPU */
-static __cpuinit void threshold_create_symlinks(unsigned int cpu)
-{
-}
-static __cpuinit void threshold_remove_symlinks(unsigned int cpu)
-{
-}
 static void threshold_remove_device(unsigned int cpu)
 {
 }
 #endif
 
 /* get notified when a cpu comes on/off */
-static int threshold_cpu_callback(struct notifier_block *nfb,
+static int __cpuinit threshold_cpu_callback(struct notifier_block *nfb,
 					    unsigned long action, void *hcpu)
 {
 	/* cpu was unsigned int to begin with */
@@ -494,13 +648,6 @@
 	switch (action) {
 	case CPU_ONLINE:
 		threshold_create_device(cpu);
-		threshold_create_symlinks(cpu);
-		break;
-	case CPU_DOWN_PREPARE:
-		threshold_remove_symlinks(cpu);
-		break;
-	case CPU_DOWN_FAILED:
-		threshold_create_symlinks(cpu);
 		break;
 	case CPU_DEAD:
 		threshold_remove_device(cpu);
@@ -512,29 +659,22 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block threshold_cpu_notifier = {
+static struct notifier_block threshold_cpu_notifier __cpuinitdata = {
 	.notifier_call = threshold_cpu_callback,
 };
 
 static __init int threshold_init_device(void)
 {
-	int err;
-	int lcpu = 0;
-
-	err = sysdev_class_register(&threshold_sysclass);
-	if (err)
-		goto out;
+	unsigned lcpu = 0;
 
 	/* to hit CPUs online before the notifier is up */
 	for_each_online_cpu(lcpu) {
-		err = threshold_create_device(lcpu);
+		int err = threshold_create_device(lcpu);
 		if (err)
-			goto out;
+			return err;
 	}
 	register_cpu_notifier(&threshold_cpu_notifier);
-
-      out:
-	return err;
+	return 0;
 }
 
 device_initcall(threshold_init_device);
diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c
index bac195c..9d0958f 100644
--- a/arch/x86_64/kernel/module.c
+++ b/arch/x86_64/kernel/module.c
@@ -145,26 +145,38 @@
 	return -ENOSYS;
 } 
 
-extern void apply_alternatives(void *start, void *end); 
-
 int module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
+                    const Elf_Shdr *sechdrs,
+                    struct module *me)
 {
-	const Elf_Shdr *s;
+	const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL;
 	char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 
-	/* look for .altinstructions to patch */ 
-	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 
-		void *seg; 		
-		if (strcmp(".altinstructions", secstrings + s->sh_name))
-			continue;
-		seg = (void *)s->sh_addr; 
-		apply_alternatives(seg, seg + s->sh_size); 
-	} 	
+	for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+		if (!strcmp(".text", secstrings + s->sh_name))
+			text = s;
+		if (!strcmp(".altinstructions", secstrings + s->sh_name))
+			alt = s;
+		if (!strcmp(".smp_locks", secstrings + s->sh_name))
+			locks= s;
+	}
+
+	if (alt) {
+		/* patch .altinstructions */
+		void *aseg = (void *)alt->sh_addr;
+		apply_alternatives(aseg, aseg + alt->sh_size);
+	}
+	if (locks && text) {
+		void *lseg = (void *)locks->sh_addr;
+		void *tseg = (void *)text->sh_addr;
+		alternatives_smp_module_add(me, me->name,
+					    lseg, lseg + locks->sh_size,
+					    tseg, tseg + text->sh_size);
+	}
 	return 0;
 }
 
 void module_arch_cleanup(struct module *mod)
 {
+	alternatives_smp_module_del(mod);
 }
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 4e6357f..0ef9cf2 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -15,11 +15,7 @@
 #include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/delay.h>
-#include <linux/bootmem.h>
-#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
-#include <linux/mc146818rtc.h>
-#include <linux/kernel_stat.h>
 #include <linux/module.h>
 #include <linux/sysdev.h>
 #include <linux/nmi.h>
@@ -27,14 +23,11 @@
 #include <linux/kprobes.h>
 
 #include <asm/smp.h>
-#include <asm/mtrr.h>
-#include <asm/mpspec.h>
 #include <asm/nmi.h>
-#include <asm/msr.h>
 #include <asm/proto.h>
 #include <asm/kdebug.h>
-#include <asm/local.h>
 #include <asm/mce.h>
+#include <asm/intel_arch_perfmon.h>
 
 /*
  * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -74,6 +67,9 @@
 #define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING	0x76
 #define K7_NMI_EVENT		K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
 
+#define ARCH_PERFMON_NMI_EVENT_SEL	ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
+#define ARCH_PERFMON_NMI_EVENT_UMASK	ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+
 #define MSR_P4_MISC_ENABLE	0x1A0
 #define MSR_P4_MISC_ENABLE_PERF_AVAIL	(1<<7)
 #define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL	(1<<12)
@@ -105,7 +101,10 @@
 	case X86_VENDOR_AMD:
 		return boot_cpu_data.x86 == 15;
 	case X86_VENDOR_INTEL:
-		return boot_cpu_data.x86 == 15;
+		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+			return 1;
+		else
+			return (boot_cpu_data.x86 == 15);
 	}
 	return 0;
 }
@@ -211,6 +210,8 @@
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
+static void disable_intel_arch_watchdog(void);
+
 static void disable_lapic_nmi_watchdog(void)
 {
 	if (nmi_active <= 0)
@@ -223,6 +224,8 @@
 		if (boot_cpu_data.x86 == 15) {
 			wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
 			wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
+		} else if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+			disable_intel_arch_watchdog();
 		}
 		break;
 	}
@@ -375,6 +378,53 @@
 	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
 }
 
+static void disable_intel_arch_watchdog(void)
+{
+	unsigned ebx;
+
+	/*
+	 * Check whether the Architectural PerfMon supports
+	 * Unhalted Core Cycles Event or not.
+	 * NOTE: Corresponding bit = 0 in ebp indicates event present.
+	 */
+	ebx = cpuid_ebx(10);
+	if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+		wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0);
+}
+
+static int setup_intel_arch_watchdog(void)
+{
+	unsigned int evntsel;
+	unsigned ebx;
+
+	/*
+	 * Check whether the Architectural PerfMon supports
+	 * Unhalted Core Cycles Event or not.
+	 * NOTE: Corresponding bit = 0 in ebp indicates event present.
+	 */
+	ebx = cpuid_ebx(10);
+	if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+		return 0;
+
+	nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+
+	clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2);
+	clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2);
+
+	evntsel = ARCH_PERFMON_EVENTSEL_INT
+		| ARCH_PERFMON_EVENTSEL_OS
+		| ARCH_PERFMON_EVENTSEL_USR
+		| ARCH_PERFMON_NMI_EVENT_SEL
+		| ARCH_PERFMON_NMI_EVENT_UMASK;
+
+	wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+	wrmsrl(MSR_ARCH_PERFMON_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+	evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
+	wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+	return 1;
+}
+
 
 static int setup_p4_watchdog(void)
 {
@@ -428,10 +478,16 @@
 		setup_k7_watchdog();
 		break;
 	case X86_VENDOR_INTEL:
-		if (boot_cpu_data.x86 != 15)
+		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+			if (!setup_intel_arch_watchdog())
+				return;
+		} else if (boot_cpu_data.x86 == 15) {
+			if (!setup_p4_watchdog())
+				return;
+		} else {
 			return;
-		if (!setup_p4_watchdog())
-			return;
+		}
+
 		break;
 
 	default:
@@ -516,7 +572,14 @@
  			 */
  			wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
  			apic_write(APIC_LVTPC, APIC_DM_NMI);
- 		}
+ 		} else if (nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
+			/*
+			 * For Intel based architectural perfmon
+			 * - LVTPC is masked on interrupt and must be
+			 *   unmasked by the LVTPC handler.
+			 */
+			apic_write(APIC_LVTPC, APIC_DM_NMI);
+		}
 		wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
 	}
 }
@@ -544,11 +607,13 @@
 	vmalloc_sync_all();
 	rcu_assign_pointer(nmi_callback, callback);
 }
+EXPORT_SYMBOL_GPL(set_nmi_callback);
 
 void unset_nmi_callback(void)
 {
 	nmi_callback = dummy_nmi_callback;
 }
+EXPORT_SYMBOL_GPL(unset_nmi_callback);
 
 #ifdef CONFIG_SYSCTL
 
diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c
new file mode 100644
index 0000000..d91cb843
--- /dev/null
+++ b/arch/x86_64/kernel/pci-calgary.c
@@ -0,0 +1,1018 @@
+/*
+ * Derived from arch/powerpc/kernel/iommu.c
+ *
+ * Copyright (C) 2006 Jon Mason <jdmason@us.ibm.com>, IBM Corporation
+ * Copyright (C) 2006 Muli Ben-Yehuda <muli@il.ibm.com>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/pci_ids.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <asm/proto.h>
+#include <asm/calgary.h>
+#include <asm/tce.h>
+#include <asm/pci-direct.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+
+#define PCI_DEVICE_ID_IBM_CALGARY 0x02a1
+#define PCI_VENDOR_DEVICE_ID_CALGARY \
+	(PCI_VENDOR_ID_IBM | PCI_DEVICE_ID_IBM_CALGARY << 16)
+
+/* we need these for register space address calculation */
+#define START_ADDRESS           0xfe000000
+#define CHASSIS_BASE            0
+#define ONE_BASED_CHASSIS_NUM   1
+
+/* register offsets inside the host bridge space */
+#define PHB_CSR_OFFSET		0x0110
+#define PHB_PLSSR_OFFSET	0x0120
+#define PHB_CONFIG_RW_OFFSET	0x0160
+#define PHB_IOBASE_BAR_LOW	0x0170
+#define PHB_IOBASE_BAR_HIGH	0x0180
+#define PHB_MEM_1_LOW		0x0190
+#define PHB_MEM_1_HIGH		0x01A0
+#define PHB_IO_ADDR_SIZE	0x01B0
+#define PHB_MEM_1_SIZE		0x01C0
+#define PHB_MEM_ST_OFFSET	0x01D0
+#define PHB_AER_OFFSET		0x0200
+#define PHB_CONFIG_0_HIGH	0x0220
+#define PHB_CONFIG_0_LOW	0x0230
+#define PHB_CONFIG_0_END	0x0240
+#define PHB_MEM_2_LOW		0x02B0
+#define PHB_MEM_2_HIGH		0x02C0
+#define PHB_MEM_2_SIZE_HIGH	0x02D0
+#define PHB_MEM_2_SIZE_LOW	0x02E0
+#define PHB_DOSHOLE_OFFSET	0x08E0
+
+/* PHB_CONFIG_RW */
+#define PHB_TCE_ENABLE		0x20000000
+#define PHB_SLOT_DISABLE	0x1C000000
+#define PHB_DAC_DISABLE		0x01000000
+#define PHB_MEM2_ENABLE		0x00400000
+#define PHB_MCSR_ENABLE		0x00100000
+/* TAR (Table Address Register) */
+#define TAR_SW_BITS		0x0000ffffffff800fUL
+#define TAR_VALID		0x0000000000000008UL
+/* CSR (Channel/DMA Status Register) */
+#define CSR_AGENT_MASK		0xffe0ffff
+
+#define MAX_NUM_OF_PHBS		8 /* how many PHBs in total? */
+#define MAX_PHB_BUS_NUM		(MAX_NUM_OF_PHBS * 2) /* max dev->bus->number */
+#define PHBS_PER_CALGARY	4
+
+/* register offsets in Calgary's internal register space */
+static const unsigned long tar_offsets[] = {
+	0x0580 /* TAR0 */,
+	0x0588 /* TAR1 */,
+	0x0590 /* TAR2 */,
+	0x0598 /* TAR3 */
+};
+
+static const unsigned long split_queue_offsets[] = {
+	0x4870 /* SPLIT QUEUE 0 */,
+	0x5870 /* SPLIT QUEUE 1 */,
+	0x6870 /* SPLIT QUEUE 2 */,
+	0x7870 /* SPLIT QUEUE 3 */
+};
+
+static const unsigned long phb_offsets[] = {
+	0x8000 /* PHB0 */,
+	0x9000 /* PHB1 */,
+	0xA000 /* PHB2 */,
+	0xB000 /* PHB3 */
+};
+
+void* tce_table_kva[MAX_NUM_OF_PHBS * MAX_NUMNODES];
+unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
+static int translate_empty_slots __read_mostly = 0;
+static int calgary_detected __read_mostly = 0;
+
+/*
+ * the bitmap of PHBs the user requested that we disable
+ * translation on.
+ */
+static DECLARE_BITMAP(translation_disabled, MAX_NUMNODES * MAX_PHB_BUS_NUM);
+
+static void tce_cache_blast(struct iommu_table *tbl);
+
+/* enable this to stress test the chip's TCE cache */
+#ifdef CONFIG_IOMMU_DEBUG
+static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+{
+	tce_cache_blast(tbl);
+}
+#else
+static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+{
+}
+#endif /* BLAST_TCE_CACHE_ON_UNMAP */
+
+static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
+{
+	unsigned int npages;
+
+	npages = PAGE_ALIGN(dma + dmalen) - (dma & PAGE_MASK);
+	npages >>= PAGE_SHIFT;
+
+	return npages;
+}
+
+static inline int translate_phb(struct pci_dev* dev)
+{
+	int disabled = test_bit(dev->bus->number, translation_disabled);
+	return !disabled;
+}
+
+static void iommu_range_reserve(struct iommu_table *tbl,
+        unsigned long start_addr, unsigned int npages)
+{
+	unsigned long index;
+	unsigned long end;
+
+	index = start_addr >> PAGE_SHIFT;
+
+	/* bail out if we're asked to reserve a region we don't cover */
+	if (index >= tbl->it_size)
+		return;
+
+	end = index + npages;
+	if (end > tbl->it_size) /* don't go off the table */
+		end = tbl->it_size;
+
+	while (index < end) {
+		if (test_bit(index, tbl->it_map))
+			printk(KERN_ERR "Calgary: entry already allocated at "
+			       "0x%lx tbl %p dma 0x%lx npages %u\n",
+			       index, tbl, start_addr, npages);
+		++index;
+	}
+	set_bit_string(tbl->it_map, start_addr >> PAGE_SHIFT, npages);
+}
+
+static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+	unsigned int npages)
+{
+	unsigned long offset;
+
+	BUG_ON(npages == 0);
+
+	offset = find_next_zero_string(tbl->it_map, tbl->it_hint,
+				       tbl->it_size, npages);
+	if (offset == ~0UL) {
+		tce_cache_blast(tbl);
+		offset = find_next_zero_string(tbl->it_map, 0,
+					       tbl->it_size, npages);
+		if (offset == ~0UL) {
+			printk(KERN_WARNING "Calgary: IOMMU full.\n");
+			if (panic_on_overflow)
+				panic("Calgary: fix the allocator.\n");
+			else
+				return bad_dma_address;
+		}
+	}
+
+	set_bit_string(tbl->it_map, offset, npages);
+	tbl->it_hint = offset + npages;
+	BUG_ON(tbl->it_hint > tbl->it_size);
+
+	return offset;
+}
+
+static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr,
+	unsigned int npages, int direction)
+{
+	unsigned long entry, flags;
+	dma_addr_t ret = bad_dma_address;
+
+	spin_lock_irqsave(&tbl->it_lock, flags);
+
+	entry = iommu_range_alloc(tbl, npages);
+
+	if (unlikely(entry == bad_dma_address))
+		goto error;
+
+	/* set the return dma address */
+	ret = (entry << PAGE_SHIFT) | ((unsigned long)vaddr & ~PAGE_MASK);
+
+	/* put the TCEs in the HW table */
+	tce_build(tbl, entry, npages, (unsigned long)vaddr & PAGE_MASK,
+		  direction);
+
+	spin_unlock_irqrestore(&tbl->it_lock, flags);
+
+	return ret;
+
+error:
+	spin_unlock_irqrestore(&tbl->it_lock, flags);
+	printk(KERN_WARNING "Calgary: failed to allocate %u pages in "
+	       "iommu %p\n", npages, tbl);
+	return bad_dma_address;
+}
+
+static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+	unsigned int npages)
+{
+	unsigned long entry;
+	unsigned long i;
+
+	entry = dma_addr >> PAGE_SHIFT;
+
+	BUG_ON(entry + npages > tbl->it_size);
+
+	tce_free(tbl, entry, npages);
+
+	for (i = 0; i < npages; ++i) {
+		if (!test_bit(entry + i, tbl->it_map))
+			printk(KERN_ERR "Calgary: bit is off at 0x%lx "
+			       "tbl %p dma 0x%Lx entry 0x%lx npages %u\n",
+			       entry + i, tbl, dma_addr, entry, npages);
+	}
+
+	__clear_bit_string(tbl->it_map, entry, npages);
+
+	tce_cache_blast_stress(tbl);
+}
+
+static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+	unsigned int npages)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tbl->it_lock, flags);
+
+	__iommu_free(tbl, dma_addr, npages);
+
+	spin_unlock_irqrestore(&tbl->it_lock, flags);
+}
+
+static void __calgary_unmap_sg(struct iommu_table *tbl,
+	struct scatterlist *sglist, int nelems, int direction)
+{
+	while (nelems--) {
+		unsigned int npages;
+		dma_addr_t dma = sglist->dma_address;
+		unsigned int dmalen = sglist->dma_length;
+
+		if (dmalen == 0)
+			break;
+
+		npages = num_dma_pages(dma, dmalen);
+		__iommu_free(tbl, dma, npages);
+		sglist++;
+	}
+}
+
+void calgary_unmap_sg(struct device *dev, struct scatterlist *sglist,
+		      int nelems, int direction)
+{
+	unsigned long flags;
+	struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+
+	if (!translate_phb(to_pci_dev(dev)))
+		return;
+
+	spin_lock_irqsave(&tbl->it_lock, flags);
+
+	__calgary_unmap_sg(tbl, sglist, nelems, direction);
+
+	spin_unlock_irqrestore(&tbl->it_lock, flags);
+}
+
+static int calgary_nontranslate_map_sg(struct device* dev,
+	struct scatterlist *sg, int nelems, int direction)
+{
+	int i;
+
+ 	for (i = 0; i < nelems; i++ ) {
+		struct scatterlist *s = &sg[i];
+		BUG_ON(!s->page);
+		s->dma_address = virt_to_bus(page_address(s->page) +s->offset);
+		s->dma_length = s->length;
+	}
+	return nelems;
+}
+
+int calgary_map_sg(struct device *dev, struct scatterlist *sg,
+	int nelems, int direction)
+{
+	struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+	unsigned long flags;
+	unsigned long vaddr;
+	unsigned int npages;
+	unsigned long entry;
+	int i;
+
+	if (!translate_phb(to_pci_dev(dev)))
+		return calgary_nontranslate_map_sg(dev, sg, nelems, direction);
+
+	spin_lock_irqsave(&tbl->it_lock, flags);
+
+	for (i = 0; i < nelems; i++ ) {
+		struct scatterlist *s = &sg[i];
+		BUG_ON(!s->page);
+
+		vaddr = (unsigned long)page_address(s->page) + s->offset;
+		npages = num_dma_pages(vaddr, s->length);
+
+		entry = iommu_range_alloc(tbl, npages);
+		if (entry == bad_dma_address) {
+			/* makes sure unmap knows to stop */
+			s->dma_length = 0;
+			goto error;
+		}
+
+		s->dma_address = (entry << PAGE_SHIFT) | s->offset;
+
+		/* insert into HW table */
+		tce_build(tbl, entry, npages, vaddr & PAGE_MASK,
+			  direction);
+
+		s->dma_length = s->length;
+	}
+
+	spin_unlock_irqrestore(&tbl->it_lock, flags);
+
+	return nelems;
+error:
+	__calgary_unmap_sg(tbl, sg, nelems, direction);
+	for (i = 0; i < nelems; i++) {
+		sg[i].dma_address = bad_dma_address;
+		sg[i].dma_length = 0;
+	}
+	spin_unlock_irqrestore(&tbl->it_lock, flags);
+	return 0;
+}
+
+dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
+	size_t size, int direction)
+{
+	dma_addr_t dma_handle = bad_dma_address;
+	unsigned long uaddr;
+	unsigned int npages;
+	struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+
+	uaddr = (unsigned long)vaddr;
+	npages = num_dma_pages(uaddr, size);
+
+	if (translate_phb(to_pci_dev(dev)))
+		dma_handle = iommu_alloc(tbl, vaddr, npages, direction);
+	else
+		dma_handle = virt_to_bus(vaddr);
+
+	return dma_handle;
+}
+
+void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle,
+	size_t size, int direction)
+{
+	struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata;
+	unsigned int npages;
+
+	if (!translate_phb(to_pci_dev(dev)))
+		return;
+
+	npages = num_dma_pages(dma_handle, size);
+	iommu_free(tbl, dma_handle, npages);
+}
+
+void* calgary_alloc_coherent(struct device *dev, size_t size,
+	dma_addr_t *dma_handle, gfp_t flag)
+{
+	void *ret = NULL;
+	dma_addr_t mapping;
+	unsigned int npages, order;
+	struct iommu_table *tbl;
+
+	tbl = to_pci_dev(dev)->bus->self->sysdata;
+
+	size = PAGE_ALIGN(size); /* size rounded up to full pages */
+	npages = size >> PAGE_SHIFT;
+	order = get_order(size);
+
+	/* alloc enough pages (and possibly more) */
+	ret = (void *)__get_free_pages(flag, order);
+	if (!ret)
+		goto error;
+	memset(ret, 0, size);
+
+	if (translate_phb(to_pci_dev(dev))) {
+		/* set up tces to cover the allocated range */
+		mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL);
+		if (mapping == bad_dma_address)
+			goto free;
+
+		*dma_handle = mapping;
+	} else /* non translated slot */
+		*dma_handle = virt_to_bus(ret);
+
+	return ret;
+
+free:
+	free_pages((unsigned long)ret, get_order(size));
+	ret = NULL;
+error:
+	return ret;
+}
+
+static struct dma_mapping_ops calgary_dma_ops = {
+	.alloc_coherent = calgary_alloc_coherent,
+	.map_single = calgary_map_single,
+	.unmap_single = calgary_unmap_single,
+	.map_sg = calgary_map_sg,
+	.unmap_sg = calgary_unmap_sg,
+};
+
+static inline int busno_to_phbid(unsigned char num)
+{
+	return bus_to_phb(num) % PHBS_PER_CALGARY;
+}
+
+static inline unsigned long split_queue_offset(unsigned char num)
+{
+	size_t idx = busno_to_phbid(num);
+
+	return split_queue_offsets[idx];
+}
+
+static inline unsigned long tar_offset(unsigned char num)
+{
+	size_t idx = busno_to_phbid(num);
+
+	return tar_offsets[idx];
+}
+
+static inline unsigned long phb_offset(unsigned char num)
+{
+	size_t idx = busno_to_phbid(num);
+
+	return phb_offsets[idx];
+}
+
+static inline void __iomem* calgary_reg(void __iomem *bar, unsigned long offset)
+{
+	unsigned long target = ((unsigned long)bar) | offset;
+	return (void __iomem*)target;
+}
+
+static void tce_cache_blast(struct iommu_table *tbl)
+{
+	u64 val;
+	u32 aer;
+	int i = 0;
+	void __iomem *bbar = tbl->bbar;
+	void __iomem *target;
+
+	/* disable arbitration on the bus */
+	target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET);
+	aer = readl(target);
+	writel(0, target);
+
+	/* read plssr to ensure it got there */
+	target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_PLSSR_OFFSET);
+	val = readl(target);
+
+	/* poll split queues until all DMA activity is done */
+	target = calgary_reg(bbar, split_queue_offset(tbl->it_busno));
+	do {
+		val = readq(target);
+		i++;
+	} while ((val & 0xff) != 0xff && i < 100);
+	if (i == 100)
+		printk(KERN_WARNING "Calgary: PCI bus not quiesced, "
+		       "continuing anyway\n");
+
+	/* invalidate TCE cache */
+	target = calgary_reg(bbar, tar_offset(tbl->it_busno));
+	writeq(tbl->tar_val, target);
+
+	/* enable arbitration */
+	target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET);
+	writel(aer, target);
+	(void)readl(target); /* flush */
+}
+
+static void __init calgary_reserve_mem_region(struct pci_dev *dev, u64 start,
+	u64 limit)
+{
+	unsigned int numpages;
+
+	limit = limit | 0xfffff;
+	limit++;
+
+	numpages = ((limit - start) >> PAGE_SHIFT);
+	iommu_range_reserve(dev->sysdata, start, numpages);
+}
+
+static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev)
+{
+	void __iomem *target;
+	u64 low, high, sizelow;
+	u64 start, limit;
+	struct iommu_table *tbl = dev->sysdata;
+	unsigned char busnum = dev->bus->number;
+	void __iomem *bbar = tbl->bbar;
+
+	/* peripheral MEM_1 region */
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_LOW);
+	low = be32_to_cpu(readl(target));
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_HIGH);
+	high = be32_to_cpu(readl(target));
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_SIZE);
+	sizelow = be32_to_cpu(readl(target));
+
+	start = (high << 32) | low;
+	limit = sizelow;
+
+	calgary_reserve_mem_region(dev, start, limit);
+}
+
+static void __init calgary_reserve_peripheral_mem_2(struct pci_dev *dev)
+{
+	void __iomem *target;
+	u32 val32;
+	u64 low, high, sizelow, sizehigh;
+	u64 start, limit;
+	struct iommu_table *tbl = dev->sysdata;
+	unsigned char busnum = dev->bus->number;
+	void __iomem *bbar = tbl->bbar;
+
+	/* is it enabled? */
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET);
+	val32 = be32_to_cpu(readl(target));
+	if (!(val32 & PHB_MEM2_ENABLE))
+		return;
+
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_LOW);
+	low = be32_to_cpu(readl(target));
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_HIGH);
+	high = be32_to_cpu(readl(target));
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_LOW);
+	sizelow = be32_to_cpu(readl(target));
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_HIGH);
+	sizehigh = be32_to_cpu(readl(target));
+
+	start = (high << 32) | low;
+	limit = (sizehigh << 32) | sizelow;
+
+	calgary_reserve_mem_region(dev, start, limit);
+}
+
+/*
+ * some regions of the IO address space do not get translated, so we
+ * must not give devices IO addresses in those regions. The regions
+ * are the 640KB-1MB region and the two PCI peripheral memory holes.
+ * Reserve all of them in the IOMMU bitmap to avoid giving them out
+ * later.
+ */
+static void __init calgary_reserve_regions(struct pci_dev *dev)
+{
+	unsigned int npages;
+	void __iomem *bbar;
+	unsigned char busnum;
+	u64 start;
+	struct iommu_table *tbl = dev->sysdata;
+
+	bbar = tbl->bbar;
+	busnum = dev->bus->number;
+
+	/* reserve bad_dma_address in case it's a legal address */
+	iommu_range_reserve(tbl, bad_dma_address, 1);
+
+	/* avoid the BIOS/VGA first 640KB-1MB region */
+	start = (640 * 1024);
+	npages = ((1024 - 640) * 1024) >> PAGE_SHIFT;
+	iommu_range_reserve(tbl, start, npages);
+
+	/* reserve the two PCI peripheral memory regions in IO space */
+	calgary_reserve_peripheral_mem_1(dev);
+	calgary_reserve_peripheral_mem_2(dev);
+}
+
+static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
+{
+	u64 val64;
+	u64 table_phys;
+	void __iomem *target;
+	int ret;
+	struct iommu_table *tbl;
+
+	/* build TCE tables for each PHB */
+	ret = build_tce_table(dev, bbar);
+	if (ret)
+		return ret;
+
+	calgary_reserve_regions(dev);
+
+	/* set TARs for each PHB */
+	target = calgary_reg(bbar, tar_offset(dev->bus->number));
+	val64 = be64_to_cpu(readq(target));
+
+	/* zero out all TAR bits under sw control */
+	val64 &= ~TAR_SW_BITS;
+
+	tbl = dev->sysdata;
+	table_phys = (u64)__pa(tbl->it_base);
+	val64 |= table_phys;
+
+	BUG_ON(specified_table_size > TCE_TABLE_SIZE_8M);
+	val64 |= (u64) specified_table_size;
+
+	tbl->tar_val = cpu_to_be64(val64);
+	writeq(tbl->tar_val, target);
+	readq(target); /* flush */
+
+	return 0;
+}
+
+static void __init calgary_free_tar(struct pci_dev *dev)
+{
+	u64 val64;
+	struct iommu_table *tbl = dev->sysdata;
+	void __iomem *target;
+
+	target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number));
+	val64 = be64_to_cpu(readq(target));
+	val64 &= ~TAR_SW_BITS;
+	writeq(cpu_to_be64(val64), target);
+	readq(target); /* flush */
+
+	kfree(tbl);
+	dev->sysdata = NULL;
+}
+
+static void calgary_watchdog(unsigned long data)
+{
+	struct pci_dev *dev = (struct pci_dev *)data;
+	struct iommu_table *tbl = dev->sysdata;
+	void __iomem *bbar = tbl->bbar;
+	u32 val32;
+	void __iomem *target;
+
+	target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_CSR_OFFSET);
+	val32 = be32_to_cpu(readl(target));
+
+	/* If no error, the agent ID in the CSR is not valid */
+	if (val32 & CSR_AGENT_MASK) {
+		printk(KERN_EMERG "calgary_watchdog: DMA error on bus %d, "
+				  "CSR = %#x\n", dev->bus->number, val32);
+		writel(0, target);
+
+		/* Disable bus that caused the error */
+		target = calgary_reg(bbar, phb_offset(tbl->it_busno) |
+					   PHB_CONFIG_RW_OFFSET);
+		val32 = be32_to_cpu(readl(target));
+		val32 |= PHB_SLOT_DISABLE;
+		writel(cpu_to_be32(val32), target);
+		readl(target); /* flush */
+	} else {
+		/* Reset the timer */
+		mod_timer(&tbl->watchdog_timer, jiffies + 2 * HZ);
+	}
+}
+
+static void __init calgary_enable_translation(struct pci_dev *dev)
+{
+	u32 val32;
+	unsigned char busnum;
+	void __iomem *target;
+	void __iomem *bbar;
+	struct iommu_table *tbl;
+
+	busnum = dev->bus->number;
+	tbl = dev->sysdata;
+	bbar = tbl->bbar;
+
+	/* enable TCE in PHB Config Register */
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET);
+	val32 = be32_to_cpu(readl(target));
+	val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE;
+
+	printk(KERN_INFO "Calgary: enabling translation on PHB %d\n", busnum);
+	printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this "
+	       "bus.\n");
+
+	writel(cpu_to_be32(val32), target);
+	readl(target); /* flush */
+
+	init_timer(&tbl->watchdog_timer);
+	tbl->watchdog_timer.function = &calgary_watchdog;
+	tbl->watchdog_timer.data = (unsigned long)dev;
+	mod_timer(&tbl->watchdog_timer, jiffies);
+}
+
+static void __init calgary_disable_translation(struct pci_dev *dev)
+{
+	u32 val32;
+	unsigned char busnum;
+	void __iomem *target;
+	void __iomem *bbar;
+	struct iommu_table *tbl;
+
+	busnum = dev->bus->number;
+	tbl = dev->sysdata;
+	bbar = tbl->bbar;
+
+	/* disable TCE in PHB Config Register */
+	target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET);
+	val32 = be32_to_cpu(readl(target));
+	val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE);
+
+	printk(KERN_INFO "Calgary: disabling translation on PHB %d!\n", busnum);
+	writel(cpu_to_be32(val32), target);
+	readl(target); /* flush */
+
+	del_timer_sync(&tbl->watchdog_timer);
+}
+
+static inline unsigned int __init locate_register_space(struct pci_dev *dev)
+{
+	int rionodeid;
+	u32 address;
+
+	rionodeid = (dev->bus->number % 15 > 4) ? 3 : 2;
+	/*
+	 * register space address calculation as follows:
+	 * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase)
+	 * ChassisBase is always zero for x366/x260/x460
+	 * RioNodeId is 2 for first Calgary, 3 for second Calgary
+	 */
+	address = START_ADDRESS	-
+		(0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 15)) +
+		(0x100000) * (rionodeid - CHASSIS_BASE);
+	return address;
+}
+
+static int __init calgary_init_one_nontraslated(struct pci_dev *dev)
+{
+	dev->sysdata = NULL;
+	dev->bus->self = dev;
+
+	return 0;
+}
+
+static int __init calgary_init_one(struct pci_dev *dev)
+{
+	u32 address;
+	void __iomem *bbar;
+	int ret;
+
+	address = locate_register_space(dev);
+	/* map entire 1MB of Calgary config space */
+	bbar = ioremap_nocache(address, 1024 * 1024);
+	if (!bbar) {
+		ret = -ENODATA;
+		goto done;
+	}
+
+	ret = calgary_setup_tar(dev, bbar);
+	if (ret)
+		goto iounmap;
+
+	dev->bus->self = dev;
+	calgary_enable_translation(dev);
+
+	return 0;
+
+iounmap:
+	iounmap(bbar);
+done:
+	return ret;
+}
+
+static int __init calgary_init(void)
+{
+	int i, ret = -ENODEV;
+	struct pci_dev *dev = NULL;
+
+	for (i = 0; i <= num_online_nodes() * MAX_NUM_OF_PHBS; i++) {
+		dev = pci_get_device(PCI_VENDOR_ID_IBM,
+				     PCI_DEVICE_ID_IBM_CALGARY,
+				     dev);
+		if (!dev)
+			break;
+		if (!translate_phb(dev)) {
+			calgary_init_one_nontraslated(dev);
+			continue;
+		}
+		if (!tce_table_kva[i] && !translate_empty_slots) {
+			pci_dev_put(dev);
+			continue;
+		}
+		ret = calgary_init_one(dev);
+		if (ret)
+			goto error;
+	}
+
+	return ret;
+
+error:
+	for (i--; i >= 0; i--) {
+		dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
+					      PCI_DEVICE_ID_IBM_CALGARY,
+					      dev);
+		if (!translate_phb(dev)) {
+			pci_dev_put(dev);
+			continue;
+		}
+		if (!tce_table_kva[i] && !translate_empty_slots)
+			continue;
+		calgary_disable_translation(dev);
+		calgary_free_tar(dev);
+		pci_dev_put(dev);
+	}
+
+	return ret;
+}
+
+static inline int __init determine_tce_table_size(u64 ram)
+{
+	int ret;
+
+	if (specified_table_size != TCE_TABLE_SIZE_UNSPECIFIED)
+		return specified_table_size;
+
+	/*
+	 * Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to
+	 * TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each
+	 * larger table size has twice as many entries, so shift the
+	 * max ram address by 13 to divide by 8K and then look at the
+	 * order of the result to choose between 0-7.
+	 */
+	ret = get_order(ram >> 13);
+	if (ret > TCE_TABLE_SIZE_8M)
+		ret = TCE_TABLE_SIZE_8M;
+
+	return ret;
+}
+
+void __init detect_calgary(void)
+{
+	u32 val;
+	int bus, table_idx;
+	void *tbl;
+	int detected = 0;
+
+	/*
+	 * if the user specified iommu=off or iommu=soft or we found
+	 * another HW IOMMU already, bail out.
+	 */
+	if (swiotlb || no_iommu || iommu_detected)
+		return;
+
+	specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
+
+	for (bus = 0, table_idx = 0;
+	     bus <= num_online_nodes() * MAX_PHB_BUS_NUM;
+	     bus++) {
+		BUG_ON(bus > MAX_NUMNODES * MAX_PHB_BUS_NUM);
+		if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
+			continue;
+		if (test_bit(bus, translation_disabled)) {
+			printk(KERN_INFO "Calgary: translation is disabled for "
+			       "PHB 0x%x\n", bus);
+			/* skip this phb, don't allocate a tbl for it */
+			tce_table_kva[table_idx] = NULL;
+			table_idx++;
+			continue;
+		}
+		/*
+		 * scan the first slot of the PCI bus to see if there
+		 * are any devices present
+		 */
+		val = read_pci_config(bus, 1, 0, 0);
+		if (val != 0xffffffff || translate_empty_slots) {
+			tbl = alloc_tce_table();
+			if (!tbl)
+				goto cleanup;
+			detected = 1;
+		} else
+			tbl = NULL;
+
+		tce_table_kva[table_idx] = tbl;
+		table_idx++;
+	}
+
+	if (detected) {
+		iommu_detected = 1;
+		calgary_detected = 1;
+		printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. "
+		       "TCE table spec is %d.\n", specified_table_size);
+	}
+	return;
+
+cleanup:
+	for (--table_idx; table_idx >= 0; --table_idx)
+		if (tce_table_kva[table_idx])
+			free_tce_table(tce_table_kva[table_idx]);
+}
+
+int __init calgary_iommu_init(void)
+{
+	int ret;
+
+	if (no_iommu || swiotlb)
+		return -ENODEV;
+
+	if (!calgary_detected)
+		return -ENODEV;
+
+	/* ok, we're trying to use Calgary - let's roll */
+	printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n");
+
+	ret = calgary_init();
+	if (ret) {
+		printk(KERN_ERR "PCI-DMA: Calgary init failed %d, "
+		       "falling back to no_iommu\n", ret);
+		if (end_pfn > MAX_DMA32_PFN)
+			printk(KERN_ERR "WARNING more than 4GB of memory, "
+					"32bit PCI may malfunction.\n");
+		return ret;
+	}
+
+	force_iommu = 1;
+	dma_ops = &calgary_dma_ops;
+
+	return 0;
+}
+
+static int __init calgary_parse_options(char *p)
+{
+	unsigned int bridge;
+	size_t len;
+	char* endp;
+
+	while (*p) {
+		if (!strncmp(p, "64k", 3))
+			specified_table_size = TCE_TABLE_SIZE_64K;
+		else if (!strncmp(p, "128k", 4))
+			specified_table_size = TCE_TABLE_SIZE_128K;
+		else if (!strncmp(p, "256k", 4))
+			specified_table_size = TCE_TABLE_SIZE_256K;
+		else if (!strncmp(p, "512k", 4))
+			specified_table_size = TCE_TABLE_SIZE_512K;
+		else if (!strncmp(p, "1M", 2))
+			specified_table_size = TCE_TABLE_SIZE_1M;
+		else if (!strncmp(p, "2M", 2))
+			specified_table_size = TCE_TABLE_SIZE_2M;
+		else if (!strncmp(p, "4M", 2))
+			specified_table_size = TCE_TABLE_SIZE_4M;
+		else if (!strncmp(p, "8M", 2))
+			specified_table_size = TCE_TABLE_SIZE_8M;
+
+		len = strlen("translate_empty_slots");
+		if (!strncmp(p, "translate_empty_slots", len))
+			translate_empty_slots = 1;
+
+		len = strlen("disable");
+		if (!strncmp(p, "disable", len)) {
+			p += len;
+			if (*p == '=')
+				++p;
+			if (*p == '\0')
+				break;
+			bridge = simple_strtol(p, &endp, 0);
+			if (p == endp)
+				break;
+
+			if (bridge <= (num_online_nodes() * MAX_PHB_BUS_NUM)) {
+				printk(KERN_INFO "Calgary: disabling "
+				       "translation for PHB 0x%x\n", bridge);
+				set_bit(bridge, translation_disabled);
+			}
+		}
+
+		p = strpbrk(p, ",");
+		if (!p)
+			break;
+
+		p++; /* skip ',' */
+	}
+	return 1;
+}
+__setup("calgary=", calgary_parse_options);
diff --git a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c
index a9275c95..9c44f4f 100644
--- a/arch/x86_64/kernel/pci-dma.c
+++ b/arch/x86_64/kernel/pci-dma.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <asm/io.h>
 #include <asm/proto.h>
+#include <asm/calgary.h>
 
 int iommu_merge __read_mostly = 0;
 EXPORT_SYMBOL(iommu_merge);
@@ -33,12 +34,15 @@
 int force_iommu __read_mostly= 0;
 #endif
 
+/* Set this to 1 if there is a HW IOMMU in the system */
+int iommu_detected __read_mostly = 0;
+
 /* Dummy device used for NULL arguments (normally ISA). Better would
    be probably a smaller DMA mask, but this is bug-to-bug compatible
    to i386. */
 struct device fallback_dev = {
 	.bus_id = "fallback device",
-	.coherent_dma_mask = 0xffffffff,
+	.coherent_dma_mask = DMA_32BIT_MASK,
 	.dma_mask = &fallback_dev.coherent_dma_mask,
 };
 
@@ -77,7 +81,7 @@
 		dev = &fallback_dev;
 	dma_mask = dev->coherent_dma_mask;
 	if (dma_mask == 0)
-		dma_mask = 0xffffffff;
+		dma_mask = DMA_32BIT_MASK;
 
 	/* Don't invoke OOM killer */
 	gfp |= __GFP_NORETRY;
@@ -90,7 +94,7 @@
 	   larger than 16MB and in this case we have a chance of
 	   finding fitting memory in the next higher zone first. If
 	   not retry with true GFP_DMA. -AK */
-	if (dma_mask <= 0xffffffff)
+	if (dma_mask <= DMA_32BIT_MASK)
 		gfp |= GFP_DMA32;
 
  again:
@@ -111,7 +115,7 @@
 
 			/* Don't use the 16MB ZONE_DMA unless absolutely
 			   needed. It's better to use remapping first. */
-			if (dma_mask < 0xffffffff && !(gfp & GFP_DMA)) {
+			if (dma_mask < DMA_32BIT_MASK && !(gfp & GFP_DMA)) {
 				gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
 				goto again;
 			}
@@ -174,7 +178,7 @@
 	/* Copied from i386. Doesn't make much sense, because it will
 	   only work for pci_alloc_coherent.
 	   The caller just has to use GFP_DMA in this case. */
-        if (mask < 0x00ffffff)
+        if (mask < DMA_24BIT_MASK)
                 return 0;
 
 	/* Tell the device to use SAC when IOMMU force is on.  This
@@ -189,7 +193,7 @@
 	   SAC for these.  Assume all masks <= 40 bits are of this
 	   type. Normally this doesn't make any difference, but gives
 	   more gentle handling of IOMMU overflow. */
-	if (iommu_sac_force && (mask >= 0xffffffffffULL)) {
+	if (iommu_sac_force && (mask >= DMA_40BIT_MASK)) {
 		printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask);
 		return 0;
 	}
@@ -266,7 +270,7 @@
 		    swiotlb = 1;
 #endif
 
-#ifdef CONFIG_GART_IOMMU
+#ifdef CONFIG_IOMMU
 	    gart_parse_options(p);
 #endif
 
@@ -276,3 +280,40 @@
     }
     return 1;
 }
+__setup("iommu=", iommu_setup);
+
+void __init pci_iommu_alloc(void)
+{
+	/*
+	 * The order of these functions is important for
+	 * fall-back/fail-over reasons
+	 */
+#ifdef CONFIG_IOMMU
+	iommu_hole_init();
+#endif
+
+#ifdef CONFIG_CALGARY_IOMMU
+	detect_calgary();
+#endif
+
+#ifdef CONFIG_SWIOTLB
+	pci_swiotlb_init();
+#endif
+}
+
+static int __init pci_iommu_init(void)
+{
+#ifdef CONFIG_CALGARY_IOMMU
+	calgary_iommu_init();
+#endif
+
+#ifdef CONFIG_IOMMU
+	gart_iommu_init();
+#endif
+
+	no_iommu_init();
+	return 0;
+}
+
+/* Must execute after PCI subsystem */
+fs_initcall(pci_iommu_init);
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 82a7c9b..4ca674d 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -32,6 +32,7 @@
 #include <asm/kdebug.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
+#include <asm/k8.h>
 
 unsigned long iommu_bus_base;	/* GART remapping area (physical) */
 static unsigned long iommu_size; 	/* size of remapping area bytes */
@@ -46,8 +47,6 @@
    also seen with Qlogic at least). */
 int iommu_fullflush = 1;
 
-#define MAX_NB 8
-
 /* Allocation bitmap for the remapping area */ 
 static DEFINE_SPINLOCK(iommu_bitmap_lock);
 static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */
@@ -63,13 +62,6 @@
 #define to_pages(addr,size) \
 	(round_up(((addr) & ~PAGE_MASK) + (size), PAGE_SIZE) >> PAGE_SHIFT)
 
-#define for_all_nb(dev) \
-	dev = NULL;	\
-	while ((dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, dev))!=NULL)
-
-static struct pci_dev *northbridges[MAX_NB];
-static u32 northbridge_flush_word[MAX_NB];
-
 #define EMERGENCY_PAGES 32 /* = 128KB */ 
 
 #ifdef CONFIG_AGP
@@ -93,7 +85,7 @@
 	offset = find_next_zero_string(iommu_gart_bitmap,next_bit,iommu_pages,size);
 	if (offset == -1) {
 		need_flush = 1;
-	       	offset = find_next_zero_string(iommu_gart_bitmap,0,next_bit,size);
+		offset = find_next_zero_string(iommu_gart_bitmap,0,iommu_pages,size);
 	}
 	if (offset != -1) { 
 		set_bit_string(iommu_gart_bitmap, offset, size); 
@@ -120,44 +112,17 @@
 /* 
  * Use global flush state to avoid races with multiple flushers.
  */
-static void flush_gart(struct device *dev)
+static void flush_gart(void)
 { 
 	unsigned long flags;
-	int flushed = 0;
-	int i, max;
-
 	spin_lock_irqsave(&iommu_bitmap_lock, flags);
-	if (need_flush) { 
-		max = 0;
-		for (i = 0; i < MAX_NB; i++) {
-			if (!northbridges[i]) 
-				continue;
-			pci_write_config_dword(northbridges[i], 0x9c, 
-					       northbridge_flush_word[i] | 1); 
-			flushed++;
-			max = i;
-		}
-		for (i = 0; i <= max; i++) {
-			u32 w;
-			if (!northbridges[i])
-				continue;
-			/* Make sure the hardware actually executed the flush. */
-			for (;;) { 
-				pci_read_config_dword(northbridges[i], 0x9c, &w);
-				if (!(w & 1))
-					break;
-				cpu_relax();
-			}
-		} 
-		if (!flushed) 
-			printk("nothing to flush?\n");
+	if (need_flush) {
+		k8_flush_garts();
 		need_flush = 0;
 	} 
 	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
 } 
 
-
-
 #ifdef CONFIG_IOMMU_LEAK
 
 #define SET_LEAK(x) if (iommu_leak_tab) \
@@ -266,7 +231,7 @@
 				 size_t size, int dir)
 {
 	dma_addr_t map = dma_map_area(dev, virt_to_bus(buf), size, dir);
-	flush_gart(dev);
+	flush_gart();
 	return map;
 }
 
@@ -289,6 +254,28 @@
 }
 
 /*
+ * Free a DMA mapping.
+ */
+void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
+		      size_t size, int direction)
+{
+	unsigned long iommu_page;
+	int npages;
+	int i;
+
+	if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE ||
+	    dma_addr >= iommu_bus_base + iommu_size)
+		return;
+	iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
+	npages = to_pages(dma_addr, size);
+	for (i = 0; i < npages; i++) {
+		iommu_gatt_base[iommu_page + i] = gart_unmapped_entry;
+		CLEAR_LEAK(iommu_page + i);
+	}
+	free_iommu(iommu_page, npages);
+}
+
+/*
  * Wrapper for pci_unmap_single working with scatterlists.
  */
 void gart_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
@@ -299,7 +286,7 @@
 		struct scatterlist *s = &sg[i];
 		if (!s->dma_length || !s->length)
 			break;
-		dma_unmap_single(dev, s->dma_address, s->dma_length, dir);
+		gart_unmap_single(dev, s->dma_address, s->dma_length, dir);
 	}
 }
 
@@ -329,7 +316,7 @@
 		s->dma_address = addr;
 		s->dma_length = s->length;
 	}
-	flush_gart(dev);
+	flush_gart();
 	return nents;
 }
 
@@ -436,13 +423,13 @@
 	if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0)
 		goto error;
 	out++;
-	flush_gart(dev);
+	flush_gart();
 	if (out < nents) 
 		sg[out].dma_length = 0; 
 	return out;
 
 error:
-	flush_gart(NULL);
+	flush_gart();
 	gart_unmap_sg(dev, sg, nents, dir);
 	/* When it was forced or merged try again in a dumb way */
 	if (force_iommu || iommu_merge) {
@@ -458,28 +445,6 @@
 	return 0;
 } 
 
-/*
- * Free a DMA mapping.
- */ 
-void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
-		      size_t size, int direction)
-{
-	unsigned long iommu_page; 
-	int npages;
-	int i;
-
-	if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || 
-	    dma_addr >= iommu_bus_base + iommu_size)
-		return;
-	iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;	
-	npages = to_pages(dma_addr, size);
-	for (i = 0; i < npages; i++) { 
-		iommu_gatt_base[iommu_page + i] = gart_unmapped_entry; 
-		CLEAR_LEAK(iommu_page + i);
-	}
-	free_iommu(iommu_page, npages);
-}
-
 static int no_agp;
 
 static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)
@@ -532,10 +497,13 @@
 	void *gatt;
 	unsigned aper_base, new_aper_base;
 	unsigned aper_size, gatt_size, new_aper_size;
-	
+	int i;
+
 	printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
 	aper_size = aper_base = info->aper_size = 0;
-	for_all_nb(dev) { 
+	dev = NULL;
+	for (i = 0; i < num_k8_northbridges; i++) {
+		dev = k8_northbridges[i];
 		new_aper_base = read_aperture(dev, &new_aper_size); 
 		if (!new_aper_base) 
 			goto nommu; 
@@ -558,11 +526,12 @@
 		panic("Cannot allocate GATT table"); 
 	memset(gatt, 0, gatt_size); 
 	agp_gatt_table = gatt;
-	
-	for_all_nb(dev) { 
+
+	for (i = 0; i < num_k8_northbridges; i++) {
 		u32 ctl; 
 		u32 gatt_reg; 
 
+		dev = k8_northbridges[i];
 		gatt_reg = __pa(gatt) >> 12; 
 		gatt_reg <<= 4; 
 		pci_write_config_dword(dev, 0x98, gatt_reg);
@@ -573,7 +542,7 @@
 
 		pci_write_config_dword(dev, 0x90, ctl); 
 	}
-	flush_gart(NULL); 
+	flush_gart();
 	
 	printk("PCI-DMA: aperture base @ %x size %u KB\n",aper_base, aper_size>>10); 
 	return 0;
@@ -602,15 +571,19 @@
 	.unmap_sg = gart_unmap_sg,
 };
 
-static int __init pci_iommu_init(void)
+void __init gart_iommu_init(void)
 { 
 	struct agp_kern_info info;
 	unsigned long aper_size;
 	unsigned long iommu_start;
-	struct pci_dev *dev;
 	unsigned long scratch;
 	long i;
 
+	if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) {
+		printk(KERN_INFO "PCI-GART: No AMD northbridge found.\n");
+		return;
+	}
+
 #ifndef CONFIG_AGP_AMD64
 	no_agp = 1; 
 #else
@@ -622,7 +595,11 @@
 #endif	
 
 	if (swiotlb)
-		return -1; 
+		return;
+
+	/* Did we detect a different HW IOMMU? */
+	if (iommu_detected && !iommu_aperture)
+		return;
 
 	if (no_iommu ||
 	    (!force_iommu && end_pfn <= MAX_DMA32_PFN) ||
@@ -634,15 +611,7 @@
 					"but IOMMU not available.\n"
 			       KERN_ERR "WARNING 32bit PCI may malfunction.\n");
 		}
-		return -1;
-	}
-
-	i = 0;
-	for_all_nb(dev)
-		i++;
-	if (i > MAX_NB) {
-		printk(KERN_ERR "PCI-GART: Too many northbridges (%ld). Disabled\n", i);
-		return -1;
+		return;
 	}
 
 	printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
@@ -707,26 +676,10 @@
 	for (i = EMERGENCY_PAGES; i < iommu_pages; i++) 
 		iommu_gatt_base[i] = gart_unmapped_entry;
 
-	for_all_nb(dev) {
-		u32 flag; 
-		int cpu = PCI_SLOT(dev->devfn) - 24;
-		if (cpu >= MAX_NB)
-			continue;
-		northbridges[cpu] = dev;
-		pci_read_config_dword(dev, 0x9c, &flag); /* cache flush word */
-		northbridge_flush_word[cpu] = flag; 
-	}
-		     
-	flush_gart(NULL);
-
+	flush_gart();
 	dma_ops = &gart_dma_ops;
-
-	return 0;
 } 
 
-/* Must execute after PCI subsystem */
-fs_initcall(pci_iommu_init);
-
 void gart_parse_options(char *p)
 {
 	int arg;
diff --git a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c
index 1f6ecc6..c4c3cc3 100644
--- a/arch/x86_64/kernel/pci-nommu.c
+++ b/arch/x86_64/kernel/pci-nommu.c
@@ -4,6 +4,8 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/string.h>
+#include <linux/dma-mapping.h>
+
 #include <asm/proto.h>
 #include <asm/processor.h>
 #include <asm/dma.h>
@@ -12,10 +14,11 @@
 check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
 {
         if (hwdev && bus + size > *hwdev->dma_mask) {
-		if (*hwdev->dma_mask >= 0xffffffffULL)
+		if (*hwdev->dma_mask >= DMA_32BIT_MASK)
 			printk(KERN_ERR
-			    "nommu_%s: overflow %Lx+%lu of device mask %Lx\n",
-	       			name, (long long)bus, size, (long long)*hwdev->dma_mask);
+			    "nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
+				name, (long long)bus, size,
+				(long long)*hwdev->dma_mask);
 		return 0;
 	}
 	return 1;
diff --git a/arch/x86_64/kernel/pci-swiotlb.c b/arch/x86_64/kernel/pci-swiotlb.c
index 990ed67..ebdb77f 100644
--- a/arch/x86_64/kernel/pci-swiotlb.c
+++ b/arch/x86_64/kernel/pci-swiotlb.c
@@ -31,7 +31,7 @@
 void pci_swiotlb_init(void)
 {
 	/* don't initialize swiotlb if iommu=off (no_iommu=1) */
-	if (!iommu_aperture && !no_iommu &&
+	if (!iommu_detected && !no_iommu &&
 	    (end_pfn > MAX_DMA32_PFN || force_iommu))
 	       swiotlb = 1;
 	if (swiotlb) {
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
index bf421ed..7554458 100644
--- a/arch/x86_64/kernel/pmtimer.c
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -27,7 +27,7 @@
 /* The I/O port the PMTMR resides at.
  * The location is detected during setup_arch(),
  * in arch/i386/kernel/acpi/boot.c */
-u32 pmtmr_ioport;
+u32 pmtmr_ioport __read_mostly;
 
 /* value of the Power timer at last timer interrupt */
 static u32 offset_delay;
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index fb903e6..ca56e19 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -10,7 +10,6 @@
  *	Andi Kleen.
  *
  *	CPU hotplug support - ashok.raj@intel.com
- *  $Id: process.c,v 1.38 2002/01/15 10:08:03 ak Exp $
  */
 
 /*
@@ -64,6 +63,7 @@
  * Powermanagement idle function, if any..
  */
 void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
 static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
 
 static ATOMIC_NOTIFIER_HEAD(idle_notifier);
@@ -111,7 +111,7 @@
 {
 	local_irq_enable();
 
-	clear_thread_flag(TIF_POLLING_NRFLAG);
+	current_thread_info()->status &= ~TS_POLLING;
 	smp_mb__after_clear_bit();
 	while (!need_resched()) {
 		local_irq_disable();
@@ -120,7 +120,7 @@
 		else
 			local_irq_enable();
 	}
-	set_thread_flag(TIF_POLLING_NRFLAG);
+	current_thread_info()->status |= TS_POLLING;
 }
 
 /*
@@ -203,8 +203,7 @@
  */
 void cpu_idle (void)
 {
-	set_thread_flag(TIF_POLLING_NRFLAG);
-
+	current_thread_info()->status |= TS_POLLING;
 	/* endless idle loop with no priority at all */
 	while (1) {
 		while (!need_resched()) {
@@ -335,7 +334,7 @@
 {
 	printk("CPU %d:", smp_processor_id());
 	__show_regs(regs);
-	show_trace(&regs->rsp);
+	show_trace(NULL, regs, (void *)(regs + 1));
 }
 
 /*
@@ -365,8 +364,11 @@
 	struct task_struct *tsk = current;
 	struct thread_info *t = current_thread_info();
 
-	if (t->flags & _TIF_ABI_PENDING)
+	if (t->flags & _TIF_ABI_PENDING) {
 		t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
+		if (t->flags & _TIF_IA32)
+			current_thread_info()->status |= TS_COMPAT;
+	}
 
 	tsk->thread.debugreg0 = 0;
 	tsk->thread.debugreg1 = 0;
diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c
index 57117b8..2d67698 100644
--- a/arch/x86_64/kernel/reboot.c
+++ b/arch/x86_64/kernel/reboot.c
@@ -20,6 +20,7 @@
  * Power off function, if any
  */
 void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
 
 static long no_idt[3];
 static enum { 
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 655b919..1129918 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -5,8 +5,6 @@
  *
  *  Nov 2001 Dave Jones <davej@suse.de>
  *  Forked from i386 setup code.
- *
- *  $Id$
  */
 
 /*
@@ -65,9 +63,7 @@
 #include <asm/setup.h>
 #include <asm/mach_apic.h>
 #include <asm/numa.h>
-#include <asm/swiotlb.h>
 #include <asm/sections.h>
-#include <asm/gart-mapping.h>
 #include <asm/dmi.h>
 
 /*
@@ -75,6 +71,7 @@
  */
 
 struct cpuinfo_x86 boot_cpu_data __read_mostly;
+EXPORT_SYMBOL(boot_cpu_data);
 
 unsigned long mmu_cr4_features;
 
@@ -103,12 +100,14 @@
  * Setup options
  */
 struct screen_info screen_info;
+EXPORT_SYMBOL(screen_info);
 struct sys_desc_table_struct {
 	unsigned short length;
 	unsigned char table[0];
 };
 
 struct edid_info edid_info;
+EXPORT_SYMBOL_GPL(edid_info);
 struct e820map e820;
 
 extern int root_mountflags;
@@ -473,80 +472,6 @@
 } 
 #endif
 
-/* Use inline assembly to define this because the nops are defined 
-   as inline assembly strings in the include files and we cannot 
-   get them easily into strings. */
-asm("\t.data\nk8nops: " 
-    K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
-    K8_NOP7 K8_NOP8); 
-    
-extern unsigned char k8nops[];
-static unsigned char *k8_nops[ASM_NOP_MAX+1] = { 
-     NULL,
-     k8nops,
-     k8nops + 1,
-     k8nops + 1 + 2,
-     k8nops + 1 + 2 + 3,
-     k8nops + 1 + 2 + 3 + 4,
-     k8nops + 1 + 2 + 3 + 4 + 5,
-     k8nops + 1 + 2 + 3 + 4 + 5 + 6,
-     k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
-}; 
-
-extern char __vsyscall_0;
-
-/* Replace instructions with better alternatives for this CPU type.
-
-   This runs before SMP is initialized to avoid SMP problems with
-   self modifying code. This implies that assymetric systems where
-   APs have less capabilities than the boot processor are not handled. 
-   In this case boot with "noreplacement". */ 
-void apply_alternatives(void *start, void *end) 
-{ 
-	struct alt_instr *a; 
-	int diff, i, k;
-	for (a = start; (void *)a < end; a++) { 
-		u8 *instr;
-
-		if (!boot_cpu_has(a->cpuid))
-			continue;
-
-		BUG_ON(a->replacementlen > a->instrlen); 
-		instr = a->instr;
-		/* vsyscall code is not mapped yet. resolve it manually. */
-		if (instr >= (u8 *)VSYSCALL_START && instr < (u8*)VSYSCALL_END)
-			instr = __va(instr - (u8*)VSYSCALL_START + (u8*)__pa_symbol(&__vsyscall_0));
-		__inline_memcpy(instr, a->replacement, a->replacementlen);
-		diff = a->instrlen - a->replacementlen; 
-
-		/* Pad the rest with nops */
-		for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
-			k = diff;
-			if (k > ASM_NOP_MAX)
-				k = ASM_NOP_MAX;
-			__inline_memcpy(instr + i, k8_nops[k], k);
-		} 
-	}
-} 
-
-static int no_replacement __initdata = 0; 
- 
-void __init alternative_instructions(void)
-{
-	extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
-	if (no_replacement) 
-		return;
-	apply_alternatives(__alt_instructions, __alt_instructions_end);
-}
-
-static int __init noreplacement_setup(char *s)
-{ 
-     no_replacement = 1; 
-     return 1;
-} 
-
-__setup("noreplacement", noreplacement_setup); 
-
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
 struct edd edd;
 #ifdef CONFIG_EDD_MODULE
@@ -728,7 +653,7 @@
 #endif
 #ifdef CONFIG_KEXEC
 	if (crashk_res.start != crashk_res.end) {
-		reserve_bootmem(crashk_res.start,
+		reserve_bootmem_generic(crashk_res.start,
 			crashk_res.end - crashk_res.start + 1);
 	}
 #endif
@@ -779,10 +704,6 @@
 
 	e820_setup_gap();
 
-#ifdef CONFIG_GART_IOMMU
-	iommu_hole_init();
-#endif
-
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
 	conswitchp = &vga_con;
@@ -867,24 +788,32 @@
 static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
-	int cpu = smp_processor_id();
 	unsigned bits;
 #ifdef CONFIG_NUMA
+	int cpu = smp_processor_id();
 	int node = 0;
 	unsigned apicid = hard_smp_processor_id();
 #endif
+	unsigned ecx = cpuid_ecx(0x80000008);
 
-	bits = 0;
-	while ((1 << bits) < c->x86_max_cores)
-		bits++;
+	c->x86_max_cores = (ecx & 0xff) + 1;
+
+	/* CPU telling us the core id bits shift? */
+	bits = (ecx >> 12) & 0xF;
+
+	/* Otherwise recompute */
+	if (bits == 0) {
+		while ((1 << bits) < c->x86_max_cores)
+			bits++;
+	}
 
 	/* Low order bits define the core id (index of core in socket) */
-	cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
+	c->cpu_core_id = c->phys_proc_id & ((1 << bits)-1);
 	/* Convert the APIC ID into the socket ID */
-	phys_proc_id[cpu] = phys_pkg_id(bits);
+	c->phys_proc_id = phys_pkg_id(bits);
 
 #ifdef CONFIG_NUMA
-  	node = phys_proc_id[cpu];
+  	node = c->phys_proc_id;
  	if (apicid_to_node[apicid] != NUMA_NO_NODE)
  		node = apicid_to_node[apicid];
  	if (!node_online(node)) {
@@ -897,7 +826,7 @@
  		   but in the same order as the HT nodeids.
  		   If that doesn't result in a usable node fall back to the
  		   path for the previous case.  */
- 		int ht_nodeid = apicid - (phys_proc_id[0] << bits);
+ 		int ht_nodeid = apicid - (cpu_data[0].phys_proc_id << bits);
  		if (ht_nodeid >= 0 &&
  		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
  			node = apicid_to_node[ht_nodeid];
@@ -907,15 +836,13 @@
  	}
 	numa_set_node(cpu, node);
 
-  	printk(KERN_INFO "CPU %d/%x(%d) -> Node %d -> Core %d\n",
-  			cpu, apicid, c->x86_max_cores, node, cpu_core_id[cpu]);
+	printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
 #endif
 #endif
 }
 
-static int __init init_amd(struct cpuinfo_x86 *c)
+static void __init init_amd(struct cpuinfo_x86 *c)
 {
-	int r;
 	unsigned level;
 
 #ifdef CONFIG_SMP
@@ -948,8 +875,8 @@
 	if (c->x86 >= 6)
 		set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
 
-	r = get_model_name(c);
-	if (!r) { 
+	level = get_model_name(c);
+	if (!level) {
 		switch (c->x86) { 
 		case 15:
 			/* Should distinguish Models here, but this is only
@@ -964,13 +891,12 @@
 	if (c->x86_power & (1<<8))
 		set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
 
-	if (c->extended_cpuid_level >= 0x80000008) {
-		c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
-
+	/* Multi core CPU? */
+	if (c->extended_cpuid_level >= 0x80000008)
 		amd_detect_cmp(c);
-	}
 
-	return r;
+	/* Fix cpuid4 emulation for more */
+	num_cache_leaves = 3;
 }
 
 static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -978,13 +904,14 @@
 #ifdef CONFIG_SMP
 	u32 	eax, ebx, ecx, edx;
 	int 	index_msb, core_bits;
-	int 	cpu = smp_processor_id();
 
 	cpuid(1, &eax, &ebx, &ecx, &edx);
 
 
-	if (!cpu_has(c, X86_FEATURE_HT) || cpu_has(c, X86_FEATURE_CMP_LEGACY))
+	if (!cpu_has(c, X86_FEATURE_HT))
 		return;
+ 	if (cpu_has(c, X86_FEATURE_CMP_LEGACY))
+		goto out;
 
 	smp_num_siblings = (ebx & 0xff0000) >> 16;
 
@@ -999,10 +926,7 @@
 		}
 
 		index_msb = get_count_order(smp_num_siblings);
-		phys_proc_id[cpu] = phys_pkg_id(index_msb);
-
-		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n",
-		       phys_proc_id[cpu]);
+		c->phys_proc_id = phys_pkg_id(index_msb);
 
 		smp_num_siblings = smp_num_siblings / c->x86_max_cores;
 
@@ -1010,13 +934,15 @@
 
 		core_bits = get_count_order(c->x86_max_cores);
 
-		cpu_core_id[cpu] = phys_pkg_id(index_msb) &
+		c->cpu_core_id = phys_pkg_id(index_msb) &
 					       ((1 << core_bits) - 1);
-
-		if (c->x86_max_cores > 1)
-			printk(KERN_INFO  "CPU: Processor Core ID: %d\n",
-			       cpu_core_id[cpu]);
 	}
+out:
+	if ((c->x86_max_cores * smp_num_siblings) > 1) {
+		printk(KERN_INFO  "CPU: Physical Processor ID: %d\n", c->phys_proc_id);
+		printk(KERN_INFO  "CPU: Processor Core ID: %d\n", c->cpu_core_id);
+	}
+
 #endif
 }
 
@@ -1025,15 +951,12 @@
  */
 static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
 {
-	unsigned int eax;
+	unsigned int eax, t;
 
 	if (c->cpuid_level < 4)
 		return 1;
 
-	__asm__("cpuid"
-		: "=a" (eax)
-		: "0" (4), "c" (0)
-		: "bx", "dx");
+	cpuid_count(4, 0, &eax, &t, &t, &t);
 
 	if (eax & 0x1f)
 		return ((eax >> 26) + 1);
@@ -1046,16 +969,17 @@
 #ifdef CONFIG_NUMA
 	unsigned node;
 	int cpu = smp_processor_id();
+	int apicid = hard_smp_processor_id();
 
 	/* Don't do the funky fallback heuristics the AMD version employs
 	   for now. */
-	node = apicid_to_node[hard_smp_processor_id()];
+	node = apicid_to_node[apicid];
 	if (node == NUMA_NO_NODE)
 		node = first_node(node_online_map);
 	numa_set_node(cpu, node);
 
 	if (acpi_numa > 0)
-		printk(KERN_INFO "CPU %d -> Node %d\n", cpu, node);
+		printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
 #endif
 }
 
@@ -1065,6 +989,13 @@
 	unsigned n;
 
 	init_intel_cacheinfo(c);
+	if (c->cpuid_level > 9 ) {
+		unsigned eax = cpuid_eax(10);
+		/* Check for version and the number of counters */
+		if ((eax & 0xff) && (((eax>>8) & 0xff) > 1))
+			set_bit(X86_FEATURE_ARCH_PERFMON, &c->x86_capability);
+	}
+
 	n = c->extended_cpuid_level;
 	if (n >= 0x80000008) {
 		unsigned eax = cpuid_eax(0x80000008);
@@ -1156,7 +1087,7 @@
 	}
 
 #ifdef CONFIG_SMP
-	phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+	c->phys_proc_id = (cpuid_ebx(1) >> 24) & 0xff;
 #endif
 }
 
@@ -1283,7 +1214,7 @@
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, "nx", NULL, "mmxext", NULL,
-		NULL, "fxsr_opt", "rdtscp", NULL, NULL, "lm", "3dnowext", "3dnow",
+		NULL, "fxsr_opt", NULL, "rdtscp", NULL, "lm", "3dnowext", "3dnow",
 
 		/* Transmeta-defined */
 		"recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
@@ -1294,7 +1225,7 @@
 		/* Other (Linux-defined) */
 		"cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
 		"constant_tsc", NULL, NULL,
-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+		"up", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
@@ -1364,9 +1295,9 @@
 #ifdef CONFIG_SMP
 	if (smp_num_siblings * c->x86_max_cores > 1) {
 		int cpu = c - cpu_data;
-		seq_printf(m, "physical id\t: %d\n", phys_proc_id[cpu]);
+		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
 		seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[cpu]));
-		seq_printf(m, "core id\t\t: %d\n", cpu_core_id[cpu]);
+		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
 		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
 	}
 #endif	
@@ -1440,7 +1371,7 @@
 	.show =	show_cpuinfo,
 };
 
-#ifdef CONFIG_INPUT_PCSPKR
+#if defined(CONFIG_INPUT_PCSPKR) || defined(CONFIG_INPUT_PCSPKR_MODULE)
 #include <linux/platform_device.h>
 static __init int add_pcspkr(void)
 {
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 8a691fa..f5934cb 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -3,7 +3,6 @@
  * Copyright (C) 1995  Linus Torvalds
  * Copyright 2001, 2002, 2003 SuSE Labs / Andi Kleen.
  * See setup.c for older changelog.
- * $Id: setup64.c,v 1.12 2002/03/21 10:09:17 ak Exp $
  */ 
 #include <linux/config.h>
 #include <linux/init.h>
@@ -31,6 +30,7 @@
 cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
 
 struct x8664_pda *_cpu_pda[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(_cpu_pda);
 struct x8664_pda boot_cpu_pda[NR_CPUS] __cacheline_aligned;
 
 struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table };
@@ -38,6 +38,7 @@
 char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
 
 unsigned long __supported_pte_mask __read_mostly = ~0UL;
+EXPORT_SYMBOL(__supported_pte_mask);
 static int do_not_nx __cpuinitdata = 0;
 
 /* noexec=on|off
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index e5f5ce79..2816117 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -7,8 +7,6 @@
  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  *  2000-2002   x86-64 support by Andi Kleen
- * 
- *  $Id: signal.c,v 1.18 2001/10/17 22:30:37 ak Exp $
  */
 
 #include <linux/sched.h>
@@ -239,7 +237,6 @@
 	rsp = regs->rsp - 128;
 
 	/* This is the X/Open sanctioned signal stack switching.  */
-	/* RED-PEN: redzone on that stack? */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
 		if (sas_ss_flags(rsp) == 0)
 			rsp = current->sas_ss_sp + current->sas_ss_size;
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 4a6628b..5a1c0a3 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -135,10 +135,10 @@
 
 	cpu = smp_processor_id();
 	/*
-	 * orig_rax contains the interrupt vector - 256.
+	 * orig_rax contains the negated interrupt vector.
 	 * Use that to determine where the sender put the data.
 	 */
-	sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
+	sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START;
 	f = &per_cpu(flush_state, sender);
 
 	if (!cpu_isset(cpu, f->flush_cpumask))
@@ -224,6 +224,7 @@
 		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
 	preempt_enable();
 }
+EXPORT_SYMBOL(flush_tlb_current_task);
 
 void flush_tlb_mm (struct mm_struct * mm)
 {
@@ -244,6 +245,7 @@
 
 	preempt_enable();
 }
+EXPORT_SYMBOL(flush_tlb_mm);
 
 void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
 {
@@ -266,6 +268,7 @@
 
 	preempt_enable();
 }
+EXPORT_SYMBOL(flush_tlb_page);
 
 static void do_flush_tlb_all(void* info)
 {
@@ -443,6 +446,7 @@
 	spin_unlock(&call_lock);
 	return 0;
 }
+EXPORT_SYMBOL(smp_call_function);
 
 void smp_stop_cpu(void)
 {
@@ -460,7 +464,7 @@
 {
 	smp_stop_cpu(); 
 	for (;;) 
-		asm("hlt"); 
+		halt();
 } 
 
 void smp_send_stop(void)
@@ -470,7 +474,7 @@
 		return;
 	/* Don't deadlock on the call lock in panic */
 	if (!spin_trylock(&call_lock)) {
-		/* ignore locking because we have paniced anyways */
+		/* ignore locking because we have panicked anyways */
 		nolock = 1;
 	}
 	__smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
@@ -520,13 +524,13 @@
 
 int safe_smp_processor_id(void)
 {
-	int apicid, i;
+	unsigned apicid, i;
 
 	if (disable_apic)
 		return 0;
 
 	apicid = hard_smp_processor_id();
-	if (x86_cpu_to_apicid[apicid] == apicid)
+	if (apicid < NR_CPUS && x86_cpu_to_apicid[apicid] == apicid)
 		return apicid;
 
 	for (i = 0; i < NR_CPUS; ++i) {
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 71a7222..540c0cc 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -63,13 +63,11 @@
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
-/* Package ID of each logical CPU */
-u8 phys_proc_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
-/* core ID of each logical CPU */
-u8 cpu_core_id[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = BAD_APICID };
+EXPORT_SYMBOL(smp_num_siblings);
 
 /* Last level cache ID of each logical CPU */
 u8 cpu_llc_id[NR_CPUS] __cpuinitdata  = {[0 ... NR_CPUS-1] = BAD_APICID};
+EXPORT_SYMBOL(cpu_llc_id);
 
 /* Bitmask of currently online CPUs */
 cpumask_t cpu_online_map __read_mostly;
@@ -82,18 +80,21 @@
  */
 cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
+EXPORT_SYMBOL(cpu_callout_map);
 
 cpumask_t cpu_possible_map;
 EXPORT_SYMBOL(cpu_possible_map);
 
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_data);
 
 /* Set when the idlers are all forked */
 int smp_threads_ready;
 
 /* representing HT siblings of each logical CPU */
 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(cpu_sibling_map);
 
 /* representing HT and core siblings of each logical CPU */
 cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
@@ -454,10 +455,12 @@
 	struct cpuinfo_x86 *c = cpu_data + cpu;
 	/*
 	 * For perf, we return last level cache shared map.
-	 * TBD: when power saving sched policy is added, we will return
-	 *      cpu_core_map when power saving policy is enabled
+	 * And for power savings, we return cpu_core_map
 	 */
-	return c->llc_shared_map;
+	if (sched_mc_power_savings || sched_smt_power_savings)
+		return cpu_core_map[cpu];
+	else
+		return c->llc_shared_map;
 }
 
 /* representing cpus for which sibling maps can be computed */
@@ -472,8 +475,8 @@
 
 	if (smp_num_siblings > 1) {
 		for_each_cpu_mask(i, cpu_sibling_setup_map) {
-			if (phys_proc_id[cpu] == phys_proc_id[i] &&
-			    cpu_core_id[cpu] == cpu_core_id[i]) {
+			if (c[cpu].phys_proc_id == c[i].phys_proc_id &&
+			    c[cpu].cpu_core_id == c[i].cpu_core_id) {
 				cpu_set(i, cpu_sibling_map[cpu]);
 				cpu_set(cpu, cpu_sibling_map[i]);
 				cpu_set(i, cpu_core_map[cpu]);
@@ -500,7 +503,7 @@
 			cpu_set(i, c[cpu].llc_shared_map);
 			cpu_set(cpu, c[i].llc_shared_map);
 		}
-		if (phys_proc_id[cpu] == phys_proc_id[i]) {
+		if (c[cpu].phys_proc_id == c[i].phys_proc_id) {
 			cpu_set(i, cpu_core_map[cpu]);
 			cpu_set(cpu, cpu_core_map[i]);
 			/*
@@ -797,6 +800,8 @@
 	}
 
 
+	alternatives_smp_switch(1);
+
 	c_idle.idle = get_idle_for_cpu(cpu);
 
 	if (c_idle.idle) {
@@ -1199,8 +1204,8 @@
 		cpu_clear(cpu, cpu_sibling_map[sibling]);
 	cpus_clear(cpu_sibling_map[cpu]);
 	cpus_clear(cpu_core_map[cpu]);
-	phys_proc_id[cpu] = BAD_APICID;
-	cpu_core_id[cpu] = BAD_APICID;
+	c[cpu].phys_proc_id = 0;
+	c[cpu].cpu_core_id = 0;
 	cpu_clear(cpu, cpu_sibling_setup_map);
 }
 
@@ -1259,6 +1264,8 @@
 		/* They ack this in play_dead by setting CPU_DEAD */
 		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
 			printk ("CPU %d is now offline\n", cpu);
+			if (1 == num_online_cpus())
+				alternatives_smp_switch(0);
 			return;
 		}
 		msleep(100);
diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c
new file mode 100644
index 0000000..8d4c67f
--- /dev/null
+++ b/arch/x86_64/kernel/tce.c
@@ -0,0 +1,202 @@
+/*
+ * Derived from arch/powerpc/platforms/pseries/iommu.c
+ *
+ * Copyright (C) 2006 Jon Mason <jdmason@us.ibm.com>, IBM Corporation
+ * Copyright (C) 2006 Muli Ben-Yehuda <muli@il.ibm.com>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/bootmem.h>
+#include <asm/tce.h>
+#include <asm/calgary.h>
+#include <asm/proto.h>
+
+/* flush a tce at 'tceaddr' to main memory */
+static inline void flush_tce(void* tceaddr)
+{
+	/* a single tce can't cross a cache line */
+	if (cpu_has_clflush)
+		asm volatile("clflush (%0)" :: "r" (tceaddr));
+	else
+		asm volatile("wbinvd":::"memory");
+}
+
+void tce_build(struct iommu_table *tbl, unsigned long index,
+	unsigned int npages, unsigned long uaddr, int direction)
+{
+	u64* tp;
+	u64 t;
+	u64 rpn;
+
+	t = (1 << TCE_READ_SHIFT);
+	if (direction != DMA_TO_DEVICE)
+		t |= (1 << TCE_WRITE_SHIFT);
+
+	tp = ((u64*)tbl->it_base) + index;
+
+	while (npages--) {
+		rpn = (virt_to_bus((void*)uaddr)) >> PAGE_SHIFT;
+		t &= ~TCE_RPN_MASK;
+		t |= (rpn << TCE_RPN_SHIFT);
+
+		*tp = cpu_to_be64(t);
+		flush_tce(tp);
+
+		uaddr += PAGE_SIZE;
+		tp++;
+	}
+}
+
+void tce_free(struct iommu_table *tbl, long index, unsigned int npages)
+{
+	u64* tp;
+
+	tp  = ((u64*)tbl->it_base) + index;
+
+	while (npages--) {
+		*tp = cpu_to_be64(0);
+		flush_tce(tp);
+		tp++;
+	}
+}
+
+static inline unsigned int table_size_to_number_of_entries(unsigned char size)
+{
+	/*
+	 * size is the order of the table, 0-7
+	 * smallest table is 8K entries, so shift result by 13 to
+	 * multiply by 8K
+	 */
+	return (1 << size) << 13;
+}
+
+static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
+{
+	unsigned int bitmapsz;
+	unsigned int tce_table_index;
+	unsigned long bmppages;
+	int ret;
+
+	tbl->it_busno = dev->bus->number;
+
+	/* set the tce table size - measured in entries */
+	tbl->it_size = table_size_to_number_of_entries(specified_table_size);
+
+	tce_table_index = bus_to_phb(tbl->it_busno);
+	tbl->it_base = (unsigned long)tce_table_kva[tce_table_index];
+	if (!tbl->it_base) {
+		printk(KERN_ERR "Calgary: iommu_table_setparms: "
+		       "no table allocated?!\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	/*
+	 * number of bytes needed for the bitmap size in number of
+	 * entries; we need one bit per entry
+	 */
+	bitmapsz = tbl->it_size / BITS_PER_BYTE;
+	bmppages = __get_free_pages(GFP_KERNEL, get_order(bitmapsz));
+	if (!bmppages) {
+		printk(KERN_ERR "Calgary: cannot allocate bitmap\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	tbl->it_map = (unsigned long*)bmppages;
+
+	memset(tbl->it_map, 0, bitmapsz);
+
+	tbl->it_hint = 0;
+
+	spin_lock_init(&tbl->it_lock);
+
+	return 0;
+
+done:
+	return ret;
+}
+
+int build_tce_table(struct pci_dev *dev, void __iomem *bbar)
+{
+	struct iommu_table *tbl;
+	int ret;
+
+	if (dev->sysdata) {
+		printk(KERN_ERR "Calgary: dev %p has sysdata %p\n",
+		       dev, dev->sysdata);
+		BUG();
+	}
+
+	tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL);
+	if (!tbl) {
+		printk(KERN_ERR "Calgary: error allocating iommu_table\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
+	ret = tce_table_setparms(dev, tbl);
+	if (ret)
+		goto free_tbl;
+
+	tce_free(tbl, 0, tbl->it_size);
+
+	tbl->bbar = bbar;
+
+	/*
+	 * NUMA is already using the bus's sysdata pointer, so we use
+	 * the bus's pci_dev's sysdata instead.
+	 */
+	dev->sysdata = tbl;
+
+	return 0;
+
+free_tbl:
+	kfree(tbl);
+done:
+	return ret;
+}
+
+void* alloc_tce_table(void)
+{
+	unsigned int size;
+
+	size = table_size_to_number_of_entries(specified_table_size);
+	size *= TCE_ENTRY_SIZE;
+
+	return __alloc_bootmem_low(size, size, 0);
+}
+
+void free_tce_table(void *tbl)
+{
+	unsigned int size;
+
+	if (!tbl)
+		return;
+
+	size = table_size_to_number_of_entries(specified_table_size);
+	size *= TCE_ENTRY_SIZE;
+
+	free_bootmem(__pa(tbl), size);
+}
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 7392570..ebbee6f 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -8,7 +8,7 @@
  *  Copyright (c) 1995  Markus Kuhn
  *  Copyright (c) 1996  Ingo Molnar
  *  Copyright (c) 1998  Andrea Arcangeli
- *  Copyright (c) 2002  Vojtech Pavlik
+ *  Copyright (c) 2002,2006  Vojtech Pavlik
  *  Copyright (c) 2003  Andi Kleen
  *  RTC support code taken from arch/i386/kernel/timers/time_hpet.c
  */
@@ -51,14 +51,21 @@
 static char *time_init_gtod(void);
 
 DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
 DEFINE_SPINLOCK(i8253_lock);
 
 int nohpet __initdata = 0;
 static int notsc __initdata = 0;
 
-#undef HPET_HACK_ENABLE_DANGEROUS
+#define USEC_PER_TICK (USEC_PER_SEC / HZ)
+#define NSEC_PER_TICK (NSEC_PER_SEC / HZ)
+#define FSEC_PER_TICK (FSEC_PER_SEC / HZ)
+
+#define NS_SCALE	10 /* 2^10, carefully chosen */
+#define US_SCALE	32 /* 2^32, arbitralrily chosen */
 
 unsigned int cpu_khz;					/* TSC clocks / usec, not used here */
+EXPORT_SYMBOL(cpu_khz);
 static unsigned long hpet_period;			/* fsecs / HPET clock */
 unsigned long hpet_tick;				/* HPET clocks / interrupt */
 int hpet_use_timer;				/* Use counter of hpet for time keeping, otherwise PIT */
@@ -90,7 +97,7 @@
 	t = get_cycles_sync();
 	if (t < vxtime.last_tsc) 
 		t = vxtime.last_tsc; /* hack */
-	x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32;
+	x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> US_SCALE;
 	return x;
 }
 
@@ -98,7 +105,7 @@
 {
 	/* cap counter read to one tick to avoid inconsistencies */
 	unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
-	return (min(counter,hpet_tick) * vxtime.quot) >> 32;
+	return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;
 }
 
 unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
@@ -118,7 +125,7 @@
 		seq = read_seqbegin(&xtime_lock);
 
 		sec = xtime.tv_sec;
-		usec = xtime.tv_nsec / 1000;
+		usec = xtime.tv_nsec / NSEC_PER_USEC;
 
 		/* i386 does some correction here to keep the clock 
 		   monotonous even when ntpd is fixing drift.
@@ -129,14 +136,14 @@
 		   in arch/x86_64/kernel/vsyscall.c and export all needed
 		   variables in vmlinux.lds. -AK */ 
 
-		t = (jiffies - wall_jiffies) * (1000000L / HZ) +
+		t = (jiffies - wall_jiffies) * USEC_PER_TICK +
 			do_gettimeoffset();
 		usec += t;
 
 	} while (read_seqretry(&xtime_lock, seq));
 
-	tv->tv_sec = sec + usec / 1000000;
-	tv->tv_usec = usec % 1000000;
+	tv->tv_sec = sec + usec / USEC_PER_SEC;
+	tv->tv_usec = usec % USEC_PER_SEC;
 }
 
 EXPORT_SYMBOL(do_gettimeofday);
@@ -157,8 +164,8 @@
 
 	write_seqlock_irq(&xtime_lock);
 
-	nsec -= do_gettimeoffset() * 1000 +
-		(jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ);
+	nsec -= do_gettimeoffset() * NSEC_PER_USEC +
+		(jiffies - wall_jiffies) * NSEC_PER_TICK;
 
 	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
 	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
@@ -288,7 +295,7 @@
 			this_offset = hpet_readl(HPET_COUNTER);
 		} while (read_seqretry(&xtime_lock, seq));
 		offset = (this_offset - last_offset);
-		offset *= (NSEC_PER_SEC/HZ) / hpet_tick;
+		offset *= NSEC_PER_TICK / hpet_tick;
 	} else {
 		do {
 			seq = read_seqbegin(&xtime_lock);
@@ -297,7 +304,8 @@
 			base = monotonic_base;
 		} while (read_seqretry(&xtime_lock, seq));
 		this_offset = get_cycles_sync();
-		offset = (this_offset - last_offset)*1000 / cpu_khz; 
+		/* FIXME: 1000 or 1000000? */
+		offset = (this_offset - last_offset)*1000 / cpu_khz;
 	}
 	return base + offset;
 }
@@ -382,7 +390,7 @@
 		}
 
 		monotonic_base += 
-			(offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
+			(offset - vxtime.last) * NSEC_PER_TICK / hpet_tick;
 
 		vxtime.last = offset;
 #ifdef CONFIG_X86_PM_TIMER
@@ -391,24 +399,25 @@
 #endif
 	} else {
 		offset = (((tsc - vxtime.last_tsc) *
-			   vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
+			   vxtime.tsc_quot) >> US_SCALE) - USEC_PER_TICK;
 
 		if (offset < 0)
 			offset = 0;
 
-		if (offset > (USEC_PER_SEC / HZ)) {
-			lost = offset / (USEC_PER_SEC / HZ);
-			offset %= (USEC_PER_SEC / HZ);
+		if (offset > USEC_PER_TICK) {
+			lost = offset / USEC_PER_TICK;
+			offset %= USEC_PER_TICK;
 		}
 
-		monotonic_base += (tsc - vxtime.last_tsc)*1000000/cpu_khz ;
+		/* FIXME: 1000 or 1000000? */
+		monotonic_base += (tsc - vxtime.last_tsc) * 1000000 / cpu_khz;
 
 		vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
 
 		if ((((tsc - vxtime.last_tsc) *
-		      vxtime.tsc_quot) >> 32) < offset)
+		      vxtime.tsc_quot) >> US_SCALE) < offset)
 			vxtime.last_tsc = tsc -
-				(((long) offset << 32) / vxtime.tsc_quot) - 1;
+				(((long) offset << US_SCALE) / vxtime.tsc_quot) - 1;
 	}
 
 	if (lost > 0) {
@@ -468,16 +477,15 @@
 }
 
 static unsigned int cyc2ns_scale __read_mostly;
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
 
 static inline void set_cyc2ns_scale(unsigned long cpu_khz)
 {
-	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
+	cyc2ns_scale = (NSEC_PER_MSEC << NS_SCALE) / cpu_khz;
 }
 
 static inline unsigned long long cycles_2_ns(unsigned long long cyc)
 {
-	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+	return (cyc * cyc2ns_scale) >> NS_SCALE;
 }
 
 unsigned long long sched_clock(void)
@@ -490,7 +498,7 @@
            Disadvantage is a small drift between CPUs in some configurations,
 	   but that should be tolerable. */
 	if (__vxtime.mode == VXTIME_HPET)
-		return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> 32;
+		return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> US_SCALE;
 #endif
 
 	/* Could do CPU core sync here. Opteron can execute rdtsc speculatively,
@@ -633,7 +641,7 @@
 
 		cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
 		if (!(freq->flags & CPUFREQ_CONST_LOOPS))
-			vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+			vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
 	}
 	
 	set_cyc2ns_scale(cpu_khz_ref);
@@ -789,8 +797,8 @@
 	if (hpet_use_timer) {
 		hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
 		    HPET_TN_32BIT, HPET_T0_CFG);
-		hpet_writel(hpet_tick, HPET_T0_CMP);
-		hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */
+		hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
+		hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
 		cfg |= HPET_CFG_LEGACY;
 	}
 /*
@@ -825,8 +833,7 @@
 	if (hpet_period < 100000 || hpet_period > 100000000)
 		return -1;
 
-	hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
-		hpet_period;
+	hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
 
 	hpet_use_timer = (id & HPET_ID_LEGSUP);
 
@@ -890,18 +897,6 @@
 	char *timename;
 	char *gtod;
 
-#ifdef HPET_HACK_ENABLE_DANGEROUS
-        if (!vxtime.hpet_address) {
-		printk(KERN_WARNING "time.c: WARNING: Enabling HPET base "
-		       "manually!\n");
-                outl(0x800038a0, 0xcf8);
-                outl(0xff000001, 0xcfc);
-                outl(0x800038a0, 0xcf8);
-                vxtime.hpet_address = inl(0xcfc) & 0xfffffffe;
-		printk(KERN_WARNING "time.c: WARNING: Enabled HPET "
-		       "at %#lx.\n", vxtime.hpet_address);
-        }
-#endif
 	if (nohpet)
 		vxtime.hpet_address = 0;
 
@@ -912,7 +907,7 @@
 	                        -xtime.tv_sec, -xtime.tv_nsec);
 
 	if (!hpet_init())
-                vxtime_hz = (1000000000000000L + hpet_period / 2) / hpet_period;
+                vxtime_hz = (FSEC_PER_SEC + hpet_period / 2) / hpet_period;
 	else
 		vxtime.hpet_address = 0;
 
@@ -941,8 +936,8 @@
 	       vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod);
 	printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
 		cpu_khz / 1000, cpu_khz % 1000);
-	vxtime.quot = (1000000L << 32) / vxtime_hz;
-	vxtime.tsc_quot = (1000L << 32) / cpu_khz;
+	vxtime.quot = (USEC_PER_SEC << US_SCALE) / vxtime_hz;
+	vxtime.tsc_quot = (USEC_PER_MSEC << US_SCALE) / cpu_khz;
 	vxtime.last_tsc = get_cycles_sync();
 	setup_irq(0, &irq0);
 
@@ -956,10 +951,10 @@
 __cpuinit int unsynchronized_tsc(void)
 {
 #ifdef CONFIG_SMP
-	if (oem_force_hpet_timer())
+	if (apic_is_clustered_box())
 		return 1;
  	/* Intel systems are normally all synchronized. Exceptions
- 	   are handled in the OEM check above. */
+ 	   are handled in the check above. */
  	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
  		return 0;
 #endif
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index cea335e..3d11a2f 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -6,8 +6,6 @@
  *
  *  Pentium III FXSR, SSE support
  *	Gareth Hughes <gareth@valinux.com>, May 2000
- *
- *  $Id: traps.c,v 1.36 2002/03/24 11:09:10 ak Exp $
  */
 
 /*
@@ -31,6 +29,7 @@
 #include <linux/nmi.h>
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
+#include <linux/unwind.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -41,7 +40,7 @@
 #include <asm/i387.h>
 #include <asm/kdebug.h>
 #include <asm/processor.h>
-
+#include <asm/unwind.h>
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
 #include <asm/pda.h>
@@ -71,6 +70,7 @@
 asmlinkage void spurious_interrupt_bug(void);
 
 ATOMIC_NOTIFIER_HEAD(die_chain);
+EXPORT_SYMBOL(die_chain);
 
 int register_die_notifier(struct notifier_block *nb)
 {
@@ -107,7 +107,8 @@
 	preempt_enable_no_resched();
 }
 
-static int kstack_depth_to_print = 10;
+static int kstack_depth_to_print = 12;
+static int call_trace = 1;
 
 #ifdef CONFIG_KALLSYMS
 #include <linux/kallsyms.h> 
@@ -191,6 +192,25 @@
 	return NULL;
 }
 
+static int show_trace_unwind(struct unwind_frame_info *info, void *context)
+{
+	int i = 11, n = 0;
+
+	while (unwind(info) == 0 && UNW_PC(info)) {
+		++n;
+		if (i > 50) {
+			printk("\n       ");
+			i = 7;
+		} else
+			i += printk(" ");
+		i += printk_address(UNW_PC(info));
+		if (arch_unw_user_mode(info))
+			break;
+	}
+	printk("\n");
+	return n;
+}
+
 /*
  * x86-64 can have upto three kernel stacks: 
  * process stack
@@ -198,15 +218,39 @@
  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
  */
 
-void show_trace(unsigned long *stack)
+void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack)
 {
 	const unsigned cpu = safe_smp_processor_id();
 	unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
-	int i;
+	int i = 11;
 	unsigned used = 0;
 
 	printk("\nCall Trace:");
 
+	if (!tsk)
+		tsk = current;
+
+	if (call_trace >= 0) {
+		int unw_ret = 0;
+		struct unwind_frame_info info;
+
+		if (regs) {
+			if (unwind_init_frame_info(&info, tsk, regs) == 0)
+				unw_ret = show_trace_unwind(&info, NULL);
+		} else if (tsk == current)
+			unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
+		else {
+			if (unwind_init_blocked(&info, tsk) == 0)
+				unw_ret = show_trace_unwind(&info, NULL);
+		}
+		if (unw_ret > 0) {
+			if (call_trace > 0)
+				return;
+			printk("Legacy call trace:");
+			i = 18;
+		}
+	}
+
 #define HANDLE_STACK(cond) \
 	do while (cond) { \
 		unsigned long addr = *stack++; \
@@ -229,7 +273,7 @@
 		} \
 	} while (0)
 
-	for(i = 11; ; ) {
+	for(; ; ) {
 		const char *id;
 		unsigned long *estack_end;
 		estack_end = in_exception_stack(cpu, (unsigned long)stack,
@@ -264,7 +308,7 @@
 	printk("\n");
 }
 
-void show_stack(struct task_struct *tsk, unsigned long * rsp)
+static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long * rsp)
 {
 	unsigned long *stack;
 	int i;
@@ -298,7 +342,12 @@
 		printk("%016lx ", *stack++);
 		touch_nmi_watchdog();
 	}
-	show_trace((unsigned long *)rsp);
+	show_trace(tsk, regs, rsp);
+}
+
+void show_stack(struct task_struct *tsk, unsigned long * rsp)
+{
+	_show_stack(tsk, NULL, rsp);
 }
 
 /*
@@ -307,7 +356,7 @@
 void dump_stack(void)
 {
 	unsigned long dummy;
-	show_trace(&dummy);
+	show_trace(NULL, NULL, &dummy);
 }
 
 EXPORT_SYMBOL(dump_stack);
@@ -334,7 +383,7 @@
 	if (in_kernel) {
 
 		printk("Stack: ");
-		show_stack(NULL, (unsigned long*)rsp);
+		_show_stack(NULL, regs, (unsigned long*)rsp);
 
 		printk("\nCode: ");
 		if (regs->rip < PAGE_OFFSET)
@@ -383,6 +432,7 @@
 { 
 	BUG(); 
 } 
+EXPORT_SYMBOL(out_of_line_bug);
 #endif
 
 static DEFINE_SPINLOCK(die_lock);
@@ -1012,3 +1062,14 @@
 }
 __setup("kstack=", kstack_setup);
 
+static int __init call_trace_setup(char *s)
+{
+	if (strcmp(s, "old") == 0)
+		call_trace = -1;
+	else if (strcmp(s, "both") == 0)
+		call_trace = 0;
+	else if (strcmp(s, "new") == 0)
+		call_trace = 1;
+	return 1;
+}
+__setup("call_trace=", call_trace_setup);
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index b81f473..1c6a5f3 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -45,6 +45,15 @@
 
   RODATA
 
+#ifdef CONFIG_STACK_UNWIND
+  . = ALIGN(8);
+  .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) {
+	__start_unwind = .;
+  	*(.eh_frame)
+	__end_unwind = .;
+  }
+#endif
+
 				/* Data */
   .data : AT(ADDR(.data) - LOAD_OFFSET) {
 	*(.data)
@@ -131,6 +140,26 @@
 	*(.data.page_aligned)
   }
 
+  /* might get freed after init */
+  . = ALIGN(4096);
+  __smp_alt_begin = .;
+  __smp_alt_instructions = .;
+  .smp_altinstructions : AT(ADDR(.smp_altinstructions) - LOAD_OFFSET) {
+	*(.smp_altinstructions)
+  }
+  __smp_alt_instructions_end = .;
+  . = ALIGN(8);
+  __smp_locks = .;
+  .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) {
+	*(.smp_locks)
+  }
+  __smp_locks_end = .;
+  .smp_altinstr_replacement : AT(ADDR(.smp_altinstr_replacement) - LOAD_OFFSET) {
+	*(.smp_altinstr_replacement)
+  }
+  . = ALIGN(4096);
+  __smp_alt_end = .;
+
   . = ALIGN(4096);		/* Init code and data */
   __init_begin = .;
   .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index 9468fb2..f603037 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -107,7 +107,7 @@
 
 int __vsyscall(0) vgettimeofday(struct timeval * tv, struct timezone * tz)
 {
-	if (unlikely(!__sysctl_vsyscall))
+	if (!__sysctl_vsyscall)
 		return gettimeofday(tv,tz);
 	if (tv)
 		do_vgettimeofday(tv);
@@ -120,7 +120,7 @@
  * unlikely */
 time_t __vsyscall(1) vtime(time_t *t)
 {
-	if (unlikely(!__sysctl_vsyscall))
+	if (!__sysctl_vsyscall)
 		return time_syscall(t);
 	else if (t)
 		*t = __xtime.tv_sec;		
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 1def21c..370952c 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -1,66 +1,21 @@
+/* Exports for assembly files.
+   All C exports should go in the respective C files. */
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/smp.h>
-#include <linux/user.h>
-#include <linux/sched.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-#include <linux/smp_lock.h>
-#include <linux/pm.h>
-#include <linux/pci.h>
-#include <linux/apm_bios.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/syscalls.h>
-#include <linux/tty.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
-#include <asm/i387.h>
 #include <asm/uaccess.h>
-#include <asm/checksum.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/irq.h>
-#include <asm/mmx.h>
-#include <asm/desc.h>
 #include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/nmi.h>
-#include <asm/kdebug.h>
-#include <asm/unistd.h>
-#include <asm/tlbflush.h>
-#include <asm/kdebug.h>
 
-extern spinlock_t rtc_lock;
-
-#ifdef CONFIG_SMP
-extern void __write_lock_failed(rwlock_t *rw);
-extern void __read_lock_failed(rwlock_t *rw);
-#endif
-
-/* platform dependent support */
-EXPORT_SYMBOL(boot_cpu_data);
-//EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(ioremap_nocache);
-EXPORT_SYMBOL(iounmap);
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(pm_idle);
-EXPORT_SYMBOL(pm_power_off);
 
 EXPORT_SYMBOL(__down_failed);
 EXPORT_SYMBOL(__down_failed_interruptible);
 EXPORT_SYMBOL(__down_failed_trylock);
 EXPORT_SYMBOL(__up_wakeup);
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
-EXPORT_SYMBOL(ip_compute_csum);
-/* Delay loops */
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(__const_udelay);
 
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
@@ -71,42 +26,20 @@
 EXPORT_SYMBOL(__put_user_4);
 EXPORT_SYMBOL(__put_user_8);
 
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(clear_user);
-EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(copy_user_generic);
 EXPORT_SYMBOL(copy_from_user);
 EXPORT_SYMBOL(copy_to_user);
-EXPORT_SYMBOL(copy_in_user);
-EXPORT_SYMBOL(strnlen_user);
-
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_mem_start);
-#endif
 
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
 
-EXPORT_SYMBOL(_cpu_pda);
 #ifdef CONFIG_SMP
-EXPORT_SYMBOL(cpu_data);
+extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
+extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
 EXPORT_SYMBOL(__write_lock_failed);
 EXPORT_SYMBOL(__read_lock_failed);
-
-EXPORT_SYMBOL(smp_call_function);
-EXPORT_SYMBOL(cpu_callout_map);
 #endif
 
-#ifdef CONFIG_VT
-EXPORT_SYMBOL(screen_info);
-#endif
-
-EXPORT_SYMBOL(rtc_lock);
-
-EXPORT_SYMBOL_GPL(set_nmi_callback);
-EXPORT_SYMBOL_GPL(unset_nmi_callback);
-
 /* Export string functions. We normally rely on gcc builtin for most of these,
    but gcc sometimes decides not to inline them. */    
 #undef memcpy
@@ -114,51 +47,14 @@
 #undef memmove
 
 extern void * memset(void *,int,__kernel_size_t);
-extern size_t strlen(const char *);
-extern void * memmove(void * dest,const void *src,size_t count);
 extern void * memcpy(void *,const void *,__kernel_size_t);
 extern void * __memcpy(void *,const void *,__kernel_size_t);
 
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__memcpy);
 
-#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
-/* prototypes are wrong, these are assembly with custom calling functions */
-extern void rwsem_down_read_failed_thunk(void);
-extern void rwsem_wake_thunk(void);
-extern void rwsem_downgrade_thunk(void);
-extern void rwsem_down_write_failed_thunk(void);
-EXPORT_SYMBOL(rwsem_down_read_failed_thunk);
-EXPORT_SYMBOL(rwsem_wake_thunk);
-EXPORT_SYMBOL(rwsem_downgrade_thunk);
-EXPORT_SYMBOL(rwsem_down_write_failed_thunk);
-#endif
-
 EXPORT_SYMBOL(empty_zero_page);
-
-EXPORT_SYMBOL(die_chain);
-
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(cpu_sibling_map);
-EXPORT_SYMBOL(smp_num_siblings);
-#endif
-
-#ifdef CONFIG_BUG
-EXPORT_SYMBOL(out_of_line_bug);
-#endif
-
 EXPORT_SYMBOL(init_level4_pgt);
-
-extern unsigned long __supported_pte_mask;
-EXPORT_SYMBOL(__supported_pte_mask);
-
-#ifdef CONFIG_SMP
-EXPORT_SYMBOL(flush_tlb_page);
-#endif
-
-EXPORT_SYMBOL(cpu_khz);
-
 EXPORT_SYMBOL(load_gs_index);
 
diff --git a/arch/x86_64/lib/csum-partial.c b/arch/x86_64/lib/csum-partial.c
index 5384e22..c493735 100644
--- a/arch/x86_64/lib/csum-partial.c
+++ b/arch/x86_64/lib/csum-partial.c
@@ -147,4 +147,5 @@
 {
 	return csum_fold(csum_partial(buff,len,0));
 }
+EXPORT_SYMBOL(ip_compute_csum);
 
diff --git a/arch/x86_64/lib/csum-wrappers.c b/arch/x86_64/lib/csum-wrappers.c
index 94323f2..b1320ec 100644
--- a/arch/x86_64/lib/csum-wrappers.c
+++ b/arch/x86_64/lib/csum-wrappers.c
@@ -109,6 +109,7 @@
 { 
 	return csum_partial_copy_generic(src,dst,len,sum,NULL,NULL);
 } 
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
 
 unsigned short csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
 			       __u32 len, unsigned short proto, unsigned int sum) 
diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c
index 03c460c..b6cd3cc 100644
--- a/arch/x86_64/lib/delay.c
+++ b/arch/x86_64/lib/delay.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <asm/delay.h>
@@ -36,18 +37,22 @@
 	}
 	while((now-bclock) < loops);
 }
+EXPORT_SYMBOL(__delay);
 
 inline void __const_udelay(unsigned long xloops)
 {
 	__delay((xloops * HZ * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32);
 }
+EXPORT_SYMBOL(__const_udelay);
 
 void __udelay(unsigned long usecs)
 {
 	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
 }
+EXPORT_SYMBOL(__udelay);
 
 void __ndelay(unsigned long nsecs)
 {
 	__const_udelay(nsecs * 0x00005);  /* 2**32 / 1000000000 (rounded up) */
 }
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/x86_64/lib/memmove.c b/arch/x86_64/lib/memmove.c
index e93d525..751ebae 100644
--- a/arch/x86_64/lib/memmove.c
+++ b/arch/x86_64/lib/memmove.c
@@ -3,12 +3,13 @@
  */
 #define _STRING_C
 #include <linux/string.h>
+#include <linux/module.h>
 
 #undef memmove
 void *memmove(void * dest,const void *src,size_t count)
 {
 	if (dest < src) { 
-		__inline_memcpy(dest,src,count);
+		return memcpy(dest,src,count);
 	} else {
 		char *p = (char *) dest + count;
 		char *s = (char *) src + count;
@@ -17,3 +18,4 @@
 	}
 	return dest;
 } 
+EXPORT_SYMBOL(memmove);
diff --git a/arch/x86_64/lib/usercopy.c b/arch/x86_64/lib/usercopy.c
index 9bc2c29..893d43f 100644
--- a/arch/x86_64/lib/usercopy.c
+++ b/arch/x86_64/lib/usercopy.c
@@ -5,6 +5,7 @@
  * Copyright 1997 Linus Torvalds
  * Copyright 2002 Andi Kleen <ak@suse.de>
  */
+#include <linux/module.h>
 #include <asm/uaccess.h>
 
 /*
@@ -47,15 +48,17 @@
 	__do_strncpy_from_user(dst, src, count, res);
 	return res;
 }
+EXPORT_SYMBOL(__strncpy_from_user);
 
 long
 strncpy_from_user(char *dst, const char __user *src, long count)
 {
 	long res = -EFAULT;
 	if (access_ok(VERIFY_READ, src, 1))
-		__do_strncpy_from_user(dst, src, count, res);
+		return __strncpy_from_user(dst, src, count);
 	return res;
 }
+EXPORT_SYMBOL(strncpy_from_user);
 
 /*
  * Zero Userspace
@@ -94,7 +97,7 @@
 		  [zero] "r" (0UL), [eight] "r" (8UL));
 	return size;
 }
-
+EXPORT_SYMBOL(__clear_user);
 
 unsigned long clear_user(void __user *to, unsigned long n)
 {
@@ -102,6 +105,7 @@
 		return __clear_user(to, n);
 	return n;
 }
+EXPORT_SYMBOL(clear_user);
 
 /*
  * Return the size of a string (including the ending 0)
@@ -125,6 +129,7 @@
 		s++;
 	}
 }
+EXPORT_SYMBOL(__strnlen_user);
 
 long strnlen_user(const char __user *s, long n)
 {
@@ -132,6 +137,7 @@
 		return 0;
 	return __strnlen_user(s, n);
 }
+EXPORT_SYMBOL(strnlen_user);
 
 long strlen_user(const char __user *s)
 {
@@ -147,6 +153,7 @@
 		s++;
 	}
 }
+EXPORT_SYMBOL(strlen_user);
 
 unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
 {
@@ -155,3 +162,5 @@
 	} 
 	return len;		
 }
+EXPORT_SYMBOL(copy_in_user);
+
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 55250593..08dc696 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -41,6 +41,41 @@
 #define PF_RSVD	(1<<3)
 #define PF_INSTR	(1<<4)
 
+#ifdef CONFIG_KPROBES
+ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
+/* Hook to register for page fault notifications */
+int register_page_fault_notifier(struct notifier_block *nb)
+{
+	vmalloc_sync_all();
+	return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
+}
+
+int unregister_page_fault_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
+}
+
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	struct die_args args = {
+		.regs = regs,
+		.str = str,
+		.err = err,
+		.trapnr = trap,
+		.signr = sig
+	};
+	return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
+}
+#else
+static inline int notify_page_fault(enum die_val val, const char *str,
+			struct pt_regs *regs, long err, int trap, int sig)
+{
+	return NOTIFY_DONE;
+}
+#endif
+
 void bust_spinlocks(int yes)
 {
 	int loglevel_save = console_loglevel;
@@ -160,7 +195,7 @@
 	printk("PGD %lx ", pgd_val(*pgd));
 	if (!pgd_present(*pgd)) goto ret; 
 
-	pud = __pud_offset_k((pud_t *)pgd_page(*pgd), address);
+	pud = pud_offset(pgd, address);
 	if (bad_address(pud)) goto bad;
 	printk("PUD %lx ", pud_val(*pud));
 	if (!pud_present(*pud))	goto ret;
@@ -348,7 +383,7 @@
 			if (vmalloc_fault(address) >= 0)
 				return;
 		}
-		if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+		if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
 						SIGSEGV) == NOTIFY_STOP)
 			return;
 		/*
@@ -358,7 +393,7 @@
 		goto bad_area_nosemaphore;
 	}
 
-	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
+	if (notify_page_fault(DIE_PAGE_FAULT, "page fault", regs, error_code, 14,
 					SIGSEGV) == NOTIFY_STOP)
 		return;
 
@@ -410,8 +445,10 @@
 	if (!(vma->vm_flags & VM_GROWSDOWN))
 		goto bad_area;
 	if (error_code & 4) {
-		// XXX: align red zone size with ABI 
-		if (address + 128 < regs->rsp)
+		/* Allow userspace just enough access below the stack pointer
+		 * to let the 'enter' instruction work.
+		 */
+		if (address + 65536 + 32 * sizeof(unsigned long) < regs->rsp)
 			goto bad_area;
 	}
 	if (expand_stack(vma, address))
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 4ba34e9..95bd232 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -23,6 +23,7 @@
 #include <linux/bootmem.h>
 #include <linux/proc_fs.h>
 #include <linux/pci.h>
+#include <linux/poison.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/memory_hotplug.h>
@@ -41,8 +42,6 @@
 #include <asm/proto.h>
 #include <asm/smp.h>
 #include <asm/sections.h>
-#include <asm/dma-mapping.h>
-#include <asm/swiotlb.h>
 
 #ifndef Dprintk
 #define Dprintk(x...)
@@ -90,8 +89,6 @@
 	printk(KERN_INFO "%lu pages swap cached\n",cached);
 }
 
-/* References to section boundaries */
-
 int after_bootmem;
 
 static __init void *spp_getpage(void)
@@ -261,9 +258,10 @@
 	for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) {
 		unsigned long entry;
 
-		if (address > end) {
-			for (; i < PTRS_PER_PMD; i++, pmd++)
-				set_pmd(pmd, __pmd(0));
+		if (address >= end) {
+			if (!after_bootmem)
+				for (; i < PTRS_PER_PMD; i++, pmd++)
+					set_pmd(pmd, __pmd(0));
 			break;
 		}
 		entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address;
@@ -341,7 +339,8 @@
 	table_end = table_start;
 
 	early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n",
-		end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT);
+		end, table_start << PAGE_SHIFT,
+		(table_start << PAGE_SHIFT) + tables);
 }
 
 /* Setup the direct mapping of the physical memory at PAGE_OFFSET.
@@ -372,7 +371,7 @@
 		pud_t *pud;
 
 		if (after_bootmem)
-			pud = pud_offset_k(pgd, start & PGDIR_MASK);
+			pud = pud_offset(pgd, start & PGDIR_MASK);
 		else
 			pud = alloc_low_page(&map, &pud_phys);
 
@@ -508,8 +507,6 @@
 /*
  * Memory hotplug specific functions
  */
-#if defined(CONFIG_ACPI_HOTPLUG_MEMORY) || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
-
 void online_page(struct page *page)
 {
 	ClearPageReserved(page);
@@ -519,7 +516,52 @@
 	num_physpages++;
 }
 
-#ifndef CONFIG_MEMORY_HOTPLUG
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ * XXX: memory_add_physaddr_to_nid() is to find node id from physical address
+ *	via probe interface of sysfs. If acpi notifies hot-add event, then it
+ *	can tell node id by searching dsdt. But, probe interface doesn't have
+ *	node id. So, return 0 as node id at this time.
+ */
+#ifdef CONFIG_NUMA
+int memory_add_physaddr_to_nid(u64 start)
+{
+	return 0;
+}
+#endif
+
+/*
+ * Memory is added always to NORMAL zone. This means you will never get
+ * additional DMA/DMA32 memory.
+ */
+int arch_add_memory(int nid, u64 start, u64 size)
+{
+	struct pglist_data *pgdat = NODE_DATA(nid);
+	struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+	unsigned long nr_pages = size >> PAGE_SHIFT;
+	int ret;
+
+	ret = __add_pages(zone, start_pfn, nr_pages);
+	if (ret)
+		goto error;
+
+	init_memory_mapping(start, (start + size -1));
+
+	return ret;
+error:
+	printk("%s: Problem encountered in __add_pages!\n", __func__);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(arch_add_memory);
+
+int remove_memory(u64 start, u64 size)
+{
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(remove_memory);
+
+#else /* CONFIG_MEMORY_HOTPLUG */
 /*
  * Memory Hotadd without sparsemem. The mem_maps have been allocated in advance,
  * just online the pages.
@@ -545,40 +587,7 @@
 	}
 	return err;
 }
-#endif
-
-/*
- * Memory is added always to NORMAL zone. This means you will never get
- * additional DMA/DMA32 memory.
- */
-int add_memory(u64 start, u64 size)
-{
-	struct pglist_data *pgdat = NODE_DATA(0);
-	struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2;
-	unsigned long start_pfn = start >> PAGE_SHIFT;
-	unsigned long nr_pages = size >> PAGE_SHIFT;
-	int ret;
-
-	ret = __add_pages(zone, start_pfn, nr_pages);
-	if (ret)
-		goto error;
-
-	init_memory_mapping(start, (start + size -1));
-
-	return ret;
-error:
-	printk("%s: Problem encountered in __add_pages!\n", __func__);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(add_memory);
-
-int remove_memory(u64 start, u64 size)
-{
-	return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(remove_memory);
-
-#endif
+#endif /* CONFIG_MEMORY_HOTPLUG */
 
 static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules,
 			 kcore_vsyscall;
@@ -587,10 +596,7 @@
 {
 	long codesize, reservedpages, datasize, initsize;
 
-#ifdef CONFIG_SWIOTLB
-	pci_swiotlb_init();
-#endif
-	no_iommu_init();
+	pci_iommu_alloc();
 
 	/* How many end-of-memory variables you have, grandma! */
 	max_low_pfn = end_pfn;
@@ -644,20 +650,31 @@
 #endif
 }
 
-void free_initmem(void)
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
 {
 	unsigned long addr;
 
-	addr = (unsigned long)(&__init_begin);
-	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+	if (begin >= end)
+		return;
+
+	printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+	for (addr = begin; addr < end; addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
 		init_page_count(virt_to_page(addr));
-		memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); 
+		memset((void *)(addr & ~(PAGE_SIZE-1)),
+			POISON_FREE_INITMEM, PAGE_SIZE);
 		free_page(addr);
 		totalram_pages++;
 	}
-	memset(__initdata_begin, 0xba, __initdata_end - __initdata_begin);
-	printk ("Freeing unused kernel memory: %luk freed\n", (__init_end - __init_begin) >> 10);
+}
+
+void free_initmem(void)
+{
+	memset(__initdata_begin, POISON_FREE_INITDATA,
+		__initdata_end - __initdata_begin);
+	free_init_pages("unused kernel memory",
+			(unsigned long)(&__init_begin),
+			(unsigned long)(&__init_end));
 }
 
 #ifdef CONFIG_DEBUG_RODATA
@@ -686,15 +703,7 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	if (start >= end)
-		return;
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-	}
+	free_init_pages("initrd memory", start, end);
 }
 #endif
 
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index ae20706..45d7d82 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -11,6 +11,7 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <asm/io.h>
 #include <asm/pgalloc.h>
 #include <asm/fixmap.h>
@@ -219,6 +220,7 @@
 	}
 	return (__force void __iomem *) (offset + (char *)addr);
 }
+EXPORT_SYMBOL(__ioremap);
 
 /**
  * ioremap_nocache     -   map bus memory into CPU space
@@ -246,6 +248,7 @@
 {
 	return __ioremap(phys_addr, size, _PAGE_PCD);
 }
+EXPORT_SYMBOL(ioremap_nocache);
 
 /**
  * iounmap - Free a IO remapping
@@ -291,3 +294,5 @@
 	BUG_ON(p != o || o == NULL);
 	kfree(p); 
 }
+EXPORT_SYMBOL(iounmap);
+
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 474df22..502fce6 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -30,7 +30,6 @@
 static struct acpi_table_slit *acpi_slit;
 
 static nodemask_t nodes_parsed __initdata;
-static nodemask_t nodes_found __initdata;
 static struct bootnode nodes[MAX_NUMNODES] __initdata;
 static struct bootnode nodes_add[MAX_NUMNODES] __initdata;
 static int found_add_area __initdata;
@@ -38,33 +37,14 @@
 #ifndef RESERVE_HOTADD
 #define hotadd_percent 0	/* Ignore all settings */
 #endif
-static u8 pxm2node[256] = { [0 ... 255] = 0xff };
 
 /* Too small nodes confuse the VM badly. Usually they result
    from BIOS bugs. */
 #define NODE_MIN_SIZE (4*1024*1024)
 
-static int node_to_pxm(int n);
-
-int pxm_to_node(int pxm)
-{
-	if ((unsigned)pxm >= 256)
-		return -1;
-	/* Extend 0xff to (int)-1 */
-	return (signed char)pxm2node[pxm];
-}
-
 static __init int setup_node(int pxm)
 {
-	unsigned node = pxm2node[pxm];
-	if (node == 0xff) {
-		if (nodes_weight(nodes_found) >= MAX_NUMNODES)
-			return -1;
-		node = first_unset_node(nodes_found); 
-		node_set(node, nodes_found);
-		pxm2node[pxm] = node;
-	}
-	return pxm2node[pxm];
+	return acpi_map_pxm_to_node(pxm);
 }
 
 static __init int conflicting_nodes(unsigned long start, unsigned long end)
@@ -440,17 +420,6 @@
 	return 0;
 }
 
-static int node_to_pxm(int n)
-{
-       int i;
-       if (pxm2node[n] == n)
-               return n;
-       for (i = 0; i < 256; i++)
-               if (pxm2node[i] == n)
-                       return i;
-       return 0;
-}
-
 void __init srat_reserve_add_area(int nodeid)
 {
 	if (found_add_area && nodes_add[nodeid].end) {
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index 3acf60d..b50a7c7 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -2,6 +2,7 @@
 #include <linux/pci.h>
 #include <asm/mpspec.h>
 #include <linux/cpumask.h>
+#include <asm/k8.h>
 
 /*
  * This discovers the pcibus <-> node mapping on AMD K8.
@@ -18,7 +19,6 @@
 #define NR_LDT_BUS_NUMBER_REGISTERS 3
 #define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF)
 #define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF)
-#define PCI_DEVICE_ID_K8HTCONFIG 0x1100
 
 /**
  * fill_mp_bus_to_cpumask()
@@ -28,8 +28,7 @@
 __init static int
 fill_mp_bus_to_cpumask(void)
 {
-	struct pci_dev *nb_dev = NULL;
-	int i, j;
+	int i, j, k;
 	u32 ldtbus, nid;
 	static int lbnr[3] = {
 		LDT_BUS_NUMBER_REGISTER_0,
@@ -37,8 +36,9 @@
 		LDT_BUS_NUMBER_REGISTER_2
 	};
 
-	while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-			PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) {
+	cache_k8_northbridges();
+	for (k = 0; k < num_k8_northbridges; k++) {
+		struct pci_dev *nb_dev = k8_northbridges[k];
 		pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid);
 
 		for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) {
diff --git a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
index a2060e4..3c55c76 100644
--- a/arch/x86_64/pci/mmconfig.c
+++ b/arch/x86_64/pci/mmconfig.c
@@ -13,7 +13,10 @@
 
 #include "pci.h"
 
-#define MMCONFIG_APER_SIZE (256*1024*1024)
+/* aperture is up to 256MB but BIOS may reserve less */
+#define MMCONFIG_APER_MIN	(2 * 1024*1024)
+#define MMCONFIG_APER_MAX	(256 * 1024*1024)
+
 /* Verify the first 16 busses. We assume that systems with more busses
    get MCFG right. */
 #define MAX_CHECK_BUS 16
@@ -175,9 +178,10 @@
 		return;
 
 	if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
-			pci_mmcfg_config[0].base_address + MMCONFIG_APER_SIZE,
+			pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
 			E820_RESERVED)) {
-		printk(KERN_ERR "PCI: BIOS Bug: MCFG area is not E820-reserved\n");
+		printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
+				pci_mmcfg_config[0].base_address);
 		printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
 		return;
 	}
@@ -190,7 +194,8 @@
 	}
 	for (i = 0; i < pci_mmcfg_config_num; ++i) {
 		pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
-		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
+		pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address,
+							 MMCONFIG_APER_MAX);
 		if (!pci_mmcfg_virt[i].virt) {
 			printk("PCI: Cannot map mmconfig aperture for segment %d\n",
 			       pci_mmcfg_config[i].pci_segment_group_number);
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index dbeb350..848f173 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -34,10 +34,6 @@
 	bool
 	default y
 
-config RWSEM_GENERIC_SPINLOCK
-       bool
-       default y
-
 source "init/Kconfig"
 
 menu "Processor type and features"
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
index 98fac84..3a3a4c6 100644
--- a/arch/xtensa/Makefile
+++ b/arch/xtensa/Makefile
@@ -71,7 +71,7 @@
 # Update machine cpu and platform symlinks if something which affects
 # them changed.
 
-$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/MARKER
+$(archinc)/.platform: $(wildcard include/config/arch/*.h) include/config/auto.conf
 	@echo '  SYMLINK $(archinc)/xtensa/config -> $(archinc)/xtensa/config-$(CPU)'
 	$(Q)mkdir -p $(archinc)
 	$(Q)mkdir -p $(archinc)/xtensa
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile
index 9e73bb8..d3d2aa2 100644
--- a/arch/xtensa/boot/lib/Makefile
+++ b/arch/xtensa/boot/lib/Makefile
@@ -2,7 +2,7 @@
 # Makefile for some libs needed by zImage.
 #
 
-zlib	:= infblock.c infcodes.c inffast.c inflate.c inftrees.c infutil.c
+zlib	:= inffast.c inflate.c inftrees.c
 
 lib-y	+= $(zlib:.c=.o) zmem.o
 
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 5c018c5..89e409e 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1102,7 +1102,7 @@
 	s32i	a7, a2, PT_AREG7
 
 	movi	a7, 4			# sizeof(unsigned int)
-	verify_area a3, a7, a0, a2, .Leac
+	access_ok a0, a3, a7, a2, .Leac
 
 	_beqi	a6, SYSXTENSA_ATOMIC_SET, .Lset
 	_beqi	a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index de19501..c6f471b 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -350,17 +350,6 @@
 }
 
 /*
- * Set vm_flags of VMA, as appropriate for this architecture, for a pci device
- * mapping.
- */
-static __inline__ void
-__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
-		     enum pci_mmap_state mmap_state)
-{
-	vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
-}
-
-/*
  * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
  * device mapping.
  */
@@ -399,7 +388,6 @@
 	if (ret < 0)
 		return ret;
 
-	__pci_mmap_set_flags(dev, vma, mmap_state);
 	__pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
 
 	ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index e252b61..c494f08 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -104,7 +104,7 @@
 
 	if (act) {
 		old_sigset_t mask;
-		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
 		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
 			return -EFAULT;
@@ -116,7 +116,7 @@
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
-		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
 			return -EFAULT;
@@ -236,7 +236,7 @@
 	err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4);
 	err |= __get_user(buf, &sc->sc_cpstate);
 	if (buf) {
-		if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+		if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
 			goto badframe;
 		err |= restore_cpextra(buf);
 	}
@@ -357,7 +357,7 @@
 	if (regs->depc > 64)
 		panic ("Double exception sys_sigreturn\n");
 
-	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 
 	if (__get_user(set.sig[0], &frame->sc.oldmask)
@@ -394,7 +394,7 @@
 		return 0;
 	}
 
-	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 
 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -433,7 +433,7 @@
 static inline void *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
 		sp = current->sas_ss_sp + current->sas_ss_size;
 
 	return (void *)((sp - frame_size) & -16ul);
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
index 937d81f6..fe14909 100644
--- a/arch/xtensa/kernel/time.c
+++ b/arch/xtensa/kernel/time.c
@@ -29,7 +29,7 @@
 
 extern volatile unsigned long wall_jiffies;
 
-spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
 
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 225d64d..27e4090 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -461,7 +461,7 @@
 	}
 }
 
-spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index f3b7753..48d090e 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -40,7 +40,7 @@
 
 choice
 	prompt "Default I/O scheduler"
-	default DEFAULT_AS
+	default DEFAULT_CFQ
 	help
 	  Select the I/O scheduler which will be used by default for all
 	  block devices.
diff --git a/block/as-iosched.c b/block/as-iosched.c
index a7caf35..3af31ed 100644
--- a/block/as-iosched.c
+++ b/block/as-iosched.c
@@ -96,7 +96,7 @@
 
 	struct as_rq *next_arq[2];	/* next in sort order */
 	sector_t last_sector[2];	/* last REQ_SYNC & REQ_ASYNC sectors */
-	struct list_head *hash;		/* request hash */
+	struct hlist_head *hash;	/* request hash */
 
 	unsigned long exit_prob;	/* probability a task will exit while
 					   being waited on */
@@ -165,8 +165,7 @@
 	/*
 	 * request hash, key is the ending offset (for back merge lookup)
 	 */
-	struct list_head hash;
-	unsigned int on_hash;
+	struct hlist_node hash;
 
 	/*
 	 * expire fifo
@@ -282,17 +281,15 @@
 #define AS_HASH_FN(sec)		(hash_long(AS_HASH_BLOCK((sec)), as_hash_shift))
 #define AS_HASH_ENTRIES		(1 << as_hash_shift)
 #define rq_hash_key(rq)		((rq)->sector + (rq)->nr_sectors)
-#define list_entry_hash(ptr)	list_entry((ptr), struct as_rq, hash)
 
 static inline void __as_del_arq_hash(struct as_rq *arq)
 {
-	arq->on_hash = 0;
-	list_del_init(&arq->hash);
+	hlist_del_init(&arq->hash);
 }
 
 static inline void as_del_arq_hash(struct as_rq *arq)
 {
-	if (arq->on_hash)
+	if (!hlist_unhashed(&arq->hash))
 		__as_del_arq_hash(arq);
 }
 
@@ -300,10 +297,9 @@
 {
 	struct request *rq = arq->request;
 
-	BUG_ON(arq->on_hash);
+	BUG_ON(!hlist_unhashed(&arq->hash));
 
-	arq->on_hash = 1;
-	list_add(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]);
+	hlist_add_head(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]);
 }
 
 /*
@@ -312,31 +308,29 @@
 static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq)
 {
 	struct request *rq = arq->request;
-	struct list_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))];
+	struct hlist_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))];
 
-	if (!arq->on_hash) {
+	if (hlist_unhashed(&arq->hash)) {
 		WARN_ON(1);
 		return;
 	}
 
-	if (arq->hash.prev != head) {
-		list_del(&arq->hash);
-		list_add(&arq->hash, head);
+	if (&arq->hash != head->first) {
+		hlist_del(&arq->hash);
+		hlist_add_head(&arq->hash, head);
 	}
 }
 
 static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
 {
-	struct list_head *hash_list = &ad->hash[AS_HASH_FN(offset)];
-	struct list_head *entry, *next = hash_list->next;
+	struct hlist_head *hash_list = &ad->hash[AS_HASH_FN(offset)];
+	struct hlist_node *entry, *next;
+	struct as_rq *arq;
 
-	while ((entry = next) != hash_list) {
-		struct as_rq *arq = list_entry_hash(entry);
+	hlist_for_each_entry_safe(arq, entry, next, hash_list, hash) {
 		struct request *__rq = arq->request;
 
-		next = entry->next;
-
-		BUG_ON(!arq->on_hash);
+		BUG_ON(hlist_unhashed(&arq->hash));
 
 		if (!rq_mergeable(__rq)) {
 			as_del_arq_hash(arq);
@@ -353,10 +347,6 @@
 /*
  * rb tree support functions
  */
-#define RB_NONE		(2)
-#define RB_EMPTY(root)	((root)->rb_node == NULL)
-#define ON_RB(node)	((node)->rb_color != RB_NONE)
-#define RB_CLEAR(node)	((node)->rb_color = RB_NONE)
 #define rb_entry_arq(node)	rb_entry((node), struct as_rq, rb_node)
 #define ARQ_RB_ROOT(ad, arq)	(&(ad)->sort_list[(arq)->is_sync])
 #define rq_rb_key(rq)		(rq)->sector
@@ -425,13 +415,13 @@
 
 static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq)
 {
-	if (!ON_RB(&arq->rb_node)) {
+	if (!RB_EMPTY_NODE(&arq->rb_node)) {
 		WARN_ON(1);
 		return;
 	}
 
 	rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq));
-	RB_CLEAR(&arq->rb_node);
+	RB_CLEAR_NODE(&arq->rb_node);
 }
 
 static struct request *
@@ -552,7 +542,7 @@
 	struct rb_node *rbprev = rb_prev(&last->rb_node);
 	struct as_rq *arq_next, *arq_prev;
 
-	BUG_ON(!ON_RB(&last->rb_node));
+	BUG_ON(!RB_EMPTY_NODE(&last->rb_node));
 
 	if (rbprev)
 		arq_prev = rb_entry_arq(rbprev);
@@ -902,7 +892,7 @@
 }
 
 /*
- * as_can_anticipate indicates weather we should either run arq
+ * as_can_anticipate indicates whether we should either run arq
  * or keep anticipating a better request.
  */
 static int as_can_anticipate(struct as_data *ad, struct as_rq *arq)
@@ -1129,7 +1119,7 @@
 	struct request *rq = arq->request;
 	const int data_dir = arq->is_sync;
 
-	BUG_ON(!ON_RB(&arq->rb_node));
+	BUG_ON(!RB_EMPTY_NODE(&arq->rb_node));
 
 	as_antic_stop(ad);
 	ad->antic_status = ANTIC_OFF;
@@ -1254,7 +1244,7 @@
 	 */
 
 	if (reads) {
-		BUG_ON(RB_EMPTY(&ad->sort_list[REQ_SYNC]));
+		BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_SYNC]));
 
 		if (writes && ad->batch_data_dir == REQ_SYNC)
 			/*
@@ -1278,7 +1268,7 @@
 
 	if (writes) {
 dispatch_writes:
-		BUG_ON(RB_EMPTY(&ad->sort_list[REQ_ASYNC]));
+		BUG_ON(RB_EMPTY_ROOT(&ad->sort_list[REQ_ASYNC]));
 
 		if (ad->batch_data_dir == REQ_SYNC) {
 			ad->changed_batch = 1;
@@ -1346,7 +1336,7 @@
 	arq->state = AS_RQ_NEW;
 
 	if (rq_data_dir(arq->request) == READ
-			|| current->flags&PF_SYNCWRITE)
+			|| (arq->request->flags & REQ_RW_SYNC))
 		arq->is_sync = 1;
 	else
 		arq->is_sync = 0;
@@ -1598,12 +1588,11 @@
 
 	if (arq) {
 		memset(arq, 0, sizeof(*arq));
-		RB_CLEAR(&arq->rb_node);
+		RB_CLEAR_NODE(&arq->rb_node);
 		arq->request = rq;
 		arq->state = AS_RQ_PRESCHED;
 		arq->io_context = NULL;
-		INIT_LIST_HEAD(&arq->hash);
-		arq->on_hash = 0;
+		INIT_HLIST_NODE(&arq->hash);
 		INIT_LIST_HEAD(&arq->fifo);
 		rq->elevator_private = arq;
 		return 0;
@@ -1663,7 +1652,7 @@
 
 	ad->q = q; /* Identify what queue the data belongs to */
 
-	ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES,
+	ad->hash = kmalloc_node(sizeof(struct hlist_head)*AS_HASH_ENTRIES,
 				GFP_KERNEL, q->node);
 	if (!ad->hash) {
 		kfree(ad);
@@ -1685,7 +1674,7 @@
 	INIT_WORK(&ad->antic_work, as_work_handler, q);
 
 	for (i = 0; i < AS_HASH_ENTRIES; i++)
-		INIT_LIST_HEAD(&ad->hash[i]);
+		INIT_HLIST_HEAD(&ad->hash[i]);
 
 	INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]);
 	INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 052b174..e25223e 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -26,7 +26,7 @@
 static const int cfq_slice_sync = HZ / 10;
 static int cfq_slice_async = HZ / 25;
 static const int cfq_slice_async_rq = 2;
-static int cfq_slice_idle = HZ / 70;
+static int cfq_slice_idle = HZ / 125;
 
 #define CFQ_IDLE_GRACE		(HZ / 10)
 #define CFQ_SLICE_SCALE		(5)
@@ -60,16 +60,6 @@
 /*
  * rb-tree defines
  */
-#define RB_NONE			(2)
-#define RB_EMPTY(node)		((node)->rb_node == NULL)
-#define RB_CLEAR_COLOR(node)	(node)->rb_color = RB_NONE
-#define RB_CLEAR(node)		do {	\
-	(node)->rb_parent = NULL;	\
-	RB_CLEAR_COLOR((node));		\
-	(node)->rb_right = NULL;	\
-	(node)->rb_left = NULL;		\
-} while (0)
-#define RB_CLEAR_ROOT(root)	((root)->rb_node = NULL)
 #define rb_entry_crq(node)	rb_entry((node), struct cfq_rq, rb_node)
 #define rq_rb_key(rq)		(rq)->sector
 
@@ -128,8 +118,6 @@
 	 */
 	struct hlist_head *crq_hash;
 
-	unsigned int max_queued;
-
 	mempool_t *crq_pool;
 
 	int rq_in_driver;
@@ -284,8 +272,6 @@
 static void cfq_dispatch_insert(request_queue_t *, struct cfq_rq *);
 static struct cfq_queue *cfq_get_queue(struct cfq_data *cfqd, unsigned int key, struct task_struct *tsk, gfp_t gfp_mask);
 
-#define process_sync(tsk)	((tsk)->flags & PF_SYNCWRITE)
-
 /*
  * lots of deadline iosched dupes, can be abstracted later...
  */
@@ -341,7 +327,7 @@
 
 static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
 {
-	if (rw == READ || process_sync(task))
+	if (rw == READ || rw == WRITE_SYNC)
 		return task->pid;
 
 	return CFQ_KEY_ASYNC;
@@ -567,9 +553,8 @@
 	cfq_update_next_crq(crq);
 
 	rb_erase(&crq->rb_node, &cfqq->sort_list);
-	RB_CLEAR_COLOR(&crq->rb_node);
 
-	if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
+	if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY_ROOT(&cfqq->sort_list))
 		cfq_del_cfqq_rr(cfqd, cfqq);
 }
 
@@ -916,13 +901,15 @@
 	return cfqq;
 }
 
+#define CIC_SEEKY(cic) ((cic)->seek_mean > (128 * 1024))
+
 static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 
 {
 	struct cfq_io_context *cic;
 	unsigned long sl;
 
-	WARN_ON(!RB_EMPTY(&cfqq->sort_list));
+	WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list));
 	WARN_ON(cfqq != cfqd->active_queue);
 
 	/*
@@ -949,7 +936,7 @@
 	 * fair distribution of slice time for a process doing back-to-back
 	 * seeks. so allow a little bit of time for him to submit a new rq
 	 */
-	if (sample_valid(cic->seek_samples) && cic->seek_mean > 131072)
+	if (sample_valid(cic->seek_samples) && CIC_SEEKY(cic))
 		sl = 2;
 
 	mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
@@ -960,11 +947,15 @@
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct cfq_queue *cfqq = crq->cfq_queue;
+	struct request *rq;
 
 	cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
 	cfq_remove_request(crq->request);
 	cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
 	elv_dispatch_sort(q, crq->request);
+
+	rq = list_entry(q->queue_head.prev, struct request, queuelist);
+	cfqd->last_sector = rq->sector + rq->nr_sectors;
 }
 
 /*
@@ -1046,10 +1037,12 @@
 	 * if queue has requests, dispatch one. if not, check if
 	 * enough slice is left to wait for one
 	 */
-	if (!RB_EMPTY(&cfqq->sort_list))
+	if (!RB_EMPTY_ROOT(&cfqq->sort_list))
 		goto keep_queue;
-	else if (cfq_cfqq_class_sync(cfqq) &&
-		 time_before(now, cfqq->slice_end)) {
+	else if (cfq_cfqq_dispatched(cfqq)) {
+		cfqq = NULL;
+		goto keep_queue;
+	} else if (cfq_cfqq_class_sync(cfqq)) {
 		if (cfq_arm_slice_timer(cfqd, cfqq))
 			return NULL;
 	}
@@ -1068,7 +1061,7 @@
 {
 	int dispatched = 0;
 
-	BUG_ON(RB_EMPTY(&cfqq->sort_list));
+	BUG_ON(RB_EMPTY_ROOT(&cfqq->sort_list));
 
 	do {
 		struct cfq_rq *crq;
@@ -1092,14 +1085,13 @@
 			cfqd->active_cic = crq->io_context;
 		}
 
-		if (RB_EMPTY(&cfqq->sort_list))
+		if (RB_EMPTY_ROOT(&cfqq->sort_list))
 			break;
 
 	} while (dispatched < max_dispatch);
 
 	/*
-	 * if slice end isn't set yet, set it. if at least one request was
-	 * sync, use the sync time slice value
+	 * if slice end isn't set yet, set it.
 	 */
 	if (!cfqq->slice_end)
 		cfq_set_prio_slice(cfqd, cfqq);
@@ -1110,7 +1102,8 @@
 	 */
 	if ((!cfq_cfqq_sync(cfqq) &&
 	    cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
-	    cfq_class_idle(cfqq))
+	    cfq_class_idle(cfqq) ||
+	    !cfq_cfqq_idle_window(cfqq))
 		cfq_slice_expired(cfqd, 0);
 
 	return dispatched;
@@ -1119,10 +1112,11 @@
 static int
 cfq_forced_dispatch_cfqqs(struct list_head *list)
 {
-	int dispatched = 0;
 	struct cfq_queue *cfqq, *next;
 	struct cfq_rq *crq;
+	int dispatched;
 
+	dispatched = 0;
 	list_for_each_entry_safe(cfqq, next, list, cfq_list) {
 		while ((crq = cfqq->next_crq)) {
 			cfq_dispatch_insert(cfqq->cfqd->queue, crq);
@@ -1130,6 +1124,7 @@
 		}
 		BUG_ON(!list_empty(&cfqq->fifo));
 	}
+
 	return dispatched;
 }
 
@@ -1156,7 +1151,8 @@
 cfq_dispatch_requests(request_queue_t *q, int force)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
-	struct cfq_queue *cfqq;
+	struct cfq_queue *cfqq, *prev_cfqq;
+	int dispatched;
 
 	if (!cfqd->busy_queues)
 		return 0;
@@ -1164,10 +1160,17 @@
 	if (unlikely(force))
 		return cfq_forced_dispatch(cfqd);
 
-	cfqq = cfq_select_queue(cfqd);
-	if (cfqq) {
+	dispatched = 0;
+	prev_cfqq = NULL;
+	while ((cfqq = cfq_select_queue(cfqd)) != NULL) {
 		int max_dispatch;
 
+		/*
+		 * Don't repeat dispatch from the previous queue.
+		 */
+		if (prev_cfqq == cfqq)
+			break;
+
 		cfq_clear_cfqq_must_dispatch(cfqq);
 		cfq_clear_cfqq_wait_request(cfqq);
 		del_timer(&cfqd->idle_slice_timer);
@@ -1176,10 +1179,19 @@
 		if (cfq_class_idle(cfqq))
 			max_dispatch = 1;
 
-		return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
+		dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
+
+		/*
+		 * If the dispatch cfqq has idling enabled and is still
+		 * the active queue, break out.
+		 */
+		if (cfq_cfqq_idle_window(cfqq) && cfqd->active_queue)
+			break;
+
+		prev_cfqq = cfqq;
 	}
 
-	return 0;
+	return dispatched;
 }
 
 /*
@@ -1324,7 +1336,6 @@
 
 	if (cic) {
 		memset(cic, 0, sizeof(*cic));
-		RB_CLEAR_COLOR(&cic->rb_node);
 		cic->last_end_request = jiffies;
 		INIT_LIST_HEAD(&cic->queue_list);
 		cic->dtor = cfq_free_io_context;
@@ -1386,25 +1397,28 @@
 {
 	struct cfq_data *cfqd = cic->key;
 	struct cfq_queue *cfqq;
-	if (cfqd) {
-		spin_lock(cfqd->queue->queue_lock);
-		cfqq = cic->cfqq[ASYNC];
-		if (cfqq) {
-			struct cfq_queue *new_cfqq;
-			new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC,
-						cic->ioc->task, GFP_ATOMIC);
-			if (new_cfqq) {
-				cic->cfqq[ASYNC] = new_cfqq;
-				cfq_put_queue(cfqq);
-			}
+
+	if (unlikely(!cfqd))
+		return;
+
+	spin_lock(cfqd->queue->queue_lock);
+
+	cfqq = cic->cfqq[ASYNC];
+	if (cfqq) {
+		struct cfq_queue *new_cfqq;
+		new_cfqq = cfq_get_queue(cfqd, CFQ_KEY_ASYNC, cic->ioc->task,
+					 GFP_ATOMIC);
+		if (new_cfqq) {
+			cic->cfqq[ASYNC] = new_cfqq;
+			cfq_put_queue(cfqq);
 		}
-		cfqq = cic->cfqq[SYNC];
-		if (cfqq) {
-			cfq_mark_cfqq_prio_changed(cfqq);
-			cfq_init_prio_data(cfqq);
-		}
-		spin_unlock(cfqd->queue->queue_lock);
 	}
+
+	cfqq = cic->cfqq[SYNC];
+	if (cfqq)
+		cfq_mark_cfqq_prio_changed(cfqq);
+
+	spin_unlock(cfqd->queue->queue_lock);
 }
 
 /*
@@ -1461,7 +1475,6 @@
 
 		INIT_HLIST_NODE(&cfqq->cfq_hash);
 		INIT_LIST_HEAD(&cfqq->cfq_list);
-		RB_CLEAR_ROOT(&cfqq->sort_list);
 		INIT_LIST_HEAD(&cfqq->fifo);
 
 		cfqq->key = key;
@@ -1473,8 +1486,7 @@
 		 * set ->slice_left to allow preemption for a new process
 		 */
 		cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
-		if (!cfqd->hw_tag)
-			cfq_mark_cfqq_idle_window(cfqq);
+		cfq_mark_cfqq_idle_window(cfqq);
 		cfq_mark_cfqq_prio_changed(cfqq);
 		cfq_init_prio_data(cfqq);
 	}
@@ -1665,7 +1677,8 @@
 {
 	int enable_idle = cfq_cfqq_idle_window(cfqq);
 
-	if (!cic->ioc->task || !cfqd->cfq_slice_idle || cfqd->hw_tag)
+	if (!cic->ioc->task || !cfqd->cfq_slice_idle ||
+	    (cfqd->hw_tag && CIC_SEEKY(cic)))
 		enable_idle = 0;
 	else if (sample_valid(cic->ttime_samples)) {
 		if (cic->ttime_mean > cfqd->cfq_slice_idle)
@@ -1695,7 +1708,7 @@
 		return 0;
 
 	if (!cfqq)
-		return 1;
+		return 0;
 
 	if (cfq_class_idle(cfqq))
 		return 1;
@@ -1727,7 +1740,7 @@
 		cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2;
 
 	cfqq->slice_end = cfqq->slice_left + jiffies;
-	__cfq_slice_expired(cfqd, cfqq, 1);
+	cfq_slice_expired(cfqd, 1);
 	__cfq_set_active_queue(cfqd, cfqq);
 }
 
@@ -1752,11 +1765,7 @@
 cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 		 struct cfq_rq *crq)
 {
-	struct cfq_io_context *cic;
-
-	cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
-
-	cic = crq->io_context;
+	struct cfq_io_context *cic = crq->io_context;
 
 	/*
 	 * we never wait for an async request and we don't allow preemption
@@ -1846,11 +1855,23 @@
 			cfqq->service_last = now;
 			cfq_resort_rr_list(cfqq, 0);
 		}
-		cfq_schedule_dispatch(cfqd);
 	}
 
-	if (cfq_crq_is_sync(crq))
+	if (sync)
 		crq->io_context->last_end_request = now;
+
+	/*
+	 * If this is the active queue, check if it needs to be expired,
+	 * or if we want to idle in case it has no pending requests.
+	 */
+	if (cfqd->active_queue == cfqq) {
+		if (time_after(now, cfqq->slice_end))
+			cfq_slice_expired(cfqd, 0);
+		else if (sync && RB_EMPTY_ROOT(&cfqq->sort_list)) {
+			if (!cfq_arm_slice_timer(cfqd, cfqq))
+				cfq_schedule_dispatch(cfqd);
+		}
+	}
 }
 
 static struct request *
@@ -1917,7 +1938,6 @@
 __cfq_may_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq,
 		struct task_struct *task, int rw)
 {
-#if 1
 	if ((cfq_cfqq_wait_request(cfqq) || cfq_cfqq_must_alloc(cfqq)) &&
 	    !cfq_cfqq_must_alloc_slice(cfqq)) {
 		cfq_mark_cfqq_must_alloc_slice(cfqq);
@@ -1925,39 +1945,6 @@
 	}
 
 	return ELV_MQUEUE_MAY;
-#else
-	if (!cfqq || task->flags & PF_MEMALLOC)
-		return ELV_MQUEUE_MAY;
-	if (!cfqq->allocated[rw] || cfq_cfqq_must_alloc(cfqq)) {
-		if (cfq_cfqq_wait_request(cfqq))
-			return ELV_MQUEUE_MUST;
-
-		/*
-		 * only allow 1 ELV_MQUEUE_MUST per slice, otherwise we
-		 * can quickly flood the queue with writes from a single task
-		 */
-		if (rw == READ || !cfq_cfqq_must_alloc_slice(cfqq)) {
-			cfq_mark_cfqq_must_alloc_slice(cfqq);
-			return ELV_MQUEUE_MUST;
-		}
-
-		return ELV_MQUEUE_MAY;
-	}
-	if (cfq_class_idle(cfqq))
-		return ELV_MQUEUE_NO;
-	if (cfqq->allocated[rw] >= cfqd->max_queued) {
-		struct io_context *ioc = get_io_context(GFP_ATOMIC);
-		int ret = ELV_MQUEUE_NO;
-
-		if (ioc && ioc->nr_batch_requests)
-			ret = ELV_MQUEUE_MAY;
-
-		put_io_context(ioc);
-		return ret;
-	}
-
-	return ELV_MQUEUE_MAY;
-#endif
 }
 
 static int cfq_may_queue(request_queue_t *q, int rw, struct bio *bio)
@@ -1986,16 +1973,13 @@
 static void cfq_check_waiters(request_queue_t *q, struct cfq_queue *cfqq)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
-	struct request_list *rl = &q->rq;
 
-	if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) {
+	if (unlikely(cfqd->rq_starved)) {
+		struct request_list *rl = &q->rq;
+
 		smp_mb();
 		if (waitqueue_active(&rl->wait[READ]))
 			wake_up(&rl->wait[READ]);
-	}
-
-	if (cfqq->allocated[WRITE] <= cfqd->max_queued || cfqd->rq_starved) {
-		smp_mb();
 		if (waitqueue_active(&rl->wait[WRITE]))
 			wake_up(&rl->wait[WRITE]);
 	}
@@ -2069,7 +2053,7 @@
 
 	crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
 	if (crq) {
-		RB_CLEAR(&crq->rb_node);
+		RB_CLEAR_NODE(&crq->rb_node);
 		crq->rb_key = 0;
 		crq->request = rq;
 		INIT_HLIST_NODE(&crq->hash);
@@ -2155,16 +2139,13 @@
 		 * only expire and reinvoke request handler, if there are
 		 * other queues with pending requests
 		 */
-		if (!cfqd->busy_queues) {
-			cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
-			add_timer(&cfqd->idle_slice_timer);
+		if (!cfqd->busy_queues)
 			goto out_cont;
-		}
 
 		/*
 		 * not expired and it has a request pending, let it dispatch
 		 */
-		if (!RB_EMPTY(&cfqq->sort_list)) {
+		if (!RB_EMPTY_ROOT(&cfqq->sort_list)) {
 			cfq_mark_cfqq_must_dispatch(cfqq);
 			goto out_kick;
 		}
@@ -2285,9 +2266,6 @@
 
 	cfqd->queue = q;
 
-	cfqd->max_queued = q->nr_requests / 4;
-	q->nr_batching = cfq_queued;
-
 	init_timer(&cfqd->idle_slice_timer);
 	cfqd->idle_slice_timer.function = cfq_idle_slice_timer;
 	cfqd->idle_slice_timer.data = (unsigned long) cfqd;
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index 3bd0415..4469dd8 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -30,8 +30,7 @@
 #define DL_HASH_FN(sec)		(hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift))
 #define DL_HASH_ENTRIES		(1 << deadline_hash_shift)
 #define rq_hash_key(rq)		((rq)->sector + (rq)->nr_sectors)
-#define list_entry_hash(ptr)	list_entry((ptr), struct deadline_rq, hash)
-#define ON_HASH(drq)		(drq)->on_hash
+#define ON_HASH(drq)		(!hlist_unhashed(&(drq)->hash))
 
 struct deadline_data {
 	/*
@@ -48,7 +47,7 @@
 	 * next in sort order. read, write or both are NULL
 	 */
 	struct deadline_rq *next_drq[2];
-	struct list_head *hash;		/* request hash */
+	struct hlist_head *hash;	/* request hash */
 	unsigned int batching;		/* number of sequential requests made */
 	sector_t last_sector;		/* head position */
 	unsigned int starved;		/* times reads have starved writes */
@@ -79,8 +78,7 @@
 	/*
 	 * request hash, key is the ending offset (for back merge lookup)
 	 */
-	struct list_head hash;
-	char on_hash;
+	struct hlist_node hash;
 
 	/*
 	 * expire fifo
@@ -100,8 +98,7 @@
  */
 static inline void __deadline_del_drq_hash(struct deadline_rq *drq)
 {
-	drq->on_hash = 0;
-	list_del_init(&drq->hash);
+	hlist_del_init(&drq->hash);
 }
 
 static inline void deadline_del_drq_hash(struct deadline_rq *drq)
@@ -117,8 +114,7 @@
 
 	BUG_ON(ON_HASH(drq));
 
-	drq->on_hash = 1;
-	list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]);
+	hlist_add_head(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]);
 }
 
 /*
@@ -128,26 +124,24 @@
 deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq)
 {
 	struct request *rq = drq->request;
-	struct list_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))];
+	struct hlist_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))];
 
-	if (ON_HASH(drq) && drq->hash.prev != head) {
-		list_del(&drq->hash);
-		list_add(&drq->hash, head);
+	if (ON_HASH(drq) && &drq->hash != head->first) {
+		hlist_del(&drq->hash);
+		hlist_add_head(&drq->hash, head);
 	}
 }
 
 static struct request *
 deadline_find_drq_hash(struct deadline_data *dd, sector_t offset)
 {
-	struct list_head *hash_list = &dd->hash[DL_HASH_FN(offset)];
-	struct list_head *entry, *next = hash_list->next;
+	struct hlist_head *hash_list = &dd->hash[DL_HASH_FN(offset)];
+	struct hlist_node *entry, *next;
+	struct deadline_rq *drq;
 
-	while ((entry = next) != hash_list) {
-		struct deadline_rq *drq = list_entry_hash(entry);
+	hlist_for_each_entry_safe(drq, entry, next, hash_list, hash) {
 		struct request *__rq = drq->request;
 
-		next = entry->next;
-		
 		BUG_ON(!ON_HASH(drq));
 
 		if (!rq_mergeable(__rq)) {
@@ -165,10 +159,6 @@
 /*
  * rb tree support functions
  */
-#define RB_NONE		(2)
-#define RB_EMPTY(root)	((root)->rb_node == NULL)
-#define ON_RB(node)	((node)->rb_color != RB_NONE)
-#define RB_CLEAR(node)	((node)->rb_color = RB_NONE)
 #define rb_entry_drq(node)	rb_entry((node), struct deadline_rq, rb_node)
 #define DRQ_RB_ROOT(dd, drq)	(&(dd)->sort_list[rq_data_dir((drq)->request)])
 #define rq_rb_key(rq)		(rq)->sector
@@ -227,9 +217,9 @@
 			dd->next_drq[data_dir] = rb_entry_drq(rbnext);
 	}
 
-	BUG_ON(!ON_RB(&drq->rb_node));
+	BUG_ON(!RB_EMPTY_NODE(&drq->rb_node));
 	rb_erase(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
-	RB_CLEAR(&drq->rb_node);
+	RB_CLEAR_NODE(&drq->rb_node);
 }
 
 static struct request *
@@ -503,7 +493,7 @@
 	 */
 
 	if (reads) {
-		BUG_ON(RB_EMPTY(&dd->sort_list[READ]));
+		BUG_ON(RB_EMPTY_ROOT(&dd->sort_list[READ]));
 
 		if (writes && (dd->starved++ >= dd->writes_starved))
 			goto dispatch_writes;
@@ -519,7 +509,7 @@
 
 	if (writes) {
 dispatch_writes:
-		BUG_ON(RB_EMPTY(&dd->sort_list[WRITE]));
+		BUG_ON(RB_EMPTY_ROOT(&dd->sort_list[WRITE]));
 
 		dd->starved = 0;
 
@@ -626,7 +616,7 @@
 		return NULL;
 	memset(dd, 0, sizeof(*dd));
 
-	dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
+	dd->hash = kmalloc_node(sizeof(struct hlist_head)*DL_HASH_ENTRIES,
 				GFP_KERNEL, q->node);
 	if (!dd->hash) {
 		kfree(dd);
@@ -642,7 +632,7 @@
 	}
 
 	for (i = 0; i < DL_HASH_ENTRIES; i++)
-		INIT_LIST_HEAD(&dd->hash[i]);
+		INIT_HLIST_HEAD(&dd->hash[i]);
 
 	INIT_LIST_HEAD(&dd->fifo_list[READ]);
 	INIT_LIST_HEAD(&dd->fifo_list[WRITE]);
@@ -675,11 +665,10 @@
 	drq = mempool_alloc(dd->drq_pool, gfp_mask);
 	if (drq) {
 		memset(drq, 0, sizeof(*drq));
-		RB_CLEAR(&drq->rb_node);
+		RB_CLEAR_NODE(&drq->rb_node);
 		drq->request = rq;
 
-		INIT_LIST_HEAD(&drq->hash);
-		drq->on_hash = 0;
+		INIT_HLIST_NODE(&drq->hash);
 
 		INIT_LIST_HEAD(&drq->fifo);
 
diff --git a/block/elevator.c b/block/elevator.c
index a0afdd3..d00b283 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -850,12 +850,9 @@
 	 * one again (along with re-adding the sysfs dir)
 	 */
 	elevator_exit(e);
-	e = NULL;
 	q->elevator = old_elevator;
 	elv_register_queue(q);
 	clear_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-	if (e)
-		kobject_put(&e->kobj);
 	return 0;
 }
 
diff --git a/block/genhd.c b/block/genhd.c
index 5a8d3bf..8d73395 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -17,8 +17,7 @@
 #include <linux/buffer_head.h>
 #include <linux/mutex.h>
 
-static struct subsystem block_subsys;
-
+struct subsystem block_subsys;
 static DEFINE_MUTEX(block_subsys_lock);
 
 /*
@@ -511,9 +510,7 @@
 	.uevent		= block_uevent,
 };
 
-/* declare block_subsys. */
-static decl_subsys(block, &ktype_block, &block_uevent_ops);
-
+decl_subsys(block, &ktype_block, &block_uevent_ops);
 
 /*
  * aggregate disk stat collector.  Uses the same stats that the sysfs
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 7eb36c5..eee03a3 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -638,7 +638,7 @@
 	/* Assume anything <= 4GB can be handled by IOMMU.
 	   Actually some IOMMUs can handle everything, but I don't
 	   know of a way to test this here. */
-	if (bounce_pfn < (0xffffffff>>PAGE_SHIFT))
+	if (bounce_pfn < (min_t(u64,0xffffffff,BLK_BOUNCE_HIGH) >> PAGE_SHIFT))
 		dma = 1;
 	q->bounce_pfn = max_low_pfn;
 #else
@@ -1663,6 +1663,8 @@
  **/
 void blk_start_queue(request_queue_t *q)
 {
+	WARN_ON(!irqs_disabled());
+
 	clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
 
 	/*
@@ -1878,7 +1880,8 @@
  *    get dealt with eventually.
  *
  *    The queue spin lock must be held while manipulating the requests on the
- *    request queue.
+ *    request queue; this lock will be taken also from interrupt context, so irq
+ *    disabling is needed for it.
  *
  *    Function returns a pointer to the initialized request queue, or NULL if
  *    it didn't succeed.
@@ -2742,7 +2745,7 @@
 		return 0;
 
 	/*
-	 * not contigious
+	 * not contiguous
 	 */
 	if (req->sector + req->nr_sectors != next->sector)
 		return 0;
@@ -2824,6 +2827,9 @@
 	if (unlikely(bio_barrier(bio)))
 		req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
 
+	if (bio_sync(bio))
+		req->flags |= REQ_RW_SYNC;
+
 	req->errors = 0;
 	req->hard_sector = req->sector = bio->bi_sector;
 	req->hard_nr_sectors = req->nr_sectors = bio_sectors(bio);
@@ -3359,12 +3365,11 @@
  */
 static void blk_done_softirq(struct softirq_action *h)
 {
-	struct list_head *cpu_list;
-	LIST_HEAD(local_list);
+	struct list_head *cpu_list, local_list;
 
 	local_irq_disable();
 	cpu_list = &__get_cpu_var(blk_cpu_done);
-	list_splice_init(cpu_list, &local_list);
+	list_replace_init(cpu_list, &local_list);
 	local_irq_enable();
 
 	while (!list_empty(&local_list)) {
@@ -3398,7 +3403,7 @@
 }
 
 
-static struct notifier_block blk_cpu_notifier = {
+static struct notifier_block __devinitdata blk_cpu_notifier = {
 	.notifier_call	= blk_cpu_notify,
 };
 
@@ -3410,7 +3415,7 @@
  *
  * Description:
  *     Ends all I/O on a request. It does not handle partial completions,
- *     unless the driver actually implements this in its completionc callback
+ *     unless the driver actually implements this in its completion callback
  *     through requeueing. Theh actual completion happens out-of-order,
  *     through a softirq handler. The user must have registered a completion
  *     callback through blk_queue_softirq_done().
@@ -3536,9 +3541,7 @@
 		INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
 
 	open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
-#ifdef CONFIG_HOTPLUG_CPU
-	register_cpu_notifier(&blk_cpu_notifier);
-#endif
+	register_hotcpu_notifier(&blk_cpu_notifier);
 
 	blk_max_low_pfn = max_low_pfn;
 	blk_max_pfn = max_pfn;
diff --git a/crypto/Kconfig b/crypto/Kconfig
index c442f2e..ba133d5 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -337,7 +337,7 @@
 
 config CRYPTO_TEST
 	tristate "Testing module"
-	depends on CRYPTO
+	depends on CRYPTO && m
 	help
 	  Quick & dirty crypto test module.
 
diff --git a/crypto/aes.c b/crypto/aes.c
index a501729..a038711 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -248,10 +248,10 @@
     t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
 }
 
-static int
-aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len, u32 *flags)
 {
-	struct aes_ctx *ctx = ctx_arg;
+	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *key = (const __le32 *)in_key;
 	u32 i, t, u, v, w;
 
@@ -318,9 +318,9 @@
     f_rl(bo, bi, 2, k);     \
     f_rl(bo, bi, 3, k)
 
-static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in)
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	const struct aes_ctx *ctx = ctx_arg;
+	const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *src = (const __le32 *)in;
 	__le32 *dst = (__le32 *)out;
 	u32 b0[4], b1[4];
@@ -373,9 +373,9 @@
     i_rl(bo, bi, 2, k);     \
     i_rl(bo, bi, 3, k)
 
-static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in)
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	const struct aes_ctx *ctx = ctx_arg;
+	const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *src = (const __le32 *)in;
 	__le32 *dst = (__le32 *)out;
 	u32 b0[4], b1[4];
diff --git a/crypto/anubis.c b/crypto/anubis.c
index 2c796bd..7e2e1a2 100644
--- a/crypto/anubis.c
+++ b/crypto/anubis.c
@@ -460,16 +460,15 @@
 	0xf726ffedU, 0xe89d6f8eU, 0x19a0f089U,
 };
 
-static int anubis_setkey(void *ctx_arg, const u8 *in_key,
+static int anubis_setkey(struct crypto_tfm *tfm, const u8 *in_key,
 			 unsigned int key_len, u32 *flags)
 {
+	struct anubis_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __be32 *key = (const __be32 *)in_key;
 	int N, R, i, r;
 	u32 kappa[ANUBIS_MAX_N];
 	u32 inter[ANUBIS_MAX_N];
 
-	struct anubis_ctx *ctx = ctx_arg;
-
 	switch (key_len)
 	{
 		case 16: case 20: case 24: case 28:
@@ -660,15 +659,15 @@
 		dst[i] = cpu_to_be32(inter[i]);
 }
 
-static void anubis_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+static void anubis_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct anubis_ctx *ctx = ctx_arg;
+	struct anubis_ctx *ctx = crypto_tfm_ctx(tfm);
 	anubis_crypt(ctx->E, dst, src, ctx->R);
 }
 
-static void anubis_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+static void anubis_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct anubis_ctx *ctx = ctx_arg;
+	struct anubis_ctx *ctx = crypto_tfm_ctx(tfm);
 	anubis_crypt(ctx->D, dst, src, ctx->R);
 }
 
diff --git a/crypto/api.c b/crypto/api.c
index 80bba63..c11ec1f 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -188,13 +188,16 @@
 	if (crypto_init_flags(tfm, flags))
 		goto out_free_tfm;
 		
-	if (crypto_init_ops(tfm)) {
-		crypto_exit_ops(tfm);
+	if (crypto_init_ops(tfm))
 		goto out_free_tfm;
-	}
+
+	if (alg->cra_init && alg->cra_init(tfm))
+		goto cra_init_failed;
 
 	goto out;
 
+cra_init_failed:
+	crypto_exit_ops(tfm);
 out_free_tfm:
 	kfree(tfm);
 	tfm = NULL;
@@ -215,6 +218,8 @@
 	alg = tfm->__crt_alg;
 	size = sizeof(*tfm) + alg->cra_ctxsize;
 
+	if (alg->cra_exit)
+		alg->cra_exit(tfm);
 	crypto_exit_ops(tfm);
 	crypto_alg_put(alg);
 	memset(tfm, 0, size);
@@ -224,7 +229,7 @@
 static inline int crypto_set_driver_name(struct crypto_alg *alg)
 {
 	static const char suffix[] = "-generic";
-	char *driver_name = (char *)alg->cra_driver_name;
+	char *driver_name = alg->cra_driver_name;
 	int len;
 
 	if (*driver_name)
@@ -262,13 +267,13 @@
 	down_write(&crypto_alg_sem);
 	
 	list_for_each_entry(q, &crypto_alg_list, cra_list) {
-		if (!strcmp(q->cra_driver_name, alg->cra_driver_name)) {
+		if (q == alg) {
 			ret = -EEXIST;
 			goto out;
 		}
 	}
 	
-	list_add_tail(&alg->cra_list, &crypto_alg_list);
+	list_add(&alg->cra_list, &crypto_alg_list);
 out:	
 	up_write(&crypto_alg_sem);
 	return ret;
diff --git a/crypto/arc4.c b/crypto/arc4.c
index 9efbcaae..5edc6a6 100644
--- a/crypto/arc4.c
+++ b/crypto/arc4.c
@@ -24,9 +24,10 @@
 	u8 x, y;
 };
 
-static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags)
+static int arc4_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+			unsigned int key_len, u32 *flags)
 {
-	struct arc4_ctx *ctx = ctx_arg;
+	struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
 	int i, j = 0, k = 0;
 
 	ctx->x = 1;
@@ -48,9 +49,9 @@
 	return 0;
 }
 
-static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in)
+static void arc4_crypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct arc4_ctx *ctx = ctx_arg;
+	struct arc4_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	u8 *const S = ctx->S;
 	u8 x = ctx->x;
diff --git a/crypto/blowfish.c b/crypto/blowfish.c
index 7f710b2..490265f 100644
--- a/crypto/blowfish.c
+++ b/crypto/blowfish.c
@@ -349,7 +349,7 @@
 	dst[1] = yl;
 }
 
-static void bf_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void bf_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
 	const __be32 *in_blk = (const __be32 *)src;
 	__be32 *const out_blk = (__be32 *)dst;
@@ -357,17 +357,18 @@
 
 	in32[0] = be32_to_cpu(in_blk[0]);
 	in32[1] = be32_to_cpu(in_blk[1]);
-	encrypt_block(ctx, out32, in32);
+	encrypt_block(crypto_tfm_ctx(tfm), out32, in32);
 	out_blk[0] = cpu_to_be32(out32[0]);
 	out_blk[1] = cpu_to_be32(out32[1]);
 }
 
-static void bf_decrypt(void *ctx, u8 *dst, const u8 *src)
+static void bf_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __be32 *in_blk = (const __be32 *)src;
 	__be32 *const out_blk = (__be32 *)dst;
-	const u32 *P = ((struct bf_ctx *)ctx)->p;
-	const u32 *S = ((struct bf_ctx *)ctx)->s;
+	const u32 *P = ctx->p;
+	const u32 *S = ctx->s;
 	u32 yl = be32_to_cpu(in_blk[0]);
 	u32 yr = be32_to_cpu(in_blk[1]);
 
@@ -398,12 +399,14 @@
 /* 
  * Calculates the blowfish S and P boxes for encryption and decryption.
  */
-static int bf_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+static int bf_setkey(struct crypto_tfm *tfm, const u8 *key,
+		     unsigned int keylen, u32 *flags)
 {
+	struct bf_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *P = ctx->p;
+	u32 *S = ctx->s;
 	short i, j, count;
 	u32 data[2], temp;
-	u32 *P = ((struct bf_ctx *)ctx)->p;
-	u32 *S = ((struct bf_ctx *)ctx)->s;
 
 	/* Copy the initialization s-boxes */
 	for (i = 0, count = 0; i < 256; i++)
diff --git a/crypto/cast5.c b/crypto/cast5.c
index 8834c85..08eef58 100644
--- a/crypto/cast5.c
+++ b/crypto/cast5.c
@@ -577,9 +577,9 @@
     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
 
 
-static void cast5_encrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
+static void cast5_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
 {
-	struct cast5_ctx *c = (struct cast5_ctx *) ctx;
+	struct cast5_ctx *c = crypto_tfm_ctx(tfm);
 	const __be32 *src = (const __be32 *)inbuf;
 	__be32 *dst = (__be32 *)outbuf;
 	u32 l, r, t;
@@ -642,9 +642,9 @@
 	dst[1] = cpu_to_be32(l);
 }
 
-static void cast5_decrypt(void *ctx, u8 * outbuf, const u8 * inbuf)
+static void cast5_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
 {
-	struct cast5_ctx *c = (struct cast5_ctx *) ctx;
+	struct cast5_ctx *c = crypto_tfm_ctx(tfm);
 	const __be32 *src = (const __be32 *)inbuf;
 	__be32 *dst = (__be32 *)outbuf;
 	u32 l, r, t;
@@ -769,15 +769,15 @@
 }
 
 
-static int
-cast5_setkey(void *ctx, const u8 * key, unsigned key_len, u32 * flags)
+static int cast5_setkey(struct crypto_tfm *tfm, const u8 *key,
+			unsigned key_len, u32 *flags)
 {
+	struct cast5_ctx *c = crypto_tfm_ctx(tfm);
 	int i;
 	u32 x[4];
 	u32 z[4];
 	u32 k[16];
 	__be32 p_key[4];
-	struct cast5_ctx *c = (struct cast5_ctx *) ctx;
 	
 	if (key_len < 5 || key_len > 16) {
 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
diff --git a/crypto/cast6.c b/crypto/cast6.c
index 9e28740..08e33bf 100644
--- a/crypto/cast6.c
+++ b/crypto/cast6.c
@@ -381,13 +381,13 @@
 	key[7] ^= F2(key[0], Tr[i % 4][7], Tm[i][7]);
 }
 
-static int
-cast6_setkey(void *ctx, const u8 * in_key, unsigned key_len, u32 * flags)
+static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+			unsigned key_len, u32 *flags)
 {
 	int i;
 	u32 key[8];
 	__be32 p_key[8]; /* padded key */
-	struct cast6_ctx *c = (struct cast6_ctx *) ctx;
+	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
 
 	if (key_len < 16 || key_len > 32 || key_len % 4 != 0) {
 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
@@ -444,8 +444,9 @@
         block[2] ^= F1(block[3], Kr[0], Km[0]);
 }
 
-static void cast6_encrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
-	struct cast6_ctx * c = (struct cast6_ctx *)ctx;
+static void cast6_encrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf)
+{
+	struct cast6_ctx *c = crypto_tfm_ctx(tfm);
 	const __be32 *src = (const __be32 *)inbuf;
 	__be32 *dst = (__be32 *)outbuf;
 	u32 block[4];
@@ -476,8 +477,8 @@
 	dst[3] = cpu_to_be32(block[3]);
 }	
 
-static void cast6_decrypt (void * ctx, u8 * outbuf, const u8 * inbuf) {
-	struct cast6_ctx * c = (struct cast6_ctx *)ctx;
+static void cast6_decrypt(struct crypto_tfm *tfm, u8 *outbuf, const u8 *inbuf) {
+	struct cast6_ctx * c = crypto_tfm_ctx(tfm);
 	const __be32 *src = (const __be32 *)inbuf;
 	__be32 *dst = (__be32 *)outbuf;
 	u32 block[4];
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 65bcea0..b899eb9 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -187,7 +187,7 @@
 	void (*xor)(u8 *, const u8 *) = tfm->crt_u.cipher.cit_xor_block;
 	int bsize = crypto_tfm_alg_blocksize(tfm);
 
-	void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
 	u8 *iv = desc->info;
 	unsigned int done = 0;
 
@@ -195,7 +195,7 @@
 
 	do {
 		xor(iv, src);
-		fn(crypto_tfm_ctx(tfm), dst, iv);
+		fn(tfm, dst, iv);
 		memcpy(iv, dst, bsize);
 
 		src += bsize;
@@ -218,7 +218,7 @@
 	u8 *buf = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
 	u8 **dst_p = src == dst ? &buf : &dst;
 
-	void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
 	u8 *iv = desc->info;
 	unsigned int done = 0;
 
@@ -227,7 +227,7 @@
 	do {
 		u8 *tmp_dst = *dst_p;
 
-		fn(crypto_tfm_ctx(tfm), tmp_dst, src);
+		fn(tfm, tmp_dst, src);
 		xor(tmp_dst, iv);
 		memcpy(iv, src, bsize);
 		if (tmp_dst != dst)
@@ -245,13 +245,13 @@
 {
 	struct crypto_tfm *tfm = desc->tfm;
 	int bsize = crypto_tfm_alg_blocksize(tfm);
-	void (*fn)(void *, u8 *, const u8 *) = desc->crfn;
+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) = desc->crfn;
 	unsigned int done = 0;
 
 	nbytes -= bsize;
 
 	do {
-		fn(crypto_tfm_ctx(tfm), dst, src);
+		fn(tfm, dst, src);
 
 		src += bsize;
 		dst += bsize;
@@ -268,7 +268,7 @@
 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 		return -EINVAL;
 	} else
-		return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen,
+		return cia->cia_setkey(tfm, key, keylen,
 		                       &tfm->crt_flags);
 }
 
diff --git a/crypto/compress.c b/crypto/compress.c
index eb36d93..eca182a 100644
--- a/crypto/compress.c
+++ b/crypto/compress.c
@@ -22,8 +22,7 @@
                             const u8 *src, unsigned int slen,
                             u8 *dst, unsigned int *dlen)
 {
-	return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm),
-	                                                 src, slen, dst,
+	return tfm->__crt_alg->cra_compress.coa_compress(tfm, src, slen, dst,
 	                                                 dlen);
 }
 
@@ -31,8 +30,7 @@
                              const u8 *src, unsigned int slen,
                              u8 *dst, unsigned int *dlen)
 {
-	return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm),
-	                                                   src, slen, dst,
+	return tfm->__crt_alg->cra_compress.coa_decompress(tfm, src, slen, dst,
 	                                                   dlen);
 }
 
@@ -43,21 +41,14 @@
 
 int crypto_init_compress_ops(struct crypto_tfm *tfm)
 {
-	int ret = 0;
 	struct compress_tfm *ops = &tfm->crt_compress;
-	
-	ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm));
-	if (ret)
-		goto out;
 
 	ops->cot_compress = crypto_compress;
 	ops->cot_decompress = crypto_decompress;
 	
-out:
-	return ret;
+	return 0;
 }
 
 void crypto_exit_compress_ops(struct crypto_tfm *tfm)
 {
-	tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm));
 }
diff --git a/crypto/crc32c.c b/crypto/crc32c.c
index 9533624..f266012 100644
--- a/crypto/crc32c.c
+++ b/crypto/crc32c.c
@@ -31,9 +31,9 @@
  * crc using table.
  */
 
-static void chksum_init(void *ctx)
+static void chksum_init(struct crypto_tfm *tfm)
 {
-	struct chksum_ctx *mctx = ctx;
+	struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
 
 	mctx->crc = ~(u32)0;			/* common usage */
 }
@@ -43,10 +43,10 @@
  * If your algorithm starts with ~0, then XOR with ~0 before you set
  * the seed.
  */
-static int chksum_setkey(void *ctx, const u8 *key, unsigned int keylen,
-	                  u32 *flags)
+static int chksum_setkey(struct crypto_tfm *tfm, const u8 *key,
+			 unsigned int keylen, u32 *flags)
 {
-	struct chksum_ctx *mctx = ctx;
+	struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
 
 	if (keylen != sizeof(mctx->crc)) {
 		if (flags)
@@ -57,9 +57,10 @@
 	return 0;
 }
 
-static void chksum_update(void *ctx, const u8 *data, unsigned int length)
+static void chksum_update(struct crypto_tfm *tfm, const u8 *data,
+			  unsigned int length)
 {
-	struct chksum_ctx *mctx = ctx;
+	struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
 	u32 mcrc;
 
 	mcrc = crc32c(mctx->crc, data, (size_t)length);
@@ -67,9 +68,9 @@
 	mctx->crc = mcrc;
 }
 
-static void chksum_final(void *ctx, u8 *out)
+static void chksum_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct chksum_ctx *mctx = ctx;
+	struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
 	u32 mcrc = (mctx->crc ^ ~(u32)0);
 	
 	*(u32 *)out = __le32_to_cpu(mcrc);
diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
index 3fcf6e8..a0d956b 100644
--- a/crypto/crypto_null.c
+++ b/crypto/crypto_null.c
@@ -27,8 +27,8 @@
 #define NULL_BLOCK_SIZE		1
 #define NULL_DIGEST_SIZE	0
 
-static int null_compress(void *ctx, const u8 *src, unsigned int slen,
-                         u8 *dst, unsigned int *dlen)
+static int null_compress(struct crypto_tfm *tfm, const u8 *src,
+			 unsigned int slen, u8 *dst, unsigned int *dlen)
 {
 	if (slen > *dlen)
 		return -EINVAL;
@@ -37,20 +37,21 @@
 	return 0;
 }
 
-static void null_init(void *ctx)
+static void null_init(struct crypto_tfm *tfm)
 { }
 
-static void null_update(void *ctx, const u8 *data, unsigned int len)
+static void null_update(struct crypto_tfm *tfm, const u8 *data,
+			unsigned int len)
 { }
 
-static void null_final(void *ctx, u8 *out)
+static void null_final(struct crypto_tfm *tfm, u8 *out)
 { }
 
-static int null_setkey(void *ctx, const u8 *key,
-                       unsigned int keylen, u32 *flags)
+static int null_setkey(struct crypto_tfm *tfm, const u8 *key,
+		       unsigned int keylen, u32 *flags)
 { return 0; }
 
-static void null_crypt(void *ctx, u8 *dst, const u8 *src)
+static void null_crypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
 	memcpy(dst, src, NULL_BLOCK_SIZE);
 }
diff --git a/crypto/deflate.c b/crypto/deflate.c
index f209368..6588bbf 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -102,8 +102,9 @@
 	kfree(ctx->decomp_stream.workspace);
 }
 
-static int deflate_init(void *ctx)
+static int deflate_init(struct crypto_tfm *tfm)
 {
+	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
 	int ret;
 	
 	ret = deflate_comp_init(ctx);
@@ -116,17 +117,19 @@
 	return ret;
 }
 
-static void deflate_exit(void *ctx)
+static void deflate_exit(struct crypto_tfm *tfm)
 {
+	struct deflate_ctx *ctx = crypto_tfm_ctx(tfm);
+
 	deflate_comp_exit(ctx);
 	deflate_decomp_exit(ctx);
 }
 
-static int deflate_compress(void *ctx, const u8 *src, unsigned int slen,
-	                    u8 *dst, unsigned int *dlen)
+static int deflate_compress(struct crypto_tfm *tfm, const u8 *src,
+			    unsigned int slen, u8 *dst, unsigned int *dlen)
 {
 	int ret = 0;
-	struct deflate_ctx *dctx = ctx;
+	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
 	struct z_stream_s *stream = &dctx->comp_stream;
 
 	ret = zlib_deflateReset(stream);
@@ -151,12 +154,12 @@
 	return ret;
 }
  
-static int deflate_decompress(void *ctx, const u8 *src, unsigned int slen,
-                              u8 *dst, unsigned int *dlen)
+static int deflate_decompress(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen)
 {
 	
 	int ret = 0;
-	struct deflate_ctx *dctx = ctx;
+	struct deflate_ctx *dctx = crypto_tfm_ctx(tfm);
 	struct z_stream_s *stream = &dctx->decomp_stream;
 
 	ret = zlib_inflateReset(stream);
@@ -198,9 +201,9 @@
 	.cra_ctxsize		= sizeof(struct deflate_ctx),
 	.cra_module		= THIS_MODULE,
 	.cra_list		= LIST_HEAD_INIT(alg.cra_list),
+	.cra_init		= deflate_init,
+	.cra_exit		= deflate_exit,
 	.cra_u			= { .compress = {
-	.coa_init		= deflate_init,
-	.coa_exit		= deflate_exit,
 	.coa_compress 		= deflate_compress,
 	.coa_decompress  	= deflate_decompress } }
 };
diff --git a/crypto/des.c b/crypto/des.c
index 2d74cab..a9d3c23 100644
--- a/crypto/des.c
+++ b/crypto/des.c
@@ -783,9 +783,10 @@
 	}
 }
 
-static int des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
+		      unsigned int keylen, u32 *flags)
 {
-	struct des_ctx *dctx = ctx;
+	struct des_ctx *dctx = crypto_tfm_ctx(tfm);
 	u32 tmp[DES_EXPKEY_WORDS];
 	int ret;
 
@@ -803,9 +804,10 @@
 	return 0;
 }
 
-static void des_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	const u32 *K = ((struct des_ctx *)ctx)->expkey;
+	struct des_ctx *ctx = crypto_tfm_ctx(tfm);
+	const u32 *K = ctx->expkey;
 	const __le32 *s = (const __le32 *)src;
 	__le32 *d = (__le32 *)dst;
 	u32 L, R, A, B;
@@ -825,9 +827,10 @@
 	d[1] = cpu_to_le32(L);
 }
 
-static void des_decrypt(void *ctx, u8 *dst, const u8 *src)
+static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	const u32 *K = ((struct des_ctx *)ctx)->expkey + DES_EXPKEY_WORDS - 2;
+	struct des_ctx *ctx = crypto_tfm_ctx(tfm);
+	const u32 *K = ctx->expkey + DES_EXPKEY_WORDS - 2;
 	const __le32 *s = (const __le32 *)src;
 	__le32 *d = (__le32 *)dst;
 	u32 L, R, A, B;
@@ -860,11 +863,11 @@
  *   property.
  *
  */
-static int des3_ede_setkey(void *ctx, const u8 *key,
+static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
 			   unsigned int keylen, u32 *flags)
 {
 	const u32 *K = (const u32 *)key;
-	struct des3_ede_ctx *dctx = ctx;
+	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
 	u32 *expkey = dctx->expkey;
 
 	if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
@@ -881,9 +884,9 @@
 	return 0;
 }
 
-static void des3_ede_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct des3_ede_ctx *dctx = ctx;
+	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
 	const u32 *K = dctx->expkey;
 	const __le32 *s = (const __le32 *)src;
 	__le32 *d = (__le32 *)dst;
@@ -912,9 +915,9 @@
 	d[1] = cpu_to_le32(L);
 }
 
-static void des3_ede_decrypt(void *ctx, u8 *dst, const u8 *src)
+static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct des3_ede_ctx *dctx = ctx;
+	struct des3_ede_ctx *dctx = crypto_tfm_ctx(tfm);
 	const u32 *K = dctx->expkey + DES3_EDE_EXPKEY_WORDS - 2;
 	const __le32 *s = (const __le32 *)src;
 	__le32 *d = (__le32 *)dst;
diff --git a/crypto/digest.c b/crypto/digest.c
index d9b6ac9..603006a 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -20,13 +20,14 @@
 
 static void init(struct crypto_tfm *tfm)
 {
-	tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm));
+	tfm->__crt_alg->cra_digest.dia_init(tfm);
 }
 
 static void update(struct crypto_tfm *tfm,
                    struct scatterlist *sg, unsigned int nsg)
 {
 	unsigned int i;
+	unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
 
 	for (i = 0; i < nsg; i++) {
 
@@ -38,12 +39,22 @@
 			unsigned int bytes_from_page = min(l, ((unsigned int)
 							   (PAGE_SIZE)) - 
 							   offset);
-			char *p = crypto_kmap(pg, 0) + offset;
+			char *src = crypto_kmap(pg, 0);
+			char *p = src + offset;
 
-			tfm->__crt_alg->cra_digest.dia_update
-					(crypto_tfm_ctx(tfm), p,
-					 bytes_from_page);
-			crypto_kunmap(p, 0);
+			if (unlikely(offset & alignmask)) {
+				unsigned int bytes =
+					alignmask + 1 - (offset & alignmask);
+				bytes = min(bytes, bytes_from_page);
+				tfm->__crt_alg->cra_digest.dia_update(tfm, p,
+								      bytes);
+				p += bytes;
+				bytes_from_page -= bytes;
+				l -= bytes;
+			}
+			tfm->__crt_alg->cra_digest.dia_update(tfm, p,
+							      bytes_from_page);
+			crypto_kunmap(src, 0);
 			crypto_yield(tfm);
 			offset = 0;
 			pg++;
@@ -54,7 +65,15 @@
 
 static void final(struct crypto_tfm *tfm, u8 *out)
 {
-	tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out);
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	if (unlikely((unsigned long)out & alignmask)) {
+		unsigned int size = crypto_tfm_alg_digestsize(tfm);
+		u8 buffer[size + alignmask];
+		u8 *dst = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+		tfm->__crt_alg->cra_digest.dia_final(tfm, dst);
+		memcpy(out, dst, size);
+	} else
+		tfm->__crt_alg->cra_digest.dia_final(tfm, out);
 }
 
 static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen)
@@ -62,25 +81,15 @@
 	u32 flags;
 	if (tfm->__crt_alg->cra_digest.dia_setkey == NULL)
 		return -ENOSYS;
-	return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm),
-						     key, keylen, &flags);
+	return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen, &flags);
 }
 
 static void digest(struct crypto_tfm *tfm,
                    struct scatterlist *sg, unsigned int nsg, u8 *out)
 {
-	unsigned int i;
-
-	tfm->crt_digest.dit_init(tfm);
-		
-	for (i = 0; i < nsg; i++) {
-		char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset;
-		tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm),
-		                                      p, sg[i].length);
-		crypto_kunmap(p, 0);
-		crypto_yield(tfm);
-	}
-	crypto_digest_final(tfm, out);
+	init(tfm);
+	update(tfm, sg, nsg);
+	final(tfm, out);
 }
 
 int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
diff --git a/crypto/khazad.c b/crypto/khazad.c
index 807f2bf..d4c9d36 100644
--- a/crypto/khazad.c
+++ b/crypto/khazad.c
@@ -754,11 +754,11 @@
 	0xccc41d14c363da5dULL, 0x5fdc7dcd7f5a6c5cULL, 0xf726ffede89d6f8eULL
 };
 
-static int khazad_setkey(void *ctx_arg, const u8 *in_key,
-                       unsigned int key_len, u32 *flags)
+static int khazad_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+			 unsigned int key_len, u32 *flags)
 {
-	struct khazad_ctx *ctx = ctx_arg;
-	const __be64 *key = (const __be64 *)in_key;
+	struct khazad_ctx *ctx = crypto_tfm_ctx(tfm);
+	const __be32 *key = (const __be32 *)in_key;
 	int r;
 	const u64 *S = T7;
 	u64 K2, K1;
@@ -769,8 +769,9 @@
 		return -EINVAL;
 	}
 
-	K2 = be64_to_cpu(key[0]);
-	K1 = be64_to_cpu(key[1]);
+	/* key is supposed to be 32-bit aligned */
+	K2 = ((u64)be32_to_cpu(key[0]) << 32) | be32_to_cpu(key[1]);
+	K1 = ((u64)be32_to_cpu(key[2]) << 32) | be32_to_cpu(key[3]);
 
 	/* setup the encrypt key */
 	for (r = 0; r <= KHAZAD_ROUNDS; r++) {
@@ -840,15 +841,15 @@
 	*dst = cpu_to_be64(state);
 }
 
-static void khazad_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
+static void khazad_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct khazad_ctx *ctx = ctx_arg;
+	struct khazad_ctx *ctx = crypto_tfm_ctx(tfm);
 	khazad_crypt(ctx->E, dst, src);
 }
 
-static void khazad_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
+static void khazad_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
-	struct khazad_ctx *ctx = ctx_arg;
+	struct khazad_ctx *ctx = crypto_tfm_ctx(tfm);
 	khazad_crypt(ctx->D, dst, src);
 }
 
diff --git a/crypto/md4.c b/crypto/md4.c
index a2d6df5..c1bc71b 100644
--- a/crypto/md4.c
+++ b/crypto/md4.c
@@ -152,9 +152,9 @@
 	md4_transform(ctx->hash, ctx->block);
 }
 
-static void md4_init(void *ctx)
+static void md4_init(struct crypto_tfm *tfm)
 {
-	struct md4_ctx *mctx = ctx;
+	struct md4_ctx *mctx = crypto_tfm_ctx(tfm);
 
 	mctx->hash[0] = 0x67452301;
 	mctx->hash[1] = 0xefcdab89;
@@ -163,9 +163,9 @@
 	mctx->byte_count = 0;
 }
 
-static void md4_update(void *ctx, const u8 *data, unsigned int len)
+static void md4_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
 {
-	struct md4_ctx *mctx = ctx;
+	struct md4_ctx *mctx = crypto_tfm_ctx(tfm);
 	const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
 
 	mctx->byte_count += len;
@@ -193,9 +193,9 @@
 	memcpy(mctx->block, data, len);
 }
 
-static void md4_final(void *ctx, u8 *out)
+static void md4_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct md4_ctx *mctx = ctx;
+	struct md4_ctx *mctx = crypto_tfm_ctx(tfm);
 	const unsigned int offset = mctx->byte_count & 0x3f;
 	char *p = (char *)mctx->block + offset;
 	int padding = 56 - (offset + 1);
diff --git a/crypto/md5.c b/crypto/md5.c
index 7f041ae..93d18e8 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -147,9 +147,9 @@
 	md5_transform(ctx->hash, ctx->block);
 }
 
-static void md5_init(void *ctx)
+static void md5_init(struct crypto_tfm *tfm)
 {
-	struct md5_ctx *mctx = ctx;
+	struct md5_ctx *mctx = crypto_tfm_ctx(tfm);
 
 	mctx->hash[0] = 0x67452301;
 	mctx->hash[1] = 0xefcdab89;
@@ -158,9 +158,9 @@
 	mctx->byte_count = 0;
 }
 
-static void md5_update(void *ctx, const u8 *data, unsigned int len)
+static void md5_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
 {
-	struct md5_ctx *mctx = ctx;
+	struct md5_ctx *mctx = crypto_tfm_ctx(tfm);
 	const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
 
 	mctx->byte_count += len;
@@ -188,9 +188,9 @@
 	memcpy(mctx->block, data, len);
 }
 
-static void md5_final(void *ctx, u8 *out)
+static void md5_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct md5_ctx *mctx = ctx;
+	struct md5_ctx *mctx = crypto_tfm_ctx(tfm);
 	const unsigned int offset = mctx->byte_count & 0x3f;
 	char *p = (char *)mctx->block + offset;
 	int padding = 56 - (offset + 1);
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index 4f6ab23..d061da2 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -45,16 +45,17 @@
 } while (0)
 
 
-static void michael_init(void *ctx)
+static void michael_init(struct crypto_tfm *tfm)
 {
-	struct michael_mic_ctx *mctx = ctx;
+	struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm);
 	mctx->pending_len = 0;
 }
 
 
-static void michael_update(void *ctx, const u8 *data, unsigned int len)
+static void michael_update(struct crypto_tfm *tfm, const u8 *data,
+			   unsigned int len)
 {
-	struct michael_mic_ctx *mctx = ctx;
+	struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm);
 	const __le32 *src;
 
 	if (mctx->pending_len) {
@@ -90,9 +91,9 @@
 }
 
 
-static void michael_final(void *ctx, u8 *out)
+static void michael_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct michael_mic_ctx *mctx = ctx;
+	struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm);
 	u8 *data = mctx->pending;
 	__le32 *dst = (__le32 *)out;
 
@@ -121,10 +122,10 @@
 }
 
 
-static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen,
-			  u32 *flags)
+static int michael_setkey(struct crypto_tfm *tfm, const u8 *key,
+			  unsigned int keylen, u32 *flags)
 {
-	struct michael_mic_ctx *mctx = ctx;
+	struct michael_mic_ctx *mctx = crypto_tfm_ctx(tfm);
 	const __le32 *data = (const __le32 *)key;
 
 	if (keylen != 8) {
@@ -145,6 +146,7 @@
 	.cra_blocksize	= 8,
 	.cra_ctxsize	= sizeof(struct michael_mic_ctx),
 	.cra_module	= THIS_MODULE,
+	.cra_alignmask	= 3,
 	.cra_list	= LIST_HEAD_INIT(michael_mic_alg.cra_list),
 	.cra_u		= { .digest = {
 	.dia_digestsize	= 8,
diff --git a/crypto/serpent.c b/crypto/serpent.c
index e366406..de60cdd 100644
--- a/crypto/serpent.c
+++ b/crypto/serpent.c
@@ -215,9 +215,11 @@
 };
 
 
-static int serpent_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+static int serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
+			  unsigned int keylen, u32 *flags)
 {
-	u32 *k = ((struct serpent_ctx *)ctx)->expkey;
+	struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 *k = ctx->expkey;
 	u8  *k8 = (u8 *)k;
 	u32 r0,r1,r2,r3,r4;
 	int i;
@@ -365,10 +367,11 @@
 	return 0;
 }
 
-static void serpent_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void serpent_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
+	struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
 	const u32
-		*k = ((struct serpent_ctx *)ctx)->expkey,
+		*k = ctx->expkey,
 		*s = (const u32 *)src;
 	u32	*d = (u32 *)dst,
 		r0, r1, r2, r3, r4;
@@ -423,8 +426,9 @@
 	d[3] = cpu_to_le32(r3);
 }
 
-static void serpent_decrypt(void *ctx, u8 *dst, const u8 *src)
+static void serpent_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
+	struct serpent_ctx *ctx = crypto_tfm_ctx(tfm);
 	const u32
 		*k = ((struct serpent_ctx *)ctx)->expkey,
 		*s = (const u32 *)src;
@@ -492,7 +496,8 @@
 	.cia_decrypt  		=	serpent_decrypt } }
 };
 
-static int tnepres_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags)
+static int tnepres_setkey(struct crypto_tfm *tfm, const u8 *key,
+			  unsigned int keylen, u32 *flags)
 {
 	u8 rev_key[SERPENT_MAX_KEY_SIZE];
 	int i;
@@ -506,10 +511,10 @@
 	for (i = 0; i < keylen; ++i)
 		rev_key[keylen - i - 1] = key[i];
  
-	return serpent_setkey(ctx, rev_key, keylen, flags);
+	return serpent_setkey(tfm, rev_key, keylen, flags);
 }
 
-static void tnepres_encrypt(void *ctx, u8 *dst, const u8 *src)
+static void tnepres_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
 	const u32 * const s = (const u32 * const)src;
 	u32 * const d = (u32 * const)dst;
@@ -521,7 +526,7 @@
 	rs[2] = swab32(s[1]);
 	rs[3] = swab32(s[0]);
 
-	serpent_encrypt(ctx, (u8 *)rd, (u8 *)rs);
+	serpent_encrypt(tfm, (u8 *)rd, (u8 *)rs);
 
 	d[0] = swab32(rd[3]);
 	d[1] = swab32(rd[2]);
@@ -529,7 +534,7 @@
 	d[3] = swab32(rd[0]);
 }
 
-static void tnepres_decrypt(void *ctx, u8 *dst, const u8 *src)
+static void tnepres_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 {
 	const u32 * const s = (const u32 * const)src;
 	u32 * const d = (u32 * const)dst;
@@ -541,7 +546,7 @@
 	rs[2] = swab32(s[1]);
 	rs[3] = swab32(s[0]);
 
-	serpent_decrypt(ctx, (u8 *)rd, (u8 *)rs);
+	serpent_decrypt(tfm, (u8 *)rd, (u8 *)rs);
 
 	d[0] = swab32(rd[3]);
 	d[1] = swab32(rd[2]);
diff --git a/crypto/sha1.c b/crypto/sha1.c
index 21571ed3..6c77b68 100644
--- a/crypto/sha1.c
+++ b/crypto/sha1.c
@@ -34,9 +34,9 @@
         u8 buffer[64];
 };
 
-static void sha1_init(void *ctx)
+static void sha1_init(struct crypto_tfm *tfm)
 {
-	struct sha1_ctx *sctx = ctx;
+	struct sha1_ctx *sctx = crypto_tfm_ctx(tfm);
 	static const struct sha1_ctx initstate = {
 	  0,
 	  { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
@@ -46,9 +46,10 @@
 	*sctx = initstate;
 }
 
-static void sha1_update(void *ctx, const u8 *data, unsigned int len)
+static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
+			unsigned int len)
 {
-	struct sha1_ctx *sctx = ctx;
+	struct sha1_ctx *sctx = crypto_tfm_ctx(tfm);
 	unsigned int partial, done;
 	const u8 *src;
 
@@ -80,9 +81,9 @@
 
 
 /* Add padding and return the message digest. */
-static void sha1_final(void* ctx, u8 *out)
+static void sha1_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct sha1_ctx *sctx = ctx;
+	struct sha1_ctx *sctx = crypto_tfm_ctx(tfm);
 	__be32 *dst = (__be32 *)out;
 	u32 i, index, padlen;
 	__be64 bits;
@@ -93,10 +94,10 @@
 	/* Pad out to 56 mod 64 */
 	index = sctx->count & 0x3f;
 	padlen = (index < 56) ? (56 - index) : ((64+56) - index);
-	sha1_update(sctx, padding, padlen);
+	sha1_update(tfm, padding, padlen);
 
 	/* Append length */
-	sha1_update(sctx, (const u8 *)&bits, sizeof(bits));
+	sha1_update(tfm, (const u8 *)&bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 5; i++)
@@ -112,6 +113,7 @@
 	.cra_blocksize	=	SHA1_HMAC_BLOCK_SIZE,
 	.cra_ctxsize	=	sizeof(struct sha1_ctx),
 	.cra_module	=	THIS_MODULE,
+	.cra_alignmask	=	3,
 	.cra_list       =       LIST_HEAD_INIT(alg.cra_list),
 	.cra_u		=	{ .digest = {
 	.dia_digestsize	=	SHA1_DIGEST_SIZE,
diff --git a/crypto/sha256.c b/crypto/sha256.c
index 9d5ef67..bc71d85 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -230,9 +230,9 @@
 	memset(W, 0, 64 * sizeof(u32));
 }
 
-static void sha256_init(void *ctx)
+static void sha256_init(struct crypto_tfm *tfm)
 {
-	struct sha256_ctx *sctx = ctx;
+	struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
 	sctx->state[0] = H0;
 	sctx->state[1] = H1;
 	sctx->state[2] = H2;
@@ -242,12 +242,12 @@
 	sctx->state[6] = H6;
 	sctx->state[7] = H7;
 	sctx->count[0] = sctx->count[1] = 0;
-	memset(sctx->buf, 0, sizeof(sctx->buf));
 }
 
-static void sha256_update(void *ctx, const u8 *data, unsigned int len)
+static void sha256_update(struct crypto_tfm *tfm, const u8 *data,
+			  unsigned int len)
 {
-	struct sha256_ctx *sctx = ctx;
+	struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
 	unsigned int i, index, part_len;
 
 	/* Compute number of bytes mod 128 */
@@ -277,9 +277,9 @@
 	memcpy(&sctx->buf[index], &data[i], len-i);
 }
 
-static void sha256_final(void* ctx, u8 *out)
+static void sha256_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct sha256_ctx *sctx = ctx;
+	struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
 	__be32 *dst = (__be32 *)out;
 	__be32 bits[2];
 	unsigned int index, pad_len;
@@ -293,10 +293,10 @@
 	/* Pad out to 56 mod 64. */
 	index = (sctx->count[0] >> 3) & 0x3f;
 	pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
-	sha256_update(sctx, padding, pad_len);
+	sha256_update(tfm, padding, pad_len);
 
 	/* Append length (before padding) */
-	sha256_update(sctx, (const u8 *)bits, sizeof(bits));
+	sha256_update(tfm, (const u8 *)bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 8; i++)
@@ -313,6 +313,7 @@
 	.cra_blocksize	=	SHA256_HMAC_BLOCK_SIZE,
 	.cra_ctxsize	=	sizeof(struct sha256_ctx),
 	.cra_module	=	THIS_MODULE,
+	.cra_alignmask	=	3,
 	.cra_list       =       LIST_HEAD_INIT(alg.cra_list),
 	.cra_u		=	{ .digest = {
 	.dia_digestsize	=	SHA256_DIGEST_SIZE,
diff --git a/crypto/sha512.c b/crypto/sha512.c
index 3e6e939..2dfe7f1 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -161,9 +161,9 @@
 }
 
 static void
-sha512_init(void *ctx)
+sha512_init(struct crypto_tfm *tfm)
 {
-        struct sha512_ctx *sctx = ctx;
+	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
 	sctx->state[0] = H0;
 	sctx->state[1] = H1;
 	sctx->state[2] = H2;
@@ -173,13 +173,12 @@
 	sctx->state[6] = H6;
 	sctx->state[7] = H7;
 	sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
-	memset(sctx->buf, 0, sizeof(sctx->buf));
 }
 
 static void
-sha384_init(void *ctx)
+sha384_init(struct crypto_tfm *tfm)
 {
-        struct sha512_ctx *sctx = ctx;
+	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
         sctx->state[0] = HP0;
         sctx->state[1] = HP1;
         sctx->state[2] = HP2;
@@ -189,13 +188,12 @@
         sctx->state[6] = HP6;
         sctx->state[7] = HP7;
         sctx->count[0] = sctx->count[1] = sctx->count[2] = sctx->count[3] = 0;
-        memset(sctx->buf, 0, sizeof(sctx->buf));
 }
 
 static void
-sha512_update(void *ctx, const u8 *data, unsigned int len)
+sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
 {
-        struct sha512_ctx *sctx = ctx;
+	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
 
 	unsigned int i, index, part_len;
 
@@ -233,9 +231,9 @@
 }
 
 static void
-sha512_final(void *ctx, u8 *hash)
+sha512_final(struct crypto_tfm *tfm, u8 *hash)
 {
-        struct sha512_ctx *sctx = ctx;
+	struct sha512_ctx *sctx = crypto_tfm_ctx(tfm);
         static u8 padding[128] = { 0x80, };
 	__be64 *dst = (__be64 *)hash;
 	__be32 bits[4];
@@ -251,10 +249,10 @@
 	/* Pad out to 112 mod 128. */
 	index = (sctx->count[0] >> 3) & 0x7f;
 	pad_len = (index < 112) ? (112 - index) : ((128+112) - index);
-	sha512_update(sctx, padding, pad_len);
+	sha512_update(tfm, padding, pad_len);
 
 	/* Append length (before padding) */
-	sha512_update(sctx, (const u8 *)bits, sizeof(bits));
+	sha512_update(tfm, (const u8 *)bits, sizeof(bits));
 
 	/* Store state in digest */
 	for (i = 0; i < 8; i++)
@@ -264,12 +262,11 @@
 	memset(sctx, 0, sizeof(struct sha512_ctx));
 }
 
-static void sha384_final(void *ctx, u8 *hash)
+static void sha384_final(struct crypto_tfm *tfm, u8 *hash)
 {
-        struct sha512_ctx *sctx = ctx;
         u8 D[64];
 
-        sha512_final(sctx, D);
+	sha512_final(tfm, D);
 
         memcpy(hash, D, 48);
         memset(D, 0, 64);
@@ -281,6 +278,7 @@
         .cra_blocksize  = SHA512_HMAC_BLOCK_SIZE,
         .cra_ctxsize    = sizeof(struct sha512_ctx),
         .cra_module     = THIS_MODULE,
+	.cra_alignmask	= 3,
         .cra_list       = LIST_HEAD_INIT(sha512.cra_list),
         .cra_u          = { .digest = {
                                 .dia_digestsize = SHA512_DIGEST_SIZE,
@@ -295,6 +293,7 @@
         .cra_flags      = CRYPTO_ALG_TYPE_DIGEST,
         .cra_blocksize  = SHA384_HMAC_BLOCK_SIZE,
         .cra_ctxsize    = sizeof(struct sha512_ctx),
+	.cra_alignmask	= 3,
         .cra_module     = THIS_MODULE,
         .cra_list       = LIST_HEAD_INIT(sha384.cra_list),
         .cra_u          = { .digest = {
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 49e344f..e52f56c 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -570,6 +570,122 @@
 	crypto_free_tfm(tfm);
 }
 
+static void test_digest_jiffies(struct crypto_tfm *tfm, char *p, int blen,
+				int plen, char *out, int sec)
+{
+	struct scatterlist sg[1];
+	unsigned long start, end;
+	int bcount, pcount;
+
+	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	     time_before(jiffies, end); bcount++) {
+		crypto_digest_init(tfm);
+		for (pcount = 0; pcount < blen; pcount += plen) {
+			sg_set_buf(sg, p + pcount, plen);
+			crypto_digest_update(tfm, sg, 1);
+		}
+		/* we assume there is enough space in 'out' for the result */
+		crypto_digest_final(tfm, out);
+	}
+
+	printk("%6u opers/sec, %9lu bytes/sec\n",
+	       bcount / sec, ((long)bcount * blen) / sec);
+
+	return;
+}
+
+static void test_digest_cycles(struct crypto_tfm *tfm, char *p, int blen,
+			       int plen, char *out)
+{
+	struct scatterlist sg[1];
+	unsigned long cycles = 0;
+	int i, pcount;
+
+	local_bh_disable();
+	local_irq_disable();
+
+	/* Warm-up run. */
+	for (i = 0; i < 4; i++) {
+		crypto_digest_init(tfm);
+		for (pcount = 0; pcount < blen; pcount += plen) {
+			sg_set_buf(sg, p + pcount, plen);
+			crypto_digest_update(tfm, sg, 1);
+		}
+		crypto_digest_final(tfm, out);
+	}
+
+	/* The real thing. */
+	for (i = 0; i < 8; i++) {
+		cycles_t start, end;
+
+		crypto_digest_init(tfm);
+
+		start = get_cycles();
+
+		for (pcount = 0; pcount < blen; pcount += plen) {
+			sg_set_buf(sg, p + pcount, plen);
+			crypto_digest_update(tfm, sg, 1);
+		}
+		crypto_digest_final(tfm, out);
+
+		end = get_cycles();
+
+		cycles += end - start;
+	}
+
+	local_irq_enable();
+	local_bh_enable();
+
+	printk("%6lu cycles/operation, %4lu cycles/byte\n",
+	       cycles / 8, cycles / (8 * blen));
+
+	return;
+}
+
+static void test_digest_speed(char *algo, unsigned int sec,
+			      struct digest_speed *speed)
+{
+	struct crypto_tfm *tfm;
+	char output[1024];
+	int i;
+
+	printk("\ntesting speed of %s\n", algo);
+
+	tfm = crypto_alloc_tfm(algo, 0);
+
+	if (tfm == NULL) {
+		printk("failed to load transform for %s\n", algo);
+		return;
+	}
+
+	if (crypto_tfm_alg_digestsize(tfm) > sizeof(output)) {
+		printk("digestsize(%u) > outputbuffer(%zu)\n",
+		       crypto_tfm_alg_digestsize(tfm), sizeof(output));
+		goto out;
+	}
+
+	for (i = 0; speed[i].blen != 0; i++) {
+		if (speed[i].blen > TVMEMSIZE) {
+			printk("template (%u) too big for tvmem (%u)\n",
+			       speed[i].blen, TVMEMSIZE);
+			goto out;
+		}
+
+		printk("test%3u (%5u byte blocks,%5u bytes per update,%4u updates): ",
+		       i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen);
+
+		memset(tvmem, 0xff, speed[i].blen);
+
+		if (sec)
+			test_digest_jiffies(tfm, tvmem, speed[i].blen, speed[i].plen, output, sec);
+		else
+			test_digest_cycles(tfm, tvmem, speed[i].blen, speed[i].plen, output);
+	}
+
+out:
+	crypto_free_tfm(tfm);
+}
+
 static void test_deflate(void)
 {
 	unsigned int i;
@@ -1086,6 +1202,60 @@
 				  des_speed_template);
 		break;
 
+	case 300:
+		/* fall through */
+
+	case 301:
+		test_digest_speed("md4", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 302:
+		test_digest_speed("md5", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 303:
+		test_digest_speed("sha1", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 304:
+		test_digest_speed("sha256", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 305:
+		test_digest_speed("sha384", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 306:
+		test_digest_speed("sha512", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 307:
+		test_digest_speed("wp256", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 308:
+		test_digest_speed("wp384", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 309:
+		test_digest_speed("wp512", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 310:
+		test_digest_speed("tgr128", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 311:
+		test_digest_speed("tgr160", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 312:
+		test_digest_speed("tgr192", sec, generic_digest_speed_template);
+		if (mode > 300 && mode < 400) break;
+
+	case 399:
+		break;
+
 	case 1000:
 		test_available();
 		break;
@@ -1113,7 +1283,14 @@
 
 	kfree(xbuf);
 	kfree(tvmem);
-	return 0;
+
+	/* We intentionaly return -EAGAIN to prevent keeping
+	 * the module. It does all its work from init()
+	 * and doesn't offer any runtime functionality 
+	 * => we don't need it in the memory, do we?
+	 *                                        -- mludvig
+	 */
+	return -EAGAIN;
 }
 
 /*
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index 1f683ba..1fac560 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -65,6 +65,11 @@
 	unsigned int blen;
 };
 
+struct digest_speed {
+	unsigned int blen;	/* buffer length */
+	unsigned int plen;	/* per-update length */
+};
+
 /*
  * MD4 test vectors from RFC1320
  */
@@ -2975,4 +2980,35 @@
 	{  .klen = 0, .blen = 0, }
 };
 
+/*
+ * Digest speed tests
+ */
+static struct digest_speed generic_digest_speed_template[] = {
+	{ .blen = 16, 	.plen = 16, },
+	{ .blen = 64,	.plen = 16, },
+	{ .blen = 64,	.plen = 64, },
+	{ .blen = 256,	.plen = 16, },
+	{ .blen = 256,	.plen = 64, },
+	{ .blen = 256,	.plen = 256, },
+	{ .blen = 1024,	.plen = 16, },
+	{ .blen = 1024,	.plen = 256, },
+	{ .blen = 1024,	.plen = 1024, },
+	{ .blen = 2048,	.plen = 16, },
+	{ .blen = 2048,	.plen = 256, },
+	{ .blen = 2048,	.plen = 1024, },
+	{ .blen = 2048,	.plen = 2048, },
+	{ .blen = 4096,	.plen = 16, },
+	{ .blen = 4096,	.plen = 256, },
+	{ .blen = 4096,	.plen = 1024, },
+	{ .blen = 4096,	.plen = 4096, },
+	{ .blen = 8192,	.plen = 16, },
+	{ .blen = 8192,	.plen = 256, },
+	{ .blen = 8192,	.plen = 1024, },
+	{ .blen = 8192,	.plen = 4096, },
+	{ .blen = 8192,	.plen = 8192, },
+
+	/* End marker */
+	{  .blen = 0,	.plen = 0, }
+};
+
 #endif	/* _CRYPTO_TCRYPT_H */
diff --git a/crypto/tea.c b/crypto/tea.c
index a6a02b3..5367adc 100644
--- a/crypto/tea.c
+++ b/crypto/tea.c
@@ -45,10 +45,10 @@
 	u32 KEY[4];
 };
 
-static int tea_setkey(void *ctx_arg, const u8 *in_key,
-                       unsigned int key_len, u32 *flags)
-{ 
-	struct tea_ctx *ctx = ctx_arg;
+static int tea_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+		      unsigned int key_len, u32 *flags)
+{
+	struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *key = (const __le32 *)in_key;
 	
 	if (key_len != 16)
@@ -66,12 +66,11 @@
 
 }
 
-static void tea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
-{ 
+static void tea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
 	u32 y, z, n, sum = 0;
 	u32 k0, k1, k2, k3;
-
-	struct tea_ctx *ctx = ctx_arg;
+	struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *in = (const __le32 *)src;
 	__le32 *out = (__le32 *)dst;
 
@@ -95,11 +94,11 @@
 	out[1] = cpu_to_le32(z);
 }
 
-static void tea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
-{ 
+static void tea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
 	u32 y, z, n, sum;
 	u32 k0, k1, k2, k3;
-	struct tea_ctx *ctx = ctx_arg;
+	struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *in = (const __le32 *)src;
 	__le32 *out = (__le32 *)dst;
 
@@ -125,10 +124,10 @@
 	out[1] = cpu_to_le32(z);
 }
 
-static int xtea_setkey(void *ctx_arg, const u8 *in_key,
-                       unsigned int key_len, u32 *flags)
-{ 
-	struct xtea_ctx *ctx = ctx_arg;
+static int xtea_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len, u32 *flags)
+{
+	struct xtea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *key = (const __le32 *)in_key;
 	
 	if (key_len != 16)
@@ -146,12 +145,11 @@
 
 }
 
-static void xtea_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
-{ 
+static void xtea_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
 	u32 y, z, sum = 0;
 	u32 limit = XTEA_DELTA * XTEA_ROUNDS;
-
-	struct xtea_ctx *ctx = ctx_arg;
+	struct xtea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *in = (const __le32 *)src;
 	__le32 *out = (__le32 *)dst;
 
@@ -168,10 +166,10 @@
 	out[1] = cpu_to_le32(z);
 }
 
-static void xtea_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
-{ 
+static void xtea_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
 	u32 y, z, sum;
-	struct tea_ctx *ctx = ctx_arg;
+	struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *in = (const __le32 *)src;
 	__le32 *out = (__le32 *)dst;
 
@@ -191,12 +189,11 @@
 }
 
 
-static void xeta_encrypt(void *ctx_arg, u8 *dst, const u8 *src)
-{ 
+static void xeta_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
 	u32 y, z, sum = 0;
 	u32 limit = XTEA_DELTA * XTEA_ROUNDS;
-
-	struct xtea_ctx *ctx = ctx_arg;
+	struct xtea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *in = (const __le32 *)src;
 	__le32 *out = (__le32 *)dst;
 
@@ -213,10 +210,10 @@
 	out[1] = cpu_to_le32(z);
 }
 
-static void xeta_decrypt(void *ctx_arg, u8 *dst, const u8 *src)
-{ 
+static void xeta_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+{
 	u32 y, z, sum;
-	struct tea_ctx *ctx = ctx_arg;
+	struct tea_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *in = (const __le32 *)src;
 	__le32 *out = (__le32 *)dst;
 
diff --git a/crypto/tgr192.c b/crypto/tgr192.c
index 2d8e44f..a0fadf3 100644
--- a/crypto/tgr192.c
+++ b/crypto/tgr192.c
@@ -496,11 +496,10 @@
 	tctx->c = c;
 }
 
-static void tgr192_init(void *ctx)
+static void tgr192_init(struct crypto_tfm *tfm)
 {
-	struct tgr192_ctx *tctx = ctx;
+	struct tgr192_ctx *tctx = crypto_tfm_ctx(tfm);
 
-	memset (tctx->hash, 0, 64);
 	tctx->a = 0x0123456789abcdefULL;
 	tctx->b = 0xfedcba9876543210ULL;
 	tctx->c = 0xf096a5b4c3b2e187ULL;
@@ -511,9 +510,10 @@
 
 /* Update the message digest with the contents
  * of INBUF with length INLEN. */
-static void tgr192_update(void *ctx, const u8 * inbuf, unsigned int len)
+static void tgr192_update(struct crypto_tfm *tfm, const u8 *inbuf,
+			  unsigned int len)
 {
-	struct tgr192_ctx *tctx = ctx;
+	struct tgr192_ctx *tctx = crypto_tfm_ctx(tfm);
 
 	if (tctx->count == 64) {	/* flush the buffer */
 		tgr192_transform(tctx, tctx->hash);
@@ -527,7 +527,7 @@
 		for (; len && tctx->count < 64; len--) {
 			tctx->hash[tctx->count++] = *inbuf++;
 		}
-		tgr192_update(tctx, NULL, 0);
+		tgr192_update(tfm, NULL, 0);
 		if (!len) {
 			return;
 		}
@@ -549,15 +549,15 @@
 
 
 /* The routine terminates the computation */
-static void tgr192_final(void *ctx, u8 * out)
+static void tgr192_final(struct crypto_tfm *tfm, u8 * out)
 {
-	struct tgr192_ctx *tctx = ctx;
+	struct tgr192_ctx *tctx = crypto_tfm_ctx(tfm);
 	__be64 *dst = (__be64 *)out;
 	__be64 *be64p;
 	__le32 *le32p;
 	u32 t, msb, lsb;
 
-	tgr192_update(tctx, NULL, 0); /* flush */ ;
+	tgr192_update(tfm, NULL, 0); /* flush */ ;
 
 	msb = 0;
 	t = tctx->nblocks;
@@ -585,7 +585,7 @@
 		while (tctx->count < 64) {
 			tctx->hash[tctx->count++] = 0;
 		}
-		tgr192_update(tctx, NULL, 0); /* flush */ ;
+		tgr192_update(tfm, NULL, 0); /* flush */ ;
 		memset(tctx->hash, 0, 56);    /* fill next block with zeroes */
 	}
 	/* append the 64 bit count */
@@ -601,22 +601,20 @@
 	dst[2] = be64p[2] = cpu_to_be64(tctx->c);
 }
 
-static void tgr160_final(void *ctx, u8 * out)
+static void tgr160_final(struct crypto_tfm *tfm, u8 * out)
 {
-	struct tgr192_ctx *wctx = ctx;
 	u8 D[64];
 
-	tgr192_final(wctx, D);
+	tgr192_final(tfm, D);
 	memcpy(out, D, TGR160_DIGEST_SIZE);
 	memset(D, 0, TGR192_DIGEST_SIZE);
 }
 
-static void tgr128_final(void *ctx, u8 * out)
+static void tgr128_final(struct crypto_tfm *tfm, u8 * out)
 {
-	struct tgr192_ctx *wctx = ctx;
 	u8 D[64];
 
-	tgr192_final(wctx, D);
+	tgr192_final(tfm, D);
 	memcpy(out, D, TGR128_DIGEST_SIZE);
 	memset(D, 0, TGR192_DIGEST_SIZE);
 }
@@ -627,6 +625,7 @@
 	.cra_blocksize = TGR192_BLOCK_SIZE,
 	.cra_ctxsize = sizeof(struct tgr192_ctx),
 	.cra_module = THIS_MODULE,
+	.cra_alignmask = 7,
 	.cra_list = LIST_HEAD_INIT(tgr192.cra_list),
 	.cra_u = {.digest = {
 			     .dia_digestsize = TGR192_DIGEST_SIZE,
@@ -641,6 +640,7 @@
 	.cra_blocksize = TGR192_BLOCK_SIZE,
 	.cra_ctxsize = sizeof(struct tgr192_ctx),
 	.cra_module = THIS_MODULE,
+	.cra_alignmask = 7,
 	.cra_list = LIST_HEAD_INIT(tgr160.cra_list),
 	.cra_u = {.digest = {
 			     .dia_digestsize = TGR160_DIGEST_SIZE,
@@ -655,6 +655,7 @@
 	.cra_blocksize = TGR192_BLOCK_SIZE,
 	.cra_ctxsize = sizeof(struct tgr192_ctx),
 	.cra_module = THIS_MODULE,
+	.cra_alignmask = 7,
 	.cra_list = LIST_HEAD_INIT(tgr128.cra_list),
 	.cra_u = {.digest = {
 			     .dia_digestsize = TGR128_DIGEST_SIZE,
diff --git a/crypto/twofish.c b/crypto/twofish.c
index ddfd5a3..ec24882 100644
--- a/crypto/twofish.c
+++ b/crypto/twofish.c
@@ -643,11 +643,11 @@
 };
 
 /* Perform the key setup. */
-static int twofish_setkey(void *cx, const u8 *key,
-                          unsigned int key_len, u32 *flags)
+static int twofish_setkey(struct crypto_tfm *tfm, const u8 *key,
+			  unsigned int key_len, u32 *flags)
 {
 	
-	struct twofish_ctx *ctx = cx;
+	struct twofish_ctx *ctx = crypto_tfm_ctx(tfm);
 
 	int i, j, k;
 
@@ -802,9 +802,9 @@
 }
 
 /* Encrypt one block.  in and out may be the same. */
-static void twofish_encrypt(void *cx, u8 *out, const u8 *in)
+static void twofish_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct twofish_ctx *ctx = cx;
+	struct twofish_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *src = (const __le32 *)in;
 	__le32 *dst = (__le32 *)out;
 
@@ -839,9 +839,9 @@
 }
 
 /* Decrypt one block.  in and out may be the same. */
-static void twofish_decrypt(void *cx, u8 *out, const u8 *in)
+static void twofish_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct twofish_ctx *ctx = cx;
+	struct twofish_ctx *ctx = crypto_tfm_ctx(tfm);
 	const __le32 *src = (const __le32 *)in;
 	__le32 *dst = (__le32 *)out;
   
diff --git a/crypto/wp512.c b/crypto/wp512.c
index b226a12..727d05a 100644
--- a/crypto/wp512.c
+++ b/crypto/wp512.c
@@ -981,9 +981,9 @@
 
 }
 
-static void wp512_init (void *ctx) {
+static void wp512_init(struct crypto_tfm *tfm) {
+	struct wp512_ctx *wctx = crypto_tfm_ctx(tfm);
 	int i;
-	struct wp512_ctx *wctx = ctx;
 
 	memset(wctx->bitLength, 0, 32);
 	wctx->bufferBits = wctx->bufferPos = 0;
@@ -993,10 +993,10 @@
 	}
 }
 
-static void wp512_update(void *ctx, const u8 *source, unsigned int len)
+static void wp512_update(struct crypto_tfm *tfm, const u8 *source,
+			 unsigned int len)
 {
-
-	struct wp512_ctx *wctx = ctx;
+	struct wp512_ctx *wctx = crypto_tfm_ctx(tfm);
 	int sourcePos    = 0;
 	unsigned int bits_len = len * 8; // convert to number of bits
 	int sourceGap    = (8 - ((int)bits_len & 7)) & 7;
@@ -1054,9 +1054,9 @@
 
 }
 
-static void wp512_final(void *ctx, u8 *out)
+static void wp512_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct wp512_ctx *wctx = ctx;
+	struct wp512_ctx *wctx = crypto_tfm_ctx(tfm);
 	int i;
    	u8 *buffer      = wctx->buffer;
    	u8 *bitLength   = wctx->bitLength;
@@ -1087,22 +1087,20 @@
    	wctx->bufferPos    = bufferPos;
 }
 
-static void wp384_final(void *ctx, u8 *out)
+static void wp384_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct wp512_ctx *wctx = ctx;
 	u8 D[64];
 
-	wp512_final (wctx, D);
+	wp512_final(tfm, D);
 	memcpy (out, D, WP384_DIGEST_SIZE);
 	memset (D, 0, WP512_DIGEST_SIZE);
 }
 
-static void wp256_final(void *ctx, u8 *out)
+static void wp256_final(struct crypto_tfm *tfm, u8 *out)
 {
-	struct wp512_ctx *wctx = ctx;
 	u8 D[64];
 
-	wp512_final (wctx, D);
+	wp512_final(tfm, D);
 	memcpy (out, D, WP256_DIGEST_SIZE);
 	memset (D, 0, WP512_DIGEST_SIZE);
 }
diff --git a/drivers/Kconfig b/drivers/Kconfig
index aeb5ab2..8b11ceb 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -72,4 +72,6 @@
 
 source "drivers/rtc/Kconfig"
 
+source "drivers/dma/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 447d8e6..fc2d744 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -74,3 +74,5 @@
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
 obj-$(CONFIG_SUPERH)		+= sh/
+obj-$(CONFIG_GENERIC_TIME)	+= clocksource/
+obj-$(CONFIG_DMA_ENGINE)	+= dma/
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index c24652d..610d2cc 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -10,9 +10,8 @@
 config ACPI
 	bool "ACPI Support"
 	depends on IA64 || X86
+	depends on PCI
 	select PM
-	select PCI
-
 	default y
 	---help---
 	  Advanced Configuration and Power Interface (ACPI) support for 
@@ -162,7 +161,7 @@
 config ACPI_NUMA
 	bool "NUMA support"
 	depends on NUMA
-	depends on (IA64 || X86_64)
+	depends on (X86 || IA64)
 	default y if IA64_GENERIC || IA64_SGI_SN2
 
 config ACPI_ASUS
@@ -329,7 +328,7 @@
 config ACPI_HOTPLUG_MEMORY
 	tristate "Memory Hotplug"
 	depends on ACPI
-	depends on MEMORY_HOTPLUG || X86_64
+	depends on MEMORY_HOTPLUG
 	default n
 	help
 	  This driver adds supports for ACPI Memory Hotplug.  This driver
diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index d882bf8..1012284 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -57,6 +57,7 @@
 
 static int acpi_memory_device_add(struct acpi_device *device);
 static int acpi_memory_device_remove(struct acpi_device *device, int type);
+static int acpi_memory_device_start(struct acpi_device *device);
 
 static struct acpi_driver acpi_memory_device_driver = {
 	.name = ACPI_MEMORY_DEVICE_DRIVER_NAME,
@@ -65,49 +66,79 @@
 	.ops = {
 		.add = acpi_memory_device_add,
 		.remove = acpi_memory_device_remove,
+		.start = acpi_memory_device_start,
 		},
 };
 
+struct acpi_memory_info {
+	struct list_head list;
+	u64 start_addr;		/* Memory Range start physical addr */
+	u64 length;		/* Memory Range length */
+	unsigned short caching;	/* memory cache attribute */
+	unsigned short write_protect;	/* memory read/write attribute */
+	unsigned int enabled:1;
+};
+
 struct acpi_memory_device {
 	acpi_handle handle;
 	unsigned int state;	/* State of the memory device */
-	unsigned short caching;	/* memory cache attribute */
-	unsigned short write_protect;	/* memory read/write attribute */
-	u64 start_addr;		/* Memory Range start physical addr */
-	u64 end_addr;		/* Memory Range end physical addr */
+	struct list_head res_list;
 };
 
+static acpi_status
+acpi_memory_get_resource(struct acpi_resource *resource, void *context)
+{
+	struct acpi_memory_device *mem_device = context;
+	struct acpi_resource_address64 address64;
+	struct acpi_memory_info *info, *new;
+	acpi_status status;
+
+	status = acpi_resource_to_address64(resource, &address64);
+	if (ACPI_FAILURE(status) ||
+	    (address64.resource_type != ACPI_MEMORY_RANGE))
+		return AE_OK;
+
+	list_for_each_entry(info, &mem_device->res_list, list) {
+		/* Can we combine the resource range information? */
+		if ((info->caching == address64.info.mem.caching) &&
+		    (info->write_protect == address64.info.mem.write_protect) &&
+		    (info->start_addr + info->length == address64.minimum)) {
+			info->length += address64.address_length;
+			return AE_OK;
+		}
+	}
+
+	new = kzalloc(sizeof(struct acpi_memory_info), GFP_KERNEL);
+	if (!new)
+		return AE_ERROR;
+
+	INIT_LIST_HEAD(&new->list);
+	new->caching = address64.info.mem.caching;
+	new->write_protect = address64.info.mem.write_protect;
+	new->start_addr = address64.minimum;
+	new->length = address64.address_length;
+	list_add_tail(&new->list, &mem_device->res_list);
+
+	return AE_OK;
+}
+
 static int
 acpi_memory_get_device_resources(struct acpi_memory_device *mem_device)
 {
 	acpi_status status;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-	struct acpi_resource *resource = NULL;
-	struct acpi_resource_address64 address64;
+	struct acpi_memory_info *info, *n;
 
 	ACPI_FUNCTION_TRACE("acpi_memory_get_device_resources");
 
-	/* Get the range from the _CRS */
-	status = acpi_get_current_resources(mem_device->handle, &buffer);
-	if (ACPI_FAILURE(status))
-		return_VALUE(-EINVAL);
-
-	resource = (struct acpi_resource *)buffer.pointer;
-	status = acpi_resource_to_address64(resource, &address64);
-	if (ACPI_SUCCESS(status)) {
-		if (address64.resource_type == ACPI_MEMORY_RANGE) {
-			/* Populate the structure */
-			mem_device->caching =
-			    address64.info.mem.caching;
-			mem_device->write_protect =
-			    address64.info.mem.write_protect;
-			mem_device->start_addr = address64.minimum;
-			mem_device->end_addr = address64.maximum;
-		}
+	status = acpi_walk_resources(mem_device->handle, METHOD_NAME__CRS,
+				     acpi_memory_get_resource, mem_device);
+	if (ACPI_FAILURE(status)) {
+		list_for_each_entry_safe(info, n, &mem_device->res_list, list)
+			kfree(info);
+		return -EINVAL;
 	}
 
-	acpi_os_free(buffer.pointer);
-	return_VALUE(0);
+	return 0;
 }
 
 static int
@@ -182,7 +213,9 @@
 
 static int acpi_memory_enable_device(struct acpi_memory_device *mem_device)
 {
-	int result;
+	int result, num_enabled = 0;
+	struct acpi_memory_info *info;
+	int node;
 
 	ACPI_FUNCTION_TRACE("acpi_memory_enable_device");
 
@@ -195,16 +228,35 @@
 		return result;
 	}
 
+	node = acpi_get_node(mem_device->handle);
 	/*
 	 * Tell the VM there is more memory here...
 	 * Note: Assume that this function returns zero on success
+	 * We don't have memory-hot-add rollback function,now.
+	 * (i.e. memory-hot-remove function)
 	 */
-	result = add_memory(mem_device->start_addr,
-			    (mem_device->end_addr - mem_device->start_addr) + 1);
-	if (result) {
+	list_for_each_entry(info, &mem_device->res_list, list) {
+		u64 start_pfn, end_pfn;
+
+		start_pfn = info->start_addr >> PAGE_SHIFT;
+		end_pfn = (info->start_addr + info->length - 1) >> PAGE_SHIFT;
+
+		if (pfn_valid(start_pfn) || pfn_valid(end_pfn)) {
+			/* already enabled. try next area */
+			num_enabled++;
+			continue;
+		}
+
+		result = add_memory(node, info->start_addr, info->length);
+		if (result)
+			continue;
+		info->enabled = 1;
+		num_enabled++;
+	}
+	if (!num_enabled) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "\nadd_memory failed\n"));
 		mem_device->state = MEMORY_INVALID_STATE;
-		return result;
+		return -EINVAL;
 	}
 
 	return result;
@@ -248,8 +300,7 @@
 static int acpi_memory_disable_device(struct acpi_memory_device *mem_device)
 {
 	int result;
-	u64 start = mem_device->start_addr;
-	u64 len = mem_device->end_addr - start + 1;
+	struct acpi_memory_info *info, *n;
 
 	ACPI_FUNCTION_TRACE("acpi_memory_disable_device");
 
@@ -257,10 +308,13 @@
 	 * Ask the VM to offline this memory range.
 	 * Note: Assume that this function returns zero on success
 	 */
-	result = remove_memory(start, len);
-	if (result) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Hot-Remove failed.\n"));
-		return_VALUE(result);
+	list_for_each_entry_safe(info, n, &mem_device->res_list, list) {
+		if (info->enabled) {
+			result = remove_memory(info->start_addr, info->length);
+			if (result)
+				return result;
+		}
+		kfree(info);
 	}
 
 	/* Power-off and eject the device */
@@ -358,6 +412,7 @@
 		return_VALUE(-ENOMEM);
 	memset(mem_device, 0, sizeof(struct acpi_memory_device));
 
+	INIT_LIST_HEAD(&mem_device->res_list);
 	mem_device->handle = device->handle;
 	sprintf(acpi_device_name(device), "%s", ACPI_MEMORY_DEVICE_NAME);
 	sprintf(acpi_device_class(device), "%s", ACPI_MEMORY_DEVICE_CLASS);
@@ -393,6 +448,25 @@
 	return_VALUE(0);
 }
 
+static int acpi_memory_device_start (struct acpi_device *device)
+{
+	struct acpi_memory_device *mem_device;
+	int result = 0;
+
+	ACPI_FUNCTION_TRACE("acpi_memory_device_start");
+
+	mem_device = acpi_driver_data(device);
+
+	if (!acpi_memory_check_device(mem_device)) {
+		/* call add_memory func */
+		result = acpi_memory_enable_device(mem_device);
+		if (result)
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				"Error in acpi_memory_enable_device\n"));
+	}
+	return_VALUE(result);
+}
+
 /*
  * Helper function to check for memory device
  */
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index f4c8775..839f423 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -817,7 +817,7 @@
 			      unsigned long count, void *data);
 
 static int
-__init asus_proc_add(char *name, proc_writefunc * writefunc,
+asus_proc_add(char *name, proc_writefunc * writefunc,
 		     proc_readfunc * readfunc, mode_t mode,
 		     struct acpi_device *device)
 {
@@ -836,7 +836,7 @@
 	return 0;
 }
 
-static int __init asus_hotk_add_fs(struct acpi_device *device)
+static int asus_hotk_add_fs(struct acpi_device *device)
 {
 	struct proc_dir_entry *proc;
 	mode_t mode;
@@ -954,7 +954,7 @@
  * This function is used to initialize the hotk with right values. In this
  * method, we can make all the detection we want, and modify the hotk struct
  */
-static int __init asus_hotk_get_info(void)
+static int asus_hotk_get_info(void)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -970,7 +970,7 @@
 	 * HID), this bit will be moved. A global variable asus_info contains
 	 * the DSDT header.
 	 */
-	status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
+	status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt);
 	if (ACPI_FAILURE(status))
 		printk(KERN_WARNING "  Couldn't get the DSDT table header\n");
 	else
@@ -1101,7 +1101,7 @@
 	return AE_OK;
 }
 
-static int __init asus_hotk_check(void)
+static int asus_hotk_check(void)
 {
 	int result = 0;
 
@@ -1119,7 +1119,9 @@
 	return result;
 }
 
-static int __init asus_hotk_add(struct acpi_device *device)
+static int asus_hotk_found;
+
+static int asus_hotk_add(struct acpi_device *device)
 {
 	acpi_status status = AE_OK;
 	int result;
@@ -1180,6 +1182,8 @@
 		}
 	}
 
+	asus_hotk_found = 1;
+
       end:
 	if (result) {
 		kfree(hotk);
@@ -1226,12 +1230,24 @@
 	asus_proc_dir->owner = THIS_MODULE;
 
 	result = acpi_bus_register_driver(&asus_hotk_driver);
-	if (result < 1) {
-		acpi_bus_unregister_driver(&asus_hotk_driver);
+	if (result < 0) {
 		remove_proc_entry(PROC_ASUS, acpi_root_dir);
 		return -ENODEV;
 	}
 
+	/*
+	 * This is a bit of a kludge.  We only want this module loaded
+	 * for ASUS systems, but there's currently no way to probe the
+	 * ACPI namespace for ASUS HIDs.  So we just return failure if
+	 * we didn't find one, which will cause the module to be
+	 * unloaded.
+	 */
+	if (!asus_hotk_found) {
+		acpi_bus_unregister_driver(&asus_hotk_driver);
+		remove_proc_entry(PROC_ASUS, acpi_root_dir);
+		return result;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 606f873..dd3983c 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -43,7 +43,7 @@
 extern void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger);
 #endif
 
-FADT_DESCRIPTOR acpi_fadt;
+struct fadt_descriptor acpi_fadt;
 EXPORT_SYMBOL(acpi_fadt);
 
 struct acpi_device *acpi_root;
@@ -205,12 +205,14 @@
 	 * Get device's current power state if it's unknown
 	 * This means device power state isn't initialized or previous setting failed
 	 */
-	if (device->power.state == ACPI_STATE_UNKNOWN)
-		acpi_bus_get_power(device->handle, &device->power.state);
-	if (state == device->power.state) {
-		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
-				  state));
-		return_VALUE(0);
+	if (!device->flags.force_power_state) {
+		if (device->power.state == ACPI_STATE_UNKNOWN)
+			acpi_bus_get_power(device->handle, &device->power.state);
+		if (state == device->power.state) {
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device is already at D%d\n",
+					  state));
+			return_VALUE(0);
+		}
 	}
 	if (!device->power.states[state].flags.valid) {
 		ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Device does not support D%d\n",
@@ -596,6 +598,8 @@
 	if (acpi_disabled)
 		return_VOID;
 
+	printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION);
+
 	/* enable workarounds, unless strict ACPI spec. compliance */
 	if (!acpi_strict)
 		acpi_gbl_enable_interpreter_slack = TRUE;
@@ -617,7 +621,7 @@
 	/*
 	 * Get a separate copy of the FADT for use by other drivers.
 	 */
-	status = acpi_get_table(ACPI_TABLE_FADT, 1, &buffer);
+	status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &buffer);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_ERR PREFIX "Unable to get the FADT\n");
 		goto error0;
@@ -743,8 +747,6 @@
 
 	ACPI_FUNCTION_TRACE("acpi_init");
 
-	printk(KERN_INFO PREFIX "Subsystem revision %08x\n", ACPI_CA_VERSION);
-
 	if (acpi_disabled) {
 		printk(KERN_INFO PREFIX "Interpreter disabled.\n");
 		return_VALUE(-ENODEV);
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
index 76bc046..a6d77ef 100644
--- a/drivers/acpi/dispatcher/dsfield.c
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -87,7 +87,7 @@
 	union acpi_operand_object *second_desc = NULL;
 	u32 flags;
 
-	ACPI_FUNCTION_TRACE("ds_create_buffer_field");
+	ACPI_FUNCTION_TRACE(ds_create_buffer_field);
 
 	/* Get the name_string argument */
 
@@ -210,7 +210,7 @@
 	acpi_status status;
 	acpi_integer position;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_get_field_names", info);
+	ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info);
 
 	/* First field starts at bit zero */
 
@@ -342,7 +342,7 @@
 	union acpi_parse_object *arg;
 	struct acpi_create_field_info info;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_create_field", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_create_field, op);
 
 	/* First arg is the name of the parent op_region (must already exist) */
 
@@ -399,7 +399,7 @@
 	struct acpi_namespace_node *node;
 	u8 type = 0;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_init_field_objects", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
 
 	switch (walk_state->opcode) {
 	case AML_FIELD_OP:
@@ -425,6 +425,7 @@
 	 * Walk the list of entries in the field_list
 	 */
 	while (arg) {
+
 		/* Ignore OFFSET and ACCESSAS terms here */
 
 		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
@@ -481,7 +482,7 @@
 	union acpi_parse_object *arg;
 	struct acpi_create_field_info info;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_create_bank_field", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op);
 
 	/* First arg is the name of the parent op_region (must already exist) */
 
@@ -554,7 +555,7 @@
 	union acpi_parse_object *arg;
 	struct acpi_create_field_info info;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_create_index_field", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op);
 
 	/* First arg is the name of the Index register (must already exist) */
 
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
index e65a07a..bbdf990 100644
--- a/drivers/acpi/dispatcher/dsinit.c
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -184,7 +184,7 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Walk the namespace starting at "start_node" and perform any
+ * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any
  *              necessary initialization on the objects found therein
  *
  ******************************************************************************/
@@ -196,7 +196,7 @@
 	acpi_status status;
 	struct acpi_init_walk_info info;
 
-	ACPI_FUNCTION_TRACE("ds_initialize_objects");
+	ACPI_FUNCTION_TRACE(ds_initialize_objects);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 			  "**** Starting initialization of namespace objects ****\n"));
@@ -213,7 +213,7 @@
 	status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
 				     acpi_ds_init_one_object, &info, NULL);
 	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
+		ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
 	}
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index c475546..bc9aca4 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -81,6 +81,7 @@
 	/* Invoke the global exception handler */
 
 	if (acpi_gbl_exception_handler) {
+
 		/* Exit the interpreter, allow handler to execute methods */
 
 		acpi_ex_exit_interpreter();
@@ -100,6 +101,7 @@
 	}
 #ifdef ACPI_DISASSEMBLER
 	if (ACPI_FAILURE(status)) {
+
 		/* Display method locals/args if disassembler is present */
 
 		acpi_dm_dump_method_info(status, walk_state, walk_state->op);
@@ -132,7 +134,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node);
+	ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node);
 
 	if (!method_node) {
 		return_ACPI_STATUS(AE_NULL_ENTRY);
@@ -168,11 +170,14 @@
 
 		/*
 		 * Get a unit from the method semaphore. This releases the
-		 * interpreter if we block
+		 * interpreter if we block (then reacquires it)
 		 */
 		status =
 		    acpi_ex_system_wait_semaphore(obj_desc->method.semaphore,
 						  ACPI_WAIT_FOREVER);
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
 	}
 
 	/*
@@ -183,7 +188,7 @@
 	if (!obj_desc->method.owner_id) {
 		status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id);
 		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
+			goto cleanup;
 		}
 	}
 
@@ -193,6 +198,14 @@
 	 */
 	obj_desc->method.thread_count++;
 	return_ACPI_STATUS(status);
+
+      cleanup:
+	/* On error, must signal the method semaphore if present */
+
+	if (obj_desc->method.semaphore) {
+		(void)acpi_os_signal_semaphore(obj_desc->method.semaphore, 1);
+	}
+	return_ACPI_STATUS(status);
 }
 
 /*******************************************************************************
@@ -218,10 +231,10 @@
 	struct acpi_namespace_node *method_node;
 	struct acpi_walk_state *next_walk_state = NULL;
 	union acpi_operand_object *obj_desc;
-	struct acpi_parameter_info info;
+	struct acpi_evaluate_info *info;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_call_control_method", this_walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 			  "Execute method %p, currentstate=%p\n",
@@ -240,25 +253,31 @@
 		return_ACPI_STATUS(AE_NULL_OBJECT);
 	}
 
-	/* Init for new method, wait on concurrency semaphore */
+	/* Init for new method, possibly wait on concurrency semaphore */
 
 	status = acpi_ds_begin_method_execution(method_node, obj_desc,
 						this_walk_state->method_node);
 	if (ACPI_FAILURE(status)) {
-		goto cleanup;
+		return_ACPI_STATUS(status);
 	}
 
+	/*
+	 * 1) Parse the method. All "normal" methods are parsed for each execution.
+	 * Internal methods (_OSI, etc.) do not require parsing.
+	 */
 	if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
-		/* 1) Parse: Create a new walk state for the preempting walk */
+
+		/* Create a new walk state for the parse */
 
 		next_walk_state =
 		    acpi_ds_create_walk_state(obj_desc->method.owner_id, op,
 					      obj_desc, NULL);
 		if (!next_walk_state) {
-			return_ACPI_STATUS(AE_NO_MEMORY);
+			status = AE_NO_MEMORY;
+			goto cleanup;
 		}
 
-		/* Create and init a Root Node */
+		/* Create and init a parse tree root */
 
 		op = acpi_ps_create_scope_op();
 		if (!op) {
@@ -271,17 +290,20 @@
 					       obj_desc->method.aml_length,
 					       NULL, 1);
 		if (ACPI_FAILURE(status)) {
-			acpi_ds_delete_walk_state(next_walk_state);
+			acpi_ps_delete_parse_tree(op);
 			goto cleanup;
 		}
 
-		/* Begin AML parse */
+		/* Begin AML parse (deletes next_walk_state) */
 
 		status = acpi_ps_parse_aml(next_walk_state);
 		acpi_ps_delete_parse_tree(op);
+		if (ACPI_FAILURE(status)) {
+			goto cleanup;
+		}
 	}
 
-	/* 2) Execute: Create a new state for the preempting walk */
+	/* 2) Begin method execution. Create a new walk state */
 
 	next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
 						    NULL, obj_desc, thread);
@@ -289,6 +311,7 @@
 		status = AE_NO_MEMORY;
 		goto cleanup;
 	}
+
 	/*
 	 * The resolved arguments were put on the previous walk state's operand
 	 * stack. Operands on the previous walk state stack always
@@ -296,12 +319,24 @@
 	 */
 	this_walk_state->operands[this_walk_state->num_operands] = NULL;
 
-	info.parameters = &this_walk_state->operands[0];
-	info.parameter_type = ACPI_PARAM_ARGS;
+	/*
+	 * Allocate and initialize the evaluation information block
+	 * TBD: this is somewhat inefficient, should change interface to
+	 * ds_init_aml_walk. For now, keeps this struct off the CPU stack
+	 */
+	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+	if (!info) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	info->parameters = &this_walk_state->operands[0];
+	info->parameter_type = ACPI_PARAM_ARGS;
 
 	status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
 				       obj_desc->method.aml_start,
-				       obj_desc->method.aml_length, &info, 3);
+				       obj_desc->method.aml_length, info, 3);
+
+	ACPI_FREE(info);
 	if (ACPI_FAILURE(status)) {
 		goto cleanup;
 	}
@@ -323,6 +358,8 @@
 			  "Starting nested execution, newstate=%p\n",
 			  next_walk_state));
 
+	/* Invoke an internal method if necessary */
+
 	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
 		status = obj_desc->method.implementation(next_walk_state);
 	}
@@ -330,16 +367,14 @@
 	return_ACPI_STATUS(status);
 
       cleanup:
-	/* Decrement the thread count on the method parse tree */
 
-	if (next_walk_state && (next_walk_state->method_desc)) {
-		next_walk_state->method_desc->method.thread_count--;
+	/* On error, we must terminate the method properly */
+
+	acpi_ds_terminate_control_method(obj_desc, next_walk_state);
+	if (next_walk_state) {
+		acpi_ds_delete_walk_state(next_walk_state);
 	}
 
-	/* On error, we must delete the new walk state */
-
-	acpi_ds_terminate_control_method(next_walk_state);
-	acpi_ds_delete_walk_state(next_walk_state);
 	return_ACPI_STATUS(status);
 }
 
@@ -362,25 +397,33 @@
 			       union acpi_operand_object *return_desc)
 {
 	acpi_status status;
+	int same_as_implicit_return;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_restart_control_method", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-			  "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
+			  "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n",
 			  (char *)&walk_state->method_node->name,
 			  walk_state->method_call_op, return_desc));
 
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-			  "    return_from_this_method_used?=%X res_stack %p Walk %p\n",
+			  "    ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n",
 			  walk_state->return_used,
 			  walk_state->results, walk_state));
 
 	/* Did the called method return a value? */
 
 	if (return_desc) {
+
+		/* Is the implicit return object the same as the return desc? */
+
+		same_as_implicit_return =
+		    (walk_state->implicit_return_obj == return_desc);
+
 		/* Are we actually going to use the return value? */
 
 		if (walk_state->return_used) {
+
 			/* Save the return value from the previous method */
 
 			status = acpi_ds_result_push(return_desc, walk_state);
@@ -397,18 +440,23 @@
 		}
 
 		/*
-		 * The following code is the
-		 * optional support for a so-called "implicit return". Some AML code
-		 * assumes that the last value of the method is "implicitly" returned
-		 * to the caller. Just save the last result as the return value.
+		 * The following code is the optional support for the so-called
+		 * "implicit return". Some AML code assumes that the last value of the
+		 * method is "implicitly" returned to the caller, in the absence of an
+		 * explicit return value.
+		 *
+		 * Just save the last result of the method as the return value.
+		 *
 		 * NOTE: this is optional because the ASL language does not actually
 		 * support this behavior.
 		 */
 		else if (!acpi_ds_do_implicit_return
-			 (return_desc, walk_state, FALSE)) {
+			 (return_desc, walk_state, FALSE)
+			 || same_as_implicit_return) {
 			/*
 			 * Delete the return value if it will not be used by the
-			 * calling method
+			 * calling method or remove one reference if the explicit return
+			 * is the same as the implicit return value.
 			 */
 			acpi_ut_remove_reference(return_desc);
 		}
@@ -421,7 +469,8 @@
  *
  * FUNCTION:    acpi_ds_terminate_control_method
  *
- * PARAMETERS:  walk_state          - State of the method
+ * PARAMETERS:  method_desc         - Method object
+ *              walk_state          - State associated with the method
  *
  * RETURN:      None
  *
@@ -431,95 +480,100 @@
  *
  ******************************************************************************/
 
-void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state)
+void
+acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
+				 struct acpi_walk_state *walk_state)
 {
-	union acpi_operand_object *obj_desc;
 	struct acpi_namespace_node *method_node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_terminate_control_method", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state);
 
-	if (!walk_state) {
+	/* method_desc is required, walk_state is optional */
+
+	if (!method_desc) {
 		return_VOID;
 	}
 
-	/* The current method object was saved in the walk state */
+	if (walk_state) {
 
-	obj_desc = walk_state->method_desc;
-	if (!obj_desc) {
-		return_VOID;
+		/* Delete all arguments and locals */
+
+		acpi_ds_method_data_delete_all(walk_state);
 	}
 
-	/* Delete all arguments and locals */
-
-	acpi_ds_method_data_delete_all(walk_state);
-
 	/*
 	 * Lock the parser while we terminate this method.
 	 * If this is the last thread executing the method,
 	 * we have additional cleanup to perform
 	 */
-	status = acpi_ut_acquire_mutex(ACPI_MTX_PARSER);
+	status = acpi_ut_acquire_mutex(ACPI_MTX_CONTROL_METHOD);
 	if (ACPI_FAILURE(status)) {
 		return_VOID;
 	}
 
 	/* Signal completion of the execution of this method if necessary */
 
-	if (walk_state->method_desc->method.semaphore) {
+	if (method_desc->method.semaphore) {
 		status =
-		    acpi_os_signal_semaphore(walk_state->method_desc->method.
-					     semaphore, 1);
+		    acpi_os_signal_semaphore(method_desc->method.semaphore, 1);
 		if (ACPI_FAILURE(status)) {
-			ACPI_ERROR((AE_INFO,
-				    "Could not signal method semaphore"));
 
-			/* Ignore error and continue cleanup */
+			/* Ignore error and continue */
+
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Could not signal method semaphore"));
 		}
 	}
 
-	/*
-	 * There are no more threads executing this method.  Perform
-	 * additional cleanup.
-	 *
-	 * The method Node is stored in the walk state
-	 */
-	method_node = walk_state->method_node;
+	if (walk_state) {
+		/*
+		 * Delete any objects created by this method during execution.
+		 * The method Node is stored in the walk state
+		 */
+		method_node = walk_state->method_node;
 
-	/* Lock namespace for possible update */
+		/* Lock namespace for possible update */
 
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		goto exit;
+		status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+		if (ACPI_FAILURE(status)) {
+			goto exit;
+		}
+
+		/*
+		 * Delete any namespace entries created immediately underneath
+		 * the method
+		 */
+		if (method_node && method_node->child) {
+			acpi_ns_delete_namespace_subtree(method_node);
+		}
+
+		/*
+		 * Delete any namespace entries created anywhere else within
+		 * the namespace by the execution of this method
+		 */
+		acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id);
+		status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	}
 
-	/*
-	 * Delete any namespace entries created immediately underneath
-	 * the method
-	 */
-	if (method_node->child) {
-		acpi_ns_delete_namespace_subtree(method_node);
-	}
+	/* Decrement the thread count on the method */
 
-	/*
-	 * Delete any namespace entries created anywhere else within
-	 * the namespace by the execution of this method
-	 */
-	acpi_ns_delete_namespace_by_owner(walk_state->method_desc->method.
-					  owner_id);
-	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	if (method_desc->method.thread_count) {
+		method_desc->method.thread_count--;
+	} else {
+		ACPI_ERROR((AE_INFO, "Invalid zero thread count in method"));
+	}
 
 	/* Are there any other threads currently executing this method? */
 
-	if (walk_state->method_desc->method.thread_count) {
+	if (method_desc->method.thread_count) {
 		/*
 		 * Additional threads. Do not release the owner_id in this case,
 		 * we immediately reuse it for the next thread executing this method
 		 */
 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 				  "*** Completed execution of one thread, %d threads remaining\n",
-				  walk_state->method_desc->method.
-				  thread_count));
+				  method_desc->method.thread_count));
 	} else {
 		/* This is the only executing thread for this method */
 
@@ -533,22 +587,20 @@
 		 * This code is here because we must wait until the last thread exits
 		 * before creating the synchronization semaphore.
 		 */
-		if ((walk_state->method_desc->method.concurrency == 1) &&
-		    (!walk_state->method_desc->method.semaphore)) {
+		if ((method_desc->method.concurrency == 1) &&
+		    (!method_desc->method.semaphore)) {
 			status = acpi_os_create_semaphore(1, 1,
-							  &walk_state->
-							  method_desc->method.
+							  &method_desc->method.
 							  semaphore);
 		}
 
 		/* No more threads, we can free the owner_id */
 
-		acpi_ut_release_owner_id(&walk_state->method_desc->method.
-					 owner_id);
+		acpi_ut_release_owner_id(&method_desc->method.owner_id);
 	}
 
       exit:
-	(void)acpi_ut_release_mutex(ACPI_MTX_PARSER);
+	(void)acpi_ut_release_mutex(ACPI_MTX_CONTROL_METHOD);
 	return_VOID;
 }
 
@@ -581,7 +633,7 @@
 	union acpi_parse_object *op;
 	struct acpi_walk_state *walk_state;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node);
+	ACPI_FUNCTION_TRACE_PTR(ds_parse_method, node);
 
 	/* Parameter Validation */
 
@@ -590,7 +642,7 @@
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-			  "**** Parsing [%4.4s] **** named_obj=%p\n",
+			  "**** Parsing [%4.4s] **** NamedObj=%p\n",
 			  acpi_ut_get_node_name(node), node));
 
 	/* Extract the method object from the method Node */
@@ -669,7 +721,7 @@
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-			  "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
+			  "**** [%4.4s] Parsed **** NamedObj=%p Op=%p\n",
 			  acpi_ut_get_node_name(node), node, op));
 
 	/*
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
index c025674..459160f 100644
--- a/drivers/acpi/dispatcher/dsmthdat.c
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -81,7 +81,7 @@
  *              special data types.
  *
  * NOTES:       walk_state fields are initialized to zero by the
- *              ACPI_MEM_CALLOCATE().
+ *              ACPI_ALLOCATE_ZEROED().
  *
  *              A pseudo-Namespace Node is assigned to each argument and local
  *              so that ref_of() can return a pointer to the Node.
@@ -92,7 +92,7 @@
 {
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ds_method_data_init");
+	ACPI_FUNCTION_TRACE(ds_method_data_init);
 
 	/* Init the method arguments */
 
@@ -100,10 +100,10 @@
 		ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
 				   NAMEOF_ARG_NTE);
 		walk_state->arguments[i].name.integer |= (i << 24);
-		walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED;
+		walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
 		walk_state->arguments[i].type = ACPI_TYPE_ANY;
-		walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST |
-		    ANOBJ_METHOD_ARG;
+		walk_state->arguments[i].flags =
+		    ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
 	}
 
 	/* Init the method locals */
@@ -113,11 +113,11 @@
 				   NAMEOF_LOCAL_NTE);
 
 		walk_state->local_variables[i].name.integer |= (i << 24);
-		walk_state->local_variables[i].descriptor =
+		walk_state->local_variables[i].descriptor_type =
 		    ACPI_DESC_TYPE_NAMED;
 		walk_state->local_variables[i].type = ACPI_TYPE_ANY;
-		walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST |
-		    ANOBJ_METHOD_LOCAL;
+		walk_state->local_variables[i].flags =
+		    ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
 	}
 
 	return_VOID;
@@ -140,7 +140,7 @@
 {
 	u32 index;
 
-	ACPI_FUNCTION_TRACE("ds_method_data_delete_all");
+	ACPI_FUNCTION_TRACE(ds_method_data_delete_all);
 
 	/* Detach the locals */
 
@@ -199,7 +199,7 @@
 	acpi_status status;
 	u32 index = 0;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_method_data_init_args", params);
+	ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params);
 
 	if (!params) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -251,7 +251,7 @@
 			     struct acpi_walk_state *walk_state,
 			     struct acpi_namespace_node **node)
 {
-	ACPI_FUNCTION_TRACE("ds_method_data_get_node");
+	ACPI_FUNCTION_TRACE(ds_method_data_get_node);
 
 	/*
 	 * Method Locals and Arguments are supported
@@ -318,10 +318,10 @@
 	acpi_status status;
 	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("ds_method_data_set_value");
+	ACPI_FUNCTION_TRACE(ds_method_data_set_value);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-			  "new_obj %p Opcode %X, Refs=%d [%s]\n", object,
+			  "NewObj %p Opcode %X, Refs=%d [%s]\n", object,
 			  opcode, object->common.reference_count,
 			  acpi_ut_get_type_name(object->common.type)));
 
@@ -336,7 +336,7 @@
 	 * Increment ref count so object can't be deleted while installed.
 	 * NOTE: We do not copy the object in order to preserve the call by
 	 * reference semantics of ACPI Control Method invocation.
-	 * (See ACPI specification 2.0_c)
+	 * (See ACPI Specification 2.0_c)
 	 */
 	acpi_ut_add_reference(object);
 
@@ -351,7 +351,7 @@
  * FUNCTION:    acpi_ds_method_data_get_value
  *
  * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
- *              Index               - which local_var or argument to get
+ *              Index               - Which local_var or argument to get
  *              walk_state          - Current walk state object
  *              dest_desc           - Where Arg or Local value is returned
  *
@@ -372,7 +372,7 @@
 	struct acpi_namespace_node *node;
 	union acpi_operand_object *object;
 
-	ACPI_FUNCTION_TRACE("ds_method_data_get_value");
+	ACPI_FUNCTION_TRACE(ds_method_data_get_value);
 
 	/* Validate the object descriptor */
 
@@ -459,7 +459,7 @@
  * FUNCTION:    acpi_ds_method_data_delete_value
  *
  * PARAMETERS:  Opcode              - Either AML_LOCAL_OP or AML_ARG_OP
- *              Index               - which local_var or argument to delete
+ *              Index               - Which local_var or argument to delete
  *              walk_state          - Current walk state object
  *
  * RETURN:      None
@@ -477,7 +477,7 @@
 	struct acpi_namespace_node *node;
 	union acpi_operand_object *object;
 
-	ACPI_FUNCTION_TRACE("ds_method_data_delete_value");
+	ACPI_FUNCTION_TRACE(ds_method_data_delete_value);
 
 	/* Get the namespace node for the arg/local */
 
@@ -538,7 +538,7 @@
 	union acpi_operand_object *current_obj_desc;
 	union acpi_operand_object *new_obj_desc;
 
-	ACPI_FUNCTION_TRACE("ds_store_object_to_local");
+	ACPI_FUNCTION_TRACE(ds_store_object_to_local);
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
 			  opcode, index, obj_desc));
 
@@ -614,7 +614,7 @@
 			    && (current_obj_desc->reference.opcode ==
 				AML_REF_OF_OP)) {
 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-						  "Arg (%p) is an obj_ref(Node), storing in node %p\n",
+						  "Arg (%p) is an ObjRef(Node), storing in node %p\n",
 						  new_obj_desc,
 						  current_obj_desc));
 
@@ -688,7 +688,7 @@
 	struct acpi_namespace_node *node;
 	union acpi_operand_object *object;
 
-	ACPI_FUNCTION_TRACE("ds_method_data_get_type");
+	ACPI_FUNCTION_TRACE(ds_method_data_get_type);
 
 	/* Get the namespace node for the arg/local */
 
@@ -701,6 +701,7 @@
 
 	object = acpi_ns_get_attached_object(node);
 	if (!object) {
+
 		/* Uninitialized local/arg, return TYPE_ANY */
 
 		return_VALUE(ACPI_TYPE_ANY);
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
index 8b21f0f..72190ab 100644
--- a/drivers/acpi/dispatcher/dsobject.c
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -81,7 +81,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ds_build_internal_object");
+	ACPI_FUNCTION_TRACE(ds_build_internal_object);
 
 	*obj_desc_ptr = NULL;
 	if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
@@ -103,6 +103,7 @@
 									 common.
 									 node)));
 			if (ACPI_FAILURE(status)) {
+
 				/* Check if we are resolving a named reference within a package */
 
 				if ((status == AE_NOT_FOUND)
@@ -186,7 +187,7 @@
 	union acpi_parse_object *byte_list;
 	u32 byte_list_length = 0;
 
-	ACPI_FUNCTION_TRACE("ds_build_internal_buffer_obj");
+	ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj);
 
 	/*
 	 * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
@@ -195,6 +196,7 @@
 	 */
 	obj_desc = *obj_desc_ptr;
 	if (!obj_desc) {
+
 		/* Create a new buffer object */
 
 		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
@@ -243,7 +245,7 @@
 				  "Buffer defined with zero length in AML, creating\n"));
 	} else {
 		obj_desc->buffer.pointer =
-		    ACPI_MEM_CALLOCATE(obj_desc->buffer.length);
+		    ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length);
 		if (!obj_desc->buffer.pointer) {
 			acpi_ut_delete_object_desc(obj_desc);
 			return_ACPI_STATUS(AE_NO_MEMORY);
@@ -291,7 +293,7 @@
 	acpi_status status = AE_OK;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE("ds_build_internal_package_obj");
+	ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
 
 	/* Find the parent of a possibly nested package */
 
@@ -339,9 +341,10 @@
 	 * individual objects). Add an extra pointer slot so
 	 * that the list is always null terminated.
 	 */
-	obj_desc->package.elements = ACPI_MEM_CALLOCATE(((acpi_size) obj_desc->
-							 package.count +
-							 1) * sizeof(void *));
+	obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
+							   obj_desc->package.
+							   count +
+							   1) * sizeof(void *));
 
 	if (!obj_desc->package.elements) {
 		acpi_ut_delete_object_desc(obj_desc);
@@ -355,6 +358,7 @@
 	arg = arg->common.next;
 	for (i = 0; arg; i++) {
 		if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
+
 			/* Object (package or buffer) is already built */
 
 			obj_desc->package.elements[i] =
@@ -396,7 +400,7 @@
 	acpi_status status;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_create_node", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_create_node, op);
 
 	/*
 	 * Because of the execution pass through the non-control-method
@@ -408,6 +412,7 @@
 	}
 
 	if (!op->common.value.arg) {
+
 		/* No arguments, there is nothing to do */
 
 		return_ACPI_STATUS(AE_OK);
@@ -464,11 +469,12 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ds_init_object_from_op");
+	ACPI_FUNCTION_TRACE(ds_init_object_from_op);
 
 	obj_desc = *ret_obj_desc;
 	op_info = acpi_ps_get_opcode_info(opcode);
 	if (op_info->class == AML_CLASS_UNKNOWN) {
+
 		/* Unknown opcode */
 
 		return_ACPI_STATUS(AE_TYPE);
@@ -626,6 +632,7 @@
 		default:	/* Other literals, etc.. */
 
 			if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+
 				/* Node was saved in Op */
 
 				obj_desc->reference.node = op->common.node;
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 6229c10..5b974a8 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -91,7 +91,7 @@
 	union acpi_parse_object *op;
 	struct acpi_walk_state *walk_state;
 
-	ACPI_FUNCTION_TRACE("ds_execute_arguments");
+	ACPI_FUNCTION_TRACE(ds_execute_arguments);
 
 	/*
 	 * Allocate a new parser op to be the root of the parsed tree
@@ -193,7 +193,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_field_arguments", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
 
 	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
 		return_ACPI_STATUS(AE_OK);
@@ -206,7 +206,7 @@
 
 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
 			(ACPI_TYPE_BUFFER_FIELD, node, NULL));
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
 			  acpi_ut_get_node_name(node)));
 
 	/* Execute the AML code for the term_arg arguments */
@@ -235,7 +235,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_get_buffer_arguments", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
 
 	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
 		return_ACPI_STATUS(AE_OK);
@@ -279,7 +279,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_get_package_arguments", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
 
 	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
 		return_ACPI_STATUS(AE_OK);
@@ -324,7 +324,7 @@
 	acpi_status status;
 	union acpi_operand_object *extra_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_get_region_arguments", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
 
 	if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
 		return_ACPI_STATUS(AE_OK);
@@ -342,8 +342,7 @@
 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
 			(ACPI_TYPE_REGION, node, NULL));
 
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-			  "[%4.4s] op_region Arg Init at AML %p\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
 			  acpi_ut_get_node_name(node),
 			  extra_desc->extra.aml_start));
 
@@ -352,6 +351,28 @@
 	status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
 					   extra_desc->extra.aml_length,
 					   extra_desc->extra.aml_start);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Validate the region address/length via the host OS */
+
+	status = acpi_os_validate_address(obj_desc->region.space_id,
+					  obj_desc->region.address,
+					  (acpi_size) obj_desc->region.length);
+	if (ACPI_FAILURE(status)) {
+		/*
+		 * Invalid address/length. We will emit an error message and mark
+		 * the region as invalid, so that it will cause an additional error if
+		 * it is ever used. Then return AE_OK.
+		 */
+		ACPI_EXCEPTION((AE_INFO, status,
+				"During address validation of OpRegion [%4.4s]",
+				node->name.ascii));
+		obj_desc->common.flags |= AOPOBJ_INVALID;
+		status = AE_OK;
+	}
+
 	return_ACPI_STATUS(status);
 }
 
@@ -411,7 +432,7 @@
 	u8 field_flags;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_init_buffer_field", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
 
 	/* Host object must be a Buffer */
 
@@ -457,7 +478,7 @@
 
 		if (bit_count == 0) {
 			ACPI_ERROR((AE_INFO,
-				    "Attempt to create_field of length zero"));
+				    "Attempt to CreateField of length zero"));
 			status = AE_AML_OPERAND_VALUE;
 			goto cleanup;
 		}
@@ -595,7 +616,7 @@
 	struct acpi_namespace_node *node;
 	union acpi_parse_object *next_op;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_eval_buffer_field_operands", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
 
 	/*
 	 * This is where we evaluate the address and length fields of the
@@ -627,7 +648,7 @@
 	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
 			   acpi_ps_get_opcode_name(op->common.aml_opcode),
 			   walk_state->num_operands,
-			   "after acpi_ex_resolve_operands");
+			   "after AcpiExResolveOperands");
 
 	if (ACPI_FAILURE(status)) {
 		ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
@@ -640,6 +661,7 @@
 	/* Initialize the Buffer Field */
 
 	if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
+
 		/* NOTE: Slightly different operands for this opcode */
 
 		status =
@@ -685,7 +707,7 @@
 	struct acpi_namespace_node *node;
 	union acpi_parse_object *next_op;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_eval_region_operands", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
 
 	/*
 	 * This is where we evaluate the address and length fields of the
@@ -718,7 +740,7 @@
 
 	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
 			   acpi_ps_get_opcode_name(op->common.aml_opcode),
-			   1, "after acpi_ex_resolve_operands");
+			   1, "after AcpiExResolveOperands");
 
 	obj_desc = acpi_ns_get_attached_object(node);
 	if (!obj_desc) {
@@ -744,7 +766,7 @@
 	    operand_desc->integer.value;
 	acpi_ut_remove_reference(operand_desc);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
 			  obj_desc,
 			  ACPI_FORMAT_UINT64(obj_desc->region.address),
 			  obj_desc->region.length));
@@ -780,7 +802,7 @@
 	union acpi_operand_object *arg_desc;
 	u32 length;
 
-	ACPI_FUNCTION_TRACE("ds_eval_data_object_operands");
+	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
 
 	/* The first operand (for all of these data objects) is the length */
 
@@ -874,7 +896,7 @@
 	acpi_status status = AE_OK;
 	union acpi_generic_state *control_state;
 
-	ACPI_FUNCTION_NAME("ds_exec_begin_control_op");
+	ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
 			  op->common.aml_opcode, walk_state));
@@ -952,7 +974,7 @@
 	acpi_status status = AE_OK;
 	union acpi_generic_state *control_state;
 
-	ACPI_FUNCTION_NAME("ds_exec_end_control_op");
+	ACPI_FUNCTION_NAME(ds_exec_end_control_op);
 
 	switch (op->common.aml_opcode) {
 	case AML_IF_OP:
@@ -984,6 +1006,7 @@
 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
 
 		if (walk_state->control_state->common.value) {
+
 			/* Predicate was true, go back and evaluate it again! */
 
 			status = AE_CTRL_PENDING;
@@ -1014,6 +1037,7 @@
 		 * has been bubbled up the tree
 		 */
 		if (op->common.value.arg) {
+
 			/* Since we have a real Return(), delete any implicit return */
 
 			acpi_ds_clear_implicit_return(walk_state);
@@ -1047,6 +1071,7 @@
 			walk_state->return_desc = walk_state->operands[0];
 		} else if ((walk_state->results) &&
 			   (walk_state->results->results.num_results > 0)) {
+
 			/* Since we have a real Return(), delete any implicit return */
 
 			acpi_ds_clear_implicit_return(walk_state);
@@ -1095,7 +1120,7 @@
 		}
 
 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "Completed RETURN_OP State=%p, ret_val=%p\n",
+				  "Completed RETURN_OP State=%p, RetVal=%p\n",
 				  walk_state, walk_state->return_desc));
 
 		/* End the control method execution right now */
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index 53356a5..05230ba 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -68,7 +68,7 @@
  ******************************************************************************/
 void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
 {
-	ACPI_FUNCTION_NAME("ds_clear_implicit_return");
+	ACPI_FUNCTION_NAME(ds_clear_implicit_return);
 
 	/*
 	 * Slack must be enabled for this feature
@@ -115,7 +115,7 @@
 acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
 			   struct acpi_walk_state *walk_state, u8 add_reference)
 {
-	ACPI_FUNCTION_NAME("ds_do_implicit_return");
+	ACPI_FUNCTION_NAME(ds_do_implicit_return);
 
 	/*
 	 * Slack must be enabled for this feature, and we must
@@ -171,7 +171,7 @@
 {
 	const struct acpi_opcode_info *parent_info;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_is_result_used", op);
+	ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
 
 	/* Must have both an Op and a Result Object */
 
@@ -202,6 +202,7 @@
 	 */
 	if ((!op->common.parent) ||
 	    (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
+
 		/* No parent, the return value cannot possibly be used */
 
 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
@@ -340,7 +341,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_delete_result_if_not_used", result_obj);
+	ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
 
 	if (!op) {
 		ACPI_ERROR((AE_INFO, "Null Op"));
@@ -352,6 +353,7 @@
 	}
 
 	if (!acpi_ds_is_result_used(op, walk_state)) {
+
 		/* Must pop the result stack (obj_desc should be equal to result_obj) */
 
 		status = acpi_ds_result_pop(&obj_desc, walk_state);
@@ -382,7 +384,7 @@
 	u32 i;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_resolve_operands", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
 
 	/*
 	 * Attempt to resolve each of the valid operands
@@ -417,7 +419,7 @@
 {
 	u32 i;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_clear_operands", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
 
 	/* Remove a reference on each operand on the stack */
 
@@ -465,7 +467,7 @@
 	acpi_interpreter_mode interpreter_mode;
 	const struct acpi_opcode_info *op_info;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_create_operand", arg);
+	ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
 
 	/* A valid name must be looked up in the namespace */
 
@@ -498,7 +500,9 @@
 		 */
 		if ((walk_state->deferred_node) &&
 		    (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
-		    && (arg_index != 0)) {
+		    && (arg_index ==
+			(u32) ((walk_state->opcode ==
+				AML_CREATE_FIELD_OP) ? 3 : 2))) {
 			obj_desc =
 			    ACPI_CAST_PTR(union acpi_operand_object,
 					  walk_state->deferred_node);
@@ -521,6 +525,7 @@
 			    && (parent_op->common.aml_opcode != AML_REGION_OP)
 			    && (parent_op->common.aml_opcode !=
 				AML_INT_NAMEPATH_OP)) {
+
 				/* Enter name into namespace if not found */
 
 				interpreter_mode = ACPI_IMODE_LOAD_PASS2;
@@ -572,7 +577,7 @@
 
 		/* Free the namestring created above */
 
-		ACPI_MEM_FREE(name_string);
+		ACPI_FREE(name_string);
 
 		/* Check status from the lookup */
 
@@ -696,7 +701,7 @@
 	union acpi_parse_object *arg;
 	u32 arg_count = 0;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_create_operands", first_arg);
+	ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
 
 	/* For all arguments in the list... */
 
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index f1af655..3acbd91 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -49,7 +49,6 @@
 #include <acpi/acinterp.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acdebug.h>
-#include <acpi/acdisasm.h>
 
 #define _COMPONENT          ACPI_DISPATCHER
 ACPI_MODULE_NAME("dswexec")
@@ -93,7 +92,7 @@
 	union acpi_operand_object *obj_desc;
 	union acpi_operand_object *local_obj_desc = NULL;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_get_predicate_value", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state);
 
 	walk_state->control_state->common.state = 0;
 
@@ -123,7 +122,7 @@
 
 	if (!obj_desc) {
 		ACPI_ERROR((AE_INFO,
-			    "No predicate obj_desc=%p State=%p",
+			    "No predicate ObjDesc=%p State=%p",
 			    obj_desc, walk_state));
 
 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
@@ -140,7 +139,7 @@
 
 	if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) {
 		ACPI_ERROR((AE_INFO,
-			    "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X",
+			    "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X",
 			    obj_desc, walk_state,
 			    ACPI_GET_OBJECT_TYPE(obj_desc)));
 
@@ -214,7 +213,7 @@
 	acpi_status status = AE_OK;
 	u32 opcode_class;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_exec_begin_op", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state);
 
 	op = walk_state->op;
 	if (!op) {
@@ -296,7 +295,7 @@
 
 	case AML_CLASS_NAMED_OBJECT:
 
-		if (walk_state->walk_type == ACPI_WALK_METHOD) {
+		if (walk_state->walk_type & ACPI_WALK_METHOD) {
 			/*
 			 * Found a named object declaration during method execution;
 			 * we must enter this object into the namespace.  The created
@@ -354,7 +353,7 @@
 	union acpi_parse_object *next_op;
 	union acpi_parse_object *first_arg;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_exec_end_op", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state);
 
 	op = walk_state->op;
 	op_type = walk_state->op_info->type;
@@ -409,6 +408,7 @@
 		 * being the object_type and size_of operators.
 		 */
 		if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
+
 			/* Resolve all operands */
 
 			status = acpi_ex_resolve_operands(walk_state->opcode,
@@ -423,7 +423,7 @@
 						   acpi_ps_get_opcode_name
 						   (walk_state->opcode),
 						   walk_state->num_operands,
-						   "after ex_resolve_operands");
+						   "after ExResolveOperands");
 			}
 		}
 
@@ -437,7 +437,7 @@
 			    acpi_gbl_op_type_dispatch[op_type] (walk_state);
 		} else {
 			/*
-			 * Treat constructs of the form "Store(local_x,local_x)" as noops when the
+			 * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the
 			 * Local is uninitialized.
 			 */
 			if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
@@ -548,6 +548,7 @@
 			 */
 			status = acpi_ds_resolve_operands(walk_state);
 			if (ACPI_FAILURE(status)) {
+
 				/* On error, clear all resolved operands */
 
 				acpi_ds_clear_operands(walk_state);
@@ -569,7 +570,7 @@
 		case AML_TYPE_CREATE_FIELD:
 
 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-					  "Executing create_field Buffer/Index Op=%p\n",
+					  "Executing CreateField Buffer/Index Op=%p\n",
 					  op));
 
 			status = acpi_ds_load2_end_op(walk_state);
@@ -584,7 +585,7 @@
 		case AML_TYPE_CREATE_OBJECT:
 
 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-					  "Executing create_object (Buffer/Package) Op=%p\n",
+					  "Executing CreateObject (Buffer/Package) Op=%p\n",
 					  op));
 
 			switch (op->common.parent->common.aml_opcode) {
@@ -657,7 +658,7 @@
 
 			if (op->common.aml_opcode == AML_REGION_OP) {
 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-						  "Executing op_region Address/Length Op=%p\n",
+						  "Executing OpRegion Address/Length Op=%p\n",
 						  op));
 
 				status =
@@ -722,6 +723,7 @@
       cleanup:
 
 	if (walk_state->result_obj) {
+
 		/* Break to debugger to display result */
 
 		ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
index d3d24da..3507439 100644
--- a/drivers/acpi/dispatcher/dswload.c
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -127,7 +127,7 @@
 	char *path;
 	u32 flags;
 
-	ACPI_FUNCTION_TRACE("ds_load1_begin_op");
+	ACPI_FUNCTION_TRACE(ds_load1_begin_op);
 
 	op = walk_state->op;
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -178,12 +178,12 @@
 			 * Target of Scope() not found.  Generate an External for it, and
 			 * insert the name into the namespace.
 			 */
-			acpi_dm_add_to_external_list(path);
+			acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0);
 			status =
 			    acpi_ns_lookup(walk_state->scope_info, path,
 					   object_type, ACPI_IMODE_LOAD_PASS1,
 					   ACPI_NS_SEARCH_PARENT, walk_state,
-					   &(node));
+					   &node);
 		}
 #endif
 		if (ACPI_FAILURE(status)) {
@@ -261,6 +261,7 @@
 		 */
 
 		if (walk_state->deferred_node) {
+
 			/* This name is already in the namespace, get the node */
 
 			node = walk_state->deferred_node;
@@ -300,10 +301,41 @@
 		status =
 		    acpi_ns_lookup(walk_state->scope_info, path, object_type,
 				   ACPI_IMODE_LOAD_PASS1, flags, walk_state,
-				   &(node));
+				   &node);
 		if (ACPI_FAILURE(status)) {
-			ACPI_ERROR_NAMESPACE(path, status);
-			return_ACPI_STATUS(status);
+			if (status == AE_ALREADY_EXISTS) {
+
+				/* The name already exists in this scope */
+
+				if (node->flags & ANOBJ_IS_EXTERNAL) {
+					/*
+					 * Allow one create on an object or segment that was
+					 * previously declared External
+					 */
+					node->flags &= ~ANOBJ_IS_EXTERNAL;
+					node->type = (u8) object_type;
+
+					/* Just retyped a node, probably will need to open a scope */
+
+					if (acpi_ns_opens_scope(object_type)) {
+						status =
+						    acpi_ds_scope_stack_push
+						    (node, object_type,
+						     walk_state);
+						if (ACPI_FAILURE(status)) {
+							return_ACPI_STATUS
+							    (status);
+						}
+					}
+					status = AE_OK;
+				}
+			}
+
+			if (ACPI_FAILURE(status)) {
+
+				ACPI_ERROR_NAMESPACE(path, status);
+				return_ACPI_STATUS(status);
+			}
 		}
 		break;
 	}
@@ -311,6 +343,7 @@
 	/* Common exit */
 
 	if (!op) {
+
 		/* Create a new op */
 
 		op = acpi_ps_alloc_op(walk_state->opcode);
@@ -359,7 +392,7 @@
 	acpi_object_type object_type;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ds_load1_end_op");
+	ACPI_FUNCTION_TRACE(ds_load1_end_op);
 
 	op = walk_state->op;
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -413,6 +446,7 @@
 #endif
 
 	if (op->common.aml_opcode == AML_NAME_OP) {
+
 		/* For Name opcode, get the object type from the argument */
 
 		if (op->common.value.arg) {
@@ -445,7 +479,7 @@
 			 * arguments.)
 			 */
 			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-					  "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
 					  walk_state, op, op->named.node));
 
 			if (!acpi_ns_get_attached_object(op->named.node)) {
@@ -511,7 +545,7 @@
 	acpi_object_type object_type;
 	char *buffer_ptr;
 
-	ACPI_FUNCTION_TRACE("ds_load2_begin_op");
+	ACPI_FUNCTION_TRACE(ds_load2_begin_op);
 
 	op = walk_state->op;
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
@@ -521,6 +555,7 @@
 		if ((walk_state->control_state) &&
 		    (walk_state->control_state->common.state ==
 		     ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
+
 			/* We are executing a while loop outside of a method */
 
 			status = acpi_ds_exec_begin_op(walk_state, out_op);
@@ -554,10 +589,12 @@
 		/* Get the name we are going to enter or lookup in the namespace */
 
 		if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
+
 			/* For Namepath op, get the path string */
 
 			buffer_ptr = op->common.value.string;
 			if (!buffer_ptr) {
+
 				/* No name, just exit */
 
 				return_ACPI_STATUS(AE_OK);
@@ -680,6 +717,7 @@
 		/* All other opcodes */
 
 		if (op && op->common.node) {
+
 			/* This op/node was previously entered into the namespace */
 
 			node = op->common.node;
@@ -705,6 +743,7 @@
 		 * Note: Name may already exist if we are executing a deferred opcode.
 		 */
 		if (walk_state->deferred_node) {
+
 			/* This name is already in the namespace, get the node */
 
 			node = walk_state->deferred_node;
@@ -727,6 +766,7 @@
 	}
 
 	if (!op) {
+
 		/* Create a new op */
 
 		op = acpi_ps_alloc_op(walk_state->opcode);
@@ -776,7 +816,7 @@
 	u32 i;
 #endif
 
-	ACPI_FUNCTION_TRACE("ds_load2_end_op");
+	ACPI_FUNCTION_TRACE(ds_load2_end_op);
 
 	op = walk_state->op;
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
@@ -870,7 +910,7 @@
 	 */
 
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-			  "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
+			  "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
 			  acpi_ps_get_opcode_name(op->common.aml_opcode),
 			  walk_state, op, node));
 
@@ -1045,7 +1085,7 @@
 			 * arguments.)
 			 */
 			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-					  "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
 					  walk_state, op, op->named.node));
 
 			if (!acpi_ns_get_attached_object(op->named.node)) {
@@ -1090,7 +1130,7 @@
 	case AML_CLASS_METHOD_CALL:
 
 		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
+				  "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
 				  walk_state, op, node));
 
 		/*
@@ -1104,7 +1144,6 @@
 				   ACPI_NS_DONT_OPEN_SCOPE, walk_state,
 				   &(new_node));
 		if (ACPI_SUCCESS(status)) {
-
 			/*
 			 * Make sure that what we found is indeed a method
 			 * We didn't search for a method on purpose, to see if the name
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
index ada21ef..c922897 100644
--- a/drivers/acpi/dispatcher/dswscope.c
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -63,9 +63,10 @@
 {
 	union acpi_generic_state *scope_info;
 
-	ACPI_FUNCTION_NAME("ds_scope_stack_clear");
+	ACPI_FUNCTION_NAME(ds_scope_stack_clear);
 
 	while (walk_state->scope_info) {
+
 		/* Pop a scope off the stack */
 
 		scope_info = walk_state->scope_info;
@@ -102,9 +103,10 @@
 	union acpi_generic_state *scope_info;
 	union acpi_generic_state *old_scope_info;
 
-	ACPI_FUNCTION_TRACE("ds_scope_stack_push");
+	ACPI_FUNCTION_TRACE(ds_scope_stack_push);
 
 	if (!node) {
+
 		/* Invalid scope   */
 
 		ACPI_ERROR((AE_INFO, "Null scope parameter"));
@@ -126,7 +128,7 @@
 
 	/* Init new scope object */
 
-	scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE;
+	scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE;
 	scope_info->scope.node = node;
 	scope_info->common.value = (u16) type;
 
@@ -176,7 +178,7 @@
 	union acpi_generic_state *scope_info;
 	union acpi_generic_state *new_scope_info;
 
-	ACPI_FUNCTION_TRACE("ds_scope_stack_pop");
+	ACPI_FUNCTION_TRACE(ds_scope_stack_pop);
 
 	/*
 	 * Pop scope info object off the stack.
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index fa78cb7..7817e55 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -66,7 +66,6 @@
 #endif
 
 #ifdef ACPI_FUTURE_USAGE
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ds_result_remove
@@ -88,7 +87,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_NAME("ds_result_remove");
+	ACPI_FUNCTION_NAME(ds_result_remove);
 
 	state = walk_state->results;
 	if (!state) {
@@ -128,7 +127,6 @@
 
 	return (AE_OK);
 }
-
 #endif				/*  ACPI_FUTURE_USAGE  */
 
 /*******************************************************************************
@@ -152,7 +150,7 @@
 	acpi_native_uint index;
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_NAME("ds_result_pop");
+	ACPI_FUNCTION_NAME(ds_result_pop);
 
 	state = walk_state->results;
 	if (!state) {
@@ -170,6 +168,7 @@
 	state->results.num_results--;
 
 	for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) {
+
 		/* Check for a valid result object */
 
 		if (state->results.obj_desc[index - 1]) {
@@ -213,7 +212,7 @@
 	acpi_native_uint index;
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_NAME("ds_result_pop_from_bottom");
+	ACPI_FUNCTION_NAME(ds_result_pop_from_bottom);
 
 	state = walk_state->results;
 	if (!state) {
@@ -278,7 +277,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_NAME("ds_result_push");
+	ACPI_FUNCTION_NAME(ds_result_push);
 
 	state = walk_state->results;
 	if (!state) {
@@ -331,14 +330,14 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_NAME("ds_result_stack_push");
+	ACPI_FUNCTION_NAME(ds_result_stack_push);
 
 	state = acpi_ut_create_generic_state();
 	if (!state) {
 		return (AE_NO_MEMORY);
 	}
 
-	state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT;
+	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT;
 	acpi_ut_push_generic_state(&walk_state->results, state);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n",
@@ -363,7 +362,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_NAME("ds_result_stack_pop");
+	ACPI_FUNCTION_NAME(ds_result_stack_pop);
 
 	/* Check for stack underflow */
 
@@ -376,7 +375,7 @@
 	state = acpi_ut_pop_generic_state(&walk_state->results);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-			  "Result=%p remaining_results=%X State=%p\n",
+			  "Result=%p RemainingResults=%X State=%p\n",
 			  state, state->results.num_results, walk_state));
 
 	acpi_ut_delete_generic_state(state);
@@ -400,7 +399,7 @@
 acpi_status
 acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state)
 {
-	ACPI_FUNCTION_NAME("ds_obj_stack_push");
+	ACPI_FUNCTION_NAME(ds_obj_stack_push);
 
 	/* Check for stack overflow */
 
@@ -445,9 +444,10 @@
 {
 	u32 i;
 
-	ACPI_FUNCTION_NAME("ds_obj_stack_pop");
+	ACPI_FUNCTION_NAME(ds_obj_stack_pop);
 
 	for (i = 0; i < pop_count; i++) {
+
 		/* Check for stack underflow */
 
 		if (walk_state->num_operands == 0) {
@@ -491,9 +491,10 @@
 	u32 i;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_NAME("ds_obj_stack_pop_and_delete");
+	ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
 
 	for (i = 0; i < pop_count; i++) {
+
 		/* Check for stack underflow */
 
 		if (walk_state->num_operands == 0) {
@@ -538,13 +539,13 @@
 struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
 						       *thread)
 {
-	ACPI_FUNCTION_NAME("ds_get_current_walk_state");
+	ACPI_FUNCTION_NAME(ds_get_current_walk_state);
 
 	if (!thread) {
 		return (NULL);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current walk_state %p\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n",
 			  thread->walk_state_list));
 
 	return (thread->walk_state_list);
@@ -567,7 +568,7 @@
 acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
 			struct acpi_thread_state *thread)
 {
-	ACPI_FUNCTION_TRACE("ds_push_walk_state");
+	ACPI_FUNCTION_TRACE(ds_push_walk_state);
 
 	walk_state->next = thread->walk_state_list;
 	thread->walk_state_list = walk_state;
@@ -593,11 +594,12 @@
 {
 	struct acpi_walk_state *walk_state;
 
-	ACPI_FUNCTION_TRACE("ds_pop_walk_state");
+	ACPI_FUNCTION_TRACE(ds_pop_walk_state);
 
 	walk_state = thread->walk_state_list;
 
 	if (walk_state) {
+
 		/* Next walk state becomes the current walk state */
 
 		thread->walk_state_list = walk_state->next;
@@ -618,7 +620,7 @@
  *
  * PARAMETERS:  owner_id        - ID for object creation
  *              Origin          - Starting point for this walk
- *              mth_desc        - Method object
+ *              method_desc     - Method object
  *              Thread          - Current thread state
  *
  * RETURN:      Pointer to the new walk state.
@@ -632,24 +634,24 @@
 						  union acpi_parse_object
 						  *origin,
 						  union acpi_operand_object
-						  *mth_desc,
+						  *method_desc,
 						  struct acpi_thread_state
 						  *thread)
 {
 	struct acpi_walk_state *walk_state;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ds_create_walk_state");
+	ACPI_FUNCTION_TRACE(ds_create_walk_state);
 
-	walk_state = ACPI_MEM_CALLOCATE(sizeof(struct acpi_walk_state));
+	walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state));
 	if (!walk_state) {
 		return_PTR(NULL);
 	}
 
-	walk_state->data_type = ACPI_DESC_TYPE_WALK;
+	walk_state->descriptor_type = ACPI_DESC_TYPE_WALK;
+	walk_state->method_desc = method_desc;
 	walk_state->owner_id = owner_id;
 	walk_state->origin = origin;
-	walk_state->method_desc = mth_desc;
 	walk_state->thread = thread;
 
 	walk_state->parser_state.start_op = origin;
@@ -664,7 +666,7 @@
 
 	status = acpi_ds_result_stack_push(walk_state);
 	if (ACPI_FAILURE(status)) {
-		ACPI_MEM_FREE(walk_state);
+		ACPI_FREE(walk_state);
 		return_PTR(NULL);
 	}
 
@@ -701,13 +703,13 @@
 		      struct acpi_namespace_node *method_node,
 		      u8 * aml_start,
 		      u32 aml_length,
-		      struct acpi_parameter_info *info, u8 pass_number)
+		      struct acpi_evaluate_info *info, u8 pass_number)
 {
 	acpi_status status;
 	struct acpi_parse_state *parser_state = &walk_state->parser_state;
 	union acpi_parse_object *extra_op;
 
-	ACPI_FUNCTION_TRACE("ds_init_aml_walk");
+	ACPI_FUNCTION_TRACE(ds_init_aml_walk);
 
 	walk_state->parser_state.aml =
 	    walk_state->parser_state.aml_start = aml_start;
@@ -778,6 +780,7 @@
 		}
 
 		if (parser_state->start_node) {
+
 			/* Push start scope on scope stack and make it current  */
 
 			status =
@@ -810,21 +813,24 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_delete_walk_state", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state);
 
 	if (!walk_state) {
 		return;
 	}
 
-	if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
+	if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) {
 		ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
 			    walk_state));
 		return;
 	}
 
+	/* There should not be any open scopes */
+
 	if (walk_state->parser_state.scope) {
 		ACPI_ERROR((AE_INFO, "%p walk still has a scope list",
 			    walk_state));
+		acpi_ps_cleanup_scope(&walk_state->parser_state);
 	}
 
 	/* Always must free any linked control states */
@@ -854,7 +860,7 @@
 		acpi_ut_delete_generic_state(state);
 	}
 
-	ACPI_MEM_FREE(walk_state);
+	ACPI_FREE(walk_state);
 	return_VOID;
 }
 
@@ -879,7 +885,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_NAME("ds_result_insert");
+	ACPI_FUNCTION_NAME(ds_result_insert);
 
 	state = walk_state->results;
 	if (!state) {
@@ -937,7 +943,7 @@
 {
 	u32 i;
 
-	ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_delete_all", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_delete_all, walk_state);
 
 	/* The stack size is configurable, but fixed */
 
@@ -969,7 +975,7 @@
 acpi_ds_obj_stack_pop_object(union acpi_operand_object **object,
 			     struct acpi_walk_state *walk_state)
 {
-	ACPI_FUNCTION_NAME("ds_obj_stack_pop_object");
+	ACPI_FUNCTION_NAME(ds_obj_stack_pop_object);
 
 	/* Check for stack underflow */
 
@@ -1025,7 +1031,7 @@
 void *acpi_ds_obj_stack_get_value(u32 index, struct acpi_walk_state *walk_state)
 {
 
-	ACPI_FUNCTION_TRACE_PTR("ds_obj_stack_get_value", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ds_obj_stack_get_value, walk_state);
 
 	/* Can't do it if the stack is empty */
 
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index eee0864..18b3ea9 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -116,7 +116,7 @@
 		struct acpi_generic_address command_addr;
 		struct acpi_generic_address data_addr;
 		unsigned long global_lock;
-		spinlock_t lock;
+		struct semaphore sem;
 	} poll;
 };
 
@@ -323,7 +323,6 @@
 {
 	acpi_status status = AE_OK;
 	int result = 0;
-	unsigned long flags = 0;
 	u32 glk = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_ec_read");
@@ -339,8 +338,11 @@
 			return_VALUE(-ENODEV);
 	}
 
-	spin_lock_irqsave(&ec->poll.lock, flags);
-
+	if (down_interruptible(&ec->poll.sem)) {
+		result = -ERESTARTSYS;
+		goto end_nosem;
+	}
+	
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ,
 				&ec->common.command_addr);
 	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
@@ -358,8 +360,8 @@
 			  *data, address));
 
       end:
-	spin_unlock_irqrestore(&ec->poll.lock, flags);
-
+	up(&ec->poll.sem);
+end_nosem:
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
 
@@ -370,7 +372,6 @@
 {
 	int result = 0;
 	acpi_status status = AE_OK;
-	unsigned long flags = 0;
 	u32 glk = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_ec_write");
@@ -384,8 +385,11 @@
 			return_VALUE(-ENODEV);
 	}
 
-	spin_lock_irqsave(&ec->poll.lock, flags);
-
+	if (down_interruptible(&ec->poll.sem)) {
+		result = -ERESTARTSYS;
+		goto end_nosem;
+	}
+	
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE,
 				&ec->common.command_addr);
 	result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE);
@@ -406,8 +410,8 @@
 			  data, address));
 
       end:
-	spin_unlock_irqrestore(&ec->poll.lock, flags);
-
+	up(&ec->poll.sem);
+end_nosem:
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
 
@@ -568,7 +572,6 @@
 {
 	int result = 0;
 	acpi_status status = AE_OK;
-	unsigned long flags = 0;
 	u32 glk = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_ec_query");
@@ -589,8 +592,11 @@
 	 * Note that successful completion of the query causes the ACPI_EC_SCI
 	 * bit to be cleared (and thus clearing the interrupt source).
 	 */
-	spin_lock_irqsave(&ec->poll.lock, flags);
-
+	if (down_interruptible(&ec->poll.sem)) {
+		result = -ERESTARTSYS;
+		goto end_nosem;
+	}
+	
 	acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY,
 				&ec->common.command_addr);
 	result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF);
@@ -602,8 +608,8 @@
 		result = -ENODATA;
 
       end:
-	spin_unlock_irqrestore(&ec->poll.lock, flags);
-
+	up(&ec->poll.sem);
+end_nosem:
 	if (ec->common.global_lock)
 		acpi_release_global_lock(glk);
 
@@ -680,7 +686,6 @@
 {
 	union acpi_ec *ec = (union acpi_ec *)ec_cxt;
 	u32 value = 0;
-	unsigned long flags = 0;
 	static char object_name[5] = { '_', 'Q', '0', '0', '\0' };
 	const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
 		'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
@@ -691,9 +696,11 @@
 	if (!ec_cxt)
 		goto end;
 
-	spin_lock_irqsave(&ec->poll.lock, flags);
+	if (down_interruptible (&ec->poll.sem)) {
+		return_VOID;
+	}
 	acpi_hw_low_level_read(8, &value, &ec->common.command_addr);
-	spin_unlock_irqrestore(&ec->poll.lock, flags);
+	up(&ec->poll.sem);
 
 	/* TBD: Implement asynch events!
 	 * NOTE: All we care about are EC-SCI's.  Other EC events are
@@ -763,8 +770,7 @@
 
 	acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR);
 
-	status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
-					     acpi_ec_gpe_query, ec);
+	status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec);
 
 	if (status == AE_OK)
 		return ACPI_INTERRUPT_HANDLED;
@@ -799,7 +805,7 @@
 
 	if (value & ACPI_EC_FLAG_SCI) {
 		atomic_add(1, &ec->intr.pending_gpe);
-		status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
+		status = acpi_os_execute(OSL_EC_BURST_HANDLER,
 						     acpi_ec_gpe_query, ec);
 		return status == AE_OK ?
 		    ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
@@ -991,7 +997,6 @@
 	int result = 0;
 	acpi_status status = AE_OK;
 	union acpi_ec *ec = NULL;
-	unsigned long uid;
 
 	ACPI_FUNCTION_TRACE("acpi_ec_add");
 
@@ -1005,7 +1010,7 @@
 
 	ec->common.handle = device->handle;
 	ec->common.uid = -1;
-	spin_lock_init(&ec->poll.lock);
+	init_MUTEX(&ec->poll.sem);
 	strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME);
 	strcpy(acpi_device_class(device), ACPI_EC_CLASS);
 	acpi_driver_data(device) = ec;
@@ -1014,10 +1019,9 @@
 	acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
 			      &ec->common.global_lock);
 
-	/* If our UID matches the UID for the ECDT-enumerated EC,
-	   we now have the *real* EC info, so kill the makeshift one. */
-	acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
-	if (ec_ecdt && ec_ecdt->common.uid == uid) {
+	/* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
+	   http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
+	if (ec_ecdt) {
 		acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
 						  ACPI_ADR_SPACE_EC,
 						  &acpi_ec_space_handler);
@@ -1062,7 +1066,6 @@
 	int result = 0;
 	acpi_status status = AE_OK;
 	union acpi_ec *ec = NULL;
-	unsigned long uid;
 
 	ACPI_FUNCTION_TRACE("acpi_ec_add");
 
@@ -1088,10 +1091,9 @@
 	acpi_evaluate_integer(ec->common.handle, "_GLK", NULL,
 			      &ec->common.global_lock);
 
-	/* If our UID matches the UID for the ECDT-enumerated EC,
-	   we now have the *real* EC info, so kill the makeshift one. */
-	acpi_evaluate_integer(ec->common.handle, "_UID", NULL, &uid);
-	if (ec_ecdt && ec_ecdt->common.uid == uid) {
+	/* XXX we don't test uids, because on some boxes ecdt uid = 0, see:
+	   http://bugzilla.kernel.org/show_bug.cgi?id=6111 */
+	if (ec_ecdt) {
 		acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
 						  ACPI_ADR_SPACE_EC,
 						  &acpi_ec_space_handler);
@@ -1300,7 +1302,7 @@
 				  &ec_ecdt->common.gpe_bit);
 	if (ACPI_FAILURE(status))
 		return status;
-	spin_lock_init(&ec_ecdt->poll.lock);
+	init_MUTEX(&ec_ecdt->poll.sem);
 	ec_ecdt->common.global_lock = TRUE;
 	ec_ecdt->common.handle = handle;
 
@@ -1416,7 +1418,7 @@
 	ec_ecdt->common.status_addr = ecdt_ptr->ec_control;
 	ec_ecdt->common.data_addr = ecdt_ptr->ec_data;
 	ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit;
-	spin_lock_init(&ec_ecdt->poll.lock);
+	init_MUTEX(&ec_ecdt->poll.sem);
 	/* use the GL just to be safe */
 	ec_ecdt->common.global_lock = TRUE;
 	ec_ecdt->common.uid = ecdt_ptr->uid;
diff --git a/drivers/acpi/events/evevent.c b/drivers/acpi/events/evevent.c
index c9ac05c..919037d 100644
--- a/drivers/acpi/events/evevent.c
+++ b/drivers/acpi/events/evevent.c
@@ -68,7 +68,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_initialize_events");
+	ACPI_FUNCTION_TRACE(ev_initialize_events);
 
 	/* Make sure we have ACPI tables */
 
@@ -118,7 +118,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_install_fadt_gpes");
+	ACPI_FUNCTION_TRACE(ev_install_fadt_gpes);
 
 	/* Namespace must be locked */
 
@@ -157,7 +157,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_install_xrupt_handlers");
+	ACPI_FUNCTION_TRACE(ev_install_xrupt_handlers);
 
 	/* Install the SCI handler */
 
@@ -241,7 +241,7 @@
 	u32 fixed_enable;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_NAME("ev_fixed_event_detect");
+	ACPI_FUNCTION_NAME(ev_fixed_event_detect);
 
 	/*
 	 * Read the fixed feature status and enable registers, as all the cases
@@ -260,12 +260,14 @@
 	 * Check for all possible Fixed Events and dispatch those that are active
 	 */
 	for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) {
+
 		/* Both the status and enable bits must be on for this event */
 
 		if ((fixed_status & acpi_gbl_fixed_event_info[i].
 		     status_bit_mask)
 		    && (fixed_enable & acpi_gbl_fixed_event_info[i].
 			enable_bit_mask)) {
+
 			/* Found an active (signalled) event */
 
 			int_status |= acpi_ev_fixed_event_dispatch((u32) i);
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index f64f977..f01d339 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -69,7 +69,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_set_gpe_type");
+	ACPI_FUNCTION_TRACE(ev_set_gpe_type);
 
 	/* Validate type and update register enable masks */
 
@@ -115,7 +115,7 @@
 	struct acpi_gpe_register_info *gpe_register_info;
 	u8 register_bit;
 
-	ACPI_FUNCTION_TRACE("ev_update_gpe_enable_masks");
+	ACPI_FUNCTION_TRACE(ev_update_gpe_enable_masks);
 
 	gpe_register_info = gpe_event_info->register_info;
 	if (!gpe_register_info) {
@@ -178,7 +178,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_enable_gpe");
+	ACPI_FUNCTION_TRACE(ev_enable_gpe);
 
 	/* Make sure HW enable masks are updated */
 
@@ -207,6 +207,7 @@
 		ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
 
 		if (write_to_hardware) {
+
 			/* Clear the GPE (of stale events), then enable it */
 
 			status = acpi_hw_clear_gpe(gpe_event_info);
@@ -243,7 +244,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_disable_gpe");
+	ACPI_FUNCTION_TRACE(ev_disable_gpe);
 
 	if (!(gpe_event_info->flags & ACPI_GPE_ENABLE_MASK)) {
 		return_ACPI_STATUS(AE_OK);
@@ -313,6 +314,7 @@
 	/* A NULL gpe_block means use the FADT-defined GPE block(s) */
 
 	if (!gpe_device) {
+
 		/* Examine GPE Block 0 and 1 (These blocks are permanent) */
 
 		for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) {
@@ -380,10 +382,11 @@
 	u32 status_reg;
 	u32 enable_reg;
 	acpi_cpu_flags flags;
+	acpi_cpu_flags hw_flags;
 	acpi_native_uint i;
 	acpi_native_uint j;
 
-	ACPI_FUNCTION_NAME("ev_gpe_detect");
+	ACPI_FUNCTION_NAME(ev_gpe_detect);
 
 	/* Check for the case where there are no GPEs */
 
@@ -391,9 +394,12 @@
 		return (int_status);
 	}
 
-	/* Examine all GPE blocks attached to this interrupt level */
+	/* We need to hold the GPE lock now, hardware lock in the loop */
 
 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+	/* Examine all GPE blocks attached to this interrupt level */
+
 	gpe_block = gpe_xrupt_list->gpe_block_list_head;
 	while (gpe_block) {
 		/*
@@ -402,10 +408,13 @@
 		 * Find all currently active GP events.
 		 */
 		for (i = 0; i < gpe_block->register_count; i++) {
+
 			/* Get the next status/enable pair */
 
 			gpe_register_info = &gpe_block->register_info[i];
 
+			hw_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
+
 			/* Read the Status Register */
 
 			status =
@@ -414,6 +423,8 @@
 						   &gpe_register_info->
 						   status_address);
 			if (ACPI_FAILURE(status)) {
+				acpi_os_release_lock(acpi_gbl_hardware_lock,
+						     hw_flags);
 				goto unlock_and_exit;
 			}
 
@@ -424,6 +435,8 @@
 						   &enable_reg,
 						   &gpe_register_info->
 						   enable_address);
+			acpi_os_release_lock(acpi_gbl_hardware_lock, hw_flags);
+
 			if (ACPI_FAILURE(status)) {
 				goto unlock_and_exit;
 			}
@@ -437,6 +450,7 @@
 
 			enabled_status_byte = (u8) (status_reg & enable_reg);
 			if (!enabled_status_byte) {
+
 				/* No active GPEs in this register, move on */
 
 				continue;
@@ -445,6 +459,7 @@
 			/* Now look at the individual GPEs in this byte register */
 
 			for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
+
 				/* Examine one GPE bit */
 
 				if (enabled_status_byte &
@@ -483,9 +498,9 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Perform the actual execution of a GPE control method.  This
- *              function is called from an invocation of acpi_os_queue_for_execution
- *              (and therefore does NOT execute at interrupt level) so that
+ * DESCRIPTION: Perform the actual execution of a GPE control method. This
+ *              function is called from an invocation of acpi_os_execute and
+ *              therefore does NOT execute at interrupt level - so that
  *              the control method itself is not executed in the context of
  *              an interrupt handler.
  *
@@ -494,12 +509,11 @@
 static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
 {
 	struct acpi_gpe_event_info *gpe_event_info = (void *)context;
-	u32 gpe_number = 0;
 	acpi_status status;
 	struct acpi_gpe_event_info local_gpe_event_info;
-	struct acpi_parameter_info info;
+	struct acpi_evaluate_info *info;
 
-	ACPI_FUNCTION_TRACE("ev_asynch_execute_gpe_method");
+	ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 	if (ACPI_FAILURE(status)) {
@@ -535,22 +549,35 @@
 	 */
 	if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
 	    ACPI_GPE_DISPATCH_METHOD) {
-		/*
-		 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
-		 * control method that corresponds to this GPE
-		 */
-		info.node = local_gpe_event_info.dispatch.method_node;
-		info.parameters =
-		    ACPI_CAST_PTR(union acpi_operand_object *, gpe_event_info);
-		info.parameter_type = ACPI_PARAM_GPE;
 
-		status = acpi_ns_evaluate_by_handle(&info);
+		/* Allocate the evaluation information block */
+
+		info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+		if (!info) {
+			status = AE_NO_MEMORY;
+		} else {
+			/*
+			 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
+			 * control method that corresponds to this GPE
+			 */
+			info->prefix_node =
+			    local_gpe_event_info.dispatch.method_node;
+			info->parameters =
+			    ACPI_CAST_PTR(union acpi_operand_object *,
+					  gpe_event_info);
+			info->parameter_type = ACPI_PARAM_GPE;
+			info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+			status = acpi_ns_evaluate(info);
+			ACPI_FREE(info);
+		}
+
 		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
-					"While evaluating method [%4.4s] for GPE[%2X]",
+					"While evaluating GPE method [%4.4s]",
 					acpi_ut_get_node_name
 					(local_gpe_event_info.dispatch.
-					 method_node), gpe_number));
+					 method_node)));
 		}
 	}
 
@@ -593,7 +620,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_gpe_dispatch");
+	ACPI_FUNCTION_TRACE(ev_gpe_dispatch);
 
 	/*
 	 * If edge-triggered, clear the GPE status bit now.  Note that
@@ -669,9 +696,9 @@
 		 * Execute the method associated with the GPE
 		 * NOTE: Level-triggered GPEs are cleared after the method completes.
 		 */
-		status = acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
-						     acpi_ev_asynch_execute_gpe_method,
-						     gpe_event_info);
+		status = acpi_os_execute(OSL_GPE_HANDLER,
+					 acpi_ev_asynch_execute_gpe_method,
+					 gpe_event_info);
 		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
 					"Unable to queue handler for GPE[%2X] - event disabled",
@@ -716,7 +743,7 @@
  *
  * DESCRIPTION: Determine if a a GPE is "wake-only".
  *
- *              Called from Notify() code in interpreter when a "device_wake"
+ *              Called from Notify() code in interpreter when a "DeviceWake"
  *              Notify comes in.
  *
  ******************************************************************************/
@@ -726,7 +753,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_check_for_wake_only_gpe");
+	ACPI_FUNCTION_TRACE(ev_check_for_wake_only_gpe);
 
 	if ((gpe_event_info) &&	/* Only >0 for _Lxx/_Exx */
 	    ((gpe_event_info->flags & ACPI_GPE_SYSTEM_MASK) == ACPI_GPE_SYSTEM_RUNNING)) {	/* System state at GPE time */
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index 0fd00b5..95ddeb4 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -131,14 +131,14 @@
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback)
+acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback)
 {
 	struct acpi_gpe_block_info *gpe_block;
 	struct acpi_gpe_xrupt_info *gpe_xrupt_info;
 	acpi_status status = AE_OK;
 	acpi_cpu_flags flags;
 
-	ACPI_FUNCTION_TRACE("ev_walk_gpe_list");
+	ACPI_FUNCTION_TRACE(ev_walk_gpe_list);
 
 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
 
@@ -146,10 +146,12 @@
 
 	gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
 	while (gpe_xrupt_info) {
+
 		/* Walk all Gpe Blocks attached to this interrupt level */
 
 		gpe_block = gpe_xrupt_info->gpe_block_list_head;
 		while (gpe_block) {
+
 			/* One callback per GPE block */
 
 			status = gpe_walk_callback(gpe_xrupt_info, gpe_block);
@@ -190,11 +192,12 @@
 	acpi_native_uint i;
 	acpi_native_uint j;
 
-	ACPI_FUNCTION_TRACE("ev_delete_gpe_handlers");
+	ACPI_FUNCTION_TRACE(ev_delete_gpe_handlers);
 
 	/* Examine each GPE Register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
+
 		/* Now look at the individual GPEs in this byte register */
 
 		for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
@@ -204,7 +207,7 @@
 
 			if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 			    ACPI_GPE_DISPATCH_HANDLER) {
-				ACPI_MEM_FREE(gpe_event_info->dispatch.handler);
+				ACPI_FREE(gpe_event_info->dispatch.handler);
 				gpe_event_info->dispatch.handler = NULL;
 				gpe_event_info->flags &=
 				    ~ACPI_GPE_DISPATCH_MASK;
@@ -248,7 +251,7 @@
 	u8 type;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_save_method_info");
+	ACPI_FUNCTION_TRACE(ev_save_method_info);
 
 	/*
 	 * _Lxx and _Exx GPE method support
@@ -279,9 +282,9 @@
 	default:
 		/* Unknown method type, just ignore it! */
 
-		ACPI_ERROR((AE_INFO,
-			    "Unknown GPE method type: %s (name not of form _Lxx or _Exx)",
-			    name));
+		ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+				  "Ignoring unknown GPE method type: %s (name not of form _Lxx or _Exx)",
+				  name));
 		return_ACPI_STATUS(AE_OK);
 	}
 
@@ -289,11 +292,12 @@
 
 	gpe_number = ACPI_STRTOUL(&name[2], NULL, 16);
 	if (gpe_number == ACPI_UINT32_MAX) {
+
 		/* Conversion failed; invalid method, just ignore it */
 
-		ACPI_ERROR((AE_INFO,
-			    "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)",
-			    name));
+		ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
+				  "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)",
+				  name));
 		return_ACPI_STATUS(AE_OK);
 	}
 
@@ -364,13 +368,14 @@
 	u32 gpe_number;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_match_prw_and_gpe");
+	ACPI_FUNCTION_TRACE(ev_match_prw_and_gpe);
 
 	/* Check for a _PRW method under this device */
 
 	status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW,
 					 ACPI_BTYPE_PACKAGE, &pkg_desc);
 	if (ACPI_FAILURE(status)) {
+
 		/* Ignore all errors from _PRW, we don't want to abort the subsystem */
 
 		return_ACPI_STATUS(AE_OK);
@@ -394,6 +399,7 @@
 	obj_desc = pkg_desc->package.elements[0];
 
 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
 		/* Use FADT-defined GPE device (from definition of _PRW) */
 
 		target_gpe_device = acpi_gbl_fadt_gpe_device;
@@ -402,6 +408,7 @@
 
 		gpe_number = (u32) obj_desc->integer.value;
 	} else if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
+
 		/* Package contains a GPE reference and GPE number within a GPE block */
 
 		if ((obj_desc->package.count < 2) ||
@@ -482,7 +489,7 @@
 	acpi_status status;
 	acpi_cpu_flags flags;
 
-	ACPI_FUNCTION_TRACE("ev_get_gpe_xrupt_block");
+	ACPI_FUNCTION_TRACE(ev_get_gpe_xrupt_block);
 
 	/* No need for lock since we are not changing any list elements here */
 
@@ -497,7 +504,7 @@
 
 	/* Not found, must allocate a new xrupt descriptor */
 
-	gpe_xrupt = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_xrupt_info));
+	gpe_xrupt = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_xrupt_info));
 	if (!gpe_xrupt) {
 		return_PTR(NULL);
 	}
@@ -556,7 +563,7 @@
 	acpi_status status;
 	acpi_cpu_flags flags;
 
-	ACPI_FUNCTION_TRACE("ev_delete_gpe_xrupt");
+	ACPI_FUNCTION_TRACE(ev_delete_gpe_xrupt);
 
 	/* We never want to remove the SCI interrupt handler */
 
@@ -588,7 +595,7 @@
 
 	/* Free the block */
 
-	ACPI_MEM_FREE(gpe_xrupt);
+	ACPI_FREE(gpe_xrupt);
 	return_ACPI_STATUS(AE_OK);
 }
 
@@ -614,7 +621,7 @@
 	acpi_status status;
 	acpi_cpu_flags flags;
 
-	ACPI_FUNCTION_TRACE("ev_install_gpe_block");
+	ACPI_FUNCTION_TRACE(ev_install_gpe_block);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 	if (ACPI_FAILURE(status)) {
@@ -667,7 +674,7 @@
 	acpi_status status;
 	acpi_cpu_flags flags;
 
-	ACPI_FUNCTION_TRACE("ev_install_gpe_block");
+	ACPI_FUNCTION_TRACE(ev_install_gpe_block);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 	if (ACPI_FAILURE(status)) {
@@ -679,6 +686,7 @@
 	status = acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block);
 
 	if (!gpe_block->previous && !gpe_block->next) {
+
 		/* This is the last gpe_block on this interrupt */
 
 		status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
@@ -704,9 +712,9 @@
 
 	/* Free the gpe_block */
 
-	ACPI_MEM_FREE(gpe_block->register_info);
-	ACPI_MEM_FREE(gpe_block->event_info);
-	ACPI_MEM_FREE(gpe_block);
+	ACPI_FREE(gpe_block->register_info);
+	ACPI_FREE(gpe_block->event_info);
+	ACPI_FREE(gpe_block);
 
       unlock_and_exit:
 	status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
@@ -736,17 +744,17 @@
 	acpi_native_uint j;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_create_gpe_info_blocks");
+	ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
 
 	/* Allocate the GPE register information block */
 
-	gpe_register_info = ACPI_MEM_CALLOCATE((acpi_size) gpe_block->
-					       register_count *
-					       sizeof(struct
-						      acpi_gpe_register_info));
+	gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->
+						 register_count *
+						 sizeof(struct
+							acpi_gpe_register_info));
 	if (!gpe_register_info) {
 		ACPI_ERROR((AE_INFO,
-			    "Could not allocate the gpe_register_info table"));
+			    "Could not allocate the GpeRegisterInfo table"));
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
@@ -754,13 +762,14 @@
 	 * Allocate the GPE event_info block. There are eight distinct GPEs
 	 * per register. Initialization to zeros is sufficient.
 	 */
-	gpe_event_info = ACPI_MEM_CALLOCATE(((acpi_size) gpe_block->
-					     register_count *
-					     ACPI_GPE_REGISTER_WIDTH) *
-					    sizeof(struct acpi_gpe_event_info));
+	gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block->
+					       register_count *
+					       ACPI_GPE_REGISTER_WIDTH) *
+					      sizeof(struct
+						     acpi_gpe_event_info));
 	if (!gpe_event_info) {
 		ACPI_ERROR((AE_INFO,
-			    "Could not allocate the gpe_event_info table"));
+			    "Could not allocate the GpeEventInfo table"));
 		status = AE_NO_MEMORY;
 		goto error_exit;
 	}
@@ -780,6 +789,7 @@
 	this_event = gpe_event_info;
 
 	for (i = 0; i < gpe_block->register_count; i++) {
+
 		/* Init the register_info for this GPE register (8 GPEs) */
 
 		this_register->base_gpe_number =
@@ -839,10 +849,10 @@
 
       error_exit:
 	if (gpe_register_info) {
-		ACPI_MEM_FREE(gpe_register_info);
+		ACPI_FREE(gpe_register_info);
 	}
 	if (gpe_event_info) {
-		ACPI_MEM_FREE(gpe_event_info);
+		ACPI_FREE(gpe_event_info);
 	}
 
 	return_ACPI_STATUS(status);
@@ -878,7 +888,7 @@
 	acpi_status status;
 	struct acpi_gpe_block_info *gpe_block;
 
-	ACPI_FUNCTION_TRACE("ev_create_gpe_block");
+	ACPI_FUNCTION_TRACE(ev_create_gpe_block);
 
 	if (!register_count) {
 		return_ACPI_STATUS(AE_OK);
@@ -886,7 +896,7 @@
 
 	/* Allocate a new GPE block */
 
-	gpe_block = ACPI_MEM_CALLOCATE(sizeof(struct acpi_gpe_block_info));
+	gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
 	if (!gpe_block) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -906,7 +916,7 @@
 	 */
 	status = acpi_ev_create_gpe_info_blocks(gpe_block);
 	if (ACPI_FAILURE(status)) {
-		ACPI_MEM_FREE(gpe_block);
+		ACPI_FREE(gpe_block);
 		return_ACPI_STATUS(status);
 	}
 
@@ -914,7 +924,7 @@
 
 	status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
 	if (ACPI_FAILURE(status)) {
-		ACPI_MEM_FREE(gpe_block);
+		ACPI_FREE(gpe_block);
 		return_ACPI_STATUS(status);
 	}
 
@@ -971,7 +981,7 @@
 	acpi_native_uint i;
 	acpi_native_uint j;
 
-	ACPI_FUNCTION_TRACE("ev_initialize_gpe_block");
+	ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
 
 	/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
 
@@ -1013,6 +1023,7 @@
 
 	for (i = 0; i < gpe_block->register_count; i++) {
 		for (j = 0; j < 8; j++) {
+
 			/* Get the info block for this particular GPE */
 
 			gpe_event_info =
@@ -1040,7 +1051,7 @@
 
 	status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block);
 	if (ACPI_FAILURE(status)) {
-		ACPI_ERROR((AE_INFO, "Could not enable GPEs in gpe_block %p",
+		ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p",
 			    gpe_block));
 	}
 
@@ -1066,7 +1077,7 @@
 	u32 gpe_number_max = 0;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_gpe_initialize");
+	ACPI_FUNCTION_TRACE(ev_gpe_initialize);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
@@ -1099,6 +1110,7 @@
 	 * particular block is not supported.
 	 */
 	if (acpi_gbl_FADT->gpe0_blk_len && acpi_gbl_FADT->xgpe0_blk.address) {
+
 		/* GPE block 0 exists (has both length and address > 0) */
 
 		register_count0 = (u16) (acpi_gbl_FADT->gpe0_blk_len / 2);
@@ -1121,6 +1133,7 @@
 	}
 
 	if (acpi_gbl_FADT->gpe1_blk_len && acpi_gbl_FADT->xgpe1_blk.address) {
+
 		/* GPE block 1 exists (has both length and address > 0) */
 
 		register_count1 = (u16) (acpi_gbl_FADT->gpe1_blk_len / 2);
@@ -1168,6 +1181,7 @@
 	/* Exit if there are no GPE registers */
 
 	if ((register_count0 + register_count1) == 0) {
+
 		/* GPEs are not required by ACPI, this is OK */
 
 		ACPI_DEBUG_PRINT((ACPI_DB_INIT,
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index 0909ba6..6eef4ef 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -49,12 +49,13 @@
 #define _COMPONENT          ACPI_EVENTS
 ACPI_MODULE_NAME("evmisc")
 
+/* Names for Notify() values, used for debug output */
 #ifdef ACPI_DEBUG_OUTPUT
 static const char *acpi_notify_value_names[] = {
 	"Bus Check",
 	"Device Check",
 	"Device Wake",
-	"Eject request",
+	"Eject Request",
 	"Device Check Light",
 	"Frequency Mismatch",
 	"Bus Mode Mismatch",
@@ -124,7 +125,7 @@
 	union acpi_generic_state *notify_info;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_NAME("ev_queue_notify_request");
+	ACPI_FUNCTION_NAME(ev_queue_notify_request);
 
 	/*
 	 * For value 3 (Ejection Request), some device method may need to be run.
@@ -150,6 +151,7 @@
 
 	obj_desc = acpi_ns_get_attached_object(node);
 	if (obj_desc) {
+
 		/* We have the notify object, Get the right handler */
 
 		switch (node->type) {
@@ -184,14 +186,15 @@
 			return (AE_NO_MEMORY);
 		}
 
-		notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY;
+		notify_info->common.descriptor_type =
+		    ACPI_DESC_TYPE_STATE_NOTIFY;
 		notify_info->notify.node = node;
 		notify_info->notify.value = (u16) notify_value;
 		notify_info->notify.handler_obj = handler_obj;
 
-		status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
-						     acpi_ev_notify_dispatch,
-						     notify_info);
+		status =
+		    acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
+				    notify_info);
 		if (ACPI_FAILURE(status)) {
 			acpi_ut_delete_generic_state(notify_info);
 		}
@@ -240,6 +243,7 @@
 	 * to the device.
 	 */
 	if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) {
+
 		/* Global system notification handler */
 
 		if (acpi_gbl_system_notify.handler) {
@@ -297,6 +301,7 @@
 	/* Signal threads that are waiting for the lock */
 
 	if (acpi_gbl_global_lock_thread_count) {
+
 		/* Send sufficient units to the semaphore */
 
 		status =
@@ -335,15 +340,16 @@
 	 */
 	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
 	if (acquired) {
+
 		/* Got the lock, now wake all threads waiting for it */
 
 		acpi_gbl_global_lock_acquired = TRUE;
 
 		/* Run the Global Lock thread which will signal all waiting threads */
 
-		status = acpi_os_queue_for_execution(OSD_PRIORITY_HIGH,
-						     acpi_ev_global_lock_thread,
-						     context);
+		status =
+		    acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER,
+				    acpi_ev_global_lock_thread, context);
 		if (ACPI_FAILURE(status)) {
 			ACPI_EXCEPTION((AE_INFO, status,
 					"Could not queue Global Lock thread"));
@@ -371,7 +377,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_init_global_lock_handler");
+	ACPI_FUNCTION_TRACE(ev_init_global_lock_handler);
 
 	acpi_gbl_global_lock_present = TRUE;
 	status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
@@ -413,7 +419,7 @@
 	acpi_status status = AE_OK;
 	u8 acquired = FALSE;
 
-	ACPI_FUNCTION_TRACE("ev_acquire_global_lock");
+	ACPI_FUNCTION_TRACE(ev_acquire_global_lock);
 
 #ifndef ACPI_APPLICATION
 	/* Make sure that we actually have a global lock */
@@ -439,6 +445,7 @@
 
 	ACPI_ACQUIRE_GLOBAL_LOCK(acpi_gbl_common_fACS.global_lock, acquired);
 	if (acquired) {
+
 		/* We got the lock */
 
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -458,8 +465,9 @@
 	 * Acquire the global lock semaphore first.
 	 * Since this wait will block, we must release the interpreter
 	 */
-	status = acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
-					       timeout);
+	status =
+	    acpi_ex_system_wait_semaphore(acpi_gbl_global_lock_semaphore,
+					  timeout);
 	return_ACPI_STATUS(status);
 }
 
@@ -480,7 +488,7 @@
 	u8 pending = FALSE;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ev_release_global_lock");
+	ACPI_FUNCTION_TRACE(ev_release_global_lock);
 
 	if (!acpi_gbl_global_lock_thread_count) {
 		ACPI_WARNING((AE_INFO,
@@ -492,6 +500,7 @@
 
 	acpi_gbl_global_lock_thread_count--;
 	if (acpi_gbl_global_lock_thread_count) {
+
 		/* There are still some threads holding the lock, cannot release */
 
 		return_ACPI_STATUS(AE_OK);
@@ -533,7 +542,7 @@
 	acpi_native_uint i;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_terminate");
+	ACPI_FUNCTION_TRACE(ev_terminate);
 
 	if (acpi_gbl_events_initialized) {
 		/*
@@ -573,7 +582,7 @@
 	if (acpi_gbl_original_mode == ACPI_SYS_MODE_LEGACY) {
 		status = acpi_disable();
 		if (ACPI_FAILURE(status)) {
-			ACPI_WARNING((AE_INFO, "acpi_disable failed"));
+			ACPI_WARNING((AE_INFO, "AcpiDisable failed"));
 		}
 	}
 	return_VOID;
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 6da58e7..094a17e 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -83,7 +83,7 @@
 	acpi_status status;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE("ev_install_region_handlers");
+	ACPI_FUNCTION_TRACE(ev_install_region_handlers);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
@@ -153,7 +153,7 @@
 	acpi_status status;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE("ev_initialize_op_regions");
+	ACPI_FUNCTION_TRACE(ev_initialize_op_regions);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
@@ -164,6 +164,7 @@
 	 * Run the _REG methods for op_regions in each default address space
 	 */
 	for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {
+
 		/* TBD: Make sure handler is the DEFAULT handler, otherwise
 		 * _REG will have already been run.
 		 */
@@ -192,12 +193,12 @@
 acpi_status
 acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)
 {
-	struct acpi_parameter_info info;
-	union acpi_operand_object *params[3];
+	struct acpi_evaluate_info *info;
+	union acpi_operand_object *args[3];
 	union acpi_operand_object *region_obj2;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_execute_reg_method");
+	ACPI_FUNCTION_TRACE(ev_execute_reg_method);
 
 	region_obj2 = acpi_ns_get_secondary_object(region_obj);
 	if (!region_obj2) {
@@ -208,48 +209,60 @@
 		return_ACPI_STATUS(AE_OK);
 	}
 
-	/*
-	 * The _REG method has two arguments:
-	 *
-	 * Arg0, Integer: Operation region space ID
-	 *          Same value as region_obj->Region.space_id
-	 * Arg1, Integer: connection status
-	 *          1 for connecting the handler,
-	 *          0 for disconnecting the handler
-	 *          Passed as a parameter
-	 */
-	params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
-	if (!params[0]) {
+	/* Allocate and initialize the evaluation information block */
+
+	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+	if (!info) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
-	params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
-	if (!params[1]) {
+	info->prefix_node = region_obj2->extra.method_REG;
+	info->pathname = NULL;
+	info->parameters = args;
+	info->parameter_type = ACPI_PARAM_ARGS;
+	info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+	/*
+	 * The _REG method has two arguments:
+	 *
+	 * Arg0 - Integer:
+	 *  Operation region space ID Same value as region_obj->Region.space_id
+	 *
+	 * Arg1 - Integer:
+	 *  connection status 1 for connecting the handler, 0 for disconnecting
+	 *  the handler (Passed as a parameter)
+	 */
+	args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+	if (!args[0]) {
 		status = AE_NO_MEMORY;
-		goto cleanup;
+		goto cleanup1;
+	}
+
+	args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+	if (!args[1]) {
+		status = AE_NO_MEMORY;
+		goto cleanup2;
 	}
 
 	/* Setup the parameter objects */
 
-	params[0]->integer.value = region_obj->region.space_id;
-	params[1]->integer.value = function;
-	params[2] = NULL;
-
-	info.node = region_obj2->extra.method_REG;
-	info.parameters = params;
-	info.parameter_type = ACPI_PARAM_ARGS;
+	args[0]->integer.value = region_obj->region.space_id;
+	args[1]->integer.value = function;
+	args[2] = NULL;
 
 	/* Execute the method, no return value */
 
 	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
-			(ACPI_TYPE_METHOD, info.node, NULL));
-	status = acpi_ns_evaluate_by_handle(&info);
+			(ACPI_TYPE_METHOD, info->prefix_node, NULL));
 
-	acpi_ut_remove_reference(params[1]);
+	status = acpi_ns_evaluate(info);
+	acpi_ut_remove_reference(args[1]);
 
-      cleanup:
-	acpi_ut_remove_reference(params[0]);
+      cleanup2:
+	acpi_ut_remove_reference(args[0]);
 
+      cleanup1:
+	ACPI_FREE(info);
 	return_ACPI_STATUS(status);
 }
 
@@ -261,7 +274,8 @@
  *              Function            - Read or Write operation
  *              Address             - Where in the space to read or write
  *              bit_width           - Field width in bits (8, 16, 32, or 64)
- *              Value               - Pointer to in or out value
+ *              Value               - Pointer to in or out value, must be
+ *                                    full 64-bit acpi_integer
  *
  * RETURN:      Status
  *
@@ -274,7 +288,7 @@
 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 			       u32 function,
 			       acpi_physical_address address,
-			       u32 bit_width, void *value)
+			       u32 bit_width, acpi_integer * value)
 {
 	acpi_status status;
 	acpi_status status2;
@@ -284,7 +298,7 @@
 	union acpi_operand_object *region_obj2;
 	void *region_context = NULL;
 
-	ACPI_FUNCTION_TRACE("ev_address_space_dispatch");
+	ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
 
 	region_obj2 = acpi_ns_get_secondary_object(region_obj);
 	if (!region_obj2) {
@@ -315,6 +329,7 @@
 		 */
 		region_setup = handler_desc->address_space.setup;
 		if (!region_setup) {
+
 			/* No initialization routine, exit with error */
 
 			ACPI_ERROR((AE_INFO,
@@ -361,9 +376,10 @@
 			region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
 
 			if (region_obj2->extra.region_context) {
+
 				/* The handler for this region was already installed */
 
-				ACPI_MEM_FREE(region_context);
+				ACPI_FREE(region_context);
 			} else {
 				/*
 				 * Save the returned context for use in all accesses to
@@ -386,9 +402,8 @@
 			  acpi_ut_get_region_name(region_obj->region.
 						  space_id)));
 
-	if (!
-	    (handler_desc->address_space.
-	     hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+	if (!(handler_desc->address_space.handler_flags &
+	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
 		 * For handlers other than the default (supplied) handlers, we must
 		 * exit the interpreter because the handler *might* block -- we don't
@@ -409,9 +424,8 @@
 							space_id)));
 	}
 
-	if (!
-	    (handler_desc->address_space.
-	     hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+	if (!(handler_desc->address_space.handler_flags &
+	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
 		 * We just returned from a non-default handler, we must re-enter the
 		 * interpreter
@@ -451,7 +465,7 @@
 	union acpi_operand_object *region_obj2;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_detach_region");
+	ACPI_FUNCTION_TRACE(ev_detach_region);
 
 	region_obj2 = acpi_ns_get_secondary_object(region_obj);
 	if (!region_obj2) {
@@ -463,6 +477,7 @@
 
 	handler_obj = region_obj->region.handler;
 	if (!handler_obj) {
+
 		/* This region has no handler, all done */
 
 		return_VOID;
@@ -474,6 +489,7 @@
 	last_obj_ptr = &handler_obj->address_space.region_list;
 
 	while (obj_desc) {
+
 		/* Is this the correct Region? */
 
 		if (obj_desc == region_obj) {
@@ -583,7 +599,7 @@
 		      u8 acpi_ns_is_locked)
 {
 
-	ACPI_FUNCTION_TRACE("ev_attach_region");
+	ACPI_FUNCTION_TRACE(ev_attach_region);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
 			  "Adding Region [%4.4s] %p to address handler %p [%s]\n",
@@ -636,7 +652,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_NAME("ev_install_handler");
+	ACPI_FUNCTION_NAME(ev_install_handler);
 
 	handler_obj = (union acpi_operand_object *)context;
 
@@ -666,6 +682,7 @@
 
 	obj_desc = acpi_ns_get_attached_object(node);
 	if (!obj_desc) {
+
 		/* No object, just exit */
 
 		return (AE_OK);
@@ -674,10 +691,12 @@
 	/* Devices are handled different than regions */
 
 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) {
+
 		/* Check if this Device already has a handler for this address space */
 
 		next_handler_obj = obj_desc->device.handler;
 		while (next_handler_obj) {
+
 			/* Found a handler, is it for the same address space? */
 
 			if (next_handler_obj->address_space.space_id ==
@@ -764,9 +783,9 @@
 	union acpi_operand_object *handler_obj;
 	acpi_status status;
 	acpi_object_type type;
-	u16 flags = 0;
+	u8 flags = 0;
 
-	ACPI_FUNCTION_TRACE("ev_install_space_handler");
+	ACPI_FUNCTION_TRACE(ev_install_space_handler);
 
 	/*
 	 * This registration is valid for only the types below
@@ -839,6 +858,7 @@
 		/* Walk the handler list for this device */
 
 		while (handler_obj) {
+
 			/* Same space_id indicates a handler already installed */
 
 			if (handler_obj->address_space.space_id == space_id) {
@@ -921,7 +941,7 @@
 	/* Init handler obj */
 
 	handler_obj->address_space.space_id = (u8) space_id;
-	handler_obj->address_space.hflags = flags;
+	handler_obj->address_space.handler_flags = flags;
 	handler_obj->address_space.region_list = NULL;
 	handler_obj->address_space.node = node;
 	handler_obj->address_space.handler = handler;
@@ -979,7 +999,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_execute_reg_methods");
+	ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
 
 	/*
 	 * Run all _REG methods for all Operation Regions for this
@@ -1001,7 +1021,7 @@
  *
  * PARAMETERS:  walk_namespace callback
  *
- * DESCRIPTION: Run _REg method for region objects of the requested space_iD
+ * DESCRIPTION: Run _REG method for region objects of the requested space_iD
  *
  ******************************************************************************/
 
@@ -1035,6 +1055,7 @@
 
 	obj_desc = acpi_ns_get_attached_object(node);
 	if (!obj_desc) {
+
 		/* No object, just exit */
 
 		return (AE_OK);
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index baed8c1..5b3c7a8 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -71,11 +71,22 @@
 	    (union acpi_operand_object *)handle;
 	struct acpi_mem_space_context *local_region_context;
 
-	ACPI_FUNCTION_TRACE("ev_system_memory_region_setup");
+	ACPI_FUNCTION_TRACE(ev_system_memory_region_setup);
 
 	if (function == ACPI_REGION_DEACTIVATE) {
 		if (*region_context) {
-			ACPI_MEM_FREE(*region_context);
+			local_region_context =
+			    (struct acpi_mem_space_context *)*region_context;
+
+			/* Delete a cached mapping if present */
+
+			if (local_region_context->mapped_length) {
+				acpi_os_unmap_memory(local_region_context->
+						     mapped_logical_address,
+						     local_region_context->
+						     mapped_length);
+			}
+			ACPI_FREE(local_region_context);
 			*region_context = NULL;
 		}
 		return_ACPI_STATUS(AE_OK);
@@ -84,7 +95,7 @@
 	/* Create a new context */
 
 	local_region_context =
-	    ACPI_MEM_CALLOCATE(sizeof(struct acpi_mem_space_context));
+	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_mem_space_context));
 	if (!(local_region_context)) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -118,7 +129,7 @@
 			      u32 function,
 			      void *handler_context, void **region_context)
 {
-	ACPI_FUNCTION_TRACE("ev_io_space_region_setup");
+	ACPI_FUNCTION_TRACE(ev_io_space_region_setup);
 
 	if (function == ACPI_REGION_DEACTIVATE) {
 		*region_context = NULL;
@@ -161,7 +172,7 @@
 	    (union acpi_operand_object *)handle;
 	struct acpi_device_id object_hID;
 
-	ACPI_FUNCTION_TRACE("ev_pci_config_region_setup");
+	ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
 
 	handler_obj = region_obj->region.handler;
 	if (!handler_obj) {
@@ -178,7 +189,7 @@
 	*region_context = NULL;
 	if (function == ACPI_REGION_DEACTIVATE) {
 		if (pci_id) {
-			ACPI_MEM_FREE(pci_id);
+			ACPI_FREE(pci_id);
 		}
 		return_ACPI_STATUS(status);
 	}
@@ -199,6 +210,7 @@
 	 * handlers with that device.
 	 */
 	if (handler_obj->address_space.node == acpi_gbl_root_node) {
+
 		/* Start search from the parent object */
 
 		pci_root_node = parent_node;
@@ -220,6 +232,7 @@
 					PCI_EXPRESS_ROOT_HID_STRING,
 					sizeof(PCI_EXPRESS_ROOT_HID_STRING)))))
 				{
+
 					/* Install a handler for this PCI root bridge */
 
 					status =
@@ -235,7 +248,7 @@
 						} else {
 							ACPI_EXCEPTION((AE_INFO,
 									status,
-									"Could not install pci_config handler for Root Bridge %4.4s",
+									"Could not install PciConfig handler for Root Bridge %4.4s",
 									acpi_ut_get_node_name
 									(pci_root_node)));
 						}
@@ -262,7 +275,7 @@
 
 	/* Region is still not initialized. Create a new context */
 
-	pci_id = ACPI_MEM_CALLOCATE(sizeof(struct acpi_pci_id));
+	pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id));
 	if (!pci_id) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -337,7 +350,7 @@
 			     u32 function,
 			     void *handler_context, void **region_context)
 {
-	ACPI_FUNCTION_TRACE("ev_pci_bar_region_setup");
+	ACPI_FUNCTION_TRACE(ev_pci_bar_region_setup);
 
 	return_ACPI_STATUS(AE_OK);
 }
@@ -364,7 +377,7 @@
 			  u32 function,
 			  void *handler_context, void **region_context)
 {
-	ACPI_FUNCTION_TRACE("ev_cmos_region_setup");
+	ACPI_FUNCTION_TRACE(ev_cmos_region_setup);
 
 	return_ACPI_STATUS(AE_OK);
 }
@@ -389,7 +402,7 @@
 			     u32 function,
 			     void *handler_context, void **region_context)
 {
-	ACPI_FUNCTION_TRACE("ev_default_region_setup");
+	ACPI_FUNCTION_TRACE(ev_default_region_setup);
 
 	if (function == ACPI_REGION_DEACTIVATE) {
 		*region_context = NULL;
@@ -435,7 +448,7 @@
 	acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
 	union acpi_operand_object *region_obj2;
 
-	ACPI_FUNCTION_TRACE_U32("ev_initialize_region", acpi_ns_locked);
+	ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);
 
 	if (!region_obj) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -462,8 +475,9 @@
 
 	/* Find any "_REG" method associated with this region definition */
 
-	status = acpi_ns_search_node(*reg_name_ptr, node,
-				     ACPI_TYPE_METHOD, &method_node);
+	status =
+	    acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
+				     &method_node);
 	if (ACPI_SUCCESS(status)) {
 		/*
 		 * The _REG method is optional and there can be only one per region
@@ -478,11 +492,13 @@
 	 * ie: acpi_gbl_root_node->parent_entry being set to NULL
 	 */
 	while (node) {
+
 		/* Check to see if a handler exists */
 
 		handler_obj = NULL;
 		obj_desc = acpi_ns_get_attached_object(node);
 		if (obj_desc) {
+
 			/* Can only be a handler if the object exists */
 
 			switch (node->type) {
@@ -507,10 +523,12 @@
 			}
 
 			while (handler_obj) {
+
 				/* Is this handler of the correct type? */
 
 				if (handler_obj->address_space.space_id ==
 				    space_id) {
+
 					/* Found correct handler */
 
 					ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
@@ -571,7 +589,7 @@
 	/* If we get here, there is no handler for this region */
 
 	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-			  "No handler for region_type %s(%X) (region_obj %p)\n",
+			  "No handler for RegionType %s(%X) (RegionObj %p)\n",
 			  acpi_ut_get_region_name(space_id), space_id,
 			  region_obj));
 
diff --git a/drivers/acpi/events/evsci.c b/drivers/acpi/events/evsci.c
index 9a62216..8106215 100644
--- a/drivers/acpi/events/evsci.c
+++ b/drivers/acpi/events/evsci.c
@@ -69,7 +69,7 @@
 	struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
 	u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
 
-	ACPI_FUNCTION_TRACE("ev_sci_xrupt_handler");
+	ACPI_FUNCTION_TRACE(ev_sci_xrupt_handler);
 
 	/*
 	 * We are guaranteed by the ACPI CA initialization/shutdown code that
@@ -108,7 +108,7 @@
 	struct acpi_gpe_xrupt_info *gpe_xrupt_list = context;
 	u32 interrupt_handled = ACPI_INTERRUPT_NOT_HANDLED;
 
-	ACPI_FUNCTION_TRACE("ev_gpe_xrupt_handler");
+	ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
 
 	/*
 	 * We are guaranteed by the ACPI CA initialization/shutdown code that
@@ -140,7 +140,7 @@
 {
 	u32 status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ev_install_sci_handler");
+	ACPI_FUNCTION_TRACE(ev_install_sci_handler);
 
 	status = acpi_os_install_interrupt_handler((u32) acpi_gbl_FADT->sci_int,
 						   acpi_ev_sci_xrupt_handler,
@@ -171,7 +171,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ev_remove_sci_handler");
+	ACPI_FUNCTION_TRACE(ev_remove_sci_handler);
 
 	/* Just let the OS remove the handler and disable the level */
 
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index b38b39d..76c34a6 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
@@ -68,7 +66,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_install_exception_handler");
+	ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 	if (ACPI_FAILURE(status)) {
@@ -90,6 +88,8 @@
 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 	return_ACPI_STATUS(status);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
 #endif				/*  ACPI_FUTURE_USAGE  */
 
 /*******************************************************************************
@@ -107,14 +107,13 @@
  *              event.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_install_fixed_event_handler(u32 event,
 				 acpi_event_handler handler, void *context)
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_install_fixed_event_handler");
+	ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
 
 	/* Parameter validation */
 
@@ -161,7 +160,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_install_fixed_event_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
 
 /*******************************************************************************
  *
@@ -175,13 +174,12 @@
  * DESCRIPTION: Disables the event and unregisters the event handler.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("acpi_remove_fixed_event_handler");
+	ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
 
 	/* Parameter validation */
 
@@ -216,7 +214,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
 
 /*******************************************************************************
  *
@@ -235,7 +233,6 @@
  * DESCRIPTION: Install a handler for notifies on an ACPI device
  *
  ******************************************************************************/
-
 acpi_status
 acpi_install_notify_handler(acpi_handle device,
 			    u32 handler_type,
@@ -246,7 +243,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_install_notify_handler");
+	ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
 
 	/* Parameter validation */
 
@@ -275,6 +272,7 @@
 	 * only one <external> global handler can be regsitered (per notify type).
 	 */
 	if (device == ACPI_ROOT_OBJECT) {
+
 		/* Make sure the handler is not already installed */
 
 		if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
@@ -317,6 +315,7 @@
 
 		obj_desc = acpi_ns_get_attached_object(node);
 		if (obj_desc) {
+
 			/* Object exists - make sure there's no handler */
 
 			if (((handler_type & ACPI_SYSTEM_NOTIFY) &&
@@ -370,6 +369,7 @@
 		}
 
 		if (handler_type == ACPI_ALL_NOTIFY) {
+
 			/* Extra ref if installed in both */
 
 			acpi_ut_add_reference(notify_obj);
@@ -381,7 +381,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_install_notify_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
 
 /*******************************************************************************
  *
@@ -399,7 +399,6 @@
  * DESCRIPTION: Remove a handler for notifies on an ACPI device
  *
  ******************************************************************************/
-
 acpi_status
 acpi_remove_notify_handler(acpi_handle device,
 			   u32 handler_type, acpi_notify_handler handler)
@@ -409,7 +408,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_remove_notify_handler");
+	ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
 
 	/* Parameter validation */
 
@@ -535,7 +534,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_remove_notify_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
 
 /*******************************************************************************
  *
@@ -554,7 +553,6 @@
  * DESCRIPTION: Install a handler for a General Purpose Event.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_install_gpe_handler(acpi_handle gpe_device,
 			 u32 gpe_number,
@@ -565,7 +563,7 @@
 	acpi_status status;
 	acpi_cpu_flags flags;
 
-	ACPI_FUNCTION_TRACE("acpi_install_gpe_handler");
+	ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
 
 	/* Parameter validation */
 
@@ -596,7 +594,7 @@
 
 	/* Allocate and init handler object */
 
-	handler = ACPI_MEM_CALLOCATE(sizeof(struct acpi_handler_info));
+	handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_handler_info));
 	if (!handler) {
 		status = AE_NO_MEMORY;
 		goto unlock_and_exit;
@@ -630,7 +628,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_install_gpe_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
 
 /*******************************************************************************
  *
@@ -646,7 +644,6 @@
  * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_remove_gpe_handler(acpi_handle gpe_device,
 			u32 gpe_number, acpi_event_handler address)
@@ -656,7 +653,7 @@
 	acpi_status status;
 	acpi_cpu_flags flags;
 
-	ACPI_FUNCTION_TRACE("acpi_remove_gpe_handler");
+	ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
 
 	/* Parameter validation */
 
@@ -724,14 +721,14 @@
 
 	/* Now we can free the handler object */
 
-	ACPI_MEM_FREE(handler);
+	ACPI_FREE(handler);
 
       unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_remove_gpe_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
 
 /*******************************************************************************
  *
@@ -746,7 +743,6 @@
  * DESCRIPTION: Acquire the ACPI Global Lock
  *
  ******************************************************************************/
-
 acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
 {
 	acpi_status status;
@@ -771,7 +767,7 @@
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_acquire_global_lock);
+ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
 
 /*******************************************************************************
  *
@@ -784,7 +780,6 @@
  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
  *
  ******************************************************************************/
-
 acpi_status acpi_release_global_lock(u32 handle)
 {
 	acpi_status status;
@@ -797,4 +792,4 @@
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_release_global_lock);
+ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index ec9ce84..7ebc2ef 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acevents.h>
 #include <acpi/acnamesp.h>
@@ -65,7 +63,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("acpi_enable");
+	ACPI_FUNCTION_TRACE(acpi_enable);
 
 	/* Make sure we have the FADT */
 
@@ -94,6 +92,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_enable)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_disable
@@ -105,12 +105,11 @@
  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
  *
  ******************************************************************************/
-
 acpi_status acpi_disable(void)
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("acpi_disable");
+	ACPI_FUNCTION_TRACE(acpi_disable);
 
 	if (!acpi_gbl_FADT) {
 		ACPI_WARNING((AE_INFO, "No FADT information present!"));
@@ -137,6 +136,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_disable)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enable_event
@@ -149,13 +150,12 @@
  * DESCRIPTION: Enable an ACPI event (fixed)
  *
  ******************************************************************************/
-
 acpi_status acpi_enable_event(u32 event, u32 flags)
 {
 	acpi_status status = AE_OK;
 	u32 value;
 
-	ACPI_FUNCTION_TRACE("acpi_enable_event");
+	ACPI_FUNCTION_TRACE(acpi_enable_event);
 
 	/* Decode the Fixed Event */
 
@@ -193,7 +193,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_enable_event);
+ACPI_EXPORT_SYMBOL(acpi_enable_event)
 
 /*******************************************************************************
  *
@@ -208,13 +208,12 @@
  * DESCRIPTION: Set the type of an individual GPE
  *
  ******************************************************************************/
-
 acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
 {
 	acpi_status status = AE_OK;
 	struct acpi_gpe_event_info *gpe_event_info;
 
-	ACPI_FUNCTION_TRACE("acpi_set_gpe_type");
+	ACPI_FUNCTION_TRACE(acpi_set_gpe_type);
 
 	/* Ensure that we have a valid GPE number */
 
@@ -236,7 +235,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_set_gpe_type);
+ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
 
 /*******************************************************************************
  *
@@ -252,13 +251,12 @@
  * DESCRIPTION: Enable an ACPI event (general purpose)
  *
  ******************************************************************************/
-
 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
 {
 	acpi_status status = AE_OK;
 	struct acpi_gpe_event_info *gpe_event_info;
 
-	ACPI_FUNCTION_TRACE("acpi_enable_gpe");
+	ACPI_FUNCTION_TRACE(acpi_enable_gpe);
 
 	/* Use semaphore lock if not executing at interrupt level */
 
@@ -288,7 +286,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_enable_gpe);
+ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
 
 /*******************************************************************************
  *
@@ -304,13 +302,12 @@
  * DESCRIPTION: Disable an ACPI event (general purpose)
  *
  ******************************************************************************/
-
 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
 {
 	acpi_status status = AE_OK;
 	struct acpi_gpe_event_info *gpe_event_info;
 
-	ACPI_FUNCTION_TRACE("acpi_disable_gpe");
+	ACPI_FUNCTION_TRACE(acpi_disable_gpe);
 
 	/* Use semaphore lock if not executing at interrupt level */
 
@@ -338,6 +335,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_disable_event
@@ -350,13 +349,12 @@
  * DESCRIPTION: Disable an ACPI event (fixed)
  *
  ******************************************************************************/
-
 acpi_status acpi_disable_event(u32 event, u32 flags)
 {
 	acpi_status status = AE_OK;
 	u32 value;
 
-	ACPI_FUNCTION_TRACE("acpi_disable_event");
+	ACPI_FUNCTION_TRACE(acpi_disable_event);
 
 	/* Decode the Fixed Event */
 
@@ -392,7 +390,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_disable_event);
+ACPI_EXPORT_SYMBOL(acpi_disable_event)
 
 /*******************************************************************************
  *
@@ -405,12 +403,11 @@
  * DESCRIPTION: Clear an ACPI event (fixed)
  *
  ******************************************************************************/
-
 acpi_status acpi_clear_event(u32 event)
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("acpi_clear_event");
+	ACPI_FUNCTION_TRACE(acpi_clear_event);
 
 	/* Decode the Fixed Event */
 
@@ -429,7 +426,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_clear_event);
+ACPI_EXPORT_SYMBOL(acpi_clear_event)
 
 /*******************************************************************************
  *
@@ -444,13 +441,12 @@
  * DESCRIPTION: Clear an ACPI event (general purpose)
  *
  ******************************************************************************/
-
 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
 {
 	acpi_status status = AE_OK;
 	struct acpi_gpe_event_info *gpe_event_info;
 
-	ACPI_FUNCTION_TRACE("acpi_clear_gpe");
+	ACPI_FUNCTION_TRACE(acpi_clear_gpe);
 
 	/* Use semaphore lock if not executing at interrupt level */
 
@@ -478,6 +474,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
+
 #ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
@@ -492,12 +490,11 @@
  * DESCRIPTION: Obtains and returns the current status of the event
  *
  ******************************************************************************/
-
 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("acpi_get_event_status");
+	ACPI_FUNCTION_TRACE(acpi_get_event_status);
 
 	if (!event_status) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -518,6 +515,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_event_status)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_gpe_status
@@ -533,7 +532,6 @@
  * DESCRIPTION: Get status of an event (general purpose)
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_gpe_status(acpi_handle gpe_device,
 		    u32 gpe_number, u32 flags, acpi_event_status * event_status)
@@ -541,7 +539,7 @@
 	acpi_status status = AE_OK;
 	struct acpi_gpe_event_info *gpe_event_info;
 
-	ACPI_FUNCTION_TRACE("acpi_get_gpe_status");
+	ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
 
 	/* Use semaphore lock if not executing at interrupt level */
 
@@ -570,6 +568,8 @@
 	}
 	return_ACPI_STATUS(status);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
 #endif				/*  ACPI_FUTURE_USAGE  */
 
 /*******************************************************************************
@@ -586,7 +586,6 @@
  * DESCRIPTION: Create and Install a block of GPE registers
  *
  ******************************************************************************/
-
 acpi_status
 acpi_install_gpe_block(acpi_handle gpe_device,
 		       struct acpi_generic_address *gpe_block_address,
@@ -597,7 +596,7 @@
 	struct acpi_namespace_node *node;
 	struct acpi_gpe_block_info *gpe_block;
 
-	ACPI_FUNCTION_TRACE("acpi_install_gpe_block");
+	ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
 
 	if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -636,6 +635,7 @@
 
 	obj_desc = acpi_ns_get_attached_object(node);
 	if (!obj_desc) {
+
 		/* No object, create a new one */
 
 		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
@@ -665,7 +665,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_install_gpe_block);
+ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
 
 /*******************************************************************************
  *
@@ -678,14 +678,13 @@
  * DESCRIPTION: Remove a previously installed block of GPE registers
  *
  ******************************************************************************/
-
 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("acpi_remove_gpe_block");
+	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
 
 	if (!gpe_device) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -721,4 +720,4 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_remove_gpe_block);
+ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
diff --git a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c
index abf5cac..e8b86a0 100644
--- a/drivers/acpi/events/evxfregn.c
+++ b/drivers/acpi/events/evxfregn.c
@@ -42,8 +42,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
@@ -75,7 +73,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_install_address_space_handler");
+	ACPI_FUNCTION_TRACE(acpi_install_address_space_handler);
 
 	/* Parameter validation */
 
@@ -114,7 +112,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_install_address_space_handler);
+ACPI_EXPORT_SYMBOL(acpi_install_address_space_handler)
 
 /*******************************************************************************
  *
@@ -129,7 +127,6 @@
  * DESCRIPTION: Remove a previously installed handler.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_remove_address_space_handler(acpi_handle device,
 				  acpi_adr_space_type space_id,
@@ -142,7 +139,7 @@
 	struct acpi_namespace_node *node;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_remove_address_space_handler");
+	ACPI_FUNCTION_TRACE(acpi_remove_address_space_handler);
 
 	/* Parameter validation */
 
@@ -176,9 +173,11 @@
 	handler_obj = obj_desc->device.handler;
 	last_obj_ptr = &obj_desc->device.handler;
 	while (handler_obj) {
+
 		/* We have a handler, see if user requested this one */
 
 		if (handler_obj->address_space.space_id == space_id) {
+
 			/* Matched space_id, first dereference this in the Regions */
 
 			ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
@@ -229,7 +228,7 @@
 	/* The handler does not exist */
 
 	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-			  "Unable to remove address handler %p for %s(%X), dev_node %p, obj %p\n",
+			  "Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n",
 			  handler, acpi_ut_get_region_name(space_id), space_id,
 			  node, obj_desc));
 
@@ -240,4 +239,4 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_remove_address_space_handler);
+ACPI_EXPORT_SYMBOL(acpi_remove_address_space_handler)
diff --git a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c
index a29782f..8233524 100644
--- a/drivers/acpi/executer/exconfig.c
+++ b/drivers/acpi/executer/exconfig.c
@@ -82,7 +82,7 @@
 	struct acpi_table_desc table_info;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_TRACE("ex_add_table");
+	ACPI_FUNCTION_TRACE(ex_add_table);
 
 	/* Create an object to be the table handle */
 
@@ -100,7 +100,7 @@
 
 	ACPI_MEMSET(&table_info, 0, sizeof(struct acpi_table_desc));
 
-	table_info.type = ACPI_TABLE_SSDT;
+	table_info.type = ACPI_TABLE_ID_SSDT;
 	table_info.pointer = table;
 	table_info.length = (acpi_size) table->length;
 	table_info.allocation = ACPI_MEM_ALLOCATED;
@@ -110,6 +110,7 @@
 
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_ALREADY_EXISTS) {
+
 			/* Table already exists, just return the handle */
 
 			return_ACPI_STATUS(AE_OK);
@@ -121,6 +122,7 @@
 
 	status = acpi_ns_load_table(table_info.installed_desc, parent_node);
 	if (ACPI_FAILURE(status)) {
+
 		/* Uninstall table on error */
 
 		(void)acpi_tb_uninstall_table(table_info.installed_desc);
@@ -160,7 +162,7 @@
 	struct acpi_namespace_node *parameter_node = NULL;
 	union acpi_operand_object *ddb_handle;
 
-	ACPI_FUNCTION_TRACE("ex_load_table_op");
+	ACPI_FUNCTION_TRACE(ex_load_table_op);
 
 #if 0
 	/*
@@ -169,6 +171,7 @@
 	 */
 	status = acpi_tb_match_signature(operand[0]->string.pointer, NULL);
 	if (status == AE_OK) {
+
 		/* Signature matched -- don't allow override */
 
 		return_ACPI_STATUS(AE_ALREADY_EXISTS);
@@ -211,9 +214,8 @@
 		 * location within the namespace where the table will be loaded.
 		 */
 		status =
-		    acpi_ns_get_node_by_path(operand[3]->string.pointer,
-					     start_node, ACPI_NS_SEARCH_PARENT,
-					     &parent_node);
+		    acpi_ns_get_node(start_node, operand[3]->string.pointer,
+				     ACPI_NS_SEARCH_PARENT, &parent_node);
 		if (ACPI_FAILURE(status)) {
 			return_ACPI_STATUS(status);
 		}
@@ -234,9 +236,8 @@
 		/* Find the node referenced by the parameter_path_string */
 
 		status =
-		    acpi_ns_get_node_by_path(operand[4]->string.pointer,
-					     start_node, ACPI_NS_SEARCH_PARENT,
-					     &parameter_node);
+		    acpi_ns_get_node(start_node, operand[4]->string.pointer,
+				     ACPI_NS_SEARCH_PARENT, &parameter_node);
 		if (ACPI_FAILURE(status)) {
 			return_ACPI_STATUS(status);
 		}
@@ -252,6 +253,7 @@
 	/* Parameter Data (optional) */
 
 	if (parameter_node) {
+
 		/* Store the parameter data into the optional parameter object */
 
 		status = acpi_ex_store(operand[5],
@@ -294,9 +296,10 @@
 	struct acpi_table_header *table_ptr = NULL;
 	acpi_physical_address address;
 	struct acpi_table_header table_header;
+	acpi_integer temp;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ex_load_op");
+	ACPI_FUNCTION_TRACE(ex_load_op);
 
 	/* Object can be either an op_region or a Field */
 
@@ -322,7 +325,7 @@
 
 		address = obj_desc->region.address;
 
-		/* Get the table length from the table header */
+		/* Get part of the table header to get the table length */
 
 		table_header.length = 0;
 		for (i = 0; i < 8; i++) {
@@ -330,11 +333,14 @@
 			    acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
 							   (acpi_physical_address)
 							   (i + address), 8,
-							   ((u8 *) &
-							    table_header) + i);
+							   &temp);
 			if (ACPI_FAILURE(status)) {
 				return_ACPI_STATUS(status);
 			}
+
+			/* Get the one valid byte of the returned 64-bit value */
+
+			ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp;
 		}
 
 		/* Sanity check the table length */
@@ -345,7 +351,7 @@
 
 		/* Allocate a buffer for the entire table */
 
-		table_ptr = ACPI_MEM_ALLOCATE(table_header.length);
+		table_ptr = ACPI_ALLOCATE(table_header.length);
 		if (!table_ptr) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
@@ -357,11 +363,14 @@
 			    acpi_ev_address_space_dispatch(obj_desc, ACPI_READ,
 							   (acpi_physical_address)
 							   (i + address), 8,
-							   ((u8 *) table_ptr +
-							    i));
+							   &temp);
 			if (ACPI_FAILURE(status)) {
 				goto cleanup;
 			}
+
+			/* Get the one valid byte of the returned 64-bit value */
+
+			ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp;
 		}
 		break;
 
@@ -407,12 +416,8 @@
 
 	/* The table must be either an SSDT or a PSDT */
 
-	if ((!ACPI_STRNCMP(table_ptr->signature,
-			   acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
-			   acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
-	    (!ACPI_STRNCMP(table_ptr->signature,
-			   acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
-			   acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
+	if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) &&
+	    (!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG))) {
 		ACPI_ERROR((AE_INFO,
 			    "Table has invalid signature [%4.4s], must be SSDT or PSDT",
 			    table_ptr->signature));
@@ -424,6 +429,7 @@
 
 	status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle);
 	if (ACPI_FAILURE(status)) {
+
 		/* On error, table_ptr was deallocated above */
 
 		return_ACPI_STATUS(status);
@@ -442,7 +448,7 @@
 
       cleanup:
 	if (ACPI_FAILURE(status)) {
-		ACPI_MEM_FREE(table_ptr);
+		ACPI_FREE(table_ptr);
 	}
 	return_ACPI_STATUS(status);
 }
@@ -465,7 +471,7 @@
 	union acpi_operand_object *table_desc = ddb_handle;
 	struct acpi_table_desc *table_info;
 
-	ACPI_FUNCTION_TRACE("ex_unload_table");
+	ACPI_FUNCTION_TRACE(ex_unload_table);
 
 	/*
 	 * Validate the handle
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index e6d52e1..b732e39 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -79,7 +79,7 @@
 	u32 count;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_convert_to_integer", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc);
 
 	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
 	case ACPI_TYPE_INTEGER:
@@ -199,7 +199,7 @@
 	union acpi_operand_object *return_desc;
 	u8 *new_buf;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_convert_to_buffer", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc);
 
 	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
 	case ACPI_TYPE_BUFFER:
@@ -319,6 +319,7 @@
 		remainder = 0;
 
 		for (i = decimal_length; i > 0; i--) {
+
 			/* Divide by nth factor of 10 */
 
 			digit = integer;
@@ -346,6 +347,7 @@
 
 		hex_length = (acpi_native_uint) ACPI_MUL_2(data_width);
 		for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
+
 			/* Get one hex digit, most significant digits first */
 
 			string[k] =
@@ -400,7 +402,7 @@
 	u16 base = 16;
 	u8 separator = ',';
 
-	ACPI_FUNCTION_TRACE_PTR("ex_convert_to_string", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc);
 
 	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
 	case ACPI_TYPE_STRING:
@@ -567,7 +569,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_convert_to_target_type");
+	ACPI_FUNCTION_TRACE(ex_convert_to_target_type);
 
 	/* Default behavior */
 
@@ -657,7 +659,7 @@
 
 	default:
 		ACPI_ERROR((AE_INFO,
-			    "Unknown Target type ID 0x%X aml_opcode %X dest_type %s",
+			    "Unknown Target type ID 0x%X AmlOpcode %X DestType %s",
 			    GET_CURRENT_ARG_TYPE(walk_state->op_info->
 						 runtime_args),
 			    walk_state->opcode,
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index 6805754..106dc72 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -69,7 +69,7 @@
 	struct acpi_namespace_node *alias_node;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_create_alias");
+	ACPI_FUNCTION_TRACE(ex_create_alias);
 
 	/* Get the source/alias operands (both namespace nodes) */
 
@@ -164,7 +164,7 @@
 	acpi_status status;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_TRACE("ex_create_event");
+	ACPI_FUNCTION_TRACE(ex_create_event);
 
 	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
 	if (!obj_desc) {
@@ -216,7 +216,7 @@
 	acpi_status status = AE_OK;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_create_mutex", ACPI_WALK_OPERANDS);
+	ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
 
 	/* Create the new mutex object */
 
@@ -243,8 +243,9 @@
 	obj_desc->mutex.node =
 	    (struct acpi_namespace_node *)walk_state->operands[0];
 
-	status = acpi_ns_attach_object(obj_desc->mutex.node,
-				       obj_desc, ACPI_TYPE_MUTEX);
+	status =
+	    acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
+				  ACPI_TYPE_MUTEX);
 
       cleanup:
 	/*
@@ -280,7 +281,7 @@
 	struct acpi_namespace_node *node;
 	union acpi_operand_object *region_obj2;
 
-	ACPI_FUNCTION_TRACE("ex_create_region");
+	ACPI_FUNCTION_TRACE(ex_create_region);
 
 	/* Get the Namespace Node */
 
@@ -300,7 +301,7 @@
 	 */
 	if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
 	    (region_space < ACPI_USER_REGION_BEGIN)) {
-		ACPI_ERROR((AE_INFO, "Invalid address_space type %X",
+		ACPI_ERROR((AE_INFO, "Invalid AddressSpace type %X",
 			    region_space));
 		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
 	}
@@ -364,7 +365,7 @@
 	struct acpi_table_header *table;
 	union acpi_operand_object *region_obj2;
 
-	ACPI_FUNCTION_TRACE("ex_create_table_region");
+	ACPI_FUNCTION_TRACE(ex_create_table_region);
 
 	/* Get the Node from the object stack  */
 
@@ -452,7 +453,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_create_processor", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
 
 	/* Create the processor object */
 
@@ -464,9 +465,9 @@
 	/* Initialize the processor object from the operands */
 
 	obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
+	obj_desc->processor.length = (u8) operand[3]->integer.value;
 	obj_desc->processor.address =
 	    (acpi_io_address) operand[2]->integer.value;
-	obj_desc->processor.length = (u8) operand[3]->integer.value;
 
 	/* Install the processor object in the parent Node */
 
@@ -499,7 +500,7 @@
 	acpi_status status;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_create_power_resource", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
 
 	/* Create the power resource object */
 
@@ -549,7 +550,7 @@
 	acpi_status status;
 	u8 method_flags;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_create_method", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
 
 	/* Create a new method object */
 
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index a7cca8d..7b9718e 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -61,6 +61,10 @@
 
 static void acpi_ex_out_address(char *title, acpi_physical_address value);
 
+static void
+acpi_ex_dump_object(union acpi_operand_object *obj_desc,
+		    struct acpi_exdump_info *info);
+
 static void acpi_ex_dump_reference_obj(union acpi_operand_object *obj_desc);
 
 static void
@@ -119,7 +123,7 @@
 
 static struct acpi_exdump_info acpi_ex_dump_method[8] = {
 	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_method), NULL},
-	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "param_count"},
+	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.param_count), "ParamCount"},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.concurrency), "Concurrency"},
 	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(method.semaphore), "Semaphore"},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(method.owner_id), "Owner Id"},
@@ -263,12 +267,10 @@
 	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(common_field.node), "Parent Node"}
 };
 
-static struct acpi_exdump_info acpi_ex_dump_node[6] = {
+static struct acpi_exdump_info acpi_ex_dump_node[5] = {
 	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_node), NULL},
 	{ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(flags), "Flags"},
 	{ACPI_EXD_UINT8, ACPI_EXD_NSOFFSET(owner_id), "Owner Id"},
-	{ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET(reference_count),
-	 "Reference Count"},
 	{ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(child), "Child List"},
 	{ACPI_EXD_POINTER, ACPI_EXD_NSOFFSET(peer), "Next Peer"}
 };
@@ -330,7 +332,7 @@
 
 	if (!info) {
 		acpi_os_printf
-		    ("ex_dump_object: Display not implemented for object type %s\n",
+		    ("ExDumpObject: Display not implemented for object type %s\n",
 		     acpi_ut_get_object_type_name(obj_desc));
 		return;
 	}
@@ -454,7 +456,7 @@
 	u32 length;
 	u32 index;
 
-	ACPI_FUNCTION_NAME("ex_dump_operand")
+	ACPI_FUNCTION_NAME(ex_dump_operand)
 
 	    if (!
 		((ACPI_LV_EXEC & acpi_dbg_level)
@@ -463,6 +465,7 @@
 	}
 
 	if (!obj_desc) {
+
 		/* This could be a null element of a package */
 
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n"));
@@ -522,7 +525,7 @@
 
 		case AML_REF_OF_OP:
 
-			acpi_os_printf("Reference: (ref_of) %p\n",
+			acpi_os_printf("Reference: (RefOf) %p\n",
 				       obj_desc->reference.object);
 			break;
 
@@ -532,6 +535,7 @@
 				       obj_desc->reference.offset);
 
 			if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
 				/* Value is an Integer */
 
 				acpi_os_printf(" value is [%8.8X%8.8x]",
@@ -610,7 +614,7 @@
 
 	case ACPI_TYPE_PACKAGE:
 
-		acpi_os_printf("Package [Len %X] element_array %p\n",
+		acpi_os_printf("Package [Len %X] ElementArray %p\n",
 			       obj_desc->package.count,
 			       obj_desc->package.elements);
 
@@ -662,13 +666,13 @@
 
 	case ACPI_TYPE_LOCAL_BANK_FIELD:
 
-		acpi_os_printf("bank_field\n");
+		acpi_os_printf("BankField\n");
 		break;
 
 	case ACPI_TYPE_LOCAL_REGION_FIELD:
 
 		acpi_os_printf
-		    ("region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
+		    ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
 		     obj_desc->field.bit_length,
 		     obj_desc->field.access_byte_width,
 		     obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
@@ -681,12 +685,12 @@
 
 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
 
-		acpi_os_printf("index_field\n");
+		acpi_os_printf("IndexField\n");
 		break;
 
 	case ACPI_TYPE_BUFFER_FIELD:
 
-		acpi_os_printf("buffer_field: %X bits at byte %X bit %X of\n",
+		acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n",
 			       obj_desc->buffer_field.bit_length,
 			       obj_desc->buffer_field.base_byte_offset,
 			       obj_desc->buffer_field.start_field_bit_offset);
@@ -777,7 +781,7 @@
 {
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_NAME("ex_dump_operands");
+	ACPI_FUNCTION_NAME(ex_dump_operands);
 
 	if (!ident) {
 		ident = "?";
@@ -901,7 +905,7 @@
 			acpi_os_printf("Could not convert name to pathname\n");
 		} else {
 			acpi_os_printf("%s\n", (char *)ret_buf.pointer);
-			ACPI_MEM_FREE(ret_buf.pointer);
+			ACPI_FREE(ret_buf.pointer);
 		}
 	} else if (obj_desc->reference.object) {
 		acpi_os_printf("\nReferenced Object: %p\n",
@@ -1017,7 +1021,7 @@
 void
 acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
 {
-	ACPI_FUNCTION_TRACE("ex_dump_object_descriptor");
+	ACPI_FUNCTION_TRACE(ex_dump_object_descriptor);
 
 	if (!obj_desc) {
 		return_VOID;
@@ -1046,7 +1050,7 @@
 
 	if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) {
 		acpi_os_printf
-		    ("ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n",
+		    ("ExDumpObjectDescriptor: %p is not an ACPI operand object: [%s]\n",
 		     obj_desc, acpi_ut_get_descriptor_name(obj_desc));
 		return_VOID;
 	}
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c
index e259201..9ea9c3a6 100644
--- a/drivers/acpi/executer/exfield.c
+++ b/drivers/acpi/executer/exfield.c
@@ -73,7 +73,7 @@
 	void *buffer;
 	u8 locked;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_read_data_from_field", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
 
 	/* Parameter validation */
 
@@ -142,6 +142,7 @@
 	length =
 	    (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
 	if (length > acpi_gbl_integer_byte_width) {
+
 		/* Field is too large for an Integer, create a Buffer instead */
 
 		buffer_desc = acpi_ut_create_buffer_object(length);
@@ -163,11 +164,11 @@
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-			  "field_read [TO]:  Obj %p, Type %X, Buf %p, byte_len %X\n",
+			  "FieldRead [TO]:   Obj %p, Type %X, Buf %p, ByteLen %X\n",
 			  obj_desc, ACPI_GET_OBJECT_TYPE(obj_desc), buffer,
 			  (u32) length));
 	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-			  "field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n",
+			  "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
 			  obj_desc->common_field.bit_length,
 			  obj_desc->common_field.start_field_bit_offset,
 			  obj_desc->common_field.base_byte_offset));
@@ -219,7 +220,7 @@
 	u8 locked;
 	union acpi_operand_object *buffer_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_write_data_to_field", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
 
 	/* Parameter validation */
 
@@ -329,9 +330,10 @@
 	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
 
 	if (length < required_length) {
+
 		/* We need to create a new buffer */
 
-		new_buffer = ACPI_MEM_CALLOCATE(required_length);
+		new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
 		if (!new_buffer) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
@@ -347,14 +349,14 @@
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-			  "field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n",
+			  "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
 			  source_desc,
 			  acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE
 						(source_desc)),
 			  ACPI_GET_OBJECT_TYPE(source_desc), buffer, length));
 
 	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-			  "field_write [TO]:  Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n",
+			  "FieldWrite [TO]:   Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
 			  obj_desc,
 			  acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc)),
 			  ACPI_GET_OBJECT_TYPE(obj_desc),
@@ -375,7 +377,7 @@
 	/* Free temporary buffer if we used one */
 
 	if (new_buffer) {
-		ACPI_MEM_FREE(new_buffer);
+		ACPI_FREE(new_buffer);
 	}
 
 	return_ACPI_STATUS(status);
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index bd1af35..051053f 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -87,7 +87,7 @@
 	acpi_status status = AE_OK;
 	union acpi_operand_object *rgn_desc;
 
-	ACPI_FUNCTION_TRACE_U32("ex_setup_region", field_datum_byte_offset);
+	ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset);
 
 	rgn_desc = obj_desc->common_field.region_obj;
 
@@ -112,7 +112,18 @@
 		}
 	}
 
+	/* Exit if Address/Length have been disallowed by the host OS */
+
+	if (rgn_desc->common.flags & AOPOBJ_INVALID) {
+		return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
+	}
+
+	/*
+	 * Exit now for SMBus address space, it has a non-linear address space
+	 * and the request cannot be directly validated
+	 */
 	if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
+
 		/* SMBus has a non-linear address space */
 
 		return_ACPI_STATUS(AE_OK);
@@ -134,10 +145,10 @@
 	 * length of one field datum (access width) must fit within the region.
 	 * (Region length is specified in bytes)
 	 */
-	if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset +
-				       field_datum_byte_offset +
-				       obj_desc->common_field.
-				       access_byte_width)) {
+	if (rgn_desc->region.length <
+	    (obj_desc->common_field.base_byte_offset +
+	     field_datum_byte_offset +
+	     obj_desc->common_field.access_byte_width)) {
 		if (acpi_gbl_enable_interpreter_slack) {
 			/*
 			 * Slack mode only:  We will go ahead and allow access to this
@@ -217,7 +228,7 @@
 	union acpi_operand_object *rgn_desc;
 	acpi_physical_address address;
 
-	ACPI_FUNCTION_TRACE("ex_access_region");
+	ACPI_FUNCTION_TRACE(ex_access_region);
 
 	/*
 	 * Ensure that the region operands are fully evaluated and verify
@@ -246,7 +257,7 @@
 	}
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD,
-			      " Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
+			      " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n",
 			      acpi_ut_get_region_name(rgn_desc->region.
 						      space_id),
 			      rgn_desc->region.space_id,
@@ -352,7 +363,7 @@
 	acpi_status status;
 	acpi_integer local_value;
 
-	ACPI_FUNCTION_TRACE_U32("ex_field_datum_io", field_datum_byte_offset);
+	ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);
 
 	if (read_write == ACPI_READ) {
 		if (!value) {
@@ -487,10 +498,11 @@
 		}
 
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-				  "I/O to Data Register: value_ptr %p\n",
+				  "I/O to Data Register: ValuePtr %p\n",
 				  value));
 
 		if (read_write == ACPI_READ) {
+
 			/* Read the datum from the data_register */
 
 			status =
@@ -559,7 +571,7 @@
 	acpi_integer merged_value;
 	acpi_integer current_value;
 
-	ACPI_FUNCTION_TRACE_U32("ex_write_with_update_rule", mask);
+	ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask);
 
 	/* Start with the new bits  */
 
@@ -568,6 +580,7 @@
 	/* If the mask is all ones, we don't need to worry about the update rule */
 
 	if (mask != ACPI_INTEGER_MAX) {
+
 		/* Decode the update rule */
 
 		switch (obj_desc->common_field.
@@ -614,7 +627,7 @@
 		default:
 
 			ACPI_ERROR((AE_INFO,
-				    "Unknown update_rule value: %X",
+				    "Unknown UpdateRule value: %X",
 				    (obj_desc->common_field.
 				     field_flags &
 				     AML_FIELD_UPDATE_RULE_MASK)));
@@ -623,7 +636,7 @@
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-			  "Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
+			  "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
 			  ACPI_FORMAT_UINT64(mask),
 			  field_datum_byte_offset,
 			  obj_desc->common_field.access_byte_width,
@@ -666,7 +679,7 @@
 	u32 field_datum_count;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ex_extract_from_field");
+	ACPI_FUNCTION_TRACE(ex_extract_from_field);
 
 	/* Validate target buffer and clear it */
 
@@ -704,6 +717,7 @@
 	/* Read the rest of the field */
 
 	for (i = 1; i < field_datum_count; i++) {
+
 		/* Get next input datum from the field */
 
 		field_offset += obj_desc->common_field.access_byte_width;
@@ -771,6 +785,7 @@
 {
 	acpi_status status;
 	acpi_integer mask;
+	acpi_integer width_mask;
 	acpi_integer merged_datum;
 	acpi_integer raw_datum = 0;
 	u32 field_offset = 0;
@@ -780,7 +795,7 @@
 	u32 field_datum_count;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ex_insert_into_field");
+	ACPI_FUNCTION_TRACE(ex_insert_into_field);
 
 	/* Validate input buffer */
 
@@ -795,15 +810,20 @@
 
 	/* Compute the number of datums (access width data items) */
 
+	width_mask =
+	    ACPI_MASK_BITS_ABOVE(obj_desc->common_field.access_bit_width);
 	mask =
-	    ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);
-	datum_count =
-	    ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
-			     obj_desc->common_field.access_bit_width);
-	field_datum_count =
-	    ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
-			     obj_desc->common_field.start_field_bit_offset,
-			     obj_desc->common_field.access_bit_width);
+	    width_mask & ACPI_MASK_BITS_BELOW(obj_desc->common_field.
+					      start_field_bit_offset);
+
+	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
+				       obj_desc->common_field.access_bit_width);
+
+	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
+					     obj_desc->common_field.
+					     start_field_bit_offset,
+					     obj_desc->common_field.
+					     access_bit_width);
 
 	/* Get initial Datum from the input buffer */
 
@@ -817,6 +837,7 @@
 	/* Write the entire field */
 
 	for (i = 1; i < field_datum_count; i++) {
+
 		/* Write merged datum to the target field */
 
 		merged_datum &= mask;
@@ -833,7 +854,7 @@
 		merged_datum = raw_datum >>
 		    (obj_desc->common_field.access_bit_width -
 		     obj_desc->common_field.start_field_bit_offset);
-		mask = ACPI_INTEGER_MAX;
+		mask = width_mask;
 
 		if (i == datum_count) {
 			break;
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index 48c18d2..bd98aab 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -72,7 +72,7 @@
 	union acpi_operand_object *reference_obj;
 	union acpi_operand_object *referenced_obj;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_get_object_reference", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_get_object_reference, obj_desc);
 
 	*return_desc = NULL;
 
@@ -168,7 +168,7 @@
 	acpi_size length1;
 	acpi_size new_length;
 
-	ACPI_FUNCTION_TRACE("ex_concat_template");
+	ACPI_FUNCTION_TRACE(ex_concat_template);
 
 	/*
 	 * Find the end_tag descriptor in each resource template.
@@ -250,7 +250,7 @@
 	char *new_buf;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ex_do_concatenate");
+	ACPI_FUNCTION_TRACE(ex_do_concatenate);
 
 	/*
 	 * Convert the second operand if necessary.  The first operand
@@ -445,10 +445,24 @@
 
 	case AML_SHIFT_LEFT_OP:	/* shift_left (Operand, shift_count, Result) */
 
+		/*
+		 * We need to check if the shiftcount is larger than the integer bit
+		 * width since the behavior of this is not well-defined in the C language.
+		 */
+		if (integer1 >= acpi_gbl_integer_bit_width) {
+			return (0);
+		}
 		return (integer0 << integer1);
 
 	case AML_SHIFT_RIGHT_OP:	/* shift_right (Operand, shift_count, Result) */
 
+		/*
+		 * We need to check if the shiftcount is larger than the integer bit
+		 * width since the behavior of this is not well-defined in the C language.
+		 */
+		if (integer1 >= acpi_gbl_integer_bit_width) {
+			return (0);
+		}
 		return (integer0 >> integer1);
 
 	case AML_SUBTRACT_OP:	/* Subtract (Integer0, Integer1, Result) */
@@ -489,7 +503,7 @@
 	acpi_status status = AE_OK;
 	u8 local_result = FALSE;
 
-	ACPI_FUNCTION_TRACE("ex_do_logical_numeric_op");
+	ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op);
 
 	switch (opcode) {
 	case AML_LAND_OP:	/* LAnd (Integer0, Integer1) */
@@ -557,7 +571,7 @@
 	u8 local_result = FALSE;
 	int compare;
 
-	ACPI_FUNCTION_TRACE("ex_do_logical_op");
+	ACPI_FUNCTION_TRACE(ex_do_logical_op);
 
 	/*
 	 * Convert the second operand if necessary.  The first operand
@@ -649,6 +663,7 @@
 			/* Length and all bytes must be equal */
 
 			if ((length0 == length1) && (compare == 0)) {
+
 				/* Length and all bytes match ==> TRUE */
 
 				local_result = TRUE;
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index f843b22..93098d6 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -61,7 +61,7 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Remove a mutex from the "acquired_mutex" list
+ * DESCRIPTION: Remove a mutex from the "AcquiredMutex" list
  *
  ******************************************************************************/
 
@@ -95,7 +95,7 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk
+ * DESCRIPTION: Add a mutex to the "AcquiredMutex" list for this walk
  *
  ******************************************************************************/
 
@@ -144,7 +144,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_acquire_mutex", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_acquire_mutex, obj_desc);
 
 	if (!obj_desc) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -165,7 +165,7 @@
 	 */
 	if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
 		ACPI_ERROR((AE_INFO,
-			    "Cannot acquire Mutex [%4.4s], incorrect sync_level",
+			    "Cannot acquire Mutex [%4.4s], incorrect SyncLevel",
 			    acpi_ut_get_node_name(obj_desc->mutex.node)));
 		return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
 	}
@@ -173,6 +173,7 @@
 	/* Support for multiple acquires by the owning thread */
 
 	if (obj_desc->mutex.owner_thread) {
+
 		/* Special case for Global Lock, allow all threads */
 
 		if ((obj_desc->mutex.owner_thread->thread_id ==
@@ -192,6 +193,7 @@
 
 	status = acpi_ex_system_acquire_mutex(time_desc, obj_desc);
 	if (ACPI_FAILURE(status)) {
+
 		/* Includes failure from a timeout on time_desc */
 
 		return_ACPI_STATUS(status);
@@ -232,7 +234,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ex_release_mutex");
+	ACPI_FUNCTION_TRACE(ex_release_mutex);
 
 	if (!obj_desc) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -277,7 +279,7 @@
 	 */
 	if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
 		ACPI_ERROR((AE_INFO,
-			    "Cannot release Mutex [%4.4s], incorrect sync_level",
+			    "Cannot release Mutex [%4.4s], incorrect SyncLevel",
 			    acpi_ut_get_node_name(obj_desc->mutex.node)));
 		return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
 	}
@@ -286,6 +288,7 @@
 
 	obj_desc->mutex.acquisition_depth--;
 	if (obj_desc->mutex.acquisition_depth != 0) {
+
 		/* Just decrement the depth and return */
 
 		return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 054fe5e..d3d7036 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -77,7 +77,7 @@
 	char *name_string;
 	u32 size_needed;
 
-	ACPI_FUNCTION_TRACE("ex_allocate_name_string");
+	ACPI_FUNCTION_TRACE(ex_allocate_name_string);
 
 	/*
 	 * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
@@ -85,6 +85,7 @@
 	 * This may actually be somewhat longer than needed.
 	 */
 	if (prefix_count == ACPI_UINT32_MAX) {
+
 		/* Special case for root */
 
 		size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
@@ -97,7 +98,7 @@
 	 * Allocate a buffer for the name.
 	 * This buffer must be deleted by the caller!
 	 */
-	name_string = ACPI_MEM_ALLOCATE(size_needed);
+	name_string = ACPI_ALLOCATE(size_needed);
 	if (!name_string) {
 		ACPI_ERROR((AE_INFO,
 			    "Could not allocate size %d", size_needed));
@@ -119,11 +120,13 @@
 	/* Set up Dual or Multi prefixes if needed */
 
 	if (num_name_segs > 2) {
+
 		/* Set up multi prefixes   */
 
 		*temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
 		*temp_ptr++ = (char)num_name_segs;
 	} else if (2 == num_name_segs) {
+
 		/* Set up dual prefixes */
 
 		*temp_ptr++ = AML_DUAL_NAME_PREFIX;
@@ -159,7 +162,7 @@
 	u32 index;
 	char char_buf[5];
 
-	ACPI_FUNCTION_TRACE("ex_name_segment");
+	ACPI_FUNCTION_TRACE(ex_name_segment);
 
 	/*
 	 * If first character is a digit, then we know that we aren't looking at a
@@ -176,7 +179,7 @@
 
 	for (index = 0;
 	     (index < ACPI_NAME_SIZE)
-	     && (acpi_ut_valid_acpi_character(*aml_address)); index++) {
+	     && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
 		char_buf[index] = *aml_address++;
 		ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
 	}
@@ -184,6 +187,7 @@
 	/* Valid name segment  */
 
 	if (index == 4) {
+
 		/* Found 4 valid characters */
 
 		char_buf[4] = '\0';
@@ -249,11 +253,12 @@
 	u32 prefix_count = 0;
 	u8 has_prefix = FALSE;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_get_name_string", aml_address);
+	ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
 
 	if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
 	    ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
 	    ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
+
 		/* Disallow prefixes for types associated with field_unit names */
 
 		name_string = acpi_ex_allocate_name_string(0, 1);
@@ -272,7 +277,7 @@
 		case AML_ROOT_PREFIX:
 
 			ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
-					  "root_prefix(\\) at %p\n",
+					  "RootPrefix(\\) at %p\n",
 					  aml_address));
 
 			/*
@@ -290,7 +295,7 @@
 
 			do {
 				ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
-						  "parent_prefix (^) at %p\n",
+						  "ParentPrefix (^) at %p\n",
 						  aml_address));
 
 				aml_address++;
@@ -314,7 +319,7 @@
 		case AML_DUAL_NAME_PREFIX:
 
 			ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
-					  "dual_name_prefix at %p\n",
+					  "DualNamePrefix at %p\n",
 					  aml_address));
 
 			aml_address++;
@@ -341,7 +346,7 @@
 		case AML_MULTI_NAME_PREFIX_OP:
 
 			ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
-					  "multi_name_prefix at %p\n",
+					  "MultiNamePrefix at %p\n",
 					  aml_address));
 
 			/* Fetch count of segments remaining in name path */
@@ -377,7 +382,7 @@
 
 			if (prefix_count == ACPI_UINT32_MAX) {
 				ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-						  "name_seg is \"\\\" followed by NULL\n"));
+						  "NameSeg is \"\\\" followed by NULL\n"));
 			}
 
 			/* Consume the NULL byte */
@@ -410,6 +415,7 @@
 	}
 
 	if (AE_CTRL_PENDING == status && has_prefix) {
+
 		/* Ran out of segments after processing a prefix */
 
 		ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
@@ -418,7 +424,7 @@
 
 	if (ACPI_FAILURE(status)) {
 		if (name_string) {
-			ACPI_MEM_FREE(name_string);
+			ACPI_FREE(name_string);
 		}
 		return_ACPI_STATUS(status);
 	}
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index 23d0823..6374d8b 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -89,7 +89,7 @@
 	acpi_status status = AE_OK;
 	union acpi_operand_object *return_desc = NULL;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_0A_0T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Examine the AML opcode */
@@ -150,7 +150,7 @@
 	union acpi_operand_object **operand = &walk_state->operands[0];
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_0R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Examine the AML opcode */
@@ -216,7 +216,7 @@
 	acpi_status status = AE_OK;
 	union acpi_operand_object **operand = &walk_state->operands[0];
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_0R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Examine the AML opcode */
@@ -264,7 +264,7 @@
 	acpi_integer power_of_ten;
 	acpi_integer digit;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_1T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Examine the AML opcode */
@@ -322,8 +322,9 @@
 
 			/* Since the bit position is one-based, subtract from 33 (65) */
 
-			return_desc->integer.value = temp32 == 0 ? 0 :
-			    (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
+			return_desc->integer.value =
+			    temp32 ==
+			    0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
 			break;
 
 		case AML_FROM_BCD_OP:	/* from_bcd (BCDValue, Result) */
@@ -342,6 +343,7 @@
 			for (i = 0;
 			     (i < acpi_gbl_integer_nybble_width) && (digit > 0);
 			     i++) {
+
 				/* Get the least significant 4-bit BCD digit */
 
 				temp32 = ((u32) digit) & 0xF;
@@ -487,6 +489,7 @@
 		status = acpi_ex_convert_to_string(operand[0], &return_desc,
 						   ACPI_EXPLICIT_CONVERT_DECIMAL);
 		if (return_desc == operand[0]) {
+
 			/* No conversion performed, add ref to handle return value */
 			acpi_ut_add_reference(return_desc);
 		}
@@ -497,6 +500,7 @@
 		status = acpi_ex_convert_to_string(operand[0], &return_desc,
 						   ACPI_EXPLICIT_CONVERT_HEX);
 		if (return_desc == operand[0]) {
+
 			/* No conversion performed, add ref to handle return value */
 			acpi_ut_add_reference(return_desc);
 		}
@@ -506,6 +510,7 @@
 
 		status = acpi_ex_convert_to_buffer(operand[0], &return_desc);
 		if (return_desc == operand[0]) {
+
 			/* No conversion performed, add ref to handle return value */
 			acpi_ut_add_reference(return_desc);
 		}
@@ -516,6 +521,7 @@
 		status = acpi_ex_convert_to_integer(operand[0], &return_desc,
 						    ACPI_ANY_BASE);
 		if (return_desc == operand[0]) {
+
 			/* No conversion performed, add ref to handle return value */
 			acpi_ut_add_reference(return_desc);
 		}
@@ -541,6 +547,7 @@
 	}
 
 	if (ACPI_SUCCESS(status)) {
+
 		/* Store the return value computed above into the target object */
 
 		status = acpi_ex_store(return_desc, operand[1], walk_state);
@@ -548,16 +555,18 @@
 
       cleanup:
 
-	if (!walk_state->result_obj) {
-		walk_state->result_obj = return_desc;
-	}
-
 	/* Delete return object on error */
 
 	if (ACPI_FAILURE(status)) {
 		acpi_ut_remove_reference(return_desc);
 	}
 
+	/* Save return object on success */
+
+	else if (!walk_state->result_obj) {
+		walk_state->result_obj = return_desc;
+	}
+
 	return_ACPI_STATUS(status);
 }
 
@@ -582,7 +591,7 @@
 	u32 type;
 	acpi_integer value;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_1A_0T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Examine the AML opcode */
@@ -625,6 +634,7 @@
 		temp_desc = operand[0];
 		if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
 		    ACPI_DESC_TYPE_OPERAND) {
+
 			/* Internal reference object - prevent deletion */
 
 			acpi_ut_add_reference(temp_desc);
@@ -689,6 +699,7 @@
 		if (ACPI_FAILURE(status)) {
 			goto cleanup;
 		}
+
 		/* Allocate a descriptor to hold the type. */
 
 		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
@@ -777,8 +788,25 @@
 
 		/* Check for a method local or argument, or standalone String */
 
-		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
+		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
 		    ACPI_DESC_TYPE_NAMED) {
+			temp_desc =
+			    acpi_ns_get_attached_object((struct
+							 acpi_namespace_node *)
+							operand[0]);
+			if (temp_desc
+			    &&
+			    ((ACPI_GET_OBJECT_TYPE(temp_desc) ==
+			      ACPI_TYPE_STRING)
+			     || (ACPI_GET_OBJECT_TYPE(temp_desc) ==
+				 ACPI_TYPE_LOCAL_REFERENCE))) {
+				operand[0] = temp_desc;
+				acpi_ut_add_reference(temp_desc);
+			} else {
+				status = AE_AML_OPERAND_TYPE;
+				goto cleanup;
+			}
+		} else {
 			switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
 			case ACPI_TYPE_LOCAL_REFERENCE:
 				/*
@@ -827,26 +855,35 @@
 				break;
 
 			case ACPI_TYPE_STRING:
+				break;
 
+			default:
+				status = AE_AML_OPERAND_TYPE;
+				goto cleanup;
+			}
+		}
+
+		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
+		    ACPI_DESC_TYPE_NAMED) {
+			if (ACPI_GET_OBJECT_TYPE(operand[0]) ==
+			    ACPI_TYPE_STRING) {
 				/*
 				 * This is a deref_of (String). The string is a reference
 				 * to a named ACPI object.
 				 *
 				 * 1) Find the owning Node
-				 * 2) Dereference the node to an actual object.  Could be a
+				 * 2) Dereference the node to an actual object. Could be a
 				 *    Field, so we need to resolve the node to a value.
 				 */
 				status =
-				    acpi_ns_get_node_by_path(operand[0]->string.
-							     pointer,
-							     walk_state->
-							     scope_info->scope.
-							     node,
-							     ACPI_NS_SEARCH_PARENT,
-							     ACPI_CAST_INDIRECT_PTR
-							     (struct
-							      acpi_namespace_node,
-							      &return_desc));
+				    acpi_ns_get_node(walk_state->scope_info->
+						     scope.node,
+						     operand[0]->string.pointer,
+						     ACPI_NS_SEARCH_PARENT,
+						     ACPI_CAST_INDIRECT_PTR
+						     (struct
+						      acpi_namespace_node,
+						      &return_desc));
 				if (ACPI_FAILURE(status)) {
 					goto cleanup;
 				}
@@ -857,11 +894,6 @@
 				     (struct acpi_namespace_node, &return_desc),
 				     walk_state);
 				goto cleanup;
-
-			default:
-
-				status = AE_AML_OPERAND_TYPE;
-				goto cleanup;
 			}
 		}
 
@@ -937,13 +969,12 @@
 						acpi_ut_add_reference
 						    (return_desc);
 					}
-
 					break;
 
 				default:
 
 					ACPI_ERROR((AE_INFO,
-						    "Unknown Index target_type %X in obj %p",
+						    "Unknown Index TargetType %X in obj %p",
 						    operand[0]->reference.
 						    target_type, operand[0]));
 					status = AE_AML_OPERAND_TYPE;
@@ -957,7 +988,6 @@
 
 				if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
 				    ACPI_DESC_TYPE_NAMED) {
-
 					return_desc =
 					    acpi_ns_get_attached_object((struct
 									 acpi_namespace_node
@@ -972,7 +1002,7 @@
 
 			default:
 				ACPI_ERROR((AE_INFO,
-					    "Unknown opcode in ref(%p) - %X",
+					    "Unknown opcode in reference(%p) - %X",
 					    operand[0],
 					    operand[0]->reference.opcode));
 
@@ -998,6 +1028,11 @@
 		acpi_ut_remove_reference(return_desc);
 	}
 
-	walk_state->result_obj = return_desc;
+	/* Save return object on success */
+
+	else {
+		walk_state->result_obj = return_desc;
+	}
+
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/executer/exoparg2.c b/drivers/acpi/executer/exoparg2.c
index e263a5d..7d2cbc1 100644
--- a/drivers/acpi/executer/exoparg2.c
+++ b/drivers/acpi/executer/exoparg2.c
@@ -92,7 +92,7 @@
 	u32 value;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Examine the opcode */
@@ -121,7 +121,7 @@
 #ifdef ACPI_GPE_NOTIFY_CHECK
 		/*
 		 * GPE method wake/notify check.  Here, we want to ensure that we
-		 * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
+		 * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx
 		 * GPE method during system runtime.  If we do, the GPE is marked
 		 * as "wake-only" and disabled.
 		 *
@@ -138,6 +138,7 @@
 			    acpi_ev_check_for_wake_only_gpe(walk_state->
 							    gpe_event_info);
 			if (ACPI_FAILURE(status)) {
+
 				/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
 
 				return_ACPI_STATUS(AE_OK)
@@ -185,7 +186,7 @@
 	union acpi_operand_object *return_desc2 = NULL;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_2T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Execute the opcode */
@@ -252,6 +253,7 @@
 	acpi_ut_remove_reference(return_desc2);
 
 	if (ACPI_FAILURE(status)) {
+
 		/* Delete the return object */
 
 		acpi_ut_remove_reference(return_desc1);
@@ -281,12 +283,13 @@
 	acpi_status status = AE_OK;
 	acpi_size length;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_1T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Execute the opcode */
 
 	if (walk_state->op_info->flags & AML_MATH) {
+
 		/* All simple math opcodes (add, etc.) */
 
 		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
@@ -383,54 +386,70 @@
 			goto cleanup;
 		}
 
+		/* Initialize the Index reference object */
+
 		index = operand[1]->integer.value;
+		return_desc->reference.offset = (u32) index;
+		return_desc->reference.opcode = AML_INDEX_OP;
 
-		/* At this point, the Source operand is a Package, Buffer, or String */
+		/*
+		 * At this point, the Source operand is a String, Buffer, or Package.
+		 * Verify that the index is within range.
+		 */
+		switch (ACPI_GET_OBJECT_TYPE(operand[0])) {
+		case ACPI_TYPE_STRING:
 
-		if (ACPI_GET_OBJECT_TYPE(operand[0]) == ACPI_TYPE_PACKAGE) {
-			/* Object to be indexed is a Package */
-
-			if (index >= operand[0]->package.count) {
-				ACPI_ERROR((AE_INFO,
-					    "Index value (%X%8.8X) beyond package end (%X)",
-					    ACPI_FORMAT_UINT64(index),
-					    operand[0]->package.count));
-				status = AE_AML_PACKAGE_LIMIT;
-				goto cleanup;
-			}
-
-			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
-			return_desc->reference.object = operand[0];
-			return_desc->reference.where =
-			    &operand[0]->package.elements[index];
-		} else {
-			/* Object to be indexed is a Buffer/String */
-
-			if (index >= operand[0]->buffer.length) {
-				ACPI_ERROR((AE_INFO,
-					    "Index value (%X%8.8X) beyond end of buffer (%X)",
-					    ACPI_FORMAT_UINT64(index),
-					    operand[0]->buffer.length));
-				status = AE_AML_BUFFER_LIMIT;
-				goto cleanup;
+			if (index >= operand[0]->string.length) {
+				status = AE_AML_STRING_LIMIT;
 			}
 
 			return_desc->reference.target_type =
 			    ACPI_TYPE_BUFFER_FIELD;
-			return_desc->reference.object = operand[0];
+			break;
+
+		case ACPI_TYPE_BUFFER:
+
+			if (index >= operand[0]->buffer.length) {
+				status = AE_AML_BUFFER_LIMIT;
+			}
+
+			return_desc->reference.target_type =
+			    ACPI_TYPE_BUFFER_FIELD;
+			break;
+
+		case ACPI_TYPE_PACKAGE:
+
+			if (index >= operand[0]->package.count) {
+				status = AE_AML_PACKAGE_LIMIT;
+			}
+
+			return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
+			return_desc->reference.where =
+			    &operand[0]->package.elements[index];
+			break;
+
+		default:
+
+			status = AE_AML_INTERNAL;
+			goto cleanup;
+		}
+
+		/* Failure means that the Index was beyond the end of the object */
+
+		if (ACPI_FAILURE(status)) {
+			ACPI_EXCEPTION((AE_INFO, status,
+					"Index (%X%8.8X) is beyond end of object",
+					ACPI_FORMAT_UINT64(index)));
+			goto cleanup;
 		}
 
 		/*
-		 * Add a reference to the target package/buffer/string for the life
-		 * of the index.
+		 * Save the target object and add a reference to it for the life
+		 * of the index
 		 */
+		return_desc->reference.object = operand[0];
 		acpi_ut_add_reference(operand[0]);
 
-		/* Complete the Index reference object */
-
-		return_desc->reference.opcode = AML_INDEX_OP;
-		return_desc->reference.offset = (u32) index;
-
 		/* Store the reference to the Target */
 
 		status = acpi_ex_store(return_desc, operand[2], walk_state);
@@ -495,7 +514,7 @@
 	acpi_status status = AE_OK;
 	u8 logical_result = FALSE;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	/* Create the internal return object */
@@ -509,6 +528,7 @@
 	/* Execute the Opcode */
 
 	if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
+
 		/* logical_op (Operand0, Operand1) */
 
 		status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
@@ -518,6 +538,7 @@
 						       value, &logical_result);
 		goto store_logical_result;
 	} else if (walk_state->op_info->flags & AML_LOGICAL) {
+
 		/* logical_op (Operand0, Operand1) */
 
 		status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
diff --git a/drivers/acpi/executer/exoparg3.c b/drivers/acpi/executer/exoparg3.c
index 6a3a883..e2d945d 100644
--- a/drivers/acpi/executer/exoparg3.c
+++ b/drivers/acpi/executer/exoparg3.c
@@ -88,20 +88,19 @@
 	struct acpi_signal_fatal_info *fatal;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_0T_0R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	switch (walk_state->opcode) {
 	case AML_FATAL_OP:	/* Fatal (fatal_type fatal_code fatal_arg) */
 
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-				  "fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
+				  "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
 				  (u32) operand[0]->integer.value,
 				  (u32) operand[1]->integer.value,
 				  (u32) operand[2]->integer.value));
 
-		fatal =
-		    ACPI_MEM_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
+		fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
 		if (fatal) {
 			fatal->type = (u32) operand[0]->integer.value;
 			fatal->code = (u32) operand[1]->integer.value;
@@ -114,7 +113,7 @@
 
 		/* Might return while OS is shutting down, just continue */
 
-		ACPI_MEM_FREE(fatal);
+		ACPI_FREE(fatal);
 		break;
 
 	default:
@@ -151,7 +150,7 @@
 	acpi_integer index;
 	acpi_size length;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_3A_1T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	switch (walk_state->opcode) {
@@ -196,7 +195,7 @@
 
 			/* Always allocate a new buffer for the String */
 
-			buffer = ACPI_MEM_CALLOCATE((acpi_size) length + 1);
+			buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
 			if (!buffer) {
 				status = AE_NO_MEMORY;
 				goto cleanup;
@@ -208,9 +207,10 @@
 			/* If the requested length is zero, don't allocate a buffer */
 
 			if (length > 0) {
+
 				/* Allocate a new buffer for the Buffer */
 
-				buffer = ACPI_MEM_CALLOCATE(length);
+				buffer = ACPI_ALLOCATE_ZEROED(length);
 				if (!buffer) {
 					status = AE_NO_MEMORY;
 					goto cleanup;
@@ -225,6 +225,7 @@
 		}
 
 		if (buffer) {
+
 			/* We have a buffer, copy the portion requested */
 
 			ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
diff --git a/drivers/acpi/executer/exoparg6.c b/drivers/acpi/executer/exoparg6.c
index e043d92..f0c0ba6 100644
--- a/drivers/acpi/executer/exoparg6.c
+++ b/drivers/acpi/executer/exoparg6.c
@@ -220,7 +220,7 @@
 	acpi_integer index;
 	union acpi_operand_object *this_element;
 
-	ACPI_FUNCTION_TRACE_STR("ex_opcode_6A_0T_1R",
+	ACPI_FUNCTION_TRACE_STR(ex_opcode_6A_0T_1R,
 				acpi_ps_get_opcode_name(walk_state->opcode));
 
 	switch (walk_state->opcode) {
@@ -276,6 +276,7 @@
 		 * match was found.
 		 */
 		for (; index < operand[0]->package.count; index++) {
+
 			/* Get the current package element */
 
 			this_element = operand[0]->package.elements[index];
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index 7719ae5..44d064f 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -97,7 +97,7 @@
 	u32 minimum_accesses = 0xFFFFFFFF;
 	u32 accesses;
 
-	ACPI_FUNCTION_TRACE("ex_generate_access");
+	ACPI_FUNCTION_TRACE(ex_generate_access);
 
 	/* Round Field start offset and length to "minimal" byte boundaries */
 
@@ -146,7 +146,7 @@
 			accesses = field_end_offset - field_start_offset;
 
 			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-					  "access_width %d end is within region\n",
+					  "AccessWidth %d end is within region\n",
 					  access_byte_width));
 
 			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
@@ -173,7 +173,7 @@
 			}
 		} else {
 			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-					  "access_width %d end is NOT within region\n",
+					  "AccessWidth %d end is NOT within region\n",
 					  access_byte_width));
 			if (access_byte_width == 1) {
 				ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
@@ -228,7 +228,7 @@
 	u32 byte_alignment;
 	u32 bit_length;
 
-	ACPI_FUNCTION_TRACE("ex_decode_field_access");
+	ACPI_FUNCTION_TRACE(ex_decode_field_access);
 
 	access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
 
@@ -322,7 +322,7 @@
 	u32 byte_alignment;
 	u32 nearest_byte_address;
 
-	ACPI_FUNCTION_TRACE("ex_prep_common_field_object");
+	ACPI_FUNCTION_TRACE(ex_prep_common_field_object);
 
 	/*
 	 * Note: the structure being initialized is the
@@ -415,13 +415,13 @@
 	u32 type;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ex_prep_field_value");
+	ACPI_FUNCTION_TRACE(ex_prep_field_value);
 
 	/* Parameter validation */
 
 	if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
 		if (!info->region_node) {
-			ACPI_ERROR((AE_INFO, "Null region_node"));
+			ACPI_ERROR((AE_INFO, "Null RegionNode"));
 			return_ACPI_STATUS(AE_AML_NO_OPERAND);
 		}
 
@@ -467,7 +467,7 @@
 		acpi_ut_add_reference(obj_desc->field.region_obj);
 
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-				  "region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
+				  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
 				  obj_desc->field.start_field_bit_offset,
 				  obj_desc->field.base_byte_offset,
 				  obj_desc->field.access_byte_width,
@@ -488,7 +488,7 @@
 		acpi_ut_add_reference(obj_desc->bank_field.bank_obj);
 
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-				  "Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
+				  "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n",
 				  obj_desc->bank_field.start_field_bit_offset,
 				  obj_desc->bank_field.base_byte_offset,
 				  obj_desc->field.access_byte_width,
@@ -519,16 +519,29 @@
 		acpi_ut_add_reference(obj_desc->index_field.index_obj);
 
 		/*
+		 * April 2006: Changed to match MS behavior
+		 *
 		 * The value written to the Index register is the byte offset of the
-		 * target field
-		 * Note: may change code to: ACPI_DIV_8 (Info->field_bit_position)
+		 * target field in units of the granularity of the index_field
+		 *
+		 * Previously, the value was calculated as an index in terms of the
+		 * width of the Data register, as below:
+		 *
+		 *      obj_desc->index_field.Value = (u32)
+		 *          (Info->field_bit_position / ACPI_MUL_8 (
+		 *              obj_desc->Field.access_byte_width));
+		 *
+		 * February 2006: Tried value as a byte offset:
+		 *      obj_desc->index_field.Value = (u32)
+		 *          ACPI_DIV_8 (Info->field_bit_position);
 		 */
-		obj_desc->index_field.value = (u32)
-		    (info->field_bit_position /
-		     ACPI_MUL_8(obj_desc->field.access_byte_width));
+		obj_desc->index_field.value =
+		    (u32) ACPI_ROUND_DOWN(ACPI_DIV_8(info->field_bit_position),
+					  obj_desc->index_field.
+					  access_byte_width);
 
 		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-				  "index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
+				  "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
 				  obj_desc->index_field.start_field_bit_offset,
 				  obj_desc->index_field.base_byte_offset,
 				  obj_desc->index_field.value,
@@ -550,7 +563,7 @@
 				       acpi_ns_get_type(info->field_node));
 
 	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
-			  "Set named_obj %p [%4.4s], obj_desc %p\n",
+			  "Set NamedObj %p [%4.4s], ObjDesc %p\n",
 			  info->field_node,
 			  acpi_ut_get_node_name(info->field_node), obj_desc));
 
diff --git a/drivers/acpi/executer/exregion.c b/drivers/acpi/executer/exregion.c
index 6a4cfdf..3cc97ba 100644
--- a/drivers/acpi/executer/exregion.c
+++ b/drivers/acpi/executer/exregion.c
@@ -81,7 +81,7 @@
 	u32 remainder;
 #endif
 
-	ACPI_FUNCTION_TRACE("ex_system_memory_space_handler");
+	ACPI_FUNCTION_TRACE(ex_system_memory_space_handler);
 
 	/* Validate and translate the bit width */
 
@@ -103,7 +103,7 @@
 		break;
 
 	default:
-		ACPI_ERROR((AE_INFO, "Invalid system_memory width %d",
+		ACPI_ERROR((AE_INFO, "Invalid SystemMemory width %d",
 			    bit_width));
 		return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
 	}
@@ -135,6 +135,7 @@
 		 * Delete the existing mapping and create a new one.
 		 */
 		if (mem_info->mapped_length) {
+
 			/* Valid mapping, delete it */
 
 			acpi_os_unmap_memory(mem_info->mapped_logical_address,
@@ -181,8 +182,8 @@
 	     (acpi_integer) mem_info->mapped_physical_address);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "system_memory %d (%d width) Address=%8.8X%8.8X\n",
-			  function, bit_width, ACPI_FORMAT_UINT64(address)));
+			  "System-Memory (width %d) R/W %d Address=%8.8X%8.8X\n",
+			  bit_width, function, ACPI_FORMAT_UINT64(address)));
 
 	/*
 	 * Perform the memory read or write
@@ -283,11 +284,11 @@
 	acpi_status status = AE_OK;
 	u32 value32;
 
-	ACPI_FUNCTION_TRACE("ex_system_io_space_handler");
+	ACPI_FUNCTION_TRACE(ex_system_io_space_handler);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "system_iO %d (%d width) Address=%8.8X%8.8X\n",
-			  function, bit_width, ACPI_FORMAT_UINT64(address)));
+			  "System-IO (width %d) R/W %d Address=%8.8X%8.8X\n",
+			  bit_width, function, ACPI_FORMAT_UINT64(address)));
 
 	/* Decode the function parameter */
 
@@ -342,7 +343,7 @@
 	struct acpi_pci_id *pci_id;
 	u16 pci_register;
 
-	ACPI_FUNCTION_TRACE("ex_pci_config_space_handler");
+	ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
 
 	/*
 	 *  The arguments to acpi_os(Read|Write)pci_configuration are:
@@ -360,7 +361,7 @@
 	pci_register = (u16) (u32) address;
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-			  "pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
+			  "Pci-Config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
 			  function, bit_width, pci_id->segment, pci_id->bus,
 			  pci_id->device, pci_id->function, pci_register));
 
@@ -414,7 +415,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_cmos_space_handler");
+	ACPI_FUNCTION_TRACE(ex_cmos_space_handler);
 
 	return_ACPI_STATUS(status);
 }
@@ -446,7 +447,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_pci_bar_space_handler");
+	ACPI_FUNCTION_TRACE(ex_pci_bar_space_handler);
 
 	return_ACPI_STATUS(status);
 }
@@ -476,23 +477,16 @@
 				 acpi_integer * value,
 				 void *handler_context, void *region_context)
 {
-	acpi_status status = AE_OK;
-	u32 byte_width = ACPI_DIV_8(bit_width);
-	u32 i;
-	char *logical_addr_ptr;
-
-	ACPI_FUNCTION_TRACE("ex_data_table_space_handler");
-
-	logical_addr_ptr = ACPI_PHYSADDR_TO_PTR(address);
+	ACPI_FUNCTION_TRACE(ex_data_table_space_handler);
 
 	/* Perform the memory read or write */
 
 	switch (function) {
 	case ACPI_READ:
 
-		for (i = 0; i < byte_width; i++) {
-			((char *)value)[i] = logical_addr_ptr[i];
-		}
+		ACPI_MEMCPY(ACPI_CAST_PTR(char, value),
+			    ACPI_PHYSADDR_TO_PTR(address),
+			    ACPI_DIV_8(bit_width));
 		break;
 
 	case ACPI_WRITE:
@@ -501,5 +495,5 @@
 		return_ACPI_STATUS(AE_SUPPORT);
 	}
 
-	return_ACPI_STATUS(status);
+	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/executer/exresnte.c b/drivers/acpi/executer/exresnte.c
index 01b26c8..3089b05 100644
--- a/drivers/acpi/executer/exresnte.c
+++ b/drivers/acpi/executer/exresnte.c
@@ -87,7 +87,7 @@
 	struct acpi_namespace_node *node;
 	acpi_object_type entry_type;
 
-	ACPI_FUNCTION_TRACE("ex_resolve_node_to_value");
+	ACPI_FUNCTION_TRACE(ex_resolve_node_to_value);
 
 	/*
 	 * The stack pointer points to a struct acpi_namespace_node (Node).  Get the
@@ -97,12 +97,13 @@
 	source_desc = acpi_ns_get_attached_object(node);
 	entry_type = acpi_ns_get_type((acpi_handle) node);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n",
 			  node, source_desc,
 			  acpi_ut_get_type_name(entry_type)));
 
 	if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
 	    (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
+
 		/* There is always exactly one level of indirection */
 
 		node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object);
@@ -113,10 +114,11 @@
 
 	/*
 	 * Several object types require no further processing:
-	 * 1) Devices rarely have an attached object, return the Node
+	 * 1) Device/Thermal objects don't have a "real" subobject, return the Node
 	 * 2) Method locals and arguments have a pseudo-Node
 	 */
-	if (entry_type == ACPI_TYPE_DEVICE ||
+	if ((entry_type == ACPI_TYPE_DEVICE) ||
+	    (entry_type == ACPI_TYPE_THERMAL) ||
 	    (node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
 		return_ACPI_STATUS(AE_OK);
 	}
@@ -141,6 +143,7 @@
 
 		status = acpi_ds_get_package_arguments(source_desc);
 		if (ACPI_SUCCESS(status)) {
+
 			/* Return an additional reference to the object */
 
 			obj_desc = source_desc;
@@ -158,6 +161,7 @@
 
 		status = acpi_ds_get_buffer_arguments(source_desc);
 		if (ACPI_SUCCESS(status)) {
+
 			/* Return an additional reference to the object */
 
 			obj_desc = source_desc;
@@ -199,7 +203,7 @@
 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
 
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "field_read Node=%p source_desc=%p Type=%X\n",
+				  "FieldRead Node=%p SourceDesc=%p Type=%X\n",
 				  node, source_desc, entry_type));
 
 		status =
@@ -213,7 +217,6 @@
 	case ACPI_TYPE_METHOD:
 	case ACPI_TYPE_POWER:
 	case ACPI_TYPE_PROCESSOR:
-	case ACPI_TYPE_THERMAL:
 	case ACPI_TYPE_EVENT:
 	case ACPI_TYPE_REGION:
 
@@ -240,6 +243,8 @@
 			/* This is a ddb_handle */
 			/* Return an additional reference to the object */
 
+		case AML_REF_OF_OP:
+
 			obj_desc = source_desc;
 			acpi_ut_add_reference(obj_desc);
 			break;
diff --git a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
index 1deed49..6499de8 100644
--- a/drivers/acpi/executer/exresolv.c
+++ b/drivers/acpi/executer/exresolv.c
@@ -78,7 +78,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_resolve_to_value", stack_ptr);
+	ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
 
 	if (!stack_ptr || !*stack_ptr) {
 		ACPI_ERROR((AE_INFO, "Internal - null pointer"));
@@ -144,7 +144,7 @@
 	union acpi_operand_object *obj_desc;
 	u16 opcode;
 
-	ACPI_FUNCTION_TRACE("ex_resolve_object_to_value");
+	ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
 
 	stack_desc = *stack_ptr;
 
@@ -190,7 +190,7 @@
 			}
 
 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-					  "[Arg/Local %X] value_obj is %p\n",
+					  "[Arg/Local %X] ValueObj is %p\n",
 					  stack_desc->reference.offset,
 					  obj_desc));
 
@@ -239,7 +239,7 @@
 				/* Invalid reference object */
 
 				ACPI_ERROR((AE_INFO,
-					    "Unknown target_type %X in Index/Reference obj %p",
+					    "Unknown TargetType %X in Index/Reference obj %p",
 					    stack_desc->reference.target_type,
 					    stack_desc));
 				status = AE_AML_INTERNAL;
@@ -257,10 +257,24 @@
 
 		case AML_INT_NAMEPATH_OP:	/* Reference to a named object */
 
-			/* Get the object pointed to by the namespace node */
+			/* Dereference the name */
 
-			*stack_ptr = (stack_desc->reference.node)->object;
-			acpi_ut_add_reference(*stack_ptr);
+			if ((stack_desc->reference.node->type ==
+			     ACPI_TYPE_DEVICE)
+			    || (stack_desc->reference.node->type ==
+				ACPI_TYPE_THERMAL)) {
+
+				/* These node types do not have 'real' subobjects */
+
+				*stack_ptr = (void *)stack_desc->reference.node;
+			} else {
+				/* Get the object pointed to by the namespace node */
+
+				*stack_ptr =
+				    (stack_desc->reference.node)->object;
+				acpi_ut_add_reference(*stack_ptr);
+			}
+
 			acpi_ut_remove_reference(stack_desc);
 			break;
 
@@ -293,7 +307,7 @@
 	case ACPI_TYPE_LOCAL_INDEX_FIELD:
 
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "field_read source_desc=%p Type=%X\n",
+				  "FieldRead SourceDesc=%p Type=%X\n",
 				  stack_desc,
 				  ACPI_GET_OBJECT_TYPE(stack_desc)));
 
@@ -337,7 +351,7 @@
 	acpi_object_type type;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_ex_resolve_multiple");
+	ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
 
 	/* Operand can be either a namespace node or an operand descriptor */
 
@@ -382,10 +396,16 @@
 	while (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
 		switch (obj_desc->reference.opcode) {
 		case AML_REF_OF_OP:
+		case AML_INT_NAMEPATH_OP:
 
 			/* Dereference the reference pointer */
 
-			node = obj_desc->reference.object;
+			if (obj_desc->reference.opcode == AML_REF_OF_OP) {
+				node = obj_desc->reference.object;
+			} else {	/* AML_INT_NAMEPATH_OP */
+
+				node = obj_desc->reference.node;
+			}
 
 			/* All "References" point to a NS node */
 
@@ -401,6 +421,7 @@
 
 			obj_desc = acpi_ns_get_attached_object(node);
 			if (!obj_desc) {
+
 				/* No object, use the NS node type */
 
 				type = acpi_ns_get_type(node);
@@ -432,6 +453,7 @@
 			 */
 			obj_desc = *(obj_desc->reference.where);
 			if (!obj_desc) {
+
 				/* NULL package elements are allowed */
 
 				type = 0;	/* Uninitialized */
@@ -439,39 +461,6 @@
 			}
 			break;
 
-		case AML_INT_NAMEPATH_OP:
-
-			/* Dereference the reference pointer */
-
-			node = obj_desc->reference.node;
-
-			/* All "References" point to a NS node */
-
-			if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
-			    ACPI_DESC_TYPE_NAMED) {
-				ACPI_ERROR((AE_INFO, "Not a NS node %p [%s]",
-					    node,
-					    acpi_ut_get_descriptor_name(node)));
-				return_ACPI_STATUS(AE_AML_INTERNAL);
-			}
-
-			/* Get the attached object */
-
-			obj_desc = acpi_ns_get_attached_object(node);
-			if (!obj_desc) {
-				/* No object, use the NS node type */
-
-				type = acpi_ns_get_type(node);
-				goto exit;
-			}
-
-			/* Check for circular references */
-
-			if (obj_desc == operand) {
-				return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
-			}
-			break;
-
 		case AML_LOCAL_OP:
 		case AML_ARG_OP:
 
@@ -513,7 +502,7 @@
 
 		case AML_DEBUG_OP:
 
-			/* The Debug Object is of type "debug_object" */
+			/* The Debug Object is of type "DebugObject" */
 
 			type = ACPI_TYPE_DEBUG_OBJECT;
 			goto exit;
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index a1c000f..4c93d09 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -77,6 +77,7 @@
 	ACPI_FUNCTION_ENTRY();
 
 	if (type_needed == ACPI_TYPE_ANY) {
+
 		/* All types OK, so we don't perform any typechecks */
 
 		return (AE_OK);
@@ -143,7 +144,7 @@
 	acpi_object_type type_needed;
 	u16 target_op = 0;
 
-	ACPI_FUNCTION_TRACE_U32("ex_resolve_operands", opcode);
+	ACPI_FUNCTION_TRACE_U32(ex_resolve_operands, opcode);
 
 	op_info = acpi_ps_get_opcode_info(opcode);
 	if (op_info->class == AML_CLASS_UNKNOWN) {
@@ -158,7 +159,7 @@
 	}
 
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-			  "Opcode %X [%s] required_operand_types=%8.8X\n",
+			  "Opcode %X [%s] RequiredOperandTypes=%8.8X\n",
 			  opcode, op_info->name, arg_types));
 
 	/*
@@ -224,6 +225,7 @@
 			}
 
 			if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
+
 				/* Decode the Reference */
 
 				op_info = acpi_ps_get_opcode_info(opcode);
@@ -247,7 +249,7 @@
 
 					ACPI_DEBUG_ONLY_MEMBERS(ACPI_DEBUG_PRINT
 								((ACPI_DB_EXEC,
-								  "Operand is a Reference, ref_opcode [%s]\n",
+								  "Operand is a Reference, RefOpcode [%s]\n",
 								  (acpi_ps_get_opcode_info
 								   (obj_desc->
 								    reference.
@@ -332,6 +334,7 @@
 			}
 
 			if (obj_desc->reference.opcode == AML_NAME_OP) {
+
 				/* Convert a named reference to the actual named object */
 
 				temp_node = obj_desc->reference.object;
@@ -623,7 +626,7 @@
 
 			default:
 				ACPI_ERROR((AE_INFO,
-					    "Needed [Region/region_field], found [%s] %p",
+					    "Needed [Region/RegionField], found [%s] %p",
 					    acpi_ut_get_object_type_name
 					    (obj_desc), obj_desc));
 
@@ -662,6 +665,7 @@
 				}
 
 				if (target_op == AML_DEBUG_OP) {
+
 					/* Allow store of any object to the Debug object */
 
 					break;
diff --git a/drivers/acpi/executer/exstore.c b/drivers/acpi/executer/exstore.c
index 3f020c0..0456405 100644
--- a/drivers/acpi/executer/exstore.c
+++ b/drivers/acpi/executer/exstore.c
@@ -82,7 +82,7 @@
 {
 	u32 i;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_do_debug_object", source_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc);
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s",
 			      level, " "));
@@ -245,7 +245,7 @@
 	acpi_status status = AE_OK;
 	union acpi_operand_object *ref_desc = dest_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_store", dest_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc);
 
 	/* Validate parameters */
 
@@ -297,7 +297,7 @@
 
 		ACPI_DUMP_STACK_ENTRY(source_desc);
 		ACPI_DUMP_STACK_ENTRY(dest_desc);
-		ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
+		ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ExStore",
 				   2,
 				   "Target is not a Reference or Constant object");
 
@@ -396,7 +396,7 @@
 	u8 value = 0;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ex_store_object_to_index");
+	ACPI_FUNCTION_TRACE(ex_store_object_to_index);
 
 	/*
 	 * Destination must be a reference pointer, and
@@ -423,6 +423,7 @@
 		}
 
 		if (obj_desc) {
+
 			/* Decrement reference count by the ref count of the parent package */
 
 			for (i = 0; i < ((union acpi_operand_object *)
@@ -502,8 +503,7 @@
 		break;
 
 	default:
-		ACPI_ERROR((AE_INFO,
-			    "Target is not a Package or buffer_field"));
+		ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField"));
 		status = AE_AML_OPERAND_TYPE;
 		break;
 	}
@@ -548,7 +548,7 @@
 	union acpi_operand_object *new_desc;
 	acpi_object_type target_type;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_node", source_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc);
 
 	/* Get current type of the node, and object attached to Node */
 
@@ -572,6 +572,7 @@
 	/* If no implicit conversion, drop into the default case below */
 
 	if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) {
+
 		/* Force execution of default (no implicit conversion) */
 
 		target_type = ACPI_TYPE_ANY;
diff --git a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
index 42967ba..591aaf0 100644
--- a/drivers/acpi/executer/exstoren.c
+++ b/drivers/acpi/executer/exstoren.c
@@ -72,7 +72,7 @@
 	union acpi_operand_object *source_desc = *source_desc_ptr;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_resolve_object");
+	ACPI_FUNCTION_TRACE(ex_resolve_object);
 
 	/* Ensure we have a Target that can be stored to */
 
@@ -97,6 +97,7 @@
 		 */
 		if (ACPI_GET_OBJECT_TYPE(source_desc) ==
 		    ACPI_TYPE_LOCAL_REFERENCE) {
+
 			/* Resolve a reference object first */
 
 			status =
@@ -121,6 +122,7 @@
 		    !((ACPI_GET_OBJECT_TYPE(source_desc) ==
 		       ACPI_TYPE_LOCAL_REFERENCE)
 		      && (source_desc->reference.opcode == AML_LOAD_OP))) {
+
 			/* Conversion successful but still not a valid type */
 
 			ACPI_ERROR((AE_INFO,
@@ -199,7 +201,7 @@
 	union acpi_operand_object *actual_src_desc;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_store_object_to_object", source_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_object, source_desc);
 
 	actual_src_desc = source_desc;
 	if (!dest_desc) {
@@ -289,6 +291,7 @@
 	}
 
 	if (actual_src_desc != source_desc) {
+
 		/* Delete the intermediate (temporary) source object */
 
 		acpi_ut_remove_reference(actual_src_desc);
diff --git a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
index 6ab7070..99ebe5a 100644
--- a/drivers/acpi/executer/exstorob.c
+++ b/drivers/acpi/executer/exstorob.c
@@ -67,7 +67,7 @@
 	u32 length;
 	u8 *buffer;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_store_buffer_to_buffer", source_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);
 
 	/* We know that source_desc is a buffer by now */
 
@@ -80,7 +80,7 @@
 	 */
 	if ((target_desc->buffer.length == 0) ||
 	    (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
-		target_desc->buffer.pointer = ACPI_MEM_ALLOCATE(length);
+		target_desc->buffer.pointer = ACPI_ALLOCATE(length);
 		if (!target_desc->buffer.pointer) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
@@ -91,6 +91,7 @@
 	/* Copy source buffer to target buffer */
 
 	if (length <= target_desc->buffer.length) {
+
 		/* Clear existing buffer and copy in the new one */
 
 		ACPI_MEMSET(target_desc->buffer.pointer, 0,
@@ -102,7 +103,7 @@
 		 * NOTE: ACPI versions up to 3.0 specified that the buffer must be
 		 * truncated if the string is smaller than the buffer.  However, "other"
 		 * implementations of ACPI never did this and thus became the defacto
-		 * standard. ACPi 3.0_a changes this behavior such that the buffer
+		 * standard. ACPI 3.0_a changes this behavior such that the buffer
 		 * is no longer truncated.
 		 */
 
@@ -113,6 +114,7 @@
 		 * copy must not truncate the original buffer.
 		 */
 		if (original_src_type == ACPI_TYPE_STRING) {
+
 			/* Set the new length of the target */
 
 			target_desc->buffer.length = length;
@@ -156,7 +158,7 @@
 	u32 length;
 	u8 *buffer;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_store_string_to_string", source_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc);
 
 	/* We know that source_desc is a string by now */
 
@@ -183,13 +185,14 @@
 		 */
 		if (target_desc->string.pointer &&
 		    (!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
+
 			/* Only free if not a pointer into the DSDT */
 
-			ACPI_MEM_FREE(target_desc->string.pointer);
+			ACPI_FREE(target_desc->string.pointer);
 		}
 
-		target_desc->string.pointer = ACPI_MEM_CALLOCATE((acpi_size)
-								 length + 1);
+		target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size)
+								   length + 1);
 		if (!target_desc->string.pointer) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index ea9144f..52beee3 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -68,7 +68,7 @@
 	acpi_status status;
 	acpi_status status2;
 
-	ACPI_FUNCTION_TRACE("ex_system_wait_semaphore");
+	ACPI_FUNCTION_TRACE(ex_system_wait_semaphore);
 
 	status = acpi_os_wait_semaphore(semaphore, 1, 0);
 	if (ACPI_SUCCESS(status)) {
@@ -76,6 +76,7 @@
 	}
 
 	if (status == AE_TIME) {
+
 		/* We must wait, so unlock the interpreter */
 
 		acpi_ex_exit_interpreter();
@@ -90,6 +91,7 @@
 
 		status2 = acpi_ex_enter_interpreter();
 		if (ACPI_FAILURE(status2)) {
+
 			/* Report fatal error, could not acquire interpreter */
 
 			return_ACPI_STATUS(status2);
@@ -191,7 +193,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_PTR("ex_system_acquire_mutex", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ex_system_acquire_mutex, obj_desc);
 
 	if (!obj_desc) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -229,7 +231,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_system_release_mutex");
+	ACPI_FUNCTION_TRACE(ex_system_release_mutex);
 
 	if (!obj_desc) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -263,7 +265,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_system_signal_event");
+	ACPI_FUNCTION_TRACE(ex_system_signal_event);
 
 	if (obj_desc) {
 		status = acpi_os_signal_semaphore(obj_desc->event.semaphore, 1);
@@ -293,7 +295,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ex_system_wait_event");
+	ACPI_FUNCTION_TRACE(ex_system_wait_event);
 
 	if (obj_desc) {
 		status =
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index f73a61a..982c8b6 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -87,9 +87,9 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ex_enter_interpreter");
+	ACPI_FUNCTION_TRACE(ex_enter_interpreter);
 
-	status = acpi_ut_acquire_mutex(ACPI_MTX_EXECUTE);
+	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
 	if (ACPI_FAILURE(status)) {
 		ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex"));
 	}
@@ -123,9 +123,9 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ex_exit_interpreter");
+	ACPI_FUNCTION_TRACE(ex_exit_interpreter);
 
-	status = acpi_ut_release_mutex(ACPI_MTX_EXECUTE);
+	status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
 	if (ACPI_FAILURE(status)) {
 		ACPI_ERROR((AE_INFO, "Could not release interpreter mutex"));
 	}
@@ -189,11 +189,12 @@
 	u8 locked = FALSE;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ex_acquire_global_lock");
+	ACPI_FUNCTION_TRACE(ex_acquire_global_lock);
 
 	/* Only attempt lock if the always_lock bit is set */
 
 	if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
+
 		/* We should attempt to get the lock, wait forever */
 
 		status = acpi_ev_acquire_global_lock(ACPI_WAIT_FOREVER);
@@ -225,15 +226,17 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ex_release_global_lock");
+	ACPI_FUNCTION_TRACE(ex_release_global_lock);
 
 	/* Only attempt unlock if the caller locked it */
 
 	if (locked_by_me) {
+
 		/* OK, now release the lock */
 
 		status = acpi_ev_release_global_lock();
 		if (ACPI_FAILURE(status)) {
+
 			/* Report the error, but there isn't much else we can do */
 
 			ACPI_EXCEPTION((AE_INFO, status,
@@ -263,7 +266,7 @@
 	u32 num_digits;
 	acpi_integer current_value;
 
-	ACPI_FUNCTION_TRACE("ex_digits_needed");
+	ACPI_FUNCTION_TRACE(ex_digits_needed);
 
 	/* acpi_integer is unsigned, so we don't worry about a '-' prefix */
 
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index e8165c4..1cd2578 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -48,6 +48,8 @@
 
 static int acpi_fan_add(struct acpi_device *device);
 static int acpi_fan_remove(struct acpi_device *device, int type);
+static int acpi_fan_suspend(struct acpi_device *device, int state);
+static int acpi_fan_resume(struct acpi_device *device, int state);
 
 static struct acpi_driver acpi_fan_driver = {
 	.name = ACPI_FAN_DRIVER_NAME,
@@ -56,6 +58,8 @@
 	.ops = {
 		.add = acpi_fan_add,
 		.remove = acpi_fan_remove,
+		.suspend = acpi_fan_suspend,
+		.resume = acpi_fan_resume,
 		},
 };
 
@@ -206,6 +210,10 @@
 		goto end;
 	}
 
+	device->flags.force_power_state = 1;
+	acpi_bus_set_power(device->handle, state);
+	device->flags.force_power_state = 0;
+
 	result = acpi_fan_add_fs(device);
 	if (result)
 		goto end;
@@ -239,6 +247,38 @@
 	return_VALUE(0);
 }
 
+static int acpi_fan_suspend(struct acpi_device *device, int state)
+{
+	if (!device)
+		return -EINVAL;
+
+	acpi_bus_set_power(device->handle, ACPI_STATE_D0);
+
+	return AE_OK;
+}
+
+static int acpi_fan_resume(struct acpi_device *device, int state)
+{
+	int result = 0;
+	int power_state = 0;
+
+	if (!device)
+		return -EINVAL;
+
+	result = acpi_bus_get_power(device->handle, &power_state);
+	if (result) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				  "Error reading fan power state\n"));
+		return result;
+	}
+
+	device->flags.force_power_state = 1;
+	acpi_bus_set_power(device->handle, power_state);
+	device->flags.force_power_state = 0;
+
+	return result;
+}
+
 static int __init acpi_fan_init(void)
 {
 	int result = 0;
diff --git a/drivers/acpi/hardware/hwacpi.c b/drivers/acpi/hardware/hwacpi.c
index ea2f132..de50fab 100644
--- a/drivers/acpi/hardware/hwacpi.c
+++ b/drivers/acpi/hardware/hwacpi.c
@@ -63,7 +63,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("hw_initialize");
+	ACPI_FUNCTION_TRACE(hw_initialize);
 
 	/* We must have the ACPI tables by the time we get here */
 
@@ -100,7 +100,7 @@
 	acpi_status status;
 	u32 retry;
 
-	ACPI_FUNCTION_TRACE("hw_set_mode");
+	ACPI_FUNCTION_TRACE(hw_set_mode);
 
 	/*
 	 * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
@@ -198,7 +198,7 @@
 	acpi_status status;
 	u32 value;
 
-	ACPI_FUNCTION_TRACE("hw_get_mode");
+	ACPI_FUNCTION_TRACE(hw_get_mode);
 
 	/*
 	 * ACPI 2.0 clarified that if SMI_CMD in FADT is zero,
diff --git a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c
index d84942d..608a3a6 100644
--- a/drivers/acpi/hardware/hwgpe.c
+++ b/drivers/acpi/hardware/hwgpe.c
@@ -214,6 +214,7 @@
 	/* Examine each GPE Register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
+
 		/* Disable all GPEs in this register */
 
 		status = acpi_hw_low_level_write(8, 0x00,
@@ -250,6 +251,7 @@
 	/* Examine each GPE Register within the block */
 
 	for (i = 0; i < gpe_block->register_count; i++) {
+
 		/* Clear status on all GPEs in this register */
 
 		status = acpi_hw_low_level_write(8, 0xFF,
@@ -368,7 +370,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("hw_disable_all_gpes");
+	ACPI_FUNCTION_TRACE(hw_disable_all_gpes);
 
 	status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block);
 	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
@@ -391,7 +393,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("hw_enable_all_runtime_gpes");
+	ACPI_FUNCTION_TRACE(hw_enable_all_runtime_gpes);
 
 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_runtime_gpe_block);
 	return_ACPI_STATUS(status);
@@ -413,7 +415,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("hw_enable_all_wakeup_gpes");
+	ACPI_FUNCTION_TRACE(hw_enable_all_wakeup_gpes);
 
 	status = acpi_ev_walk_gpe_list(acpi_hw_enable_wakeup_gpe_block);
 	return_ACPI_STATUS(status);
diff --git a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c
index e1fe754..ae142de 100644
--- a/drivers/acpi/hardware/hwregs.c
+++ b/drivers/acpi/hardware/hwregs.c
@@ -43,8 +43,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acevents.h>
@@ -63,23 +61,21 @@
  * DESCRIPTION: Clears all fixed and general purpose status bits
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
+ * NOTE: TBD: Flags parameter is obsolete, to be removed
+ *
  ******************************************************************************/
 acpi_status acpi_hw_clear_acpi_status(u32 flags)
 {
 	acpi_status status;
+	acpi_cpu_flags lock_flags = 0;
 
-	ACPI_FUNCTION_TRACE("hw_clear_acpi_status");
+	ACPI_FUNCTION_TRACE(hw_clear_acpi_status);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_IO, "About to write %04X to %04X\n",
 			  ACPI_BITMASK_ALL_FIXED_STATUS,
 			  (u16) acpi_gbl_FADT->xpm1a_evt_blk.address));
 
-	if (flags & ACPI_MTX_LOCK) {
-		status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
+	lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
 
 	status = acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK,
 					ACPI_REGISTER_PM1_STATUS,
@@ -104,9 +100,7 @@
 	status = acpi_ev_walk_gpe_list(acpi_hw_clear_gpe_block);
 
       unlock_and_exit:
-	if (flags & ACPI_MTX_LOCK) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-	}
+	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
 	return_ACPI_STATUS(status);
 }
 
@@ -129,10 +123,9 @@
 acpi_get_sleep_type_data(u8 sleep_state, u8 * sleep_type_a, u8 * sleep_type_b)
 {
 	acpi_status status = AE_OK;
-	struct acpi_parameter_info info;
-	char *sleep_state_name;
+	struct acpi_evaluate_info *info;
 
-	ACPI_FUNCTION_TRACE("acpi_get_sleep_type_data");
+	ACPI_FUNCTION_TRACE(acpi_get_sleep_type_data);
 
 	/* Validate parameters */
 
@@ -140,34 +133,39 @@
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	/* Evaluate the namespace object containing the values for this state */
+	/* Allocate the evaluation information block */
 
-	info.parameters = NULL;
-	info.return_object = NULL;
-	sleep_state_name =
+	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+	if (!info) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	info->pathname =
 	    ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
 
-	status = acpi_ns_evaluate_by_name(sleep_state_name, &info);
+	/* Evaluate the namespace object containing the values for this state */
+
+	status = acpi_ns_evaluate(info);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "%s while evaluating sleep_state [%s]\n",
+				  "%s while evaluating SleepState [%s]\n",
 				  acpi_format_exception(status),
-				  sleep_state_name));
+				  info->pathname));
 
-		return_ACPI_STATUS(status);
+		goto cleanup;
 	}
 
 	/* Must have a return object */
 
-	if (!info.return_object) {
+	if (!info->return_object) {
 		ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
-			    sleep_state_name));
+			    info->pathname));
 		status = AE_NOT_EXIST;
 	}
 
 	/* It must be of type Package */
 
-	else if (ACPI_GET_OBJECT_TYPE(info.return_object) != ACPI_TYPE_PACKAGE) {
+	else if (ACPI_GET_OBJECT_TYPE(info->return_object) != ACPI_TYPE_PACKAGE) {
 		ACPI_ERROR((AE_INFO,
 			    "Sleep State return object is not a Package"));
 		status = AE_AML_OPERAND_TYPE;
@@ -180,7 +178,7 @@
 	 * by BIOS vendors seems to be to have 2 or more elements, at least
 	 * one per sleep type (A/B).
 	 */
-	else if (info.return_object->package.count < 2) {
+	else if (info->return_object->package.count < 2) {
 		ACPI_ERROR((AE_INFO,
 			    "Sleep State return package does not have at least two elements"));
 		status = AE_AML_NO_OPERAND;
@@ -188,39 +186,42 @@
 
 	/* The first two elements must both be of type Integer */
 
-	else if ((ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[0])
+	else if ((ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[0])
 		  != ACPI_TYPE_INTEGER) ||
-		 (ACPI_GET_OBJECT_TYPE(info.return_object->package.elements[1])
+		 (ACPI_GET_OBJECT_TYPE(info->return_object->package.elements[1])
 		  != ACPI_TYPE_INTEGER)) {
 		ACPI_ERROR((AE_INFO,
 			    "Sleep State return package elements are not both Integers (%s, %s)",
-			    acpi_ut_get_object_type_name(info.return_object->
+			    acpi_ut_get_object_type_name(info->return_object->
 							 package.elements[0]),
-			    acpi_ut_get_object_type_name(info.return_object->
+			    acpi_ut_get_object_type_name(info->return_object->
 							 package.elements[1])));
 		status = AE_AML_OPERAND_TYPE;
 	} else {
 		/* Valid _Sx_ package size, type, and value */
 
 		*sleep_type_a = (u8)
-		    (info.return_object->package.elements[0])->integer.value;
+		    (info->return_object->package.elements[0])->integer.value;
 		*sleep_type_b = (u8)
-		    (info.return_object->package.elements[1])->integer.value;
+		    (info->return_object->package.elements[1])->integer.value;
 	}
 
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status,
-				"While evaluating sleep_state [%s], bad Sleep object %p type %s",
-				sleep_state_name, info.return_object,
-				acpi_ut_get_object_type_name(info.
+				"While evaluating SleepState [%s], bad Sleep object %p type %s",
+				info->pathname, info->return_object,
+				acpi_ut_get_object_type_name(info->
 							     return_object)));
 	}
 
-	acpi_ut_remove_reference(info.return_object);
+	acpi_ut_remove_reference(info->return_object);
+
+      cleanup:
+	ACPI_FREE(info);
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_sleep_type_data);
+ACPI_EXPORT_SYMBOL(acpi_get_sleep_type_data)
 
 /*******************************************************************************
  *
@@ -233,13 +234,12 @@
  * DESCRIPTION: Map register_id into a register bitmask.
  *
  ******************************************************************************/
-
 struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id)
 {
 	ACPI_FUNCTION_ENTRY();
 
 	if (register_id > ACPI_BITREG_MAX) {
-		ACPI_ERROR((AE_INFO, "Invalid bit_register ID: %X",
+		ACPI_ERROR((AE_INFO, "Invalid BitRegister ID: %X",
 			    register_id));
 		return (NULL);
 	}
@@ -260,6 +260,8 @@
  *
  * DESCRIPTION: ACPI bit_register read function.
  *
+ * NOTE: TBD: Flags parameter is obsolete, to be removed
+ *
  ******************************************************************************/
 
 acpi_status acpi_get_register(u32 register_id, u32 * return_value, u32 flags)
@@ -268,7 +270,7 @@
 	struct acpi_bit_register_info *bit_reg_info;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_get_register");
+	ACPI_FUNCTION_TRACE(acpi_get_register);
 
 	/* Get the info structure corresponding to the requested ACPI Register */
 
@@ -277,24 +279,14 @@
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	if (flags & ACPI_MTX_LOCK) {
-		status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
-
 	/* Read from the register */
 
-	status = acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK,
+	status = acpi_hw_register_read(ACPI_MTX_LOCK,
 				       bit_reg_info->parent_register,
 				       &register_value);
 
-	if (flags & ACPI_MTX_LOCK) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-	}
-
 	if (ACPI_SUCCESS(status)) {
+
 		/* Normalize the value that was read */
 
 		register_value =
@@ -311,7 +303,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_register);
+ACPI_EXPORT_SYMBOL(acpi_get_register)
 
 /*******************************************************************************
  *
@@ -326,31 +318,28 @@
  *
  * DESCRIPTION: ACPI Bit Register write function.
  *
+ * NOTE: TBD: Flags parameter is obsolete, to be removed
+ *
  ******************************************************************************/
-
 acpi_status acpi_set_register(u32 register_id, u32 value, u32 flags)
 {
 	u32 register_value = 0;
 	struct acpi_bit_register_info *bit_reg_info;
 	acpi_status status;
+	acpi_cpu_flags lock_flags;
 
-	ACPI_FUNCTION_TRACE_U32("acpi_set_register", register_id);
+	ACPI_FUNCTION_TRACE_U32(acpi_set_register, register_id);
 
 	/* Get the info structure corresponding to the requested ACPI Register */
 
 	bit_reg_info = acpi_hw_get_bit_register_info(register_id);
 	if (!bit_reg_info) {
-		ACPI_ERROR((AE_INFO, "Bad ACPI HW register_id: %X",
+		ACPI_ERROR((AE_INFO, "Bad ACPI HW RegisterId: %X",
 			    register_id));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	if (flags & ACPI_MTX_LOCK) {
-		status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-	}
+	lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
 
 	/* Always do a register read first so we can insert the new bits  */
 
@@ -458,9 +447,7 @@
 
       unlock_and_exit:
 
-	if (flags & ACPI_MTX_LOCK) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
-	}
+	acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
 
 	/* Normalize the value that was read */
 
@@ -474,7 +461,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_set_register);
+ACPI_EXPORT_SYMBOL(acpi_set_register)
 
 /******************************************************************************
  *
@@ -490,21 +477,18 @@
  *              given offset.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_hw_register_read(u8 use_lock, u32 register_id, u32 * return_value)
 {
 	u32 value1 = 0;
 	u32 value2 = 0;
 	acpi_status status;
+	acpi_cpu_flags lock_flags = 0;
 
-	ACPI_FUNCTION_TRACE("hw_register_read");
+	ACPI_FUNCTION_TRACE(hw_register_read);
 
 	if (ACPI_MTX_LOCK == use_lock) {
-		status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
+		lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
 	}
 
 	switch (register_id) {
@@ -582,7 +566,7 @@
 
       unlock_and_exit:
 	if (ACPI_MTX_LOCK == use_lock) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
+		acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
 	}
 
 	if (ACPI_SUCCESS(status)) {
@@ -610,14 +594,12 @@
 acpi_status acpi_hw_register_write(u8 use_lock, u32 register_id, u32 value)
 {
 	acpi_status status;
+	acpi_cpu_flags lock_flags = 0;
 
-	ACPI_FUNCTION_TRACE("hw_register_write");
+	ACPI_FUNCTION_TRACE(hw_register_write);
 
 	if (ACPI_MTX_LOCK == use_lock) {
-		status = acpi_ut_acquire_mutex(ACPI_MTX_HARDWARE);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
+		lock_flags = acpi_os_acquire_lock(acpi_gbl_hardware_lock);
 	}
 
 	switch (register_id) {
@@ -707,7 +689,7 @@
 
       unlock_and_exit:
 	if (ACPI_MTX_LOCK == use_lock) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_HARDWARE);
+		acpi_os_release_lock(acpi_gbl_hardware_lock, lock_flags);
 	}
 
 	return_ACPI_STATUS(status);
@@ -733,7 +715,7 @@
 	u64 address;
 	acpi_status status;
 
-	ACPI_FUNCTION_NAME("hw_low_level_read");
+	ACPI_FUNCTION_NAME(hw_low_level_read);
 
 	/*
 	 * Must have a valid pointer to a GAS structure, and
@@ -805,7 +787,7 @@
 	u64 address;
 	acpi_status status;
 
-	ACPI_FUNCTION_NAME("hw_low_level_write");
+	ACPI_FUNCTION_NAME(hw_low_level_write);
 
 	/*
 	 * Must have a valid pointer to a GAS structure, and
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index 8926927..8bb43ca 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -42,7 +42,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
 #include <acpi/acpi.h>
 
 #define _COMPONENT          ACPI_HARDWARE
@@ -64,7 +63,7 @@
 acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
 {
 
-	ACPI_FUNCTION_TRACE("acpi_set_firmware_waking_vector");
+	ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
 
 	/* Set the vector */
 
@@ -79,6 +78,8 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_firmware_waking_vector
@@ -92,13 +93,12 @@
  * DESCRIPTION: Access function for the firmware_waking_vector field in FACS
  *
  ******************************************************************************/
-
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
 acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
 {
 
-	ACPI_FUNCTION_TRACE("acpi_get_firmware_waking_vector");
+	ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector);
 
 	if (!physical_address) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -118,6 +118,8 @@
 
 	return_ACPI_STATUS(AE_OK);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector)
 #endif
 
 /*******************************************************************************
@@ -134,14 +136,13 @@
  *              various OS-specific tasks between the two steps.
  *
  ******************************************************************************/
-
 acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
 {
 	acpi_status status;
 	struct acpi_object_list arg_list;
 	union acpi_object arg;
 
-	ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_prep");
+	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
 
 	/*
 	 * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
@@ -206,6 +207,8 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enter_sleep_state
@@ -218,7 +221,6 @@
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
-
 acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
 {
 	u32 PM1Acontrol;
@@ -228,7 +230,7 @@
 	u32 in_value;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_enter_sleep_state");
+	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
 
 	if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
 	    (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
@@ -378,7 +380,7 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
-EXPORT_SYMBOL(acpi_enter_sleep_state);
+ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
 
 /*******************************************************************************
  *
@@ -392,13 +394,12 @@
  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
  *
  ******************************************************************************/
-
 acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
 {
 	u32 in_value;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_enter_sleep_state_s4bios");
+	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios);
 
 	status =
 	    acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1, ACPI_MTX_DO_NOT_LOCK);
@@ -443,7 +444,7 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
-EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios);
+ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
 
 /*******************************************************************************
  *
@@ -457,7 +458,6 @@
  *              Called with interrupts ENABLED.
  *
  ******************************************************************************/
-
 acpi_status acpi_leave_sleep_state(u8 sleep_state)
 {
 	struct acpi_object_list arg_list;
@@ -468,7 +468,7 @@
 	u32 PM1Acontrol;
 	u32 PM1Bcontrol;
 
-	ACPI_FUNCTION_TRACE("acpi_leave_sleep_state");
+	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
 
 	/*
 	 * Set SLP_TYPE and SLP_EN to state S0.
@@ -490,6 +490,7 @@
 					       ACPI_REGISTER_PM1_CONTROL,
 					       &PM1Acontrol);
 		if (ACPI_SUCCESS(status)) {
+
 			/* Clear SLP_EN and SLP_TYP fields */
 
 			PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
@@ -583,3 +584,5 @@
 
 	return_ACPI_STATUS(status);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)
diff --git a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c
index fc10b7c..c4ec47c 100644
--- a/drivers/acpi/hardware/hwtimer.c
+++ b/drivers/acpi/hardware/hwtimer.c
@@ -42,7 +42,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
 #include <acpi/acpi.h>
 
 #define _COMPONENT          ACPI_HARDWARE
@@ -61,13 +60,13 @@
  ******************************************************************************/
 acpi_status acpi_get_timer_resolution(u32 * resolution)
 {
-	ACPI_FUNCTION_TRACE("acpi_get_timer_resolution");
+	ACPI_FUNCTION_TRACE(acpi_get_timer_resolution);
 
 	if (!resolution) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	if (0 == acpi_gbl_FADT->tmr_val_ext) {
+	if (acpi_gbl_FADT->tmr_val_ext == 0) {
 		*resolution = 24;
 	} else {
 		*resolution = 32;
@@ -76,6 +75,8 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_timer_resolution)
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_get_timer
@@ -87,12 +88,11 @@
  * DESCRIPTION: Obtains current value of ACPI PM Timer (in ticks).
  *
  ******************************************************************************/
-
 acpi_status acpi_get_timer(u32 * ticks)
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_get_timer");
+	ACPI_FUNCTION_TRACE(acpi_get_timer);
 
 	if (!ticks) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -103,7 +103,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_timer);
+ACPI_EXPORT_SYMBOL(acpi_get_timer)
 
 /******************************************************************************
  *
@@ -133,7 +133,6 @@
  *              2**32 Ticks / 3,600,000 Ticks/Sec = 1193 sec or 19.88 minutes
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_timer_duration(u32 start_ticks, u32 end_ticks, u32 * time_elapsed)
 {
@@ -141,7 +140,7 @@
 	u32 delta_ticks;
 	acpi_integer quotient;
 
-	ACPI_FUNCTION_TRACE("acpi_get_timer_duration");
+	ACPI_FUNCTION_TRACE(acpi_get_timer_duration);
 
 	if (!time_elapsed) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -154,7 +153,8 @@
 	if (start_ticks < end_ticks) {
 		delta_ticks = end_ticks - start_ticks;
 	} else if (start_ticks > end_ticks) {
-		if (0 == acpi_gbl_FADT->tmr_val_ext) {
+		if (acpi_gbl_FADT->tmr_val_ext == 0) {
+
 			/* 24-bit Timer */
 
 			delta_ticks =
@@ -183,4 +183,4 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_timer_duration);
+ACPI_EXPORT_SYMBOL(acpi_get_timer_duration)
diff --git a/drivers/acpi/hotkey.c b/drivers/acpi/hotkey.c
index 2e2e4051..c25b2b9 100644
--- a/drivers/acpi/hotkey.c
+++ b/drivers/acpi/hotkey.c
@@ -723,6 +723,8 @@
 		goto do_fail;
 	count = tmp1 - tmp;
 	*action_handle = (char *)kmalloc(count + 1, GFP_KERNEL);
+	if (!*action_handle)
+		goto do_fail;
 	strncpy(*action_handle, tmp, count);
 	*(*action_handle + count) = 0;
 
diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
index 262b1f4..15fc124 100644
--- a/drivers/acpi/ibm_acpi.c
+++ b/drivers/acpi/ibm_acpi.c
@@ -567,6 +567,69 @@
 	return 0;
 }
 
+static int wan_supported;
+
+static int wan_init(void)
+{
+	wan_supported = hkey_handle &&
+	    acpi_evalf(hkey_handle, NULL, "GWAN", "qv");
+
+	return 0;
+}
+
+static int wan_status(void)
+{
+	int status;
+
+	if (!wan_supported ||
+	    !acpi_evalf(hkey_handle, &status, "GWAN", "d"))
+		status = 0;
+
+	return status;
+}
+
+static int wan_read(char *p)
+{
+	int len = 0;
+	int status = wan_status();
+
+	if (!wan_supported)
+		len += sprintf(p + len, "status:\t\tnot supported\n");
+	else if (!(status & 1))
+		len += sprintf(p + len, "status:\t\tnot installed\n");
+	else {
+		len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 1));
+		len += sprintf(p + len, "commands:\tenable, disable\n");
+	}
+
+	return len;
+}
+
+static int wan_write(char *buf)
+{
+	int status = wan_status();
+	char *cmd;
+	int do_cmd = 0;
+
+	if (!wan_supported)
+		return -ENODEV;
+
+	while ((cmd = next_cmd(&buf))) {
+		if (strlencmp(cmd, "enable") == 0) {
+			status |= 2;
+		} else if (strlencmp(cmd, "disable") == 0) {
+			status &= ~2;
+		} else
+			return -EINVAL;
+		do_cmd = 1;
+	}
+
+	if (do_cmd && !acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
+		return -EIO;
+
+	return 0;
+}
+
 static int video_supported;
 static int video_orig_autosw;
 
@@ -1563,6 +1626,13 @@
 	 .write = bluetooth_write,
 	 },
 	{
+	 .name = "wan",
+	 .init = wan_init,
+	 .read = wan_read,
+	 .write = wan_write,
+	 .experimental = 1,
+	 },
+	{
 	 .name = "video",
 	 .init = video_init,
 	 .read = video_read,
diff --git a/drivers/acpi/motherboard.c b/drivers/acpi/motherboard.c
index 4682441..d51d68f 100644
--- a/drivers/acpi/motherboard.c
+++ b/drivers/acpi/motherboard.c
@@ -37,7 +37,7 @@
 #define ACPI_MB_HID2			"PNP0C02"
 /**
  * Doesn't care about legacy IO ports, only IO ports beyond 0x1000 are reserved
- * Doesn't care about the failure of 'request_region', since other may reserve 
+ * Doesn't care about the failure of 'request_region', since other may reserve
  * the io ports as well
  */
 #define IS_RESERVED_ADDR(base, len) \
@@ -46,7 +46,7 @@
 /*
  * Clearing the flag (IORESOURCE_BUSY) allows drivers to use
  * the io ports if they really know they can use it, while
- * still preventing hotplug PCI devices from using it. 
+ * still preventing hotplug PCI devices from using it.
  */
 static acpi_status acpi_reserve_io_ranges(struct acpi_resource *res, void *data)
 {
@@ -123,49 +123,54 @@
 		},
 };
 
+static void __init acpi_request_region (struct acpi_generic_address *addr,
+	unsigned int length, char *desc)
+{
+	if (!addr->address || !length)
+		return;
+
+	if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_IO)
+		request_region(addr->address, length, desc);
+	else if (addr->address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+		request_mem_region(addr->address, length, desc);
+}
+
 static void __init acpi_reserve_resources(void)
 {
-	if (acpi_gbl_FADT->xpm1a_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
-		request_region(acpi_gbl_FADT->xpm1a_evt_blk.address,
-			       acpi_gbl_FADT->pm1_evt_len, "PM1a_EVT_BLK");
+	acpi_request_region(&acpi_gbl_FADT->xpm1a_evt_blk,
+			       acpi_gbl_FADT->pm1_evt_len, "ACPI PM1a_EVT_BLK");
 
-	if (acpi_gbl_FADT->xpm1b_evt_blk.address && acpi_gbl_FADT->pm1_evt_len)
-		request_region(acpi_gbl_FADT->xpm1b_evt_blk.address,
-			       acpi_gbl_FADT->pm1_evt_len, "PM1b_EVT_BLK");
+	acpi_request_region(&acpi_gbl_FADT->xpm1b_evt_blk,
+			       acpi_gbl_FADT->pm1_evt_len, "ACPI PM1b_EVT_BLK");
 
-	if (acpi_gbl_FADT->xpm1a_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
-		request_region(acpi_gbl_FADT->xpm1a_cnt_blk.address,
-			       acpi_gbl_FADT->pm1_cnt_len, "PM1a_CNT_BLK");
+	acpi_request_region(&acpi_gbl_FADT->xpm1a_cnt_blk,
+			       acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1a_CNT_BLK");
 
-	if (acpi_gbl_FADT->xpm1b_cnt_blk.address && acpi_gbl_FADT->pm1_cnt_len)
-		request_region(acpi_gbl_FADT->xpm1b_cnt_blk.address,
-			       acpi_gbl_FADT->pm1_cnt_len, "PM1b_CNT_BLK");
+	acpi_request_region(&acpi_gbl_FADT->xpm1b_cnt_blk,
+			       acpi_gbl_FADT->pm1_cnt_len, "ACPI PM1b_CNT_BLK");
 
-	if (acpi_gbl_FADT->xpm_tmr_blk.address && acpi_gbl_FADT->pm_tm_len == 4)
-		request_region(acpi_gbl_FADT->xpm_tmr_blk.address, 4, "PM_TMR");
+	if (acpi_gbl_FADT->pm_tm_len == 4)
+		acpi_request_region(&acpi_gbl_FADT->xpm_tmr_blk, 4, "ACPI PM_TMR");
 
-	if (acpi_gbl_FADT->xpm2_cnt_blk.address && acpi_gbl_FADT->pm2_cnt_len)
-		request_region(acpi_gbl_FADT->xpm2_cnt_blk.address,
-			       acpi_gbl_FADT->pm2_cnt_len, "PM2_CNT_BLK");
+	acpi_request_region(&acpi_gbl_FADT->xpm2_cnt_blk,
+			       acpi_gbl_FADT->pm2_cnt_len, "ACPI PM2_CNT_BLK");
 
 	/* Length of GPE blocks must be a non-negative multiple of 2 */
 
-	if (acpi_gbl_FADT->xgpe0_blk.address && acpi_gbl_FADT->gpe0_blk_len &&
-	    !(acpi_gbl_FADT->gpe0_blk_len & 0x1))
-		request_region(acpi_gbl_FADT->xgpe0_blk.address,
-			       acpi_gbl_FADT->gpe0_blk_len, "GPE0_BLK");
+	if (!(acpi_gbl_FADT->gpe0_blk_len & 0x1))
+		acpi_request_region(&acpi_gbl_FADT->xgpe0_blk,
+			       acpi_gbl_FADT->gpe0_blk_len, "ACPI GPE0_BLK");
 
-	if (acpi_gbl_FADT->xgpe1_blk.address && acpi_gbl_FADT->gpe1_blk_len &&
-	    !(acpi_gbl_FADT->gpe1_blk_len & 0x1))
-		request_region(acpi_gbl_FADT->xgpe1_blk.address,
-			       acpi_gbl_FADT->gpe1_blk_len, "GPE1_BLK");
+	if (!(acpi_gbl_FADT->gpe1_blk_len & 0x1))
+		acpi_request_region(&acpi_gbl_FADT->xgpe1_blk,
+			       acpi_gbl_FADT->gpe1_blk_len, "ACPI GPE1_BLK");
 }
 
 static int __init acpi_motherboard_init(void)
 {
 	acpi_bus_register_driver(&acpi_motherboard_driver1);
 	acpi_bus_register_driver(&acpi_motherboard_driver2);
-	/* 
+	/*
 	 * Guarantee motherboard IO reservation first
 	 * This module must run after scan.c
 	 */
diff --git a/drivers/acpi/namespace/nsaccess.c b/drivers/acpi/namespace/nsaccess.c
index 1149bc1..48fadad 100644
--- a/drivers/acpi/namespace/nsaccess.c
+++ b/drivers/acpi/namespace/nsaccess.c
@@ -70,7 +70,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_string val = NULL;
 
-	ACPI_FUNCTION_TRACE("ns_root_initialize");
+	ACPI_FUNCTION_TRACE(ns_root_initialize);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 	if (ACPI_FAILURE(status)) {
@@ -98,6 +98,7 @@
 			  "Entering predefined entries into namespace\n"));
 
 	for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
+
 		/* _OSI is optional for now, will be permanent later */
 
 		if (!ACPI_STRCMP(init_val->name, "_OSI")
@@ -156,7 +157,7 @@
 
 #if defined (ACPI_ASL_COMPILER)
 
-				/* save the parameter count for the i_aSL compiler */
+				/* Save the parameter count for the i_aSL compiler */
 
 				new_node->value = obj_desc->method.param_count;
 #else
@@ -258,10 +259,8 @@
 	/* Save a handle to "_GPE", it is always present */
 
 	if (ACPI_SUCCESS(status)) {
-		status =
-		    acpi_ns_get_node_by_path("\\_GPE", NULL,
-					     ACPI_NS_NO_UPSEARCH,
-					     &acpi_gbl_fadt_gpe_device);
+		status = acpi_ns_get_node(NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH,
+					  &acpi_gbl_fadt_gpe_device);
 	}
 
 	return_ACPI_STATUS(status);
@@ -310,17 +309,17 @@
 	acpi_object_type type_to_check_for;
 	acpi_object_type this_search_type;
 	u32 search_parent_flag = ACPI_NS_SEARCH_PARENT;
-	u32 local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND |
-				    ACPI_NS_SEARCH_PARENT);
+	u32 local_flags;
 
-	ACPI_FUNCTION_TRACE("ns_lookup");
+	ACPI_FUNCTION_TRACE(ns_lookup);
 
 	if (!return_node) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	acpi_gbl_ns_lookup_count++;
+	local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT);
 	*return_node = ACPI_ENTRY_NOT_FOUND;
+	acpi_gbl_ns_lookup_count++;
 
 	if (!acpi_gbl_root_node) {
 		return_ACPI_STATUS(AE_NO_NAMESPACE);
@@ -346,14 +345,17 @@
 			return_ACPI_STATUS(AE_AML_INTERNAL);
 		}
 
-		/*
-		 * This node might not be a actual "scope" node (such as a
-		 * Device/Method, etc.)  It could be a Package or other object node.
-		 * Backup up the tree to find the containing scope node.
-		 */
-		while (!acpi_ns_opens_scope(prefix_node->type) &&
-		       prefix_node->type != ACPI_TYPE_ANY) {
-			prefix_node = acpi_ns_get_parent_node(prefix_node);
+		if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) {
+			/*
+			 * This node might not be a actual "scope" node (such as a
+			 * Device/Method, etc.)  It could be a Package or other object node.
+			 * Backup up the tree to find the containing scope node.
+			 */
+			while (!acpi_ns_opens_scope(prefix_node->type) &&
+			       prefix_node->type != ACPI_TYPE_ANY) {
+				prefix_node =
+				    acpi_ns_get_parent_node(prefix_node);
+			}
 		}
 	}
 
@@ -365,6 +367,7 @@
 	 * Begin examination of the actual pathname
 	 */
 	if (!pathname) {
+
 		/* A Null name_path is allowed and refers to the root */
 
 		num_segments = 0;
@@ -389,6 +392,7 @@
 		 * to the current scope).
 		 */
 		if (*path == (u8) AML_ROOT_PREFIX) {
+
 			/* Pathname is fully qualified, start from the root */
 
 			this_node = acpi_gbl_root_node;
@@ -416,6 +420,7 @@
 			this_node = prefix_node;
 			num_carats = 0;
 			while (*path == (u8) AML_PARENT_PREFIX) {
+
 				/* Name is fully qualified, no search rules apply */
 
 				search_parent_flag = ACPI_NS_NO_UPSEARCH;
@@ -430,6 +435,7 @@
 				num_carats++;
 				this_node = acpi_ns_get_parent_node(this_node);
 				if (!this_node) {
+
 					/* Current scope has no parent scope */
 
 					ACPI_ERROR((AE_INFO,
@@ -569,6 +575,7 @@
 					     &this_node);
 		if (ACPI_FAILURE(status)) {
 			if (status == AE_NOT_FOUND) {
+
 				/* Name not found in ACPI namespace */
 
 				ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
@@ -602,10 +609,11 @@
 		    (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
 		    (this_node->type != ACPI_TYPE_ANY) &&
 		    (this_node->type != type_to_check_for)) {
+
 			/* Complain about a type mismatch */
 
 			ACPI_WARNING((AE_INFO,
-				      "ns_lookup: Type mismatch on %4.4s (%s), searching for (%s)",
+				      "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
 				      ACPI_CAST_PTR(char, &simple_name),
 				      acpi_ut_get_type_name(this_node->type),
 				      acpi_ut_get_type_name
diff --git a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c
index 9b871f3..dc3f073 100644
--- a/drivers/acpi/namespace/nsalloc.c
+++ b/drivers/acpi/namespace/nsalloc.c
@@ -47,9 +47,6 @@
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsalloc")
 
-/* Local prototypes */
-static void acpi_ns_remove_reference(struct acpi_namespace_node *node);
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_create_node
@@ -61,14 +58,13 @@
  * DESCRIPTION: Create a namespace node
  *
  ******************************************************************************/
-
 struct acpi_namespace_node *acpi_ns_create_node(u32 name)
 {
 	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("ns_create_node");
+	ACPI_FUNCTION_TRACE(ns_create_node);
 
-	node = ACPI_MEM_CALLOCATE(sizeof(struct acpi_namespace_node));
+	node = acpi_os_acquire_object(acpi_gbl_namespace_cache);
 	if (!node) {
 		return_PTR(NULL);
 	}
@@ -76,9 +72,7 @@
 	ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_allocated++);
 
 	node->name.integer = name;
-	node->reference_count = 1;
 	ACPI_SET_DESCRIPTOR_TYPE(node, ACPI_DESC_TYPE_NAMED);
-
 	return_PTR(node);
 }
 
@@ -100,7 +94,7 @@
 	struct acpi_namespace_node *prev_node;
 	struct acpi_namespace_node *next_node;
 
-	ACPI_FUNCTION_TRACE_PTR("ns_delete_node", node);
+	ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node);
 
 	parent_node = acpi_ns_get_parent_node(node);
 
@@ -115,6 +109,7 @@
 	}
 
 	if (prev_node) {
+
 		/* Node is not first child, unlink it */
 
 		prev_node->peer = next_node->peer;
@@ -125,6 +120,7 @@
 		/* Node is first child (has no previous peer) */
 
 		if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
+
 			/* No peers at all */
 
 			parent_node->child = NULL;
@@ -137,10 +133,10 @@
 	ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
 
 	/*
-	 * Detach an object if there is one then delete the node
+	 * Detach an object if there is one, then delete the node
 	 */
 	acpi_ns_detach_object(node);
-	ACPI_MEM_FREE(node);
+	(void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
 	return_VOID;
 }
 
@@ -171,7 +167,7 @@
 	acpi_owner_id owner_id = 0;
 	struct acpi_namespace_node *child_node;
 
-	ACPI_FUNCTION_TRACE("ns_install_node");
+	ACPI_FUNCTION_TRACE(ns_install_node);
 
 	/*
 	 * Get the owner ID from the Walk state
@@ -216,14 +212,6 @@
 			  acpi_ut_get_type_name(parent_node->type),
 			  parent_node));
 
-	/*
-	 * Increment the reference count(s) of all parents up to
-	 * the root!
-	 */
-	while ((node = acpi_ns_get_parent_node(node)) != NULL) {
-		node->reference_count++;
-	}
-
 	return_VOID;
 }
 
@@ -244,10 +232,9 @@
 {
 	struct acpi_namespace_node *child_node;
 	struct acpi_namespace_node *next_node;
-	struct acpi_namespace_node *node;
 	u8 flags;
 
-	ACPI_FUNCTION_TRACE_PTR("ns_delete_children", parent_node);
+	ACPI_FUNCTION_TRACE_PTR(ns_delete_children, parent_node);
 
 	if (!parent_node) {
 		return_VOID;
@@ -264,6 +251,7 @@
 	 * Deallocate all children at this level
 	 */
 	do {
+
 		/* Get the things we need */
 
 		next_node = child_node->peer;
@@ -289,26 +277,10 @@
 		 */
 		acpi_ns_detach_object(child_node);
 
-		/*
-		 * Decrement the reference count(s) of all parents up to
-		 * the root! (counts were incremented when the node was created)
-		 */
-		node = child_node;
-		while ((node = acpi_ns_get_parent_node(node)) != NULL) {
-			node->reference_count--;
-		}
-
-		/* There should be only one reference remaining on this node */
-
-		if (child_node->reference_count != 1) {
-			ACPI_WARNING((AE_INFO,
-				      "Existing references (%d) on node being deleted (%p)",
-				      child_node->reference_count, child_node));
-		}
-
 		/* Now we can delete the node */
 
-		ACPI_MEM_FREE(child_node);
+		(void)acpi_os_release_object(acpi_gbl_namespace_cache,
+					     child_node);
 
 		/* And move on to the next child in the list */
 
@@ -341,7 +313,7 @@
 	struct acpi_namespace_node *child_node = NULL;
 	u32 level = 1;
 
-	ACPI_FUNCTION_TRACE("ns_delete_namespace_subtree");
+	ACPI_FUNCTION_TRACE(ns_delete_namespace_subtree);
 
 	if (!parent_node) {
 		return_VOID;
@@ -352,11 +324,14 @@
 	 * to where we started.
 	 */
 	while (level > 0) {
+
 		/* Get the next node in this scope (NULL if none) */
 
-		child_node = acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
-						   child_node);
+		child_node =
+		    acpi_ns_get_next_node(ACPI_TYPE_ANY, parent_node,
+					  child_node);
 		if (child_node) {
+
 			/* Found a child node - detach any attached object */
 
 			acpi_ns_detach_object(child_node);
@@ -401,55 +376,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_remove_reference
- *
- * PARAMETERS:  Node           - Named node whose reference count is to be
- *                               decremented
- *
- * RETURN:      None.
- *
- * DESCRIPTION: Remove a Node reference.  Decrements the reference count
- *              of all parent Nodes up to the root.  Any node along
- *              the way that reaches zero references is freed.
- *
- ******************************************************************************/
-
-static void acpi_ns_remove_reference(struct acpi_namespace_node *node)
-{
-	struct acpi_namespace_node *parent_node;
-	struct acpi_namespace_node *this_node;
-
-	ACPI_FUNCTION_ENTRY();
-
-	/*
-	 * Decrement the reference count(s) of this node and all
-	 * nodes up to the root,  Delete anything with zero remaining references.
-	 */
-	this_node = node;
-	while (this_node) {
-		/* Prepare to move up to parent */
-
-		parent_node = acpi_ns_get_parent_node(this_node);
-
-		/* Decrement the reference count on this node */
-
-		this_node->reference_count--;
-
-		/* Delete the node if no more references */
-
-		if (!this_node->reference_count) {
-			/* Delete all children and delete the node */
-
-			acpi_ns_delete_children(this_node);
-			acpi_ns_delete_node(this_node);
-		}
-
-		this_node = parent_node;
-	}
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ns_delete_namespace_by_owner
  *
  * PARAMETERS:  owner_id    - All nodes with this owner will be deleted
@@ -469,15 +395,15 @@
 	u32 level;
 	struct acpi_namespace_node *parent_node;
 
-	ACPI_FUNCTION_TRACE_U32("ns_delete_namespace_by_owner", owner_id);
+	ACPI_FUNCTION_TRACE_U32(ns_delete_namespace_by_owner, owner_id);
 
 	if (owner_id == 0) {
 		return_VOID;
 	}
 
+	deletion_node = NULL;
 	parent_node = acpi_gbl_root_node;
 	child_node = NULL;
-	deletion_node = NULL;
 	level = 1;
 
 	/*
@@ -494,12 +420,14 @@
 					  child_node);
 
 		if (deletion_node) {
-			acpi_ns_remove_reference(deletion_node);
+			acpi_ns_delete_children(deletion_node);
+			acpi_ns_delete_node(deletion_node);
 			deletion_node = NULL;
 		}
 
 		if (child_node) {
 			if (child_node->owner_id == owner_id) {
+
 				/* Found a matching child node - detach any attached object */
 
 				acpi_ns_detach_object(child_node);
diff --git a/drivers/acpi/namespace/nsdump.c b/drivers/acpi/namespace/nsdump.c
index a280731..d72df66 100644
--- a/drivers/acpi/namespace/nsdump.c
+++ b/drivers/acpi/namespace/nsdump.c
@@ -75,7 +75,7 @@
 {
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_NAME("ns_print_pathname");
+	ACPI_FUNCTION_NAME(ns_print_pathname);
 
 	if (!(acpi_dbg_level & ACPI_LV_NAMES)
 	    || !(acpi_dbg_layer & ACPI_NAMESPACE)) {
@@ -123,7 +123,7 @@
 acpi_ns_dump_pathname(acpi_handle handle, char *msg, u32 level, u32 component)
 {
 
-	ACPI_FUNCTION_TRACE("ns_dump_pathname");
+	ACPI_FUNCTION_TRACE(ns_dump_pathname);
 
 	/* Do this only if the requested debug level and component are enabled */
 
@@ -167,7 +167,7 @@
 	u32 dbg_level;
 	u32 i;
 
-	ACPI_FUNCTION_NAME("ns_dump_one_object");
+	ACPI_FUNCTION_NAME(ns_dump_one_object);
 
 	/* Is output enabled? */
 
@@ -191,6 +191,7 @@
 	}
 
 	if (!(info->display_type & ACPI_DISPLAY_SHORT)) {
+
 		/* Indent the object according to the level */
 
 		acpi_os_printf("%2d%*s", (u32) level - 1, (int)level * 2, " ");
@@ -203,6 +204,9 @@
 		}
 
 		if (!acpi_ut_valid_acpi_name(this_node->name.integer)) {
+			this_node->name.integer =
+			    acpi_ut_repair_name(this_node->name.integer);
+
 			ACPI_WARNING((AE_INFO, "Invalid ACPI Name %08X",
 				      this_node->name.integer));
 		}
@@ -226,6 +230,7 @@
 	case ACPI_DISPLAY_SUMMARY:
 
 		if (!obj_desc) {
+
 			/* No attached object, we are done */
 
 			acpi_os_printf("\n");
@@ -419,6 +424,7 @@
 
 		acpi_os_printf("O:%p", obj_desc);
 		if (!obj_desc) {
+
 			/* No attached object, we are done */
 
 			acpi_os_printf("\n");
@@ -669,7 +675,7 @@
 {
 	acpi_handle search_handle = search_base;
 
-	ACPI_FUNCTION_TRACE("ns_dump_tables");
+	ACPI_FUNCTION_TRACE(ns_dump_tables);
 
 	if (!acpi_gbl_root_node) {
 		/*
@@ -682,6 +688,7 @@
 	}
 
 	if (ACPI_NS_ALL == search_base) {
+
 		/* Entire namespace */
 
 		search_handle = acpi_gbl_root_node;
diff --git a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c
index aff899a..c6bf5d3 100644
--- a/drivers/acpi/namespace/nsdumpdv.c
+++ b/drivers/acpi/namespace/nsdumpdv.c
@@ -74,7 +74,7 @@
 	acpi_status status;
 	u32 i;
 
-	ACPI_FUNCTION_NAME("ns_dump_one_device");
+	ACPI_FUNCTION_NAME(ns_dump_one_device);
 
 	status =
 	    acpi_ns_dump_one_object(obj_handle, level, context, return_value);
@@ -92,7 +92,7 @@
 				      info->hardware_id.value,
 				      ACPI_FORMAT_UINT64(info->address),
 				      info->current_status));
-		ACPI_MEM_FREE(info);
+		ACPI_FREE(info);
 	}
 
 	return (status);
@@ -115,7 +115,7 @@
 	acpi_handle sys_bus_handle;
 	acpi_status status;
 
-	ACPI_FUNCTION_NAME("ns_dump_root_devices");
+	ACPI_FUNCTION_NAME(ns_dump_root_devices);
 
 	/* Only dump the table if tracing is enabled */
 
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 19d7b94..4b0a4a8 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -1,7 +1,6 @@
 /*******************************************************************************
  *
- * Module Name: nseval - Object evaluation interfaces -- includes control
- *                       method lookup and execution.
+ * Module Name: nseval - Object evaluation, includes control method execution
  *
  ******************************************************************************/
 
@@ -50,196 +49,14 @@
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nseval")
 
-/* Local prototypes */
-static acpi_status
-acpi_ns_execute_control_method(struct acpi_parameter_info *info);
-
-static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info);
-
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_evaluate_relative
+ * FUNCTION:    acpi_ns_evaluate
  *
- * PARAMETERS:  Pathname        - Name of method to execute, If NULL, the
- *                                handle is the object to execute
- *              Info            - Method info block, contains:
- *                  return_object   - Where to put method's return value (if
- *                                    any).  If NULL, no value is returned.
- *                  Params          - List of parameters to pass to the method,
- *                                    terminated by NULL.  Params itself may be
- *                                    NULL if no parameters are being passed.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Evaluate the object or find and execute the requested method
- *
- * MUTEX:       Locks Namespace
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info)
-{
-	acpi_status status;
-	struct acpi_namespace_node *node = NULL;
-	union acpi_generic_state *scope_info;
-	char *internal_path = NULL;
-
-	ACPI_FUNCTION_TRACE("ns_evaluate_relative");
-
-	/*
-	 * Must have a valid object handle
-	 */
-	if (!info || !info->node) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
-
-	/* Build an internal name string for the method */
-
-	status = acpi_ns_internalize_name(pathname, &internal_path);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	scope_info = acpi_ut_create_generic_state();
-	if (!scope_info) {
-		goto cleanup1;
-	}
-
-	/* Get the prefix handle and Node */
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		goto cleanup;
-	}
-
-	info->node = acpi_ns_map_handle_to_node(info->node);
-	if (!info->node) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-		status = AE_BAD_PARAMETER;
-		goto cleanup;
-	}
-
-	/* Lookup the name in the namespace */
-
-	scope_info->scope.node = info->node;
-	status = acpi_ns_lookup(scope_info, internal_path, ACPI_TYPE_ANY,
-				ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
-				&node);
-
-	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object [%s] not found [%s]\n",
-				  pathname, acpi_format_exception(status)));
-		goto cleanup;
-	}
-
-	/*
-	 * Now that we have a handle to the object, we can attempt to evaluate it.
-	 */
-	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
-			  pathname, node, acpi_ns_get_attached_object(node)));
-
-	info->node = node;
-	status = acpi_ns_evaluate_by_handle(info);
-
-	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-			  "*** Completed eval of object %s ***\n", pathname));
-
-      cleanup:
-	acpi_ut_delete_generic_state(scope_info);
-
-      cleanup1:
-	ACPI_MEM_FREE(internal_path);
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_evaluate_by_name
- *
- * PARAMETERS:  Pathname        - Fully qualified pathname to the object
- *              Info                - Method info block, contains:
- *                  return_object   - Where to put method's return value (if
- *                                    any).  If NULL, no value is returned.
- *                  Params          - List of parameters to pass to the method,
- *                                    terminated by NULL.  Params itself may be
- *                                    NULL if no parameters are being passed.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Evaluate the object or rind and execute the requested method
- *              passing the given parameters
- *
- * MUTEX:       Locks Namespace
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info)
-{
-	acpi_status status;
-	char *internal_path = NULL;
-
-	ACPI_FUNCTION_TRACE("ns_evaluate_by_name");
-
-	/* Build an internal name string for the method */
-
-	status = acpi_ns_internalize_name(pathname, &internal_path);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		goto cleanup;
-	}
-
-	/* Lookup the name in the namespace */
-
-	status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
-				ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
-				&info->node);
-
-	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
-	if (ACPI_FAILURE(status)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-				  "Object at [%s] was not found, status=%.4X\n",
-				  pathname, status));
-		goto cleanup;
-	}
-
-	/*
-	 * Now that we have a handle to the object, we can attempt to evaluate it.
-	 */
-	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
-			  pathname, info->node,
-			  acpi_ns_get_attached_object(info->node)));
-
-	status = acpi_ns_evaluate_by_handle(info);
-
-	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
-			  "*** Completed eval of object %s ***\n", pathname));
-
-      cleanup:
-
-	/* Cleanup */
-
-	if (internal_path) {
-		ACPI_MEM_FREE(internal_path);
-	}
-
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_evaluate_by_handle
- *
- * PARAMETERS:  Info            - Method info block, contains:
- *                  Node            - Method/Object Node to execute
+ * PARAMETERS:  Info            - Evaluation info block, contains:
+ *                  prefix_node     - Prefix or Method/Object Node to execute
+ *                  Pathname        - Name of method to execute, If NULL, the
+ *                                    Node is the object to execute
  *                  Parameters      - List of parameters to pass to the method,
  *                                    terminated by NULL. Params itself may be
  *                                    NULL if no parameters are being passed.
@@ -248,29 +65,21 @@
  *                  parameter_type  - Type of Parameter list
  *                  return_object   - Where to put method's return value (if
  *                                    any). If NULL, no value is returned.
+ *                  Flags           - ACPI_IGNORE_RETURN_VALUE to delete return
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Evaluate object or execute the requested method passing the
- *              given parameters
+ * DESCRIPTION: Execute a control method or return the current value of an
+ *              ACPI namespace object.
  *
- * MUTEX:       Locks Namespace
+ * MUTEX:       Locks interpreter
  *
  ******************************************************************************/
-
-acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info)
+acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ns_evaluate_by_handle");
-
-	/* Check if namespace has been initialized */
-
-	if (!acpi_gbl_root_node) {
-		return_ACPI_STATUS(AE_NO_NAMESPACE);
-	}
-
-	/* Parameter Validation */
+	ACPI_FUNCTION_TRACE(ns_evaluate);
 
 	if (!info) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -280,202 +89,120 @@
 
 	info->return_object = NULL;
 
-	/* Get the prefix handle and Node */
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	/*
+	 * Get the actual namespace node for the target object. Handles these cases:
+	 *
+	 * 1) Null node, Pathname (absolute path)
+	 * 2) Node, Pathname (path relative to Node)
+	 * 3) Node, Null Pathname
+	 */
+	status = acpi_ns_get_node(info->prefix_node, info->pathname,
+				  ACPI_NS_NO_UPSEARCH, &info->resolved_node);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
-	info->node = acpi_ns_map_handle_to_node(info->node);
-	if (!info->node) {
-		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
-
 	/*
 	 * For a method alias, we must grab the actual method node so that proper
 	 * scoping context will be established before execution.
 	 */
-	if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
-		info->node =
+	if (acpi_ns_get_type(info->resolved_node) ==
+	    ACPI_TYPE_LOCAL_METHOD_ALIAS) {
+		info->resolved_node =
 		    ACPI_CAST_PTR(struct acpi_namespace_node,
-				  info->node->object);
+				  info->resolved_node->object);
 	}
 
+	ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname,
+			  info->resolved_node,
+			  acpi_ns_get_attached_object(info->resolved_node)));
+
 	/*
 	 * Two major cases here:
-	 * 1) The object is an actual control method -- execute it.
-	 * 2) The object is not a method -- just return it's current value
 	 *
-	 * In both cases, the namespace is unlocked by the acpi_ns* procedure
+	 * 1) The object is a control method -- execute it
+	 * 2) The object is not a method -- just return it's current value
 	 */
-	if (acpi_ns_get_type(info->node) == ACPI_TYPE_METHOD) {
+	if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) {
 		/*
-		 * Case 1) We have an actual control method to execute
+		 * 1) Object is a control method - execute it
 		 */
-		status = acpi_ns_execute_control_method(info);
+
+		/* Verify that there is a method object associated with this node */
+
+		info->obj_desc =
+		    acpi_ns_get_attached_object(info->resolved_node);
+		if (!info->obj_desc) {
+			ACPI_ERROR((AE_INFO,
+				    "Control method has no attached sub-object"));
+			return_ACPI_STATUS(AE_NULL_OBJECT);
+		}
+
+		ACPI_DUMP_PATHNAME(info->resolved_node, "Execute Method:",
+				   ACPI_LV_INFO, _COMPONENT);
+
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "Method at AML address %p Length %X\n",
+				  info->obj_desc->method.aml_start + 1,
+				  info->obj_desc->method.aml_length - 1));
+
+		/*
+		 * Any namespace deletion must acquire both the namespace and
+		 * interpreter locks to ensure that no thread is using the portion of
+		 * the namespace that is being deleted.
+		 *
+		 * Execute the method via the interpreter. The interpreter is locked
+		 * here before calling into the AML parser
+		 */
+		status = acpi_ex_enter_interpreter();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+
+		status = acpi_ps_execute_method(info);
+		acpi_ex_exit_interpreter();
 	} else {
 		/*
-		 * Case 2) Object is NOT a method, just return its current value
+		 * 2) Object is not a method, return its current value
 		 */
-		status = acpi_ns_get_object_value(info);
-	}
 
-	/*
-	 * Check if there is a return value on the stack that must be dealt with
-	 */
-	if (status == AE_CTRL_RETURN_VALUE) {
-		/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
+		/*
+		 * Objects require additional resolution steps (e.g., the Node may be
+		 * a field that must be read, etc.) -- we can't just grab the object
+		 * out of the node.
+		 *
+		 * Use resolve_node_to_value() to get the associated value.
+		 *
+		 * NOTE: we can get away with passing in NULL for a walk state because
+		 * resolved_node is guaranteed to not be a reference to either a method
+		 * local or a method argument (because this interface is never called
+		 * from a running method.)
+		 *
+		 * Even though we do not directly invoke the interpreter for object
+		 * resolution, we must lock it because we could access an opregion.
+		 * The opregion access code assumes that the interpreter is locked.
+		 */
+		status = acpi_ex_enter_interpreter();
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
 
-		status = AE_OK;
-	}
+		/* Function has a strange interface */
 
-	/*
-	 * Namespace was unlocked by the handling acpi_ns* function, so we
-	 * just return
-	 */
-	return_ACPI_STATUS(status);
-}
+		status =
+		    acpi_ex_resolve_node_to_value(&info->resolved_node, NULL);
+		acpi_ex_exit_interpreter();
 
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_execute_control_method
- *
- * PARAMETERS:  Info            - Method info block, contains:
- *                  Node            - Method Node to execute
- *                  obj_desc        - Method object
- *                  Parameters      - List of parameters to pass to the method,
- *                                    terminated by NULL. Params itself may be
- *                                    NULL if no parameters are being passed.
- *                  return_object   - Where to put method's return value (if
- *                                    any). If NULL, no value is returned.
- *                  parameter_type  - Type of Parameter list
- *                  return_object   - Where to put method's return value (if
- *                                    any). If NULL, no value is returned.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Execute the requested method passing the given parameters
- *
- * MUTEX:       Assumes namespace is locked
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ns_execute_control_method(struct acpi_parameter_info *info)
-{
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE("ns_execute_control_method");
-
-	/* Verify that there is a method associated with this object */
-
-	info->obj_desc = acpi_ns_get_attached_object(info->node);
-	if (!info->obj_desc) {
-		ACPI_ERROR((AE_INFO, "No attached method object"));
-
-		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-		return_ACPI_STATUS(AE_NULL_OBJECT);
-	}
-
-	ACPI_DUMP_PATHNAME(info->node, "Execute Method:",
-			   ACPI_LV_INFO, _COMPONENT);
-
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Method at AML address %p Length %X\n",
-			  info->obj_desc->method.aml_start + 1,
-			  info->obj_desc->method.aml_length - 1));
-
-	/*
-	 * Unlock the namespace before execution.  This allows namespace access
-	 * via the external Acpi* interfaces while a method is being executed.
-	 * However, any namespace deletion must acquire both the namespace and
-	 * interpreter locks to ensure that no thread is using the portion of the
-	 * namespace that is being deleted.
-	 */
-	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	/*
-	 * Execute the method via the interpreter.  The interpreter is locked
-	 * here before calling into the AML parser
-	 */
-	status = acpi_ex_enter_interpreter();
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	status = acpi_ps_execute_method(info);
-	acpi_ex_exit_interpreter();
-
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_get_object_value
- *
- * PARAMETERS:  Info            - Method info block, contains:
- *                  Node            - Object's NS node
- *                  return_object   - Where to put object value (if
- *                                    any). If NULL, no value is returned.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Return the current value of the object
- *
- * MUTEX:       Assumes namespace is locked, leaves namespace unlocked
- *
- ******************************************************************************/
-
-static acpi_status acpi_ns_get_object_value(struct acpi_parameter_info *info)
-{
-	acpi_status status = AE_OK;
-	struct acpi_namespace_node *resolved_node = info->node;
-
-	ACPI_FUNCTION_TRACE("ns_get_object_value");
-
-	/*
-	 * Objects require additional resolution steps (e.g., the Node may be a
-	 * field that must be read, etc.) -- we can't just grab the object out of
-	 * the node.
-	 */
-
-	/*
-	 * Use resolve_node_to_value() to get the associated value. This call always
-	 * deletes obj_desc (allocated above).
-	 *
-	 * NOTE: we can get away with passing in NULL for a walk state because
-	 * obj_desc is guaranteed to not be a reference to either a method local or
-	 * a method argument (because this interface can only be called from the
-	 * acpi_evaluate external interface, never called from a running method.)
-	 *
-	 * Even though we do not directly invoke the interpreter for this, we must
-	 * enter it because we could access an opregion. The opregion access code
-	 * assumes that the interpreter is locked.
-	 *
-	 * We must release the namespace lock before entering the intepreter.
-	 */
-	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	status = acpi_ex_enter_interpreter();
-	if (ACPI_SUCCESS(status)) {
-		status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
 		/*
 		 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
 		 * in resolved_node.
 		 */
-		acpi_ex_exit_interpreter();
-
 		if (ACPI_SUCCESS(status)) {
 			status = AE_CTRL_RETURN_VALUE;
-			info->return_object = ACPI_CAST_PTR
-			    (union acpi_operand_object, resolved_node);
+			info->return_object =
+			    ACPI_CAST_PTR(union acpi_operand_object,
+					  info->resolved_node);
+
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 					  "Returning object %p [%s]\n",
 					  info->return_object,
@@ -484,7 +211,30 @@
 		}
 	}
 
-	/* Namespace is unlocked */
+	/*
+	 * Check if there is a return value that must be dealt with
+	 */
+	if (status == AE_CTRL_RETURN_VALUE) {
 
+		/* If caller does not want the return value, delete it */
+
+		if (info->flags & ACPI_IGNORE_RETURN_VALUE) {
+			acpi_ut_remove_reference(info->return_object);
+			info->return_object = NULL;
+		}
+
+		/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
+
+		status = AE_OK;
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
+			  "*** Completed evaluation of object %s ***\n",
+			  info->pathname));
+
+	/*
+	 * Namespace was unlocked by the handling acpi_ns* function, so we
+	 * just return
+	 */
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index 9f929e4..aec8488 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -58,6 +58,10 @@
 acpi_ns_init_one_device(acpi_handle obj_handle,
 			u32 nesting_level, void *context, void **return_value);
 
+static acpi_status
+acpi_ns_find_ini_methods(acpi_handle obj_handle,
+			 u32 nesting_level, void *context, void **return_value);
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_initialize_objects
@@ -76,7 +80,7 @@
 	acpi_status status;
 	struct acpi_init_walk_info info;
 
-	ACPI_FUNCTION_TRACE("ns_initialize_objects");
+	ACPI_FUNCTION_TRACE(ns_initialize_objects);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 			  "**** Starting initialization of namespace objects ****\n"));
@@ -93,7 +97,7 @@
 				     ACPI_UINT32_MAX, acpi_ns_init_one_object,
 				     &info, NULL);
 	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
+		ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace"));
 	}
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
@@ -133,7 +137,7 @@
 	acpi_status status;
 	struct acpi_device_walk_info info;
 
-	ACPI_FUNCTION_TRACE("ns_initialize_devices");
+	ACPI_FUNCTION_TRACE(ns_initialize_devices);
 
 	/* Init counters */
 
@@ -142,30 +146,46 @@
 	info.num_INI = 0;
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
-			      "Executing all Device _STA and_INI methods:"));
+			      "Initializing Device/Processor/Thermal objects by executing _INI methods:"));
 
-	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	/* Walk namespace for all objects */
+	/* Tree analysis: find all subtrees that contain _INI methods */
 
 	status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
-					ACPI_UINT32_MAX, TRUE,
+					ACPI_UINT32_MAX, FALSE,
+					acpi_ns_find_ini_methods, &info, NULL);
+	if (ACPI_FAILURE(status)) {
+		goto error_exit;
+	}
+
+	/* Allocate the evaluation information block */
+
+	info.evaluate_info =
+	    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+	if (!info.evaluate_info) {
+		status = AE_NO_MEMORY;
+		goto error_exit;
+	}
+
+	/* Walk namespace to execute all _INIs on present devices */
+
+	status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
+					ACPI_UINT32_MAX, FALSE,
 					acpi_ns_init_one_device, &info, NULL);
 
-	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-
+	ACPI_FREE(info.evaluate_info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "During walk_namespace"));
+		goto error_exit;
 	}
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
-			      "\n%hd Devices found - executed %hd _STA, %hd _INI methods\n",
-			      info.device_count, info.num_STA, info.num_INI));
+			      "\nExecuted %hd _INI methods requiring %hd _STA executions (examined %hd objects)\n",
+			      info.num_INI, info.num_STA, info.device_count));
 
 	return_ACPI_STATUS(status);
+
+      error_exit:
+	ACPI_EXCEPTION((AE_INFO, status, "During device initialization"));
+	return_ACPI_STATUS(status);
 }
 
 /*******************************************************************************
@@ -200,7 +220,7 @@
 	    (struct acpi_namespace_node *)obj_handle;
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_NAME("ns_init_one_object");
+	ACPI_FUNCTION_NAME(ns_init_one_object);
 
 	info->object_count++;
 
@@ -311,6 +331,72 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ns_find_ini_methods
+ *
+ * PARAMETERS:  acpi_walk_callback
+ *
+ * RETURN:      acpi_status
+ *
+ * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
+ *              device/processor/thermal objects, and marks the entire subtree
+ *              with a SUBTREE_HAS_INI flag. This flag is used during the
+ *              subsequent device initialization walk to avoid entire subtrees
+ *              that do not contain an _INI.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_find_ini_methods(acpi_handle obj_handle,
+			 u32 nesting_level, void *context, void **return_value)
+{
+	struct acpi_device_walk_info *info =
+	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
+	struct acpi_namespace_node *node;
+	struct acpi_namespace_node *parent_node;
+
+	/* Keep count of device/processor/thermal objects */
+
+	node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
+	if ((node->type == ACPI_TYPE_DEVICE) ||
+	    (node->type == ACPI_TYPE_PROCESSOR) ||
+	    (node->type == ACPI_TYPE_THERMAL)) {
+		info->device_count++;
+		return (AE_OK);
+	}
+
+	/* We are only looking for methods named _INI */
+
+	if (!ACPI_COMPARE_NAME(node->name.ascii, METHOD_NAME__INI)) {
+		return (AE_OK);
+	}
+
+	/*
+	 * The only _INI methods that we care about are those that are
+	 * present under Device, Processor, and Thermal objects.
+	 */
+	parent_node = acpi_ns_get_parent_node(node);
+	switch (parent_node->type) {
+	case ACPI_TYPE_DEVICE:
+	case ACPI_TYPE_PROCESSOR:
+	case ACPI_TYPE_THERMAL:
+
+		/* Mark parent and bubble up the INI present flag to the root */
+
+		while (parent_node) {
+			parent_node->flags |= ANOBJ_SUBTREE_HAS_INI;
+			parent_node = acpi_ns_get_parent_node(parent_node);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return (AE_OK);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ns_init_one_device
  *
  * PARAMETERS:  acpi_walk_callback
@@ -327,119 +413,165 @@
 acpi_ns_init_one_device(acpi_handle obj_handle,
 			u32 nesting_level, void *context, void **return_value)
 {
-	struct acpi_device_walk_info *info =
-	    (struct acpi_device_walk_info *)context;
-	struct acpi_parameter_info pinfo;
+	struct acpi_device_walk_info *walk_info =
+	    ACPI_CAST_PTR(struct acpi_device_walk_info, context);
+	struct acpi_evaluate_info *info = walk_info->evaluate_info;
 	u32 flags;
 	acpi_status status;
-	struct acpi_namespace_node *ini_node;
 	struct acpi_namespace_node *device_node;
 
-	ACPI_FUNCTION_TRACE("ns_init_one_device");
+	ACPI_FUNCTION_TRACE(ns_init_one_device);
 
-	device_node = acpi_ns_map_handle_to_node(obj_handle);
-	if (!device_node) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
+	/* We are interested in Devices, Processors and thermal_zones only */
 
-	/*
-	 * We will run _STA/_INI on Devices, Processors and thermal_zones only
-	 */
+	device_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
 	if ((device_node->type != ACPI_TYPE_DEVICE) &&
 	    (device_node->type != ACPI_TYPE_PROCESSOR) &&
 	    (device_node->type != ACPI_TYPE_THERMAL)) {
 		return_ACPI_STATUS(AE_OK);
 	}
 
-	if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
-	    (!(acpi_dbg_level & ACPI_LV_INFO))) {
-		ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
-	}
-
-	info->device_count++;
-
 	/*
-	 * Check if the _INI method exists for this device -
-	 * if _INI does not exist, there is no need to run _STA
-	 * No _INI means device requires no initialization
+	 * Because of an earlier namespace analysis, all subtrees that contain an
+	 * _INI method are tagged.
+	 *
+	 * If this device subtree does not contain any _INI methods, we
+	 * can exit now and stop traversing this entire subtree.
 	 */
-	status = acpi_ns_search_node(*ACPI_CAST_PTR(u32, METHOD_NAME__INI),
-				     device_node, ACPI_TYPE_METHOD, &ini_node);
-	if (ACPI_FAILURE(status)) {
-		/* No _INI method found - move on to next device */
-
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	/*
-	 * Run _STA to determine if we can run _INI on the device -
-	 * the device must be present before _INI can be run.
-	 * However, _STA is not required - assume device present if no _STA
-	 */
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
-						      device_node,
-						      METHOD_NAME__STA));
-
-	pinfo.node = device_node;
-	pinfo.parameters = NULL;
-	pinfo.parameter_type = ACPI_PARAM_ARGS;
-
-	status = acpi_ut_execute_STA(pinfo.node, &flags);
-	if (ACPI_FAILURE(status)) {
-		/* Ignore error and move on to next device */
-
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	if (flags != ACPI_UINT32_MAX) {
-		info->num_STA++;
-	}
-
-	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
-		/* Don't look at children of a not present device */
-
+	if (!(device_node->flags & ANOBJ_SUBTREE_HAS_INI)) {
 		return_ACPI_STATUS(AE_CTRL_DEPTH);
 	}
 
 	/*
-	 * The device is present and _INI exists. Run the _INI method.
-	 * (We already have the _INI node from above)
+	 * Run _STA to determine if this device is present and functioning. We
+	 * must know this information for two important reasons (from ACPI spec):
+	 *
+	 * 1) We can only run _INI if the device is present.
+	 * 2) We must abort the device tree walk on this subtree if the device is
+	 *    not present and is not functional (we will not examine the children)
+	 *
+	 * The _STA method is not required to be present under the device, we
+	 * assume the device is present if _STA does not exist.
 	 */
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_METHOD,
-						      pinfo.node,
-						      METHOD_NAME__INI));
+	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__STA));
 
-	pinfo.node = ini_node;
-	status = acpi_ns_evaluate_by_handle(&pinfo);
+	status = acpi_ut_execute_STA(device_node, &flags);
 	if (ACPI_FAILURE(status)) {
+
 		/* Ignore error and move on to next device */
 
-#ifdef ACPI_DEBUG_OUTPUT
-		char *scope_name = acpi_ns_get_external_pathname(ini_node);
+		return_ACPI_STATUS(AE_OK);
+	}
 
-		ACPI_WARNING((AE_INFO, "%s._INI failed: %s",
-			      scope_name, acpi_format_exception(status)));
+	/*
+	 * Flags == -1 means that _STA was not found. In this case, we assume that
+	 * the device is both present and functional.
+	 *
+	 * From the ACPI spec, description of _STA:
+	 *
+	 * "If a device object (including the processor object) does not have an
+	 * _STA object, then OSPM assumes that all of the above bits are set (in
+	 * other words, the device is present, ..., and functioning)"
+	 */
+	if (flags != ACPI_UINT32_MAX) {
+		walk_info->num_STA++;
+	}
 
-		ACPI_MEM_FREE(scope_name);
-#endif
-	} else {
-		/* Delete any return object (especially if implicit_return is enabled) */
+	/*
+	 * Examine the PRESENT and FUNCTIONING status bits
+	 *
+	 * Note: ACPI spec does not seem to specify behavior for the present but
+	 * not functioning case, so we assume functioning if present.
+	 */
+	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
 
-		if (pinfo.return_object) {
-			acpi_ut_remove_reference(pinfo.return_object);
+		/* Device is not present, we must examine the Functioning bit */
+
+		if (flags & ACPI_STA_DEVICE_FUNCTIONING) {
+			/*
+			 * Device is not present but is "functioning". In this case,
+			 * we will not run _INI, but we continue to examine the children
+			 * of this device.
+			 *
+			 * From the ACPI spec, description of _STA: (Note - no mention
+			 * of whether to run _INI or not on the device in question)
+			 *
+			 * "_STA may return bit 0 clear (not present) with bit 3 set
+			 * (device is functional). This case is used to indicate a valid
+			 * device for which no device driver should be loaded (for example,
+			 * a bridge device.) Children of this device may be present and
+			 * valid. OSPM should continue enumeration below a device whose
+			 * _STA returns this bit combination"
+			 */
+			return_ACPI_STATUS(AE_OK);
+		} else {
+			/*
+			 * Device is not present and is not functioning. We must abort the
+			 * walk of this subtree immediately -- don't look at the children
+			 * of such a device.
+			 *
+			 * From the ACPI spec, description of _INI:
+			 *
+			 * "If the _STA method indicates that the device is not present,
+			 * OSPM will not run the _INI and will not examine the children
+			 * of the device for _INI methods"
+			 */
+			return_ACPI_STATUS(AE_CTRL_DEPTH);
 		}
-
-		/* Count of successful INIs */
-
-		info->num_INI++;
 	}
 
+	/*
+	 * The device is present or is assumed present if no _STA exists.
+	 * Run the _INI if it exists (not required to exist)
+	 *
+	 * Note: We know there is an _INI within this subtree, but it may not be
+	 * under this particular device, it may be lower in the branch.
+	 */
+	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+			(ACPI_TYPE_METHOD, device_node, METHOD_NAME__INI));
+
+	info->prefix_node = device_node;
+	info->pathname = METHOD_NAME__INI;
+	info->parameters = NULL;
+	info->parameter_type = ACPI_PARAM_ARGS;
+	info->flags = ACPI_IGNORE_RETURN_VALUE;
+
+	status = acpi_ns_evaluate(info);
+	if (ACPI_SUCCESS(status)) {
+		walk_info->num_INI++;
+
+		if ((acpi_dbg_level <= ACPI_LV_ALL_EXCEPTIONS) &&
+		    (!(acpi_dbg_level & ACPI_LV_INFO))) {
+			ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "."));
+		}
+	}
+#ifdef ACPI_DEBUG_OUTPUT
+	else if (status != AE_NOT_FOUND) {
+
+		/* Ignore error and move on to next device */
+
+		char *scope_name =
+		    acpi_ns_get_external_pathname(info->resolved_node);
+
+		ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
+				scope_name));
+		ACPI_FREE(scope_name);
+	}
+#endif
+
+	/* Ignore errors from above */
+
+	status = AE_OK;
+
+	/*
+	 * The _INI method has been run if present; call the Global Initialization
+	 * Handler for this device.
+	 */
 	if (acpi_gbl_init_handler) {
-		/* External initialization handler is present, call it */
-
 		status =
-		    acpi_gbl_init_handler(pinfo.node, ACPI_INIT_DEVICE_INI);
+		    acpi_gbl_init_handler(device_node, ACPI_INIT_DEVICE_INI);
 	}
 
-	return_ACPI_STATUS(AE_OK);
+	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c
index 4e0b052..fe75d88 100644
--- a/drivers/acpi/namespace/nsload.c
+++ b/drivers/acpi/namespace/nsload.c
@@ -77,13 +77,14 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ns_load_table");
+	ACPI_FUNCTION_TRACE(ns_load_table);
 
 	/* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
 
 	if (!
 	    (acpi_gbl_table_data[table_desc->type].
 	     flags & ACPI_TABLE_EXECUTABLE)) {
+
 		/* Just ignore this table */
 
 		return_ACPI_STATUS(AE_OK);
@@ -168,7 +169,7 @@
 	acpi_status status;
 	struct acpi_table_desc *table_desc;
 
-	ACPI_FUNCTION_TRACE("ns_load_table_by_type");
+	ACPI_FUNCTION_TRACE(ns_load_table_by_type);
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 	if (ACPI_FAILURE(status)) {
@@ -180,11 +181,11 @@
 	 * DSDT (one), SSDT/PSDT (multiple)
 	 */
 	switch (table_type) {
-	case ACPI_TABLE_DSDT:
+	case ACPI_TABLE_ID_DSDT:
 
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace load: DSDT\n"));
 
-		table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
+		table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_DSDT].next;
 
 		/* If table already loaded into namespace, just return */
 
@@ -200,8 +201,8 @@
 		}
 		break;
 
-	case ACPI_TABLE_SSDT:
-	case ACPI_TABLE_PSDT:
+	case ACPI_TABLE_ID_SSDT:
+	case ACPI_TABLE_ID_PSDT:
 
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 				  "Namespace load: %d SSDT or PSDTs\n",
@@ -258,7 +259,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_load_name_space");
+	ACPI_FUNCTION_TRACE(acpi_load_name_space);
 
 	/* There must be at least a DSDT installed */
 
@@ -271,15 +272,15 @@
 	 * Load the namespace.  The DSDT is required,
 	 * but the SSDT and PSDT tables are optional.
 	 */
-	status = acpi_ns_load_table_by_type(ACPI_TABLE_DSDT);
+	status = acpi_ns_load_table_by_type(ACPI_TABLE_ID_DSDT);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
 	/* Ignore exceptions from these */
 
-	(void)acpi_ns_load_table_by_type(ACPI_TABLE_SSDT);
-	(void)acpi_ns_load_table_by_type(ACPI_TABLE_PSDT);
+	(void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_SSDT);
+	(void)acpi_ns_load_table_by_type(ACPI_TABLE_ID_PSDT);
 
 	ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
 			      "ACPI Namespace successfully loaded at root %p\n",
@@ -314,7 +315,7 @@
 	acpi_handle dummy;
 	u32 level;
 
-	ACPI_FUNCTION_TRACE("ns_delete_subtree");
+	ACPI_FUNCTION_TRACE(ns_delete_subtree);
 
 	parent_handle = start_handle;
 	child_handle = NULL;
@@ -325,6 +326,7 @@
 	 * to where we started.
 	 */
 	while (level > 0) {
+
 		/* Attempt to get the next object in this scope */
 
 		status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle,
@@ -335,6 +337,7 @@
 		/* Did we get a new object? */
 
 		if (ACPI_SUCCESS(status)) {
+
 			/* Check if this object has any children */
 
 			if (ACPI_SUCCESS
@@ -392,7 +395,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ns_unload_name_space");
+	ACPI_FUNCTION_TRACE(ns_unload_name_space);
 
 	/* Parameter validation */
 
diff --git a/drivers/acpi/namespace/nsnames.c b/drivers/acpi/namespace/nsnames.c
index 639f653..97b8332 100644
--- a/drivers/acpi/namespace/nsnames.c
+++ b/drivers/acpi/namespace/nsnames.c
@@ -48,11 +48,6 @@
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsnames")
 
-/* Local prototypes */
-static void
-acpi_ns_build_external_path(struct acpi_namespace_node *node,
-			    acpi_size size, char *name_buffer);
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_build_external_path
@@ -67,8 +62,7 @@
  * DESCRIPTION: Generate a full pathaname
  *
  ******************************************************************************/
-
-static void
+void
 acpi_ns_build_external_path(struct acpi_namespace_node *node,
 			    acpi_size size, char *name_buffer)
 {
@@ -138,7 +132,7 @@
 	char *name_buffer;
 	acpi_size size;
 
-	ACPI_FUNCTION_TRACE_PTR("ns_get_external_pathname", node);
+	ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
 
 	/* Calculate required buffer size based on depth below root */
 
@@ -146,7 +140,7 @@
 
 	/* Allocate a buffer to be returned to caller */
 
-	name_buffer = ACPI_MEM_CALLOCATE(size);
+	name_buffer = ACPI_ALLOCATE_ZEROED(size);
 	if (!name_buffer) {
 		ACPI_ERROR((AE_INFO, "Allocation failure"));
 		return_PTR(NULL);
@@ -219,7 +213,7 @@
 	struct acpi_namespace_node *node;
 	acpi_size required_size;
 
-	ACPI_FUNCTION_TRACE_PTR("ns_handle_to_pathname", target_handle);
+	ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
 
 	node = acpi_ns_map_handle_to_node(target_handle);
 	if (!node) {
diff --git a/drivers/acpi/namespace/nsobject.c b/drivers/acpi/namespace/nsobject.c
index 10ae629..aabe879 100644
--- a/drivers/acpi/namespace/nsobject.c
+++ b/drivers/acpi/namespace/nsobject.c
@@ -76,19 +76,21 @@
 	union acpi_operand_object *last_obj_desc;
 	acpi_object_type object_type = ACPI_TYPE_ANY;
 
-	ACPI_FUNCTION_TRACE("ns_attach_object");
+	ACPI_FUNCTION_TRACE(ns_attach_object);
 
 	/*
 	 * Parameter validation
 	 */
 	if (!node) {
+
 		/* Invalid handle */
 
-		ACPI_ERROR((AE_INFO, "Null named_obj handle"));
+		ACPI_ERROR((AE_INFO, "Null NamedObj handle"));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	if (!object && (ACPI_TYPE_ANY != type)) {
+
 		/* Null object */
 
 		ACPI_ERROR((AE_INFO,
@@ -97,6 +99,7 @@
 	}
 
 	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
+
 		/* Not a name handle */
 
 		ACPI_ERROR((AE_INFO, "Invalid handle %p [%s]",
@@ -108,7 +111,7 @@
 
 	if (node->object == object) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "Obj %p already installed in name_obj %p\n",
+				  "Obj %p already installed in NameObj %p\n",
 				  object, node));
 
 		return_ACPI_STATUS(AE_OK);
@@ -201,7 +204,7 @@
 {
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_TRACE("ns_detach_object");
+	ACPI_FUNCTION_TRACE(ns_detach_object);
 
 	obj_desc = node->object;
 
@@ -252,7 +255,7 @@
 						       acpi_namespace_node
 						       *node)
 {
-	ACPI_FUNCTION_TRACE_PTR("ns_get_attached_object", node);
+	ACPI_FUNCTION_TRACE_PTR(ns_get_attached_object, node);
 
 	if (!node) {
 		ACPI_WARNING((AE_INFO, "Null Node ptr"));
@@ -287,7 +290,7 @@
 							acpi_operand_object
 							*obj_desc)
 {
-	ACPI_FUNCTION_TRACE_PTR("ns_get_secondary_object", obj_desc);
+	ACPI_FUNCTION_TRACE_PTR(ns_get_secondary_object, obj_desc);
 
 	if ((!obj_desc) ||
 	    (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_LOCAL_DATA) ||
diff --git a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c
index 232be43..155505a 100644
--- a/drivers/acpi/namespace/nsparse.c
+++ b/drivers/acpi/namespace/nsparse.c
@@ -62,13 +62,13 @@
  *
  ******************************************************************************/
 acpi_status
-acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc * table_desc)
+acpi_ns_one_complete_parse(u8 pass_number, struct acpi_table_desc *table_desc)
 {
 	union acpi_parse_object *parse_root;
 	acpi_status status;
 	struct acpi_walk_state *walk_state;
 
-	ACPI_FUNCTION_TRACE("ns_one_complete_parse");
+	ACPI_FUNCTION_TRACE(ns_one_complete_parse);
 
 	/* Create and init a Root Node */
 
@@ -124,7 +124,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ns_parse_table");
+	ACPI_FUNCTION_TRACE(ns_parse_table);
 
 	/*
 	 * AML Parse, pass 1
diff --git a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c
index d64b789..500e2bb 100644
--- a/drivers/acpi/namespace/nssearch.c
+++ b/drivers/acpi/namespace/nssearch.c
@@ -56,16 +56,16 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_search_node
+ * FUNCTION:    acpi_ns_search_one_scope
  *
  * PARAMETERS:  target_name     - Ascii ACPI name to search for
- *              Node            - Starting node where search will begin
+ *              parent_node     - Starting node where search will begin
  *              Type            - Object type to match
  *              return_node     - Where the matched Named obj is returned
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Search a single level of the namespace.  Performs a
+ * DESCRIPTION: Search a single level of the namespace. Performs a
  *              simple search of the specified level, and does not add
  *              entries or search parents.
  *
@@ -75,35 +75,40 @@
  *
  *      All namespace searching is linear in this implementation, but
  *      could be easily modified to support any improved search
- *      algorithm.  However, the linear search was chosen for simplicity
+ *      algorithm. However, the linear search was chosen for simplicity
  *      and because the trees are small and the other interpreter
  *      execution overhead is relatively high.
  *
+ *      Note: CPU execution analysis has shown that the AML interpreter spends
+ *      a very small percentage of its time searching the namespace. Therefore,
+ *      the linear search seems to be sufficient, as there would seem to be
+ *      little value in improving the search.
+ *
  ******************************************************************************/
 
 acpi_status
-acpi_ns_search_node(u32 target_name,
-		    struct acpi_namespace_node *node,
-		    acpi_object_type type,
-		    struct acpi_namespace_node **return_node)
+acpi_ns_search_one_scope(u32 target_name,
+			 struct acpi_namespace_node *parent_node,
+			 acpi_object_type type,
+			 struct acpi_namespace_node **return_node)
 {
-	struct acpi_namespace_node *next_node;
+	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("ns_search_node");
+	ACPI_FUNCTION_TRACE(ns_search_one_scope);
 
 #ifdef ACPI_DEBUG_OUTPUT
 	if (ACPI_LV_NAMES & acpi_dbg_level) {
 		char *scope_name;
 
-		scope_name = acpi_ns_get_external_pathname(node);
+		scope_name = acpi_ns_get_external_pathname(parent_node);
 		if (scope_name) {
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 					  "Searching %s (%p) For [%4.4s] (%s)\n",
-					  scope_name, node, ACPI_CAST_PTR(char,
-									  &target_name),
+					  scope_name, parent_node,
+					  ACPI_CAST_PTR(char, &target_name),
 					  acpi_ut_get_type_name(type)));
 
-			ACPI_MEM_FREE(scope_name);
+			ACPI_FREE(scope_name);
 		}
 	}
 #endif
@@ -112,32 +117,33 @@
 	 * Search for name at this namespace level, which is to say that we
 	 * must search for the name among the children of this object
 	 */
-	next_node = node->child;
-	while (next_node) {
+	node = parent_node->child;
+	while (node) {
+
 		/* Check for match against the name */
 
-		if (next_node->name.integer == target_name) {
+		if (node->name.integer == target_name) {
+
 			/* Resolve a control method alias if any */
 
-			if (acpi_ns_get_type(next_node) ==
+			if (acpi_ns_get_type(node) ==
 			    ACPI_TYPE_LOCAL_METHOD_ALIAS) {
-				next_node =
+				node =
 				    ACPI_CAST_PTR(struct acpi_namespace_node,
-						  next_node->object);
+						  node->object);
 			}
 
-			/*
-			 * Found matching entry.
-			 */
+			/* Found matching entry */
+
 			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 					  "Name [%4.4s] (%s) %p found in scope [%4.4s] %p\n",
 					  ACPI_CAST_PTR(char, &target_name),
-					  acpi_ut_get_type_name(next_node->
-								type),
-					  next_node,
-					  acpi_ut_get_node_name(node), node));
+					  acpi_ut_get_type_name(node->type),
+					  node,
+					  acpi_ut_get_node_name(parent_node),
+					  parent_node));
 
-			*return_node = next_node;
+			*return_node = node;
 			return_ACPI_STATUS(AE_OK);
 		}
 
@@ -145,7 +151,8 @@
 		 * The last entry in the list points back to the parent,
 		 * so a flag is used to indicate the end-of-list
 		 */
-		if (next_node->flags & ANOBJ_END_OF_PEER_LIST) {
+		if (node->flags & ANOBJ_END_OF_PEER_LIST) {
+
 			/* Searched entire list, we are done */
 
 			break;
@@ -153,7 +160,7 @@
 
 		/* Didn't match name, move on to the next peer object */
 
-		next_node = next_node->peer;
+		node = node->peer;
 	}
 
 	/* Searched entire namespace level, not found */
@@ -162,7 +169,8 @@
 			  "Name [%4.4s] (%s) not found in search in scope [%4.4s] %p first child %p\n",
 			  ACPI_CAST_PTR(char, &target_name),
 			  acpi_ut_get_type_name(type),
-			  acpi_ut_get_node_name(node), node, node->child));
+			  acpi_ut_get_node_name(parent_node), parent_node,
+			  parent_node->child));
 
 	return_ACPI_STATUS(AE_NOT_FOUND);
 }
@@ -179,14 +187,14 @@
  * RETURN:      Status
  *
  * DESCRIPTION: Called when a name has not been found in the current namespace
- *              level.  Before adding it or giving up, ACPI scope rules require
+ *              level. Before adding it or giving up, ACPI scope rules require
  *              searching enclosing scopes in cases identified by acpi_ns_local().
  *
  *              "A name is located by finding the matching name in the current
  *              name space, and then in the parent name space. If the parent
  *              name space does not contain the name, the search continues
  *              recursively until either the name is found or the name space
- *              does not have a parent (the root of the name space).  This
+ *              does not have a parent (the root of the name space). This
  *              indicates that the name is not found" (From ACPI Specification,
  *              section 5.3)
  *
@@ -201,7 +209,7 @@
 	acpi_status status;
 	struct acpi_namespace_node *parent_node;
 
-	ACPI_FUNCTION_TRACE("ns_search_parent_tree");
+	ACPI_FUNCTION_TRACE(ns_search_parent_tree);
 
 	parent_node = acpi_ns_get_parent_node(node);
 
@@ -235,20 +243,19 @@
 	 */
 	while (parent_node) {
 		/*
-		 * Search parent scope.  Use TYPE_ANY because we don't care about the
+		 * Search parent scope. Use TYPE_ANY because we don't care about the
 		 * object type at this point, we only care about the existence of
-		 * the actual name we are searching for.  Typechecking comes later.
+		 * the actual name we are searching for. Typechecking comes later.
 		 */
-		status = acpi_ns_search_node(target_name, parent_node,
+		status =
+		    acpi_ns_search_one_scope(target_name, parent_node,
 					     ACPI_TYPE_ANY, return_node);
 		if (ACPI_SUCCESS(status)) {
 			return_ACPI_STATUS(status);
 		}
 
-		/*
-		 * Not found here, go up another level
-		 * (until we reach the root)
-		 */
+		/* Not found here, go up another level (until we reach the root) */
+
 		parent_node = acpi_ns_get_parent_node(parent_node);
 	}
 
@@ -273,7 +280,7 @@
  * RETURN:      Status
  *
  * DESCRIPTION: Search for a name segment in a single namespace level,
- *              optionally adding it if it is not found.  If the passed
+ *              optionally adding it if it is not found. If the passed
  *              Type is not Any and the type previously stored in the
  *              entry was Any (i.e. unknown), update the stored type.
  *
@@ -293,29 +300,46 @@
 	acpi_status status;
 	struct acpi_namespace_node *new_node;
 
-	ACPI_FUNCTION_TRACE("ns_search_and_enter");
+	ACPI_FUNCTION_TRACE(ns_search_and_enter);
 
 	/* Parameter validation */
 
 	if (!node || !target_name || !return_node) {
 		ACPI_ERROR((AE_INFO,
-			    "Null param: Node %p Name %X return_node %p",
+			    "Null parameter: Node %p Name %X ReturnNode %p",
 			    node, target_name, return_node));
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	/* Name must consist of printable characters */
-
+	/*
+	 * Name must consist of valid ACPI characters. We will repair the name if
+	 * necessary because we don't want to abort because of this, but we want
+	 * all namespace names to be printable. A warning message is appropriate.
+	 *
+	 * This issue came up because there are in fact machines that exhibit
+	 * this problem, and we want to be able to enable ACPI support for them,
+	 * even though there are a few bad names.
+	 */
 	if (!acpi_ut_valid_acpi_name(target_name)) {
-		ACPI_ERROR((AE_INFO, "Bad character in ACPI Name: %X",
-			    target_name));
-		return_ACPI_STATUS(AE_BAD_CHARACTER);
+		target_name = acpi_ut_repair_name(target_name);
+
+		/* Report warning only if in strict mode or debug mode */
+
+		if (!acpi_gbl_enable_interpreter_slack) {
+			ACPI_WARNING((AE_INFO,
+				      "Found bad character(s) in name, repaired: [%4.4s]\n",
+				      ACPI_CAST_PTR(char, &target_name)));
+		} else {
+			ACPI_DEBUG_PRINT((ACPI_DB_WARN,
+					  "Found bad character(s) in name, repaired: [%4.4s]\n",
+					  ACPI_CAST_PTR(char, &target_name)));
+		}
 	}
 
 	/* Try to find the name in the namespace level specified by the caller */
 
 	*return_node = ACPI_ENTRY_NOT_FOUND;
-	status = acpi_ns_search_node(target_name, node, type, return_node);
+	status = acpi_ns_search_one_scope(target_name, node, type, return_node);
 	if (status != AE_NOT_FOUND) {
 		/*
 		 * If we found it AND the request specifies that a find is an error,
@@ -325,18 +349,16 @@
 			status = AE_ALREADY_EXISTS;
 		}
 
-		/*
-		 * Either found it or there was an error
-		 * -- finished either way
-		 */
+		/* Either found it or there was an error: finished either way */
+
 		return_ACPI_STATUS(status);
 	}
 
 	/*
-	 * The name was not found.  If we are NOT performing the first pass
+	 * The name was not found. If we are NOT performing the first pass
 	 * (name entry) of loading the namespace, search the parent tree (all the
 	 * way to the root if necessary.) We don't want to perform the parent
-	 * search when the namespace is actually being loaded.  We want to perform
+	 * search when the namespace is actually being loaded. We want to perform
 	 * the search when namespace references are being resolved (load pass 2)
 	 * and during the execution phase.
 	 */
@@ -354,9 +376,8 @@
 		}
 	}
 
-	/*
-	 * In execute mode, just search, never add names.  Exit now.
-	 */
+	/* In execute mode, just search, never add names. Exit now */
+
 	if (interpreter_mode == ACPI_IMODE_EXECUTE) {
 		ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 				  "%4.4s Not found in %p [Not adding]\n",
@@ -371,11 +392,18 @@
 	if (!new_node) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
+#ifdef ACPI_ASL_COMPILER
+	/*
+	 * Node is an object defined by an External() statement
+	 */
+	if (flags & ACPI_NS_EXTERNAL) {
+		new_node->flags |= ANOBJ_IS_EXTERNAL;
+	}
+#endif
 
 	/* Install the new object into the parent's list of children */
 
 	acpi_ns_install_node(walk_state, node, new_node, type);
 	*return_node = new_node;
-
 	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c
index 3e7cad5..aa4e799 100644
--- a/drivers/acpi/namespace/nsutils.c
+++ b/drivers/acpi/namespace/nsutils.c
@@ -78,15 +78,17 @@
 		     char *internal_name, acpi_status lookup_status)
 {
 	acpi_status status;
+	u32 bad_name;
 	char *name = NULL;
 
-	acpi_ut_report_error(module_name, line_number);
+	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
 
 	if (lookup_status == AE_BAD_CHARACTER) {
+
 		/* There is a non-ascii character in the name */
 
-		acpi_os_printf("[0x%4.4X] (NON-ASCII)",
-			       *(ACPI_CAST_PTR(u32, internal_name)));
+		ACPI_MOVE_32_TO_32(&bad_name, internal_name);
+		acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
 	} else {
 		/* Convert path to external format */
 
@@ -102,7 +104,7 @@
 		}
 
 		if (name) {
-			ACPI_MEM_FREE(name);
+			ACPI_FREE(name);
 		}
 	}
 
@@ -137,11 +139,12 @@
 	acpi_status status;
 	struct acpi_namespace_node *node = prefix_node;
 
-	acpi_ut_report_error(module_name, line_number);
+	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
 
 	if (path) {
-		status = acpi_ns_get_node_by_path(path, prefix_node,
-						  ACPI_NS_NO_UPSEARCH, &node);
+		status =
+		    acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
+				     &node);
 		if (ACPI_FAILURE(status)) {
 			acpi_os_printf("[Could not get node by pathname]");
 		}
@@ -185,7 +188,7 @@
 		}
 
 		acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node);
-		ACPI_MEM_FREE(buffer.pointer);
+		ACPI_FREE(buffer.pointer);
 	}
 }
 
@@ -239,7 +242,7 @@
 
 acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
 {
-	ACPI_FUNCTION_TRACE("ns_get_type");
+	ACPI_FUNCTION_TRACE(ns_get_type);
 
 	if (!node) {
 		ACPI_WARNING((AE_INFO, "Null Node parameter"));
@@ -264,9 +267,10 @@
 
 u32 acpi_ns_local(acpi_object_type type)
 {
-	ACPI_FUNCTION_TRACE("ns_local");
+	ACPI_FUNCTION_TRACE(ns_local);
 
 	if (!acpi_ut_valid_object_type(type)) {
+
 		/* Type code out of range  */
 
 		ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
@@ -363,7 +367,7 @@
 	char *result = NULL;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE("ns_build_internal_name");
+	ACPI_FUNCTION_TRACE(ns_build_internal_name);
 
 	/* Setup the correct prefixes, counts, and pointers */
 
@@ -411,6 +415,7 @@
 		for (i = 0; i < ACPI_NAME_SIZE; i++) {
 			if (acpi_ns_valid_path_separator(*external_name) ||
 			    (*external_name == 0)) {
+
 				/* Pad the segment with underscore(s) if segment is short */
 
 				result[i] = '_';
@@ -473,7 +478,7 @@
 	struct acpi_namestring_info info;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ns_internalize_name");
+	ACPI_FUNCTION_TRACE(ns_internalize_name);
 
 	if ((!external_name) || (*external_name == 0) || (!converted_name)) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -486,7 +491,7 @@
 
 	/* We need a segment to store the internal  name */
 
-	internal_name = ACPI_MEM_CALLOCATE(info.length);
+	internal_name = ACPI_ALLOCATE_ZEROED(info.length);
 	if (!internal_name) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -496,7 +501,7 @@
 	info.internal_name = internal_name;
 	status = acpi_ns_build_internal_name(&info);
 	if (ACPI_FAILURE(status)) {
-		ACPI_MEM_FREE(internal_name);
+		ACPI_FREE(internal_name);
 		return_ACPI_STATUS(status);
 	}
 
@@ -533,7 +538,7 @@
 	acpi_native_uint i = 0;
 	acpi_native_uint j = 0;
 
-	ACPI_FUNCTION_TRACE("ns_externalize_name");
+	ACPI_FUNCTION_TRACE(ns_externalize_name);
 
 	if (!internal_name_length || !internal_name || !converted_name) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -628,7 +633,7 @@
 	/*
 	 * Build converted_name
 	 */
-	*converted_name = ACPI_MEM_CALLOCATE(required_length);
+	*converted_name = ACPI_ALLOCATE_ZEROED(required_length);
 	if (!(*converted_name)) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -681,13 +686,9 @@
 	ACPI_FUNCTION_ENTRY();
 
 	/*
-	 * Simple implementation.
+	 * Simple implementation
 	 */
-	if (!handle) {
-		return (NULL);
-	}
-
-	if (handle == ACPI_ROOT_OBJECT) {
+	if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
 		return (acpi_gbl_root_node);
 	}
 
@@ -697,7 +698,7 @@
 		return (NULL);
 	}
 
-	return ((struct acpi_namespace_node *)handle);
+	return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
 }
 
 /*******************************************************************************
@@ -752,7 +753,7 @@
 {
 	union acpi_operand_object *obj_desc;
 
-	ACPI_FUNCTION_TRACE("ns_terminate");
+	ACPI_FUNCTION_TRACE(ns_terminate);
 
 	/*
 	 * 1) Free the entire namespace -- all nodes and objects
@@ -792,9 +793,10 @@
 
 u32 acpi_ns_opens_scope(acpi_object_type type)
 {
-	ACPI_FUNCTION_TRACE_STR("ns_opens_scope", acpi_ut_get_type_name(type));
+	ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type));
 
 	if (!acpi_ut_valid_object_type(type)) {
+
 		/* type code out of range  */
 
 		ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
@@ -806,12 +808,12 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_get_node_by_path
+ * FUNCTION:    acpi_ns_get_node
  *
  * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
  *                            \ (backslash) and ^ (carat) prefixes, and the
  *                            . (period) to separate segments are supported.
- *              start_node  - Root of subtree to be searched, or NS_ALL for the
+ *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
  *                            root of the name space.  If Name is fully
  *                            qualified (first s8 is '\'), the passed value
  *                            of Scope will not be accessed.
@@ -827,23 +829,29 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ns_get_node_by_path(char *pathname,
-			 struct acpi_namespace_node *start_node,
-			 u32 flags, struct acpi_namespace_node **return_node)
+acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
+		 char *pathname,
+		 u32 flags, struct acpi_namespace_node **return_node)
 {
 	union acpi_generic_state scope_info;
 	acpi_status status;
-	char *internal_path = NULL;
+	char *internal_path;
 
-	ACPI_FUNCTION_TRACE_PTR("ns_get_node_by_path", pathname);
+	ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname);
 
-	if (pathname) {
-		/* Convert path to internal representation */
-
-		status = acpi_ns_internalize_name(pathname, &internal_path);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
+	if (!pathname) {
+		*return_node = prefix_node;
+		if (!prefix_node) {
+			*return_node = acpi_gbl_root_node;
 		}
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	/* Convert path to internal representation */
+
+	status = acpi_ns_internalize_name(pathname, &internal_path);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
 	}
 
 	/* Must lock namespace during lookup */
@@ -855,26 +863,23 @@
 
 	/* Setup lookup scope (search starting point) */
 
-	scope_info.scope.node = start_node;
+	scope_info.scope.node = prefix_node;
 
 	/* Lookup the name in the namespace */
 
-	status = acpi_ns_lookup(&scope_info, internal_path,
-				ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
-				(flags | ACPI_NS_DONT_OPEN_SCOPE),
-				NULL, return_node);
+	status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
+				ACPI_IMODE_EXECUTE,
+				(flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
+				return_node);
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n",
-				  internal_path,
-				  acpi_format_exception(status)));
+				  pathname, acpi_format_exception(status)));
 	}
 
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
       cleanup:
-	if (internal_path) {
-		ACPI_MEM_FREE(internal_path);
-	}
+	ACPI_FREE(internal_path);
 	return_ACPI_STATUS(status);
 }
 
@@ -960,9 +965,10 @@
 {
 	struct acpi_namespace_node *parent_node;
 
-	ACPI_FUNCTION_TRACE("ns_find_parent_name");
+	ACPI_FUNCTION_TRACE(ns_find_parent_name);
 
 	if (child_node) {
+
 		/* Valid entry.  Get the parent Node */
 
 		parent_node = acpi_ns_get_parent_node(child_node);
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index fcab1e7..c8f6bef 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -76,6 +76,7 @@
 	ACPI_FUNCTION_ENTRY();
 
 	if (!child_node) {
+
 		/* It's really the parent's _scope_ that we want */
 
 		if (parent_node->child) {
@@ -92,6 +93,7 @@
 	/* If any type is OK, we are done */
 
 	if (type == ACPI_TYPE_ANY) {
+
 		/* next_node is NULL if we are at the end-of-list */
 
 		return (next_node);
@@ -100,6 +102,7 @@
 	/* Must search for the node -- but within this scope only */
 
 	while (next_node) {
+
 		/* If type matches, we are done */
 
 		if (next_node->type == type) {
@@ -161,7 +164,7 @@
 	acpi_object_type child_type;
 	u32 level;
 
-	ACPI_FUNCTION_TRACE("ns_walk_namespace");
+	ACPI_FUNCTION_TRACE(ns_walk_namespace);
 
 	/* Special case for the namespace Root Node */
 
@@ -182,6 +185,7 @@
 	 * bubbled up to (and passed) the original parent handle (start_entry)
 	 */
 	while (level > 0) {
+
 		/* Get the next node in this scope.  Null if not found */
 
 		status = AE_OK;
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index a95f636..6d9bd45a 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -42,8 +42,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/acinterp.h>
@@ -51,6 +49,7 @@
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsxfeval")
 
+#ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
  * FUNCTION:    acpi_evaluate_object_typed
@@ -71,18 +70,17 @@
  *              be valid (non-null)
  *
  ******************************************************************************/
-#ifdef ACPI_FUTURE_USAGE
 acpi_status
 acpi_evaluate_object_typed(acpi_handle handle,
 			   acpi_string pathname,
-			   struct acpi_object_list *external_params,
-			   struct acpi_buffer *return_buffer,
+			   struct acpi_object_list * external_params,
+			   struct acpi_buffer * return_buffer,
 			   acpi_object_type return_type)
 {
 	acpi_status status;
 	u8 must_free = FALSE;
 
-	ACPI_FUNCTION_TRACE("acpi_evaluate_object_typed");
+	ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed);
 
 	/* Return buffer must be valid */
 
@@ -110,6 +108,7 @@
 	}
 
 	if (return_buffer->length == 0) {
+
 		/* Error because caller specifically asked for a return value */
 
 		ACPI_ERROR((AE_INFO, "No return value"));
@@ -131,6 +130,7 @@
 		    acpi_ut_get_type_name(return_type)));
 
 	if (must_free) {
+
 		/* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */
 
 		acpi_os_free(return_buffer->pointer);
@@ -140,6 +140,8 @@
 	return_buffer->length = 0;
 	return_ACPI_STATUS(AE_TYPE);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
 #endif				/*  ACPI_FUTURE_USAGE  */
 
 /*******************************************************************************
@@ -161,7 +163,6 @@
  *              be valid (non-null)
  *
  ******************************************************************************/
-
 acpi_status
 acpi_evaluate_object(acpi_handle handle,
 		     acpi_string pathname,
@@ -170,51 +171,61 @@
 {
 	acpi_status status;
 	acpi_status status2;
-	struct acpi_parameter_info info;
+	struct acpi_evaluate_info *info;
 	acpi_size buffer_space_needed;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("acpi_evaluate_object");
+	ACPI_FUNCTION_TRACE(acpi_evaluate_object);
 
-	info.node = handle;
-	info.parameters = NULL;
-	info.return_object = NULL;
-	info.parameter_type = ACPI_PARAM_ARGS;
+	/* Allocate and initialize the evaluation information block */
+
+	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+	if (!info) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	info->pathname = pathname;
+	info->parameter_type = ACPI_PARAM_ARGS;
+
+	/* Convert and validate the device handle */
+
+	info->prefix_node = acpi_ns_map_handle_to_node(handle);
+	if (!info->prefix_node) {
+		status = AE_BAD_PARAMETER;
+		goto cleanup;
+	}
 
 	/*
-	 * If there are parameters to be passed to the object
-	 * (which must be a control method), the external objects
-	 * must be converted to internal objects
+	 * If there are parameters to be passed to a control method, the external
+	 * objects must all be converted to internal objects
 	 */
 	if (external_params && external_params->count) {
 		/*
 		 * Allocate a new parameter block for the internal objects
 		 * Add 1 to count to allow for null terminated internal list
 		 */
-		info.parameters = ACPI_MEM_CALLOCATE(((acpi_size)
-						      external_params->count +
-						      1) * sizeof(void *));
-		if (!info.parameters) {
-			return_ACPI_STATUS(AE_NO_MEMORY);
+		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
+							 external_params->
+							 count +
+							 1) * sizeof(void *));
+		if (!info->parameters) {
+			status = AE_NO_MEMORY;
+			goto cleanup;
 		}
 
-		/*
-		 * Convert each external object in the list to an
-		 * internal object
-		 */
+		/* Convert each external object in the list to an internal object */
+
 		for (i = 0; i < external_params->count; i++) {
 			status =
 			    acpi_ut_copy_eobject_to_iobject(&external_params->
 							    pointer[i],
-							    &info.
+							    &info->
 							    parameters[i]);
 			if (ACPI_FAILURE(status)) {
-				acpi_ut_delete_internal_object_list(info.
-								    parameters);
-				return_ACPI_STATUS(status);
+				goto cleanup;
 			}
 		}
-		info.parameters[external_params->count] = NULL;
+		info->parameters[external_params->count] = NULL;
 	}
 
 	/*
@@ -224,43 +235,31 @@
 	 * 3) Valid handle
 	 */
 	if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) {
-		/*
-		 *  The path is fully qualified, just evaluate by name
-		 */
-		status = acpi_ns_evaluate_by_name(pathname, &info);
+
+		/* The path is fully qualified, just evaluate by name */
+
+		info->prefix_node = NULL;
+		status = acpi_ns_evaluate(info);
 	} else if (!handle) {
 		/*
-		 * A handle is optional iff a fully qualified pathname
-		 * is specified.  Since we've already handled fully
-		 * qualified names above, this is an error
+		 * A handle is optional iff a fully qualified pathname is specified.
+		 * Since we've already handled fully qualified names above, this is
+		 * an error
 		 */
 		if (!pathname) {
-			ACPI_ERROR((AE_INFO,
-				    "Both Handle and Pathname are NULL"));
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					  "Both Handle and Pathname are NULL"));
 		} else {
-			ACPI_ERROR((AE_INFO,
-				    "Handle is NULL and Pathname is relative"));
+			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+					  "Null Handle with relative pathname [%s]",
+					  pathname));
 		}
 
 		status = AE_BAD_PARAMETER;
 	} else {
-		/*
-		 * We get here if we have a handle -- and if we have a
-		 * pathname it is relative.  The handle will be validated
-		 * in the lower procedures
-		 */
-		if (!pathname) {
-			/*
-			 * The null pathname case means the handle is for
-			 * the actual object to be evaluated
-			 */
-			status = acpi_ns_evaluate_by_handle(&info);
-		} else {
-			/*
-			 * Both a Handle and a relative Pathname
-			 */
-			status = acpi_ns_evaluate_relative(pathname, &info);
-		}
+		/* We have a namespace a node and a possible relative path */
+
+		status = acpi_ns_evaluate(info);
 	}
 
 	/*
@@ -268,10 +267,10 @@
 	 * copy the return value to an external object.
 	 */
 	if (return_buffer) {
-		if (!info.return_object) {
+		if (!info->return_object) {
 			return_buffer->length = 0;
 		} else {
-			if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) ==
+			if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
 			    ACPI_DESC_TYPE_NAMED) {
 				/*
 				 * If we received a NS Node as a return object, this means that
@@ -282,19 +281,19 @@
 				 * support for various types at a later date if necessary.
 				 */
 				status = AE_TYPE;
-				info.return_object = NULL;	/* No need to delete a NS Node */
+				info->return_object = NULL;	/* No need to delete a NS Node */
 				return_buffer->length = 0;
 			}
 
 			if (ACPI_SUCCESS(status)) {
-				/*
-				 * Find out how large a buffer is needed
-				 * to contain the returned object
-				 */
+
+				/* Get the size of the returned object */
+
 				status =
-				    acpi_ut_get_object_size(info.return_object,
+				    acpi_ut_get_object_size(info->return_object,
 							    &buffer_space_needed);
 				if (ACPI_SUCCESS(status)) {
+
 					/* Validate/Allocate/Clear caller buffer */
 
 					status =
@@ -303,7 +302,8 @@
 					     buffer_space_needed);
 					if (ACPI_FAILURE(status)) {
 						/*
-						 * Caller's buffer is too small or a new one can't be allocated
+						 * Caller's buffer is too small or a new one can't
+						 * be allocated
 						 */
 						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 								  "Needed buffer size %X, %s\n",
@@ -312,12 +312,11 @@
 								  acpi_format_exception
 								  (status)));
 					} else {
-						/*
-						 *  We have enough space for the object, build it
-						 */
+						/* We have enough space for the object, build it */
+
 						status =
 						    acpi_ut_copy_iobject_to_eobject
-						    (info.return_object,
+						    (info->return_object,
 						     return_buffer);
 					}
 				}
@@ -325,35 +324,37 @@
 		}
 	}
 
-	if (info.return_object) {
+	if (info->return_object) {
 		/*
-		 * Delete the internal return object.  NOTE: Interpreter
-		 * must be locked to avoid race condition.
+		 * Delete the internal return object. NOTE: Interpreter must be
+		 * locked to avoid race condition.
 		 */
 		status2 = acpi_ex_enter_interpreter();
 		if (ACPI_SUCCESS(status2)) {
-			/*
-			 * Delete the internal return object. (Or at least
-			 * decrement the reference count by one)
-			 */
-			acpi_ut_remove_reference(info.return_object);
+
+			/* Remove one reference on the return object (should delete it) */
+
+			acpi_ut_remove_reference(info->return_object);
 			acpi_ex_exit_interpreter();
 		}
 	}
 
-	/*
-	 * Free the input parameter list (if we created one),
-	 */
-	if (info.parameters) {
+      cleanup:
+
+	/* Free the input parameter list (if we created one) */
+
+	if (info->parameters) {
+
 		/* Free the allocated parameter block */
 
-		acpi_ut_delete_internal_object_list(info.parameters);
+		acpi_ut_delete_internal_object_list(info->parameters);
 	}
 
+	ACPI_FREE(info);
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_evaluate_object);
+ACPI_EXPORT_SYMBOL(acpi_evaluate_object)
 
 /*******************************************************************************
  *
@@ -384,7 +385,6 @@
  *              function, etc.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_walk_namespace(acpi_object_type type,
 		    acpi_handle start_object,
@@ -394,7 +394,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_walk_namespace");
+	ACPI_FUNCTION_TRACE(acpi_walk_namespace);
 
 	/* Parameter validation */
 
@@ -421,7 +421,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_walk_namespace);
+ACPI_EXPORT_SYMBOL(acpi_walk_namespace)
 
 /*******************************************************************************
  *
@@ -436,7 +436,6 @@
  *              on that.
  *
  ******************************************************************************/
-
 static acpi_status
 acpi_ns_get_device_callback(acpi_handle obj_handle,
 			    u32 nesting_level,
@@ -473,6 +472,7 @@
 	}
 
 	if (!(flags & ACPI_STA_DEVICE_PRESENT)) {
+
 		/* Don't examine children of the device if not present */
 
 		return (AE_CTRL_DEPTH);
@@ -489,6 +489,7 @@
 		}
 
 		if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
+
 			/* Get the list of Compatible IDs */
 
 			status = acpi_ut_execute_CID(node, &cid);
@@ -505,11 +506,11 @@
 						 sizeof(struct
 							acpi_compatible_id)) !=
 				    0) {
-					ACPI_MEM_FREE(cid);
+					ACPI_FREE(cid);
 					return (AE_OK);
 				}
 			}
-			ACPI_MEM_FREE(cid);
+			ACPI_FREE(cid);
 		}
 	}
 
@@ -551,7 +552,7 @@
 	acpi_status status;
 	struct acpi_get_devices_info info;
 
-	ACPI_FUNCTION_TRACE("acpi_get_devices");
+	ACPI_FUNCTION_TRACE(acpi_get_devices);
 
 	/* Parameter validation */
 
@@ -563,9 +564,9 @@
 	 * We're going to call their callback from OUR callback, so we need
 	 * to know what it is, and their context parameter.
 	 */
+	info.hid = HID;
 	info.context = context;
 	info.user_function = user_function;
-	info.hid = HID;
 
 	/*
 	 * Lock the namespace around the walk.
@@ -578,9 +579,8 @@
 		return_ACPI_STATUS(status);
 	}
 
-	status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE,
-					ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
-					ACPI_NS_WALK_UNLOCK,
+	status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+					ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
 					acpi_ns_get_device_callback, &info,
 					return_value);
 
@@ -588,7 +588,7 @@
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_devices);
+ACPI_EXPORT_SYMBOL(acpi_get_devices)
 
 /*******************************************************************************
  *
@@ -603,7 +603,6 @@
  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_attach_data(acpi_handle obj_handle,
 		 acpi_object_handler handler, void *data)
@@ -637,6 +636,8 @@
 	return (status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_attach_data)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_detach_data
@@ -649,7 +650,6 @@
  * DESCRIPTION: Remove data that was previously attached to a node.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
 {
@@ -682,6 +682,8 @@
 	return (status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_detach_data)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_data
@@ -695,7 +697,6 @@
  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
 {
@@ -727,3 +728,5 @@
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return (status);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_get_data)
diff --git a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c
index 8cd8675..978213a 100644
--- a/drivers/acpi/namespace/nsxfname.c
+++ b/drivers/acpi/namespace/nsxfname.c
@@ -42,8 +42,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 
@@ -114,9 +112,8 @@
 	/*
 	 *  Find the Node and convert to a handle
 	 */
-	status =
-	    acpi_ns_get_node_by_path(pathname, prefix_node, ACPI_NS_NO_UPSEARCH,
-				     &node);
+	status = acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH,
+				  &node);
 
 	*ret_handle = NULL;
 	if (ACPI_SUCCESS(status)) {
@@ -126,7 +123,7 @@
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_get_handle);
+ACPI_EXPORT_SYMBOL(acpi_get_handle)
 
 /******************************************************************************
  *
@@ -143,7 +140,6 @@
  *              complementary functions.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
 {
@@ -162,6 +158,7 @@
 	}
 
 	if (name_type == ACPI_FULL_PATHNAME) {
+
 		/* Get the full pathname (From the namespace root) */
 
 		status = acpi_ns_handle_to_pathname(handle, buffer);
@@ -203,7 +200,7 @@
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_get_name);
+ACPI_EXPORT_SYMBOL(acpi_get_name)
 
 /******************************************************************************
  *
@@ -219,7 +216,6 @@
  *              control methods (Such as in the case of a device.)
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
 {
@@ -241,7 +237,7 @@
 		return (status);
 	}
 
-	info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_device_info));
+	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info));
 	if (!info) {
 		return (AE_NO_MEMORY);
 	}
@@ -345,11 +341,11 @@
 	}
 
       cleanup:
-	ACPI_MEM_FREE(info);
+	ACPI_FREE(info);
 	if (cid_list) {
-		ACPI_MEM_FREE(cid_list);
+		ACPI_FREE(cid_list);
 	}
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_get_object_info);
+ACPI_EXPORT_SYMBOL(acpi_get_object_info)
diff --git a/drivers/acpi/namespace/nsxfobj.c b/drivers/acpi/namespace/nsxfobj.c
index a033259..a163e1d 100644
--- a/drivers/acpi/namespace/nsxfobj.c
+++ b/drivers/acpi/namespace/nsxfobj.c
@@ -42,8 +42,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 
@@ -101,7 +99,7 @@
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_get_type);
+ACPI_EXPORT_SYMBOL(acpi_get_type)
 
 /*******************************************************************************
  *
@@ -116,7 +114,6 @@
  *              Handle.
  *
  ******************************************************************************/
-
 acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
 {
 	struct acpi_namespace_node *node;
@@ -162,7 +159,7 @@
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_get_parent);
+ACPI_EXPORT_SYMBOL(acpi_get_parent)
 
 /*******************************************************************************
  *
@@ -181,7 +178,6 @@
  *              Scope is returned.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_next_object(acpi_object_type type,
 		     acpi_handle parent,
@@ -206,6 +202,7 @@
 	/* If null handle, use the parent */
 
 	if (!child) {
+
 		/* Start search at the beginning of the specified scope */
 
 		parent_node = acpi_ns_map_handle_to_node(parent);
@@ -242,4 +239,4 @@
 	return (status);
 }
 
-EXPORT_SYMBOL(acpi_get_next_object);
+ACPI_EXPORT_SYMBOL(acpi_get_next_object)
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 64b98e8..13d6d5bd 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -36,12 +36,60 @@
 #define _COMPONENT	ACPI_NUMA
 ACPI_MODULE_NAME("numa")
 
+static nodemask_t nodes_found_map = NODE_MASK_NONE;
+#define PXM_INVAL	-1
+#define NID_INVAL	-1
+
+/* maps to convert between proximity domain and logical node ID */
+int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]
+				= { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL };
+int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]
+				= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
+
 extern int __init acpi_table_parse_madt_family(enum acpi_table_id id,
 					       unsigned long madt_size,
 					       int entry_id,
 					       acpi_madt_entry_handler handler,
 					       unsigned int max_entries);
 
+int __cpuinit pxm_to_node(int pxm)
+{
+	if (pxm < 0)
+		return NID_INVAL;
+	return pxm_to_node_map[pxm];
+}
+
+int __cpuinit node_to_pxm(int node)
+{
+	if (node < 0)
+		return PXM_INVAL;
+	return node_to_pxm_map[node];
+}
+
+int __cpuinit acpi_map_pxm_to_node(int pxm)
+{
+	int node = pxm_to_node_map[pxm];
+
+	if (node < 0){
+		if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
+			return NID_INVAL;
+		node = first_unset_node(nodes_found_map);
+		pxm_to_node_map[pxm] = node;
+		node_to_pxm_map[node] = pxm;
+		node_set(node, nodes_found_map);
+	}
+
+	return node;
+}
+
+void __cpuinit acpi_unmap_pxm_to_node(int node)
+{
+	int pxm = node_to_pxm_map[node];
+	pxm_to_node_map[pxm] = NID_INVAL;
+	node_to_pxm_map[node] = PXM_INVAL;
+	node_clear(node, nodes_found_map);
+}
+
 void __init acpi_table_print_srat_entry(acpi_table_entry_header * header)
 {
 
@@ -206,5 +254,18 @@
 	} while (ACPI_SUCCESS(status));
 	return -1;
 }
-
 EXPORT_SYMBOL(acpi_get_pxm);
+
+int acpi_get_node(acpi_handle *handle)
+{
+	int pxm, node = -1;
+
+	ACPI_FUNCTION_TRACE("acpi_get_node");
+
+	pxm = acpi_get_pxm(handle);
+	if (pxm >= 0)
+		node = acpi_map_pxm_to_node(pxm);
+
+	return_VALUE(node);
+}
+EXPORT_SYMBOL(acpi_get_node);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 13b5fd5..1bb558a 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -37,6 +37,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/nmi.h>
+#include <linux/kthread.h>
 #include <acpi/acpi.h>
 #include <asm/io.h>
 #include <acpi/acpi_bus.h>
@@ -600,23 +601,41 @@
 	return_VOID;
 }
 
-acpi_status
-acpi_os_queue_for_execution(u32 priority,
+static int acpi_os_execute_thread(void *context)
+{
+	struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context;
+	if (dpc) {
+		dpc->function(dpc->context);
+		kfree(dpc);
+	}
+	do_exit(0);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_os_execute
+ *
+ * PARAMETERS:  Type               - Type of the callback
+ *              Function           - Function to be executed
+ *              Context            - Function parameters
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Depending on type, either queues function for deferred execution or
+ *              immediately executes function on a separate thread.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_os_execute(acpi_execute_type type,
 			    acpi_osd_exec_callback function, void *context)
 {
 	acpi_status status = AE_OK;
 	struct acpi_os_dpc *dpc;
 	struct work_struct *task;
-
-	ACPI_FUNCTION_TRACE("os_queue_for_execution");
-
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-			  "Scheduling function [%p(%p)] for deferred execution.\n",
-			  function, context));
+	struct task_struct *p;
 
 	if (!function)
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-
+		return AE_BAD_PARAMETER;
 	/*
 	 * Allocate/initialize DPC structure.  Note that this memory will be
 	 * freed by the callee.  The kernel handles the tq_struct list  in a
@@ -627,30 +646,37 @@
 	 * We can save time and code by allocating the DPC and tq_structs
 	 * from the same memory.
 	 */
-
-	dpc =
-	    kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct),
-		    GFP_ATOMIC);
+	if (type == OSL_NOTIFY_HANDLER) {
+		dpc = kmalloc(sizeof(struct acpi_os_dpc), GFP_KERNEL);
+	} else {
+		dpc = kmalloc(sizeof(struct acpi_os_dpc) +
+				sizeof(struct work_struct), GFP_ATOMIC);
+	}
 	if (!dpc)
-		return_ACPI_STATUS(AE_NO_MEMORY);
-
+		return AE_NO_MEMORY;
 	dpc->function = function;
 	dpc->context = context;
 
-	task = (void *)(dpc + 1);
-	INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
-
-	if (!queue_work(kacpid_wq, task)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "Call to queue_work() failed.\n"));
-		kfree(dpc);
-		status = AE_ERROR;
+	if (type == OSL_NOTIFY_HANDLER) {
+		p = kthread_create(acpi_os_execute_thread, dpc, "kacpid_notify");
+		if (!IS_ERR(p)) {
+			wake_up_process(p);
+		} else {
+			status = AE_NO_MEMORY;
+			kfree(dpc);
+		}
+	} else {
+		task = (void *)(dpc + 1);
+		INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc);
+		if (!queue_work(kacpid_wq, task)) {
+			status = AE_ERROR;
+			kfree(dpc);
+		}
 	}
-
-	return_ACPI_STATUS(status);
+	return status;
 }
 
-EXPORT_SYMBOL(acpi_os_queue_for_execution);
+EXPORT_SYMBOL(acpi_os_execute);
 
 void acpi_os_wait_events_complete(void *context)
 {
@@ -769,9 +795,6 @@
 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Waiting for semaphore[%p|%d|%d]\n",
 			  handle, units, timeout));
 
-	if (in_atomic())
-		timeout = 0;
-
 	switch (timeout) {
 		/*
 		 * No Wait:
@@ -896,14 +919,6 @@
 }
 #endif
 
-u32 acpi_os_get_thread_id(void)
-{
-	if (!in_atomic())
-		return current->pid;
-
-	return 0;
-}
-
 acpi_status acpi_os_signal(u32 function, void *info)
 {
 	switch (function) {
@@ -1050,12 +1065,12 @@
  *
  * FUNCTION:    acpi_os_create_cache
  *
- * PARAMETERS:  CacheName       - Ascii name for the cache
- *              ObjectSize      - Size of each cached object
- *              MaxDepth        - Maximum depth of the cache (in objects)
- *              ReturnCache     - Where the new cache object is returned
+ * PARAMETERS:  name      - Ascii name for the cache
+ *              size      - Size of each cached object
+ *              depth     - Maximum depth of the cache (in objects) <ignored>
+ *              cache     - Where the new cache object is returned
  *
- * RETURN:      Status
+ * RETURN:      status
  *
  * DESCRIPTION: Create a cache object
  *
@@ -1065,7 +1080,10 @@
 acpi_os_create_cache(char *name, u16 size, u16 depth, acpi_cache_t ** cache)
 {
 	*cache = kmem_cache_create(name, size, 0, 0, NULL, NULL);
-	return AE_OK;
+	if (cache == NULL)
+		return AE_ERROR;
+	else
+		return AE_OK;
 }
 
 /*******************************************************************************
@@ -1134,16 +1152,63 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Get an object from the specified cache.  If cache is empty,
- *              the object is allocated.
+ * DESCRIPTION: Return a zero-filled object.
  *
  ******************************************************************************/
 
 void *acpi_os_acquire_object(acpi_cache_t * cache)
 {
-	void *object = kmem_cache_alloc(cache, GFP_KERNEL);
+	void *object = kmem_cache_zalloc(cache, GFP_KERNEL);
 	WARN_ON(!object);
 	return object;
 }
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_os_validate_interface
+ *
+ * PARAMETERS:  interface           - Requested interface to be validated
+ *
+ * RETURN:      AE_OK if interface is supported, AE_SUPPORT otherwise
+ *
+ * DESCRIPTION: Match an interface string to the interfaces supported by the
+ *              host. Strings originate from an AML call to the _OSI method.
+ *
+ *****************************************************************************/
+
+acpi_status
+acpi_os_validate_interface (char *interface)
+{
+
+    return AE_SUPPORT;
+}
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_os_validate_address
+ *
+ * PARAMETERS:  space_id             - ACPI space ID
+ *              address             - Physical address
+ *              length              - Address length
+ *
+ * RETURN:      AE_OK if address/length is valid for the space_id. Otherwise,
+ *              should return AE_AML_ILLEGAL_ADDRESS.
+ *
+ * DESCRIPTION: Validate a system address via the host OS. Used to validate
+ *              the addresses accessed by AML operation regions.
+ *
+ *****************************************************************************/
+
+acpi_status
+acpi_os_validate_address (
+    u8                   space_id,
+    acpi_physical_address   address,
+    acpi_size               length)
+{
+
+    return AE_OK;
+}
+
+
 #endif
diff --git a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c
index de573be..bf88e07 100644
--- a/drivers/acpi/parser/psargs.c
+++ b/drivers/acpi/parser/psargs.c
@@ -79,7 +79,7 @@
 	acpi_native_uint byte_count;
 	u8 byte_zero_mask = 0x3F;	/* Default [0:5] */
 
-	ACPI_FUNCTION_TRACE("ps_get_next_package_length");
+	ACPI_FUNCTION_TRACE(ps_get_next_package_length);
 
 	/*
 	 * Byte 0 bits [6:7] contain the number of additional bytes
@@ -128,7 +128,7 @@
 	u8 *start = parser_state->aml;
 	u32 package_length;
 
-	ACPI_FUNCTION_TRACE("ps_get_next_package_end");
+	ACPI_FUNCTION_TRACE(ps_get_next_package_end);
 
 	/* Function below updates parser_state->Aml */
 
@@ -157,7 +157,7 @@
 	u8 *start = parser_state->aml;
 	u8 *end = parser_state->aml;
 
-	ACPI_FUNCTION_TRACE("ps_get_next_namestring");
+	ACPI_FUNCTION_TRACE(ps_get_next_namestring);
 
 	/* Point past any namestring prefix characters (backslash or carat) */
 
@@ -237,7 +237,7 @@
 	struct acpi_namespace_node *node;
 	union acpi_generic_state scope_info;
 
-	ACPI_FUNCTION_TRACE("ps_get_next_namepath");
+	ACPI_FUNCTION_TRACE(ps_get_next_namepath);
 
 	path = acpi_ps_get_next_namestring(parser_state);
 	acpi_ps_init_op(arg, AML_INT_NAMEPATH_OP);
@@ -275,6 +275,7 @@
 	 */
 	if (ACPI_SUCCESS(status) &&
 	    possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
+
 		/* This name is actually a control method invocation */
 
 		method_desc = acpi_ns_get_attached_object(node);
@@ -319,6 +320,7 @@
 	 * some not_found cases are allowed
 	 */
 	if (status == AE_NOT_FOUND) {
+
 		/* 1) not_found is ok during load pass 1/2 (allow forward references) */
 
 		if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) !=
@@ -354,6 +356,7 @@
 
 		if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
 		    ACPI_PARSE_EXECUTE) {
+
 			/* Report a control method execution error */
 
 			status = acpi_ds_method_error(status, walk_state);
@@ -388,7 +391,7 @@
 	u16 opcode;
 	u8 *aml = parser_state->aml;
 
-	ACPI_FUNCTION_TRACE_U32("ps_get_next_simple_arg", arg_type);
+	ACPI_FUNCTION_TRACE_U32(ps_get_next_simple_arg, arg_type);
 
 	switch (arg_type) {
 	case ARGP_BYTEDATA:
@@ -453,7 +456,7 @@
 
 	default:
 
-		ACPI_ERROR((AE_INFO, "Invalid arg_type %X", arg_type));
+		ACPI_ERROR((AE_INFO, "Invalid ArgType %X", arg_type));
 		return_VOID;
 	}
 
@@ -484,7 +487,7 @@
 	u16 opcode;
 	u32 name;
 
-	ACPI_FUNCTION_TRACE("ps_get_next_field");
+	ACPI_FUNCTION_TRACE(ps_get_next_field);
 
 	/* Determine field type */
 
@@ -590,7 +593,7 @@
 	u32 subop;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_get_next_arg", parser_state);
+	ACPI_FUNCTION_TRACE_PTR(ps_get_next_arg, parser_state);
 
 	switch (arg_type) {
 	case ARGP_BYTEDATA:
@@ -620,6 +623,7 @@
 	case ARGP_FIELDLIST:
 
 		if (parser_state->aml < parser_state->pkg_end) {
+
 			/* Non-empty list */
 
 			while (parser_state->aml < parser_state->pkg_end) {
@@ -645,6 +649,7 @@
 	case ARGP_BYTELIST:
 
 		if (parser_state->aml < parser_state->pkg_end) {
+
 			/* Non-empty list */
 
 			arg = acpi_ps_alloc_op(AML_INT_BYTELIST_OP);
@@ -673,6 +678,7 @@
 		if (subop == 0 ||
 		    acpi_ps_is_leading_char(subop) ||
 		    acpi_ps_is_prefix_char(subop)) {
+
 			/* null_name or name_string */
 
 			arg = acpi_ps_alloc_op(AML_INT_NAMEPATH_OP);
@@ -703,6 +709,7 @@
 	case ARGP_OBJLIST:
 
 		if (parser_state->aml < parser_state->pkg_end) {
+
 			/* Non-empty list of variable arguments, nothing returned */
 
 			walk_state->arg_count = ACPI_VAR_ARGS;
@@ -711,7 +718,7 @@
 
 	default:
 
-		ACPI_ERROR((AE_INFO, "Invalid arg_type: %X", arg_type));
+		ACPI_ERROR((AE_INFO, "Invalid ArgType: %X", arg_type));
 		status = AE_AML_OPERAND_TYPE;
 		break;
 	}
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
index 00b072e..e1541db 100644
--- a/drivers/acpi/parser/psloop.c
+++ b/drivers/acpi/parser/psloop.c
@@ -83,7 +83,7 @@
 	struct acpi_parse_state *parser_state;
 	u8 *aml_op_start = NULL;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state);
+	ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
 
 	if (walk_state->descending_callback == NULL) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -95,6 +95,7 @@
 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
 
 	if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
+
 		/* We are restarting a preempted control method */
 
 		if (acpi_ps_has_completed_scope(parser_state)) {
@@ -128,7 +129,7 @@
 
 					}
 					ACPI_EXCEPTION((AE_INFO, status,
-							"get_predicate Failed"));
+							"GetPredicate Failed"));
 					return_ACPI_STATUS(status);
 				}
 
@@ -143,6 +144,7 @@
 			ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 					  "Popped scope, Op=%p\n", op));
 		} else if (walk_state->prev_op) {
+
 			/* We were in the middle of an op */
 
 			op = walk_state->prev_op;
@@ -156,6 +158,7 @@
 	while ((parser_state->aml < parser_state->aml_end) || (op)) {
 		aml_op_start = parser_state->aml;
 		if (!op) {
+
 			/* Get the next opcode from the AML stream */
 
 			walk_state->aml_offset =
@@ -213,6 +216,7 @@
 			/* Create Op structure and append to parent's argument list */
 
 			if (walk_state->op_info->flags & AML_NAMED) {
+
 				/* Allocate a new pre_op if necessary */
 
 				if (!pre_op) {
@@ -371,7 +375,7 @@
 
 			if (walk_state->op_info) {
 				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-						  "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
+						  "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
 						  (u32) op->common.aml_opcode,
 						  walk_state->op_info->name, op,
 						  parser_state->aml,
@@ -388,6 +392,7 @@
 		/* Are there any arguments that must be processed? */
 
 		if (walk_state->arg_types) {
+
 			/* Get arguments */
 
 			switch (op->common.aml_opcode) {
@@ -742,7 +747,19 @@
 					if (ACPI_FAILURE(status2)) {
 						return_ACPI_STATUS(status2);
 					}
+
+					status2 =
+					    acpi_ds_result_stack_pop
+					    (walk_state);
+					if (ACPI_FAILURE(status2)) {
+						return_ACPI_STATUS(status2);
+					}
+
+					acpi_ut_delete_generic_state
+					    (acpi_ut_pop_generic_state
+					     (&walk_state->control_state));
 				}
+
 				acpi_ps_pop_scope(parser_state, &op,
 						  &walk_state->arg_types,
 						  &walk_state->arg_count);
@@ -762,6 +779,7 @@
 						return_ACPI_STATUS(status2);
 					}
 				}
+
 				acpi_ps_pop_scope(parser_state, &op,
 						  &walk_state->arg_types,
 						  &walk_state->arg_count);
@@ -853,6 +871,7 @@
 				}
 
 				else if (ACPI_FAILURE(status)) {
+
 					/* First error is most important */
 
 					(void)
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 11d6351..4bd25e3 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -725,12 +725,13 @@
 
 const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode)
 {
-	ACPI_FUNCTION_NAME("ps_get_opcode_info");
+	ACPI_FUNCTION_NAME(ps_get_opcode_info);
 
 	/*
 	 * Detect normal 8-bit opcode or extended 16-bit opcode
 	 */
 	if (!(opcode & 0xFF00)) {
+
 		/* Simple (8-bit) opcode: 0-255, can't index beyond table  */
 
 		return (&acpi_gbl_aml_op_info
@@ -739,6 +740,7 @@
 
 	if (((opcode & 0xFF00) == AML_EXTENDED_OPCODE) &&
 	    (((u8) opcode) <= MAX_EXTENDED_OPCODE)) {
+
 		/* Valid extended (16-bit) opcode */
 
 		return (&acpi_gbl_aml_op_info
@@ -779,7 +781,7 @@
 	return (op->name);
 
 #else
-	return ("AE_NOT_CONFIGURED");
+	return ("OpcodeName unavailable");
 
 #endif
 }
diff --git a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
index a9f3229..7ee2f2e 100644
--- a/drivers/acpi/parser/psparse.c
+++ b/drivers/acpi/parser/psparse.c
@@ -106,6 +106,7 @@
 	opcode = (u16) ACPI_GET8(aml);
 
 	if (opcode == AML_EXTENDED_OP_PREFIX) {
+
 		/* Extended opcode, get the second opcode byte */
 
 		aml++;
@@ -137,7 +138,7 @@
 	const struct acpi_opcode_info *parent_info;
 	union acpi_parse_object *replacement_op = NULL;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_complete_this_op", op);
+	ACPI_FUNCTION_TRACE_PTR(ps_complete_this_op, op);
 
 	/* Check for null Op, can happen if AML code is corrupt */
 
@@ -158,6 +159,7 @@
 	if (op->common.parent) {
 		prev = op->common.parent->common.value.arg;
 		if (!prev) {
+
 			/* Nothing more to do */
 
 			goto cleanup;
@@ -245,6 +247,7 @@
 		/* We must unlink this op from the parent tree */
 
 		if (prev == op) {
+
 			/* This op is the first in the list */
 
 			if (replacement_op) {
@@ -265,6 +268,7 @@
 
 		else
 			while (prev) {
+
 				/* Traverse all siblings in the parent's argument list */
 
 				next = prev->common.next;
@@ -329,7 +333,7 @@
 	struct acpi_parse_state *parser_state = &walk_state->parser_state;
 	acpi_status status = AE_CTRL_PENDING;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_next_parse_state", op);
+	ACPI_FUNCTION_TRACE_PTR(ps_next_parse_state, op);
 
 	switch (callback_status) {
 	case AE_CTRL_TERMINATE:
@@ -449,10 +453,10 @@
 	struct acpi_thread_state *prev_walk_list = acpi_gbl_current_walk_list;
 	struct acpi_walk_state *previous_walk_state;
 
-	ACPI_FUNCTION_TRACE("ps_parse_aml");
+	ACPI_FUNCTION_TRACE(ps_parse_aml);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-			  "Entered with walk_state=%p Aml=%p size=%X\n",
+			  "Entered with WalkState=%p Aml=%p size=%X\n",
 			  walk_state, walk_state->parser_state.aml,
 			  walk_state->parser_state.aml_size));
 
@@ -460,6 +464,7 @@
 
 	thread = acpi_ut_create_thread_state();
 	if (!thread) {
+		acpi_ds_delete_walk_state(walk_state);
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
@@ -510,6 +515,7 @@
 		} else if (status == AE_CTRL_TERMINATE) {
 			status = AE_OK;
 		} else if ((status != AE_OK) && (walk_state->method_desc)) {
+
 			/* Either the method parse or actual execution failed */
 
 			ACPI_ERROR_METHOD("Method parse/execution failed",
@@ -550,20 +556,9 @@
 		 */
 		if (((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) ==
 		     ACPI_PARSE_EXECUTE) || (ACPI_FAILURE(status))) {
-			if (walk_state->method_desc) {
-				/* Decrement the thread count on the method parse tree */
-
-				if (walk_state->method_desc->method.
-				    thread_count) {
-					walk_state->method_desc->method.
-					    thread_count--;
-				} else {
-					ACPI_ERROR((AE_INFO,
-						    "Invalid zero thread count in method"));
-				}
-			}
-
-			acpi_ds_terminate_control_method(walk_state);
+			acpi_ds_terminate_control_method(walk_state->
+							 method_desc,
+							 walk_state);
 		}
 
 		/* Delete this walk state and all linked control states */
@@ -572,7 +567,7 @@
 		previous_walk_state = walk_state;
 
 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-				  "return_value=%p, implicit_value=%p State=%p\n",
+				  "ReturnValue=%p, ImplicitValue=%p State=%p\n",
 				  walk_state->return_desc,
 				  walk_state->implicit_return_obj, walk_state));
 
@@ -633,12 +628,14 @@
 			}
 		} else {
 			if (previous_walk_state->return_desc) {
+
 				/* Caller doesn't want it, must delete it */
 
 				acpi_ut_remove_reference(previous_walk_state->
 							 return_desc);
 			}
 			if (previous_walk_state->implicit_return_obj) {
+
 				/* Caller doesn't want it, must delete it */
 
 				acpi_ut_remove_reference(previous_walk_state->
diff --git a/drivers/acpi/parser/psscope.c b/drivers/acpi/parser/psscope.c
index bc6047c..a3e0314d 100644
--- a/drivers/acpi/parser/psscope.c
+++ b/drivers/acpi/parser/psscope.c
@@ -106,14 +106,14 @@
 {
 	union acpi_generic_state *scope;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_init_scope", root_op);
+	ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op);
 
 	scope = acpi_ut_create_generic_state();
 	if (!scope) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
-	scope->common.data_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
+	scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
 	scope->parse_scope.op = root_op;
 	scope->parse_scope.arg_count = ACPI_VAR_ARGS;
 	scope->parse_scope.arg_end = parser_state->aml_end;
@@ -147,14 +147,14 @@
 {
 	union acpi_generic_state *scope;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_push_scope", op);
+	ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op);
 
 	scope = acpi_ut_create_generic_state();
 	if (!scope) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
-	scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE;
+	scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE;
 	scope->parse_scope.op = op;
 	scope->parse_scope.arg_list = remaining_args;
 	scope->parse_scope.arg_count = arg_count;
@@ -165,6 +165,7 @@
 	acpi_ut_push_generic_state(&parser_state->scope, scope);
 
 	if (arg_count == ACPI_VAR_ARGS) {
+
 		/* Multiple arguments */
 
 		scope->parse_scope.arg_end = parser_state->pkg_end;
@@ -199,14 +200,14 @@
 {
 	union acpi_generic_state *scope = parser_state->scope;
 
-	ACPI_FUNCTION_TRACE("ps_pop_scope");
+	ACPI_FUNCTION_TRACE(ps_pop_scope);
 
 	/* Only pop the scope if there is in fact a next scope */
 
 	if (scope->common.next) {
 		scope = acpi_ut_pop_generic_state(&parser_state->scope);
 
-		/* return to parsing previous op */
+		/* Return to parsing previous op */
 
 		*op = scope->parse_scope.op;
 		*arg_list = scope->parse_scope.arg_list;
@@ -217,7 +218,7 @@
 
 		acpi_ut_delete_generic_state(scope);
 	} else {
-		/* empty parse stack, prepare to fetch next opcode */
+		/* Empty parse stack, prepare to fetch next opcode */
 
 		*op = NULL;
 		*arg_list = 0;
@@ -246,7 +247,7 @@
 {
 	union acpi_generic_state *scope;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_cleanup_scope", parser_state);
+	ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state);
 
 	if (!parser_state) {
 		return_VOID;
diff --git a/drivers/acpi/parser/pstree.c b/drivers/acpi/parser/pstree.c
index dd6f167..0015717 100644
--- a/drivers/acpi/parser/pstree.c
+++ b/drivers/acpi/parser/pstree.c
@@ -77,6 +77,7 @@
 
 	op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
 	if (op_info->class == AML_CLASS_UNKNOWN) {
+
 		/* Invalid opcode or ASCII character */
 
 		return (NULL);
@@ -85,6 +86,7 @@
 	/* Check if this opcode requires argument sub-objects */
 
 	if (!(op_info->flags & AML_HAS_ARGS)) {
+
 		/* Has no linked argument objects */
 
 		return (NULL);
@@ -130,6 +132,7 @@
 
 	op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
 	if (op_info->class == AML_CLASS_UNKNOWN) {
+
 		/* Invalid opcode */
 
 		ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X",
@@ -140,6 +143,7 @@
 	/* Check if this opcode requires argument sub-objects */
 
 	if (!(op_info->flags & AML_HAS_ARGS)) {
+
 		/* Has no linked argument objects */
 
 		return;
@@ -148,6 +152,7 @@
 	/* Append the argument to the linked argument list */
 
 	if (op->common.value.arg) {
+
 		/* Append to existing argument list */
 
 		prev_arg = op->common.value.arg;
@@ -222,12 +227,14 @@
 		}
 
 		if (arg == origin) {
+
 			/* Reached parent of origin, end search */
 
 			return (NULL);
 		}
 
 		if (parent->common.next) {
+
 			/* Found sibling of parent */
 
 			return (parent->common.next);
@@ -299,5 +306,4 @@
 	return (child);
 }
 #endif
-
 #endif				/*  ACPI_FUTURE_USAGE  */
diff --git a/drivers/acpi/parser/psutils.c b/drivers/acpi/parser/psutils.c
index 3e07cb9..182474a 100644
--- a/drivers/acpi/parser/psutils.c
+++ b/drivers/acpi/parser/psutils.c
@@ -89,7 +89,7 @@
 {
 	ACPI_FUNCTION_ENTRY();
 
-	op->common.data_type = ACPI_DESC_TYPE_PARSER;
+	op->common.descriptor_type = ACPI_DESC_TYPE_PARSER;
 	op->common.aml_opcode = opcode;
 
 	ACPI_DISASM_ONLY_MEMBERS(ACPI_STRNCPY(op->common.aml_op_name,
@@ -135,6 +135,7 @@
 	/* Allocate the minimum required size object */
 
 	if (flags == ACPI_PARSEOP_GENERIC) {
+
 		/* The generic op (default) is by far the most common (16 to 1) */
 
 		op = acpi_os_acquire_object(acpi_gbl_ps_node_cache);
@@ -171,7 +172,7 @@
 
 void acpi_ps_free_op(union acpi_parse_object *op)
 {
-	ACPI_FUNCTION_NAME("ps_free_op");
+	ACPI_FUNCTION_NAME(ps_free_op);
 
 	if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n",
diff --git a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
index 06f05bf..a84a547 100644
--- a/drivers/acpi/parser/pswalk.c
+++ b/drivers/acpi/parser/pswalk.c
@@ -64,18 +64,21 @@
 	union acpi_parse_object *next = NULL;
 	union acpi_parse_object *parent = NULL;
 
-	ACPI_FUNCTION_TRACE_PTR("ps_delete_parse_tree", subtree_root);
+	ACPI_FUNCTION_TRACE_PTR(ps_delete_parse_tree, subtree_root);
 
 	/* Visit all nodes in the subtree */
 
 	while (op) {
+
 		/* Check if we are not ascending */
 
 		if (op != parent) {
+
 			/* Look for an argument or child of the current op */
 
 			next = acpi_ps_get_arg(op, 0);
 			if (next) {
+
 				/* Still going downward in tree (Op is not completed yet) */
 
 				op = next;
diff --git a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c
index 2dd48cb..5d996c1 100644
--- a/drivers/acpi/parser/psxface.c
+++ b/drivers/acpi/parser/psxface.c
@@ -50,14 +50,14 @@
 ACPI_MODULE_NAME("psxface")
 
 /* Local Prototypes */
-static void acpi_ps_start_trace(struct acpi_parameter_info *info);
+static void acpi_ps_start_trace(struct acpi_evaluate_info *info);
 
-static void acpi_ps_stop_trace(struct acpi_parameter_info *info);
+static void acpi_ps_stop_trace(struct acpi_evaluate_info *info);
 
-static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info);
+static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info);
 
 static void
-acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action);
+acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
 
 /*******************************************************************************
  *
@@ -113,7 +113,7 @@
  *
  ******************************************************************************/
 
-static void acpi_ps_start_trace(struct acpi_parameter_info *info)
+static void acpi_ps_start_trace(struct acpi_evaluate_info *info)
 {
 	acpi_status status;
 
@@ -125,7 +125,7 @@
 	}
 
 	if ((!acpi_gbl_trace_method_name) ||
-	    (acpi_gbl_trace_method_name != info->node->name.integer)) {
+	    (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
 		goto exit;
 	}
 
@@ -158,7 +158,7 @@
  *
  ******************************************************************************/
 
-static void acpi_ps_stop_trace(struct acpi_parameter_info *info)
+static void acpi_ps_stop_trace(struct acpi_evaluate_info *info)
 {
 	acpi_status status;
 
@@ -170,7 +170,7 @@
 	}
 
 	if ((!acpi_gbl_trace_method_name) ||
-	    (acpi_gbl_trace_method_name != info->node->name.integer)) {
+	    (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
 		goto exit;
 	}
 
@@ -212,22 +212,23 @@
  *
  ******************************************************************************/
 
-acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info)
+acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ps_execute_method");
+	ACPI_FUNCTION_TRACE(ps_execute_method);
 
 	/* Validate the Info and method Node */
 
-	if (!info || !info->node) {
+	if (!info || !info->resolved_node) {
 		return_ACPI_STATUS(AE_NULL_ENTRY);
 	}
 
 	/* Init for new method, wait on concurrency semaphore */
 
 	status =
-	    acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
+	    acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc,
+					   NULL);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
@@ -248,7 +249,7 @@
 	 */
 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 			  "**** Begin Method Parse **** Entry=%p obj=%p\n",
-			  info->node, info->obj_desc));
+			  info->resolved_node, info->obj_desc));
 
 	info->pass_number = 1;
 	status = acpi_ps_execute_pass(info);
@@ -261,7 +262,7 @@
 	 */
 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 			  "**** Begin Method Execution **** Entry=%p obj=%p\n",
-			  info->node, info->obj_desc));
+			  info->resolved_node, info->obj_desc));
 
 	info->pass_number = 3;
 	status = acpi_ps_execute_pass(info);
@@ -286,8 +287,7 @@
 	 * a control exception code
 	 */
 	if (info->return_object) {
-		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
-				  "Method returned obj_desc=%p\n",
+		ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
 				  info->return_object));
 		ACPI_DUMP_STACK_ENTRY(info->return_object);
 
@@ -301,7 +301,7 @@
  *
  * FUNCTION:    acpi_ps_update_parameter_list
  *
- * PARAMETERS:  Info            - See struct acpi_parameter_info
+ * PARAMETERS:  Info            - See struct acpi_evaluate_info
  *                                (Used: parameter_type and Parameters)
  *              Action          - Add or Remove reference
  *
@@ -312,14 +312,16 @@
  ******************************************************************************/
 
 static void
-acpi_ps_update_parameter_list(struct acpi_parameter_info *info, u16 action)
+acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
 {
 	acpi_native_uint i;
 
 	if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) {
+
 		/* Update reference count for each parameter */
 
 		for (i = 0; info->parameters[i]; i++) {
+
 			/* Ignore errors, just do them all */
 
 			(void)acpi_ut_update_object_reference(info->
@@ -333,7 +335,7 @@
  *
  * FUNCTION:    acpi_ps_execute_pass
  *
- * PARAMETERS:  Info            - See struct acpi_parameter_info
+ * PARAMETERS:  Info            - See struct acpi_evaluate_info
  *                                (Used: pass_number, Node, and obj_desc)
  *
  * RETURN:      Status
@@ -342,13 +344,13 @@
  *
  ******************************************************************************/
 
-static acpi_status acpi_ps_execute_pass(struct acpi_parameter_info *info)
+static acpi_status acpi_ps_execute_pass(struct acpi_evaluate_info *info)
 {
 	acpi_status status;
 	union acpi_parse_object *op;
 	struct acpi_walk_state *walk_state;
 
-	ACPI_FUNCTION_TRACE("ps_execute_pass");
+	ACPI_FUNCTION_TRACE(ps_execute_pass);
 
 	/* Create and init a Root Node */
 
@@ -367,7 +369,7 @@
 		goto cleanup;
 	}
 
-	status = acpi_ds_init_aml_walk(walk_state, op, info->node,
+	status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node,
 				       info->obj_desc->method.aml_start,
 				       info->obj_desc->method.aml_length,
 				       info->pass_number == 1 ? NULL : info,
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index 07bc6df..228bdb6 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -38,6 +38,7 @@
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
+#include <linux/mutex.h>
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -91,7 +92,7 @@
 	int count;
 	struct list_head entries;
 } acpi_link;
-DECLARE_MUTEX(acpi_link_lock);
+DEFINE_MUTEX(acpi_link_lock);
 
 /* --------------------------------------------------------------------------
                             PCI Link Device Management
@@ -641,19 +642,19 @@
 		return_VALUE(-1);
 	}
 
-	down(&acpi_link_lock);
+	mutex_lock(&acpi_link_lock);
 	if (acpi_pci_link_allocate(link)) {
-		up(&acpi_link_lock);
+		mutex_unlock(&acpi_link_lock);
 		return_VALUE(-1);
 	}
 
 	if (!link->irq.active) {
-		up(&acpi_link_lock);
+		mutex_unlock(&acpi_link_lock);
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n"));
 		return_VALUE(-1);
 	}
 	link->refcnt++;
-	up(&acpi_link_lock);
+	mutex_unlock(&acpi_link_lock);
 
 	if (triggering)
 		*triggering = link->irq.triggering;
@@ -691,9 +692,9 @@
 		return_VALUE(-1);
 	}
 
-	down(&acpi_link_lock);
+	mutex_lock(&acpi_link_lock);
 	if (!link->irq.initialized) {
-		up(&acpi_link_lock);
+		mutex_unlock(&acpi_link_lock);
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n"));
 		return_VALUE(-1);
 	}
@@ -716,7 +717,7 @@
 	if (link->refcnt == 0) {
 		acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
 	}
-	up(&acpi_link_lock);
+	mutex_unlock(&acpi_link_lock);
 	return_VALUE(link->irq.active);
 }
 
@@ -747,7 +748,7 @@
 	strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS);
 	acpi_driver_data(device) = link;
 
-	down(&acpi_link_lock);
+	mutex_lock(&acpi_link_lock);
 	result = acpi_pci_link_get_possible(link);
 	if (result)
 		goto end;
@@ -782,7 +783,7 @@
       end:
 	/* disable all links -- to be activated on use */
 	acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL);
-	up(&acpi_link_lock);
+	mutex_unlock(&acpi_link_lock);
 
 	if (result)
 		kfree(link);
@@ -812,6 +813,9 @@
 
 	ACPI_FUNCTION_TRACE("irqrouter_resume");
 
+	/* Make sure SCI is enabled again (Apple firmware bug?) */
+	acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1, ACPI_MTX_DO_NOT_LOCK);
+
 	acpi_in_resume = 1;
 	list_for_each(node, &acpi_link.entries) {
 		link = list_entry(node, struct acpi_pci_link, node);
@@ -837,9 +841,9 @@
 
 	link = (struct acpi_pci_link *)acpi_driver_data(device);
 
-	down(&acpi_link_lock);
+	mutex_lock(&acpi_link_lock);
 	list_del(&link->node);
-	up(&acpi_link_lock);
+	mutex_unlock(&acpi_link_lock);
 
 	kfree(link);
 
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 713b763..decaebb 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -110,7 +110,7 @@
 };
 
 struct acpi_processor *processors[NR_CPUS];
-struct acpi_processor_errata errata;
+struct acpi_processor_errata errata __read_mostly;
 
 /* --------------------------------------------------------------------------
                                 Errata Handling
@@ -388,7 +388,7 @@
 
 /* Use the acpiid in MADT to map cpus in case of SMP */
 #ifndef CONFIG_SMP
-#define convert_acpiid_to_cpu(acpi_id) (0xff)
+#define convert_acpiid_to_cpu(acpi_id) (-1)
 #else
 
 #ifdef CONFIG_IA64
@@ -401,7 +401,7 @@
 #define ARCH_BAD_APICID		(0xff)
 #endif
 
-static u8 convert_acpiid_to_cpu(u8 acpi_id)
+static int convert_acpiid_to_cpu(u8 acpi_id)
 {
 	u16 apic_id;
 	int i;
@@ -427,7 +427,7 @@
 	acpi_status status = 0;
 	union acpi_object object = { 0 };
 	struct acpi_buffer buffer = { sizeof(union acpi_object), &object };
-	u8 cpu_index;
+	int cpu_index;
 	static int cpu0_initialized;
 
 	ACPI_FUNCTION_TRACE("acpi_processor_get_info");
@@ -473,7 +473,7 @@
 	cpu_index = convert_acpiid_to_cpu(pr->acpi_id);
 
 	/* Handle UP system running SMP kernel, with no LAPIC in MADT */
-	if (!cpu0_initialized && (cpu_index == 0xff) &&
+	if (!cpu0_initialized && (cpu_index == -1) &&
 	    (num_online_cpus() == 1)) {
 		cpu_index = 0;
 	}
@@ -487,7 +487,7 @@
 	 *  less than the max # of CPUs. They should be ignored _iff
 	 *  they are physically not present.
 	 */
-	if (cpu_index >= NR_CPUS) {
+	if (cpu_index == -1) {
 		if (ACPI_FAILURE
 		    (acpi_processor_hotadd_init(pr->handle, &pr->id))) {
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
@@ -558,8 +558,8 @@
 	 */
 	if (processor_device_array[pr->id] != NULL &&
 	    processor_device_array[pr->id] != (void *)device) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "BIOS reporting wrong ACPI id"
-			"for the processor\n"));
+		printk(KERN_WARNING "BIOS reported wrong ACPI id"
+			"for the processor\n");
 		return_VALUE(-ENODEV);
 	}
 	processor_device_array[pr->id] = (void *)device;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 80fa434..8a74bf3 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -54,10 +54,10 @@
 #define US_TO_PM_TIMER_TICKS(t)		((t * (PM_TIMER_FREQUENCY/1000)) / 1000)
 #define C2_OVERHEAD			4	/* 1us (3.579 ticks per us) */
 #define C3_OVERHEAD			4	/* 1us (3.579 ticks per us) */
-static void (*pm_idle_save) (void);
+static void (*pm_idle_save) (void) __read_mostly;
 module_param(max_cstate, uint, 0644);
 
-static unsigned int nocst = 0;
+static unsigned int nocst __read_mostly;
 module_param(nocst, uint, 0000);
 
 /*
@@ -67,7 +67,7 @@
  * 100 HZ: 0x0000000F: 4 jiffies = 40ms
  * reduce history for more aggressive entry into C3
  */
-static unsigned int bm_history =
+static unsigned int bm_history __read_mostly =
     (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1));
 module_param(bm_history, uint, 0644);
 /* --------------------------------------------------------------------------
@@ -206,11 +206,11 @@
 
 static void acpi_safe_halt(void)
 {
-	clear_thread_flag(TIF_POLLING_NRFLAG);
+	current_thread_info()->status &= ~TS_POLLING;
 	smp_mb__after_clear_bit();
 	if (!need_resched())
 		safe_halt();
-	set_thread_flag(TIF_POLLING_NRFLAG);
+	current_thread_info()->status |= TS_POLLING;
 }
 
 static atomic_t c3_cpu_count;
@@ -330,10 +330,10 @@
 	 * Invoke the current Cx state to put the processor to sleep.
 	 */
 	if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) {
-		clear_thread_flag(TIF_POLLING_NRFLAG);
+		current_thread_info()->status &= ~TS_POLLING;
 		smp_mb__after_clear_bit();
 		if (need_resched()) {
-			set_thread_flag(TIF_POLLING_NRFLAG);
+			current_thread_info()->status |= TS_POLLING;
 			local_irq_enable();
 			return;
 		}
@@ -369,9 +369,14 @@
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
 		/* Get end time (ticks) */
 		t2 = inl(acpi_fadt.xpm_tmr_blk.address);
+
+#ifdef CONFIG_GENERIC_TIME
+		/* TSC halts in C2, so notify users */
+		mark_tsc_unstable();
+#endif
 		/* Re-enable interrupts */
 		local_irq_enable();
-		set_thread_flag(TIF_POLLING_NRFLAG);
+		current_thread_info()->status |= TS_POLLING;
 		/* Compute time (ticks) that we were actually asleep */
 		sleep_ticks =
 		    ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD;
@@ -409,9 +414,13 @@
 					  ACPI_MTX_DO_NOT_LOCK);
 		}
 
+#ifdef CONFIG_GENERIC_TIME
+		/* TSC halts in C3, so notify users */
+		mark_tsc_unstable();
+#endif
 		/* Re-enable interrupts */
 		local_irq_enable();
-		set_thread_flag(TIF_POLLING_NRFLAG);
+		current_thread_info()->status |= TS_POLLING;
 		/* Compute time (ticks) that we were actually asleep */
 		sleep_ticks =
 		    ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD;
@@ -1081,7 +1090,7 @@
 			      struct acpi_device *device)
 {
 	acpi_status status = 0;
-	static int first_run = 0;
+	static int first_run;
 	struct proc_dir_entry *entry = NULL;
 	unsigned int i;
 
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index f36db22..41aaaba 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -34,6 +34,7 @@
 #ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 #endif
@@ -48,7 +49,7 @@
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("acpi_processor")
 
-static DECLARE_MUTEX(performance_sem);
+static DEFINE_MUTEX(performance_mutex);
 
 /*
  * _PPC support is implemented as a CPUfreq policy notifier:
@@ -72,7 +73,7 @@
 	struct acpi_processor *pr;
 	unsigned int ppc = 0;
 
-	down(&performance_sem);
+	mutex_lock(&performance_mutex);
 
 	if (event != CPUFREQ_INCOMPATIBLE)
 		goto out;
@@ -93,7 +94,7 @@
 				     core_frequency * 1000);
 
       out:
-	up(&performance_sem);
+	mutex_unlock(&performance_mutex);
 
 	return 0;
 }
@@ -553,6 +554,230 @@
 }
 #endif				/* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */
 
+static int acpi_processor_get_psd(struct acpi_processor	*pr)
+{
+	int result = 0;
+	acpi_status status = AE_OK;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
+	struct acpi_buffer state = {0, NULL};
+	union acpi_object  *psd = NULL;
+	struct acpi_psd_package *pdomain;
+
+	status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		return -ENODEV;
+	}
+
+	psd = (union acpi_object *) buffer.pointer;
+	if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	if (psd->package.count != 1) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	pdomain = &(pr->performance->domain_info);
+
+	state.length = sizeof(struct acpi_psd_package);
+	state.pointer = pdomain;
+
+	status = acpi_extract_package(&(psd->package.elements[0]),
+		&format, &state);
+	if (ACPI_FAILURE(status)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSD data\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:num_entries\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+	if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _PSD:revision\n"));
+		result = -EFAULT;
+		goto end;
+	}
+
+end:
+	acpi_os_free(buffer.pointer);
+	return result;
+}
+
+int acpi_processor_preregister_performance(
+		struct acpi_processor_performance **performance)
+{
+	int count, count_target;
+	int retval = 0;
+	unsigned int i, j;
+	cpumask_t covered_cpus;
+	struct acpi_processor *pr;
+	struct acpi_psd_package *pdomain;
+	struct acpi_processor *match_pr;
+	struct acpi_psd_package *match_pdomain;
+
+	mutex_lock(&performance_mutex);
+
+	retval = 0;
+
+	/* Call _PSD for all CPUs */
+	for_each_possible_cpu(i) {
+		pr = processors[i];
+		if (!pr) {
+			/* Look only at processors in ACPI namespace */
+			continue;
+		}
+
+		if (pr->performance) {
+			retval = -EBUSY;
+			continue;
+		}
+
+		if (!performance || !performance[i]) {
+			retval = -EINVAL;
+			continue;
+		}
+
+		pr->performance = performance[i];
+		cpu_set(i, pr->performance->shared_cpu_map);
+		if (acpi_processor_get_psd(pr)) {
+			retval = -EINVAL;
+			continue;
+		}
+	}
+	if (retval)
+		goto err_ret;
+
+	/*
+	 * Now that we have _PSD data from all CPUs, lets setup P-state 
+	 * domain info.
+	 */
+	for_each_possible_cpu(i) {
+		pr = processors[i];
+		if (!pr)
+			continue;
+
+		/* Basic validity check for domain info */
+		pdomain = &(pr->performance->domain_info);
+		if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
+		    (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) {
+			retval = -EINVAL;
+			goto err_ret;
+		}
+		if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
+		    pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
+		    pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
+			retval = -EINVAL;
+			goto err_ret;
+		}
+	}
+
+	cpus_clear(covered_cpus);
+	for_each_possible_cpu(i) {
+		pr = processors[i];
+		if (!pr)
+			continue;
+
+		if (cpu_isset(i, covered_cpus))
+			continue;
+
+		pdomain = &(pr->performance->domain_info);
+		cpu_set(i, pr->performance->shared_cpu_map);
+		cpu_set(i, covered_cpus);
+		if (pdomain->num_processors <= 1)
+			continue;
+
+		/* Validate the Domain info */
+		count_target = pdomain->num_processors;
+		count = 1;
+		if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL ||
+		    pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) {
+			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+		} else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) {
+			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+		}
+
+		for_each_possible_cpu(j) {
+			if (i == j)
+				continue;
+
+			match_pr = processors[j];
+			if (!match_pr)
+				continue;
+
+			match_pdomain = &(match_pr->performance->domain_info);
+			if (match_pdomain->domain != pdomain->domain)
+				continue;
+
+			/* Here i and j are in the same domain */
+
+			if (match_pdomain->num_processors != count_target) {
+				retval = -EINVAL;
+				goto err_ret;
+			}
+
+			if (pdomain->coord_type != match_pdomain->coord_type) {
+				retval = -EINVAL;
+				goto err_ret;
+			}
+
+			cpu_set(j, covered_cpus);
+			cpu_set(j, pr->performance->shared_cpu_map);
+			count++;
+		}
+
+		for_each_possible_cpu(j) {
+			if (i == j)
+				continue;
+
+			match_pr = processors[j];
+			if (!match_pr)
+				continue;
+
+			match_pdomain = &(match_pr->performance->domain_info);
+			if (match_pdomain->domain != pdomain->domain)
+				continue;
+
+			match_pr->performance->shared_type = 
+					pr->performance->shared_type;
+			match_pr->performance->shared_cpu_map =
+				pr->performance->shared_cpu_map;
+		}
+	}
+
+err_ret:
+	if (retval) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error while parsing _PSD domain information. Assuming no coordination\n"));
+	}
+
+	for_each_possible_cpu(i) {
+		pr = processors[i];
+		if (!pr || !pr->performance)
+			continue;
+
+		/* Assume no coordination on any error parsing domain info */
+		if (retval) {
+			cpus_clear(pr->performance->shared_cpu_map);
+			cpu_set(i, pr->performance->shared_cpu_map);
+			pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+		}
+		pr->performance = NULL; /* Will be set for real in register */
+	}
+
+	mutex_unlock(&performance_mutex);
+	return retval;
+}
+EXPORT_SYMBOL(acpi_processor_preregister_performance);
+
+
 int
 acpi_processor_register_performance(struct acpi_processor_performance
 				    *performance, unsigned int cpu)
@@ -564,16 +789,16 @@
 	if (!(acpi_processor_ppc_status & PPC_REGISTERED))
 		return_VALUE(-EINVAL);
 
-	down(&performance_sem);
+	mutex_lock(&performance_mutex);
 
 	pr = processors[cpu];
 	if (!pr) {
-		up(&performance_sem);
+		mutex_unlock(&performance_mutex);
 		return_VALUE(-ENODEV);
 	}
 
 	if (pr->performance) {
-		up(&performance_sem);
+		mutex_unlock(&performance_mutex);
 		return_VALUE(-EBUSY);
 	}
 
@@ -583,13 +808,13 @@
 
 	if (acpi_processor_get_performance_info(pr)) {
 		pr->performance = NULL;
-		up(&performance_sem);
+		mutex_unlock(&performance_mutex);
 		return_VALUE(-EIO);
 	}
 
 	acpi_cpufreq_add_file(pr);
 
-	up(&performance_sem);
+	mutex_unlock(&performance_mutex);
 	return_VALUE(0);
 }
 
@@ -603,11 +828,11 @@
 
 	ACPI_FUNCTION_TRACE("acpi_processor_unregister_performance");
 
-	down(&performance_sem);
+	mutex_lock(&performance_mutex);
 
 	pr = processors[cpu];
 	if (!pr) {
-		up(&performance_sem);
+		mutex_unlock(&performance_mutex);
 		return_VOID;
 	}
 
@@ -617,7 +842,7 @@
 
 	acpi_cpufreq_remove_file(pr);
 
-	up(&performance_sem);
+	mutex_unlock(&performance_mutex);
 
 	return_VOID;
 }
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 4038dbf..cf87b02 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -78,6 +78,7 @@
 	ACPI_FUNCTION_ENTRY();
 
 	for (bits_set = 0; bit_field; bits_set++) {
+
 		/* Zero the least significant bit that is set */
 
 		bit_field &= (bit_field - 1);
@@ -154,15 +155,18 @@
 	 * length, minus one byte for the resource_source_index itself.
 	 */
 	if (resource_length > minimum_aml_resource_length) {
+
 		/* Compute the length of the optional string */
 
 		string_length =
 		    resource_length - minimum_aml_resource_length - 1;
 	}
 
-	/* Round up length to 32 bits for internal structure alignment */
-
-	return (ACPI_ROUND_UP_to_32_bITS(string_length));
+	/*
+	 * Round the length up to a multiple of the native word in order to
+	 * guarantee that the entire resource descriptor is native word aligned
+	 */
+	return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
 }
 
 /*******************************************************************************
@@ -186,11 +190,12 @@
 	acpi_size aml_size_needed = 0;
 	acpi_rs_length total_size;
 
-	ACPI_FUNCTION_TRACE("rs_get_aml_length");
+	ACPI_FUNCTION_TRACE(rs_get_aml_length);
 
 	/* Traverse entire list of internal resource descriptors */
 
 	while (resource) {
+
 		/* Validate the descriptor type */
 
 		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
@@ -214,6 +219,7 @@
 			 * is a Large Resource data type.
 			 */
 			if (resource->data.vendor.byte_length > 7) {
+
 				/* Base size of a Large resource descriptor */
 
 				total_size =
@@ -332,20 +338,22 @@
 	acpi_status status;
 	u8 *end_aml;
 	u8 *buffer;
-	u32 buffer_size = 0;
+	u32 buffer_size;
 	u16 temp16;
 	u16 resource_length;
 	u32 extra_struct_bytes;
 	u8 resource_index;
 	u8 minimum_aml_resource_length;
 
-	ACPI_FUNCTION_TRACE("rs_get_list_length");
+	ACPI_FUNCTION_TRACE(rs_get_list_length);
 
+	*size_needed = 0;
 	end_aml = aml_buffer + aml_buffer_length;
 
 	/* Walk the list of AML resource descriptors */
 
 	while (aml_buffer < end_aml) {
+
 		/* Validate the Resource Type and Resource Length */
 
 		status = acpi_ut_validate_resource(aml_buffer, &resource_index);
@@ -386,35 +394,28 @@
 			break;
 
 		case ACPI_RESOURCE_NAME_VENDOR_SMALL:
+		case ACPI_RESOURCE_NAME_VENDOR_LARGE:
 			/*
 			 * Vendor Resource:
-			 * Ensure a 32-bit boundary for the structure
+			 * Get the number of vendor data bytes
 			 */
-			extra_struct_bytes =
-			    ACPI_ROUND_UP_to_32_bITS(resource_length);
+			extra_struct_bytes = resource_length;
 			break;
 
 		case ACPI_RESOURCE_NAME_END_TAG:
 			/*
-			 * End Tag: This is the normal exit, add size of end_tag
+			 * End Tag:
+			 * This is the normal exit, add size of end_tag
 			 */
-			*size_needed = buffer_size + ACPI_RS_SIZE_MIN;
+			*size_needed += ACPI_RS_SIZE_MIN;
 			return_ACPI_STATUS(AE_OK);
 
-		case ACPI_RESOURCE_NAME_VENDOR_LARGE:
-			/*
-			 * Vendor Resource:
-			 * Add vendor data and ensure a 32-bit boundary for the structure
-			 */
-			extra_struct_bytes =
-			    ACPI_ROUND_UP_to_32_bITS(resource_length);
-			break;
-
 		case ACPI_RESOURCE_NAME_ADDRESS32:
 		case ACPI_RESOURCE_NAME_ADDRESS16:
+		case ACPI_RESOURCE_NAME_ADDRESS64:
 			/*
-			 * 32-Bit or 16-bit Address Resource:
-			 * Add the size of any optional data (resource_source)
+			 * Address Resource:
+			 * Add the size of the optional resource_source
 			 */
 			extra_struct_bytes =
 			    acpi_rs_stream_option_length(resource_length,
@@ -423,50 +424,46 @@
 
 		case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
 			/*
-			 * Extended IRQ:
-			 * Point past the interrupt_vector_flags to get the
-			 * interrupt_table_length.
+			 * Extended IRQ Resource:
+			 * Using the interrupt_table_length, add 4 bytes for each additional
+			 * interrupt. Note: at least one interrupt is required and is
+			 * included in the minimum descriptor size (reason for the -1)
 			 */
-			buffer++;
+			extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
 
-			extra_struct_bytes =
-			    /*
-			     * Add 4 bytes for each additional interrupt. Note: at
-			     * least one interrupt is required and is included in
-			     * the minimum descriptor size
-			     */
-			    ((*buffer - 1) * sizeof(u32)) +
-			    /* Add the size of any optional data (resource_source) */
+			/* Add the size of the optional resource_source */
+
+			extra_struct_bytes +=
 			    acpi_rs_stream_option_length(resource_length -
 							 extra_struct_bytes,
 							 minimum_aml_resource_length);
 			break;
 
-		case ACPI_RESOURCE_NAME_ADDRESS64:
-			/*
-			 * 64-Bit Address Resource:
-			 * Add the size of any optional data (resource_source)
-			 * Ensure a 64-bit boundary for the structure
-			 */
-			extra_struct_bytes =
-			    ACPI_ROUND_UP_to_64_bITS
-			    (acpi_rs_stream_option_length
-			     (resource_length, minimum_aml_resource_length));
-			break;
-
 		default:
 			break;
 		}
 
-		/* Update the required buffer size for the internal descriptor structs */
+		/*
+		 * Update the required buffer size for the internal descriptor structs
+		 *
+		 * Important: Round the size up for the appropriate alignment. This
+		 * is a requirement on IA64.
+		 */
+		buffer_size = acpi_gbl_resource_struct_sizes[resource_index] +
+		    extra_struct_bytes;
+		buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
 
-		temp16 = (u16) (acpi_gbl_resource_struct_sizes[resource_index] +
-				extra_struct_bytes);
-		buffer_size += (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(temp16);
+		*size_needed += buffer_size;
+
+		ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
+				  "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
+				  acpi_ut_get_resource_type(aml_buffer),
+				  acpi_ut_get_descriptor_length(aml_buffer),
+				  buffer_size));
 
 		/*
-		 * Point to the next resource within the stream
-		 * using the size of the header plus the length contained in the header
+		 * Point to the next resource within the AML stream using the length
+		 * contained in the resource descriptor header
 		 */
 		aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
 	}
@@ -506,7 +503,7 @@
 	u8 name_found;
 	u32 table_index;
 
-	ACPI_FUNCTION_TRACE("rs_get_pci_routing_table_length");
+	ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
 
 	number_of_elements = package_object->package.count;
 
@@ -523,6 +520,7 @@
 	top_object_list = package_object->package.elements;
 
 	for (index = 0; index < number_of_elements; index++) {
+
 		/* Dereference the sub-package */
 
 		package_element = *top_object_list;
@@ -581,7 +579,7 @@
 
 		/* Round up the size since each element must be aligned */
 
-		temp_size_needed = ACPI_ROUND_UP_to_64_bITS(temp_size_needed);
+		temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
 
 		/* Point to the next union acpi_operand_object */
 
@@ -589,7 +587,7 @@
 	}
 
 	/*
-	 * Adding an extra element to the end of the list, essentially a
+	 * Add an extra element to the end of the list, essentially a
 	 * NULL terminator
 	 */
 	*buffer_size_needed =
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index 8c128de..008058a 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -75,10 +75,11 @@
 	u8 *aml_start;
 	acpi_size list_size_needed = 0;
 	u32 aml_buffer_length;
+	void *resource;
 
-	ACPI_FUNCTION_TRACE("rs_create_resource_list");
+	ACPI_FUNCTION_TRACE(rs_create_resource_list);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_buffer = %p\n", aml_buffer));
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer));
 
 	/* Params already validated, so we don't re-validate here */
 
@@ -92,7 +93,7 @@
 	status = acpi_rs_get_list_length(aml_start, aml_buffer_length,
 					 &list_size_needed);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X list_size_needed=%X\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n",
 			  status, (u32) list_size_needed));
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
@@ -107,13 +108,15 @@
 
 	/* Do the conversion */
 
-	status = acpi_rs_convert_aml_to_resources(aml_start, aml_buffer_length,
-						  output_buffer->pointer);
+	resource = output_buffer->pointer;
+	status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length,
+					    acpi_rs_convert_aml_to_resources,
+					    &resource);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
 			  output_buffer->pointer, (u32) output_buffer->length));
 	return_ACPI_STATUS(AE_OK);
 }
@@ -155,7 +158,7 @@
 	acpi_status status;
 	struct acpi_buffer path_buffer;
 
-	ACPI_FUNCTION_TRACE("rs_create_pci_routing_table");
+	ACPI_FUNCTION_TRACE(rs_create_pci_routing_table);
 
 	/* Params already validated, so we don't re-validate here */
 
@@ -167,7 +170,7 @@
 		return_ACPI_STATUS(status);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "buffer_size_needed = %X\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
 			  (u32) buffer_size_needed));
 
 	/* Validate/Allocate/Clear caller buffer */
@@ -332,7 +335,7 @@
 		/* Now align the current length */
 
 		user_prt->length =
-		    (u32) ACPI_ROUND_UP_to_64_bITS(user_prt->length);
+		    (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length);
 
 		/* 4) Fourth subobject: Dereference the PRT.source_index */
 
@@ -341,7 +344,7 @@
 			user_prt->source_index = (u32) obj_desc->integer.value;
 		} else {
 			ACPI_ERROR((AE_INFO,
-				    "(PRT[%X].source_index) Need Integer, found %s",
+				    "(PRT[%X].SourceIndex) Need Integer, found %s",
 				    index,
 				    acpi_ut_get_object_type_name(obj_desc)));
 			return_ACPI_STATUS(AE_BAD_DATA);
@@ -352,7 +355,7 @@
 		top_object_list++;
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
 			  output_buffer->pointer, (u32) output_buffer->length));
 	return_ACPI_STATUS(AE_OK);
 }
@@ -382,9 +385,9 @@
 	acpi_status status;
 	acpi_size aml_size_needed = 0;
 
-	ACPI_FUNCTION_TRACE("rs_create_aml_resources");
+	ACPI_FUNCTION_TRACE(rs_create_aml_resources);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "linked_list_buffer = %p\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n",
 			  linked_list_buffer));
 
 	/*
@@ -395,7 +398,7 @@
 	 */
 	status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed);
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "aml_size_needed=%X, %s\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
 			  (u32) aml_size_needed,
 			  acpi_format_exception(status)));
 	if (ACPI_FAILURE(status)) {
@@ -419,7 +422,7 @@
 		return_ACPI_STATUS(status);
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "output_buffer %p Length %X\n",
+	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
 			  output_buffer->pointer, (u32) output_buffer->length));
 	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index e7de061..9c99a72 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -91,11 +91,11 @@
 struct acpi_rsdump_info acpi_rs_dump_irq[6] = {
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_irq), "IRQ", NULL},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.triggering), "Triggering",
-	 acpi_gbl_HEdecode},
+	 acpi_gbl_he_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.polarity), "Polarity",
-	 acpi_gbl_LLdecode},
+	 acpi_gbl_ll_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(irq.sharable), "Sharing",
-	 acpi_gbl_SHRdecode},
+	 acpi_gbl_shr_decode},
 	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(irq.interrupt_count),
 	 "Interrupt Count", NULL},
 	{ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(irq.interrupts[0]),
@@ -105,11 +105,11 @@
 struct acpi_rsdump_info acpi_rs_dump_dma[6] = {
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_dma), "DMA", NULL},
 	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.type), "Speed",
-	 acpi_gbl_TYPdecode},
+	 acpi_gbl_typ_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(dma.bus_master), "Mastering",
-	 acpi_gbl_BMdecode},
+	 acpi_gbl_bm_decode},
 	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(dma.transfer), "Transfer Type",
-	 acpi_gbl_SIZdecode},
+	 acpi_gbl_siz_decode},
 	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(dma.channel_count), "Channel Count",
 	 NULL},
 	{ACPI_RSD_SHORTLIST, ACPI_RSD_OFFSET(dma.channels[0]), "Channel List",
@@ -158,7 +158,7 @@
 };
 
 struct acpi_rsdump_info acpi_rs_dump_end_tag[1] = {
-	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "end_tag",
+	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_end_tag), "EndTag",
 	 NULL}
 };
 
@@ -166,7 +166,7 @@
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory24),
 	 "24-Bit Memory Range", NULL},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory24.write_protect),
-	 "Write Protect", acpi_gbl_RWdecode},
+	 "Write Protect", acpi_gbl_rw_decode},
 	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.minimum), "Address Minimum",
 	 NULL},
 	{ACPI_RSD_UINT16, ACPI_RSD_OFFSET(memory24.maximum), "Address Maximum",
@@ -181,7 +181,7 @@
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory32),
 	 "32-Bit Memory Range", NULL},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(memory32.write_protect),
-	 "Write Protect", acpi_gbl_RWdecode},
+	 "Write Protect", acpi_gbl_rw_decode},
 	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.minimum), "Address Minimum",
 	 NULL},
 	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(memory32.maximum), "Address Maximum",
@@ -196,7 +196,7 @@
 	{ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_fixed_memory32),
 	 "32-Bit Fixed Memory Range", NULL},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(fixed_memory32.write_protect),
-	 "Write Protect", acpi_gbl_RWdecode},
+	 "Write Protect", acpi_gbl_rw_decode},
 	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address), "Address",
 	 NULL},
 	{ACPI_RSD_UINT32, ACPI_RSD_OFFSET(fixed_memory32.address_length),
@@ -278,11 +278,11 @@
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.producer_consumer),
 	 "Type", acpi_gbl_consume_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.triggering),
-	 "Triggering", acpi_gbl_HEdecode},
+	 "Triggering", acpi_gbl_he_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.polarity), "Polarity",
-	 acpi_gbl_LLdecode},
+	 acpi_gbl_ll_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(extended_irq.sharable), "Sharing",
-	 acpi_gbl_SHRdecode},
+	 acpi_gbl_shr_decode},
 	{ACPI_RSD_SOURCE, ACPI_RSD_OFFSET(extended_irq.resource_source), NULL,
 	 NULL},
 	{ACPI_RSD_UINT8, ACPI_RSD_OFFSET(extended_irq.interrupt_count),
@@ -314,7 +314,7 @@
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.producer_consumer),
 	 "Consumer/Producer", acpi_gbl_consume_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.decode), "Address Decode",
-	 acpi_gbl_DECdecode},
+	 acpi_gbl_dec_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.min_address_fixed),
 	 "Min Relocatability", acpi_gbl_min_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.max_address_fixed),
@@ -325,24 +325,24 @@
 	{ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_memory_flags),
 	 "Resource Type", (void *)"Memory Range"},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.write_protect),
-	 "Write Protect", acpi_gbl_RWdecode},
+	 "Write Protect", acpi_gbl_rw_decode},
 	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.caching),
-	 "Caching", acpi_gbl_MEMdecode},
+	 "Caching", acpi_gbl_mem_decode},
 	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.mem.range_type),
-	 "Range Type", acpi_gbl_MTPdecode},
+	 "Range Type", acpi_gbl_mtp_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.mem.translation),
-	 "Translation", acpi_gbl_TTPdecode}
+	 "Translation", acpi_gbl_ttp_decode}
 };
 
 static struct acpi_rsdump_info acpi_rs_dump_io_flags[4] = {
 	{ACPI_RSD_LITERAL, ACPI_RSD_TABLE_SIZE(acpi_rs_dump_io_flags),
 	 "Resource Type", (void *)"I/O Range"},
 	{ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET(address.info.io.range_type),
-	 "Range Type", acpi_gbl_RNGdecode},
+	 "Range Type", acpi_gbl_rng_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation),
-	 "Translation", acpi_gbl_TTPdecode},
+	 "Translation", acpi_gbl_ttp_decode},
 	{ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET(address.info.io.translation_type),
-	 "Translation Type", acpi_gbl_TRSdecode}
+	 "Translation Type", acpi_gbl_trs_decode}
 };
 
 /*
diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c
index d9ae64b..9e7ae2f 100644
--- a/drivers/acpi/resources/rsinfo.c
+++ b/drivers/acpi/resources/rsinfo.c
@@ -141,6 +141,7 @@
 	acpi_rs_dump_generic_reg,	/* ACPI_RESOURCE_TYPE_GENERIC_REGISTER */
 };
 #endif
+
 #endif	/* ACPI_FUTURE_USAGE */
 /*
  * Base sizes for external AML resource descriptors, indexed by internal type.
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index 1434e78..29423ce 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -51,76 +51,62 @@
  *
  * FUNCTION:    acpi_rs_convert_aml_to_resources
  *
- * PARAMETERS:  Aml                 - Pointer to the resource byte stream
- *              aml_length          - Length of Aml
- *              output_buffer       - Pointer to the buffer that will
- *                                    contain the output structures
+ * PARAMETERS:  acpi_walk_aml_callback
+ *              resource_ptr            - Pointer to the buffer that will
+ *                                        contain the output structures
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Takes the resource byte stream and parses it, creating a
- *              linked list of resources in the caller's output buffer
+ * DESCRIPTION: Convert an AML resource to an internal representation of the
+ *              resource that is aligned and easier to access.
  *
  ******************************************************************************/
 acpi_status
-acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer)
+acpi_rs_convert_aml_to_resources(u8 * aml,
+				 u32 length,
+				 u32 offset, u8 resource_index, void **context)
 {
-	struct acpi_resource *resource = (void *)output_buffer;
+	struct acpi_resource **resource_ptr =
+	    ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context);
+	struct acpi_resource *resource;
 	acpi_status status;
-	u8 resource_index;
-	u8 *end_aml;
 
-	ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources");
+	ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources);
 
-	end_aml = aml + aml_length;
-
-	/* Loop until end-of-buffer or an end_tag is found */
-
-	while (aml < end_aml) {
-		/* Validate the Resource Type and Resource Length */
-
-		status = acpi_ut_validate_resource(aml, &resource_index);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-
-		/* Convert the AML byte stream resource to a local resource struct */
-
-		status =
-		    acpi_rs_convert_aml_to_resource(resource,
-						    ACPI_CAST_PTR(union
-								  aml_resource,
-								  aml),
-						    acpi_gbl_get_resource_dispatch
-						    [resource_index]);
-		if (ACPI_FAILURE(status)) {
-			ACPI_EXCEPTION((AE_INFO, status,
-					"Could not convert AML resource (Type %X)",
-					*aml));
-			return_ACPI_STATUS(status);
-		}
-
-		/* Normal exit on completion of an end_tag resource descriptor */
-
-		if (acpi_ut_get_resource_type(aml) ==
-		    ACPI_RESOURCE_NAME_END_TAG) {
-			return_ACPI_STATUS(AE_OK);
-		}
-
-		/* Point to the next input AML resource */
-
-		aml += acpi_ut_get_descriptor_length(aml);
-
-		/* Point to the next structure in the output buffer */
-
-		resource =
-		    ACPI_ADD_PTR(struct acpi_resource, resource,
-				 resource->length);
+	/*
+	 * Check that the input buffer and all subsequent pointers into it
+	 * are aligned on a native word boundary. Most important on IA64
+	 */
+	resource = *resource_ptr;
+	if (ACPI_IS_MISALIGNED(resource)) {
+		ACPI_WARNING((AE_INFO,
+			      "Misaligned resource pointer %p", resource));
 	}
 
-	/* Did not find an end_tag resource descriptor */
+	/* Convert the AML byte stream resource to a local resource struct */
 
-	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+	status =
+	    acpi_rs_convert_aml_to_resource(resource,
+					    ACPI_CAST_PTR(union aml_resource,
+							  aml),
+					    acpi_gbl_get_resource_dispatch
+					    [resource_index]);
+	if (ACPI_FAILURE(status)) {
+		ACPI_EXCEPTION((AE_INFO, status,
+				"Could not convert AML resource (Type %X)",
+				*aml));
+		return_ACPI_STATUS(status);
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
+			  "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
+			  acpi_ut_get_resource_type(aml), length,
+			  resource->length));
+
+	/* Point to the next structure in the output buffer */
+
+	*resource_ptr = ACPI_ADD_PTR(void, resource, resource->length);
+	return_ACPI_STATUS(AE_OK);
 }
 
 /*******************************************************************************
@@ -150,11 +136,12 @@
 	u8 *end_aml = output_buffer + aml_size_needed;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml");
+	ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml);
 
 	/* Walk the resource descriptor list, convert each descriptor */
 
 	while (aml < end_aml) {
+
 		/* Validate the (internal) Resource Type */
 
 		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
@@ -191,6 +178,7 @@
 		/* Check for end-of-list, normal exit */
 
 		if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+
 			/* An End Tag indicates the end of the input Resource Template */
 
 			return_ACPI_STATUS(AE_OK);
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index ed866cf..faf6e10 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -81,9 +81,10 @@
 	u16 item_count = 0;
 	u16 temp16 = 0;
 
-	ACPI_FUNCTION_TRACE("rs_get_resource");
+	ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource);
 
 	if (((acpi_native_uint) resource) & 0x3) {
+
 		/* Each internal resource struct is expected to be 32-bit aligned */
 
 		ACPI_WARNING((AE_INFO,
@@ -295,9 +296,11 @@
 
       exit:
 	if (!flags_mode) {
-		/* Round the resource struct length up to the next 32-bit boundary */
 
-		resource->length = ACPI_ROUND_UP_to_32_bITS(resource->length);
+		/* Round the resource struct length up to the next boundary (32 or 64) */
+
+		resource->length =
+		    (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
 	}
 	return_ACPI_STATUS(AE_OK);
 }
@@ -329,7 +332,7 @@
 	u16 temp16 = 0;
 	u16 item_count = 0;
 
-	ACPI_FUNCTION_TRACE("rs_convert_resource_to_aml");
+	ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml);
 
 	/*
 	 * First table entry must be ACPI_RSC_INITxxx and must contain the
@@ -535,6 +538,7 @@
 
 resource->data.extended_irq.interrupt_count = temp8;
 if (temp8 < 1) {
+
 	/* Must have at least one IRQ */
 
 	return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 25b5aed..a9cbee8 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -205,6 +205,7 @@
 	/* Length is stored differently for large and small descriptors */
 
 	if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
+
 		/* Large descriptor -- bytes 1-2 contain the 16-bit length */
 
 		ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
@@ -298,7 +299,8 @@
  *              string_ptr          - (optional) where to store the actual
  *                                    resource_source string
  *
- * RETURN:      Length of the string plus NULL terminator, rounded up to 32 bit
+ * RETURN:      Length of the string plus NULL terminator, rounded up to native
+ *              word boundary
  *
  * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
  *              to an internal resource descriptor
@@ -328,6 +330,7 @@
 	 * we add 1 to the minimum length.
 	 */
 	if (total_length > (acpi_rsdesc_size) (minimum_length + 1)) {
+
 		/* Get the resource_source_index */
 
 		resource_source->index = aml_resource_source[0];
@@ -344,23 +347,26 @@
 		}
 
 		/*
-		 * In order for the struct_size to fall on a 32-bit boundary, calculate
-		 * the length of the string (+1 for the NULL terminator) and expand the
-		 * struct_size to the next 32-bit boundary.
+		 * In order for the Resource length to be a multiple of the native
+		 * word, calculate the length of the string (+1 for NULL terminator)
+		 * and expand to the next word multiple.
 		 *
 		 * Zero the entire area of the buffer.
 		 */
 		total_length =
-		    ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
-					     ((char *)&aml_resource_source[1]) +
-					     1);
+		    (u32)
+		    ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) +
+		    1;
+		total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length);
+
 		ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
 
 		/* Copy the resource_source string to the destination */
 
 		resource_source->string_length =
 		    acpi_rs_strcpy(resource_source->string_ptr,
-				   (char *)&aml_resource_source[1]);
+				   ACPI_CAST_PTR(char,
+						 &aml_resource_source[1]));
 
 		return ((acpi_rs_length) total_length);
 	}
@@ -405,6 +411,7 @@
 	/* Non-zero string length indicates presence of a resource_source */
 
 	if (resource_source->string_length) {
+
 		/* Point to the end of the AML descriptor */
 
 		aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
@@ -415,7 +422,7 @@
 
 		/* Copy the resource_source string */
 
-		ACPI_STRCPY((char *)&aml_resource_source[1],
+		ACPI_STRCPY(ACPI_CAST_PTR(char, &aml_resource_source[1]),
 			    resource_source->string_ptr);
 
 		/*
@@ -435,9 +442,9 @@
  *
  * FUNCTION:    acpi_rs_get_prt_method_data
  *
- * PARAMETERS:  Handle          - a handle to the containing object
- *              ret_buffer      - a pointer to a buffer structure for the
- *                                  results
+ * PARAMETERS:  Node            - Device node
+ *              ret_buffer      - Pointer to a buffer structure for the
+ *                                results
  *
  * RETURN:      Status
  *
@@ -450,18 +457,19 @@
  ******************************************************************************/
 
 acpi_status
-acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
+acpi_rs_get_prt_method_data(struct acpi_namespace_node * node,
+			    struct acpi_buffer * ret_buffer)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("rs_get_prt_method_data");
+	ACPI_FUNCTION_TRACE(rs_get_prt_method_data);
 
 	/* Parameters guaranteed valid by caller */
 
 	/* Execute the method, no parameters */
 
-	status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT,
+	status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT,
 					 ACPI_BTYPE_PACKAGE, &obj_desc);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
@@ -483,9 +491,9 @@
  *
  * FUNCTION:    acpi_rs_get_crs_method_data
  *
- * PARAMETERS:  Handle          - a handle to the containing object
- *              ret_buffer      - a pointer to a buffer structure for the
- *                                  results
+ * PARAMETERS:  Node            - Device node
+ *              ret_buffer      - Pointer to a buffer structure for the
+ *                                results
  *
  * RETURN:      Status
  *
@@ -498,18 +506,19 @@
  ******************************************************************************/
 
 acpi_status
-acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
+acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *ret_buffer)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("rs_get_crs_method_data");
+	ACPI_FUNCTION_TRACE(rs_get_crs_method_data);
 
 	/* Parameters guaranteed valid by caller */
 
 	/* Execute the method, no parameters */
 
-	status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS,
+	status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS,
 					 ACPI_BTYPE_BUFFER, &obj_desc);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
@@ -522,7 +531,7 @@
 	 */
 	status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
 
-	/* on exit, we must delete the object returned by evaluate_object */
+	/* On exit, we must delete the object returned by evaluate_object */
 
 	acpi_ut_remove_reference(obj_desc);
 	return_ACPI_STATUS(status);
@@ -532,9 +541,9 @@
  *
  * FUNCTION:    acpi_rs_get_prs_method_data
  *
- * PARAMETERS:  Handle          - a handle to the containing object
- *              ret_buffer      - a pointer to a buffer structure for the
- *                                  results
+ * PARAMETERS:  Node            - Device node
+ *              ret_buffer      - Pointer to a buffer structure for the
+ *                                results
  *
  * RETURN:      Status
  *
@@ -548,18 +557,19 @@
 
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
-acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
+acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *ret_buffer)
 {
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("rs_get_prs_method_data");
+	ACPI_FUNCTION_TRACE(rs_get_prs_method_data);
 
 	/* Parameters guaranteed valid by caller */
 
 	/* Execute the method, no parameters */
 
-	status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS,
+	status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS,
 					 ACPI_BTYPE_BUFFER, &obj_desc);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
@@ -572,7 +582,7 @@
 	 */
 	status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
 
-	/* on exit, we must delete the object returned by evaluate_object */
+	/* On exit, we must delete the object returned by evaluate_object */
 
 	acpi_ut_remove_reference(obj_desc);
 	return_ACPI_STATUS(status);
@@ -583,10 +593,10 @@
  *
  * FUNCTION:    acpi_rs_get_method_data
  *
- * PARAMETERS:  Handle          - a handle to the containing object
+ * PARAMETERS:  Handle          - Handle to the containing object
  *              Path            - Path to method, relative to Handle
- *              ret_buffer      - a pointer to a buffer structure for the
- *                                  results
+ *              ret_buffer      - Pointer to a buffer structure for the
+ *                                results
  *
  * RETURN:      Status
  *
@@ -605,7 +615,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("rs_get_method_data");
+	ACPI_FUNCTION_TRACE(rs_get_method_data);
 
 	/* Parameters guaranteed valid by caller */
 
@@ -634,9 +644,9 @@
  *
  * FUNCTION:    acpi_rs_set_srs_method_data
  *
- * PARAMETERS:  Handle          - a handle to the containing object
- *              in_buffer       - a pointer to a buffer structure of the
- *                                  parameter
+ * PARAMETERS:  Node            - Device node
+ *              in_buffer       - Pointer to a buffer structure of the
+ *                                parameter
  *
  * RETURN:      Status
  *
@@ -646,23 +656,37 @@
  *              If the function fails an appropriate status will be returned
  *              and the contents of the callers buffer is undefined.
  *
+ * Note: Parameters guaranteed valid by caller
+ *
  ******************************************************************************/
 
 acpi_status
-acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
+acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *in_buffer)
 {
-	struct acpi_parameter_info info;
-	union acpi_operand_object *params[2];
+	struct acpi_evaluate_info *info;
+	union acpi_operand_object *args[2];
 	acpi_status status;
 	struct acpi_buffer buffer;
 
-	ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
+	ACPI_FUNCTION_TRACE(rs_set_srs_method_data);
 
-	/* Parameters guaranteed valid by caller */
+	/* Allocate and initialize the evaluation information block */
+
+	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+	if (!info) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	info->prefix_node = node;
+	info->pathname = METHOD_NAME__SRS;
+	info->parameters = args;
+	info->parameter_type = ACPI_PARAM_ARGS;
+	info->flags = ACPI_IGNORE_RETURN_VALUE;
 
 	/*
 	 * The in_buffer parameter will point to a linked list of
-	 * resource parameters.  It needs to be formatted into a
+	 * resource parameters. It needs to be formatted into a
 	 * byte stream to be sent in as an input parameter to _SRS
 	 *
 	 * Convert the linked list into a byte stream
@@ -670,41 +694,36 @@
 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
 	status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
 	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
+		goto cleanup;
 	}
 
-	/* Init the param object */
+	/* Create and initialize the method parameter object */
 
-	params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
-	if (!params[0]) {
-		acpi_os_free(buffer.pointer);
-		return_ACPI_STATUS(AE_NO_MEMORY);
+	args[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
+	if (!args[0]) {
+		/*
+		 * Must free the buffer allocated above (otherwise it is freed
+		 * later)
+		 */
+		ACPI_FREE(buffer.pointer);
+		status = AE_NO_MEMORY;
+		goto cleanup;
 	}
 
-	/* Set up the parameter object */
+	args[0]->buffer.length = (u32) buffer.length;
+	args[0]->buffer.pointer = buffer.pointer;
+	args[0]->common.flags = AOPOBJ_DATA_VALID;
+	args[1] = NULL;
 
-	params[0]->buffer.length = (u32) buffer.length;
-	params[0]->buffer.pointer = buffer.pointer;
-	params[0]->common.flags = AOPOBJ_DATA_VALID;
-	params[1] = NULL;
+	/* Execute the method, no return value is expected */
 
-	info.node = handle;
-	info.parameters = params;
-	info.parameter_type = ACPI_PARAM_ARGS;
+	status = acpi_ns_evaluate(info);
 
-	/* Execute the method, no return value */
+	/* Clean up and return the status from acpi_ns_evaluate */
 
-	status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info);
-	if (ACPI_SUCCESS(status)) {
-		/* Delete any return object (especially if implicit_return is enabled) */
+	acpi_ut_remove_reference(args[0]);
 
-		if (info.return_object) {
-			acpi_ut_remove_reference(info.return_object);
-		}
-	}
-
-	/* Clean up and return the status from acpi_ns_evaluate_relative */
-
-	acpi_ut_remove_reference(params[0]);
+      cleanup:
+	ACPI_FREE(info);
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 88b6707..1999e2a 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -41,10 +41,9 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acresrc.h>
+#include <acpi/acnamesp.h>
 
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rsxface")
@@ -68,19 +67,80 @@
 static acpi_status
 acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
 
+static acpi_status
+acpi_rs_validate_parameters(acpi_handle device_handle,
+			    struct acpi_buffer *buffer,
+			    struct acpi_namespace_node **return_node);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_rs_validate_parameters
+ *
+ * PARAMETERS:  device_handle   - Handle to a device
+ *              Buffer          - Pointer to a data buffer
+ *              return_node     - Pointer to where the device node is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Common parameter validation for resource interfaces
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_rs_validate_parameters(acpi_handle device_handle,
+			    struct acpi_buffer *buffer,
+			    struct acpi_namespace_node **return_node)
+{
+	acpi_status status;
+	struct acpi_namespace_node *node;
+
+	ACPI_FUNCTION_TRACE(rs_validate_parameters);
+
+	/*
+	 * Must have a valid handle to an ACPI device
+	 */
+	if (!device_handle) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	node = acpi_ns_map_handle_to_node(device_handle);
+	if (!node) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	if (node->type != ACPI_TYPE_DEVICE) {
+		return_ACPI_STATUS(AE_TYPE);
+	}
+
+	/*
+	 * Validate the user buffer object
+	 *
+	 * if there is a non-zero buffer length we also need a valid pointer in
+	 * the buffer. If it's a zero buffer length, we'll be returning the
+	 * needed buffer size (later), so keep going.
+	 */
+	status = acpi_ut_validate_buffer(buffer);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	*return_node = node;
+	return_ACPI_STATUS(AE_OK);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_irq_routing_table
  *
- * PARAMETERS:  device_handle   - a handle to the Bus device we are querying
- *              ret_buffer      - a pointer to a buffer to receive the
+ * PARAMETERS:  device_handle   - Handle to the Bus device we are querying
+ *              ret_buffer      - Pointer to a buffer to receive the
  *                                current resources for the device
  *
  * RETURN:      Status
  *
  * DESCRIPTION: This function is called to get the IRQ routing table for a
- *              specific bus.  The caller must first acquire a handle for the
- *              desired bus.  The routine table is placed in the buffer pointed
+ *              specific bus. The caller must first acquire a handle for the
+ *              desired bus. The routine table is placed in the buffer pointed
  *              to by the ret_buffer variable parameter.
  *
  *              If the function fails an appropriate status will be returned
@@ -96,42 +156,37 @@
 			   struct acpi_buffer *ret_buffer)
 {
 	acpi_status status;
+	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("acpi_get_irq_routing_table ");
+	ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);
 
-	/*
-	 * Must have a valid handle and buffer, So we have to have a handle
-	 * and a return buffer structure, and if there is a non-zero buffer length
-	 * we also need a valid pointer in the buffer. If it's a zero buffer length,
-	 * we'll be returning the needed buffer size, so keep going.
-	 */
-	if (!device_handle) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
+	/* Validate parameters then dispatch to internal routine */
 
-	status = acpi_ut_validate_buffer(ret_buffer);
+	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
-	status = acpi_rs_get_prt_method_data(device_handle, ret_buffer);
+	status = acpi_rs_get_prt_method_data(node, ret_buffer);
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_current_resources
  *
- * PARAMETERS:  device_handle   - a handle to the device object for the
+ * PARAMETERS:  device_handle   - Handle to the device object for the
  *                                device we are querying
- *              ret_buffer      - a pointer to a buffer to receive the
+ *              ret_buffer      - Pointer to a buffer to receive the
  *                                current resources for the device
  *
  * RETURN:      Status
  *
  * DESCRIPTION: This function is called to get the current resources for a
- *              specific device.  The caller must first acquire a handle for
- *              the desired device.  The resource data is placed in the buffer
+ *              specific device. The caller must first acquire a handle for
+ *              the desired device. The resource data is placed in the buffer
  *              pointed to by the ret_buffer variable parameter.
  *
  *              If the function fails an appropriate status will be returned
@@ -141,239 +196,133 @@
  *              the object indicated by the passed device_handle.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_current_resources(acpi_handle device_handle,
 			   struct acpi_buffer *ret_buffer)
 {
 	acpi_status status;
+	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("acpi_get_current_resources");
+	ACPI_FUNCTION_TRACE(acpi_get_current_resources);
 
-	/*
-	 * Must have a valid handle and buffer, So we have to have a handle
-	 * and a return buffer structure, and if there is a non-zero buffer length
-	 * we also need a valid pointer in the buffer. If it's a zero buffer length,
-	 * we'll be returning the needed buffer size, so keep going.
-	 */
-	if (!device_handle) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
+	/* Validate parameters then dispatch to internal routine */
 
-	status = acpi_ut_validate_buffer(ret_buffer);
+	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
-	status = acpi_rs_get_crs_method_data(device_handle, ret_buffer);
+	status = acpi_rs_get_crs_method_data(node, ret_buffer);
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_current_resources);
+ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
 
+#ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_possible_resources
  *
- * PARAMETERS:  device_handle   - a handle to the device object for the
+ * PARAMETERS:  device_handle   - Handle to the device object for the
  *                                device we are querying
- *              ret_buffer      - a pointer to a buffer to receive the
+ *              ret_buffer      - Pointer to a buffer to receive the
  *                                resources for the device
  *
  * RETURN:      Status
  *
  * DESCRIPTION: This function is called to get a list of the possible resources
- *              for a specific device.  The caller must first acquire a handle
- *              for the desired device.  The resource data is placed in the
+ *              for a specific device. The caller must first acquire a handle
+ *              for the desired device. The resource data is placed in the
  *              buffer pointed to by the ret_buffer variable.
  *
  *              If the function fails an appropriate status will be returned
  *              and the value of ret_buffer is undefined.
  *
  ******************************************************************************/
-
-#ifdef ACPI_FUTURE_USAGE
 acpi_status
 acpi_get_possible_resources(acpi_handle device_handle,
 			    struct acpi_buffer *ret_buffer)
 {
 	acpi_status status;
+	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("acpi_get_possible_resources");
+	ACPI_FUNCTION_TRACE(acpi_get_possible_resources);
 
-	/*
-	 * Must have a valid handle and buffer, So we have to have a handle
-	 * and a return buffer structure, and if there is a non-zero buffer length
-	 * we also need a valid pointer in the buffer. If it's a zero buffer length,
-	 * we'll be returning the needed buffer size, so keep going.
-	 */
-	if (!device_handle) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
+	/* Validate parameters then dispatch to internal routine */
 
-	status = acpi_ut_validate_buffer(ret_buffer);
+	status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
-	status = acpi_rs_get_prs_method_data(device_handle, ret_buffer);
+	status = acpi_rs_get_prs_method_data(node, ret_buffer);
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_possible_resources);
+ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
 #endif				/*  ACPI_FUTURE_USAGE  */
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_walk_resources
- *
- * PARAMETERS:  device_handle   - Handle to the device object for the
- *                                device we are querying
- *              Name            - Method name of the resources we want
- *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
- *              user_function   - Called for each resource
- *              Context         - Passed to user_function
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Retrieves the current or possible resource list for the
- *              specified device.  The user_function is called once for
- *              each resource in the list.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_walk_resources(acpi_handle device_handle,
-		    char *name,
-		    ACPI_WALK_RESOURCE_CALLBACK user_function, void *context)
-{
-	acpi_status status;
-	struct acpi_buffer buffer;
-	struct acpi_resource *resource;
-	struct acpi_resource *resource_end;
-
-	ACPI_FUNCTION_TRACE("acpi_walk_resources");
-
-	/* Parameter validation */
-
-	if (!device_handle || !user_function || !name ||
-	    (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
-	     ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
-	}
-
-	/* Get the _CRS or _PRS resource list */
-
-	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
-	status = acpi_rs_get_method_data(device_handle, name, &buffer);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	/* Buffer now contains the resource list */
-
-	resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
-	resource_end =
-	    ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
-
-	/* Walk the resource list until the end_tag is found (or buffer end) */
-
-	while (resource < resource_end) {
-		/* Sanity check the resource */
-
-		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
-			status = AE_AML_INVALID_RESOURCE_TYPE;
-			break;
-		}
-
-		/* Invoke the user function, abort on any error returned */
-
-		status = user_function(resource, context);
-		if (ACPI_FAILURE(status)) {
-			if (status == AE_CTRL_TERMINATE) {
-				/* This is an OK termination by the user function */
-
-				status = AE_OK;
-			}
-			break;
-		}
-
-		/* end_tag indicates end-of-list */
-
-		if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
-			break;
-		}
-
-		/* Get the next resource descriptor */
-
-		resource =
-		    ACPI_ADD_PTR(struct acpi_resource, resource,
-				 resource->length);
-	}
-
-	ACPI_MEM_FREE(buffer.pointer);
-	return_ACPI_STATUS(status);
-}
-
-EXPORT_SYMBOL(acpi_walk_resources);
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_set_current_resources
  *
- * PARAMETERS:  device_handle   - a handle to the device object for the
- *                                device we are changing the resources of
- *              in_buffer       - a pointer to a buffer containing the
+ * PARAMETERS:  device_handle   - Handle to the device object for the
+ *                                device we are setting resources
+ *              in_buffer       - Pointer to a buffer containing the
  *                                resources to be set for the device
  *
  * RETURN:      Status
  *
  * DESCRIPTION: This function is called to set the current resources for a
- *              specific device.  The caller must first acquire a handle for
- *              the desired device.  The resource data is passed to the routine
+ *              specific device. The caller must first acquire a handle for
+ *              the desired device. The resource data is passed to the routine
  *              the buffer pointed to by the in_buffer variable.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_set_current_resources(acpi_handle device_handle,
 			   struct acpi_buffer *in_buffer)
 {
 	acpi_status status;
+	struct acpi_namespace_node *node;
 
-	ACPI_FUNCTION_TRACE("acpi_set_current_resources");
+	ACPI_FUNCTION_TRACE(acpi_set_current_resources);
 
-	/* Must have a valid handle and buffer */
+	/* Validate the buffer, don't allow zero length */
 
-	if ((!device_handle) ||
-	    (!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
+	if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	status = acpi_rs_set_srs_method_data(device_handle, in_buffer);
+	/* Validate parameters then dispatch to internal routine */
+
+	status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	status = acpi_rs_set_srs_method_data(node, in_buffer);
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_set_current_resources);
+ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
 
 /******************************************************************************
  *
  * FUNCTION:    acpi_resource_to_address64
  *
- * PARAMETERS:  Resource                - Pointer to a resource
- *              Out                     - Pointer to the users's return
- *                                        buffer (a struct
- *                                        struct acpi_resource_address64)
+ * PARAMETERS:  Resource        - Pointer to a resource
+ *              Out             - Pointer to the users's return buffer
+ *                                (a struct acpi_resource_address64)
  *
  * RETURN:      Status
  *
  * DESCRIPTION: If the resource is an address16, address32, or address64,
- *              copy it to the address64 return buffer.  This saves the
+ *              copy it to the address64 return buffer. This saves the
  *              caller from having to duplicate code for different-sized
  *              addresses.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_resource_to_address64(struct acpi_resource *resource,
 			   struct acpi_resource_address64 *out)
@@ -415,18 +364,18 @@
 	return (AE_OK);
 }
 
-EXPORT_SYMBOL(acpi_resource_to_address64);
+ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_vendor_resource
  *
- * PARAMETERS:  device_handle       - Handle for the parent device object
- *              Name                - Method name for the parent resource
- *                                    (METHOD_NAME__CRS or METHOD_NAME__PRS)
- *              Uuid                - Pointer to the UUID to be matched.
- *                                    includes both subtype and 16-byte UUID
- *              ret_buffer          - Where the vendor resource is returned
+ * PARAMETERS:  device_handle   - Handle for the parent device object
+ *              Name            - Method name for the parent resource
+ *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ *              Uuid            - Pointer to the UUID to be matched.
+ *                                includes both subtype and 16-byte UUID
+ *              ret_buffer      - Where the vendor resource is returned
  *
  * RETURN:      Status
  *
@@ -435,7 +384,6 @@
  *              UUID subtype. Returns a struct acpi_resource of type Vendor.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_vendor_resource(acpi_handle device_handle,
 			 char *name,
@@ -467,18 +415,19 @@
 	return (info.status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_rs_match_vendor_resource
  *
- * PARAMETERS:  ACPI_WALK_RESOURCE_CALLBACK
+ * PARAMETERS:  acpi_walk_resource_callback
  *
  * RETURN:      Status
  *
  * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
  *
  ******************************************************************************/
-
 static acpi_status
 acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
 {
@@ -526,3 +475,101 @@
 	info->status = AE_OK;
 	return (AE_CTRL_TERMINATE);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_rs_match_vendor_resource)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_walk_resources
+ *
+ * PARAMETERS:  device_handle   - Handle to the device object for the
+ *                                device we are querying
+ *              Name            - Method name of the resources we want
+ *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
+ *              user_function   - Called for each resource
+ *              Context         - Passed to user_function
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Retrieves the current or possible resource list for the
+ *              specified device. The user_function is called once for
+ *              each resource in the list.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_walk_resources(acpi_handle device_handle,
+		    char *name,
+		    acpi_walk_resource_callback user_function, void *context)
+{
+	acpi_status status;
+	struct acpi_buffer buffer;
+	struct acpi_resource *resource;
+	struct acpi_resource *resource_end;
+
+	ACPI_FUNCTION_TRACE(acpi_walk_resources);
+
+	/* Parameter validation */
+
+	if (!device_handle || !user_function || !name ||
+	    (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) &&
+	     !ACPI_COMPARE_NAME(name, METHOD_NAME__PRS))) {
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+	}
+
+	/* Get the _CRS or _PRS resource list */
+
+	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+	status = acpi_rs_get_method_data(device_handle, name, &buffer);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	/* Buffer now contains the resource list */
+
+	resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
+	resource_end =
+	    ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
+
+	/* Walk the resource list until the end_tag is found (or buffer end) */
+
+	while (resource < resource_end) {
+
+		/* Sanity check the resource */
+
+		if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
+			status = AE_AML_INVALID_RESOURCE_TYPE;
+			break;
+		}
+
+		/* Invoke the user function, abort on any error returned */
+
+		status = user_function(resource, context);
+		if (ACPI_FAILURE(status)) {
+			if (status == AE_CTRL_TERMINATE) {
+
+				/* This is an OK termination by the user function */
+
+				status = AE_OK;
+			}
+			break;
+		}
+
+		/* end_tag indicates end-of-list */
+
+		if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
+			break;
+		}
+
+		/* Get the next resource descriptor */
+
+		resource =
+		    ACPI_ADD_PTR(struct acpi_resource, resource,
+				 resource->length);
+	}
+
+	ACPI_FREE(buffer.pointer);
+	return_ACPI_STATUS(status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_walk_resources)
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index a0ab828..f8316a0 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -142,7 +142,7 @@
 	create_sysfs_device_files(device);
 }
 
-static int acpi_device_unregister(struct acpi_device *device, int type)
+static void acpi_device_unregister(struct acpi_device *device, int type)
 {
 	spin_lock(&acpi_device_lock);
 	if (device->parent) {
@@ -158,7 +158,6 @@
 	acpi_detach_data(device->handle, acpi_bus_data_handler);
 	remove_sysfs_device_files(device);
 	kobject_unregister(&device->kobj);
-	return 0;
 }
 
 void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context)
@@ -234,12 +233,9 @@
 
 int acpi_match_ids(struct acpi_device *device, char *ids)
 {
-	int error = 0;
-	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-
 	if (device->flags.hardware_id)
 		if (strstr(ids, device->pnp.hardware_id))
-			goto Done;
+			return 0;
 
 	if (device->flags.compatible_ids) {
 		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
@@ -248,15 +244,10 @@
 		/* compare multiple _CID entries against driver ids */
 		for (i = 0; i < cid_list->count; i++) {
 			if (strstr(ids, cid_list->id[i].value))
-				goto Done;
+				return 0;
 		}
 	}
-	error = -ENOENT;
-
-      Done:
-	if (buffer.pointer)
-		acpi_os_free(buffer.pointer);
-	return error;
+	return -ENOENT;
 }
 
 static acpi_status
@@ -441,10 +432,7 @@
 	islockable = device->flags.lockable;
 	handle = device->handle;
 
-	if (type == ACPI_TYPE_PROCESSOR)
-		result = acpi_bus_trim(device, 0);
-	else
-		result = acpi_bus_trim(device, 1);
+	result = acpi_bus_trim(device, 1);
 
 	if (!result)
 		result = acpi_eject_operation(handle, islockable);
@@ -471,7 +459,6 @@
    -------------------------------------------------------------------------- */
 
 static LIST_HEAD(acpi_bus_drivers);
-static DECLARE_MUTEX(acpi_bus_drivers_lock);
 
 /**
  * acpi_bus_match - match device IDs to driver's supported IDs
@@ -548,10 +535,9 @@
 	return_VALUE(result);
 }
 
-static int acpi_driver_attach(struct acpi_driver *drv)
+static void acpi_driver_attach(struct acpi_driver *drv)
 {
 	struct list_head *node, *next;
-	int count = 0;
 
 	ACPI_FUNCTION_TRACE("acpi_driver_attach");
 
@@ -568,7 +554,6 @@
 			if (!acpi_bus_driver_init(dev, drv)) {
 				acpi_start_single_object(dev);
 				atomic_inc(&drv->references);
-				count++;
 				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 						  "Found driver [%s] for device [%s]\n",
 						  drv->name, dev->pnp.bus_id));
@@ -577,10 +562,9 @@
 		spin_lock(&acpi_device_lock);
 	}
 	spin_unlock(&acpi_device_lock);
-	return_VALUE(count);
 }
 
-static int acpi_driver_detach(struct acpi_driver *drv)
+static void acpi_driver_detach(struct acpi_driver *drv)
 {
 	struct list_head *node, *next;
 
@@ -602,7 +586,6 @@
 		}
 	}
 	spin_unlock(&acpi_device_lock);
-	return_VALUE(0);
 }
 
 /**
@@ -610,28 +593,22 @@
  * @driver: driver being registered
  *
  * Registers a driver with the ACPI bus.  Searches the namespace for all
- * devices that match the driver's criteria and binds.  Returns the
- * number of devices that were claimed by the driver, or a negative
- * error status for failure.
+ * devices that match the driver's criteria and binds.  Returns zero for
+ * success or a negative error status for failure.
  */
 int acpi_bus_register_driver(struct acpi_driver *driver)
 {
-	int count;
-
 	ACPI_FUNCTION_TRACE("acpi_bus_register_driver");
 
 	if (acpi_disabled)
 		return_VALUE(-ENODEV);
 
-	if (!driver)
-		return_VALUE(-EINVAL);
-
 	spin_lock(&acpi_device_lock);
 	list_add_tail(&driver->node, &acpi_bus_drivers);
 	spin_unlock(&acpi_device_lock);
-	count = acpi_driver_attach(driver);
+	acpi_driver_attach(driver);
 
-	return_VALUE(count);
+	return_VALUE(0);
 }
 
 EXPORT_SYMBOL(acpi_bus_register_driver);
@@ -643,23 +620,16 @@
  * Unregisters a driver with the ACPI bus.  Searches the namespace for all
  * devices that match the driver's criteria and unbinds.
  */
-int acpi_bus_unregister_driver(struct acpi_driver *driver)
+void acpi_bus_unregister_driver(struct acpi_driver *driver)
 {
-	int error = 0;
+	acpi_driver_detach(driver);
 
-	ACPI_FUNCTION_TRACE("acpi_bus_unregister_driver");
-
-	if (driver) {
-		acpi_driver_detach(driver);
-
-		if (!atomic_read(&driver->references)) {
-			spin_lock(&acpi_device_lock);
-			list_del_init(&driver->node);
-			spin_unlock(&acpi_device_lock);
-		}
-	} else
-		error = -EINVAL;
-	return_VALUE(error);
+	if (!atomic_read(&driver->references)) {
+		spin_lock(&acpi_device_lock);
+		list_del_init(&driver->node);
+		spin_unlock(&acpi_device_lock);
+	}
+	return;
 }
 
 EXPORT_SYMBOL(acpi_bus_unregister_driver);
@@ -1371,6 +1341,100 @@
 	return_VALUE(result);
 }
 
+
+static inline struct acpi_device * to_acpi_dev(struct device * dev)
+{
+	return container_of(dev, struct acpi_device, dev);
+}
+
+
+static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state)
+{
+	struct acpi_device * dev, * next;
+	int result;
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) {
+		if (dev->driver && dev->driver->ops.suspend) {
+			spin_unlock(&acpi_device_lock);
+			result = dev->driver->ops.suspend(dev, 0);
+			if (result) {
+				printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n",
+				       acpi_device_name(dev),
+				       acpi_device_bid(dev), result);
+			}
+			spin_lock(&acpi_device_lock);
+		}
+	}
+	spin_unlock(&acpi_device_lock);
+	return 0;
+}
+
+
+static int acpi_device_suspend(struct device * dev, pm_message_t state)
+{
+	struct acpi_device * acpi_dev = to_acpi_dev(dev);
+
+	/*
+	 * For now, we should only register 1 generic device -
+	 * the ACPI root device - and from there, we walk the
+	 * tree of ACPI devices to suspend each one using the
+	 * ACPI driver methods.
+	 */
+	if (acpi_dev->handle == ACPI_ROOT_OBJECT)
+		root_suspend(acpi_dev, state);
+	return 0;
+}
+
+
+
+static int root_resume(struct acpi_device * acpi_dev)
+{
+	struct acpi_device * dev, * next;
+	int result;
+
+	spin_lock(&acpi_device_lock);
+	list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) {
+		if (dev->driver && dev->driver->ops.resume) {
+			spin_unlock(&acpi_device_lock);
+			result = dev->driver->ops.resume(dev, 0);
+			if (result) {
+				printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n",
+				       acpi_device_name(dev),
+				       acpi_device_bid(dev), result);
+			}
+			spin_lock(&acpi_device_lock);
+		}
+	}
+	spin_unlock(&acpi_device_lock);
+	return 0;
+}
+
+
+static int acpi_device_resume(struct device * dev)
+{
+	struct acpi_device * acpi_dev = to_acpi_dev(dev);
+
+	/*
+	 * For now, we should only register 1 generic device -
+	 * the ACPI root device - and from there, we walk the
+	 * tree of ACPI devices to resume each one using the
+	 * ACPI driver methods.
+	 */
+	if (acpi_dev->handle == ACPI_ROOT_OBJECT)
+		root_resume(acpi_dev);
+	return 0;
+}
+
+
+struct bus_type acpi_bus_type = {
+	.name		= "acpi",
+	.suspend	= acpi_device_suspend,
+	.resume		= acpi_device_resume,
+};
+
+
+
 static int __init acpi_scan_init(void)
 {
 	int result;
@@ -1383,6 +1447,12 @@
 
 	kset_register(&acpi_namespace_kset);
 
+	result = bus_register(&acpi_bus_type);
+	if (result) {
+		/* We don't want to quit even if we failed to add suspend/resume */
+		printk(KERN_ERR PREFIX "Could not register bus type\n");
+	}
+
 	/*
 	 * Create the root device in the bus's device tree
 	 */
@@ -1392,6 +1462,16 @@
 		goto Done;
 
 	result = acpi_start_single_object(acpi_root);
+	if (result)
+		goto Done;
+
+	acpi_root->dev.bus = &acpi_bus_type;
+	snprintf(acpi_root->dev.bus_id, BUS_ID_SIZE, "%s", acpi_bus_type.name);
+	result = device_register(&acpi_root->dev);
+	if (result) {
+		/* We don't want to quit even if we failed to add suspend/resume */
+		printk(KERN_ERR PREFIX "Could not register device\n");
+	}
 
 	/*
 	 * Enumerate devices in the ACPI namespace.
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 930427f..62ce87d 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -105,6 +105,14 @@
 	default:
 		return -EINVAL;
 	}
+
+	/* ACPI 3.0 specs (P62) says that it's the responsabilty
+	 * of the OSPM to clear the status bit [ implying that the
+	 * POWER_BUTTON event should not reach userspace ]
+	 */
+	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3))
+		acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
+
 	local_irq_restore(flags);
 	printk(KERN_DEBUG "Back to C!\n");
 
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c
index 85df0ce..af1dbab 100644
--- a/drivers/acpi/sleep/wakeup.c
+++ b/drivers/acpi/sleep/wakeup.c
@@ -155,7 +155,6 @@
 
 	if (acpi_disabled)
 		return 0;
-	printk("ACPI wakeup devices: \n");
 
 	spin_lock(&acpi_device_lock);
 	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
@@ -174,10 +173,8 @@
 			dev->wakeup.state.enabled = 1;
 			spin_lock(&acpi_device_lock);
 		}
-		printk("%4s ", dev->pnp.bus_id);
 	}
 	spin_unlock(&acpi_device_lock);
-	printk("\n");
 
 	return 0;
 }
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index e4308c7..a934ac4 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -39,7 +39,7 @@
 #define ACPI_SYSTEM_FILE_EVENT		"event"
 #define ACPI_SYSTEM_FILE_DSDT		"dsdt"
 #define ACPI_SYSTEM_FILE_FADT		"fadt"
-extern FADT_DESCRIPTOR acpi_fadt;
+extern struct fadt_descriptor acpi_fadt;
 
 /* --------------------------------------------------------------------------
                               FS Interface (/proc)
@@ -82,7 +82,7 @@
 
 	ACPI_FUNCTION_TRACE("acpi_system_read_dsdt");
 
-	status = acpi_get_table(ACPI_TABLE_DSDT, 1, &dsdt);
+	status = acpi_get_table(ACPI_TABLE_ID_DSDT, 1, &dsdt);
 	if (ACPI_FAILURE(status))
 		return_VALUE(-ENODEV);
 
@@ -110,7 +110,7 @@
 
 	ACPI_FUNCTION_TRACE("acpi_system_read_fadt");
 
-	status = acpi_get_table(ACPI_TABLE_FADT, 1, &fadt);
+	status = acpi_get_table(ACPI_TABLE_ID_FADT, 1, &fadt);
 	if (ACPI_FAILURE(status))
 		return_VALUE(-ENODEV);
 
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 7f37c7c..ed5e881 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -282,8 +282,8 @@
 
 	/* Map the DSDT header via the pointer in the FADT */
 	if (id == ACPI_DSDT) {
-		struct fadt_descriptor_rev2 *fadt =
-		    (struct fadt_descriptor_rev2 *)*header;
+		struct fadt_descriptor *fadt =
+		    (struct fadt_descriptor *)*header;
 
 		if (fadt->revision == 3 && fadt->Xdsdt) {
 			*header = (void *)__acpi_map_table(fadt->Xdsdt,
diff --git a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c
index 03b37d2..d697fcb 100644
--- a/drivers/acpi/tables/tbconvrt.c
+++ b/drivers/acpi/tables/tbconvrt.c
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/actables.h>
 
@@ -56,15 +54,15 @@
 			     acpi_physical_address address);
 
 static void
-acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
+acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt,
 		      struct fadt_descriptor_rev1 *original_fadt);
 
 static void
-acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt,
-		      struct fadt_descriptor_rev2 *original_fadt);
+acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt,
+		      struct fadt_descriptor *original_fadt);
 
 u8 acpi_fadt_is_v1;
-EXPORT_SYMBOL(acpi_fadt_is_v1);
+ACPI_EXPORT_SYMBOL(acpi_fadt_is_v1)
 
 /*******************************************************************************
  *
@@ -122,7 +120,7 @@
 {
 	acpi_size table_size;
 	u32 i;
-	XSDT_DESCRIPTOR *new_table;
+	struct xsdt_descriptor *new_table;
 
 	ACPI_FUNCTION_ENTRY();
 
@@ -133,7 +131,7 @@
 
 	/* Allocate an XSDT */
 
-	new_table = ACPI_MEM_CALLOCATE(table_size);
+	new_table = ACPI_ALLOCATE_ZEROED(table_size);
 	if (!new_table) {
 		return (AE_NO_MEMORY);
 	}
@@ -147,17 +145,18 @@
 	/* Copy the table pointers */
 
 	for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
+
 		/* RSDT pointers are 32 bits, XSDT pointers are 64 bits */
 
 		if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
 			ACPI_STORE_ADDRESS(new_table->table_offset_entry[i],
 					   (ACPI_CAST_PTR
-					    (struct rsdt_descriptor_rev1,
+					    (struct rsdt_descriptor,
 					     table_info->pointer))->
 					   table_offset_entry[i]);
 		} else {
 			new_table->table_offset_entry[i] =
-			    (ACPI_CAST_PTR(XSDT_DESCRIPTOR,
+			    (ACPI_CAST_PTR(struct xsdt_descriptor,
 					   table_info->pointer))->
 			    table_offset_entry[i];
 		}
@@ -219,7 +218,7 @@
  ******************************************************************************/
 
 static void
-acpi_tb_convert_fadt1(struct fadt_descriptor_rev2 *local_fadt,
+acpi_tb_convert_fadt1(struct fadt_descriptor *local_fadt,
 		      struct fadt_descriptor_rev1 *original_fadt)
 {
 
@@ -365,14 +364,13 @@
  ******************************************************************************/
 
 static void
-acpi_tb_convert_fadt2(struct fadt_descriptor_rev2 *local_fadt,
-		      struct fadt_descriptor_rev2 *original_fadt)
+acpi_tb_convert_fadt2(struct fadt_descriptor *local_fadt,
+		      struct fadt_descriptor *original_fadt)
 {
 
 	/* We have an ACPI 2.0 FADT but we must copy it to our local buffer */
 
-	ACPI_MEMCPY(local_fadt, original_fadt,
-		    sizeof(struct fadt_descriptor_rev2));
+	ACPI_MEMCPY(local_fadt, original_fadt, sizeof(struct fadt_descriptor));
 
 	/*
 	 * "X" fields are optional extensions to the original V1.0 fields, so
@@ -491,10 +489,10 @@
 
 acpi_status acpi_tb_convert_table_fadt(void)
 {
-	struct fadt_descriptor_rev2 *local_fadt;
+	struct fadt_descriptor *local_fadt;
 	struct acpi_table_desc *table_desc;
 
-	ACPI_FUNCTION_TRACE("tb_convert_table_fadt");
+	ACPI_FUNCTION_TRACE(tb_convert_table_fadt);
 
 	/*
 	 * acpi_gbl_FADT is valid. Validate the FADT length. The table must be
@@ -508,13 +506,14 @@
 
 	/* Allocate buffer for the ACPI 2.0(+) FADT */
 
-	local_fadt = ACPI_MEM_CALLOCATE(sizeof(struct fadt_descriptor_rev2));
+	local_fadt = ACPI_ALLOCATE_ZEROED(sizeof(struct fadt_descriptor));
 	if (!local_fadt) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
 	if (acpi_gbl_FADT->revision >= FADT2_REVISION_ID) {
-		if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor_rev2)) {
+		if (acpi_gbl_FADT->length < sizeof(struct fadt_descriptor)) {
+
 			/* Length is too short to be a V2.0 table */
 
 			ACPI_WARNING((AE_INFO,
@@ -538,11 +537,11 @@
 	/* Global FADT pointer will point to the new common V2.0 FADT */
 
 	acpi_gbl_FADT = local_fadt;
-	acpi_gbl_FADT->length = sizeof(FADT_DESCRIPTOR);
+	acpi_gbl_FADT->length = sizeof(struct fadt_descriptor);
 
 	/* Free the original table */
 
-	table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next;
+	table_desc = acpi_gbl_table_lists[ACPI_TABLE_ID_FADT].next;
 	acpi_tb_delete_single_table(table_desc);
 
 	/* Install the new table */
@@ -550,7 +549,7 @@
 	table_desc->pointer =
 	    ACPI_CAST_PTR(struct acpi_table_header, acpi_gbl_FADT);
 	table_desc->allocation = ACPI_MEM_ALLOCATED;
-	table_desc->length = sizeof(struct fadt_descriptor_rev2);
+	table_desc->length = sizeof(struct fadt_descriptor);
 
 	/* Dump the entire FADT */
 
@@ -580,7 +579,7 @@
 acpi_status acpi_tb_build_common_facs(struct acpi_table_desc *table_info)
 {
 
-	ACPI_FUNCTION_TRACE("tb_build_common_facs");
+	ACPI_FUNCTION_TRACE(tb_build_common_facs);
 
 	/* Absolute minimum length is 24, but the ACPI spec says 64 */
 
@@ -603,6 +602,7 @@
 	if ((acpi_gbl_RSDP->revision < 2) ||
 	    (acpi_gbl_FACS->length < 32) ||
 	    (!(acpi_gbl_FACS->xfirmware_waking_vector))) {
+
 		/* ACPI 1.0 FACS or short table or optional X_ field is zero */
 
 		acpi_gbl_common_fACS.firmware_waking_vector = ACPI_CAST_PTR(u64,
diff --git a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c
index 09b4ee6..99eacce 100644
--- a/drivers/acpi/tables/tbget.c
+++ b/drivers/acpi/tables/tbget.c
@@ -78,7 +78,7 @@
 	acpi_status status;
 	struct acpi_table_header header;
 
-	ACPI_FUNCTION_TRACE("tb_get_table");
+	ACPI_FUNCTION_TRACE(tb_get_table);
 
 	/* Get the header in order to get signature and table size */
 
@@ -124,7 +124,7 @@
 	acpi_status status = AE_OK;
 	struct acpi_table_header *header = NULL;
 
-	ACPI_FUNCTION_TRACE("tb_get_table_header");
+	ACPI_FUNCTION_TRACE(tb_get_table_header);
 
 	/*
 	 * Flags contains the current processor mode (Virtual or Physical
@@ -148,6 +148,10 @@
 					    sizeof(struct acpi_table_header),
 					    (void *)&header);
 		if (ACPI_FAILURE(status)) {
+			ACPI_ERROR((AE_INFO,
+				    "Could not map memory at %8.8X%8.8X for table header",
+				    ACPI_FORMAT_UINT64(address->pointer.
+						       physical)));
 			return_ACPI_STATUS(status);
 		}
 
@@ -198,7 +202,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("tb_get_table_body");
+	ACPI_FUNCTION_TRACE(tb_get_table_body);
 
 	if (!table_info || !address) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -208,6 +212,7 @@
 
 	status = acpi_tb_table_override(header, table_info);
 	if (ACPI_SUCCESS(status)) {
+
 		/* Table was overridden by the host OS */
 
 		return_ACPI_STATUS(status);
@@ -241,7 +246,7 @@
 	acpi_status status;
 	struct acpi_pointer address;
 
-	ACPI_FUNCTION_TRACE("tb_table_override");
+	ACPI_FUNCTION_TRACE(tb_table_override);
 
 	/*
 	 * The OSL will examine the header and decide whether to override this
@@ -250,6 +255,7 @@
 	 */
 	status = acpi_os_table_override(header, &new_table);
 	if (ACPI_FAILURE(status)) {
+
 		/* Some severe error from the OSL, but we basically ignore it */
 
 		ACPI_EXCEPTION((AE_INFO, status,
@@ -258,6 +264,7 @@
 	}
 
 	if (!new_table) {
+
 		/* No table override */
 
 		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
@@ -311,7 +318,7 @@
 	u8 allocation;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("tb_get_this_table");
+	ACPI_FUNCTION_TRACE(tb_get_this_table);
 
 	/*
 	 * Flags contains the current processor mode (Virtual or Physical
@@ -323,7 +330,7 @@
 
 		/* Pointer matches processor mode, copy the table to a new buffer */
 
-		full_table = ACPI_MEM_ALLOCATE(header->length);
+		full_table = ACPI_ALLOCATE(header->length);
 		if (!full_table) {
 			ACPI_ERROR((AE_INFO,
 				    "Could not allocate table memory for [%4.4s] length %X",
@@ -376,11 +383,12 @@
 	 * Validate checksum for _most_ tables,
 	 * even the ones whose signature we don't recognize
 	 */
-	if (table_info->type != ACPI_TABLE_FACS) {
+	if (table_info->type != ACPI_TABLE_ID_FACS) {
 		status = acpi_tb_verify_table_checksum(full_table);
 
 #if (!ACPI_CHECKSUM_ABORT)
 		if (ACPI_FAILURE(status)) {
+
 			/* Ignore the error if configuration says so */
 
 			status = AE_OK;
@@ -409,7 +417,7 @@
  *
  * PARAMETERS:  table_type      - one of the defined table types
  *              Instance        - Which table of this type
- *              table_ptr_loc   - pointer to location to place the pointer for
+ *              return_table    - pointer to location to place the pointer for
  *                                return
  *
  * RETURN:      Status
@@ -420,57 +428,34 @@
 
 acpi_status
 acpi_tb_get_table_ptr(acpi_table_type table_type,
-		      u32 instance, struct acpi_table_header **table_ptr_loc)
+		      u32 instance, struct acpi_table_header **return_table)
 {
 	struct acpi_table_desc *table_desc;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("tb_get_table_ptr");
+	ACPI_FUNCTION_TRACE(tb_get_table_ptr);
 
-	if (!acpi_gbl_DSDT) {
-		return_ACPI_STATUS(AE_NO_ACPI_TABLES);
-	}
-
-	if (table_type > ACPI_TABLE_MAX) {
+	if (table_type > ACPI_TABLE_ID_MAX) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
-	/*
-	 * For all table types (Single/Multiple), the first
-	 * instance is always in the list head.
-	 */
-	if (instance == 1) {
-		/* Get the first */
-
-		*table_ptr_loc = NULL;
-		if (acpi_gbl_table_lists[table_type].next) {
-			*table_ptr_loc =
-			    acpi_gbl_table_lists[table_type].next->pointer;
-		}
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	/* Check for instance out of range */
+	/* Check for instance out of range of the current table count */
 
 	if (instance > acpi_gbl_table_lists[table_type].count) {
 		return_ACPI_STATUS(AE_NOT_EXIST);
 	}
 
-	/* Walk the list to get the desired table
-	 * Since the if (Instance == 1) check above checked for the
-	 * first table, setting table_desc equal to the .Next member
-	 * is actually pointing to the second table.  Therefore, we
-	 * need to walk from the 2nd table until we reach the Instance
-	 * that the user is looking for and return its table pointer.
+	/*
+	 * Walk the list to get the desired table
+	 * Note: Instance is one-based
 	 */
 	table_desc = acpi_gbl_table_lists[table_type].next;
-	for (i = 2; i < instance; i++) {
+	for (i = 1; i < instance; i++) {
 		table_desc = table_desc->next;
 	}
 
 	/* We are now pointing to the requested table's descriptor */
 
-	*table_ptr_loc = table_desc->pointer;
-
+	*return_table = table_desc->pointer;
 	return_ACPI_STATUS(AE_OK);
 }
diff --git a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c
index 134e5dc..ad982112 100644
--- a/drivers/acpi/tables/tbgetall.c
+++ b/drivers/acpi/tables/tbgetall.c
@@ -77,7 +77,7 @@
 	acpi_status status;
 	struct acpi_table_header header;
 
-	ACPI_FUNCTION_TRACE("tb_get_primary_table");
+	ACPI_FUNCTION_TRACE(tb_get_primary_table);
 
 	/* Ignore a NULL address in the RSDT */
 
@@ -140,7 +140,7 @@
 	acpi_status status;
 	struct acpi_table_header header;
 
-	ACPI_FUNCTION_TRACE_STR("tb_get_secondary_table", signature);
+	ACPI_FUNCTION_TRACE_STR(tb_get_secondary_table, signature);
 
 	/* Get the header in order to match the signature */
 
@@ -151,7 +151,7 @@
 
 	/* Signature must match request */
 
-	if (ACPI_STRNCMP(header.signature, signature, ACPI_NAME_SIZE)) {
+	if (!ACPI_COMPARE_NAME(header.signature, signature)) {
 		ACPI_ERROR((AE_INFO,
 			    "Incorrect table signature - wanted [%s] found [%4.4s]",
 			    signature, header.signature));
@@ -207,7 +207,7 @@
 	struct acpi_table_desc table_info;
 	struct acpi_pointer address;
 
-	ACPI_FUNCTION_TRACE("tb_get_required_tables");
+	ACPI_FUNCTION_TRACE(tb_get_required_tables);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%d ACPI tables in RSDT\n",
 			  acpi_gbl_rsdt_table_count));
@@ -223,6 +223,7 @@
 	 * any SSDTs.
 	 */
 	for (i = 0; i < acpi_gbl_rsdt_table_count; i++) {
+
 		/* Get the table address from the common internal XSDT */
 
 		address.pointer.value = acpi_gbl_XSDT->table_offset_entry[i];
@@ -305,6 +306,6 @@
 
 	/* Always delete the RSDP mapping, we are done with it */
 
-	acpi_tb_delete_tables_by_type(ACPI_TABLE_RSDP);
+	acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_RSDP);
 	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c
index 7ffd0fd..7ca2df7 100644
--- a/drivers/acpi/tables/tbinstal.c
+++ b/drivers/acpi/tables/tbinstal.c
@@ -73,17 +73,18 @@
 {
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE("tb_match_signature");
+	ACPI_FUNCTION_TRACE(tb_match_signature);
 
 	/* Search for a signature match among the known table types */
 
-	for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
+	for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
 		if (!(acpi_gbl_table_data[i].flags & search_type)) {
 			continue;
 		}
 
 		if (!ACPI_STRNCMP(signature, acpi_gbl_table_data[i].signature,
 				  acpi_gbl_table_data[i].sig_length)) {
+
 			/* Found a signature match, return index if requested */
 
 			if (table_info) {
@@ -122,7 +123,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("tb_install_table");
+	ACPI_FUNCTION_TRACE(tb_install_table);
 
 	/* Lock tables while installing */
 
@@ -187,7 +188,7 @@
 	struct acpi_table_header *table_header;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("tb_recognize_table");
+	ACPI_FUNCTION_TRACE(tb_recognize_table);
 
 	/* Ensure that we have a valid table pointer */
 
@@ -218,7 +219,6 @@
 	/* Return the table type and length via the info struct */
 
 	table_info->length = (acpi_size) table_header->length;
-
 	return_ACPI_STATUS(status);
 }
 
@@ -243,11 +243,11 @@
 	struct acpi_table_desc *table_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_U32("tb_init_table_descriptor", table_type);
+	ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type);
 
 	/* Allocate a descriptor for this table */
 
-	table_desc = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
+	table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc));
 	if (!table_desc) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -274,7 +274,7 @@
 		 * at this location, so return an error.
 		 */
 		if (list_head->next) {
-			ACPI_MEM_FREE(table_desc);
+			ACPI_FREE(table_desc);
 			return_ACPI_STATUS(AE_ALREADY_EXISTS);
 		}
 
@@ -312,15 +312,14 @@
 
 	/* Finish initialization of the table descriptor */
 
+	table_desc->loaded_into_namespace = FALSE;
 	table_desc->type = (u8) table_type;
 	table_desc->pointer = table_info->pointer;
 	table_desc->length = table_info->length;
 	table_desc->allocation = table_info->allocation;
 	table_desc->aml_start = (u8 *) (table_desc->pointer + 1),
-	    table_desc->aml_length = (u32) (table_desc->length -
-					    (u32) sizeof(struct
-							 acpi_table_header));
-	table_desc->loaded_into_namespace = FALSE;
+	    table_desc->aml_length = (u32)
+	    (table_desc->length - (u32) sizeof(struct acpi_table_header));
 
 	/*
 	 * Set the appropriate global pointer (if there is one) to point to the
@@ -335,7 +334,6 @@
 
 	table_info->owner_id = table_desc->owner_id;
 	table_info->installed_desc = table_desc;
-
 	return_ACPI_STATUS(AE_OK);
 }
 
@@ -359,7 +357,7 @@
 	 * Free memory allocated for ACPI tables
 	 * Memory can either be mapped or allocated
 	 */
-	for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) {
+	for (type = 0; type < (ACPI_TABLE_ID_MAX + 1); type++) {
 		acpi_tb_delete_tables_by_type(type);
 	}
 }
@@ -383,9 +381,9 @@
 	u32 count;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE_U32("tb_delete_tables_by_type", type);
+	ACPI_FUNCTION_TRACE_U32(tb_delete_tables_by_type, type);
 
-	if (type > ACPI_TABLE_MAX) {
+	if (type > ACPI_TABLE_ID_MAX) {
 		return_VOID;
 	}
 
@@ -396,28 +394,28 @@
 	/* Clear the appropriate "typed" global table pointer */
 
 	switch (type) {
-	case ACPI_TABLE_RSDP:
+	case ACPI_TABLE_ID_RSDP:
 		acpi_gbl_RSDP = NULL;
 		break;
 
-	case ACPI_TABLE_DSDT:
+	case ACPI_TABLE_ID_DSDT:
 		acpi_gbl_DSDT = NULL;
 		break;
 
-	case ACPI_TABLE_FADT:
+	case ACPI_TABLE_ID_FADT:
 		acpi_gbl_FADT = NULL;
 		break;
 
-	case ACPI_TABLE_FACS:
+	case ACPI_TABLE_ID_FACS:
 		acpi_gbl_FACS = NULL;
 		break;
 
-	case ACPI_TABLE_XSDT:
+	case ACPI_TABLE_ID_XSDT:
 		acpi_gbl_XSDT = NULL;
 		break;
 
-	case ACPI_TABLE_SSDT:
-	case ACPI_TABLE_PSDT:
+	case ACPI_TABLE_ID_SSDT:
+	case ACPI_TABLE_ID_PSDT:
 	default:
 		break;
 	}
@@ -471,7 +469,7 @@
 
 	case ACPI_MEM_ALLOCATED:
 
-		ACPI_MEM_FREE(table_desc->pointer);
+		ACPI_FREE(table_desc->pointer);
 		break;
 
 	case ACPI_MEM_MAPPED:
@@ -503,7 +501,7 @@
 {
 	struct acpi_table_desc *next_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("tb_uninstall_table", table_desc);
+	ACPI_FUNCTION_TRACE_PTR(tb_uninstall_table, table_desc);
 
 	if (!table_desc) {
 		return_PTR(NULL);
@@ -530,7 +528,7 @@
 	/* Free the table descriptor */
 
 	next_desc = table_desc->next;
-	ACPI_MEM_FREE(table_desc);
+	ACPI_FREE(table_desc);
 
 	/* Return pointer to the next descriptor */
 
diff --git a/drivers/acpi/tables/tbrsdt.c b/drivers/acpi/tables/tbrsdt.c
index 4d30822..abcb08c 100644
--- a/drivers/acpi/tables/tbrsdt.c
+++ b/drivers/acpi/tables/tbrsdt.c
@@ -64,7 +64,7 @@
 	acpi_status status;
 	struct rsdp_descriptor *rsdp;
 
-	ACPI_FUNCTION_TRACE("tb_verify_rsdp");
+	ACPI_FUNCTION_TRACE(tb_verify_rsdp);
 
 	switch (address->pointer_type) {
 	case ACPI_LOGICAL_POINTER:
@@ -78,7 +78,7 @@
 		 */
 		status = acpi_os_map_memory(address->pointer.physical,
 					    sizeof(struct rsdp_descriptor),
-					    (void *)&rsdp);
+					    ACPI_CAST_PTR(void, &rsdp));
 		if (ACPI_FAILURE(status)) {
 			return_ACPI_STATUS(status);
 		}
@@ -95,15 +95,20 @@
 		goto cleanup;
 	}
 
-	/* The RSDP supplied is OK */
+	/* RSDP is ok. Init the table info */
 
 	table_info.pointer = ACPI_CAST_PTR(struct acpi_table_header, rsdp);
 	table_info.length = sizeof(struct rsdp_descriptor);
-	table_info.allocation = ACPI_MEM_MAPPED;
+
+	if (address->pointer_type == ACPI_PHYSICAL_POINTER) {
+		table_info.allocation = ACPI_MEM_MAPPED;
+	} else {
+		table_info.allocation = ACPI_MEM_NOT_ALLOCATED;
+	}
 
 	/* Save the table pointers and allocation info */
 
-	status = acpi_tb_init_table_descriptor(ACPI_TABLE_RSDP, &table_info);
+	status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_RSDP, &table_info);
 	if (ACPI_FAILURE(status)) {
 		goto cleanup;
 	}
@@ -174,22 +179,20 @@
 
 acpi_status acpi_tb_validate_rsdt(struct acpi_table_header *table_ptr)
 {
-	int no_match;
+	char *signature;
 
 	ACPI_FUNCTION_ENTRY();
 
-	/*
-	 * Search for appropriate signature, RSDT or XSDT
-	 */
+	/* Search for appropriate signature, RSDT or XSDT */
+
 	if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
-		no_match = ACPI_STRNCMP((char *)table_ptr, RSDT_SIG,
-					sizeof(RSDT_SIG) - 1);
+		signature = RSDT_SIG;
 	} else {
-		no_match = ACPI_STRNCMP((char *)table_ptr, XSDT_SIG,
-					sizeof(XSDT_SIG) - 1);
+		signature = XSDT_SIG;
 	}
 
-	if (no_match) {
+	if (!ACPI_COMPARE_NAME(table_ptr->signature, signature)) {
+
 		/* Invalid RSDT or XSDT signature */
 
 		ACPI_ERROR((AE_INFO,
@@ -198,10 +201,8 @@
 		ACPI_DUMP_BUFFER(acpi_gbl_RSDP, 20);
 
 		ACPI_ERROR((AE_INFO,
-			    "RSDT/XSDT signature at %X (%p) is invalid",
-			    acpi_gbl_RSDP->rsdt_physical_address,
-			    (void *)(acpi_native_uint) acpi_gbl_RSDP->
-			    rsdt_physical_address));
+			    "RSDT/XSDT signature at %X is invalid",
+			    acpi_gbl_RSDP->rsdt_physical_address));
 
 		if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
 			ACPI_ERROR((AE_INFO, "Looking for RSDT"));
@@ -234,13 +235,13 @@
 	acpi_status status;
 	struct acpi_pointer address;
 
-	ACPI_FUNCTION_TRACE("tb_get_table_rsdt");
+	ACPI_FUNCTION_TRACE(tb_get_table_rsdt);
 
 	/* Get the RSDT/XSDT via the RSDP */
 
 	acpi_tb_get_rsdt_address(&address);
 
-	table_info.type = ACPI_TABLE_XSDT;
+	table_info.type = ACPI_TABLE_ID_XSDT;
 	status = acpi_tb_get_table(&address, &table_info);
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status,
@@ -274,12 +275,13 @@
 
 	/* Save the table pointers and allocation info */
 
-	status = acpi_tb_init_table_descriptor(ACPI_TABLE_XSDT, &table_info);
+	status = acpi_tb_init_table_descriptor(ACPI_TABLE_ID_XSDT, &table_info);
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
 	}
 
-	acpi_gbl_XSDT = ACPI_CAST_PTR(XSDT_DESCRIPTOR, table_info.pointer);
+	acpi_gbl_XSDT =
+	    ACPI_CAST_PTR(struct xsdt_descriptor, table_info.pointer);
 
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "XSDT located at %p\n", acpi_gbl_XSDT));
 	return_ACPI_STATUS(status);
diff --git a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c
index bc57159..209a401 100644
--- a/drivers/acpi/tables/tbutils.c
+++ b/drivers/acpi/tables/tbutils.c
@@ -71,7 +71,7 @@
 {
 	struct acpi_table_desc *table_desc;
 
-	ACPI_FUNCTION_TRACE("tb_is_table_installed");
+	ACPI_FUNCTION_TRACE(tb_is_table_installed);
 
 	/* Get the list descriptor and first table descriptor */
 
@@ -96,10 +96,11 @@
 		    (!ACPI_MEMCMP
 		     (table_desc->pointer, new_table_desc->pointer,
 		      new_table_desc->pointer->length))) {
+
 			/* Match: this table is already installed */
 
 			ACPI_DEBUG_PRINT((ACPI_DB_TABLES,
-					  "Table [%4.4s] already installed: Rev %X oem_table_id [%8.8s]\n",
+					  "Table [%4.4s] already installed: Rev %X OemTableId [%8.8s]\n",
 					  new_table_desc->pointer->signature,
 					  new_table_desc->pointer->revision,
 					  new_table_desc->pointer->
@@ -159,12 +160,8 @@
 
 	ACPI_MOVE_32_TO_32(&signature, table_header->signature);
 	if (!acpi_ut_valid_acpi_name(signature)) {
-		ACPI_ERROR((AE_INFO,
-			    "Table signature at %p [%p] has invalid characters",
-			    table_header, &signature));
-
-		ACPI_WARNING((AE_INFO, "Invalid table signature found: [%4.4s]",
-			      ACPI_CAST_PTR(char, &signature)));
+		ACPI_ERROR((AE_INFO, "Invalid table signature 0x%8.8X",
+			    signature));
 
 		ACPI_DUMP_BUFFER(table_header,
 				 sizeof(struct acpi_table_header));
@@ -175,12 +172,9 @@
 
 	if (table_header->length < sizeof(struct acpi_table_header)) {
 		ACPI_ERROR((AE_INFO,
-			    "Invalid length in table header %p name %4.4s",
-			    table_header, (char *)&signature));
-
-		ACPI_WARNING((AE_INFO,
-			      "Invalid table header length (0x%X) found",
-			      (u32) table_header->length));
+			    "Invalid length 0x%X in table with signature %4.4s",
+			    (u32) table_header->length,
+			    ACPI_CAST_PTR(char, &signature)));
 
 		ACPI_DUMP_BUFFER(table_header,
 				 sizeof(struct acpi_table_header));
@@ -192,72 +186,119 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_tb_verify_table_checksum
+ * FUNCTION:    acpi_tb_sum_table
  *
- * PARAMETERS:  *table_header           - ACPI table to verify
+ * PARAMETERS:  Buffer              - Buffer to sum
+ *              Length              - Size of the buffer
  *
- * RETURN:      8 bit checksum of table
+ * RETURN:      8 bit sum of buffer
  *
- * DESCRIPTION: Does an 8 bit checksum of table and returns status.  A correct
- *              table should have a checksum of 0.
+ * DESCRIPTION: Computes an 8 bit sum of the buffer(length) and returns it.
  *
  ******************************************************************************/
 
-acpi_status
-acpi_tb_verify_table_checksum(struct acpi_table_header * table_header)
+u8 acpi_tb_sum_table(void *buffer, u32 length)
 {
-	u8 checksum;
-	acpi_status status = AE_OK;
+	acpi_native_uint i;
+	u8 sum = 0;
 
-	ACPI_FUNCTION_TRACE("tb_verify_table_checksum");
-
-	/* Compute the checksum on the table */
-
-	checksum =
-	    acpi_tb_generate_checksum(table_header, table_header->length);
-
-	/* Return the appropriate exception */
-
-	if (checksum) {
-		ACPI_WARNING((AE_INFO,
-			      "Invalid checksum in table [%4.4s] (%02X, sum %02X is not zero)",
-			      table_header->signature,
-			      (u32) table_header->checksum, (u32) checksum));
-
-		status = AE_BAD_CHECKSUM;
+	if (!buffer || !length) {
+		return (0);
 	}
-	return_ACPI_STATUS(status);
+
+	for (i = 0; i < length; i++) {
+		sum = (u8) (sum + ((u8 *) buffer)[i]);
+	}
+	return (sum);
 }
 
 /*******************************************************************************
  *
  * FUNCTION:    acpi_tb_generate_checksum
  *
- * PARAMETERS:  Buffer              - Buffer to checksum
- *              Length              - Size of the buffer
+ * PARAMETERS:  Table               - Pointer to a valid ACPI table (with a
+ *                                    standard ACPI header)
  *
  * RETURN:      8 bit checksum of buffer
  *
- * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it.
+ * DESCRIPTION: Computes an 8 bit checksum of the table.
  *
  ******************************************************************************/
 
-u8 acpi_tb_generate_checksum(void *buffer, u32 length)
+u8 acpi_tb_generate_checksum(struct acpi_table_header * table)
 {
-	u8 *end_buffer;
-	u8 *rover;
-	u8 sum = 0;
+	u8 checksum;
 
-	if (buffer && length) {
-		/*  Buffer and Length are valid   */
+	/* Sum the entire table as-is */
 
-		end_buffer = ACPI_ADD_PTR(u8, buffer, length);
+	checksum = acpi_tb_sum_table(table, table->length);
 
-		for (rover = buffer; rover < end_buffer; rover++) {
-			sum = (u8) (sum + *rover);
-		}
+	/* Subtract off the existing checksum value in the table */
+
+	checksum = (u8) (checksum - table->checksum);
+
+	/* Compute the final checksum */
+
+	checksum = (u8) (0 - checksum);
+	return (checksum);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_set_checksum
+ *
+ * PARAMETERS:  Table               - Pointer to a valid ACPI table (with a
+ *                                    standard ACPI header)
+ *
+ * RETURN:      None. Sets the table checksum field
+ *
+ * DESCRIPTION: Computes an 8 bit checksum of the table and inserts the
+ *              checksum into the table header.
+ *
+ ******************************************************************************/
+
+void acpi_tb_set_checksum(struct acpi_table_header *table)
+{
+
+	table->checksum = acpi_tb_generate_checksum(table);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_verify_table_checksum
+ *
+ * PARAMETERS:  *table_header           - ACPI table to verify
+ *
+ * RETURN:      8 bit checksum of table
+ *
+ * DESCRIPTION: Generates an 8 bit checksum of table and returns and compares
+ *              it to the existing checksum value.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_tb_verify_table_checksum(struct acpi_table_header *table_header)
+{
+	u8 checksum;
+
+	ACPI_FUNCTION_TRACE(tb_verify_table_checksum);
+
+	/* Compute the checksum on the table */
+
+	checksum = acpi_tb_generate_checksum(table_header);
+
+	/* Checksum ok? */
+
+	if (checksum == table_header->checksum) {
+		return_ACPI_STATUS(AE_OK);
 	}
-	return (sum);
+
+	ACPI_WARNING((AE_INFO,
+		      "Incorrect checksum in table [%4.4s] - is %2.2X, should be %2.2X",
+		      table_header->signature, table_header->checksum,
+		      checksum));
+
+	return_ACPI_STATUS(AE_BAD_CHECKSUM);
 }
 
 #ifdef ACPI_OBSOLETE_FUNCTIONS
@@ -276,12 +317,12 @@
 
 acpi_status
 acpi_tb_handle_to_object(u16 table_id,
-			 struct acpi_table_desc ** return_table_desc)
+			 struct acpi_table_desc **return_table_desc)
 {
 	u32 i;
 	struct acpi_table_desc *table_desc;
 
-	ACPI_FUNCTION_NAME("tb_handle_to_object");
+	ACPI_FUNCTION_NAME(tb_handle_to_object);
 
 	for (i = 0; i < ACPI_TABLE_MAX; i++) {
 		table_desc = acpi_gbl_table_lists[i].next;
@@ -295,7 +336,7 @@
 		}
 	}
 
-	ACPI_ERROR((AE_INFO, "table_id=%X does not exist", table_id));
+	ACPI_ERROR((AE_INFO, "TableId=%X does not exist", table_id));
 	return (AE_BAD_PARAMETER);
 }
 #endif
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 9fe53c9..4e91f29 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -42,8 +42,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 #include <acpi/actables.h>
@@ -68,7 +66,7 @@
 	struct acpi_pointer rsdp_address;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_load_tables");
+	ACPI_FUNCTION_TRACE(acpi_load_tables);
 
 	/* Get the RSDP */
 
@@ -123,6 +121,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_load_tables)
+
 #ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
@@ -139,14 +139,13 @@
  *              is determined that the table is invalid, the call will fail.
  *
  ******************************************************************************/
-
 acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
 {
 	acpi_status status;
 	struct acpi_table_desc table_info;
 	struct acpi_pointer address;
 
-	ACPI_FUNCTION_TRACE("acpi_load_table");
+	ACPI_FUNCTION_TRACE(acpi_load_table);
 
 	if (!table_ptr) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -174,6 +173,7 @@
 	status = acpi_tb_install_table(&table_info);
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_ALREADY_EXISTS) {
+
 			/* Table already exists, no error */
 
 			status = AE_OK;
@@ -188,12 +188,12 @@
 	/* Convert the table to common format if necessary */
 
 	switch (table_info.type) {
-	case ACPI_TABLE_FADT:
+	case ACPI_TABLE_ID_FADT:
 
 		status = acpi_tb_convert_table_fadt();
 		break;
 
-	case ACPI_TABLE_FACS:
+	case ACPI_TABLE_ID_FACS:
 
 		status = acpi_tb_build_common_facs(&table_info);
 		break;
@@ -208,6 +208,7 @@
 	}
 
 	if (ACPI_FAILURE(status)) {
+
 		/* Uninstall table and free the buffer */
 
 		(void)acpi_tb_uninstall_table(table_info.installed_desc);
@@ -216,6 +217,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_load_table)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_unload_table
@@ -227,16 +230,15 @@
  * DESCRIPTION: This routine is used to force the unload of a table
  *
  ******************************************************************************/
-
 acpi_status acpi_unload_table(acpi_table_type table_type)
 {
 	struct acpi_table_desc *table_desc;
 
-	ACPI_FUNCTION_TRACE("acpi_unload_table");
+	ACPI_FUNCTION_TRACE(acpi_unload_table);
 
 	/* Parameter validation */
 
-	if (table_type > ACPI_TABLE_MAX) {
+	if (table_type > ACPI_TABLE_ID_MAX) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -261,6 +263,8 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_unload_table)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_table_header
@@ -281,7 +285,6 @@
  *              have a standard header and is fixed length.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_table_header(acpi_table_type table_type,
 		      u32 instance, struct acpi_table_header *out_table_header)
@@ -289,16 +292,16 @@
 	struct acpi_table_header *tbl_ptr;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_get_table_header");
+	ACPI_FUNCTION_TRACE(acpi_get_table_header);
 
 	if ((instance == 0) ||
-	    (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) {
+	    (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
 	/* Check the table type and instance */
 
-	if ((table_type > ACPI_TABLE_MAX) ||
+	if ((table_type > ACPI_TABLE_ID_MAX) ||
 	    (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
 	     instance > 1)) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -325,6 +328,7 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_get_table_header)
 #endif				/*  ACPI_FUTURE_USAGE  */
 
 /*******************************************************************************
@@ -349,7 +353,6 @@
  *              a complete table including the header.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_get_table(acpi_table_type table_type,
 	       u32 instance, struct acpi_buffer *ret_buffer)
@@ -358,7 +361,7 @@
 	acpi_status status;
 	acpi_size table_length;
 
-	ACPI_FUNCTION_TRACE("acpi_get_table");
+	ACPI_FUNCTION_TRACE(acpi_get_table);
 
 	/* Parameter validation */
 
@@ -373,7 +376,7 @@
 
 	/* Check the table type and instance */
 
-	if ((table_type > ACPI_TABLE_MAX) ||
+	if ((table_type > ACPI_TABLE_ID_MAX) ||
 	    (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
 	     instance > 1)) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
@@ -396,7 +399,8 @@
 
 	/* Get the table length */
 
-	if (table_type == ACPI_TABLE_RSDP) {
+	if (table_type == ACPI_TABLE_ID_RSDP) {
+
 		/* RSD PTR is the only "table" without a header */
 
 		table_length = sizeof(struct rsdp_descriptor);
@@ -417,4 +421,4 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
-EXPORT_SYMBOL(acpi_get_table);
+ACPI_EXPORT_SYMBOL(acpi_get_table)
diff --git a/drivers/acpi/tables/tbxfroot.c b/drivers/acpi/tables/tbxfroot.c
index a62db6a..da2648b 100644
--- a/drivers/acpi/tables/tbxfroot.c
+++ b/drivers/acpi/tables/tbxfroot.c
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/actables.h>
 
@@ -75,6 +73,7 @@
 	 *  The signature and checksum must both be correct
 	 */
 	if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) {
+
 		/* Nope, BAD Signature */
 
 		return (AE_BAD_SIGNATURE);
@@ -82,15 +81,14 @@
 
 	/* Check the standard checksum */
 
-	if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
+	if (acpi_tb_sum_table(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
 		return (AE_BAD_CHECKSUM);
 	}
 
 	/* Check extended checksum if table version >= 2 */
 
 	if ((rsdp->revision >= 2) &&
-	    (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) !=
-	     0)) {
+	    (acpi_tb_sum_table(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
 		return (AE_BAD_CHECKSUM);
 	}
 
@@ -121,7 +119,7 @@
 	acpi_status status;
 	struct acpi_table_header *table;
 
-	ACPI_FUNCTION_TRACE("tb_find_table");
+	ACPI_FUNCTION_TRACE(tb_find_table);
 
 	/* Validate string lengths */
 
@@ -131,7 +129,7 @@
 		return_ACPI_STATUS(AE_AML_STRING_LIMIT);
 	}
 
-	if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) {
+	if (ACPI_COMPARE_NAME(signature, DSDT_SIG)) {
 		/*
 		 * The DSDT pointer is contained in the FADT, not the RSDT.
 		 * This code should suffice, because the only code that would perform
@@ -156,10 +154,12 @@
 
 	/* Check oem_id and oem_table_id */
 
-	if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id,
-				       sizeof(table->oem_id))) ||
-	    (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id,
-					     sizeof(table->oem_table_id)))) {
+	if ((oem_id[0] &&
+	     ACPI_STRNCMP(oem_id, table->oem_id,
+			  sizeof(table->oem_id))) ||
+	    (oem_table_id[0] &&
+	     ACPI_STRNCMP(oem_table_id, table->oem_table_id,
+			  sizeof(table->oem_table_id)))) {
 		return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND);
 	}
 
@@ -203,7 +203,7 @@
 	u32 i;
 	u32 j;
 
-	ACPI_FUNCTION_TRACE("acpi_get_firmware_table");
+	ACPI_FUNCTION_TRACE(acpi_get_firmware_table);
 
 	/*
 	 * Ensure that at least the table manager is initialized.  We don't
@@ -217,6 +217,7 @@
 	/* Ensure that we have a RSDP */
 
 	if (!acpi_gbl_RSDP) {
+
 		/* Get the RSDP */
 
 		status = acpi_os_get_root_pointer(flags, &address);
@@ -261,7 +262,7 @@
 
 	/* Get and validate the RSDT */
 
-	rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc));
+	rsdt_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc));
 	if (!rsdt_info) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -278,13 +279,13 @@
 
 	/* Allocate a scratch table header and table descriptor */
 
-	header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header));
+	header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
 	if (!header) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
 	}
 
-	table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc));
+	table_info = ACPI_ALLOCATE(sizeof(struct acpi_table_desc));
 	if (!table_info) {
 		status = AE_NO_MEMORY;
 		goto cleanup;
@@ -308,12 +309,12 @@
 		if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) {
 			address.pointer.value =
 			    (ACPI_CAST_PTR
-			     (RSDT_DESCRIPTOR,
+			     (struct rsdt_descriptor,
 			      rsdt_info->pointer))->table_offset_entry[i];
 		} else {
 			address.pointer.value =
 			    (ACPI_CAST_PTR
-			     (XSDT_DESCRIPTOR,
+			     (struct xsdt_descriptor,
 			      rsdt_info->pointer))->table_offset_entry[i];
 		}
 
@@ -326,11 +327,13 @@
 
 		/* Compare table signatures and table instance */
 
-		if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) {
+		if (ACPI_COMPARE_NAME(header->signature, signature)) {
+
 			/* An instance of the table was found */
 
 			j++;
 			if (j >= instance) {
+
 				/* Found the correct instance, get the entire table */
 
 				status =
@@ -355,23 +358,21 @@
 		acpi_os_unmap_memory(rsdt_info->pointer,
 				     (acpi_size) rsdt_info->pointer->length);
 	}
-	ACPI_MEM_FREE(rsdt_info);
+	ACPI_FREE(rsdt_info);
 
 	if (header) {
-		ACPI_MEM_FREE(header);
+		ACPI_FREE(header);
 	}
 	if (table_info) {
-		ACPI_MEM_FREE(table_info);
+		ACPI_FREE(table_info);
 	}
 	return_ACPI_STATUS(status);
 }
 
-EXPORT_SYMBOL(acpi_get_firmware_table);
+ACPI_EXPORT_SYMBOL(acpi_get_firmware_table)
 
 /* TBD: Move to a new file */
-
 #if ACPI_MACHINE_WIDTH != 16
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_find_root_pointer
@@ -384,13 +385,12 @@
  * DESCRIPTION: Find the RSDP
  *
  ******************************************************************************/
-
 acpi_status acpi_find_root_pointer(u32 flags, struct acpi_pointer *rsdp_address)
 {
 	struct acpi_table_desc table_info;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_find_root_pointer");
+	ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
 
 	/* Get the RSDP */
 
@@ -407,6 +407,8 @@
 	return_ACPI_STATUS(AE_OK);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_find_root_pointer)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_tb_scan_memory_for_rsdp
@@ -419,14 +421,13 @@
  * DESCRIPTION: Search a block of memory for the RSDP signature
  *
  ******************************************************************************/
-
 static u8 *acpi_tb_scan_memory_for_rsdp(u8 * start_address, u32 length)
 {
 	acpi_status status;
 	u8 *mem_rover;
 	u8 *end_address;
 
-	ACPI_FUNCTION_TRACE("tb_scan_memory_for_rsdp");
+	ACPI_FUNCTION_TRACE(tb_scan_memory_for_rsdp);
 
 	end_address = start_address + length;
 
@@ -434,12 +435,14 @@
 
 	for (mem_rover = start_address; mem_rover < end_address;
 	     mem_rover += ACPI_RSDP_SCAN_STEP) {
+
 		/* The RSDP signature and checksum must both be correct */
 
 		status =
 		    acpi_tb_validate_rsdp(ACPI_CAST_PTR
 					  (struct rsdp_descriptor, mem_rover));
 		if (ACPI_SUCCESS(status)) {
+
 			/* Sig and checksum valid, we have found a real RSDP */
 
 			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -469,10 +472,10 @@
  *
  * RETURN:      Status, RSDP physical address
  *
- * DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
+ * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
  *              pointer structure.  If it is found, set *RSDP to point to it.
  *
- *              NOTE1: The RSDp must be either in the first 1_k of the Extended
+ *              NOTE1: The RSDP must be either in the first 1_k of the Extended
  *              BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
  *              Only a 32-bit physical address is necessary.
  *
@@ -489,12 +492,13 @@
 	u32 physical_address;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("tb_find_rsdp");
+	ACPI_FUNCTION_TRACE(tb_find_rsdp);
 
 	/*
 	 * Scan supports either logical addressing or physical addressing
 	 */
 	if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
+
 		/* 1a) Get the location of the Extended BIOS Data Area (EBDA) */
 
 		status = acpi_os_map_memory((acpi_physical_address)
@@ -521,7 +525,7 @@
 
 		if (physical_address > 0x400) {
 			/*
-			 * 1b) Search EBDA paragraphs (EBDa is required to be a
+			 * 1b) Search EBDA paragraphs (EBDA is required to be a
 			 *     minimum of 1_k length)
 			 */
 			status = acpi_os_map_memory((acpi_physical_address)
@@ -542,10 +546,11 @@
 			acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
 
 			if (mem_rover) {
+
 				/* Return the physical address */
 
 				physical_address +=
-				    ACPI_PTR_DIFF(mem_rover, table_ptr);
+				    (u32) ACPI_PTR_DIFF(mem_rover, table_ptr);
 
 				table_info->physical_address =
 				    (acpi_physical_address) physical_address;
@@ -576,11 +581,12 @@
 		acpi_os_unmap_memory(table_ptr, ACPI_HI_RSDP_WINDOW_SIZE);
 
 		if (mem_rover) {
+
 			/* Return the physical address */
 
-			physical_address =
-			    ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF(mem_rover,
-								     table_ptr);
+			physical_address = (u32)
+			    (ACPI_HI_RSDP_WINDOW_BASE +
+			     ACPI_PTR_DIFF(mem_rover, table_ptr));
 
 			table_info->physical_address =
 			    (acpi_physical_address) physical_address;
@@ -601,7 +607,7 @@
 
 		if (physical_address > 0x400) {
 			/*
-			 * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of
+			 * 1b) Search EBDA paragraphs (EBDA is required to be a minimum of
 			 *     1_k length)
 			 */
 			mem_rover =
@@ -609,6 +615,7 @@
 							 (physical_address),
 							 ACPI_EBDA_WINDOW_SIZE);
 			if (mem_rover) {
+
 				/* Return the physical address */
 
 				table_info->physical_address =
@@ -624,6 +631,7 @@
 						 (ACPI_HI_RSDP_WINDOW_BASE),
 						 ACPI_HI_RSDP_WINDOW_SIZE);
 		if (mem_rover) {
+
 			/* Found it, return the physical address */
 
 			table_info->physical_address =
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 19f3ea4..e7fe3a1 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -82,6 +82,7 @@
 
 static int acpi_thermal_add(struct acpi_device *device);
 static int acpi_thermal_remove(struct acpi_device *device, int type);
+static int acpi_thermal_resume(struct acpi_device *device, int state);
 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
@@ -103,6 +104,7 @@
 	.ops = {
 		.add = acpi_thermal_add,
 		.remove = acpi_thermal_remove,
+		.resume = acpi_thermal_resume,
 		},
 };
 
@@ -684,8 +686,7 @@
 {
 	struct acpi_thermal *tz = (struct acpi_thermal *)data;
 	if (!tz->zombie)
-		acpi_os_queue_for_execution(OSD_PRIORITY_GPE,
-					    acpi_thermal_check, (void *)data);
+		acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data);
 }
 
 static void acpi_thermal_check(void *data)
@@ -942,8 +943,10 @@
 	memset(limit_string, 0, ACPI_THERMAL_MAX_LIMIT_STR_LEN);
 
 	active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL);
-	if (!active)
+	if (!active) {
+		kfree(limit_string);
 		return_VALUE(-ENOMEM);
+	}
 
 	if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid argument\n"));
@@ -1342,7 +1345,7 @@
 
 	result = acpi_thermal_add_fs(device);
 	if (result)
-		return_VALUE(result);
+		goto end;
 
 	init_timer(&tz->timer);
 
@@ -1416,6 +1419,20 @@
 	return_VALUE(0);
 }
 
+static int acpi_thermal_resume(struct acpi_device *device, int state)
+{
+	struct acpi_thermal *tz = NULL;
+
+	if (!device || !acpi_driver_data(device))
+		return_VALUE(-EINVAL);
+
+	tz = (struct acpi_thermal *)acpi_driver_data(device);
+
+	acpi_thermal_check(tz);
+
+	return AE_OK;
+}
+
 static int __init acpi_thermal_init(void)
 {
 	int result = 0;
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 03b0044..7940fc1 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -46,24 +46,6 @@
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utalloc")
 
-/* Local prototypes */
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation);
-
-static acpi_status
-acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
-			 acpi_size size,
-			 u8 alloc_type, u32 component, char *module, u32 line);
-
-static acpi_status
-acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
-			  u32 component, char *module, u32 line);
-
-static acpi_status
-acpi_ut_create_list(char *list_name,
-		    u16 object_size, struct acpi_memory_list **return_cache);
-#endif
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_create_caches
@@ -75,11 +57,56 @@
  * DESCRIPTION: Create all local caches
  *
  ******************************************************************************/
-
 acpi_status acpi_ut_create_caches(void)
 {
 	acpi_status status;
 
+	/* Object Caches, for frequently used objects */
+
+	status =
+	    acpi_os_create_cache("Acpi-Namespace",
+				 sizeof(struct acpi_namespace_node),
+				 ACPI_MAX_NAMESPACE_CACHE_DEPTH,
+				 &acpi_gbl_namespace_cache);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	status =
+	    acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state),
+				 ACPI_MAX_STATE_CACHE_DEPTH,
+				 &acpi_gbl_state_cache);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	status =
+	    acpi_os_create_cache("Acpi-Parse",
+				 sizeof(struct acpi_parse_obj_common),
+				 ACPI_MAX_PARSE_CACHE_DEPTH,
+				 &acpi_gbl_ps_node_cache);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	status =
+	    acpi_os_create_cache("Acpi-ParseExt",
+				 sizeof(struct acpi_parse_obj_named),
+				 ACPI_MAX_EXTPARSE_CACHE_DEPTH,
+				 &acpi_gbl_ps_node_ext_cache);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	status =
+	    acpi_os_create_cache("Acpi-Operand",
+				 sizeof(union acpi_operand_object),
+				 ACPI_MAX_OBJECT_CACHE_DEPTH,
+				 &acpi_gbl_operand_cache);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 
 	/* Memory allocation lists */
@@ -98,43 +125,6 @@
 	}
 #endif
 
-	/* Object Caches, for frequently used objects */
-
-	status =
-	    acpi_os_create_cache("acpi_state", sizeof(union acpi_generic_state),
-				 ACPI_MAX_STATE_CACHE_DEPTH,
-				 &acpi_gbl_state_cache);
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
-
-	status =
-	    acpi_os_create_cache("acpi_parse",
-				 sizeof(struct acpi_parse_obj_common),
-				 ACPI_MAX_PARSE_CACHE_DEPTH,
-				 &acpi_gbl_ps_node_cache);
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
-
-	status =
-	    acpi_os_create_cache("acpi_parse_ext",
-				 sizeof(struct acpi_parse_obj_named),
-				 ACPI_MAX_EXTPARSE_CACHE_DEPTH,
-				 &acpi_gbl_ps_node_ext_cache);
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
-
-	status =
-	    acpi_os_create_cache("acpi_operand",
-				 sizeof(union acpi_operand_object),
-				 ACPI_MAX_OBJECT_CACHE_DEPTH,
-				 &acpi_gbl_operand_cache);
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
-
 	return (AE_OK);
 }
 
@@ -153,6 +143,9 @@
 acpi_status acpi_ut_delete_caches(void)
 {
 
+	(void)acpi_os_delete_cache(acpi_gbl_namespace_cache);
+	acpi_gbl_namespace_cache = NULL;
+
 	(void)acpi_os_delete_cache(acpi_gbl_state_cache);
 	acpi_gbl_state_cache = NULL;
 
@@ -165,6 +158,21 @@
 	(void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache);
 	acpi_gbl_ps_node_ext_cache = NULL;
 
+#ifdef ACPI_DBG_TRACK_ALLOCATIONS
+
+	/* Debug only - display leftover memory allocation, if any */
+
+	acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL);
+
+	/* Free memory lists */
+
+	acpi_os_free(acpi_gbl_global_list);
+	acpi_gbl_global_list = NULL;
+
+	acpi_os_free(acpi_gbl_ns_node_list);
+	acpi_gbl_ns_node_list = NULL;
+#endif
+
 	return (AE_OK);
 }
 
@@ -252,7 +260,7 @@
 
 		/* Allocate a new buffer with local interface to allow tracking */
 
-		buffer->pointer = ACPI_MEM_CALLOCATE(required_length);
+		buffer->pointer = ACPI_ALLOCATE_ZEROED(required_length);
 		if (!buffer->pointer) {
 			return (AE_NO_MEMORY);
 		}
@@ -288,7 +296,7 @@
  *
  * RETURN:      Address of the allocated memory on success, NULL on failure.
  *
- * DESCRIPTION: The subsystem's equivalent of malloc.
+ * DESCRIPTION: Subsystem equivalent of malloc.
  *
  ******************************************************************************/
 
@@ -296,23 +304,23 @@
 {
 	void *allocation;
 
-	ACPI_FUNCTION_TRACE_U32("ut_allocate", size);
+	ACPI_FUNCTION_TRACE_U32(ut_allocate, size);
 
 	/* Check for an inadvertent size of zero bytes */
 
 	if (!size) {
-		ACPI_ERROR((module, line,
-			    "ut_allocate: Attempt to allocate zero bytes, allocating 1 byte"));
+		ACPI_WARNING((module, line,
+			      "Attempt to allocate zero bytes, allocating 1 byte"));
 		size = 1;
 	}
 
 	allocation = acpi_os_allocate(size);
 	if (!allocation) {
+
 		/* Report allocation error */
 
-		ACPI_ERROR((module, line,
-			    "ut_allocate: Could not allocate size %X",
-			    (u32) size));
+		ACPI_WARNING((module, line,
+			      "Could not allocate size %X", (u32) size));
 
 		return_PTR(NULL);
 	}
@@ -322,7 +330,7 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_callocate
+ * FUNCTION:    acpi_ut_allocate_zeroed
  *
  * PARAMETERS:  Size                - Size of the allocation
  *              Component           - Component type of caller
@@ -331,542 +339,24 @@
  *
  * RETURN:      Address of the allocated memory on success, NULL on failure.
  *
- * DESCRIPTION: Subsystem equivalent of calloc.
+ * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory.
  *
  ******************************************************************************/
 
-void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line)
+void *acpi_ut_allocate_zeroed(acpi_size size,
+			      u32 component, char *module, u32 line)
 {
 	void *allocation;
 
-	ACPI_FUNCTION_TRACE_U32("ut_callocate", size);
-
-	/* Check for an inadvertent size of zero bytes */
-
-	if (!size) {
-		ACPI_ERROR((module, line,
-			    "Attempt to allocate zero bytes, allocating 1 byte"));
-		size = 1;
-	}
-
-	allocation = acpi_os_allocate(size);
-	if (!allocation) {
-		/* Report allocation error */
-
-		ACPI_ERROR((module, line,
-			    "Could not allocate size %X", (u32) size));
-		return_PTR(NULL);
-	}
-
-	/* Clear the memory block */
-
-	ACPI_MEMSET(allocation, 0, size);
-	return_PTR(allocation);
-}
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-/*
- * These procedures are used for tracking memory leaks in the subsystem, and
- * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
- *
- * Each memory allocation is tracked via a doubly linked list.  Each
- * element contains the caller's component, module name, function name, and
- * line number.  acpi_ut_allocate and acpi_ut_callocate call
- * acpi_ut_track_allocation to add an element to the list; deletion
- * occurs in the body of acpi_ut_free.
- */
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_create_list
- *
- * PARAMETERS:  cache_name      - Ascii name for the cache
- *              object_size     - Size of each cached object
- *              return_cache    - Where the new cache object is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create a local memory list for tracking purposed
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_create_list(char *list_name,
-		    u16 object_size, struct acpi_memory_list **return_cache)
-{
-	struct acpi_memory_list *cache;
-
-	cache = acpi_os_allocate(sizeof(struct acpi_memory_list));
-	if (!cache) {
-		return (AE_NO_MEMORY);
-	}
-
-	ACPI_MEMSET(cache, 0, sizeof(struct acpi_memory_list));
-
-	cache->list_name = list_name;
-	cache->object_size = object_size;
-
-	*return_cache = cache;
-	return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_allocate_and_track
- *
- * PARAMETERS:  Size                - Size of the allocation
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:      Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: The subsystem's equivalent of malloc.
- *
- ******************************************************************************/
-
-void *acpi_ut_allocate_and_track(acpi_size size,
-				 u32 component, char *module, u32 line)
-{
-	struct acpi_debug_mem_block *allocation;
-	acpi_status status;
-
-	allocation =
-	    acpi_ut_allocate(size + sizeof(struct acpi_debug_mem_header),
-			     component, module, line);
-	if (!allocation) {
-		return (NULL);
-	}
-
-	status = acpi_ut_track_allocation(allocation, size,
-					  ACPI_MEM_MALLOC, component, module,
-					  line);
-	if (ACPI_FAILURE(status)) {
-		acpi_os_free(allocation);
-		return (NULL);
-	}
-
-	acpi_gbl_global_list->total_allocated++;
-	acpi_gbl_global_list->current_total_size += (u32) size;
-
-	return ((void *)&allocation->user_space);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_callocate_and_track
- *
- * PARAMETERS:  Size                - Size of the allocation
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:      Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: Subsystem equivalent of calloc.
- *
- ******************************************************************************/
-
-void *acpi_ut_callocate_and_track(acpi_size size,
-				  u32 component, char *module, u32 line)
-{
-	struct acpi_debug_mem_block *allocation;
-	acpi_status status;
-
-	allocation =
-	    acpi_ut_callocate(size + sizeof(struct acpi_debug_mem_header),
-			      component, module, line);
-	if (!allocation) {
-		/* Report allocation error */
-
-		ACPI_ERROR((module, line,
-			    "Could not allocate size %X", (u32) size));
-		return (NULL);
-	}
-
-	status = acpi_ut_track_allocation(allocation, size,
-					  ACPI_MEM_CALLOC, component, module,
-					  line);
-	if (ACPI_FAILURE(status)) {
-		acpi_os_free(allocation);
-		return (NULL);
-	}
-
-	acpi_gbl_global_list->total_allocated++;
-	acpi_gbl_global_list->current_total_size += (u32) size;
-
-	return ((void *)&allocation->user_space);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_free_and_track
- *
- * PARAMETERS:  Allocation          - Address of the memory to deallocate
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:      None
- *
- * DESCRIPTION: Frees the memory at Allocation
- *
- ******************************************************************************/
-
-void
-acpi_ut_free_and_track(void *allocation, u32 component, char *module, u32 line)
-{
-	struct acpi_debug_mem_block *debug_block;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE_PTR("ut_free", allocation);
-
-	if (NULL == allocation) {
-		ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
-
-		return_VOID;
-	}
-
-	debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
-				    (((char *)allocation) -
-				     sizeof(struct acpi_debug_mem_header)));
-
-	acpi_gbl_global_list->total_freed++;
-	acpi_gbl_global_list->current_total_size -= debug_block->size;
-
-	status = acpi_ut_remove_allocation(debug_block,
-					   component, module, line);
-	if (ACPI_FAILURE(status)) {
-		ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
-	}
-
-	acpi_os_free(debug_block);
-	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed\n", allocation));
-	return_VOID;
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_find_allocation
- *
- * PARAMETERS:  Allocation              - Address of allocated memory
- *
- * RETURN:      A list element if found; NULL otherwise.
- *
- * DESCRIPTION: Searches for an element in the global allocation tracking list.
- *
- ******************************************************************************/
-
-static struct acpi_debug_mem_block *acpi_ut_find_allocation(void *allocation)
-{
-	struct acpi_debug_mem_block *element;
-
 	ACPI_FUNCTION_ENTRY();
 
-	element = acpi_gbl_global_list->list_head;
+	allocation = acpi_ut_allocate(size, component, module, line);
+	if (allocation) {
 
-	/* Search for the address. */
+		/* Clear the memory block */
 
-	while (element) {
-		if (element == allocation) {
-			return (element);
-		}
-
-		element = element->next;
+		ACPI_MEMSET(allocation, 0, size);
 	}
 
-	return (NULL);
+	return (allocation);
 }
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_track_allocation
- *
- * PARAMETERS:  Allocation          - Address of allocated memory
- *              Size                - Size of the allocation
- *              alloc_type          - MEM_MALLOC or MEM_CALLOC
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:      None.
- *
- * DESCRIPTION: Inserts an element into the global allocation tracking list.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
-			 acpi_size size,
-			 u8 alloc_type, u32 component, char *module, u32 line)
-{
-	struct acpi_memory_list *mem_list;
-	struct acpi_debug_mem_block *element;
-	acpi_status status = AE_OK;
-
-	ACPI_FUNCTION_TRACE_PTR("ut_track_allocation", allocation);
-
-	mem_list = acpi_gbl_global_list;
-	status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	/*
-	 * Search list for this address to make sure it is not already on the list.
-	 * This will catch several kinds of problems.
-	 */
-	element = acpi_ut_find_allocation(allocation);
-	if (element) {
-		ACPI_ERROR((AE_INFO,
-			    "ut_track_allocation: Allocation already present in list! (%p)",
-			    allocation));
-
-		ACPI_ERROR((AE_INFO, "Element %p Address %p",
-			    element, allocation));
-
-		goto unlock_and_exit;
-	}
-
-	/* Fill in the instance data. */
-
-	allocation->size = (u32) size;
-	allocation->alloc_type = alloc_type;
-	allocation->component = component;
-	allocation->line = line;
-
-	ACPI_STRNCPY(allocation->module, module, ACPI_MAX_MODULE_NAME);
-	allocation->module[ACPI_MAX_MODULE_NAME - 1] = 0;
-
-	/* Insert at list head */
-
-	if (mem_list->list_head) {
-		((struct acpi_debug_mem_block *)(mem_list->list_head))->
-		    previous = allocation;
-	}
-
-	allocation->next = mem_list->list_head;
-	allocation->previous = NULL;
-
-	mem_list->list_head = allocation;
-
-      unlock_and_exit:
-	status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_remove_allocation
- *
- * PARAMETERS:  Allocation          - Address of allocated memory
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:
- *
- * DESCRIPTION: Deletes an element from the global allocation tracking list.
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
-			  u32 component, char *module, u32 line)
-{
-	struct acpi_memory_list *mem_list;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE("ut_remove_allocation");
-
-	mem_list = acpi_gbl_global_list;
-	if (NULL == mem_list->list_head) {
-		/* No allocations! */
-
-		ACPI_ERROR((module, line,
-			    "Empty allocation list, nothing to free!"));
-
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
-	if (ACPI_FAILURE(status)) {
-		return_ACPI_STATUS(status);
-	}
-
-	/* Unlink */
-
-	if (allocation->previous) {
-		(allocation->previous)->next = allocation->next;
-	} else {
-		mem_list->list_head = allocation->next;
-	}
-
-	if (allocation->next) {
-		(allocation->next)->previous = allocation->previous;
-	}
-
-	/* Mark the segment as deleted */
-
-	ACPI_MEMSET(&allocation->user_space, 0xEA, allocation->size);
-
-	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n",
-			  allocation->size));
-
-	status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_dump_allocation_info
- *
- * PARAMETERS:
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print some info about the outstanding allocations.
- *
- ******************************************************************************/
-
-#ifdef ACPI_FUTURE_USAGE
-void acpi_ut_dump_allocation_info(void)
-{
-/*
-	struct acpi_memory_list         *mem_list;
-*/
-
-	ACPI_FUNCTION_TRACE("ut_dump_allocation_info");
-
-/*
-	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-			  ("%30s: %4d (%3d Kb)\n", "Current allocations",
-			  mem_list->current_count,
-			  ROUND_UP_TO_1K (mem_list->current_size)));
-
-	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-			  ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
-			  mem_list->max_concurrent_count,
-			  ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
-
-	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-			  ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
-			  running_object_count,
-			  ROUND_UP_TO_1K (running_object_size)));
-
-	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-			  ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
-			  running_alloc_count,
-			  ROUND_UP_TO_1K (running_alloc_size)));
-
-	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-			  ("%30s: %4d (%3d Kb)\n", "Current Nodes",
-			  acpi_gbl_current_node_count,
-			  ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
-
-	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
-			  ("%30s: %4d (%3d Kb)\n", "Max Nodes",
-			  acpi_gbl_max_concurrent_node_count,
-			  ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
-					 sizeof (struct acpi_namespace_node)))));
-*/
-	return_VOID;
-}
-#endif				/*  ACPI_FUTURE_USAGE  */
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_dump_allocations
- *
- * PARAMETERS:  Component           - Component(s) to dump info for.
- *              Module              - Module to dump info for.  NULL means all.
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print a list of all outstanding allocations.
- *
- ******************************************************************************/
-
-void acpi_ut_dump_allocations(u32 component, char *module)
-{
-	struct acpi_debug_mem_block *element;
-	union acpi_descriptor *descriptor;
-	u32 num_outstanding = 0;
-
-	ACPI_FUNCTION_TRACE("ut_dump_allocations");
-
-	/*
-	 * Walk the allocation list.
-	 */
-	if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
-		return;
-	}
-
-	element = acpi_gbl_global_list->list_head;
-	while (element) {
-		if ((element->component & component) &&
-		    ((module == NULL)
-		     || (0 == ACPI_STRCMP(module, element->module)))) {
-			/* Ignore allocated objects that are in a cache */
-
-			descriptor =
-			    ACPI_CAST_PTR(union acpi_descriptor,
-					  &element->user_space);
-			if (descriptor->descriptor_id != ACPI_DESC_TYPE_CACHED) {
-				acpi_os_printf("%p Len %04X %9.9s-%d [%s] ",
-					       descriptor, element->size,
-					       element->module, element->line,
-					       acpi_ut_get_descriptor_name
-					       (descriptor));
-
-				/* Most of the elements will be Operand objects. */
-
-				switch (ACPI_GET_DESCRIPTOR_TYPE(descriptor)) {
-				case ACPI_DESC_TYPE_OPERAND:
-					acpi_os_printf("%12.12s R%hd",
-						       acpi_ut_get_type_name
-						       (descriptor->object.
-							common.type),
-						       descriptor->object.
-						       common.reference_count);
-					break;
-
-				case ACPI_DESC_TYPE_PARSER:
-					acpi_os_printf("aml_opcode %04hX",
-						       descriptor->op.asl.
-						       aml_opcode);
-					break;
-
-				case ACPI_DESC_TYPE_NAMED:
-					acpi_os_printf("%4.4s",
-						       acpi_ut_get_node_name
-						       (&descriptor->node));
-					break;
-
-				default:
-					break;
-				}
-
-				acpi_os_printf("\n");
-				num_outstanding++;
-			}
-		}
-		element = element->next;
-	}
-
-	(void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
-
-	/* Print summary */
-
-	if (!num_outstanding) {
-		ACPI_INFO((AE_INFO, "No outstanding allocations"));
-	} else {
-		ACPI_ERROR((AE_INFO,
-			    "%d(%X) Outstanding allocations",
-			    num_outstanding, num_outstanding));
-	}
-
-	return_VOID;
-}
-
-#endif				/* #ifdef ACPI_DBG_TRACK_ALLOCATIONS */
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
index 2177cb1..56270a3 100644
--- a/drivers/acpi/utilities/utcache.c
+++ b/drivers/acpi/utilities/utcache.c
@@ -118,13 +118,14 @@
 	/* Walk the list of objects in this cache */
 
 	while (cache->list_head) {
+
 		/* Delete and unlink one cached state object */
 
 		next = *(ACPI_CAST_INDIRECT_PTR(char,
 						&(((char *)cache->
 						   list_head)[cache->
 							      link_offset])));
-		ACPI_MEM_FREE(cache->list_head);
+		ACPI_FREE(cache->list_head);
 
 		cache->list_head = next;
 		cache->current_depth--;
@@ -193,7 +194,7 @@
 	/* If cache is full, just free this object */
 
 	if (cache->current_depth >= cache->max_depth) {
-		ACPI_MEM_FREE(object);
+		ACPI_FREE(object);
 		ACPI_MEM_TRACKING(cache->total_freed++);
 	}
 
@@ -243,7 +244,7 @@
 	acpi_status status;
 	void *object;
 
-	ACPI_FUNCTION_NAME("os_acquire_object");
+	ACPI_FUNCTION_NAME(os_acquire_object);
 
 	if (!cache) {
 		return (NULL);
@@ -259,6 +260,7 @@
 	/* Check the cache first */
 
 	if (cache->list_head) {
+
 		/* There is an object available, use it */
 
 		object = cache->list_head;
@@ -270,9 +272,9 @@
 		cache->current_depth--;
 
 		ACPI_MEM_TRACKING(cache->hits++);
-		ACPI_MEM_TRACKING(ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-						    "Object %p from %s cache\n",
-						    object, cache->list_name)));
+		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+				  "Object %p from %s cache\n", object,
+				  cache->list_name));
 
 		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
 		if (ACPI_FAILURE(status)) {
@@ -287,14 +289,14 @@
 
 		ACPI_MEM_TRACKING(cache->total_allocated++);
 
-		/* Avoid deadlock with ACPI_MEM_CALLOCATE */
+		/* Avoid deadlock with ACPI_ALLOCATE_ZEROED */
 
 		status = acpi_ut_release_mutex(ACPI_MTX_CACHES);
 		if (ACPI_FAILURE(status)) {
 			return (NULL);
 		}
 
-		object = ACPI_MEM_CALLOCATE(cache->object_size);
+		object = ACPI_ALLOCATE_ZEROED(cache->object_size);
 		if (!object) {
 			return (NULL);
 		}
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index df2d320..5e1a80d 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -109,7 +109,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ut_copy_isimple_to_esimple");
+	ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple);
 
 	*buffer_space_used = 0;
 
@@ -325,7 +325,7 @@
 	acpi_status status;
 	struct acpi_pkg_info info;
 
-	ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_epackage");
+	ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage);
 
 	/*
 	 * First package at head of the buffer
@@ -383,7 +383,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_copy_iobject_to_eobject");
+	ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject);
 
 	if (ACPI_GET_OBJECT_TYPE(internal_object) == ACPI_TYPE_PACKAGE) {
 		/*
@@ -442,7 +442,7 @@
 {
 	union acpi_operand_object *internal_object;
 
-	ACPI_FUNCTION_TRACE("ut_copy_esimple_to_isimple");
+	ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple);
 
 	/*
 	 * Simple types supported are: String, Buffer, Integer
@@ -472,8 +472,8 @@
 	case ACPI_TYPE_STRING:
 
 		internal_object->string.pointer =
-		    ACPI_MEM_CALLOCATE((acpi_size) external_object->string.
-				       length + 1);
+		    ACPI_ALLOCATE_ZEROED((acpi_size) external_object->string.
+					 length + 1);
 		if (!internal_object->string.pointer) {
 			goto error_exit;
 		}
@@ -488,7 +488,7 @@
 	case ACPI_TYPE_BUFFER:
 
 		internal_object->buffer.pointer =
-		    ACPI_MEM_CALLOCATE(external_object->buffer.length);
+		    ACPI_ALLOCATE_ZEROED(external_object->buffer.length);
 		if (!internal_object->buffer.pointer) {
 			goto error_exit;
 		}
@@ -552,7 +552,7 @@
 	union acpi_operand_object *this_internal_obj;
 	union acpi_object *this_external_obj;
 
-	ACPI_FUNCTION_TRACE("ut_copy_epackage_to_ipackage");
+	ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
 
 	/*
 	 * First package at head of the buffer
@@ -600,7 +600,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_copy_eobject_to_iobject");
+	ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
 
 	if (external_object->type == ACPI_TYPE_PACKAGE) {
 		/*
@@ -676,7 +676,7 @@
 		if ((source_desc->buffer.pointer) &&
 		    (source_desc->buffer.length)) {
 			dest_desc->buffer.pointer =
-			    ACPI_MEM_ALLOCATE(source_desc->buffer.length);
+			    ACPI_ALLOCATE(source_desc->buffer.length);
 			if (!dest_desc->buffer.pointer) {
 				return (AE_NO_MEMORY);
 			}
@@ -697,8 +697,8 @@
 		 */
 		if (source_desc->string.pointer) {
 			dest_desc->string.pointer =
-			    ACPI_MEM_ALLOCATE((acpi_size) source_desc->string.
-					      length + 1);
+			    ACPI_ALLOCATE((acpi_size) source_desc->string.
+					  length + 1);
 			if (!dest_desc->string.pointer) {
 				return (AE_NO_MEMORY);
 			}
@@ -805,9 +805,7 @@
 		/*
 		 * Create the object array
 		 */
-		target_object->package.elements =
-		    ACPI_MEM_CALLOCATE(((acpi_size) source_object->package.
-					count + 1) * sizeof(void *));
+		target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *));
 		if (!target_object->package.elements) {
 			status = AE_NO_MEMORY;
 			goto error_exit;
@@ -856,7 +854,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ut_copy_ipackage_to_ipackage");
+	ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage);
 
 	dest_obj->common.type = ACPI_GET_OBJECT_TYPE(source_obj);
 	dest_obj->common.flags = source_obj->common.flags;
@@ -865,10 +863,10 @@
 	/*
 	 * Create the object array and walk the source package tree
 	 */
-	dest_obj->package.elements = ACPI_MEM_CALLOCATE(((acpi_size)
-							 source_obj->package.
-							 count +
-							 1) * sizeof(void *));
+	dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
+							   source_obj->package.
+							   count +
+							   1) * sizeof(void *));
 	if (!dest_obj->package.elements) {
 		ACPI_ERROR((AE_INFO, "Package allocation failure"));
 		return_ACPI_STATUS(AE_NO_MEMORY);
@@ -882,6 +880,7 @@
 					   acpi_ut_copy_ielement_to_ielement,
 					   walk_state);
 	if (ACPI_FAILURE(status)) {
+
 		/* On failure, delete the destination package object */
 
 		acpi_ut_remove_reference(dest_obj);
@@ -911,7 +910,7 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("ut_copy_iobject_to_iobject");
+	ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject);
 
 	/* Create the top level object */
 
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index 35f3d58..5ec1cfc 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 
 #define _COMPONENT          ACPI_UTILITIES
@@ -123,12 +121,14 @@
 	/* All Function names are longer than 4 chars, check is safe */
 
 	if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_MIXED) {
+
 		/* This is the case where the original source has not been modified */
 
 		return (function_name + 4);
 	}
 
 	if (*(ACPI_CAST_PTR(u32, function_name)) == ACPI_PREFIX_LOWER) {
+
 		/* This is the case where the source has been 'linuxized' */
 
 		return (function_name + 5);
@@ -162,7 +162,7 @@
 		    const char *function_name,
 		    char *module_name, u32 component_id, char *format, ...)
 {
-	u32 thread_id;
+	acpi_thread_id thread_id;
 	va_list args;
 
 	/*
@@ -177,7 +177,6 @@
 	 * Thread tracking and context switch notification
 	 */
 	thread_id = acpi_os_get_thread_id();
-
 	if (thread_id != acpi_gbl_prev_thread_id) {
 		if (ACPI_LV_THREADS & acpi_dbg_level) {
 			acpi_os_printf
@@ -206,7 +205,7 @@
 	acpi_os_vprintf(format, args);
 }
 
-EXPORT_SYMBOL(acpi_ut_debug_print);
+ACPI_EXPORT_SYMBOL(acpi_ut_debug_print)
 
 /*******************************************************************************
  *
@@ -226,7 +225,6 @@
  *              debug_print so that the same macros can be used.
  *
  ******************************************************************************/
-
 void ACPI_INTERNAL_VAR_XFACE
 acpi_ut_debug_print_raw(u32 requested_debug_level,
 			u32 line_number,
@@ -244,7 +242,7 @@
 	acpi_os_vprintf(format, args);
 }
 
-EXPORT_SYMBOL(acpi_ut_debug_print_raw);
+ACPI_EXPORT_SYMBOL(acpi_ut_debug_print_raw)
 
 /*******************************************************************************
  *
@@ -261,7 +259,6 @@
  *              set in debug_level
  *
  ******************************************************************************/
-
 void
 acpi_ut_trace(u32 line_number,
 	      const char *function_name, char *module_name, u32 component_id)
@@ -275,7 +272,7 @@
 			    component_id, "%s\n", acpi_gbl_fn_entry_str);
 }
 
-EXPORT_SYMBOL(acpi_ut_trace);
+ACPI_EXPORT_SYMBOL(acpi_ut_trace)
 
 /*******************************************************************************
  *
@@ -293,7 +290,6 @@
  *              set in debug_level
  *
  ******************************************************************************/
-
 void
 acpi_ut_trace_ptr(u32 line_number,
 		  const char *function_name,
@@ -400,7 +396,7 @@
 	acpi_gbl_nesting_level--;
 }
 
-EXPORT_SYMBOL(acpi_ut_exit);
+ACPI_EXPORT_SYMBOL(acpi_ut_exit)
 
 /*******************************************************************************
  *
@@ -418,7 +414,6 @@
  *              set in debug_level. Prints exit status also.
  *
  ******************************************************************************/
-
 void
 acpi_ut_status_exit(u32 line_number,
 		    const char *function_name,
@@ -442,7 +437,7 @@
 	acpi_gbl_nesting_level--;
 }
 
-EXPORT_SYMBOL(acpi_ut_status_exit);
+ACPI_EXPORT_SYMBOL(acpi_ut_status_exit)
 
 /*******************************************************************************
  *
@@ -460,7 +455,6 @@
  *              set in debug_level. Prints exit value also.
  *
  ******************************************************************************/
-
 void
 acpi_ut_value_exit(u32 line_number,
 		   const char *function_name,
@@ -475,7 +469,7 @@
 	acpi_gbl_nesting_level--;
 }
 
-EXPORT_SYMBOL(acpi_ut_value_exit);
+ACPI_EXPORT_SYMBOL(acpi_ut_value_exit)
 
 /*******************************************************************************
  *
@@ -493,7 +487,6 @@
  *              set in debug_level. Prints exit value also.
  *
  ******************************************************************************/
-
 void
 acpi_ut_ptr_exit(u32 line_number,
 		 const char *function_name,
@@ -524,20 +517,13 @@
  *
  ******************************************************************************/
 
-void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
+void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display)
 {
 	acpi_native_uint i = 0;
 	acpi_native_uint j;
 	u32 temp32;
 	u8 buf_char;
 
-	/* Only dump the buffer if tracing is enabled */
-
-	if (!((ACPI_LV_TABLES & acpi_dbg_level) &&
-	      (component_id & acpi_dbg_layer))) {
-		return;
-	}
-
 	if ((count < 4) || (count & 0x01)) {
 		display = DB_BYTE_DISPLAY;
 	}
@@ -545,6 +531,7 @@
 	/* Nasty little dump buffer routine! */
 
 	while (i < count) {
+
 		/* Print current offset */
 
 		acpi_os_printf("%6.4X: ", (u32) i);
@@ -553,6 +540,7 @@
 
 		for (j = 0; j < 16;) {
 			if (i + j >= count) {
+
 				/* Dump fill spaces */
 
 				acpi_os_printf("%*s", ((display * 2) + 1), " ");
@@ -561,6 +549,7 @@
 			}
 
 			switch (display) {
+			case DB_BYTE_DISPLAY:
 			default:	/* Default is BYTE display */
 
 				acpi_os_printf("%02X ", buffer[i + j]);
@@ -618,3 +607,31 @@
 
 	return;
 }
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_dump_buffer
+ *
+ * PARAMETERS:  Buffer              - Buffer to dump
+ *              Count               - Amount to dump, in bytes
+ *              Display             - BYTE, WORD, DWORD, or QWORD display
+ *              component_iD        - Caller's component ID
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Generic dump buffer in both hex and ascii.
+ *
+ ******************************************************************************/
+
+void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id)
+{
+
+	/* Only dump the buffer if tracing is enabled */
+
+	if (!((ACPI_LV_TABLES & acpi_dbg_level) &&
+	      (component_id & acpi_dbg_layer))) {
+		return;
+	}
+
+	acpi_ut_dump_buffer2(buffer, count, display);
+}
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 1db9695..67b9f32 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -76,7 +76,7 @@
 	union acpi_operand_object *second_desc;
 	union acpi_operand_object *next_desc;
 
-	ACPI_FUNCTION_TRACE_PTR("ut_delete_internal_obj", object);
+	ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object);
 
 	if (!object) {
 		return_VOID;
@@ -96,6 +96,7 @@
 		/* Free the actual string buffer */
 
 		if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
+
 			/* But only if it is NOT a pointer into an ACPI table */
 
 			obj_pointer = object->string.pointer;
@@ -111,6 +112,7 @@
 		/* Free the actual buffer */
 
 		if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
+
 			/* But only if it is NOT a pointer into an ACPI table */
 
 			obj_pointer = object->buffer.pointer;
@@ -198,11 +200,22 @@
 			 */
 			handler_desc = object->region.handler;
 			if (handler_desc) {
-				if (handler_desc->address_space.
-				    hflags &
+				if (handler_desc->address_space.handler_flags &
 				    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
-					obj_pointer =
-					    second_desc->extra.region_context;
+
+					/* Deactivate region and free region context */
+
+					if (handler_desc->address_space.setup) {
+						(void)handler_desc->
+						    address_space.setup(object,
+									ACPI_REGION_DEACTIVATE,
+									handler_desc->
+									address_space.
+									context,
+									&second_desc->
+									extra.
+									region_context);
+					}
 				}
 
 				acpi_ut_remove_reference(handler_desc);
@@ -234,7 +247,7 @@
 	if (obj_pointer) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
 				  "Deleting Object Subptr %p\n", obj_pointer));
-		ACPI_MEM_FREE(obj_pointer);
+		ACPI_FREE(obj_pointer);
 	}
 
 	/* Now the object can be safely deleted */
@@ -263,7 +276,7 @@
 {
 	union acpi_operand_object **internal_obj;
 
-	ACPI_FUNCTION_TRACE("ut_delete_internal_object_list");
+	ACPI_FUNCTION_TRACE(ut_delete_internal_object_list);
 
 	/* Walk the null-terminated internal list */
 
@@ -273,7 +286,7 @@
 
 	/* Free the combined parameter pointer list and object array */
 
-	ACPI_MEM_FREE(obj_list);
+	ACPI_FREE(obj_list);
 	return_VOID;
 }
 
@@ -296,7 +309,7 @@
 	u16 count;
 	u16 new_count;
 
-	ACPI_FUNCTION_NAME("ut_update_ref_count");
+	ACPI_FUNCTION_NAME(ut_update_ref_count);
 
 	if (!object) {
 		return;
@@ -306,11 +319,9 @@
 	new_count = count;
 
 	/*
-	 * Perform the reference count action
-	 * (increment, decrement, or force delete)
+	 * Perform the reference count action (increment, decrement, force delete)
 	 */
 	switch (action) {
-
 	case REF_INCREMENT:
 
 		new_count++;
@@ -347,7 +358,6 @@
 		if (new_count == 0) {
 			acpi_ut_delete_internal_obj(object);
 		}
-
 		break;
 
 	case REF_FORCE_DELETE:
@@ -372,13 +382,10 @@
 	 * (A deleted object will have a huge reference count)
 	 */
 	if (count > ACPI_MAX_REFERENCE_COUNT) {
-
 		ACPI_WARNING((AE_INFO,
-			      "Large Reference Count (%X) in object %p",
-			      count, object));
+			      "Large Reference Count (%X) in object %p", count,
+			      object));
 	}
-
-	return;
 }
 
 /*******************************************************************************
@@ -404,7 +411,7 @@
  ******************************************************************************/
 
 acpi_status
-acpi_ut_update_object_reference(union acpi_operand_object * object, u16 action)
+acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
 {
 	acpi_status status = AE_OK;
 	union acpi_generic_state *state_list = NULL;
@@ -412,9 +419,10 @@
 	union acpi_generic_state *state;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE_PTR("ut_update_object_reference", object);
+	ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object);
 
 	while (object) {
+
 		/* Make sure that this isn't a namespace handle */
 
 		if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) {
@@ -507,11 +515,11 @@
 
 		case ACPI_TYPE_REGION:
 		default:
-			break;	/* No subobjects */
+			break;	/* No subobjects for all other types */
 		}
 
 		/*
-		 * Now we can update the count in the main object.  This can only
+		 * Now we can update the count in the main object. This can only
 		 * happen after we update the sub-objects in case this causes the
 		 * main object to be deleted.
 		 */
@@ -556,7 +564,7 @@
 void acpi_ut_add_reference(union acpi_operand_object *object)
 {
 
-	ACPI_FUNCTION_TRACE_PTR("ut_add_reference", object);
+	ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object);
 
 	/* Ensure that we have a valid object */
 
@@ -589,11 +597,11 @@
 void acpi_ut_remove_reference(union acpi_operand_object *object)
 {
 
-	ACPI_FUNCTION_TRACE_PTR("ut_remove_reference", object);
+	ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object);
 
 	/*
-	 * Allow a NULL pointer to be passed in, just ignore it.  This saves
-	 * each caller from having to check.  Also, ignore NS nodes.
+	 * Allow a NULL pointer to be passed in, just ignore it. This saves
+	 * each caller from having to check. Also, ignore NS nodes.
 	 *
 	 */
 	if (!object ||
@@ -613,7 +621,7 @@
 
 	/*
 	 * Decrement the reference count, and only actually delete the object
-	 * if the reference count becomes 0.  (Must also decrement the ref count
+	 * if the reference count becomes 0. (Must also decrement the ref count
 	 * of all subobjects!)
 	 */
 	(void)acpi_ut_update_object_reference(object, REF_DECREMENT);
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c
index 106cc97..d6d7121 100644
--- a/drivers/acpi/utilities/uteval.c
+++ b/drivers/acpi/utilities/uteval.c
@@ -56,6 +56,34 @@
 acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc,
 			  struct acpi_compatible_id *one_cid);
 
+/*
+ * Strings supported by the _OSI predefined (internal) method.
+ */
+static const char *acpi_interfaces_supported[] = {
+	/* Operating System Vendor Strings */
+
+	"Linux",
+	"Windows 2000",
+	"Windows 2001",
+	"Windows 2001 SP0",
+	"Windows 2001 SP1",
+	"Windows 2001 SP2",
+	"Windows 2001 SP3",
+	"Windows 2001 SP4",
+	"Windows 2001.1",
+	"Windows 2001.1 SP1",	/* Added 03/2006 */
+	"Windows 2006",		/* Added 03/2006 */
+
+	/* Feature Group Strings */
+
+	"Extended Address Space Descriptor"
+	    /*
+	     * All "optional" feature group strings (features that are implemented
+	     * by the host) should be implemented in the host version of
+	     * acpi_os_validate_interface and should not be added here.
+	     */
+};
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_osi_implementation
@@ -64,18 +92,18 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Implementation of _OSI predefined control method
- *              Supported = _OSI (String)
+ * DESCRIPTION: Implementation of the _OSI predefined control method
  *
  ******************************************************************************/
 
 acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
 {
+	acpi_status status;
 	union acpi_operand_object *string_desc;
 	union acpi_operand_object *return_desc;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE("ut_osi_implementation");
+	ACPI_FUNCTION_TRACE(ut_osi_implementation);
 
 	/* Validate the string input argument */
 
@@ -84,28 +112,47 @@
 		return_ACPI_STATUS(AE_TYPE);
 	}
 
-	/* Create a return object (Default value = 0) */
+	/* Create a return object */
 
 	return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
 	if (!return_desc) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
 
-	/* Compare input string to table of supported strings */
+	/* Default return value is SUPPORTED */
 
-	for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
-		if (!ACPI_STRCMP(string_desc->string.pointer,
-				 ACPI_CAST_PTR(char,
-					       acpi_gbl_valid_osi_strings[i])))
-		{
-			/* This string is supported */
+	return_desc->integer.value = ACPI_UINT32_MAX;
+	walk_state->return_desc = return_desc;
 
-			return_desc->integer.value = 0xFFFFFFFF;
-			break;
+	/* Compare input string to static table of supported interfaces */
+
+	for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
+		if (!ACPI_STRCMP
+		    (string_desc->string.pointer,
+		     acpi_interfaces_supported[i])) {
+
+			/* The interface is supported */
+
+			return_ACPI_STATUS(AE_CTRL_TERMINATE);
 		}
 	}
 
-	walk_state->return_desc = return_desc;
+	/*
+	 * Did not match the string in the static table, call the host OSL to
+	 * check for a match with one of the optional strings (such as
+	 * "Module Device", "3.0 Thermal Model", etc.)
+	 */
+	status = acpi_os_validate_interface(string_desc->string.pointer);
+	if (ACPI_SUCCESS(status)) {
+
+		/* The interface is supported */
+
+		return_ACPI_STATUS(AE_CTRL_TERMINATE);
+	}
+
+	/* The interface is not supported */
+
+	return_desc->integer.value = 0;
 	return_ACPI_STATUS(AE_CTRL_TERMINATE);
 }
 
@@ -134,19 +181,26 @@
 			u32 expected_return_btypes,
 			union acpi_operand_object **return_desc)
 {
-	struct acpi_parameter_info info;
+	struct acpi_evaluate_info *info;
 	acpi_status status;
 	u32 return_btype;
 
-	ACPI_FUNCTION_TRACE("ut_evaluate_object");
+	ACPI_FUNCTION_TRACE(ut_evaluate_object);
 
-	info.node = prefix_node;
-	info.parameters = NULL;
-	info.parameter_type = ACPI_PARAM_ARGS;
+	/* Allocate the evaluation information block */
+
+	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
+	if (!info) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	info->prefix_node = prefix_node;
+	info->pathname = path;
+	info->parameter_type = ACPI_PARAM_ARGS;
 
 	/* Evaluate the object/method */
 
-	status = acpi_ns_evaluate_relative(path, &info);
+	status = acpi_ns_evaluate(info);
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_NOT_FOUND) {
 			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
@@ -158,25 +212,25 @@
 					  prefix_node, path, status);
 		}
 
-		return_ACPI_STATUS(status);
+		goto cleanup;
 	}
 
 	/* Did we get a return object? */
 
-	if (!info.return_object) {
+	if (!info->return_object) {
 		if (expected_return_btypes) {
 			ACPI_ERROR_METHOD("No object was returned from",
 					  prefix_node, path, AE_NOT_EXIST);
 
-			return_ACPI_STATUS(AE_NOT_EXIST);
+			status = AE_NOT_EXIST;
 		}
 
-		return_ACPI_STATUS(AE_OK);
+		goto cleanup;
 	}
 
 	/* Map the return object type to the bitmapped type */
 
-	switch (ACPI_GET_OBJECT_TYPE(info.return_object)) {
+	switch (ACPI_GET_OBJECT_TYPE(info->return_object)) {
 	case ACPI_TYPE_INTEGER:
 		return_btype = ACPI_BTYPE_INTEGER;
 		break;
@@ -204,8 +258,8 @@
 		 * happen frequently if the "implicit return" feature is enabled.
 		 * Just delete the return object and return AE_OK.
 		 */
-		acpi_ut_remove_reference(info.return_object);
-		return_ACPI_STATUS(AE_OK);
+		acpi_ut_remove_reference(info->return_object);
+		goto cleanup;
 	}
 
 	/* Is the return object one of the expected types? */
@@ -217,19 +271,23 @@
 		ACPI_ERROR((AE_INFO,
 			    "Type returned from %s was incorrect: %s, expected Btypes: %X",
 			    path,
-			    acpi_ut_get_object_type_name(info.return_object),
+			    acpi_ut_get_object_type_name(info->return_object),
 			    expected_return_btypes));
 
 		/* On error exit, we must delete the return object */
 
-		acpi_ut_remove_reference(info.return_object);
-		return_ACPI_STATUS(AE_TYPE);
+		acpi_ut_remove_reference(info->return_object);
+		status = AE_TYPE;
+		goto cleanup;
 	}
 
 	/* Object type is OK, return it */
 
-	*return_desc = info.return_object;
-	return_ACPI_STATUS(AE_OK);
+	*return_desc = info->return_object;
+
+      cleanup:
+	ACPI_FREE(info);
+	return_ACPI_STATUS(status);
 }
 
 /*******************************************************************************
@@ -257,7 +315,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_evaluate_numeric_object");
+	ACPI_FUNCTION_TRACE(ut_evaluate_numeric_object);
 
 	status = acpi_ut_evaluate_object(device_node, object_name,
 					 ACPI_BTYPE_INTEGER, &obj_desc);
@@ -333,7 +391,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_execute_HID");
+	ACPI_FUNCTION_TRACE(ut_execute_HID);
 
 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
@@ -343,6 +401,7 @@
 	}
 
 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
 		/* Convert the Numeric HID to string */
 
 		acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value,
@@ -436,7 +495,7 @@
 	struct acpi_compatible_id_list *cid_list;
 	acpi_native_uint i;
 
-	ACPI_FUNCTION_TRACE("ut_execute_CID");
+	ACPI_FUNCTION_TRACE(ut_execute_CID);
 
 	/* Evaluate the _CID method for this device */
 
@@ -459,7 +518,7 @@
 	size = (((count - 1) * sizeof(struct acpi_compatible_id)) +
 		sizeof(struct acpi_compatible_id_list));
 
-	cid_list = ACPI_MEM_CALLOCATE((acpi_size) size);
+	cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size);
 	if (!cid_list) {
 		return_ACPI_STATUS(AE_NO_MEMORY);
 	}
@@ -479,6 +538,7 @@
 	/* The _CID object can be either a single CID or a package (list) of CIDs */
 
 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_PACKAGE) {
+
 		/* Translate each package element */
 
 		for (i = 0; i < count; i++) {
@@ -499,7 +559,7 @@
 	/* Cleanup on error */
 
 	if (ACPI_FAILURE(status)) {
-		ACPI_MEM_FREE(cid_list);
+		ACPI_FREE(cid_list);
 	} else {
 		*return_cid_list = cid_list;
 	}
@@ -533,7 +593,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_execute_UID");
+	ACPI_FUNCTION_TRACE(ut_execute_UID);
 
 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
 					 ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
@@ -543,6 +603,7 @@
 	}
 
 	if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
+
 		/* Convert the Numeric UID to string */
 
 		acpi_ex_unsigned_integer_to_string(obj_desc->integer.value,
@@ -582,7 +643,7 @@
 	union acpi_operand_object *obj_desc;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_execute_STA");
+	ACPI_FUNCTION_TRACE(ut_execute_STA);
 
 	status = acpi_ut_evaluate_object(device_node, METHOD_NAME__STA,
 					 ACPI_BTYPE_INTEGER, &obj_desc);
@@ -632,7 +693,7 @@
 	acpi_status status;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ut_execute_Sxds");
+	ACPI_FUNCTION_TRACE(ut_execute_sxds);
 
 	for (i = 0; i < 4; i++) {
 		highest[i] = 0xFF;
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index ffd1338..e5999c6 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -43,7 +43,6 @@
 
 #define DEFINE_ACPI_GLOBALS
 
-#include <linux/module.h>
 #include <acpi/acpi.h>
 #include <acpi/acnamesp.h>
 
@@ -119,6 +118,7 @@
 	}
 
 	if (!exception) {
+
 		/* Exception code was not recognized */
 
 		ACPI_ERROR((AE_INFO,
@@ -143,12 +143,10 @@
 
 /* Debug switch - level and trace mask */
 u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
-EXPORT_SYMBOL(acpi_dbg_level);
 
 /* Debug switch - layer (component) mask */
 
 u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS;
-EXPORT_SYMBOL(acpi_dbg_layer);
 u32 acpi_gbl_nesting_level = 0;
 
 /* Debugger globals */
@@ -183,28 +181,6 @@
 	"_S4D"
 };
 
-/*
- * Strings supported by the _OSI predefined (internal) method.
- * When adding strings, be sure to update ACPI_NUM_OSI_STRINGS.
- */
-const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
-	/* Operating System Vendor Strings */
-
-	"Linux",
-	"Windows 2000",
-	"Windows 2001",
-	"Windows 2001.1",
-	"Windows 2001 SP0",
-	"Windows 2001 SP1",
-	"Windows 2001 SP2",
-	"Windows 2001 SP3",
-	"Windows 2001 SP4",
-
-	/* Feature Group Strings */
-
-	"Extended Address Space Descriptor"
-};
-
 /*******************************************************************************
  *
  * Namespace globals
@@ -317,9 +293,9 @@
  *
  ******************************************************************************/
 
-struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
+struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1];
 
-struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = {
+struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1] = {
 	/***********    Name,   Signature, Global typed pointer     Signature size,      Type                  How many allowed?,    Contains valid AML? */
 
 	/* RSDP 0 */ {RSDP_NAME, RSDP_SIG, NULL, sizeof(RSDP_SIG) - 1,
@@ -467,7 +443,6 @@
 /* Region type decoding */
 
 const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
-/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
 	"SystemMemory",
 	"SystemIO",
 	"PCI_Config",
@@ -476,16 +451,15 @@
 	"CMOS",
 	"PCIBARTarget",
 	"DataTable"
-/*! [End] no source code translation !*/
 };
 
 char *acpi_ut_get_region_name(u8 space_id)
 {
 
 	if (space_id >= ACPI_USER_REGION_BEGIN) {
-		return ("user_defined_region");
+		return ("UserDefinedRegion");
 	} else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) {
-		return ("invalid_space_id");
+		return ("InvalidSpaceId");
 	}
 
 	return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
@@ -506,20 +480,18 @@
 /* Event type decoding */
 
 static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
-/*! [Begin] no source code translation (keep these strings as-is) */
 	"PM_Timer",
 	"GlobalLock",
 	"PowerButton",
 	"SleepButton",
 	"RealTimeClock",
-/*! [End] no source code translation !*/
 };
 
 char *acpi_ut_get_event_name(u32 event_id)
 {
 
 	if (event_id > ACPI_EVENT_MAX) {
-		return ("invalid_event_iD");
+		return ("InvalidEventID");
 	}
 
 	return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
@@ -550,7 +522,6 @@
 /* Printable names of the ACPI object types */
 
 static const char *acpi_gbl_ns_type_names[] = {
-/*! [Begin] no source code translation (keep these strings as-is) */
 	/* 00 */ "Untyped",
 	/* 01 */ "Integer",
 	/* 02 */ "String",
@@ -582,7 +553,6 @@
 	/* 28 */ "Extra",
 	/* 29 */ "Data",
 	/* 30 */ "Invalid"
-/*! [End] no source code translation !*/
 };
 
 char *acpi_ut_get_type_name(acpi_object_type type)
@@ -635,14 +605,14 @@
 
 	/* Descriptor must be a namespace node */
 
-	if (node->descriptor != ACPI_DESC_TYPE_NAMED) {
+	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
 		return ("####");
 	}
 
 	/* Name must be a valid ACPI name */
 
 	if (!acpi_ut_valid_acpi_name(node->name.integer)) {
-		return ("????");
+		node->name.integer = acpi_ut_repair_name(node->name.integer);
 	}
 
 	/* Return the name */
@@ -665,7 +635,6 @@
 /* Printable names of object descriptor types */
 
 static const char *acpi_gbl_desc_type_names[] = {
-/*! [Begin] no source code translation (keep these ASL Keywords as-is) */
 	/* 00 */ "Invalid",
 	/* 01 */ "Cached",
 	/* 02 */ "State-Generic",
@@ -682,7 +651,6 @@
 	/* 13 */ "Parser",
 	/* 14 */ "Operand",
 	/* 15 */ "Node"
-/*! [End] no source code translation !*/
 };
 
 char *acpi_ut_get_descriptor_name(void *object)
@@ -723,7 +691,7 @@
 char *acpi_ut_get_mutex_name(u32 mutex_id)
 {
 
-	if (mutex_id > MAX_MUTEX) {
+	if (mutex_id > ACPI_MAX_MUTEX) {
 		return ("Invalid Mutex ID");
 	}
 
@@ -747,6 +715,7 @@
 {
 
 	if (type > ACPI_TYPE_LOCAL_MAX) {
+
 		/* Note: Assumes all TYPEs are contiguous (external/local) */
 
 		return (FALSE);
@@ -773,7 +742,7 @@
 	acpi_status status;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ut_init_globals");
+	ACPI_FUNCTION_TRACE(ut_init_globals);
 
 	/* Create all memory caches */
 
@@ -784,14 +753,14 @@
 
 	/* ACPI table structure */
 
-	for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
+	for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
 		acpi_gbl_table_lists[i].next = NULL;
 		acpi_gbl_table_lists[i].count = 0;
 	}
 
 	/* Mutex locked flags */
 
-	for (i = 0; i < NUM_MUTEX; i++) {
+	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
 		acpi_gbl_mutex_info[i].mutex = NULL;
 		acpi_gbl_mutex_info[i].thread_id = ACPI_MUTEX_NOT_ACQUIRED;
 		acpi_gbl_mutex_info[i].use_count = 0;
@@ -856,7 +825,7 @@
 
 	acpi_gbl_root_node = NULL;
 	acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
-	acpi_gbl_root_node_struct.descriptor = ACPI_DESC_TYPE_NAMED;
+	acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
 	acpi_gbl_root_node_struct.type = ACPI_TYPE_DEVICE;
 	acpi_gbl_root_node_struct.child = NULL;
 	acpi_gbl_root_node_struct.peer = NULL;
@@ -869,3 +838,6 @@
 
 	return_VOID;
 }
+
+ACPI_EXPORT_SYMBOL(acpi_dbg_level)
+ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
diff --git a/drivers/acpi/utilities/utinit.c b/drivers/acpi/utilities/utinit.c
index ba771b4..ff76055 100644
--- a/drivers/acpi/utilities/utinit.c
+++ b/drivers/acpi/utilities/utinit.c
@@ -50,7 +50,7 @@
 
 /* Local prototypes */
 static void
-acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset);
+acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset);
 
 static void acpi_ut_terminate(void);
 
@@ -69,12 +69,12 @@
  ******************************************************************************/
 
 static void
-acpi_ut_fadt_register_error(char *register_name, u32 value, acpi_size offset)
+acpi_ut_fadt_register_error(char *register_name, u32 value, u8 offset)
 {
 
 	ACPI_WARNING((AE_INFO,
 		      "Invalid FADT value %s=%X at offset %X FADT=%p",
-		      register_name, value, (u32) offset, acpi_gbl_FADT));
+		      register_name, value, offset, acpi_gbl_FADT));
 }
 
 /******************************************************************************
@@ -176,7 +176,7 @@
 	struct acpi_gpe_xrupt_info *gpe_xrupt_info;
 	struct acpi_gpe_xrupt_info *next_gpe_xrupt_info;
 
-	ACPI_FUNCTION_TRACE("ut_terminate");
+	ACPI_FUNCTION_TRACE(ut_terminate);
 
 	/* Free global tables, etc. */
 	/* Free global GPE blocks and related info structures */
@@ -186,14 +186,14 @@
 		gpe_block = gpe_xrupt_info->gpe_block_list_head;
 		while (gpe_block) {
 			next_gpe_block = gpe_block->next;
-			ACPI_MEM_FREE(gpe_block->event_info);
-			ACPI_MEM_FREE(gpe_block->register_info);
-			ACPI_MEM_FREE(gpe_block);
+			ACPI_FREE(gpe_block->event_info);
+			ACPI_FREE(gpe_block->register_info);
+			ACPI_FREE(gpe_block);
 
 			gpe_block = next_gpe_block;
 		}
 		next_gpe_xrupt_info = gpe_xrupt_info->next;
-		ACPI_MEM_FREE(gpe_xrupt_info);
+		ACPI_FREE(gpe_xrupt_info);
 		gpe_xrupt_info = next_gpe_xrupt_info;
 	}
 
@@ -216,7 +216,7 @@
 void acpi_ut_subsystem_shutdown(void)
 {
 
-	ACPI_FUNCTION_TRACE("ut_subsystem_shutdown");
+	ACPI_FUNCTION_TRACE(ut_subsystem_shutdown);
 
 	/* Just exit if subsystem is already shutdown */
 
@@ -228,6 +228,7 @@
 	/* Subsystem appears active, go ahead and shut it down */
 
 	acpi_gbl_shutdown = TRUE;
+	acpi_gbl_startup_flags = 0;
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
 
 	/* Close the acpi_event Handling */
@@ -245,12 +246,5 @@
 	/* Purge the local caches */
 
 	(void)acpi_ut_delete_caches();
-
-	/* Debug only - display leftover memory allocation, if any */
-
-#ifdef ACPI_DBG_TRACK_ALLOCATIONS
-	acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL);
-#endif
-
 	return_VOID;
 }
diff --git a/drivers/acpi/utilities/utmath.c b/drivers/acpi/utilities/utmath.c
index 4a33604..19d74be 100644
--- a/drivers/acpi/utilities/utmath.c
+++ b/drivers/acpi/utilities/utmath.c
@@ -77,7 +77,7 @@
 	union uint64_overlay quotient;
 	u32 remainder32;
 
-	ACPI_FUNCTION_TRACE("ut_short_divide");
+	ACPI_FUNCTION_TRACE(ut_short_divide);
 
 	/* Always check for a zero divisor */
 
@@ -139,7 +139,7 @@
 	union uint64_overlay partial2;
 	union uint64_overlay partial3;
 
-	ACPI_FUNCTION_TRACE("ut_divide");
+	ACPI_FUNCTION_TRACE(ut_divide);
 
 	/* Always check for a zero divisor */
 
@@ -261,7 +261,7 @@
 		     acpi_integer * out_quotient, u32 * out_remainder)
 {
 
-	ACPI_FUNCTION_TRACE("ut_short_divide");
+	ACPI_FUNCTION_TRACE(ut_short_divide);
 
 	/* Always check for a zero divisor */
 
@@ -287,7 +287,7 @@
 	       acpi_integer in_divisor,
 	       acpi_integer * out_quotient, acpi_integer * out_remainder)
 {
-	ACPI_FUNCTION_TRACE("ut_divide");
+	ACPI_FUNCTION_TRACE(ut_divide);
 
 	/* Always check for a zero divisor */
 
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 7364f5f..5c75d35 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -49,6 +49,33 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_is_aml_table
+ *
+ * PARAMETERS:  Table               - An ACPI table
+ *
+ * RETURN:      TRUE if table contains executable AML; FALSE otherwise
+ *
+ * DESCRIPTION: Check ACPI Signature for a table that contains AML code.
+ *              Currently, these are DSDT,SSDT,PSDT. All other table types are
+ *              data tables that do not contain AML code.
+ *
+ ******************************************************************************/
+u8 acpi_ut_is_aml_table(struct acpi_table_header *table)
+{
+
+	/* Ignore tables that contain AML */
+
+	if (ACPI_COMPARE_NAME(table->signature, DSDT_SIG) ||
+	    ACPI_COMPARE_NAME(table->signature, PSDT_SIG) ||
+	    ACPI_COMPARE_NAME(table->signature, SSDT_SIG)) {
+		return (TRUE);
+	}
+
+	return (FALSE);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_allocate_owner_id
  *
  * PARAMETERS:  owner_id        - Where the new owner ID is returned
@@ -60,6 +87,7 @@
  *              when the method exits or the table is unloaded.
  *
  ******************************************************************************/
+
 acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id)
 {
 	acpi_native_uint i;
@@ -67,7 +95,7 @@
 	acpi_native_uint k;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_allocate_owner_id");
+	ACPI_FUNCTION_TRACE(ut_allocate_owner_id);
 
 	/* Guard against multiple allocations of ID to the same location */
 
@@ -97,6 +125,7 @@
 
 		for (k = acpi_gbl_next_owner_id_offset; k < 32; k++) {
 			if (acpi_gbl_owner_id_mask[j] == ACPI_UINT32_MAX) {
+
 				/* There are no free IDs in this mask */
 
 				break;
@@ -123,7 +152,7 @@
 				    (acpi_owner_id) ((k + 1) + ACPI_MUL_32(j));
 
 				ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
-						  "Allocated owner_id: %2.2X\n",
+						  "Allocated OwnerId: %2.2X\n",
 						  (unsigned int)*owner_id));
 				goto exit;
 			}
@@ -144,7 +173,7 @@
 	 */
 	status = AE_OWNER_ID_LIMIT;
 	ACPI_ERROR((AE_INFO,
-		    "Could not allocate new owner_id (255 max), AE_OWNER_ID_LIMIT"));
+		    "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT"));
 
       exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_CACHES);
@@ -172,7 +201,7 @@
 	acpi_native_uint index;
 	u32 bit;
 
-	ACPI_FUNCTION_TRACE_U32("ut_release_owner_id", owner_id);
+	ACPI_FUNCTION_TRACE_U32(ut_release_owner_id, owner_id);
 
 	/* Always clear the input owner_id (zero is an invalid ID) */
 
@@ -181,7 +210,7 @@
 	/* Zero is not a valid owner_iD */
 
 	if (owner_id == 0) {
-		ACPI_ERROR((AE_INFO, "Invalid owner_id: %2.2X", owner_id));
+		ACPI_ERROR((AE_INFO, "Invalid OwnerId: %2.2X", owner_id));
 		return_VOID;
 	}
 
@@ -207,7 +236,7 @@
 		acpi_gbl_owner_id_mask[index] ^= bit;
 	} else {
 		ACPI_ERROR((AE_INFO,
-			    "Release of non-allocated owner_id: %2.2X",
+			    "Release of non-allocated OwnerId: %2.2X",
 			    owner_id + 1));
 	}
 
@@ -273,6 +302,7 @@
 
 	acpi_os_printf("\"");
 	for (i = 0; string[i] && (i < max_length); i++) {
+
 		/* Escape sequences */
 
 		switch (string[i]) {
@@ -461,12 +491,47 @@
 	}
 	acpi_os_printf("\n");
 
-	ACPI_MEM_FREE(buffer.pointer);
+	ACPI_FREE(buffer.pointer);
 }
 #endif
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_valid_acpi_char
+ *
+ * PARAMETERS:  Char            - The character to be examined
+ *
+ * RETURN:      TRUE if the character is valid, FALSE otherwise
+ *
+ * DESCRIPTION: Check for a valid ACPI character. Must be one of:
+ *              1) Upper case alpha
+ *              2) numeric
+ *              3) underscore
+ *
+ *              We allow a '!' as the last character because of the ASF! table
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position)
+{
+
+	if (!((character >= 'A' && character <= 'Z') ||
+	      (character >= '0' && character <= '9') || (character == '_'))) {
+
+		/* Allow a '!' in the last position */
+
+		if (character == '!' && position == 3) {
+			return (TRUE);
+		}
+
+		return (FALSE);
+	}
+
+	return (TRUE);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_valid_acpi_name
  *
  * PARAMETERS:  Name            - The name to be examined
@@ -482,19 +547,13 @@
 
 u8 acpi_ut_valid_acpi_name(u32 name)
 {
-	char *name_ptr = (char *)&name;
-	char character;
 	acpi_native_uint i;
 
 	ACPI_FUNCTION_ENTRY();
 
 	for (i = 0; i < ACPI_NAME_SIZE; i++) {
-		character = *name_ptr;
-		name_ptr++;
-
-		if (!((character == '_') ||
-		      (character >= 'A' && character <= 'Z') ||
-		      (character >= '0' && character <= '9'))) {
+		if (!acpi_ut_valid_acpi_char
+		    ((ACPI_CAST_PTR(char, &name))[i], i)) {
 			return (FALSE);
 		}
 	}
@@ -504,24 +563,37 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_valid_acpi_character
+ * FUNCTION:    acpi_ut_repair_name
  *
- * PARAMETERS:  Character           - The character to be examined
+ * PARAMETERS:  Name            - The ACPI name to be repaired
  *
- * RETURN:      1 if Character may appear in a name, else 0
+ * RETURN:      Repaired version of the name
  *
- * DESCRIPTION: Check for a printable character
+ * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and
+ *              return the new name.
  *
  ******************************************************************************/
 
-u8 acpi_ut_valid_acpi_character(char character)
+acpi_name acpi_ut_repair_name(acpi_name name)
 {
+	char *name_ptr = ACPI_CAST_PTR(char, &name);
+	char new_name[ACPI_NAME_SIZE];
+	acpi_native_uint i;
 
-	ACPI_FUNCTION_ENTRY();
+	for (i = 0; i < ACPI_NAME_SIZE; i++) {
+		new_name[i] = name_ptr[i];
 
-	return ((u8) ((character == '_') ||
-		      (character >= 'A' && character <= 'Z') ||
-		      (character >= '0' && character <= '9')));
+		/*
+		 * Replace a bad character with something printable, yet technically
+		 * still invalid. This prevents any collisions with existing "good"
+		 * names in the namespace.
+		 */
+		if (!acpi_ut_valid_acpi_char(name_ptr[i], i)) {
+			new_name[i] = '*';
+		}
+	}
+
+	return (*ACPI_CAST_PTR(u32, new_name));
 }
 
 /*******************************************************************************
@@ -529,7 +601,8 @@
  * FUNCTION:    acpi_ut_strtoul64
  *
  * PARAMETERS:  String          - Null terminated string
- *              Base            - Radix of the string: 10, 16, or ACPI_ANY_BASE
+ *              Base            - Radix of the string: 16 or ACPI_ANY_BASE;
+ *                                ACPI_ANY_BASE means 'in behalf of to_integer'
  *              ret_integer     - Where the converted integer is returned
  *
  * RETURN:      Status and Converted value
@@ -545,16 +618,17 @@
 	u32 this_digit = 0;
 	acpi_integer return_value = 0;
 	acpi_integer quotient;
+	acpi_integer dividend;
+	u32 to_integer_op = (base == ACPI_ANY_BASE);
+	u32 mode32 = (acpi_gbl_integer_byte_width == 4);
+	u8 valid_digits = 0;
+	u8 sign_of0x = 0;
+	u8 term = 0;
 
-	ACPI_FUNCTION_TRACE("ut_stroul64");
-
-	if ((!string) || !(*string)) {
-		goto error_exit;
-	}
+	ACPI_FUNCTION_TRACE(ut_stroul64);
 
 	switch (base) {
 	case ACPI_ANY_BASE:
-	case 10:
 	case 16:
 		break;
 
@@ -563,76 +637,110 @@
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
+	if (!string) {
+		goto error_exit;
+	}
+
 	/* Skip over any white space in the buffer */
 
-	while (ACPI_IS_SPACE(*string) || *string == '\t') {
+	while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) {
 		string++;
 	}
 
-	/*
-	 * If the input parameter Base is zero, then we need to
-	 * determine if it is decimal or hexadecimal:
-	 */
-	if (base == 0) {
+	if (to_integer_op) {
+		/*
+		 * Base equal to ACPI_ANY_BASE means 'to_integer operation case'.
+		 * We need to determine if it is decimal or hexadecimal.
+		 */
 		if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
+			sign_of0x = 1;
 			base = 16;
+
+			/* Skip over the leading '0x' */
 			string += 2;
 		} else {
 			base = 10;
 		}
 	}
 
-	/*
-	 * For hexadecimal base, skip over the leading
-	 * 0 or 0x, if they are present.
-	 */
-	if ((base == 16) &&
-	    (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
-		string += 2;
+	/* Any string left? Check that '0x' is not followed by white space. */
+
+	if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') {
+		if (to_integer_op) {
+			goto error_exit;
+		} else {
+			goto all_done;
+		}
 	}
 
-	/* Any string left? */
+	dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
 
-	if (!(*string)) {
-		goto error_exit;
-	}
+	/* At least one character in the string here */
 
 	/* Main loop: convert the string to a 64-bit integer */
 
 	while (*string) {
 		if (ACPI_IS_DIGIT(*string)) {
+
 			/* Convert ASCII 0-9 to Decimal value */
 
 			this_digit = ((u8) * string) - '0';
+		} else if (base == 10) {
+
+			/* Digit is out of range; possible in to_integer case only */
+
+			term = 1;
 		} else {
-			if (base == 10) {
-				/* Digit is out of range */
-
-				goto error_exit;
-			}
-
 			this_digit = (u8) ACPI_TOUPPER(*string);
 			if (ACPI_IS_XDIGIT((char)this_digit)) {
+
 				/* Convert ASCII Hex char to value */
 
 				this_digit = this_digit - 'A' + 10;
 			} else {
-				/*
-				 * We allow non-hex chars, just stop now, same as end-of-string.
-				 * See ACPI spec, string-to-integer conversion.
-				 */
+				term = 1;
+			}
+		}
+
+		if (term) {
+			if (to_integer_op) {
+				goto error_exit;
+			} else {
 				break;
 			}
+		} else if ((valid_digits == 0) && (this_digit == 0)
+			   && !sign_of0x) {
+
+			/* Skip zeros */
+			string++;
+			continue;
+		}
+
+		valid_digits++;
+
+		if (sign_of0x
+		    && ((valid_digits > 16)
+			|| ((valid_digits > 8) && mode32))) {
+			/*
+			 * This is to_integer operation case.
+			 * No any restrictions for string-to-integer conversion,
+			 * see ACPI spec.
+			 */
+			goto error_exit;
 		}
 
 		/* Divide the digit into the correct position */
 
 		(void)
-		    acpi_ut_short_divide((ACPI_INTEGER_MAX -
-					  (acpi_integer) this_digit), base,
-					 &quotient, NULL);
+		    acpi_ut_short_divide((dividend - (acpi_integer) this_digit),
+					 base, &quotient, NULL);
+
 		if (return_value > quotient) {
-			goto error_exit;
+			if (to_integer_op) {
+				goto error_exit;
+			} else {
+				break;
+			}
 		}
 
 		return_value *= base;
@@ -642,6 +750,8 @@
 
 	/* All done, normal exit */
 
+      all_done:
+
 	*ret_integer = return_value;
 	return_ACPI_STATUS(AE_OK);
 
@@ -719,7 +829,7 @@
 	u32 this_index;
 	union acpi_operand_object *this_source_obj;
 
-	ACPI_FUNCTION_TRACE("ut_walk_package_tree");
+	ACPI_FUNCTION_TRACE(ut_walk_package_tree);
 
 	state = acpi_ut_create_pkg_state(source_object, target_object, 0);
 	if (!state) {
@@ -727,6 +837,7 @@
 	}
 
 	while (state) {
+
 		/* Get one element of the package */
 
 		this_index = state->pkg.index;
@@ -814,31 +925,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_generate_checksum
- *
- * PARAMETERS:  Buffer          - Buffer to be scanned
- *              Length          - number of bytes to examine
- *
- * RETURN:      The generated checksum
- *
- * DESCRIPTION: Generate a checksum on a raw buffer
- *
- ******************************************************************************/
-
-u8 acpi_ut_generate_checksum(u8 * buffer, u32 length)
-{
-	u32 i;
-	signed char sum = 0;
-
-	for (i = 0; i < length; i++) {
-		sum = (signed char)(sum + buffer[i]);
-	}
-
-	return ((u8) (0 - sum));
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ut_error, acpi_ut_warning, acpi_ut_info
  *
  * PARAMETERS:  module_name         - Caller's module name (for error output)
@@ -900,36 +986,3 @@
 	acpi_os_vprintf(format, args);
 	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
 }
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_report_error, Warning, Info
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print error message
- *
- * Note: Legacy only, should be removed when no longer used by drivers.
- *
- ******************************************************************************/
-
-void acpi_ut_report_error(char *module_name, u32 line_number)
-{
-
-	acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
-}
-
-void acpi_ut_report_warning(char *module_name, u32 line_number)
-{
-
-	acpi_os_printf("ACPI Warning (%s-%04d): ", module_name, line_number);
-}
-
-void acpi_ut_report_info(char *module_name, u32 line_number)
-{
-
-	acpi_os_printf("ACPI (%s-%04d): ", module_name, line_number);
-}
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index 45a7244..25eb343 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/utilities/utmutex.c
@@ -68,19 +68,26 @@
 	u32 i;
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("ut_mutex_initialize");
+	ACPI_FUNCTION_TRACE(ut_mutex_initialize);
 
 	/*
 	 * Create each of the predefined mutex objects
 	 */
-	for (i = 0; i < NUM_MUTEX; i++) {
+	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
 		status = acpi_ut_create_mutex(i);
 		if (ACPI_FAILURE(status)) {
 			return_ACPI_STATUS(status);
 		}
 	}
 
+	/* Create the spinlocks for use at interrupt level */
+
 	status = acpi_os_create_lock(&acpi_gbl_gpe_lock);
+	if (ACPI_FAILURE(status)) {
+		return_ACPI_STATUS(status);
+	}
+
+	status = acpi_os_create_lock(&acpi_gbl_hardware_lock);
 	return_ACPI_STATUS(status);
 }
 
@@ -100,16 +107,19 @@
 {
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("ut_mutex_terminate");
+	ACPI_FUNCTION_TRACE(ut_mutex_terminate);
 
 	/*
 	 * Delete each predefined mutex object
 	 */
-	for (i = 0; i < NUM_MUTEX; i++) {
+	for (i = 0; i < ACPI_NUM_MUTEX; i++) {
 		(void)acpi_ut_delete_mutex(i);
 	}
 
+	/* Delete the spinlocks */
+
 	acpi_os_delete_lock(acpi_gbl_gpe_lock);
+	acpi_os_delete_lock(acpi_gbl_hardware_lock);
 	return_VOID;
 }
 
@@ -129,9 +139,9 @@
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_U32("ut_create_mutex", mutex_id);
+	ACPI_FUNCTION_TRACE_U32(ut_create_mutex, mutex_id);
 
-	if (mutex_id > MAX_MUTEX) {
+	if (mutex_id > ACPI_MAX_MUTEX) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -163,9 +173,9 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE_U32("ut_delete_mutex", mutex_id);
+	ACPI_FUNCTION_TRACE_U32(ut_delete_mutex, mutex_id);
 
-	if (mutex_id > MAX_MUTEX) {
+	if (mutex_id > ACPI_MAX_MUTEX) {
 		return_ACPI_STATUS(AE_BAD_PARAMETER);
 	}
 
@@ -192,11 +202,11 @@
 acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
 {
 	acpi_status status;
-	u32 this_thread_id;
+	acpi_thread_id this_thread_id;
 
-	ACPI_FUNCTION_NAME("ut_acquire_mutex");
+	ACPI_FUNCTION_NAME(ut_acquire_mutex);
 
-	if (mutex_id > MAX_MUTEX) {
+	if (mutex_id > ACPI_MAX_MUTEX) {
 		return (AE_BAD_PARAMETER);
 	}
 
@@ -213,7 +223,7 @@
 		 * the mutex ordering rule.  This indicates a coding error somewhere in
 		 * the ACPI subsystem code.
 		 */
-		for (i = mutex_id; i < MAX_MUTEX; i++) {
+		for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) {
 			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
 					ACPI_ERROR((AE_INFO,
@@ -275,16 +285,16 @@
 acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
 {
 	acpi_status status;
-	u32 this_thread_id;
+	acpi_thread_id this_thread_id;
 
-	ACPI_FUNCTION_NAME("ut_release_mutex");
+	ACPI_FUNCTION_NAME(ut_release_mutex);
 
 	this_thread_id = acpi_os_get_thread_id();
 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
 			  "Thread %X releasing Mutex [%s]\n", this_thread_id,
 			  acpi_ut_get_mutex_name(mutex_id)));
 
-	if (mutex_id > MAX_MUTEX) {
+	if (mutex_id > ACPI_MAX_MUTEX) {
 		return (AE_BAD_PARAMETER);
 	}
 
@@ -309,7 +319,7 @@
 		 * ordering rule.  This indicates a coding error somewhere in
 		 * the ACPI subsystem code.
 		 */
-		for (i = mutex_id; i < MAX_MUTEX; i++) {
+		for (i = mutex_id; i < ACPI_MAX_MUTEX; i++) {
 			if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
 				if (i == mutex_id) {
 					continue;
diff --git a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c
index 7ee2d1d..ba7d8ac 100644
--- a/drivers/acpi/utilities/utobject.c
+++ b/drivers/acpi/utilities/utobject.c
@@ -92,7 +92,7 @@
 	union acpi_operand_object *object;
 	union acpi_operand_object *second_object;
 
-	ACPI_FUNCTION_TRACE_STR("ut_create_internal_object_dbg",
+	ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg,
 				acpi_ut_get_type_name(type));
 
 	/* Allocate the raw object descriptor */
@@ -161,7 +161,7 @@
 	union acpi_operand_object *buffer_desc;
 	u8 *buffer = NULL;
 
-	ACPI_FUNCTION_TRACE_U32("ut_create_buffer_object", buffer_size);
+	ACPI_FUNCTION_TRACE_U32(ut_create_buffer_object, buffer_size);
 
 	/* Create a new Buffer object */
 
@@ -173,9 +173,10 @@
 	/* Create an actual buffer only if size > 0 */
 
 	if (buffer_size > 0) {
+
 		/* Allocate the actual buffer */
 
-		buffer = ACPI_MEM_CALLOCATE(buffer_size);
+		buffer = ACPI_ALLOCATE_ZEROED(buffer_size);
 		if (!buffer) {
 			ACPI_ERROR((AE_INFO, "Could not allocate size %X",
 				    (u32) buffer_size));
@@ -214,7 +215,7 @@
 	union acpi_operand_object *string_desc;
 	char *string;
 
-	ACPI_FUNCTION_TRACE_U32("ut_create_string_object", string_size);
+	ACPI_FUNCTION_TRACE_U32(ut_create_string_object, string_size);
 
 	/* Create a new String object */
 
@@ -227,7 +228,7 @@
 	 * Allocate the actual string buffer -- (Size + 1) for NULL terminator.
 	 * NOTE: Zero-length strings are NULL terminated
 	 */
-	string = ACPI_MEM_CALLOCATE(string_size + 1);
+	string = ACPI_ALLOCATE_ZEROED(string_size + 1);
 	if (!string) {
 		ACPI_ERROR((AE_INFO, "Could not allocate size %X",
 			    (u32) string_size));
@@ -260,7 +261,7 @@
 u8 acpi_ut_valid_internal_object(void *object)
 {
 
-	ACPI_FUNCTION_NAME("ut_valid_internal_object");
+	ACPI_FUNCTION_NAME(ut_valid_internal_object);
 
 	/* Check for a null pointer */
 
@@ -308,7 +309,7 @@
 {
 	union acpi_operand_object *object;
 
-	ACPI_FUNCTION_TRACE("ut_allocate_object_desc_dbg");
+	ACPI_FUNCTION_TRACE(ut_allocate_object_desc_dbg);
 
 	object = acpi_os_acquire_object(acpi_gbl_operand_cache);
 	if (!object) {
@@ -319,6 +320,7 @@
 	}
 
 	/* Mark the descriptor type */
+
 	memset(object, 0, sizeof(union acpi_operand_object));
 	ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND);
 
@@ -342,7 +344,7 @@
 
 void acpi_ut_delete_object_desc(union acpi_operand_object *object)
 {
-	ACPI_FUNCTION_TRACE_PTR("ut_delete_object_desc", object);
+	ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object);
 
 	/* Object must be an union acpi_operand_object    */
 
@@ -381,7 +383,7 @@
 	acpi_size length;
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE_PTR("ut_get_simple_object_size", internal_object);
+	ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object);
 
 	/*
 	 * Handle a null object (Could be a uninitialized package
@@ -397,6 +399,7 @@
 	length = sizeof(union acpi_object);
 
 	if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) {
+
 		/* Object is a named object (reference), just return the length */
 
 		*obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
@@ -559,7 +562,7 @@
 	acpi_status status;
 	struct acpi_pkg_info info;
 
-	ACPI_FUNCTION_TRACE_PTR("ut_get_package_object_size", internal_object);
+	ACPI_FUNCTION_TRACE_PTR(ut_get_package_object_size, internal_object);
 
 	info.length = 0;
 	info.object_space = 0;
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c
index 1646131..5a2de92 100644
--- a/drivers/acpi/utilities/utresrc.c
+++ b/drivers/acpi/utilities/utresrc.c
@@ -45,113 +45,113 @@
 #include <acpi/amlresrc.h>
 
 #define _COMPONENT          ACPI_UTILITIES
-ACPI_MODULE_NAME("utmisc")
+ACPI_MODULE_NAME("utresrc")
 
 #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
 /*
  * Strings used to decode resource descriptors.
  * Used by both the disasssembler and the debugger resource dump routines
  */
-const char *acpi_gbl_BMdecode[2] = {
-	"not_bus_master",
-	"bus_master"
+const char *acpi_gbl_bm_decode[] = {
+	"NotBusMaster",
+	"BusMaster"
 };
 
-const char *acpi_gbl_config_decode[4] = {
+const char *acpi_gbl_config_decode[] = {
 	"0 - Good Configuration",
 	"1 - Acceptable Configuration",
 	"2 - Suboptimal Configuration",
 	"3 - ***Invalid Configuration***",
 };
 
-const char *acpi_gbl_consume_decode[2] = {
-	"resource_producer",
-	"resource_consumer"
+const char *acpi_gbl_consume_decode[] = {
+	"ResourceProducer",
+	"ResourceConsumer"
 };
 
-const char *acpi_gbl_DECdecode[2] = {
-	"pos_decode",
-	"sub_decode"
+const char *acpi_gbl_dec_decode[] = {
+	"PosDecode",
+	"SubDecode"
 };
 
-const char *acpi_gbl_HEdecode[2] = {
+const char *acpi_gbl_he_decode[] = {
 	"Level",
 	"Edge"
 };
 
-const char *acpi_gbl_io_decode[2] = {
+const char *acpi_gbl_io_decode[] = {
 	"Decode10",
 	"Decode16"
 };
 
-const char *acpi_gbl_LLdecode[2] = {
-	"active_high",
-	"active_low"
+const char *acpi_gbl_ll_decode[] = {
+	"ActiveHigh",
+	"ActiveLow"
 };
 
-const char *acpi_gbl_max_decode[2] = {
-	"max_not_fixed",
-	"max_fixed"
+const char *acpi_gbl_max_decode[] = {
+	"MaxNotFixed",
+	"MaxFixed"
 };
 
-const char *acpi_gbl_MEMdecode[4] = {
-	"non_cacheable",
+const char *acpi_gbl_mem_decode[] = {
+	"NonCacheable",
 	"Cacheable",
-	"write_combining",
+	"WriteCombining",
 	"Prefetchable"
 };
 
-const char *acpi_gbl_min_decode[2] = {
-	"min_not_fixed",
-	"min_fixed"
+const char *acpi_gbl_min_decode[] = {
+	"MinNotFixed",
+	"MinFixed"
 };
 
-const char *acpi_gbl_MTPdecode[4] = {
-	"address_range_memory",
-	"address_range_reserved",
-	"address_range_aCPI",
-	"address_range_nVS"
+const char *acpi_gbl_mtp_decode[] = {
+	"AddressRangeMemory",
+	"AddressRangeReserved",
+	"AddressRangeACPI",
+	"AddressRangeNVS"
 };
 
-const char *acpi_gbl_RNGdecode[4] = {
-	"invalid_ranges",
-	"non_iSAonly_ranges",
-	"ISAonly_ranges",
-	"entire_range"
+const char *acpi_gbl_rng_decode[] = {
+	"InvalidRanges",
+	"NonISAOnlyRanges",
+	"ISAOnlyRanges",
+	"EntireRange"
 };
 
-const char *acpi_gbl_RWdecode[2] = {
-	"read_only",
-	"read_write"
+const char *acpi_gbl_rw_decode[] = {
+	"ReadOnly",
+	"ReadWrite"
 };
 
-const char *acpi_gbl_SHRdecode[2] = {
+const char *acpi_gbl_shr_decode[] = {
 	"Exclusive",
 	"Shared"
 };
 
-const char *acpi_gbl_SIZdecode[4] = {
+const char *acpi_gbl_siz_decode[] = {
 	"Transfer8",
 	"Transfer8_16",
 	"Transfer16",
-	"invalid_size"
+	"InvalidSize"
 };
 
-const char *acpi_gbl_TRSdecode[2] = {
-	"dense_translation",
-	"sparse_translation"
+const char *acpi_gbl_trs_decode[] = {
+	"DenseTranslation",
+	"SparseTranslation"
 };
 
-const char *acpi_gbl_TTPdecode[2] = {
-	"type_static",
-	"type_translation"
+const char *acpi_gbl_ttp_decode[] = {
+	"TypeStatic",
+	"TypeTranslation"
 };
 
-const char *acpi_gbl_TYPdecode[4] = {
+const char *acpi_gbl_typ_decode[] = {
 	"Compatibility",
-	"type_a",
-	"type_b",
-	"type_f"
+	"TypeA",
+	"TypeB",
+	"TypeF"
 };
 
 #endif
@@ -240,6 +240,104 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_ut_walk_aml_resources
+ *
+ * PARAMETERS:  Aml             - Pointer to the raw AML resource template
+ *              aml_length      - Length of the entire template
+ *              user_function   - Called once for each descriptor found. If
+ *                                NULL, a pointer to the end_tag is returned
+ *              Context         - Passed to user_function
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
+ *              once for each resource found.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_walk_aml_resources(u8 * aml,
+			   acpi_size aml_length,
+			   acpi_walk_aml_callback user_function, void **context)
+{
+	acpi_status status;
+	u8 *end_aml;
+	u8 resource_index;
+	u32 length;
+	u32 offset = 0;
+
+	ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
+
+	/* The absolute minimum resource template is one end_tag descriptor */
+
+	if (aml_length < sizeof(struct aml_resource_end_tag)) {
+		return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+	}
+
+	/* Point to the end of the resource template buffer */
+
+	end_aml = aml + aml_length;
+
+	/* Walk the byte list, abort on any invalid descriptor type or length */
+
+	while (aml < end_aml) {
+
+		/* Validate the Resource Type and Resource Length */
+
+		status = acpi_ut_validate_resource(aml, &resource_index);
+		if (ACPI_FAILURE(status)) {
+			return_ACPI_STATUS(status);
+		}
+
+		/* Get the length of this descriptor */
+
+		length = acpi_ut_get_descriptor_length(aml);
+
+		/* Invoke the user function */
+
+		if (user_function) {
+			status =
+			    user_function(aml, length, offset, resource_index,
+					  context);
+			if (ACPI_FAILURE(status)) {
+				return (status);
+			}
+		}
+
+		/* An end_tag descriptor terminates this resource template */
+
+		if (acpi_ut_get_resource_type(aml) ==
+		    ACPI_RESOURCE_NAME_END_TAG) {
+			/*
+			 * There must be at least one more byte in the buffer for
+			 * the 2nd byte of the end_tag
+			 */
+			if ((aml + 1) >= end_aml) {
+				return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+			}
+
+			/* Return the pointer to the end_tag if requested */
+
+			if (!user_function) {
+				*context = aml;
+			}
+
+			/* Normal exit */
+
+			return_ACPI_STATUS(AE_OK);
+		}
+
+		aml += length;
+		offset += length;
+	}
+
+	/* Did not find an end_tag descriptor */
+
+	return (AE_AML_NO_RESOURCE_END_TAG);
+}
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_ut_validate_resource
  *
  * PARAMETERS:  Aml             - Pointer to the raw AML resource descriptor
@@ -273,6 +371,7 @@
 	 * Examine the large/small bit in the resource header
 	 */
 	if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
+
 		/* Verify the large resource type (name) against the max */
 
 		if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
@@ -376,6 +475,7 @@
 	 * Examine the large/small bit in the resource header
 	 */
 	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+
 		/* Large Resource Type -- bits 6:0 contain the name */
 
 		return (ACPI_GET8(aml));
@@ -411,6 +511,7 @@
 	 * Examine the large/small bit in the resource header
 	 */
 	if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
+
 		/* Large Resource type -- bytes 1-2 contain the 16-bit length */
 
 		ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
@@ -495,60 +596,21 @@
 			     u8 ** end_tag)
 {
 	acpi_status status;
-	u8 *aml;
-	u8 *end_aml;
 
-	ACPI_FUNCTION_TRACE("ut_get_resource_end_tag");
-
-	/* Get start and end pointers */
-
-	aml = obj_desc->buffer.pointer;
-	end_aml = aml + obj_desc->buffer.length;
+	ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
 
 	/* Allow a buffer length of zero */
 
 	if (!obj_desc->buffer.length) {
-		*end_tag = aml;
+		*end_tag = obj_desc->buffer.pointer;
 		return_ACPI_STATUS(AE_OK);
 	}
 
-	/* Walk the resource template, one descriptor per iteration */
+	/* Validate the template and get a pointer to the end_tag */
 
-	while (aml < end_aml) {
-		/* Validate the Resource Type and Resource Length */
+	status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer,
+					    obj_desc->buffer.length, NULL,
+					    (void **)end_tag);
 
-		status = acpi_ut_validate_resource(aml, NULL);
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-
-		/* end_tag resource indicates the end of the resource template */
-
-		if (acpi_ut_get_resource_type(aml) ==
-		    ACPI_RESOURCE_NAME_END_TAG) {
-			/*
-			 * There must be at least one more byte in the buffer for
-			 * the 2nd byte of the end_tag
-			 */
-			if ((aml + 1) >= end_aml) {
-				return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
-			}
-
-			/* Return the pointer to the end_tag */
-
-			*end_tag = aml;
-			return_ACPI_STATUS(AE_OK);
-		}
-
-		/*
-		 * Point to the next resource descriptor in the AML buffer. The
-		 * descriptor length is guaranteed to be non-zero by resource
-		 * validation above.
-		 */
-		aml += acpi_ut_get_descriptor_length(aml);
-	}
-
-	/* Did not find an end_tag resource descriptor */
-
-	return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+	return_ACPI_STATUS(status);
 }
diff --git a/drivers/acpi/utilities/utstate.c b/drivers/acpi/utilities/utstate.c
index 4b134a7..0f5c5bb 100644
--- a/drivers/acpi/utilities/utstate.c
+++ b/drivers/acpi/utilities/utstate.c
@@ -96,7 +96,7 @@
 acpi_ut_push_generic_state(union acpi_generic_state **list_head,
 			   union acpi_generic_state *state)
 {
-	ACPI_FUNCTION_TRACE("ut_push_generic_state");
+	ACPI_FUNCTION_TRACE(ut_push_generic_state);
 
 	/* Push the state object onto the front of the list (stack) */
 
@@ -123,12 +123,13 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_TRACE("ut_pop_generic_state");
+	ACPI_FUNCTION_TRACE(ut_pop_generic_state);
 
 	/* Remove the state object at the head of the list (stack) */
 
 	state = *list_head;
 	if (state) {
+
 		/* Update the list head */
 
 		*list_head = state->common.next;
@@ -158,9 +159,10 @@
 
 	state = acpi_os_acquire_object(acpi_gbl_state_cache);
 	if (state) {
+
 		/* Initialize */
 		memset(state, 0, sizeof(union acpi_generic_state));
-		state->common.data_type = ACPI_DESC_TYPE_STATE;
+		state->common.descriptor_type = ACPI_DESC_TYPE_STATE;
 	}
 
 	return (state);
@@ -183,7 +185,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_TRACE("ut_create_thread_state");
+	ACPI_FUNCTION_TRACE(ut_create_thread_state);
 
 	/* Create the generic state object */
 
@@ -194,7 +196,7 @@
 
 	/* Init fields specific to the update struct */
 
-	state->common.data_type = ACPI_DESC_TYPE_STATE_THREAD;
+	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_THREAD;
 	state->thread.thread_id = acpi_os_get_thread_id();
 
 	return_PTR((struct acpi_thread_state *)state);
@@ -220,7 +222,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_TRACE_PTR("ut_create_update_state", object);
+	ACPI_FUNCTION_TRACE_PTR(ut_create_update_state, object);
 
 	/* Create the generic state object */
 
@@ -231,7 +233,7 @@
 
 	/* Init fields specific to the update struct */
 
-	state->common.data_type = ACPI_DESC_TYPE_STATE_UPDATE;
+	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_UPDATE;
 	state->update.object = object;
 	state->update.value = action;
 
@@ -257,7 +259,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_TRACE_PTR("ut_create_pkg_state", internal_object);
+	ACPI_FUNCTION_TRACE_PTR(ut_create_pkg_state, internal_object);
 
 	/* Create the generic state object */
 
@@ -268,7 +270,7 @@
 
 	/* Init fields specific to the update struct */
 
-	state->common.data_type = ACPI_DESC_TYPE_STATE_PACKAGE;
+	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_PACKAGE;
 	state->pkg.source_object = (union acpi_operand_object *)internal_object;
 	state->pkg.dest_object = external_object;
 	state->pkg.index = index;
@@ -294,7 +296,7 @@
 {
 	union acpi_generic_state *state;
 
-	ACPI_FUNCTION_TRACE("ut_create_control_state");
+	ACPI_FUNCTION_TRACE(ut_create_control_state);
 
 	/* Create the generic state object */
 
@@ -305,7 +307,7 @@
 
 	/* Init fields specific to the control struct */
 
-	state->common.data_type = ACPI_DESC_TYPE_STATE_CONTROL;
+	state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL;
 	state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
 
 	return_PTR(state);
@@ -319,15 +321,19 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Put a state object back into the global state cache.  The object
- *              is not actually freed at this time.
+ * DESCRIPTION: Release a state object to the state cache. NULL state objects
+ *              are ignored.
  *
  ******************************************************************************/
 
 void acpi_ut_delete_generic_state(union acpi_generic_state *state)
 {
-	ACPI_FUNCTION_TRACE("ut_delete_generic_state");
+	ACPI_FUNCTION_TRACE(ut_delete_generic_state);
 
-	(void)acpi_os_release_object(acpi_gbl_state_cache, state);
+	/* Ignore null state */
+
+	if (state) {
+		(void)acpi_os_release_object(acpi_gbl_state_cache, state);
+	}
 	return_VOID;
 }
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index 308a960..3538f69 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -41,8 +41,6 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
-#include <linux/module.h>
-
 #include <acpi/acpi.h>
 #include <acpi/acevents.h>
 #include <acpi/acnamesp.h>
@@ -67,7 +65,7 @@
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_initialize_subsystem");
+	ACPI_FUNCTION_TRACE(acpi_initialize_subsystem);
 
 	ACPI_DEBUG_EXEC(acpi_ut_init_stack_ptr_trace());
 
@@ -109,6 +107,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_initialize_subsystem)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enable_subsystem
@@ -121,12 +121,11 @@
  *              Puts system into ACPI mode if it isn't already.
  *
  ******************************************************************************/
-
 acpi_status acpi_enable_subsystem(u32 flags)
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("acpi_enable_subsystem");
+	ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
 
 	/*
 	 * We must initialize the hardware before we can enable ACPI.
@@ -152,7 +151,7 @@
 
 		status = acpi_enable();
 		if (ACPI_FAILURE(status)) {
-			ACPI_WARNING((AE_INFO, "acpi_enable failed"));
+			ACPI_WARNING((AE_INFO, "AcpiEnable failed"));
 			return_ACPI_STATUS(status);
 		}
 	}
@@ -229,6 +228,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_enable_subsystem)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_initialize_objects
@@ -241,12 +242,11 @@
  *              objects and executing AML code for Regions, buffers, etc.
  *
  ******************************************************************************/
-
 acpi_status acpi_initialize_objects(u32 flags)
 {
 	acpi_status status = AE_OK;
 
-	ACPI_FUNCTION_TRACE("acpi_initialize_objects");
+	ACPI_FUNCTION_TRACE(acpi_initialize_objects);
 
 	/*
 	 * Run all _REG methods
@@ -257,7 +257,7 @@
 	 */
 	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
-				  "[Init] Executing _REG op_region methods\n"));
+				  "[Init] Executing _REG OpRegion methods\n"));
 
 		status = acpi_ev_initialize_op_regions();
 		if (ACPI_FAILURE(status)) {
@@ -305,6 +305,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_initialize_objects)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_terminate
@@ -316,12 +318,11 @@
  * DESCRIPTION: Shutdown the ACPI subsystem.  Release all resources.
  *
  ******************************************************************************/
-
 acpi_status acpi_terminate(void)
 {
 	acpi_status status;
 
-	ACPI_FUNCTION_TRACE("acpi_terminate");
+	ACPI_FUNCTION_TRACE(acpi_terminate);
 
 	/* Terminate the AML Debugger if present */
 
@@ -348,6 +349,8 @@
 	return_ACPI_STATUS(status);
 }
 
+ACPI_EXPORT_SYMBOL(acpi_terminate)
+
 #ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
@@ -362,7 +365,6 @@
  *              initialized successfully.
  *
  ******************************************************************************/
-
 acpi_status acpi_subsystem_status(void)
 {
 
@@ -373,6 +375,8 @@
 	}
 }
 
+ACPI_EXPORT_SYMBOL(acpi_subsystem_status)
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_get_system_info
@@ -390,14 +394,13 @@
  *              and the value of out_buffer is undefined.
  *
  ******************************************************************************/
-
 acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer)
 {
 	struct acpi_system_info *info_ptr;
 	acpi_status status;
 	u32 i;
 
-	ACPI_FUNCTION_TRACE("acpi_get_system_info");
+	ACPI_FUNCTION_TRACE(acpi_get_system_info);
 
 	/* Parameter validation */
 
@@ -448,15 +451,15 @@
 
 	/* Current status of the ACPI tables, per table type */
 
-	info_ptr->num_table_types = NUM_ACPI_TABLE_TYPES;
-	for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) {
+	info_ptr->num_table_types = ACPI_TABLE_ID_MAX + 1;
+	for (i = 0; i < (ACPI_TABLE_ID_MAX + 1); i++) {
 		info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count;
 	}
 
 	return_ACPI_STATUS(AE_OK);
 }
 
-EXPORT_SYMBOL(acpi_get_system_info);
+ACPI_EXPORT_SYMBOL(acpi_get_system_info)
 
 /*****************************************************************************
  *
@@ -472,7 +475,6 @@
  * TBD: When a second function is added, must save the Function also.
  *
  ****************************************************************************/
-
 acpi_status
 acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
 {
@@ -489,6 +491,7 @@
 	return AE_OK;
 }
 
+ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
 #endif				/*  ACPI_FUTURE_USAGE  */
 
 /*****************************************************************************
@@ -502,10 +505,9 @@
  * DESCRIPTION: Empty all caches (delete the cached objects)
  *
  ****************************************************************************/
-
 acpi_status acpi_purge_cached_objects(void)
 {
-	ACPI_FUNCTION_TRACE("acpi_purge_cached_objects");
+	ACPI_FUNCTION_TRACE(acpi_purge_cached_objects);
 
 	(void)acpi_os_purge_cache(acpi_gbl_state_cache);
 	(void)acpi_os_purge_cache(acpi_gbl_operand_cache);
@@ -513,3 +515,5 @@
 	(void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);
 	return_ACPI_STATUS(AE_OK);
 }
+
+ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 6458c47..6b51685 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -273,11 +273,13 @@
 	status = acpi_evaluate_object(handle, pathname, arguments, &buffer);
 	if (ACPI_FAILURE(status)) {
 		acpi_util_eval_error(handle, pathname, status);
+		kfree(element);
 		return_ACPI_STATUS(status);
 	}
 
 	if (element->type != ACPI_TYPE_INTEGER) {
 		acpi_util_eval_error(handle, pathname, AE_BAD_DATA);
+		kfree(element);
 		return_ACPI_STATUS(AE_BAD_DATA);
 	}
 
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index bd48875..e7e9a693 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -323,7 +323,7 @@
 	if (!ACPI_SUCCESS(status))
 		return_VALUE(status);
 	obj = (union acpi_object *)buffer.pointer;
-	if (!obj && (obj->type != ACPI_TYPE_PACKAGE)) {
+	if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _BCL data\n"));
 		status = -EFAULT;
 		goto err;
@@ -1294,7 +1294,7 @@
 			      struct acpi_video_bus *video)
 {
 	unsigned long device_id;
-	int status, result;
+	int status;
 	struct acpi_video_device *data;
 
 	ACPI_FUNCTION_TRACE("acpi_video_bus_get_one_device");
@@ -1346,8 +1346,11 @@
 		if (ACPI_FAILURE(status)) {
 			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 					  "Error installing notify handler\n"));
-			result = -ENODEV;
-			goto end;
+			if(data->brightness)
+				kfree(data->brightness->levels);
+			kfree(data->brightness);
+			kfree(data);
+			return -ENODEV;
 		}
 
 		down(&video->sem);
@@ -1359,7 +1362,6 @@
 		return_VALUE(0);
 	}
 
-      end:
 	return_VALUE(-ENOENT);
 }
 
@@ -1643,8 +1645,9 @@
 			printk(KERN_WARNING PREFIX
 			       "hhuuhhuu bug in acpi video driver.\n");
 
+		if (data->brightness)
+			kfree(data->brightness->levels);
 		kfree(data->brightness);
-
 		kfree(data);
 	}
 
@@ -1785,6 +1788,10 @@
 	if (ACPI_FAILURE(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "Error installing notify handler\n"));
+		acpi_video_bus_stop_devices(video);
+		acpi_video_bus_put_devices(video);
+		kfree(video->attached_array);
+		acpi_video_bus_remove_fs(device);
 		result = -ENODEV;
 		goto end;
 	}
@@ -1796,10 +1803,8 @@
 	       video->flags.post ? "yes" : "no");
 
       end:
-	if (result) {
-		acpi_video_bus_remove_fs(device);
+	if (result)
 		kfree(video);
-	}
 
 	return_VALUE(result);
 }
diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c
index 7f7ec28..1bca86e 100644
--- a/drivers/atm/firestream.c
+++ b/drivers/atm/firestream.c
@@ -33,6 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
+#include <linux/poison.h>
 #include <linux/errno.h>
 #include <linux/atm.h>
 #include <linux/atmdev.h>
@@ -754,7 +755,7 @@
 			fs_kfree_skb (skb);
 
 			fs_dprintk (FS_DEBUG_ALLOC, "Free trans-d: %p\n", td); 
-			memset (td, 0x12, sizeof (struct FS_BPENTRY));
+			memset (td, ATM_POISON_FREE, sizeof(struct FS_BPENTRY));
 			kfree (td);
 			break;
 		default:
@@ -951,7 +952,7 @@
 		   it most likely that the chip will notice it. It also prevents us
 		   from having to wait for completion. On the other hand, we may
 		   need to wait for completion anyway, to see if it completed
-		   succesfully. */
+		   successfully. */
 
 		switch (atm_vcc->qos.aal) {
 		case ATM_AAL2:
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 05983a3..92923bf 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -167,13 +167,9 @@
 static char*
 fore200e_irq_itoa(int irq)
 {
-#if defined(__sparc_v9__)
-    return __irq_itoa(irq);
-#else
     static char str[8];
     sprintf(str, "%d", irq);
     return str;
-#endif
 }
 
 
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index f0eff3d..80502dc 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -38,3 +38,7 @@
 	  If you are unsure about this, say N here.
 
 endmenu
+
+config SYS_HYPERVISOR
+	bool
+	default n
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index e99471d..b539e5e 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -5,10 +5,12 @@
 			   cpu.o firmware.o init.o map.o dmapool.o \
 			   attribute_container.o transport_class.o
 obj-y			+= power/
+obj-$(CONFIG_ISA)	+= isa.o
 obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
 obj-$(CONFIG_NUMA)	+= node.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
 obj-$(CONFIG_SMP)	+= topology.o
+obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
 
 ifeq ($(CONFIG_DEBUG_DRIVER),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 2a7d7ae..2222073 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -236,7 +236,6 @@
 	}
 	up(&attribute_container_mutex);
 }
-EXPORT_SYMBOL_GPL(attribute_container_remove_device);
 
 /**
  * attribute_container_device_trigger - execute a trigger for each matching classdev
@@ -276,7 +275,6 @@
 	}
 	up(&attribute_container_mutex);
 }
-EXPORT_SYMBOL_GPL(attribute_container_device_trigger);
 
 /**
  * attribute_container_trigger - trigger a function for each matching container
@@ -304,7 +302,6 @@
 	}
 	up(&attribute_container_mutex);
 }
-EXPORT_SYMBOL_GPL(attribute_container_trigger);
 
 /**
  * attribute_container_add_attrs - add attributes
@@ -333,7 +330,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(attribute_container_add_attrs);
 
 /**
  * attribute_container_add_class_device - same function as class_device_add
@@ -352,7 +348,6 @@
 		return error;
 	return attribute_container_add_attrs(classdev);
 }
-EXPORT_SYMBOL_GPL(attribute_container_add_class_device);
 
 /**
  * attribute_container_add_class_device_adapter - simple adapter for triggers
@@ -367,7 +362,6 @@
 {
 	return attribute_container_add_class_device(classdev);
 }
-EXPORT_SYMBOL_GPL(attribute_container_add_class_device_adapter);
 
 /**
  * attribute_container_remove_attrs - remove any attribute files
@@ -389,7 +383,6 @@
 	for (i = 0; attrs[i]; i++)
 		class_device_remove_file(classdev, attrs[i]);
 }
-EXPORT_SYMBOL_GPL(attribute_container_remove_attrs);
 
 /**
  * attribute_container_class_device_del - equivalent of class_device_del
@@ -405,7 +398,6 @@
 	attribute_container_remove_attrs(classdev);
 	class_device_del(classdev);
 }
-EXPORT_SYMBOL_GPL(attribute_container_class_device_del);
 
 /**
  * attribute_container_find_class_device - find the corresponding class_device
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 5735b38..c3b8dc9 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -5,13 +5,21 @@
 extern int buses_init(void);
 extern int classes_init(void);
 extern int firmware_init(void);
+#ifdef CONFIG_SYS_HYPERVISOR
+extern int hypervisor_init(void);
+#else
+static inline int hypervisor_init(void) { return 0; }
+#endif
 extern int platform_bus_init(void);
 extern int system_bus_init(void);
 extern int cpu_dev_init(void);
 extern int attribute_container_init(void);
 
 extern int bus_add_device(struct device * dev);
+extern void bus_attach_device(struct device * dev);
 extern void bus_remove_device(struct device * dev);
+extern struct bus_type *get_bus(struct bus_type * bus);
+extern void put_bus(struct bus_type * bus);
 
 extern int bus_add_driver(struct device_driver *);
 extern void bus_remove_driver(struct device_driver *);
@@ -34,4 +42,5 @@
 	return container_of(_attr, struct class_device_attribute, attr);
 }
 
+extern char *make_class_name(const char *name, struct kobject *kobj);
 
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 76656ac..050d86d 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -362,8 +362,7 @@
  *	@dev:	device being added
  *
  *	- Add the device to its bus's list of devices.
- *	- Try to attach to driver.
- *	- Create link to device's physical location.
+ *	- Create link to device's bus.
  */
 int bus_add_device(struct device * dev)
 {
@@ -372,11 +371,10 @@
 
 	if (bus) {
 		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
-		device_attach(dev);
-		klist_add_tail(&dev->knode_bus, &bus->klist_devices);
 		error = device_add_attrs(bus, dev);
 		if (!error) {
 			sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
+			sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem");
 			sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
 		}
 	}
@@ -384,6 +382,22 @@
 }
 
 /**
+ *	bus_attach_device - add device to bus
+ *	@dev:	device tried to attach to a driver
+ *
+ *	- Try to attach to driver.
+ */
+void bus_attach_device(struct device * dev)
+{
+	struct bus_type * bus = dev->bus;
+
+	if (bus) {
+		device_attach(dev);
+		klist_add_tail(&dev->knode_bus, &bus->klist_devices);
+	}
+}
+
+/**
  *	bus_remove_device - remove device from bus
  *	@dev:	device to be removed
  *
@@ -395,6 +409,7 @@
 void bus_remove_device(struct device * dev)
 {
 	if (dev->bus) {
+		sysfs_remove_link(&dev->kobj, "subsystem");
 		sysfs_remove_link(&dev->kobj, "bus");
 		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
 		device_remove_attrs(dev->bus, dev);
@@ -732,14 +747,9 @@
 EXPORT_SYMBOL_GPL(bus_find_device);
 EXPORT_SYMBOL_GPL(bus_for_each_drv);
 
-EXPORT_SYMBOL_GPL(bus_add_device);
-EXPORT_SYMBOL_GPL(bus_remove_device);
 EXPORT_SYMBOL_GPL(bus_register);
 EXPORT_SYMBOL_GPL(bus_unregister);
 EXPORT_SYMBOL_GPL(bus_rescan_devices);
-EXPORT_SYMBOL_GPL(get_bus);
-EXPORT_SYMBOL_GPL(put_bus);
-EXPORT_SYMBOL_GPL(find_bus);
 
 EXPORT_SYMBOL_GPL(bus_create_file);
 EXPORT_SYMBOL_GPL(bus_remove_file);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index b1ea4df..9aa1274 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -91,14 +91,14 @@
 		sysfs_remove_file(&cls->subsys.kset.kobj, &attr->attr);
 }
 
-struct class * class_get(struct class * cls)
+static struct class *class_get(struct class *cls)
 {
 	if (cls)
 		return container_of(subsys_get(&cls->subsys), struct class, subsys);
 	return NULL;
 }
 
-void class_put(struct class * cls)
+static void class_put(struct class * cls)
 {
 	if (cls)
 		subsys_put(&cls->subsys);
@@ -142,6 +142,7 @@
 	pr_debug("device class '%s': registering\n", cls->name);
 
 	INIT_LIST_HEAD(&cls->children);
+	INIT_LIST_HEAD(&cls->devices);
 	INIT_LIST_HEAD(&cls->interfaces);
 	init_MUTEX(&cls->sem);
 	error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
@@ -504,22 +505,21 @@
 	INIT_LIST_HEAD(&class_dev->node);
 }
 
-static char *make_class_name(struct class_device *class_dev)
+char *make_class_name(const char *name, struct kobject *kobj)
 {
-	char *name;
+	char *class_name;
 	int size;
 
-	size = strlen(class_dev->class->name) +
-		strlen(kobject_name(&class_dev->kobj)) + 2;
+	size = strlen(name) + strlen(kobject_name(kobj)) + 2;
 
-	name = kmalloc(size, GFP_KERNEL);
-	if (!name)
+	class_name = kmalloc(size, GFP_KERNEL);
+	if (!class_name)
 		return ERR_PTR(-ENOMEM);
 
-	strcpy(name, class_dev->class->name);
-	strcat(name, ":");
-	strcat(name, kobject_name(&class_dev->kobj));
-	return name;
+	strcpy(class_name, name);
+	strcat(class_name, ":");
+	strcat(class_name, kobject_name(kobj));
+	return class_name;
 }
 
 int class_device_add(struct class_device *class_dev)
@@ -535,18 +535,22 @@
 		return -EINVAL;
 
 	if (!strlen(class_dev->class_id))
-		goto register_done;
+		goto out1;
 
 	parent_class = class_get(class_dev->class);
 	if (!parent_class)
-		goto register_done;
+		goto out1;
+
 	parent_class_dev = class_device_get(class_dev->parent);
 
 	pr_debug("CLASS: registering class device: ID = '%s'\n",
 		 class_dev->class_id);
 
 	/* first, register with generic layer. */
-	kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
+	error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
+	if (error)
+		goto out2;
+
 	if (parent_class_dev)
 		class_dev->kobj.parent = &parent_class_dev->kobj;
 	else
@@ -554,41 +558,58 @@
 
 	error = kobject_add(&class_dev->kobj);
 	if (error)
-		goto register_done;
+		goto out2;
 
 	/* add the needed attributes to this device */
+	sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem");
 	class_dev->uevent_attr.attr.name = "uevent";
 	class_dev->uevent_attr.attr.mode = S_IWUSR;
 	class_dev->uevent_attr.attr.owner = parent_class->owner;
 	class_dev->uevent_attr.store = store_uevent;
-	class_device_create_file(class_dev, &class_dev->uevent_attr);
+	error = class_device_create_file(class_dev, &class_dev->uevent_attr);
+	if (error)
+		goto out3;
 
 	if (MAJOR(class_dev->devt)) {
 		struct class_device_attribute *attr;
 		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
 		if (!attr) {
 			error = -ENOMEM;
-			kobject_del(&class_dev->kobj);
-			goto register_done;
+			goto out4;
 		}
 		attr->attr.name = "dev";
 		attr->attr.mode = S_IRUGO;
 		attr->attr.owner = parent_class->owner;
 		attr->show = show_dev;
-		class_device_create_file(class_dev, attr);
+		error = class_device_create_file(class_dev, attr);
+		if (error) {
+			kfree(attr);
+			goto out4;
+		}
+
 		class_dev->devt_attr = attr;
 	}
 
-	class_device_add_attrs(class_dev);
+	error = class_device_add_attrs(class_dev);
+	if (error)
+		goto out5;
+
 	if (class_dev->dev) {
-		class_name = make_class_name(class_dev);
-		sysfs_create_link(&class_dev->kobj,
-				  &class_dev->dev->kobj, "device");
-		sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
-				  class_name);
+		class_name = make_class_name(class_dev->class->name,
+					     &class_dev->kobj);
+		error = sysfs_create_link(&class_dev->kobj,
+					  &class_dev->dev->kobj, "device");
+		if (error)
+			goto out6;
+		error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
+					  class_name);
+		if (error)
+			goto out7;
 	}
 
-	class_device_add_groups(class_dev);
+	error = class_device_add_groups(class_dev);
+	if (error)
+		goto out8;
 
 	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
 
@@ -601,11 +622,28 @@
 	}
 	up(&parent_class->sem);
 
- register_done:
-	if (error) {
-		class_put(parent_class);
+	goto out1;
+
+ out8:
+	if (class_dev->dev)
+		sysfs_remove_link(&class_dev->kobj, class_name);
+ out7:
+	if (class_dev->dev)
+		sysfs_remove_link(&class_dev->kobj, "device");
+ out6:
+	class_device_remove_attrs(class_dev);
+ out5:
+	if (class_dev->devt_attr)
+		class_device_remove_file(class_dev, class_dev->devt_attr);
+ out4:
+	class_device_remove_file(class_dev, &class_dev->uevent_attr);
+ out3:
+	kobject_del(&class_dev->kobj);
+ out2:
+	if(parent_class_dev)
 		class_device_put(parent_class_dev);
-	}
+	class_put(parent_class);
+ out1:
 	class_device_put(class_dev);
 	kfree(class_name);
 	return error;
@@ -695,10 +733,12 @@
 	}
 
 	if (class_dev->dev) {
-		class_name = make_class_name(class_dev);
+		class_name = make_class_name(class_dev->class->name,
+					     &class_dev->kobj);
 		sysfs_remove_link(&class_dev->kobj, "device");
 		sysfs_remove_link(&class_dev->dev->kobj, class_name);
 	}
+	sysfs_remove_link(&class_dev->kobj, "subsystem");
 	class_device_remove_file(class_dev, &class_dev->uevent_attr);
 	if (class_dev->devt_attr)
 		class_device_remove_file(class_dev, class_dev->devt_attr);
@@ -760,14 +800,16 @@
 		 new_name);
 
 	if (class_dev->dev)
-		old_class_name = make_class_name(class_dev);
+		old_class_name = make_class_name(class_dev->class->name,
+						 &class_dev->kobj);
 
 	strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
 
 	error = kobject_rename(&class_dev->kobj, new_name);
 
 	if (class_dev->dev) {
-		new_class_name = make_class_name(class_dev);
+		new_class_name = make_class_name(class_dev->class->name,
+						 &class_dev->kobj);
 		sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
 				  new_class_name);
 		sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
@@ -858,8 +900,6 @@
 EXPORT_SYMBOL_GPL(class_remove_file);
 EXPORT_SYMBOL_GPL(class_register);
 EXPORT_SYMBOL_GPL(class_unregister);
-EXPORT_SYMBOL_GPL(class_get);
-EXPORT_SYMBOL_GPL(class_put);
 EXPORT_SYMBOL_GPL(class_create);
 EXPORT_SYMBOL_GPL(class_destroy);
 
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 6b355bd..27c2176 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/kdev_t.h>
 
 #include <asm/semaphore.h>
 
@@ -28,6 +29,22 @@
  * sysfs bindings for devices.
  */
 
+/**
+ * dev_driver_string - Return a device's driver name, if at all possible
+ * @dev: struct device to get the name of
+ *
+ * Will return the device's driver's name if it is bound to a device.  If
+ * the device is not bound to a device, it will return the name of the bus
+ * it is attached to.  If it is not attached to a bus either, an empty
+ * string will be returned.
+ */
+const char *dev_driver_string(struct device *dev)
+{
+	return dev->driver ? dev->driver->name :
+			(dev->bus ? dev->bus->name : "");
+}
+EXPORT_SYMBOL_GPL(dev_driver_string);
+
 #define to_dev(obj) container_of(obj, struct device, kobj)
 #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
 
@@ -98,6 +115,8 @@
 		struct device *dev = to_dev(kobj);
 		if (dev->bus)
 			return 1;
+		if (dev->class)
+			return 1;
 	}
 	return 0;
 }
@@ -106,7 +125,11 @@
 {
 	struct device *dev = to_dev(kobj);
 
-	return dev->bus->name;
+	if (dev->bus)
+		return dev->bus->name;
+	if (dev->class)
+		return dev->class->name;
+	return NULL;
 }
 
 static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
@@ -117,6 +140,16 @@
 	int length = 0;
 	int retval = 0;
 
+	/* add the major/minor if present */
+	if (MAJOR(dev->devt)) {
+		add_uevent_var(envp, num_envp, &i,
+			       buffer, buffer_size, &length,
+			       "MAJOR=%u", MAJOR(dev->devt));
+		add_uevent_var(envp, num_envp, &i,
+			       buffer, buffer_size, &length,
+			       "MINOR=%u", MINOR(dev->devt));
+	}
+
 	/* add bus name of physical device */
 	if (dev->bus)
 		add_uevent_var(envp, num_envp, &i,
@@ -161,6 +194,12 @@
 	return count;
 }
 
+static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	return print_dev_t(buf, dev->devt);
+}
+
 /*
  *	devices_subsys - structure to be registered with kobject core.
  */
@@ -231,6 +270,7 @@
 	klist_init(&dev->klist_children, klist_children_get,
 		   klist_children_put);
 	INIT_LIST_HEAD(&dev->dma_pools);
+	INIT_LIST_HEAD(&dev->node);
 	init_MUTEX(&dev->sem);
 	device_init_wakeup(dev, 0);
 }
@@ -249,6 +289,7 @@
 int device_add(struct device *dev)
 {
 	struct device *parent = NULL;
+	char *class_name = NULL;
 	int error = -EINVAL;
 
 	dev = get_device(dev);
@@ -274,23 +315,69 @@
 	dev->uevent_attr.store = store_uevent;
 	device_create_file(dev, &dev->uevent_attr);
 
-	kobject_uevent(&dev->kobj, KOBJ_ADD);
+	if (MAJOR(dev->devt)) {
+		struct device_attribute *attr;
+		attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+		if (!attr) {
+			error = -ENOMEM;
+			goto PMError;
+		}
+		attr->attr.name = "dev";
+		attr->attr.mode = S_IRUGO;
+		if (dev->driver)
+			attr->attr.owner = dev->driver->owner;
+		attr->show = show_dev;
+		error = device_create_file(dev, attr);
+		if (error) {
+			kfree(attr);
+			goto attrError;
+		}
+
+		dev->devt_attr = attr;
+	}
+
+	if (dev->class) {
+		sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
+				  "subsystem");
+		sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
+				  dev->bus_id);
+
+		sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
+		class_name = make_class_name(dev->class->name, &dev->kobj);
+		sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
+	}
+
 	if ((error = device_pm_add(dev)))
 		goto PMError;
 	if ((error = bus_add_device(dev)))
 		goto BusError;
+	kobject_uevent(&dev->kobj, KOBJ_ADD);
+	bus_attach_device(dev);
 	if (parent)
 		klist_add_tail(&dev->knode_parent, &parent->klist_children);
 
+	if (dev->class) {
+		/* tie the class to the device */
+		down(&dev->class->sem);
+		list_add_tail(&dev->node, &dev->class->devices);
+		up(&dev->class->sem);
+	}
+
 	/* notify platform of device entry */
 	if (platform_notify)
 		platform_notify(dev);
  Done:
+ 	kfree(class_name);
 	put_device(dev);
 	return error;
  BusError:
 	device_pm_remove(dev);
  PMError:
+	if (dev->devt_attr) {
+		device_remove_file(dev, dev->devt_attr);
+		kfree(dev->devt_attr);
+	}
+ attrError:
 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
 	kobject_del(&dev->kobj);
  Error:
@@ -362,9 +449,23 @@
 void device_del(struct device * dev)
 {
 	struct device * parent = dev->parent;
+	char *class_name = NULL;
 
 	if (parent)
 		klist_del(&dev->knode_parent);
+	if (dev->devt_attr)
+		device_remove_file(dev, dev->devt_attr);
+	if (dev->class) {
+		sysfs_remove_link(&dev->kobj, "subsystem");
+		sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id);
+		class_name = make_class_name(dev->class->name, &dev->kobj);
+		sysfs_remove_link(&dev->kobj, "device");
+		sysfs_remove_link(&dev->parent->kobj, class_name);
+		kfree(class_name);
+		down(&dev->class->sem);
+		list_del_init(&dev->node);
+		up(&dev->class->sem);
+	}
 	device_remove_file(dev, &dev->uevent_attr);
 
 	/* Notify the platform of the removal, in case they
@@ -449,3 +550,98 @@
 
 EXPORT_SYMBOL_GPL(device_create_file);
 EXPORT_SYMBOL_GPL(device_remove_file);
+
+
+static void device_create_release(struct device *dev)
+{
+	pr_debug("%s called for %s\n", __FUNCTION__, dev->bus_id);
+	kfree(dev);
+}
+
+/**
+ * device_create - creates a device and registers it with sysfs
+ * @cs: pointer to the struct class that this device should be registered to.
+ * @parent: pointer to the parent struct device of this new device, if any.
+ * @dev: the dev_t for the char device to be added.
+ * @fmt: string for the class device's name
+ *
+ * This function can be used by char device classes.  A struct
+ * device will be created in sysfs, registered to the specified
+ * class.
+ * A "dev" file will be created, showing the dev_t for the device, if
+ * the dev_t is not 0,0.
+ * If a pointer to a parent struct device is passed in, the newly
+ * created struct device will be a child of that device in sysfs.  The
+ * pointer to the struct device will be returned from the call.  Any
+ * further sysfs files that might be required can be created using this
+ * pointer.
+ *
+ * Note: the struct class passed to this function must have previously
+ * been created with a call to class_create().
+ */
+struct device *device_create(struct class *class, struct device *parent,
+			     dev_t devt, char *fmt, ...)
+{
+	va_list args;
+	struct device *dev = NULL;
+	int retval = -ENODEV;
+
+	if (class == NULL || IS_ERR(class))
+		goto error;
+	if (parent == NULL) {
+		printk(KERN_WARNING "%s does not work yet for NULL parents\n", __FUNCTION__);
+		goto error;
+	}
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	dev->devt = devt;
+	dev->class = class;
+	dev->parent = parent;
+	dev->release = device_create_release;
+
+	va_start(args, fmt);
+	vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
+	va_end(args);
+	retval = device_register(dev);
+	if (retval)
+		goto error;
+
+	return dev;
+
+error:
+	kfree(dev);
+	return ERR_PTR(retval);
+}
+EXPORT_SYMBOL_GPL(device_create);
+
+/**
+ * device_destroy - removes a device that was created with device_create()
+ * @class: the pointer to the struct class that this device was registered * with.
+ * @dev: the dev_t of the device that was previously registered.
+ *
+ * This call unregisters and cleans up a class device that was created with a
+ * call to class_device_create()
+ */
+void device_destroy(struct class *class, dev_t devt)
+{
+	struct device *dev = NULL;
+	struct device *dev_tmp;
+
+	down(&class->sem);
+	list_for_each_entry(dev_tmp, &class->devices, node) {
+		if (dev_tmp->devt == devt) {
+			dev = dev_tmp;
+			break;
+		}
+	}
+	up(&class->sem);
+
+	if (dev)
+		device_unregister(dev);
+}
+EXPORT_SYMBOL_GPL(device_destroy);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index dd712b2..4bef76a 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -8,6 +8,7 @@
 #include <linux/cpu.h>
 #include <linux/topology.h>
 #include <linux/device.h>
+#include <linux/node.h>
 
 #include "base.h"
 
@@ -57,13 +58,12 @@
 {
 	sysdev_create_file(&cpu->sysdev, &attr_online);
 }
-void unregister_cpu(struct cpu *cpu, struct node *root)
+void unregister_cpu(struct cpu *cpu)
 {
 	int logical_cpu = cpu->sysdev.id;
 
-	if (root)
-		sysfs_remove_link(&root->sysdev.kobj,
-				  kobject_name(&cpu->sysdev.kobj));
+	unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
+
 	sysdev_remove_file(&cpu->sysdev, &attr_online);
 
 	sysdev_unregister(&cpu->sysdev);
@@ -109,23 +109,21 @@
  *
  * Initialize and register the CPU device.
  */
-int __devinit register_cpu(struct cpu *cpu, int num, struct node *root)
+int __devinit register_cpu(struct cpu *cpu, int num)
 {
 	int error;
-
 	cpu->node_id = cpu_to_node(num);
 	cpu->sysdev.id = num;
 	cpu->sysdev.cls = &cpu_sysdev_class;
 
 	error = sysdev_register(&cpu->sysdev);
-	if (!error && root)
-		error = sysfs_create_link(&root->sysdev.kobj,
-					  &cpu->sysdev.kobj,
-					  kobject_name(&cpu->sysdev.kobj));
+
 	if (!error && !cpu->no_control)
 		register_cpu_control(cpu);
 	if (!error)
 		cpu_sys_devices[num] = &cpu->sysdev;
+	if (!error)
+		register_cpu_under_node(num, cpu_to_node(num));
 
 #ifdef CONFIG_KEXEC
 	if (!error)
@@ -145,5 +143,13 @@
 
 int __init cpu_dev_init(void)
 {
-	return sysdev_class_register(&cpu_sysdev_class);
+	int err;
+
+	err = sysdev_class_register(&cpu_sysdev_class);
+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+	if (!err)
+		err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
+#endif
+
+	return err;
 }
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index e2f64f9..33c5cce 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -7,6 +7,7 @@
 #include <linux/dmapool.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/poison.h>
 
 /*
  * Pool allocator ... wraps the dma_alloc_coherent page allocator, so
@@ -35,8 +36,6 @@
 };
 
 #define	POOL_TIMEOUT_JIFFIES	((100 /* msec */ * HZ) / 1000)
-#define	POOL_POISON_FREED	0xa7	/* !inuse */
-#define	POOL_POISON_ALLOCATED	0xa9	/* !initted */
 
 static DECLARE_MUTEX (pools_lock);
 
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 0c99ae6a..5d6c011 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -15,7 +15,7 @@
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #include <linux/firmware.h>
 #include "base.h"
@@ -36,7 +36,7 @@
 
 /* fw_lock could be moved to 'struct firmware_priv' but since it is just
  * guarding for corner cases a global lock should be OK */
-static DECLARE_MUTEX(fw_lock);
+static DEFINE_MUTEX(fw_lock);
 
 struct firmware_priv {
 	char fw_id[FIRMWARE_NAME_MAX];
@@ -142,9 +142,9 @@
 
 	switch (loading) {
 	case 1:
-		down(&fw_lock);
+		mutex_lock(&fw_lock);
 		if (!fw_priv->fw) {
-			up(&fw_lock);
+			mutex_unlock(&fw_lock);
 			break;
 		}
 		vfree(fw_priv->fw->data);
@@ -152,7 +152,7 @@
 		fw_priv->fw->size = 0;
 		fw_priv->alloc_size = 0;
 		set_bit(FW_STATUS_LOADING, &fw_priv->status);
-		up(&fw_lock);
+		mutex_unlock(&fw_lock);
 		break;
 	case 0:
 		if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
@@ -185,7 +185,7 @@
 	struct firmware *fw;
 	ssize_t ret_count = count;
 
-	down(&fw_lock);
+	mutex_lock(&fw_lock);
 	fw = fw_priv->fw;
 	if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
 		ret_count = -ENODEV;
@@ -200,7 +200,7 @@
 
 	memcpy(buffer, fw->data + offset, ret_count);
 out:
-	up(&fw_lock);
+	mutex_unlock(&fw_lock);
 	return ret_count;
 }
 
@@ -253,7 +253,7 @@
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
 
-	down(&fw_lock);
+	mutex_lock(&fw_lock);
 	fw = fw_priv->fw;
 	if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) {
 		retval = -ENODEV;
@@ -268,7 +268,7 @@
 	fw->size = max_t(size_t, offset + count, fw->size);
 	retval = count;
 out:
-	up(&fw_lock);
+	mutex_unlock(&fw_lock);
 	return retval;
 }
 
@@ -436,14 +436,14 @@
 	} else
 		wait_for_completion(&fw_priv->completion);
 
-	down(&fw_lock);
+	mutex_lock(&fw_lock);
 	if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
 		retval = -ENOENT;
 		release_firmware(fw_priv->fw);
 		*firmware_p = NULL;
 	}
 	fw_priv->fw = NULL;
-	up(&fw_lock);
+	mutex_unlock(&fw_lock);
 	class_device_unregister(class_dev);
 	goto out;
 
diff --git a/drivers/base/hypervisor.c b/drivers/base/hypervisor.c
new file mode 100644
index 0000000..0c85e9d
--- /dev/null
+++ b/drivers/base/hypervisor.c
@@ -0,0 +1,19 @@
+/*
+ * hypervisor.c - /sys/hypervisor subsystem.
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/kobject.h>
+#include <linux/device.h>
+
+#include "base.h"
+
+decl_subsys(hypervisor, NULL, NULL);
+EXPORT_SYMBOL_GPL(hypervisor_subsys);
+
+int __init hypervisor_init(void)
+{
+	return subsystem_register(&hypervisor_subsys);
+}
diff --git a/drivers/base/init.c b/drivers/base/init.c
index c648914..3713815 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -27,6 +27,7 @@
 	buses_init();
 	classes_init();
 	firmware_init();
+	hypervisor_init();
 
 	/* These are also core pieces, but must come after the
 	 * core core pieces.
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
new file mode 100644
index 0000000..d222239
--- /dev/null
+++ b/drivers/base/isa.c
@@ -0,0 +1,180 @@
+/*
+ * ISA bus.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/isa.h>
+
+static struct device isa_bus = {
+	.bus_id		= "isa"
+};
+
+struct isa_dev {
+	struct device dev;
+	struct device *next;
+	unsigned int id;
+};
+
+#define to_isa_dev(x) container_of((x), struct isa_dev, dev)
+
+static int isa_bus_match(struct device *dev, struct device_driver *driver)
+{
+	struct isa_driver *isa_driver = to_isa_driver(driver);
+
+	if (dev->platform_data == isa_driver) {
+		if (!isa_driver->match ||
+			isa_driver->match(dev, to_isa_dev(dev)->id))
+			return 1;
+		dev->platform_data = NULL;
+	}
+	return 0;
+}
+
+static int isa_bus_probe(struct device *dev)
+{
+	struct isa_driver *isa_driver = dev->platform_data;
+
+	if (isa_driver->probe)
+		return isa_driver->probe(dev, to_isa_dev(dev)->id);
+
+	return 0;
+}
+
+static int isa_bus_remove(struct device *dev)
+{
+	struct isa_driver *isa_driver = dev->platform_data;
+
+	if (isa_driver->remove)
+		return isa_driver->remove(dev, to_isa_dev(dev)->id);
+
+	return 0;
+}
+
+static void isa_bus_shutdown(struct device *dev)
+{
+	struct isa_driver *isa_driver = dev->platform_data;
+
+	if (isa_driver->shutdown)
+		isa_driver->shutdown(dev, to_isa_dev(dev)->id);
+}
+
+static int isa_bus_suspend(struct device *dev, pm_message_t state)
+{
+	struct isa_driver *isa_driver = dev->platform_data;
+
+	if (isa_driver->suspend)
+		return isa_driver->suspend(dev, to_isa_dev(dev)->id, state);
+
+	return 0;
+}
+
+static int isa_bus_resume(struct device *dev)
+{
+	struct isa_driver *isa_driver = dev->platform_data;
+
+	if (isa_driver->resume)
+		return isa_driver->resume(dev, to_isa_dev(dev)->id);
+
+	return 0;
+}
+
+static struct bus_type isa_bus_type = {
+	.name		= "isa",
+	.match		= isa_bus_match,
+	.probe		= isa_bus_probe,
+	.remove		= isa_bus_remove,
+	.shutdown	= isa_bus_shutdown,
+	.suspend	= isa_bus_suspend,
+	.resume		= isa_bus_resume
+};
+
+static void isa_dev_release(struct device *dev)
+{
+	kfree(to_isa_dev(dev));
+}
+
+void isa_unregister_driver(struct isa_driver *isa_driver)
+{
+	struct device *dev = isa_driver->devices;
+
+	while (dev) {
+		struct device *tmp = to_isa_dev(dev)->next;
+		device_unregister(dev);
+		dev = tmp;
+	}
+	driver_unregister(&isa_driver->driver);
+}
+EXPORT_SYMBOL_GPL(isa_unregister_driver);
+
+int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
+{
+	int error;
+	unsigned int id;
+
+	isa_driver->driver.bus	= &isa_bus_type;
+	isa_driver->devices	= NULL;
+
+	error = driver_register(&isa_driver->driver);
+	if (error)
+		return error;
+
+	for (id = 0; id < ndev; id++) {
+		struct isa_dev *isa_dev;
+
+		isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL);
+		if (!isa_dev) {
+			error = -ENOMEM;
+			break;
+		}
+
+		isa_dev->dev.parent	= &isa_bus;
+		isa_dev->dev.bus	= &isa_bus_type;
+
+		snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u",
+				isa_driver->driver.name, id);
+
+		isa_dev->dev.platform_data	= isa_driver;
+		isa_dev->dev.release		= isa_dev_release;
+		isa_dev->id			= id;
+
+		error = device_register(&isa_dev->dev);
+		if (error) {
+			put_device(&isa_dev->dev);
+			break;
+		}
+
+		if (isa_dev->dev.platform_data) {
+			isa_dev->next = isa_driver->devices;
+			isa_driver->devices = &isa_dev->dev;
+		} else
+			device_unregister(&isa_dev->dev);
+	}
+
+	if (!error && !isa_driver->devices)
+		error = -ENODEV;
+
+	if (error)
+		isa_unregister_driver(isa_driver);
+
+	return error;
+}
+EXPORT_SYMBOL_GPL(isa_register_driver);
+
+static int __init isa_bus_init(void)
+{
+	int error;
+
+	error = bus_register(&isa_bus_type);
+	if (!error) {
+		error = device_register(&isa_bus);
+		if (error)
+			bus_unregister(&isa_bus_type);
+	}
+	return error;
+}
+
+device_initcall(isa_bus_init);
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index dd547af..c6b7d9c 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -306,11 +306,13 @@
 memory_probe_store(struct class *class, const char *buf, size_t count)
 {
 	u64 phys_addr;
+	int nid;
 	int ret;
 
 	phys_addr = simple_strtoull(buf, NULL, 0);
 
-	ret = add_memory(phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
+	nid = memory_add_physaddr_to_nid(phys_addr);
+	ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
 
 	if (ret)
 		count = ret;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index c80c3ae..eae2bdc 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -11,6 +11,7 @@
 #include <linux/cpumask.h>
 #include <linux/topology.h>
 #include <linux/nodemask.h>
+#include <linux/cpu.h>
 
 static struct sysdev_class node_class = {
 	set_kset_name("node"),
@@ -190,6 +191,66 @@
 	sysdev_unregister(&node->sysdev);
 }
 
+struct node node_devices[MAX_NUMNODES];
+
+/*
+ * register cpu under node
+ */
+int register_cpu_under_node(unsigned int cpu, unsigned int nid)
+{
+	if (node_online(nid)) {
+		struct sys_device *obj = get_cpu_sysdev(cpu);
+		if (!obj)
+			return 0;
+		return sysfs_create_link(&node_devices[nid].sysdev.kobj,
+					 &obj->kobj,
+					 kobject_name(&obj->kobj));
+	 }
+
+	return 0;
+}
+
+int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
+{
+	if (node_online(nid)) {
+		struct sys_device *obj = get_cpu_sysdev(cpu);
+		if (obj)
+			sysfs_remove_link(&node_devices[nid].sysdev.kobj,
+					 kobject_name(&obj->kobj));
+	}
+	return 0;
+}
+
+int register_one_node(int nid)
+{
+	int error = 0;
+	int cpu;
+
+	if (node_online(nid)) {
+		int p_node = parent_node(nid);
+		struct node *parent = NULL;
+
+		if (p_node != nid)
+			parent = &node_devices[p_node];
+
+		error = register_node(&node_devices[nid], nid, parent);
+
+		/* link cpu under this node */
+		for_each_present_cpu(cpu) {
+			if (cpu_to_node(cpu) == nid)
+				register_cpu_under_node(cpu, nid);
+		}
+	}
+
+	return error;
+
+}
+
+void unregister_one_node(int nid)
+{
+	unregister_node(&node_devices[nid]);
+}
+
 static int __init register_node_type(void)
 {
 	return sysdev_class_register(&node_class);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 83f5c59..2b8755d 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -275,7 +275,7 @@
 	pr_debug("Registering platform device '%s'. Parent at %s\n",
 		 pdev->dev.bus_id, pdev->dev.parent->bus_id);
 
-	ret = device_register(&pdev->dev);
+	ret = device_add(&pdev->dev);
 	if (ret == 0)
 		return ret;
 
@@ -452,6 +452,37 @@
 EXPORT_SYMBOL_GPL(platform_driver_unregister);
 
 
+/* modalias support enables more hands-off userspace setup:
+ * (a) environment variable lets new-style hotplug events work once system is
+ *     fully running:  "modprobe $MODALIAS"
+ * (b) sysfs attribute lets new-style coldplug recover from hotplug events
+ *     mishandled before system is fully running:  "modprobe $(cat modalias)"
+ */
+static ssize_t
+modalias_show(struct device *dev, struct device_attribute *a, char *buf)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+	int len = snprintf(buf, PAGE_SIZE, "%s\n", pdev->name);
+
+	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute platform_dev_attrs[] = {
+	__ATTR_RO(modalias),
+	__ATTR_NULL,
+};
+
+static int platform_uevent(struct device *dev, char **envp, int num_envp,
+		char *buffer, int buffer_size)
+{
+	struct platform_device	*pdev = to_platform_device(dev);
+
+	envp[0] = buffer;
+	snprintf(buffer, buffer_size, "MODALIAS=%s", pdev->name);
+	return 0;
+}
+
+
 /**
  *	platform_match - bind platform device to platform driver.
  *	@dev:	device.
@@ -496,7 +527,9 @@
 
 struct bus_type platform_bus_type = {
 	.name		= "platform",
+	.dev_attrs	= platform_dev_attrs,
 	.match		= platform_match,
+	.uevent		= platform_uevent,
 	.suspend	= platform_suspend,
 	.resume		= platform_resume,
 };
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index c0219ad..91f2309 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,6 +1,10 @@
 obj-y			:= shutdown.o
 obj-$(CONFIG_PM)	+= main.o suspend.o resume.o runtime.o sysfs.o
+obj-$(CONFIG_PM_TRACE)	+= trace.o
 
 ifeq ($(CONFIG_DEBUG_DRIVER),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
+ifeq ($(CONFIG_PM_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 317edbf..826093e 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -9,6 +9,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/resume-trace.h>
 #include "../base.h"
 #include "power.h"
 
@@ -23,6 +24,8 @@
 {
 	int error = 0;
 
+	TRACE_DEVICE(dev);
+	TRACE_RESUME(0);
 	down(&dev->sem);
 	if (dev->power.pm_parent
 			&& dev->power.pm_parent->power.power_state.event) {
@@ -36,6 +39,7 @@
 		error = dev->bus->resume(dev);
 	}
 	up(&dev->sem);
+	TRACE_RESUME(error);
 	return error;
 }
 
@@ -49,8 +53,7 @@
 		struct device * dev = to_device(entry);
 
 		get_device(dev);
-		list_del_init(entry);
-		list_add_tail(entry, &dpm_active);
+		list_move_tail(entry, &dpm_active);
 
 		up(&dpm_list_sem);
 		if (!dev->power.prev_state.event)
@@ -97,8 +100,7 @@
 		struct device * dev = to_device(entry);
 
 		get_device(dev);
-		list_del_init(entry);
-		list_add_tail(entry, &dpm_active);
+		list_move_tail(entry, &dpm_active);
 		resume_device(dev);
 		put_device(dev);
 	}
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 2a769cc..69509e0 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -29,6 +29,15 @@
  * lists. This way, the ancestors will be accessed before their descendents.
  */
 
+static inline char *suspend_verb(u32 event)
+{
+	switch (event) {
+	case PM_EVENT_SUSPEND:	return "suspend";
+	case PM_EVENT_FREEZE:	return "freeze";
+	default:		return "(unknown suspend event)";
+	}
+}
+
 
 /**
  *	suspend_device - Save state of one device.
@@ -57,7 +66,13 @@
 	dev->power.prev_state = dev->power.power_state;
 
 	if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
-		dev_dbg(dev, "suspending\n");
+		dev_dbg(dev, "%s%s\n",
+			suspend_verb(state.event),
+			((state.event == PM_EVENT_SUSPEND)
+					&& device_may_wakeup(dev))
+				? ", may wakeup"
+				: ""
+			);
 		error = dev->bus->suspend(dev, state);
 		suspend_report_result(dev->bus->suspend, error);
 	}
@@ -101,12 +116,10 @@
 		/* Check if the device got removed */
 		if (!list_empty(&dev->power.entry)) {
 			/* Move it to the dpm_off or dpm_off_irq list */
-			if (!error) {
-				list_del(&dev->power.entry);
-				list_add(&dev->power.entry, &dpm_off);
-			} else if (error == -EAGAIN) {
-				list_del(&dev->power.entry);
-				list_add(&dev->power.entry, &dpm_off_irq);
+			if (!error)
+				list_move(&dev->power.entry, &dpm_off);
+			else if (error == -EAGAIN) {
+				list_move(&dev->power.entry, &dpm_off_irq);
 				error = 0;
 			}
 		}
@@ -124,8 +137,7 @@
 		 */
 		while (!list_empty(&dpm_off_irq)) {
 			struct list_head * entry = dpm_off_irq.next;
-			list_del(entry);
-			list_add(entry, &dpm_off);
+			list_move(entry, &dpm_off);
 		}
 		dpm_resume();
 	}
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
new file mode 100644
index 0000000..a9ab30f
--- /dev/null
+++ b/drivers/base/power/trace.c
@@ -0,0 +1,228 @@
+/*
+ * drivers/base/power/trace.c
+ *
+ * Copyright (C) 2006 Linus Torvalds
+ *
+ * Trace facility for suspend/resume problems, when none of the
+ * devices may be working.
+ */
+
+#include <linux/resume-trace.h>
+#include <linux/rtc.h>
+
+#include <asm/rtc.h>
+
+#include "power.h"
+
+/*
+ * Horrid, horrid, horrid.
+ *
+ * It turns out that the _only_ piece of hardware that actually
+ * keeps its value across a hard boot (and, more importantly, the
+ * POST init sequence) is literally the realtime clock.
+ *
+ * Never mind that an RTC chip has 114 bytes (and often a whole
+ * other bank of an additional 128 bytes) of nice SRAM that is
+ * _designed_ to keep data - the POST will clear it. So we literally
+ * can just use the few bytes of actual time data, which means that
+ * we're really limited.
+ *
+ * It means, for example, that we can't use the seconds at all
+ * (since the time between the hang and the boot might be more
+ * than a minute), and we'd better not depend on the low bits of
+ * the minutes either.
+ *
+ * There are the wday fields etc, but I wouldn't guarantee those
+ * are dependable either. And if the date isn't valid, either the
+ * hw or POST will do strange things.
+ *
+ * So we're left with:
+ *  - year: 0-99
+ *  - month: 0-11
+ *  - day-of-month: 1-28
+ *  - hour: 0-23
+ *  - min: (0-30)*2
+ *
+ * Giving us a total range of 0-16128000 (0xf61800), ie less
+ * than 24 bits of actual data we can save across reboots.
+ *
+ * And if your box can't boot in less than three minutes,
+ * you're screwed.
+ *
+ * Now, almost 24 bits of data is pitifully small, so we need
+ * to be pretty dense if we want to use it for anything nice.
+ * What we do is that instead of saving off nice readable info,
+ * we save off _hashes_ of information that we can hopefully
+ * regenerate after the reboot.
+ *
+ * In particular, this means that we might be unlucky, and hit
+ * a case where we have a hash collision, and we end up not
+ * being able to tell for certain exactly which case happened.
+ * But that's hopefully unlikely.
+ *
+ * What we do is to take the bits we can fit, and split them
+ * into three parts (16*997*1009 = 16095568), and use the values
+ * for:
+ *  - 0-15: user-settable
+ *  - 0-996: file + line number
+ *  - 0-1008: device
+ */
+#define USERHASH (16)
+#define FILEHASH (997)
+#define DEVHASH (1009)
+
+#define DEVSEED (7919)
+
+static unsigned int dev_hash_value;
+
+static int set_magic_time(unsigned int user, unsigned int file, unsigned int device)
+{
+	unsigned int n = user + USERHASH*(file + FILEHASH*device);
+
+	// June 7th, 2006
+	static struct rtc_time time = {
+		.tm_sec = 0,
+		.tm_min = 0,
+		.tm_hour = 0,
+		.tm_mday = 7,
+		.tm_mon = 5,	// June - counting from zero
+		.tm_year = 106,
+		.tm_wday = 3,
+		.tm_yday = 160,
+		.tm_isdst = 1
+	};
+
+	time.tm_year = (n % 100);
+	n /= 100;
+	time.tm_mon = (n % 12);
+	n /= 12;
+	time.tm_mday = (n % 28) + 1;
+	n /= 28;
+	time.tm_hour = (n % 24);
+	n /= 24;
+	time.tm_min = (n % 20) * 3;
+	n /= 20;
+	set_rtc_time(&time);
+	return n ? -1 : 0;
+}
+
+static unsigned int read_magic_time(void)
+{
+	struct rtc_time time;
+	unsigned int val;
+
+	get_rtc_time(&time);
+	printk("Time: %2d:%02d:%02d  Date: %02d/%02d/%02d\n",
+		time.tm_hour, time.tm_min, time.tm_sec,
+		time.tm_mon, time.tm_mday, time.tm_year);
+	val = time.tm_year;				/* 100 years */
+	if (val > 100)
+		val -= 100;
+	val += time.tm_mon * 100;			/* 12 months */
+	val += (time.tm_mday-1) * 100 * 12;		/* 28 month-days */
+	val += time.tm_hour * 100 * 12 * 28;		/* 24 hours */
+	val += (time.tm_min / 3) * 100 * 12 * 28 * 24;	/* 20 3-minute intervals */
+	return val;
+}
+
+/*
+ * This is just the sdbm hash function with a user-supplied
+ * seed and final size parameter.
+ */
+static unsigned int hash_string(unsigned int seed, const char *data, unsigned int mod)
+{
+	unsigned char c;
+	while ((c = *data++) != 0) {
+		seed = (seed << 16) + (seed << 6) - seed + c;
+	}
+	return seed % mod;
+}
+
+void set_trace_device(struct device *dev)
+{
+	dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH);
+}
+
+/*
+ * We could just take the "tracedata" index into the .tracedata
+ * section instead. Generating a hash of the data gives us a
+ * chance to work across kernel versions, and perhaps more
+ * importantly it also gives us valid/invalid check (ie we will
+ * likely not give totally bogus reports - if the hash matches,
+ * it's not any guarantee, but it's a high _likelihood_ that
+ * the match is valid).
+ */
+void generate_resume_trace(void *tracedata, unsigned int user)
+{
+	unsigned short lineno = *(unsigned short *)tracedata;
+	const char *file = *(const char **)(tracedata + 2);
+	unsigned int user_hash_value, file_hash_value;
+
+	user_hash_value = user % USERHASH;
+	file_hash_value = hash_string(lineno, file, FILEHASH);
+	set_magic_time(user_hash_value, file_hash_value, dev_hash_value);
+}
+
+extern char __tracedata_start, __tracedata_end;
+static int show_file_hash(unsigned int value)
+{
+	int match;
+	char *tracedata;
+
+	match = 0;
+	for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) {
+		unsigned short lineno = *(unsigned short *)tracedata;
+		const char *file = *(const char **)(tracedata + 2);
+		unsigned int hash = hash_string(lineno, file, FILEHASH);
+		if (hash != value)
+			continue;
+		printk("  hash matches %s:%u\n", file, lineno);
+		match++;
+	}
+	return match;
+}
+
+static int show_dev_hash(unsigned int value)
+{
+	int match = 0;
+	struct list_head * entry = dpm_active.prev;
+
+	while (entry != &dpm_active) {
+		struct device * dev = to_device(entry);
+		unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
+		if (hash == value) {
+			printk("  hash matches device %s\n", dev->bus_id);
+			match++;
+		}
+		entry = entry->prev;
+	}
+	return match;
+}
+
+static unsigned int hash_value_early_read;
+
+static int early_resume_init(void)
+{
+	hash_value_early_read = read_magic_time();
+	return 0;
+}
+
+static int late_resume_init(void)
+{
+	unsigned int val = hash_value_early_read;
+	unsigned int user, file, dev;
+
+	user = val % USERHASH;
+	val = val / USERHASH;
+	file = val % FILEHASH;
+	val = val / FILEHASH;
+	dev = val /* % DEVHASH */;
+
+	printk("  Magic number: %d:%d:%d\n", user, file, dev);
+	show_file_hash(file);
+	show_dev_hash(dev);
+	return 0;
+}
+
+core_initcall(early_resume_init);
+late_initcall(late_resume_init);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 6fc23ab..6858178 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -80,10 +80,59 @@
 EXPORT_SYMBOL_GPL(sysdev_create_file);
 EXPORT_SYMBOL_GPL(sysdev_remove_file);
 
+#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj)
+#define to_sysdev_class_attr(a) container_of(a, \
+	struct sysdev_class_attribute, attr)
+
+static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
+				 char *buffer)
+{
+	struct sysdev_class * class = to_sysdev_class(kobj);
+	struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
+
+	if (class_attr->show)
+		return class_attr->show(class, buffer);
+	return -EIO;
+}
+
+static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
+				  const char *buffer, size_t count)
+{
+	struct sysdev_class * class = to_sysdev_class(kobj);
+	struct sysdev_class_attribute * class_attr = to_sysdev_class_attr(attr);
+
+	if (class_attr->store)
+		return class_attr->store(class, buffer, count);
+	return -EIO;
+}
+
+static struct sysfs_ops sysfs_class_ops = {
+	.show	= sysdev_class_show,
+	.store	= sysdev_class_store,
+};
+
+static struct kobj_type ktype_sysdev_class = {
+	.sysfs_ops	= &sysfs_class_ops,
+};
+
+int sysdev_class_create_file(struct sysdev_class *c,
+			     struct sysdev_class_attribute *a)
+{
+	return sysfs_create_file(&c->kset.kobj, &a->attr);
+}
+EXPORT_SYMBOL_GPL(sysdev_class_create_file);
+
+void sysdev_class_remove_file(struct sysdev_class *c,
+			      struct sysdev_class_attribute *a)
+{
+	sysfs_remove_file(&c->kset.kobj, &a->attr);
+}
+EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
+
 /*
  * declare system_subsys
  */
-static decl_subsys(system, &ktype_sysdev, NULL);
+static decl_subsys(system, &ktype_sysdev_class, NULL);
 
 int sysdev_class_register(struct sysdev_class * cls)
 {
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 8c52421..c2d6216 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -107,7 +107,7 @@
 	return 0;
 }
 
-static int topology_cpu_callback(struct notifier_block *nfb,
+static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
 		unsigned long action, void *hcpu)
 {
 	unsigned int cpu = (unsigned long)hcpu;
@@ -125,7 +125,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block topology_cpu_notifier =
+static struct notifier_block __cpuinitdata topology_cpu_notifier =
 {
 	.notifier_call = topology_cpu_callback,
 };
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 45bcda5..dd8a150 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -17,8 +17,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.5.47"
-#define DAC960_DriverDate			"14 November 2002"
+#define DAC960_DriverVersion			"2.5.48"
+#define DAC960_DriverDate			"14 May 2006"
 
 
 #include <linux/module.h>
@@ -4780,15 +4780,16 @@
 	      (NewPhysicalDeviceInfo->LogicalUnit !=
 	       PhysicalDeviceInfo->LogicalUnit))
 	    {
-	      PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
+	      PhysicalDeviceInfo =
 		kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
 	      InquiryUnitSerialNumber =
-		(DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
 		  kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
 			  GFP_ATOMIC);
-	      if (InquiryUnitSerialNumber == NULL &&
-		  PhysicalDeviceInfo != NULL)
+	      if (InquiryUnitSerialNumber == NULL ||
+		  PhysicalDeviceInfo == NULL)
 		{
+		  kfree(InquiryUnitSerialNumber);
+		  InquiryUnitSerialNumber = NULL;
 		  kfree(PhysicalDeviceInfo);
 		  PhysicalDeviceInfo = NULL;
 		}
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index ae0949b..93d9474 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -402,6 +402,7 @@
 
 config BLK_DEV_INITRD
 	bool "Initial RAM filesystem and RAM disk (initramfs/initrd) support"
+	depends on BROKEN || !FRV
 	help
 	  The initial RAM filesystem is a ramfs which is loaded by the
 	  boot loader (loadlin or lilo) and that is mounted as root
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 2a8af68..2641597 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -64,6 +64,7 @@
 #include <linux/buffer_head.h>
 #include <linux/blkdev.h>
 #include <linux/elevator.h>
+#include <linux/interrupt.h>
 
 #include <asm/setup.h>
 #include <asm/uaccess.h>
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index fdff774..c1434ed 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -116,8 +116,7 @@
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (skb == NULL)
 		return 0;
-	if (skb_is_nonlinear(skb))
-	if (skb_linearize(skb, GFP_ATOMIC) < 0)
+	if (skb_linearize(skb))
 		goto exit;
 	if (!is_aoe_netif(ifp))
 		goto exit;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 1319d8f..39b0f53 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -34,7 +34,7 @@
 #include <linux/blkpg.h>
 #include <linux/timer.h>
 #include <linux/proc_fs.h>
-#include <linux/init.h> 
+#include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/spinlock.h>
 #include <linux/compat.h>
@@ -64,143 +64,129 @@
 
 /* define the PCI info for the cards we can control */
 static const struct pci_device_id cciss_pci_device_id[] = {
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS,
-			0x0E11, 0x4070, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
-                        0x0E11, 0x4080, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
-                        0x0E11, 0x4082, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
-                        0x0E11, 0x4083, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
-		0x0E11, 0x409A, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
-		0x0E11, 0x409B, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
-		0x0E11, 0x409C, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
-		0x0E11, 0x409D, 0, 0, 0},
-	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
-		0x0E11, 0x4091, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
-		0x103C, 0x3225, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
-		0x103c, 0x3223, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
-		0x103c, 0x3234, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
-		0x103c, 0x3235, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
-		0x103c, 0x3211, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
-		0x103c, 0x3212, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
-		0x103c, 0x3213, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
-		0x103c, 0x3214, 0, 0, 0},
-	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
-		0x103c, 0x3215, 0, 0, 0},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS,  0x0E11, 0x4070},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4080},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4082},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4083},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x4091},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409A},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409B},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409C},
+	{PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409D},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSA,     0x103C, 0x3225},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3223},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3234},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSC,     0x103C, 0x3235},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3211},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3212},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3213},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3214},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSD,     0x103C, 0x3215},
 	{0,}
 };
-MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
 
-#define NR_PRODUCTS ARRAY_SIZE(products)
+MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
 
 /*  board_id = Subsystem Device ID & Vendor ID
  *  product = Marketing Name for the board
- *  access = Address of the struct of function pointers 
+ *  access = Address of the struct of function pointers
  */
 static struct board_type products[] = {
-	{ 0x40700E11, "Smart Array 5300", &SA5_access },
-	{ 0x40800E11, "Smart Array 5i", &SA5B_access},
-	{ 0x40820E11, "Smart Array 532", &SA5B_access},
-	{ 0x40830E11, "Smart Array 5312", &SA5B_access},
-	{ 0x409A0E11, "Smart Array 641", &SA5_access},
-	{ 0x409B0E11, "Smart Array 642", &SA5_access},
-	{ 0x409C0E11, "Smart Array 6400", &SA5_access},
-	{ 0x409D0E11, "Smart Array 6400 EM", &SA5_access},
-	{ 0x40910E11, "Smart Array 6i", &SA5_access},
-	{ 0x3225103C, "Smart Array P600", &SA5_access},
-	{ 0x3223103C, "Smart Array P800", &SA5_access},
-	{ 0x3234103C, "Smart Array P400", &SA5_access},
-	{ 0x3235103C, "Smart Array P400i", &SA5_access},
-	{ 0x3211103C, "Smart Array E200i", &SA5_access},
-	{ 0x3212103C, "Smart Array E200", &SA5_access},
-	{ 0x3213103C, "Smart Array E200i", &SA5_access},
-	{ 0x3214103C, "Smart Array E200i", &SA5_access},
-	{ 0x3215103C, "Smart Array E200i", &SA5_access},
+	{0x40700E11, "Smart Array 5300", &SA5_access},
+	{0x40800E11, "Smart Array 5i", &SA5B_access},
+	{0x40820E11, "Smart Array 532", &SA5B_access},
+	{0x40830E11, "Smart Array 5312", &SA5B_access},
+	{0x409A0E11, "Smart Array 641", &SA5_access},
+	{0x409B0E11, "Smart Array 642", &SA5_access},
+	{0x409C0E11, "Smart Array 6400", &SA5_access},
+	{0x409D0E11, "Smart Array 6400 EM", &SA5_access},
+	{0x40910E11, "Smart Array 6i", &SA5_access},
+	{0x3225103C, "Smart Array P600", &SA5_access},
+	{0x3223103C, "Smart Array P800", &SA5_access},
+	{0x3234103C, "Smart Array P400", &SA5_access},
+	{0x3235103C, "Smart Array P400i", &SA5_access},
+	{0x3211103C, "Smart Array E200i", &SA5_access},
+	{0x3212103C, "Smart Array E200", &SA5_access},
+	{0x3213103C, "Smart Array E200i", &SA5_access},
+	{0x3214103C, "Smart Array E200i", &SA5_access},
+	{0x3215103C, "Smart Array E200i", &SA5_access},
 };
 
-/* How long to wait (in millesconds) for board to go into simple mode */
-#define MAX_CONFIG_WAIT 30000 
+/* How long to wait (in milliseconds) for board to go into simple mode */
+#define MAX_CONFIG_WAIT 30000
 #define MAX_IOCTL_CONFIG_WAIT 1000
 
 /*define how many times we will try a command because of bus resets */
 #define MAX_CMD_RETRIES 3
 
 #define READ_AHEAD 	 1024
-#define NR_CMDS		 384 /* #commands that can be outstanding */
+#define NR_CMDS		 384	/* #commands that can be outstanding */
 #define MAX_CTLR	32
 
 /* Originally cciss driver only supports 8 major numbers */
 #define MAX_CTLR_ORIG 	8
 
-
 static ctlr_info_t *hba[MAX_CTLR];
 
 static void do_cciss_request(request_queue_t *q);
 static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs);
 static int cciss_open(struct inode *inode, struct file *filep);
 static int cciss_release(struct inode *inode, struct file *filep);
-static int cciss_ioctl(struct inode *inode, struct file *filep, 
-		unsigned int cmd, unsigned long arg);
+static int cciss_ioctl(struct inode *inode, struct file *filep,
+		       unsigned int cmd, unsigned long arg);
 static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
 static int revalidate_allvol(ctlr_info_t *host);
 static int cciss_revalidate(struct gendisk *disk);
 static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
-static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all);
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
+			   int clear_all);
 
 static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
-	int withirq, unsigned int *total_size, unsigned int *block_size);
-static void cciss_geometry_inquiry(int ctlr, int logvol,
-			int withirq, unsigned int total_size,
-			unsigned int block_size, InquiryData_struct *inq_buff,
-			drive_info_struct *drv);
+				int withirq, unsigned int *total_size,
+				unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq,
+				   unsigned int total_size,
+				   unsigned int block_size,
+				   InquiryData_struct *inq_buff,
+				   drive_info_struct *drv);
 static void cciss_getgeometry(int cntl_num);
-static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, __u32);
-static void start_io( ctlr_info_t *h);
-static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
-	unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
-	unsigned char *scsi3addr, int cmd_type);
-static int sendcmd_withirq(__u8	cmd, int ctlr, void *buff, size_t size,
-	unsigned int use_unit_num, unsigned int log_unit, __u8	page_code,
-	int cmd_type);
+static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
+					   __u32);
+static void start_io(ctlr_info_t *h);
+static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size,
+		   unsigned int use_unit_num, unsigned int log_unit,
+		   __u8 page_code, unsigned char *scsi3addr, int cmd_type);
+static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
+			   unsigned int use_unit_num, unsigned int log_unit,
+			   __u8 page_code, int cmd_type);
 
 static void fail_all_cmds(unsigned long ctlr);
 
 #ifdef CONFIG_PROC_FS
-static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 
-		int length, int *eof, void *data);
+static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
+			       int length, int *eof, void *data);
 static void cciss_procinit(int i);
 #else
-static void cciss_procinit(int i) {}
-#endif /* CONFIG_PROC_FS */
+static void cciss_procinit(int i)
+{
+}
+#endif				/* CONFIG_PROC_FS */
 
 #ifdef CONFIG_COMPAT
 static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
 #endif
 
-static struct block_device_operations cciss_fops  = {
-	.owner		= THIS_MODULE,
-	.open		= cciss_open, 
-	.release       	= cciss_release,
-        .ioctl		= cciss_ioctl,
-        .getgeo		= cciss_getgeo,
+static struct block_device_operations cciss_fops = {
+	.owner = THIS_MODULE,
+	.open = cciss_open,
+	.release = cciss_release,
+	.ioctl = cciss_ioctl,
+	.getgeo = cciss_getgeo,
 #ifdef CONFIG_COMPAT
-	.compat_ioctl   = cciss_compat_ioctl,
+	.compat_ioctl = cciss_compat_ioctl,
 #endif
-	.revalidate_disk= cciss_revalidate,
+	.revalidate_disk = cciss_revalidate,
 };
 
 /*
@@ -208,28 +194,29 @@
  */
 static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c)
 {
-        if (*Qptr == NULL) {
-                *Qptr = c;
-                c->next = c->prev = c;
-        } else {
-                c->prev = (*Qptr)->prev;
-                c->next = (*Qptr);
-                (*Qptr)->prev->next = c;
-                (*Qptr)->prev = c;
-        }
+	if (*Qptr == NULL) {
+		*Qptr = c;
+		c->next = c->prev = c;
+	} else {
+		c->prev = (*Qptr)->prev;
+		c->next = (*Qptr);
+		(*Qptr)->prev->next = c;
+		(*Qptr)->prev = c;
+	}
 }
 
-static inline CommandList_struct *removeQ(CommandList_struct **Qptr, 
-						CommandList_struct *c)
+static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
+					  CommandList_struct *c)
 {
-        if (c && c->next != c) {
-                if (*Qptr == c) *Qptr = c->next;
-                c->prev->next = c->next;
-                c->next->prev = c->prev;
-        } else {
-                *Qptr = NULL;
-        }
-        return c;
+	if (c && c->next != c) {
+		if (*Qptr == c)
+			*Qptr = c->next;
+		c->prev->next = c->next;
+		c->next->prev = c->prev;
+	} else {
+		*Qptr = NULL;
+	}
+	return c;
 }
 
 #include "cciss_scsi.c"		/* For SCSI tape support */
@@ -242,23 +229,24 @@
 #define ENG_GIG 1000000000
 #define ENG_GIG_FACTOR (ENG_GIG/512)
 #define RAID_UNKNOWN 6
-static const char *raid_label[] = {"0","4","1(1+0)","5","5+1","ADG",
-	                                   "UNKNOWN"};
+static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
+	"UNKNOWN"
+};
 
 static struct proc_dir_entry *proc_cciss;
 
-static int cciss_proc_get_info(char *buffer, char **start, off_t offset, 
-		int length, int *eof, void *data)
+static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
+			       int length, int *eof, void *data)
 {
-        off_t pos = 0;
-        off_t len = 0;
-        int size, i, ctlr;
-        ctlr_info_t *h = (ctlr_info_t*)data;
-        drive_info_struct *drv;
+	off_t pos = 0;
+	off_t len = 0;
+	int size, i, ctlr;
+	ctlr_info_t *h = (ctlr_info_t *) data;
+	drive_info_struct *drv;
 	unsigned long flags;
-        sector_t vol_sz, vol_sz_frac;
+	sector_t vol_sz, vol_sz_frac;
 
-        ctlr = h->ctlr;
+	ctlr = h->ctlr;
 
 	/* prevent displaying bogus info during configuration
 	 * or deconfiguration of a logical volume
@@ -266,35 +254,35 @@
 	spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 	if (h->busy_configuring) {
 		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-	return -EBUSY;
+		return -EBUSY;
 	}
 	h->busy_configuring = 1;
 	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 
-        size = sprintf(buffer, "%s: HP %s Controller\n"
-		"Board ID: 0x%08lx\n"
-		"Firmware Version: %c%c%c%c\n"
-		"IRQ: %d\n"
-		"Logical drives: %d\n"
-		"Current Q depth: %d\n"
-		"Current # commands on controller: %d\n"
-		"Max Q depth since init: %d\n"
-		"Max # commands on controller since init: %d\n"
-		"Max SG entries since init: %d\n\n",
-                h->devname,
-                h->product_name,
-                (unsigned long)h->board_id,
-		h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3],
-                (unsigned int)h->intr[SIMPLE_MODE_INT],
-                h->num_luns, 
-		h->Qdepth, h->commands_outstanding,
-		h->maxQsinceinit, h->max_outstanding, h->maxSG);
+	size = sprintf(buffer, "%s: HP %s Controller\n"
+		       "Board ID: 0x%08lx\n"
+		       "Firmware Version: %c%c%c%c\n"
+		       "IRQ: %d\n"
+		       "Logical drives: %d\n"
+		       "Current Q depth: %d\n"
+		       "Current # commands on controller: %d\n"
+		       "Max Q depth since init: %d\n"
+		       "Max # commands on controller since init: %d\n"
+		       "Max SG entries since init: %d\n\n",
+		       h->devname,
+		       h->product_name,
+		       (unsigned long)h->board_id,
+		       h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
+		       h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT],
+		       h->num_luns, h->Qdepth, h->commands_outstanding,
+		       h->maxQsinceinit, h->max_outstanding, h->maxSG);
 
-        pos += size; len += size;
+	pos += size;
+	len += size;
 	cciss_proc_tape_report(ctlr, buffer, &pos, &len);
-	for(i=0; i<=h->highest_lun; i++) {
+	for (i = 0; i <= h->highest_lun; i++) {
 
-                drv = &h->drv[i];
+		drv = &h->drv[i];
 		if (drv->heads == 0)
 			continue;
 
@@ -305,25 +293,26 @@
 
 		if (drv->raid_level > 5)
 			drv->raid_level = RAID_UNKNOWN;
-		size = sprintf(buffer+len, "cciss/c%dd%d:"
-				"\t%4u.%02uGB\tRAID %s\n",
-				ctlr, i, (int)vol_sz, (int)vol_sz_frac,
-				raid_label[drv->raid_level]);
-                pos += size; len += size;
-        }
+		size = sprintf(buffer + len, "cciss/c%dd%d:"
+			       "\t%4u.%02uGB\tRAID %s\n",
+			       ctlr, i, (int)vol_sz, (int)vol_sz_frac,
+			       raid_label[drv->raid_level]);
+		pos += size;
+		len += size;
+	}
 
-        *eof = 1;
-        *start = buffer+offset;
-        len -= offset;
-        if (len>length)
-                len = length;
+	*eof = 1;
+	*start = buffer + offset;
+	len -= offset;
+	if (len > length)
+		len = length;
 	h->busy_configuring = 0;
-        return len;
+	return len;
 }
 
-static int 
-cciss_proc_write(struct file *file, const char __user *buffer, 
-			unsigned long count, void *data)
+static int
+cciss_proc_write(struct file *file, const char __user *buffer,
+		 unsigned long count, void *data)
 {
 	unsigned char cmd[80];
 	int len;
@@ -332,20 +321,23 @@
 	int rc;
 #endif
 
-	if (count > sizeof(cmd)-1) return -EINVAL;
-	if (copy_from_user(cmd, buffer, count)) return -EFAULT;
+	if (count > sizeof(cmd) - 1)
+		return -EINVAL;
+	if (copy_from_user(cmd, buffer, count))
+		return -EFAULT;
 	cmd[count] = '\0';
 	len = strlen(cmd);	// above 3 lines ensure safety
-	if (len && cmd[len-1] == '\n')
+	if (len && cmd[len - 1] == '\n')
 		cmd[--len] = '\0';
 #	ifdef CONFIG_CISS_SCSI_TAPE
-		if (strcmp("engage scsi", cmd)==0) {
-			rc = cciss_engage_scsi(h->ctlr);
-			if (rc != 0) return -rc;
-			return count;
-		}
-		/* might be nice to have "disengage" too, but it's not 
-		   safely possible. (only 1 module use count, lock issues.) */
+	if (strcmp("engage scsi", cmd) == 0) {
+		rc = cciss_engage_scsi(h->ctlr);
+		if (rc != 0)
+			return -rc;
+		return count;
+	}
+	/* might be nice to have "disengage" too, but it's not
+	   safely possible. (only 1 module use count, lock issues.) */
 #	endif
 	return -EINVAL;
 }
@@ -358,116 +350,113 @@
 {
 	struct proc_dir_entry *pde;
 
-        if (proc_cciss == NULL) {
-                proc_cciss = proc_mkdir("cciss", proc_root_driver);
-                if (!proc_cciss) 
+	if (proc_cciss == NULL) {
+		proc_cciss = proc_mkdir("cciss", proc_root_driver);
+		if (!proc_cciss)
 			return;
-        }
+	}
 
-	pde = create_proc_read_entry(hba[i]->devname, 
-		S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, 
-		proc_cciss, cciss_proc_get_info, hba[i]);
+	pde = create_proc_read_entry(hba[i]->devname,
+				     S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH,
+				     proc_cciss, cciss_proc_get_info, hba[i]);
 	pde->write_proc = cciss_proc_write;
 }
-#endif /* CONFIG_PROC_FS */
+#endif				/* CONFIG_PROC_FS */
 
-/* 
- * For operations that cannot sleep, a command block is allocated at init, 
+/*
+ * For operations that cannot sleep, a command block is allocated at init,
  * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
- * which ones are free or in use.  For operations that can wait for kmalloc 
- * to possible sleep, this routine can be called with get_from_pool set to 0. 
- * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was. 
- */ 
-static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
+ * which ones are free or in use.  For operations that can wait for kmalloc
+ * to possible sleep, this routine can be called with get_from_pool set to 0.
+ * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was.
+ */
+static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
 {
 	CommandList_struct *c;
-	int i; 
+	int i;
 	u64bit temp64;
 	dma_addr_t cmd_dma_handle, err_dma_handle;
 
-	if (!get_from_pool)
-	{
-		c = (CommandList_struct *) pci_alloc_consistent(
-			h->pdev, sizeof(CommandList_struct), &cmd_dma_handle); 
-        	if(c==NULL)
-                 	return NULL;
+	if (!get_from_pool) {
+		c = (CommandList_struct *) pci_alloc_consistent(h->pdev,
+			sizeof(CommandList_struct), &cmd_dma_handle);
+		if (c == NULL)
+			return NULL;
 		memset(c, 0, sizeof(CommandList_struct));
 
 		c->cmdindex = -1;
 
-		c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
-					h->pdev, sizeof(ErrorInfo_struct), 
-					&err_dma_handle);
-	
-		if (c->err_info == NULL)
-		{
-			pci_free_consistent(h->pdev, 
+		c->err_info = (ErrorInfo_struct *)
+		    pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct),
+			    &err_dma_handle);
+
+		if (c->err_info == NULL) {
+			pci_free_consistent(h->pdev,
 				sizeof(CommandList_struct), c, cmd_dma_handle);
 			return NULL;
 		}
 		memset(c->err_info, 0, sizeof(ErrorInfo_struct));
-	} else /* get it out of the controllers pool */ 
-	{
-	     	do {
-                	i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
-                        if (i == NR_CMDS)
-                                return NULL;
-                } while(test_and_set_bit(i & (BITS_PER_LONG - 1), h->cmd_pool_bits+(i/BITS_PER_LONG)) != 0);
+	} else {		/* get it out of the controllers pool */
+
+		do {
+			i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
+			if (i == NR_CMDS)
+				return NULL;
+		} while (test_and_set_bit
+			 (i & (BITS_PER_LONG - 1),
+			  h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
 #ifdef CCISS_DEBUG
 		printk(KERN_DEBUG "cciss: using command buffer %d\n", i);
 #endif
-                c = h->cmd_pool + i;
+		c = h->cmd_pool + i;
 		memset(c, 0, sizeof(CommandList_struct));
-		cmd_dma_handle = h->cmd_pool_dhandle 
-					+ i*sizeof(CommandList_struct);
+		cmd_dma_handle = h->cmd_pool_dhandle
+		    + i * sizeof(CommandList_struct);
 		c->err_info = h->errinfo_pool + i;
 		memset(c->err_info, 0, sizeof(ErrorInfo_struct));
-		err_dma_handle = h->errinfo_pool_dhandle 
-					+ i*sizeof(ErrorInfo_struct);
-                h->nr_allocs++;
+		err_dma_handle = h->errinfo_pool_dhandle
+		    + i * sizeof(ErrorInfo_struct);
+		h->nr_allocs++;
 
 		c->cmdindex = i;
-        }
+	}
 
 	c->busaddr = (__u32) cmd_dma_handle;
-	temp64.val = (__u64) err_dma_handle;	
+	temp64.val = (__u64) err_dma_handle;
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
 	c->ErrDesc.Addr.upper = temp64.val32.upper;
 	c->ErrDesc.Len = sizeof(ErrorInfo_struct);
-	
+
 	c->ctlr = h->ctlr;
-        return c;
-
-
+	return c;
 }
 
-/* 
- * Frees a command block that was previously allocated with cmd_alloc(). 
+/*
+ * Frees a command block that was previously allocated with cmd_alloc().
  */
 static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool)
 {
 	int i;
 	u64bit temp64;
 
-	if( !got_from_pool)
-	{ 
+	if (!got_from_pool) {
 		temp64.val32.lower = c->ErrDesc.Addr.lower;
 		temp64.val32.upper = c->ErrDesc.Addr.upper;
-		pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), 
-			c->err_info, (dma_addr_t) temp64.val);
-		pci_free_consistent(h->pdev, sizeof(CommandList_struct), 
-			c, (dma_addr_t) c->busaddr);
-	} else 
-	{
+		pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct),
+				    c->err_info, (dma_addr_t) temp64.val);
+		pci_free_consistent(h->pdev, sizeof(CommandList_struct),
+				    c, (dma_addr_t) c->busaddr);
+	} else {
 		i = c - h->cmd_pool;
-		clear_bit(i&(BITS_PER_LONG-1), h->cmd_pool_bits+(i/BITS_PER_LONG));
-                h->nr_frees++;
-        }
+		clear_bit(i & (BITS_PER_LONG - 1),
+			  h->cmd_pool_bits + (i / BITS_PER_LONG));
+		h->nr_frees++;
+	}
 }
 
 static inline ctlr_info_t *get_host(struct gendisk *disk)
 {
-	return disk->queue->queuedata; 
+	return disk->queue->queuedata;
 }
 
 static inline drive_info_struct *get_drv(struct gendisk *disk)
@@ -485,7 +474,7 @@
 
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
-#endif /* CCISS_DEBUG */ 
+#endif				/* CCISS_DEBUG */
 
 	if (host->busy_initializing || drv->busy_configuring)
 		return -EBUSY;
@@ -498,10 +487,10 @@
 	 * for "raw controller".
 	 */
 	if (drv->nr_blocks == 0) {
-		if (iminor(inode) != 0)	{ 	/* not node 0? */
+		if (iminor(inode) != 0) {	/* not node 0? */
 			/* if not node 0 make sure it is a partition = 0 */
 			if (iminor(inode) & 0x0f) {
-			return -ENXIO;
+				return -ENXIO;
 				/* if it is, make sure we have a LUN ID */
 			} else if (drv->LunID == 0) {
 				return -ENXIO;
@@ -514,6 +503,7 @@
 	host->usage_count++;
 	return 0;
 }
+
 /*
  * Close.  Sync first.
  */
@@ -523,8 +513,9 @@
 	drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
 
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "cciss_release %s\n", inode->i_bdev->bd_disk->disk_name);
-#endif /* CCISS_DEBUG */
+	printk(KERN_DEBUG "cciss_release %s\n",
+	       inode->i_bdev->bd_disk->disk_name);
+#endif				/* CCISS_DEBUG */
 
 	drv->usage_count--;
 	host->usage_count--;
@@ -542,8 +533,10 @@
 	return ret;
 }
 
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, unsigned long arg);
-static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd, unsigned long arg);
+static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
+				  unsigned long arg);
+static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd,
+				      unsigned long arg);
 
 static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
 {
@@ -575,19 +568,26 @@
 	}
 }
 
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, unsigned long arg)
+static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
+				  unsigned long arg)
 {
 	IOCTL32_Command_struct __user *arg32 =
-		(IOCTL32_Command_struct __user *) arg;
+	    (IOCTL32_Command_struct __user *) arg;
 	IOCTL_Command_struct arg64;
 	IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
 	int err;
 	u32 cp;
 
 	err = 0;
-	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
-	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
-	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |=
+	    copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+			   sizeof(arg64.LUN_info));
+	err |=
+	    copy_from_user(&arg64.Request, &arg32->Request,
+			   sizeof(arg64.Request));
+	err |=
+	    copy_from_user(&arg64.error_info, &arg32->error_info,
+			   sizeof(arg64.error_info));
 	err |= get_user(arg64.buf_size, &arg32->buf_size);
 	err |= get_user(cp, &arg32->buf);
 	arg64.buf = compat_ptr(cp);
@@ -596,28 +596,38 @@
 	if (err)
 		return -EFAULT;
 
-	err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long) p);
+	err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long)p);
 	if (err)
 		return err;
-	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
+	err |=
+	    copy_in_user(&arg32->error_info, &p->error_info,
+			 sizeof(arg32->error_info));
 	if (err)
 		return -EFAULT;
 	return err;
 }
 
-static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned long arg)
+static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd,
+				      unsigned long arg)
 {
 	BIG_IOCTL32_Command_struct __user *arg32 =
-		(BIG_IOCTL32_Command_struct __user *) arg;
+	    (BIG_IOCTL32_Command_struct __user *) arg;
 	BIG_IOCTL_Command_struct arg64;
-	BIG_IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
+	BIG_IOCTL_Command_struct __user *p =
+	    compat_alloc_user_space(sizeof(arg64));
 	int err;
 	u32 cp;
 
 	err = 0;
-	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
-	err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
-	err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+	err |=
+	    copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+			   sizeof(arg64.LUN_info));
+	err |=
+	    copy_from_user(&arg64.Request, &arg32->Request,
+			   sizeof(arg64.Request));
+	err |=
+	    copy_from_user(&arg64.error_info, &arg32->error_info,
+			   sizeof(arg64.error_info));
 	err |= get_user(arg64.buf_size, &arg32->buf_size);
 	err |= get_user(arg64.malloc_size, &arg32->malloc_size);
 	err |= get_user(cp, &arg32->buf);
@@ -625,12 +635,14 @@
 	err |= copy_to_user(p, &arg64, sizeof(arg64));
 
 	if (err)
-		 return -EFAULT;
+		return -EFAULT;
 
-	err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long) p);
+	err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long)p);
 	if (err)
 		return err;
-	err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
+	err |=
+	    copy_in_user(&arg32->error_info, &p->error_info,
+			 sizeof(arg32->error_info));
 	if (err)
 		return -EFAULT;
 	return err;
@@ -651,10 +663,10 @@
 }
 
 /*
- * ioctl 
+ * ioctl
  */
-static int cciss_ioctl(struct inode *inode, struct file *filep, 
-		unsigned int cmd, unsigned long arg)
+static int cciss_ioctl(struct inode *inode, struct file *filep,
+		       unsigned int cmd, unsigned long arg)
 {
 	struct block_device *bdev = inode->i_bdev;
 	struct gendisk *disk = bdev->bd_disk;
@@ -665,171 +677,193 @@
 
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg);
-#endif /* CCISS_DEBUG */ 
-	
-	switch(cmd) {
+#endif				/* CCISS_DEBUG */
+
+	switch (cmd) {
 	case CCISS_GETPCIINFO:
-	{
-		cciss_pci_info_struct pciinfo;
-
-		if (!arg) return -EINVAL;
-		pciinfo.domain = pci_domain_nr(host->pdev->bus);
-		pciinfo.bus = host->pdev->bus->number;
-		pciinfo.dev_fn = host->pdev->devfn;
-		pciinfo.board_id = host->board_id;
-		if (copy_to_user(argp, &pciinfo,  sizeof( cciss_pci_info_struct )))
-			return  -EFAULT;
-		return(0);
-	}	
-	case CCISS_GETINTINFO:
-	{
-		cciss_coalint_struct intinfo;
-		if (!arg) return -EINVAL;
-		intinfo.delay = readl(&host->cfgtable->HostWrite.CoalIntDelay);
-		intinfo.count = readl(&host->cfgtable->HostWrite.CoalIntCount);
-		if (copy_to_user(argp, &intinfo, sizeof( cciss_coalint_struct )))
-			return -EFAULT;
-                return(0);
-        }
-	case CCISS_SETINTINFO:
-        {
-                cciss_coalint_struct intinfo;
-		unsigned long flags;
-		int i;
-
-		if (!arg) return -EINVAL;	
-		if (!capable(CAP_SYS_ADMIN)) return -EPERM;
-		if (copy_from_user(&intinfo, argp, sizeof( cciss_coalint_struct)))
-			return -EFAULT;
-		if ( (intinfo.delay == 0 ) && (intinfo.count == 0))
-
 		{
-//			printk("cciss_ioctl: delay and count cannot be 0\n");
-			return( -EINVAL);
+			cciss_pci_info_struct pciinfo;
+
+			if (!arg)
+				return -EINVAL;
+			pciinfo.domain = pci_domain_nr(host->pdev->bus);
+			pciinfo.bus = host->pdev->bus->number;
+			pciinfo.dev_fn = host->pdev->devfn;
+			pciinfo.board_id = host->board_id;
+			if (copy_to_user
+			    (argp, &pciinfo, sizeof(cciss_pci_info_struct)))
+				return -EFAULT;
+			return 0;
 		}
-		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
-		/* Update the field, and then ring the doorbell */ 
-		writel( intinfo.delay, 
-			&(host->cfgtable->HostWrite.CoalIntDelay));
-		writel( intinfo.count, 
-                        &(host->cfgtable->HostWrite.CoalIntCount));
-		writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
+	case CCISS_GETINTINFO:
+		{
+			cciss_coalint_struct intinfo;
+			if (!arg)
+				return -EINVAL;
+			intinfo.delay =
+			    readl(&host->cfgtable->HostWrite.CoalIntDelay);
+			intinfo.count =
+			    readl(&host->cfgtable->HostWrite.CoalIntCount);
+			if (copy_to_user
+			    (argp, &intinfo, sizeof(cciss_coalint_struct)))
+				return -EFAULT;
+			return 0;
+		}
+	case CCISS_SETINTINFO:
+		{
+			cciss_coalint_struct intinfo;
+			unsigned long flags;
+			int i;
 
-		for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) {
-			if (!(readl(host->vaddr + SA5_DOORBELL) 
-					& CFGTBL_ChangeReq))
-				break;
-			/* delay and try again */
-			udelay(1000);
-		}	
-		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-		if (i >= MAX_IOCTL_CONFIG_WAIT)
-			return -EAGAIN;
-                return(0);
-        }
+			if (!arg)
+				return -EINVAL;
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
+			if (copy_from_user
+			    (&intinfo, argp, sizeof(cciss_coalint_struct)))
+				return -EFAULT;
+			if ((intinfo.delay == 0) && (intinfo.count == 0))
+			{
+//                      printk("cciss_ioctl: delay and count cannot be 0\n");
+				return -EINVAL;
+			}
+			spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+			/* Update the field, and then ring the doorbell */
+			writel(intinfo.delay,
+			       &(host->cfgtable->HostWrite.CoalIntDelay));
+			writel(intinfo.count,
+			       &(host->cfgtable->HostWrite.CoalIntCount));
+			writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
+
+			for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+				if (!(readl(host->vaddr + SA5_DOORBELL)
+				      & CFGTBL_ChangeReq))
+					break;
+				/* delay and try again */
+				udelay(1000);
+			}
+			spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+			if (i >= MAX_IOCTL_CONFIG_WAIT)
+				return -EAGAIN;
+			return 0;
+		}
 	case CCISS_GETNODENAME:
-        {
-                NodeName_type NodeName;
-		int i; 
+		{
+			NodeName_type NodeName;
+			int i;
 
-		if (!arg) return -EINVAL;
-		for(i=0;i<16;i++)
-			NodeName[i] = readb(&host->cfgtable->ServerName[i]);
-                if (copy_to_user(argp, NodeName, sizeof( NodeName_type)))
-                	return  -EFAULT;
-                return(0);
-        }
+			if (!arg)
+				return -EINVAL;
+			for (i = 0; i < 16; i++)
+				NodeName[i] =
+				    readb(&host->cfgtable->ServerName[i]);
+			if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
+				return -EFAULT;
+			return 0;
+		}
 	case CCISS_SETNODENAME:
-	{
-		NodeName_type NodeName;
-		unsigned long flags;
-		int i;
+		{
+			NodeName_type NodeName;
+			unsigned long flags;
+			int i;
 
-		if (!arg) return -EINVAL;
-		if (!capable(CAP_SYS_ADMIN)) return -EPERM;
-		
-		if (copy_from_user(NodeName, argp, sizeof( NodeName_type)))
-			return -EFAULT;
+			if (!arg)
+				return -EINVAL;
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
 
-		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+			if (copy_from_user
+			    (NodeName, argp, sizeof(NodeName_type)))
+				return -EFAULT;
 
-			/* Update the field, and then ring the doorbell */ 
-		for(i=0;i<16;i++)
-			writeb( NodeName[i], &host->cfgtable->ServerName[i]);
-			
-		writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
+			spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 
-		for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) {
-			if (!(readl(host->vaddr + SA5_DOORBELL) 
-					& CFGTBL_ChangeReq))
-				break;
-			/* delay and try again */
-			udelay(1000);
-		}	
-		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-		if (i >= MAX_IOCTL_CONFIG_WAIT)
-			return -EAGAIN;
-                return(0);
-        }
+			/* Update the field, and then ring the doorbell */
+			for (i = 0; i < 16; i++)
+				writeb(NodeName[i],
+				       &host->cfgtable->ServerName[i]);
+
+			writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
+
+			for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+				if (!(readl(host->vaddr + SA5_DOORBELL)
+				      & CFGTBL_ChangeReq))
+					break;
+				/* delay and try again */
+				udelay(1000);
+			}
+			spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+			if (i >= MAX_IOCTL_CONFIG_WAIT)
+				return -EAGAIN;
+			return 0;
+		}
 
 	case CCISS_GETHEARTBEAT:
-        {
-                Heartbeat_type heartbeat;
+		{
+			Heartbeat_type heartbeat;
 
-		if (!arg) return -EINVAL;
-                heartbeat = readl(&host->cfgtable->HeartBeat);
-                if (copy_to_user(argp, &heartbeat, sizeof( Heartbeat_type)))
-                	return -EFAULT;
-                return(0);
-        }
+			if (!arg)
+				return -EINVAL;
+			heartbeat = readl(&host->cfgtable->HeartBeat);
+			if (copy_to_user
+			    (argp, &heartbeat, sizeof(Heartbeat_type)))
+				return -EFAULT;
+			return 0;
+		}
 	case CCISS_GETBUSTYPES:
-        {
-                BusTypes_type BusTypes;
+		{
+			BusTypes_type BusTypes;
 
-		if (!arg) return -EINVAL;
-                BusTypes = readl(&host->cfgtable->BusTypes);
-                if (copy_to_user(argp, &BusTypes, sizeof( BusTypes_type) ))
-                	return  -EFAULT;
-                return(0);
-        }
+			if (!arg)
+				return -EINVAL;
+			BusTypes = readl(&host->cfgtable->BusTypes);
+			if (copy_to_user
+			    (argp, &BusTypes, sizeof(BusTypes_type)))
+				return -EFAULT;
+			return 0;
+		}
 	case CCISS_GETFIRMVER:
-        {
-		FirmwareVer_type firmware;
+		{
+			FirmwareVer_type firmware;
 
-		if (!arg) return -EINVAL;
-		memcpy(firmware, host->firm_ver, 4);
+			if (!arg)
+				return -EINVAL;
+			memcpy(firmware, host->firm_ver, 4);
 
-                if (copy_to_user(argp, firmware, sizeof( FirmwareVer_type)))
-                	return -EFAULT;
-                return(0);
-        }
-        case CCISS_GETDRIVVER:
-        {
-		DriverVer_type DriverVer = DRIVER_VERSION;
+			if (copy_to_user
+			    (argp, firmware, sizeof(FirmwareVer_type)))
+				return -EFAULT;
+			return 0;
+		}
+	case CCISS_GETDRIVVER:
+		{
+			DriverVer_type DriverVer = DRIVER_VERSION;
 
-                if (!arg) return -EINVAL;
+			if (!arg)
+				return -EINVAL;
 
-                if (copy_to_user(argp, &DriverVer, sizeof( DriverVer_type) ))
-                	return -EFAULT;
-                return(0);
-        }
+			if (copy_to_user
+			    (argp, &DriverVer, sizeof(DriverVer_type)))
+				return -EFAULT;
+			return 0;
+		}
 
 	case CCISS_REVALIDVOLS:
 		if (bdev != bdev->bd_contains || drv != host->drv)
 			return -ENXIO;
-                return revalidate_allvol(host);
+		return revalidate_allvol(host);
 
- 	case CCISS_GETLUNINFO: {
- 		LogvolInfo_struct luninfo;
- 		
- 		luninfo.LunID = drv->LunID;
- 		luninfo.num_opens = drv->usage_count;
- 		luninfo.num_parts = 0;
- 		if (copy_to_user(argp, &luninfo,
- 				sizeof(LogvolInfo_struct)))
- 			return -EFAULT;
- 		return(0);
- 	}
+	case CCISS_GETLUNINFO:{
+			LogvolInfo_struct luninfo;
+
+			luninfo.LunID = drv->LunID;
+			luninfo.num_opens = drv->usage_count;
+			luninfo.num_parts = 0;
+			if (copy_to_user(argp, &luninfo,
+					 sizeof(LogvolInfo_struct)))
+				return -EFAULT;
+			return 0;
+		}
 	case CCISS_DEREGDISK:
 		return rebuild_lun_table(host, disk);
 
@@ -837,278 +871,284 @@
 		return rebuild_lun_table(host, NULL);
 
 	case CCISS_PASSTHRU:
-	{
-		IOCTL_Command_struct iocommand;
-		CommandList_struct *c;
-		char 	*buff = NULL;
-		u64bit	temp64;
-		unsigned long flags;
-		DECLARE_COMPLETION(wait);
-
-		if (!arg) return -EINVAL;
-	
-		if (!capable(CAP_SYS_RAWIO)) return -EPERM;
-
-		if (copy_from_user(&iocommand, argp, sizeof( IOCTL_Command_struct) ))
-			return -EFAULT;
-		if((iocommand.buf_size < 1) && 
-				(iocommand.Request.Type.Direction != XFER_NONE))
-		{	
-			return -EINVAL;
-		} 
-#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
-		/* Check kmalloc limits */
-		if(iocommand.buf_size > 128000)
-			return -EINVAL;
-#endif
-		if(iocommand.buf_size > 0)
 		{
-			buff =  kmalloc(iocommand.buf_size, GFP_KERNEL);
-			if( buff == NULL) 
+			IOCTL_Command_struct iocommand;
+			CommandList_struct *c;
+			char *buff = NULL;
+			u64bit temp64;
+			unsigned long flags;
+			DECLARE_COMPLETION(wait);
+
+			if (!arg)
+				return -EINVAL;
+
+			if (!capable(CAP_SYS_RAWIO))
+				return -EPERM;
+
+			if (copy_from_user
+			    (&iocommand, argp, sizeof(IOCTL_Command_struct)))
 				return -EFAULT;
-		}
-		if (iocommand.Request.Type.Direction == XFER_WRITE)
-		{
-			/* Copy the data into the buffer we created */ 
-			if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))
-			{
-				kfree(buff);
-				return -EFAULT;
+			if ((iocommand.buf_size < 1) &&
+			    (iocommand.Request.Type.Direction != XFER_NONE)) {
+				return -EINVAL;
 			}
-		} else {
-			memset(buff, 0, iocommand.buf_size);
-		}
-		if ((c = cmd_alloc(host , 0)) == NULL)
-		{
-			kfree(buff);
-			return -ENOMEM;
-		}
-			// Fill in the command type 
-		c->cmd_type = CMD_IOCTL_PEND;
-			// Fill in Command Header 
-		c->Header.ReplyQueue = 0;  // unused in simple mode
-		if( iocommand.buf_size > 0) 	// buffer to fill 
-		{
-			c->Header.SGList = 1;
-			c->Header.SGTotal= 1;
-		} else	// no buffers to fill  
-		{
-			c->Header.SGList = 0;
-                	c->Header.SGTotal= 0;
-		}
-		c->Header.LUN = iocommand.LUN_info;
-		c->Header.Tag.lower = c->busaddr;  // use the kernel address the cmd block for tag
-		
-		// Fill in Request block 
-		c->Request = iocommand.Request; 
-	
-		// Fill in the scatter gather information
-		if (iocommand.buf_size > 0 ) 
-		{
-			temp64.val = pci_map_single( host->pdev, buff,
-                                        iocommand.buf_size, 
-                                PCI_DMA_BIDIRECTIONAL);	
-			c->SG[0].Addr.lower = temp64.val32.lower;
-			c->SG[0].Addr.upper = temp64.val32.upper;
-			c->SG[0].Len = iocommand.buf_size;
-			c->SG[0].Ext = 0;  // we are not chaining
-		}
-		c->waiting = &wait;
-
-		/* Put the request on the tail of the request queue */
-		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
-		addQ(&host->reqQ, c);
-		host->Qdepth++;
-		start_io(host);
-		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-
-		wait_for_completion(&wait);
-
-		/* unlock the buffers from DMA */
-		temp64.val32.lower = c->SG[0].Addr.lower;
-                temp64.val32.upper = c->SG[0].Addr.upper;
-                pci_unmap_single( host->pdev, (dma_addr_t) temp64.val,
-                	iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
-
-		/* Copy the error information out */ 
-		iocommand.error_info = *(c->err_info);
-		if ( copy_to_user(argp, &iocommand, sizeof( IOCTL_Command_struct) ) )
-		{
-			kfree(buff);
-			cmd_free(host, c, 0);
-			return( -EFAULT);	
-		} 	
-
-		if (iocommand.Request.Type.Direction == XFER_READ)
-                {
-                        /* Copy the data out of the buffer we created */
-                        if (copy_to_user(iocommand.buf, buff, iocommand.buf_size))
+#if 0				/* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
+			/* Check kmalloc limits */
+			if (iocommand.buf_size > 128000)
+				return -EINVAL;
+#endif
+			if (iocommand.buf_size > 0) {
+				buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+				if (buff == NULL)
+					return -EFAULT;
+			}
+			if (iocommand.Request.Type.Direction == XFER_WRITE) {
+				/* Copy the data into the buffer we created */
+				if (copy_from_user
+				    (buff, iocommand.buf, iocommand.buf_size)) {
+					kfree(buff);
+					return -EFAULT;
+				}
+			} else {
+				memset(buff, 0, iocommand.buf_size);
+			}
+			if ((c = cmd_alloc(host, 0)) == NULL) {
+				kfree(buff);
+				return -ENOMEM;
+			}
+			// Fill in the command type
+			c->cmd_type = CMD_IOCTL_PEND;
+			// Fill in Command Header
+			c->Header.ReplyQueue = 0;	// unused in simple mode
+			if (iocommand.buf_size > 0)	// buffer to fill
 			{
-                        	kfree(buff);
+				c->Header.SGList = 1;
+				c->Header.SGTotal = 1;
+			} else	// no buffers to fill
+			{
+				c->Header.SGList = 0;
+				c->Header.SGTotal = 0;
+			}
+			c->Header.LUN = iocommand.LUN_info;
+			c->Header.Tag.lower = c->busaddr;	// use the kernel address the cmd block for tag
+
+			// Fill in Request block
+			c->Request = iocommand.Request;
+
+			// Fill in the scatter gather information
+			if (iocommand.buf_size > 0) {
+				temp64.val = pci_map_single(host->pdev, buff,
+					iocommand.buf_size,
+					PCI_DMA_BIDIRECTIONAL);
+				c->SG[0].Addr.lower = temp64.val32.lower;
+				c->SG[0].Addr.upper = temp64.val32.upper;
+				c->SG[0].Len = iocommand.buf_size;
+				c->SG[0].Ext = 0;	// we are not chaining
+			}
+			c->waiting = &wait;
+
+			/* Put the request on the tail of the request queue */
+			spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+			addQ(&host->reqQ, c);
+			host->Qdepth++;
+			start_io(host);
+			spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+
+			wait_for_completion(&wait);
+
+			/* unlock the buffers from DMA */
+			temp64.val32.lower = c->SG[0].Addr.lower;
+			temp64.val32.upper = c->SG[0].Addr.upper;
+			pci_unmap_single(host->pdev, (dma_addr_t) temp64.val,
+					 iocommand.buf_size,
+					 PCI_DMA_BIDIRECTIONAL);
+
+			/* Copy the error information out */
+			iocommand.error_info = *(c->err_info);
+			if (copy_to_user
+			    (argp, &iocommand, sizeof(IOCTL_Command_struct))) {
+				kfree(buff);
 				cmd_free(host, c, 0);
 				return -EFAULT;
 			}
-                }
-                kfree(buff);
-		cmd_free(host, c, 0);
-                return(0);
-	} 
-	case CCISS_BIG_PASSTHRU: {
-		BIG_IOCTL_Command_struct *ioc;
-		CommandList_struct *c;
-		unsigned char **buff = NULL;
-		int	*buff_size = NULL;
-		u64bit	temp64;
-		unsigned long flags;
-		BYTE sg_used = 0;
-		int status = 0;
-		int i;
-		DECLARE_COMPLETION(wait);
-		__u32   left;
-		__u32	sz;
-		BYTE    __user *data_ptr;
 
-		if (!arg)
-			return -EINVAL;
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		ioc = (BIG_IOCTL_Command_struct *) 
-			kmalloc(sizeof(*ioc), GFP_KERNEL);
-		if (!ioc) {
-			status = -ENOMEM;
-			goto cleanup1;
+			if (iocommand.Request.Type.Direction == XFER_READ) {
+				/* Copy the data out of the buffer we created */
+				if (copy_to_user
+				    (iocommand.buf, buff, iocommand.buf_size)) {
+					kfree(buff);
+					cmd_free(host, c, 0);
+					return -EFAULT;
+				}
+			}
+			kfree(buff);
+			cmd_free(host, c, 0);
+			return 0;
 		}
-		if (copy_from_user(ioc, argp, sizeof(*ioc))) {
-			status = -EFAULT;
-			goto cleanup1;
-		}
-		if ((ioc->buf_size < 1) &&
-			(ioc->Request.Type.Direction != XFER_NONE)) {
-				status = -EINVAL;
-				goto cleanup1;
-		}
-		/* Check kmalloc limits  using all SGs */
-		if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
-			status = -EINVAL;
-			goto cleanup1;
-		}
-		if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
-			status = -EINVAL;
-			goto cleanup1;
-		}
-		buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
-		if (!buff) {
-			status = -ENOMEM;
-			goto cleanup1;
-		}
-		buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int), 
-					GFP_KERNEL);
-		if (!buff_size) {
-			status = -ENOMEM;
-			goto cleanup1;
-		}
-		left = ioc->buf_size;
-		data_ptr = ioc->buf;
-		while (left) {
-			sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
-			buff_size[sg_used] = sz;
-			buff[sg_used] = kmalloc(sz, GFP_KERNEL);
-			if (buff[sg_used] == NULL) {
+	case CCISS_BIG_PASSTHRU:{
+			BIG_IOCTL_Command_struct *ioc;
+			CommandList_struct *c;
+			unsigned char **buff = NULL;
+			int *buff_size = NULL;
+			u64bit temp64;
+			unsigned long flags;
+			BYTE sg_used = 0;
+			int status = 0;
+			int i;
+			DECLARE_COMPLETION(wait);
+			__u32 left;
+			__u32 sz;
+			BYTE __user *data_ptr;
+
+			if (!arg)
+				return -EINVAL;
+			if (!capable(CAP_SYS_RAWIO))
+				return -EPERM;
+			ioc = (BIG_IOCTL_Command_struct *)
+			    kmalloc(sizeof(*ioc), GFP_KERNEL);
+			if (!ioc) {
 				status = -ENOMEM;
 				goto cleanup1;
 			}
-			if (ioc->Request.Type.Direction == XFER_WRITE) {
-				if (copy_from_user(buff[sg_used], data_ptr, sz)) {
+			if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+				status = -EFAULT;
+				goto cleanup1;
+			}
+			if ((ioc->buf_size < 1) &&
+			    (ioc->Request.Type.Direction != XFER_NONE)) {
+				status = -EINVAL;
+				goto cleanup1;
+			}
+			/* Check kmalloc limits  using all SGs */
+			if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+				status = -EINVAL;
+				goto cleanup1;
+			}
+			if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+				status = -EINVAL;
+				goto cleanup1;
+			}
+			buff =
+			    kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+			if (!buff) {
+				status = -ENOMEM;
+				goto cleanup1;
+			}
+			buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int),
+						   GFP_KERNEL);
+			if (!buff_size) {
+				status = -ENOMEM;
+				goto cleanup1;
+			}
+			left = ioc->buf_size;
+			data_ptr = ioc->buf;
+			while (left) {
+				sz = (left >
+				      ioc->malloc_size) ? ioc->
+				    malloc_size : left;
+				buff_size[sg_used] = sz;
+				buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+				if (buff[sg_used] == NULL) {
 					status = -ENOMEM;
 					goto cleanup1;
 				}
-			} else {
-				memset(buff[sg_used], 0, sz);
-			}
-			left -= sz;
-			data_ptr += sz;
-			sg_used++;
-		}
-		if ((c = cmd_alloc(host , 0)) == NULL) {
-			status = -ENOMEM;
-			goto cleanup1;	
-		}
-		c->cmd_type = CMD_IOCTL_PEND;
-		c->Header.ReplyQueue = 0;
-		
-		if( ioc->buf_size > 0) {
-			c->Header.SGList = sg_used;
-			c->Header.SGTotal= sg_used;
-		} else { 
-			c->Header.SGList = 0;
-			c->Header.SGTotal= 0;
-		}
-		c->Header.LUN = ioc->LUN_info;
-		c->Header.Tag.lower = c->busaddr;
-		
-		c->Request = ioc->Request;
-		if (ioc->buf_size > 0 ) {
-			int i;
-			for(i=0; i<sg_used; i++) {
-				temp64.val = pci_map_single( host->pdev, buff[i],
-					buff_size[i],
-					PCI_DMA_BIDIRECTIONAL);
-				c->SG[i].Addr.lower = temp64.val32.lower;
-				c->SG[i].Addr.upper = temp64.val32.upper;
-				c->SG[i].Len = buff_size[i];
-				c->SG[i].Ext = 0;  /* we are not chaining */
-			}
-		}
-		c->waiting = &wait;
-		/* Put the request on the tail of the request queue */
-		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
-		addQ(&host->reqQ, c);
-		host->Qdepth++;
-		start_io(host);
-		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-		wait_for_completion(&wait);
-		/* unlock the buffers from DMA */
-		for(i=0; i<sg_used; i++) {
-			temp64.val32.lower = c->SG[i].Addr.lower;
-			temp64.val32.upper = c->SG[i].Addr.upper;
-			pci_unmap_single( host->pdev, (dma_addr_t) temp64.val,
-				buff_size[i], PCI_DMA_BIDIRECTIONAL);
-		}
-		/* Copy the error information out */
-		ioc->error_info = *(c->err_info);
-		if (copy_to_user(argp, ioc, sizeof(*ioc))) {
-			cmd_free(host, c, 0);
-			status = -EFAULT;
-			goto cleanup1;
-		}
-		if (ioc->Request.Type.Direction == XFER_READ) {
-			/* Copy the data out of the buffer we created */
-			BYTE __user *ptr = ioc->buf;
-	        	for(i=0; i< sg_used; i++) {
-				if (copy_to_user(ptr, buff[i], buff_size[i])) {
-					cmd_free(host, c, 0);
-					status = -EFAULT;
-					goto cleanup1;
+				if (ioc->Request.Type.Direction == XFER_WRITE) {
+					if (copy_from_user
+					    (buff[sg_used], data_ptr, sz)) {
+						status = -ENOMEM;
+						goto cleanup1;
+					}
+				} else {
+					memset(buff[sg_used], 0, sz);
 				}
-				ptr += buff_size[i];
+				left -= sz;
+				data_ptr += sz;
+				sg_used++;
 			}
+			if ((c = cmd_alloc(host, 0)) == NULL) {
+				status = -ENOMEM;
+				goto cleanup1;
+			}
+			c->cmd_type = CMD_IOCTL_PEND;
+			c->Header.ReplyQueue = 0;
+
+			if (ioc->buf_size > 0) {
+				c->Header.SGList = sg_used;
+				c->Header.SGTotal = sg_used;
+			} else {
+				c->Header.SGList = 0;
+				c->Header.SGTotal = 0;
+			}
+			c->Header.LUN = ioc->LUN_info;
+			c->Header.Tag.lower = c->busaddr;
+
+			c->Request = ioc->Request;
+			if (ioc->buf_size > 0) {
+				int i;
+				for (i = 0; i < sg_used; i++) {
+					temp64.val =
+					    pci_map_single(host->pdev, buff[i],
+						    buff_size[i],
+						    PCI_DMA_BIDIRECTIONAL);
+					c->SG[i].Addr.lower =
+					    temp64.val32.lower;
+					c->SG[i].Addr.upper =
+					    temp64.val32.upper;
+					c->SG[i].Len = buff_size[i];
+					c->SG[i].Ext = 0;	/* we are not chaining */
+				}
+			}
+			c->waiting = &wait;
+			/* Put the request on the tail of the request queue */
+			spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+			addQ(&host->reqQ, c);
+			host->Qdepth++;
+			start_io(host);
+			spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+			wait_for_completion(&wait);
+			/* unlock the buffers from DMA */
+			for (i = 0; i < sg_used; i++) {
+				temp64.val32.lower = c->SG[i].Addr.lower;
+				temp64.val32.upper = c->SG[i].Addr.upper;
+				pci_unmap_single(host->pdev,
+					(dma_addr_t) temp64.val, buff_size[i],
+					PCI_DMA_BIDIRECTIONAL);
+			}
+			/* Copy the error information out */
+			ioc->error_info = *(c->err_info);
+			if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+				cmd_free(host, c, 0);
+				status = -EFAULT;
+				goto cleanup1;
+			}
+			if (ioc->Request.Type.Direction == XFER_READ) {
+				/* Copy the data out of the buffer we created */
+				BYTE __user *ptr = ioc->buf;
+				for (i = 0; i < sg_used; i++) {
+					if (copy_to_user
+					    (ptr, buff[i], buff_size[i])) {
+						cmd_free(host, c, 0);
+						status = -EFAULT;
+						goto cleanup1;
+					}
+					ptr += buff_size[i];
+				}
+			}
+			cmd_free(host, c, 0);
+			status = 0;
+		      cleanup1:
+			if (buff) {
+				for (i = 0; i < sg_used; i++)
+					kfree(buff[i]);
+				kfree(buff);
+			}
+			kfree(buff_size);
+			kfree(ioc);
+			return status;
 		}
-		cmd_free(host, c, 0);
-		status = 0;
-cleanup1:
-		if (buff) {
-			for(i=0; i<sg_used; i++)
-				kfree(buff[i]);
-			kfree(buff);
-		}
-		kfree(buff_size);
-		kfree(ioc);
-		return(status);
-	}
 	default:
 		return -ENOTTY;
 	}
-	
 }
 
 /*
@@ -1119,7 +1159,7 @@
  *
  * Right now I'm using the getgeometry() function to do this, but this
  * function should probably be finer grained and allow you to revalidate one
- * particualar logical volume (instead of all of them on a particular
+ * particular logical volume (instead of all of them on a particular
  * controller).
  */
 static int revalidate_allvol(ctlr_info_t *host)
@@ -1127,17 +1167,17 @@
 	int ctlr = host->ctlr, i;
 	unsigned long flags;
 
-        spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
-        if (host->usage_count > 1) {
-                spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-                printk(KERN_WARNING "cciss: Device busy for volume"
-                        " revalidation (usage=%d)\n", host->usage_count);
-                return -EBUSY;
-        }
-        host->usage_count++;
+	spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+	if (host->usage_count > 1) {
+		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+		printk(KERN_WARNING "cciss: Device busy for volume"
+		       " revalidation (usage=%d)\n", host->usage_count);
+		return -EBUSY;
+	}
+	host->usage_count++;
 	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 
-	for(i=0; i< NWD; i++) {
+	for (i = 0; i < NWD; i++) {
 		struct gendisk *disk = host->gendisk[i];
 		if (disk) {
 			request_queue_t *q = disk->queue;
@@ -1149,22 +1189,22 @@
 		}
 	}
 
-        /*
-         * Set the partition and block size structures for all volumes
-         * on this controller to zero.  We will reread all of this data
-         */
-        memset(host->drv,        0, sizeof(drive_info_struct)
-						* CISS_MAX_LUN);
-        /*
-         * Tell the array controller not to give us any interrupts while
-         * we check the new geometry.  Then turn interrupts back on when
-         * we're done.
-         */
-        host->access.set_intr_mask(host, CCISS_INTR_OFF);
-        cciss_getgeometry(ctlr);
-        host->access.set_intr_mask(host, CCISS_INTR_ON);
+	/*
+	 * Set the partition and block size structures for all volumes
+	 * on this controller to zero.  We will reread all of this data
+	 */
+	memset(host->drv, 0, sizeof(drive_info_struct)
+	       * CISS_MAX_LUN);
+	/*
+	 * Tell the array controller not to give us any interrupts while
+	 * we check the new geometry.  Then turn interrupts back on when
+	 * we're done.
+	 */
+	host->access.set_intr_mask(host, CCISS_INTR_OFF);
+	cciss_getgeometry(ctlr);
+	host->access.set_intr_mask(host, CCISS_INTR_ON);
 
-	/* Loop through each real device */ 
+	/* Loop through each real device */
 	for (i = 0; i < NWD; i++) {
 		struct gendisk *disk = host->gendisk[i];
 		drive_info_struct *drv = &(host->drv[i]);
@@ -1176,8 +1216,8 @@
 		set_capacity(disk, drv->nr_blocks);
 		add_disk(disk);
 	}
-        host->usage_count--;
-        return 0;
+	host->usage_count--;
+	return 0;
 }
 
 static inline void complete_buffers(struct bio *bio, int status)
@@ -1191,7 +1231,6 @@
 		bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
 		bio = xbh;
 	}
-
 }
 
 static void cciss_softirq_done(struct request *rq)
@@ -1209,7 +1248,7 @@
 
 	/* command did not need to be retried */
 	/* unmap the DMA mapping for all the scatter gather elements */
-	for(i=0; i<cmd->Header.SGList; i++) {
+	for (i = 0; i < cmd->Header.SGList; i++) {
 		temp64.val32.lower = cmd->SG[i].Addr.lower;
 		temp64.val32.upper = cmd->SG[i].Addr.upper;
 		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
@@ -1219,11 +1258,12 @@
 
 #ifdef CCISS_DEBUG
 	printk("Done with %p\n", rq);
-#endif /* CCISS_DEBUG */
+#endif				/* CCISS_DEBUG */
 
+	add_disk_randomness(rq->rq_disk);
 	spin_lock_irqsave(&h->lock, flags);
 	end_that_request_last(rq, rq->errors);
-	cmd_free(h, cmd,1);
+	cmd_free(h, cmd, 1);
 	spin_unlock_irqrestore(&h->lock, flags);
 }
 
@@ -1234,9 +1274,9 @@
  * will always be left registered with the kernel since it is also the
  * controller node.  Any changes to disk 0 will show up on the next
  * reboot.
-*/
+ */
 static void cciss_update_drive_info(int ctlr, int drv_index)
-  {
+{
 	ctlr_info_t *h = hba[ctlr];
 	struct gendisk *disk;
 	ReadCapdata_struct *size_buff = NULL;
@@ -1246,13 +1286,13 @@
 	unsigned long flags = 0;
 	int ret = 0;
 
-	/* if the disk already exists then deregister it before proceeding*/
-	if (h->drv[drv_index].raid_level != -1){
+	/* if the disk already exists then deregister it before proceeding */
+	if (h->drv[drv_index].raid_level != -1) {
 		spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
 		h->drv[drv_index].busy_configuring = 1;
 		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 		ret = deregister_disk(h->gendisk[drv_index],
-			&h->drv[drv_index], 0);
+				      &h->drv[drv_index], 0);
 		h->drv[drv_index].busy_configuring = 0;
 	}
 
@@ -1260,27 +1300,25 @@
 	if (ret)
 		return;
 
-
-	/* Get information about the disk and modify the driver sturcture */
-	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
-        if (size_buff == NULL)
+	/* Get information about the disk and modify the driver structure */
+	size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+	if (size_buff == NULL)
 		goto mem_msg;
-	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+	inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
 	if (inq_buff == NULL)
 		goto mem_msg;
 
 	cciss_read_capacity(ctlr, drv_index, size_buff, 1,
-		&total_size, &block_size);
+			    &total_size, &block_size);
 	cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
-		inq_buff, &h->drv[drv_index]);
+			       inq_buff, &h->drv[drv_index]);
 
 	++h->num_luns;
 	disk = h->gendisk[drv_index];
 	set_capacity(disk, h->drv[drv_index].nr_blocks);
 
-
 	/* if it's the controller it's already added */
-	if (drv_index){
+	if (drv_index) {
 		disk->queue = blk_init_queue(do_cciss_request, &h->lock);
 
 		/* Set up queue information */
@@ -1300,17 +1338,17 @@
 		disk->queue->queuedata = hba[ctlr];
 
 		blk_queue_hardsect_size(disk->queue,
-			hba[ctlr]->drv[drv_index].block_size);
+					hba[ctlr]->drv[drv_index].block_size);
 
 		h->drv[drv_index].queue = disk->queue;
 		add_disk(disk);
 	}
 
-freeret:
+      freeret:
 	kfree(size_buff);
 	kfree(inq_buff);
 	return;
-mem_msg:
+      mem_msg:
 	printk(KERN_ERR "cciss: out of memory\n");
 	goto freeret;
 }
@@ -1320,13 +1358,13 @@
  * where new drives will be added.  If the index to be returned is greater
  * than the highest_lun index for the controller then highest_lun is set
  * to this new index.  If there are no available indexes then -1 is returned.
-*/
+ */
 static int cciss_find_free_drive_index(int ctlr)
 {
 	int i;
 
-	for (i=0; i < CISS_MAX_LUN; i++){
-		if (hba[ctlr]->drv[i].raid_level == -1){
+	for (i = 0; i < CISS_MAX_LUN; i++) {
+		if (hba[ctlr]->drv[i].raid_level == -1) {
 			if (i > hba[ctlr]->highest_lun)
 				hba[ctlr]->highest_lun = i;
 			return i;
@@ -1336,7 +1374,7 @@
 }
 
 /* This function will add and remove logical drives from the Logical
- * drive array of the controller and maintain persistancy of ordering
+ * drive array of the controller and maintain persistency of ordering
  * so that mount points are preserved until the next reboot.  This allows
  * for the removal of logical drives in the middle of the drive array
  * without a re-ordering of those drives.
@@ -1344,7 +1382,7 @@
  * h		= The controller to perform the operations on
  * del_disk	= The disk to remove if specified.  If the value given
  *		  is NULL then no disk is removed.
-*/
+ */
 static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
 {
 	int ctlr = h->ctlr;
@@ -1361,12 +1399,12 @@
 
 	/* Set busy_configuring flag for this operation */
 	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
-	if (h->num_luns >= CISS_MAX_LUN){
+	if (h->num_luns >= CISS_MAX_LUN) {
 		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 		return -EINVAL;
 	}
 
-	if (h->busy_configuring){
+	if (h->busy_configuring) {
 		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 		return -EBUSY;
 	}
@@ -1376,7 +1414,7 @@
 	 * and update the logical drive table.  If it is not NULL then
 	 * we will check if the disk is in use or not.
 	 */
-	if (del_disk != NULL){
+	if (del_disk != NULL) {
 		drv = get_drv(del_disk);
 		drv->busy_configuring = 1;
 		spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
@@ -1394,61 +1432,67 @@
 			goto mem_msg;
 
 		return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
-				sizeof(ReportLunData_struct), 0, 0, 0,
-				TYPE_CMD);
+					      sizeof(ReportLunData_struct), 0,
+					      0, 0, TYPE_CMD);
 
-		if (return_code == IO_OK){
-			listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
-			listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
-			listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
-			listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
-		} else{ /* reading number of logical volumes failed */
+		if (return_code == IO_OK) {
+			listlength |=
+			    (0xff & (unsigned int)(ld_buff->LUNListLength[0]))
+			    << 24;
+			listlength |=
+			    (0xff & (unsigned int)(ld_buff->LUNListLength[1]))
+			    << 16;
+			listlength |=
+			    (0xff & (unsigned int)(ld_buff->LUNListLength[2]))
+			    << 8;
+			listlength |=
+			    0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+		} else {	/* reading number of logical volumes failed */
 			printk(KERN_WARNING "cciss: report logical volume"
-				" command failed\n");
+			       " command failed\n");
 			listlength = 0;
 			goto freeret;
 		}
 
 		num_luns = listlength / 8;	/* 8 bytes per entry */
-		if (num_luns > CISS_MAX_LUN){
+		if (num_luns > CISS_MAX_LUN) {
 			num_luns = CISS_MAX_LUN;
 			printk(KERN_WARNING "cciss: more luns configured"
-				" on controller than can be handled by"
-				" this driver.\n");
+			       " on controller than can be handled by"
+			       " this driver.\n");
 		}
 
 		/* Compare controller drive array to drivers drive array.
-	 	* Check for updates in the drive information and any new drives
-	 	* on the controller.
-	 	*/
-		for (i=0; i < num_luns; i++){
+		 * Check for updates in the drive information and any new drives
+		 * on the controller.
+		 */
+		for (i = 0; i < num_luns; i++) {
 			int j;
 
 			drv_found = 0;
 
-	  		lunid = (0xff &
-				(unsigned int)(ld_buff->LUN[i][3])) << 24;
-        		lunid |= (0xff &
-				(unsigned int)(ld_buff->LUN[i][2])) << 16;
-        		lunid |= (0xff &
-				(unsigned int)(ld_buff->LUN[i][1])) << 8;
-        		lunid |= 0xff &
-				(unsigned int)(ld_buff->LUN[i][0]);
+			lunid = (0xff &
+				 (unsigned int)(ld_buff->LUN[i][3])) << 24;
+			lunid |= (0xff &
+				  (unsigned int)(ld_buff->LUN[i][2])) << 16;
+			lunid |= (0xff &
+				  (unsigned int)(ld_buff->LUN[i][1])) << 8;
+			lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
 
 			/* Find if the LUN is already in the drive array
 			 * of the controller.  If so then update its info
 			 * if not is use.  If it does not exist then find
 			 * the first free index and add it.
-			*/
-			for (j=0; j <= h->highest_lun; j++){
-				if (h->drv[j].LunID == lunid){
+			 */
+			for (j = 0; j <= h->highest_lun; j++) {
+				if (h->drv[j].LunID == lunid) {
 					drv_index = j;
 					drv_found = 1;
 				}
 			}
 
 			/* check if the drive was found already in the array */
-			if (!drv_found){
+			if (!drv_found) {
 				drv_index = cciss_find_free_drive_index(ctlr);
 				if (drv_index == -1)
 					goto freeret;
@@ -1456,18 +1500,18 @@
 			}
 			h->drv[drv_index].LunID = lunid;
 			cciss_update_drive_info(ctlr, drv_index);
-		} /* end for */
-	} /* end else */
+		}		/* end for */
+	}			/* end else */
 
-freeret:
+      freeret:
 	kfree(ld_buff);
 	h->busy_configuring = 0;
 	/* We return -1 here to tell the ACU that we have registered/updated
 	 * all of the drives that we can and to keep it from calling us
 	 * additional times.
-	*/
+	 */
 	return -1;
-mem_msg:
+      mem_msg:
 	printk(KERN_ERR "cciss: out of memory\n");
 	goto freeret;
 }
@@ -1483,7 +1527,7 @@
  * clear_all = This flag determines whether or not the disk information
  *             is going to be completely cleared out and the highest_lun
  *             reset.  Sometimes we want to clear out information about
- *             the disk in preperation for re-adding it.  In this case
+ *             the disk in preparation for re-adding it.  In this case
  *             the highest_lun should be left unchanged and the LunID
  *             should not be cleared.
 */
@@ -1496,19 +1540,17 @@
 		return -EPERM;
 
 	/* make sure logical volume is NOT is use */
-	if(clear_all || (h->gendisk[0] == disk)) {
-	if (drv->usage_count > 1)
-                return -EBUSY;
-	}
-        else
-        	if( drv->usage_count > 0 )
-                	return -EBUSY;
+	if (clear_all || (h->gendisk[0] == disk)) {
+		if (drv->usage_count > 1)
+			return -EBUSY;
+	} else if (drv->usage_count > 0)
+		return -EBUSY;
 
 	/* invalidate the devices and deregister the disk.  If it is disk
 	 * zero do not deregister it but just zero out it's values.  This
 	 * allows us to delete disk zero but keep the controller registered.
-	*/
-	if (h->gendisk[0] != disk){
+	 */
+	if (h->gendisk[0] != disk) {
 		if (disk) {
 			request_queue_t *q = disk->queue;
 			if (disk->flags & GENHD_FL_UP)
@@ -1530,91 +1572,90 @@
 	drv->raid_level = -1;	/* This can be used as a flag variable to
 				 * indicate that this element of the drive
 				 * array is free.
-				*/
+				 */
 
-	if (clear_all){
-	/* check to see if it was the last disk */
-	if (drv == h->drv + h->highest_lun) {
-		/* if so, find the new hightest lun */
-		int i, newhighest =-1;
-		for(i=0; i<h->highest_lun; i++) {
-			/* if the disk has size > 0, it is available */
+	if (clear_all) {
+		/* check to see if it was the last disk */
+		if (drv == h->drv + h->highest_lun) {
+			/* if so, find the new hightest lun */
+			int i, newhighest = -1;
+			for (i = 0; i < h->highest_lun; i++) {
+				/* if the disk has size > 0, it is available */
 				if (h->drv[i].heads)
-				newhighest = i;
+					newhighest = i;
+			}
+			h->highest_lun = newhighest;
 		}
-		h->highest_lun = newhighest;
-	}
 
-	drv->LunID = 0;
+		drv->LunID = 0;
 	}
-	return(0);
+	return 0;
 }
 
-static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
-	size_t size,
-	unsigned int use_unit_num, /* 0: address the controller,
-				      1: address logical volume log_unit,
-				      2: periph device address is scsi3addr */
-	unsigned int log_unit, __u8 page_code, unsigned char *scsi3addr,
-	int cmd_type)
+static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num,	/* 0: address the controller,
+															   1: address logical volume log_unit,
+															   2: periph device address is scsi3addr */
+		    unsigned int log_unit, __u8 page_code,
+		    unsigned char *scsi3addr, int cmd_type)
 {
-	ctlr_info_t *h= hba[ctlr];
+	ctlr_info_t *h = hba[ctlr];
 	u64bit buff_dma_handle;
 	int status = IO_OK;
 
 	c->cmd_type = CMD_IOCTL_PEND;
 	c->Header.ReplyQueue = 0;
-	if( buff != NULL) {
+	if (buff != NULL) {
 		c->Header.SGList = 1;
-		c->Header.SGTotal= 1;
+		c->Header.SGTotal = 1;
 	} else {
 		c->Header.SGList = 0;
-                c->Header.SGTotal= 0;
+		c->Header.SGTotal = 0;
 	}
 	c->Header.Tag.lower = c->busaddr;
 
 	c->Request.Type.Type = cmd_type;
 	if (cmd_type == TYPE_CMD) {
-		switch(cmd) {
-		case  CISS_INQUIRY:
+		switch (cmd) {
+		case CISS_INQUIRY:
 			/* If the logical unit number is 0 then, this is going
-			to controller so It's a physical command
-			mode = 0 target = 0.  So we have nothing to write.
-			otherwise, if use_unit_num == 1,
-			mode = 1(volume set addressing) target = LUNID
-			otherwise, if use_unit_num == 2,
-			mode = 0(periph dev addr) target = scsi3addr */
+			   to controller so It's a physical command
+			   mode = 0 target = 0.  So we have nothing to write.
+			   otherwise, if use_unit_num == 1,
+			   mode = 1(volume set addressing) target = LUNID
+			   otherwise, if use_unit_num == 2,
+			   mode = 0(periph dev addr) target = scsi3addr */
 			if (use_unit_num == 1) {
-				c->Header.LUN.LogDev.VolId=
-					h->drv[log_unit].LunID;
-                        	c->Header.LUN.LogDev.Mode = 1;
+				c->Header.LUN.LogDev.VolId =
+				    h->drv[log_unit].LunID;
+				c->Header.LUN.LogDev.Mode = 1;
 			} else if (use_unit_num == 2) {
-				memcpy(c->Header.LUN.LunAddrBytes,scsi3addr,8);
+				memcpy(c->Header.LUN.LunAddrBytes, scsi3addr,
+				       8);
 				c->Header.LUN.LogDev.Mode = 0;
 			}
 			/* are we trying to read a vital product page */
-			if(page_code != 0) {
+			if (page_code != 0) {
 				c->Request.CDB[1] = 0x01;
 				c->Request.CDB[2] = page_code;
 			}
 			c->Request.CDBLen = 6;
-			c->Request.Type.Attribute = ATTR_SIMPLE;  
+			c->Request.Type.Attribute = ATTR_SIMPLE;
 			c->Request.Type.Direction = XFER_READ;
 			c->Request.Timeout = 0;
-			c->Request.CDB[0] =  CISS_INQUIRY;
-			c->Request.CDB[4] = size  & 0xFF;  
-		break;
+			c->Request.CDB[0] = CISS_INQUIRY;
+			c->Request.CDB[4] = size & 0xFF;
+			break;
 		case CISS_REPORT_LOG:
 		case CISS_REPORT_PHYS:
-                        /* Talking to controller so It's a physical command
+			/* Talking to controller so It's a physical command
 			   mode = 00 target = 0.  Nothing to write.
-                        */
+			 */
 			c->Request.CDBLen = 12;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
 			c->Request.Type.Direction = XFER_READ;
 			c->Request.Timeout = 0;
 			c->Request.CDB[0] = cmd;
-			c->Request.CDB[6] = (size >> 24) & 0xFF;  //MSB
+			c->Request.CDB[6] = (size >> 24) & 0xFF;	//MSB
 			c->Request.CDB[7] = (size >> 16) & 0xFF;
 			c->Request.CDB[8] = (size >> 8) & 0xFF;
 			c->Request.CDB[9] = size & 0xFF;
@@ -1628,7 +1669,7 @@
 			c->Request.Type.Direction = XFER_READ;
 			c->Request.Timeout = 0;
 			c->Request.CDB[0] = cmd;
-		break;
+			break;
 		case CCISS_CACHE_FLUSH:
 			c->Request.CDBLen = 12;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1636,32 +1677,32 @@
 			c->Request.Timeout = 0;
 			c->Request.CDB[0] = BMIC_WRITE;
 			c->Request.CDB[6] = BMIC_CACHE_FLUSH;
-		break;
+			break;
 		default:
 			printk(KERN_WARNING
-				"cciss%d:  Unknown Command 0x%c\n", ctlr, cmd);
-			return(IO_ERROR);
+			       "cciss%d:  Unknown Command 0x%c\n", ctlr, cmd);
+			return IO_ERROR;
 		}
 	} else if (cmd_type == TYPE_MSG) {
 		switch (cmd) {
-		case 0: /* ABORT message */
+		case 0:	/* ABORT message */
 			c->Request.CDBLen = 12;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
 			c->Request.Type.Direction = XFER_WRITE;
 			c->Request.Timeout = 0;
-			c->Request.CDB[0] = cmd; /* abort */
-			c->Request.CDB[1] = 0;   /* abort a command */
+			c->Request.CDB[0] = cmd;	/* abort */
+			c->Request.CDB[1] = 0;	/* abort a command */
 			/* buff contains the tag of the command to abort */
 			memcpy(&c->Request.CDB[4], buff, 8);
 			break;
-		case 1: /* RESET message */
+		case 1:	/* RESET message */
 			c->Request.CDBLen = 12;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
 			c->Request.Type.Direction = XFER_WRITE;
 			c->Request.Timeout = 0;
 			memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
-			c->Request.CDB[0] = cmd;  /* reset */
-			c->Request.CDB[1] = 0x04; /* reset a LUN */
+			c->Request.CDB[0] = cmd;	/* reset */
+			c->Request.CDB[1] = 0x04;	/* reset a LUN */
 		case 3:	/* No-Op message */
 			c->Request.CDBLen = 1;
 			c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1671,168 +1712,164 @@
 			break;
 		default:
 			printk(KERN_WARNING
-				"cciss%d: unknown message type %d\n",
-				ctlr, cmd);
+			       "cciss%d: unknown message type %d\n", ctlr, cmd);
 			return IO_ERROR;
 		}
 	} else {
 		printk(KERN_WARNING
-			"cciss%d: unknown command type %d\n", ctlr, cmd_type);
+		       "cciss%d: unknown command type %d\n", ctlr, cmd_type);
 		return IO_ERROR;
 	}
 	/* Fill in the scatter gather information */
 	if (size > 0) {
 		buff_dma_handle.val = (__u64) pci_map_single(h->pdev,
-			buff, size, PCI_DMA_BIDIRECTIONAL);
+							     buff, size,
+							     PCI_DMA_BIDIRECTIONAL);
 		c->SG[0].Addr.lower = buff_dma_handle.val32.lower;
 		c->SG[0].Addr.upper = buff_dma_handle.val32.upper;
 		c->SG[0].Len = size;
-		c->SG[0].Ext = 0;  /* we are not chaining */
+		c->SG[0].Ext = 0;	/* we are not chaining */
 	}
 	return status;
 }
-static int sendcmd_withirq(__u8	cmd,
-	int	ctlr,
-	void	*buff,
-	size_t	size,
-	unsigned int use_unit_num,
-	unsigned int log_unit,
-	__u8	page_code,
-	int cmd_type)
+
+static int sendcmd_withirq(__u8 cmd,
+			   int ctlr,
+			   void *buff,
+			   size_t size,
+			   unsigned int use_unit_num,
+			   unsigned int log_unit, __u8 page_code, int cmd_type)
 {
 	ctlr_info_t *h = hba[ctlr];
 	CommandList_struct *c;
-	u64bit	buff_dma_handle;
+	u64bit buff_dma_handle;
 	unsigned long flags;
 	int return_status;
 	DECLARE_COMPLETION(wait);
-	
-	if ((c = cmd_alloc(h , 0)) == NULL)
+
+	if ((c = cmd_alloc(h, 0)) == NULL)
 		return -ENOMEM;
 	return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
-		log_unit, page_code, NULL, cmd_type);
+				 log_unit, page_code, NULL, cmd_type);
 	if (return_status != IO_OK) {
 		cmd_free(h, c, 0);
 		return return_status;
 	}
-resend_cmd2:
+      resend_cmd2:
 	c->waiting = &wait;
-	
+
 	/* Put the request on the tail of the queue and send it */
 	spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 	addQ(&h->reqQ, c);
 	h->Qdepth++;
 	start_io(h);
 	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-	
+
 	wait_for_completion(&wait);
 
-	if(c->err_info->CommandStatus != 0) 
-	{ /* an error has occurred */ 
-		switch(c->err_info->CommandStatus)
-		{
-			case CMD_TARGET_STATUS:
-				printk(KERN_WARNING "cciss: cmd %p has "
-					" completed with errors\n", c);
-				if( c->err_info->ScsiStatus)
-                		{
-                    			printk(KERN_WARNING "cciss: cmd %p "
-					"has SCSI Status = %x\n",
-                        			c,  
-						c->err_info->ScsiStatus);
-                		}
+	if (c->err_info->CommandStatus != 0) {	/* an error has occurred */
+		switch (c->err_info->CommandStatus) {
+		case CMD_TARGET_STATUS:
+			printk(KERN_WARNING "cciss: cmd %p has "
+			       " completed with errors\n", c);
+			if (c->err_info->ScsiStatus) {
+				printk(KERN_WARNING "cciss: cmd %p "
+				       "has SCSI Status = %x\n",
+				       c, c->err_info->ScsiStatus);
+			}
 
 			break;
-			case CMD_DATA_UNDERRUN:
-			case CMD_DATA_OVERRUN:
+		case CMD_DATA_UNDERRUN:
+		case CMD_DATA_OVERRUN:
 			/* expected for inquire and report lun commands */
 			break;
-			case CMD_INVALID:
-				printk(KERN_WARNING "cciss: Cmd %p is "
-					"reported invalid\n", c);
-				return_status = IO_ERROR;
+		case CMD_INVALID:
+			printk(KERN_WARNING "cciss: Cmd %p is "
+			       "reported invalid\n", c);
+			return_status = IO_ERROR;
 			break;
-			case CMD_PROTOCOL_ERR:
-                                printk(KERN_WARNING "cciss: cmd %p has "
-					"protocol error \n", c);
-                                return_status = IO_ERROR;
-                        break;
-case CMD_HARDWARE_ERR:
-                                printk(KERN_WARNING "cciss: cmd %p had " 
-                                        " hardware error\n", c);
-                                return_status = IO_ERROR;
-                        break;
-			case CMD_CONNECTION_LOST:
-				printk(KERN_WARNING "cciss: cmd %p had "
-					"connection lost\n", c);
-				return_status = IO_ERROR;
+		case CMD_PROTOCOL_ERR:
+			printk(KERN_WARNING "cciss: cmd %p has "
+			       "protocol error \n", c);
+			return_status = IO_ERROR;
 			break;
-			case CMD_ABORTED:
-				printk(KERN_WARNING "cciss: cmd %p was "
-					"aborted\n", c);
-				return_status = IO_ERROR;
+		case CMD_HARDWARE_ERR:
+			printk(KERN_WARNING "cciss: cmd %p had "
+			       " hardware error\n", c);
+			return_status = IO_ERROR;
 			break;
-			case CMD_ABORT_FAILED:
-				printk(KERN_WARNING "cciss: cmd %p reports "
-					"abort failed\n", c);
-				return_status = IO_ERROR;
+		case CMD_CONNECTION_LOST:
+			printk(KERN_WARNING "cciss: cmd %p had "
+			       "connection lost\n", c);
+			return_status = IO_ERROR;
 			break;
-			case CMD_UNSOLICITED_ABORT:
-				printk(KERN_WARNING 
-					"cciss%d: unsolicited abort %p\n",
-					ctlr, c);
-				if (c->retry_count < MAX_CMD_RETRIES) {
-					printk(KERN_WARNING 
-						"cciss%d: retrying %p\n", 
-						ctlr, c);
-					c->retry_count++;
-					/* erase the old error information */
-					memset(c->err_info, 0,
-						sizeof(ErrorInfo_struct));
-					return_status = IO_OK;
-					INIT_COMPLETION(wait);
-					goto resend_cmd2;
-				}
-				return_status = IO_ERROR;
+		case CMD_ABORTED:
+			printk(KERN_WARNING "cciss: cmd %p was "
+			       "aborted\n", c);
+			return_status = IO_ERROR;
 			break;
-			default:
-				printk(KERN_WARNING "cciss: cmd %p returned "
-					"unknown status %x\n", c, 
-						c->err_info->CommandStatus); 
-				return_status = IO_ERROR;
+		case CMD_ABORT_FAILED:
+			printk(KERN_WARNING "cciss: cmd %p reports "
+			       "abort failed\n", c);
+			return_status = IO_ERROR;
+			break;
+		case CMD_UNSOLICITED_ABORT:
+			printk(KERN_WARNING
+			       "cciss%d: unsolicited abort %p\n", ctlr, c);
+			if (c->retry_count < MAX_CMD_RETRIES) {
+				printk(KERN_WARNING
+				       "cciss%d: retrying %p\n", ctlr, c);
+				c->retry_count++;
+				/* erase the old error information */
+				memset(c->err_info, 0,
+				       sizeof(ErrorInfo_struct));
+				return_status = IO_OK;
+				INIT_COMPLETION(wait);
+				goto resend_cmd2;
+			}
+			return_status = IO_ERROR;
+			break;
+		default:
+			printk(KERN_WARNING "cciss: cmd %p returned "
+			       "unknown status %x\n", c,
+			       c->err_info->CommandStatus);
+			return_status = IO_ERROR;
 		}
-	}	
+	}
 	/* unlock the buffers from DMA */
 	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
 	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
-	pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val,
-			c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
+	pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
+			 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
 	cmd_free(h, c, 0);
-        return(return_status);
-
+	return return_status;
 }
+
 static void cciss_geometry_inquiry(int ctlr, int logvol,
-			int withirq, unsigned int total_size,
-			unsigned int block_size, InquiryData_struct *inq_buff,
-			drive_info_struct *drv)
+				   int withirq, unsigned int total_size,
+				   unsigned int block_size,
+				   InquiryData_struct *inq_buff,
+				   drive_info_struct *drv)
 {
 	int return_code;
 	memset(inq_buff, 0, sizeof(InquiryData_struct));
 	if (withirq)
 		return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
-			inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1, TYPE_CMD);
+					      inq_buff, sizeof(*inq_buff), 1,
+					      logvol, 0xC1, TYPE_CMD);
 	else
 		return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
-			sizeof(*inq_buff), 1, logvol ,0xC1, NULL, TYPE_CMD);
+				      sizeof(*inq_buff), 1, logvol, 0xC1, NULL,
+				      TYPE_CMD);
 	if (return_code == IO_OK) {
-		if(inq_buff->data_byte[8] == 0xFF) {
+		if (inq_buff->data_byte[8] == 0xFF) {
 			printk(KERN_WARNING
-				"cciss: reading geometry failed, volume "
-				"does not support reading geometry\n");
+			       "cciss: reading geometry failed, volume "
+			       "does not support reading geometry\n");
 			drv->block_size = block_size;
 			drv->nr_blocks = total_size;
 			drv->heads = 255;
-			drv->sectors = 32; // Sectors per track
+			drv->sectors = 32;	// Sectors per track
 			drv->cylinders = total_size / 255 / 32;
 		} else {
 			unsigned int t;
@@ -1846,37 +1883,42 @@
 			drv->raid_level = inq_buff->data_byte[8];
 			t = drv->heads * drv->sectors;
 			if (t > 1) {
-				drv->cylinders = total_size/t;
+				drv->cylinders = total_size / t;
 			}
 		}
-	} else { /* Get geometry failed */
+	} else {		/* Get geometry failed */
 		printk(KERN_WARNING "cciss: reading geometry failed\n");
 	}
 	printk(KERN_INFO "      heads= %d, sectors= %d, cylinders= %d\n\n",
-		drv->heads, drv->sectors, drv->cylinders);
+	       drv->heads, drv->sectors, drv->cylinders);
 }
+
 static void
 cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
-		int withirq, unsigned int *total_size, unsigned int *block_size)
+		    int withirq, unsigned int *total_size,
+		    unsigned int *block_size)
 {
 	int return_code;
 	memset(buf, 0, sizeof(*buf));
 	if (withirq)
 		return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
-			ctlr, buf, sizeof(*buf), 1, logvol, 0, TYPE_CMD);
+					      ctlr, buf, sizeof(*buf), 1,
+					      logvol, 0, TYPE_CMD);
 	else
 		return_code = sendcmd(CCISS_READ_CAPACITY,
-			ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD);
+				      ctlr, buf, sizeof(*buf), 1, logvol, 0,
+				      NULL, TYPE_CMD);
 	if (return_code == IO_OK) {
-		*total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1;
-		*block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0]));
-	} else { /* read capacity command failed */
+		*total_size =
+		    be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1;
+		*block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0]));
+	} else {		/* read capacity command failed */
 		printk(KERN_WARNING "cciss: read capacity failed\n");
 		*total_size = 0;
 		*block_size = BLOCK_SIZE;
 	}
 	printk(KERN_INFO "      blocks= %u block_size= %d\n",
-		*total_size, *block_size);
+	       *total_size, *block_size);
 	return;
 }
 
@@ -1885,38 +1927,38 @@
 	ctlr_info_t *h = get_host(disk);
 	drive_info_struct *drv = get_drv(disk);
 	int logvol;
-	int FOUND=0;
+	int FOUND = 0;
 	unsigned int block_size;
 	unsigned int total_size;
 	ReadCapdata_struct *size_buff = NULL;
 	InquiryData_struct *inq_buff = NULL;
 
-	for(logvol=0; logvol < CISS_MAX_LUN; logvol++)
-	{
-		if(h->drv[logvol].LunID == drv->LunID) {
-			FOUND=1;
+	for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
+		if (h->drv[logvol].LunID == drv->LunID) {
+			FOUND = 1;
 			break;
 		}
 	}
 
-	if (!FOUND) return 1;
+	if (!FOUND)
+		return 1;
 
-	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
-        if (size_buff == NULL)
-        {
-                printk(KERN_WARNING "cciss: out of memory\n");
-                return 1;
-        }
-	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
-        if (inq_buff == NULL)
-        {
-                printk(KERN_WARNING "cciss: out of memory\n");
+	size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+	if (size_buff == NULL) {
+		printk(KERN_WARNING "cciss: out of memory\n");
+		return 1;
+	}
+	inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+	if (inq_buff == NULL) {
+		printk(KERN_WARNING "cciss: out of memory\n");
 		kfree(size_buff);
-                return 1;
-        }
+		return 1;
+	}
 
-	cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, &block_size);
-	cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, inq_buff, drv);
+	cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size,
+			    &block_size);
+	cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
+			       inq_buff, drv);
 
 	blk_queue_hardsect_size(drv->queue, drv->block_size);
 	set_capacity(disk, drv->nr_blocks);
@@ -1943,7 +1985,7 @@
 		if (done == FIFO_EMPTY)
 			schedule_timeout_uninterruptible(1);
 		else
-			return (done);
+			return done;
 	}
 	/* Invalid address to tell caller we ran out of time */
 	return 1;
@@ -1952,28 +1994,28 @@
 static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
 {
 	/* We get in here if sendcmd() is polling for completions
-	   and gets some command back that it wasn't expecting -- 
-	   something other than that which it just sent down.  
-	   Ordinarily, that shouldn't happen, but it can happen when 
+	   and gets some command back that it wasn't expecting --
+	   something other than that which it just sent down.
+	   Ordinarily, that shouldn't happen, but it can happen when
 	   the scsi tape stuff gets into error handling mode, and
-	   starts using sendcmd() to try to abort commands and 
+	   starts using sendcmd() to try to abort commands and
 	   reset tape drives.  In that case, sendcmd may pick up
 	   completions of commands that were sent to logical drives
-	   through the block i/o system, or cciss ioctls completing, etc. 
+	   through the block i/o system, or cciss ioctls completing, etc.
 	   In that case, we need to save those completions for later
 	   processing by the interrupt handler.
-	*/
+	 */
 
 #ifdef CONFIG_CISS_SCSI_TAPE
-	struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects;	
+	struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects;
 
 	/* If it's not the scsi tape stuff doing error handling, (abort */
 	/* or reset) then we don't expect anything weird. */
 	if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) {
 #endif
-		printk( KERN_WARNING "cciss cciss%d: SendCmd "
-		      "Invalid command list address returned! (%lx)\n",
-			ctlr, complete);
+		printk(KERN_WARNING "cciss cciss%d: SendCmd "
+		       "Invalid command list address returned! (%lx)\n",
+		       ctlr, complete);
 		/* not much we can do. */
 #ifdef CONFIG_CISS_SCSI_TAPE
 		return 1;
@@ -1984,7 +2026,7 @@
 	if (srl->ncompletions >= (NR_CMDS + 2)) {
 		/* Uh oh.  No room to save it for later... */
 		printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, "
-			"reject list overflow, command lost!\n", ctlr);
+		       "reject list overflow, command lost!\n", ctlr);
 		return 1;
 	}
 	/* Save it for later */
@@ -1995,340 +2037,327 @@
 }
 
 /*
- * Send a command to the controller, and wait for it to complete.  
- * Only used at init time. 
+ * Send a command to the controller, and wait for it to complete.
+ * Only used at init time.
  */
-static int sendcmd(
-	__u8	cmd,
-	int	ctlr,
-	void	*buff,
-	size_t	size,
-	unsigned int use_unit_num, /* 0: address the controller,
-				      1: address logical volume log_unit, 
-				      2: periph device address is scsi3addr */
-	unsigned int log_unit,
-	__u8	page_code,
-	unsigned char *scsi3addr,
-	int cmd_type)
+static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num,	/* 0: address the controller,
+												   1: address logical volume log_unit,
+												   2: periph device address is scsi3addr */
+		   unsigned int log_unit,
+		   __u8 page_code, unsigned char *scsi3addr, int cmd_type)
 {
 	CommandList_struct *c;
 	int i;
 	unsigned long complete;
-	ctlr_info_t *info_p= hba[ctlr];
+	ctlr_info_t *info_p = hba[ctlr];
 	u64bit buff_dma_handle;
 	int status, done = 0;
 
 	if ((c = cmd_alloc(info_p, 1)) == NULL) {
 		printk(KERN_WARNING "cciss: unable to get memory");
-		return(IO_ERROR);
+		return IO_ERROR;
 	}
 	status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
-		log_unit, page_code, scsi3addr, cmd_type);
+			  log_unit, page_code, scsi3addr, cmd_type);
 	if (status != IO_OK) {
 		cmd_free(info_p, c, 1);
 		return status;
 	}
-resend_cmd1:
+      resend_cmd1:
 	/*
-         * Disable interrupt
-         */
+	 * Disable interrupt
+	 */
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss: turning intr off\n");
-#endif /* CCISS_DEBUG */ 
-        info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);
-	
+#endif				/* CCISS_DEBUG */
+	info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);
+
 	/* Make sure there is room in the command FIFO */
-        /* Actually it should be completely empty at this time */
+	/* Actually it should be completely empty at this time */
 	/* unless we are in here doing error handling for the scsi */
 	/* tape side of the driver. */
-        for (i = 200000; i > 0; i--) 
-	{
+	for (i = 200000; i > 0; i--) {
 		/* if fifo isn't full go */
-                if (!(info_p->access.fifo_full(info_p))) 
-		{
-			
-                        break;
-                }
-                udelay(10);
-                printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
-                        " waiting!\n", ctlr);
-        }
-        /*
-         * Send the cmd
-         */
-        info_p->access.submit_command(info_p, c);
+		if (!(info_p->access.fifo_full(info_p))) {
+
+			break;
+		}
+		udelay(10);
+		printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
+		       " waiting!\n", ctlr);
+	}
+	/*
+	 * Send the cmd
+	 */
+	info_p->access.submit_command(info_p, c);
 	done = 0;
 	do {
 		complete = pollcomplete(ctlr);
 
 #ifdef CCISS_DEBUG
 		printk(KERN_DEBUG "cciss: command completed\n");
-#endif /* CCISS_DEBUG */
+#endif				/* CCISS_DEBUG */
 
 		if (complete == 1) {
-			printk( KERN_WARNING
-				"cciss cciss%d: SendCmd Timeout out, "
-				"No command list address returned!\n",
-				ctlr);
+			printk(KERN_WARNING
+			       "cciss cciss%d: SendCmd Timeout out, "
+			       "No command list address returned!\n", ctlr);
 			status = IO_ERROR;
 			done = 1;
 			break;
 		}
 
 		/* This will need to change for direct lookup completions */
-		if ( (complete & CISS_ERROR_BIT)
-		     && (complete & ~CISS_ERROR_BIT) == c->busaddr)
-		     {
-			/* if data overrun or underun on Report command 
-				ignore it 
-			*/
+		if ((complete & CISS_ERROR_BIT)
+		    && (complete & ~CISS_ERROR_BIT) == c->busaddr) {
+			/* if data overrun or underun on Report command
+			   ignore it
+			 */
 			if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||
 			     (c->Request.CDB[0] == CISS_REPORT_PHYS) ||
 			     (c->Request.CDB[0] == CISS_INQUIRY)) &&
-				((c->err_info->CommandStatus == 
-					CMD_DATA_OVERRUN) || 
-				 (c->err_info->CommandStatus == 
-					CMD_DATA_UNDERRUN)
-			 	))
-			{
+			    ((c->err_info->CommandStatus ==
+			      CMD_DATA_OVERRUN) ||
+			     (c->err_info->CommandStatus == CMD_DATA_UNDERRUN)
+			    )) {
 				complete = c->busaddr;
 			} else {
 				if (c->err_info->CommandStatus ==
-						CMD_UNSOLICITED_ABORT) {
+				    CMD_UNSOLICITED_ABORT) {
 					printk(KERN_WARNING "cciss%d: "
-						"unsolicited abort %p\n",
-						ctlr, c);
+					       "unsolicited abort %p\n",
+					       ctlr, c);
 					if (c->retry_count < MAX_CMD_RETRIES) {
 						printk(KERN_WARNING
-						   "cciss%d: retrying %p\n",
-						   ctlr, c);
+						       "cciss%d: retrying %p\n",
+						       ctlr, c);
 						c->retry_count++;
 						/* erase the old error */
 						/* information */
 						memset(c->err_info, 0,
-						   sizeof(ErrorInfo_struct));
+						       sizeof
+						       (ErrorInfo_struct));
 						goto resend_cmd1;
 					} else {
 						printk(KERN_WARNING
-						   "cciss%d: retried %p too "
-						   "many times\n", ctlr, c);
+						       "cciss%d: retried %p too "
+						       "many times\n", ctlr, c);
 						status = IO_ERROR;
 						goto cleanup1;
 					}
-				} else if (c->err_info->CommandStatus == CMD_UNABORTABLE) {
-					printk(KERN_WARNING "cciss%d: command could not be aborted.\n", ctlr);
+				} else if (c->err_info->CommandStatus ==
+					   CMD_UNABORTABLE) {
+					printk(KERN_WARNING
+					       "cciss%d: command could not be aborted.\n",
+					       ctlr);
 					status = IO_ERROR;
 					goto cleanup1;
 				}
 				printk(KERN_WARNING "ciss ciss%d: sendcmd"
-				" Error %x \n", ctlr, 
-					c->err_info->CommandStatus); 
+				       " Error %x \n", ctlr,
+				       c->err_info->CommandStatus);
 				printk(KERN_WARNING "ciss ciss%d: sendcmd"
-				" offensive info\n"
-				"  size %x\n   num %x   value %x\n", ctlr,
-				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_size,
-				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_num,
-				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
+				       " offensive info\n"
+				       "  size %x\n   num %x   value %x\n",
+				       ctlr,
+				       c->err_info->MoreErrInfo.Invalid_Cmd.
+				       offense_size,
+				       c->err_info->MoreErrInfo.Invalid_Cmd.
+				       offense_num,
+				       c->err_info->MoreErrInfo.Invalid_Cmd.
+				       offense_value);
 				status = IO_ERROR;
 				goto cleanup1;
 			}
 		}
 		/* This will need changing for direct lookup completions */
-                if (complete != c->busaddr) {
+		if (complete != c->busaddr) {
 			if (add_sendcmd_reject(cmd, ctlr, complete) != 0) {
-				BUG(); /* we are pretty much hosed if we get here. */
+				BUG();	/* we are pretty much hosed if we get here. */
 			}
 			continue;
-                } else
+		} else
 			done = 1;
-        } while (!done);
-		
-cleanup1:	
+	} while (!done);
+
+      cleanup1:
 	/* unlock the data buffer from DMA */
 	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
 	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
 	pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
-				c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
+			 c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
 #ifdef CONFIG_CISS_SCSI_TAPE
 	/* if we saved some commands for later, process them now. */
 	if (info_p->scsi_rejects.ncompletions > 0)
 		do_cciss_intr(0, info_p, NULL);
 #endif
 	cmd_free(info_p, c, 1);
-	return (status);
-} 
+	return status;
+}
+
 /*
  * Map (physical) PCI mem into (virtual) kernel space
  */
 static void __iomem *remap_pci_mem(ulong base, ulong size)
 {
-        ulong page_base        = ((ulong) base) & PAGE_MASK;
-        ulong page_offs        = ((ulong) base) - page_base;
-        void __iomem *page_remapped = ioremap(page_base, page_offs+size);
+	ulong page_base = ((ulong) base) & PAGE_MASK;
+	ulong page_offs = ((ulong) base) - page_base;
+	void __iomem *page_remapped = ioremap(page_base, page_offs + size);
 
-        return page_remapped ? (page_remapped + page_offs) : NULL;
+	return page_remapped ? (page_remapped + page_offs) : NULL;
 }
 
-/* 
- * Takes jobs of the Q and sends them to the hardware, then puts it on 
- * the Q to wait for completion. 
- */ 
-static void start_io( ctlr_info_t *h)
+/*
+ * Takes jobs of the Q and sends them to the hardware, then puts it on
+ * the Q to wait for completion.
+ */
+static void start_io(ctlr_info_t *h)
 {
 	CommandList_struct *c;
-	
-	while(( c = h->reqQ) != NULL )
-	{
+
+	while ((c = h->reqQ) != NULL) {
 		/* can't do anything if fifo is full */
 		if ((h->access.fifo_full(h))) {
 			printk(KERN_WARNING "cciss: fifo full\n");
 			break;
 		}
 
-		/* Get the first entry from the Request Q */ 
+		/* Get the first entry from the Request Q */
 		removeQ(&(h->reqQ), c);
 		h->Qdepth--;
-	
-		/* Tell the controller execute command */ 
+
+		/* Tell the controller execute command */
 		h->access.submit_command(h, c);
-		
-		/* Put job onto the completed Q */ 
-		addQ (&(h->cmpQ), c); 
+
+		/* Put job onto the completed Q */
+		addQ(&(h->cmpQ), c);
 	}
 }
+
 /* Assumes that CCISS_LOCK(h->ctlr) is held. */
 /* Zeros out the error record and then resends the command back */
 /* to the controller */
-static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
+static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
 {
 	/* erase the old error information */
 	memset(c->err_info, 0, sizeof(ErrorInfo_struct));
 
 	/* add it to software queue and then send it to the controller */
-	addQ(&(h->reqQ),c);
+	addQ(&(h->reqQ), c);
 	h->Qdepth++;
-	if(h->Qdepth > h->maxQsinceinit)
+	if (h->Qdepth > h->maxQsinceinit)
 		h->maxQsinceinit = h->Qdepth;
 
 	start_io(h);
 }
 
-/* checks the status of the job and calls complete buffers to mark all 
+/* checks the status of the job and calls complete buffers to mark all
  * buffers for the completed job. Note that this function does not need
  * to hold the hba/queue lock.
- */ 
-static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
-		int timeout)
+ */
+static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
+				    int timeout)
 {
 	int status = 1;
 	int retry_cmd = 0;
-		
-	if (timeout)
-		status = 0; 
 
-	if(cmd->err_info->CommandStatus != 0) 
-	{ /* an error has occurred */ 
-		switch(cmd->err_info->CommandStatus)
-		{
+	if (timeout)
+		status = 0;
+
+	if (cmd->err_info->CommandStatus != 0) {	/* an error has occurred */
+		switch (cmd->err_info->CommandStatus) {
 			unsigned char sense_key;
-			case CMD_TARGET_STATUS:
-				status = 0;
-			
-				if( cmd->err_info->ScsiStatus == 0x02)
-				{
-					printk(KERN_WARNING "cciss: cmd %p "
-                                        	"has CHECK CONDITION "
-						" byte 2 = 0x%x\n", cmd,
-						cmd->err_info->SenseInfo[2]
-					);
-					/* check the sense key */
-					sense_key = 0xf & 
-						cmd->err_info->SenseInfo[2];
-					/* no status or recovered error */
-					if((sense_key == 0x0) ||
-					    (sense_key == 0x1))
-					{
-							status = 1;
-					}
-				} else
-				{
-					printk(KERN_WARNING "cciss: cmd %p "
-                                                "has SCSI Status 0x%x\n",
-						cmd, cmd->err_info->ScsiStatus);
+		case CMD_TARGET_STATUS:
+			status = 0;
+
+			if (cmd->err_info->ScsiStatus == 0x02) {
+				printk(KERN_WARNING "cciss: cmd %p "
+				       "has CHECK CONDITION "
+				       " byte 2 = 0x%x\n", cmd,
+				       cmd->err_info->SenseInfo[2]
+				    );
+				/* check the sense key */
+				sense_key = 0xf & cmd->err_info->SenseInfo[2];
+				/* no status or recovered error */
+				if ((sense_key == 0x0) || (sense_key == 0x1)) {
+					status = 1;
 				}
+			} else {
+				printk(KERN_WARNING "cciss: cmd %p "
+				       "has SCSI Status 0x%x\n",
+				       cmd, cmd->err_info->ScsiStatus);
+			}
 			break;
-			case CMD_DATA_UNDERRUN:
-				printk(KERN_WARNING "cciss: cmd %p has"
-					" completed with data underrun "
-					"reported\n", cmd);
+		case CMD_DATA_UNDERRUN:
+			printk(KERN_WARNING "cciss: cmd %p has"
+			       " completed with data underrun "
+			       "reported\n", cmd);
 			break;
-			case CMD_DATA_OVERRUN:
-				printk(KERN_WARNING "cciss: cmd %p has"
-					" completed with data overrun "
-					"reported\n", cmd);
+		case CMD_DATA_OVERRUN:
+			printk(KERN_WARNING "cciss: cmd %p has"
+			       " completed with data overrun "
+			       "reported\n", cmd);
 			break;
-			case CMD_INVALID:
-				printk(KERN_WARNING "cciss: cmd %p is "
-					"reported invalid\n", cmd);
-				status = 0;
+		case CMD_INVALID:
+			printk(KERN_WARNING "cciss: cmd %p is "
+			       "reported invalid\n", cmd);
+			status = 0;
 			break;
-			case CMD_PROTOCOL_ERR:
-                                printk(KERN_WARNING "cciss: cmd %p has "
-					"protocol error \n", cmd);
-                                status = 0;
-                        break;
-			case CMD_HARDWARE_ERR:
-                                printk(KERN_WARNING "cciss: cmd %p had " 
-                                        " hardware error\n", cmd);
-                                status = 0;
-                        break;
-			case CMD_CONNECTION_LOST:
-				printk(KERN_WARNING "cciss: cmd %p had "
-					"connection lost\n", cmd);
-				status=0;
+		case CMD_PROTOCOL_ERR:
+			printk(KERN_WARNING "cciss: cmd %p has "
+			       "protocol error \n", cmd);
+			status = 0;
 			break;
-			case CMD_ABORTED:
-				printk(KERN_WARNING "cciss: cmd %p was "
-					"aborted\n", cmd);
-				status=0;
+		case CMD_HARDWARE_ERR:
+			printk(KERN_WARNING "cciss: cmd %p had "
+			       " hardware error\n", cmd);
+			status = 0;
 			break;
-			case CMD_ABORT_FAILED:
-				printk(KERN_WARNING "cciss: cmd %p reports "
-					"abort failed\n", cmd);
-				status=0;
+		case CMD_CONNECTION_LOST:
+			printk(KERN_WARNING "cciss: cmd %p had "
+			       "connection lost\n", cmd);
+			status = 0;
 			break;
-			case CMD_UNSOLICITED_ABORT:
-				printk(KERN_WARNING "cciss%d: unsolicited "
-					"abort %p\n", h->ctlr, cmd);
-				if (cmd->retry_count < MAX_CMD_RETRIES) {
-					retry_cmd=1;
-					printk(KERN_WARNING
-						"cciss%d: retrying %p\n",
-						h->ctlr, cmd);
-					cmd->retry_count++;
-				} else
-					printk(KERN_WARNING
-						"cciss%d: %p retried too "
-						"many times\n", h->ctlr, cmd);
-				status=0;
+		case CMD_ABORTED:
+			printk(KERN_WARNING "cciss: cmd %p was "
+			       "aborted\n", cmd);
+			status = 0;
 			break;
-			case CMD_TIMEOUT:
-				printk(KERN_WARNING "cciss: cmd %p timedout\n",
-					cmd);
-				status=0;
+		case CMD_ABORT_FAILED:
+			printk(KERN_WARNING "cciss: cmd %p reports "
+			       "abort failed\n", cmd);
+			status = 0;
 			break;
-			default:
-				printk(KERN_WARNING "cciss: cmd %p returned "
-					"unknown status %x\n", cmd, 
-						cmd->err_info->CommandStatus); 
-				status=0;
+		case CMD_UNSOLICITED_ABORT:
+			printk(KERN_WARNING "cciss%d: unsolicited "
+			       "abort %p\n", h->ctlr, cmd);
+			if (cmd->retry_count < MAX_CMD_RETRIES) {
+				retry_cmd = 1;
+				printk(KERN_WARNING
+				       "cciss%d: retrying %p\n", h->ctlr, cmd);
+				cmd->retry_count++;
+			} else
+				printk(KERN_WARNING
+				       "cciss%d: %p retried too "
+				       "many times\n", h->ctlr, cmd);
+			status = 0;
+			break;
+		case CMD_TIMEOUT:
+			printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
+			status = 0;
+			break;
+		default:
+			printk(KERN_WARNING "cciss: cmd %p returned "
+			       "unknown status %x\n", cmd,
+			       cmd->err_info->CommandStatus);
+			status = 0;
 		}
 	}
 	/* We need to return this command */
-	if(retry_cmd) {
-		resend_cciss_cmd(h,cmd);
+	if (retry_cmd) {
+		resend_cciss_cmd(h, cmd);
 		return;
-	}	
+	}
 
 	cmd->rq->completion_data = cmd;
 	cmd->rq->errors = status;
@@ -2336,12 +2365,12 @@
 	blk_complete_request(cmd->rq);
 }
 
-/* 
- * Get a request and submit it to the controller. 
+/*
+ * Get a request and submit it to the controller.
  */
 static void do_cciss_request(request_queue_t *q)
 {
-	ctlr_info_t *h= q->queuedata; 
+	ctlr_info_t *h = q->queuedata;
 	CommandList_struct *c;
 	int start_blk, seg;
 	struct request *creq;
@@ -2352,18 +2381,18 @@
 
 	/* We call start_io here in case there is a command waiting on the
 	 * queue that has not been sent.
-	*/
+	 */
 	if (blk_queue_plugged(q))
 		goto startio;
 
-queue:
+      queue:
 	creq = elv_next_request(q);
 	if (!creq)
 		goto startio;
 
 	BUG_ON(creq->nr_phys_segments > MAXSGENTRIES);
 
-	if (( c = cmd_alloc(h, 1)) == NULL)
+	if ((c = cmd_alloc(h, 1)) == NULL)
 		goto full;
 
 	blkdev_dequeue_request(creq);
@@ -2372,81 +2401,82 @@
 
 	c->cmd_type = CMD_RWREQ;
 	c->rq = creq;
-	
-	/* fill in the request */ 
+
+	/* fill in the request */
 	drv = creq->rq_disk->private_data;
-	c->Header.ReplyQueue = 0;  // unused in simple mode
+	c->Header.ReplyQueue = 0;	// unused in simple mode
 	/* got command from pool, so use the command block index instead */
 	/* for direct lookups. */
 	/* The first 2 bits are reserved for controller error reporting. */
 	c->Header.Tag.lower = (c->cmdindex << 3);
-	c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
-	c->Header.LUN.LogDev.VolId= drv->LunID;
+	c->Header.Tag.lower |= 0x04;	/* flag for direct lookup. */
+	c->Header.LUN.LogDev.VolId = drv->LunID;
 	c->Header.LUN.LogDev.Mode = 1;
-	c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
-	c->Request.Type.Type =  TYPE_CMD; // It is a command. 
-	c->Request.Type.Attribute = ATTR_SIMPLE; 
-	c->Request.Type.Direction = 
-		(rq_data_dir(creq) == READ) ? XFER_READ: XFER_WRITE; 
-	c->Request.Timeout = 0; // Don't time out	
-	c->Request.CDB[0] = (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
+	c->Request.CDBLen = 10;	// 12 byte commands not in FW yet;
+	c->Request.Type.Type = TYPE_CMD;	// It is a command.
+	c->Request.Type.Attribute = ATTR_SIMPLE;
+	c->Request.Type.Direction =
+	    (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
+	c->Request.Timeout = 0;	// Don't time out
+	c->Request.CDB[0] =
+	    (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
 	start_blk = creq->sector;
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",(int) creq->sector,
-		(int) creq->nr_sectors);	
-#endif /* CCISS_DEBUG */
+	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
+	       (int)creq->nr_sectors);
+#endif				/* CCISS_DEBUG */
 
 	seg = blk_rq_map_sg(q, creq, tmp_sg);
 
-	/* get the DMA records for the setup */ 
+	/* get the DMA records for the setup */
 	if (c->Request.Type.Direction == XFER_READ)
 		dir = PCI_DMA_FROMDEVICE;
 	else
 		dir = PCI_DMA_TODEVICE;
 
-	for (i=0; i<seg; i++)
-	{
+	for (i = 0; i < seg; i++) {
 		c->SG[i].Len = tmp_sg[i].length;
 		temp64.val = (__u64) pci_map_page(h->pdev, tmp_sg[i].page,
-			 		  tmp_sg[i].offset, tmp_sg[i].length,
-					  dir);
+						  tmp_sg[i].offset,
+						  tmp_sg[i].length, dir);
 		c->SG[i].Addr.lower = temp64.val32.lower;
-                c->SG[i].Addr.upper = temp64.val32.upper;
-                c->SG[i].Ext = 0;  // we are not chaining
+		c->SG[i].Addr.upper = temp64.val32.upper;
+		c->SG[i].Ext = 0;	// we are not chaining
 	}
-	/* track how many SG entries we are using */ 
-	if( seg > h->maxSG)
-		h->maxSG = seg; 
+	/* track how many SG entries we are using */
+	if (seg > h->maxSG)
+		h->maxSG = seg;
 
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", creq->nr_sectors, seg);
-#endif /* CCISS_DEBUG */
+	printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n",
+	       creq->nr_sectors, seg);
+#endif				/* CCISS_DEBUG */
 
 	c->Header.SGList = c->Header.SGTotal = seg;
-	c->Request.CDB[1]= 0;
-	c->Request.CDB[2]= (start_blk >> 24) & 0xff;	//MSB
-	c->Request.CDB[3]= (start_blk >> 16) & 0xff;
-	c->Request.CDB[4]= (start_blk >>  8) & 0xff;
-	c->Request.CDB[5]= start_blk & 0xff;
-	c->Request.CDB[6]= 0; // (sect >> 24) & 0xff; MSB
-	c->Request.CDB[7]= (creq->nr_sectors >>  8) & 0xff; 
-	c->Request.CDB[8]= creq->nr_sectors & 0xff; 
+	c->Request.CDB[1] = 0;
+	c->Request.CDB[2] = (start_blk >> 24) & 0xff;	//MSB
+	c->Request.CDB[3] = (start_blk >> 16) & 0xff;
+	c->Request.CDB[4] = (start_blk >> 8) & 0xff;
+	c->Request.CDB[5] = start_blk & 0xff;
+	c->Request.CDB[6] = 0;	// (sect >> 24) & 0xff; MSB
+	c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
+	c->Request.CDB[8] = creq->nr_sectors & 0xff;
 	c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
 
 	spin_lock_irq(q->queue_lock);
 
-	addQ(&(h->reqQ),c);
+	addQ(&(h->reqQ), c);
 	h->Qdepth++;
-	if(h->Qdepth > h->maxQsinceinit)
-		h->maxQsinceinit = h->Qdepth; 
+	if (h->Qdepth > h->maxQsinceinit)
+		h->maxQsinceinit = h->Qdepth;
 
 	goto queue;
-full:
+      full:
 	blk_stop_queue(q);
-startio:
+      startio:
 	/* We will already have the driver lock here so not need
 	 * to lock it.
-	*/
+	 */
 	start_io(h);
 }
 
@@ -2473,7 +2503,7 @@
 static inline int interrupt_pending(ctlr_info_t *h)
 {
 #ifdef CONFIG_CISS_SCSI_TAPE
-	return ( h->access.intr_pending(h) 
+	return (h->access.intr_pending(h)
 		|| (h->scsi_rejects.ncompletions > 0));
 #else
 	return h->access.intr_pending(h);
@@ -2483,11 +2513,11 @@
 static inline long interrupt_not_for_us(ctlr_info_t *h)
 {
 #ifdef CONFIG_CISS_SCSI_TAPE
-	return (((h->access.intr_pending(h) == 0) || 
-		 (h->interrupts_enabled == 0)) 
-	      && (h->scsi_rejects.ncompletions == 0));
+	return (((h->access.intr_pending(h) == 0) ||
+		 (h->interrupts_enabled == 0))
+		&& (h->scsi_rejects.ncompletions == 0));
 #else
-	return (((h->access.intr_pending(h) == 0) || 
+	return (((h->access.intr_pending(h) == 0) ||
 		 (h->interrupts_enabled == 0)));
 #endif
 }
@@ -2509,12 +2539,14 @@
 	 */
 	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
 	while (interrupt_pending(h)) {
-		while((a = get_next_completion(h)) != FIFO_EMPTY) {
+		while ((a = get_next_completion(h)) != FIFO_EMPTY) {
 			a1 = a;
 			if ((a & 0x04)) {
 				a2 = (a >> 3);
 				if (a2 >= NR_CMDS) {
-					printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
+					printk(KERN_WARNING
+					       "cciss: controller cciss%d failed, stopping.\n",
+					       h->ctlr);
 					fail_all_cmds(h->ctlr);
 					return IRQ_HANDLED;
 				}
@@ -2523,22 +2555,24 @@
 				a = c->busaddr;
 
 			} else {
-			a &= ~3;
+				a &= ~3;
 				if ((c = h->cmpQ) == NULL) {
-					printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
-				continue;	
-			} 
-			while(c->busaddr != a) {
-				c = c->next;
-				if (c == h->cmpQ) 
-					break;
-			}
+					printk(KERN_WARNING
+					       "cciss: Completion of %08x ignored\n",
+					       a1);
+					continue;
+				}
+				while (c->busaddr != a) {
+					c = c->next;
+					if (c == h->cmpQ)
+						break;
+				}
 			}
 			/*
 			 * If we've found the command, take it off the
 			 * completion Q and free it
 			 */
-			 if (c->busaddr == a) {
+			if (c->busaddr == a) {
 				removeQ(&h->cmpQ, c);
 				if (c->cmd_type == CMD_RWREQ) {
 					complete_command(h, c, 0);
@@ -2554,130 +2588,118 @@
 		}
 	}
 
- 	/* check to see if we have maxed out the number of commands that can
- 	 * be placed on the queue.  If so then exit.  We do this check here
- 	 * in case the interrupt we serviced was from an ioctl and did not
- 	 * free any new commands.
+	/* check to see if we have maxed out the number of commands that can
+	 * be placed on the queue.  If so then exit.  We do this check here
+	 * in case the interrupt we serviced was from an ioctl and did not
+	 * free any new commands.
 	 */
- 	if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
- 		goto cleanup;
+	if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+		goto cleanup;
 
- 	/* We have room on the queue for more commands.  Now we need to queue
- 	 * them up.  We will also keep track of the next queue to run so
- 	 * that every queue gets a chance to be started first.
- 	*/
-	for (j=0; j < h->highest_lun + 1; j++){
+	/* We have room on the queue for more commands.  Now we need to queue
+	 * them up.  We will also keep track of the next queue to run so
+	 * that every queue gets a chance to be started first.
+	 */
+	for (j = 0; j < h->highest_lun + 1; j++) {
 		int curr_queue = (start_queue + j) % (h->highest_lun + 1);
- 		/* make sure the disk has been added and the drive is real
- 		 * because this can be called from the middle of init_one.
- 		*/
-		if(!(h->drv[curr_queue].queue) ||
-		 		   !(h->drv[curr_queue].heads))
- 			continue;
- 		blk_start_queue(h->gendisk[curr_queue]->queue);
+		/* make sure the disk has been added and the drive is real
+		 * because this can be called from the middle of init_one.
+		 */
+		if (!(h->drv[curr_queue].queue) || !(h->drv[curr_queue].heads))
+			continue;
+		blk_start_queue(h->gendisk[curr_queue]->queue);
 
- 		/* check to see if we have maxed out the number of commands
- 		 * that can be placed on the queue.
- 		*/
- 		if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
- 		{
- 			if (curr_queue == start_queue){
-				h->next_to_run = (start_queue + 1) % (h->highest_lun + 1);
- 				goto cleanup;
- 			} else {
- 				h->next_to_run = curr_queue;
- 				goto cleanup;
- 	}
- 		} else {
+		/* check to see if we have maxed out the number of commands
+		 * that can be placed on the queue.
+		 */
+		if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) {
+			if (curr_queue == start_queue) {
+				h->next_to_run =
+				    (start_queue + 1) % (h->highest_lun + 1);
+				goto cleanup;
+			} else {
+				h->next_to_run = curr_queue;
+				goto cleanup;
+			}
+		} else {
 			curr_queue = (curr_queue + 1) % (h->highest_lun + 1);
- 		}
- 	}
+		}
+	}
 
-cleanup:
+      cleanup:
 	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 	return IRQ_HANDLED;
 }
-/* 
- *  We cannot read the structure directly, for portablity we must use 
+
+/*
+ *  We cannot read the structure directly, for portability we must use
  *   the io functions.
- *   This is for debug only. 
+ *   This is for debug only.
  */
 #ifdef CCISS_DEBUG
-static void print_cfg_table( CfgTable_struct *tb)
+static void print_cfg_table(CfgTable_struct *tb)
 {
 	int i;
 	char temp_name[17];
 
 	printk("Controller Configuration information\n");
 	printk("------------------------------------\n");
-	for(i=0;i<4;i++)
+	for (i = 0; i < 4; i++)
 		temp_name[i] = readb(&(tb->Signature[i]));
-	temp_name[4]='\0';
-	printk("   Signature = %s\n", temp_name); 
+	temp_name[4] = '\0';
+	printk("   Signature = %s\n", temp_name);
 	printk("   Spec Number = %d\n", readl(&(tb->SpecValence)));
-	printk("   Transport methods supported = 0x%x\n", 
-				readl(&(tb-> TransportSupport)));
-	printk("   Transport methods active = 0x%x\n", 
-				readl(&(tb->TransportActive)));
-	printk("   Requested transport Method = 0x%x\n", 
-			readl(&(tb->HostWrite.TransportRequest)));
-	printk("   Coalese Interrupt Delay = 0x%x\n", 
-			readl(&(tb->HostWrite.CoalIntDelay)));
-	printk("   Coalese Interrupt Count = 0x%x\n", 
-			readl(&(tb->HostWrite.CoalIntCount)));
-	printk("   Max outstanding commands = 0x%d\n", 
-			readl(&(tb->CmdsOutMax)));
-	printk("   Bus Types = 0x%x\n", readl(&(tb-> BusTypes)));
-	for(i=0;i<16;i++)
+	printk("   Transport methods supported = 0x%x\n",
+	       readl(&(tb->TransportSupport)));
+	printk("   Transport methods active = 0x%x\n",
+	       readl(&(tb->TransportActive)));
+	printk("   Requested transport Method = 0x%x\n",
+	       readl(&(tb->HostWrite.TransportRequest)));
+	printk("   Coalesce Interrupt Delay = 0x%x\n",
+	       readl(&(tb->HostWrite.CoalIntDelay)));
+	printk("   Coalesce Interrupt Count = 0x%x\n",
+	       readl(&(tb->HostWrite.CoalIntCount)));
+	printk("   Max outstanding commands = 0x%d\n",
+	       readl(&(tb->CmdsOutMax)));
+	printk("   Bus Types = 0x%x\n", readl(&(tb->BusTypes)));
+	for (i = 0; i < 16; i++)
 		temp_name[i] = readb(&(tb->ServerName[i]));
 	temp_name[16] = '\0';
 	printk("   Server Name = %s\n", temp_name);
-	printk("   Heartbeat Counter = 0x%x\n\n\n", 
-			readl(&(tb->HeartBeat)));
+	printk("   Heartbeat Counter = 0x%x\n\n\n", readl(&(tb->HeartBeat)));
 }
-#endif /* CCISS_DEBUG */ 
+#endif				/* CCISS_DEBUG */
 
-static void release_io_mem(ctlr_info_t *c)
-{
-	/* if IO mem was not protected do nothing */
-	if( c->io_mem_addr == 0)
-		return;
-	release_region(c->io_mem_addr, c->io_mem_length);
-	c->io_mem_addr = 0;
-	c->io_mem_length = 0;
-}
-
-static int find_PCI_BAR_index(struct pci_dev *pdev,
-				unsigned long pci_bar_addr)
+static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
 {
 	int i, offset, mem_type, bar_type;
-	if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */
+	if (pci_bar_addr == PCI_BASE_ADDRESS_0)	/* looking for BAR zero? */
 		return 0;
 	offset = 0;
-	for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
-		bar_type = pci_resource_flags(pdev, i) &
-			PCI_BASE_ADDRESS_SPACE;
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		bar_type = pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE;
 		if (bar_type == PCI_BASE_ADDRESS_SPACE_IO)
 			offset += 4;
 		else {
 			mem_type = pci_resource_flags(pdev, i) &
-				PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+			    PCI_BASE_ADDRESS_MEM_TYPE_MASK;
 			switch (mem_type) {
-				case PCI_BASE_ADDRESS_MEM_TYPE_32:
-				case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-					offset += 4; /* 32 bit */
-					break;
-				case PCI_BASE_ADDRESS_MEM_TYPE_64:
-					offset += 8;
-					break;
-				default: /* reserved in PCI 2.2 */
-					printk(KERN_WARNING "Base address is invalid\n");
-			       		return -1;
+			case PCI_BASE_ADDRESS_MEM_TYPE_32:
+			case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+				offset += 4;	/* 32 bit */
+				break;
+			case PCI_BASE_ADDRESS_MEM_TYPE_64:
+				offset += 8;
+				break;
+			default:	/* reserved in PCI 2.2 */
+				printk(KERN_WARNING
+				       "Base address is invalid\n");
+				return -1;
 				break;
 			}
 		}
- 		if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0)
-			return i+1;
+		if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0)
+			return i + 1;
 	}
 	return -1;
 }
@@ -2686,53 +2708,54 @@
  * controllers that are capable. If not, we use IO-APIC mode.
  */
 
-static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, __u32 board_id)
+static void __devinit cciss_interrupt_mode(ctlr_info_t *c,
+					   struct pci_dev *pdev, __u32 board_id)
 {
 #ifdef CONFIG_PCI_MSI
-        int err;
-        struct msix_entry cciss_msix_entries[4] = {{0,0}, {0,1},
-						   {0,2}, {0,3}};
+	int err;
+	struct msix_entry cciss_msix_entries[4] = { {0, 0}, {0, 1},
+	{0, 2}, {0, 3}
+	};
 
 	/* Some boards advertise MSI but don't really support it */
 	if ((board_id == 0x40700E11) ||
-		(board_id == 0x40800E11) ||
-		(board_id == 0x40820E11) ||
-		(board_id == 0x40830E11))
+	    (board_id == 0x40800E11) ||
+	    (board_id == 0x40820E11) || (board_id == 0x40830E11))
 		goto default_int_mode;
 
-        if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
-                err = pci_enable_msix(pdev, cciss_msix_entries, 4);
-                if (!err) {
-                        c->intr[0] = cciss_msix_entries[0].vector;
-                        c->intr[1] = cciss_msix_entries[1].vector;
-                        c->intr[2] = cciss_msix_entries[2].vector;
-                        c->intr[3] = cciss_msix_entries[3].vector;
-                        c->msix_vector = 1;
-                        return;
-                }
-                if (err > 0) {
-                        printk(KERN_WARNING "cciss: only %d MSI-X vectors "
-                                        "available\n", err);
-                } else {
-                        printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
-						err);
-                }
-        }
-        if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
-                if (!pci_enable_msi(pdev)) {
-                        c->intr[SIMPLE_MODE_INT] = pdev->irq;
-                        c->msi_vector = 1;
-                        return;
-                } else {
-                        printk(KERN_WARNING "cciss: MSI init failed\n");
-        		c->intr[SIMPLE_MODE_INT] = pdev->irq;
-                        return;
-                }
-        }
-default_int_mode:
-#endif /* CONFIG_PCI_MSI */
+	if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+		err = pci_enable_msix(pdev, cciss_msix_entries, 4);
+		if (!err) {
+			c->intr[0] = cciss_msix_entries[0].vector;
+			c->intr[1] = cciss_msix_entries[1].vector;
+			c->intr[2] = cciss_msix_entries[2].vector;
+			c->intr[3] = cciss_msix_entries[3].vector;
+			c->msix_vector = 1;
+			return;
+		}
+		if (err > 0) {
+			printk(KERN_WARNING "cciss: only %d MSI-X vectors "
+			       "available\n", err);
+		} else {
+			printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
+			       err);
+		}
+	}
+	if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
+		if (!pci_enable_msi(pdev)) {
+			c->intr[SIMPLE_MODE_INT] = pdev->irq;
+			c->msi_vector = 1;
+			return;
+		} else {
+			printk(KERN_WARNING "cciss: MSI init failed\n");
+			c->intr[SIMPLE_MODE_INT] = pdev->irq;
+			return;
+		}
+	}
+      default_int_mode:
+#endif				/* CONFIG_PCI_MSI */
 	/* if we get here we're going to use the default interrupt mode */
-        c->intr[SIMPLE_MODE_INT] = pdev->irq;
+	c->intr[SIMPLE_MODE_INT] = pdev->irq;
 	return;
 }
 
@@ -2743,58 +2766,40 @@
 	__u64 cfg_offset;
 	__u32 cfg_base_addr;
 	__u64 cfg_base_addr_index;
-	int i;
+	int i, err;
 
 	/* check to see if controller has been disabled */
 	/* BEFORE trying to enable it */
-	(void) pci_read_config_word(pdev, PCI_COMMAND,&command);
-	if(!(command & 0x02))
-	{
-		printk(KERN_WARNING "cciss: controller appears to be disabled\n");
-		return(-1);
+	(void)pci_read_config_word(pdev, PCI_COMMAND, &command);
+	if (!(command & 0x02)) {
+		printk(KERN_WARNING
+		       "cciss: controller appears to be disabled\n");
+		return -ENODEV;
 	}
 
-	if (pci_enable_device(pdev))
-	{
+	err = pci_enable_device(pdev);
+	if (err) {
 		printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
-		return( -1);
+		return err;
+	}
+
+	err = pci_request_regions(pdev, "cciss");
+	if (err) {
+		printk(KERN_ERR "cciss: Cannot obtain PCI resources, "
+		       "aborting\n");
+		goto err_out_disable_pdev;
 	}
 
 	subsystem_vendor_id = pdev->subsystem_vendor;
 	subsystem_device_id = pdev->subsystem_device;
 	board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) |
-					subsystem_vendor_id);
-
-	/* search for our IO range so we can protect it */
-	for(i=0; i<DEVICE_COUNT_RESOURCE; i++)
-	{
-		/* is this an IO range */ 
-		if( pci_resource_flags(pdev, i) & 0x01 ) {
-			c->io_mem_addr = pci_resource_start(pdev, i);
-			c->io_mem_length = pci_resource_end(pdev, i) -
-				pci_resource_start(pdev, i) +1;
-#ifdef CCISS_DEBUG
-			printk("IO value found base_addr[%d] %lx %lx\n", i,
-				c->io_mem_addr, c->io_mem_length);
-#endif /* CCISS_DEBUG */
-			/* register the IO range */ 
-			if(!request_region( c->io_mem_addr,
-                                        c->io_mem_length, "cciss"))
-			{
-				printk(KERN_WARNING "cciss I/O memory range already in use addr=%lx length=%ld\n",
-				c->io_mem_addr, c->io_mem_length);
-				c->io_mem_addr= 0;
-				c->io_mem_length = 0;
-			} 
-			break;
-		}
-	}
+		    subsystem_vendor_id);
 
 #ifdef CCISS_DEBUG
 	printk("command = %x\n", command);
 	printk("irq = %x\n", pdev->irq);
 	printk("board_id = %x\n", board_id);
-#endif /* CCISS_DEBUG */ 
+#endif				/* CCISS_DEBUG */
 
 /* If the kernel supports MSI/MSI-X we will try to enable that functionality,
  * else we use the IO-APIC interrupt assigned to us by system ROM.
@@ -2803,27 +2808,28 @@
 
 	/*
 	 * Memory base addr is first addr , the second points to the config
-         *   table
+	 *   table
 	 */
 
-	c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
+	c->paddr = pci_resource_start(pdev, 0);	/* addressing mode bits already removed */
 #ifdef CCISS_DEBUG
 	printk("address 0 = %x\n", c->paddr);
-#endif /* CCISS_DEBUG */ 
+#endif				/* CCISS_DEBUG */
 	c->vaddr = remap_pci_mem(c->paddr, 200);
 
 	/* Wait for the board to become ready.  (PCI hotplug needs this.)
 	 * We poll for up to 120 secs, once per 100ms. */
-	for (i=0; i < 1200; i++) {
+	for (i = 0; i < 1200; i++) {
 		scratchpad = readl(c->vaddr + SA5_SCRATCHPAD_OFFSET);
 		if (scratchpad == CCISS_FIRMWARE_READY)
 			break;
 		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ / 10); /* wait 100ms */
+		schedule_timeout(HZ / 10);	/* wait 100ms */
 	}
 	if (scratchpad != CCISS_FIRMWARE_READY) {
 		printk(KERN_WARNING "cciss: Board not ready.  Timed out.\n");
-		return -1;
+		err = -ENODEV;
+		goto err_out_free_res;
 	}
 
 	/* get the address index number */
@@ -2831,103 +2837,108 @@
 	cfg_base_addr &= (__u32) 0x0000ffff;
 #ifdef CCISS_DEBUG
 	printk("cfg base address = %x\n", cfg_base_addr);
-#endif /* CCISS_DEBUG */
-	cfg_base_addr_index =
-		find_PCI_BAR_index(pdev, cfg_base_addr);
+#endif				/* CCISS_DEBUG */
+	cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
 #ifdef CCISS_DEBUG
 	printk("cfg base address index = %x\n", cfg_base_addr_index);
-#endif /* CCISS_DEBUG */
+#endif				/* CCISS_DEBUG */
 	if (cfg_base_addr_index == -1) {
 		printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n");
-		release_io_mem(c);
-		return -1;
+		err = -ENODEV;
+		goto err_out_free_res;
 	}
 
 	cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
 #ifdef CCISS_DEBUG
 	printk("cfg offset = %x\n", cfg_offset);
-#endif /* CCISS_DEBUG */
-	c->cfgtable =  remap_pci_mem(pci_resource_start(pdev,
-				cfg_base_addr_index) + cfg_offset,
-				sizeof(CfgTable_struct));
+#endif				/* CCISS_DEBUG */
+	c->cfgtable = remap_pci_mem(pci_resource_start(pdev,
+						       cfg_base_addr_index) +
+				    cfg_offset, sizeof(CfgTable_struct));
 	c->board_id = board_id;
 
 #ifdef CCISS_DEBUG
 	print_cfg_table(c->cfgtable);
-#endif /* CCISS_DEBUG */
+#endif				/* CCISS_DEBUG */
 
-	for(i=0; i<NR_PRODUCTS; i++) {
+	for (i = 0; i < ARRAY_SIZE(products); i++) {
 		if (board_id == products[i].board_id) {
 			c->product_name = products[i].product_name;
 			c->access = *(products[i].access);
 			break;
 		}
 	}
-	if (i == NR_PRODUCTS) {
+	if (i == ARRAY_SIZE(products)) {
 		printk(KERN_WARNING "cciss: Sorry, I don't know how"
-			" to access the Smart Array controller %08lx\n", 
-				(unsigned long)board_id);
-		return -1;
+		       " to access the Smart Array controller %08lx\n",
+		       (unsigned long)board_id);
+		err = -ENODEV;
+		goto err_out_free_res;
 	}
-	if (  (readb(&c->cfgtable->Signature[0]) != 'C') ||
-	      (readb(&c->cfgtable->Signature[1]) != 'I') ||
-	      (readb(&c->cfgtable->Signature[2]) != 'S') ||
-	      (readb(&c->cfgtable->Signature[3]) != 'S') )
-	{
+	if ((readb(&c->cfgtable->Signature[0]) != 'C') ||
+	    (readb(&c->cfgtable->Signature[1]) != 'I') ||
+	    (readb(&c->cfgtable->Signature[2]) != 'S') ||
+	    (readb(&c->cfgtable->Signature[3]) != 'S')) {
 		printk("Does not appear to be a valid CISS config table\n");
-		return -1;
+		err = -ENODEV;
+		goto err_out_free_res;
 	}
-
 #ifdef CONFIG_X86
-{
-	/* Need to enable prefetch in the SCSI core for 6400 in x86 */
-	__u32 prefetch;
-	prefetch = readl(&(c->cfgtable->SCSI_Prefetch));
-	prefetch |= 0x100;
-	writel(prefetch, &(c->cfgtable->SCSI_Prefetch));
-}
+	{
+		/* Need to enable prefetch in the SCSI core for 6400 in x86 */
+		__u32 prefetch;
+		prefetch = readl(&(c->cfgtable->SCSI_Prefetch));
+		prefetch |= 0x100;
+		writel(prefetch, &(c->cfgtable->SCSI_Prefetch));
+	}
 #endif
 
 #ifdef CCISS_DEBUG
 	printk("Trying to put board into Simple mode\n");
-#endif /* CCISS_DEBUG */ 
+#endif				/* CCISS_DEBUG */
 	c->max_commands = readl(&(c->cfgtable->CmdsOutMax));
-	/* Update the field, and then ring the doorbell */ 
-	writel( CFGTBL_Trans_Simple, 
-		&(c->cfgtable->HostWrite.TransportRequest));
-	writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);
+	/* Update the field, and then ring the doorbell */
+	writel(CFGTBL_Trans_Simple, &(c->cfgtable->HostWrite.TransportRequest));
+	writel(CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);
 
 	/* under certain very rare conditions, this can take awhile.
 	 * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
 	 * as we enter this code.) */
-	for(i=0;i<MAX_CONFIG_WAIT;i++) {
+	for (i = 0; i < MAX_CONFIG_WAIT; i++) {
 		if (!(readl(c->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
 			break;
 		/* delay and try again */
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(10);
-	}	
+	}
 
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "I counter got to %d %x\n", i, readl(c->vaddr + SA5_DOORBELL));
-#endif /* CCISS_DEBUG */
+	printk(KERN_DEBUG "I counter got to %d %x\n", i,
+	       readl(c->vaddr + SA5_DOORBELL));
+#endif				/* CCISS_DEBUG */
 #ifdef CCISS_DEBUG
-	print_cfg_table(c->cfgtable);	
-#endif /* CCISS_DEBUG */ 
+	print_cfg_table(c->cfgtable);
+#endif				/* CCISS_DEBUG */
 
-	if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple))
-	{
+	if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
 		printk(KERN_WARNING "cciss: unable to get board into"
-					" simple mode\n");
-		return -1;
+		       " simple mode\n");
+		err = -ENODEV;
+		goto err_out_free_res;
 	}
 	return 0;
 
+      err_out_free_res:
+	pci_release_regions(pdev);
+
+      err_out_disable_pdev:
+	pci_disable_device(pdev);
+	return err;
 }
 
-/* 
- * Gets information about the local volumes attached to the controller. 
- */ 
+/*
+ * Gets information about the local volumes attached to the controller.
+ */
 static void cciss_getgeometry(int cntl_num)
 {
 	ReportLunData_struct *ld_buff;
@@ -2938,102 +2949,102 @@
 	int listlength = 0;
 	__u32 lunid = 0;
 	int block_size;
-	int total_size; 
+	int total_size;
 
 	ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
-	if (ld_buff == NULL)
-	{
+	if (ld_buff == NULL) {
 		printk(KERN_ERR "cciss: out of memory\n");
 		return;
 	}
-	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
-        if (size_buff == NULL)
-        {
-                printk(KERN_ERR "cciss: out of memory\n");
+	size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+	if (size_buff == NULL) {
+		printk(KERN_ERR "cciss: out of memory\n");
 		kfree(ld_buff);
-                return;
-        }
-	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
-        if (inq_buff == NULL)
-        {
-                printk(KERN_ERR "cciss: out of memory\n");
-                kfree(ld_buff);
+		return;
+	}
+	inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+	if (inq_buff == NULL) {
+		printk(KERN_ERR "cciss: out of memory\n");
+		kfree(ld_buff);
 		kfree(size_buff);
-                return;
-        }
-	/* Get the firmware version */ 
-	return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, 
-		sizeof(InquiryData_struct), 0, 0 ,0, NULL, TYPE_CMD);
-	if (return_code == IO_OK)
-	{
+		return;
+	}
+	/* Get the firmware version */
+	return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
+			      sizeof(InquiryData_struct), 0, 0, 0, NULL,
+			      TYPE_CMD);
+	if (return_code == IO_OK) {
 		hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32];
 		hba[cntl_num]->firm_ver[1] = inq_buff->data_byte[33];
 		hba[cntl_num]->firm_ver[2] = inq_buff->data_byte[34];
 		hba[cntl_num]->firm_ver[3] = inq_buff->data_byte[35];
-	} else /* send command failed */
-	{
-		printk(KERN_WARNING "cciss: unable to determine firmware"
-			" version of controller\n");
-	}
-	/* Get the number of logical volumes */ 
-	return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, 
-			sizeof(ReportLunData_struct), 0, 0, 0, NULL, TYPE_CMD);
+	} else {		/* send command failed */
 
-	if( return_code == IO_OK)
-	{
+		printk(KERN_WARNING "cciss: unable to determine firmware"
+		       " version of controller\n");
+	}
+	/* Get the number of logical volumes */
+	return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff,
+			      sizeof(ReportLunData_struct), 0, 0, 0, NULL,
+			      TYPE_CMD);
+
+	if (return_code == IO_OK) {
 #ifdef CCISS_DEBUG
 		printk("LUN Data\n--------------------------\n");
-#endif /* CCISS_DEBUG */ 
+#endif				/* CCISS_DEBUG */
 
-		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
-		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
-		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;	
+		listlength |=
+		    (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
+		listlength |=
+		    (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
+		listlength |=
+		    (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
 		listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
-	} else /* reading number of logical volumes failed */
-	{
+	} else {		/* reading number of logical volumes failed */
+
 		printk(KERN_WARNING "cciss: report logical volume"
-			" command failed\n");
+		       " command failed\n");
 		listlength = 0;
 	}
-	hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry
-	if (hba[cntl_num]->num_luns > CISS_MAX_LUN)
-	{
-		printk(KERN_ERR "ciss:  only %d number of logical volumes supported\n",
-			CISS_MAX_LUN);
+	hba[cntl_num]->num_luns = listlength / 8;	// 8 bytes pre entry
+	if (hba[cntl_num]->num_luns > CISS_MAX_LUN) {
+		printk(KERN_ERR
+		       "ciss:  only %d number of logical volumes supported\n",
+		       CISS_MAX_LUN);
 		hba[cntl_num]->num_luns = CISS_MAX_LUN;
 	}
 #ifdef CCISS_DEBUG
-	printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],
-		ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],
-		ld_buff->LUNListLength[3],  hba[cntl_num]->num_luns);
-#endif /* CCISS_DEBUG */
+	printk(KERN_DEBUG "Length = %x %x %x %x = %d\n",
+	       ld_buff->LUNListLength[0], ld_buff->LUNListLength[1],
+	       ld_buff->LUNListLength[2], ld_buff->LUNListLength[3],
+	       hba[cntl_num]->num_luns);
+#endif				/* CCISS_DEBUG */
 
-	hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1;
-//	for(i=0; i<  hba[cntl_num]->num_luns; i++)
-	for(i=0; i < CISS_MAX_LUN; i++)
-	{
-		if (i < hba[cntl_num]->num_luns){
-		  	lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
-				 << 24;
-        		lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
-				 << 16;
-        		lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
-				 << 8;
-        	lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
-		
-		hba[cntl_num]->drv[i].LunID = lunid;
+	hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1;
+//      for(i=0; i<  hba[cntl_num]->num_luns; i++)
+	for (i = 0; i < CISS_MAX_LUN; i++) {
+		if (i < hba[cntl_num]->num_luns) {
+			lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
+			    << 24;
+			lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
+			    << 16;
+			lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
+			    << 8;
+			lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
 
+			hba[cntl_num]->drv[i].LunID = lunid;
 
 #ifdef CCISS_DEBUG
-	  	printk(KERN_DEBUG "LUN[%d]:  %x %x %x %x = %x\n", i, 
-			ld_buff->LUN[i][0], ld_buff->LUN[i][1],
-			ld_buff->LUN[i][2], ld_buff->LUN[i][3],
-			hba[cntl_num]->drv[i].LunID);
-#endif /* CCISS_DEBUG */
-		cciss_read_capacity(cntl_num, i, size_buff, 0,
-			&total_size, &block_size);
+			printk(KERN_DEBUG "LUN[%d]:  %x %x %x %x = %x\n", i,
+			       ld_buff->LUN[i][0], ld_buff->LUN[i][1],
+			       ld_buff->LUN[i][2], ld_buff->LUN[i][3],
+			       hba[cntl_num]->drv[i].LunID);
+#endif				/* CCISS_DEBUG */
+			cciss_read_capacity(cntl_num, i, size_buff, 0,
+					    &total_size, &block_size);
 			cciss_geometry_inquiry(cntl_num, i, 0, total_size,
-				block_size, inq_buff, &hba[cntl_num]->drv[i]);
+					       block_size, inq_buff,
+					       &hba[cntl_num]->drv[i]);
 		} else {
 			/* initialize raid_level to indicate a free space */
 			hba[cntl_num]->drv[i].raid_level = -1;
@@ -3042,7 +3053,7 @@
 	kfree(ld_buff);
 	kfree(size_buff);
 	kfree(inq_buff);
-}	
+}
 
 /* Function to find the first free pointer into our hba[] array */
 /* Returns -1 if no free entries are left.  */
@@ -3056,7 +3067,7 @@
 			goto out;
 	}
 
-	for(i=0; i< MAX_CTLR; i++) {
+	for (i = 0; i < MAX_CTLR; i++) {
 		if (!hba[i]) {
 			ctlr_info_t *p;
 			p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
@@ -3069,11 +3080,11 @@
 		}
 	}
 	printk(KERN_WARNING "cciss: This driver supports a maximum"
-		" of %d controllers.\n", MAX_CTLR);
+	       " of %d controllers.\n", MAX_CTLR);
 	goto out;
-Enomem:
+      Enomem:
 	printk(KERN_ERR "cciss: out of memory.\n");
-out:
+      out:
 	while (n--)
 		put_disk(disk[n]);
 	return -1;
@@ -3096,20 +3107,17 @@
  *  returns the number of block devices registered.
  */
 static int __devinit cciss_init_one(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
+				    const struct pci_device_id *ent)
 {
 	request_queue_t *q;
 	int i;
 	int j;
 	int rc;
+	int dac;
 
-	printk(KERN_DEBUG "cciss: Device 0x%x has been found at"
-			" bus %d dev %d func %d\n",
-		pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
-			PCI_FUNC(pdev->devfn));
 	i = alloc_cciss_hba();
-	if(i < 0)
-		return (-1);
+	if (i < 0)
+		return -1;
 
 	hba[i]->busy_initializing = 1;
 
@@ -3122,11 +3130,11 @@
 
 	/* configure PCI DMA stuff */
 	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
-		printk("cciss: using DAC cycles\n");
+		dac = 1;
 	else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
-		printk("cciss: not using DAC cycles\n");
+		dac = 0;
 	else {
-		printk("cciss: no suitable DMA available\n");
+		printk(KERN_ERR "cciss: no suitable DMA available\n");
 		goto clean1;
 	}
 
@@ -3138,60 +3146,69 @@
 	if (i < MAX_CTLR_ORIG)
 		hba[i]->major = COMPAQ_CISS_MAJOR + i;
 	rc = register_blkdev(hba[i]->major, hba[i]->devname);
-	if(rc == -EBUSY || rc == -EINVAL) {
+	if (rc == -EBUSY || rc == -EINVAL) {
 		printk(KERN_ERR
-			"cciss:  Unable to get major number %d for %s "
-			"on hba %d\n", hba[i]->major, hba[i]->devname, i);
+		       "cciss:  Unable to get major number %d for %s "
+		       "on hba %d\n", hba[i]->major, hba[i]->devname, i);
 		goto clean1;
-	}
-	else {
+	} else {
 		if (i >= MAX_CTLR_ORIG)
 			hba[i]->major = rc;
 	}
 
 	/* make sure the board interrupts are off */
 	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
-	if( request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr,
-		SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 
-			hba[i]->devname, hba[i])) {
+	if (request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr,
+			SA_INTERRUPT | SA_SHIRQ, hba[i]->devname, hba[i])) {
 		printk(KERN_ERR "cciss: Unable to get irq %d for %s\n",
-			hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname);
+		       hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname);
 		goto clean2;
 	}
-	hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL);
-	hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent(
-		hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), 
-		&(hba[i]->cmd_pool_dhandle));
-	hba[i]->errinfo_pool = (ErrorInfo_struct *)pci_alloc_consistent(
-		hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct), 
-		&(hba[i]->errinfo_pool_dhandle));
-	if((hba[i]->cmd_pool_bits == NULL) 
-		|| (hba[i]->cmd_pool == NULL)
-		|| (hba[i]->errinfo_pool == NULL)) {
-                printk( KERN_ERR "cciss: out of memory");
+
+	printk(KERN_INFO "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
+	       hba[i]->devname, pdev->device, pci_name(pdev),
+	       hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not");
+
+	hba[i]->cmd_pool_bits =
+	    kmalloc(((NR_CMDS + BITS_PER_LONG -
+		      1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
+	hba[i]->cmd_pool = (CommandList_struct *)
+	    pci_alloc_consistent(hba[i]->pdev,
+		    NR_CMDS * sizeof(CommandList_struct),
+		    &(hba[i]->cmd_pool_dhandle));
+	hba[i]->errinfo_pool = (ErrorInfo_struct *)
+	    pci_alloc_consistent(hba[i]->pdev,
+		    NR_CMDS * sizeof(ErrorInfo_struct),
+		    &(hba[i]->errinfo_pool_dhandle));
+	if ((hba[i]->cmd_pool_bits == NULL)
+	    || (hba[i]->cmd_pool == NULL)
+	    || (hba[i]->errinfo_pool == NULL)) {
+		printk(KERN_ERR "cciss: out of memory");
 		goto clean4;
 	}
 #ifdef CONFIG_CISS_SCSI_TAPE
-	hba[i]->scsi_rejects.complete = 
-		kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * 
-			(NR_CMDS + 5), GFP_KERNEL);
+	hba[i]->scsi_rejects.complete =
+	    kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) *
+		    (NR_CMDS + 5), GFP_KERNEL);
 	if (hba[i]->scsi_rejects.complete == NULL) {
-                printk( KERN_ERR "cciss: out of memory");
+		printk(KERN_ERR "cciss: out of memory");
 		goto clean4;
 	}
 #endif
 	spin_lock_init(&hba[i]->lock);
 
-	/* Initialize the pdev driver private data. 
-		have it point to hba[i].  */
+	/* Initialize the pdev driver private data.
+	   have it point to hba[i].  */
 	pci_set_drvdata(pdev, hba[i]);
-	/* command and error info recs zeroed out before 
-			they are used */
-        memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long));
+	/* command and error info recs zeroed out before
+	   they are used */
+	memset(hba[i]->cmd_pool_bits, 0,
+	       ((NR_CMDS + BITS_PER_LONG -
+		 1) / BITS_PER_LONG) * sizeof(unsigned long));
 
-#ifdef CCISS_DEBUG	
-	printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);
-#endif /* CCISS_DEBUG */
+#ifdef CCISS_DEBUG
+	printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n", i);
+#endif				/* CCISS_DEBUG */
 
 	cciss_getgeometry(i);
 
@@ -3203,15 +3220,15 @@
 	cciss_procinit(i);
 	hba[i]->busy_initializing = 0;
 
-	for(j=0; j < NWD; j++) { /* mfm */
+	for (j = 0; j < NWD; j++) {	/* mfm */
 		drive_info_struct *drv = &(hba[i]->drv[j]);
 		struct gendisk *disk = hba[i]->gendisk[j];
 
 		q = blk_init_queue(do_cciss_request, &hba[i]->lock);
 		if (!q) {
 			printk(KERN_ERR
-			   "cciss:  unable to allocate queue for disk %d\n",
-			   j);
+			       "cciss:  unable to allocate queue for disk %d\n",
+			       j);
 			break;
 		}
 		drv->queue = q;
@@ -3237,94 +3254,90 @@
 		disk->fops = &cciss_fops;
 		disk->queue = q;
 		disk->private_data = drv;
+		disk->driverfs_dev = &pdev->dev;
 		/* we must register the controller even if no disks exist */
 		/* this is for the online array utilities */
-		if(!drv->heads && j)
+		if (!drv->heads && j)
 			continue;
 		blk_queue_hardsect_size(q, drv->block_size);
 		set_capacity(disk, drv->nr_blocks);
 		add_disk(disk);
 	}
 
-	return(1);
+	return 1;
 
-clean4:
+      clean4:
 #ifdef CONFIG_CISS_SCSI_TAPE
 	kfree(hba[i]->scsi_rejects.complete);
 #endif
 	kfree(hba[i]->cmd_pool_bits);
-	if(hba[i]->cmd_pool)
+	if (hba[i]->cmd_pool)
 		pci_free_consistent(hba[i]->pdev,
-			NR_CMDS * sizeof(CommandList_struct),
-			hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
-	if(hba[i]->errinfo_pool)
+				    NR_CMDS * sizeof(CommandList_struct),
+				    hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
+	if (hba[i]->errinfo_pool)
 		pci_free_consistent(hba[i]->pdev,
-			NR_CMDS * sizeof( ErrorInfo_struct),
-			hba[i]->errinfo_pool,
-			hba[i]->errinfo_pool_dhandle);
+				    NR_CMDS * sizeof(ErrorInfo_struct),
+				    hba[i]->errinfo_pool,
+				    hba[i]->errinfo_pool_dhandle);
 	free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]);
-clean2:
+      clean2:
 	unregister_blkdev(hba[i]->major, hba[i]->devname);
-clean1:
-	release_io_mem(hba[i]);
+      clean1:
 	hba[i]->busy_initializing = 0;
 	free_hba(i);
-	return(-1);
+	return -1;
 }
 
-static void __devexit cciss_remove_one (struct pci_dev *pdev)
+static void __devexit cciss_remove_one(struct pci_dev *pdev)
 {
 	ctlr_info_t *tmp_ptr;
 	int i, j;
 	char flush_buf[4];
-	int return_code; 
+	int return_code;
 
-	if (pci_get_drvdata(pdev) == NULL)
-	{
-		printk( KERN_ERR "cciss: Unable to remove device \n");
+	if (pci_get_drvdata(pdev) == NULL) {
+		printk(KERN_ERR "cciss: Unable to remove device \n");
 		return;
 	}
 	tmp_ptr = pci_get_drvdata(pdev);
 	i = tmp_ptr->ctlr;
-	if (hba[i] == NULL) 
-	{
+	if (hba[i] == NULL) {
 		printk(KERN_ERR "cciss: device appears to "
-			"already be removed \n");
+		       "already be removed \n");
 		return;
 	}
 	/* Turn board interrupts off  and send the flush cache command */
 	/* sendcmd will turn off interrupt, and send the flush...
-	* To write all data in the battery backed cache to disks */
+	 * To write all data in the battery backed cache to disks */
 	memset(flush_buf, 0, 4);
 	return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
-				TYPE_CMD);
-	if(return_code != IO_OK)
-	{
-		printk(KERN_WARNING "Error Flushing cache on controller %d\n", 
-			i);
+			      TYPE_CMD);
+	if (return_code != IO_OK) {
+		printk(KERN_WARNING "Error Flushing cache on controller %d\n",
+		       i);
 	}
 	free_irq(hba[i]->intr[2], hba[i]);
 
 #ifdef CONFIG_PCI_MSI
-        if (hba[i]->msix_vector)
-                pci_disable_msix(hba[i]->pdev);
-        else if (hba[i]->msi_vector)
-                pci_disable_msi(hba[i]->pdev);
-#endif /* CONFIG_PCI_MSI */
+	if (hba[i]->msix_vector)
+		pci_disable_msix(hba[i]->pdev);
+	else if (hba[i]->msi_vector)
+		pci_disable_msi(hba[i]->pdev);
+#endif				/* CONFIG_PCI_MSI */
 
-	pci_set_drvdata(pdev, NULL);
 	iounmap(hba[i]->vaddr);
-	cciss_unregister_scsi(i);  /* unhook from SCSI subsystem */
+	cciss_unregister_scsi(i);	/* unhook from SCSI subsystem */
 	unregister_blkdev(hba[i]->major, hba[i]->devname);
-	remove_proc_entry(hba[i]->devname, proc_cciss);	
-	
+	remove_proc_entry(hba[i]->devname, proc_cciss);
+
 	/* remove it from the disk list */
 	for (j = 0; j < NWD; j++) {
 		struct gendisk *disk = hba[i]->gendisk[j];
 		if (disk) {
 			request_queue_t *q = disk->queue;
 
-			if (disk->flags & GENHD_FL_UP) 
+			if (disk->flags & GENHD_FL_UP)
 				del_gendisk(disk);
 			if (q)
 				blk_cleanup_queue(q);
@@ -3333,26 +3346,28 @@
 
 	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
 			    hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
-	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
-		hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
+	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(ErrorInfo_struct),
+			    hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
 	kfree(hba[i]->cmd_pool_bits);
 #ifdef CONFIG_CISS_SCSI_TAPE
 	kfree(hba[i]->scsi_rejects.complete);
 #endif
- 	release_io_mem(hba[i]);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
 	free_hba(i);
-}	
+}
 
 static struct pci_driver cciss_pci_driver = {
-	.name =		"cciss",
-	.probe =	cciss_init_one,
-	.remove =	__devexit_p(cciss_remove_one),
-	.id_table =	cciss_pci_device_id, /* id_table */
+	.name = "cciss",
+	.probe = cciss_init_one,
+	.remove = __devexit_p(cciss_remove_one),
+	.id_table = cciss_pci_device_id,	/* id_table */
 };
 
 /*
  *  This is it.  Register the PCI driver information for the cards we control
- *  the OS will call our registered routines when it finds one of our cards. 
+ *  the OS will call our registered routines when it finds one of our cards.
  */
 static int __init cciss_init(void)
 {
@@ -3368,12 +3383,10 @@
 
 	pci_unregister_driver(&cciss_pci_driver);
 	/* double check that all controller entrys have been removed */
-	for (i=0; i< MAX_CTLR; i++) 
-	{
-		if (hba[i] != NULL)
-		{
+	for (i = 0; i < MAX_CTLR; i++) {
+		if (hba[i] != NULL) {
 			printk(KERN_WARNING "cciss: had to remove"
-					" controller %d\n", i);
+			       " controller %d\n", i);
 			cciss_remove_one(hba[i]->pdev);
 		}
 	}
@@ -3388,21 +3401,21 @@
 	unsigned long flags;
 
 	printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
-	h->alive = 0;	/* the controller apparently died... */
+	h->alive = 0;		/* the controller apparently died... */
 
 	spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 
-	pci_disable_device(h->pdev); /* Make sure it is really dead. */
+	pci_disable_device(h->pdev);	/* Make sure it is really dead. */
 
 	/* move everything off the request queue onto the completed queue */
-	while( (c = h->reqQ) != NULL ) {
+	while ((c = h->reqQ) != NULL) {
 		removeQ(&(h->reqQ), c);
 		h->Qdepth--;
-		addQ (&(h->cmpQ), c);
+		addQ(&(h->cmpQ), c);
 	}
 
 	/* Now, fail everything on the completed queue with a HW error */
-	while( (c = h->cmpQ) != NULL ) {
+	while ((c = h->cmpQ) != NULL) {
 		removeQ(&h->cmpQ, c);
 		c->err_info->CommandStatus = CMD_HARDWARE_ERR;
 		if (c->cmd_type == CMD_RWREQ) {
@@ -3410,8 +3423,8 @@
 		} else if (c->cmd_type == CMD_IOCTL_PEND)
 			complete(c->waiting);
 #ifdef CONFIG_CISS_SCSI_TAPE
-			else if (c->cmd_type == CMD_SCSI)
-				complete_scsi_command(c, 0, 0);
+		else if (c->cmd_type == CMD_SCSI)
+			complete_scsi_command(c, 0, 0);
 #endif
 	}
 	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index b24fc05..868e0d8 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -60,8 +60,6 @@
 	__u32	board_id;
 	void __iomem *vaddr;
 	unsigned long paddr;
-	unsigned long io_mem_addr;
-	unsigned long io_mem_length;
 	CfgTable_struct __iomem *cfgtable;
 	int	interrupts_enabled;
 	int	major;
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 597c007..afdff32 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -578,7 +578,7 @@
 
 	if (cmd->use_sg) {
 		pci_unmap_sg(ctlr->pdev,
-			cmd->buffer, cmd->use_sg,
+			cmd->request_buffer, cmd->use_sg,
 				cmd->sc_data_direction); 
 	}
 	else if (cmd->request_bufflen) {
@@ -1210,7 +1210,7 @@
 		struct scsi_cmnd *cmd)
 {
 	unsigned int use_sg, nsegs=0, len;
-	struct scatterlist *scatter = (struct scatterlist *) cmd->buffer;
+	struct scatterlist *scatter = (struct scatterlist *) cmd->request_buffer;
 	__u64 addr64;
 
 	/* is it just one virtual address? */	
@@ -1232,7 +1232,7 @@
 	} /* else, must be a list of virtual addresses.... */
 	else if (cmd->use_sg <= MAXSGENTRIES) {	/* not too many addrs? */
 
-		use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, 
+		use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg,
 			cmd->sc_data_direction);
 
 		for (nsegs=0; nsegs < use_sg; nsegs++) {
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index b6ea2f0..5eb6fb7 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -392,7 +392,7 @@
 }
 
 /* pdev is NULL for eisa */
-static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
 {
 	request_queue_t *q;
 	int j;
@@ -410,8 +410,7 @@
 	}
 	hba[i]->access.set_intr_mask(hba[i], 0);
 	if (request_irq(hba[i]->intr, do_ida_intr,
-		SA_INTERRUPT|SA_SHIRQ|SA_SAMPLE_RANDOM,
-		hba[i]->devname, hba[i]))
+		SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
 	{
 		printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n",
 				hba[i]->intr, hba[i]->devname);
@@ -745,7 +744,7 @@
 /*
  * Find an EISA controller's signature.  Set up an hba if we find it.
  */
-static int cpqarray_eisa_detect(void)
+static int __init cpqarray_eisa_detect(void)
 {
 	int i=0, j;
 	__u32 board_id;
@@ -1036,6 +1035,8 @@
 
 	complete_buffers(cmd->rq->bio, ok);
 
+	add_disk_randomness(cmd->rq->rq_disk);
+
         DBGPX(printk("Done with %p\n", cmd->rq););
 	end_that_request_last(cmd->rq, ok ? 1 : -EIO);
 }
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 9c3b94e..18dd026 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -210,7 +210,7 @@
 {
 	struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
 	struct address_space *mapping = file->f_mapping;
-	struct address_space_operations *aops = mapping->a_ops;
+	const struct address_space_operations *aops = mapping->a_ops;
 	pgoff_t index;
 	unsigned offset, bv_offs;
 	int len, ret;
@@ -784,7 +784,7 @@
 
 	error = -EINVAL;
 	if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) {
-		struct address_space_operations *aops = mapping->a_ops;
+		const struct address_space_operations *aops = mapping->a_ops;
 		/*
 		 * If we can't read - sorry. If we only can't write - well,
 		 * it's going to be read-only.
@@ -818,7 +818,7 @@
 	lo->lo_device = bdev;
 	lo->lo_flags = lo_flags;
 	lo->lo_backing_file = file;
-	lo->transfer = NULL;
+	lo->transfer = transfer_none;
 	lo->ioctl = NULL;
 	lo->lo_sizelimit = 0;
 	lo->old_gfp_mask = mapping_gfp_mask(mapping);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 8bca490..7f554f2 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -7,39 +7,9 @@
  * Copyright 1997-2000 Pavel Machek <pavel@ucw.cz>
  * Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
  *
- * (part of code stolen from loop.c)
+ * This file is released under GPLv2 or later.
  *
- * 97-3-25 compiled 0-th version, not yet tested it 
- *   (it did not work, BTW) (later that day) HEY! it works!
- *   (bit later) hmm, not that much... 2:00am next day:
- *   yes, it works, but it gives something like 50kB/sec
- * 97-4-01 complete rewrite to make it possible for many requests at 
- *   once to be processed
- * 97-4-11 Making protocol independent of endianity etc.
- * 97-9-13 Cosmetic changes
- * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines
- * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl>
- * 01-2-27 Fix to store proper blockcount for kernel (calculated using
- *   BLOCK_SIZE_BITS, not device blocksize) <aga@permonline.ru>
- * 01-3-11 Make nbd work with new Linux block layer code. It now supports
- *   plugging like all the other block devices. Also added in MSG_MORE to
- *   reduce number of partial TCP segments sent. <steve@chygwyn.com>
- * 01-12-6 Fix deadlock condition by making queue locks independent of
- *   the transmit lock. <steve@chygwyn.com>
- * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes.
- *   <Paul.Clements@SteelEye.com> <James.Bottomley@SteelEye.com>
- * 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes
- *   memory corruption from module removal and possible memory corruption
- *   from sending/receiving disk data. <ldl@aros.net>
- * 03-06-23 Cosmetic changes. <ldl@aros.net>
- * 03-06-23 Enhance diagnostics support. <ldl@aros.net>
- * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct.
- *   <ldl@aros.net>
- * 03-06-24 Cleanup PARANOIA usage & code. <ldl@aros.net>
- * 04-02-19 Remove PARANOIA, plus various cleanups (Paul Clements)
- * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
- * why not: would need access_ok and friends, would share yet another
- *          structure with userland
+ * (part of code stolen from loop.c)
  */
 
 #include <linux/major.h>
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 940bfd7..0378da04 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -191,7 +191,7 @@
 	return 0;
 }
 
-static struct address_space_operations ramdisk_aops = {
+static const struct address_space_operations ramdisk_aops = {
 	.readpage	= ramdisk_readpage,
 	.prepare_write	= ramdisk_prepare_write,
 	.commit_write	= ramdisk_commit_write,
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index c688c25..60e9a94 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -10,17 +10,13 @@
  * TODO (sorted by decreasing priority)
  *  -- set readonly flag for CDs, set removable flag for CF readers
  *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
- *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
  *  -- verify the 13 conditions and do bulk resets
- *  -- kill last_pipe and simply do two-state clearing on both pipes
  *  -- highmem
  *  -- move top_sense and work_bcs into separate allocations (if they survive)
  *     for cache purists and esoteric architectures.
  *  -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ?
  *  -- prune comments, they are too volumnous
- *  -- Exterminate P3 printks
  *  -- Resove XXX's
- *  -- Redo "benh's retries", perhaps have spin-up code to handle them. V:D=?
  *  -- CLEAR, CLR2STS, CLRRS seem to be ripe for refactoring.
  */
 #include <linux/kernel.h>
@@ -180,7 +176,6 @@
 #define UB_DIR_ILLEGAL2	2
 #define UB_DIR_WRITE	3
 
-/* P3 */
 #define UB_DIR_CHAR(c)  (((c)==UB_DIR_WRITE)? 'w': \
 			 (((c)==UB_DIR_READ)? 'r': 'n'))
 
@@ -669,8 +664,9 @@
 	 */
 	n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]);
 	if (n_elem < 0) {
+		/* Impossible, because blk_rq_map_sg should not hit ENOMEM. */
 		printk(KERN_INFO "%s: failed request map (%d)\n",
-		    lun->name, n_elem); /* P3 */
+		    lun->name, n_elem);
 		goto drop;
 	}
 	if (n_elem > UB_MAX_REQ_SG) {	/* Paranoia */
@@ -824,7 +820,9 @@
 	if (urq->current_try >= 3)
 		return -EIO;
 	urq->current_try++;
-	/* P3 */ printk("%s: dir %c len/act %d/%d "
+
+	/* Remove this if anyone complains of flooding. */
+	printk(KERN_DEBUG "%s: dir %c len/act %d/%d "
 	    "[sense %x %02x %02x] retry %d\n",
 	    sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len,
 	    cmd->key, cmd->asc, cmd->ascq, urq->current_try);
@@ -1241,8 +1239,6 @@
 			 * to check. But it's not all right if the device
 			 * counts disagree with our counts.
 			 */
-			/* P3 */ printk("%s: resid %d len %d act %d\n",
-			    sc->name, len, cmd->len, cmd->act_len);
 			goto Bad_End;
 		}
 
@@ -1253,7 +1249,6 @@
 			ub_state_sense(sc, cmd);
 			return;
 		case US_BULK_STAT_PHASE:
-			/* P3 */ printk("%s: status PHASE\n", sc->name);
 			goto Bad_End;
 		default:
 			printk(KERN_INFO "%s: unknown CSW status 0x%x\n",
@@ -1568,16 +1563,14 @@
 	}
 
 	if (atomic_read(&sc->poison)) {
-		printk(KERN_NOTICE "%s: Not resetting disconnected device\n",
-		    sc->name); /* P3 This floods. Remove soon. XXX */
+		;
 	} else if ((sc->reset & 1) == 0) {
 		ub_sync_reset(sc);
 		msleep(700);	/* usb-storage sleeps 6s (!) */
 		ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
 		ub_probe_clear_stall(sc, sc->send_bulk_pipe);
 	} else if (sc->dev->actconfig->desc.bNumInterfaces != 1) {
-		printk(KERN_NOTICE "%s: Not resetting multi-interface device\n",
-		    sc->name); /* P3 This floods. Remove soon. XXX */
+		;
 	} else {
 		if ((lkr = usb_lock_device_for_reset(sc->dev, sc->intf)) < 0) {
 			printk(KERN_NOTICE
@@ -1651,15 +1644,11 @@
 static int ub_bd_open(struct inode *inode, struct file *filp)
 {
 	struct gendisk *disk = inode->i_bdev->bd_disk;
-	struct ub_lun *lun;
-	struct ub_dev *sc;
+	struct ub_lun *lun = disk->private_data;
+	struct ub_dev *sc = lun->udev;
 	unsigned long flags;
 	int rc;
 
-	if ((lun = disk->private_data) == NULL)
-		return -ENXIO;
-	sc = lun->udev;
-
 	spin_lock_irqsave(&ub_lock, flags);
 	if (atomic_read(&sc->poison)) {
 		spin_unlock_irqrestore(&ub_lock, flags);
@@ -1823,10 +1812,8 @@
 	rc = ub_submit_scsi(sc, cmd);
 	spin_unlock_irqrestore(sc->lock, flags);
 
-	if (rc != 0) {
-		printk("ub: testing ready: submit error (%d)\n", rc); /* P3 */
+	if (rc != 0)
 		goto err_submit;
-	}
 
 	wait_for_completion(&compl);
 
@@ -1884,20 +1871,16 @@
 	rc = ub_submit_scsi(sc, cmd);
 	spin_unlock_irqrestore(sc->lock, flags);
 
-	if (rc != 0) {
-		printk("ub: reading capacity: submit error (%d)\n", rc); /* P3 */
+	if (rc != 0)
 		goto err_submit;
-	}
 
 	wait_for_completion(&compl);
 
 	if (cmd->error != 0) {
-		printk("ub: reading capacity: error %d\n", cmd->error); /* P3 */
 		rc = -EIO;
 		goto err_read;
 	}
 	if (cmd->act_len != 8) {
-		printk("ub: reading capacity: size %d\n", cmd->act_len); /* P3 */
 		rc = -EIO;
 		goto err_read;
 	}
@@ -1911,7 +1894,6 @@
 	case 2048:	shift = 2;	break;
 	case 4096:	shift = 3;	break;
 	default:
-		printk("ub: Bad sector size %u\n", bsize); /* P3 */
 		rc = -EDOM;
 		goto err_inv_bsize;
 	}
@@ -2023,17 +2005,8 @@
 	sc->work_urb.error_count = 0;
 	sc->work_urb.status = 0;
 
-	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
-		if (rc == -EPIPE) {
-			printk("%s: Stall submitting GetMaxLUN, using 1 LUN\n",
-			     sc->name); /* P3 */
-		} else {
-			printk(KERN_NOTICE
-			     "%s: Unable to submit GetMaxLUN (%d)\n",
-			     sc->name, rc);
-		}
+	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
 		goto err_submit;
-	}
 
 	init_timer(&timer);
 	timer.function = ub_probe_timeout;
@@ -2046,21 +2019,10 @@
 	del_timer_sync(&timer);
 	usb_kill_urb(&sc->work_urb);
 
-	if ((rc = sc->work_urb.status) < 0) {
-		if (rc == -EPIPE) {
-			printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
-			     sc->name); /* P3 */
-		} else {
-			printk(KERN_NOTICE
-			     "%s: Error at GetMaxLUN (%d)\n",
-			     sc->name, rc);
-		}
+	if ((rc = sc->work_urb.status) < 0)
 		goto err_io;
-	}
 
 	if (sc->work_urb.actual_length != 1) {
-		printk("%s: GetMaxLUN returned %d bytes\n", sc->name,
-		    sc->work_urb.actual_length); /* P3 */
 		nluns = 0;
 	} else {
 		if ((nluns = *p) == 55) {
@@ -2071,8 +2033,6 @@
 			if (nluns > UB_MAX_LUNS)
 				nluns = UB_MAX_LUNS;
 		}
-		printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name,
-		    *p, nluns); /* P3 */
 	}
 
 	kfree(p);
@@ -2270,7 +2230,7 @@
 	 * has to succeed, so we clear checks with an additional one here.
 	 * In any case it's not our business how revaliadation is implemented.
 	 */
-	for (i = 0; i < 3; i++) {	/* Retries for benh's key */
+	for (i = 0; i < 3; i++) {  /* Retries for the schwag key from KS'04 */
 		if ((rc = ub_sync_tur(sc, NULL)) <= 0) break;
 		if (rc != 0x6) break;
 		msleep(10);
@@ -2318,7 +2278,6 @@
 		goto err_id;
 
 	lun->udev = sc;
-	list_add(&lun->link, &sc->luns);
 
 	snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)",
 	    lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num);
@@ -2331,7 +2290,6 @@
 	if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL)
 		goto err_diskalloc;
 
-	lun->disk = disk;
 	sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
 	sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
 	disk->major = UB_MAJOR;
@@ -2353,7 +2311,9 @@
 	blk_queue_max_sectors(q, UB_MAX_SECTORS);
 	blk_queue_hardsect_size(q, lun->capacity.bsize);
 
+	lun->disk = disk;
 	q->queuedata = lun;
+	list_add(&lun->link, &sc->luns);
 
 	set_capacity(disk, lun->capacity.nsec);
 	if (lun->removable)
@@ -2366,7 +2326,6 @@
 err_blkqinit:
 	put_disk(disk);
 err_diskalloc:
-	list_del(&lun->link);
 	ub_id_put(lun->id);
 err_id:
 	kfree(lun);
@@ -2379,7 +2338,6 @@
 	struct ub_dev *sc = usb_get_intfdata(intf);
 	struct list_head *p;
 	struct ub_lun *lun;
-	struct gendisk *disk;
 	unsigned long flags;
 
 	/*
@@ -2435,9 +2393,7 @@
 	 */
 	list_for_each (p, &sc->luns) {
 		lun = list_entry(p, struct ub_lun, link);
-		disk = lun->disk;
-		if (disk->flags & GENHD_FL_UP)
-			del_gendisk(disk);
+		del_gendisk(lun->disk);
 		/*
 		 * I wish I could do:
 		 *    set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index f63e07b..b0df4f5 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -747,7 +747,7 @@
  * support.
  */
 static struct vio_device_id viodasd_device_table[] __devinitdata = {
-	{ "viodasd", "" },
+	{ "block", "IBM,iSeries-viodasd" },
 	{ "", "" }
 };
 MODULE_DEVICE_TABLE(vio, viodasd_device_table);
diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
index a71a240..ed8dca8 100644
--- a/drivers/bluetooth/dtl1_cs.c
+++ b/drivers/bluetooth/dtl1_cs.c
@@ -423,6 +423,9 @@
 	nsh.len = skb->len;
 
 	s = bt_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
+	if (!s)
+		return -ENOMEM;
+
 	skb_reserve(s, NSHL);
 	memcpy(skb_put(s, skb->len), skb->data, skb->len);
 	if (skb->len & 0x0001)
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index a0b580c..0f6e7aa 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -1006,7 +1006,7 @@
 
 /* MODULE STUFF ***********************************************************/
 
-int __mcdx_init(void)
+static int __init __mcdx_init(void)
 {
 	int i;
 	int drives = 0;
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index c0f817b..af6b3bf 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -731,7 +731,7 @@
  * support.
  */
 static struct vio_device_id viocd_device_table[] __devinitdata = {
-	{ "viocd", "" },
+	{ "block", "IBM,iSeries-viocd" },
 	{ "", "" }
 };
 MODULE_DEVICE_TABLE(vio, viocd_device_table);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 78d928f..410d70c 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -62,6 +62,23 @@
 	depends on VT && !S390 && !UML
 	default y
 
+config VT_HW_CONSOLE_BINDING
+       bool "Support for binding and unbinding console drivers"
+       depends on HW_CONSOLE
+       default n
+       ---help---
+         The virtual terminal is the device that interacts with the physical
+         terminal through console drivers. On these systems, at least one
+         console driver is loaded. In other configurations, additional console
+         drivers may be enabled, such as the framebuffer console. If more than
+         1 console driver is enabled, setting this to 'y' will allow you to
+         select the console driver that will serve as the backend for the
+         virtual terminals.
+
+	 See <file:Documentation/console/console.txt> for more
+	 information. For framebuffer console users, please refer to
+	 <file:Documentation/fb/fbcon.txt>.
+
 config SERIAL_NONSTANDARD
 	bool "Non-standard serial port support"
 	---help---
@@ -670,20 +687,7 @@
 
 	  If you're not sure, say N.
 
-config HW_RANDOM
-	tristate "Intel/AMD/VIA HW Random Number Generator support"
-	depends on (X86 || IA64) && PCI
-	---help---
-	  This driver provides kernel-side support for the Random Number
-	  Generator hardware found on Intel i8xx-based motherboards,
-	  AMD 76x-based motherboards, and Via Nehemiah CPUs.
-
-	  Provides a character driver, used to read() entropy data.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called hw_random.
-
-	  If unsure, say N.
+source "drivers/char/hw_random/Kconfig"
 
 config NVRAM
 	tristate "/dev/nvram support"
@@ -865,6 +869,7 @@
 config TANBAC_TB0219
 	tristate "TANBAC TB0219 base board support"
 	depends TANBAC_TB022X
+	select GPIO_VR41XX
 
 menu "Ftape, the floppy tape device driver"
 
@@ -934,12 +939,35 @@
 config SCx200_GPIO
 	tristate "NatSemi SCx200 GPIO Support"
 	depends on SCx200
+	select NSC_GPIO
 	help
 	  Give userspace access to the GPIO pins on the National
 	  Semiconductor SCx200 processors.
 
 	  If compiled as a module, it will be called scx200_gpio.
 
+config PC8736x_GPIO
+	tristate "NatSemi PC8736x GPIO Support"
+	depends on X86
+	default SCx200_GPIO	# mostly N
+	select NSC_GPIO		# needed for support routines
+	help
+	  Give userspace access to the GPIO pins on the National
+	  Semiconductor PC-8736x (x=[03456]) SuperIO chip.  The chip
+	  has multiple functional units, inc several managed by
+	  hwmon/pc87360 driver.  Tested with PC-87366
+
+	  If compiled as a module, it will be called pc8736x_gpio.
+
+config NSC_GPIO
+	tristate "NatSemi Base GPIO Support"
+	# selected by SCx200_GPIO and PC8736x_GPIO
+	# what about 2 selectors differing: m != y
+	help
+	  Common support used (and needed) by scx200_gpio and
+	  pc8736x_gpio drivers.  If those drivers are built as
+	  modules, this one will be too, named nsc_gpio
+
 config CS5535_GPIO
 	tristate "AMD CS5535/CS5536 GPIO (Geode Companion Device)"
 	depends on X86_32
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index fb919bf..6e0f446 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -75,13 +75,15 @@
 obj-$(CONFIG_TOSHIBA)		+= toshiba.o
 obj-$(CONFIG_I8K)		+= i8k.o
 obj-$(CONFIG_DS1620)		+= ds1620.o
-obj-$(CONFIG_HW_RANDOM)		+= hw_random.o
+obj-$(CONFIG_HW_RANDOM)		+= hw_random/
 obj-$(CONFIG_FTAPE)		+= ftape/
 obj-$(CONFIG_COBALT_LCD)	+= lcd.o
 obj-$(CONFIG_PPDEV)		+= ppdev.o
 obj-$(CONFIG_NWBUTTON)		+= nwbutton.o
 obj-$(CONFIG_NWFLASH)		+= nwflash.o
 obj-$(CONFIG_SCx200_GPIO)	+= scx200_gpio.o
+obj-$(CONFIG_PC8736x_GPIO)	+= pc8736x_gpio.o
+obj-$(CONFIG_NSC_GPIO)		+= nsc_gpio.o
 obj-$(CONFIG_CS5535_GPIO)	+= cs5535_gpio.o
 obj-$(CONFIG_GPIO_VR41XX)	+= vr41xx_giu.o
 obj-$(CONFIG_TANBAC_TB0219)	+= tb0219.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 7c88c06..9826a39 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -1,7 +1,6 @@
 config AGP
-	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU
+	tristate "/dev/agpgart (AGP Support)"
 	depends on ALPHA || IA64 || PPC || X86
-	default y if GART_IOMMU
 	---help---
 	  AGP (Accelerated Graphics Port) is a bus system mainly used to
 	  connect graphics cards to the rest of the system.
@@ -56,9 +55,9 @@
 	  X on AMD Irongate, 761, and 762 chipsets.
 
 config AGP_AMD64
-	tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU
+	tristate "AMD Opteron/Athlon64 on-CPU GART support" if !IOMMU
 	depends on AGP && X86
-	default y if GART_IOMMU
+	default y if IOMMU
 	help
 	  This option gives you AGP support for the GLX component of
 	  X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
index 2b5838e..b4e00a3 100644
--- a/drivers/char/agp/alpha-agp.c
+++ b/drivers/char/agp/alpha-agp.c
@@ -46,12 +46,6 @@
 };
 
 
-static int alpha_core_agp_nop(void)
-{
-	/* just return success */
-	return 0;
-}
-
 static int alpha_core_agp_fetch_size(void)
 {
 	return alpha_core_agp_sizes[0].size;
@@ -120,6 +114,11 @@
 	return status;
 }
 
+static int alpha_core_agp_create_free_gatt_table(struct agp_bridge_data *a)
+{
+	return 0;
+}
+
 struct agp_bridge_driver alpha_core_agp_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= alpha_core_agp_sizes,
@@ -135,8 +134,8 @@
 	.tlb_flush		= alpha_core_agp_tlbflush,
 	.mask_memory		= agp_generic_mask_memory,
 	.cache_flush		= global_cache_flush,
-	.create_gatt_table	= alpha_core_agp_nop,
-	.free_gatt_table	= alpha_core_agp_nop,
+	.create_gatt_table	= alpha_core_agp_create_free_gatt_table,
+	.free_gatt_table	= alpha_core_agp_create_free_gatt_table,
 	.insert_memory		= alpha_core_agp_insert_memory,
 	.remove_memory		= alpha_core_agp_remove_memory,
 	.alloc_by_type		= agp_generic_alloc_by_type,
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 1f77665..51d0d56 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -118,7 +118,7 @@
 	return retval;
 }
 
-/* Since we don't need contigious memory we just try
+/* Since we don't need contiguous memory we just try
  * to get the gatt table once
  */
 
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index ac3c33a..f690ee8 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -15,11 +15,9 @@
 #include <linux/agp_backend.h>
 #include <linux/mmzone.h>
 #include <asm/page.h>		/* PAGE_SIZE */
+#include <asm/k8.h>
 #include "agp.h"
 
-/* Will need to be increased if AMD64 ever goes >8-way. */
-#define MAX_HAMMER_GARTS   8
-
 /* PTE bits. */
 #define GPTE_VALID	1
 #define GPTE_COHERENT	2
@@ -53,28 +51,12 @@
 #define ULI_X86_64_HTT_FEA_REG		0x50
 #define ULI_X86_64_ENU_SCR_REG		0x54
 
-static int nr_garts;
-static struct pci_dev * hammers[MAX_HAMMER_GARTS];
-
 static struct resource *aperture_resource;
 static int __initdata agp_try_unsupported = 1;
 
-#define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++)
-
-static void flush_amd64_tlb(struct pci_dev *dev)
-{
-	u32 tmp;
-
-	pci_read_config_dword (dev, AMD64_GARTCACHECTL, &tmp);
-	tmp |= INVGART;
-	pci_write_config_dword (dev, AMD64_GARTCACHECTL, tmp);
-}
-
 static void amd64_tlbflush(struct agp_memory *temp)
 {
-	int gart_iterator;
-	for_each_nb()
-		flush_amd64_tlb(hammers[gart_iterator]);
+	k8_flush_garts();
 }
 
 static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
@@ -153,7 +135,7 @@
 	u32 temp;
 	struct aper_size_info_32 *values;
 
-	dev = hammers[0];
+	dev = k8_northbridges[0];
 	if (dev==NULL)
 		return 0;
 
@@ -201,9 +183,6 @@
 	tmp &= ~(DISGARTCPU | DISGARTIO);
 	pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp);
 
-	/* keep CPU's coherent. */
-	flush_amd64_tlb (hammer);
-
 	return aper_base;
 }
 
@@ -222,13 +201,14 @@
 static int amd_8151_configure(void)
 {
 	unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
-	int gart_iterator;
+	int i;
 
 	/* Configure AGP regs in each x86-64 host bridge. */
-	for_each_nb() {
+        for (i = 0; i < num_k8_northbridges; i++) {
 		agp_bridge->gart_bus_addr =
-				amd64_configure(hammers[gart_iterator],gatt_bus);
+				amd64_configure(k8_northbridges[i], gatt_bus);
 	}
+	k8_flush_garts();
 	return 0;
 }
 
@@ -236,12 +216,13 @@
 static void amd64_cleanup(void)
 {
 	u32 tmp;
-	int gart_iterator;
-	for_each_nb() {
+	int i;
+        for (i = 0; i < num_k8_northbridges; i++) {
+		struct pci_dev *dev = k8_northbridges[i];
 		/* disable gart translation */
-		pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp);
+		pci_read_config_dword (dev, AMD64_GARTAPERTURECTL, &tmp);
 		tmp &= ~AMD64_GARTEN;
-		pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp);
+		pci_write_config_dword (dev, AMD64_GARTAPERTURECTL, tmp);
 	}
 }
 
@@ -311,7 +292,7 @@
 /*
  * W*s centric BIOS sometimes only set up the aperture in the AGP
  * bridge, not the northbridge. On AMD64 this is handled early
- * in aperture.c, but when GART_IOMMU is not enabled or we run
+ * in aperture.c, but when IOMMU is not enabled or we run
  * on a 32bit kernel this needs to be redone.
  * Unfortunately it is impossible to fix the aperture here because it's too late
  * to allocate that much memory. But at least error out cleanly instead of
@@ -361,17 +342,15 @@
 
 static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
 {
-	struct pci_dev *loop_dev = NULL;
-	int i = 0;
+	int i;
 
-	/* cache pci_devs of northbridges. */
-	while ((loop_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
-			!= NULL) {
-		if (i == MAX_HAMMER_GARTS) {
-			printk(KERN_ERR PFX "Too many northbridges for AGP\n");
-			return -1;
-		}
-		if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) {
+	if (cache_k8_northbridges() < 0)
+		return -ENODEV;
+
+	i = 0;
+	for (i = 0; i < num_k8_northbridges; i++) {
+		struct pci_dev *dev = k8_northbridges[i];
+		if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
 			printk(KERN_ERR PFX "No usable aperture found.\n");
 #ifdef __x86_64__
 			/* should port this to i386 */
@@ -379,10 +358,8 @@
 #endif
 			return -1;
 		}
-		hammers[i++] = loop_dev;
 	}
-		nr_garts = i;
-	return i == 0 ? -1 : 0;
+	return 0;
 }
 
 /* Handle AMD 8151 quirks */
@@ -450,7 +427,7 @@
 	}
 
 	/* shadow x86-64 registers into ULi registers */
-	pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &httfea);
+	pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
 
 	/* if x86-64 aperture base is beyond 4G, exit here */
 	if ((httfea & 0x7fff) >> (32 - 25))
@@ -513,7 +490,7 @@
 	pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
 
 	/* shadow x86-64 registers into NVIDIA registers */
-	pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase);
+	pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase);
 
 	/* if x86-64 aperture base is beyond 4G, exit here */
 	if ( (apbase & 0x7fff) >> (32 - 25) ) {
@@ -754,10 +731,6 @@
 int __init agp_amd64_init(void)
 {
 	int err = 0;
-	static struct pci_device_id amd64nb[] = {
-		{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
-		{ },
-	};
 
 	if (agp_off)
 		return -EINVAL;
@@ -774,7 +747,7 @@
 		}
 
 		/* First check that we have at least one AMD64 NB */
-		if (!pci_dev_present(amd64nb))
+		if (!pci_dev_present(k8_nb_ids))
 			return -ENODEV;
 
 		/* Look for any AGP bridge */
@@ -802,7 +775,7 @@
 
 /* On AMD64 the PCI driver needs to initialize this driver early
    for the IOMMU, so it has to be called via a backdoor. */
-#ifndef CONFIG_GART_IOMMU
+#ifndef CONFIG_IOMMU
 module_init(agp_amd64_init);
 module_exit(agp_amd64_cleanup);
 #endif
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 06fd10b..16056434 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -261,7 +261,7 @@
 #endif
 
 /*
- *Since we don't need contigious memory we just try
+ *Since we don't need contiguous memory we just try
  * to get the gatt table once
  */
 
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 86a966b..b788b0a 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -177,7 +177,7 @@
 
 
 /*
- * Since we don't need contigious memory we just try
+ * Since we don't need contiguous memory we just try
  * to get the gatt table once
  */
 
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 4e1891e..a92ab53 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -809,12 +809,10 @@
 				case U32_APER_SIZE:
 					bridge->current_size = A_IDX32(bridge);
 					break;
-					/* This case will never really happen. */
+				/* These cases will never really happen. */
 				case FIXED_APER_SIZE:
 				case LVL2_APER_SIZE:
 				default:
-					bridge->current_size =
-					    bridge->current_size;
 					break;
 				}
 				temp = bridge->current_size;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 8c4c6ef..907fb66 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -497,7 +497,7 @@
 			info = buffer.pointer;
 			info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0';
 			match = (strcmp(info->hardware_id.value, "HWP0001") == 0);
-			ACPI_MEM_FREE(info);
+			kfree(info);
 			if (match) {
 				status = hp_acpi_csr_space(handle, &sba_hpa, &length);
 				if (ACPI_SUCCESS(status))
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index bddcae5..61ac380 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -736,7 +736,7 @@
 static int intel_i915_fetch_size(void)
 {
 	struct aper_size_info_fixed *values;
-	u32 temp, offset = 0;
+	u32 temp, offset;
 
 #define I915_256MB_ADDRESS_MASK (1<<27)
 
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index cfa7922..d73be4c 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -329,9 +329,8 @@
 
 static void __devexit agp_sgi_cleanup(void)
 {
-	if (sgi_tioca_agp_bridges)
-		kfree(sgi_tioca_agp_bridges);
-	sgi_tioca_agp_bridges=NULL;
+	kfree(sgi_tioca_agp_bridges);
+	sgi_tioca_agp_bridges = NULL;
 }
 
 module_init(agp_sgi_init);
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 9846def..1de1b12 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -329,7 +329,7 @@
 	/* turn off AGP on the bridge */
 	agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
 	pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
-	bridge->dev_private_data = (void *)cmd;
+	bridge->dev_private_data = (void *)(long)cmd;
 	if (cmd & PCI_AGP_COMMAND_AGP) {
 		printk("uninorth-agp: disabling AGP on bridge %s\n",
 				pci_name(pdev));
@@ -351,7 +351,7 @@
 	if (bridge == NULL)
 		return -ENODEV;
 
-	command = (u32)bridge->dev_private_data;
+	command = (long)bridge->dev_private_data;
 	bridge->dev_private_data = NULL;
 	if (!(command & PCI_AGP_COMMAND_AGP))
 		return 0;
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index a370e7a..9275d5e 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -166,11 +166,7 @@
 	return boardno + 1;
 }
 
-#ifdef MODULE
-
-#define applicom_init init_module
-
-void cleanup_module(void)
+static void __exit applicom_exit(void)
 {
 	unsigned int i;
 
@@ -188,9 +184,7 @@
 	}
 }
 
-#endif				/* MODULE */
-
-int __init applicom_init(void)
+static int __init applicom_init(void)
 {
 	int i, numisa = 0;
 	struct pci_dev *dev = NULL;
@@ -355,10 +349,9 @@
 	return ret;
 }
 
+module_init(applicom_init);
+module_exit(applicom_exit);
 
-#ifndef MODULE
-__initcall(applicom_init);
-#endif
 
 static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
 {
@@ -851,28 +844,3 @@
 	return 0;
 }
 
-#ifndef MODULE
-static int __init applicom_setup(char *str)
-{
-	int ints[4];
-
-	(void) get_options(str, 4, ints);
-
-	if (ints[0] > 2) {
-		printk(KERN_WARNING "Too many arguments to 'applicom=', expected mem,irq only.\n");
-	}
-
-	if (ints[0] < 2) {
-		printk(KERN_INFO"applicom numargs: %d\n", ints[0]);
-		return 0;
-	}
-
-	mem = ints[1];
-	irq = ints[2];
-	return 1;
-}
-
-__setup("applicom=", applicom_setup);
-
-#endif				/* MODULE */
-
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index cc7acf8..122e7a7 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2833,9 +2833,8 @@
         return 0;
     }
         
-    if (!tty || !info->xmit_buf || !tmp_buf){
-        return 0;
-    }
+    if (!info->xmit_buf || !tmp_buf)
+	return 0;
 
     CY_LOCK(info, flags);
     while (1) {
@@ -2884,7 +2883,7 @@
     if (serial_paranoia_check(info, tty->name, "cy_put_char"))
         return;
 
-    if (!tty || !info->xmit_buf)
+    if (!info->xmit_buf)
         return;
 
     CY_LOCK(info, flags);
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h
index 6543b9a..d117cc9 100644
--- a/drivers/char/drm/drm_memory_debug.h
+++ b/drivers/char/drm/drm_memory_debug.h
@@ -43,7 +43,7 @@
 	unsigned long bytes_freed;
 } drm_mem_stats_t;
 
-static spinlock_t drm_mem_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(drm_mem_lock);
 static unsigned long drm_ram_available = 0;	/* In pages */
 static unsigned long drm_ram_used = 0;
 static drm_mem_stats_t drm_mem_stats[] =
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 9f4b8ce..a94233b 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -758,7 +758,9 @@
 	[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
 	[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
 	[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
-	[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }
+	[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
+	[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
+	[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
 };
 
 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 4cb3da5..5aa3e0e 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -124,6 +124,8 @@
 #define DRM_I915_INIT_HEAP	0x0a
 #define DRM_I915_CMDBUFFER	0x0b
 #define DRM_I915_DESTROY_HEAP	0x0c
+#define DRM_I915_SET_VBLANK_PIPE	0x0d
+#define DRM_I915_GET_VBLANK_PIPE	0x0e
 
 #define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
 #define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -138,6 +140,8 @@
 #define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
 #define DRM_IOCTL_I915_CMDBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
 #define DRM_IOCTL_I915_DESTROY_HEAP	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
+#define DRM_IOCTL_I915_SET_VBLANK_PIPE	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
+#define DRM_IOCTL_I915_GET_VBLANK_PIPE	DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -224,4 +228,13 @@
 	int region;
 } drm_i915_mem_destroy_heap_t;
 
+/* Allow X server to configure which pipes to monitor for vblank signals
+ */
+#define	DRM_I915_VBLANK_PIPE_A	1
+#define	DRM_I915_VBLANK_PIPE_B	2
+
+typedef struct drm_i915_vblank_pipe {
+	int pipe;
+} drm_i915_vblank_pipe_t;
+
 #endif				/* _I915_DRM_H_ */
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 7a65666..2d56503 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -45,9 +45,10 @@
  * 1.2: Add Power Management
  * 1.3: Add vblank support
  * 1.4: Fix cmdbuffer path, add heap destroy
+ * 1.5: Add vblank pipe configuration
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		4
+#define DRIVER_MINOR		5
 #define DRIVER_PATCHLEVEL	0
 
 typedef struct _drm_i915_ring_buffer {
@@ -96,6 +97,7 @@
 	int allow_batchbuffer;
 	struct mem_block *agp_heap;
 	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
+	int vblank_pipe;
 } drm_i915_private_t;
 
 extern drm_ioctl_desc_t i915_ioctls[];
@@ -119,6 +121,8 @@
 extern void i915_driver_irq_preinstall(drm_device_t * dev);
 extern void i915_driver_irq_postinstall(drm_device_t * dev);
 extern void i915_driver_irq_uninstall(drm_device_t * dev);
+extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
+extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
 
 /* i915_mem.c */
 extern int i915_mem_alloc(DRM_IOCTL_ARGS);
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index a752afd..cd96cfa 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -44,7 +44,8 @@
 	u16 temp;
 
 	temp = I915_READ16(I915REG_INT_IDENTITY_R);
-	temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG);
+
+	temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
 
 	DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
 
@@ -58,7 +59,7 @@
 	if (temp & USER_INT_FLAG)
 		DRM_WAKEUP(&dev_priv->irq_queue);
 
-	if (temp & VSYNC_PIPEA_FLAG) {
+	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
 		atomic_inc(&dev->vbl_received);
 		DRM_WAKEUP(&dev->vbl_queue);
 		drm_vbl_send_signals(dev);
@@ -182,6 +183,68 @@
 	return i915_wait_irq(dev, irqwait.irq_seq);
 }
 
+static int i915_enable_interrupt (drm_device_t *dev)
+{
+	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	u16 flag;
+
+	flag = 0;
+	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
+		flag |= VSYNC_PIPEA_FLAG;
+	if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
+		flag |= VSYNC_PIPEB_FLAG;
+	if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) {
+		DRM_ERROR("%s called with invalid pipe 0x%x\n",
+			  __FUNCTION__, dev_priv->vblank_pipe);
+		return DRM_ERR(EINVAL);
+	}
+	I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
+	return 0;
+}
+
+/* Set the vblank monitor pipe
+ */
+int i915_vblank_pipe_set(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_vblank_pipe_t pipe;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data,
+				 sizeof(pipe));
+
+	dev_priv->vblank_pipe = pipe.pipe;
+	return i915_enable_interrupt (dev);
+}
+
+int i915_vblank_pipe_get(DRM_IOCTL_ARGS)
+{
+	DRM_DEVICE;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_vblank_pipe_t pipe;
+	u16 flag;
+
+	if (!dev_priv) {
+		DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
+		return DRM_ERR(EINVAL);
+	}
+
+	flag = I915_READ(I915REG_INT_ENABLE_R);
+	pipe.pipe = 0;
+	if (flag & VSYNC_PIPEA_FLAG)
+		pipe.pipe |= DRM_I915_VBLANK_PIPE_A;
+	if (flag & VSYNC_PIPEB_FLAG)
+		pipe.pipe |= DRM_I915_VBLANK_PIPE_B;
+	DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe,
+				 sizeof(pipe));
+	return 0;
+}
+
 /* drm_dma.h hooks
 */
 void i915_driver_irq_preinstall(drm_device_t * dev)
@@ -197,7 +260,7 @@
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 
-	I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG);
+	i915_enable_interrupt(dev);
 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 }
 
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
index 7f949c9..5ad43ba 100644
--- a/drivers/char/drm/radeon_cp.c
+++ b/drivers/char/drm/radeon_cp.c
@@ -39,7 +39,7 @@
 static int radeon_do_cleanup_cp(drm_device_t * dev);
 
 /* CP microcode (from ATI) */
-static u32 R200_cp_microcode[][2] = {
+static const u32 R200_cp_microcode[][2] = {
 	{0x21007000, 0000000000},
 	{0x20007000, 0000000000},
 	{0x000000ab, 0x00000004},
@@ -298,7 +298,7 @@
 	{0000000000, 0000000000},
 };
 
-static u32 radeon_cp_microcode[][2] = {
+static const u32 radeon_cp_microcode[][2] = {
 	{0x21007000, 0000000000},
 	{0x20007000, 0000000000},
 	{0x000000b4, 0x00000004},
@@ -557,7 +557,7 @@
 	{0000000000, 0000000000},
 };
 
-static u32 R300_cp_microcode[][2] = {
+static const u32 R300_cp_microcode[][2] = {
 	{0x4200e000, 0000000000},
 	{0x4000e000, 0000000000},
 	{0x000000af, 0x00000008},
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
index c8e279e..8d6350d 100644
--- a/drivers/char/drm/radeon_drm.h
+++ b/drivers/char/drm/radeon_drm.h
@@ -161,7 +161,8 @@
 #define R200_EMIT_PP_TXCTLALL_3                     91
 #define R200_EMIT_PP_TXCTLALL_4                     92
 #define R200_EMIT_PP_TXCTLALL_5                     93
-#define RADEON_MAX_STATE_PACKETS                    94
+#define R200_EMIT_VAP_PVS_CNTL                      94
+#define RADEON_MAX_STATE_PACKETS                    95
 
 /* Commands understood by cmd_buffer ioctl.  More can be added but
  * obviously these can't be removed or changed:
@@ -176,6 +177,7 @@
 #define RADEON_CMD_WAIT         8	/* emit hw wait commands -- note:
 					 *  doesn't make the cpu wait, just
 					 *  the graphics hardware */
+#define RADEON_CMD_VECLINEAR	9       /* another r200 stopgap */
 
 typedef union {
 	int i;
@@ -192,6 +194,9 @@
 		unsigned char cmd_type, offset, stride, count;
 	} vectors;
 	struct {
+		unsigned char cmd_type, addr_lo, addr_hi, count;
+	} veclinear;
+	struct {
 		unsigned char cmd_type, buf_idx, pad0, pad1;
 	} dma;
 	struct {
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 78345ce..e5a256f 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -38,7 +38,7 @@
 
 #define DRIVER_NAME		"radeon"
 #define DRIVER_DESC		"ATI Radeon"
-#define DRIVER_DATE		"20060225"
+#define DRIVER_DATE		"20060524"
 
 /* Interface history:
  *
@@ -93,9 +93,11 @@
  * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
  * 1.23- Add new radeon memory map work from benh
  * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
+ * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
+ *       new packet type)
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		24
+#define DRIVER_MINOR		25
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -884,6 +886,8 @@
 #define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
 #define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
 
+#define RADEON_SE_TCL_STATE_FLUSH           0x2284
+
 #define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
 #define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT                 0x00000012
@@ -905,6 +909,8 @@
 #define R200_PP_AFS_0                     0x2f80
 #define R200_PP_AFS_1                     0x2f00	/* same as txcblend_0 */
 
+#define R200_VAP_PVS_CNTL_1               0x22D0
+
 /* Constants */
 #define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
 
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
index c5b8f77..5bb2234 100644
--- a/drivers/char/drm/radeon_state.c
+++ b/drivers/char/drm/radeon_state.c
@@ -249,6 +249,7 @@
 	case R200_EMIT_PP_TXCTLALL_3:
 	case R200_EMIT_PP_TXCTLALL_4:
 	case R200_EMIT_PP_TXCTLALL_5:
+	case R200_EMIT_VAP_PVS_CNTL:
 		/* These packets don't contain memory offsets */
 		break;
 
@@ -626,6 +627,7 @@
 	{R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
 	{R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
 	{R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+	{R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
 };
 
 /* ================================================================
@@ -2595,7 +2597,8 @@
 	int stride = header.vectors.stride;
 	RING_LOCALS;
 
-	BEGIN_RING(3 + sz);
+	BEGIN_RING(5 + sz);
+	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
 	OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
@@ -2607,6 +2610,32 @@
 	return 0;
 }
 
+static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
+					  drm_radeon_cmd_header_t header,
+					  drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	int sz = header.veclinear.count * 4;
+	int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
+	RING_LOCALS;
+
+        if (!sz)
+                return 0;
+        if (sz * 4 > cmdbuf->bufsz)
+                return DRM_ERR(EINVAL);
+
+	BEGIN_RING(5 + sz);
+	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+	OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+	OUT_RING_TABLE(cmdbuf->buf, sz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
 static int radeon_emit_packet3(drm_device_t * dev,
 			       drm_file_t * filp_priv,
 			       drm_radeon_kcmd_buffer_t *cmdbuf)
@@ -2865,6 +2894,14 @@
 				goto err;
 			}
 			break;
+		case RADEON_CMD_VECLINEAR:
+			DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
+			if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_veclinear failed\n");
+				goto err;
+			}
+			break;
+
 		default:
 			DRM_ERROR("bad cmd_type %d at %p\n",
 				  header.header.cmd_type,
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c
index b7f1745..78a81a4 100644
--- a/drivers/char/drm/via_dmablit.c
+++ b/drivers/char/drm/via_dmablit.c
@@ -557,7 +557,7 @@
 		blitq->num_outstanding = 0;
 		blitq->is_active = 0;
 		blitq->aborting = 0;
-		blitq->blit_lock = SPIN_LOCK_UNLOCKED;
+		spin_lock_init(&blitq->blit_lock);
 		for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) {
 			DRM_INIT_WAITQUEUE(blitq->blit_queue + j);
 		}
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 9cad850..dc0602a 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -80,7 +80,7 @@
 /* The ISA boards do window flipping into the same spaces so its only sane
    with a single lock. It's still pretty efficient */
 
-static spinlock_t epca_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(epca_lock);
 
 /* -----------------------------------------------------------------------
 	MAXBOARDS is typically 12, but ISA and EISA cards are restricted to 
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 09dc4b0..922174d 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1212,7 +1212,7 @@
 	if (serial_paranoia_check(info, tty->name, "rs_put_char"))
 		return;
 
-	if (!tty || !info->xmit_buf)
+	if (!info->xmit_buf)
 		return;
 
 	spin_lock_irqsave(&info->lock, flags);
@@ -1256,7 +1256,7 @@
 	if (serial_paranoia_check(info, tty->name, "rs_write"))
 		return 0;
 
-	if (!tty || !info->xmit_buf)
+	if (!info->xmit_buf)
 		return 0;
 	    
 	while (1) {
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index ac62641..d69f2ad 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -117,12 +117,12 @@
 __setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
 #endif /* not MODULE */
 
-#if defined(CONFIG_X86) || defined(CONFIG_S390)
+#if defined(CONFIG_X86_64) || defined(CONFIG_S390)
 # define HAVE_MONOTONIC
 # define TIMER_FREQ 1000000000ULL
 #elif defined(CONFIG_IA64)
 # define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq)
-#elif defined(CONFIG_PPC64)
+#else
 # define TIMER_FREQ (HZ*loops_per_jiffy)
 #endif
 
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index ef140eb..07473cd 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -925,11 +925,8 @@
 	status = acpi_resource_to_address64(res, &addr);
 
 	if (ACPI_SUCCESS(status)) {
-		unsigned long size;
-
-		size = addr.maximum - addr.minimum + 1;
 		hdp->hd_phys_address = addr.minimum;
-		hdp->hd_address = ioremap(addr.minimum, size);
+		hdp->hd_address = ioremap(addr.minimum, addr.address_length);
 
 		if (hpet_is_known(hdp)) {
 			printk(KERN_DEBUG "%s: 0x%lx is busy\n",
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 2b6a56b..a5c6a9d 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -553,7 +553,6 @@
 
 #define HVC_POLL_READ	0x00000001
 #define HVC_POLL_WRITE	0x00000002
-#define HVC_POLL_QUICK	0x00000004
 
 static int hvc_poll(struct hvc_struct *hp)
 {
@@ -568,6 +567,7 @@
 	/* Push pending writes */
 	if (hp->n_outbuf > 0)
 		hvc_push(hp);
+
 	/* Reschedule us if still some write pending */
 	if (hp->n_outbuf > 0)
 		poll_mask |= HVC_POLL_WRITE;
@@ -680,7 +680,7 @@
 			poll_mask |= HVC_POLL_READ;
 		if (hvc_kicked)
 			continue;
-		if (poll_mask & HVC_POLL_QUICK) {
+		if (poll_mask & HVC_POLL_WRITE) {
 			yield();
 			continue;
 		}
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c
index 83364ea..57106e02 100644
--- a/drivers/char/hvc_rtas.c
+++ b/drivers/char/hvc_rtas.c
@@ -41,37 +41,28 @@
 #define hvc_rtas_cookie 0x67781e15
 struct hvc_struct *hvc_rtas_dev;
 
-#define RTASCONS_PUT_ATTEMPTS  16
-
 static int rtascons_put_char_token = RTAS_UNKNOWN_SERVICE;
 static int rtascons_get_char_token = RTAS_UNKNOWN_SERVICE;
-static int rtascons_put_delay = 100;
-module_param_named(put_delay, rtascons_put_delay, int, 0644);
 
-static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf, int count)
-{
-	int done;
-
-	/* if there is more than one character to be displayed, wait a bit */
-	for (done = 0; done < count; done++) {
-		int result;
-		result = rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[done]);
-		if (result)
-			break;
-	}
-	/* the calling routine expects to receive the number of bytes sent */
-	return done;
-}
-
-static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
+static inline int hvc_rtas_write_console(uint32_t vtermno, const char *buf,
+		int count)
 {
 	int i;
 
 	for (i = 0; i < count; i++) {
-		int c, err;
+		if (rtas_call(rtascons_put_char_token, 1, 1, NULL, buf[i]))
+			break;
+	}
 
-		err = rtas_call(rtascons_get_char_token, 0, 2, &c);
-		if (err)
+	return i;
+}
+
+static int hvc_rtas_read_console(uint32_t vtermno, char *buf, int count)
+{
+	int i, c;
+
+	for (i = 0; i < count; i++) {
+		if (rtas_call(rtascons_get_char_token, 0, 2, &c))
 			break;
 
 		buf[i] = c;
@@ -106,7 +97,9 @@
 	hp = hvc_alloc(hvc_rtas_cookie, NO_IRQ, &hvc_rtas_get_put_ops);
 	if (IS_ERR(hp))
 		return PTR_ERR(hp);
+
 	hvc_rtas_dev = hp;
+
 	return 0;
 }
 module_init(hvc_rtas_init);
@@ -114,8 +107,8 @@
 /* This will tear down the tty portion of the driver */
 static void __exit hvc_rtas_exit(void)
 {
-	/* Really the fun isn't over until the worker thread breaks down and the
-	 * tty cleans up */
+	/* Really the fun isn't over until the worker thread breaks down and
+	 * the tty cleans up */
 	if (hvc_rtas_dev)
 		hvc_remove(hvc_rtas_dev);
 }
@@ -127,12 +120,14 @@
 	rtascons_put_char_token = rtas_token("put-term-char");
 	if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE)
 		return -EIO;
+
 	rtascons_get_char_token = rtas_token("get-term-char");
 	if (rtascons_get_char_token == RTAS_UNKNOWN_SERVICE)
 		return -EIO;
 
-	hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops );
+	hvc_instantiate(hvc_rtas_cookie, 0, &hvc_rtas_get_put_ops);
 	add_preferred_console("hvc", 0, NULL);
+
 	return 0;
 }
 console_initcall(hvc_rtas_console_init);
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index 8d97b39..afa26b6 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -1320,11 +1320,12 @@
 static int hvcs_alloc_index_list(int n)
 {
 	int i;
+
 	hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
 	if (!hvcs_index_list)
 		return -ENOMEM;
 	hvcs_index_count = n;
-	for(i = 0; i < hvcs_index_count; i++)
+	for (i = 0; i < hvcs_index_count; i++)
 		hvcs_index_list[i] = -1;
 	return 0;
 }
@@ -1332,11 +1333,9 @@
 static void hvcs_free_index_list(void)
 {
 	/* Paranoia check to be thorough. */
-	if (hvcs_index_list) {
-		kfree(hvcs_index_list);
-		hvcs_index_list = NULL;
-		hvcs_index_count = 0;
-	}
+	kfree(hvcs_index_list);
+	hvcs_index_list = NULL;
+	hvcs_index_count = 0;
 }
 
 static int __init hvcs_module_init(void)
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index a952218..a0370ed 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -1179,7 +1179,7 @@
 	if (tty_register_driver(hvsi_driver))
 		panic("Couldn't register hvsi console driver\n");
 
-	printk(KERN_INFO "HVSI: registered %i devices\n", hvsi_count);
+	printk(KERN_DEBUG "HVSI: registered %i devices\n", hvsi_count);
 
 	return 0;
 }
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
deleted file mode 100644
index 29dc87e..0000000
--- a/drivers/char/hw_random.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
-        Added support for the AMD Geode LX RNG
-	(c) Copyright 2004-2005 Advanced Micro Devices, Inc.
-
-	derived from
-
- 	Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
-	(c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
- 
- 	derived from
- 
-        Hardware driver for the AMD 768 Random Number Generator (RNG)
-        (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
-
- 	derived from
- 
-	Hardware driver for Intel i810 Random Number Generator (RNG)
-	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
-	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
-
-	Please read Documentation/hw_random.txt for details on use.
-
-	----------------------------------------------------------
-	This software may be used and distributed according to the terms
-        of the GNU General Public License, incorporated herein by reference.
-
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/random.h>
-#include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#ifdef __i386__
-#include <asm/msr.h>
-#include <asm/cpufeature.h>
-#endif
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-
-/*
- * core module and version information
- */
-#define RNG_VERSION "1.0.0"
-#define RNG_MODULE_NAME "hw_random"
-#define RNG_DRIVER_NAME   RNG_MODULE_NAME " hardware driver " RNG_VERSION
-#define PFX RNG_MODULE_NAME ": "
-
-
-/*
- * debugging macros
- */
-
-/* pr_debug() collapses to a no-op if DEBUG is not defined */
-#define DPRINTK(fmt, args...) pr_debug(PFX "%s: " fmt, __FUNCTION__ , ## args)
-
-
-#undef RNG_NDEBUG        /* define to enable lightweight runtime checks */
-#ifdef RNG_NDEBUG
-#define assert(expr)							\
-		if(!(expr)) {						\
-		printk(KERN_DEBUG PFX "Assertion failed! %s,%s,%s,"	\
-		"line=%d\n", #expr, __FILE__, __FUNCTION__, __LINE__);	\
-		}
-#else
-#define assert(expr)
-#endif
-
-#define RNG_MISCDEV_MINOR		183 /* official */
-
-static int rng_dev_open (struct inode *inode, struct file *filp);
-static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
-				loff_t * offp);
-
-static int __init intel_init (struct pci_dev *dev);
-static void intel_cleanup(void);
-static unsigned int intel_data_present (void);
-static u32 intel_data_read (void);
-
-static int __init amd_init (struct pci_dev *dev);
-static void amd_cleanup(void);
-static unsigned int amd_data_present (void);
-static u32 amd_data_read (void);
-
-#ifdef __i386__
-static int __init via_init(struct pci_dev *dev);
-static void via_cleanup(void);
-static unsigned int via_data_present (void);
-static u32 via_data_read (void);
-#endif
-
-static int __init geode_init(struct pci_dev *dev);
-static void geode_cleanup(void);
-static unsigned int geode_data_present (void);
-static u32 geode_data_read (void);
-
-struct rng_operations {
-	int (*init) (struct pci_dev *dev);
-	void (*cleanup) (void);
-	unsigned int (*data_present) (void);
-	u32 (*data_read) (void);
-	unsigned int n_bytes; /* number of bytes per ->data_read */
-};
-static struct rng_operations *rng_ops;
-
-static struct file_operations rng_chrdev_ops = {
-	.owner		= THIS_MODULE,
-	.open		= rng_dev_open,
-	.read		= rng_dev_read,
-};
-
-
-static struct miscdevice rng_miscdev = {
-	RNG_MISCDEV_MINOR,
-	RNG_MODULE_NAME,
-	&rng_chrdev_ops,
-};
-
-enum {
-	rng_hw_none,
-	rng_hw_intel,
-	rng_hw_amd,
-#ifdef __i386__
-	rng_hw_via,
-#endif
-	rng_hw_geode,
-};
-
-static struct rng_operations rng_vendor_ops[] = {
-	/* rng_hw_none */
-	{ },
-
-	/* rng_hw_intel */
-	{ intel_init, intel_cleanup, intel_data_present,
-	  intel_data_read, 1 },
-
-	/* rng_hw_amd */
-	{ amd_init, amd_cleanup, amd_data_present, amd_data_read, 4 },
-
-#ifdef __i386__
-	/* rng_hw_via */
-	{ via_init, via_cleanup, via_data_present, via_data_read, 1 },
-#endif
-
-	/* rng_hw_geode */
-	{ geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 }
-};
-
-/*
- * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
- */
-static struct pci_device_id rng_pci_tbl[] = {
-	{ 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
-	{ 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
-
-	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
-	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
-	{ 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
-	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
-	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
-	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
-
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode },
-
-	{ 0, },	/* terminate list */
-};
-MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
-
-
-/***********************************************************************
- *
- * Intel RNG operations
- *
- */
-
-/*
- * RNG registers (offsets from rng_mem)
- */
-#define INTEL_RNG_HW_STATUS			0
-#define         INTEL_RNG_PRESENT		0x40
-#define         INTEL_RNG_ENABLED		0x01
-#define INTEL_RNG_STATUS			1
-#define         INTEL_RNG_DATA_PRESENT		0x01
-#define INTEL_RNG_DATA				2
-
-/*
- * Magic address at which Intel PCI bridges locate the RNG
- */
-#define INTEL_RNG_ADDR				0xFFBC015F
-#define INTEL_RNG_ADDR_LEN			3
-
-/* token to our ioremap'd RNG register area */
-static void __iomem *rng_mem;
-
-static inline u8 intel_hwstatus (void)
-{
-	assert (rng_mem != NULL);
-	return readb (rng_mem + INTEL_RNG_HW_STATUS);
-}
-
-static inline u8 intel_hwstatus_set (u8 hw_status)
-{
-	assert (rng_mem != NULL);
-	writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS);
-	return intel_hwstatus ();
-}
-
-static unsigned int intel_data_present(void)
-{
-	assert (rng_mem != NULL);
-
-	return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ?
-		1 : 0;
-}
-
-static u32 intel_data_read(void)
-{
-	assert (rng_mem != NULL);
-
-	return readb (rng_mem + INTEL_RNG_DATA);
-}
-
-static int __init intel_init (struct pci_dev *dev)
-{
-	int rc;
-	u8 hw_status;
-
-	DPRINTK ("ENTER\n");
-
-	rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
-	if (rng_mem == NULL) {
-		printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");
-		rc = -EBUSY;
-		goto err_out;
-	}
-
-	/* Check for Intel 82802 */
-	hw_status = intel_hwstatus ();
-	if ((hw_status & INTEL_RNG_PRESENT) == 0) {
-		printk (KERN_ERR PFX "RNG not detected\n");
-		rc = -ENODEV;
-		goto err_out_free_map;
-	}
-
-	/* turn RNG h/w on, if it's off */
-	if ((hw_status & INTEL_RNG_ENABLED) == 0)
-		hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED);
-	if ((hw_status & INTEL_RNG_ENABLED) == 0) {
-		printk (KERN_ERR PFX "cannot enable RNG, aborting\n");
-		rc = -EIO;
-		goto err_out_free_map;
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out_free_map:
-	iounmap (rng_mem);
-	rng_mem = NULL;
-err_out:
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-static void intel_cleanup(void)
-{
-	u8 hw_status;
-
-	hw_status = intel_hwstatus ();
-	if (hw_status & INTEL_RNG_ENABLED)
-		intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED);
-	else
-		printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
-	iounmap(rng_mem);
-	rng_mem = NULL;
-}
-
-/***********************************************************************
- *
- * AMD RNG operations
- *
- */
-
-static u32 pmbase;			/* PMxx I/O base */
-static struct pci_dev *amd_dev;
-
-static unsigned int amd_data_present (void)
-{
-      	return inl(pmbase + 0xF4) & 1;
-}
-
-
-static u32 amd_data_read (void)
-{
-	return inl(pmbase + 0xF0);
-}
-
-static int __init amd_init (struct pci_dev *dev)
-{
-	int rc;
-	u8 rnen;
-
-	DPRINTK ("ENTER\n");
-
-	pci_read_config_dword(dev, 0x58, &pmbase);
-
-	pmbase &= 0x0000FF00;
-
-	if (pmbase == 0)
-	{
-		printk (KERN_ERR PFX "power management base not set\n");
-		rc = -EIO;
-		goto err_out;
-	}
-
-	pci_read_config_byte(dev, 0x40, &rnen);
-	rnen |= (1 << 7);	/* RNG on */
-	pci_write_config_byte(dev, 0x40, rnen);
-
-	pci_read_config_byte(dev, 0x41, &rnen);
-	rnen |= (1 << 7);	/* PMIO enable */
-	pci_write_config_byte(dev, 0x41, rnen);
-
-	pr_info( PFX "AMD768 system management I/O registers at 0x%X.\n",
-			pmbase);
-
-	amd_dev = dev;
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out:
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-static void amd_cleanup(void)
-{
-	u8 rnen;
-
-	pci_read_config_byte(amd_dev, 0x40, &rnen);
-	rnen &= ~(1 << 7);	/* RNG off */
-	pci_write_config_byte(amd_dev, 0x40, rnen);
-
-	/* FIXME: twiddle pmio, also? */
-}
-
-#ifdef __i386__
-/***********************************************************************
- *
- * VIA RNG operations
- *
- */
-
-enum {
-	VIA_STRFILT_CNT_SHIFT	= 16,
-	VIA_STRFILT_FAIL	= (1 << 15),
-	VIA_STRFILT_ENABLE	= (1 << 14),
-	VIA_RAWBITS_ENABLE	= (1 << 13),
-	VIA_RNG_ENABLE		= (1 << 6),
-	VIA_XSTORE_CNT_MASK	= 0x0F,
-
-	VIA_RNG_CHUNK_8		= 0x00,	/* 64 rand bits, 64 stored bits */
-	VIA_RNG_CHUNK_4		= 0x01,	/* 32 rand bits, 32 stored bits */
-	VIA_RNG_CHUNK_4_MASK	= 0xFFFFFFFF,
-	VIA_RNG_CHUNK_2		= 0x02,	/* 16 rand bits, 32 stored bits */
-	VIA_RNG_CHUNK_2_MASK	= 0xFFFF,
-	VIA_RNG_CHUNK_1		= 0x03,	/* 8 rand bits, 32 stored bits */
-	VIA_RNG_CHUNK_1_MASK	= 0xFF,
-};
-
-static u32 via_rng_datum;
-
-/*
- * Investigate using the 'rep' prefix to obtain 32 bits of random data
- * in one insn.  The upside is potentially better performance.  The
- * downside is that the instruction becomes no longer atomic.  Due to
- * this, just like familiar issues with /dev/random itself, the worst
- * case of a 'rep xstore' could potentially pause a cpu for an
- * unreasonably long time.  In practice, this condition would likely
- * only occur when the hardware is failing.  (or so we hope :))
- *
- * Another possible performance boost may come from simply buffering
- * until we have 4 bytes, thus returning a u32 at a time,
- * instead of the current u8-at-a-time.
- */
-
-static inline u32 xstore(u32 *addr, u32 edx_in)
-{
-	u32 eax_out;
-
-	asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
-		:"=m"(*addr), "=a"(eax_out)
-		:"D"(addr), "d"(edx_in));
-
-	return eax_out;
-}
-
-static unsigned int via_data_present(void)
-{
-	u32 bytes_out;
-
-	/* We choose the recommended 1-byte-per-instruction RNG rate,
-	 * for greater randomness at the expense of speed.  Larger
-	 * values 2, 4, or 8 bytes-per-instruction yield greater
-	 * speed at lesser randomness.
-	 *
-	 * If you change this to another VIA_CHUNK_n, you must also
-	 * change the ->n_bytes values in rng_vendor_ops[] tables.
-	 * VIA_CHUNK_8 requires further code changes.
-	 *
-	 * A copy of MSR_VIA_RNG is placed in eax_out when xstore
-	 * completes.
-	 */
-	via_rng_datum = 0; /* paranoia, not really necessary */
-	bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK;
-	if (bytes_out == 0)
-		return 0;
-
-	return 1;
-}
-
-static u32 via_data_read(void)
-{
-	return via_rng_datum;
-}
-
-static int __init via_init(struct pci_dev *dev)
-{
-	u32 lo, hi, old_lo;
-
-	/* Control the RNG via MSR.  Tread lightly and pay very close
-	 * close attention to values written, as the reserved fields
-	 * are documented to be "undefined and unpredictable"; but it
-	 * does not say to write them as zero, so I make a guess that
-	 * we restore the values we find in the register.
-	 */
-	rdmsr(MSR_VIA_RNG, lo, hi);
-
-	old_lo = lo;
-	lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
-	lo &= ~VIA_XSTORE_CNT_MASK;
-	lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
-	lo |= VIA_RNG_ENABLE;
-
-	if (lo != old_lo)
-		wrmsr(MSR_VIA_RNG, lo, hi);
-
-	/* perhaps-unnecessary sanity check; remove after testing if
-	   unneeded */
-	rdmsr(MSR_VIA_RNG, lo, hi);
-	if ((lo & VIA_RNG_ENABLE) == 0) {
-		printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void via_cleanup(void)
-{
-	/* do nothing */
-}
-#endif
-
-/***********************************************************************
- *
- * AMD Geode RNG operations
- *
- */
-
-static void __iomem *geode_rng_base = NULL;
-
-#define GEODE_RNG_DATA_REG   0x50
-#define GEODE_RNG_STATUS_REG 0x54
-
-static u32 geode_data_read(void)
-{
-	u32 val;
-
-	assert(geode_rng_base != NULL);
-	val = readl(geode_rng_base + GEODE_RNG_DATA_REG);
-	return val;
-}
-
-static unsigned int geode_data_present(void)
-{
-	u32 val;
-
-	assert(geode_rng_base != NULL);
-	val = readl(geode_rng_base + GEODE_RNG_STATUS_REG);
-	return val;
-}
-
-static void geode_cleanup(void)
-{
-	iounmap(geode_rng_base);
-  	geode_rng_base = NULL;
-}
-
-static int geode_init(struct pci_dev *dev)
-{
-	unsigned long rng_base = pci_resource_start(dev, 0);
-
-	if (rng_base == 0)
-		return 1;
-
-	geode_rng_base = ioremap(rng_base, 0x58);
-
-	if (geode_rng_base == NULL) {
-		printk(KERN_ERR PFX "Cannot ioremap RNG memory\n");
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-/***********************************************************************
- *
- * /dev/hwrandom character device handling (major 10, minor 183)
- *
- */
-
-static int rng_dev_open (struct inode *inode, struct file *filp)
-{
-	/* enforce read-only access to this chrdev */
-	if ((filp->f_mode & FMODE_READ) == 0)
-		return -EINVAL;
-	if (filp->f_mode & FMODE_WRITE)
-		return -EINVAL;
-
-	return 0;
-}
-
-
-static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
-				loff_t * offp)
-{
-	static DEFINE_SPINLOCK(rng_lock);
-	unsigned int have_data;
-	u32 data = 0;
-	ssize_t ret = 0;
-
-	while (size) {
-		spin_lock(&rng_lock);
-
-		have_data = 0;
-		if (rng_ops->data_present()) {
-			data = rng_ops->data_read();
-			have_data = rng_ops->n_bytes;
-		}
-
-		spin_unlock (&rng_lock);
-
-		while (have_data && size) {
-			if (put_user((u8)data, buf++)) {
-				ret = ret ? : -EFAULT;
-				break;
-			}
-			size--;
-			ret++;
-			have_data--;
-			data>>=8;
-		}
-
-		if (filp->f_flags & O_NONBLOCK)
-			return ret ? : -EAGAIN;
-
-		if(need_resched())
-			schedule_timeout_interruptible(1);
-		else
-			udelay(200);	/* FIXME: We could poll for 250uS ?? */
-
-		if (signal_pending (current))
-			return ret ? : -ERESTARTSYS;
-	}
-	return ret;
-}
-
-
-
-/*
- * rng_init_one - look for and attempt to init a single RNG
- */
-static int __init rng_init_one (struct pci_dev *dev)
-{
-	int rc;
-
-	DPRINTK ("ENTER\n");
-
-	assert(rng_ops != NULL);
-
-	rc = rng_ops->init(dev);
-	if (rc)
-		goto err_out;
-
-	rc = misc_register (&rng_miscdev);
-	if (rc) {
-		printk (KERN_ERR PFX "misc device register failed\n");
-		goto err_out_cleanup_hw;
-	}
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-
-err_out_cleanup_hw:
-	rng_ops->cleanup();
-err_out:
-	DPRINTK ("EXIT, returning %d\n", rc);
-	return rc;
-}
-
-
-
-MODULE_AUTHOR("The Linux Kernel team");
-MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
-MODULE_LICENSE("GPL");
-
-
-/*
- * rng_init - initialize RNG module
- */
-static int __init rng_init (void)
-{
-	int rc;
-	struct pci_dev *pdev = NULL;
-	const struct pci_device_id *ent;
-
-	DPRINTK ("ENTER\n");
-
-	/* Probe for Intel, AMD, Geode RNGs */
-	for_each_pci_dev(pdev) {
-		ent = pci_match_id(rng_pci_tbl, pdev);
-		if (ent) {
-			rng_ops = &rng_vendor_ops[ent->driver_data];
-			goto match;
-		}
-	}
-
-#ifdef __i386__
-	/* Probe for VIA RNG */
-	if (cpu_has_xstore) {
-		rng_ops = &rng_vendor_ops[rng_hw_via];
-		pdev = NULL;
-		goto match;
-	}
-#endif
-
-	DPRINTK ("EXIT, returning -ENODEV\n");
-	return -ENODEV;
-
-match:
-	rc = rng_init_one (pdev);
-	if (rc)
-		return rc;
-
-	pr_info( RNG_DRIVER_NAME " loaded\n");
-
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
-}
-
-
-/*
- * rng_init - shutdown RNG module
- */
-static void __exit rng_cleanup (void)
-{
-	DPRINTK ("ENTER\n");
-
-	misc_deregister (&rng_miscdev);
-
-	if (rng_ops->cleanup)
-		rng_ops->cleanup();
-
-	DPRINTK ("EXIT\n");
-}
-
-
-module_init (rng_init);
-module_exit (rng_cleanup);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
new file mode 100644
index 0000000..9f7635f
--- /dev/null
+++ b/drivers/char/hw_random/Kconfig
@@ -0,0 +1,90 @@
+#
+# Hardware Random Number Generator (RNG) configuration
+#
+
+config HW_RANDOM
+	bool "Hardware Random Number Generator Core support"
+	default y
+	---help---
+	  Hardware Random Number Generator Core infrastructure.
+
+	  If unsure, say Y.
+
+config HW_RANDOM_INTEL
+	tristate "Intel HW Random Number Generator support"
+	depends on HW_RANDOM && (X86 || IA64) && PCI
+	default y
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Intel i8xx-based motherboards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called intel-rng.
+
+	  If unsure, say Y.
+
+config HW_RANDOM_AMD
+	tristate "AMD HW Random Number Generator support"
+	depends on HW_RANDOM && X86 && PCI
+	default y
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on AMD 76x-based motherboards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called amd-rng.
+
+	  If unsure, say Y.
+
+config HW_RANDOM_GEODE
+	tristate "AMD Geode HW Random Number Generator support"
+	depends on HW_RANDOM && X86 && PCI
+	default y
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on the AMD Geode LX.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called geode-rng.
+
+	  If unsure, say Y.
+
+config HW_RANDOM_VIA
+	tristate "VIA HW Random Number Generator support"
+	depends on HW_RANDOM && X86_32
+	default y
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on VIA based motherboards.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called via-rng.
+
+	  If unsure, say Y.
+
+config HW_RANDOM_IXP4XX
+	tristate "Intel IXP4xx NPU HW Random Number Generator support"
+	depends on HW_RANDOM && ARCH_IXP4XX
+	default y
+	---help---
+	  This driver provides kernel-side support for the Random
+	  Number Generator hardware found on the Intel IXP4xx NPU.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ixp4xx-rng.
+
+	  If unsure, say Y.
+
+config HW_RANDOM_OMAP
+	tristate "OMAP Random Number Generator support"
+	depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX)
+	default y
+ 	---help---
+ 	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on OMAP16xx and OMAP24xx multimedia
+	  processors.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called omap-rng.
+
+ 	  If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
new file mode 100644
index 0000000..e263ae9
--- /dev/null
+++ b/drivers/char/hw_random/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for HW Random Number Generator (RNG) device drivers.
+#
+
+obj-$(CONFIG_HW_RANDOM) += core.o
+obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
+obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
+obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
+obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
+obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
+obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
new file mode 100644
index 0000000..71e4e0f
--- /dev/null
+++ b/drivers/char/hw_random/amd-rng.c
@@ -0,0 +1,152 @@
+/*
+ * RNG driver for AMD RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+
+
+#define PFX	KBUILD_MODNAME ": "
+
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static const struct pci_device_id pci_tbl[] = {
+	{ 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0, },	/* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+static struct pci_dev *amd_pdev;
+
+
+static int amd_rng_data_present(struct hwrng *rng)
+{
+	u32 pmbase = (u32)rng->priv;
+
+      	return !!(inl(pmbase + 0xF4) & 1);
+}
+
+static int amd_rng_data_read(struct hwrng *rng, u32 *data)
+{
+	u32 pmbase = (u32)rng->priv;
+
+	*data = inl(pmbase + 0xF0);
+
+	return 4;
+}
+
+static int amd_rng_init(struct hwrng *rng)
+{
+	u8 rnen;
+
+	pci_read_config_byte(amd_pdev, 0x40, &rnen);
+	rnen |= (1 << 7);	/* RNG on */
+	pci_write_config_byte(amd_pdev, 0x40, rnen);
+
+	pci_read_config_byte(amd_pdev, 0x41, &rnen);
+	rnen |= (1 << 7);	/* PMIO enable */
+	pci_write_config_byte(amd_pdev, 0x41, rnen);
+
+	return 0;
+}
+
+static void amd_rng_cleanup(struct hwrng *rng)
+{
+	u8 rnen;
+
+	pci_read_config_byte(amd_pdev, 0x40, &rnen);
+	rnen &= ~(1 << 7);	/* RNG off */
+	pci_write_config_byte(amd_pdev, 0x40, rnen);
+}
+
+
+static struct hwrng amd_rng = {
+	.name		= "amd",
+	.init		= amd_rng_init,
+	.cleanup	= amd_rng_cleanup,
+	.data_present	= amd_rng_data_present,
+	.data_read	= amd_rng_data_read,
+};
+
+
+static int __init mod_init(void)
+{
+	int err = -ENODEV;
+	struct pci_dev *pdev = NULL;
+	const struct pci_device_id *ent;
+	u32 pmbase;
+
+	for_each_pci_dev(pdev) {
+		ent = pci_match_id(pci_tbl, pdev);
+		if (ent)
+			goto found;
+	}
+	/* Device not found. */
+	goto out;
+
+found:
+	err = pci_read_config_dword(pdev, 0x58, &pmbase);
+	if (err)
+		goto out;
+	err = -EIO;
+	pmbase &= 0x0000FF00;
+	if (pmbase == 0)
+		goto out;
+	amd_rng.priv = (unsigned long)pmbase;
+	amd_pdev = pdev;
+
+	printk(KERN_INFO "AMD768 RNG detected\n");
+	err = hwrng_register(&amd_rng);
+	if (err) {
+		printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+		       err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+static void __exit mod_exit(void)
+{
+	hwrng_unregister(&amd_rng);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("The Linux Kernel team");
+MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
new file mode 100644
index 0000000..88b0266
--- /dev/null
+++ b/drivers/char/hw_random/core.c
@@ -0,0 +1,354 @@
+/*
+        Added support for the AMD Geode LX RNG
+	(c) Copyright 2004-2005 Advanced Micro Devices, Inc.
+
+	derived from
+
+ 	Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+	(c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+
+ 	derived from
+
+        Hardware driver for the AMD 768 Random Number Generator (RNG)
+        (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+
+ 	derived from
+
+	Hardware driver for Intel i810 Random Number Generator (RNG)
+	Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+	Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+
+	Added generic RNG API
+	Copyright 2006 Michael Buesch <mbuesch@freenet.de>
+	Copyright 2005 (c) MontaVista Software, Inc.
+
+	Please read Documentation/hw_random.txt for details on use.
+
+	----------------------------------------------------------
+	This software may be used and distributed according to the terms
+        of the GNU General Public License, incorporated herein by reference.
+
+ */
+
+
+#include <linux/device.h>
+#include <linux/hw_random.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+
+#define RNG_MODULE_NAME		"hw_random"
+#define PFX			RNG_MODULE_NAME ": "
+#define RNG_MISCDEV_MINOR	183 /* official */
+
+
+static struct hwrng *current_rng;
+static LIST_HEAD(rng_list);
+static DEFINE_MUTEX(rng_mutex);
+
+
+static inline int hwrng_init(struct hwrng *rng)
+{
+	if (!rng->init)
+		return 0;
+	return rng->init(rng);
+}
+
+static inline void hwrng_cleanup(struct hwrng *rng)
+{
+	if (rng && rng->cleanup)
+		rng->cleanup(rng);
+}
+
+static inline int hwrng_data_present(struct hwrng *rng)
+{
+	if (!rng->data_present)
+		return 1;
+	return rng->data_present(rng);
+}
+
+static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
+{
+	return rng->data_read(rng, data);
+}
+
+
+static int rng_dev_open(struct inode *inode, struct file *filp)
+{
+	/* enforce read-only access to this chrdev */
+	if ((filp->f_mode & FMODE_READ) == 0)
+		return -EINVAL;
+	if (filp->f_mode & FMODE_WRITE)
+		return -EINVAL;
+	return 0;
+}
+
+static ssize_t rng_dev_read(struct file *filp, char __user *buf,
+			    size_t size, loff_t *offp)
+{
+	u32 data;
+	ssize_t ret = 0;
+	int i, err = 0;
+	int data_present;
+	int bytes_read;
+
+	while (size) {
+		err = -ERESTARTSYS;
+		if (mutex_lock_interruptible(&rng_mutex))
+			goto out;
+		if (!current_rng) {
+			mutex_unlock(&rng_mutex);
+			err = -ENODEV;
+			goto out;
+		}
+		if (filp->f_flags & O_NONBLOCK) {
+			data_present = hwrng_data_present(current_rng);
+		} else {
+			/* Some RNG require some time between data_reads to gather
+			 * new entropy. Poll it.
+			 */
+			for (i = 0; i < 20; i++) {
+				data_present = hwrng_data_present(current_rng);
+				if (data_present)
+					break;
+				udelay(10);
+			}
+		}
+		bytes_read = 0;
+		if (data_present)
+			bytes_read = hwrng_data_read(current_rng, &data);
+		mutex_unlock(&rng_mutex);
+
+		err = -EAGAIN;
+		if (!bytes_read && (filp->f_flags & O_NONBLOCK))
+			goto out;
+
+		err = -EFAULT;
+		while (bytes_read && size) {
+			if (put_user((u8)data, buf++))
+				goto out;
+			size--;
+			ret++;
+			bytes_read--;
+			data >>= 8;
+		}
+
+		if (need_resched())
+			schedule_timeout_interruptible(1);
+		err = -ERESTARTSYS;
+		if (signal_pending(current))
+			goto out;
+	}
+out:
+	return ret ? : err;
+}
+
+
+static struct file_operations rng_chrdev_ops = {
+	.owner		= THIS_MODULE,
+	.open		= rng_dev_open,
+	.read		= rng_dev_read,
+};
+
+static struct miscdevice rng_miscdev = {
+	.minor		= RNG_MISCDEV_MINOR,
+	.name		= RNG_MODULE_NAME,
+	.fops		= &rng_chrdev_ops,
+};
+
+
+static ssize_t hwrng_attr_current_store(struct class_device *class,
+					const char *buf, size_t len)
+{
+	int err;
+	struct hwrng *rng;
+
+	err = mutex_lock_interruptible(&rng_mutex);
+	if (err)
+		return -ERESTARTSYS;
+	err = -ENODEV;
+	list_for_each_entry(rng, &rng_list, list) {
+		if (strcmp(rng->name, buf) == 0) {
+			if (rng == current_rng) {
+				err = 0;
+				break;
+			}
+			err = hwrng_init(rng);
+			if (err)
+				break;
+			hwrng_cleanup(current_rng);
+			current_rng = rng;
+			err = 0;
+			break;
+		}
+	}
+	mutex_unlock(&rng_mutex);
+
+	return err ? : len;
+}
+
+static ssize_t hwrng_attr_current_show(struct class_device *class,
+				       char *buf)
+{
+	int err;
+	ssize_t ret;
+	const char *name = "none";
+
+	err = mutex_lock_interruptible(&rng_mutex);
+	if (err)
+		return -ERESTARTSYS;
+	if (current_rng)
+		name = current_rng->name;
+	ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
+	mutex_unlock(&rng_mutex);
+
+	return ret;
+}
+
+static ssize_t hwrng_attr_available_show(struct class_device *class,
+					 char *buf)
+{
+	int err;
+	ssize_t ret = 0;
+	struct hwrng *rng;
+
+	err = mutex_lock_interruptible(&rng_mutex);
+	if (err)
+		return -ERESTARTSYS;
+	buf[0] = '\0';
+	list_for_each_entry(rng, &rng_list, list) {
+		strncat(buf, rng->name, PAGE_SIZE - ret - 1);
+		ret += strlen(rng->name);
+		strncat(buf, " ", PAGE_SIZE - ret - 1);
+		ret++;
+	}
+	strncat(buf, "\n", PAGE_SIZE - ret - 1);
+	ret++;
+	mutex_unlock(&rng_mutex);
+
+	return ret;
+}
+
+static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
+			 hwrng_attr_current_show,
+			 hwrng_attr_current_store);
+static CLASS_DEVICE_ATTR(rng_available, S_IRUGO,
+			 hwrng_attr_available_show,
+			 NULL);
+
+
+static void unregister_miscdev(void)
+{
+	class_device_remove_file(rng_miscdev.class,
+				 &class_device_attr_rng_available);
+	class_device_remove_file(rng_miscdev.class,
+				 &class_device_attr_rng_current);
+	misc_deregister(&rng_miscdev);
+}
+
+static int register_miscdev(void)
+{
+	int err;
+
+	err = misc_register(&rng_miscdev);
+	if (err)
+		goto out;
+	err = class_device_create_file(rng_miscdev.class,
+				       &class_device_attr_rng_current);
+	if (err)
+		goto err_misc_dereg;
+	err = class_device_create_file(rng_miscdev.class,
+				       &class_device_attr_rng_available);
+	if (err)
+		goto err_remove_current;
+out:
+	return err;
+
+err_remove_current:
+	class_device_remove_file(rng_miscdev.class,
+				 &class_device_attr_rng_current);
+err_misc_dereg:
+	misc_deregister(&rng_miscdev);
+	goto out;
+}
+
+int hwrng_register(struct hwrng *rng)
+{
+	int must_register_misc;
+	int err = -EINVAL;
+	struct hwrng *old_rng, *tmp;
+
+	if (rng->name == NULL ||
+	    rng->data_read == NULL)
+		goto out;
+
+	mutex_lock(&rng_mutex);
+
+	/* Must not register two RNGs with the same name. */
+	err = -EEXIST;
+	list_for_each_entry(tmp, &rng_list, list) {
+		if (strcmp(tmp->name, rng->name) == 0)
+			goto out_unlock;
+	}
+
+	must_register_misc = (current_rng == NULL);
+	old_rng = current_rng;
+	if (!old_rng) {
+		err = hwrng_init(rng);
+		if (err)
+			goto out_unlock;
+		current_rng = rng;
+	}
+	err = 0;
+	if (must_register_misc) {
+		err = register_miscdev();
+		if (err) {
+			if (!old_rng) {
+				hwrng_cleanup(rng);
+				current_rng = NULL;
+			}
+			goto out_unlock;
+		}
+	}
+	INIT_LIST_HEAD(&rng->list);
+	list_add_tail(&rng->list, &rng_list);
+out_unlock:
+	mutex_unlock(&rng_mutex);
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(hwrng_register);
+
+void hwrng_unregister(struct hwrng *rng)
+{
+	int err;
+
+	mutex_lock(&rng_mutex);
+
+	list_del(&rng->list);
+	if (current_rng == rng) {
+		hwrng_cleanup(rng);
+		if (list_empty(&rng_list)) {
+			current_rng = NULL;
+		} else {
+			current_rng = list_entry(rng_list.prev, struct hwrng, list);
+			err = hwrng_init(current_rng);
+			if (err)
+				current_rng = NULL;
+		}
+	}
+	if (list_empty(&rng_list))
+		unregister_miscdev();
+
+	mutex_unlock(&rng_mutex);
+}
+EXPORT_SYMBOL_GPL(hwrng_unregister);
+
+
+MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
new file mode 100644
index 0000000..be61f22
--- /dev/null
+++ b/drivers/char/hw_random/geode-rng.c
@@ -0,0 +1,128 @@
+/*
+ * RNG driver for AMD Geode RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+
+
+#define PFX	KBUILD_MODNAME ": "
+
+#define GEODE_RNG_DATA_REG   0x50
+#define GEODE_RNG_STATUS_REG 0x54
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static const struct pci_device_id pci_tbl[] = {
+	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0, },	/* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+
+static int geode_rng_data_read(struct hwrng *rng, u32 *data)
+{
+	void __iomem *mem = (void __iomem *)rng->priv;
+
+	*data = readl(mem + GEODE_RNG_DATA_REG);
+
+	return 4;
+}
+
+static int geode_rng_data_present(struct hwrng *rng)
+{
+	void __iomem *mem = (void __iomem *)rng->priv;
+
+	return !!(readl(mem + GEODE_RNG_STATUS_REG));
+}
+
+
+static struct hwrng geode_rng = {
+	.name		= "geode",
+	.data_present	= geode_rng_data_present,
+	.data_read	= geode_rng_data_read,
+};
+
+
+static int __init mod_init(void)
+{
+	int err = -ENODEV;
+	struct pci_dev *pdev = NULL;
+	const struct pci_device_id *ent;
+	void __iomem *mem;
+	unsigned long rng_base;
+
+	for_each_pci_dev(pdev) {
+		ent = pci_match_id(pci_tbl, pdev);
+		if (ent)
+			goto found;
+	}
+	/* Device not found. */
+	goto out;
+
+found:
+	rng_base = pci_resource_start(pdev, 0);
+	if (rng_base == 0)
+		goto out;
+	err = -ENOMEM;
+	mem = ioremap(rng_base, 0x58);
+	if (!mem)
+		goto out;
+	geode_rng.priv = (unsigned long)mem;
+
+	printk(KERN_INFO "AMD Geode RNG detected\n");
+	err = hwrng_register(&geode_rng);
+	if (err) {
+		printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+		       err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+static void __exit mod_exit(void)
+{
+	void __iomem *mem = (void __iomem *)geode_rng.priv;
+
+	hwrng_unregister(&geode_rng);
+	iounmap(mem);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
new file mode 100644
index 0000000..6594bd5
--- /dev/null
+++ b/drivers/char/hw_random/intel-rng.c
@@ -0,0 +1,189 @@
+/*
+ * RNG driver for Intel RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+
+
+#define PFX	KBUILD_MODNAME ": "
+
+/*
+ * RNG registers
+ */
+#define INTEL_RNG_HW_STATUS			0
+#define         INTEL_RNG_PRESENT		0x40
+#define         INTEL_RNG_ENABLED		0x01
+#define INTEL_RNG_STATUS			1
+#define         INTEL_RNG_DATA_PRESENT		0x01
+#define INTEL_RNG_DATA				2
+
+/*
+ * Magic address at which Intel PCI bridges locate the RNG
+ */
+#define INTEL_RNG_ADDR				0xFFBC015F
+#define INTEL_RNG_ADDR_LEN			3
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static const struct pci_device_id pci_tbl[] = {
+	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ 0, },	/* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, pci_tbl);
+
+
+static inline u8 hwstatus_get(void __iomem *mem)
+{
+	return readb(mem + INTEL_RNG_HW_STATUS);
+}
+
+static inline u8 hwstatus_set(void __iomem *mem,
+			      u8 hw_status)
+{
+	writeb(hw_status, mem + INTEL_RNG_HW_STATUS);
+	return hwstatus_get(mem);
+}
+
+static int intel_rng_data_present(struct hwrng *rng)
+{
+	void __iomem *mem = (void __iomem *)rng->priv;
+
+	return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
+}
+
+static int intel_rng_data_read(struct hwrng *rng, u32 *data)
+{
+	void __iomem *mem = (void __iomem *)rng->priv;
+
+	*data = readb(mem + INTEL_RNG_DATA);
+
+	return 1;
+}
+
+static int intel_rng_init(struct hwrng *rng)
+{
+	void __iomem *mem = (void __iomem *)rng->priv;
+	u8 hw_status;
+	int err = -EIO;
+
+	hw_status = hwstatus_get(mem);
+	/* turn RNG h/w on, if it's off */
+	if ((hw_status & INTEL_RNG_ENABLED) == 0)
+		hw_status = hwstatus_set(mem, hw_status | INTEL_RNG_ENABLED);
+	if ((hw_status & INTEL_RNG_ENABLED) == 0) {
+		printk(KERN_ERR PFX "cannot enable RNG, aborting\n");
+		goto out;
+	}
+	err = 0;
+out:
+	return err;
+}
+
+static void intel_rng_cleanup(struct hwrng *rng)
+{
+	void __iomem *mem = (void __iomem *)rng->priv;
+	u8 hw_status;
+
+	hw_status = hwstatus_get(mem);
+	if (hw_status & INTEL_RNG_ENABLED)
+		hwstatus_set(mem, hw_status & ~INTEL_RNG_ENABLED);
+	else
+		printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
+}
+
+
+static struct hwrng intel_rng = {
+	.name		= "intel",
+	.init		= intel_rng_init,
+	.cleanup	= intel_rng_cleanup,
+	.data_present	= intel_rng_data_present,
+	.data_read	= intel_rng_data_read,
+};
+
+
+static int __init mod_init(void)
+{
+	int err = -ENODEV;
+	void __iomem *mem;
+	u8 hw_status;
+
+	if (!pci_dev_present(pci_tbl))
+		goto out; /* Device not found. */
+
+	err = -ENOMEM;
+	mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
+	if (!mem)
+		goto out;
+	intel_rng.priv = (unsigned long)mem;
+
+	/* Check for Intel 82802 */
+	err = -ENODEV;
+	hw_status = hwstatus_get(mem);
+	if ((hw_status & INTEL_RNG_PRESENT) == 0)
+		goto err_unmap;
+
+	printk(KERN_INFO "Intel 82802 RNG detected\n");
+	err = hwrng_register(&intel_rng);
+	if (err) {
+		printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+		       err);
+		goto out;
+	}
+out:
+	return err;
+
+err_unmap:
+	iounmap(mem);
+	goto out;
+}
+
+static void __exit mod_exit(void)
+{
+	void __iomem *mem = (void __iomem *)intel_rng.priv;
+
+	hwrng_unregister(&intel_rng);
+	iounmap(mem);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
new file mode 100644
index 0000000..ef71022
--- /dev/null
+++ b/drivers/char/hw_random/ixp4xx-rng.c
@@ -0,0 +1,73 @@
+/*
+ * drivers/char/rng/ixp4xx-rng.c
+ *
+ * RNG driver for Intel IXP4xx family of NPUs
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Fixes by Michael Buesch
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/hw_random.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+
+static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer)
+{
+	void __iomem * rng_base = (void __iomem *)rng->priv;
+
+	*buffer = __raw_readl(rng_base);
+
+	return 4;
+}
+
+static struct hwrng ixp4xx_rng_ops = {
+	.name		= "ixp4xx",
+	.data_read	= ixp4xx_rng_data_read,
+};
+
+static int __init ixp4xx_rng_init(void)
+{
+	void __iomem * rng_base;
+	int err;
+
+	rng_base = ioremap(0x70002100, 4);
+	if (!rng_base)
+		return -ENOMEM;
+	ixp4xx_rng_ops.priv = (unsigned long)rng_base;
+	err = hwrng_register(&ixp4xx_rng_ops);
+	if (err)
+		iounmap(rng_base);
+
+	return err;
+}
+
+static void __exit ixp4xx_rng_exit(void)
+{
+	void __iomem * rng_base = (void __iomem *)ixp4xx_rng_ops.priv;
+
+	hwrng_unregister(&ixp4xx_rng_ops);
+	iounmap(rng_base);
+}
+
+subsys_initcall(ixp4xx_rng_init);
+module_exit(ixp4xx_rng_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
+MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
new file mode 100644
index 0000000..819516b
--- /dev/null
+++ b/drivers/char/hw_random/omap-rng.c
@@ -0,0 +1,208 @@
+/*
+ * driver/char/hw_random/omap-rng.c
+ *
+ * RNG driver for TI OMAP CPU family
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * Mostly based on original driver:
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Author: Juha Yrj��<juha.yrjola@nokia.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * TODO:
+ *
+ * - Make status updated be interrupt driven so we don't poll
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/random.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/hw_random.h>
+
+#include <asm/io.h>
+#include <asm/hardware/clock.h>
+
+#define RNG_OUT_REG		0x00		/* Output register */
+#define RNG_STAT_REG		0x04		/* Status register
+							[0] = STAT_BUSY */
+#define RNG_ALARM_REG		0x24		/* Alarm register
+							[7:0] = ALARM_COUNTER */
+#define RNG_CONFIG_REG		0x28		/* Configuration register
+							[11:6] = RESET_COUNT
+							[5:3]  = RING2_DELAY
+							[2:0]  = RING1_DELAY */
+#define RNG_REV_REG		0x3c		/* Revision register
+							[7:0] = REV_NB */
+#define RNG_MASK_REG		0x40		/* Mask and reset register
+							[2] = IT_EN
+							[1] = SOFTRESET
+							[0] = AUTOIDLE */
+#define RNG_SYSSTATUS		0x44		/* System status
+							[0] = RESETDONE */
+
+static void __iomem *rng_base;
+static struct clk *rng_ick;
+static struct device *rng_dev;
+
+static u32 omap_rng_read_reg(int reg)
+{
+	return __raw_readl(rng_base + reg);
+}
+
+static void omap_rng_write_reg(int reg, u32 val)
+{
+	__raw_writel(val, rng_base + reg);
+}
+
+/* REVISIT: Does the status bit really work on 16xx? */
+static int omap_rng_data_present(struct hwrng *rng)
+{
+	return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
+}
+
+static int omap_rng_data_read(struct hwrng *rng, u32 *data)
+{
+	*data = omap_rng_read_reg(RNG_OUT_REG);
+
+	return 4;
+}
+
+static struct hwrng omap_rng_ops = {
+	.name		= "omap",
+	.data_present	= omap_rng_data_present,
+	.data_read	= omap_rng_data_read,
+};
+
+static int __init omap_rng_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct resource *res, *mem;
+	int ret;
+
+	/*
+	 * A bit ugly, and it will never actually happen but there can
+	 * be only one RNG and this catches any bork
+	 */
+	BUG_ON(rng_dev);
+
+    	if (cpu_is_omap24xx()) {
+		rng_ick = clk_get(NULL, "rng_ick");
+		if (IS_ERR(rng_ick)) {
+			dev_err(dev, "Could not get rng_ick\n");
+			ret = PTR_ERR(rng_ick);
+			return ret;
+		}
+		else {
+			clk_use(rng_ick);
+		}
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!res)
+		return -ENOENT;
+
+	mem = request_mem_region(res->start, res->end - res->start + 1,
+				 pdev->name);
+	if (mem == NULL)
+		return -EBUSY;
+
+	dev_set_drvdata(dev, mem);
+	rng_base = (u32 __iomem *)io_p2v(res->start);
+
+	ret = hwrng_register(&omap_rng_ops);
+	if (ret) {
+		release_resource(mem);
+		rng_base = NULL;
+		return ret;
+	}
+
+	dev_info(dev, "OMAP Random Number Generator ver. %02x\n",
+		omap_rng_read_reg(RNG_REV_REG));
+	omap_rng_write_reg(RNG_MASK_REG, 0x1);
+
+	rng_dev = dev;
+
+	return 0;
+}
+
+static int __exit omap_rng_remove(struct device *dev)
+{
+	struct resource *mem = dev_get_drvdata(dev);
+
+	hwrng_unregister(&omap_rng_ops);
+
+	omap_rng_write_reg(RNG_MASK_REG, 0x0);
+
+	if (cpu_is_omap24xx()) {
+		clk_unuse(rng_ick);
+		clk_put(rng_ick);
+	}
+
+	release_resource(mem);
+	rng_base = NULL;
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
+{
+	omap_rng_write_reg(RNG_MASK_REG, 0x0);
+
+	return 0;
+}
+
+static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level)
+{
+	omap_rng_write_reg(RNG_MASK_REG, 0x1);
+
+	return 1;
+}
+
+#else
+
+#define	omap_rng_suspend	NULL
+#define	omap_rng_resume		NULL
+
+#endif
+
+
+static struct device_driver omap_rng_driver = {
+	.name		= "omap_rng",
+	.bus		= &platform_bus_type,
+	.probe		= omap_rng_probe,
+	.remove		= __exit_p(omap_rng_remove),
+	.suspend	= omap_rng_suspend,
+	.resume		= omap_rng_resume
+};
+
+static int __init omap_rng_init(void)
+{
+	if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
+		return -ENODEV;
+
+	return driver_register(&omap_rng_driver);
+}
+
+static void __exit omap_rng_exit(void)
+{
+	driver_unregister(&omap_rng_driver);
+}
+
+module_init(omap_rng_init);
+module_exit(omap_rng_exit);
+
+MODULE_AUTHOR("Deepak Saxena (and others)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
new file mode 100644
index 0000000..0e786b6
--- /dev/null
+++ b/drivers/char/hw_random/via-rng.c
@@ -0,0 +1,183 @@
+/*
+ * RNG driver for VIA RNGs
+ *
+ * Copyright 2005 (c) MontaVista Software, Inc.
+ *
+ * with the majority of the code coming from:
+ *
+ * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
+ * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for the AMD 768 Random Number Generator (RNG)
+ * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
+ *
+ * derived from
+ *
+ * Hardware driver for Intel i810 Random Number Generator (RNG)
+ * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/hw_random.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/cpufeature.h>
+
+
+#define PFX	KBUILD_MODNAME ": "
+
+
+enum {
+	VIA_STRFILT_CNT_SHIFT	= 16,
+	VIA_STRFILT_FAIL	= (1 << 15),
+	VIA_STRFILT_ENABLE	= (1 << 14),
+	VIA_RAWBITS_ENABLE	= (1 << 13),
+	VIA_RNG_ENABLE		= (1 << 6),
+	VIA_XSTORE_CNT_MASK	= 0x0F,
+
+	VIA_RNG_CHUNK_8		= 0x00,	/* 64 rand bits, 64 stored bits */
+	VIA_RNG_CHUNK_4		= 0x01,	/* 32 rand bits, 32 stored bits */
+	VIA_RNG_CHUNK_4_MASK	= 0xFFFFFFFF,
+	VIA_RNG_CHUNK_2		= 0x02,	/* 16 rand bits, 32 stored bits */
+	VIA_RNG_CHUNK_2_MASK	= 0xFFFF,
+	VIA_RNG_CHUNK_1		= 0x03,	/* 8 rand bits, 32 stored bits */
+	VIA_RNG_CHUNK_1_MASK	= 0xFF,
+};
+
+/*
+ * Investigate using the 'rep' prefix to obtain 32 bits of random data
+ * in one insn.  The upside is potentially better performance.  The
+ * downside is that the instruction becomes no longer atomic.  Due to
+ * this, just like familiar issues with /dev/random itself, the worst
+ * case of a 'rep xstore' could potentially pause a cpu for an
+ * unreasonably long time.  In practice, this condition would likely
+ * only occur when the hardware is failing.  (or so we hope :))
+ *
+ * Another possible performance boost may come from simply buffering
+ * until we have 4 bytes, thus returning a u32 at a time,
+ * instead of the current u8-at-a-time.
+ */
+
+static inline u32 xstore(u32 *addr, u32 edx_in)
+{
+	u32 eax_out;
+
+	asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
+		:"=m"(*addr), "=a"(eax_out)
+		:"D"(addr), "d"(edx_in));
+
+	return eax_out;
+}
+
+static int via_rng_data_present(struct hwrng *rng)
+{
+	u32 bytes_out;
+	u32 *via_rng_datum = (u32 *)(&rng->priv);
+
+	/* We choose the recommended 1-byte-per-instruction RNG rate,
+	 * for greater randomness at the expense of speed.  Larger
+	 * values 2, 4, or 8 bytes-per-instruction yield greater
+	 * speed at lesser randomness.
+	 *
+	 * If you change this to another VIA_CHUNK_n, you must also
+	 * change the ->n_bytes values in rng_vendor_ops[] tables.
+	 * VIA_CHUNK_8 requires further code changes.
+	 *
+	 * A copy of MSR_VIA_RNG is placed in eax_out when xstore
+	 * completes.
+	 */
+
+	*via_rng_datum = 0; /* paranoia, not really necessary */
+	bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
+	bytes_out &= VIA_XSTORE_CNT_MASK;
+	if (bytes_out == 0)
+		return 0;
+	return 1;
+}
+
+static int via_rng_data_read(struct hwrng *rng, u32 *data)
+{
+	u32 via_rng_datum = (u32)rng->priv;
+
+	*data = via_rng_datum;
+
+	return 1;
+}
+
+static int via_rng_init(struct hwrng *rng)
+{
+	u32 lo, hi, old_lo;
+
+	/* Control the RNG via MSR.  Tread lightly and pay very close
+	 * close attention to values written, as the reserved fields
+	 * are documented to be "undefined and unpredictable"; but it
+	 * does not say to write them as zero, so I make a guess that
+	 * we restore the values we find in the register.
+	 */
+	rdmsr(MSR_VIA_RNG, lo, hi);
+
+	old_lo = lo;
+	lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
+	lo &= ~VIA_XSTORE_CNT_MASK;
+	lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
+	lo |= VIA_RNG_ENABLE;
+
+	if (lo != old_lo)
+		wrmsr(MSR_VIA_RNG, lo, hi);
+
+	/* perhaps-unnecessary sanity check; remove after testing if
+	   unneeded */
+	rdmsr(MSR_VIA_RNG, lo, hi);
+	if ((lo & VIA_RNG_ENABLE) == 0) {
+		printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+
+static struct hwrng via_rng = {
+	.name		= "via",
+	.init		= via_rng_init,
+	.data_present	= via_rng_data_present,
+	.data_read	= via_rng_data_read,
+};
+
+
+static int __init mod_init(void)
+{
+	int err;
+
+	if (!cpu_has_xstore)
+		return -ENODEV;
+	printk(KERN_INFO "VIA RNG detected\n");
+	err = hwrng_register(&via_rng);
+	if (err) {
+		printk(KERN_ERR PFX "RNG registering failed (%d)\n",
+		       err);
+		goto out;
+	}
+out:
+	return err;
+}
+
+static void __exit mod_exit(void)
+{
+	hwrng_unregister(&via_rng);
+}
+
+subsys_initcall(mod_init);
+module_exit(mod_exit);
+
+MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 03db1cb..9ab33c3 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -305,7 +305,7 @@
 
 // Some functions to keep track of what irq's we have
 
-static int __init
+static int
 is_valid_irq(int irq)
 {
 	int *i = Valid_Irqs;
@@ -316,14 +316,14 @@
 	return (*i);
 }
 
-static void __init
+static void
 mark_requested_irq( char irq )
 {
 	rirqs[iindx++] = irq;
 }
 
 #ifdef MODULE
-static int __init
+static int
 clear_requested_irq( char irq )
 {
 	int i;
@@ -337,7 +337,7 @@
 }
 #endif
 
-static int __init
+static int
 have_requested_irq( char irq )
 {
 	// array init to zeros so 0 irq will not be requested as a side effect
@@ -818,7 +818,7 @@
 /* the board, the channel structures are initialized, and the board details   */
 /* are reported on the console.                                               */
 /******************************************************************************/
-static void __init
+static void
 ip2_init_board( int boardnum )
 {
 	int i;
@@ -961,7 +961,7 @@
 /* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
 /* it returns the base address of the controller.                             */
 /******************************************************************************/
-static unsigned short __init
+static unsigned short
 find_eisa_board( int start_slot )
 {
 	int i, j;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 9f2f8fd..ad26f4b 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -57,8 +57,7 @@
 static int initialized = 0;
 
 #ifdef CONFIG_PROC_FS
-struct proc_dir_entry *proc_ipmi_root = NULL;
-EXPORT_SYMBOL(proc_ipmi_root);
+static struct proc_dir_entry *proc_ipmi_root = NULL;
 #endif /* CONFIG_PROC_FS */
 
 #define MAX_EVENTS_IN_QUEUE	25
@@ -936,11 +935,8 @@
 
 	if (val) {
 		/* Deliver any queued events. */
-		list_for_each_entry_safe(msg, msg2, &intf->waiting_events,
-					 link) {
-			list_del(&msg->link);
-			list_add_tail(&msg->link, &msgs);
-		}
+		list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link)
+			list_move_tail(&msg->link, &msgs);
 		intf->waiting_events_count = 0;
 	}
 
@@ -3677,7 +3673,7 @@
 }
 #endif /* CONFIG_IPMI_PANIC_EVENT */
 
-static int has_paniced = 0;
+static int has_panicked = 0;
 
 static int panic_event(struct notifier_block *this,
 		       unsigned long         event,
@@ -3686,9 +3682,9 @@
 	int        i;
 	ipmi_smi_t intf;
 
-	if (has_paniced)
+	if (has_panicked)
 		return NOTIFY_DONE;
-	has_paniced = 1;
+	has_panicked = 1;
 
 	/* For every registered interface, set it to run to completion. */
 	for (i = 0; i < MAX_IPMI_INTERFACES; i++) {
@@ -3742,11 +3738,8 @@
 	proc_ipmi_root->owner = THIS_MODULE;
 #endif /* CONFIG_PROC_FS */
 
-	init_timer(&ipmi_timer);
-	ipmi_timer.data = 0;
-	ipmi_timer.function = ipmi_timeout;
-	ipmi_timer.expires = jiffies + IPMI_TIMEOUT_JIFFIES;
-	add_timer(&ipmi_timer);
+	setup_timer(&ipmi_timer, ipmi_timeout, 0);
+	mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
 
 	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
 
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 02a7dd7..bd4f224 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -55,23 +55,6 @@
 #include <linux/mutex.h>
 #include <linux/kthread.h>
 #include <asm/irq.h>
-#ifdef CONFIG_HIGH_RES_TIMERS
-#include <linux/hrtime.h>
-# if defined(schedule_next_int)
-/* Old high-res timer code, do translations. */
-#  define get_arch_cycles(a) quick_update_jiffies_sub(a)
-#  define arch_cycles_per_jiffy cycles_per_jiffies
-# endif
-static inline void add_usec_to_timer(struct timer_list *t, long v)
-{
-	t->arch_cycle_expires += nsec_to_arch_cycle(v * 1000);
-	while (t->arch_cycle_expires >= arch_cycles_per_jiffy)
-	{
-		t->expires++;
-		t->arch_cycle_expires -= arch_cycles_per_jiffy;
-	}
-}
-#endif
 #include <linux/interrupt.h>
 #include <linux/rcupdate.h>
 #include <linux/ipmi_smi.h>
@@ -243,8 +226,6 @@
 	return atomic_notifier_chain_register(&xaction_notifier_list, nb);
 }
 
-static void si_restart_short_timer(struct smi_info *smi_info);
-
 static void deliver_recv_msg(struct smi_info *smi_info,
 			     struct ipmi_smi_msg *msg)
 {
@@ -768,7 +749,6 @@
 	    && (smi_info->curr_msg == NULL))
 	{
 		start_next_msg(smi_info);
-		si_restart_short_timer(smi_info);
 	}
 	spin_unlock_irqrestore(&(smi_info->si_lock), flags);
 }
@@ -809,7 +789,7 @@
 			/* do nothing */
 		}
 		else if (smi_result == SI_SM_CALL_WITH_DELAY)
-			udelay(1);
+			schedule();
 		else
 			schedule_timeout_interruptible(1);
 	}
@@ -833,37 +813,6 @@
 
 static int initialized = 0;
 
-/* Must be called with interrupts off and with the si_lock held. */
-static void si_restart_short_timer(struct smi_info *smi_info)
-{
-#if defined(CONFIG_HIGH_RES_TIMERS)
-	unsigned long flags;
-	unsigned long jiffies_now;
-	unsigned long seq;
-
-	if (del_timer(&(smi_info->si_timer))) {
-		/* If we don't delete the timer, then it will go off
-		   immediately, anyway.  So we only process if we
-		   actually delete the timer. */
-
-		do {
-			seq = read_seqbegin_irqsave(&xtime_lock, flags);
-			jiffies_now = jiffies;
-			smi_info->si_timer.expires = jiffies_now;
-			smi_info->si_timer.arch_cycle_expires
-				= get_arch_cycles(jiffies_now);
-		} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-		add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
-
-		add_timer(&(smi_info->si_timer));
-		spin_lock_irqsave(&smi_info->count_lock, flags);
-		smi_info->timeout_restarts++;
-		spin_unlock_irqrestore(&smi_info->count_lock, flags);
-	}
-#endif
-}
-
 static void smi_timeout(unsigned long data)
 {
 	struct smi_info   *smi_info = (struct smi_info *) data;
@@ -904,31 +853,15 @@
 	/* If the state machine asks for a short delay, then shorten
            the timer timeout. */
 	if (smi_result == SI_SM_CALL_WITH_DELAY) {
-#if defined(CONFIG_HIGH_RES_TIMERS)
-		unsigned long seq;
-#endif
 		spin_lock_irqsave(&smi_info->count_lock, flags);
 		smi_info->short_timeouts++;
 		spin_unlock_irqrestore(&smi_info->count_lock, flags);
-#if defined(CONFIG_HIGH_RES_TIMERS)
-		do {
-			seq = read_seqbegin_irqsave(&xtime_lock, flags);
-			smi_info->si_timer.expires = jiffies;
-			smi_info->si_timer.arch_cycle_expires
-				= get_arch_cycles(smi_info->si_timer.expires);
-		} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-		add_usec_to_timer(&smi_info->si_timer, SI_SHORT_TIMEOUT_USEC);
-#else
 		smi_info->si_timer.expires = jiffies + 1;
-#endif
 	} else {
 		spin_lock_irqsave(&smi_info->count_lock, flags);
 		smi_info->long_timeouts++;
 		spin_unlock_irqrestore(&smi_info->count_lock, flags);
 		smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES;
-#if defined(CONFIG_HIGH_RES_TIMERS)
-		smi_info->si_timer.arch_cycle_expires = 0;
-#endif
 	}
 
  do_add_timer:
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 2d11ddd..1a0a19c 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -212,24 +212,16 @@
 {
 	action_fn  fn = (action_fn) kp->arg;
 	int        rv = 0;
-	const char *end;
-	char       valcp[16];
-	int        len;
+	char       *dup, *s;
 
-	/* Truncate leading and trailing spaces. */
-	while (isspace(*val))
-		val++;
-	end = val + strlen(val) - 1;
-	while ((end >= val) && isspace(*end))
-		end--;
-	len = end - val + 1;
-	if (len > sizeof(valcp) - 1)
-		return -EINVAL;
-	memcpy(valcp, val, len);
-	valcp[len] = '\0';
+	dup = kstrdup(val, GFP_KERNEL);
+	if (!dup)
+		return -ENOMEM;
+
+	s = strstrip(dup);
 
 	down_read(&register_sem);
-	rv = fn(valcp, NULL);
+	rv = fn(s, NULL);
 	if (rv)
 		goto out_unlock;
 
@@ -239,6 +231,7 @@
 
  out_unlock:
 	up_read(&register_sem);
+	kfree(dup);
 	return rv;
 }
 
@@ -956,9 +949,10 @@
 			/* Disable the WDT if we are shutting down. */
 			ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
 			panic_halt_ipmi_set_timeout();
-		} else {
+		} else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
 			/* Set a long timer to let the reboot happens, but
-			   reboot if it hangs. */
+			   reboot if it hangs, but only if the watchdog
+			   timer was already running. */
 			timeout = 120;
 			pretimeout = 0;
 			ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
@@ -980,16 +974,17 @@
 {
 	static int panic_event_handled = 0;
 
-	/* On a panic, if we have a panic timeout, make sure that the thing
-	   reboots, even if it hangs during that panic. */
-	if (watchdog_user && !panic_event_handled) {
-		/* Make sure the panic doesn't hang, and make sure we
-		   do this only once. */
+	/* On a panic, if we have a panic timeout, make sure to extend
+	   the watchdog timer to a reasonable value to complete the
+	   panic, if the watchdog timer is running.  Plus the
+	   pretimeout is meaningless at panic time. */
+	if (watchdog_user && !panic_event_handled &&
+	    ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
+		/* Make sure we do this only once. */
 		panic_event_handled = 1;
 	    
 		timeout = 255;
 		pretimeout = 0;
-		ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
 		panic_halt_ipmi_set_timeout();
 	}
 
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index e9ebaba..efaaa19 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1145,7 +1145,7 @@
 	if (isicom_paranoia_check(port, tty->name, "isicom_write"))
 		return 0;
 
-	if (!tty || !port->xmit_buf)
+	if (!port->xmit_buf)
 		return 0;
 
 	spin_lock_irqsave(&card->card_lock, flags);
@@ -1180,7 +1180,7 @@
 	if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
 		return;
 
-	if (!tty || !port->xmit_buf)
+	if (!port->xmit_buf)
 		return;
 
 	spin_lock_irqsave(&card->card_lock, flags);
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index ef20c1f..216c792 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -42,13 +42,12 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/device.h>
 #include <linux/wait.h>
+#include <linux/eisa.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_PCI
 #include <linux/pci.h>
-#endif
 
 /*****************************************************************************/
 
@@ -137,6 +136,10 @@
 
 static int	stli_nrbrds = ARRAY_SIZE(stli_brdconf);
 
+/* stli_lock must NOT be taken holding brd_lock */
+static spinlock_t stli_lock;	/* TTY logic lock */
+static spinlock_t brd_lock;	/* Board logic lock */
+
 /*
  *	There is some experimental EISA board detection code in this driver.
  *	By default it is disabled, but for those that want to try it out,
@@ -173,14 +176,6 @@
 
 static struct tty_driver	*stli_serial;
 
-/*
- *	We will need to allocate a temporary write buffer for chars that
- *	come direct from user space. The problem is that a copy from user
- *	space might cause a page fault (typically on a system that is
- *	swapping!). All ports will share one buffer - since if the system
- *	is already swapping a shared buffer won't make things any worse.
- */
-static char			*stli_tmpwritebuf;
 
 #define	STLI_TXBUFSIZE		4096
 
@@ -419,7 +414,7 @@
 #endif
 
 static struct pci_device_id istallion_pci_tbl[] = {
-	{ PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
@@ -682,7 +677,7 @@
 static ssize_t	stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
 static ssize_t	stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
 static int	stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
-static void	stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp);
+static void	stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp);
 static void	stli_poll(unsigned long arg);
 static int	stli_hostcmd(stlibrd_t *brdp, stliport_t *portp);
 static int	stli_initopen(stlibrd_t *brdp, stliport_t *portp);
@@ -693,7 +688,8 @@
 static int	stli_setport(stliport_t *portp);
 static int	stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
 static void	stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp);
+static void	__stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback);
+static void	stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp);
 static void	stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp);
 static void	stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
 static long	stli_mktiocm(unsigned long sigvalue);
@@ -799,18 +795,8 @@
 
 static int __init istallion_module_init(void)
 {
-	unsigned long	flags;
-
-#ifdef DEBUG
-	printk("init_module()\n");
-#endif
-
-	save_flags(flags);
-	cli();
 	stli_init();
-	restore_flags(flags);
-
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -819,33 +805,24 @@
 {
 	stlibrd_t	*brdp;
 	stliport_t	*portp;
-	unsigned long	flags;
 	int		i, j;
 
-#ifdef DEBUG
-	printk("cleanup_module()\n");
-#endif
-
 	printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
 		stli_drvversion);
 
-	save_flags(flags);
-	cli();
-
-/*
- *	Free up all allocated resources used by the ports. This includes
- *	memory and interrupts.
- */
+	/*
+	 *	Free up all allocated resources used by the ports. This includes
+	 *	memory and interrupts.
+	 */
 	if (stli_timeron) {
 		stli_timeron = 0;
-		del_timer(&stli_timerlist);
+		del_timer_sync(&stli_timerlist);
 	}
 
 	i = tty_unregister_driver(stli_serial);
 	if (i) {
 		printk("STALLION: failed to un-register tty driver, "
 			"errno=%d\n", -i);
-		restore_flags(flags);
 		return;
 	}
 	put_tty_driver(stli_serial);
@@ -859,16 +836,15 @@
 		printk("STALLION: failed to un-register serial memory device, "
 			"errno=%d\n", -i);
 
-	kfree(stli_tmpwritebuf);
 	kfree(stli_txcookbuf);
 
 	for (i = 0; (i < stli_nrbrds); i++) {
-		if ((brdp = stli_brds[i]) == (stlibrd_t *) NULL)
+		if ((brdp = stli_brds[i]) == NULL)
 			continue;
 		for (j = 0; (j < STL_MAXPORTS); j++) {
 			portp = brdp->ports[j];
-			if (portp != (stliport_t *) NULL) {
-				if (portp->tty != (struct tty_struct *) NULL)
+			if (portp != NULL) {
+				if (portp->tty != NULL)
 					tty_hangup(portp->tty);
 				kfree(portp);
 			}
@@ -878,10 +854,8 @@
 		if (brdp->iosize > 0)
 			release_region(brdp->iobase, brdp->iosize);
 		kfree(brdp);
-		stli_brds[i] = (stlibrd_t *) NULL;
+		stli_brds[i] = NULL;
 	}
-
-	restore_flags(flags);
 }
 
 module_init(istallion_module_init);
@@ -895,19 +869,15 @@
 
 static void stli_argbrds(void)
 {
-	stlconf_t	conf;
-	stlibrd_t	*brdp;
-	int		i;
-
-#ifdef DEBUG
-	printk("stli_argbrds()\n");
-#endif
+	stlconf_t conf;
+	stlibrd_t *brdp;
+	int i;
 
 	for (i = stli_nrbrds; i < ARRAY_SIZE(stli_brdsp); i++) {
 		memset(&conf, 0, sizeof(conf));
 		if (stli_parsebrd(&conf, stli_brdsp[i]) == 0)
 			continue;
-		if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
+		if ((brdp = stli_allocbrd()) == NULL)
 			continue;
 		stli_nrbrds = i + 1;
 		brdp->brdnr = i;
@@ -926,9 +896,9 @@
 
 static unsigned long stli_atol(char *str)
 {
-	unsigned long	val;
-	int		base, c;
-	char		*sp;
+	unsigned long val;
+	int base, c;
+	char *sp;
 
 	val = 0;
 	sp = str;
@@ -962,15 +932,11 @@
 
 static int stli_parsebrd(stlconf_t *confp, char **argp)
 {
-	char	*sp;
-	int	i;
+	char *sp;
+	int i;
 
-#ifdef DEBUG
-	printk("stli_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
-#endif
-
-	if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
-		return(0);
+	if (argp[0] == NULL || *argp[0] == 0)
+		return 0;
 
 	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
 		*sp = TOLOWER(*sp);
@@ -985,9 +951,9 @@
 	}
 
 	confp->brdtype = stli_brdstr[i].type;
-	if ((argp[1] != (char *) NULL) && (*argp[1] != 0))
+	if (argp[1] != NULL && *argp[1] != 0)
 		confp->ioaddr1 = stli_atol(argp[1]);
-	if ((argp[2] != (char *) NULL) && (*argp[2] != 0))
+	if (argp[2] !=  NULL && *argp[2] != 0)
 		confp->memaddr = stli_atol(argp[2]);
 	return(1);
 }
@@ -998,34 +964,29 @@
 
 static int stli_open(struct tty_struct *tty, struct file *filp)
 {
-	stlibrd_t	*brdp;
-	stliport_t	*portp;
-	unsigned int	minordev;
-	int		brdnr, portnr, rc;
-
-#ifdef DEBUG
-	printk("stli_open(tty=%x,filp=%x): device=%s\n", (int) tty,
-		(int) filp, tty->name);
-#endif
+	stlibrd_t *brdp;
+	stliport_t *portp;
+	unsigned int minordev;
+	int brdnr, portnr, rc;
 
 	minordev = tty->index;
 	brdnr = MINOR2BRD(minordev);
 	if (brdnr >= stli_nrbrds)
-		return(-ENODEV);
+		return -ENODEV;
 	brdp = stli_brds[brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(-ENODEV);
+	if (brdp == NULL)
+		return -ENODEV;
 	if ((brdp->state & BST_STARTED) == 0)
-		return(-ENODEV);
+		return -ENODEV;
 	portnr = MINOR2PORT(minordev);
 	if ((portnr < 0) || (portnr > brdp->nrports))
-		return(-ENODEV);
+		return -ENODEV;
 
 	portp = brdp->ports[portnr];
-	if (portp == (stliport_t *) NULL)
-		return(-ENODEV);
+	if (portp == NULL)
+		return -ENODEV;
 	if (portp->devnr < 1)
-		return(-ENODEV);
+		return -ENODEV;
 
 
 /*
@@ -1037,8 +998,8 @@
 	if (portp->flags & ASYNC_CLOSING) {
 		interruptible_sleep_on(&portp->close_wait);
 		if (portp->flags & ASYNC_HUP_NOTIFY)
-			return(-EAGAIN);
-		return(-ERESTARTSYS);
+			return -EAGAIN;
+		return -ERESTARTSYS;
 	}
 
 /*
@@ -1054,7 +1015,7 @@
 	wait_event_interruptible(portp->raw_wait,
 			!test_bit(ST_INITIALIZING, &portp->state));
 	if (signal_pending(current))
-		return(-ERESTARTSYS);
+		return -ERESTARTSYS;
 
 	if ((portp->flags & ASYNC_INITIALIZED) == 0) {
 		set_bit(ST_INITIALIZING, &portp->state);
@@ -1065,7 +1026,7 @@
 		clear_bit(ST_INITIALIZING, &portp->state);
 		wake_up_interruptible(&portp->raw_wait);
 		if (rc < 0)
-			return(rc);
+			return rc;
 	}
 
 /*
@@ -1077,8 +1038,8 @@
 	if (portp->flags & ASYNC_CLOSING) {
 		interruptible_sleep_on(&portp->close_wait);
 		if (portp->flags & ASYNC_HUP_NOTIFY)
-			return(-EAGAIN);
-		return(-ERESTARTSYS);
+			return -EAGAIN;
+		return -ERESTARTSYS;
 	}
 
 /*
@@ -1088,38 +1049,33 @@
  */
 	if (!(filp->f_flags & O_NONBLOCK)) {
 		if ((rc = stli_waitcarrier(brdp, portp, filp)) != 0)
-			return(rc);
+			return rc;
 	}
 	portp->flags |= ASYNC_NORMAL_ACTIVE;
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
 
 static void stli_close(struct tty_struct *tty, struct file *filp)
 {
-	stlibrd_t	*brdp;
-	stliport_t	*portp;
-	unsigned long	flags;
-
-#ifdef DEBUG
-	printk("stli_close(tty=%x,filp=%x)\n", (int) tty, (int) filp);
-#endif
+	stlibrd_t *brdp;
+	stliport_t *portp;
+	unsigned long flags;
 
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&stli_lock, flags);
 	if (tty_hung_up_p(filp)) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&stli_lock, flags);
 		return;
 	}
 	if ((tty->count == 1) && (portp->refcount != 1))
 		portp->refcount = 1;
 	if (portp->refcount-- > 1) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&stli_lock, flags);
 		return;
 	}
 
@@ -1134,6 +1090,8 @@
 	if (tty == stli_txcooktty)
 		stli_flushchars(tty);
 	tty->closing = 1;
+	spin_unlock_irqrestore(&stli_lock, flags);
+
 	if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, portp->closing_wait);
 
@@ -1157,7 +1115,7 @@
 	stli_flushbuffer(tty);
 
 	tty->closing = 0;
-	portp->tty = (struct tty_struct *) NULL;
+	portp->tty = NULL;
 
 	if (portp->openwaitcnt) {
 		if (portp->close_delay)
@@ -1167,7 +1125,6 @@
 
 	portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 	wake_up_interruptible(&portp->close_wait);
-	restore_flags(flags);
 }
 
 /*****************************************************************************/
@@ -1182,45 +1139,41 @@
 
 static int stli_initopen(stlibrd_t *brdp, stliport_t *portp)
 {
-	struct tty_struct	*tty;
-	asynotify_t		nt;
-	asyport_t		aport;
-	int			rc;
-
-#ifdef DEBUG
-	printk("stli_initopen(brdp=%x,portp=%x)\n", (int) brdp, (int) portp);
-#endif
+	struct tty_struct *tty;
+	asynotify_t nt;
+	asyport_t aport;
+	int rc;
 
 	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
-		return(rc);
+		return rc;
 
 	memset(&nt, 0, sizeof(asynotify_t));
 	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
 	nt.signal = SG_DCD;
 	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
 	    sizeof(asynotify_t), 0)) < 0)
-		return(rc);
+		return rc;
 
 	tty = portp->tty;
-	if (tty == (struct tty_struct *) NULL)
-		return(-ENODEV);
+	if (tty == NULL)
+		return -ENODEV;
 	stli_mkasyport(portp, &aport, tty->termios);
 	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
 	    sizeof(asyport_t), 0)) < 0)
-		return(rc);
+		return rc;
 
 	set_bit(ST_GETSIGS, &portp->state);
 	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
 	    sizeof(asysigs_t), 1)) < 0)
-		return(rc);
+		return rc;
 	if (test_and_clear_bit(ST_GETSIGS, &portp->state))
 		portp->sigs = stli_mktiocm(portp->asig.sigvalue);
 	stli_mkasysigs(&portp->asig, 1, 1);
 	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 	    sizeof(asysigs_t), 0)) < 0)
-		return(rc);
+		return rc;
 
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -1234,22 +1187,15 @@
 
 static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
 {
-	volatile cdkhdr_t	*hdrp;
-	volatile cdkctrl_t	*cp;
-	volatile unsigned char	*bits;
-	unsigned long		flags;
-	int			rc;
-
-#ifdef DEBUG
-	printk("stli_rawopen(brdp=%x,portp=%x,arg=%x,wait=%d)\n",
-		(int) brdp, (int) portp, (int) arg, wait);
-#endif
+	cdkhdr_t __iomem *hdrp;
+	cdkctrl_t __iomem *cp;
+	unsigned char __iomem *bits;
+	unsigned long flags;
+	int rc;
 
 /*
  *	Send a message to the slave to open this port.
  */
-	save_flags(flags);
-	cli();
 
 /*
  *	Slave is already closing this port. This can happen if a hangup
@@ -1260,7 +1206,6 @@
 	wait_event_interruptible(portp->raw_wait,
 			!test_bit(ST_CLOSING, &portp->state));
 	if (signal_pending(current)) {
-		restore_flags(flags);
 		return -ERESTARTSYS;
 	}
 
@@ -1269,19 +1214,20 @@
  *	memory. Once the message is in set the service bits to say that
  *	this port wants service.
  */
+	spin_lock_irqsave(&brd_lock, flags);
 	EBRDENABLE(brdp);
-	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	cp->openarg = arg;
-	cp->open = 1;
-	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
+	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
+	writel(arg, &cp->openarg);
+	writeb(1, &cp->open);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
 		portp->portidx;
-	*bits |= portp->portbit;
+	writeb(readb(bits) | portp->portbit, bits);
 	EBRDDISABLE(brdp);
 
 	if (wait == 0) {
-		restore_flags(flags);
-		return(0);
+		spin_unlock_irqrestore(&brd_lock, flags);
+		return 0;
 	}
 
 /*
@@ -1290,15 +1236,16 @@
  */
 	rc = 0;
 	set_bit(ST_OPENING, &portp->state);
+	spin_unlock_irqrestore(&brd_lock, flags);
+
 	wait_event_interruptible(portp->raw_wait,
 			!test_bit(ST_OPENING, &portp->state));
 	if (signal_pending(current))
 		rc = -ERESTARTSYS;
-	restore_flags(flags);
 
 	if ((rc == 0) && (portp->rc != 0))
 		rc = -EIO;
-	return(rc);
+	return rc;
 }
 
 /*****************************************************************************/
@@ -1311,19 +1258,11 @@
 
 static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
 {
-	volatile cdkhdr_t	*hdrp;
-	volatile cdkctrl_t	*cp;
-	volatile unsigned char	*bits;
-	unsigned long		flags;
-	int			rc;
-
-#ifdef DEBUG
-	printk("stli_rawclose(brdp=%x,portp=%x,arg=%x,wait=%d)\n",
-		(int) brdp, (int) portp, (int) arg, wait);
-#endif
-
-	save_flags(flags);
-	cli();
+	cdkhdr_t __iomem *hdrp;
+	cdkctrl_t __iomem *cp;
+	unsigned char __iomem *bits;
+	unsigned long flags;
+	int rc;
 
 /*
  *	Slave is already closing this port. This can happen if a hangup
@@ -1333,7 +1272,6 @@
 		wait_event_interruptible(portp->raw_wait,
 				!test_bit(ST_CLOSING, &portp->state));
 		if (signal_pending(current)) {
-			restore_flags(flags);
 			return -ERESTARTSYS;
 		}
 	}
@@ -1341,21 +1279,22 @@
 /*
  *	Write the close command into shared memory.
  */
+	spin_lock_irqsave(&brd_lock, flags);
 	EBRDENABLE(brdp);
-	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	cp->closearg = arg;
-	cp->close = 1;
-	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
+	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
+	writel(arg, &cp->closearg);
+	writeb(1, &cp->close);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
 		portp->portidx;
-	*bits |= portp->portbit;
+	writeb(readb(bits) |portp->portbit, bits);
 	EBRDDISABLE(brdp);
 
 	set_bit(ST_CLOSING, &portp->state);
-	if (wait == 0) {
-		restore_flags(flags);
-		return(0);
-	}
+	spin_unlock_irqrestore(&brd_lock, flags);
+
+	if (wait == 0)
+		return 0;
 
 /*
  *	Slave is in action, so now we must wait for the open acknowledgment
@@ -1366,11 +1305,10 @@
 			!test_bit(ST_CLOSING, &portp->state));
 	if (signal_pending(current))
 		rc = -ERESTARTSYS;
-	restore_flags(flags);
 
 	if ((rc == 0) && (portp->rc != 0))
 		rc = -EIO;
-	return(rc);
+	return rc;
 }
 
 /*****************************************************************************/
@@ -1384,36 +1322,21 @@
 
 static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
 {
-	unsigned long	flags;
-
-#ifdef DEBUG
-	printk("stli_cmdwait(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
-		"copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
-		(int) arg, size, copyback);
-#endif
-
-	save_flags(flags);
-	cli();
 	wait_event_interruptible(portp->raw_wait,
 			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current)) {
-		restore_flags(flags);
+	if (signal_pending(current))
 		return -ERESTARTSYS;
-	}
 
 	stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
 
 	wait_event_interruptible(portp->raw_wait,
 			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current)) {
-		restore_flags(flags);
+	if (signal_pending(current))
 		return -ERESTARTSYS;
-	}
-	restore_flags(flags);
 
 	if (portp->rc != 0)
-		return(-EIO);
-	return(0);
+		return -EIO;
+	return 0;
 }
 
 /*****************************************************************************/
@@ -1425,22 +1348,18 @@
 
 static int stli_setport(stliport_t *portp)
 {
-	stlibrd_t	*brdp;
-	asyport_t	aport;
+	stlibrd_t *brdp;
+	asyport_t aport;
 
-#ifdef DEBUG
-	printk("stli_setport(portp=%x)\n", (int) portp);
-#endif
-
-	if (portp == (stliport_t *) NULL)
-		return(-ENODEV);
-	if (portp->tty == (struct tty_struct *) NULL)
-		return(-ENODEV);
-	if ((portp->brdnr < 0) && (portp->brdnr >= stli_nrbrds))
-		return(-ENODEV);
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->tty == NULL)
+		return -ENODEV;
+	if (portp->brdnr < 0 && portp->brdnr >= stli_nrbrds)
+		return -ENODEV;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(-ENODEV);
+	if (brdp == NULL)
+		return -ENODEV;
 
 	stli_mkasyport(portp, &aport, portp->tty->termios);
 	return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
@@ -1455,13 +1374,8 @@
 
 static int stli_waitcarrier(stlibrd_t *brdp, stliport_t *portp, struct file *filp)
 {
-	unsigned long	flags;
-	int		rc, doclocal;
-
-#ifdef DEBUG
-	printk("stli_waitcarrier(brdp=%x,portp=%x,filp=%x)\n",
-		(int) brdp, (int) portp, (int) filp);
-#endif
+	unsigned long flags;
+	int rc, doclocal;
 
 	rc = 0;
 	doclocal = 0;
@@ -1469,11 +1383,11 @@
 	if (portp->tty->termios->c_cflag & CLOCAL)
 		doclocal++;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&stli_lock, flags);
 	portp->openwaitcnt++;
 	if (! tty_hung_up_p(filp))
 		portp->refcount--;
+	spin_unlock_irqrestore(&stli_lock, flags);
 
 	for (;;) {
 		stli_mkasysigs(&portp->asig, 1, 1);
@@ -1499,12 +1413,13 @@
 		interruptible_sleep_on(&portp->open_wait);
 	}
 
+	spin_lock_irqsave(&stli_lock, flags);
 	if (! tty_hung_up_p(filp))
 		portp->refcount++;
 	portp->openwaitcnt--;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&stli_lock, flags);
 
-	return(rc);
+	return rc;
 }
 
 /*****************************************************************************/
@@ -1517,46 +1432,38 @@
 
 static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
-	volatile cdkasy_t	*ap;
-	volatile cdkhdr_t	*hdrp;
-	volatile unsigned char	*bits;
-	unsigned char		*shbuf, *chbuf;
-	stliport_t		*portp;
-	stlibrd_t		*brdp;
-	unsigned int		len, stlen, head, tail, size;
-	unsigned long		flags;
+	cdkasy_t __iomem *ap;
+	cdkhdr_t __iomem *hdrp;
+	unsigned char __iomem *bits;
+	unsigned char __iomem *shbuf;
+	unsigned char *chbuf;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	unsigned int len, stlen, head, tail, size;
+	unsigned long flags;
 
-#ifdef DEBUG
-	printk("stli_write(tty=%x,buf=%x,count=%d)\n",
-		(int) tty, (int) buf, count);
-#endif
-
-	if ((tty == (struct tty_struct *) NULL) ||
-	    (stli_tmpwritebuf == (char *) NULL))
-		return(0);
 	if (tty == stli_txcooktty)
 		stli_flushchars(tty);
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return(0);
+	if (portp == NULL)
+		return 0;
 	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return(0);
+		return 0;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(0);
+	if (brdp == NULL)
+		return 0;
 	chbuf = (unsigned char *) buf;
 
 /*
  *	All data is now local, shove as much as possible into shared memory.
  */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	EBRDENABLE(brdp);
-	ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) ap->txq.head;
-	tail = (unsigned int) ap->txq.tail;
-	if (tail != ((unsigned int) ap->txq.tail))
-		tail = (unsigned int) ap->txq.tail;
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	head = (unsigned int) readw(&ap->txq.head);
+	tail = (unsigned int) readw(&ap->txq.tail);
+	if (tail != ((unsigned int) readw(&ap->txq.tail)))
+		tail = (unsigned int) readw(&ap->txq.tail);
 	size = portp->txsize;
 	if (head >= tail) {
 		len = size - (head - tail) - 1;
@@ -1568,11 +1475,11 @@
 
 	len = MIN(len, count);
 	count = 0;
-	shbuf = (char *) EBRDGETMEMPTR(brdp, portp->txoffset);
+	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
 
 	while (len > 0) {
 		stlen = MIN(len, stlen);
-		memcpy((shbuf + head), chbuf, stlen);
+		memcpy_toio(shbuf + head, chbuf, stlen);
 		chbuf += stlen;
 		len -= stlen;
 		count += stlen;
@@ -1583,20 +1490,19 @@
 		}
 	}
 
-	ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
-	ap->txq.head = head;
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	writew(head, &ap->txq.head);
 	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (ap->changed.data & DT_TXEMPTY)
-			ap->changed.data &= ~DT_TXEMPTY;
+		if (readl(&ap->changed.data) & DT_TXEMPTY)
+			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
 	}
-	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
 		portp->portidx;
-	*bits |= portp->portbit;
+	writeb(readb(bits) | portp->portbit, bits);
 	set_bit(ST_TXBUSY, &portp->state);
 	EBRDDISABLE(brdp);
-
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
 	return(count);
 }
@@ -1613,14 +1519,8 @@
 
 static void stli_putchar(struct tty_struct *tty, unsigned char ch)
 {
-#ifdef DEBUG
-	printk("stli_putchar(tty=%x,ch=%x)\n", (int) tty, (int) ch);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return;
 	if (tty != stli_txcooktty) {
-		if (stli_txcooktty != (struct tty_struct *) NULL)
+		if (stli_txcooktty != NULL)
 			stli_flushchars(stli_txcooktty);
 		stli_txcooktty = tty;
 	}
@@ -1640,29 +1540,26 @@
 
 static void stli_flushchars(struct tty_struct *tty)
 {
-	volatile cdkhdr_t	*hdrp;
-	volatile unsigned char	*bits;
-	volatile cdkasy_t	*ap;
-	struct tty_struct	*cooktty;
-	stliport_t		*portp;
-	stlibrd_t		*brdp;
-	unsigned int		len, stlen, head, tail, size, count, cooksize;
-	unsigned char		*buf, *shbuf;
-	unsigned long		flags;
-
-#ifdef DEBUG
-	printk("stli_flushchars(tty=%x)\n", (int) tty);
-#endif
+	cdkhdr_t __iomem *hdrp;
+	unsigned char __iomem *bits;
+	cdkasy_t __iomem *ap;
+	struct tty_struct *cooktty;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	unsigned int len, stlen, head, tail, size, count, cooksize;
+	unsigned char *buf;
+	unsigned char __iomem *shbuf;
+	unsigned long flags;
 
 	cooksize = stli_txcooksize;
 	cooktty = stli_txcooktty;
 	stli_txcooksize = 0;
 	stli_txcookrealsize = 0;
-	stli_txcooktty = (struct tty_struct *) NULL;
+	stli_txcooktty = NULL;
 
-	if (tty == (struct tty_struct *) NULL)
+	if (tty == NULL)
 		return;
-	if (cooktty == (struct tty_struct *) NULL)
+	if (cooktty == NULL)
 		return;
 	if (tty != cooktty)
 		tty = cooktty;
@@ -1670,23 +1567,22 @@
 		return;
 
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
 	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
 		return;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
+	if (brdp == NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	EBRDENABLE(brdp);
 
-	ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) ap->txq.head;
-	tail = (unsigned int) ap->txq.tail;
-	if (tail != ((unsigned int) ap->txq.tail))
-		tail = (unsigned int) ap->txq.tail;
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	head = (unsigned int) readw(&ap->txq.head);
+	tail = (unsigned int) readw(&ap->txq.tail);
+	if (tail != ((unsigned int) readw(&ap->txq.tail)))
+		tail = (unsigned int) readw(&ap->txq.tail);
 	size = portp->txsize;
 	if (head >= tail) {
 		len = size - (head - tail) - 1;
@@ -1703,7 +1599,7 @@
 
 	while (len > 0) {
 		stlen = MIN(len, stlen);
-		memcpy((shbuf + head), buf, stlen);
+		memcpy_toio(shbuf + head, buf, stlen);
 		buf += stlen;
 		len -= stlen;
 		count += stlen;
@@ -1714,73 +1610,66 @@
 		}
 	}
 
-	ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
-	ap->txq.head = head;
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+	writew(head, &ap->txq.head);
 
 	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (ap->changed.data & DT_TXEMPTY)
-			ap->changed.data &= ~DT_TXEMPTY;
+		if (readl(&ap->changed.data) & DT_TXEMPTY)
+			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
 	}
-	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
 		portp->portidx;
-	*bits |= portp->portbit;
+	writeb(readb(bits) | portp->portbit, bits);
 	set_bit(ST_TXBUSY, &portp->state);
 
 	EBRDDISABLE(brdp);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
 
 static int stli_writeroom(struct tty_struct *tty)
 {
-	volatile cdkasyrq_t	*rp;
-	stliport_t		*portp;
-	stlibrd_t		*brdp;
-	unsigned int		head, tail, len;
-	unsigned long		flags;
+	cdkasyrq_t __iomem *rp;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	unsigned int head, tail, len;
+	unsigned long flags;
 
-#ifdef DEBUG
-	printk("stli_writeroom(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return(0);
 	if (tty == stli_txcooktty) {
 		if (stli_txcookrealsize != 0) {
 			len = stli_txcookrealsize - stli_txcooksize;
-			return(len);
+			return len;
 		}
 	}
 
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return(0);
+	if (portp == NULL)
+		return 0;
 	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return(0);
+		return 0;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(0);
+	if (brdp == NULL)
+		return 0;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	EBRDENABLE(brdp);
-	rp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) rp->head;
-	tail = (unsigned int) rp->tail;
-	if (tail != ((unsigned int) rp->tail))
-		tail = (unsigned int) rp->tail;
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
+	head = (unsigned int) readw(&rp->head);
+	tail = (unsigned int) readw(&rp->tail);
+	if (tail != ((unsigned int) readw(&rp->tail)))
+		tail = (unsigned int) readw(&rp->tail);
 	len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head);
 	len--;
 	EBRDDISABLE(brdp);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
 	if (tty == stli_txcooktty) {
 		stli_txcookrealsize = len;
 		len -= stli_txcooksize;
 	}
-	return(len);
+	return len;
 }
 
 /*****************************************************************************/
@@ -1795,44 +1684,37 @@
 
 static int stli_charsinbuffer(struct tty_struct *tty)
 {
-	volatile cdkasyrq_t	*rp;
-	stliport_t		*portp;
-	stlibrd_t		*brdp;
-	unsigned int		head, tail, len;
-	unsigned long		flags;
+	cdkasyrq_t __iomem *rp;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	unsigned int head, tail, len;
+	unsigned long flags;
 
-#ifdef DEBUG
-	printk("stli_charsinbuffer(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return(0);
 	if (tty == stli_txcooktty)
 		stli_flushchars(tty);
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return(0);
+	if (portp == NULL)
+		return 0;
 	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return(0);
+		return 0;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(0);
+	if (brdp == NULL)
+		return 0;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	EBRDENABLE(brdp);
-	rp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) rp->head;
-	tail = (unsigned int) rp->tail;
-	if (tail != ((unsigned int) rp->tail))
-		tail = (unsigned int) rp->tail;
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
+	head = (unsigned int) readw(&rp->head);
+	tail = (unsigned int) readw(&rp->tail);
+	if (tail != ((unsigned int) readw(&rp->tail)))
+		tail = (unsigned int) readw(&rp->tail);
 	len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head));
 	if ((len == 0) && test_bit(ST_TXBUSY, &portp->state))
 		len = 1;
 	EBRDDISABLE(brdp);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
-	return(len);
+	return len;
 }
 
 /*****************************************************************************/
@@ -1843,12 +1725,8 @@
 
 static int stli_getserial(stliport_t *portp, struct serial_struct __user *sp)
 {
-	struct serial_struct	sio;
-	stlibrd_t		*brdp;
-
-#ifdef DEBUG
-	printk("stli_getserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
-#endif
+	struct serial_struct sio;
+	stlibrd_t *brdp;
 
 	memset(&sio, 0, sizeof(struct serial_struct));
 	sio.type = PORT_UNKNOWN;
@@ -1863,7 +1741,7 @@
 	sio.hub6 = 0;
 
 	brdp = stli_brds[portp->brdnr];
-	if (brdp != (stlibrd_t *) NULL)
+	if (brdp != NULL)
 		sio.port = brdp->iobase;
 		
 	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ?
@@ -1880,12 +1758,8 @@
 
 static int stli_setserial(stliport_t *portp, struct serial_struct __user *sp)
 {
-	struct serial_struct	sio;
-	int			rc;
-
-#ifdef DEBUG
-	printk("stli_setserial(portp=%p,sp=%p)\n", portp, sp);
-#endif
+	struct serial_struct sio;
+	int rc;
 
 	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
 		return -EFAULT;
@@ -1894,7 +1768,7 @@
 		    (sio.close_delay != portp->close_delay) ||
 		    ((sio.flags & ~ASYNC_USR_MASK) !=
 		    (portp->flags & ~ASYNC_USR_MASK)))
-			return(-EPERM);
+			return -EPERM;
 	} 
 
 	portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
@@ -1905,8 +1779,8 @@
 	portp->custom_divisor = sio.custom_divisor;
 
 	if ((rc = stli_setport(portp)) < 0)
-		return(rc);
-	return(0);
+		return rc;
+	return 0;
 }
 
 /*****************************************************************************/
@@ -1917,19 +1791,19 @@
 	stlibrd_t *brdp;
 	int rc;
 
-	if (portp == (stliport_t *) NULL)
-		return(-ENODEV);
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return(0);
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+		return 0;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(0);
+	if (brdp == NULL)
+		return 0;
 	if (tty->flags & (1 << TTY_IO_ERROR))
-		return(-EIO);
+		return -EIO;
 
 	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
 			       &portp->asig, sizeof(asysigs_t), 1)) < 0)
-		return(rc);
+		return rc;
 
 	return stli_mktiocm(portp->asig.sigvalue);
 }
@@ -1941,15 +1815,15 @@
 	stlibrd_t *brdp;
 	int rts = -1, dtr = -1;
 
-	if (portp == (stliport_t *) NULL)
-		return(-ENODEV);
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return(0);
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+		return 0;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(0);
+	if (brdp == NULL)
+		return 0;
 	if (tty->flags & (1 << TTY_IO_ERROR))
-		return(-EIO);
+		return -EIO;
 
 	if (set & TIOCM_RTS)
 		rts = 1;
@@ -1968,32 +1842,25 @@
 
 static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	stliport_t	*portp;
-	stlibrd_t	*brdp;
-	unsigned int	ival;
-	int		rc;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	unsigned int ival;
+	int rc;
 	void __user *argp = (void __user *)arg;
 
-#ifdef DEBUG
-	printk("stli_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n",
-		(int) tty, (int) file, cmd, (int) arg);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return(-ENODEV);
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return(-ENODEV);
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return(0);
+	if (portp == NULL)
+		return -ENODEV;
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
+		return 0;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(0);
+	if (brdp == NULL)
+		return 0;
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
  	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
-			return(-EIO);
+			return -EIO;
 	}
 
 	rc = 0;
@@ -2040,7 +1907,7 @@
 		break;
 	}
 
-	return(rc);
+	return rc;
 }
 
 /*****************************************************************************/
@@ -2052,24 +1919,20 @@
 
 static void stli_settermios(struct tty_struct *tty, struct termios *old)
 {
-	stliport_t	*portp;
-	stlibrd_t	*brdp;
-	struct termios	*tiosp;
-	asyport_t	aport;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	struct termios *tiosp;
+	asyport_t aport;
 
-#ifdef DEBUG
-	printk("stli_settermios(tty=%x,old=%x)\n", (int) tty, (int) old);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
+	if (tty == NULL)
 		return;
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
 		return;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
+	if (brdp == NULL)
 		return;
 
 	tiosp = tty->termios;
@@ -2102,18 +1965,9 @@
 
 static void stli_throttle(struct tty_struct *tty)
 {
-	stliport_t	*portp;
-
-#ifdef DEBUG
-	printk("stli_throttle(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
+	stliport_t	*portp = tty->driver_data;
+	if (portp == NULL)
 		return;
-	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return;
-
 	set_bit(ST_RXSTOP, &portp->state);
 }
 
@@ -2127,88 +1981,30 @@
 
 static void stli_unthrottle(struct tty_struct *tty)
 {
-	stliport_t	*portp;
-
-#ifdef DEBUG
-	printk("stli_unthrottle(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
+	stliport_t	*portp = tty->driver_data;
+	if (portp == NULL)
 		return;
-	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return;
-
 	clear_bit(ST_RXSTOP, &portp->state);
 }
 
 /*****************************************************************************/
 
 /*
- *	Stop the transmitter. Basically to do this we will just turn TX
- *	interrupts off.
+ *	Stop the transmitter.
  */
 
 static void stli_stop(struct tty_struct *tty)
 {
-	stlibrd_t	*brdp;
-	stliport_t	*portp;
-	asyctrl_t	actrl;
-
-#ifdef DEBUG
-	printk("stli_stop(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return;
-	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return;
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return;
-
-	memset(&actrl, 0, sizeof(asyctrl_t));
-	actrl.txctrl = CT_STOPFLOW;
-#if 0
-	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
-#endif
 }
 
 /*****************************************************************************/
 
 /*
- *	Start the transmitter again. Just turn TX interrupts back on.
+ *	Start the transmitter again.
  */
 
 static void stli_start(struct tty_struct *tty)
 {
-	stliport_t	*portp;
-	stlibrd_t	*brdp;
-	asyctrl_t	actrl;
-
-#ifdef DEBUG
-	printk("stli_start(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return;
-	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
-		return;
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return;
-
-	memset(&actrl, 0, sizeof(asyctrl_t));
-	actrl.txctrl = CT_STARTFLOW;
-#if 0
-	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
-#endif
 }
 
 /*****************************************************************************/
@@ -2224,22 +2020,9 @@
 
 static void stli_dohangup(void *arg)
 {
-	stliport_t	*portp;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_dohangup(portp=%x)\n", (int) arg);
-#endif
-
-	/*
-	 * FIXME: There's a module removal race here: tty_hangup
-	 * calls schedule_work which will call into this
-	 * driver later.
-	 */
-	portp = (stliport_t *) arg;
-	if (portp != (stliport_t *) NULL) {
-		if (portp->tty != (struct tty_struct *) NULL) {
-			tty_hangup(portp->tty);
-		}
+	stliport_t *portp = (stliport_t *) arg;
+	if (portp->tty != NULL) {
+		tty_hangup(portp->tty);
 	}
 }
 
@@ -2254,31 +2037,25 @@
 
 static void stli_hangup(struct tty_struct *tty)
 {
-	stliport_t	*portp;
-	stlibrd_t	*brdp;
-	unsigned long	flags;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	unsigned long flags;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_hangup(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return;
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
 		return;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
+	if (brdp == NULL)
 		return;
 
 	portp->flags &= ~ASYNC_INITIALIZED;
 
-	save_flags(flags);
-	cli();
-	if (! test_bit(ST_CLOSING, &portp->state))
+	if (!test_bit(ST_CLOSING, &portp->state))
 		stli_rawclose(brdp, portp, 0, 0);
+
+	spin_lock_irqsave(&stli_lock, flags);
 	if (tty->termios->c_cflag & HUPCL) {
 		stli_mkasysigs(&portp->asig, 0, 0);
 		if (test_bit(ST_CMDING, &portp->state)) {
@@ -2290,14 +2067,15 @@
 				&portp->asig, sizeof(asysigs_t), 0);
 		}
 	}
-	restore_flags(flags);
 
 	clear_bit(ST_TXBUSY, &portp->state);
 	clear_bit(ST_RXSTOP, &portp->state);
 	set_bit(TTY_IO_ERROR, &tty->flags);
-	portp->tty = (struct tty_struct *) NULL;
+	portp->tty = NULL;
 	portp->flags &= ~ASYNC_NORMAL_ACTIVE;
 	portp->refcount = 0;
+	spin_unlock_irqrestore(&stli_lock, flags);
+
 	wake_up_interruptible(&portp->open_wait);
 }
 
@@ -2312,29 +2090,22 @@
 
 static void stli_flushbuffer(struct tty_struct *tty)
 {
-	stliport_t	*portp;
-	stlibrd_t	*brdp;
-	unsigned long	ftype, flags;
+	stliport_t *portp;
+	stlibrd_t *brdp;
+	unsigned long ftype, flags;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_flushbuffer(tty=%x)\n", (int) tty);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return;
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
 		return;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
+	if (brdp == NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	if (tty == stli_txcooktty) {
-		stli_txcooktty = (struct tty_struct *) NULL;
+		stli_txcooktty = NULL;
 		stli_txcooksize = 0;
 		stli_txcookrealsize = 0;
 	}
@@ -2346,15 +2117,10 @@
 			ftype |= FLUSHRX;
 			clear_bit(ST_DOFLUSHRX, &portp->state);
 		}
-		stli_sendcmd(brdp, portp, A_FLUSH, &ftype,
-			sizeof(unsigned long), 0);
+		__stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
 	}
-	restore_flags(flags);
-
-	wake_up_interruptible(&tty->write_wait);
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
+	spin_unlock_irqrestore(&brd_lock, flags);
+	tty_wakeup(tty);
 }
 
 /*****************************************************************************/
@@ -2364,55 +2130,31 @@
 	stlibrd_t	*brdp;
 	stliport_t	*portp;
 	long		arg;
-	/* long savestate, savetime; */
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_breakctl(tty=%x,state=%d)\n", (int) tty, state);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return;
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
 		return;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
+	if (brdp == NULL)
 		return;
 
-/*
- *	Due to a bug in the tty send_break() code we need to preserve
- *	the current process state and timeout...
-	savetime = current->timeout;
-	savestate = current->state;
- */
-
 	arg = (state == -1) ? BREAKON : BREAKOFF;
 	stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
-
-/*
- *
-	current->timeout = savetime;
-	current->state = savestate;
- */
 }
 
 /*****************************************************************************/
 
 static void stli_waituntilsent(struct tty_struct *tty, int timeout)
 {
-	stliport_t	*portp;
-	unsigned long	tend;
+	stliport_t *portp;
+	unsigned long tend;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_waituntilsent(tty=%x,timeout=%x)\n", (int) tty, timeout);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
+	if (tty == NULL)
 		return;
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
 
 	if (timeout == 0)
@@ -2436,19 +2178,13 @@
 	stliport_t	*portp;
 	asyctrl_t	actrl;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch);
-#endif
-
-	if (tty == (struct tty_struct *) NULL)
-		return;
 	portp = tty->driver_data;
-	if (portp == (stliport_t *) NULL)
+	if (portp == NULL)
 		return;
-	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
+	if (portp->brdnr < 0 || portp->brdnr >= stli_nrbrds)
 		return;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
+	if (brdp == NULL)
 		return;
 
 	memset(&actrl, 0, sizeof(asyctrl_t));
@@ -2460,7 +2196,6 @@
 		actrl.txctrl = CT_SENDCHR;
 		actrl.tximdch = ch;
 	}
-
 	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
 }
 
@@ -2476,17 +2211,17 @@
 
 static int stli_portinfo(stlibrd_t *brdp, stliport_t *portp, int portnr, char *pos)
 {
-	char	*sp, *uart;
-	int	rc, cnt;
+	char *sp, *uart;
+	int rc, cnt;
 
 	rc = stli_portcmdstats(portp);
 
 	uart = "UNKNOWN";
 	if (brdp->state & BST_STARTED) {
 		switch (stli_comstats.hwid) {
-		case 0:		uart = "2681"; break;
-		case 1:		uart = "SC26198"; break;
-		default:	uart = "CD1400"; break;
+		case 0:	uart = "2681"; break;
+		case 1:	uart = "SC26198"; break;
+		default:uart = "CD1400"; break;
 		}
 	}
 
@@ -2537,17 +2272,11 @@
 
 static int stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	stlibrd_t	*brdp;
-	stliport_t	*portp;
-	int		brdnr, portnr, totalport;
-	int		curoff, maxoff;
-	char		*pos;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x,"
-		"data=%x\n", (int) page, (int) start, (int) off, count,
-		(int) eof, (int) data);
-#endif
+	stlibrd_t *brdp;
+	stliport_t *portp;
+	int brdnr, portnr, totalport;
+	int curoff, maxoff;
+	char *pos;
 
 	pos = page;
 	totalport = 0;
@@ -2568,7 +2297,7 @@
  */
 	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
 		brdp = stli_brds[brdnr];
-		if (brdp == (stlibrd_t *) NULL)
+		if (brdp == NULL)
 			continue;
 		if (brdp->state == 0)
 			continue;
@@ -2583,7 +2312,7 @@
 		for (portnr = 0; (portnr < brdp->nrports); portnr++,
 		    totalport++) {
 			portp = brdp->ports[portnr];
-			if (portp == (stliport_t *) NULL)
+			if (portp == NULL)
 				continue;
 			if (off >= (curoff += MAXLINE))
 				continue;
@@ -2610,49 +2339,54 @@
  *	a poll routine that does not have user context. Therefore you cannot
  *	copy back directly into user space, or to the kernel stack of a
  *	process. This routine does not sleep, so can be called from anywhere.
+ *
+ *	The caller must hold the brd_lock (see also stli_sendcmd the usual
+ *	entry point)
  */
 
-static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+static void __stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
 {
-	volatile cdkhdr_t	*hdrp;
-	volatile cdkctrl_t	*cp;
-	volatile unsigned char	*bits;
-	unsigned long		flags;
+	cdkhdr_t __iomem *hdrp;
+	cdkctrl_t __iomem *cp;
+	unsigned char __iomem *bits;
+	unsigned long flags;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_sendcmd(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
-		"copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
-		(int) arg, size, copyback);
-#endif
-
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 
 	if (test_bit(ST_CMDING, &portp->state)) {
 		printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",
 				(int) cmd);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&brd_lock, flags);
 		return;
 	}
 
 	EBRDENABLE(brdp);
-	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
+	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
 	if (size > 0) {
-		memcpy((void *) &(cp->args[0]), arg, size);
+		memcpy_toio((void __iomem *) &(cp->args[0]), arg, size);
 		if (copyback) {
 			portp->argp = arg;
 			portp->argsize = size;
 		}
 	}
-	cp->status = 0;
-	cp->cmd = cmd;
-	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
+	writel(0, &cp->status);
+	writel(cmd, &cp->cmd);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
 		portp->portidx;
-	*bits |= portp->portbit;
+	writeb(readb(bits) | portp->portbit, bits);
 	set_bit(ST_CMDING, &portp->state);
 	EBRDDISABLE(brdp);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
+}
+
+static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
+{
+	unsigned long		flags;
+
+	spin_lock_irqsave(&brd_lock, flags);
+	__stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -2667,28 +2401,23 @@
 
 static void stli_read(stlibrd_t *brdp, stliport_t *portp)
 {
-	volatile cdkasyrq_t	*rp;
-	volatile char		*shbuf;
+	cdkasyrq_t __iomem *rp;
+	char __iomem *shbuf;
 	struct tty_struct	*tty;
-	unsigned int		head, tail, size;
-	unsigned int		len, stlen;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_read(brdp=%x,portp=%d)\n",
-			(int) brdp, (int) portp);
-#endif
+	unsigned int head, tail, size;
+	unsigned int len, stlen;
 
 	if (test_bit(ST_RXSTOP, &portp->state))
 		return;
 	tty = portp->tty;
-	if (tty == (struct tty_struct *) NULL)
+	if (tty == NULL)
 		return;
 
-	rp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	head = (unsigned int) rp->head;
-	if (head != ((unsigned int) rp->head))
-		head = (unsigned int) rp->head;
-	tail = (unsigned int) rp->tail;
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
+	head = (unsigned int) readw(&rp->head);
+	if (head != ((unsigned int) readw(&rp->head)))
+		head = (unsigned int) readw(&rp->head);
+	tail = (unsigned int) readw(&rp->tail);
 	size = portp->rxsize;
 	if (head >= tail) {
 		len = head - tail;
@@ -2699,12 +2428,15 @@
 	}
 
 	len = tty_buffer_request_room(tty, len);
-	/* FIXME : iomap ? */
-	shbuf = (volatile char *) EBRDGETMEMPTR(brdp, portp->rxoffset);
+
+	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset);
 
 	while (len > 0) {
+		unsigned char *cptr;
+
 		stlen = MIN(len, stlen);
-		tty_insert_flip_string(tty, (char *)(shbuf + tail), stlen);
+		tty_prepare_flip_string(tty, &cptr, stlen);
+		memcpy_fromio(cptr, shbuf + tail, stlen);
 		len -= stlen;
 		tail += stlen;
 		if (tail >= size) {
@@ -2712,8 +2444,8 @@
 			stlen = head;
 		}
 	}
-	rp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	rp->tail = tail;
+	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
+	writew(tail, &rp->tail);
 
 	if (head != tail)
 		set_bit(ST_RXING, &portp->state);
@@ -2729,9 +2461,9 @@
  *	difficult to deal with them here.
  */
 
-static void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
+static void stli_dodelaycmd(stliport_t *portp, cdkctrl_t __iomem *cp)
 {
-	int	cmd;
+	int cmd;
 
 	if (test_bit(ST_DOSIGS, &portp->state)) {
 		if (test_bit(ST_DOFLUSHTX, &portp->state) &&
@@ -2746,10 +2478,10 @@
 		clear_bit(ST_DOFLUSHTX, &portp->state);
 		clear_bit(ST_DOFLUSHRX, &portp->state);
 		clear_bit(ST_DOSIGS, &portp->state);
-		memcpy((void *) &(cp->args[0]), (void *) &portp->asig,
+		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig,
 			sizeof(asysigs_t));
-		cp->status = 0;
-		cp->cmd = cmd;
+		writel(0, &cp->status);
+		writel(cmd, &cp->cmd);
 		set_bit(ST_CMDING, &portp->state);
 	} else if (test_bit(ST_DOFLUSHTX, &portp->state) ||
 	    test_bit(ST_DOFLUSHRX, &portp->state)) {
@@ -2757,9 +2489,9 @@
 		cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0);
 		clear_bit(ST_DOFLUSHTX, &portp->state);
 		clear_bit(ST_DOFLUSHRX, &portp->state);
-		memcpy((void *) &(cp->args[0]), (void *) &cmd, sizeof(int));
-		cp->status = 0;
-		cp->cmd = A_FLUSH;
+		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int));
+		writel(0, &cp->status);
+		writel(A_FLUSH, &cp->cmd);
 		set_bit(ST_CMDING, &portp->state);
 	}
 }
@@ -2779,30 +2511,25 @@
 
 static int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
 {
-	volatile cdkasy_t	*ap;
-	volatile cdkctrl_t	*cp;
-	struct tty_struct	*tty;
-	asynotify_t		nt;
-	unsigned long		oldsigs;
-	int			rc, donerx;
+	cdkasy_t __iomem *ap;
+	cdkctrl_t __iomem *cp;
+	struct tty_struct *tty;
+	asynotify_t nt;
+	unsigned long oldsigs;
+	int rc, donerx;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_hostcmd(brdp=%x,channr=%d)\n",
-			(int) brdp, channr);
-#endif
-
-	ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
+	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
 	cp = &ap->ctrl;
 
 /*
  *	Check if we are waiting for an open completion message.
  */
 	if (test_bit(ST_OPENING, &portp->state)) {
-		rc = (int) cp->openarg;
-		if ((cp->open == 0) && (rc != 0)) {
+		rc = readl(&cp->openarg);
+		if (readb(&cp->open) == 0 && rc != 0) {
 			if (rc > 0)
 				rc--;
-			cp->openarg = 0;
+			writel(0, &cp->openarg);
 			portp->rc = rc;
 			clear_bit(ST_OPENING, &portp->state);
 			wake_up_interruptible(&portp->raw_wait);
@@ -2813,11 +2540,11 @@
  *	Check if we are waiting for a close completion message.
  */
 	if (test_bit(ST_CLOSING, &portp->state)) {
-		rc = (int) cp->closearg;
-		if ((cp->close == 0) && (rc != 0)) {
+		rc = (int) readl(&cp->closearg);
+		if (readb(&cp->close) == 0 && rc != 0) {
 			if (rc > 0)
 				rc--;
-			cp->closearg = 0;
+			writel(0, &cp->closearg);
 			portp->rc = rc;
 			clear_bit(ST_CLOSING, &portp->state);
 			wake_up_interruptible(&portp->raw_wait);
@@ -2829,16 +2556,16 @@
  *	need to copy out the command results associated with this command.
  */
 	if (test_bit(ST_CMDING, &portp->state)) {
-		rc = cp->status;
-		if ((cp->cmd == 0) && (rc != 0)) {
+		rc = readl(&cp->status);
+		if (readl(&cp->cmd) == 0 && rc != 0) {
 			if (rc > 0)
 				rc--;
-			if (portp->argp != (void *) NULL) {
-				memcpy(portp->argp, (void *) &(cp->args[0]),
+			if (portp->argp != NULL) {
+				memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]),
 					portp->argsize);
-				portp->argp = (void *) NULL;
+				portp->argp = NULL;
 			}
-			cp->status = 0;
+			writel(0, &cp->status);
 			portp->rc = rc;
 			clear_bit(ST_CMDING, &portp->state);
 			stli_dodelaycmd(portp, cp);
@@ -2877,18 +2604,15 @@
 		if (nt.data & DT_TXEMPTY)
 			clear_bit(ST_TXBUSY, &portp->state);
 		if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
-			if (tty != (struct tty_struct *) NULL) {
-				if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-				    tty->ldisc.write_wakeup) {
-					(tty->ldisc.write_wakeup)(tty);
-					EBRDENABLE(brdp);
-				}
+			if (tty != NULL) {
+				tty_wakeup(tty);
+				EBRDENABLE(brdp);
 				wake_up_interruptible(&tty->write_wait);
 			}
 		}
 
 		if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
-			if (tty != (struct tty_struct *) NULL) {
+			if (tty != NULL) {
 				tty_insert_flip_char(tty, 0, TTY_BREAK);
 				if (portp->flags & ASYNC_SAK) {
 					do_SAK(tty);
@@ -2932,14 +2656,14 @@
  *	at the cdk header structure.
  */
 
-static void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
+static void stli_brdpoll(stlibrd_t *brdp, cdkhdr_t __iomem *hdrp)
 {
-	stliport_t	*portp;
-	unsigned char	hostbits[(STL_MAXCHANS / 8) + 1];
-	unsigned char	slavebits[(STL_MAXCHANS / 8) + 1];
-	unsigned char	*slavep;
-	int		bitpos, bitat, bitsize;
-	int 		channr, nrdevs, slavebitchange;
+	stliport_t *portp;
+	unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
+	unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
+	unsigned char __iomem *slavep;
+	int bitpos, bitat, bitsize;
+	int channr, nrdevs, slavebitchange;
 
 	bitsize = brdp->bitsize;
 	nrdevs = brdp->nrdevs;
@@ -2951,7 +2675,7 @@
  *	8 service bits at a time in the inner loop, so we can bypass
  *	the lot if none of them want service.
  */
-	memcpy(&hostbits[0], (((unsigned char *) hdrp) + brdp->hostoffset),
+	memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset),
 		bitsize);
 
 	memset(&slavebits[0], 0, bitsize);
@@ -2978,11 +2702,11 @@
  *	service may initiate more slave requests.
  */
 	if (slavebitchange) {
-		hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		slavep = ((unsigned char *) hdrp) + brdp->slaveoffset;
+		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+		slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset;
 		for (bitpos = 0; (bitpos < bitsize); bitpos++) {
-			if (slavebits[bitpos])
-				slavep[bitpos] &= ~slavebits[bitpos];
+			if (readb(slavebits + bitpos))
+				writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos);
 		}
 	}
 }
@@ -3000,9 +2724,9 @@
 
 static void stli_poll(unsigned long arg)
 {
-	volatile cdkhdr_t	*hdrp;
-	stlibrd_t		*brdp;
-	int 			brdnr;
+	cdkhdr_t __iomem *hdrp;
+	stlibrd_t *brdp;
+	int brdnr;
 
 	stli_timerlist.expires = STLI_TIMEOUT;
 	add_timer(&stli_timerlist);
@@ -3012,16 +2736,18 @@
  */
 	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
 		brdp = stli_brds[brdnr];
-		if (brdp == (stlibrd_t *) NULL)
+		if (brdp == NULL)
 			continue;
 		if ((brdp->state & BST_STARTED) == 0)
 			continue;
 
+		spin_lock(&brd_lock);
 		EBRDENABLE(brdp);
-		hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		if (hdrp->hostreq)
+		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+		if (readb(&hdrp->hostreq))
 			stli_brdpoll(brdp, hdrp);
 		EBRDDISABLE(brdp);
+		spin_unlock(&brd_lock);
 	}
 }
 
@@ -3034,11 +2760,6 @@
 
 static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp)
 {
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_mkasyport(portp=%x,pp=%x,tiosp=%d)\n",
-		(int) portp, (int) pp, (int) tiosp);
-#endif
-
 	memset(pp, 0, sizeof(asyport_t));
 
 /*
@@ -3157,11 +2878,6 @@
 
 static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
 {
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_mkasysigs(sp=%x,dtr=%d,rts=%d)\n",
-			(int) sp, dtr, rts);
-#endif
-
 	memset(sp, 0, sizeof(asysigs_t));
 	if (dtr >= 0) {
 		sp->signal |= SG_DTR;
@@ -3182,13 +2898,7 @@
 
 static long stli_mktiocm(unsigned long sigvalue)
 {
-	long	tiocm;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_mktiocm(sigvalue=%x)\n", (int) sigvalue);
-#endif
-
-	tiocm = 0;
+	long	tiocm = 0;
 	tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
 	tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
 	tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
@@ -3210,10 +2920,6 @@
 	stliport_t	*portp;
 	int		i, panelnr, panelport;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_initports(brdp=%x)\n", (int) brdp);
-#endif
-
 	for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
 		portp = kzalloc(sizeof(stliport_t), GFP_KERNEL);
 		if (!portp) {
@@ -3240,7 +2946,7 @@
 		brdp->ports[i] = portp;
 	}
 
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -3253,10 +2959,6 @@
 {
 	unsigned long	memconf;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpinit(brdp=%d)\n", (int) brdp);
-#endif
-
 	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
 	udelay(10);
 	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
@@ -3270,9 +2972,6 @@
 
 static void stli_ecpenable(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpenable(brdp=%x)\n", (int) brdp);
-#endif
 	outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
 }
 
@@ -3280,9 +2979,6 @@
 
 static void stli_ecpdisable(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpdisable(brdp=%x)\n", (int) brdp);
-#endif
 	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
 }
 
@@ -3290,13 +2986,8 @@
 
 static char *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void		*ptr;
-	unsigned char	val;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
-		(int) offset);
-#endif
+	void *ptr;
+	unsigned char val;
 
 	if (offset > brdp->memsize) {
 		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
@@ -3316,10 +3007,6 @@
 
 static void stli_ecpreset(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpreset(brdp=%x)\n", (int) brdp);
-#endif
-
 	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
 	udelay(10);
 	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
@@ -3330,9 +3017,6 @@
 
 static void stli_ecpintr(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpintr(brdp=%x)\n", (int) brdp);
-#endif
 	outb(0x1, brdp->iobase);
 }
 
@@ -3346,10 +3030,6 @@
 {
 	unsigned long	memconf;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpeiinit(brdp=%x)\n", (int) brdp);
-#endif
-
 	outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
 	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
 	udelay(10);
@@ -3383,11 +3063,6 @@
 	void		*ptr;
 	unsigned char	val;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecpeigetmemptr(brdp=%x,offset=%x,line=%d)\n",
-		(int) brdp, (int) offset, line);
-#endif
-
 	if (offset > brdp->memsize) {
 		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
 				"range at line=%d(%d), brd=%d\n",
@@ -3437,8 +3112,8 @@
 
 static char *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void		*ptr;
-	unsigned char	val;
+	void *ptr;
+	unsigned char val;
 
 	if (offset > brdp->memsize) {
 		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
@@ -3472,10 +3147,6 @@
 
 static void stli_ecppciinit(stlibrd_t *brdp)
 {
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecppciinit(brdp=%x)\n", (int) brdp);
-#endif
-
 	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
 	udelay(10);
 	outb(0, (brdp->iobase + ECP_PCICONFR));
@@ -3489,11 +3160,6 @@
 	void		*ptr;
 	unsigned char	val;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_ecppcigetmemptr(brdp=%x,offset=%x,line=%d)\n",
-		(int) brdp, (int) offset, line);
-#endif
-
 	if (offset > brdp->memsize) {
 		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
 				"range at line=%d(%d), board=%d\n",
@@ -3528,10 +3194,6 @@
 {
 	unsigned long	memconf;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbinit(brdp=%d)\n", (int) brdp);
-#endif
-
 	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
 	udelay(10);
 	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
@@ -3547,9 +3209,6 @@
 
 static void stli_onbenable(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbenable(brdp=%x)\n", (int) brdp);
-#endif
 	outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
 }
 
@@ -3557,9 +3216,6 @@
 
 static void stli_onbdisable(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbdisable(brdp=%x)\n", (int) brdp);
-#endif
 	outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
 }
 
@@ -3569,11 +3225,6 @@
 {	
 	void	*ptr;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
-		(int) offset);
-#endif
-
 	if (offset > brdp->memsize) {
 		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
 				"range at line=%d(%d), brd=%d\n",
@@ -3589,11 +3240,6 @@
 
 static void stli_onbreset(stlibrd_t *brdp)
 {	
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbreset(brdp=%x)\n", (int) brdp);
-#endif
-
 	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
 	udelay(10);
 	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
@@ -3610,10 +3256,6 @@
 {
 	unsigned long	memconf;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbeinit(brdp=%d)\n", (int) brdp);
-#endif
-
 	outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
 	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
 	udelay(10);
@@ -3632,9 +3274,6 @@
 
 static void stli_onbeenable(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbeenable(brdp=%x)\n", (int) brdp);
-#endif
 	outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
 }
 
@@ -3642,9 +3281,6 @@
 
 static void stli_onbedisable(stlibrd_t *brdp)
 {	
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbedisable(brdp=%x)\n", (int) brdp);
-#endif
 	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
 }
 
@@ -3652,13 +3288,8 @@
 
 static char *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void		*ptr;
-	unsigned char	val;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_onbegetmemptr(brdp=%x,offset=%x,line=%d)\n",
-		(int) brdp, (int) offset, line);
-#endif
+	void *ptr;
+	unsigned char val;
 
 	if (offset > brdp->memsize) {
 		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
@@ -3681,11 +3312,6 @@
 
 static void stli_onbereset(stlibrd_t *brdp)
 {	
-
-#ifdef DEBUG
-	printk(KERN_ERR "stli_onbereset(brdp=%x)\n", (int) brdp);
-#endif
-
 	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
 	udelay(10);
 	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
@@ -3700,11 +3326,6 @@
 
 static void stli_bbyinit(stlibrd_t *brdp)
 {
-
-#ifdef DEBUG
-	printk(KERN_ERR "stli_bbyinit(brdp=%d)\n", (int) brdp);
-#endif
-
 	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
 	udelay(10);
 	outb(0, (brdp->iobase + BBY_ATCONFR));
@@ -3717,24 +3338,13 @@
 
 static char *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void		*ptr;
-	unsigned char	val;
+	void *ptr;
+	unsigned char val;
 
-#ifdef DEBUG
-	printk(KERN_ERR "stli_bbygetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
-		(int) offset);
-#endif
+	BUG_ON(offset > brdp->memsize);
 
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % BBY_PAGESIZE);
-		val = (unsigned char) (offset / BBY_PAGESIZE);
-	}
+	ptr = brdp->membase + (offset % BBY_PAGESIZE);
+	val = (unsigned char) (offset / BBY_PAGESIZE);
 	outb(val, (brdp->iobase + BBY_ATCONFR));
 	return(ptr);
 }
@@ -3743,11 +3353,6 @@
 
 static void stli_bbyreset(stlibrd_t *brdp)
 {	
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_bbyreset(brdp=%x)\n", (int) brdp);
-#endif
-
 	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
 	udelay(10);
 	outb(0, (brdp->iobase + BBY_ATCONFR));
@@ -3762,11 +3367,6 @@
 
 static void stli_stalinit(stlibrd_t *brdp)
 {
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_stalinit(brdp=%d)\n", (int) brdp);
-#endif
-
 	outb(0x1, brdp->iobase);
 	mdelay(1000);
 }
@@ -3775,36 +3375,18 @@
 
 static char *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 {	
-	void	*ptr;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_stalgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
-		(int) offset);
-#endif
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "STALLION: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-	} else {
-		ptr = brdp->membase + (offset % STAL_PAGESIZE);
-	}
-	return(ptr);
+	BUG_ON(offset > brdp->memsize);
+	return brdp->membase + (offset % STAL_PAGESIZE);
 }
 
 /*****************************************************************************/
 
 static void stli_stalreset(stlibrd_t *brdp)
 {	
-	volatile unsigned long	*vecp;
+	u32 __iomem *vecp;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_stalreset(brdp=%x)\n", (int) brdp);
-#endif
-
-	vecp = (volatile unsigned long *) (brdp->membase + 0x30);
-	*vecp = 0xffff0000;
+	vecp = (u32 __iomem *) (brdp->membase + 0x30);
+	writel(0xffff0000, vecp);
 	outb(0, brdp->iobase);
 	mdelay(1000);
 }
@@ -3818,15 +3400,11 @@
 
 static int stli_initecp(stlibrd_t *brdp)
 {
-	cdkecpsig_t	sig;
-	cdkecpsig_t	*sigsp;
-	unsigned int	status, nxtid;
-	char		*name;
-	int		panelnr, nrports;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_initecp(brdp=%x)\n", (int) brdp);
-#endif
+	cdkecpsig_t sig;
+	cdkecpsig_t __iomem *sigsp;
+	unsigned int status, nxtid;
+	char *name;
+	int panelnr, nrports;
 
 	if (!request_region(brdp->iobase, brdp->iosize, "istallion"))
 		return -EIO;
@@ -3834,7 +3412,7 @@
 	if ((brdp->iobase == 0) || (brdp->memaddr == 0))
 	{
 		release_region(brdp->iobase, brdp->iosize);
-		return(-ENODEV);
+		return -ENODEV;
 	}
 
 	brdp->iosize = ECP_IOSIZE;
@@ -3903,7 +3481,7 @@
 
 	default:
 		release_region(brdp->iobase, brdp->iosize);
-		return(-EINVAL);
+		return -EINVAL;
 	}
 
 /*
@@ -3915,10 +3493,10 @@
 	EBRDINIT(brdp);
 
 	brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == (void *) NULL)
+	if (brdp->membase == NULL)
 	{
 		release_region(brdp->iobase, brdp->iosize);
-		return(-ENOMEM);
+		return -ENOMEM;
 	}
 
 /*
@@ -3927,23 +3505,14 @@
  *	this is, and what it is connected to it.
  */
 	EBRDENABLE(brdp);
-	sigsp = (cdkecpsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
+	sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
 	memcpy(&sig, sigsp, sizeof(cdkecpsig_t));
 	EBRDDISABLE(brdp);
 
-#if 0
-	printk("%s(%d): sig-> magic=%x rom=%x panel=%x,%x,%x,%x,%x,%x,%x,%x\n",
-		__FILE__, __LINE__, (int) sig.magic, sig.romver, sig.panelid[0],
-		(int) sig.panelid[1], (int) sig.panelid[2],
-		(int) sig.panelid[3], (int) sig.panelid[4],
-		(int) sig.panelid[5], (int) sig.panelid[6],
-		(int) sig.panelid[7]);
-#endif
-
-	if (sig.magic != ECP_MAGIC)
+	if (sig.magic != cpu_to_le32(ECP_MAGIC))
 	{
 		release_region(brdp->iobase, brdp->iosize);
-		return(-ENODEV);
+		return -ENODEV;
 	}
 
 /*
@@ -3967,7 +3536,7 @@
 
 
 	brdp->state |= BST_FOUND;
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -3979,20 +3548,16 @@
 
 static int stli_initonb(stlibrd_t *brdp)
 {
-	cdkonbsig_t	sig;
-	cdkonbsig_t	*sigsp;
-	char		*name;
-	int		i;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_initonb(brdp=%x)\n", (int) brdp);
-#endif
+	cdkonbsig_t sig;
+	cdkonbsig_t __iomem *sigsp;
+	char *name;
+	int i;
 
 /*
  *	Do a basic sanity check on the IO and memory addresses.
  */
-	if ((brdp->iobase == 0) || (brdp->memaddr == 0))
-		return(-ENODEV);
+	if (brdp->iobase == 0 || brdp->memaddr == 0)
+		return -ENODEV;
 
 	brdp->iosize = ONB_IOSIZE;
 	
@@ -4010,7 +3575,6 @@
 	case BRD_ONBOARD2:
 	case BRD_ONBOARD2_32:
 	case BRD_ONBOARDRS:
-		brdp->membase = (void *) brdp->memaddr;
 		brdp->memsize = ONB_MEMSIZE;
 		brdp->pagesize = ONB_ATPAGESIZE;
 		brdp->init = stli_onbinit;
@@ -4028,7 +3592,6 @@
 		break;
 
 	case BRD_ONBOARDE:
-		brdp->membase = (void *) brdp->memaddr;
 		brdp->memsize = ONB_EIMEMSIZE;
 		brdp->pagesize = ONB_EIPAGESIZE;
 		brdp->init = stli_onbeinit;
@@ -4044,7 +3607,6 @@
 	case BRD_BRUMBY4:
 	case BRD_BRUMBY8:
 	case BRD_BRUMBY16:
-		brdp->membase = (void *) brdp->memaddr;
 		brdp->memsize = BBY_MEMSIZE;
 		brdp->pagesize = BBY_PAGESIZE;
 		brdp->init = stli_bbyinit;
@@ -4058,7 +3620,6 @@
 		break;
 
 	case BRD_STALLION:
-		brdp->membase = (void *) brdp->memaddr;
 		brdp->memsize = STAL_MEMSIZE;
 		brdp->pagesize = STAL_PAGESIZE;
 		brdp->init = stli_stalinit;
@@ -4073,7 +3634,7 @@
 
 	default:
 		release_region(brdp->iobase, brdp->iosize);
-		return(-EINVAL);
+		return -EINVAL;
 	}
 
 /*
@@ -4085,10 +3646,10 @@
 	EBRDINIT(brdp);
 
 	brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == (void *) NULL)
+	if (brdp->membase == NULL)
 	{
 		release_region(brdp->iobase, brdp->iosize);
-		return(-ENOMEM);
+		return -ENOMEM;
 	}
 
 /*
@@ -4097,21 +3658,17 @@
  *	this is, and how many ports.
  */
 	EBRDENABLE(brdp);
-	sigsp = (cdkonbsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
-	memcpy(&sig, sigsp, sizeof(cdkonbsig_t));
+	sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
+	memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t));
 	EBRDDISABLE(brdp);
 
-#if 0
-	printk("%s(%d): sig-> magic=%x:%x:%x:%x romver=%x amask=%x:%x:%x\n",
-		__FILE__, __LINE__, sig.magic0, sig.magic1, sig.magic2,
-		sig.magic3, sig.romver, sig.amask0, sig.amask1, sig.amask2);
-#endif
-
-	if ((sig.magic0 != ONB_MAGIC0) || (sig.magic1 != ONB_MAGIC1) ||
-	    (sig.magic2 != ONB_MAGIC2) || (sig.magic3 != ONB_MAGIC3))
+	if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
+	    sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
+	    sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
+	    sig.magic3 != cpu_to_le16(ONB_MAGIC3))
 	{
 		release_region(brdp->iobase, brdp->iosize);
-		return(-ENODEV);
+		return -ENODEV;
 	}
 
 /*
@@ -4132,7 +3689,7 @@
 
 
 	brdp->state |= BST_FOUND;
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4145,31 +3702,25 @@
 
 static int stli_startbrd(stlibrd_t *brdp)
 {
-	volatile cdkhdr_t	*hdrp;
-	volatile cdkmem_t	*memp;
-	volatile cdkasy_t	*ap;
-	unsigned long		flags;
-	stliport_t		*portp;
-	int			portnr, nrdevs, i, rc;
+	cdkhdr_t __iomem *hdrp;
+	cdkmem_t __iomem *memp;
+	cdkasy_t __iomem *ap;
+	unsigned long flags;
+	stliport_t *portp;
+	int portnr, nrdevs, i, rc = 0;
+	u32 memoff;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_startbrd(brdp=%x)\n", (int) brdp);
-#endif
-
-	rc = 0;
-
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	EBRDENABLE(brdp);
-	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
+	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 	nrdevs = hdrp->nrdevs;
 
 #if 0
 	printk("%s(%d): CDK version %d.%d.%d --> "
 		"nrdevs=%d memp=%x hostp=%x slavep=%x\n",
-		 __FILE__, __LINE__, hdrp->ver_release, hdrp->ver_modification,
-		 hdrp->ver_fix, nrdevs, (int) hdrp->memp, (int) hdrp->hostp,
-		 (int) hdrp->slavep);
+		 __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification),
+		 readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp),
+		 readl(&hdrp->slavep));
 #endif
 
 	if (nrdevs < (brdp->nrports + 1)) {
@@ -4181,14 +3732,14 @@
 	brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
 	brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
 	brdp->bitsize = (nrdevs + 7) / 8;
-	memp = (volatile cdkmem_t *) hdrp->memp;
-	if (((unsigned long) memp) > brdp->memsize) {
+	memoff = readl(&hdrp->memp);
+	if (memoff > brdp->memsize) {
 		printk(KERN_ERR "STALLION: corrupted shared memory region?\n");
 		rc = -EIO;
 		goto stli_donestartup;
 	}
-	memp = (volatile cdkmem_t *) EBRDGETMEMPTR(brdp, (unsigned long) memp);
-	if (memp->dtype != TYP_ASYNCTRL) {
+	memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff);
+	if (readw(&memp->dtype) != TYP_ASYNCTRL) {
 		printk(KERN_ERR "STALLION: no slave control device found\n");
 		goto stli_donestartup;
 	}
@@ -4200,19 +3751,19 @@
  *	change pages while reading memory map.
  */
 	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
-		if (memp->dtype != TYP_ASYNC)
+		if (readw(&memp->dtype) != TYP_ASYNC)
 			break;
 		portp = brdp->ports[portnr];
-		if (portp == (stliport_t *) NULL)
+		if (portp == NULL)
 			break;
 		portp->devnr = i;
-		portp->addr = memp->offset;
+		portp->addr = readl(&memp->offset);
 		portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs));
 		portp->portidx = (unsigned char) (i / 8);
 		portp->portbit = (unsigned char) (0x1 << (i % 8));
 	}
 
-	hdrp->slavereq = 0xff;
+	writeb(0xff, &hdrp->slavereq);
 
 /*
  *	For each port setup a local copy of the RX and TX buffer offsets
@@ -4221,22 +3772,22 @@
  */
 	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
 		portp = brdp->ports[portnr];
-		if (portp == (stliport_t *) NULL)
+		if (portp == NULL)
 			break;
 		if (portp->addr == 0)
 			break;
-		ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
-		if (ap != (volatile cdkasy_t *) NULL) {
-			portp->rxsize = ap->rxq.size;
-			portp->txsize = ap->txq.size;
-			portp->rxoffset = ap->rxq.offset;
-			portp->txoffset = ap->txq.offset;
+		ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
+		if (ap != NULL) {
+			portp->rxsize = readw(&ap->rxq.size);
+			portp->txsize = readw(&ap->txq.size);
+			portp->rxoffset = readl(&ap->rxq.offset);
+			portp->txoffset = readl(&ap->txq.offset);
 		}
 	}
 
 stli_donestartup:
 	EBRDDISABLE(brdp);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
 	if (rc == 0)
 		brdp->state |= BST_STARTED;
@@ -4247,7 +3798,7 @@
 		add_timer(&stli_timerlist);
 	}
 
-	return(rc);
+	return rc;
 }
 
 /*****************************************************************************/
@@ -4258,10 +3809,6 @@
 
 static int __init stli_brdinit(stlibrd_t *brdp)
 {
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_brdinit(brdp=%x)\n", (int) brdp);
-#endif
-
 	stli_brds[brdp->brdnr] = brdp;
 
 	switch (brdp->brdtype) {
@@ -4289,11 +3836,11 @@
 	case BRD_ECHPCI:
 		printk(KERN_ERR "STALLION: %s board type not supported in "
 				"this driver\n", stli_brdnames[brdp->brdtype]);
-		return(ENODEV);
+		return -ENODEV;
 	default:
 		printk(KERN_ERR "STALLION: board=%d is unknown board "
 				"type=%d\n", brdp->brdnr, brdp->brdtype);
-		return(ENODEV);
+		return -ENODEV;
 	}
 
 	if ((brdp->state & BST_FOUND) == 0) {
@@ -4301,7 +3848,7 @@
 				"io=%x mem=%x\n",
 			stli_brdnames[brdp->brdtype], brdp->brdnr,
 			brdp->iobase, (int) brdp->memaddr);
-		return(ENODEV);
+		return -ENODEV;
 	}
 
 	stli_initports(brdp);
@@ -4309,7 +3856,7 @@
 		"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
 		brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
 		brdp->nrpanels, brdp->nrports);
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4321,14 +3868,10 @@
 
 static int stli_eisamemprobe(stlibrd_t *brdp)
 {
-	cdkecpsig_t	ecpsig, *ecpsigp;
-	cdkonbsig_t	onbsig, *onbsigp;
+	cdkecpsig_t	ecpsig, __iomem *ecpsigp;
+	cdkonbsig_t	onbsig, __iomem *onbsigp;
 	int		i, foundit;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_eisamemprobe(brdp=%x)\n", (int) brdp);
-#endif
-
 /*
  *	First up we reset the board, to get it into a known state. There
  *	is only 2 board types here we need to worry about. Don;t use the
@@ -4352,7 +3895,7 @@
 		mdelay(1);
 		stli_onbeenable(brdp);
 	} else {
-		return(-ENODEV);
+		return -ENODEV;
 	}
 
 	foundit = 0;
@@ -4364,25 +3907,24 @@
  */
 	for (i = 0; (i < stli_eisamempsize); i++) {
 		brdp->memaddr = stli_eisamemprobeaddrs[i];
-		brdp->membase = (void *) brdp->memaddr;
 		brdp->membase = ioremap(brdp->memaddr, brdp->memsize);
-		if (brdp->membase == (void *) NULL)
+		if (brdp->membase == NULL)
 			continue;
 
 		if (brdp->brdtype == BRD_ECPE) {
-			ecpsigp = (cdkecpsig_t *) stli_ecpeigetmemptr(brdp,
+			ecpsigp = (cdkecpsig_t __iomem *) stli_ecpeigetmemptr(brdp,
 				CDK_SIGADDR, __LINE__);
-			memcpy(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
-			if (ecpsig.magic == ECP_MAGIC)
+			memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
+			if (ecpsig.magic == cpu_to_le32(ECP_MAGIC))
 				foundit = 1;
 		} else {
-			onbsigp = (cdkonbsig_t *) stli_onbegetmemptr(brdp,
+			onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp,
 				CDK_SIGADDR, __LINE__);
-			memcpy(&onbsig, onbsigp, sizeof(cdkonbsig_t));
-			if ((onbsig.magic0 == ONB_MAGIC0) &&
-			    (onbsig.magic1 == ONB_MAGIC1) &&
-			    (onbsig.magic2 == ONB_MAGIC2) &&
-			    (onbsig.magic3 == ONB_MAGIC3))
+			memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t));
+			if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) &&
+			    (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) &&
+			    (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) &&
+			    (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3)))
 				foundit = 1;
 		}
 
@@ -4406,9 +3948,9 @@
 		printk(KERN_ERR "STALLION: failed to probe shared memory "
 				"region for %s in EISA slot=%d\n",
 			stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
-		return(-ENODEV);
+		return -ENODEV;
 	}
-	return(0);
+	return 0;
 }
 
 static int stli_getbrdnr(void)
@@ -4439,22 +3981,16 @@
 
 static int stli_findeisabrds(void)
 {
-	stlibrd_t	*brdp;
-	unsigned int	iobase, eid;
-	int		i;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_findeisabrds()\n");
-#endif
+	stlibrd_t *brdp;
+	unsigned int iobase, eid;
+	int i;
 
 /*
- *	Firstly check if this is an EISA system. Do this by probing for
- *	the system board EISA ID. If this is not an EISA system then
+ *	Firstly check if this is an EISA system.  If this is not an EISA system then
  *	don't bother going any further!
  */
-	outb(0xff, 0xc80);
-	if (inb(0xc80) == 0xff)
-		return(0);
+	if (EISA_bus)
+		return 0;
 
 /*
  *	Looks like an EISA system, so go searching for EISA boards.
@@ -4472,7 +4008,7 @@
  */
 		for (i = 0; (i < STL_MAXBRDS); i++) {
 			brdp = stli_brds[i];
-			if (brdp == (stlibrd_t *) NULL)
+			if (brdp == NULL)
 				continue;
 			if (brdp->iobase == iobase)
 				break;
@@ -4484,10 +4020,10 @@
  *		We have found a Stallion board and it is not configured already.
  *		Allocate a board structure and initialize it.
  */
-		if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
-			return(-ENOMEM);
+		if ((brdp = stli_allocbrd()) == NULL)
+			return -ENOMEM;
 		if ((brdp->brdnr = stli_getbrdnr()) < 0)
-			return(-ENOMEM);
+			return -ENOMEM;
 		eid = inb(iobase + 0xc82);
 		if (eid == ECP_EISAID)
 			brdp->brdtype = BRD_ECPE;
@@ -4502,7 +4038,7 @@
 		stli_brdinit(brdp);
 	}
 
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4523,32 +4059,18 @@
 
 static int stli_initpcibrd(int brdtype, struct pci_dev *devp)
 {
-	stlibrd_t	*brdp;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_initpcibrd(brdtype=%d,busnr=%x,devnr=%x)\n",
-		brdtype, dev->bus->number, dev->devfn);
-#endif
+	stlibrd_t *brdp;
 
 	if (pci_enable_device(devp))
-		return(-EIO);
-	if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
-		return(-ENOMEM);
+		return -EIO;
+	if ((brdp = stli_allocbrd()) == NULL)
+		return -ENOMEM;
 	if ((brdp->brdnr = stli_getbrdnr()) < 0) {
 		printk(KERN_INFO "STALLION: too many boards found, "
 			"maximum supported %d\n", STL_MAXBRDS);
-		return(0);
+		return 0;
 	}
 	brdp->brdtype = brdtype;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "%s(%d): BAR[]=%lx,%lx,%lx,%lx\n", __FILE__, __LINE__,
-		pci_resource_start(devp, 0),
-		pci_resource_start(devp, 1),
-		pci_resource_start(devp, 2),
-		pci_resource_start(devp, 3));
-#endif
-
 /*
  *	We have all resources from the board, so lets setup the actual
  *	board structure now.
@@ -4557,7 +4079,7 @@
 	brdp->memaddr = pci_resource_start(devp, 2);
 	stli_brdinit(brdp);
 
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4569,20 +4091,12 @@
 
 static int stli_findpcibrds(void)
 {
-	struct pci_dev	*dev = NULL;
-	int		rc;
+	struct pci_dev *dev = NULL;
 
-#ifdef DEBUG
-	printk("stli_findpcibrds()\n");
-#endif
-
-	while ((dev = pci_find_device(PCI_VENDOR_ID_STALLION,
-	    PCI_DEVICE_ID_ECRA, dev))) {
-		if ((rc = stli_initpcibrd(BRD_ECPPCI, dev)))
-			return(rc);
+	while ((dev = pci_get_device(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA, dev))) {
+		stli_initpcibrd(BRD_ECPPCI, dev);
 	}
-
-	return(0);
+	return 0;
 }
 
 #endif
@@ -4595,17 +4109,16 @@
 
 static stlibrd_t *stli_allocbrd(void)
 {
-	stlibrd_t	*brdp;
+	stlibrd_t *brdp;
 
 	brdp = kzalloc(sizeof(stlibrd_t), GFP_KERNEL);
 	if (!brdp) {
 		printk(KERN_ERR "STALLION: failed to allocate memory "
-				"(size=%d)\n", sizeof(stlibrd_t));
+				"(size=%Zd)\n", sizeof(stlibrd_t));
 		return NULL;
 	}
-
 	brdp->magic = STLI_BOARDMAGIC;
-	return(brdp);
+	return brdp;
 }
 
 /*****************************************************************************/
@@ -4617,13 +4130,9 @@
 
 static int stli_initbrds(void)
 {
-	stlibrd_t	*brdp, *nxtbrdp;
-	stlconf_t	*confp;
-	int		i, j;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_initbrds()\n");
-#endif
+	stlibrd_t *brdp, *nxtbrdp;
+	stlconf_t *confp;
+	int i, j;
 
 	if (stli_nrbrds > STL_MAXBRDS) {
 		printk(KERN_INFO "STALLION: too many boards in configuration "
@@ -4638,11 +4147,9 @@
  */
 	for (i = 0; (i < stli_nrbrds); i++) {
 		confp = &stli_brdconf[i];
-#ifdef MODULE
 		stli_parsebrd(confp, stli_brdsp[i]);
-#endif
-		if ((brdp = stli_allocbrd()) == (stlibrd_t *) NULL)
-			return(-ENOMEM);
+		if ((brdp = stli_allocbrd()) == NULL)
+			return -ENOMEM;
 		brdp->brdnr = i;
 		brdp->brdtype = confp->brdtype;
 		brdp->iobase = confp->ioaddr1;
@@ -4654,9 +4161,7 @@
  *	Static configuration table done, so now use dynamic methods to
  *	see if any more boards should be configured.
  */
-#ifdef MODULE
 	stli_argbrds();
-#endif
 	if (STLI_EISAPROBE)
 		stli_findeisabrds();
 #ifdef CONFIG_PCI
@@ -4672,11 +4177,11 @@
 	if (stli_nrbrds > 1) {
 		for (i = 0; (i < stli_nrbrds); i++) {
 			brdp = stli_brds[i];
-			if (brdp == (stlibrd_t *) NULL)
+			if (brdp == NULL)
 				continue;
 			for (j = i + 1; (j < stli_nrbrds); j++) {
 				nxtbrdp = stli_brds[j];
-				if (nxtbrdp == (stlibrd_t *) NULL)
+				if (nxtbrdp == NULL)
 					continue;
 				if ((brdp->membase >= nxtbrdp->membase) &&
 				    (brdp->membase <= (nxtbrdp->membase +
@@ -4691,7 +4196,7 @@
 	if (stli_shared == 0) {
 		for (i = 0; (i < stli_nrbrds); i++) {
 			brdp = stli_brds[i];
-			if (brdp == (stlibrd_t *) NULL)
+			if (brdp == NULL)
 				continue;
 			if (brdp->state & BST_FOUND) {
 				EBRDENABLE(brdp);
@@ -4701,7 +4206,7 @@
 		}
 	}
 
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4714,48 +4219,55 @@
 
 static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp)
 {
-	unsigned long	flags;
-	void		*memptr;
-	stlibrd_t	*brdp;
-	int		brdnr, size, n;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_memread(fp=%x,buf=%x,count=%x,offp=%x)\n",
-			(int) fp, (int) buf, count, (int) offp);
-#endif
+	unsigned long flags;
+	void *memptr;
+	stlibrd_t *brdp;
+	int brdnr, size, n;
+	void *p;
+	loff_t off = *offp;
 
 	brdnr = iminor(fp->f_dentry->d_inode);
 	if (brdnr >= stli_nrbrds)
-		return(-ENODEV);
+		return -ENODEV;
 	brdp = stli_brds[brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(-ENODEV);
+	if (brdp == NULL)
+		return -ENODEV;
 	if (brdp->state == 0)
-		return(-ENODEV);
-	if (fp->f_pos >= brdp->memsize)
-		return(0);
+		return -ENODEV;
+	if (off >= brdp->memsize || off + count < off)
+		return 0;
 
-	size = MIN(count, (brdp->memsize - fp->f_pos));
+	size = MIN(count, (brdp->memsize - off));
 
-	save_flags(flags);
-	cli();
-	EBRDENABLE(brdp);
+	/*
+	 *	Copy the data a page at a time
+	 */
+
+	p = (void *)__get_free_page(GFP_KERNEL);
+	if(p == NULL)
+		return -ENOMEM;
+
 	while (size > 0) {
-		memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos);
-		n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize)));
-		if (copy_to_user(buf, memptr, n)) {
+		spin_lock_irqsave(&brd_lock, flags);
+		EBRDENABLE(brdp);
+		memptr = (void *) EBRDGETMEMPTR(brdp, off);
+		n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+		n = MIN(n, PAGE_SIZE);
+		memcpy_fromio(p, memptr, n);
+		EBRDDISABLE(brdp);
+		spin_unlock_irqrestore(&brd_lock, flags);
+		if (copy_to_user(buf, p, n)) {
 			count = -EFAULT;
 			goto out;
 		}
-		fp->f_pos += n;
+		off += n;
 		buf += n;
 		size -= n;
 	}
 out:
-	EBRDDISABLE(brdp);
-	restore_flags(flags);
-
-	return(count);
+	*offp = off;
+	free_page((unsigned long)p);
+	return count;
 }
 
 /*****************************************************************************/
@@ -4764,54 +4276,65 @@
  *	Code to handle an "staliomem" write operation. This device is the 
  *	contents of the board shared memory. It is used for down loading
  *	the slave image (and debugging :-)
+ *
+ *	FIXME: copy under lock
  */
 
 static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp)
 {
-	unsigned long	flags;
-	void		*memptr;
-	stlibrd_t	*brdp;
-	char		__user *chbuf;
-	int		brdnr, size, n;
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_memwrite(fp=%x,buf=%x,count=%x,offp=%x)\n",
-			(int) fp, (int) buf, count, (int) offp);
-#endif
+	unsigned long flags;
+	void *memptr;
+	stlibrd_t *brdp;
+	char __user *chbuf;
+	int brdnr, size, n;
+	void *p;
+	loff_t off = *offp;
 
 	brdnr = iminor(fp->f_dentry->d_inode);
+
 	if (brdnr >= stli_nrbrds)
-		return(-ENODEV);
+		return -ENODEV;
 	brdp = stli_brds[brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(-ENODEV);
+	if (brdp == NULL)
+		return -ENODEV;
 	if (brdp->state == 0)
-		return(-ENODEV);
-	if (fp->f_pos >= brdp->memsize)
-		return(0);
+		return -ENODEV;
+	if (off >= brdp->memsize || off + count < off)
+		return 0;
 
 	chbuf = (char __user *) buf;
-	size = MIN(count, (brdp->memsize - fp->f_pos));
+	size = MIN(count, (brdp->memsize - off));
 
-	save_flags(flags);
-	cli();
-	EBRDENABLE(brdp);
+	/*
+	 *	Copy the data a page at a time
+	 */
+
+	p = (void *)__get_free_page(GFP_KERNEL);
+	if(p == NULL)
+		return -ENOMEM;
+
 	while (size > 0) {
-		memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos);
-		n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize)));
-		if (copy_from_user(memptr, chbuf, n)) {
-			count = -EFAULT;
+		n = MIN(size, (brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
+		n = MIN(n, PAGE_SIZE);
+		if (copy_from_user(p, chbuf, n)) {
+			if (count == 0)
+				count = -EFAULT;
 			goto out;
 		}
-		fp->f_pos += n;
+		spin_lock_irqsave(&brd_lock, flags);
+		EBRDENABLE(brdp);
+		memptr = (void *) EBRDGETMEMPTR(brdp, off);
+		memcpy_toio(memptr, p, n);
+		EBRDDISABLE(brdp);
+		spin_unlock_irqrestore(&brd_lock, flags);
+		off += n;
 		chbuf += n;
 		size -= n;
 	}
 out:
-	EBRDDISABLE(brdp);
-	restore_flags(flags);
-
-	return(count);
+	free_page((unsigned long) p);
+	*offp = off;
+	return count;
 }
 
 /*****************************************************************************/
@@ -4822,16 +4345,16 @@
 
 static int stli_getbrdstats(combrd_t __user *bp)
 {
-	stlibrd_t	*brdp;
-	int		i;
+	stlibrd_t *brdp;
+	int i;
 
 	if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
 		return -EFAULT;
 	if (stli_brdstats.brd >= STL_MAXBRDS)
-		return(-ENODEV);
+		return -ENODEV;
 	brdp = stli_brds[stli_brdstats.brd];
-	if (brdp == (stlibrd_t *) NULL)
-		return(-ENODEV);
+	if (brdp == NULL)
+		return -ENODEV;
 
 	memset(&stli_brdstats, 0, sizeof(combrd_t));
 	stli_brdstats.brd = brdp->brdnr;
@@ -4850,7 +4373,7 @@
 
 	if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t)))
 		return -EFAULT;
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4861,19 +4384,19 @@
 
 static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
 {
-	stlibrd_t	*brdp;
-	int		i;
+	stlibrd_t *brdp;
+	int i;
 
-	if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
-		return((stliport_t *) NULL);
+	if (brdnr < 0 || brdnr >= STL_MAXBRDS)
+		return NULL;
 	brdp = stli_brds[brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return((stliport_t *) NULL);
+	if (brdp == NULL)
+		return NULL;
 	for (i = 0; (i < panelnr); i++)
 		portnr += brdp->panels[i];
 	if ((portnr < 0) || (portnr >= brdp->nrports))
-		return((stliport_t *) NULL);
-	return(brdp->ports[portnr]);
+		return NULL;
+	return brdp->ports[portnr];
 }
 
 /*****************************************************************************/
@@ -4892,16 +4415,16 @@
 
 	memset(&stli_comstats, 0, sizeof(comstats_t));
 
-	if (portp == (stliport_t *) NULL)
-		return(-ENODEV);
+	if (portp == NULL)
+		return -ENODEV;
 	brdp = stli_brds[portp->brdnr];
-	if (brdp == (stlibrd_t *) NULL)
-		return(-ENODEV);
+	if (brdp == NULL)
+		return -ENODEV;
 
 	if (brdp->state & BST_STARTED) {
 		if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
 		    &stli_cdkstats, sizeof(asystats_t), 1)) < 0)
-			return(rc);
+			return rc;
 	} else {
 		memset(&stli_cdkstats, 0, sizeof(asystats_t));
 	}
@@ -4912,13 +4435,12 @@
 	stli_comstats.state = portp->state;
 	stli_comstats.flags = portp->flags;
 
-	save_flags(flags);
-	cli();
-	if (portp->tty != (struct tty_struct *) NULL) {
+	spin_lock_irqsave(&brd_lock, flags);
+	if (portp->tty != NULL) {
 		if (portp->tty->driver_data == portp) {
 			stli_comstats.ttystate = portp->tty->flags;
-			stli_comstats.rxbuffered = -1 /*portp->tty->flip.count*/;
-			if (portp->tty->termios != (struct termios *) NULL) {
+			stli_comstats.rxbuffered = -1;
+			if (portp->tty->termios != NULL) {
 				stli_comstats.cflags = portp->tty->termios->c_cflag;
 				stli_comstats.iflags = portp->tty->termios->c_iflag;
 				stli_comstats.oflags = portp->tty->termios->c_oflag;
@@ -4926,7 +4448,7 @@
 			}
 		}
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
 	stli_comstats.txtotal = stli_cdkstats.txchars;
 	stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
@@ -4948,7 +4470,7 @@
 	stli_comstats.hwid = stli_cdkstats.hwid;
 	stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
 
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
@@ -4961,8 +4483,8 @@
 
 static int stli_getportstats(stliport_t *portp, comstats_t __user *cp)
 {
-	stlibrd_t	*brdp;
-	int		rc;
+	stlibrd_t *brdp;
+	int rc;
 
 	if (!portp) {
 		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
@@ -4992,8 +4514,8 @@
 
 static int stli_clrportstats(stliport_t *portp, comstats_t __user *cp)
 {
-	stlibrd_t	*brdp;
-	int		rc;
+	stlibrd_t *brdp;
+	int rc;
 
 	if (!portp) {
 		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
@@ -5031,7 +4553,7 @@
 
 static int stli_getportstruct(stliport_t __user *arg)
 {
-	stliport_t	*portp;
+	stliport_t *portp;
 
 	if (copy_from_user(&stli_dummyport, arg, sizeof(stliport_t)))
 		return -EFAULT;
@@ -5052,7 +4574,7 @@
 
 static int stli_getbrdstruct(stlibrd_t __user *arg)
 {
-	stlibrd_t	*brdp;
+	stlibrd_t *brdp;
 
 	if (copy_from_user(&stli_dummybrd, arg, sizeof(stlibrd_t)))
 		return -EFAULT;
@@ -5076,15 +4598,10 @@
 
 static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
 {
-	stlibrd_t	*brdp;
-	int		brdnr, rc, done;
+	stlibrd_t *brdp;
+	int brdnr, rc, done;
 	void __user *argp = (void __user *)arg;
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "stli_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n",
-			(int) ip, (int) fp, cmd, (int) arg);
-#endif
-
 /*
  *	First up handle the board independent ioctls.
  */
@@ -5115,7 +4632,7 @@
 	}
 
 	if (done)
-		return(rc);
+		return rc;
 
 /*
  *	Now handle the board specific ioctls. These all depend on the
@@ -5123,12 +4640,12 @@
  */
 	brdnr = iminor(ip);
 	if (brdnr >= STL_MAXBRDS)
-		return(-ENODEV);
+		return -ENODEV;
 	brdp = stli_brds[brdnr];
 	if (!brdp)
-		return(-ENODEV);
+		return -ENODEV;
 	if (brdp->state == 0)
-		return(-ENODEV);
+		return -ENODEV;
 
 	switch (cmd) {
 	case STL_BINTR:
@@ -5152,8 +4669,7 @@
 		rc = -ENOIOCTLCMD;
 		break;
 	}
-
-	return(rc);
+	return rc;
 }
 
 static struct tty_operations stli_ops = {
@@ -5187,6 +4703,9 @@
 	int i;
 	printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
 
+	spin_lock_init(&stli_lock);
+	spin_lock_init(&brd_lock);
+
 	stli_initbrds();
 
 	stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
@@ -5196,10 +4715,6 @@
 /*
  *	Allocate a temporary write buffer.
  */
-	stli_tmpwritebuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
-	if (!stli_tmpwritebuf)
-		printk(KERN_ERR "STALLION: failed to allocate memory "
-				"(size=%d)\n", STLI_TXBUFSIZE);
 	stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
 	if (!stli_txcookbuf)
 		printk(KERN_ERR "STALLION: failed to allocate memory "
@@ -5243,7 +4758,7 @@
 		printk(KERN_ERR "STALLION: failed to register serial driver\n");
 		return -EBUSY;
 	}
-	return(0);
+	return 0;
 }
 
 /*****************************************************************************/
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 5755b7e..4bb3d22 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -39,6 +39,7 @@
 #include <linux/vt_kern.h>
 #include <linux/sysrq.h>
 #include <linux/input.h>
+#include <linux/reboot.h>
 
 static void kbd_disconnect(struct input_handle *handle);
 extern void ctrl_alt_del(void);
@@ -150,6 +151,7 @@
         "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
         "\r\000/";                                      /* 0x60 - 0x6f */
 static int sysrq_down;
+static int sysrq_alt_use;
 #endif
 static int sysrq_alt;
 
@@ -672,7 +674,7 @@
  */
 static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
 {
-	static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
+	static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
 	value = ret_diacr[value];
 	k_deadunicode(vc, value, up_flag, regs);
 }
@@ -709,8 +711,8 @@
 
 static void k_pad(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
 {
-	static const char *pad_chars = "0123456789+-*/\015,.?()#";
-	static const char *app_map = "pqrstuvwxylSRQMnnmPQS";
+	static const char pad_chars[] = "0123456789+-*/\015,.?()#";
+	static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
 
 	if (up_flag)
 		return;		/* no action, if this is a key release */
@@ -1035,7 +1037,7 @@
 #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
 			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
 
-static unsigned short x86_keycodes[256] =
+static const unsigned short x86_keycodes[256] =
 	{ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 	 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
 	 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -1073,11 +1075,13 @@
 			put_queue(vc, 0x1d | up_flag);
 			put_queue(vc, 0x45 | up_flag);
 			return 0;
-		case KEY_HANGUEL:
-			if (!up_flag) put_queue(vc, 0xf1);
+		case KEY_HANGEUL:
+			if (!up_flag)
+				put_queue(vc, 0xf2);
 			return 0;
 		case KEY_HANJA:
-			if (!up_flag) put_queue(vc, 0xf2);
+			if (!up_flag)
+				put_queue(vc, 0xf1);
 			return 0;
 	}
 
@@ -1142,7 +1146,7 @@
 	kbd = kbd_table + fg_console;
 
 	if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
-		sysrq_alt = down;
+		sysrq_alt = down ? keycode : 0;
 #ifdef CONFIG_SPARC
 	if (keycode == KEY_STOP)
 		sparc_l1_a_state = down;
@@ -1162,9 +1166,14 @@
 
 #ifdef CONFIG_MAGIC_SYSRQ	       /* Handle the SysRq Hack */
 	if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
-		sysrq_down = down;
+		if (!sysrq_down) {
+			sysrq_down = down;
+			sysrq_alt_use = sysrq_alt;
+		}
 		return;
 	}
+	if (sysrq_down && !down && keycode == sysrq_alt_use)
+		sysrq_down = 0;
 	if (sysrq_down && down && !rep) {
 		handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
 		return;
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 1b05fa6..d65b310 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -329,7 +329,6 @@
 	if (PAGE_SIZE > (1 << 16))
 		return -ENOSYS;
 
-	vma->vm_flags |= (VM_IO | VM_SHM | VM_LOCKED );
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 	mmtimer_addr = __pa(RTC_COUNTER_ADDR);
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index f43c2e0..01247cc 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -301,7 +301,7 @@
 	.tiocmset = moxa_tiocmset,
 };
 
-static spinlock_t moxa_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(moxa_lock);
 
 #ifdef CONFIG_PCI
 static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 0fb2fb9..72cfd09 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -9,7 +9,7 @@
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
  *      the Free Software Foundation; either version 2 of the License, or
-*      (at your option) any later version.
+ *      (at your option) any later version.
  *
  *      This program is distributed in the hope that it will be useful,
  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -71,8 +71,8 @@
 #define	MXSERMAJOR	 174
 #define	MXSERCUMAJOR	 175
 
-#define	MXSER_EVENT_TXLOW	 1
-#define	MXSER_EVENT_HANGUP	 2
+#define	MXSER_EVENT_TXLOW	1
+#define	MXSER_EVENT_HANGUP	2
 
 #define MXSER_BOARDS		4	/* Max. boards */
 #define MXSER_PORTS		32	/* Max. ports */
@@ -92,7 +92,8 @@
 #define UART_MCR_AFE		0x20
 #define UART_LSR_SPECIAL	0x1E
 
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|IXON|IXOFF))
+#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
+					  IXON|IXOFF))
 
 #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
 
@@ -152,27 +153,27 @@
 };
 
 static int mxser_numports[] = {
-	8,			// C168-ISA
-	4,			// C104-ISA
-	4,			// CI104J
-	8,			// C168-PCI
-	4,			// C104-PCI
-	2,			// C102-ISA
-	2,			// CI132
-	4,			// CI134
-	2,			// CP132
-	4,			// CP114
-	4,			// CT114
-	2,			// CP102
-	4,			// CP104U
-	8,			// CP168U
-	2,			// CP132U
-	4,			// CP134U
-	4,			// CP104JU
-	8,			// RC7000
-	8,			// CP118U 
-	2,			// CP102UL 
-	2,			// CP102U
+	8,			/* C168-ISA */
+	4,			/* C104-ISA */
+	4,			/* CI104J */
+	8,			/* C168-PCI */
+	4,			/* C104-PCI */
+	2,			/* C102-ISA */
+	2,			/* CI132 */
+	4,			/* CI134 */
+	2,			/* CP132 */
+	4,			/* CP114 */
+	4,			/* CT114 */
+	2,			/* CP102 */
+	4,			/* CP104U */
+	8,			/* CP168U */
+	2,			/* CP132U */
+	4,			/* CP134U */
+	4,			/* CP104JU */
+	8,			/* RC7000 */
+	8,			/* CP118U */
+	2,			/* CP102UL */
+	2,			/* CP102U */
 };
 
 #define UART_TYPE_NUM	2
@@ -182,7 +183,7 @@
 	MOXA_MUST_MU860_HWID
 };
 
-// This is only for PCI
+/* This is only for PCI */
 #define UART_INFO_NUM	3
 struct mxpciuart_info {
 	int type;
@@ -231,7 +232,7 @@
 typedef struct _moxa_pci_info {
 	unsigned short busNum;
 	unsigned short devNum;
-	struct pci_dev *pdev;	// add by Victor Yu. 06-23-2003
+	struct pci_dev *pdev;	/* add by Victor Yu. 06-23-2003 */
 } moxa_pci_info;
 
 static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
@@ -280,6 +281,7 @@
 	int fifo[32];
 	int iftype[32];
 };
+
 struct mxser_hwconf {
 	int board_type;
 	int ports;
@@ -290,9 +292,9 @@
 	int ioaddr[MXSER_PORTS_PER_BOARD];
 	int baud_base[MXSER_PORTS_PER_BOARD];
 	moxa_pci_info pciInfo;
-	int IsMoxaMustChipFlag;	// add by Victor Yu. 08-30-2002
-	int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD];	// add by Victor Yu. 09-04-2002
-	int opmode_ioaddr[MXSER_PORTS_PER_BOARD];	// add by Victor Yu. 01-05-2004
+	int IsMoxaMustChipFlag;	/* add by Victor Yu. 08-30-2002 */
+	int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD];	/* add by Victor Yu. 09-04-2002 */
+	int opmode_ioaddr[MXSER_PORTS_PER_BOARD];	/* add by Victor Yu. 01-05-2004 */
 };
 
 struct mxser_struct {
@@ -334,9 +336,9 @@
 	wait_queue_head_t delta_msr_wait;
 	struct async_icount icount;	/* kernel counters for the 4 input interrupts */
 	int timeout;
-	int IsMoxaMustChipFlag;	// add by Victor Yu. 08-30-2002
-	int MaxCanSetBaudRate;	// add by Victor Yu. 09-04-2002
-	int opmode_ioaddr;	// add by Victor Yu. 01-05-2004
+	int IsMoxaMustChipFlag;	/* add by Victor Yu. 08-30-2002 */
+	int MaxCanSetBaudRate;	/* add by Victor Yu. 09-04-2002 */
+	int opmode_ioaddr;	/* add by Victor Yu. 01-05-2004 */
 	unsigned char stop_rx;
 	unsigned char ldisc_stop_rx;
 	long realbaud;
@@ -345,7 +347,6 @@
 	spinlock_t slock;
 };
 
-
 struct mxser_mstatus {
 	tcflag_t cflag;
 	int cts;
@@ -358,7 +359,7 @@
 
 static int mxserBoardCAP[MXSER_BOARDS] = {
 	0, 0, 0, 0
-	    /*  0x180, 0x280, 0x200, 0x320   */
+	/*  0x180, 0x280, 0x200, 0x320 */
 };
 
 static struct tty_driver *mxvar_sdriver;
@@ -386,7 +387,7 @@
 static void mxser_getcfg(int board, struct mxser_hwconf *hwconf);
 static int mxser_init(void);
 
-//static void   mxser_poll(unsigned long);
+/* static void   mxser_poll(unsigned long); */
 static int mxser_get_ISA_conf(int, struct mxser_hwconf *);
 static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *);
 static void mxser_do_softint(void *);
@@ -440,18 +441,18 @@
 	SET_MOXA_MUST_XON1_VALUE(io, 0x11);
 	if ((hwid = inb(io + UART_MCR)) != 0) {
 		outb(oldmcr, io + UART_MCR);
-		return (MOXA_OTHER_UART);
+		return MOXA_OTHER_UART;
 	}
 
 	GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
 	for (i = 0; i < UART_TYPE_NUM; i++) {
 		if (hwid == Gmoxa_uart_id[i])
-			return (int) hwid;
+			return (int)hwid;
 	}
 	return MOXA_OTHER_UART;
 }
 
-// above is modified by Victor Yu. 08-15-2002
+/* above is modified by Victor Yu. 08-15-2002 */
 
 static struct tty_operations mxser_ops = {
 	.open = mxser_open,
@@ -504,7 +505,6 @@
 	else
 		printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n");
 
-
 	for (i = 0; i < MXSER_BOARDS; i++) {
 		struct pci_dev *pdev;
 
@@ -513,7 +513,7 @@
 		else {
 			pdev = mxsercfg[i].pciInfo.pdev;
 			free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
-			if (pdev != NULL) {	//PCI
+			if (pdev != NULL) {	/* PCI */
 				release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));
 				release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
 			} else {
@@ -524,7 +524,6 @@
 	}
 	if (verbose)
 		printk(KERN_DEBUG "Done.\n");
-
 }
 
 static void process_txrx_fifo(struct mxser_struct *info)
@@ -558,8 +557,10 @@
 	n = board * MXSER_PORTS_PER_BOARD;
 	info = &mxvar_table[n];
 	/*if (verbose) */  {
-		printk(KERN_DEBUG "        ttyM%d - ttyM%d ", n, n + hwconf->ports - 1);
-		printk(" max. baud rate = %d bps.\n", hwconf->MaxCanSetBaudRate[0]);
+		printk(KERN_DEBUG "        ttyM%d - ttyM%d ",
+			n, n + hwconf->ports - 1);
+		printk(" max. baud rate = %d bps.\n",
+			hwconf->MaxCanSetBaudRate[0]);
 	}
 
 	for (i = 0; i < hwconf->ports; i++, n++, info++) {
@@ -568,12 +569,12 @@
 		info->irq = hwconf->irq;
 		info->vector = hwconf->vector;
 		info->vectormask = hwconf->vector_mask;
-		info->opmode_ioaddr = hwconf->opmode_ioaddr[i];	// add by Victor Yu. 01-05-2004
+		info->opmode_ioaddr = hwconf->opmode_ioaddr[i];	/* add by Victor Yu. 01-05-2004 */
 		info->stop_rx = 0;
 		info->ldisc_stop_rx = 0;
 
 		info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag;
-		//Enhance mode enabled here
+		/* Enhance mode enabled here */
 		if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
 			ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);
 		}
@@ -606,22 +607,25 @@
 
 	/* before set INT ISR, disable all int */
 	for (i = 0; i < hwconf->ports; i++) {
-		outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0, hwconf->ioaddr[i] + UART_IER);
+		outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0,
+			hwconf->ioaddr[i] + UART_IER);
 	}
 
 	n = board * MXSER_PORTS_PER_BOARD;
 	info = &mxvar_table[n];
 
-	retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info), "mxser", info);
+	retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),
+				"mxser", info);
 	if (retval) {
-		printk(KERN_ERR "Board %d: %s", board, mxser_brdname[hwconf->board_type - 1]);
-		printk("  Request irq fail,IRQ (%d) may be conflit with another device.\n", info->irq);
+		printk(KERN_ERR "Board %d: %s",
+			board, mxser_brdname[hwconf->board_type - 1]);
+		printk("  Request irq failed, IRQ (%d) may conflict with"
+			" another device.\n", info->irq);
 		return retval;
 	}
 	return 0;
 }
 
-
 static void mxser_getcfg(int board, struct mxser_hwconf *hwconf)
 {
 	mxsercfg[board] = *hwconf;
@@ -631,26 +635,27 @@
 static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxser_hwconf *hwconf)
 {
 	int i, j;
-//      unsigned int    val;
+	/* unsigned int val; */
 	unsigned int ioaddress;
 	struct pci_dev *pdev = hwconf->pciInfo.pdev;
 
-	//io address
+	/* io address */
 	hwconf->board_type = board_type;
 	hwconf->ports = mxser_numports[board_type - 1];
 	ioaddress = pci_resource_start(pdev, 2);
-	request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2), "mxser(IO)");
+	request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2),
+			"mxser(IO)");
 
-	for (i = 0; i < hwconf->ports; i++) {
+	for (i = 0; i < hwconf->ports; i++)
 		hwconf->ioaddr[i] = ioaddress + 8 * i;
-	}
 
-	//vector
+	/* vector */
 	ioaddress = pci_resource_start(pdev, 3);
-	request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3), "mxser(vector)");
+	request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3),
+			"mxser(vector)");
 	hwconf->vector = ioaddress;
 
-	//irq
+	/* irq */
 	hwconf->irq = hwconf->pciInfo.pdev->irq;
 
 	hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]);
@@ -663,7 +668,7 @@
 			if (Gpci_uart_info[j].type == hwconf->IsMoxaMustChipFlag) {
 				hwconf->MaxCanSetBaudRate[i] = Gpci_uart_info[j].max_baud;
 
-				//exception....CP-102
+				/* exception....CP-102 */
 				if (board_type == MXSER_BOARD_CP102)
 					hwconf->MaxCanSetBaudRate[i] = 921600;
 				break;
@@ -678,15 +683,15 @@
 			else
 				hwconf->opmode_ioaddr[i] = ioaddress + 0x0c;
 		}
-		outb(0, ioaddress + 4);	// default set to RS232 mode
-		outb(0, ioaddress + 0x0c);	//default set to RS232 mode
+		outb(0, ioaddress + 4);	/* default set to RS232 mode */
+		outb(0, ioaddress + 0x0c);	/* default set to RS232 mode */
 	}
 
 	for (i = 0; i < hwconf->ports; i++) {
 		hwconf->vector_mask |= (1 << i);
 		hwconf->baud_base[i] = 921600;
 	}
-	return (0);
+	return 0;
 }
 #endif
 
@@ -707,7 +712,8 @@
 		mxsercfg[i].board_type = -1;
 	}
 
-	printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", MXSER_VERSION);
+	printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
+		MXSER_VERSION);
 
 	/* Initialize the tty_driver structure */
 	memset(mxvar_sdriver, 0, sizeof(struct tty_driver));
@@ -719,7 +725,7 @@
 	mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
 	mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
 	mxvar_sdriver->init_termios = tty_std_termios;
-	mxvar_sdriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
 	mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW;
 	tty_set_operations(mxvar_sdriver, &mxser_ops);
 	mxvar_sdriver->ttys = mxvar_tty;
@@ -739,23 +745,29 @@
 	/* Start finding ISA boards here */
 	for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
 		int cap;
+
 		if (!(cap = mxserBoardCAP[b]))
 			continue;
 
 		retval = mxser_get_ISA_conf(cap, &hwconf);
 
 		if (retval != 0)
-			printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
+			printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n",
+				mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
 
 		if (retval <= 0) {
 			if (retval == MXSER_ERR_IRQ)
-				printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+				printk(KERN_ERR "Invalid interrupt number, "
+					"board not configured\n");
 			else if (retval == MXSER_ERR_IRQ_CONFLIT)
-				printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+				printk(KERN_ERR "Invalid interrupt number, "
+					"board not configured\n");
 			else if (retval == MXSER_ERR_VECTOR)
-				printk(KERN_ERR "Invalid interrupt vector,board not configured\n");
+				printk(KERN_ERR "Invalid interrupt vector, "
+					"board not configured\n");
 			else if (retval == MXSER_ERR_IOADDR)
-				printk(KERN_ERR "Invalid I/O address,board not configured\n");
+				printk(KERN_ERR "Invalid I/O address, "
+					"board not configured\n");
 
 			continue;
 		}
@@ -765,35 +777,43 @@
 		hwconf.pciInfo.pdev = NULL;
 
 		mxser_getcfg(m, &hwconf);
-		//init mxsercfg first, or mxsercfg data is not correct on ISR.
-		//mxser_initbrd will hook ISR.
+		/*
+		 * init mxsercfg first,
+		 * or mxsercfg data is not correct on ISR.
+		 */
+		/* mxser_initbrd will hook ISR. */
 		if (mxser_initbrd(m, &hwconf) < 0)
 			continue;
 
-
 		m++;
 	}
 
 	/* Start finding ISA boards from module arg */
 	for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
 		int cap;
+
 		if (!(cap = ioaddr[b]))
 			continue;
 
 		retval = mxser_get_ISA_conf(cap, &hwconf);
 
 		if (retval != 0)
-			printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
+			printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n",
+				mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
 
 		if (retval <= 0) {
 			if (retval == MXSER_ERR_IRQ)
-				printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+				printk(KERN_ERR "Invalid interrupt number, "
+					"board not configured\n");
 			else if (retval == MXSER_ERR_IRQ_CONFLIT)
-				printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+				printk(KERN_ERR "Invalid interrupt number, "
+					"board not configured\n");
 			else if (retval == MXSER_ERR_VECTOR)
-				printk(KERN_ERR "Invalid interrupt vector,board not configured\n");
+				printk(KERN_ERR "Invalid interrupt vector, "
+					"board not configured\n");
 			else if (retval == MXSER_ERR_IOADDR)
-				printk(KERN_ERR "Invalid I/O address,board not configured\n");
+				printk(KERN_ERR "Invalid I/O address, "
+					"board not configured\n");
 
 			continue;
 		}
@@ -803,8 +823,11 @@
 		hwconf.pciInfo.pdev = NULL;
 
 		mxser_getcfg(m, &hwconf);
-		//init mxsercfg first, or mxsercfg data is not correct on ISR.
-		//mxser_initbrd will hook ISR.
+		/*
+		 * init mxsercfg first,
+		 * or mxsercfg data is not correct on ISR.
+		 */
+		/* mxser_initbrd will hook ISR. */
 		if (mxser_initbrd(m, &hwconf) < 0)
 			continue;
 
@@ -817,7 +840,8 @@
 	index = 0;
 	b = 0;
 	while (b < n) {
-		pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev);
+		pdev = pci_find_device(mxser_pcibrds[b].vendor,
+				mxser_pcibrds[b].device, pdev);
 			if (pdev == NULL) {
 			b++;
 			continue;
@@ -825,30 +849,48 @@
 		hwconf.pciInfo.busNum = busnum = pdev->bus->number;
 		hwconf.pciInfo.devNum = devnum = PCI_SLOT(pdev->devfn) << 3;
 		hwconf.pciInfo.pdev = pdev;
-		printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n", mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1], busnum, devnum >> 3);
+		printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
+			mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1],
+			busnum, devnum >> 3);
 		index++;
-		if (m >= MXSER_BOARDS) {
-			printk(KERN_ERR "Too many Smartio/Industio family boards find (maximum %d),board not configured\n", MXSER_BOARDS);
-		} else {
+		if (m >= MXSER_BOARDS)
+			printk(KERN_ERR
+				"Too many Smartio/Industio family boards find "
+				"(maximum %d), board not configured\n",
+				MXSER_BOARDS);
+		else {
 			if (pci_enable_device(pdev)) {
-				printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n");
+				printk(KERN_ERR "Moxa SmartI/O PCI enable "
+					"fail !\n");
 				continue;
 			}
-			retval = mxser_get_PCI_conf(busnum, devnum, (int) mxser_pcibrds[b].driver_data, &hwconf);
+			retval = mxser_get_PCI_conf(busnum, devnum,
+					(int)mxser_pcibrds[b].driver_data,
+					&hwconf);
 			if (retval < 0) {
 				if (retval == MXSER_ERR_IRQ)
-					printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+					printk(KERN_ERR
+						"Invalid interrupt number, "
+						"board not configured\n");
 				else if (retval == MXSER_ERR_IRQ_CONFLIT)
-					printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+					printk(KERN_ERR
+						"Invalid interrupt number, "
+						"board not configured\n");
 				else if (retval == MXSER_ERR_VECTOR)
-					printk(KERN_ERR "Invalid interrupt vector,board not configured\n");
+					printk(KERN_ERR
+						"Invalid interrupt vector, "
+						"board not configured\n");
 				else if (retval == MXSER_ERR_IOADDR)
-					printk(KERN_ERR "Invalid I/O address,board not configured\n");
+					printk(KERN_ERR
+						"Invalid I/O address, "
+						"board not configured\n");
 				continue;
 			}
 			mxser_getcfg(m, &hwconf);
-			//init mxsercfg first, or mxsercfg data is not correct on ISR.
-			//mxser_initbrd will hook ISR.
+			/* init mxsercfg first,
+			 * or mxsercfg data is not correct on ISR.
+			 */
+			/* mxser_initbrd will hook ISR. */
 			if (mxser_initbrd(m, &hwconf) < 0)
 				continue;
 			m++;
@@ -858,7 +900,8 @@
 
 	retval = tty_register_driver(mxvar_sdriver);
 	if (retval) {
-		printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family driver !\n");
+		printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family"
+				" driver !\n");
 		put_tty_driver(mxvar_sdriver);
 
 		for (i = 0; i < MXSER_BOARDS; i++) {
@@ -866,7 +909,7 @@
 				continue;
 			else {
 				free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
-				//todo: release io, vector
+				/* todo: release io, vector */
 			}
 		}
 		return retval;
@@ -877,7 +920,7 @@
 
 static void mxser_do_softint(void *private_)
 {
-	struct mxser_struct *info = (struct mxser_struct *) private_;
+	struct mxser_struct *info = private_;
 	struct tty_struct *tty;
 
 	tty = info->tty;
@@ -926,7 +969,7 @@
 		return -ENODEV;
 	info = mxvar_table + line;
 	if (!info->base)
-		return (-ENODEV);
+		return -ENODEV;
 
 	tty->driver_data = info;
 	info->tty = tty;
@@ -935,11 +978,11 @@
 	 */
 	retval = mxser_startup(info);
 	if (retval)
-		return (retval);
+		return retval;
 
 	retval = mxser_block_til_ready(tty, filp, info);
 	if (retval)
-		return (retval);
+		return retval;
 
 	info->count++;
 
@@ -953,13 +996,13 @@
 
 	info->session = current->signal->session;
 	info->pgrp = process_group(current);
-	clear_bit(TTY_DONT_FLIP, &tty->flags);
 
-	//status = mxser_get_msr(info->base, 0, info->port);
-	//mxser_check_modem_status(info, status);
+	/*
+	status = mxser_get_msr(info->base, 0, info->port);
+	mxser_check_modem_status(info, status);
+	*/
 
-/* unmark here for very high baud rate (ex. 921600 bps) used
-*/
+/* unmark here for very high baud rate (ex. 921600 bps) used */
 	tty->low_latency = 1;
 	return 0;
 }
@@ -972,7 +1015,7 @@
  */
 static void mxser_close(struct tty_struct *tty, struct file *filp)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 
 	unsigned long timeout;
 	unsigned long flags;
@@ -997,11 +1040,13 @@
 		 * one, we've got real problems, since it means the
 		 * serial port won't be shutdown.
 		 */
-		printk(KERN_ERR "mxser_close: bad serial port count; tty->count is 1, " "info->count is %d\n", info->count);
+		printk(KERN_ERR "mxser_close: bad serial port count; "
+			"tty->count is 1, info->count is %d\n", info->count);
 		info->count = 1;
 	}
 	if (--info->count < 0) {
-		printk(KERN_ERR "mxser_close: bad serial port count for ttys%d: %d\n", info->port, info->count);
+		printk(KERN_ERR "mxser_close: bad serial port count for "
+			"ttys%d: %d\n", info->port, info->count);
 		info->count = 0;
 	}
 	if (info->count) {
@@ -1056,7 +1101,7 @@
 		
 	ld = tty_ldisc_ref(tty);
 	if (ld) {
-		if(ld->flush_buffer)
+		if (ld->flush_buffer)
 			ld->flush_buffer(tty);
 		tty_ldisc_deref(ld);
 	}
@@ -1078,31 +1123,34 @@
 static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
 	int c, total = 0;
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
-	if (!tty || !info->xmit_buf)
-		return (0);
+	if (!info->xmit_buf)
+		return 0;
 
 	while (1) {
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head));
+		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					  SERIAL_XMIT_SIZE - info->xmit_head));
 		if (c <= 0)
 			break;
 
 		memcpy(info->xmit_buf + info->xmit_head, buf, c);
 		spin_lock_irqsave(&info->slock, flags);
-		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+		info->xmit_head = (info->xmit_head + c) &
+				  (SERIAL_XMIT_SIZE - 1);
 		info->xmit_cnt += c;
 		spin_unlock_irqrestore(&info->slock, flags);
 
 		buf += c;
 		count -= c;
 		total += c;
-
 	}
 
 	if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) {
-		if (!tty->hw_stopped || (info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) {
+		if (!tty->hw_stopped ||
+				(info->type == PORT_16550A) ||
+				(info->IsMoxaMustChipFlag)) {
 			spin_lock_irqsave(&info->slock, flags);
 			info->IER |= UART_IER_THRI;
 			outb(info->IER, info->base + UART_IER);
@@ -1114,10 +1162,10 @@
 
 static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
-	if (!tty || !info->xmit_buf)
+	if (!info->xmit_buf)
 		return;
 
 	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
@@ -1129,7 +1177,9 @@
 	info->xmit_cnt++;
 	spin_unlock_irqrestore(&info->slock, flags);
 	if (!tty->stopped && !(info->IER & UART_IER_THRI)) {
-		if (!tty->hw_stopped || (info->type == PORT_16550A) || info->IsMoxaMustChipFlag) {
+		if (!tty->hw_stopped ||
+				(info->type == PORT_16550A) ||
+				info->IsMoxaMustChipFlag) {
 			spin_lock_irqsave(&info->slock, flags);
 			info->IER |= UART_IER_THRI;
 			outb(info->IER, info->base + UART_IER);
@@ -1141,10 +1191,16 @@
 
 static void mxser_flush_chars(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
-	if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf || (tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)))
+	if (info->xmit_cnt <= 0 ||
+			tty->stopped ||
+			!info->xmit_buf ||
+			(tty->hw_stopped &&
+			 (info->type != PORT_16550A) &&
+			 (!info->IsMoxaMustChipFlag)
+			))
 		return;
 
 	spin_lock_irqsave(&info->slock, flags);
@@ -1157,24 +1213,24 @@
 
 static int mxser_write_room(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	int ret;
 
 	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
 	if (ret < 0)
 		ret = 0;
-	return (ret);
+	return ret;
 }
 
 static int mxser_chars_in_buffer(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	return info->xmit_cnt;
 }
 
 static void mxser_flush_buffer(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	char fcr;
 	unsigned long flags;
 
@@ -1184,7 +1240,8 @@
 
 	/* below added by shinhay */
 	fcr = inb(info->base + UART_FCR);
-	outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
+	outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+		info->base + UART_FCR);
 	outb(fcr, info->base + UART_FCR);
 
 	spin_unlock_irqrestore(&info->slock, flags);
@@ -1197,7 +1254,7 @@
 
 static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	int retval;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
 	struct serial_icounter_struct __user *p_cuser;
@@ -1206,9 +1263,9 @@
 	void __user *argp = (void __user *)arg;
 
 	if (tty->index == MXSER_PORTS)
-		return (mxser_ioctl_special(cmd, argp));
+		return mxser_ioctl_special(cmd, argp);
 
-	// following add by Victor Yu. 01-05-2004
+	/* following add by Victor Yu. 01-05-2004 */
 	if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
 		int opmode, p;
 		static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
@@ -1219,7 +1276,10 @@
 		if (cmd == MOXA_SET_OP_MODE) {
 			if (get_user(opmode, (int __user *) argp))
 				return -EFAULT;
-			if (opmode != RS232_MODE && opmode != RS485_2WIRE_MODE && opmode != RS422_MODE && opmode != RS485_4WIRE_MODE)
+			if (opmode != RS232_MODE &&
+					opmode != RS485_2WIRE_MODE &&
+					opmode != RS422_MODE &&
+					opmode != RS485_4WIRE_MODE)
 				return -EFAULT;
 			mask = ModeMask[p];
 			shiftbit = p * 2;
@@ -1236,36 +1296,36 @@
 		}
 		return 0;
 	}
-	// above add by Victor Yu. 01-05-2004
+	/* above add by Victor Yu. 01-05-2004 */
 
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
 		if (tty->flags & (1 << TTY_IO_ERROR))
-			return (-EIO);
+			return -EIO;
 	}
 	switch (cmd) {
 	case TCSBRK:		/* SVID version: non-zero arg --> no break */
 		retval = tty_check_change(tty);
 		if (retval)
-			return (retval);
+			return retval;
 		tty_wait_until_sent(tty, 0);
 		if (!arg)
 			mxser_send_break(info, HZ / 4);	/* 1/4 second */
-		return (0);
+		return 0;
 	case TCSBRKP:		/* support for POSIX tcsendbreak() */
 		retval = tty_check_change(tty);
 		if (retval)
-			return (retval);
+			return retval;
 		tty_wait_until_sent(tty, 0);
 		mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
-		return (0);
+		return 0;
 	case TIOCGSOFTCAR:
-		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
+		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
 	case TIOCSSOFTCAR:
 		if (get_user(templ, (unsigned long __user *) argp))
 			return -EFAULT;
 		arg = templ;
 		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
-		return (0);
+		return 0;
 	case TIOCGSERIAL:
 		return mxser_get_serial_info(info, argp);
 	case TIOCSSERIAL:
@@ -1278,7 +1338,7 @@
 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
 		 * Caller should use TIOCGICOUNT to see which one it was
 		 */
-	case TIOCMIWAIT:{
+	case TIOCMIWAIT: {
 			DECLARE_WAITQUEUE(wait, current);
 			int ret;
 			spin_lock_irqsave(&info->slock, flags);
@@ -1292,7 +1352,14 @@
 				spin_unlock_irqrestore(&info->slock, flags);
 
 				set_current_state(TASK_INTERRUPTIBLE);
-				if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+				if (((arg & TIOCM_RNG) &&
+						(cnow.rng != cprev.rng)) ||
+						((arg & TIOCM_DSR) &&
+						(cnow.dsr != cprev.dsr)) ||
+						((arg & TIOCM_CD) &&
+						(cnow.dcd != cprev.dcd)) ||
+						((arg & TIOCM_CTS) &&
+						(cnow.cts != cprev.cts))) {
 					ret = 0;
 					break;
 				}
@@ -1338,21 +1405,18 @@
 		put_user(cnow.dsr, &p_cuser->dsr);
 		put_user(cnow.rng, &p_cuser->rng);
 		put_user(cnow.dcd, &p_cuser->dcd);
-
-/* */
 		return 0;
 	case MOXA_HighSpeedOn:
-		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *) argp);
-
-	case MOXA_SDS_RSTICOUNTER:{
+		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
+	case MOXA_SDS_RSTICOUNTER: {
 			info->mon_data.rxcnt = 0;
 			info->mon_data.txcnt = 0;
 			return 0;
 		}
-// (above) added by James.
+/* (above) added by James. */
 	case MOXA_ASPP_SETBAUD:{
 			long baud;
-			if (get_user(baud, (long __user *) argp))
+			if (get_user(baud, (long __user *)argp))
 				return -EFAULT;
 			mxser_set_baud(info, baud);
 			return 0;
@@ -1377,9 +1441,10 @@
 
 			return 0;
 		}
-	case MOXA_ASPP_MON:{
+	case MOXA_ASPP_MON: {
 			int mcr, status;
-//      info->mon_data.ser_param = tty->termios->c_cflag;
+
+			/* info->mon_data.ser_param = tty->termios->c_cflag; */
 
 			status = mxser_get_msr(info->base, 1, info->port, info);
 			mxser_check_modem_status(info, status);
@@ -1400,25 +1465,25 @@
 			else
 				info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
 
-
-			if (copy_to_user(argp, &info->mon_data, sizeof(struct mxser_mon)))
+			if (copy_to_user(argp, &info->mon_data,
+					sizeof(struct mxser_mon)))
 				return -EFAULT;
 
 			return 0;
-
 		}
 
-	case MOXA_ASPP_LSTATUS:{
-			if (copy_to_user(argp, &info->err_shadow, sizeof(unsigned char)))
+	case MOXA_ASPP_LSTATUS: {
+			if (copy_to_user(argp, &info->err_shadow,
+					sizeof(unsigned char)))
 				return -EFAULT;
 
 			info->err_shadow = 0;
 			return 0;
-
 		}
-	case MOXA_SET_BAUD_METHOD:{
+	case MOXA_SET_BAUD_METHOD: {
 			int method;
-			if (get_user(method, (int __user *) argp))
+
+			if (get_user(method, (int __user *)argp))
 				return -EFAULT;
 			mxser_set_baud_method[info->port] = method;
 			if (copy_to_user(argp, &method, sizeof(int)))
@@ -1442,7 +1507,8 @@
 
 	switch (cmd) {
 	case MOXA_GET_CONF:
-		if (copy_to_user(argp, mxsercfg, sizeof(struct mxser_hwconf) * 4))
+		if (copy_to_user(argp, mxsercfg,
+				sizeof(struct mxser_hwconf) * 4))
 			return -EFAULT;
 		return 0;
 	case MOXA_GET_MAJOR:
@@ -1461,11 +1527,11 @@
 			if (mxvar_table[i].base)
 				result |= (1 << i);
 		}
-		return put_user(result, (unsigned long __user *) argp);
+		return put_user(result, (unsigned long __user *)argp);
 	case MOXA_GETDATACOUNT:
 		if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
 			return -EFAULT;
-		return (0);
+		return 0;
 	case MOXA_GETMSTATUS:
 		for (i = 0; i < MXSER_PORTS; i++) {
 			GMStatus[i].ri = 0;
@@ -1498,22 +1564,26 @@
 			else
 				GMStatus[i].cts = 0;
 		}
-		if (copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MXSER_PORTS))
+		if (copy_to_user(argp, GMStatus,
+				sizeof(struct mxser_mstatus) * MXSER_PORTS))
 			return -EFAULT;
 		return 0;
-	case MOXA_ASPP_MON_EXT:{
+	case MOXA_ASPP_MON_EXT: {
 			int status;
 			int opmode, p;
 			int shiftbit;
 			unsigned cflag, iflag;
 
 			for (i = 0; i < MXSER_PORTS; i++) {
-
 				if (!mxvar_table[i].base)
 					continue;
 
-				status = mxser_get_msr(mxvar_table[i].base, 0, i, &(mxvar_table[i]));
-//                      mxser_check_modem_status(&mxvar_table[i], status);
+				status = mxser_get_msr(mxvar_table[i].base, 0,
+							i, &(mxvar_table[i]));
+				/*
+				mxser_check_modem_status(&mxvar_table[i],
+								status);
+				*/
 				if (status & UART_MSR_TERI)
 					mxvar_table[i].icount.rng++;
 				if (status & UART_MSR_DDSR)
@@ -1578,75 +1648,76 @@
 	return 0;
 }
 
-
 static void mxser_stoprx(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
-	//unsigned long flags;
-
+	struct mxser_struct *info = tty->driver_data;
+	/* unsigned long flags; */
 
 	info->ldisc_stop_rx = 1;
 	if (I_IXOFF(tty)) {
-
-		//MX_LOCK(&info->slock);
-		// following add by Victor Yu. 09-02-2002
+		/* MX_LOCK(&info->slock); */
+		/* following add by Victor Yu. 09-02-2002 */
 		if (info->IsMoxaMustChipFlag) {
 			info->IER &= ~MOXA_MUST_RECV_ISR;
 			outb(info->IER, info->base + UART_IER);
 		} else {
-			// above add by Victor Yu. 09-02-2002
-
+			/* above add by Victor Yu. 09-02-2002 */
 			info->x_char = STOP_CHAR(tty);
-			//      outb(info->IER, 0); // mask by Victor Yu. 09-02-2002
+			/* mask by Victor Yu. 09-02-2002 */
+			/* outb(info->IER, 0); */
 			outb(0, info->base + UART_IER);
 			info->IER |= UART_IER_THRI;
-			outb(info->IER, info->base + UART_IER);	/* force Tx interrupt */
-		}		// add by Victor Yu. 09-02-2002
-		//MX_UNLOCK(&info->slock);
+			/* force Tx interrupt */
+			outb(info->IER, info->base + UART_IER);
+		}		/* add by Victor Yu. 09-02-2002 */
+		/* MX_UNLOCK(&info->slock); */
 	}
 
 	if (info->tty->termios->c_cflag & CRTSCTS) {
-		//MX_LOCK(&info->slock);
+		/* MX_LOCK(&info->slock); */
 		info->MCR &= ~UART_MCR_RTS;
 		outb(info->MCR, info->base + UART_MCR);
-		//MX_UNLOCK(&info->slock);
+		/* MX_UNLOCK(&info->slock); */
 	}
 }
 
 static void mxser_startrx(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
-	//unsigned long flags;
+	struct mxser_struct *info = tty->driver_data;
+	/* unsigned long flags; */
 
 	info->ldisc_stop_rx = 0;
 	if (I_IXOFF(tty)) {
 		if (info->x_char)
 			info->x_char = 0;
 		else {
-			//MX_LOCK(&info->slock);
+			/* MX_LOCK(&info->slock); */
 
-			// following add by Victor Yu. 09-02-2002
+			/* following add by Victor Yu. 09-02-2002 */
 			if (info->IsMoxaMustChipFlag) {
 				info->IER |= MOXA_MUST_RECV_ISR;
 				outb(info->IER, info->base + UART_IER);
 			} else {
-				// above add by Victor Yu. 09-02-2002
+				/* above add by Victor Yu. 09-02-2002 */
 
 				info->x_char = START_CHAR(tty);
-				//          outb(info->IER, 0); // mask by Victor Yu. 09-02-2002
-				outb(0, info->base + UART_IER);	// add by Victor Yu. 09-02-2002
-				info->IER |= UART_IER_THRI;	/* force Tx interrupt */
+				/* mask by Victor Yu. 09-02-2002 */
+				/* outb(info->IER, 0); */
+				/* add by Victor Yu. 09-02-2002 */
+				outb(0, info->base + UART_IER);
+				/* force Tx interrupt */
+				info->IER |= UART_IER_THRI;
 				outb(info->IER, info->base + UART_IER);
-			}	// add by Victor Yu. 09-02-2002
-			//MX_UNLOCK(&info->slock);
+			}	/* add by Victor Yu. 09-02-2002 */
+			/* MX_UNLOCK(&info->slock); */
 		}
 	}
 
 	if (info->tty->termios->c_cflag & CRTSCTS) {
-		//MX_LOCK(&info->slock);
+		/* MX_LOCK(&info->slock); */
 		info->MCR |= UART_MCR_RTS;
 		outb(info->MCR, info->base + UART_MCR);
-		//MX_UNLOCK(&info->slock);
+		/* MX_UNLOCK(&info->slock); */
 	}
 }
 
@@ -1656,48 +1727,53 @@
  */
 static void mxser_throttle(struct tty_struct *tty)
 {
-	//struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
-	//unsigned long flags;
-	//MX_LOCK(&info->slock);
+	/* struct mxser_struct *info = tty->driver_data; */
+	/* unsigned long flags; */
+
+	/* MX_LOCK(&info->slock); */
 	mxser_stoprx(tty);
-	//MX_UNLOCK(&info->slock);
+	/* MX_UNLOCK(&info->slock); */
 }
 
 static void mxser_unthrottle(struct tty_struct *tty)
 {
-	//struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
-	//unsigned long flags;
-	//MX_LOCK(&info->slock);
+	/* struct mxser_struct *info = tty->driver_data; */
+	/* unsigned long flags; */
+
+	/* MX_LOCK(&info->slock); */
 	mxser_startrx(tty);
-	//MX_UNLOCK(&info->slock);
+	/* MX_UNLOCK(&info->slock); */
 }
 
 static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
-	if ((tty->termios->c_cflag != old_termios->c_cflag) || (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+	if ((tty->termios->c_cflag != old_termios->c_cflag) ||
+			(RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
 
 		mxser_change_speed(info, old_termios);
 
-		if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
+		if ((old_termios->c_cflag & CRTSCTS) &&
+				!(tty->termios->c_cflag & CRTSCTS)) {
 			tty->hw_stopped = 0;
 			mxser_start(tty);
 		}
 	}
 
 /* Handle sw stopped */
-	if ((old_termios->c_iflag & IXON) && !(tty->termios->c_iflag & IXON)) {
+	if ((old_termios->c_iflag & IXON) &&
+			!(tty->termios->c_iflag & IXON)) {
 		tty->stopped = 0;
 
-		// following add by Victor Yu. 09-02-2002
+		/* following add by Victor Yu. 09-02-2002 */
 		if (info->IsMoxaMustChipFlag) {
 			spin_lock_irqsave(&info->slock, flags);
 			DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
 			spin_unlock_irqrestore(&info->slock, flags);
 		}
-		// above add by Victor Yu. 09-02-2002
+		/* above add by Victor Yu. 09-02-2002 */
 
 		mxser_start(tty);
 	}
@@ -1711,7 +1787,7 @@
  */
 static void mxser_stop(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&info->slock, flags);
@@ -1724,7 +1800,7 @@
 
 static void mxser_start(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&info->slock, flags);
@@ -1740,7 +1816,7 @@
  */
 static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long orig_jiffies, char_time;
 	int lsr;
 
@@ -1777,7 +1853,8 @@
 	if (!timeout || timeout > 2 * info->timeout)
 		timeout = 2 * info->timeout;
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+	printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
+		timeout, char_time);
 	printk("jiff=%lu...", jiffies);
 #endif
 	while (!((lsr = inb(info->base + UART_LSR)) & UART_LSR_TEMT)) {
@@ -1803,7 +1880,7 @@
  */
 void mxser_hangup(struct tty_struct *tty)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 
 	mxser_flush_buffer(tty);
 	mxser_shutdown(info);
@@ -1815,24 +1892,26 @@
 }
 
 
-// added by James 03-12-2004.
+/* added by James 03-12-2004. */
 /*
  * mxser_rs_break() --- routine which turns the break handling on or off
  */
 static void mxser_rs_break(struct tty_struct *tty, int break_state)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&info->slock, flags);
 	if (break_state == -1)
-		outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
+		outb(inb(info->base + UART_LCR) | UART_LCR_SBC,
+			info->base + UART_LCR);
 	else
-		outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
+		outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC,
+			info->base + UART_LCR);
 	spin_unlock_irqrestore(&info->slock, flags);
 }
 
-// (above) added by James.
+/* (above) added by James. */
 
 
 /*
@@ -1848,7 +1927,7 @@
 	int handled = IRQ_NONE;
 
 	port = NULL;
-	//spin_lock(&gm_lock);
+	/* spin_lock(&gm_lock); */
 
 	for (i = 0; i < MXSER_BOARDS; i++) {
 		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
@@ -1857,29 +1936,25 @@
 		}
 	}
 
-	if (i == MXSER_BOARDS) {
+	if (i == MXSER_BOARDS)
 		goto irq_stop;
-	}
-	if (port == 0) {
+	if (port == 0)
 		goto irq_stop;
-	}
 	max = mxser_numports[mxsercfg[i].board_type - 1];
 	while (1) {
 		irqbits = inb(port->vector) & port->vectormask;
-		if (irqbits == port->vectormask) {
+		if (irqbits == port->vectormask)
 			break;
-		}
 
 		handled = IRQ_HANDLED;
 		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
-			if (irqbits == port->vectormask) {
+			if (irqbits == port->vectormask)
 				break;
-			}
 			if (bits & irqbits)
 				continue;
 			info = port + i;
 
-			// following add by Victor Yu. 09-13-2002
+			/* following add by Victor Yu. 09-13-2002 */
 			iir = inb(info->base + UART_IIR);
 			if (iir & UART_IIR_NO_INT)
 				continue;
@@ -1890,9 +1965,9 @@
 				inb(info->base + UART_MSR);
 				continue;
 			}
-			// above add by Victor Yu. 09-13-2002
+			/* above add by Victor Yu. 09-13-2002 */
 			/*
-			   if ( info->tty->flip.count < TTY_FLIPBUF_SIZE/4 ){
+			   if (info->tty->flip.count < TTY_FLIPBUF_SIZE / 4) {
 			   info->IER |= MOXA_MUST_RECV_ISR;
 			   outb(info->IER, info->base + UART_IER);
 			   }
@@ -1908,18 +1983,15 @@
 			   status = inb(info->base + UART_LSR) & info->read_status_mask;
 			 */
 
-			// following add by Victor Yu. 09-02-2002
+			/* following add by Victor Yu. 09-02-2002 */
 			status = inb(info->base + UART_LSR);
 
-			if (status & UART_LSR_PE) {
+			if (status & UART_LSR_PE)
 				info->err_shadow |= NPPI_NOTIFY_PARITY;
-			}
-			if (status & UART_LSR_FE) {
+			if (status & UART_LSR_FE)
 				info->err_shadow |= NPPI_NOTIFY_FRAMING;
-			}
-			if (status & UART_LSR_OE) {
+			if (status & UART_LSR_OE)
 				info->err_shadow |= NPPI_NOTIFY_HW_OVERRUN;
-			}
 			if (status & UART_LSR_BI)
 				info->err_shadow |= NPPI_NOTIFY_BREAK;
 
@@ -1930,11 +2002,14 @@
 				   continue;
 				   }
 				 */
-				if (iir == MOXA_MUST_IIR_GDA || iir == MOXA_MUST_IIR_RDA || iir == MOXA_MUST_IIR_RTO || iir == MOXA_MUST_IIR_LSR)
+				if (iir == MOXA_MUST_IIR_GDA ||
+						iir == MOXA_MUST_IIR_RDA ||
+						iir == MOXA_MUST_IIR_RTO ||
+						iir == MOXA_MUST_IIR_LSR)
 					mxser_receive_chars(info, &status);
 
 			} else {
-				// above add by Victor Yu. 09-02-2002
+				/* above add by Victor Yu. 09-02-2002 */
 
 				status &= info->read_status_mask;
 				if (status & UART_LSR_DR)
@@ -1944,13 +2019,13 @@
 			if (msr & UART_MSR_ANY_DELTA) {
 				mxser_check_modem_status(info, msr);
 			}
-			// following add by Victor Yu. 09-13-2002
+			/* following add by Victor Yu. 09-13-2002 */
 			if (info->IsMoxaMustChipFlag) {
 				if ((iir == 0x02) && (status & UART_LSR_THRE)) {
 					mxser_transmit_chars(info);
 				}
 			} else {
-				// above add by Victor Yu. 09-13-2002
+				/* above add by Victor Yu. 09-13-2002 */
 
 				if (status & UART_LSR_THRE) {
 /* 8-2-99 by William
@@ -1966,7 +2041,7 @@
 	}
 
       irq_stop:
-	//spin_unlock(&gm_lock);
+	/* spin_unlock(&gm_lock); */
 	return handled;
 }
 
@@ -1984,56 +2059,58 @@
 
 	recv_room = tty->receive_room;
 	if ((recv_room == 0) && (!info->ldisc_stop_rx)) {
-		//mxser_throttle(tty);
+		/* mxser_throttle(tty); */
 		mxser_stoprx(tty);
-		//return;
+		/* return; */
 	}
 
-	// following add by Victor Yu. 09-02-2002
+	/* following add by Victor Yu. 09-02-2002 */
 	if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
 
 		if (*status & UART_LSR_SPECIAL) {
 			goto intr_old;
 		}
-		// following add by Victor Yu. 02-11-2004
-		if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID && (*status & MOXA_MUST_LSR_RERR))
+		/* following add by Victor Yu. 02-11-2004 */
+		if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID &&
+				(*status & MOXA_MUST_LSR_RERR))
 			goto intr_old;
-		// above add by Victor Yu. 02-14-2004
+		/* above add by Victor Yu. 02-14-2004 */
 		if (*status & MOXA_MUST_LSR_RERR)
 			goto intr_old;
 
 		gdl = inb(info->base + MOXA_MUST_GDL_REGISTER);
 
-		if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID)	// add by Victor Yu. 02-11-2004
+		/* add by Victor Yu. 02-11-2004 */
+		if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID)
 			gdl &= MOXA_MUST_GDL_MASK;
 		if (gdl >= recv_room) {
 			if (!info->ldisc_stop_rx) {
-				//mxser_throttle(tty);
+				/* mxser_throttle(tty); */
 				mxser_stoprx(tty);
 			}
-			//return;
+			/* return; */
 		}
 		while (gdl--) {
 			ch = inb(info->base + UART_RX);
 			tty_insert_flip_char(tty, ch, 0);
 			cnt++;
 			/*
-			   if((cnt>=HI_WATER) && (info->stop_rx==0)){
+			   if ((cnt >= HI_WATER) && (info->stop_rx == 0)) {
 			   mxser_stoprx(tty);
-			   info->stop_rx=1;
+			   info->stop_rx = 1;
 			   break;
 			   } */
 		}
 		goto end_intr;
 	}
-intr_old:
-	// above add by Victor Yu. 09-02-2002
+ intr_old:
+	/* above add by Victor Yu. 09-02-2002 */
 
 	do {
 		if (max-- < 0)
 			break;
 		/*
-		   if((cnt>=HI_WATER) && (info->stop_rx==0)){
+		   if ((cnt >= HI_WATER) && (info->stop_rx == 0)) {
 		   mxser_stoprx(tty);
 		   info->stop_rx=1;
 		   break;
@@ -2041,11 +2118,11 @@
 		 */
 
 		ch = inb(info->base + UART_RX);
-		// following add by Victor Yu. 09-02-2002
+		/* following add by Victor Yu. 09-02-2002 */
 		if (info->IsMoxaMustChipFlag && (*status & UART_LSR_OE) /*&& !(*status&UART_LSR_DR) */ )
 			outb(0x23, info->base + UART_FCR);
 		*status &= info->read_status_mask;
-		// above add by Victor Yu. 09-02-2002
+		/* above add by Victor Yu. 09-02-2002 */
 		if (*status & info->ignore_status_mask) {
 			if (++ignored > 100)
 				break;
@@ -2080,7 +2157,7 @@
 			cnt++;
 			if (cnt >= recv_room) {
 				if (!info->ldisc_stop_rx) {
-					//mxser_throttle(tty);
+					/* mxser_throttle(tty); */
 					mxser_stoprx(tty);
 				}
 				break;
@@ -2088,21 +2165,20 @@
 
 		}
 
-		// following add by Victor Yu. 09-02-2002
+		/* following add by Victor Yu. 09-02-2002 */
 		if (info->IsMoxaMustChipFlag)
 			break;
-		// above add by Victor Yu. 09-02-2002
+		/* above add by Victor Yu. 09-02-2002 */
 
 		/* mask by Victor Yu. 09-02-2002
 		 *status = inb(info->base + UART_LSR) & info->read_status_mask;
 		 */
-		// following add by Victor Yu. 09-02-2002
+		/* following add by Victor Yu. 09-02-2002 */
 		*status = inb(info->base + UART_LSR);
-		// above add by Victor Yu. 09-02-2002
+		/* above add by Victor Yu. 09-02-2002 */
 	} while (*status & UART_LSR_DR);
 
-end_intr:		// add by Victor Yu. 09-02-2002
-
+end_intr:		/* add by Victor Yu. 09-02-2002 */
 	mxvar_log.rxcnt[info->port] += cnt;
 	info->mon_data.rxcnt += cnt;
 	info->mon_data.up_rxcnt += cnt;
@@ -2137,7 +2213,10 @@
 		return;
 	}
 
-	if ((info->xmit_cnt <= 0) || info->tty->stopped || (info->tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag))) {
+	if ((info->xmit_cnt <= 0) || info->tty->stopped ||
+			(info->tty->hw_stopped &&
+			(info->type != PORT_16550A) &&
+			(!info->IsMoxaMustChipFlag))) {
 		info->IER &= ~UART_IER_THRI;
 		outb(info->IER, info->base + UART_IER);
 		spin_unlock_irqrestore(&info->slock, flags);
@@ -2147,17 +2226,18 @@
 	cnt = info->xmit_cnt;
 	count = info->xmit_fifo_size;
 	do {
-		outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
+		outb(info->xmit_buf[info->xmit_tail++],
+			info->base + UART_TX);
 		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
 		if (--info->xmit_cnt <= 0)
 			break;
 	} while (--count > 0);
 	mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
 
-// added by James 03-12-2004.
+/* added by James 03-12-2004. */
 	info->mon_data.txcnt += (cnt - info->xmit_cnt);
 	info->mon_data.up_txcnt += (cnt - info->xmit_cnt);
-// (above) added by James.
+/* (above) added by James. */
 
 /* added by casper 1/11/2000 */
 	info->icount.tx += (cnt - info->xmit_cnt);
@@ -2188,7 +2268,6 @@
 	info->mon_data.modem_status = status;
 	wake_up_interruptible(&info->delta_msr_wait);
 
-
 	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
 		if (status & UART_MSR_DCD)
 			wake_up_interruptible(&info->open_wait);
@@ -2200,7 +2279,8 @@
 			if (status & UART_MSR_CTS) {
 				info->tty->hw_stopped = 0;
 
-				if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+				if ((info->type != PORT_16550A) &&
+						(!info->IsMoxaMustChipFlag)) {
 					info->IER |= UART_IER_THRI;
 					outb(info->IER, info->base + UART_IER);
 				}
@@ -2209,7 +2289,8 @@
 		} else {
 			if (!(status & UART_MSR_CTS)) {
 				info->tty->hw_stopped = 1;
-				if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+				if ((info->type != PORT_16550A) &&
+						(!info->IsMoxaMustChipFlag)) {
 					info->IER &= ~UART_IER_THRI;
 					outb(info->IER, info->base + UART_IER);
 				}
@@ -2231,7 +2312,7 @@
 	 */
 	if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
 		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return (0);
+		return 0;
 	}
 
 	if (tty->termios->c_cflag & CLOCAL)
@@ -2254,7 +2335,8 @@
 	info->blocked_open++;
 	while (1) {
 		spin_lock_irqsave(&info->slock, flags);
-		outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR);
+		outb(inb(info->base + UART_MCR) |
+			UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR);
 		spin_unlock_irqrestore(&info->slock, flags);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) {
@@ -2264,7 +2346,9 @@
 				retval = -ERESTARTSYS;
 			break;
 		}
-		if (!(info->flags & ASYNC_CLOSING) && (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)))
+		if (!(info->flags & ASYNC_CLOSING) &&
+				(do_clocal ||
+				(inb(info->base + UART_MSR) & UART_MSR_DCD)))
 			break;
 		if (signal_pending(current)) {
 			retval = -ERESTARTSYS;
@@ -2278,27 +2362,26 @@
 		info->count++;
 	info->blocked_open--;
 	if (retval)
-		return (retval);
+		return retval;
 	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return (0);
+	return 0;
 }
 
 static int mxser_startup(struct mxser_struct *info)
 {
-
 	unsigned long page;
 	unsigned long flags;
 
 	page = __get_free_page(GFP_KERNEL);
 	if (!page)
-		return (-ENOMEM);
+		return -ENOMEM;
 
 	spin_lock_irqsave(&info->slock, flags);
 
 	if (info->flags & ASYNC_INITIALIZED) {
 		free_page(page);
 		spin_unlock_irqrestore(&info->slock, flags);
-		return (0);
+		return 0;
 	}
 
 	if (!info->base || !info->type) {
@@ -2306,7 +2389,7 @@
 			set_bit(TTY_IO_ERROR, &info->tty->flags);
 		free_page(page);
 		spin_unlock_irqrestore(&info->slock, flags);
-		return (0);
+		return 0;
 	}
 	if (info->xmit_buf)
 		free_page(page);
@@ -2318,9 +2401,12 @@
 	 * (they will be reenabled in mxser_change_speed())
 	 */
 	if (info->IsMoxaMustChipFlag)
-		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
+		outb((UART_FCR_CLEAR_RCVR |
+			UART_FCR_CLEAR_XMIT |
+			MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
 	else
-		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
+		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+			info->base + UART_FCR);
 
 	/*
 	 * At this point there's no way the LSR could still be 0xFF;
@@ -2332,9 +2418,9 @@
 		if (capable(CAP_SYS_ADMIN)) {
 			if (info->tty)
 				set_bit(TTY_IO_ERROR, &info->tty->flags);
-			return (0);
+			return 0;
 		} else
-			return (-ENODEV);
+			return -ENODEV;
 	}
 
 	/*
@@ -2356,12 +2442,12 @@
 	 * Finally, enable interrupts
 	 */
 	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
-//      info->IER = UART_IER_RLSI | UART_IER_RDI;
+	/* info->IER = UART_IER_RLSI | UART_IER_RDI; */
 
-	// following add by Victor Yu. 08-30-2002
+	/* following add by Victor Yu. 08-30-2002 */
 	if (info->IsMoxaMustChipFlag)
 		info->IER |= MOXA_MUST_IER_EGDAI;
-	// above add by Victor Yu. 08-30-2002
+	/* above add by Victor Yu. 08-30-2002 */
 	outb(info->IER, info->base + UART_IER);	/* enable interrupts */
 
 	/*
@@ -2383,7 +2469,7 @@
 	mxser_change_speed(info, NULL);
 
 	info->flags |= ASYNC_INITIALIZED;
-	return (0);
+	return 0;
 }
 
 /*
@@ -2421,12 +2507,15 @@
 	outb(info->MCR, info->base + UART_MCR);
 
 	/* clear Rx/Tx FIFO's */
-	// following add by Victor Yu. 08-30-2002
+	/* following add by Victor Yu. 08-30-2002 */
 	if (info->IsMoxaMustChipFlag)
-		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
+		outb((UART_FCR_CLEAR_RCVR |
+			UART_FCR_CLEAR_XMIT |
+			MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
 	else
-		// above add by Victor Yu. 08-30-2002
-		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
+		/* above add by Victor Yu. 08-30-2002 */
+		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+			info->base + UART_FCR);
 
 	/* read data port to reset things */
 	(void) inb(info->base + UART_RX);
@@ -2436,11 +2525,10 @@
 
 	info->flags &= ~ASYNC_INITIALIZED;
 
-	// following add by Victor Yu. 09-23-2002
-	if (info->IsMoxaMustChipFlag) {
+	/* following add by Victor Yu. 09-23-2002 */
+	if (info->IsMoxaMustChipFlag)
 		SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
-	}
-	// above add by Victor Yu. 09-23-2002
+	/* above add by Victor Yu. 09-23-2002 */
 
 	spin_unlock_irqrestore(&info->slock, flags);
 }
@@ -2457,14 +2545,12 @@
 	long baud;
 	unsigned long flags;
 
-
 	if (!info->tty || !info->tty->termios)
 		return ret;
 	cflag = info->tty->termios->c_cflag;
 	if (!(info->base))
 		return ret;
 
-
 #ifndef B921600
 #define B921600 (B460800 +1)
 #endif
@@ -2559,9 +2645,8 @@
 		cval |= 0x04;
 	if (cflag & PARENB)
 		cval |= UART_LCR_PARITY;
-	if (!(cflag & PARODD)) {
+	if (!(cflag & PARODD))
 		cval |= UART_LCR_EPAR;
-	}
 	if (cflag & CMSPAR)
 		cval |= UART_LCR_SPAR;
 
@@ -2574,13 +2659,12 @@
 			fcr = 0;
 	} else {
 		fcr = UART_FCR_ENABLE_FIFO;
-		// following add by Victor Yu. 08-30-2002
+		/* following add by Victor Yu. 08-30-2002 */
 		if (info->IsMoxaMustChipFlag) {
 			fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
 			SET_MOXA_MUST_FIFO_VALUE(info);
 		} else {
-			// above add by Victor Yu. 08-30-2002
-
+			/* above add by Victor Yu. 08-30-2002 */
 			switch (info->rx_trigger) {
 			case 1:
 				fcr |= UART_FCR_TRIGGER_1;
@@ -2606,22 +2690,24 @@
 		info->IER |= UART_IER_MSI;
 		if ((info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) {
 			info->MCR |= UART_MCR_AFE;
-			//status = mxser_get_msr(info->base, 0, info->port);
-/*	save_flags(flags);
+			/* status = mxser_get_msr(info->base, 0, info->port); */
+/*
+	save_flags(flags);
 	cli();
 	status = inb(baseaddr + UART_MSR);
-	restore_flags(flags);*/
-			//mxser_check_modem_status(info, status);
+	restore_flags(flags);
+*/
+			/* mxser_check_modem_status(info, status); */
 		} else {
-			//status = mxser_get_msr(info->base, 0, info->port);
-
-			//MX_LOCK(&info->slock);
+			/* status = mxser_get_msr(info->base, 0, info->port); */
+			/* MX_LOCK(&info->slock); */
 			status = inb(info->base + UART_MSR);
-			//MX_UNLOCK(&info->slock);
+			/* MX_UNLOCK(&info->slock); */
 			if (info->tty->hw_stopped) {
 				if (status & UART_MSR_CTS) {
 					info->tty->hw_stopped = 0;
-					if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+					if ((info->type != PORT_16550A) &&
+							(!info->IsMoxaMustChipFlag)) {
 						info->IER |= UART_IER_THRI;
 						outb(info->IER, info->base + UART_IER);
 					}
@@ -2630,7 +2716,8 @@
 			} else {
 				if (!(status & UART_MSR_CTS)) {
 					info->tty->hw_stopped = 1;
-					if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+					if ((info->type != PORT_16550A) &&
+							(!info->IsMoxaMustChipFlag)) {
 						info->IER &= ~UART_IER_THRI;
 						outb(info->IER, info->base + UART_IER);
 					}
@@ -2668,11 +2755,17 @@
 		 * overruns too.  (For real raw support).
 		 */
 		if (I_IGNPAR(info->tty)) {
-			info->ignore_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
-			info->read_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
+			info->ignore_status_mask |=
+						UART_LSR_OE |
+						UART_LSR_PE |
+						UART_LSR_FE;
+			info->read_status_mask |=
+						UART_LSR_OE |
+						UART_LSR_PE |
+						UART_LSR_FE;
 		}
 	}
-	// following add by Victor Yu. 09-02-2002
+	/* following add by Victor Yu. 09-02-2002 */
 	if (info->IsMoxaMustChipFlag) {
 		spin_lock_irqsave(&info->slock, flags);
 		SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty));
@@ -2698,7 +2791,7 @@
 		 */
 		spin_unlock_irqrestore(&info->slock, flags);
 	}
-	// above add by Victor Yu. 09-02-2002
+	/* above add by Victor Yu. 09-02-2002 */
 
 
 	outb(fcr, info->base + UART_FCR);	/* set fcr */
@@ -2729,10 +2822,8 @@
 		quot = (2 * info->baud_base / 269);
 	} else if (newspd) {
 		quot = info->baud_base / newspd;
-
 		if (quot == 0)
 			quot = 1;
-
 	} else {
 		quot = 0;
 	}
@@ -2765,8 +2856,6 @@
 	return ret;
 }
 
-
-
 /*
  * ------------------------------------------------------------
  * friends of mxser_ioctl()
@@ -2777,7 +2866,7 @@
 	struct serial_struct tmp;
 
 	if (!retinfo)
-		return (-EFAULT);
+		return -EFAULT;
 	memset(&tmp, 0, sizeof(tmp));
 	tmp.type = info->type;
 	tmp.line = info->port;
@@ -2791,7 +2880,7 @@
 	tmp.hub6 = 0;
 	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
 		return -EFAULT;
-	return (0);
+	return 0;
 }
 
 static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct __user *new_info)
@@ -2801,29 +2890,37 @@
 	int retval = 0;
 
 	if (!new_info || !info->base)
-		return (-EFAULT);
+		return -EFAULT;
 	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
 		return -EFAULT;
 
-	if ((new_serial.irq != info->irq) || (new_serial.port != info->base) || (new_serial.custom_divisor != info->custom_divisor) || (new_serial.baud_base != info->baud_base))
-		return (-EPERM);
+	if ((new_serial.irq != info->irq) ||
+			(new_serial.port != info->base) ||
+			(new_serial.custom_divisor != info->custom_divisor) ||
+			(new_serial.baud_base != info->baud_base))
+		return -EPERM;
 
 	flags = info->flags & ASYNC_SPD_MASK;
 
 	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.baud_base != info->baud_base) || (new_serial.close_delay != info->close_delay) || ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK)))
-			return (-EPERM);
-		info->flags = ((info->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK));
+		if ((new_serial.baud_base != info->baud_base) ||
+				(new_serial.close_delay != info->close_delay) ||
+				((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+				(new_serial.flags & ASYNC_USR_MASK));
 	} else {
 		/*
 		 * OK, past this point, all the error checking has been done.
 		 * At this point, we start making changes.....
 		 */
-		info->flags = ((info->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS));
+		info->flags = ((info->flags & ~ASYNC_FLAGS) |
+				(new_serial.flags & ASYNC_FLAGS));
 		info->close_delay = new_serial.close_delay * HZ / 100;
 		info->closing_wait = new_serial.closing_wait * HZ / 100;
-		info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-		info->tty->low_latency = 0;	//(info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+		info->tty->low_latency =
+				(info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+		info->tty->low_latency = 0;	/* (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; */
 	}
 
 	/* added by casper, 3/17/2000, for mouse */
@@ -2831,7 +2928,6 @@
 
 	process_txrx_fifo(info);
 
-	/* */
 	if (info->flags & ASYNC_INITIALIZED) {
 		if (flags != (info->flags & ASYNC_SPD_MASK)) {
 			mxser_change_speed(info, NULL);
@@ -2839,7 +2935,7 @@
 	} else {
 		retval = mxser_startup(info);
 	}
-	return (retval);
+	return retval;
 }
 
 /*
@@ -2876,25 +2972,27 @@
 		return;
 	set_current_state(TASK_INTERRUPTIBLE);
 	spin_lock_irqsave(&info->slock, flags);
-	outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
+	outb(inb(info->base + UART_LCR) | UART_LCR_SBC,
+		info->base + UART_LCR);
 	spin_unlock_irqrestore(&info->slock, flags);
 	schedule_timeout(duration);
 	spin_lock_irqsave(&info->slock, flags);
-	outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
+	outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC,
+		info->base + UART_LCR);
 	spin_unlock_irqrestore(&info->slock, flags);
 }
 
 static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned char control, status;
 	unsigned long flags;
 
 
 	if (tty->index == MXSER_PORTS)
-		return (-ENOIOCTLCMD);
+		return -ENOIOCTLCMD;
 	if (tty->flags & (1 << TTY_IO_ERROR))
-		return (-EIO);
+		return -EIO;
 
 	control = info->MCR;
 
@@ -2904,12 +3002,16 @@
 		mxser_check_modem_status(info, status);
 	spin_unlock_irqrestore(&info->slock, flags);
 	return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
-	    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+		    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
+		    ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
+		    ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
+		    ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
+		    ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
 }
 
 static int mxser_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear)
 {
-	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	struct mxser_struct *info = tty->driver_data;
 	unsigned long flags;
 
 
@@ -2968,38 +3070,36 @@
 		hwconf->board_type = MXSER_BOARD_CI104J;
 		hwconf->ports = 4;
 	} else
-		return (0);
+		return 0;
 
 	irq = 0;
 	if (hwconf->ports == 2) {
 		irq = regs[9] & 0xF000;
 		irq = irq | (irq >> 4);
 		if (irq != (regs[9] & 0xFF00))
-			return (MXSER_ERR_IRQ_CONFLIT);
+			return MXSER_ERR_IRQ_CONFLIT;
 	} else if (hwconf->ports == 4) {
 		irq = regs[9] & 0xF000;
 		irq = irq | (irq >> 4);
 		irq = irq | (irq >> 8);
 		if (irq != regs[9])
-			return (MXSER_ERR_IRQ_CONFLIT);
+			return MXSER_ERR_IRQ_CONFLIT;
 	} else if (hwconf->ports == 8) {
 		irq = regs[9] & 0xF000;
 		irq = irq | (irq >> 4);
 		irq = irq | (irq >> 8);
 		if ((irq != regs[9]) || (irq != regs[10]))
-			return (MXSER_ERR_IRQ_CONFLIT);
+			return MXSER_ERR_IRQ_CONFLIT;
 	}
 
-	if (!irq) {
-		return (MXSER_ERR_IRQ);
-	}
-	hwconf->irq = ((int) (irq & 0xF000) >> 12);
+	if (!irq)
+		return MXSER_ERR_IRQ;
+	hwconf->irq = ((int)(irq & 0xF000) >> 12);
 	for (i = 0; i < 8; i++)
 		hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8;
-	if ((regs[12] & 0x80) == 0) {
-		return (MXSER_ERR_VECTOR);
-	}
-	hwconf->vector = (int) regs[11];	/* interrupt vector */
+	if ((regs[12] & 0x80) == 0)
+		return MXSER_ERR_VECTOR;
+	hwconf->vector = (int)regs[11];	/* interrupt vector */
 	if (id == 1)
 		hwconf->vector_mask = 0x00FF;
 	else
@@ -3007,10 +3107,10 @@
 	for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
 		if (regs[12] & bits) {
 			hwconf->baud_base[i] = 921600;
-			hwconf->MaxCanSetBaudRate[i] = 921600;	// add by Victor Yu. 09-04-2002
+			hwconf->MaxCanSetBaudRate[i] = 921600;	/* add by Victor Yu. 09-04-2002 */
 		} else {
 			hwconf->baud_base[i] = 115200;
-			hwconf->MaxCanSetBaudRate[i] = 115200;	// add by Victor Yu. 09-04-2002
+			hwconf->MaxCanSetBaudRate[i] = 115200;	/* add by Victor Yu. 09-04-2002 */
 		}
 	}
 	scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
@@ -3030,7 +3130,7 @@
 		hwconf->ports = 4;
 	request_region(hwconf->ioaddr[0], 8 * hwconf->ports, "mxser(IO)");
 	request_region(hwconf->vector, 1, "mxser(vector)");
-	return (hwconf->ports);
+	return hwconf->ports;
 }
 
 #define CHIP_SK 	0x01	/* Serial Data Clock  in Eprom */
@@ -3053,7 +3153,7 @@
 
 	id = mxser_program_mode(port);
 	if (id < 0)
-		return (id);
+		return id;
 	for (i = 0; i < 14; i++) {
 		k = (i & 0x3F) | 0x180;
 		for (j = 0x100; j > 0; j >>= 1) {
@@ -3066,7 +3166,7 @@
 				outb(CHIP_CS | CHIP_SK, port);	/* A? bit of read */
 			}
 		}
-		(void) inb(port);
+		(void)inb(port);
 		value = 0;
 		for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
 			outb(CHIP_CS, port);
@@ -3078,28 +3178,33 @@
 		outb(0, port);
 	}
 	mxser_normal_mode(port);
-	return (id);
+	return id;
 }
 
 static int mxser_program_mode(int port)
 {
 	int id, i, j, n;
-	//unsigned long flags;
+	/* unsigned long flags; */
 
 	spin_lock(&gm_lock);
 	outb(0, port);
 	outb(0, port);
 	outb(0, port);
-	(void) inb(port);
-	(void) inb(port);
+	(void)inb(port);
+	(void)inb(port);
 	outb(0, port);
-	(void) inb(port);
-	//restore_flags(flags);
+	(void)inb(port);
+	/* restore_flags(flags); */
 	spin_unlock(&gm_lock);
 
 	id = inb(port + 1) & 0x1F;
-	if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != C102_ASIC_ID) && (id != CI132_ASIC_ID) && (id != CI134_ASIC_ID) && (id != CI104J_ASIC_ID))
-		return (-1);
+	if ((id != C168_ASIC_ID) &&
+			(id != C104_ASIC_ID) &&
+			(id != C102_ASIC_ID) &&
+			(id != CI132_ASIC_ID) &&
+			(id != CI134_ASIC_ID) &&
+			(id != CI104J_ASIC_ID))
+		return -1;
 	for (i = 0, j = 0; i < 4; i++) {
 		n = inb(port + 2);
 		if (n == 'M') {
@@ -3112,7 +3217,7 @@
 	}
 	if (j != 2)
 		id = -2;
-	return (id);
+	return id;
 }
 
 static void mxser_normal_mode(int port)
@@ -3130,7 +3235,7 @@
 		if ((n & 0x61) == 0x60)
 			break;
 		if ((n & 1) == 1)
-			(void) inb(port);
+			(void)inb(port);
 	}
 	outb(0x00, port + 4);
 }
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index c48de09..203dc2b 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -951,7 +951,8 @@
    {
 queue_the_message:
 
-      pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
+      pMsg = kmalloc(sizeof(struct r3964_message),
+		     error_code?GFP_ATOMIC:GFP_KERNEL);
       TRACE_M("add_msg - kmalloc %p",pMsg);
       if(pMsg==NULL) {
          return;
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index b9371d5..603b9ad 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1132,7 +1132,7 @@
  *	buffer, and once to drain the space from the (physical) beginning of
  *	the buffer to head pointer.
  *
- *	Called under the tty->atomic_read_lock sem and with TTY_DONT_FLIP set
+ *	Called under the tty->atomic_read_lock sem
  *
  */
  
@@ -1271,7 +1271,6 @@
 	}
 
 	add_wait_queue(&tty->read_wait, &wait);
-	set_bit(TTY_DONT_FLIP, &tty->flags);
 	while (nr) {
 		/* First test for status change. */
 		if (tty->packet && tty->link->ctrl_status) {
@@ -1315,9 +1314,7 @@
 				break;
 			}
 			n_tty_set_room(tty);
-			clear_bit(TTY_DONT_FLIP, &tty->flags);
 			timeout = schedule_timeout(timeout);
-			set_bit(TTY_DONT_FLIP, &tty->flags);
 			continue;
 		}
 		__set_current_state(TASK_RUNNING);
@@ -1394,7 +1391,6 @@
 		if (time)
 			timeout = time;
 	}
-	clear_bit(TTY_DONT_FLIP, &tty->flags);
 	mutex_unlock(&tty->atomic_read_lock);
 	remove_wait_queue(&tty->read_wait, &wait);
 
diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c
new file mode 100644
index 0000000..5b91e4e
--- /dev/null
+++ b/drivers/char/nsc_gpio.c
@@ -0,0 +1,142 @@
+/* linux/drivers/char/nsc_gpio.c
+
+   National Semiconductor common GPIO device-file/VFS methods.
+   Allows a user space process to control the GPIO pins.
+
+   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
+   Copyright (c) 2005      Jim Cromie <jim.cromie@gmail.com>
+*/
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/nsc_gpio.h>
+#include <linux/platform_device.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#define NAME "nsc_gpio"
+
+void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index)
+{
+	/* retrieve current config w/o changing it */
+	u32 config = amp->gpio_config(index, ~0, 0);
+
+	/* user requested via 'v' command, so its INFO */
+	dev_info(amp->dev, "io%02u: 0x%04x %s %s %s %s %s %s %s\tio:%d/%d\n",
+		 index, config,
+		 (config & 1) ? "OE" : "TS",      /* output-enabled/tristate */
+		 (config & 2) ? "PP" : "OD",      /* push pull / open drain */
+		 (config & 4) ? "PUE" : "PUD",    /* pull up enabled/disabled */
+		 (config & 8) ? "LOCKED" : "",    /* locked / unlocked */
+		 (config & 16) ? "LEVEL" : "EDGE",/* level/edge input */
+		 (config & 32) ? "HI" : "LO",     /* trigger on rise/fall edge */
+		 (config & 64) ? "DEBOUNCE" : "", /* debounce */
+
+		 amp->gpio_get(index), amp->gpio_current(index));
+}
+
+ssize_t nsc_gpio_write(struct file *file, const char __user *data,
+		       size_t len, loff_t *ppos)
+{
+	unsigned m = iminor(file->f_dentry->d_inode);
+	struct nsc_gpio_ops *amp = file->private_data;
+	struct device *dev = amp->dev;
+	size_t i;
+	int err = 0;
+
+	for (i = 0; i < len; ++i) {
+		char c;
+		if (get_user(c, data + i))
+			return -EFAULT;
+		switch (c) {
+		case '0':
+			amp->gpio_set(m, 0);
+			break;
+		case '1':
+			amp->gpio_set(m, 1);
+			break;
+		case 'O':
+			dev_dbg(dev, "GPIO%d output enabled\n", m);
+			amp->gpio_config(m, ~1, 1);
+			break;
+		case 'o':
+			dev_dbg(dev, "GPIO%d output disabled\n", m);
+			amp->gpio_config(m, ~1, 0);
+			break;
+		case 'T':
+			dev_dbg(dev, "GPIO%d output is push pull\n",
+			       m);
+			amp->gpio_config(m, ~2, 2);
+			break;
+		case 't':
+			dev_dbg(dev, "GPIO%d output is open drain\n",
+			       m);
+			amp->gpio_config(m, ~2, 0);
+			break;
+		case 'P':
+			dev_dbg(dev, "GPIO%d pull up enabled\n", m);
+			amp->gpio_config(m, ~4, 4);
+			break;
+		case 'p':
+			dev_dbg(dev, "GPIO%d pull up disabled\n", m);
+			amp->gpio_config(m, ~4, 0);
+			break;
+		case 'v':
+			/* View Current pin settings */
+			amp->gpio_dump(amp, m);
+			break;
+		case '\n':
+			/* end of settings string, do nothing */
+			break;
+		default:
+			dev_err(dev, "io%2d bad setting: chr<0x%2x>\n",
+				m, (int)c);
+			err++;
+		}
+	}
+	if (err)
+		return -EINVAL;	/* full string handled, report error */
+
+	return len;
+}
+
+ssize_t nsc_gpio_read(struct file *file, char __user * buf,
+		      size_t len, loff_t * ppos)
+{
+	unsigned m = iminor(file->f_dentry->d_inode);
+	int value;
+	struct nsc_gpio_ops *amp = file->private_data;
+
+	value = amp->gpio_get(m);
+	if (put_user(value ? '1' : '0', buf))
+		return -EFAULT;
+
+	return 1;
+}
+
+/* common file-ops routines for both scx200_gpio and pc87360_gpio */
+EXPORT_SYMBOL(nsc_gpio_write);
+EXPORT_SYMBOL(nsc_gpio_read);
+EXPORT_SYMBOL(nsc_gpio_dump);
+
+static int __init nsc_gpio_init(void)
+{
+	printk(KERN_DEBUG NAME " initializing\n");
+	return 0;
+}
+
+static void __exit nsc_gpio_cleanup(void)
+{
+	printk(KERN_DEBUG NAME " cleanup\n");
+}
+
+module_init(nsc_gpio_init);
+module_exit(nsc_gpio_cleanup);
+
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
+MODULE_DESCRIPTION("NatSemi GPIO Common Methods");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
new file mode 100644
index 0000000..1c706cc
--- /dev/null
+++ b/drivers/char/pc8736x_gpio.c
@@ -0,0 +1,340 @@
+/* linux/drivers/char/pc8736x_gpio.c
+
+   National Semiconductor PC8736x GPIO driver.  Allows a user space
+   process to play with the GPIO pins.
+
+   Copyright (c) 2005 Jim Cromie <jim.cromie@gmail.com>
+
+   adapted from linux/drivers/char/scx200_gpio.c
+   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>,
+*/
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/mutex.h>
+#include <linux/nsc_gpio.h>
+#include <linux/platform_device.h>
+#include <asm/uaccess.h>
+
+#define DEVNAME "pc8736x_gpio"
+
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
+MODULE_DESCRIPTION("NatSemi PC-8736x GPIO Pin Driver");
+MODULE_LICENSE("GPL");
+
+static int major;		/* default to dynamic major */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+static DEFINE_MUTEX(pc8736x_gpio_config_lock);
+static unsigned pc8736x_gpio_base;
+static u8 pc8736x_gpio_shadow[4];
+
+#define SIO_BASE1       0x2E	/* 1st command-reg to check */
+#define SIO_BASE2       0x4E	/* alt command-reg to check */
+#define SIO_BASE_OFFSET 0x20
+
+#define SIO_SID		0x20	/* SuperI/O ID Register */
+#define SIO_SID_VALUE	0xe9	/* Expected value in SuperI/O ID Register */
+
+#define SIO_CF1		0x21	/* chip config, bit0 is chip enable */
+
+#define PC8736X_GPIO_SIZE	16
+
+#define SIO_UNIT_SEL	0x7	/* unit select reg */
+#define SIO_UNIT_ACT	0x30	/* unit enable */
+#define SIO_GPIO_UNIT	0x7	/* unit number of GPIO */
+#define SIO_VLM_UNIT	0x0D
+#define SIO_TMS_UNIT	0x0E
+
+/* config-space addrs to read/write each unit's runtime addr */
+#define SIO_BASE_HADDR		0x60
+#define SIO_BASE_LADDR		0x61
+
+/* GPIO config-space pin-control addresses */
+#define SIO_GPIO_PIN_SELECT	0xF0
+#define SIO_GPIO_PIN_CONFIG     0xF1
+#define SIO_GPIO_PIN_EVENT      0xF2
+
+static unsigned char superio_cmd = 0;
+static unsigned char selected_device = 0xFF;	/* bogus start val */
+
+/* GPIO port runtime access, functionality */
+static int port_offset[] = { 0, 4, 8, 10 };	/* non-uniform offsets ! */
+/* static int event_capable[] = { 1, 1, 0, 0 };   ports 2,3 are hobbled */
+
+#define PORT_OUT	0
+#define PORT_IN		1
+#define PORT_EVT_EN	2
+#define PORT_EVT_STST	3
+
+static struct platform_device *pdev;  /* use in dev_*() */
+
+static inline void superio_outb(int addr, int val)
+{
+	outb_p(addr, superio_cmd);
+	outb_p(val, superio_cmd + 1);
+}
+
+static inline int superio_inb(int addr)
+{
+	outb_p(addr, superio_cmd);
+	return inb_p(superio_cmd + 1);
+}
+
+static int pc8736x_superio_present(void)
+{
+	/* try the 2 possible values, read a hardware reg to verify */
+	superio_cmd = SIO_BASE1;
+	if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+		return superio_cmd;
+
+	superio_cmd = SIO_BASE2;
+	if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+		return superio_cmd;
+
+	return 0;
+}
+
+static void device_select(unsigned devldn)
+{
+	superio_outb(SIO_UNIT_SEL, devldn);
+	selected_device = devldn;
+}
+
+static void select_pin(unsigned iminor)
+{
+	/* select GPIO port/pin from device minor number */
+	device_select(SIO_GPIO_UNIT);
+	superio_outb(SIO_GPIO_PIN_SELECT,
+		     ((iminor << 1) & 0xF0) | (iminor & 0x7));
+}
+
+static inline u32 pc8736x_gpio_configure_fn(unsigned index, u32 mask, u32 bits,
+					    u32 func_slct)
+{
+	u32 config, new_config;
+
+	mutex_lock(&pc8736x_gpio_config_lock);
+
+	device_select(SIO_GPIO_UNIT);
+	select_pin(index);
+
+	/* read current config value */
+	config = superio_inb(func_slct);
+
+	/* set new config */
+	new_config = (config & mask) | bits;
+	superio_outb(func_slct, new_config);
+
+	mutex_unlock(&pc8736x_gpio_config_lock);
+
+	return config;
+}
+
+static u32 pc8736x_gpio_configure(unsigned index, u32 mask, u32 bits)
+{
+	return pc8736x_gpio_configure_fn(index, mask, bits,
+					 SIO_GPIO_PIN_CONFIG);
+}
+
+static int pc8736x_gpio_get(unsigned minor)
+{
+	int port, bit, val;
+
+	port = minor >> 3;
+	bit = minor & 7;
+	val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN);
+	val >>= bit;
+	val &= 1;
+
+	dev_dbg(&pdev->dev, "_gpio_get(%d from %x bit %d) == val %d\n",
+		minor, pc8736x_gpio_base + port_offset[port] + PORT_IN, bit,
+		val);
+
+	return val;
+}
+
+static void pc8736x_gpio_set(unsigned minor, int val)
+{
+	int port, bit, curval;
+
+	minor &= 0x1f;
+	port = minor >> 3;
+	bit = minor & 7;
+	curval = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_OUT);
+
+	dev_dbg(&pdev->dev, "addr:%x cur:%x bit-pos:%d cur-bit:%x + new:%d -> bit-new:%d\n",
+		pc8736x_gpio_base + port_offset[port] + PORT_OUT,
+		curval, bit, (curval & ~(1 << bit)), val, (val << bit));
+
+	val = (curval & ~(1 << bit)) | (val << bit);
+
+	dev_dbg(&pdev->dev, "gpio_set(minor:%d port:%d bit:%d)"
+		" %2x -> %2x\n", minor, port, bit, curval, val);
+
+	outb_p(val, pc8736x_gpio_base + port_offset[port] + PORT_OUT);
+
+	curval = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_OUT);
+	val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN);
+
+	dev_dbg(&pdev->dev, "wrote %x, read: %x\n", curval, val);
+	pc8736x_gpio_shadow[port] = val;
+}
+
+static void pc8736x_gpio_set_high(unsigned index)
+{
+	pc8736x_gpio_set(index, 1);
+}
+
+static void pc8736x_gpio_set_low(unsigned index)
+{
+	pc8736x_gpio_set(index, 0);
+}
+
+static int pc8736x_gpio_current(unsigned minor)
+{
+	int port, bit;
+	minor &= 0x1f;
+	port = minor >> 3;
+	bit = minor & 7;
+	return ((pc8736x_gpio_shadow[port] >> bit) & 0x01);
+}
+
+static void pc8736x_gpio_change(unsigned index)
+{
+	pc8736x_gpio_set(index, !pc8736x_gpio_current(index));
+}
+
+static struct nsc_gpio_ops pc8736x_access = {
+	.owner		= THIS_MODULE,
+	.gpio_config	= pc8736x_gpio_configure,
+	.gpio_dump	= nsc_gpio_dump,
+	.gpio_get	= pc8736x_gpio_get,
+	.gpio_set	= pc8736x_gpio_set,
+	.gpio_set_high	= pc8736x_gpio_set_high,
+	.gpio_set_low	= pc8736x_gpio_set_low,
+	.gpio_change	= pc8736x_gpio_change,
+	.gpio_current	= pc8736x_gpio_current
+};
+
+static int pc8736x_gpio_open(struct inode *inode, struct file *file)
+{
+	unsigned m = iminor(inode);
+	file->private_data = &pc8736x_access;
+
+	dev_dbg(&pdev->dev, "open %d\n", m);
+
+	if (m > 63)
+		return -EINVAL;
+	return nonseekable_open(inode, file);
+}
+
+static struct file_operations pc8736x_gpio_fops = {
+	.owner	= THIS_MODULE,
+	.open	= pc8736x_gpio_open,
+	.write	= nsc_gpio_write,
+	.read	= nsc_gpio_read,
+};
+
+static void __init pc8736x_init_shadow(void)
+{
+	int port;
+
+	/* read the current values driven on the GPIO signals */
+	for (port = 0; port < 4; ++port)
+		pc8736x_gpio_shadow[port]
+		    = inb_p(pc8736x_gpio_base + port_offset[port]
+			    + PORT_OUT);
+
+}
+
+static int __init pc8736x_gpio_init(void)
+{
+	int rc = 0;
+
+	pdev = platform_device_alloc(DEVNAME, 0);
+	if (!pdev)
+		return -ENOMEM;
+
+	rc = platform_device_add(pdev);
+	if (rc) {
+		rc = -ENODEV;
+		goto undo_platform_dev_alloc;
+	}
+	dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n");
+
+	if (!pc8736x_superio_present()) {
+		rc = -ENODEV;
+		dev_err(&pdev->dev, "no device found\n");
+		goto undo_platform_dev_add;
+	}
+	pc8736x_access.dev = &pdev->dev;
+
+	/* Verify that chip and it's GPIO unit are both enabled.
+	   My BIOS does this, so I take minimum action here
+	 */
+	rc = superio_inb(SIO_CF1);
+	if (!(rc & 0x01)) {
+		rc = -ENODEV;
+		dev_err(&pdev->dev, "device not enabled\n");
+		goto undo_platform_dev_add;
+	}
+	device_select(SIO_GPIO_UNIT);
+	if (!superio_inb(SIO_UNIT_ACT)) {
+		rc = -ENODEV;
+		dev_err(&pdev->dev, "GPIO unit not enabled\n");
+		goto undo_platform_dev_add;
+	}
+
+	/* read the GPIO unit base addr that chip responds to */
+	pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8
+			     | superio_inb(SIO_BASE_LADDR));
+
+	if (!request_region(pc8736x_gpio_base, 16, DEVNAME)) {
+		rc = -ENODEV;
+		dev_err(&pdev->dev, "GPIO ioport %x busy\n",
+			pc8736x_gpio_base);
+		goto undo_platform_dev_add;
+	}
+	dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base);
+
+	rc = register_chrdev(major, DEVNAME, &pc8736x_gpio_fops);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc);
+		goto undo_platform_dev_add;
+	}
+	if (!major) {
+		major = rc;
+		dev_dbg(&pdev->dev, "got dynamic major %d\n", major);
+	}
+
+	pc8736x_init_shadow();
+	return 0;
+
+undo_platform_dev_add:
+	platform_device_put(pdev);
+undo_platform_dev_alloc:
+	kfree(pdev);
+	return rc;
+}
+
+static void __exit pc8736x_gpio_cleanup(void)
+{
+	dev_dbg(&pdev->dev, " cleanup\n");
+
+	release_region(pc8736x_gpio_base, 16);
+
+	unregister_chrdev(major, DEVNAME);
+}
+
+EXPORT_SYMBOL(pc8736x_access);
+
+module_init(pc8736x_gpio_init);
+module_exit(pc8736x_gpio_cleanup);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 0721345..17bc8ab 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -844,7 +844,7 @@
 	return rc;
 }
 
-void bh_handler(void* Context)
+static void bh_handler(void* Context)
 {
 	MGSLPC_INFO *info = (MGSLPC_INFO*)Context;
 	int action;
@@ -888,7 +888,7 @@
 			__FILE__,__LINE__,info->device_name);
 }
 
-void bh_transmit(MGSLPC_INFO *info)
+static void bh_transmit(MGSLPC_INFO *info)
 {
 	struct tty_struct *tty = info->tty;
 	if (debug_level >= DEBUG_LEVEL_BH)
@@ -900,7 +900,7 @@
 	}
 }
 
-void bh_status(MGSLPC_INFO *info)
+static void bh_status(MGSLPC_INFO *info)
 {
 	info->ri_chkcount = 0;
 	info->dsr_chkcount = 0;
@@ -1582,7 +1582,7 @@
 	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char"))
 		return;
 
-	if (!tty || !info->tx_buf)
+	if (!info->tx_buf)
 		return;
 
 	spin_lock_irqsave(&info->lock,flags);
@@ -1649,7 +1649,7 @@
 			__FILE__,__LINE__,info->device_name,count);
 	
 	if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write") ||
-	    !tty || !info->tx_buf)
+		!info->tx_buf)
 		goto cleanup;
 
 	if (info->params.mode == MGSL_MODE_HDLC) {
@@ -2305,7 +2305,7 @@
 	return ioctl_common(info, cmd, arg);
 }
 
-int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
+static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg)
 {
 	int error;
 	struct mgsl_icount cnow;	/* kernel counter temps */
@@ -2877,7 +2877,7 @@
 	return ((count < begin+len-off) ? count : begin+len-off);
 }
 
-int rx_alloc_buffers(MGSLPC_INFO *info)
+static int rx_alloc_buffers(MGSLPC_INFO *info)
 {
 	/* each buffer has header and data */
 	info->rx_buf_size = sizeof(RXBUF) + info->max_frame_size;
@@ -2900,13 +2900,13 @@
 	return 0;
 }
 
-void rx_free_buffers(MGSLPC_INFO *info)
+static void rx_free_buffers(MGSLPC_INFO *info)
 {
 	kfree(info->rx_buf);
 	info->rx_buf = NULL;
 }
 
-int claim_resources(MGSLPC_INFO *info)
+static int claim_resources(MGSLPC_INFO *info)
 {
 	if (rx_alloc_buffers(info) < 0 ) {
 		printk( "Cant allocate rx buffer %s\n", info->device_name);
@@ -2916,7 +2916,7 @@
 	return 0;
 }
 
-void release_resources(MGSLPC_INFO *info)
+static void release_resources(MGSLPC_INFO *info)
 {
 	if (debug_level >= DEBUG_LEVEL_INFO)
 		printk("release_resources(%s)\n", info->device_name);
@@ -2928,7 +2928,7 @@
  * 	
  * Arguments:		info	pointer to device instance data
  */
-void mgslpc_add_device(MGSLPC_INFO *info)
+static void mgslpc_add_device(MGSLPC_INFO *info)
 {
 	info->next_device = NULL;
 	info->line = mgslpc_device_count;
@@ -2964,7 +2964,7 @@
 #endif
 }
 
-void mgslpc_remove_device(MGSLPC_INFO *remove_info)
+static void mgslpc_remove_device(MGSLPC_INFO *remove_info)
 {
 	MGSLPC_INFO *info = mgslpc_device_list;
 	MGSLPC_INFO *last = NULL;
@@ -3257,7 +3257,7 @@
 	write_reg(info, CHA + MODE, val);
 }
 
-void hdlc_mode(MGSLPC_INFO *info)
+static void hdlc_mode(MGSLPC_INFO *info)
 {
 	unsigned char val;
 	unsigned char clkmode, clksubmode;
@@ -3497,7 +3497,7 @@
 	rx_stop(info);
 }
 
-void rx_stop(MGSLPC_INFO *info)
+static void rx_stop(MGSLPC_INFO *info)
 {
 	if (debug_level >= DEBUG_LEVEL_ISR)
 		printk("%s(%d):rx_stop(%s)\n",
@@ -3510,7 +3510,7 @@
 	info->rx_overflow = 0;
 }
 
-void rx_start(MGSLPC_INFO *info)
+static void rx_start(MGSLPC_INFO *info)
 {
 	if (debug_level >= DEBUG_LEVEL_ISR)
 		printk("%s(%d):rx_start(%s)\n",
@@ -3526,7 +3526,7 @@
 	info->rx_enabled = 1;
 }
 
-void tx_start(MGSLPC_INFO *info)
+static void tx_start(MGSLPC_INFO *info)
 {
 	if (debug_level >= DEBUG_LEVEL_ISR)
 		printk("%s(%d):tx_start(%s)\n",
@@ -3564,7 +3564,7 @@
 		info->tx_enabled = 1;
 }
 
-void tx_stop(MGSLPC_INFO *info)
+static void tx_stop(MGSLPC_INFO *info)
 {
 	if (debug_level >= DEBUG_LEVEL_ISR)
 		printk("%s(%d):tx_stop(%s)\n",
@@ -3578,7 +3578,7 @@
 
 /* Reset the adapter to a known state and prepare it for further use.
  */
-void reset_device(MGSLPC_INFO *info)
+static void reset_device(MGSLPC_INFO *info)
 {
 	/* power up both channels (set BIT7) */ 
 	write_reg(info, CHA + CCR0, 0x80);
@@ -3628,7 +3628,7 @@
 	write_reg(info, IPC, 0x05);
 }
 
-void async_mode(MGSLPC_INFO *info)
+static void async_mode(MGSLPC_INFO *info)
 {
 	unsigned char val;
 
@@ -3799,7 +3799,7 @@
 
 /* Set the HDLC idle mode for the transmitter.
  */
-void tx_set_idle(MGSLPC_INFO *info)
+static void tx_set_idle(MGSLPC_INFO *info)
 {
 	/* Note: ESCC2 only supports flags and one idle modes */ 
 	if (info->idle_mode == HDLC_TXIDLE_FLAGS)
@@ -3810,7 +3810,7 @@
 
 /* get state of the V24 status (input) signals.
  */
-void get_signals(MGSLPC_INFO *info)
+static void get_signals(MGSLPC_INFO *info)
 {
 	unsigned char status = 0;
 	
@@ -3832,7 +3832,7 @@
 /* Set the state of DTR and RTS based on contents of
  * serial_signals member of device extension.
  */
-void set_signals(MGSLPC_INFO *info)
+static void set_signals(MGSLPC_INFO *info)
 {
 	unsigned char val;
 
@@ -3856,7 +3856,7 @@
 		set_reg_bits(info, CHA + PVR, PVR_DTR);
 }
 
-void rx_reset_buffers(MGSLPC_INFO *info)
+static void rx_reset_buffers(MGSLPC_INFO *info)
 {
 	RXBUF *buf;
 	int i;
@@ -3875,7 +3875,7 @@
  *
  * Returns 1 if frame returned, otherwise 0
  */
-int rx_get_frame(MGSLPC_INFO *info)
+static int rx_get_frame(MGSLPC_INFO *info)
 {
 	unsigned short status;
 	RXBUF *buf;
@@ -3961,7 +3961,7 @@
 	return 1;
 }
 
-BOOLEAN register_test(MGSLPC_INFO *info)
+static BOOLEAN register_test(MGSLPC_INFO *info)
 {
 	static unsigned char patterns[] = 
 	    { 0x00, 0xff, 0xaa, 0x55, 0x69, 0x96, 0x0f };
@@ -3987,7 +3987,7 @@
 	return rc;
 }
 
-BOOLEAN irq_test(MGSLPC_INFO *info)
+static BOOLEAN irq_test(MGSLPC_INFO *info)
 {
 	unsigned long end_time;
 	unsigned long flags;
@@ -4022,7 +4022,7 @@
 	return info->irq_occurred ? TRUE : FALSE;
 }
 
-int adapter_test(MGSLPC_INFO *info)
+static int adapter_test(MGSLPC_INFO *info)
 {
 	if (!register_test(info)) {
 		info->init_error = DiagStatus_AddressFailure;
@@ -4044,7 +4044,7 @@
 	return 0;
 }
 
-void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit)
+static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit)
 {
 	int i;
 	int linecount;
@@ -4079,7 +4079,7 @@
 /* HDLC frame time out
  * update stats and do tx completion processing
  */
-void tx_timeout(unsigned long context)
+static void tx_timeout(unsigned long context)
 {
 	MGSLPC_INFO *info = (MGSLPC_INFO*)context;
 	unsigned long flags;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 9b5a2c0..0c17f61 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -101,7 +101,7 @@
  *
  * FIXME: Our pty_write method is called with our ldisc lock held but
  * not our partners. We can't just take the other one blindly without
- * risking deadlocks.  There is also the small matter of TTY_DONT_FLIP
+ * risking deadlocks.
  */
 static int pty_write(struct tty_struct * tty, const unsigned char *buf, int count)
 {
diff --git a/drivers/char/rio/daemon.h b/drivers/char/rio/daemon.h
index 5818a8a..6e63f8b 100644
--- a/drivers/char/rio/daemon.h
+++ b/drivers/char/rio/daemon.h
@@ -51,7 +51,7 @@
 };
 
 struct DownLoad {
-	char *DataP;
+	char __user *DataP;
 	unsigned int Count;
 	unsigned int ProductCode;
 };
@@ -83,18 +83,18 @@
 struct LpbReq {
 	unsigned int Host;
 	unsigned int Link;
-	struct LPB *LpbP;
+	struct LPB __user *LpbP;
 };
 
 struct RupReq {
 	unsigned int HostNum;
 	unsigned int RupNum;
-	struct RUP *RupP;
+	struct RUP __user *RupP;
 };
 
 struct PortReq {
 	unsigned int SysPort;
-	struct Port *PortP;
+	struct Port __user *PortP;
 };
 
 struct StreamInfo {
@@ -105,12 +105,12 @@
 
 struct HostReq {
 	unsigned int HostNum;
-	struct Host *HostP;
+	struct Host __user *HostP;
 };
 
 struct HostDpRam {
 	unsigned int HostNum;
-	struct DpRam *DpRamP;
+	struct DpRam __user *DpRamP;
 };
 
 struct DebugCtrl {
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index e64fe99..6b03918 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -46,7 +46,7 @@
 int RIOBootCodeHOST(struct rio_info *, struct DownLoad *);
 int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
 void msec_timeout(struct Host *);
-int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT *);
+int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
 int RIOBootOk(struct rio_info *, struct Host *, unsigned long);
 int RIORtaBound(struct rio_info *, unsigned int);
 void rio_fill_host_slot(int, int, unsigned int, struct Host *);
@@ -55,8 +55,8 @@
 int RIOFoadRta(struct Host *, struct Map *);
 int RIOZombieRta(struct Host *, struct Map *);
 int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *));
-int RIOIdentifyRta(struct rio_info *, void *);
-int RIOKillNeighbour(struct rio_info *, void *);
+int RIOIdentifyRta(struct rio_info *, void __user *);
+int RIOKillNeighbour(struct rio_info *, void __user *);
 int RIOSuspendBootRta(struct Host *, int, int);
 int RIOFoadWakeup(struct rio_info *);
 struct CmdBlk *RIOGetCmdBlk(void);
@@ -68,7 +68,8 @@
 int RIOUnUse(unsigned long, struct CmdBlk *);
 
 /* rioctrl.c */
-int riocontrol(struct rio_info *, dev_t, int, caddr_t, int);
+int riocontrol(struct rio_info *, dev_t, int, unsigned long, int);
+
 int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char);
 
 /* rioinit.c */
@@ -77,13 +78,13 @@
 void RIOISAinit(struct rio_info *, int);
 int RIODoAT(struct rio_info *, int, int);
 caddr_t RIOCheckForATCard(int);
-int RIOAssignAT(struct rio_info *, int, caddr_t, int);
-int RIOBoardTest(unsigned long, caddr_t, unsigned char, int);
+int RIOAssignAT(struct rio_info *, int, void __iomem *, int);
+int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int);
 void RIOAllocDataStructs(struct rio_info *);
 void RIOSetupDataStructs(struct rio_info *);
 int RIODefaultName(struct rio_info *, struct Host *, unsigned int);
 struct rioVersion *RIOVersid(void);
-void RIOHostReset(unsigned int, struct DpRam *, unsigned int);
+void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int);
 
 /* riointr.c */
 void RIOTxEnable(char *);
@@ -95,14 +96,14 @@
 int RIODelay(struct Port *PortP, int);
 int RIODelay_ni(struct Port *PortP, int);
 void ms_timeout(struct Port *);
-int can_add_transmit(struct PKT **, struct Port *);
+int can_add_transmit(struct PKT __iomem **, struct Port *);
 void add_transmit(struct Port *);
-void put_free_end(struct Host *, struct PKT *);
-int can_remove_receive(struct PKT **, struct Port *);
+void put_free_end(struct Host *, struct PKT __iomem *);
+int can_remove_receive(struct PKT __iomem **, struct Port *);
 void remove_receive(struct Port *);
 
 /* rioroute.c */
-int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT *);
+int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
 void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int);
 unsigned int GetUnitType(unsigned int);
 int RIOSetChange(struct rio_info *);
@@ -139,7 +140,7 @@
 struct rio_info *rio_info_store(int cmd, struct rio_info *p);
 #endif
 
-extern void rio_copy_to_card(void *to, void *from, int len);
+extern void rio_copy_to_card(void *from, void __iomem *to, int len);
 extern int rio_minor(struct tty_struct *tty);
 extern int rio_ismodem(struct tty_struct *tty);
 
diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h
index 179cdbe..ee2ddea 100644
--- a/drivers/char/rio/host.h
+++ b/drivers/char/rio/host.h
@@ -48,8 +48,8 @@
 	unsigned char Ivec;		/* POLLED or ivec number */
 	unsigned char Mode;		/* Control stuff */
 	unsigned char Slot;		/* Slot */
-	caddr_t Caddr;			/* KV address of DPRAM */
-	struct DpRam *CardP;		/* KV address of DPRAM, with overlay */
+	void  __iomem *Caddr;		/* KV address of DPRAM */
+	struct DpRam __iomem *CardP;	/* KV address of DPRAM, with overlay */
 	unsigned long PaddrP;		/* Phys. address of DPRAM */
 	char Name[MAX_NAME_LEN];	/* The name of the host */
 	unsigned int UniqueNum;		/* host unique number */
@@ -57,7 +57,7 @@
 	unsigned int WorkToBeDone;	/* set to true each interrupt */
 	unsigned int InIntr;		/* Being serviced? */
 	unsigned int IntSrvDone;	/* host's interrupt has been serviced */
-	void (*Copy) (void *, void *, int);	/* copy func */
+	void (*Copy) (void *, void __iomem *, int);	/* copy func */
 	struct timer_list timer;
 	/*
 	 **               I M P O R T A N T !
@@ -83,11 +83,11 @@
 
 	struct Top Topology[LINKS_PER_UNIT];	/* one per link */
 	struct Map Mapping[MAX_RUP];		/* Mappings for host */
-	struct PHB *PhbP;			/* Pointer to the PHB array */
-	unsigned short *PhbNumP;		/* Ptr to Number of PHB's */
-	struct LPB *LinkStrP;			/* Link Structure Array */
-	struct RUP *RupP;			/* Sixteen real rups here */
-	struct PARM_MAP *ParmMapP;		/* points to the parmmap */
+	struct PHB __iomem *PhbP;		/* Pointer to the PHB array */
+	unsigned short __iomem *PhbNumP;	/* Ptr to Number of PHB's */
+	struct LPB __iomem *LinkStrP;		/* Link Structure Array */
+	struct RUP __iomem *RupP;		/* Sixteen real rups here */
+	struct PARM_MAP __iomem *ParmMapP;	/* points to the parmmap */
 	unsigned int ExtraUnits[MAX_EXTRA_UNITS];	/* unknown things */
 	unsigned int NumExtraBooted;		/* how many of the above */
 	/*
diff --git a/drivers/char/rio/port.h b/drivers/char/rio/port.h
index 9b5fa3e..49cf6d1 100644
--- a/drivers/char/rio/port.h
+++ b/drivers/char/rio/port.h
@@ -40,7 +40,7 @@
 	struct gs_port gs;
 	int PortNum;			/* RIO port no., 0-511 */
 	struct Host *HostP;
-	caddr_t Caddr;
+	void __iomem *Caddr;
 	unsigned short HostPort;	/* Port number on host card */
 	unsigned char RupNum;		/* Number of RUP for port */
 	unsigned char ID2;		/* Second ID of RTA for port */
@@ -92,13 +92,13 @@
 #define RIO_RTSFLOW	0x0400		/* RIO's own RTSFLOW flag */
 
 
-	struct PHB *PhbP;		/* pointer to PHB for port */
-	u16 *TxAdd;			/* Add packets here */
-	u16 *TxStart;			/* Start of add array */
-	u16 *TxEnd;			/* End of add array */
-	u16 *RxRemove;			/* Remove packets here */
-	u16 *RxStart;			/* Start of remove array */
-	u16 *RxEnd;			/* End of remove array */
+	struct PHB __iomem *PhbP;	/* pointer to PHB for port */
+	u16 __iomem *TxAdd;		/* Add packets here */
+	u16 __iomem *TxStart;		/* Start of add array */
+	u16 __iomem *TxEnd;		/* End of add array */
+	u16 __iomem *RxRemove;		/* Remove packets here */
+	u16 __iomem *RxStart;		/* Start of remove array */
+	u16 __iomem *RxEnd;		/* End of remove array */
 	unsigned int RtaUniqueNum;	/* Unique number of RTA */
 	unsigned short PortState;	/* status of port */
 	unsigned short ModemState;	/* status of modem lines */
diff --git a/drivers/char/rio/rio.h b/drivers/char/rio/rio.h
index b4c9187..1bf3622 100644
--- a/drivers/char/rio/rio.h
+++ b/drivers/char/rio/rio.h
@@ -129,8 +129,8 @@
 **	RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and
 **	returns the offset into the DP RAM area.
 */
-#define	RIO_PTR(C,O) (((unsigned char *)(C))+(0xFFFF&(O)))
-#define	RIO_OFF(C,O) ((long)(O)-(long)(C))
+#define	RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O)))
+#define	RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C))
 
 /*
 **	How to convert from various different device number formats:
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 78dd856..aa43436 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -333,9 +333,9 @@
 	return !RIO_FAIL;
 }
 
-void rio_copy_to_card(void *to, void *from, int len)
+void rio_copy_to_card(void *from, void __iomem *to, int len)
 {
-	rio_memcpy_toio(NULL, to, from, len);
+	rio_copy_toio(to, from, len);
 }
 
 int rio_minor(struct tty_struct *tty)
@@ -573,7 +573,7 @@
 	func_enter();
 
 	/* The "dev" argument isn't used. */
-	rc = riocontrol(p, 0, cmd, (void *) arg, capable(CAP_SYS_ADMIN));
+	rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
 
 	func_exit();
 	return rc;
@@ -583,6 +583,7 @@
 
 static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
 {
+	void __user *argp = (void __user *)arg;
 	int rc;
 	struct Port *PortP;
 	int ival;
@@ -594,14 +595,14 @@
 	rc = 0;
 	switch (cmd) {
 	case TIOCSSOFTCAR:
-		if ((rc = get_user(ival, (unsigned int *) arg)) == 0) {
+		if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) {
 			tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
 		}
 		break;
 	case TIOCGSERIAL:
 		rc = -EFAULT;
-		if (access_ok(VERIFY_WRITE, (void *) arg, sizeof(struct serial_struct)))
-			rc = gs_getserial(&PortP->gs, (struct serial_struct *) arg);
+		if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct)))
+			rc = gs_getserial(&PortP->gs, argp);
 		break;
 	case TCSBRK:
 		if (PortP->State & RIO_DELETED) {
@@ -631,8 +632,8 @@
 		break;
 	case TIOCSSERIAL:
 		rc = -EFAULT;
-		if (access_ok(VERIFY_READ, (void *) arg, sizeof(struct serial_struct)))
-			rc = gs_setserial(&PortP->gs, (struct serial_struct *) arg);
+		if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct)))
+			rc = gs_setserial(&PortP->gs, argp);
 		break;
 	default:
 		rc = -ENOIOCTLCMD;
@@ -919,7 +920,7 @@
 static void fix_rio_pci(struct pci_dev *pdev)
 {
 	unsigned long hwbase;
-	unsigned char *rebase;
+	unsigned char __iomem *rebase;
 	unsigned int t;
 
 #define CNTRL_REG_OFFSET        0x50
@@ -999,7 +1000,7 @@
 		if (((1 << hp->Ivec) & rio_irqmask) == 0)
 			hp->Ivec = 0;
 		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam *) hp->Caddr;
+		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
 		hp->Type = RIO_PCI;
 		hp->Copy = rio_copy_to_card;
 		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
@@ -1021,7 +1022,7 @@
 			p->RIONumHosts++;
 			found++;
 		} else {
-			iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr));
+			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
 		}
 	}
 
@@ -1047,7 +1048,7 @@
 			hp->Ivec = 0;
 		hp->Ivec |= 0x8000;	/* Mark as non-sharable */
 		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam *) hp->Caddr;
+		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
 		hp->Type = RIO_PCI;
 		hp->Copy = rio_copy_to_card;
 		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
@@ -1070,7 +1071,7 @@
 			p->RIONumHosts++;
 			found++;
 		} else {
-			iounmap((char *) (p->RIOHosts[p->RIONumHosts].Caddr));
+			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
 		}
 #else
 		printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
@@ -1085,7 +1086,7 @@
 		/* There was something about the IRQs of these cards. 'Forget what.--REW */
 		hp->Ivec = 0;
 		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam *) hp->Caddr;
+		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
 		hp->Type = RIO_AT;
 		hp->Copy = rio_copy_to_card;	/* AT card PCI???? - PVDL
                                          * -- YES! this is now a normal copy. Only the
@@ -1111,7 +1112,7 @@
 			}
 
 			if (!okboard)
-				iounmap((char *) (hp->Caddr));
+				iounmap(hp->Caddr);
 		}
 	}
 
diff --git a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h
index 4ce77fb..55b9c97 100644
--- a/drivers/char/rio/rio_linux.h
+++ b/drivers/char/rio/rio_linux.h
@@ -131,9 +131,9 @@
 
 
 #ifdef CONFIG_RIO_OLDPCI
-static inline void *rio_memcpy_toio(void *dummy, void *dest, void *source, int n)
+static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n)
 {
-	char *dst = dest;
+	char __iomem *dst = dest;
 	char *src = source;
 
 	while (n--) {
@@ -144,11 +144,22 @@
 	return dest;
 }
 
+static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n)
+{
+	char __iomem *dst = dest;
+	char *src = source;
 
-static inline void *rio_memcpy_fromio(void *dest, void *source, int n)
+	while (n--)
+		writeb(*src++, dst++);
+
+	return dest;
+}
+
+
+static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n)
 {
 	char *dst = dest;
-	char *src = source;
+	char __iomem *src = source;
 
 	while (n--)
 		*dst++ = readb(src++);
@@ -158,6 +169,7 @@
 
 #else
 #define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
+#define rio_copy_toio   		       memcpy_toio
 #define rio_memcpy_fromio                      memcpy_fromio
 #endif
 
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index 290143a..eca2b95 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -71,7 +71,7 @@
 #include "cmdblk.h"
 #include "route.h"
 
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd *PktCmdP);
+static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP);
 
 static const unsigned char RIOAtVec2Ctrl[] = {
 	/* 0 */ INTERRUPT_DISABLE,
@@ -204,13 +204,13 @@
 int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp)
 {
 	struct Host *HostP;
-	u8 *Cad;
-	PARM_MAP *ParmMapP;
+	u8 __iomem *Cad;
+	PARM_MAP __iomem *ParmMapP;
 	int RupN;
 	int PortN;
 	unsigned int host;
-	u8 *StartP;
-	u8 *DestP;
+	u8 __iomem *StartP;
+	u8 __iomem *DestP;
 	int wait_count;
 	u16 OldParmMap;
 	u16 offset;		/* It is very important that this is a u16 */
@@ -262,7 +262,7 @@
 		 ** Ensure that the host really is stopped.
 		 ** Disable it's external bus & twang its reset line.
 		 */
-		RIOHostReset(HostP->Type, (struct DpRam *) HostP->CardP, HostP->Slot);
+		RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot);
 
 		/*
 		 ** Copy the data directly from user space to the SRAM.
@@ -280,7 +280,7 @@
 			func_exit();
 			return -ENOMEM;
 		}
-		if (copy_from_user(rbp->DataP, DownCode, rbp->Count)) {
+		if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) {
 			kfree(DownCode);
 			p->RIOError.Error = COPYIN_FAILED;
 			func_exit();
@@ -366,7 +366,7 @@
 		 ** a short branch to 0x7FF8, where a long branch is coded.
 		 */
 
-		DestP = (u8 *) &Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
+		DestP = &Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
 
 #define	NFIX(N)	(0x60 | (N))	/* .O  = (~(.O + N))<<4 */
 #define	PFIX(N)	(0x20 | (N))	/* .O  =   (.O + N)<<4  */
@@ -438,7 +438,7 @@
 			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n");
 			HostP->Flags &= ~RUN_STATE;
 			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );
+			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
 			continue;
 		}
 
@@ -453,9 +453,9 @@
 		/*
 		 ** Grab a 32 bit pointer to the parmmap structure
 		 */
-		ParmMapP = (PARM_MAP *) RIO_PTR(Cad, readw(&HostP->__ParmMapR));
+		ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR));
 		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
-		ParmMapP = (PARM_MAP *) ((unsigned long) Cad + readw(&HostP->__ParmMapR));
+		ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR));
 		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
 
 		/*
@@ -468,7 +468,7 @@
 			rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links));
 			HostP->Flags &= ~RUN_STATE;
 			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );
+			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
 			continue;
 		}
 
@@ -491,7 +491,7 @@
 			rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n");
 			HostP->Flags &= ~RUN_STATE;
 			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, (struct DpRam *)HostP->CardP, HostP->Slot );
+			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
 			continue;
 		}
 
@@ -512,10 +512,10 @@
 		 ** 32 bit pointers for the driver in ioremap space.
 		 */
 		HostP->ParmMapP = ParmMapP;
-		HostP->PhbP = (struct PHB *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr));
-		HostP->RupP = (struct RUP *) RIO_PTR(Cad, readw(&ParmMapP->rups));
-		HostP->PhbNumP = (unsigned short *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr));
-		HostP->LinkStrP = (struct LPB *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr));
+		HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr));
+		HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups));
+		HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr));
+		HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr));
 
 		/*
 		 ** point the UnixRups at the real Rups
@@ -540,7 +540,7 @@
 		for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) {
 			if (p->RIOPortp[PortN]->HostP == HostP) {
 				struct Port *PortP = p->RIOPortp[PortN];
-				struct PHB *PhbP;
+				struct PHB __iomem *PhbP;
 				/* int oldspl; */
 
 				if (!PortP->Mapped)
@@ -551,12 +551,12 @@
 
 				PortP->PhbP = PhbP;
 
-				PortP->TxAdd = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_add));
-				PortP->TxStart = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_start));
-				PortP->TxEnd = (u16 *) RIO_PTR(Cad, readw(&PhbP->tx_end));
-				PortP->RxRemove = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_remove));
-				PortP->RxStart = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_start));
-				PortP->RxEnd = (u16 *) RIO_PTR(Cad, readw(&PhbP->rx_end));
+				PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add));
+				PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start));
+				PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end));
+				PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove));
+				PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start));
+				PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end));
 
 				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 				/*
@@ -601,9 +601,9 @@
  *	return 1. If we havent, then return 0.
  */
 
-int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT *PacketP)
+int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP)
 {
-	struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;
+	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
 	struct PktCmd_M *PktReplyP;
 	struct CmdBlk *CmdBlkP;
 	unsigned int sequence;
@@ -722,7 +722,7 @@
  *	RtaUniq is the booted RTA.
  */
 
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd *PktCmdP)
+static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP)
 {
 	struct Map *MapP = NULL;
 	struct Map *MapP2 = NULL;
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index e6d2b14b..4df6ab2 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -180,7 +180,7 @@
 }
 
 
-int RIOIdentifyRta(struct rio_info *p, void * arg)
+int RIOIdentifyRta(struct rio_info *p, void __user * arg)
 {
 	unsigned int Host;
 
@@ -245,7 +245,7 @@
 }
 
 
-int RIOKillNeighbour(struct rio_info *p, void * arg)
+int RIOKillNeighbour(struct rio_info *p, void __user * arg)
 {
 	uint Host;
 	uint ID;
@@ -370,9 +370,9 @@
 /*
 ** Incoming command on the COMMAND_RUP to be processed.
 */
-static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT * PacketP)
+static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP)
 {
-	struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;
+	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data;
 	struct Port *PortP;
 	struct UnixRup *UnixRupP;
 	unsigned short SysPort;
@@ -407,12 +407,12 @@
 		} else
 			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
 
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", PacketP->dest_unit, PacketP->dest_port);
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n", PacketP->src_unit, PacketP->src_port);
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", PacketP->len, PacketP->len);
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", PacketP->control, PacketP->control);
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", PacketP->csum, PacketP->csum);
-		rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", PktCmdP->PhbNum, PktCmdP->Command);
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control));
+		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum));
+		rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command));
 		return 1;
 	}
 	PortP = p->RIOPortp[SysPort];
@@ -601,7 +601,7 @@
 		/*
 		 ** Whammy! blat that pack!
 		 */
-		HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(struct PKT));
+		HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
 
 		/*
 		 ** place command packet on the pending position.
@@ -655,7 +655,7 @@
 {
 	struct CmdBlk *CmdBlkP;
 	struct UnixRup *UnixRupP;
-	struct PKT *PacketP;
+	struct PKT __iomem *PacketP;
 	unsigned short Rup;
 	unsigned long flags;
 
@@ -676,7 +676,7 @@
 		if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
 			int FreeMe;
 
-			PacketP = (struct PKT *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt));
+			PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt));
 
 			switch (readb(&PacketP->dest_port)) {
 			case BOOT_RUP:
@@ -694,9 +694,9 @@
 				 */
 				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
 				FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
-				if (PacketP->data[5] == MEMDUMP) {
-					rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", *(unsigned short *) & (PacketP->data[6]));
-					HostP->Copy((caddr_t) & (PacketP->data[8]), (caddr_t) p->RIOMemDump, 32);
+				if (readb(&PacketP->data[5]) == MEMDUMP) {
+					rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
+					rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
 				}
 				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
 				break;
@@ -782,7 +782,7 @@
 				/*
 				 ** Whammy! blat that pack!
 				 */
-				HostP->Copy((caddr_t) & CmdBlkP->Packet, RIO_PTR(HostP->Caddr, UnixRupP->RupP->txpkt), sizeof(struct PKT));
+				HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
 
 				/*
 				 ** remove the command from the rup command queue...
@@ -824,7 +824,7 @@
 int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP)
 {
 	struct Port *PortP = (struct Port *) iPortP;
-	struct PKT *PacketP;
+	struct PKT __iomem *PacketP;
 	unsigned long flags;
 
 	rio_spin_lock_irqsave(&PortP->portSem, flags);
diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c
index 75b2557..052e812 100644
--- a/drivers/char/rio/rioctrl.c
+++ b/drivers/char/rio/rioctrl.c
@@ -80,7 +80,7 @@
 static struct LpbReq LpbReq;
 static struct RupReq RupReq;
 static struct PortReq PortReq;
-static struct HostReq HostReq;
+static struct HostReq HostReq;	/* oh really?  global?  and no locking? */
 static struct HostDpRam HostDpRam;
 static struct DebugCtrl DebugCtrl;
 static struct Map MapEnt;
@@ -126,12 +126,19 @@
 
 #define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
 
-int riocontrol(p, dev, cmd, arg, su)
-struct rio_info *p;
-dev_t dev;
-int cmd;
-caddr_t arg;
-int su;
+static int copy_from_io(void __user *to, void __iomem *from, size_t size)
+{
+	void *buf = kmalloc(size, GFP_KERNEL);
+	int res = -ENOMEM;
+	if (buf) {
+		rio_memcpy_fromio(buf, from, size);
+		res = copy_to_user(to, buf, size);
+		kfree(buf);
+	}
+	return res;
+}
+
+int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su)
 {
 	uint Host;		/* leave me unsigned! */
 	uint port;		/* and me! */
@@ -139,9 +146,10 @@
 	ushort loop;
 	int Entry;
 	struct Port *PortP;
-	struct PKT *PacketP;
+	struct PKT __iomem *PacketP;
 	int retval = 0;
 	unsigned long flags;
+	void __user *argp = (void __user *)arg;
 
 	func_enter();
 
@@ -149,7 +157,7 @@
 	Host = 0;
 	PortP = NULL;
 
-	rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, arg);
+	rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp);
 
 	switch (cmd) {
 		/*
@@ -160,11 +168,11 @@
 		 ** otherwise just the specified host card will be changed.
 		 */
 	case RIO_SET_TIMER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", (unsigned long)arg);
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg);
 		{
 			int host, value;
-			host = ((unsigned long) arg >> 16) & 0x0000FFFF;
-			value = (unsigned long) arg & 0x0000ffff;
+			host = (arg >> 16) & 0x0000FFFF;
+			value = arg & 0x0000ffff;
 			if (host == -1) {
 				for (host = 0; host < p->RIONumHosts; host++) {
 					if (p->RIOHosts[host].Flags == RC_RUNNING) {
@@ -183,26 +191,26 @@
 
 	case RIO_FOAD_RTA:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
-		return RIOCommandRta(p, (unsigned long)arg, RIOFoadRta);
+		return RIOCommandRta(p, arg, RIOFoadRta);
 
 	case RIO_ZOMBIE_RTA:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
-		return RIOCommandRta(p, (unsigned long)arg, RIOZombieRta);
+		return RIOCommandRta(p, arg, RIOZombieRta);
 
 	case RIO_IDENTIFY_RTA:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
-		return RIOIdentifyRta(p, arg);
+		return RIOIdentifyRta(p, argp);
 
 	case RIO_KILL_NEIGHBOUR:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
-		return RIOKillNeighbour(p, arg);
+		return RIOKillNeighbour(p, argp);
 
 	case SPECIAL_RUP_CMD:
 		{
 			struct CmdBlk *CmdBlkP;
 
 			rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
-			if (copy_from_user(&SpecialRupCmd, arg, sizeof(SpecialRupCmd))) {
+			if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) {
 				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
 				p->RIOError.Error = COPYIN_FAILED;
 				return -EFAULT;
@@ -239,7 +247,7 @@
 		if ((retval = RIOApel(p)) != 0)
 			return retval;
 
-		if (copy_to_user(arg, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
+		if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -284,7 +292,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_from_user(&p->RIOConnectTable[0], arg, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
+		if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -330,7 +338,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_to_user(arg, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
+		if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -349,7 +357,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_from_user(&p->RIOBindTab[0], arg, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
+		if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -373,12 +381,12 @@
 			for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
 				if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
 					EmptySlot = Entry;
-				else if (p->RIOBindTab[Entry] == (long)arg) {
+				else if (p->RIOBindTab[Entry] == arg) {
 					/*
 					 ** Already exists - delete
 					 */
 					p->RIOBindTab[Entry] = 0L;
-					rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", (unsigned long)arg);
+					rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg);
 					return 0;
 				}
 			}
@@ -386,10 +394,10 @@
 			 ** Dosen't exist - add
 			 */
 			if (EmptySlot != -1) {
-				p->RIOBindTab[EmptySlot] = (unsigned long)arg;
-				rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", (unsigned long) arg);
+				p->RIOBindTab[EmptySlot] = arg;
+				rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg);
 			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", (unsigned long) arg);
+				rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg);
 				return -ENOMEM;
 			}
 			return 0;
@@ -397,7 +405,7 @@
 
 	case RIO_RESUME:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
-		port = (unsigned long) arg;
+		port = arg;
 		if ((port < 0) || (port > 511)) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
@@ -433,7 +441,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) {
+		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -447,7 +455,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) {
+		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -461,7 +469,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_from_user(&MapEnt, arg, sizeof(MapEnt))) {
+		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -469,14 +477,14 @@
 		return RIODeleteRta(p, &MapEnt);
 
 	case RIO_QUICK_CHECK:
-		if (copy_to_user(arg, &p->RIORtaDisCons, sizeof(unsigned int))) {
+		if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
 		return 0;
 
 	case RIO_LAST_ERROR:
-		if (copy_to_user(arg, &p->RIOError, sizeof(struct Error)))
+		if (copy_to_user(argp, &p->RIOError, sizeof(struct Error)))
 			return -EFAULT;
 		return 0;
 
@@ -485,7 +493,7 @@
 		return -EINVAL;
 
 	case RIO_GET_MODTYPE:
-		if (copy_from_user(&port, arg, sizeof(unsigned int))) {
+		if (copy_from_user(&port, argp, sizeof(unsigned int))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -505,7 +513,7 @@
 		 ** Return module type of port
 		 */
 		port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
-		if (copy_to_user(arg, &port, sizeof(unsigned int))) {
+		if (copy_to_user(argp, &port, sizeof(unsigned int))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
@@ -521,7 +529,7 @@
 
 	case RIO_SETUP_PORTS:
 		rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
-		if (copy_from_user(&PortSetup, arg, sizeof(PortSetup))) {
+		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
 			return -EFAULT;
@@ -551,7 +559,7 @@
 
 	case RIO_GET_PORT_SETUP:
 		rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
-		if (copy_from_user(&PortSetup, arg, sizeof(PortSetup))) {
+		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -572,7 +580,7 @@
 		PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
 		PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
 
-		if (copy_to_user(arg, &PortSetup, sizeof(PortSetup))) {
+		if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
@@ -580,7 +588,7 @@
 
 	case RIO_GET_PORT_PARAMS:
 		rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
-		if (copy_from_user(&PortParams, arg, sizeof(struct PortParams))) {
+		if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -593,7 +601,7 @@
 		PortParams.State = PortP->State;
 		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
 
-		if (copy_to_user(arg, &PortParams, sizeof(struct PortParams))) {
+		if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
@@ -601,7 +609,7 @@
 
 	case RIO_GET_PORT_TTY:
 		rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
-		if (copy_from_user(&PortTty, arg, sizeof(struct PortTty))) {
+		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -612,14 +620,14 @@
 
 		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
 		PortP = (p->RIOPortp[PortTty.port]);
-		if (copy_to_user(arg, &PortTty, sizeof(struct PortTty))) {
+		if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
 		return retval;
 
 	case RIO_SET_PORT_TTY:
-		if (copy_from_user(&PortTty, arg, sizeof(struct PortTty))) {
+		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -634,7 +642,7 @@
 
 	case RIO_SET_PORT_PARAMS:
 		rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
-		if (copy_from_user(&PortParams, arg, sizeof(PortParams))) {
+		if (copy_from_user(&PortParams, argp, sizeof(PortParams))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -650,7 +658,7 @@
 
 	case RIO_GET_PORT_STATS:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
-		if (copy_from_user(&portStats, arg, sizeof(struct portStats))) {
+		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -665,14 +673,14 @@
 		portStats.opens = PortP->opens;
 		portStats.closes = PortP->closes;
 		portStats.ioctls = PortP->ioctls;
-		if (copy_to_user(arg, &portStats, sizeof(struct portStats))) {
+		if (copy_to_user(argp, &portStats, sizeof(struct portStats))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
 		return retval;
 
 	case RIO_RESET_PORT_STATS:
-		port = (unsigned long) arg;
+		port = arg;
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
 		if (port >= RIO_PORTS) {
 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
@@ -690,7 +698,7 @@
 
 	case RIO_GATHER_PORT_STATS:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
-		if (copy_from_user(&portStats, arg, sizeof(struct portStats))) {
+		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -706,7 +714,7 @@
 
 	case RIO_READ_CONFIG:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
-		if (copy_to_user(arg, &p->RIOConf, sizeof(struct Conf))) {
+		if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
@@ -718,7 +726,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_from_user(&p->RIOConf, arg, sizeof(struct Conf))) {
+		if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -746,7 +754,7 @@
 	case RIO_SETDEBUG:
 	case RIO_GETDEBUG:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
-		if (copy_from_user(&DebugCtrl, arg, sizeof(DebugCtrl))) {
+		if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -763,7 +771,7 @@
 				rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
 				DebugCtrl.Debug = p->rio_debug;
 				DebugCtrl.Wait = p->RIODebugWait;
-				if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) {
+				if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
 					rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
 					p->RIOError.Error = COPYOUT_FAILED;
 					return -EFAULT;
@@ -785,7 +793,7 @@
 		} else {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
 			DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
-			if (copy_to_user(arg, &DebugCtrl, sizeof(DebugCtrl))) {
+			if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
 				rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
 				p->RIOError.Error = COPYOUT_FAILED;
 				return -EFAULT;
@@ -800,7 +808,7 @@
 		 ** textual null terminated string.
 		 */
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
-		if (copy_to_user(arg, RIOVersid(), sizeof(struct rioVersion))) {
+		if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -813,7 +821,7 @@
 		 ** at init time.
 		 */
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
-		if (copy_to_user(arg, &p->RIONumHosts, sizeof(p->RIONumHosts))) {
+		if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -824,7 +832,7 @@
 		/*
 		 ** Kill host. This may not be in the final version...
 		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", (unsigned long) arg);
+		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg);
 		if (!su) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
 			p->RIOError.Error = NOT_SUPER_USER;
@@ -858,7 +866,7 @@
 			p->RIOError.Error = NOT_SUPER_USER;
 			return -EPERM;
 		}
-		if (copy_from_user(&DownLoad, arg, sizeof(DownLoad))) {
+		if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -888,7 +896,7 @@
 		{
 			unsigned int host;
 
-			if (copy_from_user(&host, arg, sizeof(host))) {
+			if (copy_from_user(&host, argp, sizeof(host))) {
 				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
 				p->RIOError.Error = COPYIN_FAILED;
 				return -EFAULT;
@@ -897,7 +905,7 @@
 			 ** Fetch the parmmap
 			 */
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
-			if (copy_to_user(arg, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {
+			if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {
 				p->RIOError.Error = COPYOUT_FAILED;
 				rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
 				return -EFAULT;
@@ -907,7 +915,7 @@
 
 	case RIO_HOST_REQ:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
-		if (copy_from_user(&HostReq, arg, sizeof(HostReq))) {
+		if (copy_from_user(&HostReq, argp, sizeof(HostReq))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -928,7 +936,7 @@
 
 	case RIO_HOST_DPRAM:
 		rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
-		if (copy_from_user(&HostDpRam, arg, sizeof(HostDpRam))) {
+		if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -945,13 +953,13 @@
 			/* It's hardware like this that really gets on my tits. */
 			static unsigned char copy[sizeof(struct DpRam)];
 			for (off = 0; off < sizeof(struct DpRam); off++)
-				copy[off] = readb(&p->RIOHosts[HostDpRam.HostNum].Caddr[off]);
+				copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off);
 			if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) {
 				p->RIOError.Error = COPYOUT_FAILED;
 				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
 				return -EFAULT;
 			}
-		} else if (copy_to_user(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {
+		} else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
 			return -EFAULT;
@@ -960,13 +968,13 @@
 
 	case RIO_SET_BUSY:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
-		if ((unsigned long) arg > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", (unsigned long) arg);
+		if (arg > 511) {
+			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg);
 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
 			return -EINVAL;
 		}
 		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		p->RIOPortp[(unsigned long) arg]->State |= RIO_BUSY;
+		p->RIOPortp[arg]->State |= RIO_BUSY;
 		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 		return retval;
 
@@ -976,7 +984,7 @@
 		 ** (probably for debug reasons)
 		 */
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
-		if (copy_from_user(&PortReq, arg, sizeof(PortReq))) {
+		if (copy_from_user(&PortReq, argp, sizeof(PortReq))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -1001,7 +1009,7 @@
 		 ** (probably for debug reasons)
 		 */
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
-		if (copy_from_user(&RupReq, arg, sizeof(RupReq))) {
+		if (copy_from_user(&RupReq, argp, sizeof(RupReq))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -1025,7 +1033,7 @@
 		}
 		rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
 
-		if (copy_to_user(HostP->UnixRups[RupReq.RupNum].RupP, RupReq.RupP, sizeof(struct RUP))) {
+		if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
 			return -EFAULT;
@@ -1038,7 +1046,7 @@
 		 ** (probably for debug reasons)
 		 */
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
-		if (copy_from_user(&LpbReq, arg, sizeof(LpbReq))) {
+		if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -1062,7 +1070,7 @@
 		}
 		rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
 
-		if (copy_to_user(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {
+		if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -1136,7 +1144,7 @@
 	case RIO_MAP_B110_TO_110:
 	case RIO_MAP_B110_TO_115200:
 		rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
-		port = (unsigned long) arg;
+		port = arg;
 		if (port < 0 || port > 511) {
 			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
 			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
@@ -1166,7 +1174,7 @@
 
 	case RIO_SEND_PACKET:
 		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
-		if (copy_from_user(&SendPack, arg, sizeof(SendPack))) {
+		if (copy_from_user(&SendPack, argp, sizeof(SendPack))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
@@ -1210,7 +1218,7 @@
 		return su ? 0 : -EPERM;
 
 	case RIO_WHAT_MESG:
-		if (copy_to_user(arg, &p->RIONoMessage, sizeof(p->RIONoMessage))) {
+		if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -1218,7 +1226,7 @@
 		return 0;
 
 	case RIO_MEM_DUMP:
-		if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) {
+		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -1248,7 +1256,7 @@
 			PortP->State |= RIO_BUSY;
 
 		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(arg, p->RIOMemDump, MEMDUMP_SIZE)) {
+		if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -1256,30 +1264,30 @@
 		return 0;
 
 	case RIO_TICK:
-		if ((unsigned long) arg >= p->RIONumHosts)
+		if (arg >= p->RIONumHosts)
 			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", (unsigned long) arg);
-		writeb(0xFF, &p->RIOHosts[(unsigned long) arg].SetInt);
+		rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg);
+		writeb(0xFF, &p->RIOHosts[arg].SetInt);
 		return 0;
 
 	case RIO_TOCK:
-		if ((unsigned long) arg >= p->RIONumHosts)
+		if (arg >= p->RIONumHosts)
 			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", (unsigned long) arg);
-		writeb(0xFF, &p->RIOHosts[(unsigned long) arg].ResetInt);
+		rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg);
+		writeb(0xFF, &p->RIOHosts[arg].ResetInt);
 		return 0;
 
 	case RIO_READ_CHECK:
 		/* Check reads for pkts with data[0] the same */
 		p->RIOReadCheck = !p->RIOReadCheck;
-		if (copy_to_user(arg, &p->RIOReadCheck, sizeof(unsigned int))) {
+		if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) {
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
 		}
 		return 0;
 
 	case RIO_READ_REGISTER:
-		if (copy_from_user(&SubCmd, arg, sizeof(struct SubCmdStruct))) {
+		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
 			p->RIOError.Error = COPYIN_FAILED;
 			return -EFAULT;
 		}
@@ -1314,7 +1322,7 @@
 			PortP->State |= RIO_BUSY;
 
 		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(arg, &p->CdRegister, sizeof(unsigned int))) {
+		if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) {
 			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
 			p->RIOError.Error = COPYOUT_FAILED;
 			return -EFAULT;
@@ -1327,10 +1335,10 @@
 		 */
 	case RIO_MAKE_DEV:
 		{
-			unsigned int port = (unsigned long) arg & RIO_MODEM_MASK;
+			unsigned int port = arg & RIO_MODEM_MASK;
 			unsigned int ret;
 
-			switch ((unsigned long) arg & RIO_DEV_MASK) {
+			switch (arg & RIO_DEV_MASK) {
 			case RIO_DEV_DIRECT:
 				ret = drv_makedev(MAJOR(dev), port);
 				rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret);
@@ -1358,7 +1366,7 @@
 			int mino;
 			unsigned long ret;
 
-			dv = (dev_t) ((unsigned long) arg);
+			dv = (dev_t) (arg);
 			mino = RIO_UNMODEM(dv);
 
 			if (RIO_ISMODEM(dv)) {
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index 24d2992..12e34bc 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -79,7 +79,7 @@
 
 int RIOPCIinit(struct rio_info *p, int Mode);
 
-static int RIOScrub(int, u8 *, int);
+static int RIOScrub(int, u8 __iomem *, int);
 
 
 /**
@@ -92,10 +92,10 @@
 ** bits > 0 indicates 16 bit operation.
 */
 
-int RIOAssignAT(struct rio_info *p, int	Base, caddr_t	virtAddr, int mode)
+int RIOAssignAT(struct rio_info *p, int	Base, void __iomem *virtAddr, int mode)
 {
 	int		bits;
-	struct DpRam *cardp = (struct DpRam *)virtAddr;
+	struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr;
 
 	if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE))
 		bits = BYTE_OPERATION;
@@ -107,7 +107,7 @@
 	** transient stuff.
 	*/
 	p->RIOHosts[p->RIONumHosts].Caddr	= virtAddr;
-	p->RIOHosts[p->RIONumHosts].CardP	= (struct DpRam *)virtAddr;
+	p->RIOHosts[p->RIONumHosts].CardP	= virtAddr;
 
 	/*
 	** Revision 01 AT host cards don't support WORD operations,
@@ -151,10 +151,10 @@
 ** RAM test a board. 
 ** Nothing too complicated, just enough to check it out.
 */
-int RIOBoardTest(unsigned long paddr, caddr_t	caddr, unsigned char type, int slot)
+int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot)
 {
-	struct DpRam *DpRam = (struct DpRam *)caddr;
-	char *ram[4];
+	struct DpRam __iomem *DpRam = caddr;
+	void __iomem *ram[4];
 	int  size[4];
 	int  op, bank;
 	int  nbanks;
@@ -179,12 +179,12 @@
 	size[2] = DP_SRAM3_SIZE;
 	size[3] = DP_SCRATCH_SIZE;
 
-	ram[0] = (char *)&DpRam->DpSram1[0];
-	ram[1] = (char *)&DpRam->DpSram2[0];
-	ram[2] = (char *)&DpRam->DpSram3[0];
+	ram[0] = DpRam->DpSram1;
+	ram[1] = DpRam->DpSram2;
+	ram[2] = DpRam->DpSram3;
 	nbanks = (type == RIO_PCI) ? 3 : 4;
 	if (nbanks == 4)
-		ram[3] = (char *)&DpRam->DpScratch[0];
+		ram[3] = DpRam->DpScratch;
 
 
 	if (nbanks == 3) {
@@ -202,7 +202,7 @@
 	*/
 	for (op=0; op<TEST_END; op++) {
 		for (bank=0; bank<nbanks; bank++) {
-			if (RIOScrub(op, (u8 *)ram[bank], size[bank]) == RIO_FAIL) {
+			if (RIOScrub(op, ram[bank], size[bank]) == RIO_FAIL) {
 				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", 
 							bank, op);
 				return RIO_FAIL;
@@ -227,7 +227,7 @@
 ** to check that the data from the previous phase was retained.
 */
 
-static int RIOScrub(int op, u8 *ram, int size)
+static int RIOScrub(int op, u8 __iomem *ram, int size)
 {
 	int off;
 	unsigned char	oldbyte;
@@ -393,7 +393,7 @@
     return &stVersion;
 }
 
-void RIOHostReset(unsigned int Type, struct DpRam *DpRamP, unsigned int Slot)
+void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot)
 {
 	/*
 	** Reset the Tpu
diff --git a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c
index 97f0fa5..0bd0904 100644
--- a/drivers/char/rio/riointr.c
+++ b/drivers/char/rio/riointr.c
@@ -102,7 +102,7 @@
 	struct rio_info *p;
 	struct tty_struct *tty;
 	int c;
-	struct PKT *PacketP;
+	struct PKT __iomem *PacketP;
 	unsigned long flags;
 
 	PortP = (struct Port *) en;
@@ -144,7 +144,7 @@
 		if (c == 0)
 			break;
 
-		rio_memcpy_toio(PortP->HostP->Caddr, (caddr_t) PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
+		rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
 		/*    udelay (1); */
 
 		writeb(c, &(PacketP->len));
@@ -219,7 +219,7 @@
 		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
 			struct Port *PortP = p->RIOPortp[port];
 			struct tty_struct *ttyP;
-			struct PKT *PacketP;
+			struct PKT __iomem *PacketP;
 
 			/*
 			 ** not mapped in - most of the RIOPortp[] information
@@ -298,7 +298,7 @@
 		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
 			struct Port *PortP = p->RIOPortp[port];
 			struct tty_struct *ttyP;
-			struct PKT *PacketP;
+			struct PKT __iomem *PacketP;
 
 			/*
 			 ** not mapped in - most of the RIOPortp[] information
@@ -427,13 +427,13 @@
 
 				while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
 					int p;
-					struct PktCmd *PktCmdP;
+					struct PktCmd __iomem *PktCmdP;
 
 					rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
 					/*
 					 ** make it look just like a WFLUSH command
 					 */
-					PktCmdP = (struct PktCmd *) &PacketP->data[0];
+					PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
 
 					writeb(WFLUSH, &PktCmdP->Command);
 
@@ -525,9 +525,9 @@
 {
 	struct tty_struct *TtyP;
 	unsigned short transCount;
-	struct PKT *PacketP;
+	struct PKT __iomem *PacketP;
 	register unsigned int DataCnt;
-	unsigned char *ptr;
+	unsigned char __iomem *ptr;
 	unsigned char *buf;
 	int copied = 0;
 
@@ -546,7 +546,7 @@
 	 ** run out of space it will be set to the offset of the
 	 ** next byte to copy from the packet data area. The packet
 	 ** length field is decremented by the number of bytes that
-	 ** we succesfully removed from the packet. When this reaches
+	 ** we successfully removed from the packet. When this reaches
 	 ** zero, we reset the offset pointer to be zero, and free
 	 ** the packet from the front of the queue.
 	 */
@@ -585,19 +585,19 @@
 			/*
 			 ** check that it is not a command!
 			 */
-			if (PacketP->len & PKT_CMD_BIT) {
+			if (readb(&PacketP->len) & PKT_CMD_BIT) {
 				rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
 				/*      rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
-				rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", PacketP->dest_unit);
-				rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", PacketP->dest_port);
-				rio_dprintk(RIO_DEBUG_INTR, " src_unit  = %d\n", PacketP->src_unit);
-				rio_dprintk(RIO_DEBUG_INTR, " src_port  = %d\n", PacketP->src_port);
-				rio_dprintk(RIO_DEBUG_INTR, " len	   = %d\n", PacketP->len);
-				rio_dprintk(RIO_DEBUG_INTR, " control   = %d\n", PacketP->control);
-				rio_dprintk(RIO_DEBUG_INTR, " csum	   = %d\n", PacketP->csum);
+				rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit));
+				rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port));
+				rio_dprintk(RIO_DEBUG_INTR, " src_unit  = %d\n", readb(&PacketP->src_unit));
+				rio_dprintk(RIO_DEBUG_INTR, " src_port  = %d\n", readb(&PacketP->src_port));
+				rio_dprintk(RIO_DEBUG_INTR, " len	   = %d\n", readb(&PacketP->len));
+				rio_dprintk(RIO_DEBUG_INTR, " control   = %d\n", readb(&PacketP->control));
+				rio_dprintk(RIO_DEBUG_INTR, " csum	   = %d\n", readw(&PacketP->csum));
 				rio_dprintk(RIO_DEBUG_INTR, "	 data bytes: ");
 				for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
-					rio_dprintk(RIO_DEBUG_INTR, "%d\n", PacketP->data[DataCnt]);
+					rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt]));
 				remove_receive(PortP);
 				put_free_end(PortP->HostP, PacketP);
 				continue;	/* with next packet */
@@ -618,24 +618,24 @@
 			 ** and available space.
 			 */
 
-			transCount = tty_buffer_request_room(TtyP, PacketP->len & PKT_LEN_MASK);
+			transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK);
 			rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
 			/*
 			 ** To use the following 'kkprintfs' for debugging - change the '#undef'
 			 ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
 			 ** driver).
 			 */
-			ptr = (unsigned char *) PacketP->data + PortP->RxDataStart;
+			ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart;
 
 			tty_prepare_flip_string(TtyP, &buf, transCount);
 			rio_memcpy_fromio(buf, ptr, transCount);
 			PortP->RxDataStart += transCount;
-			PacketP->len -= transCount;
+			writeb(readb(&PacketP->len)-transCount, &PacketP->len);
 			copied += transCount;
 
 
 
-			if (PacketP->len == 0) {
+			if (readb(&PacketP->len) == 0) {
 				/*
 				 ** If we have emptied the packet, then we can
 				 ** free it, and reset the start pointer for
diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c
index d2e8092..1066d97 100644
--- a/drivers/char/rio/rioparam.c
+++ b/drivers/char/rio/rioparam.c
@@ -154,8 +154,8 @@
 {
 	struct tty_struct *TtyP;
 	int retval;
-	struct phb_param *phb_param_ptr;
-	struct PKT *PacketP;
+	struct phb_param __iomem *phb_param_ptr;
+	struct PKT __iomem *PacketP;
 	int res;
 	u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
 	u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
@@ -235,7 +235,7 @@
 	rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
 	rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP);
 
-	phb_param_ptr = (struct phb_param *) PacketP->data;
+	phb_param_ptr = (struct phb_param __iomem *) PacketP->data;
 
 
 	switch (TtyP->termios->c_cflag & CSIZE) {
@@ -580,11 +580,11 @@
 ** We can add another packet to a transmit queue if the packet pointer pointed
 ** to by the TxAdd pointer has PKT_IN_USE clear in its address.
 */
-int can_add_transmit(struct PKT **PktP, struct Port *PortP)
+int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP)
 {
-	struct PKT *tp;
+	struct PKT __iomem *tp;
 
-	*PktP = tp = (struct PKT *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd));
+	*PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd));
 
 	return !((unsigned long) tp & PKT_IN_USE);
 }
@@ -608,9 +608,9 @@
  * Put a packet onto the end of the
  * free list
  ****************************************/
-void put_free_end(struct Host *HostP, struct PKT *PktP)
+void put_free_end(struct Host *HostP, struct PKT __iomem *PktP)
 {
-	struct rio_free_list *tmp_pointer;
+	struct rio_free_list __iomem *tmp_pointer;
 	unsigned short old_end, new_end;
 	unsigned long flags;
 
@@ -625,15 +625,15 @@
 
 	if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) {
 		new_end = RIO_OFF(HostP->Caddr, PktP);
-		tmp_pointer = (struct rio_free_list *) RIO_PTR(HostP->Caddr, old_end);
+		tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end);
 		writew(new_end, &tmp_pointer->next);
-		writew(old_end, &((struct rio_free_list *) PktP)->prev);
-		writew(TPNULL, &((struct rio_free_list *) PktP)->next);
+		writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev);
+		writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next);
 		writew(new_end, &HostP->ParmMapP->free_list_end);
 	} else {		/* First packet on the free list this should never happen! */
 		rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
 		writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end);
-		tmp_pointer = (struct rio_free_list *) PktP;
+		tmp_pointer = (struct rio_free_list __iomem *) PktP;
 		writew(TPNULL, &tmp_pointer->prev);
 		writew(TPNULL, &tmp_pointer->next);
 	}
@@ -647,10 +647,10 @@
 ** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
 ** then can_remove_receive() returns 0.
 */
-int can_remove_receive(struct PKT **PktP, struct Port *PortP)
+int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP)
 {
 	if (readw(PortP->RxRemove) & PKT_IN_USE) {
-		*PktP = (struct PKT *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE);
+		*PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE);
 		return 1;
 	}
 	return 0;
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
index 3570853..a99f3d9 100644
--- a/drivers/char/rio/rioroute.c
+++ b/drivers/char/rio/rioroute.c
@@ -86,9 +86,9 @@
 ** Incoming on the ROUTE_RUP
 ** I wrote this while I was tired. Forgive me.
 */
-int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT * PacketP)
+int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP)
 {
-	struct PktCmd *PktCmdP = (struct PktCmd *) PacketP->data;
+	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
 	struct PktCmd_M *PktReplyP;
 	struct CmdBlk *CmdBlkP;
 	struct Port *PortP;
@@ -307,7 +307,7 @@
 	if (!RIOBootOk(p, HostP, RtaUniq)) {
 		rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
 		PktReplyP->Command = ROUTE_FOAD;
-		HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
 		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
 		return 1;
 	}
@@ -341,7 +341,7 @@
 					HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
 				}
 				PktReplyP->Command = ROUTE_FOAD;
-				HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+				memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
 				RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
 				return 1;
 			}
@@ -367,7 +367,7 @@
 				PktReplyP->IDNum2 = ROUTE_NO_ID;
 				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
 			}
-			HostP->Copy("RT_ALLOCAT", PktReplyP->CommandText, 10);
+			memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10);
 
 			RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
 
@@ -469,7 +469,7 @@
 		}
 
 		PktReplyP->Command = ROUTE_FOAD;
-		HostP->Copy("RT_FOAD", PktReplyP->CommandText, 7);
+		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
 	} else {
 		/*
 		 ** we did boot it (as an extra), and there may now be a table
@@ -489,7 +489,7 @@
 			}
 		}
 		PktReplyP->Command = ROUTE_USED;
-		HostP->Copy("RT_USED", PktReplyP->CommandText, 7);
+		memcpy(PktReplyP->CommandText, "RT_USED", 7);
 	}
 	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
 	return 1;
@@ -517,8 +517,8 @@
 
 		for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
 			unsigned short dest_port = port + 8;
-			u16 *TxPktP;
-			struct PKT *Pkt;
+			u16 __iomem *TxPktP;
+			struct PKT __iomem *Pkt;
 
 			PortP = p->RIOPortp[PortN];
 
@@ -555,12 +555,12 @@
 				 ** card. This needs to be translated into a 32 bit pointer
 				 ** so it can be accessed from the driver.
 				 */
-				Pkt = (struct PKT *) RIO_PTR(HostP->Caddr, readw(TxPktP));
+				Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));
 
 				/*
 				 ** If the packet is used, reset it.
 				 */
-				Pkt = (struct PKT *) ((unsigned long) Pkt & ~PKT_IN_USE);
+				Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE);
 				writeb(dest_unit, &Pkt->dest_unit);
 				writeb(dest_port, &Pkt->dest_port);
 			}
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
index d3abe0d..7e98835 100644
--- a/drivers/char/rio/riotable.c
+++ b/drivers/char/rio/riotable.c
@@ -534,8 +534,8 @@
 						if (PortP->SecondBlock) {
 							u16 dest_unit = HostMapP->ID;
 							u16 dest_port = port - SysPort;
-							u16 *TxPktP;
-							struct PKT *Pkt;
+							u16 __iomem *TxPktP;
+							struct PKT __iomem *Pkt;
 
 							for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
 								/*
@@ -545,12 +545,12 @@
 								 ** a 32 bit pointer so it can be
 								 ** accessed from the driver.
 								 */
-								Pkt = (struct PKT *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
-								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", *TxPktP, Pkt->dest_unit, Pkt->dest_port, dest_unit, dest_port);
+								Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
+								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port);
 								writew(dest_unit, &Pkt->dest_unit);
 								writew(dest_port, &Pkt->dest_port);
 							}
-							rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, PortP->PhbP->destination & 0xff, (PortP->PhbP->destination >> 8) & 0xff, dest_unit, dest_port);
+							rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
 							writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
 						}
 						rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
@@ -781,13 +781,13 @@
 		 ** unless the host has been booted
 		 */
 		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
-			struct PHB *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
-			PortP->TxAdd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
-			PortP->TxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
-			PortP->TxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
-			PortP->RxRemove = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
-			PortP->RxStart = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
-			PortP->RxEnd = (u16 *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));
+			struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
+			PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
+			PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
+			PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
+			PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
+			PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
+			PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));
 		} else
 			PortP->PhbP = NULL;
 
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index 2042676..a4f0b1e 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -576,7 +576,7 @@
 */
 int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
 {
-	struct PKT *PacketP;
+	struct PKT __iomem *PacketP;
 	int retries = 20;	/* at 10 per second -> 2 seconds */
 	unsigned long flags;
 
diff --git a/drivers/char/rio/unixrup.h b/drivers/char/rio/unixrup.h
index 4306e01..46bd532 100644
--- a/drivers/char/rio/unixrup.h
+++ b/drivers/char/rio/unixrup.h
@@ -44,7 +44,7 @@
 struct UnixRup {
 	struct CmdBlk *CmdsWaitingP;	/* Commands waiting to be done */
 	struct CmdBlk *CmdPendingP;	/* The command currently being sent */
-	struct RUP *RupP;	/* the Rup to send it to */
+	struct RUP __iomem *RupP;	/* the Rup to send it to */
 	unsigned int Id;		/* Id number */
 	unsigned int BaseSysPort;	/* SysPort of first tty on this RTA */
 	unsigned int ModTypes;		/* Modules on this RTA */
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 7edc6a4..0708c51 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -324,35 +324,15 @@
 			  CHANNEL_t * cp, unsigned int ChanStatus)
 {
 	unsigned int CharNStat;
-	int ToRecv, wRecv, space = 0, count;
-	unsigned char *cbuf, *chead;
-	char *fbuf, *fhead;
-	struct tty_ldisc *ld;
-
-	ld = tty_ldisc_ref(tty);
+	int ToRecv, wRecv, space;
+	unsigned char *cbuf;
 
 	ToRecv = sGetRxCnt(cp);
-	space = tty->receive_room;
-	if (space > 2 * TTY_FLIPBUF_SIZE)
-		space = 2 * TTY_FLIPBUF_SIZE;
-	count = 0;
 #ifdef ROCKET_DEBUG_INTR
-	printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
+	printk(KERN_INFO "rp_do_receive(%d)...", ToRecv);
 #endif
-
-	/*
-	 * determine how many we can actually read in.  If we can't
-	 * read any in then we have a software overrun condition.
-	 */
-	if (ToRecv > space)
-		ToRecv = space;
-
-	ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv);
-	if (ToRecv <= 0)
-		goto done;
-
-	cbuf = chead;
-	fbuf = fhead;
+	if (ToRecv == 0)
+		return;
 
 	/*
 	 * if status indicates there are errored characters in the
@@ -380,6 +360,8 @@
 		       info->read_status_mask);
 #endif
 		while (ToRecv) {
+			char flag;
+
 			CharNStat = sInW(sGetTxRxDataIO(cp));
 #ifdef ROCKET_DEBUG_RECEIVE
 			printk(KERN_INFO "%x...", CharNStat);
@@ -392,17 +374,16 @@
 			}
 			CharNStat &= info->read_status_mask;
 			if (CharNStat & STMBREAKH)
-				*fbuf++ = TTY_BREAK;
+				flag = TTY_BREAK;
 			else if (CharNStat & STMPARITYH)
-				*fbuf++ = TTY_PARITY;
+				flag = TTY_PARITY;
 			else if (CharNStat & STMFRAMEH)
-				*fbuf++ = TTY_FRAME;
+				flag = TTY_FRAME;
 			else if (CharNStat & STMRCVROVRH)
-				*fbuf++ = TTY_OVERRUN;
+				flag = TTY_OVERRUN;
 			else
-				*fbuf++ = TTY_NORMAL;
-			*cbuf++ = CharNStat & 0xff;
-			count++;
+				flag = TTY_NORMAL;
+			tty_insert_flip_char(tty, CharNStat & 0xff, flag);
 			ToRecv--;
 		}
 
@@ -422,20 +403,23 @@
 		 * characters at time by doing repeated word IO
 		 * transfer.
 		 */
+		space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
+		if (space < ToRecv) {
+#ifdef ROCKET_DEBUG_RECEIVE
+			printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
+#endif
+			if (space <= 0)
+				return;
+			ToRecv = space;
+		}
 		wRecv = ToRecv >> 1;
 		if (wRecv)
 			sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
 		if (ToRecv & 1)
 			cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
-		memset(fbuf, TTY_NORMAL, ToRecv);
-		cbuf += ToRecv;
-		fbuf += ToRecv;
-		count += ToRecv;
 	}
 	/*  Push the data up to the tty layer */
-	ld->receive_buf(tty, chead, fhead, count);
-done:
-	tty_ldisc_deref(ld);
+	tty_flip_buffer_push(tty);
 }
 
 /*
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 7cac6d0..0897b0c 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -928,7 +928,7 @@
 #ifdef __sparc__
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if(strcmp(edev->prom_name, "rtc") == 0) {
+			if(strcmp(edev->prom_node->name, "rtc") == 0) {
 				rtc_port = edev->resource[0].start;
 				rtc_irq = edev->irqs[0];
 				goto found;
@@ -938,7 +938,7 @@
 #ifdef __sparc_v9__
 	for_each_isa(isa_br) {
 		for_each_isadev(isa_dev, isa_br) {
-			if (strcmp(isa_dev->prom_name, "rtc") == 0) {
+			if (strcmp(isa_dev->prom_node->name, "rtc") == 0) {
 				rtc_port = isa_dev->resource.start;
 				rtc_irq = isa_dev->irq;
 				goto found;
@@ -960,10 +960,6 @@
 	 * PCI Slot 2 INTA# (and some INTx# in Slot 1).
 	 */
 	if (request_irq(rtc_irq, rtc_interrupt, SA_SHIRQ, "rtc", (void *)&rtc_port)) {
-		/*
-		 * Standard way for sparc to print irq's is to use
-		 * __irq_itoa(). I think for EBus it's ok to use %d.
-		 */
 		printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
 		return -EIO;
 	}
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index 664a6e9..5a280a3 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -1,4 +1,4 @@
-/* linux/drivers/char/scx200_gpio.c 
+/* linux/drivers/char/scx200_gpio.c
 
    National Semiconductor SCx200 GPIO driver.  Allows a user space
    process to play with the GPIO pins.
@@ -6,17 +6,26 @@
    Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */
 
 #include <linux/config.h>
+#include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+#include <linux/types.h>
+#include <linux/cdev.h>
+
 #include <linux/scx200_gpio.h>
+#include <linux/nsc_gpio.h>
 
 #define NAME "scx200_gpio"
+#define DEVNAME NAME
+
+static struct platform_device *pdev;
 
 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
 MODULE_DESCRIPTION("NatSemi SCx200 GPIO Pin Driver");
@@ -26,70 +35,23 @@
 module_param(major, int, 0);
 MODULE_PARM_DESC(major, "Major device number");
 
-static ssize_t scx200_gpio_write(struct file *file, const char __user *data, 
-				 size_t len, loff_t *ppos)
-{
-	unsigned m = iminor(file->f_dentry->d_inode);
-	size_t i;
-
-	for (i = 0; i < len; ++i) {
-		char c;
-		if (get_user(c, data+i))
-			return -EFAULT;
-		switch (c)
-		{
-		case '0': 
-			scx200_gpio_set(m, 0); 
-			break;
-		case '1': 
-			scx200_gpio_set(m, 1); 
-			break;
-		case 'O':
-			printk(KERN_INFO NAME ": GPIO%d output enabled\n", m);
-			scx200_gpio_configure(m, ~1, 1);
-			break;
-		case 'o':
-			printk(KERN_INFO NAME ": GPIO%d output disabled\n", m);
-			scx200_gpio_configure(m, ~1, 0);
-			break;
-		case 'T':
-			printk(KERN_INFO NAME ": GPIO%d output is push pull\n", m);
-			scx200_gpio_configure(m, ~2, 2);
-			break;
-		case 't':
-			printk(KERN_INFO NAME ": GPIO%d output is open drain\n", m);
-			scx200_gpio_configure(m, ~2, 0);
-			break;
-		case 'P':
-			printk(KERN_INFO NAME ": GPIO%d pull up enabled\n", m);
-			scx200_gpio_configure(m, ~4, 4);
-			break;
-		case 'p':
-			printk(KERN_INFO NAME ": GPIO%d pull up disabled\n", m);
-			scx200_gpio_configure(m, ~4, 0);
-			break;
-		}
-	}
-
-	return len;
-}
-
-static ssize_t scx200_gpio_read(struct file *file, char __user *buf,
-				size_t len, loff_t *ppos)
-{
-	unsigned m = iminor(file->f_dentry->d_inode);
-	int value;
-
-	value = scx200_gpio_get(m);
-	if (put_user(value ? '1' : '0', buf))
-		return -EFAULT;
-	
-	return 1;
-}
+struct nsc_gpio_ops scx200_access = {
+	.owner		= THIS_MODULE,
+	.gpio_config	= scx200_gpio_configure,
+	.gpio_dump	= nsc_gpio_dump,
+	.gpio_get	= scx200_gpio_get,
+	.gpio_set	= scx200_gpio_set,
+	.gpio_set_high	= scx200_gpio_set_high,
+	.gpio_set_low	= scx200_gpio_set_low,
+	.gpio_change	= scx200_gpio_change,
+	.gpio_current	= scx200_gpio_current
+};
 
 static int scx200_gpio_open(struct inode *inode, struct file *file)
 {
 	unsigned m = iminor(inode);
+	file->private_data = &scx200_access;
+
 	if (m > 63)
 		return -EINVAL;
 	return nonseekable_open(inode, file);
@@ -103,47 +65,81 @@
 
 static struct file_operations scx200_gpio_fops = {
 	.owner   = THIS_MODULE,
-	.write   = scx200_gpio_write,
-	.read    = scx200_gpio_read,
+	.write   = nsc_gpio_write,
+	.read    = nsc_gpio_read,
 	.open    = scx200_gpio_open,
 	.release = scx200_gpio_release,
 };
 
+struct cdev *scx200_devices;
+static int num_pins = 32;
+
 static int __init scx200_gpio_init(void)
 {
-	int r;
-
-	printk(KERN_DEBUG NAME ": NatSemi SCx200 GPIO Driver\n");
+	int rc, i;
+	dev_t dev = MKDEV(major, 0);
 
 	if (!scx200_gpio_present()) {
-		printk(KERN_ERR NAME ": no SCx200 gpio pins available\n");
+		printk(KERN_ERR NAME ": no SCx200 gpio present\n");
 		return -ENODEV;
 	}
 
-	r = register_chrdev(major, NAME, &scx200_gpio_fops);
-	if (r < 0) {
-		printk(KERN_ERR NAME ": unable to register character device\n");
-		return r;
+	/* support dev_dbg() with pdev->dev */
+	pdev = platform_device_alloc(DEVNAME, 0);
+	if (!pdev)
+		return -ENOMEM;
+
+	rc = platform_device_add(pdev);
+	if (rc)
+		goto undo_malloc;
+
+	/* nsc_gpio uses dev_dbg(), so needs this */
+	scx200_access.dev = &pdev->dev;
+
+	if (major)
+		rc = register_chrdev_region(dev, num_pins, "scx200_gpio");
+	else {
+		rc = alloc_chrdev_region(&dev, 0, num_pins, "scx200_gpio");
+		major = MAJOR(dev);
 	}
-	if (!major) {
-		major = r;
-		printk(KERN_DEBUG NAME ": got dynamic major %d\n", major);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc);
+		goto undo_platform_device_add;
+	}
+	scx200_devices = kzalloc(num_pins * sizeof(struct cdev), GFP_KERNEL);
+	if (!scx200_devices) {
+		rc = -ENOMEM;
+		goto undo_chrdev_region;
+	}
+	for (i = 0; i < num_pins; i++) {
+		struct cdev *cdev = &scx200_devices[i];
+		cdev_init(cdev, &scx200_gpio_fops);
+		cdev->owner = THIS_MODULE;
+		rc = cdev_add(cdev, MKDEV(major, i), 1);
+		/* tolerate 'minor' errors */
+		if (rc)
+			dev_err(&pdev->dev, "Error %d on minor %d", rc, i);
 	}
 
-	return 0;
+	return 0; /* succeed */
+
+undo_chrdev_region:
+	unregister_chrdev_region(dev, num_pins);
+undo_platform_device_add:
+	platform_device_put(pdev);
+undo_malloc:
+	kfree(pdev);
+	return rc;
 }
 
 static void __exit scx200_gpio_cleanup(void)
 {
-	unregister_chrdev(major, NAME);
+	kfree(scx200_devices);
+	unregister_chrdev_region(MKDEV(major, 0), num_pins);
+	platform_device_put(pdev);
+	platform_device_unregister(pdev);
+	/* kfree(pdev); */
 }
 
 module_init(scx200_gpio_init);
 module_exit(scx200_gpio_cleanup);
-
-/*
-    Local variables:
-        compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules"
-        c-basic-offset: 8
-    End:
-*/
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index a90f5d9..43dfd86 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -512,7 +512,7 @@
 
 #ifdef CONFIG_ACPI
 static struct acpi_device *sonypi_acpi_device;
-static int acpi_enabled;
+static int acpi_driver_registered;
 #endif
 
 static int sonypi_ec_write(u8 addr, u8 value)
@@ -869,7 +869,7 @@
 		sonypi_report_input_event(event);
 
 #ifdef CONFIG_ACPI
-	if (acpi_enabled)
+	if (sonypi_acpi_device)
 		acpi_bus_generate_event(sonypi_acpi_device, 1, event);
 #endif
 
@@ -1551,8 +1551,8 @@
 		goto err_free_device;
 
 #ifdef CONFIG_ACPI
-	if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0)
-		acpi_enabled = 1;
+	if (acpi_bus_register_driver(&sonypi_acpi_driver) >= 0)
+		acpi_driver_registered = 1;
 #endif
 
 	return 0;
@@ -1567,7 +1567,7 @@
 static void __exit sonypi_exit(void)
 {
 #ifdef CONFIG_ACPI
-	if (acpi_enabled)
+	if (acpi_driver_registered)
 		acpi_bus_unregister_driver(&sonypi_acpi_driver);
 #endif
 	platform_device_unregister(sonypi_platform_device);
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 5343e9f..d2d6b01 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1683,7 +1683,7 @@
 
 	bp = port_Board(port);
 
-	if (!tty || !port->xmit_buf || !tmp_buf) {
+	if (!port->xmit_buf || !tmp_buf) {
 		func_exit();
 		return 0;
 	}
@@ -1733,7 +1733,7 @@
 		return;
 	}
 	dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
-	if (!tty || !port->xmit_buf) {
+	if (!port->xmit_buf) {
 		func_exit();
 		return;
 	}
@@ -2477,7 +2477,7 @@
 #endif
 
 	for (i = 0; i < SX_NBOARD; i++)
-		sx_board[i].lock = SPIN_LOCK_UNLOCKED;
+		spin_lock_init(&sx_board[i].lock);
 
 	if (sx_init_drivers()) {
 		func_exit();
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index a9c5a72..00b4a21 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -141,15 +141,6 @@
 static struct tty_driver	*stl_serial;
 
 /*
- *	We will need to allocate a temporary write buffer for chars that
- *	come direct from user space. The problem is that a copy from user
- *	space might cause a page fault (typically on a system that is
- *	swapping!). All ports will share one buffer - since if the system
- *	is already swapping a shared buffer won't make things any worse.
- */
-static char			*stl_tmpwritebuf;
-
-/*
  *	Define a local default termios struct. All ports will be created
  *	with this termios initially. Basically all it defines is a raw port
  *	at 9600, 8 data bits, 1 stop bit.
@@ -363,6 +354,14 @@
 };
 
 /*
+ *	Lock ordering is that you may not take stallion_lock holding
+ *	brd_lock.
+ */
+
+static spinlock_t brd_lock; 		/* Guard the board mapping */
+static spinlock_t stallion_lock;	/* Guard the tty driver */
+
+/*
  *	Set up enable and disable macros for the ECH boards. They require
  *	the secondary io address space to be activated and deactivated.
  *	This way all ECH boards can share their secondary io region.
@@ -725,17 +724,7 @@
 
 static int __init stallion_module_init(void)
 {
-	unsigned long	flags;
-
-#ifdef DEBUG
-	printk("init_module()\n");
-#endif
-
-	save_flags(flags);
-	cli();
 	stl_init();
-	restore_flags(flags);
-
 	return 0;
 }
 
@@ -746,7 +735,6 @@
 	stlbrd_t	*brdp;
 	stlpanel_t	*panelp;
 	stlport_t	*portp;
-	unsigned long	flags;
 	int		i, j, k;
 
 #ifdef DEBUG
@@ -756,9 +744,6 @@
 	printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
 		stl_drvversion);
 
-	save_flags(flags);
-	cli();
-
 /*
  *	Free up all allocated resources used by the ports. This includes
  *	memory and interrupts. As part of this process we will also do
@@ -770,7 +755,6 @@
 	if (i) {
 		printk("STALLION: failed to un-register tty driver, "
 			"errno=%d\n", -i);
-		restore_flags(flags);
 		return;
 	}
 	for (i = 0; i < 4; i++) {
@@ -783,8 +767,6 @@
 			"errno=%d\n", -i);
 	class_destroy(stallion_class);
 
-	kfree(stl_tmpwritebuf);
-
 	for (i = 0; (i < stl_nrbrds); i++) {
 		if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
 			continue;
@@ -814,8 +796,6 @@
 		kfree(brdp);
 		stl_brds[i] = (stlbrd_t *) NULL;
 	}
-
-	restore_flags(flags);
 }
 
 module_init(stallion_module_init);
@@ -948,7 +928,7 @@
 
 	brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL);
 	if (!brdp) {
-		printk("STALLION: failed to allocate memory (size=%d)\n",
+		printk("STALLION: failed to allocate memory (size=%Zd)\n",
 			sizeof(stlbrd_t));
 		return NULL;
 	}
@@ -1066,16 +1046,17 @@
 	rc = 0;
 	doclocal = 0;
 
+	spin_lock_irqsave(&stallion_lock, flags);
+
 	if (portp->tty->termios->c_cflag & CLOCAL)
 		doclocal++;
 
-	save_flags(flags);
-	cli();
 	portp->openwaitcnt++;
 	if (! tty_hung_up_p(filp))
 		portp->refcount--;
 
 	for (;;) {
+		/* Takes brd_lock internally */
 		stl_setsignals(portp, 1, 1);
 		if (tty_hung_up_p(filp) ||
 		    ((portp->flags & ASYNC_INITIALIZED) == 0)) {
@@ -1093,13 +1074,14 @@
 			rc = -ERESTARTSYS;
 			break;
 		}
+		/* FIXME */
 		interruptible_sleep_on(&portp->open_wait);
 	}
 
 	if (! tty_hung_up_p(filp))
 		portp->refcount++;
 	portp->openwaitcnt--;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&stallion_lock, flags);
 
 	return rc;
 }
@@ -1119,16 +1101,15 @@
 	if (portp == (stlport_t *) NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&stallion_lock, flags);
 	if (tty_hung_up_p(filp)) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&stallion_lock, flags);
 		return;
 	}
 	if ((tty->count == 1) && (portp->refcount != 1))
 		portp->refcount = 1;
 	if (portp->refcount-- > 1) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&stallion_lock, flags);
 		return;
 	}
 
@@ -1142,11 +1123,18 @@
  *	(The sc26198 has no "end-of-data" interrupt only empty FIFO)
  */
 	tty->closing = 1;
+
+	spin_unlock_irqrestore(&stallion_lock, flags);
+
 	if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
 		tty_wait_until_sent(tty, portp->closing_wait);
 	stl_waituntilsent(tty, (HZ / 2));
 
+
+	spin_lock_irqsave(&stallion_lock, flags);
 	portp->flags &= ~ASYNC_INITIALIZED;
+	spin_unlock_irqrestore(&stallion_lock, flags);
+
 	stl_disableintrs(portp);
 	if (tty->termios->c_cflag & HUPCL)
 		stl_setsignals(portp, 0, 0);
@@ -1173,7 +1161,6 @@
 
 	portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 	wake_up_interruptible(&portp->close_wait);
-	restore_flags(flags);
 }
 
 /*****************************************************************************/
@@ -1195,9 +1182,6 @@
 		(int) tty, (int) buf, count);
 #endif
 
-	if ((tty == (struct tty_struct *) NULL) ||
-	    (stl_tmpwritebuf == (char *) NULL))
-		return 0;
 	portp = tty->driver_data;
 	if (portp == (stlport_t *) NULL)
 		return 0;
@@ -1302,11 +1286,6 @@
 	if (portp->tx.buf == (char *) NULL)
 		return;
 
-#if 0
-	if (tty->stopped || tty->hw_stopped ||
-	    (portp->tx.head == portp->tx.tail))
-		return;
-#endif
 	stl_startrxtx(portp, -1, 1);
 }
 
@@ -1977,12 +1956,14 @@
 	unsigned int	iobase;
 	int		handled = 0;
 
+	spin_lock(&brd_lock);
 	panelp = brdp->panels[0];
 	iobase = panelp->iobase;
 	while (inb(brdp->iostatus) & EIO_INTRPEND) {
 		handled = 1;
 		(* panelp->isr)(panelp, iobase);
 	}
+	spin_unlock(&brd_lock);
 	return handled;
 }
 
@@ -2168,7 +2149,7 @@
 		portp = kzalloc(sizeof(stlport_t), GFP_KERNEL);
 		if (!portp) {
 			printk("STALLION: failed to allocate memory "
-				"(size=%d)\n", sizeof(stlport_t));
+				"(size=%Zd)\n", sizeof(stlport_t));
 			break;
 		}
 
@@ -2304,7 +2285,7 @@
 	panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
 	if (!panelp) {
 		printk(KERN_WARNING "STALLION: failed to allocate memory "
-			"(size=%d)\n", sizeof(stlpanel_t));
+			"(size=%Zd)\n", sizeof(stlpanel_t));
 		return -ENOMEM;
 	}
 
@@ -2478,7 +2459,7 @@
 		panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
 		if (!panelp) {
 			printk("STALLION: failed to allocate memory "
-				"(size=%d)\n", sizeof(stlpanel_t));
+				"(size=%Zd)\n", sizeof(stlpanel_t));
 			break;
 		}
 		panelp->magic = STL_PANELMAGIC;
@@ -2879,8 +2860,7 @@
 	portp->stats.lflags = 0;
 	portp->stats.rxbuffered = 0;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&stallion_lock, flags);
 	if (portp->tty != (struct tty_struct *) NULL) {
 		if (portp->tty->driver_data == portp) {
 			portp->stats.ttystate = portp->tty->flags;
@@ -2894,7 +2874,7 @@
 			}
 		}
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&stallion_lock, flags);
 
 	head = portp->tx.head;
 	tail = portp->tx.tail;
@@ -3049,6 +3029,9 @@
 	int i;
 	printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
 
+	spin_lock_init(&stallion_lock);
+	spin_lock_init(&brd_lock);
+
 	stl_initbrds();
 
 	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
@@ -3056,14 +3039,6 @@
 		return -1;
 
 /*
- *	Allocate a temporary write buffer.
- */
-	stl_tmpwritebuf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
-	if (!stl_tmpwritebuf)
-		printk("STALLION: failed to allocate memory (size=%d)\n",
-			STL_TXBUFSIZE);
-
-/*
  *	Set up a character driver for per board stuff. This is mainly used
  *	to do stats ioctls on the ports.
  */
@@ -3147,11 +3122,13 @@
 	unsigned int	gfrcr;
 	int		chipmask, i, j;
 	int		nrchips, uartaddr, ioaddr;
+	unsigned long   flags;
 
 #ifdef DEBUG
 	printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp);
 #endif
 
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(panelp->brdnr, panelp->pagenr);
 
 /*
@@ -3189,6 +3166,7 @@
 	}
 
 	BRDDISABLE(panelp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
 	return chipmask;
 }
 
@@ -3200,6 +3178,7 @@
 
 static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
 {
+	unsigned long flags;
 #ifdef DEBUG
 	printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n",
 		(int) brdp, (int) panelp, (int) portp);
@@ -3209,6 +3188,7 @@
 	    (portp == (stlport_t *) NULL))
 		return;
 
+	spin_lock_irqsave(&brd_lock, flags);
 	portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
 		(portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
 	portp->uartaddr = (portp->portnr & 0x04) << 5;
@@ -3219,6 +3199,7 @@
 	stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
 	portp->hwid = stl_cd1400getreg(portp, GFRCR);
 	BRDDISABLE(portp->brdnr);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3428,8 +3409,7 @@
 		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
 	srer = stl_cd1400getreg(portp, SRER);
@@ -3466,7 +3446,7 @@
 		portp->sigs &= ~TIOCM_CD;
 	stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3492,8 +3472,7 @@
 	if (rts > 0)
 		msvr2 = MSVR2_RTS;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	if (rts >= 0)
@@ -3501,7 +3480,7 @@
 	if (dtr >= 0)
 		stl_cd1400setreg(portp, MSVR1, msvr1);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3520,14 +3499,13 @@
 	printk("stl_cd1400getsignals(portp=%x)\n", (int) portp);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	msvr1 = stl_cd1400getreg(portp, MSVR1);
 	msvr2 = stl_cd1400getreg(portp, MSVR2);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
 	sigs = 0;
 	sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
@@ -3569,15 +3547,14 @@
 	else if (rx > 0)
 		ccr |= CCR_RXENABLE;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	stl_cd1400ccrwait(portp);
 	stl_cd1400setreg(portp, CCR, ccr);
 	stl_cd1400ccrwait(portp);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3609,8 +3586,7 @@
 	else if (rx > 0)
 		sreron |= SRER_RXDATA;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	stl_cd1400setreg(portp, SRER,
@@ -3618,7 +3594,7 @@
 	BRDDISABLE(portp->brdnr);
 	if (tx > 0)
 		set_bit(ASYI_TXBUSY, &portp->istate);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3634,13 +3610,12 @@
 #ifdef DEBUG
 	printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp);
 #endif
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	stl_cd1400setreg(portp, SRER, 0);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3653,8 +3628,7 @@
 	printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	stl_cd1400setreg(portp, SRER,
@@ -3664,7 +3638,7 @@
 	portp->brklen = len;
 	if (len == 1)
 		portp->stats.txbreaks++;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3688,8 +3662,7 @@
 	if (tty == (struct tty_struct *) NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 
@@ -3729,7 +3702,7 @@
 	}
 
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3753,8 +3726,7 @@
 	if (tty == (struct tty_struct *) NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	if (state) {
@@ -3769,7 +3741,7 @@
 		stl_cd1400ccrwait(portp);
 	}
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3785,8 +3757,7 @@
 	if (portp == (stlport_t *) NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 	stl_cd1400ccrwait(portp);
@@ -3794,7 +3765,7 @@
 	stl_cd1400ccrwait(portp);
 	portp->tx.tail = portp->tx.head;
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3833,6 +3804,7 @@
 		(int) panelp, iobase);
 #endif
 
+	spin_lock(&brd_lock);
 	outb(SVRR, iobase);
 	svrtype = inb(iobase + EREG_DATA);
 	if (panelp->nrports > 4) {
@@ -3846,6 +3818,8 @@
 		stl_cd1400txisr(panelp, iobase);
 	else if (svrtype & SVRR_MDM)
 		stl_cd1400mdmisr(panelp, iobase);
+
+	spin_unlock(&brd_lock);
 }
 
 /*****************************************************************************/
@@ -4433,8 +4407,7 @@
 		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_sc26198setreg(portp, IMR, 0);
 	stl_sc26198updatereg(portp, MR0, mr0);
@@ -4461,7 +4434,7 @@
 	portp->imr = (portp->imr & ~imroff) | imron;
 	stl_sc26198setreg(portp, IMR, portp->imr);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4491,13 +4464,12 @@
 	else if (rts > 0)
 		iopioron |= IPR_RTS;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_sc26198setreg(portp, IOPIOR,
 		((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4516,12 +4488,11 @@
 	printk("stl_sc26198getsignals(portp=%x)\n", (int) portp);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	ipr = stl_sc26198getreg(portp, IPR);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
 	sigs = 0;
 	sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
@@ -4558,13 +4529,12 @@
 	else if (rx > 0)
 		ccr |= CR_RXENABLE;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_sc26198setreg(portp, SCCR, ccr);
 	BRDDISABLE(portp->brdnr);
 	portp->crenable = ccr;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4593,15 +4563,14 @@
 	else if (rx > 0)
 		imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_sc26198setreg(portp, IMR, imr);
 	BRDDISABLE(portp->brdnr);
 	portp->imr = imr;
 	if (tx > 0)
 		set_bit(ASYI_TXBUSY, &portp->istate);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4618,13 +4587,12 @@
 	printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	portp->imr = 0;
 	stl_sc26198setreg(portp, IMR, 0);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4637,8 +4605,7 @@
 	printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	if (len == 1) {
 		stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
@@ -4647,7 +4614,7 @@
 		stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
 	}
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4672,8 +4639,7 @@
 	if (tty == (struct tty_struct *) NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 
 	if (state) {
@@ -4719,7 +4685,7 @@
 	}
 
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4744,8 +4710,7 @@
 	if (tty == (struct tty_struct *) NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	if (state) {
 		mr0 = stl_sc26198getreg(portp, MR0);
@@ -4765,7 +4730,7 @@
 		stl_sc26198setreg(portp, MR0, mr0);
 	}
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4781,14 +4746,13 @@
 	if (portp == (stlport_t *) NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	stl_sc26198setreg(portp, SCCR, CR_TXRESET);
 	stl_sc26198setreg(portp, SCCR, portp->crenable);
 	BRDDISABLE(portp->brdnr);
 	portp->tx.tail = portp->tx.head;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4815,12 +4779,11 @@
 	if (test_bit(ASYI_TXBUSY, &portp->istate))
 		return 1;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&brd_lock, flags);
 	BRDENABLE(portp->brdnr, portp->pagenr);
 	sr = stl_sc26198getreg(portp, SR);
 	BRDDISABLE(portp->brdnr);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&brd_lock, flags);
 
 	return (sr & SR_TXEMPTY) ? 0 : 1;
 }
@@ -4878,6 +4841,8 @@
 	stlport_t	*portp;
 	unsigned int	iack;
 
+	spin_lock(&brd_lock);
+
 /* 
  *	Work around bug in sc26198 chip... Cannot have A6 address
  *	line of UART high, else iack will be returned as 0.
@@ -4893,6 +4858,8 @@
 		stl_sc26198txisr(portp);
 	else
 		stl_sc26198otherisr(portp, iack);
+
+	spin_unlock(&brd_lock);
 }
 
 /*****************************************************************************/
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 3b47472..76b9107 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -2320,7 +2320,7 @@
 #ifdef NEW_WRITE_LOCKING
 			port->gs.port_write_mutex = MUTEX;
 #endif
-			port->gs.driver_lock = SPIN_LOCK_UNLOCKED;
+			spin_lock_init(&port->gs.driver_lock);
 			/*
 			 * Initializing wait queue
 			 */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index b4d1f4e..4e35d41 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -101,6 +101,7 @@
 
 static struct pci_device_id pci_table[] = {
 	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 	{0,}, /* terminate list */
@@ -870,7 +871,7 @@
 		goto cleanup;
 	DBGINFO(("%s write count=%d\n", info->device_name, count));
 
-	if (!tty || !info->tx_buf)
+	if (!info->tx_buf)
 		goto cleanup;
 
 	if (count > info->max_frame_size) {
@@ -924,7 +925,7 @@
 	if (sanity_check(info, tty->name, "put_char"))
 		return;
 	DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
-	if (!tty || !info->tx_buf)
+	if (!info->tx_buf)
 		return;
 	spin_lock_irqsave(&info->lock,flags);
 	if (!info->tx_active && (info->tx_count < info->max_frame_size))
@@ -2515,7 +2516,8 @@
 	DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode));
 	spin_lock_irqsave(&info->lock,flags);
 	info->idle_mode = idle_mode;
-	tx_set_idle(info);
+	if (info->params.mode != MGSL_MODE_ASYNC)
+		tx_set_idle(info);
 	spin_unlock_irqrestore(&info->lock,flags);
 	return 0;
 }
@@ -3076,7 +3078,7 @@
 
 static int alloc_tmp_rbuf(struct slgt_info *info)
 {
-	info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL);
+	info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL);
 	if (info->tmp_rbuf == NULL)
 		return -ENOMEM;
 	return 0;
@@ -3276,6 +3278,9 @@
 	case SYNCLINK_GT_DEVICE_ID:
 		devstr = "GT";
 		break;
+	case SYNCLINK_GT2_DEVICE_ID:
+		devstr = "GT2";
+		break;
 	case SYNCLINK_GT4_DEVICE_ID:
 		devstr = "GT4";
 		break;
@@ -3353,7 +3358,9 @@
 	int i;
 	int port_count = 1;
 
-	if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
+	if (pdev->device == SYNCLINK_GT2_DEVICE_ID)
+		port_count = 2;
+	else if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
 		port_count = 4;
 
 	/* allocate device instances for all ports */
@@ -3940,8 +3947,6 @@
 
 	msc_set_vcr(info);
 
-	tx_set_idle(info);
-
 	/* SCR (serial control)
 	 *
 	 * 15  1=tx req on FIFO half empty
@@ -4012,7 +4017,7 @@
 	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
 	}
 
-	switch (info->params.crc_type)
+	switch (info->params.crc_type & HDLC_CRC_MASK)
 	{
 	case HDLC_CRC_16_CCITT: val |= BIT9; break;
 	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
@@ -4073,7 +4078,7 @@
 	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
 	}
 
-	switch (info->params.crc_type)
+	switch (info->params.crc_type & HDLC_CRC_MASK)
 	{
 	case HDLC_CRC_16_CCITT: val |= BIT9; break;
 	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
@@ -4175,17 +4180,38 @@
  */
 static void tx_set_idle(struct slgt_info *info)
 {
-	unsigned char val = 0xff;
+	unsigned char val;
+	unsigned short tcr;
 
-	switch(info->idle_mode)
-	{
-	case HDLC_TXIDLE_FLAGS:          val = 0x7e; break;
-	case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break;
-	case HDLC_TXIDLE_ZEROS:          val = 0x00; break;
-	case HDLC_TXIDLE_ONES:           val = 0xff; break;
-	case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
-	case HDLC_TXIDLE_SPACE:          val = 0x00; break;
-	case HDLC_TXIDLE_MARK:           val = 0xff; break;
+	/* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits
+	 * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits
+	 */
+	tcr = rd_reg16(info, TCR);
+	if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) {
+		/* disable preamble, set idle size to 16 bits */
+		tcr = (tcr & ~(BIT6 + BIT5)) | BIT4;
+		/* MSB of 16 bit idle specified in tx preamble register (TPR) */
+		wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff));
+	} else if (!(tcr & BIT6)) {
+		/* preamble is disabled, set idle size to 8 bits */
+		tcr &= ~(BIT5 + BIT4);
+	}
+	wr_reg16(info, TCR, tcr);
+
+	if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) {
+		/* LSB of custom tx idle specified in tx idle register */
+		val = (unsigned char)(info->idle_mode & 0xff);
+	} else {
+		/* standard 8 bit idle patterns */
+		switch(info->idle_mode)
+		{
+		case HDLC_TXIDLE_FLAGS:          val = 0x7e; break;
+		case HDLC_TXIDLE_ALT_ZEROS_ONES:
+		case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
+		case HDLC_TXIDLE_ZEROS:
+		case HDLC_TXIDLE_SPACE:          val = 0x00; break;
+		default:                         val = 0xff;
+		}
 	}
 
 	wr_reg8(info, TIR, val);
@@ -4313,6 +4339,12 @@
 	unsigned long flags;
 	struct tty_struct *tty = info->tty;
 	unsigned char addr_field = 0xff;
+	unsigned int crc_size = 0;
+
+	switch (info->params.crc_type & HDLC_CRC_MASK) {
+	case HDLC_CRC_16_CCITT: crc_size = 2; break;
+	case HDLC_CRC_32_CCITT: crc_size = 4; break;
+	}
 
 check_again:
 
@@ -4357,7 +4389,7 @@
 	status = desc_status(info->rbufs[end]);
 
 	/* ignore CRC bit if not using CRC (bit is undefined) */
-	if (info->params.crc_type == HDLC_CRC_NONE)
+	if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE)
 		status &= ~BIT1;
 
 	if (framesize == 0 ||
@@ -4366,34 +4398,34 @@
 		goto check_again;
 	}
 
-	if (framesize < 2 || status & (BIT1+BIT0)) {
-		if (framesize < 2 || (status & BIT0))
-			info->icount.rxshort++;
-		else
-			info->icount.rxcrc++;
+	if (framesize < (2 + crc_size) || status & BIT0) {
+		info->icount.rxshort++;
 		framesize = 0;
+	} else if (status & BIT1) {
+		info->icount.rxcrc++;
+		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX))
+			framesize = 0;
+	}
 
 #ifdef CONFIG_HDLC
-		{
-			struct net_device_stats *stats = hdlc_stats(info->netdev);
-			stats->rx_errors++;
-			stats->rx_frame_errors++;
-		}
-#endif
-	} else {
-		/* adjust frame size for CRC, if any */
-		if (info->params.crc_type == HDLC_CRC_16_CCITT)
-			framesize -= 2;
-		else if (info->params.crc_type == HDLC_CRC_32_CCITT)
-			framesize -= 4;
+	if (framesize == 0) {
+		struct net_device_stats *stats = hdlc_stats(info->netdev);
+		stats->rx_errors++;
+		stats->rx_frame_errors++;
 	}
+#endif
 
 	DBGBH(("%s rx frame status=%04X size=%d\n",
 		info->device_name, status, framesize));
 	DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
 
 	if (framesize) {
-		if (framesize > info->max_frame_size)
+		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
+			framesize -= crc_size;
+			crc_size = 0;
+		}
+
+		if (framesize > info->max_frame_size + crc_size)
 			info->icount.rxlong++;
 		else {
 			/* copy dma buffer(s) to contiguous temp buffer */
@@ -4413,6 +4445,11 @@
 					i = 0;
 			}
 
+			if (info->params.crc_type & HDLC_CRC_RETURN_EX) {
+				*p = (status & BIT1) ? RX_CRC_ERROR : RX_OK;
+				framesize++;
+			}
+
 #ifdef CONFIG_HDLC
 			if (info->netcount)
 				hdlcdev_rx(info,info->tmp_rbuf, framesize);
@@ -4671,13 +4708,13 @@
 static int adapter_test(struct slgt_info *info)
 {
 	DBGINFO(("testing %s\n", info->device_name));
-	if ((info->init_error = register_test(info)) < 0) {
+	if (register_test(info) < 0) {
 		printk("register test failure %s addr=%08X\n",
 			info->device_name, info->phys_reg_addr);
-	} else if ((info->init_error = irq_test(info)) < 0) {
+	} else if (irq_test(info) < 0) {
 		printk("IRQ test failure %s IRQ=%d\n",
 			info->device_name, info->irq_level);
-	} else if ((info->init_error = loopback_test(info)) < 0) {
+	} else if (loopback_test(info) < 0) {
 		printk("loopback test failure %s\n", info->device_name);
 	}
 	return info->init_error;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 8587401..21bf15a 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -988,7 +988,7 @@
 	if (sanity_check(info, tty->name, "write"))
 		goto cleanup;
 
-	if (!tty || !info->tx_buf)
+	if (!info->tx_buf)
 		goto cleanup;
 
 	if (info->params.mode == MGSL_MODE_HDLC) {
@@ -1067,7 +1067,7 @@
 	if (sanity_check(info, tty->name, "put_char"))
 		return;
 
-	if (!tty || !info->tx_buf)
+	if (!info->tx_buf)
 		return;
 
 	spin_lock_irqsave(&info->lock,flags);
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index f58ad7f..ef68d15 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -343,7 +343,7 @@
 
 	val = (unsigned char)tmp;
 	spin_lock_irqsave(&event_lock, flags);
-	SET_PORT_BITS(TLCLK_REG1, 0xef, val << 1);
+	SET_PORT_BITS(TLCLK_REG1, 0xdf, val << 1);
 	spin_unlock_irqrestore(&event_lock, flags);
 
 	return strnlen(buf, count);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a88b94a..8d19f72 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -267,7 +267,6 @@
 	p->used = 0;
 	p->size = size;
 	p->next = NULL;
-	p->active = 0;
 	p->commit = 0;
 	p->read = 0;
 	p->char_buf_ptr = (char *)(p->data);
@@ -327,10 +326,9 @@
 	/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
 	   remove this conditional if its worth it. This would be invisible
 	   to the callers */
-	if ((b = tty->buf.tail) != NULL) {
+	if ((b = tty->buf.tail) != NULL)
 		left = b->size - b->used;
-		b->active = 1;
-	} else
+	else
 		left = 0;
 
 	if (left < size) {
@@ -338,12 +336,10 @@
 		if ((n = tty_buffer_find(tty, size)) != NULL) {
 			if (b != NULL) {
 				b->next = n;
-				b->active = 0;
 				b->commit = b->used;
 			} else
 				tty->buf.head = n;
 			tty->buf.tail = n;
-			n->active = 1;
 		} else
 			size = left;
 	}
@@ -404,10 +400,8 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&tty->buf.lock, flags);
-	if (tty->buf.tail != NULL) {
-		tty->buf.tail->active = 0;
+	if (tty->buf.tail != NULL)
 		tty->buf.tail->commit = tty->buf.tail->used;
-	}
 	spin_unlock_irqrestore(&tty->buf.lock, flags);
 	schedule_delayed_work(&tty->buf.work, 1);
 }
@@ -784,11 +778,8 @@
 	}
 
 	clear_bit(TTY_LDISC, &tty->flags);
-	clear_bit(TTY_DONT_FLIP, &tty->flags);
-	if (o_tty) {
+	if (o_tty)
 		clear_bit(TTY_LDISC, &o_tty->flags);
-		clear_bit(TTY_DONT_FLIP, &o_tty->flags);
-	}
 	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 
 	/*
@@ -1955,7 +1946,6 @@
 	 * race with the set_ldisc code path.
 	 */
 	clear_bit(TTY_LDISC, &tty->flags);
-	clear_bit(TTY_DONT_FLIP, &tty->flags);
 	cancel_delayed_work(&tty->buf.work);
 
 	/*
@@ -2621,10 +2611,9 @@
 			tty->driver->break_ctl(tty, 0);
 			return 0;
 		case TCSBRK:   /* SVID version: non-zero arg --> no break */
-			/*
-			 * XXX is the above comment correct, or the
-			 * code below correct?  Is this ioctl used at
-			 * all by anyone?
+			/* non-zero arg means wait for all output data
+			 * to be sent (performed above) but don't send break.
+			 * This is used by the tcdrain() termios function.
 			 */
 			if (!arg)
 				return send_break(tty, 250);
@@ -2776,8 +2765,7 @@
 	struct tty_struct *tty = (struct tty_struct *) private_;
 	unsigned long 	flags;
 	struct tty_ldisc *disc;
-	struct tty_buffer *tbuf;
-	int count;
+	struct tty_buffer *tbuf, *head;
 	char *char_buf;
 	unsigned char *flag_buf;
 
@@ -2785,32 +2773,37 @@
 	if (disc == NULL)	/*  !TTY_LDISC */
 		return;
 
-	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
-		/*
-		 * Do it after the next timer tick:
-		 */
-		schedule_delayed_work(&tty->buf.work, 1);
-		goto out;
-	}
 	spin_lock_irqsave(&tty->buf.lock, flags);
-	while((tbuf = tty->buf.head) != NULL) {
-		while ((count = tbuf->commit - tbuf->read) != 0) {
-			char_buf = tbuf->char_buf_ptr + tbuf->read;
-			flag_buf = tbuf->flag_buf_ptr + tbuf->read;
-			tbuf->read += count;
+	head = tty->buf.head;
+	if (head != NULL) {
+		tty->buf.head = NULL;
+		for (;;) {
+			int count = head->commit - head->read;
+			if (!count) {
+				if (head->next == NULL)
+					break;
+				tbuf = head;
+				head = head->next;
+				tty_buffer_free(tty, tbuf);
+				continue;
+			}
+			if (!tty->receive_room) {
+				schedule_delayed_work(&tty->buf.work, 1);
+				break;
+			}
+			if (count > tty->receive_room)
+				count = tty->receive_room;
+			char_buf = head->char_buf_ptr + head->read;
+			flag_buf = head->flag_buf_ptr + head->read;
+			head->read += count;
 			spin_unlock_irqrestore(&tty->buf.lock, flags);
 			disc->receive_buf(tty, char_buf, flag_buf, count);
 			spin_lock_irqsave(&tty->buf.lock, flags);
 		}
-		if (tbuf->active)
-			break;
-		tty->buf.head = tbuf->next;
-		if (tty->buf.head == NULL)
-			tty->buf.tail = NULL;
-		tty_buffer_free(tty, tbuf);
+		tty->buf.head = head;
 	}
 	spin_unlock_irqrestore(&tty->buf.lock, flags);
-out:
+
 	tty_ldisc_deref(disc);
 }
 
@@ -2903,10 +2896,8 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&tty->buf.lock, flags);
-	if (tty->buf.tail != NULL) {
-		tty->buf.tail->active = 0;
+	if (tty->buf.tail != NULL)
 		tty->buf.tail->commit = tty->buf.tail->used;
-	}
 	spin_unlock_irqrestore(&tty->buf.lock, flags);
 
 	if (tty->low_latency)
@@ -2961,12 +2952,14 @@
  *	This field is optional, if there is no known struct device for this
  *	tty device it can be set to NULL safely.
  *
+ * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
+ *
  * This call is required to be made to register an individual tty device if
  * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set.  If that
  * bit is not set, this function should not be called.
  */
-void tty_register_device(struct tty_driver *driver, unsigned index,
-			 struct device *device)
+struct class_device *tty_register_device(struct tty_driver *driver,
+					 unsigned index, struct device *device)
 {
 	char name[64];
 	dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
@@ -2974,7 +2967,7 @@
 	if (index >= driver->num) {
 		printk(KERN_ERR "Attempt to register invalid tty line number "
 		       " (%d).\n", index);
-		return;
+		return ERR_PTR(-EINVAL);
 	}
 
 	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
@@ -2984,7 +2977,8 @@
 		pty_line_name(driver, index, name);
 	else
 		tty_line_name(driver, index, name);
-	class_device_create(tty_class, NULL, dev, device, "%s", name);
+
+	return class_device_create(tty_class, NULL, dev, device, "%s", name);
 }
 
 /**
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 60aabdb..11c7e9d 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -989,7 +989,7 @@
  * support.
  */
 static struct vio_device_id viotape_device_table[] __devinitdata = {
-	{ "viotape", "" },
+	{ "byte", "IBM,iSeries-viotape" },
 	{ "", "" }
 };
 MODULE_DEVICE_TABLE(vio, viotape_device_table);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6c94879..714d95f 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -98,7 +98,22 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#define MAX_NR_CON_DRIVER 16
 
+#define CON_DRIVER_FLAG_MODULE 1
+#define CON_DRIVER_FLAG_INIT 2
+
+struct con_driver {
+	const struct consw *con;
+	const char *desc;
+	struct class_device *class_dev;
+	int node;
+	int first;
+	int last;
+	int flag;
+};
+
+static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER];
 const struct consw *conswitchp;
 
 /* A bitmap for codes <32. A bit of 1 indicates that the code
@@ -2557,7 +2572,7 @@
 {
 	const char *display_desc = NULL;
 	struct vc_data *vc;
-	unsigned int currcons = 0;
+	unsigned int currcons = 0, i;
 
 	acquire_console_sem();
 
@@ -2569,6 +2584,22 @@
 		return 0;
 	}
 
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		struct con_driver *con_driver = &registered_con_driver[i];
+
+		if (con_driver->con == NULL) {
+			con_driver->con = conswitchp;
+			con_driver->desc = display_desc;
+			con_driver->flag = CON_DRIVER_FLAG_INIT;
+			con_driver->first = 0;
+			con_driver->last = MAX_NR_CONSOLES - 1;
+			break;
+		}
+	}
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++)
+		con_driver_map[i] = conswitchp;
+
 	init_timer(&console_timer);
 	console_timer.function = blank_screen_t;
 	if (blankinterval) {
@@ -2656,38 +2687,53 @@
 }
 
 #ifndef VT_SINGLE_DRIVER
+#include <linux/device.h>
 
-/*
- *	If we support more console drivers, this function is used
- *	when a driver wants to take over some existing consoles
- *	and become default driver for newly opened ones.
- */
+static struct class *vtconsole_class;
 
-int take_over_console(const struct consw *csw, int first, int last, int deflt)
+static int bind_con_driver(const struct consw *csw, int first, int last,
+			   int deflt)
 {
-	int i, j = -1;
-	const char *desc;
-	struct module *owner;
+	struct module *owner = csw->owner;
+	const char *desc = NULL;
+	struct con_driver *con_driver;
+	int i, j = -1, k = -1, retval = -ENODEV;
 
-	owner = csw->owner;
 	if (!try_module_get(owner))
 		return -ENODEV;
 
 	acquire_console_sem();
 
-	desc = csw->con_startup();
-	if (!desc) {
-		release_console_sem();
-		module_put(owner);
-		return -ENODEV;
+	/* check if driver is registered */
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		con_driver = &registered_con_driver[i];
+
+		if (con_driver->con == csw) {
+			desc = con_driver->desc;
+			retval = 0;
+			break;
+		}
 	}
+
+	if (retval)
+		goto err;
+
+	if (!(con_driver->flag & CON_DRIVER_FLAG_INIT)) {
+		csw->con_startup();
+		con_driver->flag |= CON_DRIVER_FLAG_INIT;
+	}
+
 	if (deflt) {
 		if (conswitchp)
 			module_put(conswitchp->owner);
+
 		__module_get(owner);
 		conswitchp = csw;
 	}
 
+	first = max(first, con_driver->first);
+	last = min(last, con_driver->last);
+
 	for (i = first; i <= last; i++) {
 		int old_was_color;
 		struct vc_data *vc = vc_cons[i].d;
@@ -2701,15 +2747,17 @@
 			continue;
 
 		j = i;
-		if (CON_IS_VISIBLE(vc))
+
+		if (CON_IS_VISIBLE(vc)) {
+			k = i;
 			save_screen(vc);
+		}
+
 		old_was_color = vc->vc_can_do_color;
 		vc->vc_sw->con_deinit(vc);
 		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
-		vc->vc_visible_origin = vc->vc_origin;
-		vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
-		vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
 		visual_init(vc, i, 0);
+		set_origin(vc);
 		update_attr(vc);
 
 		/* If the console changed between mono <-> color, then
@@ -2718,37 +2766,507 @@
 		 */
 		if (old_was_color != vc->vc_can_do_color)
 			clear_buffer_attributes(vc);
-
-		if (CON_IS_VISIBLE(vc))
-			update_screen(vc);
 	}
+
 	printk("Console: switching ");
 	if (!deflt)
 		printk("consoles %d-%d ", first+1, last+1);
-	if (j >= 0)
+	if (j >= 0) {
+		struct vc_data *vc = vc_cons[j].d;
+
 		printk("to %s %s %dx%d\n",
-		       vc_cons[j].d->vc_can_do_color ? "colour" : "mono",
-		       desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows);
-	else
+		       vc->vc_can_do_color ? "colour" : "mono",
+		       desc, vc->vc_cols, vc->vc_rows);
+
+		if (k >= 0) {
+			vc = vc_cons[k].d;
+			update_screen(vc);
+		}
+	} else
 		printk("to %s\n", desc);
 
+	retval = 0;
+err:
 	release_console_sem();
-
 	module_put(owner);
-	return 0;
+	return retval;
+};
+
+#ifdef CONFIG_VT_HW_CONSOLE_BINDING
+static int con_is_graphics(const struct consw *csw, int first, int last)
+{
+	int i, retval = 0;
+
+	for (i = first; i <= last; i++) {
+		struct vc_data *vc = vc_cons[i].d;
+
+		if (vc && vc->vc_mode == KD_GRAPHICS) {
+			retval = 1;
+			break;
+		}
+	}
+
+	return retval;
 }
 
-void give_up_console(const struct consw *csw)
+static int unbind_con_driver(const struct consw *csw, int first, int last,
+			     int deflt)
 {
-	int i;
+	struct module *owner = csw->owner;
+	const struct consw *defcsw = NULL;
+	struct con_driver *con_driver = NULL, *con_back = NULL;
+	int i, retval = -ENODEV;
 
-	for(i = 0; i < MAX_NR_CONSOLES; i++)
+	if (!try_module_get(owner))
+		return -ENODEV;
+
+	acquire_console_sem();
+
+	/* check if driver is registered and if it is unbindable */
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		con_driver = &registered_con_driver[i];
+
+		if (con_driver->con == csw &&
+		    con_driver->flag & CON_DRIVER_FLAG_MODULE) {
+			retval = 0;
+			break;
+		}
+	}
+
+	if (retval) {
+		release_console_sem();
+		goto err;
+	}
+
+	retval = -ENODEV;
+
+	/* check if backup driver exists */
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		con_back = &registered_con_driver[i];
+
+		if (con_back->con &&
+		    !(con_back->flag & CON_DRIVER_FLAG_MODULE)) {
+			defcsw = con_back->con;
+			retval = 0;
+			break;
+		}
+	}
+
+	if (retval) {
+		release_console_sem();
+		goto err;
+	}
+
+	if (!con_is_bound(csw)) {
+		release_console_sem();
+		goto err;
+	}
+
+	first = max(first, con_driver->first);
+	last = min(last, con_driver->last);
+
+	for (i = first; i <= last; i++) {
 		if (con_driver_map[i] == csw) {
 			module_put(csw->owner);
 			con_driver_map[i] = NULL;
 		}
+	}
+
+	if (!con_is_bound(defcsw)) {
+		const struct consw *defconsw = conswitchp;
+
+		defcsw->con_startup();
+		con_back->flag |= CON_DRIVER_FLAG_INIT;
+		/*
+		 * vgacon may change the default driver to point
+		 * to dummycon, we restore it here...
+		 */
+		conswitchp = defconsw;
+	}
+
+	if (!con_is_bound(csw))
+		con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
+
+	release_console_sem();
+	/* ignore return value, binding should not fail */
+	bind_con_driver(defcsw, first, last, deflt);
+err:
+	module_put(owner);
+	return retval;
+
 }
 
+static int vt_bind(struct con_driver *con)
+{
+	const struct consw *defcsw = NULL, *csw = NULL;
+	int i, more = 1, first = -1, last = -1, deflt = 0;
+
+ 	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
+	    con_is_graphics(con->con, con->first, con->last))
+		goto err;
+
+	csw = con->con;
+
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		struct con_driver *con = &registered_con_driver[i];
+
+		if (con->con && !(con->flag & CON_DRIVER_FLAG_MODULE)) {
+			defcsw = con->con;
+			break;
+		}
+	}
+
+	if (!defcsw)
+		goto err;
+
+	while (more) {
+		more = 0;
+
+		for (i = con->first; i <= con->last; i++) {
+			if (con_driver_map[i] == defcsw) {
+				if (first == -1)
+					first = i;
+				last = i;
+				more = 1;
+			} else if (first != -1)
+				break;
+		}
+
+		if (first == 0 && last == MAX_NR_CONSOLES -1)
+			deflt = 1;
+
+		if (first != -1)
+			bind_con_driver(csw, first, last, deflt);
+
+		first = -1;
+		last = -1;
+		deflt = 0;
+	}
+
+err:
+	return 0;
+}
+
+static int vt_unbind(struct con_driver *con)
+{
+	const struct consw *csw = NULL;
+	int i, more = 1, first = -1, last = -1, deflt = 0;
+
+ 	if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
+	    con_is_graphics(con->con, con->first, con->last))
+		goto err;
+
+	csw = con->con;
+
+	while (more) {
+		more = 0;
+
+		for (i = con->first; i <= con->last; i++) {
+			if (con_driver_map[i] == csw) {
+				if (first == -1)
+					first = i;
+				last = i;
+				more = 1;
+			} else if (first != -1)
+				break;
+		}
+
+		if (first == 0 && last == MAX_NR_CONSOLES -1)
+			deflt = 1;
+
+		if (first != -1)
+			unbind_con_driver(csw, first, last, deflt);
+
+		first = -1;
+		last = -1;
+		deflt = 0;
+	}
+
+err:
+	return 0;
+}
+#else
+static inline int vt_bind(struct con_driver *con)
+{
+	return 0;
+}
+static inline int vt_unbind(struct con_driver *con)
+{
+	return 0;
+}
+#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
+
+static ssize_t store_bind(struct class_device *class_device,
+			  const char *buf, size_t count)
+{
+	struct con_driver *con = class_get_devdata(class_device);
+	int bind = simple_strtoul(buf, NULL, 0);
+
+	if (bind)
+		vt_bind(con);
+	else
+		vt_unbind(con);
+
+	return count;
+}
+
+static ssize_t show_bind(struct class_device *class_device, char *buf)
+{
+	struct con_driver *con = class_get_devdata(class_device);
+	int bind = con_is_bound(con->con);
+
+	return snprintf(buf, PAGE_SIZE, "%i\n", bind);
+}
+
+static ssize_t show_name(struct class_device *class_device, char *buf)
+{
+	struct con_driver *con = class_get_devdata(class_device);
+
+	return snprintf(buf, PAGE_SIZE, "%s %s\n",
+			(con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
+			 con->desc);
+
+}
+
+static struct class_device_attribute class_device_attrs[] = {
+	__ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
+	__ATTR(name, S_IRUGO, show_name, NULL),
+};
+
+static int vtconsole_init_class_device(struct con_driver *con)
+{
+	int i;
+
+	class_set_devdata(con->class_dev, con);
+	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+		class_device_create_file(con->class_dev,
+					 &class_device_attrs[i]);
+
+	return 0;
+}
+
+static void vtconsole_deinit_class_device(struct con_driver *con)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+		class_device_remove_file(con->class_dev,
+					 &class_device_attrs[i]);
+}
+
+/**
+ * con_is_bound - checks if driver is bound to the console
+ * @csw: console driver
+ *
+ * RETURNS: zero if unbound, nonzero if bound
+ *
+ * Drivers can call this and if zero, they should release
+ * all resources allocated on con_startup()
+ */
+int con_is_bound(const struct consw *csw)
+{
+	int i, bound = 0;
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+		if (con_driver_map[i] == csw) {
+			bound = 1;
+			break;
+		}
+	}
+
+	return bound;
+}
+EXPORT_SYMBOL(con_is_bound);
+
+/**
+ * register_con_driver - register console driver to console layer
+ * @csw: console driver
+ * @first: the first console to take over, minimum value is 0
+ * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
+ *
+ * DESCRIPTION: This function registers a console driver which can later
+ * bind to a range of consoles specified by @first and @last. It will
+ * also initialize the console driver by calling con_startup().
+ */
+int register_con_driver(const struct consw *csw, int first, int last)
+{
+	struct module *owner = csw->owner;
+	struct con_driver *con_driver;
+	const char *desc;
+	int i, retval = 0;
+
+	if (!try_module_get(owner))
+		return -ENODEV;
+
+	acquire_console_sem();
+
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		con_driver = &registered_con_driver[i];
+
+		/* already registered */
+		if (con_driver->con == csw)
+			retval = -EINVAL;
+	}
+
+	if (retval)
+		goto err;
+
+	desc = csw->con_startup();
+
+	if (!desc)
+		goto err;
+
+	retval = -EINVAL;
+
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		con_driver = &registered_con_driver[i];
+
+		if (con_driver->con == NULL) {
+			con_driver->con = csw;
+			con_driver->desc = desc;
+			con_driver->node = i;
+			con_driver->flag = CON_DRIVER_FLAG_MODULE |
+			                   CON_DRIVER_FLAG_INIT;
+			con_driver->first = first;
+			con_driver->last = last;
+			retval = 0;
+			break;
+		}
+	}
+
+	if (retval)
+		goto err;
+
+	con_driver->class_dev = class_device_create(vtconsole_class, NULL,
+						    MKDEV(0, con_driver->node),
+						    NULL, "vtcon%i",
+						    con_driver->node);
+
+	if (IS_ERR(con_driver->class_dev)) {
+		printk(KERN_WARNING "Unable to create class_device for %s; "
+		       "errno = %ld\n", con_driver->desc,
+		       PTR_ERR(con_driver->class_dev));
+		con_driver->class_dev = NULL;
+	} else {
+		vtconsole_init_class_device(con_driver);
+	}
+err:
+	release_console_sem();
+	module_put(owner);
+	return retval;
+}
+EXPORT_SYMBOL(register_con_driver);
+
+/**
+ * unregister_con_driver - unregister console driver from console layer
+ * @csw: console driver
+ *
+ * DESCRIPTION: All drivers that registers to the console layer must
+ * call this function upon exit, or if the console driver is in a state
+ * where it won't be able to handle console services, such as the
+ * framebuffer console without loaded framebuffer drivers.
+ *
+ * The driver must unbind first prior to unregistration.
+ */
+int unregister_con_driver(const struct consw *csw)
+{
+	int i, retval = -ENODEV;
+
+	acquire_console_sem();
+
+	/* cannot unregister a bound driver */
+	if (con_is_bound(csw))
+		goto err;
+
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		struct con_driver *con_driver = &registered_con_driver[i];
+
+		if (con_driver->con == csw &&
+		    con_driver->flag & CON_DRIVER_FLAG_MODULE) {
+			vtconsole_deinit_class_device(con_driver);
+			class_device_destroy(vtconsole_class,
+					     MKDEV(0, con_driver->node));
+			con_driver->con = NULL;
+			con_driver->desc = NULL;
+			con_driver->class_dev = NULL;
+			con_driver->node = 0;
+			con_driver->flag = 0;
+			con_driver->first = 0;
+			con_driver->last = 0;
+			retval = 0;
+			break;
+		}
+	}
+err:
+	release_console_sem();
+	return retval;
+}
+EXPORT_SYMBOL(unregister_con_driver);
+
+/*
+ *	If we support more console drivers, this function is used
+ *	when a driver wants to take over some existing consoles
+ *	and become default driver for newly opened ones.
+ *
+ *      take_over_console is basically a register followed by unbind
+ */
+int take_over_console(const struct consw *csw, int first, int last, int deflt)
+{
+	int err;
+
+	err = register_con_driver(csw, first, last);
+
+	if (!err)
+		bind_con_driver(csw, first, last, deflt);
+
+	return err;
+}
+
+/*
+ * give_up_console is a wrapper to unregister_con_driver. It will only
+ * work if driver is fully unbound.
+ */
+void give_up_console(const struct consw *csw)
+{
+	unregister_con_driver(csw);
+}
+
+static int __init vtconsole_class_init(void)
+{
+	int i;
+
+	vtconsole_class = class_create(THIS_MODULE, "vtconsole");
+	if (IS_ERR(vtconsole_class)) {
+		printk(KERN_WARNING "Unable to create vt console class; "
+		       "errno = %ld\n", PTR_ERR(vtconsole_class));
+		vtconsole_class = NULL;
+	}
+
+	/* Add system drivers to sysfs */
+	for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
+		struct con_driver *con = &registered_con_driver[i];
+
+		if (con->con && !con->class_dev) {
+			con->class_dev =
+				class_device_create(vtconsole_class, NULL,
+						    MKDEV(0, con->node), NULL,
+						    "vtcon%i", con->node);
+
+			if (IS_ERR(con->class_dev)) {
+				printk(KERN_WARNING "Unable to create "
+				       "class_device for %s; errno = %ld\n",
+				       con->desc, PTR_ERR(con->class_dev));
+				con->class_dev = NULL;
+			} else {
+				vtconsole_init_class_device(con);
+			}
+		}
+	}
+
+	return 0;
+}
+postcore_initcall(vtconsole_class_init);
+
 #endif
 
 /*
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
new file mode 100644
index 0000000..a522254
--- /dev/null
+++ b/drivers/clocksource/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_X86_CYCLONE_TIMER)	+= cyclone.o
+obj-$(CONFIG_X86_PM_TIMER)	+= acpi_pm.o
+obj-$(CONFIG_SCx200HR_TIMER)	+= scx200_hrt.o
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
new file mode 100644
index 0000000..7ad3be8
--- /dev/null
+++ b/drivers/clocksource/acpi_pm.c
@@ -0,0 +1,177 @@
+/*
+ * linux/drivers/clocksource/acpi_pm.c
+ *
+ * This file contains the ACPI PM based clocksource.
+ *
+ * This code was largely moved from the i386 timer_pm.c file
+ * which was (C) Dominik Brodowski <linux@brodo.de> 2003
+ * and contained the following comments:
+ *
+ * Driver to use the Power Management Timer (PMTMR) available in some
+ * southbridges as primary timing source for the Linux kernel.
+ *
+ * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
+ * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
+ *
+ * This file is licensed under the GPL v2.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+/* Number of PMTMR ticks expected during calibration run */
+#define PMTMR_TICKS_PER_SEC 3579545
+
+/*
+ * The I/O port the PMTMR resides at.
+ * The location is detected during setup_arch(),
+ * in arch/i386/acpi/boot.c
+ */
+u32 pmtmr_ioport __read_mostly;
+
+#define ACPI_PM_MASK CLOCKSOURCE_MASK(24) /* limit it to 24 bits */
+
+static inline u32 read_pmtmr(void)
+{
+	/* mask the output to 24 bits */
+	return inl(pmtmr_ioport) & ACPI_PM_MASK;
+}
+
+static cycle_t acpi_pm_read_verified(void)
+{
+	u32 v1 = 0, v2 = 0, v3 = 0;
+
+	/*
+	 * It has been reported that because of various broken
+	 * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM clock
+	 * source is not latched, you must read it multiple
+	 * times to ensure a safe value is read:
+	 */
+	do {
+		v1 = read_pmtmr();
+		v2 = read_pmtmr();
+		v3 = read_pmtmr();
+	} while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1)
+			|| (v3 > v1 && v3 < v2));
+
+	return (cycle_t)v2;
+}
+
+static cycle_t acpi_pm_read(void)
+{
+	return (cycle_t)read_pmtmr();
+}
+
+static struct clocksource clocksource_acpi_pm = {
+	.name		= "acpi_pm",
+	.rating		= 200,
+	.read		= acpi_pm_read,
+	.mask		= (cycle_t)ACPI_PM_MASK,
+	.mult		= 0, /*to be caluclated*/
+	.shift		= 22,
+	.is_continuous	= 1,
+};
+
+
+#ifdef CONFIG_PCI
+static int acpi_pm_good;
+static int __init acpi_pm_good_setup(char *__str)
+{
+       acpi_pm_good = 1;
+       return 1;
+}
+__setup("acpi_pm_good", acpi_pm_good_setup);
+
+static inline void acpi_pm_need_workaround(void)
+{
+	clocksource_acpi_pm.read = acpi_pm_read_verified;
+	clocksource_acpi_pm.rating = 110;
+}
+
+/*
+ * PIIX4 Errata:
+ *
+ * The power management timer may return improper results when read.
+ * Although the timer value settles properly after incrementing,
+ * while incrementing there is a 3 ns window every 69.8 ns where the
+ * timer value is indeterminate (a 4.2% chance that the data will be
+ * incorrect when read). As a result, the ACPI free running count up
+ * timer specification is violated due to erroneous reads.
+ */
+static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev)
+{
+	u8 rev;
+
+	if (acpi_pm_good)
+		return;
+
+	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+	/* the bug has been fixed in PIIX4M */
+	if (rev < 3) {
+		printk(KERN_WARNING "* Found PM-Timer Bug on the chipset."
+		       " Due to workarounds for a bug,\n"
+		       "* this clock source is slow. Consider trying"
+		       " other clock sources\n");
+
+		acpi_pm_need_workaround();
+	}
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3,
+			acpi_pm_check_blacklist);
+
+static void __devinit acpi_pm_check_graylist(struct pci_dev *dev)
+{
+	if (acpi_pm_good)
+		return;
+
+	printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to"
+	       " workarounds for a bug,\n"
+	       "* this clock source is slow. If you are sure your timer"
+	       " does not have\n"
+	       "* this bug, please use \"acpi_pm_good\" to disable the"
+	       " workaround\n");
+
+	acpi_pm_need_workaround();
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
+			acpi_pm_check_graylist);
+#endif
+
+
+static int __init init_acpi_pm_clocksource(void)
+{
+	u32 value1, value2;
+	unsigned int i;
+
+	if (!pmtmr_ioport)
+		return -ENODEV;
+
+	clocksource_acpi_pm.mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC,
+						clocksource_acpi_pm.shift);
+
+	/* "verify" this timing source: */
+	value1 = read_pmtmr();
+	for (i = 0; i < 10000; i++) {
+		value2 = read_pmtmr();
+		if (value2 == value1)
+			continue;
+		if (value2 > value1)
+			goto pm_good;
+		if ((value2 < value1) && ((value2) < 0xFFF))
+			goto pm_good;
+		printk(KERN_INFO "PM-Timer had inconsistent results:"
+			" 0x%#x, 0x%#x - aborting.\n", value1, value2);
+		return -EINVAL;
+	}
+	printk(KERN_INFO "PM-Timer had no reasonable result:"
+			" 0x%#x - aborting.\n", value1);
+	return -ENODEV;
+
+pm_good:
+	return clocksource_register(&clocksource_acpi_pm);
+}
+
+module_init(init_acpi_pm_clocksource);
diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c
new file mode 100644
index 0000000..bf4d3d5
--- /dev/null
+++ b/drivers/clocksource/cyclone.c
@@ -0,0 +1,119 @@
+#include <linux/clocksource.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/timex.h>
+#include <linux/init.h>
+
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+#include "mach_timer.h"
+
+#define CYCLONE_CBAR_ADDR	0xFEB00CD0	/* base address ptr */
+#define CYCLONE_PMCC_OFFSET	0x51A0		/* offset to control register */
+#define CYCLONE_MPCS_OFFSET	0x51A8		/* offset to select register */
+#define CYCLONE_MPMC_OFFSET	0x51D0		/* offset to count register */
+#define CYCLONE_TIMER_FREQ	99780000	/* 100Mhz, but not really */
+#define CYCLONE_TIMER_MASK	CLOCKSOURCE_MASK(32) /* 32 bit mask */
+
+int use_cyclone = 0;
+static void __iomem *cyclone_ptr;
+
+static cycle_t read_cyclone(void)
+{
+	return (cycle_t)readl(cyclone_ptr);
+}
+
+static struct clocksource clocksource_cyclone = {
+	.name		= "cyclone",
+	.rating		= 250,
+	.read		= read_cyclone,
+	.mask		= CYCLONE_TIMER_MASK,
+	.mult		= 10,
+	.shift		= 0,
+	.is_continuous	= 1,
+};
+
+static int __init init_cyclone_clocksource(void)
+{
+	unsigned long base;	/* saved value from CBAR */
+	unsigned long offset;
+	u32 __iomem* volatile cyclone_timer;	/* Cyclone MPMC0 register */
+	u32 __iomem* reg;
+	int i;
+
+	/* make sure we're on a summit box: */
+	if (!use_cyclone)
+		return -ENODEV;
+
+	printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
+
+	/* find base address: */
+	offset = CYCLONE_CBAR_ADDR;
+	reg = ioremap_nocache(offset, sizeof(reg));
+	if (!reg) {
+		printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
+		return -ENODEV;
+	}
+	/* even on 64bit systems, this is only 32bits: */
+	base = readl(reg);
+	if (!base) {
+		printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
+		return -ENODEV;
+	}
+	iounmap(reg);
+
+	/* setup PMCC: */
+	offset = base + CYCLONE_PMCC_OFFSET;
+	reg = ioremap_nocache(offset, sizeof(reg));
+	if (!reg) {
+		printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
+		return -ENODEV;
+	}
+	writel(0x00000001,reg);
+	iounmap(reg);
+
+	/* setup MPCS: */
+	offset = base + CYCLONE_MPCS_OFFSET;
+	reg = ioremap_nocache(offset, sizeof(reg));
+	if (!reg) {
+		printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
+		return -ENODEV;
+	}
+	writel(0x00000001,reg);
+	iounmap(reg);
+
+	/* map in cyclone_timer: */
+	offset = base + CYCLONE_MPMC_OFFSET;
+	cyclone_timer = ioremap_nocache(offset, sizeof(u64));
+	if (!cyclone_timer) {
+		printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
+		return -ENODEV;
+	}
+
+	/* quick test to make sure its ticking: */
+	for (i = 0; i < 3; i++){
+		u32 old = readl(cyclone_timer);
+		int stall = 100;
+
+		while (stall--)
+			barrier();
+
+		if (readl(cyclone_timer) == old) {
+			printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
+			iounmap(cyclone_timer);
+			cyclone_timer = NULL;
+			return -ENODEV;
+		}
+	}
+	cyclone_ptr = cyclone_timer;
+
+	/* sort out mult/shift values: */
+	clocksource_cyclone.shift = 22;
+	clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ,
+						clocksource_cyclone.shift);
+
+	return clocksource_register(&clocksource_cyclone);
+}
+
+module_init(init_cyclone_clocksource);
diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c
new file mode 100644
index 0000000..d418b82
--- /dev/null
+++ b/drivers/clocksource/scx200_hrt.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2006 Jim Cromie
+ *
+ * This is a clocksource driver for the Geode SCx200's 1 or 27 MHz
+ * high-resolution timer.  The Geode SC-1100 (at least) has a buggy
+ * time stamp counter (TSC), which loses time unless 'idle=poll' is
+ * given as a boot-arg. In its absence, the Generic Timekeeping code
+ * will detect and de-rate the bad TSC, allowing this timer to take
+ * over timekeeping duties.
+ *
+ * Based on work by John Stultz, and Ted Phelps (in a 2.6.12-rc6 patch)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/scx200.h>
+
+#define NAME "scx200_hrt"
+
+static int mhz27;
+module_param(mhz27, int, 0);	/* load time only */
+MODULE_PARM_DESC(mhz27, "count at 27.0 MHz (default is 1.0 MHz)");
+
+static int ppm;
+module_param(ppm, int, 0);	/* load time only */
+MODULE_PARM_DESC(ppm, "+-adjust to actual XO freq (ppm)");
+
+/* HiRes Timer configuration register address */
+#define SCx200_TMCNFG_OFFSET (SCx200_TIMER_OFFSET + 5)
+
+/* and config settings */
+#define HR_TMEN (1 << 0)	/* timer interrupt enable */
+#define HR_TMCLKSEL (1 << 1)	/* 1|0 counts at 27|1 MHz */
+#define HR_TM27MPD (1 << 2)	/* 1 turns off input clock (power-down) */
+
+/* The base timer frequency, * 27 if selected */
+#define HRT_FREQ   1000000
+
+static cycle_t read_hrt(void)
+{
+	/* Read the timer value */
+	return (cycle_t) inl(scx200_cb_base + SCx200_TIMER_OFFSET);
+}
+
+#define HRT_SHIFT_1	22
+#define HRT_SHIFT_27	26
+
+static struct clocksource cs_hrt = {
+	.name		= "scx200_hrt",
+	.rating		= 250,
+	.read		= read_hrt,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.is_continuous	= 1,
+	/* mult, shift are set based on mhz27 flag */
+};
+
+static int __init init_hrt_clocksource(void)
+{
+	/* Make sure scx200 has initializedd the configuration block */
+	if (!scx200_cb_present())
+		return -ENODEV;
+
+	/* Reserve the timer's ISA io-region for ourselves */
+	if (!request_region(scx200_cb_base + SCx200_TIMER_OFFSET,
+			    SCx200_TIMER_SIZE,
+			    "NatSemi SCx200 High-Resolution Timer")) {
+		printk(KERN_WARNING NAME ": unable to lock timer region\n");
+		return -ENODEV;
+	}
+
+	/* write timer config */
+	outb(HR_TMEN | (mhz27) ? HR_TMCLKSEL : 0,
+	     scx200_cb_base + SCx200_TMCNFG_OFFSET);
+
+	if (mhz27) {
+		cs_hrt.shift = HRT_SHIFT_27;
+		cs_hrt.mult = clocksource_hz2mult((HRT_FREQ + ppm) * 27,
+						  cs_hrt.shift);
+	} else {
+		cs_hrt.shift = HRT_SHIFT_1;
+		cs_hrt.mult = clocksource_hz2mult(HRT_FREQ + ppm,
+						  cs_hrt.shift);
+	}
+	printk(KERN_INFO "enabling scx200 high-res timer (%s MHz +%d ppm)\n",
+		mhz27 ? "27":"1", ppm);
+
+	return clocksource_register(&cs_hrt);
+}
+
+module_init(init_hrt_clocksource);
+
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>");
+MODULE_DESCRIPTION("clocksource on SCx200 HiRes Timer");
+MODULE_LICENSE("GPL");
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 4b4d7db..498aa37 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/ktime.h>
 #include <linux/init.h>
+#include <linux/connector.h>
 #include <asm/atomic.h>
 
 #include <linux/cn_proc.h>
diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
index 9f2f00d..05f8ce2 100644
--- a/drivers/connector/cn_queue.c
+++ b/drivers/connector/cn_queue.c
@@ -127,7 +127,7 @@
 
 	if (found) {
 		cn_queue_free_callback(cbq);
-		atomic_dec_and_test(&dev->refcnt);
+		atomic_dec(&dev->refcnt);
 	}
 }
 
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 3589707..b49bacf 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -121,6 +121,7 @@
 	kfree_skb(skb);
 	return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(cn_netlink_send);
 
 /*
  * Callback helper - queues work and setup destructor for given data.
@@ -308,6 +309,9 @@
 	int err;
 	struct cn_dev *dev = &cdev;
 
+	if (!cn_already_initialized)
+		return -EAGAIN;
+
 	err = cn_queue_add_callback(dev->cbdev, name, id, callback);
 	if (err)
 		return err;
@@ -316,6 +320,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(cn_add_callback);
 
 /*
  * Callback remove routing - removes callback
@@ -332,6 +337,7 @@
 	cn_queue_del_callback(dev->cbdev, id);
 	cn_notify(id, 1);
 }
+EXPORT_SYMBOL_GPL(cn_del_callback);
 
 /*
  * Checks two connector's control messages to be the same.
@@ -435,7 +441,7 @@
 	mutex_unlock(&notify_lock);
 }
 
-static int __init cn_init(void)
+static int __devinit cn_init(void)
 {
 	struct cn_dev *dev = &cdev;
 	int err;
@@ -456,21 +462,22 @@
 			sock_release(dev->nls->sk_socket);
 		return -EINVAL;
 	}
+	
+	cn_already_initialized = 1;
 
 	err = cn_add_callback(&dev->id, "connector", &cn_callback);
 	if (err) {
+		cn_already_initialized = 0;
 		cn_queue_free_dev(dev->cbdev);
 		if (dev->nls->sk_socket)
 			sock_release(dev->nls->sk_socket);
 		return -EINVAL;
 	}
 
-	cn_already_initialized = 1;
-
 	return 0;
 }
 
-static void __exit cn_fini(void)
+static void __devexit cn_fini(void)
 {
 	struct cn_dev *dev = &cdev;
 
@@ -482,9 +489,5 @@
 		sock_release(dev->nls->sk_socket);
 }
 
-module_init(cn_init);
+subsys_initcall(cn_init);
 module_exit(cn_fini);
-
-EXPORT_SYMBOL_GPL(cn_add_callback);
-EXPORT_SYMBOL_GPL(cn_del_callback);
-EXPORT_SYMBOL_GPL(cn_netlink_send);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 29b2fa5..35e0b9c 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -257,7 +257,7 @@
 		if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) {
 			if ((policy) && (policy->cpu == freqs->cpu) &&
 			    (policy->cur) && (policy->cur != freqs->old)) {
-				dprintk(KERN_WARNING "Warning: CPU frequency is"
+				dprintk("Warning: CPU frequency is"
 					" %u, cpufreq assumed %u kHz.\n",
 					freqs->old, policy->cur);
 				freqs->old = policy->cur;
@@ -874,7 +874,7 @@
 {
 	struct cpufreq_freqs freqs;
 
-	dprintk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
+	dprintk("Warning: CPU frequency out of sync: cpufreq and timing "
 	       "core thinks of %u, is %u kHz.\n", old_freq, new_freq);
 
 	freqs.cpu = cpu;
@@ -1006,7 +1006,7 @@
 		struct cpufreq_freqs freqs;
 
 		if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-			dprintk(KERN_DEBUG "Warning: CPU frequency is %u, "
+			dprintk("Warning: CPU frequency is %u, "
 			       "cpufreq assumed %u kHz.\n",
 			       cur_freq, cpu_policy->cur);
 
@@ -1087,7 +1087,7 @@
 			struct cpufreq_freqs freqs;
 
 			if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
-				dprintk(KERN_WARNING "Warning: CPU frequency"
+				dprintk("Warning: CPU frequency"
 				       "is %u, cpufreq assumed %u kHz.\n",
 				       cur_freq, cpu_policy->cur);
 
@@ -1497,6 +1497,7 @@
 }
 EXPORT_SYMBOL(cpufreq_update_policy);
 
+#ifdef CONFIG_HOTPLUG_CPU
 static int cpufreq_cpu_callback(struct notifier_block *nfb,
 					unsigned long action, void *hcpu)
 {
@@ -1532,10 +1533,11 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block cpufreq_cpu_notifier =
+static struct notifier_block __cpuinitdata cpufreq_cpu_notifier =
 {
     .notifier_call = cpufreq_cpu_callback,
 };
+#endif /* CONFIG_HOTPLUG_CPU */
 
 /*********************************************************************
  *               REGISTER / UNREGISTER CPUFREQ DRIVER                *
@@ -1596,7 +1598,7 @@
 	}
 
 	if (!ret) {
-		register_cpu_notifier(&cpufreq_cpu_notifier);
+		register_hotcpu_notifier(&cpufreq_cpu_notifier);
 		dprintk("driver %s up and running\n", driver_data->name);
 		cpufreq_debug_enable_ratelimit();
 	}
@@ -1628,7 +1630,7 @@
 	dprintk("unregistering driver %s\n", driver->name);
 
 	sysdev_driver_unregister(&cpu_sysdev_class, &cpufreq_sysdev_driver);
-	unregister_cpu_notifier(&cpufreq_cpu_notifier);
+	unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
 
 	spin_lock_irqsave(&cpufreq_driver_lock, flags);
 	cpufreq_driver = NULL;
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index e07a354..b3ebc8f 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/sysfs.h>
+#include <linux/cpu.h>
 #include <linux/sched.h>
 #include <linux/kmod.h>
 #include <linux/workqueue.h>
@@ -72,6 +73,14 @@
 
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
+/*
+ * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug
+ * lock and dbs_mutex. cpu_hotplug lock should always be held before
+ * dbs_mutex. If any function that can potentially take cpu_hotplug lock
+ * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then
+ * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
+ * is recursive for the same process. -Venki
+ */
 static DEFINE_MUTEX 	(dbs_mutex);
 static DECLARE_WORK	(dbs_work, do_dbs_timer, NULL);
 
@@ -414,12 +423,14 @@
 static void do_dbs_timer(void *data)
 { 
 	int i;
+	lock_cpu_hotplug();
 	mutex_lock(&dbs_mutex);
 	for_each_online_cpu(i)
 		dbs_check_cpu(i);
 	schedule_delayed_work(&dbs_work, 
 			usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
 	mutex_unlock(&dbs_mutex);
+	unlock_cpu_hotplug();
 } 
 
 static inline void dbs_timer_init(void)
@@ -514,6 +525,7 @@
 		break;
 
 	case CPUFREQ_GOV_LIMITS:
+		lock_cpu_hotplug();
 		mutex_lock(&dbs_mutex);
 		if (policy->max < this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(
@@ -524,6 +536,7 @@
 					this_dbs_info->cur_policy,
 				       	policy->min, CPUFREQ_RELATION_L);
 		mutex_unlock(&dbs_mutex);
+		unlock_cpu_hotplug();
 		break;
 	}
 	return 0;
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 3e6ffca..693e540 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -21,6 +21,7 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/sysfs.h>
+#include <linux/cpu.h>
 #include <linux/sched.h>
 #include <linux/kmod.h>
 #include <linux/workqueue.h>
@@ -71,6 +72,14 @@
 
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
+/*
+ * DEADLOCK ALERT! There is a ordering requirement between cpu_hotplug
+ * lock and dbs_mutex. cpu_hotplug lock should always be held before
+ * dbs_mutex. If any function that can potentially take cpu_hotplug lock
+ * (like __cpufreq_driver_target()) is being called with dbs_mutex taken, then
+ * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock
+ * is recursive for the same process. -Venki
+ */
 static DEFINE_MUTEX (dbs_mutex);
 static DECLARE_WORK	(dbs_work, do_dbs_timer, NULL);
 
@@ -363,12 +372,14 @@
 static void do_dbs_timer(void *data)
 {
 	int i;
+	lock_cpu_hotplug();
 	mutex_lock(&dbs_mutex);
 	for_each_online_cpu(i)
 		dbs_check_cpu(i);
 	queue_delayed_work(dbs_workq, &dbs_work,
 			   usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
 	mutex_unlock(&dbs_mutex);
+	unlock_cpu_hotplug();
 }
 
 static inline void dbs_timer_init(void)
@@ -469,6 +480,7 @@
 		break;
 
 	case CPUFREQ_GOV_LIMITS:
+		lock_cpu_hotplug();
 		mutex_lock(&dbs_mutex);
 		if (policy->max < this_dbs_info->cur_policy->cur)
 			__cpufreq_driver_target(
@@ -479,6 +491,7 @@
 					this_dbs_info->cur_policy,
 					policy->min, CPUFREQ_RELATION_L);
 		mutex_unlock(&dbs_mutex);
+		unlock_cpu_hotplug();
 		break;
 	}
 	return 0;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 9694b6e..145061b 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -74,7 +74,7 @@
 show_total_trans(struct cpufreq_policy *policy, char *buf)
 {
 	struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
-	if(!stat)
+	if (!stat)
 		return 0;
 	return sprintf(buf, "%d\n",
 			cpufreq_stats_table[stat->cpu]->total_trans);
@@ -86,7 +86,7 @@
 	ssize_t len = 0;
 	int i;
 	struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
-	if(!stat)
+	if (!stat)
 		return 0;
 	cpufreq_stats_update(stat->cpu);
 	for (i = 0; i < stat->state_num; i++) {
@@ -104,7 +104,7 @@
 	int i, j;
 
 	struct cpufreq_stats *stat = cpufreq_stats_table[policy->cpu];
-	if(!stat)
+	if (!stat)
 		return 0;
 	cpufreq_stats_update(stat->cpu);
 	len += snprintf(buf + len, PAGE_SIZE - len, "   From  :    To\n");
@@ -350,7 +350,7 @@
 		return ret;
 	}
 
-	register_cpu_notifier(&cpufreq_stat_cpu_notifier);
+	register_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
 	lock_cpu_hotplug();
 	for_each_online_cpu(cpu) {
 		cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_ONLINE,
@@ -368,7 +368,7 @@
 			CPUFREQ_POLICY_NOTIFIER);
 	cpufreq_unregister_notifier(&notifier_trans_block,
 			CPUFREQ_TRANSITION_NOTIFIER);
-	unregister_cpu_notifier(&cpufreq_stat_cpu_notifier);
+	unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
 	lock_cpu_hotplug();
 	for_each_online_cpu(cpu) {
 		cpufreq_stat_cpu_callback(&cpufreq_stat_cpu_notifier, CPU_DEAD,
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index a4818ce..551f4cc 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -20,7 +20,7 @@
 {
 	unsigned int min_freq = ~0;
 	unsigned int max_freq = 0;
-	unsigned int i = 0;
+	unsigned int i;
 
 	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
 		unsigned int freq = table[i].frequency;
@@ -51,7 +51,7 @@
 				   struct cpufreq_frequency_table *table)
 {
 	unsigned int next_larger = ~0;
-	unsigned int i = 0;
+	unsigned int i;
 	unsigned int count = 0;
 
 	dprintk("request for verification of policy (%u - %u kHz) for cpu %u\n", policy->min, policy->max, policy->cpu);
@@ -91,20 +91,24 @@
 				   unsigned int relation,
 				   unsigned int *index)
 {
-	struct cpufreq_frequency_table optimal = { .index = ~0, };
-	struct cpufreq_frequency_table suboptimal = { .index = ~0, };
+	struct cpufreq_frequency_table optimal = {
+		.index = ~0,
+		.frequency = 0,
+	};
+	struct cpufreq_frequency_table suboptimal = {
+		.index = ~0,
+		.frequency = 0,
+	};
 	unsigned int i;
 
 	dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu);
 
 	switch (relation) {
 	case CPUFREQ_RELATION_H:
-		optimal.frequency = 0;
 		suboptimal.frequency = ~0;
 		break;
 	case CPUFREQ_RELATION_L:
 		optimal.frequency = ~0;
-		suboptimal.frequency = 0;
 		break;
 	}
 
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index 5158a9d..17ee684 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -60,15 +60,14 @@
 #define AES_EXTENDED_KEY_SIZE_B	(AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
 
 struct aes_ctx {
-	uint32_t e_data[AES_EXTENDED_KEY_SIZE];
-	uint32_t d_data[AES_EXTENDED_KEY_SIZE];
 	struct {
 		struct cword encrypt;
 		struct cword decrypt;
 	} cword;
-	uint32_t *E;
-	uint32_t *D;
+	u32 *D;
 	int key_length;
+	u32 E[AES_EXTENDED_KEY_SIZE];
+	u32 d_data[AES_EXTENDED_KEY_SIZE];
 };
 
 /* ====== Key management routines ====== */
@@ -282,19 +281,20 @@
 	return 0;
 }
 
-static inline struct aes_ctx *aes_ctx(void *ctx)
+static inline struct aes_ctx *aes_ctx(struct crypto_tfm *tfm)
 {
+	unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm);
 	unsigned long align = PADLOCK_ALIGNMENT;
 
 	if (align <= crypto_tfm_ctx_alignment())
 		align = 1;
-	return (struct aes_ctx *)ALIGN((unsigned long)ctx, align);
+	return (struct aes_ctx *)ALIGN(addr, align);
 }
 
-static int
-aes_set_key(void *ctx_arg, const uint8_t *in_key, unsigned int key_len, uint32_t *flags)
+static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+		       unsigned int key_len, u32 *flags)
 {
-	struct aes_ctx *ctx = aes_ctx(ctx_arg);
+	struct aes_ctx *ctx = aes_ctx(tfm);
 	const __le32 *key = (const __le32 *)in_key;
 	uint32_t i, t, u, v, w;
 	uint32_t P[AES_EXTENDED_KEY_SIZE];
@@ -312,8 +312,7 @@
 	 * itself we must supply the plain key for both encryption
 	 * and decryption.
 	 */
-	ctx->E = ctx->e_data;
-	ctx->D = ctx->e_data;
+	ctx->D = ctx->E;
 
 	E_KEY[0] = le32_to_cpu(key[0]);
 	E_KEY[1] = le32_to_cpu(key[1]);
@@ -414,24 +413,22 @@
 	return iv;
 }
 
-static void
-aes_encrypt(void *ctx_arg, uint8_t *out, const uint8_t *in)
+static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct aes_ctx *ctx = aes_ctx(ctx_arg);
+	struct aes_ctx *ctx = aes_ctx(tfm);
 	padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt, 1);
 }
 
-static void
-aes_decrypt(void *ctx_arg, uint8_t *out, const uint8_t *in)
+static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
 {
-	struct aes_ctx *ctx = aes_ctx(ctx_arg);
+	struct aes_ctx *ctx = aes_ctx(tfm);
 	padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt, 1);
 }
 
 static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
 				    const u8 *in, unsigned int nbytes)
 {
-	struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm));
+	struct aes_ctx *ctx = aes_ctx(desc->tfm);
 	padlock_xcrypt_ecb(in, out, ctx->E, &ctx->cword.encrypt,
 			   nbytes / AES_BLOCK_SIZE);
 	return nbytes & ~(AES_BLOCK_SIZE - 1);
@@ -440,7 +437,7 @@
 static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
 				    const u8 *in, unsigned int nbytes)
 {
-	struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm));
+	struct aes_ctx *ctx = aes_ctx(desc->tfm);
 	padlock_xcrypt_ecb(in, out, ctx->D, &ctx->cword.decrypt,
 			   nbytes / AES_BLOCK_SIZE);
 	return nbytes & ~(AES_BLOCK_SIZE - 1);
@@ -449,7 +446,7 @@
 static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
 				    const u8 *in, unsigned int nbytes)
 {
-	struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm));
+	struct aes_ctx *ctx = aes_ctx(desc->tfm);
 	u8 *iv;
 
 	iv = padlock_xcrypt_cbc(in, out, ctx->E, desc->info,
@@ -462,7 +459,7 @@
 static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
 				    const u8 *in, unsigned int nbytes)
 {
-	struct aes_ctx *ctx = aes_ctx(crypto_tfm_ctx(desc->tfm));
+	struct aes_ctx *ctx = aes_ctx(desc->tfm);
 	padlock_xcrypt_cbc(in, out, ctx->D, desc->info, &ctx->cword.decrypt,
 			   nbytes / AES_BLOCK_SIZE);
 	return nbytes & ~(AES_BLOCK_SIZE - 1);
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
new file mode 100644
index 0000000..30d021d
--- /dev/null
+++ b/drivers/dma/Kconfig
@@ -0,0 +1,34 @@
+#
+# DMA engine configuration
+#
+
+menu "DMA Engine support"
+
+config DMA_ENGINE
+	bool "Support for DMA engines"
+	---help---
+	  DMA engines offload copy operations from the CPU to dedicated
+	  hardware, allowing the copies to happen asynchronously.
+
+comment "DMA Clients"
+
+config NET_DMA
+	bool "Network: TCP receive copy offload"
+	depends on DMA_ENGINE && NET
+	default y
+	---help---
+	  This enables the use of DMA engines in the network stack to
+	  offload receive copy-to-user operations, freeing CPU cycles.
+	  Since this is the main user of the DMA engine, it should be enabled;
+	  say Y here.
+
+comment "DMA Devices"
+
+config INTEL_IOATDMA
+	tristate "Intel I/OAT DMA support"
+	depends on DMA_ENGINE && PCI
+	default m
+	---help---
+	  Enable support for the Intel(R) I/OAT DMA engine.
+
+endmenu
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
new file mode 100644
index 0000000..bdcfdbd
--- /dev/null
+++ b/drivers/dma/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
+obj-$(CONFIG_NET_DMA) += iovlock.o
+obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
new file mode 100644
index 0000000..5829143
--- /dev/null
+++ b/drivers/dma/dmaengine.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This code implements the DMA subsystem. It provides a HW-neutral interface
+ * for other kernel code to use asynchronous memory copy capabilities,
+ * if present, and allows different HW DMA drivers to register as providing
+ * this capability.
+ *
+ * Due to the fact we are accelerating what is already a relatively fast
+ * operation, the code goes to great lengths to avoid additional overhead,
+ * such as locking.
+ *
+ * LOCKING:
+ *
+ * The subsystem keeps two global lists, dma_device_list and dma_client_list.
+ * Both of these are protected by a mutex, dma_list_mutex.
+ *
+ * Each device has a channels list, which runs unlocked but is never modified
+ * once the device is registered, it's just setup by the driver.
+ *
+ * Each client has a channels list, it's only modified under the client->lock
+ * and in an RCU callback, so it's safe to read under rcu_read_lock().
+ *
+ * Each device has a kref, which is initialized to 1 when the device is
+ * registered. A kref_put is done for each class_device registered.  When the
+ * class_device is released, the coresponding kref_put is done in the release
+ * method. Every time one of the device's channels is allocated to a client,
+ * a kref_get occurs.  When the channel is freed, the coresponding kref_put
+ * happens. The device's release function does a completion, so
+ * unregister_device does a remove event, class_device_unregister, a kref_put
+ * for the first reference, then waits on the completion for all other
+ * references to finish.
+ *
+ * Each channel has an open-coded implementation of Rusty Russell's "bigref,"
+ * with a kref and a per_cpu local_t.  A single reference is set when on an
+ * ADDED event, and removed with a REMOVE event.  Net DMA client takes an
+ * extra reference per outstanding transaction.  The relase function does a
+ * kref_put on the device. -ChrisL
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/percpu.h>
+#include <linux/rcupdate.h>
+#include <linux/mutex.h>
+
+static DEFINE_MUTEX(dma_list_mutex);
+static LIST_HEAD(dma_device_list);
+static LIST_HEAD(dma_client_list);
+
+/* --- sysfs implementation --- */
+
+static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
+{
+	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+	unsigned long count = 0;
+	int i;
+
+	for_each_possible_cpu(i)
+		count += per_cpu_ptr(chan->local, i)->memcpy_count;
+
+	return sprintf(buf, "%lu\n", count);
+}
+
+static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
+{
+	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+	unsigned long count = 0;
+	int i;
+
+	for_each_possible_cpu(i)
+		count += per_cpu_ptr(chan->local, i)->bytes_transferred;
+
+	return sprintf(buf, "%lu\n", count);
+}
+
+static ssize_t show_in_use(struct class_device *cd, char *buf)
+{
+	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+
+	return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
+}
+
+static struct class_device_attribute dma_class_attrs[] = {
+	__ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
+	__ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
+	__ATTR(in_use, S_IRUGO, show_in_use, NULL),
+	__ATTR_NULL
+};
+
+static void dma_async_device_cleanup(struct kref *kref);
+
+static void dma_class_dev_release(struct class_device *cd)
+{
+	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
+	kref_put(&chan->device->refcount, dma_async_device_cleanup);
+}
+
+static struct class dma_devclass = {
+	.name            = "dma",
+	.class_dev_attrs = dma_class_attrs,
+	.release = dma_class_dev_release,
+};
+
+/* --- client and device registration --- */
+
+/**
+ * dma_client_chan_alloc - try to allocate a channel to a client
+ * @client: &dma_client
+ *
+ * Called with dma_list_mutex held.
+ */
+static struct dma_chan *dma_client_chan_alloc(struct dma_client *client)
+{
+	struct dma_device *device;
+	struct dma_chan *chan;
+	unsigned long flags;
+	int desc;	/* allocated descriptor count */
+
+	/* Find a channel, any DMA engine will do */
+	list_for_each_entry(device, &dma_device_list, global_node) {
+		list_for_each_entry(chan, &device->channels, device_node) {
+			if (chan->client)
+				continue;
+
+			desc = chan->device->device_alloc_chan_resources(chan);
+			if (desc >= 0) {
+				kref_get(&device->refcount);
+				kref_init(&chan->refcount);
+				chan->slow_ref = 0;
+				INIT_RCU_HEAD(&chan->rcu);
+				chan->client = client;
+				spin_lock_irqsave(&client->lock, flags);
+				list_add_tail_rcu(&chan->client_node,
+				                  &client->channels);
+				spin_unlock_irqrestore(&client->lock, flags);
+				return chan;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * dma_client_chan_free - release a DMA channel
+ * @chan: &dma_chan
+ */
+void dma_chan_cleanup(struct kref *kref)
+{
+	struct dma_chan *chan = container_of(kref, struct dma_chan, refcount);
+	chan->device->device_free_chan_resources(chan);
+	chan->client = NULL;
+	kref_put(&chan->device->refcount, dma_async_device_cleanup);
+}
+
+static void dma_chan_free_rcu(struct rcu_head *rcu)
+{
+	struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu);
+	int bias = 0x7FFFFFFF;
+	int i;
+	for_each_possible_cpu(i)
+		bias -= local_read(&per_cpu_ptr(chan->local, i)->refcount);
+	atomic_sub(bias, &chan->refcount.refcount);
+	kref_put(&chan->refcount, dma_chan_cleanup);
+}
+
+static void dma_client_chan_free(struct dma_chan *chan)
+{
+	atomic_add(0x7FFFFFFF, &chan->refcount.refcount);
+	chan->slow_ref = 1;
+	call_rcu(&chan->rcu, dma_chan_free_rcu);
+}
+
+/**
+ * dma_chans_rebalance - reallocate channels to clients
+ *
+ * When the number of DMA channel in the system changes,
+ * channels need to be rebalanced among clients
+ */
+static void dma_chans_rebalance(void)
+{
+	struct dma_client *client;
+	struct dma_chan *chan;
+	unsigned long flags;
+
+	mutex_lock(&dma_list_mutex);
+
+	list_for_each_entry(client, &dma_client_list, global_node) {
+		while (client->chans_desired > client->chan_count) {
+			chan = dma_client_chan_alloc(client);
+			if (!chan)
+				break;
+			client->chan_count++;
+			client->event_callback(client,
+	                                       chan,
+	                                       DMA_RESOURCE_ADDED);
+		}
+		while (client->chans_desired < client->chan_count) {
+			spin_lock_irqsave(&client->lock, flags);
+			chan = list_entry(client->channels.next,
+			                  struct dma_chan,
+			                  client_node);
+			list_del_rcu(&chan->client_node);
+			spin_unlock_irqrestore(&client->lock, flags);
+			client->chan_count--;
+			client->event_callback(client,
+			                       chan,
+			                       DMA_RESOURCE_REMOVED);
+			dma_client_chan_free(chan);
+		}
+	}
+
+	mutex_unlock(&dma_list_mutex);
+}
+
+/**
+ * dma_async_client_register - allocate and register a &dma_client
+ * @event_callback: callback for notification of channel addition/removal
+ */
+struct dma_client *dma_async_client_register(dma_event_callback event_callback)
+{
+	struct dma_client *client;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (!client)
+		return NULL;
+
+	INIT_LIST_HEAD(&client->channels);
+	spin_lock_init(&client->lock);
+	client->chans_desired = 0;
+	client->chan_count = 0;
+	client->event_callback = event_callback;
+
+	mutex_lock(&dma_list_mutex);
+	list_add_tail(&client->global_node, &dma_client_list);
+	mutex_unlock(&dma_list_mutex);
+
+	return client;
+}
+
+/**
+ * dma_async_client_unregister - unregister a client and free the &dma_client
+ * @client:
+ *
+ * Force frees any allocated DMA channels, frees the &dma_client memory
+ */
+void dma_async_client_unregister(struct dma_client *client)
+{
+	struct dma_chan *chan;
+
+	if (!client)
+		return;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(chan, &client->channels, client_node)
+		dma_client_chan_free(chan);
+	rcu_read_unlock();
+
+	mutex_lock(&dma_list_mutex);
+	list_del(&client->global_node);
+	mutex_unlock(&dma_list_mutex);
+
+	kfree(client);
+	dma_chans_rebalance();
+}
+
+/**
+ * dma_async_client_chan_request - request DMA channels
+ * @client: &dma_client
+ * @number: count of DMA channels requested
+ *
+ * Clients call dma_async_client_chan_request() to specify how many
+ * DMA channels they need, 0 to free all currently allocated.
+ * The resulting allocations/frees are indicated to the client via the
+ * event callback.
+ */
+void dma_async_client_chan_request(struct dma_client *client,
+			unsigned int number)
+{
+	client->chans_desired = number;
+	dma_chans_rebalance();
+}
+
+/**
+ * dma_async_device_register -
+ * @device: &dma_device
+ */
+int dma_async_device_register(struct dma_device *device)
+{
+	static int id;
+	int chancnt = 0;
+	struct dma_chan* chan;
+
+	if (!device)
+		return -ENODEV;
+
+	init_completion(&device->done);
+	kref_init(&device->refcount);
+	device->dev_id = id++;
+
+	/* represent channels in sysfs. Probably want devs too */
+	list_for_each_entry(chan, &device->channels, device_node) {
+		chan->local = alloc_percpu(typeof(*chan->local));
+		if (chan->local == NULL)
+			continue;
+
+		chan->chan_id = chancnt++;
+		chan->class_dev.class = &dma_devclass;
+		chan->class_dev.dev = NULL;
+		snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
+		         device->dev_id, chan->chan_id);
+
+		kref_get(&device->refcount);
+		class_device_register(&chan->class_dev);
+	}
+
+	mutex_lock(&dma_list_mutex);
+	list_add_tail(&device->global_node, &dma_device_list);
+	mutex_unlock(&dma_list_mutex);
+
+	dma_chans_rebalance();
+
+	return 0;
+}
+
+/**
+ * dma_async_device_unregister -
+ * @device: &dma_device
+ */
+static void dma_async_device_cleanup(struct kref *kref)
+{
+	struct dma_device *device;
+
+	device = container_of(kref, struct dma_device, refcount);
+	complete(&device->done);
+}
+
+void dma_async_device_unregister(struct dma_device* device)
+{
+	struct dma_chan *chan;
+	unsigned long flags;
+
+	mutex_lock(&dma_list_mutex);
+	list_del(&device->global_node);
+	mutex_unlock(&dma_list_mutex);
+
+	list_for_each_entry(chan, &device->channels, device_node) {
+		if (chan->client) {
+			spin_lock_irqsave(&chan->client->lock, flags);
+			list_del(&chan->client_node);
+			chan->client->chan_count--;
+			spin_unlock_irqrestore(&chan->client->lock, flags);
+			chan->client->event_callback(chan->client,
+			                             chan,
+			                             DMA_RESOURCE_REMOVED);
+			dma_client_chan_free(chan);
+		}
+		class_device_unregister(&chan->class_dev);
+	}
+	dma_chans_rebalance();
+
+	kref_put(&device->refcount, dma_async_device_cleanup);
+	wait_for_completion(&device->done);
+}
+
+static int __init dma_bus_init(void)
+{
+	mutex_init(&dma_list_mutex);
+	return class_register(&dma_devclass);
+}
+
+subsys_initcall(dma_bus_init);
+
+EXPORT_SYMBOL(dma_async_client_register);
+EXPORT_SYMBOL(dma_async_client_unregister);
+EXPORT_SYMBOL(dma_async_client_chan_request);
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf);
+EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg);
+EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg);
+EXPORT_SYMBOL(dma_async_memcpy_complete);
+EXPORT_SYMBOL(dma_async_memcpy_issue_pending);
+EXPORT_SYMBOL(dma_async_device_register);
+EXPORT_SYMBOL(dma_async_device_unregister);
+EXPORT_SYMBOL(dma_chan_cleanup);
diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c
new file mode 100644
index 0000000..2801d14
--- /dev/null
+++ b/drivers/dma/ioatdma.c
@@ -0,0 +1,839 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This driver supports an Intel I/OAT DMA engine, which does asynchronous
+ * copy operations.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include "ioatdma.h"
+#include "ioatdma_io.h"
+#include "ioatdma_registers.h"
+#include "ioatdma_hw.h"
+
+#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common)
+#define to_ioat_device(dev) container_of(dev, struct ioat_device, common)
+#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node)
+
+/* internal functions */
+static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void __devexit ioat_remove(struct pci_dev *pdev);
+
+static int enumerate_dma_channels(struct ioat_device *device)
+{
+	u8 xfercap_scale;
+	u32 xfercap;
+	int i;
+	struct ioat_dma_chan *ioat_chan;
+
+	device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET);
+	xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET);
+	xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale));
+
+	for (i = 0; i < device->common.chancnt; i++) {
+		ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL);
+		if (!ioat_chan) {
+			device->common.chancnt = i;
+			break;
+		}
+
+		ioat_chan->device = device;
+		ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1));
+		ioat_chan->xfercap = xfercap;
+		spin_lock_init(&ioat_chan->cleanup_lock);
+		spin_lock_init(&ioat_chan->desc_lock);
+		INIT_LIST_HEAD(&ioat_chan->free_desc);
+		INIT_LIST_HEAD(&ioat_chan->used_desc);
+		/* This should be made common somewhere in dmaengine.c */
+		ioat_chan->common.device = &device->common;
+		ioat_chan->common.client = NULL;
+		list_add_tail(&ioat_chan->common.device_node,
+		              &device->common.channels);
+	}
+	return device->common.chancnt;
+}
+
+static struct ioat_desc_sw *ioat_dma_alloc_descriptor(
+	struct ioat_dma_chan *ioat_chan,
+	int flags)
+{
+	struct ioat_dma_descriptor *desc;
+	struct ioat_desc_sw *desc_sw;
+	struct ioat_device *ioat_device;
+	dma_addr_t phys;
+
+	ioat_device = to_ioat_device(ioat_chan->common.device);
+	desc = pci_pool_alloc(ioat_device->dma_pool, flags, &phys);
+	if (unlikely(!desc))
+		return NULL;
+
+	desc_sw = kzalloc(sizeof(*desc_sw), flags);
+	if (unlikely(!desc_sw)) {
+		pci_pool_free(ioat_device->dma_pool, desc, phys);
+		return NULL;
+	}
+
+	memset(desc, 0, sizeof(*desc));
+	desc_sw->hw = desc;
+	desc_sw->phys = phys;
+
+	return desc_sw;
+}
+
+#define INITIAL_IOAT_DESC_COUNT 128
+
+static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan);
+
+/* returns the actual number of allocated descriptors */
+static int ioat_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+	struct ioat_desc_sw *desc = NULL;
+	u16 chanctrl;
+	u32 chanerr;
+	int i;
+	LIST_HEAD(tmp_list);
+
+	/*
+	 * In-use bit automatically set by reading chanctrl
+	 * If 0, we got it, if 1, someone else did
+	 */
+	chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+	if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE)
+		return -EBUSY;
+
+        /* Setup register to interrupt and write completion status on error */
+	chanctrl = IOAT_CHANCTRL_CHANNEL_IN_USE |
+		IOAT_CHANCTRL_ERR_INT_EN |
+		IOAT_CHANCTRL_ANY_ERR_ABORT_EN |
+		IOAT_CHANCTRL_ERR_COMPLETION_EN;
+        ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+
+	chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET);
+	if (chanerr) {
+		printk("IOAT: CHANERR = %x, clearing\n", chanerr);
+		ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr);
+	}
+
+	/* Allocate descriptors */
+	for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) {
+		desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
+		if (!desc) {
+			printk(KERN_ERR "IOAT: Only %d initial descriptors\n", i);
+			break;
+		}
+		list_add_tail(&desc->node, &tmp_list);
+	}
+	spin_lock_bh(&ioat_chan->desc_lock);
+	list_splice(&tmp_list, &ioat_chan->free_desc);
+	spin_unlock_bh(&ioat_chan->desc_lock);
+
+	/* allocate a completion writeback area */
+	/* doing 2 32bit writes to mmio since 1 64b write doesn't work */
+	ioat_chan->completion_virt =
+		pci_pool_alloc(ioat_chan->device->completion_pool,
+		               GFP_KERNEL,
+		               &ioat_chan->completion_addr);
+	memset(ioat_chan->completion_virt, 0,
+	       sizeof(*ioat_chan->completion_virt));
+	ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW,
+	               ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF);
+	ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH,
+	               ((u64) ioat_chan->completion_addr) >> 32);
+
+	ioat_start_null_desc(ioat_chan);
+	return i;
+}
+
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan);
+
+static void ioat_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+	struct ioat_device *ioat_device = to_ioat_device(chan->device);
+	struct ioat_desc_sw *desc, *_desc;
+	u16 chanctrl;
+	int in_use_descs = 0;
+
+	ioat_dma_memcpy_cleanup(ioat_chan);
+
+	ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET);
+
+	spin_lock_bh(&ioat_chan->desc_lock);
+	list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) {
+		in_use_descs++;
+		list_del(&desc->node);
+		pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+		kfree(desc);
+	}
+	list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) {
+		list_del(&desc->node);
+		pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys);
+		kfree(desc);
+	}
+	spin_unlock_bh(&ioat_chan->desc_lock);
+
+	pci_pool_free(ioat_device->completion_pool,
+	              ioat_chan->completion_virt,
+	              ioat_chan->completion_addr);
+
+	/* one is ok since we left it on there on purpose */
+	if (in_use_descs > 1)
+		printk(KERN_ERR "IOAT: Freeing %d in use descriptors!\n",
+			in_use_descs - 1);
+
+	ioat_chan->last_completion = ioat_chan->completion_addr = 0;
+
+	/* Tell hw the chan is free */
+	chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET);
+	chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE;
+	ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl);
+}
+
+/**
+ * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+ * @dest: DMA destination address
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan,
+                                       dma_addr_t dest,
+                                       dma_addr_t src,
+                                       size_t len)
+{
+	struct ioat_desc_sw *first;
+	struct ioat_desc_sw *prev;
+	struct ioat_desc_sw *new;
+	dma_cookie_t cookie;
+	LIST_HEAD(new_chain);
+	u32 copy;
+	size_t orig_len;
+	dma_addr_t orig_src, orig_dst;
+	unsigned int desc_count = 0;
+	unsigned int append = 0;
+
+	if (!ioat_chan || !dest || !src)
+		return -EFAULT;
+
+	if (!len)
+		return ioat_chan->common.cookie;
+
+	orig_len = len;
+	orig_src = src;
+	orig_dst = dest;
+
+	first = NULL;
+	prev = NULL;
+
+	spin_lock_bh(&ioat_chan->desc_lock);
+
+	while (len) {
+		if (!list_empty(&ioat_chan->free_desc)) {
+			new = to_ioat_desc(ioat_chan->free_desc.next);
+			list_del(&new->node);
+		} else {
+			/* try to get another desc */
+			new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC);
+			/* will this ever happen? */
+			/* TODO add upper limit on these */
+			BUG_ON(!new);
+		}
+
+		copy = min((u32) len, ioat_chan->xfercap);
+
+		new->hw->size = copy;
+		new->hw->ctl = 0;
+		new->hw->src_addr = src;
+		new->hw->dst_addr = dest;
+		new->cookie = 0;
+
+		/* chain together the physical address list for the HW */
+		if (!first)
+			first = new;
+		else
+			prev->hw->next = (u64) new->phys;
+
+		prev = new;
+
+		len  -= copy;
+		dest += copy;
+		src  += copy;
+
+		list_add_tail(&new->node, &new_chain);
+		desc_count++;
+	}
+	new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS;
+	new->hw->next = 0;
+
+	/* cookie incr and addition to used_list must be atomic */
+
+	cookie = ioat_chan->common.cookie;
+	cookie++;
+	if (cookie < 0)
+		cookie = 1;
+	ioat_chan->common.cookie = new->cookie = cookie;
+
+	pci_unmap_addr_set(new, src, orig_src);
+	pci_unmap_addr_set(new, dst, orig_dst);
+	pci_unmap_len_set(new, src_len, orig_len);
+	pci_unmap_len_set(new, dst_len, orig_len);
+
+	/* write address into NextDescriptor field of last desc in chain */
+	to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys;
+	list_splice_init(&new_chain, ioat_chan->used_desc.prev);
+
+	ioat_chan->pending += desc_count;
+	if (ioat_chan->pending >= 20) {
+		append = 1;
+		ioat_chan->pending = 0;
+	}
+
+	spin_unlock_bh(&ioat_chan->desc_lock);
+
+	if (append)
+		ioatdma_chan_write8(ioat_chan,
+		                    IOAT_CHANCMD_OFFSET,
+		                    IOAT_CHANCMD_APPEND);
+	return cookie;
+}
+
+/**
+ * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs
+ * @chan: IOAT DMA channel handle
+ * @dest: DMA destination address
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan,
+                                               void *dest,
+                                               void *src,
+                                               size_t len)
+{
+	dma_addr_t dest_addr;
+	dma_addr_t src_addr;
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+	dest_addr = pci_map_single(ioat_chan->device->pdev,
+		dest, len, PCI_DMA_FROMDEVICE);
+	src_addr = pci_map_single(ioat_chan->device->pdev,
+		src, len, PCI_DMA_TODEVICE);
+
+	return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page
+ * @chan: IOAT DMA channel handle
+ * @page: pointer to the page to copy to
+ * @offset: offset into that page
+ * @src: DMA source address
+ * @len: transaction length in bytes
+ */
+
+static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan,
+                                              struct page *page,
+                                              unsigned int offset,
+                                              void *src,
+                                              size_t len)
+{
+	dma_addr_t dest_addr;
+	dma_addr_t src_addr;
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+	dest_addr = pci_map_page(ioat_chan->device->pdev,
+		page, offset, len, PCI_DMA_FROMDEVICE);
+	src_addr = pci_map_single(ioat_chan->device->pdev,
+		src, len, PCI_DMA_TODEVICE);
+
+	return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages
+ * @chan: IOAT DMA channel handle
+ * @dest_pg: pointer to the page to copy to
+ * @dest_off: offset into that page
+ * @src_pg: pointer to the page to copy from
+ * @src_off: offset into that page
+ * @len: transaction length in bytes. This is guaranteed to not make a copy
+ *	 across a page boundary.
+ */
+
+static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan,
+                                             struct page *dest_pg,
+                                             unsigned int dest_off,
+                                             struct page *src_pg,
+                                             unsigned int src_off,
+                                             size_t len)
+{
+	dma_addr_t dest_addr;
+	dma_addr_t src_addr;
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+	dest_addr = pci_map_page(ioat_chan->device->pdev,
+		dest_pg, dest_off, len, PCI_DMA_FROMDEVICE);
+	src_addr = pci_map_page(ioat_chan->device->pdev,
+		src_pg, src_off, len, PCI_DMA_TODEVICE);
+
+	return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len);
+}
+
+/**
+ * ioat_dma_memcpy_issue_pending - push potentially unrecognoized appended descriptors to hw
+ * @chan: DMA channel handle
+ */
+
+static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan)
+{
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+
+	if (ioat_chan->pending != 0) {
+		ioat_chan->pending = 0;
+		ioatdma_chan_write8(ioat_chan,
+		                    IOAT_CHANCMD_OFFSET,
+		                    IOAT_CHANCMD_APPEND);
+	}
+}
+
+static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan)
+{
+	unsigned long phys_complete;
+	struct ioat_desc_sw *desc, *_desc;
+	dma_cookie_t cookie = 0;
+
+	prefetch(chan->completion_virt);
+
+	if (!spin_trylock(&chan->cleanup_lock))
+		return;
+
+	/* The completion writeback can happen at any time,
+	   so reads by the driver need to be atomic operations
+	   The descriptor physical addresses are limited to 32-bits
+	   when the CPU can only do a 32-bit mov */
+
+#if (BITS_PER_LONG == 64)
+	phys_complete =
+	chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR;
+#else
+	phys_complete = chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK;
+#endif
+
+	if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) ==
+		IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) {
+		printk("IOAT: Channel halted, chanerr = %x\n",
+			ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET));
+
+		/* TODO do something to salvage the situation */
+	}
+
+	if (phys_complete == chan->last_completion) {
+		spin_unlock(&chan->cleanup_lock);
+		return;
+	}
+
+	spin_lock_bh(&chan->desc_lock);
+	list_for_each_entry_safe(desc, _desc, &chan->used_desc, node) {
+
+		/*
+		 * Incoming DMA requests may use multiple descriptors, due to
+		 * exceeding xfercap, perhaps. If so, only the last one will
+		 * have a cookie, and require unmapping.
+		 */
+		if (desc->cookie) {
+			cookie = desc->cookie;
+
+			/* yes we are unmapping both _page and _single alloc'd
+			   regions with unmap_page. Is this *really* that bad?
+			*/
+			pci_unmap_page(chan->device->pdev,
+					pci_unmap_addr(desc, dst),
+					pci_unmap_len(desc, dst_len),
+					PCI_DMA_FROMDEVICE);
+			pci_unmap_page(chan->device->pdev,
+					pci_unmap_addr(desc, src),
+					pci_unmap_len(desc, src_len),
+					PCI_DMA_TODEVICE);
+		}
+
+		if (desc->phys != phys_complete) {
+			/* a completed entry, but not the last, so cleanup */
+			list_del(&desc->node);
+			list_add_tail(&desc->node, &chan->free_desc);
+		} else {
+			/* last used desc. Do not remove, so we can append from
+			   it, but don't look at it next time, either */
+			desc->cookie = 0;
+
+			/* TODO check status bits? */
+			break;
+		}
+	}
+
+	spin_unlock_bh(&chan->desc_lock);
+
+	chan->last_completion = phys_complete;
+	if (cookie != 0)
+		chan->completed_cookie = cookie;
+
+	spin_unlock(&chan->cleanup_lock);
+}
+
+/**
+ * ioat_dma_is_complete - poll the status of a IOAT DMA transaction
+ * @chan: IOAT DMA channel handle
+ * @cookie: DMA transaction identifier
+ */
+
+static enum dma_status ioat_dma_is_complete(struct dma_chan *chan,
+                                            dma_cookie_t cookie,
+                                            dma_cookie_t *done,
+                                            dma_cookie_t *used)
+{
+	struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan);
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+	enum dma_status ret;
+
+	last_used = chan->cookie;
+	last_complete = ioat_chan->completed_cookie;
+
+	if (done)
+		*done= last_complete;
+	if (used)
+		*used = last_used;
+
+	ret = dma_async_is_complete(cookie, last_complete, last_used);
+	if (ret == DMA_SUCCESS)
+		return ret;
+
+	ioat_dma_memcpy_cleanup(ioat_chan);
+
+	last_used = chan->cookie;
+	last_complete = ioat_chan->completed_cookie;
+
+	if (done)
+		*done= last_complete;
+	if (used)
+		*used = last_used;
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+/* PCI API */
+
+static struct pci_device_id ioat_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) },
+	{ 0, }
+};
+
+static struct pci_driver ioat_pci_drv = {
+	.name 	= "ioatdma",
+	.id_table = ioat_pci_tbl,
+	.probe	= ioat_probe,
+	.remove	= __devexit_p(ioat_remove),
+};
+
+static irqreturn_t ioat_do_interrupt(int irq, void *data, struct pt_regs *regs)
+{
+	struct ioat_device *instance = data;
+	unsigned long attnstatus;
+	u8 intrctrl;
+
+	intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET);
+
+	if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN))
+		return IRQ_NONE;
+
+	if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) {
+		ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+		return IRQ_NONE;
+	}
+
+	attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET);
+
+	printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus);
+
+	ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl);
+	return IRQ_HANDLED;
+}
+
+static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan)
+{
+	struct ioat_desc_sw *desc;
+
+	spin_lock_bh(&ioat_chan->desc_lock);
+
+	if (!list_empty(&ioat_chan->free_desc)) {
+		desc = to_ioat_desc(ioat_chan->free_desc.next);
+		list_del(&desc->node);
+	} else {
+		/* try to get another desc */
+		spin_unlock_bh(&ioat_chan->desc_lock);
+		desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL);
+		spin_lock_bh(&ioat_chan->desc_lock);
+		/* will this ever happen? */
+		BUG_ON(!desc);
+	}
+
+	desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL;
+	desc->hw->next = 0;
+
+	list_add_tail(&desc->node, &ioat_chan->used_desc);
+	spin_unlock_bh(&ioat_chan->desc_lock);
+
+#if (BITS_PER_LONG == 64)
+	ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys);
+#else
+	ioatdma_chan_write32(ioat_chan,
+	                     IOAT_CHAINADDR_OFFSET_LOW,
+	                     (u32) desc->phys);
+	ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0);
+#endif
+	ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START);
+}
+
+/*
+ * Perform a IOAT transaction to verify the HW works.
+ */
+#define IOAT_TEST_SIZE 2000
+
+static int ioat_self_test(struct ioat_device *device)
+{
+	int i;
+	u8 *src;
+	u8 *dest;
+	struct dma_chan *dma_chan;
+	dma_cookie_t cookie;
+	int err = 0;
+
+	src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+	if (!src)
+		return -ENOMEM;
+	dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL);
+	if (!dest) {
+		kfree(src);
+		return -ENOMEM;
+	}
+
+	/* Fill in src buffer */
+	for (i = 0; i < IOAT_TEST_SIZE; i++)
+		src[i] = (u8)i;
+
+	/* Start copy, using first DMA channel */
+	dma_chan = container_of(device->common.channels.next,
+	                        struct dma_chan,
+	                        device_node);
+	if (ioat_dma_alloc_chan_resources(dma_chan) < 1) {
+		err = -ENODEV;
+		goto out;
+	}
+
+	cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE);
+	ioat_dma_memcpy_issue_pending(dma_chan);
+	msleep(1);
+
+	if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) {
+		printk(KERN_ERR "ioatdma: Self-test copy timed out, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+	if (memcmp(src, dest, IOAT_TEST_SIZE)) {
+		printk(KERN_ERR "ioatdma: Self-test copy failed compare, disabling\n");
+		err = -ENODEV;
+		goto free_resources;
+	}
+
+free_resources:
+	ioat_dma_free_chan_resources(dma_chan);
+out:
+	kfree(src);
+	kfree(dest);
+	return err;
+}
+
+static int __devinit ioat_probe(struct pci_dev *pdev,
+                                const struct pci_device_id *ent)
+{
+	int err;
+	unsigned long mmio_start, mmio_len;
+	void *reg_base;
+	struct ioat_device *device;
+
+	err = pci_enable_device(pdev);
+	if (err)
+		goto err_enable_device;
+
+	err = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+	if (err)
+		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	if (err)
+		goto err_set_dma_mask;
+
+	err = pci_request_regions(pdev, ioat_pci_drv.name);
+	if (err)
+		goto err_request_regions;
+
+	mmio_start = pci_resource_start(pdev, 0);
+	mmio_len = pci_resource_len(pdev, 0);
+
+	reg_base = ioremap(mmio_start, mmio_len);
+	if (!reg_base) {
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	device = kzalloc(sizeof(*device), GFP_KERNEL);
+	if (!device) {
+		err = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	/* DMA coherent memory pool for DMA descriptor allocations */
+	device->dma_pool = pci_pool_create("dma_desc_pool", pdev,
+		sizeof(struct ioat_dma_descriptor), 64, 0);
+	if (!device->dma_pool) {
+		err = -ENOMEM;
+		goto err_dma_pool;
+	}
+
+	device->completion_pool = pci_pool_create("completion_pool", pdev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES);
+	if (!device->completion_pool) {
+		err = -ENOMEM;
+		goto err_completion_pool;
+	}
+
+	device->pdev = pdev;
+	pci_set_drvdata(pdev, device);
+#ifdef CONFIG_PCI_MSI
+	if (pci_enable_msi(pdev) == 0) {
+		device->msi = 1;
+	} else {
+		device->msi = 0;
+	}
+#endif
+	err = request_irq(pdev->irq, &ioat_do_interrupt, SA_SHIRQ, "ioat",
+		device);
+	if (err)
+		goto err_irq;
+
+	device->reg_base = reg_base;
+
+	ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN);
+	pci_set_master(pdev);
+
+	INIT_LIST_HEAD(&device->common.channels);
+	enumerate_dma_channels(device);
+
+	device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources;
+	device->common.device_free_chan_resources = ioat_dma_free_chan_resources;
+	device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf;
+	device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg;
+	device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg;
+	device->common.device_memcpy_complete = ioat_dma_is_complete;
+	device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending;
+	printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n",
+		device->common.chancnt);
+
+	err = ioat_self_test(device);
+	if (err)
+		goto err_self_test;
+
+	dma_async_device_register(&device->common);
+
+	return 0;
+
+err_self_test:
+err_irq:
+	pci_pool_destroy(device->completion_pool);
+err_completion_pool:
+	pci_pool_destroy(device->dma_pool);
+err_dma_pool:
+	kfree(device);
+err_kzalloc:
+	iounmap(reg_base);
+err_ioremap:
+	pci_release_regions(pdev);
+err_request_regions:
+err_set_dma_mask:
+	pci_disable_device(pdev);
+err_enable_device:
+	return err;
+}
+
+static void __devexit ioat_remove(struct pci_dev *pdev)
+{
+	struct ioat_device *device;
+	struct dma_chan *chan, *_chan;
+	struct ioat_dma_chan *ioat_chan;
+
+	device = pci_get_drvdata(pdev);
+	dma_async_device_unregister(&device->common);
+
+	free_irq(device->pdev->irq, device);
+#ifdef CONFIG_PCI_MSI
+	if (device->msi)
+		pci_disable_msi(device->pdev);
+#endif
+	pci_pool_destroy(device->dma_pool);
+	pci_pool_destroy(device->completion_pool);
+	iounmap(device->reg_base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) {
+		ioat_chan = to_ioat_chan(chan);
+		list_del(&chan->device_node);
+		kfree(ioat_chan);
+	}
+	kfree(device);
+}
+
+/* MODULE API */
+MODULE_VERSION("1.7");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Intel Corporation");
+
+static int __init ioat_init_module(void)
+{
+	/* it's currently unsafe to unload this module */
+	/* if forced, worst case is that rmmod hangs */
+	__unsafe(THIS_MODULE);
+
+	pci_module_init(&ioat_pci_drv);
+}
+
+module_init(ioat_init_module);
+
+static void __exit ioat_exit_module(void)
+{
+	pci_unregister_driver(&ioat_pci_drv);
+}
+
+module_exit(ioat_exit_module);
diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h
new file mode 100644
index 0000000..a5d3b36
--- /dev/null
+++ b/drivers/dma/ioatdma.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef IOATDMA_H
+#define IOATDMA_H
+
+#include <linux/dmaengine.h>
+#include "ioatdma_hw.h"
+#include <linux/init.h>
+#include <linux/dmapool.h>
+#include <linux/cache.h>
+#include <linux/pci_ids.h>
+
+#define IOAT_LOW_COMPLETION_MASK	0xffffffc0
+
+extern struct list_head dma_device_list;
+extern struct list_head dma_client_list;
+
+/**
+ * struct ioat_device - internal representation of a IOAT device
+ * @pdev: PCI-Express device
+ * @reg_base: MMIO register space base address
+ * @dma_pool: for allocating DMA descriptors
+ * @common: embedded struct dma_device
+ * @msi: Message Signaled Interrupt number
+ */
+
+struct ioat_device {
+	struct pci_dev *pdev;
+	void *reg_base;
+	struct pci_pool *dma_pool;
+	struct pci_pool *completion_pool;
+
+	struct dma_device common;
+	u8 msi;
+};
+
+/**
+ * struct ioat_dma_chan - internal representation of a DMA channel
+ * @device:
+ * @reg_base:
+ * @sw_in_use:
+ * @completion:
+ * @completion_low:
+ * @completion_high:
+ * @completed_cookie: last cookie seen completed on cleanup
+ * @cookie: value of last cookie given to client
+ * @last_completion:
+ * @xfercap:
+ * @desc_lock:
+ * @free_desc:
+ * @used_desc:
+ * @resource:
+ * @device_node:
+ */
+
+struct ioat_dma_chan {
+
+	void *reg_base;
+
+	dma_cookie_t completed_cookie;
+	unsigned long last_completion;
+
+	u32 xfercap;	/* XFERCAP register value expanded out */
+
+	spinlock_t cleanup_lock;
+	spinlock_t desc_lock;
+	struct list_head free_desc;
+	struct list_head used_desc;
+
+	int pending;
+
+	struct ioat_device *device;
+	struct dma_chan common;
+
+	dma_addr_t completion_addr;
+	union {
+		u64 full; /* HW completion writeback */
+		struct {
+			u32 low;
+			u32 high;
+		};
+	} *completion_virt;
+};
+
+/* wrapper around hardware descriptor format + additional software fields */
+
+/**
+ * struct ioat_desc_sw - wrapper around hardware descriptor
+ * @hw: hardware DMA descriptor
+ * @node:
+ * @cookie:
+ * @phys:
+ */
+
+struct ioat_desc_sw {
+	struct ioat_dma_descriptor *hw;
+	struct list_head node;
+	dma_cookie_t cookie;
+	dma_addr_t phys;
+	DECLARE_PCI_UNMAP_ADDR(src)
+	DECLARE_PCI_UNMAP_LEN(src_len)
+	DECLARE_PCI_UNMAP_ADDR(dst)
+	DECLARE_PCI_UNMAP_LEN(dst_len)
+};
+
+#endif /* IOATDMA_H */
+
diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h
new file mode 100644
index 0000000..4d7a128
--- /dev/null
+++ b/drivers/dma/ioatdma_hw.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef _IOAT_HW_H_
+#define _IOAT_HW_H_
+
+/* PCI Configuration Space Values */
+#define IOAT_PCI_VID			0x8086
+#define IOAT_PCI_DID			0x1A38
+#define IOAT_PCI_RID			0x00
+#define IOAT_PCI_SVID			0x8086
+#define IOAT_PCI_SID			0x8086
+#define IOAT_VER			0x12	/* Version 1.2 */
+
+struct ioat_dma_descriptor {
+	uint32_t	size;
+	uint32_t	ctl;
+	uint64_t	src_addr;
+	uint64_t	dst_addr;
+	uint64_t	next;
+	uint64_t	rsv1;
+	uint64_t	rsv2;
+	uint64_t	user1;
+	uint64_t	user2;
+};
+
+#define IOAT_DMA_DESCRIPTOR_CTL_INT_GN	0x00000001
+#define IOAT_DMA_DESCRIPTOR_CTL_SRC_SN	0x00000002
+#define IOAT_DMA_DESCRIPTOR_CTL_DST_SN	0x00000004
+#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS	0x00000008
+#define IOAT_DMA_DESCRIPTOR_CTL_FRAME	0x00000010
+#define IOAT_DMA_DESCRIPTOR_NUL		0x00000020
+#define IOAT_DMA_DESCRIPTOR_OPCODE	0xFF000000
+
+#endif
diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h
new file mode 100644
index 0000000..c0b4bf6
--- /dev/null
+++ b/drivers/dma/ioatdma_io.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef IOATDMA_IO_H
+#define IOATDMA_IO_H
+
+#include <asm/io.h>
+
+/*
+ * device and per-channel MMIO register read and write functions
+ * this is a lot of anoying inline functions, but it's typesafe
+ */
+
+static inline u8 ioatdma_read8(struct ioat_device *device,
+                               unsigned int offset)
+{
+	return readb(device->reg_base + offset);
+}
+
+static inline u16 ioatdma_read16(struct ioat_device *device,
+                                 unsigned int offset)
+{
+	return readw(device->reg_base + offset);
+}
+
+static inline u32 ioatdma_read32(struct ioat_device *device,
+                                 unsigned int offset)
+{
+	return readl(device->reg_base + offset);
+}
+
+static inline void ioatdma_write8(struct ioat_device *device,
+                                  unsigned int offset, u8 value)
+{
+	writeb(value, device->reg_base + offset);
+}
+
+static inline void ioatdma_write16(struct ioat_device *device,
+                                   unsigned int offset, u16 value)
+{
+	writew(value, device->reg_base + offset);
+}
+
+static inline void ioatdma_write32(struct ioat_device *device,
+                                   unsigned int offset, u32 value)
+{
+	writel(value, device->reg_base + offset);
+}
+
+static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan,
+                                    unsigned int offset)
+{
+	return readb(chan->reg_base + offset);
+}
+
+static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+	return readw(chan->reg_base + offset);
+}
+
+static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+	return readl(chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan,
+                                       unsigned int offset, u8 value)
+{
+	writeb(value, chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u16 value)
+{
+	writew(value, chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u32 value)
+{
+	writel(value, chan->reg_base + offset);
+}
+
+#if (BITS_PER_LONG == 64)
+static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan,
+                                      unsigned int offset)
+{
+	return readq(chan->reg_base + offset);
+}
+
+static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan,
+                                        unsigned int offset, u64 value)
+{
+	writeq(value, chan->reg_base + offset);
+}
+#endif
+
+#endif /* IOATDMA_IO_H */
+
diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h
new file mode 100644
index 0000000..41a21ab
--- /dev/null
+++ b/drivers/dma/ioatdma_registers.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef _IOAT_REGISTERS_H_
+#define _IOAT_REGISTERS_H_
+
+
+/* MMIO Device Registers */
+#define IOAT_CHANCNT_OFFSET			0x00	/*  8-bit */
+
+#define IOAT_XFERCAP_OFFSET			0x01	/*  8-bit */
+#define IOAT_XFERCAP_4KB			12
+#define IOAT_XFERCAP_8KB			13
+#define IOAT_XFERCAP_16KB			14
+#define IOAT_XFERCAP_32KB			15
+#define IOAT_XFERCAP_32GB			0
+
+#define IOAT_GENCTRL_OFFSET			0x02	/*  8-bit */
+#define IOAT_GENCTRL_DEBUG_EN			0x01
+
+#define IOAT_INTRCTRL_OFFSET			0x03	/*  8-bit */
+#define IOAT_INTRCTRL_MASTER_INT_EN		0x01	/* Master Interrupt Enable */
+#define IOAT_INTRCTRL_INT_STATUS		0x02	/* ATTNSTATUS -or- Channel Int */
+#define IOAT_INTRCTRL_INT			0x04	/* INT_STATUS -and- MASTER_INT_EN */
+
+#define IOAT_ATTNSTATUS_OFFSET			0x04	/* Each bit is a channel */
+
+#define IOAT_VER_OFFSET				0x08	/*  8-bit */
+#define IOAT_VER_MAJOR_MASK			0xF0
+#define IOAT_VER_MINOR_MASK			0x0F
+#define GET_IOAT_VER_MAJOR(x)			((x) & IOAT_VER_MAJOR_MASK)
+#define GET_IOAT_VER_MINOR(x)			((x) & IOAT_VER_MINOR_MASK)
+
+#define IOAT_PERPORTOFFSET_OFFSET		0x0A	/* 16-bit */
+
+#define IOAT_INTRDELAY_OFFSET			0x0C	/* 16-bit */
+#define IOAT_INTRDELAY_INT_DELAY_MASK		0x3FFF	/* Interrupt Delay Time */
+#define IOAT_INTRDELAY_COALESE_SUPPORT		0x8000	/* Interrupt Coalesing Supported */
+
+#define IOAT_DEVICE_STATUS_OFFSET		0x0E	/* 16-bit */
+#define IOAT_DEVICE_STATUS_DEGRADED_MODE	0x0001
+
+
+#define IOAT_CHANNEL_MMIO_SIZE			0x80	/* Each Channel MMIO space is this size */
+
+/* DMA Channel Registers */
+#define IOAT_CHANCTRL_OFFSET			0x00	/* 16-bit Channel Control Register */
+#define IOAT_CHANCTRL_CHANNEL_PRIORITY_MASK	0xF000
+#define IOAT_CHANCTRL_CHANNEL_IN_USE		0x0100
+#define IOAT_CHANCTRL_DESCRIPTOR_ADDR_SNOOP_CONTROL	0x0020
+#define IOAT_CHANCTRL_ERR_INT_EN		0x0010
+#define IOAT_CHANCTRL_ANY_ERR_ABORT_EN		0x0008
+#define IOAT_CHANCTRL_ERR_COMPLETION_EN		0x0004
+#define IOAT_CHANCTRL_INT_DISABLE		0x0001
+
+#define IOAT_DMA_COMP_OFFSET			0x02	/* 16-bit DMA channel compatability */
+#define IOAT_DMA_COMP_V1			0x0001	/* Compatability with DMA version 1 */
+
+#define IOAT_CHANSTS_OFFSET			0x04	/* 64-bit Channel Status Register */
+#define IOAT_CHANSTS_OFFSET_LOW			0x04
+#define IOAT_CHANSTS_OFFSET_HIGH		0x08
+#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR	0xFFFFFFFFFFFFFFC0
+#define IOAT_CHANSTS_SOFT_ERR			0x0000000000000010
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS	0x0000000000000007
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE	0x0
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE	0x1
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED	0x2
+#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED	0x3
+
+#define IOAT_CHAINADDR_OFFSET			0x0C	/* 64-bit Descriptor Chain Address Register */
+#define IOAT_CHAINADDR_OFFSET_LOW		0x0C
+#define IOAT_CHAINADDR_OFFSET_HIGH		0x10
+
+#define IOAT_CHANCMD_OFFSET			0x14	/*  8-bit DMA Channel Command Register */
+#define IOAT_CHANCMD_RESET			0x20
+#define IOAT_CHANCMD_RESUME			0x10
+#define IOAT_CHANCMD_ABORT			0x08
+#define IOAT_CHANCMD_SUSPEND			0x04
+#define IOAT_CHANCMD_APPEND			0x02
+#define IOAT_CHANCMD_START			0x01
+
+#define IOAT_CHANCMP_OFFSET			0x18	/* 64-bit Channel Completion Address Register */
+#define IOAT_CHANCMP_OFFSET_LOW			0x18
+#define IOAT_CHANCMP_OFFSET_HIGH		0x1C
+
+#define IOAT_CDAR_OFFSET			0x20	/* 64-bit Current Descriptor Address Register */
+#define IOAT_CDAR_OFFSET_LOW			0x20
+#define IOAT_CDAR_OFFSET_HIGH			0x24
+
+#define IOAT_CHANERR_OFFSET			0x28	/* 32-bit Channel Error Register */
+#define IOAT_CHANERR_DMA_TRANSFER_SRC_ADDR_ERR	0x0001
+#define IOAT_CHANERR_DMA_TRANSFER_DEST_ADDR_ERR	0x0002
+#define IOAT_CHANERR_NEXT_DESCRIPTOR_ADDR_ERR	0x0004
+#define IOAT_CHANERR_NEXT_DESCRIPTOR_ALIGNMENT_ERR	0x0008
+#define IOAT_CHANERR_CHAIN_ADDR_VALUE_ERR	0x0010
+#define IOAT_CHANERR_CHANCMD_ERR		0x0020
+#define IOAT_CHANERR_CHIPSET_UNCORRECTABLE_DATA_INTEGRITY_ERR	0x0040
+#define IOAT_CHANERR_DMA_UNCORRECTABLE_DATA_INTEGRITY_ERR	0x0080
+#define IOAT_CHANERR_READ_DATA_ERR		0x0100
+#define IOAT_CHANERR_WRITE_DATA_ERR		0x0200
+#define IOAT_CHANERR_DESCRIPTOR_CONTROL_ERR	0x0400
+#define IOAT_CHANERR_DESCRIPTOR_LENGTH_ERR	0x0800
+#define IOAT_CHANERR_COMPLETION_ADDR_ERR	0x1000
+#define IOAT_CHANERR_INT_CONFIGURATION_ERR	0x2000
+#define IOAT_CHANERR_SOFT_ERR			0x4000
+
+#define IOAT_CHANERR_MASK_OFFSET		0x2C	/* 32-bit Channel Error Register */
+
+#endif /* _IOAT_REGISTERS_H_ */
diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c
new file mode 100644
index 0000000..5ed327e
--- /dev/null
+++ b/drivers/dma/iovlock.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Portions based on net/core/datagram.c and copyrighted by their authors.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This code allows the net stack to make use of a DMA engine for
+ * skb to iovec copies.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/pagemap.h>
+#include <net/tcp.h> /* for memcpy_toiovec */
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+int num_pages_spanned(struct iovec *iov)
+{
+	return
+	((PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) -
+	((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT);
+}
+
+/*
+ * Pin down all the iovec pages needed for len bytes.
+ * Return a struct dma_pinned_list to keep track of pages pinned down.
+ *
+ * We are allocating a single chunk of memory, and then carving it up into
+ * 3 sections, the latter 2 whose size depends on the number of iovecs and the
+ * total number of pages, respectively.
+ */
+struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len)
+{
+	struct dma_pinned_list *local_list;
+	struct page **pages;
+	int i;
+	int ret;
+	int nr_iovecs = 0;
+	int iovec_len_used = 0;
+	int iovec_pages_used = 0;
+	long err;
+
+	/* don't pin down non-user-based iovecs */
+	if (segment_eq(get_fs(), KERNEL_DS))
+		return NULL;
+
+	/* determine how many iovecs/pages there are, up front */
+	do {
+		iovec_len_used += iov[nr_iovecs].iov_len;
+		iovec_pages_used += num_pages_spanned(&iov[nr_iovecs]);
+		nr_iovecs++;
+	} while (iovec_len_used < len);
+
+	/* single kmalloc for pinned list, page_list[], and the page arrays */
+	local_list = kmalloc(sizeof(*local_list)
+		+ (nr_iovecs * sizeof (struct dma_page_list))
+		+ (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL);
+	if (!local_list) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/* list of pages starts right after the page list array */
+	pages = (struct page **) &local_list->page_list[nr_iovecs];
+
+	for (i = 0; i < nr_iovecs; i++) {
+		struct dma_page_list *page_list = &local_list->page_list[i];
+
+		len -= iov[i].iov_len;
+
+		if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) {
+			err = -EFAULT;
+			goto unpin;
+		}
+
+		page_list->nr_pages = num_pages_spanned(&iov[i]);
+		page_list->base_address = iov[i].iov_base;
+
+		page_list->pages = pages;
+		pages += page_list->nr_pages;
+
+		/* pin pages down */
+		down_read(&current->mm->mmap_sem);
+		ret = get_user_pages(
+			current,
+			current->mm,
+			(unsigned long) iov[i].iov_base,
+			page_list->nr_pages,
+			1,	/* write */
+			0,	/* force */
+			page_list->pages,
+			NULL);
+		up_read(&current->mm->mmap_sem);
+
+		if (ret != page_list->nr_pages) {
+			err = -ENOMEM;
+			goto unpin;
+		}
+
+		local_list->nr_iovecs = i + 1;
+	}
+
+	return local_list;
+
+unpin:
+	dma_unpin_iovec_pages(local_list);
+out:
+	return ERR_PTR(err);
+}
+
+void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list)
+{
+	int i, j;
+
+	if (!pinned_list)
+		return;
+
+	for (i = 0; i < pinned_list->nr_iovecs; i++) {
+		struct dma_page_list *page_list = &pinned_list->page_list[i];
+		for (j = 0; j < page_list->nr_pages; j++) {
+			set_page_dirty_lock(page_list->pages[j]);
+			page_cache_release(page_list->pages[j]);
+		}
+	}
+
+	kfree(pinned_list);
+}
+
+static dma_cookie_t dma_memcpy_to_kernel_iovec(struct dma_chan *chan, struct
+	iovec *iov, unsigned char *kdata, size_t len)
+{
+	dma_cookie_t dma_cookie = 0;
+
+	while (len > 0) {
+		if (iov->iov_len) {
+			int copy = min_t(unsigned int, iov->iov_len, len);
+			dma_cookie = dma_async_memcpy_buf_to_buf(
+					chan,
+					iov->iov_base,
+					kdata,
+					copy);
+			kdata += copy;
+			len -= copy;
+			iov->iov_len -= copy;
+			iov->iov_base += copy;
+		}
+		iov++;
+	}
+
+	return dma_cookie;
+}
+
+/*
+ * We have already pinned down the pages we will be using in the iovecs.
+ * Each entry in iov array has corresponding entry in pinned_list->page_list.
+ * Using array indexing to keep iov[] and page_list[] in sync.
+ * Initial elements in iov array's iov->iov_len will be 0 if already copied into
+ *   by another call.
+ * iov array length remaining guaranteed to be bigger than len.
+ */
+dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
+	struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len)
+{
+	int iov_byte_offset;
+	int copy;
+	dma_cookie_t dma_cookie = 0;
+	int iovec_idx;
+	int page_idx;
+
+	if (!chan)
+		return memcpy_toiovec(iov, kdata, len);
+
+	/* -> kernel copies (e.g. smbfs) */
+	if (!pinned_list)
+		return dma_memcpy_to_kernel_iovec(chan, iov, kdata, len);
+
+	iovec_idx = 0;
+	while (iovec_idx < pinned_list->nr_iovecs) {
+		struct dma_page_list *page_list;
+
+		/* skip already used-up iovecs */
+		while (!iov[iovec_idx].iov_len)
+			iovec_idx++;
+
+		page_list = &pinned_list->page_list[iovec_idx];
+
+		iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK);
+		page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK)
+			 - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT;
+
+		/* break up copies to not cross page boundary */
+		while (iov[iovec_idx].iov_len) {
+			copy = min_t(int, PAGE_SIZE - iov_byte_offset, len);
+			copy = min_t(int, copy, iov[iovec_idx].iov_len);
+
+			dma_cookie = dma_async_memcpy_buf_to_pg(chan,
+					page_list->pages[page_idx],
+					iov_byte_offset,
+					kdata,
+					copy);
+
+			len -= copy;
+			iov[iovec_idx].iov_len -= copy;
+			iov[iovec_idx].iov_base += copy;
+
+			if (!len)
+				return dma_cookie;
+
+			kdata += copy;
+			iov_byte_offset = 0;
+			page_idx++;
+		}
+		iovec_idx++;
+	}
+
+	/* really bad if we ever run out of iovecs */
+	BUG();
+	return -EFAULT;
+}
+
+dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
+	struct dma_pinned_list *pinned_list, struct page *page,
+	unsigned int offset, size_t len)
+{
+	int iov_byte_offset;
+	int copy;
+	dma_cookie_t dma_cookie = 0;
+	int iovec_idx;
+	int page_idx;
+	int err;
+
+	/* this needs as-yet-unimplemented buf-to-buff, so punt. */
+	/* TODO: use dma for this */
+	if (!chan || !pinned_list) {
+		u8 *vaddr = kmap(page);
+		err = memcpy_toiovec(iov, vaddr + offset, len);
+		kunmap(page);
+		return err;
+	}
+
+	iovec_idx = 0;
+	while (iovec_idx < pinned_list->nr_iovecs) {
+		struct dma_page_list *page_list;
+
+		/* skip already used-up iovecs */
+		while (!iov[iovec_idx].iov_len)
+			iovec_idx++;
+
+		page_list = &pinned_list->page_list[iovec_idx];
+
+		iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK);
+		page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK)
+			 - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT;
+
+		/* break up copies to not cross page boundary */
+		while (iov[iovec_idx].iov_len) {
+			copy = min_t(int, PAGE_SIZE - iov_byte_offset, len);
+			copy = min_t(int, copy, iov[iovec_idx].iov_len);
+
+			dma_cookie = dma_async_memcpy_pg_to_pg(chan,
+					page_list->pages[page_idx],
+					iov_byte_offset,
+					page,
+					offset,
+					copy);
+
+			len -= copy;
+			iov[iovec_idx].iov_len -= copy;
+			iov[iovec_idx].iov_base += copy;
+
+			if (!len)
+				return dma_cookie;
+
+			offset += copy;
+			iov_byte_offset = 0;
+			page_idx++;
+		}
+		iovec_idx++;
+	}
+
+	/* really bad if we ever run out of iovecs */
+	BUG();
+	return -EFAULT;
+}
diff --git a/drivers/fc4/soc.c b/drivers/fc4/soc.c
index ec1f947..cf8768b 100644
--- a/drivers/fc4/soc.c
+++ b/drivers/fc4/soc.c
@@ -643,7 +643,7 @@
 		return;
 	}
 
-	SOD(("SOC uses IRQ%s\n", __irq_itoa(irq)))
+	SOD(("SOC uses IRQ %d\n", irq))
 	
 	s->port[0].fc.irq = irq;
 	s->port[1].fc.irq = irq;
diff --git a/drivers/fc4/socal.c b/drivers/fc4/socal.c
index 922e961..f52d1e5b 100644
--- a/drivers/fc4/socal.c
+++ b/drivers/fc4/socal.c
@@ -767,7 +767,7 @@
 		return;
 	}
 
-	SOD(("SOCAL uses IRQ %s\n", __irq_itoa(irq)))
+	SOD(("SOCAL uses IRQ %d\n", irq))
 	
 	s->port[0].fc.irq = irq;
 	s->port[1].fc.irq = irq;
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 1e371a5..731c3d5 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -6,8 +6,7 @@
 menu "Firmware Drivers"
 
 config EDD
-	tristate "BIOS Enhanced Disk Drive calls determine boot disk (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	tristate "BIOS Enhanced Disk Drive calls determine boot disk"
 	depends on !IA64
 	help
 	  Say Y or M here if you want to enable BIOS Enhanced Disk Drive
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 948bd7e..b9e3886 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -255,10 +255,15 @@
 /**
  *	dmi_check_system - check system DMI data
  *	@list: array of dmi_system_id structures to match against
+ *		All non-null elements of the list must match
+ *		their slot's (field index's) data (i.e., each
+ *		list string must be a substring of the specified
+ *		DMI slot's string data) to be considered a
+ *		successful match.
  *
  *	Walk the blacklist table running matching functions until someone
  *	returns non zero or we hit the end. Callback function is called for
- *	each successfull match. Returns the number of matches.
+ *	each successful match. Returns the number of matches.
  */
 int dmi_check_system(struct dmi_system_id *list)
 {
@@ -287,7 +292,7 @@
 
 /**
  *	dmi_get_system_info - return DMI data value
- *	@field: data index (see enum dmi_filed)
+ *	@field: data index (see enum dmi_field)
  *
  *	Returns one DMI data value, can be used to perform
  *	complex DMI data checks.
@@ -301,13 +306,13 @@
 /**
  *	dmi_find_device - find onboard device by type/name
  *	@type: device type or %DMI_DEV_TYPE_ANY to match all device types
- *	@desc: device name string or %NULL to match all
+ *	@name: device name string or %NULL to match all
  *	@from: previous device found in search, or %NULL for new search.
  *
  *	Iterates through the list of known onboard devices. If a device is
  *	found with a matching @vendor and @device, a pointer to its device
  *	structure is returned.  Otherwise, %NULL is returned.
- *	A new search is initiated by passing %NULL to the @from argument.
+ *	A new search is initiated by passing %NULL as the @from argument.
  *	If @from is not %NULL, searches continue from next device.
  */
 struct dmi_device * dmi_find_device(int type, const char *name,
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 99cdc61..0e31a0c 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1,5 +1,5 @@
 #
-# I2C Sensor chip drivers configuration
+# Hardware monitoring chip drivers configuration
 #
 
 menu "Hardware Monitoring support"
@@ -16,6 +16,10 @@
 	  should say Y here and also to the specific driver(s) for your
 	  sensors chip(s) below.
 
+	  To find out which specific driver(s) you need, use the
+	  sensors-detect script from the lm_sensors package.  Read
+	  <file:Documentation/hwmon/userspace-tools> for details.
+
 	  This support can also be built as a module.  If so, the module
 	  will be called hwmon.
 
@@ -23,6 +27,18 @@
 	tristate
 	default n
 
+config SENSORS_ABITUGURU
+	tristate "Abit uGuru"
+	depends on HWMON && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Abit uGuru chips
+	  sensor part. The voltage and frequency control parts of the Abit
+	  uGuru are not supported. The Abit uGuru chip can be found on Abit
+	  uGuru featuring motherboards (most modern Abit motherboards).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called abituguru.
+
 config SENSORS_ADM1021
 	tristate "Analog Devices ADM1021 and compatibles"
 	depends on HWMON && I2C
@@ -188,6 +204,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm63.
 
+config SENSORS_LM70
+	tristate "National Semiconductor LM70"
+	depends on HWMON && SPI_MASTER && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the National Semiconductor
+	  LM70 digital temperature sensor chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm70.
+
 config SENSORS_LM75
 	tristate "National Semiconductor LM75 and compatibles"
 	depends on HWMON && I2C
@@ -236,11 +262,11 @@
 	  will be called lm80.
 
 config SENSORS_LM83
-	tristate "National Semiconductor LM83"
+	tristate "National Semiconductor LM83 and compatibles"
 	depends on HWMON && I2C
 	help
 	  If you say yes here you get support for National Semiconductor
-	  LM83 sensor chips.
+	  LM82 and LM83 sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm83.
@@ -333,11 +359,32 @@
 	help
 	  If you say yes here you get support for the integrated fan
 	  monitoring and control capabilities of the SMSC LPC47B27x,
-	  LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 chips.
+	  LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and
+	  LPC47M997 chips.
+
+	  The temperature and voltage sensor features of the LPC47M192
+	  and LPC47M997 are supported by another driver, select also
+	  "SMSC LPC47M192 and compatibles" below for those.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47m1.
 
+config SENSORS_SMSC47M192
+	tristate "SMSC LPC47M192 and compatibles"
+	depends on HWMON && I2C && EXPERIMENTAL
+	select HWMON_VID
+	help
+	  If you say yes here you get support for the temperature and
+	  voltage sensors of the SMSC LPC47M192 and LPC47M997 chips.
+
+	  The fan monitoring and control capabilities of these chips
+	  are supported by another driver, select
+	  "SMSC LPC47M10x and compatibles" above. You need both drivers
+	  if you want fan control and voltage/temperature sensor support.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called smsc47m192.
+
 config SENSORS_SMSC47B397
 	tristate "SMSC LPC47B397-NC"
 	depends on HWMON && I2C && EXPERIMENTAL
@@ -385,6 +432,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83781d.
 
+config SENSORS_W83791D
+	tristate "Winbond W83791D"
+	depends on HWMON && I2C && EXPERIMENTAL
+	select HWMON_VID
+	help
+	  If you say yes here you get support for the Winbond W83791D chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called w83791d.
+
 config SENSORS_W83792D
 	tristate "Winbond W83792D"
 	depends on HWMON && I2C && EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index fbdb8d9..3141584 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -10,7 +10,9 @@
 obj-$(CONFIG_SENSORS_W83627HF)	+= w83627hf.o
 obj-$(CONFIG_SENSORS_W83792D)	+= w83792d.o
 obj-$(CONFIG_SENSORS_W83781D)	+= w83781d.o
+obj-$(CONFIG_SENSORS_W83791D)	+= w83791d.o
 
+obj-$(CONFIG_SENSORS_ABITUGURU)	+= abituguru.o
 obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
 obj-$(CONFIG_SENSORS_ADM1025)	+= adm1025.o
 obj-$(CONFIG_SENSORS_ADM1026)	+= adm1026.o
@@ -26,6 +28,7 @@
 obj-$(CONFIG_SENSORS_HDAPS)	+= hdaps.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
+obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
 obj-$(CONFIG_SENSORS_LM75)	+= lm75.o
 obj-$(CONFIG_SENSORS_LM77)	+= lm77.o
 obj-$(CONFIG_SENSORS_LM78)	+= lm78.o
@@ -40,6 +43,7 @@
 obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
+obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
 obj-$(CONFIG_SENSORS_W83627EHF)	+= w83627ehf.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
new file mode 100644
index 0000000..59122cc
--- /dev/null
+++ b/drivers/hwmon/abituguru.c
@@ -0,0 +1,1415 @@
+/*
+    abituguru.c Copyright (c) 2005-2006 Hans de Goede <j.w.r.degoede@hhs.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+    This driver supports the sensor part of the custom Abit uGuru chip found
+    on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM /
+    etc voltage & frequency control is not supported!
+*/
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <asm/io.h>
+
+/* Banks */
+#define ABIT_UGURU_ALARM_BANK			0x20 /* 1x 3 bytes */
+#define ABIT_UGURU_SENSOR_BANK1			0x21 /* 16x volt and temp */
+#define ABIT_UGURU_FAN_PWM			0x24 /* 3x 5 bytes */
+#define ABIT_UGURU_SENSOR_BANK2			0x26 /* fans */
+/* max nr of sensors in bank1, a bank1 sensor can be in, temp or nc */
+#define ABIT_UGURU_MAX_BANK1_SENSORS		16
+/* Warning if you increase one of the 2 MAX defines below to 10 or higher you
+   should adjust the belonging _NAMES_LENGTH macro for the 2 digit number! */
+/* max nr of sensors in bank2, currently mb's with max 6 fans are known */
+#define ABIT_UGURU_MAX_BANK2_SENSORS		6
+/* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */
+#define ABIT_UGURU_MAX_PWMS			5
+/* uGuru sensor bank 1 flags */			     /* Alarm if: */
+#define ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE	0x01 /*  temp over warn */
+#define ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE	0x02 /*  volt over max */
+#define ABIT_UGURU_VOLT_LOW_ALARM_ENABLE	0x04 /*  volt under min */
+#define ABIT_UGURU_TEMP_HIGH_ALARM_FLAG		0x10 /* temp is over warn */
+#define ABIT_UGURU_VOLT_HIGH_ALARM_FLAG		0x20 /* volt is over max */
+#define ABIT_UGURU_VOLT_LOW_ALARM_FLAG		0x40 /* volt is under min */
+/* uGuru sensor bank 2 flags */			     /* Alarm if: */
+#define ABIT_UGURU_FAN_LOW_ALARM_ENABLE		0x01 /*   fan under min */
+/* uGuru sensor bank common flags */
+#define ABIT_UGURU_BEEP_ENABLE			0x08 /* beep if alarm */
+#define ABIT_UGURU_SHUTDOWN_ENABLE		0x80 /* shutdown if alarm */
+/* uGuru fan PWM (speed control) flags */
+#define ABIT_UGURU_FAN_PWM_ENABLE		0x80 /* enable speed control */
+/* Values used for conversion */
+#define ABIT_UGURU_FAN_MAX			15300 /* RPM */
+/* Bank1 sensor types */
+#define ABIT_UGURU_IN_SENSOR			0
+#define ABIT_UGURU_TEMP_SENSOR			1
+#define ABIT_UGURU_NC				2
+/* Timeouts / Retries, if these turn out to need a lot of fiddling we could
+   convert them to params. */
+/* 250 was determined by trial and error, 200 works most of the time, but not
+   always. I assume this is cpu-speed independent, since the ISA-bus and not
+   the CPU should be the bottleneck. Note that 250 sometimes is still not
+   enough (only reported on AN7 mb) this is handled by a higher layer. */
+#define ABIT_UGURU_WAIT_TIMEOUT			250
+/* Normally all expected status in abituguru_ready, are reported after the
+   first read, but sometimes not and we need to poll, 5 polls was not enough
+   50 sofar is. */
+#define ABIT_UGURU_READY_TIMEOUT		50
+/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */
+#define ABIT_UGURU_MAX_RETRIES			3
+#define ABIT_UGURU_RETRY_DELAY			(HZ/5)
+/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is an error */
+#define ABIT_UGURU_MAX_TIMEOUTS			2
+/* utility macros */
+#define ABIT_UGURU_NAME				"abituguru"
+#define ABIT_UGURU_DEBUG(level, format, arg...)				\
+	if (level <= verbose)						\
+		printk(KERN_DEBUG ABIT_UGURU_NAME ": "	format , ## arg)
+/* Macros to help calculate the sysfs_names array length */
+/* sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
+   in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0 */
+#define ABITUGURU_IN_NAMES_LENGTH	(11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14)
+/* sum of strlen of: temp??_input\0, temp??_max\0, temp??_crit\0,
+   temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0 */
+#define ABITUGURU_TEMP_NAMES_LENGTH	(13 + 11 + 12 + 13 + 20 + 12 + 16)
+/* sum of strlen of: fan?_input\0, fan?_min\0, fan?_alarm\0,
+   fan?_alarm_enable\0, fan?_beep\0, fan?_shutdown\0 */
+#define ABITUGURU_FAN_NAMES_LENGTH	(11 + 9 + 11 + 18 + 10 + 14)
+/* sum of strlen of: pwm?_enable\0, pwm?_auto_channels_temp\0,
+   pwm?_auto_point{1,2}_pwm\0, pwm?_auto_point{1,2}_temp\0 */
+#define ABITUGURU_PWM_NAMES_LENGTH	(12 + 24 + 2 * 21 + 2 * 22)
+/* IN_NAMES_LENGTH > TEMP_NAMES_LENGTH so assume all bank1 sensors are in */
+#define ABITUGURU_SYSFS_NAMES_LENGTH	( \
+	ABIT_UGURU_MAX_BANK1_SENSORS * ABITUGURU_IN_NAMES_LENGTH + \
+	ABIT_UGURU_MAX_BANK2_SENSORS * ABITUGURU_FAN_NAMES_LENGTH + \
+	ABIT_UGURU_MAX_PWMS * ABITUGURU_PWM_NAMES_LENGTH)
+
+/* All the macros below are named identical to the oguru and oguru2 programs
+   reverse engineered by Olle Sandberg, hence the names might not be 100%
+   logical. I could come up with better names, but I prefer keeping the names
+   identical so that this driver can be compared with his work more easily. */
+/* Two i/o-ports are used by uGuru */
+#define ABIT_UGURU_BASE				0x00E0
+/* Used to tell uGuru what to read and to read the actual data */
+#define ABIT_UGURU_CMD				0x00
+/* Mostly used to check if uGuru is busy */
+#define ABIT_UGURU_DATA				0x04
+#define ABIT_UGURU_REGION_LENGTH		5
+/* uGuru status' */
+#define ABIT_UGURU_STATUS_WRITE			0x00 /* Ready to be written */
+#define ABIT_UGURU_STATUS_READ			0x01 /* Ready to be read */
+#define ABIT_UGURU_STATUS_INPUT			0x08 /* More input */
+#define ABIT_UGURU_STATUS_READY			0x09 /* Ready to be written */
+
+/* Constants */
+/* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */
+static const int abituguru_bank1_max_value[2] = { 3494, 255000 };
+/* Min / Max allowed values for sensor2 (fan) alarm threshold, these values
+   correspond to 300-3000 RPM */
+static const u8 abituguru_bank2_min_threshold = 5;
+static const u8 abituguru_bank2_max_threshold = 50;
+/* Register 0 is a bitfield, 1 and 2 are pwm settings (255 = 100%), 3 and 4
+   are temperature trip points. */
+static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 };
+/* Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a
+   special case the minium allowed pwm% setting for this is 30% (77) on
+   some MB's this special case is handled in the code! */
+static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 };
+static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 };
+
+
+/* Insmod parameters */
+static int force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Set to one to force detection.");
+static int fan_sensors;
+module_param(fan_sensors, int, 0);
+MODULE_PARM_DESC(fan_sensors, "Number of fan sensors on the uGuru "
+	"(0 = autodetect)");
+static int pwms;
+module_param(pwms, int, 0);
+MODULE_PARM_DESC(pwms, "Number of PWMs on the uGuru "
+	"(0 = autodetect)");
+
+/* Default verbose is 2, since this driver is still in the testing phase */
+static int verbose = 2;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n"
+	"   0 normal output\n"
+	"   1 + verbose error reporting\n"
+	"   2 + sensors type probing info\n"
+	"   3 + retryable error reporting");
+
+
+/* For the Abit uGuru, we need to keep some data in memory.
+   The structure is dynamically allocated, at the same time when a new
+   abituguru device is allocated. */
+struct abituguru_data {
+	struct class_device *class_dev; /* hwmon registered device */
+	struct mutex update_lock;	/* protect access to data and uGuru */
+	unsigned long last_updated;	/* In jiffies */
+	unsigned short addr;		/* uguru base address */
+	char uguru_ready;		/* is the uguru in ready state? */
+	unsigned char update_timeouts;	/* number of update timeouts since last
+					   successful update */
+
+	/* The sysfs attr and their names are generated automatically, for bank1
+	   we cannot use a predefined array because we don't know beforehand
+	   of a sensor is a volt or a temp sensor, for bank2 and the pwms its
+	   easier todo things the same way.  For in sensors we have 9 (temp 7)
+	   sysfs entries per sensor, for bank2 and pwms 6. */
+	struct sensor_device_attribute_2 sysfs_attr[
+		ABIT_UGURU_MAX_BANK1_SENSORS * 9 +
+		ABIT_UGURU_MAX_BANK2_SENSORS * 6 + ABIT_UGURU_MAX_PWMS * 6];
+	/* Buffer to store the dynamically generated sysfs names */
+	char sysfs_names[ABITUGURU_SYSFS_NAMES_LENGTH];
+
+	/* Bank 1 data */
+	/* number of and addresses of [0] in, [1] temp sensors */
+	u8 bank1_sensors[2];
+	u8 bank1_address[2][ABIT_UGURU_MAX_BANK1_SENSORS];
+	u8 bank1_value[ABIT_UGURU_MAX_BANK1_SENSORS];
+	/* This array holds 3 entries per sensor for the bank 1 sensor settings
+	   (flags, min, max for voltage / flags, warn, shutdown for temp). */
+	u8 bank1_settings[ABIT_UGURU_MAX_BANK1_SENSORS][3];
+	/* Maximum value for each sensor used for scaling in mV/millidegrees
+	   Celsius. */
+	int bank1_max_value[ABIT_UGURU_MAX_BANK1_SENSORS];
+
+	/* Bank 2 data, ABIT_UGURU_MAX_BANK2_SENSORS entries for bank2 */
+	u8 bank2_sensors; /* actual number of bank2 sensors found */
+	u8 bank2_value[ABIT_UGURU_MAX_BANK2_SENSORS];
+	u8 bank2_settings[ABIT_UGURU_MAX_BANK2_SENSORS][2]; /* flags, min */
+
+	/* Alarms 2 bytes for bank1, 1 byte for bank2 */
+	u8 alarms[3];
+
+	/* Fan PWM (speed control) 5 bytes per PWM */
+	u8 pwms; /* actual number of pwms found */
+	u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5];
+};
+
+/* wait till the uguru is in the specified state */
+static int abituguru_wait(struct abituguru_data *data, u8 state)
+{
+	int timeout = ABIT_UGURU_WAIT_TIMEOUT;
+
+	while (inb_p(data->addr + ABIT_UGURU_DATA) != state) {
+		timeout--;
+		if (timeout == 0)
+			return -EBUSY;
+	}
+	return 0;
+}
+
+/* Put the uguru in ready for input state */
+static int abituguru_ready(struct abituguru_data *data)
+{
+	int timeout = ABIT_UGURU_READY_TIMEOUT;
+
+	if (data->uguru_ready)
+		return 0;
+
+	/* Reset? / Prepare for next read/write cycle */
+	outb(0x00, data->addr + ABIT_UGURU_DATA);
+
+	/* Wait till the uguru is ready */
+	if (abituguru_wait(data, ABIT_UGURU_STATUS_READY)) {
+		ABIT_UGURU_DEBUG(1,
+			"timeout exceeded waiting for ready state\n");
+		return -EIO;
+	}
+
+	/* Cmd port MUST be read now and should contain 0xAC */
+	while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
+		timeout--;
+		if (timeout == 0) {
+			ABIT_UGURU_DEBUG(1,
+			   "CMD reg does not hold 0xAC after ready command\n");
+			return -EIO;
+		}
+	}
+
+	/* After this the ABIT_UGURU_DATA port should contain
+	   ABIT_UGURU_STATUS_INPUT */
+	timeout = ABIT_UGURU_READY_TIMEOUT;
+	while (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) {
+		timeout--;
+		if (timeout == 0) {
+			ABIT_UGURU_DEBUG(1,
+				"state != more input after ready command\n");
+			return -EIO;
+		}
+	}
+
+	data->uguru_ready = 1;
+	return 0;
+}
+
+/* Send the bank and then sensor address to the uGuru for the next read/write
+   cycle. This function gets called as the first part of a read/write by
+   abituguru_read and abituguru_write. This function should never be
+   called by any other function. */
+static int abituguru_send_address(struct abituguru_data *data,
+	u8 bank_addr, u8 sensor_addr, int retries)
+{
+	/* assume the caller does error handling itself if it has not requested
+	   any retries, and thus be quiet. */
+	int report_errors = retries;
+
+	for (;;) {
+		/* Make sure the uguru is ready and then send the bank address,
+		   after this the uguru is no longer "ready". */
+		if (abituguru_ready(data) != 0)
+			return -EIO;
+		outb(bank_addr, data->addr + ABIT_UGURU_DATA);
+		data->uguru_ready = 0;
+
+		/* Wait till the uguru is ABIT_UGURU_STATUS_INPUT state again
+		   and send the sensor addr */
+		if (abituguru_wait(data, ABIT_UGURU_STATUS_INPUT)) {
+			if (retries) {
+				ABIT_UGURU_DEBUG(3, "timeout exceeded "
+					"waiting for more input state, %d "
+					"tries remaining\n", retries);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule_timeout(ABIT_UGURU_RETRY_DELAY);
+				retries--;
+				continue;
+			}
+			if (report_errors)
+				ABIT_UGURU_DEBUG(1, "timeout exceeded "
+					"waiting for more input state "
+					"(bank: %d)\n", (int)bank_addr);
+			return -EBUSY;
+		}
+		outb(sensor_addr, data->addr + ABIT_UGURU_CMD);
+		return 0;
+	}
+}
+
+/* Read count bytes from sensor sensor_addr in bank bank_addr and store the
+   result in buf, retry the send address part of the read retries times. */
+static int abituguru_read(struct abituguru_data *data,
+	u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries)
+{
+	int i;
+
+	/* Send the address */
+	i = abituguru_send_address(data, bank_addr, sensor_addr, retries);
+	if (i)
+		return i;
+
+	/* And read the data */
+	for (i = 0; i < count; i++) {
+		if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
+			ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for "
+				"read state (bank: %d, sensor: %d)\n",
+				(int)bank_addr, (int)sensor_addr);
+			break;
+		}
+		buf[i] = inb(data->addr + ABIT_UGURU_CMD);
+	}
+
+	/* Last put the chip back in ready state */
+	abituguru_ready(data);
+
+	return i;
+}
+
+/* Write count bytes from buf to sensor sensor_addr in bank bank_addr, the send
+   address part of the write is always retried ABIT_UGURU_MAX_RETRIES times. */
+static int abituguru_write(struct abituguru_data *data,
+	u8 bank_addr, u8 sensor_addr, u8 *buf, int count)
+{
+	int i;
+
+	/* Send the address */
+	i = abituguru_send_address(data, bank_addr, sensor_addr,
+		ABIT_UGURU_MAX_RETRIES);
+	if (i)
+		return i;
+
+	/* And write the data */
+	for (i = 0; i < count; i++) {
+		if (abituguru_wait(data, ABIT_UGURU_STATUS_WRITE)) {
+			ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for "
+				"write state (bank: %d, sensor: %d)\n",
+				(int)bank_addr, (int)sensor_addr);
+			break;
+		}
+		outb(buf[i], data->addr + ABIT_UGURU_CMD);
+	}
+
+	/* Now we need to wait till the chip is ready to be read again,
+	   don't ask why */
+	if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) {
+		ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state "
+			"after write (bank: %d, sensor: %d)\n", (int)bank_addr,
+			(int)sensor_addr);
+		return -EIO;
+	}
+
+	/* Cmd port MUST be read now and should contain 0xAC */
+	if (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) {
+		ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after write "
+			"(bank: %d, sensor: %d)\n", (int)bank_addr,
+			(int)sensor_addr);
+		return -EIO;
+	}
+
+	/* Last put the chip back in ready state */
+	abituguru_ready(data);
+
+	return i;
+}
+
+/* Detect sensor type. Temp and Volt sensors are enabled with
+   different masks and will ignore enable masks not meant for them.
+   This enables us to test what kind of sensor we're dealing with.
+   By setting the alarm thresholds so that we will always get an
+   alarm for sensor type X and then enabling the sensor as sensor type
+   X, if we then get an alarm it is a sensor of type X. */
+static int __devinit
+abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
+				   u8 sensor_addr)
+{
+	u8 val, buf[3];
+	int ret = ABIT_UGURU_NC;
+
+	/* First read the sensor and the current settings */
+	if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val,
+			1, ABIT_UGURU_MAX_RETRIES) != 1)
+		return -ENODEV;
+
+	/* Test val is sane / usable for sensor type detection. */
+	if ((val < 10u) || (val > 240u)) {
+		printk(KERN_WARNING ABIT_UGURU_NAME
+			": bank1-sensor: %d reading (%d) too close to limits, "
+			"unable to determine sensor type, skipping sensor\n",
+			(int)sensor_addr, (int)val);
+		/* assume no sensor is there for sensors for which we can't
+		   determine the sensor type because their reading is too close
+		   to their limits, this usually means no sensor is there. */
+		return ABIT_UGURU_NC;
+	}
+
+	ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr);
+	/* Volt sensor test, enable volt low alarm, set min value ridicously
+	   high. If its a volt sensor this should always give us an alarm. */
+	buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE;
+	buf[1] = 245;
+	buf[2] = 250;
+	if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
+			buf, 3) != 3)
+		return -ENODEV;
+	/* Now we need 20 ms to give the uguru time to read the sensors
+	   and raise a voltage alarm */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ/50);
+	/* Check for alarm and check the alarm is a volt low alarm. */
+	if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
+			ABIT_UGURU_MAX_RETRIES) != 3)
+		return -ENODEV;
+	if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
+		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
+				sensor_addr, buf, 3,
+				ABIT_UGURU_MAX_RETRIES) != 3)
+			return -ENODEV;
+		if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) {
+			/* Restore original settings */
+			if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
+					sensor_addr,
+					data->bank1_settings[sensor_addr],
+					3) != 3)
+				return -ENODEV;
+			ABIT_UGURU_DEBUG(2, "  found volt sensor\n");
+			return ABIT_UGURU_IN_SENSOR;
+		} else
+			ABIT_UGURU_DEBUG(2, "  alarm raised during volt "
+				"sensor test, but volt low flag not set\n");
+	} else
+		ABIT_UGURU_DEBUG(2, "  alarm not raised during volt sensor "
+			"test\n");
+
+	/* Temp sensor test, enable sensor as a temp sensor, set beep value
+	   ridicously low (but not too low, otherwise uguru ignores it).
+	   If its a temp sensor this should always give us an alarm. */
+	buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE;
+	buf[1] = 5;
+	buf[2] = 10;
+	if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
+			buf, 3) != 3)
+		return -ENODEV;
+	/* Now we need 50 ms to give the uguru time to read the sensors
+	   and raise a temp alarm */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(HZ/20);
+	/* Check for alarm and check the alarm is a temp high alarm. */
+	if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3,
+			ABIT_UGURU_MAX_RETRIES) != 3)
+		return -ENODEV;
+	if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) {
+		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1,
+				sensor_addr, buf, 3,
+				ABIT_UGURU_MAX_RETRIES) != 3)
+			return -ENODEV;
+		if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) {
+			ret = ABIT_UGURU_TEMP_SENSOR;
+			ABIT_UGURU_DEBUG(2, "  found temp sensor\n");
+		} else
+			ABIT_UGURU_DEBUG(2, "  alarm raised during temp "
+				"sensor test, but temp high flag not set\n");
+	} else
+		ABIT_UGURU_DEBUG(2, "  alarm not raised during temp sensor "
+			"test\n");
+
+	/* Restore original settings */
+	if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
+			data->bank1_settings[sensor_addr], 3) != 3)
+		return -ENODEV;
+
+	return ret;
+}
+
+/* These functions try to find out how many sensors there are in bank2 and how
+   many pwms there are. The purpose of this is to make sure that we don't give
+   the user the possibility to change settings for non-existent sensors / pwm.
+   The uGuru will happily read / write whatever memory happens to be after the
+   memory storing the PWM settings when reading/writing to a PWM which is not
+   there. Notice even if we detect a PWM which doesn't exist we normally won't
+   write to it, unless the user tries to change the settings.
+
+   Although the uGuru allows reading (settings) from non existing bank2
+   sensors, my version of the uGuru does seem to stop writing to them, the
+   write function above aborts in this case with:
+   "CMD reg does not hold 0xAC after write"
+
+   Notice these 2 tests are non destructive iow read-only tests, otherwise
+   they would defeat their purpose. Although for the bank2_sensors detection a
+   read/write test would be feasible because of the reaction above, I've
+   however opted to stay on the safe side. */
+static void __devinit
+abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
+{
+	int i;
+
+	if (fan_sensors) {
+		data->bank2_sensors = fan_sensors;
+		ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of "
+			"\"fan_sensors\" module param\n",
+			(int)data->bank2_sensors);
+		return;
+	}
+
+	ABIT_UGURU_DEBUG(2, "detecting number of fan sensors\n");
+	for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) {
+		/* 0x89 are the known used bits:
+		   -0x80 enable shutdown
+		   -0x08 enable beep
+		   -0x01 enable alarm
+		   All other bits should be 0, but on some motherboards
+		   0x40 (bit 6) is also high for some of the fans?? */
+		if (data->bank2_settings[i][0] & ~0xC9) {
+			ABIT_UGURU_DEBUG(2, "  bank2 sensor %d does not seem "
+				"to be a fan sensor: settings[0] = %02X\n",
+				i, (unsigned int)data->bank2_settings[i][0]);
+			break;
+		}
+
+		/* check if the threshold is within the allowed range */
+		if (data->bank2_settings[i][1] <
+				abituguru_bank2_min_threshold) {
+			ABIT_UGURU_DEBUG(2, "  bank2 sensor %d does not seem "
+				"to be a fan sensor: the threshold (%d) is "
+				"below the minimum (%d)\n", i,
+				(int)data->bank2_settings[i][1],
+				(int)abituguru_bank2_min_threshold);
+			break;
+		}
+		if (data->bank2_settings[i][1] >
+				abituguru_bank2_max_threshold) {
+			ABIT_UGURU_DEBUG(2, "  bank2 sensor %d does not seem "
+				"to be a fan sensor: the threshold (%d) is "
+				"above the maximum (%d)\n", i,
+				(int)data->bank2_settings[i][1],
+				(int)abituguru_bank2_max_threshold);
+			break;
+		}
+	}
+
+	data->bank2_sensors = i;
+	ABIT_UGURU_DEBUG(2, " found: %d fan sensors\n",
+		(int)data->bank2_sensors);
+}
+
+static void __devinit
+abituguru_detect_no_pwms(struct abituguru_data *data)
+{
+	int i, j;
+
+	if (pwms) {
+		data->pwms = pwms;
+		ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of "
+			"\"pwms\" module param\n", (int)data->pwms);
+		return;
+	}
+
+	ABIT_UGURU_DEBUG(2, "detecting number of PWM outputs\n");
+	for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) {
+		/* 0x80 is the enable bit and the low
+		   nibble is which temp sensor to use,
+		   the other bits should be 0 */
+		if (data->pwm_settings[i][0] & ~0x8F) {
+			ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+				"to be a pwm channel: settings[0] = %02X\n",
+				i, (unsigned int)data->pwm_settings[i][0]);
+			break;
+		}
+
+		/* the low nibble must correspond to one of the temp sensors
+		   we've found */
+		for (j = 0; j < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR];
+				j++) {
+			if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][j] ==
+					(data->pwm_settings[i][0] & 0x0F))
+				break;
+		}
+		if (j == data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) {
+			ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+				"to be a pwm channel: %d is not a valid temp "
+				"sensor address\n", i,
+				data->pwm_settings[i][0] & 0x0F);
+			break;
+		}
+
+		/* check if all other settings are within the allowed range */
+		for (j = 1; j < 5; j++) {
+			u8 min;
+			/* special case pwm1 min pwm% */
+			if ((i == 0) && ((j == 1) || (j == 2)))
+				min = 77;
+			else
+				min = abituguru_pwm_min[j];
+			if (data->pwm_settings[i][j] < min) {
+				ABIT_UGURU_DEBUG(2, "  pwm channel %d does "
+					"not seem to be a pwm channel: "
+					"setting %d (%d) is below the minimum "
+					"value (%d)\n", i, j,
+					(int)data->pwm_settings[i][j],
+					(int)min);
+				goto abituguru_detect_no_pwms_exit;
+			}
+			if (data->pwm_settings[i][j] > abituguru_pwm_max[j]) {
+				ABIT_UGURU_DEBUG(2, "  pwm channel %d does "
+					"not seem to be a pwm channel: "
+					"setting %d (%d) is above the maximum "
+					"value (%d)\n", i, j,
+					(int)data->pwm_settings[i][j],
+					(int)abituguru_pwm_max[j]);
+				goto abituguru_detect_no_pwms_exit;
+			}
+		}
+
+		/* check that min temp < max temp and min pwm < max pwm */
+		if (data->pwm_settings[i][1] >= data->pwm_settings[i][2]) {
+			ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+				"to be a pwm channel: min pwm (%d) >= "
+				"max pwm (%d)\n", i,
+				(int)data->pwm_settings[i][1],
+				(int)data->pwm_settings[i][2]);
+			break;
+		}
+		if (data->pwm_settings[i][3] >= data->pwm_settings[i][4]) {
+			ABIT_UGURU_DEBUG(2, "  pwm channel %d does not seem "
+				"to be a pwm channel: min temp (%d) >= "
+				"max temp (%d)\n", i,
+				(int)data->pwm_settings[i][3],
+				(int)data->pwm_settings[i][4]);
+			break;
+		}
+	}
+
+abituguru_detect_no_pwms_exit:
+	data->pwms = i;
+	ABIT_UGURU_DEBUG(2, " found: %d PWM outputs\n", (int)data->pwms);
+}
+
+/* Following are the sysfs callback functions. These functions expect:
+   sensor_device_attribute_2->index:   sensor address/offset in the bank
+   sensor_device_attribute_2->nr:      register offset, bitmask or NA. */
+static struct abituguru_data *abituguru_update_device(struct device *dev);
+
+static ssize_t show_bank1_value(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = abituguru_update_device(dev);
+	if (!data)
+		return -EIO;
+	return sprintf(buf, "%d\n", (data->bank1_value[attr->index] *
+		data->bank1_max_value[attr->index] + 128) / 255);
+}
+
+static ssize_t show_bank1_setting(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n",
+		(data->bank1_settings[attr->index][attr->nr] *
+		data->bank1_max_value[attr->index] + 128) / 255);
+}
+
+static ssize_t show_bank2_value(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = abituguru_update_device(dev);
+	if (!data)
+		return -EIO;
+	return sprintf(buf, "%d\n", (data->bank2_value[attr->index] *
+		ABIT_UGURU_FAN_MAX + 128) / 255);
+}
+
+static ssize_t show_bank2_setting(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n",
+		(data->bank2_settings[attr->index][attr->nr] *
+		ABIT_UGURU_FAN_MAX + 128) / 255);
+}
+
+static ssize_t store_bank1_setting(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	u8 val = (simple_strtoul(buf, NULL, 10) * 255 +
+		data->bank1_max_value[attr->index]/2) /
+		data->bank1_max_value[attr->index];
+	ssize_t ret = count;
+
+	mutex_lock(&data->update_lock);
+	if (data->bank1_settings[attr->index][attr->nr] != val) {
+		u8 orig_val = data->bank1_settings[attr->index][attr->nr];
+		data->bank1_settings[attr->index][attr->nr] = val;
+		if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2,
+				attr->index, data->bank1_settings[attr->index],
+				3) <= attr->nr) {
+			data->bank1_settings[attr->index][attr->nr] = orig_val;
+			ret = -EIO;
+		}
+	}
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t store_bank2_setting(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	u8 val = (simple_strtoul(buf, NULL, 10)*255 + ABIT_UGURU_FAN_MAX/2) /
+		ABIT_UGURU_FAN_MAX;
+	ssize_t ret = count;
+
+	/* this check can be done before taking the lock */
+	if ((val < abituguru_bank2_min_threshold) ||
+			(val > abituguru_bank2_max_threshold))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	if (data->bank2_settings[attr->index][attr->nr] != val) {
+		u8 orig_val = data->bank2_settings[attr->index][attr->nr];
+		data->bank2_settings[attr->index][attr->nr] = val;
+		if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK2 + 2,
+				attr->index, data->bank2_settings[attr->index],
+				2) <= attr->nr) {
+			data->bank2_settings[attr->index][attr->nr] = orig_val;
+			ret = -EIO;
+		}
+	}
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t show_bank1_alarm(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = abituguru_update_device(dev);
+	if (!data)
+		return -EIO;
+	/* See if the alarm bit for this sensor is set, and if the
+	   alarm matches the type of alarm we're looking for (for volt
+	   it can be either low or high). The type is stored in a few
+	   readonly bits in the settings part of the relevant sensor.
+	   The bitmask of the type is passed to us in attr->nr. */
+	if ((data->alarms[attr->index / 8] & (0x01 << (attr->index % 8))) &&
+			(data->bank1_settings[attr->index][0] & attr->nr))
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static ssize_t show_bank2_alarm(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = abituguru_update_device(dev);
+	if (!data)
+		return -EIO;
+	if (data->alarms[2] & (0x01 << attr->index))
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static ssize_t show_bank1_mask(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	if (data->bank1_settings[attr->index][0] & attr->nr)
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static ssize_t show_bank2_mask(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	if (data->bank2_settings[attr->index][0] & attr->nr)
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static ssize_t store_bank1_mask(struct device *dev,
+	struct device_attribute *devattr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	int mask = simple_strtoul(buf, NULL, 10);
+	ssize_t ret = count;
+	u8 orig_val;
+
+	mutex_lock(&data->update_lock);
+	orig_val = data->bank1_settings[attr->index][0];
+
+	if (mask)
+		data->bank1_settings[attr->index][0] |= attr->nr;
+	else
+		data->bank1_settings[attr->index][0] &= ~attr->nr;
+
+	if ((data->bank1_settings[attr->index][0] != orig_val) &&
+			(abituguru_write(data,
+			ABIT_UGURU_SENSOR_BANK1 + 2, attr->index,
+			data->bank1_settings[attr->index], 3) < 1)) {
+		data->bank1_settings[attr->index][0] = orig_val;
+		ret = -EIO;
+	}
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t store_bank2_mask(struct device *dev,
+	struct device_attribute *devattr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	int mask = simple_strtoul(buf, NULL, 10);
+	ssize_t ret = count;
+	u8 orig_val;
+
+	mutex_lock(&data->update_lock);
+	orig_val = data->bank2_settings[attr->index][0];
+
+	if (mask)
+		data->bank2_settings[attr->index][0] |= attr->nr;
+	else
+		data->bank2_settings[attr->index][0] &= ~attr->nr;
+
+	if ((data->bank2_settings[attr->index][0] != orig_val) &&
+			(abituguru_write(data,
+			ABIT_UGURU_SENSOR_BANK2 + 2, attr->index,
+			data->bank2_settings[attr->index], 2) < 1)) {
+		data->bank2_settings[attr->index][0] = orig_val;
+		ret = -EIO;
+	}
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+/* Fan PWM (speed control) */
+static ssize_t show_pwm_setting(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", data->pwm_settings[attr->index][attr->nr] *
+		abituguru_pwm_settings_multiplier[attr->nr]);
+}
+
+static ssize_t store_pwm_setting(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	u8 min, val = (simple_strtoul(buf, NULL, 10) +
+		abituguru_pwm_settings_multiplier[attr->nr]/2) /
+		abituguru_pwm_settings_multiplier[attr->nr];
+	ssize_t ret = count;
+
+	/* special case pwm1 min pwm% */
+	if ((attr->index == 0) && ((attr->nr == 1) || (attr->nr == 2)))
+		min = 77;
+	else
+		min = abituguru_pwm_min[attr->nr];
+
+	/* this check can be done before taking the lock */
+	if ((val < min) || (val > abituguru_pwm_max[attr->nr]))
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	/* this check needs to be done after taking the lock */
+	if ((attr->nr & 1) &&
+			(val >= data->pwm_settings[attr->index][attr->nr + 1]))
+		ret = -EINVAL;
+	else if (!(attr->nr & 1) &&
+			(val <= data->pwm_settings[attr->index][attr->nr - 1]))
+		ret = -EINVAL;
+	else if (data->pwm_settings[attr->index][attr->nr] != val) {
+		u8 orig_val = data->pwm_settings[attr->index][attr->nr];
+		data->pwm_settings[attr->index][attr->nr] = val;
+		if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
+				attr->index, data->pwm_settings[attr->index],
+				5) <= attr->nr) {
+			data->pwm_settings[attr->index][attr->nr] =
+				orig_val;
+			ret = -EIO;
+		}
+	}
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t show_pwm_sensor(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	int i;
+	/* We need to walk to the temp sensor addresses to find what
+	   the userspace id of the configured temp sensor is. */
+	for (i = 0; i < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; i++)
+		if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][i] ==
+				(data->pwm_settings[attr->index][0] & 0x0F))
+			return sprintf(buf, "%d\n", i+1);
+
+	return -ENXIO;
+}
+
+static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	unsigned long val = simple_strtoul(buf, NULL, 10) - 1;
+	ssize_t ret = count;
+
+	mutex_lock(&data->update_lock);
+	if (val < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) {
+		u8 orig_val = data->pwm_settings[attr->index][0];
+		u8 address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val];
+		data->pwm_settings[attr->index][0] &= 0xF0;
+		data->pwm_settings[attr->index][0] |= address;
+		if (data->pwm_settings[attr->index][0] != orig_val) {
+			if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
+					attr->index,
+					data->pwm_settings[attr->index],
+					5) < 1) {
+				data->pwm_settings[attr->index][0] = orig_val;
+				ret = -EIO;
+			}
+		}
+	}
+	else
+		ret = -EINVAL;
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	int res = 0;
+	if (data->pwm_settings[attr->index][0] & ABIT_UGURU_FAN_PWM_ENABLE)
+		res = 2;
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
+	*devattr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	u8 orig_val, user_val = simple_strtoul(buf, NULL, 10);
+	ssize_t ret = count;
+
+	mutex_lock(&data->update_lock);
+	orig_val = data->pwm_settings[attr->index][0];
+	switch (user_val) {
+		case 0:
+			data->pwm_settings[attr->index][0] &=
+				~ABIT_UGURU_FAN_PWM_ENABLE;
+			break;
+		case 2:
+			data->pwm_settings[attr->index][0] |=
+				ABIT_UGURU_FAN_PWM_ENABLE;
+			break;
+		default:
+			ret = -EINVAL;
+	}
+	if ((data->pwm_settings[attr->index][0] != orig_val) &&
+			(abituguru_write(data, ABIT_UGURU_FAN_PWM + 1,
+			attr->index, data->pwm_settings[attr->index],
+			5) < 1)) {
+		data->pwm_settings[attr->index][0] = orig_val;
+		ret = -EIO;
+	}
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static ssize_t show_name(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	return sprintf(buf, "%s\n", ABIT_UGURU_NAME);
+}
+
+/* Sysfs attr templates, the real entries are generated automatically. */
+static const
+struct sensor_device_attribute_2 abituguru_sysfs_bank1_templ[2][9] = {
+	{
+	SENSOR_ATTR_2(in%d_input, 0444, show_bank1_value, NULL, 0, 0),
+	SENSOR_ATTR_2(in%d_min, 0644, show_bank1_setting,
+		store_bank1_setting, 1, 0),
+	SENSOR_ATTR_2(in%d_min_alarm, 0444, show_bank1_alarm, NULL,
+		ABIT_UGURU_VOLT_LOW_ALARM_FLAG, 0),
+	SENSOR_ATTR_2(in%d_max, 0644, show_bank1_setting,
+		store_bank1_setting, 2, 0),
+	SENSOR_ATTR_2(in%d_max_alarm, 0444, show_bank1_alarm, NULL,
+		ABIT_UGURU_VOLT_HIGH_ALARM_FLAG, 0),
+	SENSOR_ATTR_2(in%d_beep, 0644, show_bank1_mask,
+		store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0),
+	SENSOR_ATTR_2(in%d_shutdown, 0644, show_bank1_mask,
+		store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0),
+	SENSOR_ATTR_2(in%d_min_alarm_enable, 0644, show_bank1_mask,
+		store_bank1_mask, ABIT_UGURU_VOLT_LOW_ALARM_ENABLE, 0),
+	SENSOR_ATTR_2(in%d_max_alarm_enable, 0644, show_bank1_mask,
+		store_bank1_mask, ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE, 0),
+	}, {
+	SENSOR_ATTR_2(temp%d_input, 0444, show_bank1_value, NULL, 0, 0),
+	SENSOR_ATTR_2(temp%d_alarm, 0444, show_bank1_alarm, NULL,
+		ABIT_UGURU_TEMP_HIGH_ALARM_FLAG, 0),
+	SENSOR_ATTR_2(temp%d_max, 0644, show_bank1_setting,
+		store_bank1_setting, 1, 0),
+	SENSOR_ATTR_2(temp%d_crit, 0644, show_bank1_setting,
+		store_bank1_setting, 2, 0),
+	SENSOR_ATTR_2(temp%d_beep, 0644, show_bank1_mask,
+		store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0),
+	SENSOR_ATTR_2(temp%d_shutdown, 0644, show_bank1_mask,
+		store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0),
+	SENSOR_ATTR_2(temp%d_alarm_enable, 0644, show_bank1_mask,
+		store_bank1_mask, ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE, 0),
+	}
+};
+
+static const struct sensor_device_attribute_2 abituguru_sysfs_fan_templ[6] = {
+	SENSOR_ATTR_2(fan%d_input, 0444, show_bank2_value, NULL, 0, 0),
+	SENSOR_ATTR_2(fan%d_alarm, 0444, show_bank2_alarm, NULL, 0, 0),
+	SENSOR_ATTR_2(fan%d_min, 0644, show_bank2_setting,
+		store_bank2_setting, 1, 0),
+	SENSOR_ATTR_2(fan%d_beep, 0644, show_bank2_mask,
+		store_bank2_mask, ABIT_UGURU_BEEP_ENABLE, 0),
+	SENSOR_ATTR_2(fan%d_shutdown, 0644, show_bank2_mask,
+		store_bank2_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0),
+	SENSOR_ATTR_2(fan%d_alarm_enable, 0644, show_bank2_mask,
+		store_bank2_mask, ABIT_UGURU_FAN_LOW_ALARM_ENABLE, 0),
+};
+
+static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] = {
+	SENSOR_ATTR_2(pwm%d_enable, 0644, show_pwm_enable,
+		store_pwm_enable, 0, 0),
+	SENSOR_ATTR_2(pwm%d_auto_channels_temp, 0644, show_pwm_sensor,
+		store_pwm_sensor, 0, 0),
+	SENSOR_ATTR_2(pwm%d_auto_point1_pwm, 0644, show_pwm_setting,
+		store_pwm_setting, 1, 0),
+	SENSOR_ATTR_2(pwm%d_auto_point2_pwm, 0644, show_pwm_setting,
+		store_pwm_setting, 2, 0),
+	SENSOR_ATTR_2(pwm%d_auto_point1_temp, 0644, show_pwm_setting,
+		store_pwm_setting, 3, 0),
+	SENSOR_ATTR_2(pwm%d_auto_point2_temp, 0644, show_pwm_setting,
+		store_pwm_setting, 4, 0),
+};
+
+static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = {
+	SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
+};
+
+static int __devinit abituguru_probe(struct platform_device *pdev)
+{
+	struct abituguru_data *data;
+	int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
+	char *sysfs_filename;
+
+	/* El weirdo probe order, to keep the sysfs order identical to the
+	   BIOS and window-appliction listing order. */
+	const u8 probe_order[ABIT_UGURU_MAX_BANK1_SENSORS] = {
+		0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02,
+		0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C };
+
+	if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL)))
+		return -ENOMEM;
+
+	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+	mutex_init(&data->update_lock);
+	platform_set_drvdata(pdev, data);
+
+	/* See if the uGuru is ready */
+	if (inb_p(data->addr + ABIT_UGURU_DATA) == ABIT_UGURU_STATUS_INPUT)
+		data->uguru_ready = 1;
+
+	/* Completely read the uGuru this has 2 purposes:
+	   - testread / see if one really is there.
+	   - make an in memory copy of all the uguru settings for future use. */
+	if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
+			data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3)
+		goto abituguru_probe_error;
+
+	for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
+		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i,
+				&data->bank1_value[i], 1,
+				ABIT_UGURU_MAX_RETRIES) != 1)
+			goto abituguru_probe_error;
+		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i,
+				data->bank1_settings[i], 3,
+				ABIT_UGURU_MAX_RETRIES) != 3)
+			goto abituguru_probe_error;
+	}
+	/* Note: We don't know how many bank2 sensors / pwms there really are,
+	   but in order to "detect" this we need to read the maximum amount
+	   anyways. If we read sensors/pwms not there we'll just read crap
+	   this can't hurt. We need the detection because we don't want
+	   unwanted writes, which will hurt! */
+	for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) {
+		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i,
+				&data->bank2_value[i], 1,
+				ABIT_UGURU_MAX_RETRIES) != 1)
+			goto abituguru_probe_error;
+		if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i,
+				data->bank2_settings[i], 2,
+				ABIT_UGURU_MAX_RETRIES) != 2)
+			goto abituguru_probe_error;
+	}
+	for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) {
+		if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i,
+				data->pwm_settings[i], 5,
+				ABIT_UGURU_MAX_RETRIES) != 5)
+			goto abituguru_probe_error;
+	}
+	data->last_updated = jiffies;
+
+	/* Detect sensor types and fill the sysfs attr for bank1 */
+	sysfs_attr_i = 0;
+	sysfs_filename = data->sysfs_names;
+	sysfs_names_free = ABITUGURU_SYSFS_NAMES_LENGTH;
+	for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
+		res = abituguru_detect_bank1_sensor_type(data, probe_order[i]);
+		if (res < 0)
+			goto abituguru_probe_error;
+		if (res == ABIT_UGURU_NC)
+			continue;
+
+		/* res 1 (temp) sensors have 7 sysfs entries, 0 (in) 9 */
+		for (j = 0; j < (res ? 7 : 9); j++) {
+			used = snprintf(sysfs_filename, sysfs_names_free,
+				abituguru_sysfs_bank1_templ[res][j].dev_attr.
+				attr.name, data->bank1_sensors[res] + res)
+				+ 1;
+			data->sysfs_attr[sysfs_attr_i] =
+				abituguru_sysfs_bank1_templ[res][j];
+			data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
+				sysfs_filename;
+			data->sysfs_attr[sysfs_attr_i].index = probe_order[i];
+			sysfs_filename += used;
+			sysfs_names_free -= used;
+			sysfs_attr_i++;
+		}
+		data->bank1_max_value[probe_order[i]] =
+			abituguru_bank1_max_value[res];
+		data->bank1_address[res][data->bank1_sensors[res]] =
+			probe_order[i];
+		data->bank1_sensors[res]++;
+	}
+	/* Detect number of sensors and fill the sysfs attr for bank2 (fans) */
+	abituguru_detect_no_bank2_sensors(data);
+	for (i = 0; i < data->bank2_sensors; i++) {
+		for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_fan_templ); j++) {
+			used = snprintf(sysfs_filename, sysfs_names_free,
+				abituguru_sysfs_fan_templ[j].dev_attr.attr.name,
+				i + 1) + 1;
+			data->sysfs_attr[sysfs_attr_i] =
+				abituguru_sysfs_fan_templ[j];
+			data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
+				sysfs_filename;
+			data->sysfs_attr[sysfs_attr_i].index = i;
+			sysfs_filename += used;
+			sysfs_names_free -= used;
+			sysfs_attr_i++;
+		}
+	}
+	/* Detect number of sensors and fill the sysfs attr for pwms */
+	abituguru_detect_no_pwms(data);
+	for (i = 0; i < data->pwms; i++) {
+		for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_pwm_templ); j++) {
+			used = snprintf(sysfs_filename, sysfs_names_free,
+				abituguru_sysfs_pwm_templ[j].dev_attr.attr.name,
+				i + 1) + 1;
+			data->sysfs_attr[sysfs_attr_i] =
+				abituguru_sysfs_pwm_templ[j];
+			data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
+				sysfs_filename;
+			data->sysfs_attr[sysfs_attr_i].index = i;
+			sysfs_filename += used;
+			sysfs_names_free -= used;
+			sysfs_attr_i++;
+		}
+	}
+	/* Fail safe check, this should never happen! */
+	if (sysfs_names_free < 0) {
+		printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of "
+		       "space for sysfs attr names. This should never "
+		       "happen please report to the abituguru maintainer "
+		       "(see MAINTAINERS)\n");
+		res = -ENAMETOOLONG;
+		goto abituguru_probe_error;
+	}
+	printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n");
+
+	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->class_dev)) {
+		res = PTR_ERR(data->class_dev);
+		goto abituguru_probe_error;
+	}
+	for (i = 0; i < sysfs_attr_i; i++)
+		device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
+		device_create_file(&pdev->dev,
+			&abituguru_sysfs_attr[i].dev_attr);
+
+	return 0;
+
+abituguru_probe_error:
+	kfree(data);
+	return res;
+}
+
+static int __devexit abituguru_remove(struct platform_device *pdev)
+{
+	struct abituguru_data *data = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	hwmon_device_unregister(data->class_dev);
+	kfree(data);
+
+	return 0;
+}
+
+static struct abituguru_data *abituguru_update_device(struct device *dev)
+{
+	int i, err;
+	struct abituguru_data *data = dev_get_drvdata(dev);
+	/* fake a complete successful read if no update necessary. */
+	char success = 1;
+
+	mutex_lock(&data->update_lock);
+	if (time_after(jiffies, data->last_updated + HZ)) {
+		success = 0;
+		if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
+				data->alarms, 3, 0)) != 3)
+			goto LEAVE_UPDATE;
+		for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) {
+			if ((err = abituguru_read(data,
+					ABIT_UGURU_SENSOR_BANK1, i,
+					&data->bank1_value[i], 1, 0)) != 1)
+				goto LEAVE_UPDATE;
+			if ((err = abituguru_read(data,
+					ABIT_UGURU_SENSOR_BANK1 + 1, i,
+					data->bank1_settings[i], 3, 0)) != 3)
+				goto LEAVE_UPDATE;
+		}
+		for (i = 0; i < data->bank2_sensors; i++)
+			if ((err = abituguru_read(data,
+					ABIT_UGURU_SENSOR_BANK2, i,
+					&data->bank2_value[i], 1, 0)) != 1)
+				goto LEAVE_UPDATE;
+		/* success! */
+		success = 1;
+		data->update_timeouts = 0;
+LEAVE_UPDATE:
+		/* handle timeout condition */
+		if (err == -EBUSY) {
+			/* No overflow please */
+			if (data->update_timeouts < 255u)
+				data->update_timeouts++;
+			if (data->update_timeouts <= ABIT_UGURU_MAX_TIMEOUTS) {
+				ABIT_UGURU_DEBUG(3, "timeout exceeded, will "
+					"try again next update\n");
+				/* Just a timeout, fake a successful read */
+				success = 1;
+			} else
+				ABIT_UGURU_DEBUG(1, "timeout exceeded %d "
+					"times waiting for more input state\n",
+					(int)data->update_timeouts);
+		}
+		/* On success set last_updated */
+		if (success)
+			data->last_updated = jiffies;
+	}
+	mutex_unlock(&data->update_lock);
+
+	if (success)
+		return data;
+	else
+		return NULL;
+}
+
+static struct platform_driver abituguru_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= ABIT_UGURU_NAME,
+	},
+	.probe	= abituguru_probe,
+	.remove	= __devexit_p(abituguru_remove),
+};
+
+static int __init abituguru_detect(void)
+{
+	/* See if there is an uguru there. After a reboot uGuru will hold 0x00
+	   at DATA and 0xAC, when this driver has already been loaded once
+	   DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either
+	   scenario but some will hold 0x00.
+	   Some uGuru's initally hold 0x09 at DATA and will only hold 0x08
+	   after reading CMD first, so CMD must be read first! */
+	u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD);
+	u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA);
+	if (((data_val == 0x00) || (data_val == 0x08)) &&
+	    ((cmd_val == 0x00) || (cmd_val == 0xAC)))
+		return ABIT_UGURU_BASE;
+
+	ABIT_UGURU_DEBUG(2, "no Abit uGuru found, data = 0x%02X, cmd = "
+		"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
+
+	if (force) {
+		printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is "
+				"present because of \"force\" parameter\n");
+		return ABIT_UGURU_BASE;
+	}
+
+	/* No uGuru found */
+	return -ENODEV;
+}
+
+static struct platform_device *abituguru_pdev;
+
+static int __init abituguru_init(void)
+{
+	int address, err;
+	struct resource res = { .flags = IORESOURCE_IO };
+
+	address = abituguru_detect();
+	if (address < 0)
+		return address;
+
+	err = platform_driver_register(&abituguru_driver);
+	if (err)
+		goto exit;
+
+	abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address);
+	if (!abituguru_pdev) {
+		printk(KERN_ERR ABIT_UGURU_NAME
+			": Device allocation failed\n");
+		err = -ENOMEM;
+		goto exit_driver_unregister;
+	}
+
+	res.start = address;
+	res.end = address + ABIT_UGURU_REGION_LENGTH - 1;
+	res.name = ABIT_UGURU_NAME;
+
+	err = platform_device_add_resources(abituguru_pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR ABIT_UGURU_NAME
+			": Device resource addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(abituguru_pdev);
+	if (err) {
+		printk(KERN_ERR ABIT_UGURU_NAME
+			": Device addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(abituguru_pdev);
+exit_driver_unregister:
+	platform_driver_unregister(&abituguru_driver);
+exit:
+	return err;
+}
+
+static void __exit abituguru_exit(void)
+{
+	platform_device_unregister(abituguru_pdev);
+	platform_driver_unregister(&abituguru_driver);
+}
+
+MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_DESCRIPTION("Abit uGuru Sensor device");
+MODULE_LICENSE("GPL");
+
+module_init(abituguru_init);
+module_exit(abituguru_exit);
diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c
index 65b2709..facc1cc 100644
--- a/drivers/hwmon/asb100.c
+++ b/drivers/hwmon/asb100.c
@@ -341,7 +341,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t set_fan_div(struct device *dev, const char *buf,
 				size_t count, int nr)
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 885465d..fd72440 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -99,10 +99,6 @@
 #define ADDR_REG_OFFSET		0
 #define DATA_REG_OFFSET		1
 
-static struct resource f71805f_resource __initdata = {
-	.flags	= IORESOURCE_IO,
-};
-
 /*
  * Registers
  */
@@ -782,6 +778,11 @@
 
 static int __init f71805f_device_add(unsigned short address)
 {
+	struct resource res = {
+		.start	= address,
+		.end	= address + REGION_LENGTH - 1,
+		.flags	= IORESOURCE_IO,
+	};
 	int err;
 
 	pdev = platform_device_alloc(DRVNAME, address);
@@ -791,10 +792,8 @@
 		goto exit;
 	}
 
-	f71805f_resource.start = address;
-	f71805f_resource.end = address + REGION_LENGTH - 1;
-	f71805f_resource.name = pdev->name;
-	err = platform_device_add_resources(pdev, &f71805f_resource, 1);
+	res.name = pdev->name;
+	err = platform_device_add_resources(pdev, &res, 1);
 	if (err) {
 		printk(KERN_ERR DRVNAME ": Device resource addition failed "
 		       "(%d)\n", err);
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index 1659f6c..42b6328 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -41,7 +41,7 @@
 #define HDAPS_PORT_STATE	0x1611	/* device state */
 #define HDAPS_PORT_YPOS		0x1612	/* y-axis position */
 #define	HDAPS_PORT_XPOS		0x1614	/* x-axis position */
-#define HDAPS_PORT_TEMP1	0x1616	/* device temperature, in celcius */
+#define HDAPS_PORT_TEMP1	0x1616	/* device temperature, in Celsius */
 #define HDAPS_PORT_YVAR		0x1617	/* y-axis variance (what is this?) */
 #define HDAPS_PORT_XVAR		0x1619	/* x-axis variance (what is this?) */
 #define HDAPS_PORT_TEMP2	0x161b	/* device temperature (again?) */
@@ -522,13 +522,15 @@
 {
 	int ret;
 
-	/* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */
+	/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
+	  "ThinkPad T42p", so the order of the entries matters */
 	struct dmi_system_id hdaps_whitelist[] = {
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),
 		HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad R52"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad H"),	 /* R52 (1846AQG) */
 		HDAPS_DMI_MATCH_INVERT("ThinkPad T41p"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad T41"),
 		HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"),
@@ -536,9 +538,9 @@
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
 		HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
-		HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
 		HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"),
 		HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"),
+		HDAPS_DMI_MATCH_NORMAL("ThinkPad Z60m"),
 		{ .ident = NULL }
 	};
 
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
index a74a44f..a6764ff 100644
--- a/drivers/hwmon/hwmon-vid.c
+++ b/drivers/hwmon/hwmon-vid.c
@@ -58,11 +58,20 @@
     doesn't seem to be any named specification for these. The conversion
     tables are detailed directly in the various Pentium M datasheets:
     http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm
+
+    The 14 specification corresponds to Intel Core series. There
+    doesn't seem to be any named specification for these. The conversion
+    tables are detailed directly in the various Pentium Core datasheets:
+    http://www.intel.com/design/mobile/datashts/309221.htm
+
+    The 110 (VRM 11) specification corresponds to Intel Conroe based series.
+    http://www.intel.com/design/processor/applnots/313214.htm
 */
 
 /* vrm is the VRM/VRD document version multiplied by 10.
-   val is the 4-, 5- or 6-bit VID code.
-   Returned value is in mV to avoid floating point in the kernel. */
+   val is the 4-bit or more VID code.
+   Returned value is in mV to avoid floating point in the kernel.
+   Some VID have some bits in uV scale, this is rounded to mV */
 int vid_from_reg(int val, u8 vrm)
 {
 	int vid;
@@ -70,26 +79,36 @@
 	switch(vrm) {
 
 	case 100:               /* VRD 10.0 */
+		/* compute in uV, round to mV */
+		val &= 0x3f;
 		if((val & 0x1f) == 0x1f)
 			return 0;
 		if((val & 0x1f) <= 0x09 || val == 0x0a)
-			vid = 10875 - (val & 0x1f) * 250;
+			vid = 1087500 - (val & 0x1f) * 25000;
 		else
-			vid = 18625 - (val & 0x1f) * 250;
+			vid = 1862500 - (val & 0x1f) * 25000;
 		if(val & 0x20)
-			vid -= 125;
-		vid /= 10;      /* only return 3 dec. places for now */
-		return vid;
+			vid -= 12500;
+		return((vid + 500) / 1000);
 
+	case 110:		/* Intel Conroe */
+				/* compute in uV, round to mV */
+		val &= 0xff;
+		if(((val & 0x7e) == 0xfe) || (!(val & 0x7e)))
+			return 0;
+		return((1600000 - (val - 2) * 6250 + 500) / 1000);
 	case 24:                /* Opteron processor */
+		val &= 0x1f;
 		return(val == 0x1f ? 0 : 1550 - val * 25);
 
 	case 91:		/* VRM 9.1 */
 	case 90:		/* VRM 9.0 */
+		val &= 0x1f;
 		return(val == 0x1f ? 0 :
 		                       1850 - val * 25);
 
 	case 85:		/* VRM 8.5 */
+		val &= 0x1f;
 		return((val & 0x10  ? 25 : 0) +
 		       ((val & 0x0f) > 0x04 ? 2050 : 1250) -
 		       ((val & 0x0f) * 50));
@@ -98,14 +117,21 @@
 		val &= 0x0f;
 				/* fall through */
 	case 82:		/* VRM 8.2 */
+		val &= 0x1f;
 		return(val == 0x1f ? 0 :
 		       val & 0x10  ? 5100 - (val) * 100 :
 		                     2050 - (val) * 50);
 	case 17:		/* Intel IMVP-II */
+		val &= 0x1f;
 		return(val & 0x10 ? 975 - (val & 0xF) * 25 :
 				    1750 - val * 50);
 	case 13:
-		return(1708 - (val & 0x3f) * 16);
+		val &= 0x3f;
+		return(1708 - val * 16);
+	case 14:		/* Intel Core */
+				/* compute in uV, round to mV */
+		val &= 0x7f;
+		return(val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000);
 	default:		/* report 0 for unknown */
 		printk(KERN_INFO "hwmon-vid: requested unknown VRM version\n");
 		return 0;
@@ -138,6 +164,8 @@
 	{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13},		/* Pentium M (130 nm) */
 	{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85},		/* Tualatin */
 	{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13},		/* Pentium M (90 nm) */
+	{X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14},		/* Intel Core (65 nm) */
+	{X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110},		/* Intel Conroe */
 	{X86_VENDOR_INTEL, 0x6, ANY, ANY, 82},		/* any P6 */
 	{X86_VENDOR_INTEL, 0x7, ANY, ANY, 0},		/* Itanium */
 	{X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90},		/* P4 */
diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c
new file mode 100644
index 0000000..6ba8473
--- /dev/null
+++ b/drivers/hwmon/lm70.c
@@ -0,0 +1,165 @@
+/*
+ * lm70.c
+ *
+ * The LM70 is a temperature sensor chip from National Semiconductor (NS).
+ * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com>
+ *
+ * The LM70 communicates with a host processor via an SPI/Microwire Bus
+ * interface. The complete datasheet is available at National's website
+ * here:
+ * http://www.national.com/pf/LM/LM70.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/spi/spi.h>
+#include <asm/semaphore.h>
+
+#define DRVNAME		"lm70"
+
+struct lm70 {
+	struct class_device *cdev;
+	struct semaphore sem;
+};
+
+/* sysfs hook function */
+static ssize_t lm70_sense_temp(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	int status, val;
+	u8 rxbuf[2];
+	s16 raw=0;
+	struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
+
+	if (down_interruptible(&p_lm70->sem))
+		return -ERESTARTSYS;
+
+	/*
+	 * spi_read() requires a DMA-safe buffer; so we use
+	 * spi_write_then_read(), transmitting 0 bytes.
+	 */
+	status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2);
+	if (status < 0) {
+		printk(KERN_WARNING
+		"spi_write_then_read failed with status %d\n", status);
+		goto out;
+	}
+	dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]);
+
+	raw = (rxbuf[1] << 8) + rxbuf[0];
+	dev_dbg(dev, "raw=0x%x\n", raw);
+
+	/*
+	 * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's
+	 * complement value. Only the MSB 11 bits (1 sign + 10 temperature
+	 * bits) are meaningful; the LSB 5 bits are to be discarded.
+	 * See the datasheet.
+	 *
+	 * Further, each bit represents 0.25 degrees Celsius; so, multiply
+	 * by 0.25. Also multiply by 1000 to represent in millidegrees
+	 * Celsius.
+	 * So it's equivalent to multiplying by 0.25 * 1000 = 250.
+	 */
+	val = ((int)raw/32) * 250;
+	status = sprintf(buf, "%+d\n", val); /* millidegrees Celsius */
+out:
+	up(&p_lm70->sem);
+	return status;
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL);
+
+/*----------------------------------------------------------------------*/
+
+static int __devinit lm70_probe(struct spi_device *spi)
+{
+	struct lm70 *p_lm70;
+	int status;
+
+	p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL);
+	if (!p_lm70)
+		return -ENOMEM;
+
+	init_MUTEX(&p_lm70->sem);
+
+	/* sysfs hook */
+	p_lm70->cdev = hwmon_device_register(&spi->dev);
+	if (IS_ERR(p_lm70->cdev)) {
+		dev_dbg(&spi->dev, "hwmon_device_register failed.\n");
+		status = PTR_ERR(p_lm70->cdev);
+		goto out_dev_reg_failed;
+	}
+	dev_set_drvdata(&spi->dev, p_lm70);
+
+	if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))) {
+		dev_dbg(&spi->dev, "device_create_file failure.\n");
+		goto out_dev_create_file_failed;
+	}
+
+	return 0;
+
+out_dev_create_file_failed:
+	hwmon_device_unregister(p_lm70->cdev);
+out_dev_reg_failed:
+	dev_set_drvdata(&spi->dev, NULL);
+	kfree(p_lm70);
+	return status;
+}
+
+static int __exit lm70_remove(struct spi_device *spi)
+{
+	struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev);
+
+	device_remove_file(&spi->dev, &dev_attr_temp1_input);
+	hwmon_device_unregister(p_lm70->cdev);
+	dev_set_drvdata(&spi->dev, NULL);
+	kfree(p_lm70);
+
+	return 0;
+}
+
+static struct spi_driver lm70_driver = {
+	.driver = {
+		.name	= "lm70",
+		.owner	= THIS_MODULE,
+	},
+	.probe	= lm70_probe,
+	.remove	= __devexit_p(lm70_remove),
+};
+
+static int __init init_lm70(void)
+{
+	return spi_register_driver(&lm70_driver);
+}
+
+static void __exit cleanup_lm70(void)
+{
+	spi_unregister_driver(&lm70_driver);
+}
+
+module_init(init_lm70);
+module_exit(cleanup_lm70);
+
+MODULE_AUTHOR("Kaiwan N Billimoria");
+MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 94be3d7..a6ce7ab 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -358,7 +358,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t set_fan_div(struct device *dev, const char *buf,
 	size_t count, int nr)
diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c
index f72120d..b4ccdfc 100644
--- a/drivers/hwmon/lm80.c
+++ b/drivers/hwmon/lm80.c
@@ -253,7 +253,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t set_fan_div(struct device *dev, const char *buf,
 	size_t count, int nr)
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index aac4ec2..2137d78 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -12,6 +12,10 @@
  * Since the datasheet omits to give the chip stepping code, I give it
  * here: 0x03 (at register 0xff).
  *
+ * Also supports the LM82 temp sensor, which is basically a stripped down
+ * model of the LM83.  Datasheet is here:
+ * http://www.national.com/pf/LM/LM82.html
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -52,7 +56,7 @@
  * Insmod parameters
  */
 
-I2C_CLIENT_INSMOD_1(lm83);
+I2C_CLIENT_INSMOD_2(lm83, lm82);
 
 /*
  * The LM83 registers
@@ -283,6 +287,9 @@
 		if (man_id == 0x01) { /* National Semiconductor */
 			if (chip_id == 0x03) {
 				kind = lm83;
+			} else
+			if (chip_id == 0x01) {
+				kind = lm82;
 			}
 		}
 
@@ -296,6 +303,9 @@
 
 	if (kind == lm83) {
 		name = "lm83";
+	} else
+	if (kind == lm82) {
+		name = "lm82";
 	}
 
 	/* We can fill in the remaining client fields */
@@ -319,32 +329,46 @@
 		goto exit_detach;
 	}
 
+	/*
+	 * The LM82 can only monitor one external diode which is
+	 * at the same register as the LM83 temp3 entry - so we
+	 * declare 1 and 3 common, and then 2 and 4 only for the LM83.
+	 */
+
 	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp1_input.dev_attr);
 	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_input.dev_attr);
-	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp3_input.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp4_input.dev_attr);
+
 	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp1_max.dev_attr);
 	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_max.dev_attr);
-	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp3_max.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp4_max.dev_attr);
+
 	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp1_crit.dev_attr);
 	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp2_crit.dev_attr);
-	device_create_file(&new_client->dev,
 			   &sensor_dev_attr_temp3_crit.dev_attr);
-	device_create_file(&new_client->dev,
-			   &sensor_dev_attr_temp4_crit.dev_attr);
+
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
+	if (kind == lm83) {
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_temp2_input.dev_attr);
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_temp4_input.dev_attr);
+
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_temp2_max.dev_attr);
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_temp4_max.dev_attr);
+
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_temp2_crit.dev_attr);
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_temp4_crit.dev_attr);
+	}
+
 	return 0;
 
 exit_detach:
diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c
index e229daf..e6c1b63 100644
--- a/drivers/hwmon/lm87.c
+++ b/drivers/hwmon/lm87.c
@@ -421,7 +421,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan clock divider.  This follows the principle
-   of least suprise; the user doesn't expect the fan minimum to change just
+   of least surprise; the user doesn't expect the fan minimum to change just
    because the divider changed. */
 static ssize_t set_fan_div(struct device *dev, const char *buf,
 		size_t count, int nr)
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 6f3fda7..063f71c 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -380,7 +380,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t set_fan_div(struct device *dev, const char *buf,
 	size_t count, int nr)
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 7732aec..825e8f7 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -207,7 +207,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan clock divider.  This follows the principle
-   of least suprise; the user doesn't expect the fan minimum to change just
+   of least surprise; the user doesn't expect the fan minimum to change just
    because the divider changed. */
 static ssize_t set_fan_div(struct device *dev, const char *buf,
 		size_t count, int nr)
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
new file mode 100644
index 0000000..bdc4570
--- /dev/null
+++ b/drivers/hwmon/smsc47m192.c
@@ -0,0 +1,648 @@
+/*
+    smsc47m192.c - Support for hardware monitoring block of
+                   SMSC LPC47M192 and LPC47M997 Super I/O chips
+
+    Copyright (C) 2006  Hartmut Rick <linux@rick.claranet.de>
+
+    Derived from lm78.c and other chip drivers.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(smsc47m192);
+
+/* SMSC47M192 registers */
+#define SMSC47M192_REG_IN(nr)		((nr)<6 ? (0x20 + (nr)) : \
+					(0x50 + (nr) - 6))
+#define SMSC47M192_REG_IN_MAX(nr)	((nr)<6 ? (0x2b + (nr) * 2) : \
+					(0x54 + (((nr) - 6) * 2)))
+#define SMSC47M192_REG_IN_MIN(nr)	((nr)<6 ? (0x2c + (nr) * 2) : \
+					(0x55 + (((nr) - 6) * 2)))
+static u8 SMSC47M192_REG_TEMP[3] =	{ 0x27, 0x26, 0x52 };
+static u8 SMSC47M192_REG_TEMP_MAX[3] =	{ 0x39, 0x37, 0x58 };
+static u8 SMSC47M192_REG_TEMP_MIN[3] =	{ 0x3A, 0x38, 0x59 };
+#define SMSC47M192_REG_TEMP_OFFSET(nr)	((nr)==2 ? 0x1e : 0x1f)
+#define SMSC47M192_REG_ALARM1		0x41
+#define SMSC47M192_REG_ALARM2		0x42
+#define SMSC47M192_REG_VID		0x47
+#define SMSC47M192_REG_VID4		0x49
+#define SMSC47M192_REG_CONFIG		0x40
+#define SMSC47M192_REG_SFR		0x4f
+#define SMSC47M192_REG_COMPANY_ID	0x3e
+#define SMSC47M192_REG_VERSION		0x3f
+
+/* generalised scaling with integer rounding */
+static inline int SCALE(long val, int mul, int div)
+{
+	if (val < 0)
+		return (val * mul - div / 2) / div;
+	else
+		return (val * mul + div / 2) / div;
+}
+
+/* Conversions */
+
+/* smsc47m192 internally scales voltage measurements */
+static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 };
+
+static inline unsigned int IN_FROM_REG(u8 reg, int n)
+{
+	return SCALE(reg, nom_mv[n], 192);
+}
+
+static inline u8 IN_TO_REG(unsigned long val, int n)
+{
+	return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
+}
+
+/* TEMP: 0.001 degC units (-128C to +127C)
+   REG: 1C/bit, two's complement */
+static inline s8 TEMP_TO_REG(int val)
+{
+	return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000);
+}
+
+static inline int TEMP_FROM_REG(s8 val)
+{
+	return val * 1000;
+}
+
+struct smsc47m192_data {
+	struct i2c_client client;
+	struct class_device *class_dev;
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	u8 in[8];		/* Register value */
+	u8 in_max[8];		/* Register value */
+	u8 in_min[8];		/* Register value */
+	s8 temp[3];		/* Register value */
+	s8 temp_max[3];		/* Register value */
+	s8 temp_min[3];		/* Register value */
+	s8 temp_offset[3];	/* Register value */
+	u16 alarms;		/* Register encoding, combined */
+	u8 vid;			/* Register encoding, combined */
+	u8 vrm;
+};
+
+static int smsc47m192_attach_adapter(struct i2c_adapter *adapter);
+static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
+		int kind);
+static int smsc47m192_detach_client(struct i2c_client *client);
+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev);
+
+static struct i2c_driver smsc47m192_driver = {
+	.driver = {
+		.name	= "smsc47m192",
+	},
+	.attach_adapter	= smsc47m192_attach_adapter,
+	.detach_client	= smsc47m192_detach_client,
+};
+
+/* Voltages */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+}
+
+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
+}
+
+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
+}
+
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_min[nr] = IN_TO_REG(val, nr);
+	i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr),
+							data->in_min[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->in_max[nr] = IN_TO_REG(val, nr);
+	i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr),
+							data->in_max[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+#define show_in_offset(offset)					\
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
+		show_in, NULL, offset);				\
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_in_min, set_in_min, offset);		\
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_in_max, set_in_max, offset);
+
+show_in_offset(0)
+show_in_offset(1)
+show_in_offset(2)
+show_in_offset(3)
+show_in_offset(4)
+show_in_offset(5)
+show_in_offset(6)
+show_in_offset(7)
+
+/* Temperatures */
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
+}
+
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr]));
+}
+
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_min[nr] = TEMP_TO_REG(val);
+	i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr],
+						data->temp_min[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_max[nr] = TEMP_TO_REG(val);
+	i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr],
+						data->temp_max[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp_offset(struct device *dev, struct device_attribute
+		*attr, char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
+}
+
+static ssize_t set_temp_offset(struct device *dev, struct device_attribute
+		*attr, const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp_offset[nr] = TEMP_TO_REG(val);
+	if (nr>1)
+		i2c_smbus_write_byte_data(client,
+			SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
+	else if (data->temp_offset[nr] != 0) {
+		/* offset[0] and offset[1] share the same register,
+			SFR bit 4 activates offset[0] */
+		i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
+					(sfr & 0xef) | (nr==0 ? 0x10 : 0));
+		data->temp_offset[1-nr] = 0;
+		i2c_smbus_write_byte_data(client,
+			SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]);
+	} else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0))
+		i2c_smbus_write_byte_data(client,
+					SMSC47M192_REG_TEMP_OFFSET(nr), 0);
+	up(&data->update_lock);
+	return count;
+}
+
+#define show_temp_index(index)						\
+static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO,			\
+		show_temp, NULL, index-1);				\
+static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR,		\
+		show_temp_min, set_temp_min, index-1);			\
+static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR,		\
+		show_temp_max, set_temp_max, index-1);			\
+static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR,	\
+		show_temp_offset, set_temp_offset, index-1);
+
+show_temp_index(1)
+show_temp_index(2)
+show_temp_index(3)
+
+/* VID */
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	data->vrm = simple_strtoul(buf, NULL, 10);
+	return count;
+}
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
+
+/* Alarms */
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct smsc47m192_data *data = smsc47m192_update_device(dev);
+	return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0);
+}
+
+static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010);
+static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020);
+static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040);
+static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000);
+static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000);
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800);
+
+/* This function is called when:
+    * smsc47m192_driver is inserted (when this module is loaded), for each
+      available adapter
+    * when a new adapter is inserted (and smsc47m192_driver is still present) */
+static int smsc47m192_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, smsc47m192_detect);
+}
+
+static void smsc47m192_init_client(struct i2c_client *client)
+{
+	int i;
+	u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
+	u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+
+	/* select cycle mode (pause 1 sec between updates) */
+	i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR,
+						(sfr & 0xfd) | 0x02);
+	if (!(config & 0x01)) {
+		/* initialize alarm limits */
+		for (i=0; i<8; i++) {
+			i2c_smbus_write_byte_data(client,
+				SMSC47M192_REG_IN_MIN(i), 0);
+			i2c_smbus_write_byte_data(client,
+				SMSC47M192_REG_IN_MAX(i), 0xff);
+		}
+		for (i=0; i<3; i++) {
+			i2c_smbus_write_byte_data(client,
+				SMSC47M192_REG_TEMP_MIN[i], 0x80);
+			i2c_smbus_write_byte_data(client,
+				SMSC47M192_REG_TEMP_MAX[i], 0x7f);
+		}
+
+		/* start monitoring */
+		i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG,
+						(config & 0xf7) | 0x01);
+	}
+}
+
+/* This function is called by i2c_probe */
+static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
+		int kind)
+{
+	struct i2c_client *client;
+	struct smsc47m192_data *data;
+	int err = 0;
+	int version, config;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &smsc47m192_driver;
+
+	if (kind == 0)
+		kind = smsc47m192;
+
+	/* Detection criteria from sensors_detect script */
+	if (kind < 0) {
+		if (i2c_smbus_read_byte_data(client,
+				SMSC47M192_REG_COMPANY_ID) == 0x55
+		 && ((version = i2c_smbus_read_byte_data(client,
+				SMSC47M192_REG_VERSION)) & 0xf0) == 0x20
+		 && (i2c_smbus_read_byte_data(client,
+				SMSC47M192_REG_VID) & 0x70) == 0x00
+		 && (i2c_smbus_read_byte_data(client,
+				SMSC47M192_REG_VID4) & 0xfe) == 0x80) {
+			dev_info(&adapter->dev,
+				 "found SMSC47M192 or SMSC47M997, "
+				 "version 2, stepping A%d\n", version & 0x0f);
+		} else {
+			dev_dbg(&adapter->dev,
+				"SMSC47M192 detection failed at 0x%02x\n",
+				address);
+			goto exit_free;
+		}
+	}
+
+	/* Fill in the remaining client fields and put into the global list */
+	strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE);
+	data->vrm = vid_which_vrm();
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto exit_free;
+
+	/* Initialize the SMSC47M192 chip */
+	smsc47m192_init_client(client);
+
+	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_detach;
+	}
+
+	device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr);
+
+	/* Pin 110 is either in4 (+12V) or VID4 */
+	config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG);
+	if (!(config & 0x20)) {
+		device_create_file(&client->dev,
+				   &sensor_dev_attr_in4_input.dev_attr);
+		device_create_file(&client->dev,
+				   &sensor_dev_attr_in4_min.dev_attr);
+		device_create_file(&client->dev,
+				   &sensor_dev_attr_in4_max.dev_attr);
+		device_create_file(&client->dev,
+				   &sensor_dev_attr_in4_alarm.dev_attr);
+	}
+	device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+	device_create_file(&client->dev,
+			   &sensor_dev_attr_temp1_offset.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+	device_create_file(&client->dev,
+			   &sensor_dev_attr_temp2_offset.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr);
+	device_create_file(&client->dev,
+			   &sensor_dev_attr_temp2_input_fault.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+	device_create_file(&client->dev,
+			   &sensor_dev_attr_temp3_offset.dev_attr);
+	device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr);
+	device_create_file(&client->dev,
+			   &sensor_dev_attr_temp3_input_fault.dev_attr);
+	device_create_file(&client->dev, &dev_attr_cpu0_vid);
+	device_create_file(&client->dev, &dev_attr_vrm);
+
+	return 0;
+
+exit_detach:
+	i2c_detach_client(client);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int smsc47m192_detach_client(struct i2c_client *client)
+{
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	int err;
+
+	hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
+
+	return 0;
+}
+
+static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct smsc47m192_data *data = i2c_get_clientdata(client);
+	int i, config;
+
+	down(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	 || !data->valid) {
+		u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
+
+		dev_dbg(&client->dev, "Starting smsc47m192 update\n");
+
+		for (i = 0; i <= 7; i++) {
+			data->in[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_IN(i));
+			data->in_min[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_IN_MIN(i));
+			data->in_max[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_IN_MAX(i));
+		}
+		for (i = 0; i < 3; i++) {
+			data->temp[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP[i]);
+			data->temp_max[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP_MAX[i]);
+			data->temp_min[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP_MIN[i]);
+		}
+		for (i = 1; i < 3; i++)
+			data->temp_offset[i] = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_TEMP_OFFSET(i));
+		/* first offset is temp_offset[0] if SFR bit 4 is set,
+					temp_offset[1] otherwise */
+		if (sfr & 0x10) {
+			data->temp_offset[0] = data->temp_offset[1];
+			data->temp_offset[1] = 0;
+		} else
+			data->temp_offset[0] = 0;
+
+		data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID)
+			    & 0x0f;
+		config = i2c_smbus_read_byte_data(client,
+						  SMSC47M192_REG_CONFIG);
+		if (config & 0x20)
+			data->vid |= (i2c_smbus_read_byte_data(client,
+					SMSC47M192_REG_VID4) & 0x01) << 4;
+		data->alarms = i2c_smbus_read_byte_data(client,
+						SMSC47M192_REG_ALARM1) |
+			       (i2c_smbus_read_byte_data(client,
+		       				SMSC47M192_REG_ALARM2) << 8);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return data;
+}
+
+static int __init smsc47m192_init(void)
+{
+	return i2c_add_driver(&smsc47m192_driver);
+}
+
+static void __exit smsc47m192_exit(void)
+{
+	i2c_del_driver(&smsc47m192_driver);
+}
+
+MODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>");
+MODULE_DESCRIPTION("SMSC47M192 driver");
+MODULE_LICENSE("GPL");
+
+module_init(smsc47m192_init);
+module_exit(smsc47m192_exit);
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index b6bd568..40301bc 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -30,10 +30,7 @@
     Supports the following chips:
 
     Chip        #vin    #fan    #pwm    #temp   chip_id man_id
-    w83627ehf   -       5       -       3       0x88    0x5ca3
-
-    This is a preliminary version of the driver, only supporting the
-    fan and temperature inputs. The chip does much more than that.
+    w83627ehf   10      5       -       3       0x88    0x5ca3
 */
 
 #include <linux/module.h>
@@ -121,6 +118,14 @@
 static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
 static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
 
+/* The W83627EHF registers for nr=7,8,9 are in bank 5 */
+#define W83627EHF_REG_IN_MAX(nr)	((nr < 7) ? (0x2b + (nr) * 2) : \
+					 (0x554 + (((nr) - 7) * 2)))
+#define W83627EHF_REG_IN_MIN(nr)	((nr < 7) ? (0x2c + (nr) * 2) : \
+					 (0x555 + (((nr) - 7) * 2)))
+#define W83627EHF_REG_IN(nr)		((nr < 7) ? (0x20 + (nr)) : \
+					 (0x550 + (nr) - 7))
+
 #define W83627EHF_REG_TEMP1		0x27
 #define W83627EHF_REG_TEMP1_HYST	0x3a
 #define W83627EHF_REG_TEMP1_OVER	0x39
@@ -136,6 +141,10 @@
 #define W83627EHF_REG_DIODE		0x59
 #define W83627EHF_REG_SMI_OVT		0x4C
 
+#define W83627EHF_REG_ALARM1		0x459
+#define W83627EHF_REG_ALARM2		0x45A
+#define W83627EHF_REG_ALARM3		0x45B
+
 /*
  * Conversions
  */
@@ -172,6 +181,20 @@
 	return (temp + 500) / 1000;
 }
 
+/* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
+
+static u8 scale_in[10] = { 8, 8, 16, 16, 8, 8, 8, 16, 16, 8 };
+
+static inline long in_from_reg(u8 reg, u8 nr)
+{
+	return reg * scale_in[nr];
+}
+
+static inline u8 in_to_reg(u32 val, u8 nr)
+{
+	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255);
+}
+
 /*
  * Data structures and manipulation thereof
  */
@@ -186,6 +209,9 @@
 	unsigned long last_updated;	/* In jiffies */
 
 	/* Register values */
+	u8 in[10];		/* Register value */
+	u8 in_max[10];		/* Register value */
+	u8 in_min[10];		/* Register value */
 	u8 fan[5];
 	u8 fan_min[5];
 	u8 fan_div[5];
@@ -196,6 +222,7 @@
 	s16 temp[2];
 	s16 temp_max[2];
 	s16 temp_max_hyst[2];
+	u32 alarms;
 };
 
 static inline int is_word_sized(u16 reg)
@@ -349,6 +376,16 @@
 			data->fan_div[3] |= (i >> 5) & 0x04;
 		}
 
+		/* Measured voltages and limits */
+		for (i = 0; i < 10; i++) {
+			data->in[i] = w83627ehf_read_value(client,
+				      W83627EHF_REG_IN(i));
+			data->in_min[i] = w83627ehf_read_value(client,
+					  W83627EHF_REG_IN_MIN(i));
+			data->in_max[i] = w83627ehf_read_value(client,
+					  W83627EHF_REG_IN_MAX(i));
+		}
+
 		/* Measured fan speeds and limits */
 		for (i = 0; i < 5; i++) {
 			if (!(data->has_fan & (1 << i)))
@@ -395,6 +432,13 @@
 						 W83627EHF_REG_TEMP_HYST[i]);
 		}
 
+		data->alarms = w83627ehf_read_value(client,
+					W83627EHF_REG_ALARM1) |
+			       (w83627ehf_read_value(client,
+					W83627EHF_REG_ALARM2) << 8) |
+			       (w83627ehf_read_value(client,
+					W83627EHF_REG_ALARM3) << 16);
+
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -406,6 +450,109 @@
 /*
  * Sysfs callback functions
  */
+#define show_in_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, struct device_attribute *attr, \
+	   char *buf) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
+}
+show_in_reg(in)
+show_in_reg(in_min)
+show_in_reg(in_max)
+
+#define store_in_reg(REG, reg) \
+static ssize_t \
+store_in_##reg (struct device *dev, struct device_attribute *attr, \
+			const char *buf, size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	int nr = sensor_attr->index; \
+	u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+	mutex_lock(&data->update_lock); \
+	data->in_##reg[nr] = in_to_reg(val, nr); \
+	w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \
+			      data->in_##reg[nr]); \
+	mutex_unlock(&data->update_lock); \
+	return count; \
+}
+
+store_in_reg(MIN, min)
+store_in_reg(MAX, max)
+
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01);
+}
+
+static struct sensor_device_attribute sda_in_input[] = {
+	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
+	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
+	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
+	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
+	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
+	SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
+	SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
+};
+
+static struct sensor_device_attribute sda_in_alarm[] = {
+	SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0),
+	SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1),
+	SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2),
+	SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3),
+	SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8),
+	SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21),
+	SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20),
+	SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16),
+	SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17),
+	SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19),
+};
+
+static struct sensor_device_attribute sda_in_min[] = {
+       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
+       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
+       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
+       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
+       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
+       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
+       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
+       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
+       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
+       SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
+};
+
+static struct sensor_device_attribute sda_in_max[] = {
+       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
+       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
+       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
+       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
+       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
+       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
+       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
+       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
+       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
+       SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
+};
+
+static void device_create_file_in(struct device *dev, int i)
+{
+	device_create_file(dev, &sda_in_input[i].dev_attr);
+	device_create_file(dev, &sda_in_alarm[i].dev_attr);
+	device_create_file(dev, &sda_in_min[i].dev_attr);
+	device_create_file(dev, &sda_in_max[i].dev_attr);
+}
 
 #define show_fan_reg(reg) \
 static ssize_t \
@@ -505,6 +652,14 @@
 	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
 };
 
+static struct sensor_device_attribute sda_fan_alarm[] = {
+	SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6),
+	SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7),
+	SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11),
+	SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10),
+	SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23),
+};
+
 static struct sensor_device_attribute sda_fan_min[] = {
 	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
 		    store_fan_min, 0),
@@ -529,6 +684,7 @@
 static void device_create_file_fan(struct device *dev, int i)
 {
 	device_create_file(dev, &sda_fan_input[i].dev_attr);
+	device_create_file(dev, &sda_fan_alarm[i].dev_attr);
 	device_create_file(dev, &sda_fan_div[i].dev_attr);
 	device_create_file(dev, &sda_fan_min[i].dev_attr);
 }
@@ -616,6 +772,9 @@
 		    store_temp_max_hyst, 0),
 	SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
 		    store_temp_max_hyst, 1),
+	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
+	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
+	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
 };
 
 /*
@@ -705,6 +864,9 @@
 		goto exit_detach;
 	}
 
+	for (i = 0; i < 10; i++)
+		device_create_file_in(dev, i);
+
 	for (i = 0; i < 5; i++) {
 		if (data->has_fan & (1 << i))
 			device_create_file_fan(dev, i);
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 71fb7f1..79368d5 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -781,7 +781,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t
 store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index e4c7003..7be469e 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -630,7 +630,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t
 store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c
new file mode 100644
index 0000000..eec43ab
--- /dev/null
+++ b/drivers/hwmon/w83791d.c
@@ -0,0 +1,1255 @@
+/*
+    w83791d.c - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+
+    Copyright (C) 2006 Charles Spirakis <bezaur@gmail.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+    Supports following chips:
+
+    Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
+    w83791d	10	5	3	3	0x71	0x5ca3	yes	no
+
+    The w83791d chip appears to be part way between the 83781d and the
+    83792d. Thus, this file is derived from both the w83792d.c and
+    w83781d.c files, but its output is more along the lines of the
+    83781d (which means there are no changes to the user-mode sensors
+    program which treats the 83791d as an 83781d).
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+#define NUMBER_OF_VIN		10
+#define NUMBER_OF_FANIN		5
+#define NUMBER_OF_TEMPIN	3
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83791d);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+			"{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int reset;
+module_param(reset, bool, 0);
+MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset");
+
+static int init;
+module_param(init, bool, 0);
+MODULE_PARM_DESC(init, "Set to one to force extra software initialization");
+
+/* The W83791D registers */
+static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = {
+	0x20,			/* VCOREA in DataSheet */
+	0x21,			/* VINR0 in DataSheet */
+	0x22,			/* +3.3VIN in DataSheet */
+	0x23,			/* VDD5V in DataSheet */
+	0x24,			/* +12VIN in DataSheet */
+	0x25,			/* -12VIN in DataSheet */
+	0x26,			/* -5VIN in DataSheet */
+	0xB0,			/* 5VSB in DataSheet */
+	0xB1,			/* VBAT in DataSheet */
+	0xB2			/* VINR1 in DataSheet */
+};
+
+static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = {
+	0x2B,			/* VCOREA High Limit in DataSheet */
+	0x2D,			/* VINR0 High Limit in DataSheet */
+	0x2F,			/* +3.3VIN High Limit in DataSheet */
+	0x31,			/* VDD5V High Limit in DataSheet */
+	0x33,			/* +12VIN High Limit in DataSheet */
+	0x35,			/* -12VIN High Limit in DataSheet */
+	0x37,			/* -5VIN High Limit in DataSheet */
+	0xB4,			/* 5VSB High Limit in DataSheet */
+	0xB6,			/* VBAT High Limit in DataSheet */
+	0xB8			/* VINR1 High Limit in DataSheet */
+};
+static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = {
+	0x2C,			/* VCOREA Low Limit in DataSheet */
+	0x2E,			/* VINR0 Low Limit in DataSheet */
+	0x30,			/* +3.3VIN Low Limit in DataSheet */
+	0x32,			/* VDD5V Low Limit in DataSheet */
+	0x34,			/* +12VIN Low Limit in DataSheet */
+	0x36,			/* -12VIN Low Limit in DataSheet */
+	0x38,			/* -5VIN Low Limit in DataSheet */
+	0xB5,			/* 5VSB Low Limit in DataSheet */
+	0xB7,			/* VBAT Low Limit in DataSheet */
+	0xB9			/* VINR1 Low Limit in DataSheet */
+};
+static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = {
+	0x28,			/* FAN 1 Count in DataSheet */
+	0x29,			/* FAN 2 Count in DataSheet */
+	0x2A,			/* FAN 3 Count in DataSheet */
+	0xBA,			/* FAN 4 Count in DataSheet */
+	0xBB,			/* FAN 5 Count in DataSheet */
+};
+static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = {
+	0x3B,			/* FAN 1 Count Low Limit in DataSheet */
+	0x3C,			/* FAN 2 Count Low Limit in DataSheet */
+	0x3D,			/* FAN 3 Count Low Limit in DataSheet */
+	0xBC,			/* FAN 4 Count Low Limit in DataSheet */
+	0xBD,			/* FAN 5 Count Low Limit in DataSheet */
+};
+
+static const u8 W83791D_REG_FAN_CFG[2] = {
+	0x84,			/* FAN 1/2 configuration */
+	0x95,			/* FAN 3 configuration */
+};
+
+static const u8 W83791D_REG_FAN_DIV[3] = {
+	0x47,			/* contains FAN1 and FAN2 Divisor */
+	0x4b,			/* contains FAN3 Divisor */
+	0x5C,			/* contains FAN4 and FAN5 Divisor */
+};
+
+#define W83791D_REG_BANK		0x4E
+#define W83791D_REG_TEMP2_CONFIG	0xC2
+#define W83791D_REG_TEMP3_CONFIG	0xCA
+
+static const u8 W83791D_REG_TEMP1[3] = {
+	0x27,			/* TEMP 1 in DataSheet */
+	0x39,			/* TEMP 1 Over in DataSheet */
+	0x3A,			/* TEMP 1 Hyst in DataSheet */
+};
+
+static const u8 W83791D_REG_TEMP_ADD[2][6] = {
+	{0xC0,			/* TEMP 2 in DataSheet */
+	 0xC1,			/* TEMP 2(0.5 deg) in DataSheet */
+	 0xC5,			/* TEMP 2 Over High part in DataSheet */
+	 0xC6,			/* TEMP 2 Over Low part in DataSheet */
+	 0xC3,			/* TEMP 2 Thyst High part in DataSheet */
+	 0xC4},			/* TEMP 2 Thyst Low part in DataSheet */
+	{0xC8,			/* TEMP 3 in DataSheet */
+	 0xC9,			/* TEMP 3(0.5 deg) in DataSheet */
+	 0xCD,			/* TEMP 3 Over High part in DataSheet */
+	 0xCE,			/* TEMP 3 Over Low part in DataSheet */
+	 0xCB,			/* TEMP 3 Thyst High part in DataSheet */
+	 0xCC}			/* TEMP 3 Thyst Low part in DataSheet */
+};
+
+#define W83791D_REG_BEEP_CONFIG		0x4D
+
+static const u8 W83791D_REG_BEEP_CTRL[3] = {
+	0x56,			/* BEEP Control Register 1 */
+	0x57,			/* BEEP Control Register 2 */
+	0xA3,			/* BEEP Control Register 3 */
+};
+
+#define W83791D_REG_CONFIG		0x40
+#define W83791D_REG_VID_FANDIV		0x47
+#define W83791D_REG_DID_VID4		0x49
+#define W83791D_REG_WCHIPID		0x58
+#define W83791D_REG_CHIPMAN		0x4F
+#define W83791D_REG_PIN			0x4B
+#define W83791D_REG_I2C_SUBADDR		0x4A
+
+#define W83791D_REG_ALARM1 0xA9	/* realtime status register1 */
+#define W83791D_REG_ALARM2 0xAA	/* realtime status register2 */
+#define W83791D_REG_ALARM3 0xAB	/* realtime status register3 */
+
+#define W83791D_REG_VBAT		0x5D
+#define W83791D_REG_I2C_ADDR		0x48
+
+/* The SMBus locks itself. The Winbond W83791D has a bank select register
+   (index 0x4e), but the driver only accesses registers in bank 0. Since
+   we don't switch banks, we don't need any special code to handle
+   locking access between bank switches */
+static inline int w83791d_read(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* The analog voltage inputs have 16mV LSB. Since the sysfs output is
+   in mV as would be measured on the chip input pin, need to just
+   multiply/divide by 16 to translate from/to register values. */
+#define IN_TO_REG(val)		(SENSORS_LIMIT((((val) + 8) / 16), 0, 255))
+#define IN_FROM_REG(val)	((val) * 16)
+
+static u8 fan_to_reg(long rpm, int div)
+{
+	if (rpm == 0)
+		return 255;
+	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div)	((val) == 0   ? -1 : \
+				((val) == 255 ? 0 : \
+					1350000 / ((val) * (div))))
+
+/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */
+#define TEMP1_FROM_REG(val)	((val) * 1000)
+#define TEMP1_TO_REG(val)	((val) <= -128000 ? -128 : \
+				 (val) >= 127000 ? 127 : \
+				 (val) < 0 ? ((val) - 500) / 1000 : \
+				 ((val) + 500) / 1000)
+
+/* for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius
+   Assumes the top 8 bits are the integral amount and the bottom 8 bits
+   are the fractional amount. Since we only have 0.5 degree resolution,
+   the bottom 7 bits will always be zero */
+#define TEMP23_FROM_REG(val)	((val) / 128 * 500)
+#define TEMP23_TO_REG(val)	((val) <= -128000 ? 0x8000 : \
+				 (val) >= 127500 ? 0x7F80 : \
+				 (val) < 0 ? ((val) - 250) / 500 * 128 : \
+				 ((val) + 250) / 500 * 128)
+
+
+#define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
+#define BEEP_MASK_FROM_REG(val)		((val) & 0xffffff)
+
+#define DIV_FROM_REG(val)		(1 << (val))
+
+static u8 div_to_reg(int nr, long val)
+{
+	int i;
+	int max;
+
+	/* first three fan's divisor max out at 8, rest max out at 128 */
+	max = (nr < 3) ? 8 : 128;
+	val = SENSORS_LIMIT(val, 1, max) >> 1;
+	for (i = 0; i < 7; i++) {
+		if (val == 0)
+			break;
+		val >>= 1;
+	}
+	return (u8) i;
+}
+
+struct w83791d_data {
+	struct i2c_client client;
+	struct class_device *class_dev;
+	struct mutex update_lock;
+
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* array of 2 pointers to subclients */
+	struct i2c_client *lm75[2];
+
+	/* volts */
+	u8 in[NUMBER_OF_VIN];		/* Register value */
+	u8 in_max[NUMBER_OF_VIN];	/* Register value */
+	u8 in_min[NUMBER_OF_VIN];	/* Register value */
+
+	/* fans */
+	u8 fan[NUMBER_OF_FANIN];	/* Register value */
+	u8 fan_min[NUMBER_OF_FANIN];	/* Register value */
+	u8 fan_div[NUMBER_OF_FANIN];	/* Register encoding, shifted right */
+
+	/* Temperature sensors */
+
+	s8 temp1[3];		/* current, over, thyst */
+	s16 temp_add[2][3];	/* fixed point value. Top 8 bits are the
+				   integral part, bottom 8 bits are the
+				   fractional part. We only use the top
+				   9 bits as the resolution is only
+				   to the 0.5 degree C...
+				   two sensors with three values
+				   (cur, over, hyst)  */
+
+	/* Misc */
+	u32 alarms;		/* realtime status register encoding,combined */
+	u8 beep_enable;		/* Global beep enable */
+	u32 beep_mask;		/* Mask off specific beeps */
+	u8 vid;			/* Register encoding, combined */
+	u8 vrm;			/* hwmon-vid */
+};
+
+static int w83791d_attach_adapter(struct i2c_adapter *adapter);
+static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83791d_detach_client(struct i2c_client *client);
+
+static int w83791d_read(struct i2c_client *client, u8 register);
+static int w83791d_write(struct i2c_client *client, u8 register, u8 value);
+static struct w83791d_data *w83791d_update_device(struct device *dev);
+
+#ifdef DEBUG
+static void w83791d_print_debug(struct w83791d_data *data, struct device *dev);
+#endif
+
+static void w83791d_init_client(struct i2c_client *client);
+
+static struct i2c_driver w83791d_driver = {
+	.driver = {
+		.name = "w83791d",
+	},
+	.attach_adapter = w83791d_attach_adapter,
+	.detach_client = w83791d_detach_client,
+};
+
+/* following are the sysfs callback functions */
+#define show_in_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+			char *buf) \
+{ \
+	struct sensor_device_attribute *sensor_attr = \
+						to_sensor_dev_attr(attr); \
+	struct w83791d_data *data = w83791d_update_device(dev); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \
+}
+
+show_in_reg(in);
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg(struct device *dev, \
+				struct device_attribute *attr, \
+				const char *buf, size_t count) \
+{ \
+	struct sensor_device_attribute *sensor_attr = \
+						to_sensor_dev_attr(attr); \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83791d_data *data = i2c_get_clientdata(client); \
+	unsigned long val = simple_strtoul(buf, NULL, 10); \
+	int nr = sensor_attr->index; \
+	 \
+	mutex_lock(&data->update_lock); \
+	data->in_##reg[nr] = IN_TO_REG(val); \
+	w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+	mutex_unlock(&data->update_lock); \
+	 \
+	return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+static struct sensor_device_attribute sda_in_input[] = {
+	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
+	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
+	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
+	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
+	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
+	SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
+	SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9),
+};
+
+static struct sensor_device_attribute sda_in_min[] = {
+	SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
+	SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
+	SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
+	SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
+	SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
+	SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
+	SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
+	SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
+	SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
+	SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
+};
+
+static struct sensor_device_attribute sda_in_max[] = {
+	SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
+	SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
+	SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
+	SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
+	SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
+	SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
+	SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
+	SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
+	SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
+	SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
+};
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+				char *buf) \
+{ \
+	struct sensor_device_attribute *sensor_attr = \
+						to_sensor_dev_attr(attr); \
+	struct w83791d_data *data = w83791d_update_device(dev); \
+	int nr = sensor_attr->index; \
+	return sprintf(buf,"%d\n", \
+		FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+}
+
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int nr = sensor_attr->index;
+
+	mutex_lock(&data->update_lock);
+	data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr]));
+	w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	struct w83791d_data *data = w83791d_update_device(dev);
+	return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr]));
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least suprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
+static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	int nr = sensor_attr->index;
+	unsigned long min;
+	u8 tmp_fan_div;
+	u8 fan_div_reg;
+	int indx = 0;
+	u8 keep_mask = 0;
+	u8 new_shift = 0;
+
+	/* Save fan_min */
+	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
+
+	mutex_lock(&data->update_lock);
+	data->fan_div[nr] = div_to_reg(nr, simple_strtoul(buf, NULL, 10));
+
+	switch (nr) {
+	case 0:
+		indx = 0;
+		keep_mask = 0xcf;
+		new_shift = 4;
+		break;
+	case 1:
+		indx = 0;
+		keep_mask = 0x3f;
+		new_shift = 6;
+		break;
+	case 2:
+		indx = 1;
+		keep_mask = 0x3f;
+		new_shift = 6;
+		break;
+	case 3:
+		indx = 2;
+		keep_mask = 0xf8;
+		new_shift = 0;
+		break;
+	case 4:
+		indx = 2;
+		keep_mask = 0x8f;
+		new_shift = 4;
+		break;
+#ifdef DEBUG
+	default:
+		dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr);
+		count = -EINVAL;
+		goto err_exit;
+#endif
+	}
+
+	fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx])
+			& keep_mask;
+	tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask;
+
+	w83791d_write(client, W83791D_REG_FAN_DIV[indx],
+				fan_div_reg | tmp_fan_div);
+
+	/* Restore fan_min */
+	data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr]));
+	w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]);
+
+#ifdef DEBUG
+err_exit:
+#endif
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute sda_fan_input[] = {
+	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
+	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
+	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
+	SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
+	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
+};
+
+static struct sensor_device_attribute sda_fan_min[] = {
+	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 0),
+	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 1),
+	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 2),
+	SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 3),
+	SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO,
+			show_fan_min, store_fan_min, 4),
+};
+
+static struct sensor_device_attribute sda_fan_div[] = {
+	SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 0),
+	SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 1),
+	SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 2),
+	SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 3),
+	SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO,
+			show_fan_div, store_fan_div, 4),
+};
+
+/* read/write the temperature1, includes measured value and limits */
+static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr,
+				char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct w83791d_data *data = w83791d_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index]));
+}
+
+static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	int nr = attr->index;
+
+	mutex_lock(&data->update_lock);
+	data->temp1[nr] = TEMP1_TO_REG(val);
+	w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* read/write temperature2-3, includes measured value and limits */
+static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr,
+				char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct w83791d_data *data = w83791d_update_device(dev);
+	int nr = attr->nr;
+	int index = attr->index;
+	return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index]));
+}
+
+static ssize_t store_temp23(struct device *dev,
+				struct device_attribute *devattr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	int nr = attr->nr;
+	int index = attr->index;
+
+	mutex_lock(&data->update_lock);
+	data->temp_add[nr][index] = TEMP23_TO_REG(val);
+	w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2],
+				data->temp_add[nr][index] >> 8);
+	w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1],
+				data->temp_add[nr][index] & 0x80);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute_2 sda_temp_input[] = {
+	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0),
+	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0),
+	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max[] = {
+	SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR,
+			show_temp1, store_temp1, 0, 1),
+	SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR,
+			show_temp23, store_temp23, 0, 1),
+	SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR,
+			show_temp23, store_temp23, 1, 1),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
+	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR,
+			show_temp1, store_temp1, 0, 2),
+	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR,
+			show_temp23, store_temp23, 0, 2),
+	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR,
+			show_temp23, store_temp23, 1, 2),
+};
+
+
+/* get reatime status of all sensors items: voltage, temp, fan */
+static ssize_t show_alarms_reg(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct w83791d_data *data = w83791d_update_device(dev);
+	return sprintf(buf, "%u\n", data->alarms);
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+
+/* Beep control */
+
+#define GLOBAL_BEEP_ENABLE_SHIFT	15
+#define GLOBAL_BEEP_ENABLE_MASK		(1 << GLOBAL_BEEP_ENABLE_SHIFT)
+
+static ssize_t show_beep_enable(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct w83791d_data *data = w83791d_update_device(dev);
+	return sprintf(buf, "%d\n", data->beep_enable);
+}
+
+static ssize_t show_beep_mask(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct w83791d_data *data = w83791d_update_device(dev);
+	return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask));
+}
+
+
+static ssize_t store_beep_mask(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	/* The beep_enable state overrides any enabling request from
+	   the masks */
+	data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK;
+	data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
+
+	val = data->beep_mask;
+
+	for (i = 0; i < 3; i++) {
+		w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff));
+		val >>= 8;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t store_beep_enable(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+
+	data->beep_enable = val ? 1 : 0;
+
+	/* Keep the full mask value in sync with the current enable */
+	data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK;
+	data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT);
+
+	/* The global control is in the second beep control register
+	   so only need to update that register */
+	val = (data->beep_mask >> 8) & 0xff;
+
+	w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val);
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute sda_beep_ctrl[] = {
+	SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+			show_beep_enable, store_beep_enable, 0),
+	SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR,
+			show_beep_mask, store_beep_mask, 1)
+};
+
+/* cpu voltage regulation information */
+static ssize_t show_vid_reg(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct w83791d_data *data = w83791d_update_device(dev);
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
+
+static ssize_t show_vrm_reg(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct w83791d_data *data = w83791d_update_device(dev);
+	return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t store_vrm_reg(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	/* No lock needed as vrm is internal to the driver
+	   (not read from a chip register) and so is not
+	   updated in w83791d_update_device() */
+	data->vrm = val;
+
+	return count;
+}
+
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
+
+/* This function is called when:
+     * w83791d_driver is inserted (when this module is loaded), for each
+       available adapter
+     * when a new adapter is inserted (and w83791d_driver is still present) */
+static int w83791d_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, w83791d_detect);
+}
+
+
+static int w83791d_create_subclient(struct i2c_adapter *adapter,
+				struct i2c_client *client, int addr,
+				struct i2c_client **sub_cli)
+{
+	int err;
+	struct i2c_client *sub_client;
+
+	(*sub_cli) = sub_client =
+			kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (!(sub_client)) {
+		return -ENOMEM;
+	}
+	sub_client->addr = 0x48 + addr;
+	i2c_set_clientdata(sub_client, NULL);
+	sub_client->adapter = adapter;
+	sub_client->driver = &w83791d_driver;
+	strlcpy(sub_client->name, "w83791d subclient", I2C_NAME_SIZE);
+	if ((err = i2c_attach_client(sub_client))) {
+		dev_err(&client->dev, "subclient registration "
+			"at address 0x%x failed\n", sub_client->addr);
+		kfree(sub_client);
+		return err;
+	}
+	return 0;
+}
+
+
+static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address,
+				int kind, struct i2c_client *client)
+{
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	int i, id, err;
+	u8 val;
+
+	id = i2c_adapter_id(adapter);
+	if (force_subclients[0] == id && force_subclients[1] == address) {
+		for (i = 2; i <= 3; i++) {
+			if (force_subclients[i] < 0x48 ||
+			    force_subclients[i] > 0x4f) {
+				dev_err(&client->dev,
+					"invalid subclient "
+					"address %d; must be 0x48-0x4f\n",
+					force_subclients[i]);
+				err = -ENODEV;
+				goto error_sc_0;
+			}
+		}
+		w83791d_write(client, W83791D_REG_I2C_SUBADDR,
+					(force_subclients[2] & 0x07) |
+					((force_subclients[3] & 0x07) << 4));
+	}
+
+	val = w83791d_read(client, W83791D_REG_I2C_SUBADDR);
+	if (!(val & 0x08)) {
+		err = w83791d_create_subclient(adapter, client,
+						val & 0x7, &data->lm75[0]);
+		if (err < 0)
+			goto error_sc_0;
+	}
+	if (!(val & 0x80)) {
+		if ((data->lm75[0] != NULL) &&
+				((val & 0x7) == ((val >> 4) & 0x7))) {
+			dev_err(&client->dev,
+				"duplicate addresses 0x%x, "
+				"use force_subclient\n",
+				data->lm75[0]->addr);
+			err = -ENODEV;
+			goto error_sc_1;
+		}
+		err = w83791d_create_subclient(adapter, client,
+					(val >> 4) & 0x7, &data->lm75[1]);
+		if (err < 0)
+			goto error_sc_1;
+	}
+
+	return 0;
+
+/* Undo inits in case of errors */
+
+error_sc_1:
+	if (data->lm75[0] != NULL) {
+		i2c_detach_client(data->lm75[0]);
+		kfree(data->lm75[0]);
+	}
+error_sc_0:
+	return err;
+}
+
+
+static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct device *dev;
+	struct w83791d_data *data;
+	int i, val1, val2;
+	int err = 0;
+	const char *client_name = "";
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		goto error0;
+	}
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access w83791d_{read,write}_value. */
+	if (!(data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto error0;
+	}
+
+	client = &data->client;
+	dev = &client->dev;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &w83791d_driver;
+	mutex_init(&data->update_lock);
+
+	/* Now, we do the remaining detection. */
+
+	/* The w83791d may be stuck in some other bank than bank 0. This may
+	   make reading other information impossible. Specify a force=...
+	   parameter, and the Winbond will be reset to the right bank. */
+	if (kind < 0) {
+		if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) {
+			dev_dbg(dev, "Detection failed at step 1\n");
+			goto error1;
+		}
+		val1 = w83791d_read(client, W83791D_REG_BANK);
+		val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
+		/* Check for Winbond ID if in bank 0 */
+		if (!(val1 & 0x07)) {
+			/* yes it is Bank0 */
+			if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
+			    ((val1 & 0x80) && (val2 != 0x5c))) {
+				dev_dbg(dev, "Detection failed at step 2\n");
+				goto error1;
+			}
+		}
+		/* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
+		   should match */
+		if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) {
+			dev_dbg(dev, "Detection failed at step 3\n");
+			goto error1;
+		}
+	}
+
+	/* We either have a force parameter or we have reason to
+	   believe it is a Winbond chip. Either way, we want bank 0 and
+	   Vendor ID high byte */
+	val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78;
+	w83791d_write(client, W83791D_REG_BANK, val1 | 0x80);
+
+	/* Verify it is a Winbond w83791d */
+	if (kind <= 0) {
+		/* get vendor ID */
+		val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
+		if (val2 != 0x5c) {	/* the vendor is NOT Winbond */
+			dev_dbg(dev, "Detection failed at step 4\n");
+			goto error1;
+		}
+		val1 = w83791d_read(client, W83791D_REG_WCHIPID);
+		if (val1 == 0x71) {
+			kind = w83791d;
+		} else {
+			if (kind == 0)
+				dev_warn(dev,
+					"w83791d: Ignoring 'force' parameter "
+					"for unknown chip at adapter %d, "
+					"address 0x%02x\n",
+					i2c_adapter_id(adapter), address);
+			goto error1;
+		}
+	}
+
+	if (kind == w83791d) {
+		client_name = "w83791d";
+	} else {
+		dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?",
+			kind);
+		goto error1;
+	}
+
+#ifdef DEBUG
+	val1 = w83791d_read(client, W83791D_REG_DID_VID4);
+	dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n",
+			(val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1);
+#endif
+
+	/* Fill in the remaining client fields and put into the global list */
+	strlcpy(client->name, client_name, I2C_NAME_SIZE);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto error1;
+
+	if ((err = w83791d_detect_subclients(adapter, address, kind, client)))
+		goto error2;
+
+	/* Initialize the chip */
+	w83791d_init_client(client);
+
+	/* If the fan_div is changed, make sure there is a rational
+	   fan_min in place */
+	for (i = 0; i < NUMBER_OF_FANIN; i++) {
+		data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]);
+	}
+
+	/* Register sysfs hooks */
+	data->class_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto error3;
+	}
+
+	for (i = 0; i < NUMBER_OF_VIN; i++) {
+		device_create_file(dev, &sda_in_input[i].dev_attr);
+		device_create_file(dev, &sda_in_min[i].dev_attr);
+		device_create_file(dev, &sda_in_max[i].dev_attr);
+	}
+
+	for (i = 0; i < NUMBER_OF_FANIN; i++) {
+		device_create_file(dev, &sda_fan_input[i].dev_attr);
+		device_create_file(dev, &sda_fan_div[i].dev_attr);
+		device_create_file(dev, &sda_fan_min[i].dev_attr);
+	}
+
+	for (i = 0; i < NUMBER_OF_TEMPIN; i++) {
+		device_create_file(dev, &sda_temp_input[i].dev_attr);
+		device_create_file(dev, &sda_temp_max[i].dev_attr);
+		device_create_file(dev, &sda_temp_max_hyst[i].dev_attr);
+	}
+
+	device_create_file(dev, &dev_attr_alarms);
+
+	for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) {
+		device_create_file(dev, &sda_beep_ctrl[i].dev_attr);
+	}
+
+	device_create_file(dev, &dev_attr_cpu0_vid);
+	device_create_file(dev, &dev_attr_vrm);
+
+	return 0;
+
+error3:
+	if (data->lm75[0] != NULL) {
+		i2c_detach_client(data->lm75[0]);
+		kfree(data->lm75[0]);
+	}
+	if (data->lm75[1] != NULL) {
+		i2c_detach_client(data->lm75[1]);
+		kfree(data->lm75[1]);
+	}
+error2:
+	i2c_detach_client(client);
+error1:
+	kfree(data);
+error0:
+	return err;
+}
+
+static int w83791d_detach_client(struct i2c_client *client)
+{
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	int err;
+
+	/* main client */
+	if (data)
+		hwmon_device_unregister(data->class_dev);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	/* main client */
+	if (data)
+		kfree(data);
+	/* subclient */
+	else
+		kfree(client);
+
+	return 0;
+}
+
+static void w83791d_init_client(struct i2c_client *client)
+{
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	u8 tmp;
+	u8 old_beep;
+
+	/* The difference between reset and init is that reset
+	   does a hard reset of the chip via index 0x40, bit 7,
+	   but init simply forces certain registers to have "sane"
+	   values. The hope is that the BIOS has done the right
+	   thing (which is why the default is reset=0, init=0),
+	   but if not, reset is the hard hammer and init
+	   is the soft mallet both of which are trying to whack
+	   things into place...
+	   NOTE: The data sheet makes a distinction between
+	   "power on defaults" and "reset by MR". As far as I can tell,
+	   the hard reset puts everything into a power-on state so I'm
+	   not sure what "reset by MR" means or how it can happen.
+	   */
+	if (reset || init) {
+		/* keep some BIOS settings when we... */
+		old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG);
+
+		if (reset) {
+			/* ... reset the chip and ... */
+			w83791d_write(client, W83791D_REG_CONFIG, 0x80);
+		}
+
+		/* ... disable power-on abnormal beep */
+		w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80);
+
+		/* disable the global beep (not done by hard reset) */
+		tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]);
+		w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef);
+
+		if (init) {
+			/* Make sure monitoring is turned on for add-ons */
+			tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG);
+			if (tmp & 1) {
+				w83791d_write(client, W83791D_REG_TEMP2_CONFIG,
+					tmp & 0xfe);
+			}
+
+			tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG);
+			if (tmp & 1) {
+				w83791d_write(client, W83791D_REG_TEMP3_CONFIG,
+					tmp & 0xfe);
+			}
+
+			/* Start monitoring */
+			tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7;
+			w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01);
+		}
+	}
+
+	data->vrm = vid_which_vrm();
+}
+
+static struct w83791d_data *w83791d_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83791d_data *data = i2c_get_clientdata(client);
+	int i, j;
+	u8 reg_array_tmp[3];
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + (HZ * 3))
+			|| !data->valid) {
+		dev_dbg(dev, "Starting w83791d device update\n");
+
+		/* Update the voltages measured value and limits */
+		for (i = 0; i < NUMBER_OF_VIN; i++) {
+			data->in[i] = w83791d_read(client,
+						W83791D_REG_IN[i]);
+			data->in_max[i] = w83791d_read(client,
+						W83791D_REG_IN_MAX[i]);
+			data->in_min[i] = w83791d_read(client,
+						W83791D_REG_IN_MIN[i]);
+		}
+
+		/* Update the fan counts and limits */
+		for (i = 0; i < NUMBER_OF_FANIN; i++) {
+			/* Update the Fan measured value and limits */
+			data->fan[i] = w83791d_read(client,
+						W83791D_REG_FAN[i]);
+			data->fan_min[i] = w83791d_read(client,
+						W83791D_REG_FAN_MIN[i]);
+		}
+
+		/* Update the fan divisor */
+		for (i = 0; i < 3; i++) {
+			reg_array_tmp[i] = w83791d_read(client,
+						W83791D_REG_FAN_DIV[i]);
+		}
+		data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03;
+		data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03;
+		data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03;
+		data->fan_div[3] = reg_array_tmp[2] & 0x07;
+		data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07;
+
+		/* Update the first temperature sensor */
+		for (i = 0; i < 3; i++) {
+			data->temp1[i] = w83791d_read(client,
+						W83791D_REG_TEMP1[i]);
+		}
+
+		/* Update the rest of the temperature sensors */
+		for (i = 0; i < 2; i++) {
+			for (j = 0; j < 3; j++) {
+				data->temp_add[i][j] =
+					(w83791d_read(client,
+					W83791D_REG_TEMP_ADD[i][j * 2]) << 8) |
+					w83791d_read(client,
+					W83791D_REG_TEMP_ADD[i][j * 2 + 1]);
+			}
+		}
+
+		/* Update the realtime status */
+		data->alarms =
+			w83791d_read(client, W83791D_REG_ALARM1) +
+			(w83791d_read(client, W83791D_REG_ALARM2) << 8) +
+			(w83791d_read(client, W83791D_REG_ALARM3) << 16);
+
+		/* Update the beep configuration information */
+		data->beep_mask =
+			w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) +
+			(w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) +
+			(w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16);
+
+		data->beep_enable =
+			(data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01;
+
+		/* Update the cpu voltage information */
+		i = w83791d_read(client, W83791D_REG_VID_FANDIV);
+		data->vid = i & 0x0f;
+		data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01)
+				<< 4;
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+#ifdef DEBUG
+	w83791d_print_debug(data, dev);
+#endif
+
+	return data;
+}
+
+#ifdef DEBUG
+static void w83791d_print_debug(struct w83791d_data *data, struct device *dev)
+{
+	int i = 0, j = 0;
+
+	dev_dbg(dev, "======Start of w83791d debug values======\n");
+	dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN);
+	for (i = 0; i < NUMBER_OF_VIN; i++) {
+		dev_dbg(dev, "vin[%d] is:     0x%02x\n", i, data->in[i]);
+		dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]);
+		dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]);
+	}
+	dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN);
+	for (i = 0; i < NUMBER_OF_FANIN; i++) {
+		dev_dbg(dev, "fan[%d] is:     0x%02x\n", i, data->fan[i]);
+		dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]);
+		dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]);
+	}
+
+	/* temperature math is signed, but only print out the
+	   bits that matter */
+	dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN);
+	for (i = 0; i < 3; i++) {
+		dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]);
+	}
+	for (i = 0; i < 2; i++) {
+		for (j = 0; j < 3; j++) {
+			dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j,
+				(u16) data->temp_add[i][j]);
+		}
+	}
+
+	dev_dbg(dev, "Misc Information: ===>\n");
+	dev_dbg(dev, "alarm is:     0x%08x\n", data->alarms);
+	dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask);
+	dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable);
+	dev_dbg(dev, "vid is: 0x%02x\n", data->vid);
+	dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm);
+	dev_dbg(dev, "=======End of w83791d debug values========\n");
+	dev_dbg(dev, "\n");
+}
+#endif
+
+static int __init sensors_w83791d_init(void)
+{
+	return i2c_add_driver(&w83791d_driver);
+}
+
+static void __exit sensors_w83791d_exit(void)
+{
+	i2c_del_driver(&w83791d_driver);
+}
+
+MODULE_AUTHOR("Charles Spirakis <bezaur@gmail.com>");
+MODULE_DESCRIPTION("W83791D driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83791d_init);
+module_exit(sensors_w83791d_exit);
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
index 958602e..e407c74 100644
--- a/drivers/hwmon/w83792d.c
+++ b/drivers/hwmon/w83792d.c
@@ -250,8 +250,6 @@
 			: (val)) / 1000, 0, 0xff))
 #define TEMP_ADD_TO_REG_LOW(val)	((val%1000) ? 0x80 : 0x00)
 
-#define PWM_FROM_REG(val)		(val)
-#define PWM_TO_REG(val)			(SENSORS_LIMIT((val),0,255))
 #define DIV_FROM_REG(val)		(1 << (val))
 
 static inline u8
@@ -291,7 +289,6 @@
 	u8 pwm[7];		/* We only consider the first 3 set of pwm,
 				   although 792 chip has 7 set of pwm. */
 	u8 pwmenable[3];
-	u8 pwm_mode[7];		/* indicates PWM or DC mode: 1->PWM; 0->DC */
 	u32 alarms;		/* realtime status register encoding,combined */
 	u8 chassis;		/* Chassis status */
 	u8 chassis_clear;	/* CLR_CHS, clear chassis intrusion detection */
@@ -375,8 +372,10 @@
 	u32 val; \
 	 \
 	val = simple_strtoul(buf, NULL, 10); \
+	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \
 	w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+	mutex_unlock(&data->update_lock); \
 	 \
 	return count; \
 }
@@ -443,9 +442,11 @@
 	u32 val;
 
 	val = simple_strtoul(buf, NULL, 10);
+	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
 	w83792d_write_value(client, W83792D_REG_FAN_MIN[nr],
 				data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -462,7 +463,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t
 store_fan_div(struct device *dev, struct device_attribute *attr,
@@ -478,6 +479,7 @@
 	u8 tmp_fan_div;
 
 	/* Save fan_min */
+	mutex_lock(&data->update_lock);
 	min = FAN_FROM_REG(data->fan_min[nr],
 			   DIV_FROM_REG(data->fan_div[nr]));
 
@@ -493,6 +495,7 @@
 	/* Restore fan_min */
 	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
 	w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -547,10 +550,11 @@
 	s32 val;
 
 	val = simple_strtol(buf, NULL, 10);
-
+	mutex_lock(&data->update_lock);
 	data->temp1[nr] = TEMP1_TO_REG(val);
 	w83792d_write_value(client, W83792D_REG_TEMP1[nr],
 		data->temp1[nr]);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -580,13 +584,14 @@
 	s32 val;
 
 	val = simple_strtol(buf, NULL, 10);
-
+	mutex_lock(&data->update_lock);
 	data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val);
 	data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val);
 	w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index],
 		data->temp_add[nr][index]);
 	w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1],
 		data->temp_add[nr][index+1]);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -627,7 +632,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct w83792d_data *data = w83792d_update_device(dev);
-	return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1]));
+	return sprintf(buf, "%d\n", (data->pwm[nr] & 0x0f) << 4);
 }
 
 static ssize_t
@@ -659,14 +664,16 @@
 		const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index - 1;
+	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
-	u32 val;
+	u8 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255) >> 4;
 
-	val = simple_strtoul(buf, NULL, 10);
-	data->pwm[nr] = PWM_TO_REG(val);
+	mutex_lock(&data->update_lock);
+	val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0;
+	data->pwm[nr] = val;
 	w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -683,6 +690,10 @@
 	u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp;
 
 	val = simple_strtoul(buf, NULL, 10);
+	if (val < 1 || val > 3)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
 	switch (val) {
 	case 1:
 		data->pwmenable[nr] = 0; /* manual mode */
@@ -693,8 +704,6 @@
 	case 3:
 		data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */
 		break;
-	default:
-		return -EINVAL;
 	}
 	cfg1_tmp = data->pwmenable[0];
 	cfg2_tmp = (data->pwmenable[1]) << 2;
@@ -702,14 +711,15 @@
 	cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
 	fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp;
 	w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
 
 static struct sensor_device_attribute sda_pwm[] = {
-	SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
-	SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
-	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3),
+	SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0),
+	SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1),
+	SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2),
 };
 static struct sensor_device_attribute sda_pwm_enable[] = {
 	SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
@@ -728,7 +738,7 @@
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	struct w83792d_data *data = w83792d_update_device(dev);
-	return sprintf(buf, "%d\n", data->pwm_mode[nr-1]);
+	return sprintf(buf, "%d\n", data->pwm[nr] >> 7);
 }
 
 static ssize_t
@@ -736,29 +746,35 @@
 			const char *buf, size_t count)
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
-	int nr = sensor_attr->index - 1;
+	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
 	u32 val;
-	u8 pwm_mode_mask = 0;
 
 	val = simple_strtoul(buf, NULL, 10);
-	data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1);
-	pwm_mode_mask = w83792d_read_value(client,
-		W83792D_REG_PWM[nr]) & 0x7f;
-	w83792d_write_value(client, W83792D_REG_PWM[nr],
-		((data->pwm_mode[nr]) << 7) | pwm_mode_mask);
+	if (val != 0 && val != 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->pwm[nr] = w83792d_read_value(client, W83792D_REG_PWM[nr]);
+	if (val) {			/* PWM mode */
+		data->pwm[nr] |= 0x80;
+	} else {			/* DC mode */
+		data->pwm[nr] &= 0x7f;
+	}
+	w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
 
 static struct sensor_device_attribute sda_pwm_mode[] = {
 	SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO,
-		    show_pwm_mode, store_pwm_mode, 1),
+		    show_pwm_mode, store_pwm_mode, 0),
 	SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO,
-		    show_pwm_mode, store_pwm_mode, 2),
+		    show_pwm_mode, store_pwm_mode, 1),
 	SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO,
-		    show_pwm_mode, store_pwm_mode, 3),
+		    show_pwm_mode, store_pwm_mode, 2),
 };
 
 
@@ -789,12 +805,13 @@
 	u8 temp1 = 0, temp2 = 0;
 
 	val = simple_strtoul(buf, NULL, 10);
-
+	mutex_lock(&data->update_lock);
 	data->chassis_clear = SENSORS_LIMIT(val, 0 ,1);
 	temp1 = ((data->chassis_clear) << 7) & 0x80;
 	temp2 = w83792d_read_value(client,
 		W83792D_REG_CHASSIS_CLR) & 0x7f;
 	w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -827,10 +844,12 @@
 	val = simple_strtoul(buf, NULL, 10);
 	target_tmp = val;
 	target_tmp = target_tmp & 0x7f;
+	mutex_lock(&data->update_lock);
 	target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80;
 	data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255);
 	w83792d_write_value(client, W83792D_REG_THERMAL[nr],
 		(data->thermal_cruise[nr]) | target_mask);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -867,6 +886,7 @@
 	u8 tol_tmp, tol_mask;
 
 	val = simple_strtoul(buf, NULL, 10);
+	mutex_lock(&data->update_lock);
 	tol_mask = w83792d_read_value(client,
 		W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0);
 	tol_tmp = SENSORS_LIMIT(val, 0, 15);
@@ -877,6 +897,7 @@
 	}
 	w83792d_write_value(client, W83792D_REG_TOLERANCE[nr],
 		tol_mask | tol_tmp);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -915,11 +936,13 @@
 	u8 mask_tmp = 0;
 
 	val = simple_strtoul(buf, NULL, 10);
+	mutex_lock(&data->update_lock);
 	data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127);
 	mask_tmp = w83792d_read_value(client,
 					W83792D_REG_POINTS[index][nr]) & 0x80;
 	w83792d_write_value(client, W83792D_REG_POINTS[index][nr],
 		mask_tmp|data->sf2_points[index][nr]);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -979,6 +1002,7 @@
 	u8 mask_tmp=0, level_tmp=0;
 
 	val = simple_strtoul(buf, NULL, 10);
+	mutex_lock(&data->update_lock);
 	data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15);
 	mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr])
 		& ((nr==3) ? 0xf0 : 0x0f);
@@ -988,6 +1012,7 @@
 		level_tmp = data->sf2_levels[index][nr] << 4;
 	}
 	w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp);
+	mutex_unlock(&data->update_lock);
 
 	return count;
 }
@@ -1373,7 +1398,7 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83792d_data *data = i2c_get_clientdata(client);
 	int i, j;
-	u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
+	u8 reg_array_tmp[4], reg_tmp;
 
 	mutex_lock(&data->update_lock);
 
@@ -1402,10 +1427,8 @@
 			data->fan_min[i] = w83792d_read_value(client,
 						W83792D_REG_FAN_MIN[i]);
 			/* Update the PWM/DC Value and PWM/DC flag */
-			pwm_array_tmp[i] = w83792d_read_value(client,
+			data->pwm[i] = w83792d_read_value(client,
 						W83792D_REG_PWM[i]);
-			data->pwm[i] = pwm_array_tmp[i] & 0x0f;
-			data->pwm_mode[i] = pwm_array_tmp[i] >> 7;
 		}
 
 		reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
@@ -1513,7 +1536,6 @@
 		dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
 		dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
 		dev_dbg(dev, "pwm[%d]     is: 0x%x\n", i, data->pwm[i]);
-		dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]);
 	}
 	dev_dbg(dev, "3 set of Temperatures: =====>\n");
 	for (i=0; i<3; i++) {
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d6d4494..884320e 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -163,7 +163,7 @@
 	  I2C bus.
 
 config I2C_PIIX4
-	tristate "Intel PIIX4"
+	tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
 	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the Intel
@@ -172,6 +172,9 @@
 	  of Broadcom):
 	    Intel PIIX4
 	    Intel 440MX
+	    ATI IXP200
+	    ATI IXP300
+	    ATI IXP400
 	    Serverworks OSB4
 	    Serverworks CSB5
 	    Serverworks CSB6
@@ -252,12 +255,12 @@
 	  will be called i2c-powermac.
 
 config I2C_MPC
-	tristate "MPC107/824x/85xx/52xx"
+	tristate "MPC107/824x/85xx/52xx/86xx"
 	depends on I2C && PPC32
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
-	  MPC85xx family processors. The driver may also work on 52xx
+	  MPC85xx/MPC8641 family processors. The driver may also work on 52xx
 	  family processors, though interrupts are known not to work.
 
 	  This driver can also be built as a module.  If so, the module
@@ -273,6 +276,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-nforce2.
 
+config I2C_OCORES
+	tristate "OpenCores I2C Controller"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the
+	  OpenCores I2C controller. For details see
+	  http://www.opencores.org/projects.cgi/web/i2c/overview
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-ocores.
+
 config I2C_PARPORT
 	tristate "Parallel port adapter"
 	depends on I2C && PARPORT
@@ -500,6 +514,7 @@
 	tristate "PCA9564 on an ISA bus"
 	depends on I2C
 	select I2C_ALGOPCA
+	default n
 	help
 	  This driver supports ISA boards using the Philips PCA 9564
 	  Parallel bus to I2C bus controller
@@ -507,6 +522,11 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-pca-isa.
 
+	  This device is almost undetectable and using this driver on a
+	  system which doesn't have this device will result in long
+	  delays when I2C/SMBus chip drivers are loaded (e.g. at boot
+	  time).  If unsure, say N.
+
 config I2C_MV64XXX
 	tristate "Marvell mv64xxx I2C Controller"
 	depends on I2C && MV64X60 && EXPERIMENTAL
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index b44831d..ac56df5 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
+obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index dfca749..8b46ef7 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -1,5 +1,5 @@
 /*
-    i801.c - Part of lm_sensors, Linux kernel modules for hardware
+    i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware
               monitoring
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
@@ -36,7 +36,7 @@
     This driver supports several versions of Intel's I/O Controller Hubs (ICH).
     For SMBus support, they are similar to the PIIX4 and are part
     of Intel's '810' and other chipsets.
-    See the doc/busses/i2c-i801 file for details.
+    See the file Documentation/i2c/busses/i2c-i801 for details.
     I2C Block Read and Process Call are not supported.
 */
 
@@ -66,9 +66,8 @@
 #define SMBAUXCTL	(13 + i801_smba)	/* ICH4 only */
 
 /* PCI Address Constants */
-#define SMBBA		0x020
+#define SMBBAR		4
 #define SMBHSTCFG	0x040
-#define SMBREV		0x008
 
 /* Host configuration bits for SMBHSTCFG */
 #define SMBHSTCFG_HST_EN	1
@@ -92,92 +91,16 @@
 #define I801_START		0x40
 #define I801_PEC_EN		0x80	/* ICH4 only */
 
-/* insmod parameters */
-
-/* If force_addr is set to anything different from 0, we forcibly enable
-   the I801 at the given address. VERY DANGEROUS! */
-static u16 force_addr;
-module_param(force_addr, ushort, 0);
-MODULE_PARM_DESC(force_addr,
-		 "Forcibly enable the I801 at the given address. "
-		 "EXTREMELY DANGEROUS!");
 
 static int i801_transaction(void);
 static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
 				  int command, int hwpec);
 
-static unsigned short i801_smba;
+static unsigned long i801_smba;
 static struct pci_driver i801_driver;
 static struct pci_dev *I801_dev;
 static int isich4;
 
-static int i801_setup(struct pci_dev *dev)
-{
-	int error_return = 0;
-	unsigned char temp;
-
-	/* Note: we keep on searching until we have found 'function 3' */
-	if(PCI_FUNC(dev->devfn) != 3)
-		return -ENODEV;
-
-	I801_dev = dev;
-	if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
-	    (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
-	    (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
-		isich4 = 1;
-	else
-		isich4 = 0;
-
-	/* Determine the address of the SMBus areas */
-	if (force_addr) {
-		i801_smba = force_addr & 0xfff0;
-	} else {
-		pci_read_config_word(I801_dev, SMBBA, &i801_smba);
-		i801_smba &= 0xfff0;
-		if(i801_smba == 0) {
-			dev_err(&dev->dev, "SMB base address uninitialized "
-				"- upgrade BIOS or use force_addr=0xaddr\n");
-			return -ENODEV;
-		}
-	}
-
-	if (!request_region(i801_smba, (isich4 ? 16 : 8), i801_driver.name)) {
-		dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n",
-			i801_smba);
-		error_return = -EBUSY;
-		goto END;
-	}
-
-	pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
-	temp &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
-	pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
-
-	/* If force_addr is set, we program the new address here. Just to make
-	   sure, we disable the device first. */
-	if (force_addr) {
-		pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
-		pci_write_config_word(I801_dev, SMBBA, i801_smba);
-		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
-		dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to "
-			"new address %04x!\n", i801_smba);
-	} else if ((temp & 1) == 0) {
-		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
-		dev_warn(&dev->dev, "enabling SMBus device\n");
-	}
-
-	if (temp & 0x02)
-		dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n");
-	else
-		dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n");
-
-	pci_read_config_byte(I801_dev, SMBREV, &temp);
-	dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp);
-	dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba);
-
-END:
-	return error_return;
-}
-
 static int i801_transaction(void)
 {
 	int temp;
@@ -334,8 +257,8 @@
 		/* We will always wait for a fraction of a second! */
 		timeout = 0;
 		do {
-			temp = inb_p(SMBHSTSTS);
 			msleep(1);
+			temp = inb_p(SMBHSTSTS);
 		}
 		    while ((!(temp & 0x80))
 			   && (timeout++ < MAX_TIMEOUT));
@@ -393,8 +316,8 @@
 		/* wait for INTR bit as advised by Intel */
 		timeout = 0;
 		do {
-			temp = inb_p(SMBHSTSTS);
 			msleep(1);
+			temp = inb_p(SMBHSTSTS);
 		} while ((!(temp & 0x02))
 			   && (timeout++ < MAX_TIMEOUT));
 
@@ -541,25 +464,80 @@
 
 static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	unsigned char temp;
+	int err;
 
-	if (i801_setup(dev)) {
-		dev_warn(&dev->dev,
-			"I801 not detected, module not inserted.\n");
-		return -ENODEV;
+	I801_dev = dev;
+	if ((dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) ||
+	    (dev->device == PCI_DEVICE_ID_INTEL_82801EB_3) ||
+	    (dev->device == PCI_DEVICE_ID_INTEL_ESB_4))
+		isich4 = 1;
+	else
+		isich4 = 0;
+
+	err = pci_enable_device(dev);
+	if (err) {
+		dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n",
+			err);
+		goto exit;
 	}
 
+	/* Determine the address of the SMBus area */
+	i801_smba = pci_resource_start(dev, SMBBAR);
+	if (!i801_smba) {
+		dev_err(&dev->dev, "SMBus base address uninitialized, "
+			"upgrade BIOS\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	err = pci_request_region(dev, SMBBAR, i801_driver.name);
+	if (err) {
+		dev_err(&dev->dev, "Failed to request SMBus region "
+			"0x%lx-0x%lx\n", i801_smba,
+			pci_resource_end(dev, SMBBAR));
+		goto exit;
+	}
+
+	pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
+	temp &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
+	if (!(temp & SMBHSTCFG_HST_EN)) {
+		dev_info(&dev->dev, "Enabling SMBus device\n");
+		temp |= SMBHSTCFG_HST_EN;
+	}
+	pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
+
+	if (temp & SMBHSTCFG_SMB_SMI_EN)
+		dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n");
+	else
+		dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
+
 	/* set up the driverfs linkage to our parent device */
 	i801_adapter.dev.parent = &dev->dev;
 
 	snprintf(i801_adapter.name, I2C_NAME_SIZE,
-		"SMBus I801 adapter at %04x", i801_smba);
-	return i2c_add_adapter(&i801_adapter);
+		"SMBus I801 adapter at %04lx", i801_smba);
+	err = i2c_add_adapter(&i801_adapter);
+	if (err) {
+		dev_err(&dev->dev, "Failed to add SMBus adapter\n");
+		goto exit_release;
+	}
+	return 0;
+
+exit_release:
+	pci_release_region(dev, SMBBAR);
+exit:
+	return err;
 }
 
 static void __devexit i801_remove(struct pci_dev *dev)
 {
 	i2c_del_adapter(&i801_adapter);
-	release_region(i801_smba, (isich4 ? 16 : 8));
+	pci_release_region(dev, SMBBAR);
+	/*
+	 * do not call pci_disable_device(dev) since it can cause hard hangs on
+	 * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010)
+	 */
 }
 
 static struct pci_driver i801_driver = {
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 2d80eb2..604b49e 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -31,6 +31,8 @@
     nForce3 250Gb MCP		00E4
     nForce4 MCP			0052
     nForce4 MCP-04		0034
+    nForce4 MCP51		0264
+    nForce4 MCP55		0368
 
     This driver supports the 2 SMBuses that are included in the MCP of the
     nForce2/3/4 chipsets.
@@ -64,6 +66,7 @@
 
 /*
  * nVidia nForce2 SMBus control register definitions
+ * (Newer incarnations use standard BARs 4 and 5 instead)
  */
 #define NFORCE_PCI_SMB1	0x50
 #define NFORCE_PCI_SMB2	0x54
@@ -259,6 +262,8 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
 	{ 0 }
 };
 
@@ -266,19 +271,29 @@
 MODULE_DEVICE_TABLE (pci, nforce2_ids);
 
 
-static int __devinit nforce2_probe_smb (struct pci_dev *dev, int reg,
-	struct nforce2_smbus *smbus, char *name)
+static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
+	int alt_reg, struct nforce2_smbus *smbus, const char *name)
 {
-	u16 iobase;
 	int error;
 
-	if (pci_read_config_word(dev, reg, &iobase) != PCIBIOS_SUCCESSFUL) {
-		dev_err(&smbus->adapter.dev, "Error reading PCI config for %s\n", name);
-		return -1;
+	smbus->base = pci_resource_start(dev, bar);
+	if (smbus->base) {
+		smbus->size = pci_resource_len(dev, bar);
+	} else {
+		/* Older incarnations of the device used non-standard BARs */
+		u16 iobase;
+
+		if (pci_read_config_word(dev, alt_reg, &iobase)
+		    != PCIBIOS_SUCCESSFUL) {
+			dev_err(&dev->dev, "Error reading PCI config for %s\n",
+				name);
+			return -1;
+		}
+
+		smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
+		smbus->size = 8;
 	}
-	smbus->dev  = dev;
-	smbus->base = iobase & 0xfffc;
-	smbus->size = 8;
+	smbus->dev = dev;
 
 	if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
 		dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
@@ -313,12 +328,13 @@
 	pci_set_drvdata(dev, smbuses);
 
 	/* SMBus adapter 1 */
-	res1 = nforce2_probe_smb (dev, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
+	res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");
 	if (res1 < 0) {
 		dev_err(&dev->dev, "Error probing SMB1.\n");
 		smbuses[0].base = 0;	/* to have a check value */
 	}
-	res2 = nforce2_probe_smb (dev, NFORCE_PCI_SMB2, &smbuses[1], "SMB2");
+	/* SMBus adapter 2 */
+	res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], "SMB2");
 	if (res2 < 0) {
 		dev_err(&dev->dev, "Error probing SMB2.\n");
 		smbuses[1].base = 0;	/* to have a check value */
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
new file mode 100644
index 0000000..5928240
--- /dev/null
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -0,0 +1,341 @@
+/*
+ * i2c-ocores.c: I2C bus driver for OpenCores I2C controller
+ * (http://www.opencores.org/projects.cgi/web/i2c/overview).
+ *
+ * Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/i2c-ocores.h>
+#include <asm/io.h>
+
+struct ocores_i2c {
+	void __iomem *base;
+	int regstep;
+	wait_queue_head_t wait;
+	struct i2c_adapter adap;
+	struct i2c_msg *msg;
+	int pos;
+	int nmsgs;
+	int state; /* see STATE_ */
+};
+
+/* registers */
+#define OCI2C_PRELOW		0
+#define OCI2C_PREHIGH		1
+#define OCI2C_CONTROL		2
+#define OCI2C_DATA		3
+#define OCI2C_CMD		4 /* write only */
+#define OCI2C_STATUS		4 /* read only, same address as OCI2C_CMD */
+
+#define OCI2C_CTRL_IEN		0x40
+#define OCI2C_CTRL_EN		0x80
+
+#define OCI2C_CMD_START		0x91
+#define OCI2C_CMD_STOP		0x41
+#define OCI2C_CMD_READ		0x21
+#define OCI2C_CMD_WRITE		0x11
+#define OCI2C_CMD_READ_ACK	0x21
+#define OCI2C_CMD_READ_NACK	0x29
+#define OCI2C_CMD_IACK		0x01
+
+#define OCI2C_STAT_IF		0x01
+#define OCI2C_STAT_TIP		0x02
+#define OCI2C_STAT_ARBLOST	0x20
+#define OCI2C_STAT_BUSY		0x40
+#define OCI2C_STAT_NACK		0x80
+
+#define STATE_DONE		0
+#define STATE_START		1
+#define STATE_WRITE		2
+#define STATE_READ		3
+#define STATE_ERROR		4
+
+static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
+{
+	iowrite8(value, i2c->base + reg * i2c->regstep);
+}
+
+static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
+{
+	return ioread8(i2c->base + reg * i2c->regstep);
+}
+
+static void ocores_process(struct ocores_i2c *i2c)
+{
+	struct i2c_msg *msg = i2c->msg;
+	u8 stat = oc_getreg(i2c, OCI2C_STATUS);
+
+	if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
+		/* stop has been sent */
+		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
+		wake_up(&i2c->wait);
+		return;
+	}
+
+	/* error? */
+	if (stat & OCI2C_STAT_ARBLOST) {
+		i2c->state = STATE_ERROR;
+		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+		return;
+	}
+
+	if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) {
+		i2c->state =
+			(msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
+
+		if (stat & OCI2C_STAT_NACK) {
+			i2c->state = STATE_ERROR;
+			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+			return;
+		}
+	} else
+		msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA);
+
+	/* end of msg? */
+	if (i2c->pos == msg->len) {
+		i2c->nmsgs--;
+		i2c->msg++;
+		i2c->pos = 0;
+		msg = i2c->msg;
+
+		if (i2c->nmsgs) {	/* end? */
+			/* send start? */
+			if (!(msg->flags & I2C_M_NOSTART)) {
+				u8 addr = (msg->addr << 1);
+
+				if (msg->flags & I2C_M_RD)
+					addr |= 1;
+
+				i2c->state = STATE_START;
+
+				oc_setreg(i2c, OCI2C_DATA, addr);
+				oc_setreg(i2c, OCI2C_CMD,  OCI2C_CMD_START);
+				return;
+			} else
+				i2c->state = (msg->flags & I2C_M_RD)
+					? STATE_READ : STATE_WRITE;
+		} else {
+			i2c->state = STATE_DONE;
+			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
+			return;
+		}
+	}
+
+	if (i2c->state == STATE_READ) {
+		oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ?
+			  OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK);
+	} else {
+		oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]);
+		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE);
+	}
+}
+
+static irqreturn_t ocores_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct ocores_i2c *i2c = dev_id;
+
+	ocores_process(i2c);
+
+	return IRQ_HANDLED;
+}
+
+static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+	struct ocores_i2c *i2c = i2c_get_adapdata(adap);
+
+	i2c->msg = msgs;
+	i2c->pos = 0;
+	i2c->nmsgs = num;
+	i2c->state = STATE_START;
+
+	oc_setreg(i2c, OCI2C_DATA,
+			(i2c->msg->addr << 1) |
+			((i2c->msg->flags & I2C_M_RD) ? 1:0));
+
+	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
+
+	if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
+			       (i2c->state == STATE_DONE), HZ))
+		return (i2c->state == STATE_DONE) ? num : -EIO;
+	else
+		return -ETIMEDOUT;
+}
+
+static void ocores_init(struct ocores_i2c *i2c,
+			struct ocores_i2c_platform_data *pdata)
+{
+	int prescale;
+	u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
+
+	/* make sure the device is disabled */
+	oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
+
+	prescale = (pdata->clock_khz / (5*100)) - 1;
+	oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
+	oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
+
+	/* Init the device */
+	oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
+	oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN);
+}
+
+
+static u32 ocores_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm ocores_algorithm = {
+	.master_xfer	= ocores_xfer,
+	.functionality	= ocores_func,
+};
+
+static struct i2c_adapter ocores_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "i2c-ocores",
+	.class		= I2C_CLASS_HWMON,
+	.algo		= &ocores_algorithm,
+};
+
+
+static int __devinit ocores_i2c_probe(struct platform_device *pdev)
+{
+	struct ocores_i2c *i2c;
+	struct ocores_i2c_platform_data *pdata;
+	struct resource *res, *res2;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res2)
+		return -ENODEV;
+
+	pdata = (struct ocores_i2c_platform_data*) pdev->dev.platform_data;
+	if (!pdata)
+		return -ENODEV;
+
+	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+	if (!i2c)
+		return -ENOMEM;
+
+	if (!request_mem_region(res->start, res->end - res->start + 1,
+				pdev->name)) {
+		dev_err(&pdev->dev, "Memory region busy\n");
+		ret = -EBUSY;
+		goto request_mem_failed;
+	}
+
+	i2c->base = ioremap(res->start, res->end - res->start + 1);
+	if (!i2c->base) {
+		dev_err(&pdev->dev, "Unable to map registers\n");
+		ret = -EIO;
+		goto map_failed;
+	}
+
+	i2c->regstep = pdata->regstep;
+	ocores_init(i2c, pdata);
+
+	init_waitqueue_head(&i2c->wait);
+	ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c);
+	if (ret) {
+		dev_err(&pdev->dev, "Cannot claim IRQ\n");
+		goto request_irq_failed;
+	}
+
+	/* hook up driver to tree */
+	platform_set_drvdata(pdev, i2c);
+	i2c->adap = ocores_adapter;
+	i2c_set_adapdata(&i2c->adap, i2c);
+	i2c->adap.dev.parent = &pdev->dev;
+
+	/* add i2c adapter to i2c tree */
+	ret = i2c_add_adapter(&i2c->adap);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add adapter\n");
+		goto add_adapter_failed;
+	}
+
+	return 0;
+
+add_adapter_failed:
+	free_irq(res2->start, i2c);
+request_irq_failed:
+	iounmap(i2c->base);
+map_failed:
+	release_mem_region(res->start, res->end - res->start + 1);
+request_mem_failed:
+	kfree(i2c);
+
+	return ret;
+}
+
+static int __devexit ocores_i2c_remove(struct platform_device* pdev)
+{
+	struct ocores_i2c *i2c = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	/* disable i2c logic */
+	oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL)
+		  & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
+
+	/* remove adapter & data */
+	i2c_del_adapter(&i2c->adap);
+	platform_set_drvdata(pdev, NULL);
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (res)
+		free_irq(res->start, i2c);
+
+	iounmap(i2c->base);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res)
+		release_mem_region(res->start, res->end - res->start + 1);
+
+	kfree(i2c);
+
+	return 0;
+}
+
+static struct platform_driver ocores_i2c_driver = {
+	.probe  = ocores_i2c_probe,
+	.remove = __devexit_p(ocores_i2c_remove),
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "ocores-i2c",
+	},
+};
+
+static int __init ocores_i2c_init(void)
+{
+	return platform_driver_register(&ocores_i2c_driver);
+}
+
+static void __exit ocores_i2c_exit(void)
+{
+	platform_driver_unregister(&ocores_i2c_driver);
+}
+
+module_init(ocores_i2c_init);
+module_exit(ocores_i2c_exit);
+
+MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
+MODULE_DESCRIPTION("OpenCores I2C bus driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index d9c7c00..8f2f65b 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -102,13 +102,6 @@
 		 "Forcibly enable the PIIX4 at the given address. "
 		 "EXTREMELY DANGEROUS!");
 
-/* If fix_hstcfg is set to anything different from 0, we reset one of the
-   registers to be a valid value. */
-static int fix_hstcfg;
-module_param (fix_hstcfg, int, 0);
-MODULE_PARM_DESC(fix_hstcfg,
-		"Fix config register. Needed on some boards (Force CPCI735).");
-
 static int piix4_transaction(void);
 
 static unsigned short piix4_smba;
@@ -137,7 +130,7 @@
 	/* Don't access SMBus on IBM systems which get corrupted eeproms */
 	if (dmi_check_system(piix4_dmi_table) &&
 			PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
-		dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module "
+		dev_err(&PIIX4_dev->dev, "IBM system detected; this module "
 			"may corrupt your serial eeprom! Refusing to load "
 			"module!\n");
 		return -EPERM;
@@ -166,22 +159,6 @@
 
 	pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
 
-	/* Some BIOS will set up the chipset incorrectly and leave a register
-	   in an undefined state (causing I2C to act very strangely). */
-	if (temp & 0x02) {
-		if (fix_hstcfg) {
-			dev_info(&PIIX4_dev->dev, "Working around buggy BIOS "
-					"(I2C)\n");
-			temp &= 0xfd;
-			pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp);
-		} else {
-			dev_info(&PIIX4_dev->dev, "Unusual config register "
-					"value\n");
-			dev_info(&PIIX4_dev->dev, "Try using fix_hstcfg=1 if "
-					"you experience problems\n");
-		}
-	}
- 
 	/* If force_addr is set, we program the new address here. Just to make
 	   sure, we disable the PIIX4 first. */
 	if (force_addr) {
@@ -214,7 +191,7 @@
 		}
 	}
 
-	if ((temp & 0x0E) == 8)
+	if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2))
 		dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n");
 	else if ((temp & 0x0E) == 0)
 		dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n");
@@ -413,6 +390,12 @@
 static struct pci_device_id piix4_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3),
 	  .driver_data = 3 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS),
+	  .driver_data = 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS),
+	  .driver_data = 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS),
+	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
 	  .driver_data = 0 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 766cc96..22a3eda 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -33,7 +33,6 @@
 #include <linux/delay.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
-#include <asm/msr.h>
 
 #include <linux/scx200.h>
 
@@ -85,6 +84,10 @@
 	u8 *ptr;
 	char needs_reset;
 	unsigned len;
+
+	/* PCI device info */
+	struct pci_dev *pdev;
+	int bar;
 };
 
 /* Register Definitions */
@@ -381,7 +384,7 @@
 static struct scx200_acb_iface *scx200_acb_list;
 static DECLARE_MUTEX(scx200_acb_list_mutex);
 
-static int scx200_acb_probe(struct scx200_acb_iface *iface)
+static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
 {
 	u8 val;
 
@@ -417,17 +420,16 @@
 	return 0;
 }
 
-static int  __init scx200_acb_create(const char *text, int base, int index)
+static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
+		int index)
 {
 	struct scx200_acb_iface *iface;
 	struct i2c_adapter *adapter;
-	int rc;
 
 	iface = kzalloc(sizeof(*iface), GFP_KERNEL);
 	if (!iface) {
 		printk(KERN_ERR NAME ": can't allocate memory\n");
-		rc = -ENOMEM;
-		goto errout;
+		return NULL;
 	}
 
 	adapter = &iface->adapter;
@@ -440,26 +442,27 @@
 
 	mutex_init(&iface->mutex);
 
-	if (!request_region(base, 8, adapter->name)) {
-		printk(KERN_ERR NAME ": can't allocate io 0x%x-0x%x\n",
-			base, base + 8-1);
-		rc = -EBUSY;
-		goto errout_free;
-	}
-	iface->base = base;
+	return iface;
+}
+
+static int __init scx200_acb_create(struct scx200_acb_iface *iface)
+{
+	struct i2c_adapter *adapter;
+	int rc;
+
+	adapter = &iface->adapter;
 
 	rc = scx200_acb_probe(iface);
 	if (rc) {
 		printk(KERN_WARNING NAME ": probe failed\n");
-		goto errout_release;
+		return rc;
 	}
 
 	scx200_acb_reset(iface);
 
 	if (i2c_add_adapter(adapter) < 0) {
 		printk(KERN_ERR NAME ": failed to register\n");
-		rc = -ENODEV;
-		goto errout_release;
+		return -ENODEV;
 	}
 
 	down(&scx200_acb_list_mutex);
@@ -468,64 +471,148 @@
 	up(&scx200_acb_list_mutex);
 
 	return 0;
+}
 
- errout_release:
-	release_region(iface->base, 8);
+static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
+		int bar)
+{
+	struct scx200_acb_iface *iface;
+	int rc;
+
+	iface = scx200_create_iface(text, 0);
+
+	if (iface == NULL)
+		return -ENOMEM;
+
+	iface->pdev = pdev;
+	iface->bar = bar;
+
+	pci_enable_device_bars(iface->pdev, 1 << iface->bar);
+
+	rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name);
+
+	if (rc != 0) {
+		printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n",
+				iface->bar);
+		goto errout_free;
+	}
+
+	iface->base = pci_resource_start(iface->pdev, iface->bar);
+	rc = scx200_acb_create(iface);
+
+	if (rc == 0)
+		return 0;
+
+	pci_release_region(iface->pdev, iface->bar);
+	pci_dev_put(iface->pdev);
  errout_free:
 	kfree(iface);
- errout:
 	return rc;
 }
 
-static struct pci_device_id scx200[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
-	{ },
-};
-
-static struct pci_device_id divil_pci[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS,  PCI_DEVICE_ID_NS_CS5535_ISA) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
-	{ } /* NULL entry */
-};
-
-#define MSR_LBAR_SMB		0x5140000B
-
-static __init int scx200_add_cs553x(void)
+static int __init scx200_create_isa(const char *text, unsigned long base,
+		int index)
 {
-	u32	low, hi;
-	u32	smb_base;
+	struct scx200_acb_iface *iface;
+	int rc;
 
-	/* Grab & reserve the SMB I/O range */
-	rdmsr(MSR_LBAR_SMB, low, hi);
+	iface = scx200_create_iface(text, index);
 
-	/* Check the IO mask and whether SMB is enabled */
-	if (hi != 0x0000F001) {
-		printk(KERN_WARNING NAME ": SMBus not enabled\n");
-		return -ENODEV;
+	if (iface == NULL)
+		return -ENOMEM;
+
+	if (request_region(base, 8, iface->adapter.name) == 0) {
+		printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
+		       base, base + 8 - 1);
+		rc = -EBUSY;
+		goto errout_free;
 	}
 
-	/* SMBus IO size is 8 bytes */
-	smb_base = low & 0x0000FFF8;
+	iface->base = base;
+	rc = scx200_acb_create(iface);
 
-	return scx200_acb_create("CS5535", smb_base, 0);
+	if (rc == 0)
+		return 0;
+
+	release_region(base, 8);
+ errout_free:
+	kfree(iface);
+	return rc;
+}
+
+/* Driver data is an index into the scx200_data array that indicates
+ * the name and the BAR where the I/O address resource is located.  ISA
+ * devices are flagged with a bar value of -1 */
+
+static struct pci_device_id scx200_pci[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE),
+	  .driver_data = 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE),
+	  .driver_data = 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA),
+	  .driver_data = 1 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA),
+	  .driver_data = 2 }
+};
+
+static struct {
+	const char *name;
+	int bar;
+} scx200_data[] = {
+	{ "SCx200", -1 },
+	{ "CS5535",  0 },
+	{ "CS5536",  0 }
+};
+
+static __init int scx200_scan_pci(void)
+{
+	int data, dev;
+	int rc = -ENODEV;
+	struct pci_dev *pdev;
+
+	for(dev = 0; dev < ARRAY_SIZE(scx200_pci); dev++) {
+		pdev = pci_get_device(scx200_pci[dev].vendor,
+				scx200_pci[dev].device, NULL);
+
+		if (pdev == NULL)
+			continue;
+
+		data = scx200_pci[dev].driver_data;
+
+		/* if .bar is greater or equal to zero, this is a
+		 * PCI device - otherwise, we assume
+		   that the ports are ISA based
+		*/
+
+		if (scx200_data[data].bar >= 0)
+			rc = scx200_create_pci(scx200_data[data].name, pdev,
+					scx200_data[data].bar);
+		else {
+			int i;
+
+			for (i = 0; i < MAX_DEVICES; ++i) {
+				if (base[i] == 0)
+					continue;
+
+				rc = scx200_create_isa(scx200_data[data].name,
+						base[i],
+						i);
+			}
+		}
+
+		break;
+	}
+
+	return rc;
 }
 
 static int __init scx200_acb_init(void)
 {
-	int i;
-	int	rc = -ENODEV;
+	int rc;
 
 	pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
 
-	/* Verify that this really is a SCx200 processor */
-	if (pci_dev_present(scx200)) {
-		for (i = 0; i < MAX_DEVICES; ++i) {
-			if (base[i] > 0)
-				rc = scx200_acb_create("SCx200", base[i], i);
-		}
-	} else if (pci_dev_present(divil_pci))
-		rc = scx200_add_cs553x();
+	rc = scx200_scan_pci();
 
 	/* If at least one bus was created, init must succeed */
 	if (scx200_acb_list)
@@ -543,7 +630,14 @@
 		up(&scx200_acb_list_mutex);
 
 		i2c_del_adapter(&iface->adapter);
-		release_region(iface->base, 8);
+
+		if (iface->pdev) {
+			pci_release_region(iface->pdev, iface->bar);
+			pci_dev_put(iface->pdev);
+		}
+		else
+			release_region(iface->base, 8);
+
 		kfree(iface);
 		down(&scx200_acb_list_mutex);
 	}
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 7aa5c38..87ee3ce 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -39,6 +39,7 @@
 config SENSORS_PCF8574
 	tristate "Philips PCF8574 and PCF8574A"
 	depends on I2C && EXPERIMENTAL
+	default n
 	help
 	  If you say yes here you get support for Philips PCF8574 and 
 	  PCF8574A chips.
@@ -46,6 +47,9 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called pcf8574.
 
+	  These devices are hard to detect and rarely found on mainstream
+	  hardware.  If unsure, say N.
+
 config SENSORS_PCA9539
 	tristate "Philips PCA9539 16-bit I/O port"
 	depends on I2C && EXPERIMENTAL
@@ -59,12 +63,16 @@
 config SENSORS_PCF8591
 	tristate "Philips PCF8591"
 	depends on I2C && EXPERIMENTAL
+	default n
 	help
 	  If you say yes here you get support for Philips PCF8591 chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called pcf8591.
 
+	  These devices are hard to detect and rarely found on mainstream
+	  hardware.  If unsure, say N.
+
 config ISP1301_OMAP
 	tristate "Philips ISP1301 with OMAP OTG"
 	depends on I2C && ARCH_OMAP_OTG
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index 99ab4ec..2dd0a34 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -1,11 +1,9 @@
 /*
- * drivers/i2c/chips/m41t00.c
- *
- * I2C client/driver for the ST M41T00 Real-Time Clock chip.
+ * I2C client/driver for the ST M41T00 family of i2c rtc chips.
  *
  * Author: Mark A. Greer <mgreer@mvista.com>
  *
- * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under
  * the terms of the GNU General Public License version 2. This program
  * is licensed "as is" without any warranty of any kind, whether express
  * or implied.
@@ -13,9 +11,6 @@
 /*
  * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
  * interface and the SMBus interface of the i2c subsystem.
- * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
- * recommened in .../Documentation/i2c/writing-clients section
- * "Sending and receiving", using SMBus level communication is preferred.
  */
 
 #include <linux/kernel.h>
@@ -24,56 +19,110 @@
 #include <linux/i2c.h>
 #include <linux/rtc.h>
 #include <linux/bcd.h>
-#include <linux/mutex.h>
 #include <linux/workqueue.h>
-
+#include <linux/platform_device.h>
+#include <linux/m41t00.h>
 #include <asm/time.h>
 #include <asm/rtc.h>
 
-#define	M41T00_DRV_NAME		"m41t00"
-
-static DEFINE_MUTEX(m41t00_mutex);
-
 static struct i2c_driver m41t00_driver;
 static struct i2c_client *save_client;
 
 static unsigned short ignore[] = { I2C_CLIENT_END };
-static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
+static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END };
 
 static struct i2c_client_address_data addr_data = {
-	.normal_i2c		= normal_addr,
-	.probe			= ignore,
-	.ignore			= ignore,
+	.normal_i2c	= normal_addr,
+	.probe		= ignore,
+	.ignore		= ignore,
 };
 
+struct m41t00_chip_info {
+	u8	type;
+	char	*name;
+	u8	read_limit;
+	u8	sec;		/* Offsets for chip regs */
+	u8	min;
+	u8	hour;
+	u8	day;
+	u8	mon;
+	u8	year;
+	u8	alarm_mon;
+	u8	alarm_hour;
+	u8	sqw;
+	u8	sqw_freq;
+};
+
+static struct m41t00_chip_info m41t00_chip_info_tbl[] = {
+	{
+		.type		= M41T00_TYPE_M41T00,
+		.name		= "m41t00",
+		.read_limit	= 5,
+		.sec		= 0,
+		.min		= 1,
+		.hour		= 2,
+		.day		= 4,
+		.mon		= 5,
+		.year		= 6,
+	},
+	{
+		.type		= M41T00_TYPE_M41T81,
+		.name		= "m41t81",
+		.read_limit	= 1,
+		.sec		= 1,
+		.min		= 2,
+		.hour		= 3,
+		.day		= 5,
+		.mon		= 6,
+		.year		= 7,
+		.alarm_mon	= 0xa,
+		.alarm_hour	= 0xc,
+		.sqw		= 0x13,
+	},
+	{
+		.type		= M41T00_TYPE_M41T85,
+		.name		= "m41t85",
+		.read_limit	= 1,
+		.sec		= 1,
+		.min		= 2,
+		.hour		= 3,
+		.day		= 5,
+		.mon		= 6,
+		.year		= 7,
+		.alarm_mon	= 0xa,
+		.alarm_hour	= 0xc,
+		.sqw		= 0x13,
+	},
+};
+static struct m41t00_chip_info *m41t00_chip;
+
 ulong
 m41t00_get_rtc_time(void)
 {
-	s32	sec, min, hour, day, mon, year;
-	s32	sec1, min1, hour1, day1, mon1, year1;
-	ulong	limit = 10;
+	s32 sec, min, hour, day, mon, year;
+	s32 sec1, min1, hour1, day1, mon1, year1;
+	u8 reads = 0;
+	u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= msgbuf,
+		},
+		{
+			.addr	= save_client->addr,
+			.flags	= I2C_M_RD,
+			.len	= 8,
+			.buf	= buf,
+		},
+	};
 
 	sec = min = hour = day = mon = year = 0;
-	sec1 = min1 = hour1 = day1 = mon1 = year1 = 0;
 
-	mutex_lock(&m41t00_mutex);
 	do {
-		if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0)
-			&& ((min = i2c_smbus_read_byte_data(save_client, 1))
-				>= 0)
-			&& ((hour = i2c_smbus_read_byte_data(save_client, 2))
-				>= 0)
-			&& ((day = i2c_smbus_read_byte_data(save_client, 4))
-				>= 0)
-			&& ((mon = i2c_smbus_read_byte_data(save_client, 5))
-				>= 0)
-			&& ((year = i2c_smbus_read_byte_data(save_client, 6))
-				>= 0)
-			&& ((sec == sec1) && (min == min1) && (hour == hour1)
-				&& (day == day1) && (mon == mon1)
-				&& (year == year1)))
-
-				break;
+		if (i2c_transfer(save_client->adapter, msgs, 2) < 0)
+			goto read_err;
 
 		sec1 = sec;
 		min1 = min;
@@ -81,69 +130,88 @@
 		day1 = day;
 		mon1 = mon;
 		year1 = year;
-	} while (--limit > 0);
-	mutex_unlock(&m41t00_mutex);
 
-	if (limit == 0) {
-		dev_warn(&save_client->dev,
-			"m41t00: can't read rtc chip\n");
-		sec = min = hour = day = mon = year = 0;
-	}
+		sec = buf[m41t00_chip->sec] & 0x7f;
+		min = buf[m41t00_chip->min] & 0x7f;
+		hour = buf[m41t00_chip->hour] & 0x3f;
+		day = buf[m41t00_chip->day] & 0x3f;
+		mon = buf[m41t00_chip->mon] & 0x1f;
+		year = buf[m41t00_chip->year];
+	} while ((++reads < m41t00_chip->read_limit) && ((sec != sec1)
+			|| (min != min1) || (hour != hour1) || (day != day1)
+			|| (mon != mon1) || (year != year1)));
 
-	sec &= 0x7f;
-	min &= 0x7f;
-	hour &= 0x3f;
-	day &= 0x3f;
-	mon &= 0x1f;
-	year &= 0xff;
+	if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1)
+			|| (hour != hour1) || (day != day1) || (mon != mon1)
+			|| (year != year1)))
+		goto read_err;
 
-	BCD_TO_BIN(sec);
-	BCD_TO_BIN(min);
-	BCD_TO_BIN(hour);
-	BCD_TO_BIN(day);
-	BCD_TO_BIN(mon);
-	BCD_TO_BIN(year);
+	sec = BCD2BIN(sec);
+	min = BCD2BIN(min);
+	hour = BCD2BIN(hour);
+	day = BCD2BIN(day);
+	mon = BCD2BIN(mon);
+	year = BCD2BIN(year);
 
 	year += 1900;
 	if (year < 1970)
 		year += 100;
 
 	return mktime(year, mon, day, hour, min, sec);
+
+read_err:
+	dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n");
+	return 0;
 }
+EXPORT_SYMBOL_GPL(m41t00_get_rtc_time);
 
 static void
 m41t00_set(void *arg)
 {
 	struct rtc_time	tm;
-	ulong	nowtime = *(ulong *)arg;
+	int nowtime = *(int *)arg;
+	s32 sec, min, hour, day, mon, year;
+	u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 };
+	struct i2c_msg msgs[] = {
+		{
+			.addr	= save_client->addr,
+			.flags	= 0,
+			.len	= 1,
+			.buf	= msgbuf,
+		},
+		{
+			.addr	= save_client->addr,
+			.flags	= I2C_M_RD,
+			.len	= 8,
+			.buf	= buf,
+		},
+	};
 
 	to_tm(nowtime, &tm);
 	tm.tm_year = (tm.tm_year - 1900) % 100;
 
-	BIN_TO_BCD(tm.tm_sec);
-	BIN_TO_BCD(tm.tm_min);
-	BIN_TO_BCD(tm.tm_hour);
-	BIN_TO_BCD(tm.tm_mon);
-	BIN_TO_BCD(tm.tm_mday);
-	BIN_TO_BCD(tm.tm_year);
+	sec = BIN2BCD(tm.tm_sec);
+	min = BIN2BCD(tm.tm_min);
+	hour = BIN2BCD(tm.tm_hour);
+	day = BIN2BCD(tm.tm_mday);
+	mon = BIN2BCD(tm.tm_mon);
+	year = BIN2BCD(tm.tm_year);
 
-	mutex_lock(&m41t00_mutex);
-	if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
-		|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
-			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
-			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
-			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
-			< 0)
-		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
-			< 0))
+	/* Read reg values into buf[0..7]/wbuf[1..8] */
+	if (i2c_transfer(save_client->adapter, msgs, 2) < 0) {
+		dev_err(&save_client->dev, "m41t00_set: Read error\n");
+		return;
+	}
 
-		dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
+	wbuf[0] = 0; /* offset into rtc's regs */
+	buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f);
+	buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f);
+	buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f);
+	buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f);
+	buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f);
 
-	mutex_unlock(&m41t00_mutex);
-	return;
+	if (i2c_master_send(save_client, wbuf, 9) < 0)
+		dev_err(&save_client->dev, "m41t00_set: Write error\n");
 }
 
 static ulong new_time;
@@ -162,6 +230,48 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(m41t00_set_rtc_time);
+
+/*
+ *****************************************************************************
+ *
+ *	platform_data Driver Interface
+ *
+ *****************************************************************************
+ */
+static int __init
+m41t00_platform_probe(struct platform_device *pdev)
+{
+	struct m41t00_platform_data *pdata;
+	int i;
+
+	if (pdev && (pdata = pdev->dev.platform_data)) {
+		normal_addr[0] = pdata->i2c_addr;
+
+		for (i=0; i<ARRAY_SIZE(m41t00_chip_info_tbl); i++)
+			if (m41t00_chip_info_tbl[i].type == pdata->type) {
+				m41t00_chip = &m41t00_chip_info_tbl[i];
+				m41t00_chip->sqw_freq = pdata->sqw_freq;
+				return 0;
+			}
+	}
+	return -ENODEV;
+}
+
+static int __exit
+m41t00_platform_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver m41t00_platform_driver = {
+	.probe  = m41t00_platform_probe,
+	.remove = m41t00_platform_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name  = M41T00_DRV_NAME,
+	},
+};
 
 /*
  *****************************************************************************
@@ -176,23 +286,71 @@
 	struct i2c_client *client;
 	int rc;
 
+	if (!i2c_check_functionality(adap, I2C_FUNC_I2C
+			| I2C_FUNC_SMBUS_BYTE_DATA))
+		return 0;
+
 	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
 	if (!client)
 		return -ENOMEM;
 
-	strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
+	strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE);
 	client->addr = addr;
 	client->adapter = adap;
 	client->driver = &m41t00_driver;
 
-	if ((rc = i2c_attach_client(client)) != 0) {
-		kfree(client);
-		return rc;
+	if ((rc = i2c_attach_client(client)))
+		goto attach_err;
+
+	if (m41t00_chip->type != M41T00_TYPE_M41T00) {
+		/* If asked, disable SQW, set SQW frequency & re-enable */
+		if (m41t00_chip->sqw_freq)
+			if (((rc = i2c_smbus_read_byte_data(client,
+					m41t00_chip->alarm_mon)) < 0)
+			 || ((rc = i2c_smbus_write_byte_data(client,
+					m41t00_chip->alarm_mon, rc & ~0x40)) <0)
+			 || ((rc = i2c_smbus_write_byte_data(client,
+					m41t00_chip->sqw,
+					m41t00_chip->sqw_freq)) < 0)
+			 || ((rc = i2c_smbus_write_byte_data(client,
+					m41t00_chip->alarm_mon, rc | 0x40)) <0))
+				goto sqw_err;
+
+		/* Make sure HT (Halt Update) bit is cleared */
+		if ((rc = i2c_smbus_read_byte_data(client,
+				m41t00_chip->alarm_hour)) < 0)
+			goto ht_err;
+
+		if (rc & 0x40)
+			if ((rc = i2c_smbus_write_byte_data(client,
+					m41t00_chip->alarm_hour, rc & ~0x40))<0)
+				goto ht_err;
 	}
 
-	m41t00_wq = create_singlethread_workqueue("m41t00");
+	/* Make sure ST (stop) bit is cleared */
+	if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0)
+		goto st_err;
+
+	if (rc & 0x80)
+		if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec,
+				rc & ~0x80)) < 0)
+			goto st_err;
+
+	m41t00_wq = create_singlethread_workqueue(m41t00_chip->name);
 	save_client = client;
 	return 0;
+
+st_err:
+	dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n");
+	goto attach_err;
+ht_err:
+	dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n");
+	goto attach_err;
+sqw_err:
+	dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n");
+attach_err:
+	kfree(client);
+	return rc;
 }
 
 static int
@@ -204,7 +362,7 @@
 static int
 m41t00_detach(struct i2c_client *client)
 {
-	int	rc;
+	int rc;
 
 	if ((rc = i2c_detach_client(client)) == 0) {
 		kfree(client);
@@ -225,14 +383,18 @@
 static int __init
 m41t00_init(void)
 {
-	return i2c_add_driver(&m41t00_driver);
+	int rc;
+
+	if (!(rc = platform_driver_register(&m41t00_platform_driver)))
+		rc = i2c_add_driver(&m41t00_driver);
+	return rc;
 }
 
 static void __exit
 m41t00_exit(void)
 {
 	i2c_del_driver(&m41t00_driver);
-	return;
+	platform_driver_unregister(&m41t00_platform_driver);
 }
 
 module_init(m41t00_init);
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 45e2cdf..a45155f 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -916,7 +916,7 @@
 }
 
 s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
-			       u8 length, u8 *values)
+			       u8 length, const u8 *values)
 {
 	union i2c_smbus_data data;
 
@@ -944,7 +944,7 @@
 }
 
 s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
-				   u8 length, u8 *values)
+				   u8 length, const u8 *values)
 {
 	union i2c_smbus_data data;
 
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index ed7eed3..58ccddd 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -426,10 +426,7 @@
 
 	/* register this i2c device with the driver core */
 	i2c_dev->adap = adap;
-	if (adap->dev.parent == &platform_bus)
-		dev = &adap->dev;
-	else
-		dev = adap->dev.parent;
+	dev = &adap->dev;
 	i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
 						 MKDEV(I2C_MAJOR, i2c_dev->minor),
 						 dev, "i2c-%d", i2c_dev->minor);
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index b4a41d6..99fa424 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -395,7 +395,8 @@
 			 * we cannot reliably check if drive can auto-close
 			 */
 			if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
-				log = 0;
+				break;
+			log = 1;
 			break;
 		case UNIT_ATTENTION:
 			/*
@@ -417,6 +418,11 @@
 			      struct request *failed_command,
 			      struct request_sense *sense)
 {
+	unsigned long sector;
+	unsigned long bio_sectors;
+	unsigned long valid;
+	struct cdrom_info *info = drive->driver_data;
+
 	if (!cdrom_log_sense(drive, failed_command, sense))
 		return;
 
@@ -429,6 +435,37 @@
 		if (sense->sense_key == 0x05 && sense->asc == 0x24)
 			return;
 
+ 	if (sense->error_code == 0x70) {	/* Current Error */
+ 		switch(sense->sense_key) {
+		case MEDIUM_ERROR:
+		case VOLUME_OVERFLOW:
+		case ILLEGAL_REQUEST:
+			if (!sense->valid)
+				break;
+			if (failed_command == NULL ||
+					!blk_fs_request(failed_command))
+				break;
+			sector = (sense->information[0] << 24) |
+				 (sense->information[1] << 16) |
+				 (sense->information[2] <<  8) |
+				 (sense->information[3]);
+
+			bio_sectors = bio_sectors(failed_command->bio);
+			if (bio_sectors < 4)
+				bio_sectors = 4;
+			if (drive->queue->hardsect_size == 2048)
+				sector <<= 2;	/* Device sector size is 2K */
+			sector &= ~(bio_sectors -1);
+			valid = (sector - failed_command->sector) << 9;
+
+			if (valid < 0)
+				valid = 0;
+			if (sector < get_capacity(info->disk) &&
+				drive->probed_capacity - sector < 4 * 75) {
+				set_capacity(info->disk, sector);
+			}
+ 		}
+ 	}
 #if VERBOSE_IDE_CD_ERRORS
 	{
 		int i;
@@ -609,17 +646,23 @@
 				sense = failed->sense;
 				failed->sense_len = rq->sense_len;
 			}
-
+			cdrom_analyze_sense_data(drive, failed, sense);
 			/*
 			 * now end failed request
 			 */
-			spin_lock_irqsave(&ide_lock, flags);
-			end_that_request_chunk(failed, 0, failed->data_len);
-			end_that_request_last(failed, 0);
-			spin_unlock_irqrestore(&ide_lock, flags);
-		}
-
-		cdrom_analyze_sense_data(drive, failed, sense);
+			if (blk_fs_request(failed)) {
+				if (ide_end_dequeued_request(drive, failed, 0,
+						failed->hard_nr_sectors))
+					BUG();
+			} else {
+				spin_lock_irqsave(&ide_lock, flags);
+				end_that_request_chunk(failed, 0,
+							failed->data_len);
+				end_that_request_last(failed, 0);
+				spin_unlock_irqrestore(&ide_lock, flags);
+			}
+		} else
+			cdrom_analyze_sense_data(drive, NULL, sense);
 	}
 
 	if (!rq->current_nr_sectors && blk_fs_request(rq))
@@ -633,6 +676,13 @@
 	ide_end_request(drive, uptodate, nsectors);
 }
 
+static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
+{
+	if (stat & 0x80)
+		return;
+	ide_dump_status(drive, msg, stat);
+}
+
 /* Returns 0 if the request should be continued.
    Returns 1 if the request was ended. */
 static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
@@ -761,16 +811,16 @@
 			   sense_key == DATA_PROTECT) {
 			/* No point in retrying after an illegal
 			   request or data protect error.*/
-			ide_dump_status (drive, "command error", stat);
+			ide_dump_status_no_sense (drive, "command error", stat);
 			do_end_request = 1;
 		} else if (sense_key == MEDIUM_ERROR) {
 			/* No point in re-trying a zillion times on a bad 
 			 * sector...  If we got here the error is not correctable */
-			ide_dump_status (drive, "media error (bad sector)", stat);
+			ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
 			do_end_request = 1;
 		} else if (sense_key == BLANK_CHECK) {
 			/* Disk appears blank ?? */
-			ide_dump_status (drive, "media error (blank)", stat);
+			ide_dump_status_no_sense (drive, "media error (blank)", stat);
 			do_end_request = 1;
 		} else if ((err & ~ABRT_ERR) != 0) {
 			/* Go to the default handler
@@ -782,13 +832,27 @@
 			do_end_request = 1;
 		}
 
-		if (do_end_request)
-			cdrom_end_request(drive, 0);
+		/* End a request through request sense analysis when we have
+		   sense data. We need this in order to perform end of media
+		   processing */
 
-		/* If we got a CHECK_CONDITION status,
-		   queue a request sense command. */
-		if ((stat & ERR_STAT) != 0)
-			cdrom_queue_request_sense(drive, NULL, NULL);
+		if (do_end_request) {
+			if (stat & ERR_STAT) {
+				unsigned long flags;
+				spin_lock_irqsave(&ide_lock, flags);
+				blkdev_dequeue_request(rq);
+				HWGROUP(drive)->rq = NULL;
+				spin_unlock_irqrestore(&ide_lock, flags);
+
+				cdrom_queue_request_sense(drive, rq->sense, rq);
+			} else
+				cdrom_end_request(drive, 0);
+		} else {
+			/* If we got a CHECK_CONDITION status,
+			   queue a request sense command. */
+			if (stat & ERR_STAT)
+				cdrom_queue_request_sense(drive, NULL, NULL);
+		}
 	} else {
 		blk_dump_rq_flags(rq, "ide-cd: bad rq");
 		cdrom_end_request(drive, 0);
@@ -1451,9 +1515,12 @@
 	} else {
 confused:
 		printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
-			"appears confused (ireason = 0x%02x)\n",
+			"appears confused (ireason = 0x%02x). "
+			"Trying to recover by ending request.\n",
 			drive->name, ireason);
 		rq->flags |= REQ_FAILED;
+		cdrom_end_request(drive, 0);
+		return ide_stopped;
 	}
 
 	/* Now we wait for another interrupt. */
@@ -1488,8 +1555,7 @@
 }
 
 
-static
-int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
 {
 	struct request_sense sense;
 	int retries = 10;
@@ -1722,8 +1788,7 @@
 		}
 	}
 
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
+	BUG_ON(HWGROUP(drive)->handler != NULL);
 
 	ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);
 	return ide_started;
@@ -2218,6 +2283,9 @@
 		toc->capacity = 0x1fffff;
 
 	set_capacity(info->disk, toc->capacity * sectors_per_frame);
+	/* Save a private copy of te TOC capacity for error handling */
+	drive->probed_capacity = toc->capacity * sectors_per_frame;
+
 	blk_queue_hardsect_size(drive->queue,
 				sectors_per_frame << SECTOR_BITS);
 
@@ -2340,6 +2408,7 @@
 	if (!stat && (last_written > toc->capacity)) {
 		toc->capacity = last_written;
 		set_capacity(info->disk, toc->capacity * sectors_per_frame);
+		drive->probed_capacity = toc->capacity * sectors_per_frame;
 	}
 
 	/* Remember that we've read this stuff. */
@@ -2696,14 +2765,11 @@
 	 * any other way to detect this...
 	 */
 	if (sense.sense_key == NOT_READY) {
-		if (sense.asc == 0x3a) {
-			if (sense.ascq == 1)
-				return CDS_NO_DISC;
-			else if (sense.ascq == 0 || sense.ascq == 2)
-				return CDS_TRAY_OPEN;
-		}
+		if (sense.asc == 0x3a && sense.ascq == 1)
+			return CDS_NO_DISC;
+		else
+			return CDS_TRAY_OPEN;
 	}
-
 	return CDS_DRIVE_NOT_READY;
 }
 
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index a5017de..f033d73 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -37,7 +37,7 @@
  * Version 1.15		convert all calls to ide_raw_taskfile
  *				since args will return register content.
  * Version 1.16		added suspend-resume-checkpower
- * Version 1.17		do flush on standy, do flush on ATA < ATA6
+ * Version 1.17		do flush on standby, do flush on ATA < ATA6
  *			fix wcache setup.
  */
 
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index c481be8..783a247 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -206,8 +206,7 @@
 	ide_hwif_t *hwif = HWIF(drive);
 	struct scatterlist *sg = hwif->sg_table;
 
-	if ((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256)
-		BUG();
+	BUG_ON((rq->flags & REQ_DRIVE_TASKFILE) && rq->nr_sectors > 256);
 
 	ide_map_sg(drive, rq);
 
@@ -947,8 +946,7 @@
 	}
 	printk("\n");
 
-	if (!(hwif->dma_master))
-		BUG();
+	BUG_ON(!hwif->dma_master);
 }
 
 EXPORT_SYMBOL_GPL(ide_setup_dma);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index a53e3ce..4656587 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -898,8 +898,7 @@
 					"to send us more data than expected "
 					"- discarding data\n");
 				idefloppy_discard_data(drive,bcount.all);
-				if (HWGROUP(drive)->handler != NULL)
-					BUG();
+				BUG_ON(HWGROUP(drive)->handler != NULL);
 				ide_set_handler(drive,
 						&idefloppy_pc_intr,
 						IDEFLOPPY_WAIT_CMD,
@@ -932,8 +931,7 @@
 	pc->actually_transferred += bcount.all;
 	pc->current_position += bcount.all;
 
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
+	BUG_ON(HWGROUP(drive)->handler != NULL);
 	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
 	return ide_started;
 }
@@ -960,8 +958,7 @@
 				"issuing a packet command\n");
 		return ide_do_reset(drive);
 	}
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
+	BUG_ON(HWGROUP(drive)->handler != NULL);
 	/* Set the interrupt routine */
 	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
 	/* Send the actual packet */
@@ -1017,8 +1014,7 @@
 	 * 40 and 50msec work well. idefloppy_pc_intr will not be actually
 	 * used until after the packet is moved in about 50 msec.
 	 */
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
+	BUG_ON(HWGROUP(drive)->handler != NULL);
 	ide_set_handler(drive, 
 	  &idefloppy_pc_intr, 		/* service routine for packet command */
 	  floppy->ticks,		/* wait this long before "failing" */
@@ -1288,7 +1284,7 @@
 
 	debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n",
 			rq->rq_status,
-			rq->rq_disk ? rq->rq_disk->disk_name ? "?",
+			rq->rq_disk ? rq->rq_disk->disk_name : "?",
 			rq->flags, rq->errors);
 	debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
 			"current_nr_sectors: %d\n", (long)rq->sector,
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index c01615d..26ceab1 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -142,38 +142,41 @@
 
 static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
 {
+	struct request_pm_state *pm = rq->end_io_data;
+
 	if (drive->media != ide_disk)
 		return;
 
-	switch (rq->pm->pm_step) {
+	switch (pm->pm_step) {
 	case ide_pm_flush_cache:	/* Suspend step 1 (flush cache) complete */
-		if (rq->pm->pm_state == PM_EVENT_FREEZE)
-			rq->pm->pm_step = ide_pm_state_completed;
+		if (pm->pm_state == PM_EVENT_FREEZE)
+			pm->pm_step = ide_pm_state_completed;
 		else
-			rq->pm->pm_step = idedisk_pm_standby;
+			pm->pm_step = idedisk_pm_standby;
 		break;
 	case idedisk_pm_standby:	/* Suspend step 2 (standby) complete */
-		rq->pm->pm_step = ide_pm_state_completed;
+		pm->pm_step = ide_pm_state_completed;
 		break;
 	case idedisk_pm_idle:		/* Resume step 1 (idle) complete */
-		rq->pm->pm_step = ide_pm_restore_dma;
+		pm->pm_step = ide_pm_restore_dma;
 		break;
 	}
 }
 
 static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
 {
+	struct request_pm_state *pm = rq->end_io_data;
 	ide_task_t *args = rq->special;
 
 	memset(args, 0, sizeof(*args));
 
 	if (drive->media != ide_disk) {
 		/* skip idedisk_pm_idle for ATAPI devices */
-		if (rq->pm->pm_step == idedisk_pm_idle)
-			rq->pm->pm_step = ide_pm_restore_dma;
+		if (pm->pm_step == idedisk_pm_idle)
+			pm->pm_step = ide_pm_restore_dma;
 	}
 
-	switch (rq->pm->pm_step) {
+	switch (pm->pm_step) {
 	case ide_pm_flush_cache:	/* Suspend step 1 (flush cache) */
 		if (drive->media != ide_disk)
 			break;
@@ -215,11 +218,68 @@
 		drive->hwif->ide_dma_check(drive);
 		break;
 	}
-	rq->pm->pm_step = ide_pm_state_completed;
+	pm->pm_step = ide_pm_state_completed;
 	return ide_stopped;
 }
 
 /**
+ *	ide_end_dequeued_request	-	complete an IDE I/O
+ *	@drive: IDE device for the I/O
+ *	@uptodate:
+ *	@nr_sectors: number of sectors completed
+ *
+ *	Complete an I/O that is no longer on the request queue. This
+ *	typically occurs when we pull the request and issue a REQUEST_SENSE.
+ *	We must still finish the old request but we must not tamper with the
+ *	queue in the meantime.
+ *
+ *	NOTE: This path does not handle barrier, but barrier is not supported
+ *	on ide-cd anyway.
+ */
+
+int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
+			     int uptodate, int nr_sectors)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&ide_lock, flags);
+
+	BUG_ON(!(rq->flags & REQ_STARTED));
+
+	/*
+	 * if failfast is set on a request, override number of sectors and
+	 * complete the whole request right now
+	 */
+	if (blk_noretry_request(rq) && end_io_error(uptodate))
+		nr_sectors = rq->hard_nr_sectors;
+
+	if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+		rq->errors = -EIO;
+
+	/*
+	 * decide whether to reenable DMA -- 3 is a random magic for now,
+	 * if we DMA timeout more than 3 times, just stay in PIO
+	 */
+	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+		drive->state = 0;
+		HWGROUP(drive)->hwif->ide_dma_on(drive);
+	}
+
+	if (!end_that_request_first(rq, uptodate, nr_sectors)) {
+		add_disk_randomness(rq->rq_disk);
+		if (blk_rq_tagged(rq))
+			blk_queue_end_tag(drive->queue, rq);
+		end_that_request_last(rq, uptodate);
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&ide_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
+
+
+/**
  *	ide_complete_pm_request - end the current Power Management request
  *	@drive: target drive
  *	@rq: request
@@ -362,12 +422,13 @@
 			}
 		}
 	} else if (blk_pm_request(rq)) {
+		struct request_pm_state *pm = rq->end_io_data;
 #ifdef DEBUG_PM
 		printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n",
 			drive->name, rq->pm->pm_step, stat, err);
 #endif
 		ide_complete_power_step(drive, rq, stat, err);
-		if (rq->pm->pm_step == ide_pm_state_completed)
+		if (pm->pm_step == ide_pm_state_completed)
 			ide_complete_pm_request(drive, rq);
 		return;
 	}
@@ -444,7 +505,7 @@
 		}
 	}
 
-	if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
+	if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ && hwif->err_stops_fifo == 0)
 		try_to_flush_leftover_data(drive);
 
 	if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
@@ -871,6 +932,39 @@
  	return ide_stopped;
 }
 
+static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
+{
+	struct request_pm_state *pm = rq->end_io_data;
+
+	if (blk_pm_suspend_request(rq) &&
+	    pm->pm_step == ide_pm_state_start_suspend)
+		/* Mark drive blocked when starting the suspend sequence. */
+		drive->blocked = 1;
+	else if (blk_pm_resume_request(rq) &&
+		 pm->pm_step == ide_pm_state_start_resume) {
+		/* 
+		 * The first thing we do on wakeup is to wait for BSY bit to
+		 * go away (with a looong timeout) as a drive on this hwif may
+		 * just be POSTing itself.
+		 * We do that before even selecting as the "other" device on
+		 * the bus may be broken enough to walk on our toes at this
+		 * point.
+		 */
+		int rc;
+#ifdef DEBUG_PM
+		printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
+#endif
+		rc = ide_wait_not_busy(HWIF(drive), 35000);
+		if (rc)
+			printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
+		SELECT_DRIVE(drive);
+		HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
+		rc = ide_wait_not_busy(HWIF(drive), 100000);
+		if (rc)
+			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
+	}
+}
+
 /**
  *	start_request	-	start of I/O and command issuing for IDE
  *
@@ -909,33 +1003,8 @@
 	if (block == 0 && drive->remap_0_to_1 == 1)
 		block = 1;  /* redirect MBR access to EZ-Drive partn table */
 
-	if (blk_pm_suspend_request(rq) &&
-	    rq->pm->pm_step == ide_pm_state_start_suspend)
-		/* Mark drive blocked when starting the suspend sequence. */
-		drive->blocked = 1;
-	else if (blk_pm_resume_request(rq) &&
-		 rq->pm->pm_step == ide_pm_state_start_resume) {
-		/* 
-		 * The first thing we do on wakeup is to wait for BSY bit to
-		 * go away (with a looong timeout) as a drive on this hwif may
-		 * just be POSTing itself.
-		 * We do that before even selecting as the "other" device on
-		 * the bus may be broken enough to walk on our toes at this
-		 * point.
-		 */
-		int rc;
-#ifdef DEBUG_PM
-		printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name);
-#endif
-		rc = ide_wait_not_busy(HWIF(drive), 35000);
-		if (rc)
-			printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
-		SELECT_DRIVE(drive);
-		HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
-		rc = ide_wait_not_busy(HWIF(drive), 10000);
-		if (rc)
-			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
-	}
+	if (blk_pm_request(rq))
+		ide_check_pm_state(drive, rq);
 
 	SELECT_DRIVE(drive);
 	if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
@@ -950,13 +1019,14 @@
 		else if (rq->flags & REQ_DRIVE_TASKFILE)
 			return execute_drive_cmd(drive, rq);
 		else if (blk_pm_request(rq)) {
+			struct request_pm_state *pm = rq->end_io_data;
 #ifdef DEBUG_PM
 			printk("%s: start_power_step(step: %d)\n",
 				drive->name, rq->pm->pm_step);
 #endif
 			startstop = ide_start_power_step(drive, rq);
 			if (startstop == ide_stopped &&
-			    rq->pm->pm_step == ide_pm_state_completed)
+			    pm->pm_step == ide_pm_state_completed)
 				ide_complete_pm_request(drive, rq);
 			return startstop;
 		}
@@ -1595,7 +1665,7 @@
  *	Initialize a request before we fill it in and send it down to
  *	ide_do_drive_cmd. Commands must be set up by this function. Right
  *	now it doesn't do a lot, but if that changes abusers will have a
- *	nasty suprise.
+ *	nasty surprise.
  */
 
 void ide_init_drive_cmd (struct request *rq)
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b72dde7..32117f0 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -597,6 +597,10 @@
 {
 	if(HWIF(drive)->udma_four == 0)
 		return 0;
+
+	/* Check for SATA but only if we are ATA5 or higher */
+	if (drive->id->hw_config == 0 && (drive->id->major_rev_num & 0x7FE0))
+		return 1;
 	if (!(drive->id->hw_config & 0x6000))
 		return 0;
 #ifndef CONFIG_IDEDMA_IVB
@@ -939,8 +943,7 @@
 	
 	spin_lock_irqsave(&ide_lock, flags);
 	
-	if(hwgroup->handler)
-		BUG();
+	BUG_ON(hwgroup->handler);
 	hwgroup->handler	= handler;
 	hwgroup->expiry		= expiry;
 	hwgroup->timer.expires	= jiffies + timeout;
@@ -981,8 +984,7 @@
 		printk("%s: ATAPI reset complete\n", drive->name);
 	} else {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
-			if (HWGROUP(drive)->handler != NULL)
-				BUG();
+			BUG_ON(HWGROUP(drive)->handler != NULL);
 			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
 			/* continue polling */
 			return ide_started;
@@ -1021,8 +1023,7 @@
 
 	if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
-			if (HWGROUP(drive)->handler != NULL)
-				BUG();
+			BUG_ON(HWGROUP(drive)->handler != NULL);
 			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
 			/* continue polling */
 			return ide_started;
@@ -1138,8 +1139,7 @@
 	hwgroup = HWGROUP(drive);
 
 	/* We must not reset with running handlers */
-	if(hwgroup->handler != NULL)
-		BUG();
+	BUG_ON(hwgroup->handler != NULL);
 
 	/* For an ATAPI device, first try an ATAPI SRST. */
 	if (drive->media != ide_disk && !do_not_try_atapi) {
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 41d46db..7ddb118 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -164,8 +164,7 @@
 //	printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed);
 
 	/* So that we remember to update this if new modes appear */
-	if (mode > 4)
-		BUG();
+	BUG_ON(mode > 4);
 	return min(speed, speed_max[mode]);
 #else /* !CONFIG_BLK_DEV_IDEDMA */
 	return min(speed, (u8)XFER_PIO_4);
@@ -486,7 +485,7 @@
 	unsigned long flags;
 	u8 err = 0;
 
-	local_irq_set(flags);
+	local_irq_save(flags);
 	printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
 	if (stat & BUSY_STAT)
 		printk("Busy ");
@@ -568,7 +567,7 @@
 
 	status.all = stat;
 	error.all = 0;
-	local_irq_set(flags);
+	local_irq_save(flags);
 	printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
 	if (status.b.bsy)
 		printk("Busy ");
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 1b7b4c5..9ebf8ae 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1138,16 +1138,11 @@
 		spin_unlock_irq(&ide_lock);
 	}
 
-#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
+#if !defined(__mc68000__) && !defined(CONFIG_APUS)
 	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET],
 		hwif->io_ports[IDE_DATA_OFFSET]+7,
 		hwif->io_ports[IDE_CONTROL_OFFSET], hwif->irq);
-#elif defined(__sparc__)
-	printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %s", hwif->name,
-		hwif->io_ports[IDE_DATA_OFFSET],
-		hwif->io_ports[IDE_DATA_OFFSET]+7,
-		hwif->io_ports[IDE_CONTROL_OFFSET], __irq_itoa(hwif->irq));
 #else
 	printk("%s at 0x%08lx on irq %d", hwif->name,
 		hwif->io_ports[IDE_DATA_OFFSET], hwif->irq);
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index f04791a..09f3a7d 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2646,21 +2646,23 @@
 	return __idetape_kmalloc_stage(tape, 0, 0);
 }
 
-static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
+static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
 {
 	struct idetape_bh *bh = tape->bh;
 	int count;
+	int ret = 0;
 
 	while (n) {
 #if IDETAPE_DEBUG_BUGS
 		if (bh == NULL) {
 			printk(KERN_ERR "ide-tape: bh == NULL in "
 				"idetape_copy_stage_from_user\n");
-			return;
+			return 1;
 		}
 #endif /* IDETAPE_DEBUG_BUGS */
 		count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
-		copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count);
+		if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
+			ret = 1;
 		n -= count;
 		atomic_add(count, &bh->b_count);
 		buf += count;
@@ -2671,23 +2673,26 @@
 		}
 	}
 	tape->bh = bh;
+	return ret;
 }
 
-static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
+static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
 {
 	struct idetape_bh *bh = tape->bh;
 	int count;
+	int ret = 0;
 
 	while (n) {
 #if IDETAPE_DEBUG_BUGS
 		if (bh == NULL) {
 			printk(KERN_ERR "ide-tape: bh == NULL in "
 				"idetape_copy_stage_to_user\n");
-			return;
+			return 1;
 		}
 #endif /* IDETAPE_DEBUG_BUGS */
 		count = min(tape->b_count, n);
-		copy_to_user(buf, tape->b_data, count);
+		if  (copy_to_user(buf, tape->b_data, count))
+			ret = 1;
 		n -= count;
 		tape->b_data += count;
 		tape->b_count -= count;
@@ -2700,6 +2705,7 @@
 			}
 		}
 	}
+	return ret;
 }
 
 static void idetape_init_merge_stage (idetape_tape_t *tape)
@@ -3719,6 +3725,7 @@
 	struct ide_tape_obj *tape = ide_tape_f(file);
 	ide_drive_t *drive = tape->drive;
 	ssize_t bytes_read,temp, actually_read = 0, rc;
+	ssize_t ret = 0;
 
 #if IDETAPE_DEBUG_LOG
 	if (tape->debug_level >= 3)
@@ -3737,7 +3744,8 @@
 		return (0);
 	if (tape->merge_stage_size) {
 		actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count);
-		idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read);
+		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read))
+			ret = -EFAULT;
 		buf += actually_read;
 		tape->merge_stage_size -= actually_read;
 		count -= actually_read;
@@ -3746,7 +3754,8 @@
 		bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
 		if (bytes_read <= 0)
 			goto finish;
-		idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read);
+		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
+			ret = -EFAULT;
 		buf += bytes_read;
 		count -= bytes_read;
 		actually_read += bytes_read;
@@ -3756,7 +3765,8 @@
 		if (bytes_read <= 0)
 			goto finish;
 		temp = min((unsigned long)count, (unsigned long)bytes_read);
-		idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp);
+		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp))
+			ret = -EFAULT;
 		actually_read += temp;
 		tape->merge_stage_size = bytes_read-temp;
 	}
@@ -3769,7 +3779,8 @@
 		idetape_space_over_filemarks(drive, MTFSF, 1);
 		return 0;
 	}
-	return actually_read;
+
+	return (ret) ? ret : actually_read;
 }
 
 static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
@@ -3777,7 +3788,8 @@
 {
 	struct ide_tape_obj *tape = ide_tape_f(file);
 	ide_drive_t *drive = tape->drive;
-	ssize_t retval, actually_written = 0;
+	ssize_t actually_written = 0;
+	ssize_t ret = 0;
 
 	/* The drive is write protected. */
 	if (tape->write_prot)
@@ -3813,7 +3825,7 @@
 		 *	some drives (Seagate STT3401A) will return an error.
 		 */
 		if (drive->dsc_overlap) {
-			retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
+			ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
 			if (retval < 0) {
 				__idetape_kfree_stage(tape->merge_stage);
 				tape->merge_stage = NULL;
@@ -3834,12 +3846,14 @@
 		}
 #endif /* IDETAPE_DEBUG_BUGS */
 		actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
-		idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written);
+		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
+				ret = -EFAULT;
 		buf += actually_written;
 		tape->merge_stage_size += actually_written;
 		count -= actually_written;
 
 		if (tape->merge_stage_size == tape->stage_size) {
+			ssize_t retval;
 			tape->merge_stage_size = 0;
 			retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
 			if (retval <= 0)
@@ -3847,7 +3861,9 @@
 		}
 	}
 	while (count >= tape->stage_size) {
-		idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size);
+		ssize_t retval;
+		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size))
+			ret = -EFAULT;
 		buf += tape->stage_size;
 		count -= tape->stage_size;
 		retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
@@ -3857,10 +3873,11 @@
 	}
 	if (count) {
 		actually_written += count;
-		idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count);
+		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count))
+			ret = -EFAULT;
 		tape->merge_stage_size += count;
 	}
-	return (actually_written);
+	return (ret) ? ret : actually_written;
 }
 
 static int idetape_write_filemark (ide_drive_t *drive)
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 9233b81..a839b2a 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -196,8 +196,7 @@
 	if (stat & (ERR_STAT|DRQ_STAT))
 		return ide_error(drive, "set_geometry_intr", stat);
 
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
+	BUG_ON(HWGROUP(drive)->handler != NULL);
 	ide_set_handler(drive, &set_geometry_intr, WAIT_WORSTCASE, NULL);
 	return ide_started;
 }
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index 2fcfac6..c0864b1 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -220,6 +220,12 @@
 		return -EINVAL;
 
 /*
+ * Copy the timing from the table.
+ */
+
+	*t = *s;
+
+/*
  * If the drive is an EIDE drive, it can tell us it needs extended
  * PIO/MWDMA cycle timing.
  */
@@ -247,7 +253,7 @@
  * Convert the timing to bus clock counts.
  */
 
-	ide_timing_quantize(s, t, T, UT);
+	ide_timing_quantize(t, t, T, UT);
 
 /*
  * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 3fdab56..59fe358 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -726,6 +726,7 @@
 {
 	int i;
 
+	memset(hw, 0, sizeof(hw_regs_t));
 	for (i = 0; i < IDE_NR_PORTS; i++) {
 		if (offsets[i] == -1) {
 			switch(i) {
@@ -1225,7 +1226,7 @@
 	memset(&args, 0, sizeof(args));
 	rq.flags = REQ_PM_SUSPEND;
 	rq.special = &args;
-	rq.pm = &rqpm;
+	rq.end_io_data = &rqpm;
 	rqpm.pm_step = ide_pm_state_start_suspend;
 	rqpm.pm_state = state.event;
 
@@ -1244,7 +1245,7 @@
 	memset(&args, 0, sizeof(args));
 	rq.flags = REQ_PM_RESUME;
 	rq.special = &args;
-	rq.pm = &rqpm;
+	rq.end_io_data = &rqpm;
 	rqpm.pm_step = ide_pm_state_start_resume;
 	rqpm.pm_state = PM_EVENT_ON;
 
@@ -1366,8 +1367,7 @@
 
 			ide_abort(drive, "drive reset");
 
-			if(HWGROUP(drive)->handler)
-				BUG();
+			BUG_ON(HWGROUP(drive)->handler);
 				
 			/* Ensure nothing gets queued after we
 			   drop the lock. Reset will clear the busy */
diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
index 2a78b79..434a94f 100644
--- a/drivers/ide/legacy/q40ide.c
+++ b/drivers/ide/legacy/q40ide.c
@@ -80,6 +80,7 @@
 {
 	int i;
 
+	memset(hw, 0, sizeof(hw_regs_t));
 	for (i = 0; i < IDE_NR_PORTS; i++) {
 		/* BIG FAT WARNING: 
 		   assumption: only DATA port is ever used in 16 bit mode */
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index c743e68..ff0cdc1 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -22,7 +22,7 @@
 	u8 ultra_settings;
 };
 
-static struct chipset_bus_clock_list_entry aec6xxx_33_base [] = {
+static const struct chipset_bus_clock_list_entry aec6xxx_33_base [] = {
 	{	XFER_UDMA_6,	0x31,	0x07	},
 	{	XFER_UDMA_5,	0x31,	0x06	},
 	{	XFER_UDMA_4,	0x31,	0x05	},
@@ -42,7 +42,7 @@
 	{	0,		0x00,	0x00	}
 };
 
-static struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
+static const struct chipset_bus_clock_list_entry aec6xxx_34_base [] = {
 	{	XFER_UDMA_6,	0x41,	0x06	},
 	{	XFER_UDMA_5,	0x41,	0x05	},
 	{	XFER_UDMA_4,	0x41,	0x04	},
@@ -425,12 +425,12 @@
 	return d->init_setup(dev, d);
 }
 
-static struct pci_device_id aec62xx_pci_tbl[] = {
-	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
-	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
-	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
-	{ PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+static const struct pci_device_id aec62xx_pci_tbl[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF), 0 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860), 1 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R), 2 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865), 3 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP865R), 4 },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, aec62xx_pci_tbl);
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index b22ee54..85007cb 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -74,6 +74,8 @@
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_AMD_CS5536_IDE,			0x40, AMD_UDMA_100 },
 	{ 0 }
 };
@@ -488,7 +490,9 @@
 	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
 	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
 	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
-	/* 17 */ DECLARE_AMD_DEV("AMD5536"),
+	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
+	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
+	/* 19 */ DECLARE_AMD_DEV("AMD5536"),
 };
 
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -525,7 +529,9 @@
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
-	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 3d9c7af..92b7b15 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -190,14 +190,6 @@
 #endif	/* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */
 
 /*
- * Registers and masks for easy access by drive index:
- */
-#if 0
-static u8 prefetch_regs[4]  = {CNTRL, CNTRL, ARTTIM23, ARTTIM23};
-static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3};
-#endif
-
-/*
  * This routine writes the prepared setup/active/recovery counts
  * for a drive into the cmd646 chipset registers to active them.
  */
@@ -606,13 +598,6 @@
 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
 	class_rev &= 0xff;
 
-#ifdef __i386__
-	if (dev->resource[PCI_ROM_RESOURCE].start) {
-		pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
-		printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
-	}
-#endif
-
 	switch(dev->device) {
 		case PCI_DEVICE_ID_CMD_643:
 			break;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index acd6317..2c9e938 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -338,6 +338,8 @@
 	hwif->ultra_mask = 0x7f;
 	hwif->mwdma_mask = 0x07;
 
+	hwif->err_stops_fifo = 1;
+
 	hwif->ide_dma_check = &pdcnew_config_drive_xfer_rate;
 	hwif->ide_dma_lostirq = &pdcnew_ide_dma_lostirq;
 	hwif->ide_dma_timeout = &pdcnew_ide_dma_timeout;
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 7ce5bf7..26bc688 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -101,31 +101,6 @@
 #define	MC1		0x02	/* DMA"C" timing */
 #define	MC0		0x01	/* DMA"C" timing */
 
-#if 0
-	unsigned long bibma  = pci_resource_start(dev, 4);
-	u8 hi = 0, lo = 0;
-
-	u8 sc1c	= inb_p((u16)bibma + 0x1c); 
-	u8 sc1e	= inb_p((u16)bibma + 0x1e);
-	u8 sc1f	= inb_p((u16)bibma + 0x1f);
-
-	p += sprintf(p, "Host Mode                            : %s\n",
-		(sc1f & 0x08) ? "Tri-Stated" : "Normal");
-	p += sprintf(p, "Bus Clocking                         : %s\n",
-		((sc1f & 0xC0) == 0xC0) ? "100 External" :
-		((sc1f & 0x80) == 0x80) ? "66 External" :
-		((sc1f & 0x40) == 0x40) ? "33 External" : "33 PCI Internal");
-	p += sprintf(p, "IO pad select                        : %s mA\n",
-		((sc1c & 0x03) == 0x03) ? "10" :
-		((sc1c & 0x02) == 0x02) ? "8" :
-		((sc1c & 0x01) == 0x01) ? "6" :
-		((sc1c & 0x00) == 0x00) ? "4" : "??");
-	hi = sc1e >> 4;
-	lo = sc1e & 0xf;
-	p += sprintf(p, "Status Polling Period                : %d\n", hi);
-	p += sprintf(p, "Interrupt Check Status Polling Delay : %d\n", lo);
-#endif
-
 static u8 pdc202xx_ratemask (ide_drive_t *drive)
 {
 	u8 mode;
@@ -370,7 +345,6 @@
 	if (!(speed)) {
 		/* restore original pci-config space */
 		pci_write_config_dword(dev, drive_pci, drive_conf);
-		hwif->tuneproc(drive, 5);
 		return 0;
 	}
 
@@ -415,8 +389,6 @@
 	if (drive->addressing == 1) {
 		struct request *rq	= HWGROUP(drive)->rq;
 		ide_hwif_t *hwif	= HWIF(drive);
-//		struct pci_dev *dev	= hwif->pci_dev;
-//		unsgned long high_16	= pci_resource_start(dev, 4);
 		unsigned long high_16   = hwif->dma_master;
 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
 		u32 word_count	= 0;
@@ -436,7 +408,6 @@
 {
 	if (drive->addressing == 1) {
 		ide_hwif_t *hwif	= HWIF(drive);
-//		unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
 		unsigned long high_16	= hwif->dma_master;
 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
 		u8 clock		= 0;
@@ -453,8 +424,6 @@
 static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
-//	struct pci_dev *dev	= hwif->pci_dev;
-//	unsigned long high_16	= pci_resource_start(dev, 4);
 	unsigned long high_16	= hwif->dma_master;
 	u8 dma_stat		= hwif->INB(hwif->dma_status);
 	u8 sc1d			= hwif->INB((high_16 + 0x001d));
@@ -492,12 +461,7 @@
 
 static void pdc202xx_reset_host (ide_hwif_t *hwif)
 {
-#ifdef CONFIG_BLK_DEV_IDEDMA
-//	unsigned long high_16	= hwif->dma_base - (8*(hwif->channel));
 	unsigned long high_16	= hwif->dma_master;
-#else /* !CONFIG_BLK_DEV_IDEDMA */
-	unsigned long high_16	= pci_resource_start(hwif->pci_dev, 4);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	u8 udma_speed_flag	= hwif->INB(high_16|0x001f);
 
 	hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f));
@@ -516,67 +480,13 @@
 	
 	pdc202xx_reset_host(hwif);
 	pdc202xx_reset_host(mate);
-#if 0
-	/*
-	 * FIXME: Have to kick all the drives again :-/
-	 * What a pain in the ACE!
-	 */
-	if (hwif->present) {
-		u16 hunit = 0;
-		for (hunit = 0; hunit < MAX_DRIVES; ++hunit) {
-			ide_drive_t *hdrive = &hwif->drives[hunit];
-			if (hdrive->present) {
-				if (hwif->ide_dma_check)
-					hwif->ide_dma_check(hdrive);
-				else
-					hwif->tuneproc(hdrive, 5);
-			}
-		}
-	}
-	if (mate->present) {
-		u16 munit = 0;
-		for (munit = 0; munit < MAX_DRIVES; ++munit) {
-			ide_drive_t *mdrive = &mate->drives[munit];
-			if (mdrive->present) {
-				if (mate->ide_dma_check) 
-					mate->ide_dma_check(mdrive);
-				else
-					mate->tuneproc(mdrive, 5);
-			}
-		}
-	}
-#else
 	hwif->tuneproc(drive, 5);
-#endif
 }
 
-/*
- * Since SUN Cobalt is attempting to do this operation, I should disclose
- * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
- * HOTSWAP ATA Infrastructure.
- */
-static int pdc202xx_tristate (ide_drive_t * drive, int state)
+static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
+							const char *name)
 {
-	ide_hwif_t *hwif	= HWIF(drive);
-//	unsigned long high_16	= hwif->dma_base - (8*(hwif->channel));
-	unsigned long high_16	= hwif->dma_master;
-	u8 sc1f			= hwif->INB(high_16|0x001f);
-
-	if (!hwif)
-		return -EINVAL;
-
-//	hwif->bus_state = state;
-
-	if (state) {
-		hwif->OUTB(sc1f | 0x08, (high_16|0x001f));
-	} else {
-		hwif->OUTB(sc1f & ~0x08, (high_16|0x001f));
-	}
-	return 0;
-}
-
-static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, const char *name)
-{
+	/* This doesn't appear needed */
 	if (dev->resource[PCI_ROM_RESOURCE].start) {
 		pci_write_config_dword(dev, PCI_ROM_ADDRESS,
 			dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
@@ -584,30 +494,6 @@
 			name, dev->resource[PCI_ROM_RESOURCE].start);
 	}
 
-	/*
-	 * software reset -  this is required because the bios
-	 * will set UDMA timing on if the hdd supports it. The
-	 * user may want to turn udma off. A bug in the pdc20262
-	 * is that it cannot handle a downgrade in timing from
-	 * UDMA to DMA. Disk accesses after issuing a set
-	 * feature command will result in errors. A software
-	 * reset leaves the timing registers intact,
-	 * but resets the drives.
-	 */
-#if 0
-	if ((dev->device == PCI_DEVICE_ID_PROMISE_20267) ||
-	    (dev->device == PCI_DEVICE_ID_PROMISE_20265) ||
-	    (dev->device == PCI_DEVICE_ID_PROMISE_20263) ||
-	    (dev->device == PCI_DEVICE_ID_PROMISE_20262)) {
-		unsigned long high_16	= pci_resource_start(dev, 4);
-		byte udma_speed_flag	= inb(high_16 + 0x001f);
-		outb(udma_speed_flag | 0x10, high_16 + 0x001f);
-		mdelay(100);
-		outb(udma_speed_flag & ~0x10, high_16 + 0x001f);
-		mdelay(2000);	/* 2 seconds ?! */
-	}
-
-#endif
 	return dev->irq;
 }
 
@@ -624,10 +510,8 @@
 	hwif->tuneproc  = &config_chipset_for_pio;
 	hwif->quirkproc = &pdc202xx_quirkproc;
 
-	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
-		hwif->busproc   = &pdc202xx_tristate;
+	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
 		hwif->resetproc = &pdc202xx_reset;
-	}
 
 	hwif->speedproc = &pdc202xx_tune_chipset;
 
@@ -637,6 +521,8 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
+	hwif->err_stops_fifo = 1;
+
 	hwif->ide_dma_check = &pdc202xx_config_drive_xfer_rate;
 	hwif->ide_dma_lostirq = &pdc202xx_ide_dma_lostirq;
 	hwif->ide_dma_timeout = &pdc202xx_ide_dma_timeout;
@@ -725,19 +611,6 @@
 				"mirror fixed.\n", d->name);
 		}
 	}
-
-#if 0
-        if (dev->device == PCI_DEVICE_ID_PROMISE_20262)
-        if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
-             (tmp & e->mask) != e->val))
-
-        if (d->enablebits[0].reg != d->enablebits[1].reg) {
-                d->enablebits[0].reg    = d->enablebits[1].reg;
-                d->enablebits[0].mask   = d->enablebits[1].mask;
-                d->enablebits[0].val    = d->enablebits[1].val;
-        }
-#endif
-
 	return ide_setup_pci_device(dev, d);
 }
 
@@ -752,22 +625,6 @@
 			"attached to I2O RAID controller.\n");
 		return -ENODEV;
 	}
-
-#if 0
-        {
-                u8 pri = 0, sec = 0;
-
-        if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
-             (tmp & e->mask) != e->val))
-
-        if (d->enablebits[0].reg != d->enablebits[1].reg) {
-                d->enablebits[0].reg    = d->enablebits[1].reg;
-                d->enablebits[0].mask   = d->enablebits[1].mask;
-                d->enablebits[0].val    = d->enablebits[1].val;
-        }
-        }
-#endif
-
 	return ide_setup_pci_device(dev, d);
 }
 
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index e9b83e1..7fac6f5 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -222,6 +222,8 @@
 	unsigned long flags;
 	u16 master_data;
 	u8 slave_data;
+	static DEFINE_SPINLOCK(tune_lock);
+
 				 /* ISP  RTC */
 	u8 timings[][2]	= { { 0, 0 },
 			    { 0, 0 },
@@ -230,7 +232,13 @@
 			    { 2, 3 }, };
 
 	pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
-	spin_lock_irqsave(&ide_lock, flags);
+
+	/*
+	 * Master vs slave is synchronized above us but the slave register is
+	 * shared by the two hwifs so the corner case of two slave timeouts in
+	 * parallel must be locked.
+	 */
+	spin_lock_irqsave(&tune_lock, flags);
 	pci_read_config_word(dev, master_port, &master_data);
 	if (is_slave) {
 		master_data = master_data | 0x4000;
@@ -250,7 +258,7 @@
 	pci_write_config_word(dev, master_port, master_data);
 	if (is_slave)
 		pci_write_config_byte(dev, slave_port, slave_data);
-	spin_unlock_irqrestore(&ide_lock, flags);
+	spin_unlock_irqrestore(&tune_lock, flags);
 }
 
 /**
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 24e21b2..778b82a 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -395,7 +395,6 @@
 {
 	ide_hwif_t	*hwif = NULL;
 
-printk("SC1200: resume\n");
 	pci_set_power_state(dev, PCI_D0);	// bring chip back from sleep state
 	dev->current_state = PM_EVENT_ON;
 	pci_enable_device(dev);
@@ -405,7 +404,6 @@
 	while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
 		unsigned int		basereg, r, d, format;
 		sc1200_saved_state_t	*ss = (sc1200_saved_state_t *)hwif->config_data;
-printk("%s: SC1200: resume\n", hwif->name);
 
 		//
 		// Restore timing registers:  this may be unnecessary if BIOS also does it
@@ -493,7 +491,7 @@
 }
 
 static struct pci_device_id sc1200_pci_tbl[] = {
-	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_IDE), 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, sc1200_pci_tbl);
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 0d3073f..5100b82 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -123,11 +123,11 @@
 }
 static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
 {
-	u8 udma_modes[]		= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
-	u8 dma_modes[]		= { 0x77, 0x21, 0x20 };
-	u8 pio_modes[]		= { 0x5d, 0x47, 0x34, 0x22, 0x20 };
-	u8 drive_pci[]		= { 0x41, 0x40, 0x43, 0x42 };
-	u8 drive_pci2[]		= { 0x45, 0x44, 0x47, 0x46 };
+	static const u8 udma_modes[]		= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
+	static const u8 dma_modes[]		= { 0x77, 0x21, 0x20 };
+	static const u8 pio_modes[]		= { 0x5d, 0x47, 0x34, 0x22, 0x20 };
+	static const u8 drive_pci[]		= { 0x41, 0x40, 0x43, 0x42 };
+	static const u8 drive_pci2[]		= { 0x45, 0x44, 0x47, 0x46 };
 
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -392,16 +392,6 @@
 			}
 			outb_p(0x06, 0x0c00);
 			dev->irq = inb_p(0x0c01);
-#if 0
-			printk("%s: device class (0x%04x)\n",
-				name, dev->class);
-			if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) {
-				dev->class &= ~0x000F0F00;
-		//		dev->class |= ~0x00000400;
-				dev->class |= ~0x00010100;
-				/**/
-			}
-#endif
 		} else {
 			struct pci_dev * findev = NULL;
 			u8 reg41 = 0;
@@ -452,7 +442,7 @@
 		pci_write_config_byte(dev, 0x5A, btr);
 	}
 
-	return (dev->irq) ? dev->irq : 0;
+	return dev->irq;
 }
 
 static unsigned int __devinit ata66_svwks_svwks (ide_hwif_t *hwif)
@@ -500,11 +490,6 @@
 {
 	struct pci_dev *dev = hwif->pci_dev;
 
-	/* Per Specified Design by OEM, and ASIC Architect */
-	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
-	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
-		return 1;
-
 	/* Server Works */
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS)
 		return ata66_svwks_svwks (hwif);
@@ -517,10 +502,14 @@
 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN)
 		return ata66_svwks_cobalt (hwif);
 
+	/* Per Specified Design by OEM, and ASIC Architect */
+	if ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
+	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2))
+		return 1;
+
 	return 0;
 }
 
-#undef CAN_SW_DMA
 static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
 {
 	u8 dma_stat = 0;
@@ -537,9 +526,6 @@
 		hwif->ultra_mask = 0x3f;
 
 	hwif->mwdma_mask = 0x07;
-#ifdef CAN_SW_DMA
-	hwif->swdma_mask = 0x07;
-#endif /* CAN_SW_DMA */
 
 	hwif->autodma = 0;
 
@@ -562,8 +548,6 @@
 	hwif->drives[1].autodma = (dma_stat & 0x40);
 	hwif->drives[0].autotune = (!(dma_stat & 0x20));
 	hwif->drives[1].autotune = (!(dma_stat & 0x40));
-//	hwif->drives[0].autodma = hwif->autodma;
-//	hwif->drives[1].autodma = hwif->autodma;
 }
 
 /*
@@ -593,11 +577,6 @@
 		if (dev->resource[0].start == 0x01f1)
 			d->bootable = ON_BOARD;
 	}
-#if 0
-	if ((IDE_PCI_DEVID_EQ(d->devid, DEVID_CSB6) &&
-             (!(PCI_FUNC(dev->devfn) & 1)))
-		d->autodma = AUTODMA;
-#endif
 
 	d->channels = ((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE ||
 			dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2) &&
@@ -671,11 +650,11 @@
 }
 
 static struct pci_device_id svwks_pci_tbl[] = {
-	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
-	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3},
-	{ PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE), 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE), 1},
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE), 2},
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2), 3},
+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000IDE), 4},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, svwks_pci_tbl);
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 27c9eb9..e125032 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -723,6 +723,12 @@
 int
 ioc4_ide_attach_one(struct ioc4_driver_data *idd)
 {
+	/* PCI-RT does not bring out IDE connection.
+	 * Do not attach to this particular IOC4.
+	 */
+	if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
+		return 0;
+
 	return pci_init_sgiioc4(idd->idd_pdev,
 				&sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
 }
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index f1ca154..72dade1 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -38,9 +38,6 @@
 
 #include <asm/io.h>
 
-#undef SIIMAGE_VIRTUAL_DMAPIO
-#undef SIIMAGE_LARGE_DMA
-
 /**
  *	pdev_is_sata		-	check if device is SATA
  *	@pdev:	PCI device to check
@@ -461,36 +458,6 @@
 	return 0;
 }
 
-#if 0
-/**
- *	siimage_mmio_ide_dma_count	-	DMA bytes done
- *	@drive
- *
- *	If we are doing VDMA the CMD680 requires a little bit
- *	of more careful handling and we have to read the counts
- *	off ourselves. For non VDMA life is normal.
- */
- 
-static int siimage_mmio_ide_dma_count (ide_drive_t *drive)
-{
-#ifdef SIIMAGE_VIRTUAL_DMAPIO
-	struct request *rq	= HWGROUP(drive)->rq;
-	ide_hwif_t *hwif	= HWIF(drive);
-	u32 count		= (rq->nr_sectors * SECTOR_SIZE);
-	u32 rcount		= 0;
-	unsigned long addr	= siimage_selreg(hwif, 0x1C);
-
-	hwif->OUTL(count, addr);
-	rcount = hwif->INL(addr);
-
-	printk("\n%s: count = %d, rcount = %d, nr_sectors = %lu\n",
-		drive->name, count, rcount, rq->nr_sectors);
-
-#endif /* SIIMAGE_VIRTUAL_DMAPIO */
-	return __ide_dma_count(drive);
-}
-#endif
-
 /**
  *	siimage_mmio_ide_dma_test_irq	-	check we caused an IRQ
  *	@drive: drive we are testing
@@ -512,12 +479,10 @@
 			u32 sata_error = hwif->INL(SATA_ERROR_REG);
 			hwif->OUTL(sata_error, SATA_ERROR_REG);
 			watchdog = (sata_error & 0x00680000) ? 1 : 0;
-#if 1
 			printk(KERN_WARNING "%s: sata_error = 0x%08x, "
 				"watchdog = %d, %s\n",
 				drive->name, sata_error, watchdog,
 				__FUNCTION__);
-#endif
 
 		} else {
 			watchdog = (ext_stat & 0x8000) ? 1 : 0;
@@ -863,7 +828,7 @@
  *	time.
  *
  *	The hardware supports buffered taskfiles and also some rather nice
- *	extended PRD tables. Unfortunately right now we don't.
+ *	extended PRD tables. For better SI3112 support use the libata driver
  */
 
 static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
@@ -900,9 +865,6 @@
 	 *	so we can't currently use it sanely since we want to
 	 *	use LBA48 mode.
 	 */	
-//	base += 0x10;
-//	hwif->no_lba48 = 1;
-
 	hw.io_ports[IDE_DATA_OFFSET]	= base;
 	hw.io_ports[IDE_ERROR_OFFSET]	= base + 1;
 	hw.io_ports[IDE_NSECTOR_OFFSET]	= base + 2;
@@ -936,15 +898,8 @@
 
        	base = (unsigned long) addr;
 
-#ifdef SIIMAGE_LARGE_DMA
-/* Watch the brackets - even Ken and Dennis get some language design wrong */
-	hwif->dma_base			= base + (ch ? 0x18 : 0x10);
-	hwif->dma_base2			= base + (ch ? 0x08 : 0x00);
-	hwif->dma_prdtable		= hwif->dma_base2 + 4;
-#else /* ! SIIMAGE_LARGE_DMA */
 	hwif->dma_base			= base + (ch ? 0x08 : 0x00);
 	hwif->dma_base2			= base + (ch ? 0x18 : 0x10);
-#endif /* SIIMAGE_LARGE_DMA */
 	hwif->mmio			= 2;
 }
 
@@ -1052,9 +1007,16 @@
 	hwif->reset_poll = &siimage_reset_poll;
 	hwif->pre_reset = &siimage_pre_reset;
 
-	if(is_sata(hwif))
+	if(is_sata(hwif)) {
+		static int first = 1;
+
 		hwif->busproc   = &siimage_busproc;
 
+		if (first) {
+			printk(KERN_INFO "siimage: For full SATA support you should use the libata sata_sil module.\n");
+			first = 0;
+		}
+	}
 	if (!hwif->dma_base) {
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
@@ -1121,10 +1083,10 @@
 }
 
 static struct pci_device_id siimage_pci_tbl[] = {
-	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680), 0},
 #ifdef CONFIG_BLK_DEV_IDE_SATA
-	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-	{ PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+	{ PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112), 1},
+	{ PCI_DEVICE(PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA), 2},
 #endif
 	{ 0, },
 };
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index 8a5c7b2..900301e 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -447,7 +447,6 @@
 		printk("    %s: Winbond 553 bridge revision %d, BM-DMA disabled\n",
 		       hwif->name, rev);
 	} else {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		dma_state |= 0x60;
 
 		hwif->atapi_dma = 1;
@@ -468,7 +467,6 @@
 
 		if (hwif->mate)
 			hwif->serialized = hwif->mate->serialized = 1;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 	}
 	hwif->OUTB(dma_state, hwif->dma_base + 2);
 }
@@ -489,7 +487,7 @@
 }
 
 static struct pci_device_id sl82c105_pci_tbl[] = {
-	{ PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105), 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, sl82c105_pci_tbl);
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index 5112c72..0968f6b 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -72,7 +72,8 @@
 	u16 master_data;
 	u8 slave_data;
 				 /* ISP  RTC */
-	u8 timings[][2]	= { { 0, 0 },
+	static const u8 timings[][2]= {
+				    { 0, 0 },
 				    { 0, 0 },
 				    { 1, 0 },
 				    { 2, 1 },
@@ -119,7 +120,6 @@
 	pci_read_config_word(dev, 0x4a, &reg4a);
 
 	switch(speed) {
-#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_4:	u_speed = 4 << (drive->dn * 4); break;
 		case XFER_UDMA_3:	u_speed = 3 << (drive->dn * 4); break;
 		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
@@ -128,7 +128,6 @@
 		case XFER_MW_DMA_2:
 		case XFER_MW_DMA_1:
 		case XFER_SW_DMA_2:	break;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
 		case XFER_PIO_3:
 		case XFER_PIO_2:
@@ -156,7 +155,6 @@
 	return (ide_config_drive_speed(drive, speed));
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
 static int slc90e66_config_drive_for_dma (ide_drive_t *drive)
 {
 	u8 speed = ide_dma_speed(drive, slc90e66_ratemask(drive));
@@ -194,7 +192,6 @@
 	/* IORDY not supported */
 	return 0;
 }
-#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
 {
@@ -222,7 +219,6 @@
 	hwif->mwdma_mask = 0x07;
 	hwif->swdma_mask = 0x07;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA 
 	if (!(hwif->udma_four))
 		/* bit[0(1)]: 0:80, 1:40 */
 		hwif->udma_four = (reg47 & mask) ? 0 : 1;
@@ -232,7 +228,6 @@
 		hwif->autodma = 1;
 	hwif->drives[0].autodma = hwif->autodma;
 	hwif->drives[1].autodma = hwif->autodma;
-#endif /* !CONFIG_BLK_DEV_IDEDMA */
 }
 
 static ide_pci_device_t slc90e66_chipset __devinitdata = {
@@ -250,7 +245,7 @@
 }
 
 static struct pci_device_id slc90e66_pci_tbl[] = {
-	{ PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_1), 0},
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, slc90e66_pci_tbl);
diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
index c26c8ca..fe80295 100644
--- a/drivers/ide/pci/trm290.c
+++ b/drivers/ide/pci/trm290.c
@@ -183,8 +183,7 @@
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 
-	if (HWGROUP(drive)->handler != NULL)	/* paranoia check */
-		BUG();
+	BUG_ON(HWGROUP(drive)->handler != NULL);	/* paranoia check */
 	ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
 	/* issue cmd to drive */
 	hwif->OUTB(command, IDE_COMMAND_REG);
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 462ed30..c11e3b2 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -694,13 +694,8 @@
 				goto out;
 		}
 		if (noisy)
-#ifdef __sparc__
-			printk(KERN_INFO "%s: 100%% native mode on irq %s\n",
-			       d->name, __irq_itoa(pciirq));
-#else
 			printk(KERN_INFO "%s: 100%% native mode on irq %d\n",
 				d->name, pciirq);
-#endif
 	}
 
 	/* FIXME: silent failure can happen */
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 39142e2..1867375 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -128,8 +128,17 @@
 	  1394 bus.  SBP-2 devices include harddrives and DVD devices.
 
 config IEEE1394_SBP2_PHYS_DMA
-	bool "Enable Phys DMA support for SBP2 (Debug)"
-	depends on IEEE1394 && IEEE1394_SBP2
+	bool "Enable replacement for physical DMA in SBP2"
+	depends on IEEE1394 && IEEE1394_SBP2 && EXPERIMENTAL && (X86_32 || PPC_32)
+	help
+	  This builds sbp2 for use with non-OHCI host adapters which do not
+	  support physical DMA or for when ohci1394 is run with phys_dma=0.
+	  Physical DMA is data movement without assistence of the drivers'
+	  interrupt handlers.  This option includes the interrupt handlers
+	  that are required in absence of this hardware feature.
+
+	  This option is buggy and currently broken on some architectures.
+	  If unsure, say N.
 
 config IEEE1394_ETH1394
 	tristate "Ethernet over 1394"
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
index 157735442..586f71e 100644
--- a/drivers/ieee1394/csr1212.c
+++ b/drivers/ieee1394/csr1212.c
@@ -779,7 +779,7 @@
 	romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
 
 	csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);
-	if (csr_addr == ~0ULL) {
+	if (csr_addr == CSR1212_INVALID_ADDR_SPACE) {
 		return CSR1212_ENOMEM;
 	}
 	if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
index cecd587..17ddd72 100644
--- a/drivers/ieee1394/csr1212.h
+++ b/drivers/ieee1394/csr1212.h
@@ -192,6 +192,7 @@
 
 #define  CSR1212_EXTENDED_ROM_SIZE		(0x10000 * sizeof(u_int32_t))
 
+#define  CSR1212_INVALID_ADDR_SPACE		-1
 
 /* Config ROM image structures */
 struct csr1212_bus_info_block_img {
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
index 9fb2769d..ca5167d 100644
--- a/drivers/ieee1394/dma.c
+++ b/drivers/ieee1394/dma.c
@@ -145,12 +145,12 @@
 /* find the scatterlist index and remaining offset corresponding to a
    given offset from the beginning of the buffer */
 static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
-				  unsigned long *rem)
+				  unsigned int start, unsigned long *rem)
 {
 	int i;
 	unsigned long off = offset;
 
-	for (i = 0; i < dma->n_dma_pages; i++) {
+	for (i = start; i < dma->n_dma_pages; i++) {
 		if (off < sg_dma_len(&dma->sglist[i])) {
 			*rem = off;
 			break;
@@ -170,7 +170,7 @@
 	unsigned long rem = 0;
 
 	struct scatterlist *sg =
-	    &dma->sglist[dma_region_find(dma, offset, &rem)];
+	    &dma->sglist[dma_region_find(dma, offset, 0, &rem)];
 	return sg_dma_address(sg) + rem;
 }
 
@@ -178,13 +178,13 @@
 			     unsigned long len)
 {
 	int first, last;
-	unsigned long rem;
+	unsigned long rem = 0;
 
 	if (!len)
 		len = 1;
 
-	first = dma_region_find(dma, offset, &rem);
-	last = dma_region_find(dma, offset + len - 1, &rem);
+	first = dma_region_find(dma, offset, 0, &rem);
+	last = dma_region_find(dma, rem + len - 1, first, &rem);
 
 	pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1,
 				dma->direction);
@@ -194,13 +194,13 @@
 				unsigned long len)
 {
 	int first, last;
-	unsigned long rem;
+	unsigned long rem = 0;
 
 	if (!len)
 		len = 1;
 
-	first = dma_region_find(dma, offset, &rem);
-	last = dma_region_find(dma, offset + len - 1, &rem);
+	first = dma_region_find(dma, offset, 0, &rem);
+	last = dma_region_find(dma, rem + len - 1, first, &rem);
 
 	pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first],
 				   last - first + 1, dma->direction);
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
index 30fa0d4..2d5b57b 100644
--- a/drivers/ieee1394/eth1394.c
+++ b/drivers/ieee1394/eth1394.c
@@ -367,7 +367,7 @@
 	spin_lock_init(&node_info->pdg.lock);
 	INIT_LIST_HEAD(&node_info->pdg.list);
 	node_info->pdg.sz = 0;
-	node_info->fifo = ETHER1394_INVALID_ADDR;
+	node_info->fifo = CSR1212_INVALID_ADDR_SPACE;
 
 	ud->device.driver_data = node_info;
 	new_node->ud = ud;
@@ -502,10 +502,8 @@
 
 	/* Determine speed limit */
 	for (i = 0; i < host->node_count; i++)
-		if (max_speed > host->speed_map[NODEID_TO_NODE(host->node_id) *
-						64 + i])
-			max_speed = host->speed_map[NODEID_TO_NODE(host->node_id) *
-						    64 + i];
+		if (max_speed > host->speed[i])
+			max_speed = host->speed[i];
 	priv->bc_sspd = max_speed;
 
 	/* We'll use our maxpayload as the default mtu */
@@ -568,13 +566,11 @@
 	if (!(host->config_roms & HPSB_CONFIG_ROM_ENTRY_IP1394))
 		return;
 
-	fifo_addr = hpsb_allocate_and_register_addrspace(&eth1394_highlevel,
-							 host,
-							 &addr_ops,
-							 ETHER1394_REGION_ADDR_LEN,
-							 ETHER1394_REGION_ADDR_LEN,
-							 -1, -1);
-	if (fifo_addr == ~0ULL)
+	fifo_addr = hpsb_allocate_and_register_addrspace(
+			&eth1394_highlevel, host, &addr_ops,
+			ETHER1394_REGION_ADDR_LEN, ETHER1394_REGION_ADDR_LEN,
+			CSR1212_INVALID_ADDR_SPACE, CSR1212_INVALID_ADDR_SPACE);
+	if (fifo_addr == CSR1212_INVALID_ADDR_SPACE)
 		goto out;
 
 	/* We should really have our own alloc_hpsbdev() function in
@@ -774,7 +770,7 @@
 	default:
 		ETH1394_PRINT(KERN_DEBUG, dev->name,
 			      "unable to resolve type %04x addresses.\n",
-			      eth->h_proto);
+			      ntohs(eth->h_proto));
 		break;
 	}
 
@@ -796,9 +792,8 @@
 						      (16 - ETH1394_HLEN));
 	struct net_device *dev = neigh->dev;
 
-	if (type == __constant_htons(ETH_P_802_3)) {
+	if (type == htons(ETH_P_802_3))
 		return -1;
-	}
 
 	eth->h_proto = type;
 	memcpy(eth->h_dest, neigh->ha, dev->addr_len);
@@ -887,7 +882,7 @@
 	/* If this is an ARP packet, convert it. First, we want to make
 	 * use of some of the fields, since they tell us a little bit
 	 * about the sending machine.  */
-	if (ether_type == __constant_htons (ETH_P_ARP)) {
+	if (ether_type == htons(ETH_P_ARP)) {
 		struct eth1394_arp *arp1394 = (struct eth1394_arp*)skb->data;
 		struct arphdr *arp = (struct arphdr *)skb->data;
 		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
@@ -935,7 +930,7 @@
 		*(u32*)arp_ptr = arp1394->sip;	/* move sender IP addr */
 		arp_ptr += arp->ar_pln;		/* skip over sender IP addr */
 
-		if (arp->ar_op == 1)
+		if (arp->ar_op == htons(ARPOP_REQUEST))
 			/* just set ARP req target unique ID to 0 */
 			*((u64*)arp_ptr) = 0;
 		else
@@ -943,8 +938,8 @@
 	}
 
 	/* Now add the ethernet header. */
-	if (dev->hard_header (skb, dev, __constant_ntohs (ether_type),
-			      &dest_hw, NULL, skb->len) >= 0)
+	if (dev->hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL,
+			     skb->len) >= 0)
 		ret = ether1394_type_trans(skb, dev);
 
 	return ret;
@@ -1079,8 +1074,7 @@
 
 	/* Move list entry to beginnig of list so that oldest partial
 	 * datagrams percolate to the end of the list */
-	list_del(lh);
-	list_add(lh, pdgl);
+	list_move(lh, pdgl);
 
 	return 0;
 }
@@ -1395,7 +1389,7 @@
 /* We need to encapsulate the standard header with our own. We use the
  * ethernet header's proto for our own. */
 static inline unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
-						      int proto,
+						      __be16 proto,
 						      union eth1394_hdr *hdr,
 						      u16 dg_size, u16 dgl)
 {
@@ -1514,8 +1508,8 @@
 	p->data = ((quadlet_t*)skb->data) - 2;
 	p->data[0] = cpu_to_be32((priv->host->node_id << 16) |
 				 ETHER1394_GASP_SPECIFIER_ID_HI);
-	p->data[1] = __constant_cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) |
-					    ETHER1394_GASP_VERSION);
+	p->data[1] = cpu_to_be32((ETHER1394_GASP_SPECIFIER_ID_LO << 24) |
+				 ETHER1394_GASP_VERSION);
 
 	/* Setting the node id to ALL_NODES (not LOCAL_BUS | ALL_NODES)
 	 * prevents hpsb_send_packet() from setting the speed to an arbitrary
@@ -1626,7 +1620,7 @@
 	gfp_t kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
 	struct eth1394hdr *eth;
 	struct eth1394_priv *priv = netdev_priv(dev);
-	int proto;
+	__be16 proto;
 	unsigned long flags;
 	nodeid_t dest_node;
 	eth1394_tx_type tx_type;
@@ -1670,9 +1664,9 @@
 	/* Set the transmission type for the packet.  ARP packets and IP
 	 * broadcast packets are sent via GASP. */
 	if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
-	    proto == __constant_htons(ETH_P_ARP) ||
-	    (proto == __constant_htons(ETH_P_IP) &&
-	     IN_MULTICAST(__constant_ntohl(skb->nh.iph->daddr)))) {
+	    proto == htons(ETH_P_ARP) ||
+	    (proto == htons(ETH_P_IP) &&
+	     IN_MULTICAST(ntohl(skb->nh.iph->daddr)))) {
 		tx_type = ETH1394_GASP;
 		dest_node = LOCAL_BUS | ALL_NODES;
 		max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD;
@@ -1688,7 +1682,7 @@
 			goto fail;
 		}
 		node_info = (struct eth1394_node_info*)node->ud->device.driver_data;
-		if (node_info->fifo == ETHER1394_INVALID_ADDR) {
+		if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE) {
 			ret = -EAGAIN;
 			goto fail;
 		}
@@ -1704,7 +1698,7 @@
 	}
 
 	/* If this is an ARP packet, convert it */
-	if (proto == __constant_htons (ETH_P_ARP))
+	if (proto == htons(ETH_P_ARP))
 		ether1394_arp_to_1394arp (skb, dev);
 
 	ptask->hdr.words.word1 = 0;
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
index a77213c..c45cbff 100644
--- a/drivers/ieee1394/eth1394.h
+++ b/drivers/ieee1394/eth1394.h
@@ -32,8 +32,6 @@
  * S3200 (per Table 16-3 of IEEE 1394b-2002). */
 #define ETHER1394_REGION_ADDR_LEN	4096
 
-#define ETHER1394_INVALID_ADDR		~0ULL
-
 /* GASP identifier numbers for IPv4 over IEEE 1394 */
 #define ETHER1394_GASP_SPECIFIER_ID	0x00005E
 #define ETHER1394_GASP_SPECIFIER_ID_HI	((ETHER1394_GASP_SPECIFIER_ID >> 8) & 0xffff)
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
index 491e603..25b2260 100644
--- a/drivers/ieee1394/highlevel.c
+++ b/drivers/ieee1394/highlevel.c
@@ -53,7 +53,7 @@
 
 
 static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
-					      struct hpsb_host *host)
+					    struct hpsb_host *host)
 {
 	struct hl_host_info *hi = NULL;
 
@@ -68,24 +68,18 @@
 		}
 	}
 	read_unlock(&hl->host_info_lock);
-
 	return NULL;
 }
 
-
 /* Returns a per host/driver data structure that was previously stored by
  * hpsb_create_hostinfo. */
 void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
 {
 	struct hl_host_info *hi = hl_get_hostinfo(hl, host);
 
-	if (hi)
-		return hi->data;
-
-	return NULL;
+	return hi ? hi->data : NULL;
 }
 
-
 /* If size is zero, then the return here is only valid for error checking */
 void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
 			   size_t data_size)
@@ -96,8 +90,8 @@
 
 	hi = hl_get_hostinfo(hl, host);
 	if (hi) {
-		HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already exists",
-			 hl->name);
+		HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already"
+			 " exists", hl->name);
 		return NULL;
 	}
 
@@ -120,7 +114,6 @@
 	return data;
 }
 
-
 int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
 		      void *data)
 {
@@ -132,16 +125,14 @@
 			hi->data = data;
 			return 0;
 		} else
-			HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo already has data",
-				 hl->name);
+			HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo "
+				 "already has data", hl->name);
 	} else
 		HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists",
 			 hl->name);
-
 	return -EINVAL;
 }
 
-
 void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
 {
 	struct hl_host_info *hi;
@@ -154,23 +145,20 @@
 		write_unlock_irqrestore(&hl->host_info_lock, flags);
 		kfree(hi);
 	}
-
 	return;
 }
 
-
-void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key)
+void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
+			   unsigned long key)
 {
 	struct hl_host_info *hi;
 
 	hi = hl_get_hostinfo(hl, host);
 	if (hi)
 		hi->key = key;
-
 	return;
 }
 
-
 void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
 {
 	struct hl_host_info *hi;
@@ -187,46 +175,41 @@
 		}
 	}
 	read_unlock(&hl->host_info_lock);
-
 	return data;
 }
 
-
 static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
 {
 	struct hpsb_highlevel *hl = __data;
 
 	hl->add_host(host);
 
-        if (host->update_config_rom) {
-		if (hpsb_update_config_rom_image(host) < 0) {
-			HPSB_ERR("Failed to generate Configuration ROM image for host "
-				 "%s-%d", hl->name, host->id);
-		}
-	}
-
+	if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
+		HPSB_ERR("Failed to generate Configuration ROM image for host "
+			 "%s-%d", hl->name, host->id);
 	return 0;
 }
 
 void hpsb_register_highlevel(struct hpsb_highlevel *hl)
 {
-        INIT_LIST_HEAD(&hl->addr_list);
+	unsigned long flags;
+
+	INIT_LIST_HEAD(&hl->addr_list);
 	INIT_LIST_HEAD(&hl->host_info_list);
 
 	rwlock_init(&hl->host_info_lock);
 
 	down_write(&hl_drivers_sem);
-        list_add_tail(&hl->hl_list, &hl_drivers);
+	list_add_tail(&hl->hl_list, &hl_drivers);
 	up_write(&hl_drivers_sem);
 
-	write_lock(&hl_irqs_lock);
+	write_lock_irqsave(&hl_irqs_lock, flags);
 	list_add_tail(&hl->irq_list, &hl_irqs);
-	write_unlock(&hl_irqs_lock);
+	write_unlock_irqrestore(&hl_irqs_lock, flags);
 
 	if (hl->add_host)
 		nodemgr_for_each_host(hl, highlevel_for_each_host_reg);
-
-        return;
+	return;
 }
 
 static void __delete_addr(struct hpsb_address_serve *as)
@@ -236,7 +219,8 @@
 	kfree(as);
 }
 
-static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host, int update_cr)
+static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host,
+			      int update_cr)
 {
 	unsigned long flags;
 	struct list_head *lh, *next;
@@ -251,7 +235,6 @@
 	write_lock_irqsave(&addr_space_lock, flags);
 	list_for_each_safe (lh, next, &hl->addr_list) {
 		as = list_entry(lh, struct hpsb_address_serve, hl_list);
-
 		if (as->host == host)
 			__delete_addr(as);
 	}
@@ -259,15 +242,12 @@
 
 	/* Now update the config-rom to reflect anything removed by the
 	 * highlevel driver. */
-	if (update_cr && host->update_config_rom) {
-		if (hpsb_update_config_rom_image(host) < 0) {
-			HPSB_ERR("Failed to generate Configuration ROM image for host "
-				 "%s-%d", hl->name, host->id);
-		}
-	}
+	if (update_cr && host->update_config_rom &&
+	    hpsb_update_config_rom_image(host) < 0)
+		HPSB_ERR("Failed to generate Configuration ROM image for host "
+			 "%s-%d", hl->name, host->id);
 
-	/* And finally, remove all the host info associated between these
-	 * two. */
+	/* Finally remove all the host info associated between these two. */
 	hpsb_destroy_hostinfo(hl, host);
 }
 
@@ -276,18 +256,19 @@
 	struct hpsb_highlevel *hl = __data;
 
 	__unregister_host(hl, host, 1);
-
 	return 0;
 }
 
 void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
 {
-	write_lock(&hl_irqs_lock);
+	unsigned long flags;
+
+	write_lock_irqsave(&hl_irqs_lock, flags);
 	list_del(&hl->irq_list);
-	write_unlock(&hl_irqs_lock);
+	write_unlock_irqrestore(&hl_irqs_lock, flags);
 
 	down_write(&hl_drivers_sem);
-        list_del(&hl->hl_list);
+	list_del(&hl->hl_list);
 	up_write(&hl_drivers_sem);
 
 	nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
@@ -301,7 +282,7 @@
 {
 	struct hpsb_address_serve *as, *a1, *a2;
 	struct list_head *entry;
-	u64 retval = ~0ULL;
+	u64 retval = CSR1212_INVALID_ADDR_SPACE;
 	unsigned long flags;
 	u64 align_mask = ~(alignment - 1);
 
@@ -312,14 +293,19 @@
 		return retval;
 	}
 
-	if (start == ~0ULL && end == ~0ULL) {
-		start = CSR1212_ALL_SPACE_BASE + 0xffff00000000ULL;  /* ohci1394.c limit */
-		end = CSR1212_ALL_SPACE_END;
+	/* default range,
+	 * avoids controller's posted write area (see OHCI 1.1 clause 1.5) */
+	if (start == CSR1212_INVALID_ADDR_SPACE &&
+	    end   == CSR1212_INVALID_ADDR_SPACE) {
+		start = host->middle_addr_space;
+		end   = CSR1212_ALL_SPACE_END;
 	}
 
-	if (((start|end) & ~align_mask) || (start >= end) || (end > 0x1000000000000ULL)) {
-		HPSB_ERR("%s called with invalid addresses (start = %012Lx    end = %012Lx)",
-			 __FUNCTION__, (unsigned long long)start, (unsigned long long)end);
+	if (((start|end) & ~align_mask) || (start >= end) ||
+	    (end > CSR1212_ALL_SPACE_END)) {
+		HPSB_ERR("%s called with invalid addresses "
+			 "(start = %012Lx  end = %012Lx)", __FUNCTION__,
+			 (unsigned long long)start,(unsigned long long)end);
 		return retval;
 	}
 
@@ -333,20 +319,21 @@
 	as->host = host;
 
 	write_lock_irqsave(&addr_space_lock, flags);
-
 	list_for_each(entry, &host->addr_space) {
 		u64 a1sa, a1ea;
 		u64 a2sa, a2ea;
 
 		a1 = list_entry(entry, struct hpsb_address_serve, host_list);
-		a2 = list_entry(entry->next, struct hpsb_address_serve, host_list);
+		a2 = list_entry(entry->next, struct hpsb_address_serve,
+				host_list);
 
 		a1sa = a1->start & align_mask;
 		a1ea = (a1->end + alignment -1) & align_mask;
 		a2sa = a2->start & align_mask;
 		a2ea = (a2->end + alignment -1) & align_mask;
 
-		if ((a2sa - a1ea >= size) && (a2sa - start >= size) && (a2sa > start)) {
+		if ((a2sa - a1ea >= size) && (a2sa - start >= size) &&
+		    (a2sa > start)) {
 			as->start = max(start, a1ea);
 			as->end = as->start + size;
 			list_add(&as->host_list, entry);
@@ -355,47 +342,45 @@
 			break;
 		}
 	}
-
 	write_unlock_irqrestore(&addr_space_lock, flags);
 
-	if (retval == ~0ULL) {
+	if (retval == CSR1212_INVALID_ADDR_SPACE)
 		kfree(as);
-	}
-
 	return retval;
 }
 
 int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                            struct hpsb_address_ops *ops, u64 start, u64 end)
+			    struct hpsb_address_ops *ops, u64 start, u64 end)
 {
-        struct hpsb_address_serve *as;
+	struct hpsb_address_serve *as;
 	struct list_head *lh;
-        int retval = 0;
-        unsigned long flags;
+	int retval = 0;
+	unsigned long flags;
 
-        if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) {
-                HPSB_ERR("%s called with invalid addresses", __FUNCTION__);
-                return 0;
-        }
+	if (((start|end) & 3) || (start >= end) ||
+	    (end > CSR1212_ALL_SPACE_END)) {
+		HPSB_ERR("%s called with invalid addresses", __FUNCTION__);
+		return 0;
+	}
 
 	as = kmalloc(sizeof(*as), GFP_ATOMIC);
 	if (!as)
 		return 0;
 
-        INIT_LIST_HEAD(&as->host_list);
-        INIT_LIST_HEAD(&as->hl_list);
-        as->op = ops;
-        as->start = start;
-        as->end = end;
+	INIT_LIST_HEAD(&as->host_list);
+	INIT_LIST_HEAD(&as->hl_list);
+	as->op = ops;
+	as->start = start;
+	as->end = end;
 	as->host = host;
 
 	write_lock_irqsave(&addr_space_lock, flags);
-
 	list_for_each(lh, &host->addr_space) {
 		struct hpsb_address_serve *as_this =
 			list_entry(lh, struct hpsb_address_serve, host_list);
 		struct hpsb_address_serve *as_next =
-			list_entry(lh->next, struct hpsb_address_serve, host_list);
+			list_entry(lh->next, struct hpsb_address_serve,
+				   host_list);
 
 		if (as_this->end > as->start)
 			break;
@@ -411,60 +396,51 @@
 
 	if (retval == 0)
 		kfree(as);
-
-        return retval;
+	return retval;
 }
 
 int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                              u64 start)
+			      u64 start)
 {
-        int retval = 0;
-        struct hpsb_address_serve *as;
-        struct list_head *lh, *next;
-        unsigned long flags;
+	int retval = 0;
+	struct hpsb_address_serve *as;
+	struct list_head *lh, *next;
+	unsigned long flags;
 
-        write_lock_irqsave(&addr_space_lock, flags);
-
+	write_lock_irqsave(&addr_space_lock, flags);
 	list_for_each_safe (lh, next, &hl->addr_list) {
-                as = list_entry(lh, struct hpsb_address_serve, hl_list);
-                if (as->start == start && as->host == host) {
+		as = list_entry(lh, struct hpsb_address_serve, hl_list);
+		if (as->start == start && as->host == host) {
 			__delete_addr(as);
-                        retval = 1;
-                        break;
-                }
-        }
-
-        write_unlock_irqrestore(&addr_space_lock, flags);
-
-        return retval;
+			retval = 1;
+			break;
+		}
+	}
+	write_unlock_irqrestore(&addr_space_lock, flags);
+	return retval;
 }
 
 int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                         unsigned int channel)
+			unsigned int channel)
 {
-        if (channel > 63) {
-                HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-                return -EINVAL;
-        }
-
-        if (host->iso_listen_count[channel]++ == 0) {
-                return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
-        }
-
+	if (channel > 63) {
+		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (host->iso_listen_count[channel]++ == 0)
+		return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
 	return 0;
 }
 
 void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                           unsigned int channel)
+			   unsigned int channel)
 {
-        if (channel > 63) {
-                HPSB_ERR("%s called with invalid channel", __FUNCTION__);
-                return;
-        }
-
-        if (--host->iso_listen_count[channel] == 0) {
-                host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
-        }
+	if (channel > 63) {
+		HPSB_ERR("%s called with invalid channel", __FUNCTION__);
+		return;
+	}
+	if (--host->iso_listen_count[channel] == 0)
+		host->driver->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
 }
 
 static void init_hpsb_highlevel(struct hpsb_host *host)
@@ -485,26 +461,24 @@
 
 void highlevel_add_host(struct hpsb_host *host)
 {
-        struct hpsb_highlevel *hl;
+	struct hpsb_highlevel *hl;
 
 	init_hpsb_highlevel(host);
 
 	down_read(&hl_drivers_sem);
-        list_for_each_entry(hl, &hl_drivers, hl_list) {
+	list_for_each_entry(hl, &hl_drivers, hl_list) {
 		if (hl->add_host)
 			hl->add_host(host);
-        }
-	up_read(&hl_drivers_sem);
-	if (host->update_config_rom) {
-		if (hpsb_update_config_rom_image(host) < 0)
-			HPSB_ERR("Failed to generate Configuration ROM image for "
-				 "host %s-%d", hl->name, host->id);
 	}
+	up_read(&hl_drivers_sem);
+	if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
+		HPSB_ERR("Failed to generate Configuration ROM image for host "
+			 "%s-%d", hl->name, host->id);
 }
 
 void highlevel_remove_host(struct hpsb_host *host)
 {
-        struct hpsb_highlevel *hl;
+	struct hpsb_highlevel *hl;
 
 	down_read(&hl_drivers_sem);
 	list_for_each_entry(hl, &hl_drivers, hl_list)
@@ -514,184 +488,169 @@
 
 void highlevel_host_reset(struct hpsb_host *host)
 {
-        struct hpsb_highlevel *hl;
+	unsigned long flags;
+	struct hpsb_highlevel *hl;
 
-	read_lock(&hl_irqs_lock);
+	read_lock_irqsave(&hl_irqs_lock, flags);
 	list_for_each_entry(hl, &hl_irqs, irq_list) {
-                if (hl->host_reset)
-                        hl->host_reset(host);
-        }
-	read_unlock(&hl_irqs_lock);
+		if (hl->host_reset)
+			hl->host_reset(host);
+	}
+	read_unlock_irqrestore(&hl_irqs_lock, flags);
 }
 
 void highlevel_iso_receive(struct hpsb_host *host, void *data, size_t length)
 {
-        struct hpsb_highlevel *hl;
-        int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
+	unsigned long flags;
+	struct hpsb_highlevel *hl;
+	int channel = (((quadlet_t *)data)[0] >> 8) & 0x3f;
 
-        read_lock(&hl_irqs_lock);
+	read_lock_irqsave(&hl_irqs_lock, flags);
 	list_for_each_entry(hl, &hl_irqs, irq_list) {
-                if (hl->iso_receive)
-                        hl->iso_receive(host, channel, data, length);
-        }
-        read_unlock(&hl_irqs_lock);
+		if (hl->iso_receive)
+			hl->iso_receive(host, channel, data, length);
+	}
+	read_unlock_irqrestore(&hl_irqs_lock, flags);
 }
 
 void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
 			   void *data, size_t length)
 {
-        struct hpsb_highlevel *hl;
-        int cts = ((quadlet_t *)data)[0] >> 4;
+	unsigned long flags;
+	struct hpsb_highlevel *hl;
+	int cts = ((quadlet_t *)data)[0] >> 4;
 
-        read_lock(&hl_irqs_lock);
+	read_lock_irqsave(&hl_irqs_lock, flags);
 	list_for_each_entry(hl, &hl_irqs, irq_list) {
-                if (hl->fcp_request)
-                        hl->fcp_request(host, nodeid, direction, cts, data,
+		if (hl->fcp_request)
+			hl->fcp_request(host, nodeid, direction, cts, data,
 					length);
-        }
-        read_unlock(&hl_irqs_lock);
+	}
+	read_unlock_irqrestore(&hl_irqs_lock, flags);
 }
 
-int highlevel_read(struct hpsb_host *host, int nodeid, void *data,
-                   u64 addr, unsigned int length, u16 flags)
+int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
+		   unsigned int length, u16 flags)
 {
-        struct hpsb_address_serve *as;
-        unsigned int partlength;
-        int rcode = RCODE_ADDRESS_ERROR;
+	struct hpsb_address_serve *as;
+	unsigned int partlength;
+	int rcode = RCODE_ADDRESS_ERROR;
 
-        read_lock(&addr_space_lock);
-
+	read_lock(&addr_space_lock);
 	list_for_each_entry(as, &host->addr_space, host_list) {
 		if (as->start > addr)
 			break;
 
-                if (as->end > addr) {
-                        partlength = min(as->end - addr, (u64) length);
+		if (as->end > addr) {
+			partlength = min(as->end - addr, (u64) length);
 
-                        if (as->op->read) {
-                                rcode = as->op->read(host, nodeid, data,
+			if (as->op->read)
+				rcode = as->op->read(host, nodeid, data,
 						     addr, partlength, flags);
-                        } else {
-                                rcode = RCODE_TYPE_ERROR;
-                        }
+			else
+				rcode = RCODE_TYPE_ERROR;
 
 			data += partlength;
-                        length -= partlength;
-                        addr += partlength;
+			length -= partlength;
+			addr += partlength;
 
-                        if ((rcode != RCODE_COMPLETE) || !length) {
-                                break;
-                        }
-                }
-        }
+			if ((rcode != RCODE_COMPLETE) || !length)
+				break;
+		}
+	}
+	read_unlock(&addr_space_lock);
 
-        read_unlock(&addr_space_lock);
-
-        if (length && (rcode == RCODE_COMPLETE)) {
-                rcode = RCODE_ADDRESS_ERROR;
-        }
-
-        return rcode;
+	if (length && (rcode == RCODE_COMPLETE))
+		rcode = RCODE_ADDRESS_ERROR;
+	return rcode;
 }
 
-int highlevel_write(struct hpsb_host *host, int nodeid, int destid,
-		    void *data, u64 addr, unsigned int length, u16 flags)
+int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
+		    u64 addr, unsigned int length, u16 flags)
 {
-        struct hpsb_address_serve *as;
-        unsigned int partlength;
-        int rcode = RCODE_ADDRESS_ERROR;
+	struct hpsb_address_serve *as;
+	unsigned int partlength;
+	int rcode = RCODE_ADDRESS_ERROR;
 
-        read_lock(&addr_space_lock);
-
+	read_lock(&addr_space_lock);
 	list_for_each_entry(as, &host->addr_space, host_list) {
 		if (as->start > addr)
 			break;
 
-                if (as->end > addr) {
-                        partlength = min(as->end - addr, (u64) length);
+		if (as->end > addr) {
+			partlength = min(as->end - addr, (u64) length);
 
-                        if (as->op->write) {
-                                rcode = as->op->write(host, nodeid, destid,
-						      data, addr, partlength, flags);
-                        } else {
-                                rcode = RCODE_TYPE_ERROR;
-                        }
+			if (as->op->write)
+				rcode = as->op->write(host, nodeid, destid,
+						      data, addr, partlength,
+						      flags);
+			else
+				rcode = RCODE_TYPE_ERROR;
 
 			data += partlength;
-                        length -= partlength;
-                        addr += partlength;
+			length -= partlength;
+			addr += partlength;
 
-                        if ((rcode != RCODE_COMPLETE) || !length) {
-                                break;
-                        }
-                }
-        }
+			if ((rcode != RCODE_COMPLETE) || !length)
+				break;
+		}
+	}
+	read_unlock(&addr_space_lock);
 
-        read_unlock(&addr_space_lock);
-
-        if (length && (rcode == RCODE_COMPLETE)) {
-                rcode = RCODE_ADDRESS_ERROR;
-        }
-
-        return rcode;
+	if (length && (rcode == RCODE_COMPLETE))
+		rcode = RCODE_ADDRESS_ERROR;
+	return rcode;
 }
 
-
 int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags)
+		   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
+		   u16 flags)
 {
-        struct hpsb_address_serve *as;
-        int rcode = RCODE_ADDRESS_ERROR;
+	struct hpsb_address_serve *as;
+	int rcode = RCODE_ADDRESS_ERROR;
 
-        read_lock(&addr_space_lock);
-
+	read_lock(&addr_space_lock);
 	list_for_each_entry(as, &host->addr_space, host_list) {
 		if (as->start > addr)
 			break;
 
-                if (as->end > addr) {
-                        if (as->op->lock) {
-                                rcode = as->op->lock(host, nodeid, store, addr,
-                                                     data, arg, ext_tcode, flags);
-                        } else {
-                                rcode = RCODE_TYPE_ERROR;
-                        }
-
-                        break;
-                }
-        }
-
-        read_unlock(&addr_space_lock);
-
-        return rcode;
+		if (as->end > addr) {
+			if (as->op->lock)
+				rcode = as->op->lock(host, nodeid, store, addr,
+						     data, arg, ext_tcode,
+						     flags);
+			else
+				rcode = RCODE_TYPE_ERROR;
+			break;
+		}
+	}
+	read_unlock(&addr_space_lock);
+	return rcode;
 }
 
 int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags)
+		     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
+		     u16 flags)
 {
-        struct hpsb_address_serve *as;
-        int rcode = RCODE_ADDRESS_ERROR;
+	struct hpsb_address_serve *as;
+	int rcode = RCODE_ADDRESS_ERROR;
 
-        read_lock(&addr_space_lock);
+	read_lock(&addr_space_lock);
 
 	list_for_each_entry(as, &host->addr_space, host_list) {
 		if (as->start > addr)
 			break;
 
-                if (as->end > addr) {
-                        if (as->op->lock64) {
-                                rcode = as->op->lock64(host, nodeid, store,
-                                                       addr, data, arg,
-                                                       ext_tcode, flags);
-                        } else {
-                                rcode = RCODE_TYPE_ERROR;
-                        }
-
-                        break;
-                }
-        }
-
-        read_unlock(&addr_space_lock);
-
-        return rcode;
+		if (as->end > addr) {
+			if (as->op->lock64)
+				rcode = as->op->lock64(host, nodeid, store,
+						       addr, data, arg,
+						       ext_tcode, flags);
+			else
+				rcode = RCODE_TYPE_ERROR;
+			break;
+		}
+	}
+	read_unlock(&addr_space_lock);
+	return rcode;
 }
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
index ba09741..ad49c04 100644
--- a/drivers/ieee1394/hosts.c
+++ b/drivers/ieee1394/hosts.c
@@ -19,6 +19,7 @@
 #include <linux/pci.h>
 #include <linux/timer.h>
 #include <linux/jiffies.h>
+#include <linux/mutex.h>
 
 #include "csr1212.h"
 #include "ieee1394.h"
@@ -102,10 +103,10 @@
  * driver specific parts, enable the controller and make it available
  * to the general subsystem using hpsb_add_host().
  *
- * Return Value: a pointer to the &hpsb_host if succesful, %NULL if
+ * Return Value: a pointer to the &hpsb_host if successful, %NULL if
  * no memory was available.
  */
-static DECLARE_MUTEX(host_num_alloc);
+static DEFINE_MUTEX(host_num_alloc);
 
 struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
 				  struct device *dev)
@@ -148,7 +149,7 @@
 	h->topology_map = h->csr.topology_map + 3;
 	h->speed_map = (u8 *)(h->csr.speed_map + 2);
 
-	down(&host_num_alloc);
+	mutex_lock(&host_num_alloc);
 
 	while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
 		hostnum++;
@@ -167,7 +168,7 @@
 	class_device_register(&h->class_dev);
 	get_device(&h->device);
 
-	up(&host_num_alloc);
+	mutex_unlock(&host_num_alloc);
 
 	return h;
 }
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
index 07d188c..9ad4b24 100644
--- a/drivers/ieee1394/hosts.h
+++ b/drivers/ieee1394/hosts.h
@@ -30,13 +30,14 @@
 
 	unsigned char iso_listen_count[64];
 
-	int node_count; /* number of identified nodes on this bus */
-	int selfid_count; /* total number of SelfIDs received */
-	int nodes_active; /* number of nodes that are actually active */
+	int node_count;      /* number of identified nodes on this bus */
+	int selfid_count;    /* total number of SelfIDs received */
+	int nodes_active;    /* number of nodes with active link layer */
+	u8 speed[ALL_NODES]; /* speed between each node and local node */
 
-	nodeid_t node_id; /* node ID of this host */
-	nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
-	nodeid_t busmgr_id; /* ID of this bus' bus manager */
+	nodeid_t node_id;    /* node ID of this host */
+	nodeid_t irm_id;     /* ID of this bus' isochronous resource manager */
+	nodeid_t busmgr_id;  /* ID of this bus' bus manager */
 
 	/* this nodes state */
 	unsigned in_bus_reset:1;
@@ -55,7 +56,7 @@
 	struct csr_control csr;
 
 	/* Per node tlabel pool allocation */
-	struct hpsb_tlabel_pool tpool[64];
+	struct hpsb_tlabel_pool tpool[ALL_NODES];
 
 	struct hpsb_host_driver *driver;
 
@@ -72,6 +73,8 @@
 	unsigned int config_roms;
 
 	struct list_head addr_space;
+	u64 low_addr_space;	/* upper bound of physical DMA area */
+	u64 middle_addr_space;	/* upper bound of posted write area */
 };
 
 
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index be6854e..49354de 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -33,6 +33,7 @@
 #include <linux/kdev_t.h>
 #include <linux/skbuff.h>
 #include <linux/suspend.h>
+#include <linux/kthread.h>
 
 #include <asm/byteorder.h>
 #include <asm/semaphore.h>
@@ -285,9 +286,9 @@
 
 static void build_speed_map(struct hpsb_host *host, int nodecount)
 {
-	u8 speedcap[nodecount];
 	u8 cldcnt[nodecount];
 	u8 *map = host->speed_map;
+	u8 *speedcap = host->speed;
 	struct selfid *sid;
 	struct ext_selfid *esid;
 	int i, j, n;
@@ -354,6 +355,11 @@
 			}
 		}
 	}
+
+	/* assume maximum speed for 1394b PHYs, nodemgr will correct it */
+	for (n = 0; n < nodecount; n++)
+		if (speedcap[n] == 3)
+			speedcap[n] = IEEE1394_SPEED_MAX;
 }
 
 
@@ -554,11 +560,10 @@
 		return 0;
 	}
 
-	if (packet->type == hpsb_async && packet->node_id != ALL_NODES) {
+	if (packet->type == hpsb_async &&
+	    NODEID_TO_NODE(packet->node_id) != ALL_NODES)
 		packet->speed_code =
-			host->speed_map[NODEID_TO_NODE(host->node_id) * 64
-				       + NODEID_TO_NODE(packet->node_id)];
-	}
+			host->speed[NODEID_TO_NODE(packet->node_id)];
 
 	dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
 
@@ -997,11 +1002,8 @@
  * packets that have a "complete" function are sent here. This way, the
  * completion is run out of kernel context, and doesn't block the rest of
  * the stack. */
-static int khpsbpkt_pid = -1, khpsbpkt_kill;
-static DECLARE_COMPLETION(khpsbpkt_complete);
+static struct task_struct *khpsbpkt_thread;
 static struct sk_buff_head hpsbpkt_queue;
-static DECLARE_MUTEX_LOCKED(khpsbpkt_sig);
-
 
 static void queue_packet_complete(struct hpsb_packet *packet)
 {
@@ -1011,9 +1013,7 @@
 	}
 	if (packet->complete_routine != NULL) {
 		skb_queue_tail(&hpsbpkt_queue, packet->skb);
-
-		/* Signal the kernel thread to handle this */
-		up(&khpsbpkt_sig);
+		wake_up_process(khpsbpkt_thread);
 	}
 	return;
 }
@@ -1025,19 +1025,9 @@
 	void (*complete_routine)(void*);
 	void *complete_data;
 
-	daemonize("khpsbpkt");
-
 	current->flags |= PF_NOFREEZE;
 
-	while (1) {
-		if (down_interruptible(&khpsbpkt_sig)) {
-			printk("khpsbpkt: received unexpected signal?!\n" );
-			break;
-		}
-
-		if (khpsbpkt_kill)
-			break;
-
+	while (!kthread_should_stop()) {
 		while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) {
 			packet = (struct hpsb_packet *)skb->data;
 
@@ -1048,9 +1038,13 @@
 
 			complete_routine(complete_data);
 		}
-	}
 
-	complete_and_exit(&khpsbpkt_complete, 0);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!skb_peek(&hpsbpkt_queue))
+			schedule();
+		__set_current_state(TASK_RUNNING);
+	}
+	return 0;
 }
 
 static int __init ieee1394_init(void)
@@ -1065,10 +1059,10 @@
 		HPSB_ERR("Some features may not be available\n");
 	}
 
-	khpsbpkt_pid = kernel_thread(hpsbpkt_thread, NULL, CLONE_KERNEL);
-	if (khpsbpkt_pid < 0) {
+	khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt");
+	if (IS_ERR(khpsbpkt_thread)) {
 		HPSB_ERR("Failed to start hpsbpkt thread!\n");
-		ret = -ENOMEM;
+		ret = PTR_ERR(khpsbpkt_thread);
 		goto exit_cleanup_config_roms;
 	}
 
@@ -1148,10 +1142,7 @@
 release_chrdev:
 	unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 exit_release_kernel_thread:
-	if (khpsbpkt_pid >= 0) {
-		kill_proc(khpsbpkt_pid, SIGTERM, 1);
-		wait_for_completion(&khpsbpkt_complete);
-	}
+	kthread_stop(khpsbpkt_thread);
 exit_cleanup_config_roms:
 	hpsb_cleanup_config_roms();
 	return ret;
@@ -1172,12 +1163,7 @@
 		bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
 	bus_unregister(&ieee1394_bus_type);
 
-	if (khpsbpkt_pid >= 0) {
-		khpsbpkt_kill = 1;
-		mb();
-		up(&khpsbpkt_sig);
-		wait_for_completion(&khpsbpkt_complete);
-	}
+	kthread_stop(khpsbpkt_thread);
 
 	hpsb_cleanup_config_roms();
 
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index e7b55e8..0ecbf33 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -139,7 +139,7 @@
 
 /*
  * Hand over received selfid packet to the core.  Complement check (second
- * quadlet is complement of first) is expected to be done and succesful.
+ * quadlet is complement of first) is expected to be done and successful.
  */
 void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid);
 
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 3fe2f6c..a114b91 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -136,8 +136,11 @@
 {
 	unsigned long flags;
 	struct hpsb_tlabel_pool *tp;
+	int n = NODEID_TO_NODE(packet->node_id);
 
-	tp = &packet->host->tpool[packet->node_id & NODE_MASK];
+	if (unlikely(n == ALL_NODES))
+		return 0;
+	tp = &packet->host->tpool[n];
 
 	if (irqs_disabled() || in_atomic()) {
 		if (down_trylock(&tp->count))
@@ -175,8 +178,11 @@
 {
 	unsigned long flags;
 	struct hpsb_tlabel_pool *tp;
+	int n = NODEID_TO_NODE(packet->node_id);
 
-	tp = &packet->host->tpool[packet->node_id & NODE_MASK];
+	if (unlikely(n == ALL_NODES))
+		return;
+	tp = &packet->host->tpool[n];
 
 	BUG_ON(packet->tlabel > 63 || packet->tlabel < 0);
 
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 082c7fd..50c71e1 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -8,6 +8,7 @@
  * directory of the kernel sources for details.
  */
 
+#include <linux/bitmap.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
 #include <linux/list.h>
@@ -38,6 +39,7 @@
 	struct hpsb_host *host;
 	nodeid_t nodeid;
 	unsigned int generation;
+	unsigned int speed_unverified:1;
 };
 
 
@@ -57,23 +59,75 @@
 	return NULL;
 }
 
+/*
+ * Correct the speed map entry.  This is necessary
+ *  - for nodes with link speed < phy speed,
+ *  - for 1394b nodes with negotiated phy port speed < IEEE1394_SPEED_MAX.
+ * A possible speed is determined by trial and error, using quadlet reads.
+ */
+static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
+			       quadlet_t *buffer)
+{
+	quadlet_t q;
+	u8 i, *speed, old_speed, good_speed;
+	int ret;
+
+	speed = ci->host->speed + NODEID_TO_NODE(ci->nodeid);
+	old_speed = *speed;
+	good_speed = IEEE1394_SPEED_MAX + 1;
+
+	/* Try every speed from S100 to old_speed.
+	 * If we did it the other way around, a too low speed could be caught
+	 * if the retry succeeded for some other reason, e.g. because the link
+	 * just finished its initialization. */
+	for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
+		*speed = i;
+		ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
+				&q, sizeof(quadlet_t));
+		if (ret)
+			break;
+		*buffer = q;
+		good_speed = i;
+	}
+	if (good_speed <= IEEE1394_SPEED_MAX) {
+		HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s",
+			   NODE_BUS_ARGS(ci->host, ci->nodeid),
+			   hpsb_speedto_str[good_speed]);
+		*speed = good_speed;
+		ci->speed_unverified = 0;
+		return 0;
+	}
+	*speed = old_speed;
+	return ret;
+}
 
 static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length,
                             void *buffer, void *__ci)
 {
 	struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
-	int i, ret = 0;
+	int i, ret;
 
 	for (i = 1; ; i++) {
 		ret = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
 				buffer, length);
-		if (!ret || i == 3)
+		if (!ret) {
+			ci->speed_unverified = 0;
+			break;
+		}
+		/* Give up after 3rd failure. */
+		if (i == 3)
 			break;
 
+		/* The ieee1394_core guessed the node's speed capability from
+		 * the self ID.  Check whether a lower speed works. */
+		if (ci->speed_unverified && length == sizeof(quadlet_t)) {
+			ret = nodemgr_check_speed(ci, addr, buffer);
+			if (!ret)
+				break;
+		}
 		if (msleep_interruptible(334))
 			return -EINTR;
 	}
-
 	return ret;
 }
 
@@ -281,10 +335,12 @@
 static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
 
 
+/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically
+ * here, therefore displayed values may be occasionally wrong. */
 static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct node_entry *ne = container_of(dev, struct node_entry, device);
-	return sprintf(buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1);
+	return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64));
 }
 static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
 
@@ -1204,6 +1260,8 @@
 	ci->host = host;
 	ci->nodeid = nodeid;
 	ci->generation = generation;
+	ci->speed_unverified =
+		host->speed[NODEID_TO_NODE(nodeid)] > IEEE1394_SPEED_100;
 
 	/* We need to detect when the ConfigROM's generation has changed,
 	 * so we only update the node's info when it needs to be.  */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 11f1377..3d27841 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -163,7 +163,7 @@
 
 /* Module Parameters */
 static int phys_dma = 1;
-module_param(phys_dma, int, 0644);
+module_param(phys_dma, int, 0444);
 MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
 
 static void dma_trm_tasklet(unsigned long data);
@@ -553,7 +553,8 @@
 	 * register content.
 	 * To actually enable physical responses is the job of our interrupt
 	 * handler which programs the physical request filter. */
-	reg_write(ohci, OHCI1394_PhyUpperBound, 0x01000000);
+	reg_write(ohci, OHCI1394_PhyUpperBound,
+		  OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED >> 16);
 
 	DBGMSG("physUpperBoundOffset=%08x",
 	       reg_read(ohci, OHCI1394_PhyUpperBound));
@@ -580,17 +581,14 @@
 		  OHCI1394_isochRx |
 		  OHCI1394_isochTx |
 		  OHCI1394_postedWriteErr |
+		  OHCI1394_cycleTooLong |
 		  OHCI1394_cycleInconsistent);
 
 	/* Enable link */
 	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
 
 	buf = reg_read(ohci, OHCI1394_Version);
-#ifndef __sparc__
 	sprintf (irq_buf, "%d", ohci->dev->irq);
-#else
-	sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));
-#endif
 	PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s]  "
 	      "MMIO=[%lx-%lx]  Max Packet=[%d]  IR/IT contexts=[%d/%d]",
 	      ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
@@ -2386,6 +2384,15 @@
 		PRINT(KERN_ERR, "physical posted write error");
 		/* no recovery strategy yet, had to involve protocol drivers */
 	}
+	if (event & OHCI1394_cycleTooLong) {
+		if(printk_ratelimit())
+			PRINT(KERN_WARNING, "isochronous cycle too long");
+		else
+			DBGMSG("OHCI1394_cycleTooLong");
+		reg_write(ohci, OHCI1394_LinkControlSet,
+			  OHCI1394_LinkControl_CycleMaster);
+		event &= ~OHCI1394_cycleTooLong;
+	}
 	if (event & OHCI1394_cycleInconsistent) {
 		/* We subscribe to the cycleInconsistent event only to
 		 * clear the corresponding event bit... otherwise,
@@ -3404,6 +3411,14 @@
 	host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf;
 	host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7;
 
+	if (phys_dma) {
+		host->low_addr_space =
+			(u64) reg_read(ohci, OHCI1394_PhyUpperBound) << 16;
+		if (!host->low_addr_space)
+			host->low_addr_space = OHCI1394_PHYS_UPPER_BOUND_FIXED;
+	}
+	host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE;
+
 	/* Tell the highlevel this host is ready */
 	if (hpsb_add_host(host))
 		FAIL(-ENOMEM, "Failed to register host with highlevel");
@@ -3462,24 +3477,13 @@
 	case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE:
 		/* The ohci_soft_reset() stops all DMA contexts, so we
 		 * dont need to do this.  */
-		/* Free AR dma */
 		free_dma_rcv_ctx(&ohci->ar_req_context);
 		free_dma_rcv_ctx(&ohci->ar_resp_context);
-
-		/* Free AT dma */
 		free_dma_trm_ctx(&ohci->at_req_context);
 		free_dma_trm_ctx(&ohci->at_resp_context);
-
-		/* Free IR dma */
 		free_dma_rcv_ctx(&ohci->ir_legacy_context);
-
-		/* Free IT dma */
 		free_dma_trm_ctx(&ohci->it_legacy_context);
 
-		/* Free IR legacy dma */
-		free_dma_rcv_ctx(&ohci->ir_legacy_context);
-
-
 	case OHCI_INIT_HAVE_SELFID_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
 				    ohci->selfid_buf_cpu,
@@ -3539,6 +3543,7 @@
 	}
 #endif /* CONFIG_PPC_PMAC */
 
+	pci_restore_state(pdev);
 	pci_enable_device(pdev);
 
 	return 0;
@@ -3558,6 +3563,8 @@
 	}
 #endif
 
+	pci_save_state(pdev);
+
 	return 0;
 }
 
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index 7df0962..fa05f11 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -443,6 +443,16 @@
 
 #define OHCI1394_TCODE_PHY               0xE
 
+/* Node offset map (phys DMA area, posted write area).
+ * The value of OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED may be modified but must
+ * be lower than OHCI1394_MIDDLE_ADDRESS_SPACE.
+ * OHCI1394_PHYS_UPPER_BOUND_FIXED and OHCI1394_MIDDLE_ADDRESS_SPACE are
+ * constants given by the OHCI spec.
+ */
+#define OHCI1394_PHYS_UPPER_BOUND_FIXED		0x000100000000ULL /* 4 GB */
+#define OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED	0x010000000000ULL /* 1 TB */
+#define OHCI1394_MIDDLE_ADDRESS_SPACE		0xffff00000000ULL
+
 void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet,
 			       int type,
 			       void (*func)(unsigned long),
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index e2edc41..e29dfd2 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -1252,11 +1252,7 @@
         /* Fix buggy cards with autoboot pin not tied low: */
         reg_write(lynx, DMA0_CHAN_CTRL, 0);
 
-#ifndef __sparc__
 	sprintf (irq_buf, "%d", dev->irq);
-#else
-	sprintf (irq_buf, "%s", __irq_itoa(dev->irq));
-#endif
 
         if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ,
                          PCILYNX_DRIVER_NAME, lynx)) {
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index f7de546..571ea68 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -132,8 +132,7 @@
 static void __queue_complete_req(struct pending_request *req)
 {
 	struct file_info *fi = req->file_info;
-	list_del(&req->list);
-	list_add_tail(&req->list, &fi->req_complete);
+	list_move_tail(&req->list, &fi->req_complete);
 
 	up(&fi->complete_sem);
 	wake_up_interruptible(&fi->poll_wait_complete);
@@ -408,34 +407,34 @@
 
 #ifdef CONFIG_COMPAT
 struct compat_raw1394_req {
-        __u32 type;
-        __s32 error;
-        __u32 misc;
+	__u32 type;
+	__s32 error;
+	__u32 misc;
 
-        __u32 generation;
-        __u32 length;
+	__u32 generation;
+	__u32 length;
 
-        __u64 address;
+	__u64 address;
 
-        __u64 tag;
+	__u64 tag;
 
-        __u64 sendb;
-        __u64 recvb;
-}  __attribute__((packed));
+	__u64 sendb;
+	__u64 recvb;
+} __attribute__((packed));
 
 static const char __user *raw1394_compat_write(const char __user *buf)
 {
-	struct compat_raw1394_req __user *cr = (typeof(cr)) buf; 
+	struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
 	struct raw1394_request __user *r;
 	r = compat_alloc_user_space(sizeof(struct raw1394_request));
 
 #define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x))
 
 	if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) ||
-		C(address) ||
-		C(tag) ||
-		C(sendb) ||
-		C(recvb))
+	    C(address) ||
+	    C(tag) ||
+	    C(sendb) ||
+	    C(recvb))
 		return ERR_PTR(-EFAULT);
 	return (const char __user *)r;
 }
@@ -443,11 +442,11 @@
 
 #define P(x) __put_user(r->x, &cr->x)
 
-static int 
+static int
 raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
 {
-	struct compat_raw1394_req __user *cr = (typeof(cr)) r; 
-	if (!access_ok(VERIFY_WRITE,cr,sizeof(struct compat_raw1394_req)) ||
+	struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+	if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
 	    P(type) ||
 	    P(error) ||
 	    P(misc) ||
@@ -512,18 +511,17 @@
 	}
 
 #ifdef CONFIG_COMPAT
-	if (count == sizeof(struct compat_raw1394_req) && 
-   		sizeof(struct compat_raw1394_req) != 
-			sizeof(struct raw1394_request)) { 
+	if (count == sizeof(struct compat_raw1394_req) &&
+   	    sizeof(struct compat_raw1394_req) !=
+			sizeof(struct raw1394_request)) {
 		ret = raw1394_compat_read(buffer, &req->req);
-
-	} else	
+	} else
 #endif
 	{
 		if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
 			ret = -EFAULT;
 			goto out;
-		}		
+		}
 		ret = (ssize_t) sizeof(struct raw1394_request);
 	}
       out:
@@ -2348,7 +2346,6 @@
 	return handle_async_request(fi, req, node);
 }
 
-
 static ssize_t raw1394_write(struct file *file, const char __user * buffer,
 			     size_t count, loff_t * offset_is_ignored)
 {
@@ -2357,9 +2354,9 @@
 	ssize_t retval = 0;
 
 #ifdef CONFIG_COMPAT
-	if (count == sizeof(struct compat_raw1394_req) && 
-   		sizeof(struct compat_raw1394_req) != 
-			sizeof(struct raw1394_request)) { 
+	if (count == sizeof(struct compat_raw1394_req) &&
+   	    sizeof(struct compat_raw1394_req) !=
+			sizeof(struct raw1394_request)) {
 		buffer = raw1394_compat_write(buffer);
 		if (IS_ERR(buffer))
 			return PTR_ERR(buffer);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 5413dc4..1d5ceb7 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -127,10 +127,12 @@
  * talking to a single sbp2 device at the same time (filesystem coherency,
  * etc.). If you're running an sbp2 device that supports multiple logins,
  * and you're either running read-only filesystems or some sort of special
- * filesystem supporting multiple hosts (one such filesystem is OpenGFS,
- * see opengfs.sourceforge.net for more info), then set exclusive_login
- * to zero. Note: The Oxsemi OXFW911 sbp2 chipset supports up to four
- * concurrent logins.
+ * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster
+ * File System, or Lustre, then set exclusive_login to zero.
+ *
+ * So far only bridges from Oxford Semiconductor are known to support
+ * concurrent logins. Depending on firmware, four or two concurrent logins
+ * are possible on OXFW911 and newer Oxsemi bridges.
  */
 static int exclusive_login = 1;
 module_param(exclusive_login, int, 0644);
@@ -306,8 +308,9 @@
 	u32 model_id;
 	unsigned workarounds;
 } sbp2_workarounds_table[] = {
-	/* TSB42AA9 */ {
+	/* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
 		.firmware_revision	= 0x002800,
+		.model_id		= 0x001010,
 		.workarounds		= SBP2_WORKAROUND_INQUIRY_36 |
 					  SBP2_WORKAROUND_MODE_SENSE_8,
 	},
@@ -791,12 +794,12 @@
 	scsi_id->ud = ud;
 	scsi_id->speed_code = IEEE1394_SPEED_100;
 	scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
+	scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
 	atomic_set(&scsi_id->sbp2_login_complete, 0);
 	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse);
 	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
 	INIT_LIST_HEAD(&scsi_id->scsi_list);
 	spin_lock_init(&scsi_id->sbp2_command_orb_lock);
-	scsi_id->sbp2_lun = 0;
 
 	ud->device.driver_data = scsi_id;
 
@@ -844,8 +847,8 @@
 	scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace(
 			&sbp2_highlevel, ud->ne->host, &sbp2_ops,
 			sizeof(struct sbp2_status_block), sizeof(quadlet_t),
-			0x010000000000ULL, CSR1212_ALL_SPACE_END);
-	if (scsi_id->status_fifo_addr == ~0ULL) {
+			ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END);
+	if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
 		SBP2_ERR("failed to allocate status FIFO address range");
 		goto failed_alloc;
 	}
@@ -1087,9 +1090,9 @@
 		SBP2_DMA_FREE("single query logins data");
 	}
 
-	if (scsi_id->status_fifo_addr)
+	if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)
 		hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
-			scsi_id->status_fifo_addr);
+					  scsi_id->status_fifo_addr);
 
 	scsi_id->ud->device.driver_data = NULL;
 
@@ -1213,13 +1216,11 @@
 	SBP2_DEBUG("length_max_logins = %x",
 		   (unsigned int)scsi_id->query_logins_response->length_max_logins);
 
-	SBP2_DEBUG("Query logins to SBP-2 device successful");
-
 	max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins);
-	SBP2_DEBUG("Maximum concurrent logins supported: %d", max_logins);
+	SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
 
 	active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins);
-	SBP2_DEBUG("Number of active logins: %d", active_logins);
+	SBP2_INFO("Number of active logins: %d", active_logins);
 
 	if (active_logins >= max_logins) {
 		return -EIO;
@@ -1648,6 +1649,8 @@
 	}
 }
 
+#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2))
+
 /*
  * This function is called in order to determine the max speed and packet
  * size we can use in our ORBs. Note, that we (the driver and host) only
@@ -1660,13 +1663,12 @@
 static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id)
 {
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
+	u8 payload;
 
 	SBP2_DEBUG_ENTER();
 
-	/* Initial setting comes from the hosts speed map */
 	scsi_id->speed_code =
-	    hi->host->speed_map[NODEID_TO_NODE(hi->host->node_id) * 64 +
-				NODEID_TO_NODE(scsi_id->ne->nodeid)];
+	    hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)];
 
 	/* Bump down our speed if the user requested it */
 	if (scsi_id->speed_code > max_speed) {
@@ -1677,15 +1679,22 @@
 
 	/* Payload size is the lesser of what our speed supports and what
 	 * our host supports.  */
-	scsi_id->max_payload_size =
-	    min(sbp2_speedto_max_payload[scsi_id->speed_code],
-		(u8) (hi->host->csr.max_rec - 1));
+	payload = min(sbp2_speedto_max_payload[scsi_id->speed_code],
+		      (u8) (hi->host->csr.max_rec - 1));
+
+	/* If physical DMA is off, work around limitation in ohci1394:
+	 * packet size must not exceed PAGE_SIZE */
+	if (scsi_id->ne->host->low_addr_space < (1ULL << 32))
+		while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE &&
+		       payload)
+			payload--;
 
 	HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
 		   NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid),
 		   hpsb_speedto_str[scsi_id->speed_code],
-		   1 << ((u32) scsi_id->max_payload_size + 2));
+		   SBP2_PAYLOAD_TO_BYTES(payload));
 
+	scsi_id->max_payload_size = payload;
 	return 0;
 }
 
@@ -2113,33 +2122,6 @@
 }
 
 /*
- * This function is called after a command is completed, in order to do any necessary SBP-2
- * response data translations for the SCSI stack
- */
-static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
-				     struct scsi_cmnd *SCpnt)
-{
-	u8 *scsi_buf = SCpnt->request_buffer;
-
-	SBP2_DEBUG_ENTER();
-
-	if (SCpnt->cmnd[0] == INQUIRY && (SCpnt->cmnd[1] & 3) == 0) {
-		/*
-		 * Make sure data length is ok. Minimum length is 36 bytes
-		 */
-		if (scsi_buf[4] == 0) {
-			scsi_buf[4] = 36 - 5;
-		}
-
-		/*
-		 * Fix ansi revision and response data format
-		 */
-		scsi_buf[2] |= 2;
-		scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;
-	}
-}
-
-/*
  * This function deals with status writes from the SBP-2 device
  */
 static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid,
@@ -2478,13 +2460,6 @@
 	}
 
 	/*
-	 * Take care of any sbp2 response data mucking here (RBC stuff, etc.)
-	 */
-	if (SCpnt->result == DID_OK << 16) {
-		sbp2_check_sbp2_response(scsi_id, SCpnt);
-	}
-
-	/*
 	 * If a bus reset is in progress and there was an error, complete
 	 * the command as busy so that it will get retried.
 	 */
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index f4ccc9d..b22ce1a 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -52,7 +52,7 @@
 	u32 data_descriptor_lo;
 	u32 misc;
 	u8 cdb[12];
-};
+} __attribute__((packed));
 
 #define SBP2_LOGIN_REQUEST		0x0
 #define SBP2_QUERY_LOGINS_REQUEST	0x1
@@ -80,7 +80,7 @@
 	u32 passwd_resp_lengths;
 	u32 status_fifo_hi;
 	u32 status_fifo_lo;
-};
+} __attribute__((packed));
 
 #define RESPONSE_GET_LOGIN_ID(value)            (value & 0xffff)
 #define RESPONSE_GET_LENGTH(value)              ((value >> 16) & 0xffff)
@@ -91,7 +91,7 @@
 	u32 command_block_agent_hi;
 	u32 command_block_agent_lo;
 	u32 reconnect_hold;
-};
+} __attribute__((packed));
 
 #define ORB_SET_LOGIN_ID(value)                 (value & 0xffff)
 
@@ -106,7 +106,7 @@
 	u32 reserved_resp_length;
 	u32 status_fifo_hi;
 	u32 status_fifo_lo;
-};
+} __attribute__((packed));
 
 #define RESPONSE_GET_MAX_LOGINS(value)          (value & 0xffff)
 #define RESPONSE_GET_ACTIVE_LOGINS(value)       ((RESPONSE_GET_LENGTH(value) - 4) / 12)
@@ -116,7 +116,7 @@
 	u32 misc_IDs;
 	u32 initiator_misc_hi;
 	u32 initiator_misc_lo;
-};
+} __attribute__((packed));
 
 struct sbp2_reconnect_orb {
 	u32 reserved1;
@@ -127,7 +127,7 @@
 	u32 reserved5;
 	u32 status_fifo_hi;
 	u32 status_fifo_lo;
-};
+} __attribute__((packed));
 
 struct sbp2_logout_orb {
 	u32 reserved1;
@@ -138,7 +138,7 @@
 	u32 reserved5;
 	u32 status_fifo_hi;
 	u32 status_fifo_lo;
-};
+} __attribute__((packed));
 
 #define PAGE_TABLE_SET_SEGMENT_BASE_HI(value)   (value & 0xffff)
 #define PAGE_TABLE_SET_SEGMENT_LENGTH(value)    ((value & 0xffff) << 16)
@@ -146,7 +146,7 @@
 struct sbp2_unrestricted_page_table {
 	u32 length_segment_base_hi;
 	u32 segment_base_lo;
-};
+} __attribute__((packed));
 
 #define RESP_STATUS_REQUEST_COMPLETE		0x0
 #define RESP_STATUS_TRANSPORT_FAILURE		0x1
@@ -191,7 +191,7 @@
 	u32 ORB_offset_hi_misc;
 	u32 ORB_offset_lo;
 	u8 command_set_dependent[24];
-};
+} __attribute__((packed));
 
 /*
  * Miscellaneous SBP2 related config rom defines
@@ -395,9 +395,8 @@
 static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
 			     struct scsi_cmnd *SCpnt,
 			     void (*done)(struct scsi_cmnd *));
-static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
-static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
-				     struct scsi_cmnd *SCpnt);
+static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status,
+					      unchar *sense_data);
 static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 				      struct unit_directory *ud);
 static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id);
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 4e3bd62..295d0f8 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -331,7 +331,7 @@
 
         spin_lock_init(&d->lock);
 
-	PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers "
+	DBGMSG(ohci->host->id, "Iso %s DMA: %d buffers "
 	      "of size %d allocated for a frame size %d, each with %d prgs",
 	      (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
 	      d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd);
@@ -759,7 +759,7 @@
 		} else {
 			mask = (u64)0x1<<v.channel;
 		}
-		PRINT(KERN_INFO, ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",
+		DBGMSG(ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",
 			(u32)(mask>>32),(u32)(mask&0xffffffff),
 			(u32)(ohci->ISO_channel_usage>>32),
 			(u32)(ohci->ISO_channel_usage&0xffffffff));
@@ -805,7 +805,7 @@
 			v.buf_size = d->buf_size;
 			list_add_tail(&d->link, &ctx->context_list);
 
-			PRINT(KERN_INFO, ohci->host->id,
+			DBGMSG(ohci->host->id,
 			      "iso context %d listen on channel %d",
 			      d->ctx, v.channel);
 		}
@@ -828,7 +828,7 @@
 
 			list_add_tail(&d->link, &ctx->context_list);
 
-			PRINT(KERN_INFO, ohci->host->id,
+			DBGMSG(ohci->host->id,
 			      "Iso context %d talk on channel %d", d->ctx,
 			      v.channel);
 		}
@@ -873,7 +873,7 @@
 			d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
 
 		if (d == NULL) return -ESRCH;
-		PRINT(KERN_INFO, ohci->host->id, "Iso context %d "
+		DBGMSG(ohci->host->id, "Iso context %d "
 		      "stop talking on channel %d", d->ctx, channel);
 		free_dma_iso_ctx(d);
 
@@ -935,7 +935,7 @@
 		else {
 			/* Wake up dma context if necessary */
 			if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-				PRINT(KERN_INFO, ohci->host->id,
+				DBGMSG(ohci->host->id,
 				      "Waking up iso dma ctx=%d", d->ctx);
 				reg_write(ohci, d->ctrlSet, 0x1000);
 			}
@@ -1106,7 +1106,7 @@
 		else {
 			/* Wake up dma context if necessary */
 			if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-				PRINT(KERN_INFO, ohci->host->id,
+				DBGMSG(ohci->host->id,
 				      "Waking up iso transmit dma ctx=%d",
 				      d->ctx);
 				put_timestamp(ohci, d, d->last_buffer);
@@ -1232,7 +1232,7 @@
 			      "is not being used", d->channel);
 		else
 			ohci->ISO_channel_usage &= ~mask;
-		PRINT(KERN_INFO, ohci->host->id, "On release: Iso %s context "
+		DBGMSG(ohci->host->id, "On release: Iso %s context "
 		      "%d stop listening on channel %d",
 		      d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit",
 		      d->ctx, d->channel);
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index afc612b..69a53d4 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -29,6 +29,11 @@
 	  libibverbs, libibcm and a hardware driver library from
 	  <http://www.openib.org>.
 
+config INFINIBAND_ADDR_TRANS
+	bool
+	depends on INFINIBAND && INET
+	default y
+
 source "drivers/infiniband/hw/mthca/Kconfig"
 source "drivers/infiniband/hw/ipath/Kconfig"
 
@@ -36,4 +41,6 @@
 
 source "drivers/infiniband/ulp/srp/Kconfig"
 
+source "drivers/infiniband/ulp/iser/Kconfig"
+
 endmenu
diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
index eea2732..c7ff58c 100644
--- a/drivers/infiniband/Makefile
+++ b/drivers/infiniband/Makefile
@@ -3,3 +3,4 @@
 obj-$(CONFIG_IPATH_CORE)		+= hw/ipath/
 obj-$(CONFIG_INFINIBAND_IPOIB)		+= ulp/ipoib/
 obj-$(CONFIG_INFINIBAND_SRP)		+= ulp/srp/
+obj-$(CONFIG_INFINIBAND_ISER)		+= ulp/iser/
diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
index ec3353f..68e73ec 100644
--- a/drivers/infiniband/core/Makefile
+++ b/drivers/infiniband/core/Makefile
@@ -1,5 +1,7 @@
+infiniband-$(CONFIG_INFINIBAND_ADDR_TRANS)	:= ib_addr.o rdma_cm.o
+
 obj-$(CONFIG_INFINIBAND) +=		ib_core.o ib_mad.o ib_sa.o \
-					ib_cm.o
+					ib_cm.o $(infiniband-y)
 obj-$(CONFIG_INFINIBAND_USER_MAD) +=	ib_umad.o
 obj-$(CONFIG_INFINIBAND_USER_ACCESS) +=	ib_uverbs.o ib_ucm.o
 
@@ -12,8 +14,13 @@
 
 ib_cm-y :=			cm.o
 
+rdma_cm-y :=			cma.o
+
+ib_addr-y :=			addr.o
+
 ib_umad-y :=			user_mad.o
 
 ib_ucm-y :=			ucm.o
 
-ib_uverbs-y :=			uverbs_main.o uverbs_cmd.o uverbs_mem.o
+ib_uverbs-y :=			uverbs_main.o uverbs_cmd.o uverbs_mem.o \
+				uverbs_marshall.o
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
new file mode 100644
index 0000000..d294bbc
--- /dev/null
+++ b/drivers/infiniband/core/addr.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
+ * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+#include <linux/mutex.h>
+#include <linux/inetdevice.h>
+#include <linux/workqueue.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+#include <net/neighbour.h>
+#include <net/route.h>
+#include <rdma/ib_addr.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("IB Address Translation");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct addr_req {
+	struct list_head list;
+	struct sockaddr src_addr;
+	struct sockaddr dst_addr;
+	struct rdma_dev_addr *addr;
+	void *context;
+	void (*callback)(int status, struct sockaddr *src_addr,
+			 struct rdma_dev_addr *addr, void *context);
+	unsigned long timeout;
+	int status;
+};
+
+static void process_req(void *data);
+
+static DEFINE_MUTEX(lock);
+static LIST_HEAD(req_list);
+static DECLARE_WORK(work, process_req, NULL);
+static struct workqueue_struct *addr_wq;
+
+static int copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev,
+		     unsigned char *dst_dev_addr)
+{
+	switch (dev->type) {
+	case ARPHRD_INFINIBAND:
+		dev_addr->dev_type = IB_NODE_CA;
+		break;
+	default:
+		return -EADDRNOTAVAIL;
+	}
+
+	memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+	memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN);
+	if (dst_dev_addr)
+		memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN);
+	return 0;
+}
+
+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
+{
+	struct net_device *dev;
+	u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+	int ret;
+
+	dev = ip_dev_find(ip);
+	if (!dev)
+		return -EADDRNOTAVAIL;
+
+	ret = copy_addr(dev_addr, dev, NULL);
+	dev_put(dev);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_translate_ip);
+
+static void set_timeout(unsigned long time)
+{
+	unsigned long delay;
+
+	cancel_delayed_work(&work);
+
+	delay = time - jiffies;
+	if ((long)delay <= 0)
+		delay = 1;
+
+	queue_delayed_work(addr_wq, &work, delay);
+}
+
+static void queue_req(struct addr_req *req)
+{
+	struct addr_req *temp_req;
+
+	mutex_lock(&lock);
+	list_for_each_entry_reverse(temp_req, &req_list, list) {
+		if (time_after(req->timeout, temp_req->timeout))
+			break;
+	}
+
+	list_add(&req->list, &temp_req->list);
+
+	if (req_list.next == &req->list)
+		set_timeout(req->timeout);
+	mutex_unlock(&lock);
+}
+
+static void addr_send_arp(struct sockaddr_in *dst_in)
+{
+	struct rtable *rt;
+	struct flowi fl;
+	u32 dst_ip = dst_in->sin_addr.s_addr;
+
+	memset(&fl, 0, sizeof fl);
+	fl.nl_u.ip4_u.daddr = dst_ip;
+	if (ip_route_output_key(&rt, &fl))
+		return;
+
+	arp_send(ARPOP_REQUEST, ETH_P_ARP, rt->rt_gateway, rt->idev->dev,
+		 rt->rt_src, NULL, rt->idev->dev->dev_addr, NULL);
+	ip_rt_put(rt);
+}
+
+static int addr_resolve_remote(struct sockaddr_in *src_in,
+			       struct sockaddr_in *dst_in,
+			       struct rdma_dev_addr *addr)
+{
+	u32 src_ip = src_in->sin_addr.s_addr;
+	u32 dst_ip = dst_in->sin_addr.s_addr;
+	struct flowi fl;
+	struct rtable *rt;
+	struct neighbour *neigh;
+	int ret;
+
+	memset(&fl, 0, sizeof fl);
+	fl.nl_u.ip4_u.daddr = dst_ip;
+	fl.nl_u.ip4_u.saddr = src_ip;
+	ret = ip_route_output_key(&rt, &fl);
+	if (ret)
+		goto out;
+
+	/* If the device does ARP internally, return 'done' */
+	if (rt->idev->dev->flags & IFF_NOARP) {
+		copy_addr(addr, rt->idev->dev, NULL);
+		goto put;
+	}
+
+	neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev);
+	if (!neigh) {
+		ret = -ENODATA;
+		goto put;
+	}
+
+	if (!(neigh->nud_state & NUD_VALID)) {
+		ret = -ENODATA;
+		goto release;
+	}
+
+	if (!src_ip) {
+		src_in->sin_family = dst_in->sin_family;
+		src_in->sin_addr.s_addr = rt->rt_src;
+	}
+
+	ret = copy_addr(addr, neigh->dev, neigh->ha);
+release:
+	neigh_release(neigh);
+put:
+	ip_rt_put(rt);
+out:
+	return ret;
+}
+
+static void process_req(void *data)
+{
+	struct addr_req *req, *temp_req;
+	struct sockaddr_in *src_in, *dst_in;
+	struct list_head done_list;
+
+	INIT_LIST_HEAD(&done_list);
+
+	mutex_lock(&lock);
+	list_for_each_entry_safe(req, temp_req, &req_list, list) {
+		if (req->status) {
+			src_in = (struct sockaddr_in *) &req->src_addr;
+			dst_in = (struct sockaddr_in *) &req->dst_addr;
+			req->status = addr_resolve_remote(src_in, dst_in,
+							  req->addr);
+		}
+		if (req->status && time_after(jiffies, req->timeout))
+			req->status = -ETIMEDOUT;
+		else if (req->status == -ENODATA)
+			continue;
+
+		list_del(&req->list);
+		list_add_tail(&req->list, &done_list);
+	}
+
+	if (!list_empty(&req_list)) {
+		req = list_entry(req_list.next, struct addr_req, list);
+		set_timeout(req->timeout);
+	}
+	mutex_unlock(&lock);
+
+	list_for_each_entry_safe(req, temp_req, &done_list, list) {
+		list_del(&req->list);
+		req->callback(req->status, &req->src_addr, req->addr,
+			      req->context);
+		kfree(req);
+	}
+}
+
+static int addr_resolve_local(struct sockaddr_in *src_in,
+			      struct sockaddr_in *dst_in,
+			      struct rdma_dev_addr *addr)
+{
+	struct net_device *dev;
+	u32 src_ip = src_in->sin_addr.s_addr;
+	u32 dst_ip = dst_in->sin_addr.s_addr;
+	int ret;
+
+	dev = ip_dev_find(dst_ip);
+	if (!dev)
+		return -EADDRNOTAVAIL;
+
+	if (ZERONET(src_ip)) {
+		src_in->sin_family = dst_in->sin_family;
+		src_in->sin_addr.s_addr = dst_ip;
+		ret = copy_addr(addr, dev, dev->dev_addr);
+	} else if (LOOPBACK(src_ip)) {
+		ret = rdma_translate_ip((struct sockaddr *)dst_in, addr);
+		if (!ret)
+			memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+	} else {
+		ret = rdma_translate_ip((struct sockaddr *)src_in, addr);
+		if (!ret)
+			memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+	}
+
+	dev_put(dev);
+	return ret;
+}
+
+int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
+		    struct rdma_dev_addr *addr, int timeout_ms,
+		    void (*callback)(int status, struct sockaddr *src_addr,
+				     struct rdma_dev_addr *addr, void *context),
+		    void *context)
+{
+	struct sockaddr_in *src_in, *dst_in;
+	struct addr_req *req;
+	int ret = 0;
+
+	req = kmalloc(sizeof *req, GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+	memset(req, 0, sizeof *req);
+
+	if (src_addr)
+		memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr));
+	memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr));
+	req->addr = addr;
+	req->callback = callback;
+	req->context = context;
+
+	src_in = (struct sockaddr_in *) &req->src_addr;
+	dst_in = (struct sockaddr_in *) &req->dst_addr;
+
+	req->status = addr_resolve_local(src_in, dst_in, addr);
+	if (req->status == -EADDRNOTAVAIL)
+		req->status = addr_resolve_remote(src_in, dst_in, addr);
+
+	switch (req->status) {
+	case 0:
+		req->timeout = jiffies;
+		queue_req(req);
+		break;
+	case -ENODATA:
+		req->timeout = msecs_to_jiffies(timeout_ms) + jiffies;
+		queue_req(req);
+		addr_send_arp(dst_in);
+		break;
+	default:
+		ret = req->status;
+		kfree(req);
+		break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_ip);
+
+void rdma_addr_cancel(struct rdma_dev_addr *addr)
+{
+	struct addr_req *req, *temp_req;
+
+	mutex_lock(&lock);
+	list_for_each_entry_safe(req, temp_req, &req_list, list) {
+		if (req->addr == addr) {
+			req->status = -ECANCELED;
+			req->timeout = jiffies;
+			list_del(&req->list);
+			list_add(&req->list, &req_list);
+			set_timeout(req->timeout);
+			break;
+		}
+	}
+	mutex_unlock(&lock);
+}
+EXPORT_SYMBOL(rdma_addr_cancel);
+
+static int addr_arp_recv(struct sk_buff *skb, struct net_device *dev,
+			 struct packet_type *pkt, struct net_device *orig_dev)
+{
+	struct arphdr *arp_hdr;
+
+	arp_hdr = (struct arphdr *) skb->nh.raw;
+
+	if (arp_hdr->ar_op == htons(ARPOP_REQUEST) ||
+	    arp_hdr->ar_op == htons(ARPOP_REPLY))
+		set_timeout(jiffies);
+
+	kfree_skb(skb);
+	return 0;
+}
+
+static struct packet_type addr_arp = {
+	.type           = __constant_htons(ETH_P_ARP),
+	.func           = addr_arp_recv,
+	.af_packet_priv = (void*) 1,
+};
+
+static int addr_init(void)
+{
+	addr_wq = create_singlethread_workqueue("ib_addr_wq");
+	if (!addr_wq)
+		return -ENOMEM;
+
+	dev_add_pack(&addr_arp);
+	return 0;
+}
+
+static void addr_cleanup(void)
+{
+	dev_remove_pack(&addr_arp);
+	destroy_workqueue(addr_wq);
+}
+
+module_init(addr_init);
+module_exit(addr_cleanup);
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 50364c0..e05ca2c 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -191,6 +191,24 @@
 }
 EXPORT_SYMBOL(ib_find_cached_pkey);
 
+int ib_get_cached_lmc(struct ib_device *device,
+		      u8                port_num,
+		      u8                *lmc)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (port_num < start_port(device) || port_num > end_port(device))
+		return -EINVAL;
+
+	read_lock_irqsave(&device->cache.lock, flags);
+	*lmc = device->cache.lmc_cache[port_num - start_port(device)];
+	read_unlock_irqrestore(&device->cache.lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(ib_get_cached_lmc);
+
 static void ib_cache_update(struct ib_device *device,
 			    u8                port)
 {
@@ -251,6 +269,8 @@
 	device->cache.pkey_cache[port - start_port(device)] = pkey_cache;
 	device->cache.gid_cache [port - start_port(device)] = gid_cache;
 
+	device->cache.lmc_cache[port - start_port(device)] = tprops->lmc;
+
 	write_unlock_irq(&device->cache.lock);
 
 	kfree(old_pkey_cache);
@@ -305,7 +325,13 @@
 		kmalloc(sizeof *device->cache.gid_cache *
 			(end_port(device) - start_port(device) + 1), GFP_KERNEL);
 
-	if (!device->cache.pkey_cache || !device->cache.gid_cache) {
+	device->cache.lmc_cache = kmalloc(sizeof *device->cache.lmc_cache *
+					  (end_port(device) -
+					   start_port(device) + 1),
+					  GFP_KERNEL);
+
+	if (!device->cache.pkey_cache || !device->cache.gid_cache ||
+	    !device->cache.lmc_cache) {
 		printk(KERN_WARNING "Couldn't allocate cache "
 		       "for %s\n", device->name);
 		goto err;
@@ -333,6 +359,7 @@
 err:
 	kfree(device->cache.pkey_cache);
 	kfree(device->cache.gid_cache);
+	kfree(device->cache.lmc_cache);
 }
 
 static void ib_cache_cleanup_one(struct ib_device *device)
@@ -349,6 +376,7 @@
 
 	kfree(device->cache.pkey_cache);
 	kfree(device->cache.gid_cache);
+	kfree(device->cache.lmc_cache);
 }
 
 static struct ib_client cache_client = {
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 86fee43..450adfe 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -32,7 +32,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: cm.c 2821 2005-07-08 17:07:28Z sean.hefty $
+ * $Id: cm.c 4311 2005-12-05 18:42:01Z sean.hefty $
  */
 
 #include <linux/completion.h>
@@ -132,6 +132,7 @@
 	/* todo: use alternate port on send failure */
 	struct cm_av av;
 	struct cm_av alt_av;
+	struct ib_cm_compare_data *compare_data;
 
 	void *private_data;
 	__be64 tid;
@@ -253,23 +254,13 @@
 	cm_id_priv->private_data_len = private_data_len;
 }
 
-static void cm_set_ah_attr(struct ib_ah_attr *ah_attr, u8 port_num,
-			   u16 dlid, u8 sl, u16 src_path_bits)
-{
-	memset(ah_attr, 0, sizeof ah_attr);
-	ah_attr->dlid = dlid;
-	ah_attr->sl = sl;
-	ah_attr->src_path_bits = src_path_bits;
-	ah_attr->port_num = port_num;
-}
-
-static void cm_init_av_for_response(struct cm_port *port,
-				    struct ib_wc *wc, struct cm_av *av)
+static void cm_init_av_for_response(struct cm_port *port, struct ib_wc *wc,
+				    struct ib_grh *grh, struct cm_av *av)
 {
 	av->port = port;
 	av->pkey_index = wc->pkey_index;
-	cm_set_ah_attr(&av->ah_attr, port->port_num, wc->slid,
-		       wc->sl, wc->dlid_path_bits);
+	ib_init_ah_from_wc(port->cm_dev->device, port->port_num, wc,
+			   grh, &av->ah_attr);
 }
 
 static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
@@ -299,9 +290,8 @@
 		return ret;
 
 	av->port = port;
-	cm_set_ah_attr(&av->ah_attr, av->port->port_num,
-		       be16_to_cpu(path->dlid), path->sl,
-		       be16_to_cpu(path->slid) & 0x7F);
+	ib_init_ah_from_path(cm_dev->device, port->port_num, path,
+			     &av->ah_attr);
 	av->packet_life_time = path->packet_life_time;
 	return 0;
 }
@@ -357,6 +347,41 @@
 	return cm_id_priv;
 }
 
+static void cm_mask_copy(u8 *dst, u8 *src, u8 *mask)
+{
+	int i;
+
+	for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++)
+		((unsigned long *) dst)[i] = ((unsigned long *) src)[i] &
+					     ((unsigned long *) mask)[i];
+}
+
+static int cm_compare_data(struct ib_cm_compare_data *src_data,
+			   struct ib_cm_compare_data *dst_data)
+{
+	u8 src[IB_CM_COMPARE_SIZE];
+	u8 dst[IB_CM_COMPARE_SIZE];
+
+	if (!src_data || !dst_data)
+		return 0;
+
+	cm_mask_copy(src, src_data->data, dst_data->mask);
+	cm_mask_copy(dst, dst_data->data, src_data->mask);
+	return memcmp(src, dst, IB_CM_COMPARE_SIZE);
+}
+
+static int cm_compare_private_data(u8 *private_data,
+				   struct ib_cm_compare_data *dst_data)
+{
+	u8 src[IB_CM_COMPARE_SIZE];
+
+	if (!dst_data)
+		return 0;
+
+	cm_mask_copy(src, private_data, dst_data->mask);
+	return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
+}
+
 static struct cm_id_private * cm_insert_listen(struct cm_id_private *cm_id_priv)
 {
 	struct rb_node **link = &cm.listen_service_table.rb_node;
@@ -364,14 +389,18 @@
 	struct cm_id_private *cur_cm_id_priv;
 	__be64 service_id = cm_id_priv->id.service_id;
 	__be64 service_mask = cm_id_priv->id.service_mask;
+	int data_cmp;
 
 	while (*link) {
 		parent = *link;
 		cur_cm_id_priv = rb_entry(parent, struct cm_id_private,
 					  service_node);
+		data_cmp = cm_compare_data(cm_id_priv->compare_data,
+					   cur_cm_id_priv->compare_data);
 		if ((cur_cm_id_priv->id.service_mask & service_id) ==
 		    (service_mask & cur_cm_id_priv->id.service_id) &&
-		    (cm_id_priv->id.device == cur_cm_id_priv->id.device))
+		    (cm_id_priv->id.device == cur_cm_id_priv->id.device) &&
+		    !data_cmp)
 			return cur_cm_id_priv;
 
 		if (cm_id_priv->id.device < cur_cm_id_priv->id.device)
@@ -380,6 +409,10 @@
 			link = &(*link)->rb_right;
 		else if (service_id < cur_cm_id_priv->id.service_id)
 			link = &(*link)->rb_left;
+		else if (service_id > cur_cm_id_priv->id.service_id)
+			link = &(*link)->rb_right;
+		else if (data_cmp < 0)
+			link = &(*link)->rb_left;
 		else
 			link = &(*link)->rb_right;
 	}
@@ -389,16 +422,20 @@
 }
 
 static struct cm_id_private * cm_find_listen(struct ib_device *device,
-					     __be64 service_id)
+					     __be64 service_id,
+					     u8 *private_data)
 {
 	struct rb_node *node = cm.listen_service_table.rb_node;
 	struct cm_id_private *cm_id_priv;
+	int data_cmp;
 
 	while (node) {
 		cm_id_priv = rb_entry(node, struct cm_id_private, service_node);
+		data_cmp = cm_compare_private_data(private_data,
+						   cm_id_priv->compare_data);
 		if ((cm_id_priv->id.service_mask & service_id) ==
 		     cm_id_priv->id.service_id &&
-		    (cm_id_priv->id.device == device))
+		    (cm_id_priv->id.device == device) && !data_cmp)
 			return cm_id_priv;
 
 		if (device < cm_id_priv->id.device)
@@ -407,6 +444,10 @@
 			node = node->rb_right;
 		else if (service_id < cm_id_priv->id.service_id)
 			node = node->rb_left;
+		else if (service_id > cm_id_priv->id.service_id)
+			node = node->rb_right;
+		else if (data_cmp < 0)
+			node = node->rb_left;
 		else
 			node = node->rb_right;
 	}
@@ -730,15 +771,14 @@
 	wait_for_completion(&cm_id_priv->comp);
 	while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
 		cm_free_work(work);
-	if (cm_id_priv->private_data && cm_id_priv->private_data_len)
-		kfree(cm_id_priv->private_data);
+	kfree(cm_id_priv->compare_data);
+	kfree(cm_id_priv->private_data);
 	kfree(cm_id_priv);
 }
 EXPORT_SYMBOL(ib_destroy_cm_id);
 
-int ib_cm_listen(struct ib_cm_id *cm_id,
-		 __be64 service_id,
-		 __be64 service_mask)
+int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask,
+		 struct ib_cm_compare_data *compare_data)
 {
 	struct cm_id_private *cm_id_priv, *cur_cm_id_priv;
 	unsigned long flags;
@@ -752,7 +792,19 @@
 		return -EINVAL;
 
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
-	BUG_ON(cm_id->state != IB_CM_IDLE);
+	if (cm_id->state != IB_CM_IDLE)
+		return -EINVAL;
+
+	if (compare_data) {
+		cm_id_priv->compare_data = kzalloc(sizeof *compare_data,
+						   GFP_KERNEL);
+		if (!cm_id_priv->compare_data)
+			return -ENOMEM;
+		cm_mask_copy(cm_id_priv->compare_data->data,
+			     compare_data->data, compare_data->mask);
+		memcpy(cm_id_priv->compare_data->mask, compare_data->mask,
+		       IB_CM_COMPARE_SIZE);
+	}
 
 	cm_id->state = IB_CM_LISTEN;
 
@@ -769,6 +821,8 @@
 
 	if (cur_cm_id_priv) {
 		cm_id->state = IB_CM_IDLE;
+		kfree(cm_id_priv->compare_data);
+		cm_id_priv->compare_data = NULL;
 		ret = -EBUSY;
 	}
 	return ret;
@@ -1241,7 +1295,8 @@
 
 	/* Find matching listen request. */
 	listen_cm_id_priv = cm_find_listen(cm_id_priv->id.device,
-					   req_msg->service_id);
+					   req_msg->service_id,
+					   req_msg->private_data);
 	if (!listen_cm_id_priv) {
 		spin_unlock_irqrestore(&cm.lock, flags);
 		cm_issue_rej(work->port, work->mad_recv_wc,
@@ -1276,6 +1331,7 @@
 	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
 	cm_id_priv->id.remote_id = req_msg->local_comm_id;
 	cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
+				work->mad_recv_wc->recv_buf.grh,
 				&cm_id_priv->av);
 	cm_id_priv->timewait_info = cm_create_timewait_info(cm_id_priv->
 							    id.local_id);
@@ -2549,7 +2605,7 @@
 	cm_format_mad_hdr(&sidr_req_msg->hdr, CM_SIDR_REQ_ATTR_ID,
 			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_SIDR));
 	sidr_req_msg->request_id = cm_id_priv->id.local_id;
-	sidr_req_msg->pkey = cpu_to_be16(param->pkey);
+	sidr_req_msg->pkey = cpu_to_be16(param->path->pkey);
 	sidr_req_msg->service_id = param->service_id;
 
 	if (param->private_data && param->private_data_len)
@@ -2641,6 +2697,7 @@
 	cm_id_priv->av.dgid.global.subnet_prefix = cpu_to_be64(wc->slid);
 	cm_id_priv->av.dgid.global.interface_id = 0;
 	cm_init_av_for_response(work->port, work->mad_recv_wc->wc,
+				work->mad_recv_wc->recv_buf.grh,
 				&cm_id_priv->av);
 	cm_id_priv->id.remote_id = sidr_req_msg->request_id;
 	cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
@@ -2654,7 +2711,8 @@
 		goto out; /* Duplicate message. */
 	}
 	cur_cm_id_priv = cm_find_listen(cm_id->device,
-					sidr_req_msg->service_id);
+					sidr_req_msg->service_id,
+					sidr_req_msg->private_data);
 	if (!cur_cm_id_priv) {
 		rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
 		spin_unlock_irqrestore(&cm.lock, flags);
@@ -3291,7 +3349,6 @@
 
 static void __exit ib_cm_cleanup(void)
 {
-	flush_workqueue(cm.wq);
 	destroy_workqueue(cm.wq);
 	ib_unregister_client(&cm_client);
 	idr_destroy(&cm.local_id_table);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
new file mode 100644
index 0000000..863f64b
--- /dev/null
+++ b/drivers/infiniband/core/cma.c
@@ -0,0 +1,1927 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
+ * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved.
+ * Copyright (c) 2005-2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#include <linux/completion.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/mutex.h>
+#include <linux/random.h>
+#include <linux/idr.h>
+
+#include <net/tcp.h>
+
+#include <rdma/rdma_cm.h>
+#include <rdma/rdma_cm_ib.h>
+#include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
+#include <rdma/ib_sa.h>
+
+MODULE_AUTHOR("Sean Hefty");
+MODULE_DESCRIPTION("Generic RDMA CM Agent");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define CMA_CM_RESPONSE_TIMEOUT 20
+#define CMA_MAX_CM_RETRIES 3
+
+static void cma_add_one(struct ib_device *device);
+static void cma_remove_one(struct ib_device *device);
+
+static struct ib_client cma_client = {
+	.name   = "cma",
+	.add    = cma_add_one,
+	.remove = cma_remove_one
+};
+
+static LIST_HEAD(dev_list);
+static LIST_HEAD(listen_any_list);
+static DEFINE_MUTEX(lock);
+static struct workqueue_struct *cma_wq;
+static DEFINE_IDR(sdp_ps);
+static DEFINE_IDR(tcp_ps);
+
+struct cma_device {
+	struct list_head	list;
+	struct ib_device	*device;
+	__be64			node_guid;
+	struct completion	comp;
+	atomic_t		refcount;
+	struct list_head	id_list;
+};
+
+enum cma_state {
+	CMA_IDLE,
+	CMA_ADDR_QUERY,
+	CMA_ADDR_RESOLVED,
+	CMA_ROUTE_QUERY,
+	CMA_ROUTE_RESOLVED,
+	CMA_CONNECT,
+	CMA_DISCONNECT,
+	CMA_ADDR_BOUND,
+	CMA_LISTEN,
+	CMA_DEVICE_REMOVAL,
+	CMA_DESTROYING
+};
+
+struct rdma_bind_list {
+	struct idr		*ps;
+	struct hlist_head	owners;
+	unsigned short		port;
+};
+
+/*
+ * Device removal can occur at anytime, so we need extra handling to
+ * serialize notifying the user of device removal with other callbacks.
+ * We do this by disabling removal notification while a callback is in process,
+ * and reporting it after the callback completes.
+ */
+struct rdma_id_private {
+	struct rdma_cm_id	id;
+
+	struct rdma_bind_list	*bind_list;
+	struct hlist_node	node;
+	struct list_head	list;
+	struct list_head	listen_list;
+	struct cma_device	*cma_dev;
+
+	enum cma_state		state;
+	spinlock_t		lock;
+	struct completion	comp;
+	atomic_t		refcount;
+	wait_queue_head_t	wait_remove;
+	atomic_t		dev_remove;
+
+	int			backlog;
+	int			timeout_ms;
+	struct ib_sa_query	*query;
+	int			query_id;
+	union {
+		struct ib_cm_id	*ib;
+	} cm_id;
+
+	u32			seq_num;
+	u32			qp_num;
+	enum ib_qp_type		qp_type;
+	u8			srq;
+};
+
+struct cma_work {
+	struct work_struct	work;
+	struct rdma_id_private	*id;
+	enum cma_state		old_state;
+	enum cma_state		new_state;
+	struct rdma_cm_event	event;
+};
+
+union cma_ip_addr {
+	struct in6_addr ip6;
+	struct {
+		__u32 pad[3];
+		__u32 addr;
+	} ip4;
+};
+
+struct cma_hdr {
+	u8 cma_version;
+	u8 ip_version;	/* IP version: 7:4 */
+	__u16 port;
+	union cma_ip_addr src_addr;
+	union cma_ip_addr dst_addr;
+};
+
+struct sdp_hh {
+	u8 bsdh[16];
+	u8 sdp_version; /* Major version: 7:4 */
+	u8 ip_version;	/* IP version: 7:4 */
+	u8 sdp_specific1[10];
+	__u16 port;
+	__u16 sdp_specific2;
+	union cma_ip_addr src_addr;
+	union cma_ip_addr dst_addr;
+};
+
+struct sdp_hah {
+	u8 bsdh[16];
+	u8 sdp_version;
+};
+
+#define CMA_VERSION 0x00
+#define SDP_MAJ_VERSION 0x2
+
+static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&id_priv->lock, flags);
+	ret = (id_priv->state == comp);
+	spin_unlock_irqrestore(&id_priv->lock, flags);
+	return ret;
+}
+
+static int cma_comp_exch(struct rdma_id_private *id_priv,
+			 enum cma_state comp, enum cma_state exch)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&id_priv->lock, flags);
+	if ((ret = (id_priv->state == comp)))
+		id_priv->state = exch;
+	spin_unlock_irqrestore(&id_priv->lock, flags);
+	return ret;
+}
+
+static enum cma_state cma_exch(struct rdma_id_private *id_priv,
+			       enum cma_state exch)
+{
+	unsigned long flags;
+	enum cma_state old;
+
+	spin_lock_irqsave(&id_priv->lock, flags);
+	old = id_priv->state;
+	id_priv->state = exch;
+	spin_unlock_irqrestore(&id_priv->lock, flags);
+	return old;
+}
+
+static inline u8 cma_get_ip_ver(struct cma_hdr *hdr)
+{
+	return hdr->ip_version >> 4;
+}
+
+static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver)
+{
+	hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF);
+}
+
+static inline u8 sdp_get_majv(u8 sdp_version)
+{
+	return sdp_version >> 4;
+}
+
+static inline u8 sdp_get_ip_ver(struct sdp_hh *hh)
+{
+	return hh->ip_version >> 4;
+}
+
+static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver)
+{
+	hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF);
+}
+
+static void cma_attach_to_dev(struct rdma_id_private *id_priv,
+			      struct cma_device *cma_dev)
+{
+	atomic_inc(&cma_dev->refcount);
+	id_priv->cma_dev = cma_dev;
+	id_priv->id.device = cma_dev->device;
+	list_add_tail(&id_priv->list, &cma_dev->id_list);
+}
+
+static inline void cma_deref_dev(struct cma_device *cma_dev)
+{
+	if (atomic_dec_and_test(&cma_dev->refcount))
+		complete(&cma_dev->comp);
+}
+
+static void cma_detach_from_dev(struct rdma_id_private *id_priv)
+{
+	list_del(&id_priv->list);
+	cma_deref_dev(id_priv->cma_dev);
+	id_priv->cma_dev = NULL;
+}
+
+static int cma_acquire_ib_dev(struct rdma_id_private *id_priv)
+{
+	struct cma_device *cma_dev;
+	union ib_gid *gid;
+	int ret = -ENODEV;
+
+	gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr);
+
+	mutex_lock(&lock);
+	list_for_each_entry(cma_dev, &dev_list, list) {
+		ret = ib_find_cached_gid(cma_dev->device, gid,
+					 &id_priv->id.port_num, NULL);
+		if (!ret) {
+			cma_attach_to_dev(id_priv, cma_dev);
+			break;
+		}
+	}
+	mutex_unlock(&lock);
+	return ret;
+}
+
+static int cma_acquire_dev(struct rdma_id_private *id_priv)
+{
+	switch (id_priv->id.route.addr.dev_addr.dev_type) {
+	case IB_NODE_CA:
+		return cma_acquire_ib_dev(id_priv);
+	default:
+		return -ENODEV;
+	}
+}
+
+static void cma_deref_id(struct rdma_id_private *id_priv)
+{
+	if (atomic_dec_and_test(&id_priv->refcount))
+		complete(&id_priv->comp);
+}
+
+static void cma_release_remove(struct rdma_id_private *id_priv)
+{
+	if (atomic_dec_and_test(&id_priv->dev_remove))
+		wake_up(&id_priv->wait_remove);
+}
+
+struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
+				  void *context, enum rdma_port_space ps)
+{
+	struct rdma_id_private *id_priv;
+
+	id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL);
+	if (!id_priv)
+		return ERR_PTR(-ENOMEM);
+
+	id_priv->state = CMA_IDLE;
+	id_priv->id.context = context;
+	id_priv->id.event_handler = event_handler;
+	id_priv->id.ps = ps;
+	spin_lock_init(&id_priv->lock);
+	init_completion(&id_priv->comp);
+	atomic_set(&id_priv->refcount, 1);
+	init_waitqueue_head(&id_priv->wait_remove);
+	atomic_set(&id_priv->dev_remove, 0);
+	INIT_LIST_HEAD(&id_priv->listen_list);
+	get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
+
+	return &id_priv->id;
+}
+EXPORT_SYMBOL(rdma_create_id);
+
+static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+{
+	struct ib_qp_attr qp_attr;
+	struct rdma_dev_addr *dev_addr;
+	int ret;
+
+	dev_addr = &id_priv->id.route.addr.dev_addr;
+	ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
+				  ib_addr_get_pkey(dev_addr),
+				  &qp_attr.pkey_index);
+	if (ret)
+		return ret;
+
+	qp_attr.qp_state = IB_QPS_INIT;
+	qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE;
+	qp_attr.port_num = id_priv->id.port_num;
+	return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS |
+					  IB_QP_PKEY_INDEX | IB_QP_PORT);
+}
+
+int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
+		   struct ib_qp_init_attr *qp_init_attr)
+{
+	struct rdma_id_private *id_priv;
+	struct ib_qp *qp;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (id->device != pd->device)
+		return -EINVAL;
+
+	qp = ib_create_qp(pd, qp_init_attr);
+	if (IS_ERR(qp))
+		return PTR_ERR(qp);
+
+	switch (id->device->node_type) {
+	case IB_NODE_CA:
+		ret = cma_init_ib_qp(id_priv, qp);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
+	if (ret)
+		goto err;
+
+	id->qp = qp;
+	id_priv->qp_num = qp->qp_num;
+	id_priv->qp_type = qp->qp_type;
+	id_priv->srq = (qp->srq != NULL);
+	return 0;
+err:
+	ib_destroy_qp(qp);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_create_qp);
+
+void rdma_destroy_qp(struct rdma_cm_id *id)
+{
+	ib_destroy_qp(id->qp);
+}
+EXPORT_SYMBOL(rdma_destroy_qp);
+
+static int cma_modify_qp_rtr(struct rdma_cm_id *id)
+{
+	struct ib_qp_attr qp_attr;
+	int qp_attr_mask, ret;
+
+	if (!id->qp)
+		return 0;
+
+	/* Need to update QP attributes from default values. */
+	qp_attr.qp_state = IB_QPS_INIT;
+	ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+	if (ret)
+		return ret;
+
+	ret = ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+	if (ret)
+		return ret;
+
+	qp_attr.qp_state = IB_QPS_RTR;
+	ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+	if (ret)
+		return ret;
+
+	return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+}
+
+static int cma_modify_qp_rts(struct rdma_cm_id *id)
+{
+	struct ib_qp_attr qp_attr;
+	int qp_attr_mask, ret;
+
+	if (!id->qp)
+		return 0;
+
+	qp_attr.qp_state = IB_QPS_RTS;
+	ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask);
+	if (ret)
+		return ret;
+
+	return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask);
+}
+
+static int cma_modify_qp_err(struct rdma_cm_id *id)
+{
+	struct ib_qp_attr qp_attr;
+
+	if (!id->qp)
+		return 0;
+
+	qp_attr.qp_state = IB_QPS_ERR;
+	return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE);
+}
+
+int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
+		       int *qp_attr_mask)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	switch (id_priv->id.device->node_type) {
+	case IB_NODE_CA:
+		ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr,
+					 qp_attr_mask);
+		if (qp_attr->qp_state == IB_QPS_RTR)
+			qp_attr->rq_psn = id_priv->seq_num;
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(rdma_init_qp_attr);
+
+static inline int cma_zero_addr(struct sockaddr *addr)
+{
+	struct in6_addr *ip6;
+
+	if (addr->sa_family == AF_INET)
+		return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
+	else {
+		ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
+		return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
+			ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0;
+	}
+}
+
+static inline int cma_loopback_addr(struct sockaddr *addr)
+{
+	return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
+}
+
+static inline int cma_any_addr(struct sockaddr *addr)
+{
+	return cma_zero_addr(addr) || cma_loopback_addr(addr);
+}
+
+static inline int cma_any_port(struct sockaddr *addr)
+{
+	return !((struct sockaddr_in *) addr)->sin_port;
+}
+
+static int cma_get_net_info(void *hdr, enum rdma_port_space ps,
+			    u8 *ip_ver, __u16 *port,
+			    union cma_ip_addr **src, union cma_ip_addr **dst)
+{
+	switch (ps) {
+	case RDMA_PS_SDP:
+		if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) !=
+		    SDP_MAJ_VERSION)
+			return -EINVAL;
+
+		*ip_ver	= sdp_get_ip_ver(hdr);
+		*port	= ((struct sdp_hh *) hdr)->port;
+		*src	= &((struct sdp_hh *) hdr)->src_addr;
+		*dst	= &((struct sdp_hh *) hdr)->dst_addr;
+		break;
+	default:
+		if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION)
+			return -EINVAL;
+
+		*ip_ver	= cma_get_ip_ver(hdr);
+		*port	= ((struct cma_hdr *) hdr)->port;
+		*src	= &((struct cma_hdr *) hdr)->src_addr;
+		*dst	= &((struct cma_hdr *) hdr)->dst_addr;
+		break;
+	}
+
+	if (*ip_ver != 4 && *ip_ver != 6)
+		return -EINVAL;
+	return 0;
+}
+
+static void cma_save_net_info(struct rdma_addr *addr,
+			      struct rdma_addr *listen_addr,
+			      u8 ip_ver, __u16 port,
+			      union cma_ip_addr *src, union cma_ip_addr *dst)
+{
+	struct sockaddr_in *listen4, *ip4;
+	struct sockaddr_in6 *listen6, *ip6;
+
+	switch (ip_ver) {
+	case 4:
+		listen4 = (struct sockaddr_in *) &listen_addr->src_addr;
+		ip4 = (struct sockaddr_in *) &addr->src_addr;
+		ip4->sin_family = listen4->sin_family;
+		ip4->sin_addr.s_addr = dst->ip4.addr;
+		ip4->sin_port = listen4->sin_port;
+
+		ip4 = (struct sockaddr_in *) &addr->dst_addr;
+		ip4->sin_family = listen4->sin_family;
+		ip4->sin_addr.s_addr = src->ip4.addr;
+		ip4->sin_port = port;
+		break;
+	case 6:
+		listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr;
+		ip6 = (struct sockaddr_in6 *) &addr->src_addr;
+		ip6->sin6_family = listen6->sin6_family;
+		ip6->sin6_addr = dst->ip6;
+		ip6->sin6_port = listen6->sin6_port;
+
+		ip6 = (struct sockaddr_in6 *) &addr->dst_addr;
+		ip6->sin6_family = listen6->sin6_family;
+		ip6->sin6_addr = src->ip6;
+		ip6->sin6_port = port;
+		break;
+	default:
+		break;
+	}
+}
+
+static inline int cma_user_data_offset(enum rdma_port_space ps)
+{
+	switch (ps) {
+	case RDMA_PS_SDP:
+		return 0;
+	default:
+		return sizeof(struct cma_hdr);
+	}
+}
+
+static int cma_notify_user(struct rdma_id_private *id_priv,
+			   enum rdma_cm_event_type type, int status,
+			   void *data, u8 data_len)
+{
+	struct rdma_cm_event event;
+
+	event.event = type;
+	event.status = status;
+	event.private_data = data;
+	event.private_data_len = data_len;
+
+	return id_priv->id.event_handler(&id_priv->id, &event);
+}
+
+static void cma_cancel_route(struct rdma_id_private *id_priv)
+{
+	switch (id_priv->id.device->node_type) {
+	case IB_NODE_CA:
+		if (id_priv->query)
+			ib_sa_cancel_query(id_priv->query_id, id_priv->query);
+		break;
+	default:
+		break;
+	}
+}
+
+static inline int cma_internal_listen(struct rdma_id_private *id_priv)
+{
+	return (id_priv->state == CMA_LISTEN) && id_priv->cma_dev &&
+	       cma_any_addr(&id_priv->id.route.addr.src_addr);
+}
+
+static void cma_destroy_listen(struct rdma_id_private *id_priv)
+{
+	cma_exch(id_priv, CMA_DESTROYING);
+
+	if (id_priv->cma_dev) {
+		switch (id_priv->id.device->node_type) {
+		case IB_NODE_CA:
+	 		if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+				ib_destroy_cm_id(id_priv->cm_id.ib);
+			break;
+		default:
+			break;
+		}
+		cma_detach_from_dev(id_priv);
+	}
+	list_del(&id_priv->listen_list);
+
+	cma_deref_id(id_priv);
+	wait_for_completion(&id_priv->comp);
+
+	kfree(id_priv);
+}
+
+static void cma_cancel_listens(struct rdma_id_private *id_priv)
+{
+	struct rdma_id_private *dev_id_priv;
+
+	mutex_lock(&lock);
+	list_del(&id_priv->list);
+
+	while (!list_empty(&id_priv->listen_list)) {
+		dev_id_priv = list_entry(id_priv->listen_list.next,
+					 struct rdma_id_private, listen_list);
+		cma_destroy_listen(dev_id_priv);
+	}
+	mutex_unlock(&lock);
+}
+
+static void cma_cancel_operation(struct rdma_id_private *id_priv,
+				 enum cma_state state)
+{
+	switch (state) {
+	case CMA_ADDR_QUERY:
+		rdma_addr_cancel(&id_priv->id.route.addr.dev_addr);
+		break;
+	case CMA_ROUTE_QUERY:
+		cma_cancel_route(id_priv);
+		break;
+	case CMA_LISTEN:
+		if (cma_any_addr(&id_priv->id.route.addr.src_addr) &&
+		    !id_priv->cma_dev)
+			cma_cancel_listens(id_priv);
+		break;
+	default:
+		break;
+	}
+}
+
+static void cma_release_port(struct rdma_id_private *id_priv)
+{
+	struct rdma_bind_list *bind_list = id_priv->bind_list;
+
+	if (!bind_list)
+		return;
+
+	mutex_lock(&lock);
+	hlist_del(&id_priv->node);
+	if (hlist_empty(&bind_list->owners)) {
+		idr_remove(bind_list->ps, bind_list->port);
+		kfree(bind_list);
+	}
+	mutex_unlock(&lock);
+}
+
+void rdma_destroy_id(struct rdma_cm_id *id)
+{
+	struct rdma_id_private *id_priv;
+	enum cma_state state;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	state = cma_exch(id_priv, CMA_DESTROYING);
+	cma_cancel_operation(id_priv, state);
+
+	if (id_priv->cma_dev) {
+		switch (id->device->node_type) {
+		case IB_NODE_CA:
+	 		if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
+				ib_destroy_cm_id(id_priv->cm_id.ib);
+			break;
+		default:
+			break;
+		}
+	  	mutex_lock(&lock);
+		cma_detach_from_dev(id_priv);
+		mutex_unlock(&lock);
+	}
+
+	cma_release_port(id_priv);
+	cma_deref_id(id_priv);
+	wait_for_completion(&id_priv->comp);
+
+	kfree(id_priv->id.route.path_rec);
+	kfree(id_priv);
+}
+EXPORT_SYMBOL(rdma_destroy_id);
+
+static int cma_rep_recv(struct rdma_id_private *id_priv)
+{
+	int ret;
+
+	ret = cma_modify_qp_rtr(&id_priv->id);
+	if (ret)
+		goto reject;
+
+	ret = cma_modify_qp_rts(&id_priv->id);
+	if (ret)
+		goto reject;
+
+	ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0);
+	if (ret)
+		goto reject;
+
+	return 0;
+reject:
+	cma_modify_qp_err(&id_priv->id);
+	ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
+		       NULL, 0, NULL, 0);
+	return ret;
+}
+
+static int cma_verify_rep(struct rdma_id_private *id_priv, void *data)
+{
+	if (id_priv->id.ps == RDMA_PS_SDP &&
+	    sdp_get_majv(((struct sdp_hah *) data)->sdp_version) !=
+	    SDP_MAJ_VERSION)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int cma_rtu_recv(struct rdma_id_private *id_priv)
+{
+	int ret;
+
+	ret = cma_modify_qp_rts(&id_priv->id);
+	if (ret)
+		goto reject;
+
+	return 0;
+reject:
+	cma_modify_qp_err(&id_priv->id);
+	ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED,
+		       NULL, 0, NULL, 0);
+	return ret;
+}
+
+static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
+{
+	struct rdma_id_private *id_priv = cm_id->context;
+	enum rdma_cm_event_type event;
+	u8 private_data_len = 0;
+	int ret = 0, status = 0;
+
+	atomic_inc(&id_priv->dev_remove);
+	if (!cma_comp(id_priv, CMA_CONNECT))
+		goto out;
+
+	switch (ib_event->event) {
+	case IB_CM_REQ_ERROR:
+	case IB_CM_REP_ERROR:
+		event = RDMA_CM_EVENT_UNREACHABLE;
+		status = -ETIMEDOUT;
+		break;
+	case IB_CM_REP_RECEIVED:
+		status = cma_verify_rep(id_priv, ib_event->private_data);
+		if (status)
+			event = RDMA_CM_EVENT_CONNECT_ERROR;
+		else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) {
+			status = cma_rep_recv(id_priv);
+			event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
+					 RDMA_CM_EVENT_ESTABLISHED;
+		} else
+			event = RDMA_CM_EVENT_CONNECT_RESPONSE;
+		private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE;
+		break;
+	case IB_CM_RTU_RECEIVED:
+		status = cma_rtu_recv(id_priv);
+		event = status ? RDMA_CM_EVENT_CONNECT_ERROR :
+				 RDMA_CM_EVENT_ESTABLISHED;
+		break;
+	case IB_CM_DREQ_ERROR:
+		status = -ETIMEDOUT; /* fall through */
+	case IB_CM_DREQ_RECEIVED:
+	case IB_CM_DREP_RECEIVED:
+		if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT))
+			goto out;
+		event = RDMA_CM_EVENT_DISCONNECTED;
+		break;
+	case IB_CM_TIMEWAIT_EXIT:
+	case IB_CM_MRA_RECEIVED:
+		/* ignore event */
+		goto out;
+	case IB_CM_REJ_RECEIVED:
+		cma_modify_qp_err(&id_priv->id);
+		status = ib_event->param.rej_rcvd.reason;
+		event = RDMA_CM_EVENT_REJECTED;
+		break;
+	default:
+		printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d",
+		       ib_event->event);
+		goto out;
+	}
+
+	ret = cma_notify_user(id_priv, event, status, ib_event->private_data,
+			      private_data_len);
+	if (ret) {
+		/* Destroy the CM ID by returning a non-zero value. */
+		id_priv->cm_id.ib = NULL;
+		cma_exch(id_priv, CMA_DESTROYING);
+		cma_release_remove(id_priv);
+		rdma_destroy_id(&id_priv->id);
+		return ret;
+	}
+out:
+	cma_release_remove(id_priv);
+	return ret;
+}
+
+static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id,
+					  struct ib_cm_event *ib_event)
+{
+	struct rdma_id_private *id_priv;
+	struct rdma_cm_id *id;
+	struct rdma_route *rt;
+	union cma_ip_addr *src, *dst;
+	__u16 port;
+	u8 ip_ver;
+
+	id = rdma_create_id(listen_id->event_handler, listen_id->context,
+			    listen_id->ps);
+	if (IS_ERR(id))
+		return NULL;
+
+	rt = &id->route;
+	rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
+	rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL);
+	if (!rt->path_rec)
+		goto err;
+
+	if (cma_get_net_info(ib_event->private_data, listen_id->ps,
+			     &ip_ver, &port, &src, &dst))
+		goto err;
+
+	cma_save_net_info(&id->route.addr, &listen_id->route.addr,
+			  ip_ver, port, src, dst);
+	rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path;
+	if (rt->num_paths == 2)
+		rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path;
+
+	ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid);
+	ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid);
+	ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey));
+	rt->addr.dev_addr.dev_type = IB_NODE_CA;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	id_priv->state = CMA_CONNECT;
+	return id_priv;
+err:
+	rdma_destroy_id(id);
+	return NULL;
+}
+
+static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
+{
+	struct rdma_id_private *listen_id, *conn_id;
+	int offset, ret;
+
+	listen_id = cm_id->context;
+	atomic_inc(&listen_id->dev_remove);
+	if (!cma_comp(listen_id, CMA_LISTEN)) {
+		ret = -ECONNABORTED;
+		goto out;
+	}
+
+	conn_id = cma_new_id(&listen_id->id, ib_event);
+	if (!conn_id) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	atomic_inc(&conn_id->dev_remove);
+	ret = cma_acquire_ib_dev(conn_id);
+	if (ret) {
+		ret = -ENODEV;
+		cma_release_remove(conn_id);
+		rdma_destroy_id(&conn_id->id);
+		goto out;
+	}
+
+	conn_id->cm_id.ib = cm_id;
+	cm_id->context = conn_id;
+	cm_id->cm_handler = cma_ib_handler;
+
+	offset = cma_user_data_offset(listen_id->id.ps);
+	ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0,
+			      ib_event->private_data + offset,
+			      IB_CM_REQ_PRIVATE_DATA_SIZE - offset);
+	if (ret) {
+		/* Destroy the CM ID by returning a non-zero value. */
+		conn_id->cm_id.ib = NULL;
+		cma_exch(conn_id, CMA_DESTROYING);
+		cma_release_remove(conn_id);
+		rdma_destroy_id(&conn_id->id);
+	}
+out:
+	cma_release_remove(listen_id);
+	return ret;
+}
+
+static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr)
+{
+	return cpu_to_be64(((u64)ps << 16) +
+	       be16_to_cpu(((struct sockaddr_in *) addr)->sin_port));
+}
+
+static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr,
+				 struct ib_cm_compare_data *compare)
+{
+	struct cma_hdr *cma_data, *cma_mask;
+	struct sdp_hh *sdp_data, *sdp_mask;
+	__u32 ip4_addr;
+	struct in6_addr ip6_addr;
+
+	memset(compare, 0, sizeof *compare);
+	cma_data = (void *) compare->data;
+	cma_mask = (void *) compare->mask;
+	sdp_data = (void *) compare->data;
+	sdp_mask = (void *) compare->mask;
+
+	switch (addr->sa_family) {
+	case AF_INET:
+		ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+		if (ps == RDMA_PS_SDP) {
+			sdp_set_ip_ver(sdp_data, 4);
+			sdp_set_ip_ver(sdp_mask, 0xF);
+			sdp_data->dst_addr.ip4.addr = ip4_addr;
+			sdp_mask->dst_addr.ip4.addr = ~0;
+		} else {
+			cma_set_ip_ver(cma_data, 4);
+			cma_set_ip_ver(cma_mask, 0xF);
+			cma_data->dst_addr.ip4.addr = ip4_addr;
+			cma_mask->dst_addr.ip4.addr = ~0;
+		}
+		break;
+	case AF_INET6:
+		ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr;
+		if (ps == RDMA_PS_SDP) {
+			sdp_set_ip_ver(sdp_data, 6);
+			sdp_set_ip_ver(sdp_mask, 0xF);
+			sdp_data->dst_addr.ip6 = ip6_addr;
+			memset(&sdp_mask->dst_addr.ip6, 0xFF,
+			       sizeof sdp_mask->dst_addr.ip6);
+		} else {
+			cma_set_ip_ver(cma_data, 6);
+			cma_set_ip_ver(cma_mask, 0xF);
+			cma_data->dst_addr.ip6 = ip6_addr;
+			memset(&cma_mask->dst_addr.ip6, 0xFF,
+			       sizeof cma_mask->dst_addr.ip6);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static int cma_ib_listen(struct rdma_id_private *id_priv)
+{
+	struct ib_cm_compare_data compare_data;
+	struct sockaddr *addr;
+	__be64 svc_id;
+	int ret;
+
+	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler,
+					    id_priv);
+	if (IS_ERR(id_priv->cm_id.ib))
+		return PTR_ERR(id_priv->cm_id.ib);
+
+	addr = &id_priv->id.route.addr.src_addr;
+	svc_id = cma_get_service_id(id_priv->id.ps, addr);
+	if (cma_any_addr(addr))
+		ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL);
+	else {
+		cma_set_compare_data(id_priv->id.ps, addr, &compare_data);
+		ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, &compare_data);
+	}
+
+	if (ret) {
+		ib_destroy_cm_id(id_priv->cm_id.ib);
+		id_priv->cm_id.ib = NULL;
+	}
+
+	return ret;
+}
+
+static int cma_listen_handler(struct rdma_cm_id *id,
+			      struct rdma_cm_event *event)
+{
+	struct rdma_id_private *id_priv = id->context;
+
+	id->context = id_priv->id.context;
+	id->event_handler = id_priv->id.event_handler;
+	return id_priv->id.event_handler(id, event);
+}
+
+static void cma_listen_on_dev(struct rdma_id_private *id_priv,
+			      struct cma_device *cma_dev)
+{
+	struct rdma_id_private *dev_id_priv;
+	struct rdma_cm_id *id;
+	int ret;
+
+	id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps);
+	if (IS_ERR(id))
+		return;
+
+	dev_id_priv = container_of(id, struct rdma_id_private, id);
+
+	dev_id_priv->state = CMA_ADDR_BOUND;
+	memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr,
+	       ip_addr_size(&id_priv->id.route.addr.src_addr));
+
+	cma_attach_to_dev(dev_id_priv, cma_dev);
+	list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);
+
+	ret = rdma_listen(id, id_priv->backlog);
+	if (ret)
+		goto err;
+
+	return;
+err:
+	cma_destroy_listen(dev_id_priv);
+}
+
+static void cma_listen_on_all(struct rdma_id_private *id_priv)
+{
+	struct cma_device *cma_dev;
+
+	mutex_lock(&lock);
+	list_add_tail(&id_priv->list, &listen_any_list);
+	list_for_each_entry(cma_dev, &dev_list, list)
+		cma_listen_on_dev(id_priv, cma_dev);
+	mutex_unlock(&lock);
+}
+
+static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af)
+{
+	struct sockaddr_in addr_in;
+
+	memset(&addr_in, 0, sizeof addr_in);
+	addr_in.sin_family = af;
+	return rdma_bind_addr(id, (struct sockaddr *) &addr_in);
+}
+
+int rdma_listen(struct rdma_cm_id *id, int backlog)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (id_priv->state == CMA_IDLE) {
+		ret = cma_bind_any(id, AF_INET);
+		if (ret)
+			return ret;
+	}
+
+	if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN))
+		return -EINVAL;
+
+	id_priv->backlog = backlog;
+	if (id->device) {
+		switch (id->device->node_type) {
+		case IB_NODE_CA:
+			ret = cma_ib_listen(id_priv);
+			if (ret)
+				goto err;
+			break;
+		default:
+			ret = -ENOSYS;
+			goto err;
+		}
+	} else
+		cma_listen_on_all(id_priv);
+
+	return 0;
+err:
+	id_priv->backlog = 0;
+	cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_listen);
+
+static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec,
+			      void *context)
+{
+	struct cma_work *work = context;
+	struct rdma_route *route;
+
+	route = &work->id->id.route;
+
+	if (!status) {
+		route->num_paths = 1;
+		*route->path_rec = *path_rec;
+	} else {
+		work->old_state = CMA_ROUTE_QUERY;
+		work->new_state = CMA_ADDR_RESOLVED;
+		work->event.event = RDMA_CM_EVENT_ROUTE_ERROR;
+	}
+
+	queue_work(cma_wq, &work->work);
+}
+
+static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms,
+			      struct cma_work *work)
+{
+	struct rdma_dev_addr *addr = &id_priv->id.route.addr.dev_addr;
+	struct ib_sa_path_rec path_rec;
+
+	memset(&path_rec, 0, sizeof path_rec);
+	path_rec.sgid = *ib_addr_get_sgid(addr);
+	path_rec.dgid = *ib_addr_get_dgid(addr);
+	path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr));
+	path_rec.numb_path = 1;
+
+	id_priv->query_id = ib_sa_path_rec_get(id_priv->id.device,
+				id_priv->id.port_num, &path_rec,
+				IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID |
+				IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH,
+				timeout_ms, GFP_KERNEL,
+				cma_query_handler, work, &id_priv->query);
+
+	return (id_priv->query_id < 0) ? id_priv->query_id : 0;
+}
+
+static void cma_work_handler(void *data)
+{
+	struct cma_work *work = data;
+	struct rdma_id_private *id_priv = work->id;
+	int destroy = 0;
+
+	atomic_inc(&id_priv->dev_remove);
+	if (!cma_comp_exch(id_priv, work->old_state, work->new_state))
+		goto out;
+
+	if (id_priv->id.event_handler(&id_priv->id, &work->event)) {
+		cma_exch(id_priv, CMA_DESTROYING);
+		destroy = 1;
+	}
+out:
+	cma_release_remove(id_priv);
+	cma_deref_id(id_priv);
+	if (destroy)
+		rdma_destroy_id(&id_priv->id);
+	kfree(work);
+}
+
+static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms)
+{
+	struct rdma_route *route = &id_priv->id.route;
+	struct cma_work *work;
+	int ret;
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	work->id = id_priv;
+	INIT_WORK(&work->work, cma_work_handler, work);
+	work->old_state = CMA_ROUTE_QUERY;
+	work->new_state = CMA_ROUTE_RESOLVED;
+	work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+
+	route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL);
+	if (!route->path_rec) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	ret = cma_query_ib_route(id_priv, timeout_ms, work);
+	if (ret)
+		goto err2;
+
+	return 0;
+err2:
+	kfree(route->path_rec);
+	route->path_rec = NULL;
+err1:
+	kfree(work);
+	return ret;
+}
+
+int rdma_set_ib_paths(struct rdma_cm_id *id,
+		      struct ib_sa_path_rec *path_rec, int num_paths)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED))
+		return -EINVAL;
+
+	id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL);
+	if (!id->route.path_rec) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths);
+	return 0;
+err:
+	cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_set_ib_paths);
+
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY))
+		return -EINVAL;
+
+	atomic_inc(&id_priv->refcount);
+	switch (id->device->node_type) {
+	case IB_NODE_CA:
+		ret = cma_resolve_ib_route(id_priv, timeout_ms);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED);
+	cma_deref_id(id_priv);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_route);
+
+static int cma_bind_loopback(struct rdma_id_private *id_priv)
+{
+	struct cma_device *cma_dev;
+	struct ib_port_attr port_attr;
+	union ib_gid *gid;
+	u16 pkey;
+	int ret;
+	u8 p;
+
+	mutex_lock(&lock);
+	list_for_each_entry(cma_dev, &dev_list, list)
+		for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p)
+			if (!ib_query_port (cma_dev->device, p, &port_attr) &&
+			    port_attr.state == IB_PORT_ACTIVE)
+				goto port_found;
+
+	if (!list_empty(&dev_list)) {
+		p = 1;
+		cma_dev = list_entry(dev_list.next, struct cma_device, list);
+	} else {
+		ret = -ENODEV;
+		goto out;
+	}
+
+port_found:
+	gid = ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr);
+	ret = ib_get_cached_gid(cma_dev->device, p, 0, gid);
+	if (ret)
+		goto out;
+
+	ret = ib_get_cached_pkey(cma_dev->device, p, 0, &pkey);
+	if (ret)
+		goto out;
+
+	ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey);
+	id_priv->id.port_num = p;
+	cma_attach_to_dev(id_priv, cma_dev);
+out:
+	mutex_unlock(&lock);
+	return ret;
+}
+
+static void addr_handler(int status, struct sockaddr *src_addr,
+			 struct rdma_dev_addr *dev_addr, void *context)
+{
+	struct rdma_id_private *id_priv = context;
+	enum rdma_cm_event_type event;
+
+	atomic_inc(&id_priv->dev_remove);
+	if (!id_priv->cma_dev && !status)
+		status = cma_acquire_dev(id_priv);
+
+	if (status) {
+		if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND))
+			goto out;
+		event = RDMA_CM_EVENT_ADDR_ERROR;
+	} else {
+		if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
+			goto out;
+		memcpy(&id_priv->id.route.addr.src_addr, src_addr,
+		       ip_addr_size(src_addr));
+		event = RDMA_CM_EVENT_ADDR_RESOLVED;
+	}
+
+	if (cma_notify_user(id_priv, event, status, NULL, 0)) {
+		cma_exch(id_priv, CMA_DESTROYING);
+		cma_release_remove(id_priv);
+		cma_deref_id(id_priv);
+		rdma_destroy_id(&id_priv->id);
+		return;
+	}
+out:
+	cma_release_remove(id_priv);
+	cma_deref_id(id_priv);
+}
+
+static int cma_resolve_loopback(struct rdma_id_private *id_priv)
+{
+	struct cma_work *work;
+	struct sockaddr_in *src_in, *dst_in;
+	int ret;
+
+	work = kzalloc(sizeof *work, GFP_KERNEL);
+	if (!work)
+		return -ENOMEM;
+
+	if (!id_priv->cma_dev) {
+		ret = cma_bind_loopback(id_priv);
+		if (ret)
+			goto err;
+	}
+
+	ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr,
+			 ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr));
+
+	if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) {
+		src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr;
+		dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr;
+		src_in->sin_family = dst_in->sin_family;
+		src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr;
+	}
+
+	work->id = id_priv;
+	INIT_WORK(&work->work, cma_work_handler, work);
+	work->old_state = CMA_ADDR_QUERY;
+	work->new_state = CMA_ADDR_RESOLVED;
+	work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;
+	queue_work(cma_wq, &work->work);
+	return 0;
+err:
+	kfree(work);
+	return ret;
+}
+
+static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+			 struct sockaddr *dst_addr)
+{
+	if (src_addr && src_addr->sa_family)
+		return rdma_bind_addr(id, src_addr);
+	else
+		return cma_bind_any(id, dst_addr->sa_family);
+}
+
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+		      struct sockaddr *dst_addr, int timeout_ms)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (id_priv->state == CMA_IDLE) {
+		ret = cma_bind_addr(id, src_addr, dst_addr);
+		if (ret)
+			return ret;
+	}
+
+	if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY))
+		return -EINVAL;
+
+	atomic_inc(&id_priv->refcount);
+	memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr));
+	if (cma_any_addr(dst_addr))
+		ret = cma_resolve_loopback(id_priv);
+	else
+		ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr,
+				      &id->route.addr.dev_addr,
+				      timeout_ms, addr_handler, id_priv);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND);
+	cma_deref_id(id_priv);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_resolve_addr);
+
+static void cma_bind_port(struct rdma_bind_list *bind_list,
+			  struct rdma_id_private *id_priv)
+{
+	struct sockaddr_in *sin;
+
+	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
+	sin->sin_port = htons(bind_list->port);
+	id_priv->bind_list = bind_list;
+	hlist_add_head(&id_priv->node, &bind_list->owners);
+}
+
+static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
+			  unsigned short snum)
+{
+	struct rdma_bind_list *bind_list;
+	int port, start, ret;
+
+	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
+	if (!bind_list)
+		return -ENOMEM;
+
+	start = snum ? snum : sysctl_local_port_range[0];
+
+	do {
+		ret = idr_get_new_above(ps, bind_list, start, &port);
+	} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
+
+	if (ret)
+		goto err;
+
+	if ((snum && port != snum) ||
+	    (!snum && port > sysctl_local_port_range[1])) {
+		idr_remove(ps, port);
+		ret = -EADDRNOTAVAIL;
+		goto err;
+	}
+
+	bind_list->ps = ps;
+	bind_list->port = (unsigned short) port;
+	cma_bind_port(bind_list, id_priv);
+	return 0;
+err:
+	kfree(bind_list);
+	return ret;
+}
+
+static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
+{
+	struct rdma_id_private *cur_id;
+	struct sockaddr_in *sin, *cur_sin;
+	struct rdma_bind_list *bind_list;
+	struct hlist_node *node;
+	unsigned short snum;
+
+	sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr;
+	snum = ntohs(sin->sin_port);
+	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+		return -EACCES;
+
+	bind_list = idr_find(ps, snum);
+	if (!bind_list)
+		return cma_alloc_port(ps, id_priv, snum);
+
+	/*
+	 * We don't support binding to any address if anyone is bound to
+	 * a specific address on the same port.
+	 */
+	if (cma_any_addr(&id_priv->id.route.addr.src_addr))
+		return -EADDRNOTAVAIL;
+
+	hlist_for_each_entry(cur_id, node, &bind_list->owners, node) {
+		if (cma_any_addr(&cur_id->id.route.addr.src_addr))
+			return -EADDRNOTAVAIL;
+		
+		cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr;
+		if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr)
+			return -EADDRINUSE;
+	}
+
+	cma_bind_port(bind_list, id_priv);
+	return 0;
+}
+
+static int cma_get_port(struct rdma_id_private *id_priv)
+{
+	struct idr *ps;
+	int ret;
+
+	switch (id_priv->id.ps) {
+	case RDMA_PS_SDP:
+		ps = &sdp_ps;
+		break;
+	case RDMA_PS_TCP:
+		ps = &tcp_ps;
+		break;
+	default:
+		return -EPROTONOSUPPORT;
+	}
+
+	mutex_lock(&lock);
+	if (cma_any_port(&id_priv->id.route.addr.src_addr))
+		ret = cma_alloc_port(ps, id_priv, 0);
+	else
+		ret = cma_use_port(ps, id_priv);
+	mutex_unlock(&lock);
+
+	return ret;
+}
+
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	if (addr->sa_family != AF_INET)
+		return -EAFNOSUPPORT;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND))
+		return -EINVAL;
+
+	if (!cma_any_addr(addr)) {
+		ret = rdma_translate_ip(addr, &id->route.addr.dev_addr);
+		if (!ret)
+			ret = cma_acquire_dev(id_priv);
+		if (ret)
+			goto err;
+	}
+
+	memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr));
+	ret = cma_get_port(id_priv);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_bind_addr);
+
+static int cma_format_hdr(void *hdr, enum rdma_port_space ps,
+			  struct rdma_route *route)
+{
+	struct sockaddr_in *src4, *dst4;
+	struct cma_hdr *cma_hdr;
+	struct sdp_hh *sdp_hdr;
+
+	src4 = (struct sockaddr_in *) &route->addr.src_addr;
+	dst4 = (struct sockaddr_in *) &route->addr.dst_addr;
+
+	switch (ps) {
+	case RDMA_PS_SDP:
+		sdp_hdr = hdr;
+		if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION)
+			return -EINVAL;
+		sdp_set_ip_ver(sdp_hdr, 4);
+		sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+		sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+		sdp_hdr->port = src4->sin_port;
+		break;
+	default:
+		cma_hdr = hdr;
+		cma_hdr->cma_version = CMA_VERSION;
+		cma_set_ip_ver(cma_hdr, 4);
+		cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr;
+		cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr;
+		cma_hdr->port = src4->sin_port;
+		break;
+	}
+	return 0;
+}
+
+static int cma_connect_ib(struct rdma_id_private *id_priv,
+			  struct rdma_conn_param *conn_param)
+{
+	struct ib_cm_req_param req;
+	struct rdma_route *route;
+	void *private_data;
+	int offset, ret;
+
+	memset(&req, 0, sizeof req);
+	offset = cma_user_data_offset(id_priv->id.ps);
+	req.private_data_len = offset + conn_param->private_data_len;
+	private_data = kzalloc(req.private_data_len, GFP_ATOMIC);
+	if (!private_data)
+		return -ENOMEM;
+
+	if (conn_param->private_data && conn_param->private_data_len)
+		memcpy(private_data + offset, conn_param->private_data,
+		       conn_param->private_data_len);
+
+	id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler,
+					    id_priv);
+	if (IS_ERR(id_priv->cm_id.ib)) {
+		ret = PTR_ERR(id_priv->cm_id.ib);
+		goto out;
+	}
+
+	route = &id_priv->id.route;
+	ret = cma_format_hdr(private_data, id_priv->id.ps, route);
+	if (ret)
+		goto out;
+	req.private_data = private_data;
+
+	req.primary_path = &route->path_rec[0];
+	if (route->num_paths == 2)
+		req.alternate_path = &route->path_rec[1];
+
+	req.service_id = cma_get_service_id(id_priv->id.ps,
+					    &route->addr.dst_addr);
+	req.qp_num = id_priv->qp_num;
+	req.qp_type = id_priv->qp_type;
+	req.starting_psn = id_priv->seq_num;
+	req.responder_resources = conn_param->responder_resources;
+	req.initiator_depth = conn_param->initiator_depth;
+	req.flow_control = conn_param->flow_control;
+	req.retry_count = conn_param->retry_count;
+	req.rnr_retry_count = conn_param->rnr_retry_count;
+	req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
+	req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT;
+	req.max_cm_retries = CMA_MAX_CM_RETRIES;
+	req.srq = id_priv->srq ? 1 : 0;
+
+	ret = ib_send_cm_req(id_priv->cm_id.ib, &req);
+out:
+	kfree(private_data);
+	return ret;
+}
+
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT))
+		return -EINVAL;
+
+	if (!id->qp) {
+		id_priv->qp_num = conn_param->qp_num;
+		id_priv->qp_type = conn_param->qp_type;
+		id_priv->srq = conn_param->srq;
+	}
+
+	switch (id->device->node_type) {
+	case IB_NODE_CA:
+		ret = cma_connect_ib(id_priv, conn_param);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_connect);
+
+static int cma_accept_ib(struct rdma_id_private *id_priv,
+			 struct rdma_conn_param *conn_param)
+{
+	struct ib_cm_rep_param rep;
+	int ret;
+
+	ret = cma_modify_qp_rtr(&id_priv->id);
+	if (ret)
+		return ret;
+
+	memset(&rep, 0, sizeof rep);
+	rep.qp_num = id_priv->qp_num;
+	rep.starting_psn = id_priv->seq_num;
+	rep.private_data = conn_param->private_data;
+	rep.private_data_len = conn_param->private_data_len;
+	rep.responder_resources = conn_param->responder_resources;
+	rep.initiator_depth = conn_param->initiator_depth;
+	rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT;
+	rep.failover_accepted = 0;
+	rep.flow_control = conn_param->flow_control;
+	rep.rnr_retry_count = conn_param->rnr_retry_count;
+	rep.srq = id_priv->srq ? 1 : 0;
+
+	return ib_send_cm_rep(id_priv->cm_id.ib, &rep);
+}
+
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp(id_priv, CMA_CONNECT))
+		return -EINVAL;
+
+	if (!id->qp && conn_param) {
+		id_priv->qp_num = conn_param->qp_num;
+		id_priv->qp_type = conn_param->qp_type;
+		id_priv->srq = conn_param->srq;
+	}
+
+	switch (id->device->node_type) {
+	case IB_NODE_CA:
+		if (conn_param)
+			ret = cma_accept_ib(id_priv, conn_param);
+		else
+			ret = cma_rep_recv(id_priv);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+
+	if (ret)
+		goto reject;
+
+	return 0;
+reject:
+	cma_modify_qp_err(id);
+	rdma_reject(id, NULL, 0);
+	return ret;
+}
+EXPORT_SYMBOL(rdma_accept);
+
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,
+		u8 private_data_len)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp(id_priv, CMA_CONNECT))
+		return -EINVAL;
+
+	switch (id->device->node_type) {
+	case IB_NODE_CA:
+		ret = ib_send_cm_rej(id_priv->cm_id.ib,
+				     IB_CM_REJ_CONSUMER_DEFINED, NULL, 0,
+				     private_data, private_data_len);
+		break;
+	default:
+		ret = -ENOSYS;
+		break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(rdma_reject);
+
+int rdma_disconnect(struct rdma_cm_id *id)
+{
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	id_priv = container_of(id, struct rdma_id_private, id);
+	if (!cma_comp(id_priv, CMA_CONNECT) &&
+	    !cma_comp(id_priv, CMA_DISCONNECT))
+		return -EINVAL;
+
+	ret = cma_modify_qp_err(id);
+	if (ret)
+		goto out;
+
+	switch (id->device->node_type) {
+	case IB_NODE_CA:
+		/* Initiate or respond to a disconnect. */
+		if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0))
+			ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0);
+		break;
+	default:
+		break;
+	}
+out:
+	return ret;
+}
+EXPORT_SYMBOL(rdma_disconnect);
+
+static void cma_add_one(struct ib_device *device)
+{
+	struct cma_device *cma_dev;
+	struct rdma_id_private *id_priv;
+
+	cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL);
+	if (!cma_dev)
+		return;
+
+	cma_dev->device = device;
+	cma_dev->node_guid = device->node_guid;
+	if (!cma_dev->node_guid)
+		goto err;
+
+	init_completion(&cma_dev->comp);
+	atomic_set(&cma_dev->refcount, 1);
+	INIT_LIST_HEAD(&cma_dev->id_list);
+	ib_set_client_data(device, &cma_client, cma_dev);
+
+	mutex_lock(&lock);
+	list_add_tail(&cma_dev->list, &dev_list);
+	list_for_each_entry(id_priv, &listen_any_list, list)
+		cma_listen_on_dev(id_priv, cma_dev);
+	mutex_unlock(&lock);
+	return;
+err:
+	kfree(cma_dev);
+}
+
+static int cma_remove_id_dev(struct rdma_id_private *id_priv)
+{
+	enum cma_state state;
+
+	/* Record that we want to remove the device */
+	state = cma_exch(id_priv, CMA_DEVICE_REMOVAL);
+	if (state == CMA_DESTROYING)
+		return 0;
+
+	cma_cancel_operation(id_priv, state);
+	wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove));
+
+	/* Check for destruction from another callback. */
+	if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL))
+		return 0;
+
+	return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL,
+			       0, NULL, 0);
+}
+
+static void cma_process_remove(struct cma_device *cma_dev)
+{
+	struct list_head remove_list;
+	struct rdma_id_private *id_priv;
+	int ret;
+
+	INIT_LIST_HEAD(&remove_list);
+
+	mutex_lock(&lock);
+	while (!list_empty(&cma_dev->id_list)) {
+		id_priv = list_entry(cma_dev->id_list.next,
+				     struct rdma_id_private, list);
+
+		if (cma_internal_listen(id_priv)) {
+			cma_destroy_listen(id_priv);
+			continue;
+		}
+
+		list_del(&id_priv->list);
+		list_add_tail(&id_priv->list, &remove_list);
+		atomic_inc(&id_priv->refcount);
+		mutex_unlock(&lock);
+
+		ret = cma_remove_id_dev(id_priv);
+		cma_deref_id(id_priv);
+		if (ret)
+			rdma_destroy_id(&id_priv->id);
+
+		mutex_lock(&lock);
+	}
+	mutex_unlock(&lock);
+
+	cma_deref_dev(cma_dev);
+	wait_for_completion(&cma_dev->comp);
+}
+
+static void cma_remove_one(struct ib_device *device)
+{
+	struct cma_device *cma_dev;
+
+	cma_dev = ib_get_client_data(device, &cma_client);
+	if (!cma_dev)
+		return;
+
+	mutex_lock(&lock);
+	list_del(&cma_dev->list);
+	mutex_unlock(&lock);
+
+	cma_process_remove(cma_dev);
+	kfree(cma_dev);
+}
+
+static int cma_init(void)
+{
+	int ret;
+
+	cma_wq = create_singlethread_workqueue("rdma_cm_wq");
+	if (!cma_wq)
+		return -ENOMEM;
+
+	ret = ib_register_client(&cma_client);
+	if (ret)
+		goto err;
+	return 0;
+
+err:
+	destroy_workqueue(cma_wq);
+	return ret;
+}
+
+static void cma_cleanup(void)
+{
+	ib_unregister_client(&cma_client);
+	destroy_workqueue(cma_wq);
+	idr_destroy(&sdp_ps);
+	idr_destroy(&tcp_ps);
+}
+
+module_init(cma_init);
+module_exit(cma_cleanup);
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index 838bf54..615fe9c 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -54,7 +54,7 @@
 /*
  * If an FMR is not in use, then the list member will point to either
  * its pool's free_list (if the FMR can be mapped again; that is,
- * remap_count < IB_FMR_MAX_REMAPS) or its pool's dirty_list (if the
+ * remap_count < pool->max_remaps) or its pool's dirty_list (if the
  * FMR needs to be unmapped before being remapped).  In either of
  * these cases it is a bug if the ref_count is not 0.  In other words,
  * if ref_count is > 0, then the list member must not be linked into
@@ -84,6 +84,7 @@
 
 	int                       pool_size;
 	int                       max_pages;
+	int			  max_remaps;
 	int                       dirty_watermark;
 	int                       dirty_len;
 	struct list_head          free_list;
@@ -214,8 +215,10 @@
 {
 	struct ib_device   *device;
 	struct ib_fmr_pool *pool;
+	struct ib_device_attr *attr;
 	int i;
 	int ret;
+	int max_remaps;
 
 	if (!params)
 		return ERR_PTR(-EINVAL);
@@ -228,6 +231,26 @@
 		return ERR_PTR(-ENOSYS);
 	}
 
+	attr = kmalloc(sizeof *attr, GFP_KERNEL);
+	if (!attr) {
+		printk(KERN_WARNING "couldn't allocate device attr struct");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	ret = ib_query_device(device, attr);
+	if (ret) {
+		printk(KERN_WARNING "couldn't query device");
+		kfree(attr);
+		return ERR_PTR(ret);
+	}
+
+	if (!attr->max_map_per_fmr)
+		max_remaps = IB_FMR_MAX_REMAPS;
+	else
+		max_remaps = attr->max_map_per_fmr;
+
+	kfree(attr);
+
 	pool = kmalloc(sizeof *pool, GFP_KERNEL);
 	if (!pool) {
 		printk(KERN_WARNING "couldn't allocate pool struct");
@@ -258,6 +281,7 @@
 
 	pool->pool_size       = 0;
 	pool->max_pages       = params->max_pages_per_fmr;
+	pool->max_remaps      = max_remaps;
 	pool->dirty_watermark = params->dirty_watermark;
 	pool->dirty_len       = 0;
 	spin_lock_init(&pool->pool_lock);
@@ -279,7 +303,7 @@
 		struct ib_pool_fmr *fmr;
 		struct ib_fmr_attr attr = {
 			.max_pages  = params->max_pages_per_fmr,
-			.max_maps   = IB_FMR_MAX_REMAPS,
+			.max_maps   = pool->max_remaps,
 			.page_shift = params->page_shift
 		};
 
@@ -489,7 +513,7 @@
 
 	--fmr->ref_count;
 	if (!fmr->ref_count) {
-		if (fmr->remap_count < IB_FMR_MAX_REMAPS) {
+		if (fmr->remap_count < pool->max_remaps) {
 			list_add_tail(&fmr->list, &pool->free_list);
 		} else {
 			list_add_tail(&fmr->list, &pool->dirty_list);
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 5ad41a6..5ed4dab 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -34,6 +34,7 @@
  * $Id: mad.c 5596 2006-03-03 01:00:07Z sean.hefty $
  */
 #include <linux/dma-mapping.h>
+#include <rdma/ib_cache.h>
 
 #include "mad_priv.h"
 #include "mad_rmpp.h"
@@ -45,8 +46,7 @@
 MODULE_AUTHOR("Hal Rosenstock");
 MODULE_AUTHOR("Sean Hefty");
 
-
-kmem_cache_t *ib_mad_cache;
+static kmem_cache_t *ib_mad_cache;
 
 static struct list_head ib_mad_port_list;
 static u32 ib_mad_client_id = 0;
@@ -1673,20 +1673,21 @@
 		rwc->recv_buf.mad->mad_hdr.mgmt_class;
 }
 
-static inline int rcv_has_same_gid(struct ib_mad_send_wr_private *wr,
+static inline int rcv_has_same_gid(struct ib_mad_agent_private *mad_agent_priv,
+				   struct ib_mad_send_wr_private *wr,
 				   struct ib_mad_recv_wc *rwc )
 {
 	struct ib_ah_attr attr;
 	u8 send_resp, rcv_resp;
+	union ib_gid sgid;
+	struct ib_device *device = mad_agent_priv->agent.device;
+	u8 port_num = mad_agent_priv->agent.port_num;
+	u8 lmc;
 
 	send_resp = ((struct ib_mad *)(wr->send_buf.mad))->
 		     mad_hdr.method & IB_MGMT_METHOD_RESP;
 	rcv_resp = rwc->recv_buf.mad->mad_hdr.method & IB_MGMT_METHOD_RESP;
 
-	if (!send_resp && rcv_resp)
-		/* is request/response. GID/LIDs are both local (same). */
-		return 1;
-
 	if (send_resp == rcv_resp)
 		/* both requests, or both responses. GIDs different */
 		return 0;
@@ -1695,48 +1696,78 @@
 		/* Assume not equal, to avoid false positives. */
 		return 0;
 
-	if (!(attr.ah_flags & IB_AH_GRH) && !(rwc->wc->wc_flags & IB_WC_GRH))
-		return attr.dlid == rwc->wc->slid;
-	else if ((attr.ah_flags & IB_AH_GRH) &&
-		 (rwc->wc->wc_flags & IB_WC_GRH))
-		return memcmp(attr.grh.dgid.raw,
-			      rwc->recv_buf.grh->sgid.raw, 16) == 0;
-	else
+	if (!!(attr.ah_flags & IB_AH_GRH) !=
+	    !!(rwc->wc->wc_flags & IB_WC_GRH))
 		/* one has GID, other does not.  Assume different */
 		return 0;
+
+	if (!send_resp && rcv_resp) {
+		/* is request/response. */
+		if (!(attr.ah_flags & IB_AH_GRH)) {
+			if (ib_get_cached_lmc(device, port_num, &lmc))
+				return 0;
+			return (!lmc || !((attr.src_path_bits ^
+					   rwc->wc->dlid_path_bits) &
+					  ((1 << lmc) - 1)));
+		} else {
+			if (ib_get_cached_gid(device, port_num,
+					      attr.grh.sgid_index, &sgid))
+				return 0;
+			return !memcmp(sgid.raw, rwc->recv_buf.grh->dgid.raw,
+				       16);
+		}
+	}
+
+	if (!(attr.ah_flags & IB_AH_GRH))
+		return attr.dlid == rwc->wc->slid;
+	else
+		return !memcmp(attr.grh.dgid.raw, rwc->recv_buf.grh->sgid.raw,
+			       16);
 }
+
+static inline int is_direct(u8 class)
+{
+	return (class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE);
+}
+
 struct ib_mad_send_wr_private*
 ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv,
-		 struct ib_mad_recv_wc *mad_recv_wc)
+		 struct ib_mad_recv_wc *wc)
 {
-	struct ib_mad_send_wr_private *mad_send_wr;
+	struct ib_mad_send_wr_private *wr;
 	struct ib_mad *mad;
 
-	mad = (struct ib_mad *)mad_recv_wc->recv_buf.mad;
+	mad = (struct ib_mad *)wc->recv_buf.mad;
 
-	list_for_each_entry(mad_send_wr, &mad_agent_priv->wait_list,
-			    agent_list) {
-		if ((mad_send_wr->tid == mad->mad_hdr.tid) &&
-		    rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
-		    rcv_has_same_gid(mad_send_wr, mad_recv_wc))
-			return mad_send_wr;
+	list_for_each_entry(wr, &mad_agent_priv->wait_list, agent_list) {
+		if ((wr->tid == mad->mad_hdr.tid) &&
+		    rcv_has_same_class(wr, wc) &&
+		    /*
+		     * Don't check GID for direct routed MADs.
+		     * These might have permissive LIDs.
+		     */
+		    (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
+		     rcv_has_same_gid(mad_agent_priv, wr, wc)))
+			return wr;
 	}
 
 	/*
 	 * It's possible to receive the response before we've
 	 * been notified that the send has completed
 	 */
-	list_for_each_entry(mad_send_wr, &mad_agent_priv->send_list,
-			    agent_list) {
-		if (is_data_mad(mad_agent_priv, mad_send_wr->send_buf.mad) &&
-		    mad_send_wr->tid == mad->mad_hdr.tid &&
-		    mad_send_wr->timeout &&
-		    rcv_has_same_class(mad_send_wr, mad_recv_wc) &&
-		    rcv_has_same_gid(mad_send_wr, mad_recv_wc)) {
+	list_for_each_entry(wr, &mad_agent_priv->send_list, agent_list) {
+		if (is_data_mad(mad_agent_priv, wr->send_buf.mad) &&
+		    wr->tid == mad->mad_hdr.tid &&
+		    wr->timeout &&
+		    rcv_has_same_class(wr, wc) &&
+		    /*
+		     * Don't check GID for direct routed MADs.
+		     * These might have permissive LIDs.
+		     */
+		    (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) ||
+		     rcv_has_same_gid(mad_agent_priv, wr, wc)))
 			/* Verify request has not been canceled */
-			return (mad_send_wr->status == IB_WC_SUCCESS) ?
-				mad_send_wr : NULL;
-		}
+			return (wr->status == IB_WC_SUCCESS) ? wr : NULL;
 	}
 	return NULL;
 }
@@ -1744,11 +1775,9 @@
 void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr)
 {
 	mad_send_wr->timeout = 0;
-	if (mad_send_wr->refcount == 1) {
-		list_del(&mad_send_wr->agent_list);
-		list_add_tail(&mad_send_wr->agent_list,
+	if (mad_send_wr->refcount == 1)
+		list_move_tail(&mad_send_wr->agent_list,
 			      &mad_send_wr->mad_agent_priv->done_list);
-	}
 }
 
 static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
@@ -2067,8 +2096,7 @@
 		queued_send_wr = container_of(mad_list,
 					struct ib_mad_send_wr_private,
 					mad_list);
-		list_del(&mad_list->list);
-		list_add_tail(&mad_list->list, &send_queue->list);
+		list_move_tail(&mad_list->list, &send_queue->list);
 	}
 	spin_unlock_irqrestore(&send_queue->lock, flags);
 
diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
index b4fa28d..d147f3b 100644
--- a/drivers/infiniband/core/mad_priv.h
+++ b/drivers/infiniband/core/mad_priv.h
@@ -212,8 +212,6 @@
 	struct ib_mad_qp_info qp_info[IB_MAD_QPS_CORE];
 };
 
-extern kmem_cache_t *ib_mad_cache;
-
 int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr);
 
 struct ib_mad_send_wr_private *
diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
index d4704e0..ebcd5b1 100644
--- a/drivers/infiniband/core/mad_rmpp.c
+++ b/drivers/infiniband/core/mad_rmpp.c
@@ -665,8 +665,7 @@
 			goto out;
 
 		mad_send_wr->refcount++;
-		list_del(&mad_send_wr->agent_list);
-		list_add_tail(&mad_send_wr->agent_list,
+		list_move_tail(&mad_send_wr->agent_list,
 			      &mad_send_wr->mad_agent_priv->send_list);
 	}
 out:
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 501cc05..e911c99 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -47,6 +47,7 @@
 
 #include <rdma/ib_pack.h>
 #include <rdma/ib_sa.h>
+#include <rdma/ib_cache.h>
 
 MODULE_AUTHOR("Roland Dreier");
 MODULE_DESCRIPTION("InfiniBand subnet administration query support");
@@ -441,6 +442,36 @@
 }
 EXPORT_SYMBOL(ib_sa_cancel_query);
 
+int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
+			 struct ib_sa_path_rec *rec, struct ib_ah_attr *ah_attr)
+{
+	int ret;
+	u16 gid_index;
+
+	memset(ah_attr, 0, sizeof *ah_attr);
+	ah_attr->dlid = be16_to_cpu(rec->dlid);
+	ah_attr->sl = rec->sl;
+	ah_attr->src_path_bits = be16_to_cpu(rec->slid) & 0x7f;
+	ah_attr->port_num = port_num;
+
+	if (rec->hop_limit > 1) {
+		ah_attr->ah_flags = IB_AH_GRH;
+		ah_attr->grh.dgid = rec->dgid;
+
+		ret = ib_find_cached_gid(device, &rec->sgid, &port_num,
+					 &gid_index);
+		if (ret)
+			return ret;
+
+		ah_attr->grh.sgid_index    = gid_index;
+		ah_attr->grh.flow_label    = be32_to_cpu(rec->flow_label);
+		ah_attr->grh.hop_limit     = rec->hop_limit;
+		ah_attr->grh.traffic_class = rec->traffic_class;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ib_init_ah_from_path);
+
 static void init_mad(struct ib_sa_mad *mad, struct ib_mad_agent *agent)
 {
 	unsigned long flags;
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 9164a09..c1c6fda 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -30,7 +30,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ucm.c 2594 2005-06-13 19:46:02Z libor $
+ * $Id: ucm.c 4311 2005-12-05 18:42:01Z sean.hefty $
  */
 
 #include <linux/completion.h>
@@ -50,6 +50,7 @@
 
 #include <rdma/ib_cm.h>
 #include <rdma/ib_user_cm.h>
+#include <rdma/ib_marshall.h>
 
 MODULE_AUTHOR("Libor Michalek");
 MODULE_DESCRIPTION("InfiniBand userspace Connection Manager access");
@@ -63,7 +64,7 @@
 };
 
 struct ib_ucm_file {
-	struct semaphore mutex;
+	struct mutex file_mutex;
 	struct file *filp;
 	struct ib_ucm_device *device;
 
@@ -152,7 +153,7 @@
 {
 	struct ib_ucm_event *uevent;
 
-	down(&ctx->file->mutex);
+	mutex_lock(&ctx->file->file_mutex);
 	list_del(&ctx->file_list);
 	while (!list_empty(&ctx->events)) {
 
@@ -167,7 +168,7 @@
 
 		kfree(uevent);
 	}
-	up(&ctx->file->mutex);
+	mutex_unlock(&ctx->file->file_mutex);
 }
 
 static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file)
@@ -205,36 +206,6 @@
 	return NULL;
 }
 
-static void ib_ucm_event_path_get(struct ib_ucm_path_rec *upath,
-				  struct ib_sa_path_rec	 *kpath)
-{
-	if (!kpath || !upath)
-		return;
-
-	memcpy(upath->dgid, kpath->dgid.raw, sizeof *upath->dgid);
-	memcpy(upath->sgid, kpath->sgid.raw, sizeof *upath->sgid);
-
-	upath->dlid             = kpath->dlid;
-	upath->slid             = kpath->slid;
-	upath->raw_traffic      = kpath->raw_traffic;
-	upath->flow_label       = kpath->flow_label;
-	upath->hop_limit        = kpath->hop_limit;
-	upath->traffic_class    = kpath->traffic_class;
-	upath->reversible       = kpath->reversible;
-	upath->numb_path        = kpath->numb_path;
-	upath->pkey             = kpath->pkey;
-	upath->sl	        = kpath->sl;
-	upath->mtu_selector     = kpath->mtu_selector;
-	upath->mtu              = kpath->mtu;
-	upath->rate_selector    = kpath->rate_selector;
-	upath->rate             = kpath->rate;
-	upath->packet_life_time = kpath->packet_life_time;
-	upath->preference       = kpath->preference;
-
-	upath->packet_life_time_selector =
-		kpath->packet_life_time_selector;
-}
-
 static void ib_ucm_event_req_get(struct ib_ucm_req_event_resp *ureq,
 				 struct ib_cm_req_event_param *kreq)
 {
@@ -253,8 +224,10 @@
 	ureq->srq                        = kreq->srq;
 	ureq->port			 = kreq->port;
 
-	ib_ucm_event_path_get(&ureq->primary_path, kreq->primary_path);
-	ib_ucm_event_path_get(&ureq->alternate_path, kreq->alternate_path);
+	ib_copy_path_rec_to_user(&ureq->primary_path, kreq->primary_path);
+	if (kreq->alternate_path)
+		ib_copy_path_rec_to_user(&ureq->alternate_path,
+					 kreq->alternate_path);
 }
 
 static void ib_ucm_event_rep_get(struct ib_ucm_rep_event_resp *urep,
@@ -324,8 +297,8 @@
 		info	      = evt->param.rej_rcvd.ari;
 		break;
 	case IB_CM_LAP_RECEIVED:
-		ib_ucm_event_path_get(&uvt->resp.u.lap_resp.path,
-				      evt->param.lap_rcvd.alternate_path);
+		ib_copy_path_rec_to_user(&uvt->resp.u.lap_resp.path,
+					 evt->param.lap_rcvd.alternate_path);
 		uvt->data_len = IB_CM_LAP_PRIVATE_DATA_SIZE;
 		uvt->resp.present = IB_UCM_PRES_ALTERNATE;
 		break;
@@ -402,11 +375,11 @@
 	if (result)
 		goto err2;
 
-	down(&ctx->file->mutex);
+	mutex_lock(&ctx->file->file_mutex);
 	list_add_tail(&uevent->file_list, &ctx->file->events);
 	list_add_tail(&uevent->ctx_list, &ctx->events);
 	wake_up_interruptible(&ctx->file->poll_wait);
-	up(&ctx->file->mutex);
+	mutex_unlock(&ctx->file->file_mutex);
 	return 0;
 
 err2:
@@ -432,7 +405,7 @@
 	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 		return -EFAULT;
 
-	down(&file->mutex);
+	mutex_lock(&file->file_mutex);
 	while (list_empty(&file->events)) {
 
 		if (file->filp->f_flags & O_NONBLOCK) {
@@ -447,9 +420,9 @@
 
 		prepare_to_wait(&file->poll_wait, &wait, TASK_INTERRUPTIBLE);
 
-		up(&file->mutex);
+		mutex_unlock(&file->file_mutex);
 		schedule();
-		down(&file->mutex);
+		mutex_lock(&file->file_mutex);
 
 		finish_wait(&file->poll_wait, &wait);
 	}
@@ -509,7 +482,7 @@
 	kfree(uevent->info);
 	kfree(uevent);
 done:
-	up(&file->mutex);
+	mutex_unlock(&file->file_mutex);
 	return result;
 }
 
@@ -528,9 +501,9 @@
 	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
 		return -EFAULT;
 
-	down(&file->mutex);
+	mutex_lock(&file->file_mutex);
 	ctx = ib_ucm_ctx_alloc(file);
-	up(&file->mutex);
+	mutex_unlock(&file->file_mutex);
 	if (!ctx)
 		return -ENOMEM;
 
@@ -637,65 +610,11 @@
 	return result;
 }
 
-static void ib_ucm_copy_ah_attr(struct ib_ucm_ah_attr *dest_attr,
-				struct ib_ah_attr *src_attr)
-{
-	memcpy(dest_attr->grh_dgid, src_attr->grh.dgid.raw,
-	       sizeof src_attr->grh.dgid);
-	dest_attr->grh_flow_label = src_attr->grh.flow_label;
-	dest_attr->grh_sgid_index = src_attr->grh.sgid_index;
-	dest_attr->grh_hop_limit = src_attr->grh.hop_limit;
-	dest_attr->grh_traffic_class = src_attr->grh.traffic_class;
-
-	dest_attr->dlid = src_attr->dlid;
-	dest_attr->sl = src_attr->sl;
-	dest_attr->src_path_bits = src_attr->src_path_bits;
-	dest_attr->static_rate = src_attr->static_rate;
-	dest_attr->is_global = (src_attr->ah_flags & IB_AH_GRH);
-	dest_attr->port_num = src_attr->port_num;
-}
-
-static void ib_ucm_copy_qp_attr(struct ib_ucm_init_qp_attr_resp *dest_attr,
-				struct ib_qp_attr *src_attr)
-{
-	dest_attr->cur_qp_state = src_attr->cur_qp_state;
-	dest_attr->path_mtu = src_attr->path_mtu;
-	dest_attr->path_mig_state = src_attr->path_mig_state;
-	dest_attr->qkey = src_attr->qkey;
-	dest_attr->rq_psn = src_attr->rq_psn;
-	dest_attr->sq_psn = src_attr->sq_psn;
-	dest_attr->dest_qp_num = src_attr->dest_qp_num;
-	dest_attr->qp_access_flags = src_attr->qp_access_flags;
-
-	dest_attr->max_send_wr = src_attr->cap.max_send_wr;
-	dest_attr->max_recv_wr = src_attr->cap.max_recv_wr;
-	dest_attr->max_send_sge = src_attr->cap.max_send_sge;
-	dest_attr->max_recv_sge = src_attr->cap.max_recv_sge;
-	dest_attr->max_inline_data = src_attr->cap.max_inline_data;
-
-	ib_ucm_copy_ah_attr(&dest_attr->ah_attr, &src_attr->ah_attr);
-	ib_ucm_copy_ah_attr(&dest_attr->alt_ah_attr, &src_attr->alt_ah_attr);
-
-	dest_attr->pkey_index = src_attr->pkey_index;
-	dest_attr->alt_pkey_index = src_attr->alt_pkey_index;
-	dest_attr->en_sqd_async_notify = src_attr->en_sqd_async_notify;
-	dest_attr->sq_draining = src_attr->sq_draining;
-	dest_attr->max_rd_atomic = src_attr->max_rd_atomic;
-	dest_attr->max_dest_rd_atomic = src_attr->max_dest_rd_atomic;
-	dest_attr->min_rnr_timer = src_attr->min_rnr_timer;
-	dest_attr->port_num = src_attr->port_num;
-	dest_attr->timeout = src_attr->timeout;
-	dest_attr->retry_cnt = src_attr->retry_cnt;
-	dest_attr->rnr_retry = src_attr->rnr_retry;
-	dest_attr->alt_port_num = src_attr->alt_port_num;
-	dest_attr->alt_timeout = src_attr->alt_timeout;
-}
-
 static ssize_t ib_ucm_init_qp_attr(struct ib_ucm_file *file,
 				   const char __user *inbuf,
 				   int in_len, int out_len)
 {
-	struct ib_ucm_init_qp_attr_resp resp;
+	struct ib_uverbs_qp_attr resp;
 	struct ib_ucm_init_qp_attr cmd;
 	struct ib_ucm_context *ctx;
 	struct ib_qp_attr qp_attr;
@@ -718,7 +637,7 @@
 	if (result)
 		goto out;
 
-	ib_ucm_copy_qp_attr(&resp, &qp_attr);
+	ib_copy_qp_attr_to_user(&resp, &qp_attr);
 
 	if (copy_to_user((void __user *)(unsigned long)cmd.response,
 			 &resp, sizeof(resp)))
@@ -729,6 +648,17 @@
 	return result;
 }
 
+static int ucm_validate_listen(__be64 service_id, __be64 service_mask)
+{
+	service_id &= service_mask;
+
+	if (((service_id & IB_CMA_SERVICE_ID_MASK) == IB_CMA_SERVICE_ID) ||
+	    ((service_id & IB_SDP_SERVICE_ID_MASK) == IB_SDP_SERVICE_ID))
+		return -EINVAL;
+
+	return 0;
+}
+
 static ssize_t ib_ucm_listen(struct ib_ucm_file *file,
 			     const char __user *inbuf,
 			     int in_len, int out_len)
@@ -744,7 +674,13 @@
 	if (IS_ERR(ctx))
 		return PTR_ERR(ctx);
 
-	result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask);
+	result = ucm_validate_listen(cmd.service_id, cmd.service_mask);
+	if (result)
+		goto out;
+
+	result = ib_cm_listen(ctx->cm_id, cmd.service_id, cmd.service_mask,
+			      NULL);
+out:
 	ib_ucm_ctx_put(ctx);
 	return result;
 }
@@ -793,7 +729,7 @@
 
 static int ib_ucm_path_get(struct ib_sa_path_rec **path, u64 src)
 {
-	struct ib_ucm_path_rec ucm_path;
+	struct ib_user_path_rec upath;
 	struct ib_sa_path_rec  *sa_path;
 
 	*path = NULL;
@@ -805,36 +741,14 @@
 	if (!sa_path)
 		return -ENOMEM;
 
-	if (copy_from_user(&ucm_path, (void __user *)(unsigned long)src,
-			   sizeof(ucm_path))) {
+	if (copy_from_user(&upath, (void __user *)(unsigned long)src,
+			   sizeof(upath))) {
 
 		kfree(sa_path);
 		return -EFAULT;
 	}
 
-	memcpy(sa_path->dgid.raw, ucm_path.dgid, sizeof sa_path->dgid);
-	memcpy(sa_path->sgid.raw, ucm_path.sgid, sizeof sa_path->sgid);
-
-	sa_path->dlid	          = ucm_path.dlid;
-	sa_path->slid	          = ucm_path.slid;
-	sa_path->raw_traffic      = ucm_path.raw_traffic;
-	sa_path->flow_label       = ucm_path.flow_label;
-	sa_path->hop_limit        = ucm_path.hop_limit;
-	sa_path->traffic_class    = ucm_path.traffic_class;
-	sa_path->reversible       = ucm_path.reversible;
-	sa_path->numb_path        = ucm_path.numb_path;
-	sa_path->pkey             = ucm_path.pkey;
-	sa_path->sl               = ucm_path.sl;
-	sa_path->mtu_selector     = ucm_path.mtu_selector;
-	sa_path->mtu              = ucm_path.mtu;
-	sa_path->rate_selector    = ucm_path.rate_selector;
-	sa_path->rate             = ucm_path.rate;
-	sa_path->packet_life_time = ucm_path.packet_life_time;
-	sa_path->preference       = ucm_path.preference;
-
-	sa_path->packet_life_time_selector =
-		ucm_path.packet_life_time_selector;
-
+	ib_copy_path_rec_from_user(sa_path, &upath);
 	*path = sa_path;
 	return 0;
 }
@@ -1130,7 +1044,6 @@
 	param.service_id       = cmd.sid;
 	param.timeout_ms       = cmd.timeout;
 	param.max_cm_retries   = cmd.max_cm_retries;
-	param.pkey             = cmd.pkey;
 
 	ctx = ib_ucm_ctx_get(file, cmd.id);
 	if (!IS_ERR(ctx)) {
@@ -1263,7 +1176,7 @@
 	INIT_LIST_HEAD(&file->ctxs);
 	init_waitqueue_head(&file->poll_wait);
 
-	init_MUTEX(&file->mutex);
+	mutex_init(&file->file_mutex);
 
 	filp->private_data = file;
 	file->filp = filp;
@@ -1277,11 +1190,11 @@
 	struct ib_ucm_file *file = filp->private_data;
 	struct ib_ucm_context *ctx;
 
-	down(&file->mutex);
+	mutex_lock(&file->file_mutex);
 	while (!list_empty(&file->ctxs)) {
 		ctx = list_entry(file->ctxs.next,
 				 struct ib_ucm_context, file_list);
-		up(&file->mutex);
+		mutex_unlock(&file->file_mutex);
 
 		mutex_lock(&ctx_id_mutex);
 		idr_remove(&ctx_id_table, ctx->id);
@@ -1291,9 +1204,9 @@
 		ib_ucm_cleanup_events(ctx);
 		kfree(ctx);
 
-		down(&file->mutex);
+		mutex_lock(&file->file_mutex);
 	}
-	up(&file->mutex);
+	mutex_unlock(&file->file_mutex);
 	kfree(file);
 	return 0;
 }
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index 3372d67..bb9bee5 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -132,7 +132,7 @@
 	u32			async_events_reported;
 };
 
-extern struct mutex ib_uverbs_idr_mutex;
+extern spinlock_t ib_uverbs_idr_lock;
 extern struct idr ib_uverbs_pd_idr;
 extern struct idr ib_uverbs_mr_idr;
 extern struct idr ib_uverbs_mw_idr;
@@ -141,6 +141,8 @@
 extern struct idr ib_uverbs_qp_idr;
 extern struct idr ib_uverbs_srq_idr;
 
+void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
+
 struct file *ib_uverbs_alloc_event_file(struct ib_uverbs_file *uverbs_file,
 					int is_async, int *fd);
 void ib_uverbs_release_event_file(struct kref *ref);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 9f69bd48..a908a7b 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -50,6 +50,196 @@
 		(udata)->outlen = (olen);				\
 	} while (0)
 
+/*
+ * The ib_uobject locking scheme is as follows:
+ *
+ * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it
+ *   needs to be held during all idr operations.  When an object is
+ *   looked up, a reference must be taken on the object's kref before
+ *   dropping this lock.
+ *
+ * - Each object also has an rwsem.  This rwsem must be held for
+ *   reading while an operation that uses the object is performed.
+ *   For example, while registering an MR, the associated PD's
+ *   uobject.mutex must be held for reading.  The rwsem must be held
+ *   for writing while initializing or destroying an object.
+ *
+ * - In addition, each object has a "live" flag.  If this flag is not
+ *   set, then lookups of the object will fail even if it is found in
+ *   the idr.  This handles a reader that blocks and does not acquire
+ *   the rwsem until after the object is destroyed.  The destroy
+ *   operation will set the live flag to 0 and then drop the rwsem;
+ *   this will allow the reader to acquire the rwsem, see that the
+ *   live flag is 0, and then drop the rwsem and its reference to
+ *   object.  The underlying storage will not be freed until the last
+ *   reference to the object is dropped.
+ */
+
+static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
+		      struct ib_ucontext *context)
+{
+	uobj->user_handle = user_handle;
+	uobj->context     = context;
+	kref_init(&uobj->ref);
+	init_rwsem(&uobj->mutex);
+	uobj->live        = 0;
+}
+
+static void release_uobj(struct kref *kref)
+{
+	kfree(container_of(kref, struct ib_uobject, ref));
+}
+
+static void put_uobj(struct ib_uobject *uobj)
+{
+	kref_put(&uobj->ref, release_uobj);
+}
+
+static void put_uobj_read(struct ib_uobject *uobj)
+{
+	up_read(&uobj->mutex);
+	put_uobj(uobj);
+}
+
+static void put_uobj_write(struct ib_uobject *uobj)
+{
+	up_write(&uobj->mutex);
+	put_uobj(uobj);
+}
+
+static int idr_add_uobj(struct idr *idr, struct ib_uobject *uobj)
+{
+	int ret;
+
+retry:
+	if (!idr_pre_get(idr, GFP_KERNEL))
+		return -ENOMEM;
+
+	spin_lock(&ib_uverbs_idr_lock);
+	ret = idr_get_new(idr, uobj, &uobj->id);
+	spin_unlock(&ib_uverbs_idr_lock);
+
+	if (ret == -EAGAIN)
+		goto retry;
+
+	return ret;
+}
+
+void idr_remove_uobj(struct idr *idr, struct ib_uobject *uobj)
+{
+	spin_lock(&ib_uverbs_idr_lock);
+	idr_remove(idr, uobj->id);
+	spin_unlock(&ib_uverbs_idr_lock);
+}
+
+static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
+					 struct ib_ucontext *context)
+{
+	struct ib_uobject *uobj;
+
+	spin_lock(&ib_uverbs_idr_lock);
+	uobj = idr_find(idr, id);
+	if (uobj)
+		kref_get(&uobj->ref);
+	spin_unlock(&ib_uverbs_idr_lock);
+
+	return uobj;
+}
+
+static struct ib_uobject *idr_read_uobj(struct idr *idr, int id,
+					struct ib_ucontext *context)
+{
+	struct ib_uobject *uobj;
+
+	uobj = __idr_get_uobj(idr, id, context);
+	if (!uobj)
+		return NULL;
+
+	down_read(&uobj->mutex);
+	if (!uobj->live) {
+		put_uobj_read(uobj);
+		return NULL;
+	}
+
+	return uobj;
+}
+
+static struct ib_uobject *idr_write_uobj(struct idr *idr, int id,
+					 struct ib_ucontext *context)
+{
+	struct ib_uobject *uobj;
+
+	uobj = __idr_get_uobj(idr, id, context);
+	if (!uobj)
+		return NULL;
+
+	down_write(&uobj->mutex);
+	if (!uobj->live) {
+		put_uobj_write(uobj);
+		return NULL;
+	}
+
+	return uobj;
+}
+
+static void *idr_read_obj(struct idr *idr, int id, struct ib_ucontext *context)
+{
+	struct ib_uobject *uobj;
+
+	uobj = idr_read_uobj(idr, id, context);
+	return uobj ? uobj->object : NULL;
+}
+
+static struct ib_pd *idr_read_pd(int pd_handle, struct ib_ucontext *context)
+{
+	return idr_read_obj(&ib_uverbs_pd_idr, pd_handle, context);
+}
+
+static void put_pd_read(struct ib_pd *pd)
+{
+	put_uobj_read(pd->uobject);
+}
+
+static struct ib_cq *idr_read_cq(int cq_handle, struct ib_ucontext *context)
+{
+	return idr_read_obj(&ib_uverbs_cq_idr, cq_handle, context);
+}
+
+static void put_cq_read(struct ib_cq *cq)
+{
+	put_uobj_read(cq->uobject);
+}
+
+static struct ib_ah *idr_read_ah(int ah_handle, struct ib_ucontext *context)
+{
+	return idr_read_obj(&ib_uverbs_ah_idr, ah_handle, context);
+}
+
+static void put_ah_read(struct ib_ah *ah)
+{
+	put_uobj_read(ah->uobject);
+}
+
+static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context)
+{
+	return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context);
+}
+
+static void put_qp_read(struct ib_qp *qp)
+{
+	put_uobj_read(qp->uobject);
+}
+
+static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
+{
+	return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context);
+}
+
+static void put_srq_read(struct ib_srq *srq)
+{
+	put_uobj_read(srq->uobject);
+}
+
 ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
 			      const char __user *buf,
 			      int in_len, int out_len)
@@ -80,8 +270,10 @@
 		   in_len - sizeof cmd, out_len - sizeof resp);
 
 	ucontext = ibdev->alloc_ucontext(ibdev, &udata);
-	if (IS_ERR(ucontext))
-		return PTR_ERR(file->ucontext);
+	if (IS_ERR(ucontext)) {
+		ret = PTR_ERR(file->ucontext);
+		goto err;
+	}
 
 	ucontext->device = ibdev;
 	INIT_LIST_HEAD(&ucontext->pd_list);
@@ -278,7 +470,8 @@
 	if (!uobj)
 		return -ENOMEM;
 
-	uobj->context = file->ucontext;
+	init_uobj(uobj, 0, file->ucontext);
+	down_write(&uobj->mutex);
 
 	pd = file->device->ib_dev->alloc_pd(file->device->ib_dev,
 					    file->ucontext, &udata);
@@ -291,20 +484,10 @@
 	pd->uobject = uobj;
 	atomic_set(&pd->usecnt, 0);
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-retry:
-	if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) {
-		ret = -ENOMEM;
-		goto err_up;
-	}
-
-	ret = idr_get_new(&ib_uverbs_pd_idr, pd, &uobj->id);
-
-	if (ret == -EAGAIN)
-		goto retry;
+	uobj->object = pd;
+	ret = idr_add_uobj(&ib_uverbs_pd_idr, uobj);
 	if (ret)
-		goto err_up;
+		goto err_idr;
 
 	memset(&resp, 0, sizeof resp);
 	resp.pd_handle = uobj->id;
@@ -312,26 +495,27 @@
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_idr;
+		goto err_copy;
 	}
 
 	mutex_lock(&file->mutex);
 	list_add_tail(&uobj->list, &file->ucontext->pd_list);
 	mutex_unlock(&file->mutex);
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	uobj->live = 1;
+
+	up_write(&uobj->mutex);
 
 	return in_len;
 
-err_idr:
-	idr_remove(&ib_uverbs_pd_idr, uobj->id);
+err_copy:
+	idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
 
-err_up:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+err_idr:
 	ib_dealloc_pd(pd);
 
 err:
-	kfree(uobj);
+	put_uobj_write(uobj);
 	return ret;
 }
 
@@ -340,37 +524,34 @@
 			     int in_len, int out_len)
 {
 	struct ib_uverbs_dealloc_pd cmd;
-	struct ib_pd               *pd;
 	struct ib_uobject          *uobj;
-	int                         ret = -EINVAL;
+	int                         ret;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	uobj = idr_write_uobj(&ib_uverbs_pd_idr, cmd.pd_handle, file->ucontext);
+	if (!uobj)
+		return -EINVAL;
 
-	pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-	if (!pd || pd->uobject->context != file->ucontext)
-		goto out;
+	ret = ib_dealloc_pd(uobj->object);
+	if (!ret)
+		uobj->live = 0;
 
-	uobj = pd->uobject;
+	put_uobj_write(uobj);
 
-	ret = ib_dealloc_pd(pd);
 	if (ret)
-		goto out;
+		return ret;
 
-	idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle);
+	idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
 
 	mutex_lock(&file->mutex);
 	list_del(&uobj->list);
 	mutex_unlock(&file->mutex);
 
-	kfree(uobj);
+	put_uobj(uobj);
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
-	return ret ? ret : in_len;
+	return in_len;
 }
 
 ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
@@ -410,7 +591,8 @@
 	if (!obj)
 		return -ENOMEM;
 
-	obj->uobject.context = file->ucontext;
+	init_uobj(&obj->uobject, 0, file->ucontext);
+	down_write(&obj->uobject.mutex);
 
 	/*
 	 * We ask for writable memory if any access flags other than
@@ -427,23 +609,14 @@
 
 	obj->umem.virt_base = cmd.hca_va;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-	if (!pd || pd->uobject->context != file->ucontext) {
-		ret = -EINVAL;
-		goto err_up;
-	}
-
-	if (!pd->device->reg_user_mr) {
-		ret = -ENOSYS;
-		goto err_up;
-	}
+	pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+	if (!pd)
+		goto err_release;
 
 	mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata);
 	if (IS_ERR(mr)) {
 		ret = PTR_ERR(mr);
-		goto err_up;
+		goto err_put;
 	}
 
 	mr->device  = pd->device;
@@ -452,53 +625,48 @@
 	atomic_inc(&pd->usecnt);
 	atomic_set(&mr->usecnt, 0);
 
-	memset(&resp, 0, sizeof resp);
-	resp.lkey = mr->lkey;
-	resp.rkey = mr->rkey;
-
-retry:
-	if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) {
-		ret = -ENOMEM;
-		goto err_unreg;
-	}
-
-	ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id);
-
-	if (ret == -EAGAIN)
-		goto retry;
+	obj->uobject.object = mr;
+	ret = idr_add_uobj(&ib_uverbs_mr_idr, &obj->uobject);
 	if (ret)
 		goto err_unreg;
 
+	memset(&resp, 0, sizeof resp);
+	resp.lkey      = mr->lkey;
+	resp.rkey      = mr->rkey;
 	resp.mr_handle = obj->uobject.id;
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_idr;
+		goto err_copy;
 	}
 
+	put_pd_read(pd);
+
 	mutex_lock(&file->mutex);
 	list_add_tail(&obj->uobject.list, &file->ucontext->mr_list);
 	mutex_unlock(&file->mutex);
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	obj->uobject.live = 1;
+
+	up_write(&obj->uobject.mutex);
 
 	return in_len;
 
-err_idr:
-	idr_remove(&ib_uverbs_mr_idr, obj->uobject.id);
+err_copy:
+	idr_remove_uobj(&ib_uverbs_mr_idr, &obj->uobject);
 
 err_unreg:
 	ib_dereg_mr(mr);
-	atomic_dec(&pd->usecnt);
 
-err_up:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+err_put:
+	put_pd_read(pd);
 
+err_release:
 	ib_umem_release(file->device->ib_dev, &obj->umem);
 
 err_free:
-	kfree(obj);
+	put_uobj_write(&obj->uobject);
 	return ret;
 }
 
@@ -508,37 +676,40 @@
 {
 	struct ib_uverbs_dereg_mr cmd;
 	struct ib_mr             *mr;
+	struct ib_uobject	 *uobj;
 	struct ib_umem_object    *memobj;
 	int                       ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	uobj = idr_write_uobj(&ib_uverbs_mr_idr, cmd.mr_handle, file->ucontext);
+	if (!uobj)
+		return -EINVAL;
 
-	mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle);
-	if (!mr || mr->uobject->context != file->ucontext)
-		goto out;
-
-	memobj = container_of(mr->uobject, struct ib_umem_object, uobject);
+	memobj = container_of(uobj, struct ib_umem_object, uobject);
+	mr     = uobj->object;
 
 	ret = ib_dereg_mr(mr);
-	if (ret)
-		goto out;
+	if (!ret)
+		uobj->live = 0;
 
-	idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle);
+	put_uobj_write(uobj);
+
+	if (ret)
+		return ret;
+
+	idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
 
 	mutex_lock(&file->mutex);
-	list_del(&memobj->uobject.list);
+	list_del(&uobj->list);
 	mutex_unlock(&file->mutex);
 
 	ib_umem_release(file->device->ib_dev, &memobj->umem);
-	kfree(memobj);
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	put_uobj(uobj);
 
-	return ret ? ret : in_len;
+	return in_len;
 }
 
 ssize_t ib_uverbs_create_comp_channel(struct ib_uverbs_file *file,
@@ -577,7 +748,7 @@
 	struct ib_uverbs_create_cq      cmd;
 	struct ib_uverbs_create_cq_resp resp;
 	struct ib_udata                 udata;
-	struct ib_ucq_object           *uobj;
+	struct ib_ucq_object           *obj;
 	struct ib_uverbs_event_file    *ev_file = NULL;
 	struct ib_cq                   *cq;
 	int                             ret;
@@ -595,10 +766,13 @@
 	if (cmd.comp_vector >= file->device->num_comp_vectors)
 		return -EINVAL;
 
-	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
-	if (!uobj)
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj)
 		return -ENOMEM;
 
+	init_uobj(&obj->uobject, cmd.user_handle, file->ucontext);
+	down_write(&obj->uobject.mutex);
+
 	if (cmd.comp_channel >= 0) {
 		ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel);
 		if (!ev_file) {
@@ -607,72 +781,64 @@
 		}
 	}
 
-	uobj->uobject.user_handle   = cmd.user_handle;
-	uobj->uobject.context       = file->ucontext;
-	uobj->uverbs_file	    = file;
-	uobj->comp_events_reported  = 0;
-	uobj->async_events_reported = 0;
-	INIT_LIST_HEAD(&uobj->comp_list);
-	INIT_LIST_HEAD(&uobj->async_list);
+	obj->uverbs_file	   = file;
+	obj->comp_events_reported  = 0;
+	obj->async_events_reported = 0;
+	INIT_LIST_HEAD(&obj->comp_list);
+	INIT_LIST_HEAD(&obj->async_list);
 
 	cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe,
 					     file->ucontext, &udata);
 	if (IS_ERR(cq)) {
 		ret = PTR_ERR(cq);
-		goto err;
+		goto err_file;
 	}
 
 	cq->device        = file->device->ib_dev;
-	cq->uobject       = &uobj->uobject;
+	cq->uobject       = &obj->uobject;
 	cq->comp_handler  = ib_uverbs_comp_handler;
 	cq->event_handler = ib_uverbs_cq_event_handler;
 	cq->cq_context    = ev_file;
 	atomic_set(&cq->usecnt, 0);
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-retry:
-	if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) {
-		ret = -ENOMEM;
-		goto err_up;
-	}
-
-	ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id);
-
-	if (ret == -EAGAIN)
-		goto retry;
+	obj->uobject.object = cq;
+	ret = idr_add_uobj(&ib_uverbs_cq_idr, &obj->uobject);
 	if (ret)
-		goto err_up;
+		goto err_free;
 
 	memset(&resp, 0, sizeof resp);
-	resp.cq_handle = uobj->uobject.id;
+	resp.cq_handle = obj->uobject.id;
 	resp.cqe       = cq->cqe;
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_idr;
+		goto err_copy;
 	}
 
 	mutex_lock(&file->mutex);
-	list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list);
+	list_add_tail(&obj->uobject.list, &file->ucontext->cq_list);
 	mutex_unlock(&file->mutex);
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	obj->uobject.live = 1;
+
+	up_write(&obj->uobject.mutex);
 
 	return in_len;
 
-err_idr:
-	idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id);
+err_copy:
+	idr_remove_uobj(&ib_uverbs_cq_idr, &obj->uobject);
 
-err_up:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+
+err_free:
 	ib_destroy_cq(cq);
 
-err:
+err_file:
 	if (ev_file)
-		ib_uverbs_release_ucq(file, ev_file, uobj);
-	kfree(uobj);
+		ib_uverbs_release_ucq(file, ev_file, obj);
+
+err:
+	put_uobj_write(&obj->uobject);
 	return ret;
 }
 
@@ -693,11 +859,9 @@
 		   (unsigned long) cmd.response + sizeof resp,
 		   in_len - sizeof cmd, out_len - sizeof resp);
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-	if (!cq || cq->uobject->context != file->ucontext || !cq->device->resize_cq)
-		goto out;
+	cq = idr_read_cq(cmd.cq_handle, file->ucontext);
+	if (!cq)
+		return -EINVAL;
 
 	ret = cq->device->resize_cq(cq, cmd.cqe, &udata);
 	if (ret)
@@ -711,7 +875,7 @@
 		ret = -EFAULT;
 
 out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	put_cq_read(cq);
 
 	return ret ? ret : in_len;
 }
@@ -722,6 +886,7 @@
 {
 	struct ib_uverbs_poll_cq       cmd;
 	struct ib_uverbs_poll_cq_resp *resp;
+	struct ib_uobject	      *uobj;
 	struct ib_cq                  *cq;
 	struct ib_wc                  *wc;
 	int                            ret = 0;
@@ -742,15 +907,17 @@
 		goto out_wc;
 	}
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-	cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-	if (!cq || cq->uobject->context != file->ucontext) {
+	uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
+	if (!uobj) {
 		ret = -EINVAL;
 		goto out;
 	}
+	cq = uobj->object;
 
 	resp->count = ib_poll_cq(cq, cmd.ne, wc);
 
+	put_uobj_read(uobj);
+
 	for (i = 0; i < resp->count; i++) {
 		resp->wc[i].wr_id 	   = wc[i].wr_id;
 		resp->wc[i].status 	   = wc[i].status;
@@ -772,7 +939,6 @@
 		ret = -EFAULT;
 
 out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
 	kfree(resp);
 
 out_wc:
@@ -785,22 +951,23 @@
 				int out_len)
 {
 	struct ib_uverbs_req_notify_cq cmd;
+	struct ib_uobject	      *uobj;
 	struct ib_cq                  *cq;
-	int                            ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-	cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-	if (cq && cq->uobject->context == file->ucontext) {
-		ib_req_notify_cq(cq, cmd.solicited_only ?
-					IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
-		ret = in_len;
-	}
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	uobj = idr_read_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
+	if (!uobj)
+		return -EINVAL;
+	cq = uobj->object;
 
-	return ret;
+	ib_req_notify_cq(cq, cmd.solicited_only ?
+			 IB_CQ_SOLICITED : IB_CQ_NEXT_COMP);
+
+	put_uobj_read(uobj);
+
+	return in_len;
 }
 
 ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file,
@@ -809,52 +976,50 @@
 {
 	struct ib_uverbs_destroy_cq      cmd;
 	struct ib_uverbs_destroy_cq_resp resp;
+	struct ib_uobject		*uobj;
 	struct ib_cq               	*cq;
-	struct ib_ucq_object        	*uobj;
+	struct ib_ucq_object        	*obj;
 	struct ib_uverbs_event_file	*ev_file;
-	u64				 user_handle;
 	int                        	 ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	memset(&resp, 0, sizeof resp);
-
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle);
-	if (!cq || cq->uobject->context != file->ucontext)
-		goto out;
-
-	user_handle = cq->uobject->user_handle;
-	uobj        = container_of(cq->uobject, struct ib_ucq_object, uobject);
-	ev_file     = cq->cq_context;
+	uobj = idr_write_uobj(&ib_uverbs_cq_idr, cmd.cq_handle, file->ucontext);
+	if (!uobj)
+		return -EINVAL;
+	cq      = uobj->object;
+	ev_file = cq->cq_context;
+	obj     = container_of(cq->uobject, struct ib_ucq_object, uobject);
 
 	ret = ib_destroy_cq(cq);
-	if (ret)
-		goto out;
+	if (!ret)
+		uobj->live = 0;
 
-	idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle);
+	put_uobj_write(uobj);
+
+	if (ret)
+		return ret;
+
+	idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
 
 	mutex_lock(&file->mutex);
-	list_del(&uobj->uobject.list);
+	list_del(&uobj->list);
 	mutex_unlock(&file->mutex);
 
-	ib_uverbs_release_ucq(file, ev_file, uobj);
+	ib_uverbs_release_ucq(file, ev_file, obj);
 
-	resp.comp_events_reported  = uobj->comp_events_reported;
-	resp.async_events_reported = uobj->async_events_reported;
+	memset(&resp, 0, sizeof resp);
+	resp.comp_events_reported  = obj->comp_events_reported;
+	resp.async_events_reported = obj->async_events_reported;
 
-	kfree(uobj);
+	put_uobj(uobj);
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp))
-		ret = -EFAULT;
+		return -EFAULT;
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
-	return ret ? ret : in_len;
+	return in_len;
 }
 
 ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file,
@@ -864,7 +1029,7 @@
 	struct ib_uverbs_create_qp      cmd;
 	struct ib_uverbs_create_qp_resp resp;
 	struct ib_udata                 udata;
-	struct ib_uqp_object           *uobj;
+	struct ib_uqp_object           *obj;
 	struct ib_pd                   *pd;
 	struct ib_cq                   *scq, *rcq;
 	struct ib_srq                  *srq;
@@ -882,23 +1047,21 @@
 		   (unsigned long) cmd.response + sizeof resp,
 		   in_len - sizeof cmd, out_len - sizeof resp);
 
-	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
-	if (!uobj)
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj)
 		return -ENOMEM;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	init_uobj(&obj->uevent.uobject, cmd.user_handle, file->ucontext);
+	down_write(&obj->uevent.uobject.mutex);
 
-	pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-	scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
-	rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
-	srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL;
+	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+	scq = idr_read_cq(cmd.send_cq_handle, file->ucontext);
+	rcq = idr_read_cq(cmd.recv_cq_handle, file->ucontext);
+	srq = cmd.is_srq ? idr_read_srq(cmd.srq_handle, file->ucontext) : NULL;
 
-	if (!pd  || pd->uobject->context  != file->ucontext ||
-	    !scq || scq->uobject->context != file->ucontext ||
-	    !rcq || rcq->uobject->context != file->ucontext ||
-	    (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
+	if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
 		ret = -EINVAL;
-		goto err_up;
+		goto err_put;
 	}
 
 	attr.event_handler = ib_uverbs_qp_event_handler;
@@ -915,16 +1078,14 @@
 	attr.cap.max_recv_sge    = cmd.max_recv_sge;
 	attr.cap.max_inline_data = cmd.max_inline_data;
 
-	uobj->uevent.uobject.user_handle = cmd.user_handle;
-	uobj->uevent.uobject.context     = file->ucontext;
-	uobj->uevent.events_reported     = 0;
-	INIT_LIST_HEAD(&uobj->uevent.event_list);
-	INIT_LIST_HEAD(&uobj->mcast_list);
+	obj->uevent.events_reported     = 0;
+	INIT_LIST_HEAD(&obj->uevent.event_list);
+	INIT_LIST_HEAD(&obj->mcast_list);
 
 	qp = pd->device->create_qp(pd, &attr, &udata);
 	if (IS_ERR(qp)) {
 		ret = PTR_ERR(qp);
-		goto err_up;
+		goto err_put;
 	}
 
 	qp->device     	  = pd->device;
@@ -932,7 +1093,7 @@
 	qp->send_cq    	  = attr.send_cq;
 	qp->recv_cq    	  = attr.recv_cq;
 	qp->srq	       	  = attr.srq;
-	qp->uobject       = &uobj->uevent.uobject;
+	qp->uobject       = &obj->uevent.uobject;
 	qp->event_handler = attr.event_handler;
 	qp->qp_context    = attr.qp_context;
 	qp->qp_type	  = attr.qp_type;
@@ -942,23 +1103,14 @@
 	if (attr.srq)
 		atomic_inc(&attr.srq->usecnt);
 
-	memset(&resp, 0, sizeof resp);
-	resp.qpn = qp->qp_num;
-
-retry:
-	if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) {
-		ret = -ENOMEM;
-		goto err_destroy;
-	}
-
-	ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uevent.uobject.id);
-
-	if (ret == -EAGAIN)
-		goto retry;
+	obj->uevent.uobject.object = qp;
+	ret = idr_add_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
 	if (ret)
 		goto err_destroy;
 
-	resp.qp_handle       = uobj->uevent.uobject.id;
+	memset(&resp, 0, sizeof resp);
+	resp.qpn             = qp->qp_num;
+	resp.qp_handle       = obj->uevent.uobject.id;
 	resp.max_recv_sge    = attr.cap.max_recv_sge;
 	resp.max_send_sge    = attr.cap.max_send_sge;
 	resp.max_recv_wr     = attr.cap.max_recv_wr;
@@ -968,32 +1120,42 @@
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_idr;
+		goto err_copy;
 	}
 
+	put_pd_read(pd);
+	put_cq_read(scq);
+	put_cq_read(rcq);
+	if (srq)
+		put_srq_read(srq);
+
 	mutex_lock(&file->mutex);
-	list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list);
+	list_add_tail(&obj->uevent.uobject.list, &file->ucontext->qp_list);
 	mutex_unlock(&file->mutex);
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	obj->uevent.uobject.live = 1;
+
+	up_write(&obj->uevent.uobject.mutex);
 
 	return in_len;
 
-err_idr:
-	idr_remove(&ib_uverbs_qp_idr, uobj->uevent.uobject.id);
+err_copy:
+	idr_remove_uobj(&ib_uverbs_qp_idr, &obj->uevent.uobject);
 
 err_destroy:
 	ib_destroy_qp(qp);
-	atomic_dec(&pd->usecnt);
-	atomic_dec(&attr.send_cq->usecnt);
-	atomic_dec(&attr.recv_cq->usecnt);
-	if (attr.srq)
-		atomic_dec(&attr.srq->usecnt);
 
-err_up:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+err_put:
+	if (pd)
+		put_pd_read(pd);
+	if (scq)
+		put_cq_read(scq);
+	if (rcq)
+		put_cq_read(rcq);
+	if (srq)
+		put_srq_read(srq);
 
-	kfree(uobj);
+	put_uobj_write(&obj->uevent.uobject);
 	return ret;
 }
 
@@ -1018,15 +1180,15 @@
 		goto out;
 	}
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-	if (qp && qp->uobject->context == file->ucontext)
-		ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr);
-	else
+	qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+	if (!qp) {
 		ret = -EINVAL;
+		goto out;
+	}
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	ret = ib_query_qp(qp, attr, cmd.attr_mask, init_attr);
+
+	put_qp_read(qp);
 
 	if (ret)
 		goto out;
@@ -1113,10 +1275,8 @@
 	if (!attr)
 		return -ENOMEM;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-	if (!qp || qp->uobject->context != file->ucontext) {
+	qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+	if (!qp) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -1168,13 +1328,15 @@
 	attr->alt_ah_attr.port_num 	    = cmd.alt_dest.port_num;
 
 	ret = ib_modify_qp(qp, attr, cmd.attr_mask);
+
+	put_qp_read(qp);
+
 	if (ret)
 		goto out;
 
 	ret = in_len;
 
 out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
 	kfree(attr);
 
 	return ret;
@@ -1186,8 +1348,9 @@
 {
 	struct ib_uverbs_destroy_qp      cmd;
 	struct ib_uverbs_destroy_qp_resp resp;
+	struct ib_uobject		*uobj;
 	struct ib_qp               	*qp;
-	struct ib_uqp_object        	*uobj;
+	struct ib_uqp_object        	*obj;
 	int                        	 ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1195,43 +1358,43 @@
 
 	memset(&resp, 0, sizeof resp);
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	uobj = idr_write_uobj(&ib_uverbs_qp_idr, cmd.qp_handle, file->ucontext);
+	if (!uobj)
+		return -EINVAL;
+	qp  = uobj->object;
+	obj = container_of(uobj, struct ib_uqp_object, uevent.uobject);
 
-	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-	if (!qp || qp->uobject->context != file->ucontext)
-		goto out;
-
-	uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
-
-	if (!list_empty(&uobj->mcast_list)) {
-		ret = -EBUSY;
-		goto out;
+	if (!list_empty(&obj->mcast_list)) {
+		put_uobj_write(uobj);
+		return -EBUSY;
 	}
 
 	ret = ib_destroy_qp(qp);
-	if (ret)
-		goto out;
+	if (!ret)
+		uobj->live = 0;
 
-	idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle);
+	put_uobj_write(uobj);
+
+	if (ret)
+		return ret;
+
+	idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
 
 	mutex_lock(&file->mutex);
-	list_del(&uobj->uevent.uobject.list);
+	list_del(&uobj->list);
 	mutex_unlock(&file->mutex);
 
-	ib_uverbs_release_uevent(file, &uobj->uevent);
+	ib_uverbs_release_uevent(file, &obj->uevent);
 
-	resp.events_reported = uobj->uevent.events_reported;
+	resp.events_reported = obj->uevent.events_reported;
 
-	kfree(uobj);
+	put_uobj(uobj);
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp))
-		ret = -EFAULT;
+		return -EFAULT;
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
-	return ret ? ret : in_len;
+	return in_len;
 }
 
 ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
@@ -1244,6 +1407,7 @@
 	struct ib_send_wr              *wr = NULL, *last, *next, *bad_wr;
 	struct ib_qp                   *qp;
 	int                             i, sg_ind;
+	int				is_ud;
 	ssize_t                         ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
@@ -1260,12 +1424,11 @@
 	if (!user_wr)
 		return -ENOMEM;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-	if (!qp || qp->uobject->context != file->ucontext)
+	qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+	if (!qp)
 		goto out;
 
+	is_ud = qp->qp_type == IB_QPT_UD;
 	sg_ind = 0;
 	last = NULL;
 	for (i = 0; i < cmd.wr_count; ++i) {
@@ -1273,12 +1436,12 @@
 				   buf + sizeof cmd + i * cmd.wqe_size,
 				   cmd.wqe_size)) {
 			ret = -EFAULT;
-			goto out;
+			goto out_put;
 		}
 
 		if (user_wr->num_sge + sg_ind > cmd.sge_count) {
 			ret = -EINVAL;
-			goto out;
+			goto out_put;
 		}
 
 		next = kmalloc(ALIGN(sizeof *next, sizeof (struct ib_sge)) +
@@ -1286,7 +1449,7 @@
 			       GFP_KERNEL);
 		if (!next) {
 			ret = -ENOMEM;
-			goto out;
+			goto out_put;
 		}
 
 		if (!last)
@@ -1302,12 +1465,12 @@
 		next->send_flags = user_wr->send_flags;
 		next->imm_data   = (__be32 __force) user_wr->imm_data;
 
-		if (qp->qp_type == IB_QPT_UD) {
-			next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr,
-						  user_wr->wr.ud.ah);
+		if (is_ud) {
+			next->wr.ud.ah = idr_read_ah(user_wr->wr.ud.ah,
+						     file->ucontext);
 			if (!next->wr.ud.ah) {
 				ret = -EINVAL;
-				goto out;
+				goto out_put;
 			}
 			next->wr.ud.remote_qpn  = user_wr->wr.ud.remote_qpn;
 			next->wr.ud.remote_qkey = user_wr->wr.ud.remote_qkey;
@@ -1344,7 +1507,7 @@
 					   sg_ind * sizeof (struct ib_sge),
 					   next->num_sge * sizeof (struct ib_sge))) {
 				ret = -EFAULT;
-				goto out;
+				goto out_put;
 			}
 			sg_ind += next->num_sge;
 		} else
@@ -1364,15 +1527,18 @@
 			 &resp, sizeof resp))
 		ret = -EFAULT;
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+out_put:
+	put_qp_read(qp);
 
 	while (wr) {
+		if (is_ud && wr->wr.ud.ah)
+			put_ah_read(wr->wr.ud.ah);
 		next = wr->next;
 		kfree(wr);
 		wr = next;
 	}
 
+out:
 	kfree(user_wr);
 
 	return ret ? ret : in_len;
@@ -1482,14 +1648,15 @@
 	if (IS_ERR(wr))
 		return PTR_ERR(wr);
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-	if (!qp || qp->uobject->context != file->ucontext)
+	qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+	if (!qp)
 		goto out;
 
 	resp.bad_wr = 0;
 	ret = qp->device->post_recv(qp, wr, &bad_wr);
+
+	put_qp_read(qp);
+
 	if (ret)
 		for (next = wr; next; next = next->next) {
 			++resp.bad_wr;
@@ -1503,8 +1670,6 @@
 		ret = -EFAULT;
 
 out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
 	while (wr) {
 		next = wr->next;
 		kfree(wr);
@@ -1533,14 +1698,15 @@
 	if (IS_ERR(wr))
 		return PTR_ERR(wr);
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-	if (!srq || srq->uobject->context != file->ucontext)
+	srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+	if (!srq)
 		goto out;
 
 	resp.bad_wr = 0;
 	ret = srq->device->post_srq_recv(srq, wr, &bad_wr);
+
+	put_srq_read(srq);
+
 	if (ret)
 		for (next = wr; next; next = next->next) {
 			++resp.bad_wr;
@@ -1554,8 +1720,6 @@
 		ret = -EFAULT;
 
 out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
 	while (wr) {
 		next = wr->next;
 		kfree(wr);
@@ -1587,17 +1751,15 @@
 	if (!uobj)
 		return -ENOMEM;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	init_uobj(uobj, cmd.user_handle, file->ucontext);
+	down_write(&uobj->mutex);
 
-	pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-	if (!pd || pd->uobject->context != file->ucontext) {
+	pd = idr_read_pd(cmd.pd_handle, file->ucontext);
+	if (!pd) {
 		ret = -EINVAL;
-		goto err_up;
+		goto err;
 	}
 
-	uobj->user_handle = cmd.user_handle;
-	uobj->context     = file->ucontext;
-
 	attr.dlid 	       = cmd.attr.dlid;
 	attr.sl 	       = cmd.attr.sl;
 	attr.src_path_bits     = cmd.attr.src_path_bits;
@@ -1613,21 +1775,13 @@
 	ah = ib_create_ah(pd, &attr);
 	if (IS_ERR(ah)) {
 		ret = PTR_ERR(ah);
-		goto err_up;
+		goto err;
 	}
 
-	ah->uobject = uobj;
+	ah->uobject  = uobj;
+	uobj->object = ah;
 
-retry:
-	if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) {
-		ret = -ENOMEM;
-		goto err_destroy;
-	}
-
-	ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id);
-
-	if (ret == -EAGAIN)
-		goto retry;
+	ret = idr_add_uobj(&ib_uverbs_ah_idr, uobj);
 	if (ret)
 		goto err_destroy;
 
@@ -1636,27 +1790,29 @@
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_idr;
+		goto err_copy;
 	}
 
+	put_pd_read(pd);
+
 	mutex_lock(&file->mutex);
 	list_add_tail(&uobj->list, &file->ucontext->ah_list);
 	mutex_unlock(&file->mutex);
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	uobj->live = 1;
+
+	up_write(&uobj->mutex);
 
 	return in_len;
 
-err_idr:
-	idr_remove(&ib_uverbs_ah_idr, uobj->id);
+err_copy:
+	idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
 
 err_destroy:
 	ib_destroy_ah(ah);
 
-err_up:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
-	kfree(uobj);
+err:
+	put_uobj_write(uobj);
 	return ret;
 }
 
@@ -1666,35 +1822,34 @@
 	struct ib_uverbs_destroy_ah cmd;
 	struct ib_ah		   *ah;
 	struct ib_uobject	   *uobj;
-	int			    ret = -EINVAL;
+	int			    ret;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);
-	if (!ah || ah->uobject->context != file->ucontext)
-		goto out;
-
-	uobj = ah->uobject;
+	uobj = idr_write_uobj(&ib_uverbs_ah_idr, cmd.ah_handle, file->ucontext);
+	if (!uobj)
+		return -EINVAL;
+	ah = uobj->object;
 
 	ret = ib_destroy_ah(ah);
-	if (ret)
-		goto out;
+	if (!ret)
+		uobj->live = 0;
 
-	idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);
+	put_uobj_write(uobj);
+
+	if (ret)
+		return ret;
+
+	idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
 
 	mutex_lock(&file->mutex);
 	list_del(&uobj->list);
 	mutex_unlock(&file->mutex);
 
-	kfree(uobj);
+	put_uobj(uobj);
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
-	return ret ? ret : in_len;
+	return in_len;
 }
 
 ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file,
@@ -1703,47 +1858,43 @@
 {
 	struct ib_uverbs_attach_mcast cmd;
 	struct ib_qp                 *qp;
-	struct ib_uqp_object         *uobj;
+	struct ib_uqp_object         *obj;
 	struct ib_uverbs_mcast_entry *mcast;
-	int                           ret = -EINVAL;
+	int                           ret;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+	if (!qp)
+		return -EINVAL;
 
-	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-	if (!qp || qp->uobject->context != file->ucontext)
-		goto out;
+	obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
 
-	uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
-
-	list_for_each_entry(mcast, &uobj->mcast_list, list)
+	list_for_each_entry(mcast, &obj->mcast_list, list)
 		if (cmd.mlid == mcast->lid &&
 		    !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
 			ret = 0;
-			goto out;
+			goto out_put;
 		}
 
 	mcast = kmalloc(sizeof *mcast, GFP_KERNEL);
 	if (!mcast) {
 		ret = -ENOMEM;
-		goto out;
+		goto out_put;
 	}
 
 	mcast->lid = cmd.mlid;
 	memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);
 
 	ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);
-	if (!ret) {
-		uobj = container_of(qp->uobject, struct ib_uqp_object,
-				    uevent.uobject);
-		list_add_tail(&mcast->list, &uobj->mcast_list);
-	} else
+	if (!ret)
+		list_add_tail(&mcast->list, &obj->mcast_list);
+	else
 		kfree(mcast);
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+out_put:
+	put_qp_read(qp);
 
 	return ret ? ret : in_len;
 }
@@ -1753,7 +1904,7 @@
 			       int out_len)
 {
 	struct ib_uverbs_detach_mcast cmd;
-	struct ib_uqp_object         *uobj;
+	struct ib_uqp_object         *obj;
 	struct ib_qp                 *qp;
 	struct ib_uverbs_mcast_entry *mcast;
 	int                           ret = -EINVAL;
@@ -1761,19 +1912,17 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);
-	if (!qp || qp->uobject->context != file->ucontext)
-		goto out;
+	qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+	if (!qp)
+		return -EINVAL;
 
 	ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);
 	if (ret)
-		goto out;
+		goto out_put;
 
-	uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
+	obj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);
 
-	list_for_each_entry(mcast, &uobj->mcast_list, list)
+	list_for_each_entry(mcast, &obj->mcast_list, list)
 		if (cmd.mlid == mcast->lid &&
 		    !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {
 			list_del(&mcast->list);
@@ -1781,8 +1930,8 @@
 			break;
 		}
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+out_put:
+	put_qp_read(qp);
 
 	return ret ? ret : in_len;
 }
@@ -1794,7 +1943,7 @@
 	struct ib_uverbs_create_srq      cmd;
 	struct ib_uverbs_create_srq_resp resp;
 	struct ib_udata                  udata;
-	struct ib_uevent_object         *uobj;
+	struct ib_uevent_object         *obj;
 	struct ib_pd                    *pd;
 	struct ib_srq                   *srq;
 	struct ib_srq_init_attr          attr;
@@ -1810,17 +1959,17 @@
 		   (unsigned long) cmd.response + sizeof resp,
 		   in_len - sizeof cmd, out_len - sizeof resp);
 
-	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
-	if (!uobj)
+	obj = kmalloc(sizeof *obj, GFP_KERNEL);
+	if (!obj)
 		return -ENOMEM;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	init_uobj(&obj->uobject, 0, file->ucontext);
+	down_write(&obj->uobject.mutex);
 
-	pd  = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle);
-
-	if (!pd || pd->uobject->context != file->ucontext) {
+	pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+	if (!pd) {
 		ret = -EINVAL;
-		goto err_up;
+		goto err;
 	}
 
 	attr.event_handler  = ib_uverbs_srq_event_handler;
@@ -1829,69 +1978,59 @@
 	attr.attr.max_sge   = cmd.max_sge;
 	attr.attr.srq_limit = cmd.srq_limit;
 
-	uobj->uobject.user_handle = cmd.user_handle;
-	uobj->uobject.context     = file->ucontext;
-	uobj->events_reported     = 0;
-	INIT_LIST_HEAD(&uobj->event_list);
+	obj->events_reported     = 0;
+	INIT_LIST_HEAD(&obj->event_list);
 
 	srq = pd->device->create_srq(pd, &attr, &udata);
 	if (IS_ERR(srq)) {
 		ret = PTR_ERR(srq);
-		goto err_up;
+		goto err;
 	}
 
 	srq->device    	   = pd->device;
 	srq->pd        	   = pd;
-	srq->uobject       = &uobj->uobject;
+	srq->uobject       = &obj->uobject;
 	srq->event_handler = attr.event_handler;
 	srq->srq_context   = attr.srq_context;
 	atomic_inc(&pd->usecnt);
 	atomic_set(&srq->usecnt, 0);
 
-	memset(&resp, 0, sizeof resp);
-
-retry:
-	if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) {
-		ret = -ENOMEM;
-		goto err_destroy;
-	}
-
-	ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id);
-
-	if (ret == -EAGAIN)
-		goto retry;
+	obj->uobject.object = srq;
+	ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
 	if (ret)
 		goto err_destroy;
 
-	resp.srq_handle = uobj->uobject.id;
+	memset(&resp, 0, sizeof resp);
+	resp.srq_handle = obj->uobject.id;
 	resp.max_wr     = attr.attr.max_wr;
 	resp.max_sge    = attr.attr.max_sge;
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp)) {
 		ret = -EFAULT;
-		goto err_idr;
+		goto err_copy;
 	}
 
+	put_pd_read(pd);
+
 	mutex_lock(&file->mutex);
-	list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);
+	list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
 	mutex_unlock(&file->mutex);
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	obj->uobject.live = 1;
+
+	up_write(&obj->uobject.mutex);
 
 	return in_len;
 
-err_idr:
-	idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);
+err_copy:
+	idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
 
 err_destroy:
 	ib_destroy_srq(srq);
-	atomic_dec(&pd->usecnt);
 
-err_up:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
-	kfree(uobj);
+err:
+	put_uobj_write(&obj->uobject);
 	return ret;
 }
 
@@ -1907,21 +2046,16 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-	if (!srq || srq->uobject->context != file->ucontext) {
-		ret = -EINVAL;
-		goto out;
-	}
+	srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+	if (!srq)
+		return -EINVAL;
 
 	attr.max_wr    = cmd.max_wr;
 	attr.srq_limit = cmd.srq_limit;
 
 	ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	put_srq_read(srq);
 
 	return ret ? ret : in_len;
 }
@@ -1942,18 +2076,16 @@
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
+	srq = idr_read_srq(cmd.srq_handle, file->ucontext);
+	if (!srq)
+		return -EINVAL;
 
-	srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-	if (srq && srq->uobject->context == file->ucontext)
-		ret = ib_query_srq(srq, &attr);
-	else
-		ret = -EINVAL;
+	ret = ib_query_srq(srq, &attr);
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
+	put_srq_read(srq);
 
 	if (ret)
-		goto out;
+		return ret;
 
 	memset(&resp, 0, sizeof resp);
 
@@ -1963,10 +2095,9 @@
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp))
-		ret = -EFAULT;
+		return -EFAULT;
 
-out:
-	return ret ? ret : in_len;
+	return in_len;
 }
 
 ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file,
@@ -1975,45 +2106,45 @@
 {
 	struct ib_uverbs_destroy_srq      cmd;
 	struct ib_uverbs_destroy_srq_resp resp;
+	struct ib_uobject		 *uobj;
 	struct ib_srq               	 *srq;
-	struct ib_uevent_object        	 *uobj;
+	struct ib_uevent_object        	 *obj;
 	int                         	  ret = -EINVAL;
 
 	if (copy_from_user(&cmd, buf, sizeof cmd))
 		return -EFAULT;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
-	memset(&resp, 0, sizeof resp);
-
-	srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
-	if (!srq || srq->uobject->context != file->ucontext)
-		goto out;
-
-	uobj = container_of(srq->uobject, struct ib_uevent_object, uobject);
+	uobj = idr_write_uobj(&ib_uverbs_srq_idr, cmd.srq_handle, file->ucontext);
+	if (!uobj)
+		return -EINVAL;
+	srq = uobj->object;
+	obj = container_of(uobj, struct ib_uevent_object, uobject);
 
 	ret = ib_destroy_srq(srq);
-	if (ret)
-		goto out;
+	if (!ret)
+		uobj->live = 0;
 
-	idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
+	put_uobj_write(uobj);
+
+	if (ret)
+		return ret;
+
+	idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
 
 	mutex_lock(&file->mutex);
-	list_del(&uobj->uobject.list);
+	list_del(&uobj->list);
 	mutex_unlock(&file->mutex);
 
-	ib_uverbs_release_uevent(file, uobj);
+	ib_uverbs_release_uevent(file, obj);
 
-	resp.events_reported = uobj->events_reported;
+	memset(&resp, 0, sizeof resp);
+	resp.events_reported = obj->events_reported;
 
-	kfree(uobj);
+	put_uobj(uobj);
 
 	if (copy_to_user((void __user *) (unsigned long) cmd.response,
 			 &resp, sizeof resp))
 		ret = -EFAULT;
 
-out:
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
 	return ret ? ret : in_len;
 }
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index ff092a0..e725ccc 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -66,7 +66,7 @@
 
 static struct class *uverbs_class;
 
-DEFINE_MUTEX(ib_uverbs_idr_mutex);
+DEFINE_SPINLOCK(ib_uverbs_idr_lock);
 DEFINE_IDR(ib_uverbs_pd_idr);
 DEFINE_IDR(ib_uverbs_mr_idr);
 DEFINE_IDR(ib_uverbs_mw_idr);
@@ -183,47 +183,45 @@
 	if (!context)
 		return 0;
 
-	mutex_lock(&ib_uverbs_idr_mutex);
-
 	list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) {
-		struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id);
-		idr_remove(&ib_uverbs_ah_idr, uobj->id);
+		struct ib_ah *ah = uobj->object;
+
+		idr_remove_uobj(&ib_uverbs_ah_idr, uobj);
 		ib_destroy_ah(ah);
-		list_del(&uobj->list);
 		kfree(uobj);
 	}
 
 	list_for_each_entry_safe(uobj, tmp, &context->qp_list, list) {
-		struct ib_qp *qp = idr_find(&ib_uverbs_qp_idr, uobj->id);
+		struct ib_qp *qp = uobj->object;
 		struct ib_uqp_object *uqp =
 			container_of(uobj, struct ib_uqp_object, uevent.uobject);
-		idr_remove(&ib_uverbs_qp_idr, uobj->id);
+
+		idr_remove_uobj(&ib_uverbs_qp_idr, uobj);
 		ib_uverbs_detach_umcast(qp, uqp);
 		ib_destroy_qp(qp);
-		list_del(&uobj->list);
 		ib_uverbs_release_uevent(file, &uqp->uevent);
 		kfree(uqp);
 	}
 
 	list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
-		struct ib_cq *cq = idr_find(&ib_uverbs_cq_idr, uobj->id);
+		struct ib_cq *cq = uobj->object;
 		struct ib_uverbs_event_file *ev_file = cq->cq_context;
 		struct ib_ucq_object *ucq =
 			container_of(uobj, struct ib_ucq_object, uobject);
-		idr_remove(&ib_uverbs_cq_idr, uobj->id);
+
+		idr_remove_uobj(&ib_uverbs_cq_idr, uobj);
 		ib_destroy_cq(cq);
-		list_del(&uobj->list);
 		ib_uverbs_release_ucq(file, ev_file, ucq);
 		kfree(ucq);
 	}
 
 	list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
-		struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+		struct ib_srq *srq = uobj->object;
 		struct ib_uevent_object *uevent =
 			container_of(uobj, struct ib_uevent_object, uobject);
-		idr_remove(&ib_uverbs_srq_idr, uobj->id);
+
+		idr_remove_uobj(&ib_uverbs_srq_idr, uobj);
 		ib_destroy_srq(srq);
-		list_del(&uobj->list);
 		ib_uverbs_release_uevent(file, uevent);
 		kfree(uevent);
 	}
@@ -231,30 +229,27 @@
 	/* XXX Free MWs */
 
 	list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
-		struct ib_mr *mr = idr_find(&ib_uverbs_mr_idr, uobj->id);
+		struct ib_mr *mr = uobj->object;
 		struct ib_device *mrdev = mr->device;
 		struct ib_umem_object *memobj;
 
-		idr_remove(&ib_uverbs_mr_idr, uobj->id);
+		idr_remove_uobj(&ib_uverbs_mr_idr, uobj);
 		ib_dereg_mr(mr);
 
 		memobj = container_of(uobj, struct ib_umem_object, uobject);
 		ib_umem_release_on_close(mrdev, &memobj->umem);
 
-		list_del(&uobj->list);
 		kfree(memobj);
 	}
 
 	list_for_each_entry_safe(uobj, tmp, &context->pd_list, list) {
-		struct ib_pd *pd = idr_find(&ib_uverbs_pd_idr, uobj->id);
-		idr_remove(&ib_uverbs_pd_idr, uobj->id);
+		struct ib_pd *pd = uobj->object;
+
+		idr_remove_uobj(&ib_uverbs_pd_idr, uobj);
 		ib_dealloc_pd(pd);
-		list_del(&uobj->list);
 		kfree(uobj);
 	}
 
-	mutex_unlock(&ib_uverbs_idr_mutex);
-
 	return context->device->dealloc_ucontext(context);
 }
 
@@ -820,11 +815,12 @@
 	kref_put(&uverbs_dev->ref, ib_uverbs_release_dev);
 }
 
-static struct super_block *uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
-					       const char *dev_name, void *data)
+static int uverbs_event_get_sb(struct file_system_type *fs_type, int flags,
+			       const char *dev_name, void *data,
+			       struct vfsmount *mnt)
 {
 	return get_sb_pseudo(fs_type, "infinibandevent:", NULL,
-			     INFINIBANDEVENTFS_MAGIC);
+			     INFINIBANDEVENTFS_MAGIC, mnt);
 }
 
 static struct file_system_type uverbs_event_fs = {
diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c
new file mode 100644
index 0000000..ce46b13
--- /dev/null
+++ b/drivers/infiniband/core/uverbs_marshall.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <rdma/ib_marshall.h>
+
+static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst,
+				    struct ib_ah_attr *src)
+{
+	memcpy(dst->grh.dgid, src->grh.dgid.raw, sizeof src->grh.dgid);
+	dst->grh.flow_label        = src->grh.flow_label;
+	dst->grh.sgid_index        = src->grh.sgid_index;
+	dst->grh.hop_limit         = src->grh.hop_limit;
+	dst->grh.traffic_class     = src->grh.traffic_class;
+	dst->dlid 	    	   = src->dlid;
+	dst->sl   	    	   = src->sl;
+	dst->src_path_bits 	   = src->src_path_bits;
+	dst->static_rate   	   = src->static_rate;
+	dst->is_global             = src->ah_flags & IB_AH_GRH ? 1 : 0;
+	dst->port_num 	    	   = src->port_num;
+}
+
+void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+			     struct ib_qp_attr *src)
+{
+	dst->cur_qp_state	= src->cur_qp_state;
+	dst->path_mtu		= src->path_mtu;
+	dst->path_mig_state	= src->path_mig_state;
+	dst->qkey		= src->qkey;
+	dst->rq_psn		= src->rq_psn;
+	dst->sq_psn		= src->sq_psn;
+	dst->dest_qp_num	= src->dest_qp_num;
+	dst->qp_access_flags	= src->qp_access_flags;
+
+	dst->max_send_wr	= src->cap.max_send_wr;
+	dst->max_recv_wr	= src->cap.max_recv_wr;
+	dst->max_send_sge	= src->cap.max_send_sge;
+	dst->max_recv_sge	= src->cap.max_recv_sge;
+	dst->max_inline_data	= src->cap.max_inline_data;
+
+	ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr);
+	ib_copy_ah_attr_to_user(&dst->alt_ah_attr, &src->alt_ah_attr);
+
+	dst->pkey_index		= src->pkey_index;
+	dst->alt_pkey_index	= src->alt_pkey_index;
+	dst->en_sqd_async_notify = src->en_sqd_async_notify;
+	dst->sq_draining	= src->sq_draining;
+	dst->max_rd_atomic	= src->max_rd_atomic;
+	dst->max_dest_rd_atomic	= src->max_dest_rd_atomic;
+	dst->min_rnr_timer	= src->min_rnr_timer;
+	dst->port_num		= src->port_num;
+	dst->timeout		= src->timeout;
+	dst->retry_cnt		= src->retry_cnt;
+	dst->rnr_retry		= src->rnr_retry;
+	dst->alt_port_num	= src->alt_port_num;
+	dst->alt_timeout	= src->alt_timeout;
+}
+EXPORT_SYMBOL(ib_copy_qp_attr_to_user);
+
+void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+			      struct ib_sa_path_rec *src)
+{
+	memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid);
+	memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid);
+
+	dst->dlid		= src->dlid;
+	dst->slid		= src->slid;
+	dst->raw_traffic	= src->raw_traffic;
+	dst->flow_label		= src->flow_label;
+	dst->hop_limit		= src->hop_limit;
+	dst->traffic_class	= src->traffic_class;
+	dst->reversible		= src->reversible;
+	dst->numb_path		= src->numb_path;
+	dst->pkey		= src->pkey;
+	dst->sl			= src->sl;
+	dst->mtu_selector	= src->mtu_selector;
+	dst->mtu		= src->mtu;
+	dst->rate_selector	= src->rate_selector;
+	dst->rate		= src->rate;
+	dst->packet_life_time	= src->packet_life_time;
+	dst->preference		= src->preference;
+	dst->packet_life_time_selector = src->packet_life_time_selector;
+}
+EXPORT_SYMBOL(ib_copy_path_rec_to_user);
+
+void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst,
+				struct ib_user_path_rec *src)
+{
+	memcpy(dst->dgid.raw, src->dgid, sizeof dst->dgid);
+	memcpy(dst->sgid.raw, src->sgid, sizeof dst->sgid);
+
+	dst->dlid		= src->dlid;
+	dst->slid		= src->slid;
+	dst->raw_traffic	= src->raw_traffic;
+	dst->flow_label		= src->flow_label;
+	dst->hop_limit		= src->hop_limit;
+	dst->traffic_class	= src->traffic_class;
+	dst->reversible		= src->reversible;
+	dst->numb_path		= src->numb_path;
+	dst->pkey		= src->pkey;
+	dst->sl			= src->sl;
+	dst->mtu_selector	= src->mtu_selector;
+	dst->mtu		= src->mtu;
+	dst->rate_selector	= src->rate_selector;
+	dst->rate		= src->rate;
+	dst->packet_life_time	= src->packet_life_time;
+	dst->preference		= src->preference;
+	dst->packet_life_time_selector = src->packet_life_time_selector;
+}
+EXPORT_SYMBOL(ib_copy_path_rec_from_user);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index b78e7dc..468999c 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -125,35 +125,47 @@
 }
 EXPORT_SYMBOL(ib_create_ah);
 
-struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
-				   struct ib_grh *grh, u8 port_num)
+int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
+		       struct ib_grh *grh, struct ib_ah_attr *ah_attr)
 {
-	struct ib_ah_attr ah_attr;
 	u32 flow_class;
 	u16 gid_index;
 	int ret;
 
-	memset(&ah_attr, 0, sizeof ah_attr);
-	ah_attr.dlid = wc->slid;
-	ah_attr.sl = wc->sl;
-	ah_attr.src_path_bits = wc->dlid_path_bits;
-	ah_attr.port_num = port_num;
+	memset(ah_attr, 0, sizeof *ah_attr);
+	ah_attr->dlid = wc->slid;
+	ah_attr->sl = wc->sl;
+	ah_attr->src_path_bits = wc->dlid_path_bits;
+	ah_attr->port_num = port_num;
 
 	if (wc->wc_flags & IB_WC_GRH) {
-		ah_attr.ah_flags = IB_AH_GRH;
-		ah_attr.grh.dgid = grh->sgid;
+		ah_attr->ah_flags = IB_AH_GRH;
+		ah_attr->grh.dgid = grh->sgid;
 
-		ret = ib_find_cached_gid(pd->device, &grh->dgid, &port_num,
+		ret = ib_find_cached_gid(device, &grh->dgid, &port_num,
 					 &gid_index);
 		if (ret)
-			return ERR_PTR(ret);
+			return ret;
 
-		ah_attr.grh.sgid_index = (u8) gid_index;
+		ah_attr->grh.sgid_index = (u8) gid_index;
 		flow_class = be32_to_cpu(grh->version_tclass_flow);
-		ah_attr.grh.flow_label = flow_class & 0xFFFFF;
-		ah_attr.grh.traffic_class = (flow_class >> 20) & 0xFF;
-		ah_attr.grh.hop_limit = grh->hop_limit;
+		ah_attr->grh.flow_label = flow_class & 0xFFFFF;
+		ah_attr->grh.hop_limit = grh->hop_limit;
+		ah_attr->grh.traffic_class = (flow_class >> 20) & 0xFF;
 	}
+	return 0;
+}
+EXPORT_SYMBOL(ib_init_ah_from_wc);
+
+struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc,
+				   struct ib_grh *grh, u8 port_num)
+{
+	struct ib_ah_attr ah_attr;
+	int ret;
+
+	ret = ib_init_ah_from_wc(pd->device, port_num, wc, grh, &ah_attr);
+	if (ret)
+		return ERR_PTR(ret);
 
 	return ib_create_ah(pd, &ah_attr);
 }
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index e274120..63de304 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -542,13 +542,14 @@
 	return ret;
 }
 
-static struct super_block *ipathfs_get_sb(struct file_system_type *fs_type,
-				        int flags, const char *dev_name,
-					void *data)
+static int ipathfs_get_sb(struct file_system_type *fs_type, int flags,
+			const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	ipath_super = get_sb_single(fs_type, flags, data,
-				    ipathfs_fill_super);
-	return ipath_super;
+	int ret = get_sb_single(fs_type, flags, data,
+				    ipathfs_fill_super, mnt);
+	if (ret >= 0)
+		ipath_super = mnt->mnt_sb;
+	return ret;
 }
 
 static void ipathfs_kill_super(struct super_block *s)
diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
index f7f8391..1a9d0a2 100644
--- a/drivers/infiniband/hw/ipath/ipath_mad.c
+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
@@ -137,47 +137,11 @@
 	return reply(smp);
 }
 
-struct port_info {
-	__be64 mkey;
-	__be64 gid_prefix;
-	__be16 lid;
-	__be16 sm_lid;
-	__be32 cap_mask;
-	__be16 diag_code;
-	__be16 mkey_lease_period;
-	u8 local_port_num;
-	u8 link_width_enabled;
-	u8 link_width_supported;
-	u8 link_width_active;
-	u8 linkspeed_portstate;			/* 4 bits, 4 bits */
-	u8 portphysstate_linkdown;		/* 4 bits, 4 bits */
-	u8 mkeyprot_resv_lmc;			/* 2 bits, 3, 3 */
-	u8 linkspeedactive_enabled;		/* 4 bits, 4 bits */
-	u8 neighbormtu_mastersmsl;		/* 4 bits, 4 bits */
-	u8 vlcap_inittype;			/* 4 bits, 4 bits */
-	u8 vl_high_limit;
-	u8 vl_arb_high_cap;
-	u8 vl_arb_low_cap;
-	u8 inittypereply_mtucap;		/* 4 bits, 4 bits */
-	u8 vlstallcnt_hoqlife;			/* 3 bits, 5 bits */
-	u8 operationalvl_pei_peo_fpi_fpo;	/* 4 bits, 1, 1, 1, 1 */
-	__be16 mkey_violations;
-	__be16 pkey_violations;
-	__be16 qkey_violations;
-	u8 guid_cap;
-	u8 clientrereg_resv_subnetto;		/* 1 bit, 2 bits, 5 */
-	u8 resv_resptimevalue;			/* 3 bits, 5 bits */
-	u8 localphyerrors_overrunerrors;	/* 4 bits, 4 bits */
-	__be16 max_credit_hint;
-	u8 resv;
-	u8 link_roundtrip_latency[3];
-} __attribute__ ((packed));
-
 static int recv_subn_get_portinfo(struct ib_smp *smp,
 				  struct ib_device *ibdev, u8 port)
 {
 	struct ipath_ibdev *dev;
-	struct port_info *pip = (struct port_info *)smp->data;
+	struct ib_port_info *pip = (struct ib_port_info *)smp->data;
 	u16 lid;
 	u8 ibcstat;
 	u8 mtu;
@@ -312,7 +276,7 @@
 static int recv_subn_set_portinfo(struct ib_smp *smp,
 				  struct ib_device *ibdev, u8 port)
 {
-	struct port_info *pip = (struct port_info *)smp->data;
+	struct ib_port_info *pip = (struct ib_port_info *)smp->data;
 	struct ib_event event;
 	struct ipath_ibdev *dev;
 	u32 flags;
@@ -445,7 +409,7 @@
 
 	if (pip->clientrereg_resv_subnetto & 0x80) {
 		clientrereg = 1;
-		event.event = IB_EVENT_LID_CHANGE;
+		event.event = IB_EVENT_CLIENT_REREGISTER;
 		ib_dispatch_event(&event);
 	}
 
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 798e13e..d0f7731 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -174,7 +174,6 @@
 
 struct mthca_cmd_context {
 	struct completion done;
-	struct timer_list timer;
 	int               result;
 	int               next;
 	u64               out_param;
@@ -362,15 +361,6 @@
 	complete(&context->done);
 }
 
-static void event_timeout(unsigned long context_ptr)
-{
-	struct mthca_cmd_context *context =
-		(struct mthca_cmd_context *) context_ptr;
-
-	context->result = -EBUSY;
-	complete(&context->done);
-}
-
 static int mthca_cmd_wait(struct mthca_dev *dev,
 			  u64 in_param,
 			  u64 *out_param,
@@ -401,11 +391,10 @@
 	if (err)
 		goto out;
 
-	context->timer.expires  = jiffies + timeout;
-	add_timer(&context->timer);
-
-	wait_for_completion(&context->done);
-	del_timer_sync(&context->timer);
+	if (!wait_for_completion_timeout(&context->done, timeout)) {
+		err = -EBUSY;
+		goto out;
+	}
 
 	err = context->result;
 	if (err)
@@ -535,10 +524,6 @@
 	for (i = 0; i < dev->cmd.max_cmds; ++i) {
 		dev->cmd.context[i].token = i;
 		dev->cmd.context[i].next = i + 1;
-		init_timer(&dev->cmd.context[i].timer);
-		dev->cmd.context[i].timer.data     =
-			(unsigned long) &dev->cmd.context[i];
-		dev->cmd.context[i].timer.function = event_timeout;
 	}
 
 	dev->cmd.context[dev->cmd.max_cmds - 1].next = -1;
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index 205854e..3e27a08 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -540,8 +540,17 @@
 		entry->wr_id = srq->wrid[wqe_index];
 		mthca_free_srq_wqe(srq, wqe);
 	} else {
+		s32 wqe;
 		wq = &(*cur_qp)->rq;
-		wqe_index = be32_to_cpu(cqe->wqe) >> wq->wqe_shift;
+		wqe = be32_to_cpu(cqe->wqe);
+		wqe_index = wqe >> wq->wqe_shift;
+               /*
+		* WQE addr == base - 1 might be reported in receive completion
+		* with error instead of (rq size - 1) by Sinai FW 1.0.800 and
+		* Arbel FW 5.1.400.  This bug should be fixed in later FW revs.
+		*/
+		if (unlikely(wqe_index < 0))
+			wqe_index = wq->max - 1;
 		entry->wr_id = (*cur_qp)->wrid[wqe_index];
 	}
 
@@ -813,6 +822,7 @@
 	spin_lock_init(&cq->lock);
 	cq->refcount = 1;
 	init_waitqueue_head(&cq->wait);
+	mutex_init(&cq->mutex);
 
 	memset(cq_context, 0, sizeof *cq_context);
 	cq_context->flags           = cpu_to_be32(MTHCA_CQ_STATUS_OK      |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 99f109c..d536217 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -695,10 +695,6 @@
 
 static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
 {
-	unsigned long mthca_base;
-
-	mthca_base = pci_resource_start(dev->pdev, 0);
-
 	if (mthca_is_memfree(dev)) {
 		/*
 		 * We assume that the EQ arm and EQ set CI registers
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c
index 4730863..d9bc030 100644
--- a/drivers/infiniband/hw/mthca/mthca_mad.c
+++ b/drivers/infiniband/hw/mthca/mthca_mad.c
@@ -114,14 +114,22 @@
 	     mad->mad_hdr.mgmt_class  == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) &&
 	    mad->mad_hdr.method     == IB_MGMT_METHOD_SET) {
 		if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) {
+			struct ib_port_info *pinfo =
+				(struct ib_port_info *) ((struct ib_smp *) mad)->data;
+
 			mthca_update_rate(to_mdev(ibdev), port_num);
 			update_sm_ah(to_mdev(ibdev), port_num,
-				     be16_to_cpup((__be16 *) (mad->data + 58)),
-				     (*(u8 *) (mad->data + 76)) & 0xf);
+				     be16_to_cpu(pinfo->lid),
+				     pinfo->neighbormtu_mastersmsl & 0xf);
 
 			event.device           = ibdev;
-			event.event            = IB_EVENT_LID_CHANGE;
 			event.element.port_num = port_num;
+
+			if(pinfo->clientrereg_resv_subnetto & 0x80)
+				event.event    = IB_EVENT_CLIENT_REREGISTER;
+			else
+				event.event    = IB_EVENT_LID_CHANGE;
+
 			ib_dispatch_event(&event);
 		}
 
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index a2eae8a..230ae21 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -115,6 +115,16 @@
 	props->max_mcast_qp_attach = MTHCA_QP_PER_MGM;
 	props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
 					   props->max_mcast_grp;
+	/*
+	 * If Sinai memory key optimization is being used, then only
+	 * the 8-bit key portion will change.  For other HCAs, the
+	 * unused index bits will also be used for FMR remapping.
+	 */
+	if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)
+		props->max_map_per_fmr = 255;
+	else
+		props->max_map_per_fmr =
+			(1 << (32 - long_log2(mdev->limits.num_mpts))) - 1;
 
 	err = 0;
  out:
@@ -783,18 +793,24 @@
 	if (entries < 1 || entries > dev->limits.max_cqes)
 		return -EINVAL;
 
+	mutex_lock(&cq->mutex);
+
 	entries = roundup_pow_of_two(entries + 1);
-	if (entries == ibcq->cqe + 1)
-		return 0;
+	if (entries == ibcq->cqe + 1) {
+		ret = 0;
+		goto out;
+	}
 
 	if (cq->is_kernel) {
 		ret = mthca_alloc_resize_buf(dev, cq, entries);
 		if (ret)
-			return ret;
+			goto out;
 		lkey = cq->resize_buf->buf.mr.ibmr.lkey;
 	} else {
-		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
-			return -EFAULT;
+		if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) {
+			ret = -EFAULT;
+			goto out;
+		}
 		lkey = ucmd.lkey;
 	}
 
@@ -811,7 +827,7 @@
 			cq->resize_buf = NULL;
 			spin_unlock_irq(&cq->lock);
 		}
-		return ret;
+		goto out;
 	}
 
 	if (cq->is_kernel) {
@@ -838,7 +854,10 @@
 	} else
 		ibcq->cqe = entries - 1;
 
-	return 0;
+out:
+	mutex_unlock(&cq->mutex);
+
+	return ret;
 }
 
 static int mthca_destroy_cq(struct ib_cq *cq)
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index 179a8f6..8de2887 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -214,6 +214,7 @@
 	int			arm_sn;
 
 	wait_queue_head_t	wait;
+	struct mutex		mutex;
 };
 
 struct mthca_srq {
@@ -237,6 +238,7 @@
 	struct mthca_mr		mr;
 
 	wait_queue_head_t	wait;
+	struct mutex		mutex;
 };
 
 struct mthca_wq {
@@ -278,6 +280,7 @@
 	union mthca_buf	       queue;
 
 	wait_queue_head_t      wait;
+	struct mutex	       mutex;
 };
 
 struct mthca_sqp {
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 07c13be..16c387d 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -534,7 +534,9 @@
 	struct mthca_qp_context *qp_context;
 	u32 sqd_event = 0;
 	u8 status;
-	int err;
+	int err = -EINVAL;
+
+	mutex_lock(&qp->mutex);
 
 	if (attr_mask & IB_QP_CUR_STATE) {
 		cur_state = attr->cur_qp_state;
@@ -553,39 +555,41 @@
 			  "%d->%d with attr 0x%08x\n",
 			  qp->transport, cur_state, new_state,
 			  attr_mask);
-		return -EINVAL;
+		goto out;
 	}
 
 	if ((attr_mask & IB_QP_PKEY_INDEX) &&
 	     attr->pkey_index >= dev->limits.pkey_table_len) {
 		mthca_dbg(dev, "P_Key index (%u) too large. max is %d\n",
 			  attr->pkey_index, dev->limits.pkey_table_len-1);
-		return -EINVAL;
+		goto out;
 	}
 
 	if ((attr_mask & IB_QP_PORT) &&
 	    (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) {
 		mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num);
-		return -EINVAL;
+		goto out;
 	}
 
 	if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC &&
 	    attr->max_rd_atomic > dev->limits.max_qp_init_rdma) {
 		mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n",
 			  attr->max_rd_atomic, dev->limits.max_qp_init_rdma);
-		return -EINVAL;
+		goto out;
 	}
 
 	if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC &&
 	    attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) {
 		mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n",
 			  attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift);
-		return -EINVAL;
+		goto out;
 	}
 
 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
-	if (IS_ERR(mailbox))
-		return PTR_ERR(mailbox);
+	if (IS_ERR(mailbox)) {
+		err = PTR_ERR(mailbox);
+		goto out;
+	}
 	qp_param = mailbox->buf;
 	qp_context = &qp_param->context;
 	memset(qp_param, 0, sizeof *qp_param);
@@ -618,7 +622,7 @@
 		if (attr->path_mtu < IB_MTU_256 || attr->path_mtu > IB_MTU_2048) {
 			mthca_dbg(dev, "path MTU (%u) is invalid\n",
 				  attr->path_mtu);
-			return -EINVAL;
+			goto out_mailbox;
 		}
 		qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
 	}
@@ -672,7 +676,7 @@
 	if (attr_mask & IB_QP_AV) {
 		if (mthca_path_set(dev, &attr->ah_attr, &qp_context->pri_path,
 				   attr_mask & IB_QP_PORT ? attr->port_num : qp->port))
-			return -EINVAL;
+			goto out_mailbox;
 
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH);
 	}
@@ -686,18 +690,18 @@
 		if (attr->alt_pkey_index >= dev->limits.pkey_table_len) {
 			mthca_dbg(dev, "Alternate P_Key index (%u) too large. max is %d\n",
 				  attr->alt_pkey_index, dev->limits.pkey_table_len-1);
-			return -EINVAL;
+			goto out_mailbox;
 		}
 
 		if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) {
 			mthca_dbg(dev, "Alternate port number (%u) is invalid\n",
 				attr->alt_port_num);
-			return -EINVAL;
+			goto out_mailbox;
 		}
 
 		if (mthca_path_set(dev, &attr->alt_ah_attr, &qp_context->alt_path,
 				   attr->alt_ah_attr.port_num))
-			return -EINVAL;
+			goto out_mailbox;
 
 		qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index |
 							      attr->alt_port_num << 24);
@@ -793,12 +797,12 @@
 	err = mthca_MODIFY_QP(dev, cur_state, new_state, qp->qpn, 0,
 			      mailbox, sqd_event, &status);
 	if (err)
-		goto out;
+		goto out_mailbox;
 	if (status) {
 		mthca_warn(dev, "modify QP %d->%d returned status %02x.\n",
 			   cur_state, new_state, status);
 		err = -EINVAL;
-		goto out;
+		goto out_mailbox;
 	}
 
 	qp->state = new_state;
@@ -853,8 +857,11 @@
 		}
 	}
 
-out:
+out_mailbox:
 	mthca_free_mailbox(dev, mailbox);
+
+out:
+	mutex_unlock(&qp->mutex);
 	return err;
 }
 
@@ -1100,6 +1107,7 @@
 
 	qp->refcount = 1;
 	init_waitqueue_head(&qp->wait);
+	mutex_init(&qp->mutex);
 	qp->state    	 = IB_QPS_RESET;
 	qp->atomic_rd_en = 0;
 	qp->resp_depth   = 0;
diff --git a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
index df5e494..f4fddd5 100644
--- a/drivers/infiniband/hw/mthca/mthca_reset.c
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c
@@ -49,6 +49,12 @@
 	u32 *hca_header    = NULL;
 	u32 *bridge_header = NULL;
 	struct pci_dev *bridge = NULL;
+	int bridge_pcix_cap = 0;
+	int hca_pcie_cap = 0;
+	int hca_pcix_cap = 0;
+
+	u16 devctl;
+	u16 linkctl;
 
 #define MTHCA_RESET_OFFSET 0xf0010
 #define MTHCA_RESET_VALUE  swab32(1)
@@ -110,6 +116,9 @@
 		}
 	}
 
+	hca_pcix_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);
+	hca_pcie_cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);
+
 	if (bridge) {
 		bridge_header = kmalloc(256, GFP_KERNEL);
 		if (!bridge_header) {
@@ -129,6 +138,13 @@
 				goto out;
 			}
 		}
+		bridge_pcix_cap = pci_find_capability(bridge, PCI_CAP_ID_PCIX);
+		if (!bridge_pcix_cap) {
+				err = -ENODEV;
+				mthca_err(mdev, "Couldn't locate HCA bridge "
+					  "PCI-X capability, aborting.\n");
+				goto out;
+		}
 	}
 
 	/* actually hit reset */
@@ -178,6 +194,20 @@
 good:
 	/* Now restore the PCI headers */
 	if (bridge) {
+		if (pci_write_config_dword(bridge, bridge_pcix_cap + 0x8,
+				 bridge_header[(bridge_pcix_cap + 0x8) / 4])) {
+			err = -ENODEV;
+			mthca_err(mdev, "Couldn't restore HCA bridge Upstream "
+				  "split transaction control, aborting.\n");
+			goto out;
+		}
+		if (pci_write_config_dword(bridge, bridge_pcix_cap + 0xc,
+				 bridge_header[(bridge_pcix_cap + 0xc) / 4])) {
+			err = -ENODEV;
+			mthca_err(mdev, "Couldn't restore HCA bridge Downstream "
+				  "split transaction control, aborting.\n");
+			goto out;
+		}
 		/*
 		 * Bridge control register is at 0x3e, so we'll
 		 * naturally restore it last in this loop.
@@ -203,6 +233,35 @@
 		}
 	}
 
+	if (hca_pcix_cap) {
+		if (pci_write_config_dword(mdev->pdev, hca_pcix_cap,
+				 hca_header[hca_pcix_cap / 4])) {
+			err = -ENODEV;
+			mthca_err(mdev, "Couldn't restore HCA PCI-X "
+				  "command register, aborting.\n");
+			goto out;
+		}
+	}
+
+	if (hca_pcie_cap) {
+		devctl = hca_header[(hca_pcie_cap + PCI_EXP_DEVCTL) / 4];
+		if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_DEVCTL,
+					   devctl)) {
+			err = -ENODEV;
+			mthca_err(mdev, "Couldn't restore HCA PCI Express "
+				  "Device Control register, aborting.\n");
+			goto out;
+		}
+		linkctl = hca_header[(hca_pcie_cap + PCI_EXP_LNKCTL) / 4];
+		if (pci_write_config_word(mdev->pdev, hca_pcie_cap + PCI_EXP_LNKCTL,
+					   linkctl)) {
+			err = -ENODEV;
+			mthca_err(mdev, "Couldn't restore HCA PCI Express "
+				  "Link control register, aborting.\n");
+			goto out;
+		}
+	}
+
 	for (i = 0; i < 16; ++i) {
 		if (i * 4 == PCI_COMMAND)
 			continue;
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index b292fef..fab417c 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -243,6 +243,7 @@
 	spin_lock_init(&srq->lock);
 	srq->refcount = 1;
 	init_waitqueue_head(&srq->wait);
+	mutex_init(&srq->mutex);
 
 	if (mthca_is_memfree(dev))
 		mthca_arbel_init_srq_context(dev, pd, srq, mailbox->buf);
@@ -371,7 +372,11 @@
 	if (attr_mask & IB_SRQ_LIMIT) {
 		if (attr->srq_limit > srq->max)
 			return -EINVAL;
+
+		mutex_lock(&srq->mutex);
 		ret = mthca_ARM_SRQ(dev, srq->srqn, attr->srq_limit, &status);
+		mutex_unlock(&srq->mutex);
+
 		if (ret)
 			return ret;
 		if (status)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 12a1e05..491d2af 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -272,8 +272,7 @@
 void ipoib_dev_cleanup(struct net_device *dev);
 
 void ipoib_mcast_join_task(void *dev_ptr);
-void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
-		      struct sk_buff *skb);
+void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb);
 
 void ipoib_mcast_restart_task(void *dev_ptr);
 int ipoib_mcast_start_thread(struct net_device *dev);
@@ -369,15 +368,26 @@
 #endif /* CONFIG_INFINIBAND_IPOIB_DEBUG_DATA */
 
 
-#define IPOIB_GID_FMT		"%x:%x:%x:%x:%x:%x:%x:%x"
+#define IPOIB_GID_FMT		"%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:" \
+				"%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x:%2.2x%2.2x"
 
-#define IPOIB_GID_ARG(gid)	be16_to_cpup((__be16 *) ((gid).raw +  0)), \
-				be16_to_cpup((__be16 *) ((gid).raw +  2)), \
-				be16_to_cpup((__be16 *) ((gid).raw +  4)), \
-				be16_to_cpup((__be16 *) ((gid).raw +  6)), \
-				be16_to_cpup((__be16 *) ((gid).raw +  8)), \
-				be16_to_cpup((__be16 *) ((gid).raw + 10)), \
-				be16_to_cpup((__be16 *) ((gid).raw + 12)), \
-				be16_to_cpup((__be16 *) ((gid).raw + 14))
+#define IPOIB_GID_RAW_ARG(gid)	((u8 *)(gid))[0], \
+				((u8 *)(gid))[1], \
+				((u8 *)(gid))[2], \
+				((u8 *)(gid))[3], \
+				((u8 *)(gid))[4], \
+				((u8 *)(gid))[5], \
+				((u8 *)(gid))[6], \
+				((u8 *)(gid))[7], \
+				((u8 *)(gid))[8], \
+				((u8 *)(gid))[9], \
+				((u8 *)(gid))[10],\
+				((u8 *)(gid))[11],\
+				((u8 *)(gid))[12],\
+				((u8 *)(gid))[13],\
+				((u8 *)(gid))[14],\
+				((u8 *)(gid))[15]
+
+#define IPOIB_GID_ARG(gid)	IPOIB_GID_RAW_ARG((gid).raw)
 
 #endif /* _IPOIB_H */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 8406839..5033666 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -84,15 +84,9 @@
 
 	unsigned long flags;
 
-	if ((int) priv->tx_tail - (int) ah->last_send >= 0) {
-		ipoib_dbg(priv, "Freeing ah %p\n", ah->ah);
-		ib_destroy_ah(ah->ah);
-		kfree(ah);
-	} else {
-		spin_lock_irqsave(&priv->lock, flags);
-		list_add_tail(&ah->list, &priv->dead_ahs);
-		spin_unlock_irqrestore(&priv->lock, flags);
-	}
+	spin_lock_irqsave(&priv->lock, flags);
+	list_add_tail(&ah->list, &priv->dead_ahs);
+	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static int ipoib_ib_post_receive(struct net_device *dev, int id)
@@ -377,19 +371,16 @@
 	struct ipoib_ah *ah, *tah;
 	LIST_HEAD(remove_list);
 
-	spin_lock_irq(&priv->lock);
+	spin_lock_irq(&priv->tx_lock);
+	spin_lock(&priv->lock);
 	list_for_each_entry_safe(ah, tah, &priv->dead_ahs, list)
 		if ((int) priv->tx_tail - (int) ah->last_send >= 0) {
 			list_del(&ah->list);
-			list_add_tail(&ah->list, &remove_list);
+			ib_destroy_ah(ah->ah);
+			kfree(ah);
 		}
-	spin_unlock_irq(&priv->lock);
-
-	list_for_each_entry_safe(ah, tah, &remove_list, list) {
-		ipoib_dbg(priv, "Reaping ah %p\n", ah->ah);
-		ib_destroy_ah(ah->ah);
-		kfree(ah);
-	}
+	spin_unlock(&priv->lock);
+	spin_unlock_irq(&priv->tx_lock);
 }
 
 void ipoib_reap_ah(void *dev_ptr)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index cb078a7..1c6ea1c 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -185,8 +185,7 @@
 	return 0;
 }
 
-static struct ipoib_path *__path_find(struct net_device *dev,
-				      union ib_gid *gid)
+static struct ipoib_path *__path_find(struct net_device *dev, void *gid)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct rb_node *n = priv->path_tree.rb_node;
@@ -196,7 +195,7 @@
 	while (n) {
 		path = rb_entry(n, struct ipoib_path, rb_node);
 
-		ret = memcmp(gid->raw, path->pathrec.dgid.raw,
+		ret = memcmp(gid, path->pathrec.dgid.raw,
 			     sizeof (union ib_gid));
 
 		if (ret < 0)
@@ -424,8 +423,7 @@
 	}
 }
 
-static struct ipoib_path *path_rec_create(struct net_device *dev,
-					  union ib_gid *gid)
+static struct ipoib_path *path_rec_create(struct net_device *dev, void *gid)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_path *path;
@@ -440,7 +438,7 @@
 
 	INIT_LIST_HEAD(&path->neigh_list);
 
-	memcpy(path->pathrec.dgid.raw, gid->raw, sizeof (union ib_gid));
+	memcpy(path->pathrec.dgid.raw, gid, sizeof (union ib_gid));
 	path->pathrec.sgid      = priv->local_gid;
 	path->pathrec.pkey      = cpu_to_be16(priv->pkey);
 	path->pathrec.numb_path = 1;
@@ -498,10 +496,9 @@
 	 */
 	spin_lock(&priv->lock);
 
-	path = __path_find(dev, (union ib_gid *) (skb->dst->neighbour->ha + 4));
+	path = __path_find(dev, skb->dst->neighbour->ha + 4);
 	if (!path) {
-		path = path_rec_create(dev,
-				       (union ib_gid *) (skb->dst->neighbour->ha + 4));
+		path = path_rec_create(dev, skb->dst->neighbour->ha + 4);
 		if (!path)
 			goto err_path;
 
@@ -551,7 +548,7 @@
 	/* Add in the P_Key for multicasts */
 	skb->dst->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
 	skb->dst->neighbour->ha[9] = priv->pkey & 0xff;
-	ipoib_mcast_send(dev, (union ib_gid *) (skb->dst->neighbour->ha + 4), skb);
+	ipoib_mcast_send(dev, skb->dst->neighbour->ha + 4, skb);
 }
 
 static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
@@ -566,10 +563,9 @@
 	 */
 	spin_lock(&priv->lock);
 
-	path = __path_find(dev, (union ib_gid *) (phdr->hwaddr + 4));
+	path = __path_find(dev, phdr->hwaddr + 4);
 	if (!path) {
-		path = path_rec_create(dev,
-				       (union ib_gid *) (phdr->hwaddr + 4));
+		path = path_rec_create(dev, phdr->hwaddr + 4);
 		if (path) {
 			/* put pseudoheader back on for next time */
 			skb_push(skb, sizeof *phdr);
@@ -660,7 +656,7 @@
 			phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
 			phdr->hwaddr[9] = priv->pkey & 0xff;
 
-			ipoib_mcast_send(dev, (union ib_gid *) (phdr->hwaddr + 4), skb);
+			ipoib_mcast_send(dev, phdr->hwaddr + 4, skb);
 		} else {
 			/* unicast GID -- should be ARP or RARP reply */
 
@@ -671,7 +667,7 @@
 					   skb->dst ? "neigh" : "dst",
 					   be16_to_cpup((__be16 *) skb->data),
 					   be32_to_cpup((__be32 *) phdr->hwaddr),
-					   IPOIB_GID_ARG(*(union ib_gid *) (phdr->hwaddr + 4)));
+					   IPOIB_GID_RAW_ARG(phdr->hwaddr + 4));
 				dev_kfree_skb_any(skb);
 				++priv->stats.tx_dropped;
 				goto out;
@@ -754,7 +750,7 @@
 	ipoib_dbg(priv,
 		  "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
 		  be32_to_cpup((__be32 *) n->ha),
-		  IPOIB_GID_ARG(*((union ib_gid *) (n->ha + 4))));
+		  IPOIB_GID_RAW_ARG(n->ha + 4));
 
 	spin_lock_irqsave(&priv->lock, flags);
 
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 1dae4b2..ab40488 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -154,7 +154,7 @@
 	return mcast;
 }
 
-static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, union ib_gid *mgid)
+static struct ipoib_mcast *__ipoib_mcast_find(struct net_device *dev, void *mgid)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct rb_node *n = priv->multicast_tree.rb_node;
@@ -165,7 +165,7 @@
 
 		mcast = rb_entry(n, struct ipoib_mcast, rb_node);
 
-		ret = memcmp(mgid->raw, mcast->mcmember.mgid.raw,
+		ret = memcmp(mgid, mcast->mcmember.mgid.raw,
 			     sizeof (union ib_gid));
 		if (ret < 0)
 			n = n->rb_left;
@@ -694,8 +694,7 @@
 	return 0;
 }
 
-void ipoib_mcast_send(struct net_device *dev, union ib_gid *mgid,
-		      struct sk_buff *skb)
+void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_mcast *mcast;
@@ -718,7 +717,7 @@
 	if (!mcast) {
 		/* Let's create a new send only group now */
 		ipoib_dbg_mcast(priv, "setting up send only multicast group for "
-				IPOIB_GID_FMT "\n", IPOIB_GID_ARG(*mgid));
+				IPOIB_GID_FMT "\n", IPOIB_GID_RAW_ARG(mgid));
 
 		mcast = ipoib_mcast_alloc(dev, 0);
 		if (!mcast) {
@@ -730,7 +729,7 @@
 		}
 
 		set_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags);
-		mcast->mcmember.mgid = *mgid;
+		memcpy(mcast->mcmember.mgid.raw, mgid, sizeof (union ib_gid));
 		__ipoib_mcast_add(dev, mcast);
 		list_add_tail(&mcast->list, &priv->multicast_list);
 	}
@@ -821,7 +820,8 @@
 
 	ipoib_mcast_stop_thread(dev, 0);
 
-	spin_lock_irqsave(&dev->xmit_lock, flags);
+	local_irq_save(flags);
+	netif_tx_lock(dev);
 	spin_lock(&priv->lock);
 
 	/*
@@ -864,8 +864,7 @@
 
 			if (mcast) {
 				/* Destroy the send only entry */
-				list_del(&mcast->list);
-				list_add_tail(&mcast->list, &remove_list);
+				list_move_tail(&mcast->list, &remove_list);
 
 				rb_replace_node(&mcast->rb_node,
 						&nmcast->rb_node,
@@ -890,13 +889,13 @@
 			rb_erase(&mcast->rb_node, &priv->multicast_tree);
 
 			/* Move to the remove list */
-			list_del(&mcast->list);
-			list_add_tail(&mcast->list, &remove_list);
+			list_move_tail(&mcast->list, &remove_list);
 		}
 	}
 
 	spin_unlock(&priv->lock);
-	spin_unlock_irqrestore(&dev->xmit_lock, flags);
+	netif_tx_unlock(dev);
+	local_irq_restore(flags);
 
 	/* We have to cancel outside of the spinlock */
 	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 1d49d16..7b717c64 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -255,7 +255,8 @@
 	    record->event == IB_EVENT_PKEY_CHANGE ||
 	    record->event == IB_EVENT_PORT_ACTIVE ||
 	    record->event == IB_EVENT_LID_CHANGE  ||
-	    record->event == IB_EVENT_SM_CHANGE) {
+	    record->event == IB_EVENT_SM_CHANGE   ||
+	    record->event == IB_EVENT_CLIENT_REREGISTER) {
 		ipoib_dbg(priv, "Port state change event\n");
 		queue_work(ipoib_workqueue, &priv->flush_task);
 	}
diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig
new file mode 100644
index 0000000..fead87d
--- /dev/null
+++ b/drivers/infiniband/ulp/iser/Kconfig
@@ -0,0 +1,11 @@
+config INFINIBAND_ISER
+	tristate "ISCSI RDMA Protocol"
+	depends on INFINIBAND && SCSI
+	select SCSI_ISCSI_ATTRS
+	---help---
+	  Support for the ISCSI RDMA Protocol over InfiniBand.  This
+	  allows you to access storage devices that speak ISER/ISCSI
+	  over InfiniBand.
+
+	  The ISER protocol is defined by IETF.
+	  See <http://www.ietf.org/>.
diff --git a/drivers/infiniband/ulp/iser/Makefile b/drivers/infiniband/ulp/iser/Makefile
new file mode 100644
index 0000000..fe6cd15f
--- /dev/null
+++ b/drivers/infiniband/ulp/iser/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_INFINIBAND_ISER)	+= ib_iser.o
+
+ib_iser-y			:= iser_verbs.o iser_initiator.o iser_memory.o \
+				   iscsi_iser.o
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
new file mode 100644
index 0000000..4c3f2de
--- /dev/null
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -0,0 +1,790 @@
+/*
+ * iSCSI Initiator over iSER Data-Path
+ *
+ * Copyright (C) 2004 Dmitry Yusupov
+ * Copyright (C) 2004 Alex Aizman
+ * Copyright (C) 2005 Mike Christie
+ * Copyright (c) 2005, 2006 Voltaire, Inc. All rights reserved.
+ * maintained by openib-general@openib.org
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *	- Redistributions of source code must retain the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer.
+ *
+ *	- Redistributions in binary form must reproduce the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer in the documentation and/or other materials
+ *	  provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Credits:
+ *	Christoph Hellwig
+ *	FUJITA Tomonori
+ *	Arne Redlich
+ *	Zhenyu Wang
+ * Modified by:
+ *      Erez Zilber
+ *
+ *
+ * $Id: iscsi_iser.c 6965 2006-05-07 11:36:20Z ogerlitz $
+ */
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/hardirq.h>
+#include <linux/kfifo.h>
+#include <linux/blkdev.h>
+#include <linux/init.h>
+#include <linux/ioctl.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/cdev.h>
+#include <linux/in.h>
+#include <linux/net.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+
+#include <net/sock.h>
+
+#include <asm/uaccess.h>
+
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include "iscsi_iser.h"
+
+static unsigned int iscsi_max_lun = 512;
+module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+
+int iser_debug_level = 0;
+
+MODULE_DESCRIPTION("iSER (iSCSI Extensions for RDMA) Datamover "
+		   "v" DRV_VER " (" DRV_DATE ")");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Alex Nezhinsky, Dan Bar Dov, Or Gerlitz");
+
+module_param_named(debug_level, iser_debug_level, int, 0644);
+MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:disabled)");
+
+struct iser_global ig;
+
+void
+iscsi_iser_recv(struct iscsi_conn *conn,
+		struct iscsi_hdr *hdr, char *rx_data, int rx_data_len)
+{
+	int rc = 0;
+	uint32_t ret_itt;
+	int datalen;
+	int ahslen;
+
+	/* verify PDU length */
+	datalen = ntoh24(hdr->dlength);
+	if (datalen != rx_data_len) {
+		printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n",
+		       datalen, rx_data_len);
+		rc = ISCSI_ERR_DATALEN;
+		goto error;
+	}
+
+	/* read AHS */
+	ahslen = hdr->hlength * 4;
+
+	/* verify itt (itt encoding: age+cid+itt) */
+	rc = iscsi_verify_itt(conn, hdr, &ret_itt);
+
+	if (!rc)
+		rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len);
+
+	if (rc && rc != ISCSI_ERR_NO_SCSI_CMD)
+		goto error;
+
+	return;
+error:
+	iscsi_conn_failure(conn, rc);
+}
+
+
+/**
+ * iscsi_iser_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+ *
+ **/
+static void
+iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_iser_conn     *iser_conn  = ctask->conn->dd_data;
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+	struct scsi_cmnd  *sc = ctask->sc;
+
+	iser_ctask->command_sent = 0;
+	iser_ctask->iser_conn    = iser_conn;
+
+	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+		BUG_ON(ctask->total_length == 0);
+		/* bytes to be sent via RDMA operations */
+		iser_ctask->rdma_data_count = ctask->total_length -
+					 ctask->imm_count -
+					 ctask->unsol_count;
+
+		debug_scsi("cmd [itt %x total %d imm %d unsol_data %d "
+			   "rdma_data %d]\n",
+			   ctask->itt, ctask->total_length, ctask->imm_count,
+			   ctask->unsol_count, iser_ctask->rdma_data_count);
+	} else
+		/* bytes to be sent via RDMA operations */
+		iser_ctask->rdma_data_count = ctask->total_length;
+
+	iser_ctask_rdma_init(iser_ctask);
+}
+
+/**
+ * iscsi_mtask_xmit - xmit management(immediate) task
+ * @conn: iscsi connection
+ * @mtask: task management task
+ *
+ * Notes:
+ *	The function can return -EAGAIN in which case caller must
+ *	call it again later, or recover. '0' return code means successful
+ *	xmit.
+ *
+ **/
+static int
+iscsi_iser_mtask_xmit(struct iscsi_conn *conn,
+		      struct iscsi_mgmt_task *mtask)
+{
+	int error = 0;
+
+	debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt);
+
+	error = iser_send_control(conn, mtask);
+
+	/* since iser xmits control with zero copy, mtasks can not be recycled
+	 * right after sending them.
+	 * The recycling scheme is based on whether a response is expected
+	 * - if yes, the mtask is recycled at iscsi_complete_pdu
+	 * - if no,  the mtask is recycled at iser_snd_completion
+	 */
+	if (error && error != -EAGAIN)
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+
+	return error;
+}
+
+static int
+iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn,
+				 struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_data  hdr;
+	int error = 0;
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+
+	/* Send data-out PDUs while there's still unsolicited data to send */
+	while (ctask->unsol_count > 0) {
+		iscsi_prep_unsolicit_data_pdu(ctask, &hdr,
+					      iser_ctask->rdma_data_count);
+
+		debug_scsi("Sending data-out: itt 0x%x, data count %d\n",
+			   hdr.itt, ctask->data_count);
+
+		/* the buffer description has been passed with the command */
+		/* Send the command */
+		error = iser_send_data_out(conn, ctask, &hdr);
+		if (error) {
+			ctask->unsol_datasn--;
+			goto iscsi_iser_ctask_xmit_unsol_data_exit;
+		}
+		ctask->unsol_count -= ctask->data_count;
+		debug_scsi("Need to send %d more as data-out PDUs\n",
+			   ctask->unsol_count);
+	}
+
+iscsi_iser_ctask_xmit_unsol_data_exit:
+	return error;
+}
+
+static int
+iscsi_iser_ctask_xmit(struct iscsi_conn *conn,
+		      struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+	int error = 0;
+
+	debug_scsi("ctask deq [cid %d itt 0x%x]\n",
+		   conn->id, ctask->itt);
+
+	/*
+	 * serialize with TMF AbortTask
+	 */
+	if (ctask->mtask)
+		return error;
+
+	/* Send the cmd PDU */
+	if (!iser_ctask->command_sent) {
+		error = iser_send_command(conn, ctask);
+		if (error)
+			goto iscsi_iser_ctask_xmit_exit;
+		iser_ctask->command_sent = 1;
+	}
+
+	/* Send unsolicited data-out PDU(s) if necessary */
+	if (ctask->unsol_count)
+		error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask);
+
+ iscsi_iser_ctask_xmit_exit:
+	if (error && error != -EAGAIN)
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	return error;
+}
+
+static void
+iscsi_iser_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+
+	if (iser_ctask->status == ISER_TASK_STATUS_STARTED) {
+		iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+		iser_ctask_rdma_finalize(iser_ctask);
+	}
+}
+
+static struct iser_conn *
+iscsi_iser_ib_conn_lookup(__u64 ep_handle)
+{
+	struct iser_conn *ib_conn;
+	struct iser_conn *uib_conn = (struct iser_conn *)(unsigned long)ep_handle;
+
+	mutex_lock(&ig.connlist_mutex);
+	list_for_each_entry(ib_conn, &ig.connlist, conn_list) {
+		if (ib_conn == uib_conn) {
+			mutex_unlock(&ig.connlist_mutex);
+			return ib_conn;
+		}
+	}
+	mutex_unlock(&ig.connlist_mutex);
+	iser_err("no conn exists for eph %llx\n",(unsigned long long)ep_handle);
+	return NULL;
+}
+
+static struct iscsi_cls_conn *
+iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+{
+	struct iscsi_conn *conn;
+	struct iscsi_cls_conn *cls_conn;
+	struct iscsi_iser_conn *iser_conn;
+
+	cls_conn = iscsi_conn_setup(cls_session, conn_idx);
+	if (!cls_conn)
+		return NULL;
+	conn = cls_conn->dd_data;
+
+	/*
+	 * due to issues with the login code re iser sematics
+	 * this not set in iscsi_conn_setup - FIXME
+	 */
+	conn->max_recv_dlength = 128;
+
+	iser_conn = kzalloc(sizeof(*iser_conn), GFP_KERNEL);
+	if (!iser_conn)
+		goto conn_alloc_fail;
+
+	/* currently this is the only field which need to be initiated */
+	rwlock_init(&iser_conn->lock);
+
+	conn->dd_data = iser_conn;
+	iser_conn->iscsi_conn = conn;
+
+	return cls_conn;
+
+conn_alloc_fail:
+	iscsi_conn_teardown(cls_conn);
+	return NULL;
+}
+
+static void
+iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+
+	iscsi_conn_teardown(cls_conn);
+	kfree(iser_conn);
+}
+
+static int
+iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
+		     struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+		     int is_leading)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_iser_conn *iser_conn;
+	struct iser_conn *ib_conn;
+	int error;
+
+	error = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+	if (error)
+		return error;
+
+	/* the transport ep handle comes from user space so it must be
+	 * verified against the global ib connections list */
+	ib_conn = iscsi_iser_ib_conn_lookup(transport_eph);
+	if (!ib_conn) {
+		iser_err("can't bind eph %llx\n",
+			 (unsigned long long)transport_eph);
+		return -EINVAL;
+	}
+	/* binds the iSER connection retrieved from the previously
+	 * connected ep_handle to the iSCSI layer connection. exchanges
+	 * connection pointers */
+	iser_err("binding iscsi conn %p to iser_conn %p\n",conn,ib_conn);
+	iser_conn = conn->dd_data;
+	ib_conn->iser_conn = iser_conn;
+	iser_conn->ib_conn  = ib_conn;
+
+	conn->recv_lock = &iser_conn->lock;
+
+	return 0;
+}
+
+static int
+iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	int err;
+
+	err = iscsi_conn_start(cls_conn);
+	if (err)
+		return err;
+
+	return iser_conn_set_full_featured_mode(conn);
+}
+
+static void
+iscsi_iser_conn_terminate(struct iscsi_conn *conn)
+{
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+	struct iser_conn *ib_conn = iser_conn->ib_conn;
+
+	BUG_ON(!ib_conn);
+	/* starts conn teardown process, waits until all previously   *
+	 * posted buffers get flushed, deallocates all conn resources */
+	iser_conn_terminate(ib_conn);
+	iser_conn->ib_conn = NULL;
+	conn->recv_lock = NULL;
+}
+
+
+static struct iscsi_transport iscsi_iser_transport;
+
+static struct iscsi_cls_session *
+iscsi_iser_session_create(struct iscsi_transport *iscsit,
+			 struct scsi_transport_template *scsit,
+			  uint32_t initial_cmdsn, uint32_t *hostno)
+{
+	struct iscsi_cls_session *cls_session;
+	struct iscsi_session *session;
+	int i;
+	uint32_t hn;
+	struct iscsi_cmd_task  *ctask;
+	struct iscsi_mgmt_task *mtask;
+	struct iscsi_iser_cmd_task *iser_ctask;
+	struct iser_desc *desc;
+
+	cls_session = iscsi_session_setup(iscsit, scsit,
+					  sizeof(struct iscsi_iser_cmd_task),
+					  sizeof(struct iser_desc),
+					  initial_cmdsn, &hn);
+	if (!cls_session)
+	return NULL;
+
+	*hostno = hn;
+	session = class_to_transport_session(cls_session);
+
+	/* libiscsi setup itts, data and pool so just set desc fields */
+	for (i = 0; i < session->cmds_max; i++) {
+		ctask      = session->cmds[i];
+		iser_ctask = ctask->dd_data;
+		ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header;
+	}
+
+	for (i = 0; i < session->mgmtpool_max; i++) {
+		mtask      = session->mgmt_cmds[i];
+		desc       = mtask->dd_data;
+		mtask->hdr = &desc->iscsi_header;
+		desc->data = mtask->data;
+	}
+
+	return cls_session;
+}
+
+static int
+iscsi_iser_conn_set_param(struct iscsi_cls_conn *cls_conn,
+			  enum iscsi_param param, uint32_t value)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+
+	spin_lock_bh(&session->lock);
+	if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
+	    conn->stop_stage != STOP_CONN_RECOVER) {
+		printk(KERN_ERR "iscsi_iser: can not change parameter [%d]\n",
+		       param);
+		spin_unlock_bh(&session->lock);
+		return 0;
+	}
+	spin_unlock_bh(&session->lock);
+
+	switch (param) {
+	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		/* TBD */
+		break;
+	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		conn->max_xmit_dlength =  value;
+		break;
+	case ISCSI_PARAM_HDRDGST_EN:
+		if (value) {
+			printk(KERN_ERR "DataDigest wasn't negotiated to None");
+			return -EPROTO;
+		}
+		break;
+	case ISCSI_PARAM_DATADGST_EN:
+		if (value) {
+			printk(KERN_ERR "DataDigest wasn't negotiated to None");
+			return -EPROTO;
+		}
+		break;
+	case ISCSI_PARAM_INITIAL_R2T_EN:
+		session->initial_r2t_en = value;
+		break;
+	case ISCSI_PARAM_IMM_DATA_EN:
+		session->imm_data_en = value;
+		break;
+	case ISCSI_PARAM_FIRST_BURST:
+		session->first_burst = value;
+		break;
+	case ISCSI_PARAM_MAX_BURST:
+		session->max_burst = value;
+		break;
+	case ISCSI_PARAM_PDU_INORDER_EN:
+		session->pdu_inorder_en = value;
+		break;
+	case ISCSI_PARAM_DATASEQ_INORDER_EN:
+		session->dataseq_inorder_en = value;
+		break;
+	case ISCSI_PARAM_ERL:
+		session->erl = value;
+		break;
+	case ISCSI_PARAM_IFMARKER_EN:
+		if (value) {
+			printk(KERN_ERR "IFMarker wasn't negotiated to No");
+			return -EPROTO;
+		}
+		break;
+	case ISCSI_PARAM_OFMARKER_EN:
+		if (value) {
+			printk(KERN_ERR "OFMarker wasn't negotiated to No");
+			return -EPROTO;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int
+iscsi_iser_session_get_param(struct iscsi_cls_session *cls_session,
+			     enum iscsi_param param, uint32_t *value)
+{
+	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+
+	switch (param) {
+	case ISCSI_PARAM_INITIAL_R2T_EN:
+		*value = session->initial_r2t_en;
+		break;
+	case ISCSI_PARAM_MAX_R2T:
+		*value = session->max_r2t;
+		break;
+	case ISCSI_PARAM_IMM_DATA_EN:
+		*value = session->imm_data_en;
+		break;
+	case ISCSI_PARAM_FIRST_BURST:
+		*value = session->first_burst;
+		break;
+	case ISCSI_PARAM_MAX_BURST:
+		*value = session->max_burst;
+		break;
+	case ISCSI_PARAM_PDU_INORDER_EN:
+		*value = session->pdu_inorder_en;
+		break;
+	case ISCSI_PARAM_DATASEQ_INORDER_EN:
+		*value = session->dataseq_inorder_en;
+		break;
+	case ISCSI_PARAM_ERL:
+		*value = session->erl;
+		break;
+	case ISCSI_PARAM_IFMARKER_EN:
+		*value = 0;
+		break;
+	case ISCSI_PARAM_OFMARKER_EN:
+		*value = 0;
+		break;
+	default:
+		return ISCSI_ERR_PARAM_NOT_FOUND;
+	}
+
+	return 0;
+}
+
+static int
+iscsi_iser_conn_get_param(struct iscsi_cls_conn *cls_conn,
+			  enum iscsi_param param, uint32_t *value)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+
+	switch(param) {
+	case ISCSI_PARAM_MAX_RECV_DLENGTH:
+		*value = conn->max_recv_dlength;
+		break;
+	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
+		*value = conn->max_xmit_dlength;
+		break;
+	case ISCSI_PARAM_HDRDGST_EN:
+		*value = 0;
+		break;
+	case ISCSI_PARAM_DATADGST_EN:
+		*value = 0;
+		break;
+	/*case ISCSI_PARAM_TARGET_RECV_DLENGTH:
+		*value = conn->target_recv_dlength;
+		break;
+	case ISCSI_PARAM_INITIATOR_RECV_DLENGTH:
+		*value = conn->initiator_recv_dlength;
+		break;*/
+	default:
+		return ISCSI_ERR_PARAM_NOT_FOUND;
+	}
+
+	return 0;
+}
+
+
+static void
+iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+
+	stats->txdata_octets = conn->txdata_octets;
+	stats->rxdata_octets = conn->rxdata_octets;
+	stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
+	stats->dataout_pdus = conn->dataout_pdus_cnt;
+	stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
+	stats->datain_pdus = conn->datain_pdus_cnt; /* always 0 */
+	stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */
+	stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
+	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
+	stats->custom_length = 3;
+	strcpy(stats->custom[0].desc, "qp_tx_queue_full");
+	stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */
+	strcpy(stats->custom[1].desc, "fmr_map_not_avail");
+	stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */;
+	strcpy(stats->custom[2].desc, "eh_abort_cnt");
+	stats->custom[2].value = conn->eh_abort_cnt;
+}
+
+static int
+iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking,
+		      __u64 *ep_handle)
+{
+	int err;
+	struct iser_conn *ib_conn;
+
+	err = iser_conn_init(&ib_conn);
+	if (err)
+		goto out;
+
+	err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr, non_blocking);
+	if (!err)
+		*ep_handle = (__u64)(unsigned long)ib_conn;
+
+out:
+	return err;
+}
+
+static int
+iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms)
+{
+	struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+	int rc;
+
+	if (!ib_conn)
+		return -EINVAL;
+
+	rc = wait_event_interruptible_timeout(ib_conn->wait,
+			     ib_conn->state == ISER_CONN_UP,
+			     msecs_to_jiffies(timeout_ms));
+
+	/* if conn establishment failed, return error code to iscsi */
+	if (!rc &&
+	    (ib_conn->state == ISER_CONN_TERMINATING ||
+	     ib_conn->state == ISER_CONN_DOWN))
+		rc = -1;
+
+	iser_err("ib conn %p rc = %d\n", ib_conn, rc);
+
+	if (rc > 0)
+		return 1; /* success, this is the equivalent of POLLOUT */
+	else if (!rc)
+		return 0; /* timeout */
+	else
+		return rc; /* signal */
+}
+
+static void
+iscsi_iser_ep_disconnect(__u64 ep_handle)
+{
+	struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle);
+
+	if (!ib_conn)
+		return;
+
+	iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state);
+
+	iser_conn_terminate(ib_conn);
+}
+
+static struct scsi_host_template iscsi_iser_sht = {
+	.name                   = "iSCSI Initiator over iSER, v." DRV_VER,
+	.queuecommand           = iscsi_queuecommand,
+	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+	.sg_tablesize           = ISCSI_ISER_SG_TABLESIZE,
+	.cmd_per_lun            = ISCSI_MAX_CMD_PER_LUN,
+	.eh_abort_handler       = iscsi_eh_abort,
+	.eh_host_reset_handler	= iscsi_eh_host_reset,
+	.use_clustering         = DISABLE_CLUSTERING,
+	.proc_name              = "iscsi_iser",
+	.this_id                = -1,
+};
+
+static struct iscsi_transport iscsi_iser_transport = {
+	.owner                  = THIS_MODULE,
+	.name                   = "iser",
+	.caps                   = CAP_RECOVERY_L0 | CAP_MULTI_R2T,
+	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
+				  ISCSI_MAX_XMIT_DLENGTH |
+				  ISCSI_HDRDGST_EN |
+				  ISCSI_DATADGST_EN |
+				  ISCSI_INITIAL_R2T_EN |
+				  ISCSI_MAX_R2T |
+				  ISCSI_IMM_DATA_EN |
+				  ISCSI_FIRST_BURST |
+				  ISCSI_MAX_BURST |
+				  ISCSI_PDU_INORDER_EN |
+				  ISCSI_DATASEQ_INORDER_EN,
+	.host_template          = &iscsi_iser_sht,
+	.conndata_size		= sizeof(struct iscsi_conn),
+	.max_lun                = ISCSI_ISER_MAX_LUN,
+	.max_cmd_len            = ISCSI_ISER_MAX_CMD_LEN,
+	/* session management */
+	.create_session         = iscsi_iser_session_create,
+	.destroy_session        = iscsi_session_teardown,
+	/* connection management */
+	.create_conn            = iscsi_iser_conn_create,
+	.bind_conn              = iscsi_iser_conn_bind,
+	.destroy_conn           = iscsi_iser_conn_destroy,
+	.set_param              = iscsi_iser_conn_set_param,
+	.get_conn_param		= iscsi_iser_conn_get_param,
+	.get_session_param	= iscsi_iser_session_get_param,
+	.start_conn             = iscsi_iser_conn_start,
+	.stop_conn              = iscsi_conn_stop,
+	/* these are called as part of conn recovery */
+	.suspend_conn_recv	= NULL, /* FIXME is/how this relvant to iser? */
+	.terminate_conn		= iscsi_iser_conn_terminate,
+	/* IO */
+	.send_pdu		= iscsi_conn_send_pdu,
+	.get_stats		= iscsi_iser_conn_get_stats,
+	.init_cmd_task		= iscsi_iser_cmd_init,
+	.xmit_cmd_task		= iscsi_iser_ctask_xmit,
+	.xmit_mgmt_task		= iscsi_iser_mtask_xmit,
+	.cleanup_cmd_task	= iscsi_iser_cleanup_ctask,
+	/* recovery */
+	.session_recovery_timedout = iscsi_session_recovery_timedout,
+
+	.ep_connect             = iscsi_iser_ep_connect,
+	.ep_poll                = iscsi_iser_ep_poll,
+	.ep_disconnect          = iscsi_iser_ep_disconnect
+};
+
+static int __init iser_init(void)
+{
+	int err;
+
+	iser_dbg("Starting iSER datamover...\n");
+
+	if (iscsi_max_lun < 1) {
+		printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
+		return -EINVAL;
+	}
+
+	iscsi_iser_transport.max_lun = iscsi_max_lun;
+
+	memset(&ig, 0, sizeof(struct iser_global));
+
+	ig.desc_cache = kmem_cache_create("iser_descriptors",
+					  sizeof (struct iser_desc),
+					  0, SLAB_HWCACHE_ALIGN,
+					  NULL, NULL);
+	if (ig.desc_cache == NULL)
+		return -ENOMEM;
+
+	/* device init is called only after the first addr resolution */
+	mutex_init(&ig.device_list_mutex);
+	INIT_LIST_HEAD(&ig.device_list);
+	mutex_init(&ig.connlist_mutex);
+	INIT_LIST_HEAD(&ig.connlist);
+
+	if (!iscsi_register_transport(&iscsi_iser_transport)) {
+		iser_err("iscsi_register_transport failed\n");
+		err = -EINVAL;
+		goto register_transport_failure;
+	}
+
+	return 0;
+
+register_transport_failure:
+	kmem_cache_destroy(ig.desc_cache);
+
+	return err;
+}
+
+static void __exit iser_exit(void)
+{
+	iser_dbg("Removing iSER datamover...\n");
+	iscsi_unregister_transport(&iscsi_iser_transport);
+	kmem_cache_destroy(ig.desc_cache);
+}
+
+module_init(iser_init);
+module_exit(iser_exit);
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
new file mode 100644
index 0000000..3350ba6
--- /dev/null
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -0,0 +1,354 @@
+/*
+ * iSER transport for the Open iSCSI Initiator & iSER transport internals
+ *
+ * Copyright (C) 2004 Dmitry Yusupov
+ * Copyright (C) 2004 Alex Aizman
+ * Copyright (C) 2005 Mike Christie
+ * based on code maintained by open-iscsi@googlegroups.com
+ *
+ * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *	- Redistributions of source code must retain the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer.
+ *
+ *	- Redistributions in binary form must reproduce the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer in the documentation and/or other materials
+ *	  provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iscsi_iser.h 7051 2006-05-10 12:29:11Z ogerlitz $
+ */
+#ifndef __ISCSI_ISER_H__
+#define __ISCSI_ISER_H__
+
+#include <linux/types.h>
+#include <linux/net.h>
+#include <scsi/libiscsi.h>
+#include <scsi/scsi_transport_iscsi.h>
+
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/mutex.h>
+#include <linux/mempool.h>
+#include <linux/uio.h>
+
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_fmr_pool.h>
+#include <rdma/rdma_cm.h>
+
+#define DRV_NAME	"iser"
+#define PFX		DRV_NAME ": "
+#define DRV_VER		"0.1"
+#define DRV_DATE	"May 7th, 2006"
+
+#define iser_dbg(fmt, arg...)				\
+	do {						\
+		if (iser_debug_level > 0)		\
+			printk(KERN_DEBUG PFX "%s:" fmt,\
+				__func__ , ## arg);	\
+	} while (0)
+
+#define iser_err(fmt, arg...)				\
+	do {						\
+		printk(KERN_ERR PFX "%s:" fmt,          \
+		       __func__ , ## arg);		\
+	} while (0)
+
+					/* support upto 512KB in one RDMA */
+#define ISCSI_ISER_SG_TABLESIZE         (0x80000 >> PAGE_SHIFT)
+#define ISCSI_ISER_MAX_LUN		256
+#define ISCSI_ISER_MAX_CMD_LEN		16
+
+/* QP settings */
+/* Maximal bounds on received asynchronous PDUs */
+#define ISER_MAX_RX_MISC_PDUS		4 /* NOOP_IN(2) , ASYNC_EVENT(2)   */
+
+#define ISER_MAX_TX_MISC_PDUS		6 /* NOOP_OUT(2), TEXT(1),         *
+					   * SCSI_TMFUNC(2), LOGOUT(1) */
+
+#define ISER_QP_MAX_RECV_DTOS		(ISCSI_XMIT_CMDS_MAX + \
+					ISER_MAX_RX_MISC_PDUS    +  \
+					ISER_MAX_TX_MISC_PDUS)
+
+/* the max TX (send) WR supported by the iSER QP is defined by                 *
+ * max_send_wr = T * (1 + D) + C ; D is how many inflight dataouts we expect   *
+ * to have at max for SCSI command. The tx posting & completion handling code  *
+ * supports -EAGAIN scheme where tx is suspended till the QP has room for more *
+ * send WR. D=8 comes from 64K/8K                                              */
+
+#define ISER_INFLIGHT_DATAOUTS		8
+
+#define ISER_QP_MAX_REQ_DTOS		(ISCSI_XMIT_CMDS_MAX *    \
+					(1 + ISER_INFLIGHT_DATAOUTS) + \
+					ISER_MAX_TX_MISC_PDUS        + \
+					ISER_MAX_RX_MISC_PDUS)
+
+#define ISER_VER			0x10
+#define ISER_WSV			0x08
+#define ISER_RSV			0x04
+
+struct iser_hdr {
+	u8      flags;
+	u8      rsvd[3];
+	__be32  write_stag; /* write rkey */
+	__be64  write_va;
+	__be32  read_stag;  /* read rkey */
+	__be64  read_va;
+} __attribute__((packed));
+
+
+/* Length of an object name string */
+#define ISER_OBJECT_NAME_SIZE		    64
+
+enum iser_ib_conn_state {
+	ISER_CONN_INIT,		   /* descriptor allocd, no conn          */
+	ISER_CONN_PENDING,	   /* in the process of being established */
+	ISER_CONN_UP,		   /* up and running                      */
+	ISER_CONN_TERMINATING,	   /* in the process of being terminated  */
+	ISER_CONN_DOWN,		   /* shut down                           */
+	ISER_CONN_STATES_NUM
+};
+
+enum iser_task_status {
+	ISER_TASK_STATUS_INIT = 0,
+	ISER_TASK_STATUS_STARTED,
+	ISER_TASK_STATUS_COMPLETED
+};
+
+enum iser_data_dir {
+	ISER_DIR_IN = 0,	   /* to initiator */
+	ISER_DIR_OUT,		   /* from initiator */
+	ISER_DIRS_NUM
+};
+
+struct iser_data_buf {
+	void               *buf;      /* pointer to the sg list               */
+	unsigned int       size;      /* num entries of this sg               */
+	unsigned long      data_len;  /* total data len                       */
+	unsigned int       dma_nents; /* returned by dma_map_sg               */
+	char       	   *copy_buf; /* allocated copy buf for SGs unaligned *
+	                               * for rdma which are copied            */
+	struct scatterlist sg_single; /* SG-ified clone of a non SG SC or     *
+				       * unaligned SG                         */
+  };
+
+/* fwd declarations */
+struct iser_device;
+struct iscsi_iser_conn;
+struct iscsi_iser_cmd_task;
+
+struct iser_mem_reg {
+	u32  lkey;
+	u32  rkey;
+	u64  va;
+	u64  len;
+	void *mem_h;
+};
+
+struct iser_regd_buf {
+	struct iser_mem_reg     reg;        /* memory registration info        */
+	void                    *virt_addr;
+	struct iser_device      *device;    /* device->device for dma_unmap    */
+	dma_addr_t              dma_addr;   /* if non zero, addr for dma_unmap */
+	enum dma_data_direction direction;  /* direction for dma_unmap	       */
+	unsigned int            data_size;
+	atomic_t                ref_count;  /* refcount, freed when dec to 0   */
+};
+
+#define MAX_REGD_BUF_VECTOR_LEN	2
+
+struct iser_dto {
+	struct iscsi_iser_cmd_task *ctask;
+	struct iscsi_iser_conn     *conn;
+	int                        notify_enable;
+
+	/* vector of registered buffers */
+	unsigned int               regd_vector_len;
+	struct iser_regd_buf       *regd[MAX_REGD_BUF_VECTOR_LEN];
+
+	/* offset into the registered buffer may be specified */
+	unsigned int               offset[MAX_REGD_BUF_VECTOR_LEN];
+
+	/* a smaller size may be specified, if 0, then full size is used */
+	unsigned int               used_sz[MAX_REGD_BUF_VECTOR_LEN];
+};
+
+enum iser_desc_type {
+	ISCSI_RX,
+	ISCSI_TX_CONTROL ,
+	ISCSI_TX_SCSI_COMMAND,
+	ISCSI_TX_DATAOUT
+};
+
+struct iser_desc {
+	struct iser_hdr              iser_header;
+	struct iscsi_hdr             iscsi_header;
+	struct iser_regd_buf         hdr_regd_buf;
+	void                         *data;         /* used by RX & TX_CONTROL */
+	struct iser_regd_buf         data_regd_buf; /* used by RX & TX_CONTROL */
+	enum   iser_desc_type        type;
+	struct iser_dto              dto;
+};
+
+struct iser_device {
+	struct ib_device             *ib_device;
+	struct ib_pd	             *pd;
+	struct ib_cq	             *cq;
+	struct ib_mr	             *mr;
+	struct tasklet_struct	     cq_tasklet;
+	struct list_head             ig_list; /* entry in ig devices list */
+	int                          refcount;
+};
+
+struct iser_conn {
+	struct iscsi_iser_conn       *iser_conn; /* iser conn for upcalls  */
+	enum iser_ib_conn_state	     state;	    /* rdma connection state   */
+	spinlock_t		     lock;	    /* used for state changes  */
+	struct iser_device           *device;       /* device context          */
+	struct rdma_cm_id            *cma_id;       /* CMA ID		       */
+	struct ib_qp	             *qp;           /* QP 		       */
+	struct ib_fmr_pool           *fmr_pool;     /* pool of IB FMRs         */
+	int                          disc_evt_flag; /* disconn event delivered */
+	wait_queue_head_t	     wait;          /* waitq for conn/disconn  */
+	atomic_t                     post_recv_buf_count; /* posted rx count   */
+	atomic_t                     post_send_buf_count; /* posted tx count   */
+	struct work_struct           comperror_work; /* conn term sleepable ctx*/
+	char 			     name[ISER_OBJECT_NAME_SIZE];
+	struct iser_page_vec         *page_vec;     /* represents SG to fmr maps*
+						     * maps serialized as tx is*/
+	struct list_head	     conn_list;       /* entry in ig conn list */
+};
+
+struct iscsi_iser_conn {
+	struct iscsi_conn            *iscsi_conn;/* ptr to iscsi conn */
+	struct iser_conn             *ib_conn;   /* iSER IB conn      */
+
+	rwlock_t		     lock;
+};
+
+struct iscsi_iser_cmd_task {
+	struct iser_desc             desc;
+	struct iscsi_iser_conn	     *iser_conn;
+	int			     rdma_data_count;/* RDMA bytes           */
+	enum iser_task_status 	     status;
+	int                          command_sent;  /* set if command  sent  */
+	int                          dir[ISER_DIRS_NUM];      /* set if dir use*/
+	struct iser_regd_buf         rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */
+	struct iser_data_buf         data[ISER_DIRS_NUM];     /* orig. data des*/
+	struct iser_data_buf         data_copy[ISER_DIRS_NUM];/* contig. copy  */
+};
+
+struct iser_page_vec {
+	u64 *pages;
+	int length;
+	int offset;
+	int data_size;
+};
+
+struct iser_global {
+	struct mutex      device_list_mutex;/*                   */
+	struct list_head  device_list;	     /* all iSER devices */
+	struct mutex      connlist_mutex;
+	struct list_head  connlist;		/* all iSER IB connections */
+
+	kmem_cache_t *desc_cache;
+};
+
+extern struct iser_global ig;
+extern int iser_debug_level;
+
+/* allocate connection resources needed for rdma functionality */
+int iser_conn_set_full_featured_mode(struct iscsi_conn *conn);
+
+int iser_send_control(struct iscsi_conn      *conn,
+		      struct iscsi_mgmt_task *mtask);
+
+int iser_send_command(struct iscsi_conn      *conn,
+		      struct iscsi_cmd_task  *ctask);
+
+int iser_send_data_out(struct iscsi_conn     *conn,
+		       struct iscsi_cmd_task *ctask,
+		       struct iscsi_data          *hdr);
+
+void iscsi_iser_recv(struct iscsi_conn *conn,
+		     struct iscsi_hdr       *hdr,
+		     char                   *rx_data,
+		     int                    rx_data_len);
+
+int  iser_conn_init(struct iser_conn **ib_conn);
+
+void iser_conn_terminate(struct iser_conn *ib_conn);
+
+void iser_conn_release(struct iser_conn *ib_conn);
+
+void iser_rcv_completion(struct iser_desc *desc,
+			 unsigned long    dto_xfer_len);
+
+void iser_snd_completion(struct iser_desc *desc);
+
+void iser_ctask_rdma_init(struct iscsi_iser_cmd_task     *ctask);
+
+void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *ctask);
+
+void iser_dto_buffs_release(struct iser_dto *dto);
+
+int  iser_regd_buff_release(struct iser_regd_buf *regd_buf);
+
+void iser_reg_single(struct iser_device      *device,
+		     struct iser_regd_buf    *regd_buf,
+		     enum dma_data_direction direction);
+
+int  iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task    *ctask,
+				  enum iser_data_dir            cmd_dir);
+
+void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask,
+				     enum iser_data_dir         cmd_dir);
+
+int  iser_reg_rdma_mem(struct iscsi_iser_cmd_task *ctask,
+		       enum   iser_data_dir        cmd_dir);
+
+int  iser_connect(struct iser_conn   *ib_conn,
+		  struct sockaddr_in *src_addr,
+		  struct sockaddr_in *dst_addr,
+		  int                non_blocking);
+
+int  iser_reg_page_vec(struct iser_conn     *ib_conn,
+		       struct iser_page_vec *page_vec,
+		       struct iser_mem_reg  *mem_reg);
+
+void iser_unreg_mem(struct iser_mem_reg *mem_reg);
+
+int  iser_post_recv(struct iser_desc *rx_desc);
+int  iser_post_send(struct iser_desc *tx_desc);
+
+int iser_conn_state_comp(struct iser_conn *ib_conn,
+			 enum iser_ib_conn_state comp);
+#endif
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
new file mode 100644
index 0000000..ccf56f6
--- /dev/null
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *	- Redistributions of source code must retain the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer.
+ *
+ *	- Redistributions in binary form must reproduce the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer in the documentation and/or other materials
+ *	  provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iser_initiator.c 6964 2006-05-07 11:11:43Z ogerlitz $
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+#include <linux/kfifo.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+
+#include "iscsi_iser.h"
+
+/* Constant PDU lengths calculations */
+#define ISER_TOTAL_HEADERS_LEN  (sizeof (struct iser_hdr) + \
+				 sizeof (struct iscsi_hdr))
+
+/* iser_dto_add_regd_buff - increments the reference count for *
+ * the registered buffer & adds it to the DTO object           */
+static void iser_dto_add_regd_buff(struct iser_dto *dto,
+				   struct iser_regd_buf *regd_buf,
+				   unsigned long use_offset,
+				   unsigned long use_size)
+{
+	int add_idx;
+
+	atomic_inc(&regd_buf->ref_count);
+
+	add_idx = dto->regd_vector_len;
+	dto->regd[add_idx] = regd_buf;
+	dto->used_sz[add_idx] = use_size;
+	dto->offset[add_idx] = use_offset;
+
+	dto->regd_vector_len++;
+}
+
+static int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask,
+				  struct iser_data_buf       *data,
+				  enum   iser_data_dir       iser_dir,
+				  enum   dma_data_direction  dma_dir)
+{
+	struct device *dma_device;
+
+	iser_ctask->dir[iser_dir] = 1;
+	dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+	data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir);
+	if (data->dma_nents == 0) {
+		iser_err("dma_map_sg failed!!!\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask)
+{
+	struct device  *dma_device;
+	struct iser_data_buf *data;
+
+	dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+	if (iser_ctask->dir[ISER_DIR_IN]) {
+		data = &iser_ctask->data[ISER_DIR_IN];
+		dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE);
+	}
+
+	if (iser_ctask->dir[ISER_DIR_OUT]) {
+		data = &iser_ctask->data[ISER_DIR_OUT];
+		dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE);
+	}
+}
+
+/* Register user buffer memory and initialize passive rdma
+ *  dto descriptor. Total data size is stored in
+ *  iser_ctask->data[ISER_DIR_IN].data_len
+ */
+static int iser_prepare_read_cmd(struct iscsi_cmd_task *ctask,
+				 unsigned int edtl)
+
+{
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+	struct iser_regd_buf *regd_buf;
+	int err;
+	struct iser_hdr *hdr = &iser_ctask->desc.iser_header;
+	struct iser_data_buf *buf_in = &iser_ctask->data[ISER_DIR_IN];
+
+	err = iser_dma_map_task_data(iser_ctask,
+				     buf_in,
+				     ISER_DIR_IN,
+				     DMA_FROM_DEVICE);
+	if (err)
+		return err;
+
+	if (edtl > iser_ctask->data[ISER_DIR_IN].data_len) {
+		iser_err("Total data length: %ld, less than EDTL: "
+			 "%d, in READ cmd BHS itt: %d, conn: 0x%p\n",
+			 iser_ctask->data[ISER_DIR_IN].data_len, edtl,
+			 ctask->itt, iser_ctask->iser_conn);
+		return -EINVAL;
+	}
+
+	err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_IN);
+	if (err) {
+		iser_err("Failed to set up Data-IN RDMA\n");
+		return err;
+	}
+	regd_buf = &iser_ctask->rdma_regd[ISER_DIR_IN];
+
+	hdr->flags    |= ISER_RSV;
+	hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey);
+	hdr->read_va   = cpu_to_be64(regd_buf->reg.va);
+
+	iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n",
+		 ctask->itt, regd_buf->reg.rkey,
+		 (unsigned long long)regd_buf->reg.va);
+
+	return 0;
+}
+
+/* Register user buffer memory and initialize passive rdma
+ *  dto descriptor. Total data size is stored in
+ *  ctask->data[ISER_DIR_OUT].data_len
+ */
+static int
+iser_prepare_write_cmd(struct iscsi_cmd_task *ctask,
+		       unsigned int imm_sz,
+		       unsigned int unsol_sz,
+		       unsigned int edtl)
+{
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+	struct iser_regd_buf *regd_buf;
+	int err;
+	struct iser_dto *send_dto = &iser_ctask->desc.dto;
+	struct iser_hdr *hdr = &iser_ctask->desc.iser_header;
+	struct iser_data_buf *buf_out = &iser_ctask->data[ISER_DIR_OUT];
+
+	err = iser_dma_map_task_data(iser_ctask,
+				     buf_out,
+				     ISER_DIR_OUT,
+				     DMA_TO_DEVICE);
+	if (err)
+		return err;
+
+	if (edtl > iser_ctask->data[ISER_DIR_OUT].data_len) {
+		iser_err("Total data length: %ld, less than EDTL: %d, "
+			 "in WRITE cmd BHS itt: %d, conn: 0x%p\n",
+			 iser_ctask->data[ISER_DIR_OUT].data_len,
+			 edtl, ctask->itt, ctask->conn);
+		return -EINVAL;
+	}
+
+	err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_OUT);
+	if (err != 0) {
+		iser_err("Failed to register write cmd RDMA mem\n");
+		return err;
+	}
+
+	regd_buf = &iser_ctask->rdma_regd[ISER_DIR_OUT];
+
+	if (unsol_sz < edtl) {
+		hdr->flags     |= ISER_WSV;
+		hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey);
+		hdr->write_va   = cpu_to_be64(regd_buf->reg.va + unsol_sz);
+
+		iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X "
+			 "VA:%#llX + unsol:%d\n",
+			 ctask->itt, regd_buf->reg.rkey,
+			 (unsigned long long)regd_buf->reg.va, unsol_sz);
+	}
+
+	if (imm_sz > 0) {
+		iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n",
+			 ctask->itt, imm_sz);
+		iser_dto_add_regd_buff(send_dto,
+				       regd_buf,
+				       0,
+				       imm_sz);
+	}
+
+	return 0;
+}
+
+/**
+ * iser_post_receive_control - allocates, initializes and posts receive DTO.
+ */
+static int iser_post_receive_control(struct iscsi_conn *conn)
+{
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+	struct iser_desc     *rx_desc;
+	struct iser_regd_buf *regd_hdr;
+	struct iser_regd_buf *regd_data;
+	struct iser_dto      *recv_dto = NULL;
+	struct iser_device  *device = iser_conn->ib_conn->device;
+	int rx_data_size, err = 0;
+
+	rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
+	if (rx_desc == NULL) {
+		iser_err("Failed to alloc desc for post recv\n");
+		return -ENOMEM;
+	}
+	rx_desc->type = ISCSI_RX;
+
+	/* for the login sequence we must support rx of upto 8K; login is done
+	 * after conn create/bind (connect) and conn stop/bind (reconnect),
+	 * what's common for both schemes is that the connection is not started
+	 */
+	if (conn->c_stage != ISCSI_CONN_STARTED)
+		rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+	else /* FIXME till user space sets conn->max_recv_dlength correctly */
+		rx_data_size = 128;
+
+	rx_desc->data = kmalloc(rx_data_size, GFP_NOIO);
+	if (rx_desc->data == NULL) {
+		iser_err("Failed to alloc data buf for post recv\n");
+		err = -ENOMEM;
+		goto post_rx_kmalloc_failure;
+	}
+
+	recv_dto = &rx_desc->dto;
+	recv_dto->conn          = iser_conn;
+	recv_dto->regd_vector_len = 0;
+
+	regd_hdr = &rx_desc->hdr_regd_buf;
+	memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
+	regd_hdr->device  = device;
+	regd_hdr->virt_addr  = rx_desc; /* == &rx_desc->iser_header */
+	regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;
+
+	iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE);
+
+	iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0);
+
+	regd_data = &rx_desc->data_regd_buf;
+	memset(regd_data, 0, sizeof(struct iser_regd_buf));
+	regd_data->device  = device;
+	regd_data->virt_addr  = rx_desc->data;
+	regd_data->data_size  = rx_data_size;
+
+	iser_reg_single(device, regd_data, DMA_FROM_DEVICE);
+
+	iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0);
+
+	err = iser_post_recv(rx_desc);
+	if (!err)
+		return 0;
+
+	/* iser_post_recv failed */
+	iser_dto_buffs_release(recv_dto);
+	kfree(rx_desc->data);
+post_rx_kmalloc_failure:
+	kmem_cache_free(ig.desc_cache, rx_desc);
+	return err;
+}
+
+/* creates a new tx descriptor and adds header regd buffer */
+static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn,
+				  struct iser_desc       *tx_desc)
+{
+	struct iser_regd_buf *regd_hdr = &tx_desc->hdr_regd_buf;
+	struct iser_dto      *send_dto = &tx_desc->dto;
+
+	memset(regd_hdr, 0, sizeof(struct iser_regd_buf));
+	regd_hdr->device  = iser_conn->ib_conn->device;
+	regd_hdr->virt_addr  = tx_desc; /* == &tx_desc->iser_header */
+	regd_hdr->data_size  = ISER_TOTAL_HEADERS_LEN;
+
+	send_dto->conn          = iser_conn;
+	send_dto->notify_enable   = 1;
+	send_dto->regd_vector_len = 0;
+
+	memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr));
+	tx_desc->iser_header.flags = ISER_VER;
+
+	iser_dto_add_regd_buff(send_dto, regd_hdr, 0, 0);
+}
+
+/**
+ *  iser_conn_set_full_featured_mode - (iSER API)
+ */
+int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
+{
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+
+	int i;
+	/* no need to keep it in a var, we are after login so if this should
+	 * be negotiated, by now the result should be available here */
+	int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS;
+
+	iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num);
+
+	/* Check that there is no posted recv or send buffers left - */
+	/* they must be consumed during the login phase */
+	BUG_ON(atomic_read(&iser_conn->ib_conn->post_recv_buf_count) != 0);
+	BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
+
+	/* Initial post receive buffers */
+	for (i = 0; i < initial_post_recv_bufs_num; i++) {
+		if (iser_post_receive_control(conn) != 0) {
+			iser_err("Failed to post recv bufs at:%d conn:0x%p\n",
+				 i, conn);
+			return -ENOMEM;
+		}
+	}
+	iser_dbg("Posted %d post recv bufs, conn:0x%p\n", i, conn);
+	return 0;
+}
+
+static int
+iser_check_xmit(struct iscsi_conn *conn, void *task)
+{
+	int rc = 0;
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+
+	write_lock_bh(conn->recv_lock);
+	if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) ==
+	    ISER_QP_MAX_REQ_DTOS) {
+		iser_dbg("%ld can't xmit task %p, suspending tx\n",jiffies,task);
+		set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+		rc = -EAGAIN;
+	}
+	write_unlock_bh(conn->recv_lock);
+	return rc;
+}
+
+
+/**
+ * iser_send_command - send command PDU
+ */
+int iser_send_command(struct iscsi_conn     *conn,
+		      struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+	struct iser_dto *send_dto = NULL;
+	unsigned long edtl;
+	int err = 0;
+	struct iser_data_buf *data_buf;
+
+	struct iscsi_cmd *hdr =  ctask->hdr;
+	struct scsi_cmnd *sc  =  ctask->sc;
+
+	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
+		return -EPERM;
+	}
+	if (iser_check_xmit(conn, ctask))
+		return -EAGAIN;
+
+	edtl = ntohl(hdr->data_length);
+
+	/* build the tx desc regd header and add it to the tx desc dto */
+	iser_ctask->desc.type = ISCSI_TX_SCSI_COMMAND;
+	send_dto = &iser_ctask->desc.dto;
+	send_dto->ctask = iser_ctask;
+	iser_create_send_desc(iser_conn, &iser_ctask->desc);
+
+	if (hdr->flags & ISCSI_FLAG_CMD_READ)
+		data_buf = &iser_ctask->data[ISER_DIR_IN];
+	else
+		data_buf = &iser_ctask->data[ISER_DIR_OUT];
+
+	if (sc->use_sg) { /* using a scatter list */
+		data_buf->buf  = sc->request_buffer;
+		data_buf->size = sc->use_sg;
+	} else if (sc->request_bufflen) {
+		/* using a single buffer - convert it into one entry SG */
+		sg_init_one(&data_buf->sg_single,
+			    sc->request_buffer, sc->request_bufflen);
+		data_buf->buf   = &data_buf->sg_single;
+		data_buf->size  = 1;
+	}
+
+	data_buf->data_len = sc->request_bufflen;
+
+	if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+		err = iser_prepare_read_cmd(ctask, edtl);
+		if (err)
+			goto send_command_error;
+	}
+	if (hdr->flags & ISCSI_FLAG_CMD_WRITE) {
+		err = iser_prepare_write_cmd(ctask,
+					     ctask->imm_count,
+				             ctask->imm_count +
+					     ctask->unsol_count,
+					     edtl);
+		if (err)
+			goto send_command_error;
+	}
+
+	iser_reg_single(iser_conn->ib_conn->device,
+			send_dto->regd[0], DMA_TO_DEVICE);
+
+	if (iser_post_receive_control(conn) != 0) {
+		iser_err("post_recv failed!\n");
+		err = -ENOMEM;
+		goto send_command_error;
+	}
+
+	iser_ctask->status = ISER_TASK_STATUS_STARTED;
+
+	err = iser_post_send(&iser_ctask->desc);
+	if (!err)
+		return 0;
+
+send_command_error:
+	iser_dto_buffs_release(send_dto);
+	iser_err("conn %p failed ctask->itt %d err %d\n",conn, ctask->itt, err);
+	return err;
+}
+
+/**
+ * iser_send_data_out - send data out PDU
+ */
+int iser_send_data_out(struct iscsi_conn     *conn,
+		       struct iscsi_cmd_task *ctask,
+		       struct iscsi_data *hdr)
+{
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+	struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data;
+	struct iser_desc *tx_desc = NULL;
+	struct iser_dto *send_dto = NULL;
+	unsigned long buf_offset;
+	unsigned long data_seg_len;
+	unsigned int itt;
+	int err = 0;
+
+	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
+		return -EPERM;
+	}
+
+	if (iser_check_xmit(conn, ctask))
+		return -EAGAIN;
+
+	itt = ntohl(hdr->itt);
+	data_seg_len = ntoh24(hdr->dlength);
+	buf_offset   = ntohl(hdr->offset);
+
+	iser_dbg("%s itt %d dseg_len %d offset %d\n",
+		 __func__,(int)itt,(int)data_seg_len,(int)buf_offset);
+
+	tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO);
+	if (tx_desc == NULL) {
+		iser_err("Failed to alloc desc for post dataout\n");
+		return -ENOMEM;
+	}
+
+	tx_desc->type = ISCSI_TX_DATAOUT;
+	memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr));
+
+	/* build the tx desc regd header and add it to the tx desc dto */
+	send_dto = &tx_desc->dto;
+	send_dto->ctask = iser_ctask;
+	iser_create_send_desc(iser_conn, tx_desc);
+
+	iser_reg_single(iser_conn->ib_conn->device,
+			send_dto->regd[0], DMA_TO_DEVICE);
+
+	/* all data was registered for RDMA, we can use the lkey */
+	iser_dto_add_regd_buff(send_dto,
+			       &iser_ctask->rdma_regd[ISER_DIR_OUT],
+			       buf_offset,
+			       data_seg_len);
+
+	if (buf_offset + data_seg_len > iser_ctask->data[ISER_DIR_OUT].data_len) {
+		iser_err("Offset:%ld & DSL:%ld in Data-Out "
+			 "inconsistent with total len:%ld, itt:%d\n",
+			 buf_offset, data_seg_len,
+			 iser_ctask->data[ISER_DIR_OUT].data_len, itt);
+		err = -EINVAL;
+		goto send_data_out_error;
+	}
+	iser_dbg("data-out itt: %d, offset: %ld, sz: %ld\n",
+		 itt, buf_offset, data_seg_len);
+
+
+	err = iser_post_send(tx_desc);
+	if (!err)
+		return 0;
+
+send_data_out_error:
+	iser_dto_buffs_release(send_dto);
+	kmem_cache_free(ig.desc_cache, tx_desc);
+	iser_err("conn %p failed err %d\n",conn, err);
+	return err;
+}
+
+int iser_send_control(struct iscsi_conn *conn,
+		      struct iscsi_mgmt_task *mtask)
+{
+	struct iscsi_iser_conn *iser_conn = conn->dd_data;
+	struct iser_desc *mdesc = mtask->dd_data;
+	struct iser_dto *send_dto = NULL;
+	unsigned int itt;
+	unsigned long data_seg_len;
+	int err = 0;
+	unsigned char opcode;
+	struct iser_regd_buf *regd_buf;
+	struct iser_device *device;
+
+	if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) {
+		iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn);
+		return -EPERM;
+	}
+
+	if (iser_check_xmit(conn,mtask))
+		return -EAGAIN;
+
+	/* build the tx desc regd header and add it to the tx desc dto */
+	mdesc->type = ISCSI_TX_CONTROL;
+	send_dto = &mdesc->dto;
+	send_dto->ctask = NULL;
+	iser_create_send_desc(iser_conn, mdesc);
+
+	device = iser_conn->ib_conn->device;
+
+	iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE);
+
+	itt = ntohl(mtask->hdr->itt);
+	opcode = mtask->hdr->opcode & ISCSI_OPCODE_MASK;
+	data_seg_len = ntoh24(mtask->hdr->dlength);
+
+	if (data_seg_len > 0) {
+		regd_buf = &mdesc->data_regd_buf;
+		memset(regd_buf, 0, sizeof(struct iser_regd_buf));
+		regd_buf->device = device;
+		regd_buf->virt_addr = mtask->data;
+		regd_buf->data_size = mtask->data_count;
+		iser_reg_single(device, regd_buf,
+				DMA_TO_DEVICE);
+		iser_dto_add_regd_buff(send_dto, regd_buf,
+				       0,
+				       data_seg_len);
+	}
+
+	if (iser_post_receive_control(conn) != 0) {
+		iser_err("post_rcv_buff failed!\n");
+		err = -ENOMEM;
+		goto send_control_error;
+	}
+
+	err = iser_post_send(mdesc);
+	if (!err)
+		return 0;
+
+send_control_error:
+	iser_dto_buffs_release(send_dto);
+	iser_err("conn %p failed err %d\n",conn, err);
+	return err;
+}
+
+/**
+ * iser_rcv_dto_completion - recv DTO completion
+ */
+void iser_rcv_completion(struct iser_desc *rx_desc,
+			 unsigned long dto_xfer_len)
+{
+	struct iser_dto        *dto = &rx_desc->dto;
+	struct iscsi_iser_conn *conn = dto->conn;
+	struct iscsi_session *session = conn->iscsi_conn->session;
+	struct iscsi_cmd_task *ctask;
+	struct iscsi_iser_cmd_task *iser_ctask;
+	struct iscsi_hdr *hdr;
+	char   *rx_data = NULL;
+	int     rx_data_len = 0;
+	unsigned int itt;
+	unsigned char opcode;
+
+	hdr = &rx_desc->iscsi_header;
+
+	iser_dbg("op 0x%x itt 0x%x\n", hdr->opcode,hdr->itt);
+
+	if (dto_xfer_len > ISER_TOTAL_HEADERS_LEN) { /* we have data */
+		rx_data_len = dto_xfer_len - ISER_TOTAL_HEADERS_LEN;
+		rx_data     = dto->regd[1]->virt_addr;
+		rx_data    += dto->offset[1];
+	}
+
+	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
+
+	if (opcode == ISCSI_OP_SCSI_CMD_RSP) {
+	        itt = hdr->itt & ISCSI_ITT_MASK; /* mask out cid and age bits */
+		if (!(itt < session->cmds_max))
+			iser_err("itt can't be matched to task!!!"
+				 "conn %p opcode %d cmds_max %d itt %d\n",
+				 conn->iscsi_conn,opcode,session->cmds_max,itt);
+		/* use the mapping given with the cmds array indexed by itt */
+		ctask = (struct iscsi_cmd_task *)session->cmds[itt];
+		iser_ctask = ctask->dd_data;
+		iser_dbg("itt %d ctask %p\n",itt,ctask);
+		iser_ctask->status = ISER_TASK_STATUS_COMPLETED;
+		iser_ctask_rdma_finalize(iser_ctask);
+	}
+
+	iser_dto_buffs_release(dto);
+
+	iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len);
+
+	kfree(rx_desc->data);
+	kmem_cache_free(ig.desc_cache, rx_desc);
+
+	/* decrementing conn->post_recv_buf_count only --after-- freeing the   *
+	 * task eliminates the need to worry on tasks which are completed in   *
+	 * parallel to the execution of iser_conn_term. So the code that waits *
+	 * for the posted rx bufs refcount to become zero handles everything   */
+	atomic_dec(&conn->ib_conn->post_recv_buf_count);
+}
+
+void iser_snd_completion(struct iser_desc *tx_desc)
+{
+	struct iser_dto        *dto = &tx_desc->dto;
+	struct iscsi_iser_conn *iser_conn = dto->conn;
+	struct iscsi_conn      *conn = iser_conn->iscsi_conn;
+	struct iscsi_mgmt_task *mtask;
+
+	iser_dbg("Initiator, Data sent dto=0x%p\n", dto);
+
+	iser_dto_buffs_release(dto);
+
+	if (tx_desc->type == ISCSI_TX_DATAOUT)
+		kmem_cache_free(ig.desc_cache, tx_desc);
+
+	atomic_dec(&iser_conn->ib_conn->post_send_buf_count);
+
+	write_lock(conn->recv_lock);
+	if (conn->suspend_tx) {
+		iser_dbg("%ld resuming tx\n",jiffies);
+		clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+		scsi_queue_work(conn->session->host, &conn->xmitwork);
+	}
+	write_unlock(conn->recv_lock);
+
+	if (tx_desc->type == ISCSI_TX_CONTROL) {
+		/* this arithmetic is legal by libiscsi dd_data allocation */
+		mtask = (void *) ((long)(void *)tx_desc -
+				  sizeof(struct iscsi_mgmt_task));
+		if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+			struct iscsi_session *session = conn->session;
+
+			spin_lock(&conn->session->lock);
+			list_del(&mtask->running);
+			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+				    sizeof(void*));
+			spin_unlock(&session->lock);
+		}
+	}
+}
+
+void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *iser_ctask)
+
+{
+	iser_ctask->status = ISER_TASK_STATUS_INIT;
+
+	iser_ctask->dir[ISER_DIR_IN] = 0;
+	iser_ctask->dir[ISER_DIR_OUT] = 0;
+
+	iser_ctask->data[ISER_DIR_IN].data_len  = 0;
+	iser_ctask->data[ISER_DIR_OUT].data_len = 0;
+
+	memset(&iser_ctask->rdma_regd[ISER_DIR_IN], 0,
+	       sizeof(struct iser_regd_buf));
+	memset(&iser_ctask->rdma_regd[ISER_DIR_OUT], 0,
+	       sizeof(struct iser_regd_buf));
+}
+
+void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask)
+{
+	int deferred;
+
+	/* if we were reading, copy back to unaligned sglist,
+	 * anyway dma_unmap and free the copy
+	 */
+	if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL)
+		iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_IN);
+	if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL)
+		iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_OUT);
+
+	if (iser_ctask->dir[ISER_DIR_IN]) {
+		deferred = iser_regd_buff_release
+			(&iser_ctask->rdma_regd[ISER_DIR_IN]);
+		if (deferred) {
+			iser_err("References remain for BUF-IN rdma reg\n");
+			BUG();
+		}
+	}
+
+	if (iser_ctask->dir[ISER_DIR_OUT]) {
+		deferred = iser_regd_buff_release
+			(&iser_ctask->rdma_regd[ISER_DIR_OUT]);
+		if (deferred) {
+			iser_err("References remain for BUF-OUT rdma reg\n");
+			BUG();
+		}
+	}
+
+	iser_dma_unmap_task_data(iser_ctask);
+}
+
+void iser_dto_buffs_release(struct iser_dto *dto)
+{
+	int i;
+
+	for (i = 0; i < dto->regd_vector_len; i++)
+		iser_regd_buff_release(dto->regd[i]);
+}
+
diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c
new file mode 100644
index 0000000..31950a5
--- /dev/null
+++ b/drivers/infiniband/ulp/iser/iser_memory.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *	- Redistributions of source code must retain the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer.
+ *
+ *	- Redistributions in binary form must reproduce the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer in the documentation and/or other materials
+ *	  provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iser_memory.c 6964 2006-05-07 11:11:43Z ogerlitz $
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+
+#include "iscsi_iser.h"
+
+#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */
+/**
+ * Decrements the reference count for the
+ * registered buffer & releases it
+ *
+ * returns 0 if released, 1 if deferred
+ */
+int iser_regd_buff_release(struct iser_regd_buf *regd_buf)
+{
+	struct device *dma_device;
+
+	if ((atomic_read(&regd_buf->ref_count) == 0) ||
+	    atomic_dec_and_test(&regd_buf->ref_count)) {
+		/* if we used the dma mr, unreg is just NOP */
+		if (regd_buf->reg.rkey != 0)
+			iser_unreg_mem(&regd_buf->reg);
+
+		if (regd_buf->dma_addr) {
+			dma_device = regd_buf->device->ib_device->dma_device;
+			dma_unmap_single(dma_device,
+					 regd_buf->dma_addr,
+					 regd_buf->data_size,
+					 regd_buf->direction);
+		}
+		/* else this regd buf is associated with task which we */
+		/* dma_unmap_single/sg later */
+		return 0;
+	} else {
+		iser_dbg("Release deferred, regd.buff: 0x%p\n", regd_buf);
+		return 1;
+	}
+}
+
+/**
+ * iser_reg_single - fills registered buffer descriptor with
+ *		     registration information
+ */
+void iser_reg_single(struct iser_device *device,
+		     struct iser_regd_buf *regd_buf,
+		     enum dma_data_direction direction)
+{
+	dma_addr_t dma_addr;
+
+	dma_addr  = dma_map_single(device->ib_device->dma_device,
+				   regd_buf->virt_addr,
+				   regd_buf->data_size, direction);
+	BUG_ON(dma_mapping_error(dma_addr));
+
+	regd_buf->reg.lkey = device->mr->lkey;
+	regd_buf->reg.rkey = 0; /* indicate there's no need to unreg */
+	regd_buf->reg.len  = regd_buf->data_size;
+	regd_buf->reg.va   = dma_addr;
+
+	regd_buf->dma_addr  = dma_addr;
+	regd_buf->direction = direction;
+}
+
+/**
+ * iser_start_rdma_unaligned_sg
+ */
+int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task  *iser_ctask,
+				 enum iser_data_dir cmd_dir)
+{
+	int dma_nents;
+	struct device *dma_device;
+	char *mem = NULL;
+	struct iser_data_buf *data = &iser_ctask->data[cmd_dir];
+	unsigned long  cmd_data_len = data->data_len;
+
+	if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
+		mem = (void *)__get_free_pages(GFP_NOIO,
+		      long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+	else
+		mem = kmalloc(cmd_data_len, GFP_NOIO);
+
+	if (mem == NULL) {
+		iser_err("Failed to allocate mem size %d %d for copying sglist\n",
+			 data->size,(int)cmd_data_len);
+		return -ENOMEM;
+	}
+
+	if (cmd_dir == ISER_DIR_OUT) {
+		/* copy the unaligned sg the buffer which is used for RDMA */
+		struct scatterlist *sg = (struct scatterlist *)data->buf;
+		int i;
+		char *p, *from;
+
+		for (p = mem, i = 0; i < data->size; i++) {
+			from = kmap_atomic(sg[i].page, KM_USER0);
+			memcpy(p,
+			       from + sg[i].offset,
+			       sg[i].length);
+			kunmap_atomic(from, KM_USER0);
+			p += sg[i].length;
+		}
+	}
+
+	sg_init_one(&iser_ctask->data_copy[cmd_dir].sg_single, mem, cmd_data_len);
+	iser_ctask->data_copy[cmd_dir].buf  =
+		&iser_ctask->data_copy[cmd_dir].sg_single;
+	iser_ctask->data_copy[cmd_dir].size = 1;
+
+	iser_ctask->data_copy[cmd_dir].copy_buf  = mem;
+
+	dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+
+	if (cmd_dir == ISER_DIR_OUT)
+		dma_nents = dma_map_sg(dma_device,
+				       &iser_ctask->data_copy[cmd_dir].sg_single,
+				       1, DMA_TO_DEVICE);
+	else
+		dma_nents = dma_map_sg(dma_device,
+				       &iser_ctask->data_copy[cmd_dir].sg_single,
+				       1, DMA_FROM_DEVICE);
+
+	BUG_ON(dma_nents == 0);
+
+	iser_ctask->data_copy[cmd_dir].dma_nents = dma_nents;
+	return 0;
+}
+
+/**
+ * iser_finalize_rdma_unaligned_sg
+ */
+void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask,
+				     enum iser_data_dir         cmd_dir)
+{
+	struct device *dma_device;
+	struct iser_data_buf *mem_copy;
+	unsigned long  cmd_data_len;
+
+	dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device;
+	mem_copy   = &iser_ctask->data_copy[cmd_dir];
+
+	if (cmd_dir == ISER_DIR_OUT)
+		dma_unmap_sg(dma_device, &mem_copy->sg_single, 1,
+			     DMA_TO_DEVICE);
+	else
+		dma_unmap_sg(dma_device, &mem_copy->sg_single, 1,
+			     DMA_FROM_DEVICE);
+
+	if (cmd_dir == ISER_DIR_IN) {
+		char *mem;
+		struct scatterlist *sg;
+		unsigned char *p, *to;
+		unsigned int sg_size;
+		int i;
+
+		/* copy back read RDMA to unaligned sg */
+		mem	= mem_copy->copy_buf;
+
+		sg	= (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf;
+		sg_size = iser_ctask->data[ISER_DIR_IN].size;
+
+		for (p = mem, i = 0; i < sg_size; i++){
+			to = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
+			memcpy(to + sg[i].offset,
+			       p,
+			       sg[i].length);
+			kunmap_atomic(to, KM_SOFTIRQ0);
+			p += sg[i].length;
+		}
+	}
+
+	cmd_data_len = iser_ctask->data[cmd_dir].data_len;
+
+	if (cmd_data_len > ISER_KMALLOC_THRESHOLD)
+		free_pages((unsigned long)mem_copy->copy_buf,
+			   long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT);
+	else
+		kfree(mem_copy->copy_buf);
+
+	mem_copy->copy_buf = NULL;
+}
+
+/**
+ * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses
+ * and returns the length of resulting physical address array (may be less than
+ * the original due to possible compaction).
+ *
+ * we build a "page vec" under the assumption that the SG meets the RDMA
+ * alignment requirements. Other then the first and last SG elements, all
+ * the "internal" elements can be compacted into a list whose elements are
+ * dma addresses of physical pages. The code supports also the weird case
+ * where --few fragments of the same page-- are present in the SG as
+ * consecutive elements. Also, it handles one entry SG.
+ */
+static int iser_sg_to_page_vec(struct iser_data_buf *data,
+			       struct iser_page_vec *page_vec)
+{
+	struct scatterlist *sg = (struct scatterlist *)data->buf;
+	dma_addr_t first_addr, last_addr, page;
+	int start_aligned, end_aligned;
+	unsigned int cur_page = 0;
+	unsigned long total_sz = 0;
+	int i;
+
+	/* compute the offset of first element */
+	page_vec->offset = (u64) sg[0].offset;
+
+	for (i = 0; i < data->dma_nents; i++) {
+		total_sz += sg_dma_len(&sg[i]);
+
+		first_addr = sg_dma_address(&sg[i]);
+		last_addr  = first_addr + sg_dma_len(&sg[i]);
+
+		start_aligned = !(first_addr & ~PAGE_MASK);
+		end_aligned   = !(last_addr  & ~PAGE_MASK);
+
+		/* continue to collect page fragments till aligned or SG ends */
+		while (!end_aligned && (i + 1 < data->dma_nents)) {
+			i++;
+			total_sz += sg_dma_len(&sg[i]);
+			last_addr = sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]);
+			end_aligned = !(last_addr  & ~PAGE_MASK);
+		}
+
+		first_addr = first_addr & PAGE_MASK;
+
+		for (page = first_addr; page < last_addr; page += PAGE_SIZE)
+			page_vec->pages[cur_page++] = page;
+
+	}
+	page_vec->data_size = total_sz;
+	iser_dbg("page_vec->data_size:%d cur_page %d\n", page_vec->data_size,cur_page);
+	return cur_page;
+}
+
+#define MASK_4K			((1UL << 12) - 1) /* 0xFFF */
+#define IS_4K_ALIGNED(addr)	((((unsigned long)addr) & MASK_4K) == 0)
+
+/**
+ * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned
+ * for RDMA sub-list of a scatter-gather list of memory buffers, and  returns
+ * the number of entries which are aligned correctly. Supports the case where
+ * consecutive SG elements are actually fragments of the same physcial page.
+ */
+static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data)
+{
+	struct scatterlist *sg;
+	dma_addr_t end_addr, next_addr;
+	int i, cnt;
+	unsigned int ret_len = 0;
+
+	sg = (struct scatterlist *)data->buf;
+
+	for (cnt = 0, i = 0; i < data->dma_nents; i++, cnt++) {
+		/* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX "
+		   "offset: %ld sz: %ld\n", i,
+		   (unsigned long)page_to_phys(sg[i].page),
+		   (unsigned long)sg[i].offset,
+		   (unsigned long)sg[i].length); */
+		end_addr = sg_dma_address(&sg[i]) +
+			   sg_dma_len(&sg[i]);
+		/* iser_dbg("Checking sg iobuf end address "
+		       "0x%08lX\n", end_addr); */
+		if (i + 1 < data->dma_nents) {
+			next_addr = sg_dma_address(&sg[i+1]);
+			/* are i, i+1 fragments of the same page? */
+			if (end_addr == next_addr)
+				continue;
+			else if (!IS_4K_ALIGNED(end_addr)) {
+				ret_len = cnt + 1;
+				break;
+			}
+		}
+	}
+	if (i == data->dma_nents)
+		ret_len = cnt;	/* loop ended */
+	iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n",
+		 ret_len, data->dma_nents, data);
+	return ret_len;
+}
+
+static void iser_data_buf_dump(struct iser_data_buf *data)
+{
+	struct scatterlist *sg = (struct scatterlist *)data->buf;
+	int i;
+
+	for (i = 0; i < data->size; i++)
+		iser_err("sg[%d] dma_addr:0x%lX page:0x%p "
+			 "off:%d sz:%d dma_len:%d\n",
+			 i, (unsigned long)sg_dma_address(&sg[i]),
+			 sg[i].page, sg[i].offset,
+			 sg[i].length,sg_dma_len(&sg[i]));
+}
+
+static void iser_dump_page_vec(struct iser_page_vec *page_vec)
+{
+	int i;
+
+	iser_err("page vec length %d data size %d\n",
+		 page_vec->length, page_vec->data_size);
+	for (i = 0; i < page_vec->length; i++)
+		iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]);
+}
+
+static void iser_page_vec_build(struct iser_data_buf *data,
+				struct iser_page_vec *page_vec)
+{
+	int page_vec_len = 0;
+
+	page_vec->length = 0;
+	page_vec->offset = 0;
+
+	iser_dbg("Translating sg sz: %d\n", data->dma_nents);
+	page_vec_len = iser_sg_to_page_vec(data,page_vec);
+	iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents,page_vec_len);
+
+	page_vec->length = page_vec_len;
+
+	if (page_vec_len * PAGE_SIZE < page_vec->data_size) {
+		iser_err("page_vec too short to hold this SG\n");
+		iser_data_buf_dump(data);
+		iser_dump_page_vec(page_vec);
+		BUG();
+	}
+}
+
+/**
+ * iser_reg_rdma_mem - Registers memory intended for RDMA,
+ * obtaining rkey and va
+ *
+ * returns 0 on success, errno code on failure
+ */
+int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask,
+		      enum   iser_data_dir        cmd_dir)
+{
+	struct iser_conn     *ib_conn = iser_ctask->iser_conn->ib_conn;
+	struct iser_data_buf *mem = &iser_ctask->data[cmd_dir];
+	struct iser_regd_buf *regd_buf;
+	int aligned_len;
+	int err;
+
+	regd_buf = &iser_ctask->rdma_regd[cmd_dir];
+
+	aligned_len = iser_data_buf_aligned_len(mem);
+	if (aligned_len != mem->size) {
+		iser_err("rdma alignment violation %d/%d aligned\n",
+			 aligned_len, mem->size);
+		iser_data_buf_dump(mem);
+		/* allocate copy buf, if we are writing, copy the */
+		/* unaligned scatterlist, dma map the copy        */
+		if (iser_start_rdma_unaligned_sg(iser_ctask, cmd_dir) != 0)
+				return -ENOMEM;
+		mem = &iser_ctask->data_copy[cmd_dir];
+	}
+
+	iser_page_vec_build(mem, ib_conn->page_vec);
+	err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, &regd_buf->reg);
+	if (err)
+		return err;
+
+	/* take a reference on this regd buf such that it will not be released *
+	 * (eg in send dto completion) before we get the scsi response         */
+	atomic_inc(&regd_buf->ref_count);
+	return 0;
+}
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c
new file mode 100644
index 0000000..ff117bb
--- /dev/null
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -0,0 +1,827 @@
+/*
+ * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2005, 2006 Cisco Systems.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *	- Redistributions of source code must retain the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer.
+ *
+ *	- Redistributions in binary form must reproduce the above
+ *	  copyright notice, this list of conditions and the following
+ *	  disclaimer in the documentation and/or other materials
+ *	  provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id: iser_verbs.c 7051 2006-05-10 12:29:11Z ogerlitz $
+ */
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+
+#include "iscsi_iser.h"
+
+#define ISCSI_ISER_MAX_CONN	8
+#define ISER_MAX_CQ_LEN		((ISER_QP_MAX_RECV_DTOS + \
+				ISER_QP_MAX_REQ_DTOS) *   \
+				 ISCSI_ISER_MAX_CONN)
+
+static void iser_cq_tasklet_fn(unsigned long data);
+static void iser_cq_callback(struct ib_cq *cq, void *cq_context);
+static void iser_comp_error_worker(void *data);
+
+static void iser_cq_event_callback(struct ib_event *cause, void *context)
+{
+	iser_err("got cq event %d \n", cause->event);
+}
+
+static void iser_qp_event_callback(struct ib_event *cause, void *context)
+{
+	iser_err("got qp event %d\n",cause->event);
+}
+
+/**
+ * iser_create_device_ib_res - creates Protection Domain (PD), Completion
+ * Queue (CQ), DMA Memory Region (DMA MR) with the device associated with
+ * the adapator.
+ *
+ * returns 0 on success, -1 on failure
+ */
+static int iser_create_device_ib_res(struct iser_device *device)
+{
+	device->pd = ib_alloc_pd(device->ib_device);
+	if (IS_ERR(device->pd))
+		goto pd_err;
+
+	device->cq = ib_create_cq(device->ib_device,
+				  iser_cq_callback,
+				  iser_cq_event_callback,
+				  (void *)device,
+				  ISER_MAX_CQ_LEN);
+	if (IS_ERR(device->cq))
+		goto cq_err;
+
+	if (ib_req_notify_cq(device->cq, IB_CQ_NEXT_COMP))
+		goto cq_arm_err;
+
+	tasklet_init(&device->cq_tasklet,
+		     iser_cq_tasklet_fn,
+		     (unsigned long)device);
+
+	device->mr = ib_get_dma_mr(device->pd,
+				   IB_ACCESS_LOCAL_WRITE);
+	if (IS_ERR(device->mr))
+		goto dma_mr_err;
+
+	return 0;
+
+dma_mr_err:
+	tasklet_kill(&device->cq_tasklet);
+cq_arm_err:
+	ib_destroy_cq(device->cq);
+cq_err:
+	ib_dealloc_pd(device->pd);
+pd_err:
+	iser_err("failed to allocate an IB resource\n");
+	return -1;
+}
+
+/**
+ * iser_free_device_ib_res - destory/dealloc/dereg the DMA MR,
+ * CQ and PD created with the device associated with the adapator.
+ */
+static void iser_free_device_ib_res(struct iser_device *device)
+{
+	BUG_ON(device->mr == NULL);
+
+	tasklet_kill(&device->cq_tasklet);
+
+	(void)ib_dereg_mr(device->mr);
+	(void)ib_destroy_cq(device->cq);
+	(void)ib_dealloc_pd(device->pd);
+
+	device->mr = NULL;
+	device->cq = NULL;
+	device->pd = NULL;
+}
+
+/**
+ * iser_create_ib_conn_res - Creates FMR pool and Queue-Pair (QP)
+ *
+ * returns 0 on success, -1 on failure
+ */
+static int iser_create_ib_conn_res(struct iser_conn *ib_conn)
+{
+	struct iser_device	*device;
+	struct ib_qp_init_attr	init_attr;
+	int			ret;
+	struct ib_fmr_pool_param params;
+
+	BUG_ON(ib_conn->device == NULL);
+
+	device = ib_conn->device;
+
+	ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) +
+				    (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)),
+				    GFP_KERNEL);
+	if (!ib_conn->page_vec) {
+		ret = -ENOMEM;
+		goto alloc_err;
+	}
+	ib_conn->page_vec->pages = (u64 *) (ib_conn->page_vec + 1);
+
+	params.page_shift        = PAGE_SHIFT;
+	/* when the first/last SG element are not start/end *
+	 * page aligned, the map whould be of N+1 pages     */
+	params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1;
+	/* make the pool size twice the max number of SCSI commands *
+	 * the ML is expected to queue, watermark for unmap at 50%  */
+	params.pool_size	 = ISCSI_XMIT_CMDS_MAX * 2;
+	params.dirty_watermark	 = ISCSI_XMIT_CMDS_MAX;
+	params.cache		 = 0;
+	params.flush_function	 = NULL;
+	params.access		 = (IB_ACCESS_LOCAL_WRITE  |
+				    IB_ACCESS_REMOTE_WRITE |
+				    IB_ACCESS_REMOTE_READ);
+
+	ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, &params);
+	if (IS_ERR(ib_conn->fmr_pool)) {
+		ret = PTR_ERR(ib_conn->fmr_pool);
+		goto fmr_pool_err;
+	}
+
+	memset(&init_attr, 0, sizeof init_attr);
+
+	init_attr.event_handler = iser_qp_event_callback;
+	init_attr.qp_context	= (void *)ib_conn;
+	init_attr.send_cq	= device->cq;
+	init_attr.recv_cq	= device->cq;
+	init_attr.cap.max_send_wr  = ISER_QP_MAX_REQ_DTOS;
+	init_attr.cap.max_recv_wr  = ISER_QP_MAX_RECV_DTOS;
+	init_attr.cap.max_send_sge = MAX_REGD_BUF_VECTOR_LEN;
+	init_attr.cap.max_recv_sge = 2;
+	init_attr.sq_sig_type	= IB_SIGNAL_REQ_WR;
+	init_attr.qp_type	= IB_QPT_RC;
+
+	ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr);
+	if (ret)
+		goto qp_err;
+
+	ib_conn->qp = ib_conn->cma_id->qp;
+	iser_err("setting conn %p cma_id %p: fmr_pool %p qp %p\n",
+		 ib_conn, ib_conn->cma_id,
+		 ib_conn->fmr_pool, ib_conn->cma_id->qp);
+	return ret;
+
+qp_err:
+	(void)ib_destroy_fmr_pool(ib_conn->fmr_pool);
+fmr_pool_err:
+	kfree(ib_conn->page_vec);
+alloc_err:
+	iser_err("unable to alloc mem or create resource, err %d\n", ret);
+	return ret;
+}
+
+/**
+ * releases the FMR pool, QP and CMA ID objects, returns 0 on success,
+ * -1 on failure
+ */
+static int iser_free_ib_conn_res(struct iser_conn *ib_conn)
+{
+	BUG_ON(ib_conn == NULL);
+
+	iser_err("freeing conn %p cma_id %p fmr pool %p qp %p\n",
+		 ib_conn, ib_conn->cma_id,
+		 ib_conn->fmr_pool, ib_conn->qp);
+
+	/* qp is created only once both addr & route are resolved */
+	if (ib_conn->fmr_pool != NULL)
+		ib_destroy_fmr_pool(ib_conn->fmr_pool);
+
+	if (ib_conn->qp != NULL)
+		rdma_destroy_qp(ib_conn->cma_id);
+
+	if (ib_conn->cma_id != NULL)
+		rdma_destroy_id(ib_conn->cma_id);
+
+	ib_conn->fmr_pool = NULL;
+	ib_conn->qp	  = NULL;
+	ib_conn->cma_id   = NULL;
+	kfree(ib_conn->page_vec);
+
+	return 0;
+}
+
+/**
+ * based on the resolved device node GUID see if there already allocated
+ * device for this device. If there's no such, create one.
+ */
+static
+struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id)
+{
+	struct list_head    *p_list;
+	struct iser_device  *device = NULL;
+
+	mutex_lock(&ig.device_list_mutex);
+
+	p_list = ig.device_list.next;
+	while (p_list != &ig.device_list) {
+		device = list_entry(p_list, struct iser_device, ig_list);
+		/* find if there's a match using the node GUID */
+		if (device->ib_device->node_guid == cma_id->device->node_guid)
+			break;
+	}
+
+	if (device == NULL) {
+		device = kzalloc(sizeof *device, GFP_KERNEL);
+		if (device == NULL)
+			goto out;
+		/* assign this device to the device */
+		device->ib_device = cma_id->device;
+		/* init the device and link it into ig device list */
+		if (iser_create_device_ib_res(device)) {
+			kfree(device);
+			device = NULL;
+			goto out;
+		}
+		list_add(&device->ig_list, &ig.device_list);
+	}
+out:
+	BUG_ON(device == NULL);
+	device->refcount++;
+	mutex_unlock(&ig.device_list_mutex);
+	return device;
+}
+
+/* if there's no demand for this device, release it */
+static void iser_device_try_release(struct iser_device *device)
+{
+	mutex_lock(&ig.device_list_mutex);
+	device->refcount--;
+	iser_err("device %p refcount %d\n",device,device->refcount);
+	if (!device->refcount) {
+		iser_free_device_ib_res(device);
+		list_del(&device->ig_list);
+		kfree(device);
+	}
+	mutex_unlock(&ig.device_list_mutex);
+}
+
+int iser_conn_state_comp(struct iser_conn *ib_conn,
+			enum iser_ib_conn_state comp)
+{
+	int ret;
+
+	spin_lock_bh(&ib_conn->lock);
+	ret = (ib_conn->state == comp);
+	spin_unlock_bh(&ib_conn->lock);
+	return ret;
+}
+
+static int iser_conn_state_comp_exch(struct iser_conn *ib_conn,
+				     enum iser_ib_conn_state comp,
+				     enum iser_ib_conn_state exch)
+{
+	int ret;
+
+	spin_lock_bh(&ib_conn->lock);
+	if ((ret = (ib_conn->state == comp)))
+		ib_conn->state = exch;
+	spin_unlock_bh(&ib_conn->lock);
+	return ret;
+}
+
+/**
+ * triggers start of the disconnect procedures and wait for them to be done
+ */
+void iser_conn_terminate(struct iser_conn *ib_conn)
+{
+	int err = 0;
+
+	/* change the ib conn state only if the conn is UP, however always call
+	 * rdma_disconnect since this is the only way to cause the CMA to change
+	 * the QP state to ERROR
+	 */
+
+	iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, ISER_CONN_TERMINATING);
+	err = rdma_disconnect(ib_conn->cma_id);
+	if (err)
+		iser_err("Failed to disconnect, conn: 0x%p err %d\n",
+			 ib_conn,err);
+
+	wait_event_interruptible(ib_conn->wait,
+				 ib_conn->state == ISER_CONN_DOWN);
+
+	iser_conn_release(ib_conn);
+}
+
+static void iser_connect_error(struct rdma_cm_id *cma_id)
+{
+	struct iser_conn *ib_conn;
+	ib_conn = (struct iser_conn *)cma_id->context;
+
+	ib_conn->state = ISER_CONN_DOWN;
+	wake_up_interruptible(&ib_conn->wait);
+}
+
+static void iser_addr_handler(struct rdma_cm_id *cma_id)
+{
+	struct iser_device *device;
+	struct iser_conn   *ib_conn;
+	int    ret;
+
+	device = iser_device_find_by_ib_device(cma_id);
+	ib_conn = (struct iser_conn *)cma_id->context;
+	ib_conn->device = device;
+
+	ret = rdma_resolve_route(cma_id, 1000);
+	if (ret) {
+		iser_err("resolve route failed: %d\n", ret);
+		iser_connect_error(cma_id);
+	}
+	return;
+}
+
+static void iser_route_handler(struct rdma_cm_id *cma_id)
+{
+	struct rdma_conn_param conn_param;
+	int    ret;
+
+	ret = iser_create_ib_conn_res((struct iser_conn *)cma_id->context);
+	if (ret)
+		goto failure;
+
+	iser_dbg("path.mtu is %d setting it to %d\n",
+		 cma_id->route.path_rec->mtu, IB_MTU_1024);
+
+	/* we must set the MTU to 1024 as this is what the target is assuming */
+	if (cma_id->route.path_rec->mtu > IB_MTU_1024)
+		cma_id->route.path_rec->mtu = IB_MTU_1024;
+
+	memset(&conn_param, 0, sizeof conn_param);
+	conn_param.responder_resources = 4;
+	conn_param.initiator_depth     = 1;
+	conn_param.retry_count	       = 7;
+	conn_param.rnr_retry_count     = 6;
+
+	ret = rdma_connect(cma_id, &conn_param);
+	if (ret) {
+		iser_err("failure connecting: %d\n", ret);
+		goto failure;
+	}
+
+	return;
+failure:
+	iser_connect_error(cma_id);
+}
+
+static void iser_connected_handler(struct rdma_cm_id *cma_id)
+{
+	struct iser_conn *ib_conn;
+
+	ib_conn = (struct iser_conn *)cma_id->context;
+	ib_conn->state = ISER_CONN_UP;
+	wake_up_interruptible(&ib_conn->wait);
+}
+
+static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
+{
+	struct iser_conn *ib_conn;
+
+	ib_conn = (struct iser_conn *)cma_id->context;
+	ib_conn->disc_evt_flag = 1;
+
+	/* getting here when the state is UP means that the conn is being *
+	 * terminated asynchronously from the iSCSI layer's perspective.  */
+	if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
+				      ISER_CONN_TERMINATING))
+		iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
+				   ISCSI_ERR_CONN_FAILED);
+
+	/* Complete the termination process if no posts are pending */
+	if ((atomic_read(&ib_conn->post_recv_buf_count) == 0) &&
+	    (atomic_read(&ib_conn->post_send_buf_count) == 0)) {
+		ib_conn->state = ISER_CONN_DOWN;
+		wake_up_interruptible(&ib_conn->wait);
+	}
+}
+
+static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
+{
+	int ret = 0;
+
+	iser_err("event %d conn %p id %p\n",event->event,cma_id->context,cma_id);
+
+	switch (event->event) {
+	case RDMA_CM_EVENT_ADDR_RESOLVED:
+		iser_addr_handler(cma_id);
+		break;
+	case RDMA_CM_EVENT_ROUTE_RESOLVED:
+		iser_route_handler(cma_id);
+		break;
+	case RDMA_CM_EVENT_ESTABLISHED:
+		iser_connected_handler(cma_id);
+		break;
+	case RDMA_CM_EVENT_ADDR_ERROR:
+	case RDMA_CM_EVENT_ROUTE_ERROR:
+	case RDMA_CM_EVENT_CONNECT_ERROR:
+	case RDMA_CM_EVENT_UNREACHABLE:
+	case RDMA_CM_EVENT_REJECTED:
+		iser_err("event: %d, error: %d\n", event->event, event->status);
+		iser_connect_error(cma_id);
+		break;
+	case RDMA_CM_EVENT_DISCONNECTED:
+		iser_disconnected_handler(cma_id);
+		break;
+	case RDMA_CM_EVENT_DEVICE_REMOVAL:
+		BUG();
+		break;
+	case RDMA_CM_EVENT_CONNECT_RESPONSE:
+		BUG();
+		break;
+	case RDMA_CM_EVENT_CONNECT_REQUEST:
+	default:
+		break;
+	}
+	return ret;
+}
+
+int iser_conn_init(struct iser_conn **ibconn)
+{
+	struct iser_conn *ib_conn;
+
+	ib_conn = kzalloc(sizeof *ib_conn, GFP_KERNEL);
+	if (!ib_conn) {
+		iser_err("can't alloc memory for struct iser_conn\n");
+		return -ENOMEM;
+	}
+	ib_conn->state = ISER_CONN_INIT;
+	init_waitqueue_head(&ib_conn->wait);
+	atomic_set(&ib_conn->post_recv_buf_count, 0);
+	atomic_set(&ib_conn->post_send_buf_count, 0);
+	INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker,
+		  ib_conn);
+	INIT_LIST_HEAD(&ib_conn->conn_list);
+	spin_lock_init(&ib_conn->lock);
+
+	*ibconn = ib_conn;
+	return 0;
+}
+
+ /**
+ * starts the process of connecting to the target
+ * sleeps untill the connection is established or rejected
+ */
+int iser_connect(struct iser_conn   *ib_conn,
+		 struct sockaddr_in *src_addr,
+		 struct sockaddr_in *dst_addr,
+		 int                 non_blocking)
+{
+	struct sockaddr *src, *dst;
+	int err = 0;
+
+	sprintf(ib_conn->name,"%d.%d.%d.%d:%d",
+		NIPQUAD(dst_addr->sin_addr.s_addr), dst_addr->sin_port);
+
+	/* the device is known only --after-- address resolution */
+	ib_conn->device = NULL;
+
+	iser_err("connecting to: %d.%d.%d.%d, port 0x%x\n",
+		 NIPQUAD(dst_addr->sin_addr), dst_addr->sin_port);
+
+	ib_conn->state = ISER_CONN_PENDING;
+
+	ib_conn->cma_id = rdma_create_id(iser_cma_handler,
+					     (void *)ib_conn,
+					     RDMA_PS_TCP);
+	if (IS_ERR(ib_conn->cma_id)) {
+		err = PTR_ERR(ib_conn->cma_id);
+		iser_err("rdma_create_id failed: %d\n", err);
+		goto id_failure;
+	}
+
+	src = (struct sockaddr *)src_addr;
+	dst = (struct sockaddr *)dst_addr;
+	err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000);
+	if (err) {
+		iser_err("rdma_resolve_addr failed: %d\n", err);
+		goto addr_failure;
+	}
+
+	if (!non_blocking) {
+		wait_event_interruptible(ib_conn->wait,
+					 (ib_conn->state != ISER_CONN_PENDING));
+
+		if (ib_conn->state != ISER_CONN_UP) {
+			err =  -EIO;
+			goto connect_failure;
+		}
+	}
+
+	mutex_lock(&ig.connlist_mutex);
+	list_add(&ib_conn->conn_list, &ig.connlist);
+	mutex_unlock(&ig.connlist_mutex);
+	return 0;
+
+id_failure:
+	ib_conn->cma_id = NULL;
+addr_failure:
+	ib_conn->state = ISER_CONN_DOWN;
+connect_failure:
+	iser_conn_release(ib_conn);
+	return err;
+}
+
+/**
+ * Frees all conn objects and deallocs conn descriptor
+ */
+void iser_conn_release(struct iser_conn *ib_conn)
+{
+	struct iser_device  *device = ib_conn->device;
+
+	BUG_ON(ib_conn->state != ISER_CONN_DOWN);
+
+	mutex_lock(&ig.connlist_mutex);
+	list_del(&ib_conn->conn_list);
+	mutex_unlock(&ig.connlist_mutex);
+
+	iser_free_ib_conn_res(ib_conn);
+	ib_conn->device = NULL;
+	/* on EVENT_ADDR_ERROR there's no device yet for this conn */
+	if (device != NULL)
+		iser_device_try_release(device);
+	kfree(ib_conn);
+}
+
+
+/**
+ * iser_reg_page_vec - Register physical memory
+ *
+ * returns: 0 on success, errno code on failure
+ */
+int iser_reg_page_vec(struct iser_conn     *ib_conn,
+		      struct iser_page_vec *page_vec,
+		      struct iser_mem_reg  *mem_reg)
+{
+	struct ib_pool_fmr *mem;
+	u64		   io_addr;
+	u64		   *page_list;
+	int		   status;
+
+	page_list = page_vec->pages;
+	io_addr	  = page_list[0];
+
+	mem  = ib_fmr_pool_map_phys(ib_conn->fmr_pool,
+				    page_list,
+				    page_vec->length,
+				    &io_addr);
+
+	if (IS_ERR(mem)) {
+		status = (int)PTR_ERR(mem);
+		iser_err("ib_fmr_pool_map_phys failed: %d\n", status);
+		return status;
+	}
+
+	mem_reg->lkey  = mem->fmr->lkey;
+	mem_reg->rkey  = mem->fmr->rkey;
+	mem_reg->len   = page_vec->length * PAGE_SIZE;
+	mem_reg->va    = io_addr;
+	mem_reg->mem_h = (void *)mem;
+
+	mem_reg->va   += page_vec->offset;
+	mem_reg->len   = page_vec->data_size;
+
+	iser_dbg("PHYSICAL Mem.register, [PHYS p_array: 0x%p, sz: %d, "
+		 "entry[0]: (0x%08lx,%ld)] -> "
+		 "[lkey: 0x%08X mem_h: 0x%p va: 0x%08lX sz: %ld]\n",
+		 page_vec, page_vec->length,
+		 (unsigned long)page_vec->pages[0],
+		 (unsigned long)page_vec->data_size,
+		 (unsigned int)mem_reg->lkey, mem_reg->mem_h,
+		 (unsigned long)mem_reg->va, (unsigned long)mem_reg->len);
+	return 0;
+}
+
+/**
+ * Unregister (previosuly registered) memory.
+ */
+void iser_unreg_mem(struct iser_mem_reg *reg)
+{
+	int ret;
+
+	iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n",reg->mem_h);
+
+	ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h);
+	if (ret)
+		iser_err("ib_fmr_pool_unmap failed %d\n", ret);
+
+	reg->mem_h = NULL;
+}
+
+/**
+ * iser_dto_to_iov - builds IOV from a dto descriptor
+ */
+static void iser_dto_to_iov(struct iser_dto *dto, struct ib_sge *iov, int iov_len)
+{
+	int		     i;
+	struct ib_sge	     *sge;
+	struct iser_regd_buf *regd_buf;
+
+	if (dto->regd_vector_len > iov_len) {
+		iser_err("iov size %d too small for posting dto of len %d\n",
+			 iov_len, dto->regd_vector_len);
+		BUG();
+	}
+
+	for (i = 0; i < dto->regd_vector_len; i++) {
+		sge	    = &iov[i];
+		regd_buf  = dto->regd[i];
+
+		sge->addr   = regd_buf->reg.va;
+		sge->length = regd_buf->reg.len;
+		sge->lkey   = regd_buf->reg.lkey;
+
+		if (dto->used_sz[i] > 0)  /* Adjust size */
+			sge->length = dto->used_sz[i];
+
+		/* offset and length should not exceed the regd buf length */
+		if (sge->length + dto->offset[i] > regd_buf->reg.len) {
+			iser_err("Used len:%ld + offset:%d, exceed reg.buf.len:"
+				 "%ld in dto:0x%p [%d], va:0x%08lX\n",
+				 (unsigned long)sge->length, dto->offset[i],
+				 (unsigned long)regd_buf->reg.len, dto, i,
+				 (unsigned long)sge->addr);
+			BUG();
+		}
+
+		sge->addr += dto->offset[i]; /* Adjust offset */
+	}
+}
+
+/**
+ * iser_post_recv - Posts a receive buffer.
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_post_recv(struct iser_desc *rx_desc)
+{
+	int		  ib_ret, ret_val = 0;
+	struct ib_recv_wr recv_wr, *recv_wr_failed;
+	struct ib_sge	  iov[2];
+	struct iser_conn  *ib_conn;
+	struct iser_dto   *recv_dto = &rx_desc->dto;
+
+	/* Retrieve conn */
+	ib_conn = recv_dto->conn->ib_conn;
+
+	iser_dto_to_iov(recv_dto, iov, 2);
+
+	recv_wr.next	= NULL;
+	recv_wr.sg_list = iov;
+	recv_wr.num_sge = recv_dto->regd_vector_len;
+	recv_wr.wr_id	= (unsigned long)rx_desc;
+
+	atomic_inc(&ib_conn->post_recv_buf_count);
+	ib_ret	= ib_post_recv(ib_conn->qp, &recv_wr, &recv_wr_failed);
+	if (ib_ret) {
+		iser_err("ib_post_recv failed ret=%d\n", ib_ret);
+		atomic_dec(&ib_conn->post_recv_buf_count);
+		ret_val = -1;
+	}
+
+	return ret_val;
+}
+
+/**
+ * iser_start_send - Initiate a Send DTO operation
+ *
+ * returns 0 on success, -1 on failure
+ */
+int iser_post_send(struct iser_desc *tx_desc)
+{
+	int		  ib_ret, ret_val = 0;
+	struct ib_send_wr send_wr, *send_wr_failed;
+	struct ib_sge	  iov[MAX_REGD_BUF_VECTOR_LEN];
+	struct iser_conn  *ib_conn;
+	struct iser_dto   *dto = &tx_desc->dto;
+
+	ib_conn = dto->conn->ib_conn;
+
+	iser_dto_to_iov(dto, iov, MAX_REGD_BUF_VECTOR_LEN);
+
+	send_wr.next	   = NULL;
+	send_wr.wr_id	   = (unsigned long)tx_desc;
+	send_wr.sg_list	   = iov;
+	send_wr.num_sge	   = dto->regd_vector_len;
+	send_wr.opcode	   = IB_WR_SEND;
+	send_wr.send_flags = dto->notify_enable ? IB_SEND_SIGNALED : 0;
+
+	atomic_inc(&ib_conn->post_send_buf_count);
+
+	ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed);
+	if (ib_ret) {
+		iser_err("Failed to start SEND DTO, dto: 0x%p, IOV len: %d\n",
+			 dto, dto->regd_vector_len);
+		iser_err("ib_post_send failed, ret:%d\n", ib_ret);
+		atomic_dec(&ib_conn->post_send_buf_count);
+		ret_val = -1;
+	}
+
+	return ret_val;
+}
+
+static void iser_comp_error_worker(void *data)
+{
+	struct iser_conn *ib_conn = data;
+
+	/* getting here when the state is UP means that the conn is being *
+	 * terminated asynchronously from the iSCSI layer's perspective.  */
+	if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
+				      ISER_CONN_TERMINATING))
+		iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn,
+					ISCSI_ERR_CONN_FAILED);
+
+	/* complete the termination process if disconnect event was delivered *
+	 * note there are no more non completed posts to the QP               */
+	if (ib_conn->disc_evt_flag) {
+		ib_conn->state = ISER_CONN_DOWN;
+		wake_up_interruptible(&ib_conn->wait);
+	}
+}
+
+static void iser_handle_comp_error(struct iser_desc *desc)
+{
+	struct iser_dto  *dto     = &desc->dto;
+	struct iser_conn *ib_conn = dto->conn->ib_conn;
+
+	iser_dto_buffs_release(dto);
+
+	if (desc->type == ISCSI_RX) {
+		kfree(desc->data);
+		kmem_cache_free(ig.desc_cache, desc);
+		atomic_dec(&ib_conn->post_recv_buf_count);
+	} else { /* type is TX control/command/dataout */
+		if (desc->type == ISCSI_TX_DATAOUT)
+			kmem_cache_free(ig.desc_cache, desc);
+		atomic_dec(&ib_conn->post_send_buf_count);
+	}
+
+	if (atomic_read(&ib_conn->post_recv_buf_count) == 0 &&
+	    atomic_read(&ib_conn->post_send_buf_count) == 0)
+		schedule_work(&ib_conn->comperror_work);
+}
+
+static void iser_cq_tasklet_fn(unsigned long data)
+{
+	 struct iser_device  *device = (struct iser_device *)data;
+	 struct ib_cq	     *cq = device->cq;
+	 struct ib_wc	     wc;
+	 struct iser_desc    *desc;
+	 unsigned long	     xfer_len;
+
+	while (ib_poll_cq(cq, 1, &wc) == 1) {
+		desc	 = (struct iser_desc *) (unsigned long) wc.wr_id;
+		BUG_ON(desc == NULL);
+
+		if (wc.status == IB_WC_SUCCESS) {
+			if (desc->type == ISCSI_RX) {
+				xfer_len = (unsigned long)wc.byte_len;
+				iser_rcv_completion(desc, xfer_len);
+			} else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */
+				iser_snd_completion(desc);
+		} else {
+			iser_err("comp w. error op %d status %d\n",desc->type,wc.status);
+			iser_handle_comp_error(desc);
+		}
+	}
+	/* #warning "it is assumed here that arming CQ only once its empty" *
+	 * " would not cause interrupts to be missed"                       */
+	ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
+}
+
+static void iser_cq_callback(struct ib_cq *cq, void *cq_context)
+{
+	struct iser_device  *device = (struct iser_device *)cq_context;
+
+	tasklet_schedule(&device->cq_tasklet);
+}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 9cbdffa..4e22afef 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -62,6 +62,13 @@
 		   "v" DRV_VERSION " (" DRV_RELDATE ")");
 MODULE_LICENSE("Dual BSD/GPL");
 
+static int srp_sg_tablesize = SRP_DEF_SG_TABLESIZE;
+static int srp_max_iu_len;
+
+module_param(srp_sg_tablesize, int, 0444);
+MODULE_PARM_DESC(srp_sg_tablesize,
+		 "Max number of gather/scatter entries per I/O (default is 12)");
+
 static int topspin_workarounds = 1;
 
 module_param(topspin_workarounds, int, 0444);
@@ -105,7 +112,8 @@
 	if (!iu->buf)
 		goto out_free_iu;
 
-	iu->dma = dma_map_single(host->dev->dma_device, iu->buf, size, direction);
+	iu->dma = dma_map_single(host->dev->dev->dma_device,
+				 iu->buf, size, direction);
 	if (dma_mapping_error(iu->dma))
 		goto out_free_buf;
 
@@ -127,7 +135,8 @@
 	if (!iu)
 		return;
 
-	dma_unmap_single(host->dev->dma_device, iu->dma, iu->size, iu->direction);
+	dma_unmap_single(host->dev->dev->dma_device,
+			 iu->dma, iu->size, iu->direction);
 	kfree(iu->buf);
 	kfree(iu);
 }
@@ -147,7 +156,7 @@
 	if (!attr)
 		return -ENOMEM;
 
-	ret = ib_find_cached_pkey(target->srp_host->dev,
+	ret = ib_find_cached_pkey(target->srp_host->dev->dev,
 				  target->srp_host->port,
 				  be16_to_cpu(target->path.pkey),
 				  &attr->pkey_index);
@@ -179,7 +188,7 @@
 	if (!init_attr)
 		return -ENOMEM;
 
-	target->cq = ib_create_cq(target->srp_host->dev, srp_completion,
+	target->cq = ib_create_cq(target->srp_host->dev->dev, srp_completion,
 				  NULL, target, SRP_CQ_SIZE);
 	if (IS_ERR(target->cq)) {
 		ret = PTR_ERR(target->cq);
@@ -198,7 +207,7 @@
 	init_attr->send_cq             = target->cq;
 	init_attr->recv_cq             = target->cq;
 
-	target->qp = ib_create_qp(target->srp_host->pd, init_attr);
+	target->qp = ib_create_qp(target->srp_host->dev->pd, init_attr);
 	if (IS_ERR(target->qp)) {
 		ret = PTR_ERR(target->qp);
 		ib_destroy_cq(target->cq);
@@ -250,7 +259,7 @@
 
 	init_completion(&target->done);
 
-	target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev,
+	target->path_query_id = ib_sa_path_rec_get(target->srp_host->dev->dev,
 						   target->srp_host->port,
 						   &target->path,
 						   IB_SA_PATH_REC_DGID		|
@@ -309,10 +318,32 @@
 
 	req->priv.opcode     	= SRP_LOGIN_REQ;
 	req->priv.tag        	= 0;
-	req->priv.req_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
+	req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len);
 	req->priv.req_buf_fmt 	= cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
 					      SRP_BUF_FORMAT_INDIRECT);
-	memcpy(req->priv.initiator_port_id, target->srp_host->initiator_port_id, 16);
+	/*
+	 * In the published SRP specification (draft rev. 16a), the 
+	 * port identifier format is 8 bytes of ID extension followed
+	 * by 8 bytes of GUID.  Older drafts put the two halves in the
+	 * opposite order, so that the GUID comes first.
+	 *
+	 * Targets conforming to these obsolete drafts can be
+	 * recognized by the I/O Class they report.
+	 */
+	if (target->io_class == SRP_REV10_IB_IO_CLASS) {
+		memcpy(req->priv.initiator_port_id,
+		       target->srp_host->initiator_port_id + 8, 8);
+		memcpy(req->priv.initiator_port_id + 8,
+		       target->srp_host->initiator_port_id, 8);
+		memcpy(req->priv.target_port_id,     &target->ioc_guid, 8);
+		memcpy(req->priv.target_port_id + 8, &target->id_ext, 8);
+	} else {
+		memcpy(req->priv.initiator_port_id,
+		       target->srp_host->initiator_port_id, 16);
+		memcpy(req->priv.target_port_id,     &target->id_ext, 8);
+		memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
+	}
+
 	/*
 	 * Topspin/Cisco SRP targets will reject our login unless we
 	 * zero out the first 8 bytes of our initiator port ID.  The
@@ -325,8 +356,6 @@
 		       (unsigned long long) be64_to_cpu(target->ioc_guid));
 		memset(req->priv.initiator_port_id, 0, 8);
 	}
-	memcpy(req->priv.target_port_id,     &target->id_ext, 8);
-	memcpy(req->priv.target_port_id + 8, &target->ioc_guid, 8);
 
 	status = ib_send_cm_req(target->cm_id, &req->param);
 
@@ -359,9 +388,9 @@
 	target->state = SRP_TARGET_REMOVED;
 	spin_unlock_irq(target->scsi_host->host_lock);
 
-	mutex_lock(&target->srp_host->target_mutex);
+	spin_lock(&target->srp_host->target_lock);
 	list_del(&target->list);
-	mutex_unlock(&target->srp_host->target_mutex);
+	spin_unlock(&target->srp_host->target_lock);
 
 	scsi_remove_host(target->scsi_host);
 	ib_destroy_cm_id(target->cm_id);
@@ -421,6 +450,11 @@
 	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
 		return;
 
+	if (req->fmr) {
+		ib_fmr_pool_unmap(req->fmr);
+		req->fmr = NULL;
+	}
+
 	/*
 	 * This handling of non-SG commands can be killed when the
 	 * SCSI midlayer no longer generates non-SG commands.
@@ -433,18 +467,30 @@
 		scat  = &req->fake_sg;
 	}
 
-	dma_unmap_sg(target->srp_host->dev->dma_device, scat, nents,
+	dma_unmap_sg(target->srp_host->dev->dev->dma_device, scat, nents,
 		     scmnd->sc_data_direction);
 }
 
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
+{
+	srp_unmap_data(req->scmnd, target, req);
+	list_move_tail(&req->list, &target->free_reqs);
+}
+
+static void srp_reset_req(struct srp_target_port *target, struct srp_request *req)
+{
+	req->scmnd->result = DID_RESET << 16;
+	req->scmnd->scsi_done(req->scmnd);
+	srp_remove_req(target, req);
+}
+
 static int srp_reconnect_target(struct srp_target_port *target)
 {
 	struct ib_cm_id *new_cm_id;
 	struct ib_qp_attr qp_attr;
-	struct srp_request *req;
+	struct srp_request *req, *tmp;
 	struct ib_wc wc;
 	int ret;
-	int i;
 
 	spin_lock_irq(target->scsi_host->host_lock);
 	if (target->state != SRP_TARGET_LIVE) {
@@ -459,7 +505,7 @@
 	 * Now get a new local CM ID so that we avoid confusing the
 	 * target in case things are really fouled up.
 	 */
-	new_cm_id = ib_create_cm_id(target->srp_host->dev,
+	new_cm_id = ib_create_cm_id(target->srp_host->dev->dev,
 				    srp_cm_handler, target);
 	if (IS_ERR(new_cm_id)) {
 		ret = PTR_ERR(new_cm_id);
@@ -480,19 +526,12 @@
 	while (ib_poll_cq(target->cq, 1, &wc) > 0)
 		; /* nothing */
 
-	list_for_each_entry(req, &target->req_queue, list) {
-		req->scmnd->result = DID_RESET << 16;
-		req->scmnd->scsi_done(req->scmnd);
-		srp_unmap_data(req->scmnd, target, req);
-	}
+	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
+		srp_reset_req(target, req);
 
 	target->rx_head	 = 0;
 	target->tx_head	 = 0;
 	target->tx_tail  = 0;
-	INIT_LIST_HEAD(&target->free_reqs);
-	INIT_LIST_HEAD(&target->req_queue);
-	for (i = 0; i < SRP_SQ_SIZE; ++i)
-		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
 
 	ret = srp_connect_target(target);
 	if (ret)
@@ -528,14 +567,79 @@
 	return ret;
 }
 
+static int srp_map_fmr(struct srp_device *dev, struct scatterlist *scat,
+		       int sg_cnt, struct srp_request *req,
+		       struct srp_direct_buf *buf)
+{
+	u64 io_addr = 0;
+	u64 *dma_pages;
+	u32 len;
+	int page_cnt;
+	int i, j;
+	int ret;
+
+	if (!dev->fmr_pool)
+		return -ENODEV;
+
+	len = page_cnt = 0;
+	for (i = 0; i < sg_cnt; ++i) {
+		if (sg_dma_address(&scat[i]) & ~dev->fmr_page_mask) {
+			if (i > 0)
+				return -EINVAL;
+			else
+				++page_cnt;
+		}
+		if ((sg_dma_address(&scat[i]) + sg_dma_len(&scat[i])) &
+		    ~dev->fmr_page_mask) {
+			if (i < sg_cnt - 1)
+				return -EINVAL;
+			else
+				++page_cnt;
+		}
+
+		len += sg_dma_len(&scat[i]);
+	}
+
+	page_cnt += len >> dev->fmr_page_shift;
+	if (page_cnt > SRP_FMR_SIZE)
+		return -ENOMEM;
+
+	dma_pages = kmalloc(sizeof (u64) * page_cnt, GFP_ATOMIC);
+	if (!dma_pages)
+		return -ENOMEM;
+
+	page_cnt = 0;
+	for (i = 0; i < sg_cnt; ++i)
+		for (j = 0; j < sg_dma_len(&scat[i]); j += dev->fmr_page_size)
+			dma_pages[page_cnt++] =
+				(sg_dma_address(&scat[i]) & dev->fmr_page_mask) + j;
+
+	req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool,
+					dma_pages, page_cnt, &io_addr);
+	if (IS_ERR(req->fmr)) {
+		ret = PTR_ERR(req->fmr);
+		goto out;
+	}
+
+	buf->va  = cpu_to_be64(sg_dma_address(&scat[0]) & ~dev->fmr_page_mask);
+	buf->key = cpu_to_be32(req->fmr->fmr->rkey);
+	buf->len = cpu_to_be32(len);
+
+	ret = 0;
+
+out:
+	kfree(dma_pages);
+
+	return ret;
+}
+
 static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
 			struct srp_request *req)
 {
 	struct scatterlist *scat;
 	struct srp_cmd *cmd = req->cmd->buf;
 	int len, nents, count;
-	int i;
-	u8 fmt;
+	u8 fmt = SRP_DATA_DESC_DIRECT;
 
 	if (!scmnd->request_buffer || scmnd->sc_data_direction == DMA_NONE)
 		return sizeof (struct srp_cmd);
@@ -560,53 +664,63 @@
 		sg_init_one(scat, scmnd->request_buffer, scmnd->request_bufflen);
 	}
 
-	count = dma_map_sg(target->srp_host->dev->dma_device, scat, nents,
-			   scmnd->sc_data_direction);
+	count = dma_map_sg(target->srp_host->dev->dev->dma_device,
+			   scat, nents, scmnd->sc_data_direction);
+
+	fmt = SRP_DATA_DESC_DIRECT;
+	len = sizeof (struct srp_cmd) +	sizeof (struct srp_direct_buf);
 
 	if (count == 1) {
+		/*
+		 * The midlayer only generated a single gather/scatter
+		 * entry, or DMA mapping coalesced everything to a
+		 * single entry.  So a direct descriptor along with
+		 * the DMA MR suffices.
+		 */
 		struct srp_direct_buf *buf = (void *) cmd->add_data;
 
-		fmt = SRP_DATA_DESC_DIRECT;
-
 		buf->va  = cpu_to_be64(sg_dma_address(scat));
-		buf->key = cpu_to_be32(target->srp_host->mr->rkey);
+		buf->key = cpu_to_be32(target->srp_host->dev->mr->rkey);
 		buf->len = cpu_to_be32(sg_dma_len(scat));
-
-		len = sizeof (struct srp_cmd) +
-			sizeof (struct srp_direct_buf);
-	} else {
+	} else if (srp_map_fmr(target->srp_host->dev, scat, count, req,
+			       (void *) cmd->add_data)) {
+		/*
+		 * FMR mapping failed, and the scatterlist has more
+		 * than one entry.  Generate an indirect memory
+		 * descriptor.
+		 */
 		struct srp_indirect_buf *buf = (void *) cmd->add_data;
 		u32 datalen = 0;
+		int i;
 
 		fmt = SRP_DATA_DESC_INDIRECT;
+		len = sizeof (struct srp_cmd) +
+			sizeof (struct srp_indirect_buf) +
+			count * sizeof (struct srp_direct_buf);
+
+		for (i = 0; i < count; ++i) {
+			buf->desc_list[i].va  =
+				cpu_to_be64(sg_dma_address(&scat[i]));
+			buf->desc_list[i].key =
+				cpu_to_be32(target->srp_host->dev->mr->rkey);
+			buf->desc_list[i].len =
+				cpu_to_be32(sg_dma_len(&scat[i]));
+			datalen += sg_dma_len(&scat[i]);
+		}
 
 		if (scmnd->sc_data_direction == DMA_TO_DEVICE)
 			cmd->data_out_desc_cnt = count;
 		else
 			cmd->data_in_desc_cnt = count;
 
-		buf->table_desc.va  = cpu_to_be64(req->cmd->dma +
-						  sizeof *cmd +
-						  sizeof *buf);
+		buf->table_desc.va  =
+			cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf);
 		buf->table_desc.key =
-			cpu_to_be32(target->srp_host->mr->rkey);
+			cpu_to_be32(target->srp_host->dev->mr->rkey);
 		buf->table_desc.len =
 			cpu_to_be32(count * sizeof (struct srp_direct_buf));
 
-		for (i = 0; i < count; ++i) {
-			buf->desc_list[i].va  = cpu_to_be64(sg_dma_address(&scat[i]));
-			buf->desc_list[i].key =
-				cpu_to_be32(target->srp_host->mr->rkey);
-			buf->desc_list[i].len = cpu_to_be32(sg_dma_len(&scat[i]));
-
-			datalen += sg_dma_len(&scat[i]);
-		}
-
 		buf->len = cpu_to_be32(datalen);
-
-		len = sizeof (struct srp_cmd) +
-			sizeof (struct srp_indirect_buf) +
-			count * sizeof (struct srp_direct_buf);
 	}
 
 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
@@ -617,12 +731,6 @@
 	return len;
 }
 
-static void srp_remove_req(struct srp_target_port *target, struct srp_request *req)
-{
-	srp_unmap_data(req->scmnd, target, req);
-	list_move_tail(&req->list, &target->free_reqs);
-}
-
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 {
 	struct srp_request *req;
@@ -689,7 +797,7 @@
 
 	iu = target->rx_ring[wc->wr_id & ~SRP_OP_RECV];
 
-	dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
+	dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma,
 				target->max_ti_iu_len, DMA_FROM_DEVICE);
 
 	opcode = *(u8 *) iu->buf;
@@ -726,7 +834,7 @@
 		break;
 	}
 
-	dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma,
+	dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma,
 				   target->max_ti_iu_len, DMA_FROM_DEVICE);
 }
 
@@ -770,7 +878,7 @@
 
 	list.addr   = iu->dma;
 	list.length = iu->size;
-	list.lkey   = target->srp_host->mr->lkey;
+	list.lkey   = target->srp_host->dev->mr->lkey;
 
 	wr.next     = NULL;
 	wr.sg_list  = &list;
@@ -805,12 +913,8 @@
 	if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
 		return NULL;
 
-	if (unlikely(target->req_lim < 1)) {
-		if (printk_ratelimit())
-			printk(KERN_DEBUG PFX "Target has req_lim %d\n",
-			       target->req_lim);
-		return NULL;
-	}
+	if (unlikely(target->req_lim < 1))
+		++target->zero_req_lim;
 
 	return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
 }
@@ -828,7 +932,7 @@
 
 	list.addr   = iu->dma;
 	list.length = len;
-	list.lkey   = target->srp_host->mr->lkey;
+	list.lkey   = target->srp_host->dev->mr->lkey;
 
 	wr.next       = NULL;
 	wr.wr_id      = target->tx_head & SRP_SQ_SIZE;
@@ -870,8 +974,8 @@
 	if (!iu)
 		goto err;
 
-	dma_sync_single_for_cpu(target->srp_host->dev->dma_device, iu->dma,
-				SRP_MAX_IU_LEN, DMA_TO_DEVICE);
+	dma_sync_single_for_cpu(target->srp_host->dev->dev->dma_device, iu->dma,
+				srp_max_iu_len, DMA_TO_DEVICE);
 
 	req = list_entry(target->free_reqs.next, struct srp_request, list);
 
@@ -903,8 +1007,8 @@
 		goto err_unmap;
 	}
 
-	dma_sync_single_for_device(target->srp_host->dev->dma_device, iu->dma,
-				   SRP_MAX_IU_LEN, DMA_TO_DEVICE);
+	dma_sync_single_for_device(target->srp_host->dev->dev->dma_device, iu->dma,
+				   srp_max_iu_len, DMA_TO_DEVICE);
 
 	if (__srp_post_send(target, iu, len)) {
 		printk(KERN_ERR PFX "Send failed\n");
@@ -936,7 +1040,7 @@
 
 	for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
 		target->tx_ring[i] = srp_alloc_iu(target->srp_host,
-						  SRP_MAX_IU_LEN,
+						  srp_max_iu_len,
 						  GFP_KERNEL, DMA_TO_DEVICE);
 		if (!target->tx_ring[i])
 			goto err;
@@ -1107,11 +1211,10 @@
 		srp_cm_rej_handler(cm_id, event, target);
 		break;
 
-	case IB_CM_MRA_RECEIVED:
-		printk(KERN_ERR PFX "MRA received\n");
-		break;
-
-	case IB_CM_DREP_RECEIVED:
+	case IB_CM_DREQ_RECEIVED:
+		printk(KERN_WARNING PFX "DREQ received - connection closed\n");
+		if (ib_send_cm_drep(cm_id, NULL, 0))
+			printk(KERN_ERR PFX "Sending CM DREP failed\n");
 		break;
 
 	case IB_CM_TIMEWAIT_EXIT:
@@ -1121,6 +1224,11 @@
 		target->status = 0;
 		break;
 
+	case IB_CM_MRA_RECEIVED:
+	case IB_CM_DREQ_ERROR:
+	case IB_CM_DREP_RECEIVED:
+		break;
+
 	default:
 		printk(KERN_WARNING PFX "Unhandled CM event %d\n", event->event);
 		break;
@@ -1239,11 +1347,8 @@
 	spin_lock_irq(target->scsi_host->host_lock);
 
 	list_for_each_entry_safe(req, tmp, &target->req_queue, list)
-		if (req->scmnd->device == scmnd->device) {
-			req->scmnd->result = DID_RESET << 16;
-			req->scmnd->scsi_done(req->scmnd);
-			srp_remove_req(target, req);
-		}
+		if (req->scmnd->device == scmnd->device)
+			srp_reset_req(target, req);
 
 	spin_unlock_irq(target->scsi_host->host_lock);
 
@@ -1329,11 +1434,23 @@
 		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[7]));
 }
 
+static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf)
+{
+	struct srp_target_port *target = host_to_target(class_to_shost(cdev));
+
+	if (target->state == SRP_TARGET_DEAD ||
+	    target->state == SRP_TARGET_REMOVED)
+		return -ENODEV;
+
+	return sprintf(buf, "%d\n", target->zero_req_lim);
+}
+
 static CLASS_DEVICE_ATTR(id_ext,	S_IRUGO, show_id_ext,		NULL);
 static CLASS_DEVICE_ATTR(ioc_guid,	S_IRUGO, show_ioc_guid,		NULL);
 static CLASS_DEVICE_ATTR(service_id,	S_IRUGO, show_service_id,	NULL);
 static CLASS_DEVICE_ATTR(pkey,		S_IRUGO, show_pkey,		NULL);
 static CLASS_DEVICE_ATTR(dgid,		S_IRUGO, show_dgid,		NULL);
+static CLASS_DEVICE_ATTR(zero_req_lim,	S_IRUGO, show_zero_req_lim,	NULL);
 
 static struct class_device_attribute *srp_host_attrs[] = {
 	&class_device_attr_id_ext,
@@ -1341,6 +1458,7 @@
 	&class_device_attr_service_id,
 	&class_device_attr_pkey,
 	&class_device_attr_dgid,
+	&class_device_attr_zero_req_lim,
 	NULL
 };
 
@@ -1354,7 +1472,6 @@
 	.eh_host_reset_handler		= srp_reset_host,
 	.can_queue			= SRP_SQ_SIZE,
 	.this_id			= -1,
-	.sg_tablesize			= SRP_MAX_INDIRECT,
 	.cmd_per_lun			= SRP_SQ_SIZE,
 	.use_clustering			= ENABLE_CLUSTERING,
 	.shost_attrs			= srp_host_attrs
@@ -1365,18 +1482,17 @@
 	sprintf(target->target_name, "SRP.T10:%016llX",
 		 (unsigned long long) be64_to_cpu(target->id_ext));
 
-	if (scsi_add_host(target->scsi_host, host->dev->dma_device))
+	if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))
 		return -ENODEV;
 
-	mutex_lock(&host->target_mutex);
+	spin_lock(&host->target_lock);
 	list_add_tail(&target->list, &host->target_list);
-	mutex_unlock(&host->target_mutex);
+	spin_unlock(&host->target_lock);
 
 	target->state = SRP_TARGET_LIVE;
 
-	/* XXX: are we supposed to have a definition of SCAN_WILD_CARD ?? */
 	scsi_scan_target(&target->scsi_host->shost_gendev,
-			 0, target->scsi_id, ~0, 0);
+			 0, target->scsi_id, SCAN_WILD_CARD, 0);
 
 	return 0;
 }
@@ -1410,6 +1526,8 @@
 	SRP_OPT_PKEY		= 1 << 3,
 	SRP_OPT_SERVICE_ID	= 1 << 4,
 	SRP_OPT_MAX_SECT	= 1 << 5,
+	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
+	SRP_OPT_IO_CLASS	= 1 << 7,
 	SRP_OPT_ALL		= (SRP_OPT_ID_EXT	|
 				   SRP_OPT_IOC_GUID	|
 				   SRP_OPT_DGID		|
@@ -1418,13 +1536,15 @@
 };
 
 static match_table_t srp_opt_tokens = {
-	{ SRP_OPT_ID_EXT,	"id_ext=%s" 	},
-	{ SRP_OPT_IOC_GUID,	"ioc_guid=%s" 	},
-	{ SRP_OPT_DGID,		"dgid=%s" 	},
-	{ SRP_OPT_PKEY,		"pkey=%x" 	},
-	{ SRP_OPT_SERVICE_ID,	"service_id=%s" },
-	{ SRP_OPT_MAX_SECT,     "max_sect=%d" 	},
-	{ SRP_OPT_ERR,		NULL 		}
+	{ SRP_OPT_ID_EXT,		"id_ext=%s" 		},
+	{ SRP_OPT_IOC_GUID,		"ioc_guid=%s" 		},
+	{ SRP_OPT_DGID,			"dgid=%s" 		},
+	{ SRP_OPT_PKEY,			"pkey=%x" 		},
+	{ SRP_OPT_SERVICE_ID,		"service_id=%s"		},
+	{ SRP_OPT_MAX_SECT,		"max_sect=%d" 		},
+	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
+	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
+	{ SRP_OPT_ERR,			NULL 			}
 };
 
 static int srp_parse_options(const char *buf, struct srp_target_port *target)
@@ -1500,6 +1620,29 @@
 			target->scsi_host->max_sectors = token;
 			break;
 
+		case SRP_OPT_MAX_CMD_PER_LUN:
+			if (match_int(args, &token)) {
+				printk(KERN_WARNING PFX "bad max cmd_per_lun parameter '%s'\n", p);
+				goto out;
+			}
+			target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE);
+			break;
+
+		case SRP_OPT_IO_CLASS:
+			if (match_hex(args, &token)) {
+				printk(KERN_WARNING PFX "bad  IO class parameter '%s' \n", p);
+				goto out;
+			}
+			if (token != SRP_REV10_IB_IO_CLASS &&
+			    token != SRP_REV16A_IB_IO_CLASS) {
+				printk(KERN_WARNING PFX "unknown IO class parameter value"
+				       " %x specified (use %x or %x).\n",
+				       token, SRP_REV10_IB_IO_CLASS, SRP_REV16A_IB_IO_CLASS);
+				goto out;
+			}
+			target->io_class = token;
+			break;
+
 		default:
 			printk(KERN_WARNING PFX "unknown parameter or missing value "
 			       "'%s' in target creation request\n", p);
@@ -1542,6 +1685,7 @@
 	target = host_to_target(target_host);
 	memset(target, 0, sizeof *target);
 
+	target->io_class   = SRP_REV16A_IB_IO_CLASS;
 	target->scsi_host  = target_host;
 	target->srp_host   = host;
 
@@ -1558,7 +1702,7 @@
 	if (ret)
 		goto err;
 
-	ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid);
+	ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid);
 
 	printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
 	       "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
@@ -1579,7 +1723,7 @@
 	if (ret)
 		goto err;
 
-	target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target);
+	target->cm_id = ib_create_cm_id(host->dev->dev, srp_cm_handler, target);
 	if (IS_ERR(target->cm_id)) {
 		ret = PTR_ERR(target->cm_id);
 		goto err_free;
@@ -1619,7 +1763,7 @@
 	struct srp_host *host =
 		container_of(class_dev, struct srp_host, class_dev);
 
-	return sprintf(buf, "%s\n", host->dev->name);
+	return sprintf(buf, "%s\n", host->dev->dev->name);
 }
 
 static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
@@ -1634,7 +1778,7 @@
 
 static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
 
-static struct srp_host *srp_add_port(struct ib_device *device, u8 port)
+static struct srp_host *srp_add_port(struct srp_device *device, u8 port)
 {
 	struct srp_host *host;
 
@@ -1643,32 +1787,21 @@
 		return NULL;
 
 	INIT_LIST_HEAD(&host->target_list);
-	mutex_init(&host->target_mutex);
+	spin_lock_init(&host->target_lock);
 	init_completion(&host->released);
 	host->dev  = device;
 	host->port = port;
 
 	host->initiator_port_id[7] = port;
-	memcpy(host->initiator_port_id + 8, &device->node_guid, 8);
-
-	host->pd   = ib_alloc_pd(device);
-	if (IS_ERR(host->pd))
-		goto err_free;
-
-	host->mr   = ib_get_dma_mr(host->pd,
-				   IB_ACCESS_LOCAL_WRITE |
-				   IB_ACCESS_REMOTE_READ |
-				   IB_ACCESS_REMOTE_WRITE);
-	if (IS_ERR(host->mr))
-		goto err_pd;
+	memcpy(host->initiator_port_id + 8, &device->dev->node_guid, 8);
 
 	host->class_dev.class = &srp_class;
-	host->class_dev.dev   = device->dma_device;
+	host->class_dev.dev   = device->dev->dma_device;
 	snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d",
-		 device->name, port);
+		 device->dev->name, port);
 
 	if (class_device_register(&host->class_dev))
-		goto err_mr;
+		goto free_host;
 	if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))
 		goto err_class;
 	if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))
@@ -1681,13 +1814,7 @@
 err_class:
 	class_device_unregister(&host->class_dev);
 
-err_mr:
-	ib_dereg_mr(host->mr);
-
-err_pd:
-	ib_dealloc_pd(host->pd);
-
-err_free:
+free_host:
 	kfree(host);
 
 	return NULL;
@@ -1695,15 +1822,62 @@
 
 static void srp_add_one(struct ib_device *device)
 {
-	struct list_head *dev_list;
+	struct srp_device *srp_dev;
+	struct ib_device_attr *dev_attr;
+	struct ib_fmr_pool_param fmr_param;
 	struct srp_host *host;
 	int s, e, p;
 
-	dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
-	if (!dev_list)
+	dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
+	if (!dev_attr)
 		return;
 
-	INIT_LIST_HEAD(dev_list);
+	if (ib_query_device(device, dev_attr)) {
+		printk(KERN_WARNING PFX "Query device failed for %s\n",
+		       device->name);
+		goto free_attr;
+	}
+
+	srp_dev = kmalloc(sizeof *srp_dev, GFP_KERNEL);
+	if (!srp_dev)
+		goto free_attr;
+
+	/*
+	 * Use the smallest page size supported by the HCA, down to a
+	 * minimum of 512 bytes (which is the smallest sector that a
+	 * SCSI command will ever carry).
+	 */
+	srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1);
+	srp_dev->fmr_page_size  = 1 << srp_dev->fmr_page_shift;
+	srp_dev->fmr_page_mask  = ~((unsigned long) srp_dev->fmr_page_size - 1);
+
+	INIT_LIST_HEAD(&srp_dev->dev_list);
+
+	srp_dev->dev = device;
+	srp_dev->pd  = ib_alloc_pd(device);
+	if (IS_ERR(srp_dev->pd))
+		goto free_dev;
+
+	srp_dev->mr = ib_get_dma_mr(srp_dev->pd,
+				    IB_ACCESS_LOCAL_WRITE |
+				    IB_ACCESS_REMOTE_READ |
+				    IB_ACCESS_REMOTE_WRITE);
+	if (IS_ERR(srp_dev->mr))
+		goto err_pd;
+
+	memset(&fmr_param, 0, sizeof fmr_param);
+	fmr_param.pool_size	    = SRP_FMR_POOL_SIZE;
+	fmr_param.dirty_watermark   = SRP_FMR_DIRTY_SIZE;
+	fmr_param.cache		    = 1;
+	fmr_param.max_pages_per_fmr = SRP_FMR_SIZE;
+	fmr_param.page_shift	    = srp_dev->fmr_page_shift;
+	fmr_param.access	    = (IB_ACCESS_LOCAL_WRITE |
+				       IB_ACCESS_REMOTE_WRITE |
+				       IB_ACCESS_REMOTE_READ);
+
+	srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param);
+	if (IS_ERR(srp_dev->fmr_pool))
+		srp_dev->fmr_pool = NULL;
 
 	if (device->node_type == IB_NODE_SWITCH) {
 		s = 0;
@@ -1714,25 +1888,35 @@
 	}
 
 	for (p = s; p <= e; ++p) {
-		host = srp_add_port(device, p);
+		host = srp_add_port(srp_dev, p);
 		if (host)
-			list_add_tail(&host->list, dev_list);
+			list_add_tail(&host->list, &srp_dev->dev_list);
 	}
 
-	ib_set_client_data(device, &srp_client, dev_list);
+	ib_set_client_data(device, &srp_client, srp_dev);
+
+	goto free_attr;
+
+err_pd:
+	ib_dealloc_pd(srp_dev->pd);
+
+free_dev:
+	kfree(srp_dev);
+
+free_attr:
+	kfree(dev_attr);
 }
 
 static void srp_remove_one(struct ib_device *device)
 {
-	struct list_head *dev_list;
+	struct srp_device *srp_dev;
 	struct srp_host *host, *tmp_host;
 	LIST_HEAD(target_list);
 	struct srp_target_port *target, *tmp_target;
-	unsigned long flags;
 
-	dev_list = ib_get_client_data(device, &srp_client);
+	srp_dev = ib_get_client_data(device, &srp_client);
 
-	list_for_each_entry_safe(host, tmp_host, dev_list, list) {
+	list_for_each_entry_safe(host, tmp_host, &srp_dev->dev_list, list) {
 		class_device_unregister(&host->class_dev);
 		/*
 		 * Wait for the sysfs entry to go away, so that no new
@@ -1744,15 +1928,13 @@
 		 * Mark all target ports as removed, so we stop queueing
 		 * commands and don't try to reconnect.
 		 */
-		mutex_lock(&host->target_mutex);
-		list_for_each_entry_safe(target, tmp_target,
-					 &host->target_list, list) {
-			spin_lock_irqsave(target->scsi_host->host_lock, flags);
-			if (target->state != SRP_TARGET_REMOVED)
-				target->state = SRP_TARGET_REMOVED;
-			spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+		spin_lock(&host->target_lock);
+		list_for_each_entry(target, &host->target_list, list) {
+			spin_lock_irq(target->scsi_host->host_lock);
+			target->state = SRP_TARGET_REMOVED;
+			spin_unlock_irq(target->scsi_host->host_lock);
 		}
-		mutex_unlock(&host->target_mutex);
+		spin_unlock(&host->target_lock);
 
 		/*
 		 * Wait for any reconnection tasks that may have
@@ -1770,18 +1952,26 @@
 			scsi_host_put(target->scsi_host);
 		}
 
-		ib_dereg_mr(host->mr);
-		ib_dealloc_pd(host->pd);
 		kfree(host);
 	}
 
-	kfree(dev_list);
+	if (srp_dev->fmr_pool)
+		ib_destroy_fmr_pool(srp_dev->fmr_pool);
+	ib_dereg_mr(srp_dev->mr);
+	ib_dealloc_pd(srp_dev->pd);
+
+	kfree(srp_dev);
 }
 
 static int __init srp_init_module(void)
 {
 	int ret;
 
+	srp_template.sg_tablesize = srp_sg_tablesize;
+	srp_max_iu_len = (sizeof (struct srp_cmd) +
+			  sizeof (struct srp_indirect_buf) +
+			  srp_sg_tablesize * 16);
+
 	ret = class_register(&srp_class);
 	if (ret) {
 		printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
index c5cd43a..5b581fb 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.h
+++ b/drivers/infiniband/ulp/srp/ib_srp.h
@@ -46,6 +46,7 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/ib_sa.h>
 #include <rdma/ib_cm.h>
+#include <rdma/ib_fmr_pool.h>
 
 enum {
 	SRP_PATH_REC_TIMEOUT_MS	= 1000,
@@ -55,20 +56,21 @@
 	SRP_DLID_REDIRECT	= 2,
 
 	SRP_MAX_LUN		= 512,
-	SRP_MAX_IU_LEN		= 256,
+	SRP_DEF_SG_TABLESIZE	= 12,
 
 	SRP_RQ_SHIFT    	= 6,
 	SRP_RQ_SIZE		= 1 << SRP_RQ_SHIFT,
 	SRP_SQ_SIZE		= SRP_RQ_SIZE - 1,
 	SRP_CQ_SIZE		= SRP_SQ_SIZE + SRP_RQ_SIZE,
 
-	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1)
+	SRP_TAG_TSK_MGMT	= 1 << (SRP_RQ_SHIFT + 1),
+
+	SRP_FMR_SIZE		= 256,
+	SRP_FMR_POOL_SIZE	= 1024,
+	SRP_FMR_DIRTY_SIZE	= SRP_FMR_POOL_SIZE / 4
 };
 
 #define SRP_OP_RECV		(1 << 31)
-#define SRP_MAX_INDIRECT	((SRP_MAX_IU_LEN -			\
-				  sizeof (struct srp_cmd) -		\
-				  sizeof (struct srp_indirect_buf)) / 16)
 
 enum srp_target_state {
 	SRP_TARGET_LIVE,
@@ -77,15 +79,24 @@
 	SRP_TARGET_REMOVED
 };
 
-struct srp_host {
-	u8			initiator_port_id[16];
+struct srp_device {
+	struct list_head	dev_list;
 	struct ib_device       *dev;
-	u8                      port;
 	struct ib_pd	       *pd;
 	struct ib_mr	       *mr;
+	struct ib_fmr_pool     *fmr_pool;
+	int			fmr_page_shift;
+	int			fmr_page_size;
+	unsigned long		fmr_page_mask;
+};
+
+struct srp_host {
+	u8			initiator_port_id[16];
+	struct srp_device      *dev;
+	u8			port;
 	struct class_device	class_dev;
 	struct list_head	target_list;
-	struct mutex            target_mutex;
+	spinlock_t		target_lock;
 	struct completion	released;
 	struct list_head	list;
 };
@@ -95,6 +106,7 @@
 	struct scsi_cmnd       *scmnd;
 	struct srp_iu	       *cmd;
 	struct srp_iu	       *tsk_mgmt;
+	struct ib_pool_fmr     *fmr;
 	/*
 	 * Fake scatterlist used when scmnd->use_sg==0.  Can be killed
 	 * when the SCSI midlayer no longer generates non-SG commands.
@@ -110,6 +122,7 @@
 	__be64			id_ext;
 	__be64			ioc_guid;
 	__be64			service_id;
+	u16			io_class;
 	struct srp_host	       *srp_host;
 	struct Scsi_Host       *scsi_host;
 	char			target_name[32];
@@ -126,6 +139,8 @@
 	int			max_ti_iu_len;
 	s32			req_lim;
 
+	int			zero_req_lim;
+
 	unsigned		rx_head;
 	struct srp_iu	       *rx_ring[SRP_RQ_SIZE];
 
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index ba325f1..a29d5ce 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -78,14 +78,19 @@
 {
 	int retval;
 	struct evdev_list *list = file->private_data;
+
 	retval = fasync_helper(fd, file, on, &list->fasync);
+
 	return retval < 0 ? retval : 0;
 }
 
-static int evdev_flush(struct file * file)
+static int evdev_flush(struct file *file, fl_owner_t id)
 {
 	struct evdev_list *list = file->private_data;
-	if (!list->evdev->exist) return -ENODEV;
+
+	if (!list->evdev->exist)
+		return -ENODEV;
+
 	return input_flush_device(&list->evdev->handle, file);
 }
 
@@ -300,6 +305,7 @@
 static unsigned int evdev_poll(struct file *file, poll_table *wait)
 {
 	struct evdev_list *list = file->private_data;
+
 	poll_wait(file, &list->evdev->wait, wait);
 	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
 		(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3038c26..a90486f 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -28,20 +28,6 @@
 MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(input_allocate_device);
-EXPORT_SYMBOL(input_register_device);
-EXPORT_SYMBOL(input_unregister_device);
-EXPORT_SYMBOL(input_register_handler);
-EXPORT_SYMBOL(input_unregister_handler);
-EXPORT_SYMBOL(input_grab_device);
-EXPORT_SYMBOL(input_release_device);
-EXPORT_SYMBOL(input_open_device);
-EXPORT_SYMBOL(input_close_device);
-EXPORT_SYMBOL(input_accept_process);
-EXPORT_SYMBOL(input_flush_device);
-EXPORT_SYMBOL(input_event);
-EXPORT_SYMBOL_GPL(input_class);
-
 #define INPUT_DEVICES	256
 
 static LIST_HEAD(input_dev_list);
@@ -63,11 +49,13 @@
 		case EV_SYN:
 			switch (code) {
 				case SYN_CONFIG:
-					if (dev->event) dev->event(dev, type, code, value);
+					if (dev->event)
+						dev->event(dev, type, code, value);
 					break;
 
 				case SYN_REPORT:
-					if (dev->sync) return;
+					if (dev->sync)
+						return;
 					dev->sync = 1;
 					break;
 			}
@@ -136,7 +124,8 @@
 			if (code > MSC_MAX || !test_bit(code, dev->mscbit))
 				return;
 
-			if (dev->event) dev->event(dev, type, code, value);
+			if (dev->event)
+				dev->event(dev, type, code, value);
 
 			break;
 
@@ -146,7 +135,9 @@
 				return;
 
 			change_bit(code, dev->led);
-			if (dev->event) dev->event(dev, type, code, value);
+
+			if (dev->event)
+				dev->event(dev, type, code, value);
 
 			break;
 
@@ -158,21 +149,25 @@
 			if (!!test_bit(code, dev->snd) != !!value)
 				change_bit(code, dev->snd);
 
-			if (dev->event) dev->event(dev, type, code, value);
+			if (dev->event)
+				dev->event(dev, type, code, value);
 
 			break;
 
 		case EV_REP:
 
-			if (code > REP_MAX || value < 0 || dev->rep[code] == value) return;
+			if (code > REP_MAX || value < 0 || dev->rep[code] == value)
+				return;
 
 			dev->rep[code] = value;
-			if (dev->event) dev->event(dev, type, code, value);
+			if (dev->event)
+				dev->event(dev, type, code, value);
 
 			break;
 
 		case EV_FF:
-			if (dev->event) dev->event(dev, type, code, value);
+			if (dev->event)
+				dev->event(dev, type, code, value);
 			break;
 	}
 
@@ -186,6 +181,7 @@
 			if (handle->open)
 				handle->handler->event(handle, type, code, value);
 }
+EXPORT_SYMBOL(input_event);
 
 static void input_repeat_key(unsigned long data)
 {
@@ -208,6 +204,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(input_accept_process);
 
 int input_grab_device(struct input_handle *handle)
 {
@@ -217,12 +214,14 @@
 	handle->dev->grab = handle;
 	return 0;
 }
+EXPORT_SYMBOL(input_grab_device);
 
 void input_release_device(struct input_handle *handle)
 {
 	if (handle->dev->grab == handle)
 		handle->dev->grab = NULL;
 }
+EXPORT_SYMBOL(input_release_device);
 
 int input_open_device(struct input_handle *handle)
 {
@@ -245,6 +244,7 @@
 
 	return err;
 }
+EXPORT_SYMBOL(input_open_device);
 
 int input_flush_device(struct input_handle* handle, struct file* file)
 {
@@ -253,6 +253,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(input_flush_device);
 
 void input_close_device(struct input_handle *handle)
 {
@@ -268,6 +269,7 @@
 
 	mutex_unlock(&dev->mutex);
 }
+EXPORT_SYMBOL(input_close_device);
 
 static void input_link_handle(struct input_handle *handle)
 {
@@ -335,9 +337,11 @@
 static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
 {
 	int state = input_devices_state;
+
 	poll_wait(file, &input_devices_poll_wait, wait);
 	if (state != input_devices_state)
 		return POLLIN | POLLRDNORM;
+
 	return 0;
 }
 
@@ -629,7 +633,7 @@
 
 	len = input_print_modalias(buf, PAGE_SIZE, id, 1);
 
-	return max_t(int, len, PAGE_SIZE);
+	return min_t(int, len, PAGE_SIZE);
 }
 static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
 
@@ -862,6 +866,7 @@
 	.release		= input_dev_release,
 	.uevent			= input_dev_uevent,
 };
+EXPORT_SYMBOL_GPL(input_class);
 
 struct input_dev *input_allocate_device(void)
 {
@@ -872,12 +877,27 @@
 		dev->dynalloc = 1;
 		dev->cdev.class = &input_class;
 		class_device_initialize(&dev->cdev);
+		mutex_init(&dev->mutex);
 		INIT_LIST_HEAD(&dev->h_list);
 		INIT_LIST_HEAD(&dev->node);
 	}
 
 	return dev;
 }
+EXPORT_SYMBOL(input_allocate_device);
+
+void input_free_device(struct input_dev *dev)
+{
+	if (dev) {
+
+		mutex_lock(&dev->mutex);
+		dev->name = dev->phys = dev->uniq = NULL;
+		mutex_unlock(&dev->mutex);
+
+		input_put_device(dev);
+	}
+}
+EXPORT_SYMBOL(input_free_device);
 
 int input_register_device(struct input_dev *dev)
 {
@@ -895,7 +915,6 @@
 		return -EINVAL;
 	}
 
-	mutex_init(&dev->mutex);
 	set_bit(EV_SYN, dev->evbit);
 
 	/*
@@ -956,12 +975,14 @@
  fail1:	class_device_del(&dev->cdev);
 	return error;
 }
+EXPORT_SYMBOL(input_register_device);
 
 void input_unregister_device(struct input_dev *dev)
 {
-	struct list_head * node, * next;
+	struct list_head *node, *next;
 
-	if (!dev) return;
+	if (!dev)
+		return;
 
 	del_timer_sync(&dev->timer);
 
@@ -977,10 +998,16 @@
 	sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group);
 	sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group);
 	sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
+
+	mutex_lock(&dev->mutex);
+	dev->name = dev->phys = dev->uniq = NULL;
+	mutex_unlock(&dev->mutex);
+
 	class_device_unregister(&dev->cdev);
 
 	input_wakeup_procfs_readers();
 }
+EXPORT_SYMBOL(input_unregister_device);
 
 void input_register_handler(struct input_handler *handler)
 {
@@ -988,7 +1015,8 @@
 	struct input_handle *handle;
 	struct input_device_id *id;
 
-	if (!handler) return;
+	if (!handler)
+		return;
 
 	INIT_LIST_HEAD(&handler->h_list);
 
@@ -1005,10 +1033,11 @@
 
 	input_wakeup_procfs_readers();
 }
+EXPORT_SYMBOL(input_register_handler);
 
 void input_unregister_handler(struct input_handler *handler)
 {
-	struct list_head * node, * next;
+	struct list_head *node, *next;
 
 	list_for_each_safe(node, next, &handler->h_list) {
 		struct input_handle * handle = to_handle_h(node);
@@ -1024,6 +1053,7 @@
 
 	input_wakeup_procfs_readers();
 }
+EXPORT_SYMBOL(input_unregister_handler);
 
 static int input_open_file(struct inode *inode, struct file *file)
 {
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 949bdce..d671575 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -81,10 +81,7 @@
 			return 0;
 	}
 
-	if (value < -32767) return -32767;
-	if (value >  32767) return  32767;
-
-	return value;
+	return value < -32767 ? -32767 : (value > 32767 ? 32767 : value);
 }
 
 static void joydev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
@@ -96,7 +93,8 @@
 	switch (type) {
 
 		case EV_KEY:
-			if (code < BTN_MISC || value == 2) return;
+			if (code < BTN_MISC || value == 2)
+				return;
 			event.type = JS_EVENT_BUTTON;
 			event.number = joydev->keymap[code - BTN_MISC];
 			event.value = value;
@@ -106,7 +104,8 @@
 			event.type = JS_EVENT_AXIS;
 			event.number = joydev->absmap[code];
 			event.value = joydev_correct(value, joydev->corr + event.number);
-			if (event.value == joydev->abs[event.number]) return;
+			if (event.value == joydev->abs[event.number])
+				return;
 			joydev->abs[event.number] = event.value;
 			break;
 
@@ -134,7 +133,9 @@
 {
 	int retval;
 	struct joydev_list *list = file->private_data;
+
 	retval = fasync_helper(fd, file, on, &list->fasync);
+
 	return retval < 0 ? retval : 0;
 }
 
@@ -222,12 +223,12 @@
 		return sizeof(struct JS_DATA_TYPE);
 	}
 
-	if (list->startup == joydev->nabs + joydev->nkey
-		&& list->head == list->tail && (file->f_flags & O_NONBLOCK))
-			return -EAGAIN;
+	if (list->startup == joydev->nabs + joydev->nkey &&
+	    list->head == list->tail && (file->f_flags & O_NONBLOCK))
+		return -EAGAIN;
 
 	retval = wait_event_interruptible(list->joydev->wait,
-		 			  !list->joydev->exist ||
+					  !list->joydev->exist ||
 					  list->startup < joydev->nabs + joydev->nkey ||
 					  list->head != list->tail);
 
@@ -276,8 +277,9 @@
 static unsigned int joydev_poll(struct file *file, poll_table *wait)
 {
 	struct joydev_list *list = file->private_data;
+
 	poll_wait(file, &list->joydev->wait, wait);
-	return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? 
+	return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ?
 		(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
@@ -291,20 +293,26 @@
 		case JS_SET_CAL:
 			return copy_from_user(&joydev->glue.JS_CORR, argp,
 				sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
+
 		case JS_GET_CAL:
 			return copy_to_user(argp, &joydev->glue.JS_CORR,
 				sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0;
+
 		case JS_SET_TIMEOUT:
 			return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
+
 		case JS_GET_TIMEOUT:
 			return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp);
 
 		case JSIOCGVERSION:
 			return put_user(JS_VERSION, (__u32 __user *) argp);
+
 		case JSIOCGAXES:
 			return put_user(joydev->nabs, (__u8 __user *) argp);
+
 		case JSIOCGBUTTONS:
 			return put_user(joydev->nkey, (__u8 __user *) argp);
+
 		case JSIOCSCORR:
 			if (copy_from_user(joydev->corr, argp,
 				      sizeof(joydev->corr[0]) * joydev->nabs))
@@ -314,38 +322,49 @@
 			        joydev->abs[i] = joydev_correct(dev->abs[j], joydev->corr + i);
 			}
 			return 0;
+
 		case JSIOCGCORR:
 			return copy_to_user(argp, joydev->corr,
 						sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0;
+
 		case JSIOCSAXMAP:
 			if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
 				return -EFAULT;
 			for (i = 0; i < joydev->nabs; i++) {
-				if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
+				if (joydev->abspam[i] > ABS_MAX)
+					return -EINVAL;
 				joydev->absmap[joydev->abspam[i]] = i;
 			}
 			return 0;
+
 		case JSIOCGAXMAP:
 			return copy_to_user(argp, joydev->abspam,
 						sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
+
 		case JSIOCSBTNMAP:
 			if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
 				return -EFAULT;
 			for (i = 0; i < joydev->nkey; i++) {
-				if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
+				if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC)
+					return -EINVAL;
 				joydev->keymap[joydev->keypam[i] - BTN_MISC] = i;
 			}
 			return 0;
+
 		case JSIOCGBTNMAP:
 			return copy_to_user(argp, joydev->keypam,
 						sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
+
 		default:
 			if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
 				int len;
-				if (!dev->name) return 0;
+				if (!dev->name)
+					return 0;
 				len = strlen(dev->name) + 1;
-				if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
-				if (copy_to_user(argp, dev->name, len)) return -EFAULT;
+				if (len > _IOC_SIZE(cmd))
+					len = _IOC_SIZE(cmd);
+				if (copy_to_user(argp, dev->name, len))
+					return -EFAULT;
 				return len;
 			}
 	}
@@ -362,7 +381,9 @@
 	struct JS_DATA_SAVE_TYPE_32 ds32;
 	int err;
 
-	if (!joydev->exist) return -ENODEV;
+	if (!joydev->exist)
+		return -ENODEV;
+
 	switch(cmd) {
 	case JS_SET_TIMELIMIT:
 		err = get_user(tmp32, (s32 __user *) arg);
@@ -395,8 +416,7 @@
 		ds32.JS_SAVE       = joydev->glue.JS_SAVE;
 		ds32.JS_CORR       = joydev->glue.JS_CORR;
 
-		err = copy_to_user(argp, &ds32,
-					  sizeof(ds32)) ? -EFAULT : 0;
+		err = copy_to_user(argp, &ds32, sizeof(ds32)) ? -EFAULT : 0;
 		break;
 
 	default:
@@ -412,7 +432,8 @@
 	struct joydev *joydev = list->joydev;
 	void __user *argp = (void __user *)arg;
 
-	if (!joydev->exist) return -ENODEV;
+	if (!joydev->exist)
+		return -ENODEV;
 
 	switch(cmd) {
 		case JS_SET_TIMELIMIT:
@@ -546,8 +567,8 @@
 		.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT,
 		.evbit = { BIT(EV_KEY) },
 		.keybit = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
-	}, 	/* Avoid itouchpads, touchscreens and tablets */
-	{ }, 	/* Terminating entry */
+	},	/* Avoid itouchpads, touchscreens and tablets */
+	{ }	/* Terminating entry */
 };
 
 static struct input_device_id joydev_ids[] = {
@@ -566,7 +587,7 @@
 		.evbit = { BIT(EV_ABS) },
 		.absbit = { BIT(ABS_THROTTLE) },
 	},
-	{ }, 	/* Terminating entry */
+	{ }	/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(input, joydev_ids);
@@ -579,7 +600,7 @@
 	.minor =	JOYDEV_MINOR_BASE,
 	.name =		"joydev",
 	.id_table =	joydev_ids,
-	.blacklist = 	joydev_blacklist,
+	.blacklist =	joydev_blacklist,
 };
 
 static int __init joydev_init(void)
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
index 4612d13..b11a4bb 100644
--- a/drivers/input/joystick/a3d.c
+++ b/drivers/input/joystick/a3d.c
@@ -306,7 +306,7 @@
 	gameport_set_poll_handler(gameport, a3d_poll);
 	gameport_set_poll_interval(gameport, 20);
 
-	sprintf(a3d->phys, "%s/input0", gameport->phys);
+	snprintf(a3d->phys, sizeof(a3d->phys), "%s/input0", gameport->phys);
 
 	input_dev->name = a3d_names[a3d->mode];
 	input_dev->phys = a3d->phys;
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 3121961..01dc0b1 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -408,21 +408,23 @@
 
 static void analog_name(struct analog *analog)
 {
-	sprintf(analog->name, "Analog %d-axis %d-button",
-		hweight8(analog->mask & ANALOG_AXES_STD),
-		hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
-		hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
+	snprintf(analog->name, sizeof(analog->name), "Analog %d-axis %d-button",
+		 hweight8(analog->mask & ANALOG_AXES_STD),
+		 hweight8(analog->mask & ANALOG_BTNS_STD) + !!(analog->mask & ANALOG_BTNS_CHF) * 2 +
+		 hweight16(analog->mask & ANALOG_BTNS_GAMEPAD) + !!(analog->mask & ANALOG_HBTN_CHF) * 4);
 
 	if (analog->mask & ANALOG_HATS_ALL)
-		sprintf(analog->name, "%s %d-hat",
-			analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));
+		snprintf(analog->name, sizeof(analog->name), "%s %d-hat",
+			 analog->name, hweight16(analog->mask & ANALOG_HATS_ALL));
 
 	if (analog->mask & ANALOG_HAT_FCS)
-			strcat(analog->name, " FCS");
+		strlcat(analog->name, " FCS", sizeof(analog->name));
 	if (analog->mask & ANALOG_ANY_CHF)
-			strcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF");
+		strlcat(analog->name, (analog->mask & ANALOG_SAITEK) ? " Saitek" : " CHF",
+			sizeof(analog->name));
 
-	strcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick");
+	strlcat(analog->name, (analog->mask & ANALOG_GAMEPAD) ? " gamepad": " joystick",
+		sizeof(analog->name));
 }
 
 /*
@@ -435,7 +437,8 @@
 	int i, j, t, v, w, x, y, z;
 
 	analog_name(analog);
-	sprintf(analog->phys, "%s/input%d", port->gameport->phys, index);
+	snprintf(analog->phys, sizeof(analog->phys),
+		 "%s/input%d", port->gameport->phys, index);
 	analog->buttons = (analog->mask & ANALOG_GAMEPAD) ? analog_pad_btn : analog_joy_btn;
 
 	analog->dev = input_dev = input_allocate_device();
diff --git a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
index 1909f7e..d5e42eb 100644
--- a/drivers/input/joystick/cobra.c
+++ b/drivers/input/joystick/cobra.c
@@ -202,7 +202,8 @@
 			goto fail3;
 		}
 
-		sprintf(cobra->phys[i], "%s/input%d", gameport->phys, i);
+		snprintf(cobra->phys[i], sizeof(cobra->phys[i]),
+			 "%s/input%d", gameport->phys, i);
 
 		input_dev->name = "Creative Labs Blaster GamePad Cobra";
 		input_dev->phys = cobra->phys[i];
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index e618946..5080e15 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -584,7 +584,7 @@
 		goto err_out;
 	}
 
-	if (db9_mode[mode].bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
+	if (db9_mode->bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
 		printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
 		err = -EINVAL;
 		goto err_put_pp;
@@ -620,7 +620,8 @@
 			goto err_unreg_devs;
 		}
 
-		sprintf(db9->phys[i], "%s/input%d", db9->pd->port->name, i);
+		snprintf(db9->phys[i], sizeof(db9->phys[i]),
+			 "%s/input%d", db9->pd->port->name, i);
 
 		input_dev->name = db9_mode->name;
 		input_dev->phys = db9->phys[i];
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
index ecbdb6b..fe12aa3 100644
--- a/drivers/input/joystick/gamecon.c
+++ b/drivers/input/joystick/gamecon.c
@@ -761,7 +761,8 @@
 		if (!pads[i])
 			continue;
 
-		sprintf(gc->phys[i], "%s/input%d", gc->pd->port->name, i);
+		snprintf(gc->phys[i], sizeof(gc->phys[i]),
+			 "%s/input%d", gc->pd->port->name, i);
 		err = gc_setup_pad(gc, i, pads[i]);
 		if (err)
 			goto err_unreg_devs;
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
index 8a3ad45..e4a699f 100644
--- a/drivers/input/joystick/gf2k.c
+++ b/drivers/input/joystick/gf2k.c
@@ -298,7 +298,7 @@
 	gameport_set_poll_handler(gameport, gf2k_poll);
 	gameport_set_poll_interval(gameport, 20);
 
-	sprintf(gf2k->phys, "%s/input0", gameport->phys);
+	snprintf(gf2k->phys, sizeof(gf2k->phys), "%s/input0", gameport->phys);
 
 	gf2k->length = gf2k_lens[gf2k->id];
 
diff --git a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
index 20cb98a..17a90c4 100644
--- a/drivers/input/joystick/grip.c
+++ b/drivers/input/joystick/grip.c
@@ -354,7 +354,8 @@
 			goto fail3;
 		}
 
-		sprintf(grip->phys[i], "%s/input%d", gameport->phys, i);
+		snprintf(grip->phys[i], sizeof(grip->phys[i]),
+			 "%s/input%d", gameport->phys, i);
 
 		input_dev->name = grip_name[grip->mode[i]];
 		input_dev->phys = grip->phys[i];
diff --git a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
index 6e2c721..840ed9b 100644
--- a/drivers/input/joystick/guillemot.c
+++ b/drivers/input/joystick/guillemot.c
@@ -222,7 +222,7 @@
 	gameport_set_poll_handler(gameport, guillemot_poll);
 	gameport_set_poll_interval(gameport, 20);
 
-	sprintf(guillemot->phys, "%s/input0", gameport->phys);
+	snprintf(guillemot->phys, sizeof(guillemot->phys), "%s/input0", gameport->phys);
 	guillemot->type = guillemot_type + i;
 
 	input_dev->name = guillemot_type[i].name;
diff --git a/drivers/input/joystick/iforce/iforce-ff.c b/drivers/input/joystick/iforce/iforce-ff.c
index 2b8e845..50c9076 100644
--- a/drivers/input/joystick/iforce/iforce-ff.c
+++ b/drivers/input/joystick/iforce/iforce-ff.c
@@ -47,7 +47,7 @@
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
 			mutex_unlock(&iforce->mem_mutex);
-			return -ENOMEM;
+			return -ENOSPC;
 		}
 		mutex_unlock(&iforce->mem_mutex);
 	}
@@ -80,7 +80,7 @@
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
 			mutex_unlock(&iforce->mem_mutex);
-			return -ENOMEM;
+			return -ENOSPC;
 		}
 		mutex_unlock(&iforce->mem_mutex);
 	}
@@ -120,7 +120,7 @@
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
 			mutex_unlock(&iforce->mem_mutex);
-			return -ENOMEM;
+			return -ENOSPC;
 		}
 		mutex_unlock(&iforce->mem_mutex);
 	}
@@ -157,7 +157,7 @@
 			iforce->device_memory.start, iforce->device_memory.end, 2L,
 			NULL, NULL)) {
 			mutex_unlock(&iforce->mem_mutex);
-			return -ENOMEM;
+			return -ENOSPC;
 		}
 		mutex_unlock(&iforce->mem_mutex);
 	}
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index ab0a26b..6d99e3c 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -86,7 +86,7 @@
 
 static int iforce_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct iforce* iforce = (struct iforce*)(dev->private);
+	struct iforce* iforce = dev->private;
 	unsigned char data[3];
 
 	if (type != EV_FF)
@@ -138,7 +138,7 @@
  */
 static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect)
 {
-	struct iforce* iforce = (struct iforce*)(dev->private);
+	struct iforce* iforce = dev->private;
 	int id;
 	int ret;
 	int is_update;
@@ -218,7 +218,7 @@
  */
 static int iforce_erase_effect(struct input_dev *dev, int effect_id)
 {
-	struct iforce* iforce = (struct iforce*)(dev->private);
+	struct iforce* iforce = dev->private;
 	int err = 0;
 	struct iforce_core_effect* core_effect;
 
diff --git a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
index c4ed017..bbfeb9c 100644
--- a/drivers/input/joystick/interact.c
+++ b/drivers/input/joystick/interact.c
@@ -251,7 +251,7 @@
 	gameport_set_poll_handler(gameport, interact_poll);
 	gameport_set_poll_interval(gameport, 20);
 
-	sprintf(interact->phys, "%s/input0", gameport->phys);
+	snprintf(interact->phys, sizeof(interact->phys), "%s/input0", gameport->phys);
 
 	interact->type = i;
 	interact->length = interact_type[i].length;
diff --git a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
index ca3cc23..168b106 100644
--- a/drivers/input/joystick/magellan.c
+++ b/drivers/input/joystick/magellan.c
@@ -162,7 +162,7 @@
 		goto fail;
 
 	magellan->dev = input_dev;
-	sprintf(magellan->phys, "%s/input0", serio->phys);
+	snprintf(magellan->phys, sizeof(magellan->phys), "%s/input0", serio->phys);
 
 	input_dev->name = "LogiCad3D Magellan / SpaceMouse";
 	input_dev->phys = magellan->phys;
diff --git a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
index 95c0de7..e58b22c 100644
--- a/drivers/input/joystick/sidewinder.c
+++ b/drivers/input/joystick/sidewinder.c
@@ -541,7 +541,7 @@
  * Unfortunately I don't know how to do this for the other SW types.
  */
 
-static void sw_3dp_id(unsigned char *buf, char *comment)
+static void sw_3dp_id(unsigned char *buf, char *comment, size_t size)
 {
 	int i;
 	char pnp[8], rev[9];
@@ -554,7 +554,7 @@
 
 	pnp[7] = rev[8] = 0;
 
-	sprintf(comment, " [PnP %d.%02d id %s rev %s]",
+	snprintf(comment, size, " [PnP %d.%02d id %s rev %s]",
 		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |		/* Two 6-bit values */
 			sw_get_bits(buf, 16, 6, 1)) / 100,
 		(int) ((sw_get_bits(buf, 8, 6, 1) << 6) |
@@ -695,7 +695,7 @@
 						sw->type = SW_ID_FFP;
 						sprintf(comment, " [AC %s]", sw_get_bits(idbuf,38,1,3) ? "off" : "on");
 					} else
-					sw->type = SW_ID_PP;
+						sw->type = SW_ID_PP;
 					break;
 				case 66:
 					sw->bits = 3;
@@ -703,7 +703,8 @@
 					sw->length = 22;
 				case 64:
 					sw->type = SW_ID_3DP;
-					if (j == 160) sw_3dp_id(idbuf, comment);
+					if (j == 160)
+						sw_3dp_id(idbuf, comment, sizeof(comment));
 					break;
 			}
 		}
@@ -733,8 +734,10 @@
 	for (i = 0; i < sw->number; i++) {
 		int bits, code;
 
-		sprintf(sw->name, "Microsoft SideWinder %s", sw_name[sw->type]);
-		sprintf(sw->phys[i], "%s/input%d", gameport->phys, i);
+		snprintf(sw->name, sizeof(sw->name),
+			 "Microsoft SideWinder %s", sw_name[sw->type]);
+		snprintf(sw->phys[i], sizeof(sw->phys[i]),
+			 "%s/input%d", gameport->phys, i);
 
 		sw->dev[i] = input_dev = input_allocate_device();
 		if (!input_dev) {
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
index d6f8db8..75eb5ca 100644
--- a/drivers/input/joystick/spaceball.c
+++ b/drivers/input/joystick/spaceball.c
@@ -220,7 +220,7 @@
 		goto fail;
 
 	spaceball->dev = input_dev;
-	sprintf(spaceball->phys, "%s/input0", serio->phys);
+	snprintf(spaceball->phys, sizeof(spaceball->phys), "%s/input0", serio->phys);
 
 	input_dev->name = spaceball_names[id];
 	input_dev->phys = spaceball->phys;
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
index 7c123a0..3e2782e 100644
--- a/drivers/input/joystick/spaceorb.c
+++ b/drivers/input/joystick/spaceorb.c
@@ -177,7 +177,7 @@
 		goto fail;
 
 	spaceorb->dev = input_dev;
-	sprintf(spaceorb->phys, "%s/input0", serio->phys);
+	snprintf(spaceorb->phys, sizeof(spaceorb->phys), "%s/input0", serio->phys);
 
 	input_dev->name = "SpaceTec SpaceOrb 360 / Avenger";
 	input_dev->phys = spaceorb->phys;
diff --git a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
index 0a9ed1d..011ec48 100644
--- a/drivers/input/joystick/stinger.c
+++ b/drivers/input/joystick/stinger.c
@@ -148,7 +148,7 @@
 		goto fail;
 
 	stinger->dev = input_dev;
-	sprintf(stinger->phys, "%s/serio0", serio->phys);
+	snprintf(stinger->phys, sizeof(stinger->phys), "%s/serio0", serio->phys);
 
 	input_dev->name = "Gravis Stinger";
 	input_dev->phys = stinger->phys;
diff --git a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
index 7f8b009..076f237 100644
--- a/drivers/input/joystick/twidjoy.c
+++ b/drivers/input/joystick/twidjoy.c
@@ -199,7 +199,7 @@
 		goto fail;
 
 	twidjoy->dev = input_dev;
-	sprintf(twidjoy->phys, "%s/input0", serio->phys);
+	snprintf(twidjoy->phys, sizeof(twidjoy->phys), "%s/input0", serio->phys);
 
 	input_dev->name = "Handykey Twiddler";
 	input_dev->phys = twidjoy->phys;
diff --git a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
index 1849b17..f9c1a03 100644
--- a/drivers/input/joystick/warrior.c
+++ b/drivers/input/joystick/warrior.c
@@ -154,7 +154,7 @@
 		goto fail;
 
 	warrior->dev = input_dev;
-	sprintf(warrior->phys, "%s/input0", serio->phys);
+	snprintf(warrior->phys, sizeof(warrior->phys), "%s/input0", serio->phys);
 
 	input_dev->name = "Logitech WingMan Warrior";
 	input_dev->phys = warrior->phys;
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index 4c8fb1f..f1f9db9 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -36,6 +36,7 @@
 #include <linux/input.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/keyboard.h>
 
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
@@ -45,7 +46,7 @@
 MODULE_DESCRIPTION("Amiga keyboard driver");
 MODULE_LICENSE("GPL");
 
-static unsigned char amikbd_keycode[0x78] = {
+static unsigned char amikbd_keycode[0x78] __initdata = {
 	[0]	 = KEY_GRAVE,
 	[1]	 = KEY_1,
 	[2]	 = KEY_2,
@@ -170,12 +171,9 @@
 	scancode >>= 1;
 
 	if (scancode < 0x78) {		/* scancodes < 0x78 are keys */
-
-		scancode = amikbd_keycode[scancode];
-
 		input_regs(amikbd_dev, fp);
 
-		if (scancode == KEY_CAPSLOCK) {	/* CapsLock is a toggle switch key on Amiga */
+		if (scancode == 98) {	/* CapsLock is a toggle switch key on Amiga */
 			input_report_key(amikbd_dev, scancode, 1);
 			input_report_key(amikbd_dev, scancode, 0);
 		} else {
@@ -191,7 +189,7 @@
 
 static int __init amikbd_init(void)
 {
-	int i;
+	int i, j;
 
 	if (!AMIGAHW_PRESENT(AMI_KEYBOARD))
 		return -EIO;
@@ -214,14 +212,26 @@
 	amikbd_dev->id.version = 0x0100;
 
 	amikbd_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
-	amikbd_dev->keycode = amikbd_keycode;
-	amikbd_dev->keycodesize = sizeof(unsigned char);
-	amikbd_dev->keycodemax = ARRAY_SIZE(amikbd_keycode);
 
 	for (i = 0; i < 0x78; i++)
-		if (amikbd_keycode[i])
-			set_bit(amikbd_keycode[i], amikbd_dev->keybit);
+		set_bit(i, amikbd_dev->keybit);
 
+	for (i = 0; i < MAX_NR_KEYMAPS; i++) {
+		static u_short temp_map[NR_KEYS] __initdata;
+		if (!key_maps[i])
+			continue;
+		memset(temp_map, 0, sizeof(temp_map));
+		for (j = 0; j < 0x78; j++) {
+			if (!amikbd_keycode[j])
+				continue;
+			temp_map[j] = key_maps[i][amikbd_keycode[j]];
+		}
+		for (j = 0; j < NR_KEYS; j++) {
+			if (!temp_map[j])
+				temp_map[j] = 0xf200;
+		}
+		memcpy(key_maps[i], temp_map, sizeof(temp_map));
+	}
 	ciaa.cra &= ~0x41;	 /* serial data in, turn off TA */
 	request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", amikbd_interrupt);
 
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index fad04b6..ce1f10e 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -55,7 +55,7 @@
 module_param_named(softraw, atkbd_softraw, bool, 0);
 MODULE_PARM_DESC(softraw, "Use software generated rawmode");
 
-static int atkbd_scroll = 0;
+static int atkbd_scroll;
 module_param_named(scroll, atkbd_scroll, bool, 0);
 MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
 
@@ -150,8 +150,8 @@
 #define ATKBD_RET_EMUL0		0xe0
 #define ATKBD_RET_EMUL1		0xe1
 #define ATKBD_RET_RELEASE	0xf0
-#define ATKBD_RET_HANGUEL	0xf1
-#define ATKBD_RET_HANJA		0xf2
+#define ATKBD_RET_HANJA		0xf1
+#define ATKBD_RET_HANGEUL	0xf2
 #define ATKBD_RET_ERR		0xff
 
 #define ATKBD_KEY_UNKNOWN	  0
@@ -170,6 +170,13 @@
 #define ATKBD_LED_EVENT_BIT	0
 #define ATKBD_REP_EVENT_BIT	1
 
+#define ATKBD_XL_ERR		0x01
+#define ATKBD_XL_BAT		0x02
+#define ATKBD_XL_ACK		0x04
+#define ATKBD_XL_NAK		0x08
+#define ATKBD_XL_HANGEUL	0x10
+#define ATKBD_XL_HANJA		0x20
+
 static struct {
 	unsigned char keycode;
 	unsigned char set2;
@@ -211,8 +218,7 @@
 	unsigned char emul;
 	unsigned char resend;
 	unsigned char release;
-	unsigned char bat_xl;
-	unsigned char err_xl;
+	unsigned long xl_bit;
 	unsigned int last;
 	unsigned long time;
 
@@ -245,17 +251,65 @@
 ATKBD_DEFINE_ATTR(softrepeat);
 ATKBD_DEFINE_ATTR(softraw);
 
+static const unsigned int xl_table[] = {
+	ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK,
+	ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL,
+};
 
-static void atkbd_report_key(struct input_dev *dev, struct pt_regs *regs, int code, int value)
+/*
+ * Checks if we should mangle the scancode to extract 'release' bit
+ * in translated mode.
+ */
+static int atkbd_need_xlate(unsigned long xl_bit, unsigned char code)
 {
-	input_regs(dev, regs);
-	if (value == 3) {
-		input_report_key(dev, code, 1);
-		input_sync(dev);
-		input_report_key(dev, code, 0);
-	} else
-		input_event(dev, EV_KEY, code, value);
-	input_sync(dev);
+	int i;
+
+	if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1)
+		return 0;
+
+	for (i = 0; i < ARRAY_SIZE(xl_table); i++)
+		if (code == xl_table[i])
+			return test_bit(i, &xl_bit);
+
+	return 1;
+}
+
+/*
+ * Calculates new value of xl_bit so the driver can distinguish
+ * between make/break pair of scancodes for select keys and PS/2
+ * protocol responses.
+ */
+static void atkbd_calculate_xl_bit(struct atkbd *atkbd, unsigned char code)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(xl_table); i++) {
+		if (!((code ^ xl_table[i]) & 0x7f)) {
+			if (code & 0x80)
+				__clear_bit(i, &atkbd->xl_bit);
+			else
+				__set_bit(i, &atkbd->xl_bit);
+			break;
+		}
+	}
+}
+
+/*
+ * Encode the scancode, 0xe0 prefix, and high bit into a single integer,
+ * keeping kernel 2.4 compatibility for set 2
+ */
+static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code)
+{
+	if (atkbd->set == 3) {
+		if (atkbd->emul == 1)
+			code |= 0x100;
+        } else {
+		code = (code & 0x7f) | ((code & 0x80) << 1);
+		if (atkbd->emul == 1)
+			code |= 0x80;
+	}
+
+	return code;
 }
 
 /*
@@ -267,9 +321,11 @@
 			unsigned int flags, struct pt_regs *regs)
 {
 	struct atkbd *atkbd = serio_get_drvdata(serio);
+	struct input_dev *dev = atkbd->dev;
 	unsigned int code = data;
-	int scroll = 0, hscroll = 0, click = -1;
+	int scroll = 0, hscroll = 0, click = -1, add_release_event = 0;
 	int value;
+	unsigned char keycode;
 
 #ifdef ATKBD_DEBUG
 	printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
@@ -298,25 +354,17 @@
 	if (!atkbd->enabled)
 		goto out;
 
-	input_event(atkbd->dev, EV_MSC, MSC_RAW, code);
+	input_event(dev, EV_MSC, MSC_RAW, code);
 
 	if (atkbd->translated) {
 
-		if (atkbd->emul ||
-		    (code != ATKBD_RET_EMUL0 && code != ATKBD_RET_EMUL1 &&
-		     code != ATKBD_RET_HANGUEL && code != ATKBD_RET_HANJA &&
-		     (code != ATKBD_RET_ERR || atkbd->err_xl) &&
-	             (code != ATKBD_RET_BAT || atkbd->bat_xl))) {
+		if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
 			atkbd->release = code >> 7;
 			code &= 0x7f;
 		}
 
-		if (!atkbd->emul) {
-		     if ((code & 0x7f) == (ATKBD_RET_BAT & 0x7f))
-			atkbd->bat_xl = !(data >> 7);
-		     if ((code & 0x7f) == (ATKBD_RET_ERR & 0x7f))
-			atkbd->err_xl = !(data >> 7);
-		}
+		if (!atkbd->emul)
+			atkbd_calculate_xl_bit(atkbd, data);
 	}
 
 	switch (code) {
@@ -333,47 +381,48 @@
 		case ATKBD_RET_RELEASE:
 			atkbd->release = 1;
 			goto out;
-		case ATKBD_RET_HANGUEL:
-			atkbd_report_key(atkbd->dev, regs, KEY_HANGUEL, 3);
+		case ATKBD_RET_ACK:
+		case ATKBD_RET_NAK:
+			printk(KERN_WARNING "atkbd.c: Spurious %s on %s. "
+			       "Some program might be trying access hardware directly.\n",
+			       data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
 			goto out;
+		case ATKBD_RET_HANGEUL:
 		case ATKBD_RET_HANJA:
-			atkbd_report_key(atkbd->dev, regs, KEY_HANJA, 3);
-			goto out;
+			/*
+			 * These keys do not report release and thus need to be
+			 * flagged properly
+			 */
+			add_release_event = 1;
+			break;
 		case ATKBD_RET_ERR:
 			printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys);
 			goto out;
 	}
 
-	if (atkbd->set != 3)
-		code = (code & 0x7f) | ((code & 0x80) << 1);
-	if (atkbd->emul) {
-		if (--atkbd->emul)
-			goto out;
-		code |= (atkbd->set != 3) ? 0x80 : 0x100;
-	}
+	code = atkbd_compat_scancode(atkbd, code);
 
-	if (atkbd->keycode[code] != ATKBD_KEY_NULL)
-		input_event(atkbd->dev, EV_MSC, MSC_SCAN, code);
+	if (atkbd->emul && --atkbd->emul)
+		goto out;
 
-	switch (atkbd->keycode[code]) {
+	keycode = atkbd->keycode[code];
+
+	if (keycode != ATKBD_KEY_NULL)
+		input_event(dev, EV_MSC, MSC_SCAN, code);
+
+	switch (keycode) {
 		case ATKBD_KEY_NULL:
 			break;
 		case ATKBD_KEY_UNKNOWN:
-			if (data == ATKBD_RET_ACK || data == ATKBD_RET_NAK) {
-				printk(KERN_WARNING "atkbd.c: Spurious %s on %s. Some program, "
-				       "like XFree86, might be trying access hardware directly.\n",
-				       data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
-			} else {
-				printk(KERN_WARNING "atkbd.c: Unknown key %s "
-				       "(%s set %d, code %#x on %s).\n",
-				       atkbd->release ? "released" : "pressed",
-				       atkbd->translated ? "translated" : "raw",
-				       atkbd->set, code, serio->phys);
-				printk(KERN_WARNING "atkbd.c: Use 'setkeycodes %s%02x <keycode>' "
-				       "to make it known.\n",
-				       code & 0x80 ? "e0" : "", code & 0x7f);
-			}
-			input_sync(atkbd->dev);
+			printk(KERN_WARNING
+			       "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n",
+			       atkbd->release ? "released" : "pressed",
+			       atkbd->translated ? "translated" : "raw",
+			       atkbd->set, code, serio->phys);
+			printk(KERN_WARNING
+			       "atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n",
+			       code & 0x80 ? "e0" : "", code & 0x7f);
+			input_sync(dev);
 			break;
 		case ATKBD_SCR_1:
 			scroll = 1 - atkbd->release * 2;
@@ -397,33 +446,35 @@
 			hscroll = 1;
 			break;
 		default:
-			value = atkbd->release ? 0 :
-				(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev->key)));
-
-			switch (value) {	/* Workaround Toshiba laptop multiple keypress */
-				case 0:
-					atkbd->last = 0;
-					break;
-				case 1:
-					atkbd->last = code;
-					atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev->rep[REP_DELAY]) / 2;
-					break;
-				case 2:
-					if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
-						value = 1;
-					break;
+			if (atkbd->release) {
+				value = 0;
+				atkbd->last = 0;
+			} else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) {
+				/* Workaround Toshiba laptop multiple keypress */
+				value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2;
+			} else {
+				value = 1;
+				atkbd->last = code;
+				atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2;
 			}
 
-			atkbd_report_key(atkbd->dev, regs, atkbd->keycode[code], value);
+			input_regs(dev, regs);
+			input_event(dev, EV_KEY, keycode, value);
+			input_sync(dev);
+
+			if (value && add_release_event) {
+				input_report_key(dev, keycode, 0);
+				input_sync(dev);
+			}
 	}
 
 	if (atkbd->scroll) {
-		input_regs(atkbd->dev, regs);
+		input_regs(dev, regs);
 		if (click != -1)
-			input_report_key(atkbd->dev, BTN_MIDDLE, click);
-		input_report_rel(atkbd->dev, REL_WHEEL, scroll);
-		input_report_rel(atkbd->dev, REL_HWHEEL, hscroll);
-		input_sync(atkbd->dev);
+			input_report_key(dev, BTN_MIDDLE, click);
+		input_report_rel(dev, REL_WHEEL, scroll);
+		input_report_rel(dev, REL_HWHEEL, hscroll);
+		input_sync(dev);
 	}
 
 	atkbd->release = 0;
@@ -764,6 +815,9 @@
 			for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
 				atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;
 	}
+
+	atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL)] = KEY_HANGUEL;
+	atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA)] = KEY_HANJA;
 }
 
 /*
@@ -776,12 +830,15 @@
 	int i;
 
 	if (atkbd->extra)
-		sprintf(atkbd->name, "AT Set 2 Extra keyboard");
+		snprintf(atkbd->name, sizeof(atkbd->name),
+			 "AT Set 2 Extra keyboard");
 	else
-		sprintf(atkbd->name, "AT %s Set %d keyboard",
-			atkbd->translated ? "Translated" : "Raw", atkbd->set);
+		snprintf(atkbd->name, sizeof(atkbd->name),
+			 "AT %s Set %d keyboard",
+			 atkbd->translated ? "Translated" : "Raw", atkbd->set);
 
-	sprintf(atkbd->phys, "%s/input0", atkbd->ps2dev.serio->phys);
+	snprintf(atkbd->phys, sizeof(atkbd->phys),
+		 "%s/input0", atkbd->ps2dev.serio->phys);
 
 	input_dev->name = atkbd->name;
 	input_dev->phys = atkbd->phys;
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
index 77c4d96..5174224 100644
--- a/drivers/input/keyboard/lkkbd.c
+++ b/drivers/input/keyboard/lkkbd.c
@@ -384,18 +384,21 @@
 	 */
 	switch (lk->id[4]) {
 		case 1:
-			sprintf (lk->name, "DEC LK201 keyboard");
+			strlcpy (lk->name, "DEC LK201 keyboard",
+				 sizeof (lk->name));
 
 			if (lk201_compose_is_alt)
 				lk->keycode[0xb1] = KEY_LEFTALT;
 			break;
 
 		case 2:
-			sprintf (lk->name, "DEC LK401 keyboard");
+			strlcpy (lk->name, "DEC LK401 keyboard",
+				 sizeof (lk->name));
 			break;
 
 		default:
-			sprintf (lk->name, "Unknown DEC keyboard");
+			strlcpy (lk->name, "Unknown DEC keyboard",
+				 sizeof (lk->name));
 			printk (KERN_ERR "lkkbd: keyboard on %s is unknown, "
 					"please report to Jan-Benedict Glaw "
 					"<jbglaw@lug-owl.de>\n", lk->phys);
diff --git a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
index d10983c..40a3f551 100644
--- a/drivers/input/keyboard/newtonkbd.c
+++ b/drivers/input/keyboard/newtonkbd.c
@@ -96,7 +96,7 @@
 
 	nkbd->serio = serio;
 	nkbd->dev = input_dev;
-	sprintf(nkbd->phys, "%s/input0", serio->phys);
+	snprintf(nkbd->phys, sizeof(nkbd->phys), "%s/input0", serio->phys);
 	memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
 
 	input_dev->name = "Newton Keyboard";
diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
index b15b6d8..9dbd7b8 100644
--- a/drivers/input/keyboard/sunkbd.c
+++ b/drivers/input/keyboard/sunkbd.c
@@ -263,7 +263,7 @@
 		goto fail;
 	}
 
-	sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
+	snprintf(sunkbd->name, sizeof(sunkbd->name), "Sun Type %d keyboard", sunkbd->type);
 	memcpy(sunkbd->keycode, sunkbd_keycode, sizeof(sunkbd->keycode));
 
 	input_dev->name = sunkbd->name;
diff --git a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
index 4135e3e..0821d53 100644
--- a/drivers/input/keyboard/xtkbd.c
+++ b/drivers/input/keyboard/xtkbd.c
@@ -100,7 +100,7 @@
 
 	xtkbd->serio = serio;
 	xtkbd->dev = input_dev;
-	sprintf(xtkbd->phys, "%s/input0", serio->phys);
+	snprintf(xtkbd->phys, sizeof(xtkbd->phys), "%s/input0", serio->phys);
 	memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
 
 	input_dev->name = "XT Keyboard";
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 4bad588..a6dfc74 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -26,7 +26,7 @@
 
 config INPUT_SPARCSPKR
 	tristate "SPARC Speaker support"
-	depends on PCI && SPARC
+	depends on PCI && SPARC64
 	help
 	  Say Y here if you want the standard Speaker on Sparc PCI systems
 	  to be used for bells and whistles.
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c
index f0fd2c4..42c11fb 100644
--- a/drivers/input/misc/sparcspkr.c
+++ b/drivers/input/misc/sparcspkr.c
@@ -2,7 +2,7 @@
  *  Driver for PC-speaker like devices found on various Sparc systems.
  *
  *  Copyright (c) 2002 Vojtech Pavlik
- *  Copyright (c) 2002 David S. Miller (davem@redhat.com)
+ *  Copyright (c) 2002, 2006 David S. Miller (davem@davemloft.net)
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -13,21 +13,23 @@
 
 #include <asm/io.h>
 #include <asm/ebus.h>
-#ifdef CONFIG_SPARC64
 #include <asm/isa.h>
-#endif
 
-MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
+MODULE_AUTHOR("David S. Miller <davem@davemloft.net>");
 MODULE_DESCRIPTION("Sparc Speaker beeper driver");
 MODULE_LICENSE("GPL");
 
-const char *beep_name;
-static unsigned long beep_iobase;
-static int (*beep_event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
-static DEFINE_SPINLOCK(beep_lock);
+struct sparcspkr_state {
+	const char		*name;
+	unsigned long		iobase;
+	int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
+	spinlock_t		lock;
+	struct input_dev	*input_dev;
+};
 
 static int ebus_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
+	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
 	unsigned int count = 0;
 	unsigned long flags;
 
@@ -43,24 +45,24 @@
 	if (value > 20 && value < 32767)
 		count = 1193182 / value;
 
-	spin_lock_irqsave(&beep_lock, flags);
+	spin_lock_irqsave(&state->lock, flags);
 
 	/* EBUS speaker only has on/off state, the frequency does not
 	 * appear to be programmable.
 	 */
-	if (beep_iobase & 0x2UL)
-		outb(!!count, beep_iobase);
+	if (state->iobase & 0x2UL)
+		outb(!!count, state->iobase);
 	else
-		outl(!!count, beep_iobase);
+		outl(!!count, state->iobase);
 
-	spin_unlock_irqrestore(&beep_lock, flags);
+	spin_unlock_irqrestore(&state->lock, flags);
 
 	return 0;
 }
 
-#ifdef CONFIG_SPARC64
 static int isa_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
+	struct sparcspkr_state *state = dev_get_drvdata(dev->cdev.dev);
 	unsigned int count = 0;
 	unsigned long flags;
 
@@ -76,29 +78,29 @@
 	if (value > 20 && value < 32767)
 		count = 1193182 / value;
 
-	spin_lock_irqsave(&beep_lock, flags);
+	spin_lock_irqsave(&state->lock, flags);
 
 	if (count) {
 		/* enable counter 2 */
-		outb(inb(beep_iobase + 0x61) | 3, beep_iobase + 0x61);
+		outb(inb(state->iobase + 0x61) | 3, state->iobase + 0x61);
 		/* set command for counter 2, 2 byte write */
-		outb(0xB6, beep_iobase + 0x43);
+		outb(0xB6, state->iobase + 0x43);
 		/* select desired HZ */
-		outb(count & 0xff, beep_iobase + 0x42);
-		outb((count >> 8) & 0xff, beep_iobase + 0x42);
+		outb(count & 0xff, state->iobase + 0x42);
+		outb((count >> 8) & 0xff, state->iobase + 0x42);
 	} else {
 		/* disable counter 2 */
-		outb(inb_p(beep_iobase + 0x61) & 0xFC, beep_iobase + 0x61);
+		outb(inb_p(state->iobase + 0x61) & 0xFC, state->iobase + 0x61);
 	}
 
-	spin_unlock_irqrestore(&beep_lock, flags);
+	spin_unlock_irqrestore(&state->lock, flags);
 
 	return 0;
 }
-#endif
 
-static int __devinit sparcspkr_probe(struct platform_device *dev)
+static int __devinit sparcspkr_probe(struct device *dev)
 {
+	struct sparcspkr_state *state = dev_get_drvdata(dev);
 	struct input_dev *input_dev;
 	int error;
 
@@ -106,18 +108,18 @@
 	if (!input_dev)
 		return -ENOMEM;
 
-	input_dev->name = beep_name;
+	input_dev->name = state->name;
 	input_dev->phys = "sparc/input0";
 	input_dev->id.bustype = BUS_ISA;
 	input_dev->id.vendor = 0x001f;
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0100;
-	input_dev->cdev.dev = &dev->dev;
+	input_dev->cdev.dev = dev;
 
 	input_dev->evbit[0] = BIT(EV_SND);
 	input_dev->sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE);
 
-	input_dev->event = beep_event;
+	input_dev->event = state->event;
 
 	error = input_register_device(input_dev);
 	if (error) {
@@ -125,111 +127,137 @@
 		return error;
 	}
 
-	platform_set_drvdata(dev, input_dev);
+	state->input_dev = input_dev;
 
 	return 0;
 }
 
-static int __devexit sparcspkr_remove(struct platform_device *dev)
+static int __devexit sparcspkr_remove(struct of_device *dev)
 {
-	struct input_dev *input_dev = platform_get_drvdata(dev);
+	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
+	struct input_dev *input_dev = state->input_dev;
+
+	/* turn off the speaker */
+	state->event(input_dev, EV_SND, SND_BELL, 0);
 
 	input_unregister_device(input_dev);
-	platform_set_drvdata(dev, NULL);
-	/* turn off the speaker */
-	beep_event(NULL, EV_SND, SND_BELL, 0);
+
+	dev_set_drvdata(&dev->dev, NULL);
+	kfree(state);
 
 	return 0;
 }
 
-static void sparcspkr_shutdown(struct platform_device *dev)
+static int sparcspkr_shutdown(struct of_device *dev)
 {
+	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
+	struct input_dev *input_dev = state->input_dev;
+
 	/* turn off the speaker */
-	beep_event(NULL, EV_SND, SND_BELL, 0);
+	state->event(input_dev, EV_SND, SND_BELL, 0);
+
+	return 0;
 }
 
-static struct platform_driver sparcspkr_platform_driver = {
-	.driver		= {
-		.name	= "sparcspkr",
-		.owner	= THIS_MODULE,
+static int __devinit ebus_beep_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
+	struct sparcspkr_state *state;
+	int err;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	state->name = "Sparc EBUS Speaker";
+	state->iobase = edev->resource[0].start;
+	state->event = ebus_spkr_event;
+	spin_lock_init(&state->lock);
+
+	dev_set_drvdata(&dev->dev, state);
+
+	err = sparcspkr_probe(&dev->dev);
+	if (err) {
+		dev_set_drvdata(&dev->dev, NULL);
+		kfree(state);
+	}
+
+	return 0;
+}
+
+static struct of_device_id ebus_beep_match[] = {
+	{
+		.name = "beep",
 	},
-	.probe		= sparcspkr_probe,
-	.remove		= __devexit_p(sparcspkr_remove),
+	{},
+};
+
+static struct of_platform_driver ebus_beep_driver = {
+	.name		= "beep",
+	.match_table	= ebus_beep_match,
+	.probe		= ebus_beep_probe,
+	.remove		= sparcspkr_remove,
 	.shutdown	= sparcspkr_shutdown,
 };
 
-static struct platform_device *sparcspkr_platform_device;
-
-static int __init sparcspkr_drv_init(void)
+static int __devinit isa_beep_probe(struct of_device *dev, const struct of_device_id *match)
 {
-	int error;
+	struct sparc_isa_device *idev = to_isa_device(&dev->dev);
+	struct sparcspkr_state *state;
+	int err;
 
-	error = platform_driver_register(&sparcspkr_platform_driver);
-	if (error)
-		return error;
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
 
-	sparcspkr_platform_device = platform_device_alloc("sparcspkr", -1);
-	if (!sparcspkr_platform_device) {
-		error = -ENOMEM;
-		goto err_unregister_driver;
+	state->name = "Sparc ISA Speaker";
+	state->iobase = idev->resource.start;
+	state->event = isa_spkr_event;
+	spin_lock_init(&state->lock);
+
+	dev_set_drvdata(&dev->dev, state);
+
+	err = sparcspkr_probe(&dev->dev);
+	if (err) {
+		dev_set_drvdata(&dev->dev, NULL);
+		kfree(state);
 	}
 
-	error = platform_device_add(sparcspkr_platform_device);
-	if (error)
-		goto err_free_device;
-
 	return 0;
-
- err_free_device:
-	platform_device_put(sparcspkr_platform_device);
- err_unregister_driver:
-	platform_driver_unregister(&sparcspkr_platform_driver);
-
-	return error;
 }
 
+static struct of_device_id isa_beep_match[] = {
+	{
+		.name = "dma",
+	},
+	{},
+};
+
+static struct of_platform_driver isa_beep_driver = {
+	.name		= "beep",
+	.match_table	= isa_beep_match,
+	.probe		= isa_beep_probe,
+	.remove		= sparcspkr_remove,
+	.shutdown	= sparcspkr_shutdown,
+};
+
 static int __init sparcspkr_init(void)
 {
-	struct linux_ebus *ebus;
-	struct linux_ebus_device *edev;
-#ifdef CONFIG_SPARC64
-	struct sparc_isa_bridge *isa_br;
-	struct sparc_isa_device *isa_dev;
-#endif
+	int err = of_register_driver(&ebus_beep_driver, &ebus_bus_type);
 
-	for_each_ebus(ebus) {
-		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "beep")) {
-				beep_name = "Sparc EBUS Speaker";
-				beep_event = ebus_spkr_event;
-				beep_iobase = edev->resource[0].start;
-				return sparcspkr_drv_init();
-			}
-		}
+	if (!err) {
+		err = of_register_driver(&isa_beep_driver, &isa_bus_type);
+		if (err)
+			of_unregister_driver(&ebus_beep_driver);
 	}
-#ifdef CONFIG_SPARC64
-	for_each_isa(isa_br) {
-		for_each_isadev(isa_dev, isa_br) {
-			/* A hack, the beep device's base lives in
-			 * the DMA isa node.
-			 */
-			if (!strcmp(isa_dev->prom_name, "dma")) {
-				beep_name = "Sparc ISA Speaker";
-				beep_event = isa_spkr_event,
-				beep_iobase = isa_dev->resource.start;
-				return sparcspkr_drv_init();
-			}
-		}
-	}
-#endif
 
-	return -ENODEV;
+	return err;
 }
 
 static void __exit sparcspkr_exit(void)
 {
-	platform_device_unregister(sparcspkr_platform_device);
-	platform_driver_unregister(&sparcspkr_platform_driver);
+	of_unregister_driver(&ebus_beep_driver);
+	of_unregister_driver(&isa_beep_driver);
 }
 
 module_init(sparcspkr_init);
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index e4e5be1..ccf0fae 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -285,6 +285,15 @@
 	{ KE_END, 0 }
 };
 
+static struct key_entry keymap_wistron_ms2111[] = {
+	{ KE_KEY,  0x11, KEY_PROG1 },
+	{ KE_KEY,  0x12, KEY_PROG2 },
+	{ KE_KEY,  0x13, KEY_PROG3 },
+	{ KE_KEY,  0x31, KEY_MAIL },
+	{ KE_KEY,  0x36, KEY_WWW },
+	{ KE_END,  0 }
+};
+
 static struct key_entry keymap_wistron_ms2141[] = {
 	{ KE_KEY,  0x11, KEY_PROG1 },
 	{ KE_KEY,  0x12, KEY_PROG2 },
@@ -326,6 +335,7 @@
 	{ KE_WIFI, 0x30, 0 },
 	{ KE_KEY,  0x31, KEY_MAIL },
 	{ KE_KEY,  0x36, KEY_WWW },
+	{ KE_END,  0 },
 };
 
 /*
@@ -388,6 +398,15 @@
 		},
 		.driver_data = keymap_aopen_1559as
 	},
+	{
+		.callback = dmi_matched,
+		.ident = "Medion MD 9783",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"),
+		},
+		.driver_data = keymap_wistron_ms2111
+	},
 	{ NULL, }
 };
 
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index a0e2e79..070d753 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -470,7 +470,7 @@
 		dev1->keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
 	}
 
-	sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
+	snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys);
 	dev2->phys = priv->phys;
 	dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
 	dev2->id.bustype = BUS_I8042;
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index 136321a..8bc9f51 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -150,9 +150,20 @@
  */
 
 	if (psmouse->type == PSMOUSE_IMEX) {
-		input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7));
-		input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1);
-		input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1);
+		switch (packet[3] & 0xC0) {
+			case 0x80: /* vertical scroll on IntelliMouse Explorer 4.0 */
+				input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31));
+				break;
+			case 0x40: /* horizontal scroll on IntelliMouse Explorer 4.0 */
+				input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31));
+				break;
+			case 0x00:
+			case 0xC0:
+				input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7));
+				input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1);
+				input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1);
+				break;
+		}
 	}
 
 /*
@@ -466,9 +477,25 @@
 	if (param[0] != 4)
 		return -1;
 
+/* Magic to enable horizontal scrolling on IntelliMouse 4.0 */
+	param[0] = 200;
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+	param[0] =  80;
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+	param[0] =  40;
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+
+	param[0] = 200;
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+	param[0] = 200;
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+	param[0] =  60;
+	ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE);
+
 	if (set_properties) {
 		set_bit(BTN_MIDDLE, psmouse->dev->keybit);
 		set_bit(REL_WHEEL, psmouse->dev->relbit);
+		set_bit(REL_HWHEEL, psmouse->dev->relbit);
 		set_bit(BTN_SIDE, psmouse->dev->keybit);
 		set_bit(BTN_EXTRA, psmouse->dev->keybit);
 
@@ -1057,8 +1084,8 @@
 	if (psmouse->resync_time && psmouse->poll(psmouse))
 		psmouse->resync_time = 0;
 
-	sprintf(psmouse->devname, "%s %s %s",
-		psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
+	snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s",
+		 psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name);
 
 	input_dev->name = psmouse->devname;
 	input_dev->phys = psmouse->phys;
@@ -1099,7 +1126,7 @@
 	ps2_init(&psmouse->ps2dev, serio);
 	INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse);
 	psmouse->dev = input_dev;
-	sprintf(psmouse->phys, "%s/input0", serio->phys);
+	snprintf(psmouse->phys, sizeof(psmouse->phys), "%s/input0", serio->phys);
 
 	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index 2f9a04a..a897424 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -254,7 +254,7 @@
 		goto fail;
 
 	sermouse->dev = input_dev;
-	sprintf(sermouse->phys, "%s/input0", serio->phys);
+	snprintf(sermouse->phys, sizeof(sermouse->phys), "%s/input0", serio->phys);
 	sermouse->type = serio->id.proto;
 
 	input_dev->name = sermouse_protocols[sermouse->type];
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
index 36e9442..7b85bc2 100644
--- a/drivers/input/mouse/vsxxxaa.c
+++ b/drivers/input/mouse/vsxxxaa.c
@@ -153,22 +153,25 @@
 {
 	switch (mouse->type) {
 		case 0x02:
-			sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse");
+			strlcpy (mouse->name, "DEC VSXXX-AA/-GA mouse",
+				 sizeof (mouse->name));
 			break;
 
 		case 0x04:
-			sprintf (mouse->name, "DEC VSXXX-AB digitizer");
+			strlcpy (mouse->name, "DEC VSXXX-AB digitizer",
+				 sizeof (mouse->name));
 			break;
 
 		default:
-			sprintf (mouse->name, "unknown DEC pointer device "
-					"(type = 0x%02x)", mouse->type);
+			snprintf (mouse->name, sizeof (mouse->name),
+				  "unknown DEC pointer device (type = 0x%02x)",
+				  mouse->type);
 			break;
 	}
 
-	printk (KERN_INFO "Found %s version 0x%02x from country 0x%02x "
-			"on port %s\n", mouse->name, mouse->version,
-			mouse->country, mouse->phys);
+	printk (KERN_INFO
+		"Found %s version 0x%02x from country 0x%02x on port %s\n",
+		mouse->name, mouse->version, mouse->country, mouse->phys);
 }
 
 /*
@@ -503,8 +506,9 @@
 
 	mouse->dev = input_dev;
 	mouse->serio = serio;
-	sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
-	sprintf (mouse->phys, "%s/input0", serio->phys);
+	strlcat (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer",
+		 sizeof (mouse->name));
+	snprintf (mouse->phys, sizeof (mouse->phys), "%s/input0", serio->phys);
 
 	input_dev->name = mouse->name;
 	input_dev->phys = mouse->phys;
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index b685a50..eb721b1 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -123,7 +123,9 @@
 
 	if (mousedev->touch) {
 		size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
-		if (size == 0) size = 256 * 2;
+		if (size == 0)
+			size = 256 * 2;
+
 		switch (code) {
 			case ABS_X:
 				fx(0) = value;
@@ -155,18 +157,24 @@
 	switch (code) {
 		case ABS_X:
 			size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
-			if (size == 0) size = xres ? : 1;
-			if (value > dev->absmax[ABS_X]) value = dev->absmax[ABS_X];
-			if (value < dev->absmin[ABS_X]) value = dev->absmin[ABS_X];
+			if (size == 0)
+				size = xres ? : 1;
+			if (value > dev->absmax[ABS_X])
+				value = dev->absmax[ABS_X];
+			if (value < dev->absmin[ABS_X])
+				value = dev->absmin[ABS_X];
 			mousedev->packet.x = ((value - dev->absmin[ABS_X]) * xres) / size;
 			mousedev->packet.abs_event = 1;
 			break;
 
 		case ABS_Y:
 			size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
-			if (size == 0) size = yres ? : 1;
-			if (value > dev->absmax[ABS_Y]) value = dev->absmax[ABS_Y];
-			if (value < dev->absmin[ABS_Y]) value = dev->absmin[ABS_Y];
+			if (size == 0)
+				size = yres ? : 1;
+			if (value > dev->absmax[ABS_Y])
+				value = dev->absmax[ABS_Y];
+			if (value < dev->absmin[ABS_Y])
+				value = dev->absmin[ABS_Y];
 			mousedev->packet.y = yres - ((value - dev->absmin[ABS_Y]) * yres) / size;
 			mousedev->packet.abs_event = 1;
 			break;
@@ -202,7 +210,7 @@
 		case BTN_SIDE:		index = 3; break;
 		case BTN_4:
 		case BTN_EXTRA:		index = 4; break;
-		default: 		return;
+		default:		return;
 	}
 
 	if (value) {
@@ -285,10 +293,9 @@
 		mousedev->touch = mousedev->pkt_count = 0;
 		mousedev->frac_dx = 0;
 		mousedev->frac_dy = 0;
-	}
-	else
-		if (!mousedev->touch)
-			mousedev->touch = jiffies;
+
+	} else if (!mousedev->touch)
+		mousedev->touch = jiffies;
 }
 
 static void mousedev_event(struct input_handle *handle, unsigned int type, unsigned int code, int value)
@@ -327,7 +334,7 @@
 					mousedev->pkt_count++;
 					/* Input system eats duplicate events, but we need all of them
 					 * to do correct averaging so apply present one forward
-			 		 */
+					 */
 					fx(0) = fx(1);
 					fy(0) = fy(1);
 				}
@@ -346,7 +353,9 @@
 {
 	int retval;
 	struct mousedev_list *list = file->private_data;
+
 	retval = fasync_helper(fd, file, on, &list->fasync);
+
 	return retval < 0 ? retval : 0;
 }
 
@@ -507,14 +516,16 @@
 				list->imexseq = 0;
 				list->mode = MOUSEDEV_EMUL_EXPS;
 			}
-		} else list->imexseq = 0;
+		} else
+			list->imexseq = 0;
 
 		if (c == mousedev_imps_seq[list->impsseq]) {
 			if (++list->impsseq == MOUSEDEV_SEQ_LEN) {
 				list->impsseq = 0;
 				list->mode = MOUSEDEV_EMUL_IMPS;
 			}
-		} else list->impsseq = 0;
+		} else
+			list->impsseq = 0;
 
 		list->ps2[0] = 0xfa;
 
@@ -598,6 +609,7 @@
 static unsigned int mousedev_poll(struct file *file, poll_table *wait)
 {
 	struct mousedev_list *list = file->private_data;
+
 	poll_wait(file, &list->mousedev->wait, wait);
 	return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
 		(list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h
index ed9446f..6d66351 100644
--- a/drivers/input/serio/i8042-sparcio.h
+++ b/drivers/input/serio/i8042-sparcio.h
@@ -74,7 +74,7 @@
 
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
-				if (!strcmp(edev->prom_name, "8042"))
+				if (!strcmp(edev->prom_node->name, "8042"))
 					goto edev_found;
 			}
 		}
@@ -82,14 +82,14 @@
 
 	edev_found:
 		for_each_edevchild(edev, child) {
-			if (!strcmp(child->prom_name, OBP_PS2KBD_NAME1) ||
-			    !strcmp(child->prom_name, OBP_PS2KBD_NAME2)) {
+			if (!strcmp(child->prom_node->name, OBP_PS2KBD_NAME1) ||
+			    !strcmp(child->prom_node->name, OBP_PS2KBD_NAME2)) {
 				i8042_kbd_irq = child->irqs[0];
 				kbd_iobase =
 					ioremap(child->resource[0].start, 8);
 			}
-			if (!strcmp(child->prom_name, OBP_PS2MS_NAME1) ||
-			    !strcmp(child->prom_name, OBP_PS2MS_NAME2))
+			if (!strcmp(child->prom_node->name, OBP_PS2MS_NAME1) ||
+			    !strcmp(child->prom_node->name, OBP_PS2MS_NAME2))
 				i8042_aux_irq = child->irqs[0];
 		}
 		if (i8042_kbd_irq == -1 ||
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 161afdd..386023c 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -773,8 +773,7 @@
 
 	ts->last_msg = m;
 
-	if (request_irq(spi->irq, ads7846_irq,
-			SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
+	if (request_irq(spi->irq, ads7846_irq, SA_TRIGGER_FALLING,
 			spi->dev.driver->name, ts)) {
 		dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
 		err = -EBUSY;
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index 466da19..b769b21 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -129,7 +129,7 @@
 
 	gunze->serio = serio;
 	gunze->dev = input_dev;
-	sprintf(gunze->phys, "%s/input0", serio->phys);
+	snprintf(gunze->phys, sizeof(serio->phys), "%s/input0", serio->phys);
 
 	input_dev->private = gunze;
 	input_dev->name = "Gunze AHL-51S TouchScreen";
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index a18d56b..2de2139 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -363,7 +363,7 @@
 
 	ts->serio = serio;
 	ts->dev = input_dev;
-	sprintf(ts->phys, "%s/input0", serio->phys);
+	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", serio->phys);
 
 	input_dev->name = "H3600 TouchScreen";
 	input_dev->phys = ts->phys;
@@ -399,16 +399,14 @@
 	set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
 
 	if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
-			SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
-			"h3600_action", &ts->dev)) {
+			SA_SHIRQ | SA_INTERRUPT, "h3600_action", &ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
 		err = -EBUSY;
 		goto fail2;
 	}
 
 	if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
-			SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
-			"h3600_suspend", &ts->dev)) {
+			SA_SHIRQ | SA_INTERRUPT, "h3600_suspend", &ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
 		err = -EBUSY;
 		goto fail3;
diff --git a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
index 1d0d37e..8647a90 100644
--- a/drivers/input/touchscreen/mtouch.c
+++ b/drivers/input/touchscreen/mtouch.c
@@ -143,7 +143,7 @@
 
 	mtouch->serio = serio;
 	mtouch->dev = input_dev;
-	sprintf(mtouch->phys, "%s/input0", serio->phys);
+	snprintf(mtouch->phys, sizeof(mtouch->phys), "%s/input0", serio->phys);
 
 	input_dev->private = mtouch;
 	input_dev->name = "MicroTouch Serial TouchScreen";
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index d678d14..5f9ecad 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -35,7 +35,7 @@
  * e-mail - mail your message to <jsimmons@infradead.org>.
  */
 
-#define TSDEV_MINOR_BASE 	128
+#define TSDEV_MINOR_BASE	128
 #define TSDEV_MINORS		32
 /* First 16 devices are h3600_ts compatible; second 16 are h3600_tsraw */
 #define TSDEV_MINOR_MASK	15
@@ -230,6 +230,7 @@
 static unsigned int tsdev_poll(struct file *file, poll_table * wait)
 {
 	struct tsdev_list *list = file->private_data;
+
 	poll_wait(file, &list->tsdev->wait, wait);
 	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
 		(list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
@@ -248,11 +249,13 @@
 				  sizeof (struct ts_calibration)))
 			retval = -EFAULT;
 		break;
+
 	case TS_SET_CAL:
 		if (copy_from_user (&tsdev->cal, (void __user *)arg,
 				    sizeof (struct ts_calibration)))
 			retval = -EFAULT;
 		break;
+
 	default:
 		retval = -EINVAL;
 		break;
@@ -284,9 +287,11 @@
 		case ABS_X:
 			tsdev->x = value;
 			break;
+
 		case ABS_Y:
 			tsdev->y = value;
 			break;
+
 		case ABS_PRESSURE:
 			if (value > handle->dev->absmax[ABS_PRESSURE])
 				value = handle->dev->absmax[ABS_PRESSURE];
@@ -307,6 +312,7 @@
 			else if (tsdev->x > xres)
 				tsdev->x = xres;
 			break;
+
 		case REL_Y:
 			tsdev->y += value;
 			if (tsdev->y < 0)
@@ -323,6 +329,7 @@
 			case 0:
 				tsdev->pressure = 0;
 				break;
+
 			case 1:
 				if (!tsdev->pressure)
 					tsdev->pressure = 1;
@@ -370,9 +377,8 @@
 	struct class_device *cdev;
 	int minor, delta;
 
-	for (minor = 0; minor < TSDEV_MINORS/2 && tsdev_table[minor];
-	     minor++);
-	if (minor >= TSDEV_MINORS/2) {
+	for (minor = 0; minor < TSDEV_MINORS / 2 && tsdev_table[minor]; minor++);
+	if (minor >= TSDEV_MINORS / 2) {
 		printk(KERN_ERR
 		       "tsdev: You have way too many touchscreens\n");
 		return NULL;
@@ -444,22 +450,22 @@
 	      .evbit	= { BIT(EV_KEY) | BIT(EV_REL) },
 	      .keybit	= { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) },
 	      .relbit	= { BIT(REL_X) | BIT(REL_Y) },
-	 },/* A mouse like device, at least one button, two relative axes */
+	}, /* A mouse like device, at least one button, two relative axes */
 
 	{
 	      .flags	= INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
 	      .evbit	= { BIT(EV_KEY) | BIT(EV_ABS) },
 	      .keybit	= { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
 	      .absbit	= { BIT(ABS_X) | BIT(ABS_Y) },
-	 },/* A tablet like device, at least touch detection, two absolute axes */
+	}, /* A tablet like device, at least touch detection, two absolute axes */
 
 	{
 	      .flags	= INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
 	      .evbit	= { BIT(EV_ABS) },
 	      .absbit	= { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) },
-	 },/* A tablet like device with several gradations of pressure */
+	}, /* A tablet like device with several gradations of pressure */
 
-	{},/* Terminating entry */
+	{} /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(input, tsdev_ids);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 173c899..2e541fa 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -87,6 +87,11 @@
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 struct capiminor;
 
+struct datahandle_queue {
+	struct list_head	list;
+	u16			datahandle;
+};
+
 struct capiminor {
 	struct list_head list;
 	struct capincci  *nccip;
@@ -109,12 +114,9 @@
 	int                 outbytes;
 
 	/* transmit path */
-	struct datahandle_queue {
-		    struct datahandle_queue *next;
-		    u16                    datahandle;
-	} *ackqueue;
+	struct list_head ackqueue;
 	int nack;
-
+	spinlock_t ackqlock;
 };
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 
@@ -156,48 +158,54 @@
 
 static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
 {
-	struct datahandle_queue *n, **pp;
+	struct datahandle_queue *n;
+	unsigned long flags;
 
 	n = kmalloc(sizeof(*n), GFP_ATOMIC);
-	if (!n) {
-	   printk(KERN_ERR "capi: alloc datahandle failed\n");
-	   return -1;
+	if (unlikely(!n)) {
+		printk(KERN_ERR "capi: alloc datahandle failed\n");
+		return -1;
 	}
-	n->next = NULL;
 	n->datahandle = datahandle;
-	for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ;
-	*pp = n;
+	INIT_LIST_HEAD(&n->list);
+	spin_lock_irqsave(&mp->ackqlock, flags);
+	list_add_tail(&n->list, &mp->ackqueue);
 	mp->nack++;
+	spin_unlock_irqrestore(&mp->ackqlock, flags);
 	return 0;
 }
 
 static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
 {
-	struct datahandle_queue **pp, *p;
+	struct datahandle_queue *p, *tmp;
+	unsigned long flags;
 
-	for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) {
- 		if ((*pp)->datahandle == datahandle) {
-			p = *pp;
-			*pp = (*pp)->next;
+	spin_lock_irqsave(&mp->ackqlock, flags);
+	list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
+ 		if (p->datahandle == datahandle) {
+			list_del(&p->list);
 			kfree(p);
 			mp->nack--;
+			spin_unlock_irqrestore(&mp->ackqlock, flags);
 			return 0;
 		}
 	}
+	spin_unlock_irqrestore(&mp->ackqlock, flags);
 	return -1;
 }
 
 static void capiminor_del_all_ack(struct capiminor *mp)
 {
-	struct datahandle_queue **pp, *p;
+	struct datahandle_queue *p, *tmp;
+	unsigned long flags;
 
-	pp = &mp->ackqueue;
-	while (*pp) {
-		p = *pp;
-		*pp = (*pp)->next;
+	spin_lock_irqsave(&mp->ackqlock, flags);
+	list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
+		list_del(&p->list);
 		kfree(p);
 		mp->nack--;
 	}
+	spin_unlock_irqrestore(&mp->ackqlock, flags);
 }
 
 
@@ -220,6 +228,8 @@
 	mp->ncci = ncci;
 	mp->msgid = 0;
 	atomic_set(&mp->ttyopencount,0);
+	INIT_LIST_HEAD(&mp->ackqueue);
+	spin_lock_init(&mp->ackqlock);
 
 	skb_queue_head_init(&mp->inqueue);
 	skb_queue_head_init(&mp->outqueue);
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c
index 0a37ade..9ea6bd0 100644
--- a/drivers/isdn/capi/capifs.c
+++ b/drivers/isdn/capi/capifs.c
@@ -121,10 +121,10 @@
 	return -ENOMEM;
 }
 
-static struct super_block *capifs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int capifs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, capifs_fill_super);
+	return get_sb_single(fs_type, flags, data, capifs_fill_super, mnt);
 }
 
 static struct file_system_type capifs_fs_type = {
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
index f1a1f9a..1f5ebe9 100644
--- a/drivers/isdn/divert/isdn_divert.c
+++ b/drivers/isdn/divert/isdn_divert.c
@@ -592,7 +592,7 @@
 } /* put_address */
 
 /*************************************/
-/* report a succesfull interrogation */
+/* report a successful interrogation */
 /*************************************/
 static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
 { char *src = ic->parm.dss1_io.data;
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c
index eb41aba..8a45715 100644
--- a/drivers/isdn/gigaset/bas-gigaset.c
+++ b/drivers/isdn/gigaset/bas-gigaset.c
@@ -65,23 +65,22 @@
 
 MODULE_DEVICE_TABLE(usb, gigaset_table);
 
-/*======================= local function prototypes =============================*/
+/*======================= local function prototypes ==========================*/
 
-/* This function is called if a new device is connected to the USB port. It
- * checks whether this new device belongs to this driver.
- */
+/* function called if a new device belonging to this driver is connected */
 static int gigaset_probe(struct usb_interface *interface,
 			 const struct usb_device_id *id);
 
 /* Function will be called if the device is unplugged */
 static void gigaset_disconnect(struct usb_interface *interface);
 
-static void read_ctrl_callback(struct urb *, struct pt_regs *);
+static int atread_submit(struct cardstate *, int);
 static void stopurbs(struct bas_bc_state *);
+static int req_submit(struct bc_state *, int, int, int);
 static int atwrite_submit(struct cardstate *, unsigned char *, int);
 static int start_cbsend(struct cardstate *);
 
-/*==============================================================================*/
+/*============================================================================*/
 
 struct bas_cardstate {
 	struct usb_device	*udev;		/* USB device pointer */
@@ -91,6 +90,7 @@
 	struct urb		*urb_ctrl;	/* control pipe default URB */
 	struct usb_ctrlrequest	dr_ctrl;
 	struct timer_list	timer_ctrl;	/* control request timeout */
+	int			retry_ctrl;
 
 	struct timer_list	timer_atrdy;	/* AT command ready timeout */
 	struct urb		*urb_cmd_out;	/* for sending AT commands */
@@ -307,6 +307,7 @@
  * hang up any existing connection because of an unrecoverable error
  * This function may be called from any context and takes care of scheduling
  * the necessary actions for execution outside of interrupt context.
+ * cs->lock must not be held.
  * argument:
  *	B channel control structure
  */
@@ -325,14 +326,17 @@
 
 /* error_reset
  * reset Gigaset device because of an unrecoverable error
- * This function may be called from any context, and should take care of
+ * This function may be called from any context, and takes care of
  * scheduling the necessary actions for execution outside of interrupt context.
- * Right now, it just generates a kernel message calling for help.
+ * cs->lock must not be held.
  * argument:
  *	controller state structure
  */
 static inline void error_reset(struct cardstate *cs)
 {
+	/* close AT command channel to recover (ignore errors) */
+	req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT);
+
 	//FIXME try to recover without bothering the user
 	dev_err(cs->dev,
 	    "unrecoverable error - please disconnect Gigaset base to reset\n");
@@ -403,14 +407,30 @@
 {
 	struct cardstate *cs = (struct cardstate *) data;
 	struct bas_cardstate *ucs = cs->hw.bas;
+	int rc;
 
 	if (!ucs->rcvbuf_size) {
 		gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__);
 		return;
 	}
 
-	dev_err(cs->dev, "timeout reading AT response\n");
-	error_reset(cs);	//FIXME retry?
+	if (ucs->retry_cmd_in++ < BAS_RETRY) {
+		dev_notice(cs->dev, "control read: timeout, retry %d\n",
+			   ucs->retry_cmd_in);
+		rc = atread_submit(cs, BAS_TIMEOUT);
+		if (rc >= 0 || rc == -ENODEV)
+			/* resubmitted or disconnected */
+			/* - bypass regular exit block */
+			return;
+	} else {
+		dev_err(cs->dev,
+			"control read: timeout, giving up after %d tries\n",
+			ucs->retry_cmd_in);
+	}
+	kfree(ucs->rcvbuf);
+	ucs->rcvbuf = NULL;
+	ucs->rcvbuf_size = 0;
+	error_reset(cs);
 }
 
 /* set/clear bits in base connection state, return previous state
@@ -428,6 +448,96 @@
 	return state;
 }
 
+/* read_ctrl_callback
+ * USB completion handler for control pipe input
+ * called by the USB subsystem in interrupt context
+ * parameter:
+ *	urb	USB request block
+ *		urb->context = inbuf structure for controller state
+ */
+static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
+{
+	struct inbuf_t *inbuf = urb->context;
+	struct cardstate *cs = inbuf->cs;
+	struct bas_cardstate *ucs = cs->hw.bas;
+	int have_data = 0;
+	unsigned numbytes;
+	int rc;
+
+	update_basstate(ucs, 0, BS_ATRDPEND);
+
+	if (!ucs->rcvbuf_size) {
+		dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
+		return;
+	}
+
+	del_timer(&ucs->timer_cmd_in);
+
+	switch (urb->status) {
+	case 0:				/* normal completion */
+		numbytes = urb->actual_length;
+		if (unlikely(numbytes != ucs->rcvbuf_size)) {
+			dev_warn(cs->dev,
+			       "control read: received %d chars, expected %d\n",
+				 numbytes, ucs->rcvbuf_size);
+			if (numbytes > ucs->rcvbuf_size)
+				numbytes = ucs->rcvbuf_size;
+		}
+
+		/* copy received bytes to inbuf */
+		have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes);
+
+		if (unlikely(numbytes < ucs->rcvbuf_size)) {
+			/* incomplete - resubmit for remaining bytes */
+			ucs->rcvbuf_size -= numbytes;
+			ucs->retry_cmd_in = 0;
+			rc = atread_submit(cs, BAS_TIMEOUT);
+			if (rc >= 0 || rc == -ENODEV)
+				/* resubmitted or disconnected */
+				/* - bypass regular exit block */
+				return;
+			error_reset(cs);
+		}
+		break;
+
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
+	case -EINPROGRESS:		/* pending */
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
+		/* no action necessary */
+		gig_dbg(DEBUG_USBREQ, "%s: %s",
+			__func__, get_usb_statmsg(urb->status));
+		break;
+
+	default:			/* severe trouble */
+		dev_warn(cs->dev, "control read: %s\n",
+			 get_usb_statmsg(urb->status));
+		if (ucs->retry_cmd_in++ < BAS_RETRY) {
+			dev_notice(cs->dev, "control read: retry %d\n",
+				   ucs->retry_cmd_in);
+			rc = atread_submit(cs, BAS_TIMEOUT);
+			if (rc >= 0 || rc == -ENODEV)
+				/* resubmitted or disconnected */
+				/* - bypass regular exit block */
+				return;
+		} else {
+			dev_err(cs->dev,
+				"control read: giving up after %d tries\n",
+				ucs->retry_cmd_in);
+		}
+		error_reset(cs);
+	}
+
+	kfree(ucs->rcvbuf);
+	ucs->rcvbuf = NULL;
+	ucs->rcvbuf_size = 0;
+	if (have_data) {
+		gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
+		gigaset_schedule_event(cs);
+	}
+}
+
 /* atread_submit
  * submit an HD_READ_ATMESSAGE command URB and optionally start a timeout
  * parameters:
@@ -466,7 +576,7 @@
 	if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) {
 		update_basstate(ucs, 0, BS_ATRDPEND);
 		dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n",
-			get_usb_statmsg(ret));
+			get_usb_rcmsg(ret));
 		return ret;
 	}
 
@@ -611,9 +721,12 @@
 			kfree(ucs->rcvbuf);
 			ucs->rcvbuf = NULL;
 			ucs->rcvbuf_size = 0;
-			if (rc != -ENODEV)
+			if (rc != -ENODEV) {
 				//FIXME corrective action?
+				spin_unlock_irqrestore(&cs->lock, flags);
 				error_reset(cs);
+				break;
+			}
 		}
 		spin_unlock_irqrestore(&cs->lock, flags);
 		break;
@@ -643,97 +756,6 @@
 	}
 }
 
-/* read_ctrl_callback
- * USB completion handler for control pipe input
- * called by the USB subsystem in interrupt context
- * parameter:
- *	urb	USB request block
- *		urb->context = inbuf structure for controller state
- */
-static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs)
-{
-	struct inbuf_t *inbuf = urb->context;
-	struct cardstate *cs = inbuf->cs;
-	struct bas_cardstate *ucs = cs->hw.bas;
-	int have_data = 0;
-	unsigned numbytes;
-	int rc;
-
-	update_basstate(ucs, 0, BS_ATRDPEND);
-
-	if (!ucs->rcvbuf_size) {
-		dev_warn(cs->dev, "%s: no receive in progress\n", __func__);
-		return;
-	}
-
-	del_timer(&ucs->timer_cmd_in);
-
-	switch (urb->status) {
-	case 0:				/* normal completion */
-		numbytes = urb->actual_length;
-		if (unlikely(numbytes == 0)) {
-			dev_warn(cs->dev,
-				 "control read: empty block received\n");
-			goto retry;
-		}
-		if (unlikely(numbytes != ucs->rcvbuf_size)) {
-			dev_warn(cs->dev,
-			       "control read: received %d chars, expected %d\n",
-				 numbytes, ucs->rcvbuf_size);
-			if (numbytes > ucs->rcvbuf_size)
-				numbytes = ucs->rcvbuf_size;
-		}
-
-		/* copy received bytes to inbuf */
-		have_data = gigaset_fill_inbuf(inbuf, ucs->rcvbuf, numbytes);
-
-		if (unlikely(numbytes < ucs->rcvbuf_size)) {
-			/* incomplete - resubmit for remaining bytes */
-			ucs->rcvbuf_size -= numbytes;
-			ucs->retry_cmd_in = 0;
-			goto retry;
-		}
-		break;
-
-	case -ENOENT:			/* cancelled */
-	case -ECONNRESET:		/* cancelled (async) */
-	case -EINPROGRESS:		/* pending */
-	case -ENODEV:			/* device removed */
-	case -ESHUTDOWN:		/* device shut down */
-		/* no action necessary */
-		gig_dbg(DEBUG_USBREQ, "%s: %s",
-			__func__, get_usb_statmsg(urb->status));
-		break;
-
-	default:			/* severe trouble */
-		dev_warn(cs->dev, "control read: %s\n",
-			 get_usb_statmsg(urb->status));
-	retry:
-		if (ucs->retry_cmd_in++ < BAS_RETRY) {
-			dev_notice(cs->dev, "control read: retry %d\n",
-				   ucs->retry_cmd_in);
-			rc = atread_submit(cs, BAS_TIMEOUT);
-			if (rc >= 0 || rc == -ENODEV)
-				/* resubmitted or disconnected */
-				/* - bypass regular exit block */
-				return;
-		} else {
-			dev_err(cs->dev,
-				"control read: giving up after %d tries\n",
-				ucs->retry_cmd_in);
-		}
-		error_reset(cs);
-	}
-
-	kfree(ucs->rcvbuf);
-	ucs->rcvbuf = NULL;
-	ucs->rcvbuf_size = 0;
-	if (have_data) {
-		gig_dbg(DEBUG_INTR, "%s-->BH", __func__);
-		gigaset_schedule_event(cs);
-	}
-}
-
 /* read_iso_callback
  * USB completion handler for B channel isochronous input
  * called by the USB subsystem in interrupt context
@@ -1378,6 +1400,7 @@
 	case HD_CLOSE_B1CHANNEL:
 		dev_err(bcs->cs->dev, "timeout closing channel %d\n",
 			bcs->channel + 1);
+		error_reset(bcs->cs);
 		break;
 
 	default:
@@ -1396,22 +1419,61 @@
 static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs)
 {
 	struct bas_cardstate *ucs = urb->context;
+	int rc;
 	unsigned long flags;
 
-	spin_lock_irqsave(&ucs->lock, flags);
-	if (urb->status && ucs->pending) {
-		dev_err(&ucs->interface->dev,
-			"control request 0x%02x failed: %s\n",
-			ucs->pending, get_usb_statmsg(urb->status));
-		del_timer(&ucs->timer_ctrl);
-		ucs->pending = 0;
-	}
-	/* individual handling of specific request types */
-	switch (ucs->pending) {
-	case HD_DEVICE_INIT_ACK:		/* no reply expected */
-		ucs->pending = 0;
+	/* check status */
+	switch (urb->status) {
+	case 0:					/* normal completion */
+		spin_lock_irqsave(&ucs->lock, flags);
+		switch (ucs->pending) {
+		case HD_DEVICE_INIT_ACK:	/* no reply expected */
+			del_timer(&ucs->timer_ctrl);
+			ucs->pending = 0;
+			break;
+		}
+		spin_unlock_irqrestore(&ucs->lock, flags);
+		return;
+
+	case -ENOENT:			/* cancelled */
+	case -ECONNRESET:		/* cancelled (async) */
+	case -EINPROGRESS:		/* pending */
+	case -ENODEV:			/* device removed */
+	case -ESHUTDOWN:		/* device shut down */
+		/* ignore silently */
+		gig_dbg(DEBUG_USBREQ, "%s: %s",
+			__func__, get_usb_statmsg(urb->status));
 		break;
+
+	default:				/* any failure */
+		if (++ucs->retry_ctrl > BAS_RETRY) {
+			dev_err(&ucs->interface->dev,
+				"control request 0x%02x failed: %s\n",
+				ucs->dr_ctrl.bRequest,
+				get_usb_statmsg(urb->status));
+			break;		/* give up */
+		}
+		dev_notice(&ucs->interface->dev,
+			   "control request 0x%02x: %s, retry %d\n",
+			   ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status),
+			   ucs->retry_ctrl);
+		/* urb->dev is clobbered by USB subsystem */
+		urb->dev = ucs->udev;
+		rc = usb_submit_urb(urb, SLAB_ATOMIC);
+		if (unlikely(rc)) {
+			dev_err(&ucs->interface->dev,
+				"could not resubmit request 0x%02x: %s\n",
+				ucs->dr_ctrl.bRequest, get_usb_rcmsg(rc));
+			break;
+		}
+		/* resubmitted */
+		return;
 	}
+
+	/* failed, clear pending request */
+	spin_lock_irqsave(&ucs->lock, flags);
+	del_timer(&ucs->timer_ctrl);
+	ucs->pending = 0;
 	spin_unlock_irqrestore(&ucs->lock, flags);
 }
 
@@ -1455,9 +1517,11 @@
 			     usb_sndctrlpipe(ucs->udev, 0),
 			     (unsigned char*) &ucs->dr_ctrl, NULL, 0,
 			     write_ctrl_callback, ucs);
-	if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) {
+	ucs->retry_ctrl = 0;
+	ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC);
+	if (unlikely(ret)) {
 		dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n",
-			req, get_usb_statmsg(ret));
+			req, get_usb_rcmsg(ret));
 		spin_unlock_irqrestore(&ucs->lock, flags);
 		return ret;
 	}
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index e55767b..2a56bf3 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -460,6 +460,9 @@
 
 	switch (cs->cs_init) {
 	default:
+		/* clear device sysfs */
+		gigaset_free_dev_sysfs(cs);
+
 		gigaset_if_free(cs);
 
 		gig_dbg(DEBUG_INIT, "clearing hw");
@@ -699,6 +702,7 @@
 	cs->open_count = 0;
 	cs->dev = NULL;
 	cs->tty = NULL;
+	cs->class = NULL;
 	cs->cidmode = cidmode != 0;
 
 	//if(onechannel) { //FIXME
@@ -760,6 +764,9 @@
 
 	gigaset_if_init(cs);
 
+	/* set up device sysfs */
+	gigaset_init_dev_sysfs(cs);
+
 	spin_lock_irqsave(&cs->lock, flags);
 	cs->running = 1;
 	spin_unlock_irqrestore(&cs->lock, flags);
@@ -902,9 +909,6 @@
 
 	wait_event(cs->waitqueue, !cs->waiting);
 
-	/* set up device sysfs */
-	gigaset_init_dev_sysfs(cs);
-
 	mutex_unlock(&cs->mutex);
 	return 1;
 
@@ -969,9 +973,6 @@
 		//FIXME
 	}
 
-	/* clear device sysfs */
-	gigaset_free_dev_sysfs(cs);
-
 	cleanup_cs(cs);
 
 exit:
@@ -980,7 +981,7 @@
 EXPORT_SYMBOL_GPL(gigaset_stop);
 
 static LIST_HEAD(drivers);
-static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(driver_lock);
 
 struct cardstate *gigaset_get_cs_by_id(int id)
 {
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c
index 18e05c0..44f02db 100644
--- a/drivers/isdn/gigaset/ev-layer.c
+++ b/drivers/isdn/gigaset/ev-layer.c
@@ -1262,7 +1262,8 @@
 		break;
 	case ACT_HUPMODEM:
 		/* send "+++" (hangup in unimodem mode) */
-		cs->ops->write_cmd(cs, "+++", 3, NULL);
+		if (cs->connected)
+			cs->ops->write_cmd(cs, "+++", 3, NULL);
 		break;
 	case ACT_RING:
 		/* get fresh AT state structure for new CID */
@@ -1294,7 +1295,6 @@
 		break;
 	case ACT_ICALL:
 		handle_icall(cs, bcs, p_at_state);
-		at_state = *p_at_state;
 		break;
 	case ACT_FAILSDOWN:
 		dev_warn(cs->dev, "Could not shut down the device.\n");
@@ -1334,10 +1334,8 @@
 			 */
 			at_state->pending_commands |= PC_DLE0;
 			atomic_set(&cs->commands_pending, 1);
-		} else {
+		} else
 			disconnect(p_at_state);
-			at_state = *p_at_state;
-		}
 		break;
 	case ACT_FAKEDLE0:
 		at_state->int_var[VAR_ZDLE] = 0;
@@ -1354,10 +1352,8 @@
 		at_state->cid = -1;
 		if (bcs && cs->onechannel)
 			at_state->pending_commands |= PC_DLE0;
-		else {
+		else
 			disconnect(p_at_state);
-			at_state = *p_at_state;
-		}
 		schedule_init(cs, MS_RECOVER);
 		break;
 	case ACT_FAILDLE0:
@@ -1410,7 +1406,6 @@
 
 	case ACT_ABORTACCEPT:	/* hangup/error/timeout during ICALL processing */
 		disconnect(p_at_state);
-		at_state = *p_at_state;
 		break;
 
 	case ACT_ABORTDIAL:	/* error/timeout during dial preparation */
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h
index 22b9693..8d63d82 100644
--- a/drivers/isdn/gigaset/gigaset.h
+++ b/drivers/isdn/gigaset/gigaset.h
@@ -445,6 +445,7 @@
 	struct gigaset_driver *driver;
 	unsigned minor_index;
 	struct device *dev;
+	struct class_device *class;
 
 	const struct gigaset_ops *ops;
 
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index 08e4c4e..74fd234 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -625,7 +625,14 @@
 		return;
 
 	tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
-	tty_register_device(drv->tty, cs->minor_index, NULL);
+	cs->class = tty_register_device(drv->tty, cs->minor_index, NULL);
+
+	if (!IS_ERR(cs->class))
+		class_set_devdata(cs->class, cs);
+	else {
+		warn("could not register device to the tty subsystem");
+		cs->class = NULL;
+	}
 }
 
 void gigaset_if_free(struct cardstate *cs)
@@ -638,6 +645,7 @@
 
 	tasklet_disable(&cs->if_wake_tasklet);
 	tasklet_kill(&cs->if_wake_tasklet);
+	cs->class = NULL;
 	tty_unregister_device(drv->tty, cs->minor_index);
 }
 
diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c
index d267a63..9ae3a7f 100644
--- a/drivers/isdn/gigaset/proc.c
+++ b/drivers/isdn/gigaset/proc.c
@@ -16,12 +16,11 @@
 #include "gigaset.h"
 #include <linux/ctype.h>
 
-static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr,
-			    char *buf)
+static ssize_t show_cidmode(struct class_device *class, char *buf)
 {
 	int ret;
 	unsigned long flags;
-	struct cardstate *cs = dev_get_drvdata(dev);
+	struct cardstate *cs = class_get_devdata(class);
 
 	spin_lock_irqsave(&cs->lock, flags);
 	ret = sprintf(buf, "%u\n", cs->cidmode);
@@ -30,10 +29,10 @@
 	return ret;
 }
 
-static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
+static ssize_t set_cidmode(struct class_device *class,
 			   const char *buf, size_t count)
 {
-	struct cardstate *cs = dev_get_drvdata(dev);
+	struct cardstate *cs = class_get_devdata(class);
 	long int value;
 	char *end;
 
@@ -65,18 +64,24 @@
 	return count;
 }
 
-static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
+static CLASS_DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
 
 /* free sysfs for device */
 void gigaset_free_dev_sysfs(struct cardstate *cs)
 {
+	if (!cs->class)
+		return;
+
 	gig_dbg(DEBUG_INIT, "removing sysfs entries");
-	device_remove_file(cs->dev, &dev_attr_cidmode);
+	class_device_remove_file(cs->class, &class_device_attr_cidmode);
 }
 
 /* initialize sysfs for device */
 void gigaset_init_dev_sysfs(struct cardstate *cs)
 {
+	if (!cs->class)
+		return;
+
 	gig_dbg(DEBUG_INIT, "setting up sysfs");
-	device_create_file(cs->dev, &dev_attr_cidmode);
+	class_device_create_file(cs->class, &class_device_attr_cidmode);
 }
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index abecabf..aacbf0d 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -1402,12 +1402,12 @@
 			}
 			/* No, locate it in the table */
 			if (cset == 0) {
-				for (i = 0; i < IESIZE; i++)
+				for (i = 0; i < IESIZE_NI1; i++)
 					if (*buf == ielist_ni1[i].nr)
 						break;
 
 				/* When not found, give appropriate msg */
-				if (i != IESIZE) {
+				if (i != IESIZE_NI1) {
 					dp += sprintf(dp, "  %s\n", ielist_ni1[i].descr);
 					dp += ielist_ni1[i].f(dp, buf);
 				} else
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 22759c0..b26e509 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -933,7 +933,7 @@
 			count_put = count_pull;
 			if(count_put > 1)
 				tty_insert_flip_string(tty, skb->data, count_put - 1);
-			last = skb->data[count_put] - 1;
+			last = skb->data[count_put - 1];
 			len -= count_put;
 #ifdef CONFIG_ISDN_AUDIO
 		}
@@ -1177,9 +1177,8 @@
 			goto out;
 		}
 		chidx = isdn_minor2chan(minor);
-		while (isdn_writebuf_stub(drvidx, chidx, buf, count) != count)
+		while ((retval = isdn_writebuf_stub(drvidx, chidx, buf, count)) == 0)
 			interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
-		retval = count;
 		goto out;
 	}
 	if (minor <= ISDN_MINOR_CTRLMAX) {
@@ -1951,9 +1950,10 @@
 	struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
 
 	if (!skb)
-		return 0;
+		return -ENOMEM;
 	skb_reserve(skb, hl);
-	copy_from_user(skb_put(skb, len), buf, len);
+	if (copy_from_user(skb_put(skb, len), buf, len))
+		return -EFAULT;
 	ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
 	if (ret <= 0)
 		dev_kfree_skb(skb);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 2ac9024..433389d 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -82,7 +82,7 @@
 						int l = skb->len;
 						unsigned char *dp = skb->data;
 						while (--l) {
-							if (*skb->data == DLE)
+							if (*dp == DLE)
 								tty_insert_flip_char(tty, DLE, 0);
 							tty_insert_flip_char(tty, *dp++, 0);
 						}
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index f4f7122..57c4ab9 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -97,6 +97,7 @@
 
 	case SCIOCSTART:
 	{
+		kfree(rcvmsg);
 		pr_debug("%s: SCIOSTART: ioctl received\n",
 				sc_adapter[card]->devicename);
 		if(sc_adapter[card]->EngineUp) {
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 6265062..9650998 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -63,6 +63,12 @@
 	  This option enables support for LEDs connected to GPIO lines
 	  on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
 
+config LEDS_AMS_DELTA
+	tristate "LED Support for the Amstrad Delta (E3)"
+	depends LEDS_CLASS && MACH_AMS_DELTA
+	help
+	  This option enables support for the LEDs on Amstrad Delta (E3).
+
 comment "LED Triggers"
 
 config LEDS_TRIGGERS
@@ -87,5 +93,14 @@
 	  This allows LEDs to be controlled by IDE disk activity.
 	  If unsure, say Y.
 
+config LEDS_TRIGGER_HEARTBEAT
+	tristate "LED Heartbeat Trigger"
+	depends LEDS_TRIGGERS
+	help
+	  This allows LEDs to be controlled by a CPU load average.
+	  The flash frequency is a hyperbolic function of the 1-minute
+	  load average.
+	  If unsure, say Y.
+
 endmenu
 
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 40f0426..88d3b6e 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -11,7 +11,9 @@
 obj-$(CONFIG_LEDS_IXP4XX)		+= leds-ixp4xx-gpio.o
 obj-$(CONFIG_LEDS_TOSA)			+= leds-tosa.o
 obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
+obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
 
 # LED Triggers
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
 obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o
+obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index fe65413..9b015f9 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -18,7 +18,7 @@
 #include <linux/leds.h>
 #include "leds.h"
 
-rwlock_t leds_list_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(leds_list_lock);
 LIST_HEAD(leds_list);
 
 EXPORT_SYMBOL_GPL(leds_list);
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 5e2cd8b..1b1ce65 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -26,7 +26,7 @@
 /*
  * Nests outside led_cdev->trigger_lock
  */
-static rwlock_t triggers_list_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(triggers_list_lock);
 static LIST_HEAD(trigger_list);
 
 ssize_t led_trigger_store(struct class_device *dev, const char *buf,
diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c
new file mode 100644
index 0000000..e9f0611
--- /dev/null
+++ b/drivers/leds/leds-ams-delta.c
@@ -0,0 +1,162 @@
+/*
+ * LEDs driver for Amstrad Delta (E3)
+ *
+ * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <asm/arch/board-ams-delta.h>
+
+/*
+ * Our context
+ */
+struct ams_delta_led {
+	struct led_classdev	cdev;
+	u8			bitmask;
+};
+
+static void ams_delta_led_set(struct led_classdev *led_cdev,
+		enum led_brightness value)
+{
+	struct ams_delta_led *led_dev =
+		container_of(led_cdev, struct ams_delta_led, cdev);
+
+	if (value)
+		ams_delta_latch1_write(led_dev->bitmask, led_dev->bitmask);
+	else
+		ams_delta_latch1_write(led_dev->bitmask, 0);
+}
+
+static struct ams_delta_led ams_delta_leds[] = {
+	{
+		.cdev		= {
+			.name		= "ams-delta:camera",
+			.brightness_set = ams_delta_led_set,
+		},
+		.bitmask	= AMS_DELTA_LATCH1_LED_CAMERA,
+	},
+	{
+		.cdev		= {
+			.name		= "ams-delta:advert",
+			.brightness_set = ams_delta_led_set,
+		},
+		.bitmask	= AMS_DELTA_LATCH1_LED_ADVERT,
+	},
+	{
+		.cdev		= {
+			.name		= "ams-delta:email",
+			.brightness_set = ams_delta_led_set,
+		},
+		.bitmask	= AMS_DELTA_LATCH1_LED_EMAIL,
+	},
+	{
+		.cdev		= {
+			.name		= "ams-delta:handsfree",
+			.brightness_set = ams_delta_led_set,
+		},
+		.bitmask	= AMS_DELTA_LATCH1_LED_HANDSFREE,
+	},
+	{
+		.cdev		= {
+			.name		= "ams-delta:voicemail",
+			.brightness_set = ams_delta_led_set,
+		},
+		.bitmask	= AMS_DELTA_LATCH1_LED_VOICEMAIL,
+	},
+	{
+		.cdev		= {
+			.name		= "ams-delta:voice",
+			.brightness_set = ams_delta_led_set,
+		},
+		.bitmask	= AMS_DELTA_LATCH1_LED_VOICE,
+	},
+};
+
+#ifdef CONFIG_PM
+static int ams_delta_led_suspend(struct platform_device *dev,
+		pm_message_t state)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
+		led_classdev_suspend(&ams_delta_leds[i].cdev);
+
+	return 0;
+}
+
+static int ams_delta_led_resume(struct platform_device *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
+		led_classdev_resume(&ams_delta_leds[i].cdev);
+
+	return 0;
+}
+#else
+#define ams_delta_led_suspend NULL
+#define ams_delta_led_resume NULL
+#endif
+
+static int ams_delta_led_probe(struct platform_device *pdev)
+{
+	int i;
+	int ret;
+
+	for (i = ret = 0; ret >= 0 && i < ARRAY_SIZE(ams_delta_leds); i++) {
+		ret = led_classdev_register(&pdev->dev,
+				&ams_delta_leds[i].cdev);
+	}
+
+	if (ret < 0 && i > 1) {
+		for (i = i - 2; i >= 0; i--)
+			led_classdev_unregister(&ams_delta_leds[i].cdev);
+	}
+
+	return ret;
+}
+
+static int ams_delta_led_remove(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(ams_delta_leds) - 1; i >= 0; i--)
+		led_classdev_unregister(&ams_delta_leds[i].cdev);
+
+	return 0;
+}
+
+static struct platform_driver ams_delta_led_driver = {
+	.probe		= ams_delta_led_probe,
+	.remove		= ams_delta_led_remove,
+	.suspend	= ams_delta_led_suspend,
+	.resume		= ams_delta_led_resume,
+	.driver		= {
+		.name = "ams-delta-led",
+	},
+};
+
+static int __init ams_delta_led_init(void)
+{
+	return platform_driver_register(&ams_delta_led_driver);
+}
+
+static void __exit ams_delta_led_exit(void)
+{
+	return platform_driver_unregister(&ams_delta_led_driver);
+}
+
+module_init(ams_delta_led_init);
+module_exit(ams_delta_led_exit);
+
+MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
+MODULE_DESCRIPTION("Amstrad Delta LED driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/leds/leds-locomo.c b/drivers/leds/leds-locomo.c
index 749a86c..8419e29 100644
--- a/drivers/leds/leds-locomo.c
+++ b/drivers/leds/leds-locomo.c
@@ -45,11 +45,13 @@
 
 static struct led_classdev locomo_led0 = {
 	.name			= "locomo:amber",
+	.default_trigger	= "sharpsl-charge",
 	.brightness_set		= locomoled_brightness_set0,
 };
 
 static struct led_classdev locomo_led1 = {
 	.name			= "locomo:green",
+	.default_trigger	= "nand-disk",
 	.brightness_set		= locomoled_brightness_set1,
 };
 
diff --git a/drivers/leds/ledtrig-heartbeat.c b/drivers/leds/ledtrig-heartbeat.c
new file mode 100644
index 0000000..4bf8cec
--- /dev/null
+++ b/drivers/leds/ledtrig-heartbeat.c
@@ -0,0 +1,118 @@
+/*
+ * LED Heartbeat Trigger
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * Based on Richard Purdie's ledtrig-timer.c and some arch's
+ * CONFIG_HEARTBEAT code.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+struct heartbeat_trig_data {
+	unsigned int phase;
+	unsigned int period;
+	struct timer_list timer;
+};
+
+static void led_heartbeat_function(unsigned long data)
+{
+	struct led_classdev *led_cdev = (struct led_classdev *) data;
+	struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+	unsigned long brightness = LED_OFF;
+	unsigned long delay = 0;
+
+	/* acts like an actual heart beat -- ie thump-thump-pause... */
+	switch (heartbeat_data->phase) {
+	case 0:
+		/*
+		 * The hyperbolic function below modifies the
+		 * heartbeat period length in dependency of the
+		 * current (1min) load. It goes through the points
+		 * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
+		 */
+		heartbeat_data->period = 300 +
+			(6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
+		heartbeat_data->period =
+			msecs_to_jiffies(heartbeat_data->period);
+		delay = msecs_to_jiffies(70);
+		heartbeat_data->phase++;
+		brightness = LED_FULL;
+		break;
+	case 1:
+		delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
+		heartbeat_data->phase++;
+		break;
+	case 2:
+		delay = msecs_to_jiffies(70);
+		heartbeat_data->phase++;
+		brightness = LED_FULL;
+		break;
+	default:
+		delay = heartbeat_data->period - heartbeat_data->period / 4 -
+			msecs_to_jiffies(70);
+		heartbeat_data->phase = 0;
+		break;
+	}
+
+	led_set_brightness(led_cdev, brightness);
+	mod_timer(&heartbeat_data->timer, jiffies + delay);
+}
+
+static void heartbeat_trig_activate(struct led_classdev *led_cdev)
+{
+	struct heartbeat_trig_data *heartbeat_data;
+
+	heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
+	if (!heartbeat_data)
+		return;
+
+	led_cdev->trigger_data = heartbeat_data;
+	setup_timer(&heartbeat_data->timer,
+		    led_heartbeat_function, (unsigned long) led_cdev);
+	heartbeat_data->phase = 0;
+	led_heartbeat_function(heartbeat_data->timer.data);
+}
+
+static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
+{
+	struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+
+	if (heartbeat_data) {
+		del_timer_sync(&heartbeat_data->timer);
+		kfree(heartbeat_data);
+	}
+}
+
+static struct led_trigger heartbeat_led_trigger = {
+	.name     = "heartbeat",
+	.activate = heartbeat_trig_activate,
+	.deactivate = heartbeat_trig_deactivate,
+};
+
+static int __init heartbeat_trig_init(void)
+{
+	return led_trigger_register(&heartbeat_led_trigger);
+}
+
+static void __exit heartbeat_trig_exit(void)
+{
+	led_trigger_unregister(&heartbeat_led_trigger);
+}
+
+module_init(heartbeat_trig_init);
+module_exit(heartbeat_trig_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Heartbeat LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index 12ad462..37cd6ee 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -99,17 +99,22 @@
 	  devices are not fully supported in the bay as I never had one to
 	  try with
 
-# made a separate option since backlight may end up beeing used
-# on non-powerbook machines (but only on PMU based ones AFAIK)
 config PMAC_BACKLIGHT
 	bool "Backlight control for LCD screens"
 	depends on ADB_PMU && (BROKEN || !PPC64)
 	help
-	  Say Y here to build in code to manage the LCD backlight on a
-	  Macintosh PowerBook.  With this code, the backlight will be turned
-	  on and off appropriately on power-management and lid-open/lid-closed
-	  events; also, the PowerBook button device will be enabled so you can
-	  change the screen brightness.
+	  Say Y here to enable Macintosh specific extensions of the generic
+	  backlight code. With this enabled, the brightness keys on older
+	  PowerBooks will be enabled so you can change the screen brightness.
+	  Newer models should use an userspace daemon like pbbuttonsd.
+
+config PMAC_BACKLIGHT_LEGACY
+	bool "Provide legacy ioctl's on /dev/pmu for the backlight"
+	depends on PMAC_BACKLIGHT && (BROKEN || !PPC64)
+	help
+	  Say Y if you want to enable legacy ioctl's on /dev/pmu. This is for
+	  programs which use this old interface. New and updated programs
+	  should use the backlight classes in sysfs.
 
 config ADB_MACIO
 	bool "Include MacIO (CHRP) ADB driver"
@@ -171,6 +176,7 @@
 
 config WINDFARM
 	tristate "New PowerMac thermal control infrastructure"
+	depends on PPC
 
 config WINDFARM_PM81
 	tristate "Support for thermal management on iMac G5"
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6081acd..45a268f 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -11,7 +11,8 @@
 obj-$(CONFIG_INPUT_ADBHID)	+= adbhid.o
 obj-$(CONFIG_ANSLCD)		+= ans-lcd.o
 
-obj-$(CONFIG_ADB_PMU)		+= via-pmu.o
+obj-$(CONFIG_ADB_PMU)		+= via-pmu.o via-pmu-event.o
+obj-$(CONFIG_PMAC_BACKLIGHT)	+= via-pmu-backlight.o
 obj-$(CONFIG_ADB_CUDA)		+= via-cuda.o
 obj-$(CONFIG_PMAC_APM_EMU)	+= apm_emu.o
 obj-$(CONFIG_PMAC_SMU)		+= smu.o
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 394334e..cbfbbe2 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -179,7 +179,7 @@
 	/* 0x65 */ KEY_F9,		/*  67 */
 	/* 0x66 */ KEY_HANJA,		/* 123 */
 	/* 0x67 */ KEY_F11,		/*  87 */
-	/* 0x68 */ KEY_HANGUEL,		/* 122 */
+	/* 0x68 */ KEY_HANGEUL,		/* 122 */
 	/* 0x69 */ KEY_SYSRQ,		/*  99 */
 	/* 0x6a */ 0,
 	/* 0x6b */ KEY_SCROLLLOCK,	/*  70 */
@@ -503,9 +503,7 @@
 	case 0x1f: /* Powerbook button device */
 	  {
 		int down = (data[1] == (data[1] & 0xf));
-#ifdef CONFIG_PMAC_BACKLIGHT
-		int backlight = get_backlight_level();
-#endif
+
 		/*
 		 * XXX: Where is the contrast control for the passive?
 		 *  -- Cort
@@ -530,29 +528,17 @@
 
 		case 0xa:	/* brightness decrease */
 #ifdef CONFIG_PMAC_BACKLIGHT
-			if (!disable_kernel_backlight) {
-				if (down && backlight >= 0) {
-					if (backlight > BACKLIGHT_OFF)
-						set_backlight_level(backlight-1);
-					else
-						set_backlight_level(BACKLIGHT_OFF);
-				}
-			}
-#endif /* CONFIG_PMAC_BACKLIGHT */
+			if (!disable_kernel_backlight && down)
+				pmac_backlight_key_down();
+#endif
 			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
 			break;
 
 		case 0x9:	/* brightness increase */
 #ifdef CONFIG_PMAC_BACKLIGHT
-			if (!disable_kernel_backlight) {
-				if (down && backlight >= 0) {
-					if (backlight < BACKLIGHT_MAX)
-						set_backlight_level(backlight+1);
-					else 
-						set_backlight_level(BACKLIGHT_MAX);
-				}
-			}
-#endif /* CONFIG_PMAC_BACKLIGHT */
+			if (!disable_kernel_backlight && down)
+				pmac_backlight_key_up();
+#endif
 			input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
 			break;
 
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
new file mode 100644
index 0000000..b42d05f
--- /dev/null
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -0,0 +1,150 @@
+/*
+ * Backlight code for via-pmu
+ *
+ * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
+ * Copyright (C) 2001-2002 Benjamin Herrenschmidt
+ * Copyright (C) 2006      Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ */
+
+#include <asm/ptrace.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/backlight.h>
+#include <asm/prom.h>
+
+#define MAX_PMU_LEVEL 0xFF
+
+static struct device_node *vias;
+static struct backlight_properties pmu_backlight_data;
+
+static int pmu_backlight_get_level_brightness(struct fb_info *info,
+		int level)
+{
+	int pmulevel;
+
+	/* Get and convert the value */
+	mutex_lock(&info->bl_mutex);
+	pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
+	mutex_unlock(&info->bl_mutex);
+
+	if (pmulevel < 0)
+		pmulevel = 0;
+	else if (pmulevel > MAX_PMU_LEVEL)
+		pmulevel = MAX_PMU_LEVEL;
+
+	return pmulevel;
+}
+
+static int pmu_backlight_update_status(struct backlight_device *bd)
+{
+	struct fb_info *info = class_get_devdata(&bd->class_dev);
+	struct adb_request req;
+	int pmulevel, level = bd->props->brightness;
+
+	if (vias == NULL)
+		return -ENODEV;
+
+	if (bd->props->power != FB_BLANK_UNBLANK ||
+	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+
+	pmulevel = pmu_backlight_get_level_brightness(info, level);
+
+	pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
+	pmu_wait_complete(&req);
+
+	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+		PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF));
+	pmu_wait_complete(&req);
+
+	return 0;
+}
+
+static int pmu_backlight_get_brightness(struct backlight_device *bd)
+{
+	return bd->props->brightness;
+}
+
+static struct backlight_properties pmu_backlight_data = {
+	.owner		= THIS_MODULE,
+	.get_brightness	= pmu_backlight_get_brightness,
+	.update_status	= pmu_backlight_update_status,
+	.max_brightness	= (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void __init pmu_backlight_init(struct device_node *in_vias)
+{
+	struct backlight_device *bd;
+	struct fb_info *info;
+	char name[10];
+	int level, autosave;
+
+	vias = in_vias;
+
+	/* Special case for the old PowerBook since I can't test on it */
+	autosave =
+		machine_is_compatible("AAPL,3400/2400") ||
+		machine_is_compatible("AAPL,3500");
+
+	if (!autosave &&
+	    !pmac_has_backlight_type("pmu") &&
+	    !machine_is_compatible("AAPL,PowerBook1998") &&
+	    !machine_is_compatible("PowerBook1,1"))
+		return;
+
+	/* Actually, this is a hack, but I don't know of a better way
+	 * to get the first framebuffer device.
+	 */
+	info = registered_fb[0];
+	if (!info) {
+		printk("pmubl: No framebuffer found\n");
+		goto error;
+	}
+
+	snprintf(name, sizeof(name), "pmubl%d", info->node);
+
+	bd = backlight_device_register(name, info, &pmu_backlight_data);
+	if (IS_ERR(bd)) {
+		printk("pmubl: Backlight registration failed\n");
+		goto error;
+	}
+
+	mutex_lock(&info->bl_mutex);
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0x7F, 0x46, 0x0E);
+	mutex_unlock(&info->bl_mutex);
+
+	level = pmu_backlight_data.max_brightness;
+
+	if (autosave) {
+		/* read autosaved value if available */
+		struct adb_request req;
+		pmu_request(&req, NULL, 2, 0xd9, 0);
+		pmu_wait_complete(&req);
+
+		mutex_lock(&info->bl_mutex);
+		level = pmac_backlight_curve_lookup(info,
+				(req.reply[0] >> 4) *
+				pmu_backlight_data.max_brightness / 15);
+		mutex_unlock(&info->bl_mutex);
+	}
+
+	up(&bd->sem);
+	bd->props->brightness = level;
+	bd->props->power = FB_BLANK_UNBLANK;
+	bd->props->update_status(bd);
+	down(&bd->sem);
+
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = bd;
+	mutex_unlock(&pmac_backlight_mutex);
+
+	printk("pmubl: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
diff --git a/drivers/macintosh/via-pmu-event.c b/drivers/macintosh/via-pmu-event.c
new file mode 100644
index 0000000..25cd565
--- /dev/null
+++ b/drivers/macintosh/via-pmu-event.c
@@ -0,0 +1,80 @@
+/*
+ * via-pmu event device for reporting some events that come through the PMU
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ */
+
+#include <linux/input.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include "via-pmu-event.h"
+
+static struct input_dev *pmu_input_dev;
+
+static int __init via_pmu_event_init(void)
+{
+	int err;
+
+	/* do other models report button/lid status? */
+	if (pmu_get_model() != PMU_KEYLARGO_BASED)
+		return -ENODEV;
+
+	pmu_input_dev = input_allocate_device();
+	if (!pmu_input_dev)
+		return -ENOMEM;
+
+	pmu_input_dev->name = "PMU";
+	pmu_input_dev->id.bustype = BUS_HOST;
+	pmu_input_dev->id.vendor = 0x0001;
+	pmu_input_dev->id.product = 0x0001;
+	pmu_input_dev->id.version = 0x0100;
+
+	set_bit(EV_KEY, pmu_input_dev->evbit);
+	set_bit(EV_SW, pmu_input_dev->evbit);
+	set_bit(KEY_POWER, pmu_input_dev->keybit);
+	set_bit(SW_LID, pmu_input_dev->swbit);
+
+	err = input_register_device(pmu_input_dev);
+	if (err)
+		input_free_device(pmu_input_dev);
+	return err;
+}
+
+void via_pmu_event(int key, int down)
+{
+
+	if (unlikely(!pmu_input_dev))
+		return;
+
+	switch (key) {
+	case PMU_EVT_POWER:
+		input_report_key(pmu_input_dev, KEY_POWER, down);
+		break;
+	case PMU_EVT_LID:
+		input_report_switch(pmu_input_dev, SW_LID, down);
+		break;
+	default:
+		/* no such key handled */
+		return;
+	}
+
+	input_sync(pmu_input_dev);
+}
+
+late_initcall(via_pmu_event_init);
diff --git a/drivers/macintosh/via-pmu-event.h b/drivers/macintosh/via-pmu-event.h
new file mode 100644
index 0000000..72c54de
--- /dev/null
+++ b/drivers/macintosh/via-pmu-event.h
@@ -0,0 +1,8 @@
+#ifndef __VIA_PMU_EVENT_H
+#define __VIA_PMU_EVENT_H
+
+#define PMU_EVT_POWER	0
+#define PMU_EVT_LID	1
+extern void via_pmu_event(int key, int down);
+
+#endif /* __VIA_PMU_EVENT_H */
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 0b5ff55..1ab4f16c 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -69,6 +69,8 @@
 #include <asm/open_pic.h>
 #endif
 
+#include "via-pmu-event.h"
+
 /* Some compile options */
 #undef SUSPEND_USES_PMU
 #define DEBUG_SLEEP
@@ -144,7 +146,6 @@
 static int data_len;
 static volatile int adb_int_pending;
 static volatile int disable_poll;
-static struct adb_request bright_req_1, bright_req_2;
 static struct device_node *vias;
 static int pmu_kind = PMU_UNKNOWN;
 static int pmu_fully_inited = 0;
@@ -161,7 +162,7 @@
 #if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 static int option_lid_wakeup = 1;
 #endif /* CONFIG_PM && CONFIG_PPC32 */
-#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT)
+#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
 static int sleep_in_progress;
 #endif
 static unsigned long async_req_locks;
@@ -208,10 +209,6 @@
 			  int count, int *eof, void *data);
 static int proc_get_irqstats(char *page, char **start, off_t off,
 			  int count, int *eof, void *data);
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int pmu_set_backlight_level(int level, void* data);
-static int pmu_set_backlight_enable(int on, int level, void* data);
-#endif /* CONFIG_PMAC_BACKLIGHT */
 static void pmu_pass_intr(unsigned char *data, int len);
 static int proc_get_batt(char *page, char **start, off_t off,
 			int count, int *eof, void *data);
@@ -292,13 +289,6 @@
 	"Core99"
 };
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-static struct backlight_controller pmu_backlight_controller = {
-	pmu_set_backlight_enable,
-	pmu_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
 int __init find_via_pmu(void)
 {
 	u64 taddr;
@@ -417,8 +407,6 @@
 	if (vias == NULL)
 		return -ENODEV;
 
-	bright_req_1.complete = 1;
-	bright_req_2.complete = 1;
 	batt_req.complete = 1;
 
 #ifndef CONFIG_PPC_MERGE
@@ -483,9 +471,9 @@
 		return -ENODEV;
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	/* Enable backlight */
-	register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
-#endif /* CONFIG_PMAC_BACKLIGHT */
+	/* Initialize backlight */
+	pmu_backlight_init(vias);
+#endif
 
 #ifdef CONFIG_PPC32
   	if (machine_is_compatible("AAPL,3400/2400") ||
@@ -1424,7 +1412,7 @@
 #ifdef CONFIG_INPUT_ADBHID
 			if (!disable_kernel_backlight)
 #endif /* CONFIG_INPUT_ADBHID */
-				set_backlight_level(data[1] >> 4);
+				pmac_backlight_set_legacy_brightness(data[1] >> 4);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 	}
 	/* Tick interrupt */
@@ -1441,6 +1429,12 @@
 		if (pmu_battery_count)
 			query_battery_state();
 		pmu_pass_intr(data, len);
+		/* len == 6 is probably a bad check. But how do I
+		 * know what PMU versions send what events here? */
+		if (len == 6) {
+			via_pmu_event(PMU_EVT_POWER, !!(data[1]&8));
+			via_pmu_event(PMU_EVT_LID, data[1]&1);
+		}
 	} else {
 	       pmu_pass_intr(data, len);
 	}
@@ -1674,61 +1668,6 @@
 	return IRQ_NONE;
 }
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight_to_bright[] = {
-	0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,
-	0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e
-};
- 
-static int
-pmu_set_backlight_enable(int on, int level, void* data)
-{
-	struct adb_request req;
-	
-	if (vias == NULL)
-		return -ENODEV;
-
-	if (on) {
-		pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
-			    backlight_to_bright[level]);
-		pmu_wait_complete(&req);
-	}
-	pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
-		    PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));
-       	pmu_wait_complete(&req);
-
-	return 0;
-}
-
-static void
-pmu_bright_complete(struct adb_request *req)
-{
-	if (req == &bright_req_1)
-		clear_bit(1, &async_req_locks);
-	if (req == &bright_req_2)
-		clear_bit(2, &async_req_locks);
-}
-
-static int
-pmu_set_backlight_level(int level, void* data)
-{
-	if (vias == NULL)
-		return -ENODEV;
-
-	if (test_and_set_bit(1, &async_req_locks))
-		return -EAGAIN;
-	pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT,
-		backlight_to_bright[level]);
-	if (test_and_set_bit(2, &async_req_locks))
-		return -EAGAIN;
-	pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL,
-		    PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ?
-					 PMU_POW_ON : PMU_POW_OFF));
-
-	return 0;
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
 void
 pmu_enable_irled(int on)
 {
@@ -2145,9 +2084,8 @@
 		return -EBUSY;
 	}
 
-	/* Wait for completion of async backlight requests */
-	while (!bright_req_1.complete || !bright_req_2.complete ||
-			!batt_req.complete)
+	/* Wait for completion of async requests */
+	while (!batt_req.complete)
 		pmu_poll();
 
 	/* Giveup the lazy FPU & vec so we don't have to back them
@@ -2268,7 +2206,7 @@
  		_set_L2CR(save_l2cr);
 	
 	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
+	set_context(current->active_mm->context.id, current->active_mm->pgd);
 
 	/* Power things up */
 	pmu_unlock();
@@ -2366,7 +2304,7 @@
  		_set_L3CR(save_l3cr);
 	
 	/* Restore userland MMU context */
-	set_context(current->active_mm->context, current->active_mm->pgd);
+	set_context(current->active_mm->context.id, current->active_mm->pgd);
 
 	/* Tell PMU we are ready */
 	pmu_unlock();
@@ -2678,26 +2616,34 @@
 			return put_user(1, argp);
 #endif /* CONFIG_PM && CONFIG_PPC32 */
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Backlight should have its own device or go via
-	 * the fbdev
-	 */
+#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
+	/* Compatibility ioctl's for backlight */
 	case PMU_IOC_GET_BACKLIGHT:
+	{
+		int brightness;
+
 		if (sleep_in_progress)
 			return -EBUSY;
-		error = get_backlight_level();
-		if (error < 0)
-			return error;
-		return put_user(error, argp);
+
+		brightness = pmac_backlight_get_legacy_brightness();
+		if (brightness < 0)
+			return brightness;
+		else
+			return put_user(brightness, argp);
+
+	}
 	case PMU_IOC_SET_BACKLIGHT:
 	{
-		__u32 value;
+		int brightness;
+
 		if (sleep_in_progress)
 			return -EBUSY;
-		error = get_user(value, argp);
-		if (!error)
-			error = set_backlight_level(value);
-		break;
+
+		error = get_user(brightness, argp);
+		if (error)
+			return error;
+
+		return pmac_backlight_set_legacy_brightness(brightness);
 	}
 #ifdef CONFIG_INPUT_ADBHID
 	case PMU_IOC_GRAB_BACKLIGHT: {
@@ -2713,7 +2659,7 @@
 		return 0;
 	}
 #endif /* CONFIG_INPUT_ADBHID */
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
 	case PMU_IOC_GET_MODEL:
 	    	return put_user(pmu_kind, argp);
 	case PMU_IOC_HAS_ADB:
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index ac25a48..bf869ed 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -90,7 +90,7 @@
 	depends on BLK_DEV_MD && EXPERIMENTAL
 	---help---
 	  RAID-10 provides a combination of striping (RAID-0) and
-	  mirroring (RAID-1) with easier configuration and more flexable
+	  mirroring (RAID-1) with easier configuration and more flexible
 	  layout.
 	  Unlike RAID-0, but like RAID-1, RAID-10 requires all devices to
 	  be the same size (or at least, only as much as the smallest device
@@ -104,8 +104,8 @@
 
 	  If unsure, say Y.
 
-config MD_RAID5
-	tristate "RAID-4/RAID-5 mode"
+config MD_RAID456
+	tristate "RAID-4/RAID-5/RAID-6 mode"
 	depends on BLK_DEV_MD
 	---help---
 	  A RAID-5 set of N drives with a capacity of C MB per drive provides
@@ -116,20 +116,28 @@
 	  while a RAID-5 set distributes the parity across the drives in one
 	  of the available parity distribution methods.
 
+	  A RAID-6 set of N drives with a capacity of C MB per drive
+	  provides the capacity of C * (N - 2) MB, and protects
+	  against a failure of any two drives. For a given sector
+	  (row) number, (N - 2) drives contain data sectors, and two
+	  drives contains two independent redundancy syndromes.  Like
+	  RAID-5, RAID-6 distributes the syndromes across the drives
+	  in one of the available parity distribution methods.
+
 	  Information about Software RAID on Linux is contained in the
 	  Software-RAID mini-HOWTO, available from
 	  <http://www.tldp.org/docs.html#howto>. There you will also
 	  learn where to get the supporting user space utilities raidtools.
 
-	  If you want to use such a RAID-4/RAID-5 set, say Y.  To
+	  If you want to use such a RAID-4/RAID-5/RAID-6 set, say Y.  To
 	  compile this code as a module, choose M here: the module
-	  will be called raid5.
+	  will be called raid456.
 
 	  If unsure, say Y.
 
 config MD_RAID5_RESHAPE
 	bool "Support adding drives to a raid-5 array (experimental)"
-	depends on MD_RAID5 && EXPERIMENTAL
+	depends on MD_RAID456 && EXPERIMENTAL
 	---help---
 	  A RAID-5 set can be expanded by adding extra drives. This
 	  requires "restriping" the array which means (almost) every
@@ -139,7 +147,7 @@
 	  is online.  However it is still EXPERIMENTAL code.  It should
 	  work, but please be sure that you have backups.
 
-	  You will need mdadm verion 2.4.1 or later to use this
+	  You will need mdadm version 2.4.1 or later to use this
 	  feature safely.  During the early stage of reshape there is
 	  a critical section where live data is being over-written.  A
 	  crash during this time needs extra care for recovery.  The
@@ -154,28 +162,6 @@
 	  There should be enough spares already present to make the new
 	  array workable.
 
-config MD_RAID6
-	tristate "RAID-6 mode"
-	depends on BLK_DEV_MD
-	---help---
-	  A RAID-6 set of N drives with a capacity of C MB per drive
-	  provides the capacity of C * (N - 2) MB, and protects
-	  against a failure of any two drives. For a given sector
-	  (row) number, (N - 2) drives contain data sectors, and two
-	  drives contains two independent redundancy syndromes.  Like
-	  RAID-5, RAID-6 distributes the syndromes across the drives
-	  in one of the available parity distribution methods.
-
-	  RAID-6 requires mdadm-1.5.0 or later, available at:
-
-	  ftp://ftp.kernel.org/pub/linux/utils/raid/mdadm/
-
-	  If you want to use such a RAID-6 set, say Y.  To compile
-	  this code as a module, choose M here: the module will be
-	  called raid6.
-
-	  If unsure, say Y.
-
 config MD_MULTIPATH
 	tristate "Multipath I/O support"
 	depends on BLK_DEV_MD
@@ -235,7 +221,7 @@
        tristate "Snapshot target (EXPERIMENTAL)"
        depends on BLK_DEV_DM && EXPERIMENTAL
        ---help---
-         Allow volume managers to take writeable snapshots of a device.
+         Allow volume managers to take writable snapshots of a device.
 
 config DM_MIRROR
        tristate "Mirror target (EXPERIMENTAL)"
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index d3efedf..34957a6 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -8,7 +8,7 @@
 dm-snapshot-objs := dm-snap.o dm-exception-store.o
 dm-mirror-objs	:= dm-log.o dm-raid1.o
 md-mod-objs     := md.o bitmap.o
-raid6-objs	:= raid6main.o raid6algos.o raid6recov.o raid6tables.o \
+raid456-objs	:= raid5.o raid6algos.o raid6recov.o raid6tables.o \
 		   raid6int1.o raid6int2.o raid6int4.o \
 		   raid6int8.o raid6int16.o raid6int32.o \
 		   raid6altivec1.o raid6altivec2.o raid6altivec4.o \
@@ -25,8 +25,7 @@
 obj-$(CONFIG_MD_RAID0)		+= raid0.o
 obj-$(CONFIG_MD_RAID1)		+= raid1.o
 obj-$(CONFIG_MD_RAID10)		+= raid10.o
-obj-$(CONFIG_MD_RAID5)		+= raid5.o xor.o
-obj-$(CONFIG_MD_RAID6)		+= raid6.o xor.o
+obj-$(CONFIG_MD_RAID456)	+= raid456.o xor.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
 obj-$(CONFIG_MD_FAULTY)		+= faulty.o
 obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index f8ffaee..ebbd2d8 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -7,7 +7,6 @@
  * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.:
  * - added disk storage for bitmap
  * - changes to allow various bitmap chunk sizes
- * - added bitmap daemon (to asynchronously clear bitmap bits from disk)
  */
 
 /*
@@ -15,9 +14,6 @@
  *
  * flush after percent set rather than just time based. (maybe both).
  * wait if count gets too high, wake when it drops to half.
- * allow bitmap to be mirrored with superblock (before or after...)
- * allow hot-add to re-instate a current device.
- * allow hot-add of bitmap after quiessing device
  */
 
 #include <linux/module.h>
@@ -73,24 +69,6 @@
 
 
 /*
- * test if the bitmap is active
- */
-int bitmap_active(struct bitmap *bitmap)
-{
-	unsigned long flags;
-	int res = 0;
-
-	if (!bitmap)
-		return res;
-	spin_lock_irqsave(&bitmap->lock, flags);
-	res = bitmap->flags & BITMAP_ACTIVE;
-	spin_unlock_irqrestore(&bitmap->lock, flags);
-	return res;
-}
-
-#define WRITE_POOL_SIZE 256
-
-/*
  * just a placeholder - calls kmalloc for bitmap pages
  */
 static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
@@ -269,6 +247,8 @@
 
 		if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) {
 			page->index = index;
+			attach_page_buffers(page, NULL); /* so that free_buffer will
+							  * quietly no-op */
 			return page;
 		}
 	}
@@ -300,77 +280,132 @@
  */
 static int write_page(struct bitmap *bitmap, struct page *page, int wait)
 {
-	int ret = -ENOMEM;
+	struct buffer_head *bh;
 
 	if (bitmap->file == NULL)
 		return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
 
-	flush_dcache_page(page); /* make sure visible to anyone reading the file */
+	bh = page_buffers(page);
 
-	if (wait)
-		lock_page(page);
-	else {
-		if (TestSetPageLocked(page))
-			return -EAGAIN; /* already locked */
-		if (PageWriteback(page)) {
-			unlock_page(page);
-			return -EAGAIN;
-		}
+	while (bh && bh->b_blocknr) {
+		atomic_inc(&bitmap->pending_writes);
+		set_buffer_locked(bh);
+		set_buffer_mapped(bh);
+		submit_bh(WRITE, bh);
+		bh = bh->b_this_page;
 	}
 
-	ret = page->mapping->a_ops->prepare_write(bitmap->file, page, 0, PAGE_SIZE);
-	if (!ret)
-		ret = page->mapping->a_ops->commit_write(bitmap->file, page, 0,
-			PAGE_SIZE);
-	if (ret) {
-		unlock_page(page);
-		return ret;
+	if (wait) {
+		wait_event(bitmap->write_wait,
+			   atomic_read(&bitmap->pending_writes)==0);
+		return (bitmap->flags & BITMAP_WRITE_ERROR) ? -EIO : 0;
 	}
-
-	set_page_dirty(page); /* force it to be written out */
-
-	if (!wait) {
-		/* add to list to be waited for by daemon */
-		struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
-		item->page = page;
-		get_page(page);
-		spin_lock(&bitmap->write_lock);
-		list_add(&item->list, &bitmap->complete_pages);
-		spin_unlock(&bitmap->write_lock);
-		md_wakeup_thread(bitmap->writeback_daemon);
-	}
-	return write_one_page(page, wait);
+	return 0;
 }
 
-/* read a page from a file, pinning it into cache, and return bytes_read */
-static struct page *read_page(struct file *file, unsigned long index,
-					unsigned long *bytes_read)
+static void end_bitmap_write(struct buffer_head *bh, int uptodate)
 {
-	struct inode *inode = file->f_mapping->host;
+	struct bitmap *bitmap = bh->b_private;
+	unsigned long flags;
+
+	if (!uptodate) {
+		spin_lock_irqsave(&bitmap->lock, flags);
+		bitmap->flags |= BITMAP_WRITE_ERROR;
+		spin_unlock_irqrestore(&bitmap->lock, flags);
+	}
+	if (atomic_dec_and_test(&bitmap->pending_writes))
+		wake_up(&bitmap->write_wait);
+}
+
+/* copied from buffer.c */
+static void
+__clear_page_buffers(struct page *page)
+{
+	ClearPagePrivate(page);
+	set_page_private(page, 0);
+	page_cache_release(page);
+}
+static void free_buffers(struct page *page)
+{
+	struct buffer_head *bh = page_buffers(page);
+
+	while (bh) {
+		struct buffer_head *next = bh->b_this_page;
+		free_buffer_head(bh);
+		bh = next;
+	}
+	__clear_page_buffers(page);
+	put_page(page);
+}
+
+/* read a page from a file.
+ * We both read the page, and attach buffers to the page to record the
+ * address of each block (using bmap).  These addresses will be used
+ * to write the block later, completely bypassing the filesystem.
+ * This usage is similar to how swap files are handled, and allows us
+ * to write to a file with no concerns of memory allocation failing.
+ */
+static struct page *read_page(struct file *file, unsigned long index,
+			      struct bitmap *bitmap,
+			      unsigned long count)
+{
 	struct page *page = NULL;
-	loff_t isize = i_size_read(inode);
-	unsigned long end_index = isize >> PAGE_SHIFT;
+	struct inode *inode = file->f_dentry->d_inode;
+	struct buffer_head *bh;
+	sector_t block;
 
 	PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_SIZE,
 			(unsigned long long)index << PAGE_SHIFT);
 
-	page = read_cache_page(inode->i_mapping, index,
-			(filler_t *)inode->i_mapping->a_ops->readpage, file);
+	page = alloc_page(GFP_KERNEL);
+	if (!page)
+		page = ERR_PTR(-ENOMEM);
 	if (IS_ERR(page))
 		goto out;
-	wait_on_page_locked(page);
-	if (!PageUptodate(page) || PageError(page)) {
+
+	bh = alloc_page_buffers(page, 1<<inode->i_blkbits, 0);
+	if (!bh) {
 		put_page(page);
-		page = ERR_PTR(-EIO);
+		page = ERR_PTR(-ENOMEM);
 		goto out;
 	}
+	attach_page_buffers(page, bh);
+	block = index << (PAGE_SHIFT - inode->i_blkbits);
+	while (bh) {
+		if (count == 0)
+			bh->b_blocknr = 0;
+		else {
+			bh->b_blocknr = bmap(inode, block);
+			if (bh->b_blocknr == 0) {
+				/* Cannot use this file! */
+				free_buffers(page);
+				page = ERR_PTR(-EINVAL);
+				goto out;
+			}
+			bh->b_bdev = inode->i_sb->s_bdev;
+			if (count < (1<<inode->i_blkbits))
+				count = 0;
+			else
+				count -= (1<<inode->i_blkbits);
 
-	if (index > end_index) /* we have read beyond EOF */
-		*bytes_read = 0;
-	else if (index == end_index) /* possible short read */
-		*bytes_read = isize & ~PAGE_MASK;
-	else
-		*bytes_read = PAGE_SIZE; /* got a full page */
+			bh->b_end_io = end_bitmap_write;
+			bh->b_private = bitmap;
+			atomic_inc(&bitmap->pending_writes);
+			set_buffer_locked(bh);
+			set_buffer_mapped(bh);
+			submit_bh(READ, bh);
+		}
+		block++;
+		bh = bh->b_this_page;
+	}
+	page->index = index;
+
+	wait_event(bitmap->write_wait,
+		   atomic_read(&bitmap->pending_writes)==0);
+	if (bitmap->flags & BITMAP_WRITE_ERROR) {
+		free_buffers(page);
+		page = ERR_PTR(-EIO);
+	}
 out:
 	if (IS_ERR(page))
 		printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
@@ -441,16 +476,14 @@
 	char *reason = NULL;
 	bitmap_super_t *sb;
 	unsigned long chunksize, daemon_sleep, write_behind;
-	unsigned long bytes_read;
 	unsigned long long events;
 	int err = -EINVAL;
 
 	/* page 0 is the superblock, read it... */
 	if (bitmap->file)
-		bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
+		bitmap->sb_page = read_page(bitmap->file, 0, bitmap, PAGE_SIZE);
 	else {
 		bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
-		bytes_read = PAGE_SIZE;
 	}
 	if (IS_ERR(bitmap->sb_page)) {
 		err = PTR_ERR(bitmap->sb_page);
@@ -460,13 +493,6 @@
 
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 
-	if (bytes_read < sizeof(*sb)) { /* short read */
-		printk(KERN_INFO "%s: bitmap file superblock truncated\n",
-			bmname(bitmap));
-		err = -ENOSPC;
-		goto out;
-	}
-
 	chunksize = le32_to_cpu(sb->chunksize);
 	daemon_sleep = le32_to_cpu(sb->daemon_sleep);
 	write_behind = le32_to_cpu(sb->write_behind);
@@ -550,7 +576,6 @@
 		spin_unlock_irqrestore(&bitmap->lock, flags);
 		return;
 	}
-	get_page(bitmap->sb_page);
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 	sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0);
 	switch (op) {
@@ -561,7 +586,6 @@
 		default: BUG();
 	}
 	kunmap_atomic(sb, KM_USER0);
-	put_page(bitmap->sb_page);
 }
 
 /*
@@ -614,48 +638,17 @@
 
 	while (pages--)
 		if (map[pages]->index != 0) /* 0 is sb_page, release it below */
-			put_page(map[pages]);
+			free_buffers(map[pages]);
 	kfree(map);
 	kfree(attr);
 
-	safe_put_page(sb_page);
-}
-
-static void bitmap_stop_daemon(struct bitmap *bitmap);
-
-/* dequeue the next item in a page list -- don't call from irq context */
-static struct page_list *dequeue_page(struct bitmap *bitmap)
-{
-	struct page_list *item = NULL;
-	struct list_head *head = &bitmap->complete_pages;
-
-	spin_lock(&bitmap->write_lock);
-	if (list_empty(head))
-		goto out;
-	item = list_entry(head->prev, struct page_list, list);
-	list_del(head->prev);
-out:
-	spin_unlock(&bitmap->write_lock);
-	return item;
-}
-
-static void drain_write_queues(struct bitmap *bitmap)
-{
-	struct page_list *item;
-
-	while ((item = dequeue_page(bitmap))) {
-		/* don't bother to wait */
-		put_page(item->page);
-		mempool_free(item, bitmap->write_pool);
-	}
-
-	wake_up(&bitmap->write_wait);
+	if (sb_page)
+		free_buffers(sb_page);
 }
 
 static void bitmap_file_put(struct bitmap *bitmap)
 {
 	struct file *file;
-	struct inode *inode;
 	unsigned long flags;
 
 	spin_lock_irqsave(&bitmap->lock, flags);
@@ -663,17 +656,14 @@
 	bitmap->file = NULL;
 	spin_unlock_irqrestore(&bitmap->lock, flags);
 
-	bitmap_stop_daemon(bitmap);
-
-	drain_write_queues(bitmap);
-
+	if (file)
+		wait_event(bitmap->write_wait,
+			   atomic_read(&bitmap->pending_writes)==0);
 	bitmap_file_unmap(bitmap);
 
 	if (file) {
-		inode = file->f_mapping->host;
-		spin_lock(&inode->i_lock);
-		atomic_set(&inode->i_writecount, 1); /* allow writes again */
-		spin_unlock(&inode->i_lock);
+		struct inode *inode = file->f_dentry->d_inode;
+		invalidate_inode_pages(inode->i_mapping);
 		fput(file);
 	}
 }
@@ -708,26 +698,27 @@
 }
 
 enum bitmap_page_attr {
-	BITMAP_PAGE_DIRTY = 1, // there are set bits that need to be synced
-	BITMAP_PAGE_CLEAN = 2, // there are bits that might need to be cleared
-	BITMAP_PAGE_NEEDWRITE=4, // there are cleared bits that need to be synced
+	BITMAP_PAGE_DIRTY = 0, // there are set bits that need to be synced
+	BITMAP_PAGE_CLEAN = 1, // there are bits that might need to be cleared
+	BITMAP_PAGE_NEEDWRITE=2, // there are cleared bits that need to be synced
 };
 
 static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
 				enum bitmap_page_attr attr)
 {
-	bitmap->filemap_attr[page->index] |= attr;
+	__set_bit((page->index<<2) + attr, bitmap->filemap_attr);
 }
 
 static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
 				enum bitmap_page_attr attr)
 {
-	bitmap->filemap_attr[page->index] &= ~attr;
+	__clear_bit((page->index<<2) + attr, bitmap->filemap_attr);
 }
 
-static inline unsigned long get_page_attr(struct bitmap *bitmap, struct page *page)
+static inline unsigned long test_page_attr(struct bitmap *bitmap, struct page *page,
+					   enum bitmap_page_attr attr)
 {
-	return bitmap->filemap_attr[page->index];
+	return test_bit((page->index<<2) + attr, bitmap->filemap_attr);
 }
 
 /*
@@ -751,11 +742,6 @@
 	page = filemap_get_page(bitmap, chunk);
 	bit = file_page_offset(chunk);
 
-
-	/* make sure the page stays cached until it gets written out */
-	if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
-		get_page(page);
-
  	/* set the bit */
 	kaddr = kmap_atomic(page, KM_USER0);
 	if (bitmap->flags & BITMAP_HOSTENDIAN)
@@ -775,7 +761,8 @@
  * sync the dirty pages of the bitmap file to disk */
 int bitmap_unplug(struct bitmap *bitmap)
 {
-	unsigned long i, attr, flags;
+	unsigned long i, flags;
+	int dirty, need_write;
 	struct page *page;
 	int wait = 0;
 	int err;
@@ -792,35 +779,26 @@
 			return 0;
 		}
 		page = bitmap->filemap[i];
-		attr = get_page_attr(bitmap, page);
+		dirty = test_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+		need_write = test_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
 		clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
 		clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
-		if ((attr & BITMAP_PAGE_DIRTY))
+		if (dirty)
 			wait = 1;
 		spin_unlock_irqrestore(&bitmap->lock, flags);
 
-		if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) {
+		if (dirty | need_write)
 			err = write_page(bitmap, page, 0);
-			if (err == -EAGAIN) {
-				if (attr & BITMAP_PAGE_DIRTY)
-					err = write_page(bitmap, page, 1);
-				else
-					err = 0;
-			}
-			if (err)
-				return 1;
-		}
 	}
 	if (wait) { /* if any writes were performed, we need to wait on them */
-		if (bitmap->file) {
-			spin_lock_irq(&bitmap->write_lock);
-			wait_event_lock_irq(bitmap->write_wait,
-					    list_empty(&bitmap->complete_pages), bitmap->write_lock,
-					    wake_up_process(bitmap->writeback_daemon->tsk));
-			spin_unlock_irq(&bitmap->write_lock);
-		} else
+		if (bitmap->file)
+			wait_event(bitmap->write_wait,
+				   atomic_read(&bitmap->pending_writes)==0);
+		else
 			md_super_wait(bitmap->mddev);
 	}
+	if (bitmap->flags & BITMAP_WRITE_ERROR)
+		bitmap_file_kick(bitmap);
 	return 0;
 }
 
@@ -842,7 +820,7 @@
 	struct page *page = NULL, *oldpage = NULL;
 	unsigned long num_pages, bit_cnt = 0;
 	struct file *file;
-	unsigned long bytes, offset, dummy;
+	unsigned long bytes, offset;
 	int outofdate;
 	int ret = -ENOSPC;
 	void *paddr;
@@ -879,7 +857,12 @@
 	if (!bitmap->filemap)
 		goto out;
 
-	bitmap->filemap_attr = kzalloc(sizeof(long) * num_pages, GFP_KERNEL);
+	/* We need 4 bits per page, rounded up to a multiple of sizeof(unsigned long) */
+	bitmap->filemap_attr = kzalloc(
+		(((num_pages*4/8)+sizeof(unsigned long)-1)
+		 /sizeof(unsigned long))
+		*sizeof(unsigned long),
+		GFP_KERNEL);
 	if (!bitmap->filemap_attr)
 		goto out;
 
@@ -890,7 +873,12 @@
 		index = file_page_index(i);
 		bit = file_page_offset(i);
 		if (index != oldindex) { /* this is a new page, read it in */
+			int count;
 			/* unmap the old page, we're done with it */
+			if (index == num_pages-1)
+				count = bytes - index * PAGE_SIZE;
+			else
+				count = PAGE_SIZE;
 			if (index == 0) {
 				/*
 				 * if we're here then the superblock page
@@ -900,7 +888,7 @@
 				page = bitmap->sb_page;
 				offset = sizeof(bitmap_super_t);
 			} else if (file) {
-				page = read_page(file, index, &dummy);
+				page = read_page(file, index, bitmap, count);
 				offset = 0;
 			} else {
 				page = read_sb_page(bitmap->mddev, bitmap->offset, index);
@@ -971,12 +959,11 @@
 	/* We don't actually write all bitmap blocks here,
 	 * just flag them as needing to be written
 	 */
+	int i;
 
-	unsigned long chunks = bitmap->chunks;
-	unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t);
-	unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE;
-	while (num_pages--)
-		bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE;
+	for (i=0; i < bitmap->file_pages; i++)
+		set_page_attr(bitmap, bitmap->filemap[i],
+			      BITMAP_PAGE_NEEDWRITE);
 }
 
 
@@ -1007,7 +994,6 @@
 	struct page *page = NULL, *lastpage = NULL;
 	int err = 0;
 	int blocks;
-	int attr;
 	void *paddr;
 
 	if (bitmap == NULL)
@@ -1029,43 +1015,34 @@
 
 		if (page != lastpage) {
 			/* skip this page unless it's marked as needing cleaning */
-			if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
-				if (attr & BITMAP_PAGE_NEEDWRITE) {
-					get_page(page);
+			if (!test_page_attr(bitmap, page, BITMAP_PAGE_CLEAN)) {
+				int need_write = test_page_attr(bitmap, page,
+								BITMAP_PAGE_NEEDWRITE);
+				if (need_write)
 					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
-				}
+
 				spin_unlock_irqrestore(&bitmap->lock, flags);
-				if (attr & BITMAP_PAGE_NEEDWRITE) {
+				if (need_write) {
 					switch (write_page(bitmap, page, 0)) {
-					case -EAGAIN:
-						set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
-						break;
 					case 0:
 						break;
 					default:
 						bitmap_file_kick(bitmap);
 					}
-					put_page(page);
 				}
 				continue;
 			}
 
 			/* grab the new page, sync and release the old */
-			get_page(page);
 			if (lastpage != NULL) {
-				if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
+				if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
 					clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 					err = write_page(bitmap, lastpage, 0);
-					if (err == -EAGAIN) {
-						err = 0;
-						set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
-					}
 				} else {
 					set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 					spin_unlock_irqrestore(&bitmap->lock, flags);
 				}
-				put_page(lastpage);
 				if (err)
 					bitmap_file_kick(bitmap);
 			} else
@@ -1107,131 +1084,19 @@
 	/* now sync the final page */
 	if (lastpage != NULL) {
 		spin_lock_irqsave(&bitmap->lock, flags);
-		if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
+		if (test_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE)) {
 			clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
 			err = write_page(bitmap, lastpage, 0);
-			if (err == -EAGAIN) {
-				set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
-				err = 0;
-			}
 		} else {
 			set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
 			spin_unlock_irqrestore(&bitmap->lock, flags);
 		}
-
-		put_page(lastpage);
 	}
 
 	return err;
 }
 
-static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon)
-{
-	mdk_thread_t *dmn;
-	unsigned long flags;
-
-	/* if no one is waiting on us, we'll free the md thread struct
-	 * and exit, otherwise we let the waiter clean things up */
-	spin_lock_irqsave(&bitmap->lock, flags);
-	if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */
-		*daemon = NULL;
-		spin_unlock_irqrestore(&bitmap->lock, flags);
-		kfree(dmn);
-		complete_and_exit(NULL, 0); /* do_exit not exported */
-	}
-	spin_unlock_irqrestore(&bitmap->lock, flags);
-}
-
-static void bitmap_writeback_daemon(mddev_t *mddev)
-{
-	struct bitmap *bitmap = mddev->bitmap;
-	struct page *page;
-	struct page_list *item;
-	int err = 0;
-
-	if (signal_pending(current)) {
-		printk(KERN_INFO
-		       "%s: bitmap writeback daemon got signal, exiting...\n",
-		       bmname(bitmap));
-		err = -EINTR;
-		goto out;
-	}
-	if (bitmap == NULL)
-		/* about to be stopped. */
-		return;
-
-	PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
-	/* wait on bitmap page writebacks */
-	while ((item = dequeue_page(bitmap))) {
-		page = item->page;
-		mempool_free(item, bitmap->write_pool);
-		PRINTK("wait on page writeback: %p\n", page);
-		wait_on_page_writeback(page);
-		PRINTK("finished page writeback: %p\n", page);
-
-		err = PageError(page);
-		put_page(page);
-		if (err) {
-			printk(KERN_WARNING "%s: bitmap file writeback "
-			       "failed (page %lu): %d\n",
-			       bmname(bitmap), page->index, err);
-			bitmap_file_kick(bitmap);
-			goto out;
-		}
-	}
- out:
-	wake_up(&bitmap->write_wait);
-	if (err) {
-		printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
-		       bmname(bitmap), err);
-		daemon_exit(bitmap, &bitmap->writeback_daemon);
-	}
-}
-
-static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
-				void (*func)(mddev_t *), char *name)
-{
-	mdk_thread_t *daemon;
-	char namebuf[32];
-
-#ifdef INJECT_FATAL_FAULT_2
-	daemon = NULL;
-#else
-	sprintf(namebuf, "%%s_%s", name);
-	daemon = md_register_thread(func, bitmap->mddev, namebuf);
-#endif
-	if (!daemon) {
-		printk(KERN_ERR "%s: failed to start bitmap daemon\n",
-			bmname(bitmap));
-		return ERR_PTR(-ECHILD);
-	}
-
-	md_wakeup_thread(daemon); /* start it running */
-
-	PRINTK("%s: %s daemon (pid %d) started...\n",
-		bmname(bitmap), name, daemon->tsk->pid);
-
-	return daemon;
-}
-
-static void bitmap_stop_daemon(struct bitmap *bitmap)
-{
-	/* the daemon can't stop itself... it'll just exit instead... */
-	if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
-	    current->pid != bitmap->writeback_daemon->tsk->pid) {
-		mdk_thread_t *daemon;
-		unsigned long flags;
-
-		spin_lock_irqsave(&bitmap->lock, flags);
-		daemon = bitmap->writeback_daemon;
-		bitmap->writeback_daemon = NULL;
-		spin_unlock_irqrestore(&bitmap->lock, flags);
-		if (daemon && ! IS_ERR(daemon))
-			md_unregister_thread(daemon); /* destroy the thread */
-	}
-}
-
 static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
 					    sector_t offset, int *blocks,
 					    int create)
@@ -1500,8 +1365,6 @@
 
 	/* free all allocated memory */
 
-	mempool_destroy(bitmap->write_pool);
-
 	if (bp) /* deallocate the page memory */
 		for (k = 0; k < pages; k++)
 			if (bp[k].map && !bp[k].hijacked)
@@ -1549,20 +1412,20 @@
 		return -ENOMEM;
 
 	spin_lock_init(&bitmap->lock);
-	bitmap->mddev = mddev;
-
-	spin_lock_init(&bitmap->write_lock);
-	INIT_LIST_HEAD(&bitmap->complete_pages);
+	atomic_set(&bitmap->pending_writes, 0);
 	init_waitqueue_head(&bitmap->write_wait);
-	bitmap->write_pool = mempool_create_kmalloc_pool(WRITE_POOL_SIZE,
-						sizeof(struct page_list));
-	err = -ENOMEM;
-	if (!bitmap->write_pool)
-		goto error;
+
+	bitmap->mddev = mddev;
 
 	bitmap->file = file;
 	bitmap->offset = mddev->bitmap_offset;
-	if (file) get_file(file);
+	if (file) {
+		get_file(file);
+		do_sync_file_range(file, 0, LLONG_MAX,
+				   SYNC_FILE_RANGE_WAIT_BEFORE |
+				   SYNC_FILE_RANGE_WRITE |
+				   SYNC_FILE_RANGE_WAIT_AFTER);
+	}
 	/* read superblock from bitmap file (this sets bitmap->chunksize) */
 	err = bitmap_read_sb(bitmap);
 	if (err)
@@ -1594,8 +1457,6 @@
 	if (!bitmap->bp)
 		goto error;
 
-	bitmap->flags |= BITMAP_ACTIVE;
-
 	/* now that we have some pages available, initialize the in-memory
 	 * bitmap from the on-disk bitmap */
 	start = 0;
@@ -1613,15 +1474,6 @@
 
 	mddev->bitmap = bitmap;
 
-	if (file)
-		/* kick off the bitmap writeback daemon */
-		bitmap->writeback_daemon =
-			bitmap_start_daemon(bitmap,
-					    bitmap_writeback_daemon,
-					    "bitmap_wb");
-
-	if (IS_ERR(bitmap->writeback_daemon))
-		return PTR_ERR(bitmap->writeback_daemon);
 	mddev->thread->timeout = bitmap->daemon_sleep * HZ;
 
 	return bitmap_update_sb(bitmap);
@@ -1638,4 +1490,3 @@
 EXPORT_SYMBOL(bitmap_end_sync);
 EXPORT_SYMBOL(bitmap_unplug);
 EXPORT_SYMBOL(bitmap_close_sync);
-EXPORT_SYMBOL(bitmap_daemon_work);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 61a590b..6022ed1 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -20,7 +20,7 @@
 
 #include "dm.h"
 
-#define PFX	"crypt: "
+#define DM_MSG_PREFIX "crypt"
 
 /*
  * per bio private data
@@ -125,19 +125,19 @@
 	u8 *salt;
 
 	if (opts == NULL) {
-		ti->error = PFX "Digest algorithm missing for ESSIV mode";
+		ti->error = "Digest algorithm missing for ESSIV mode";
 		return -EINVAL;
 	}
 
 	/* Hash the cipher key with the given hash algorithm */
 	hash_tfm = crypto_alloc_tfm(opts, CRYPTO_TFM_REQ_MAY_SLEEP);
 	if (hash_tfm == NULL) {
-		ti->error = PFX "Error initializing ESSIV hash";
+		ti->error = "Error initializing ESSIV hash";
 		return -EINVAL;
 	}
 
 	if (crypto_tfm_alg_type(hash_tfm) != CRYPTO_ALG_TYPE_DIGEST) {
-		ti->error = PFX "Expected digest algorithm for ESSIV hash";
+		ti->error = "Expected digest algorithm for ESSIV hash";
 		crypto_free_tfm(hash_tfm);
 		return -EINVAL;
 	}
@@ -145,7 +145,7 @@
 	saltsize = crypto_tfm_alg_digestsize(hash_tfm);
 	salt = kmalloc(saltsize, GFP_KERNEL);
 	if (salt == NULL) {
-		ti->error = PFX "Error kmallocing salt storage in ESSIV";
+		ti->error = "Error kmallocing salt storage in ESSIV";
 		crypto_free_tfm(hash_tfm);
 		return -ENOMEM;
 	}
@@ -159,20 +159,20 @@
 	                             CRYPTO_TFM_MODE_ECB |
 	                             CRYPTO_TFM_REQ_MAY_SLEEP);
 	if (essiv_tfm == NULL) {
-		ti->error = PFX "Error allocating crypto tfm for ESSIV";
+		ti->error = "Error allocating crypto tfm for ESSIV";
 		kfree(salt);
 		return -EINVAL;
 	}
 	if (crypto_tfm_alg_blocksize(essiv_tfm)
 	    != crypto_tfm_alg_ivsize(cc->tfm)) {
-		ti->error = PFX "Block size of ESSIV cipher does "
+		ti->error = "Block size of ESSIV cipher does "
 			        "not match IV size of block cipher";
 		crypto_free_tfm(essiv_tfm);
 		kfree(salt);
 		return -EINVAL;
 	}
 	if (crypto_cipher_setkey(essiv_tfm, salt, saltsize) < 0) {
-		ti->error = PFX "Failed to set key for ESSIV cipher";
+		ti->error = "Failed to set key for ESSIV cipher";
 		crypto_free_tfm(essiv_tfm);
 		kfree(salt);
 		return -EINVAL;
@@ -521,7 +521,7 @@
 	unsigned long long tmpll;
 
 	if (argc != 5) {
-		ti->error = PFX "Not enough arguments";
+		ti->error = "Not enough arguments";
 		return -EINVAL;
 	}
 
@@ -532,21 +532,21 @@
 	ivmode = strsep(&ivopts, ":");
 
 	if (tmp)
-		DMWARN(PFX "Unexpected additional cipher options");
+		DMWARN("Unexpected additional cipher options");
 
 	key_size = strlen(argv[1]) >> 1;
 
 	cc = kmalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
 	if (cc == NULL) {
 		ti->error =
-			PFX "Cannot allocate transparent encryption context";
+			"Cannot allocate transparent encryption context";
 		return -ENOMEM;
 	}
 
 	cc->key_size = key_size;
 	if ((!key_size && strcmp(argv[1], "-") != 0) ||
 	    (key_size && crypt_decode_key(cc->key, argv[1], key_size) < 0)) {
-		ti->error = PFX "Error decoding key";
+		ti->error = "Error decoding key";
 		goto bad1;
 	}
 
@@ -562,22 +562,22 @@
 	else if (strcmp(chainmode, "ecb") == 0)
 		crypto_flags = CRYPTO_TFM_MODE_ECB;
 	else {
-		ti->error = PFX "Unknown chaining mode";
+		ti->error = "Unknown chaining mode";
 		goto bad1;
 	}
 
 	if (crypto_flags != CRYPTO_TFM_MODE_ECB && !ivmode) {
-		ti->error = PFX "This chaining mode requires an IV mechanism";
+		ti->error = "This chaining mode requires an IV mechanism";
 		goto bad1;
 	}
 
 	tfm = crypto_alloc_tfm(cipher, crypto_flags | CRYPTO_TFM_REQ_MAY_SLEEP);
 	if (!tfm) {
-		ti->error = PFX "Error allocating crypto tfm";
+		ti->error = "Error allocating crypto tfm";
 		goto bad1;
 	}
 	if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER) {
-		ti->error = PFX "Expected cipher algorithm";
+		ti->error = "Expected cipher algorithm";
 		goto bad2;
 	}
 
@@ -595,7 +595,7 @@
 	else if (strcmp(ivmode, "essiv") == 0)
 		cc->iv_gen_ops = &crypt_iv_essiv_ops;
 	else {
-		ti->error = PFX "Invalid IV mode";
+		ti->error = "Invalid IV mode";
 		goto bad2;
 	}
 
@@ -610,7 +610,7 @@
 	else {
 		cc->iv_size = 0;
 		if (cc->iv_gen_ops) {
-			DMWARN(PFX "Selected cipher does not support IVs");
+			DMWARN("Selected cipher does not support IVs");
 			if (cc->iv_gen_ops->dtr)
 				cc->iv_gen_ops->dtr(cc);
 			cc->iv_gen_ops = NULL;
@@ -619,36 +619,36 @@
 
 	cc->io_pool = mempool_create_slab_pool(MIN_IOS, _crypt_io_pool);
 	if (!cc->io_pool) {
-		ti->error = PFX "Cannot allocate crypt io mempool";
+		ti->error = "Cannot allocate crypt io mempool";
 		goto bad3;
 	}
 
 	cc->page_pool = mempool_create_page_pool(MIN_POOL_PAGES, 0);
 	if (!cc->page_pool) {
-		ti->error = PFX "Cannot allocate page mempool";
+		ti->error = "Cannot allocate page mempool";
 		goto bad4;
 	}
 
 	if (tfm->crt_cipher.cit_setkey(tfm, cc->key, key_size) < 0) {
-		ti->error = PFX "Error setting key";
+		ti->error = "Error setting key";
 		goto bad5;
 	}
 
 	if (sscanf(argv[2], "%llu", &tmpll) != 1) {
-		ti->error = PFX "Invalid iv_offset sector";
+		ti->error = "Invalid iv_offset sector";
 		goto bad5;
 	}
 	cc->iv_offset = tmpll;
 
 	if (sscanf(argv[4], "%llu", &tmpll) != 1) {
-		ti->error = PFX "Invalid device sector";
+		ti->error = "Invalid device sector";
 		goto bad5;
 	}
 	cc->start = tmpll;
 
 	if (dm_get_device(ti, argv[3], cc->start, ti->len,
 	                  dm_table_get_mode(ti->table), &cc->dev)) {
-		ti->error = PFX "Device lookup failed";
+		ti->error = "Device lookup failed";
 		goto bad5;
 	}
 
@@ -657,7 +657,7 @@
 			*(ivopts - 1) = ':';
 		cc->iv_mode = kmalloc(strlen(ivmode) + 1, GFP_KERNEL);
 		if (!cc->iv_mode) {
-			ti->error = PFX "Error kmallocing iv_mode string";
+			ti->error = "Error kmallocing iv_mode string";
 			goto bad5;
 		}
 		strcpy(cc->iv_mode, ivmode);
@@ -918,13 +918,13 @@
 	_kcryptd_workqueue = create_workqueue("kcryptd");
 	if (!_kcryptd_workqueue) {
 		r = -ENOMEM;
-		DMERR(PFX "couldn't create kcryptd");
+		DMERR("couldn't create kcryptd");
 		goto bad1;
 	}
 
 	r = dm_register_target(&crypt_target);
 	if (r < 0) {
-		DMERR(PFX "register failed %d", r);
+		DMERR("register failed %d", r);
 		goto bad2;
 	}
 
@@ -942,7 +942,7 @@
 	int r = dm_unregister_target(&crypt_target);
 
 	if (r < 0)
-		DMERR(PFX "unregister failed %d", r);
+		DMERR("unregister failed %d", r);
 
 	destroy_workqueue(_kcryptd_workqueue);
 	kmem_cache_destroy(_crypt_io_pool);
diff --git a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
index c706767..2a374cc 100644
--- a/drivers/md/dm-emc.c
+++ b/drivers/md/dm-emc.c
@@ -12,6 +12,8 @@
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 
+#define DM_MSG_PREFIX "multipath emc"
+
 struct emc_handler {
 	spinlock_t lock;
 
@@ -66,7 +68,7 @@
 
 	bio = bio_alloc(GFP_ATOMIC, 1);
 	if (!bio) {
-		DMERR("dm-emc: get_failover_bio: bio_alloc() failed.");
+		DMERR("get_failover_bio: bio_alloc() failed.");
 		return NULL;
 	}
 
@@ -78,13 +80,13 @@
 
 	page = alloc_page(GFP_ATOMIC);
 	if (!page) {
-		DMERR("dm-emc: get_failover_bio: alloc_page() failed.");
+		DMERR("get_failover_bio: alloc_page() failed.");
 		bio_put(bio);
 		return NULL;
 	}
 
 	if (bio_add_page(bio, page, data_size, 0) != data_size) {
-		DMERR("dm-emc: get_failover_bio: alloc_page() failed.");
+		DMERR("get_failover_bio: alloc_page() failed.");
 		__free_page(page);
 		bio_put(bio);
 		return NULL;
@@ -103,7 +105,7 @@
 	/* FIXME: Figure out why it fails with GFP_ATOMIC. */
 	rq = blk_get_request(q, WRITE, __GFP_WAIT);
 	if (!rq) {
-		DMERR("dm-emc: get_failover_req: blk_get_request failed");
+		DMERR("get_failover_req: blk_get_request failed");
 		return NULL;
 	}
 
@@ -160,7 +162,7 @@
 
 	bio = get_failover_bio(path, data_size);
 	if (!bio) {
-		DMERR("dm-emc: emc_trespass_get: no bio");
+		DMERR("emc_trespass_get: no bio");
 		return NULL;
 	}
 
@@ -173,7 +175,7 @@
 	/* get request for block layer packet command */
 	rq = get_failover_req(h, bio, path);
 	if (!rq) {
-		DMERR("dm-emc: emc_trespass_get: no rq");
+		DMERR("emc_trespass_get: no rq");
 		free_bio(bio);
 		return NULL;
 	}
@@ -200,18 +202,18 @@
 	 * initial state passed into us and then get an update here.
 	 */
 	if (!q) {
-		DMINFO("dm-emc: emc_pg_init: no queue");
+		DMINFO("emc_pg_init: no queue");
 		goto fail_path;
 	}
 
 	/* FIXME: The request should be pre-allocated. */
 	rq = emc_trespass_get(hwh->context, path);
 	if (!rq) {
-		DMERR("dm-emc: emc_pg_init: no rq");
+		DMERR("emc_pg_init: no rq");
 		goto fail_path;
 	}
 
-	DMINFO("dm-emc: emc_pg_init: sending switch-over command");
+	DMINFO("emc_pg_init: sending switch-over command");
 	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
 	return;
 
@@ -241,18 +243,18 @@
 		hr = 0;
 		short_trespass = 0;
 	} else if (argc != 2) {
-		DMWARN("dm-emc hwhandler: incorrect number of arguments");
+		DMWARN("incorrect number of arguments");
 		return -EINVAL;
 	} else {
 		if ((sscanf(argv[0], "%u", &short_trespass) != 1)
 			|| (short_trespass > 1)) {
-			DMWARN("dm-emc: invalid trespass mode selected");
+			DMWARN("invalid trespass mode selected");
 			return -EINVAL;
 		}
 
 		if ((sscanf(argv[1], "%u", &hr) != 1)
 			|| (hr > 1)) {
-			DMWARN("dm-emc: invalid honor reservation flag selected");
+			DMWARN("invalid honor reservation flag selected");
 			return -EINVAL;
 		}
 	}
@@ -264,14 +266,14 @@
 	hwh->context = h;
 
 	if ((h->short_trespass = short_trespass))
-		DMWARN("dm-emc: short trespass command will be send");
+		DMWARN("short trespass command will be send");
 	else
-		DMWARN("dm-emc: long trespass command will be send");
+		DMWARN("long trespass command will be send");
 
 	if ((h->hr = hr))
-		DMWARN("dm-emc: honor reservation bit will be set");
+		DMWARN("honor reservation bit will be set");
 	else
-		DMWARN("dm-emc: honor reservation bit will not be set (default)");
+		DMWARN("honor reservation bit will not be set (default)");
 
 	return 0;
 }
@@ -336,9 +338,9 @@
 	int r = dm_register_hw_handler(&emc_hwh);
 
 	if (r < 0)
-		DMERR("emc: register failed %d", r);
+		DMERR("register failed %d", r);
 
-	DMINFO("dm-emc version 0.0.3 loaded");
+	DMINFO("version 0.0.3 loaded");
 
 	return r;
 }
@@ -348,7 +350,7 @@
 	int r = dm_unregister_hw_handler(&emc_hwh);
 
 	if (r < 0)
-		DMERR("emc: unregister failed %d", r);
+		DMERR("unregister failed %d", r);
 }
 
 module_init(dm_emc_init);
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index cc07bbe..d12379b 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -16,6 +16,8 @@
 #include <linux/vmalloc.h>
 #include <linux/slab.h>
 
+#define DM_MSG_PREFIX "snapshots"
+
 /*-----------------------------------------------------------------
  * Persistent snapshots, by persistent we mean that the snapshot
  * will survive a reboot.
@@ -91,7 +93,6 @@
 	struct dm_snapshot *snap;	/* up pointer to my snapshot */
 	int version;
 	int valid;
-	uint32_t chunk_size;
 	uint32_t exceptions_per_area;
 
 	/*
@@ -133,7 +134,7 @@
 	int r = -ENOMEM;
 	size_t len;
 
-	len = ps->chunk_size << SECTOR_SHIFT;
+	len = ps->snap->chunk_size << SECTOR_SHIFT;
 
 	/*
 	 * Allocate the chunk_size block of memory that will hold
@@ -160,8 +161,8 @@
 	unsigned long bits;
 
 	where.bdev = ps->snap->cow->bdev;
-	where.sector = ps->chunk_size * chunk;
-	where.count = ps->chunk_size;
+	where.sector = ps->snap->chunk_size * chunk;
+	where.count = ps->snap->chunk_size;
 
 	return dm_io_sync_vm(1, &where, rw, ps->area, &bits);
 }
@@ -188,7 +189,7 @@
 
 static int zero_area(struct pstore *ps, uint32_t area)
 {
-	memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT);
+	memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
 	return area_io(ps, area, WRITE);
 }
 
@@ -196,6 +197,7 @@
 {
 	int r;
 	struct disk_header *dh;
+	chunk_t chunk_size;
 
 	r = chunk_io(ps, 0, READ);
 	if (r)
@@ -210,8 +212,29 @@
 		*new_snapshot = 0;
 		ps->valid = le32_to_cpu(dh->valid);
 		ps->version = le32_to_cpu(dh->version);
-		ps->chunk_size = le32_to_cpu(dh->chunk_size);
+		chunk_size = le32_to_cpu(dh->chunk_size);
+		if (ps->snap->chunk_size != chunk_size) {
+			DMWARN("chunk size %llu in device metadata overrides "
+			       "table chunk size of %llu.",
+			       (unsigned long long)chunk_size,
+			       (unsigned long long)ps->snap->chunk_size);
 
+			/* We had a bogus chunk_size. Fix stuff up. */
+			dm_io_put(sectors_to_pages(ps->snap->chunk_size));
+			free_area(ps);
+
+			ps->snap->chunk_size = chunk_size;
+			ps->snap->chunk_mask = chunk_size - 1;
+			ps->snap->chunk_shift = ffs(chunk_size) - 1;
+
+			r = alloc_area(ps);
+			if (r)
+				return r;
+
+			r = dm_io_get(sectors_to_pages(chunk_size));
+			if (r)
+				return r;
+		}
 	} else {
 		DMWARN("Invalid/corrupt snapshot");
 		r = -ENXIO;
@@ -224,13 +247,13 @@
 {
 	struct disk_header *dh;
 
-	memset(ps->area, 0, ps->chunk_size << SECTOR_SHIFT);
+	memset(ps->area, 0, ps->snap->chunk_size << SECTOR_SHIFT);
 
 	dh = (struct disk_header *) ps->area;
 	dh->magic = cpu_to_le32(SNAP_MAGIC);
 	dh->valid = cpu_to_le32(ps->valid);
 	dh->version = cpu_to_le32(ps->version);
-	dh->chunk_size = cpu_to_le32(ps->chunk_size);
+	dh->chunk_size = cpu_to_le32(ps->snap->chunk_size);
 
 	return chunk_io(ps, 0, WRITE);
 }
@@ -365,7 +388,7 @@
 {
 	struct pstore *ps = get_info(store);
 
-	dm_io_put(sectors_to_pages(ps->chunk_size));
+	dm_io_put(sectors_to_pages(ps->snap->chunk_size));
 	vfree(ps->callbacks);
 	free_area(ps);
 	kfree(ps);
@@ -384,6 +407,16 @@
 		return r;
 
 	/*
+	 * Now we know correct chunk_size, complete the initialisation.
+	 */
+	ps->exceptions_per_area = (ps->snap->chunk_size << SECTOR_SHIFT) /
+				  sizeof(struct disk_exception);
+	ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
+			sizeof(*ps->callbacks));
+	if (!ps->callbacks)
+		return -ENOMEM;
+
+	/*
 	 * Do we need to setup a new snapshot ?
 	 */
 	if (new_snapshot) {
@@ -533,9 +566,6 @@
 	ps->snap = store->snap;
 	ps->valid = 1;
 	ps->version = SNAPSHOT_DISK_VERSION;
-	ps->chunk_size = chunk_size;
-	ps->exceptions_per_area = (chunk_size << SECTOR_SHIFT) /
-	    sizeof(struct disk_exception);
 	ps->next_free = 2;	/* skipping the header and first area */
 	ps->current_committed = 0;
 
@@ -543,18 +573,9 @@
 	if (r)
 		goto bad;
 
-	/*
-	 * Allocate space for all the callbacks.
-	 */
 	ps->callback_count = 0;
 	atomic_set(&ps->pending_count, 0);
-	ps->callbacks = dm_vcalloc(ps->exceptions_per_area,
-				   sizeof(*ps->callbacks));
-
-	if (!ps->callbacks) {
-		r = -ENOMEM;
-		goto bad;
-	}
+	ps->callbacks = NULL;
 
 	store->destroy = persistent_destroy;
 	store->read_metadata = persistent_read_metadata;
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 8edd643..3edb347 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
- * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004 - 2006 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the GPL.
  */
@@ -19,6 +19,7 @@
 
 #include <asm/uaccess.h>
 
+#define DM_MSG_PREFIX "ioctl"
 #define DM_DRIVER_EMAIL "dm-devel@redhat.com"
 
 /*-----------------------------------------------------------------
@@ -48,7 +49,7 @@
 static struct list_head _name_buckets[NUM_BUCKETS];
 static struct list_head _uuid_buckets[NUM_BUCKETS];
 
-static void dm_hash_remove_all(void);
+static void dm_hash_remove_all(int keep_open_devices);
 
 /*
  * Guards access to both hash tables.
@@ -73,7 +74,7 @@
 
 static void dm_hash_exit(void)
 {
-	dm_hash_remove_all();
+	dm_hash_remove_all(0);
 	devfs_remove(DM_DIR);
 }
 
@@ -102,8 +103,10 @@
 	unsigned int h = hash_str(str);
 
 	list_for_each_entry (hc, _name_buckets + h, name_list)
-		if (!strcmp(hc->name, str))
+		if (!strcmp(hc->name, str)) {
+			dm_get(hc->md);
 			return hc;
+		}
 
 	return NULL;
 }
@@ -114,8 +117,10 @@
 	unsigned int h = hash_str(str);
 
 	list_for_each_entry (hc, _uuid_buckets + h, uuid_list)
-		if (!strcmp(hc->uuid, str))
+		if (!strcmp(hc->uuid, str)) {
+			dm_get(hc->md);
 			return hc;
+		}
 
 	return NULL;
 }
@@ -191,7 +196,7 @@
  */
 static int dm_hash_insert(const char *name, const char *uuid, struct mapped_device *md)
 {
-	struct hash_cell *cell;
+	struct hash_cell *cell, *hc;
 
 	/*
 	 * Allocate the new cells.
@@ -204,14 +209,19 @@
 	 * Insert the cell into both hash tables.
 	 */
 	down_write(&_hash_lock);
-	if (__get_name_cell(name))
+	hc = __get_name_cell(name);
+	if (hc) {
+		dm_put(hc->md);
 		goto bad;
+	}
 
 	list_add(&cell->name_list, _name_buckets + hash_str(name));
 
 	if (uuid) {
-		if (__get_uuid_cell(uuid)) {
+		hc = __get_uuid_cell(uuid);
+		if (hc) {
 			list_del(&cell->name_list);
+			dm_put(hc->md);
 			goto bad;
 		}
 		list_add(&cell->uuid_list, _uuid_buckets + hash_str(uuid));
@@ -251,19 +261,41 @@
 	free_cell(hc);
 }
 
-static void dm_hash_remove_all(void)
+static void dm_hash_remove_all(int keep_open_devices)
 {
-	int i;
+	int i, dev_skipped, dev_removed;
 	struct hash_cell *hc;
 	struct list_head *tmp, *n;
 
 	down_write(&_hash_lock);
+
+retry:
+	dev_skipped = dev_removed = 0;
 	for (i = 0; i < NUM_BUCKETS; i++) {
 		list_for_each_safe (tmp, n, _name_buckets + i) {
 			hc = list_entry(tmp, struct hash_cell, name_list);
+
+			if (keep_open_devices &&
+			    dm_lock_for_deletion(hc->md)) {
+				dev_skipped++;
+				continue;
+			}
 			__hash_remove(hc);
+			dev_removed = 1;
 		}
 	}
+
+	/*
+	 * Some mapped devices may be using other mapped devices, so if any
+	 * still exist, repeat until we make no further progress.
+	 */
+	if (dev_skipped) {
+		if (dev_removed)
+			goto retry;
+
+		DMWARN("remove_all left %d open device(s)", dev_skipped);
+	}
+
 	up_write(&_hash_lock);
 }
 
@@ -289,6 +321,7 @@
 	if (hc) {
 		DMWARN("asked to rename to an already existing name %s -> %s",
 		       old, new);
+		dm_put(hc->md);
 		up_write(&_hash_lock);
 		kfree(new_name);
 		return -EBUSY;
@@ -328,6 +361,7 @@
 		dm_table_put(table);
 	}
 
+	dm_put(hc->md);
 	up_write(&_hash_lock);
 	kfree(old_name);
 	return 0;
@@ -344,7 +378,7 @@
 
 static int remove_all(struct dm_ioctl *param, size_t param_size)
 {
-	dm_hash_remove_all();
+	dm_hash_remove_all(1);
 	param->data_size = 0;
 	return 0;
 }
@@ -524,7 +558,6 @@
 {
 	struct gendisk *disk = dm_disk(md);
 	struct dm_table *table;
-	struct block_device *bdev;
 
 	param->flags &= ~(DM_SUSPEND_FLAG | DM_READONLY_FLAG |
 			  DM_ACTIVE_PRESENT_FLAG);
@@ -534,20 +567,12 @@
 
 	param->dev = huge_encode_dev(MKDEV(disk->major, disk->first_minor));
 
-	if (!(param->flags & DM_SKIP_BDGET_FLAG)) {
-		bdev = bdget_disk(disk, 0);
-		if (!bdev)
-			return -ENXIO;
-
-		/*
-		 * Yes, this will be out of date by the time it gets back
-		 * to userland, but it is still very useful for
-		 * debugging.
-		 */
-		param->open_count = bdev->bd_openers;
-		bdput(bdev);
-	} else
-		param->open_count = -1;
+	/*
+	 * Yes, this will be out of date by the time it gets back
+	 * to userland, but it is still very useful for
+	 * debugging.
+	 */
+	param->open_count = dm_open_count(md);
 
 	if (disk->policy)
 		param->flags |= DM_READONLY_FLAG;
@@ -567,7 +592,7 @@
 
 static int dev_create(struct dm_ioctl *param, size_t param_size)
 {
-	int r;
+	int r, m = DM_ANY_MINOR;
 	struct mapped_device *md;
 
 	r = check_name(param->name);
@@ -575,10 +600,9 @@
 		return r;
 
 	if (param->flags & DM_PERSISTENT_DEV_FLAG)
-		r = dm_create_with_minor(MINOR(huge_decode_dev(param->dev)), &md);
-	else
-		r = dm_create(&md);
+		m = MINOR(huge_decode_dev(param->dev));
 
+	r = dm_create(m, &md);
 	if (r)
 		return r;
 
@@ -611,10 +635,8 @@
 		return __get_name_cell(param->name);
 
 	md = dm_get_md(huge_decode_dev(param->dev));
-	if (md) {
+	if (md)
 		mdptr = dm_get_mdptr(md);
-		dm_put(md);
-	}
 
 	return mdptr;
 }
@@ -628,7 +650,6 @@
 	hc = __find_device_hash_cell(param);
 	if (hc) {
 		md = hc->md;
-		dm_get(md);
 
 		/*
 		 * Sneakily write in both the name and the uuid
@@ -653,6 +674,8 @@
 static int dev_remove(struct dm_ioctl *param, size_t param_size)
 {
 	struct hash_cell *hc;
+	struct mapped_device *md;
+	int r;
 
 	down_write(&_hash_lock);
 	hc = __find_device_hash_cell(param);
@@ -663,8 +686,22 @@
 		return -ENXIO;
 	}
 
+	md = hc->md;
+
+	/*
+	 * Ensure the device is not open and nothing further can open it.
+	 */
+	r = dm_lock_for_deletion(md);
+	if (r) {
+		DMWARN("unable to remove open device %s", hc->name);
+		up_write(&_hash_lock);
+		dm_put(md);
+		return r;
+	}
+
 	__hash_remove(hc);
 	up_write(&_hash_lock);
+	dm_put(md);
 	param->data_size = 0;
 	return 0;
 }
@@ -790,7 +827,6 @@
 	}
 
 	md = hc->md;
-	dm_get(md);
 
 	new_map = hc->new_map;
 	hc->new_map = NULL;
@@ -1078,6 +1114,7 @@
 {
 	int r;
 	struct hash_cell *hc;
+	struct mapped_device *md;
 
 	down_write(&_hash_lock);
 
@@ -1096,7 +1133,9 @@
 	param->flags &= ~DM_INACTIVE_PRESENT_FLAG;
 
 	r = __dev_status(hc->md, param);
+	md = hc->md;
 	up_write(&_hash_lock);
+	dm_put(md);
 	return r;
 }
 
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index daf586c..47b3c62 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -12,6 +12,8 @@
 #include <linux/bio.h>
 #include <linux/slab.h>
 
+#define DM_MSG_PREFIX "linear"
+
 /*
  * Linear: maps a linear range of a device.
  */
@@ -29,7 +31,7 @@
 	unsigned long long tmp;
 
 	if (argc != 2) {
-		ti->error = "dm-linear: Invalid argument count";
+		ti->error = "Invalid argument count";
 		return -EINVAL;
 	}
 
@@ -111,7 +113,7 @@
 	int r = dm_register_target(&linear_target);
 
 	if (r < 0)
-		DMERR("linear: register failed %d", r);
+		DMERR("register failed %d", r);
 
 	return r;
 }
@@ -121,5 +123,5 @@
 	int r = dm_unregister_target(&linear_target);
 
 	if (r < 0)
-		DMERR("linear: unregister failed %d", r);
+		DMERR("unregister failed %d", r);
 }
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index d73779a..64b764b 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -12,6 +12,8 @@
 #include "dm-log.h"
 #include "dm-io.h"
 
+#define DM_MSG_PREFIX "mirror log"
+
 static LIST_HEAD(_log_types);
 static DEFINE_SPINLOCK(_lock);
 
@@ -155,8 +157,6 @@
 
 	struct io_region header_location;
 	struct log_header *disk_header;
-
-	struct io_region bits_location;
 };
 
 /*
@@ -241,43 +241,21 @@
 }
 
 /*----------------------------------------------------------------
- * Bits IO
- *--------------------------------------------------------------*/
-static int read_bits(struct log_c *log)
-{
-	int r;
-	unsigned long ebits;
-
-	r = dm_io_sync_vm(1, &log->bits_location, READ,
-			  log->clean_bits, &ebits);
-	if (r)
-		return r;
-
-	return 0;
-}
-
-static int write_bits(struct log_c *log)
-{
-	unsigned long ebits;
-	return dm_io_sync_vm(1, &log->bits_location, WRITE,
-			     log->clean_bits, &ebits);
-}
-
-/*----------------------------------------------------------------
  * core log constructor/destructor
  *
  * argv contains region_size followed optionally by [no]sync
  *--------------------------------------------------------------*/
 #define BYTE_SHIFT 3
-static int core_ctr(struct dirty_log *log, struct dm_target *ti,
-		    unsigned int argc, char **argv)
+static int create_log_context(struct dirty_log *log, struct dm_target *ti,
+			      unsigned int argc, char **argv,
+			      struct dm_dev *dev)
 {
 	enum sync sync = DEFAULTSYNC;
 
 	struct log_c *lc;
 	uint32_t region_size;
 	unsigned int region_count;
-	size_t bitset_size;
+	size_t bitset_size, buf_size;
 
 	if (argc < 1 || argc > 2) {
 		DMWARN("wrong number of arguments to mirror log");
@@ -319,22 +297,53 @@
 	 * Work out how many "unsigned long"s we need to hold the bitset.
 	 */
 	bitset_size = dm_round_up(region_count,
-				  sizeof(unsigned long) << BYTE_SHIFT);
+				  sizeof(*lc->clean_bits) << BYTE_SHIFT);
 	bitset_size >>= BYTE_SHIFT;
 
-	lc->bitset_uint32_count = bitset_size / 4;
-	lc->clean_bits = vmalloc(bitset_size);
-	if (!lc->clean_bits) {
-		DMWARN("couldn't allocate clean bitset");
-		kfree(lc);
-		return -ENOMEM;
+	lc->bitset_uint32_count = bitset_size / sizeof(*lc->clean_bits);
+
+	/*
+	 * Disk log?
+	 */
+	if (!dev) {
+		lc->clean_bits = vmalloc(bitset_size);
+		if (!lc->clean_bits) {
+			DMWARN("couldn't allocate clean bitset");
+			kfree(lc);
+			return -ENOMEM;
+		}
+		lc->disk_header = NULL;
+	} else {
+		lc->log_dev = dev;
+		lc->header_location.bdev = lc->log_dev->bdev;
+		lc->header_location.sector = 0;
+
+		/*
+		 * Buffer holds both header and bitset.
+		 */
+		buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) +
+				       bitset_size, ti->limits.hardsect_size);
+		lc->header_location.count = buf_size >> SECTOR_SHIFT;
+
+		lc->disk_header = vmalloc(buf_size);
+		if (!lc->disk_header) {
+			DMWARN("couldn't allocate disk log buffer");
+			kfree(lc);
+			return -ENOMEM;
+		}
+
+		lc->clean_bits = (void *)lc->disk_header +
+				 (LOG_OFFSET << SECTOR_SHIFT);
 	}
+
 	memset(lc->clean_bits, -1, bitset_size);
 
 	lc->sync_bits = vmalloc(bitset_size);
 	if (!lc->sync_bits) {
 		DMWARN("couldn't allocate sync bitset");
-		vfree(lc->clean_bits);
+		if (!dev)
+			vfree(lc->clean_bits);
+		vfree(lc->disk_header);
 		kfree(lc);
 		return -ENOMEM;
 	}
@@ -345,23 +354,38 @@
 	if (!lc->recovering_bits) {
 		DMWARN("couldn't allocate sync bitset");
 		vfree(lc->sync_bits);
-		vfree(lc->clean_bits);
+		if (!dev)
+			vfree(lc->clean_bits);
+		vfree(lc->disk_header);
 		kfree(lc);
 		return -ENOMEM;
 	}
 	memset(lc->recovering_bits, 0, bitset_size);
 	lc->sync_search = 0;
 	log->context = lc;
+
 	return 0;
 }
 
+static int core_ctr(struct dirty_log *log, struct dm_target *ti,
+		    unsigned int argc, char **argv)
+{
+	return create_log_context(log, ti, argc, argv, NULL);
+}
+
+static void destroy_log_context(struct log_c *lc)
+{
+	vfree(lc->sync_bits);
+	vfree(lc->recovering_bits);
+	kfree(lc);
+}
+
 static void core_dtr(struct dirty_log *log)
 {
 	struct log_c *lc = (struct log_c *) log->context;
+
 	vfree(lc->clean_bits);
-	vfree(lc->sync_bits);
-	vfree(lc->recovering_bits);
-	kfree(lc);
+	destroy_log_context(lc);
 }
 
 /*----------------------------------------------------------------
@@ -373,8 +397,6 @@
 		    unsigned int argc, char **argv)
 {
 	int r;
-	size_t size;
-	struct log_c *lc;
 	struct dm_dev *dev;
 
 	if (argc < 2 || argc > 3) {
@@ -387,49 +409,22 @@
 	if (r)
 		return r;
 
-	r = core_ctr(log, ti, argc - 1, argv + 1);
+	r = create_log_context(log, ti, argc - 1, argv + 1, dev);
 	if (r) {
 		dm_put_device(ti, dev);
 		return r;
 	}
 
-	lc = (struct log_c *) log->context;
-	lc->log_dev = dev;
-
-	/* setup the disk header fields */
-	lc->header_location.bdev = lc->log_dev->bdev;
-	lc->header_location.sector = 0;
-	lc->header_location.count = 1;
-
-	/*
-	 * We can't read less than this amount, even though we'll
-	 * not be using most of this space.
-	 */
-	lc->disk_header = vmalloc(1 << SECTOR_SHIFT);
-	if (!lc->disk_header)
-		goto bad;
-
-	/* setup the disk bitset fields */
-	lc->bits_location.bdev = lc->log_dev->bdev;
-	lc->bits_location.sector = LOG_OFFSET;
-
-	size = dm_round_up(lc->bitset_uint32_count * sizeof(uint32_t),
-			   1 << SECTOR_SHIFT);
-	lc->bits_location.count = size >> SECTOR_SHIFT;
 	return 0;
-
- bad:
-	dm_put_device(ti, lc->log_dev);
-	core_dtr(log);
-	return -ENOMEM;
 }
 
 static void disk_dtr(struct dirty_log *log)
 {
 	struct log_c *lc = (struct log_c *) log->context;
+
 	dm_put_device(lc->ti, lc->log_dev);
 	vfree(lc->disk_header);
-	core_dtr(log);
+	destroy_log_context(lc);
 }
 
 static int count_bits32(uint32_t *addr, unsigned size)
@@ -454,12 +449,7 @@
 	if (r)
 		return r;
 
-	/* read the bits */
-	r = read_bits(lc);
-	if (r)
-		return r;
-
-	/* set or clear any new bits */
+	/* set or clear any new bits -- device has grown */
 	if (lc->sync == NOSYNC)
 		for (i = lc->header.nr_regions; i < lc->region_count; i++)
 			/* FIXME: amazingly inefficient */
@@ -469,15 +459,14 @@
 			/* FIXME: amazingly inefficient */
 			log_clear_bit(lc, lc->clean_bits, i);
 
+	/* clear any old bits -- device has shrunk */
+	for (i = lc->region_count; i % (sizeof(*lc->clean_bits) << BYTE_SHIFT); i++)
+		log_clear_bit(lc, lc->clean_bits, i);
+
 	/* copy clean across to sync */
 	memcpy(lc->sync_bits, lc->clean_bits, size);
 	lc->sync_count = count_bits32(lc->clean_bits, lc->bitset_uint32_count);
 
-	/* write the bits */
-	r = write_bits(lc);
-	if (r)
-		return r;
-
 	/* set the correct number of regions in the header */
 	lc->header.nr_regions = lc->region_count;
 
@@ -518,7 +507,7 @@
 	if (!lc->touched)
 		return 0;
 
-	r = write_bits(lc);
+	r = write_header(lc);
 	if (!r)
 		lc->touched = 0;
 
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 1816f30..217615b 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <asm/atomic.h>
 
+#define DM_MSG_PREFIX "multipath"
 #define MESG_STR(x) x, sizeof(x)
 
 /* Path properties */
@@ -446,8 +447,6 @@
 	char *error;
 };
 
-#define ESTR(s) ("dm-multipath: " s)
-
 static int read_param(struct param *param, char *str, unsigned *v, char **error)
 {
 	if (!str ||
@@ -495,12 +494,12 @@
 	unsigned ps_argc;
 
 	static struct param _params[] = {
-		{0, 1024, ESTR("invalid number of path selector args")},
+		{0, 1024, "invalid number of path selector args"},
 	};
 
 	pst = dm_get_path_selector(shift(as));
 	if (!pst) {
-		ti->error = ESTR("unknown path selector type");
+		ti->error = "unknown path selector type";
 		return -EINVAL;
 	}
 
@@ -511,7 +510,7 @@
 	r = pst->create(&pg->ps, ps_argc, as->argv);
 	if (r) {
 		dm_put_path_selector(pst);
-		ti->error = ESTR("path selector constructor failed");
+		ti->error = "path selector constructor failed";
 		return r;
 	}
 
@@ -529,7 +528,7 @@
 
 	/* we need at least a path arg */
 	if (as->argc < 1) {
-		ti->error = ESTR("no device given");
+		ti->error = "no device given";
 		return NULL;
 	}
 
@@ -540,7 +539,7 @@
 	r = dm_get_device(ti, shift(as), ti->begin, ti->len,
 			  dm_table_get_mode(ti->table), &p->path.dev);
 	if (r) {
-		ti->error = ESTR("error getting device");
+		ti->error = "error getting device";
 		goto bad;
 	}
 
@@ -562,8 +561,8 @@
 						   struct dm_target *ti)
 {
 	static struct param _params[] = {
-		{1, 1024, ESTR("invalid number of paths")},
-		{0, 1024, ESTR("invalid number of selector args")}
+		{1, 1024, "invalid number of paths"},
+		{0, 1024, "invalid number of selector args"}
 	};
 
 	int r;
@@ -572,13 +571,13 @@
 
 	if (as->argc < 2) {
 		as->argc = 0;
-		ti->error = ESTR("not enough priority group aruments");
+		ti->error = "not enough priority group aruments";
 		return NULL;
 	}
 
 	pg = alloc_priority_group();
 	if (!pg) {
-		ti->error = ESTR("couldn't allocate priority group");
+		ti->error = "couldn't allocate priority group";
 		return NULL;
 	}
 	pg->m = m;
@@ -633,7 +632,7 @@
 	unsigned hw_argc;
 
 	static struct param _params[] = {
-		{0, 1024, ESTR("invalid number of hardware handler args")},
+		{0, 1024, "invalid number of hardware handler args"},
 	};
 
 	r = read_param(_params, shift(as), &hw_argc, &ti->error);
@@ -645,14 +644,14 @@
 
 	hwht = dm_get_hw_handler(shift(as));
 	if (!hwht) {
-		ti->error = ESTR("unknown hardware handler type");
+		ti->error = "unknown hardware handler type";
 		return -EINVAL;
 	}
 
 	r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv);
 	if (r) {
 		dm_put_hw_handler(hwht);
-		ti->error = ESTR("hardware handler constructor failed");
+		ti->error = "hardware handler constructor failed";
 		return r;
 	}
 
@@ -669,7 +668,7 @@
 	unsigned argc;
 
 	static struct param _params[] = {
-		{0, 1, ESTR("invalid number of feature args")},
+		{0, 1, "invalid number of feature args"},
 	};
 
 	r = read_param(_params, shift(as), &argc, &ti->error);
@@ -692,8 +691,8 @@
 {
 	/* target parameters */
 	static struct param _params[] = {
-		{1, 1024, ESTR("invalid number of priority groups")},
-		{1, 1024, ESTR("invalid initial priority group number")},
+		{1, 1024, "invalid number of priority groups"},
+		{1, 1024, "invalid initial priority group number"},
 	};
 
 	int r;
@@ -707,7 +706,7 @@
 
 	m = alloc_multipath();
 	if (!m) {
-		ti->error = ESTR("can't allocate multipath");
+		ti->error = "can't allocate multipath";
 		return -EINVAL;
 	}
 
@@ -746,7 +745,7 @@
 	}
 
 	if (pg_count != m->nr_priority_groups) {
-		ti->error = ESTR("priority group count mismatch");
+		ti->error = "priority group count mismatch";
 		r = -EINVAL;
 		goto bad;
 	}
@@ -807,7 +806,7 @@
 	if (!pgpath->path.is_active)
 		goto out;
 
-	DMWARN("dm-multipath: Failing path %s.", pgpath->path.dev->name);
+	DMWARN("Failing path %s.", pgpath->path.dev->name);
 
 	pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path);
 	pgpath->path.is_active = 0;
@@ -1250,7 +1249,7 @@
 	r = dm_get_device(ti, argv[1], ti->begin, ti->len,
 			  dm_table_get_mode(ti->table), &dev);
 	if (r) {
-		DMWARN("dm-multipath message: error getting device %s",
+		DMWARN("message: error getting device %s",
 		       argv[1]);
 		return -EINVAL;
 	}
@@ -1309,7 +1308,7 @@
 		return -ENOMEM;
 	}
 
-	DMINFO("dm-multipath version %u.%u.%u loaded",
+	DMINFO("version %u.%u.%u loaded",
 	       multipath_target.version[0], multipath_target.version[1],
 	       multipath_target.version[2]);
 
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index d12cf3e..be48ced 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -20,6 +20,8 @@
 #include <linux/vmalloc.h>
 #include <linux/workqueue.h>
 
+#define DM_MSG_PREFIX "raid1"
+
 static struct workqueue_struct *_kmirrord_wq;
 static struct work_struct _kmirrord_work;
 
@@ -106,12 +108,42 @@
 	struct bio_list delayed_bios;
 };
 
+
+/*-----------------------------------------------------------------
+ * Mirror set structures.
+ *---------------------------------------------------------------*/
+struct mirror {
+	atomic_t error_count;
+	struct dm_dev *dev;
+	sector_t offset;
+};
+
+struct mirror_set {
+	struct dm_target *ti;
+	struct list_head list;
+	struct region_hash rh;
+	struct kcopyd_client *kcopyd_client;
+
+	spinlock_t lock;	/* protects the next two lists */
+	struct bio_list reads;
+	struct bio_list writes;
+
+	/* recovery */
+	region_t nr_regions;
+	int in_sync;
+
+	struct mirror *default_mirror;	/* Default mirror */
+
+	unsigned int nr_mirrors;
+	struct mirror mirror[0];
+};
+
 /*
  * Conversion fns
  */
 static inline region_t bio_to_region(struct region_hash *rh, struct bio *bio)
 {
-	return bio->bi_sector >> rh->region_shift;
+	return (bio->bi_sector - rh->ms->ti->begin) >> rh->region_shift;
 }
 
 static inline sector_t region_to_sector(struct region_hash *rh, region_t region)
@@ -458,11 +490,9 @@
 	/* Already quiesced ? */
 	if (atomic_read(&reg->pending))
 		list_del_init(&reg->list);
+	else
+		list_move(&reg->list, &rh->quiesced_regions);
 
-	else {
-		list_del_init(&reg->list);
-		list_add(&reg->list, &rh->quiesced_regions);
-	}
 	spin_unlock_irq(&rh->region_lock);
 
 	return 1;
@@ -541,35 +571,6 @@
 	wake();
 }
 
-/*-----------------------------------------------------------------
- * Mirror set structures.
- *---------------------------------------------------------------*/
-struct mirror {
-	atomic_t error_count;
-	struct dm_dev *dev;
-	sector_t offset;
-};
-
-struct mirror_set {
-	struct dm_target *ti;
-	struct list_head list;
-	struct region_hash rh;
-	struct kcopyd_client *kcopyd_client;
-
-	spinlock_t lock;	/* protects the next two lists */
-	struct bio_list reads;
-	struct bio_list writes;
-
-	/* recovery */
-	region_t nr_regions;
-	int in_sync;
-
-	struct mirror *default_mirror;	/* Default mirror */
-
-	unsigned int nr_mirrors;
-	struct mirror mirror[0];
-};
-
 /*
  * Every mirror should look like this one.
  */
@@ -603,7 +604,7 @@
 	struct region *reg = (struct region *) context;
 
 	/* FIXME: better error handling */
-	rh_recovery_end(reg, read_err || write_err);
+	rh_recovery_end(reg, !(read_err || write_err));
 }
 
 static int recover(struct mirror_set *ms, struct region *reg)
@@ -893,7 +894,7 @@
 
 	ms = kmalloc(len, GFP_KERNEL);
 	if (!ms) {
-		ti->error = "dm-mirror: Cannot allocate mirror context";
+		ti->error = "Cannot allocate mirror context";
 		return NULL;
 	}
 
@@ -907,7 +908,7 @@
 	ms->default_mirror = &ms->mirror[DEFAULT_MIRROR];
 
 	if (rh_init(&ms->rh, ms, dl, region_size, ms->nr_regions)) {
-		ti->error = "dm-mirror: Error creating dirty region hash";
+		ti->error = "Error creating dirty region hash";
 		kfree(ms);
 		return NULL;
 	}
@@ -937,14 +938,14 @@
 	unsigned long long offset;
 
 	if (sscanf(argv[1], "%llu", &offset) != 1) {
-		ti->error = "dm-mirror: Invalid offset";
+		ti->error = "Invalid offset";
 		return -EINVAL;
 	}
 
 	if (dm_get_device(ti, argv[0], offset, ti->len,
 			  dm_table_get_mode(ti->table),
 			  &ms->mirror[mirror].dev)) {
-		ti->error = "dm-mirror: Device lookup failure";
+		ti->error = "Device lookup failure";
 		return -ENXIO;
 	}
 
@@ -981,30 +982,30 @@
 	struct dirty_log *dl;
 
 	if (argc < 2) {
-		ti->error = "dm-mirror: Insufficient mirror log arguments";
+		ti->error = "Insufficient mirror log arguments";
 		return NULL;
 	}
 
 	if (sscanf(argv[1], "%u", &param_count) != 1) {
-		ti->error = "dm-mirror: Invalid mirror log argument count";
+		ti->error = "Invalid mirror log argument count";
 		return NULL;
 	}
 
 	*args_used = 2 + param_count;
 
 	if (argc < *args_used) {
-		ti->error = "dm-mirror: Insufficient mirror log arguments";
+		ti->error = "Insufficient mirror log arguments";
 		return NULL;
 	}
 
 	dl = dm_create_dirty_log(argv[0], ti, param_count, argv + 2);
 	if (!dl) {
-		ti->error = "dm-mirror: Error creating mirror dirty log";
+		ti->error = "Error creating mirror dirty log";
 		return NULL;
 	}
 
 	if (!_check_region_size(ti, dl->type->get_region_size(dl))) {
-		ti->error = "dm-mirror: Invalid region size";
+		ti->error = "Invalid region size";
 		dm_destroy_dirty_log(dl);
 		return NULL;
 	}
@@ -1038,7 +1039,7 @@
 
 	if (!argc || sscanf(argv[0], "%u", &nr_mirrors) != 1 ||
 	    nr_mirrors < 2 || nr_mirrors > KCOPYD_MAX_REGIONS + 1) {
-		ti->error = "dm-mirror: Invalid number of mirrors";
+		ti->error = "Invalid number of mirrors";
 		dm_destroy_dirty_log(dl);
 		return -EINVAL;
 	}
@@ -1046,7 +1047,7 @@
 	argv++, argc--;
 
 	if (argc != nr_mirrors * 2) {
-		ti->error = "dm-mirror: Wrong number of mirror arguments";
+		ti->error = "Wrong number of mirror arguments";
 		dm_destroy_dirty_log(dl);
 		return -EINVAL;
 	}
@@ -1115,7 +1116,7 @@
 	struct mirror *m;
 	struct mirror_set *ms = ti->private;
 
-	map_context->ll = bio->bi_sector >> ms->rh.region_shift;
+	map_context->ll = bio_to_region(&ms->rh, bio);
 
 	if (rw == WRITE) {
 		queue_bio(ms, bio, rw);
@@ -1221,7 +1222,7 @@
 
 static struct target_type mirror_target = {
 	.name	 = "mirror",
-	.version = {1, 0, 1},
+	.version = {1, 0, 2},
 	.module	 = THIS_MODULE,
 	.ctr	 = mirror_ctr,
 	.dtr	 = mirror_dtr,
diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
index d002486..c5a16c5 100644
--- a/drivers/md/dm-round-robin.c
+++ b/drivers/md/dm-round-robin.c
@@ -14,6 +14,8 @@
 
 #include <linux/slab.h>
 
+#define DM_MSG_PREFIX "multipath round-robin"
+
 /*-----------------------------------------------------------------
  * Path-handling code, paths are held in lists
  *---------------------------------------------------------------*/
@@ -191,9 +193,9 @@
 	int r = dm_register_path_selector(&rr_ps);
 
 	if (r < 0)
-		DMERR("round-robin: register failed %d", r);
+		DMERR("register failed %d", r);
 
-	DMINFO("dm-round-robin version 1.0.0 loaded");
+	DMINFO("version 1.0.0 loaded");
 
 	return r;
 }
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 08312b4..8eea0ddb 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -23,6 +23,8 @@
 #include "dm-bio-list.h"
 #include "kcopyd.h"
 
+#define DM_MSG_PREFIX "snapshots"
+
 /*
  * The percentage increment we will wake up users at
  */
@@ -117,7 +119,7 @@
 	_origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
 			   GFP_KERNEL);
 	if (!_origins) {
-		DMERR("Device mapper: Snapshot: unable to allocate memory");
+		DMERR("unable to allocate memory");
 		return -ENOMEM;
 	}
 
@@ -412,7 +414,7 @@
 	int blocksize;
 
 	if (argc < 4) {
-		ti->error = "dm-snapshot: requires exactly 4 arguments";
+		ti->error = "requires exactly 4 arguments";
 		r = -EINVAL;
 		goto bad1;
 	}
@@ -530,7 +532,7 @@
 	}
 
 	ti->private = s;
-	ti->split_io = chunk_size;
+	ti->split_io = s->chunk_size;
 
 	return 0;
 
@@ -1127,7 +1129,7 @@
 	struct dm_dev *dev;
 
 	if (argc != 1) {
-		ti->error = "dm-origin: incorrect number of arguments";
+		ti->error = "origin: incorrect number of arguments";
 		return -EINVAL;
 	}
 
@@ -1204,7 +1206,7 @@
 
 static struct target_type origin_target = {
 	.name    = "snapshot-origin",
-	.version = {1, 1, 0},
+	.version = {1, 4, 0},
 	.module  = THIS_MODULE,
 	.ctr     = origin_ctr,
 	.dtr     = origin_dtr,
@@ -1215,7 +1217,7 @@
 
 static struct target_type snapshot_target = {
 	.name    = "snapshot",
-	.version = {1, 1, 0},
+	.version = {1, 4, 0},
 	.module  = THIS_MODULE,
 	.ctr     = snapshot_ctr,
 	.dtr     = snapshot_dtr,
@@ -1236,7 +1238,7 @@
 
 	r = dm_register_target(&origin_target);
 	if (r < 0) {
-		DMERR("Device mapper: Origin: register failed %d\n", r);
+		DMERR("Origin target register failed %d", r);
 		goto bad1;
 	}
 
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index 08328a8..6c29fce 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -12,6 +12,8 @@
 #include <linux/bio.h>
 #include <linux/slab.h>
 
+#define DM_MSG_PREFIX "striped"
+
 struct stripe {
 	struct dm_dev *dev;
 	sector_t physical_start;
@@ -78,19 +80,19 @@
 	unsigned int i;
 
 	if (argc < 2) {
-		ti->error = "dm-stripe: Not enough arguments";
+		ti->error = "Not enough arguments";
 		return -EINVAL;
 	}
 
 	stripes = simple_strtoul(argv[0], &end, 10);
 	if (*end) {
-		ti->error = "dm-stripe: Invalid stripe count";
+		ti->error = "Invalid stripe count";
 		return -EINVAL;
 	}
 
 	chunk_size = simple_strtoul(argv[1], &end, 10);
 	if (*end) {
-		ti->error = "dm-stripe: Invalid chunk_size";
+		ti->error = "Invalid chunk_size";
 		return -EINVAL;
 	}
 
@@ -99,19 +101,19 @@
 	 */
 	if (!chunk_size || (chunk_size & (chunk_size - 1)) ||
 	    (chunk_size < (PAGE_SIZE >> SECTOR_SHIFT))) {
-		ti->error = "dm-stripe: Invalid chunk size";
+		ti->error = "Invalid chunk size";
 		return -EINVAL;
 	}
 
 	if (ti->len & (chunk_size - 1)) {
-		ti->error = "dm-stripe: Target length not divisible by "
+		ti->error = "Target length not divisible by "
 		    "chunk size";
 		return -EINVAL;
 	}
 
 	width = ti->len;
 	if (sector_div(width, stripes)) {
-		ti->error = "dm-stripe: Target length not divisible by "
+		ti->error = "Target length not divisible by "
 		    "number of stripes";
 		return -EINVAL;
 	}
@@ -120,14 +122,14 @@
 	 * Do we have enough arguments for that many stripes ?
 	 */
 	if (argc != (2 + 2 * stripes)) {
-		ti->error = "dm-stripe: Not enough destinations "
+		ti->error = "Not enough destinations "
 			"specified";
 		return -EINVAL;
 	}
 
 	sc = alloc_context(stripes);
 	if (!sc) {
-		ti->error = "dm-stripe: Memory allocation for striped context "
+		ti->error = "Memory allocation for striped context "
 		    "failed";
 		return -ENOMEM;
 	}
@@ -149,8 +151,7 @@
 
 		r = get_stripe(ti, sc, i, argv);
 		if (r < 0) {
-			ti->error = "dm-stripe: Couldn't parse stripe "
-				"destination";
+			ti->error = "Couldn't parse stripe destination";
 			while (i--)
 				dm_put_device(ti, sc->stripe[i].dev);
 			kfree(sc);
@@ -227,7 +228,7 @@
 
 	r = dm_register_target(&stripe_target);
 	if (r < 0)
-		DMWARN("striped target registration failed");
+		DMWARN("target registration failed");
 
 	return r;
 }
@@ -235,7 +236,7 @@
 void dm_stripe_exit(void)
 {
 	if (dm_unregister_target(&stripe_target))
-		DMWARN("striped target unregistration failed");
+		DMWARN("target unregistration failed");
 
 	return;
 }
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 8f56a54..75fe949 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -17,6 +17,8 @@
 #include <linux/mutex.h>
 #include <asm/atomic.h>
 
+#define DM_MSG_PREFIX "table"
+
 #define MAX_DEPTH 16
 #define NODE_SIZE L1_CACHE_BYTES
 #define KEYS_PER_NODE (NODE_SIZE / sizeof(sector_t))
@@ -237,6 +239,44 @@
 	return 0;
 }
 
+int dm_create_error_table(struct dm_table **result, struct mapped_device *md)
+{
+	struct dm_table *t;
+	sector_t dev_size = 1;
+	int r;
+
+	/*
+	 * Find current size of device.
+	 * Default to 1 sector if inactive.
+	 */
+	t = dm_get_table(md);
+	if (t) {
+		dev_size = dm_table_get_size(t);
+		dm_table_put(t);
+	}
+
+	r = dm_table_create(&t, FMODE_READ, 1, md);
+	if (r)
+		return r;
+
+	r = dm_table_add_target(t, "error", 0, dev_size, NULL);
+	if (r)
+		goto out;
+
+	r = dm_table_complete(t);
+	if (r)
+		goto out;
+
+	*result = t;
+
+out:
+	if (r)
+		dm_table_put(t);
+
+	return r;
+}
+EXPORT_SYMBOL_GPL(dm_create_error_table);
+
 static void free_devices(struct list_head *devices)
 {
 	struct list_head *tmp, *next;
@@ -590,6 +630,12 @@
 	unsigned array_size = 0;
 
 	*argc = 0;
+
+	if (!input) {
+		*argvp = NULL;
+		return 0;
+	}
+
 	argv = realloc_argv(&array_size, argv);
 	if (!argv)
 		return -ENOMEM;
@@ -671,15 +717,14 @@
 	memset(tgt, 0, sizeof(*tgt));
 
 	if (!len) {
-		tgt->error = "zero-length target";
-		DMERR("%s", tgt->error);
+		DMERR("%s: zero-length target", dm_device_name(t->md));
 		return -EINVAL;
 	}
 
 	tgt->type = dm_get_target_type(type);
 	if (!tgt->type) {
-		tgt->error = "unknown target type";
-		DMERR("%s", tgt->error);
+		DMERR("%s: %s: unknown target type", dm_device_name(t->md),
+		      type);
 		return -EINVAL;
 	}
 
@@ -716,7 +761,7 @@
 	return 0;
 
  bad:
-	DMERR("%s", tgt->error);
+	DMERR("%s: %s: %s", dm_device_name(t->md), type, tgt->error);
 	dm_put_target_type(tgt->type);
 	return r;
 }
@@ -802,7 +847,7 @@
 
 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index)
 {
-	if (index > t->num_targets)
+	if (index >= t->num_targets)
 		return NULL;
 
 	return t->targets + index;
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index 64fd8e7..477a041 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -12,6 +12,8 @@
 #include <linux/bio.h>
 #include <linux/slab.h>
 
+#define DM_MSG_PREFIX "target"
+
 struct tt_internal {
 	struct target_type tt;
 
diff --git a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
index 51c0639..ea569f7 100644
--- a/drivers/md/dm-zero.c
+++ b/drivers/md/dm-zero.c
@@ -10,13 +10,15 @@
 #include <linux/init.h>
 #include <linux/bio.h>
 
+#define DM_MSG_PREFIX "zero"
+
 /*
  * Construct a dummy mapping that only returns zeros
  */
 static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 {
 	if (argc != 0) {
-		ti->error = "dm-zero: No arguments required";
+		ti->error = "No arguments required";
 		return -EINVAL;
 	}
 
@@ -60,7 +62,7 @@
 	int r = dm_register_target(&zero_target);
 
 	if (r < 0)
-		DMERR("zero: register failed %d", r);
+		DMERR("register failed %d", r);
 
 	return r;
 }
@@ -70,7 +72,7 @@
 	int r = dm_unregister_target(&zero_target);
 
 	if (r < 0)
-		DMERR("zero: unregister failed %d", r);
+		DMERR("unregister failed %d", r);
 }
 
 module_init(dm_zero_init)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 4d710b7..3ed2e53 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001, 2002 Sistina Software (UK) Limited.
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the GPL.
  */
@@ -21,11 +21,14 @@
 #include <linux/hdreg.h>
 #include <linux/blktrace_api.h>
 
+#define DM_MSG_PREFIX "core"
+
 static const char *_name = DM_NAME;
 
 static unsigned int major = 0;
 static unsigned int _major = 0;
 
+static DEFINE_SPINLOCK(_minor_lock);
 /*
  * One of these is allocated per bio.
  */
@@ -49,23 +52,28 @@
 
 union map_info *dm_get_mapinfo(struct bio *bio)
 {
-        if (bio && bio->bi_private)
-                return &((struct target_io *)bio->bi_private)->info;
-        return NULL;
+	if (bio && bio->bi_private)
+		return &((struct target_io *)bio->bi_private)->info;
+	return NULL;
 }
 
+#define MINOR_ALLOCED ((void *)-1)
+
 /*
  * Bits for the md->flags field.
  */
 #define DMF_BLOCK_IO 0
 #define DMF_SUSPENDED 1
 #define DMF_FROZEN 2
+#define DMF_FREEING 3
+#define DMF_DELETING 4
 
 struct mapped_device {
 	struct rw_semaphore io_lock;
 	struct semaphore suspend_lock;
 	rwlock_t map_lock;
 	atomic_t holders;
+	atomic_t open_count;
 
 	unsigned long flags;
 
@@ -218,9 +226,25 @@
 {
 	struct mapped_device *md;
 
+	spin_lock(&_minor_lock);
+
 	md = inode->i_bdev->bd_disk->private_data;
+	if (!md)
+		goto out;
+
+	if (test_bit(DMF_FREEING, &md->flags) ||
+	    test_bit(DMF_DELETING, &md->flags)) {
+		md = NULL;
+		goto out;
+	}
+
 	dm_get(md);
-	return 0;
+	atomic_inc(&md->open_count);
+
+out:
+	spin_unlock(&_minor_lock);
+
+	return md ? 0 : -ENXIO;
 }
 
 static int dm_blk_close(struct inode *inode, struct file *file)
@@ -228,10 +252,35 @@
 	struct mapped_device *md;
 
 	md = inode->i_bdev->bd_disk->private_data;
+	atomic_dec(&md->open_count);
 	dm_put(md);
 	return 0;
 }
 
+int dm_open_count(struct mapped_device *md)
+{
+	return atomic_read(&md->open_count);
+}
+
+/*
+ * Guarantees nothing is using the device before it's deleted.
+ */
+int dm_lock_for_deletion(struct mapped_device *md)
+{
+	int r = 0;
+
+	spin_lock(&_minor_lock);
+
+	if (dm_open_count(md))
+		r = -EBUSY;
+	else
+		set_bit(DMF_DELETING, &md->flags);
+
+	spin_unlock(&_minor_lock);
+
+	return r;
+}
+
 static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
 	struct mapped_device *md = bdev->bd_disk->private_data;
@@ -456,8 +505,8 @@
 	if (r > 0) {
 		/* the bio has been remapped so dispatch it */
 
-		blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone, 
-				    tio->io->bio->bi_bdev->bd_dev, sector, 
+		blk_add_trace_remap(bdev_get_queue(clone->bi_bdev), clone,
+				    tio->io->bio->bi_bdev->bd_dev, sector,
 				    clone->bi_sector);
 
 		generic_make_request(clone);
@@ -744,43 +793,39 @@
 /*-----------------------------------------------------------------
  * An IDR is used to keep track of allocated minor numbers.
  *---------------------------------------------------------------*/
-static DEFINE_MUTEX(_minor_lock);
 static DEFINE_IDR(_minor_idr);
 
-static void free_minor(unsigned int minor)
+static void free_minor(int minor)
 {
-	mutex_lock(&_minor_lock);
+	spin_lock(&_minor_lock);
 	idr_remove(&_minor_idr, minor);
-	mutex_unlock(&_minor_lock);
+	spin_unlock(&_minor_lock);
 }
 
 /*
  * See if the device with a specific minor # is free.
  */
-static int specific_minor(struct mapped_device *md, unsigned int minor)
+static int specific_minor(struct mapped_device *md, int minor)
 {
 	int r, m;
 
 	if (minor >= (1 << MINORBITS))
 		return -EINVAL;
 
-	mutex_lock(&_minor_lock);
+	r = idr_pre_get(&_minor_idr, GFP_KERNEL);
+	if (!r)
+		return -ENOMEM;
+
+	spin_lock(&_minor_lock);
 
 	if (idr_find(&_minor_idr, minor)) {
 		r = -EBUSY;
 		goto out;
 	}
 
-	r = idr_pre_get(&_minor_idr, GFP_KERNEL);
-	if (!r) {
-		r = -ENOMEM;
+	r = idr_get_new_above(&_minor_idr, MINOR_ALLOCED, minor, &m);
+	if (r)
 		goto out;
-	}
-
-	r = idr_get_new_above(&_minor_idr, md, minor, &m);
-	if (r) {
-		goto out;
-	}
 
 	if (m != minor) {
 		idr_remove(&_minor_idr, m);
@@ -789,24 +834,21 @@
 	}
 
 out:
-	mutex_unlock(&_minor_lock);
+	spin_unlock(&_minor_lock);
 	return r;
 }
 
-static int next_free_minor(struct mapped_device *md, unsigned int *minor)
+static int next_free_minor(struct mapped_device *md, int *minor)
 {
-	int r;
-	unsigned int m;
-
-	mutex_lock(&_minor_lock);
+	int r, m;
 
 	r = idr_pre_get(&_minor_idr, GFP_KERNEL);
-	if (!r) {
-		r = -ENOMEM;
-		goto out;
-	}
+	if (!r)
+		return -ENOMEM;
 
-	r = idr_get_new(&_minor_idr, md, &m);
+	spin_lock(&_minor_lock);
+
+	r = idr_get_new(&_minor_idr, MINOR_ALLOCED, &m);
 	if (r) {
 		goto out;
 	}
@@ -820,7 +862,7 @@
 	*minor = m;
 
 out:
-	mutex_unlock(&_minor_lock);
+	spin_unlock(&_minor_lock);
 	return r;
 }
 
@@ -829,18 +871,25 @@
 /*
  * Allocate and initialise a blank device with a given minor.
  */
-static struct mapped_device *alloc_dev(unsigned int minor, int persistent)
+static struct mapped_device *alloc_dev(int minor)
 {
 	int r;
 	struct mapped_device *md = kmalloc(sizeof(*md), GFP_KERNEL);
+	void *old_md;
 
 	if (!md) {
 		DMWARN("unable to allocate device, out of memory.");
 		return NULL;
 	}
 
+	if (!try_module_get(THIS_MODULE))
+		goto bad0;
+
 	/* get a minor number for the dev */
-	r = persistent ? specific_minor(md, minor) : next_free_minor(md, &minor);
+	if (minor == DM_ANY_MINOR)
+		r = next_free_minor(md, &minor);
+	else
+		r = specific_minor(md, minor);
 	if (r < 0)
 		goto bad1;
 
@@ -849,6 +898,7 @@
 	init_MUTEX(&md->suspend_lock);
 	rwlock_init(&md->map_lock);
 	atomic_set(&md->holders, 1);
+	atomic_set(&md->open_count, 0);
 	atomic_set(&md->event_nr, 0);
 
 	md->queue = blk_alloc_queue(GFP_KERNEL);
@@ -875,6 +925,10 @@
 	if (!md->disk)
 		goto bad4;
 
+	atomic_set(&md->pending, 0);
+	init_waitqueue_head(&md->wait);
+	init_waitqueue_head(&md->eventq);
+
 	md->disk->major = _major;
 	md->disk->first_minor = minor;
 	md->disk->fops = &dm_blk_dops;
@@ -884,9 +938,12 @@
 	add_disk(md->disk);
 	format_dev_t(md->name, MKDEV(_major, minor));
 
-	atomic_set(&md->pending, 0);
-	init_waitqueue_head(&md->wait);
-	init_waitqueue_head(&md->eventq);
+	/* Populate the mapping, nobody knows we exist yet */
+	spin_lock(&_minor_lock);
+	old_md = idr_replace(&_minor_idr, md, minor);
+	spin_unlock(&_minor_lock);
+
+	BUG_ON(old_md != MINOR_ALLOCED);
 
 	return md;
 
@@ -898,13 +955,15 @@
 	blk_cleanup_queue(md->queue);
 	free_minor(minor);
  bad1:
+	module_put(THIS_MODULE);
+ bad0:
 	kfree(md);
 	return NULL;
 }
 
 static void free_dev(struct mapped_device *md)
 {
-	unsigned int minor = md->disk->first_minor;
+	int minor = md->disk->first_minor;
 
 	if (md->suspended_bdev) {
 		thaw_bdev(md->suspended_bdev, NULL);
@@ -914,8 +973,14 @@
 	mempool_destroy(md->io_pool);
 	del_gendisk(md->disk);
 	free_minor(minor);
+
+	spin_lock(&_minor_lock);
+	md->disk->private_data = NULL;
+	spin_unlock(&_minor_lock);
+
 	put_disk(md->disk);
 	blk_cleanup_queue(md->queue);
+	module_put(THIS_MODULE);
 	kfree(md);
 }
 
@@ -984,12 +1049,11 @@
 /*
  * Constructor for a new device.
  */
-static int create_aux(unsigned int minor, int persistent,
-		      struct mapped_device **result)
+int dm_create(int minor, struct mapped_device **result)
 {
 	struct mapped_device *md;
 
-	md = alloc_dev(minor, persistent);
+	md = alloc_dev(minor);
 	if (!md)
 		return -ENXIO;
 
@@ -997,16 +1061,6 @@
 	return 0;
 }
 
-int dm_create(struct mapped_device **result)
-{
-	return create_aux(0, 0, result);
-}
-
-int dm_create_with_minor(unsigned int minor, struct mapped_device **result)
-{
-	return create_aux(minor, 1, result);
-}
-
 static struct mapped_device *dm_find_md(dev_t dev)
 {
 	struct mapped_device *md;
@@ -1015,13 +1069,18 @@
 	if (MAJOR(dev) != _major || minor >= (1 << MINORBITS))
 		return NULL;
 
-	mutex_lock(&_minor_lock);
+	spin_lock(&_minor_lock);
 
 	md = idr_find(&_minor_idr, minor);
-	if (!md || (dm_disk(md)->first_minor != minor))
+	if (md && (md == MINOR_ALLOCED ||
+		   (dm_disk(md)->first_minor != minor) ||
+		   test_bit(DMF_FREEING, &md->flags))) {
 		md = NULL;
+		goto out;
+	}
 
-	mutex_unlock(&_minor_lock);
+out:
+	spin_unlock(&_minor_lock);
 
 	return md;
 }
@@ -1051,12 +1110,23 @@
 	atomic_inc(&md->holders);
 }
 
+const char *dm_device_name(struct mapped_device *md)
+{
+	return md->name;
+}
+EXPORT_SYMBOL_GPL(dm_device_name);
+
 void dm_put(struct mapped_device *md)
 {
 	struct dm_table *map;
 
-	if (atomic_dec_and_test(&md->holders)) {
+	BUG_ON(test_bit(DMF_FREEING, &md->flags));
+
+	if (atomic_dec_and_lock(&md->holders, &_minor_lock)) {
 		map = dm_get_table(md);
+		idr_replace(&_minor_idr, MINOR_ALLOCED, dm_disk(md)->first_minor);
+		set_bit(DMF_FREEING, &md->flags);
+		spin_unlock(&_minor_lock);
 		if (!dm_suspended(md)) {
 			dm_table_presuspend_targets(map);
 			dm_table_postsuspend_targets(map);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index fd90bc8..3c03c0e 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -2,7 +2,7 @@
  * Internal header file for device mapper
  *
  * Copyright (C) 2001, 2002 Sistina Software
- * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the LGPL.
  */
@@ -17,9 +17,10 @@
 #include <linux/hdreg.h>
 
 #define DM_NAME "device-mapper"
-#define DMWARN(f, x...) printk(KERN_WARNING DM_NAME ": " f "\n" , ## x)
-#define DMERR(f, x...) printk(KERN_ERR DM_NAME ": " f "\n" , ## x)
-#define DMINFO(f, x...) printk(KERN_INFO DM_NAME ": " f "\n" , ## x)
+
+#define DMERR(f, arg...) printk(KERN_ERR DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMWARN(f, arg...) printk(KERN_WARNING DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
+#define DMINFO(f, arg...) printk(KERN_INFO DM_NAME ": " DM_MSG_PREFIX ": " f "\n", ## arg)
 
 #define DMEMIT(x...) sz += ((sz >= maxlen) ? \
 			  0 : scnprintf(result + sz, maxlen - sz, x))
@@ -39,83 +40,16 @@
 };
 
 struct dm_table;
-struct mapped_device;
 
 /*-----------------------------------------------------------------
- * Functions for manipulating a struct mapped_device.
- * Drop the reference with dm_put when you finish with the object.
+ * Internal table functions.
  *---------------------------------------------------------------*/
-int dm_create(struct mapped_device **md);
-int dm_create_with_minor(unsigned int minor, struct mapped_device **md);
-void dm_set_mdptr(struct mapped_device *md, void *ptr);
-void *dm_get_mdptr(struct mapped_device *md);
-struct mapped_device *dm_get_md(dev_t dev);
-
-/*
- * Reference counting for md.
- */
-void dm_get(struct mapped_device *md);
-void dm_put(struct mapped_device *md);
-
-/*
- * A device can still be used while suspended, but I/O is deferred.
- */
-int dm_suspend(struct mapped_device *md, int with_lockfs);
-int dm_resume(struct mapped_device *md);
-
-/*
- * The device must be suspended before calling this method.
- */
-int dm_swap_table(struct mapped_device *md, struct dm_table *t);
-
-/*
- * Drop a reference on the table when you've finished with the
- * result.
- */
-struct dm_table *dm_get_table(struct mapped_device *md);
-
-/*
- * Event functions.
- */
-uint32_t dm_get_event_nr(struct mapped_device *md);
-int dm_wait_event(struct mapped_device *md, int event_nr);
-
-/*
- * Info functions.
- */
-struct gendisk *dm_disk(struct mapped_device *md);
-int dm_suspended(struct mapped_device *md);
-
-/*
- * Geometry functions.
- */
-int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo);
-int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
-
-/*-----------------------------------------------------------------
- * Functions for manipulating a table.  Tables are also reference
- * counted.
- *---------------------------------------------------------------*/
-int dm_table_create(struct dm_table **result, int mode,
-		    unsigned num_targets, struct mapped_device *md);
-
-void dm_table_get(struct dm_table *t);
-void dm_table_put(struct dm_table *t);
-
-int dm_table_add_target(struct dm_table *t, const char *type,
-			sector_t start,	sector_t len, char *params);
-int dm_table_complete(struct dm_table *t);
 void dm_table_event_callback(struct dm_table *t,
 			     void (*fn)(void *), void *context);
-void dm_table_event(struct dm_table *t);
-sector_t dm_table_get_size(struct dm_table *t);
 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
 struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector);
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
-unsigned int dm_table_get_num_targets(struct dm_table *t);
 struct list_head *dm_table_get_devices(struct dm_table *t);
-int dm_table_get_mode(struct dm_table *t);
-struct mapped_device *dm_table_get_md(struct dm_table *t);
 void dm_table_presuspend_targets(struct dm_table *t);
 void dm_table_postsuspend_targets(struct dm_table *t);
 void dm_table_resume_targets(struct dm_table *t);
@@ -133,7 +67,6 @@
 int dm_target_iterate(void (*iter_func)(struct target_type *tt,
 					void *param), void *param);
 
-
 /*-----------------------------------------------------------------
  * Useful inlines.
  *---------------------------------------------------------------*/
@@ -191,5 +124,7 @@
 
 void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
 union map_info *dm_get_mapinfo(struct bio *bio);
+int dm_open_count(struct mapped_device *md);
+int dm_lock_for_deletion(struct mapped_device *md);
 
 #endif
diff --git a/drivers/md/kcopyd.c b/drivers/md/kcopyd.c
index 72480a4..73ab875 100644
--- a/drivers/md/kcopyd.c
+++ b/drivers/md/kcopyd.c
@@ -314,7 +314,7 @@
 
 	if (error) {
 		if (job->rw == WRITE)
-			job->write_err &= error;
+			job->write_err |= error;
 		else
 			job->read_err = 1;
 
@@ -460,7 +460,7 @@
 		job->read_err = 1;
 
 	if (write_err)
-		job->write_err &= write_err;
+		job->write_err |= write_err;
 
 	/*
 	 * Only dispatch more work if there hasn't been an error.
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 7775854..ff83c9b 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -111,7 +111,7 @@
 	return ret;
 }
 
-static int linear_run (mddev_t *mddev)
+static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
 {
 	linear_conf_t *conf;
 	dev_info_t **table;
@@ -121,20 +121,21 @@
 	sector_t curr_offset;
 	struct list_head *tmp;
 
-	conf = kzalloc (sizeof (*conf) + mddev->raid_disks*sizeof(dev_info_t),
+	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
 			GFP_KERNEL);
 	if (!conf)
-		goto out;
+		return NULL;
+
 	mddev->private = conf;
 
 	cnt = 0;
-	mddev->array_size = 0;
+	conf->array_size = 0;
 
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		int j = rdev->raid_disk;
 		dev_info_t *disk = conf->disks + j;
 
-		if (j < 0 || j > mddev->raid_disks || disk->rdev) {
+		if (j < 0 || j > raid_disks || disk->rdev) {
 			printk("linear: disk numbering problem. Aborting!\n");
 			goto out;
 		}
@@ -152,11 +153,11 @@
 			blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
 
 		disk->size = rdev->size;
-		mddev->array_size += rdev->size;
+		conf->array_size += rdev->size;
 
 		cnt++;
 	}
-	if (cnt != mddev->raid_disks) {
+	if (cnt != raid_disks) {
 		printk("linear: not enough drives present. Aborting!\n");
 		goto out;
 	}
@@ -200,7 +201,7 @@
 		unsigned round;
 		unsigned long base;
 
-		sz = mddev->array_size >> conf->preshift;
+		sz = conf->array_size >> conf->preshift;
 		sz += 1; /* force round-up */
 		base = conf->hash_spacing >> conf->preshift;
 		round = sector_div(sz, base);
@@ -247,14 +248,56 @@
 
 	BUG_ON(table - conf->hash_table > nb_zone);
 
+	return conf;
+
+out:
+	kfree(conf);
+	return NULL;
+}
+
+static int linear_run (mddev_t *mddev)
+{
+	linear_conf_t *conf;
+
+	conf = linear_conf(mddev, mddev->raid_disks);
+
+	if (!conf)
+		return 1;
+	mddev->private = conf;
+	mddev->array_size = conf->array_size;
+
 	blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
 	mddev->queue->unplug_fn = linear_unplug;
 	mddev->queue->issue_flush_fn = linear_issue_flush;
 	return 0;
+}
 
-out:
-	kfree(conf);
-	return 1;
+static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+	/* Adding a drive to a linear array allows the array to grow.
+	 * It is permitted if the new drive has a matching superblock
+	 * already on it, with raid_disk equal to raid_disks.
+	 * It is achieved by creating a new linear_private_data structure
+	 * and swapping it in in-place of the current one.
+	 * The current one is never freed until the array is stopped.
+	 * This avoids races.
+	 */
+	linear_conf_t *newconf;
+
+	if (rdev->raid_disk != mddev->raid_disks)
+		return -EINVAL;
+
+	newconf = linear_conf(mddev,mddev->raid_disks+1);
+
+	if (!newconf)
+		return -ENOMEM;
+
+	newconf->prev = mddev_to_conf(mddev);
+	mddev->private = newconf;
+	mddev->raid_disks++;
+	mddev->array_size = newconf->array_size;
+	set_capacity(mddev->gendisk, mddev->array_size << 1);
+	return 0;
 }
 
 static int linear_stop (mddev_t *mddev)
@@ -262,8 +305,12 @@
 	linear_conf_t *conf = mddev_to_conf(mddev);
   
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
-	kfree(conf->hash_table);
-	kfree(conf);
+	do {
+		linear_conf_t *t = conf->prev;
+		kfree(conf->hash_table);
+		kfree(conf);
+		conf = t;
+	} while (conf);
 
 	return 0;
 }
@@ -360,6 +407,7 @@
 	.run		= linear_run,
 	.stop		= linear_stop,
 	.status		= linear_status,
+	.hot_add_disk	= linear_add,
 };
 
 static int __init linear_init (void)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index f19b874..306268e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -44,6 +44,7 @@
 #include <linux/suspend.h>
 #include <linux/poll.h>
 #include <linux/mutex.h>
+#include <linux/ctype.h>
 
 #include <linux/init.h>
 
@@ -72,6 +73,10 @@
 static LIST_HEAD(pers_list);
 static DEFINE_SPINLOCK(pers_lock);
 
+static void md_print_devices(void);
+
+#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
+
 /*
  * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit'
  * is 1000 KB/sec, so the extra system load does not show up that much.
@@ -170,7 +175,7 @@
 /* Alternate version that can be called from interrupts
  * when calling sysfs_notify isn't needed.
  */
-void md_new_event_inintr(mddev_t *mddev)
+static void md_new_event_inintr(mddev_t *mddev)
 {
 	atomic_inc(&md_event_count);
 	wake_up(&md_event_waiters);
@@ -732,6 +737,7 @@
 {
 	mdp_disk_t *desc;
 	mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
+	__u64 ev1 = md_event(sb);
 
 	rdev->raid_disk = -1;
 	rdev->flags = 0;
@@ -748,7 +754,7 @@
 		mddev->layout = sb->layout;
 		mddev->raid_disks = sb->raid_disks;
 		mddev->size = sb->size;
-		mddev->events = md_event(sb);
+		mddev->events = ev1;
 		mddev->bitmap_offset = 0;
 		mddev->default_bitmap_offset = MD_SB_BYTES >> 9;
 
@@ -797,7 +803,6 @@
 
 	} else if (mddev->pers == NULL) {
 		/* Insist on good event counter while assembling */
-		__u64 ev1 = md_event(sb);
 		++ev1;
 		if (ev1 < mddev->events) 
 			return -EINVAL;
@@ -805,19 +810,21 @@
 		/* if adding to array with a bitmap, then we can accept an
 		 * older device ... but not too old.
 		 */
-		__u64 ev1 = md_event(sb);
 		if (ev1 < mddev->bitmap->events_cleared)
 			return 0;
-	} else /* just a hot-add of a new device, leave raid_disk at -1 */
-		return 0;
+	} else {
+		if (ev1 < mddev->events)
+			/* just a hot-add of a new device, leave raid_disk at -1 */
+			return 0;
+	}
 
 	if (mddev->level != LEVEL_MULTIPATH) {
 		desc = sb->disks + rdev->desc_nr;
 
 		if (desc->state & (1<<MD_DISK_FAULTY))
 			set_bit(Faulty, &rdev->flags);
-		else if (desc->state & (1<<MD_DISK_SYNC) &&
-			 desc->raid_disk < mddev->raid_disks) {
+		else if (desc->state & (1<<MD_DISK_SYNC) /* &&
+			    desc->raid_disk < mddev->raid_disks */) {
 			set_bit(In_sync, &rdev->flags);
 			rdev->raid_disk = desc->raid_disk;
 		}
@@ -1100,6 +1107,7 @@
 static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 {
 	struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+	__u64 ev1 = le64_to_cpu(sb->events);
 
 	rdev->raid_disk = -1;
 	rdev->flags = 0;
@@ -1115,7 +1123,7 @@
 		mddev->layout = le32_to_cpu(sb->layout);
 		mddev->raid_disks = le32_to_cpu(sb->raid_disks);
 		mddev->size = le64_to_cpu(sb->size)/2;
-		mddev->events = le64_to_cpu(sb->events);
+		mddev->events = ev1;
 		mddev->bitmap_offset = 0;
 		mddev->default_bitmap_offset = 1024 >> 9;
 		
@@ -1149,7 +1157,6 @@
 
 	} else if (mddev->pers == NULL) {
 		/* Insist of good event counter while assembling */
-		__u64 ev1 = le64_to_cpu(sb->events);
 		++ev1;
 		if (ev1 < mddev->events)
 			return -EINVAL;
@@ -1157,12 +1164,13 @@
 		/* If adding to array with a bitmap, then we can accept an
 		 * older device, but not too old.
 		 */
-		__u64 ev1 = le64_to_cpu(sb->events);
 		if (ev1 < mddev->bitmap->events_cleared)
 			return 0;
-	} else /* just a hot-add of a new device, leave raid_disk at -1 */
-		return 0;
-
+	} else {
+		if (ev1 < mddev->events)
+			/* just a hot-add of a new device, leave raid_disk at -1 */
+			return 0;
+	}
 	if (mddev->level != LEVEL_MULTIPATH) {
 		int role;
 		rdev->desc_nr = le32_to_cpu(sb->dev_number);
@@ -1174,7 +1182,11 @@
 			set_bit(Faulty, &rdev->flags);
 			break;
 		default:
-			set_bit(In_sync, &rdev->flags);
+			if ((le32_to_cpu(sb->feature_map) &
+			     MD_FEATURE_RECOVERY_OFFSET))
+				rdev->recovery_offset = le64_to_cpu(sb->recovery_offset);
+			else
+				set_bit(In_sync, &rdev->flags);
 			rdev->raid_disk = role;
 			break;
 		}
@@ -1198,6 +1210,7 @@
 
 	sb->feature_map = 0;
 	sb->pad0 = 0;
+	sb->recovery_offset = cpu_to_le64(0);
 	memset(sb->pad1, 0, sizeof(sb->pad1));
 	memset(sb->pad2, 0, sizeof(sb->pad2));
 	memset(sb->pad3, 0, sizeof(sb->pad3));
@@ -1218,6 +1231,14 @@
 		sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
 		sb->feature_map = cpu_to_le32(MD_FEATURE_BITMAP_OFFSET);
 	}
+
+	if (rdev->raid_disk >= 0 &&
+	    !test_bit(In_sync, &rdev->flags) &&
+	    rdev->recovery_offset > 0) {
+		sb->feature_map |= cpu_to_le32(MD_FEATURE_RECOVERY_OFFSET);
+		sb->recovery_offset = cpu_to_le64(rdev->recovery_offset);
+	}
+
 	if (mddev->reshape_position != MaxSector) {
 		sb->feature_map |= cpu_to_le32(MD_FEATURE_RESHAPE_ACTIVE);
 		sb->reshape_position = cpu_to_le64(mddev->reshape_position);
@@ -1242,11 +1263,12 @@
 			sb->dev_roles[i] = cpu_to_le16(0xfffe);
 		else if (test_bit(In_sync, &rdev2->flags))
 			sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk);
+		else if (rdev2->raid_disk >= 0 && rdev2->recovery_offset > 0)
+			sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk);
 		else
 			sb->dev_roles[i] = cpu_to_le16(0xffff);
 	}
 
-	sb->recovery_offset = cpu_to_le64(0); /* not supported yet */
 	sb->sb_csum = calc_sb_1_csum(sb);
 }
 
@@ -1507,7 +1529,7 @@
 		printk(KERN_INFO "md: no rdev superblock!\n");
 }
 
-void md_print_devices(void)
+static void md_print_devices(void)
 {
 	struct list_head *tmp, *tmp2;
 	mdk_rdev_t *rdev;
@@ -1536,15 +1558,30 @@
 }
 
 
-static void sync_sbs(mddev_t * mddev)
+static void sync_sbs(mddev_t * mddev, int nospares)
 {
+	/* Update each superblock (in-memory image), but
+	 * if we are allowed to, skip spares which already
+	 * have the right event counter, or have one earlier
+	 * (which would mean they aren't being marked as dirty
+	 * with the rest of the array)
+	 */
 	mdk_rdev_t *rdev;
 	struct list_head *tmp;
 
 	ITERATE_RDEV(mddev,rdev,tmp) {
-		super_types[mddev->major_version].
-			sync_super(mddev, rdev);
-		rdev->sb_loaded = 1;
+		if (rdev->sb_events == mddev->events ||
+		    (nospares &&
+		     rdev->raid_disk < 0 &&
+		     (rdev->sb_events&1)==0 &&
+		     rdev->sb_events+1 == mddev->events)) {
+			/* Don't update this superblock */
+			rdev->sb_loaded = 2;
+		} else {
+			super_types[mddev->major_version].
+				sync_super(mddev, rdev);
+			rdev->sb_loaded = 1;
+		}
 	}
 }
 
@@ -1554,12 +1591,42 @@
 	struct list_head *tmp;
 	mdk_rdev_t *rdev;
 	int sync_req;
+	int nospares = 0;
 
 repeat:
 	spin_lock_irq(&mddev->write_lock);
 	sync_req = mddev->in_sync;
 	mddev->utime = get_seconds();
-	mddev->events ++;
+	if (mddev->sb_dirty == 3)
+		/* just a clean<-> dirty transition, possibly leave spares alone,
+		 * though if events isn't the right even/odd, we will have to do
+		 * spares after all
+		 */
+		nospares = 1;
+
+	/* If this is just a dirty<->clean transition, and the array is clean
+	 * and 'events' is odd, we can roll back to the previous clean state */
+	if (mddev->sb_dirty == 3
+	    && (mddev->in_sync && mddev->recovery_cp == MaxSector)
+	    && (mddev->events & 1))
+		mddev->events--;
+	else {
+		/* otherwise we have to go forward and ... */
+		mddev->events ++;
+		if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */
+			/* .. if the array isn't clean, insist on an odd 'events' */
+			if ((mddev->events&1)==0) {
+				mddev->events++;
+				nospares = 0;
+			}
+		} else {
+			/* otherwise insist on an even 'events' (for clean states) */
+			if ((mddev->events&1)) {
+				mddev->events++;
+				nospares = 0;
+			}
+		}
+	}
 
 	if (!mddev->events) {
 		/*
@@ -1571,7 +1638,7 @@
 		mddev->events --;
 	}
 	mddev->sb_dirty = 2;
-	sync_sbs(mddev);
+	sync_sbs(mddev, nospares);
 
 	/*
 	 * do not write anything to disk if using
@@ -1593,6 +1660,8 @@
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		char b[BDEVNAME_SIZE];
 		dprintk(KERN_INFO "md: ");
+		if (rdev->sb_loaded != 1)
+			continue; /* no noise on spare devices */
 		if (test_bit(Faulty, &rdev->flags))
 			dprintk("(skipping faulty ");
 
@@ -1604,6 +1673,7 @@
 			dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
 				bdevname(rdev->bdev,b),
 				(unsigned long long)rdev->sb_offset);
+			rdev->sb_events = mddev->events;
 
 		} else
 			dprintk(")\n");
@@ -1667,6 +1737,10 @@
 		len += sprintf(page+len, "%sin_sync",sep);
 		sep = ",";
 	}
+	if (test_bit(WriteMostly, &rdev->flags)) {
+		len += sprintf(page+len, "%swrite_mostly",sep);
+		sep = ",";
+	}
 	if (!test_bit(Faulty, &rdev->flags) &&
 	    !test_bit(In_sync, &rdev->flags)) {
 		len += sprintf(page+len, "%sspare", sep);
@@ -1675,8 +1749,40 @@
 	return len+sprintf(page+len, "\n");
 }
 
+static ssize_t
+state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+{
+	/* can write
+	 *  faulty  - simulates and error
+	 *  remove  - disconnects the device
+	 *  writemostly - sets write_mostly
+	 *  -writemostly - clears write_mostly
+	 */
+	int err = -EINVAL;
+	if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
+		md_error(rdev->mddev, rdev);
+		err = 0;
+	} else if (cmd_match(buf, "remove")) {
+		if (rdev->raid_disk >= 0)
+			err = -EBUSY;
+		else {
+			mddev_t *mddev = rdev->mddev;
+			kick_rdev_from_array(rdev);
+			md_update_sb(mddev);
+			md_new_event(mddev);
+			err = 0;
+		}
+	} else if (cmd_match(buf, "writemostly")) {
+		set_bit(WriteMostly, &rdev->flags);
+		err = 0;
+	} else if (cmd_match(buf, "-writemostly")) {
+		clear_bit(WriteMostly, &rdev->flags);
+		err = 0;
+	}
+	return err ? err : len;
+}
 static struct rdev_sysfs_entry
-rdev_state = __ATTR_RO(state);
+rdev_state = __ATTR(state, 0644, state_show, state_store);
 
 static ssize_t
 super_show(mdk_rdev_t *rdev, char *page)
@@ -1873,6 +1979,7 @@
 	rdev->desc_nr = -1;
 	rdev->flags = 0;
 	rdev->data_offset = 0;
+	rdev->sb_events = 0;
 	atomic_set(&rdev->nr_pending, 0);
 	atomic_set(&rdev->read_errors, 0);
 	atomic_set(&rdev->corrected_errors, 0);
@@ -1978,6 +2085,54 @@
 }
 
 static ssize_t
+safe_delay_show(mddev_t *mddev, char *page)
+{
+	int msec = (mddev->safemode_delay*1000)/HZ;
+	return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
+}
+static ssize_t
+safe_delay_store(mddev_t *mddev, const char *cbuf, size_t len)
+{
+	int scale=1;
+	int dot=0;
+	int i;
+	unsigned long msec;
+	char buf[30];
+	char *e;
+	/* remove a period, and count digits after it */
+	if (len >= sizeof(buf))
+		return -EINVAL;
+	strlcpy(buf, cbuf, len);
+	buf[len] = 0;
+	for (i=0; i<len; i++) {
+		if (dot) {
+			if (isdigit(buf[i])) {
+				buf[i-1] = buf[i];
+				scale *= 10;
+			}
+			buf[i] = 0;
+		} else if (buf[i] == '.') {
+			dot=1;
+			buf[i] = 0;
+		}
+	}
+	msec = simple_strtoul(buf, &e, 10);
+	if (e == buf || (*e && *e != '\n'))
+		return -EINVAL;
+	msec = (msec * 1000) / scale;
+	if (msec == 0)
+		mddev->safemode_delay = 0;
+	else {
+		mddev->safemode_delay = (msec*HZ)/1000;
+		if (mddev->safemode_delay == 0)
+			mddev->safemode_delay = 1;
+	}
+	return len;
+}
+static struct md_sysfs_entry md_safe_delay =
+__ATTR(safe_mode_delay, 0644,safe_delay_show, safe_delay_store);
+
+static ssize_t
 level_show(mddev_t *mddev, char *page)
 {
 	struct mdk_personality *p = mddev->pers;
@@ -2012,6 +2167,32 @@
 static struct md_sysfs_entry md_level =
 __ATTR(level, 0644, level_show, level_store);
 
+
+static ssize_t
+layout_show(mddev_t *mddev, char *page)
+{
+	/* just a number, not meaningful for all levels */
+	return sprintf(page, "%d\n", mddev->layout);
+}
+
+static ssize_t
+layout_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	char *e;
+	unsigned long n = simple_strtoul(buf, &e, 10);
+	if (mddev->pers)
+		return -EBUSY;
+
+	if (!*buf || (*e && *e != '\n'))
+		return -EINVAL;
+
+	mddev->layout = n;
+	return len;
+}
+static struct md_sysfs_entry md_layout =
+__ATTR(layout, 0655, layout_show, layout_store);
+
+
 static ssize_t
 raid_disks_show(mddev_t *mddev, char *page)
 {
@@ -2067,6 +2248,200 @@
 __ATTR(chunk_size, 0644, chunk_size_show, chunk_size_store);
 
 static ssize_t
+resync_start_show(mddev_t *mddev, char *page)
+{
+	return sprintf(page, "%llu\n", (unsigned long long)mddev->recovery_cp);
+}
+
+static ssize_t
+resync_start_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	/* can only set chunk_size if array is not yet active */
+	char *e;
+	unsigned long long n = simple_strtoull(buf, &e, 10);
+
+	if (mddev->pers)
+		return -EBUSY;
+	if (!*buf || (*e && *e != '\n'))
+		return -EINVAL;
+
+	mddev->recovery_cp = n;
+	return len;
+}
+static struct md_sysfs_entry md_resync_start =
+__ATTR(resync_start, 0644, resync_start_show, resync_start_store);
+
+/*
+ * The array state can be:
+ *
+ * clear
+ *     No devices, no size, no level
+ *     Equivalent to STOP_ARRAY ioctl
+ * inactive
+ *     May have some settings, but array is not active
+ *        all IO results in error
+ *     When written, doesn't tear down array, but just stops it
+ * suspended (not supported yet)
+ *     All IO requests will block. The array can be reconfigured.
+ *     Writing this, if accepted, will block until array is quiessent
+ * readonly
+ *     no resync can happen.  no superblocks get written.
+ *     write requests fail
+ * read-auto
+ *     like readonly, but behaves like 'clean' on a write request.
+ *
+ * clean - no pending writes, but otherwise active.
+ *     When written to inactive array, starts without resync
+ *     If a write request arrives then
+ *       if metadata is known, mark 'dirty' and switch to 'active'.
+ *       if not known, block and switch to write-pending
+ *     If written to an active array that has pending writes, then fails.
+ * active
+ *     fully active: IO and resync can be happening.
+ *     When written to inactive array, starts with resync
+ *
+ * write-pending
+ *     clean, but writes are blocked waiting for 'active' to be written.
+ *
+ * active-idle
+ *     like active, but no writes have been seen for a while (100msec).
+ *
+ */
+enum array_state { clear, inactive, suspended, readonly, read_auto, clean, active,
+		   write_pending, active_idle, bad_word};
+static char *array_states[] = {
+	"clear", "inactive", "suspended", "readonly", "read-auto", "clean", "active",
+	"write-pending", "active-idle", NULL };
+
+static int match_word(const char *word, char **list)
+{
+	int n;
+	for (n=0; list[n]; n++)
+		if (cmd_match(word, list[n]))
+			break;
+	return n;
+}
+
+static ssize_t
+array_state_show(mddev_t *mddev, char *page)
+{
+	enum array_state st = inactive;
+
+	if (mddev->pers)
+		switch(mddev->ro) {
+		case 1:
+			st = readonly;
+			break;
+		case 2:
+			st = read_auto;
+			break;
+		case 0:
+			if (mddev->in_sync)
+				st = clean;
+			else if (mddev->safemode)
+				st = active_idle;
+			else
+				st = active;
+		}
+	else {
+		if (list_empty(&mddev->disks) &&
+		    mddev->raid_disks == 0 &&
+		    mddev->size == 0)
+			st = clear;
+		else
+			st = inactive;
+	}
+	return sprintf(page, "%s\n", array_states[st]);
+}
+
+static int do_md_stop(mddev_t * mddev, int ro);
+static int do_md_run(mddev_t * mddev);
+static int restart_array(mddev_t *mddev);
+
+static ssize_t
+array_state_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	int err = -EINVAL;
+	enum array_state st = match_word(buf, array_states);
+	switch(st) {
+	case bad_word:
+		break;
+	case clear:
+		/* stopping an active array */
+		if (mddev->pers) {
+			if (atomic_read(&mddev->active) > 1)
+				return -EBUSY;
+			err = do_md_stop(mddev, 0);
+		}
+		break;
+	case inactive:
+		/* stopping an active array */
+		if (mddev->pers) {
+			if (atomic_read(&mddev->active) > 1)
+				return -EBUSY;
+			err = do_md_stop(mddev, 2);
+		}
+		break;
+	case suspended:
+		break; /* not supported yet */
+	case readonly:
+		if (mddev->pers)
+			err = do_md_stop(mddev, 1);
+		else {
+			mddev->ro = 1;
+			err = do_md_run(mddev);
+		}
+		break;
+	case read_auto:
+		/* stopping an active array */
+		if (mddev->pers) {
+			err = do_md_stop(mddev, 1);
+			if (err == 0)
+				mddev->ro = 2; /* FIXME mark devices writable */
+		} else {
+			mddev->ro = 2;
+			err = do_md_run(mddev);
+		}
+		break;
+	case clean:
+		if (mddev->pers) {
+			restart_array(mddev);
+			spin_lock_irq(&mddev->write_lock);
+			if (atomic_read(&mddev->writes_pending) == 0) {
+				mddev->in_sync = 1;
+				mddev->sb_dirty = 1;
+			}
+			spin_unlock_irq(&mddev->write_lock);
+		} else {
+			mddev->ro = 0;
+			mddev->recovery_cp = MaxSector;
+			err = do_md_run(mddev);
+		}
+		break;
+	case active:
+		if (mddev->pers) {
+			restart_array(mddev);
+			mddev->sb_dirty = 0;
+			wake_up(&mddev->sb_wait);
+			err = 0;
+		} else {
+			mddev->ro = 0;
+			err = do_md_run(mddev);
+		}
+		break;
+	case write_pending:
+	case active_idle:
+		/* these cannot be set */
+		break;
+	}
+	if (err)
+		return err;
+	else
+		return len;
+}
+static struct md_sysfs_entry md_array_state = __ATTR(array_state, 0644, array_state_show, array_state_store);
+
+static ssize_t
 null_show(mddev_t *mddev, char *page)
 {
 	return -EINVAL;
@@ -2428,11 +2803,15 @@
 
 static struct attribute *md_default_attrs[] = {
 	&md_level.attr,
+	&md_layout.attr,
 	&md_raid_disks.attr,
 	&md_chunk_size.attr,
 	&md_size.attr,
+	&md_resync_start.attr,
 	&md_metadata.attr,
 	&md_new_device.attr,
+	&md_safe_delay.attr,
+	&md_array_state.attr,
 	NULL,
 };
 
@@ -2553,8 +2932,6 @@
 	return NULL;
 }
 
-void md_wakeup_thread(mdk_thread_t *thread);
-
 static void md_safemode_timeout(unsigned long data)
 {
 	mddev_t *mddev = (mddev_t *) data;
@@ -2708,7 +3085,7 @@
 	mddev->safemode = 0;
 	mddev->safemode_timer.function = md_safemode_timeout;
 	mddev->safemode_timer.data = (unsigned long) mddev;
-	mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */
+	mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
 	mddev->in_sync = 1;
 
 	ITERATE_RDEV(mddev,rdev,tmp)
@@ -2736,6 +3113,36 @@
 	mddev->queue->queuedata = mddev;
 	mddev->queue->make_request_fn = mddev->pers->make_request;
 
+	/* If there is a partially-recovered drive we need to
+	 * start recovery here.  If we leave it to md_check_recovery,
+	 * it will remove the drives and not do the right thing
+	 */
+	if (mddev->degraded) {
+		struct list_head *rtmp;
+		int spares = 0;
+		ITERATE_RDEV(mddev,rdev,rtmp)
+			if (rdev->raid_disk >= 0 &&
+			    !test_bit(In_sync, &rdev->flags) &&
+			    !test_bit(Faulty, &rdev->flags))
+				/* complete an interrupted recovery */
+				spares++;
+		if (spares && mddev->pers->sync_request) {
+			mddev->recovery = 0;
+			set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
+			mddev->sync_thread = md_register_thread(md_do_sync,
+								mddev,
+								"%s_resync");
+			if (!mddev->sync_thread) {
+				printk(KERN_ERR "%s: could not start resync"
+				       " thread...\n",
+				       mdname(mddev));
+				/* leave the spares where they are, it shouldn't hurt */
+				mddev->recovery = 0;
+			} else
+				md_wakeup_thread(mddev->sync_thread);
+		}
+	}
+
 	mddev->changed = 1;
 	md_new_event(mddev);
 	return 0;
@@ -2769,18 +3176,47 @@
 		 */
 		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		md_wakeup_thread(mddev->thread);
+		md_wakeup_thread(mddev->sync_thread);
 		err = 0;
-	} else {
-		printk(KERN_ERR "md: %s has no personality assigned.\n",
-			mdname(mddev));
+	} else
 		err = -EINVAL;
-	}
 
 out:
 	return err;
 }
 
-static int do_md_stop(mddev_t * mddev, int ro)
+/* similar to deny_write_access, but accounts for our holding a reference
+ * to the file ourselves */
+static int deny_bitmap_write_access(struct file * file)
+{
+	struct inode *inode = file->f_mapping->host;
+
+	spin_lock(&inode->i_lock);
+	if (atomic_read(&inode->i_writecount) > 1) {
+		spin_unlock(&inode->i_lock);
+		return -ETXTBSY;
+	}
+	atomic_set(&inode->i_writecount, -1);
+	spin_unlock(&inode->i_lock);
+
+	return 0;
+}
+
+static void restore_bitmap_write_access(struct file *file)
+{
+	struct inode *inode = file->f_mapping->host;
+
+	spin_lock(&inode->i_lock);
+	atomic_set(&inode->i_writecount, 1);
+	spin_unlock(&inode->i_lock);
+}
+
+/* mode:
+ *   0 - completely stop and dis-assemble array
+ *   1 - switch to readonly
+ *   2 - stop but do not disassemble array
+ */
+static int do_md_stop(mddev_t * mddev, int mode)
 {
 	int err = 0;
 	struct gendisk *disk = mddev->gendisk;
@@ -2792,6 +3228,7 @@
 		}
 
 		if (mddev->sync_thread) {
+			set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 			set_bit(MD_RECOVERY_INTR, &mddev->recovery);
 			md_unregister_thread(mddev->sync_thread);
 			mddev->sync_thread = NULL;
@@ -2801,12 +3238,15 @@
 
 		invalidate_partition(disk, 0);
 
-		if (ro) {
+		switch(mode) {
+		case 1: /* readonly */
 			err  = -ENXIO;
 			if (mddev->ro==1)
 				goto out;
 			mddev->ro = 1;
-		} else {
+			break;
+		case 0: /* disassemble */
+		case 2: /* stop */
 			bitmap_flush(mddev);
 			md_super_wait(mddev);
 			if (mddev->ro)
@@ -2821,19 +3261,20 @@
 			if (mddev->ro)
 				mddev->ro = 0;
 		}
-		if (!mddev->in_sync) {
+		if (!mddev->in_sync || mddev->sb_dirty) {
 			/* mark array as shutdown cleanly */
 			mddev->in_sync = 1;
 			md_update_sb(mddev);
 		}
-		if (ro)
+		if (mode == 1)
 			set_disk_ro(disk, 1);
+		clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 	}
 
 	/*
 	 * Free resources if final stop
 	 */
-	if (!ro) {
+	if (mode == 0) {
 		mdk_rdev_t *rdev;
 		struct list_head *tmp;
 		struct gendisk *disk;
@@ -2841,7 +3282,7 @@
 
 		bitmap_destroy(mddev);
 		if (mddev->bitmap_file) {
-			atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
+			restore_bitmap_write_access(mddev->bitmap_file);
 			fput(mddev->bitmap_file);
 			mddev->bitmap_file = NULL;
 		}
@@ -2857,11 +3298,15 @@
 		export_array(mddev);
 
 		mddev->array_size = 0;
+		mddev->size = 0;
+		mddev->raid_disks = 0;
+		mddev->recovery_cp = 0;
+
 		disk = mddev->gendisk;
 		if (disk)
 			set_capacity(disk, 0);
 		mddev->changed = 1;
-	} else
+	} else if (mddev->pers)
 		printk(KERN_INFO "md: %s switched to read-only mode.\n",
 			mdname(mddev));
 	err = 0;
@@ -3264,6 +3709,17 @@
 
 		rdev->raid_disk = -1;
 		err = bind_rdev_to_array(rdev, mddev);
+		if (!err && !mddev->pers->hot_remove_disk) {
+			/* If there is hot_add_disk but no hot_remove_disk
+			 * then added disks for geometry changes,
+			 * and should be added immediately.
+			 */
+			super_types[mddev->major_version].
+				validate_super(mddev, rdev);
+			err = mddev->pers->hot_add_disk(mddev, rdev);
+			if (err)
+				unbind_rdev_from_array(rdev);
+		}
 		if (err)
 			export_rdev(rdev);
 
@@ -3434,23 +3890,6 @@
 	return err;
 }
 
-/* similar to deny_write_access, but accounts for our holding a reference
- * to the file ourselves */
-static int deny_bitmap_write_access(struct file * file)
-{
-	struct inode *inode = file->f_mapping->host;
-
-	spin_lock(&inode->i_lock);
-	if (atomic_read(&inode->i_writecount) > 1) {
-		spin_unlock(&inode->i_lock);
-		return -ETXTBSY;
-	}
-	atomic_set(&inode->i_writecount, -1);
-	spin_unlock(&inode->i_lock);
-
-	return 0;
-}
-
 static int set_bitmap_file(mddev_t *mddev, int fd)
 {
 	int err;
@@ -3491,12 +3930,17 @@
 		mddev->pers->quiesce(mddev, 1);
 		if (fd >= 0)
 			err = bitmap_create(mddev);
-		if (fd < 0 || err)
+		if (fd < 0 || err) {
 			bitmap_destroy(mddev);
+			fd = -1; /* make sure to put the file */
+		}
 		mddev->pers->quiesce(mddev, 0);
-	} else if (fd < 0) {
-		if (mddev->bitmap_file)
+	}
+	if (fd < 0) {
+		if (mddev->bitmap_file) {
+			restore_bitmap_write_access(mddev->bitmap_file);
 			fput(mddev->bitmap_file);
+		}
 		mddev->bitmap_file = NULL;
 	}
 
@@ -3977,11 +4421,6 @@
 			goto done_unlock;
 
 		default:
-			if (_IOC_TYPE(cmd) == MD_MAJOR)
-				printk(KERN_WARNING "md: %s(pid %d) used"
-					" obsolete MD ioctl, upgrade your"
-					" software to use new ictls.\n",
-					current->comm, current->pid);
 			err = -EINVAL;
 			goto abort_unlock;
 	}
@@ -4586,7 +5025,7 @@
 		spin_lock_irq(&mddev->write_lock);
 		if (mddev->in_sync) {
 			mddev->in_sync = 0;
-			mddev->sb_dirty = 1;
+			mddev->sb_dirty = 3;
 			md_wakeup_thread(mddev->thread);
 		}
 		spin_unlock_irq(&mddev->write_lock);
@@ -4599,7 +5038,7 @@
 	if (atomic_dec_and_test(&mddev->writes_pending)) {
 		if (mddev->safemode == 2)
 			md_wakeup_thread(mddev->thread);
-		else
+		else if (mddev->safemode_delay)
 			mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay);
 	}
 }
@@ -4620,10 +5059,14 @@
 	struct list_head *tmp;
 	sector_t last_check;
 	int skipped = 0;
+	struct list_head *rtmp;
+	mdk_rdev_t *rdev;
 
 	/* just incase thread restarts... */
 	if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
 		return;
+	if (mddev->ro) /* never try to sync a read-only array */
+		return;
 
 	/* we overload curr_resync somewhat here.
 	 * 0 == not engaged in resync at all
@@ -4682,17 +5125,30 @@
 		}
 	} while (mddev->curr_resync < 2);
 
+	j = 0;
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
 		/* resync follows the size requested by the personality,
 		 * which defaults to physical size, but can be virtual size
 		 */
 		max_sectors = mddev->resync_max_sectors;
 		mddev->resync_mismatches = 0;
+		/* we don't use the checkpoint if there's a bitmap */
+		if (!mddev->bitmap &&
+		    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
+			j = mddev->recovery_cp;
 	} else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
 		max_sectors = mddev->size << 1;
-	else
+	else {
 		/* recovery follows the physical size of devices */
 		max_sectors = mddev->size << 1;
+		j = MaxSector;
+		ITERATE_RDEV(mddev,rdev,rtmp)
+			if (rdev->raid_disk >= 0 &&
+			    !test_bit(Faulty, &rdev->flags) &&
+			    !test_bit(In_sync, &rdev->flags) &&
+			    rdev->recovery_offset < j)
+				j = rdev->recovery_offset;
+	}
 
 	printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev));
 	printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:"
@@ -4702,12 +5158,7 @@
 	       speed_max(mddev));
 
 	is_mddev_idle(mddev); /* this also initializes IO event counters */
-	/* we don't use the checkpoint if there's a bitmap */
-	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap
-	    && ! test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
-		j = mddev->recovery_cp;
-	else
-		j = 0;
+
 	io_sectors = 0;
 	for (m = 0; m < SYNC_MARKS; m++) {
 		mark[m] = jiffies;
@@ -4828,15 +5279,28 @@
 	if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
 	    test_bit(MD_RECOVERY_SYNC, &mddev->recovery) &&
 	    !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
-	    mddev->curr_resync > 2 &&
-	    mddev->curr_resync >= mddev->recovery_cp) {
-		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
-			printk(KERN_INFO 
-				"md: checkpointing recovery of %s.\n",
-				mdname(mddev));
-			mddev->recovery_cp = mddev->curr_resync;
-		} else
-			mddev->recovery_cp = MaxSector;
+	    mddev->curr_resync > 2) {
+		if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+			if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {
+				if (mddev->curr_resync >= mddev->recovery_cp) {
+					printk(KERN_INFO
+					       "md: checkpointing recovery of %s.\n",
+					       mdname(mddev));
+					mddev->recovery_cp = mddev->curr_resync;
+				}
+			} else
+				mddev->recovery_cp = MaxSector;
+		} else {
+			if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery))
+				mddev->curr_resync = MaxSector;
+			ITERATE_RDEV(mddev,rdev,rtmp)
+				if (rdev->raid_disk >= 0 &&
+				    !test_bit(Faulty, &rdev->flags) &&
+				    !test_bit(In_sync, &rdev->flags) &&
+				    rdev->recovery_offset < mddev->curr_resync)
+					rdev->recovery_offset = mddev->curr_resync;
+			mddev->sb_dirty = 1;
+		}
 	}
 
  skip:
@@ -4908,7 +5372,7 @@
 		if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
 		    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
 			mddev->in_sync = 1;
-			mddev->sb_dirty = 1;
+			mddev->sb_dirty = 3;
 		}
 		if (mddev->safemode == 1)
 			mddev->safemode = 0;
@@ -4957,6 +5421,8 @@
 		clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
 		clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
 
+		if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
+			goto unlock;
 		/* no recovery is running.
 		 * remove any failed drives, then
 		 * add spares if possible.
@@ -4979,6 +5445,7 @@
 			ITERATE_RDEV(mddev,rdev,rtmp)
 				if (rdev->raid_disk < 0
 				    && !test_bit(Faulty, &rdev->flags)) {
+					rdev->recovery_offset = 0;
 					if (mddev->pers->hot_add_disk(mddev,rdev)) {
 						char nm[20];
 						sprintf(nm, "rd%d", rdev->raid_disk);
@@ -5216,7 +5683,6 @@
 EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
-EXPORT_SYMBOL(md_print_devices);
 EXPORT_SYMBOL(md_check_recovery);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md");
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 4070eff..cead918 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -374,26 +374,26 @@
 	 * already.
 	 */
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) {
+		if (test_bit(R1BIO_BarrierRetry, &r1_bio->state))
 			reschedule_retry(r1_bio);
-			goto out;
+		else {
+			/* it really is the end of this request */
+			if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
+				/* free extra copy of the data pages */
+				int i = bio->bi_vcnt;
+				while (i--)
+					safe_put_page(bio->bi_io_vec[i].bv_page);
+			}
+			/* clear the bitmap if all writes complete successfully */
+			bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+					r1_bio->sectors,
+					!test_bit(R1BIO_Degraded, &r1_bio->state),
+					behind);
+			md_write_end(r1_bio->mddev);
+			raid_end_bio_io(r1_bio);
 		}
-		/* it really is the end of this request */
-		if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
-			/* free extra copy of the data pages */
-			int i = bio->bi_vcnt;
-			while (i--)
-				safe_put_page(bio->bi_io_vec[i].bv_page);
-		}
-		/* clear the bitmap if all writes complete successfully */
-		bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
-				r1_bio->sectors,
-				!test_bit(R1BIO_Degraded, &r1_bio->state),
-				behind);
-		md_write_end(r1_bio->mddev);
-		raid_end_bio_io(r1_bio);
 	}
- out:
+
 	if (to_put)
 		bio_put(to_put);
 
@@ -1625,6 +1625,12 @@
 	/* before building a request, check if we can skip these blocks..
 	 * This call the bitmap_start_sync doesn't actually record anything
 	 */
+	if (mddev->bitmap == NULL &&
+	    mddev->recovery_cp == MaxSector &&
+	    conf->fullsync == 0) {
+		*skipped = 1;
+		return max_sector - sector_nr;
+	}
 	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
 	    !conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
 		/* We can skip this block, and probably several more */
@@ -1888,7 +1894,8 @@
 
 		disk = conf->mirrors + i;
 
-		if (!disk->rdev) {
+		if (!disk->rdev ||
+		    !test_bit(In_sync, &disk->rdev->flags)) {
 			disk->head_position = 0;
 			mddev->degraded++;
 		}
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1440935..7f63628 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -29,6 +29,7 @@
  *    raid_disks
  *    near_copies (stored in low byte of layout)
  *    far_copies (stored in second byte of layout)
+ *    far_offset (stored in bit 16 of layout )
  *
  * The data to be stored is divided into chunks using chunksize.
  * Each device is divided into far_copies sections.
@@ -36,10 +37,14 @@
  * near_copies copies of each chunk is stored (each on a different drive).
  * The starting device for each section is offset near_copies from the starting
  * device of the previous section.
- * Thus there are (near_copies*far_copies) of each chunk, and each is on a different
+ * Thus they are (near_copies*far_copies) of each chunk, and each is on a different
  * drive.
  * near_copies and far_copies must be at least one, and their product is at most
  * raid_disks.
+ *
+ * If far_offset is true, then the far_copies are handled a bit differently.
+ * The copies are still in different stripes, but instead of be very far apart
+ * on disk, there are adjacent stripes.
  */
 
 /*
@@ -357,8 +362,7 @@
  * With this layout, and block is never stored twice on the one device.
  *
  * raid10_find_phys finds the sector offset of a given virtual sector
- * on each device that it is on. If a block isn't on a device,
- * that entry in the array is set to MaxSector.
+ * on each device that it is on.
  *
  * raid10_find_virt does the reverse mapping, from a device and a
  * sector offset to a virtual address
@@ -381,6 +385,8 @@
 	chunk *= conf->near_copies;
 	stripe = chunk;
 	dev = sector_div(stripe, conf->raid_disks);
+	if (conf->far_offset)
+		stripe *= conf->far_copies;
 
 	sector += stripe << conf->chunk_shift;
 
@@ -414,16 +420,24 @@
 {
 	sector_t offset, chunk, vchunk;
 
-	while (sector > conf->stride) {
-		sector -= conf->stride;
-		if (dev < conf->near_copies)
-			dev += conf->raid_disks - conf->near_copies;
-		else
-			dev -= conf->near_copies;
-	}
-
 	offset = sector & conf->chunk_mask;
-	chunk = sector >> conf->chunk_shift;
+	if (conf->far_offset) {
+		int fc;
+		chunk = sector >> conf->chunk_shift;
+		fc = sector_div(chunk, conf->far_copies);
+		dev -= fc * conf->near_copies;
+		if (dev < 0)
+			dev += conf->raid_disks;
+	} else {
+		while (sector > conf->stride) {
+			sector -= conf->stride;
+			if (dev < conf->near_copies)
+				dev += conf->raid_disks - conf->near_copies;
+			else
+				dev -= conf->near_copies;
+		}
+		chunk = sector >> conf->chunk_shift;
+	}
 	vchunk = chunk * conf->raid_disks + dev;
 	sector_div(vchunk, conf->near_copies);
 	return (vchunk << conf->chunk_shift) + offset;
@@ -900,9 +914,12 @@
 		seq_printf(seq, " %dK chunks", mddev->chunk_size/1024);
 	if (conf->near_copies > 1)
 		seq_printf(seq, " %d near-copies", conf->near_copies);
-	if (conf->far_copies > 1)
-		seq_printf(seq, " %d far-copies", conf->far_copies);
-
+	if (conf->far_copies > 1) {
+		if (conf->far_offset)
+			seq_printf(seq, " %d offset-copies", conf->far_copies);
+		else
+			seq_printf(seq, " %d far-copies", conf->far_copies);
+	}
 	seq_printf(seq, " [%d/%d] [", conf->raid_disks,
 						conf->working_disks);
 	for (i = 0; i < conf->raid_disks; i++)
@@ -1915,7 +1932,7 @@
 	mirror_info_t *disk;
 	mdk_rdev_t *rdev;
 	struct list_head *tmp;
-	int nc, fc;
+	int nc, fc, fo;
 	sector_t stride, size;
 
 	if (mddev->chunk_size == 0) {
@@ -1925,8 +1942,9 @@
 
 	nc = mddev->layout & 255;
 	fc = (mddev->layout >> 8) & 255;
+	fo = mddev->layout & (1<<16);
 	if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
-	    (mddev->layout >> 16)) {
+	    (mddev->layout >> 17)) {
 		printk(KERN_ERR "raid10: %s: unsupported raid10 layout: 0x%8x\n",
 		       mdname(mddev), mddev->layout);
 		goto out;
@@ -1958,12 +1976,16 @@
 	conf->near_copies = nc;
 	conf->far_copies = fc;
 	conf->copies = nc*fc;
+	conf->far_offset = fo;
 	conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1;
 	conf->chunk_shift = ffz(~mddev->chunk_size) - 9;
-	stride = mddev->size >> (conf->chunk_shift-1);
-	sector_div(stride, fc);
-	conf->stride = stride << conf->chunk_shift;
-
+	if (fo)
+		conf->stride = 1 << conf->chunk_shift;
+	else {
+		stride = mddev->size >> (conf->chunk_shift-1);
+		sector_div(stride, fc);
+		conf->stride = stride << conf->chunk_shift;
+	}
 	conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
 						r10bio_pool_free, conf);
 	if (!conf->r10bio_pool) {
@@ -2015,7 +2037,8 @@
 
 		disk = conf->mirrors + i;
 
-		if (!disk->rdev) {
+		if (!disk->rdev ||
+		    !test_bit(In_sync, &rdev->flags)) {
 			disk->head_position = 0;
 			mddev->degraded++;
 		}
@@ -2037,7 +2060,13 @@
 	/*
 	 * Ok, everything is just fine now
 	 */
-	size = conf->stride * conf->raid_disks;
+	if (conf->far_offset) {
+		size = mddev->size >> (conf->chunk_shift-1);
+		size *= conf->raid_disks;
+		size <<= conf->chunk_shift;
+		sector_div(size, conf->far_copies);
+	} else
+		size = conf->stride * conf->raid_disks;
 	sector_div(size, conf->near_copies);
 	mddev->array_size = size/2;
 	mddev->resync_max_sectors = size;
@@ -2050,7 +2079,7 @@
 	 * maybe...
 	 */
 	{
-		int stripe = conf->raid_disks * mddev->chunk_size / PAGE_SIZE;
+		int stripe = conf->raid_disks * (mddev->chunk_size / PAGE_SIZE);
 		stripe /= conf->near_copies;
 		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 3184360..f920e50 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2,8 +2,11 @@
  * raid5.c : Multiple Devices driver for Linux
  *	   Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman
  *	   Copyright (C) 1999, 2000 Ingo Molnar
+ *	   Copyright (C) 2002, 2003 H. Peter Anvin
  *
- * RAID-5 management functions.
+ * RAID-4/5/6 management functions.
+ * Thanks to Penguin Computing for making the RAID-6 development possible
+ * by donating a test server!
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -19,11 +22,11 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/raid/raid5.h>
 #include <linux/highmem.h>
 #include <linux/bitops.h>
 #include <linux/kthread.h>
 #include <asm/atomic.h>
+#include "raid6.h"
 
 #include <linux/raid/bitmap.h>
 
@@ -68,6 +71,16 @@
 #define __inline__
 #endif
 
+#if !RAID6_USE_EMPTY_ZERO_PAGE
+/* In .bss so it's zeroed */
+const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256)));
+#endif
+
+static inline int raid6_next_disk(int disk, int raid_disks)
+{
+	disk++;
+	return (disk < raid_disks) ? disk : 0;
+}
 static void print_raid5_conf (raid5_conf_t *conf);
 
 static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
@@ -104,7 +117,7 @@
 {
 	raid5_conf_t *conf = sh->raid_conf;
 	unsigned long flags;
-	
+
 	spin_lock_irqsave(&conf->device_lock, flags);
 	__release_stripe(conf, sh);
 	spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -117,7 +130,7 @@
 	hlist_del_init(&sh->hash);
 }
 
-static void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
+static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh)
 {
 	struct hlist_head *hp = stripe_hash(conf, sh->sector);
 
@@ -190,7 +203,7 @@
 		(unsigned long long)sh->sector);
 
 	remove_hash(sh);
-	
+
 	sh->sector = sector;
 	sh->pd_idx = pd_idx;
 	sh->state = 0;
@@ -269,8 +282,9 @@
 			} else {
 				if (!test_bit(STRIPE_HANDLE, &sh->state))
 					atomic_inc(&conf->active_stripes);
-				if (!list_empty(&sh->lru))
-					list_del_init(&sh->lru);
+				if (list_empty(&sh->lru))
+					BUG();
+				list_del_init(&sh->lru);
 			}
 		}
 	} while (sh == NULL);
@@ -321,10 +335,9 @@
 		return 1;
 	conf->slab_cache = sc;
 	conf->pool_size = devs;
-	while (num--) {
+	while (num--)
 		if (!grow_one_stripe(conf))
 			return 1;
-	}
 	return 0;
 }
 
@@ -631,8 +644,7 @@
 	dev->req.bi_private = sh;
 
 	dev->flags = 0;
-	if (i != sh->pd_idx)
-		dev->sector = compute_blocknr(sh, i);
+	dev->sector = compute_blocknr(sh, i);
 }
 
 static void error(mddev_t *mddev, mdk_rdev_t *rdev)
@@ -659,7 +671,7 @@
 			" Operation continuing on %d devices\n",
 			bdevname(rdev->bdev,b), conf->working_disks);
 	}
-}	
+}
 
 /*
  * Input: a 'big' sector number,
@@ -697,9 +709,12 @@
 	/*
 	 * Select the parity disk based on the user selected algorithm.
 	 */
-	if (conf->level == 4)
+	switch(conf->level) {
+	case 4:
 		*pd_idx = data_disks;
-	else switch (conf->algorithm) {
+		break;
+	case 5:
+		switch (conf->algorithm) {
 		case ALGORITHM_LEFT_ASYMMETRIC:
 			*pd_idx = data_disks - stripe % raid_disks;
 			if (*dd_idx >= *pd_idx)
@@ -721,6 +736,39 @@
 		default:
 			printk(KERN_ERR "raid5: unsupported algorithm %d\n",
 				conf->algorithm);
+		}
+		break;
+	case 6:
+
+		/**** FIX THIS ****/
+		switch (conf->algorithm) {
+		case ALGORITHM_LEFT_ASYMMETRIC:
+			*pd_idx = raid_disks - 1 - (stripe % raid_disks);
+			if (*pd_idx == raid_disks-1)
+				(*dd_idx)++; 	/* Q D D D P */
+			else if (*dd_idx >= *pd_idx)
+				(*dd_idx) += 2; /* D D P Q D */
+			break;
+		case ALGORITHM_RIGHT_ASYMMETRIC:
+			*pd_idx = stripe % raid_disks;
+			if (*pd_idx == raid_disks-1)
+				(*dd_idx)++; 	/* Q D D D P */
+			else if (*dd_idx >= *pd_idx)
+				(*dd_idx) += 2; /* D D P Q D */
+			break;
+		case ALGORITHM_LEFT_SYMMETRIC:
+			*pd_idx = raid_disks - 1 - (stripe % raid_disks);
+			*dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks;
+			break;
+		case ALGORITHM_RIGHT_SYMMETRIC:
+			*pd_idx = stripe % raid_disks;
+			*dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks;
+			break;
+		default:
+			printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
+				conf->algorithm);
+		}
+		break;
 	}
 
 	/*
@@ -742,12 +790,17 @@
 	int chunk_number, dummy1, dummy2, dd_idx = i;
 	sector_t r_sector;
 
+
 	chunk_offset = sector_div(new_sector, sectors_per_chunk);
 	stripe = new_sector;
 	BUG_ON(new_sector != stripe);
 
-	
-	switch (conf->algorithm) {
+	if (i == sh->pd_idx)
+		return 0;
+	switch(conf->level) {
+	case 4: break;
+	case 5:
+		switch (conf->algorithm) {
 		case ALGORITHM_LEFT_ASYMMETRIC:
 		case ALGORITHM_RIGHT_ASYMMETRIC:
 			if (i > sh->pd_idx)
@@ -761,7 +814,37 @@
 			break;
 		default:
 			printk(KERN_ERR "raid5: unsupported algorithm %d\n",
+			       conf->algorithm);
+		}
+		break;
+	case 6:
+		data_disks = raid_disks - 2;
+		if (i == raid6_next_disk(sh->pd_idx, raid_disks))
+			return 0; /* It is the Q disk */
+		switch (conf->algorithm) {
+		case ALGORITHM_LEFT_ASYMMETRIC:
+		case ALGORITHM_RIGHT_ASYMMETRIC:
+		  	if (sh->pd_idx == raid_disks-1)
+				i--; 	/* Q D D D P */
+			else if (i > sh->pd_idx)
+				i -= 2; /* D D P Q D */
+			break;
+		case ALGORITHM_LEFT_SYMMETRIC:
+		case ALGORITHM_RIGHT_SYMMETRIC:
+			if (sh->pd_idx == raid_disks-1)
+				i--; /* Q D D D P */
+			else {
+				/* D D P Q D */
+				if (i < sh->pd_idx)
+					i += raid_disks;
+				i -= (sh->pd_idx + 2);
+			}
+			break;
+		default:
+			printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
 				conf->algorithm);
+		}
+		break;
 	}
 
 	chunk_number = stripe * data_disks + i;
@@ -778,10 +861,11 @@
 
 
 /*
- * Copy data between a page in the stripe cache, and a bio.
- * There are no alignment or size guarantees between the page or the
- * bio except that there is some overlap.
- * All iovecs in the bio must be considered.
+ * Copy data between a page in the stripe cache, and one or more bion
+ * The page could align with the middle of the bio, or there could be
+ * several bion, each with several bio_vecs, which cover part of the page
+ * Multiple bion are linked together on bi_next.  There may be extras
+ * at the end of this list.  We ignore them.
  */
 static void copy_data(int frombio, struct bio *bio,
 		     struct page *page,
@@ -810,7 +894,7 @@
 		if (len > 0 && page_offset + len > STRIPE_SIZE)
 			clen = STRIPE_SIZE - page_offset;
 		else clen = len;
-			
+
 		if (clen > 0) {
 			char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
 			if (frombio)
@@ -862,14 +946,14 @@
 	set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
 }
 
-static void compute_parity(struct stripe_head *sh, int method)
+static void compute_parity5(struct stripe_head *sh, int method)
 {
 	raid5_conf_t *conf = sh->raid_conf;
 	int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
 	void *ptr[MAX_XOR_BLOCKS];
 	struct bio *chosen;
 
-	PRINTK("compute_parity, stripe %llu, method %d\n",
+	PRINTK("compute_parity5, stripe %llu, method %d\n",
 		(unsigned long long)sh->sector, method);
 
 	count = 1;
@@ -956,9 +1040,195 @@
 		clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
 }
 
+static void compute_parity6(struct stripe_head *sh, int method)
+{
+	raid6_conf_t *conf = sh->raid_conf;
+	int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count;
+	struct bio *chosen;
+	/**** FIX THIS: This could be very bad if disks is close to 256 ****/
+	void *ptrs[disks];
+
+	qd_idx = raid6_next_disk(pd_idx, disks);
+	d0_idx = raid6_next_disk(qd_idx, disks);
+
+	PRINTK("compute_parity, stripe %llu, method %d\n",
+		(unsigned long long)sh->sector, method);
+
+	switch(method) {
+	case READ_MODIFY_WRITE:
+		BUG();		/* READ_MODIFY_WRITE N/A for RAID-6 */
+	case RECONSTRUCT_WRITE:
+		for (i= disks; i-- ;)
+			if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) {
+				chosen = sh->dev[i].towrite;
+				sh->dev[i].towrite = NULL;
+
+				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+					wake_up(&conf->wait_for_overlap);
+
+				if (sh->dev[i].written) BUG();
+				sh->dev[i].written = chosen;
+			}
+		break;
+	case CHECK_PARITY:
+		BUG();		/* Not implemented yet */
+	}
+
+	for (i = disks; i--;)
+		if (sh->dev[i].written) {
+			sector_t sector = sh->dev[i].sector;
+			struct bio *wbi = sh->dev[i].written;
+			while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
+				copy_data(1, wbi, sh->dev[i].page, sector);
+				wbi = r5_next_bio(wbi, sector);
+			}
+
+			set_bit(R5_LOCKED, &sh->dev[i].flags);
+			set_bit(R5_UPTODATE, &sh->dev[i].flags);
+		}
+
+//	switch(method) {
+//	case RECONSTRUCT_WRITE:
+//	case CHECK_PARITY:
+//	case UPDATE_PARITY:
+		/* Note that unlike RAID-5, the ordering of the disks matters greatly. */
+		/* FIX: Is this ordering of drives even remotely optimal? */
+		count = 0;
+		i = d0_idx;
+		do {
+			ptrs[count++] = page_address(sh->dev[i].page);
+			if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags))
+				printk("block %d/%d not uptodate on parity calc\n", i,count);
+			i = raid6_next_disk(i, disks);
+		} while ( i != d0_idx );
+//		break;
+//	}
+
+	raid6_call.gen_syndrome(disks, STRIPE_SIZE, ptrs);
+
+	switch(method) {
+	case RECONSTRUCT_WRITE:
+		set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+		set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
+		set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
+		set_bit(R5_LOCKED,   &sh->dev[qd_idx].flags);
+		break;
+	case UPDATE_PARITY:
+		set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
+		set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
+		break;
+	}
+}
+
+
+/* Compute one missing block */
+static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
+{
+	raid6_conf_t *conf = sh->raid_conf;
+	int i, count, disks = conf->raid_disks;
+	void *ptr[MAX_XOR_BLOCKS], *p;
+	int pd_idx = sh->pd_idx;
+	int qd_idx = raid6_next_disk(pd_idx, disks);
+
+	PRINTK("compute_block_1, stripe %llu, idx %d\n",
+		(unsigned long long)sh->sector, dd_idx);
+
+	if ( dd_idx == qd_idx ) {
+		/* We're actually computing the Q drive */
+		compute_parity6(sh, UPDATE_PARITY);
+	} else {
+		ptr[0] = page_address(sh->dev[dd_idx].page);
+		if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
+		count = 1;
+		for (i = disks ; i--; ) {
+			if (i == dd_idx || i == qd_idx)
+				continue;
+			p = page_address(sh->dev[i].page);
+			if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
+				ptr[count++] = p;
+			else
+				printk("compute_block() %d, stripe %llu, %d"
+				       " not present\n", dd_idx,
+				       (unsigned long long)sh->sector, i);
+
+			check_xor();
+		}
+		if (count != 1)
+			xor_block(count, STRIPE_SIZE, ptr);
+		if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+		else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
+	}
+}
+
+/* Compute two missing blocks */
+static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
+{
+	raid6_conf_t *conf = sh->raid_conf;
+	int i, count, disks = conf->raid_disks;
+	int pd_idx = sh->pd_idx;
+	int qd_idx = raid6_next_disk(pd_idx, disks);
+	int d0_idx = raid6_next_disk(qd_idx, disks);
+	int faila, failb;
+
+	/* faila and failb are disk numbers relative to d0_idx */
+	/* pd_idx become disks-2 and qd_idx become disks-1 */
+	faila = (dd_idx1 < d0_idx) ? dd_idx1+(disks-d0_idx) : dd_idx1-d0_idx;
+	failb = (dd_idx2 < d0_idx) ? dd_idx2+(disks-d0_idx) : dd_idx2-d0_idx;
+
+	BUG_ON(faila == failb);
+	if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
+
+	PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
+	       (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
+
+	if ( failb == disks-1 ) {
+		/* Q disk is one of the missing disks */
+		if ( faila == disks-2 ) {
+			/* Missing P+Q, just recompute */
+			compute_parity6(sh, UPDATE_PARITY);
+			return;
+		} else {
+			/* We're missing D+Q; recompute D from P */
+			compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0);
+			compute_parity6(sh, UPDATE_PARITY); /* Is this necessary? */
+			return;
+		}
+	}
+
+	/* We're missing D+P or D+D; build pointer table */
+	{
+		/**** FIX THIS: This could be very bad if disks is close to 256 ****/
+		void *ptrs[disks];
+
+		count = 0;
+		i = d0_idx;
+		do {
+			ptrs[count++] = page_address(sh->dev[i].page);
+			i = raid6_next_disk(i, disks);
+			if (i != dd_idx1 && i != dd_idx2 &&
+			    !test_bit(R5_UPTODATE, &sh->dev[i].flags))
+				printk("compute_2 with missing block %d/%d\n", count, i);
+		} while ( i != d0_idx );
+
+		if ( failb == disks-2 ) {
+			/* We're missing D+P. */
+			raid6_datap_recov(disks, STRIPE_SIZE, faila, ptrs);
+		} else {
+			/* We're missing D+D. */
+			raid6_2data_recov(disks, STRIPE_SIZE, faila, failb, ptrs);
+		}
+
+		/* Both the above update both missing blocks */
+		set_bit(R5_UPTODATE, &sh->dev[dd_idx1].flags);
+		set_bit(R5_UPTODATE, &sh->dev[dd_idx2].flags);
+	}
+}
+
+
+
 /*
  * Each stripe/dev can have one or more bion attached.
- * toread/towrite point to the first in a chain. 
+ * toread/towrite point to the first in a chain.
  * The bi_next chain must be in order.
  */
 static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
@@ -1031,6 +1301,13 @@
 
 static void end_reshape(raid5_conf_t *conf);
 
+static int page_is_zero(struct page *p)
+{
+	char *a = page_address(p);
+	return ((*(u32*)a) == 0 &&
+		memcmp(a, a+4, STRIPE_SIZE-4)==0);
+}
+
 static int stripe_to_pdidx(sector_t stripe, raid5_conf_t *conf, int disks)
 {
 	int sectors_per_chunk = conf->chunk_size >> 9;
@@ -1062,7 +1339,7 @@
  *
  */
  
-static void handle_stripe(struct stripe_head *sh)
+static void handle_stripe5(struct stripe_head *sh)
 {
 	raid5_conf_t *conf = sh->raid_conf;
 	int disks = sh->disks;
@@ -1394,7 +1671,7 @@
 		if (locked == 0 && (rcw == 0 ||rmw == 0) &&
 		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
 			PRINTK("Computing parity...\n");
-			compute_parity(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
+			compute_parity5(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
 			/* now every locked buffer is ready to be written */
 			for (i=disks; i--;)
 				if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
@@ -1421,13 +1698,10 @@
 	    !test_bit(STRIPE_INSYNC, &sh->state)) {
 		set_bit(STRIPE_HANDLE, &sh->state);
 		if (failed == 0) {
-			char *pagea;
 			BUG_ON(uptodate != disks);
-			compute_parity(sh, CHECK_PARITY);
+			compute_parity5(sh, CHECK_PARITY);
 			uptodate--;
-			pagea = page_address(sh->dev[sh->pd_idx].page);
-			if ((*(u32*)pagea) == 0 &&
-			    !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) {
+			if (page_is_zero(sh->dev[sh->pd_idx].page)) {
 				/* parity is correct (on disc, not in buffer any more) */
 				set_bit(STRIPE_INSYNC, &sh->state);
 			} else {
@@ -1487,7 +1761,7 @@
 		/* Need to write out all blocks after computing parity */
 		sh->disks = conf->raid_disks;
 		sh->pd_idx = stripe_to_pdidx(sh->sector, conf, conf->raid_disks);
-		compute_parity(sh, RECONSTRUCT_WRITE);
+		compute_parity5(sh, RECONSTRUCT_WRITE);
 		for (i= conf->raid_disks; i--;) {
 			set_bit(R5_LOCKED, &sh->dev[i].flags);
 			locked++;
@@ -1615,6 +1889,569 @@
 	}
 }
 
+static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
+{
+	raid6_conf_t *conf = sh->raid_conf;
+	int disks = conf->raid_disks;
+	struct bio *return_bi= NULL;
+	struct bio *bi;
+	int i;
+	int syncing;
+	int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
+	int non_overwrite = 0;
+	int failed_num[2] = {0, 0};
+	struct r5dev *dev, *pdev, *qdev;
+	int pd_idx = sh->pd_idx;
+	int qd_idx = raid6_next_disk(pd_idx, disks);
+	int p_failed, q_failed;
+
+	PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",
+	       (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),
+	       pd_idx, qd_idx);
+
+	spin_lock(&sh->lock);
+	clear_bit(STRIPE_HANDLE, &sh->state);
+	clear_bit(STRIPE_DELAYED, &sh->state);
+
+	syncing = test_bit(STRIPE_SYNCING, &sh->state);
+	/* Now to look around and see what can be done */
+
+	rcu_read_lock();
+	for (i=disks; i--; ) {
+		mdk_rdev_t *rdev;
+		dev = &sh->dev[i];
+		clear_bit(R5_Insync, &dev->flags);
+
+		PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
+			i, dev->flags, dev->toread, dev->towrite, dev->written);
+		/* maybe we can reply to a read */
+		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
+			struct bio *rbi, *rbi2;
+			PRINTK("Return read for disc %d\n", i);
+			spin_lock_irq(&conf->device_lock);
+			rbi = dev->toread;
+			dev->toread = NULL;
+			if (test_and_clear_bit(R5_Overlap, &dev->flags))
+				wake_up(&conf->wait_for_overlap);
+			spin_unlock_irq(&conf->device_lock);
+			while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
+				copy_data(0, rbi, dev->page, dev->sector);
+				rbi2 = r5_next_bio(rbi, dev->sector);
+				spin_lock_irq(&conf->device_lock);
+				if (--rbi->bi_phys_segments == 0) {
+					rbi->bi_next = return_bi;
+					return_bi = rbi;
+				}
+				spin_unlock_irq(&conf->device_lock);
+				rbi = rbi2;
+			}
+		}
+
+		/* now count some things */
+		if (test_bit(R5_LOCKED, &dev->flags)) locked++;
+		if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
+
+
+		if (dev->toread) to_read++;
+		if (dev->towrite) {
+			to_write++;
+			if (!test_bit(R5_OVERWRITE, &dev->flags))
+				non_overwrite++;
+		}
+		if (dev->written) written++;
+		rdev = rcu_dereference(conf->disks[i].rdev);
+		if (!rdev || !test_bit(In_sync, &rdev->flags)) {
+			/* The ReadError flag will just be confusing now */
+			clear_bit(R5_ReadError, &dev->flags);
+			clear_bit(R5_ReWrite, &dev->flags);
+		}
+		if (!rdev || !test_bit(In_sync, &rdev->flags)
+		    || test_bit(R5_ReadError, &dev->flags)) {
+			if ( failed < 2 )
+				failed_num[failed] = i;
+			failed++;
+		} else
+			set_bit(R5_Insync, &dev->flags);
+	}
+	rcu_read_unlock();
+	PRINTK("locked=%d uptodate=%d to_read=%d"
+	       " to_write=%d failed=%d failed_num=%d,%d\n",
+	       locked, uptodate, to_read, to_write, failed,
+	       failed_num[0], failed_num[1]);
+	/* check if the array has lost >2 devices and, if so, some requests might
+	 * need to be failed
+	 */
+	if (failed > 2 && to_read+to_write+written) {
+		for (i=disks; i--; ) {
+			int bitmap_end = 0;
+
+			if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
+				mdk_rdev_t *rdev;
+				rcu_read_lock();
+				rdev = rcu_dereference(conf->disks[i].rdev);
+				if (rdev && test_bit(In_sync, &rdev->flags))
+					/* multiple read failures in one stripe */
+					md_error(conf->mddev, rdev);
+				rcu_read_unlock();
+			}
+
+			spin_lock_irq(&conf->device_lock);
+			/* fail all writes first */
+			bi = sh->dev[i].towrite;
+			sh->dev[i].towrite = NULL;
+			if (bi) { to_write--; bitmap_end = 1; }
+
+			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+				wake_up(&conf->wait_for_overlap);
+
+			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
+				struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+				clear_bit(BIO_UPTODATE, &bi->bi_flags);
+				if (--bi->bi_phys_segments == 0) {
+					md_write_end(conf->mddev);
+					bi->bi_next = return_bi;
+					return_bi = bi;
+				}
+				bi = nextbi;
+			}
+			/* and fail all 'written' */
+			bi = sh->dev[i].written;
+			sh->dev[i].written = NULL;
+			if (bi) bitmap_end = 1;
+			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
+				struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
+				clear_bit(BIO_UPTODATE, &bi->bi_flags);
+				if (--bi->bi_phys_segments == 0) {
+					md_write_end(conf->mddev);
+					bi->bi_next = return_bi;
+					return_bi = bi;
+				}
+				bi = bi2;
+			}
+
+			/* fail any reads if this device is non-operational */
+			if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
+			    test_bit(R5_ReadError, &sh->dev[i].flags)) {
+				bi = sh->dev[i].toread;
+				sh->dev[i].toread = NULL;
+				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
+					wake_up(&conf->wait_for_overlap);
+				if (bi) to_read--;
+				while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
+					struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
+					clear_bit(BIO_UPTODATE, &bi->bi_flags);
+					if (--bi->bi_phys_segments == 0) {
+						bi->bi_next = return_bi;
+						return_bi = bi;
+					}
+					bi = nextbi;
+				}
+			}
+			spin_unlock_irq(&conf->device_lock);
+			if (bitmap_end)
+				bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+						STRIPE_SECTORS, 0, 0);
+		}
+	}
+	if (failed > 2 && syncing) {
+		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
+		clear_bit(STRIPE_SYNCING, &sh->state);
+		syncing = 0;
+	}
+
+	/*
+	 * might be able to return some write requests if the parity blocks
+	 * are safe, or on a failed drive
+	 */
+	pdev = &sh->dev[pd_idx];
+	p_failed = (failed >= 1 && failed_num[0] == pd_idx)
+		|| (failed >= 2 && failed_num[1] == pd_idx);
+	qdev = &sh->dev[qd_idx];
+	q_failed = (failed >= 1 && failed_num[0] == qd_idx)
+		|| (failed >= 2 && failed_num[1] == qd_idx);
+
+	if ( written &&
+	     ( p_failed || ((test_bit(R5_Insync, &pdev->flags)
+			     && !test_bit(R5_LOCKED, &pdev->flags)
+			     && test_bit(R5_UPTODATE, &pdev->flags))) ) &&
+	     ( q_failed || ((test_bit(R5_Insync, &qdev->flags)
+			     && !test_bit(R5_LOCKED, &qdev->flags)
+			     && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {
+		/* any written block on an uptodate or failed drive can be
+		 * returned.  Note that if we 'wrote' to a failed drive,
+		 * it will be UPTODATE, but never LOCKED, so we don't need
+		 * to test 'failed' directly.
+		 */
+		for (i=disks; i--; )
+			if (sh->dev[i].written) {
+				dev = &sh->dev[i];
+				if (!test_bit(R5_LOCKED, &dev->flags) &&
+				    test_bit(R5_UPTODATE, &dev->flags) ) {
+					/* We can return any write requests */
+					int bitmap_end = 0;
+					struct bio *wbi, *wbi2;
+					PRINTK("Return write for stripe %llu disc %d\n",
+					       (unsigned long long)sh->sector, i);
+					spin_lock_irq(&conf->device_lock);
+					wbi = dev->written;
+					dev->written = NULL;
+					while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
+						wbi2 = r5_next_bio(wbi, dev->sector);
+						if (--wbi->bi_phys_segments == 0) {
+							md_write_end(conf->mddev);
+							wbi->bi_next = return_bi;
+							return_bi = wbi;
+						}
+						wbi = wbi2;
+					}
+					if (dev->towrite == NULL)
+						bitmap_end = 1;
+					spin_unlock_irq(&conf->device_lock);
+					if (bitmap_end)
+						bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+								STRIPE_SECTORS,
+								!test_bit(STRIPE_DEGRADED, &sh->state), 0);
+				}
+			}
+	}
+
+	/* Now we might consider reading some blocks, either to check/generate
+	 * parity, or to satisfy requests
+	 * or to load a block that is being partially written.
+	 */
+	if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) {
+		for (i=disks; i--;) {
+			dev = &sh->dev[i];
+			if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
+			    (dev->toread ||
+			     (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
+			     syncing ||
+			     (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
+			     (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
+				    )
+				) {
+				/* we would like to get this block, possibly
+				 * by computing it, but we might not be able to
+				 */
+				if (uptodate == disks-1) {
+					PRINTK("Computing stripe %llu block %d\n",
+					       (unsigned long long)sh->sector, i);
+					compute_block_1(sh, i, 0);
+					uptodate++;
+				} else if ( uptodate == disks-2 && failed >= 2 ) {
+					/* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
+					int other;
+					for (other=disks; other--;) {
+						if ( other == i )
+							continue;
+						if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )
+							break;
+					}
+					BUG_ON(other < 0);
+					PRINTK("Computing stripe %llu blocks %d,%d\n",
+					       (unsigned long long)sh->sector, i, other);
+					compute_block_2(sh, i, other);
+					uptodate += 2;
+				} else if (test_bit(R5_Insync, &dev->flags)) {
+					set_bit(R5_LOCKED, &dev->flags);
+					set_bit(R5_Wantread, &dev->flags);
+#if 0
+					/* if I am just reading this block and we don't have
+					   a failed drive, or any pending writes then sidestep the cache */
+					if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&
+					    ! syncing && !failed && !to_write) {
+						sh->bh_cache[i]->b_page =  sh->bh_read[i]->b_page;
+						sh->bh_cache[i]->b_data =  sh->bh_read[i]->b_data;
+					}
+#endif
+					locked++;
+					PRINTK("Reading block %d (sync=%d)\n",
+						i, syncing);
+				}
+			}
+		}
+		set_bit(STRIPE_HANDLE, &sh->state);
+	}
+
+	/* now to consider writing and what else, if anything should be read */
+	if (to_write) {
+		int rcw=0, must_compute=0;
+		for (i=disks ; i--;) {
+			dev = &sh->dev[i];
+			/* Would I have to read this buffer for reconstruct_write */
+			if (!test_bit(R5_OVERWRITE, &dev->flags)
+			    && i != pd_idx && i != qd_idx
+			    && (!test_bit(R5_LOCKED, &dev->flags)
+#if 0
+				|| sh->bh_page[i] != bh->b_page
+#endif
+				    ) &&
+			    !test_bit(R5_UPTODATE, &dev->flags)) {
+				if (test_bit(R5_Insync, &dev->flags)) rcw++;
+				else {
+					PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);
+					must_compute++;
+				}
+			}
+		}
+		PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",
+		       (unsigned long long)sh->sector, rcw, must_compute);
+		set_bit(STRIPE_HANDLE, &sh->state);
+
+		if (rcw > 0)
+			/* want reconstruct write, but need to get some data */
+			for (i=disks; i--;) {
+				dev = &sh->dev[i];
+				if (!test_bit(R5_OVERWRITE, &dev->flags)
+				    && !(failed == 0 && (i == pd_idx || i == qd_idx))
+				    && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
+				    test_bit(R5_Insync, &dev->flags)) {
+					if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
+					{
+						PRINTK("Read_old stripe %llu block %d for Reconstruct\n",
+						       (unsigned long long)sh->sector, i);
+						set_bit(R5_LOCKED, &dev->flags);
+						set_bit(R5_Wantread, &dev->flags);
+						locked++;
+					} else {
+						PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",
+						       (unsigned long long)sh->sector, i);
+						set_bit(STRIPE_DELAYED, &sh->state);
+						set_bit(STRIPE_HANDLE, &sh->state);
+					}
+				}
+			}
+		/* now if nothing is locked, and if we have enough data, we can start a write request */
+		if (locked == 0 && rcw == 0 &&
+		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
+			if ( must_compute > 0 ) {
+				/* We have failed blocks and need to compute them */
+				switch ( failed ) {
+				case 0:	BUG();
+				case 1: compute_block_1(sh, failed_num[0], 0); break;
+				case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
+				default: BUG();	/* This request should have been failed? */
+				}
+			}
+
+			PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);
+			compute_parity6(sh, RECONSTRUCT_WRITE);
+			/* now every locked buffer is ready to be written */
+			for (i=disks; i--;)
+				if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
+					PRINTK("Writing stripe %llu block %d\n",
+					       (unsigned long long)sh->sector, i);
+					locked++;
+					set_bit(R5_Wantwrite, &sh->dev[i].flags);
+				}
+			/* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
+			set_bit(STRIPE_INSYNC, &sh->state);
+
+			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
+				atomic_dec(&conf->preread_active_stripes);
+				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
+					md_wakeup_thread(conf->mddev->thread);
+			}
+		}
+	}
+
+	/* maybe we need to check and possibly fix the parity for this stripe
+	 * Any reads will already have been scheduled, so we just see if enough data
+	 * is available
+	 */
+	if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
+		int update_p = 0, update_q = 0;
+		struct r5dev *dev;
+
+		set_bit(STRIPE_HANDLE, &sh->state);
+
+		BUG_ON(failed>2);
+		BUG_ON(uptodate < disks);
+		/* Want to check and possibly repair P and Q.
+		 * However there could be one 'failed' device, in which
+		 * case we can only check one of them, possibly using the
+		 * other to generate missing data
+		 */
+
+		/* If !tmp_page, we cannot do the calculations,
+		 * but as we have set STRIPE_HANDLE, we will soon be called
+		 * by stripe_handle with a tmp_page - just wait until then.
+		 */
+		if (tmp_page) {
+			if (failed == q_failed) {
+				/* The only possible failed device holds 'Q', so it makes
+				 * sense to check P (If anything else were failed, we would
+				 * have used P to recreate it).
+				 */
+				compute_block_1(sh, pd_idx, 1);
+				if (!page_is_zero(sh->dev[pd_idx].page)) {
+					compute_block_1(sh,pd_idx,0);
+					update_p = 1;
+				}
+			}
+			if (!q_failed && failed < 2) {
+				/* q is not failed, and we didn't use it to generate
+				 * anything, so it makes sense to check it
+				 */
+				memcpy(page_address(tmp_page),
+				       page_address(sh->dev[qd_idx].page),
+				       STRIPE_SIZE);
+				compute_parity6(sh, UPDATE_PARITY);
+				if (memcmp(page_address(tmp_page),
+					   page_address(sh->dev[qd_idx].page),
+					   STRIPE_SIZE)!= 0) {
+					clear_bit(STRIPE_INSYNC, &sh->state);
+					update_q = 1;
+				}
+			}
+			if (update_p || update_q) {
+				conf->mddev->resync_mismatches += STRIPE_SECTORS;
+				if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
+					/* don't try to repair!! */
+					update_p = update_q = 0;
+			}
+
+			/* now write out any block on a failed drive,
+			 * or P or Q if they need it
+			 */
+
+			if (failed == 2) {
+				dev = &sh->dev[failed_num[1]];
+				locked++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
+			if (failed >= 1) {
+				dev = &sh->dev[failed_num[0]];
+				locked++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
+
+			if (update_p) {
+				dev = &sh->dev[pd_idx];
+				locked ++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
+			if (update_q) {
+				dev = &sh->dev[qd_idx];
+				locked++;
+				set_bit(R5_LOCKED, &dev->flags);
+				set_bit(R5_Wantwrite, &dev->flags);
+			}
+			clear_bit(STRIPE_DEGRADED, &sh->state);
+
+			set_bit(STRIPE_INSYNC, &sh->state);
+		}
+	}
+
+	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
+		md_done_sync(conf->mddev, STRIPE_SECTORS,1);
+		clear_bit(STRIPE_SYNCING, &sh->state);
+	}
+
+	/* If the failed drives are just a ReadError, then we might need
+	 * to progress the repair/check process
+	 */
+	if (failed <= 2 && ! conf->mddev->ro)
+		for (i=0; i<failed;i++) {
+			dev = &sh->dev[failed_num[i]];
+			if (test_bit(R5_ReadError, &dev->flags)
+			    && !test_bit(R5_LOCKED, &dev->flags)
+			    && test_bit(R5_UPTODATE, &dev->flags)
+				) {
+				if (!test_bit(R5_ReWrite, &dev->flags)) {
+					set_bit(R5_Wantwrite, &dev->flags);
+					set_bit(R5_ReWrite, &dev->flags);
+					set_bit(R5_LOCKED, &dev->flags);
+				} else {
+					/* let's read it back */
+					set_bit(R5_Wantread, &dev->flags);
+					set_bit(R5_LOCKED, &dev->flags);
+				}
+			}
+		}
+	spin_unlock(&sh->lock);
+
+	while ((bi=return_bi)) {
+		int bytes = bi->bi_size;
+
+		return_bi = bi->bi_next;
+		bi->bi_next = NULL;
+		bi->bi_size = 0;
+		bi->bi_end_io(bi, bytes, 0);
+	}
+	for (i=disks; i-- ;) {
+		int rw;
+		struct bio *bi;
+		mdk_rdev_t *rdev;
+		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
+			rw = 1;
+		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
+			rw = 0;
+		else
+			continue;
+
+		bi = &sh->dev[i].req;
+
+		bi->bi_rw = rw;
+		if (rw)
+			bi->bi_end_io = raid5_end_write_request;
+		else
+			bi->bi_end_io = raid5_end_read_request;
+
+		rcu_read_lock();
+		rdev = rcu_dereference(conf->disks[i].rdev);
+		if (rdev && test_bit(Faulty, &rdev->flags))
+			rdev = NULL;
+		if (rdev)
+			atomic_inc(&rdev->nr_pending);
+		rcu_read_unlock();
+
+		if (rdev) {
+			if (syncing)
+				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
+
+			bi->bi_bdev = rdev->bdev;
+			PRINTK("for %llu schedule op %ld on disc %d\n",
+				(unsigned long long)sh->sector, bi->bi_rw, i);
+			atomic_inc(&sh->count);
+			bi->bi_sector = sh->sector + rdev->data_offset;
+			bi->bi_flags = 1 << BIO_UPTODATE;
+			bi->bi_vcnt = 1;
+			bi->bi_max_vecs = 1;
+			bi->bi_idx = 0;
+			bi->bi_io_vec = &sh->dev[i].vec;
+			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
+			bi->bi_io_vec[0].bv_offset = 0;
+			bi->bi_size = STRIPE_SIZE;
+			bi->bi_next = NULL;
+			if (rw == WRITE &&
+			    test_bit(R5_ReWrite, &sh->dev[i].flags))
+				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
+			generic_make_request(bi);
+		} else {
+			if (rw == 1)
+				set_bit(STRIPE_DEGRADED, &sh->state);
+			PRINTK("skip op %ld on disc %d for sector %llu\n",
+				bi->bi_rw, i, (unsigned long long)sh->sector);
+			clear_bit(R5_LOCKED, &sh->dev[i].flags);
+			set_bit(STRIPE_HANDLE, &sh->state);
+		}
+	}
+}
+
+static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
+{
+	if (sh->raid_conf->level == 6)
+		handle_stripe6(sh, tmp_page);
+	else
+		handle_stripe5(sh);
+}
+
+
+
 static void raid5_activate_delayed(raid5_conf_t *conf)
 {
 	if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
@@ -1753,7 +2590,7 @@
 
 	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
 		DEFINE_WAIT(w);
-		int disks;
+		int disks, data_disks;
 
 	retry:
 		prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
@@ -1781,7 +2618,9 @@
 			}
 			spin_unlock_irq(&conf->device_lock);
 		}
- 		new_sector = raid5_compute_sector(logical_sector, disks, disks - 1,
+		data_disks = disks - conf->max_degraded;
+
+ 		new_sector = raid5_compute_sector(logical_sector, disks, data_disks,
 						  &dd_idx, &pd_idx, conf);
 		PRINTK("raid5: make_request, sector %llu logical %llu\n",
 			(unsigned long long)new_sector, 
@@ -1833,7 +2672,7 @@
 			}
 			finish_wait(&conf->wait_for_overlap, &w);
 			raid5_plug_device(conf);
-			handle_stripe(sh);
+			handle_stripe(sh, NULL);
 			release_stripe(sh);
 		} else {
 			/* cannot get stripe for read-ahead, just give-up */
@@ -1849,7 +2688,7 @@
 	if (remaining == 0) {
 		int bytes = bi->bi_size;
 
-		if ( bio_data_dir(bi) == WRITE )
+		if ( rw == WRITE )
 			md_write_end(mddev);
 		bi->bi_size = 0;
 		bi->bi_end_io(bi, bytes, 0);
@@ -1857,17 +2696,142 @@
 	return 0;
 }
 
-/* FIXME go_faster isn't used */
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped)
 {
+	/* reshaping is quite different to recovery/resync so it is
+	 * handled quite separately ... here.
+	 *
+	 * On each call to sync_request, we gather one chunk worth of
+	 * destination stripes and flag them as expanding.
+	 * Then we find all the source stripes and request reads.
+	 * As the reads complete, handle_stripe will copy the data
+	 * into the destination stripe and release that stripe.
+	 */
 	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
 	struct stripe_head *sh;
 	int pd_idx;
 	sector_t first_sector, last_sector;
+	int raid_disks;
+	int data_disks;
+	int i;
+	int dd_idx;
+	sector_t writepos, safepos, gap;
+
+	if (sector_nr == 0 &&
+	    conf->expand_progress != 0) {
+		/* restarting in the middle, skip the initial sectors */
+		sector_nr = conf->expand_progress;
+		sector_div(sector_nr, conf->raid_disks-1);
+		*skipped = 1;
+		return sector_nr;
+	}
+
+	/* we update the metadata when there is more than 3Meg
+	 * in the block range (that is rather arbitrary, should
+	 * probably be time based) or when the data about to be
+	 * copied would over-write the source of the data at
+	 * the front of the range.
+	 * i.e. one new_stripe forward from expand_progress new_maps
+	 * to after where expand_lo old_maps to
+	 */
+	writepos = conf->expand_progress +
+		conf->chunk_size/512*(conf->raid_disks-1);
+	sector_div(writepos, conf->raid_disks-1);
+	safepos = conf->expand_lo;
+	sector_div(safepos, conf->previous_raid_disks-1);
+	gap = conf->expand_progress - conf->expand_lo;
+
+	if (writepos >= safepos ||
+	    gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) {
+		/* Cannot proceed until we've updated the superblock... */
+		wait_event(conf->wait_for_overlap,
+			   atomic_read(&conf->reshape_stripes)==0);
+		mddev->reshape_position = conf->expand_progress;
+		mddev->sb_dirty = 1;
+		md_wakeup_thread(mddev->thread);
+		wait_event(mddev->sb_wait, mddev->sb_dirty == 0 ||
+			   kthread_should_stop());
+		spin_lock_irq(&conf->device_lock);
+		conf->expand_lo = mddev->reshape_position;
+		spin_unlock_irq(&conf->device_lock);
+		wake_up(&conf->wait_for_overlap);
+	}
+
+	for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) {
+		int j;
+		int skipped = 0;
+		pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks);
+		sh = get_active_stripe(conf, sector_nr+i,
+				       conf->raid_disks, pd_idx, 0);
+		set_bit(STRIPE_EXPANDING, &sh->state);
+		atomic_inc(&conf->reshape_stripes);
+		/* If any of this stripe is beyond the end of the old
+		 * array, then we need to zero those blocks
+		 */
+		for (j=sh->disks; j--;) {
+			sector_t s;
+			if (j == sh->pd_idx)
+				continue;
+			s = compute_blocknr(sh, j);
+			if (s < (mddev->array_size<<1)) {
+				skipped = 1;
+				continue;
+			}
+			memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE);
+			set_bit(R5_Expanded, &sh->dev[j].flags);
+			set_bit(R5_UPTODATE, &sh->dev[j].flags);
+		}
+		if (!skipped) {
+			set_bit(STRIPE_EXPAND_READY, &sh->state);
+			set_bit(STRIPE_HANDLE, &sh->state);
+		}
+		release_stripe(sh);
+	}
+	spin_lock_irq(&conf->device_lock);
+	conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1);
+	spin_unlock_irq(&conf->device_lock);
+	/* Ok, those stripe are ready. We can start scheduling
+	 * reads on the source stripes.
+	 * The source stripes are determined by mapping the first and last
+	 * block on the destination stripes.
+	 */
+	raid_disks = conf->previous_raid_disks;
+	data_disks = raid_disks - 1;
+	first_sector =
+		raid5_compute_sector(sector_nr*(conf->raid_disks-1),
+				     raid_disks, data_disks,
+				     &dd_idx, &pd_idx, conf);
+	last_sector =
+		raid5_compute_sector((sector_nr+conf->chunk_size/512)
+				     *(conf->raid_disks-1) -1,
+				     raid_disks, data_disks,
+				     &dd_idx, &pd_idx, conf);
+	if (last_sector >= (mddev->size<<1))
+		last_sector = (mddev->size<<1)-1;
+	while (first_sector <= last_sector) {
+		pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks);
+		sh = get_active_stripe(conf, first_sector,
+				       conf->previous_raid_disks, pd_idx, 0);
+		set_bit(STRIPE_EXPAND_SOURCE, &sh->state);
+		set_bit(STRIPE_HANDLE, &sh->state);
+		release_stripe(sh);
+		first_sector += STRIPE_SECTORS;
+	}
+	return conf->chunk_size>>9;
+}
+
+/* FIXME go_faster isn't used */
+static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
+{
+	raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
+	struct stripe_head *sh;
+	int pd_idx;
 	int raid_disks = conf->raid_disks;
-	int data_disks = raid_disks-1;
+	int data_disks = raid_disks - conf->max_degraded;
 	sector_t max_sector = mddev->size << 1;
 	int sync_blocks;
+	int still_degraded = 0;
+	int i;
 
 	if (sector_nr >= max_sector) {
 		/* just being told to finish up .. nothing much to do */
@@ -1880,134 +2844,22 @@
 		if (mddev->curr_resync < max_sector) /* aborted */
 			bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
 					&sync_blocks, 1);
-		else /* compelted sync */
+		else /* completed sync */
 			conf->fullsync = 0;
 		bitmap_close_sync(mddev->bitmap);
 
 		return 0;
 	}
 
-	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
-		/* reshaping is quite different to recovery/resync so it is
-		 * handled quite separately ... here.
-		 *
-		 * On each call to sync_request, we gather one chunk worth of
-		 * destination stripes and flag them as expanding.
-		 * Then we find all the source stripes and request reads.
-		 * As the reads complete, handle_stripe will copy the data
-		 * into the destination stripe and release that stripe.
-		 */
-		int i;
-		int dd_idx;
-		sector_t writepos, safepos, gap;
+	if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+		return reshape_request(mddev, sector_nr, skipped);
 
-		if (sector_nr == 0 &&
-		    conf->expand_progress != 0) {
-			/* restarting in the middle, skip the initial sectors */
-			sector_nr = conf->expand_progress;
-			sector_div(sector_nr, conf->raid_disks-1);
-			*skipped = 1;
-			return sector_nr;
-		}
-
-		/* we update the metadata when there is more than 3Meg
-		 * in the block range (that is rather arbitrary, should
-		 * probably be time based) or when the data about to be
-		 * copied would over-write the source of the data at
-		 * the front of the range.
-		 * i.e. one new_stripe forward from expand_progress new_maps
-		 * to after where expand_lo old_maps to
-		 */
-		writepos = conf->expand_progress +
-			conf->chunk_size/512*(conf->raid_disks-1);
-		sector_div(writepos, conf->raid_disks-1);
-		safepos = conf->expand_lo;
-		sector_div(safepos, conf->previous_raid_disks-1);
-		gap = conf->expand_progress - conf->expand_lo;
-
-		if (writepos >= safepos ||
-		    gap > (conf->raid_disks-1)*3000*2 /*3Meg*/) {
-			/* Cannot proceed until we've updated the superblock... */
-			wait_event(conf->wait_for_overlap,
-				   atomic_read(&conf->reshape_stripes)==0);
-			mddev->reshape_position = conf->expand_progress;
-			mddev->sb_dirty = 1;
-			md_wakeup_thread(mddev->thread);
-			wait_event(mddev->sb_wait, mddev->sb_dirty == 0 ||
-				   kthread_should_stop());
-			spin_lock_irq(&conf->device_lock);
-			conf->expand_lo = mddev->reshape_position;
-			spin_unlock_irq(&conf->device_lock);
-			wake_up(&conf->wait_for_overlap);
-		}
-
-		for (i=0; i < conf->chunk_size/512; i+= STRIPE_SECTORS) {
-			int j;
-			int skipped = 0;
-			pd_idx = stripe_to_pdidx(sector_nr+i, conf, conf->raid_disks);
-			sh = get_active_stripe(conf, sector_nr+i,
-					       conf->raid_disks, pd_idx, 0);
-			set_bit(STRIPE_EXPANDING, &sh->state);
-			atomic_inc(&conf->reshape_stripes);
-			/* If any of this stripe is beyond the end of the old
-			 * array, then we need to zero those blocks
-			 */
-			for (j=sh->disks; j--;) {
-				sector_t s;
-				if (j == sh->pd_idx)
-					continue;
-				s = compute_blocknr(sh, j);
-				if (s < (mddev->array_size<<1)) {
-					skipped = 1;
-					continue;
-				}
-				memset(page_address(sh->dev[j].page), 0, STRIPE_SIZE);
-				set_bit(R5_Expanded, &sh->dev[j].flags);
-				set_bit(R5_UPTODATE, &sh->dev[j].flags);
-			}
-			if (!skipped) {
-				set_bit(STRIPE_EXPAND_READY, &sh->state);
-				set_bit(STRIPE_HANDLE, &sh->state);
-			}
-			release_stripe(sh);
-		}
-		spin_lock_irq(&conf->device_lock);
-		conf->expand_progress = (sector_nr + i)*(conf->raid_disks-1);
-		spin_unlock_irq(&conf->device_lock);
-		/* Ok, those stripe are ready. We can start scheduling
-		 * reads on the source stripes.
-		 * The source stripes are determined by mapping the first and last
-		 * block on the destination stripes.
-		 */
-		raid_disks = conf->previous_raid_disks;
-		data_disks = raid_disks - 1;
-		first_sector =
-			raid5_compute_sector(sector_nr*(conf->raid_disks-1),
-					     raid_disks, data_disks,
-					     &dd_idx, &pd_idx, conf);
-		last_sector =
-			raid5_compute_sector((sector_nr+conf->chunk_size/512)
-					       *(conf->raid_disks-1) -1,
-					     raid_disks, data_disks,
-					     &dd_idx, &pd_idx, conf);
-		if (last_sector >= (mddev->size<<1))
-			last_sector = (mddev->size<<1)-1;
-		while (first_sector <= last_sector) {
-			pd_idx = stripe_to_pdidx(first_sector, conf, conf->previous_raid_disks);
-			sh = get_active_stripe(conf, first_sector,
-					       conf->previous_raid_disks, pd_idx, 0);
-			set_bit(STRIPE_EXPAND_SOURCE, &sh->state);
-			set_bit(STRIPE_HANDLE, &sh->state);
-			release_stripe(sh);
-			first_sector += STRIPE_SECTORS;
-		}
-		return conf->chunk_size>>9;
-	}
-	/* if there is 1 or more failed drives and we are trying
+	/* if there is too many failed drives and we are trying
 	 * to resync, then assert that we are finished, because there is
 	 * nothing we can do.
 	 */
-	if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+	if (mddev->degraded >= conf->max_degraded &&
+	    test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
 		sector_t rv = (mddev->size << 1) - sector_nr;
 		*skipped = 1;
 		return rv;
@@ -2026,17 +2878,26 @@
 	if (sh == NULL) {
 		sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0);
 		/* make sure we don't swamp the stripe cache if someone else
-		 * is trying to get access 
+		 * is trying to get access
 		 */
 		schedule_timeout_uninterruptible(1);
 	}
-	bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
-	spin_lock(&sh->lock);	
+	/* Need to check if array will still be degraded after recovery/resync
+	 * We don't need to check the 'failed' flag as when that gets set,
+	 * recovery aborts.
+	 */
+	for (i=0; i<mddev->raid_disks; i++)
+		if (conf->disks[i].rdev == NULL)
+			still_degraded = 1;
+
+	bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
+
+	spin_lock(&sh->lock);
 	set_bit(STRIPE_SYNCING, &sh->state);
 	clear_bit(STRIPE_INSYNC, &sh->state);
 	spin_unlock(&sh->lock);
 
-	handle_stripe(sh);
+	handle_stripe(sh, NULL);
 	release_stripe(sh);
 
 	return STRIPE_SECTORS;
@@ -2091,7 +2952,7 @@
 		spin_unlock_irq(&conf->device_lock);
 		
 		handled++;
-		handle_stripe(sh);
+		handle_stripe(sh, conf->spare_page);
 		release_stripe(sh);
 
 		spin_lock_irq(&conf->device_lock);
@@ -2181,8 +3042,8 @@
 	struct disk_info *disk;
 	struct list_head *tmp;
 
-	if (mddev->level != 5 && mddev->level != 4) {
-		printk(KERN_ERR "raid5: %s: raid level not set to 4/5 (%d)\n",
+	if (mddev->level != 5 && mddev->level != 4 && mddev->level != 6) {
+		printk(KERN_ERR "raid5: %s: raid level not set to 4/5/6 (%d)\n",
 		       mdname(mddev), mddev->level);
 		return -EIO;
 	}
@@ -2251,6 +3112,11 @@
 	if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
 		goto abort;
 
+	if (mddev->level == 6) {
+		conf->spare_page = alloc_page(GFP_KERNEL);
+		if (!conf->spare_page)
+			goto abort;
+	}
 	spin_lock_init(&conf->device_lock);
 	init_waitqueue_head(&conf->wait_for_stripe);
 	init_waitqueue_head(&conf->wait_for_overlap);
@@ -2282,12 +3148,16 @@
 	}
 
 	/*
-	 * 0 for a fully functional array, 1 for a degraded array.
+	 * 0 for a fully functional array, 1 or 2 for a degraded array.
 	 */
 	mddev->degraded = conf->failed_disks = conf->raid_disks - conf->working_disks;
 	conf->mddev = mddev;
 	conf->chunk_size = mddev->chunk_size;
 	conf->level = mddev->level;
+	if (conf->level == 6)
+		conf->max_degraded = 2;
+	else
+		conf->max_degraded = 1;
 	conf->algorithm = mddev->layout;
 	conf->max_nr_stripes = NR_STRIPES;
 	conf->expand_progress = mddev->reshape_position;
@@ -2296,6 +3166,11 @@
 	mddev->size &= ~(mddev->chunk_size/1024 -1);
 	mddev->resync_max_sectors = mddev->size << 1;
 
+	if (conf->level == 6 && conf->raid_disks < 4) {
+		printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n",
+		       mdname(mddev), conf->raid_disks);
+		goto abort;
+	}
 	if (!conf->chunk_size || conf->chunk_size % 4) {
 		printk(KERN_ERR "raid5: invalid chunk size %d for %s\n",
 			conf->chunk_size, mdname(mddev));
@@ -2307,14 +3182,14 @@
 			conf->algorithm, mdname(mddev));
 		goto abort;
 	}
-	if (mddev->degraded > 1) {
+	if (mddev->degraded > conf->max_degraded) {
 		printk(KERN_ERR "raid5: not enough operational devices for %s"
 			" (%d/%d failed)\n",
 			mdname(mddev), conf->failed_disks, conf->raid_disks);
 		goto abort;
 	}
 
-	if (mddev->degraded == 1 &&
+	if (mddev->degraded > 0 &&
 	    mddev->recovery_cp != MaxSector) {
 		if (mddev->ok_start_degraded)
 			printk(KERN_WARNING
@@ -2379,11 +3254,12 @@
 	}
 
 	/* read-ahead size must cover two whole stripes, which is
-	 * 2 * (n-1) * chunksize where 'n' is the number of raid devices
+	 * 2 * (datadisks) * chunksize where 'n' is the number of raid devices
 	 */
 	{
-		int stripe = (mddev->raid_disks-1) * mddev->chunk_size
-			/ PAGE_SIZE;
+		int data_disks = conf->previous_raid_disks - conf->max_degraded;
+		int stripe = data_disks *
+			(mddev->chunk_size / PAGE_SIZE);
 		if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
 			mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
 	}
@@ -2393,12 +3269,14 @@
 
 	mddev->queue->unplug_fn = raid5_unplug_device;
 	mddev->queue->issue_flush_fn = raid5_issue_flush;
-	mddev->array_size =  mddev->size * (conf->previous_raid_disks - 1);
+	mddev->array_size =  mddev->size * (conf->previous_raid_disks -
+					    conf->max_degraded);
 
 	return 0;
 abort:
 	if (conf) {
 		print_raid5_conf(conf);
+		safe_put_page(conf->spare_page);
 		kfree(conf->disks);
 		kfree(conf->stripe_hashtbl);
 		kfree(conf);
@@ -2427,23 +3305,23 @@
 }
 
 #if RAID5_DEBUG
-static void print_sh (struct stripe_head *sh)
+static void print_sh (struct seq_file *seq, struct stripe_head *sh)
 {
 	int i;
 
-	printk("sh %llu, pd_idx %d, state %ld.\n",
-		(unsigned long long)sh->sector, sh->pd_idx, sh->state);
-	printk("sh %llu,  count %d.\n",
-		(unsigned long long)sh->sector, atomic_read(&sh->count));
-	printk("sh %llu, ", (unsigned long long)sh->sector);
+	seq_printf(seq, "sh %llu, pd_idx %d, state %ld.\n",
+		   (unsigned long long)sh->sector, sh->pd_idx, sh->state);
+	seq_printf(seq, "sh %llu,  count %d.\n",
+		   (unsigned long long)sh->sector, atomic_read(&sh->count));
+	seq_printf(seq, "sh %llu, ", (unsigned long long)sh->sector);
 	for (i = 0; i < sh->disks; i++) {
-		printk("(cache%d: %p %ld) ", 
-			i, sh->dev[i].page, sh->dev[i].flags);
+		seq_printf(seq, "(cache%d: %p %ld) ",
+			   i, sh->dev[i].page, sh->dev[i].flags);
 	}
-	printk("\n");
+	seq_printf(seq, "\n");
 }
 
-static void printall (raid5_conf_t *conf)
+static void printall (struct seq_file *seq, raid5_conf_t *conf)
 {
 	struct stripe_head *sh;
 	struct hlist_node *hn;
@@ -2454,7 +3332,7 @@
 		hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
 			if (sh->raid_conf != conf)
 				continue;
-			print_sh(sh);
+			print_sh(seq, sh);
 		}
 	}
 	spin_unlock_irq(&conf->device_lock);
@@ -2474,9 +3352,8 @@
 			       test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
 	seq_printf (seq, "]");
 #if RAID5_DEBUG
-#define D(x) \
-	seq_printf (seq, "<"#x":%d>", atomic_read(&conf->x))
-	printall(conf);
+	seq_printf (seq, "\n");
+	printall(seq, conf);
 #endif
 }
 
@@ -2560,14 +3437,20 @@
 	int disk;
 	struct disk_info *p;
 
-	if (mddev->degraded > 1)
+	if (mddev->degraded > conf->max_degraded)
 		/* no point adding a device */
 		return 0;
 
 	/*
-	 * find the disk ...
+	 * find the disk ... but prefer rdev->saved_raid_disk
+	 * if possible.
 	 */
-	for (disk=0; disk < conf->raid_disks; disk++)
+	if (rdev->saved_raid_disk >= 0 &&
+	    conf->disks[rdev->saved_raid_disk].rdev == NULL)
+		disk = rdev->saved_raid_disk;
+	else
+		disk = 0;
+	for ( ; disk < conf->raid_disks; disk++)
 		if ((p=conf->disks + disk)->rdev == NULL) {
 			clear_bit(In_sync, &rdev->flags);
 			rdev->raid_disk = disk;
@@ -2590,8 +3473,10 @@
 	 * any io in the removed space completes, but it hardly seems
 	 * worth it.
 	 */
+	raid5_conf_t *conf = mddev_to_conf(mddev);
+
 	sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
-	mddev->array_size = (sectors * (mddev->raid_disks-1))>>1;
+	mddev->array_size = (sectors * (mddev->raid_disks-conf->max_degraded))>>1;
 	set_capacity(mddev->gendisk, mddev->array_size << 1);
 	mddev->changed = 1;
 	if (sectors/2  > mddev->size && mddev->recovery_cp == MaxSector) {
@@ -2680,6 +3565,7 @@
 				set_bit(In_sync, &rdev->flags);
 				conf->working_disks++;
 				added_devices++;
+				rdev->recovery_offset = 0;
 				sprintf(nm, "rd%d", rdev->raid_disk);
 				sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
 			} else
@@ -2731,6 +3617,17 @@
 		conf->expand_progress = MaxSector;
 		spin_unlock_irq(&conf->device_lock);
 		conf->mddev->reshape_position = MaxSector;
+
+		/* read-ahead size must cover two whole stripes, which is
+		 * 2 * (datadisks) * chunksize where 'n' is the number of raid devices
+		 */
+		{
+			int data_disks = conf->previous_raid_disks - conf->max_degraded;
+			int stripe = data_disks *
+				(conf->mddev->chunk_size / PAGE_SIZE);
+			if (conf->mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
+				conf->mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
+		}
 	}
 }
 
@@ -2762,6 +3659,23 @@
 	}
 }
 
+static struct mdk_personality raid6_personality =
+{
+	.name		= "raid6",
+	.level		= 6,
+	.owner		= THIS_MODULE,
+	.make_request	= make_request,
+	.run		= run,
+	.stop		= stop,
+	.status		= status,
+	.error_handler	= error,
+	.hot_add_disk	= raid5_add_disk,
+	.hot_remove_disk= raid5_remove_disk,
+	.spare_active	= raid5_spare_active,
+	.sync_request	= sync_request,
+	.resize		= raid5_resize,
+	.quiesce	= raid5_quiesce,
+};
 static struct mdk_personality raid5_personality =
 {
 	.name		= "raid5",
@@ -2804,6 +3718,12 @@
 
 static int __init raid5_init(void)
 {
+	int e;
+
+	e = raid6_select_algo();
+	if ( e )
+		return e;
+	register_md_personality(&raid6_personality);
 	register_md_personality(&raid5_personality);
 	register_md_personality(&raid4_personality);
 	return 0;
@@ -2811,6 +3731,7 @@
 
 static void raid5_exit(void)
 {
+	unregister_md_personality(&raid6_personality);
 	unregister_md_personality(&raid5_personality);
 	unregister_md_personality(&raid4_personality);
 }
@@ -2823,3 +3744,10 @@
 MODULE_ALIAS("md-raid4");
 MODULE_ALIAS("md-level-5");
 MODULE_ALIAS("md-level-4");
+MODULE_ALIAS("md-personality-8"); /* RAID6 */
+MODULE_ALIAS("md-raid6");
+MODULE_ALIAS("md-level-6");
+
+/* This used to be two separate modules, they were: */
+MODULE_ALIAS("raid5");
+MODULE_ALIAS("raid6");
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c
index 51c63c0..9265761 100644
--- a/drivers/md/raid6algos.c
+++ b/drivers/md/raid6algos.c
@@ -139,15 +139,14 @@
 		}
 	}
 
-	if ( best )
+	if (best) {
 		printk("raid6: using algorithm %s (%ld MB/s)\n",
 		       best->name,
 		       (bestperf*HZ) >> (20-16+RAID6_TIME_JIFFIES_LG2));
-	else
+		raid6_call = *best;
+	} else
 		printk("raid6: Yikes!  No algorithm found!\n");
 
-	raid6_call = *best;
-
 	free_pages((unsigned long)syndromes, 1);
 
 	return best ? 0 : -EINVAL;
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
deleted file mode 100644
index bc69355..0000000
--- a/drivers/md/raid6main.c
+++ /dev/null
@@ -1,2427 +0,0 @@
-/*
- * raid6main.c : Multiple Devices driver for Linux
- *	   Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman
- *	   Copyright (C) 1999, 2000 Ingo Molnar
- *	   Copyright (C) 2002, 2003 H. Peter Anvin
- *
- * RAID-6 management functions.  This code is derived from raid5.c.
- * Last merge from raid5.c bkcvs version 1.79 (kernel 2.6.1).
- *
- * Thanks to Penguin Computing for making the RAID-6 development possible
- * by donating a test server!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * 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.
- */
-
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/highmem.h>
-#include <linux/bitops.h>
-#include <asm/atomic.h>
-#include "raid6.h"
-
-#include <linux/raid/bitmap.h>
-
-/*
- * Stripe cache
- */
-
-#define NR_STRIPES		256
-#define STRIPE_SIZE		PAGE_SIZE
-#define STRIPE_SHIFT		(PAGE_SHIFT - 9)
-#define STRIPE_SECTORS		(STRIPE_SIZE>>9)
-#define	IO_THRESHOLD		1
-#define NR_HASH			(PAGE_SIZE / sizeof(struct hlist_head))
-#define HASH_MASK		(NR_HASH - 1)
-
-#define stripe_hash(conf, sect)	(&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]))
-
-/* bio's attached to a stripe+device for I/O are linked together in bi_sector
- * order without overlap.  There may be several bio's per stripe+device, and
- * a bio could span several devices.
- * When walking this list for a particular stripe+device, we must never proceed
- * beyond a bio that extends past this device, as the next bio might no longer
- * be valid.
- * This macro is used to determine the 'next' bio in the list, given the sector
- * of the current stripe+device
- */
-#define r5_next_bio(bio, sect) ( ( (bio)->bi_sector + ((bio)->bi_size>>9) < sect + STRIPE_SECTORS) ? (bio)->bi_next : NULL)
-/*
- * The following can be used to debug the driver
- */
-#define RAID6_DEBUG	0	/* Extremely verbose printk */
-#define RAID6_PARANOIA	1	/* Check spinlocks */
-#define RAID6_DUMPSTATE 0	/* Include stripe cache state in /proc/mdstat */
-#if RAID6_PARANOIA && defined(CONFIG_SMP)
-# define CHECK_DEVLOCK() assert_spin_locked(&conf->device_lock)
-#else
-# define CHECK_DEVLOCK()
-#endif
-
-#define PRINTK(x...) ((void)(RAID6_DEBUG && printk(KERN_DEBUG x)))
-#if RAID6_DEBUG
-#undef inline
-#undef __inline__
-#define inline
-#define __inline__
-#endif
-
-#if !RAID6_USE_EMPTY_ZERO_PAGE
-/* In .bss so it's zeroed */
-const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256)));
-#endif
-
-static inline int raid6_next_disk(int disk, int raid_disks)
-{
-	disk++;
-	return (disk < raid_disks) ? disk : 0;
-}
-
-static void print_raid6_conf (raid6_conf_t *conf);
-
-static void __release_stripe(raid6_conf_t *conf, struct stripe_head *sh)
-{
-	if (atomic_dec_and_test(&sh->count)) {
-		BUG_ON(!list_empty(&sh->lru));
-		BUG_ON(atomic_read(&conf->active_stripes)==0);
-		if (test_bit(STRIPE_HANDLE, &sh->state)) {
-			if (test_bit(STRIPE_DELAYED, &sh->state))
-				list_add_tail(&sh->lru, &conf->delayed_list);
-			else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
-				 conf->seq_write == sh->bm_seq)
-				list_add_tail(&sh->lru, &conf->bitmap_list);
-			else {
-				clear_bit(STRIPE_BIT_DELAY, &sh->state);
-				list_add_tail(&sh->lru, &conf->handle_list);
-			}
-			md_wakeup_thread(conf->mddev->thread);
-		} else {
-			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-				atomic_dec(&conf->preread_active_stripes);
-				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-					md_wakeup_thread(conf->mddev->thread);
-			}
-			list_add_tail(&sh->lru, &conf->inactive_list);
-			atomic_dec(&conf->active_stripes);
-			if (!conf->inactive_blocked ||
-			    atomic_read(&conf->active_stripes) < (conf->max_nr_stripes*3/4))
-				wake_up(&conf->wait_for_stripe);
-		}
-	}
-}
-static void release_stripe(struct stripe_head *sh)
-{
-	raid6_conf_t *conf = sh->raid_conf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&conf->device_lock, flags);
-	__release_stripe(conf, sh);
-	spin_unlock_irqrestore(&conf->device_lock, flags);
-}
-
-static inline void remove_hash(struct stripe_head *sh)
-{
-	PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector);
-
-	hlist_del_init(&sh->hash);
-}
-
-static inline void insert_hash(raid6_conf_t *conf, struct stripe_head *sh)
-{
-	struct hlist_head *hp = stripe_hash(conf, sh->sector);
-
-	PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector);
-
-	CHECK_DEVLOCK();
-	hlist_add_head(&sh->hash, hp);
-}
-
-
-/* find an idle stripe, make sure it is unhashed, and return it. */
-static struct stripe_head *get_free_stripe(raid6_conf_t *conf)
-{
-	struct stripe_head *sh = NULL;
-	struct list_head *first;
-
-	CHECK_DEVLOCK();
-	if (list_empty(&conf->inactive_list))
-		goto out;
-	first = conf->inactive_list.next;
-	sh = list_entry(first, struct stripe_head, lru);
-	list_del_init(first);
-	remove_hash(sh);
-	atomic_inc(&conf->active_stripes);
-out:
-	return sh;
-}
-
-static void shrink_buffers(struct stripe_head *sh, int num)
-{
-	struct page *p;
-	int i;
-
-	for (i=0; i<num ; i++) {
-		p = sh->dev[i].page;
-		if (!p)
-			continue;
-		sh->dev[i].page = NULL;
-		put_page(p);
-	}
-}
-
-static int grow_buffers(struct stripe_head *sh, int num)
-{
-	int i;
-
-	for (i=0; i<num; i++) {
-		struct page *page;
-
-		if (!(page = alloc_page(GFP_KERNEL))) {
-			return 1;
-		}
-		sh->dev[i].page = page;
-	}
-	return 0;
-}
-
-static void raid6_build_block (struct stripe_head *sh, int i);
-
-static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
-{
-	raid6_conf_t *conf = sh->raid_conf;
-	int disks = conf->raid_disks, i;
-
-	BUG_ON(atomic_read(&sh->count) != 0);
-	BUG_ON(test_bit(STRIPE_HANDLE, &sh->state));
-
-	CHECK_DEVLOCK();
-	PRINTK("init_stripe called, stripe %llu\n",
-		(unsigned long long)sh->sector);
-
-	remove_hash(sh);
-
-	sh->sector = sector;
-	sh->pd_idx = pd_idx;
-	sh->state = 0;
-
-	for (i=disks; i--; ) {
-		struct r5dev *dev = &sh->dev[i];
-
-		if (dev->toread || dev->towrite || dev->written ||
-		    test_bit(R5_LOCKED, &dev->flags)) {
-			PRINTK("sector=%llx i=%d %p %p %p %d\n",
-			       (unsigned long long)sh->sector, i, dev->toread,
-			       dev->towrite, dev->written,
-			       test_bit(R5_LOCKED, &dev->flags));
-			BUG();
-		}
-		dev->flags = 0;
-		raid6_build_block(sh, i);
-	}
-	insert_hash(conf, sh);
-}
-
-static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector)
-{
-	struct stripe_head *sh;
-	struct hlist_node *hn;
-
-	CHECK_DEVLOCK();
-	PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
-	hlist_for_each_entry (sh, hn,  stripe_hash(conf, sector), hash)
-		if (sh->sector == sector)
-			return sh;
-	PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
-	return NULL;
-}
-
-static void unplug_slaves(mddev_t *mddev);
-
-static struct stripe_head *get_active_stripe(raid6_conf_t *conf, sector_t sector,
-					     int pd_idx, int noblock)
-{
-	struct stripe_head *sh;
-
-	PRINTK("get_stripe, sector %llu\n", (unsigned long long)sector);
-
-	spin_lock_irq(&conf->device_lock);
-
-	do {
-		wait_event_lock_irq(conf->wait_for_stripe,
-				    conf->quiesce == 0,
-				    conf->device_lock, /* nothing */);
-		sh = __find_stripe(conf, sector);
-		if (!sh) {
-			if (!conf->inactive_blocked)
-				sh = get_free_stripe(conf);
-			if (noblock && sh == NULL)
-				break;
-			if (!sh) {
-				conf->inactive_blocked = 1;
-				wait_event_lock_irq(conf->wait_for_stripe,
-						    !list_empty(&conf->inactive_list) &&
-						    (atomic_read(&conf->active_stripes)
-						     < (conf->max_nr_stripes *3/4)
-						     || !conf->inactive_blocked),
-						    conf->device_lock,
-						    unplug_slaves(conf->mddev);
-					);
-				conf->inactive_blocked = 0;
-			} else
-				init_stripe(sh, sector, pd_idx);
-		} else {
-			if (atomic_read(&sh->count)) {
-				BUG_ON(!list_empty(&sh->lru));
-			} else {
-				if (!test_bit(STRIPE_HANDLE, &sh->state))
-					atomic_inc(&conf->active_stripes);
-				BUG_ON(list_empty(&sh->lru));
-				list_del_init(&sh->lru);
-			}
-		}
-	} while (sh == NULL);
-
-	if (sh)
-		atomic_inc(&sh->count);
-
-	spin_unlock_irq(&conf->device_lock);
-	return sh;
-}
-
-static int grow_one_stripe(raid6_conf_t *conf)
-{
-	struct stripe_head *sh;
-	sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
-	if (!sh)
-		return 0;
-	memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
-	sh->raid_conf = conf;
-	spin_lock_init(&sh->lock);
-
-	if (grow_buffers(sh, conf->raid_disks)) {
-		shrink_buffers(sh, conf->raid_disks);
-		kmem_cache_free(conf->slab_cache, sh);
-		return 0;
-	}
-	/* we just created an active stripe so... */
-	atomic_set(&sh->count, 1);
-	atomic_inc(&conf->active_stripes);
-	INIT_LIST_HEAD(&sh->lru);
-	release_stripe(sh);
-	return 1;
-}
-
-static int grow_stripes(raid6_conf_t *conf, int num)
-{
-	kmem_cache_t *sc;
-	int devs = conf->raid_disks;
-
-	sprintf(conf->cache_name[0], "raid6/%s", mdname(conf->mddev));
-
-	sc = kmem_cache_create(conf->cache_name[0],
-			       sizeof(struct stripe_head)+(devs-1)*sizeof(struct r5dev),
-			       0, 0, NULL, NULL);
-	if (!sc)
-		return 1;
-	conf->slab_cache = sc;
-	while (num--)
-		if (!grow_one_stripe(conf))
-			return 1;
-	return 0;
-}
-
-static int drop_one_stripe(raid6_conf_t *conf)
-{
-	struct stripe_head *sh;
-	spin_lock_irq(&conf->device_lock);
-	sh = get_free_stripe(conf);
-	spin_unlock_irq(&conf->device_lock);
-	if (!sh)
-		return 0;
-	BUG_ON(atomic_read(&sh->count));
-	shrink_buffers(sh, conf->raid_disks);
-	kmem_cache_free(conf->slab_cache, sh);
-	atomic_dec(&conf->active_stripes);
-	return 1;
-}
-
-static void shrink_stripes(raid6_conf_t *conf)
-{
-	while (drop_one_stripe(conf))
-		;
-
-	if (conf->slab_cache)
-		kmem_cache_destroy(conf->slab_cache);
-	conf->slab_cache = NULL;
-}
-
-static int raid6_end_read_request(struct bio * bi, unsigned int bytes_done,
-				  int error)
-{
- 	struct stripe_head *sh = bi->bi_private;
-	raid6_conf_t *conf = sh->raid_conf;
-	int disks = conf->raid_disks, i;
-	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
-
-	if (bi->bi_size)
-		return 1;
-
-	for (i=0 ; i<disks; i++)
-		if (bi == &sh->dev[i].req)
-			break;
-
-	PRINTK("end_read_request %llu/%d, count: %d, uptodate %d.\n",
-		(unsigned long long)sh->sector, i, atomic_read(&sh->count),
-		uptodate);
-	if (i == disks) {
-		BUG();
-		return 0;
-	}
-
-	if (uptodate) {
-#if 0
-		struct bio *bio;
-		unsigned long flags;
-		spin_lock_irqsave(&conf->device_lock, flags);
-		/* we can return a buffer if we bypassed the cache or
-		 * if the top buffer is not in highmem.  If there are
-		 * multiple buffers, leave the extra work to
-		 * handle_stripe
-		 */
-		buffer = sh->bh_read[i];
-		if (buffer &&
-		    (!PageHighMem(buffer->b_page)
-		     || buffer->b_page == bh->b_page )
-			) {
-			sh->bh_read[i] = buffer->b_reqnext;
-			buffer->b_reqnext = NULL;
-		} else
-			buffer = NULL;
-		spin_unlock_irqrestore(&conf->device_lock, flags);
-		if (sh->bh_page[i]==bh->b_page)
-			set_buffer_uptodate(bh);
-		if (buffer) {
-			if (buffer->b_page != bh->b_page)
-				memcpy(buffer->b_data, bh->b_data, bh->b_size);
-			buffer->b_end_io(buffer, 1);
-		}
-#else
-		set_bit(R5_UPTODATE, &sh->dev[i].flags);
-#endif
-		if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-			printk(KERN_INFO "raid6: read error corrected!!\n");
-			clear_bit(R5_ReadError, &sh->dev[i].flags);
-			clear_bit(R5_ReWrite, &sh->dev[i].flags);
-		}
-		if (atomic_read(&conf->disks[i].rdev->read_errors))
-			atomic_set(&conf->disks[i].rdev->read_errors, 0);
-	} else {
-		int retry = 0;
-		clear_bit(R5_UPTODATE, &sh->dev[i].flags);
-		atomic_inc(&conf->disks[i].rdev->read_errors);
-		if (conf->mddev->degraded)
-			printk(KERN_WARNING "raid6: read error not correctable.\n");
-		else if (test_bit(R5_ReWrite, &sh->dev[i].flags))
-			/* Oh, no!!! */
-			printk(KERN_WARNING "raid6: read error NOT corrected!!\n");
-		else if (atomic_read(&conf->disks[i].rdev->read_errors)
-			 > conf->max_nr_stripes)
-			printk(KERN_WARNING
-			       "raid6: Too many read errors, failing device.\n");
-		else
-			retry = 1;
-		if (retry)
-			set_bit(R5_ReadError, &sh->dev[i].flags);
-		else {
-			clear_bit(R5_ReadError, &sh->dev[i].flags);
-			clear_bit(R5_ReWrite, &sh->dev[i].flags);
-			md_error(conf->mddev, conf->disks[i].rdev);
-		}
-	}
-	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
-#if 0
-	/* must restore b_page before unlocking buffer... */
-	if (sh->bh_page[i] != bh->b_page) {
-		bh->b_page = sh->bh_page[i];
-		bh->b_data = page_address(bh->b_page);
-		clear_buffer_uptodate(bh);
-	}
-#endif
-	clear_bit(R5_LOCKED, &sh->dev[i].flags);
-	set_bit(STRIPE_HANDLE, &sh->state);
-	release_stripe(sh);
-	return 0;
-}
-
-static int raid6_end_write_request (struct bio *bi, unsigned int bytes_done,
-				    int error)
-{
- 	struct stripe_head *sh = bi->bi_private;
-	raid6_conf_t *conf = sh->raid_conf;
-	int disks = conf->raid_disks, i;
-	unsigned long flags;
-	int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
-
-	if (bi->bi_size)
-		return 1;
-
-	for (i=0 ; i<disks; i++)
-		if (bi == &sh->dev[i].req)
-			break;
-
-	PRINTK("end_write_request %llu/%d, count %d, uptodate: %d.\n",
-		(unsigned long long)sh->sector, i, atomic_read(&sh->count),
-		uptodate);
-	if (i == disks) {
-		BUG();
-		return 0;
-	}
-
-	spin_lock_irqsave(&conf->device_lock, flags);
-	if (!uptodate)
-		md_error(conf->mddev, conf->disks[i].rdev);
-
-	rdev_dec_pending(conf->disks[i].rdev, conf->mddev);
-
-	clear_bit(R5_LOCKED, &sh->dev[i].flags);
-	set_bit(STRIPE_HANDLE, &sh->state);
-	__release_stripe(conf, sh);
-	spin_unlock_irqrestore(&conf->device_lock, flags);
-	return 0;
-}
-
-
-static sector_t compute_blocknr(struct stripe_head *sh, int i);
-
-static void raid6_build_block (struct stripe_head *sh, int i)
-{
-	struct r5dev *dev = &sh->dev[i];
-	int pd_idx = sh->pd_idx;
-	int qd_idx = raid6_next_disk(pd_idx, sh->raid_conf->raid_disks);
-
-	bio_init(&dev->req);
-	dev->req.bi_io_vec = &dev->vec;
-	dev->req.bi_vcnt++;
-	dev->req.bi_max_vecs++;
-	dev->vec.bv_page = dev->page;
-	dev->vec.bv_len = STRIPE_SIZE;
-	dev->vec.bv_offset = 0;
-
-	dev->req.bi_sector = sh->sector;
-	dev->req.bi_private = sh;
-
-	dev->flags = 0;
-	if (i != pd_idx && i != qd_idx)
-		dev->sector = compute_blocknr(sh, i);
-}
-
-static void error(mddev_t *mddev, mdk_rdev_t *rdev)
-{
-	char b[BDEVNAME_SIZE];
-	raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
-	PRINTK("raid6: error called\n");
-
-	if (!test_bit(Faulty, &rdev->flags)) {
-		mddev->sb_dirty = 1;
-		if (test_bit(In_sync, &rdev->flags)) {
-			conf->working_disks--;
-			mddev->degraded++;
-			conf->failed_disks++;
-			clear_bit(In_sync, &rdev->flags);
-			/*
-			 * if recovery was running, make sure it aborts.
-			 */
-			set_bit(MD_RECOVERY_ERR, &mddev->recovery);
-		}
-		set_bit(Faulty, &rdev->flags);
-		printk (KERN_ALERT
-			"raid6: Disk failure on %s, disabling device."
-			" Operation continuing on %d devices\n",
-			bdevname(rdev->bdev,b), conf->working_disks);
-	}
-}
-
-/*
- * Input: a 'big' sector number,
- * Output: index of the data and parity disk, and the sector # in them.
- */
-static sector_t raid6_compute_sector(sector_t r_sector, unsigned int raid_disks,
-			unsigned int data_disks, unsigned int * dd_idx,
-			unsigned int * pd_idx, raid6_conf_t *conf)
-{
-	long stripe;
-	unsigned long chunk_number;
-	unsigned int chunk_offset;
-	sector_t new_sector;
-	int sectors_per_chunk = conf->chunk_size >> 9;
-
-	/* First compute the information on this sector */
-
-	/*
-	 * Compute the chunk number and the sector offset inside the chunk
-	 */
-	chunk_offset = sector_div(r_sector, sectors_per_chunk);
-	chunk_number = r_sector;
-	if ( r_sector != chunk_number ) {
-		printk(KERN_CRIT "raid6: ERROR: r_sector = %llu, chunk_number = %lu\n",
-		       (unsigned long long)r_sector, (unsigned long)chunk_number);
-		BUG();
-	}
-
-	/*
-	 * Compute the stripe number
-	 */
-	stripe = chunk_number / data_disks;
-
-	/*
-	 * Compute the data disk and parity disk indexes inside the stripe
-	 */
-	*dd_idx = chunk_number % data_disks;
-
-	/*
-	 * Select the parity disk based on the user selected algorithm.
-	 */
-
-	/**** FIX THIS ****/
-	switch (conf->algorithm) {
-	case ALGORITHM_LEFT_ASYMMETRIC:
-		*pd_idx = raid_disks - 1 - (stripe % raid_disks);
-		if (*pd_idx == raid_disks-1)
-		  	(*dd_idx)++; 	/* Q D D D P */
-		else if (*dd_idx >= *pd_idx)
-		  	(*dd_idx) += 2; /* D D P Q D */
-		break;
-	case ALGORITHM_RIGHT_ASYMMETRIC:
-		*pd_idx = stripe % raid_disks;
-		if (*pd_idx == raid_disks-1)
-		  	(*dd_idx)++; 	/* Q D D D P */
-		else if (*dd_idx >= *pd_idx)
-		  	(*dd_idx) += 2; /* D D P Q D */
-		break;
-	case ALGORITHM_LEFT_SYMMETRIC:
-		*pd_idx = raid_disks - 1 - (stripe % raid_disks);
-		*dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks;
-		break;
-	case ALGORITHM_RIGHT_SYMMETRIC:
-		*pd_idx = stripe % raid_disks;
-		*dd_idx = (*pd_idx + 2 + *dd_idx) % raid_disks;
-		break;
-	default:
-		printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
-			conf->algorithm);
-	}
-
-	PRINTK("raid6: chunk_number = %lu, pd_idx = %u, dd_idx = %u\n",
-	       chunk_number, *pd_idx, *dd_idx);
-
-	/*
-	 * Finally, compute the new sector number
-	 */
-	new_sector = (sector_t) stripe * sectors_per_chunk + chunk_offset;
-	return new_sector;
-}
-
-
-static sector_t compute_blocknr(struct stripe_head *sh, int i)
-{
-	raid6_conf_t *conf = sh->raid_conf;
-	int raid_disks = conf->raid_disks, data_disks = raid_disks - 2;
-	sector_t new_sector = sh->sector, check;
-	int sectors_per_chunk = conf->chunk_size >> 9;
-	sector_t stripe;
-	int chunk_offset;
-	int chunk_number, dummy1, dummy2, dd_idx = i;
-	sector_t r_sector;
-	int i0 = i;
-
-	chunk_offset = sector_div(new_sector, sectors_per_chunk);
-	stripe = new_sector;
-	if ( new_sector != stripe ) {
-		printk(KERN_CRIT "raid6: ERROR: new_sector = %llu, stripe = %lu\n",
-		       (unsigned long long)new_sector, (unsigned long)stripe);
-		BUG();
-	}
-
-	switch (conf->algorithm) {
-		case ALGORITHM_LEFT_ASYMMETRIC:
-		case ALGORITHM_RIGHT_ASYMMETRIC:
-		  	if (sh->pd_idx == raid_disks-1)
-				i--; 	/* Q D D D P */
-			else if (i > sh->pd_idx)
-				i -= 2; /* D D P Q D */
-			break;
-		case ALGORITHM_LEFT_SYMMETRIC:
-		case ALGORITHM_RIGHT_SYMMETRIC:
-			if (sh->pd_idx == raid_disks-1)
-				i--; /* Q D D D P */
-			else {
-				/* D D P Q D */
-				if (i < sh->pd_idx)
-					i += raid_disks;
-				i -= (sh->pd_idx + 2);
-			}
-			break;
-		default:
-			printk (KERN_CRIT "raid6: unsupported algorithm %d\n",
-				conf->algorithm);
-	}
-
-	PRINTK("raid6: compute_blocknr: pd_idx = %u, i0 = %u, i = %u\n", sh->pd_idx, i0, i);
-
-	chunk_number = stripe * data_disks + i;
-	r_sector = (sector_t)chunk_number * sectors_per_chunk + chunk_offset;
-
-	check = raid6_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf);
-	if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) {
-		printk(KERN_CRIT "raid6: compute_blocknr: map not correct\n");
-		return 0;
-	}
-	return r_sector;
-}
-
-
-
-/*
- * Copy data between a page in the stripe cache, and one or more bion
- * The page could align with the middle of the bio, or there could be
- * several bion, each with several bio_vecs, which cover part of the page
- * Multiple bion are linked together on bi_next.  There may be extras
- * at the end of this list.  We ignore them.
- */
-static void copy_data(int frombio, struct bio *bio,
-		     struct page *page,
-		     sector_t sector)
-{
-	char *pa = page_address(page);
-	struct bio_vec *bvl;
-	int i;
-	int page_offset;
-
-	if (bio->bi_sector >= sector)
-		page_offset = (signed)(bio->bi_sector - sector) * 512;
-	else
-		page_offset = (signed)(sector - bio->bi_sector) * -512;
-	bio_for_each_segment(bvl, bio, i) {
-		int len = bio_iovec_idx(bio,i)->bv_len;
-		int clen;
-		int b_offset = 0;
-
-		if (page_offset < 0) {
-			b_offset = -page_offset;
-			page_offset += b_offset;
-			len -= b_offset;
-		}
-
-		if (len > 0 && page_offset + len > STRIPE_SIZE)
-			clen = STRIPE_SIZE - page_offset;
-		else clen = len;
-
-		if (clen > 0) {
-			char *ba = __bio_kmap_atomic(bio, i, KM_USER0);
-			if (frombio)
-				memcpy(pa+page_offset, ba+b_offset, clen);
-			else
-				memcpy(ba+b_offset, pa+page_offset, clen);
-			__bio_kunmap_atomic(ba, KM_USER0);
-		}
-		if (clen < len) /* hit end of page */
-			break;
-		page_offset +=  len;
-	}
-}
-
-#define check_xor() 	do { 						\
-			   if (count == MAX_XOR_BLOCKS) {		\
-				xor_block(count, STRIPE_SIZE, ptr);	\
-				count = 1;				\
-			   }						\
-			} while(0)
-
-/* Compute P and Q syndromes */
-static void compute_parity(struct stripe_head *sh, int method)
-{
-	raid6_conf_t *conf = sh->raid_conf;
-	int i, pd_idx = sh->pd_idx, qd_idx, d0_idx, disks = conf->raid_disks, count;
-	struct bio *chosen;
-	/**** FIX THIS: This could be very bad if disks is close to 256 ****/
-	void *ptrs[disks];
-
-	qd_idx = raid6_next_disk(pd_idx, disks);
-	d0_idx = raid6_next_disk(qd_idx, disks);
-
-	PRINTK("compute_parity, stripe %llu, method %d\n",
-		(unsigned long long)sh->sector, method);
-
-	switch(method) {
-	case READ_MODIFY_WRITE:
-		BUG();		/* READ_MODIFY_WRITE N/A for RAID-6 */
-	case RECONSTRUCT_WRITE:
-		for (i= disks; i-- ;)
-			if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) {
-				chosen = sh->dev[i].towrite;
-				sh->dev[i].towrite = NULL;
-
-				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-					wake_up(&conf->wait_for_overlap);
-
-				BUG_ON(sh->dev[i].written);
-				sh->dev[i].written = chosen;
-			}
-		break;
-	case CHECK_PARITY:
-		BUG();		/* Not implemented yet */
-	}
-
-	for (i = disks; i--;)
-		if (sh->dev[i].written) {
-			sector_t sector = sh->dev[i].sector;
-			struct bio *wbi = sh->dev[i].written;
-			while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) {
-				copy_data(1, wbi, sh->dev[i].page, sector);
-				wbi = r5_next_bio(wbi, sector);
-			}
-
-			set_bit(R5_LOCKED, &sh->dev[i].flags);
-			set_bit(R5_UPTODATE, &sh->dev[i].flags);
-		}
-
-//	switch(method) {
-//	case RECONSTRUCT_WRITE:
-//	case CHECK_PARITY:
-//	case UPDATE_PARITY:
-		/* Note that unlike RAID-5, the ordering of the disks matters greatly. */
-		/* FIX: Is this ordering of drives even remotely optimal? */
-		count = 0;
-		i = d0_idx;
-		do {
-			ptrs[count++] = page_address(sh->dev[i].page);
-			if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags))
-				printk("block %d/%d not uptodate on parity calc\n", i,count);
-			i = raid6_next_disk(i, disks);
-		} while ( i != d0_idx );
-//		break;
-//	}
-
-	raid6_call.gen_syndrome(disks, STRIPE_SIZE, ptrs);
-
-	switch(method) {
-	case RECONSTRUCT_WRITE:
-		set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-		set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
-		set_bit(R5_LOCKED,   &sh->dev[pd_idx].flags);
-		set_bit(R5_LOCKED,   &sh->dev[qd_idx].flags);
-		break;
-	case UPDATE_PARITY:
-		set_bit(R5_UPTODATE, &sh->dev[pd_idx].flags);
-		set_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
-		break;
-	}
-}
-
-/* Compute one missing block */
-static void compute_block_1(struct stripe_head *sh, int dd_idx, int nozero)
-{
-	raid6_conf_t *conf = sh->raid_conf;
-	int i, count, disks = conf->raid_disks;
-	void *ptr[MAX_XOR_BLOCKS], *p;
-	int pd_idx = sh->pd_idx;
-	int qd_idx = raid6_next_disk(pd_idx, disks);
-
-	PRINTK("compute_block_1, stripe %llu, idx %d\n",
-		(unsigned long long)sh->sector, dd_idx);
-
-	if ( dd_idx == qd_idx ) {
-		/* We're actually computing the Q drive */
-		compute_parity(sh, UPDATE_PARITY);
-	} else {
-		ptr[0] = page_address(sh->dev[dd_idx].page);
-		if (!nozero) memset(ptr[0], 0, STRIPE_SIZE);
-		count = 1;
-		for (i = disks ; i--; ) {
-			if (i == dd_idx || i == qd_idx)
-				continue;
-			p = page_address(sh->dev[i].page);
-			if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
-				ptr[count++] = p;
-			else
-				printk("compute_block() %d, stripe %llu, %d"
-				       " not present\n", dd_idx,
-				       (unsigned long long)sh->sector, i);
-
-			check_xor();
-		}
-		if (count != 1)
-			xor_block(count, STRIPE_SIZE, ptr);
-		if (!nozero) set_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
-		else clear_bit(R5_UPTODATE, &sh->dev[dd_idx].flags);
-	}
-}
-
-/* Compute two missing blocks */
-static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2)
-{
-	raid6_conf_t *conf = sh->raid_conf;
-	int i, count, disks = conf->raid_disks;
-	int pd_idx = sh->pd_idx;
-	int qd_idx = raid6_next_disk(pd_idx, disks);
-	int d0_idx = raid6_next_disk(qd_idx, disks);
-	int faila, failb;
-
-	/* faila and failb are disk numbers relative to d0_idx */
-	/* pd_idx become disks-2 and qd_idx become disks-1 */
-	faila = (dd_idx1 < d0_idx) ? dd_idx1+(disks-d0_idx) : dd_idx1-d0_idx;
-	failb = (dd_idx2 < d0_idx) ? dd_idx2+(disks-d0_idx) : dd_idx2-d0_idx;
-
-	BUG_ON(faila == failb);
-	if ( failb < faila ) { int tmp = faila; faila = failb; failb = tmp; }
-
-	PRINTK("compute_block_2, stripe %llu, idx %d,%d (%d,%d)\n",
-	       (unsigned long long)sh->sector, dd_idx1, dd_idx2, faila, failb);
-
-	if ( failb == disks-1 ) {
-		/* Q disk is one of the missing disks */
-		if ( faila == disks-2 ) {
-			/* Missing P+Q, just recompute */
-			compute_parity(sh, UPDATE_PARITY);
-			return;
-		} else {
-			/* We're missing D+Q; recompute D from P */
-			compute_block_1(sh, (dd_idx1 == qd_idx) ? dd_idx2 : dd_idx1, 0);
-			compute_parity(sh, UPDATE_PARITY); /* Is this necessary? */
-			return;
-		}
-	}
-
-	/* We're missing D+P or D+D; build pointer table */
-	{
-		/**** FIX THIS: This could be very bad if disks is close to 256 ****/
-		void *ptrs[disks];
-
-		count = 0;
-		i = d0_idx;
-		do {
-			ptrs[count++] = page_address(sh->dev[i].page);
-			i = raid6_next_disk(i, disks);
-			if (i != dd_idx1 && i != dd_idx2 &&
-			    !test_bit(R5_UPTODATE, &sh->dev[i].flags))
-				printk("compute_2 with missing block %d/%d\n", count, i);
-		} while ( i != d0_idx );
-
-		if ( failb == disks-2 ) {
-			/* We're missing D+P. */
-			raid6_datap_recov(disks, STRIPE_SIZE, faila, ptrs);
-		} else {
-			/* We're missing D+D. */
-			raid6_2data_recov(disks, STRIPE_SIZE, faila, failb, ptrs);
-		}
-
-		/* Both the above update both missing blocks */
-		set_bit(R5_UPTODATE, &sh->dev[dd_idx1].flags);
-		set_bit(R5_UPTODATE, &sh->dev[dd_idx2].flags);
-	}
-}
-
-
-/*
- * Each stripe/dev can have one or more bion attached.
- * toread/towrite point to the first in a chain.
- * The bi_next chain must be in order.
- */
-static int add_stripe_bio(struct stripe_head *sh, struct bio *bi, int dd_idx, int forwrite)
-{
-	struct bio **bip;
-	raid6_conf_t *conf = sh->raid_conf;
-	int firstwrite=0;
-
-	PRINTK("adding bh b#%llu to stripe s#%llu\n",
-		(unsigned long long)bi->bi_sector,
-		(unsigned long long)sh->sector);
-
-
-	spin_lock(&sh->lock);
-	spin_lock_irq(&conf->device_lock);
-	if (forwrite) {
-		bip = &sh->dev[dd_idx].towrite;
-		if (*bip == NULL && sh->dev[dd_idx].written == NULL)
-			firstwrite = 1;
-	} else
-		bip = &sh->dev[dd_idx].toread;
-	while (*bip && (*bip)->bi_sector < bi->bi_sector) {
-		if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
-			goto overlap;
-		bip = &(*bip)->bi_next;
-	}
-	if (*bip && (*bip)->bi_sector < bi->bi_sector + ((bi->bi_size)>>9))
-		goto overlap;
-
-	BUG_ON(*bip && bi->bi_next && (*bip) != bi->bi_next);
-	if (*bip)
-		bi->bi_next = *bip;
-	*bip = bi;
-	bi->bi_phys_segments ++;
-	spin_unlock_irq(&conf->device_lock);
-	spin_unlock(&sh->lock);
-
-	PRINTK("added bi b#%llu to stripe s#%llu, disk %d.\n",
-		(unsigned long long)bi->bi_sector,
-		(unsigned long long)sh->sector, dd_idx);
-
-	if (conf->mddev->bitmap && firstwrite) {
-		sh->bm_seq = conf->seq_write;
-		bitmap_startwrite(conf->mddev->bitmap, sh->sector,
-				  STRIPE_SECTORS, 0);
-		set_bit(STRIPE_BIT_DELAY, &sh->state);
-	}
-
-	if (forwrite) {
-		/* check if page is covered */
-		sector_t sector = sh->dev[dd_idx].sector;
-		for (bi=sh->dev[dd_idx].towrite;
-		     sector < sh->dev[dd_idx].sector + STRIPE_SECTORS &&
-			     bi && bi->bi_sector <= sector;
-		     bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) {
-			if (bi->bi_sector + (bi->bi_size>>9) >= sector)
-				sector = bi->bi_sector + (bi->bi_size>>9);
-		}
-		if (sector >= sh->dev[dd_idx].sector + STRIPE_SECTORS)
-			set_bit(R5_OVERWRITE, &sh->dev[dd_idx].flags);
-	}
-	return 1;
-
- overlap:
-	set_bit(R5_Overlap, &sh->dev[dd_idx].flags);
-	spin_unlock_irq(&conf->device_lock);
-	spin_unlock(&sh->lock);
-	return 0;
-}
-
-
-static int page_is_zero(struct page *p)
-{
-	char *a = page_address(p);
-	return ((*(u32*)a) == 0 &&
-		memcmp(a, a+4, STRIPE_SIZE-4)==0);
-}
-/*
- * handle_stripe - do things to a stripe.
- *
- * We lock the stripe and then examine the state of various bits
- * to see what needs to be done.
- * Possible results:
- *    return some read request which now have data
- *    return some write requests which are safely on disc
- *    schedule a read on some buffers
- *    schedule a write of some buffers
- *    return confirmation of parity correctness
- *
- * Parity calculations are done inside the stripe lock
- * buffers are taken off read_list or write_list, and bh_cache buffers
- * get BH_Lock set before the stripe lock is released.
- *
- */
-
-static void handle_stripe(struct stripe_head *sh, struct page *tmp_page)
-{
-	raid6_conf_t *conf = sh->raid_conf;
-	int disks = conf->raid_disks;
-	struct bio *return_bi= NULL;
-	struct bio *bi;
-	int i;
-	int syncing;
-	int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
-	int non_overwrite = 0;
-	int failed_num[2] = {0, 0};
-	struct r5dev *dev, *pdev, *qdev;
-	int pd_idx = sh->pd_idx;
-	int qd_idx = raid6_next_disk(pd_idx, disks);
-	int p_failed, q_failed;
-
-	PRINTK("handling stripe %llu, state=%#lx cnt=%d, pd_idx=%d, qd_idx=%d\n",
-	       (unsigned long long)sh->sector, sh->state, atomic_read(&sh->count),
-	       pd_idx, qd_idx);
-
-	spin_lock(&sh->lock);
-	clear_bit(STRIPE_HANDLE, &sh->state);
-	clear_bit(STRIPE_DELAYED, &sh->state);
-
-	syncing = test_bit(STRIPE_SYNCING, &sh->state);
-	/* Now to look around and see what can be done */
-
-	rcu_read_lock();
-	for (i=disks; i--; ) {
-		mdk_rdev_t *rdev;
-		dev = &sh->dev[i];
-		clear_bit(R5_Insync, &dev->flags);
-
-		PRINTK("check %d: state 0x%lx read %p write %p written %p\n",
-			i, dev->flags, dev->toread, dev->towrite, dev->written);
-		/* maybe we can reply to a read */
-		if (test_bit(R5_UPTODATE, &dev->flags) && dev->toread) {
-			struct bio *rbi, *rbi2;
-			PRINTK("Return read for disc %d\n", i);
-			spin_lock_irq(&conf->device_lock);
-			rbi = dev->toread;
-			dev->toread = NULL;
-			if (test_and_clear_bit(R5_Overlap, &dev->flags))
-				wake_up(&conf->wait_for_overlap);
-			spin_unlock_irq(&conf->device_lock);
-			while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-				copy_data(0, rbi, dev->page, dev->sector);
-				rbi2 = r5_next_bio(rbi, dev->sector);
-				spin_lock_irq(&conf->device_lock);
-				if (--rbi->bi_phys_segments == 0) {
-					rbi->bi_next = return_bi;
-					return_bi = rbi;
-				}
-				spin_unlock_irq(&conf->device_lock);
-				rbi = rbi2;
-			}
-		}
-
-		/* now count some things */
-		if (test_bit(R5_LOCKED, &dev->flags)) locked++;
-		if (test_bit(R5_UPTODATE, &dev->flags)) uptodate++;
-
-
-		if (dev->toread) to_read++;
-		if (dev->towrite) {
-			to_write++;
-			if (!test_bit(R5_OVERWRITE, &dev->flags))
-				non_overwrite++;
-		}
-		if (dev->written) written++;
-		rdev = rcu_dereference(conf->disks[i].rdev);
-		if (!rdev || !test_bit(In_sync, &rdev->flags)) {
-			/* The ReadError flag will just be confusing now */
-			clear_bit(R5_ReadError, &dev->flags);
-			clear_bit(R5_ReWrite, &dev->flags);
-		}
-		if (!rdev || !test_bit(In_sync, &rdev->flags)
-		    || test_bit(R5_ReadError, &dev->flags)) {
-			if ( failed < 2 )
-				failed_num[failed] = i;
-			failed++;
-		} else
-			set_bit(R5_Insync, &dev->flags);
-	}
-	rcu_read_unlock();
-	PRINTK("locked=%d uptodate=%d to_read=%d"
-	       " to_write=%d failed=%d failed_num=%d,%d\n",
-	       locked, uptodate, to_read, to_write, failed,
-	       failed_num[0], failed_num[1]);
-	/* check if the array has lost >2 devices and, if so, some requests might
-	 * need to be failed
-	 */
-	if (failed > 2 && to_read+to_write+written) {
-		for (i=disks; i--; ) {
-			int bitmap_end = 0;
-
-			if (test_bit(R5_ReadError, &sh->dev[i].flags)) {
-				mdk_rdev_t *rdev;
-				rcu_read_lock();
-				rdev = rcu_dereference(conf->disks[i].rdev);
-				if (rdev && test_bit(In_sync, &rdev->flags))
-					/* multiple read failures in one stripe */
-					md_error(conf->mddev, rdev);
-				rcu_read_unlock();
-			}
-
-			spin_lock_irq(&conf->device_lock);
-			/* fail all writes first */
-			bi = sh->dev[i].towrite;
-			sh->dev[i].towrite = NULL;
-			if (bi) { to_write--; bitmap_end = 1; }
-
-			if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-				wake_up(&conf->wait_for_overlap);
-
-			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-				struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-				clear_bit(BIO_UPTODATE, &bi->bi_flags);
-				if (--bi->bi_phys_segments == 0) {
-					md_write_end(conf->mddev);
-					bi->bi_next = return_bi;
-					return_bi = bi;
-				}
-				bi = nextbi;
-			}
-			/* and fail all 'written' */
-			bi = sh->dev[i].written;
-			sh->dev[i].written = NULL;
-			if (bi) bitmap_end = 1;
-			while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
-				struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
-				clear_bit(BIO_UPTODATE, &bi->bi_flags);
-				if (--bi->bi_phys_segments == 0) {
-					md_write_end(conf->mddev);
-					bi->bi_next = return_bi;
-					return_bi = bi;
-				}
-				bi = bi2;
-			}
-
-			/* fail any reads if this device is non-operational */
-			if (!test_bit(R5_Insync, &sh->dev[i].flags) ||
-			    test_bit(R5_ReadError, &sh->dev[i].flags)) {
-				bi = sh->dev[i].toread;
-				sh->dev[i].toread = NULL;
-				if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
-					wake_up(&conf->wait_for_overlap);
-				if (bi) to_read--;
-				while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){
-					struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector);
-					clear_bit(BIO_UPTODATE, &bi->bi_flags);
-					if (--bi->bi_phys_segments == 0) {
-						bi->bi_next = return_bi;
-						return_bi = bi;
-					}
-					bi = nextbi;
-				}
-			}
-			spin_unlock_irq(&conf->device_lock);
-			if (bitmap_end)
-				bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-						STRIPE_SECTORS, 0, 0);
-		}
-	}
-	if (failed > 2 && syncing) {
-		md_done_sync(conf->mddev, STRIPE_SECTORS,0);
-		clear_bit(STRIPE_SYNCING, &sh->state);
-		syncing = 0;
-	}
-
-	/*
-	 * might be able to return some write requests if the parity blocks
-	 * are safe, or on a failed drive
-	 */
-	pdev = &sh->dev[pd_idx];
-	p_failed = (failed >= 1 && failed_num[0] == pd_idx)
-		|| (failed >= 2 && failed_num[1] == pd_idx);
-	qdev = &sh->dev[qd_idx];
-	q_failed = (failed >= 1 && failed_num[0] == qd_idx)
-		|| (failed >= 2 && failed_num[1] == qd_idx);
-
-	if ( written &&
-	     ( p_failed || ((test_bit(R5_Insync, &pdev->flags)
-			     && !test_bit(R5_LOCKED, &pdev->flags)
-			     && test_bit(R5_UPTODATE, &pdev->flags))) ) &&
-	     ( q_failed || ((test_bit(R5_Insync, &qdev->flags)
-			     && !test_bit(R5_LOCKED, &qdev->flags)
-			     && test_bit(R5_UPTODATE, &qdev->flags))) ) ) {
-		/* any written block on an uptodate or failed drive can be
-		 * returned.  Note that if we 'wrote' to a failed drive,
-		 * it will be UPTODATE, but never LOCKED, so we don't need
-		 * to test 'failed' directly.
-		 */
-		for (i=disks; i--; )
-			if (sh->dev[i].written) {
-				dev = &sh->dev[i];
-				if (!test_bit(R5_LOCKED, &dev->flags) &&
-				    test_bit(R5_UPTODATE, &dev->flags) ) {
-					/* We can return any write requests */
-					int bitmap_end = 0;
-					struct bio *wbi, *wbi2;
-					PRINTK("Return write for stripe %llu disc %d\n",
-					       (unsigned long long)sh->sector, i);
-					spin_lock_irq(&conf->device_lock);
-					wbi = dev->written;
-					dev->written = NULL;
-					while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) {
-						wbi2 = r5_next_bio(wbi, dev->sector);
-						if (--wbi->bi_phys_segments == 0) {
-							md_write_end(conf->mddev);
-							wbi->bi_next = return_bi;
-							return_bi = wbi;
-						}
-						wbi = wbi2;
-					}
-					if (dev->towrite == NULL)
-						bitmap_end = 1;
-					spin_unlock_irq(&conf->device_lock);
-					if (bitmap_end)
-						bitmap_endwrite(conf->mddev->bitmap, sh->sector,
-								STRIPE_SECTORS,
-								!test_bit(STRIPE_DEGRADED, &sh->state), 0);
-				}
-			}
-	}
-
-	/* Now we might consider reading some blocks, either to check/generate
-	 * parity, or to satisfy requests
-	 * or to load a block that is being partially written.
-	 */
-	if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) {
-		for (i=disks; i--;) {
-			dev = &sh->dev[i];
-			if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-			    (dev->toread ||
-			     (dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
-			     syncing ||
-			     (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
-			     (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
-				    )
-				) {
-				/* we would like to get this block, possibly
-				 * by computing it, but we might not be able to
-				 */
-				if (uptodate == disks-1) {
-					PRINTK("Computing stripe %llu block %d\n",
-					       (unsigned long long)sh->sector, i);
-					compute_block_1(sh, i, 0);
-					uptodate++;
-				} else if ( uptodate == disks-2 && failed >= 2 ) {
-					/* Computing 2-failure is *very* expensive; only do it if failed >= 2 */
-					int other;
-					for (other=disks; other--;) {
-						if ( other == i )
-							continue;
-						if ( !test_bit(R5_UPTODATE, &sh->dev[other].flags) )
-							break;
-					}
-					BUG_ON(other < 0);
-					PRINTK("Computing stripe %llu blocks %d,%d\n",
-					       (unsigned long long)sh->sector, i, other);
-					compute_block_2(sh, i, other);
-					uptodate += 2;
-				} else if (test_bit(R5_Insync, &dev->flags)) {
-					set_bit(R5_LOCKED, &dev->flags);
-					set_bit(R5_Wantread, &dev->flags);
-#if 0
-					/* if I am just reading this block and we don't have
-					   a failed drive, or any pending writes then sidestep the cache */
-					if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&
-					    ! syncing && !failed && !to_write) {
-						sh->bh_cache[i]->b_page =  sh->bh_read[i]->b_page;
-						sh->bh_cache[i]->b_data =  sh->bh_read[i]->b_data;
-					}
-#endif
-					locked++;
-					PRINTK("Reading block %d (sync=%d)\n",
-						i, syncing);
-				}
-			}
-		}
-		set_bit(STRIPE_HANDLE, &sh->state);
-	}
-
-	/* now to consider writing and what else, if anything should be read */
-	if (to_write) {
-		int rcw=0, must_compute=0;
-		for (i=disks ; i--;) {
-			dev = &sh->dev[i];
-			/* Would I have to read this buffer for reconstruct_write */
-			if (!test_bit(R5_OVERWRITE, &dev->flags)
-			    && i != pd_idx && i != qd_idx
-			    && (!test_bit(R5_LOCKED, &dev->flags)
-#if 0
-				|| sh->bh_page[i] != bh->b_page
-#endif
-				    ) &&
-			    !test_bit(R5_UPTODATE, &dev->flags)) {
-				if (test_bit(R5_Insync, &dev->flags)) rcw++;
-				else {
-					PRINTK("raid6: must_compute: disk %d flags=%#lx\n", i, dev->flags);
-					must_compute++;
-				}
-			}
-		}
-		PRINTK("for sector %llu, rcw=%d, must_compute=%d\n",
-		       (unsigned long long)sh->sector, rcw, must_compute);
-		set_bit(STRIPE_HANDLE, &sh->state);
-
-		if (rcw > 0)
-			/* want reconstruct write, but need to get some data */
-			for (i=disks; i--;) {
-				dev = &sh->dev[i];
-				if (!test_bit(R5_OVERWRITE, &dev->flags)
-				    && !(failed == 0 && (i == pd_idx || i == qd_idx))
-				    && !test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
-				    test_bit(R5_Insync, &dev->flags)) {
-					if (test_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-					{
-						PRINTK("Read_old stripe %llu block %d for Reconstruct\n",
-						       (unsigned long long)sh->sector, i);
-						set_bit(R5_LOCKED, &dev->flags);
-						set_bit(R5_Wantread, &dev->flags);
-						locked++;
-					} else {
-						PRINTK("Request delayed stripe %llu block %d for Reconstruct\n",
-						       (unsigned long long)sh->sector, i);
-						set_bit(STRIPE_DELAYED, &sh->state);
-						set_bit(STRIPE_HANDLE, &sh->state);
-					}
-				}
-			}
-		/* now if nothing is locked, and if we have enough data, we can start a write request */
-		if (locked == 0 && rcw == 0 &&
-		    !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
-			if ( must_compute > 0 ) {
-				/* We have failed blocks and need to compute them */
-				switch ( failed ) {
-				case 0:	BUG();
-				case 1: compute_block_1(sh, failed_num[0], 0); break;
-				case 2: compute_block_2(sh, failed_num[0], failed_num[1]); break;
-				default: BUG();	/* This request should have been failed? */
-				}
-			}
-
-			PRINTK("Computing parity for stripe %llu\n", (unsigned long long)sh->sector);
-			compute_parity(sh, RECONSTRUCT_WRITE);
-			/* now every locked buffer is ready to be written */
-			for (i=disks; i--;)
-				if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
-					PRINTK("Writing stripe %llu block %d\n",
-					       (unsigned long long)sh->sector, i);
-					locked++;
-					set_bit(R5_Wantwrite, &sh->dev[i].flags);
-				}
-			/* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
-			set_bit(STRIPE_INSYNC, &sh->state);
-
-			if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
-				atomic_dec(&conf->preread_active_stripes);
-				if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD)
-					md_wakeup_thread(conf->mddev->thread);
-			}
-		}
-	}
-
-	/* maybe we need to check and possibly fix the parity for this stripe
-	 * Any reads will already have been scheduled, so we just see if enough data
-	 * is available
-	 */
-	if (syncing && locked == 0 && !test_bit(STRIPE_INSYNC, &sh->state)) {
-		int update_p = 0, update_q = 0;
-		struct r5dev *dev;
-
-		set_bit(STRIPE_HANDLE, &sh->state);
-
-		BUG_ON(failed>2);
-		BUG_ON(uptodate < disks);
-		/* Want to check and possibly repair P and Q.
-		 * However there could be one 'failed' device, in which
-		 * case we can only check one of them, possibly using the
-		 * other to generate missing data
-		 */
-
-		/* If !tmp_page, we cannot do the calculations,
-		 * but as we have set STRIPE_HANDLE, we will soon be called
-		 * by stripe_handle with a tmp_page - just wait until then.
-		 */
-		if (tmp_page) {
-			if (failed == q_failed) {
-				/* The only possible failed device holds 'Q', so it makes
-				 * sense to check P (If anything else were failed, we would
-				 * have used P to recreate it).
-				 */
-				compute_block_1(sh, pd_idx, 1);
-				if (!page_is_zero(sh->dev[pd_idx].page)) {
-					compute_block_1(sh,pd_idx,0);
-					update_p = 1;
-				}
-			}
-			if (!q_failed && failed < 2) {
-				/* q is not failed, and we didn't use it to generate
-				 * anything, so it makes sense to check it
-				 */
-				memcpy(page_address(tmp_page),
-				       page_address(sh->dev[qd_idx].page),
-				       STRIPE_SIZE);
-				compute_parity(sh, UPDATE_PARITY);
-				if (memcmp(page_address(tmp_page),
-					   page_address(sh->dev[qd_idx].page),
-					   STRIPE_SIZE)!= 0) {
-					clear_bit(STRIPE_INSYNC, &sh->state);
-					update_q = 1;
-				}
-			}
-			if (update_p || update_q) {
-				conf->mddev->resync_mismatches += STRIPE_SECTORS;
-				if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery))
-					/* don't try to repair!! */
-					update_p = update_q = 0;
-			}
-
-			/* now write out any block on a failed drive,
-			 * or P or Q if they need it
-			 */
-
-			if (failed == 2) {
-				dev = &sh->dev[failed_num[1]];
-				locked++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-			if (failed >= 1) {
-				dev = &sh->dev[failed_num[0]];
-				locked++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-
-			if (update_p) {
-				dev = &sh->dev[pd_idx];
-				locked ++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-			if (update_q) {
-				dev = &sh->dev[qd_idx];
-				locked++;
-				set_bit(R5_LOCKED, &dev->flags);
-				set_bit(R5_Wantwrite, &dev->flags);
-			}
-			clear_bit(STRIPE_DEGRADED, &sh->state);
-
-			set_bit(STRIPE_INSYNC, &sh->state);
-		}
-	}
-
-	if (syncing && locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
-		md_done_sync(conf->mddev, STRIPE_SECTORS,1);
-		clear_bit(STRIPE_SYNCING, &sh->state);
-	}
-
-	/* If the failed drives are just a ReadError, then we might need
-	 * to progress the repair/check process
-	 */
-	if (failed <= 2 && ! conf->mddev->ro)
-		for (i=0; i<failed;i++) {
-			dev = &sh->dev[failed_num[i]];
-			if (test_bit(R5_ReadError, &dev->flags)
-			    && !test_bit(R5_LOCKED, &dev->flags)
-			    && test_bit(R5_UPTODATE, &dev->flags)
-				) {
-				if (!test_bit(R5_ReWrite, &dev->flags)) {
-					set_bit(R5_Wantwrite, &dev->flags);
-					set_bit(R5_ReWrite, &dev->flags);
-					set_bit(R5_LOCKED, &dev->flags);
-				} else {
-					/* let's read it back */
-					set_bit(R5_Wantread, &dev->flags);
-					set_bit(R5_LOCKED, &dev->flags);
-				}
-			}
-		}
-	spin_unlock(&sh->lock);
-
-	while ((bi=return_bi)) {
-		int bytes = bi->bi_size;
-
-		return_bi = bi->bi_next;
-		bi->bi_next = NULL;
-		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes, 0);
-	}
-	for (i=disks; i-- ;) {
-		int rw;
-		struct bio *bi;
-		mdk_rdev_t *rdev;
-		if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags))
-			rw = 1;
-		else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-			rw = 0;
-		else
-			continue;
-
-		bi = &sh->dev[i].req;
-
-		bi->bi_rw = rw;
-		if (rw)
-			bi->bi_end_io = raid6_end_write_request;
-		else
-			bi->bi_end_io = raid6_end_read_request;
-
-		rcu_read_lock();
-		rdev = rcu_dereference(conf->disks[i].rdev);
-		if (rdev && test_bit(Faulty, &rdev->flags))
-			rdev = NULL;
-		if (rdev)
-			atomic_inc(&rdev->nr_pending);
-		rcu_read_unlock();
-
-		if (rdev) {
-			if (syncing)
-				md_sync_acct(rdev->bdev, STRIPE_SECTORS);
-
-			bi->bi_bdev = rdev->bdev;
-			PRINTK("for %llu schedule op %ld on disc %d\n",
-				(unsigned long long)sh->sector, bi->bi_rw, i);
-			atomic_inc(&sh->count);
-			bi->bi_sector = sh->sector + rdev->data_offset;
-			bi->bi_flags = 1 << BIO_UPTODATE;
-			bi->bi_vcnt = 1;
-			bi->bi_max_vecs = 1;
-			bi->bi_idx = 0;
-			bi->bi_io_vec = &sh->dev[i].vec;
-			bi->bi_io_vec[0].bv_len = STRIPE_SIZE;
-			bi->bi_io_vec[0].bv_offset = 0;
-			bi->bi_size = STRIPE_SIZE;
-			bi->bi_next = NULL;
-			if (rw == WRITE &&
-			    test_bit(R5_ReWrite, &sh->dev[i].flags))
-				atomic_add(STRIPE_SECTORS, &rdev->corrected_errors);
-			generic_make_request(bi);
-		} else {
-			if (rw == 1)
-				set_bit(STRIPE_DEGRADED, &sh->state);
-			PRINTK("skip op %ld on disc %d for sector %llu\n",
-				bi->bi_rw, i, (unsigned long long)sh->sector);
-			clear_bit(R5_LOCKED, &sh->dev[i].flags);
-			set_bit(STRIPE_HANDLE, &sh->state);
-		}
-	}
-}
-
-static void raid6_activate_delayed(raid6_conf_t *conf)
-{
-	if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) {
-		while (!list_empty(&conf->delayed_list)) {
-			struct list_head *l = conf->delayed_list.next;
-			struct stripe_head *sh;
-			sh = list_entry(l, struct stripe_head, lru);
-			list_del_init(l);
-			clear_bit(STRIPE_DELAYED, &sh->state);
-			if (!test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
-				atomic_inc(&conf->preread_active_stripes);
-			list_add_tail(&sh->lru, &conf->handle_list);
-		}
-	}
-}
-
-static void activate_bit_delay(raid6_conf_t *conf)
-{
-	/* device_lock is held */
-	struct list_head head;
-	list_add(&head, &conf->bitmap_list);
-	list_del_init(&conf->bitmap_list);
-	while (!list_empty(&head)) {
-		struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
-		list_del_init(&sh->lru);
-		atomic_inc(&sh->count);
-		__release_stripe(conf, sh);
-	}
-}
-
-static void unplug_slaves(mddev_t *mddev)
-{
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	int i;
-
-	rcu_read_lock();
-	for (i=0; i<mddev->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
-		if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
-			request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
-
-			atomic_inc(&rdev->nr_pending);
-			rcu_read_unlock();
-
-			if (r_queue->unplug_fn)
-				r_queue->unplug_fn(r_queue);
-
-			rdev_dec_pending(rdev, mddev);
-			rcu_read_lock();
-		}
-	}
-	rcu_read_unlock();
-}
-
-static void raid6_unplug_device(request_queue_t *q)
-{
-	mddev_t *mddev = q->queuedata;
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	unsigned long flags;
-
-	spin_lock_irqsave(&conf->device_lock, flags);
-
-	if (blk_remove_plug(q)) {
-		conf->seq_flush++;
-		raid6_activate_delayed(conf);
-	}
-	md_wakeup_thread(mddev->thread);
-
-	spin_unlock_irqrestore(&conf->device_lock, flags);
-
-	unplug_slaves(mddev);
-}
-
-static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk,
-			     sector_t *error_sector)
-{
-	mddev_t *mddev = q->queuedata;
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	int i, ret = 0;
-
-	rcu_read_lock();
-	for (i=0; i<mddev->raid_disks && ret == 0; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
-		if (rdev && !test_bit(Faulty, &rdev->flags)) {
-			struct block_device *bdev = rdev->bdev;
-			request_queue_t *r_queue = bdev_get_queue(bdev);
-
-			if (!r_queue->issue_flush_fn)
-				ret = -EOPNOTSUPP;
-			else {
-				atomic_inc(&rdev->nr_pending);
-				rcu_read_unlock();
-				ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
-							      error_sector);
-				rdev_dec_pending(rdev, mddev);
-				rcu_read_lock();
-			}
-		}
-	}
-	rcu_read_unlock();
-	return ret;
-}
-
-static inline void raid6_plug_device(raid6_conf_t *conf)
-{
-	spin_lock_irq(&conf->device_lock);
-	blk_plug_device(conf->mddev->queue);
-	spin_unlock_irq(&conf->device_lock);
-}
-
-static int make_request (request_queue_t *q, struct bio * bi)
-{
-	mddev_t *mddev = q->queuedata;
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	const unsigned int raid_disks = conf->raid_disks;
-	const unsigned int data_disks = raid_disks - 2;
-	unsigned int dd_idx, pd_idx;
-	sector_t new_sector;
-	sector_t logical_sector, last_sector;
-	struct stripe_head *sh;
-	const int rw = bio_data_dir(bi);
-
-	if (unlikely(bio_barrier(bi))) {
-		bio_endio(bi, bi->bi_size, -EOPNOTSUPP);
-		return 0;
-	}
-
-	md_write_start(mddev, bi);
-
-	disk_stat_inc(mddev->gendisk, ios[rw]);
-	disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bi));
-
-	logical_sector = bi->bi_sector & ~((sector_t)STRIPE_SECTORS-1);
-	last_sector = bi->bi_sector + (bi->bi_size>>9);
-
-	bi->bi_next = NULL;
-	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
-
-	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
-		DEFINE_WAIT(w);
-
-		new_sector = raid6_compute_sector(logical_sector,
-						  raid_disks, data_disks, &dd_idx, &pd_idx, conf);
-
-		PRINTK("raid6: make_request, sector %llu logical %llu\n",
-		       (unsigned long long)new_sector,
-		       (unsigned long long)logical_sector);
-
-	retry:
-		prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
-		sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
-		if (sh) {
-			if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
-				/* Add failed due to overlap.  Flush everything
-				 * and wait a while
-				 */
-				raid6_unplug_device(mddev->queue);
-				release_stripe(sh);
-				schedule();
-				goto retry;
-			}
-			finish_wait(&conf->wait_for_overlap, &w);
-			raid6_plug_device(conf);
-			handle_stripe(sh, NULL);
-			release_stripe(sh);
-		} else {
-			/* cannot get stripe for read-ahead, just give-up */
-			clear_bit(BIO_UPTODATE, &bi->bi_flags);
-			finish_wait(&conf->wait_for_overlap, &w);
-			break;
-		}
-
-	}
-	spin_lock_irq(&conf->device_lock);
-	if (--bi->bi_phys_segments == 0) {
-		int bytes = bi->bi_size;
-
-		if (rw == WRITE )
-			md_write_end(mddev);
-		bi->bi_size = 0;
-		bi->bi_end_io(bi, bytes, 0);
-	}
-	spin_unlock_irq(&conf->device_lock);
-	return 0;
-}
-
-/* FIXME go_faster isn't used */
-static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
-{
-	raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
-	struct stripe_head *sh;
-	int sectors_per_chunk = conf->chunk_size >> 9;
-	sector_t x;
-	unsigned long stripe;
-	int chunk_offset;
-	int dd_idx, pd_idx;
-	sector_t first_sector;
-	int raid_disks = conf->raid_disks;
-	int data_disks = raid_disks - 2;
-	sector_t max_sector = mddev->size << 1;
-	int sync_blocks;
-	int still_degraded = 0;
-	int i;
-
-	if (sector_nr >= max_sector) {
-		/* just being told to finish up .. nothing much to do */
-		unplug_slaves(mddev);
-
-		if (mddev->curr_resync < max_sector) /* aborted */
-			bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
-					&sync_blocks, 1);
-		else /* completed sync */
-			conf->fullsync = 0;
-		bitmap_close_sync(mddev->bitmap);
-
-		return 0;
-	}
-	/* if there are 2 or more failed drives and we are trying
-	 * to resync, then assert that we are finished, because there is
-	 * nothing we can do.
-	 */
-	if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
-		sector_t rv = (mddev->size << 1) - sector_nr;
-		*skipped = 1;
-		return rv;
-	}
-	if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
-	    !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
-	    !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
-		/* we can skip this block, and probably more */
-		sync_blocks /= STRIPE_SECTORS;
-		*skipped = 1;
-		return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
-	}
-
-	x = sector_nr;
-	chunk_offset = sector_div(x, sectors_per_chunk);
-	stripe = x;
-	BUG_ON(x != stripe);
-
-	first_sector = raid6_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk
-		+ chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf);
-	sh = get_active_stripe(conf, sector_nr, pd_idx, 1);
-	if (sh == NULL) {
-		sh = get_active_stripe(conf, sector_nr, pd_idx, 0);
-		/* make sure we don't swamp the stripe cache if someone else
-		 * is trying to get access
-		 */
-		schedule_timeout_uninterruptible(1);
-	}
-	/* Need to check if array will still be degraded after recovery/resync
-	 * We don't need to check the 'failed' flag as when that gets set,
-	 * recovery aborts.
-	 */
-	for (i=0; i<mddev->raid_disks; i++)
-		if (conf->disks[i].rdev == NULL)
-			still_degraded = 1;
-
-	bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, still_degraded);
-
-	spin_lock(&sh->lock);
-	set_bit(STRIPE_SYNCING, &sh->state);
-	clear_bit(STRIPE_INSYNC, &sh->state);
-	spin_unlock(&sh->lock);
-
-	handle_stripe(sh, NULL);
-	release_stripe(sh);
-
-	return STRIPE_SECTORS;
-}
-
-/*
- * This is our raid6 kernel thread.
- *
- * We scan the hash table for stripes which can be handled now.
- * During the scan, completed stripes are saved for us by the interrupt
- * handler, so that they will not have to wait for our next wakeup.
- */
-static void raid6d (mddev_t *mddev)
-{
-	struct stripe_head *sh;
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	int handled;
-
-	PRINTK("+++ raid6d active\n");
-
-	md_check_recovery(mddev);
-
-	handled = 0;
-	spin_lock_irq(&conf->device_lock);
-	while (1) {
-		struct list_head *first;
-
-		if (conf->seq_flush - conf->seq_write > 0) {
-			int seq = conf->seq_flush;
-			spin_unlock_irq(&conf->device_lock);
-			bitmap_unplug(mddev->bitmap);
-			spin_lock_irq(&conf->device_lock);
-			conf->seq_write = seq;
-			activate_bit_delay(conf);
-		}
-
-		if (list_empty(&conf->handle_list) &&
-		    atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
-		    !blk_queue_plugged(mddev->queue) &&
-		    !list_empty(&conf->delayed_list))
-			raid6_activate_delayed(conf);
-
-		if (list_empty(&conf->handle_list))
-			break;
-
-		first = conf->handle_list.next;
-		sh = list_entry(first, struct stripe_head, lru);
-
-		list_del_init(first);
-		atomic_inc(&sh->count);
-		BUG_ON(atomic_read(&sh->count)!= 1);
-		spin_unlock_irq(&conf->device_lock);
-
-		handled++;
-		handle_stripe(sh, conf->spare_page);
-		release_stripe(sh);
-
-		spin_lock_irq(&conf->device_lock);
-	}
-	PRINTK("%d stripes handled\n", handled);
-
-	spin_unlock_irq(&conf->device_lock);
-
-	unplug_slaves(mddev);
-
-	PRINTK("--- raid6d inactive\n");
-}
-
-static ssize_t
-raid6_show_stripe_cache_size(mddev_t *mddev, char *page)
-{
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	if (conf)
-		return sprintf(page, "%d\n", conf->max_nr_stripes);
-	else
-		return 0;
-}
-
-static ssize_t
-raid6_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len)
-{
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	char *end;
-	int new;
-	if (len >= PAGE_SIZE)
-		return -EINVAL;
-	if (!conf)
-		return -ENODEV;
-
-	new = simple_strtoul(page, &end, 10);
-	if (!*page || (*end && *end != '\n') )
-		return -EINVAL;
-	if (new <= 16 || new > 32768)
-		return -EINVAL;
-	while (new < conf->max_nr_stripes) {
-		if (drop_one_stripe(conf))
-			conf->max_nr_stripes--;
-		else
-			break;
-	}
-	while (new > conf->max_nr_stripes) {
-		if (grow_one_stripe(conf))
-			conf->max_nr_stripes++;
-		else break;
-	}
-	return len;
-}
-
-static struct md_sysfs_entry
-raid6_stripecache_size = __ATTR(stripe_cache_size, S_IRUGO | S_IWUSR,
-				raid6_show_stripe_cache_size,
-				raid6_store_stripe_cache_size);
-
-static ssize_t
-stripe_cache_active_show(mddev_t *mddev, char *page)
-{
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-	if (conf)
-		return sprintf(page, "%d\n", atomic_read(&conf->active_stripes));
-	else
-		return 0;
-}
-
-static struct md_sysfs_entry
-raid6_stripecache_active = __ATTR_RO(stripe_cache_active);
-
-static struct attribute *raid6_attrs[] =  {
-	&raid6_stripecache_size.attr,
-	&raid6_stripecache_active.attr,
-	NULL,
-};
-static struct attribute_group raid6_attrs_group = {
-	.name = NULL,
-	.attrs = raid6_attrs,
-};
-
-static int run(mddev_t *mddev)
-{
-	raid6_conf_t *conf;
-	int raid_disk, memory;
-	mdk_rdev_t *rdev;
-	struct disk_info *disk;
-	struct list_head *tmp;
-
-	if (mddev->level != 6) {
-		PRINTK("raid6: %s: raid level not set to 6 (%d)\n", mdname(mddev), mddev->level);
-		return -EIO;
-	}
-
-	mddev->private = kzalloc(sizeof (raid6_conf_t), GFP_KERNEL);
-	if ((conf = mddev->private) == NULL)
-		goto abort;
-	conf->disks = kzalloc(mddev->raid_disks * sizeof(struct disk_info),
-				 GFP_KERNEL);
-	if (!conf->disks)
-		goto abort;
-
-	conf->mddev = mddev;
-
-	if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL)
-		goto abort;
-
-	conf->spare_page = alloc_page(GFP_KERNEL);
-	if (!conf->spare_page)
-		goto abort;
-
-	spin_lock_init(&conf->device_lock);
-	init_waitqueue_head(&conf->wait_for_stripe);
-	init_waitqueue_head(&conf->wait_for_overlap);
-	INIT_LIST_HEAD(&conf->handle_list);
-	INIT_LIST_HEAD(&conf->delayed_list);
-	INIT_LIST_HEAD(&conf->bitmap_list);
-	INIT_LIST_HEAD(&conf->inactive_list);
-	atomic_set(&conf->active_stripes, 0);
-	atomic_set(&conf->preread_active_stripes, 0);
-
-	PRINTK("raid6: run(%s) called.\n", mdname(mddev));
-
-	ITERATE_RDEV(mddev,rdev,tmp) {
-		raid_disk = rdev->raid_disk;
-		if (raid_disk >= mddev->raid_disks
-		    || raid_disk < 0)
-			continue;
-		disk = conf->disks + raid_disk;
-
-		disk->rdev = rdev;
-
-		if (test_bit(In_sync, &rdev->flags)) {
-			char b[BDEVNAME_SIZE];
-			printk(KERN_INFO "raid6: device %s operational as raid"
-			       " disk %d\n", bdevname(rdev->bdev,b),
-			       raid_disk);
-			conf->working_disks++;
-		}
-	}
-
-	conf->raid_disks = mddev->raid_disks;
-
-	/*
-	 * 0 for a fully functional array, 1 or 2 for a degraded array.
-	 */
-	mddev->degraded = conf->failed_disks = conf->raid_disks - conf->working_disks;
-	conf->mddev = mddev;
-	conf->chunk_size = mddev->chunk_size;
-	conf->level = mddev->level;
-	conf->algorithm = mddev->layout;
-	conf->max_nr_stripes = NR_STRIPES;
-
-	/* device size must be a multiple of chunk size */
-	mddev->size &= ~(mddev->chunk_size/1024 -1);
-	mddev->resync_max_sectors = mddev->size << 1;
-
-	if (conf->raid_disks < 4) {
-		printk(KERN_ERR "raid6: not enough configured devices for %s (%d, minimum 4)\n",
-		       mdname(mddev), conf->raid_disks);
-		goto abort;
-	}
-	if (!conf->chunk_size || conf->chunk_size % 4) {
-		printk(KERN_ERR "raid6: invalid chunk size %d for %s\n",
-		       conf->chunk_size, mdname(mddev));
-		goto abort;
-	}
-	if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) {
-		printk(KERN_ERR
-		       "raid6: unsupported parity algorithm %d for %s\n",
-		       conf->algorithm, mdname(mddev));
-		goto abort;
-	}
-	if (mddev->degraded > 2) {
-		printk(KERN_ERR "raid6: not enough operational devices for %s"
-		       " (%d/%d failed)\n",
-		       mdname(mddev), conf->failed_disks, conf->raid_disks);
-		goto abort;
-	}
-
-	if (mddev->degraded > 0 &&
-	    mddev->recovery_cp != MaxSector) {
-		if (mddev->ok_start_degraded)
-			printk(KERN_WARNING "raid6: starting dirty degraded array:%s"
-			       "- data corruption possible.\n",
-			       mdname(mddev));
-		else {
-			printk(KERN_ERR "raid6: cannot start dirty degraded array"
-			       " for %s\n", mdname(mddev));
-			goto abort;
-		}
-	}
-
-	{
-		mddev->thread = md_register_thread(raid6d, mddev, "%s_raid6");
-		if (!mddev->thread) {
-			printk(KERN_ERR
-			       "raid6: couldn't allocate thread for %s\n",
-			       mdname(mddev));
-			goto abort;
-		}
-	}
-
-	memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
-		 conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
-	if (grow_stripes(conf, conf->max_nr_stripes)) {
-		printk(KERN_ERR
-		       "raid6: couldn't allocate %dkB for buffers\n", memory);
-		shrink_stripes(conf);
-		md_unregister_thread(mddev->thread);
-		goto abort;
-	} else
-		printk(KERN_INFO "raid6: allocated %dkB for %s\n",
-		       memory, mdname(mddev));
-
-	if (mddev->degraded == 0)
-		printk(KERN_INFO "raid6: raid level %d set %s active with %d out of %d"
-		       " devices, algorithm %d\n", conf->level, mdname(mddev),
-		       mddev->raid_disks-mddev->degraded, mddev->raid_disks,
-		       conf->algorithm);
-	else
-		printk(KERN_ALERT "raid6: raid level %d set %s active with %d"
-		       " out of %d devices, algorithm %d\n", conf->level,
-		       mdname(mddev), mddev->raid_disks - mddev->degraded,
-		       mddev->raid_disks, conf->algorithm);
-
-	print_raid6_conf(conf);
-
-	/* read-ahead size must cover two whole stripes, which is
-	 * 2 * (n-2) * chunksize where 'n' is the number of raid devices
-	 */
-	{
-		int stripe = (mddev->raid_disks-2) * mddev->chunk_size
-			/ PAGE_SIZE;
-		if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
-			mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
-	}
-
-	/* Ok, everything is just fine now */
-	sysfs_create_group(&mddev->kobj, &raid6_attrs_group);
-
-	mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
-
-	mddev->queue->unplug_fn = raid6_unplug_device;
-	mddev->queue->issue_flush_fn = raid6_issue_flush;
-	return 0;
-abort:
-	if (conf) {
-		print_raid6_conf(conf);
-		safe_put_page(conf->spare_page);
-		kfree(conf->stripe_hashtbl);
-		kfree(conf->disks);
-		kfree(conf);
-	}
-	mddev->private = NULL;
-	printk(KERN_ALERT "raid6: failed to run raid set %s\n", mdname(mddev));
-	return -EIO;
-}
-
-
-
-static int stop (mddev_t *mddev)
-{
-	raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
-
-	md_unregister_thread(mddev->thread);
-	mddev->thread = NULL;
-	shrink_stripes(conf);
-	kfree(conf->stripe_hashtbl);
-	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
-	sysfs_remove_group(&mddev->kobj, &raid6_attrs_group);
-	kfree(conf);
-	mddev->private = NULL;
-	return 0;
-}
-
-#if RAID6_DUMPSTATE
-static void print_sh (struct seq_file *seq, struct stripe_head *sh)
-{
-	int i;
-
-	seq_printf(seq, "sh %llu, pd_idx %d, state %ld.\n",
-		   (unsigned long long)sh->sector, sh->pd_idx, sh->state);
-	seq_printf(seq, "sh %llu,  count %d.\n",
-		   (unsigned long long)sh->sector, atomic_read(&sh->count));
-	seq_printf(seq, "sh %llu, ", (unsigned long long)sh->sector);
-	for (i = 0; i < sh->raid_conf->raid_disks; i++) {
-		seq_printf(seq, "(cache%d: %p %ld) ",
-			   i, sh->dev[i].page, sh->dev[i].flags);
-	}
-	seq_printf(seq, "\n");
-}
-
-static void printall (struct seq_file *seq, raid6_conf_t *conf)
-{
-	struct stripe_head *sh;
-	struct hlist_node *hn;
-	int i;
-
-	spin_lock_irq(&conf->device_lock);
-	for (i = 0; i < NR_HASH; i++) {
-		sh = conf->stripe_hashtbl[i];
-		hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) {
-			if (sh->raid_conf != conf)
-				continue;
-			print_sh(seq, sh);
-		}
-	}
-	spin_unlock_irq(&conf->device_lock);
-}
-#endif
-
-static void status (struct seq_file *seq, mddev_t *mddev)
-{
-	raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
-	int i;
-
-	seq_printf (seq, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout);
-	seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks);
-	for (i = 0; i < conf->raid_disks; i++)
- 		seq_printf (seq, "%s",
-			    conf->disks[i].rdev &&
-			    test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_");
-	seq_printf (seq, "]");
-#if RAID6_DUMPSTATE
-	seq_printf (seq, "\n");
-	printall(seq, conf);
-#endif
-}
-
-static void print_raid6_conf (raid6_conf_t *conf)
-{
-	int i;
-	struct disk_info *tmp;
-
-	printk("RAID6 conf printout:\n");
-	if (!conf) {
-		printk("(conf==NULL)\n");
-		return;
-	}
-	printk(" --- rd:%d wd:%d fd:%d\n", conf->raid_disks,
-		 conf->working_disks, conf->failed_disks);
-
-	for (i = 0; i < conf->raid_disks; i++) {
-		char b[BDEVNAME_SIZE];
-		tmp = conf->disks + i;
-		if (tmp->rdev)
-		printk(" disk %d, o:%d, dev:%s\n",
-			i, !test_bit(Faulty, &tmp->rdev->flags),
-			bdevname(tmp->rdev->bdev,b));
-	}
-}
-
-static int raid6_spare_active(mddev_t *mddev)
-{
-	int i;
-	raid6_conf_t *conf = mddev->private;
-	struct disk_info *tmp;
-
-	for (i = 0; i < conf->raid_disks; i++) {
-		tmp = conf->disks + i;
-		if (tmp->rdev
-		    && !test_bit(Faulty, &tmp->rdev->flags)
-		    && !test_bit(In_sync, &tmp->rdev->flags)) {
-			mddev->degraded--;
-			conf->failed_disks--;
-			conf->working_disks++;
-			set_bit(In_sync, &tmp->rdev->flags);
-		}
-	}
-	print_raid6_conf(conf);
-	return 0;
-}
-
-static int raid6_remove_disk(mddev_t *mddev, int number)
-{
-	raid6_conf_t *conf = mddev->private;
-	int err = 0;
-	mdk_rdev_t *rdev;
-	struct disk_info *p = conf->disks + number;
-
-	print_raid6_conf(conf);
-	rdev = p->rdev;
-	if (rdev) {
-		if (test_bit(In_sync, &rdev->flags) ||
-		    atomic_read(&rdev->nr_pending)) {
-			err = -EBUSY;
-			goto abort;
-		}
-		p->rdev = NULL;
-		synchronize_rcu();
-		if (atomic_read(&rdev->nr_pending)) {
-			/* lost the race, try later */
-			err = -EBUSY;
-			p->rdev = rdev;
-		}
-	}
-
-abort:
-
-	print_raid6_conf(conf);
-	return err;
-}
-
-static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
-{
-	raid6_conf_t *conf = mddev->private;
-	int found = 0;
-	int disk;
-	struct disk_info *p;
-
-	if (mddev->degraded > 2)
-		/* no point adding a device */
-		return 0;
-	/*
-	 * find the disk ... but prefer rdev->saved_raid_disk
-	 * if possible.
-	 */
-	if (rdev->saved_raid_disk >= 0 &&
-	    conf->disks[rdev->saved_raid_disk].rdev == NULL)
-		disk = rdev->saved_raid_disk;
-	else
-		disk = 0;
-	for ( ; disk < mddev->raid_disks; disk++)
-		if ((p=conf->disks + disk)->rdev == NULL) {
-			clear_bit(In_sync, &rdev->flags);
-			rdev->raid_disk = disk;
-			found = 1;
-			if (rdev->saved_raid_disk != disk)
-				conf->fullsync = 1;
-			rcu_assign_pointer(p->rdev, rdev);
-			break;
-		}
-	print_raid6_conf(conf);
-	return found;
-}
-
-static int raid6_resize(mddev_t *mddev, sector_t sectors)
-{
-	/* no resync is happening, and there is enough space
-	 * on all devices, so we can resize.
-	 * We need to make sure resync covers any new space.
-	 * If the array is shrinking we should possibly wait until
-	 * any io in the removed space completes, but it hardly seems
-	 * worth it.
-	 */
-	sectors &= ~((sector_t)mddev->chunk_size/512 - 1);
-	mddev->array_size = (sectors * (mddev->raid_disks-2))>>1;
-	set_capacity(mddev->gendisk, mddev->array_size << 1);
-	mddev->changed = 1;
-	if (sectors/2  > mddev->size && mddev->recovery_cp == MaxSector) {
-		mddev->recovery_cp = mddev->size << 1;
-		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
-	}
-	mddev->size = sectors /2;
-	mddev->resync_max_sectors = sectors;
-	return 0;
-}
-
-static void raid6_quiesce(mddev_t *mddev, int state)
-{
-	raid6_conf_t *conf = mddev_to_conf(mddev);
-
-	switch(state) {
-	case 1: /* stop all writes */
-		spin_lock_irq(&conf->device_lock);
-		conf->quiesce = 1;
-		wait_event_lock_irq(conf->wait_for_stripe,
-				    atomic_read(&conf->active_stripes) == 0,
-				    conf->device_lock, /* nothing */);
-		spin_unlock_irq(&conf->device_lock);
-		break;
-
-	case 0: /* re-enable writes */
-		spin_lock_irq(&conf->device_lock);
-		conf->quiesce = 0;
-		wake_up(&conf->wait_for_stripe);
-		spin_unlock_irq(&conf->device_lock);
-		break;
-	}
-}
-
-static struct mdk_personality raid6_personality =
-{
-	.name		= "raid6",
-	.level		= 6,
-	.owner		= THIS_MODULE,
-	.make_request	= make_request,
-	.run		= run,
-	.stop		= stop,
-	.status		= status,
-	.error_handler	= error,
-	.hot_add_disk	= raid6_add_disk,
-	.hot_remove_disk= raid6_remove_disk,
-	.spare_active	= raid6_spare_active,
-	.sync_request	= sync_request,
-	.resize		= raid6_resize,
-	.quiesce	= raid6_quiesce,
-};
-
-static int __init raid6_init(void)
-{
-	int e;
-
-	e = raid6_select_algo();
-	if ( e )
-		return e;
-
-	return register_md_personality(&raid6_personality);
-}
-
-static void raid6_exit (void)
-{
-	unregister_md_personality(&raid6_personality);
-}
-
-module_init(raid6_init);
-module_exit(raid6_exit);
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("md-personality-8"); /* RAID6 */
-MODULE_ALIAS("md-raid6");
-MODULE_ALIAS("md-level-6");
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 344d83a..ef52e6d 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -25,7 +25,7 @@
 	  module will be called videodev.
 
 config VIDEO_V4L1
-	boolean "Enable Video For Linux API 1 (DEPRECATED)"
+	bool "Enable Video For Linux API 1 (DEPRECATED)"
 	depends on VIDEO_DEV
 	select VIDEO_V4L1_COMPAT
 	default y
@@ -36,7 +36,7 @@
 	  If you are unsure as to whether this is required, answer Y.
 
 config VIDEO_V4L1_COMPAT
-	boolean "Enable Video For Linux API 1 compatible Layer"
+	bool "Enable Video For Linux API 1 compatible Layer"
 	depends on VIDEO_DEV
 	default y
 	---help---
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
index 61b8961..8e74482 100644
--- a/drivers/media/common/Makefile
+++ b/drivers/media/common/Makefile
@@ -1,5 +1,5 @@
 saa7146-objs    := saa7146_i2c.o saa7146_core.o
-saa7146_vv-objs := saa7146_vv_ksyms.o saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
+saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
 ir-common-objs  := ir-functions.o ir-keymaps.o
 
 obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
index 397cff8..8eaa88f 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -269,4 +269,3 @@
  * c-basic-offset: 8
  * End:
  */
-
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index a294d5c..ca98d94 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -618,7 +618,7 @@
 
 EXPORT_SYMBOL_GPL(ir_codes_em_terratec);
 
-IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE] = {
+IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE] = {
 	[ 0x3a ] = KEY_0,
 	[ 0x31 ] = KEY_1,
 	[ 0x32 ] = KEY_2,
@@ -670,7 +670,7 @@
 	[ 0x27 ] = KEY_RECORD,
 };
 
-EXPORT_SYMBOL_GPL(ir_codes_em_pinnacle_usb);
+EXPORT_SYMBOL_GPL(ir_codes_pinnacle_grey);
 
 IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE] = {
 	[ 0x0f ] = KEY_0,
@@ -1263,34 +1263,51 @@
 	[ 0x0f ] = KEY_9,
 
 	[ 0x00 ] = KEY_POWER,
-	[ 0x02 ] = KEY_TUNER,		/* TV/FM */
-	[ 0x1e ] = KEY_VIDEO,
+	[ 0x1b ] = KEY_AUDIO,           /* Audio Source */
+	[ 0x02 ] = KEY_TUNER,		/* TV/FM, not on Y0400052 */
+	[ 0x1e ] = KEY_VIDEO,           /* Video Source */
+	[ 0x16 ] = KEY_INFO,            /* Display information */
 	[ 0x04 ] = KEY_VOLUMEUP,
 	[ 0x08 ] = KEY_VOLUMEDOWN,
 	[ 0x0c ] = KEY_CHANNELUP,
 	[ 0x10 ] = KEY_CHANNELDOWN,
 	[ 0x03 ] = KEY_ZOOM,		/* fullscreen */
-	[ 0x1f ] = KEY_SUBTITLE,		/* closed caption/teletext */
+	[ 0x1f ] = KEY_TEXT,		/* closed caption/teletext */
 	[ 0x20 ] = KEY_SLEEP,
+	[ 0x29 ] = KEY_CLEAR,           /* boss key */
 	[ 0x14 ] = KEY_MUTE,
 	[ 0x2b ] = KEY_RED,
 	[ 0x2c ] = KEY_GREEN,
 	[ 0x2d ] = KEY_YELLOW,
 	[ 0x2e ] = KEY_BLUE,
-	[ 0x18 ] = KEY_KPPLUS,		/* fine tune + */
-	[ 0x19 ] = KEY_KPMINUS,		/* fine tune - */
+	[ 0x18 ] = KEY_KPPLUS,		/* fine tune + , not on Y040052 */
+	[ 0x19 ] = KEY_KPMINUS,		/* fine tune - , not on Y040052 */
+	[ 0x2a ] = KEY_MEDIA,           /* PIP (Picture in picture */
 	[ 0x21 ] = KEY_DOT,
 	[ 0x13 ] = KEY_ENTER,
-	[ 0x22 ] = KEY_BACK,
+	[ 0x11 ] = KEY_LAST,            /* Recall (last channel */
+	[ 0x22 ] = KEY_PREVIOUS,
 	[ 0x23 ] = KEY_PLAYPAUSE,
 	[ 0x24 ] = KEY_NEXT,
+	[ 0x25 ] = KEY_ARCHIVE,       /* Time Shifting */
 	[ 0x26 ] = KEY_STOP,
-	[ 0x27 ] = KEY_RECORD
+	[ 0x27 ] = KEY_RECORD,
+	[ 0x28 ] = KEY_SAVE,          /* Screenshot */
+	[ 0x2f ] = KEY_MENU,
+	[ 0x30 ] = KEY_CANCEL,
+	[ 0x31 ] = KEY_CHANNEL,       /* Channel Surf */
+	[ 0x32 ] = KEY_SUBTITLE,
+	[ 0x33 ] = KEY_LANGUAGE,
+	[ 0x34 ] = KEY_REWIND,
+	[ 0x35 ] = KEY_FASTFORWARD,
+	[ 0x36 ] = KEY_TV,
+	[ 0x37 ] = KEY_RADIO,         /* FM */
+	[ 0x38 ] = KEY_DVD
 };
 
 EXPORT_SYMBOL_GPL(ir_codes_winfast);
 
-IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
+IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE] = {
 	[ 0x59 ] = KEY_MUTE,
 	[ 0x4a ] = KEY_POWER,
 
@@ -1348,7 +1365,7 @@
 	[ 0x0a ] = KEY_BACKSPACE,
 };
 
-EXPORT_SYMBOL_GPL(ir_codes_pinnacle);
+EXPORT_SYMBOL_GPL(ir_codes_pinnacle_color);
 
 /* Hauppauge: the newer, gray remotes (seems there are multiple
  * slightly different versions), shipped with cx88+ivtv cards.
@@ -1413,3 +1430,46 @@
 
 EXPORT_SYMBOL_GPL(ir_codes_hauppauge_new);
 
+IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE] = {
+	[ 0x1d ] = KEY_SWITCHVIDEOMODE, /* switch inputs */
+	[ 0x2a ] = KEY_FRONT,
+
+	[ 0x3e ] = KEY_1,
+	[ 0x02 ] = KEY_2,
+	[ 0x06 ] = KEY_3,
+	[ 0x0a ] = KEY_4,
+	[ 0x0e ] = KEY_5,
+	[ 0x12 ] = KEY_6,
+	[ 0x16 ] = KEY_7,
+	[ 0x1a ] = KEY_8,
+	[ 0x1e ] = KEY_9,
+	[ 0x3a ] = KEY_0,
+	[ 0x22 ] = KEY_NUMLOCK,         /* -/-- */
+	[ 0x20 ] = KEY_REFRESH,
+
+	[ 0x03 ] = KEY_BRIGHTNESSDOWN,
+	[ 0x28 ] = KEY_AUDIO,
+	[ 0x3c ] = KEY_UP,
+	[ 0x3f ] = KEY_LEFT,
+	[ 0x2e ] = KEY_MUTE,
+	[ 0x3b ] = KEY_RIGHT,
+	[ 0x00 ] = KEY_DOWN,
+	[ 0x07 ] = KEY_BRIGHTNESSUP,
+	[ 0x2c ] = KEY_TEXT,
+
+	[ 0x37 ] = KEY_RECORD,
+	[ 0x17 ] = KEY_PLAY,
+	[ 0x13 ] = KEY_PAUSE,
+	[ 0x26 ] = KEY_STOP,
+	[ 0x18 ] = KEY_FASTFORWARD,
+	[ 0x14 ] = KEY_REWIND,
+	[ 0x33 ] = KEY_ZOOM,
+	[ 0x32 ] = KEY_KEYBOARD,
+	[ 0x30 ] = KEY_GOTO,            /* Pointing arrow */
+	[ 0x36 ] = KEY_MACRO,           /* Maximize/Minimize (yellow) */
+	[ 0x0b ] = KEY_RADIO,
+	[ 0x10 ] = KEY_POWER,
+
+};
+
+EXPORT_SYMBOL_GPL(ir_codes_npgtech);
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index 523ab38..0027acc 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -501,6 +501,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_vv_init);
 
 int saa7146_vv_release(struct saa7146_dev* dev)
 {
@@ -515,6 +516,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_vv_release);
 
 int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
 			    char *name, int type)
@@ -553,6 +555,7 @@
 	*vid = vfd;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_register_device);
 
 int saa7146_unregister_device(struct video_device **vid, struct saa7146_dev* dev)
 {
@@ -571,6 +574,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_unregister_device);
 
 static int __init saa7146_vv_init_module(void)
 {
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index 33bec8a..2092e6c 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -641,6 +641,7 @@
 	vv->current_hps_source = source;
 	vv->current_hps_sync = sync;
 }
+EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
 
 int saa7146_enable_overlay(struct saa7146_fh *fh)
 {
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index e7079d1..8393d47 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -318,6 +318,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_start_preview);
 
 int saa7146_stop_preview(struct saa7146_fh *fh)
 {
@@ -352,6 +353,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(saa7146_stop_preview);
 
 static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
 {
diff --git a/drivers/media/common/saa7146_vv_ksyms.c b/drivers/media/common/saa7146_vv_ksyms.c
deleted file mode 100644
index 62226eb4..0000000
--- a/drivers/media/common/saa7146_vv_ksyms.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <linux/module.h>
-#include <media/saa7146_vv.h>
-
-EXPORT_SYMBOL_GPL(saa7146_start_preview);
-EXPORT_SYMBOL_GPL(saa7146_stop_preview);
-
-EXPORT_SYMBOL_GPL(saa7146_set_hps_source_and_sync);
-EXPORT_SYMBOL_GPL(saa7146_register_device);
-EXPORT_SYMBOL_GPL(saa7146_unregister_device);
-
-EXPORT_SYMBOL_GPL(saa7146_vv_init);
-EXPORT_SYMBOL_GPL(saa7146_vv_release);
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 9c7f122..3be87c7 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -14,6 +14,7 @@
 #include "stv0297.h"
 #include "mt312.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
 #include "dvb-pll.h"
 
 /* lnb control */
@@ -166,11 +167,12 @@
 	return 0;
 }
 
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int samsung_tbmu24112_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	u8 buf[4];
 	u32 div;
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	struct flexcop_device *fc = fe->dvb->priv;
 
 	div = params->frequency / 125;
 
@@ -181,8 +183,11 @@
 
 	if (params->frequency < 1500000) buf[3] |= 0x10;
 
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1) {
 		return -EIO;
+	}
 	return 0;
 }
 
@@ -241,7 +246,6 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.min_delay_ms = 100,
 	.set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
-	.pll_set = samsung_tbmu24112_pll_set,
 };
 
 /* dvb-t mt352 */
@@ -264,11 +268,14 @@
 	return 0;
 }
 
-static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int samsung_tdtc9251dh0_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
 {
 	u32 div;
 	unsigned char bs = 0;
 
+	if (buf_len < 5)
+		return -EINVAL;
+
 	#define IF_FREQUENCYx6 217    /* 6 * 36.16666666667MHz */
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
@@ -276,19 +283,18 @@
 	if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
 	if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
 
-	pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */
+	pllbuf[0] = 0x61;
 	pllbuf[1] = div >> 8;
 	pllbuf[2] = div & 0xff;
 	pllbuf[3] = 0xcc;
 	pllbuf[4] = bs;
 
-	return 0;
+	return 5;
 }
 
 static struct mt352_config samsung_tdtc9251dh0_config = {
 	.demod_address = 0x0f,
 	.demod_init    = samsung_tdtc9251dh0_demod_init,
-	.pll_set       = samsung_tdtc9251dh0_pll_set,
 };
 
 static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
@@ -297,56 +303,21 @@
 	return request_firmware(fw, name, fc->dev);
 }
 
-static int lgdt3303_pll_set(struct dvb_frontend* fe,
-			    struct dvb_frontend_parameters* params)
+static int lgdt3303_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct flexcop_device *fc = fe->dvb->priv;
-	u8 buf[4];
-	struct i2c_msg msg =
-		{ .addr = 0x61, .flags = 0, .buf = buf, .len = 4 };
-	int err;
-
-	dvb_pll_configure(&dvb_pll_tdvs_tua6034,buf, params->frequency, 0);
-	dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-			__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-	if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
-		printk(KERN_WARNING "lgdt3303: %s error "
-			   "(addr %02x <- %02x, err = %i)\n",
-			   __FUNCTION__, buf[0], buf[1], err);
-		if (err < 0)
-			return err;
-		else
-			return -EREMOTEIO;
-	}
-
-	buf[0] = 0x86 | 0x18;
-	buf[1] = 0x50;
-	msg.len = 2;
-	if ((err = i2c_transfer(&fc->i2c_adap, &msg, 1)) != 1) {
-		printk(KERN_WARNING "lgdt3303: %s error "
-			   "(addr %02x <- %02x, err = %i)\n",
-			   __FUNCTION__, buf[0], buf[1], err);
-		if (err < 0)
-			return err;
-		else
-			return -EREMOTEIO;
-	}
-
-	return 0;
+	return lg_h06xf_pll_set(fe, &fc->i2c_adap, params);
 }
 
 static struct lgdt330x_config air2pc_atsc_hd5000_config = {
 	.demod_address       = 0x59,
 	.demod_chip          = LGDT3303,
 	.serial_mpeg         = 0x04,
-	.pll_set             = lgdt3303_pll_set,
 	.clock_polarity_flip = 1,
 };
 
 static struct nxt200x_config samsung_tbmv_config = {
 	.demod_address    = 0x0a,
-	.pll_address      = 0xc2,
-	.pll_desc         = &dvb_pll_samsung_tbmv,
 };
 
 static struct bcm3510_config air2pc_atsc_first_gen_config = {
@@ -354,7 +325,7 @@
 	.request_firmware = flexcop_fe_request_firmware,
 };
 
-static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int skystar23_samsung_tbdu18132_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	u8 buf[4];
 	u32 div;
@@ -371,6 +342,8 @@
 	if (params->frequency < 1550000)
 		buf[3] |= 0x02;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -379,9 +352,52 @@
 static struct mt312_config skystar23_samsung_tbdu18132_config = {
 
 	.demod_address = 0x0e,
-	.pll_set = skystar23_samsung_tbdu18132_pll_set,
 };
 
+static int alps_tdee4_stv0297_tuner_set_params(struct dvb_frontend* fe,
+					       struct dvb_frontend_parameters *fep)
+{
+	struct flexcop_device *fc = fe->dvb->priv;
+	u8 buf[4];
+	u16 div;
+	int ret;
+
+/*  62.5 kHz * 10 */
+#define REF_FREQ    625
+#define FREQ_OFFSET 36125
+
+	div = ((fep->frequency/1000 + FREQ_OFFSET ) * 10)  / REF_FREQ; // 4 MHz = 4000 KHz
+
+	buf[0] = (u8)( div >> 8) & 0x7f;
+	buf[1] = (u8)        div & 0xff;
+
+/* F(osc) = N * Reference Freq. (62.5 kHz)
+ * byte 2 :  0 N14 N13 N12 N11 N10 N9  N8
+ * byte 3 : N7 N6  N5  N4  N3  N2  N1  N0
+ * byte 4 : 1  *   *   AGD R3  R2  R1  R0
+ * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
+ * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95 */
+	buf[2] = 0x95;
+
+// Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
+//  47 - 153   0  *  0   0   0   0   0   1   0x01
+// 153 - 430   0  *  0   0   0   0   1   0   0x02
+// 430 - 822   0  *  0   0   1   0   0   0   0x08
+// 822 - 862   1  *  0   0   1   0   0   0   0x88
+
+	     if (fep->frequency <= 153000000) buf[3] = 0x01;
+	else if (fep->frequency <= 430000000) buf[3] = 0x02;
+	else if (fep->frequency <= 822000000) buf[3] = 0x08;
+	else buf[3] = 0x88;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	deb_tuner("tuner buffer for %d Hz: %x %x %x %x\n",fep->frequency, buf[0],buf[1],buf[2],buf[3]);
+	ret = fc->i2c_request(fc,FC_WRITE,FC_I2C_PORT_TUNER,0x61,buf[0],&buf[1],3);
+	deb_tuner("tuner write returned: %d\n",ret);
+
+	return 0;
+}
 
 static u8 alps_tdee4_stv0297_inittab[] = {
 	0x80, 0x01,
@@ -490,7 +506,9 @@
 
 	/* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
 	if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
-		ops = fc->fe->ops;
+		ops = &fc->fe->ops;
+
+		ops->tuner_ops.set_params = samsung_tbmu24112_tuner_set_params;
 
 		ops->set_voltage = flexcop_set_voltage;
 
@@ -503,16 +521,19 @@
 	/* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
 	if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
 		fc->dev_type          = FC_AIR_DVB;
+		fc->fe->ops.tuner_ops.calc_regs = samsung_tdtc9251dh0_calc_regs;
 		info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
 	} else
 	/* try the air atsc 2nd generation (nxt2002) */
 	if ((fc->fe = nxt200x_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
 		fc->dev_type          = FC_AIR_ATSC2;
+		dvb_pll_attach(fc->fe, 0x61, &fc->i2c_adap, &dvb_pll_samsung_tbmv);
 		info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
 	} else
 	/* try the air atsc 3nd generation (lgdt3303) */
 	if ((fc->fe = lgdt330x_attach(&air2pc_atsc_hd5000_config, &fc->i2c_adap)) != NULL) {
 		fc->dev_type          = FC_AIR_ATSC3;
+		fc->fe->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
 		info("found the lgdt3303 at i2c address: 0x%02x",air2pc_atsc_hd5000_config.demod_address);
 	} else
 	/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
@@ -523,11 +544,14 @@
 	/* try the cable dvb (stv0297) */
 	if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap)) != NULL) {
 		fc->dev_type                        = FC_CABLE;
+		fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params;
 		info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
 	} else
 	/* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
 	if ((fc->fe = vp310_mt312_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
-		ops = fc->fe->ops;
+		ops = &fc->fe->ops;
+
+		ops->tuner_ops.set_params = skystar23_samsung_tbdu18132_tuner_set_params;
 
 		ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
 		ops->diseqc_send_burst      = flexcop_diseqc_send_burst;
@@ -547,7 +571,7 @@
 	} else {
 		if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
 			err("frontend registration failed!");
-			ops = fc->fe->ops;
+			ops = &fc->fe->ops;
 			if (ops->release != NULL)
 				ops->release(fc->fe);
 			fc->fe = NULL;
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
index 9bc40bd..f0404170 100644
--- a/drivers/media/dvb/b2c2/flexcop-pci.c
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -242,19 +242,16 @@
 	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
 		return ret;
 
-	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0)
-		goto dma1_free;
+	if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0) {
+		flexcop_dma_free(&fc_pci->dma[0]);
+		return ret;
+	}
 
 	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
 	flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO   | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
 
 	fc_pci->init_state |= FC_PCI_DMA_INIT;
 
-	goto success;
-dma1_free:
-	flexcop_dma_free(&fc_pci->dma[0]);
-
-success:
 	return ret;
 }
 
@@ -303,7 +300,7 @@
 	spin_lock_init(&fc_pci->irq_lock);
 
 	fc_pci->init_state |= FC_PCI_INIT;
-	goto success;
+	return ret;
 
 err_pci_iounmap:
 	pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
@@ -312,8 +309,6 @@
 	pci_release_regions(fc_pci->pdev);
 err_pci_disable_device:
 	pci_disable_device(fc_pci->pdev);
-
-success:
 	return ret;
 }
 
@@ -378,14 +373,14 @@
 
 	INIT_WORK(&fc_pci->irq_check_work, flexcop_pci_irq_check_work, fc_pci);
 
-	goto success;
+	return ret;
+
 err_fc_exit:
 	flexcop_device_exit(fc);
 err_pci_exit:
 	flexcop_pci_exit(fc_pci);
 err_kfree:
 	flexcop_device_kfree(fc);
-success:
 	return ret;
 }
 
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
index 06ec9fff..515954f 100644
--- a/drivers/media/dvb/b2c2/flexcop-usb.c
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -433,11 +433,10 @@
 	flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
 	flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
 
-	ret = 0;
-	goto success;
+	return 0;
+
 urb_error:
 	flexcop_usb_transfer_exit(fc_usb);
-success:
 	return ret;
 }
 
@@ -515,15 +514,14 @@
 		goto err_fc_exit;
 
 	info("%s successfully initialized and connected.",DRIVER_NAME);
-	ret = 0;
-	goto success;
+	return 0;
+
 err_fc_exit:
 	flexcop_device_exit(fc);
 err_usb_exit:
 	flexcop_usb_exit(fc_usb);
 err_kfree:
 	flexcop_device_kfree(fc);
-success:
 	return ret;
 }
 
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
index 56ba524..29ec418 100644
--- a/drivers/media/dvb/b2c2/flexcop.c
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -67,7 +67,7 @@
 static int flexcop_dvb_init(struct flexcop_device *fc)
 {
 	int ret;
-	if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner)) < 0) {
+	if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner,fc->dev)) < 0) {
 		err("error registering DVB adapter");
 		return ret;
 	}
@@ -116,7 +116,7 @@
 	dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
 
 	fc->init_state |= FC_STATE_DVB_INIT;
-	goto success;
+	return 0;
 
 err_connect_frontend:
 	fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
@@ -129,9 +129,6 @@
 err_dmx:
 	dvb_unregister_adapter(&fc->dvb_adapter);
 	return ret;
-
-success:
-	return 0;
 }
 
 static void flexcop_dvb_exit(struct flexcop_device *fc)
@@ -279,11 +276,10 @@
 
 	flexcop_device_name(fc,"initialization of","complete");
 
-	ret = 0;
-	goto success;
+	return 0;
+
 error:
 	flexcop_device_exit(fc);
-success:
 	return ret;
 }
 EXPORT_SYMBOL(flexcop_device_initialize);
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 5500f8a..761fa6e 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -63,8 +63,6 @@
 int bt878_num;
 struct bt878 bt878[BT878_MAX];
 
-EXPORT_SYMBOL(bt878_debug);
-EXPORT_SYMBOL(bt878_verbose);
 EXPORT_SYMBOL(bt878_num);
 EXPORT_SYMBOL(bt878);
 
@@ -393,7 +391,9 @@
 	{ 0x07711461, BTTV_BOARD_AVDVBT_771,			"AVermedia AverTV DVB-T 771" },
 	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,		"DViCO FusionHDTV DVB-T Lite" },
 	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,	"DViCO FusionHDTV 5 Lite" },
-	{ 0x20007063, BTTV_BOARD_PC_HDTV,			"pcHDTV HD-2000 TV"},
+	{ 0x20007063, BTTV_BOARD_PC_HDTV,			"pcHDTV HD-2000 TV" },
+	{ 0x00261822, BTTV_BOARD_TWINHAN_DST,			"DNTV Live! Mini" },
+
 	{ 0, -1, NULL }
 };
 
@@ -417,6 +417,11 @@
 
 	printk(KERN_INFO "bt878: Bt878 AUDIO function found (%d).\n",
 	       bt878_num);
+	if (bt878_num >= BT878_MAX) {
+		printk(KERN_ERR "bt878: Too many devices inserted\n");
+		result = -ENOMEM;
+		goto fail0;
+	}
 	if (pci_enable_device(dev))
 		return -EIO;
 
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index 1cfa5e5..d687a14 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -38,6 +38,10 @@
 module_param(dst_addons, int, 0644);
 MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
 
+static unsigned int dst_algo;
+module_param(dst_algo, int, 0644);
+MODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)");
+
 #define HAS_LOCK		1
 #define ATTEMPT_TUNE		2
 #define HAS_POWER		4
@@ -47,20 +51,24 @@
 #define DST_INFO		2
 #define DST_DEBUG		3
 
-#define dprintk(x, y, z, format, arg...) do {						\
-	if (z) {									\
-		if	((x > DST_ERROR) && (x > y))					\
-			printk(KERN_ERR "%s: " format "\n", __FUNCTION__ , ##arg);	\
-		else if	((x > DST_NOTICE) && (x > y))					\
-			printk(KERN_NOTICE "%s: " format "\n", __FUNCTION__ , ##arg);	\
-		else if ((x > DST_INFO) && (x > y))					\
-			printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##arg);	\
-		else if ((x > DST_DEBUG) && (x > y))					\
-			printk(KERN_DEBUG "%s: " format "\n", __FUNCTION__ , ##arg);	\
-	} else {									\
-		if (x > y)								\
-			printk(format, ##arg);						\
-	}										\
+#define dprintk(x, y, z, format, arg...) do {				\
+	if (z) {							\
+		if	((x > DST_ERROR) && (x > y))			\
+			printk(KERN_ERR "dst(%d) %s: " format "\n",	\
+				state->bt->nr, __func__ , ##arg);	\
+		else if	((x > DST_NOTICE) && (x > y))			\
+			printk(KERN_NOTICE "dst(%d) %s: " format "\n",  \
+				state->bt->nr, __func__ , ##arg);	\
+		else if ((x > DST_INFO) && (x > y))			\
+			printk(KERN_INFO "dst(%d) %s: " format "\n",	\
+				state->bt->nr, __func__ , ##arg);	\
+		else if ((x > DST_DEBUG) && (x > y))			\
+			printk(KERN_DEBUG "dst(%d) %s: " format "\n",	\
+				state->bt->nr,  __func__ , ##arg);	\
+	} else {							\
+		if (x > y)						\
+			printk(format, ##arg);				\
+	}								\
 } while(0)
 
 
@@ -110,7 +118,7 @@
 
 	*result = 0;
 	if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)\n", err);
+		dprintk(verbose, DST_ERROR, 1, "dst_gpio_inb error (err == %i)", err);
 		return -EREMOTEIO;
 	}
 	*result = (u8) rd_packet.rd.value;
@@ -363,6 +371,17 @@
 		state->tx_tuna[2] = (freq >> 16) & 0xff;
 		state->tx_tuna[3] = (freq >> 8) & 0xff;
 		state->tx_tuna[4] = (u8) freq;
+	} else if (state->dst_type == DST_TYPE_IS_ATSC) {
+		freq = freq / 1000;
+		if (freq < 51000 || freq > 858000)
+			return -EINVAL;
+		state->tx_tuna[2] = (freq >> 16) & 0xff;
+		state->tx_tuna[3] = (freq >>  8) & 0xff;
+		state->tx_tuna[4] = (u8) freq;
+		state->tx_tuna[5] = 0x00;		/*	ATSC	*/
+		state->tx_tuna[6] = 0x00;
+		if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG)
+			state->tx_tuna[7] = 0x00;	/*	Digital	*/
 	} else
 		return -EINVAL;
 
@@ -447,29 +466,41 @@
 	}
 	dprintk(verbose, DST_INFO, 1, "set symrate %u", srate);
 	srate /= 1000;
-	if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
-		sval = srate;
-		sval <<= 20;
-		do_div(sval, 88000);
-		symcalc = (u32) sval;
-		dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
-		state->tx_tuna[5] = (u8) (symcalc >> 12);
-		state->tx_tuna[6] = (u8) (symcalc >> 4);
-		state->tx_tuna[7] = (u8) (symcalc << 4);
-	} else {
-		state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
-		state->tx_tuna[6] = (u8) (srate >> 8);
-		state->tx_tuna[7] = (u8) srate;
-	}
-	state->tx_tuna[8] &= ~0x20;
-	if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
-		if (srate > 8000)
-			state->tx_tuna[8] |= 0x20;
+	if (state->dst_type == DST_TYPE_IS_SAT) {
+		if (state->type_flags & DST_TYPE_HAS_SYMDIV) {
+			sval = srate;
+			sval <<= 20;
+			do_div(sval, 88000);
+			symcalc = (u32) sval;
+			dprintk(verbose, DST_INFO, 1, "set symcalc %u", symcalc);
+			state->tx_tuna[5] = (u8) (symcalc >> 12);
+			state->tx_tuna[6] = (u8) (symcalc >> 4);
+			state->tx_tuna[7] = (u8) (symcalc << 4);
+		} else {
+			state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f;
+			state->tx_tuna[6] = (u8) (srate >> 8);
+			state->tx_tuna[7] = (u8) srate;
+		}
+		state->tx_tuna[8] &= ~0x20;
+		if (state->type_flags & DST_TYPE_HAS_OBS_REGS) {
+			if (srate > 8000)
+				state->tx_tuna[8] |= 0x20;
+		}
+	} else if (state->dst_type == DST_TYPE_IS_CABLE) {
+		dprintk(verbose, DST_DEBUG, 1, "%s", state->fw_name);
+		if (!strncmp(state->fw_name, "DCTNEW", 6)) {
+			state->tx_tuna[5] = (u8) (srate >> 8);
+			state->tx_tuna[6] = (u8) srate;
+			state->tx_tuna[7] = 0x00;
+		} else if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+			state->tx_tuna[5] = 0x00;
+			state->tx_tuna[6] = (u8) (srate >> 8);
+			state->tx_tuna[7] = (u8) srate;
+		}
 	}
 	return 0;
 }
 
-
 static int dst_set_modulation(struct dst_state *state, fe_modulation_t modulation)
 {
 	if (state->dst_type != DST_TYPE_IS_CABLE)
@@ -490,7 +521,10 @@
 		state->tx_tuna[8] = 0x80;
 		break;
 	case QAM_256:
-		state->tx_tuna[8] = 0x00;
+		if (!strncmp(state->fw_name, "DCTNEW", 6))
+			state->tx_tuna[8] = 0xff;
+		else if (!strncmp(state->fw_name, "DCT-CI", 6))
+			state->tx_tuna[8] = 0x00;
 		break;
 	case QPSK:
 	case QAM_AUTO:
@@ -523,13 +557,19 @@
 }
 EXPORT_SYMBOL(dst_check_sum);
 
-static void dst_type_flags_print(u32 type_flags)
+static void dst_type_flags_print(struct dst_state *state)
 {
+	u32 type_flags = state->type_flags;
+
 	dprintk(verbose, DST_ERROR, 0, "DST type flags :");
-	if (type_flags & DST_TYPE_HAS_NEWTUNE)
-		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_NEWTUNE);
+	if (type_flags & DST_TYPE_HAS_TS188)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner", DST_TYPE_HAS_TS188);
+	if (type_flags & DST_TYPE_HAS_NEWTUNE_2)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x newtuner 2", DST_TYPE_HAS_NEWTUNE_2);
 	if (type_flags & DST_TYPE_HAS_TS204)
 		dprintk(verbose, DST_ERROR, 0, " 0x%x ts204", DST_TYPE_HAS_TS204);
+	if (type_flags & DST_TYPE_HAS_VLF)
+		dprintk(verbose, DST_ERROR, 0, " 0x%x VLF", DST_TYPE_HAS_VLF);
 	if (type_flags & DST_TYPE_HAS_SYMDIV)
 		dprintk(verbose, DST_ERROR, 0, " 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
 	if (type_flags & DST_TYPE_HAS_FW_1)
@@ -542,7 +582,7 @@
 }
 
 
-static int dst_type_print(u8 type)
+static int dst_type_print(struct dst_state *state, u8 type)
 {
 	char *otype;
 	switch (type) {
@@ -558,6 +598,10 @@
 		otype = "cable";
 		break;
 
+	case DST_TYPE_IS_ATSC:
+		otype = "atsc";
+		break;
+
 	default:
 		dprintk(verbose, DST_INFO, 1, "invalid dst type %d", type);
 		return -EINVAL;
@@ -567,6 +611,127 @@
 	return 0;
 }
 
+struct tuner_types tuner_list[] = {
+	{
+		.tuner_type = TUNER_TYPE_L64724,
+		.tuner_name = "L 64724",
+		.board_name = "UNKNOWN",
+		.fw_name    = "UNKNOWN"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1020",
+		.fw_name    = "DST-MOT"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1020",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_MB86A15,
+		.tuner_name = "MB 86A15",
+		.board_name = "VP1022",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_MB86A15,
+		.tuner_name = "MB 86A15",
+		.board_name = "VP1025",
+		.fw_name    = "DST-03T"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1030",
+		.fw_name    = "DST-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_STV0299,
+		.tuner_name = "STV 0299",
+		.board_name = "VP1030",
+		.fw_name    = "DSTMCI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2021",
+		.fw_name    = "DCTNEW"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2030",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2031",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP2040",
+		.fw_name    = "DCT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3020",
+		.fw_name    = "DTTFTA"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3021",
+		.fw_name    = "DTTFTA"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_TDA10046,
+		.tuner_name = "TDA10046",
+		.board_name = "VP3040",
+		.fw_name    = "DTT-CI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_UNKNOWN,
+		.tuner_name = "UNKNOWN",
+		.board_name = "VP3051",
+		.fw_name    = "DTTNXT"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_NXT200x,
+		.tuner_name = "NXT200x",
+		.board_name = "VP3220",
+		.fw_name    = "ATSCDI"
+	},
+
+	{
+		.tuner_type = TUNER_TYPE_NXT200x,
+		.tuner_name = "NXT200x",
+		.board_name = "VP3250",
+		.fw_name    = "ATSCAD"
+	},
+};
+
 /*
 	Known cards list
 	Satellite
@@ -608,7 +773,8 @@
 		.offset = 0,
 		.dst_type =  DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 
 	{
@@ -616,15 +782,17 @@
 		.offset = 0,
 		.dst_type =  DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 
 	{
 		.device_id = "DST-030",
 		.offset =  0,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 
 	{
@@ -633,7 +801,8 @@
 		.dst_type = DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
 		.dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
-							 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
+							 | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO,
+		.tuner_type = TUNER_TYPE_MULTI
 	 },
 
 	{
@@ -641,57 +810,63 @@
 		.offset =  0,
 		.dst_type = DST_TYPE_IS_SAT,
 		.type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/*	obsolete	*/
 
 	{
 		.device_id = "DST-CI",
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-		.dst_feature = DST_TYPE_HAS_CA
+		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
 	},	/*	An OEM board	*/
 
 	{
 		.device_id = "DSTMCI",
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT,
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF,
 		.dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
-							| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
+							| DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC,
+		.tuner_type = TUNER_TYPE_MULTI
 	},
 
 	{
 		.device_id = "DSTFCI",
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_SAT,
-		.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1,
+		.dst_feature = 0,
+		.tuner_type = 0
 	},	/* unknown to vendor	*/
 
 	{
 		.device_id = "DCT-CI",
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_CABLE,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
-							| DST_TYPE_HAS_FW_2,
-		.dst_feature = DST_TYPE_HAS_CA
+		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1	| DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
 	},
 
 	{
 		.device_id = "DCTNEW",
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_CABLE,
-		.type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE,
+		.dst_feature = 0,
+		.tuner_type = 0
 	},
 
 	{
 		.device_id = "DTT-CI",
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_TERR,
-		.type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE,
-		.dst_feature = DST_TYPE_HAS_CA
+		.type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF,
+		.dst_feature = DST_TYPE_HAS_CA,
+		.tuner_type = 0
 	},
 
 	{
@@ -699,7 +874,8 @@
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_TERR,
 		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},
 
 	{
@@ -707,7 +883,8 @@
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_TERR,
 		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = DST_TYPE_HAS_ANALOG
+		.dst_feature = DST_TYPE_HAS_ANALOG,
+		.tuner_type = 0
 	},
 
 	{
@@ -715,15 +892,17 @@
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_ATSC,
 		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0
+		.dst_feature = 0,
+		.tuner_type = 0
 	},
 
 	{
 		.device_id = "ATSCAD",
 		.offset = 1,
 		.dst_type = DST_TYPE_IS_ATSC,
-		.type_flags = DST_TYPE_HAS_FW_2,
-		.dst_feature = 0
+		.type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+		.dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG,
+		.tuner_type = 0
 	},
 
 	{ }
@@ -768,6 +947,9 @@
 
 static int dst_card_type(struct dst_state *state)
 {
+	int j;
+	struct tuner_types *p_tuner_list = NULL;
+
 	u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 	get_type[7] = dst_check_sum(get_type, 7);
 	if (dst_command(state, get_type, 8) < 0) {
@@ -775,9 +957,17 @@
 		return -1;
 	}
 	memset(&state->card_info, '\0', 8);
-	memcpy(&state->card_info, &state->rxbuffer, 8);
+	memcpy(&state->card_info, &state->rxbuffer, 7);
 	dprintk(verbose, DST_ERROR, 1, "Device Model=[%s]", &state->card_info[0]);
 
+	for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+		if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) {
+			state->tuner_type = p_tuner_list->tuner_type;
+			dprintk(verbose, DST_ERROR, 1, "DST has [%s] tuner, tuner type=[%d]",
+				p_tuner_list->tuner_name, p_tuner_list->tuner_type);
+		}
+	}
+
 	return 0;
 }
 
@@ -790,12 +980,64 @@
 		return -1;
 	}
 	memset(&state->vendor, '\0', 8);
-	memcpy(&state->vendor, &state->rxbuffer, 8);
+	memcpy(&state->vendor, &state->rxbuffer, 7);
 	dprintk(verbose, DST_ERROR, 1, "Vendor=[%s]", &state->vendor[0]);
 
 	return 0;
 }
 
+static void debug_dst_buffer(struct dst_state *state)
+{
+	int i;
+
+	if (verbose > 2) {
+		printk("%s: [", __func__);
+		for (i = 0; i < 8; i++)
+			printk(" %02x", state->rxbuffer[i]);
+		printk("]\n");
+	}
+}
+
+static int dst_check_stv0299(struct dst_state *state)
+{
+	u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	check_stv0299[7] = dst_check_sum(check_stv0299, 7);
+	if (dst_command(state, check_stv0299, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x04] failed");
+		return -1;
+	}
+	debug_dst_buffer(state);
+
+	if (memcmp(&check_stv0299, &state->rxbuffer, 8)) {
+		dprintk(verbose, DST_ERROR, 1, "Found a STV0299 NIM");
+		state->tuner_type = TUNER_TYPE_STV0299;
+		return 0;
+	}
+
+	return -1;
+}
+
+static int dst_check_mb86a15(struct dst_state *state)
+{
+	u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+	check_mb86a15[7] = dst_check_sum(check_mb86a15, 7);
+	if (dst_command(state, check_mb86a15, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Cmd=[0x10], failed");
+		return -1;
+	}
+	debug_dst_buffer(state);
+
+	if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) {
+		dprintk(verbose, DST_ERROR, 1, "Found a MB86A15 NIM");
+		state->tuner_type = TUNER_TYPE_MB86A15;
+		return 0;
+	}
+
+	return -1;
+}
+
 static int dst_get_tuner_info(struct dst_state *state)
 {
 	u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -803,60 +1045,59 @@
 
 	get_tuner_1[7] = dst_check_sum(get_tuner_1, 7);
 	get_tuner_2[7] = dst_check_sum(get_tuner_2, 7);
+	dprintk(verbose, DST_ERROR, 1, "DST TYpe = MULTI FE");
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-		if (dst_command(state, get_tuner_2, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-			return -1;
+		if (dst_command(state, get_tuner_1, 8) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Cmd=[0x13], Unsupported");
+			goto force;
 		}
 	} else {
-		if (dst_command(state, get_tuner_1, 8) < 0) {
-			dprintk(verbose, DST_INFO, 1, "Unsupported Command");
-			return -1;
+		if (dst_command(state, get_tuner_2, 8) < 0) {
+			dprintk(verbose, DST_INFO, 1, "Cmd=[0xb], Unsupported");
+			goto force;
 		}
 	}
 	memset(&state->board_info, '\0', 8);
 	memcpy(&state->board_info, &state->rxbuffer, 8);
 	if (state->type_flags & DST_TYPE_HAS_MULTI_FE) {
-		if (state->board_info[1] == 0x0b) {
-			if (state->type_flags & DST_TYPE_HAS_TS204)
-				state->type_flags &= ~DST_TYPE_HAS_TS204;
-			state->type_flags |= DST_TYPE_HAS_NEWTUNE;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=188");
-		} else {
-			if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-				state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
-			state->type_flags |= DST_TYPE_HAS_TS204;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=204");
-		}
-	} else {
-		if (state->board_info[0] == 0xbc) {
-			if (state->type_flags & DST_TYPE_HAS_TS204)
-				state->type_flags &= ~DST_TYPE_HAS_TS204;
-			state->type_flags |= DST_TYPE_HAS_NEWTUNE;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=188, Daughterboard=[%d]", state->board_info[1]);
+		dprintk(verbose, DST_ERROR, 1, "DST type has TS=188");
+	}
+	if (state->board_info[0] == 0xbc) {
+		if (state->type_flags != DST_TYPE_IS_ATSC)
+			state->type_flags |= DST_TYPE_HAS_TS188;
+		else
+			state->type_flags |= DST_TYPE_HAS_NEWTUNE_2;
 
-		} else if (state->board_info[0] == 0xcc) {
-			if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-				state->type_flags &= ~DST_TYPE_HAS_NEWTUNE;
-			state->type_flags |= DST_TYPE_HAS_TS204;
-			dprintk(verbose, DST_INFO, 1, "DST type has TS=204 Daughterboard=[%d]", state->board_info[1]);
+		if (state->board_info[1] == 0x01) {
+			state->dst_hw_cap |= DST_TYPE_HAS_DBOARD;
+			dprintk(verbose, DST_ERROR, 1, "DST has Daughterboard");
 		}
 	}
 
 	return 0;
+force:
+	if (!strncmp(state->fw_name, "DCT-CI", 6)) {
+		state->type_flags |= DST_TYPE_HAS_TS204;
+		dprintk(verbose, DST_ERROR, 1, "Forcing [%s] to TS188", state->fw_name);
+	}
+
+	return -1;
 }
 
 static int dst_get_device_id(struct dst_state *state)
 {
 	u8 reply;
 
-	int i;
-	struct dst_types *p_dst_type;
+	int i, j;
+	struct dst_types *p_dst_type = NULL;
+	struct tuner_types *p_tuner_list = NULL;
+
 	u8 use_dst_type = 0;
 	u32 use_type_flags = 0;
 
 	static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
 
+	state->tuner_type = 0;
 	device_type[7] = dst_check_sum(device_type, 7);
 
 	if (write_dst(state, device_type, FIXED_COMM))
@@ -888,8 +1129,34 @@
 
 			/*	Card capabilities	*/
 			state->dst_hw_cap = p_dst_type->dst_feature;
-			dprintk(verbose, DST_ERROR, 1, "Recognise [%s]\n", p_dst_type->device_id);
-
+			dprintk(verbose, DST_ERROR, 1, "Recognise [%s]", p_dst_type->device_id);
+			strncpy(&state->fw_name[0], p_dst_type->device_id, 6);
+			/*	Multiple tuners		*/
+			if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) {
+				switch (use_dst_type) {
+				case DST_TYPE_IS_SAT:
+					/*	STV0299 check	*/
+					if (dst_check_stv0299(state) < 0) {
+						dprintk(verbose, DST_ERROR, 1, "Unsupported");
+						state->tuner_type = TUNER_TYPE_MB86A15;
+					}
+					break;
+				default:
+					break;
+				}
+				if (dst_check_mb86a15(state) < 0)
+					dprintk(verbose, DST_ERROR, 1, "Unsupported");
+			/*	Single tuner		*/
+			} else {
+				state->tuner_type = p_dst_type->tuner_type;
+			}
+			for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) {
+				if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) &&
+					p_tuner_list->tuner_type == state->tuner_type) {
+					dprintk(verbose, DST_ERROR, 1, "[%s] has a [%s]",
+						p_dst_type->device_id, p_tuner_list->tuner_name);
+				}
+			}
 			break;
 		}
 	}
@@ -900,10 +1167,10 @@
 		use_dst_type = DST_TYPE_IS_SAT;
 		use_type_flags = DST_TYPE_HAS_SYMDIV;
 	}
-	dst_type_print(use_dst_type);
+	dst_type_print(state, use_dst_type);
 	state->type_flags = use_type_flags;
 	state->dst_type = use_dst_type;
-	dst_type_flags_print(state->type_flags);
+	dst_type_flags_print(state);
 
 	return 0;
 }
@@ -911,15 +1178,15 @@
 static int dst_probe(struct dst_state *state)
 {
 	mutex_init(&state->dst_mutex);
-	if ((rdc_8820_reset(state)) < 0) {
-		dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
-		return -1;
-	}
-	if (dst_addons & DST_TYPE_HAS_CA)
+	if (dst_addons & DST_TYPE_HAS_CA) {
+		if ((rdc_8820_reset(state)) < 0) {
+			dprintk(verbose, DST_ERROR, 1, "RDC 8820 RESET Failed.");
+			return -1;
+		}
 		msleep(4000);
-	else
+	} else {
 		msleep(100);
-
+	}
 	if ((dst_comm_init(state)) < 0) {
 		dprintk(verbose, DST_ERROR, 1, "DST Initialization Failed.");
 		return -1;
@@ -931,7 +1198,6 @@
 	}
 	if (dst_get_mac(state) < 0) {
 		dprintk(verbose, DST_INFO, 1, "MAC: Unsupported command");
-		return 0;
 	}
 	if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) {
 		if (dst_get_tuner_info(state) < 0)
@@ -1048,6 +1314,10 @@
 			state->decode_lock = (state->rxbuffer[1]) ? 1 : 0;
 			state->decode_strength = state->rxbuffer[4] << 8;
 			state->decode_snr = state->rxbuffer[3] << 8;
+		} else if (state->dst_type == DST_TYPE_IS_ATSC) {
+			state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0;
+			state->decode_strength = state->rxbuffer[4] << 8;
+			state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3];
 		}
 		state->cur_jiff = jiffies;
 	}
@@ -1078,8 +1348,9 @@
 	state->diseq_flags &= ~(HAS_LOCK);
 	if (!dst_wait_dst_ready(state, NO_DELAY))
 		return -EIO;
-	if (state->type_flags & DST_TYPE_HAS_NEWTUNE)
-		/* how to get variable length reply ???? */
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		!(state->dst_type == DST_TYPE_IS_ATSC))
+
 		retval = read_dst(state, state->rx_tuna, 10);
 	else
 		retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
@@ -1087,7 +1358,10 @@
 		dprintk(verbose, DST_DEBUG, 1, "read not successful");
 		return retval;
 	}
-	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		!(state->dst_type == DST_TYPE_IS_CABLE) &&
+		!(state->dst_type == DST_TYPE_IS_ATSC)) {
+
 		if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
 			dprintk(verbose, DST_INFO, 1, "checksum failure ? ");
 			return -EIO;
@@ -1133,7 +1407,10 @@
 		dprintk(verbose, DST_DEBUG, 1, "DST Communication initialization failed.");
 		goto error;
 	}
-	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+//	if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
+	if ((state->type_flags & DST_TYPE_HAS_VLF) &&
+		(!(state->dst_type == DST_TYPE_IS_ATSC))) {
+
 		state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
 		retval = write_dst(state, &state->tx_tuna[0], 10);
 	} else {
@@ -1189,9 +1466,12 @@
 
 	if (state->dst_type != DST_TYPE_IS_SAT)
 		return 0;
-	if (cmd->msg_len == 0 || cmd->msg_len > 4)
+	if (cmd->msg_len > 0 && cmd->msg_len < 5)
+		memcpy(&paket[3], cmd->msg, cmd->msg_len);
+	else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5)
+		memcpy(&paket[2], cmd->msg, cmd->msg_len);
+	else
 		return -EINVAL;
-	memcpy(&paket[3], cmd->msg, cmd->msg_len);
 	paket[7] = dst_check_sum(&paket[0], 7);
 	dst_command(state, paket, 8);
 	return 0;
@@ -1287,8 +1567,9 @@
 	static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 };
 	static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 	static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
-	static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 	static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
+	static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 };
 
 	state->inversion = INVERSION_OFF;
 	state->voltage = SEC_VOLTAGE_13;
@@ -1298,11 +1579,13 @@
 	state->bandwidth = BANDWIDTH_7_MHZ;
 	state->cur_jiff = jiffies;
 	if (state->dst_type == DST_TYPE_IS_SAT)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204));
 	else if (state->dst_type == DST_TYPE_IS_TERR)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204));
 	else if (state->dst_type == DST_TYPE_IS_CABLE)
-		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_NEWTUNE) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+		memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204));
+	else if (state->dst_type == DST_TYPE_IS_ATSC)
+		memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner));
 
 	return 0;
 }
@@ -1341,7 +1624,36 @@
 	return 0;
 }
 
-static int dst_set_frontend(struct dvb_frontend* fe,
+static int dst_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
+{
+	struct dst_state *state = fe->demodulator_priv;
+
+	if (p != NULL) {
+		dst_set_freq(state, p->frequency);
+		dprintk(verbose, DST_DEBUG, 1, "Set Frequency=[%d]", p->frequency);
+
+		if (state->dst_type == DST_TYPE_IS_SAT) {
+			if (state->type_flags & DST_TYPE_HAS_OBS_REGS)
+				dst_set_inversion(state, p->inversion);
+			dst_set_fec(state, p->u.qpsk.fec_inner);
+			dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+			dst_set_polarization(state);
+			dprintk(verbose, DST_DEBUG, 1, "Set Symbolrate=[%d]", p->u.qpsk.symbol_rate);
+
+		} else if (state->dst_type == DST_TYPE_IS_TERR)
+			dst_set_bandwidth(state, p->u.ofdm.bandwidth);
+		else if (state->dst_type == DST_TYPE_IS_CABLE) {
+			dst_set_fec(state, p->u.qam.fec_inner);
+			dst_set_symbolrate(state, p->u.qam.symbol_rate);
+			dst_set_modulation(state, p->u.qam.modulation);
+		}
+		dst_write_tuna(fe);
+	}
+
+	return 0;
+}
+
+static int dst_tune_frontend(struct dvb_frontend* fe,
 			    struct dvb_frontend_parameters* p,
 			    unsigned int mode_flags,
 			    int *delay,
@@ -1378,6 +1690,11 @@
 	return 0;
 }
 
+static int dst_get_tuning_algo(struct dvb_frontend *fe)
+{
+	return dst_algo;
+}
+
 static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
 	struct dst_state *state = fe->demodulator_priv;
@@ -1408,6 +1725,7 @@
 static struct dvb_frontend_ops dst_dvbt_ops;
 static struct dvb_frontend_ops dst_dvbs_ops;
 static struct dvb_frontend_ops dst_dvbc_ops;
+static struct dvb_frontend_ops dst_atsc_ops;
 
 struct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
 {
@@ -1417,24 +1735,25 @@
 		return NULL;
 	}
 	/* determine settings based on type */
+	/* create dvb_frontend */
 	switch (state->dst_type) {
 	case DST_TYPE_IS_TERR:
-		memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
 		break;
 	case DST_TYPE_IS_CABLE:
-		memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
 		break;
 	case DST_TYPE_IS_SAT:
-		memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
+		break;
+	case DST_TYPE_IS_ATSC:
+		memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops));
 		break;
 	default:
 		dprintk(verbose, DST_ERROR, 1, "unknown DST type. please report to the LinuxTV.org DVB mailinglist.");
 		kfree(state);
 		return NULL;
 	}
-
-	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
 	state->frontend.demodulator_priv = state;
 
 	return state;				/*	Manu (DST is a card not a frontend)	*/
@@ -1455,8 +1774,10 @@
 
 	.release = dst_release,
 	.init = dst_init,
-	.tune = dst_set_frontend,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
 	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
 	.read_status = dst_read_status,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_snr = dst_read_snr,
@@ -1479,8 +1800,10 @@
 
 	.release = dst_release,
 	.init = dst_init,
-	.tune = dst_set_frontend,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
 	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
 	.read_status = dst_read_status,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_snr = dst_read_snr,
@@ -1506,13 +1829,38 @@
 
 	.release = dst_release,
 	.init = dst_init,
-	.tune = dst_set_frontend,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
 	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
 	.read_status = dst_read_status,
 	.read_signal_strength = dst_read_signal_strength,
 	.read_snr = dst_read_snr,
 };
 
-MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
+static struct dvb_frontend_ops dst_atsc_ops = {
+	.info = {
+		.name = "DST ATSC",
+		.type = FE_ATSC,
+		.frequency_stepsize = 62500,
+		.frequency_min = 510000000,
+		.frequency_max = 858000000,
+		.symbol_rate_min = 1000000,
+		.symbol_rate_max = 45000000,
+		.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
+	},
+
+	.release = dst_release,
+	.init = dst_init,
+	.tune = dst_tune_frontend,
+	.set_frontend = dst_set_frontend,
+	.get_frontend = dst_get_frontend,
+	.get_frontend_algo = dst_get_tuning_algo,
+	.read_status = dst_read_status,
+	.read_signal_strength = dst_read_signal_strength,
+	.read_snr = dst_read_snr,
+};
+
+MODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver");
 MODULE_AUTHOR("Jamie Honan, Manu Abraham");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
index f6b49a8..fa923b9 100644
--- a/drivers/media/dvb/bt8xx/dst_ca.c
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -68,6 +68,13 @@
 	return -EOPNOTSUPP;
 }
 
+static void put_command_and_length(u8 *data, int command, int length)
+{
+	data[0] = (command >> 16) & 0xff;
+	data[1] = (command >> 8) & 0xff;
+	data[2] = command & 0xff;
+	data[3] = length;
+}
 
 static void put_checksum(u8 *check_string, int length)
 {
@@ -124,15 +131,18 @@
 	u8 dst_ca_comm_err = 0;
 
 	while (dst_ca_comm_err < RETRIES) {
-		dst_comm_init(state);
 		dprintk(verbose, DST_CA_NOTICE, 1, " Put Command");
 		if (dst_ci_command(state, data, ca_string, len, read)) {	// If error
 			dst_error_recovery(state);
 			dst_ca_comm_err++; // work required here.
+		} else {
+			break;
 		}
-		break;
 	}
 
+	if(dst_ca_comm_err == RETRIES)
+		return -1;
+
 	return 0;
 }
 
@@ -140,6 +150,7 @@
 
 static int ca_get_app_info(struct dst_state *state)
 {
+	int length, str_length;
 	static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
 
 	put_checksum(&command[0], command[0]);
@@ -154,6 +165,68 @@
 		(state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
 	dprintk(verbose, DST_CA_INFO, 1, " ==================================================================================================");
 
+	// Transform dst message to correct application_info message
+	length = state->messages[5];
+	str_length = length - 6;
+	if (str_length < 0) {
+		str_length = 0;
+		dprintk(verbose, DST_CA_ERROR, 1, "Invalid string length returned in ca_get_app_info(). Recovering.");
+	}
+
+	// First, the command and length fields
+	put_command_and_length(&state->messages[0], CA_APP_INFO, length);
+
+	// Copy application_type, application_manufacturer and manufacturer_code
+	memcpy(&state->messages[4], &state->messages[7], 5);
+
+	// Set string length and copy string
+	state->messages[9] = str_length;
+	memcpy(&state->messages[10], &state->messages[12], str_length);
+
+	return 0;
+}
+
+static int ca_get_ca_info(struct dst_state *state)
+{
+	int srcPtr, dstPtr, i, num_ids;
+	static u8 slot_command[8] = {0x07, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0xff};
+	const int in_system_id_pos = 8, out_system_id_pos = 4, in_num_ids_pos = 7;
+
+	put_checksum(&slot_command[0], slot_command[0]);
+	if ((dst_put_ci(state, slot_command, sizeof (slot_command), state->messages, GET_REPLY)) < 0) {
+		dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !");
+		return -1;
+	}
+	dprintk(verbose, DST_CA_INFO, 1, " -->dst_put_ci SUCCESS !");
+
+	// Print raw data
+	dprintk(verbose, DST_CA_INFO, 0, " DST data = [");
+	for (i = 0; i < state->messages[0] + 1; i++) {
+		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x", state->messages[i]);
+	}
+	dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
+	// Set the command and length of the output
+	num_ids = state->messages[in_num_ids_pos];
+	if (num_ids >= 100) {
+		num_ids = 100;
+		dprintk(verbose, DST_CA_ERROR, 1, "Invalid number of ids (>100). Recovering.");
+	}
+	put_command_and_length(&state->messages[0], CA_INFO, num_ids * 2);
+
+	dprintk(verbose, DST_CA_INFO, 0, " CA_INFO = [");
+	srcPtr = in_system_id_pos;
+	dstPtr = out_system_id_pos;
+	for(i = 0; i < num_ids; i++) {
+		dprintk(verbose, DST_CA_INFO, 0, " 0x%02x%02x", state->messages[srcPtr + 0], state->messages[srcPtr + 1]);
+		// Append to output
+		state->messages[dstPtr + 0] = state->messages[srcPtr + 0];
+		state->messages[dstPtr + 1] = state->messages[srcPtr + 1];
+		srcPtr += 2;
+		dstPtr += 2;
+	}
+	dprintk(verbose, DST_CA_INFO, 0, "]\n");
+
 	return 0;
 }
 
@@ -174,7 +247,7 @@
 
 	dprintk(verbose, DST_CA_INFO, 1, " Slot cap = [%d]", slot_cap[7]);
 	dprintk(verbose, DST_CA_INFO, 0, "===================================\n");
-	for (i = 0; i < 8; i++)
+	for (i = 0; i < slot_cap[0] + 1; i++)
 		dprintk(verbose, DST_CA_INFO, 0, " %d", slot_cap[i]);
 	dprintk(verbose, DST_CA_INFO, 0, "\n");
 
@@ -260,6 +333,11 @@
 			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
 				return -EFAULT;
 			break;
+		case CA_INFO:
+			memcpy(p_ca_message->msg, state->messages, 128);
+			if (copy_to_user(arg, p_ca_message, sizeof (struct ca_msg)) )
+				return -EFAULT;
+			break;
 		}
 	}
 
@@ -302,7 +380,7 @@
 		rdc_reset_state(state);
 		return -1;
 	}
-	dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command succes.");
+	dprintk(verbose, DST_CA_NOTICE, 1, " DST-CI Command success.");
 
 	return 0;
 }
@@ -340,6 +418,7 @@
 	return 0;
 }
 
+
 static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
 {
 	u32 length = 0;
@@ -455,6 +534,16 @@
 			}
 			dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !");
 			break;
+		case CA_INFO_ENQUIRY:
+			dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information");
+
+			if ((ca_get_ca_info(state)) < 0) {
+				dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !");
+				result = -1;
+				goto free_mem_and_exit;
+			}
+			dprintk(verbose, DST_CA_INFO, 1, " -->CA_INFO_ENQUIRY Success !");
+			break;
 		}
 	}
 free_mem_and_exit:
@@ -473,18 +562,15 @@
 	void __user *arg = (void __user *)ioctl_arg;
 	int result = 0;
 
-	if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
+	p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
+	p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
+	p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL);
+	if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) {
 		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		return -ENOMEM;
+		result = -ENOMEM;
+		goto free_mem_and_exit;
 	}
-	if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
-		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		return -ENOMEM;
-	}
-	if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
-		dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure");
-		return -ENOMEM;
-	}
+
 	/*	We have now only the standard ioctl's, the driver is upposed to handle internals.	*/
 	switch (cmd) {
 	case CA_SEND_MSG:
@@ -582,7 +668,7 @@
 
 static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset)
 {
-	int bytes_read = 0;
+	ssize_t bytes_read = 0;
 
 	dprintk(verbose, DST_CA_DEBUG, 1, " Device read.");
 
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
index 51d4e04..0677b04 100644
--- a/drivers/media/dvb/bt8xx/dst_common.h
+++ b/drivers/media/dvb/bt8xx/dst_common.h
@@ -42,7 +42,7 @@
 #define DST_TYPE_IS_CABLE	2
 #define DST_TYPE_IS_ATSC	3
 
-#define DST_TYPE_HAS_NEWTUNE	1
+#define DST_TYPE_HAS_TS188	1
 #define DST_TYPE_HAS_TS204	2
 #define DST_TYPE_HAS_SYMDIV	4
 #define DST_TYPE_HAS_FW_1	8
@@ -52,6 +52,9 @@
 #define DST_TYPE_HAS_OBS_REGS	128
 #define DST_TYPE_HAS_INC_COUNT	256
 #define DST_TYPE_HAS_MULTI_FE	512
+#define DST_TYPE_HAS_NEWTUNE_2	1024
+#define DST_TYPE_HAS_DBOARD	2048
+#define DST_TYPE_HAS_VLF	4096
 
 /*	Card capability list	*/
 
@@ -64,6 +67,20 @@
 #define	DST_TYPE_HAS_ANALOG	64	/*	Analog inputs	*/
 #define DST_TYPE_HAS_SESSION	128
 
+#define TUNER_TYPE_MULTI	1
+#define TUNER_TYPE_UNKNOWN	2
+/*	DVB-S		*/
+#define TUNER_TYPE_L64724	4
+#define TUNER_TYPE_STV0299	8
+#define TUNER_TYPE_MB86A15	16
+
+/*	DVB-T		*/
+#define TUNER_TYPE_TDA10046	32
+
+/*	ATSC		*/
+#define TUNER_TYPE_NXT200x	64
+
+
 #define RDC_8820_PIO_0_DISABLE	0
 #define RDC_8820_PIO_0_ENABLE	1
 #define RDC_8820_INT		2
@@ -84,8 +101,6 @@
 
 	struct bt878* bt;
 
-	struct dvb_frontend_ops ops;
-
 	/* configuration settings */
 	const struct dst_config* config;
 
@@ -121,8 +136,17 @@
 	u8 card_info[8];
 	u8 vendor[8];
 	u8 board_info[8];
-
+	u32 tuner_type;
+	char *tuner_name;
 	struct mutex dst_mutex;
+	u8 fw_name[8];
+};
+
+struct tuner_types {
+	u32 tuner_type;
+	char *tuner_name;
+	char *board_name;
+	char *fw_name;
 };
 
 struct dst_types {
@@ -131,6 +155,7 @@
 	u8 dst_type;
 	u32 type_flags;
 	u32 dst_feature;
+	u32 tuner_type;
 };
 
 struct dst_config
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index ccc7b2e..b715b97 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -147,12 +147,15 @@
 	return 0;
 }
 
-static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int thomson_dtt7579_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
 	u32 div;
 	unsigned char bs = 0;
 	unsigned char cp = 0;
 
+	if (buf_len < 5)
+		return -EINVAL;
+
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
 	if (params->frequency < 542000000)
@@ -169,22 +172,25 @@
 	else
 		bs = 0x08;
 
-	pllbuf[0] = 0xc0; // Note: non-linux standard PLL i2c address
+	pllbuf[0] = 0x60;
 	pllbuf[1] = div >> 8;
 	pllbuf[2] = div & 0xff;
 	pllbuf[3] = cp;
 	pllbuf[4] = bs;
 
-	return 0;
+	return 5;
 }
 
 static struct mt352_config thomson_dtt7579_config = {
 	.demod_address = 0x0f,
 	.demod_init = thomson_dtt7579_demod_init,
-	.pll_set = thomson_dtt7579_pll_set,
 };
 
-static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static struct zl10353_config thomson_dtt7579_zl10353_config = {
+	.demod_address = 0x0f,
+};
+
+static int cx24108_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	u32 freq = params->frequency;
 
@@ -237,7 +243,7 @@
 	return 0;
 }
 
-static int pinnsat_pll_init(struct dvb_frontend* fe)
+static int pinnsat_tuner_init(struct dvb_frontend* fe)
 {
 	struct dvb_bt8xx_card *card = fe->dvb->priv;
 
@@ -247,7 +253,7 @@
 	return 0;
 }
 
-static int pinnsat_pll_sleep(struct dvb_frontend* fe)
+static int pinnsat_tuner_sleep(struct dvb_frontend* fe)
 {
 	struct dvb_bt8xx_card *card = fe->dvb->priv;
 
@@ -258,12 +264,9 @@
 
 static struct cx24110_config pctvsat_config = {
 	.demod_address = 0x55,
-	.pll_init = pinnsat_pll_init,
-	.pll_set = cx24108_pll_set,
-	.pll_sleep = pinnsat_pll_sleep,
 };
 
-static int microtune_mt7202dtf_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int microtune_mt7202dtf_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
 	u8 cfg, cpump, band_select;
@@ -297,6 +300,8 @@
 	data[2] = ((div >> 10) & 0x60) | cfg;
 	data[3] = (cpump << 6) | band_select;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(card->i2c_adapter, &msg, 1);
 	return (div * 166666 - 36000000);
 }
@@ -310,7 +315,6 @@
 
 static struct sp887x_config microtune_mt7202dtf_config = {
 	.demod_address = 0x70,
-	.pll_set = microtune_mt7202dtf_pll_set,
 	.request_firmware = microtune_mt7202dtf_request_firmware,
 };
 
@@ -337,12 +341,14 @@
 	return 0;
 }
 
-static int advbt771_samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int advbt771_samsung_tdtc9251dh0_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
 	u32 div;
 	unsigned char bs = 0;
 	unsigned char cp = 0;
 
+	if (buf_len < 5) return -EINVAL;
+
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
 	if (params->frequency < 150000000)
@@ -383,19 +389,18 @@
 	else
 		bs = 0x08;
 
-	pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
+	pllbuf[0] = 0x61;
 	pllbuf[1] = div >> 8;
 	pllbuf[2] = div & 0xff;
 	pllbuf[3] = cp;
 	pllbuf[4] = bs;
 
-	return 0;
+	return 5;
 }
 
 static struct mt352_config advbt771_samsung_tdtc9251dh0_config = {
 	.demod_address = 0x0f,
 	.demod_init = advbt771_samsung_tdtc9251dh0_demod_init,
-	.pll_set = advbt771_samsung_tdtc9251dh0_pll_set,
 };
 
 static struct dst_config dst_config = {
@@ -455,7 +460,7 @@
 	.sleep = or51211_sleep,
 };
 
-static int vp3021_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int vp3021_alps_tded4_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
 	u8 buf[4];
@@ -478,6 +483,8 @@
 	else
 		return -EINVAL;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(card->i2c_adapter, &msg, 1);
 	return 0;
 }
@@ -485,7 +492,6 @@
 static struct nxt6000_config vp3021_alps_tded4_config = {
 	.demod_address = 0x0a,
 	.clock_inversion = 1,
-	.pll_set = vp3021_alps_tded4_pll_set,
 };
 
 static int digitv_alps_tded4_demod_init(struct dvb_frontend* fe)
@@ -506,14 +512,17 @@
 	return 0;
 }
 
-static int digitv_alps_tded4_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+static int digitv_alps_tded4_tuner_calc_regs(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf, int buf_len)
 {
 	u32 div;
 	struct dvb_ofdm_parameters *op = &params->u.ofdm;
 
+	if (buf_len < 5)
+		return -EINVAL;
+
 	div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
 
-	pllbuf[0] = 0xc2;
+	pllbuf[0] = 0x61;
 	pllbuf[1] = (div >> 8) & 0x7F;
 	pllbuf[2] = div & 0xFF;
 	pllbuf[3] = 0x85;
@@ -530,7 +539,7 @@
 	if (op->bandwidth == 8)
 		pllbuf[4] |= 0x04;
 
-	return 0;
+	return 5;
 }
 
 static void digitv_alps_tded4_reset(struct dvb_bt8xx_card *bt)
@@ -557,43 +566,18 @@
 static struct mt352_config digitv_alps_tded4_config = {
 	.demod_address = 0x0a,
 	.demod_init = digitv_alps_tded4_demod_init,
-	.pll_set = digitv_alps_tded4_pll_set,
 };
 
-static int tdvs_tua6034_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int tdvs_tua6034_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct dvb_bt8xx_card *card = (struct dvb_bt8xx_card *) fe->dvb->priv;
-	u8 buf[4];
-	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-	int err;
-
-	dvb_pll_configure(&dvb_pll_tdvs_tua6034, buf, params->frequency, 0);
-	dprintk("%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
-	if ((err = i2c_transfer(card->i2c_adapter, &msg, 1)) != 1) {
-		printk(KERN_WARNING "dvb-bt8xx: %s error "
-			"(addr %02x <- %02x, err = %i)\n",
-			__FUNCTION__, buf[0], buf[1], err);
-		if (err < 0)
-			return err;
-		else
-			return -EREMOTEIO;
-	}
-
-	/* Set the Auxiliary Byte. */
-	buf[2] &= ~0x20;
-	buf[2] |= 0x18;
-	buf[3] = 0x50;
-	i2c_transfer(card->i2c_adapter, &msg, 1);
-
-	return 0;
+	return lg_h06xf_pll_set(fe, card->i2c_adapter, params);
 }
 
 static struct lgdt330x_config tdvs_tua6034_config = {
 	.demod_address    = 0x0e,
 	.demod_chip       = LGDT3303,
 	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-	.pll_set          = tdvs_tua6034_pll_set,
 };
 
 static void lgdt330x_reset(struct dvb_bt8xx_card *bt)
@@ -617,17 +601,25 @@
 	switch(type) {
 	case BTTV_BOARD_DVICO_DVBT_LITE:
 		card->fe = mt352_attach(&thomson_dtt7579_config, card->i2c_adapter);
+
+		if (card->fe == NULL)
+			card->fe = zl10353_attach(&thomson_dtt7579_zl10353_config,
+						  card->i2c_adapter);
+
 		if (card->fe != NULL) {
-			card->fe->ops->info.frequency_min = 174000000;
-			card->fe->ops->info.frequency_max = 862000000;
+			card->fe->ops.tuner_ops.calc_regs = thomson_dtt7579_tuner_calc_regs;
+			card->fe->ops.info.frequency_min = 174000000;
+			card->fe->ops.info.frequency_max = 862000000;
 		}
 		break;
 
 	case BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE:
 		lgdt330x_reset(card);
 		card->fe = lgdt330x_attach(&tdvs_tua6034_config, card->i2c_adapter);
-		if (card->fe != NULL)
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.set_params = tdvs_tua6034_tuner_set_params;
 			dprintk ("dvb_bt8xx: lgdt330x detected\n");
+		}
 		break;
 
 	case BTTV_BOARD_NEBULA_DIGITV:
@@ -640,6 +632,7 @@
 		digitv_alps_tded4_reset(card);
 		card->fe = nxt6000_attach(&vp3021_alps_tded4_config, card->i2c_adapter);
 		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.set_params = vp3021_alps_tded4_tuner_set_params;
 			dprintk ("dvb_bt8xx: an nxt6000 was detected on your digitv card\n");
 			break;
 		}
@@ -648,19 +641,25 @@
 		digitv_alps_tded4_reset(card);
 		card->fe = mt352_attach(&digitv_alps_tded4_config, card->i2c_adapter);
 
-		if (card->fe != NULL)
+		if (card->fe != NULL) {
+			card->fe->ops.tuner_ops.calc_regs = digitv_alps_tded4_tuner_calc_regs;
 			dprintk ("dvb_bt8xx: an mt352 was detected on your digitv card\n");
+		}
 		break;
 
 	case BTTV_BOARD_AVDVBT_761:
 		card->fe = sp887x_attach(&microtune_mt7202dtf_config, card->i2c_adapter);
+		if (card->fe) {
+			card->fe->ops.tuner_ops.set_params = microtune_mt7202dtf_tuner_set_params;
+		}
 		break;
 
 	case BTTV_BOARD_AVDVBT_771:
 		card->fe = mt352_attach(&advbt771_samsung_tdtc9251dh0_config, card->i2c_adapter);
 		if (card->fe != NULL) {
-			card->fe->ops->info.frequency_min = 174000000;
-			card->fe->ops->info.frequency_max = 862000000;
+			card->fe->ops.tuner_ops.calc_regs = advbt771_samsung_tdtc9251dh0_tuner_calc_regs;
+			card->fe->ops.info.frequency_min = 174000000;
+			card->fe->ops.info.frequency_max = 862000000;
 		}
 		break;
 
@@ -687,6 +686,11 @@
 
 	case BTTV_BOARD_PINNACLESAT:
 		card->fe = cx24110_attach(&pctvsat_config, card->i2c_adapter);
+		if (card->fe) {
+			card->fe->ops.tuner_ops.init = pinnsat_tuner_init;
+			card->fe->ops.tuner_ops.sleep = pinnsat_tuner_sleep;
+			card->fe->ops.tuner_ops.set_params = cx24108_tuner_set_params;
+		}
 		break;
 
 	case BTTV_BOARD_PC_HDTV:
@@ -703,8 +707,8 @@
 	else
 		if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
 			printk("dvb-bt8xx: Frontend registration failed!\n");
-			if (card->fe->ops->release)
-				card->fe->ops->release(card->fe);
+			if (card->fe->ops.release)
+				card->fe->ops.release(card->fe);
 			card->fe = NULL;
 		}
 }
@@ -713,7 +717,7 @@
 {
 	int result;
 
-	if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE)) < 0) {
+	if ((result = dvb_register_adapter(&card->dvb_adapter, card->card_name, THIS_MODULE, &card->bt->dev->dev)) < 0) {
 		printk("dvb_bt8xx: dvb_register_adapter failed (errno = %d)\n", result);
 		return result;
 	}
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 00dd9fa..4745a90 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -37,6 +37,8 @@
 #include "cx24110.h"
 #include "or51211.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
+#include "zl10353.h"
 
 struct dvb_bt8xx_card {
 	struct mutex lock;
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig
index 6018fcd..b5cdd57 100644
--- a/drivers/media/dvb/cinergyT2/Kconfig
+++ b/drivers/media/dvb/cinergyT2/Kconfig
@@ -64,7 +64,7 @@
 config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
 	bool "Register the onboard IR Remote Control Receiver as Input Device"
 	depends on DVB_CINERGYT2_TUNING
-	default "yes"
+	default y
 	help
 	  Enable this option if you want to use the onboard Infrared Remote
 	  Control Receiver as Linux-Input device.
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 9325d03..1b89536 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -544,15 +544,19 @@
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct cinergyt2 *cinergyt2 = dvbdev->priv;
+       unsigned int mask = 0;
 
 	if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
 		return -ERESTARTSYS;
 
 	poll_wait(file, &cinergyt2->poll_wq, wait);
 
+       if (cinergyt2->pending_fe_events != 0)
+		mask |= (POLLIN | POLLRDNORM | POLLPRI);
+
 	mutex_unlock(&cinergyt2->sem);
 
-	return (POLLIN | POLLRDNORM | POLLPRI);
+       return mask;
 }
 
 
@@ -902,7 +906,7 @@
 		return -ENOMEM;
 	}
 
-	if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) {
+	if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE, &cinergyt2->udev->dev)) < 0) {
 		kfree(cinergyt2);
 		return err;
 	}
diff --git a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile
index 7adb50c..1105465 100644
--- a/drivers/media/dvb/dvb-core/Makefile
+++ b/drivers/media/dvb/dvb-core/Makefile
@@ -2,8 +2,8 @@
 # Makefile for the kernel DVB device drivers.
 #
 
-dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \
-		dvb_ca_en50221.o dvb_frontend.o \
-		dvb_net.o dvb_ringbuffer.o
+dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o 	\
+		dvb_ca_en50221.o dvb_frontend.o 		\
+		dvb_net.o dvb_ringbuffer.o dvb_math.o
 
 obj-$(CONFIG_DVB_CORE) += dvb-core.o
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 04578df..988499d 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -872,9 +872,6 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
-	case DMX_GET_EVENT:
-		break;
-
 	case DMX_GET_PES_PIDS:
 		if (!dmxdev->demux->get_pes_pids) {
 			ret = -EINVAL;
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index 00347a7..2a03bf5 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -1060,8 +1060,18 @@
 				break;
 
 			case DVB_CA_SLOTSTATE_VALIDATE:
-				if (dvb_ca_en50221_parse_attributes(ca, slot)
-				    != 0) {
+				if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
+					/* we need this extra check for annoying interfaces like the budget-av */
+					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+					    (ca->pub->poll_slot_status)) {
+						int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+							dvb_ca_en50221_thread_update_delay(ca);
+							break;
+						}
+					}
+
 					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
 					       ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
@@ -1108,6 +1118,17 @@
 
 			case DVB_CA_SLOTSTATE_LINKINIT:
 				if (dvb_ca_en50221_link_init(ca, slot) != 0) {
+					/* we need this extra check for annoying interfaces like the budget-av */
+					if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
+					    (ca->pub->poll_slot_status)) {
+						int status = ca->pub->poll_slot_status(ca->pub, slot, 0);
+						if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
+							ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
+							dvb_ca_en50221_thread_update_delay(ca);
+							break;
+						}
+					}
+
 					printk("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num);
 					ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 					dvb_ca_en50221_thread_update_delay(ca);
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 83ec5e0..fcff5ea 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -473,7 +473,7 @@
 			goto bailout;
 		}
 		memcpy(&demux->tsbuf[i], buf, j);
-		if ((demux->tsbuf[0] == 0x47) | (demux->tsbuf[0] == 0xB8)) {
+		if ((demux->tsbuf[0] == 0x47) || (demux->tsbuf[0] == 0xB8)) {
 			memcpy(tmppack, demux->tsbuf, 188);
 			if (tmppack[0] == 0xB8)
 				tmppack[0] = 0x47;
@@ -484,7 +484,7 @@
 	}
 
 	while (p < count) {
-		if ((buf[p] == 0x47) | (buf[p] == 0xB8)) {
+		if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
 			if (count - p >= 204) {
 				memcpy(tmppack, &buf[p], 188);
 				if (tmppack[0] == 0xB8)
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index a051790..5e8bb41a 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -56,7 +56,7 @@
 module_param(dvb_override_tune_delay, int, 0644);
 MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
 module_param(dvb_powerdown_on_sleep, int, 0644);
-MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)");
+MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB voltage off on sleep (default)");
 
 #define dprintk if (dvb_frontend_debug) printk
 
@@ -72,6 +72,8 @@
 #define FESTATE_SEARCHING_FAST (FESTATE_TUNING_FAST | FESTATE_ZIGZAG_FAST)
 #define FESTATE_SEARCHING_SLOW (FESTATE_TUNING_SLOW | FESTATE_ZIGZAG_SLOW)
 #define FESTATE_LOSTLOCK (FESTATE_ZIGZAG_FAST | FESTATE_ZIGZAG_SLOW)
+
+#define FE_ALGO_HW		1
 /*
  * FESTATE_IDLE. No tuning parameters have been supplied and the loop is idling.
  * FESTATE_RETUNE. Parameters have been supplied, but we have not yet performed the first tune.
@@ -151,8 +153,8 @@
 		sizeof (struct dvb_frontend_parameters));
 
 	if (status & FE_HAS_LOCK)
-		if (fe->ops->get_frontend)
-			fe->ops->get_frontend(fe, &e->parameters);
+		if (fe->ops.get_frontend)
+			fe->ops.get_frontend(fe, &e->parameters);
 
 	events->eventw = wp;
 
@@ -211,10 +213,15 @@
 {
 	dprintk ("DVB: initialising frontend %i (%s)...\n",
 		 fe->dvb->num,
-		 fe->ops->info.name);
+		 fe->ops.info.name);
 
-	if (fe->ops->init)
-		fe->ops->init(fe);
+	if (fe->ops.init)
+		fe->ops.init(fe);
+	if (fe->ops.tuner_ops.init) {
+		fe->ops.tuner_ops.init(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 }
 
 void dvb_frontend_reinitialise(struct dvb_frontend *fe)
@@ -259,7 +266,7 @@
 	u32 original_frequency = fepriv->parameters.frequency;
 
 	/* are we using autoinversion? */
-	autoinversion = ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+	autoinversion = ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
 			 (fepriv->parameters.inversion == INVERSION_AUTO));
 
 	/* setup parameters correctly */
@@ -329,8 +336,8 @@
 	fepriv->parameters.frequency += fepriv->lnb_drift;
 	if (autoinversion)
 		fepriv->parameters.inversion = fepriv->inversion;
-	if (fe->ops->set_frontend)
-		fe->ops->set_frontend(fe, &fepriv->parameters);
+	if (fe->ops.set_frontend)
+		fe->ops.set_frontend(fe, &fepriv->parameters);
 
 	fepriv->parameters.frequency = original_frequency;
 	fepriv->parameters.inversion = original_inversion;
@@ -354,8 +361,8 @@
 	/* in SCAN mode, we just set the frontend when asked and leave it alone */
 	if (fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT) {
 		if (fepriv->state & FESTATE_RETUNE) {
-			if (fe->ops->set_frontend)
-				fe->ops->set_frontend(fe, &fepriv->parameters);
+			if (fe->ops.set_frontend)
+				fe->ops.set_frontend(fe, &fepriv->parameters);
 			fepriv->state = FESTATE_TUNED;
 		}
 		fepriv->delay = 3*HZ;
@@ -367,8 +374,8 @@
 	if (fepriv->state & FESTATE_RETUNE) {
 		s = 0;
 	} else {
-		if (fe->ops->read_status)
-			fe->ops->read_status(fe, &s);
+		if (fe->ops.read_status)
+			fe->ops.read_status(fe, &s);
 		if (s != fepriv->status) {
 			dvb_frontend_add_event(fe, s);
 			fepriv->status = s;
@@ -381,7 +388,7 @@
 		fepriv->state = FESTATE_TUNED;
 
 		/* if we're tuned, then we have determined the correct inversion */
-		if ((!(fe->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
+		if ((!(fe->ops.info.caps & FE_CAN_INVERSION_AUTO)) &&
 		    (fepriv->parameters.inversion == INVERSION_AUTO)) {
 			fepriv->parameters.inversion = fepriv->inversion;
 		}
@@ -405,7 +412,7 @@
 	/* don't actually do anything if we're in the LOSTLOCK state,
 	 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
 	if ((fepriv->state & FESTATE_LOSTLOCK) &&
-	    (fe->ops->info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
+	    (fe->ops.info.caps & FE_CAN_RECOVER) && (fepriv->max_drift == 0)) {
 		dvb_frontend_swzigzag_update_delay(fepriv, s & FE_HAS_LOCK);
 		return;
 	}
@@ -540,39 +547,45 @@
 		if (fepriv->reinitialise) {
 			dvb_frontend_init(fe);
 			if (fepriv->tone != -1) {
-				fe->ops->set_tone(fe, fepriv->tone);
+				fe->ops.set_tone(fe, fepriv->tone);
 			}
 			if (fepriv->voltage != -1) {
-				fe->ops->set_voltage(fe, fepriv->voltage);
+				fe->ops.set_voltage(fe, fepriv->voltage);
 			}
 			fepriv->reinitialise = 0;
 		}
 
 		/* do an iteration of the tuning loop */
-		if (fe->ops->tune) {
-			/* have we been asked to retune? */
-			params = NULL;
-			if (fepriv->state & FESTATE_RETUNE) {
-				params = &fepriv->parameters;
-				fepriv->state = FESTATE_TUNED;
-			}
+		if (fe->ops.get_frontend_algo) {
+			if (fe->ops.get_frontend_algo(fe) == FE_ALGO_HW) {
+				/* have we been asked to retune? */
+				params = NULL;
+				if (fepriv->state & FESTATE_RETUNE) {
+					params = &fepriv->parameters;
+					fepriv->state = FESTATE_TUNED;
+				}
 
-			fe->ops->tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
-			if (s != fepriv->status) {
-				dvb_frontend_add_event(fe, s);
-				fepriv->status = s;
+				fe->ops.tune(fe, params, fepriv->tune_mode_flags, &fepriv->delay, &s);
+				if (s != fepriv->status) {
+					dvb_frontend_add_event(fe, s);
+					fepriv->status = s;
+				}
 			}
-		} else {
+		} else
 			dvb_frontend_swzigzag(fe);
-		}
 	}
 
 	if (dvb_shutdown_timeout) {
 		if (dvb_powerdown_on_sleep)
-			if (fe->ops->set_voltage)
-				fe->ops->set_voltage(fe, SEC_VOLTAGE_OFF);
-		if (fe->ops->sleep)
-			fe->ops->sleep(fe);
+			if (fe->ops.set_voltage)
+				fe->ops.set_voltage(fe, SEC_VOLTAGE_OFF);
+		if (fe->ops.tuner_ops.sleep) {
+			fe->ops.tuner_ops.sleep(fe);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (fe->ops.sleep)
+			fe->ops.sleep(fe);
 	}
 
 	fepriv->thread_pid = 0;
@@ -724,7 +737,7 @@
 	switch (cmd) {
 	case FE_GET_INFO: {
 		struct dvb_frontend_info* info = parg;
-		memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));
+		memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
 
 		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
 		 * do it, it is done for it. */
@@ -744,58 +757,58 @@
 			break;
 		}
 
-		if (fe->ops->read_status)
-			err = fe->ops->read_status(fe, status);
+		if (fe->ops.read_status)
+			err = fe->ops.read_status(fe, status);
 		break;
 	}
 	case FE_READ_BER:
-		if (fe->ops->read_ber)
-			err = fe->ops->read_ber(fe, (__u32*) parg);
+		if (fe->ops.read_ber)
+			err = fe->ops.read_ber(fe, (__u32*) parg);
 		break;
 
 	case FE_READ_SIGNAL_STRENGTH:
-		if (fe->ops->read_signal_strength)
-			err = fe->ops->read_signal_strength(fe, (__u16*) parg);
+		if (fe->ops.read_signal_strength)
+			err = fe->ops.read_signal_strength(fe, (__u16*) parg);
 		break;
 
 	case FE_READ_SNR:
-		if (fe->ops->read_snr)
-			err = fe->ops->read_snr(fe, (__u16*) parg);
+		if (fe->ops.read_snr)
+			err = fe->ops.read_snr(fe, (__u16*) parg);
 		break;
 
 	case FE_READ_UNCORRECTED_BLOCKS:
-		if (fe->ops->read_ucblocks)
-			err = fe->ops->read_ucblocks(fe, (__u32*) parg);
+		if (fe->ops.read_ucblocks)
+			err = fe->ops.read_ucblocks(fe, (__u32*) parg);
 		break;
 
 
 	case FE_DISEQC_RESET_OVERLOAD:
-		if (fe->ops->diseqc_reset_overload) {
-			err = fe->ops->diseqc_reset_overload(fe);
+		if (fe->ops.diseqc_reset_overload) {
+			err = fe->ops.diseqc_reset_overload(fe);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 		}
 		break;
 
 	case FE_DISEQC_SEND_MASTER_CMD:
-		if (fe->ops->diseqc_send_master_cmd) {
-			err = fe->ops->diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
+		if (fe->ops.diseqc_send_master_cmd) {
+			err = fe->ops.diseqc_send_master_cmd(fe, (struct dvb_diseqc_master_cmd*) parg);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 		}
 		break;
 
 	case FE_DISEQC_SEND_BURST:
-		if (fe->ops->diseqc_send_burst) {
-			err = fe->ops->diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
+		if (fe->ops.diseqc_send_burst) {
+			err = fe->ops.diseqc_send_burst(fe, (fe_sec_mini_cmd_t) parg);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
 		}
 		break;
 
 	case FE_SET_TONE:
-		if (fe->ops->set_tone) {
-			err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg);
+		if (fe->ops.set_tone) {
+			err = fe->ops.set_tone(fe, (fe_sec_tone_mode_t) parg);
 			fepriv->tone = (fe_sec_tone_mode_t) parg;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
@@ -803,8 +816,8 @@
 		break;
 
 	case FE_SET_VOLTAGE:
-		if (fe->ops->set_voltage) {
-			err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg);
+		if (fe->ops.set_voltage) {
+			err = fe->ops.set_voltage(fe, (fe_sec_voltage_t) parg);
 			fepriv->voltage = (fe_sec_voltage_t) parg;
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
@@ -812,11 +825,11 @@
 		break;
 
 	case FE_DISHNETWORK_SEND_LEGACY_CMD:
-		if (fe->ops->dishnetwork_send_legacy_command) {
-			err = fe->ops->dishnetwork_send_legacy_command(fe, (unsigned long) parg);
+		if (fe->ops.dishnetwork_send_legacy_command) {
+			err = fe->ops.dishnetwork_send_legacy_command(fe, (unsigned long) parg);
 			fepriv->state = FESTATE_DISEQC;
 			fepriv->status = 0;
-		} else if (fe->ops->set_voltage) {
+		} else if (fe->ops.set_voltage) {
 			/*
 			 * NOTE: This is a fallback condition.  Some frontends
 			 * (stv0299 for instance) take longer than 8msec to
@@ -846,7 +859,7 @@
 			/* before sending a command, initialize by sending
 			 * a 32ms 18V to the switch
 			 */
-			fe->ops->set_voltage(fe, SEC_VOLTAGE_18);
+			fe->ops.set_voltage(fe, SEC_VOLTAGE_18);
 			dvb_frontend_sleep_until(&nexttime, 32000);
 
 			for (i = 0; i < 9; i++) {
@@ -854,7 +867,7 @@
 					do_gettimeofday(&tv[i + 1]);
 				if ((cmd & 0x01) != last) {
 					/* set voltage to (last ? 13V : 18V) */
-					fe->ops->set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+					fe->ops.set_voltage(fe, (last) ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
 					last = (last) ? 0 : 1;
 				}
 				cmd = cmd >> 1;
@@ -874,13 +887,13 @@
 		break;
 
 	case FE_DISEQC_RECV_SLAVE_REPLY:
-		if (fe->ops->diseqc_recv_slave_reply)
-			err = fe->ops->diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
+		if (fe->ops.diseqc_recv_slave_reply)
+			err = fe->ops.diseqc_recv_slave_reply(fe, (struct dvb_diseqc_slave_reply*) parg);
 		break;
 
 	case FE_ENABLE_HIGH_LNB_VOLTAGE:
-		if (fe->ops->enable_high_lnb_voltage)
-			err = fe->ops->enable_high_lnb_voltage(fe, (long) parg);
+		if (fe->ops.enable_high_lnb_voltage)
+			err = fe->ops.enable_high_lnb_voltage(fe, (long) parg);
 		break;
 
 	case FE_SET_FRONTEND: {
@@ -898,7 +911,7 @@
 			fepriv->parameters.inversion = INVERSION_AUTO;
 			fetunesettings.parameters.inversion = INVERSION_AUTO;
 		}
-		if (fe->ops->info.type == FE_OFDM) {
+		if (fe->ops.info.type == FE_OFDM) {
 			/* without hierachical coding code_rate_LP is irrelevant,
 			 * so we tolerate the otherwise invalid FEC_NONE setting */
 			if (fepriv->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
@@ -907,13 +920,13 @@
 		}
 
 		/* get frontend-specific tuning settings */
-		if (fe->ops->get_tune_settings && (fe->ops->get_tune_settings(fe, &fetunesettings) == 0)) {
+		if (fe->ops.get_tune_settings && (fe->ops.get_tune_settings(fe, &fetunesettings) == 0)) {
 			fepriv->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
 			fepriv->max_drift = fetunesettings.max_drift;
 			fepriv->step_size = fetunesettings.step_size;
 		} else {
 			/* default values */
-			switch(fe->ops->info.type) {
+			switch(fe->ops.info.type) {
 			case FE_QPSK:
 				fepriv->min_delay = HZ/20;
 				fepriv->step_size = fepriv->parameters.u.qpsk.symbol_rate / 16000;
@@ -928,11 +941,13 @@
 
 			case FE_OFDM:
 				fepriv->min_delay = HZ/20;
-				fepriv->step_size = fe->ops->info.frequency_stepsize * 2;
-				fepriv->max_drift = (fe->ops->info.frequency_stepsize * 2) + 1;
+				fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
+				fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
 				break;
 			case FE_ATSC:
-				printk("dvb-core: FE_ATSC not handled yet.\n");
+				fepriv->min_delay = HZ/20;
+				fepriv->step_size = 0;
+				fepriv->max_drift = 0;
 				break;
 			}
 		}
@@ -952,9 +967,9 @@
 		break;
 
 	case FE_GET_FRONTEND:
-		if (fe->ops->get_frontend) {
+		if (fe->ops.get_frontend) {
 			memcpy (parg, &fepriv->parameters, sizeof (struct dvb_frontend_parameters));
-			err = fe->ops->get_frontend(fe, (struct dvb_frontend_parameters*) parg);
+			err = fe->ops.get_frontend(fe, (struct dvb_frontend_parameters*) parg);
 		}
 		break;
 
@@ -1067,7 +1082,7 @@
 
 	printk ("DVB: registering frontend %i (%s)...\n",
 		fe->dvb->num,
-		fe->ops->info.name);
+		fe->ops.info.name);
 
 	dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
 			     fe, DVB_DEVICE_FRONTEND);
@@ -1085,10 +1100,15 @@
 	mutex_lock(&frontend_mutex);
 	dvb_unregister_device (fepriv->dvbdev);
 	dvb_frontend_stop (fe);
-	if (fe->ops->release)
-		fe->ops->release(fe);
+	if (fe->ops.tuner_ops.release) {
+		fe->ops.tuner_ops.release(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+	if (fe->ops.release)
+		fe->ops.release(fe);
 	else
-		printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops->info.name);
+		printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->ops.info.name);
 	/* fe is invalid now */
 	kfree(fepriv);
 	mutex_unlock(&frontend_mutex);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h
index 5926a3b..2887e2b 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.h
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.h
@@ -49,6 +49,44 @@
 
 struct dvb_frontend;
 
+struct dvb_tuner_info {
+	char name[128];
+
+	u32 frequency_min;
+	u32 frequency_max;
+	u32 frequency_step;
+
+	u32 bandwidth_min;
+	u32 bandwidth_max;
+	u32 bandwidth_step;
+};
+
+struct dvb_tuner_ops {
+
+	struct dvb_tuner_info info;
+
+	int (*release)(struct dvb_frontend *fe);
+	int (*init)(struct dvb_frontend *fe);
+	int (*sleep)(struct dvb_frontend *fe);
+
+	/** This is for simple PLLs - set all parameters in one go. */
+	int (*set_params)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
+
+	/** This is support for demods like the mt352 - fills out the supplied buffer with what to write. */
+	int (*calc_regs)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p, u8 *buf, int buf_len);
+
+	int (*get_frequency)(struct dvb_frontend *fe, u32 *frequency);
+	int (*get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
+
+#define TUNER_STATUS_LOCKED 1
+	int (*get_status)(struct dvb_frontend *fe, u32 *status);
+
+	/** These are provided seperately from set_params in order to facilitate silicon
+	 * tuners which require sophisticated tuning loops, controlling each parameter seperately. */
+	int (*set_frequency)(struct dvb_frontend *fe, u32 frequency);
+	int (*set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
+};
+
 struct dvb_frontend_ops {
 
 	struct dvb_frontend_info info;
@@ -64,6 +102,8 @@
 		    unsigned int mode_flags,
 		    int *delay,
 		    fe_status_t *status);
+	/* get frontend tuning algorithm from the module */
+	int (*get_frontend_algo)(struct dvb_frontend *fe);
 
 	/* these two are only used for the swzigzag code */
 	int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
@@ -86,6 +126,8 @@
 	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, long arg);
 	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
 	int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
+
+	struct dvb_tuner_ops tuner_ops;
 };
 
 #define MAX_EVENT 8
@@ -100,9 +142,10 @@
 };
 
 struct dvb_frontend {
-	struct dvb_frontend_ops* ops;
+	struct dvb_frontend_ops ops;
 	struct dvb_adapter *dvb;
 	void* demodulator_priv;
+	void* tuner_priv;
 	void* frontend_priv;
 	void* misc_priv;
 };
diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c
new file mode 100644
index 0000000..beb7c93
--- /dev/null
+++ b/drivers/media/dvb/dvb-core/dvb_math.c
@@ -0,0 +1,145 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/bug.h>
+#include "dvb_math.h"
+
+static const unsigned short logtable[256] = {
+	0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7,
+	0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508,
+	0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6,
+	0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37,
+	0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f,
+	0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41,
+	0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1,
+	0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142,
+	0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68,
+	0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355,
+	0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c,
+	0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490,
+	0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3,
+	0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507,
+	0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe,
+	0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca,
+	0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c,
+	0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7,
+	0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c,
+	0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c,
+	0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a,
+	0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065,
+	0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730,
+	0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc,
+	0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469,
+	0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9,
+	0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c,
+	0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765,
+	0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83,
+	0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387,
+	0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973,
+	0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47
+};
+
+unsigned int intlog2(u32 value)
+{
+	/**
+	 *	returns: log2(value) * 2^24
+	 *	wrong result if value = 0 (log2(0) is undefined)
+	 */
+	unsigned int msb;
+	unsigned int logentry;
+	unsigned int significand;
+	unsigned int interpolation;
+
+	if (unlikely(value == 0)) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	/* first detect the msb (count begins at 0) */
+	msb = fls(value) - 1;
+
+	/**
+	 *	now we use a logtable after the following method:
+	 *
+	 *	log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24
+	 *	where x = msb and therefore 1 <= y < 2
+	 *	first y is determined by shifting the value left
+	 *	so that msb is bit 31
+	 *		0x00231f56 -> 0x8C7D5800
+	 *	the result is y * 2^31 -> "significand"
+	 *	then the highest 9 bits are used for a table lookup
+	 *	the highest bit is discarded because it's always set
+	 *	the highest nine bits in our example are 100011000
+	 *	so we would use the entry 0x18
+	 */
+	significand = value << (31 - msb);
+	logentry = (significand >> 23) & 0xff;
+
+	/**
+	 *	last step we do is interpolation because of the
+	 *	limitations of the log table the error is that part of
+	 *	the significand which isn't used for lookup then we
+	 *	compute the ratio between the error and the next table entry
+	 *	and interpolate it between the log table entry used and the
+	 *	next one the biggest error possible is 0x7fffff
+	 *	(in our example it's 0x7D5800)
+	 *	needed value for next table entry is 0x800000
+	 *	so the interpolation is
+	 *	(error / 0x800000) * (logtable_next - logtable_current)
+	 *	in the implementation the division is moved to the end for
+	 *	better accuracy there is also an overflow correction if
+	 *	logtable_next is 256
+	 */
+	interpolation = ((significand & 0x7fffff) *
+			((logtable[(logentry + 1) & 0xff] -
+			  logtable[logentry]) & 0xffff)) >> 15;
+
+	/* now we return the result */
+	return ((msb << 24) + (logtable[logentry] << 8) + interpolation);
+}
+EXPORT_SYMBOL(intlog2);
+
+unsigned int intlog10(u32 value)
+{
+	/**
+	 *	returns: log10(value) * 2^24
+	 *	wrong result if value = 0 (log10(0) is undefined)
+	 */
+	u64 log;
+
+	if (unlikely(value == 0)) {
+		WARN_ON(1);
+		return 0;
+	}
+
+	log = intlog2(value);
+
+	/**
+	 *	we use the following method:
+	 *	log10(x) = log2(x) * log10(2)
+	 */
+
+	return (log * 646456993) >> 31;
+}
+EXPORT_SYMBOL(intlog10);
diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h
new file mode 100644
index 0000000..aecc867
--- /dev/null
+++ b/drivers/media/dvb/dvb-core/dvb_math.h
@@ -0,0 +1,58 @@
+/*
+ * dvb-math provides some complex fixed-point math
+ * operations shared between the dvb related stuff
+ *
+ * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DVB_MATH_H
+#define __DVB_MATH_H
+
+#include <linux/types.h>
+
+/**
+ * computes log2 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog2(value) = intlog2(value * 2^x) - x * 2^24
+ *
+ * example: intlog2(8) will give 3 << 24 = 3 * 2^24
+ * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24
+ * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24
+ *
+ * @param value The value (must be != 0)
+ * @return log2(value) * 2^24
+ */
+extern unsigned int intlog2(u32 value);
+
+/**
+ * computes log10 of a value; the result is shifted left by 24 bits
+ *
+ * to use rational values you can use the following method:
+ *   intlog10(value) = intlog10(value * 10^x) - x * 2^24
+ *
+ * example: intlog10(1000) will give 3 << 24 = 3 * 2^24
+ *   due to the implementation intlog10(1000) might be not exactly 3 * 2^24
+ *
+ * look at intlog2 for similar examples
+ *
+ * @param value The value (must be != 0)
+ * @return log10(value) * 2^24
+ */
+extern unsigned int intlog10(u32 value);
+
+#endif
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 2f0f358..8859ab7 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -12,7 +12,7 @@
  *                          Hilmar Linder <hlinder@cosy.sbg.ac.at>
  *                      and Wolfram Stering <wstering@cosy.sbg.ac.at>
  *
- * ULE Decaps according to draft-ietf-ipdvb-ule-03.txt.
+ * ULE Decaps according to RFC 4326.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -42,6 +42,9 @@
  *                     Bugfixes and robustness improvements.
  *                     Filtering on dest MAC addresses, if present (D-Bit = 0)
  *                     ULE_DEBUG compile-time option.
+ * Apr 2006: cp v3:    Bugfixes and compliency with RFC 4326 (ULE) by
+ *                       Christian Praehauser <cpraehaus@cosy.sbg.ac.at>,
+ *                       Paris Lodron University of Salzburg.
  */
 
 /*
@@ -49,9 +52,6 @@
  *
  * Unloading does not work for 2.6.9 kernels: a refcount doesn't go to zero.
  *
- * TS_FEED callback is called once for every single TS cell although it is
- * registered (in dvb_net_feed_start()) for 100 TS cells (used for dvb_net_ule()).
- *
  */
 
 #include <linux/module.h>
@@ -89,6 +89,9 @@
 
 #ifdef ULE_DEBUG
 
+#define MAC_ADDR_PRINTFMT "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"
+#define MAX_ADDR_PRINTFMT_ARGS(macap) (macap)[0],(macap)[1],(macap)[2],(macap)[3],(macap)[4],(macap)[5]
+
 #define isprint(c)	((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))
 
 static void hexdump( const unsigned char *buf, unsigned short len )
@@ -214,6 +217,8 @@
 #define ULE_TEST	0
 #define ULE_BRIDGED	1
 
+#define ULE_OPTEXTHDR_PADDING 0
+
 static int ule_test_sndu( struct dvb_net_priv *p )
 {
 	return -1;
@@ -221,14 +226,28 @@
 
 static int ule_bridged_sndu( struct dvb_net_priv *p )
 {
-	/* BRIDGE SNDU handling sucks in draft-ietf-ipdvb-ule-03.txt.
-	 * This has to be the last extension header, otherwise it won't work.
-	 * Blame the authors!
+	struct ethhdr *hdr = (struct ethhdr*) p->ule_next_hdr;
+	if(ntohs(hdr->h_proto) < 1536) {
+		int framelen = p->ule_sndu_len - ((p->ule_next_hdr+sizeof(struct ethhdr)) - p->ule_skb->data);
+		/* A frame Type < 1536 for a bridged frame, introduces a LLC Length field. */
+		if(framelen != ntohs(hdr->h_proto)) {
+			return -1;
+		}
+	}
+	/* Note:
+	 * From RFC4326:
+	 *  "A bridged SNDU is a Mandatory Extension Header of Type 1.
+	 *   It must be the final (or only) extension header specified in the header chain of a SNDU."
+	 * The 'ule_bridged' flag will cause the extension header processing loop to terminate.
 	 */
 	p->ule_bridged = 1;
 	return 0;
 }
 
+static int ule_exthdr_padding(struct dvb_net_priv *p)
+{
+	return 0;
+}
 
 /** Handle ULE extension headers.
  *  Function is called after a successful CRC32 verification of an ULE SNDU to complete its decoding.
@@ -242,7 +261,8 @@
 		{ [0] = ule_test_sndu, [1] = ule_bridged_sndu, [2] = NULL,  };
 
 	/* Table of optional extension header handlers.  The header type is the index. */
-	static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) = { NULL, };
+	static int (*ule_optional_ext_handlers[255])( struct dvb_net_priv *p ) =
+		{ [0] = ule_exthdr_padding, [1] = NULL, };
 
 	int ext_len = 0;
 	unsigned char hlen = (p->ule_sndu_type & 0x0700) >> 8;
@@ -253,25 +273,31 @@
 		/* Mandatory extension header */
 		if (ule_mandatory_ext_handlers[htype]) {
 			ext_len = ule_mandatory_ext_handlers[htype]( p );
-			p->ule_next_hdr += ext_len;
-			if (! p->ule_bridged) {
-				p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
-				p->ule_next_hdr += 2;
-			} else {
-				p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)) );
-				/* This assures the extension handling loop will terminate. */
+			if(ext_len >= 0) {
+				p->ule_next_hdr += ext_len;
+				if (!p->ule_bridged) {
+					p->ule_sndu_type = ntohs(*(unsigned short *)p->ule_next_hdr);
+					p->ule_next_hdr += 2;
+				} else {
+					p->ule_sndu_type = ntohs(*(unsigned short *)(p->ule_next_hdr + ((p->ule_dbit ? 2 : 3) * ETH_ALEN)));
+					/* This assures the extension handling loop will terminate. */
+				}
 			}
+			// else: extension handler failed or SNDU should be discarded
 		} else
 			ext_len = -1;	/* SNDU has to be discarded. */
 	} else {
 		/* Optional extension header.  Calculate the length. */
-		ext_len = hlen << 2;
+		ext_len = hlen << 1;
 		/* Process the optional extension header according to its type. */
 		if (ule_optional_ext_handlers[htype])
 			(void)ule_optional_ext_handlers[htype]( p );
 		p->ule_next_hdr += ext_len;
-		p->ule_sndu_type = ntohs( *(unsigned short *)p->ule_next_hdr );
-		p->ule_next_hdr += 2;
+		p->ule_sndu_type = ntohs( *(unsigned short *)(p->ule_next_hdr-2) );
+		/*
+		 * note: the length of the next header type is included in the
+		 * length of THIS optional extension header
+		 */
 	}
 
 	return ext_len;
@@ -284,8 +310,14 @@
 	p->ule_next_hdr = p->ule_skb->data;
 	do {
 		l = handle_one_ule_extension( p );
-		if (l == -1) return -1;	/* Stop extension header processing and discard SNDU. */
+		if (l < 0)
+			return l;	/* Stop extension header processing and discard SNDU. */
 		total_ext_len += l;
+#ifdef ULE_DEBUG
+		dprintk("handle_ule_extensions: ule_next_hdr=%p, ule_sndu_type=%i, "
+			"l=%i, total_ext_len=%i\n", p->ule_next_hdr,
+			(int) p->ule_sndu_type, l, total_ext_len);
+#endif
 
 	} while (p->ule_sndu_type < 1536);
 
@@ -355,8 +387,8 @@
 				if (priv->ule_skb) {
 					dev_kfree_skb( priv->ule_skb );
 					/* Prepare for next SNDU. */
-					((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-					((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+					priv->stats.rx_errors++;
+					priv->stats.rx_frame_errors++;
 				}
 				reset_ule(priv);
 				priv->need_pusi = 1;
@@ -396,27 +428,25 @@
 			}
 		}
 
-		/* Check continuity counter. */
 		if (new_ts) {
+			/* Check continuity counter. */
 			if ((ts[3] & 0x0F) == priv->tscc)
 				priv->tscc = (priv->tscc + 1) & 0x0F;
 			else {
 				/* TS discontinuity handling: */
 				printk(KERN_WARNING "%lu: TS discontinuity: got %#x, "
-				       "exptected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
+				       "expected %#x.\n", priv->ts_count, ts[3] & 0x0F, priv->tscc);
 				/* Drop partly decoded SNDU, reset state, resync on PUSI. */
 				if (priv->ule_skb) {
 					dev_kfree_skb( priv->ule_skb );
 					/* Prepare for next SNDU. */
 					// reset_ule(priv);  moved to below.
-					((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-					((struct dvb_net_priv *) dev->priv)->stats.rx_frame_errors++;
+					priv->stats.rx_errors++;
+					priv->stats.rx_frame_errors++;
 				}
 				reset_ule(priv);
 				/* skip to next PUSI. */
 				priv->need_pusi = 1;
-				ts += TS_SZ;
-				priv->ts_count++;
 				continue;
 			}
 			/* If we still have an incomplete payload, but PUSI is
@@ -425,7 +455,7 @@
 			 * cells (continuity counter wrap). */
 			if (ts[1] & TS_PUSI) {
 				if (! priv->need_pusi) {
-					if (*from_where > 181) {
+					if (!(*from_where < (ts_remain-1)) || *from_where != priv->ule_sndu_remain) {
 						/* Pointer field is invalid.  Drop this TS cell and any started ULE SNDU. */
 						printk(KERN_WARNING "%lu: Invalid pointer "
 						       "field: %u.\n", priv->ts_count, *from_where);
@@ -438,8 +468,6 @@
 						}
 						reset_ule(priv);
 						priv->need_pusi = 1;
-						ts += TS_SZ;
-						priv->ts_count++;
 						continue;
 					}
 					/* Skip pointer field (we're processing a
@@ -452,8 +480,8 @@
 				if (priv->ule_sndu_remain > 183) {
 					/* Current SNDU lacks more data than there could be available in the
 					 * current TS cell. */
-					((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-					((struct dvb_net_priv *) dev->priv)->stats.rx_length_errors++;
+					priv->stats.rx_errors++;
+					priv->stats.rx_length_errors++;
 					printk(KERN_WARNING "%lu: Expected %d more SNDU bytes, but "
 					       "got PUSI (pf %d, ts_remain %d).  Flushing incomplete payload.\n",
 					       priv->ts_count, priv->ule_sndu_remain, ts[4], ts_remain);
@@ -492,9 +520,11 @@
 				} else
 					priv->ule_dbit = 0;
 
-				if (priv->ule_sndu_len > 32763) {
+				if (priv->ule_sndu_len < 5) {
 					printk(KERN_WARNING "%lu: Invalid ULE SNDU length %u. "
 					       "Resyncing.\n", priv->ts_count, priv->ule_sndu_len);
+					priv->stats.rx_errors++;
+					priv->stats.rx_length_errors++;
 					priv->ule_sndu_len = 0;
 					priv->need_pusi = 1;
 					new_ts = 1;
@@ -608,58 +638,103 @@
 				ule_dump = 1;
 #endif
 
-				((struct dvb_net_priv *) dev->priv)->stats.rx_errors++;
-				((struct dvb_net_priv *) dev->priv)->stats.rx_crc_errors++;
+				priv->stats.rx_errors++;
+				priv->stats.rx_crc_errors++;
 				dev_kfree_skb(priv->ule_skb);
 			} else {
 				/* CRC32 verified OK. */
-				/* Handle ULE Extension Headers. */
-				if (priv->ule_sndu_type < 1536) {
-					/* There is an extension header.  Handle it accordingly. */
-					int l = handle_ule_extensions( priv );
-					if (l < 0) {
-						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */
-						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
-						dev_kfree_skb( priv->ule_skb );
-						goto sndu_done;
-					}
-					skb_pull( priv->ule_skb, l );
-				}
+				u8 dest_addr[ETH_ALEN];
+				static const u8 bc_addr[ETH_ALEN] =
+					{ [ 0 ... ETH_ALEN-1] = 0xff };
 
 				/* CRC32 was OK. Remove it from skb. */
 				priv->ule_skb->tail -= 4;
 				priv->ule_skb->len -= 4;
 
-				/* Filter on receiver's destination MAC address, if present. */
 				if (!priv->ule_dbit) {
-					/* The destination MAC address is the next data in the skb. */
-					if (memcmp( priv->ule_skb->data, dev->dev_addr, ETH_ALEN )) {
-						/* MAC addresses don't match.  Drop SNDU. */
-						// printk( KERN_WARNING "Dropping SNDU, MAC address.\n" );
-						dev_kfree_skb( priv->ule_skb );
+					/*
+					 * The destination MAC address is the
+					 * next data in the skb.  It comes
+					 * before any extension headers.
+					 *
+					 * Check if the payload of this SNDU
+					 * should be passed up the stack.
+					 */
+					register int drop = 0;
+					if (priv->rx_mode != RX_MODE_PROMISC) {
+						if (priv->ule_skb->data[0] & 0x01) {
+							/* multicast or broadcast */
+							if (memcmp(priv->ule_skb->data, bc_addr, ETH_ALEN)) {
+								/* multicast */
+								if (priv->rx_mode == RX_MODE_MULTI) {
+									int i;
+									for(i = 0; i < priv->multi_num && memcmp(priv->ule_skb->data, priv->multi_macs[i], ETH_ALEN); i++)
+										;
+									if (i == priv->multi_num)
+										drop = 1;
+								} else if (priv->rx_mode != RX_MODE_ALL_MULTI)
+									drop = 1; /* no broadcast; */
+								/* else: all multicast mode: accept all multicast packets */
+							}
+							/* else: broadcast */
+						}
+						else if (memcmp(priv->ule_skb->data, dev->dev_addr, ETH_ALEN))
+							drop = 1;
+						/* else: destination address matches the MAC address of our receiver device */
+					}
+					/* else: promiscious mode; pass everything up the stack */
+
+					if (drop) {
+#ifdef ULE_DEBUG
+						dprintk("Dropping SNDU: MAC destination address does not match: dest addr: "MAC_ADDR_PRINTFMT", dev addr: "MAC_ADDR_PRINTFMT"\n",
+							MAX_ADDR_PRINTFMT_ARGS(priv->ule_skb->data), MAX_ADDR_PRINTFMT_ARGS(dev->dev_addr));
+#endif
+						dev_kfree_skb(priv->ule_skb);
 						goto sndu_done;
 					}
-					if (! priv->ule_bridged) {
-						skb_push( priv->ule_skb, ETH_ALEN + 2 );
-						ethh = (struct ethhdr *)priv->ule_skb->data;
-						memcpy( ethh->h_dest, ethh->h_source, ETH_ALEN );
-						memset( ethh->h_source, 0, ETH_ALEN );
-						ethh->h_proto = htons( priv->ule_sndu_type );
-					} else {
-						/* Skip the Receiver destination MAC address. */
-						skb_pull( priv->ule_skb, ETH_ALEN );
-					}
-				} else {
-					if (! priv->ule_bridged) {
-						skb_push( priv->ule_skb, ETH_HLEN );
-						ethh = (struct ethhdr *)priv->ule_skb->data;
-						memcpy( ethh->h_dest, dev->dev_addr, ETH_ALEN );
-						memset( ethh->h_source, 0, ETH_ALEN );
-						ethh->h_proto = htons( priv->ule_sndu_type );
-					} else {
-						/* skb is in correct state; nothing to do. */
+					else
+					{
+						memcpy(dest_addr,  priv->ule_skb->data, ETH_ALEN);
+						skb_pull(priv->ule_skb, ETH_ALEN);
 					}
 				}
+
+				/* Handle ULE Extension Headers. */
+				if (priv->ule_sndu_type < 1536) {
+					/* There is an extension header.  Handle it accordingly. */
+					int l = handle_ule_extensions(priv);
+					if (l < 0) {
+						/* Mandatory extension header unknown or TEST SNDU.  Drop it. */
+						// printk( KERN_WARNING "Dropping SNDU, extension headers.\n" );
+						dev_kfree_skb(priv->ule_skb);
+						goto sndu_done;
+					}
+					skb_pull(priv->ule_skb, l);
+				}
+
+				/*
+				 * Construct/assure correct ethernet header.
+				 * Note: in bridged mode (priv->ule_bridged !=
+				 * 0) we already have the (original) ethernet
+				 * header at the start of the payload (after
+				 * optional dest. address and any extension
+				 * headers).
+				 */
+
+				if (!priv->ule_bridged) {
+					skb_push(priv->ule_skb, ETH_HLEN);
+					ethh = (struct ethhdr *)priv->ule_skb->data;
+					if (!priv->ule_dbit) {
+						 /* dest_addr buffer is only valid if priv->ule_dbit == 0 */
+						memcpy(ethh->h_dest, dest_addr, ETH_ALEN);
+						memset(ethh->h_source, 0, ETH_ALEN);
+					}
+					else /* zeroize source and dest */
+						memset( ethh, 0, ETH_ALEN*2 );
+
+					ethh->h_proto = htons(priv->ule_sndu_type);
+				}
+				/* else:  skb is in correct state; nothing to do. */
 				priv->ule_bridged = 0;
 
 				/* Stuff into kernel's protocol stack. */
@@ -668,8 +743,8 @@
 				 * receive the packet anyhow. */
 				/* if (priv->ule_dbit && skb->pkt_type == PACKET_OTHERHOST)
 					priv->ule_skb->pkt_type = PACKET_HOST; */
-				((struct dvb_net_priv *) dev->priv)->stats.rx_packets++;
-				((struct dvb_net_priv *) dev->priv)->stats.rx_bytes += priv->ule_skb->len;
+				priv->stats.rx_packets++;
+				priv->stats.rx_bytes += priv->ule_skb->len;
 				netif_rx(priv->ule_skb);
 			}
 			sndu_done:
@@ -944,7 +1019,7 @@
 		dprintk("%s: start filtering\n", __FUNCTION__);
 		priv->secfeed->start_filtering(priv->secfeed);
 	} else if (priv->feedtype == DVB_NET_FEEDTYPE_ULE) {
-		struct timespec timeout = { 0, 30000000 }; // 30 msec
+		struct timespec timeout = { 0, 10000000 }; // 10 msec
 
 		/* we have payloads encapsulated in TS */
 		dprintk("%s: alloc tsfeed\n", __FUNCTION__);
@@ -956,10 +1031,13 @@
 
 		/* Set netdevice pointer for ts decaps callback. */
 		priv->tsfeed->priv = (void *)dev;
-		ret = priv->tsfeed->set(priv->tsfeed, priv->pid,
-					TS_PACKET, DMX_TS_PES_OTHER,
+		ret = priv->tsfeed->set(priv->tsfeed,
+					priv->pid, /* pid */
+					TS_PACKET, /* type */
+					DMX_TS_PES_OTHER, /* pes type */
 					32768,     /* circular buffer size */
-					timeout);
+					timeout    /* timeout */
+					);
 
 		if (ret < 0) {
 			printk("%s: could not set ts feed\n", dev->name);
@@ -1052,7 +1130,7 @@
 
 	dvb_net_feed_stop(dev);
 	priv->rx_mode = RX_MODE_UNI;
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 
 	if (dev->flags & IFF_PROMISC) {
 		dprintk("%s: promiscuous mode\n", dev->name);
@@ -1077,7 +1155,7 @@
 		}
 	}
 
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 	dvb_net_feed_start(dev);
 }
 
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 3852430..134c2bb 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -236,7 +236,7 @@
 			"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 
 	class_device_create(dvb_class, NULL, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
-			    NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+			    adap->device, "dvb%d.%s%d", adap->num, dnames[type], id);
 
 	dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 		adap->num, dnames[type], id, nums2minor(adap->num, type, id),
@@ -285,7 +285,7 @@
 }
 
 
-int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module, struct device *device)
 {
 	int num;
 
@@ -306,6 +306,7 @@
 	adap->num = num;
 	adap->name = name;
 	adap->module = module;
+	adap->device = device;
 
 	list_add_tail (&adap->list_head, &dvb_adapter_list);
 
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 74ed585..d7a976d 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -51,6 +51,8 @@
 	u8 proposed_mac [6];
 	void* priv;
 
+	struct device *device;
+
 	struct module *module;
 };
 
@@ -76,7 +78,7 @@
 };
 
 
-extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module);
+extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module, struct device *device);
 extern int dvb_unregister_adapter (struct dvb_adapter *adap);
 
 extern int dvb_register_device (struct dvb_adapter *adap,
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
index e388fb1..3bc6722 100644
--- a/drivers/media/dvb/dvb-usb/Kconfig
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -88,6 +88,7 @@
 	select DVB_CX22702
 	select DVB_LGDT330X
 	select DVB_MT352
+	select DVB_ZL10353
 	help
 	  Say Y here to support the Conexant USB2.0 hybrid reference design.
 	  Currently, only DVB and ATSC modes are supported, analog mode
@@ -130,6 +131,15 @@
 
 	  DVB-S USB2.0 receivers.
 
+config DVB_USB_GP8PSK
+	tristate "GENPIX 8PSK->USB module support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the
+	    GENPIX 8psk module
+
+	  DVB-S USB2.0 receivers.
+
 config DVB_USB_NOVA_T_USB2
 	tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
 	depends on DVB_USB
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
index 2dc9aad..9643f56 100644
--- a/drivers/media/dvb/dvb-usb/Makefile
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -7,6 +7,9 @@
 dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
 obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
 
+dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
+obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
+
 dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
 obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
 
diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c
index 1f0d3e9..ae23bdd 100644
--- a/drivers/media/dvb/dvb-usb/cxusb.c
+++ b/drivers/media/dvb/dvb-usb/cxusb.c
@@ -27,8 +27,10 @@
 
 #include "cx22702.h"
 #include "lgdt330x.h"
+#include "lg_h06xf.h"
 #include "mt352.h"
 #include "mt352_priv.h"
+#include "zl10353.h"
 
 /* debug */
 int dvb_usb_cxusb_debug;
@@ -322,32 +324,37 @@
 	return 0;
 }
 
+static int cxusb_lgh064f_tuner_set_params(struct dvb_frontend *fe,
+					  struct dvb_frontend_parameters *fep)
+{
+	struct dvb_usb_device *d = fe->dvb->priv;
+	return lg_h06xf_pll_set(fe, &d->i2c_adap, fep);
+}
+
 static struct cx22702_config cxusb_cx22702_config = {
 	.demod_address = 0x63,
 
 	.output_mode = CX22702_PARALLEL_OUTPUT,
-
-	.pll_init = dvb_usb_pll_init_i2c,
-	.pll_set  = dvb_usb_pll_set_i2c,
 };
 
 static struct lgdt330x_config cxusb_lgdt3303_config = {
 	.demod_address = 0x0e,
 	.demod_chip    = LGDT3303,
-	.pll_set       = dvb_usb_pll_set_i2c,
 };
 
 static struct mt352_config cxusb_dee1601_config = {
 	.demod_address = 0x0f,
 	.demod_init    = cxusb_dee1601_demod_init,
-	.pll_set       = dvb_usb_pll_set,
 };
 
-struct mt352_config cxusb_mt352_config = {
+static struct zl10353_config cxusb_zl10353_dee1601_config = {
+	.demod_address = 0x0f,
+};
+
+static struct mt352_config cxusb_mt352_config = {
 	/* used in both lgz201 and th7579 */
 	.demod_address = 0x0f,
 	.demod_init    = cxusb_mt352_demod_init,
-	.pll_set       = dvb_usb_pll_set,
 };
 
 /* Callbacks for DVB USB */
@@ -357,17 +364,10 @@
 	d->pll_addr = 0x61;
 	memcpy(d->pll_init, bpll, 4);
 	d->pll_desc = &dvb_pll_fmd1216me;
-	return 0;
-}
 
-static int cxusb_lgh064f_tuner_attach(struct dvb_usb_device *d)
-{
-	u8 bpll[4] = { 0x00, 0x00, 0x18, 0x50 };
-	/* bpll[2] : unset bit 3, set bits 4&5
-	   bpll[3] : 0x50 - digital, 0x20 - analog */
-	d->pll_addr = 0x61;
-	memcpy(d->pll_init, bpll, 4);
-	d->pll_desc = &dvb_pll_tdvs_tua6034;
+	d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+	d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
 	return 0;
 }
 
@@ -375,6 +375,7 @@
 {
 	d->pll_addr = 0x61;
 	d->pll_desc = &dvb_pll_thomson_dtt7579;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 }
 
@@ -382,6 +383,7 @@
 {
 	d->pll_addr = 0x61;
 	d->pll_desc = &dvb_pll_lg_z201;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 }
 
@@ -389,6 +391,13 @@
 {
 	d->pll_addr = 0x60;
 	d->pll_desc = &dvb_pll_thomson_dtt7579;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
+	return 0;
+}
+
+static int cxusb_lgdt3303_tuner_attach(struct dvb_usb_device *d)
+{
+	d->fe->ops.tuner_ops.set_params = cxusb_lgh064f_tuner_set_params;
 	return 0;
 }
 
@@ -439,7 +448,8 @@
 
 	cxusb_ctrl_msg(d,CMD_DIGITAL, NULL, 0, NULL, 0);
 
-	if ((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL)
+	if (((d->fe = mt352_attach(&cxusb_dee1601_config, &d->i2c_adap)) != NULL) ||
+	    ((d->fe = zl10353_attach(&cxusb_zl10353_dee1601_config, &d->i2c_adap)) != NULL))
 		return 0;
 
 	return -EIO;
@@ -555,7 +565,7 @@
 	.streaming_ctrl   = cxusb_streaming_ctrl,
 	.power_ctrl       = cxusb_bluebird_power_ctrl,
 	.frontend_attach  = cxusb_lgdt3303_frontend_attach,
-	.tuner_attach     = cxusb_lgh064f_tuner_attach,
+	.tuner_attach     = cxusb_lgdt3303_tuner_attach,
 
 	.i2c_algo         = &cxusb_i2c_algo,
 
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 2d52b76..abd75b4 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -173,11 +173,10 @@
 	struct dib3000_config demod_cfg;
 	struct dibusb_state *st = d->priv;
 
-	demod_cfg.pll_set = dvb_usb_pll_set_i2c;
-	demod_cfg.pll_init = dvb_usb_pll_init_i2c;
-
 	for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
 		if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
+			d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+			d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
 			d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 			return 0;
 		}
@@ -190,6 +189,10 @@
 {
 	d->pll_addr = 0x60;
 	d->pll_desc = &dvb_pll_env57h1xd5;
+
+	d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+	d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
+
 	return 0;
 }
 EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
index dd5a131..f4c45f3 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -20,11 +20,12 @@
 	struct dibusb_state *st = d->priv;
 
 	demod_cfg.demod_address = 0x8;
-	demod_cfg.pll_set = dvb_usb_pll_set_i2c;
-	demod_cfg.pll_init = dvb_usb_pll_init_i2c;
 
-	if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
+	if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL) {
+		d->fe->ops.tuner_ops.init = dvb_usb_tuner_init_i2c;
+		d->fe->ops.tuner_ops.set_params = dvb_usb_tuner_set_params_i2c;
 		return -ENODEV;
+	}
 
 	d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
 
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
index 91136c0..c14d9ef 100644
--- a/drivers/media/dvb/dvb-usb/digitv.c
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -112,27 +112,30 @@
 
 static struct mt352_config digitv_mt352_config = {
 	.demod_init = digitv_mt352_demod_init,
-	.pll_set = dvb_usb_pll_set,
 };
 
-static int digitv_nxt6000_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 	u8 b[5];
-	dvb_usb_pll_set(fe,fep,b);
+	dvb_usb_tuner_calc_regs(fe,fep,b, 5);
 	return digitv_ctrl_msg(d,USB_WRITE_TUNER,0,&b[1],4,NULL,0);
 }
 
 static struct nxt6000_config digitv_nxt6000_config = {
 	.clock_inversion = 1,
-	.pll_set = digitv_nxt6000_pll_set,
 };
 
 static int digitv_frontend_attach(struct dvb_usb_device *d)
 {
-	if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL ||
-		(d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL)
+	if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) != NULL) {
+		d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 		return 0;
+	}
+	if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) != NULL) {
+		d->fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
+		return 0;
+	}
 	return -EIO;
 }
 
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index cd21ddb..17413ad 100644
--- a/drivers/media/dvb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -18,7 +18,6 @@
 
 	struct dvb_frontend_parameters fep;
 	struct dvb_frontend frontend;
-	struct dvb_frontend_ops ops;
 };
 
 static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
@@ -163,16 +162,13 @@
 	deb_info("attaching frontend dtt200u\n");
 
 	state->d = d;
-	memcpy(&state->ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
 
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
-	goto success;
+	return &state->frontend;
 error:
 	return NULL;
-success:
-	return &state->frontend;
 }
 
 static struct dvb_frontend_ops dtt200u_fe_ops = {
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index 6fa9210..ec63170 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -82,7 +82,7 @@
 	int ret;
 
 	if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
-			d->owner)) < 0) {
+			d->owner, &d->udev->dev)) < 0) {
 		deb_info("dvb_register_adapter failed: error %d", ret);
 		goto err;
 	}
@@ -121,16 +121,15 @@
 
 	dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
 
-	goto success;
+	d->state |= DVB_USB_STATE_DVB;
+	return 0;
+
 err_dmx_dev:
 	dvb_dmx_release(&d->demux);
 err_dmx:
 	dvb_unregister_adapter(&d->dvb_adap);
 err:
 	return ret;
-success:
-	d->state |= DVB_USB_STATE_DVB;
-	return 0;
 }
 
 int dvb_usb_dvb_exit(struct dvb_usb_device *d)
@@ -184,13 +183,13 @@
 
 	/* re-assign sleep and wakeup functions */
 	if (d->fe != NULL) {
-		d->fe_init = d->fe->ops->init;   d->fe->ops->init  = dvb_usb_fe_wakeup;
-		d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
+		d->fe_init = d->fe->ops.init;   d->fe->ops.init  = dvb_usb_fe_wakeup;
+		d->fe_sleep = d->fe->ops.sleep; d->fe->ops.sleep = dvb_usb_fe_sleep;
 
 		if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
 			err("Frontend registration failed.");
-			if (d->fe->ops->release)
-				d->fe->ops->release(d->fe);
+			if (d->fe->ops.release)
+				d->fe->ops.release(d->fe);
 			d->fe = NULL;
 			return -ENODEV;
 		}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
index 9b25453..6b611a7 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -46,7 +46,7 @@
 	return 0;
 }
 
-int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
+int dvb_usb_tuner_init_i2c(struct dvb_frontend *fe)
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
@@ -63,6 +63,8 @@
 	deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
 			d->pll_init[2],d->pll_init[3]);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
 		err("tuner i2c write failed for pll_init.");
 		ret = -EREMOTEIO;
@@ -73,38 +75,42 @@
 		d->tuner_pass_ctrl(fe,0,d->pll_addr);
 	return ret;
 }
-EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_init_i2c);
 
-int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
+int dvb_usb_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 *b, int buf_len)
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 
+	if (buf_len != 5)
+		return -EINVAL;
 	if (d->pll_desc == NULL)
 		return 0;
 
 	deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
 
-	b[0] = d->pll_addr << 1;
+	b[0] = d->pll_addr;
 	dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
 
 	deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
 
-	return 0;
+	return 5;
 }
-EXPORT_SYMBOL(dvb_usb_pll_set);
+EXPORT_SYMBOL(dvb_usb_tuner_calc_regs);
 
-int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 	struct dvb_usb_device *d = fe->dvb->priv;
 	int ret = 0;
 	u8 b[5];
 	struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
 
-	dvb_usb_pll_set(fe,fep,b);
+	dvb_usb_tuner_calc_regs(fe,fep,b,5);
 
 	if (d->tuner_pass_ctrl)
 		d->tuner_pass_ctrl(fe,1,d->pll_addr);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
 		err("tuner i2c write failed for pll_set.");
 		ret = -EREMOTEIO;
@@ -116,4 +122,4 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
+EXPORT_SYMBOL(dvb_usb_tuner_set_params_i2c);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
index cb23904..9569891 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -31,6 +31,7 @@
 #define USB_VID_VISIONPLUS					0x13d3
 #define USB_VID_TWINHAN						0x1822
 #define USB_VID_ULTIMA_ELECTRONIC			0x05d8
+#define USB_VID_GENPIX					0x09c0
 
 /* Product IDs */
 #define USB_PID_ADSTECH_USB2_COLD			0xa333
@@ -104,5 +105,6 @@
 #define USB_PID_KYE_DVB_T_WARM				0x701f
 #define USB_PID_PCTV_200E					0x020e
 #define USB_PID_PCTV_400E					0x020f
-
+#define USB_PID_GENPIX_8PSK_COLD				0x0200
+#define USB_PID_GENPIX_8PSK_WARM				0x0201
 #endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
index fead958..4cf9f89 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb.h
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -330,9 +330,9 @@
 extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
 
 /* commonly used pll init and set functions */
-extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
-extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
-extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+extern int dvb_usb_tuner_init_i2c(struct dvb_frontend *);
+extern int dvb_usb_tuner_calc_regs(struct dvb_frontend *, struct dvb_frontend_parameters *, u8 *buf, int buf_len);
+extern int dvb_usb_tuner_set_params_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
 
 /* commonly used firmware download types and function */
 struct hexline {
diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
new file mode 100644
index 0000000..6ccbdc9
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c
@@ -0,0 +1,272 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+struct gp8psk_fe_state {
+	struct dvb_frontend fe;
+
+	struct dvb_usb_device *d;
+
+	u16 snr;
+
+	unsigned long next_snr_check;
+};
+
+static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+	u8 lock;
+
+	if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1))
+		return -EINVAL;
+
+	if (lock)
+		*status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER;
+	else
+		*status = 0;
+
+	return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+	(void) fe;
+	*ber = 0;
+	return 0;
+}
+
+/* not supported by this Frontend */
+static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+	(void) fe;
+	*unc = 0;
+	return 0;
+}
+
+static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+	u8 buf[2];
+
+	if (time_after(jiffies,st->next_snr_check)) {
+		gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2);
+		*snr = (int)(buf[1]) << 8 | buf[0];
+		/* snr is reported in dBu*256 */
+		/* snr / 38.4 ~= 100% strength */
+		/* snr * 17 returns 100% strength as 65535 */
+		if (*snr <= 3855)
+			*snr = (*snr<<4) + *snr; // snr * 17
+		else
+			*snr = 65535;
+		st->next_snr_check = jiffies + (10*HZ)/1000;
+	} else {
+		*snr = st->snr;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+	return gp8psk_fe_read_snr(fe, strength);
+}
+
+static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 800;
+	return 0;
+}
+
+static int gp8psk_fe_set_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	struct gp8psk_fe_state *state = fe->demodulator_priv;
+	u8 cmd[10];
+	u32 freq = fep->frequency * 1000;
+
+	cmd[4] = freq         & 0xff;
+	cmd[5] = (freq >> 8)  & 0xff;
+	cmd[6] = (freq >> 16) & 0xff;
+	cmd[7] = (freq >> 24) & 0xff;
+
+	switch(fe->ops.info.type) {
+	case FE_QPSK:
+		cmd[0] =  fep->u.qpsk.symbol_rate        & 0xff;
+		cmd[1] = (fep->u.qpsk.symbol_rate >>  8) & 0xff;
+		cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff;
+		cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff;
+		cmd[8] = ADV_MOD_DVB_QPSK;
+		cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/
+		break;
+	default:
+		// other modes are unsuported right now
+		cmd[0] = 0;
+		cmd[1] = 0;
+		cmd[2] = 0;
+		cmd[3] = 0;
+		cmd[8] = 0;
+		cmd[9] = 0;
+		break;
+	}
+
+	gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10);
+
+	state->next_snr_check = jiffies;
+
+	return 0;
+}
+
+static int gp8psk_fe_get_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	return 0;
+}
+
+
+static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe,
+				    struct dvb_diseqc_master_cmd *m)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+
+	deb_fe("%s\n",__FUNCTION__);
+
+	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0,
+			m->msg, m->msg_len)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe,
+				    fe_sec_mini_cmd_t burst)
+{
+	struct gp8psk_fe_state *st = fe->demodulator_priv;
+	u8 cmd;
+
+	deb_fe("%s\n",__FUNCTION__);
+
+	/* These commands are certainly wrong */
+	cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01;
+
+	if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0,
+			&cmd, 0)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
+{
+	struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+	if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE,
+		 (tone == SEC_TONE_ON), 0, NULL, 0)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+	struct gp8psk_fe_state* state = fe->demodulator_priv;
+
+	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE,
+			 voltage == SEC_VOLTAGE_18, 0, NULL, 0)) {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd)
+{
+	struct gp8psk_fe_state* state = fe->demodulator_priv;
+	u8 cmd = sw_cmd & 0x7f;
+
+	if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0,
+			NULL, 0)) {
+		return -EINVAL;
+	}
+	if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80),
+			0, NULL, 0)) {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void gp8psk_fe_release(struct dvb_frontend* fe)
+{
+	struct gp8psk_fe_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops gp8psk_fe_ops;
+
+struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d)
+{
+	struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL);
+	if (s == NULL)
+		goto error;
+
+	s->d = d;
+	memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops));
+	s->fe.demodulator_priv = s;
+
+	goto success;
+error:
+	return NULL;
+success:
+	return &s->fe;
+}
+
+
+static struct dvb_frontend_ops gp8psk_fe_ops = {
+	.info = {
+		.name			= "Genpix 8psk-USB DVB-S",
+		.type			= FE_QPSK,
+		.frequency_min		= 950000,
+		.frequency_max		= 2150000,
+		.frequency_stepsize	= 100,
+		.symbol_rate_min        = 1000000,
+		.symbol_rate_max        = 45000000,
+		.symbol_rate_tolerance  = 500,  /* ppm */
+		.caps = FE_CAN_INVERSION_AUTO |
+				FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+				FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+				FE_CAN_QPSK
+	},
+
+	.release = gp8psk_fe_release,
+
+	.init = NULL,
+	.sleep = NULL,
+
+	.set_frontend = gp8psk_fe_set_frontend,
+	.get_frontend = gp8psk_fe_get_frontend,
+	.get_tune_settings = gp8psk_fe_get_tune_settings,
+
+	.read_status = gp8psk_fe_read_status,
+	.read_ber = gp8psk_fe_read_ber,
+	.read_signal_strength = gp8psk_fe_read_signal_strength,
+	.read_snr = gp8psk_fe_read_snr,
+	.read_ucblocks = gp8psk_fe_read_unc_blocks,
+
+	.diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg,
+	.diseqc_send_burst = gp8psk_fe_send_diseqc_burst,
+	.set_tone = gp8psk_fe_set_tone,
+	.set_voltage = gp8psk_fe_set_voltage,
+	.dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd,
+};
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c
new file mode 100644
index 0000000..9a98f3f
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gp8psk.c
@@ -0,0 +1,256 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "gp8psk.h"
+
+/* debug */
+static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw";
+int dvb_usb_gp8psk_debug;
+module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)
+{
+	int ret = 0,try = 0;
+
+	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+		return ret;
+
+	while (ret >= 0 && ret != blen && try < 3) {
+		ret = usb_control_msg(d->udev,
+			usb_rcvctrlpipe(d->udev,0),
+			req,
+			USB_TYPE_VENDOR | USB_DIR_IN,
+			value,index,b,blen,
+			2000);
+		deb_info("reading number %d (ret: %d)\n",try,ret);
+		try++;
+	}
+
+	if (ret < 0 || ret != blen) {
+		warn("usb in operation failed.");
+		ret = -EIO;
+	} else
+		ret = 0;
+
+	deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+	debug_dump(b,blen,deb_xfer);
+
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
+}
+
+int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+			     u16 index, u8 *b, int blen)
+{
+	int ret;
+
+	deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);
+	debug_dump(b,blen,deb_xfer);
+
+	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
+		return ret;
+
+	if (usb_control_msg(d->udev,
+			usb_sndctrlpipe(d->udev,0),
+			req,
+			USB_TYPE_VENDOR | USB_DIR_OUT,
+			value,index,b,blen,
+			2000) != blen) {
+		warn("usb out operation failed.");
+		ret = -EIO;
+	} else
+		ret = 0;
+	mutex_unlock(&d->usb_mutex);
+
+	return ret;
+}
+
+static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
+{
+	int ret;
+	const struct firmware *fw = NULL;
+	u8 *ptr, *buf;
+	if ((ret = request_firmware(&fw, bcm4500_firmware,
+					&d->udev->dev)) != 0) {
+		err("did not find the bcm4500 firmware file. (%s) "
+			"Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+			bcm4500_firmware,ret);
+		return ret;
+	}
+
+	ret = -EINVAL;
+
+	if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0))
+		goto out_rel_fw;
+
+	info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware);
+
+	ptr = fw->data;
+	buf = kmalloc(512, GFP_KERNEL | GFP_DMA);
+
+	while (ptr[0] != 0xff) {
+		u16 buflen = ptr[0] + 4;
+		if (ptr + buflen >= fw->data + fw->size) {
+			err("failed to load bcm4500 firmware.");
+			goto out_free;
+		}
+		memcpy(buf, ptr, buflen);
+		if (dvb_usb_generic_write(d, buf, buflen)) {
+			err("failed to load bcm4500 firmware.");
+			goto out_free;
+		}
+		ptr += buflen;
+	}
+
+	ret = 0;
+
+out_free:
+	kfree(buf);
+out_rel_fw:
+	release_firmware(fw);
+
+	return ret;
+}
+
+static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 status, buf;
+	if (onoff) {
+		gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+		if (! (status & 0x01))  /* started */
+			if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1))
+				return -EINVAL;
+
+		if (! (status & 0x02)) /* BCM4500 firmware loaded */
+			if(gp8psk_load_bcm4500fw(d))
+				return EINVAL;
+
+		if (! (status & 0x04)) /* LNB Power */
+			if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0,
+					&buf, 1))
+				return EINVAL;
+
+		/* Set DVB mode */
+		if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0))
+			return -EINVAL;
+		gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1);
+	} else {
+		/* Turn off LNB power */
+		if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1))
+			return EINVAL;
+		/* Turn off 8psk power */
+		if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1))
+			return -EINVAL;
+
+	}
+	return 0;
+}
+
+
+static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0);
+}
+
+static int gp8psk_frontend_attach(struct dvb_usb_device *d)
+{
+	d->fe = gp8psk_fe_attach(d);
+
+	return 0;
+}
+
+static struct dvb_usb_properties gp8psk_properties;
+
+static int gp8psk_usb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL);
+}
+
+static struct usb_device_id gp8psk_usb_table [] = {
+	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) },
+	    { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) },
+	    { 0 },
+};
+MODULE_DEVICE_TABLE(usb, gp8psk_usb_table);
+
+static struct dvb_usb_properties gp8psk_properties = {
+	.caps = 0,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-gp8psk-01.fw",
+
+	.streaming_ctrl   = gp8psk_streaming_ctrl,
+	.power_ctrl       = gp8psk_power_ctrl,
+	.frontend_attach  = gp8psk_frontend_attach,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x82,
+		.u = {
+			.bulk = {
+				.buffersize = 8192,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{ .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver",
+		  .cold_ids = { &gp8psk_usb_table[0], NULL },
+		  .warm_ids = { &gp8psk_usb_table[1], NULL },
+		},
+		{ 0 },
+	}
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver gp8psk_usb_driver = {
+	.name		= "dvb_usb_gp8psk",
+	.probe		= gp8psk_usb_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= gp8psk_usb_table,
+};
+
+/* module stuff */
+static int __init gp8psk_usb_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&gp8psk_usb_driver))) {
+		err("usb_register failed. (%d)",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit gp8psk_usb_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&gp8psk_usb_driver);
+}
+
+module_init(gp8psk_usb_module_init);
+module_exit(gp8psk_usb_module_exit);
+
+MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>");
+MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h
new file mode 100644
index 0000000..3eba706
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/gp8psk.h
@@ -0,0 +1,79 @@
+/* DVB USB compliant Linux driver for the
+ *  - GENPIX 8pks/qpsk USB2.0 DVB-S module
+ *
+ * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com)
+ *
+ * Thanks to GENPIX for the sample code used to implement this module.
+ *
+ * This module is based off the vp7045 and vp702x modules
+ *
+ *	This program is free software; you can redistribute it and/or modify it
+ *	under the terms of the GNU General Public License as published by the Free
+ *	Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_GP8PSK_H_
+#define _DVB_USB_GP8PSK_H_
+
+#define DVB_USB_LOG_PREFIX "gp8psk"
+#include "dvb-usb.h"
+
+extern int dvb_usb_gp8psk_debug;
+#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args)
+#define deb_rc(args...)   dprintk(dvb_usb_gp8psk_debug,0x04,args)
+#define deb_fe(args...)   dprintk(dvb_usb_gp8psk_debug,0x08,args)
+/* gp8psk commands */
+
+/* Twinhan Vendor requests */
+#define TH_COMMAND_IN                     0xC0
+#define TH_COMMAND_OUT                    0xC1
+
+/* command bytes */
+#define GET_8PSK_CONFIG                 0x80
+#define SET_8PSK_CONFIG                 0x81
+#define ARM_TRANSFER                    0x85
+#define TUNE_8PSK                       0x86
+#define GET_SIGNAL_STRENGTH             0x87
+#define LOAD_BCM4500                    0x88
+#define BOOT_8PSK                       0x89
+#define START_INTERSIL                  0x8A
+#define SET_LNB_VOLTAGE                 0x8B
+#define SET_22KHZ_TONE                  0x8C
+#define SEND_DISEQC_COMMAND             0x8D
+#define SET_DVB_MODE                    0x8E
+#define SET_DN_SWITCH                   0x8F
+#define GET_SIGNAL_LOCK                 0x90
+
+/* Satellite modulation modes */
+#define ADV_MOD_DVB_QPSK 0     /* DVB-S QPSK */
+#define ADV_MOD_TURBO_QPSK 1   /* Turbo QPSK */
+#define ADV_MOD_TURBO_8PSK 2   /* Turbo 8PSK (also used for Trellis 8PSK) */
+#define ADV_MOD_TURBO_16QAM 3  /* Turbo 16QAM (also used for Trellis 8PSK) */
+
+#define ADV_MOD_DCII_C_QPSK 4  /* Digicipher II Combo */
+#define ADV_MOD_DCII_I_QPSK 5  /* Digicipher II I-stream */
+#define ADV_MOD_DCII_Q_QPSK 6  /* Digicipher II Q-stream */
+#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
+#define ADV_MOD_DSS_QPSK 8     /* DSS (DIRECTV) QPSK */
+#define ADV_MOD_DVB_BPSK 9     /* DVB-S BPSK */
+
+#define GET_USB_SPEED                     0x07
+ #define USB_SPEED_LOW                    0
+ #define USB_SPEED_FULL                   1
+ #define USB_SPEED_HIGH                   2
+
+#define RESET_FX2                         0x13
+
+#define FW_VERSION_READ                   0x0B
+#define VENDOR_STRING_READ                0x0C
+#define PRODUCT_STRING_READ               0x0D
+#define FW_BCD_VERSION_READ               0x14
+
+extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d);
+extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen);
+extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,
+			     u16 index, u8 *b, int blen);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
index 14f1911..97d74da 100644
--- a/drivers/media/dvb/dvb-usb/umt-010.c
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -57,7 +57,6 @@
 	memset(&umt_config,0,sizeof(struct mt352_config));
 	umt_config.demod_init = umt_mt352_demod_init;
 	umt_config.demod_address = 0xf;
-	umt_config.pll_set = dvb_usb_pll_set;
 
 	d->fe = mt352_attach(&umt_config, &d->i2c_adap);
 
@@ -68,6 +67,7 @@
 {
 	d->pll_addr = 0x61;
 	d->pll_desc = &dvb_pll_tua6034;
+	d->fe->ops.tuner_ops.calc_regs = dvb_usb_tuner_calc_regs;
 	return 0;
 }
 
diff --git a/drivers/media/dvb/dvb-usb/vp702x-fe.c b/drivers/media/dvb/dvb-usb/vp702x-fe.c
index 2a89f8c..d4da494 100644
--- a/drivers/media/dvb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp702x-fe.c
@@ -287,17 +287,16 @@
 		goto error;
 
 	s->d = d;
-	s->fe.ops = &vp702x_fe_ops;
+
+	memcpy(&s->fe.ops,&vp702x_fe_ops,sizeof(struct dvb_frontend_ops));
 	s->fe.demodulator_priv = s;
 
 	s->lnb_buf[1] = SET_LNB_POWER;
 	s->lnb_buf[3] = 0xff; /* 0=tone burst, 2=data burst, ff=off */
 
-	goto success;
+	return &s->fe;
 error:
 	return NULL;
-success:
-	return &s->fe;
 }
 
 
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
index 9999336..8452eef 100644
--- a/drivers/media/dvb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -23,8 +23,6 @@
 
 struct vp7045_fe_state {
 	struct dvb_frontend fe;
-	struct dvb_frontend_ops ops;
-
 	struct dvb_usb_device *d;
 };
 
@@ -151,15 +149,12 @@
 		goto error;
 
 	s->d = d;
-	memcpy(&s->ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
-	s->fe.ops = &s->ops;
+	memcpy(&s->fe.ops, &vp7045_fe_ops, sizeof(struct dvb_frontend_ops));
 	s->fe.demodulator_priv = s;
 
-	goto success;
+	return &s->fe;
 error:
 	return NULL;
-success:
-	return &s->fe;
 }
 
 
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 37d5e0a..0ef361f 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -157,7 +157,7 @@
 	help
 	  A DVB-C tuner module. Say Y when you want to support this frontend.
 
-comment "ATSC (North American/Korean Terresterial DTV) frontends"
+comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
 	depends on DVB_CORE
 
 config DVB_NXT200X
@@ -216,4 +216,20 @@
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 
+
+comment "Miscellaneous devices"
+	depends on DVB_CORE
+
+config DVB_LNBP21
+	tristate "LNBP21 SEC controller"
+	depends on DVB_CORE
+	help
+	  An SEC control chip.
+
+config DVB_ISL6421
+	tristate "ISL6421 SEC controller"
+	depends on DVB_CORE
+	help
+	  An SEC control chip.
+
 endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index d09b607..5222245 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -31,3 +31,5 @@
 obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
 obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
 obj-$(CONFIG_DVB_CX24123) += cx24123.o
+obj-$(CONFIG_DVB_LNBP21) += lnbp21.o
+obj-$(CONFIG_DVB_ISL6421) += isl6421.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
index 1708a1d..baeb311d 100644
--- a/drivers/media/dvb/frontends/bcm3510.c
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -48,7 +48,6 @@
 struct bcm3510_state {
 
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct bcm3510_config* config;
 	struct dvb_frontend frontend;
 
@@ -791,10 +790,9 @@
 
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
 	mutex_init(&state->hab_mutex);
diff --git a/drivers/media/dvb/frontends/bsbe1.h b/drivers/media/dvb/frontends/bsbe1.h
index 78573b2..d8f6573 100644
--- a/drivers/media/dvb/frontends/bsbe1.h
+++ b/drivers/media/dvb/frontends/bsbe1.h
@@ -89,12 +89,13 @@
 	return 0;
 }
 
-static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters* params)
+static int alps_bsbe1_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	int ret;
 	u8 data[4];
 	u32 div;
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+	struct i2c_adapter *i2c = fe->tuner_priv;
 
 	if ((params->frequency < 950000) || (params->frequency > 2150000))
 		return -EINVAL;
@@ -105,6 +106,8 @@
 	data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
 	data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	ret = i2c_transfer(i2c, &msg, 1);
 	return (ret != 1) ? -EIO : 0;
 }
@@ -117,7 +120,6 @@
 	.skip_reinit = 0,
 	.min_delay_ms = 100,
 	.set_symbol_rate = alps_bsbe1_set_symbol_rate,
-	.pll_set = alps_bsbe1_pll_set,
 };
 
 #endif
diff --git a/drivers/media/dvb/frontends/bsru6.h b/drivers/media/dvb/frontends/bsru6.h
index 2a5366c..e231cd8 100644
--- a/drivers/media/dvb/frontends/bsru6.h
+++ b/drivers/media/dvb/frontends/bsru6.h
@@ -101,11 +101,12 @@
 	return 0;
 }
 
-static int alps_bsru6_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
+static int alps_bsru6_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	u8 buf[4];
 	u32 div;
 	struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	struct i2c_adapter *i2c = fe->tuner_priv;
 
 	if ((params->frequency < 950000) || (params->frequency > 2150000))
 		return -EINVAL;
@@ -119,6 +120,8 @@
 	if (params->frequency > 1530000)
 		buf[3] = 0xc0;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(i2c, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -134,7 +137,6 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.min_delay_ms = 100,
 	.set_symbol_rate = alps_bsru6_set_symbol_rate,
-	.pll_set = alps_bsru6_pll_set,
 };
 
 #endif
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
index 755f774..3c7c09a 100644
--- a/drivers/media/dvb/frontends/cx22700.c
+++ b/drivers/media/dvb/frontends/cx22700.c
@@ -34,8 +34,6 @@
 
 	struct i2c_adapter* i2c;
 
-	struct dvb_frontend_ops ops;
-
 	const struct cx22700_config* config;
 
 	struct dvb_frontend frontend;
@@ -247,12 +245,6 @@
 
 	cx22700_writereg (state, 0x00, 0x01);
 
-	if (state->config->pll_init) {
-		cx22700_writereg (state, 0x0a, 0x00);  /* open i2c bus switch */
-		state->config->pll_init(fe);
-		cx22700_writereg (state, 0x0a, 0x01);  /* close i2c bus switch */
-	}
-
 	return 0;
 }
 
@@ -333,9 +325,11 @@
 	cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
 	cx22700_writereg (state, 0x00, 0x00);
 
-	cx22700_writereg (state, 0x0a, 0x00);  /* open i2c bus switch */
-	state->config->pll_set(fe, p);
-	cx22700_writereg (state, 0x0a, 0x01);  /* close i2c bus switch */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
 	cx22700_set_inversion (state, p->inversion);
 	cx22700_set_tps (state, &p->u.ofdm);
 	cx22700_writereg (state, 0x37, 0x01);  /* PAL loop filter off */
@@ -353,6 +347,17 @@
 	return cx22700_get_tps (state, &p->u.ofdm);
 }
 
+static int cx22700_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct cx22700_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return cx22700_writereg(state, 0x0a, 0x00);
+	} else {
+		return cx22700_writereg(state, 0x0a, 0x01);
+	}
+}
+
 static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
 	fesettings->min_delay_ms = 150;
@@ -381,13 +386,12 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check if the demod is there */
 	if (cx22700_readreg(state, 0x07) < 0) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx22700_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -413,6 +417,7 @@
 	.release = cx22700_release,
 
 	.init = cx22700_init,
+	.i2c_gate_ctrl = cx22700_i2c_gate_ctrl,
 
 	.set_frontend = cx22700_set_frontend,
 	.get_frontend = cx22700_get_frontend,
diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h
index c9145b4..dcd8979 100644
--- a/drivers/media/dvb/frontends/cx22700.h
+++ b/drivers/media/dvb/frontends/cx22700.h
@@ -29,10 +29,6 @@
 {
 	/* the demodulator's i2c address */
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 0fc899f..4106d46 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -40,8 +40,6 @@
 
 	struct i2c_adapter* i2c;
 
-	struct dvb_frontend_ops ops;
-
 	/* configuration settings */
 	const struct cx22702_config* config;
 
@@ -211,22 +209,10 @@
 	u8 val;
 	struct cx22702_state* state = fe->demodulator_priv;
 
-	/* set PLL */
-	cx22702_i2c_gate_ctrl(fe, 1);
-	if (state->config->pll_set) {
-		state->config->pll_set(fe, p);
-	} else if (state->config->pll_desc) {
-		u8 pllbuf[4];
-		struct i2c_msg msg = { .addr = state->config->pll_address,
-				       .buf = pllbuf, .len = 4 };
-		dvb_pll_configure(state->config->pll_desc, pllbuf,
-				  p->frequency,
-				  p->u.ofdm.bandwidth);
-		i2c_transfer(state->i2c, &msg, 1);
-	} else {
-		BUG();
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 	}
-	cx22702_i2c_gate_ctrl(fe, 0);
 
 	/* set inversion */
 	cx22702_set_inversion (state, p->inversion);
@@ -358,10 +344,6 @@
 
 	cx22702_writereg (state, 0xf8, (state->config->output_mode << 1) & 0x02);
 
-	/* init PLL */
-	if (state->config->pll_init)
-		state->config->pll_init(fe);
-
 	cx22702_i2c_gate_ctrl(fe, 0);
 
 	return 0;
@@ -495,7 +477,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
 	state->prevUCBlocks = 0;
 
 	/* check if the demod is there */
@@ -503,7 +484,7 @@
 		goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx22702_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -530,6 +511,7 @@
 	.release = cx22702_release,
 
 	.init = cx22702_init,
+	.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
 
 	.set_frontend = cx22702_set_tps,
 	.get_frontend = cx22702_get_frontend,
@@ -540,7 +522,6 @@
 	.read_signal_strength = cx22702_read_signal_strength,
 	.read_snr = cx22702_read_snr,
 	.read_ucblocks = cx22702_read_ucblocks,
-	.i2c_gate_ctrl = cx22702_i2c_gate_ctrl,
 };
 
 module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h
index 5633976..7f2f241 100644
--- a/drivers/media/dvb/frontends/cx22702.h
+++ b/drivers/media/dvb/frontends/cx22702.h
@@ -39,13 +39,6 @@
 #define CX22702_PARALLEL_OUTPUT 0
 #define CX22702_SERIAL_OUTPUT   1
 	u8 output_mode;
-
-	/* PLL maintenance */
-	u8 pll_address;
-	struct dvb_pll_desc *pll_desc;
-
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index f3edf8b..ce3c7398 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -36,8 +36,6 @@
 
 	struct i2c_adapter* i2c;
 
-	struct dvb_frontend_ops ops;
-
 	const struct cx24110_config* config;
 
 	struct dvb_frontend frontend;
@@ -250,7 +248,7 @@
 	static const u32 bands[]={5000000UL,15000000UL,90999000UL/2};
 	int i;
 
-dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
+	dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
 	if (srate>90999000UL/2)
 		srate=90999000UL/2;
 	if (srate<500000)
@@ -366,17 +364,6 @@
 		cx24110_writereg(state, cx24110_regdata[i].reg, cx24110_regdata[i].data);
 	};
 
-	if (state->config->pll_init) state->config->pll_init(fe);
-
-	return 0;
-}
-
-static int cx24110_sleep(struct dvb_frontend *fe)
-{
-	struct cx24110_state *state = fe->demodulator_priv;
-
-	if (state->config->pll_sleep)
-		  return state->config->pll_sleep(fe);
 	return 0;
 }
 
@@ -548,7 +535,12 @@
 {
 	struct cx24110_state *state = fe->demodulator_priv;
 
-	state->config->pll_set(fe, p);
+
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
 	cx24110_set_inversion (state, p->inversion);
 	cx24110_set_fec (state, p->u.qpsk.fec_inner);
 	cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -612,7 +604,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
 	state->lastber = 0;
 	state->lastbler = 0;
 	state->lastesn0 = 0;
@@ -622,7 +613,7 @@
 	if ((ret != 0x5a) && (ret != 0x69)) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx24110_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -651,7 +642,6 @@
 	.release = cx24110_release,
 
 	.init = cx24110_initfe,
-	.sleep = cx24110_sleep,
 	.set_frontend = cx24110_set_frontend,
 	.get_frontend = cx24110_get_frontend,
 	.read_status = cx24110_read_status,
diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h
index 609ac64..b354a64 100644
--- a/drivers/media/dvb/frontends/cx24110.h
+++ b/drivers/media/dvb/frontends/cx24110.h
@@ -31,11 +31,6 @@
 {
 	/* the demodulator's i2c address */
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-	int (*pll_sleep)(struct dvb_frontend* fe);
 };
 
 extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c
index 691dc84..f2f795c 100644
--- a/drivers/media/dvb/frontends/cx24123.c
+++ b/drivers/media/dvb/frontends/cx24123.c
@@ -41,14 +41,12 @@
 struct cx24123_state
 {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct cx24123_config* config;
 
 	struct dvb_frontend frontend;
 
 	u32 lastber;
 	u16 snr;
-	u8  lnbreg;
 
 	/* Some PLL specifics for tuning */
 	u32 VCAarg;
@@ -249,29 +247,6 @@
 	return 0;
 }
 
-static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data)
-{
-	u8 buf[] = { reg, data };
-	/* fixme: put the intersil addr int the config */
-	struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 };
-	int err;
-
-	if (debug>1)
-		printk("cx24123: %s:  writeln addr=0x08, reg 0x%02x, value 0x%02x\n",
-						__FUNCTION__,reg, data);
-
-	if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) {
-		printk("%s: writelnbreg error (err == %i, reg == 0x%02x,"
-			 " data == 0x%02x)\n", __FUNCTION__, err, reg, data);
-		return -EREMOTEIO;
-	}
-
-	/* cache the write, no way to read back */
-	state->lnbreg = data;
-
-	return 0;
-}
-
 static int cx24123_readreg(struct cx24123_state* state, u8 reg)
 {
 	int ret;
@@ -295,11 +270,6 @@
 	return b1[0];
 }
 
-static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg)
-{
-	return state->lnbreg;
-}
-
 static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion)
 {
 	u8 nom_reg = cx24123_readreg(state, 0x0e);
@@ -458,8 +428,8 @@
 	u8 pll_mult;
 
 	/*  check if symbol rate is within limits */
-	if ((srate > state->ops.info.symbol_rate_max) ||
-	    (srate < state->ops.info.symbol_rate_min))
+	if ((srate > state->frontend.ops.info.symbol_rate_max) ||
+	    (srate < state->frontend.ops.info.symbol_rate_min))
 		return -EOPNOTSUPP;;
 
 	/* choose the sampling rate high enough for the required operation,
@@ -687,13 +657,6 @@
 	for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++)
 		cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data);
 
-	if (state->config->pll_init)
-		state->config->pll_init(fe);
-
-	/* Configure the LNB for 14V */
-	if (state->config->use_isl6421)
-		cx24123_writelnbreg(state, 0x0, 0x2a);
-
 	return 0;
 }
 
@@ -702,50 +665,18 @@
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
 
-	switch (state->config->use_isl6421) {
+	val = cx24123_readreg(state, 0x29) & ~0x40;
 
-	case 1:
-
-		val = cx24123_readlnbreg(state, 0x0);
-
-		switch (voltage) {
-		case SEC_VOLTAGE_13:
-			dprintk("%s:  isl6421 voltage = 13V\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */
-		case SEC_VOLTAGE_18:
-			dprintk("%s:  isl6421 voltage = 18V\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */
-		case SEC_VOLTAGE_OFF:
-			dprintk("%s:  isl5421 voltage off\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val & 0x30);
-		default:
-			return -EINVAL;
-		};
-
-	case 0:
-
-		val = cx24123_readreg(state, 0x29);
-
-		switch (voltage) {
-		case SEC_VOLTAGE_13:
-			dprintk("%s: setting voltage 13V\n", __FUNCTION__);
-			if (state->config->enable_lnb_voltage)
-				state->config->enable_lnb_voltage(fe, 1);
-			return cx24123_writereg(state, 0x29, val | 0x80);
-		case SEC_VOLTAGE_18:
-			dprintk("%s: setting voltage 18V\n", __FUNCTION__);
-			if (state->config->enable_lnb_voltage)
-				state->config->enable_lnb_voltage(fe, 1);
-			return cx24123_writereg(state, 0x29, val & 0x7f);
-		case SEC_VOLTAGE_OFF:
-			dprintk("%s: setting voltage off\n", __FUNCTION__);
-			if (state->config->enable_lnb_voltage)
-				state->config->enable_lnb_voltage(fe, 0);
-			return 0;
-		default:
-			return -EINVAL;
-		};
-	}
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		dprintk("%s: setting voltage 13V\n", __FUNCTION__);
+		return cx24123_writereg(state, 0x29, val | 0x80);
+	case SEC_VOLTAGE_18:
+		dprintk("%s: setting voltage 18V\n", __FUNCTION__);
+		return cx24123_writereg(state, 0x29, val & 0x7f);
+	default:
+		return -EINVAL;
+	};
 
 	return 0;
 }
@@ -766,27 +697,20 @@
 static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
-	int i, val;
+	int i, val, tone;
 
 	dprintk("%s:\n",__FUNCTION__);
 
-	/* check if continuous tone has been stopped */
-	if (state->config->use_isl6421)
-		val = cx24123_readlnbreg(state, 0x00) & 0x10;
-	else
-		val = cx24123_readreg(state, 0x29) & 0x10;
-
-
-	if (val) {
-		printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-		return -ENOTSUPP;
-	}
+	/* stop continuous tone if enabled */
+	tone = cx24123_readreg(state, 0x29);
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x50);
 
 	/* wait for diseqc queue ready */
 	cx24123_wait_for_diseqc(state);
 
 	/* select tone mode */
-	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8);
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
 	for (i = 0; i < cmd->msg_len; i++)
 		cx24123_writereg(state, 0x2C + i, cmd->msg[i]);
@@ -797,36 +721,33 @@
 	/* wait for diseqc message to finish sending */
 	cx24123_wait_for_diseqc(state);
 
+	/* restart continuous tone if enabled */
+	if (tone & 0x10) {
+		cx24123_writereg(state, 0x29, tone & ~0x40);
+	}
+
 	return 0;
 }
 
 static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
 {
 	struct cx24123_state *state = fe->demodulator_priv;
-	int val;
+	int val, tone;
 
 	dprintk("%s:\n", __FUNCTION__);
 
-	/* check if continuous tone has been stoped */
-	if (state->config->use_isl6421)
-		val = cx24123_readlnbreg(state, 0x00) & 0x10;
-	else
-		val = cx24123_readreg(state, 0x29) & 0x10;
+	/* stop continuous tone if enabled */
+	tone = cx24123_readreg(state, 0x29);
+	if (tone & 0x10)
+		cx24123_writereg(state, 0x29, tone & ~0x50);
 
-
-	if (val) {
-		printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__);
-		return -ENOTSUPP;
-	}
-
+	/* wait for diseqc queue ready */
 	cx24123_wait_for_diseqc(state);
 
 	/* select tone mode */
-	val = cx24123_readreg(state, 0x2a) & 0xf8;
-	cx24123_writereg(state, 0x2a, val | 0x04);
-
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) | 0x4);
+	msleep(30);
 	val = cx24123_readreg(state, 0x29);
-
 	if (burst == SEC_MINI_A)
 		cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00));
 	else if (burst == SEC_MINI_B)
@@ -835,7 +756,12 @@
 		return -EINVAL;
 
 	cx24123_wait_for_diseqc(state);
+	cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xfb);
 
+	/* restart continuous tone if enabled */
+	if (tone & 0x10) {
+		cx24123_writereg(state, 0x29, tone & ~0x40);
+	}
 	return 0;
 }
 
@@ -976,38 +902,21 @@
 	struct cx24123_state *state = fe->demodulator_priv;
 	u8 val;
 
-	switch (state->config->use_isl6421) {
-	case 1:
+	/* wait for diseqc queue ready */
+	cx24123_wait_for_diseqc(state);
 
-		val = cx24123_readlnbreg(state, 0x0);
+	val = cx24123_readreg(state, 0x29) & ~0x40;
 
-		switch (tone) {
-		case SEC_TONE_ON:
-			dprintk("%s:  isl6421 sec tone on\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val | 0x10);
-		case SEC_TONE_OFF:
-			dprintk("%s:  isl6421 sec tone off\n",__FUNCTION__);
-			return cx24123_writelnbreg(state, 0x0, val & 0x2f);
-		default:
-			printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-			return -EINVAL;
-		}
-
-	case 0:
-
-		val = cx24123_readreg(state, 0x29);
-
-		switch (tone) {
-		case SEC_TONE_ON:
-			dprintk("%s: setting tone on\n", __FUNCTION__);
-			return cx24123_writereg(state, 0x29, val | 0x10);
-		case SEC_TONE_OFF:
-			dprintk("%s: setting tone off\n",__FUNCTION__);
-			return cx24123_writereg(state, 0x29, val & 0xef);
-		default:
-			printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
-			return -EINVAL;
-		}
+	switch (tone) {
+	case SEC_TONE_ON:
+		dprintk("%s: setting tone on\n", __FUNCTION__);
+		return cx24123_writereg(state, 0x29, val | 0x10);
+	case SEC_TONE_OFF:
+		dprintk("%s: setting tone off\n",__FUNCTION__);
+		return cx24123_writereg(state, 0x29, val & 0xef);
+	default:
+		printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone);
+		return -EINVAL;
 	}
 
 	return 0;
@@ -1040,10 +949,8 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
 	state->lastber = 0;
 	state->snr = 0;
-	state->lnbreg = 0;
 	state->VCAarg = 0;
 	state->VGAarg = 0;
 	state->bandselectarg = 0;
@@ -1059,7 +966,7 @@
 	}
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &cx24123_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h
index 0c922b5..9606f82 100644
--- a/drivers/media/dvb/frontends/cx24123.h
+++ b/drivers/media/dvb/frontends/cx24123.h
@@ -28,21 +28,8 @@
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
-	/*
-	   cards like Hauppauge Nova-S Plus/Nova-SE2 use an Intersil ISL6421 chip
-	   for LNB control, while KWorld DVB-S 100 use the LNBDC and LNBTone bits
-	   from register 0x29 of the CX24123 demodulator
-	*/
-	int use_isl6421;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
 	/* Need to set device param for start_dma */
 	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
-
-	void (*enable_lnb_voltage)(struct dvb_frontend* fe, int on);
 };
 
 extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config,
diff --git a/drivers/media/dvb/frontends/dib3000-common.h b/drivers/media/dvb/frontends/dib3000-common.h
index c31d6df..be1c0d3 100644
--- a/drivers/media/dvb/frontends/dib3000-common.h
+++ b/drivers/media/dvb/frontends/dib3000-common.h
@@ -38,8 +38,6 @@
 struct dib3000_state {
 	struct i2c_adapter* i2c;
 
-	struct dvb_frontend_ops ops;
-
 /* configuration settings */
 	struct dib3000_config config;
 
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index 2d5475b..ec92762 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -30,10 +30,6 @@
 {
 	/* the demodulator's i2c address */
 	u8 demod_address;
-
-	/* PLL maintenance and the i2c address of the PLL */
-	int (*pll_init)(struct dvb_frontend *fe);
-	int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
 };
 
 struct dib_fe_xfer_ops
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index ae589ad..7c6dc7e 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -60,8 +60,9 @@
 	fe_code_rate_t fe_cr = FEC_NONE;
 	int search_state, seq;
 
-	if (tuner && state->config.pll_set) {
-		state->config.pll_set(fe, fep);
+	if (tuner && fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, fep);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
 		deb_setf("bandwidth: ");
 		switch (ofdm->bandwidth) {
@@ -386,9 +387,6 @@
 
 	wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
 
-	if (state->config.pll_init)
-		state->config.pll_init(fe);
-
 	return 0;
 }
 
@@ -707,7 +705,6 @@
 	/* setup the state */
 	state->i2c = i2c;
 	memcpy(&state->config,config,sizeof(struct dib3000_config));
-	memcpy(&state->ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check for the correct demod */
 	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -717,7 +714,7 @@
 		goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dib3000mb_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
 	/* set the xfer operations */
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 3b303db..6c3be25 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -462,8 +462,9 @@
 	int search_state,auto_val;
 	u16 val;
 
-	if (tuner && state->config.pll_set) { /* initial call from dvb */
-		state->config.pll_set(fe,fep);
+	if (tuner && fe->ops.tuner_ops.set_params) { /* initial call from dvb */
+		fe->ops.tuner_ops.set_params(fe, fep);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 
 		state->last_tuned_freq = fep->frequency;
 	//	if (!scanboost) {
@@ -642,9 +643,6 @@
 
 	set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
 
-	if (state->config.pll_init)
-		state->config.pll_init(fe);
-
 	deb_info("init end\n");
 	return 0;
 }
@@ -839,7 +837,6 @@
 	/* setup the state */
 	state->i2c = i2c;
 	memcpy(&state->config,config,sizeof(struct dib3000_config));
-	memcpy(&state->ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check for the correct demod */
 	if (rd(DIB3000_REG_MANUFACTOR_ID) != DIB3000_I2C_ID_DIBCOM)
@@ -859,7 +856,7 @@
 	}
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dib3000mc_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
 	/* set the xfer operations */
@@ -876,6 +873,7 @@
 	kfree(state);
 	return NULL;
 }
+EXPORT_SYMBOL(dib3000mc_attach);
 
 static struct dvb_frontend_ops dib3000mc_ops = {
 
@@ -914,5 +912,3 @@
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dib3000mc_attach);
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 791706e..a189683 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -227,10 +227,10 @@
 EXPORT_SYMBOL(dvb_pll_tua6034);
 
 /* Infineon TUA6034
- * used in LG TDVS H061F and LG TDVS H062F
+ * used in LG TDVS-H061F, LG TDVS-H062F and LG TDVS-H064F
  */
-struct dvb_pll_desc dvb_pll_tdvs_tua6034 = {
-	.name  = "LG/Infineon TUA6034",
+struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf = {
+	.name  = "LG TDVS-H06xF",
 	.min   =  54000000,
 	.max   = 863000000,
 	.count = 3,
@@ -240,7 +240,7 @@
 		{  999999999, 44000000, 62500, 0xce, 0x04 },
 	},
 };
-EXPORT_SYMBOL(dvb_pll_tdvs_tua6034);
+EXPORT_SYMBOL(dvb_pll_lg_tdvs_h06xf);
 
 /* Philips FMD1216ME
  * used in Medion Hybrid PCMCIA card and USB Box
@@ -419,6 +419,19 @@
 };
 EXPORT_SYMBOL(dvb_pll_thomson_fe6600);
 
+struct dvb_pll_priv {
+	/* i2c details */
+	int pll_i2c_address;
+	struct i2c_adapter *i2c;
+
+	/* the PLL descriptor */
+	struct dvb_pll_desc *pll_desc;
+
+	/* cached frequency/bandwidth */
+	u32 frequency;
+	u32 bandwidth;
+};
+
 /* ----------------------------------------------------------- */
 /* code                                                        */
 
@@ -443,7 +456,8 @@
 	if (debug)
 		printk("pll: %s: freq=%d bw=%d | i=%d/%d\n",
 		       desc->name, freq, bandwidth, i, desc->count);
-	BUG_ON(i == desc->count);
+	if (i == desc->count)
+		return -EINVAL;
 
 	div = (freq + desc->entries[i].offset) / desc->entries[i].stepsize;
 	buf[0] = div >> 8;
@@ -462,6 +476,163 @@
 }
 EXPORT_SYMBOL(dvb_pll_configure);
 
+static int dvb_pll_release(struct dvb_frontend *fe)
+{
+	if (fe->tuner_priv)
+		kfree(fe->tuner_priv);
+	fe->tuner_priv = NULL;
+	return 0;
+}
+
+static int dvb_pll_sleep(struct dvb_frontend *fe)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	u8 buf[4];
+	struct i2c_msg msg =
+		{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	int i;
+	int result;
+
+	for (i = 0; i < priv->pll_desc->count; i++) {
+		if (priv->pll_desc->entries[i].limit == 0)
+			break;
+	}
+	if (i == priv->pll_desc->count)
+		return 0;
+
+	buf[0] = 0;
+	buf[1] = 0;
+	buf[2] = priv->pll_desc->entries[i].config;
+	buf[3] = priv->pll_desc->entries[i].cb;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+		return result;
+	}
+
+	return 0;
+}
+
+static int dvb_pll_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	u8 buf[4];
+	struct i2c_msg msg =
+		{ .addr = priv->pll_i2c_address, .flags = 0, .buf = buf, .len = sizeof(buf) };
+	int result;
+	u32 div;
+	int i;
+	u32 bandwidth = 0;
+
+	if (priv->i2c == NULL)
+		return -EINVAL;
+
+	// DVBT bandwidth only just now
+	if (fe->ops.info.type == FE_OFDM) {
+		bandwidth = params->u.ofdm.bandwidth;
+	}
+
+	if ((result = dvb_pll_configure(priv->pll_desc, buf, params->frequency, bandwidth)) != 0)
+		return result;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+		return result;
+	}
+
+	// calculate the frequency we set it to
+	for (i = 0; i < priv->pll_desc->count; i++) {
+		if (params->frequency > priv->pll_desc->entries[i].limit)
+			continue;
+		break;
+	}
+	div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+	priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+	priv->bandwidth = bandwidth;
+
+	return 0;
+}
+
+static int dvb_pll_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8 *buf, int buf_len)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	int result;
+	u32 div;
+	int i;
+	u32 bandwidth = 0;
+
+	if (buf_len < 5)
+		return -EINVAL;
+
+	// DVBT bandwidth only just now
+	if (fe->ops.info.type == FE_OFDM) {
+		bandwidth = params->u.ofdm.bandwidth;
+	}
+
+	if ((result = dvb_pll_configure(priv->pll_desc, buf+1, params->frequency, bandwidth)) != 0)
+		return result;
+	buf[0] = priv->pll_i2c_address;
+
+	// calculate the frequency we set it to
+	for (i = 0; i < priv->pll_desc->count; i++) {
+		if (params->frequency > priv->pll_desc->entries[i].limit)
+			continue;
+		break;
+	}
+	div = (params->frequency + priv->pll_desc->entries[i].offset) / priv->pll_desc->entries[i].stepsize;
+	priv->frequency = (div * priv->pll_desc->entries[i].stepsize) - priv->pll_desc->entries[i].offset;
+	priv->bandwidth = bandwidth;
+
+	return 5;
+}
+
+static int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	*frequency = priv->frequency;
+	return 0;
+}
+
+static int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
+{
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	*bandwidth = priv->bandwidth;
+	return 0;
+}
+
+static struct dvb_tuner_ops dvb_pll_tuner_ops = {
+	.release = dvb_pll_release,
+	.sleep = dvb_pll_sleep,
+	.set_params = dvb_pll_set_params,
+	.calc_regs = dvb_pll_calc_regs,
+	.get_frequency = dvb_pll_get_frequency,
+	.get_bandwidth = dvb_pll_get_bandwidth,
+};
+
+int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc)
+{
+	struct dvb_pll_priv *priv = NULL;
+
+	priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
+	if (priv == NULL)
+		return -ENOMEM;
+
+	priv->pll_i2c_address = pll_addr;
+	priv->i2c = i2c;
+	priv->pll_desc = desc;
+
+	memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops, sizeof(struct dvb_tuner_ops));
+	strncpy(fe->ops.tuner_ops.info.name, desc->name, 128);
+	fe->ops.tuner_ops.info.frequency_min = desc->min;
+	fe->ops.tuner_ops.info.frequency_min = desc->max;
+
+	fe->tuner_priv = priv;
+	return 0;
+}
+EXPORT_SYMBOL(dvb_pll_attach);
+
 MODULE_DESCRIPTION("dvb pll library");
 MODULE_AUTHOR("Gerd Knorr");
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 2b84617..66361cd 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -5,6 +5,9 @@
 #ifndef __DVB_PLL_H__
 #define __DVB_PLL_H__
 
+#include <linux/i2c.h>
+#include "dvb_frontend.h"
+
 struct dvb_pll_desc {
 	char *name;
 	u32  min;
@@ -31,7 +34,7 @@
 extern struct dvb_pll_desc dvb_pll_tua6010xs;
 extern struct dvb_pll_desc dvb_pll_env57h1xd5;
 extern struct dvb_pll_desc dvb_pll_tua6034;
-extern struct dvb_pll_desc dvb_pll_tdvs_tua6034;
+extern struct dvb_pll_desc dvb_pll_lg_tdvs_h06xf;
 extern struct dvb_pll_desc dvb_pll_tda665x;
 extern struct dvb_pll_desc dvb_pll_fmd1216me;
 extern struct dvb_pll_desc dvb_pll_tded4;
@@ -44,7 +47,18 @@
 
 extern struct dvb_pll_desc dvb_pll_thomson_fe6600;
 
-int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
+extern int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
 		      u32 freq, int bandwidth);
 
+/**
+ * Attach a dvb-pll to the supplied frontend structure.
+ *
+ * @param fe Frontend to attach to.
+ * @param pll_addr i2c address of the PLL (if used).
+ * @param i2c i2c adapter to use (set to NULL if not used).
+ * @param desc dvb_pll_desc to use.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, struct dvb_pll_desc *desc);
+
 #endif
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index 645946a..6271b1e 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -30,7 +30,6 @@
 
 
 struct dvb_dummy_fe_state {
-	struct dvb_frontend_ops ops;
 	struct dvb_frontend frontend;
 };
 
@@ -77,6 +76,11 @@
 
 static int dvb_dummy_fe_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
 {
+	if (fe->ops->tuner_ops->set_params) {
+		fe->ops->tuner_ops->set_params(fe, p);
+		if (fe->ops->i2c_gate_ctrl) fe->ops->i2c_gate_ctrl(fe, 0);
+	}
+
 	return 0;
 }
 
@@ -116,11 +120,8 @@
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
-	/* setup the state */
-	memcpy(&state->ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
-
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_ofdm_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -139,11 +140,8 @@
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
-	/* setup the state */
-	memcpy(&state->ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
-
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_qpsk_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -162,11 +160,8 @@
 	state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
 	if (state == NULL) goto error;
 
-	/* setup the state */
-	memcpy(&state->ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
-
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &dvb_dummy_fe_qam_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c
new file mode 100644
index 0000000..58c34db
--- /dev/null
+++ b/drivers/media/dvb/frontends/isl6421.c
@@ -0,0 +1,149 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "isl6421.h"
+
+struct isl6421 {
+	u8			config;
+	u8			override_or;
+	u8			override_and;
+	struct i2c_adapter	*i2c;
+	u8			i2c_addr;
+	void			(*release_chain)(struct dvb_frontend* fe);
+};
+
+static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
+				.buf = &isl6421->config,
+				.len = sizeof(isl6421->config) };
+
+	isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1);
+
+	switch(voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		isl6421->config |= ISL6421_EN1;
+		break;
+	case SEC_VOLTAGE_18:
+		isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	isl6421->config |= isl6421->override_or;
+	isl6421->config &= isl6421->override_and;
+
+	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = isl6421->i2c_addr, .flags = 0,
+				.buf = &isl6421->config,
+				.len = sizeof(isl6421->config) };
+
+	if (arg)
+		isl6421->config |= ISL6421_LLC1;
+	else
+		isl6421->config &= ~ISL6421_LLC1;
+
+	isl6421->config |= isl6421->override_or;
+	isl6421->config &= isl6421->override_and;
+
+	return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void isl6421_release(struct dvb_frontend *fe)
+{
+	struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv;
+
+	/* power off */
+	isl6421_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data & call next release routine */
+	fe->ops.release = isl6421->release_chain;
+	kfree(fe->misc_priv);
+	fe->misc_priv = NULL;
+	if (fe->ops.release)
+		fe->ops.release(fe);
+}
+
+int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+		   u8 override_set, u8 override_clear)
+{
+	struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
+	if (!isl6421)
+		return -ENOMEM;
+
+	/* default configuration */
+	isl6421->config = ISL6421_ISEL1;
+	isl6421->i2c = i2c;
+	isl6421->i2c_addr = i2c_addr;
+	fe->misc_priv = isl6421;
+
+	/* bits which should be forced to '1' */
+	isl6421->override_or = override_set;
+
+	/* bits which should be forced to '0' */
+	isl6421->override_and = ~override_clear;
+
+	/* detect if it is present or not */
+	if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		kfree(isl6421);
+		fe->misc_priv = NULL;
+		return -EIO;
+	}
+
+	/* install release callback */
+	isl6421->release_chain = fe->ops.release;
+	fe->ops.release = isl6421_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = isl6421_set_voltage;
+	fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
+
+	return 0;
+}
+EXPORT_SYMBOL(isl6421_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
+MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h
new file mode 100644
index 0000000..675f80a
--- /dev/null
+++ b/drivers/media/dvb/frontends/isl6421.h
@@ -0,0 +1,46 @@
+/*
+ * isl6421.h - driver for lnb supply and control ic ISL6421
+ *
+ * Copyright (C) 2006 Andrew de Quincey
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+
+#ifndef _ISL6421_H
+#define _ISL6421_H
+
+#include <linux/dvb/frontend.h>
+
+/* system register bits */
+#define ISL6421_OLF1	0x01
+#define ISL6421_EN1	0x02
+#define ISL6421_VSEL1	0x04
+#define ISL6421_LLC1	0x08
+#define ISL6421_ENT1	0x10
+#define ISL6421_ISEL1	0x20
+#define ISL6421_DCL	0x40
+
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
+			  u8 override_set, u8 override_clear);
+
+#endif
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index 1c7c912..f3bc82e 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -32,7 +32,6 @@
 
 struct l64781_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct l64781_config* config;
 	struct dvb_frontend frontend;
 
@@ -141,7 +140,10 @@
 	u8 val0x06;
 	int bw = p->bandwidth - BANDWIDTH_8_MHZ;
 
-	state->config->pll_set(fe, param);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	if (param->inversion != INVERSION_ON &&
 	    param->inversion != INVERSION_OFF)
@@ -463,8 +465,6 @@
 	/* Everything is two's complement, soft bit and CSI_OUT too */
 	l64781_writereg (state, 0x1e, 0x09);
 
-	if (state->config->pll_init) state->config->pll_init(fe);
-
 	/* delay a bit after first init attempt */
 	if (state->first) {
 		state->first = 0;
@@ -508,7 +508,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
 	state->first = 1;
 
 	/**
@@ -554,7 +553,7 @@
 	}
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &l64781_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h
index 947f65f..83b8bc2 100644
--- a/drivers/media/dvb/frontends/l64781.h
+++ b/drivers/media/dvb/frontends/l64781.h
@@ -29,10 +29,6 @@
 {
 	/* the demodulator's i2c address */
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 
diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h
new file mode 100644
index 0000000..754d51d
--- /dev/null
+++ b/drivers/media/dvb/frontends/lg_h06xf.h
@@ -0,0 +1,64 @@
+/*
+ *  lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _LG_H06XF_H_
+#define _LG_H06XF_H_
+#include "dvb-pll.h"
+
+static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap,
+		     struct dvb_frontend_parameters* params)
+{
+	u8 buf[4];
+	struct i2c_msg msg = { .addr = 0x61, .flags = 0,
+			       .buf = buf, .len = sizeof(buf) };
+	int err;
+
+	dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+		printk(KERN_WARNING "lg_h06xf: %s error "
+			"(addr %02x <- %02x, err = %i)\n",
+			__FUNCTION__, buf[0], buf[1], err);
+		if (err < 0)
+			return err;
+		else
+			return -EREMOTEIO;
+	}
+
+	/* Set the Auxiliary Byte. */
+	buf[0] = buf[2];
+	buf[0] &= ~0x20;
+	buf[0] |= 0x18;
+	buf[1] = 0x50;
+	msg.len = 2;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) {
+		printk(KERN_WARNING "lg_h06xf: %s error "
+			"(addr %02x <- %02x, err = %i)\n",
+			__FUNCTION__, buf[0], buf[1], err);
+		if (err < 0)
+			return err;
+		else
+			return -EREMOTEIO;
+	}
+
+	return 0;
+}
+#endif
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 4691ac5..6e8ad17 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -29,6 +29,7 @@
  *   DViCO FusionHDTV 5 Lite
  *   DViCO FusionHDTV 5 USB Gold
  *   Air2PC/AirStar 2 ATSC 3rd generation (HD5000)
+ *   pcHDTV HD5500
  *
  * TODO:
  * signal strength always returns 0.
@@ -59,7 +60,6 @@
 struct lgdt330x_state
 {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 
 	/* Configuration settings */
 	const struct lgdt330x_config* config;
@@ -399,8 +399,10 @@
 	}
 
 	/* Tune to the specified frequency */
-	if (state->config->pll_set)
-		state->config->pll_set(fe, param);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	/* Keep track of the new frequency */
 	/* FIXME this is the wrong way to do this...           */
@@ -672,6 +674,7 @@
 
 	if (state->current_modulation == VSB_8) {
 
+		i2c_read_demod_bytes(state, 0x6e, buf, 5);
 		/* Phase Tracker Mean-Square Error Register for VSB */
 		noise = ((buf[0] & 7) << 16) | (buf[3] << 8) | buf[4];
 	} else {
@@ -721,16 +724,19 @@
 	/* Setup the state */
 	state->config = config;
 	state->i2c = i2c;
+
+	/* Create dvb_frontend */
 	switch (config->demod_chip) {
 	case LGDT3302:
-		memcpy(&state->ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &lgdt3302_ops, sizeof(struct dvb_frontend_ops));
 		break;
 	case LGDT3303:
-		memcpy(&state->ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
+		memcpy(&state->frontend.ops, &lgdt3303_ops, sizeof(struct dvb_frontend_ops));
 		break;
 	default:
 		goto error;
 	}
+	state->frontend.demodulator_priv = state;
 
 	/* Verify communication with demod chip */
 	if (i2c_read_demod_bytes(state, 2, buf, 1))
@@ -739,9 +745,6 @@
 	state->current_frequency = -1;
 	state->current_modulation = -1;
 
-	/* Create dvb_frontend */
-	state->frontend.ops = &state->ops;
-	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
 error:
diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h
index 2a6529c..bad903c 100644
--- a/drivers/media/dvb/frontends/lgdt330x.h
+++ b/drivers/media/dvb/frontends/lgdt330x.h
@@ -43,7 +43,6 @@
 
 	/* PLL interface */
 	int (*pll_rf_set) (struct dvb_frontend* fe, int index);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 
 	/* Need to set device param for start_dma */
 	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c
new file mode 100644
index 0000000..e933edc
--- /dev/null
+++ b/drivers/media/dvb/frontends/lnbp21.c
@@ -0,0 +1,145 @@
+/*
+ * lnbp21.h - driver for lnb supply and control ic lnbp21
+ *
+ * Copyright (C) 2006 Oliver Endriss
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * the project's page is at http://www.linuxtv.org
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+
+#include "dvb_frontend.h"
+#include "lnbp21.h"
+
+struct lnbp21 {
+	u8			config;
+	u8			override_or;
+	u8			override_and;
+	struct i2c_adapter	*i2c;
+	void			(*release_chain)(struct dvb_frontend* fe);
+};
+
+static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
+
+	switch(voltage) {
+	case SEC_VOLTAGE_OFF:
+		break;
+	case SEC_VOLTAGE_13:
+		lnbp21->config |= LNBP21_EN;
+		break;
+	case SEC_VOLTAGE_18:
+		lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
+				.buf = &lnbp21->config,
+				.len = sizeof(lnbp21->config) };
+
+	if (arg)
+		lnbp21->config |= LNBP21_LLC;
+	else
+		lnbp21->config &= ~LNBP21_LLC;
+
+	lnbp21->config |= lnbp21->override_or;
+	lnbp21->config &= lnbp21->override_and;
+
+	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
+}
+
+static void lnbp21_release(struct dvb_frontend *fe)
+{
+	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
+
+	/* LNBP power off */
+	lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
+
+	/* free data & call next release routine */
+	fe->ops.release = lnbp21->release_chain;
+	kfree(fe->misc_priv);
+	fe->misc_priv = NULL;
+	if (fe->ops.release)
+		fe->ops.release(fe);
+}
+
+int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
+{
+	struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
+	if (!lnbp21)
+		return -ENOMEM;
+
+	/* default configuration */
+	lnbp21->config = LNBP21_ISEL;
+	lnbp21->i2c = i2c;
+	fe->misc_priv = lnbp21;
+
+	/* bits which should be forced to '1' */
+	lnbp21->override_or = override_set;
+
+	/* bits which should be forced to '0' */
+	lnbp21->override_and = ~override_clear;
+
+	/* detect if it is present or not */
+	if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) {
+		kfree(lnbp21);
+		fe->misc_priv = NULL;
+		return -EIO;
+	}
+
+	/* install release callback */
+	lnbp21->release_chain = fe->ops.release;
+	fe->ops.release = lnbp21_release;
+
+	/* override frontend ops */
+	fe->ops.set_voltage = lnbp21_set_voltage;
+	fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
+
+	return 0;
+}
+EXPORT_SYMBOL(lnbp21_attach);
+
+MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21");
+MODULE_AUTHOR("Oliver Endriss");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h
index 0dcbe61..047a4ab6 100644
--- a/drivers/media/dvb/frontends/lnbp21.h
+++ b/drivers/media/dvb/frontends/lnbp21.h
@@ -27,7 +27,7 @@
 #ifndef _LNBP21_H
 #define _LNBP21_H
 
-/* system register */
+/* system register bits */
 #define LNBP21_OLF	0x01
 #define LNBP21_OTF	0x02
 #define LNBP21_EN	0x04
@@ -37,103 +37,9 @@
 #define LNBP21_ISEL	0x40
 #define LNBP21_PCL	0x80
 
-struct lnbp21 {
-	u8			config;
-	u8			override_or;
-	u8			override_and;
-	struct i2c_adapter	*i2c;
-	void			(*release_chain)(struct dvb_frontend* fe);
-};
+#include <linux/dvb/frontend.h>
 
-static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
-				.buf = &lnbp21->config,
-				.len = sizeof(lnbp21->config) };
-
-	lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN);
-
-	switch(voltage) {
-	case SEC_VOLTAGE_OFF:
-		break;
-	case SEC_VOLTAGE_13:
-		lnbp21->config |= LNBP21_EN;
-		break;
-	case SEC_VOLTAGE_18:
-		lnbp21->config |= (LNBP21_EN | LNBP21_VSEL);
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	lnbp21->config |= lnbp21->override_or;
-	lnbp21->config &= lnbp21->override_and;
-
-	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-	struct i2c_msg msg = {	.addr = 0x08, .flags = 0,
-				.buf = &lnbp21->config,
-				.len = sizeof(lnbp21->config) };
-
-	if (arg)
-		lnbp21->config |= LNBP21_LLC;
-	else
-		lnbp21->config &= ~LNBP21_LLC;
-
-	lnbp21->config |= lnbp21->override_or;
-	lnbp21->config &= lnbp21->override_and;
-
-	return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO;
-}
-
-static void lnbp21_exit(struct dvb_frontend *fe)
-{
-	struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv;
-
-	/* LNBP power off */
-	lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-
-	/* free data & call next release routine */
-	fe->ops->release = lnbp21->release_chain;
-	kfree(fe->misc_priv);
-	fe->misc_priv = NULL;
-	if (fe->ops->release)
-		fe->ops->release(fe);
-}
-
-static int lnbp21_init(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear)
-{
-	struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL);
-
-	if (!lnbp21)
-		return -ENOMEM;
-
-	/* default configuration */
-	lnbp21->config = LNBP21_ISEL;
-
-	/* bits which should be forced to '1' */
-	lnbp21->override_or = override_set;
-
-	/* bits which should be forced to '0' */
-	lnbp21->override_and = ~override_clear;
-
-	/* install release callback */
-	lnbp21->release_chain = fe->ops->release;
-	fe->ops->release = lnbp21_exit;
-
-	/* override frontend ops */
-	fe->ops->set_voltage = lnbp21_set_voltage;
-	fe->ops->enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage;
-
-	lnbp21->i2c = i2c;
-	fe->misc_priv = lnbp21;
-
-	return lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF);
-}
+/* override_set and override_clear control which system register bits (above) to always set & clear */
+extern int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear);
 
 #endif
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index d3aea83..1ef8218 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -39,7 +39,6 @@
 
 struct mt312_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	/* configuration settings */
 	const struct mt312_config* config;
 	struct dvb_frontend frontend;
@@ -277,12 +276,6 @@
 	if ((ret = mt312_writereg(state, CS_SW_LIM, 0x69)) < 0)
 		return ret;
 
-	if (state->config->pll_init) {
-		mt312_writereg(state, GPP_CTRL, 0x40);
-		state->config->pll_init(fe);
-		mt312_writereg(state, GPP_CTRL, 0x00);
-	}
-
 	return 0;
 }
 
@@ -477,16 +470,16 @@
 
 	dprintk("%s: Freq %d\n", __FUNCTION__, p->frequency);
 
-	if ((p->frequency < fe->ops->info.frequency_min)
-	    || (p->frequency > fe->ops->info.frequency_max))
+	if ((p->frequency < fe->ops.info.frequency_min)
+	    || (p->frequency > fe->ops.info.frequency_max))
 		return -EINVAL;
 
 	if ((p->inversion < INVERSION_OFF)
 	    || (p->inversion > INVERSION_ON))
 		return -EINVAL;
 
-	if ((p->u.qpsk.symbol_rate < fe->ops->info.symbol_rate_min)
-	    || (p->u.qpsk.symbol_rate > fe->ops->info.symbol_rate_max))
+	if ((p->u.qpsk.symbol_rate < fe->ops.info.symbol_rate_min)
+	    || (p->u.qpsk.symbol_rate > fe->ops.info.symbol_rate_max))
 		return -EINVAL;
 
 	if ((p->u.qpsk.fec_inner < FEC_NONE)
@@ -529,9 +522,10 @@
 		return -EINVAL;
 	}
 
-	mt312_writereg(state, GPP_CTRL, 0x40);
-	state->config->pll_set(fe, p);
-	mt312_writereg(state, GPP_CTRL, 0x00);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	/* sr = (u16)(sr * 256.0 / 1000000.0) */
 	sr = mt312_div(p->u.qpsk.symbol_rate * 4, 15625);
@@ -578,6 +572,17 @@
 	return 0;
 }
 
+static int mt312_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct mt312_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return mt312_writereg(state, GPP_CTRL, 0x40);
+	} else {
+		return mt312_writereg(state, GPP_CTRL, 0x00);
+	}
+}
+
 static int mt312_sleep(struct dvb_frontend* fe)
 {
 	struct mt312_state *state = fe->demodulator_priv;
@@ -633,6 +638,7 @@
 
 	.init = mt312_initfe,
 	.sleep = mt312_sleep,
+	.i2c_gate_ctrl = mt312_i2c_gate_ctrl,
 
 	.set_frontend = mt312_set_frontend,
 	.get_frontend = mt312_get_frontend,
@@ -663,19 +669,22 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check if the demod is there */
 	if (mt312_readreg(state, ID, &state->id) < 0)
 		goto error;
 
+	/* create dvb_frontend */
+	memcpy(&state->frontend.ops, &vp310_mt312_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.demodulator_priv = state;
+
 	switch (state->id) {
 	case ID_VP310:
-		strcpy(state->ops.info.name, "Zarlink VP310 DVB-S");
+		strcpy(state->frontend.ops.info.name, "Zarlink VP310 DVB-S");
 		state->frequency = 90;
 		break;
 	case ID_MT312:
-		strcpy(state->ops.info.name, "Zarlink MT312 DVB-S");
+		strcpy(state->frontend.ops.info.name, "Zarlink MT312 DVB-S");
 		state->frequency = 60;
 		break;
 	default:
@@ -683,9 +692,6 @@
 		goto error;
 	}
 
-	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
-	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
 error:
diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h
index 074d844..666a1bd 100644
--- a/drivers/media/dvb/frontends/mt312.h
+++ b/drivers/media/dvb/frontends/mt312.h
@@ -32,10 +32,6 @@
 {
 	/* the demodulator's i2c address */
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config,
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index aaaec90..5de7376c 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -45,7 +45,6 @@
 struct mt352_state {
 	struct i2c_adapter* i2c;
 	struct dvb_frontend frontend;
-	struct dvb_frontend_ops ops;
 
 	/* configuration settings */
 	struct mt352_config config;
@@ -286,16 +285,25 @@
 
 	mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
 	mt352_calc_input_freq(state, buf+6);
-	state->config.pll_set(fe, param, buf+8);
 
-	mt352_write(fe, buf, sizeof(buf));
 	if (state->config.no_tuner) {
-		/* start decoding */
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe, param);
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+
+		mt352_write(fe, buf, 8);
 		mt352_write(fe, fsm_go, 2);
 	} else {
-		/* start tuning */
-		mt352_write(fe, tuner_go, 2);
+		if (fe->ops.tuner_ops.calc_regs) {
+			fe->ops.tuner_ops.calc_regs(fe, param, buf+8, 5);
+			buf[8] <<= 1;
+			mt352_write(fe, buf, sizeof(buf));
+			mt352_write(fe, tuner_go, 2);
+		}
 	}
+
 	return 0;
 }
 
@@ -541,13 +549,12 @@
 	/* setup the state */
 	state->i2c = i2c;
 	memcpy(&state->config,config,sizeof(struct mt352_config));
-	memcpy(&state->ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check if the demod is there */
 	if (mt352_read_register(state, CHIP_ID) != ID_MT352) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
index 03040cd..9e7ff4b 100644
--- a/drivers/media/dvb/frontends/mt352.h
+++ b/drivers/media/dvb/frontends/mt352.h
@@ -49,12 +49,6 @@
 
 	/* Initialise the demodulator and PLL. Cannot be NULL */
 	int (*demod_init)(struct dvb_frontend* fe);
-
-	/* PLL setup - fill out the supplied 5 byte buffer with your PLL settings.
-	 * byte0: Set to pll i2c address (nonlinux; left shifted by 1)
-	 * byte1-4: PLL configuration.
-	 */
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf);
 };
 
 extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
diff --git a/drivers/media/dvb/frontends/nxt200x.c b/drivers/media/dvb/frontends/nxt200x.c
index 9e353539..55671cb 100644
--- a/drivers/media/dvb/frontends/nxt200x.c
+++ b/drivers/media/dvb/frontends/nxt200x.c
@@ -55,7 +55,6 @@
 struct nxt200x_state {
 
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct nxt200x_config* config;
 	struct dvb_frontend frontend;
 
@@ -333,17 +332,17 @@
 
 	dprintk("%s\n", __FUNCTION__);
 
-	dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]);
+	dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
 
 	/* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
 	 * direct write is required for Philips TUV1236D and ALPS TDHU2 */
 	switch (state->demod_chip) {
 		case NXT2004:
-			if (i2c_writebytes(state, state->config->pll_address, data, 4))
+			if (i2c_writebytes(state, data[0], data+1, 4))
 				printk(KERN_WARNING "nxt200x: error writing to tuner\n");
 			/* wait until we have a lock */
 			while (count < 20) {
-				i2c_readbytes(state, state->config->pll_address, &buf, 1);
+				i2c_readbytes(state, data[0], &buf, 1);
 				if (buf & 0x40)
 					return 0;
 				msleep(100);
@@ -361,10 +360,10 @@
 			nxt200x_writebytes(state, 0x34, &buf, 1);
 
 			/* write actual tuner bytes */
-			nxt200x_writebytes(state, 0x36, data, 4);
+			nxt200x_writebytes(state, 0x36, data+1, 4);
 
 			/* set tuner i2c address */
-			buf = state->config->pll_address;
+			buf = data[0] << 1;
 			nxt200x_writebytes(state, 0x35, &buf, 1);
 
 			/* write UC Opmode to begin transfer */
@@ -534,7 +533,7 @@
 					     struct dvb_frontend_parameters *p)
 {
 	struct nxt200x_state* state = fe->demodulator_priv;
-	u8 buf[4];
+	u8 buf[5];
 
 	/* stop the micro first */
 	nxt200x_microcontroller_stop(state);
@@ -548,7 +547,9 @@
 	}
 
 	/* get tuning information */
-	dvb_pll_configure(state->config->pll_desc, buf, p->frequency, 0);
+	if (fe->ops.tuner_ops.calc_regs) {
+		fe->ops.tuner_ops.calc_regs(fe, p, buf, 5);
+	}
 
 	/* set additional params */
 	switch (p->u.vsb.modulation) {
@@ -1159,7 +1160,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
 	state->initialised = 0;
 
 	/* read card id */
@@ -1198,7 +1198,7 @@
 	}
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &nxt200x_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h
index 1d9d70b..34d6173 100644
--- a/drivers/media/dvb/frontends/nxt200x.h
+++ b/drivers/media/dvb/frontends/nxt200x.h
@@ -38,10 +38,6 @@
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
-	/* tuner information */
-	u8 pll_address;
-	struct dvb_pll_desc *pll_desc;
-
 	/* used to set pll input */
 	int (*set_pll_input)(u8* buf, int input);
 
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a16eeba..d313d7d 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -33,7 +33,6 @@
 
 struct nxt6000_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	/* configuration settings */
 	const struct nxt6000_config* config;
 	struct dvb_frontend frontend;
@@ -207,12 +206,6 @@
 		nxt6000_writereg(state, SUB_DIAG_MODE_SEL, 0);
 
 	nxt6000_writereg(state, TS_FORMAT, 0);
-
-	if (state->config->pll_init) {
-		nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);	/* open i2c bus switch */
-		state->config->pll_init(fe);
-		nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);	/* close i2c bus switch */
-	}
 }
 
 static void nxt6000_dump_status(struct nxt6000_state *state)
@@ -469,9 +462,10 @@
 	struct nxt6000_state* state = fe->demodulator_priv;
 	int result;
 
-	nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);	/* open i2c bus switch */
-	state->config->pll_set(fe, param);
-	nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);	/* close i2c bus switch */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	if ((result = nxt6000_set_bandwidth(state, param->u.ofdm.bandwidth)) < 0)
 		return result;
@@ -532,6 +526,17 @@
 	return 0;
 }
 
+static int nxt6000_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct nxt6000_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01);
+	} else {
+		return nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x00);
+	}
+}
+
 static struct dvb_frontend_ops nxt6000_ops;
 
 struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -546,13 +551,12 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check if the demod is there */
 	if (nxt6000_readreg(state, OFDM_MSC_REV) != NXT6000ASICDEVICE) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &nxt6000_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -584,6 +588,7 @@
 	.release = nxt6000_release,
 
 	.init = nxt6000_init,
+	.i2c_gate_ctrl = nxt6000_i2c_gate_ctrl,
 
 	.get_tune_settings = nxt6000_fe_get_tune_settings,
 
diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h
index b7d9bea..117031d 100644
--- a/drivers/media/dvb/frontends/nxt6000.h
+++ b/drivers/media/dvb/frontends/nxt6000.h
@@ -31,10 +31,6 @@
 
 	/* should clock inversion be used? */
 	u8 clock_inversion:1;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index 80e0f28..d20ab30 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -54,7 +54,6 @@
 struct or51132_state
 {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 
 	/* Configuration settings */
 	const struct or51132_config* config;
@@ -106,9 +105,8 @@
 {
 	struct or51132_state* state = fe->demodulator_priv;
 	static u8 run_buf[] = {0x7F,0x01};
-	static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
-	u8 rec_buf[14];
-	u8 cmd_buf[14];
+	u8 rec_buf[8];
+	u8 cmd_buf[3];
 	u32 firmwareAsize, firmwareBsize;
 	int i,ret;
 
@@ -157,7 +155,6 @@
 	cmd_buf[0] = 0x10;
 	cmd_buf[1] = 0x10;
 	cmd_buf[2] = 0x00;
-	cmd_buf[3] = 0x00;
 	msleep(20); /* 20ms */
 	if ((ret = i2c_writebytes(state,state->config->demod_address,
 				 cmd_buf,3))) {
@@ -167,8 +164,6 @@
 
 	cmd_buf[0] = 0x04;
 	cmd_buf[1] = 0x17;
-	cmd_buf[2] = 0x00;
-	cmd_buf[3] = 0x00;
 	msleep(20); /* 20ms */
 	if ((ret = i2c_writebytes(state,state->config->demod_address,
 				 cmd_buf,2))) {
@@ -178,8 +173,6 @@
 
 	cmd_buf[0] = 0x00;
 	cmd_buf[1] = 0x00;
-	cmd_buf[2] = 0x00;
-	cmd_buf[3] = 0x00;
 	msleep(20); /* 20ms */
 	if ((ret = i2c_writebytes(state,state->config->demod_address,
 				 cmd_buf,2))) {
@@ -189,7 +182,11 @@
 
 	for(i=0;i<4;i++) {
 		msleep(20); /* 20ms */
-		get_ver_buf[4] = i+1;
+		/* Once upon a time, this command might have had something
+		   to do with getting the firmware version, but it's
+		   not used anymore:
+		   {0x04,0x00,0x30,0x00,i+1} */
+		/* Read 8 bytes, two bytes at a time */
 		if ((ret = i2c_readbytes(state,state->config->demod_address,
 					&rec_buf[i*2],2))) {
 			printk(KERN_WARNING
@@ -208,7 +205,6 @@
 	cmd_buf[0] = 0x10;
 	cmd_buf[1] = 0x00;
 	cmd_buf[2] = 0x00;
-	cmd_buf[3] = 0x00;
 	msleep(20); /* 20ms */
 	if ((ret = i2c_writebytes(state,state->config->demod_address,
 				 cmd_buf,3))) {
@@ -243,7 +239,7 @@
 static int or51132_setmode(struct dvb_frontend* fe)
 {
 	struct or51132_state* state = fe->demodulator_priv;
-	unsigned char cmd_buf[4];
+	unsigned char cmd_buf[3];
 
 	dprintk("setmode %d\n",(int)state->current_modulation);
 	/* set operation mode in Receiver 1 register; */
@@ -263,7 +259,6 @@
 	default:
 		printk("setmode:Modulation set to unsupported value\n");
 	};
-	cmd_buf[3] = 0x00;
 	if (i2c_writebytes(state,state->config->demod_address,
 			   cmd_buf,3)) {
 		printk(KERN_WARNING "or51132: set_mode error 1\n");
@@ -301,7 +296,6 @@
 	default:
 		printk("setmode: Modulation set to unsupported value\n");
 	};
-	cmd_buf[3] = 0x00;
 	msleep(20); /* 20ms */
 	if (i2c_writebytes(state,state->config->demod_address,
 			   cmd_buf,3)) {
@@ -313,52 +307,65 @@
 	return 0;
 }
 
+/* Some modulations use the same firmware.  This classifies modulations
+   by the firmware they use. */
+#define MOD_FWCLASS_UNKNOWN	0
+#define MOD_FWCLASS_VSB		1
+#define MOD_FWCLASS_QAM		2
+static int modulation_fw_class(fe_modulation_t modulation)
+{
+	switch(modulation) {
+	case VSB_8:
+		return MOD_FWCLASS_VSB;
+	case QAM_AUTO:
+	case QAM_64:
+	case QAM_256:
+		return MOD_FWCLASS_QAM;
+	default:
+		return MOD_FWCLASS_UNKNOWN;
+	}
+}
+
 static int or51132_set_parameters(struct dvb_frontend* fe,
 				  struct dvb_frontend_parameters *param)
 {
 	int ret;
-	u8 buf[4];
 	struct or51132_state* state = fe->demodulator_priv;
 	const struct firmware *fw;
+	const char *fwname;
+	int clock_mode;
 
-	/* Change only if we are actually changing the modulation */
-	if (state->current_modulation != param->u.vsb.modulation) {
-		switch(param->u.vsb.modulation) {
-		case VSB_8:
+	/* Upload new firmware only if we need a different one */
+	if (modulation_fw_class(state->current_modulation) !=
+	    modulation_fw_class(param->u.vsb.modulation)) {
+		switch(modulation_fw_class(param->u.vsb.modulation)) {
+		case MOD_FWCLASS_VSB:
 			dprintk("set_parameters VSB MODE\n");
-			printk("or51132: Waiting for firmware upload(%s)...\n",
-			       OR51132_VSB_FIRMWARE);
-			ret = request_firmware(&fw, OR51132_VSB_FIRMWARE,
-					       &state->i2c->dev);
-			if (ret){
-				printk(KERN_WARNING "or51132: No firmware up"
-				       "loaded(timeout or file not found?)\n");
-				return ret;
-			}
+			fwname = OR51132_VSB_FIRMWARE;
+
 			/* Set non-punctured clock for VSB */
-			state->config->set_ts_params(fe, 0);
+			clock_mode = 0;
 			break;
-		case QAM_AUTO:
-		case QAM_64:
-		case QAM_256:
+		case MOD_FWCLASS_QAM:
 			dprintk("set_parameters QAM MODE\n");
-			printk("or51132: Waiting for firmware upload(%s)...\n",
-			       OR51132_QAM_FIRMWARE);
-			ret = request_firmware(&fw, OR51132_QAM_FIRMWARE,
-					       &state->i2c->dev);
-			if (ret){
-				printk(KERN_WARNING "or51132: No firmware up"
-				       "loaded(timeout or file not found?)\n");
-				return ret;
-			}
+			fwname = OR51132_QAM_FIRMWARE;
+
 			/* Set punctured clock for QAM */
-			state->config->set_ts_params(fe, 1);
+			clock_mode = 1;
 			break;
 		default:
-			printk("or51132:Modulation type(%d) UNSUPPORTED\n",
+			printk("or51132: Modulation type(%d) UNSUPPORTED\n",
 			       param->u.vsb.modulation);
 			return -1;
-		};
+		}
+		printk("or51132: Waiting for firmware upload(%s)...\n",
+		       fwname);
+		ret = request_firmware(&fw, fwname, &state->i2c->dev);
+		if (ret) {
+			printk(KERN_WARNING "or51132: No firmware up"
+			       "loaded(timeout or file not found?)\n");
+			return ret;
+		}
 		ret = or51132_load_firmware(fe, fw);
 		release_firmware(fw);
 		if (ret) {
@@ -367,18 +374,18 @@
 			return ret;
 		}
 		printk("or51132: Firmware upload complete.\n");
-
+		state->config->set_ts_params(fe, clock_mode);
+	}
+	/* Change only if we are actually changing the modulation */
+	if (state->current_modulation != param->u.vsb.modulation) {
 		state->current_modulation = param->u.vsb.modulation;
 		or51132_setmode(fe);
 	}
 
-	dvb_pll_configure(state->config->pll_desc, buf,
-			  param->frequency, 0);
-	dprintk("set_parameters tuner bytes: 0x%02x 0x%02x "
-		"0x%02x 0x%02x\n",buf[0],buf[1],buf[2],buf[3]);
-	if (i2c_writebytes(state, state->config->pll_address ,buf, 4))
-		printk(KERN_WARNING "or51132: set_parameters error "
-		       "writing to tuner\n");
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	/* Set to current mode */
 	or51132_setmode(fe);
@@ -388,6 +395,44 @@
 	return 0;
 }
 
+static int or51132_get_parameters(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *param)
+{
+	struct or51132_state* state = fe->demodulator_priv;
+	u8 buf[2];
+
+	/* Receiver Status */
+	buf[0]=0x04;
+	buf[1]=0x00;
+	msleep(30); /* 30ms */
+	if (i2c_writebytes(state,state->config->demod_address,buf,2)) {
+		printk(KERN_WARNING "or51132: get_parameters write error\n");
+		return -EREMOTEIO;
+	}
+	msleep(30); /* 30ms */
+	if (i2c_readbytes(state,state->config->demod_address,buf,2)) {
+		printk(KERN_WARNING "or51132: get_parameters read error\n");
+		return -EREMOTEIO;
+	}
+	switch(buf[0]) {
+		case 0x06: param->u.vsb.modulation = VSB_8; break;
+		case 0x43: param->u.vsb.modulation = QAM_64; break;
+		case 0x45: param->u.vsb.modulation = QAM_256; break;
+		default:
+			printk(KERN_WARNING "or51132: unknown status 0x%02x\n",
+			       buf[0]);
+			return -EREMOTEIO;
+	}
+
+	/* FIXME: Read frequency from frontend, take AFC into account */
+	param->frequency = state->current_frequency;
+
+	/* FIXME: How to read inversion setting? Receiver 6 register? */
+	param->inversion = INVERSION_AUTO;
+
+	return 0;
+}
+
 static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
 {
 	struct or51132_state* state = fe->demodulator_priv;
@@ -572,12 +617,11 @@
 	/* Setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
 	state->current_frequency = -1;
 	state->current_modulation = -1;
 
 	/* Create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &or51132_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -590,7 +634,7 @@
 
 	.info = {
 		.name			= "Oren OR51132 VSB/QAM Frontend",
-		.type 			= FE_ATSC,
+		.type			= FE_ATSC,
 		.frequency_min		= 44000000,
 		.frequency_max		= 958000000,
 		.frequency_stepsize	= 166666,
@@ -606,6 +650,7 @@
 	.sleep = or51132_sleep,
 
 	.set_frontend = or51132_set_parameters,
+	.get_frontend = or51132_get_parameters,
 	.get_tune_settings = or51132_get_tune_settings,
 
 	.read_status = or51132_read_status,
diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h
index 622cdd1..8965888 100644
--- a/drivers/media/dvb/frontends/or51132.h
+++ b/drivers/media/dvb/frontends/or51132.h
@@ -29,8 +29,6 @@
 {
 	/* The demodulator's i2c address */
 	u8 demod_address;
-	u8 pll_address;
-	struct dvb_pll_desc *pll_desc;
 
 	/* Need to set device param for start_dma */
 	int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured);
diff --git a/drivers/media/dvb/frontends/or51211.c b/drivers/media/dvb/frontends/or51211.c
index 7c3aed1..26bed61 100644
--- a/drivers/media/dvb/frontends/or51211.c
+++ b/drivers/media/dvb/frontends/or51211.c
@@ -54,7 +54,6 @@
 struct or51211_state {
 
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 
 	/* Configuration settings */
 	const struct or51211_config* config;
@@ -585,12 +584,11 @@
 	/* Setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
 	state->initialized = 0;
 	state->current_frequency = 0;
 
 	/* Create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &or51211_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/s5h1420.c b/drivers/media/dvb/frontends/s5h1420.c
index d694775..2c2c344 100644
--- a/drivers/media/dvb/frontends/s5h1420.c
+++ b/drivers/media/dvb/frontends/s5h1420.c
@@ -38,7 +38,6 @@
 
 struct s5h1420_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct s5h1420_config* config;
 	struct dvb_frontend frontend;
 
@@ -584,7 +583,6 @@
 	struct s5h1420_state* state = fe->demodulator_priv;
 	int frequency_delta;
 	struct dvb_frontend_tune_settings fesettings;
-	u32 tmp;
 
 	/* check if we should do a fast-tune */
 	memcpy(&fesettings.parameters, p, sizeof(struct dvb_frontend_parameters));
@@ -596,10 +594,17 @@
 	    (state->fec_inner == p->u.qpsk.fec_inner) &&
 	    (state->symbol_rate == p->u.qpsk.symbol_rate)) {
 
-		if (state->config->pll_set) {
-			s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-			state->config->pll_set(fe, p, &tmp);
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe, p);
+			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+		if (fe->ops.tuner_ops.get_frequency) {
+			u32 tmp;
+			fe->ops.tuner_ops.get_frequency(fe, &tmp);
+			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 			s5h1420_setfreqoffset(state, p->frequency - tmp);
+		} else {
+			s5h1420_setfreqoffset(state, 0);
 		}
 		return 0;
 	}
@@ -646,9 +651,9 @@
 	s5h1420_writereg(state, 0x05, s5h1420_readreg(state, 0x05) | 1);
 
 	/* set tuner PLL */
-	if (state->config->pll_set) {
-		s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-		state->config->pll_set(fe, p, &tmp);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 		s5h1420_setfreqoffset(state, 0);
 	}
 
@@ -708,6 +713,17 @@
 	return 0;
 }
 
+static int s5h1420_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct s5h1420_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
+	} else {
+		return s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
+	}
+}
+
 static int s5h1420_init (struct dvb_frontend* fe)
 {
 	struct s5h1420_state* state = fe->demodulator_priv;
@@ -717,13 +733,6 @@
 	msleep(10);
 	s5h1420_reset(state);
 
-	/* init PLL */
-	if (state->config->pll_init) {
-		s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) | 1);
-		state->config->pll_init(fe);
-		s5h1420_writereg (state, 0x02, s5h1420_readreg(state,0x02) & 0xfe);
-	}
-
 	return 0;
 }
 
@@ -756,7 +765,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
 	state->postlocked = 0;
 	state->fclk = 88000000;
 	state->tunedfreq = 0;
@@ -769,7 +777,7 @@
 		goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &s5h1420_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -800,6 +808,7 @@
 
 	.init = s5h1420_init,
 	.sleep = s5h1420_sleep,
+	.i2c_gate_ctrl = s5h1420_i2c_gate_ctrl,
 
 	.set_frontend = s5h1420_set_frontend,
 	.get_frontend = s5h1420_get_frontend,
diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h
index 73296f1..4e39015 100644
--- a/drivers/media/dvb/frontends/s5h1420.h
+++ b/drivers/media/dvb/frontends/s5h1420.h
@@ -32,10 +32,6 @@
 
 	/* does the inversion require inversion? */
 	u8 invert:1;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout);
 };
 
 extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config,
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index 73829e6..44ec5b9 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -44,8 +44,6 @@
 
 	struct i2c_adapter* i2c;
 
-	struct dvb_frontend_ops ops;
-
 	const struct sp8870_config* config;
 
 	struct dvb_frontend frontend;
@@ -262,9 +260,10 @@
 	sp8870_microcontroller_stop(state);
 
 	// set tuner parameters
-	sp8870_writereg(state, 0x206, 0x001);
-	state->config->pll_set(fe, p);
-	sp8870_writereg(state, 0x206, 0x000);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	// sample rate correction bit [23..17]
 	sp8870_writereg(state, 0x0319, 0x000A);
@@ -349,13 +348,6 @@
 	sp8870_writereg(state, 0x0D00, 0x010);
 	sp8870_writereg(state, 0x0D01, 0x000);
 
-	/* setup PLL */
-	if (state->config->pll_init) {
-		sp8870_writereg(state, 0x206, 0x001);
-		state->config->pll_init(fe);
-		sp8870_writereg(state, 0x206, 0x000);
-	}
-
 	return 0;
 }
 
@@ -541,6 +533,17 @@
 	return 0;
 }
 
+static int sp8870_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct sp8870_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return sp8870_writereg(state, 0x206, 0x001);
+	} else {
+		return sp8870_writereg(state, 0x206, 0x000);
+	}
+}
+
 static void sp8870_release(struct dvb_frontend* fe)
 {
 	struct sp8870_state* state = fe->demodulator_priv;
@@ -561,14 +564,13 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
 	state->initialised = 0;
 
 	/* check if the demod is there */
 	if (sp8870_readreg(state, 0x0200) < 0) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &sp8870_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -597,6 +599,7 @@
 
 	.init = sp8870_init,
 	.sleep = sp8870_sleep,
+	.i2c_gate_ctrl = sp8870_i2c_gate_ctrl,
 
 	.set_frontend = sp8870_set_frontend,
 	.get_tune_settings = sp8870_get_tune_settings,
diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h
index f3b555d..93afbb9 100644
--- a/drivers/media/dvb/frontends/sp8870.h
+++ b/drivers/media/dvb/frontends/sp8870.h
@@ -31,10 +31,6 @@
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
 	/* request firmware for device */
 	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index eb8a602..b0a2b02 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -24,7 +24,6 @@
 
 struct sp887x_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct sp887x_config* config;
 	struct dvb_frontend frontend;
 
@@ -208,15 +207,6 @@
 	/* bit 0x010: enable data valid signal */
 	sp887x_writereg(state, 0xd00, 0x010);
 	sp887x_writereg(state, 0x0d1, 0x000);
-
-	/* setup the PLL */
-	if (state->config->pll_init) {
-		sp887x_writereg(state, 0x206, 0x001);
-		state->config->pll_init(fe);
-		sp887x_writereg(state, 0x206, 0x000);
-	}
-
-	printk ("done.\n");
 	return 0;
 };
 
@@ -362,9 +352,16 @@
 	sp887x_microcontroller_stop(state);
 
 	/* setup the PLL */
-	sp887x_writereg(state, 0x206, 0x001);
-	actual_freq = state->config->pll_set(fe, p);
-	sp887x_writereg(state, 0x206, 0x000);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+	if (fe->ops.tuner_ops.get_frequency) {
+		fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	} else {
+		actual_freq = p->frequency;
+	}
 
 	/* read status reg in order to clear <pending irqs */
 	sp887x_readreg(state, 0x200);
@@ -486,6 +483,17 @@
 	return 0;
 }
 
+static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct sp887x_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return sp887x_writereg(state, 0x206, 0x001);
+	} else {
+		return sp887x_writereg(state, 0x206, 0x000);
+	}
+}
+
 static int sp887x_sleep(struct dvb_frontend* fe)
 {
 	struct sp887x_state* state = fe->demodulator_priv;
@@ -555,14 +563,13 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
 	state->initialised = 0;
 
 	/* check if the demod is there */
 	if (sp887x_readreg(state, 0x0200) < 0) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -589,6 +596,7 @@
 
 	.init = sp887x_init,
 	.sleep = sp887x_sleep,
+	.i2c_gate_ctrl = sp887x_i2c_gate_ctrl,
 
 	.set_frontend = sp887x_setup_frontend_parameters,
 	.get_tune_settings = sp887x_get_tune_settings,
diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h
index 6a05d8f..c44b0eb 100644
--- a/drivers/media/dvb/frontends/sp887x.h
+++ b/drivers/media/dvb/frontends/sp887x.h
@@ -13,12 +13,6 @@
 	/* the demodulator's i2c address */
 	u8 demod_address;
 
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-
-	/* this should return the actual frequency tuned to */
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
 	/* request firmware for device */
 	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
 };
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index eb15676..1ca6424 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -32,7 +32,6 @@
 
 struct stv0297_state {
 	struct i2c_adapter *i2c;
-	struct dvb_frontend_ops ops;
 	const struct stv0297_config *config;
 	struct dvb_frontend frontend;
 
@@ -68,19 +67,25 @@
 	int ret;
 	u8 b0[] = { reg };
 	u8 b1[] = { 0 };
-	struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len =
-				  1},
-	{.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
-	};
+	struct i2c_msg msg[] = { {.addr = state->config->demod_address,.flags = 0,.buf = b0,.len = 1},
+				 {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = b1,.len = 1}
+			       };
 
 	// this device needs a STOP between the register and data
-	if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
-		return -1;
-	}
-	if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
-		return -1;
+	if (state->config->stop_during_read) {
+		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+			return -1;
+		}
+		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+			return -1;
+		}
+	} else {
+		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg, ret);
+			return -1;
+		}
 	}
 
 	return b1[0];
@@ -107,13 +112,20 @@
 	};
 
 	// this device needs a STOP between the register and data
-	if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
-		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
-		return -1;
-	}
-	if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
-		dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
-		return -1;
+	if (state->config->stop_during_read) {
+		if ((ret = i2c_transfer(state->i2c, &msg[0], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+			return -1;
+		}
+		if ((ret = i2c_transfer(state->i2c, &msg[1], 1)) != 1) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+			return -1;
+		}
+	} else {
+		if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
+			dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n", __FUNCTION__, reg1, ret);
+			return -1;
+		}
 	}
 
 	return 0;
@@ -276,12 +288,14 @@
 	return 0;
 }
 
-int stv0297_enable_plli2c(struct dvb_frontend *fe)
+static int stv0297_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
 	struct stv0297_state *state = fe->demodulator_priv;
 
-	stv0297_writereg(state, 0x87, 0x78);
-	stv0297_writereg(state, 0x86, 0xc8);
+	if (enable) {
+		stv0297_writereg(state, 0x87, 0x78);
+		stv0297_writereg(state, 0x86, 0xc8);
+	}
 
 	return 0;
 }
@@ -296,9 +310,6 @@
 		stv0297_writereg(state, state->config->inittab[i], state->config->inittab[i+1]);
 	msleep(200);
 
-	if (state->config->pll_init)
-		state->config->pll_init(fe);
-
 	return 0;
 }
 
@@ -389,7 +400,7 @@
 	case QAM_32:
 	case QAM_64:
 		delay = 100;
-		sweeprate = 1500;
+		sweeprate = 1000;
 		break;
 
 	case QAM_128:
@@ -421,7 +432,10 @@
 	}
 
 	stv0297_init(fe);
-	state->config->pll_set(fe, p);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	/* clear software interrupts */
 	stv0297_writereg(state, 0x82, 0x0);
@@ -634,7 +648,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
 	state->base_freq = 0;
 
 	/* check if the demod is there */
@@ -642,7 +655,7 @@
 		goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &stv0297_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -668,6 +681,7 @@
 
 	.init = stv0297_init,
 	.sleep = stv0297_sleep,
+	.i2c_gate_ctrl = stv0297_i2c_gate_ctrl,
 
 	.set_frontend = stv0297_set_frontend,
 	.get_frontend = stv0297_get_frontend,
@@ -684,4 +698,3 @@
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(stv0297_attach);
-EXPORT_SYMBOL(stv0297_enable_plli2c);
diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h
index 9e53f01..1da5384 100644
--- a/drivers/media/dvb/frontends/stv0297.h
+++ b/drivers/media/dvb/frontends/stv0297.h
@@ -38,13 +38,11 @@
 	/* does the "inversion" need inverted? */
 	u8 invert:1;
 
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+	/* set to 1 if the device requires an i2c STOP during reading */
+	u8 stop_during_read:1;
 };
 
 extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config,
 					   struct i2c_adapter* i2c);
-extern int stv0297_enable_plli2c(struct dvb_frontend* fe);
 
 #endif // STV0297_H
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 5bcd00f..96648a7 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -56,7 +56,6 @@
 
 struct stv0299_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct stv0299_config* config;
 	struct dvb_frontend frontend;
 
@@ -131,13 +130,6 @@
 	return ret == 2 ? 0 : ret;
 }
 
-int stv0299_enable_plli2c (struct dvb_frontend* fe)
-{
-	struct stv0299_state* state = fe->demodulator_priv;
-
-	return stv0299_writeregI(state, 0x05, 0xb5);	/*  enable i2c repeater on stv0299  */
-}
-
 static int stv0299_set_FEC (struct stv0299_state* state, fe_code_rate_t fec)
 {
 	dprintk ("%s\n", __FUNCTION__);
@@ -457,12 +449,6 @@
 	for (i=0; !(state->config->inittab[i] == 0xff && state->config->inittab[i+1] == 0xff); i+=2)
 		stv0299_writeregI(state, state->config->inittab[i], state->config->inittab[i+1]);
 
-	if (state->config->pll_init) {
-		stv0299_writeregI(state, 0x05, 0xb5);	/*  enable i2c repeater on stv0299  */
-		state->config->pll_init(fe, state->i2c);
-		stv0299_writeregI(state, 0x05, 0x35);	/*  disable i2c repeater on stv0299  */
-	}
-
 	return 0;
 }
 
@@ -560,9 +546,10 @@
 	if (state->config->invert) invval = (~invval) & 1;
 	stv0299_writeregI(state, 0x0c, (stv0299_readreg(state, 0x0c) & 0xfe) | invval);
 
-	stv0299_writeregI(state, 0x05, 0xb5);	/*  enable i2c repeater on stv0299  */
-	state->config->pll_set(fe, state->i2c, p);
-	stv0299_writeregI(state, 0x05, 0x35);	/*  disable i2c repeater on stv0299  */
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	stv0299_set_FEC (state, p->u.qpsk.fec_inner);
 	stv0299_set_symbolrate (fe, p->u.qpsk.symbol_rate);
@@ -611,6 +598,19 @@
 	return 0;
 }
 
+static int stv0299_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct stv0299_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		stv0299_writeregI(state, 0x05, 0xb5);
+	} else {
+		stv0299_writeregI(state, 0x05, 0x35);
+	}
+	udelay(1);
+	return 0;
+}
+
 static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
 	struct stv0299_state* state = fe->demodulator_priv;
@@ -647,7 +647,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
 	state->initialised = 0;
 	state->tuner_frequency = 0;
 	state->symbol_rate = 0;
@@ -664,7 +663,7 @@
 	if (id != 0xa1 && id != 0x80) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &stv0299_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -695,6 +694,7 @@
 
 	.init = stv0299_init,
 	.sleep = stv0299_sleep,
+	.i2c_gate_ctrl = stv0299_i2c_gate_ctrl,
 
 	.set_frontend = stv0299_set_frontend,
 	.get_frontend = stv0299_get_frontend,
@@ -721,9 +721,8 @@
 
 MODULE_DESCRIPTION("ST STV0299 DVB Demodulator driver");
 MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, "
-	      "Andreas Oberritter, Andrew de Quincey, Kenneth Aafløy");
+	      "Andreas Oberritter, Andrew de Quincey, Kenneth Aafly");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(stv0299_enable_plli2c);
 EXPORT_SYMBOL(stv0299_writereg);
 EXPORT_SYMBOL(stv0299_attach);
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 32c87b4..1504828 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -87,14 +87,9 @@
 
 	/* Set the symbol rate */
 	int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio);
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend *fe, struct i2c_adapter *i2c);
-	int (*pll_set)(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params);
 };
 
 extern int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data);
-extern int stv0299_enable_plli2c (struct dvb_frontend* fe);
 
 extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
 					   struct i2c_adapter* i2c);
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 21255ca..e83ff21 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -36,7 +36,6 @@
 
 struct tda10021_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	/* configuration settings */
 	const struct tda10021_config* config;
 	struct dvb_frontend frontend;
@@ -90,6 +89,14 @@
 	return (ret != 1) ? -EREMOTEIO : 0;
 }
 
+int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	return tda10021_writereg(state, reg, data);
+}
+EXPORT_SYMBOL(tda10021_write_byte);
+
 static u8 tda10021_readreg (struct tda10021_state* state, u8 reg)
 {
 	u8 b0 [] = { reg };
@@ -225,13 +232,6 @@
 
 	//Activate PLL
 	tda10021_writereg(state, 0x2a, tda10021_inittab[0x2a] & 0xef);
-
-	if (state->config->pll_init) {
-		lock_tuner(state);
-		state->config->pll_init(fe);
-		unlock_tuner(state);
-	}
-
 	return 0;
 }
 
@@ -259,9 +259,10 @@
 
 	//printk("tda10021: set frequency to %d qam=%d symrate=%d\n", p->frequency,qam,p->u.qam.symbol_rate);
 
-	lock_tuner(state);
-	state->config->pll_set(fe, p);
-	unlock_tuner(state);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 
 	tda10021_set_symbolrate (state, p->u.qam.symbol_rate);
 	tda10021_writereg (state, 0x34, state->pwm);
@@ -376,6 +377,18 @@
 	return 0;
 }
 
+static int tda10021_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct tda10021_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		lock_tuner(state);
+	} else {
+		unlock_tuner(state);
+	}
+	return 0;
+}
+
 static int tda10021_sleep(struct dvb_frontend* fe)
 {
 	struct tda10021_state* state = fe->demodulator_priv;
@@ -407,7 +420,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
 	state->pwm = pwm;
 	state->reg0 = tda10021_inittab[0];
 
@@ -415,7 +427,7 @@
 	if ((tda10021_readreg(state, 0x1a) & 0xf0) != 0x70) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &tda10021_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -448,6 +460,7 @@
 
 	.init = tda10021_init,
 	.sleep = tda10021_sleep,
+	.i2c_gate_ctrl = tda10021_i2c_gate_ctrl,
 
 	.set_frontend = tda10021_set_parameters,
 	.get_frontend = tda10021_get_frontend,
diff --git a/drivers/media/dvb/frontends/tda10021.h b/drivers/media/dvb/frontends/tda10021.h
index 53be939..b1df425 100644
--- a/drivers/media/dvb/frontends/tda10021.h
+++ b/drivers/media/dvb/frontends/tda10021.h
@@ -30,13 +30,11 @@
 {
 	/* the demodulator's i2c address */
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
 					    struct i2c_adapter* i2c, u8 pwm);
 
+extern int tda10021_write_byte(struct dvb_frontend* fe, int reg, int data);
+
 #endif // TDA10021_H
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index b83dafa..59a2ed6 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -47,7 +47,6 @@
 
 struct tda1004x_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	const struct tda1004x_config* config;
 	struct dvb_frontend frontend;
 
@@ -600,13 +599,6 @@
 
 	tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0); // wake up the ADC
 
-	// Init the PLL
-	if (state->config->pll_init) {
-		tda1004x_enable_tuner_i2c(state);
-		state->config->pll_init(fe);
-		tda1004x_disable_tuner_i2c(state);
-	}
-
 	// tda setup
 	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
 	tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
@@ -635,16 +627,6 @@
 			return -EIO;
 	}
 
-	// Init the tuner PLL
-	if (state->config->pll_init) {
-		tda1004x_enable_tuner_i2c(state);
-		if (state->config->pll_init(fe)) {
-			printk(KERN_ERR "tda1004x: pll init failed\n");
-			return 	-EIO;
-		}
-		tda1004x_disable_tuner_i2c(state);
-	}
-
 	// tda setup
 	tda1004x_write_mask(state, TDA1004X_CONFC4, 0x20, 0); // disable DSP watchdog timer
 	tda1004x_write_byteI(state, TDA1004X_AUTO, 0x87);    // 100 ppm crystal, select HP stream
@@ -712,12 +694,10 @@
 	}
 
 	// set frequency
-	tda1004x_enable_tuner_i2c(state);
-	if (state->config->pll_set(fe, fe_params)) {
-		printk(KERN_ERR "tda1004x: pll set failed\n");
-		return 	-EIO;
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, fe_params);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
 	}
-	tda1004x_disable_tuner_i2c(state);
 
 	// Hardcoded to use auto as much as possible on the TDA10045 as it
 	// is very unreliable if AUTO mode is _not_ used.
@@ -1183,16 +1163,6 @@
 		break;
 
 	case TDA1004X_DEMOD_TDA10046:
-		if (state->config->pll_sleep != NULL) {
-			tda1004x_enable_tuner_i2c(state);
-			state->config->pll_sleep(fe);
-			if (state->config->if_freq != TDA10046_FREQ_052) {
-				/* special hack for Philips EUROPA Based boards:
-				 * keep the I2c bridge open for tuner access in analog mode
-				 */
-				tda1004x_disable_tuner_i2c(state);
-			}
-		}
 		/* set outputs to tristate */
 		tda1004x_write_byteI(state, TDA10046H_CONF_TRISTATE1, 0xff);
 		tda1004x_write_mask(state, TDA1004X_CONFC4, 1, 1);
@@ -1202,6 +1172,17 @@
 	return 0;
 }
 
+static int tda1004x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct tda1004x_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return tda1004x_enable_tuner_i2c(state);
+	} else {
+		return tda1004x_disable_tuner_i2c(state);
+	}
+}
+
 static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
 {
 	fesettings->min_delay_ms = 800;
@@ -1235,6 +1216,7 @@
 
 	.init = tda10045_init,
 	.sleep = tda1004x_sleep,
+	.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
 
 	.set_frontend = tda1004x_set_fe,
 	.get_frontend = tda1004x_get_fe,
@@ -1260,7 +1242,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
 	state->demod_type = TDA1004X_DEMOD_TDA10045;
 
 	/* check if the demod is there */
@@ -1270,7 +1251,7 @@
 	}
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 }
@@ -1293,6 +1274,7 @@
 
 	.init = tda10046_init,
 	.sleep = tda1004x_sleep,
+	.i2c_gate_ctrl = tda1004x_i2c_gate_ctrl,
 
 	.set_frontend = tda1004x_set_fe,
 	.get_frontend = tda1004x_get_fe,
@@ -1318,7 +1300,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
 	state->demod_type = TDA1004X_DEMOD_TDA10046;
 
 	/* check if the demod is there */
@@ -1328,7 +1309,7 @@
 	}
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 }
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h
index cc0c4af..b877b23 100644
--- a/drivers/media/dvb/frontends/tda1004x.h
+++ b/drivers/media/dvb/frontends/tda1004x.h
@@ -66,11 +66,6 @@
 	/* AGC configuration */
 	enum tda10046_agc agc_config;
 
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	void (*pll_sleep)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
-
 	/* request firmware for device */
 	/* set this to NULL if the card has a firmware EEPROM */
 	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index 91baa9c..3aa45eb 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -37,7 +37,6 @@
 
 struct tda8083_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	/* configuration settings */
 	const struct tda8083_config* config;
 	struct dvb_frontend frontend;
@@ -293,7 +292,11 @@
 {
 	struct tda8083_state* state = fe->demodulator_priv;
 
-	state->config->pll_set(fe, p);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
 	tda8083_set_inversion (state, p->inversion);
 	tda8083_set_fec (state, p->u.qpsk.fec_inner);
 	tda8083_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -334,8 +337,6 @@
 	for (i=0; i<44; i++)
 		tda8083_writereg (state, i, tda8083_init_tab[i]);
 
-	if (state->config->pll_init) state->config->pll_init(fe);
-
 	tda8083_writereg (state, 0x00, 0x3c);
 	tda8083_writereg (state, 0x00, 0x04);
 
@@ -395,13 +396,12 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check if the demod is there */
 	if ((tda8083_readreg(state, 0x00)) != 0x05) goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &tda8083_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h
index 4666633..e7a48f6 100644
--- a/drivers/media/dvb/frontends/tda8083.h
+++ b/drivers/media/dvb/frontends/tda8083.h
@@ -33,10 +33,6 @@
 {
 	/* the demodulator's i2c address */
 	u8 demod_address;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index ad8647a3..6bffe85 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -35,7 +35,6 @@
 
 struct ves1820_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	/* configuration settings */
 	const struct ves1820_config* config;
 	struct dvb_frontend frontend;
@@ -204,9 +203,6 @@
 
 	ves1820_writereg(state, 0x34, state->pwm);
 
-	if (state->config->pll_init)
-		state->config->pll_init(fe);
-
 	return 0;
 }
 
@@ -223,7 +219,11 @@
 	if (real_qam < 0 || real_qam > 4)
 		return -EINVAL;
 
-	state->config->pll_set(fe, p);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
 	ves1820_set_symbolrate(state, p->u.qam.symbol_rate);
 	ves1820_writereg(state, 0x34, state->pwm);
 
@@ -380,7 +380,6 @@
 		goto error;
 
 	/* setup the state */
-	memcpy(&state->ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
 	state->reg0 = ves1820_inittab[0];
 	state->config = config;
 	state->i2c = i2c;
@@ -393,12 +392,12 @@
 	if (verbose)
 		printk("ves1820: pwm=0x%02x\n", state->pwm);
 
-	state->ops.info.symbol_rate_min = (state->config->xin / 2) / 64;      /* SACLK/64 == (XIN/2)/64 */
-	state->ops.info.symbol_rate_max = (state->config->xin / 2) / 4;       /* SACLK/4 */
-
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &ves1820_ops, sizeof(struct dvb_frontend_ops));
+	state->frontend.ops.info.symbol_rate_min = (state->config->xin / 2) / 64;      /* SACLK/64 == (XIN/2)/64 */
+	state->frontend.ops.info.symbol_rate_max = (state->config->xin / 2) / 4;       /* SACLK/4 */
 	state->frontend.demodulator_priv = state;
+
 	return &state->frontend;
 
 error:
diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h
index 355f130..520f095 100644
--- a/drivers/media/dvb/frontends/ves1820.h
+++ b/drivers/media/dvb/frontends/ves1820.h
@@ -39,10 +39,6 @@
 
 	/* SELAGC control */
 	u8 selagc:1;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
index 821df8e..54d7b07 100644
--- a/drivers/media/dvb/frontends/ves1x93.c
+++ b/drivers/media/dvb/frontends/ves1x93.c
@@ -36,7 +36,6 @@
 
 struct ves1x93_state {
 	struct i2c_adapter* i2c;
-	struct dvb_frontend_ops ops;
 	/* configuration settings */
 	const struct ves1x93_config* config;
 	struct dvb_frontend frontend;
@@ -278,12 +277,6 @@
 		}
 	}
 
-	if (state->config->pll_init) {
-		ves1x93_writereg(state, 0x00, 0x11);
-		state->config->pll_init(fe);
-		ves1x93_writereg(state, 0x00, 0x01);
-	}
-
 	return 0;
 }
 
@@ -395,9 +388,10 @@
 {
 	struct ves1x93_state* state = fe->demodulator_priv;
 
-	ves1x93_writereg(state, 0x00, 0x11);
-	state->config->pll_set(fe, p);
-	ves1x93_writereg(state, 0x00, 0x01);
+	if (fe->ops.tuner_ops.set_params) {
+		fe->ops.tuner_ops.set_params(fe, p);
+		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+	}
 	ves1x93_set_inversion (state, p->inversion);
 	ves1x93_set_fec (state, p->u.qpsk.fec_inner);
 	ves1x93_set_symbolrate (state, p->u.qpsk.symbol_rate);
@@ -442,6 +436,17 @@
 	kfree(state);
 }
 
+static int ves1x93_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
+{
+	struct ves1x93_state* state = fe->demodulator_priv;
+
+	if (enable) {
+		return ves1x93_writereg(state, 0x00, 0x11);
+	} else {
+		return ves1x93_writereg(state, 0x00, 0x01);
+	}
+}
+
 static struct dvb_frontend_ops ves1x93_ops;
 
 struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
@@ -457,7 +462,6 @@
 	/* setup the state */
 	state->config = config;
 	state->i2c = i2c;
-	memcpy(&state->ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
 	state->inversion = INVERSION_OFF;
 
 	/* check if the demod is there + identify it */
@@ -492,7 +496,7 @@
 	}
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &ves1x93_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 
@@ -523,6 +527,7 @@
 
 	.init = ves1x93_init,
 	.sleep = ves1x93_sleep,
+	.i2c_gate_ctrl = ves1x93_i2c_gate_ctrl,
 
 	.set_frontend = ves1x93_set_frontend,
 	.get_frontend = ves1x93_get_frontend,
diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h
index 1627e37..ba88ae0 100644
--- a/drivers/media/dvb/frontends/ves1x93.h
+++ b/drivers/media/dvb/frontends/ves1x93.h
@@ -38,10 +38,6 @@
 
 	/* should PWM be inverted? */
 	u8 invert_pwm:1;
-
-	/* PLL maintenance */
-	int (*pll_init)(struct dvb_frontend* fe);
-	int (*pll_set)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
 };
 
 extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c
index d7d9f59..2b95e8b 100644
--- a/drivers/media/dvb/frontends/zl10353.c
+++ b/drivers/media/dvb/frontends/zl10353.c
@@ -34,7 +34,6 @@
 struct zl10353_state {
 	struct i2c_adapter *i2c;
 	struct dvb_frontend frontend;
-	struct dvb_frontend_ops ops;
 
 	struct zl10353_config config;
 };
@@ -126,6 +125,7 @@
 				  struct dvb_frontend_parameters *param)
 {
 	struct zl10353_state *state = fe->demodulator_priv;
+
 	u8 pllbuf[6] = { 0x67 };
 
 	/* These settings set "auto-everything" and start the FSM. */
@@ -142,7 +142,30 @@
 	zl10353_single_write(fe, 0x66, 0xE9);
 	zl10353_single_write(fe, 0x62, 0x0A);
 
-	state->config.pll_set(fe, param, pllbuf + 1);
+	// if there is no attached secondary tuner, we call set_params to program
+	// a potential tuner attached somewhere else
+	if (state->config.no_tuner) {
+		if (fe->ops.tuner_ops.set_params) {
+			fe->ops.tuner_ops.set_params(fe, param);
+			if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
+		}
+	}
+
+	// if pllbuf is defined, retrieve the settings
+	if (fe->ops.tuner_ops.calc_regs) {
+		fe->ops.tuner_ops.calc_regs(fe, param, pllbuf+1, 5);
+		pllbuf[1] <<= 1;
+	} else {
+		// fake pllbuf settings
+		pllbuf[1] = 0x61 << 1;
+		pllbuf[2] = 0;
+		pllbuf[3] = 0;
+		pllbuf[3] = 0;
+		pllbuf[4] = 0;
+	}
+
+	// there is no call to _just_ start decoding, so we send the pllbuf anyway
+	// even if there isn't a PLL attached to the secondary bus
 	zl10353_write(fe, pllbuf, sizeof(pllbuf));
 
 	zl10353_single_write(fe, 0x70, 0x01);
@@ -254,14 +277,13 @@
 	/* setup the state */
 	state->i2c = i2c;
 	memcpy(&state->config, config, sizeof(struct zl10353_config));
-	memcpy(&state->ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
 
 	/* check if the demod is there */
 	if (zl10353_read_register(state, CHIP_ID) != ID_ZL10353)
 		goto error;
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &zl10353_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 
 	return &state->frontend;
diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h
index 5cc4ae71..9770cb8 100644
--- a/drivers/media/dvb/frontends/zl10353.h
+++ b/drivers/media/dvb/frontends/zl10353.h
@@ -29,10 +29,8 @@
 	/* demodulator's I2C address */
 	u8 demod_address;
 
-	/* function which configures the PLL buffer (for secondary I2C
-	 * connected tuner) or tunes the PLL (for direct connected tuner) */
-	int (*pll_set)(struct dvb_frontend *fe,
-		       struct dvb_frontend_parameters *params, u8 *pllbuf);
+	/* set if no pll is connected to the secondary i2c bus */
+	int no_tuner;
 };
 
 extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config,
diff --git a/drivers/media/dvb/pluto2/pluto2.c b/drivers/media/dvb/pluto2/pluto2.c
index 1c5316e..acabea0 100644
--- a/drivers/media/dvb/pluto2/pluto2.c
+++ b/drivers/media/dvb/pluto2/pluto2.c
@@ -424,8 +424,8 @@
 }
 
 /* LG Innotek TDTE-E001P (Infineon TUA6034) */
-static int lg_tdtpe001p_pll_set(struct dvb_frontend *fe,
-				struct dvb_frontend_parameters *p)
+static int lg_tdtpe001p_tuner_set_params(struct dvb_frontend *fe,
+					 struct dvb_frontend_parameters *p)
 {
 	struct pluto *pluto = frontend_to_pluto(fe);
 	struct i2c_msg msg;
@@ -473,6 +473,8 @@
 	msg.buf = buf;
 	msg.len = sizeof(buf);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	ret = i2c_transfer(&pluto->i2c_adap, &msg, 1);
 	if (ret < 0)
 		return ret;
@@ -497,8 +499,6 @@
 	.xtal_freq = TDA10046_XTAL_16M,
 	.agc_config = TDA10046_AGC_DEFAULT,
 	.if_freq = TDA10046_FREQ_3617,
-	.pll_set = lg_tdtpe001p_pll_set,
-	.pll_sleep = NULL,
 	.request_firmware = pluto2_request_firmware,
 };
 
@@ -511,11 +511,12 @@
 		dev_err(&pluto->pdev->dev, "could not attach frontend\n");
 		return -ENODEV;
 	}
+	pluto->fe->ops.tuner_ops.set_params = lg_tdtpe001p_tuner_set_params;
 
 	ret = dvb_register_frontend(&pluto->dvb_adapter, pluto->fe);
 	if (ret < 0) {
-		if (pluto->fe->ops->release)
-			pluto->fe->ops->release(pluto->fe);
+		if (pluto->fe->ops.release)
+			pluto->fe->ops.release(pluto->fe);
 		return ret;
 	}
 
@@ -647,7 +648,7 @@
 		goto err_pluto_hw_exit;
 
 	/* dvb */
-	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE);
+	ret = dvb_register_adapter(&pluto->dvb_adapter, DRIVER_NAME, THIS_MODULE, &pdev->dev);
 	if (ret < 0)
 		goto err_i2c_bit_del_bus;
 
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig
index b5ac7df..987881f 100644
--- a/drivers/media/dvb/ttpci/Kconfig
+++ b/drivers/media/dvb/ttpci/Kconfig
@@ -10,6 +10,7 @@
 	select DVB_SP8870
 	select DVB_STV0297
 	select DVB_L64781
+	select DVB_LNBP21
 	help
 	  Support for SAA7146 and AV7110 based DVB cards as produced
 	  by Fujitsu-Siemens, Technotrend, Hauppauge and others.
@@ -67,6 +68,7 @@
 	select DVB_TDA8083
 	select DVB_TDA10021
 	select DVB_S5H1420
+	select DVB_LNBP21
 	help
 	  Support for simple SAA7146 based DVB cards
 	  (so called Budget- or Nova-PCI cards) without onboard
@@ -84,6 +86,7 @@
 	select DVB_STV0297
 	select DVB_STV0299
 	select DVB_TDA1004X
+	select DVB_LNBP21
 	help
 	  Support for simple SAA7146 based DVB cards
 	  (so called Budget- or Nova-PCI cards) without onboard
diff --git a/drivers/media/dvb/ttpci/Makefile b/drivers/media/dvb/ttpci/Makefile
index a690730..aa85ecd 100644
--- a/drivers/media/dvb/ttpci/Makefile
+++ b/drivers/media/dvb/ttpci/Makefile
@@ -15,9 +15,9 @@
 
 hostprogs-y	:= fdump
 
-ifdef CONFIG_DVB_AV7110_FIRMWARE
-$(obj)/av7110.o: $(obj)/fdump $(obj)/av7110_firm.h
+ifeq ($(CONFIG_DVB_AV7110_FIRMWARE),y)
+$(obj)/av7110.o: $(obj)/av7110_firm.h
 
-$(obj)/av7110_firm.h:
+$(obj)/av7110_firm.h: $(obj)/fdump
 	$(obj)/fdump $(CONFIG_DVB_AV7110_FIRMWARE_FILE) dvb_ttpci_fw $@
 endif
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index d028245..7a5c99c 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -152,13 +152,9 @@
 	/* remaining inits according to card and frontend type */
 	av7110->analog_tuner_flags = 0;
 	av7110->current_input = 0;
-	if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a) {
-		printk("dvb-ttpci: MSP3415 audio DAC @ card %d\n",
-			av7110->dvb_adapter.num);
-		av7110->adac_type = DVB_ADAC_MSP34x5;
+	if (dev->pci->subsystem_vendor == 0x13c2 && dev->pci->subsystem_device == 0x000a)
 		av7110_fw_cmd(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 0); // SPDIF on
-	}
-	else if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
+	if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
 		printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
 			av7110->dvb_adapter.num);
 		av7110->adac_type = DVB_ADAC_CRYSTAL;
@@ -1552,7 +1548,7 @@
 #endif
 
 
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
 	u8 pwr = 0;
@@ -1575,6 +1571,8 @@
 	// NOTE: since we're using a prescaler of 2, we set the
 	// divisor frequency to 62.5kHz and divide by 125 above
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -1584,10 +1582,9 @@
 	.demod_address = 0x08,
 	.xin = 90100000UL,
 	.invert_pwm = 0,
-	.pll_set = alps_bsrv2_pll_set,
 };
 
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct av7110* av7110 = fe->dvb->priv;
 	u32 div;
@@ -1601,6 +1598,8 @@
 	data[2] = 0x85 | ((div >> 10) & 0x60);
 	data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -1611,14 +1610,12 @@
 	.xin = 57840000UL,
 	.invert = 1,
 	.selagc = VES1820_SELAGC_SIGNAMPERR,
-	.pll_set = alps_tdbe2_pll_set,
 };
 
 
 
 
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe,
-				     struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct av7110* av7110 = fe->dvb->priv;
 	u32 div;
@@ -1631,6 +1628,8 @@
 	data[2] = 0x8e;
 	data[3] = 0x00;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -1638,13 +1637,11 @@
 
 static struct tda8083_config grundig_29504_451_config = {
 	.demod_address = 0x68,
-	.pll_set = grundig_29504_451_pll_set,
 };
 
 
 
-static int philips_cd1516_pll_set(struct dvb_frontend* fe,
-				  struct dvb_frontend_parameters* params)
+static int philips_cd1516_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct av7110* av7110 = fe->dvb->priv;
 	u32 div;
@@ -1659,6 +1656,8 @@
 	data[2] = 0x8e;
 	data[3] = (f < 174000000 ? 0xa1 : f < 470000000 ? 0x92 : 0x34);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -1669,12 +1668,11 @@
 	.xin = 57840000UL,
 	.invert = 1,
 	.selagc = VES1820_SELAGC_SIGNAMPERR,
-	.pll_set = philips_cd1516_pll_set,
 };
 
 
 
-static int alps_tdlb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdlb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct av7110* av7110 = fe->dvb->priv;
 	u32 div, pwr;
@@ -1693,6 +1691,8 @@
 	data[2] = 0x85;
 	data[3] = pwr << 6;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -1708,7 +1708,6 @@
 static struct sp8870_config alps_tdlb7_config = {
 
 	.demod_address = 0x71,
-	.pll_set = alps_tdlb7_pll_set,
 	.request_firmware = alps_tdlb7_request_firmware,
 };
 
@@ -1806,7 +1805,7 @@
 	0xff, 0xff,
 };
 
-static int nexusca_stv0297_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int nexusca_stv0297_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct av7110* av7110 = fe->dvb->priv;
 	u32 div;
@@ -1832,7 +1831,8 @@
 	else
 		return -EINVAL;
 
-	stv0297_enable_plli2c(fe);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&av7110->i2c_adap, &msg, 1) != 1) {
 		printk("nexusca: pll transfer failed!\n");
 		return -EIO;
@@ -1840,8 +1840,8 @@
 
 	// wait for PLL lock
 	for(i = 0; i < 20; i++) {
-
-		stv0297_enable_plli2c(fe);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
 		if (i2c_transfer(&av7110->i2c_adap, &readmsg, 1) == 1)
 			if (data[0] & 0x40) break;
 		msleep(10);
@@ -1855,12 +1855,12 @@
 	.demod_address = 0x1C,
 	.inittab = nexusca_stv0297_inittab,
 	.invert = 1,
-	.pll_set = nexusca_stv0297_pll_set,
+	.stop_during_read = 1,
 };
 
 
 
-static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters *params)
 {
 	struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
 	u32 div;
@@ -1887,13 +1887,14 @@
 	data[2] = ((div >> 10) & 0x60) | cfg;
 	data[3] = (cpump << 6) | band_select;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&av7110->i2c_adap, &msg, 1) != 1) return -EIO;
 	return 0;
 }
 
 static struct l64781_config grundig_29504_401_config = {
 	.demod_address = 0x55,
-	.pll_set = grundig_29504_401_pll_set,
 };
 
 
@@ -2079,6 +2080,9 @@
 		case 0x0000: // Fujitsu/Siemens DVB-Cable (ves1820/Philips CD1516(??))
 			av7110->fe = ves1820_attach(&philips_cd1516_config,
 						    &av7110->i2c_adap, read_pwm(av7110));
+			if (av7110->fe) {
+				av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+			}
 			break;
 		}
 
@@ -2091,9 +2095,10 @@
 			// try the ALPS BSRV2 first of all
 			av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
 			if (av7110->fe) {
-				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops->set_tone = av7110_set_tone;
+				av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+				av7110->fe->ops.set_tone = av7110_set_tone;
 				av7110->recover = dvb_s_recover;
 				break;
 			}
@@ -2101,9 +2106,12 @@
 			// try the ALPS BSRU6 now
 			av7110->fe = stv0299_attach(&alps_bsru6_config, &av7110->i2c_adap);
 			if (av7110->fe) {
-				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops->set_tone = av7110_set_tone;
+				av7110->fe->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+				av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+				av7110->fe->ops.set_tone = av7110_set_tone;
 				av7110->recover = dvb_s_recover;
 				break;
 			}
@@ -2111,9 +2119,10 @@
 			// Try the grundig 29504-451
 			av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
 			if (av7110->fe) {
-				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops->set_tone = av7110_set_tone;
+				av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+				av7110->fe->ops.set_tone = av7110_set_tone;
 				av7110->recover = dvb_s_recover;
 				break;
 			}
@@ -2124,11 +2133,17 @@
 				/* Siemens DVB-C (full-length card) VES1820/Philips CD1516 */
 				av7110->fe = ves1820_attach(&philips_cd1516_config, &av7110->i2c_adap,
 							read_pwm(av7110));
+				if (av7110->fe) {
+					av7110->fe->ops.tuner_ops.set_params = philips_cd1516_tuner_set_params;
+				}
 				break;
 			case 0x0003:
 				/* Hauppauge DVB-C 2.1 VES1820/ALPS TDBE2 */
 				av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap,
 							read_pwm(av7110));
+				if (av7110->fe) {
+					av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+				}
 				break;
 			}
 			break;
@@ -2137,20 +2152,27 @@
 
 			// ALPS TDLB7
 			av7110->fe = sp8870_attach(&alps_tdlb7_config, &av7110->i2c_adap);
+			if (av7110->fe) {
+				av7110->fe->ops.tuner_ops.set_params = alps_tdlb7_tuner_set_params;
+			}
 			break;
 
 		case 0x0002: // Hauppauge/TT DVB-C premium rev2.X
 
 			av7110->fe = ves1820_attach(&alps_tdbe2_config, &av7110->i2c_adap, read_pwm(av7110));
+			if (av7110->fe) {
+				av7110->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+			}
 			break;
 
 		case 0x0004: // Galaxis DVB-S rev1.3
 			/* ALPS BSRV2 */
 			av7110->fe = ves1x93_attach(&alps_bsrv2_config, &av7110->i2c_adap);
 			if (av7110->fe) {
-				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops->set_tone = av7110_set_tone;
+				av7110->fe->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+				av7110->fe->ops.set_tone = av7110_set_tone;
 				av7110->recover = dvb_s_recover;
 			}
 			break;
@@ -2159,9 +2181,10 @@
 			/* Grundig 29504-451 */
 			av7110->fe = tda8083_attach(&grundig_29504_451_config, &av7110->i2c_adap);
 			if (av7110->fe) {
-				av7110->fe->ops->diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
-				av7110->fe->ops->diseqc_send_burst = av7110_diseqc_send_burst;
-				av7110->fe->ops->set_tone = av7110_set_tone;
+				av7110->fe->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+				av7110->fe->ops.diseqc_send_master_cmd = av7110_diseqc_send_master_cmd;
+				av7110->fe->ops.diseqc_send_burst = av7110_diseqc_send_burst;
+				av7110->fe->ops.set_tone = av7110_set_tone;
 				av7110->recover = dvb_s_recover;
 			}
 			break;
@@ -2169,12 +2192,17 @@
 		case 0x0008: // Hauppauge/TT DVB-T
 
 			av7110->fe = l64781_attach(&grundig_29504_401_config, &av7110->i2c_adap);
+			if (av7110->fe) {
+				av7110->fe->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+			}
 			break;
 
 		case 0x000A: // Hauppauge/TT Nexus-CA rev1.X
 
 			av7110->fe = stv0297_attach(&nexusca_stv0297_config, &av7110->i2c_adap);
 			if (av7110->fe) {
+				av7110->fe->ops.tuner_ops.set_params = nexusca_stv0297_tuner_set_params;
+
 				/* set TDA9819 into DVB mode */
 				saa7146_setgpio(av7110->dev, 1, SAA7146_GPIO_OUTLO); // TDA9198 pin9(STD)
 				saa7146_setgpio(av7110->dev, 3, SAA7146_GPIO_OUTLO); // TDA9198 pin30(VIF)
@@ -2189,13 +2217,16 @@
 			/* ALPS BSBE1 */
 			av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
 			if (av7110->fe) {
-				if (lnbp21_init(av7110->fe, &av7110->i2c_adap, 0, 0)) {
+				av7110->fe->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+				av7110->fe->tuner_priv = &av7110->i2c_adap;
+
+				if (lnbp21_attach(av7110->fe, &av7110->i2c_adap, 0, 0)) {
 					printk("dvb-ttpci: LNBP21 not found!\n");
-					if (av7110->fe->ops->release)
-						av7110->fe->ops->release(av7110->fe);
+					if (av7110->fe->ops.release)
+						av7110->fe->ops.release(av7110->fe);
 					av7110->fe = NULL;
 				} else {
-					av7110->fe->ops->dishnetwork_send_legacy_command = NULL;
+					av7110->fe->ops.dishnetwork_send_legacy_command = NULL;
 					av7110->recover = dvb_s_recover;
 				}
 			}
@@ -2212,21 +2243,21 @@
 		       av7110->dev->pci->subsystem_vendor,
 		       av7110->dev->pci->subsystem_device);
 	} else {
-		FE_FUNC_OVERRIDE(av7110->fe->ops->init, av7110->fe_init, av7110_fe_init);
-		FE_FUNC_OVERRIDE(av7110->fe->ops->read_status, av7110->fe_read_status, av7110_fe_read_status);
-		FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
-		FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
-		FE_FUNC_OVERRIDE(av7110->fe->ops->diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
-		FE_FUNC_OVERRIDE(av7110->fe->ops->set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
-		FE_FUNC_OVERRIDE(av7110->fe->ops->set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
-		FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
-		FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.init, av7110->fe_init, av7110_fe_init);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.read_status, av7110->fe_read_status, av7110_fe_read_status);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_reset_overload, av7110->fe_diseqc_reset_overload, av7110_fe_diseqc_reset_overload);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_master_cmd, av7110->fe_diseqc_send_master_cmd, av7110_fe_diseqc_send_master_cmd);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.diseqc_send_burst, av7110->fe_diseqc_send_burst, av7110_fe_diseqc_send_burst);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.set_tone, av7110->fe_set_tone, av7110_fe_set_tone);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.set_voltage, av7110->fe_set_voltage, av7110_fe_set_voltage;)
+		FE_FUNC_OVERRIDE(av7110->fe->ops.dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
+		FE_FUNC_OVERRIDE(av7110->fe->ops.set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
 
 		ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
 		if (ret < 0) {
 			printk("av7110: Frontend registration failed!\n");
-			if (av7110->fe->ops->release)
-				av7110->fe->ops->release(av7110->fe);
+			if (av7110->fe->ops.release)
+				av7110->fe->ops.release(av7110->fe);
 			av7110->fe = NULL;
 		}
 	}
@@ -2413,7 +2444,7 @@
 		goto err_kfree_0;
 
 	ret = dvb_register_adapter(&av7110->dvb_adapter, av7110->card_name,
-				   THIS_MODULE);
+				   THIS_MODULE, &dev->pci->dev);
 	if (ret < 0)
 		goto err_put_firmware_1;
 
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index 2eff09f..0f3a044 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -318,7 +318,17 @@
 		msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
 		msp_writereg(av7110, MSP_WR_DSP, 0x0006, val); /* headphonesr */
 		return 0;
+
+	case DVB_ADAC_MSP34x5:
+		vol = (volleft > volright) ? volleft : volright;
+		val = (vol * 0x73 / 255) << 8;
+		if (vol > 0)
+			balance = ((volright - volleft) * 127) / vol;
+		msp_writereg(av7110, MSP_WR_DSP, 0x0001, balance << 8);
+		msp_writereg(av7110, MSP_WR_DSP, 0x0000, val); /* loudspeaker */
+		return 0;
 	}
+
 	return 0;
 }
 
@@ -1267,23 +1277,32 @@
 		switch(av7110->audiostate.channel_select) {
 		case AUDIO_STEREO:
 			ret = audcom(av7110, AUDIO_CMD_STEREO);
-			if (!ret)
+			if (!ret) {
 				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
 					i2c_writereg(av7110, 0x20, 0x02, 0x49);
+				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
+					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220);
+			}
 			break;
 
 		case AUDIO_MONO_LEFT:
 			ret = audcom(av7110, AUDIO_CMD_MONO_L);
-			if (!ret)
+			if (!ret) {
 				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
 					i2c_writereg(av7110, 0x20, 0x02, 0x4a);
+				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
+					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0200);
+			}
 			break;
 
 		case AUDIO_MONO_RIGHT:
 			ret = audcom(av7110, AUDIO_CMD_MONO_R);
-			if (!ret)
+			if (!ret) {
 				if (av7110->adac_type == DVB_ADAC_CRYSTAL)
 					i2c_writereg(av7110, 0x20, 0x02, 0x45);
+				else if (av7110->adac_type == DVB_ADAC_MSP34x5)
+					msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0210);
+			}
 			break;
 
 		default:
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index 603a22e..6405546 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -42,7 +42,18 @@
 int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
 {
 	u8 msg[5] = { dev, reg >> 8, reg & 0xff, val >> 8 , val & 0xff };
-	struct i2c_msg msgs = { .flags = 0, .addr = 0x40, .len = 5, .buf = msg };
+	struct i2c_msg msgs = { .flags = 0, .len = 5, .buf = msg };
+
+	switch (av7110->adac_type) {
+	case DVB_ADAC_MSP34x0:
+		msgs.addr = 0x40;
+		break;
+	case DVB_ADAC_MSP34x5:
+		msgs.addr = 0x42;
+		break;
+	default:
+		return 0;
+	}
 
 	if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
 		dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
@@ -57,10 +68,23 @@
 	u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
 	u8 msg2[2];
 	struct i2c_msg msgs[2] = {
-		{ .flags = 0,	     .addr = 0x40, .len = 3, .buf = msg1 },
-		{ .flags = I2C_M_RD, .addr = 0x40, .len = 2, .buf = msg2 }
+		{ .flags = 0	   , .len = 3, .buf = msg1 },
+		{ .flags = I2C_M_RD, .len = 2, .buf = msg2 }
 	};
 
+	switch (av7110->adac_type) {
+	case DVB_ADAC_MSP34x0:
+		msgs[0].addr = 0x40;
+		msgs[1].addr = 0x40;
+		break;
+	case DVB_ADAC_MSP34x5:
+		msgs[0].addr = 0x42;
+		msgs[1].addr = 0x42;
+		break;
+	default:
+		return 0;
+	}
+
 	if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
 		dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
 		       av7110->dvb_adapter.num, reg);
@@ -678,17 +702,23 @@
 {
 	u16 version1, version2;
 
-	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) != 1
-	    || i2c_writereg(av7110, 0x80, 0x0, 0) != 1)
+	if (i2c_writereg(av7110, 0x80, 0x0, 0x80) == 1 &&
+	    i2c_writereg(av7110, 0x80, 0x0, 0) == 1) {
+		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
+			av7110->dvb_adapter.num);
+		av7110->adac_type = DVB_ADAC_MSP34x0;
+	} else if (i2c_writereg(av7110, 0x84, 0x0, 0x80) == 1 &&
+		   i2c_writereg(av7110, 0x84, 0x0, 0) == 1) {
+		printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3415\n",
+			av7110->dvb_adapter.num);
+		av7110->adac_type = DVB_ADAC_MSP34x5;
+	} else
 		return -ENODEV;
 
-	printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
-		av7110->dvb_adapter.num);
-	av7110->adac_type = DVB_ADAC_MSP34x0;
 	msleep(100); // the probing above resets the msp...
 	msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
 	msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
-	dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n",
+	dprintk(1, "dvb-ttpci: @ card %d MSP34xx version 0x%04x 0x%04x\n",
 		av7110->dvb_adapter.num, version1, version2);
 	msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
 	msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
@@ -697,7 +727,7 @@
 	msp_writereg(av7110, MSP_WR_DSP, 0x0004, 0x7f00); // loudspeaker volume
 	msp_writereg(av7110, MSP_WR_DSP, 0x000a, 0x0220); // SCART 1 source
 	msp_writereg(av7110, MSP_WR_DSP, 0x0007, 0x7f00); // SCART 1 volume
-	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x4800); // prescale SCART
+	msp_writereg(av7110, MSP_WR_DSP, 0x000d, 0x1900); // prescale SCART
 
 	if (i2c_writereg(av7110, 0x48, 0x01, 0x00)!=1) {
 		INFO(("saa7113 not accessible.\n"));
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 8a7cd7d..6163cb0 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -50,6 +50,12 @@
 
 #define DEBICICAM		0x02420000
 
+#define SLOTSTATUS_NONE         1
+#define SLOTSTATUS_PRESENT      2
+#define SLOTSTATUS_RESET        4
+#define SLOTSTATUS_READY        8
+#define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)
+
 struct budget_av {
 	struct budget budget;
 	struct video_device *vd;
@@ -58,8 +64,15 @@
 	struct tasklet_struct ciintf_irq_tasklet;
 	int slot_status;
 	struct dvb_ca_en50221 ca;
+	u8 reinitialise_demod:1;
+	u8 tda10021_poclkp:1;
+	u8 tda10021_ts_enabled;
+	int (*tda10021_set_frontend)(struct dvb_frontend *fe, struct dvb_frontend_parameters *p);
 };
 
+static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);
+
+
 /* GPIO Connections:
  * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!
  * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory
@@ -129,9 +142,10 @@
 	udelay(1);
 
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+	if (result == -ETIMEDOUT) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 1\n");
+	}
 	return result;
 }
 
@@ -147,9 +161,10 @@
 	udelay(1);
 
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+	if (result == -ETIMEDOUT) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 2\n");
+	}
 	return result;
 }
 
@@ -165,9 +180,11 @@
 	udelay(1);
 
 	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+	if ((result == -ETIMEDOUT) || ((result == 0xff) && ((address & 3) < 2))) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 3\n");
+		return -ETIMEDOUT;
+	}
 	return result;
 }
 
@@ -183,9 +200,10 @@
 	udelay(1);
 
 	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);
-
-	if (result == -ETIMEDOUT)
-		budget_av->slot_status = 0;
+	if (result == -ETIMEDOUT) {
+		ciintf_slot_shutdown(ca, slot);
+		printk(KERN_INFO "budget-av: cam ejected 5\n");
+	}
 	return result;
 }
 
@@ -193,12 +211,12 @@
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
 	struct saa7146_dev *saa = budget_av->budget.dev;
-	int timeout = 50; // 5 seconds (4.4.6 Ready)
 
 	if (slot != 0)
 		return -EINVAL;
 
 	dprintk(1, "ciintf_slot_reset\n");
+	budget_av->slot_status = SLOTSTATUS_RESET;
 
 	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
 
@@ -208,20 +226,17 @@
 	msleep(20); /* 20 ms Vcc settling time */
 
 	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+	msleep(20);
 
-	/* This should have been based on pin 16 READY of the pcmcia port,
-	 * but AFAICS it is not routed to the saa7146 */
-	while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
-		msleep(100);
+	/* reinitialise the frontend if necessary */
+	if (budget_av->reinitialise_demod)
+		dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
 
-	/* reinitialise the frontend */
-	dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);
-
-	if (timeout <= 0)
-	{
-		printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
-		saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-		return -ETIMEDOUT;
+	/* set tda10021 back to original clock configuration on reset */
+	if (budget_av->tda10021_poclkp) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+		budget_av->tda10021_ts_enabled = 0;
 	}
 
 	return 0;
@@ -238,7 +253,13 @@
 	dprintk(1, "ciintf_slot_shutdown\n");
 
 	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
-	budget_av->slot_status = 0;
+	budget_av->slot_status = SLOTSTATUS_NONE;
+
+	/* set tda10021 back to original clock configuration when cam removed */
+	if (budget_av->tda10021_poclkp) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+		budget_av->tda10021_ts_enabled = 0;
+	}
 	return 0;
 }
 
@@ -253,6 +274,13 @@
 	dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status);
 
 	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);
+
+	/* tda10021 seems to need a different TS clock config when data is routed to the CAM */
+	if (budget_av->tda10021_poclkp) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+		budget_av->tda10021_ts_enabled = 1;
+	}
+
 	return 0;
 }
 
@@ -260,50 +288,61 @@
 {
 	struct budget_av *budget_av = (struct budget_av *) ca->data;
 	struct saa7146_dev *saa = budget_av->budget.dev;
-	int cam_present = 0;
+	int result;
 
 	if (slot != 0)
 		return -EINVAL;
 
-	if (!budget_av->slot_status)
-	{
-		// first of all test the card detect line
+	/* test the card detect line - needs to be done carefully
+	 * since it never goes high for some CAMs on this interface (e.g. topuptv) */
+	if (budget_av->slot_status == SLOTSTATUS_NONE) {
 		saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
 		udelay(1);
-		if (saa7146_read(saa, PSR) & MASK_06)
-		{
-			cam_present = 1;
-		}
-		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-
-		// that is unreliable however, so try and read from IO memory
-		if (!cam_present)
-		{
-			saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-			if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) != -ETIMEDOUT)
-			{
-				cam_present = 1;
+		if (saa7146_read(saa, PSR) & MASK_06) {
+			if (budget_av->slot_status == SLOTSTATUS_NONE) {
+				budget_av->slot_status = SLOTSTATUS_PRESENT;
+				printk(KERN_INFO "budget-av: cam inserted A\n");
 			}
 		}
+		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
+	}
 
-		// did we find something?
-		if (cam_present) {
-			printk(KERN_INFO "budget-av: cam inserted\n");
-			budget_av->slot_status = 1;
-		}
-	} else if (!open) {
+	/* We also try and read from IO memory to work round the above detection bug. If
+	 * there is no CAM, we will get a timeout. Only done if there is no cam
+	 * present, since this test actually breaks some cams :(
+	 *
+	 * if the CI interface is not open, we also do the above test since we
+	 * don't care if the cam has problems - we'll be resetting it on open() anyway */
+	if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {
 		saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
-		if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
-		{
-			printk(KERN_INFO "budget-av: cam ejected\n");
-			saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
-			budget_av->slot_status = 0;
+		result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);
+		if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {
+			budget_av->slot_status = SLOTSTATUS_PRESENT;
+			printk(KERN_INFO "budget-av: cam inserted B\n");
+		} else if (result < 0) {
+			if (budget_av->slot_status != SLOTSTATUS_NONE) {
+				ciintf_slot_shutdown(ca, slot);
+				printk(KERN_INFO "budget-av: cam ejected 5\n");
+				return 0;
+			}
 		}
 	}
 
-	if (budget_av->slot_status == 1)
-		return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+	/* read from attribute memory in reset/ready state to know when the CAM is ready */
+	if (budget_av->slot_status == SLOTSTATUS_RESET) {
+		result = ciintf_read_attribute_mem(ca, slot, 0);
+		if (result == 0x1d) {
+			budget_av->slot_status = SLOTSTATUS_READY;
+		}
+	}
 
+	/* work out correct return code */
+	if (budget_av->slot_status != SLOTSTATUS_NONE) {
+		if (budget_av->slot_status & SLOTSTATUS_READY) {
+			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;
+		}
+		return DVB_CA_EN50221_POLL_CAM_PRESENT;
+	}
 	return 0;
 }
 
@@ -333,6 +372,8 @@
 	budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
 	budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
 	budget_av->ca.data = budget_av;
+	budget_av->budget.ci_present = 1;
+	budget_av->slot_status = SLOTSTATUS_NONE;
 
 	if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
 					  &budget_av->ca, 0, 1)) != 0) {
@@ -341,7 +382,6 @@
 	}
 
 	printk(KERN_INFO "budget-av: ci interface initialised.\n");
-	budget_av->budget.ci_present = 1;
 	return 0;
 
 error:
@@ -472,12 +512,12 @@
 	return 0;
 }
 
-static int philips_su1278_ty_ci_pll_set(struct dvb_frontend *fe,
-					struct i2c_adapter *i2c,
-					struct dvb_frontend_parameters *params)
+static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe,
+						 struct dvb_frontend_parameters *params)
 {
 	u32 div;
 	u8 buf[4];
+	struct budget *budget = (struct budget *) fe->dvb->priv;
 	struct i2c_msg msg = {.addr = 0x61,.flags = 0,.buf = buf,.len = sizeof(buf) };
 
 	if ((params->frequency < 950000) || (params->frequency > 2150000))
@@ -501,7 +541,9 @@
 	else if (params->frequency < 2150000)
 		buf[3] |= 0xC0;
 
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
 }
@@ -509,9 +551,8 @@
 #define MIN2(a,b) ((a) < (b) ? (a) : (b))
 #define MIN3(a,b,c) MIN2(MIN2(a,b),c)
 
-static int philips_su1278sh2_tua6100_pll_set(struct dvb_frontend *fe,
-					struct i2c_adapter *i2c,
-					struct dvb_frontend_parameters *params)
+static int philips_su1278sh2_tua6100_tuner_set_params(struct dvb_frontend *fe,
+						      struct dvb_frontend_parameters *params)
 {
 	u8 reg0 [2] = { 0x00, 0x00 };
 	u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 };
@@ -521,6 +562,7 @@
 	int R, A, N, P, M;
 	struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = NULL,.len = 0 };
 	int freq = params->frequency;
+	struct budget *budget = (struct budget *) fe->dvb->priv;
 
 	first_ZF = (freq) / 1000;
 
@@ -620,21 +662,25 @@
 	reg0[1] |= 0x03;
 
 	/* already enabled - do not reenable i2c repeater or TX fails */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	msg.buf = reg0;
 	msg.len = sizeof(reg0);
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 
-	stv0299_enable_plli2c(fe);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	msg.buf = reg1;
 	msg.len = sizeof(reg1);
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 
-	stv0299_enable_plli2c(fe);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	msg.buf = reg2;
 	msg.len = sizeof(reg2);
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 
 	return 0;
@@ -692,7 +738,6 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
 	.min_delay_ms = 100,
 	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-	.pll_set = philips_su1278_ty_ci_pll_set,
 };
 
 
@@ -706,7 +751,6 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
 	.min_delay_ms = 100,
 	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-	.pll_set = philips_su1278_ty_ci_pll_set,
 };
 
 static struct stv0299_config cinergy_1200s_1894_0010_config = {
@@ -719,10 +763,9 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
 	.min_delay_ms = 100,
 	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,
-	.pll_set = philips_su1278sh2_tua6100_pll_set,
 };
 
-static int philips_cu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct budget *budget = (struct budget *) fe->dvb->priv;
 	u8 buf[4];
@@ -738,6 +781,8 @@
 	buf[3] = (params->frequency < 150000000 ? 0x01 :
 		  params->frequency < 445000000 ? 0x02 : 0x04);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -745,19 +790,20 @@
 
 static struct tda10021_config philips_cu1216_config = {
 	.demod_address = 0x0c,
-	.pll_set = philips_cu1216_pll_set,
 };
 
 
 
 
-static int philips_tu1216_pll_init(struct dvb_frontend *fe)
+static int philips_tu1216_tuner_init(struct dvb_frontend *fe)
 {
 	struct budget *budget = (struct budget *) fe->dvb->priv;
 	static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };
 	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
 
 	// setup PLL configuration
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 	msleep(1);
@@ -765,7 +811,7 @@
 	return 0;
 }
 
-static int philips_tu1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct budget *budget = (struct budget *) fe->dvb->priv;
 	u8 tuner_buf[4];
@@ -839,6 +885,8 @@
 	tuner_buf[2] = 0xca;
 	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 
@@ -862,9 +910,6 @@
 	.xtal_freq = TDA10046_XTAL_4M,
 	.agc_config = TDA10046_AGC_DEFAULT,
 	.if_freq = TDA10046_FREQ_3617,
-	.pll_init = philips_tu1216_pll_init,
-	.pll_set = philips_tu1216_pll_set,
-	.pll_sleep = NULL,
 	.request_firmware = philips_tu1216_request_firmware,
 };
 
@@ -911,13 +956,13 @@
 	0xff, 0xff
 };
 
-static int philips_sd1878_tda8261_pll_set(struct dvb_frontend *fe,
-		struct i2c_adapter *i2c,
-		struct dvb_frontend_parameters *params)
+static int philips_sd1878_tda8261_tuner_set_params(struct dvb_frontend *fe,
+						   struct dvb_frontend_parameters *params)
 {
 	u8              buf[4];
 	int             rc;
 	struct i2c_msg  tuner_msg = {.addr=0x60,.flags=0,.buf=buf,.len=sizeof(buf)};
+	struct budget *budget = (struct budget *) fe->dvb->priv;
 
 	if((params->frequency < 950000) || (params->frequency > 2150000))
 		return -EINVAL;
@@ -926,7 +971,9 @@
 			params->frequency, 0);
 	if(rc < 0) return rc;
 
-	if(i2c_transfer(i2c, &tuner_msg, 1) != 1)
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if(i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 
     return 0;
@@ -969,7 +1016,7 @@
 
 static struct stv0299_config philips_sd1878_config = {
 	.demod_address = 0x68,
-	.inittab = philips_sd1878_inittab,
+     .inittab = philips_sd1878_inittab,
 	.mclk = 88000000UL,
 	.invert = 0,
 	.skip_reinit = 0,
@@ -977,7 +1024,6 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP0,
 	.min_delay_ms = 100,
 	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,
-	.pll_set = philips_sd1878_tda8261_pll_set,
 };
 
 static u8 read_pwm(struct budget_av *budget_av)
@@ -1003,6 +1049,7 @@
 
 #define SUBID_DVBS_TV_STAR	0x0014
 #define SUBID_DVBS_TV_STAR_CI	0x0016
+#define SUBID_DVBS_EASYWATCH_1  0x001a
 #define SUBID_DVBS_EASYWATCH	0x001e
 #define SUBID_DVBC_KNC1		0x0020
 #define SUBID_DVBC_KNC1_PLUS	0x0021
@@ -1012,17 +1059,36 @@
 #define SUBID_DVBT_KNC1		0x0030
 #define SUBID_DVBT_CINERGY1200	0x1157
 
+
+static int tda10021_set_frontend(struct dvb_frontend *fe,
+				 struct dvb_frontend_parameters *p)
+{
+	struct budget_av* budget_av = fe->dvb->priv;
+	int result;
+
+	result = budget_av->tda10021_set_frontend(fe, p);
+	if (budget_av->tda10021_ts_enabled) {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa1);
+	} else {
+		tda10021_write_byte(budget_av->budget.dvb_frontend, 0x12, 0xa0);
+	}
+
+	return result;
+}
+
 static void frontend_init(struct budget_av *budget_av)
 {
 	struct saa7146_dev * saa = budget_av->budget.dev;
 	struct dvb_frontend * fe = NULL;
 
+	/* Enable / PowerON Frontend */
+	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+
+	/* additional setup necessary for the PLUS cards */
 	switch (saa->pci->subsystem_device) {
 		case SUBID_DVBS_KNC1_PLUS:
 		case SUBID_DVBC_KNC1_PLUS:
 		case SUBID_DVBT_KNC1_PLUS:
-			// Enable / PowerON Frontend
-			saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
 			saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
 			break;
 	}
@@ -1030,12 +1096,19 @@
 	switch (saa->pci->subsystem_device) {
 
 	case SUBID_DVBS_KNC1:
+	case SUBID_DVBS_EASYWATCH_1:
 		if (saa->pci->subsystem_vendor == 0x1894) {
 			fe = stv0299_attach(&cinergy_1200s_1894_0010_config,
 					     &budget_av->budget.i2c_adap);
+			if (fe) {
+				fe->ops.tuner_ops.set_params = philips_su1278sh2_tua6100_tuner_set_params;
+			}
 		} else {
 			fe = stv0299_attach(&typhoon_config,
 					     &budget_av->budget.i2c_adap);
+			if (fe) {
+				fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+			}
 		}
 		break;
 
@@ -1045,41 +1118,53 @@
 	case SUBID_DVBS_EASYWATCH:
 		fe = stv0299_attach(&philips_sd1878_config,
 				&budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_sd1878_tda8261_tuner_set_params;
+		}
 		break;
 
 	case SUBID_DVBS_KNC1_PLUS:
 	case SUBID_DVBS_TYPHOON:
 		fe = stv0299_attach(&typhoon_config,
 				    &budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+		}
 		break;
 
 	case SUBID_DVBS_CINERGY1200:
 		fe = stv0299_attach(&cinergy_1200s_config,
 				    &budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;
+		}
 		break;
 
 	case SUBID_DVBC_KNC1:
 	case SUBID_DVBC_KNC1_PLUS:
+	case SUBID_DVBC_CINERGY1200:
+		budget_av->reinitialise_demod = 1;
 		fe = tda10021_attach(&philips_cu1216_config,
 				     &budget_av->budget.i2c_adap,
 				     read_pwm(budget_av));
+		if (fe) {
+			budget_av->tda10021_poclkp = 1;
+			budget_av->tda10021_set_frontend = fe->ops.set_frontend;
+			fe->ops.set_frontend = tda10021_set_frontend;
+			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;
+		}
 		break;
 
 	case SUBID_DVBT_KNC1:
 	case SUBID_DVBT_KNC1_PLUS:
-		fe = tda10046_attach(&philips_tu1216_config,
-				     &budget_av->budget.i2c_adap);
-		break;
-
-	case SUBID_DVBC_CINERGY1200:
-		fe = tda10021_attach(&philips_cu1216_config,
-				     &budget_av->budget.i2c_adap,
-				     read_pwm(budget_av));
-		break;
-
 	case SUBID_DVBT_CINERGY1200:
+		budget_av->reinitialise_demod = 1;
 		fe = tda10046_attach(&philips_tu1216_config,
 				     &budget_av->budget.i2c_adap);
+		if (fe) {
+			fe->ops.tuner_ops.init = philips_tu1216_tuner_init;
+			fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;
+		}
 		break;
 	}
 
@@ -1098,8 +1183,8 @@
 	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
 				  budget_av->budget.dvb_frontend)) {
 		printk(KERN_ERR "budget-av: Frontend registration failed!\n");
-		if (budget_av->budget.dvb_frontend->ops->release)
-			budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
+		if (budget_av->budget.dvb_frontend->ops.release)
+			budget_av->budget.dvb_frontend->ops.release(budget_av->budget.dvb_frontend);
 		budget_av->budget.dvb_frontend = NULL;
 	}
 }
@@ -1293,6 +1378,7 @@
 MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
 MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);
 MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);
+MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);
 MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
 MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
 MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
@@ -1309,6 +1395,7 @@
 	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),
 	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),
 	MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),
+	MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),
 	MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
 	MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
 	MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index e64a609..4b966ee 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -620,10 +620,10 @@
 	return 0;
 }
 
-static int philips_su1278_tt_pll_set(struct dvb_frontend *fe,
-				     struct i2c_adapter *i2c,
-				     struct dvb_frontend_parameters *params)
+static int philips_su1278_tt_tuner_set_params(struct dvb_frontend *fe,
+					   struct dvb_frontend_parameters *params)
 {
+	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 	u32 div;
 	u8 buf[4];
 	struct i2c_msg msg = {.addr = 0x60,.flags = 0,.buf = buf,.len = sizeof(buf) };
@@ -649,7 +649,9 @@
 	else if (params->frequency < 2150000)
 		buf[3] |= 0xC0;
 
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&budget_ci->budget.i2c_adap, &msg, 1) != 1)
 		return -EIO;
 	return 0;
 }
@@ -665,12 +667,11 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.min_delay_ms = 50,
 	.set_symbol_rate = philips_su1278_tt_set_symbol_rate,
-	.pll_set = philips_su1278_tt_pll_set,
 };
 
 
 
-static int philips_tdm1316l_pll_init(struct dvb_frontend *fe)
+static int philips_tdm1316l_tuner_init(struct dvb_frontend *fe)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
@@ -679,6 +680,8 @@
 			sizeof(td1316_init) };
 
 	// setup PLL configuration
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 	msleep(1);
@@ -687,14 +690,18 @@
 	tuner_msg.addr = 0x65;
 	tuner_msg.buf = disable_mc44BC374c;
 	tuner_msg.len = sizeof(disable_mc44BC374c);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
 		i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1);
 	}
 
 	return 0;
 }
 
-static int philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 	u8 tuner_buf[4];
@@ -770,6 +777,8 @@
 	tuner_buf[2] = 0xca;
 	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 
@@ -793,13 +802,10 @@
 	.xtal_freq = TDA10046_XTAL_4M,
 	.agc_config = TDA10046_AGC_DEFAULT,
 	.if_freq = TDA10046_FREQ_3617,
-	.pll_init = philips_tdm1316l_pll_init,
-	.pll_set = philips_tdm1316l_pll_set,
-	.pll_sleep = NULL,
 	.request_firmware = philips_tdm1316l_request_firmware,
 };
 
-static int dvbc_philips_tdm1316l_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct budget_ci *budget_ci = (struct budget_ci *) fe->dvb->priv;
 	u8 tuner_buf[5];
@@ -857,13 +863,15 @@
 	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 	tuner_buf[4] = 0x80;
 
-	stv0297_enable_plli2c(fe);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 
 	msleep(50);
 
-	stv0297_enable_plli2c(fe);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&budget_ci->budget.i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 
@@ -969,7 +977,7 @@
 	.demod_address = 0x1c,
 	.inittab = dvbc_philips_tdm1316l_inittab,
 	.invert = 0,
-	.pll_set = dvbc_philips_tdm1316l_pll_set,
+	.stop_during_read = 1,
 };
 
 
@@ -982,6 +990,8 @@
 		budget_ci->budget.dvb_frontend =
 			stv0299_attach(&alps_bsru6_config, &budget_ci->budget.i2c_adap);
 		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+			budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
 			break;
 		}
 		break;
@@ -990,6 +1000,7 @@
 		budget_ci->budget.dvb_frontend =
 			stv0299_attach(&philips_su1278_tt_config, &budget_ci->budget.i2c_adap);
 		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_su1278_tt_tuner_set_params;
 			break;
 		}
 		break;
@@ -999,6 +1010,7 @@
 		budget_ci->budget.dvb_frontend =
 			stv0297_attach(&dvbc_philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
 		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
 			break;
 		}
 		break;
@@ -1008,6 +1020,8 @@
 		budget_ci->budget.dvb_frontend =
 			tda10045_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
 		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
 			break;
 		}
 		break;
@@ -1017,6 +1031,8 @@
 		budget_ci->budget.dvb_frontend =
 			tda10046_attach(&philips_tdm1316l_config, &budget_ci->budget.i2c_adap);
 		if (budget_ci->budget.dvb_frontend) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
 			break;
 		}
 		break;
@@ -1024,11 +1040,14 @@
 	case 0x1017:		// TT S-1500 PCI
 		budget_ci->budget.dvb_frontend = stv0299_attach(&alps_bsbe1_config, &budget_ci->budget.i2c_adap);
 		if (budget_ci->budget.dvb_frontend) {
-			budget_ci->budget.dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
-			if (lnbp21_init(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
+			budget_ci->budget.dvb_frontend->ops.tuner_ops.set_params = alps_bsbe1_tuner_set_params;
+			budget_ci->budget.dvb_frontend->tuner_priv = &budget_ci->budget.i2c_adap;
+
+			budget_ci->budget.dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
+			if (lnbp21_attach(budget_ci->budget.dvb_frontend, &budget_ci->budget.i2c_adap, LNBP21_LLC, 0)) {
 				printk("%s: No LNBP21 found!\n", __FUNCTION__);
-				if (budget_ci->budget.dvb_frontend->ops->release)
-					budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
+				if (budget_ci->budget.dvb_frontend->ops.release)
+					budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
 				budget_ci->budget.dvb_frontend = NULL;
 			}
 		}
@@ -1046,8 +1065,8 @@
 		if (dvb_register_frontend
 		    (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
 			printk("budget-ci: Frontend registration failed!\n");
-			if (budget_ci->budget.dvb_frontend->ops->release)
-				budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
+			if (budget_ci->budget.dvb_frontend->ops.release)
+				budget_ci->budget.dvb_frontend->ops.release(budget_ci->budget.dvb_frontend);
 			budget_ci->budget.dvb_frontend = NULL;
 		}
 	}
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index ea2066d..e4cf777 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -400,7 +400,9 @@
 		budget->dev->name, budget->buffer_width, budget->buffer_height);
 	printk("%s: dma buffer size %u\n", budget->dev->name, budget->buffer_size);
 
-	dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner);
+	if ((ret = dvb_register_adapter(&budget->dvb_adapter, budget->card->name, owner, &budget->dev->pci->dev)) < 0) {
+		return ret;
+	}
 
 	/* set dd1 stream a & b */
 	saa7146_write(dev, DD1_STREAM_B, 0x00000000);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 1b3aaac..ee60ce9 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -258,7 +258,7 @@
 	return 0;
 }
 
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
 	u8 pwr = 0;
@@ -281,7 +281,10 @@
 	// NOTE: since we're using a prescaler of 2, we set the
 	// divisor frequency to 62.5kHz and divide by 125 above
 
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+		return -EIO;
 	return 0;
 }
 
@@ -289,10 +292,9 @@
 	.demod_address = 0x08,
 	.xin = 90100000UL,
 	.invert_pwm = 0,
-	.pll_set = alps_bsrv2_pll_set,
 };
 
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv;
 	u32 div;
@@ -305,13 +307,15 @@
 	data[2] = 0x8e;
 	data[3] = 0x00;
 
-	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1)
+		return -EIO;
 	return 0;
 }
 
 static struct tda8083_config grundig_29504_451_config = {
 	.demod_address = 0x68,
-	.pll_set = grundig_29504_451_pll_set,
 };
 
 static void frontend_init(struct budget_patch* budget)
@@ -323,27 +327,32 @@
 		// try the ALPS BSRV2 first of all
 		budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst;
-			budget->dvb_frontend->ops->set_tone = budget_patch_set_tone;
+			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd;
+			budget->dvb_frontend->ops.diseqc_send_burst = budget_patch_diseqc_send_burst;
+			budget->dvb_frontend->ops.set_tone = budget_patch_set_tone;
 			break;
 		}
 
 		// try the ALPS BSRU6 now
 		budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops->set_tone = budget_set_tone;
+			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+
+			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+			budget->dvb_frontend->ops.set_tone = budget_set_tone;
 			break;
 		}
 
 		// Try the grundig 29504-451
 		budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops->set_tone = budget_set_tone;
+			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+			budget->dvb_frontend->ops.set_tone = budget_set_tone;
 			break;
 		}
 		break;
@@ -358,8 +367,8 @@
 	} else {
 		if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
 			printk("budget-av: Frontend registration failed!\n");
-			if (budget->dvb_frontend->ops->release)
-				budget->dvb_frontend->ops->release(budget->dvb_frontend);
+			if (budget->dvb_frontend->ops.release)
+				budget->dvb_frontend->ops.release(budget->dvb_frontend);
 			budget->dvb_frontend = NULL;
 		}
 	}
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index c23c02d..35761f1 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -186,7 +186,7 @@
 	return 0;
 }
 
-static int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_bsrv2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct budget* budget = (struct budget*) fe->dvb->priv;
 	u8 pwr = 0;
@@ -209,6 +209,8 @@
 	// NOTE: since we're using a prescaler of 2, we set the
 	// divisor frequency to 62.5kHz and divide by 125 above
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 	return 0;
 }
@@ -218,10 +220,9 @@
 	.demod_address = 0x08,
 	.xin = 90100000UL,
 	.invert_pwm = 0,
-	.pll_set = alps_bsrv2_pll_set,
 };
 
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct budget* budget = (struct budget*) fe->dvb->priv;
 	u32 div;
@@ -235,6 +236,8 @@
 	data[2] = 0x85 | ((div >> 10) & 0x60);
 	data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 	return 0;
 }
@@ -244,10 +247,9 @@
 	.xin = 57840000UL,
 	.invert = 1,
 	.selagc = VES1820_SELAGC_SIGNAMPERR,
-	.pll_set = alps_tdbe2_pll_set,
 };
 
-static int grundig_29504_401_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_401_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct budget* budget = (struct budget*) fe->dvb->priv;
 	u32 div;
@@ -274,16 +276,17 @@
 	data[2] = ((div >> 10) & 0x60) | cfg;
 	data[3] = (cpump << 6) | band_select;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 	return 0;
 }
 
 static struct l64781_config grundig_29504_401_config = {
 	.demod_address = 0x55,
-	.pll_set = grundig_29504_401_pll_set,
 };
 
-static int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int grundig_29504_451_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct budget* budget = (struct budget*) fe->dvb->priv;
 	u32 div;
@@ -296,16 +299,17 @@
 	data[2] = 0x8e;
 	data[3] = 0x00;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 	return 0;
 }
 
 static struct tda8083_config grundig_29504_451_config = {
 	.demod_address = 0x68,
-	.pll_set = grundig_29504_451_pll_set,
 };
 
-static int s5h1420_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u32* freqout)
+static int s5h1420_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct budget* budget = (struct budget*) fe->dvb->priv;
 	u32 div;
@@ -326,16 +330,16 @@
 	else
 		data[3] = 0xc0;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO;
 
-	*freqout = div * 1000;
 	return 0;
 }
 
 static struct s5h1420_config s5h1420_config = {
 	.demod_address = 0x53,
 	.invert = 1,
-	.pll_set = s5h1420_pll_set,
 };
 
 static u8 read_pwm(struct budget* budget)
@@ -359,18 +363,21 @@
 		// try the ALPS BSRV2 first of all
 		budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops->set_tone = budget_set_tone;
+			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsrv2_tuner_set_params;
+			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+			budget->dvb_frontend->ops.set_tone = budget_set_tone;
 			break;
 		}
 
 		// try the ALPS BSRU6 now
 		budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
-			budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst;
-			budget->dvb_frontend->ops->set_tone = budget_set_tone;
+			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+			budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd;
+			budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst;
+			budget->dvb_frontend->ops.set_tone = budget_set_tone;
 			break;
 		}
 		break;
@@ -378,35 +385,45 @@
 	case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
 
 		budget->dvb_frontend = ves1820_attach(&alps_tdbe2_config, &budget->i2c_adap, read_pwm(budget));
-		if (budget->dvb_frontend) break;
+		if (budget->dvb_frontend) {
+			budget->dvb_frontend->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
+			break;
+		}
 		break;
 
 	case 0x1005: // Hauppauge/TT Nova-T budget (L64781/Grundig 29504-401(tsa5060))
 
 		budget->dvb_frontend = l64781_attach(&grundig_29504_401_config, &budget->i2c_adap);
-		if (budget->dvb_frontend) break;
+		if (budget->dvb_frontend) {
+			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_401_tuner_set_params;
+			break;
+		}
 		break;
 
 	case 0x4f60: // Fujitsu Siemens Activy Budget-S PCI rev AL (stv0299/ALPS BSRU6(tsa5059))
 		budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
-			budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
+			budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params;
+			budget->dvb_frontend->tuner_priv = &budget->i2c_adap;
+			budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+			budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
 		}
 		break;
 
 	case 0x4f61: // Fujitsu Siemens Activy Budget-S PCI rev GR (tda8083/Grundig 29504-451(tsa5522))
 		budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			budget->dvb_frontend->ops->set_voltage = siemens_budget_set_voltage;
-			budget->dvb_frontend->ops->dishnetwork_send_legacy_command = NULL;
+			budget->dvb_frontend->ops.tuner_ops.set_params = grundig_29504_451_tuner_set_params;
+			budget->dvb_frontend->ops.set_voltage = siemens_budget_set_voltage;
+			budget->dvb_frontend->ops.dishnetwork_send_legacy_command = NULL;
 		}
 		break;
 
 	case 0x1016: // Hauppauge/TT Nova-S SE (samsung s5h1420/????(tda8260))
 		budget->dvb_frontend = s5h1420_attach(&s5h1420_config, &budget->i2c_adap);
 		if (budget->dvb_frontend) {
-			if (lnbp21_init(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
+			budget->dvb_frontend->ops.tuner_ops.set_params = s5h1420_tuner_set_params;
+			if (lnbp21_attach(budget->dvb_frontend, &budget->i2c_adap, 0, 0)) {
 				printk("%s: No LNBP21 found!\n", __FUNCTION__);
 				goto error_out;
 			}
@@ -428,8 +445,8 @@
 
 error_out:
 	printk("budget: Frontend registration failed!\n");
-	if (budget->dvb_frontend->ops->release)
-		budget->dvb_frontend->ops->release(budget->dvb_frontend);
+	if (budget->dvb_frontend->ops.release)
+		budget->dvb_frontend->ops.release(budget->dvb_frontend);
 	budget->dvb_frontend = NULL;
 	return;
 }
diff --git a/drivers/media/dvb/ttusb-budget/Kconfig b/drivers/media/dvb/ttusb-budget/Kconfig
index 914587d..92c7cdc 100644
--- a/drivers/media/dvb/ttusb-budget/Kconfig
+++ b/drivers/media/dvb/ttusb-budget/Kconfig
@@ -6,6 +6,8 @@
 	select DVB_VES1820
 	select DVB_TDA8083
 	select DVB_STV0299
+	select DVB_STV0297
+	select DVB_LNBP21
 	help
 	  Support for external USB adapters designed by Technotrend and
 	  produced by Hauppauge, shipped under the brand name 'Nova-USB'.
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 6ceae38..14559ef 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -30,6 +30,8 @@
 #include "tda1004x.h"
 #include "stv0299.h"
 #include "tda8083.h"
+#include "stv0297.h"
+#include "lnbp21.h"
 
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/dmx.h>
@@ -486,31 +488,6 @@
 }
 #endif
 
-static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
-{
-	struct  ttusb* ttusb = (struct ttusb*)  fe->dvb->priv;
-	int ret;
-	u8 data[1];
-	struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) };
-
-	switch(voltage) {
-	case SEC_VOLTAGE_OFF:
-		data[0] = 0x00;
-		break;
-	case SEC_VOLTAGE_13:
-		data[0] = 0x44;
-		break;
-	case SEC_VOLTAGE_18:
-		data[0] = 0x4c;
-		break;
-	default:
-		return -EINVAL;
-	};
-
-	ret = i2c_transfer(&ttusb->i2c_adap, &msg, 1);
-	return (ret != 1) ? -EIO : 0;
-}
-
 static int ttusb_update_lnb(struct ttusb *ttusb)
 {
 	u8 b[] = { 0xaa, ++ttusb->c, 0x16, 5, /*power: */ 1,
@@ -1048,7 +1025,7 @@
 
 
 
-static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdmb7_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
 	u8 data[4];
@@ -1062,20 +1039,21 @@
 	data[2] = ((div >> 10) & 0x60) | 0x85;
 	data[3] = params->frequency < 592000000 ? 0x40 : 0x80;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1) return -EIO;
 	return 0;
 }
 
 static struct cx22700_config alps_tdmb7_config = {
 	.demod_address = 0x43,
-	.pll_set = alps_tdmb7_pll_set,
 };
 
 
 
 
 
-static int philips_tdm1316l_pll_init(struct dvb_frontend* fe)
+static int philips_tdm1316l_tuner_init(struct dvb_frontend* fe)
 {
 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
 	static u8 td1316_init[] = { 0x0b, 0xf5, 0x85, 0xab };
@@ -1083,6 +1061,8 @@
 	struct i2c_msg tuner_msg = { .addr=0x60, .flags=0, .buf=td1316_init, .len=sizeof(td1316_init) };
 
 	// setup PLL configuration
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) return -EIO;
 	msleep(1);
 
@@ -1090,6 +1070,8 @@
 	tuner_msg.addr = 0x65;
 	tuner_msg.buf = disable_mc44BC374c;
 	tuner_msg.len = sizeof(disable_mc44BC374c);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
 		i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1);
 	}
@@ -1097,7 +1079,7 @@
 	return 0;
 }
 
-static int philips_tdm1316l_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int philips_tdm1316l_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
 	u8 tuner_buf[4];
@@ -1157,6 +1139,8 @@
 	tuner_buf[2] = 0xca;
 	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 
@@ -1176,8 +1160,6 @@
 	.demod_address = 0x8,
 	.invert = 1,
 	.invert_oclk = 0,
-	.pll_init = philips_tdm1316l_pll_init,
-	.pll_set = philips_tdm1316l_pll_set,
 	.request_firmware = philips_tdm1316l_request_firmware,
 };
 
@@ -1299,7 +1281,7 @@
 	return 0;
 }
 
-static int philips_tsa5059_pll_set(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dvb_frontend_parameters *params)
+static int philips_tsa5059_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
 	u8 buf[4];
@@ -1322,7 +1304,9 @@
 	if (ttusb->revision == TTUSB_REV_2_2)
 		buf[3] |= 0x20;
 
-	if (i2c_transfer(i2c, &msg, 1) != 1)
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 
 	return 0;
@@ -1338,10 +1322,9 @@
 	.volt13_op0_op1 = STV0299_VOLT13_OP1,
 	.min_delay_ms = 100,
 	.set_symbol_rate = alps_stv0299_set_symbol_rate,
-	.pll_set = philips_tsa5059_pll_set,
 };
 
-static int ttusb_novas_grundig_29504_491_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int ttusb_novas_grundig_29504_491_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct ttusb* ttusb = (struct ttusb*) fe->dvb->priv;
 	u8 buf[4];
@@ -1355,6 +1338,8 @@
 	buf[2] = 0x8e;
 	buf[3] = 0x00;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&ttusb->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 
@@ -1364,10 +1349,9 @@
 static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
 
 	.demod_address = 0x68,
-	.pll_set = ttusb_novas_grundig_29504_491_pll_set,
 };
 
-static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+static int alps_tdbe2_tuner_set_params(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
 {
 	struct ttusb* ttusb = fe->dvb->priv;
 	u32 div;
@@ -1381,6 +1365,8 @@
 	data[2] = 0x85 | ((div >> 10) & 0x60);
 	data[3] = (params->frequency < 174000000 ? 0x88 : params->frequency < 470000000 ? 0x84 : 0x81);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer (&ttusb->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 
@@ -1393,7 +1379,6 @@
 	.xin = 57840000UL,
 	.invert = 1,
 	.selagc = VES1820_SELAGC_SIGNAMPERR,
-	.pll_set = alps_tdbe2_pll_set,
 };
 
 static u8 read_pwm(struct ttusb* ttusb)
@@ -1410,6 +1395,174 @@
 }
 
 
+static int dvbc_philips_tdm1316l_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+{
+	struct ttusb *ttusb = (struct ttusb *) fe->dvb->priv;
+	u8 tuner_buf[5];
+	struct i2c_msg tuner_msg = {.addr = 0x60,
+				    .flags = 0,
+				    .buf = tuner_buf,
+				    .len = sizeof(tuner_buf) };
+	int tuner_frequency = 0;
+	u8 band, cp, filter;
+
+	// determine charge pump
+	tuner_frequency = params->frequency;
+	if      (tuner_frequency <  87000000) {return -EINVAL;}
+	else if (tuner_frequency < 130000000) {cp = 3; band = 1;}
+	else if (tuner_frequency < 160000000) {cp = 5; band = 1;}
+	else if (tuner_frequency < 200000000) {cp = 6; band = 1;}
+	else if (tuner_frequency < 290000000) {cp = 3; band = 2;}
+	else if (tuner_frequency < 420000000) {cp = 5; band = 2;}
+	else if (tuner_frequency < 480000000) {cp = 6; band = 2;}
+	else if (tuner_frequency < 620000000) {cp = 3; band = 4;}
+	else if (tuner_frequency < 830000000) {cp = 5; band = 4;}
+	else if (tuner_frequency < 895000000) {cp = 7; band = 4;}
+	else {return -EINVAL;}
+
+	// assume PLL filter should always be 8MHz for the moment.
+	filter = 1;
+
+	// calculate divisor
+	// (Finput + Fif)/Fref; Fif = 36125000 Hz, Fref = 62500 Hz
+	tuner_frequency = ((params->frequency + 36125000) / 62500);
+
+	// setup tuner buffer
+	tuner_buf[0] = tuner_frequency >> 8;
+	tuner_buf[1] = tuner_frequency & 0xff;
+	tuner_buf[2] = 0xc8;
+	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
+	tuner_buf[4] = 0x80;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
+		printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 1\n");
+		return -EIO;
+	}
+
+	msleep(50);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+	if (i2c_transfer(&ttusb->i2c_adap, &tuner_msg, 1) != 1) {
+		printk("dvb-ttusb-budget: dvbc_philips_tdm1316l_pll_set Error 2\n");
+		return -EIO;
+	}
+
+	msleep(1);
+
+	return 0;
+}
+
+static u8 dvbc_philips_tdm1316l_inittab[] = {
+	0x80, 0x21,
+	0x80, 0x20,
+	0x81, 0x01,
+	0x81, 0x00,
+	0x00, 0x09,
+	0x01, 0x69,
+	0x03, 0x00,
+	0x04, 0x00,
+	0x07, 0x00,
+	0x08, 0x00,
+	0x20, 0x00,
+	0x21, 0x40,
+	0x22, 0x00,
+	0x23, 0x00,
+	0x24, 0x40,
+	0x25, 0x88,
+	0x30, 0xff,
+	0x31, 0x00,
+	0x32, 0xff,
+	0x33, 0x00,
+	0x34, 0x50,
+	0x35, 0x7f,
+	0x36, 0x00,
+	0x37, 0x20,
+	0x38, 0x00,
+	0x40, 0x1c,
+	0x41, 0xff,
+	0x42, 0x29,
+	0x43, 0x20,
+	0x44, 0xff,
+	0x45, 0x00,
+	0x46, 0x00,
+	0x49, 0x04,
+	0x4a, 0xff,
+	0x4b, 0x7f,
+	0x52, 0x30,
+	0x55, 0xae,
+	0x56, 0x47,
+	0x57, 0xe1,
+	0x58, 0x3a,
+	0x5a, 0x1e,
+	0x5b, 0x34,
+	0x60, 0x00,
+	0x63, 0x00,
+	0x64, 0x00,
+	0x65, 0x00,
+	0x66, 0x00,
+	0x67, 0x00,
+	0x68, 0x00,
+	0x69, 0x00,
+	0x6a, 0x02,
+	0x6b, 0x00,
+	0x70, 0xff,
+	0x71, 0x00,
+	0x72, 0x00,
+	0x73, 0x00,
+	0x74, 0x0c,
+	0x80, 0x00,
+	0x81, 0x00,
+	0x82, 0x00,
+	0x83, 0x00,
+	0x84, 0x04,
+	0x85, 0x80,
+	0x86, 0x24,
+	0x87, 0x78,
+	0x88, 0x00,
+	0x89, 0x00,
+	0x90, 0x01,
+	0x91, 0x01,
+	0xa0, 0x00,
+	0xa1, 0x00,
+	0xa2, 0x00,
+	0xb0, 0x91,
+	0xb1, 0x0b,
+	0xc0, 0x4b,
+	0xc1, 0x00,
+	0xc2, 0x00,
+	0xd0, 0x00,
+	0xd1, 0x00,
+	0xd2, 0x00,
+	0xd3, 0x00,
+	0xd4, 0x00,
+	0xd5, 0x00,
+	0xde, 0x00,
+	0xdf, 0x00,
+	0x61, 0x38,
+	0x62, 0x0a,
+	0x53, 0x13,
+	0x59, 0x08,
+	0x55, 0x00,
+	0x56, 0x40,
+	0x57, 0x08,
+	0x58, 0x3d,
+	0x88, 0x10,
+	0xa0, 0x00,
+	0xa0, 0x00,
+	0xa0, 0x00,
+	0xa0, 0x04,
+	0xff, 0xff,
+};
+
+static struct stv0297_config dvbc_philips_tdm1316l_config = {
+	.demod_address = 0x1c,
+	.inittab = dvbc_philips_tdm1316l_inittab,
+	.invert = 0,
+};
+
 static void frontend_init(struct ttusb* ttusb)
 {
 	switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
@@ -1417,11 +1570,13 @@
 		// try the stv0299 based first
 		ttusb->fe = stv0299_attach(&alps_stv0299_config, &ttusb->i2c_adap);
 		if (ttusb->fe != NULL) {
+			ttusb->fe->ops.tuner_ops.set_params = philips_tsa5059_tuner_set_params;
+
 			if(ttusb->revision == TTUSB_REV_2_2) { // ALPS BSBE1
 				alps_stv0299_config.inittab = alps_bsbe1_inittab;
-				ttusb->fe->ops->set_voltage = lnbp21_set_voltage;
+				lnbp21_attach(ttusb->fe, &ttusb->i2c_adap, 0, 0);
 			} else { // ALPS BSRU6
-				ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+				ttusb->fe->ops.set_voltage = ttusb_set_voltage;
 			}
 			break;
 		}
@@ -1429,28 +1584,41 @@
 		// Grundig 29504-491
 		ttusb->fe = tda8083_attach(&ttusb_novas_grundig_29504_491_config, &ttusb->i2c_adap);
 		if (ttusb->fe != NULL) {
-			ttusb->fe->ops->set_voltage = ttusb_set_voltage;
+			ttusb->fe->ops.tuner_ops.set_params = ttusb_novas_grundig_29504_491_tuner_set_params;
+			ttusb->fe->ops.set_voltage = ttusb_set_voltage;
 			break;
 		}
-
 		break;
 
 	case 0x1004: // Hauppauge/TT DVB-C budget (ves1820/ALPS TDBE2(sp5659))
 		ttusb->fe = ves1820_attach(&alps_tdbe2_config, &ttusb->i2c_adap, read_pwm(ttusb));
-		if (ttusb->fe != NULL)
+		if (ttusb->fe != NULL) {
+			ttusb->fe->ops.tuner_ops.set_params = alps_tdbe2_tuner_set_params;
 			break;
+		}
+
+		ttusb->fe = stv0297_attach(&dvbc_philips_tdm1316l_config, &ttusb->i2c_adap);
+		if (ttusb->fe != NULL) {
+			ttusb->fe->ops.tuner_ops.set_params = dvbc_philips_tdm1316l_tuner_set_params;
+			break;
+		}
 		break;
 
 	case 0x1005: // Hauppauge/TT Nova-USB-t budget (tda10046/Philips td1316(tda6651tt) OR cx22700/ALPS TDMB7(??))
 		// try the ALPS TDMB7 first
 		ttusb->fe = cx22700_attach(&alps_tdmb7_config, &ttusb->i2c_adap);
-		if (ttusb->fe != NULL)
+		if (ttusb->fe != NULL) {
+			ttusb->fe->ops.tuner_ops.set_params = alps_tdmb7_tuner_set_params;
 			break;
+		}
 
 		// Philips td1316
 		ttusb->fe = tda10046_attach(&philips_tdm1316l_config, &ttusb->i2c_adap);
-		if (ttusb->fe != NULL)
+		if (ttusb->fe != NULL) {
+			ttusb->fe->ops.tuner_ops.init = philips_tdm1316l_tuner_init;
+			ttusb->fe->ops.tuner_ops.set_params = philips_tdm1316l_tuner_set_params;
 			break;
+		}
 		break;
 	}
 
@@ -1461,8 +1629,8 @@
 	} else {
 		if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
 			printk("dvb-ttusb-budget: Frontend registration failed!\n");
-			if (ttusb->fe->ops->release)
-				ttusb->fe->ops->release(ttusb->fe);
+			if (ttusb->fe->ops.release)
+				ttusb->fe->ops.release(ttusb->fe);
 			ttusb->fe = NULL;
 		}
 	}
@@ -1507,7 +1675,7 @@
 
 	mutex_unlock(&ttusb->semi2c);
 
-	if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) {
+	if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE, &udev->dev)) < 0) {
 		ttusb_free_iso_urbs(ttusb);
 		kfree(ttusb);
 		return result;
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 44dea32..6c1cb77 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1432,7 +1432,7 @@
 	dprintk("%s\n", __FUNCTION__);
 
 	if ((result = dvb_register_adapter(&dec->adapter,
-					   dec->model_name, THIS_MODULE)) < 0) {
+					   dec->model_name, THIS_MODULE, &dec->udev->dev)) < 0) {
 		printk("%s: dvb_register_adapter failed: error %d\n",
 		       __FUNCTION__, result);
 
@@ -1657,8 +1657,8 @@
 	} else {
 		if (dvb_register_frontend(&dec->adapter, dec->fe)) {
 			printk("budget-ci: Frontend registration failed!\n");
-			if (dec->fe->ops->release)
-				dec->fe->ops->release(dec->fe);
+			if (dec->fe->ops.release)
+				dec->fe->ops.release(dec->fe);
 			dec->fe = NULL;
 		}
 	}
diff --git a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
index a5a4617..42f39a8 100644
--- a/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
+++ b/drivers/media/dvb/ttusb-dec/ttusbdecfe.c
@@ -28,8 +28,6 @@
 
 struct ttusbdecfe_state {
 
-	struct dvb_frontend_ops ops;
-
 	/* configuration settings */
 	const struct ttusbdecfe_config* config;
 
@@ -203,10 +201,9 @@
 
 	/* setup the state */
 	state->config = config;
-	memcpy(&state->ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &ttusbdecfe_dvbt_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 }
@@ -226,10 +223,9 @@
 	state->config = config;
 	state->voltage = 0;
 	state->hi_band = 0;
-	memcpy(&state->ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
 
 	/* create dvb_frontend */
-	state->frontend.ops = &state->ops;
+	memcpy(&state->frontend.ops, &ttusbdecfe_dvbs_ops, sizeof(struct dvb_frontend_ops));
 	state->frontend.demodulator_priv = state;
 	return &state->frontend;
 }
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 3fff757..de3128a 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -136,7 +136,7 @@
 	  Choose Y here if you have this PCI FM radio card.
 
 	  In order to control your radio card, you will need to use programs
-	  that are compatible with the Video for Linux API.  Information on 
+	  that are compatible with the Video for Linux API.  Information on
 	  this API and pointers to "v4l" programs may be found at
 	  <file:Documentation/video4linux/API.html>.
 
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index 8b35194..e95b680 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -20,3 +20,5 @@
 obj-$(CONFIG_RADIO_GEMTEK_PCI) += radio-gemtek-pci.o
 obj-$(CONFIG_RADIO_TRUST) += radio-trust.o
 obj-$(CONFIG_RADIO_MAESTRO) += radio-maestro.o
+
+EXTRA_CFLAGS += -Isound
diff --git a/drivers/media/radio/miropcm20-radio.c b/drivers/media/radio/miropcm20-radio.c
index dc292da..c4312fa 100644
--- a/drivers/media/radio/miropcm20-radio.c
+++ b/drivers/media/radio/miropcm20-radio.c
@@ -16,13 +16,14 @@
 
 /* What ever you think about the ACI, version 0x07 is not very well!
  * I can't get frequency, 'tuner status', 'tuner flags' or mute/mono
- * conditions...                Robert 
+ * conditions...                Robert
  */
 
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
-#include "../../../sound/oss/aci.h"
+#include <media/v4l2-common.h>
+#include "oss/aci.h"
 #include "miropcm20-rds-core.h"
 
 static int radio_nr = -1;
@@ -123,7 +124,7 @@
 	struct video_device *dev = video_devdata(file);
 	struct pcm20_device *pcm20 = dev->priv;
 	int i;
-	
+
 	switch(cmd)
 	{
 		case VIDIOCGCAP:
@@ -139,7 +140,7 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner *v = arg;
-			if(v->tuner)	/* Only 1 tuner */ 
+			if(v->tuner)	/* Only 1 tuner */
 				return -EINVAL;
 			v->rangelow=87*16000;
 			v->rangehigh=108*16000;
@@ -172,7 +173,7 @@
 			return i;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0, sizeof(*v));
 			v->flags=VIDEO_AUDIO_MUTABLE;
@@ -183,12 +184,12 @@
 				v->mode|=VIDEO_SOUND_MONO;
 			/* v->step=2048; */
 			strcpy(v->name, "Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
 
 			pcm20_mute(pcm20, !!(v->flags&VIDEO_AUDIO_MUTE));
@@ -237,7 +238,7 @@
 {
 	if(video_register_device(&pcm20_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 		goto video_register_device;
-		
+
 	if(attach_aci_rds()<0)
 		goto attach_aci_rds;
 
diff --git a/drivers/media/radio/miropcm20-rds-core.c b/drivers/media/radio/miropcm20-rds-core.c
index b602c73..9428d8b 100644
--- a/drivers/media/radio/miropcm20-rds-core.c
+++ b/drivers/media/radio/miropcm20-rds-core.c
@@ -21,7 +21,7 @@
 #include <linux/mutex.h>
 
 #include <asm/io.h>
-#include "../../../sound/oss/aci.h"
+#include "oss/aci.h"
 #include "miropcm20-rds-core.h"
 
 #define DEBUG 0
@@ -33,24 +33,24 @@
 #define RDS_BUSYMASK        0x10   /* Bit 4 */
 #define RDS_CLOCKMASK       0x08   /* Bit 3 */
 
-#define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1) 
+#define RDS_DATA(x)         (((x) >> RDS_DATASHIFT) & 1)
 
 
 #if DEBUG
 static void print_matrix(char array[], unsigned int length)
 {
-        int i, j;
+	int i, j;
 
-        for (i=0; i<length; i++) {
-                printk(KERN_DEBUG "aci-rds: ");
-                for (j=7; j>=0; j--) {
-                        printk("%d", (array[i] >> j) & 0x1);
-                }
-                if (i%8 == 0)
-                        printk(" byte-border\n");
-                else
-                        printk("\n");
-        }
+	for (i=0; i<length; i++) {
+		printk(KERN_DEBUG "aci-rds: ");
+		for (j=7; j>=0; j--) {
+			printk("%d", (array[i] >> j) & 0x1);
+		}
+		if (i%8 == 0)
+			printk(" byte-border\n");
+		else
+			printk("\n");
+	}
 }
 #endif /* DEBUG */
 
@@ -114,7 +114,7 @@
 {
 	unsigned char sendbuffer[8];
 	int i;
-	
+
 	if (byte2trans(cmd, sendbuffer, 8) != 0){
 		return -1;
 	} else {
@@ -151,7 +151,7 @@
 	   I have to waitread() here */
 	if (rds_waitread() < 0)
 		return -1;
-	
+
 	memset(databuffer, 0, datasize);
 
 	for (i=0; i< READSIZE; i++)
@@ -194,7 +194,7 @@
 		ret = 0;
 
 	mutex_unlock(&aci_rds_mutex);
-	
+
 	return ret;
 }
 EXPORT_SYMBOL(aci_rds_cmd);
diff --git a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c
index e092140..87b37b7 100644
--- a/drivers/media/radio/miropcm20-rds.c
+++ b/drivers/media/radio/miropcm20-rds.c
@@ -48,7 +48,7 @@
 
 static void print_matrix(char *ch, char out[])
 {
-        int j;
+	int j;
 
 	for (j=7; j>=0; j--) {
 		 out[7-j] = ((*ch >> j) & 0x1) + '0';
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 557fb5c..df22a58 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -24,7 +24,7 @@
  *   out(port, start_increasing_volume);
  *   wait(a_wee_while);
  *   out(port, stop_changing_the_volume);
- *  
+ *
  */
 
 #include <linux/module.h>	/* Modules 			*/
@@ -34,6 +34,7 @@
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_RTRACK_PORT 	*/
 #include <asm/semaphore.h>	/* Lock for the I/O 		*/
 
@@ -41,7 +42,7 @@
 #define CONFIG_RADIO_RTRACK_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_RTRACK_PORT; 
+static int io = CONFIG_RADIO_RTRACK_PORT;
 static int radio_nr = -1;
 static struct mutex lock;
 
@@ -93,12 +94,12 @@
 	int i;
 
 	mutex_lock(&lock);
-	
+
 	if(vol == dev->curvol) {	/* requested volume = current */
 		if (dev->muted) {	/* user is unmuting the card  */
 			dev->muted = 0;
 			outb (0xd8, io);	/* enable card */
-		}	
+		}
 		mutex_unlock(&lock);
 		return 0;
 	}
@@ -114,10 +115,10 @@
 
 	dev->muted = 0;
 	if(vol > dev->curvol)
-		for(i = dev->curvol; i < vol; i++) 
+		for(i = dev->curvol; i < vol; i++)
 			rt_incvol();
 	else
-		for(i = dev->curvol; i > vol; i--) 
+		for(i = dev->curvol; i > vol; i--)
 			rt_decvol();
 
 	dev->curvol = vol;
@@ -125,7 +126,7 @@
 	return 0;
 }
 
-/* the 128+64 on these outb's is to keep the volume stable while tuning 
+/* the 128+64 on these outb's is to keep the volume stable while tuning
  * without them, the volume _will_ creep up with each frequency change
  * and bit 4 (+16) is to keep the signal strength meter enabled
  */
@@ -140,7 +141,7 @@
 		outb_p(128+64+16+8+  1, port);  /* on + wr-enable + data low */
 		outb_p(128+64+16+8+2+1, port);  /* clock */
 	}
-	sleep_delay(1000); 
+	sleep_delay(1000);
 }
 
 static void send_1_byte(int port, struct rt_device *dev)
@@ -148,13 +149,13 @@
 	if ((dev->curvol == 0) || (dev->muted)) {
 		outb_p(128+64+16+4  +1, port);   /* wr-enable+data high */
 		outb_p(128+64+16+4+2+1, port);   /* clock */
-	} 
+	}
 	else {
 		outb_p(128+64+16+8+4  +1, port); /* on+wr-enable+data high */
 		outb_p(128+64+16+8+4+2+1, port); /* clock */
 	}
 
-	sleep_delay(1000); 
+	sleep_delay(1000);
 }
 
 static int rt_setfreq(struct rt_device *dev, unsigned long freq)
@@ -167,9 +168,9 @@
 
 	freq += 171200;			/* Add 10.7 MHz IF 		*/
 	freq /= 800;			/* Convert to 50 kHz units	*/
-	
+
 	mutex_lock(&lock);			/* Stop other ops interfering */
-	 
+
 	send_0_byte (io, dev);		/*  0: LSB of frequency		*/
 
 	for (i = 0; i < 13; i++)	/*   : frequency bits (1-13)	*/
@@ -195,7 +196,7 @@
 		outb (0xd0, io);	/* volume steady + sigstr */
 	else
 		outb (0xd8, io);	/* volume steady + sigstr + on */
-		
+
 	mutex_unlock(&lock);
 
 	return 0;
@@ -213,7 +214,7 @@
 {
 	struct video_device *dev = video_devdata(file);
 	struct rt_device *rt=dev->priv;
-	
+
 	switch(cmd)
 	{
 		case VIDIOCGCAP:
@@ -229,7 +230,7 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner *v = arg;
-			if(v->tuner)	/* Only 1 tuner */ 
+			if(v->tuner)	/* Only 1 tuner */
 				return -EINVAL;
 			v->rangelow=(87*16000);
 			v->rangehigh=(108*16000);
@@ -261,21 +262,21 @@
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0, sizeof(*v));
 			v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
 			v->volume=rt->curvol * 6554;
 			v->step=6554;
 			strcpy(v->name, "Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
-			if(v->flags&VIDEO_AUDIO_MUTE) 
+			if(v->flags&VIDEO_AUDIO_MUTE)
 				rt_mute(rt);
 			else
 				rt_setvol(rt,v->volume/6554);
@@ -298,7 +299,7 @@
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
-	.ioctl	        = rt_ioctl,
+	.ioctl		= rt_ioctl,
 	.compat_ioctl	= v4l_compat_ioctl32,
 	.llseek         = no_llseek,
 };
@@ -320,14 +321,14 @@
 		return -EINVAL;
 	}
 
-	if (!request_region(io, 2, "rtrack")) 
+	if (!request_region(io, 2, "rtrack"))
 	{
 		printk(KERN_ERR "rtrack: port 0x%x already in use\n", io);
 		return -EBUSY;
 	}
 
 	rtrack_radio.priv=&rtrack_unit;
-	
+
 	if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 2);
@@ -336,10 +337,10 @@
 	printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n");
 
 	/* Set up the I/O locking */
-	
+
 	mutex_init(&lock);
-	
- 	/* mute card - prevents noisy bootups */
+
+	/* mute card - prevents noisy bootups */
 
 	/* this ensures that the volume is all the way down  */
 	outb(0x48, io);		/* volume down but still "on"	*/
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c
index 83bdae2..95e6322 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -1,11 +1,11 @@
-/* radio-aztech.c - Aztech radio card driver for Linux 2.2 
+/* radio-aztech.c - Aztech radio card driver for Linux 2.2
  *
- * Adapted to support the Video for Linux API by 
+ * Adapted to support the Video for Linux API by
  * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
  * Quay Ly
  * Donald Song
- * Jason Lewis      (jlewis@twilight.vtc.vsc.edu) 
+ * Jason Lewis      (jlewis@twilight.vtc.vsc.edu)
  * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
  * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
  *
@@ -31,6 +31,7 @@
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_AZTECH_PORT 	*/
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
@@ -39,7 +40,7 @@
 #define CONFIG_RADIO_AZTECH_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_AZTECH_PORT; 
+static int io = CONFIG_RADIO_AZTECH_PORT;
 static int radio_nr = -1;
 static int radio_wait_time = 1000;
 static struct mutex lock;
@@ -53,15 +54,15 @@
 
 static int volconvert(int level)
 {
-	level>>=14;	 	/* Map 16bits down to 2 bit */
- 	level&=3;
-	
+	level>>=14;		/* Map 16bits down to 2 bit */
+	level&=3;
+
 	/* convert to card-friendly values */
-	switch (level) 
+	switch (level)
 	{
-		case 0: 
+		case 0:
 			return 0;
-		case 1: 
+		case 1:
 			return 1;
 		case 2:
 			return 4;
@@ -121,9 +122,9 @@
 
 	frequency += 171200;		/* Add 10.7 MHz IF		*/
 	frequency /= 800;		/* Convert to 50 kHz units	*/
-					
+
 	mutex_lock(&lock);
-	
+
 	send_0_byte (dev);		/*  0: LSB of frequency       */
 
 	for (i = 0; i < 13; i++)	/*   : frequency bits (1-13)  */
@@ -151,7 +152,7 @@
 
 	udelay (radio_wait_time);
 	outb_p(128+64+volconvert(dev->curvol), io);
-	
+
 	mutex_unlock(&lock);
 
 	return 0;
@@ -162,7 +163,7 @@
 {
 	struct video_device *dev = video_devdata(file);
 	struct az_device *az = dev->priv;
-	
+
 	switch(cmd)
 	{
 		case VIDIOCGCAP:
@@ -178,7 +179,7 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner *v = arg;
-			if(v->tuner)	/* Only 1 tuner */ 
+			if(v->tuner)	/* Only 1 tuner */
 				return -EINVAL;
 			v->rangelow=(87*16000);
 			v->rangehigh=(108*16000);
@@ -211,7 +212,7 @@
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0, sizeof(*v));
 			v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
@@ -222,17 +223,17 @@
 			v->volume=az->curvol;
 			v->step=16384;
 			strcpy(v->name, "Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
 			az->curvol=v->volume;
 
 			az->stereo=(v->mode&VIDEO_SOUND_STEREO)?1:0;
-			if(v->flags&VIDEO_AUDIO_MUTE) 
+			if(v->flags&VIDEO_AUDIO_MUTE)
 				az_setvol(az,0);
 			else
 				az_setvol(az,az->curvol);
@@ -277,7 +278,7 @@
 		return -EINVAL;
 	}
 
-	if (!request_region(io, 2, "aztech")) 
+	if (!request_region(io, 2, "aztech"))
 	{
 		printk(KERN_ERR "aztech: port 0x%x already in use\n", io);
 		return -EBUSY;
@@ -285,13 +286,13 @@
 
 	mutex_init(&lock);
 	aztech_radio.priv=&aztech_unit;
-	
+
 	if(video_register_device(&aztech_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io,2);
 		return -EINVAL;
 	}
-		
+
 	printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
 	/* mute card - prevents noisy bootups */
 	outb (0, io);
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index f1b5ac8..8641aec 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -8,7 +8,7 @@
  * Russell Kroll    (rkroll@exploits.org)
  * Quay Ly
  * Donald Song
- * Jason Lewis      (jlewis@twilight.vtc.vsc.edu) 
+ * Jason Lewis      (jlewis@twilight.vtc.vsc.edu)
  * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
  * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
  *
@@ -34,6 +34,7 @@
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/param.h>
 #include <linux/pnp.h>
 
@@ -55,29 +56,29 @@
 
 /*
  * Signal Strength Threshold Values
- * The V4L API spec does not define any particular unit for the signal 
+ * The V4L API spec does not define any particular unit for the signal
  * strength value.  These values are in microvolts of RF at the tuner's input.
  */
 static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}};
 
 static int cadet_getrds(void)
 {
-        int rdsstat=0;
+	int rdsstat=0;
 
 	spin_lock(&cadet_io_lock);
-        outb(3,io);                 /* Select Decoder Control/Status */
+	outb(3,io);                 /* Select Decoder Control/Status */
 	outb(inb(io+1)&0x7f,io+1);  /* Reset RDS detection */
 	spin_unlock(&cadet_io_lock);
-	
+
 	msleep(100);
 
-	spin_lock(&cadet_io_lock);	
-        outb(3,io);                 /* Select Decoder Control/Status */
+	spin_lock(&cadet_io_lock);
+	outb(3,io);                 /* Select Decoder Control/Status */
 	if((inb(io+1)&0x80)!=0) {
-	        rdsstat|=VIDEO_TUNER_RDS_ON;
+		rdsstat|=VIDEO_TUNER_RDS_ON;
 	}
 	if((inb(io+1)&0x10)!=0) {
-	        rdsstat|=VIDEO_TUNER_MBS_ON;
+		rdsstat|=VIDEO_TUNER_MBS_ON;
 	}
 	spin_unlock(&cadet_io_lock);
 	return rdsstat;
@@ -86,49 +87,49 @@
 static int cadet_getstereo(void)
 {
 	int ret = 0;
-        if(curtuner != 0)	/* Only FM has stereo capability! */
-	        return 0;
+	if(curtuner != 0)	/* Only FM has stereo capability! */
+		return 0;
 
 	spin_lock(&cadet_io_lock);
-        outb(7,io);          /* Select tuner control */
+	outb(7,io);          /* Select tuner control */
 	if( (inb(io+1) & 0x40) == 0)
-        	ret = 1;
-        spin_unlock(&cadet_io_lock);
-        return ret;
+		ret = 1;
+	spin_unlock(&cadet_io_lock);
+	return ret;
 }
 
 static unsigned cadet_gettune(void)
 {
-        int curvol,i;
+	int curvol,i;
 	unsigned fifo=0;
 
-        /*
-         * Prepare for read
-         */
+	/*
+	 * Prepare for read
+	 */
 
 	spin_lock(&cadet_io_lock);
-	
-        outb(7,io);       /* Select tuner control */
-        curvol=inb(io+1); /* Save current volume/mute setting */
-        outb(0x00,io+1);  /* Ensure WRITE-ENABLE is LOW */
+
+	outb(7,io);       /* Select tuner control */
+	curvol=inb(io+1); /* Save current volume/mute setting */
+	outb(0x00,io+1);  /* Ensure WRITE-ENABLE is LOW */
 	tunestat=0xffff;
 
-        /*
-         * Read the shift register
-         */
-        for(i=0;i<25;i++) {
-                fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
-                if(i<24) {
-                        outb(0x01,io+1);
+	/*
+	 * Read the shift register
+	 */
+	for(i=0;i<25;i++) {
+		fifo=(fifo<<1)|((inb(io+1)>>7)&0x01);
+		if(i<24) {
+			outb(0x01,io+1);
 			tunestat&=inb(io+1);
-                        outb(0x00,io+1);
-                }
-        }
+			outb(0x00,io+1);
+		}
+	}
 
-        /*
-         * Restore volume/mute setting
-         */
-        outb(curvol,io+1);
+	/*
+	 * Restore volume/mute setting
+	 */
+	outb(curvol,io+1);
 	spin_unlock(&cadet_io_lock);
 
 	return fifo;
@@ -136,43 +137,43 @@
 
 static unsigned cadet_getfreq(void)
 {
-        int i;
-        unsigned freq=0,test,fifo=0;
+	int i;
+	unsigned freq=0,test,fifo=0;
 
 	/*
 	 * Read current tuning
 	 */
 	fifo=cadet_gettune();
 
-        /*
-         * Convert to actual frequency
-         */
+	/*
+	 * Convert to actual frequency
+	 */
 	if(curtuner==0) {    /* FM */
-	        test=12500;
-                for(i=0;i<14;i++) {
-                        if((fifo&0x01)!=0) {
-                                freq+=test;
-                        }
-                        test=test<<1;
-                        fifo=fifo>>1;
-                }
-                freq-=10700000;           /* IF frequency is 10.7 MHz */
-                freq=(freq*16)/1000000;   /* Make it 1/16 MHz */
+		test=12500;
+		for(i=0;i<14;i++) {
+			if((fifo&0x01)!=0) {
+				freq+=test;
+			}
+			test=test<<1;
+			fifo=fifo>>1;
+		}
+		freq-=10700000;           /* IF frequency is 10.7 MHz */
+		freq=(freq*16)/1000000;   /* Make it 1/16 MHz */
 	}
 	if(curtuner==1) {    /* AM */
-	        freq=((fifo&0x7fff)-2010)*16;
+		freq=((fifo&0x7fff)-2010)*16;
 	}
 
-        return freq;
+	return freq;
 }
 
 static void cadet_settune(unsigned fifo)
 {
-        int i;
-	unsigned test;  
+	int i;
+	unsigned test;
 
 	spin_lock(&cadet_io_lock);
-	
+
 	outb(7,io);                /* Select tuner control */
 	/*
 	 * Write the shift register
@@ -183,7 +184,7 @@
 	outb(7,io);                /* Select tuner control */
 	outb(test,io+1);           /* Initialize for write */
 	for(i=0;i<25;i++) {
-   	        test|=0x01;              /* Toggle SCK High */
+		test|=0x01;              /* Toggle SCK High */
 		outb(test,io+1);
 		test&=0xfe;              /* Toggle SCK Low */
 		outb(test,io+1);
@@ -196,57 +197,57 @@
 
 static void cadet_setfreq(unsigned freq)
 {
-        unsigned fifo;
-        int i,j,test;
-        int curvol;
+	unsigned fifo;
+	int i,j,test;
+	int curvol;
 
-        /* 
-         * Formulate a fifo command
-         */
+	/*
+	 * Formulate a fifo command
+	 */
 	fifo=0;
 	if(curtuner==0) {    /* FM */
-        	test=102400;
-                freq=(freq*1000)/16;       /* Make it kHz */
-                freq+=10700;               /* IF is 10700 kHz */
-                for(i=0;i<14;i++) {
-                        fifo=fifo<<1;
-                        if(freq>=test) {
-                                fifo|=0x01;
-                                freq-=test;
-                        }
-                        test=test>>1;
-                }
+		test=102400;
+		freq=(freq*1000)/16;       /* Make it kHz */
+		freq+=10700;               /* IF is 10700 kHz */
+		for(i=0;i<14;i++) {
+			fifo=fifo<<1;
+			if(freq>=test) {
+				fifo|=0x01;
+				freq-=test;
+			}
+			test=test>>1;
+		}
 	}
 	if(curtuner==1) {    /* AM */
-                fifo=(freq/16)+2010;            /* Make it kHz */
+		fifo=(freq/16)+2010;            /* Make it kHz */
 		fifo|=0x100000;            /* Select AM Band */
 	}
 
-        /*
-         * Save current volume/mute setting
-         */
+	/*
+	 * Save current volume/mute setting
+	 */
 
 	spin_lock(&cadet_io_lock);
 	outb(7,io);                /* Select tuner control */
-        curvol=inb(io+1); 
-        spin_unlock(&cadet_io_lock);
+	curvol=inb(io+1);
+	spin_unlock(&cadet_io_lock);
 
 	/*
 	 * Tune the card
 	 */
 	for(j=3;j>-1;j--) {
-	        cadet_settune(fifo|(j<<16));
-	        
-	        spin_lock(&cadet_io_lock);
+		cadet_settune(fifo|(j<<16));
+
+		spin_lock(&cadet_io_lock);
 		outb(7,io);         /* Select tuner control */
 		outb(curvol,io+1);
 		spin_unlock(&cadet_io_lock);
-		
+
 		msleep(100);
 
 		cadet_gettune();
 		if((tunestat & 0x40) == 0) {   /* Tuned */
-		        sigstrength=sigtable[curtuner][j];
+			sigstrength=sigtable[curtuner][j];
 			return;
 		}
 	}
@@ -257,28 +258,28 @@
 static int cadet_getvol(void)
 {
 	int ret = 0;
-	
+
 	spin_lock(&cadet_io_lock);
-	
-        outb(7,io);                /* Select tuner control */
-        if((inb(io + 1) & 0x20) != 0)
-        	ret = 0xffff;
-        
-        spin_unlock(&cadet_io_lock);
-        return ret;
+
+	outb(7,io);                /* Select tuner control */
+	if((inb(io + 1) & 0x20) != 0)
+		ret = 0xffff;
+
+	spin_unlock(&cadet_io_lock);
+	return ret;
 }
 
 
 static void cadet_setvol(int vol)
 {
 	spin_lock(&cadet_io_lock);
-        outb(7,io);                /* Select tuner control */
-        if(vol>0)
-                outb(0x20,io+1);
-        else
-                outb(0x00,io+1);
+	outb(7,io);                /* Select tuner control */
+	if(vol>0)
+		outb(0x20,io+1);
+	else
+		outb(0x00,io+1);
 	spin_unlock(&cadet_io_lock);
-}  
+}
 
 static void cadet_handler(unsigned long data)
 {
@@ -288,15 +289,15 @@
 
 	if(spin_trylock(&cadet_io_lock))
 	{
-	        outb(0x3,io);       /* Select RDS Decoder Control */
+		outb(0x3,io);       /* Select RDS Decoder Control */
 		if((inb(io+1)&0x20)!=0) {
-		        printk(KERN_CRIT "cadet: RDS fifo overflow\n");
+			printk(KERN_CRIT "cadet: RDS fifo overflow\n");
 		}
 		outb(0x80,io);      /* Select RDS fifo */
 		while((inb(io)&0x80)!=0) {
-		        rdsbuf[rdsin]=inb(io+1);
+			rdsbuf[rdsin]=inb(io+1);
 			if(rdsin==rdsout)
-			        printk(KERN_WARNING "cadet: RDS buffer overflow\n");
+				printk(KERN_WARNING "cadet: RDS buffer overflow\n");
 			else
 				rdsin++;
 		}
@@ -307,9 +308,9 @@
 	 * Service pending read
 	 */
 	if( rdsin!=rdsout)
-	        wake_up_interruptible(&read_queue);
+		wake_up_interruptible(&read_queue);
 
-	/* 
+	/*
 	 * Clean up and exit
 	 */
 	init_timer(&readtimer);
@@ -324,12 +325,12 @@
 static ssize_t cadet_read(struct file *file, char __user *data,
 			  size_t count, loff_t *ppos)
 {
-        int i=0;
+	int i=0;
 	unsigned char readbuf[RDS_BUFFER];
 
-        if(rdsstat==0) {
+	if(rdsstat==0) {
 		spin_lock(&cadet_io_lock);
-	        rdsstat=1;
+		rdsstat=1;
 		outb(0x80,io);        /* Select RDS fifo */
 		spin_unlock(&cadet_io_lock);
 		init_timer(&readtimer);
@@ -339,15 +340,15 @@
 		add_timer(&readtimer);
 	}
 	if(rdsin==rdsout) {
-  	        if (file->f_flags & O_NONBLOCK)
-		        return -EWOULDBLOCK;
-	        interruptible_sleep_on(&read_queue);
-	}		
+		if (file->f_flags & O_NONBLOCK)
+			return -EWOULDBLOCK;
+		interruptible_sleep_on(&read_queue);
+	}
 	while( i<count && rdsin!=rdsout)
-	        readbuf[i++]=rdsbuf[rdsout++];
+		readbuf[i++]=rdsbuf[rdsout++];
 
 	if (copy_to_user(data,readbuf,i))
-	        return -EFAULT;
+		return -EFAULT;
 	return i;
 }
 
@@ -375,29 +376,29 @@
 				return -EINVAL;
 			}
 			switch(v->tuner) {
-			        case 0:
-			        strcpy(v->name,"FM");
-			        v->rangelow=1400;     /* 87.5 MHz */
-			        v->rangehigh=1728;    /* 108.0 MHz */
-			        v->flags=0;
-			        v->mode=0;
-			        v->mode|=VIDEO_MODE_AUTO;
-			        v->signal=sigstrength;
-			        if(cadet_getstereo()==1) {
-				        v->flags|=VIDEO_TUNER_STEREO_ON;
-			        }
+				case 0:
+				strcpy(v->name,"FM");
+				v->rangelow=1400;     /* 87.5 MHz */
+				v->rangehigh=1728;    /* 108.0 MHz */
+				v->flags=0;
+				v->mode=0;
+				v->mode|=VIDEO_MODE_AUTO;
+				v->signal=sigstrength;
+				if(cadet_getstereo()==1) {
+					v->flags|=VIDEO_TUNER_STEREO_ON;
+				}
 				v->flags|=cadet_getrds();
-			        break;
-			        case 1:
-			        strcpy(v->name,"AM");
-			        v->rangelow=8320;      /* 520 kHz */
-			        v->rangehigh=26400;    /* 1650 kHz */
-			        v->flags=0;
-			        v->flags|=VIDEO_TUNER_LOW;
-			        v->mode=0;
-			        v->mode|=VIDEO_MODE_AUTO;
-			        v->signal=sigstrength;
-			        break;
+				break;
+				case 1:
+				strcpy(v->name,"AM");
+				v->rangelow=8320;      /* 520 kHz */
+				v->rangehigh=26400;    /* 1650 kHz */
+				v->flags=0;
+				v->flags|=VIDEO_TUNER_LOW;
+				v->mode=0;
+				v->mode|=VIDEO_MODE_AUTO;
+				v->signal=sigstrength;
+				break;
 			}
 			return 0;
 		}
@@ -407,49 +408,49 @@
 			if((v->tuner<0)||(v->tuner>1)) {
 				return -EINVAL;
 			}
-			curtuner=v->tuner;	
+			curtuner=v->tuner;
 			return 0;
 		}
 		case VIDIOCGFREQ:
 		{
-		        unsigned long *freq = arg;
+			unsigned long *freq = arg;
 			*freq = cadet_getfreq();
 			return 0;
 		}
 		case VIDIOCSFREQ:
 		{
-		        unsigned long *freq = arg;
+			unsigned long *freq = arg;
 			if((curtuner==0)&&((*freq<1400)||(*freq>1728))) {
-			        return -EINVAL;
+				return -EINVAL;
 			}
 			if((curtuner==1)&&((*freq<8320)||(*freq>26400))) {
-			        return -EINVAL;
+				return -EINVAL;
 			}
 			cadet_setfreq(*freq);
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0, sizeof(*v));
 			v->flags=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
 			if(cadet_getstereo()==0) {
-			        v->mode=VIDEO_SOUND_MONO;
+				v->mode=VIDEO_SOUND_MONO;
 			} else {
 				v->mode=VIDEO_SOUND_STEREO;
 			}
 			v->volume=cadet_getvol();
 			v->step=0xffff;
 			strcpy(v->name, "Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
 			cadet_setvol(v->volume);
-			if(v->flags&VIDEO_AUDIO_MUTE) 
+			if(v->flags&VIDEO_AUDIO_MUTE)
 				cadet_setvol(0);
 			else
 				cadet_setvol(0xffff);
@@ -539,16 +540,16 @@
 
 static int cadet_probe(void)
 {
-        static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
+	static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e};
 	int i;
 
 	for(i=0;i<8;i++) {
-	        io=iovals[i];
+		io=iovals[i];
 		if (request_region(io, 2, "cadet-probe")) {
-		        cadet_setfreq(1410);
+			cadet_setfreq(1410);
 			if(cadet_getfreq()==1410) {
 				release_region(io, 2);
-			        return io;
+				return io;
 			}
 			release_region(io, 2);
 		}
@@ -556,7 +557,7 @@
 	return -1;
 }
 
-/* 
+/*
  * io should only be set if the user has used something like
  * isapnp (the userspace program) to initialize this card for us
  */
@@ -564,7 +565,7 @@
 static int __init cadet_init(void)
 {
 	spin_lock_init(&cadet_io_lock);
-	
+
 	/*
 	 *	If a probe was requested then probe ISAPnP first (safest)
 	 */
@@ -579,12 +580,12 @@
 	/*
 	 *	Else we bail out
 	 */
-	 
-        if(io < 0) {
-#ifdef MODULE        
+
+	if(io < 0) {
+#ifdef MODULE
 		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
 #endif
-	        goto fail;
+		goto fail;
 	}
 	if (!request_region(io,2,"cadet"))
 		goto fail;
diff --git a/drivers/media/radio/radio-gemtek-pci.c b/drivers/media/radio/radio-gemtek-pci.c
index 8e499b8..9f249e7 100644
--- a/drivers/media/radio/radio-gemtek-pci.c
+++ b/drivers/media/radio/radio-gemtek-pci.c
@@ -1,6 +1,6 @@
 /*
  ***************************************************************************
- *     
+ *
  *     radio-gemtek-pci.c - Gemtek PCI Radio driver
  *     (C) 2001 Vladimir Shebordaev <vshebordaev@mail.ru>
  *
@@ -31,7 +31,7 @@
  *     radio device driver.
  *
  *     Please, let me know if this piece of code was useful :)
- * 
+ *
  *     TODO: multiple device support and portability were not tested
  *
  ***************************************************************************
@@ -44,6 +44,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/errno.h>
 
 #include <asm/io.h>
@@ -69,18 +70,18 @@
 #define TRUE (1)
 #endif
 
-#ifndef FALSE 
+#ifndef FALSE
 #define FALSE (0)
 #endif
 
 struct gemtek_pci_card {
 	struct video_device *videodev;
-	
+
 	u32 iobase;
 	u32 length;
 	u8  chiprev;
 	u16 model;
-	
+
 	u32 current_frequency;
 	u8  mute;
 };
@@ -96,7 +97,7 @@
 	return (u8)value;
 }
 
-#define _b0( v ) *((u8 *)&v)  
+#define _b0( v ) *((u8 *)&v)
 static void __gemtek_pci_cmd( u16 value, u32 port, u8 *last_byte, int keep )
 {
 	register u8 byte = *last_byte;
@@ -104,7 +105,7 @@
 	if ( !value ) {
 		if ( !keep )
 			value = (u16)port;
-		byte &= 0xfd;	
+		byte &= 0xfd;
 	} else
 		byte |= 2;
 
@@ -116,7 +117,7 @@
 	byte &= 0xfe;
 	_b0( value ) = byte;
 	outw( value, port );
-	
+
 	*last_byte = byte;
 }
 
@@ -193,13 +194,13 @@
 			c->audios = 1;
 			strcpy( c->name, "Gemtek PCI Radio" );
 			return 0;
-		} 
+		}
 
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner *t = arg;
 
-			if ( t->tuner ) 
+			if ( t->tuner )
 				return -EINVAL;
 
 			t->rangelow = GEMTEK_PCI_RANGE_LOW;
@@ -228,7 +229,7 @@
 		case VIDIOCSFREQ:
 		{
 			unsigned long *freq = arg;
-	 
+
 			if ( (*freq < GEMTEK_PCI_RANGE_LOW) ||
 			     (*freq > GEMTEK_PCI_RANGE_HIGH) )
 				return -EINVAL;
@@ -239,9 +240,9 @@
 
 			return 0;
 		}
-  
+
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *a = arg;
 
 			memset( a, 0, sizeof( *a ) );
@@ -249,17 +250,17 @@
 			a->volume = 1;
 			a->step = 65535;
 			strcpy( a->name, "Radio" );
-			return 0;			
+			return 0;
 		}
 
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *a = arg;
 
-			if ( a->audio ) 
+			if ( a->audio )
 				return -EINVAL;
 
-			if ( a->flags & VIDEO_AUDIO_MUTE ) 
+			if ( a->flags & VIDEO_AUDIO_MUTE )
 				gemtek_pci_mute( card );
 			else
 				gemtek_pci_unmute( card );
@@ -323,9 +324,9 @@
 		return -ENOMEM;
 	}
 
-	if ( pci_enable_device( pci_dev ) ) 
+	if ( pci_enable_device( pci_dev ) )
 		goto err_pci;
-	
+
 	card->iobase = pci_resource_start( pci_dev, 0 );
 	card->length = pci_resource_len( pci_dev, 0 );
 
@@ -338,7 +339,7 @@
 	pci_read_config_word( pci_dev, PCI_SUBSYSTEM_ID, &card->model );
 
 	pci_set_drvdata( pci_dev, card );
- 
+
 	if ( (devradio = kmalloc( sizeof( struct video_device ), GFP_KERNEL )) == NULL ) {
 		printk( KERN_ERR "gemtek_pci: out of memory\n" );
 		goto err_video;
@@ -354,7 +355,7 @@
 	devradio->priv = card;
 	gemtek_pci_mute( card );
 
-	printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n", 
+	printk( KERN_INFO "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
 		card->chiprev, card->iobase, card->iobase + card->length - 1 );
 
 	return 0;
@@ -364,7 +365,7 @@
 
 err_pci:
 	kfree( card );
-	return -ENODEV;        
+	return -ENODEV;
 }
 
 static void __devexit gemtek_pci_remove( struct pci_dev *pci_dev )
@@ -375,12 +376,12 @@
 	kfree( card->videodev );
 
 	release_region( card->iobase, card->length );
-	
+
 	if ( mx )
 		gemtek_pci_mute( card );
 
 	kfree( card );
-	
+
 	pci_set_drvdata( pci_dev, NULL );
 }
 
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c
index 47173be..162f37d 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -6,7 +6,7 @@
  * Besides the protocol changes, this is mostly a copy of:
  *
  *    RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
- * 
+ *
  *    Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
  *    Converted to new API by Alan Cox <Alan.Cox@linux.org>
  *    Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
@@ -22,6 +22,7 @@
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_GEMTEK_PORT 	*/
 #include <linux/spinlock.h>
 
@@ -29,7 +30,7 @@
 #define CONFIG_RADIO_GEMTEK_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_GEMTEK_PORT; 
+static int io = CONFIG_RADIO_GEMTEK_PORT;
 static int radio_nr = -1;
 static spinlock_t lock;
 
@@ -48,7 +49,7 @@
  */
 static void gemtek_mute(struct gemtek_device *dev)
 {
-        if(dev->muted)
+	if(dev->muted)
 		return;
 	spin_lock(&lock);
 	outb(0x10, io);
@@ -94,20 +95,20 @@
 	freq /= 100000;
 
 	spin_lock(&lock);
-	
+
 	/* 2 start bits */
 	outb_p(0x03, io);
 	udelay(5);
 	outb_p(0x07, io);
 	udelay(5);
 
-        /* 28 frequency bits (lsb first) */
+	/* 28 frequency bits (lsb first) */
 	for (i = 0; i < 14; i++)
 		if (freq & (1 << i))
 			one();
 		else
 			zero();
-        /* 36 unknown bits */
+	/* 36 unknown bits */
 	for (i = 0; i < 11; i++)
 		zero();
 	one();
@@ -123,7 +124,7 @@
 	udelay(5);
 
 	spin_unlock(&lock);
-	
+
 	return 0;
 }
 
@@ -159,7 +160,7 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner *v = arg;
-			if(v->tuner)	/* Only 1 tuner */ 
+			if(v->tuner)	/* Only 1 tuner */
 				return -EINVAL;
 			v->rangelow=87*16000;
 			v->rangehigh=108*16000;
@@ -193,25 +194,25 @@
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0, sizeof(*v));
 			v->flags|=VIDEO_AUDIO_MUTABLE;
 			v->volume=1;
 			v->step=65535;
 			strcpy(v->name, "Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
 
-			if(v->flags&VIDEO_AUDIO_MUTE) 
+			if(v->flags&VIDEO_AUDIO_MUTE)
 				gemtek_mute(rt);
 			else
-			        gemtek_unmute(rt);
+				gemtek_unmute(rt);
 
 			return 0;
 		}
@@ -254,14 +255,14 @@
 		return -EINVAL;
 	}
 
-	if (!request_region(io, 4, "gemtek")) 
+	if (!request_region(io, 4, "gemtek"))
 	{
 		printk(KERN_ERR "gemtek: port 0x%x already in use\n", io);
 		return -EBUSY;
 	}
 
 	gemtek_radio.priv=&gemtek_unit;
-	
+
 	if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 4);
@@ -274,7 +275,7 @@
 	/* this is _maybe_ unnecessary */
 	outb(0x01, io);
 
- 	/* mute card - prevents noisy bootups */
+	/* mute card - prevents noisy bootups */
 	gemtek_unit.muted = 0;
 	gemtek_mute(&gemtek_unit);
 
diff --git a/drivers/media/radio/radio-maestro.c b/drivers/media/radio/radio-maestro.c
index 39c1d91..fcfa6c9 100644
--- a/drivers/media/radio/radio-maestro.c
+++ b/drivers/media/radio/radio-maestro.c
@@ -2,7 +2,7 @@
  * (c) 2000 A. Tlalka, atlka@pg.gda.pl
  * Notes on the hardware
  *
- *  + Frequency control is done digitally 
+ *  + Frequency control is done digitally
  *  + No volume control - only mute/unmute - you have to use Aux line volume
  *  control on Maestro card to set the volume
  *  + Radio status (tuned/not_tuned and stereo/mono) is valid some time after
@@ -26,7 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/videodev.h>
-
+#include <media/v4l2-common.h>
 
 #define DRIVER_VERSION	"0.05"
 
@@ -103,7 +103,7 @@
 struct radio_device {
 	u16	io,	/* base of Maestro card radio io (GPIO_DATA)*/
 		muted,	/* VIDEO_AUDIO_MUTE */
-		stereo,	/* VIDEO_TUNER_STEREO_ON */	
+		stereo,	/* VIDEO_TUNER_STEREO_ON */
 		tuned;	/* signal strength (0 or 0xffff) */
 	struct mutex lock;
 };
@@ -122,14 +122,14 @@
 	for (l=24;l--;) {
 		outw(STR_CLK, io);		/* HI state */
 		udelay(2);
-		if(!l) 
+		if(!l)
 			dev->tuned = inw(io) & STR_MOST ? 0 : 0xffff;
 		outw(0, io);			/* LO state */
 		udelay(2);
 		data <<= 1;			/* shift data */
 		rdata = inw(io);
 		if(!l)
-			dev->stereo =  rdata & STR_MOST ? 
+			dev->stereo =  rdata & STR_MOST ?
 			0 : VIDEO_TUNER_STEREO_ON;
 		else
 			if(rdata & STR_DATA)
diff --git a/drivers/media/radio/radio-maxiradio.c b/drivers/media/radio/radio-maxiradio.c
index f0bf47b..f93d7af 100644
--- a/drivers/media/radio/radio-maxiradio.c
+++ b/drivers/media/radio/radio-maxiradio.c
@@ -1,15 +1,15 @@
-/* 
- * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux 
+/*
+ * Guillemot Maxi Radio FM 2000 PCI radio card driver for Linux
  * (C) 2001 Dimitromanolakis Apostolos <apdim@grecian.net>
  *
  * Based in the radio Maestro PCI driver. Actually it uses the same chip
  * for radio but different pci controller.
  *
  * I didn't have any specs I reversed engineered the protocol from
- * the windows driver (radio.dll). 
+ * the windows driver (radio.dll).
  *
  * The card uses the TEA5757 chip that includes a search function but it
- * is useless as I haven't found any way to read back the frequency. If 
+ * is useless as I haven't found any way to read back the frequency. If
  * anybody does please mail me.
  *
  * For the pdf file see:
@@ -24,7 +24,7 @@
  *     - tiding up
  *     - removed support for multiple devices as it didn't work anyway
  *
- * BUGS: 
+ * BUGS:
  *   - card unmutes if you change frequency
  *
  */
@@ -41,6 +41,7 @@
 
 #include <linux/pci.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 /* version 0.75      Sun Feb  4 22:51:27 EET 2001 */
 #define DRIVER_VERSION	"0.75"
@@ -80,7 +81,7 @@
 	.owner		= THIS_MODULE,
 	.open           = video_exclusive_open,
 	.release        = video_exclusive_release,
-	.ioctl	        = radio_ioctl,
+	.ioctl		= radio_ioctl,
 	.compat_ioctl	= v4l_compat_ioctl32,
 	.llseek         = no_llseek,
 };
@@ -97,11 +98,11 @@
 {
 	__u16	io,	/* base of radio io */
 		muted,	/* VIDEO_AUDIO_MUTE */
-		stereo,	/* VIDEO_TUNER_STEREO_ON */	
+		stereo,	/* VIDEO_TUNER_STEREO_ON */
 		tuned;	/* signal strength (0 or 0xffff) */
-		
+
 	unsigned long freq;
-	
+
 	struct mutex lock;
 } radio_unit = {0, 0, 0, 0, };
 
@@ -114,7 +115,7 @@
 			outb(  power|wren|data|clk ,io); udelay(4);
 			outb(  power|wren|data     ,io); udelay(4);
 		}
-	else	
+	else
 		{
 			outb(  power|wren          ,io); udelay(4);
 			outb(  power|wren|clk      ,io); udelay(4);
@@ -132,12 +133,12 @@
 {
 	unsigned long int si;
 	int bl;
-	
+
 	/* TEA5757 shift register bits (see pdf) */
 
-	outbit(0,io); // 24  search 
+	outbit(0,io); // 24  search
 	outbit(1,io); // 23  search up/down
-	
+
 	outbit(0,io); // 22  stereo/mono
 
 	outbit(0,io); // 21  band
@@ -145,24 +146,24 @@
 
 	outbit(0,io); // 19  port ?
 	outbit(0,io); // 18  port ?
-	
+
 	outbit(0,io); // 17  search level
 	outbit(0,io); // 16  search level
- 
+
 	si = 0x8000;
 	for(bl = 1; bl <= 16 ; bl++) { outbit(data & si,io); si >>=1; }
-	
+
 	outb(power,io);
 }
 
 static int get_stereo(__u16 io)
-{	
+{
 	outb(power,io); udelay(4);
 	return !(inb(io) & mo_st);
 }
 
 static int get_tune(__u16 io)
-{	
+{
 	outb(power+clk,io); udelay(4);
 	return !(inb(io) & mo_st);
 }
@@ -177,7 +178,7 @@
 	switch(cmd) {
 		case VIDIOCGCAP: {
 			struct video_capability *v = arg;
-			
+
 			memset(v,0,sizeof(*v));
 			strcpy(v->name, "Maxi Radio FM2000 radio");
 			v->type=VID_TYPE_TUNER;
@@ -186,22 +187,22 @@
 		}
 		case VIDIOCGTUNER: {
 			struct video_tuner *v = arg;
-			
+
 			if(v->tuner)
 				return -EINVAL;
-				
+
 			card->stereo = 0xffff * get_stereo(card->io);
 			card->tuned = 0xffff * get_tune(card->io);
-			
+
 			v->flags = VIDEO_TUNER_LOW | card->stereo;
 			v->signal = card->tuned;
-			
+
 			strcpy(v->name, "FM");
-			
+
 			v->rangelow = FREQ_LO;
 			v->rangehigh = FREQ_HI;
 			v->mode = VIDEO_MODE_AUTO;
-			
+
 			return 0;
 		}
 		case VIDIOCSTUNER: {
@@ -212,13 +213,13 @@
 		}
 		case VIDIOCGFREQ: {
 			unsigned long *freq = arg;
-			
+
 			*freq = card->freq;
 			return 0;
 		}
 		case VIDIOCSFREQ: {
 			unsigned long *freq = arg;
-			
+
 			if (*freq < FREQ_LO || *freq > FREQ_HI)
 				return -EINVAL;
 			card->freq = *freq;
@@ -226,18 +227,18 @@
 			msleep(125);
 			return 0;
 		}
-		case VIDIOCGAUDIO: {	
+		case VIDIOCGAUDIO: {
 			struct video_audio *v = arg;
 			memset(v,0,sizeof(*v));
 			strcpy(v->name, "Radio");
 			v->flags=VIDEO_AUDIO_MUTABLE | card->muted;
 			v->mode=VIDEO_SOUND_STEREO;
-			return 0;		
+			return 0;
 		}
-		
+
 		case VIDIOCSAUDIO: {
 			struct video_audio *v = arg;
-			
+
 			if(v->audio)
 				return -EINVAL;
 			card->muted = v->flags & VIDEO_AUDIO_MUTE;
@@ -249,13 +250,13 @@
 		}
 		case VIDIOCGUNIT: {
 			struct video_unit *v = arg;
-			
+
 			v->video=VIDEO_NO_UNIT;
 			v->vbi=VIDEO_NO_UNIT;
 			v->radio=dev->minor;
 			v->audio=0;
 			v->teletext=VIDEO_NO_UNIT;
-			return 0;		
+			return 0;
 		}
 		default: return -ENOIOCTLCMD;
 	}
@@ -267,7 +268,7 @@
 	struct video_device *dev = video_devdata(file);
 	struct radio_device *card=dev->priv;
 	int ret;
-	
+
 	mutex_lock(&card->lock);
 	ret = video_usercopy(inode, file, cmd, arg, radio_function);
 	mutex_unlock(&card->lock);
@@ -282,21 +283,21 @@
 static int __devinit maxiradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	if(!request_region(pci_resource_start(pdev, 0),
-	                   pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) {
-	        printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n");
-	        goto err_out;
+			   pci_resource_len(pdev, 0), "Maxi Radio FM 2000")) {
+		printk(KERN_ERR "radio-maxiradio: can't reserve I/O ports\n");
+		goto err_out;
 	}
 
 	if (pci_enable_device(pdev))
-	        goto err_out_free_region;
+		goto err_out_free_region;
 
 	radio_unit.io = pci_resource_start(pdev, 0);
 	mutex_init(&radio_unit.lock);
 	maxiradio_radio.priv = &radio_unit;
 
 	if(video_register_device(&maxiradio_radio, VFL_TYPE_RADIO, radio_nr)==-1) {
-	        printk("radio-maxiradio: can't register device!");
-	        goto err_out_free_region;
+		printk("radio-maxiradio: can't register device!");
+		goto err_out_free_region;
 	}
 
 	printk(KERN_INFO "radio-maxiradio: version "
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c
index 28a47c9..5b68ac4 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -1,5 +1,5 @@
 /* RadioTrack II driver for Linux radio support (C) 1998 Ben Pfaff
- * 
+ *
  * Based on RadioTrack I/RadioReveal (C) 1997 M. Kirkwood
  * Converted to new API by Alan Cox <Alan.Cox@linux.org>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
@@ -15,6 +15,7 @@
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_RTRACK2_PORT 	*/
 #include <linux/spinlock.h>
 
@@ -22,7 +23,7 @@
 #define CONFIG_RADIO_RTRACK2_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_RTRACK2_PORT; 
+static int io = CONFIG_RADIO_RTRACK2_PORT;
 static int radio_nr = -1;
 static spinlock_t lock;
 
@@ -38,7 +39,7 @@
 
 static void rt_mute(struct rt_device *dev)
 {
-        if(dev->muted)
+	if(dev->muted)
 		return;
 	spin_lock(&lock);
 	outb(1, io);
@@ -58,14 +59,14 @@
 
 static void zero(void)
 {
-        outb_p(1, io);
+	outb_p(1, io);
 	outb_p(3, io);
 	outb_p(1, io);
 }
 
 static void one(void)
 {
-        outb_p(5, io);
+	outb_p(5, io);
 	outb_p(7, io);
 	outb_p(5, io);
 }
@@ -75,7 +76,7 @@
 	int i;
 
 	freq = freq / 200 + 856;
-	
+
 	spin_lock(&lock);
 
 	outb_p(0xc8, io);
@@ -94,7 +95,7 @@
 	outb_p(0xc8, io);
 	if (!dev->muted)
 		outb_p(0, io);
-		
+
 	spin_unlock(&lock);
 	return 0;
 }
@@ -127,7 +128,7 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner *v = arg;
-			if(v->tuner)	/* Only 1 tuner */ 
+			if(v->tuner)	/* Only 1 tuner */
 				return -EINVAL;
 			v->rangelow=88*16000;
 			v->rangehigh=108*16000;
@@ -159,25 +160,25 @@
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0, sizeof(*v));
 			v->flags|=VIDEO_AUDIO_MUTABLE;
 			v->volume=1;
 			v->step=65535;
 			strcpy(v->name, "Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
 
-			if(v->flags&VIDEO_AUDIO_MUTE) 
+			if(v->flags&VIDEO_AUDIO_MUTE)
 				rt_mute(rt);
 			else
-			        rt_unmute(rt);
+				rt_unmute(rt);
 
 			return 0;
 		}
@@ -219,7 +220,7 @@
 		printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
 		return -EINVAL;
 	}
-	if (!request_region(io, 4, "rtrack2")) 
+	if (!request_region(io, 4, "rtrack2"))
 	{
 		printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
 		return -EBUSY;
@@ -227,16 +228,16 @@
 
 	rtrack2_radio.priv=&rtrack2_unit;
 
-	spin_lock_init(&lock);	
+	spin_lock_init(&lock);
 	if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io, 4);
 		return -EINVAL;
 	}
-		
+
 	printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n");
 
- 	/* mute card - prevents noisy bootups */
+	/* mute card - prevents noisy bootups */
 	outb(1, io);
 	rtrack2_unit.muted = 1;
 
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 53073b4..efee6e3 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -12,7 +12,7 @@
  *  Frequency control is done digitally -- ie out(port,encodefreq(95.8));
  *  No volume control - only mute/unmute - you have to use line volume
  *  control on SB-part of SF16FMI
- *  
+ *
  */
 
 #include <linux/kernel.h>	/* __setup			*/
@@ -21,6 +21,7 @@
 #include <linux/ioport.h>	/* request_region		*/
 #include <linux/delay.h>	/* udelay			*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/isapnp.h>
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
@@ -29,19 +30,19 @@
 struct fmi_device
 {
 	int port;
-        int curvol; /* 1 or 0 */
-        unsigned long curfreq; /* freq in kHz */
-        __u32 flags;
+	int curvol; /* 1 or 0 */
+	unsigned long curfreq; /* freq in kHz */
+	__u32 flags;
 };
 
-static int io = -1; 
+static int io = -1;
 static int radio_nr = -1;
 static struct pnp_dev *dev = NULL;
 static struct mutex lock;
 
 /* freq is in 1/16 kHz to internal number, hw precision is 50 kHz */
 /* It is only useful to give freq in intervall of 800 (=0.05Mhz),
- * other bits will be truncated, e.g 92.7400016 -> 92.7, but 
+ * other bits will be truncated, e.g 92.7400016 -> 92.7, but
  * 92.7400017 -> 92.75
  */
 #define RSF16_ENCODE(x)	((x)/800+214)
@@ -51,7 +52,7 @@
 static void outbits(int bits, unsigned int data, int port)
 {
 	while(bits--) {
- 		if(data & 1) {
+		if(data & 1) {
 			outb(5, port);
 			udelay(6);
 			outb(7, port);
@@ -101,7 +102,7 @@
 	int res;
 	int myport = dev->port;
 
-	
+
 	mutex_lock(&lock);
 	val = dev->curvol ? 0x08 : 0x00;	/* unmute/mute */
 	outb(val, myport);
@@ -109,7 +110,7 @@
 	msleep(143); 		/* was schedule_timeout(HZ/7) */
 	res = (int)inb(myport+1);
 	outb(val, myport);
-	
+
 	mutex_unlock(&lock);
 	return (res & 2) ? 0 : 0xFFFF;
 }
@@ -119,7 +120,7 @@
 {
 	struct video_device *dev = video_devdata(file);
 	struct fmi_device *fmi=dev->priv;
-	
+
 	switch(cmd)
 	{
 		case VIDIOCGCAP:
@@ -174,18 +175,18 @@
 				return -EINVAL;
 			/*rounding in steps of 800 to match th freq
 			  that will be used */
-			fmi->curfreq = (*freq/800)*800; 
+			fmi->curfreq = (*freq/800)*800;
 			fmi_setfreq(fmi);
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0,sizeof(*v));
 			v->flags=( (!fmi->curvol)*VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE);
 			strcpy(v->name, "Radio");
 			v->mode=VIDEO_SOUND_STEREO;
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
@@ -193,19 +194,19 @@
 			if(v->audio)
 				return -EINVAL;
 			fmi->curvol= v->flags&VIDEO_AUDIO_MUTE ? 0 : 1;
-			fmi->curvol ? 
+			fmi->curvol ?
 				fmi_unmute(fmi->port) : fmi_mute(fmi->port);
 			return 0;
 		}
-	        case VIDIOCGUNIT:
+		case VIDIOCGUNIT:
 		{
-               		struct video_unit *v = arg;
+			struct video_unit *v = arg;
 			v->video=VIDEO_NO_UNIT;
 			v->vbi=VIDEO_NO_UNIT;
 			v->radio=dev->minor;
 			v->audio=0; /* How do we find out this??? */
 			v->teletext=VIDEO_NO_UNIT;
-			return 0;			
+			return 0;
 		}
 		default:
 			return -ENOIOCTLCMD;
@@ -295,14 +296,14 @@
 	fmi_unit.curfreq = 0;
 	fmi_unit.flags = VIDEO_TUNER_LOW;
 	fmi_radio.priv = &fmi_unit;
-	
+
 	mutex_init(&lock);
-	
+
 	if (video_register_device(&fmi_radio, VFL_TYPE_RADIO, radio_nr) == -1) {
 		release_region(io, 2);
 		return -EINVAL;
 	}
-		
+
 	printk(KERN_INFO "SF16FMx radio card driver at 0x%x\n", io);
 	/* mute card - prevents noisy bootups */
 	fmi_mute(io);
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index bcebd8c..3483b2c 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -19,6 +19,7 @@
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 static struct mutex lock;
@@ -202,7 +203,7 @@
 }
 
 static int fmr2_do_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, void *arg)
+		      unsigned int cmd, void *arg)
 {
 	struct video_device *dev = video_devdata(file);
 	struct fmr2_device *fmr2 = dev->priv;
@@ -344,7 +345,7 @@
 }
 
 static int fmr2_ioctl(struct inode *inode, struct file *file,
-                      unsigned int cmd, unsigned long arg)
+		      unsigned int cmd, unsigned long arg)
  {
 	return video_usercopy(inode, file, cmd, arg, fmr2_do_ioctl);
 }
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c
index fcfde2e..dfba4ae 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -2,11 +2,11 @@
  * (c) 1999 R. Offermanns (rolf@offermanns.de)
  * based on the aimslab radio driver from M. Kirkwood
  * many thanks to Michael Becker and Friedhelm Birth (from TerraTec)
- * 
+ *
  *
  * History:
  * 1999-05-21	First preview release
- * 
+ *
  *  Notes on the hardware:
  *  There are two "main" chips on the card:
  *  - Philips OM5610 (http://www-us.semiconductors.philips.com/acrobat/datasheets/OM5610_2.pdf)
@@ -20,7 +20,7 @@
  *  (as soon i have understand how to get started :)
  *  If you can help me out with that, please contact me!!
  *
- *  
+ *
  */
 
 #include <linux/module.h>	/* Modules 			*/
@@ -30,6 +30,7 @@
 #include <asm/io.h>		/* outb, outb_p			*/
 #include <asm/uaccess.h>	/* copy to/from user		*/
 #include <linux/videodev.h>	/* kernel radio structs		*/
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_TERRATEC_PORT 	*/
 #include <linux/spinlock.h>
 
@@ -49,7 +50,7 @@
 #define WRT_EN		0x10
 /*******************************************************************/
 
-static int io = CONFIG_RADIO_TERRATEC_PORT; 
+static int io = CONFIG_RADIO_TERRATEC_PORT;
 static int radio_nr = -1;
 static spinlock_t lock;
 
@@ -88,15 +89,15 @@
 
 static int tt_setvol(struct tt_device *dev, int vol)
 {
-	
+
 //	printk(KERN_ERR "setvol called, vol = %d\n", vol);
 
 	if(vol == dev->curvol) {	/* requested volume = current */
 		if (dev->muted) {	/* user is unmuting the card  */
 			dev->muted = 0;
 			cardWriteVol(vol);	/* enable card */
-		}	
-	
+		}
+
 		return 0;
 	}
 
@@ -107,9 +108,9 @@
 	}
 
 	dev->muted = 0;
-	
+
 	cardWriteVol(vol);
-	 
+
 	dev->curvol = vol;
 
 	return 0;
@@ -121,13 +122,13 @@
 /* many more or less strange things are going on here, but hey, it works :) */
 
 static int tt_setfreq(struct tt_device *dev, unsigned long freq1)
-{	
+{
 	int freq;
 	int i;
 	int p;
 	int  temp;
 	long rest;
-     
+
 	unsigned char buffer[25];		/* we have to bit shift 25 registers */
 	freq = freq1/160;			/* convert the freq. to a nice to handle value */
 	for(i=24;i>-1;i--)
@@ -142,9 +143,9 @@
 	{
 		if (rest%temp  == rest)
 			buffer[i] = 0;
-		else 
+		else
 		{
-			buffer[i] = 1; 
+			buffer[i] = 1;
 			rest = rest-temp;
 		}
 		i--;
@@ -153,10 +154,10 @@
        }
 
 	spin_lock(&lock);
-	
+
 	for (i=24;i>-1;i--)			/* bit shift the values to the radiocard */
 	{
-		if (buffer[i]==1) 
+		if (buffer[i]==1)
 		{
 			outb(WRT_EN|DATA, BASEPORT);
 			outb(WRT_EN|DATA|CLK_ON  , BASEPORT);
@@ -168,11 +169,11 @@
 			outb(WRT_EN|0x00|CLK_ON  , BASEPORT);
 		}
 	}
-	outb(0x00, BASEPORT);     
-	
+	outb(0x00, BASEPORT);
+
 	spin_unlock(&lock);
-  
-  	return 0;
+
+	return 0;
 }
 
 static int tt_getsigstr(struct tt_device *dev)		/* TODO */
@@ -190,7 +191,7 @@
 {
 	struct video_device *dev = video_devdata(file);
 	struct tt_device *tt=dev->priv;
-	
+
 	switch(cmd)
 	{
 		case VIDIOCGCAP:
@@ -206,7 +207,7 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner *v = arg;
-			if(v->tuner)	/* Only 1 tuner */ 
+			if(v->tuner)	/* Only 1 tuner */
 				return -EINVAL;
 			v->rangelow=(87*16000);
 			v->rangehigh=(108*16000);
@@ -238,21 +239,21 @@
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 			memset(v,0, sizeof(*v));
 			v->flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
 			v->volume=tt->curvol * 6554;
 			v->step=6554;
 			strcpy(v->name, "Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
-			if(v->flags&VIDEO_AUDIO_MUTE) 
+			if(v->flags&VIDEO_AUDIO_MUTE)
 				tt_mute(tt);
 			else
 				tt_setvol(tt,v->volume/6554);
@@ -296,25 +297,25 @@
 		printk(KERN_ERR "You must set an I/O address with io=0x???\n");
 		return -EINVAL;
 	}
-	if (!request_region(io, 2, "terratec")) 
+	if (!request_region(io, 2, "terratec"))
 	{
 		printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io);
 		return -EBUSY;
 	}
 
 	terratec_radio.priv=&terratec_unit;
-	
+
 	spin_lock_init(&lock);
-	
+
 	if(video_register_device(&terratec_radio, VFL_TYPE_RADIO, radio_nr)==-1)
 	{
 		release_region(io,2);
 		return -EINVAL;
 	}
-		
+
 	printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n");
 
- 	/* mute card - prevents noisy bootups */
+	/* mute card - prevents noisy bootups */
 
 	/* this ensures that the volume is all the way down  */
 	cardWriteVol(0);
@@ -334,7 +335,7 @@
 {
 	video_unregister_device(&terratec_radio);
 	release_region(io,2);
-	printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n");	
+	printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n");
 }
 
 module_init(terratec_init);
diff --git a/drivers/media/radio/radio-trust.c b/drivers/media/radio/radio-trust.c
index 5a099a5..8da4bad 100644
--- a/drivers/media/radio/radio-trust.c
+++ b/drivers/media/radio/radio-trust.c
@@ -1,14 +1,14 @@
-/* radio-trust.c - Trust FM Radio card driver for Linux 2.2 
+/* radio-trust.c - Trust FM Radio card driver for Linux 2.2
  * by Eric Lammerts <eric@scintilla.utwente.nl>
  *
  * Based on radio-aztech.c. Original notes:
  *
- * Adapted to support the Video for Linux API by 
+ * Adapted to support the Video for Linux API by
  * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
  * Quay Ly
  * Donald Song
- * Jason Lewis      (jlewis@twilight.vtc.vsc.edu) 
+ * Jason Lewis      (jlewis@twilight.vtc.vsc.edu)
  * Scott McGrath    (smcgrath@twilight.vtc.vsc.edu)
  * William McGrath  (wmcgrath@twilight.vtc.vsc.edu)
  *
@@ -22,6 +22,7 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_TRUST_PORT 	*/
 
 /* acceptable ports: 0x350 (JP3 shorted), 0x358 (JP3 open) */
@@ -30,7 +31,7 @@
 #define CONFIG_RADIO_TRUST_PORT -1
 #endif
 
-static int io = CONFIG_RADIO_TRUST_PORT; 
+static int io = CONFIG_RADIO_TRUST_PORT;
 static int radio_nr = -1;
 static int ioval = 0xf;
 static __u16 curvol;
@@ -135,7 +136,7 @@
 static int tr_getsigstr(void)
 {
 	int i, v;
-	
+
 	for(i = 0, v = 0; i < 100; i++) v |= inb(io);
 	return (v & 1)? 0 : 0xffff;
 }
@@ -175,7 +176,7 @@
 		{
 			struct video_tuner *v = arg;
 
-			if(v->tuner)	/* Only 1 tuner */ 
+			if(v->tuner)	/* Only 1 tuner */
 				return -EINVAL;
 
 			v->rangelow = 87500 * 16;
@@ -211,28 +212,28 @@
 			return 0;
 		}
 		case VIDIOCGAUDIO:
-		{	
+		{
 			struct video_audio *v = arg;
 
 			memset(v,0, sizeof(*v));
 			v->flags = VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME |
-			          VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE;
+				  VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE;
 			v->mode = curstereo? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
 			v->volume = curvol * 2048;
 			v->step = 2048;
 			v->bass = curbass * 4370;
 			v->treble = curtreble * 4370;
-			
+
 			strcpy(v->name, "Trust FM Radio");
-			return 0;			
+			return 0;
 		}
 		case VIDIOCSAUDIO:
 		{
 			struct video_audio *v = arg;
 
-			if(v->audio) 
+			if(v->audio)
 				return -EINVAL;
-			tr_setvol(v->volume);					
+			tr_setvol(v->volume);
 			tr_setbass(v->bass);
 			tr_settreble(v->treble);
 			tr_setstereo(v->mode & VIDEO_SOUND_STEREO);
@@ -292,7 +293,7 @@
 	write_i2c(2, TDA7318_ADDR, 0xe0);	/* speaker att. RR = 0 dB */
 	write_i2c(2, TDA7318_ADDR, 0x40);	/* stereo 1 input, gain = 18.75 dB */
 
-	tr_setvol(0x8000);					
+	tr_setvol(0x8000);
 	tr_setbass(0x8000);
 	tr_settreble(0x8000);
 	tr_setstereo(1);
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c
index e509558..edd0122 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -36,6 +36,7 @@
 #include <asm/io.h>		/* outb, outb_p                   */
 #include <asm/uaccess.h>	/* copy to/from user              */
 #include <linux/videodev.h>	/* kernel radio structs           */
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_TYPHOON_*         */
 
 #define BANNER "Typhoon Radio Card driver v0.1\n"
@@ -361,8 +362,8 @@
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
 	if (!create_proc_info_entry("driver/radio-typhoon", 0, NULL,
-				    typhoon_get_info)) 
-	    	printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
+				    typhoon_get_info))
+		printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
 #endif
 
 	return 0;
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c
index 7bf1a42..59b86a6 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -1,7 +1,7 @@
 /* zoltrix radio plus driver for Linux radio support
  * (c) 1998 C. van Schaik <carl@leg.uct.ac.za>
  *
- * BUGS  
+ * BUGS
  *  Due to the inconsistency in reading from the signal flags
  *  it is difficult to get an accurate tuned signal.
  *
@@ -14,7 +14,7 @@
  *
  * 1999-05-06 - (C. van Schaik)
  *	      - Make signal strength and stereo scans
- *	        kinder to cpu while in delay
+ *		kinder to cpu while in delay
  * 1999-01-05 - (C. van Schaik)
  *	      - Changed tuning to 1/160Mhz accuracy
  *	      - Added stereo support
@@ -33,6 +33,7 @@
 #include <asm/io.h>		/* outb, outb_p                   */
 #include <asm/uaccess.h>	/* copy to/from user              */
 #include <linux/videodev.h>	/* kernel radio structs           */
+#include <media/v4l2-common.h>
 #include <linux/config.h>	/* CONFIG_RADIO_ZOLTRIX_PORT      */
 
 #ifndef CONFIG_RADIO_ZOLTRIX_PORT
@@ -105,7 +106,7 @@
 	i = 45;
 
 	mutex_lock(&dev->lock);
-	
+
 	outb(0, io);
 	outb(0, io);
 	inb(io + 3);            /* Zoltrix needs to be read to confirm */
@@ -139,8 +140,8 @@
 	udelay(1000);
 	inb(io+2);
 
-        udelay(1000);
-        
+	udelay(1000);
+
 	if (dev->muted)
 	{
 		outb(0, io);
@@ -148,12 +149,12 @@
 		inb(io + 3);
 		udelay(1000);
 	}
-	
+
 	mutex_unlock(&dev->lock);
-	
+
 	if(!dev->muted)
 	{
-	        zol_setvol(dev, dev->curvol);
+		zol_setvol(dev, dev->curvol);
 	}
 	return 0;
 }
@@ -174,14 +175,14 @@
 	b = inb(io);
 
 	mutex_unlock(&dev->lock);
-	
+
 	if (a != b)
 		return (0);
 
-        if ((a == 0xcf) || (a == 0xdf)  /* I found this out by playing */
+	if ((a == 0xcf) || (a == 0xdf)  /* I found this out by playing */
 		|| (a == 0xef))       /* with a binary scanner on the card io */
 		return (1);
- 	return (0);
+	return (0);
 }
 
 static int zol_is_stereo (struct zol_device *dev)
@@ -189,7 +190,7 @@
 	int x1, x2;
 
 	mutex_lock(&dev->lock);
-	
+
 	outb(0x00, io);
 	outb(dev->curvol, io);
 	msleep(20);
@@ -199,7 +200,7 @@
 	x2 = inb(io);
 
 	mutex_unlock(&dev->lock);
-	
+
 	if ((x1 == x2) && (x1 == 0xcf))
 		return 1;
 	return 0;
@@ -226,7 +227,7 @@
 	case VIDIOCGTUNER:
 		{
 			struct video_tuner *v = arg;
-			if (v->tuner)	
+			if (v->tuner)
 				return -EINVAL;
 			strcpy(v->name, "FM");
 			v->rangelow = (int) (88.0 * 16000);
@@ -351,7 +352,7 @@
 	printk(KERN_INFO "Zoltrix Radio Plus card driver.\n");
 
 	mutex_init(&zoltrix_unit.lock);
-	
+
 	/* mute card - prevents noisy bootups */
 
 	/* this ensures that the volume is all the way down  */
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 6b41970..6d532f1 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -224,6 +224,12 @@
 	  support for the Linux Media Labs LML33R10 MJPEG capture/playback
 	  card.
 
+config VIDEO_ZORAN_AVS6EYES
+	tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
+	depends on VIDEO_ZORAN && EXPERIMENTAL && VIDEO_V4L1
+	help
+	  Support for the AverMedia 6 Eyes video surveillance card.
+
 config VIDEO_ZR36120
 	tristate "Zoran ZR36120/36125 Video For Linux"
 	depends on PCI && I2C && VIDEO_V4L1 && BROKEN
@@ -306,17 +312,6 @@
 
 source "drivers/media/video/cx88/Kconfig"
 
-config VIDEO_OVCAMCHIP
-	tristate "OmniVision Camera Chip support"
-	depends on I2C && VIDEO_V4L1
-	---help---
-	  Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
-	  This driver is intended to be used with the ov511 and w9968cf USB
-	  camera drivers.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called ovcamchip.
-
 config VIDEO_M32R_AR
 	tristate "AR devices"
 	depends on M32R && VIDEO_V4L1
@@ -357,6 +352,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cs53l32a.
 
+config VIDEO_TLV320AIC23B
+	tristate "Texas Instruments TLV320AIC23B audio codec"
+	depends on VIDEO_DEV && I2C && EXPERIMENTAL
+	---help---
+	  Support for the Texas Instruments TLV320AIC23B audio codec.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tlv320aic23b.
+
 config VIDEO_WM8775
 	tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
 	depends on VIDEO_DEV && I2C && EXPERIMENTAL
@@ -377,13 +381,25 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called wm8739.
 
+config VIDEO_CX2341X
+	tristate "Conexant CX2341x MPEG encoders"
+	depends on VIDEO_V4L2 && EXPERIMENTAL
+	---help---
+	  Support for the Conexant CX23416 MPEG encoders
+	  and CX23415 MPEG encoder/decoders.
+
+	  This module currently supports the encoding functions only.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx2341x.
+
 source "drivers/media/video/cx25840/Kconfig"
 
 config VIDEO_SAA711X
-	tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)"
-	depends on VIDEO_V4L1 && I2C && EXPERIMENTAL
+	tristate "Philips SAA7113/4/5 video decoders"
+	depends on VIDEO_DEV && I2C && EXPERIMENTAL
 	---help---
-	  Old support for the Philips SAA7113/4 video decoders.
+	  Support for the Philips SAA7113/4/5 video decoders.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called saa7115.
@@ -429,6 +445,8 @@
 menu "V4L USB devices"
 	depends on USB && VIDEO_DEV
 
+source "drivers/media/video/pvrusb2/Kconfig"
+
 source "drivers/media/video/em28xx/Kconfig"
 
 config USB_DSBR
@@ -447,6 +465,35 @@
 
 source "drivers/media/video/et61x251/Kconfig"
 
+config VIDEO_OVCAMCHIP
+	tristate "OmniVision Camera Chip support"
+	depends on I2C && VIDEO_V4L1
+	---help---
+	  Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
+	  This driver is intended to be used with the ov511 and w9968cf USB
+	  camera drivers.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ovcamchip.
+
+config USB_W9968CF
+	tristate "USB W996[87]CF JPEG Dual Mode Camera support"
+	depends on USB && VIDEO_V4L1 && I2C
+	select VIDEO_OVCAMCHIP
+	---help---
+	  Say Y here if you want support for cameras based on OV681 or
+	  Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
+
+	  This driver has an optional plugin, which is distributed as a
+	  separate module only (released under GPL). It allows to use higher
+	  resolutions and framerates, but cannot be included in the official
+	  Linux kernel for performance purposes.
+
+	  See <file:Documentation/video4linux/w9968cf.txt> for more info.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called w9968cf.
+
 config USB_OV511
 	tristate "USB OV511 Camera support"
 	depends on USB && VIDEO_V4L1
@@ -483,24 +530,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called stv680.
 
-config USB_W9968CF
-	tristate "USB W996[87]CF JPEG Dual Mode Camera support"
-	depends on USB && VIDEO_V4L1 && I2C
-	select VIDEO_OVCAMCHIP
-	---help---
-	  Say Y here if you want support for cameras based on OV681 or
-	  Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
-
-	  This driver has an optional plugin, which is distributed as a
-	  separate module only (released under GPL). It allows to use higher
-	  resolutions and framerates, but cannot be included in the official
-	  Linux kernel for performance purposes.
-
-	  See <file:Documentation/video4linux/w9968cf.txt> for more info.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called w9968cf.
-
 source "drivers/media/video/zc0301/Kconfig"
 
 source "drivers/media/video/pwc/Kconfig"
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index e5bf268..353d61c 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -6,7 +6,7 @@
 zr36067-objs	:=	zoran_procfs.o zoran_device.o \
 			zoran_driver.o zoran_card.o
 tuner-objs	:=	tuner-core.o tuner-types.o tuner-simple.o \
-			mt20xx.o tda8290.o tea5767.o
+			mt20xx.o tda8290.o tea5767.o tda9887.o
 
 msp3400-objs	:=	msp3400-driver.o msp3400-kthreads.o
 
@@ -33,6 +33,7 @@
 	zr36016.o
 obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o zr36060.o
 obj-$(CONFIG_VIDEO_ZORAN_LML33R10) += saa7114.o adv7170.o zr36060.o
+obj-$(CONFIG_VIDEO_ZORAN_AVS6EYES) += bt866.o ks0127.o zr36060.o
 obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o videocodec.o
 obj-$(CONFIG_VIDEO_PMS) += pms.o
 obj-$(CONFIG_VIDEO_PLANB) += planb.o
@@ -46,8 +47,10 @@
 obj-$(CONFIG_VIDEO_CX88) += cx88/
 obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
 obj-$(CONFIG_VIDEO_EM28XX) += tvp5150.o
+obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
 obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
 obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
+obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
 obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
 obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
 obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
@@ -58,7 +61,7 @@
 obj-$(CONFIG_VIDEO_DPC) += saa7111.o dpc7146.o
 obj-$(CONFIG_TUNER_3036) += tuner-3036.o
 
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o tda9887.o
+obj-$(CONFIG_VIDEO_TUNER) += tuner.o
 obj-$(CONFIG_VIDEO_BUF)   += video-buf.o
 obj-$(CONFIG_VIDEO_BUF_DVB) += video-buf-dvb.o
 obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
@@ -71,6 +74,7 @@
 obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
 obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
 obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
 
 obj-$(CONFIG_USB_DABUSB)        += dabusb.o
 obj-$(CONFIG_USB_DSBR)          += dsbr100.o
diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c
index dbe0251..6e08e32 100644
--- a/drivers/media/video/arv.c
+++ b/drivers/media/video/arv.c
@@ -31,6 +31,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
@@ -212,7 +213,7 @@
 	ar_outl(0x0300, PLDI2CMOD); 	/* I2CMOD ACK/8b-data/7b-addr/auto */
 	ar_outl(0x1, PLDI2CACK);	/* I2CACK ACK                      */
 
-    	/* I2C CLK */
+	/* I2C CLK */
 	/* 50MH-100k */
 	if (freq == 75) {
 		ar_outl(369, PLDI2CFREQ);	/* BCLK = 75MHz */
diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c
new file mode 100644
index 0000000..05e42bb
--- /dev/null
+++ b/drivers/media/video/bt866.c
@@ -0,0 +1,377 @@
+/*
+    bt866 - BT866 Digital Video Encoder (Rockwell Part)
+
+    Copyright (C) 1999 Mike Bernson <mike@mlb.org>
+    Copyright (C) 1998 Dave Perks <dperks@ibm.net>
+
+    Modifications for LML33/DC10plus unified driver
+    Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx>
+
+    This code was modify/ported from the saa7111 driver written
+    by Dave Perks.
+
+    This code was adapted for the bt866 by Christer Weinigel and ported
+    to 2.6 by Martin Samuelsson.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+#include <linux/videodev.h>
+#include <asm/uaccess.h>
+
+#include <linux/video_encoder.h>
+
+MODULE_LICENSE("GPL");
+
+#define	BT866_DEVNAME	"bt866"
+#define I2C_BT866	0x88
+
+MODULE_LICENSE("GPL");
+
+#define DEBUG(x)		/* Debug driver */
+
+/* ----------------------------------------------------------------------- */
+
+struct bt866 {
+	struct i2c_client *i2c;
+	int addr;
+	unsigned char reg[128];
+
+	int norm;
+	int enable;
+	int bright;
+	int contrast;
+	int hue;
+	int sat;
+};
+
+static int bt866_write(struct bt866 *dev,
+			unsigned char subaddr, unsigned char data);
+
+static int bt866_do_command(struct bt866 *encoder,
+			unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case ENCODER_GET_CAPABILITIES:
+	{
+		struct video_encoder_capability *cap = arg;
+
+		DEBUG(printk
+		      (KERN_INFO "%s: get capabilities\n",
+		       encoder->i2c->name));
+
+		cap->flags
+			= VIDEO_ENCODER_PAL
+			| VIDEO_ENCODER_NTSC
+			| VIDEO_ENCODER_CCIR;
+		cap->inputs = 2;
+		cap->outputs = 1;
+	}
+	break;
+
+	case ENCODER_SET_NORM:
+	{
+		int *iarg = arg;
+
+		DEBUG(printk(KERN_INFO "%s: set norm %d\n",
+			     encoder->i2c->name, *iarg));
+
+		switch (*iarg) {
+
+		case VIDEO_MODE_NTSC:
+			break;
+
+		case VIDEO_MODE_PAL:
+			break;
+
+		default:
+			return -EINVAL;
+
+		}
+		encoder->norm = *iarg;
+	}
+	break;
+
+	case ENCODER_SET_INPUT:
+	{
+		int *iarg = arg;
+		static const __u8 init[] = {
+			0xc8, 0xcc, /* CRSCALE */
+			0xca, 0x91, /* CBSCALE */
+			0xcc, 0x24, /* YC16 | OSDNUM */
+			0xda, 0x00, /*  */
+			0xdc, 0x24, /* SETMODE | PAL */
+			0xde, 0x02, /* EACTIVE */
+
+			/* overlay colors */
+			0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */
+			0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */
+			0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */
+			0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */
+			0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */
+			0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */
+			0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */
+			0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */
+
+			0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */
+			0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */
+			0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */
+			0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */
+			0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */
+			0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */
+			0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */
+			0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */
+		};
+		int i;
+		u8 val;
+
+		for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2)
+			bt866_write(encoder, init[i], init[i+1]);
+
+		val = encoder->reg[0xdc];
+
+		if (*iarg == 0)
+			val |= 0x40; /* CBSWAP */
+		else
+			val &= ~0x40; /* !CBSWAP */
+
+		bt866_write(encoder, 0xdc, val);
+
+		val = encoder->reg[0xcc];
+		if (*iarg == 2)
+			val |= 0x01; /* OSDBAR */
+		else
+			val &= ~0x01; /* !OSDBAR */
+		bt866_write(encoder, 0xcc, val);
+
+		DEBUG(printk(KERN_INFO "%s: set input %d\n",
+			     encoder->i2c->name, *iarg));
+
+		switch (*iarg) {
+		case 0:
+			break;
+		case 1:
+			break;
+		default:
+			return -EINVAL;
+
+		}
+	}
+	break;
+
+	case ENCODER_SET_OUTPUT:
+	{
+		int *iarg = arg;
+
+		DEBUG(printk(KERN_INFO "%s: set output %d\n",
+			     encoder->i2c->name, *iarg));
+
+		/* not much choice of outputs */
+		if (*iarg != 0)
+			return -EINVAL;
+	}
+	break;
+
+	case ENCODER_ENABLE_OUTPUT:
+	{
+		int *iarg = arg;
+		encoder->enable = !!*iarg;
+
+		DEBUG(printk
+		      (KERN_INFO "%s: enable output %d\n",
+		       encoder->i2c->name, encoder->enable));
+	}
+	break;
+
+	case 4711:
+	{
+		int *iarg = arg;
+		__u8 val;
+
+		printk("bt866: square = %d\n", *iarg);
+
+		val = encoder->reg[0xdc];
+		if (*iarg)
+			val |= 1; /* SQUARE */
+		else
+			val &= ~1; /* !SQUARE */
+		bt866_write(encoder, 0xdc, val);
+		break;
+	}
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int bt866_write(struct bt866 *encoder,
+			unsigned char subaddr, unsigned char data)
+{
+	unsigned char buffer[2];
+	int err;
+
+	buffer[0] = subaddr;
+	buffer[1] = data;
+
+	encoder->reg[subaddr] = data;
+
+	DEBUG(printk
+	      ("%s: write 0x%02X = 0x%02X\n",
+	       encoder->i2c->name, subaddr, data));
+
+	for (err = 0; err < 3;) {
+		if (i2c_master_send(encoder->i2c, buffer, 2) == 2)
+			break;
+		err++;
+		printk(KERN_WARNING "%s: I/O error #%d "
+		       "(write 0x%02x/0x%02x)\n",
+		       encoder->i2c->name, err, encoder->addr, subaddr);
+		schedule_timeout_interruptible(HZ/10);
+	}
+	if (err == 3) {
+		printk(KERN_WARNING "%s: giving up\n",
+		       encoder->i2c->name);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int bt866_attach(struct i2c_adapter *adapter);
+static int bt866_detach(struct i2c_client *client);
+static int bt866_command(struct i2c_client *client,
+			 unsigned int cmd, void *arg);
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[]	= {I2C_BT866>>1, I2C_CLIENT_END};
+static unsigned short probe[2]		= {I2C_CLIENT_END, I2C_CLIENT_END};
+static unsigned short ignore[2]		= {I2C_CLIENT_END, I2C_CLIENT_END};
+
+static struct i2c_client_address_data addr_data = {
+	normal_i2c,
+	probe,
+	ignore,
+};
+
+static struct i2c_driver i2c_driver_bt866 = {
+	.driver.name = BT866_DEVNAME,
+	.id = I2C_DRIVERID_BT866,
+	.attach_adapter = bt866_attach,
+	.detach_client = bt866_detach,
+	.command = bt866_command
+};
+
+
+static struct i2c_client bt866_client_tmpl =
+{
+	.name = "(nil)",
+	.addr = 0,
+	.adapter = NULL,
+	.driver = &i2c_driver_bt866,
+	.usage_count = 0
+};
+
+static int bt866_found_proc(struct i2c_adapter *adapter,
+			    int addr, int kind)
+{
+	struct bt866 *encoder;
+	struct i2c_client *client;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (client == NULL)
+		return -ENOMEM;
+	memcpy(client, &bt866_client_tmpl, sizeof(*client));
+
+	encoder = kzalloc(sizeof(*encoder), GFP_KERNEL);
+	if (encoder == NULL) {
+		kfree(client);
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(client, encoder);
+	client->adapter = adapter;
+	client->addr = addr;
+	sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id);
+
+	encoder->i2c = client;
+	encoder->addr = addr;
+	//encoder->encoder_type = ENCODER_TYPE_UNKNOWN;
+
+	/* initialize */
+
+	i2c_attach_client(client);
+
+	return 0;
+}
+
+static int bt866_attach(struct i2c_adapter *adapter)
+{
+	if (adapter->id == I2C_HW_B_ZR36067)
+		return i2c_probe(adapter, &addr_data, bt866_found_proc);
+	return 0;
+}
+
+static int bt866_detach(struct i2c_client *client)
+{
+	struct bt866 *encoder = i2c_get_clientdata(client);
+
+	i2c_detach_client(client);
+	kfree(encoder);
+	kfree(client);
+
+	return 0;
+}
+
+static int bt866_command(struct i2c_client *client,
+			 unsigned int cmd, void *arg)
+{
+	struct bt866 *encoder = i2c_get_clientdata(client);
+	return bt866_do_command(encoder, cmd, arg);
+}
+
+static int __devinit bt866_init(void)
+{
+	i2c_add_driver(&i2c_driver_bt866);
+	return 0;
+}
+
+static void __devexit bt866_exit(void)
+{
+	i2c_del_driver(&i2c_driver_bt866);
+}
+
+module_init(bt866_init);
+module_exit(bt866_exit);
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
index 2b64aa8..e68a6d2 100644
--- a/drivers/media/video/bt8xx/bttv-cards.c
+++ b/drivers/media/video/bt8xx/bttv-cards.c
@@ -269,7 +269,7 @@
 	{ 0x41a0a051, BTTV_BOARD_FLYVIDEO_98FM, "Lifeview FlyVideo 98 LR50 Rev Q" },
 	{ 0x18501f7f, BTTV_BOARD_FLYVIDEO_98,   "Lifeview Flyvideo 98" },
 
-    	{ 0x010115cb, BTTV_BOARD_GMV1,          "AG GMV1" },
+	{ 0x010115cb, BTTV_BOARD_GMV1,          "AG GMV1" },
 	{ 0x010114c7, BTTV_BOARD_MODTEC_205,    "Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV" },
 
 	{ 0x10b42636, BTTV_BOARD_HAUPPAUGE878,  "STB ???" },
@@ -309,6 +309,7 @@
 	{ 0x07611461, BTTV_BOARD_AVDVBT_761,    "AverMedia AverTV DVB-T 761" },
 	{ 0xdb1018ac, BTTV_BOARD_DVICO_DVBT_LITE,    "DViCO FusionHDTV DVB-T Lite" },
 	{ 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE,    "DViCO FusionHDTV 5 Lite" },
+	{ 0x00261822, BTTV_BOARD_TWINHAN_DST,	"DNTV Live! Mini "},
 
 	{ 0, -1, NULL }
 };
@@ -1903,7 +1904,7 @@
 		.no_tda7432     = 1,
 	},
 	[BTTV_BOARD_OSPREY2x0] = {
-		.name           = "Osprey 210/220",   /* 0x1(A|B)-04C0-C1 */
+		.name           = "Osprey 210/220/230",   /* 0x1(A|B)-04C0-C1 */
 		.video_inputs   = 2,
 		.audio_inputs   = 1,
 		.tuner          = -1,
@@ -2745,7 +2746,7 @@
 		/* Michael Krufky <mkrufky@m1k.net> */
 		.name           = "DViCO FusionHDTV 5 Lite",
 		.tuner          = 0,
-		.tuner_type     = TUNER_LG_TDVS_H062F,
+		.tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr     = ADDR_UNSET,
 		.video_inputs   = 3,
@@ -2762,7 +2763,7 @@
 	},
 		/* ---- card 0x88---------------------------------- */
 	[BTTV_BOARD_ACORP_Y878F] = {
-		/* Mauro Carvalho Chehab <mchehab@brturbo.com.br> */
+		/* Mauro Carvalho Chehab <mchehab@infradead.org> */
 		.name		= "Acorp Y878F",
 		.video_inputs	= 3,
 		.audio_inputs	= 1,
@@ -3790,6 +3791,7 @@
 		       break;
 	       case 0x0060:
 	       case 0x0070:
+	       case 0x00A0:
 		       btv->c.type = BTTV_BOARD_OSPREY2x0;
 		       /* enable output on select control lines */
 		       gpio_inout(0xffffff,0x000303);
@@ -4846,7 +4848,7 @@
  *
  * The IVC120G security card has 4 i2c controlled TDA8540 matrix
  * swichers to provide 16 channels to MUX0. The TDA8540's have
- * 4 indepedant outputs and as such the IVC120G also has the
+ * 4 independent outputs and as such the IVC120G also has the
  * optional "Monitor Out" bus. This allows the card to be looking
  * at one input while the monitor is looking at another.
  *
diff --git a/drivers/media/video/bt8xx/bttv-gpio.c b/drivers/media/video/bt8xx/bttv-gpio.c
index c4d5e2b..ba081f6 100644
--- a/drivers/media/video/bt8xx/bttv-gpio.c
+++ b/drivers/media/video/bt8xx/bttv-gpio.c
@@ -118,20 +118,6 @@
 	return 0;
 }
 
-void bttv_gpio_irq(struct bttv_core *core)
-{
-	struct bttv_sub_driver *drv;
-	struct bttv_sub_device *dev;
-	struct list_head *item;
-
-	list_for_each(item,&core->subs) {
-		dev = list_entry(item,struct bttv_sub_device,list);
-		drv = to_bttv_sub_drv(dev->dev.driver);
-		if (drv && drv->gpio_irq)
-			drv->gpio_irq(dev);
-	}
-}
-
 /* ----------------------------------------------------------------------- */
 /* external: sub-driver register/unregister                                */
 
diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c
index 69efa0e..b41f81d 100644
--- a/drivers/media/video/bt8xx/bttv-input.c
+++ b/drivers/media/video/bt8xx/bttv-input.c
@@ -355,7 +355,7 @@
 
 	if (ir->rc5_gpio) {
 		u32 gpio;
-	    	/* enable remote irq */
+		/* enable remote irq */
 		bttv_gpio_inout(&btv->c, (1 << 4), 1 << 4);
 		gpio = bttv_gpio_read(&btv->c);
 		bttv_gpio_write(&btv->c, gpio & ~(1 << 4));
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h
index 3a23265..f9c9e3c 100644
--- a/drivers/media/video/bt8xx/bttv.h
+++ b/drivers/media/video/bt8xx/bttv.h
@@ -350,7 +350,6 @@
 	char                   wanted[BUS_ID_SIZE];
 	int                    (*probe)(struct bttv_sub_device *sub);
 	void                   (*remove)(struct bttv_sub_device *sub);
-	void                   (*gpio_irq)(struct bttv_sub_device *sub);
 };
 #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv)
 
diff --git a/drivers/media/video/bt8xx/bttvp.h b/drivers/media/video/bt8xx/bttvp.h
index ee989d2..d295601 100644
--- a/drivers/media/video/bt8xx/bttvp.h
+++ b/drivers/media/video/bt8xx/bttvp.h
@@ -33,6 +33,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/pci.h>
 #include <linux/input.h>
 #include <linux/mutex.h>
@@ -214,7 +215,6 @@
 extern struct bus_type bttv_sub_bus_type;
 int bttv_sub_add_device(struct bttv_core *core, char *name);
 int bttv_sub_del_devices(struct bttv_core *core);
-void bttv_gpio_irq(struct bttv_core *core);
 
 
 /* ---------------------------------------------------------- */
diff --git a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c
index cf61c59..7d0b6e5 100644
--- a/drivers/media/video/bw-qcam.c
+++ b/drivers/media/video/bw-qcam.c
@@ -73,6 +73,7 @@
 #include <linux/parport.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 
@@ -759,7 +760,7 @@
 		{
 			struct video_picture *p = arg;
 			if(p->palette!=VIDEO_PALETTE_GREY)
-			    	return -EINVAL;
+				return -EINVAL;
 			if(p->depth!=4 && p->depth!=6)
 				return -EINVAL;
 
diff --git a/drivers/media/video/c-qcam.c b/drivers/media/video/c-qcam.c
index 22a7386..a3989bd 100644
--- a/drivers/media/video/c-qcam.c
+++ b/drivers/media/video/c-qcam.c
@@ -34,6 +34,7 @@
 #include <linux/parport.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 85d84e8..95c5acee 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -47,13 +47,6 @@
 
 #include "cpia.h"
 
-#ifdef CONFIG_VIDEO_CPIA_PP
-extern int cpia_pp_init(void);
-#endif
-#ifdef CONFIG_VIDEO_CPIA_USB
-extern int cpia_usb_init(void);
-#endif
-
 static int video_nr = -1;
 
 #ifdef MODULE
@@ -67,10 +60,10 @@
 static unsigned short colorspace_conv;
 module_param(colorspace_conv, ushort, 0444);
 MODULE_PARM_DESC(colorspace_conv,
-                 " Colorspace conversion:"
-                 "\n  0 = disable, 1 = enable"
-                 "\n  Default value is 0"
-                 );
+		 " Colorspace conversion:"
+		 "\n  0 = disable, 1 = enable"
+		 "\n  Default value is 0"
+		 );
 
 #define ABOUT "V4L-Driver for Vision CPiA based cameras"
 
@@ -4047,13 +4040,6 @@
 	proc_cpia_create();
 #endif
 
-#ifdef CONFIG_VIDEO_CPIA_PP
-	cpia_pp_init();
-#endif
-#ifdef CONFIG_VIDEO_CPIA_USB
-	cpia_usb_init();
-#endif
-
 	return 0;
 }
 
diff --git a/drivers/media/video/cpia.h b/drivers/media/video/cpia.h
index dde27a6..6eaa692 100644
--- a/drivers/media/video/cpia.h
+++ b/drivers/media/video/cpia.h
@@ -45,6 +45,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/list.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
@@ -247,7 +248,7 @@
 struct cam_data {
 	struct list_head cam_data_list;
 
-	struct mutex busy_lock;     /* guard against SMP multithreading */
+	struct mutex busy_lock;		/* guard against SMP multithreading */
 	struct cpia_camera_ops *ops;	/* lowlevel driver operations */
 	void *lowlevel_data;		/* private data for lowlevel driver */
 	u8 *raw_image;			/* buffer for raw image data */
diff --git a/drivers/media/video/cpia2/cpia2.h b/drivers/media/video/cpia2/cpia2.h
index 1764991..c5ecb2b 100644
--- a/drivers/media/video/cpia2/cpia2.h
+++ b/drivers/media/video/cpia2/cpia2.h
@@ -33,6 +33,7 @@
 
 #include <linux/version.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/poll.h>
 
diff --git a/drivers/media/video/cpia2/cpia2_v4l.c b/drivers/media/video/cpia2/cpia2_v4l.c
index 481e178..d129db5 100644
--- a/drivers/media/video/cpia2/cpia2_v4l.c
+++ b/drivers/media/video/cpia2/cpia2_v4l.c
@@ -343,7 +343,9 @@
 		cpia2_free_buffers(cam);
 		if (!cam->present) {
 			video_unregister_device(dev);
+			mutex_unlock(&cam->busy_lock);
 			kfree(cam);
+			return 0;
 		}
 	}
 
@@ -1167,9 +1169,9 @@
 		} else {
 		    if(cam->params.flicker_control.cam_register &
 		       CPIA2_VP_FLICKER_MODES_50HZ) {
-		    	mode = FLICKER_50;
+			mode = FLICKER_50;
 		    } else {
-		    	mode = FLICKER_60;
+			mode = FLICKER_60;
 		    }
 		}
 		for(i=0; i<NUM_FLICKER_CONTROLS; i++) {
diff --git a/drivers/media/video/cpia_pp.c b/drivers/media/video/cpia_pp.c
index 0b00e60..4c89bd3 100644
--- a/drivers/media/video/cpia_pp.c
+++ b/drivers/media/video/cpia_pp.c
@@ -803,7 +803,7 @@
 	.detach = cpia_pp_detach,
 };
 
-int cpia_pp_init(void)
+static int cpia_pp_init(void)
 {
 	printk(KERN_INFO "%s v%d.%d.%d\n",ABOUT,
 	       CPIA_PP_MAJ_VER,CPIA_PP_MIN_VER,CPIA_PP_PATCH_VER);
@@ -860,6 +860,8 @@
 
 static int __init cpia_pp_setup(char *str)
 {
+	int err;
+
 	if (!strncmp(str, "parport", 7)) {
 		int n = simple_strtoul(str + 7, NULL, 10);
 		if (parport_ptr < PARPORT_MAX) {
@@ -873,6 +875,10 @@
 		parport_nr[parport_ptr++] = PPCPIA_PARPORT_NONE;
 	}
 
+	err=cpia_pp_init();
+	if (err)
+		return err;
+
 	return 1;
 }
 
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 9c49a4b..2ee34a3 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -474,12 +474,6 @@
 	return 0;
 }
 
-int cpia_usb_init(void)
-{
-	/* return -ENODEV; */
-	return 0;
-}
-
 /* Probing and initializing */
 
 static int cpia_probe(struct usb_interface *intf,
diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c
new file mode 100644
index 0000000..65f00fc
--- /dev/null
+++ b/drivers/media/video/cx2341x.c
@@ -0,0 +1,932 @@
+/*
+ * cx2341x - generic code for cx23415/6 based devices
+ *
+ * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+
+#include <media/tuner.h>
+#include <media/cx2341x.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("cx23415/6 driver");
+MODULE_AUTHOR("Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+const u32 cx2341x_mpeg_ctrls[] = {
+	V4L2_CID_MPEG_CLASS,
+	V4L2_CID_MPEG_STREAM_TYPE,
+	V4L2_CID_MPEG_STREAM_VBI_FMT,
+	V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+	V4L2_CID_MPEG_AUDIO_ENCODING,
+	V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+	V4L2_CID_MPEG_AUDIO_MODE,
+	V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+	V4L2_CID_MPEG_AUDIO_EMPHASIS,
+	V4L2_CID_MPEG_AUDIO_CRC,
+	V4L2_CID_MPEG_VIDEO_ENCODING,
+	V4L2_CID_MPEG_VIDEO_ASPECT,
+	V4L2_CID_MPEG_VIDEO_B_FRAMES,
+	V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+	V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+	V4L2_CID_MPEG_VIDEO_PULLDOWN,
+	V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+	V4L2_CID_MPEG_VIDEO_BITRATE,
+	V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+	V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+	V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+	V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+	V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+	V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+	V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+	V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+	V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+	0
+};
+
+
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params,
+		struct v4l2_ext_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		ctrl->value = params->audio_sampling_freq;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		ctrl->value = params->audio_encoding;
+		break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		ctrl->value = params->audio_l2_bitrate;
+		break;
+	case V4L2_CID_MPEG_AUDIO_MODE:
+		ctrl->value = params->audio_mode;
+		break;
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+		ctrl->value = params->audio_mode_extension;
+		break;
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+		ctrl->value = params->audio_emphasis;
+		break;
+	case V4L2_CID_MPEG_AUDIO_CRC:
+		ctrl->value = params->audio_crc;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		ctrl->value = params->video_encoding;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		ctrl->value = params->video_aspect;
+		break;
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+		ctrl->value = params->video_b_frames;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		ctrl->value = params->video_gop_size;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		ctrl->value = params->video_gop_closure;
+		break;
+	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+		ctrl->value = params->video_pulldown;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		ctrl->value = params->video_bitrate_mode;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		ctrl->value = params->video_bitrate;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		ctrl->value = params->video_bitrate_peak;
+		break;
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+		ctrl->value = params->video_temporal_decimation;
+		break;
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		ctrl->value = params->stream_type;
+		break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		ctrl->value = params->stream_vbi_fmt;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		ctrl->value = params->video_spatial_filter_mode;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		ctrl->value = params->video_spatial_filter;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		ctrl->value = params->video_luma_spatial_filter_type;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		ctrl->value = params->video_chroma_spatial_filter_type;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		ctrl->value = params->video_temporal_filter_mode;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		ctrl->value = params->video_temporal_filter;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		ctrl->value = params->video_median_filter_type;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		ctrl->value = params->video_luma_median_filter_top;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		ctrl->value = params->video_luma_median_filter_bottom;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		ctrl->value = params->video_chroma_median_filter_top;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		ctrl->value = params->video_chroma_median_filter_bottom;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Map the control ID to the correct field in the cx2341x_mpeg_params
+   struct. Return -EINVAL if the ID is unknown, else return 0. */
+static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params,
+		struct v4l2_ext_control *ctrl)
+{
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		params->audio_sampling_freq = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		params->audio_encoding = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		params->audio_l2_bitrate = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_MODE:
+		params->audio_mode = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+		params->audio_mode_extension = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+		params->audio_emphasis = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_AUDIO_CRC:
+		params->audio_crc = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		params->video_aspect = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES: {
+		int b = ctrl->value + 1;
+		int gop = params->video_gop_size;
+		params->video_b_frames = ctrl->value;
+		params->video_gop_size = b * ((gop + b - 1) / b);
+		/* Max GOP size = 34 */
+		while (params->video_gop_size > 34)
+			params->video_gop_size -= b;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE: {
+		int b = params->video_b_frames + 1;
+		int gop = ctrl->value;
+		params->video_gop_size = b * ((gop + b - 1) / b);
+		/* Max GOP size = 34 */
+		while (params->video_gop_size > 34)
+			params->video_gop_size -= b;
+		ctrl->value = params->video_gop_size;
+		break;
+	}
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		params->video_gop_closure = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+		params->video_pulldown = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		/* MPEG-1 only allows CBR */
+		if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 &&
+		    ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+			return -EINVAL;
+		params->video_bitrate_mode = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		params->video_bitrate = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		params->video_bitrate_peak = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+		params->video_temporal_decimation = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		params->stream_type = ctrl->value;
+		params->video_encoding =
+			(params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS ||
+			 params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ?
+			V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+		if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+			/* MPEG-1 implies CBR */
+			params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+		}
+		break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		params->stream_vbi_fmt = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		params->video_spatial_filter_mode = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		params->video_spatial_filter = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		params->video_luma_spatial_filter_type = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		params->video_chroma_spatial_filter_type = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		params->video_temporal_filter_mode = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		params->video_temporal_filter = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		params->video_median_filter_type = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		params->video_luma_median_filter_top = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		params->video_luma_median_filter_bottom = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		params->video_chroma_median_filter_top = ctrl->value;
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		params->video_chroma_median_filter_bottom = ctrl->value;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+{
+	const char *name;
+
+	qctrl->flags = 0;
+	switch (qctrl->id) {
+	/* MPEG controls */
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		name = "Spatial Filter Mode";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		name = "Spatial Filter";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		name = "Spatial Luma Filter Type";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		name = "Spatial Chroma Filter Type";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		name = "Temporal Filter Mode";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		name = "Temporal Filter";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		name = "Median Filter Type";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		name = "Median Luma Filter Maximum";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		name = "Median Luma Filter Minimum";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		name = "Median Chroma Filter Maximum";
+		break;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		name = "Median Chroma Filter Minimum";
+		break;
+
+	default:
+		return v4l2_ctrl_query_fill(qctrl, min, max, step, def);
+	}
+	switch (qctrl->id) {
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		qctrl->type = V4L2_CTRL_TYPE_MENU;
+		min = 0;
+		step = 1;
+		break;
+	default:
+		qctrl->type = V4L2_CTRL_TYPE_INTEGER;
+		break;
+	}
+	switch (qctrl->id) {
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
+		break;
+	}
+	qctrl->minimum = min;
+	qctrl->maximum = max;
+	qctrl->step = step;
+	qctrl->default_value = def;
+	qctrl->reserved[0] = qctrl->reserved[1] = 0;
+	snprintf(qctrl->name, sizeof(qctrl->name), name);
+	return 0;
+}
+
+int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl)
+{
+	int err;
+
+	switch (qctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_L2_BITRATE_192K,
+				V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+				V4L2_MPEG_AUDIO_L2_BITRATE_224K);
+
+	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+		return -EINVAL;
+
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+		err = v4l2_ctrl_query_fill_std(qctrl);
+		if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return err;
+
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		/* this setting is read-only for the cx2341x since the
+		   V4L2_CID_MPEG_STREAM_TYPE really determines the
+		   MPEG-1/2 setting */
+		err = v4l2_ctrl_query_fill_std(qctrl);
+		if (err == 0)
+			qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+		return err;
+
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		err = v4l2_ctrl_query_fill_std(qctrl);
+		if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return err;
+
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		err = v4l2_ctrl_query_fill_std(qctrl);
+		if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR)
+			qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return err;
+
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI)
+			return v4l2_ctrl_query_fill_std(qctrl);
+		return cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE, 1,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE);
+
+	/* CX23415/6 specific */
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		return cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+				V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1,
+				V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER:
+		cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF,
+				V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1,
+				V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF);
+		if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF,
+				V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1,
+				V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF);
+		if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		return cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+				V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1,
+				V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER:
+		cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		return cx2341x_ctrl_query_fill(qctrl,
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1,
+				V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF);
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM:
+		cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF)
+		       qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE;
+		return 0;
+
+	default:
+		return v4l2_ctrl_query_fill_std(qctrl);
+
+	}
+}
+
+const char **cx2341x_ctrl_get_menu(u32 id)
+{
+	static const char *mpeg_stream_type[] = {
+		"MPEG-2 Program Stream",
+		"",
+		"MPEG-1 System Stream",
+		"MPEG-2 DVD-compatible Stream",
+		"MPEG-1 VCD-compatible Stream",
+		"MPEG-2 SVCD-compatible Stream",
+		NULL
+	};
+
+	static const char *cx2341x_video_spatial_filter_mode_menu[] = {
+		"Manual",
+		"Auto",
+		NULL
+	};
+
+	static const char *cx2341x_video_luma_spatial_filter_type_menu[] = {
+		"Off",
+		"1D Horizontal",
+		"1D Vertical",
+		"2D H/V Separable",
+		"2D Symmetric non-separable",
+		NULL
+	};
+
+	static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = {
+		"Off",
+		"1D Horizontal",
+		NULL
+	};
+
+	static const char *cx2341x_video_temporal_filter_mode_menu[] = {
+		"Manual",
+		"Auto",
+		NULL
+	};
+
+	static const char *cx2341x_video_median_filter_type_menu[] = {
+		"Off",
+		"Horizontal",
+		"Vertical",
+		"Horizontal/Vertical",
+		"Diagonal",
+		NULL
+	};
+
+	switch (id) {
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		return mpeg_stream_type;
+	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+		return NULL;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE:
+		return cx2341x_video_spatial_filter_mode_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE:
+		return cx2341x_video_luma_spatial_filter_type_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE:
+		return cx2341x_video_chroma_spatial_filter_type_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE:
+		return cx2341x_video_temporal_filter_mode_menu;
+	case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE:
+		return cx2341x_video_median_filter_type_menu;
+	default:
+		return v4l2_ctrl_get_menu(id);
+	}
+}
+
+static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params)
+{
+	params->audio_properties = (params->audio_sampling_freq << 0) |
+		((3 - params->audio_encoding) << 2) |
+		((1 + params->audio_l2_bitrate) << 4) |
+		(params->audio_mode << 8) |
+		(params->audio_mode_extension << 10) |
+		(((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ?
+		  3 :
+		  params->audio_emphasis) << 12) |
+		(params->audio_crc << 14);
+}
+
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+		  struct v4l2_ext_controls *ctrls, unsigned int cmd)
+{
+	int err = 0;
+	int i;
+
+	if (cmd == VIDIOC_G_EXT_CTRLS) {
+		for (i = 0; i < ctrls->count; i++) {
+			struct v4l2_ext_control *ctrl = ctrls->controls + i;
+
+			err = cx2341x_get_ctrl(params, ctrl);
+			if (err) {
+				ctrls->error_idx = i;
+				break;
+			}
+		}
+		return err;
+	}
+	for (i = 0; i < ctrls->count; i++) {
+		struct v4l2_ext_control *ctrl = ctrls->controls + i;
+		struct v4l2_queryctrl qctrl;
+		const char **menu_items = NULL;
+
+		qctrl.id = ctrl->id;
+		err = cx2341x_ctrl_query(params, &qctrl);
+		if (err)
+			break;
+		if (qctrl.type == V4L2_CTRL_TYPE_MENU)
+			menu_items = cx2341x_ctrl_get_menu(qctrl.id);
+		err = v4l2_ctrl_check(ctrl, &qctrl, menu_items);
+		if (err)
+			break;
+		err = cx2341x_set_ctrl(params, ctrl);
+		if (err)
+			break;
+	}
+	if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR &&
+			params->video_bitrate_peak < params->video_bitrate) {
+		err = -ERANGE;
+		ctrls->error_idx = ctrls->count;
+	}
+	if (err) {
+		ctrls->error_idx = i;
+	}
+	else {
+		cx2341x_calc_audio_properties(params);
+	}
+	return err;
+}
+
+void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p)
+{
+	static struct cx2341x_mpeg_params default_params = {
+	/* misc */
+	.capabilities = 0,
+	.port = CX2341X_PORT_MEMORY,
+	.width = 720,
+	.height = 480,
+	.is_50hz = 0,
+
+	/* stream */
+	.stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+	.stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE,
+
+	/* audio */
+	.audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000,
+	.audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2,
+	.audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K,
+	.audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO,
+	.audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
+	.audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE,
+	.audio_crc = V4L2_MPEG_AUDIO_CRC_NONE,
+
+	/* video */
+	.video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2,
+	.video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3,
+	.video_b_frames = 2,
+	.video_gop_size = 12,
+	.video_gop_closure = 1,
+	.video_pulldown = 0,
+	.video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+	.video_bitrate = 6000000,
+	.video_bitrate_peak = 8000000,
+	.video_temporal_decimation = 0,
+
+	/* encoding filters */
+	.video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL,
+	.video_spatial_filter = 0,
+	.video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR,
+	.video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR,
+	.video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL,
+	.video_temporal_filter = 0,
+	.video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF,
+	.video_luma_median_filter_top = 255,
+	.video_luma_median_filter_bottom = 0,
+	.video_chroma_median_filter_top = 255,
+	.video_chroma_median_filter_bottom = 0,
+	};
+
+	*p = default_params;
+	cx2341x_calc_audio_properties(p);
+}
+
+static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	va_list vargs;
+	int i;
+
+	va_start(vargs, args);
+
+	for (i = 0; i < args; i++) {
+		data[i] = va_arg(vargs, int);
+	}
+	va_end(vargs);
+	return func(priv, cmd, args, 0, data);
+}
+
+int cx2341x_update(void *priv, cx2341x_mbox_func func,
+		const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new)
+{
+	static int mpeg_stream_type[] = {
+		0,	/* MPEG-2 PS */
+		1,	/* MPEG-2 TS */
+		2,	/* MPEG-1 SS */
+		14,	/* DVD */
+		11,	/* VCD */
+		12,	/* SVCD */
+	};
+
+	int err = 0;
+
+	cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0);
+
+	if (old == NULL || old->is_50hz != new->is_50hz) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz);
+		if (err) return err;
+	}
+
+	if (old == NULL || old->width != new->width || old->height != new->height ||
+			old->video_encoding != new->video_encoding) {
+		u16 w = new->width;
+		u16 h = new->height;
+
+		if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) {
+			w /= 2;
+			h /= 2;
+		}
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w);
+		if (err) return err;
+	}
+
+	if (old == NULL || old->stream_type != new->stream_type) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]);
+		if (err) return err;
+	}
+	if (old == NULL || old->video_aspect != new->video_aspect) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect);
+		if (err) return err;
+	}
+	if (old == NULL || old->video_b_frames != new->video_b_frames ||
+		old->video_gop_size != new->video_gop_size) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2,
+				new->video_gop_size, new->video_b_frames + 1);
+		if (err) return err;
+	}
+	if (old == NULL || old->video_gop_closure != new->video_gop_closure) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure);
+		if (err) return err;
+	}
+	if (old == NULL || old->video_pulldown != new->video_pulldown) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown);
+		if (err) return err;
+	}
+	if (old == NULL || old->audio_properties != new->audio_properties) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties);
+		if (err) return err;
+	}
+	if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode ||
+		old->video_bitrate != new->video_bitrate ||
+		old->video_bitrate_peak != new->video_bitrate_peak) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5,
+				new->video_bitrate_mode, new->video_bitrate,
+				new->video_bitrate_peak / 400, 0, 0);
+		if (err) return err;
+	}
+	if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode ||
+		old->video_temporal_filter_mode != new->video_temporal_filter_mode ||
+		old->video_median_filter_type != new->video_median_filter_type) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2,
+				new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1),
+				new->video_median_filter_type);
+		if (err) return err;
+	}
+	if (old == NULL ||
+		old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom ||
+		old->video_luma_median_filter_top != new->video_luma_median_filter_top ||
+		old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom ||
+		old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4,
+				new->video_luma_median_filter_bottom,
+				new->video_luma_median_filter_top,
+				new->video_chroma_median_filter_bottom,
+				new->video_chroma_median_filter_top);
+		if (err) return err;
+	}
+	if (old == NULL ||
+		old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type ||
+		old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2,
+			new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type);
+		if (err) return err;
+	}
+	if (old == NULL ||
+		old->video_spatial_filter != new->video_spatial_filter ||
+		old->video_temporal_filter != new->video_temporal_filter) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2,
+			new->video_spatial_filter, new->video_temporal_filter);
+		if (err) return err;
+	}
+	if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) {
+		err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1,
+			new->video_temporal_decimation);
+		if (err) return err;
+	}
+	return 0;
+}
+
+static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id)
+{
+	const char **menu = cx2341x_ctrl_get_menu(id);
+	struct v4l2_ext_control ctrl;
+
+	if (menu == NULL)
+		goto invalid;
+	ctrl.id = id;
+	if (cx2341x_get_ctrl(p, &ctrl))
+		goto invalid;
+	while (ctrl.value-- && *menu) menu++;
+	if (*menu == NULL)
+		goto invalid;
+	return *menu;
+
+invalid:
+	return "<invalid>";
+}
+
+void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix)
+{
+	int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+
+	/* Stream */
+	printk(KERN_INFO "%s: Stream: %s\n",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE));
+
+	/* Video */
+	printk(KERN_INFO "%s: Video:  %dx%d, %d fps\n",
+		prefix,
+		p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1),
+		p->is_50hz ? 25 : 30);
+	printk(KERN_INFO "%s: Video:  %s, %s, %s, %d",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE),
+		p->video_bitrate);
+	if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+		printk(", Peak %d", p->video_bitrate_peak);
+	}
+	printk("\n");
+	printk(KERN_INFO "%s: Video:  GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n",
+		prefix,
+		p->video_gop_size, p->video_b_frames,
+		p->video_gop_closure ? "" : "No ",
+		p->video_pulldown ? "" : "No ");
+	if (p->video_temporal_decimation) {
+		printk(KERN_INFO "%s: Video: Temporal Decimation %d\n",
+			prefix, p->video_temporal_decimation);
+	}
+
+	/* Audio */
+	printk(KERN_INFO "%s: Audio:  %s, %s, %s, %s",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE));
+	if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) {
+		printk(", %s",
+			cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION));
+	}
+	printk(", %s, %s\n",
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC));
+
+	/* Encoding filters */
+	printk(KERN_INFO "%s: Spatial Filter:  %s, Luma %s, Chroma %s, %d\n",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE),
+		cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE),
+		p->video_spatial_filter);
+	printk(KERN_INFO "%s: Temporal Filter: %s, %d\n",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE),
+		p->video_temporal_filter);
+	printk(KERN_INFO "%s: Median Filter:   %s, Luma [%d, %d], Chroma [%d, %d]\n",
+		prefix,
+		cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE),
+		p->video_luma_median_filter_bottom,
+		p->video_luma_median_filter_top,
+		p->video_chroma_median_filter_bottom,
+		p->video_chroma_median_filter_top);
+}
+
+EXPORT_SYMBOL(cx2341x_fill_defaults);
+EXPORT_SYMBOL(cx2341x_ctrl_query);
+EXPORT_SYMBOL(cx2341x_ctrl_get_menu);
+EXPORT_SYMBOL(cx2341x_ext_ctrls);
+EXPORT_SYMBOL(cx2341x_update);
+EXPORT_SYMBOL(cx2341x_log_status);
+EXPORT_SYMBOL(cx2341x_mpeg_ctrls);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c
index 9a4b813..f897c1e 100644
--- a/drivers/media/video/cx25840/cx25840-audio.c
+++ b/drivers/media/video/cx25840/cx25840-audio.c
@@ -30,9 +30,6 @@
 	if (freq != 32000 && freq != 44100 && freq != 48000)
 		return -EINVAL;
 
-	/* assert soft reset */
-	cx25840_and_or(client, 0x810, ~0x1, 0x01);
-
 	/* common for all inputs and rates */
 	/* SA_MCLK_SEL=1, SA_MCLK_DIV=0x10 */
 	cx25840_write(client, 0x127, 0x50);
@@ -46,6 +43,9 @@
 			/* AUX_PLL_FRAC */
 			cx25840_write4(client, 0x110, 0xee39bb01);
 
+			if (state->is_cx25836)
+				break;
+
 			/* src3/4/6_ctl = 0x0801f77f */
 			cx25840_write4(client, 0x900, 0x7ff70108);
 			cx25840_write4(client, 0x904, 0x7ff70108);
@@ -59,6 +59,9 @@
 			/* AUX_PLL_FRAC */
 			cx25840_write4(client, 0x110, 0xd66bec00);
 
+			if (state->is_cx25836)
+				break;
+
 			/* src3/4/6_ctl = 0x08016d59 */
 			cx25840_write4(client, 0x900, 0x596d0108);
 			cx25840_write4(client, 0x904, 0x596d0108);
@@ -72,6 +75,9 @@
 			/* AUX_PLL_FRAC */
 			cx25840_write4(client, 0x110, 0xe5d69800);
 
+			if (state->is_cx25836)
+				break;
+
 			/* src3/4/6_ctl = 0x08014faa */
 			cx25840_write4(client, 0x900, 0xaa4f0108);
 			cx25840_write4(client, 0x904, 0xaa4f0108);
@@ -87,6 +93,9 @@
 			/* AUX_PLL_FRAC */
 			cx25840_write4(client, 0x110, 0x69082a01);
 
+			if (state->is_cx25836)
+				break;
+
 			/* src1_ctl = 0x08010000 */
 			cx25840_write4(client, 0x8f8, 0x00000108);
 
@@ -106,6 +115,9 @@
 			/* AUX_PLL_FRAC */
 			cx25840_write4(client, 0x110, 0xd66bec00);
 
+			if (state->is_cx25836)
+				break;
+
 			/* src1_ctl = 0x08010000 */
 			cx25840_write4(client, 0x8f8, 0xcd600108);
 
@@ -122,6 +134,9 @@
 			/* AUX_PLL_FRAC */
 			cx25840_write4(client, 0x110, 0xe5d69800);
 
+			if (state->is_cx25836)
+				break;
+
 			/* src1_ctl = 0x08010000 */
 			cx25840_write4(client, 0x8f8, 0x00800108);
 
@@ -133,9 +148,6 @@
 		}
 	}
 
-	/* deassert soft reset */
-	cx25840_and_or(client, 0x810, ~0x1, 0x00);
-
 	state->audclk_freq = freq;
 
 	return 0;
@@ -148,6 +160,10 @@
 	/* stop microcontroller */
 	cx25840_and_or(client, 0x803, ~0x10, 0);
 
+	/* assert soft reset */
+	if (!state->is_cx25836)
+		cx25840_and_or(client, 0x810, ~0x1, 0x01);
+
 	/* Mute everything to prevent the PFFT! */
 	cx25840_write(client, 0x8d3, 0x1f);
 
@@ -161,13 +177,19 @@
 	} else {
 		/* Set Path1 to Analog Demod Main Channel */
 		cx25840_write4(client, 0x8d0, 0x7038061f);
+	}
 
+	set_audclk_freq(client, state->audclk_freq);
+
+	/* deassert soft reset */
+	if (!state->is_cx25836)
+		cx25840_and_or(client, 0x810, ~0x1, 0x00);
+
+	if (state->aud_input != CX25840_AUDIO_SERIAL) {
 		/* When the microcontroller detects the
 		 * audio format, it will unmute the lines */
 		cx25840_and_or(client, 0x803, ~0x10, 0x10);
 	}
-
-	set_audclk_freq(client, state->audclk_freq);
 }
 
 static int get_volume(struct i2c_client *client)
@@ -291,11 +313,25 @@
 
 int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
 {
+	struct cx25840_state *state = i2c_get_clientdata(client);
 	struct v4l2_control *ctrl = arg;
+	int retval;
 
 	switch (cmd) {
 	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
-		return set_audclk_freq(client, *(u32 *)arg);
+		if (state->aud_input != CX25840_AUDIO_SERIAL) {
+			cx25840_and_or(client, 0x803, ~0x10, 0);
+			cx25840_write(client, 0x8d3, 0x1f);
+		}
+		if (!state->is_cx25836)
+			cx25840_and_or(client, 0x810, ~0x1, 1);
+		retval = set_audclk_freq(client, *(u32 *)arg);
+		if (!state->is_cx25836)
+			cx25840_and_or(client, 0x810, ~0x1, 0);
+		if (state->aud_input != CX25840_AUDIO_SERIAL) {
+			cx25840_and_or(client, 0x803, ~0x10, 0x10);
+		}
+		return retval;
 
 	case VIDIOC_G_CTRL:
 		switch (ctrl->id) {
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c
index a961bb2..5c2036b 100644
--- a/drivers/media/video/cx25840/cx25840-core.c
+++ b/drivers/media/video/cx25840/cx25840-core.c
@@ -10,6 +10,9 @@
  *
  * VBI support by Hans Verkuil <hverkuil@xs4all.nl>.
  *
+ * NTSC sliced VBI support by Christopher Neufeld <television@cneufeld.ca>
+ * with additional fixes by Hans Verkuil <hverkuil@xs4all.nl>.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
@@ -43,7 +46,7 @@
 static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
 
 
-static int cx25840_debug;
+int cx25840_debug;
 
 module_param_named(debug,cx25840_debug, int, 0644);
 
@@ -105,7 +108,7 @@
 	    (buffer[2] << 8) | buffer[3];
 }
 
-int cx25840_and_or(struct i2c_client *client, u16 addr, u8 and_mask,
+int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
 		   u8 or_value)
 {
 	return cx25840_write(client, addr,
@@ -117,7 +120,8 @@
 
 static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
 						enum cx25840_audio_input aud_input);
-static void log_status(struct i2c_client *client);
+static void log_audio_status(struct i2c_client *client);
+static void log_video_status(struct i2c_client *client);
 
 /* ----------------------------------------------------------------------- */
 
@@ -147,6 +151,33 @@
 	cx25840_write(client, 0x15d, 0xe1);
 }
 
+static void cx25836_initialize(struct i2c_client *client)
+{
+	/* reset configuration is described on page 3-77 of the CX25836 datasheet */
+	/* 2. */
+	cx25840_and_or(client, 0x000, ~0x01, 0x01);
+	cx25840_and_or(client, 0x000, ~0x01, 0x00);
+	/* 3a. */
+	cx25840_and_or(client, 0x15a, ~0x70, 0x00);
+	/* 3b. */
+	cx25840_and_or(client, 0x15b, ~0x1e, 0x06);
+	/* 3c. */
+	cx25840_and_or(client, 0x159, ~0x02, 0x02);
+	/* 3d. */
+	/* There should be a 10-us delay here, but since the
+	   i2c bus already has a 10-us delay we don't need to do
+	   anything */
+	/* 3e. */
+	cx25840_and_or(client, 0x159, ~0x02, 0x00);
+	/* 3f. */
+	cx25840_and_or(client, 0x159, ~0xc0, 0xc0);
+	/* 3g. */
+	cx25840_and_or(client, 0x159, ~0x01, 0x00);
+	cx25840_and_or(client, 0x159, ~0x01, 0x01);
+	/* 3h. */
+	cx25840_and_or(client, 0x15b, ~0x1e, 0x10);
+}
+
 static void cx25840_initialize(struct i2c_client *client, int loadfw)
 {
 	struct cx25840_state *state = i2c_get_clientdata(client);
@@ -220,17 +251,7 @@
 	cx25840_and_or(client, 0x401, ~0x60, 0);
 	cx25840_and_or(client, 0x401, ~0x60, 0x60);
 
-	/* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC
-	   instead of V4L2_STD_PAL. Someone needs to test this. */
-	if (std & V4L2_STD_PAL) {
-		/* Follow tuner change procedure for PAL */
-		cx25840_write(client, 0x808, 0xff);
-		cx25840_write(client, 0x80b, 0x10);
-	} else if (std & V4L2_STD_SECAM) {
-		/* Select autodetect for SECAM */
-		cx25840_write(client, 0x808, 0xff);
-		cx25840_write(client, 0x80b, 0x10);
-	} else if (std & V4L2_STD_NTSC) {
+	if (std & V4L2_STD_525_60) {
 		/* Certain Hauppauge PVR150 models have a hardware bug
 		   that causes audio to drop out. For these models the
 		   audio standard must be set explicitly.
@@ -249,6 +270,14 @@
 			cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
 		}
 		cx25840_write(client, 0x80b, 0x00);
+	} else if (std & V4L2_STD_PAL) {
+		/* Follow tuner change procedure for PAL */
+		cx25840_write(client, 0x808, 0xff);
+		cx25840_write(client, 0x80b, 0x10);
+	} else if (std & V4L2_STD_SECAM) {
+		/* Select autodetect for SECAM */
+		cx25840_write(client, 0x808, 0xff);
+		cx25840_write(client, 0x80b, 0x10);
 	}
 
 	if (cx25840_read(client, 0x803) & 0x10) {
@@ -319,8 +348,10 @@
 
 	state->vid_input = vid_input;
 	state->aud_input = aud_input;
-	cx25840_audio_set_path(client);
-	input_change(client);
+	if (!state->is_cx25836) {
+		cx25840_audio_set_path(client);
+		input_change(client);
+	}
 	return 0;
 }
 
@@ -354,6 +385,8 @@
 		}
 	}
 
+	v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
+
 	/* Follow step 9 of section 3.16 in the cx25840 datasheet.
 	   Without this PAL may display a vertical ghosting effect.
 	   This happens for example with the Yuan MPC622. */
@@ -370,6 +403,7 @@
 
 v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
 {
+	struct cx25840_state *state = i2c_get_clientdata(client);
 	/* check VID_FMT_SEL first */
 	u8 fmt = cx25840_read(client, 0x400) & 0xf;
 
@@ -383,7 +417,7 @@
 	{
 		/* if the audio std is A2-M, then this is the South Korean
 		   NTSC standard */
-		if (cx25840_read(client, 0x805) == 2)
+		if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
 			return V4L2_STD_NTSC_M_KR;
 		return V4L2_STD_NTSC_M;
 	}
@@ -456,6 +490,8 @@
 	case V4L2_CID_AUDIO_TREBLE:
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_MUTE:
+		if (state->is_cx25836)
+			return -EINVAL;
 		return cx25840_audio(client, VIDIOC_S_CTRL, ctrl);
 
 	default:
@@ -490,6 +526,8 @@
 	case V4L2_CID_AUDIO_TREBLE:
 	case V4L2_CID_AUDIO_BALANCE:
 	case V4L2_CID_AUDIO_MUTE:
+		if (state->is_cx25836)
+			return -EINVAL;
 		return cx25840_audio(client, VIDIOC_G_CTRL, ctrl);
 	default:
 		return -EINVAL;
@@ -579,91 +617,6 @@
 
 /* ----------------------------------------------------------------------- */
 
-static struct v4l2_queryctrl cx25840_qctrl[] = {
-	{
-		.id            = V4L2_CID_BRIGHTNESS,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Brightness",
-		.minimum       = 0,
-		.maximum       = 255,
-		.step          = 1,
-		.default_value = 128,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_CONTRAST,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Contrast",
-		.minimum       = 0,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 64,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_SATURATION,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Saturation",
-		.minimum       = 0,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 64,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_HUE,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Hue",
-		.minimum       = -128,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 0,
-		.flags 	       = 0,
-	}, {
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 58880,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_AUDIO_BALANCE,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Balance",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.step          = 1,
-		.default_value = 1,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_AUDIO_BASS,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Bass",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-	}, {
-		.id            = V4L2_CID_AUDIO_TREBLE,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Treble",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-	},
-};
-
-/* ----------------------------------------------------------------------- */
-
 static int cx25840_command(struct i2c_client *client, unsigned int cmd,
 			   void *arg)
 {
@@ -706,8 +659,8 @@
 
 	case VIDIOC_STREAMON:
 		v4l_dbg(1, cx25840_debug, client, "enable output\n");
-		cx25840_write(client, 0x115, 0x8c);
-		cx25840_write(client, 0x116, 0x07);
+		cx25840_write(client, 0x115, state->is_cx25836 ? 0x0c : 0x8c);
+		cx25840_write(client, 0x116, state->is_cx25836 ? 0x04 : 0x07);
 		break;
 
 	case VIDIOC_STREAMOFF:
@@ -717,7 +670,9 @@
 		break;
 
 	case VIDIOC_LOG_STATUS:
-		log_status(client);
+		log_video_status(client);
+		if (!state->is_cx25836)
+			log_audio_status(client);
 		break;
 
 	case VIDIOC_G_CTRL:
@@ -729,13 +684,29 @@
 	case VIDIOC_QUERYCTRL:
 	{
 		struct v4l2_queryctrl *qc = arg;
-		int i;
 
-		for (i = 0; i < ARRAY_SIZE(cx25840_qctrl); i++)
-			if (qc->id && qc->id == cx25840_qctrl[i].id) {
-				memcpy(qc, &cx25840_qctrl[i], sizeof(*qc));
-				return 0;
-			}
+		switch (qc->id) {
+			case V4L2_CID_BRIGHTNESS:
+			case V4L2_CID_CONTRAST:
+			case V4L2_CID_SATURATION:
+			case V4L2_CID_HUE:
+				return v4l2_ctrl_query_fill_std(qc);
+			default:
+				break;
+		}
+		if (state->is_cx25836)
+			return -EINVAL;
+
+		switch (qc->id) {
+			case V4L2_CID_AUDIO_VOLUME:
+			case V4L2_CID_AUDIO_MUTE:
+			case V4L2_CID_AUDIO_BALANCE:
+			case V4L2_CID_AUDIO_BASS:
+			case V4L2_CID_AUDIO_TREBLE:
+				return v4l2_ctrl_query_fill_std(qc);
+			default:
+				return -EINVAL;
+		}
 		return -EINVAL;
 	}
 
@@ -760,31 +731,41 @@
 		return set_input(client, route->input, state->aud_input);
 
 	case VIDIOC_INT_G_AUDIO_ROUTING:
+		if (state->is_cx25836)
+			return -EINVAL;
 		route->input = state->aud_input;
 		route->output = 0;
 		break;
 
 	case VIDIOC_INT_S_AUDIO_ROUTING:
+		if (state->is_cx25836)
+			return -EINVAL;
 		return set_input(client, state->vid_input, route->input);
 
 	case VIDIOC_S_FREQUENCY:
-		input_change(client);
+		if (!state->is_cx25836) {
+			input_change(client);
+		}
 		break;
 
 	case VIDIOC_G_TUNER:
 	{
-		u8 mode = cx25840_read(client, 0x804);
-		u8 vpres = cx25840_read(client, 0x80a) & 0x10;
+		u8 vpres = cx25840_read(client, 0x40e) & 0x20;
+		u8 mode;
 		int val = 0;
 
 		if (state->radio)
 			break;
 
+		vt->signal = vpres ? 0xffff : 0x0;
+		if (state->is_cx25836)
+			break;
+
 		vt->capability |=
 		    V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LANG1 |
 		    V4L2_TUNER_CAP_LANG2 | V4L2_TUNER_CAP_SAP;
 
-		vt->signal = vpres ? 0xffff : 0x0;
+		mode = cx25840_read(client, 0x804);
 
 		/* get rxsubchans and audmode */
 		if ((mode & 0xf) == 1)
@@ -804,7 +785,7 @@
 	}
 
 	case VIDIOC_S_TUNER:
-		if (state->radio)
+		if (state->radio || state->is_cx25836)
 			break;
 
 		switch (vt->audmode) {
@@ -846,12 +827,14 @@
 		return set_v4lfmt(client, (struct v4l2_format *)arg);
 
 	case VIDIOC_INT_RESET:
-		cx25840_initialize(client, 0);
+		if (state->is_cx25836)
+			cx25836_initialize(client);
+		else
+			cx25840_initialize(client, 0);
 		break;
 
 	case VIDIOC_INT_G_CHIP_IDENT:
-		*(enum v4l2_chip_ident *)arg =
-			V4L2_IDENT_CX25840 + ((cx25840_read(client, 0x100) >> 4) & 0xf);
+		*(enum v4l2_chip_ident *)arg = state->id;
 		break;
 
 	default:
@@ -870,6 +853,7 @@
 {
 	struct i2c_client *client;
 	struct cx25840_state *state;
+	enum v4l2_chip_ident id;
 	u16 device_id;
 
 	/* Check if the adapter supports the needed features
@@ -878,10 +862,11 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
 		return 0;
 
-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
-	if (client == 0)
+	state = kzalloc(sizeof(struct cx25840_state), GFP_KERNEL);
+	if (state == 0)
 		return -ENOMEM;
 
+	client = &state->c;
 	client->addr = address;
 	client->adapter = adapter;
 	client->driver = &i2c_driver_cx25840;
@@ -893,10 +878,18 @@
 	device_id |= cx25840_read(client, 0x100);
 
 	/* The high byte of the device ID should be
-	 * 0x84 if chip is present */
-	if ((device_id & 0xff00) != 0x8400) {
+	 * 0x83 for the cx2583x and 0x84 for the cx2584x */
+	if ((device_id & 0xff00) == 0x8300) {
+		id = V4L2_IDENT_CX25836 + ((device_id >> 4) & 0xf) - 6;
+		state->is_cx25836 = 1;
+	}
+	else if ((device_id & 0xff00) == 0x8400) {
+		id = V4L2_IDENT_CX25840 + ((device_id >> 4) & 0xf);
+		state->is_cx25836 = 0;
+	}
+	else {
 		v4l_dbg(1, cx25840_debug, client, "cx25840 not found\n");
-		kfree(client);
+		kfree(state);
 		return 0;
 	}
 
@@ -905,21 +898,19 @@
 		    (device_id & 0x0f) < 3 ? (device_id & 0x0f) + 1 : 3,
 		    address << 1, adapter->name);
 
-	state = kmalloc(sizeof(struct cx25840_state), GFP_KERNEL);
-	if (state == NULL) {
-		kfree(client);
-		return -ENOMEM;
-	}
-
 	i2c_set_clientdata(client, state);
-	memset(state, 0, sizeof(struct cx25840_state));
 	state->vid_input = CX25840_COMPOSITE7;
 	state->aud_input = CX25840_AUDIO8;
 	state->audclk_freq = 48000;
 	state->pvr150_workaround = 0;
 	state->audmode = V4L2_TUNER_MODE_LANG1;
+	state->vbi_line_offset = 8;
+	state->id = id;
 
-	cx25840_initialize(client, 1);
+	if (state->is_cx25836)
+		cx25836_initialize(client);
+	else
+		cx25840_initialize(client, 1);
 
 	i2c_attach_client(client);
 
@@ -944,7 +935,6 @@
 	}
 
 	kfree(state);
-	kfree(client);
 
 	return 0;
 }
@@ -977,7 +967,7 @@
 
 /* ----------------------------------------------------------------------- */
 
-static void log_status(struct i2c_client *client)
+static void log_video_status(struct i2c_client *client)
 {
 	static const char *const fmt_strs[] = {
 		"0x0",
@@ -989,9 +979,36 @@
 	};
 
 	struct cx25840_state *state = i2c_get_clientdata(client);
-	u8 microctrl_vidfmt = cx25840_read(client, 0x80a);
 	u8 vidfmt_sel = cx25840_read(client, 0x400) & 0xf;
 	u8 gen_stat1 = cx25840_read(client, 0x40d);
+	u8 gen_stat2 = cx25840_read(client, 0x40e);
+	int vid_input = state->vid_input;
+
+	v4l_info(client, "Video signal:              %spresent\n",
+		    (gen_stat2 & 0x20) ? "" : "not ");
+	v4l_info(client, "Detected format:           %s\n",
+		    fmt_strs[gen_stat1 & 0xf]);
+
+	v4l_info(client, "Specified standard:        %s\n",
+		    vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
+
+	if (vid_input >= CX25840_COMPOSITE1 &&
+	    vid_input <= CX25840_COMPOSITE8) {
+		v4l_info(client, "Specified video input:     Composite %d\n",
+			vid_input - CX25840_COMPOSITE1 + 1);
+	} else {
+		v4l_info(client, "Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
+			(vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
+	}
+
+	v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void log_audio_status(struct i2c_client *client)
+{
+	struct cx25840_state *state = i2c_get_clientdata(client);
 	u8 download_ctl = cx25840_read(client, 0x803);
 	u8 mod_det_stat0 = cx25840_read(client, 0x804);
 	u8 mod_det_stat1 = cx25840_read(client, 0x805);
@@ -999,15 +1016,9 @@
 	u8 pref_mode = cx25840_read(client, 0x809);
 	u8 afc0 = cx25840_read(client, 0x80b);
 	u8 mute_ctl = cx25840_read(client, 0x8d3);
-	int vid_input = state->vid_input;
 	int aud_input = state->aud_input;
 	char *p;
 
-	v4l_info(client, "Video signal:              %spresent\n",
-		    (microctrl_vidfmt & 0x10) ? "" : "not ");
-	v4l_info(client, "Detected format:           %s\n",
-		    fmt_strs[gen_stat1 & 0xf]);
-
 	switch (mod_det_stat0) {
 	case 0x00: p = "mono"; break;
 	case 0x01: p = "stereo"; break;
@@ -1107,25 +1118,12 @@
 		v4l_info(client, "Configured audio system:   %s\n", p);
 	}
 
-	v4l_info(client, "Specified standard:        %s\n",
-		    vidfmt_sel ? fmt_strs[vidfmt_sel] : "automatic detection");
-
-	if (vid_input >= CX25840_COMPOSITE1 &&
-	    vid_input <= CX25840_COMPOSITE8) {
-		v4l_info(client, "Specified video input:     Composite %d\n",
-			vid_input - CX25840_COMPOSITE1 + 1);
-	} else {
-		v4l_info(client, "Specified video input:     S-Video (Luma In%d, Chroma In%d)\n",
-			(vid_input & 0xf0) >> 4, (vid_input & 0xf00) >> 8);
-	}
 	if (aud_input) {
 		v4l_info(client, "Specified audio input:     Tuner (In%d)\n", aud_input);
 	} else {
 		v4l_info(client, "Specified audio input:     External\n");
 	}
 
-	v4l_info(client, "Specified audioclock freq: %d Hz\n", state->audclk_freq);
-
 	switch (pref_mode & 0xf) {
 	case 0: p = "mono/language A"; break;
 	case 1: p = "language B"; break;
diff --git a/drivers/media/video/cx25840/cx25840-core.h b/drivers/media/video/cx25840/cx25840-core.h
index 1736929..2804906 100644
--- a/drivers/media/video/cx25840/cx25840-core.h
+++ b/drivers/media/video/cx25840/cx25840-core.h
@@ -24,6 +24,8 @@
 #include <linux/videodev2.h>
 #include <linux/i2c.h>
 
+extern int cx25840_debug;
+
 /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is
    present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
    certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
@@ -33,12 +35,16 @@
 #define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)
 
 struct cx25840_state {
+	struct i2c_client c;
 	int pvr150_workaround;
 	int radio;
 	enum cx25840_video_input vid_input;
 	enum cx25840_audio_input aud_input;
 	u32 audclk_freq;
 	int audmode;
+	int vbi_line_offset;
+	enum v4l2_chip_ident id;
+	int is_cx25836;
 };
 
 /* ----------------------------------------------------------------------- */
@@ -47,7 +53,7 @@
 int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
 u8 cx25840_read(struct i2c_client *client, u16 addr);
 u32 cx25840_read4(struct i2c_client *client, u16 addr);
-int cx25840_and_or(struct i2c_client *client, u16 addr, u8 mask, u8 value);
+int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
 v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
 
 /* ----------------------------------------------------------------------- */
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c
index 57feca2..6cc8bf2 100644
--- a/drivers/media/video/cx25840/cx25840-vbi.c
+++ b/drivers/media/video/cx25840/cx25840-vbi.c
@@ -84,67 +84,140 @@
 
 void cx25840_vbi_setup(struct i2c_client *client)
 {
+	struct cx25840_state *state = i2c_get_clientdata(client);
 	v4l2_std_id std = cx25840_get_v4lstd(client);
+	int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
+	int luma_lpf,uv_lpf, comb;
+	u32 pll_int,pll_frac,pll_post;
 
+	/* datasheet startup, step 8d */
 	if (std & ~V4L2_STD_NTSC) {
-		/* datasheet startup, step 8d */
 		cx25840_write(client, 0x49f, 0x11);
-
-		cx25840_write(client, 0x470, 0x84);
-		cx25840_write(client, 0x471, 0x00);
-		cx25840_write(client, 0x472, 0x2d);
-		cx25840_write(client, 0x473, 0x5d);
-
-		cx25840_write(client, 0x474, 0x24);
-		cx25840_write(client, 0x475, 0x40);
-		cx25840_write(client, 0x476, 0x24);
-		cx25840_write(client, 0x477, 0x28);
-
-		cx25840_write(client, 0x478, 0x1f);
-		cx25840_write(client, 0x479, 0x02);
-
-		if (std & V4L2_STD_SECAM) {
-			cx25840_write(client, 0x47a, 0x80);
-			cx25840_write(client, 0x47b, 0x00);
-			cx25840_write(client, 0x47c, 0x5f);
-			cx25840_write(client, 0x47d, 0x42);
-		} else {
-			cx25840_write(client, 0x47a, 0x90);
-			cx25840_write(client, 0x47b, 0x20);
-			cx25840_write(client, 0x47c, 0x63);
-			cx25840_write(client, 0x47d, 0x82);
-		}
-
-		cx25840_write(client, 0x47e, 0x0a);
-		cx25840_write(client, 0x47f, 0x01);
 	} else {
-		/* datasheet startup, step 8d */
 		cx25840_write(client, 0x49f, 0x14);
+	}
 
-		cx25840_write(client, 0x470, 0x7a);
-		cx25840_write(client, 0x471, 0x00);
-		cx25840_write(client, 0x472, 0x2d);
-		cx25840_write(client, 0x473, 0x5b);
+	if (std & V4L2_STD_625_50) {
+		hblank=0x084;
+		hactive=0x2d0;
+		burst=0x5d;
+		vblank=0x024;
+		vactive=0x244;
+		vblank656=0x28;
+		src_decimation=0x21f;
 
-		cx25840_write(client, 0x474, 0x1a);
-		cx25840_write(client, 0x475, 0x70);
-		cx25840_write(client, 0x476, 0x1e);
-		cx25840_write(client, 0x477, 0x1e);
+		luma_lpf=2;
+		if (std & V4L2_STD_SECAM) {
+			uv_lpf=0;
+			comb=0;
+			sc=0x0a425f;
+		} else {
+			uv_lpf=1;
+			comb=0x20;
+			sc=0x0a8263;
+		}
+	} else {
+		hactive=720;
+		hblank=122;
+		vactive=487;
+		luma_lpf=1;
+		uv_lpf=1;
 
-		cx25840_write(client, 0x478, 0x1f);
-		cx25840_write(client, 0x479, 0x02);
-		cx25840_write(client, 0x47a, 0x50);
-		cx25840_write(client, 0x47b, 0x66);
+		src_decimation=0x21f;
+		if (std == V4L2_STD_PAL_M) {
+			vblank=20;
+			vblank656=24;
+			burst=0x61;
+			comb=0x20;
 
-		cx25840_write(client, 0x47c, 0x1f);
-		cx25840_write(client, 0x47d, 0x7c);
-		cx25840_write(client, 0x47e, 0x08);
+			sc=555452;
+		} else {
+			vblank=26;
+			vblank656=26;
+			burst=0x5b;
+			comb=0x66;
+			sc=556063;
+		}
+	}
+
+	/* DEBUG: Displays configured PLL frequency */
+	pll_int=cx25840_read(client, 0x108);
+	pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff;
+	pll_post=cx25840_read(client, 0x109);
+	v4l_dbg(1, cx25840_debug, client,
+				"PLL regs = int: %u, frac: %u, post: %u\n",
+				pll_int,pll_frac,pll_post);
+
+	if (pll_post) {
+		int fin, fsc;
+		int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L;
+
+		pll/=pll_post;
+		v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
+						pll/1000000, pll%1000000);
+		v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
+						pll/8000000, (pll/8)%1000000);
+
+		fin=((u64)src_decimation*pll)>>12;
+		v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = "
+						"%d.%06d MHz\n",
+						fin/1000000,fin%1000000);
+
+		fsc= (((u64)sc)*pll) >> 24L;
+		v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = "
+						"%d.%06d MHz\n",
+						fsc/1000000,fsc%1000000);
+
+		v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
+			"vblank %i , vactive %i, vblank656 %i, src_dec %i,"
+			"burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
+			" sc 0x%06x\n",
+			hblank, hactive, vblank, vactive, vblank656,
+			src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
+	}
+
+	/* Sets horizontal blanking delay and active lines */
+	cx25840_write(client, 0x470, hblank);
+	cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4)));
+	cx25840_write(client, 0x472, hactive>>4);
+
+	/* Sets burst gate delay */
+	cx25840_write(client, 0x473, burst);
+
+	/* Sets vertical blanking delay and active duration */
+	cx25840_write(client, 0x474, vblank);
+	cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4)));
+	cx25840_write(client, 0x476, vactive>>4);
+	cx25840_write(client, 0x477, vblank656);
+
+	/* Sets src decimation rate */
+	cx25840_write(client, 0x478, 0xff&src_decimation);
+	cx25840_write(client, 0x479, 0xff&(src_decimation>>8));
+
+	/* Sets Luma and UV Low pass filters */
+	cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30));
+
+	/* Enables comb filters */
+	cx25840_write(client, 0x47b, comb);
+
+	/* Sets SC Step*/
+	cx25840_write(client, 0x47c, sc);
+	cx25840_write(client, 0x47d, 0xff&sc>>8);
+	cx25840_write(client, 0x47e, 0xff&sc>>16);
+
+	/* Sets VBI parameters */
+	if (std & V4L2_STD_625_50) {
+		cx25840_write(client, 0x47f, 0x01);
+		state->vbi_line_offset = 5;
+	} else {
 		cx25840_write(client, 0x47f, 0x00);
+		state->vbi_line_offset = 8;
 	}
 }
 
 int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
 {
+	struct cx25840_state *state = i2c_get_clientdata(client);
 	struct v4l2_format *fmt;
 	struct v4l2_sliced_vbi_format *svbi;
 
@@ -182,7 +255,7 @@
 
 	case VIDIOC_S_FMT:
 	{
-		int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC);
+		int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
 		int vbi_offset = is_pal ? 1 : 0;
 		int i, x;
 		u8 lcr[24];
@@ -211,7 +284,7 @@
 		cx25840_vbi_setup(client);
 
 		/* Sliced VBI */
-		cx25840_write(client, 0x404, 0x36);	/* Ancillery data */
+		cx25840_write(client, 0x404, 0x32);	/* Ancillary data */
 		cx25840_write(client, 0x406, 0x13);
 		cx25840_write(client, 0x47f, vbi_offset);
 
@@ -248,8 +321,18 @@
 			}
 		}
 
-		for (x = 1, i = 0x424; i <= 0x434; i++, x++) {
-			cx25840_write(client, i, lcr[6 + x]);
+		if (is_pal) {
+			for (x = 1, i = 0x424; i <= 0x434; i++, x++) {
+				cx25840_write(client, i, lcr[6 + x]);
+			}
+		}
+		else {
+			for (x = 1, i = 0x424; i <= 0x430; i++, x++) {
+				cx25840_write(client, i, lcr[9 + x]);
+			}
+			for (i = 0x431; i <= 0x434; i++) {
+				cx25840_write(client, i, 0);
+			}
 		}
 
 		cx25840_write(client, 0x43c, 0x16);
@@ -257,7 +340,7 @@
 		if (is_pal) {
 			cx25840_write(client, 0x474, 0x2a);
 		} else {
-			cx25840_write(client, 0x474, 0x1a + 6);
+			cx25840_write(client, 0x474, 0x22);
 		}
 		break;
 	}
@@ -278,7 +361,7 @@
 		id1 = p[-1];
 		id2 = p[0] & 0xf;
 		l = p[2] & 0x3f;
-		l += 5;
+		l += state->vbi_line_offset;
 		p += 4;
 
 		switch (id2) {
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig
index 6302739..80e23ee 100644
--- a/drivers/media/video/cx88/Kconfig
+++ b/drivers/media/video/cx88/Kconfig
@@ -35,13 +35,25 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cx88-alsa.
 
+config VIDEO_CX88_BLACKBIRD
+	tristate "Blackbird MPEG encoder support (cx2388x + cx23416)"
+	depends on VIDEO_CX88
+	select VIDEO_CX2341X
+	---help---
+	  This adds support for MPEG encoder cards based on the
+	  Blackbird reference design, using the Conexant 2388x
+	  and 23416 chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cx88-blackbird.
+
 config VIDEO_CX88_DVB
 	tristate "DVB/ATSC Support for cx2388x based TV cards"
 	depends on VIDEO_CX88 && DVB_CORE
 	select VIDEO_BUF_DVB
 	---help---
 	  This adds support for DVB/ATSC cards based on the
-	  Connexant 2388x chip.
+	  Conexant 2388x chip.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called cx88-dvb.
@@ -61,6 +73,7 @@
 	select DVB_LGDT330X
 	select DVB_NXT200X
 	select DVB_CX24123
+	select DVB_ISL6421
 	---help---
 	  This builds cx88-dvb with all currently supported frontend
 	  demodulators.  If you wish to tweak your configuration, and
@@ -139,6 +152,7 @@
 	default y
 	depends on VIDEO_CX88_DVB && !VIDEO_CX88_DVB_ALL_FRONTENDS
 	select DVB_CX24123
+	select DVB_ISL6421
 	---help---
 	  This adds DVB-S support for cards based on the
 	  Connexant 2388x chip and the CX24123 demodulator.
diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile
index 0dcd09b..352b919 100644
--- a/drivers/media/video/cx88/Makefile
+++ b/drivers/media/video/cx88/Makefile
@@ -3,9 +3,10 @@
 cx8800-objs	:= cx88-video.o cx88-vbi.o
 cx8802-objs	:= cx88-mpeg.o
 
-obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o cx88-blackbird.o
-obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
+obj-$(CONFIG_VIDEO_CX88) += cx88xx.o cx8800.o cx8802.o
 obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o
+obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
+obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
 obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 320b3d9..2194cbe 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -4,7 +4,7 @@
  *  PCI function #1 of the cx2388x.
  *
  *    (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
- *    (c) 2005 Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+ *    (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
  *    Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
  *    Based on dummy.c by Jaroslav Kysela <perex@suse.cz>
  *
@@ -111,7 +111,7 @@
 
 MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Ricardo Cerqueira");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@brturbo.com.br>");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Conexant,23881},"
 			"{{Conexant,23882},"
@@ -696,7 +696,6 @@
 	chip->irq = -1;
 	spin_lock_init(&chip->reg_lock);
 
-	cx88_reset(core);
 	chip->core = core;
 
 	/* get irq */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index e100d8e..4ff8158 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -30,9 +30,10 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <media/v4l2-common.h>
+#include <media/cx2341x.h>
 
 #include "cx88.h"
-#include <media/v4l2-common.h>
 
 MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
 MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -53,7 +54,6 @@
 
 /* ------------------------------------------------------------------ */
 
-#define BLACKBIRD_FIRM_ENC_FILENAME "blackbird-fw-enc.bin"
 #define BLACKBIRD_FIRM_IMAGE_SIZE 256*1024
 
 /* defines below are from ivtv-driver.h */
@@ -63,8 +63,6 @@
 /* Firmware API commands */
 #define IVTV_API_STD_TIMEOUT 500
 
-#define BLACKBIRD_API_PING               0x80
-#define BLACKBIRD_API_BEGIN_CAPTURE      0x81
 enum blackbird_capture_type {
 	BLACKBIRD_MPEG_CAPTURE,
 	BLACKBIRD_RAW_CAPTURE,
@@ -78,205 +76,29 @@
 	BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
 	BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
 };
-#define BLACKBIRD_API_END_CAPTURE        0x82
 enum blackbird_capture_end {
 	BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
 	BLACKBIRD_END_NOW, /* stop immediately, no irq */
 };
-#define BLACKBIRD_API_SET_AUDIO_ID       0x89
-#define BLACKBIRD_API_SET_VIDEO_ID       0x8B
-#define BLACKBIRD_API_SET_PCR_ID         0x8D
-#define BLACKBIRD_API_SET_FRAMERATE      0x8F
 enum blackbird_framerate {
 	BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
 	BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
 };
-#define BLACKBIRD_API_SET_RESOLUTION     0x91
-#define BLACKBIRD_API_SET_VIDEO_BITRATE  0x95
-enum blackbird_video_bitrate_type {
-	BLACKBIRD_VIDEO_VBR,
-	BLACKBIRD_VIDEO_CBR
-};
-#define BLACKBIRD_PEAK_RATE_DIVISOR 400
-enum blackbird_mux_rate {
-	BLACKBIRD_MUX_RATE_DEFAULT,
-	 /* dvd mux rate: multiply by 400 to get the actual rate */
-	BLACKBIRD_MUX_RATE_DVD = 25200
-};
-#define BLACKBIRD_API_SET_GOP_STRUCTURE  0x97
-#define BLACKBIRD_API_SET_ASPECT_RATIO   0x99
-enum blackbird_aspect_ratio {
-	BLACKBIRD_ASPECT_RATIO_FORBIDDEN,
-	BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
-	BLACKBIRD_ASPECT_RATIO_4_3,
-	BLACKBIRD_ASPECT_RATIO_16_9,
-	BLACKBIRD_ASPECT_RATIO_221_100,
-	BLACKBIRD_ASPECT_RATIO_RESERVED
-};
-#define BLACKBIRD_API_SET_DNR_MODE       0x9B
-enum blackbird_dnr_bits {
-	BLACKBIRD_DNR_BITS_MANUAL,
-	BLACKBIRD_DNR_BITS_AUTO_SPATIAL,
-	BLACKBIRD_DNR_BITS_AUTO_TEMPORAL,
-	BLACKBIRD_DNR_BITS_AUTO
-};
-enum blackbird_median_filter {
-	BLACKBIRD_MEDIAN_FILTER_DISABLED,
-	BLACKBIRD_MEDIAN_FILTER_HORIZONTAL,
-	BLACKBIRD_MEDIAN_FILTER_VERTICAL,
-	BLACKBIRD_MEDIAN_FILTER_HV,
-	BLACKBIRD_MEDIAN_FILTER_DIAGONAL
-};
-#define BLACKBIRD_API_SET_MANUAL_DNR     0x9D
-#define BLACKBIRD_API_SET_DNR_MEDIAN     0x9F
-#define BLACKBIRD_API_SET_SPATIAL_FILTER 0xA1
-enum blackbird_spatial_filter_luma {
-	BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED,
-	BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
-	BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT,
-	BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */
-	BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */
-};
-enum blackbird_spatial_filter_chroma {
-	BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED,
-	BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */
-};
-#define BLACKBIRD_API_SET_3_2_PULLDOWN   0xB1
-enum blackbird_pulldown {
-	BLACKBIRD_3_2_PULLDOWN_DISABLED,
-	BLACKBIRD_3_2_PULLDOWN_ENABLED
-};
-#define BLACKBIRD_API_SET_VBI_LINE_NO    0xB7
-enum blackbird_vbi_line_bits {
-	BLACKBIRD_VBI_LINE_BITS_TOP_FIELD,
-	BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31),
-	BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF
-};
-enum blackbird_vbi_line {
-	BLACKBIRD_VBI_LINE_DISABLED,
-	BLACKBIRD_VBI_LINE_ENABLED
-};
-enum blackbird_vbi_slicing {
-	BLACKBIRD_VBI_SLICING_NONE,
-	BLACKBIRD_VBI_SLICING_CLOSED_CAPTION
-};
-#define BLACKBIRD_API_SET_STREAM_TYPE    0xB9
-enum blackbird_stream_type {
-	BLACKBIRD_STREAM_PROGRAM,
-	BLACKBIRD_STREAM_TRANSPORT,
-	BLACKBIRD_STREAM_MPEG1,
-	BLACKBIRD_STREAM_PES_AV,
-	BLACKBIRD_STREAM_UNKNOWN4,
-	BLACKBIRD_STREAM_PES_VIDEO,
-	BLACKBIRD_STREAM_UNKNOWN6,
-	BLACKBIRD_STREAM_PES_AUDIO,
-	BLACKBIRD_STREAM_UNKNOWN8,
-	BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */
-	BLACKBIRD_STREAM_DVD,
-	BLACKBIRD_STREAM_VCD,
-	BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */
-};
-#define BLACKBIRD_API_SET_OUTPUT_PORT    0xBB
 enum blackbird_stream_port {
 	BLACKBIRD_OUTPUT_PORT_MEMORY,
 	BLACKBIRD_OUTPUT_PORT_STREAMING,
 	BLACKBIRD_OUTPUT_PORT_SERIAL
 };
-#define BLACKBIRD_API_SET_AUDIO_PARAMS   0xBD
-enum blackbird_audio_bits_sample_rate {
-	BLACKBIRD_AUDIO_BITS_44100HZ,
-	BLACKBIRD_AUDIO_BITS_48000HZ,
-	BLACKBIRD_AUDIO_BITS_32000HZ,
-	BLACKBIRD_AUDIO_BITS_RESERVED_HZ,
-};
-enum blackbird_audio_bits_encoding {
-	BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2,
-	BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2,
-};
-enum blackbird_audio_bits_bitrate_layer_1 {
-	BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_32  = 0x01 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_64  = 0x02 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_96  = 0x03 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4,
-};
-enum blackbird_audio_bits_bitrate_layer_2 {
-	BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_32  = 0x01 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_48  = 0x02 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_56  = 0x03 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_64  = 0x04 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_80  = 0x05 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_96  = 0x06 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4,
-	BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4,
-};
-enum blackbird_audio_bits_mode {
-	BLACKBIRD_AUDIO_BITS_STEREO,
-	BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8,
-	BLACKBIRD_AUDIO_BITS_DUAL         = 0x2 << 8,
-	BLACKBIRD_AUDIO_BITS_MONO         = 0x3 << 8,
-};
-enum blackbird_audio_bits_mode_extension {
-	BLACKBIRD_AUDIO_BITS_BOUND_4,
-	BLACKBIRD_AUDIO_BITS_BOUND_8  = 0x1 << 10,
-	BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10,
-	BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10,
-};
-enum blackbird_audio_bits_emphasis {
-	BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE,
-	BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15     = 0x1 << 12,
-	BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED  = 0x2 << 12,
-	BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12,
-};
-enum blackbird_audio_bits_crc {
-	BLACKBIRD_AUDIO_BITS_CRC_OFF,
-	BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14,
-};
-enum blackbird_audio_bits_copyright {
-	BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF,
-	BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15,
-};
-enum blackbird_audio_bits_original {
-	BLACKBIRD_AUDIO_BITS_COPY,
-	BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16,
-};
-#define BLACKBIRD_API_HALT               0xC3
-#define BLACKBIRD_API_GET_VERSION        0xC4
-#define BLACKBIRD_API_SET_GOP_CLOSURE    0xC5
-enum blackbird_gop_closure {
-	BLACKBIRD_GOP_CLOSURE_OFF,
-	BLACKBIRD_GOP_CLOSURE_ON,
-};
-#define BLACKBIRD_API_DATA_XFER_STATUS   0xC6
 enum blackbird_data_xfer_status {
 	BLACKBIRD_MORE_BUFFERS_FOLLOW,
 	BLACKBIRD_LAST_BUFFER,
 };
-#define BLACKBIRD_API_PROGRAM_INDEX_INFO 0xC7
 enum blackbird_picture_mask {
 	BLACKBIRD_PICTURE_MASK_NONE,
 	BLACKBIRD_PICTURE_MASK_I_FRAMES,
 	BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
 	BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
 };
-#define BLACKBIRD_API_SET_VBI_PARAMS     0xC8
 enum blackbird_vbi_mode_bits {
 	BLACKBIRD_VBI_BITS_SLICED,
 	BLACKBIRD_VBI_BITS_RAW,
@@ -288,33 +110,23 @@
 	BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
 	BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
 };
-#define BLACKBIRD_API_SET_DMA_BLOCK_SIZE 0xC9
 enum blackbird_dma_unit {
 	BLACKBIRD_DMA_BYTES,
 	BLACKBIRD_DMA_FRAMES,
 };
-#define BLACKBIRD_API_DMA_TRANSFER_INFO  0xCA
-#define BLACKBIRD_API_DMA_TRANSFER_STAT  0xCB
 enum blackbird_dma_transfer_status_bits {
 	BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
 	BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
 	BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
 };
-#define BLACKBIRD_API_SET_DMA2HOST_ADDR  0xCC
-#define BLACKBIRD_API_INIT_VIDEO_INPUT   0xCD
-#define BLACKBIRD_API_SET_FRAMESKIP      0xD0
-#define BLACKBIRD_API_PAUSE              0xD2
 enum blackbird_pause {
 	BLACKBIRD_PAUSE_ENCODING,
 	BLACKBIRD_RESUME_ENCODING,
 };
-#define BLACKBIRD_API_REFRESH_INPUT      0xD3
-#define BLACKBIRD_API_SET_COPYRIGHT      0xD4
 enum blackbird_copyright {
 	BLACKBIRD_COPYRIGHT_OFF,
 	BLACKBIRD_COPYRIGHT_ON,
 };
-#define BLACKBIRD_API_SET_NOTIFICATION   0xD5
 enum blackbird_notification_type {
 	BLACKBIRD_NOTIFICATION_REFRESH,
 };
@@ -325,7 +137,6 @@
 enum blackbird_notification_mailbox {
 	BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
 };
-#define BLACKBIRD_API_SET_CAPTURE_LINES  0xD6
 enum blackbird_field1_lines {
 	BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
 	BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
@@ -336,12 +147,10 @@
 	BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
 	BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
 };
-#define BLACKBIRD_API_SET_CUSTOM_DATA    0xD7
 enum blackbird_custom_data_type {
 	BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
 	BLACKBIRD_CUSTOM_PRIVATE_PACKET,
 };
-#define BLACKBIRD_API_MUTE_VIDEO         0xD9
 enum blackbird_mute {
 	BLACKBIRD_UNMUTE,
 	BLACKBIRD_MUTE,
@@ -356,7 +165,6 @@
 	BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
 	BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
 };
-#define BLACKBIRD_API_MUTE_AUDIO         0xDA
 
 /* Registers */
 #define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
@@ -498,15 +306,12 @@
 
 /* ------------------------------------------------------------------ */
 
-/* We don't need to call the API often, so using just one mailbox will probably suffice */
-static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
-			     u32 inputcnt, u32 outputcnt, ...)
+static int blackbird_mbox_func(void *priv, int command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
 {
+	struct cx8802_dev *dev = priv;
 	unsigned long timeout;
 	u32 value, flag, retval;
 	int i;
-	va_list args;
-	va_start(args, outputcnt);
 
 	dprintk(1,"%s: 0x%X\n", __FUNCTION__, command);
 
@@ -530,12 +335,11 @@
 	/* write command + args + fill remaining with zeros */
 	memory_write(dev->core, dev->mailbox + 1, command); /* command code */
 	memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
-	for (i = 0; i < inputcnt ; i++) {
-		value = va_arg(args, int);
-		memory_write(dev->core, dev->mailbox + 4 + i, value);
-		dprintk(1, "API Input %d = %d\n", i, value);
+	for (i = 0; i < in; i++) {
+		memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
+		dprintk(1, "API Input %d = %d\n", i, data[i]);
 	}
-	for (; i < 16 ; i++)
+	for (; i < CX2341X_MBOX_MAX_DATA; i++)
 		memory_write(dev->core, dev->mailbox + 4 + i, 0);
 
 	flag |= 3; /* tell 'em we're done writing */
@@ -555,12 +359,10 @@
 	}
 
 	/* read output values */
-	for (i = 0; i < outputcnt ; i++) {
-		int *vptr = va_arg(args, int *);
-		memory_read(dev->core, dev->mailbox + 4 + i, vptr);
-		dprintk(1, "API Output %d = %d\n", i, *vptr);
+	for (i = 0; i < out; i++) {
+		memory_read(dev->core, dev->mailbox + 4 + i, data + i);
+		dprintk(1, "API Output %d = %d\n", i, data[i]);
 	}
-	va_end(args);
 
 	memory_read(dev->core, dev->mailbox + 2, &retval);
 	dprintk(1, "API result = %d\n",retval);
@@ -569,7 +371,29 @@
 	memory_write(dev->core, dev->mailbox, flag);
 	return retval;
 }
+/* ------------------------------------------------------------------ */
 
+/* We don't need to call the API often, so using just one mailbox will probably suffice */
+static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
+			     u32 inputcnt, u32 outputcnt, ...)
+{
+	u32 data[CX2341X_MBOX_MAX_DATA];
+	va_list vargs;
+	int i, err;
+
+	va_start(vargs, outputcnt);
+
+	for (i = 0; i < inputcnt; i++) {
+		data[i] = va_arg(vargs, int);
+	}
+	err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data);
+	for (i = 0; i < outputcnt; i++) {
+		int *vptr = va_arg(vargs, int *);
+		*vptr = data[i];
+	}
+	va_end(vargs);
+	return err;
+}
 
 static int blackbird_find_mailbox(struct cx8802_dev *dev)
 {
@@ -614,13 +438,13 @@
 	if (retval < 0)
 		dprintk(0, "Error with register_write\n");
 
-	retval = request_firmware(&firmware, BLACKBIRD_FIRM_ENC_FILENAME,
+	retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
 				  &dev->pci->dev);
 
 
 	if (retval != 0) {
 		dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
-			BLACKBIRD_FIRM_ENC_FILENAME);
+			CX2341X_FIRM_ENC_FILENAME);
 		dprintk(0, "Please fix your hotplug setup, the board will "
 			"not work without firmware loaded!\n");
 		return -1;
@@ -686,12 +510,19 @@
 *DB: "DirectBurn"
 */
 
-static struct blackbird_dnr default_dnr_params = {
-	.mode     = BLACKBIRD_DNR_BITS_MANUAL,
-	.type     = BLACKBIRD_MEDIAN_FILTER_DISABLED,
-	.spatial  = 0,
-	.temporal = 0
-};
+static void blackbird_codec_settings(struct cx8802_dev *dev)
+{
+	/* assign frame size */
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
+				dev->height, dev->width);
+
+	dev->params.width = dev->width;
+	dev->params.height = dev->height;
+	dev->params.is_50hz = (dev->core->tvnorm->id & V4L2_STD_625_50) != 0;
+
+	cx2341x_update(dev, blackbird_mbox_func, NULL, &dev->params);
+}
+
 static struct v4l2_mpeg_compression default_mpeg_params = {
 	.st_type          = V4L2_MPEG_PS_2,
 	.st_bitrate       = {
@@ -712,7 +543,7 @@
 		.target   = 224,
 		.max      = 224
 	},
-	.au_sample_rate    = 44100,
+	.au_sample_rate    = 48000,
 	.au_pesid          = 0,
 	.vi_type           = V4L2_MPEG_VI_2,
 	.vi_aspect_ratio   = V4L2_MPEG_ASPECT_4_3,
@@ -723,524 +554,13 @@
 		.max       = 6000
 	},
 	.vi_frame_rate     = 25,
-	.vi_frames_per_gop = 15,
+	.vi_frames_per_gop = 12,
 	.vi_bframes_count  = 2,
 	.vi_pesid          = 0,
-	.closed_gops       = 0,
+	.closed_gops       = 1,
 	.pulldown          = 0
 };
 
-static enum blackbird_stream_type mpeg_stream_types[] = {
-	[V4L2_MPEG_SS_1]   = BLACKBIRD_STREAM_MPEG1,
-	[V4L2_MPEG_PS_2]   = BLACKBIRD_STREAM_PROGRAM,
-	[V4L2_MPEG_TS_2]   = BLACKBIRD_STREAM_TRANSPORT,
-	[V4L2_MPEG_PS_DVD] = BLACKBIRD_STREAM_DVD,
-};
-static enum blackbird_aspect_ratio mpeg_stream_ratios[] = {
-	[V4L2_MPEG_ASPECT_SQUARE] = BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
-	[V4L2_MPEG_ASPECT_4_3]    = BLACKBIRD_ASPECT_RATIO_4_3,
-	[V4L2_MPEG_ASPECT_16_9]   = BLACKBIRD_ASPECT_RATIO_16_9,
-	[V4L2_MPEG_ASPECT_1_221]  = BLACKBIRD_ASPECT_RATIO_221_100,
-};
-static enum blackbird_video_bitrate_type mpeg_video_bitrates[] = {
-	[V4L2_BITRATE_NONE] = BLACKBIRD_VIDEO_CBR,
-	[V4L2_BITRATE_CBR]  = BLACKBIRD_VIDEO_CBR,
-	[V4L2_BITRATE_VBR]  = BLACKBIRD_VIDEO_VBR,
-};
-/* find the best layer I/II bitrate to fit a given numeric value */
-struct bitrate_bits {
-	u32 bits; /* layer bits for the best fit */
-	u32 rate; /* actual numeric value for the layer best fit */
-};
-struct bitrate_approximation {
-	u32                 target;   /* numeric value of the rate we want */
-	struct bitrate_bits layer[2];
-};
-static struct bitrate_approximation mpeg_audio_bitrates[] = {
-	/* target  layer[0].bits           layer[0].rate       layer[1].bits           layer[1].rate */
-	{   0, { {                                0,   0, }, {                                0,   0, }, }, },
-	{  32, { { BLACKBIRD_AUDIO_BITS_LAYER_1_32 ,  32, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_32 ,  32, }, }, },
-	{  48, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_48 ,  48, }, }, },
-	{  56, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_56 ,  56, }, }, },
-	{  64, { { BLACKBIRD_AUDIO_BITS_LAYER_1_64 ,  64, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_64 ,  64, }, }, },
-	{  80, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 ,  96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_80 ,  80, }, }, },
-	{  96, { { BLACKBIRD_AUDIO_BITS_LAYER_1_96 ,  96, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_96 ,  96, }, }, },
-	{ 112, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_112, 112, }, }, },
-	{ 128, { { BLACKBIRD_AUDIO_BITS_LAYER_1_128, 128, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_128, 128, }, }, },
-	{ 160, { { BLACKBIRD_AUDIO_BITS_LAYER_1_160, 160, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_160, 160, }, }, },
-	{ 192, { { BLACKBIRD_AUDIO_BITS_LAYER_1_192, 192, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_192, 192, }, }, },
-	{ 224, { { BLACKBIRD_AUDIO_BITS_LAYER_1_224, 224, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_224, 224, }, }, },
-	{ 256, { { BLACKBIRD_AUDIO_BITS_LAYER_1_256, 256, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_256, 256, }, }, },
-	{ 288, { { BLACKBIRD_AUDIO_BITS_LAYER_1_288, 288, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, },
-	{ 320, { { BLACKBIRD_AUDIO_BITS_LAYER_1_320, 320, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_320, 320, }, }, },
-	{ 352, { { BLACKBIRD_AUDIO_BITS_LAYER_1_352, 352, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-	{ 384, { { BLACKBIRD_AUDIO_BITS_LAYER_1_384, 384, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-	{ 416, { { BLACKBIRD_AUDIO_BITS_LAYER_1_416, 416, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-	{ 448, { { BLACKBIRD_AUDIO_BITS_LAYER_1_448, 448, }, { BLACKBIRD_AUDIO_BITS_LAYER_2_384, 384, }, }, },
-};
-static const int BITRATES_SIZE = ARRAY_SIZE(mpeg_audio_bitrates);
-
-static void blackbird_set_default_params(struct cx8802_dev *dev)
-{
-	struct v4l2_mpeg_compression *params = &dev->params;
-	u32 au_params;
-
-	/* assign stream type */
-	if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) )
-		params->st_type = V4L2_MPEG_PS_2;
-	if( params->st_type == V4L2_MPEG_SS_1 )
-		params->vi_type = V4L2_MPEG_VI_1;
-	else
-		params->vi_type = V4L2_MPEG_VI_2;
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]);
-
-	/* assign framerate */
-	if( params->vi_frame_rate <= 25 )
-	{
-		params->vi_frame_rate = 25;
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
-	}
-	else
-	{
-		params->vi_frame_rate = 30;
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30);
-	}
-
-	/* assign aspect ratio */
-	if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) )
-		params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3;
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]);
-
-	/* assign gop properties */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1);
-
-	/* assign gop closure */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops);
-
-	/* assign 3 2 pulldown */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown);
-
-	/* make sure the params are within bounds */
-	if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-		params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-	if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-		params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-	if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-		params->au_bitrate.mode = V4L2_BITRATE_NONE;
-
-	/* assign audio properties */
-	/* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
-	au_params = BLACKBIRD_AUDIO_BITS_STEREO |
-			/* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
-			BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
-			BLACKBIRD_AUDIO_BITS_CRC_OFF |
-			BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
-			BLACKBIRD_AUDIO_BITS_COPY |
-			0;
-	if( params->au_sample_rate <= 32000 )
-	{
-		params->au_sample_rate = 32000;
-		au_params |= BLACKBIRD_AUDIO_BITS_32000HZ;
-	}
-	else if( params->au_sample_rate <= 44100 )
-	{
-		params->au_sample_rate = 44100;
-		au_params |= BLACKBIRD_AUDIO_BITS_44100HZ;
-	}
-	else
-	{
-		params->au_sample_rate = 48000;
-		au_params |= BLACKBIRD_AUDIO_BITS_48000HZ;
-	}
-	if( params->au_type == V4L2_MPEG_AU_2_I )
-	{
-		au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1;
-	}
-	else
-	{
-		/* TODO: try to handle the other formats more gracefully */
-		params->au_type = V4L2_MPEG_AU_2_II;
-		au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2;
-	}
-	if( params->au_bitrate.mode )
-	{
-		int layer;
-
-		if( params->au_bitrate.mode == V4L2_BITRATE_CBR )
-			params->au_bitrate.max = params->vi_bitrate.target;
-		else
-			params->au_bitrate.target = params->vi_bitrate.max;
-
-		layer = params->au_type;
-		if( params->au_bitrate.target == 0 )
-		{
-			/* TODO: use the minimum possible bitrate instead of 0 ? */
-			au_params |= 0;
-		}
-		else if( params->au_bitrate.target >=
-			 mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate )
-		{
-			/* clamp the bitrate to the max supported by the standard */
-			params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate;
-			params->au_bitrate.max = params->au_bitrate.target;
-			au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits;
-		}
-		else
-		{
-			/* round up to the nearest supported bitrate */
-			int i;
-			for(i = 1; i < BITRATES_SIZE; i++)
-			{
-				if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate &&
-				    params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate )
-				{
-					params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate;
-					params->au_bitrate.max = params->au_bitrate.target;
-					au_params |= mpeg_audio_bitrates[i].layer[layer].bits;
-					break;
-				}
-			}
-		}
-	}
-	else
-	{
-		/* TODO: ??? */
-		params->au_bitrate.target = params->au_bitrate.max = 0;
-		au_params |= 0;
-	}
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params );
-
-	/* assign bitrates */
-	if( params->vi_bitrate.mode )
-	{
-		/* bitrate is set, let's figure out the cbr/vbr mess */
-		if( params->vi_bitrate.max < params->vi_bitrate.target )
-		{
-			if( params->vi_bitrate.mode == V4L2_BITRATE_CBR )
-				params->vi_bitrate.max = params->vi_bitrate.target;
-			else
-				params->vi_bitrate.target = params->vi_bitrate.max;
-		}
-	}
-	else
-	{
-		if( params->st_bitrate.max < params->st_bitrate.target )
-		{
-			if( params->st_bitrate.mode == V4L2_BITRATE_VBR )
-				params->st_bitrate.target = params->st_bitrate.max;
-			else
-				params->st_bitrate.max = params->st_bitrate.target;
-		}
-		/* calculate vi_bitrate = st_bitrate - au_bitrate */
-		params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max;
-		params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target;
-	}
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0,
-				mpeg_video_bitrates[params->vi_bitrate.mode],
-				params->vi_bitrate.target * 1000, /* kbps -> bps */
-				params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
-				BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
-
-	/* TODO: implement the stream ID stuff:
-		ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr,
-		ps_size, au_pesid, vi_pesid
-	*/
-}
-#define CHECK_PARAM( name ) ( dev->params.name != params->name )
-#define IF_PARAM( name ) if( CHECK_PARAM( name ) )
-#define UPDATE_PARAM( name ) dev->params.name = params->name
-void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression *params)
-{
-	u32 au_params;
-
-	/* assign stream type */
-	if( params->st_type >= ARRAY_SIZE(mpeg_stream_types) )
-		params->st_type = V4L2_MPEG_PS_2;
-	if( params->st_type == V4L2_MPEG_SS_1 )
-		params->vi_type = V4L2_MPEG_VI_1;
-	else
-		params->vi_type = V4L2_MPEG_VI_2;
-	if( CHECK_PARAM( st_type ) || CHECK_PARAM( vi_type ) )
-	{
-		UPDATE_PARAM( st_type );
-		UPDATE_PARAM( vi_type );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, mpeg_stream_types[params->st_type]);
-	}
-
-	/* assign framerate */
-	if( params->vi_frame_rate <= 25 )
-		params->vi_frame_rate = 25;
-	else
-		params->vi_frame_rate = 30;
-	IF_PARAM( vi_frame_rate )
-	{
-		UPDATE_PARAM( vi_frame_rate );
-		if( params->vi_frame_rate == 25 )
-			blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
-		else
-			blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_NTSC_30);
-	}
-
-	/* assign aspect ratio */
-	if( params->vi_aspect_ratio >= ARRAY_SIZE(mpeg_stream_ratios) )
-		params->vi_aspect_ratio = V4L2_MPEG_ASPECT_4_3;
-	IF_PARAM( vi_aspect_ratio )
-	{
-		UPDATE_PARAM( vi_aspect_ratio );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, mpeg_stream_ratios[params->vi_aspect_ratio]);
-	}
-
-	/* assign gop properties */
-	if( CHECK_PARAM( vi_frames_per_gop ) || CHECK_PARAM( vi_bframes_count ) )
-	{
-		UPDATE_PARAM( vi_frames_per_gop );
-		UPDATE_PARAM( vi_bframes_count );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, params->vi_frames_per_gop, params->vi_bframes_count+1);
-	}
-
-	/* assign gop closure */
-	IF_PARAM( closed_gops )
-	{
-		UPDATE_PARAM( closed_gops );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, params->closed_gops);
-	}
-
-	/* assign 3 2 pulldown */
-	IF_PARAM( pulldown )
-	{
-		UPDATE_PARAM( pulldown );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, params->pulldown);
-	}
-
-	/* make sure the params are within bounds */
-	if( params->st_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-		params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-	if( params->vi_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-		params->vi_bitrate.mode = V4L2_BITRATE_NONE;
-	if( params->au_bitrate.mode >= ARRAY_SIZE(mpeg_video_bitrates) )
-		params->au_bitrate.mode = V4L2_BITRATE_NONE;
-
-	/* assign audio properties */
-	/* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
-	au_params = BLACKBIRD_AUDIO_BITS_STEREO |
-			/* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
-	BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
-		BLACKBIRD_AUDIO_BITS_CRC_OFF |
-		BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
-		BLACKBIRD_AUDIO_BITS_COPY |
-		0;
-	if( params->au_sample_rate < 32000 )
-	{
-		params->au_sample_rate = 32000;
-		au_params |= BLACKBIRD_AUDIO_BITS_32000HZ;
-	}
-	else if( params->au_sample_rate < 44100 )
-	{
-		params->au_sample_rate = 44100;
-		au_params |= BLACKBIRD_AUDIO_BITS_44100HZ;
-	}
-	else
-	{
-		params->au_sample_rate = 48000;
-		au_params |= BLACKBIRD_AUDIO_BITS_48000HZ;
-	}
-	if( params->au_type == V4L2_MPEG_AU_2_I )
-	{
-		au_params |= BLACKBIRD_AUDIO_BITS_LAYER_1;
-	}
-	else
-	{
-		/* TODO: try to handle the other formats more gracefully */
-		params->au_type = V4L2_MPEG_AU_2_II;
-		au_params |= BLACKBIRD_AUDIO_BITS_LAYER_2;
-	}
-	if( params->au_bitrate.mode )
-	{
-		int layer;
-
-		if( params->au_bitrate.mode == V4L2_BITRATE_CBR )
-			params->au_bitrate.max = params->vi_bitrate.target;
-		else
-			params->au_bitrate.target = params->vi_bitrate.max;
-
-		layer = params->au_type;
-		if( params->au_bitrate.target == 0 )
-		{
-			/* TODO: use the minimum possible bitrate instead of 0 ? */
-			au_params |= 0;
-		}
-		else if( params->au_bitrate.target >=
-			 mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate )
-		{
-			/* clamp the bitrate to the max supported by the standard */
-			params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate;
-			params->au_bitrate.max = params->au_bitrate.target;
-			au_params |= mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].bits;
-		}
-		else
-		{
-			/* round up to the nearest supported bitrate */
-			int i;
-			for(i = 1; i < BITRATES_SIZE; i++)
-			{
-				if( params->au_bitrate.target > mpeg_audio_bitrates[i-1].layer[layer].rate &&
-				    params->au_bitrate.target <= mpeg_audio_bitrates[i].layer[layer].rate )
-				{
-					params->au_bitrate.target = mpeg_audio_bitrates[i].layer[layer].rate;
-					params->au_bitrate.max = params->au_bitrate.target;
-					au_params |= mpeg_audio_bitrates[i].layer[layer].bits;
-					break;
-				}
-			}
-		}
-	}
-	else
-	{
-		/* TODO: ??? */
-		params->au_bitrate.target = params->au_bitrate.max = 0;
-		au_params |= 0;
-	}
-	if( CHECK_PARAM( au_type ) || CHECK_PARAM( au_sample_rate )
-		|| CHECK_PARAM( au_bitrate.mode ) || CHECK_PARAM( au_bitrate.max )
-		|| CHECK_PARAM( au_bitrate.target )
-	)
-	{
-		UPDATE_PARAM( au_type );
-		UPDATE_PARAM( au_sample_rate );
-		UPDATE_PARAM( au_bitrate );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0, au_params );
-	}
-
-	/* assign bitrates */
-	if( params->vi_bitrate.mode )
-	{
-		/* bitrate is set, let's figure out the cbr/vbr mess */
-		if( params->vi_bitrate.max < params->vi_bitrate.target )
-		{
-			if( params->vi_bitrate.mode == V4L2_BITRATE_CBR )
-				params->vi_bitrate.max = params->vi_bitrate.target;
-			else
-				params->vi_bitrate.target = params->vi_bitrate.max;
-		}
-	}
-	else
-	{
-		if( params->st_bitrate.max < params->st_bitrate.target )
-		{
-			if( params->st_bitrate.mode == V4L2_BITRATE_VBR )
-				params->st_bitrate.target = params->st_bitrate.max;
-			else
-				params->st_bitrate.max = params->st_bitrate.target;
-		}
-		/* calculate vi_bitrate = st_bitrate - au_bitrate */
-		params->vi_bitrate.max = params->st_bitrate.max - params->au_bitrate.max;
-		params->vi_bitrate.target = params->st_bitrate.target - params->au_bitrate.target;
-	}
-	UPDATE_PARAM( st_bitrate );
-	if( CHECK_PARAM( vi_bitrate.mode ) || CHECK_PARAM( vi_bitrate.max )
-		|| CHECK_PARAM( vi_bitrate.target )
-	)
-	{
-		UPDATE_PARAM( vi_bitrate );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 4, 0,
-				mpeg_video_bitrates[params->vi_bitrate.mode],
-				params->vi_bitrate.target * 1000, /* kbps -> bps */
-				params->vi_bitrate.max * 1000 / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
-				BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
-	}
-
-	/* TODO: implement the stream ID stuff:
-		ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr,
-		ps_size, au_pesid, vi_pesid
-	*/
-	UPDATE_PARAM( ts_pid_pmt );
-	UPDATE_PARAM( ts_pid_audio );
-	UPDATE_PARAM( ts_pid_video );
-	UPDATE_PARAM( ts_pid_pcr );
-	UPDATE_PARAM( ps_size );
-	UPDATE_PARAM( au_pesid );
-	UPDATE_PARAM( vi_pesid );
-}
-
-static void blackbird_set_default_dnr_params(struct cx8802_dev *dev)
-{
-	/* assign dnr filter mode */
-	if( dev->dnr_params.mode > BLACKBIRD_DNR_BITS_AUTO )
-		dev->dnr_params.mode = BLACKBIRD_DNR_BITS_MANUAL;
-	if( dev->dnr_params.type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL )
-		dev->dnr_params.type = BLACKBIRD_MEDIAN_FILTER_DISABLED;
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0,
-				dev->dnr_params.mode,
-				dev->dnr_params.type
-			);
-
-	/* assign dnr filter props*/
-	if( dev->dnr_params.spatial > 15 )
-		dev->dnr_params.spatial = 15;
-	if( dev->dnr_params.temporal > 31 )
-		dev->dnr_params.temporal = 31;
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0,
-				dev->dnr_params.spatial,
-				dev->dnr_params.temporal
-			);
-}
-#define CHECK_DNR_PARAM( name ) ( dev->dnr_params.name != dnr_params->name )
-#define UPDATE_DNR_PARAM( name ) dev->dnr_params.name = dnr_params->name
-void blackbird_set_dnr_params(struct cx8802_dev *dev, struct blackbird_dnr* dnr_params)
-{
-	/* assign dnr filter mode */
-	/* clamp values */
-	if( dnr_params->mode > BLACKBIRD_DNR_BITS_AUTO )
-		dnr_params->mode = BLACKBIRD_DNR_BITS_MANUAL;
-	if( dnr_params->type > BLACKBIRD_MEDIAN_FILTER_DIAGONAL )
-		dnr_params->type = BLACKBIRD_MEDIAN_FILTER_DISABLED;
-	/* check if the params actually changed */
-	if( CHECK_DNR_PARAM( mode ) || CHECK_DNR_PARAM( type ) )
-	{
-		UPDATE_DNR_PARAM( mode );
-		UPDATE_DNR_PARAM( type );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0, dnr_params->mode, dnr_params->type);
-	}
-
-	/* assign dnr filter props*/
-	if( dnr_params->spatial > 15 )
-		dnr_params->spatial = 15;
-	if( dnr_params->temporal > 31 )
-		dnr_params->temporal = 31;
-	if( CHECK_DNR_PARAM( spatial ) || CHECK_DNR_PARAM( temporal ) )
-	{
-		UPDATE_DNR_PARAM( spatial );
-		UPDATE_DNR_PARAM( temporal );
-		blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, dnr_params->spatial, dnr_params->temporal);
-	}
-}
-
-static void blackbird_codec_settings(struct cx8802_dev *dev)
-{
-
-	/* assign output port */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
-
-	/* assign frame size */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0,
-				dev->height, dev->width);
-
-	/* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255);
-
-	/* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0,
-				BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
-				BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ
-			);
-
-	/* assign frame drop rate */
-	/* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */
-
-	blackbird_set_default_params(dev);
-	blackbird_set_default_dnr_params(dev);
-}
-
 static int blackbird_initialize_codec(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
@@ -1248,7 +568,7 @@
 	int retval;
 
 	dprintk(1,"Initialize codec\n");
-	retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
+	retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
 	if (retval < 0) {
 		/* ping was not successful, reset and upload firmware */
 		cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
@@ -1263,13 +583,13 @@
 		if (dev->mailbox < 0)
 			return -1;
 
-		retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
+		retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
 		if (retval < 0) {
 			dprintk(0, "ERROR: Firmware ping failed!\n");
 			return -1;
 		}
 
-		retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version);
+		retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
 		if (retval < 0) {
 			dprintk(0, "ERROR: Firmware get encoder version failed!\n");
 			return -1;
@@ -1289,35 +609,35 @@
 	/* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
 	   blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
 	   blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0,
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
 			BLACKBIRD_FIELD1_SAA7115,
-			BLACKBIRD_FIELD1_SAA7115
+			BLACKBIRD_FIELD2_SAA7115
 		);
 
 	/* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */
-	blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0,
+	blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
 			BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
 	/* initialize the video input */
-	blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0);
+	blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
 
 	msleep(1);
 
-	blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
+	blackbird_api_cmd(dev, CX2341X_ENC_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
 	msleep(1);
-	blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
+	blackbird_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
 	msleep(1);
 
 	/* start capturing to the host interface */
-	/* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); */
-	blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
+	/* blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, 0, 0x13); */
+	blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
 			BLACKBIRD_MPEG_CAPTURE,
 			BLACKBIRD_RAW_BITS_NONE
 		);
 	msleep(10);
 
-	blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
+	blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0,0);
 	return 0;
 }
 
@@ -1485,27 +805,74 @@
 	{
 		struct v4l2_mpeg_compression *f = arg;
 
-		memcpy(f,&dev->params,sizeof(*f));
+		printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
+				    "Replace with VIDIOC_G_EXT_CTRLS!");
+		memcpy(f,&default_mpeg_params,sizeof(*f));
 		return 0;
 	}
 	case VIDIOC_S_MPEGCOMP:
+		printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
+				    "Replace with VIDIOC_S_EXT_CTRLS!");
+		return 0;
+	case VIDIOC_G_EXT_CTRLS:
 	{
-		struct v4l2_mpeg_compression *f = arg;
+		struct v4l2_ext_controls *f = arg;
 
-		blackbird_set_params(dev, f);
+		if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+			return -EINVAL;
+		return cx2341x_ext_ctrls(&dev->params, f, cmd);
+	}
+	case VIDIOC_S_EXT_CTRLS:
+	case VIDIOC_TRY_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *f = arg;
+		struct cx2341x_mpeg_params p;
+		int err;
+
+		if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+			return -EINVAL;
+		p = dev->params;
+		err = cx2341x_ext_ctrls(&p, f, cmd);
+		if (err == 0 && cmd == VIDIOC_S_EXT_CTRLS) {
+			err = cx2341x_update(dev, blackbird_mbox_func, &dev->params, &p);
+			dev->params = p;
+		}
+		return err;
+	}
+	case VIDIOC_S_FREQUENCY:
+	{
+		blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
+				  BLACKBIRD_END_NOW,
+				  BLACKBIRD_MPEG_CAPTURE,
+				  BLACKBIRD_RAW_BITS_NONE);
+
+		cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
+
+		blackbird_initialize_codec(dev);
+		cx88_set_scale(dev->core, dev->width, dev->height,
+			       fh->mpegq.field);
+		return 0;
+	}
+	case VIDIOC_LOG_STATUS:
+	{
+		char name[32 + 2];
+
+		snprintf(name, sizeof(name), "%s/2", core->name);
+		printk("%s/2: ============  START LOG STATUS  ============\n",
+		       core->name);
+		cx88_call_i2c_clients(core, VIDIOC_LOG_STATUS, 0);
+		cx2341x_log_status(&dev->params, name);
+		printk("%s/2: =============  END LOG STATUS  =============\n",
+		       core->name);
 		return 0;
 	}
 
 	default:
-		return cx88_do_ioctl( inode, file, 0, dev->core, cmd, arg, cx88_ioctl_hook );
+		return cx88_do_ioctl(inode, file, 0, dev->core, cmd, arg, mpeg_do_ioctl);
 	}
 	return 0;
 }
 
-int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
-			unsigned int cmd, void *arg);
-unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
-
 static unsigned int mpeg_translate_ioctl(unsigned int cmd)
 {
 	return cmd;
@@ -1514,8 +881,8 @@
 static int mpeg_ioctl(struct inode *inode, struct file *file,
 			unsigned int cmd, unsigned long arg)
 {
-	cmd = cx88_ioctl_translator( cmd );
-	return video_usercopy(inode, file, cmd, arg, cx88_ioctl_hook);
+	cmd = mpeg_translate_ioctl( cmd );
+	return video_usercopy(inode, file, cmd, arg, mpeg_do_ioctl);
 }
 
 static int mpeg_open(struct inode *inode, struct file *file)
@@ -1562,13 +929,14 @@
 {
 	struct cx8802_fh  *fh  = file->private_data;
 
-	/* blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
-	blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0,
+	/* blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
+	blackbird_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
 			BLACKBIRD_END_NOW,
 			BLACKBIRD_MPEG_CAPTURE,
 			BLACKBIRD_RAW_BITS_NONE
 		);
 
+	cx8802_cancel_buffers(fh->dev);
 	/* stop mpeg capture */
 	if (fh->mpegq.streaming)
 		videobuf_streamoff(&fh->mpegq);
@@ -1683,19 +1051,13 @@
 	dev->core = core;
 	dev->width = 720;
 	dev->height = 576;
-	memcpy(&dev->params,&default_mpeg_params,sizeof(default_mpeg_params));
-	memcpy(&dev->dnr_params,&default_dnr_params,sizeof(default_dnr_params));
+	cx2341x_fill_defaults(&dev->params);
+	dev->params.port = CX2341X_PORT_STREAMING;
 
-	if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN) {
-
-		if (core->tuner_formats & V4L2_STD_525_60) {
-			dev->height = 480;
-			dev->params.vi_frame_rate = 30;
-		} else {
-			dev->height = 576;
-			dev->params.vi_frame_rate = 25;
-		}
-
+	if (core->tvnorm->id & V4L2_STD_525_60) {
+		dev->height = 480;
+	} else {
+		dev->height = 576;
 	}
 
 	err = cx8802_init_common(dev);
@@ -1766,8 +1128,6 @@
 	printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n",
 	       SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
 #endif
-	cx88_ioctl_hook = mpeg_do_ioctl;
-	cx88_ioctl_translator = mpeg_translate_ioctl;
 	return pci_register_driver(&blackbird_pci_driver);
 }
 
@@ -1779,11 +1139,6 @@
 module_init(blackbird_init);
 module_exit(blackbird_fini);
 
-EXPORT_SYMBOL(cx88_ioctl_hook);
-EXPORT_SYMBOL(cx88_ioctl_translator);
-EXPORT_SYMBOL(blackbird_set_params);
-EXPORT_SYMBOL(blackbird_set_dnr_params);
-
 /* ----------------------------------------------------------- */
 /*
  * Local variables:
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index f80154b..f9d68f2 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -114,7 +114,7 @@
 		.radio = {
 			 .type  = CX88_RADIO,
 			 .gpio0 = 0xff10,
-		 },
+		},
 	},
 	[CX88_BOARD_ATI_WONDER_PRO] = {
 		.name           = "ATI TV Wonder Pro",
@@ -267,7 +267,7 @@
 			.gpio1  = 0x00007004,
 			.gpio2  = 0x0035d700,
 			.gpio3  = 0x02000000,
-		 },
+		},
 	},
 	[CX88_BOARD_LEADTEK_PVR2000] = {
 		// gpio values for PAL version from regspy by DScaler
@@ -413,7 +413,7 @@
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
 			.gpio0  = 0x000027df,
-		 },{
+		},{
 			.type   = CX88_VMUX_SVIDEO,
 			.vmux   = 2,
 			.gpio0  = 0x000027df,
@@ -536,7 +536,7 @@
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
 			.gpio0  = 0x000027df,
-		 },{
+		},{
 			.type   = CX88_VMUX_SVIDEO,
 			.vmux   = 2,
 			.gpio0  = 0x000027df,
@@ -759,7 +759,7 @@
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD] = {
 		.name           = "DViCO FusionHDTV 5 Gold",
-		.tuner_type     = TUNER_LG_TDVS_H062F,
+		.tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H062F */
 		.radio_type     = UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
@@ -1050,11 +1050,7 @@
 		.dvb            = 1,
 	},
 	[CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT] = {
-		/* FIXME: Standard video using the cx88 broadcast decoder is
-		 * working, but blackbird isn't working yet, audio is only
-		 * working correctly for television mode. S-Video and Composite
-		 * are working for video-only, so I have them disabled for now.
-		 */
+		/* FIXME: Audio not working for s-video / composite inputs. */
 		.name           = "KWorld HardwareMpegTV XPert",
 		.tuner_type     = TUNER_PHILIPS_TDA8290,
 		.radio_type     = UNSET,
@@ -1065,12 +1061,21 @@
 			.vmux   = 0,
 			.gpio0  = 0x3de2,
 			.gpio2  = 0x00ff,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x3de6,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x3de6,
 		}},
 		.radio = {
 			.type   = CX88_RADIO,
 			.gpio0  = 0x3de6,
 			.gpio2  = 0x00ff,
 		},
+		.blackbird      = 1,
 	},
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID] = {
 		.name           = "DViCO FusionHDTV DVB-T Hybrid",
@@ -1093,7 +1098,102 @@
 		}},
 		.dvb            = 1,
 	},
-
+	[CX88_BOARD_PCHDTV_HD5500] = {
+		.name           = "pcHDTV HD5500 HDTV",
+		.tuner_type     = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x87fd,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x87f9,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x87f9,
+		}},
+		.dvb            = 1,
+	},
+	[CX88_BOARD_KWORLD_MCE200_DELUXE] = {
+		/* FIXME: tested TV input only, disabled composite,
+		   svideo and radio until they can be tested also. */
+		.name           = "Kworld MCE 200 Deluxe",
+		.tuner_type     = TUNER_TENA_9533_DI,
+		.radio_type     = UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0000BDE6
+		}},
+		.blackbird = 1,
+	},
+	[CX88_BOARD_PIXELVIEW_PLAYTV_P7000] = {
+		/* FIXME: SVideo, Composite and FM inputs are untested */
+		.name           = "PixelView PlayTV P7000",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT | TDA9887_PORT1_ACTIVE |
+				  TDA9887_PORT2_ACTIVE,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x5da6,
+		}},
+		.blackbird = 1,
+	},
+	[CX88_BOARD_NPGTECH_REALTV_TOP10FM] = {
+		.name           = "NPG Tech Real TV FM Top 10",
+		.tuner_type     = TUNER_TNF_5335MF, /* Actually a TNF9535 */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0	= 0x0788,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0x078b,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0x078b,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0x074a,
+		},
+	},
+	[CX88_BOARD_WINFAST_DTV2000H] = {
+		/* video inputs and radio still in testing */
+		.name           = "WinFast DTV2000 H",
+		.tuner_type     = TUNER_PHILIPS_FMD1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x00017304,
+			.gpio1  = 0x00008203,
+			.gpio2  = 0x00017304,
+			.gpio3  = 0x02000000,
+		}},
+		.dvb            = 1,
+	},
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -1311,6 +1411,34 @@
 		.subvendor = 0x18ac,
 		.subdevice = 0xdb44,
 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID,
+	},{
+		.subvendor = 0x7063,
+		.subdevice = 0x5500,
+		.card      = CX88_BOARD_PCHDTV_HD5500,
+	},{
+		.subvendor = 0x17de,
+		.subdevice = 0x0841,
+		.card      = CX88_BOARD_KWORLD_MCE200_DELUXE,
+	},{
+		.subvendor = 0x1822,
+		.subdevice = 0x0019,
+		.card      = CX88_BOARD_DNTV_LIVE_DVB_T_PRO,
+	},{
+		.subvendor = 0x1554,
+		.subdevice = 0x4813,
+		.card      = CX88_BOARD_PIXELVIEW_PLAYTV_P7000,
+	},{
+		.subvendor = 0x14f1,
+		.subdevice = 0x0842,
+		.card      = CX88_BOARD_NPGTECH_REALTV_TOP10FM,
+	},{
+		.subvendor = 0x107d,
+		.subdevice = 0x665e,
+		.card      = CX88_BOARD_WINFAST_DTV2000H,
+	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xd800, /* FusionHDTV 3 Gold (original revision) */
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q,
 	},
 };
 const unsigned int cx88_idcount = ARRAY_SIZE(cx88_subids);
@@ -1572,11 +1700,6 @@
 /* ------------------------------------------------------------------ */
 
 EXPORT_SYMBOL(cx88_boards);
-EXPORT_SYMBOL(cx88_bcount);
-EXPORT_SYMBOL(cx88_subids);
-EXPORT_SYMBOL(cx88_idcount);
-EXPORT_SYMBOL(cx88_card_list);
-EXPORT_SYMBOL(cx88_card_setup);
 
 /*
  * Local variables:
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index e1092d5..26f4c0f 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -677,7 +677,7 @@
 
 static unsigned int inline norm_vbipack(struct cx88_tvnorm *norm)
 {
-	return (norm->id & V4L2_STD_625_50) ? 511 : 288;
+	return (norm->id & V4L2_STD_625_50) ? 511 : 400;
 }
 
 int cx88_set_scale(struct cx88_core *core, unsigned int width, unsigned int height,
@@ -932,9 +932,9 @@
 		htotal, cx_read(MO_HTOTAL), (u32)tmp64);
 	cx_write(MO_HTOTAL, htotal);
 
-	// vbi stuff
-	cx_write(MO_VBI_PACKET, ((1 << 11) | /* (norm_vdelay(norm)   << 11) | */
-				 norm_vbipack(norm)));
+	// vbi stuff, set vbi offset to 10 (for 20 Clk*2 pixels), this makes
+	// the effective vbi offset ~244 samples, the same as the Bt8x8
+	cx_write(MO_VBI_PACKET, (10<<11) | norm_vbipack(norm));
 
 	// this is needed as well to set all tvnorm parameter
 	cx88_set_scale(core, 320, 240, V4L2_FIELD_INTERLACED);
@@ -1181,8 +1181,6 @@
 EXPORT_SYMBOL(cx88_vdev_init);
 EXPORT_SYMBOL(cx88_core_get);
 EXPORT_SYMBOL(cx88_core_put);
-EXPORT_SYMBOL(cx88_start_audio_dma);
-EXPORT_SYMBOL(cx88_stop_audio_dma);
 
 /*
  * Local variables:
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 3619a44..dce1fed 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -51,6 +51,7 @@
 #endif
 #ifdef HAVE_LGDT330X
 # include "lgdt330x.h"
+# include "lg_h06xf.h"
 #endif
 #ifdef HAVE_NXT200X
 # include "nxt200x.h"
@@ -58,6 +59,7 @@
 #ifdef HAVE_CX24123
 # include "cx24123.h"
 #endif
+#include "isl6421.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -113,21 +115,6 @@
 
 /* ------------------------------------------------------------------ */
 
-#if defined(HAVE_MT352) || defined(HAVE_ZL10353)
-static int zarlink_pll_set(struct dvb_frontend *fe,
-			      struct dvb_frontend_parameters *params,
-			      u8 *pllbuf)
-{
-	struct cx8802_dev *dev = fe->dvb->priv;
-
-	pllbuf[0] = dev->core->pll_addr << 1;
-	dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
-			  params->frequency,
-			  params->u.ofdm.bandwidth);
-	return 0;
-}
-#endif
-
 #ifdef HAVE_MT352
 static int dvico_fusionhdtv_demod_init(struct dvb_frontend* fe)
 {
@@ -196,19 +183,16 @@
 static struct mt352_config dvico_fusionhdtv = {
 	.demod_address = 0x0F,
 	.demod_init    = dvico_fusionhdtv_demod_init,
-	.pll_set       = zarlink_pll_set,
 };
 
 static struct mt352_config dntv_live_dvbt_config = {
 	.demod_address = 0x0f,
 	.demod_init    = dntv_live_dvbt_demod_init,
-	.pll_set       = zarlink_pll_set,
 };
 
 static struct mt352_config dvico_fusionhdtv_dual = {
 	.demod_address = 0x0F,
 	.demod_init    = dvico_dual_demod_init,
-	.pll_set       = zarlink_pll_set,
 };
 
 #ifdef HAVE_VP3054_I2C
@@ -246,6 +230,8 @@
 		  .buf = fmd1216_init, .len = sizeof(fmd1216_init) };
 	int err;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
 		if (err < 0)
 			return err;
@@ -256,14 +242,14 @@
 	return 0;
 }
 
-static int dntv_live_dvbt_pro_pll_set(struct dvb_frontend* fe,
-				      struct dvb_frontend_parameters* params,
-				      u8* pllbuf)
+static int dntv_live_dvbt_pro_tuner_set_params(struct dvb_frontend* fe,
+					       struct dvb_frontend_parameters* params)
 {
 	struct cx8802_dev *dev= fe->dvb->priv;
+	u8 buf[4];
 	struct i2c_msg msg =
 		{ .addr = dev->core->pll_addr, .flags = 0,
-		  .buf = pllbuf+1, .len = 4 };
+		  .buf = buf, .len = 4 };
 	int err;
 
 	/* Switch PLL to DVB mode */
@@ -272,14 +258,16 @@
 		return err;
 
 	/* Tune PLL */
-	pllbuf[0] = dev->core->pll_addr << 1;
-	dvb_pll_configure(dev->core->pll_desc, pllbuf+1,
+	dvb_pll_configure(dev->core->pll_desc, buf,
 			  params->frequency,
 			  params->u.ofdm.bandwidth);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
+
 		printk(KERN_WARNING "cx88-dvb: %s error "
 			   "(addr %02x <- %02x, err = %i)\n",
-			   __FUNCTION__, pllbuf[0], pllbuf[1], err);
+			   __FUNCTION__, dev->core->pll_addr, buf[0], err);
 		if (err < 0)
 			return err;
 		else
@@ -293,27 +281,27 @@
 	.demod_address = 0x0f,
 	.no_tuner      = 1,
 	.demod_init    = dntv_live_dvbt_pro_demod_init,
-	.pll_set       = dntv_live_dvbt_pro_pll_set,
 };
 #endif
 #endif
 
 #ifdef HAVE_ZL10353
-static int dvico_hybrid_tune_pll(struct dvb_frontend *fe,
-				 struct dvb_frontend_parameters *params,
-				 u8 *pllbuf)
+static int dvico_hybrid_tuner_set_params(struct dvb_frontend *fe,
+					 struct dvb_frontend_parameters *params)
 {
+	u8 pllbuf[4];
 	struct cx8802_dev *dev= fe->dvb->priv;
 	struct i2c_msg msg =
 		{ .addr = dev->core->pll_addr, .flags = 0,
-		  .buf = pllbuf + 1, .len = 4 };
+		  .buf = pllbuf, .len = 4 };
 	int err;
 
-	pllbuf[0] = dev->core->pll_addr << 1;
-	dvb_pll_configure(dev->core->pll_desc, pllbuf + 1,
+	dvb_pll_configure(dev->core->pll_desc, pllbuf,
 			  params->frequency,
 			  params->u.ofdm.bandwidth);
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if ((err = i2c_transfer(&dev->core->i2c_adap, &msg, 1)) != 1) {
 		printk(KERN_WARNING "cx88-dvb: %s error "
 			   "(addr %02x <- %02x, err = %i)\n",
@@ -329,12 +317,11 @@
 
 static struct zl10353_config dvico_fusionhdtv_hybrid = {
 	.demod_address = 0x0F,
-	.pll_set       = dvico_hybrid_tune_pll,
+	.no_tuner      = 1,
 };
 
 static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = {
 	.demod_address = 0x0F,
-	.pll_set       = zarlink_pll_set,
 };
 #endif
 
@@ -342,21 +329,15 @@
 static struct cx22702_config connexant_refboard_config = {
 	.demod_address = 0x43,
 	.output_mode   = CX22702_SERIAL_OUTPUT,
-	.pll_address   = 0x60,
-	.pll_desc      = &dvb_pll_thomson_dtt7579,
 };
 
 static struct cx22702_config hauppauge_novat_config = {
 	.demod_address = 0x43,
 	.output_mode   = CX22702_SERIAL_OUTPUT,
-	.pll_address   = 0x61,
-	.pll_desc      = &dvb_pll_thomson_dtt759x,
 };
 static struct cx22702_config hauppauge_hvr1100_config = {
 	.demod_address = 0x63,
 	.output_mode   = CX22702_SERIAL_OUTPUT,
-	.pll_address   = 0x61,
-	.pll_desc      = &dvb_pll_fmd1216me,
 };
 #endif
 
@@ -371,15 +352,13 @@
 
 static struct or51132_config pchdtv_hd3000 = {
 	.demod_address    = 0x15,
-	.pll_address      = 0x61,
-	.pll_desc         = &dvb_pll_thomson_dtt761x,
 	.set_ts_params    = or51132_set_ts_param,
 };
 #endif
 
 #ifdef HAVE_LGDT330X
-static int lgdt330x_pll_set(struct dvb_frontend* fe,
-			    struct dvb_frontend_parameters* params)
+static int lgdt3302_tuner_set_params(struct dvb_frontend* fe,
+				     struct dvb_frontend_parameters* params)
 {
 	/* FIXME make this routine use the tuner-simple code.
 	 * It could probably be shared with a number of ATSC
@@ -392,12 +371,12 @@
 		{ .addr = dev->core->pll_addr, .flags = 0, .buf = buf, .len = 4 };
 	int err;
 
-	/* Put the analog decoder in standby to keep it quiet */
-	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
-
 	dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
 	dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n",
 			__FUNCTION__, msg.addr, buf[0],buf[1],buf[2],buf[3]);
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if ((err = i2c_transfer(&core->i2c_adap, &msg, 1)) != 1) {
 		printk(KERN_WARNING "cx88-dvb: %s error "
 			   "(addr %02x <- %02x, err = %i)\n",
@@ -407,16 +386,21 @@
 		else
 			return -EREMOTEIO;
 	}
-	if (core->tuner_type == TUNER_LG_TDVS_H062F) {
-		/* Set the Auxiliary Byte. */
-		buf[2] &= ~0x20;
-		buf[2] |= 0x18;
-		buf[3] = 0x50;
-		i2c_transfer(&core->i2c_adap, &msg, 1);
-	}
 	return 0;
 }
 
+static int lgdt3303_tuner_set_params(struct dvb_frontend* fe,
+				     struct dvb_frontend_parameters* params)
+{
+	struct cx8802_dev *dev= fe->dvb->priv;
+	struct cx88_core *core = dev->core;
+
+	/* Put the analog decoder in standby to keep it quiet */
+	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
+	return lg_h06xf_pll_set(fe, &core->i2c_adap, params);
+}
+
 static int lgdt330x_pll_rf_set(struct dvb_frontend* fe, int index)
 {
 	struct cx8802_dev *dev= fe->dvb->priv;
@@ -444,7 +428,6 @@
 	.demod_address    = 0x0e,
 	.demod_chip       = LGDT3302,
 	.serial_mpeg      = 0x04, /* TPSERIAL for 3302 in TOP_CONTROL */
-	.pll_set          = lgdt330x_pll_set,
 	.set_ts_params    = lgdt330x_set_ts_param,
 };
 
@@ -452,7 +435,13 @@
 	.demod_address    = 0x0e,
 	.demod_chip       = LGDT3303,
 	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
-	.pll_set          = lgdt330x_pll_set,
+	.set_ts_params    = lgdt330x_set_ts_param,
+};
+
+static struct lgdt330x_config pchdtv_hd5500 = {
+	.demod_address    = 0x59,
+	.demod_chip       = LGDT3303,
+	.serial_mpeg      = 0x40, /* TPSERIAL for 3303 in TOP_CONTROL */
 	.set_ts_params    = lgdt330x_set_ts_param,
 };
 #endif
@@ -477,8 +466,6 @@
 
 static struct nxt200x_config ati_hdtvwonder = {
 	.demod_address    = 0x0a,
-	.pll_address      = 0x61,
-	.pll_desc         = &dvb_pll_tuv1236d,
 	.set_pll_input    = nxt200x_set_pll_input,
 	.set_ts_params    = nxt200x_set_ts_param,
 };
@@ -493,28 +480,30 @@
 	return 0;
 }
 
-static void cx24123_enable_lnb_voltage(struct dvb_frontend* fe, int on)
+static int kworld_dvbs_100_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
 {
 	struct cx8802_dev *dev= fe->dvb->priv;
 	struct cx88_core *core = dev->core;
 
-	if (on)
-		cx_write(MO_GP0_IO, 0x000006f9);
-	else
+	if (voltage == SEC_VOLTAGE_OFF) {
 		cx_write(MO_GP0_IO, 0x000006fB);
+	} else {
+		cx_write(MO_GP0_IO, 0x000006f9);
+	}
+
+	if (core->prev_set_voltage)
+		return core->prev_set_voltage(fe, voltage);
+	return 0;
 }
 
 static struct cx24123_config hauppauge_novas_config = {
 	.demod_address		= 0x55,
-	.use_isl6421		= 1,
 	.set_ts_params		= cx24123_set_ts_param,
 };
 
 static struct cx24123_config kworld_dvbs_100_config = {
 	.demod_address		= 0x15,
-	.use_isl6421		= 0,
 	.set_ts_params		= cx24123_set_ts_param,
-	.enable_lnb_voltage	= cx24123_enable_lnb_voltage,
 };
 #endif
 
@@ -530,6 +519,11 @@
 	case CX88_BOARD_HAUPPAUGE_DVB_T1:
 		dev->dvb.frontend = cx22702_attach(&hauppauge_novat_config,
 						   &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_thomson_dtt759x);
+		}
 		break;
 	case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1:
 	case CX88_BOARD_CONEXANT_DVB_T1:
@@ -537,44 +531,92 @@
 	case CX88_BOARD_WINFAST_DTV1000:
 		dev->dvb.frontend = cx22702_attach(&connexant_refboard_config,
 						   &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x60,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_thomson_dtt7579);
+		}
 		break;
+	case CX88_BOARD_WINFAST_DTV2000H:
 	case CX88_BOARD_HAUPPAUGE_HVR1100:
 	case CX88_BOARD_HAUPPAUGE_HVR1100LP:
 		dev->dvb.frontend = cx22702_attach(&hauppauge_hvr1100_config,
 						   &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_fmd1216me);
+		}
 		break;
 #endif
 #if defined(HAVE_MT352) || defined(HAVE_ZL10353)
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS:
-		dev->core->pll_addr = 0x60;
-		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
 #ifdef HAVE_MT352
 		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
 						 &dev->core->i2c_adap);
-		if (dev->dvb.frontend != NULL)
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x60,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_thomson_dtt7579);
 			break;
+		}
 #endif
 #ifdef HAVE_ZL10353
 		/* ZL10353 replaces MT352 on later cards */
 		dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
 						   &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x60,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_thomson_dtt7579);
+		}
+#endif
+		break;
+	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
+#ifdef HAVE_MT352
+		/* The tin box says DEE1601, but it seems to be DTT7579
+		 * compatible, with a slightly different MT352 AGC gain. */
+		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
+						 &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_thomson_dtt7579);
+			break;
+		}
+#endif
+#ifdef HAVE_ZL10353
+		/* ZL10353 replaces MT352 on later cards */
+		dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_plus_v1_1,
+						   &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_thomson_dtt7579);
+		}
 #endif
 		break;
 #endif /* HAVE_MT352 || HAVE_ZL10353 */
 #ifdef HAVE_MT352
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1:
-		dev->core->pll_addr = 0x61;
-		dev->core->pll_desc = &dvb_pll_lg_z201;
 		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv,
 						 &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_lg_z201);
+		}
 		break;
 	case CX88_BOARD_KWORLD_DVB_T:
 	case CX88_BOARD_DNTV_LIVE_DVB_T:
 	case CX88_BOARD_ADSTECH_DVB_T_PCI:
-		dev->core->pll_addr = 0x61;
-		dev->core->pll_desc = &dvb_pll_unknown_1;
 		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_config,
 						 &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_unknown_1);
+		}
 		break;
 	case CX88_BOARD_DNTV_LIVE_DVB_T_PRO:
 #ifdef HAVE_VP3054_I2C
@@ -582,18 +624,13 @@
 		dev->core->pll_desc = &dvb_pll_fmd1216me;
 		dev->dvb.frontend = mt352_attach(&dntv_live_dvbt_pro_config,
 			&((struct vp3054_i2c_state *)dev->card_priv)->adap);
+		if (dev->dvb.frontend != NULL) {
+			dev->dvb.frontend->ops.tuner_ops.set_params = dntv_live_dvbt_pro_tuner_set_params;
+		}
 #else
 		printk("%s: built without vp3054 support\n", dev->core->name);
 #endif
 		break;
-	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL:
-		/* The tin box says DEE1601, but it seems to be DTT7579
-		 * compatible, with a slightly different MT352 AGC gain. */
-		dev->core->pll_addr = 0x61;
-		dev->core->pll_desc = &dvb_pll_thomson_dtt7579;
-		dev->dvb.frontend = mt352_attach(&dvico_fusionhdtv_dual,
-						 &dev->core->i2c_adap);
-		break;
 #endif
 #ifdef HAVE_ZL10353
 	case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID:
@@ -601,12 +638,20 @@
 		dev->core->pll_desc = &dvb_pll_thomson_fe6600;
 		dev->dvb.frontend = zl10353_attach(&dvico_fusionhdtv_hybrid,
 						   &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dev->dvb.frontend->ops.tuner_ops.set_params = dvico_hybrid_tuner_set_params;
+		}
 		break;
 #endif
 #ifdef HAVE_OR51132
 	case CX88_BOARD_PCHDTV_HD3000:
 		dev->dvb.frontend = or51132_attach(&pchdtv_hd3000,
 						 &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_thomson_dtt761x);
+		}
 		break;
 #endif
 #ifdef HAVE_LGDT330X
@@ -627,6 +672,9 @@
 		dev->core->pll_desc = &dvb_pll_microtune_4042;
 		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
 						    &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+		}
 		}
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
@@ -643,6 +691,9 @@
 		dev->core->pll_desc = &dvb_pll_thomson_dtt761x;
 		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_3_gold,
 						    &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3302_tuner_set_params;
+		}
 		}
 		break;
 	case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
@@ -655,10 +706,28 @@
 		mdelay(100);
 		cx_set(MO_GP0_IO, 1);
 		mdelay(200);
-		dev->core->pll_addr = 0x61;
-		dev->core->pll_desc = &dvb_pll_tdvs_tua6034;
 		dev->dvb.frontend = lgdt330x_attach(&fusionhdtv_5_gold,
 						    &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+		}
+		}
+		break;
+	case CX88_BOARD_PCHDTV_HD5500:
+		dev->ts_gen_cntrl = 0x08;
+		{
+		/* Do a hardware reset of chip before using it. */
+		struct cx88_core *core = dev->core;
+
+		cx_clear(MO_GP0_IO, 1);
+		mdelay(100);
+		cx_set(MO_GP0_IO, 1);
+		mdelay(200);
+		dev->dvb.frontend = lgdt330x_attach(&pchdtv_hd5500,
+						    &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dev->dvb.frontend->ops.tuner_ops.set_params = lgdt3303_tuner_set_params;
+		}
 		}
 		break;
 #endif
@@ -666,6 +735,11 @@
 	case CX88_BOARD_ATI_HDTVWONDER:
 		dev->dvb.frontend = nxt200x_attach(&ati_hdtvwonder,
 						 &dev->core->i2c_adap);
+		if (dev->dvb.frontend != NULL) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61,
+				       &dev->core->i2c_adap,
+				       &dvb_pll_tuv1236d);
+		}
 		break;
 #endif
 #ifdef HAVE_CX24123
@@ -673,10 +747,18 @@
 	case CX88_BOARD_HAUPPAUGE_NOVASE2_S1:
 		dev->dvb.frontend = cx24123_attach(&hauppauge_novas_config,
 			&dev->core->i2c_adap);
+		if (dev->dvb.frontend) {
+			isl6421_attach(dev->dvb.frontend, &dev->core->i2c_adap,
+				       0x08, 0x00, 0x00);
+		}
 		break;
 	case CX88_BOARD_KWORLD_DVBS_100:
 		dev->dvb.frontend = cx24123_attach(&kworld_dvbs_100_config,
 			&dev->core->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage;
+			dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage;
+		}
 		break;
 #endif
 	default:
@@ -690,15 +772,15 @@
 	}
 
 	if (dev->core->pll_desc) {
-		dev->dvb.frontend->ops->info.frequency_min = dev->core->pll_desc->min;
-		dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
+		dev->dvb.frontend->ops.info.frequency_min = dev->core->pll_desc->min;
+		dev->dvb.frontend->ops.info.frequency_max = dev->core->pll_desc->max;
 	}
 
 	/* Put the analog decoder in standby to keep it quiet */
 	cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
 
 	/* register everything */
-	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
+	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
 }
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index f720901..7066380 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -138,13 +138,13 @@
 		return;
 
 	if (core->dvbdev) {
-		if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
-			core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
+		if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
+			core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 1);
 
 		i2c_clients_command(&core->i2c_adap, cmd, arg);
 
-		if (core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl)
-			core->dvbdev->dvb.frontend->ops->i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
+		if (core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl)
+			core->dvbdev->dvb.frontend->ops.i2c_gate_ctrl(core->dvbdev->dvb.frontend, 0);
 	} else
 		i2c_clients_command(&core->i2c_adap, cmd, arg);
 }
@@ -234,7 +234,6 @@
 /* ----------------------------------------------------------------------- */
 
 EXPORT_SYMBOL(cx88_call_i2c_clients);
-EXPORT_SYMBOL(cx88_i2c_init);
 
 /*
  * Local variables:
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index 78a63b7..72b630a 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -70,14 +70,33 @@
 static void cx88_ir_handle_key(struct cx88_IR *ir)
 {
 	struct cx88_core *core = ir->core;
-	u32 gpio, data;
+	u32 gpio, data, auxgpio;
 
 	/* read gpio value */
 	gpio = cx_read(ir->gpio_addr);
+	if (core->board == CX88_BOARD_NPGTECH_REALTV_TOP10FM) {
+		/* This board apparently uses a combination of 2 GPIO
+		   to represent the keys. Additionally, the second GPIO
+		   can be used for parity.
+
+		   Example:
+
+		   for key "5"
+			gpio = 0x758, auxgpio = 0xe5 or 0xf5
+		   for key "Power"
+			gpio = 0x758, auxgpio = 0xed or 0xfd
+		 */
+
+		auxgpio = cx_read(MO_GP1_IO);
+		/* Take out the parity part */
+		gpio+=(gpio & 0x7fd) + (auxgpio & 0xef);
+	} else
+		auxgpio = gpio;
+
 	if (ir->polling) {
-		if (ir->last_gpio == gpio)
+		if (ir->last_gpio == auxgpio)
 			return;
-		ir->last_gpio = gpio;
+		ir->last_gpio = auxgpio;
 	}
 
 	/* extract data */
@@ -172,12 +191,13 @@
 		ir_type = IR_TYPE_RC5;
 		ir->sampling = 1;
 		break;
+	case CX88_BOARD_WINFAST_DTV2000H:
 	case CX88_BOARD_WINFAST2000XP_EXPERT:
 		ir_codes = ir_codes_winfast;
 		ir->gpio_addr = MO_GP0_IO;
 		ir->mask_keycode = 0x8f8;
 		ir->mask_keyup = 0x100;
-		ir->polling = 1; /* ms */
+		ir->polling = 50; /* ms */
 		break;
 	case CX88_BOARD_IODATA_GVBCTV7E:
 		ir_codes = ir_codes_iodata_bctv7e;
@@ -228,6 +248,12 @@
 		ir_type = IR_TYPE_PD;
 		ir->sampling = 0xff00; /* address */
 		break;
+	case CX88_BOARD_NPGTECH_REALTV_TOP10FM:
+		ir_codes = ir_codes_npgtech;
+		ir->gpio_addr = MO_GP0_IO;
+		ir->mask_keycode = 0xfa;
+		ir->polling = 50; /* ms */
+		break;
 	}
 
 	if (NULL == ir_codes) {
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 7d16888..a9d7795 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -54,7 +54,7 @@
 {
 	struct cx88_core *core = dev->core;
 
-	dprintk(0, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field);
+	dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n", dev->width, dev->height, buf->vb.field);
 
 	/* setup fifo + format */
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
@@ -76,6 +76,7 @@
 		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q:
 		case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T:
 		case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD:
+		case CX88_BOARD_PCHDTV_HD5500:
 			cx_write(TS_SOP_STAT, 1<<13);
 			break;
 		case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1:
@@ -109,7 +110,7 @@
 	q->count = 1;
 
 	/* enable irqs */
-	dprintk( 0, "setting the interrupt mask\n" );
+	dprintk( 1, "setting the interrupt mask\n" );
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
 	cx_set(MO_TS_INTMSK,  0x1f0011);
 
@@ -122,7 +123,7 @@
 static int cx8802_stop_dma(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
-	dprintk( 0, "cx8802_stop_dma\n" );
+	dprintk( 1, "cx8802_stop_dma\n" );
 
 	/* stop dma */
 	cx_clear(MO_TS_DMACNTRL, 0x11);
@@ -142,10 +143,43 @@
 	struct cx88_buffer *buf;
 	struct list_head *item;
 
-	dprintk( 0, "cx8802_restart_queue\n" );
+       dprintk( 1, "cx8802_restart_queue\n" );
 	if (list_empty(&q->active))
 	{
-		dprintk( 0, "cx8802_restart_queue: queue is empty\n" );
+	       struct cx88_buffer *prev;
+	       prev = NULL;
+
+	       dprintk(1, "cx8802_restart_queue: queue is empty\n" );
+
+	       for (;;) {
+		       if (list_empty(&q->queued))
+			       return 0;
+		       buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+		       if (NULL == prev) {
+			       list_del(&buf->vb.queue);
+			       list_add_tail(&buf->vb.queue,&q->active);
+			       cx8802_start_dma(dev, q, buf);
+			       buf->vb.state = STATE_ACTIVE;
+			       buf->count    = q->count++;
+			       mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+			       dprintk(1,"[%p/%d] restart_queue - first active\n",
+				       buf,buf->vb.i);
+
+		       } else if (prev->vb.width  == buf->vb.width  &&
+				  prev->vb.height == buf->vb.height &&
+				  prev->fmt       == buf->fmt) {
+			       list_del(&buf->vb.queue);
+			       list_add_tail(&buf->vb.queue,&q->active);
+			       buf->vb.state = STATE_ACTIVE;
+			       buf->count    = q->count++;
+			       prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+			       dprintk(1,"[%p/%d] restart_queue - move to active\n",
+				       buf,buf->vb.i);
+		       } else {
+			       return 0;
+		       }
+		       prev = buf;
+	       }
 		return 0;
 	}
 
@@ -204,13 +238,13 @@
 	buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
 
 	if (list_empty(&cx88q->active)) {
-		dprintk( 0, "queue is empty - first active\n" );
+		dprintk( 1, "queue is empty - first active\n" );
 		list_add_tail(&buf->vb.queue,&cx88q->active);
 		cx8802_start_dma(dev, cx88q, buf);
 		buf->vb.state = STATE_ACTIVE;
 		buf->count    = cx88q->count++;
 		mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
-		dprintk(0,"[%p/%d] %s - first active\n",
+		dprintk(1,"[%p/%d] %s - first active\n",
 			buf, buf->vb.i, __FUNCTION__);
 
 	} else {
@@ -244,7 +278,7 @@
 	}
 	if (restart)
 	{
-		dprintk(0, "restarting queue\n" );
+		dprintk(1, "restarting queue\n" );
 		cx8802_restart_queue(dev,q);
 	}
 	spin_unlock_irqrestore(&dev->slock,flags);
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index 641a0c5..5785c34 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -52,6 +52,7 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/delay.h>
+#include <linux/config.h>
 #include <linux/kthread.h>
 
 #include "cx88.h"
@@ -137,21 +138,28 @@
 {
 	u32 volume;
 
-#ifndef USING_CX88_ALSA
+#ifndef CONFIG_VIDEO_CX88_ALSA
 	/* restart dma; This avoids buzz in NICAM and is good in others  */
 	cx88_stop_audio_dma(core);
 #endif
 	cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
-#ifndef USING_CX88_ALSA
+#ifndef CONFIG_VIDEO_CX88_ALSA
 	cx88_start_audio_dma(core);
 #endif
 
 	if (cx88_boards[core->board].blackbird) {
 		/* sets sound input from external adc */
-		if (core->board == CX88_BOARD_HAUPPAUGE_ROSLYN)
+		switch (core->board) {
+		case CX88_BOARD_HAUPPAUGE_ROSLYN:
+		case CX88_BOARD_KWORLD_MCE200_DELUXE:
+		case CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT:
+		case CX88_BOARD_PIXELVIEW_PLAYTV_P7000:
+		case CX88_BOARD_ASUS_PVR_416:
 			cx_clear(AUD_CTL, EN_I2SIN_ENABLE);
-		else
+			break;
+		default:
 			cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+		}
 
 		cx_write(AUD_I2SINPUTCNTL, 4);
 		cx_write(AUD_BAUDRATE, 1);
@@ -718,7 +726,7 @@
 
 /* ----------------------------------------------------------- */
 
-int cx88_detect_nicam(struct cx88_core *core)
+static int cx88_detect_nicam(struct cx88_core *core)
 {
 	int i, j = 0;
 
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 846faad..aa2a697 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -34,8 +34,8 @@
 	if (dev->core->tvnorm->id & V4L2_STD_525_60) {
 		/* ntsc */
 		f->fmt.vbi.sampling_rate = 28636363;
-		f->fmt.vbi.start[0] = 10 -1;
-		f->fmt.vbi.start[1] = 273 -1;
+		f->fmt.vbi.start[0] = 10;
+		f->fmt.vbi.start[1] = 273;
 
 	} else if (dev->core->tvnorm->id & V4L2_STD_625_50) {
 		/* pal */
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index 694d1d8..dcda529 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -494,8 +494,7 @@
 			return 0;
 		buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
 		if (NULL == prev) {
-			list_del(&buf->vb.queue);
-			list_add_tail(&buf->vb.queue,&q->active);
+			list_move_tail(&buf->vb.queue, &q->active);
 			start_video_dma(dev, q, buf);
 			buf->vb.state = STATE_ACTIVE;
 			buf->count    = q->count++;
@@ -506,8 +505,7 @@
 		} else if (prev->vb.width  == buf->vb.width  &&
 			   prev->vb.height == buf->vb.height &&
 			   prev->fmt       == buf->fmt) {
-			list_del(&buf->vb.queue);
-			list_add_tail(&buf->vb.queue,&q->active);
+			list_move_tail(&buf->vb.queue, &q->active);
 			buf->vb.state = STATE_ACTIVE;
 			buf->count    = q->count++;
 			prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 326a25f..9a9a0fc 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -25,9 +25,11 @@
 #include <linux/videodev2.h>
 #include <linux/kdev_t.h>
 
+#include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <media/tveeprom.h>
 #include <media/video-buf.h>
+#include <media/cx2341x.h>
 #include <media/video-buf-dvb.h>
 
 #include "btcx-risc.h"
@@ -35,7 +37,7 @@
 
 #include <linux/version.h>
 #include <linux/mutex.h>
-#define CX88_VERSION_CODE KERNEL_VERSION(0,0,5)
+#define CX88_VERSION_CODE KERNEL_VERSION(0,0,6)
 
 #ifndef TRUE
 # define TRUE (1==1)
@@ -189,6 +191,11 @@
 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL 44
 #define CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT 45
 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID 46
+#define CX88_BOARD_PCHDTV_HD5500           47
+#define CX88_BOARD_KWORLD_MCE200_DELUXE    48
+#define CX88_BOARD_PIXELVIEW_PLAYTV_P7000  49
+#define CX88_BOARD_NPGTECH_REALTV_TOP10FM  50
+#define CX88_BOARD_WINFAST_DTV2000H        51
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
@@ -296,6 +303,7 @@
 	/* config info -- dvb */
 	struct dvb_pll_desc        *pll_desc;
 	unsigned int               pll_addr;
+	int 			   (*prev_set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
 
 	/* state info */
 	struct task_struct         *kthread;
@@ -391,14 +399,6 @@
 	int                        disabled;
 };
 
-/* TODO: move this to struct v4l2_mpeg_compression ? */
-struct blackbird_dnr {
-	u32                       mode;
-	u32                       type;
-	u32                       spatial;
-	u32                       temporal;
-};
-
 struct cx8802_dev {
 	struct cx88_core           *core;
 	spinlock_t                 slock;
@@ -432,8 +432,7 @@
 	unsigned char              ts_gen_cntrl;
 
 	/* mpeg params */
-	struct v4l2_mpeg_compression params;
-	struct blackbird_dnr       dnr_params;
+	struct cx2341x_mpeg_params params;
 };
 
 /* ----------------------------------------------------------- */
@@ -564,7 +563,6 @@
 void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t);
 void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual);
 int cx88_audio_thread(void *data);
-int cx88_detect_nicam(struct cx88_core *core);
 
 /* ----------------------------------------------------------- */
 /* cx88-input.c                                                */
@@ -593,16 +591,6 @@
 				struct cx88_core *core, unsigned int cmd,
 				void *arg, v4l2_kioctl driver_ioctl);
 
-/* ----------------------------------------------------------- */
-/* cx88-blackbird.c                                            */
-extern int (*cx88_ioctl_hook)(struct inode *inode, struct file *file,
-				unsigned int cmd, void *arg);
-extern unsigned int (*cx88_ioctl_translator)(unsigned int cmd);
-void blackbird_set_params(struct cx8802_dev *dev,
-				struct v4l2_mpeg_compression *params);
-void blackbird_set_dnr_params(struct cx8802_dev *dev,
-				struct blackbird_dnr* dnr_params);
-
 /*
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/media/video/dsbr100.c b/drivers/media/video/dsbr100.c
index 3b4e998..f7e33f9 100644
--- a/drivers/media/video/dsbr100.c
+++ b/drivers/media/video/dsbr100.c
@@ -72,6 +72,7 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
 
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 3ba3439..ed882eb 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
 		      Markus Rechberger <mrechberger@gmail.com>
-		      Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+		      Mauro Carvalho Chehab <mchehab@infradead.org>
 		      Sascha Sommer <saschasommer@freenet.de>
 
    This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,8 @@
 #include <linux/usb.h>
 #include <media/tuner.h>
 #include <media/msp3400.h>
+#include <media/saa7115.h>
+#include <media/tvp5150.h>
 #include <media/tveeprom.h>
 #include <media/audiochip.h>
 #include <media/v4l2-common.h>
@@ -46,11 +48,11 @@
 		.decoder      = EM28XX_SAA7113,
 		.input           = {{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -64,11 +66,11 @@
 		.decoder      = EM28XX_SAA7113,
 		.input           = {{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -82,11 +84,11 @@
 		.decoder      = EM28XX_SAA7113,
 		.input           = {{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -100,15 +102,15 @@
 		.decoder      = EM28XX_SAA7113,
 		.input          = {{
 			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = 2,
+			.vmux     = SAA7115_COMPOSITE2,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -122,15 +124,15 @@
 		.decoder      = EM28XX_SAA7113,
 		.input          = {{
 			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = 2,
+			.vmux     = SAA7115_COMPOSITE2,
 			.amux     = 0,
 		},{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -146,11 +148,11 @@
 		/*FIXME: S-Video not tested */
 		.input          = {{
 			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = 0,
+			.vmux     = TVP5150_COMPOSITE0,
 			.amux     = MSP_INPUT_DEFAULT,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 2,
+			.vmux     = TVP5150_SVIDEO,
 			.amux     = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
 					MSP_DSP_IN_SCART, MSP_DSP_IN_SCART),
 		}},
@@ -165,15 +167,15 @@
 		.decoder        = EM28XX_SAA7114,
 		.input          = {{
 			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = 4,
+			.vmux     = SAA7115_COMPOSITE4,
 			.amux     = 0,
 		},{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -188,15 +190,15 @@
 		.decoder      = EM28XX_SAA7113,
 		.input          = {{
 			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = 2,
+			.vmux     = SAA7115_COMPOSITE2,
 			.amux     = 0,
 		},{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -211,15 +213,15 @@
 		.decoder      = EM28XX_SAA7113,
 		.input          = {{
 			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = 2,
+			.vmux     = SAA7115_COMPOSITE2,
 			.amux     = 0,
 		},{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -234,15 +236,15 @@
 		.decoder      = EM28XX_SAA7113,
 		.input          = {{
 			.type     = EM28XX_VMUX_TELEVISION,
-			.vmux     = 2,
+			.vmux     = SAA7115_COMPOSITE2,
 			.amux     = 0,
 		},{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -254,11 +256,11 @@
 		.decoder      = EM28XX_SAA7113,
 		.input          = {{
 			.type     = EM28XX_VMUX_COMPOSITE1,
-			.vmux     = 0,
+			.vmux     = SAA7115_COMPOSITE0,
 			.amux     = 1,
 		},{
 			.type     = EM28XX_VMUX_SVIDEO,
-			.vmux     = 9,
+			.vmux     = SAA7115_SVIDEO3,
 			.amux     = 1,
 		}},
 	},
@@ -324,8 +326,4 @@
 	}
 }
 
-EXPORT_SYMBOL(em28xx_boards);
-EXPORT_SYMBOL(em28xx_bcount);
-EXPORT_SYMBOL(em28xx_id_table);
-
 MODULE_DEVICE_TABLE (usb, em28xx_id_table);
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index e5ee8bc..4350cc7 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
 		      Markus Rechberger <mrechberger@gmail.com>
-		      Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+		      Mauro Carvalho Chehab <mchehab@infradead.org>
 		      Sascha Sommer <saschasommer@freenet.de>
 
    This program is free software; you can redistribute it and/or modify
@@ -317,8 +317,8 @@
 	return em28xx_write_regs(dev, VINCTRL_REG, "\x11", 1);
 }
 
-int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin,
-				  u8 ymax)
+static int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax,
+				  u8 ymin, u8 ymax)
 {
 	em28xx_coredbg("em28xx Scale: (%d,%d)-(%d,%d)\n", xmin, ymin, xmax, ymax);
 
@@ -328,7 +328,7 @@
 	return em28xx_write_regs(dev, YMAX_REG, &ymax, 1);
 }
 
-int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
+static int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
 				   u16 width, u16 height)
 {
 	u8 cwidth = width;
@@ -345,7 +345,7 @@
 	return em28xx_write_regs(dev, OFLOW_REG, &overflow, 1);
 }
 
-int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
+static int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v)
 {
 	u8 mode;
 	/* the em2800 scaler only supports scaling down to 50% */
@@ -534,7 +534,7 @@
  * em28xx_isoIrq()
  * handles the incoming isoc urbs and fills the frames from our inqueue
  */
-void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
+static void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs)
 {
 	struct em28xx *dev = urb->context;
 	int i, status;
diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c
index 5b6cece..d829d8f 100644
--- a/drivers/media/video/em28xx/em28xx-i2c.c
+++ b/drivers/media/video/em28xx/em28xx-i2c.c
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
 		      Markus Rechberger <mrechberger@gmail.com>
-		      Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+		      Mauro Carvalho Chehab <mchehab@infradead.org>
 		      Sascha Sommer <saschasommer@freenet.de>
 
    This program is free software; you can redistribute it and/or modify
@@ -399,17 +399,6 @@
 	return I2C_FUNC_SMBUS_EMUL;
 }
 
-#ifndef I2C_PEC
-static void inc_use(struct i2c_adapter *adap)
-{
-	MOD_INC_USE_COUNT;
-}
-
-static void dec_use(struct i2c_adapter *adap)
-{
-	MOD_DEC_USE_COUNT;
-}
-#endif
 
 static int em28xx_set_tuner(int check_eeprom, struct i2c_client *client)
 {
@@ -436,9 +425,19 @@
 	struct em28xx *dev = client->adapter->algo_data;
 
 	switch (client->addr << 1) {
-		case 0x86:
+		case 0x43:
+		case 0x4b:
+		{
+			struct tuner_setup tun_setup;
+
+			tun_setup.mode_mask = T_ANALOG_TV | T_RADIO;
+			tun_setup.type = TUNER_TDA9887;
+			tun_setup.addr = client->addr;
+
+			em28xx_i2c_call_clients(dev, TUNER_SET_TYPE_ADDR, &tun_setup);
 			em28xx_i2c_call_clients(dev, TDA9887_SET_CONFIG, &dev->tda9887_conf);
 			break;
+		}
 		case 0x42:
 			dprintk1(1,"attach_inform: saa7114 detected.\n");
 			break;
@@ -464,6 +463,7 @@
 		case 0xba:
 			dprintk1(1,"attach_inform: tvp5150 detected.\n");
 			break;
+
 		default:
 			dprintk1(1,"attach inform: detected I2C address %x\n", client->addr << 1);
 			dev->tuner_addr = client->addr;
@@ -480,12 +480,7 @@
 };
 
 static struct i2c_adapter em28xx_adap_template = {
-#ifdef I2C_PEC
 	.owner = THIS_MODULE,
-#else
-	.inc_use = inc_use,
-	.dec_use = dec_use,
-#endif
 	.class = I2C_CLASS_TV_ANALOG,
 	.name = "em28xx",
 	.id = I2C_HW_B_EM28XX,
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index 31e89e4..3ffb568 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
 		      Markus Rechberger <mrechberger@gmail.com>
-		      Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+		      Mauro Carvalho Chehab <mchehab@infradead.org>
 		      Sascha Sommer <saschasommer@freenet.de>
 
   This program is free software; you can redistribute it and/or modify
@@ -105,7 +105,7 @@
 	return 1;
 }
 
-static int get_key_pinnacle_usb(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
 {
 	unsigned char buf[3];
 
@@ -148,8 +148,8 @@
 		snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Terratec)");
 		break;
 	case (EM2820_BOARD_PINNACLE_USB_2):
-		ir->ir_codes = ir_codes_em_pinnacle_usb;
-		ir->get_key = get_key_pinnacle_usb;
+		ir->ir_codes = ir_codes_pinnacle_grey;
+		ir->get_key = get_key_pinnacle_usb_grey;
 		snprintf(ir->c.name, sizeof(ir->c.name), "i2c IR (EM28XX Pinnacle PCTV)");
 		break;
 	case (EM2820_BOARD_HAUPPAUGE_WINTV_USB_2):
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index cf7cdf9..9286090 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
 		      Markus Rechberger <mrechberger@gmail.com>
-		      Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+		      Mauro Carvalho Chehab <mchehab@infradead.org>
 		      Sascha Sommer <saschasommer@freenet.de>
 
 	Some parts based on SN9C10x PC Camera Controllers GPL driver made
@@ -42,7 +42,7 @@
 
 #define DRIVER_AUTHOR "Ludovico Cavedon <cavedon@sssup.it>, " \
 		      "Markus Rechberger <mrechberger@gmail.com>, " \
-		      "Mauro Carvalho Chehab <mchehab@brturbo.com.br>, " \
+		      "Mauro Carvalho Chehab <mchehab@infradead.org>, " \
 		      "Sascha Sommer <saschasommer@freenet.de>"
 
 #define DRIVER_NAME         "em28xx"
@@ -170,8 +170,12 @@
 static void em28xx_config_i2c(struct em28xx *dev)
 {
 	struct v4l2_frequency f;
+	struct v4l2_routing route;
+
+	route.input = INPUT(dev->ctl_input)->vmux;
+	route.output = 0;
 	em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL);
-	em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &dev->ctl_input);
+	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 	em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL);
 
 	/* configure tuner */
@@ -206,19 +210,19 @@
 
 static void video_mux(struct em28xx *dev, int index)
 {
-	int input, ainput;
+	int ainput;
+	struct v4l2_routing route;
 
-	input = INPUT(index)->vmux;
+	route.input = INPUT(index)->vmux;
+	route.output = 0;
 	dev->ctl_input = index;
 	dev->ctl_ainput = INPUT(index)->amux;
 
-	em28xx_i2c_call_clients(dev, VIDIOC_S_INPUT, &input);
+	em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route);
 
-	em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput);
+	em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,route.input,dev->ctl_ainput);
 
 	if (dev->has_msp34xx) {
-		struct v4l2_routing route;
-
 		if (dev->i2s_speed)
 			em28xx_i2c_call_clients(dev, VIDIOC_INT_I2S_CLOCK_FREQ, &dev->i2s_speed);
 		route.input = dev->ctl_ainput;
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index e1ddc2f..d8fcc9e 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -3,7 +3,7 @@
 
    Copyright (C) 2005 Markus Rechberger <mrechberger@gmail.com>
 		      Ludovico Cavedon <cavedon@sssup.it>
-		      Mauro Carvalho Chehab <mchehab@brturbo.com.br>
+		      Mauro Carvalho Chehab <mchehab@infradead.org>
 
    Based on the em2800 driver from Sascha Sommer <saschasommer@freenet.de>
 
@@ -319,13 +319,7 @@
 int em28xx_colorlevels_set_default(struct em28xx *dev);
 int em28xx_capture_start(struct em28xx *dev, int start);
 int em28xx_outfmt_set_yuv422(struct em28xx *dev);
-int em28xx_accumulator_set(struct em28xx *dev, u8 xmin, u8 xmax, u8 ymin,
-			   u8 ymax);
-int em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
-			    u16 width, u16 height);
-int em28xx_scaler_set(struct em28xx *dev, u16 h, u16 v);
 int em28xx_resolution_set(struct em28xx *dev);
-void em28xx_isocIrq(struct urb *urb, struct pt_regs *regs);
 int em28xx_init_isoc(struct em28xx *dev);
 void em28xx_uninit_isoc(struct em28xx *dev);
 int em28xx_set_alternate(struct em28xx *dev);
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c
index dfc9dd7..8992b6e 100644
--- a/drivers/media/video/et61x251/et61x251_core.c
+++ b/drivers/media/video/et61x251/et61x251_core.c
@@ -2341,11 +2341,9 @@
 	case VIDIOC_G_CTRL:
 		return et61x251_vidioc_g_ctrl(cam, arg);
 
-	case VIDIOC_S_CTRL_OLD:
 	case VIDIOC_S_CTRL:
 		return et61x251_vidioc_s_ctrl(cam, arg);
 
-	case VIDIOC_CROPCAP_OLD:
 	case VIDIOC_CROPCAP:
 		return et61x251_vidioc_cropcap(cam, arg);
 
@@ -2392,7 +2390,6 @@
 	case VIDIOC_G_PARM:
 		return et61x251_vidioc_g_parm(cam, arg);
 
-	case VIDIOC_S_PARM_OLD:
 	case VIDIOC_S_PARM:
 		return et61x251_vidioc_s_parm(cam, arg);
 
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
index 7e66d83..fba30a4 100644
--- a/drivers/media/video/ir-kbd-i2c.c
+++ b/drivers/media/video/ir-kbd-i2c.c
@@ -150,12 +150,11 @@
 	return 1;
 }
 
-/* The new pinnacle PCTV remote (with the colored buttons)
+/* Common (grey or coloured) pinnacle PCTV remote handling
  *
- * Ricardo Cerqueira <v4l@cerqueira.org>
  */
-
-int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw,
+			    int parity_offset, int marker, int code_modulo)
 {
 	unsigned char b[4];
 	unsigned int start = 0,parity = 0,code = 0;
@@ -167,9 +166,9 @@
 	}
 
 	for (start = 0; start<4; start++) {
-		if (b[start] == 0x80) {
-			code=b[(start+3)%4];
-			parity=b[(start+2)%4];
+		if (b[start] == marker) {
+			code=b[(start+parity_offset+1)%4];
+			parity=b[(start+parity_offset)%4];
 		}
 	}
 
@@ -181,16 +180,14 @@
 	if (ir->old == parity)
 		return 0;
 
-
 	ir->old = parity;
 
-	/* Reduce code value to fit inside IR_KEYTAB_SIZE
-	 *
-	 * this is the only value that results in 42 unique
-	 * codes < 128
-	 */
+	/* drop special codes when a key is held down a long time for the grey controller
+	   In this case, the second bit of the code is asserted */
+	if (marker == 0xfe && (code & 0x40))
+		return 0;
 
-	code %= 0x88;
+	code %= code_modulo;
 
 	*ir_raw = code;
 	*ir_key = code;
@@ -200,7 +197,40 @@
 	return 1;
 }
 
-EXPORT_SYMBOL_GPL(get_key_pinnacle);
+/* The grey pinnacle PCTV remote
+ *
+ *  There are one issue with this remote:
+ *   - I2c packet does not change when the same key is pressed quickly. The workaround
+ *     is to hold down each key for about half a second, so that another code is generated
+ *     in the i2c packet, and the function can distinguish key presses.
+ *
+ * Sylvain Pasche <sylvain.pasche@gmail.com>
+ */
+int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+
+	return get_key_pinnacle(ir, ir_key, ir_raw, 1, 0xfe, 0xff);
+}
+
+EXPORT_SYMBOL_GPL(get_key_pinnacle_grey);
+
+
+/* The new pinnacle PCTV remote (with the colored buttons)
+ *
+ * Ricardo Cerqueira <v4l@cerqueira.org>
+ */
+int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
+{
+	/* code_modulo parameter (0x88) is used to reduce code value to fit inside IR_KEYTAB_SIZE
+	 *
+	 * this is the only value that results in 42 unique
+	 * codes < 128
+	 */
+
+	return get_key_pinnacle(ir, ir_key, ir_raw, 2, 0x80, 0x88);
+}
+
+EXPORT_SYMBOL_GPL(get_key_pinnacle_color);
 
 /* ----------------------------------------------------------------------- */
 
diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c
new file mode 100644
index 0000000..3bf7ac4
--- /dev/null
+++ b/drivers/media/video/ks0127.c
@@ -0,0 +1,846 @@
+/*
+ * Video Capture Driver (Video for Linux 1/2)
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *****************************************************************************
+ *
+ * Modified and extended by
+ *	Mike Bernson <mike@mlb.org>
+ *	Gerard v.d. Horst
+ *	Leon van Stuivenberg <l.vanstuivenberg@chello.nl>
+ *	Gernot Ziegler <gz@lysator.liu.se>
+ *
+ * Version History:
+ * V1.0 Ryan Drake	   Initial version by Ryan Drake
+ * V1.1 Gerard v.d. Horst  Added some debugoutput, reset the video-standard
+ */
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include "ks0127.h"
+
+#include <linux/i2c.h>
+#include <linux/video_decoder.h>
+
+#define dprintk     if (debug) printk
+
+/* i2c identification */
+#define I2C_KS0127_ADDON   0xD8
+#define I2C_KS0127_ONBOARD 0xDA
+
+#define KS_TYPE_UNKNOWN	0
+#define KS_TYPE_0122S	1
+#define KS_TYPE_0127	2
+#define KS_TYPE_0127B	3
+
+/* ks0127 control registers */
+#define KS_STAT     0x00
+#define KS_CMDA     0x01
+#define KS_CMDB     0x02
+#define KS_CMDC     0x03
+#define KS_CMDD     0x04
+#define KS_HAVB     0x05
+#define KS_HAVE     0x06
+#define KS_HS1B     0x07
+#define KS_HS1E     0x08
+#define KS_HS2B     0x09
+#define KS_HS2E     0x0a
+#define KS_AGC      0x0b
+#define KS_HXTRA    0x0c
+#define KS_CDEM     0x0d
+#define KS_PORTAB   0x0e
+#define KS_LUMA     0x0f
+#define KS_CON      0x10
+#define KS_BRT      0x11
+#define KS_CHROMA   0x12
+#define KS_CHROMB   0x13
+#define KS_DEMOD    0x14
+#define KS_SAT      0x15
+#define KS_HUE      0x16
+#define KS_VERTIA   0x17
+#define KS_VERTIB   0x18
+#define KS_VERTIC   0x19
+#define KS_HSCLL    0x1a
+#define KS_HSCLH    0x1b
+#define KS_VSCLL    0x1c
+#define KS_VSCLH    0x1d
+#define KS_OFMTA    0x1e
+#define KS_OFMTB    0x1f
+#define KS_VBICTL   0x20
+#define KS_CCDAT2   0x21
+#define KS_CCDAT1   0x22
+#define KS_VBIL30   0x23
+#define KS_VBIL74   0x24
+#define KS_VBIL118  0x25
+#define KS_VBIL1512 0x26
+#define KS_TTFRAM   0x27
+#define KS_TESTA    0x28
+#define KS_UVOFFH   0x29
+#define KS_UVOFFL   0x2a
+#define KS_UGAIN    0x2b
+#define KS_VGAIN    0x2c
+#define KS_VAVB     0x2d
+#define KS_VAVE     0x2e
+#define KS_CTRACK   0x2f
+#define KS_POLCTL   0x30
+#define KS_REFCOD   0x31
+#define KS_INVALY   0x32
+#define KS_INVALU   0x33
+#define KS_INVALV   0x34
+#define KS_UNUSEY   0x35
+#define KS_UNUSEU   0x36
+#define KS_UNUSEV   0x37
+#define KS_USRSAV   0x38
+#define KS_USREAV   0x39
+#define KS_SHS1A    0x3a
+#define KS_SHS1B    0x3b
+#define KS_SHS1C    0x3c
+#define KS_CMDE     0x3d
+#define KS_VSDEL    0x3e
+#define KS_CMDF     0x3f
+#define KS_GAMMA0   0x40
+#define KS_GAMMA1   0x41
+#define KS_GAMMA2   0x42
+#define KS_GAMMA3   0x43
+#define KS_GAMMA4   0x44
+#define KS_GAMMA5   0x45
+#define KS_GAMMA6   0x46
+#define KS_GAMMA7   0x47
+#define KS_GAMMA8   0x48
+#define KS_GAMMA9   0x49
+#define KS_GAMMA10  0x4a
+#define KS_GAMMA11  0x4b
+#define KS_GAMMA12  0x4c
+#define KS_GAMMA13  0x4d
+#define KS_GAMMA14  0x4e
+#define KS_GAMMA15  0x4f
+#define KS_GAMMA16  0x50
+#define KS_GAMMA17  0x51
+#define KS_GAMMA18  0x52
+#define KS_GAMMA19  0x53
+#define KS_GAMMA20  0x54
+#define KS_GAMMA21  0x55
+#define KS_GAMMA22  0x56
+#define KS_GAMMA23  0x57
+#define KS_GAMMA24  0x58
+#define KS_GAMMA25  0x59
+#define KS_GAMMA26  0x5a
+#define KS_GAMMA27  0x5b
+#define KS_GAMMA28  0x5c
+#define KS_GAMMA29  0x5d
+#define KS_GAMMA30  0x5e
+#define KS_GAMMA31  0x5f
+#define KS_GAMMAD0  0x60
+#define KS_GAMMAD1  0x61
+#define KS_GAMMAD2  0x62
+#define KS_GAMMAD3  0x63
+#define KS_GAMMAD4  0x64
+#define KS_GAMMAD5  0x65
+#define KS_GAMMAD6  0x66
+#define KS_GAMMAD7  0x67
+#define KS_GAMMAD8  0x68
+#define KS_GAMMAD9  0x69
+#define KS_GAMMAD10 0x6a
+#define KS_GAMMAD11 0x6b
+#define KS_GAMMAD12 0x6c
+#define KS_GAMMAD13 0x6d
+#define KS_GAMMAD14 0x6e
+#define KS_GAMMAD15 0x6f
+#define KS_GAMMAD16 0x70
+#define KS_GAMMAD17 0x71
+#define KS_GAMMAD18 0x72
+#define KS_GAMMAD19 0x73
+#define KS_GAMMAD20 0x74
+#define KS_GAMMAD21 0x75
+#define KS_GAMMAD22 0x76
+#define KS_GAMMAD23 0x77
+#define KS_GAMMAD24 0x78
+#define KS_GAMMAD25 0x79
+#define KS_GAMMAD26 0x7a
+#define KS_GAMMAD27 0x7b
+#define KS_GAMMAD28 0x7c
+#define KS_GAMMAD29 0x7d
+#define KS_GAMMAD30 0x7e
+#define KS_GAMMAD31 0x7f
+
+
+/****************************************************************************
+* mga_dev : represents one ks0127 chip.
+****************************************************************************/
+
+struct adjust {
+	int	contrast;
+	int	bright;
+	int	hue;
+	int	ugain;
+	int	vgain;
+};
+
+struct ks0127 {
+	struct i2c_client *client;
+	unsigned char	addr;
+	int		format_width;
+	int		format_height;
+	int		cap_width;
+	int		cap_height;
+	int		norm;
+	int		ks_type;
+	u8 		regs[256];
+};
+
+
+static int debug; /* insmod parameter */
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug output");
+MODULE_LICENSE("GPL");
+
+static u8 reg_defaults[64];
+
+
+
+static void init_reg_defaults(void)
+{
+	u8 *table = reg_defaults;
+
+	table[KS_CMDA]     = 0x2c;  /* VSE=0, CCIR 601, autodetect standard */
+	table[KS_CMDB]     = 0x12;  /* VALIGN=0, AGC control and input */
+	table[KS_CMDC]     = 0x00;  /* Test options */
+	/* clock & input select, write 1 to PORTA */
+	table[KS_CMDD]     = 0x01;
+	table[KS_HAVB]     = 0x00;  /* HAV Start Control */
+	table[KS_HAVE]     = 0x00;  /* HAV End Control */
+	table[KS_HS1B]     = 0x10;  /* HS1 Start Control */
+	table[KS_HS1E]     = 0x00;  /* HS1 End Control */
+	table[KS_HS2B]     = 0x00;  /* HS2 Start Control */
+	table[KS_HS2E]     = 0x00;  /* HS2 End Control */
+	table[KS_AGC]      = 0x53;  /* Manual setting for AGC */
+	table[KS_HXTRA]    = 0x00;  /* Extra Bits for HAV and HS1/2 */
+	table[KS_CDEM]     = 0x00;  /* Chroma Demodulation Control */
+	table[KS_PORTAB]   = 0x0f;  /* port B is input, port A output GPPORT */
+	table[KS_LUMA]     = 0x01;  /* Luma control */
+	table[KS_CON]      = 0x00;  /* Contrast Control */
+	table[KS_BRT]      = 0x00;  /* Brightness Control */
+	table[KS_CHROMA]   = 0x2a;  /* Chroma control A */
+	table[KS_CHROMB]   = 0x90;  /* Chroma control B */
+	table[KS_DEMOD]    = 0x00;  /* Chroma Demodulation Control & Status */
+	table[KS_SAT]      = 0x00;  /* Color Saturation Control*/
+	table[KS_HUE]      = 0x00;  /* Hue Control */
+	table[KS_VERTIA]   = 0x00;  /* Vertical Processing Control A */
+	/* Vertical Processing Control B, luma 1 line delayed */
+	table[KS_VERTIB]   = 0x12;
+	table[KS_VERTIC]   = 0x0b;  /* Vertical Processing Control C */
+	table[KS_HSCLL]    = 0x00;  /* Horizontal Scaling Ratio Low */
+	table[KS_HSCLH]    = 0x00;  /* Horizontal Scaling Ratio High */
+	table[KS_VSCLL]    = 0x00;  /* Vertical Scaling Ratio Low */
+	table[KS_VSCLH]    = 0x00;  /* Vertical Scaling Ratio High */
+	/* 16 bit YCbCr 4:2:2 output; I can't make the bt866 like 8 bit /Sam */
+	table[KS_OFMTA]    = 0x30;
+	table[KS_OFMTB]    = 0x00;  /* Output Control B */
+	/* VBI Decoder Control; 4bit fmt: avoid Y overflow */
+	table[KS_VBICTL]   = 0x5d;
+	table[KS_CCDAT2]   = 0x00;  /* Read Only register */
+	table[KS_CCDAT1]   = 0x00;  /* Read Only register */
+	table[KS_VBIL30]   = 0xa8;  /* VBI data decoding options */
+	table[KS_VBIL74]   = 0xaa;  /* VBI data decoding options */
+	table[KS_VBIL118]  = 0x2a;  /* VBI data decoding options */
+	table[KS_VBIL1512] = 0x00;  /* VBI data decoding options */
+	table[KS_TTFRAM]   = 0x00;  /* Teletext frame alignment pattern */
+	table[KS_TESTA]    = 0x00;  /* test register, shouldn't be written */
+	table[KS_UVOFFH]   = 0x00;  /* UV Offset Adjustment High */
+	table[KS_UVOFFL]   = 0x00;  /* UV Offset Adjustment Low */
+	table[KS_UGAIN]    = 0x00;  /* U Component Gain Adjustment */
+	table[KS_VGAIN]    = 0x00;  /* V Component Gain Adjustment */
+	table[KS_VAVB]     = 0x07;  /* VAV Begin */
+	table[KS_VAVE]     = 0x00;  /* VAV End */
+	table[KS_CTRACK]   = 0x00;  /* Chroma Tracking Control */
+	table[KS_POLCTL]   = 0x41;  /* Timing Signal Polarity Control */
+	table[KS_REFCOD]   = 0x80;  /* Reference Code Insertion Control */
+	table[KS_INVALY]   = 0x10;  /* Invalid Y Code */
+	table[KS_INVALU]   = 0x80;  /* Invalid U Code */
+	table[KS_INVALV]   = 0x80;  /* Invalid V Code */
+	table[KS_UNUSEY]   = 0x10;  /* Unused Y Code */
+	table[KS_UNUSEU]   = 0x80;  /* Unused U Code */
+	table[KS_UNUSEV]   = 0x80;  /* Unused V Code */
+	table[KS_USRSAV]   = 0x00;  /* reserved */
+	table[KS_USREAV]   = 0x00;  /* reserved */
+	table[KS_SHS1A]    = 0x00;  /* User Defined SHS1 A */
+	/* User Defined SHS1 B, ALT656=1 on 0127B */
+	table[KS_SHS1B]    = 0x80;
+	table[KS_SHS1C]    = 0x00;  /* User Defined SHS1 C */
+	table[KS_CMDE]     = 0x00;  /* Command Register E */
+	table[KS_VSDEL]    = 0x00;  /* VS Delay Control */
+	/* Command Register F, update -immediately- */
+	/* (there might come no vsync)*/
+	table[KS_CMDF]     = 0x02;
+}
+
+
+/* We need to manually read because of a bug in the KS0127 chip.
+ *
+ * An explanation from kayork@mail.utexas.edu:
+ *
+ * During I2C reads, the KS0127 only samples for a stop condition
+ * during the place where the acknoledge bit should be. Any standard
+ * I2C implementation (correctly) throws in another clock transition
+ * at the 9th bit, and the KS0127 will not recognize the stop condition
+ * and will continue to clock out data.
+ *
+ * So we have to do the read ourself.  Big deal.
+	   workaround in i2c-algo-bit
+ */
+
+
+static u8 ks0127_read(struct ks0127 *ks, u8 reg)
+{
+	struct i2c_client *c = ks->client;
+	char val = 0;
+	struct i2c_msg msgs[] = {
+		{c->addr, 0, sizeof(reg), &reg},
+		{c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}};
+	int ret;
+
+	ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret != ARRAY_SIZE(msgs))
+		dprintk("ks0127_write error\n");
+
+	return val;
+}
+
+
+static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val)
+{
+	char msg[] = {reg, val};
+
+	if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg))
+		dprintk("ks0127_write error\n");
+
+	ks->regs[reg] = val;
+}
+
+
+/* generic bit-twiddling */
+static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v)
+{
+	u8 val = ks->regs[reg];
+	val = (val & and_v) | or_v;
+	ks0127_write(ks, reg, val);
+}
+
+
+
+/****************************************************************************
+* ks0127 private api
+****************************************************************************/
+static void ks0127_reset(struct ks0127* ks)
+{
+	int i;
+	u8 *table = reg_defaults;
+
+	ks->ks_type = KS_TYPE_UNKNOWN;
+
+	dprintk("ks0127: reset\n");
+	msleep(1);
+
+	/* initialize all registers to known values */
+	/* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */
+
+	for(i = 1; i < 33; i++)
+		ks0127_write(ks, i, table[i]);
+
+	for(i = 35; i < 40; i++)
+		ks0127_write(ks, i, table[i]);
+
+	for(i = 41; i < 56; i++)
+		ks0127_write(ks, i, table[i]);
+
+	for(i = 58; i < 64; i++)
+		ks0127_write(ks, i, table[i]);
+
+
+	if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) {
+		ks->ks_type = KS_TYPE_0122S;
+		dprintk("ks0127: ks0122s Found\n");
+		return;
+	}
+
+	switch(ks0127_read(ks, KS_CMDE) & 0x0f) {
+
+	case 0:
+		ks->ks_type = KS_TYPE_0127;
+		dprintk("ks0127: ks0127 found\n");
+		break;
+
+	case 9:
+		ks->ks_type = KS_TYPE_0127B;
+		dprintk("ks0127: ks0127B Revision A found\n");
+		break;
+
+	default:
+		dprintk("ks0127: unknown revision\n");
+		break;
+	}
+}
+
+static int ks0127_command(struct i2c_client *client,
+			  unsigned int cmd, void *arg)
+{
+	struct ks0127 *ks = i2c_get_clientdata(client);
+
+	int		*iarg = (int*)arg;
+
+	int		status;
+
+	if (!ks)
+		return -ENODEV;
+
+	switch (cmd) {
+
+	case DECODER_INIT:
+		dprintk("ks0127: command DECODER_INIT\n");
+		ks0127_reset(ks);
+		break;
+
+	case DECODER_SET_INPUT:
+		switch(*iarg) {
+		case KS_INPUT_COMPOSITE_1:
+		case KS_INPUT_COMPOSITE_2:
+		case KS_INPUT_COMPOSITE_3:
+		case KS_INPUT_COMPOSITE_4:
+		case KS_INPUT_COMPOSITE_5:
+		case KS_INPUT_COMPOSITE_6:
+			dprintk("ks0127: command DECODER_SET_INPUT %d: "
+				"Composite\n", *iarg);
+			/* autodetect 50/60 Hz */
+			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+			/* VSE=0 */
+			ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+			/* set input line */
+			ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+			/* non-freerunning mode */
+			ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+			/* analog input */
+			ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+			/* enable chroma demodulation */
+			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+			/* chroma trap, HYBWR=1 */
+			ks0127_and_or(ks, KS_LUMA,   0x00,
+				       (reg_defaults[KS_LUMA])|0x0c);
+			/* scaler fullbw, luma comb off */
+			ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+			/* manual chroma comb .25 .5 .25 */
+			ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90);
+
+			/* chroma path delay */
+			ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90);
+
+			ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
+			ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
+			ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+			ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+			break;
+
+		case KS_INPUT_SVIDEO_1:
+		case KS_INPUT_SVIDEO_2:
+		case KS_INPUT_SVIDEO_3:
+			dprintk("ks0127: command DECODER_SET_INPUT %d: "
+				"S-Video\n", *iarg);
+			/* autodetect 50/60 Hz */
+			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+			/* VSE=0 */
+			ks0127_and_or(ks, KS_CMDA,   ~0x40, 0x00);
+			/* set input line */
+			ks0127_and_or(ks, KS_CMDB,   0xb0, *iarg);
+			/* non-freerunning mode */
+			ks0127_and_or(ks, KS_CMDC,   0x70, 0x0a);
+			/* analog input */
+			ks0127_and_or(ks, KS_CMDD,   0x03, 0x00);
+			/* enable chroma demodulation */
+			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00);
+			ks0127_and_or(ks, KS_LUMA, 0x00,
+				       reg_defaults[KS_LUMA]);
+			/* disable luma comb */
+			ks0127_and_or(ks, KS_VERTIA, 0x08,
+				       (reg_defaults[KS_VERTIA]&0xf0)|0x01);
+			ks0127_and_or(ks, KS_VERTIC, 0x0f,
+				       reg_defaults[KS_VERTIC]&0xf0);
+
+			ks0127_and_or(ks, KS_CHROMB, 0x0f,
+				       reg_defaults[KS_CHROMB]&0xf0);
+
+			ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]);
+			ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]);
+			ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]);
+			ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]);
+			break;
+
+		case KS_INPUT_YUV656:
+			dprintk("ks0127: command DECODER_SET_INPUT 15: "
+				"YUV656\n");
+			if (ks->norm == VIDEO_MODE_NTSC ||
+			    ks->norm == KS_STD_PAL_M)
+				/* force 60 Hz */
+				ks0127_and_or(ks, KS_CMDA,   0xfc, 0x03);
+			else
+				/* force 50 Hz */
+				ks0127_and_or(ks, KS_CMDA,   0xfc, 0x02);
+
+			ks0127_and_or(ks, KS_CMDA,   0xff, 0x40); /* VSE=1 */
+			/* set input line and VALIGN */
+			ks0127_and_or(ks, KS_CMDB,   0xb0, (*iarg | 0x40));
+			/* freerunning mode, */
+			/* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0  VMEM=1*/
+			ks0127_and_or(ks, KS_CMDC,   0x70, 0x87);
+			/* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */
+			ks0127_and_or(ks, KS_CMDD,   0x03, 0x08);
+			/* disable chroma demodulation */
+			ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30);
+			/* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */
+			ks0127_and_or(ks, KS_LUMA,   0x00, 0x71);
+			ks0127_and_or(ks, KS_VERTIC, 0x0f,
+				       reg_defaults[KS_VERTIC]&0xf0);
+
+			/* scaler fullbw, luma comb off */
+			ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81);
+
+			ks0127_and_or(ks, KS_CHROMB, 0x0f,
+				       reg_defaults[KS_CHROMB]&0xf0);
+
+			ks0127_and_or(ks, KS_CON, 0x00, 0x00);
+			ks0127_and_or(ks, KS_BRT, 0x00, 32);	/* spec: 34 */
+				/* spec: 229 (e5) */
+			ks0127_and_or(ks, KS_SAT, 0x00, 0xe8);
+			ks0127_and_or(ks, KS_HUE, 0x00, 0);
+
+			ks0127_and_or(ks, KS_UGAIN, 0x00, 238);
+			ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00);
+
+			/*UOFF:0x30, VOFF:0x30, TSTCGN=1 */
+			ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f);
+			ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00);
+			break;
+
+		default:
+			dprintk("ks0127: command DECODER_SET_INPUT: "
+				"Unknown input %d\n", *iarg);
+			break;
+		}
+
+		/* hack: CDMLPF sometimes spontaneously switches on; */
+		/* force back off */
+		ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]);
+		break;
+
+	case DECODER_SET_OUTPUT:
+		switch(*iarg) {
+		case KS_OUTPUT_YUV656E:
+			dprintk("ks0127: command DECODER_SET_OUTPUT: "
+				"OUTPUT_YUV656E (Missing)\n");
+			return -EINVAL;
+			break;
+
+		case KS_OUTPUT_EXV:
+			dprintk("ks0127: command DECODER_SET_OUTPUT: "
+				"OUTPUT_EXV\n");
+			ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09);
+			break;
+		}
+		break;
+
+	case DECODER_SET_NORM: //sam This block mixes old and new norm names...
+		/* Set to automatic SECAM/Fsc mode */
+		ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+
+		ks->norm = *iarg;
+		switch(*iarg)
+		{
+		/* this is untested !! */
+		/* It just detects PAL_N/NTSC_M (no special frequencies) */
+		/* And you have to set the standard a second time afterwards */
+		case VIDEO_MODE_AUTO:
+			dprintk("ks0127: command DECODER_SET_NORM: AUTO\n");
+
+			/* The chip determines the format */
+			/* based on the current field rate */
+			ks0127_and_or(ks, KS_CMDA,   0xfc, 0x00);
+			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+			/* This is wrong for PAL ! As I said, */
+			/* you need to set the standard once again !! */
+			ks->format_height = 240;
+			ks->format_width = 704;
+			break;
+
+		case VIDEO_MODE_NTSC:
+			dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n");
+			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+			ks->format_height = 240;
+			ks->format_width = 704;
+			break;
+
+		case KS_STD_NTSC_N:
+			dprintk("ks0127: command KS0127_SET_STANDARD: "
+				"NTSC_N (fixme)\n");
+			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+			ks->format_height = 240;
+			ks->format_width = 704;
+			break;
+
+		case VIDEO_MODE_PAL:
+			dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n");
+			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20);
+			ks->format_height = 290;
+			ks->format_width = 704;
+			break;
+
+		case KS_STD_PAL_M:
+			dprintk("ks0127: command KS0127_SET_STANDARD: "
+				"PAL_M (fixme)\n");
+			ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40);
+			ks->format_height = 290;
+			ks->format_width = 704;
+			break;
+
+		case VIDEO_MODE_SECAM:
+			dprintk("ks0127: command KS0127_SET_STANDARD: "
+				"SECAM\n");
+			ks->format_height = 290;
+			ks->format_width = 704;
+
+			/* set to secam autodetection */
+			ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20);
+			ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00);
+			schedule_timeout_interruptible(HZ/10+1);
+
+			/* did it autodetect? */
+			if (ks0127_read(ks, KS_DEMOD) & 0x40)
+				break;
+
+			/* force to secam mode */
+			ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f);
+			break;
+
+		default:
+			dprintk("ks0127: command DECODER_SET_NORM: "
+				"Unknown norm %d\n", *iarg);
+			break;
+		}
+		break;
+
+	case DECODER_SET_PICTURE:
+		dprintk("ks0127: command DECODER_SET_PICTURE "
+			"not yet supported (fixme)\n");
+		return -EINVAL;
+
+	//sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE
+	//sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE
+	//sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE?
+	//sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE
+	//sam todo: KS0127_SET_AGC_MODE:
+	//sam todo: KS0127_SET_AGC:
+	//sam todo: KS0127_SET_CHROMA_MODE:
+	//sam todo: KS0127_SET_PIXCLK_MODE:
+	//sam todo: KS0127_SET_GAMMA_MODE:
+	//sam todo: KS0127_SET_UGAIN:
+	//sam todo: KS0127_SET_VGAIN:
+	//sam todo: KS0127_SET_INVALY:
+	//sam todo: KS0127_SET_INVALU:
+	//sam todo: KS0127_SET_INVALV:
+	//sam todo: KS0127_SET_UNUSEY:
+	//sam todo: KS0127_SET_UNUSEU:
+	//sam todo: KS0127_SET_UNUSEV:
+	//sam todo: KS0127_SET_VSALIGN_MODE:
+
+	case DECODER_ENABLE_OUTPUT:
+	{
+
+		int *iarg = arg;
+		int enable = (*iarg != 0);
+			if (enable) {
+				dprintk("ks0127: command "
+					"DECODER_ENABLE_OUTPUT on "
+					"(%d)\n", enable);
+				/* All output pins on */
+				ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30);
+				/* Obey the OEN pin */
+				ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00);
+			} else {
+				dprintk("ks0127: command "
+					"DECODER_ENABLE_OUTPUT off "
+					"(%d)\n", enable);
+				/* Video output pins off */
+				ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00);
+				/* Ignore the OEN pin */
+				ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80);
+			}
+	}
+		break;
+
+	//sam todo: KS0127_SET_OUTPUT_MODE:
+	//sam todo: KS0127_SET_WIDTH:
+	//sam todo: KS0127_SET_HEIGHT:
+	//sam todo: KS0127_SET_HSCALE:
+
+	case DECODER_GET_STATUS:
+		dprintk("ks0127: command DECODER_GET_STATUS\n");
+		*iarg = 0;
+		status = ks0127_read(ks, KS_STAT);
+		if (!(status & 0x20))		 /* NOVID not set */
+			*iarg = (*iarg & DECODER_STATUS_GOOD);
+		if ((status & 0x01))		      /* CLOCK set */
+			*iarg = (*iarg & DECODER_STATUS_COLOR);
+		if ((status & 0x08))		   /* PALDET set */
+			*iarg = (*iarg & DECODER_STATUS_PAL);
+		else
+			*iarg = (*iarg & DECODER_STATUS_NTSC);
+		break;
+
+	//Catch any unknown command
+	default:
+		dprintk("ks0127: command unknown: %04X\n", cmd);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+
+
+
+static int ks0127_probe(struct i2c_adapter *adapter);
+static int ks0127_detach(struct i2c_client *client);
+static int ks0127_command(struct i2c_client *client,
+			  unsigned int cmd, void *arg);
+
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1,
+				       I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END};
+static unsigned short probe[2] =	{I2C_CLIENT_END, I2C_CLIENT_END};
+static unsigned short ignore[2] = 	{I2C_CLIENT_END, I2C_CLIENT_END};
+static struct i2c_client_address_data addr_data = {
+	normal_i2c,
+	probe,
+	ignore,
+};
+
+static struct i2c_driver i2c_driver_ks0127 = {
+	.driver.name = "ks0127",
+	.id             = I2C_DRIVERID_KS0127,
+	.attach_adapter = ks0127_probe,
+	.detach_client  = ks0127_detach,
+	.command        = ks0127_command
+};
+
+static struct i2c_client ks0127_client_tmpl =
+{
+	.name = "(ks0127 unset)",
+	.addr = 0,
+	.adapter = NULL,
+	.driver = &i2c_driver_ks0127,
+	.usage_count = 0
+};
+
+static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind)
+{
+	struct ks0127 *ks;
+	struct i2c_client *client;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (client == NULL)
+		return -ENOMEM;
+	memcpy(client, &ks0127_client_tmpl, sizeof(*client));
+
+	ks = kzalloc(sizeof(*ks), GFP_KERNEL);
+	if (ks == NULL) {
+		kfree(client);
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(client, ks);
+	client->adapter = adapter;
+	client->addr = addr;
+	sprintf(client->name, "ks0127-%02x", adapter->id);
+
+	ks->client = client;
+	ks->addr = addr;
+	ks->ks_type = KS_TYPE_UNKNOWN;
+
+	/* power up */
+	ks0127_write(ks, KS_CMDA, 0x2c);
+	mdelay(10);
+
+	/* reset the device */
+	ks0127_reset(ks);
+	printk(KERN_INFO "ks0127: attach: %s video decoder\n",
+	       ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board");
+
+	i2c_attach_client(client);
+	return 0;
+}
+
+
+static int ks0127_probe(struct i2c_adapter *adapter)
+{
+	if (adapter->id == I2C_HW_B_ZR36067)
+		return i2c_probe(adapter, &addr_data, ks0127_found_proc);
+	return 0;
+}
+
+static int ks0127_detach(struct i2c_client *client)
+{
+	struct ks0127 *ks = i2c_get_clientdata(client);
+
+	ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/
+	ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */
+
+	i2c_detach_client(client);
+	kfree(ks);
+	kfree(client);
+
+	dprintk("ks0127: detach\n");
+	return 0;
+}
+
+
+static int __devinit ks0127_init_module(void)
+{
+	init_reg_defaults();
+	i2c_add_driver(&i2c_driver_ks0127);
+	return 0;
+}
+
+static void __devexit ks0127_cleanup_module(void)
+{
+	i2c_del_driver(&i2c_driver_ks0127);
+}
+
+
+module_init(ks0127_init_module);
+module_exit(ks0127_cleanup_module);
diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h
new file mode 100644
index 0000000..1ec5788
--- /dev/null
+++ b/drivers/media/video/ks0127.h
@@ -0,0 +1,53 @@
+/*
+ * Video Capture Driver ( Video for Linux 1/2 )
+ * for the Matrox Marvel G200,G400 and Rainbow Runner-G series
+ *
+ * This module is an interface to the KS0127 video decoder chip.
+ *
+ * Copyright (C) 1999  Ryan Drake <stiletto@mediaone.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef KS0127_H
+#define KS0127_H
+
+#include <linux/videodev.h>
+
+/* input channels */
+#define KS_INPUT_COMPOSITE_1    0
+#define KS_INPUT_COMPOSITE_2    1
+#define KS_INPUT_COMPOSITE_3    2
+#define KS_INPUT_COMPOSITE_4    4
+#define KS_INPUT_COMPOSITE_5    5
+#define KS_INPUT_COMPOSITE_6    6
+
+#define KS_INPUT_SVIDEO_1       8
+#define KS_INPUT_SVIDEO_2       9
+#define KS_INPUT_SVIDEO_3       10
+
+#define KS_INPUT_YUV656		15
+#define KS_INPUT_COUNT          10
+
+/* output channels */
+#define KS_OUTPUT_YUV656E       0
+#define KS_OUTPUT_EXV           1
+
+/* video standards */
+#define KS_STD_NTSC_N           112       /* 50 Hz NTSC */
+#define KS_STD_PAL_M            113       /* 60 Hz PAL  */
+
+#endif /* KS0127_H */
+
diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c
index 850bee9..f68ca7d 100644
--- a/drivers/media/video/meye.c
+++ b/drivers/media/video/meye.c
@@ -32,6 +32,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <linux/delay.h>
@@ -1682,13 +1683,13 @@
 
 static void meye_vm_open(struct vm_area_struct *vma)
 {
-	int idx = (int)vma->vm_private_data;
+	long idx = (long)vma->vm_private_data;
 	meye.vma_use_count[idx]++;
 }
 
 static void meye_vm_close(struct vm_area_struct *vma)
 {
-	int idx = (int)vma->vm_private_data;
+	long idx = (long)vma->vm_private_data;
 	meye.vma_use_count[idx]--;
 }
 
diff --git a/drivers/media/video/msp3400-driver.c b/drivers/media/video/msp3400-driver.c
index b806999..dbb75a7 100644
--- a/drivers/media/video/msp3400-driver.c
+++ b/drivers/media/video/msp3400-driver.c
@@ -385,67 +385,6 @@
 	return V4L2_TUNER_MODE_MONO;
 }
 
-static struct v4l2_queryctrl msp_qctrl_std[] = {
-	{
-		.id            = V4L2_CID_AUDIO_VOLUME,
-		.name          = "Volume",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 58880,
-		.flags         = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_MUTE,
-		.name          = "Mute",
-		.minimum       = 0,
-		.maximum       = 1,
-		.step          = 1,
-		.default_value = 1,
-		.flags         = 0,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},
-};
-
-static struct v4l2_queryctrl msp_qctrl_sound_processing[] = {
-	{
-		.id            = V4L2_CID_AUDIO_BALANCE,
-		.name          = "Balance",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.flags         = 0,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_BASS,
-		.name          = "Bass",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_TREBLE,
-		.name          = "Treble",
-		.minimum       = 0,
-		.maximum       = 65535,
-		.step          = 65535/100,
-		.default_value = 32768,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-	},{
-		.id            = V4L2_CID_AUDIO_LOUDNESS,
-		.name          = "Loudness",
-		.minimum       = 0,
-		.maximum       = 1,
-		.step          = 1,
-		.default_value = 1,
-		.flags         = 0,
-		.type          = V4L2_CTRL_TYPE_BOOLEAN,
-	},
-};
-
-
 static int msp_get_ctrl(struct i2c_client *client, struct v4l2_control *ctrl)
 {
 	struct msp_state *state = i2c_get_clientdata(client);
@@ -674,22 +613,31 @@
 		int sc1_out = rt->output & 0xf;
 		int sc2_out = (rt->output >> 4) & 0xf;
 		u16 val, reg;
+		int i;
+		int extern_input = 1;
 
 		if (state->routing.input == rt->input &&
 		    state->routing.output == rt->output)
 			break;
 		state->routing = *rt;
+		/* check if the tuner input is used */
+		for (i = 0; i < 5; i++) {
+			if (((rt->input >> (4 + i * 4)) & 0xf) == 0)
+				extern_input = 0;
+		}
+		if (extern_input)
+			state->mode = MSP_MODE_EXTERN;
+		else
+			state->mode = MSP_MODE_AM_DETECT;
 		msp_set_scart(client, sc_in, 0);
 		msp_set_scart(client, sc1_out, 1);
 		msp_set_scart(client, sc2_out, 2);
 		msp_set_audmode(client);
 		reg = (state->opmode == OPMODE_AUTOSELECT) ? 0x30 : 0xbb;
 		val = msp_read_dem(client, reg);
-		if (tuner != ((val >> 8) & 1)) {
-			msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
-			/* wake thread when a new tuner input is chosen */
-			msp_wake_thread(client);
-		}
+		msp_write_dem(client, reg, (val & ~0x100) | (tuner << 8));
+		/* wake thread when a new input is chosen */
+		msp_wake_thread(client);
 		break;
 	}
 
@@ -744,21 +692,25 @@
 	case VIDIOC_QUERYCTRL:
 	{
 		struct v4l2_queryctrl *qc = arg;
-		int i;
 
-		for (i = 0; i < ARRAY_SIZE(msp_qctrl_std); i++)
-			if (qc->id && qc->id == msp_qctrl_std[i].id) {
-				memcpy(qc, &msp_qctrl_std[i], sizeof(*qc));
-				return 0;
-			}
+		switch (qc->id) {
+			case V4L2_CID_AUDIO_VOLUME:
+			case V4L2_CID_AUDIO_MUTE:
+				return v4l2_ctrl_query_fill_std(qc);
+			default:
+				break;
+		}
 		if (!state->has_sound_processing)
 			return -EINVAL;
-		for (i = 0; i < ARRAY_SIZE(msp_qctrl_sound_processing); i++)
-			if (qc->id && qc->id == msp_qctrl_sound_processing[i].id) {
-				memcpy(qc, &msp_qctrl_sound_processing[i], sizeof(*qc));
-				return 0;
-			}
-		return -EINVAL;
+		switch (qc->id) {
+			case V4L2_CID_AUDIO_LOUDNESS:
+			case V4L2_CID_AUDIO_BALANCE:
+			case V4L2_CID_AUDIO_BASS:
+			case V4L2_CID_AUDIO_TREBLE:
+				return v4l2_ctrl_query_fill_std(qc);
+			default:
+				return -EINVAL;
+		}
 	}
 
 	case VIDIOC_G_CTRL:
@@ -794,7 +746,9 @@
 		case MSP_MODE_EXTERN: p = "External input"; break;
 		default: p = "unknown"; break;
 		}
-		if (state->opmode == OPMODE_MANUAL) {
+		if (state->mode == MSP_MODE_EXTERN) {
+			v4l_info(client, "Mode:     %s\n", p);
+		} else if (state->opmode == OPMODE_MANUAL) {
 			v4l_info(client, "Mode:     %s (%s%s)\n", p,
 				(state->rxsubchans & V4L2_TUNER_SUB_STEREO) ? "stereo" : "mono",
 				(state->rxsubchans & V4L2_TUNER_SUB_LANG2) ? ", dual" : "");
diff --git a/drivers/media/video/msp3400-kthreads.c b/drivers/media/video/msp3400-kthreads.c
index 633a102..f2fd919 100644
--- a/drivers/media/video/msp3400-kthreads.c
+++ b/drivers/media/video/msp3400-kthreads.c
@@ -244,19 +244,21 @@
 	   the hardware does not support SAP. So the rxsubchans combination
 	   of STEREO | LANG2 does not occur. */
 
-	/* switch to mono if only mono is available */
-	if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
-		audmode = V4L2_TUNER_MODE_MONO;
-	/* if bilingual */
-	else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
-		/* and mono or stereo, then fallback to lang1 */
-		if (audmode == V4L2_TUNER_MODE_MONO ||
-		    audmode == V4L2_TUNER_MODE_STEREO)
-			audmode = V4L2_TUNER_MODE_LANG1;
+	if (state->mode != MSP_MODE_EXTERN) {
+		/* switch to mono if only mono is available */
+		if (state->rxsubchans == V4L2_TUNER_SUB_MONO)
+			audmode = V4L2_TUNER_MODE_MONO;
+		/* if bilingual */
+		else if (state->rxsubchans & V4L2_TUNER_SUB_LANG2) {
+			/* and mono or stereo, then fallback to lang1 */
+			if (audmode == V4L2_TUNER_MODE_MONO ||
+			    audmode == V4L2_TUNER_MODE_STEREO)
+				audmode = V4L2_TUNER_MODE_LANG1;
+		}
+		/* if stereo, and audmode is not mono, then switch to stereo */
+		else if (audmode != V4L2_TUNER_MODE_MONO)
+			audmode = V4L2_TUNER_MODE_STEREO;
 	}
-	/* if stereo, and audmode is not mono, then switch to stereo */
-	else if (audmode != V4L2_TUNER_MODE_MONO)
-		audmode = V4L2_TUNER_MODE_STEREO;
 
 	/* switch demodulator */
 	switch (state->mode) {
@@ -481,6 +483,7 @@
 			/* no carrier scan, just unmute */
 			v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
 			state->scan_in_progress = 0;
+			state->rxsubchans = V4L2_TUNER_SUB_STEREO;
 			msp_set_audio(client);
 			continue;
 		}
@@ -947,6 +950,14 @@
 		if (kthread_should_stop())
 			break;
 
+		if (state->mode == MSP_MODE_EXTERN) {
+			/* no carrier scan needed, just unmute */
+			v4l_dbg(1, msp_debug, client, "thread: no carrier scan\n");
+			state->scan_in_progress = 0;
+			msp_set_audio(client);
+			continue;
+		}
+
 		/* setup the chip*/
 		msp34xxg_reset(client);
 		state->std = state->radio ? 0x40 : msp_standard;
@@ -978,6 +989,11 @@
 		v4l_dbg(1, msp_debug, client, "detected standard: %s (0x%04x)\n",
 			msp_standard_std_name(state->std), state->std);
 
+		if (state->std == 9) {
+			/* AM NICAM mode */
+			msp_write_dsp(client, 0x0e, 0x7c00);
+		}
+
 		/* unmute: dispatch sound to scart output, set scart volume */
 		msp_set_audio(client);
 
diff --git a/drivers/media/video/ov511.c b/drivers/media/video/ov511.c
index fdc8e3f..a988df2 100644
--- a/drivers/media/video/ov511.c
+++ b/drivers/media/video/ov511.c
@@ -3239,7 +3239,7 @@
 		RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
 
 		if (frame->scanstate == STATE_LINES) {
-	    		int nextf;
+			int nextf;
 
 			frame->grabstate = FRAME_DONE;
 			wake_up_interruptible(&frame->wq);
@@ -3405,7 +3405,7 @@
 	RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
 
 	if (frame->scanstate == STATE_LINES) {
-    		int nextf;
+		int nextf;
 
 		frame->grabstate = FRAME_DONE;
 		wake_up_interruptible(&frame->wq);
diff --git a/drivers/media/video/ov511.h b/drivers/media/video/ov511.h
index 12b3d51..68b082b 100644
--- a/drivers/media/video/ov511.h
+++ b/drivers/media/video/ov511.h
@@ -3,6 +3,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
diff --git a/drivers/media/video/planb.c b/drivers/media/video/planb.c
index d9e3cad..3484e36 100644
--- a/drivers/media/video/planb.c
+++ b/drivers/media/video/planb.c
@@ -40,6 +40,7 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff --git a/drivers/media/video/pms.c b/drivers/media/video/pms.c
index 09835ca..5d681fa 100644
--- a/drivers/media/video/pms.c
+++ b/drivers/media/video/pms.c
@@ -30,6 +30,7 @@
 #include <asm/io.h>
 #include <linux/sched.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include <asm/uaccess.h>
@@ -804,7 +805,7 @@
 			struct video_picture *p = arg;
 			if(!((p->palette==VIDEO_PALETTE_RGB565 && p->depth==16)
 			    ||(p->palette==VIDEO_PALETTE_RGB555 && p->depth==15)))
-			    	return -EINVAL;
+				return -EINVAL;
 			pd->picture= *p;
 
 			/*
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig
new file mode 100644
index 0000000..7e727fe
--- /dev/null
+++ b/drivers/media/video/pvrusb2/Kconfig
@@ -0,0 +1,62 @@
+config VIDEO_PVRUSB2
+	tristate "Hauppauge WinTV-PVR USB2 support"
+	depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL
+	select FW_LOADER
+	select VIDEO_TUNER
+	select VIDEO_TVEEPROM
+	select VIDEO_CX2341X
+	select VIDEO_SAA711X
+	select VIDEO_MSP3400
+	---help---
+	  This is a video4linux driver for Conexant 23416 based
+	  usb2 personal video recorder devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pvrusb2
+
+config VIDEO_PVRUSB2_24XXX
+	bool "Hauppauge WinTV-PVR USB2 support for 24xxx model series"
+	depends on VIDEO_PVRUSB2 && EXPERIMENTAL
+	select VIDEO_CX25840
+	select VIDEO_WM8775
+	---help---
+	  This option enables inclusion of additional logic to operate
+	  newer WinTV-PVR USB2 devices whose model number is of the
+	  form "24xxx" (leading prefix of "24" followed by 3 digits).
+	  To see if you may need this option, examine the white
+	  sticker on the underside of your device.  Enabling this
+	  option will not harm support for older devices, however it
+	  is a separate option because of the experimental nature of
+	  this new feature.
+
+	  If you are in doubt, say N.
+
+	  Note: This feature is _very_ experimental.  You have been
+	  warned.
+
+config VIDEO_PVRUSB2_SYSFS
+	bool "pvrusb2 sysfs support (EXPERIMENTAL)"
+	default y
+	depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL
+	---help---
+	  This option enables the operation of a sysfs based
+	  interface for query and control of the pvrusb2 driver.
+
+	  This is not generally needed for v4l applications,
+	  although certain applications are optimized to take
+	  advantage of this feature.
+
+	  If you are in doubt, say Y.
+
+	  Note: This feature is experimental and subject to change.
+
+config VIDEO_PVRUSB2_DEBUGIFC
+	bool "pvrusb2 debug interface"
+	depends on VIDEO_PVRUSB2_SYSFS
+	---help---
+	  This option enables the inclusion of a debug interface
+	  in the pvrusb2 driver, hosted through sysfs.
+
+	  You do not need to select this option unless you plan
+	  on debugging the driver or performing a manual firmware
+	  extraction.
diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile
new file mode 100644
index 0000000..fed603a
--- /dev/null
+++ b/drivers/media/video/pvrusb2/Makefile
@@ -0,0 +1,18 @@
+obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o
+obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o
+
+obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \
+		   pvrusb2-cx2584x-v4l.o \
+		   pvrusb2-wm8775.o
+
+pvrusb2-objs	:= pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \
+		   pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \
+		   pvrusb2-encoder.o pvrusb2-video-v4l.o \
+		   pvrusb2-eeprom.o pvrusb2-tuner.o pvrusb2-demod.o \
+		   pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \
+		   pvrusb2-ctrl.o pvrusb2-std.o \
+		   pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \
+		   $(obj-pvrusb2-24xxx-y) \
+		   $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y)
+
+obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c
new file mode 100644
index 0000000..313d2dc
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c
@@ -0,0 +1,204 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-audio.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/msp3400.h>
+#include <media/v4l2-common.h>
+
+struct pvr2_msp3400_handler {
+	struct pvr2_hdw *hdw;
+	struct pvr2_i2c_client *client;
+	struct pvr2_i2c_handler i2c_handler;
+	struct pvr2_audio_stat astat;
+	unsigned long stale_mask;
+};
+
+
+/* This function selects the correct audio input source */
+static void set_stereo(struct pvr2_msp3400_handler *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	struct v4l2_routing route;
+
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo");
+
+	if (hdw->input_val == PVR2_CVAL_INPUT_TV) {
+		struct v4l2_tuner vt;
+		memset(&vt,0,sizeof(vt));
+		vt.audmode = hdw->audiomode_val;
+		pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt);
+	}
+
+	route.input = MSP_INPUT_DEFAULT;
+	route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
+	switch (hdw->input_val) {
+	case PVR2_CVAL_INPUT_TV:
+		break;
+	case PVR2_CVAL_INPUT_RADIO:
+		/* Assume that msp34xx also handle FM decoding, in which case
+		   we're still using the tuner. */
+		/* HV: actually it is more likely to be the SCART2 input if
+		   the ivtv experience is any indication. */
+		route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+		break;
+	case PVR2_CVAL_INPUT_SVIDEO:
+	case PVR2_CVAL_INPUT_COMPOSITE:
+		/* SCART 1 input */
+		route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1,
+				    MSP_DSP_IN_SCART, MSP_DSP_IN_SCART);
+		break;
+	}
+	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
+}
+
+
+static int check_stereo(struct pvr2_msp3400_handler *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	return (hdw->input_dirty ||
+		hdw->audiomode_dirty);
+}
+
+
+struct pvr2_msp3400_ops {
+	void (*update)(struct pvr2_msp3400_handler *);
+	int (*check)(struct pvr2_msp3400_handler *);
+};
+
+
+static const struct pvr2_msp3400_ops msp3400_ops[] = {
+	{ .update = set_stereo, .check = check_stereo},
+};
+
+
+static int msp3400_check(struct pvr2_msp3400_handler *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (ctxt->stale_mask & msk) continue;
+		if (msp3400_ops[idx].check(ctxt)) {
+			ctxt->stale_mask |= msk;
+		}
+	}
+	return ctxt->stale_mask != 0;
+}
+
+
+static void msp3400_update(struct pvr2_msp3400_handler *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (!(ctxt->stale_mask & msk)) continue;
+		ctxt->stale_mask &= ~msk;
+		msp3400_ops[idx].update(ctxt);
+	}
+}
+
+
+/* This reads back the current signal type */
+static int get_audio_status(struct pvr2_msp3400_handler *ctxt)
+{
+	struct v4l2_tuner vt;
+	int stat;
+
+	memset(&vt,0,sizeof(vt));
+	stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
+	if (stat < 0) return stat;
+
+	ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0;
+	ctxt->hdw->flag_bilingual =
+		(vt.audmode & V4L2_TUNER_MODE_LANG2) != 0;
+	return 0;
+}
+
+
+static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt)
+{
+	ctxt->client->handler = 0;
+	ctxt->hdw->audio_stat = 0;
+	kfree(ctxt);
+}
+
+
+static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt,
+					  char *buf,unsigned int cnt)
+{
+	return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2");
+}
+
+
+const static struct pvr2_i2c_handler_functions msp3400_funcs = {
+	.detach = (void (*)(void *))pvr2_msp3400_detach,
+	.check = (int (*)(void *))msp3400_check,
+	.update = (void (*)(void *))msp3400_update,
+	.describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe,
+};
+
+
+int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+	struct pvr2_msp3400_handler *ctxt;
+	if (hdw->audio_stat) return 0;
+	if (cp->handler) return 0;
+
+	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	if (!ctxt) return 0;
+	memset(ctxt,0,sizeof(*ctxt));
+
+	ctxt->i2c_handler.func_data = ctxt;
+	ctxt->i2c_handler.func_table = &msp3400_funcs;
+	ctxt->client = cp;
+	ctxt->hdw = hdw;
+	ctxt->astat.ctxt = ctxt;
+	ctxt->astat.status = (int (*)(void *))get_audio_status;
+	ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach;
+	ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/
+				  sizeof(msp3400_ops[0]))) - 1;
+	cp->handler = &ctxt->i2c_handler;
+	hdw->audio_stat = &ctxt->astat;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up",
+		   cp->client->addr);
+	return !0;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h
new file mode 100644
index 0000000..536339b
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h
@@ -0,0 +1,40 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_AUDIO_H
+#define __PVRUSB2_AUDIO_H
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+#endif /* __PVRUSB2_AUDIO_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c
new file mode 100644
index 0000000..40dc598
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.c
@@ -0,0 +1,230 @@
+/*
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-context.h"
+#include "pvrusb2-io.h"
+#include "pvrusb2-ioread.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+
+
+static void pvr2_context_destroy(struct pvr2_context *mp)
+{
+	if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
+	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
+	flush_workqueue(mp->workqueue);
+	destroy_workqueue(mp->workqueue);
+	kfree(mp);
+}
+
+
+static void pvr2_context_trigger_poll(struct pvr2_context *mp)
+{
+	queue_work(mp->workqueue,&mp->workpoll);
+}
+
+
+static void pvr2_context_poll(struct pvr2_context *mp)
+{
+	pvr2_context_enter(mp); do {
+		pvr2_hdw_poll(mp->hdw);
+	} while (0); pvr2_context_exit(mp);
+}
+
+
+static void pvr2_context_setup(struct pvr2_context *mp)
+{
+	pvr2_context_enter(mp); do {
+		if (!pvr2_hdw_dev_ok(mp->hdw)) break;
+		pvr2_hdw_setup(mp->hdw);
+		pvr2_hdw_setup_poll_trigger(
+			mp->hdw,
+			(void (*)(void *))pvr2_context_trigger_poll,
+			mp);
+		if (!pvr2_hdw_dev_ok(mp->hdw)) break;
+		if (!pvr2_hdw_init_ok(mp->hdw)) break;
+		mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
+		if (mp->setup_func) {
+			mp->setup_func(mp);
+		}
+	} while (0); pvr2_context_exit(mp);
+}
+
+
+struct pvr2_context *pvr2_context_create(
+	struct usb_interface *intf,
+	const struct usb_device_id *devid,
+	void (*setup_func)(struct pvr2_context *))
+{
+	struct pvr2_context *mp = 0;
+	mp = kmalloc(sizeof(*mp),GFP_KERNEL);
+	if (!mp) goto done;
+	memset(mp,0,sizeof(*mp));
+	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
+	mp->setup_func = setup_func;
+	mutex_init(&mp->mutex);
+	mp->hdw = pvr2_hdw_create(intf,devid);
+	if (!mp->hdw) {
+		pvr2_context_destroy(mp);
+		mp = 0;
+		goto done;
+	}
+
+	mp->workqueue = create_singlethread_workqueue("pvrusb2");
+	INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp);
+	INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp);
+	queue_work(mp->workqueue,&mp->workinit);
+ done:
+	return mp;
+}
+
+
+void pvr2_context_enter(struct pvr2_context *mp)
+{
+	mutex_lock(&mp->mutex);
+	pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
+}
+
+
+void pvr2_context_exit(struct pvr2_context *mp)
+{
+	int destroy_flag = 0;
+	if (!(mp->mc_first || !mp->disconnect_flag)) {
+		destroy_flag = !0;
+	}
+	pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
+	mutex_unlock(&mp->mutex);
+	if (destroy_flag) pvr2_context_destroy(mp);
+}
+
+
+static void pvr2_context_run_checks(struct pvr2_context *mp)
+{
+	struct pvr2_channel *ch1,*ch2;
+	for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
+		ch2 = ch1->mc_next;
+		if (ch1->check_func) {
+			ch1->check_func(ch1);
+		}
+	}
+}
+
+
+void pvr2_context_disconnect(struct pvr2_context *mp)
+{
+	pvr2_context_enter(mp); do {
+		pvr2_hdw_disconnect(mp->hdw);
+		mp->disconnect_flag = !0;
+		pvr2_context_run_checks(mp);
+	} while (0); pvr2_context_exit(mp);
+}
+
+
+void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
+{
+	cp->hdw = mp->hdw;
+	cp->mc_head = mp;
+	cp->mc_next = 0;
+	cp->mc_prev = mp->mc_last;
+	if (mp->mc_last) {
+		mp->mc_last->mc_next = cp;
+	} else {
+		mp->mc_first = cp;
+	}
+	mp->mc_last = cp;
+}
+
+
+static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
+{
+	if (!cp->stream) return;
+	pvr2_stream_kill(cp->stream->stream);
+	cp->stream->user = 0;
+	cp->stream = 0;
+}
+
+
+void pvr2_channel_done(struct pvr2_channel *cp)
+{
+	struct pvr2_context *mp = cp->mc_head;
+	pvr2_channel_disclaim_stream(cp);
+	if (cp->mc_next) {
+		cp->mc_next->mc_prev = cp->mc_prev;
+	} else {
+		mp->mc_last = cp->mc_prev;
+	}
+	if (cp->mc_prev) {
+		cp->mc_prev->mc_next = cp->mc_next;
+	} else {
+		mp->mc_first = cp->mc_next;
+	}
+	cp->hdw = 0;
+}
+
+
+int pvr2_channel_claim_stream(struct pvr2_channel *cp,
+			      struct pvr2_context_stream *sp)
+{
+	int code = 0;
+	pvr2_context_enter(cp->mc_head); do {
+		if (sp == cp->stream) break;
+		if (sp->user) {
+			code = -EBUSY;
+			break;
+		}
+		pvr2_channel_disclaim_stream(cp);
+		if (!sp) break;
+		sp->user = cp;
+		cp->stream = sp;
+	} while (0); pvr2_context_exit(cp->mc_head);
+	return code;
+}
+
+
+// This is the marker for the real beginning of a legitimate mpeg2 stream.
+static char stream_sync_key[] = {
+	0x00, 0x00, 0x01, 0xba,
+};
+
+struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+	struct pvr2_context_stream *sp)
+{
+	struct pvr2_ioread *cp;
+	cp = pvr2_ioread_create();
+	if (!cp) return 0;
+	pvr2_ioread_setup(cp,sp->stream);
+	pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key));
+	return cp;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h
new file mode 100644
index 0000000..6327fa1
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-context.h
@@ -0,0 +1,92 @@
+/*
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_BASE_H
+#define __PVRUSB2_BASE_H
+
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+
+struct pvr2_hdw;     /* hardware interface - defined elsewhere */
+struct pvr2_stream;  /* stream interface - defined elsewhere */
+
+struct pvr2_context;        /* All central state */
+struct pvr2_channel;        /* One I/O pathway to a user */
+struct pvr2_context_stream; /* Wrapper for a stream */
+struct pvr2_crit_reg;       /* Critical region pointer */
+struct pvr2_ioread;         /* Low level stream structure */
+
+struct pvr2_context_stream {
+	struct pvr2_channel *user;
+	struct pvr2_stream *stream;
+};
+
+struct pvr2_context {
+	struct pvr2_channel *mc_first;
+	struct pvr2_channel *mc_last;
+	struct pvr2_hdw *hdw;
+	struct pvr2_context_stream video_stream;
+	struct mutex mutex;
+	int disconnect_flag;
+
+	/* Called after pvr2_context initialization is complete */
+	void (*setup_func)(struct pvr2_context *);
+
+	/* Work queue overhead for out-of-line processing */
+	struct workqueue_struct *workqueue;
+	struct work_struct workinit;
+	struct work_struct workpoll;
+};
+
+struct pvr2_channel {
+	struct pvr2_context *mc_head;
+	struct pvr2_channel *mc_next;
+	struct pvr2_channel *mc_prev;
+	struct pvr2_context_stream *stream;
+	struct pvr2_hdw *hdw;
+	void (*check_func)(struct pvr2_channel *);
+};
+
+void pvr2_context_enter(struct pvr2_context *);
+void pvr2_context_exit(struct pvr2_context *);
+
+struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
+					 const struct usb_device_id *devid,
+					 void (*setup_func)(struct pvr2_context *));
+void pvr2_context_disconnect(struct pvr2_context *);
+
+void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *);
+void pvr2_channel_done(struct pvr2_channel *);
+int pvr2_channel_claim_stream(struct pvr2_channel *,
+			      struct pvr2_context_stream *);
+struct pvr2_ioread *pvr2_channel_create_mpeg_stream(
+	struct pvr2_context_stream *);
+
+
+#endif /* __PVRUSB2_CONTEXT_H */
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
new file mode 100644
index 0000000..d5df9fb
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c
@@ -0,0 +1,593 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-ctrl.h"
+#include "pvrusb2-hdw-internal.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mutex.h>
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
+{
+	return pvr2_ctrl_set_mask_value(cptr,~0,val);
+}
+
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
+{
+	int ret = 0;
+	if (!cptr) return -EINVAL;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->set_value != 0) {
+			if (cptr->info->type == pvr2_ctl_bitmask) {
+				mask &= cptr->info->def.type_bitmask.valid_bits;
+			} else if (cptr->info->type == pvr2_ctl_int) {
+				if (val < cptr->info->def.type_int.min_value) {
+					break;
+				}
+				if (val > cptr->info->def.type_int.max_value) {
+					break;
+				}
+			} else if (cptr->info->type == pvr2_ctl_enum) {
+				if (val >= cptr->info->def.type_enum.count) {
+					break;
+				}
+			} else if (cptr->info->type != pvr2_ctl_bool) {
+				break;
+			}
+			ret = cptr->info->set_value(cptr,mask,val);
+		} else {
+			ret = -EPERM;
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
+{
+	int ret = 0;
+	if (!cptr) return -EINVAL;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		ret = cptr->info->get_value(cptr,valptr);
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
+{
+	if (!cptr) return pvr2_ctl_int;
+	return cptr->info->type;
+}
+
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
+{
+	int ret = 0;
+	if (!cptr) return 0;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->type == pvr2_ctl_int) {
+			ret = cptr->info->def.type_int.max_value;
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
+{
+	int ret = 0;
+	if (!cptr) return 0;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->type == pvr2_ctl_int) {
+			ret = cptr->info->def.type_int.min_value;
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr)
+{
+	int ret = 0;
+	if (!cptr) return 0;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->type == pvr2_ctl_int) {
+			ret = cptr->info->default_value;
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
+{
+	int ret = 0;
+	if (!cptr) return 0;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->type == pvr2_ctl_enum) {
+			ret = cptr->info->def.type_enum.count;
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
+{
+	int ret = 0;
+	if (!cptr) return 0;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->type == pvr2_ctl_bitmask) {
+			ret = cptr->info->def.type_bitmask.valid_bits;
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
+{
+	if (!cptr) return 0;
+	return cptr->info->name;
+}
+
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
+{
+	if (!cptr) return 0;
+	return cptr->info->desc;
+}
+
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
+			  char *bptr,unsigned int bmax,
+			  unsigned int *blen)
+{
+	int ret = -EINVAL;
+	if (!cptr) return 0;
+	*blen = 0;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->type == pvr2_ctl_enum) {
+			const char **names;
+			names = cptr->info->def.type_enum.value_names;
+			if ((val >= 0) &&
+			    (val < cptr->info->def.type_enum.count)) {
+				if (names[val]) {
+					*blen = scnprintf(
+						bptr,bmax,"%s",
+						names[val]);
+				} else {
+					*blen = 0;
+				}
+				ret = 0;
+			}
+		} else if (cptr->info->type == pvr2_ctl_bitmask) {
+			const char **names;
+			unsigned int idx;
+			int msk;
+			names = cptr->info->def.type_bitmask.bit_names;
+			val &= cptr->info->def.type_bitmask.valid_bits;
+			for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
+				if (val & msk) {
+					*blen = scnprintf(bptr,bmax,"%s",
+							  names[idx]);
+					ret = 0;
+					break;
+				}
+			}
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
+{
+	if (!cptr) return 0;
+	return cptr->info->v4l_id;
+}
+
+
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
+{
+	unsigned int flags = 0;
+
+	if (cptr->info->get_v4lflags) {
+		flags = cptr->info->get_v4lflags(cptr);
+	}
+
+	if (cptr->info->set_value) {
+		flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
+	} else {
+		flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	}
+
+	return flags;
+}
+
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
+{
+	if (!cptr) return 0;
+	return cptr->info->set_value != 0;
+}
+
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
+{
+	if (!cptr) return 0;
+	if (!cptr->info->val_to_sym) return 0;
+	if (!cptr->info->sym_to_val) return 0;
+	return !0;
+}
+
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
+				  int mask,int val,
+				  char *buf,unsigned int maxlen,
+				  unsigned int *len)
+{
+	if (!cptr) return -EINVAL;
+	if (!cptr->info->val_to_sym) return -EINVAL;
+	return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
+				  const char *buf,unsigned int len,
+				  int *maskptr,int *valptr)
+{
+	if (!cptr) return -EINVAL;
+	if (!cptr->info->sym_to_val) return -EINVAL;
+	return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
+}
+
+
+static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
+				       const char **names,
+				       char *ptr,unsigned int len)
+{
+	unsigned int idx;
+	long sm,um;
+	int spcFl;
+	unsigned int uc,cnt;
+	const char *idStr;
+
+	spcFl = 0;
+	uc = 0;
+	um = 0;
+	for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
+		if (sm & msk) {
+			msk &= ~sm;
+			idStr = names[idx];
+			if (idStr) {
+				cnt = scnprintf(ptr,len,"%s%s%s",
+						(spcFl ? " " : ""),
+						(msk_only ? "" :
+						 ((val & sm) ? "+" : "-")),
+						idStr);
+				ptr += cnt; len -= cnt; uc += cnt;
+				spcFl = !0;
+			} else {
+				um |= sm;
+			}
+		}
+	}
+	if (um) {
+		if (msk_only) {
+			cnt = scnprintf(ptr,len,"%s0x%lx",
+					(spcFl ? " " : ""),
+					um);
+			ptr += cnt; len -= cnt; uc += cnt;
+			spcFl = !0;
+		} else if (um & val) {
+			cnt = scnprintf(ptr,len,"%s+0x%lx",
+					(spcFl ? " " : ""),
+					um & val);
+			ptr += cnt; len -= cnt; uc += cnt;
+			spcFl = !0;
+		} else if (um & ~val) {
+			cnt = scnprintf(ptr,len,"%s+0x%lx",
+					(spcFl ? " " : ""),
+					um & ~val);
+			ptr += cnt; len -= cnt; uc += cnt;
+			spcFl = !0;
+		}
+	}
+	return uc;
+}
+
+
+static const char *boolNames[] = {
+	"false",
+	"true",
+	"no",
+	"yes",
+};
+
+
+static int parse_token(const char *ptr,unsigned int len,
+		       int *valptr,
+		       const char **names,unsigned int namecnt)
+{
+	char buf[33];
+	unsigned int slen;
+	unsigned int idx;
+	int negfl;
+	char *p2;
+	*valptr = 0;
+	if (!names) namecnt = 0;
+	for (idx = 0; idx < namecnt; idx++) {
+		if (!names[idx]) continue;
+		slen = strlen(names[idx]);
+		if (slen != len) continue;
+		if (memcmp(names[idx],ptr,slen)) continue;
+		*valptr = idx;
+		return 0;
+	}
+	negfl = 0;
+	if ((*ptr == '-') || (*ptr == '+')) {
+		negfl = (*ptr == '-');
+		ptr++; len--;
+	}
+	if (len >= sizeof(buf)) return -EINVAL;
+	memcpy(buf,ptr,len);
+	buf[len] = 0;
+	*valptr = simple_strtol(buf,&p2,0);
+	if (negfl) *valptr = -(*valptr);
+	if (*p2) return -EINVAL;
+	return 1;
+}
+
+
+static int parse_mtoken(const char *ptr,unsigned int len,
+			int *valptr,
+			const char **names,int valid_bits)
+{
+	char buf[33];
+	unsigned int slen;
+	unsigned int idx;
+	char *p2;
+	int msk;
+	*valptr = 0;
+	for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
+		if (!msk & valid_bits) continue;
+		valid_bits &= ~msk;
+		if (!names[idx]) continue;
+		slen = strlen(names[idx]);
+		if (slen != len) continue;
+		if (memcmp(names[idx],ptr,slen)) continue;
+		*valptr = msk;
+		return 0;
+	}
+	if (len >= sizeof(buf)) return -EINVAL;
+	memcpy(buf,ptr,len);
+	buf[len] = 0;
+	*valptr = simple_strtol(buf,&p2,0);
+	if (*p2) return -EINVAL;
+	return 0;
+}
+
+
+static int parse_tlist(const char *ptr,unsigned int len,
+		       int *maskptr,int *valptr,
+		       const char **names,int valid_bits)
+{
+	unsigned int cnt;
+	int mask,val,kv,mode,ret;
+	mask = 0;
+	val = 0;
+	ret = 0;
+	while (len) {
+		cnt = 0;
+		while ((cnt < len) &&
+		       ((ptr[cnt] <= 32) ||
+			(ptr[cnt] >= 127))) cnt++;
+		ptr += cnt;
+		len -= cnt;
+		mode = 0;
+		if ((*ptr == '-') || (*ptr == '+')) {
+			mode = (*ptr == '-') ? -1 : 1;
+			ptr++;
+			len--;
+		}
+		cnt = 0;
+		while (cnt < len) {
+			if (ptr[cnt] <= 32) break;
+			if (ptr[cnt] >= 127) break;
+			cnt++;
+		}
+		if (!cnt) break;
+		if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
+			ret = -EINVAL;
+			break;
+		}
+		ptr += cnt;
+		len -= cnt;
+		switch (mode) {
+		case 0:
+			mask = valid_bits;
+			val |= kv;
+			break;
+		case -1:
+			mask |= kv;
+			val &= ~kv;
+			break;
+		case 1:
+			mask |= kv;
+			val |= kv;
+			break;
+		default:
+			break;
+		}
+	}
+	*maskptr = mask;
+	*valptr = val;
+	return ret;
+}
+
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
+			   const char *ptr,unsigned int len,
+			   int *maskptr,int *valptr)
+{
+	int ret = -EINVAL;
+	unsigned int cnt;
+
+	*maskptr = 0;
+	*valptr = 0;
+
+	cnt = 0;
+	while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
+	len -= cnt; ptr += cnt;
+	cnt = 0;
+	while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
+			       (ptr[len-(cnt+1)] >= 127))) cnt++;
+	len -= cnt;
+
+	if (!len) return -EINVAL;
+
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		if (cptr->info->type == pvr2_ctl_int) {
+			ret = parse_token(ptr,len,valptr,0,0);
+			if ((ret >= 0) &&
+			    ((*valptr < cptr->info->def.type_int.min_value) ||
+			     (*valptr > cptr->info->def.type_int.max_value))) {
+				ret = -ERANGE;
+			}
+			if (maskptr) *maskptr = ~0;
+		} else if (cptr->info->type == pvr2_ctl_bool) {
+			ret = parse_token(
+				ptr,len,valptr,boolNames,
+				sizeof(boolNames)/sizeof(boolNames[0]));
+			if (ret == 1) {
+				*valptr = *valptr ? !0 : 0;
+			} else if (ret == 0) {
+				*valptr = (*valptr & 1) ? !0 : 0;
+			}
+			if (maskptr) *maskptr = 1;
+		} else if (cptr->info->type == pvr2_ctl_enum) {
+			ret = parse_token(
+				ptr,len,valptr,
+				cptr->info->def.type_enum.value_names,
+				cptr->info->def.type_enum.count);
+			if ((ret >= 0) &&
+			    ((*valptr < 0) ||
+			     (*valptr >= cptr->info->def.type_enum.count))) {
+				ret = -ERANGE;
+			}
+			if (maskptr) *maskptr = ~0;
+		} else if (cptr->info->type == pvr2_ctl_bitmask) {
+			ret = parse_tlist(
+				ptr,len,maskptr,valptr,
+				cptr->info->def.type_bitmask.bit_names,
+				cptr->info->def.type_bitmask.valid_bits);
+		}
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
+				    int mask,int val,
+				    char *buf,unsigned int maxlen,
+				    unsigned int *len)
+{
+	int ret = -EINVAL;
+
+	*len = 0;
+	if (cptr->info->type == pvr2_ctl_int) {
+		*len = scnprintf(buf,maxlen,"%d",val);
+		ret = 0;
+	} else if (cptr->info->type == pvr2_ctl_bool) {
+		*len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
+		ret = 0;
+	} else if (cptr->info->type == pvr2_ctl_enum) {
+		const char **names;
+		names = cptr->info->def.type_enum.value_names;
+		if ((val >= 0) &&
+		    (val < cptr->info->def.type_enum.count)) {
+			if (names[val]) {
+				*len = scnprintf(
+					buf,maxlen,"%s",
+					names[val]);
+			} else {
+				*len = 0;
+			}
+			ret = 0;
+		}
+	} else if (cptr->info->type == pvr2_ctl_bitmask) {
+		*len = gen_bitmask_string(
+			val & mask & cptr->info->def.type_bitmask.valid_bits,
+			~0,!0,
+			cptr->info->def.type_bitmask.bit_names,
+			buf,maxlen);
+	}
+	return ret;
+}
+
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
+			   int mask,int val,
+			   char *buf,unsigned int maxlen,
+			   unsigned int *len)
+{
+	int ret;
+	LOCK_TAKE(cptr->hdw->big_lock); do {
+		ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
+						      buf,maxlen,len);
+	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
+	return ret;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
new file mode 100644
index 0000000..c1680053
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h
@@ -0,0 +1,123 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_CTRL_H
+#define __PVRUSB2_CTRL_H
+
+struct pvr2_ctrl;
+
+enum pvr2_ctl_type {
+	pvr2_ctl_int = 0,
+	pvr2_ctl_enum = 1,
+	pvr2_ctl_bitmask = 2,
+	pvr2_ctl_bool = 3,
+};
+
+
+/* Set the given control. */
+int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val);
+
+/* Set/clear specific bits of the given control. */
+int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val);
+
+/* Get the current value of the given control. */
+int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr);
+
+/* Retrieve control's type */
+enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *);
+
+/* Retrieve control's maximum value (int type) */
+int pvr2_ctrl_get_max(struct pvr2_ctrl *);
+
+/* Retrieve control's minimum value (int type) */
+int pvr2_ctrl_get_min(struct pvr2_ctrl *);
+
+/* Retrieve control's default value (any type) */
+int pvr2_ctrl_get_def(struct pvr2_ctrl *);
+
+/* Retrieve control's enumeration count (enum only) */
+int pvr2_ctrl_get_cnt(struct pvr2_ctrl *);
+
+/* Retrieve control's valid mask bits (bit mask only) */
+int pvr2_ctrl_get_mask(struct pvr2_ctrl *);
+
+/* Retrieve the control's name */
+const char *pvr2_ctrl_get_name(struct pvr2_ctrl *);
+
+/* Retrieve the control's desc */
+const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *);
+
+/* Retrieve a control enumeration or bit mask value */
+int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int,
+			  unsigned int *);
+
+/* Return true if control is writable */
+int pvr2_ctrl_is_writable(struct pvr2_ctrl *);
+
+/* Return V4L flags value for control (or zero if there is no v4l control
+   actually under this control) */
+unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *);
+
+/* Return V4L ID for this control or zero if none */
+int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *);
+
+/* Return true if control has custom symbolic representation */
+int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *);
+
+/* Convert a given mask/val to a custom symbolic value */
+int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *,
+				  int mask,int val,
+				  char *buf,unsigned int maxlen,
+				  unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *,
+				  const char *buf,unsigned int len,
+				  int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value */
+int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *,
+			   int mask,int val,
+			   char *buf,unsigned int maxlen,
+			   unsigned int *len);
+
+/* Convert a symbolic value to a mask/value pair */
+int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *,
+			   const char *buf,unsigned int len,
+			   int *maskptr,int *valptr);
+
+/* Convert a given mask/val to a symbolic value - must already be
+   inside of critical region. */
+int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *,
+			   int mask,int val,
+			   char *buf,unsigned int maxlen,
+			   unsigned int *len);
+
+#endif /* __PVRUSB2_CTRL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
new file mode 100644
index 0000000..27eadaf
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
@@ -0,0 +1,279 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   cx2584x, in kernels 2.6.16 or newer.
+
+*/
+
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-video-v4l.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <media/cx25840.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+struct pvr2_v4l_cx2584x {
+	struct pvr2_i2c_handler handler;
+	struct pvr2_decoder_ctrl ctrl;
+	struct pvr2_i2c_client *client;
+	struct pvr2_hdw *hdw;
+	unsigned long stale_mask;
+};
+
+
+static void set_input(struct pvr2_v4l_cx2584x *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	struct v4l2_routing route;
+	enum cx25840_video_input vid_input;
+	enum cx25840_audio_input aud_input;
+
+	memset(&route,0,sizeof(route));
+
+	switch(hdw->input_val) {
+	case PVR2_CVAL_INPUT_TV:
+		vid_input = CX25840_COMPOSITE7;
+		aud_input = CX25840_AUDIO8;
+		break;
+	case PVR2_CVAL_INPUT_COMPOSITE:
+		vid_input = CX25840_COMPOSITE3;
+		aud_input = CX25840_AUDIO_SERIAL;
+		break;
+	case PVR2_CVAL_INPUT_SVIDEO:
+		vid_input = CX25840_SVIDEO1;
+		aud_input = CX25840_AUDIO_SERIAL;
+		break;
+	case PVR2_CVAL_INPUT_RADIO:
+	default:
+		// Just set it to be composite input for now...
+		vid_input = CX25840_COMPOSITE3;
+		aud_input = CX25840_AUDIO_SERIAL;
+		break;
+	}
+
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x",
+		   vid_input,aud_input);
+	route.input = (u32)vid_input;
+	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
+	route.input = (u32)aud_input;
+	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
+}
+
+
+static int check_input(struct pvr2_v4l_cx2584x *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	return hdw->input_dirty != 0;
+}
+
+
+static void set_audio(struct pvr2_v4l_cx2584x *ctxt)
+{
+	u32 val;
+	struct pvr2_hdw *hdw = ctxt->hdw;
+
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d",
+		   hdw->srate_val);
+	switch (hdw->srate_val) {
+	default:
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
+		val = 48000;
+		break;
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+		val = 44100;
+		break;
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+		val = 32000;
+		break;
+	}
+	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
+}
+
+
+static int check_audio(struct pvr2_v4l_cx2584x *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	return hdw->srate_dirty != 0;
+}
+
+
+struct pvr2_v4l_cx2584x_ops {
+	void (*update)(struct pvr2_v4l_cx2584x *);
+	int (*check)(struct pvr2_v4l_cx2584x *);
+};
+
+
+static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = {
+	{ .update = set_input, .check = check_input},
+	{ .update = set_audio, .check = check_audio},
+};
+
+
+static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt)
+{
+	ctxt->client->handler = 0;
+	ctxt->hdw->decoder_ctrl = 0;
+	kfree(ctxt);
+}
+
+
+static int decoder_check(struct pvr2_v4l_cx2584x *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (ctxt->stale_mask & msk) continue;
+		if (decoder_ops[idx].check(ctxt)) {
+			ctxt->stale_mask |= msk;
+		}
+	}
+	return ctxt->stale_mask != 0;
+}
+
+
+static void decoder_update(struct pvr2_v4l_cx2584x *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (!(ctxt->stale_mask & msk)) continue;
+		ctxt->stale_mask &= ~msk;
+		decoder_ops[idx].update(ctxt);
+	}
+}
+
+
+static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl)
+{
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl);
+	pvr2_v4l2_cmd_stream(ctxt->client,fl);
+}
+
+
+static int decoder_detect(struct pvr2_i2c_client *cp)
+{
+	int ret;
+	/* Attempt to query the decoder - let's see if it will answer */
+	struct v4l2_queryctrl qc;
+
+	memset(&qc,0,sizeof(qc));
+
+	qc.id = V4L2_CID_BRIGHTNESS;
+
+	ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc);
+	return ret == 0; /* Return true if it answered */
+}
+
+
+static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt)
+{
+	struct v4l2_tuner vt;
+	int ret;
+
+	memset(&vt,0,sizeof(vt));
+	ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
+	if (ret < 0) return -EINVAL;
+	return vt.signal ? 1 : 0;
+}
+
+
+static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt,
+				     char *buf,unsigned int cnt)
+{
+	return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l");
+}
+
+
+static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt)
+{
+	int ret;
+	ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,0);
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret);
+}
+
+
+const static struct pvr2_i2c_handler_functions hfuncs = {
+	.detach = (void (*)(void *))decoder_detach,
+	.check = (int (*)(void *))decoder_check,
+	.update = (void (*)(void *))decoder_update,
+	.describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
+};
+
+
+int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw,
+			       struct pvr2_i2c_client *cp)
+{
+	struct pvr2_v4l_cx2584x *ctxt;
+
+	if (hdw->decoder_ctrl) return 0;
+	if (cp->handler) return 0;
+	if (!decoder_detect(cp)) return 0;
+
+	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	if (!ctxt) return 0;
+	memset(ctxt,0,sizeof(*ctxt));
+
+	ctxt->handler.func_data = ctxt;
+	ctxt->handler.func_table = &hfuncs;
+	ctxt->ctrl.ctxt = ctxt;
+	ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
+	ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
+	ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
+	ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset;
+	ctxt->client = cp;
+	ctxt->hdw = hdw;
+	ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
+				  sizeof(decoder_ops[0]))) - 1;
+	hdw->decoder_ctrl = &ctxt->ctrl;
+	cp->handler = &ctxt->handler;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up",
+		   cp->client->addr);
+	return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
new file mode 100644
index 0000000..54b2844
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h
@@ -0,0 +1,53 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_CX2584X_V4L_H
+#define __PVRUSB2_CX2584X_V4L_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles combined device audio & video processing.
+   This interface is used internally by the driver; higher level code
+   should only interact through the interface provided by
+   pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+
+#endif /* __PVRUSB2_CX2584X_V4L_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h
new file mode 100644
index 0000000..d95a858
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h
@@ -0,0 +1,67 @@
+/*
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_DEBUG_H
+#define __PVRUSB2_DEBUG_H
+
+extern int pvrusb2_debug;
+
+#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0)
+
+/* These are listed in *rough* order of decreasing usefulness and
+   increasing noise level. */
+#define PVR2_TRACE_INFO       (1 <<  0) // Normal messages
+#define PVR2_TRACE_ERROR_LEGS (1 <<  1) // error messages
+#define PVR2_TRACE_TOLERANCE  (1 <<  2) // track tolerance-affected errors
+#define PVR2_TRACE_TRAP       (1 <<  3) // Trap & report misbehavior from app
+#define PVR2_TRACE_INIT       (1 <<  4) // misc initialization steps
+#define PVR2_TRACE_START_STOP (1 <<  5) // Streaming start / stop
+#define PVR2_TRACE_CTL        (1 <<  6) // commit of control changes
+#define PVR2_TRACE_DEBUG      (1 <<  7) // Temporary debug code
+#define PVR2_TRACE_EEPROM     (1 <<  8) // eeprom parsing / report
+#define PVR2_TRACE_STRUCT     (1 <<  9) // internal struct creation
+#define PVR2_TRACE_OPEN_CLOSE (1 << 10) // application open / close
+#define PVR2_TRACE_CREG       (1 << 11) // Main critical region entry / exit
+#define PVR2_TRACE_SYSFS      (1 << 12) // Sysfs driven I/O
+#define PVR2_TRACE_FIRMWARE   (1 << 13) // firmware upload actions
+#define PVR2_TRACE_CHIPS      (1 << 14) // chip broadcast operation
+#define PVR2_TRACE_I2C        (1 << 15) // I2C related stuff
+#define PVR2_TRACE_I2C_CMD    (1 << 16) // Software commands to I2C modules
+#define PVR2_TRACE_I2C_CORE   (1 << 17) // I2C core debugging
+#define PVR2_TRACE_I2C_TRAF   (1 << 18) // I2C traffic through the adapter
+#define PVR2_TRACE_V4LIOCTL   (1 << 19) // v4l ioctl details
+#define PVR2_TRACE_ENCODER    (1 << 20) // mpeg2 encoder operation
+#define PVR2_TRACE_BUF_POOL   (1 << 21) // Track buffer pool management
+#define PVR2_TRACE_BUF_FLOW   (1 << 22) // Track buffer flow in system
+#define PVR2_TRACE_DATA_FLOW  (1 << 23) // Track data flow
+#define PVR2_TRACE_DEBUGIFC   (1 << 24) // Debug interface actions
+#define PVR2_TRACE_GPIO       (1 << 25) // GPIO state bit changes
+
+
+#endif /* __PVRUSB2_HDW_INTERNAL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
new file mode 100644
index 0000000..586900e
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c
@@ -0,0 +1,478 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include "pvrusb2-debugifc.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-i2c-core.h"
+
+struct debugifc_mask_item {
+	const char *name;
+	unsigned long msk;
+};
+
+static struct debugifc_mask_item mask_items[] = {
+	{"ENC_FIRMWARE",(1<<PVR2_SUBSYS_B_ENC_FIRMWARE)},
+	{"ENC_CFG",(1<<PVR2_SUBSYS_B_ENC_CFG)},
+	{"DIG_RUN",(1<<PVR2_SUBSYS_B_DIGITIZER_RUN)},
+	{"USB_RUN",(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)},
+	{"ENC_RUN",(1<<PVR2_SUBSYS_B_ENC_RUN)},
+};
+
+
+static unsigned int debugifc_count_whitespace(const char *buf,
+					      unsigned int count)
+{
+	unsigned int scnt;
+	char ch;
+
+	for (scnt = 0; scnt < count; scnt++) {
+		ch = buf[scnt];
+		if (ch == ' ') continue;
+		if (ch == '\t') continue;
+		if (ch == '\n') continue;
+		break;
+	}
+	return scnt;
+}
+
+
+static unsigned int debugifc_count_nonwhitespace(const char *buf,
+						 unsigned int count)
+{
+	unsigned int scnt;
+	char ch;
+
+	for (scnt = 0; scnt < count; scnt++) {
+		ch = buf[scnt];
+		if (ch == ' ') break;
+		if (ch == '\t') break;
+		if (ch == '\n') break;
+	}
+	return scnt;
+}
+
+
+static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
+					  const char **wstrPtr,
+					  unsigned int *wlenPtr)
+{
+	const char *wptr;
+	unsigned int consume_cnt = 0;
+	unsigned int wlen;
+	unsigned int scnt;
+
+	wptr = 0;
+	wlen = 0;
+	scnt = debugifc_count_whitespace(buf,count);
+	consume_cnt += scnt; count -= scnt; buf += scnt;
+	if (!count) goto done;
+
+	scnt = debugifc_count_nonwhitespace(buf,count);
+	if (!scnt) goto done;
+	wptr = buf;
+	wlen = scnt;
+	consume_cnt += scnt; count -= scnt; buf += scnt;
+
+ done:
+	*wstrPtr = wptr;
+	*wlenPtr = wlen;
+	return consume_cnt;
+}
+
+
+static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
+					  u32 *num_ptr)
+{
+	u32 result = 0;
+	u32 val;
+	int ch;
+	int radix = 10;
+	if ((count >= 2) && (buf[0] == '0') &&
+	    ((buf[1] == 'x') || (buf[1] == 'X'))) {
+		radix = 16;
+		count -= 2;
+		buf += 2;
+	} else if ((count >= 1) && (buf[0] == '0')) {
+		radix = 8;
+	}
+
+	while (count--) {
+		ch = *buf++;
+		if ((ch >= '0') && (ch <= '9')) {
+			val = ch - '0';
+		} else if ((ch >= 'a') && (ch <= 'f')) {
+			val = ch - 'a' + 10;
+		} else if ((ch >= 'A') && (ch <= 'F')) {
+			val = ch - 'A' + 10;
+		} else {
+			return -EINVAL;
+		}
+		if (val >= radix) return -EINVAL;
+		result *= radix;
+		result += val;
+	}
+	*num_ptr = result;
+	return 0;
+}
+
+
+static int debugifc_match_keyword(const char *buf,unsigned int count,
+				  const char *keyword)
+{
+	unsigned int kl;
+	if (!keyword) return 0;
+	kl = strlen(keyword);
+	if (kl != count) return 0;
+	return !memcmp(buf,keyword,kl);
+}
+
+
+static unsigned long debugifc_find_mask(const char *buf,unsigned int count)
+{
+	struct debugifc_mask_item *mip;
+	unsigned int idx;
+	for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+		mip = mask_items + idx;
+		if (debugifc_match_keyword(buf,count,mip->name)) {
+			return mip->msk;
+		}
+	}
+	return 0;
+}
+
+
+static int debugifc_print_mask(char *buf,unsigned int sz,
+			       unsigned long msk,unsigned long val)
+{
+	struct debugifc_mask_item *mip;
+	unsigned int idx;
+	int bcnt = 0;
+	int ccnt;
+	for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) {
+		mip = mask_items + idx;
+		if (!(mip->msk & msk)) continue;
+		ccnt = scnprintf(buf,sz,"%s%c%s",
+				 (bcnt ? " " : ""),
+				 ((mip->msk & val) ? '+' : '-'),
+				 mip->name);
+		sz -= ccnt;
+		buf += ccnt;
+		bcnt += ccnt;
+	}
+	return bcnt;
+}
+
+static unsigned int debugifc_parse_subsys_mask(const char *buf,
+					       unsigned int count,
+					       unsigned long *mskPtr,
+					       unsigned long *valPtr)
+{
+	const char *wptr;
+	unsigned int consume_cnt = 0;
+	unsigned int scnt;
+	unsigned int wlen;
+	int mode;
+	unsigned long m1,msk,val;
+
+	msk = 0;
+	val = 0;
+
+	while (count) {
+		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+		if (!scnt) break;
+		consume_cnt += scnt; count -= scnt; buf += scnt;
+		if (!wptr) break;
+
+		mode = 0;
+		if (wlen) switch (wptr[0]) {
+		case '+':
+			wptr++;
+			wlen--;
+			break;
+		case '-':
+			mode = 1;
+			wptr++;
+			wlen--;
+			break;
+		}
+		if (!wlen) continue;
+		m1 = debugifc_find_mask(wptr,wlen);
+		if (!m1) break;
+		msk |= m1;
+		if (!mode) val |= m1;
+	}
+	*mskPtr = msk;
+	*valPtr = val;
+	return consume_cnt;
+}
+
+
+int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
+{
+	int bcnt = 0;
+	int ccnt;
+	struct pvr2_hdw_debug_info dbg;
+
+	pvr2_hdw_get_debug_info(hdw,&dbg);
+
+	ccnt = scnprintf(buf,acnt,"big lock %s; ctl lock %s",
+			 (dbg.big_lock_held ? "held" : "free"),
+			 (dbg.ctl_lock_held ? "held" : "free"));
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	if (dbg.ctl_lock_held) {
+		ccnt = scnprintf(buf,acnt,"; cmd_state=%d cmd_code=%d"
+				 " cmd_wlen=%d cmd_rlen=%d"
+				 " wpend=%d rpend=%d tmout=%d rstatus=%d"
+				 " wstatus=%d",
+				 dbg.cmd_debug_state,dbg.cmd_code,
+				 dbg.cmd_debug_write_len,
+				 dbg.cmd_debug_read_len,
+				 dbg.cmd_debug_write_pend,
+				 dbg.cmd_debug_read_pend,
+				 dbg.cmd_debug_timeout,
+				 dbg.cmd_debug_rstatus,
+				 dbg.cmd_debug_wstatus);
+		bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	}
+	ccnt = scnprintf(buf,acnt,"\n");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(
+		buf,acnt,"driver flags: %s %s %s\n",
+		(dbg.flag_init_ok ? "initialized" : "uninitialized"),
+		(dbg.flag_ok ? "ok" : "fail"),
+		(dbg.flag_disconnected ? "disconnected" : "connected"));
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: ");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = debugifc_print_mask(buf,acnt,dbg.subsys_flags,dbg.subsys_flags);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"\n");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: ");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = debugifc_print_mask(buf,acnt,~dbg.subsys_flags,dbg.subsys_flags);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"\n");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+	ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = pvr2_i2c_report(hdw,buf,acnt);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+	return bcnt;
+}
+
+
+int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
+			       char *buf,unsigned int acnt)
+{
+	int bcnt = 0;
+	int ccnt;
+	unsigned long msk;
+	int ret;
+	u32 gpio_dir,gpio_in,gpio_out;
+
+	ret = pvr2_hdw_is_hsm(hdw);
+	ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
+			 (ret < 0 ? "FAIL" : (ret ? "high" : "full")));
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+	gpio_dir = 0; gpio_in = 0; gpio_out = 0;
+	pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
+	pvr2_hdw_gpio_get_out(hdw,&gpio_out);
+	pvr2_hdw_gpio_get_in(hdw,&gpio_in);
+	ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
+			 gpio_dir,gpio_in,gpio_out);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+	ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
+			 pvr2_hdw_get_streaming(hdw) ? "on" : "off");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+	msk = pvr2_hdw_subsys_get(hdw);
+	ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: ");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = debugifc_print_mask(buf,acnt,msk,msk);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"\n");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: ");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = debugifc_print_mask(buf,acnt,~msk,msk);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"\n");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+	msk = pvr2_hdw_subsys_stream_get(hdw);
+	ccnt = scnprintf(buf,acnt,"Subsystems stopped on stream shutdown: ");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = debugifc_print_mask(buf,acnt,msk,msk);
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+	ccnt = scnprintf(buf,acnt,"\n");
+	bcnt += ccnt; acnt -= ccnt; buf += ccnt;
+
+	return bcnt;
+}
+
+
+int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
+			 unsigned int count)
+{
+	const char *wptr;
+	unsigned int wlen;
+	unsigned int scnt;
+
+	scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+	if (!scnt) return 0;
+	count -= scnt; buf += scnt;
+	if (!wptr) return 0;
+
+	pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
+	if (debugifc_match_keyword(wptr,wlen,"reset")) {
+		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+		if (!scnt) return -EINVAL;
+		count -= scnt; buf += scnt;
+		if (!wptr) return -EINVAL;
+		if (debugifc_match_keyword(wptr,wlen,"cpu")) {
+			pvr2_hdw_cpureset_assert(hdw,!0);
+			pvr2_hdw_cpureset_assert(hdw,0);
+			return 0;
+		} else if (debugifc_match_keyword(wptr,wlen,"bus")) {
+			pvr2_hdw_device_reset(hdw);
+		} else if (debugifc_match_keyword(wptr,wlen,"soft")) {
+			return pvr2_hdw_cmd_powerup(hdw);
+		} else if (debugifc_match_keyword(wptr,wlen,"deep")) {
+			return pvr2_hdw_cmd_deep_reset(hdw);
+		} else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
+			return pvr2_upload_firmware2(hdw);
+		} else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
+			return pvr2_hdw_cmd_decoder_reset(hdw);
+		}
+		return -EINVAL;
+	} else if (debugifc_match_keyword(wptr,wlen,"subsys_flags")) {
+		unsigned long msk = 0;
+		unsigned long val = 0;
+		if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) {
+			pvr2_trace(PVR2_TRACE_DEBUGIFC,
+				   "debugifc parse error on subsys mask");
+			return -EINVAL;
+		}
+		pvr2_hdw_subsys_bit_chg(hdw,msk,val);
+		return 0;
+	} else if (debugifc_match_keyword(wptr,wlen,"stream_flags")) {
+		unsigned long msk = 0;
+		unsigned long val = 0;
+		if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) {
+			pvr2_trace(PVR2_TRACE_DEBUGIFC,
+				   "debugifc parse error on stream mask");
+			return -EINVAL;
+		}
+		pvr2_hdw_subsys_stream_bit_chg(hdw,msk,val);
+		return 0;
+	} else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
+		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+		if (!scnt) return -EINVAL;
+		count -= scnt; buf += scnt;
+		if (!wptr) return -EINVAL;
+		if (debugifc_match_keyword(wptr,wlen,"fetch")) {
+			pvr2_hdw_cpufw_set_enabled(hdw,!0);
+			return 0;
+		} else if (debugifc_match_keyword(wptr,wlen,"done")) {
+			pvr2_hdw_cpufw_set_enabled(hdw,0);
+			return 0;
+		} else {
+			return -EINVAL;
+		}
+	} else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
+		int dir_fl = 0;
+		int ret;
+		u32 msk,val;
+		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+		if (!scnt) return -EINVAL;
+		count -= scnt; buf += scnt;
+		if (!wptr) return -EINVAL;
+		if (debugifc_match_keyword(wptr,wlen,"dir")) {
+			dir_fl = !0;
+		} else if (!debugifc_match_keyword(wptr,wlen,"out")) {
+			return -EINVAL;
+		}
+		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+		if (!scnt) return -EINVAL;
+		count -= scnt; buf += scnt;
+		if (!wptr) return -EINVAL;
+		ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
+		if (ret) return ret;
+		scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
+		if (wptr) {
+			ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
+			if (ret) return ret;
+		} else {
+			val = msk;
+			msk = 0xffffffff;
+		}
+		if (dir_fl) {
+			ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
+		} else {
+			ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
+		}
+		return ret;
+	}
+	pvr2_trace(PVR2_TRACE_DEBUGIFC,
+		   "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
+	return -EINVAL;
+}
+
+
+int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
+			unsigned int count)
+{
+	unsigned int bcnt = 0;
+	int ret;
+
+	while (count) {
+		for (bcnt = 0; bcnt < count; bcnt++) {
+			if (buf[bcnt] == '\n') break;
+		}
+
+		ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
+		if (ret < 0) return ret;
+		if (bcnt < count) bcnt++;
+		buf += bcnt;
+		count -= bcnt;
+	}
+
+	return 0;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
new file mode 100644
index 0000000..990b02d
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h
@@ -0,0 +1,53 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_DEBUGIFC_H
+#define __PVRUSB2_DEBUGIFC_H
+
+struct pvr2_hdw;
+
+/* Non-intrusively print some useful debugging info from inside the
+   driver.  This should work even if the driver appears to be
+   wedged. */
+int pvr2_debugifc_print_info(struct pvr2_hdw *,
+			     char *buf_ptr,unsigned int buf_size);
+
+/* Print general status of driver.  This will also trigger a probe of
+   the USB link.  Unlike print_info(), this one synchronizes with the
+   driver so the information should be self-consistent (but it will
+   hang if the driver is wedged). */
+int pvr2_debugifc_print_status(struct pvr2_hdw *,
+			       char *buf_ptr,unsigned int buf_size);
+
+/* Parse a string command into a driver action. */
+int pvr2_debugifc_docmd(struct pvr2_hdw *,
+			const char *buf_ptr,unsigned int buf_size);
+
+#endif /* __PVRUSB2_DEBUGIFC_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-demod.c b/drivers/media/video/pvrusb2/pvrusb2-demod.c
new file mode 100644
index 0000000..9686569
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-demod.c
@@ -0,0 +1,126 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2.h"
+#include "pvrusb2-util.h"
+#include "pvrusb2-demod.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/tuner.h>
+#include <media/v4l2-common.h>
+
+
+struct pvr2_demod_handler {
+	struct pvr2_hdw *hdw;
+	struct pvr2_i2c_client *client;
+	struct pvr2_i2c_handler i2c_handler;
+	int type_update_fl;
+};
+
+
+static void set_config(struct pvr2_demod_handler *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	int cfg = 0;
+
+	switch (hdw->tuner_type) {
+	case TUNER_PHILIPS_FM1216ME_MK3:
+	case TUNER_PHILIPS_FM1236_MK3:
+		cfg = TDA9887_PORT1_ACTIVE|TDA9887_PORT2_ACTIVE;
+		break;
+	default:
+		break;
+	}
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c demod set_config(0x%x)",cfg);
+	pvr2_i2c_client_cmd(ctxt->client,TDA9887_SET_CONFIG,&cfg);
+	ctxt->type_update_fl = 0;
+}
+
+
+static int demod_check(struct pvr2_demod_handler *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	if (hdw->tuner_updated) ctxt->type_update_fl = !0;
+	return ctxt->type_update_fl != 0;
+}
+
+
+static void demod_update(struct pvr2_demod_handler *ctxt)
+{
+	if (ctxt->type_update_fl) set_config(ctxt);
+}
+
+
+static void demod_detach(struct pvr2_demod_handler *ctxt)
+{
+	ctxt->client->handler = 0;
+	kfree(ctxt);
+}
+
+
+static unsigned int demod_describe(struct pvr2_demod_handler *ctxt,char *buf,unsigned int cnt)
+{
+	return scnprintf(buf,cnt,"handler: pvrusb2-demod");
+}
+
+
+const static struct pvr2_i2c_handler_functions tuner_funcs = {
+	.detach = (void (*)(void *))demod_detach,
+	.check = (int (*)(void *))demod_check,
+	.update = (void (*)(void *))demod_update,
+	.describe = (unsigned int (*)(void *,char *,unsigned int))demod_describe,
+};
+
+
+int pvr2_i2c_demod_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+	struct pvr2_demod_handler *ctxt;
+	if (cp->handler) return 0;
+
+	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	if (!ctxt) return 0;
+	memset(ctxt,0,sizeof(*ctxt));
+
+	ctxt->i2c_handler.func_data = ctxt;
+	ctxt->i2c_handler.func_table = &tuner_funcs;
+	ctxt->type_update_fl = !0;
+	ctxt->client = cp;
+	ctxt->hdw = hdw;
+	cp->handler = &ctxt->i2c_handler;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tda9887 V4L2 handler set up",
+		   cp->client->addr);
+	return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-demod.h b/drivers/media/video/pvrusb2/pvrusb2-demod.h
new file mode 100644
index 0000000..4c4e40f
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-demod.h
@@ -0,0 +1,38 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_DEMOD_H
+#define __PVRUSB2_DEMOD_H
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_demod_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+#endif /* __PVRUSB2_DEMOD_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
new file mode 100644
index 0000000..94d383f
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
@@ -0,0 +1,164 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-eeprom.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+
+#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__)
+
+
+
+/*
+
+   Read and analyze data in the eeprom.  Use tveeprom to figure out
+   the packet structure, since this is another Hauppauge device and
+   internally it has a family resemblence to ivtv-type devices
+
+*/
+
+#include <media/tveeprom.h>
+
+/* We seem to only be interested in the last 128 bytes of the EEPROM */
+#define EEPROM_SIZE 128
+
+/* Grab EEPROM contents, needed for direct method. */
+static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw)
+{
+	struct i2c_msg msg[2];
+	u8 *eeprom;
+	u8 iadd[2];
+	u8 addr;
+	u16 eepromSize;
+	unsigned int offs;
+	int ret;
+	int mode16 = 0;
+	unsigned pcnt,tcnt;
+	eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL);
+	if (!eeprom) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Failed to allocate memory"
+			   " required to read eeprom");
+		return 0;
+	}
+
+	trace_eeprom("Value for eeprom addr from controller was 0x%x",
+		     hdw->eeprom_addr);
+	addr = hdw->eeprom_addr;
+	/* Seems that if the high bit is set, then the *real* eeprom
+	   address is shifted right now bit position (noticed this in
+	   newer PVR USB2 hardware) */
+	if (addr & 0x80) addr >>= 1;
+
+	/* FX2 documentation states that a 16bit-addressed eeprom is
+	   expected if the I2C address is an odd number (yeah, this is
+	   strange but it's what they do) */
+	mode16 = (addr & 1);
+	eepromSize = (mode16 ? 4096 : 256);
+	trace_eeprom("Examining %d byte eeprom at location 0x%x"
+		     " using %d bit addressing",eepromSize,addr,
+		     mode16 ? 16 : 8);
+
+	msg[0].addr = addr;
+	msg[0].flags = 0;
+	msg[0].len = mode16 ? 2 : 1;
+	msg[0].buf = iadd;
+	msg[1].addr = addr;
+	msg[1].flags = I2C_M_RD;
+
+	/* We have to do the actual eeprom data fetch ourselves, because
+	   (1) we're only fetching part of the eeprom, and (2) if we were
+	   getting the whole thing our I2C driver can't grab it in one
+	   pass - which is what tveeprom is otherwise going to attempt */
+	memset(eeprom,0,EEPROM_SIZE);
+	for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) {
+		pcnt = 16;
+		if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt;
+		offs = tcnt + (eepromSize - EEPROM_SIZE);
+		if (mode16) {
+			iadd[0] = offs >> 8;
+			iadd[1] = offs;
+		} else {
+			iadd[0] = offs;
+		}
+		msg[1].len = pcnt;
+		msg[1].buf = eeprom+tcnt;
+		if ((ret = i2c_transfer(
+			     &hdw->i2c_adap,
+			     msg,sizeof(msg)/sizeof(msg[0]))) != 2) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "eeprom fetch set offs err=%d",ret);
+			kfree(eeprom);
+			return 0;
+		}
+	}
+	return eeprom;
+}
+
+
+/* Directly call eeprom analysis function within tveeprom. */
+int pvr2_eeprom_analyze(struct pvr2_hdw *hdw)
+{
+	u8 *eeprom;
+	struct tveeprom tvdata;
+
+	memset(&tvdata,0,sizeof(tvdata));
+
+	eeprom = pvr2_eeprom_fetch(hdw);
+	if (!eeprom) return -EINVAL;
+
+	{
+		struct i2c_client fake_client;
+		/* Newer version expects a useless client interface */
+		fake_client.addr = hdw->eeprom_addr;
+		fake_client.adapter = &hdw->i2c_adap;
+		tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom);
+	}
+
+	trace_eeprom("eeprom assumed v4l tveeprom module");
+	trace_eeprom("eeprom direct call results:");
+	trace_eeprom("has_radio=%d",tvdata.has_radio);
+	trace_eeprom("tuner_type=%d",tvdata.tuner_type);
+	trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats);
+	trace_eeprom("audio_processor=%d",tvdata.audio_processor);
+	trace_eeprom("model=%d",tvdata.model);
+	trace_eeprom("revision=%d",tvdata.revision);
+	trace_eeprom("serial_number=%d",tvdata.serial_number);
+	trace_eeprom("rev_str=%s",tvdata.rev_str);
+	hdw->tuner_type = tvdata.tuner_type;
+	hdw->serial_number = tvdata.serial_number;
+	hdw->std_mask_eeprom = tvdata.tuner_formats;
+
+	kfree(eeprom);
+
+	return 0;
+}
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
new file mode 100644
index 0000000..8424297
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h
@@ -0,0 +1,40 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_EEPROM_H
+#define __PVRUSB2_EEPROM_H
+
+struct pvr2_hdw;
+
+int pvr2_eeprom_analyze(struct pvr2_hdw *);
+
+#endif /* __PVRUSB2_EEPROM_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
new file mode 100644
index 0000000..2cc3169
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c
@@ -0,0 +1,418 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/device.h>   // for linux/firmware.h
+#include <linux/firmware.h>
+#include "pvrusb2-util.h"
+#include "pvrusb2-encoder.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+
+
+
+/* Firmware mailbox flags - definitions found from ivtv */
+#define IVTV_MBOX_FIRMWARE_DONE 0x00000004
+#define IVTV_MBOX_DRIVER_DONE 0x00000002
+#define IVTV_MBOX_DRIVER_BUSY 0x00000001
+
+
+static int pvr2_encoder_write_words(struct pvr2_hdw *hdw,
+				    const u32 *data, unsigned int dlen)
+{
+	unsigned int idx;
+	int ret;
+	unsigned int offs = 0;
+	unsigned int chunkCnt;
+
+	/*
+
+	Format: First byte must be 0x01.  Remaining 32 bit words are
+	spread out into chunks of 7 bytes each, little-endian ordered,
+	offset at zero within each 2 blank bytes following and a
+	single byte that is 0x44 plus the offset of the word.  Repeat
+	request for additional words, with offset adjusted
+	accordingly.
+
+	*/
+	while (dlen) {
+		chunkCnt = 8;
+		if (chunkCnt > dlen) chunkCnt = dlen;
+		memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
+		hdw->cmd_buffer[0] = 0x01;
+		for (idx = 0; idx < chunkCnt; idx++) {
+			hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs;
+			PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7),
+					  data[idx]);
+		}
+		ret = pvr2_send_request(hdw,
+					hdw->cmd_buffer,1+(chunkCnt*7),
+					0,0);
+		if (ret) return ret;
+		data += chunkCnt;
+		dlen -= chunkCnt;
+		offs += chunkCnt;
+	}
+
+	return 0;
+}
+
+
+static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl,
+				   u32 *data, unsigned int dlen)
+{
+	unsigned int idx;
+	int ret;
+	unsigned int offs = 0;
+	unsigned int chunkCnt;
+
+	/*
+
+	Format: First byte must be 0x02 (status check) or 0x28 (read
+	back block of 32 bit words).  Next 6 bytes must be zero,
+	followed by a single byte of 0x44+offset for portion to be
+	read.  Returned data is packed set of 32 bits words that were
+	read.
+
+	*/
+
+	while (dlen) {
+		chunkCnt = 16;
+		if (chunkCnt > dlen) chunkCnt = dlen;
+		memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer));
+		hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28;
+		hdw->cmd_buffer[7] = 0x44 + offs;
+		ret = pvr2_send_request(hdw,
+					hdw->cmd_buffer,8,
+					hdw->cmd_buffer,chunkCnt * 4);
+		if (ret) return ret;
+
+		for (idx = 0; idx < chunkCnt; idx++) {
+			data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4);
+		}
+		data += chunkCnt;
+		dlen -= chunkCnt;
+		offs += chunkCnt;
+	}
+
+	return 0;
+}
+
+
+/* This prototype is set up to be compatible with the
+   cx2341x_mbox_func prototype in cx2341x.h, which should be in
+   kernels 2.6.18 or later.  We do this so that we can enable
+   cx2341x.ko to write to our encoder (by handing it a pointer to this
+   function).  For earlier kernels this doesn't really matter. */
+static int pvr2_encoder_cmd(void *ctxt,
+			    int cmd,
+			    int arg_cnt_send,
+			    int arg_cnt_recv,
+			    u32 *argp)
+{
+	unsigned int poll_count;
+	int ret = 0;
+	unsigned int idx;
+	/* These sizes look to be limited by the FX2 firmware implementation */
+	u32 wrData[16];
+	u32 rdData[16];
+	struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt;
+
+
+	/*
+
+	The encoder seems to speak entirely using blocks 32 bit words.
+	In ivtv driver terms, this is a mailbox which we populate with
+	data and watch what the hardware does with it.  The first word
+	is a set of flags used to control the transaction, the second
+	word is the command to execute, the third byte is zero (ivtv
+	driver suggests that this is some kind of return value), and
+	the fourth byte is a specified timeout (windows driver always
+	uses 0x00060000 except for one case when it is zero).  All
+	successive words are the argument words for the command.
+
+	First, write out the entire set of words, with the first word
+	being zero.
+
+	Next, write out just the first word again, but set it to
+	IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which
+	probably means "go").
+
+	Next, read back 16 words as status.  Check the first word,
+	which should have IVTV_MBOX_FIRMWARE_DONE set.  If however
+	that bit is not set, then the command isn't done so repeat the
+	read.
+
+	Next, read back 32 words and compare with the original
+	arugments.  Hopefully they will match.
+
+	Finally, write out just the first word again, but set it to
+	0x0 this time (which probably means "idle").
+
+	*/
+
+	if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"Failed to write cx23416 command"
+			" - too many input arguments"
+			" (was given %u limit %u)",
+			arg_cnt_send,
+			(unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4);
+		return -EINVAL;
+	}
+
+	if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"Failed to write cx23416 command"
+			" - too many return arguments"
+			" (was given %u limit %u)",
+			arg_cnt_recv,
+			(unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4);
+		return -EINVAL;
+	}
+
+
+	LOCK_TAKE(hdw->ctl_lock); do {
+
+		wrData[0] = 0;
+		wrData[1] = cmd;
+		wrData[2] = 0;
+		wrData[3] = 0x00060000;
+		for (idx = 0; idx < arg_cnt_send; idx++) {
+			wrData[idx+4] = argp[idx];
+		}
+		for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) {
+			wrData[idx+4] = 0;
+		}
+
+		ret = pvr2_encoder_write_words(hdw,wrData,idx);
+		if (ret) break;
+		wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY;
+		ret = pvr2_encoder_write_words(hdw,wrData,1);
+		if (ret) break;
+		poll_count = 0;
+		while (1) {
+			if (poll_count < 10000000) poll_count++;
+			ret = pvr2_encoder_read_words(hdw,!0,rdData,1);
+			if (ret) break;
+			if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) {
+				break;
+			}
+			if (poll_count == 100) {
+				pvr2_trace(
+					PVR2_TRACE_ERROR_LEGS,
+					"***WARNING*** device's encoder"
+					" appears to be stuck"
+					" (status=0%08x)",rdData[0]);
+				pvr2_trace(
+					PVR2_TRACE_ERROR_LEGS,
+					"Encoder command: 0x%02x",cmd);
+				for (idx = 4; idx < arg_cnt_send; idx++) {
+					pvr2_trace(
+						PVR2_TRACE_ERROR_LEGS,
+						"Encoder arg%d: 0x%08x",
+						idx-3,wrData[idx]);
+				}
+				pvr2_trace(
+					PVR2_TRACE_ERROR_LEGS,
+					"Giving up waiting."
+					"  It is likely that"
+					" this is a bad idea...");
+				ret = -EBUSY;
+				break;
+			}
+		}
+		if (ret) break;
+		wrData[0] = 0x7;
+		ret = pvr2_encoder_read_words(
+			hdw,0,rdData,
+			sizeof(rdData)/sizeof(rdData[0]));
+		if (ret) break;
+		for (idx = 0; idx < arg_cnt_recv; idx++) {
+			argp[idx] = rdData[idx+4];
+		}
+
+		wrData[0] = 0x0;
+		ret = pvr2_encoder_write_words(hdw,wrData,1);
+		if (ret) break;
+
+	} while(0); LOCK_GIVE(hdw->ctl_lock);
+
+	return ret;
+}
+
+
+static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd,
+			     int args, ...)
+{
+	va_list vl;
+	unsigned int idx;
+	u32 data[12];
+
+	if (args > sizeof(data)/sizeof(data[0])) {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"Failed to write cx23416 command"
+			" - too many arguments"
+			" (was given %u limit %u)",
+			args,(unsigned int)(sizeof(data)/sizeof(data[0])));
+		return -EINVAL;
+	}
+
+	va_start(vl, args);
+	for (idx = 0; idx < args; idx++) {
+		data[idx] = va_arg(vl, u32);
+	}
+	va_end(vl);
+
+	return pvr2_encoder_cmd(hdw,cmd,args,0,data);
+}
+
+int pvr2_encoder_configure(struct pvr2_hdw *hdw)
+{
+	int ret;
+	pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure"
+		   " (cx2341x module)");
+	hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING;
+	hdw->enc_ctl_state.width = hdw->res_hor_val;
+	hdw->enc_ctl_state.height = hdw->res_ver_val;
+	hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur &
+				       (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ?
+				      0 : 1);
+
+	ret = 0;
+
+	if (!ret) ret = pvr2_encoder_vcmd(
+		hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2,
+		0xf0, 0xf0);
+
+	/* setup firmware to notify us about some events (don't know why...) */
+	if (!ret) ret = pvr2_encoder_vcmd(
+		hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4,
+		0, 0, 0x10000000, 0xffffffff);
+
+	if (!ret) ret = pvr2_encoder_vcmd(
+		hdw,CX2341X_ENC_SET_VBI_LINE, 5,
+		0xffffffff,0,0,0,0);
+
+	if (ret) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Failed to configure cx32416");
+		return ret;
+	}
+
+	ret = cx2341x_update(hdw,pvr2_encoder_cmd,
+			     (hdw->enc_cur_valid ? &hdw->enc_cur_state : 0),
+			     &hdw->enc_ctl_state);
+	if (ret) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Error from cx2341x module code=%d",ret);
+		return ret;
+	}
+
+	ret = 0;
+
+	if (!ret) ret = pvr2_encoder_vcmd(
+		hdw, CX2341X_ENC_INITIALIZE_INPUT, 0);
+
+	if (ret) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Failed to initialize cx32416 video input");
+		return ret;
+	}
+
+	hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
+	memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state,
+	       sizeof(struct cx2341x_mpeg_params));
+	hdw->enc_cur_valid = !0;
+	return 0;
+}
+
+
+int pvr2_encoder_start(struct pvr2_hdw *hdw)
+{
+	int status;
+
+	/* unmask some interrupts */
+	pvr2_write_register(hdw, 0x0048, 0xbfffffff);
+
+	/* change some GPIO data */
+	pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481);
+	pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+
+	if (hdw->config == pvr2_config_vbi) {
+		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+					   0x01,0x14);
+	} else if (hdw->config == pvr2_config_mpeg) {
+		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+					   0,0x13);
+	} else {
+		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2,
+					   0,0x13);
+	}
+	if (!status) {
+		hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN);
+	}
+	return status;
+}
+
+int pvr2_encoder_stop(struct pvr2_hdw *hdw)
+{
+	int status;
+
+	/* mask all interrupts */
+	pvr2_write_register(hdw, 0x0048, 0xffffffff);
+
+	if (hdw->config == pvr2_config_vbi) {
+		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+					   0x01,0x01,0x14);
+	} else if (hdw->config == pvr2_config_mpeg) {
+		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+					   0x01,0,0x13);
+	} else {
+		status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3,
+					   0x01,0,0x13);
+	}
+
+	/* change some GPIO data */
+	/* Note: Bit d7 of dir appears to control the LED.  So we shut it
+	   off here. */
+	pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401);
+	pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000);
+
+	if (!status) {
+		hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN);
+	}
+	return status;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.h b/drivers/media/video/pvrusb2/pvrusb2-encoder.h
new file mode 100644
index 0000000..01b5a0b
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.h
@@ -0,0 +1,42 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_ENCODER_H
+#define __PVRUSB2_ENCODER_H
+
+struct pvr2_hdw;
+
+int pvr2_encoder_configure(struct pvr2_hdw *);
+int pvr2_encoder_start(struct pvr2_hdw *);
+int pvr2_encoder_stop(struct pvr2_hdw *);
+
+#endif /* __PVRUSB2_ENCODER_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
new file mode 100644
index 0000000..ba2afbf
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
@@ -0,0 +1,384 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_HDW_INTERNAL_H
+#define __PVRUSB2_HDW_INTERNAL_H
+
+/*
+
+  This header sets up all the internal structures and definitions needed to
+  track and coordinate the driver's interaction with the hardware.  ONLY
+  source files which actually implement part of that whole circus should be
+  including this header.  Higher levels, like the external layers to the
+  various public APIs (V4L, sysfs, etc) should NOT ever include this
+  private, internal header.  This means that pvrusb2-hdw, pvrusb2-encoder,
+  etc will include this, but pvrusb2-v4l should not.
+
+*/
+
+#include <linux/config.h>
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-io.h"
+#include <media/cx2341x.h>
+
+/* Legal values for the SRATE state variable */
+#define PVR2_CVAL_SRATE_48 0
+#define PVR2_CVAL_SRATE_44_1 1
+
+/* Legal values for the AUDIOBITRATE state variable */
+#define PVR2_CVAL_AUDIOBITRATE_384 0
+#define PVR2_CVAL_AUDIOBITRATE_320 1
+#define PVR2_CVAL_AUDIOBITRATE_256 2
+#define PVR2_CVAL_AUDIOBITRATE_224 3
+#define PVR2_CVAL_AUDIOBITRATE_192 4
+#define PVR2_CVAL_AUDIOBITRATE_160 5
+#define PVR2_CVAL_AUDIOBITRATE_128 6
+#define PVR2_CVAL_AUDIOBITRATE_112 7
+#define PVR2_CVAL_AUDIOBITRATE_96 8
+#define PVR2_CVAL_AUDIOBITRATE_80 9
+#define PVR2_CVAL_AUDIOBITRATE_64 10
+#define PVR2_CVAL_AUDIOBITRATE_56 11
+#define PVR2_CVAL_AUDIOBITRATE_48 12
+#define PVR2_CVAL_AUDIOBITRATE_32 13
+#define PVR2_CVAL_AUDIOBITRATE_VBR 14
+
+/* Legal values for the AUDIOEMPHASIS state variable */
+#define PVR2_CVAL_AUDIOEMPHASIS_NONE 0
+#define PVR2_CVAL_AUDIOEMPHASIS_50_15 1
+#define PVR2_CVAL_AUDIOEMPHASIS_CCITT 2
+
+/* Legal values for PVR2_CID_HSM */
+#define PVR2_CVAL_HSM_FAIL 0
+#define PVR2_CVAL_HSM_FULL 1
+#define PVR2_CVAL_HSM_HIGH 2
+
+#define PVR2_VID_ENDPOINT        0x84
+#define PVR2_UNK_ENDPOINT        0x86    /* maybe raw yuv ? */
+#define PVR2_VBI_ENDPOINT        0x88
+
+#define PVR2_CTL_BUFFSIZE        64
+
+#define FREQTABLE_SIZE 500
+
+#define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0)
+#define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0)
+
+struct pvr2_decoder;
+
+typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *);
+typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *);
+typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *);
+typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val);
+typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val,
+				    char *,unsigned int,unsigned int *);
+typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *,
+				    const char *,unsigned int,
+				    int *mskp,int *valp);
+typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *);
+
+/* This structure describes a specific control.  A table of these is set up
+   in pvrusb2-hdw.c. */
+struct pvr2_ctl_info {
+	/* Control's name suitable for use as an identifier */
+	const char *name;
+
+	/* Short description of control */
+	const char *desc;
+
+	/* Control's implementation */
+	pvr2_ctlf_get_value get_value;      /* Get its value */
+	pvr2_ctlf_set_value set_value;      /* Set its value */
+	pvr2_ctlf_val_to_sym val_to_sym;    /* Custom convert value->symbol */
+	pvr2_ctlf_sym_to_val sym_to_val;    /* Custom convert symbol->value */
+	pvr2_ctlf_is_dirty is_dirty;        /* Return true if dirty */
+	pvr2_ctlf_clear_dirty clear_dirty;  /* Clear dirty state */
+	pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */
+
+	/* Control's type (int, enum, bitmask) */
+	enum pvr2_ctl_type type;
+
+	/* Associated V4L control ID, if any */
+	int v4l_id;
+
+	/* Associated driver internal ID, if any */
+	int internal_id;
+
+	/* Don't implicitly initialize this control's value */
+	int skip_init;
+
+	/* Starting value for this control */
+	int default_value;
+
+	/* Type-specific control information */
+	union {
+		struct { /* Integer control */
+			long min_value; /* lower limit */
+			long max_value; /* upper limit */
+		} type_int;
+		struct { /* enumerated control */
+			unsigned int count;       /* enum value count */
+			const char **value_names; /* symbol names */
+		} type_enum;
+		struct { /* bitmask control */
+			unsigned int valid_bits; /* bits in use */
+			const char **bit_names;  /* symbol name/bit */
+		} type_bitmask;
+	} def;
+};
+
+
+/* Same as pvr2_ctl_info, but includes storage for the control description */
+#define PVR2_CTLD_INFO_DESC_SIZE 32
+struct pvr2_ctld_info {
+	struct pvr2_ctl_info info;
+	char desc[PVR2_CTLD_INFO_DESC_SIZE];
+};
+
+struct pvr2_ctrl {
+	const struct pvr2_ctl_info *info;
+	struct pvr2_hdw *hdw;
+};
+
+
+struct pvr2_audio_stat {
+	void *ctxt;
+	void (*detach)(void *);
+	int (*status)(void *);
+};
+
+struct pvr2_decoder_ctrl {
+	void *ctxt;
+	void (*detach)(void *);
+	void (*enable)(void *,int);
+	int (*tuned)(void *);
+	void (*force_reset)(void *);
+};
+
+#define PVR2_I2C_PEND_DETECT  0x01  /* Need to detect a client type */
+#define PVR2_I2C_PEND_CLIENT  0x02  /* Client needs a specific update */
+#define PVR2_I2C_PEND_REFRESH 0x04  /* Client has specific pending bits */
+#define PVR2_I2C_PEND_STALE   0x08  /* Broadcast pending bits */
+
+#define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\
+			   PVR2_I2C_PEND_CLIENT |\
+			   PVR2_I2C_PEND_REFRESH |\
+			   PVR2_I2C_PEND_STALE)
+
+/* Disposition of firmware1 loading situation */
+#define FW1_STATE_UNKNOWN 0
+#define FW1_STATE_MISSING 1
+#define FW1_STATE_FAILED 2
+#define FW1_STATE_RELOAD 3
+#define FW1_STATE_OK 4
+
+/* Known major hardware variants, keyed from device ID */
+#define PVR2_HDW_TYPE_29XXX 0
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+#define PVR2_HDW_TYPE_24XXX 1
+#endif
+
+typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16);
+#define PVR2_I2C_FUNC_CNT 128
+
+/* This structure contains all state data directly needed to
+   manipulate the hardware (as opposed to complying with a kernel
+   interface) */
+struct pvr2_hdw {
+	/* Underlying USB device handle */
+	struct usb_device *usb_dev;
+	struct usb_interface *usb_intf;
+
+	/* Device type, one of PVR2_HDW_TYPE_xxxxx */
+	unsigned int hdw_type;
+
+	/* Video spigot */
+	struct pvr2_stream *vid_stream;
+
+	/* Mutex for all hardware state control */
+	struct mutex big_lock_mutex;
+	int big_lock_held;  /* For debugging */
+
+	void (*poll_trigger_func)(void *);
+	void *poll_trigger_data;
+
+	char name[32];
+
+	/* I2C stuff */
+	struct i2c_adapter i2c_adap;
+	struct i2c_algorithm i2c_algo;
+	pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT];
+	int i2c_cx25840_hack_state;
+	int i2c_linked;
+	unsigned int i2c_pend_types;    /* Which types of update are needed */
+	unsigned long i2c_pend_mask;    /* Change bits we need to scan */
+	unsigned long i2c_stale_mask;   /* Pending broadcast change bits */
+	unsigned long i2c_active_mask;  /* All change bits currently in use */
+	struct list_head i2c_clients;
+	struct mutex i2c_list_lock;
+
+	/* Frequency table */
+	unsigned int freqTable[FREQTABLE_SIZE];
+	unsigned int freqProgSlot;
+	unsigned int freqSlot;
+
+	/* Stuff for handling low level control interaction with device */
+	struct mutex ctl_lock_mutex;
+	int ctl_lock_held;  /* For debugging */
+	struct urb *ctl_write_urb;
+	struct urb *ctl_read_urb;
+	unsigned char *ctl_write_buffer;
+	unsigned char *ctl_read_buffer;
+	volatile int ctl_write_pend_flag;
+	volatile int ctl_read_pend_flag;
+	volatile int ctl_timeout_flag;
+	struct completion ctl_done;
+	unsigned char cmd_buffer[PVR2_CTL_BUFFSIZE];
+	int cmd_debug_state;               // Low level command debugging info
+	unsigned char cmd_debug_code;      //
+	unsigned int cmd_debug_write_len;  //
+	unsigned int cmd_debug_read_len;   //
+
+	int flag_ok;            // device in known good state
+	int flag_disconnected;  // flag_ok == 0 due to disconnect
+	int flag_init_ok;       // true if structure is fully initialized
+	int flag_streaming_enabled; // true if streaming should be on
+	int fw1_state;          // current situation with fw1
+
+	int flag_decoder_is_tuned;
+
+	struct pvr2_decoder_ctrl *decoder_ctrl;
+
+	// CPU firmware info (used to help find / save firmware data)
+	char *fw_buffer;
+	unsigned int fw_size;
+
+	// Which subsystem pieces have been enabled / configured
+	unsigned long subsys_enabled_mask;
+
+	// Which subsystems are manipulated to enable streaming
+	unsigned long subsys_stream_mask;
+
+	// True if there is a request to trigger logging of state in each
+	// module.
+	int log_requested;
+
+	/* Tuner / frequency control stuff */
+	unsigned int tuner_type;
+	int tuner_updated;
+	unsigned int freqVal;
+	int freqDirty;
+
+	/* Video standard handling */
+	v4l2_std_id std_mask_eeprom; // Hardware supported selections
+	v4l2_std_id std_mask_avail;  // Which standards we may select from
+	v4l2_std_id std_mask_cur;    // Currently selected standard(s)
+	unsigned int std_enum_cnt;   // # of enumerated standards
+	int std_enum_cur;            // selected standard enumeration value
+	int std_dirty;               // True if std_mask_cur has changed
+	struct pvr2_ctl_info std_info_enum;
+	struct pvr2_ctl_info std_info_avail;
+	struct pvr2_ctl_info std_info_cur;
+	struct v4l2_standard *std_defs;
+	const char **std_enum_names;
+
+	// Generated string names, one per actual V4L2 standard
+	const char *std_mask_ptrs[32];
+	char std_mask_names[32][10];
+
+	int unit_number;             /* ID for driver instance */
+	unsigned long serial_number; /* ID for hardware itself */
+
+	/* Minor number used by v4l logic (yes, this is a hack, as there should
+	   be no v4l junk here).  Probably a better way to do this. */
+	int v4l_minor_number;
+
+	/* Location of eeprom or a negative number if none */
+	int eeprom_addr;
+
+	enum pvr2_config config;
+
+	/* Information about what audio signal we're hearing */
+	int flag_stereo;
+	int flag_bilingual;
+	struct pvr2_audio_stat *audio_stat;
+
+	/* Control state needed for cx2341x module */
+	struct cx2341x_mpeg_params enc_cur_state;
+	struct cx2341x_mpeg_params enc_ctl_state;
+	/* True if an encoder attribute has changed */
+	int enc_stale;
+	/* True if enc_cur_state is valid */
+	int enc_cur_valid;
+
+	/* Control state */
+#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty
+	VCREATE_DATA(brightness);
+	VCREATE_DATA(contrast);
+	VCREATE_DATA(saturation);
+	VCREATE_DATA(hue);
+	VCREATE_DATA(volume);
+	VCREATE_DATA(balance);
+	VCREATE_DATA(bass);
+	VCREATE_DATA(treble);
+	VCREATE_DATA(mute);
+	VCREATE_DATA(input);
+	VCREATE_DATA(audiomode);
+	VCREATE_DATA(res_hor);
+	VCREATE_DATA(res_ver);
+	VCREATE_DATA(srate);
+#undef VCREATE_DATA
+
+	struct pvr2_ctld_info *mpeg_ctrl_info;
+
+	struct pvr2_ctrl *controls;
+	unsigned int control_cnt;
+};
+
+int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw);
+
+unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *);
+
+void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
+				     unsigned long msk,unsigned long val);
+void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
+					    unsigned long msk,
+					    unsigned long val);
+
+void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw);
+void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw);
+
+int pvr2_i2c_basic_op(struct pvr2_hdw *,u8 i2c_addr,
+		      u8 *wdata,u16 wlen,
+		      u8 *rdata,u16 rlen);
+
+#endif /* __PVRUSB2_HDW_INTERNAL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
new file mode 100644
index 0000000..643c471
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -0,0 +1,3120 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/videodev2.h>
+#include <asm/semaphore.h>
+#include "pvrusb2.h"
+#include "pvrusb2-std.h"
+#include "pvrusb2-util.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-tuner.h"
+#include "pvrusb2-eeprom.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-encoder.h"
+#include "pvrusb2-debug.h"
+
+struct usb_device_id pvr2_device_table[] = {
+	[PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+	[PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },
+#endif
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, pvr2_device_table);
+
+static const char *pvr2_device_names[] = {
+	[PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx",
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+	[PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx",
+#endif
+};
+
+struct pvr2_string_table {
+	const char **lst;
+	unsigned int cnt;
+};
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+// Names of other client modules to request for 24xxx model hardware
+static const char *pvr2_client_24xxx[] = {
+	"cx25840",
+	"tuner",
+	"tda9887",
+	"wm8775",
+};
+#endif
+
+// Names of other client modules to request for 29xxx model hardware
+static const char *pvr2_client_29xxx[] = {
+	"msp3400",
+	"saa7115",
+	"tuner",
+	"tda9887",
+};
+
+static struct pvr2_string_table pvr2_client_lists[] = {
+	[PVR2_HDW_TYPE_29XXX] = {
+		pvr2_client_29xxx,
+		sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]),
+	},
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+	[PVR2_HDW_TYPE_24XXX] = {
+		pvr2_client_24xxx,
+		sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]),
+	},
+#endif
+};
+
+static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = 0};
+DECLARE_MUTEX(pvr2_unit_sem);
+
+static int ctlchg = 0;
+static int initusbreset = 1;
+static int procreload = 0;
+static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };
+static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };
+static int init_pause_msec = 0;
+
+module_param(ctlchg, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");
+module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");
+module_param(initusbreset, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe");
+module_param(procreload, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(procreload,
+		 "Attempt init failure recovery with firmware reload");
+module_param_array(tuner,    int, NULL, 0444);
+MODULE_PARM_DESC(tuner,"specify installed tuner type");
+module_param_array(video_std,    int, NULL, 0444);
+MODULE_PARM_DESC(video_std,"specify initial video standard");
+module_param_array(tolerance,    int, NULL, 0444);
+MODULE_PARM_DESC(tolerance,"specify stream error tolerance");
+
+#define PVR2_CTL_WRITE_ENDPOINT  0x01
+#define PVR2_CTL_READ_ENDPOINT   0x81
+
+#define PVR2_GPIO_IN 0x9008
+#define PVR2_GPIO_OUT 0x900c
+#define PVR2_GPIO_DIR 0x9020
+
+#define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__)
+
+#define PVR2_FIRMWARE_ENDPOINT   0x02
+
+/* size of a firmware chunk */
+#define FIRMWARE_CHUNK_SIZE 0x2000
+
+/* Define the list of additional controls we'll dynamically construct based
+   on query of the cx2341x module. */
+struct pvr2_mpeg_ids {
+	const char *strid;
+	int id;
+};
+static const struct pvr2_mpeg_ids mpeg_ids[] = {
+	{
+		.strid = "audio_layer",
+		.id = V4L2_CID_MPEG_AUDIO_ENCODING,
+	},{
+		.strid = "audio_bitrate",
+		.id = V4L2_CID_MPEG_AUDIO_L2_BITRATE,
+	},{
+		/* Already using audio_mode elsewhere :-( */
+		.strid = "mpeg_audio_mode",
+		.id = V4L2_CID_MPEG_AUDIO_MODE,
+	},{
+		.strid = "mpeg_audio_mode_extension",
+		.id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION,
+	},{
+		.strid = "audio_emphasis",
+		.id = V4L2_CID_MPEG_AUDIO_EMPHASIS,
+	},{
+		.strid = "audio_crc",
+		.id = V4L2_CID_MPEG_AUDIO_CRC,
+	},{
+		.strid = "video_aspect",
+		.id = V4L2_CID_MPEG_VIDEO_ASPECT,
+	},{
+		.strid = "video_b_frames",
+		.id = V4L2_CID_MPEG_VIDEO_B_FRAMES,
+	},{
+		.strid = "video_gop_size",
+		.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+	},{
+		.strid = "video_gop_closure",
+		.id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE,
+	},{
+		.strid = "video_pulldown",
+		.id = V4L2_CID_MPEG_VIDEO_PULLDOWN,
+	},{
+		.strid = "video_bitrate_mode",
+		.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+	},{
+		.strid = "video_bitrate",
+		.id = V4L2_CID_MPEG_VIDEO_BITRATE,
+	},{
+		.strid = "video_bitrate_peak",
+		.id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK,
+	},{
+		.strid = "video_temporal_decimation",
+		.id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION,
+	},{
+		.strid = "stream_type",
+		.id = V4L2_CID_MPEG_STREAM_TYPE,
+	},{
+		.strid = "video_spatial_filter_mode",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE,
+	},{
+		.strid = "video_spatial_filter",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
+	},{
+		.strid = "video_luma_spatial_filter_type",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE,
+	},{
+		.strid = "video_chroma_spatial_filter_type",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE,
+	},{
+		.strid = "video_temporal_filter_mode",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE,
+	},{
+		.strid = "video_temporal_filter",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER,
+	},{
+		.strid = "video_median_filter_type",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE,
+	},{
+		.strid = "video_luma_median_filter_top",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP,
+	},{
+		.strid = "video_luma_median_filter_bottom",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM,
+	},{
+		.strid = "video_chroma_median_filter_top",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP,
+	},{
+		.strid = "video_chroma_median_filter_bottom",
+		.id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM,
+	}
+};
+#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0]))
+
+static const char *control_values_srate[] = {
+	[PVR2_CVAL_SRATE_48]   = "48KHz",
+	[PVR2_CVAL_SRATE_44_1] = "44.1KHz",
+};
+
+
+
+
+static const char *control_values_input[] = {
+	[PVR2_CVAL_INPUT_TV]        = "television",  /*xawtv needs this name*/
+	[PVR2_CVAL_INPUT_RADIO]     = "radio",
+	[PVR2_CVAL_INPUT_SVIDEO]    = "s-video",
+	[PVR2_CVAL_INPUT_COMPOSITE] = "composite",
+};
+
+
+static const char *control_values_audiomode[] = {
+	[V4L2_TUNER_MODE_MONO]   = "Mono",
+	[V4L2_TUNER_MODE_STEREO] = "Stereo",
+	[V4L2_TUNER_MODE_LANG1]  = "Lang1",
+	[V4L2_TUNER_MODE_LANG2]  = "Lang2",
+	[V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2",
+};
+
+
+static const char *control_values_hsm[] = {
+	[PVR2_CVAL_HSM_FAIL] = "Fail",
+	[PVR2_CVAL_HSM_HIGH] = "High",
+	[PVR2_CVAL_HSM_FULL] = "Full",
+};
+
+
+static const char *control_values_subsystem[] = {
+	[PVR2_SUBSYS_B_ENC_FIRMWARE]  = "enc_firmware",
+	[PVR2_SUBSYS_B_ENC_CFG] = "enc_config",
+	[PVR2_SUBSYS_B_DIGITIZER_RUN] = "digitizer_run",
+	[PVR2_SUBSYS_B_USBSTREAM_RUN] = "usbstream_run",
+	[PVR2_SUBSYS_B_ENC_RUN] = "enc_run",
+};
+
+
+static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+	if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
+		*vp = hdw->freqTable[hdw->freqProgSlot-1];
+	} else {
+		*vp = 0;
+	}
+	return 0;
+}
+
+static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+	if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) {
+		hdw->freqTable[hdw->freqProgSlot-1] = v;
+	}
+	return 0;
+}
+
+static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->freqProgSlot;
+	return 0;
+}
+
+static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+	if ((v >= 0) && (v <= FREQTABLE_SIZE)) {
+		hdw->freqProgSlot = v;
+	}
+	return 0;
+}
+
+static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->freqSlot;
+	return 0;
+}
+
+static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	unsigned freq = 0;
+	struct pvr2_hdw *hdw = cptr->hdw;
+	hdw->freqSlot = v;
+	if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) {
+		freq = hdw->freqTable[hdw->freqSlot-1];
+	}
+	if (freq && (freq != hdw->freqVal)) {
+		hdw->freqVal = freq;
+		hdw->freqDirty = !0;
+	}
+	return 0;
+}
+
+static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->freqVal;
+	return 0;
+}
+
+static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr)
+{
+	return cptr->hdw->freqDirty != 0;
+}
+
+static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr)
+{
+	cptr->hdw->freqDirty = 0;
+}
+
+static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+	hdw->freqVal = v;
+	hdw->freqDirty = !0;
+	hdw->freqSlot = 0;
+	return 0;
+}
+
+static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr)
+{
+	return cptr->hdw->enc_stale != 0;
+}
+
+static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr)
+{
+	cptr->hdw->enc_stale = 0;
+}
+
+static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	int ret;
+	struct v4l2_ext_controls cs;
+	struct v4l2_ext_control c1;
+	memset(&cs,0,sizeof(cs));
+	memset(&c1,0,sizeof(c1));
+	cs.controls = &c1;
+	cs.count = 1;
+	c1.id = cptr->info->v4l_id;
+	ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+				VIDIOC_G_EXT_CTRLS);
+	if (ret) return ret;
+	*vp = c1.value;
+	return 0;
+}
+
+static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	int ret;
+	struct v4l2_ext_controls cs;
+	struct v4l2_ext_control c1;
+	memset(&cs,0,sizeof(cs));
+	memset(&c1,0,sizeof(c1));
+	cs.controls = &c1;
+	cs.count = 1;
+	c1.id = cptr->info->v4l_id;
+	c1.value = v;
+	ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs,
+				VIDIOC_S_EXT_CTRLS);
+	if (ret) return ret;
+	cptr->hdw->enc_stale = !0;
+	return 0;
+}
+
+static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr)
+{
+	struct v4l2_queryctrl qctrl;
+	struct pvr2_ctl_info *info;
+	qctrl.id = cptr->info->v4l_id;
+	cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl);
+	/* Strip out the const so we can adjust a function pointer.  It's
+	   OK to do this here because we know this is a dynamically created
+	   control, so the underlying storage for the info pointer is (a)
+	   private to us, and (b) not in read-only storage.  Either we do
+	   this or we significantly complicate the underlying control
+	   implementation. */
+	info = (struct pvr2_ctl_info *)(cptr->info);
+	if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) {
+		if (info->set_value) {
+			info->set_value = 0;
+		}
+	} else {
+		if (!(info->set_value)) {
+			info->set_value = ctrl_cx2341x_set;
+		}
+	}
+	return qctrl.flags;
+}
+
+static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->flag_streaming_enabled;
+	return 0;
+}
+
+static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	int result = pvr2_hdw_is_hsm(cptr->hdw);
+	*vp = PVR2_CVAL_HSM_FULL;
+	if (result < 0) *vp = PVR2_CVAL_HSM_FAIL;
+	if (result) *vp = PVR2_CVAL_HSM_HIGH;
+	return 0;
+}
+
+static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->std_mask_avail;
+	return 0;
+}
+
+static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+	v4l2_std_id ns;
+	ns = hdw->std_mask_avail;
+	ns = (ns & ~m) | (v & m);
+	if (ns == hdw->std_mask_avail) return 0;
+	hdw->std_mask_avail = ns;
+	pvr2_hdw_internal_set_std_avail(hdw);
+	pvr2_hdw_internal_find_stdenum(hdw);
+	return 0;
+}
+
+static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val,
+			       char *bufPtr,unsigned int bufSize,
+			       unsigned int *len)
+{
+	*len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val);
+	return 0;
+}
+
+static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr,
+			       const char *bufPtr,unsigned int bufSize,
+			       int *mskp,int *valp)
+{
+	int ret;
+	v4l2_std_id id;
+	ret = pvr2_std_str_to_id(&id,bufPtr,bufSize);
+	if (ret < 0) return ret;
+	if (mskp) *mskp = id;
+	if (valp) *valp = id;
+	return 0;
+}
+
+static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->std_mask_cur;
+	return 0;
+}
+
+static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+	v4l2_std_id ns;
+	ns = hdw->std_mask_cur;
+	ns = (ns & ~m) | (v & m);
+	if (ns == hdw->std_mask_cur) return 0;
+	hdw->std_mask_cur = ns;
+	hdw->std_dirty = !0;
+	pvr2_hdw_internal_find_stdenum(hdw);
+	return 0;
+}
+
+static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr)
+{
+	return cptr->hdw->std_dirty != 0;
+}
+
+static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr)
+{
+	cptr->hdw->std_dirty = 0;
+}
+
+static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) &
+		PVR2_SIGNAL_OK) ? 1 : 0);
+	return 0;
+}
+
+static int ctrl_subsys_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->subsys_enabled_mask;
+	return 0;
+}
+
+static int ctrl_subsys_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,m,v);
+	return 0;
+}
+
+static int ctrl_subsys_stream_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->subsys_stream_mask;
+	return 0;
+}
+
+static int ctrl_subsys_stream_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,m,v);
+	return 0;
+}
+
+static int ctrl_stdenumcur_set(struct pvr2_ctrl *cptr,int m,int v)
+{
+	struct pvr2_hdw *hdw = cptr->hdw;
+	if (v < 0) return -EINVAL;
+	if (v > hdw->std_enum_cnt) return -EINVAL;
+	hdw->std_enum_cur = v;
+	if (!v) return 0;
+	v--;
+	if (hdw->std_mask_cur == hdw->std_defs[v].id) return 0;
+	hdw->std_mask_cur = hdw->std_defs[v].id;
+	hdw->std_dirty = !0;
+	return 0;
+}
+
+
+static int ctrl_stdenumcur_get(struct pvr2_ctrl *cptr,int *vp)
+{
+	*vp = cptr->hdw->std_enum_cur;
+	return 0;
+}
+
+
+static int ctrl_stdenumcur_is_dirty(struct pvr2_ctrl *cptr)
+{
+	return cptr->hdw->std_dirty != 0;
+}
+
+
+static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr)
+{
+	cptr->hdw->std_dirty = 0;
+}
+
+
+#define DEFINT(vmin,vmax) \
+	.type = pvr2_ctl_int, \
+	.def.type_int.min_value = vmin, \
+	.def.type_int.max_value = vmax
+
+#define DEFENUM(tab) \
+	.type = pvr2_ctl_enum, \
+	.def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \
+	.def.type_enum.value_names = tab
+
+#define DEFBOOL \
+	.type = pvr2_ctl_bool
+
+#define DEFMASK(msk,tab) \
+	.type = pvr2_ctl_bitmask, \
+	.def.type_bitmask.valid_bits = msk, \
+	.def.type_bitmask.bit_names = tab
+
+#define DEFREF(vname) \
+	.set_value = ctrl_set_##vname, \
+	.get_value = ctrl_get_##vname, \
+	.is_dirty = ctrl_isdirty_##vname, \
+	.clear_dirty = ctrl_cleardirty_##vname
+
+
+#define VCREATE_FUNCS(vname) \
+static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \
+{*vp = cptr->hdw->vname##_val; return 0;} \
+static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \
+{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \
+static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \
+{return cptr->hdw->vname##_dirty != 0;} \
+static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \
+{cptr->hdw->vname##_dirty = 0;}
+
+VCREATE_FUNCS(brightness)
+VCREATE_FUNCS(contrast)
+VCREATE_FUNCS(saturation)
+VCREATE_FUNCS(hue)
+VCREATE_FUNCS(volume)
+VCREATE_FUNCS(balance)
+VCREATE_FUNCS(bass)
+VCREATE_FUNCS(treble)
+VCREATE_FUNCS(mute)
+VCREATE_FUNCS(input)
+VCREATE_FUNCS(audiomode)
+VCREATE_FUNCS(res_hor)
+VCREATE_FUNCS(res_ver)
+VCREATE_FUNCS(srate)
+
+#define MIN_FREQ 55250000L
+#define MAX_FREQ 850000000L
+
+/* Table definition of all controls which can be manipulated */
+static const struct pvr2_ctl_info control_defs[] = {
+	{
+		.v4l_id = V4L2_CID_BRIGHTNESS,
+		.desc = "Brightness",
+		.name = "brightness",
+		.default_value = 128,
+		DEFREF(brightness),
+		DEFINT(0,255),
+	},{
+		.v4l_id = V4L2_CID_CONTRAST,
+		.desc = "Contrast",
+		.name = "contrast",
+		.default_value = 68,
+		DEFREF(contrast),
+		DEFINT(0,127),
+	},{
+		.v4l_id = V4L2_CID_SATURATION,
+		.desc = "Saturation",
+		.name = "saturation",
+		.default_value = 64,
+		DEFREF(saturation),
+		DEFINT(0,127),
+	},{
+		.v4l_id = V4L2_CID_HUE,
+		.desc = "Hue",
+		.name = "hue",
+		.default_value = 0,
+		DEFREF(hue),
+		DEFINT(-128,127),
+	},{
+		.v4l_id = V4L2_CID_AUDIO_VOLUME,
+		.desc = "Volume",
+		.name = "volume",
+		.default_value = 65535,
+		DEFREF(volume),
+		DEFINT(0,65535),
+	},{
+		.v4l_id = V4L2_CID_AUDIO_BALANCE,
+		.desc = "Balance",
+		.name = "balance",
+		.default_value = 0,
+		DEFREF(balance),
+		DEFINT(-32768,32767),
+	},{
+		.v4l_id = V4L2_CID_AUDIO_BASS,
+		.desc = "Bass",
+		.name = "bass",
+		.default_value = 0,
+		DEFREF(bass),
+		DEFINT(-32768,32767),
+	},{
+		.v4l_id = V4L2_CID_AUDIO_TREBLE,
+		.desc = "Treble",
+		.name = "treble",
+		.default_value = 0,
+		DEFREF(treble),
+		DEFINT(-32768,32767),
+	},{
+		.v4l_id = V4L2_CID_AUDIO_MUTE,
+		.desc = "Mute",
+		.name = "mute",
+		.default_value = 0,
+		DEFREF(mute),
+		DEFBOOL,
+	},{
+		.desc = "Video Source",
+		.name = "input",
+		.internal_id = PVR2_CID_INPUT,
+		.default_value = PVR2_CVAL_INPUT_TV,
+		DEFREF(input),
+		DEFENUM(control_values_input),
+	},{
+		.desc = "Audio Mode",
+		.name = "audio_mode",
+		.internal_id = PVR2_CID_AUDIOMODE,
+		.default_value = V4L2_TUNER_MODE_STEREO,
+		DEFREF(audiomode),
+		DEFENUM(control_values_audiomode),
+	},{
+		.desc = "Horizontal capture resolution",
+		.name = "resolution_hor",
+		.internal_id = PVR2_CID_HRES,
+		.default_value = 720,
+		DEFREF(res_hor),
+		DEFINT(320,720),
+	},{
+		.desc = "Vertical capture resolution",
+		.name = "resolution_ver",
+		.internal_id = PVR2_CID_VRES,
+		.default_value = 480,
+		DEFREF(res_ver),
+		DEFINT(200,625),
+	},{
+		.v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
+		.desc = "Sample rate",
+		.name = "srate",
+		.default_value = PVR2_CVAL_SRATE_48,
+		DEFREF(srate),
+		DEFENUM(control_values_srate),
+	},{
+		.desc = "Tuner Frequency (Hz)",
+		.name = "frequency",
+		.internal_id = PVR2_CID_FREQUENCY,
+		.default_value = 175250000L,
+		.set_value = ctrl_freq_set,
+		.get_value = ctrl_freq_get,
+		.is_dirty = ctrl_freq_is_dirty,
+		.clear_dirty = ctrl_freq_clear_dirty,
+		DEFINT(MIN_FREQ,MAX_FREQ),
+	},{
+		.desc = "Channel",
+		.name = "channel",
+		.set_value = ctrl_channel_set,
+		.get_value = ctrl_channel_get,
+		DEFINT(0,FREQTABLE_SIZE),
+	},{
+		.desc = "Channel Program Frequency",
+		.name = "freq_table_value",
+		.set_value = ctrl_channelfreq_set,
+		.get_value = ctrl_channelfreq_get,
+		DEFINT(MIN_FREQ,MAX_FREQ),
+	},{
+		.desc = "Channel Program ID",
+		.name = "freq_table_channel",
+		.set_value = ctrl_channelprog_set,
+		.get_value = ctrl_channelprog_get,
+		DEFINT(0,FREQTABLE_SIZE),
+	},{
+		.desc = "Streaming Enabled",
+		.name = "streaming_enabled",
+		.get_value = ctrl_streamingenabled_get,
+		DEFBOOL,
+	},{
+		.desc = "USB Speed",
+		.name = "usb_speed",
+		.get_value = ctrl_hsm_get,
+		DEFENUM(control_values_hsm),
+	},{
+		.desc = "Signal Present",
+		.name = "signal_present",
+		.get_value = ctrl_signal_get,
+		DEFBOOL,
+	},{
+		.desc = "Video Standards Available Mask",
+		.name = "video_standard_mask_available",
+		.internal_id = PVR2_CID_STDAVAIL,
+		.skip_init = !0,
+		.get_value = ctrl_stdavail_get,
+		.set_value = ctrl_stdavail_set,
+		.val_to_sym = ctrl_std_val_to_sym,
+		.sym_to_val = ctrl_std_sym_to_val,
+		.type = pvr2_ctl_bitmask,
+	},{
+		.desc = "Video Standards In Use Mask",
+		.name = "video_standard_mask_active",
+		.internal_id = PVR2_CID_STDCUR,
+		.skip_init = !0,
+		.get_value = ctrl_stdcur_get,
+		.set_value = ctrl_stdcur_set,
+		.is_dirty = ctrl_stdcur_is_dirty,
+		.clear_dirty = ctrl_stdcur_clear_dirty,
+		.val_to_sym = ctrl_std_val_to_sym,
+		.sym_to_val = ctrl_std_sym_to_val,
+		.type = pvr2_ctl_bitmask,
+	},{
+		.desc = "Subsystem enabled mask",
+		.name = "debug_subsys_mask",
+		.skip_init = !0,
+		.get_value = ctrl_subsys_get,
+		.set_value = ctrl_subsys_set,
+		DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
+	},{
+		.desc = "Subsystem stream mask",
+		.name = "debug_subsys_stream_mask",
+		.skip_init = !0,
+		.get_value = ctrl_subsys_stream_get,
+		.set_value = ctrl_subsys_stream_set,
+		DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem),
+	},{
+		.desc = "Video Standard Name",
+		.name = "video_standard",
+		.internal_id = PVR2_CID_STDENUM,
+		.skip_init = !0,
+		.get_value = ctrl_stdenumcur_get,
+		.set_value = ctrl_stdenumcur_set,
+		.is_dirty = ctrl_stdenumcur_is_dirty,
+		.clear_dirty = ctrl_stdenumcur_clear_dirty,
+		.type = pvr2_ctl_enum,
+	}
+};
+
+#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0]))
+
+
+const char *pvr2_config_get_name(enum pvr2_config cfg)
+{
+	switch (cfg) {
+	case pvr2_config_empty: return "empty";
+	case pvr2_config_mpeg: return "mpeg";
+	case pvr2_config_vbi: return "vbi";
+	case pvr2_config_radio: return "radio";
+	}
+	return "<unknown>";
+}
+
+
+struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *hdw)
+{
+	return hdw->usb_dev;
+}
+
+
+unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw)
+{
+	return hdw->serial_number;
+}
+
+
+struct pvr2_hdw *pvr2_hdw_find(int unit_number)
+{
+	if (unit_number < 0) return 0;
+	if (unit_number >= PVR_NUM) return 0;
+	return unit_pointers[unit_number];
+}
+
+
+int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw)
+{
+	return hdw->unit_number;
+}
+
+
+/* Attempt to locate one of the given set of files.  Messages are logged
+   appropriate to what has been found.  The return value will be 0 or
+   greater on success (it will be the index of the file name found) and
+   fw_entry will be filled in.  Otherwise a negative error is returned on
+   failure.  If the return value is -ENOENT then no viable firmware file
+   could be located. */
+static int pvr2_locate_firmware(struct pvr2_hdw *hdw,
+				const struct firmware **fw_entry,
+				const char *fwtypename,
+				unsigned int fwcount,
+				const char *fwnames[])
+{
+	unsigned int idx;
+	int ret = -EINVAL;
+	for (idx = 0; idx < fwcount; idx++) {
+		ret = request_firmware(fw_entry,
+				       fwnames[idx],
+				       &hdw->usb_dev->dev);
+		if (!ret) {
+			trace_firmware("Located %s firmware: %s;"
+				       " uploading...",
+				       fwtypename,
+				       fwnames[idx]);
+			return idx;
+		}
+		if (ret == -ENOENT) continue;
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "request_firmware fatal error with code=%d",ret);
+		return ret;
+	}
+	pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+		   "***WARNING***"
+		   " Device %s firmware"
+		   " seems to be missing.",
+		   fwtypename);
+	pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+		   "Did you install the pvrusb2 firmware files"
+		   " in their proper location?");
+	if (fwcount == 1) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "request_firmware unable to locate %s file %s",
+			   fwtypename,fwnames[0]);
+	} else {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "request_firmware unable to locate"
+			   " one of the following %s files:",
+			   fwtypename);
+		for (idx = 0; idx < fwcount; idx++) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "request_firmware: Failed to find %s",
+				   fwnames[idx]);
+		}
+	}
+	return ret;
+}
+
+
+/*
+ * pvr2_upload_firmware1().
+ *
+ * Send the 8051 firmware to the device.  After the upload, arrange for
+ * device to re-enumerate.
+ *
+ * NOTE : the pointer to the firmware data given by request_firmware()
+ * is not suitable for an usb transaction.
+ *
+ */
+int pvr2_upload_firmware1(struct pvr2_hdw *hdw)
+{
+	const struct firmware *fw_entry = 0;
+	void  *fw_ptr;
+	unsigned int pipe;
+	int ret;
+	u16 address;
+	static const char *fw_files_29xxx[] = {
+		"v4l-pvrusb2-29xxx-01.fw",
+	};
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+	static const char *fw_files_24xxx[] = {
+		"v4l-pvrusb2-24xxx-01.fw",
+	};
+#endif
+	static const struct pvr2_string_table fw_file_defs[] = {
+		[PVR2_HDW_TYPE_29XXX] = {
+			fw_files_29xxx,
+			sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]),
+		},
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+		[PVR2_HDW_TYPE_24XXX] = {
+			fw_files_24xxx,
+			sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]),
+		},
+#endif
+	};
+	hdw->fw1_state = FW1_STATE_FAILED; // default result
+
+	trace_firmware("pvr2_upload_firmware1");
+
+	ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller",
+				   fw_file_defs[hdw->hdw_type].cnt,
+				   fw_file_defs[hdw->hdw_type].lst);
+	if (ret < 0) {
+		if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING;
+		return ret;
+	}
+
+	usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0);
+	usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f));
+
+	pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
+
+	if (fw_entry->size != 0x2000){
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,"wrong fx2 firmware size");
+		release_firmware(fw_entry);
+		return -ENOMEM;
+	}
+
+	fw_ptr = kmalloc(0x800, GFP_KERNEL);
+	if (fw_ptr == NULL){
+		release_firmware(fw_entry);
+		return -ENOMEM;
+	}
+
+	/* We have to hold the CPU during firmware upload. */
+	pvr2_hdw_cpureset_assert(hdw,1);
+
+	/* upload the firmware to address 0000-1fff in 2048 (=0x800) bytes
+	   chunk. */
+
+	ret = 0;
+	for(address = 0; address < fw_entry->size; address += 0x800) {
+		memcpy(fw_ptr, fw_entry->data + address, 0x800);
+		ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address,
+				       0, fw_ptr, 0x800, HZ);
+	}
+
+	trace_firmware("Upload done, releasing device's CPU");
+
+	/* Now release the CPU.  It will disconnect and reconnect later. */
+	pvr2_hdw_cpureset_assert(hdw,0);
+
+	kfree(fw_ptr);
+	release_firmware(fw_entry);
+
+	trace_firmware("Upload done (%d bytes sent)",ret);
+
+	/* We should have written 8192 bytes */
+	if (ret == 8192) {
+		hdw->fw1_state = FW1_STATE_RELOAD;
+		return 0;
+	}
+
+	return -EIO;
+}
+
+
+/*
+ * pvr2_upload_firmware2()
+ *
+ * This uploads encoder firmware on endpoint 2.
+ *
+ */
+
+int pvr2_upload_firmware2(struct pvr2_hdw *hdw)
+{
+	const struct firmware *fw_entry = 0;
+	void  *fw_ptr;
+	unsigned int pipe, fw_len, fw_done;
+	int actual_length;
+	int ret = 0;
+	int fwidx;
+	static const char *fw_files[] = {
+		CX2341X_FIRM_ENC_FILENAME,
+	};
+
+	trace_firmware("pvr2_upload_firmware2");
+
+	ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder",
+				   sizeof(fw_files)/sizeof(fw_files[0]),
+				   fw_files);
+	if (ret < 0) return ret;
+	fwidx = ret;
+	ret = 0;
+	/* Since we're about to completely reinitialize the encoder,
+	   invalidate our cached copy of its configuration state.  Next
+	   time we configure the encoder, then we'll fully configure it. */
+	hdw->enc_cur_valid = 0;
+
+	/* First prepare firmware loading */
+	ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/
+	ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/
+	ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
+	ret |= pvr2_hdw_cmd_deep_reset(hdw);
+	ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/
+	ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/
+	ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/
+	ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/
+	ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/
+	ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/
+	ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/
+	ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/
+	ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/
+	ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/
+	ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/
+	ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/
+	ret |= pvr2_write_u8(hdw, 0x52, 0);
+	ret |= pvr2_write_u16(hdw, 0x0600, 0);
+
+	if (ret) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "firmware2 upload prep failed, ret=%d",ret);
+		release_firmware(fw_entry);
+		return ret;
+	}
+
+	/* Now send firmware */
+
+	fw_len = fw_entry->size;
+
+	if (fw_len % FIRMWARE_CHUNK_SIZE) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "size of %s firmware"
+			   " must be a multiple of 8192B",
+			   fw_files[fwidx]);
+		release_firmware(fw_entry);
+		return -1;
+	}
+
+	fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL);
+	if (fw_ptr == NULL){
+		release_firmware(fw_entry);
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "failed to allocate memory for firmware2 upload");
+		return -ENOMEM;
+	}
+
+	pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT);
+
+	for (fw_done = 0 ; (fw_done < fw_len) && !ret ;
+	     fw_done += FIRMWARE_CHUNK_SIZE ) {
+		int i;
+		memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE);
+		/* Usbsnoop log  shows that we must swap bytes... */
+		for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++)
+			((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]);
+
+		ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr,
+				    FIRMWARE_CHUNK_SIZE,
+				    &actual_length, HZ);
+		ret |= (actual_length != FIRMWARE_CHUNK_SIZE);
+	}
+
+	trace_firmware("upload of %s : %i / %i ",
+		       fw_files[fwidx],fw_done,fw_len);
+
+	kfree(fw_ptr);
+	release_firmware(fw_entry);
+
+	if (ret) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "firmware2 upload transfer failure");
+		return ret;
+	}
+
+	/* Finish upload */
+
+	ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/
+	ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/
+	ret |= pvr2_write_u16(hdw, 0x0600, 0);
+
+	if (ret) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "firmware2 upload post-proc failure");
+	} else {
+		hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_FIRMWARE);
+	}
+	return ret;
+}
+
+
+#define FIRMWARE_RECOVERY_BITS \
+	((1<<PVR2_SUBSYS_B_ENC_CFG) | \
+	 (1<<PVR2_SUBSYS_B_ENC_RUN) | \
+	 (1<<PVR2_SUBSYS_B_ENC_FIRMWARE) | \
+	 (1<<PVR2_SUBSYS_B_USBSTREAM_RUN))
+
+/*
+
+  This single function is key to pretty much everything.  The pvrusb2
+  device can logically be viewed as a series of subsystems which can be
+  stopped / started or unconfigured / configured.  To get things streaming,
+  one must configure everything and start everything, but there may be
+  various reasons over time to deconfigure something or stop something.
+  This function handles all of this activity.  Everything EVERYWHERE that
+  must affect a subsystem eventually comes here to do the work.
+
+  The current state of all subsystems is represented by a single bit mask,
+  known as subsys_enabled_mask.  The bit positions are defined by the
+  PVR2_SUBSYS_xxxx macros, with one subsystem per bit position.  At any
+  time the set of configured or active subsystems can be queried just by
+  looking at that mask.  To change bits in that mask, this function here
+  must be called.  The "msk" argument indicates which bit positions to
+  change, and the "val" argument defines the new values for the positions
+  defined by "msk".
+
+  There is a priority ordering of starting / stopping things, and for
+  multiple requested changes, this function implements that ordering.
+  (Thus we will act on a request to load encoder firmware before we
+  configure the encoder.)  In addition to priority ordering, there is a
+  recovery strategy implemented here.  If a particular step fails and we
+  detect that failure, this function will clear the affected subsystem bits
+  and restart.  Thus we have a means for recovering from a dead encoder:
+  Clear all bits that correspond to subsystems that we need to restart /
+  reconfigure and start over.
+
+*/
+void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw,
+				     unsigned long msk,unsigned long val)
+{
+	unsigned long nmsk;
+	unsigned long vmsk;
+	int ret;
+	unsigned int tryCount = 0;
+
+	if (!hdw->flag_ok) return;
+
+	msk &= PVR2_SUBSYS_ALL;
+	nmsk = (hdw->subsys_enabled_mask & ~msk) | (val & msk);
+	nmsk &= PVR2_SUBSYS_ALL;
+
+	for (;;) {
+		tryCount++;
+		if (!((nmsk ^ hdw->subsys_enabled_mask) &
+		      PVR2_SUBSYS_ALL)) break;
+		if (tryCount > 4) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "Too many retries when configuring device;"
+				   " giving up");
+			pvr2_hdw_render_useless(hdw);
+			break;
+		}
+		if (tryCount > 1) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "Retrying device reconfiguration");
+		}
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "subsys mask changing 0x%lx:0x%lx"
+			   " from 0x%lx to 0x%lx",
+			   msk,val,hdw->subsys_enabled_mask,nmsk);
+
+		vmsk = (nmsk ^ hdw->subsys_enabled_mask) &
+			hdw->subsys_enabled_mask;
+		if (vmsk) {
+			if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " pvr2_encoder_stop");
+				ret = pvr2_encoder_stop(hdw);
+				if (ret) {
+					pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+						   "Error recovery initiated");
+					hdw->subsys_enabled_mask &=
+						~FIRMWARE_RECOVERY_BITS;
+					continue;
+				}
+			}
+			if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " pvr2_hdw_cmd_usbstream(0)");
+				pvr2_hdw_cmd_usbstream(hdw,0);
+			}
+			if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " decoder disable");
+				if (hdw->decoder_ctrl) {
+					hdw->decoder_ctrl->enable(
+						hdw->decoder_ctrl->ctxt,0);
+				} else {
+					pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+						   "WARNING:"
+						   " No decoder present");
+				}
+				hdw->subsys_enabled_mask &=
+					~(1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
+			}
+			if (vmsk & PVR2_SUBSYS_CFG_ALL) {
+				hdw->subsys_enabled_mask &=
+					~(vmsk & PVR2_SUBSYS_CFG_ALL);
+			}
+		}
+		vmsk = (nmsk ^ hdw->subsys_enabled_mask) & nmsk;
+		if (vmsk) {
+			if (vmsk & (1<<PVR2_SUBSYS_B_ENC_FIRMWARE)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " pvr2_upload_firmware2");
+				ret = pvr2_upload_firmware2(hdw);
+				if (ret) {
+					pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+						   "Failure uploading encoder"
+						   " firmware");
+					pvr2_hdw_render_useless(hdw);
+					break;
+				}
+			}
+			if (vmsk & (1<<PVR2_SUBSYS_B_ENC_CFG)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " pvr2_encoder_configure");
+				ret = pvr2_encoder_configure(hdw);
+				if (ret) {
+					pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+						   "Error recovery initiated");
+					hdw->subsys_enabled_mask &=
+						~FIRMWARE_RECOVERY_BITS;
+					continue;
+				}
+			}
+			if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " decoder enable");
+				if (hdw->decoder_ctrl) {
+					hdw->decoder_ctrl->enable(
+						hdw->decoder_ctrl->ctxt,!0);
+				} else {
+					pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+						   "WARNING:"
+						   " No decoder present");
+				}
+				hdw->subsys_enabled_mask |=
+					(1<<PVR2_SUBSYS_B_DIGITIZER_RUN);
+			}
+			if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " pvr2_hdw_cmd_usbstream(1)");
+				pvr2_hdw_cmd_usbstream(hdw,!0);
+			}
+			if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) {
+				pvr2_trace(PVR2_TRACE_CTL,
+					   "/*---TRACE_CTL----*/"
+					   " pvr2_encoder_start");
+				ret = pvr2_encoder_start(hdw);
+				if (ret) {
+					pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+						   "Error recovery initiated");
+					hdw->subsys_enabled_mask &=
+						~FIRMWARE_RECOVERY_BITS;
+					continue;
+				}
+			}
+		}
+	}
+}
+
+
+void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw,
+			     unsigned long msk,unsigned long val)
+{
+	LOCK_TAKE(hdw->big_lock); do {
+		pvr2_hdw_subsys_bit_chg_no_lock(hdw,msk,val);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+void pvr2_hdw_subsys_bit_set(struct pvr2_hdw *hdw,unsigned long msk)
+{
+	pvr2_hdw_subsys_bit_chg(hdw,msk,msk);
+}
+
+
+void pvr2_hdw_subsys_bit_clr(struct pvr2_hdw *hdw,unsigned long msk)
+{
+	pvr2_hdw_subsys_bit_chg(hdw,msk,0);
+}
+
+
+unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *hdw)
+{
+	return hdw->subsys_enabled_mask;
+}
+
+
+unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *hdw)
+{
+	return hdw->subsys_stream_mask;
+}
+
+
+void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw,
+					    unsigned long msk,
+					    unsigned long val)
+{
+	unsigned long val2;
+	msk &= PVR2_SUBSYS_ALL;
+	val2 = ((hdw->subsys_stream_mask & ~msk) | (val & msk));
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "stream mask changing 0x%lx:0x%lx from 0x%lx to 0x%lx",
+		   msk,val,hdw->subsys_stream_mask,val2);
+	hdw->subsys_stream_mask = val2;
+}
+
+
+void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw,
+				    unsigned long msk,
+				    unsigned long val)
+{
+	LOCK_TAKE(hdw->big_lock); do {
+		pvr2_hdw_subsys_stream_bit_chg_no_lock(hdw,msk,val);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl)
+{
+	if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0;
+	if (enableFl) {
+		pvr2_trace(PVR2_TRACE_START_STOP,
+			   "/*--TRACE_STREAM--*/ enable");
+		pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,~0);
+	} else {
+		pvr2_trace(PVR2_TRACE_START_STOP,
+			   "/*--TRACE_STREAM--*/ disable");
+		pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0);
+	}
+	if (!hdw->flag_ok) return -EIO;
+	hdw->flag_streaming_enabled = enableFl != 0;
+	return 0;
+}
+
+
+int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw)
+{
+	return hdw->flag_streaming_enabled != 0;
+}
+
+
+int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag)
+{
+	int ret;
+	LOCK_TAKE(hdw->big_lock); do {
+		ret = pvr2_hdw_set_streaming_no_lock(hdw,enable_flag);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+	return ret;
+}
+
+
+int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw,
+				     enum pvr2_config config)
+{
+	unsigned long sm = hdw->subsys_enabled_mask;
+	if (!hdw->flag_ok) return -EIO;
+	pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0);
+	hdw->config = config;
+	pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,sm);
+	return 0;
+}
+
+
+int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config)
+{
+	int ret;
+	if (!hdw->flag_ok) return -EIO;
+	LOCK_TAKE(hdw->big_lock);
+	ret = pvr2_hdw_set_stream_type_no_lock(hdw,config);
+	LOCK_GIVE(hdw->big_lock);
+	return ret;
+}
+
+
+static int get_default_tuner_type(struct pvr2_hdw *hdw)
+{
+	int unit_number = hdw->unit_number;
+	int tp = -1;
+	if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+		tp = tuner[unit_number];
+	}
+	if (tp < 0) return -EINVAL;
+	hdw->tuner_type = tp;
+	return 0;
+}
+
+
+static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw)
+{
+	int unit_number = hdw->unit_number;
+	int tp = 0;
+	if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+		tp = video_std[unit_number];
+	}
+	return tp;
+}
+
+
+static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw)
+{
+	int unit_number = hdw->unit_number;
+	int tp = 0;
+	if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+		tp = tolerance[unit_number];
+	}
+	return tp;
+}
+
+
+static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw)
+{
+	/* Try a harmless request to fetch the eeprom's address over
+	   endpoint 1.  See what happens.  Only the full FX2 image can
+	   respond to this.  If this probe fails then likely the FX2
+	   firmware needs be loaded. */
+	int result;
+	LOCK_TAKE(hdw->ctl_lock); do {
+		hdw->cmd_buffer[0] = 0xeb;
+		result = pvr2_send_request_ex(hdw,HZ*1,!0,
+					   hdw->cmd_buffer,1,
+					   hdw->cmd_buffer,1);
+		if (result < 0) break;
+	} while(0); LOCK_GIVE(hdw->ctl_lock);
+	if (result) {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Probe of device endpoint 1 result status %d",
+			   result);
+	} else {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Probe of device endpoint 1 succeeded");
+	}
+	return result == 0;
+}
+
+static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw)
+{
+	char buf[40];
+	unsigned int bcnt;
+	v4l2_std_id std1,std2;
+
+	std1 = get_default_standard(hdw);
+
+	bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom);
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "Supported video standard(s) reported by eeprom: %.*s",
+		   bcnt,buf);
+
+	hdw->std_mask_avail = hdw->std_mask_eeprom;
+
+	std2 = std1 & ~hdw->std_mask_avail;
+	if (std2) {
+		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2);
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Expanding supported video standards"
+			   " to include: %.*s",
+			   bcnt,buf);
+		hdw->std_mask_avail |= std2;
+	}
+
+	pvr2_hdw_internal_set_std_avail(hdw);
+
+	if (std1) {
+		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1);
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Initial video standard forced to %.*s",
+			   bcnt,buf);
+		hdw->std_mask_cur = std1;
+		hdw->std_dirty = !0;
+		pvr2_hdw_internal_find_stdenum(hdw);
+		return;
+	}
+
+	if (hdw->std_enum_cnt > 1) {
+		// Autoselect the first listed standard
+		hdw->std_enum_cur = 1;
+		hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id;
+		hdw->std_dirty = !0;
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Initial video standard auto-selected to %s",
+			   hdw->std_defs[hdw->std_enum_cur-1].name);
+		return;
+	}
+
+	pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+		   "Unable to select a viable initial video standard");
+}
+
+
+static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw)
+{
+	int ret;
+	unsigned int idx;
+	struct pvr2_ctrl *cptr;
+	int reloadFl = 0;
+	if (!reloadFl) {
+		reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints
+			    == 0);
+		if (reloadFl) {
+			pvr2_trace(PVR2_TRACE_INIT,
+				   "USB endpoint config looks strange"
+				   "; possibly firmware needs to be loaded");
+		}
+	}
+	if (!reloadFl) {
+		reloadFl = !pvr2_hdw_check_firmware(hdw);
+		if (reloadFl) {
+			pvr2_trace(PVR2_TRACE_INIT,
+				   "Check for FX2 firmware failed"
+				   "; possibly firmware needs to be loaded");
+		}
+	}
+	if (reloadFl) {
+		if (pvr2_upload_firmware1(hdw) != 0) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "Failure uploading firmware1");
+		}
+		return;
+	}
+	hdw->fw1_state = FW1_STATE_OK;
+
+	if (initusbreset) {
+		pvr2_hdw_device_reset(hdw);
+	}
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) {
+		request_module(pvr2_client_lists[hdw->hdw_type].lst[idx]);
+	}
+
+	pvr2_hdw_cmd_powerup(hdw);
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	if (pvr2_upload_firmware2(hdw)){
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!");
+		pvr2_hdw_render_useless(hdw);
+		return;
+	}
+
+	// This step MUST happen after the earlier powerup step.
+	pvr2_i2c_core_init(hdw);
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
+		cptr = hdw->controls + idx;
+		if (cptr->info->skip_init) continue;
+		if (!cptr->info->set_value) continue;
+		cptr->info->set_value(cptr,~0,cptr->info->default_value);
+	}
+
+	// Do not use pvr2_reset_ctl_endpoints() here.  It is not
+	// thread-safe against the normal pvr2_send_request() mechanism.
+	// (We should make it thread safe).
+
+	ret = pvr2_hdw_get_eeprom_addr(hdw);
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+	if (ret < 0) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Unable to determine location of eeprom, skipping");
+	} else {
+		hdw->eeprom_addr = ret;
+		pvr2_eeprom_analyze(hdw);
+		if (!pvr2_hdw_dev_ok(hdw)) return;
+	}
+
+	pvr2_hdw_setup_std(hdw);
+
+	if (!get_default_tuner_type(hdw)) {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "pvr2_hdw_setup: Tuner type overridden to %d",
+			   hdw->tuner_type);
+	}
+
+	hdw->tuner_updated = !0;
+	pvr2_i2c_core_check_stale(hdw);
+	hdw->tuner_updated = 0;
+
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	pvr2_hdw_commit_ctl_internal(hdw);
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	hdw->vid_stream = pvr2_stream_create();
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "pvr2_hdw_setup: video stream is %p",hdw->vid_stream);
+	if (hdw->vid_stream) {
+		idx = get_default_error_tolerance(hdw);
+		if (idx) {
+			pvr2_trace(PVR2_TRACE_INIT,
+				   "pvr2_hdw_setup: video stream %p"
+				   " setting tolerance %u",
+				   hdw->vid_stream,idx);
+		}
+		pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev,
+				  PVR2_VID_ENDPOINT,idx);
+	}
+
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	/* Make sure everything is up to date */
+	pvr2_i2c_core_sync(hdw);
+
+	if (!pvr2_hdw_dev_ok(hdw)) return;
+
+	hdw->flag_init_ok = !0;
+}
+
+
+int pvr2_hdw_setup(struct pvr2_hdw *hdw)
+{
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw);
+	LOCK_TAKE(hdw->big_lock); do {
+		pvr2_hdw_setup_low(hdw);
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d",
+			   hdw,hdw->flag_ok,hdw->flag_init_ok);
+		if (pvr2_hdw_dev_ok(hdw)) {
+			if (pvr2_hdw_init_ok(hdw)) {
+				pvr2_trace(
+					PVR2_TRACE_INFO,
+					"Device initialization"
+					" completed successfully.");
+				break;
+			}
+			if (hdw->fw1_state == FW1_STATE_RELOAD) {
+				pvr2_trace(
+					PVR2_TRACE_INFO,
+					"Device microcontroller firmware"
+					" (re)loaded; it should now reset"
+					" and reconnect.");
+				break;
+			}
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"Device initialization was not successful.");
+			if (hdw->fw1_state == FW1_STATE_MISSING) {
+				pvr2_trace(
+					PVR2_TRACE_ERROR_LEGS,
+					"Giving up since device"
+					" microcontroller firmware"
+					" appears to be missing.");
+				break;
+			}
+		}
+		if (procreload) {
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"Attempting pvrusb2 recovery by reloading"
+				" primary firmware.");
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"If this works, device should disconnect"
+				" and reconnect in a sane state.");
+			hdw->fw1_state = FW1_STATE_UNKNOWN;
+			pvr2_upload_firmware1(hdw);
+		} else {
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"***WARNING*** pvrusb2 device hardware"
+				" appears to be jammed"
+				" and I can't clear it.");
+			pvr2_trace(
+				PVR2_TRACE_ERROR_LEGS,
+				"You might need to power cycle"
+				" the pvrusb2 device"
+				" in order to recover.");
+		}
+	} while (0); LOCK_GIVE(hdw->big_lock);
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw);
+	return hdw->flag_init_ok;
+}
+
+
+/* Create and return a structure for interacting with the underlying
+   hardware */
+struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+				 const struct usb_device_id *devid)
+{
+	unsigned int idx,cnt1,cnt2;
+	struct pvr2_hdw *hdw;
+	unsigned int hdw_type;
+	int valid_std_mask;
+	struct pvr2_ctrl *cptr;
+	__u8 ifnum;
+	struct v4l2_queryctrl qctrl;
+	struct pvr2_ctl_info *ciptr;
+
+	hdw_type = devid - pvr2_device_table;
+	if (hdw_type >=
+	    sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Bogus device type of %u reported",hdw_type);
+		return 0;
+	}
+
+	hdw = kmalloc(sizeof(*hdw),GFP_KERNEL);
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"",
+		   hdw,pvr2_device_names[hdw_type]);
+	if (!hdw) goto fail;
+	memset(hdw,0,sizeof(*hdw));
+	cx2341x_fill_defaults(&hdw->enc_ctl_state);
+
+	hdw->control_cnt = CTRLDEF_COUNT;
+	hdw->control_cnt += MPEGDEF_COUNT;
+	hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+				GFP_KERNEL);
+	if (!hdw->controls) goto fail;
+	memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt);
+	hdw->hdw_type = hdw_type;
+	for (idx = 0; idx < hdw->control_cnt; idx++) {
+		cptr = hdw->controls + idx;
+		cptr->hdw = hdw;
+	}
+	for (idx = 0; idx < 32; idx++) {
+		hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx];
+	}
+	for (idx = 0; idx < CTRLDEF_COUNT; idx++) {
+		cptr = hdw->controls + idx;
+		cptr->info = control_defs+idx;
+	}
+	/* Define and configure additional controls from cx2341x module. */
+	hdw->mpeg_ctrl_info = kmalloc(
+		sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL);
+	if (!hdw->mpeg_ctrl_info) goto fail;
+	memset(hdw->mpeg_ctrl_info,0,
+	       sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT);
+	for (idx = 0; idx < MPEGDEF_COUNT; idx++) {
+		cptr = hdw->controls + idx + CTRLDEF_COUNT;
+		ciptr = &(hdw->mpeg_ctrl_info[idx].info);
+		ciptr->desc = hdw->mpeg_ctrl_info[idx].desc;
+		ciptr->name = mpeg_ids[idx].strid;
+		ciptr->v4l_id = mpeg_ids[idx].id;
+		ciptr->skip_init = !0;
+		ciptr->get_value = ctrl_cx2341x_get;
+		ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags;
+		ciptr->is_dirty = ctrl_cx2341x_is_dirty;
+		if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty;
+		qctrl.id = ciptr->v4l_id;
+		cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl);
+		if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) {
+			ciptr->set_value = ctrl_cx2341x_set;
+		}
+		strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name,
+			PVR2_CTLD_INFO_DESC_SIZE);
+		hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0;
+		ciptr->default_value = qctrl.default_value;
+		switch (qctrl.type) {
+		default:
+		case V4L2_CTRL_TYPE_INTEGER:
+			ciptr->type = pvr2_ctl_int;
+			ciptr->def.type_int.min_value = qctrl.minimum;
+			ciptr->def.type_int.max_value = qctrl.maximum;
+			break;
+		case V4L2_CTRL_TYPE_BOOLEAN:
+			ciptr->type = pvr2_ctl_bool;
+			break;
+		case V4L2_CTRL_TYPE_MENU:
+			ciptr->type = pvr2_ctl_enum;
+			ciptr->def.type_enum.value_names =
+				cx2341x_ctrl_get_menu(ciptr->v4l_id);
+			for (cnt1 = 0;
+			     ciptr->def.type_enum.value_names[cnt1] != NULL;
+			     cnt1++) { }
+			ciptr->def.type_enum.count = cnt1;
+			break;
+		}
+		cptr->info = ciptr;
+	}
+
+	// Initialize video standard enum dynamic control
+	cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM);
+	if (cptr) {
+		memcpy(&hdw->std_info_enum,cptr->info,
+		       sizeof(hdw->std_info_enum));
+		cptr->info = &hdw->std_info_enum;
+
+	}
+	// Initialize control data regarding video standard masks
+	valid_std_mask = pvr2_std_get_usable();
+	for (idx = 0; idx < 32; idx++) {
+		if (!(valid_std_mask & (1 << idx))) continue;
+		cnt1 = pvr2_std_id_to_str(
+			hdw->std_mask_names[idx],
+			sizeof(hdw->std_mask_names[idx])-1,
+			1 << idx);
+		hdw->std_mask_names[idx][cnt1] = 0;
+	}
+	cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL);
+	if (cptr) {
+		memcpy(&hdw->std_info_avail,cptr->info,
+		       sizeof(hdw->std_info_avail));
+		cptr->info = &hdw->std_info_avail;
+		hdw->std_info_avail.def.type_bitmask.bit_names =
+			hdw->std_mask_ptrs;
+		hdw->std_info_avail.def.type_bitmask.valid_bits =
+			valid_std_mask;
+	}
+	cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR);
+	if (cptr) {
+		memcpy(&hdw->std_info_cur,cptr->info,
+		       sizeof(hdw->std_info_cur));
+		cptr->info = &hdw->std_info_cur;
+		hdw->std_info_cur.def.type_bitmask.bit_names =
+			hdw->std_mask_ptrs;
+		hdw->std_info_avail.def.type_bitmask.valid_bits =
+			valid_std_mask;
+	}
+
+	hdw->eeprom_addr = -1;
+	hdw->unit_number = -1;
+	hdw->v4l_minor_number = -1;
+	hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
+	if (!hdw->ctl_write_buffer) goto fail;
+	hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL);
+	if (!hdw->ctl_read_buffer) goto fail;
+	hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL);
+	if (!hdw->ctl_write_urb) goto fail;
+	hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL);
+	if (!hdw->ctl_read_urb) goto fail;
+
+	down(&pvr2_unit_sem); do {
+		for (idx = 0; idx < PVR_NUM; idx++) {
+			if (unit_pointers[idx]) continue;
+			hdw->unit_number = idx;
+			unit_pointers[idx] = hdw;
+			break;
+		}
+	} while (0); up(&pvr2_unit_sem);
+
+	cnt1 = 0;
+	cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2");
+	cnt1 += cnt2;
+	if (hdw->unit_number >= 0) {
+		cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c",
+				 ('a' + hdw->unit_number));
+		cnt1 += cnt2;
+	}
+	if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1;
+	hdw->name[cnt1] = 0;
+
+	pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
+		   hdw->unit_number,hdw->name);
+
+	hdw->tuner_type = -1;
+	hdw->flag_ok = !0;
+	/* Initialize the mask of subsystems that we will shut down when we
+	   stop streaming. */
+	hdw->subsys_stream_mask = PVR2_SUBSYS_RUN_ALL;
+	hdw->subsys_stream_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
+
+	pvr2_trace(PVR2_TRACE_INIT,"subsys_stream_mask: 0x%lx",
+		   hdw->subsys_stream_mask);
+
+	hdw->usb_intf = intf;
+	hdw->usb_dev = interface_to_usbdev(intf);
+
+	ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber;
+	usb_set_interface(hdw->usb_dev,ifnum,0);
+
+	mutex_init(&hdw->ctl_lock_mutex);
+	mutex_init(&hdw->big_lock_mutex);
+
+	return hdw;
+ fail:
+	if (hdw) {
+		if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb);
+		if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb);
+		if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
+		if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
+		if (hdw->controls) kfree(hdw->controls);
+		if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
+		kfree(hdw);
+	}
+	return 0;
+}
+
+
+/* Remove _all_ associations between this driver and the underlying USB
+   layer. */
+void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw)
+{
+	if (hdw->flag_disconnected) return;
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw);
+	if (hdw->ctl_read_urb) {
+		usb_kill_urb(hdw->ctl_read_urb);
+		usb_free_urb(hdw->ctl_read_urb);
+		hdw->ctl_read_urb = 0;
+	}
+	if (hdw->ctl_write_urb) {
+		usb_kill_urb(hdw->ctl_write_urb);
+		usb_free_urb(hdw->ctl_write_urb);
+		hdw->ctl_write_urb = 0;
+	}
+	if (hdw->ctl_read_buffer) {
+		kfree(hdw->ctl_read_buffer);
+		hdw->ctl_read_buffer = 0;
+	}
+	if (hdw->ctl_write_buffer) {
+		kfree(hdw->ctl_write_buffer);
+		hdw->ctl_write_buffer = 0;
+	}
+	pvr2_hdw_render_useless_unlocked(hdw);
+	hdw->flag_disconnected = !0;
+	hdw->usb_dev = 0;
+	hdw->usb_intf = 0;
+}
+
+
+/* Destroy hardware interaction structure */
+void pvr2_hdw_destroy(struct pvr2_hdw *hdw)
+{
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw);
+	if (hdw->fw_buffer) {
+		kfree(hdw->fw_buffer);
+		hdw->fw_buffer = 0;
+	}
+	if (hdw->vid_stream) {
+		pvr2_stream_destroy(hdw->vid_stream);
+		hdw->vid_stream = 0;
+	}
+	if (hdw->audio_stat) {
+		hdw->audio_stat->detach(hdw->audio_stat->ctxt);
+	}
+	if (hdw->decoder_ctrl) {
+		hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt);
+	}
+	pvr2_i2c_core_done(hdw);
+	pvr2_hdw_remove_usb_stuff(hdw);
+	down(&pvr2_unit_sem); do {
+		if ((hdw->unit_number >= 0) &&
+		    (hdw->unit_number < PVR_NUM) &&
+		    (unit_pointers[hdw->unit_number] == hdw)) {
+			unit_pointers[hdw->unit_number] = 0;
+		}
+	} while (0); up(&pvr2_unit_sem);
+	if (hdw->controls) kfree(hdw->controls);
+	if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info);
+	if (hdw->std_defs) kfree(hdw->std_defs);
+	if (hdw->std_enum_names) kfree(hdw->std_enum_names);
+	kfree(hdw);
+}
+
+
+int pvr2_hdw_init_ok(struct pvr2_hdw *hdw)
+{
+	return hdw->flag_init_ok;
+}
+
+
+int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw)
+{
+	return (hdw && hdw->flag_ok);
+}
+
+
+/* Called when hardware has been unplugged */
+void pvr2_hdw_disconnect(struct pvr2_hdw *hdw)
+{
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw);
+	LOCK_TAKE(hdw->big_lock);
+	LOCK_TAKE(hdw->ctl_lock);
+	pvr2_hdw_remove_usb_stuff(hdw);
+	LOCK_GIVE(hdw->ctl_lock);
+	LOCK_GIVE(hdw->big_lock);
+}
+
+
+// Attempt to autoselect an appropriate value for std_enum_cur given
+// whatever is currently in std_mask_cur
+void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw)
+{
+	unsigned int idx;
+	for (idx = 1; idx < hdw->std_enum_cnt; idx++) {
+		if (hdw->std_defs[idx-1].id == hdw->std_mask_cur) {
+			hdw->std_enum_cur = idx;
+			return;
+		}
+	}
+	hdw->std_enum_cur = 0;
+}
+
+
+// Calculate correct set of enumerated standards based on currently known
+// set of available standards bits.
+void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw)
+{
+	struct v4l2_standard *newstd;
+	unsigned int std_cnt;
+	unsigned int idx;
+
+	newstd = pvr2_std_create_enum(&std_cnt,hdw->std_mask_avail);
+
+	if (hdw->std_defs) {
+		kfree(hdw->std_defs);
+		hdw->std_defs = 0;
+	}
+	hdw->std_enum_cnt = 0;
+	if (hdw->std_enum_names) {
+		kfree(hdw->std_enum_names);
+		hdw->std_enum_names = 0;
+	}
+
+	if (!std_cnt) {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"WARNING: Failed to identify any viable standards");
+	}
+	hdw->std_enum_names = kmalloc(sizeof(char *)*(std_cnt+1),GFP_KERNEL);
+	hdw->std_enum_names[0] = "none";
+	for (idx = 0; idx < std_cnt; idx++) {
+		hdw->std_enum_names[idx+1] =
+			newstd[idx].name;
+	}
+	// Set up the dynamic control for this standard
+	hdw->std_info_enum.def.type_enum.value_names = hdw->std_enum_names;
+	hdw->std_info_enum.def.type_enum.count = std_cnt+1;
+	hdw->std_defs = newstd;
+	hdw->std_enum_cnt = std_cnt+1;
+	hdw->std_enum_cur = 0;
+	hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail;
+}
+
+
+int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,
+			       struct v4l2_standard *std,
+			       unsigned int idx)
+{
+	int ret = -EINVAL;
+	if (!idx) return ret;
+	LOCK_TAKE(hdw->big_lock); do {
+		if (idx >= hdw->std_enum_cnt) break;
+		idx--;
+		memcpy(std,hdw->std_defs+idx,sizeof(*std));
+		ret = 0;
+	} while (0); LOCK_GIVE(hdw->big_lock);
+	return ret;
+}
+
+
+/* Get the number of defined controls */
+unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw)
+{
+	return hdw->control_cnt;
+}
+
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw,
+					     unsigned int idx)
+{
+	if (idx >= hdw->control_cnt) return 0;
+	return hdw->controls + idx;
+}
+
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw,
+					  unsigned int ctl_id)
+{
+	struct pvr2_ctrl *cptr;
+	unsigned int idx;
+	int i;
+
+	/* This could be made a lot more efficient, but for now... */
+	for (idx = 0; idx < hdw->control_cnt; idx++) {
+		cptr = hdw->controls + idx;
+		i = cptr->info->internal_id;
+		if (i && (i == ctl_id)) return cptr;
+	}
+	return 0;
+}
+
+
+/* Given a V4L ID, retrieve the control structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id)
+{
+	struct pvr2_ctrl *cptr;
+	unsigned int idx;
+	int i;
+
+	/* This could be made a lot more efficient, but for now... */
+	for (idx = 0; idx < hdw->control_cnt; idx++) {
+		cptr = hdw->controls + idx;
+		i = cptr->info->v4l_id;
+		if (i && (i == ctl_id)) return cptr;
+	}
+	return 0;
+}
+
+
+/* Given a V4L ID for its immediate predecessor, retrieve the control
+   structure associated with it. */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw,
+					    unsigned int ctl_id)
+{
+	struct pvr2_ctrl *cptr,*cp2;
+	unsigned int idx;
+	int i;
+
+	/* This could be made a lot more efficient, but for now... */
+	cp2 = 0;
+	for (idx = 0; idx < hdw->control_cnt; idx++) {
+		cptr = hdw->controls + idx;
+		i = cptr->info->v4l_id;
+		if (!i) continue;
+		if (i <= ctl_id) continue;
+		if (cp2 && (cp2->info->v4l_id < i)) continue;
+		cp2 = cptr;
+	}
+	return cp2;
+	return 0;
+}
+
+
+static const char *get_ctrl_typename(enum pvr2_ctl_type tp)
+{
+	switch (tp) {
+	case pvr2_ctl_int: return "integer";
+	case pvr2_ctl_enum: return "enum";
+	case pvr2_ctl_bool: return "boolean";
+	case pvr2_ctl_bitmask: return "bitmask";
+	}
+	return "";
+}
+
+
+/* Commit all control changes made up to this point.  Subsystems can be
+   indirectly affected by these changes.  For a given set of things being
+   committed, we'll clear the affected subsystem bits and then once we're
+   done committing everything we'll make a request to restore the subsystem
+   state(s) back to their previous value before this function was called.
+   Thus we can automatically reconfigure affected pieces of the driver as
+   controls are changed. */
+int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw)
+{
+	unsigned long saved_subsys_mask = hdw->subsys_enabled_mask;
+	unsigned long stale_subsys_mask = 0;
+	unsigned int idx;
+	struct pvr2_ctrl *cptr;
+	int value;
+	int commit_flag = 0;
+	char buf[100];
+	unsigned int bcnt,ccnt;
+
+	for (idx = 0; idx < hdw->control_cnt; idx++) {
+		cptr = hdw->controls + idx;
+		if (cptr->info->is_dirty == 0) continue;
+		if (!cptr->info->is_dirty(cptr)) continue;
+		if (!commit_flag) {
+			commit_flag = !0;
+		}
+
+		bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ",
+				 cptr->info->name);
+		value = 0;
+		cptr->info->get_value(cptr,&value);
+		pvr2_ctrl_value_to_sym_internal(cptr,~0,value,
+						buf+bcnt,
+						sizeof(buf)-bcnt,&ccnt);
+		bcnt += ccnt;
+		bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>",
+				  get_ctrl_typename(cptr->info->type));
+		pvr2_trace(PVR2_TRACE_CTL,
+			   "/*--TRACE_COMMIT--*/ %.*s",
+			   bcnt,buf);
+	}
+
+	if (!commit_flag) {
+		/* Nothing has changed */
+		return 0;
+	}
+
+	/* When video standard changes, reset the hres and vres values -
+	   but if the user has pending changes there, then let the changes
+	   take priority. */
+	if (hdw->std_dirty) {
+		/* Rewrite the vertical resolution to be appropriate to the
+		   video standard that has been selected. */
+		int nvres;
+		if (hdw->std_mask_cur & V4L2_STD_525_60) {
+			nvres = 480;
+		} else {
+			nvres = 576;
+		}
+		if (nvres != hdw->res_ver_val) {
+			hdw->res_ver_val = nvres;
+			hdw->res_ver_dirty = !0;
+		}
+	}
+
+	if (hdw->std_dirty ||
+	    0) {
+		/* If any of this changes, then the encoder needs to be
+		   reconfigured, and we need to reset the stream. */
+		stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG);
+		stale_subsys_mask |= hdw->subsys_stream_mask;
+	}
+
+	if (hdw->srate_dirty) {
+		/* Write new sample rate into control structure since
+		 * the master copy is stale.  We must track srate
+		 * separate from the mpeg control structure because
+		 * other logic also uses this value. */
+		struct v4l2_ext_controls cs;
+		struct v4l2_ext_control c1;
+		memset(&cs,0,sizeof(cs));
+		memset(&c1,0,sizeof(c1));
+		cs.controls = &c1;
+		cs.count = 1;
+		c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ;
+		c1.value = hdw->srate_val;
+		cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS);
+	}
+
+	/* Scan i2c core at this point - before we clear all the dirty
+	   bits.  Various parts of the i2c core will notice dirty bits as
+	   appropriate and arrange to broadcast or directly send updates to
+	   the client drivers in order to keep everything in sync */
+	pvr2_i2c_core_check_stale(hdw);
+
+	for (idx = 0; idx < hdw->control_cnt; idx++) {
+		cptr = hdw->controls + idx;
+		if (!cptr->info->clear_dirty) continue;
+		cptr->info->clear_dirty(cptr);
+	}
+
+	/* Now execute i2c core update */
+	pvr2_i2c_core_sync(hdw);
+
+	pvr2_hdw_subsys_bit_chg_no_lock(hdw,stale_subsys_mask,0);
+	pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,saved_subsys_mask);
+
+	return 0;
+}
+
+
+int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw)
+{
+	LOCK_TAKE(hdw->big_lock); do {
+		pvr2_hdw_commit_ctl_internal(hdw);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+	return 0;
+}
+
+
+void pvr2_hdw_poll(struct pvr2_hdw *hdw)
+{
+	LOCK_TAKE(hdw->big_lock); do {
+		pvr2_i2c_core_sync(hdw);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *hdw,
+				 void (*func)(void *),
+				 void *data)
+{
+	LOCK_TAKE(hdw->big_lock); do {
+		hdw->poll_trigger_func = func;
+		hdw->poll_trigger_data = data;
+	} while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw)
+{
+	if (hdw->poll_trigger_func) {
+		hdw->poll_trigger_func(hdw->poll_trigger_data);
+	}
+}
+
+
+void pvr2_hdw_poll_trigger(struct pvr2_hdw *hdw)
+{
+	LOCK_TAKE(hdw->big_lock); do {
+		pvr2_hdw_poll_trigger_unlocked(hdw);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+/* Return name for this driver instance */
+const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw)
+{
+	return hdw->name;
+}
+
+
+/* Return bit mask indicating signal status */
+unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw)
+{
+	unsigned int msk = 0;
+	switch (hdw->input_val) {
+	case PVR2_CVAL_INPUT_TV:
+	case PVR2_CVAL_INPUT_RADIO:
+		if (hdw->decoder_ctrl &&
+		    hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) {
+			msk |= PVR2_SIGNAL_OK;
+			if (hdw->audio_stat &&
+			    hdw->audio_stat->status(hdw->audio_stat->ctxt)) {
+				if (hdw->flag_stereo) {
+					msk |= PVR2_SIGNAL_STEREO;
+				}
+				if (hdw->flag_bilingual) {
+					msk |= PVR2_SIGNAL_SAP;
+				}
+			}
+		}
+		break;
+	default:
+		msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO;
+	}
+	return msk;
+}
+
+
+int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw)
+{
+	int result;
+	LOCK_TAKE(hdw->ctl_lock); do {
+		hdw->cmd_buffer[0] = 0x0b;
+		result = pvr2_send_request(hdw,
+					   hdw->cmd_buffer,1,
+					   hdw->cmd_buffer,1);
+		if (result < 0) break;
+		result = (hdw->cmd_buffer[0] != 0);
+	} while(0); LOCK_GIVE(hdw->ctl_lock);
+	return result;
+}
+
+
+/* Return bit mask indicating signal status */
+unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw)
+{
+	unsigned int msk = 0;
+	LOCK_TAKE(hdw->big_lock); do {
+		msk = pvr2_hdw_get_signal_status_internal(hdw);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+	return msk;
+}
+
+
+/* Get handle to video output stream */
+struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp)
+{
+	return hp->vid_stream;
+}
+
+
+void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw)
+{
+	int nr = pvr2_hdw_get_unit_number(hdw);
+	LOCK_TAKE(hdw->big_lock); do {
+		hdw->log_requested = !0;
+		printk(KERN_INFO "pvrusb2: =================  START STATUS CARD #%d  =================\n", nr);
+		pvr2_i2c_core_check_stale(hdw);
+		hdw->log_requested = 0;
+		pvr2_i2c_core_sync(hdw);
+		pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:");
+		cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2");
+		printk(KERN_INFO "pvrusb2: ==================  END STATUS CARD #%d  ==================\n", nr);
+	} while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag)
+{
+	int ret;
+	u16 address;
+	unsigned int pipe;
+	LOCK_TAKE(hdw->big_lock); do {
+		if ((hdw->fw_buffer == 0) == !enable_flag) break;
+
+		if (!enable_flag) {
+			pvr2_trace(PVR2_TRACE_FIRMWARE,
+				   "Cleaning up after CPU firmware fetch");
+			kfree(hdw->fw_buffer);
+			hdw->fw_buffer = 0;
+			hdw->fw_size = 0;
+			/* Now release the CPU.  It will disconnect and
+			   reconnect later. */
+			pvr2_hdw_cpureset_assert(hdw,0);
+			break;
+		}
+
+		pvr2_trace(PVR2_TRACE_FIRMWARE,
+			   "Preparing to suck out CPU firmware");
+		hdw->fw_size = 0x2000;
+		hdw->fw_buffer = kmalloc(hdw->fw_size,GFP_KERNEL);
+		if (!hdw->fw_buffer) {
+			hdw->fw_size = 0;
+			break;
+		}
+
+		memset(hdw->fw_buffer,0,hdw->fw_size);
+
+		/* We have to hold the CPU during firmware upload. */
+		pvr2_hdw_cpureset_assert(hdw,1);
+
+		/* download the firmware from address 0000-1fff in 2048
+		   (=0x800) bytes chunk. */
+
+		pvr2_trace(PVR2_TRACE_FIRMWARE,"Grabbing CPU firmware");
+		pipe = usb_rcvctrlpipe(hdw->usb_dev, 0);
+		for(address = 0; address < hdw->fw_size; address += 0x800) {
+			ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0xc0,
+					      address,0,
+					      hdw->fw_buffer+address,0x800,HZ);
+			if (ret < 0) break;
+		}
+
+		pvr2_trace(PVR2_TRACE_FIRMWARE,"Done grabbing CPU firmware");
+
+	} while (0); LOCK_GIVE(hdw->big_lock);
+}
+
+
+/* Return true if we're in a mode for retrieval CPU firmware */
+int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw)
+{
+	return hdw->fw_buffer != 0;
+}
+
+
+int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs,
+		       char *buf,unsigned int cnt)
+{
+	int ret = -EINVAL;
+	LOCK_TAKE(hdw->big_lock); do {
+		if (!buf) break;
+		if (!cnt) break;
+
+		if (!hdw->fw_buffer) {
+			ret = -EIO;
+			break;
+		}
+
+		if (offs >= hdw->fw_size) {
+			pvr2_trace(PVR2_TRACE_FIRMWARE,
+				   "Read firmware data offs=%d EOF",
+				   offs);
+			ret = 0;
+			break;
+		}
+
+		if (offs + cnt > hdw->fw_size) cnt = hdw->fw_size - offs;
+
+		memcpy(buf,hdw->fw_buffer+offs,cnt);
+
+		pvr2_trace(PVR2_TRACE_FIRMWARE,
+			   "Read firmware data offs=%d cnt=%d",
+			   offs,cnt);
+		ret = cnt;
+	} while (0); LOCK_GIVE(hdw->big_lock);
+
+	return ret;
+}
+
+
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw)
+{
+	return hdw->v4l_minor_number;
+}
+
+
+/* Store the v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v)
+{
+	hdw->v4l_minor_number = v;
+}
+
+
+void pvr2_reset_ctl_endpoints(struct pvr2_hdw *hdw)
+{
+	if (!hdw->usb_dev) return;
+	usb_settoggle(hdw->usb_dev, PVR2_CTL_WRITE_ENDPOINT & 0xf,
+		      !(PVR2_CTL_WRITE_ENDPOINT & USB_DIR_IN), 0);
+	usb_settoggle(hdw->usb_dev, PVR2_CTL_READ_ENDPOINT & 0xf,
+		      !(PVR2_CTL_READ_ENDPOINT & USB_DIR_IN), 0);
+	usb_clear_halt(hdw->usb_dev,
+		       usb_rcvbulkpipe(hdw->usb_dev,
+				       PVR2_CTL_READ_ENDPOINT & 0x7f));
+	usb_clear_halt(hdw->usb_dev,
+		       usb_sndbulkpipe(hdw->usb_dev,
+				       PVR2_CTL_WRITE_ENDPOINT & 0x7f));
+}
+
+
+static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs)
+{
+	struct pvr2_hdw *hdw = urb->context;
+	hdw->ctl_write_pend_flag = 0;
+	if (hdw->ctl_read_pend_flag) return;
+	complete(&hdw->ctl_done);
+}
+
+
+static void pvr2_ctl_read_complete(struct urb *urb, struct pt_regs *regs)
+{
+	struct pvr2_hdw *hdw = urb->context;
+	hdw->ctl_read_pend_flag = 0;
+	if (hdw->ctl_write_pend_flag) return;
+	complete(&hdw->ctl_done);
+}
+
+
+static void pvr2_ctl_timeout(unsigned long data)
+{
+	struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
+	if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
+		hdw->ctl_timeout_flag = !0;
+		if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) {
+			usb_unlink_urb(hdw->ctl_write_urb);
+		}
+		if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) {
+			usb_unlink_urb(hdw->ctl_read_urb);
+		}
+	}
+}
+
+
+int pvr2_send_request_ex(struct pvr2_hdw *hdw,
+			 unsigned int timeout,int probe_fl,
+			 void *write_data,unsigned int write_len,
+			 void *read_data,unsigned int read_len)
+{
+	unsigned int idx;
+	int status = 0;
+	struct timer_list timer;
+	if (!hdw->ctl_lock_held) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Attempted to execute control transfer"
+			   " without lock!!");
+		return -EDEADLK;
+	}
+	if ((!hdw->flag_ok) && !probe_fl) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Attempted to execute control transfer"
+			   " when device not ok");
+		return -EIO;
+	}
+	if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) {
+		if (!probe_fl) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "Attempted to execute control transfer"
+				   " when USB is disconnected");
+		}
+		return -ENOTTY;
+	}
+
+	/* Ensure that we have sane parameters */
+	if (!write_data) write_len = 0;
+	if (!read_data) read_len = 0;
+	if (write_len > PVR2_CTL_BUFFSIZE) {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"Attempted to execute %d byte"
+			" control-write transfer (limit=%d)",
+			write_len,PVR2_CTL_BUFFSIZE);
+		return -EINVAL;
+	}
+	if (read_len > PVR2_CTL_BUFFSIZE) {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"Attempted to execute %d byte"
+			" control-read transfer (limit=%d)",
+			write_len,PVR2_CTL_BUFFSIZE);
+		return -EINVAL;
+	}
+	if ((!write_len) && (!read_len)) {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"Attempted to execute null control transfer?");
+		return -EINVAL;
+	}
+
+
+	hdw->cmd_debug_state = 1;
+	if (write_len) {
+		hdw->cmd_debug_code = ((unsigned char *)write_data)[0];
+	} else {
+		hdw->cmd_debug_code = 0;
+	}
+	hdw->cmd_debug_write_len = write_len;
+	hdw->cmd_debug_read_len = read_len;
+
+	/* Initialize common stuff */
+	init_completion(&hdw->ctl_done);
+	hdw->ctl_timeout_flag = 0;
+	hdw->ctl_write_pend_flag = 0;
+	hdw->ctl_read_pend_flag = 0;
+	init_timer(&timer);
+	timer.expires = jiffies + timeout;
+	timer.data = (unsigned long)hdw;
+	timer.function = pvr2_ctl_timeout;
+
+	if (write_len) {
+		hdw->cmd_debug_state = 2;
+		/* Transfer write data to internal buffer */
+		for (idx = 0; idx < write_len; idx++) {
+			hdw->ctl_write_buffer[idx] =
+				((unsigned char *)write_data)[idx];
+		}
+		/* Initiate a write request */
+		usb_fill_bulk_urb(hdw->ctl_write_urb,
+				  hdw->usb_dev,
+				  usb_sndbulkpipe(hdw->usb_dev,
+						  PVR2_CTL_WRITE_ENDPOINT),
+				  hdw->ctl_write_buffer,
+				  write_len,
+				  pvr2_ctl_write_complete,
+				  hdw);
+		hdw->ctl_write_urb->actual_length = 0;
+		hdw->ctl_write_pend_flag = !0;
+		status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL);
+		if (status < 0) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "Failed to submit write-control"
+				   " URB status=%d",status);
+			hdw->ctl_write_pend_flag = 0;
+			goto done;
+		}
+	}
+
+	if (read_len) {
+		hdw->cmd_debug_state = 3;
+		memset(hdw->ctl_read_buffer,0x43,read_len);
+		/* Initiate a read request */
+		usb_fill_bulk_urb(hdw->ctl_read_urb,
+				  hdw->usb_dev,
+				  usb_rcvbulkpipe(hdw->usb_dev,
+						  PVR2_CTL_READ_ENDPOINT),
+				  hdw->ctl_read_buffer,
+				  read_len,
+				  pvr2_ctl_read_complete,
+				  hdw);
+		hdw->ctl_read_urb->actual_length = 0;
+		hdw->ctl_read_pend_flag = !0;
+		status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL);
+		if (status < 0) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "Failed to submit read-control"
+				   " URB status=%d",status);
+			hdw->ctl_read_pend_flag = 0;
+			goto done;
+		}
+	}
+
+	/* Start timer */
+	add_timer(&timer);
+
+	/* Now wait for all I/O to complete */
+	hdw->cmd_debug_state = 4;
+	while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
+		wait_for_completion(&hdw->ctl_done);
+	}
+	hdw->cmd_debug_state = 5;
+
+	/* Stop timer */
+	del_timer_sync(&timer);
+
+	hdw->cmd_debug_state = 6;
+	status = 0;
+
+	if (hdw->ctl_timeout_flag) {
+		status = -ETIMEDOUT;
+		if (!probe_fl) {
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "Timed out control-write");
+		}
+		goto done;
+	}
+
+	if (write_len) {
+		/* Validate results of write request */
+		if ((hdw->ctl_write_urb->status != 0) &&
+		    (hdw->ctl_write_urb->status != -ENOENT) &&
+		    (hdw->ctl_write_urb->status != -ESHUTDOWN) &&
+		    (hdw->ctl_write_urb->status != -ECONNRESET)) {
+			/* USB subsystem is reporting some kind of failure
+			   on the write */
+			status = hdw->ctl_write_urb->status;
+			if (!probe_fl) {
+				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+					   "control-write URB failure,"
+					   " status=%d",
+					   status);
+			}
+			goto done;
+		}
+		if (hdw->ctl_write_urb->actual_length < write_len) {
+			/* Failed to write enough data */
+			status = -EIO;
+			if (!probe_fl) {
+				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+					   "control-write URB short,"
+					   " expected=%d got=%d",
+					   write_len,
+					   hdw->ctl_write_urb->actual_length);
+			}
+			goto done;
+		}
+	}
+	if (read_len) {
+		/* Validate results of read request */
+		if ((hdw->ctl_read_urb->status != 0) &&
+		    (hdw->ctl_read_urb->status != -ENOENT) &&
+		    (hdw->ctl_read_urb->status != -ESHUTDOWN) &&
+		    (hdw->ctl_read_urb->status != -ECONNRESET)) {
+			/* USB subsystem is reporting some kind of failure
+			   on the read */
+			status = hdw->ctl_read_urb->status;
+			if (!probe_fl) {
+				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+					   "control-read URB failure,"
+					   " status=%d",
+					   status);
+			}
+			goto done;
+		}
+		if (hdw->ctl_read_urb->actual_length < read_len) {
+			/* Failed to read enough data */
+			status = -EIO;
+			if (!probe_fl) {
+				pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+					   "control-read URB short,"
+					   " expected=%d got=%d",
+					   read_len,
+					   hdw->ctl_read_urb->actual_length);
+			}
+			goto done;
+		}
+		/* Transfer retrieved data out from internal buffer */
+		for (idx = 0; idx < read_len; idx++) {
+			((unsigned char *)read_data)[idx] =
+				hdw->ctl_read_buffer[idx];
+		}
+	}
+
+ done:
+
+	hdw->cmd_debug_state = 0;
+	if ((status < 0) && (!probe_fl)) {
+		pvr2_hdw_render_useless_unlocked(hdw);
+	}
+	return status;
+}
+
+
+int pvr2_send_request(struct pvr2_hdw *hdw,
+		      void *write_data,unsigned int write_len,
+		      void *read_data,unsigned int read_len)
+{
+	return pvr2_send_request_ex(hdw,HZ*4,0,
+				    write_data,write_len,
+				    read_data,read_len);
+}
+
+int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data)
+{
+	int ret;
+
+	LOCK_TAKE(hdw->ctl_lock);
+
+	hdw->cmd_buffer[0] = 0x04;  /* write register prefix */
+	PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data);
+	hdw->cmd_buffer[5] = 0;
+	hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
+	hdw->cmd_buffer[7] = reg & 0xff;
+
+
+	ret = pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 0);
+
+	LOCK_GIVE(hdw->ctl_lock);
+
+	return ret;
+}
+
+
+int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data)
+{
+	int ret = 0;
+
+	LOCK_TAKE(hdw->ctl_lock);
+
+	hdw->cmd_buffer[0] = 0x05;  /* read register prefix */
+	hdw->cmd_buffer[1] = 0;
+	hdw->cmd_buffer[2] = 0;
+	hdw->cmd_buffer[3] = 0;
+	hdw->cmd_buffer[4] = 0;
+	hdw->cmd_buffer[5] = 0;
+	hdw->cmd_buffer[6] = (reg >> 8) & 0xff;
+	hdw->cmd_buffer[7] = reg & 0xff;
+
+	ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4);
+	*data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0);
+
+	LOCK_GIVE(hdw->ctl_lock);
+
+	return ret;
+}
+
+
+int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res)
+{
+	int ret;
+
+	LOCK_TAKE(hdw->ctl_lock);
+
+	hdw->cmd_buffer[0] = (data >> 8) & 0xff;
+	hdw->cmd_buffer[1] = data & 0xff;
+
+	ret = pvr2_send_request(hdw, hdw->cmd_buffer, 2, hdw->cmd_buffer, res);
+
+	LOCK_GIVE(hdw->ctl_lock);
+
+	return ret;
+}
+
+
+int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res)
+{
+	int ret;
+
+	LOCK_TAKE(hdw->ctl_lock);
+
+	hdw->cmd_buffer[0] = data;
+
+	ret = pvr2_send_request(hdw, hdw->cmd_buffer, 1, hdw->cmd_buffer, res);
+
+	LOCK_GIVE(hdw->ctl_lock);
+
+	return ret;
+}
+
+
+void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw)
+{
+	if (!hdw->flag_ok) return;
+	pvr2_trace(PVR2_TRACE_INIT,"render_useless");
+	hdw->flag_ok = 0;
+	if (hdw->vid_stream) {
+		pvr2_stream_setup(hdw->vid_stream,0,0,0);
+	}
+	hdw->flag_streaming_enabled = 0;
+	hdw->subsys_enabled_mask = 0;
+}
+
+
+void pvr2_hdw_render_useless(struct pvr2_hdw *hdw)
+{
+	LOCK_TAKE(hdw->ctl_lock);
+	pvr2_hdw_render_useless_unlocked(hdw);
+	LOCK_GIVE(hdw->ctl_lock);
+}
+
+
+void pvr2_hdw_device_reset(struct pvr2_hdw *hdw)
+{
+	int ret;
+	pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset...");
+	ret = usb_lock_device_for_reset(hdw->usb_dev,0);
+	if (ret == 1) {
+		ret = usb_reset_device(hdw->usb_dev);
+		usb_unlock_device(hdw->usb_dev);
+	} else {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Failed to lock USB device ret=%d",ret);
+	}
+	if (init_pause_msec) {
+		pvr2_trace(PVR2_TRACE_INFO,
+			   "Waiting %u msec for hardware to settle",
+			   init_pause_msec);
+		msleep(init_pause_msec);
+	}
+
+}
+
+
+void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val)
+{
+	char da[1];
+	unsigned int pipe;
+	int ret;
+
+	if (!hdw->usb_dev) return;
+
+	pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val);
+
+	da[0] = val ? 0x01 : 0x00;
+
+	/* Write the CPUCS register on the 8051.  The lsb of the register
+	   is the reset bit; a 1 asserts reset while a 0 clears it. */
+	pipe = usb_sndctrlpipe(hdw->usb_dev, 0);
+	ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ);
+	if (ret < 0) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "cpureset_assert(%d) error=%d",val,ret);
+		pvr2_hdw_render_useless(hdw);
+	}
+}
+
+
+int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw)
+{
+	int status;
+	LOCK_TAKE(hdw->ctl_lock); do {
+		pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset");
+		hdw->flag_ok = !0;
+		hdw->cmd_buffer[0] = 0xdd;
+		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+	} while (0); LOCK_GIVE(hdw->ctl_lock);
+	return status;
+}
+
+
+int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw)
+{
+	int status;
+	LOCK_TAKE(hdw->ctl_lock); do {
+		pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup");
+		hdw->cmd_buffer[0] = 0xde;
+		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+	} while (0); LOCK_GIVE(hdw->ctl_lock);
+	return status;
+}
+
+
+int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw)
+{
+	if (!hdw->decoder_ctrl) {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Unable to reset decoder: nothing attached");
+		return -ENOTTY;
+	}
+
+	if (!hdw->decoder_ctrl->force_reset) {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "Unable to reset decoder: not implemented");
+		return -ENOTTY;
+	}
+
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "Requesting decoder reset");
+	hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt);
+	return 0;
+}
+
+
+int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl)
+{
+	int status;
+	LOCK_TAKE(hdw->ctl_lock); do {
+		hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37);
+		status = pvr2_send_request(hdw,hdw->cmd_buffer,1,0,0);
+	} while (0); LOCK_GIVE(hdw->ctl_lock);
+	if (!status) {
+		hdw->subsys_enabled_mask =
+			((hdw->subsys_enabled_mask &
+			  ~(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) |
+			 (runFl ? (1<<PVR2_SUBSYS_B_USBSTREAM_RUN) : 0));
+	}
+	return status;
+}
+
+
+void pvr2_hdw_get_debug_info(const struct pvr2_hdw *hdw,
+			     struct pvr2_hdw_debug_info *ptr)
+{
+	ptr->big_lock_held = hdw->big_lock_held;
+	ptr->ctl_lock_held = hdw->ctl_lock_held;
+	ptr->flag_ok = hdw->flag_ok;
+	ptr->flag_disconnected = hdw->flag_disconnected;
+	ptr->flag_init_ok = hdw->flag_init_ok;
+	ptr->flag_streaming_enabled = hdw->flag_streaming_enabled;
+	ptr->subsys_flags = hdw->subsys_enabled_mask;
+	ptr->cmd_debug_state = hdw->cmd_debug_state;
+	ptr->cmd_code = hdw->cmd_debug_code;
+	ptr->cmd_debug_write_len = hdw->cmd_debug_write_len;
+	ptr->cmd_debug_read_len = hdw->cmd_debug_read_len;
+	ptr->cmd_debug_timeout = hdw->ctl_timeout_flag;
+	ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag;
+	ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag;
+	ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status;
+	ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status;
+}
+
+
+int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp)
+{
+	return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp);
+}
+
+
+int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *dp)
+{
+	return pvr2_read_register(hdw,PVR2_GPIO_OUT,dp);
+}
+
+
+int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *dp)
+{
+	return pvr2_read_register(hdw,PVR2_GPIO_IN,dp);
+}
+
+
+int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val)
+{
+	u32 cval,nval;
+	int ret;
+	if (~msk) {
+		ret = pvr2_read_register(hdw,PVR2_GPIO_DIR,&cval);
+		if (ret) return ret;
+		nval = (cval & ~msk) | (val & msk);
+		pvr2_trace(PVR2_TRACE_GPIO,
+			   "GPIO direction changing 0x%x:0x%x"
+			   " from 0x%x to 0x%x",
+			   msk,val,cval,nval);
+	} else {
+		nval = val;
+		pvr2_trace(PVR2_TRACE_GPIO,
+			   "GPIO direction changing to 0x%x",nval);
+	}
+	return pvr2_write_register(hdw,PVR2_GPIO_DIR,nval);
+}
+
+
+int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val)
+{
+	u32 cval,nval;
+	int ret;
+	if (~msk) {
+		ret = pvr2_read_register(hdw,PVR2_GPIO_OUT,&cval);
+		if (ret) return ret;
+		nval = (cval & ~msk) | (val & msk);
+		pvr2_trace(PVR2_TRACE_GPIO,
+			   "GPIO output changing 0x%x:0x%x from 0x%x to 0x%x",
+			   msk,val,cval,nval);
+	} else {
+		nval = val;
+		pvr2_trace(PVR2_TRACE_GPIO,
+			   "GPIO output changing to 0x%x",nval);
+	}
+	return pvr2_write_register(hdw,PVR2_GPIO_OUT,nval);
+}
+
+
+int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw)
+{
+	int result;
+	LOCK_TAKE(hdw->ctl_lock); do {
+		hdw->cmd_buffer[0] = 0xeb;
+		result = pvr2_send_request(hdw,
+					   hdw->cmd_buffer,1,
+					   hdw->cmd_buffer,1);
+		if (result < 0) break;
+		result = hdw->cmd_buffer[0];
+	} while(0); LOCK_GIVE(hdw->ctl_lock);
+	return result;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
new file mode 100644
index 0000000..63f5291
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h
@@ -0,0 +1,335 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_HDW_H
+#define __PVRUSB2_HDW_H
+
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+#include "pvrusb2-io.h"
+#include "pvrusb2-ctrl.h"
+
+
+/* Private internal control ids, look these up with
+   pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */
+#define PVR2_CID_STDENUM 1
+#define PVR2_CID_STDCUR 2
+#define PVR2_CID_STDAVAIL 3
+#define PVR2_CID_INPUT 4
+#define PVR2_CID_AUDIOMODE 5
+#define PVR2_CID_FREQUENCY 6
+#define PVR2_CID_HRES 7
+#define PVR2_CID_VRES 8
+
+/* Legal values for the INPUT state variable */
+#define PVR2_CVAL_INPUT_TV 0
+#define PVR2_CVAL_INPUT_SVIDEO 1
+#define PVR2_CVAL_INPUT_COMPOSITE 2
+#define PVR2_CVAL_INPUT_RADIO 3
+
+/* Values that pvr2_hdw_get_signal_status() returns */
+#define PVR2_SIGNAL_OK     0x0001
+#define PVR2_SIGNAL_STEREO 0x0002
+#define PVR2_SIGNAL_SAP    0x0004
+
+
+/* Subsystem definitions - these are various pieces that can be
+   independently stopped / started.  Usually you don't want to mess with
+   this directly (let the driver handle things itself), but it is useful
+   for debugging. */
+#define PVR2_SUBSYS_B_ENC_FIRMWARE        0
+#define PVR2_SUBSYS_B_ENC_CFG             1
+#define PVR2_SUBSYS_B_DIGITIZER_RUN       2
+#define PVR2_SUBSYS_B_USBSTREAM_RUN       3
+#define PVR2_SUBSYS_B_ENC_RUN             4
+
+#define PVR2_SUBSYS_CFG_ALL ( \
+	(1 << PVR2_SUBSYS_B_ENC_FIRMWARE) | \
+	(1 << PVR2_SUBSYS_B_ENC_CFG) )
+#define PVR2_SUBSYS_RUN_ALL ( \
+	(1 << PVR2_SUBSYS_B_DIGITIZER_RUN) | \
+	(1 << PVR2_SUBSYS_B_USBSTREAM_RUN) | \
+	(1 << PVR2_SUBSYS_B_ENC_RUN) )
+#define PVR2_SUBSYS_ALL ( \
+	PVR2_SUBSYS_CFG_ALL | \
+	PVR2_SUBSYS_RUN_ALL )
+
+enum pvr2_config {
+	pvr2_config_empty,
+	pvr2_config_mpeg,
+	pvr2_config_vbi,
+	pvr2_config_radio,
+};
+
+const char *pvr2_config_get_name(enum pvr2_config);
+
+struct pvr2_hdw;
+
+/* Create and return a structure for interacting with the underlying
+   hardware */
+struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
+				 const struct usb_device_id *devid);
+
+/* Poll for background activity (if any) */
+void pvr2_hdw_poll(struct pvr2_hdw *);
+
+/* Trigger a poll to take place later at a convenient time */
+void pvr2_hdw_poll_trigger(struct pvr2_hdw *);
+void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *);
+
+/* Register a callback used to trigger a future poll */
+void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *,
+				 void (*func)(void *),
+				 void *data);
+
+/* Get pointer to structure given unit number */
+struct pvr2_hdw *pvr2_hdw_find(int unit_number);
+
+/* Destroy hardware interaction structure */
+void pvr2_hdw_destroy(struct pvr2_hdw *);
+
+/* Set up the structure and attempt to put the device into a usable state.
+   This can be a time-consuming operation, which is why it is not done
+   internally as part of the create() step.  Return value is exactly the
+   same as pvr2_hdw_init_ok(). */
+int pvr2_hdw_setup(struct pvr2_hdw *);
+
+/* Initialization succeeded */
+int pvr2_hdw_init_ok(struct pvr2_hdw *);
+
+/* Return true if in the ready (normal) state */
+int pvr2_hdw_dev_ok(struct pvr2_hdw *);
+
+/* Return small integer number [1..N] for logical instance number of this
+   device.  This is useful for indexing array-valued module parameters. */
+int pvr2_hdw_get_unit_number(struct pvr2_hdw *);
+
+/* Get pointer to underlying USB device */
+struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *);
+
+/* Retrieve serial number of device */
+unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *);
+
+/* Called when hardware has been unplugged */
+void pvr2_hdw_disconnect(struct pvr2_hdw *);
+
+/* Get the number of defined controls */
+unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *);
+
+/* Retrieve a control handle given its index (0..count-1) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int);
+
+/* Retrieve a control handle given its internal ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int);
+
+/* Retrieve a control handle given its V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id);
+
+/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */
+struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *,
+					    unsigned int ctl_id);
+
+/* Commit all control changes made up to this point */
+int pvr2_hdw_commit_ctl(struct pvr2_hdw *);
+
+/* Return name for this driver instance */
+const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *);
+
+/* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */
+unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *);
+
+/* Query device and see if it thinks it is on a high-speed USB link */
+int pvr2_hdw_is_hsm(struct pvr2_hdw *);
+
+/* Turn streaming on/off */
+int pvr2_hdw_set_streaming(struct pvr2_hdw *,int);
+
+/* Find out if streaming is on */
+int pvr2_hdw_get_streaming(struct pvr2_hdw *);
+
+/* Configure the type of stream to generate */
+int pvr2_hdw_set_stream_type(struct pvr2_hdw *, enum pvr2_config);
+
+/* Get handle to video output stream */
+struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *);
+
+/* Emit a video standard struct */
+int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std,
+			       unsigned int idx);
+
+/* Enable / disable various pieces of hardware.  Items to change are
+   identified by bit positions within msk, and new state for each item is
+   identified by corresponding bit positions within val. */
+void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw,
+			     unsigned long msk,unsigned long val);
+
+/* Shortcut for pvr2_hdw_subsys_bit_chg(hdw,msk,msk) */
+void pvr2_hdw_subsys_bit_set(struct pvr2_hdw *hdw,unsigned long msk);
+
+/* Shortcut for pvr2_hdw_subsys_bit_chg(hdw,msk,0) */
+void pvr2_hdw_subsys_bit_clr(struct pvr2_hdw *hdw,unsigned long msk);
+
+/* Retrieve mask indicating which pieces of hardware are currently enabled
+   / configured. */
+unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *);
+
+/* Adjust mask of what get shut down when streaming is stopped.  This is a
+   debugging aid. */
+void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw,
+				    unsigned long msk,unsigned long val);
+
+/* Retrieve mask indicating which pieces of hardware are disabled when
+   streaming is turned off. */
+unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *);
+
+
+/* Enable / disable retrieval of CPU firmware.  This must be enabled before
+   pvr2_hdw_cpufw_get() will function.  Note that doing this may prevent
+   the device from running (and leaving this mode may imply a device
+   reset). */
+void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, int enable_flag);
+
+/* Return true if we're in a mode for retrieval CPU firmware */
+int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *);
+
+/* Retrieve a piece of the CPU's firmware at the given offset.  Return
+   value is the number of bytes retrieved or zero if we're past the end or
+   an error otherwise (e.g. if firmware retrieval is not enabled). */
+int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs,
+		       char *buf,unsigned int cnt);
+
+/* Retrieve previously stored v4l minor device number */
+int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *);
+
+/* Store the v4l minor device number */
+void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int);
+
+
+/* The following entry points are all lower level things you normally don't
+   want to worry about. */
+
+/* Attempt to recover from a USB foul-up (in practice I find that if you
+   have to do this, then it's already too late). */
+void pvr2_reset_ctl_endpoints(struct pvr2_hdw *hdw);
+
+/* Issue a command and get a response from the device.  LOTS of higher
+   level stuff is built on this. */
+int pvr2_send_request(struct pvr2_hdw *,
+		      void *write_ptr,unsigned int write_len,
+		      void *read_ptr,unsigned int read_len);
+
+/* Issue a command and get a response from the device.  This extended
+   version includes a probe flag (which if set means that device errors
+   should not be logged or treated as fatal) and a timeout in jiffies.
+   This can be used to non-lethally probe the health of endpoint 1. */
+int pvr2_send_request_ex(struct pvr2_hdw *,unsigned int timeout,int probe_fl,
+			 void *write_ptr,unsigned int write_len,
+			 void *read_ptr,unsigned int read_len);
+
+/* Slightly higher level device communication functions. */
+int pvr2_write_register(struct pvr2_hdw *, u16, u32);
+int pvr2_read_register(struct pvr2_hdw *, u16, u32 *);
+int pvr2_write_u16(struct pvr2_hdw *, u16, int);
+int pvr2_write_u8(struct pvr2_hdw *, u8, int);
+
+/* Call if for any reason we can't talk to the hardware anymore - this will
+   cause the driver to stop flailing on the device. */
+void pvr2_hdw_render_useless(struct pvr2_hdw *);
+void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *);
+
+/* Set / clear 8051's reset bit */
+void pvr2_hdw_cpureset_assert(struct pvr2_hdw *,int);
+
+/* Execute a USB-commanded device reset */
+void pvr2_hdw_device_reset(struct pvr2_hdw *);
+
+/* Execute hard reset command (after this point it's likely that the
+   encoder will have to be reconfigured).  This also clears the "useless"
+   state. */
+int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *);
+
+/* Execute simple reset command */
+int pvr2_hdw_cmd_powerup(struct pvr2_hdw *);
+
+/* Order decoder to reset */
+int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *);
+
+/* Stop / start video stream transport */
+int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl);
+
+/* Find I2C address of eeprom */
+int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *);
+
+/* Direct manipulation of GPIO bits */
+int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *);
+int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val);
+int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val);
+
+/* This data structure is specifically for the next function... */
+struct pvr2_hdw_debug_info {
+	int big_lock_held;
+	int ctl_lock_held;
+	int flag_ok;
+	int flag_disconnected;
+	int flag_init_ok;
+	int flag_streaming_enabled;
+	unsigned long subsys_flags;
+	int cmd_debug_state;
+	int cmd_debug_write_len;
+	int cmd_debug_read_len;
+	int cmd_debug_write_pend;
+	int cmd_debug_read_pend;
+	int cmd_debug_timeout;
+	int cmd_debug_rstatus;
+	int cmd_debug_wstatus;
+	unsigned char cmd_code;
+};
+
+/* Non-intrusively retrieve internal state info - this is useful for
+   diagnosing lockups.  Note that this operation is completed without any
+   kind of locking and so it is not atomic and may yield inconsistent
+   results.  This is *purely* a debugging aid. */
+void pvr2_hdw_get_debug_info(const struct pvr2_hdw *hdw,
+			     struct pvr2_hdw_debug_info *);
+
+/* Cause modules to log their state once */
+void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw);
+
+/* Cause encoder firmware to be uploaded into the device.  This is normally
+   done autonomously, but the interface is exported here because it is also
+   a debugging aid. */
+int pvr2_upload_firmware2(struct pvr2_hdw *hdw);
+
+/* List of device types that we can match */
+extern struct usb_device_id pvr2_device_table[];
+
+#endif /* __PVRUSB2_HDW_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
new file mode 100644
index 0000000..1dd4f62
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c
@@ -0,0 +1,115 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+#include "pvrusb2-audio.h"
+#include "pvrusb2-tuner.h"
+#include "pvrusb2-demod.h"
+#include "pvrusb2-video-v4l.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+#include "pvrusb2-cx2584x-v4l.h"
+#include "pvrusb2-wm8775.h"
+#endif
+
+#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
+
+#define OP_STANDARD 0
+#define OP_BCSH 1
+#define OP_VOLUME 2
+#define OP_FREQ 3
+#define OP_AUDIORATE 4
+#define OP_SIZE 5
+#define OP_LOG 6
+
+static const struct pvr2_i2c_op * const ops[] = {
+	[OP_STANDARD] = &pvr2_i2c_op_v4l2_standard,
+	[OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh,
+	[OP_VOLUME] = &pvr2_i2c_op_v4l2_volume,
+	[OP_FREQ] = &pvr2_i2c_op_v4l2_frequency,
+	[OP_SIZE] = &pvr2_i2c_op_v4l2_size,
+	[OP_LOG] = &pvr2_i2c_op_v4l2_log,
+};
+
+void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+	int id;
+	id = cp->client->driver->id;
+	cp->ctl_mask = ((1 << OP_STANDARD) |
+			(1 << OP_BCSH) |
+			(1 << OP_VOLUME) |
+			(1 << OP_FREQ) |
+			(1 << OP_SIZE) |
+			(1 << OP_LOG));
+
+	if (id == I2C_DRIVERID_MSP3400) {
+		if (pvr2_i2c_msp3400_setup(hdw,cp)) {
+			return;
+		}
+	}
+	if (id == I2C_DRIVERID_TUNER) {
+		if (pvr2_i2c_tuner_setup(hdw,cp)) {
+			return;
+		}
+	}
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+	if (id == I2C_DRIVERID_CX25840) {
+		if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) {
+			return;
+		}
+	}
+	if (id == I2C_DRIVERID_WM8775) {
+		if (pvr2_i2c_wm8775_setup(hdw,cp)) {
+			return;
+		}
+	}
+#endif
+	if (id == I2C_DRIVERID_SAA711X) {
+		if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) {
+			return;
+		}
+	}
+	if (id == I2C_DRIVERID_TDA9887) {
+		if (pvr2_i2c_demod_setup(hdw,cp)) {
+			return;
+		}
+	}
+}
+
+
+const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx)
+{
+	if (idx >= sizeof(ops)/sizeof(ops[0])) return 0;
+	return ops[idx];
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
new file mode 100644
index 0000000..9f81aff
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c
@@ -0,0 +1,232 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-i2c-cmd-v4l2.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+
+
+static void set_standard(struct pvr2_hdw *hdw)
+{
+	v4l2_std_id vs;
+	vs = hdw->std_mask_cur;
+	pvr2_trace(PVR2_TRACE_CHIPS,
+		   "i2c v4l2 set_standard(0x%llx)",(__u64)vs);
+
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs);
+}
+
+
+static int check_standard(struct pvr2_hdw *hdw)
+{
+	return hdw->std_dirty != 0;
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = {
+	.check = check_standard,
+	.update = set_standard,
+	.name = "v4l2_standard",
+};
+
+
+static void set_bcsh(struct pvr2_hdw *hdw)
+{
+	struct v4l2_control ctrl;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh"
+		   " b=%d c=%d s=%d h=%d",
+		   hdw->brightness_val,hdw->contrast_val,
+		   hdw->saturation_val,hdw->hue_val);
+	memset(&ctrl,0,sizeof(ctrl));
+	ctrl.id = V4L2_CID_BRIGHTNESS;
+	ctrl.value = hdw->brightness_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+	ctrl.id = V4L2_CID_CONTRAST;
+	ctrl.value = hdw->contrast_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+	ctrl.id = V4L2_CID_SATURATION;
+	ctrl.value = hdw->saturation_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+	ctrl.id = V4L2_CID_HUE;
+	ctrl.value = hdw->hue_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+}
+
+
+static int check_bcsh(struct pvr2_hdw *hdw)
+{
+	return (hdw->brightness_dirty ||
+		hdw->contrast_dirty ||
+		hdw->saturation_dirty ||
+		hdw->hue_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = {
+	.check = check_bcsh,
+	.update = set_bcsh,
+	.name = "v4l2_bcsh",
+};
+
+
+static void set_volume(struct pvr2_hdw *hdw)
+{
+	struct v4l2_control ctrl;
+	pvr2_trace(PVR2_TRACE_CHIPS,
+		   "i2c v4l2 set_volume"
+		   "(vol=%d bal=%d bas=%d treb=%d mute=%d)",
+		   hdw->volume_val,
+		   hdw->balance_val,
+		   hdw->bass_val,
+		   hdw->treble_val,
+		   hdw->mute_val);
+	memset(&ctrl,0,sizeof(ctrl));
+	ctrl.id = V4L2_CID_AUDIO_MUTE;
+	ctrl.value = hdw->mute_val ? 1 : 0;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+	ctrl.id = V4L2_CID_AUDIO_VOLUME;
+	ctrl.value = hdw->volume_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+	ctrl.id = V4L2_CID_AUDIO_BALANCE;
+	ctrl.value = hdw->balance_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+	ctrl.id = V4L2_CID_AUDIO_BASS;
+	ctrl.value = hdw->bass_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+	ctrl.id = V4L2_CID_AUDIO_TREBLE;
+	ctrl.value = hdw->treble_val;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl);
+}
+
+
+static int check_volume(struct pvr2_hdw *hdw)
+{
+	return (hdw->volume_dirty ||
+		hdw->balance_dirty ||
+		hdw->bass_dirty ||
+		hdw->treble_dirty ||
+		hdw->mute_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = {
+	.check = check_volume,
+	.update = set_volume,
+	.name = "v4l2_volume",
+};
+
+
+static void set_frequency(struct pvr2_hdw *hdw)
+{
+	unsigned long fv;
+	struct v4l2_frequency freq;
+	fv = hdw->freqVal;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv);
+	memset(&freq,0,sizeof(freq));
+	freq.frequency = fv / 62500;
+	freq.tuner = 0;
+	freq.type = V4L2_TUNER_ANALOG_TV;
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq);
+}
+
+
+static int check_frequency(struct pvr2_hdw *hdw)
+{
+	return hdw->freqDirty != 0;
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = {
+	.check = check_frequency,
+	.update = set_frequency,
+	.name = "v4l2_freq",
+};
+
+
+static void set_size(struct pvr2_hdw *hdw)
+{
+	struct v4l2_format fmt;
+
+	memset(&fmt,0,sizeof(fmt));
+
+	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	fmt.fmt.pix.width = hdw->res_hor_val;
+	fmt.fmt.pix.height = hdw->res_ver_val;
+
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)",
+			   fmt.fmt.pix.width,fmt.fmt.pix.height);
+
+	pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt);
+}
+
+
+static int check_size(struct pvr2_hdw *hdw)
+{
+	return (hdw->res_hor_dirty || hdw->res_ver_dirty);
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = {
+	.check = check_size,
+	.update = set_size,
+	.name = "v4l2_size",
+};
+
+
+static void do_log(struct pvr2_hdw *hdw)
+{
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()");
+	pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,0);
+
+}
+
+
+static int check_log(struct pvr2_hdw *hdw)
+{
+	return hdw->log_requested != 0;
+}
+
+
+const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = {
+	.check = check_log,
+	.update = do_log,
+	.name = "v4l2_log",
+};
+
+
+void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl)
+{
+	pvr2_i2c_client_cmd(cp,
+			    (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),0);
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
new file mode 100644
index 0000000..ecabddb
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h
@@ -0,0 +1,47 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_CMD_V4L2_H
+#define __PVRUSB2_CMD_V4L2_H
+
+#include "pvrusb2-i2c-core.h"
+
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size;
+extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log;
+
+void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int);
+
+#endif /* __PVRUSB2_CMD_V4L2_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
new file mode 100644
index 0000000..c8d0bde
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
@@ -0,0 +1,937 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-i2c-core.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+
+#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__)
+
+/*
+
+  This module attempts to implement a compliant I2C adapter for the pvrusb2
+  device.  By doing this we can then make use of existing functionality in
+  V4L (e.g. tuner.c) rather than rolling our own.
+
+*/
+
+static unsigned int i2c_scan = 0;
+module_param(i2c_scan, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time");
+
+static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */
+			  u8 i2c_addr,      /* I2C address we're talking to */
+			  u8 *data,         /* Data to write */
+			  u16 length)       /* Size of data to write */
+{
+	/* Return value - default 0 means success */
+	int ret;
+
+
+	if (!data) length = 0;
+	if (length > (sizeof(hdw->cmd_buffer) - 3)) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Killing an I2C write to %u that is too large"
+			   " (desired=%u limit=%u)",
+			   i2c_addr,
+			   length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3));
+		return -ENOTSUPP;
+	}
+
+	LOCK_TAKE(hdw->ctl_lock);
+
+	/* Clear the command buffer (likely to be paranoia) */
+	memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
+
+	/* Set up command buffer for an I2C write */
+	hdw->cmd_buffer[0] = 0x08;      /* write prefix */
+	hdw->cmd_buffer[1] = i2c_addr;  /* i2c addr of chip */
+	hdw->cmd_buffer[2] = length;    /* length of what follows */
+	if (length) memcpy(hdw->cmd_buffer + 3, data, length);
+
+	/* Do the operation */
+	ret = pvr2_send_request(hdw,
+				hdw->cmd_buffer,
+				length + 3,
+				hdw->cmd_buffer,
+				1);
+	if (!ret) {
+		if (hdw->cmd_buffer[0] != 8) {
+			ret = -EIO;
+			if (hdw->cmd_buffer[0] != 7) {
+				trace_i2c("unexpected status"
+					  " from i2_write[%d]: %d",
+					  i2c_addr,hdw->cmd_buffer[0]);
+			}
+		}
+	}
+
+	LOCK_GIVE(hdw->ctl_lock);
+
+	return ret;
+}
+
+static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */
+			 u8 i2c_addr,       /* I2C address we're talking to */
+			 u8 *data,          /* Data to write */
+			 u16 dlen,          /* Size of data to write */
+			 u8 *res,           /* Where to put data we read */
+			 u16 rlen)          /* Amount of data to read */
+{
+	/* Return value - default 0 means success */
+	int ret;
+
+
+	if (!data) dlen = 0;
+	if (dlen > (sizeof(hdw->cmd_buffer) - 4)) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Killing an I2C read to %u that has wlen too large"
+			   " (desired=%u limit=%u)",
+			   i2c_addr,
+			   dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4));
+		return -ENOTSUPP;
+	}
+	if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Killing an I2C read to %u that has rlen too large"
+			   " (desired=%u limit=%u)",
+			   i2c_addr,
+			   rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1));
+		return -ENOTSUPP;
+	}
+
+	LOCK_TAKE(hdw->ctl_lock);
+
+	/* Clear the command buffer (likely to be paranoia) */
+	memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer));
+
+	/* Set up command buffer for an I2C write followed by a read */
+	hdw->cmd_buffer[0] = 0x09;  /* read prefix */
+	hdw->cmd_buffer[1] = dlen;  /* arg length */
+	hdw->cmd_buffer[2] = rlen;  /* answer length. Device will send one
+				       more byte (status). */
+	hdw->cmd_buffer[3] = i2c_addr;  /* i2c addr of chip */
+	if (dlen) memcpy(hdw->cmd_buffer + 4, data, dlen);
+
+	/* Do the operation */
+	ret = pvr2_send_request(hdw,
+				hdw->cmd_buffer,
+				4 + dlen,
+				hdw->cmd_buffer,
+				rlen + 1);
+	if (!ret) {
+		if (hdw->cmd_buffer[0] != 8) {
+			ret = -EIO;
+			if (hdw->cmd_buffer[0] != 7) {
+				trace_i2c("unexpected status"
+					  " from i2_read[%d]: %d",
+					  i2c_addr,hdw->cmd_buffer[0]);
+			}
+		}
+	}
+
+	/* Copy back the result */
+	if (res && rlen) {
+		if (ret) {
+			/* Error, just blank out the return buffer */
+			memset(res, 0, rlen);
+		} else {
+			memcpy(res, hdw->cmd_buffer + 1, rlen);
+		}
+	}
+
+	LOCK_GIVE(hdw->ctl_lock);
+
+	return ret;
+}
+
+/* This is the common low level entry point for doing I2C operations to the
+   hardware. */
+int pvr2_i2c_basic_op(struct pvr2_hdw *hdw,
+		      u8 i2c_addr,
+		      u8 *wdata,
+		      u16 wlen,
+		      u8 *rdata,
+		      u16 rlen)
+{
+	if (!rdata) rlen = 0;
+	if (!wdata) wlen = 0;
+	if (rlen || !wlen) {
+		return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+	} else {
+		return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen);
+	}
+}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+
+/* This is a special entry point that is entered if an I2C operation is
+   attempted to a wm8775 chip on model 24xxx hardware.  Autodetect of this
+   part doesn't work, but we know it is really there.  So let's look for
+   the autodetect attempt and just return success if we see that. */
+static int i2c_hack_wm8775(struct pvr2_hdw *hdw,
+			   u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+	if (!(rlen || wlen)) {
+		// This is a probe attempt.  Just let it succeed.
+		return 0;
+	}
+	return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+}
+
+/* This is a special entry point that is entered if an I2C operation is
+   attempted to a cx25840 chip on model 24xxx hardware.  This chip can
+   sometimes wedge itself.  Worse still, when this happens msp3400 can
+   falsely detect this part and then the system gets hosed up after msp3400
+   gets confused and dies.  What we want to do here is try to keep msp3400
+   away and also try to notice if the chip is wedged and send a warning to
+   the system log. */
+static int i2c_hack_cx25840(struct pvr2_hdw *hdw,
+			    u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen)
+{
+	int ret;
+	unsigned int subaddr;
+	u8 wbuf[2];
+	int state = hdw->i2c_cx25840_hack_state;
+
+	if (!(rlen || wlen)) {
+		// Probe attempt - always just succeed and don't bother the
+		// hardware (this helps to make the state machine further
+		// down somewhat easier).
+		return 0;
+	}
+
+	if (state == 3) {
+		return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen);
+	}
+
+	/* We're looking for the exact pattern where the revision register
+	   is being read.  The cx25840 module will always look at the
+	   revision register first.  Any other pattern of access therefore
+	   has to be a probe attempt from somebody else so we'll reject it.
+	   Normally we could just let each client just probe the part
+	   anyway, but when the cx25840 is wedged, msp3400 will get a false
+	   positive and that just screws things up... */
+
+	if (wlen == 0) {
+		switch (state) {
+		case 1: subaddr = 0x0100; break;
+		case 2: subaddr = 0x0101; break;
+		default: goto fail;
+		}
+	} else if (wlen == 2) {
+		subaddr = (wdata[0] << 8) | wdata[1];
+		switch (subaddr) {
+		case 0x0100: state = 1; break;
+		case 0x0101: state = 2; break;
+		default: goto fail;
+		}
+	} else {
+		goto fail;
+	}
+	if (!rlen) goto success;
+	state = 0;
+	if (rlen != 1) goto fail;
+
+	/* If we get to here then we have a legitimate read for one of the
+	   two revision bytes, so pass it through. */
+	wbuf[0] = subaddr >> 8;
+	wbuf[1] = subaddr;
+	ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen);
+
+	if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "WARNING: Detected a wedged cx25840 chip;"
+			   " the device will not work.");
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "WARNING: Try power cycling the pvrusb2 device.");
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "WARNING: Disabling further access to the device"
+			   " to prevent other foul-ups.");
+		// This blocks all further communication with the part.
+		hdw->i2c_func[0x44] = 0;
+		pvr2_hdw_render_useless(hdw);
+		goto fail;
+	}
+
+	/* Success! */
+	pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK.");
+	state = 3;
+
+ success:
+	hdw->i2c_cx25840_hack_state = state;
+	return 0;
+
+ fail:
+	hdw->i2c_cx25840_hack_state = state;
+	return -EIO;
+}
+
+#endif /* CONFIG_VIDEO_PVRUSB2_24XXX */
+
+/* This is a very, very limited I2C adapter implementation.  We can only
+   support what we actually know will work on the device... */
+static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap,
+			 struct i2c_msg msgs[],
+			 int num)
+{
+	int ret = -ENOTSUPP;
+	pvr2_i2c_func funcp = 0;
+	struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data);
+
+	if (!num) {
+		ret = -EINVAL;
+		goto done;
+	}
+	if ((msgs[0].flags & I2C_M_NOSTART)) {
+		trace_i2c("i2c refusing I2C_M_NOSTART");
+		goto done;
+	}
+	if (msgs[0].addr < PVR2_I2C_FUNC_CNT) {
+		funcp = hdw->i2c_func[msgs[0].addr];
+	}
+	if (!funcp) {
+		ret = -EIO;
+		goto done;
+	}
+
+	if (num == 1) {
+		if (msgs[0].flags & I2C_M_RD) {
+			/* Simple read */
+			u16 tcnt,bcnt,offs;
+			if (!msgs[0].len) {
+				/* Length == 0 read.  This is a probe. */
+				if (funcp(hdw,msgs[0].addr,0,0,0,0)) {
+					ret = -EIO;
+					goto done;
+				}
+				ret = 1;
+				goto done;
+			}
+			/* If the read is short enough we'll do the whole
+			   thing atomically.  Otherwise we have no choice
+			   but to break apart the reads. */
+			tcnt = msgs[0].len;
+			offs = 0;
+			while (tcnt) {
+				bcnt = tcnt;
+				if (bcnt > sizeof(hdw->cmd_buffer)-1) {
+					bcnt = sizeof(hdw->cmd_buffer)-1;
+				}
+				if (funcp(hdw,msgs[0].addr,0,0,
+					  msgs[0].buf+offs,bcnt)) {
+					ret = -EIO;
+					goto done;
+				}
+				offs += bcnt;
+				tcnt -= bcnt;
+			}
+			ret = 1;
+			goto done;
+		} else {
+			/* Simple write */
+			ret = 1;
+			if (funcp(hdw,msgs[0].addr,
+				  msgs[0].buf,msgs[0].len,0,0)) {
+				ret = -EIO;
+			}
+			goto done;
+		}
+	} else if (num == 2) {
+		if (msgs[0].addr != msgs[1].addr) {
+			trace_i2c("i2c refusing 2 phase transfer with"
+				  " conflicting target addresses");
+			ret = -ENOTSUPP;
+			goto done;
+		}
+		if ((!((msgs[0].flags & I2C_M_RD))) &&
+		    (msgs[1].flags & I2C_M_RD)) {
+			u16 tcnt,bcnt,wcnt,offs;
+			/* Write followed by atomic read.  If the read
+			   portion is short enough we'll do the whole thing
+			   atomically.  Otherwise we have no choice but to
+			   break apart the reads. */
+			tcnt = msgs[1].len;
+			wcnt = msgs[0].len;
+			offs = 0;
+			while (tcnt || wcnt) {
+				bcnt = tcnt;
+				if (bcnt > sizeof(hdw->cmd_buffer)-1) {
+					bcnt = sizeof(hdw->cmd_buffer)-1;
+				}
+				if (funcp(hdw,msgs[0].addr,
+					  msgs[0].buf,wcnt,
+					  msgs[1].buf+offs,bcnt)) {
+					ret = -EIO;
+					goto done;
+				}
+				offs += bcnt;
+				tcnt -= bcnt;
+				wcnt = 0;
+			}
+			ret = 2;
+			goto done;
+		} else {
+			trace_i2c("i2c refusing complex transfer"
+				  " read0=%d read1=%d",
+				  (msgs[0].flags & I2C_M_RD),
+				  (msgs[1].flags & I2C_M_RD));
+		}
+	} else {
+		trace_i2c("i2c refusing %d phase transfer",num);
+	}
+
+ done:
+	if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) {
+		unsigned int idx,offs,cnt;
+		for (idx = 0; idx < num; idx++) {
+			cnt = msgs[idx].len;
+			printk(KERN_INFO
+			       "pvrusb2 i2c xfer %u/%u:"
+			       " addr=0x%x len=%d %s%s",
+			       idx+1,num,
+			       msgs[idx].addr,
+			       cnt,
+			       (msgs[idx].flags & I2C_M_RD ?
+				"read" : "write"),
+			       (msgs[idx].flags & I2C_M_NOSTART ?
+				" nostart" : ""));
+			if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) {
+				if (cnt > 8) cnt = 8;
+				printk(" [");
+				for (offs = 0; offs < (cnt>8?8:cnt); offs++) {
+					if (offs) printk(" ");
+					printk("%02x",msgs[idx].buf[offs]);
+				}
+				if (offs < cnt) printk(" ...");
+				printk("]");
+			}
+			if (idx+1 == num) {
+				printk(" result=%d",ret);
+			}
+			printk("\n");
+		}
+		if (!num) {
+			printk(KERN_INFO
+			       "pvrusb2 i2c xfer null transfer result=%d\n",
+			       ret);
+		}
+	}
+	return ret;
+}
+
+static int pvr2_i2c_control(struct i2c_adapter *adapter,
+			    unsigned int cmd, unsigned long arg)
+{
+	return 0;
+}
+
+static u32 pvr2_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA;
+}
+
+static int pvr2_i2c_core_singleton(struct i2c_client *cp,
+				   unsigned int cmd,void *arg)
+{
+	int stat;
+	if (!cp) return -EINVAL;
+	if (!(cp->driver)) return -EINVAL;
+	if (!(cp->driver->command)) return -EINVAL;
+	if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN;
+	stat = cp->driver->command(cp,cmd,arg);
+	module_put(cp->driver->driver.owner);
+	return stat;
+}
+
+int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg)
+{
+	int stat;
+	if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
+		char buf[100];
+		unsigned int cnt;
+		cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
+					       buf,sizeof(buf));
+		pvr2_trace(PVR2_TRACE_I2C_CMD,
+			   "i2c COMMAND (code=%u 0x%x) to %.*s",
+			   cmd,cmd,cnt,buf);
+	}
+	stat = pvr2_i2c_core_singleton(cp->client,cmd,arg);
+	if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) {
+		char buf[100];
+		unsigned int cnt;
+		cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG,
+					       buf,sizeof(buf));
+		pvr2_trace(PVR2_TRACE_I2C_CMD,
+			   "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat);
+	}
+	return stat;
+}
+
+int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg)
+{
+	struct list_head *item,*nc;
+	struct pvr2_i2c_client *cp;
+	int stat = -EINVAL;
+
+	if (!hdw) return stat;
+
+	mutex_lock(&hdw->i2c_list_lock);
+	list_for_each_safe(item,nc,&hdw->i2c_clients) {
+		cp = list_entry(item,struct pvr2_i2c_client,list);
+		if (!cp->recv_enable) continue;
+		mutex_unlock(&hdw->i2c_list_lock);
+		stat = pvr2_i2c_client_cmd(cp,cmd,arg);
+		mutex_lock(&hdw->i2c_list_lock);
+	}
+	mutex_unlock(&hdw->i2c_list_lock);
+	return stat;
+}
+
+
+static int handler_check(struct pvr2_i2c_client *cp)
+{
+	struct pvr2_i2c_handler *hp = cp->handler;
+	if (!hp) return 0;
+	if (!hp->func_table->check) return 0;
+	return hp->func_table->check(hp->func_data) != 0;
+}
+
+#define BUFSIZE 500
+
+void pvr2_i2c_core_sync(struct pvr2_hdw *hdw)
+{
+	unsigned long msk;
+	unsigned int idx;
+	struct list_head *item,*nc;
+	struct pvr2_i2c_client *cp;
+
+	if (!hdw->i2c_linked) return;
+	if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) {
+		return;
+	}
+	mutex_lock(&hdw->i2c_list_lock); do {
+		pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN");
+		if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) {
+			/* One or more I2C clients have attached since we
+			   last synced.  So scan the list and identify the
+			   new clients. */
+			char *buf;
+			unsigned int cnt;
+			unsigned long amask = 0;
+			buf = kmalloc(BUFSIZE,GFP_KERNEL);
+			pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT");
+			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT;
+			list_for_each(item,&hdw->i2c_clients) {
+				cp = list_entry(item,struct pvr2_i2c_client,
+						list);
+				if (!cp->detected_flag) {
+					cp->ctl_mask = 0;
+					pvr2_i2c_probe(hdw,cp);
+					cp->detected_flag = !0;
+					msk = cp->ctl_mask;
+					cnt = 0;
+					if (buf) {
+						cnt = pvr2_i2c_client_describe(
+							cp,
+							PVR2_I2C_DETAIL_ALL,
+							buf,BUFSIZE);
+					}
+					trace_i2c("Probed: %.*s",cnt,buf);
+					if (handler_check(cp)) {
+						hdw->i2c_pend_types |=
+							PVR2_I2C_PEND_CLIENT;
+					}
+					cp->pend_mask = msk;
+					hdw->i2c_pend_mask |= msk;
+					hdw->i2c_pend_types |=
+						PVR2_I2C_PEND_REFRESH;
+				}
+				amask |= cp->ctl_mask;
+			}
+			hdw->i2c_active_mask = amask;
+			if (buf) kfree(buf);
+		}
+		if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) {
+			/* Need to do one or more global updates.  Arrange
+			   for this to happen. */
+			unsigned long m2;
+			pvr2_trace(PVR2_TRACE_I2C_CORE,
+				   "i2c: PEND_STALE (0x%lx)",
+				   hdw->i2c_stale_mask);
+			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE;
+			list_for_each(item,&hdw->i2c_clients) {
+				cp = list_entry(item,struct pvr2_i2c_client,
+						list);
+				m2 = hdw->i2c_stale_mask;
+				m2 &= cp->ctl_mask;
+				m2 &= ~cp->pend_mask;
+				if (m2) {
+					pvr2_trace(PVR2_TRACE_I2C_CORE,
+						   "i2c: cp=%p setting 0x%lx",
+						   cp,m2);
+					cp->pend_mask |= m2;
+				}
+			}
+			hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
+			hdw->i2c_stale_mask = 0;
+			hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH;
+		}
+		if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) {
+			/* One or more client handlers are asking for an
+			   update.  Run through the list of known clients
+			   and update each one. */
+			pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT");
+			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT;
+			list_for_each_safe(item,nc,&hdw->i2c_clients) {
+				cp = list_entry(item,struct pvr2_i2c_client,
+						list);
+				if (!cp->handler) continue;
+				if (!cp->handler->func_table->update) continue;
+				pvr2_trace(PVR2_TRACE_I2C_CORE,
+					   "i2c: cp=%p update",cp);
+				mutex_unlock(&hdw->i2c_list_lock);
+				cp->handler->func_table->update(
+					cp->handler->func_data);
+				mutex_lock(&hdw->i2c_list_lock);
+				/* If client's update function set some
+				   additional pending bits, account for that
+				   here. */
+				if (cp->pend_mask & ~hdw->i2c_pend_mask) {
+					hdw->i2c_pend_mask |= cp->pend_mask;
+					hdw->i2c_pend_types |=
+						PVR2_I2C_PEND_REFRESH;
+				}
+			}
+		}
+		if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) {
+			const struct pvr2_i2c_op *opf;
+			unsigned long pm;
+			/* Some actual updates are pending.  Walk through
+			   each update type and perform it. */
+			pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH"
+				   " (0x%lx)",hdw->i2c_pend_mask);
+			hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH;
+			pm = hdw->i2c_pend_mask;
+			hdw->i2c_pend_mask = 0;
+			for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
+				if (!(pm & msk)) continue;
+				pm &= ~msk;
+				list_for_each(item,&hdw->i2c_clients) {
+					cp = list_entry(item,
+							struct pvr2_i2c_client,
+							list);
+					if (cp->pend_mask & msk) {
+						cp->pend_mask &= ~msk;
+						cp->recv_enable = !0;
+					} else {
+						cp->recv_enable = 0;
+					}
+				}
+				opf = pvr2_i2c_get_op(idx);
+				if (!opf) continue;
+				mutex_unlock(&hdw->i2c_list_lock);
+				opf->update(hdw);
+				mutex_lock(&hdw->i2c_list_lock);
+			}
+		}
+		pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END");
+	} while (0); mutex_unlock(&hdw->i2c_list_lock);
+}
+
+int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw)
+{
+	unsigned long msk,sm,pm;
+	unsigned int idx;
+	const struct pvr2_i2c_op *opf;
+	struct list_head *item;
+	struct pvr2_i2c_client *cp;
+	unsigned int pt = 0;
+
+	pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN");
+
+	pm = hdw->i2c_active_mask;
+	sm = 0;
+	for (idx = 0, msk = 1; pm; idx++, msk <<= 1) {
+		if (!(msk & pm)) continue;
+		pm &= ~msk;
+		opf = pvr2_i2c_get_op(idx);
+		if (!opf) continue;
+		if (opf->check(hdw)) {
+			sm |= msk;
+		}
+	}
+	if (sm) pt |= PVR2_I2C_PEND_STALE;
+
+	list_for_each(item,&hdw->i2c_clients) {
+		cp = list_entry(item,struct pvr2_i2c_client,list);
+		if (!handler_check(cp)) continue;
+		pt |= PVR2_I2C_PEND_CLIENT;
+	}
+
+	if (pt) {
+		mutex_lock(&hdw->i2c_list_lock); do {
+			hdw->i2c_pend_types |= pt;
+			hdw->i2c_stale_mask |= sm;
+			hdw->i2c_pend_mask |= hdw->i2c_stale_mask;
+		} while (0); mutex_unlock(&hdw->i2c_list_lock);
+	}
+
+	pvr2_trace(PVR2_TRACE_I2C_CORE,
+		   "i2c: types=0x%x stale=0x%lx pend=0x%lx",
+		   hdw->i2c_pend_types,
+		   hdw->i2c_stale_mask,
+		   hdw->i2c_pend_mask);
+	pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END");
+
+	return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0;
+}
+
+unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp,
+				      unsigned int detail,
+				      char *buf,unsigned int maxlen)
+{
+	unsigned int ccnt,bcnt;
+	int spcfl = 0;
+	const struct pvr2_i2c_op *opf;
+
+	ccnt = 0;
+	if (detail & PVR2_I2C_DETAIL_DEBUG) {
+		bcnt = scnprintf(buf,maxlen,
+				 "ctxt=%p ctl_mask=0x%lx",
+				 cp,cp->ctl_mask);
+		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+		spcfl = !0;
+	}
+	bcnt = scnprintf(buf,maxlen,
+			 "%s%s @ 0x%x",
+			 (spcfl ? " " : ""),
+			 cp->client->name,
+			 cp->client->addr);
+	ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+	if ((detail & PVR2_I2C_DETAIL_HANDLER) &&
+	    cp->handler && cp->handler->func_table->describe) {
+		bcnt = scnprintf(buf,maxlen," (");
+		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+		bcnt = cp->handler->func_table->describe(
+			cp->handler->func_data,buf,maxlen);
+		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+		bcnt = scnprintf(buf,maxlen,")");
+		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+	}
+	if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) {
+		unsigned int idx;
+		unsigned long msk,sm;
+		int spcfl;
+		bcnt = scnprintf(buf,maxlen," [");
+		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+		sm = 0;
+		spcfl = 0;
+		for (idx = 0, msk = 1; msk; idx++, msk <<= 1) {
+			if (!(cp->ctl_mask & msk)) continue;
+			opf = pvr2_i2c_get_op(idx);
+			if (opf) {
+				bcnt = scnprintf(buf,maxlen,"%s%s",
+						 spcfl ? " " : "",
+						 opf->name);
+				ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+				spcfl = !0;
+			} else {
+				sm |= msk;
+			}
+		}
+		if (sm) {
+			bcnt = scnprintf(buf,maxlen,"%s%lx",
+					 idx != 0 ? " " : "",sm);
+			ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+		}
+		bcnt = scnprintf(buf,maxlen,"]");
+		ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+	}
+	return ccnt;
+}
+
+unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw,
+			     char *buf,unsigned int maxlen)
+{
+	unsigned int ccnt,bcnt;
+	struct list_head *item;
+	struct pvr2_i2c_client *cp;
+	ccnt = 0;
+	mutex_lock(&hdw->i2c_list_lock); do {
+		list_for_each(item,&hdw->i2c_clients) {
+			cp = list_entry(item,struct pvr2_i2c_client,list);
+			bcnt = pvr2_i2c_client_describe(
+				cp,
+				(PVR2_I2C_DETAIL_HANDLER|
+				 PVR2_I2C_DETAIL_CTLMASK),
+				buf,maxlen);
+			ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+			bcnt = scnprintf(buf,maxlen,"\n");
+			ccnt += bcnt; buf += bcnt; maxlen -= bcnt;
+		}
+	} while (0); mutex_unlock(&hdw->i2c_list_lock);
+	return ccnt;
+}
+
+static int pvr2_i2c_attach_inform(struct i2c_client *client)
+{
+	struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
+	struct pvr2_i2c_client *cp;
+	int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL);
+	cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+	trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]",
+		  client->name,
+		  client->addr,cp);
+	if (!cp) return -ENOMEM;
+	memset(cp,0,sizeof(*cp));
+	INIT_LIST_HEAD(&cp->list);
+	cp->client = client;
+	mutex_lock(&hdw->i2c_list_lock); do {
+		list_add_tail(&cp->list,&hdw->i2c_clients);
+		hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT;
+	} while (0); mutex_unlock(&hdw->i2c_list_lock);
+	if (fl) pvr2_hdw_poll_trigger_unlocked(hdw);
+	return 0;
+}
+
+static int pvr2_i2c_detach_inform(struct i2c_client *client)
+{
+	struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data);
+	struct pvr2_i2c_client *cp;
+	struct list_head *item,*nc;
+	unsigned long amask = 0;
+	int foundfl = 0;
+	mutex_lock(&hdw->i2c_list_lock); do {
+		list_for_each_safe(item,nc,&hdw->i2c_clients) {
+			cp = list_entry(item,struct pvr2_i2c_client,list);
+			if (cp->client == client) {
+				trace_i2c("pvr2_i2c_detach"
+					  " [client=%s @ 0x%x ctxt=%p]",
+					  client->name,
+					  client->addr,cp);
+				if (cp->handler &&
+				    cp->handler->func_table->detach) {
+					cp->handler->func_table->detach(
+						cp->handler->func_data);
+				}
+				list_del(&cp->list);
+				kfree(cp);
+				foundfl = !0;
+				continue;
+			}
+			amask |= cp->ctl_mask;
+		}
+		hdw->i2c_active_mask = amask;
+	} while (0); mutex_unlock(&hdw->i2c_list_lock);
+	if (!foundfl) {
+		trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]",
+			  client->name,
+			  client->addr);
+	}
+	return 0;
+}
+
+static struct i2c_algorithm pvr2_i2c_algo_template = {
+	.master_xfer   = pvr2_i2c_xfer,
+	.algo_control  = pvr2_i2c_control,
+	.functionality = pvr2_i2c_functionality,
+};
+
+static struct i2c_adapter pvr2_i2c_adap_template = {
+	.owner         = THIS_MODULE,
+	.class	   = I2C_CLASS_TV_ANALOG,
+	.id            = I2C_HW_B_BT848,
+	.client_register = pvr2_i2c_attach_inform,
+	.client_unregister = pvr2_i2c_detach_inform,
+};
+
+static void do_i2c_scan(struct pvr2_hdw *hdw)
+{
+	struct i2c_msg msg[1];
+	int i,rc;
+	msg[0].addr = 0;
+	msg[0].flags = I2C_M_RD;
+	msg[0].len = 0;
+	msg[0].buf = 0;
+	printk("%s: i2c scan beginning\n",hdw->name);
+	for (i = 0; i < 128; i++) {
+		msg[0].addr = i;
+		rc = i2c_transfer(&hdw->i2c_adap,msg,
+				  sizeof(msg)/sizeof(msg[0]));
+		if (rc != 1) continue;
+		printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i);
+	}
+	printk("%s: i2c scan done.\n",hdw->name);
+}
+
+void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
+{
+	unsigned int idx;
+
+	// The default action for all possible I2C addresses is just to do
+	// the transfer normally.
+	for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) {
+		hdw->i2c_func[idx] = pvr2_i2c_basic_op;
+	}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_24XXX
+	// If however we're dealing with new hardware, insert some hacks in
+	// the I2C transfer stack to let things work better.
+	if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) {
+		hdw->i2c_func[0x1b] = i2c_hack_wm8775;
+		hdw->i2c_func[0x44] = i2c_hack_cx25840;
+	}
+#endif
+
+	// Configure the adapter and set up everything else related to it.
+	memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
+	memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo));
+	strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
+	hdw->i2c_adap.algo = &hdw->i2c_algo;
+	hdw->i2c_adap.algo_data = hdw;
+	hdw->i2c_pend_mask = 0;
+	hdw->i2c_stale_mask = 0;
+	hdw->i2c_active_mask = 0;
+	INIT_LIST_HEAD(&hdw->i2c_clients);
+	mutex_init(&hdw->i2c_list_lock);
+	hdw->i2c_linked = !0;
+	i2c_add_adapter(&hdw->i2c_adap);
+	if (i2c_scan) do_i2c_scan(hdw);
+}
+
+void pvr2_i2c_core_done(struct pvr2_hdw *hdw)
+{
+	if (hdw->i2c_linked) {
+		i2c_del_adapter(&hdw->i2c_adap);
+		hdw->i2c_linked = 0;
+	}
+}
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
new file mode 100644
index 0000000..e8af5b0e
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h
@@ -0,0 +1,96 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_I2C_CORE_H
+#define __PVRUSB2_I2C_CORE_H
+
+#include <linux/list.h>
+#include <linux/i2c.h>
+
+struct pvr2_hdw;
+struct pvr2_i2c_client;
+struct pvr2_i2c_handler;
+struct pvr2_i2c_handler_functions;
+struct pvr2_i2c_op;
+struct pvr2_i2c_op_functions;
+
+struct pvr2_i2c_client {
+	struct i2c_client *client;
+	struct pvr2_i2c_handler *handler;
+	struct list_head list;
+	int detected_flag;
+	int recv_enable;
+	unsigned long pend_mask;
+	unsigned long ctl_mask;
+};
+
+struct pvr2_i2c_handler {
+	void *func_data;
+	const struct pvr2_i2c_handler_functions *func_table;
+};
+
+struct pvr2_i2c_handler_functions {
+	void (*detach)(void *);
+	int (*check)(void *);
+	void (*update)(void *);
+	unsigned int (*describe)(void *,char *,unsigned int);
+};
+
+struct pvr2_i2c_op {
+	int (*check)(struct pvr2_hdw *);
+	void (*update)(struct pvr2_hdw *);
+	const char *name;
+};
+
+void pvr2_i2c_core_init(struct pvr2_hdw *);
+void pvr2_i2c_core_done(struct pvr2_hdw *);
+
+int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg);
+int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg);
+
+int pvr2_i2c_core_check_stale(struct pvr2_hdw *);
+void pvr2_i2c_core_sync(struct pvr2_hdw *);
+unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen);
+#define PVR2_I2C_DETAIL_DEBUG   0x0001
+#define PVR2_I2C_DETAIL_HANDLER 0x0002
+#define PVR2_I2C_DETAIL_CTLMASK 0x0004
+#define PVR2_I2C_DETAIL_ALL (\
+	PVR2_I2C_DETAIL_DEBUG |\
+	PVR2_I2C_DETAIL_HANDLER |\
+	PVR2_I2C_DETAIL_CTLMASK)
+unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *,
+				      unsigned int detail_mask,
+				      char *buf,unsigned int maxlen);
+
+void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *);
+const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx);
+
+#endif /* __PVRUSB2_I2C_CORE_H */
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c
new file mode 100644
index 0000000..a984c91
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.c
@@ -0,0 +1,695 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-io.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+
+#define BUFFER_SIG 0x47653271
+
+// #define SANITY_CHECK_BUFFERS
+
+
+#ifdef SANITY_CHECK_BUFFERS
+#define BUFFER_CHECK(bp) do { \
+	if ((bp)->signature != BUFFER_SIG) { \
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS, \
+		"Buffer %p is bad at %s:%d", \
+		(bp),__FILE__,__LINE__); \
+		pvr2_buffer_describe(bp,"BadSig"); \
+		BUG(); \
+	} \
+} while (0)
+#else
+#define BUFFER_CHECK(bp) do {} while(0)
+#endif
+
+struct pvr2_stream {
+	/* Buffers queued for reading */
+	struct list_head queued_list;
+	unsigned int q_count;
+	unsigned int q_bcount;
+	/* Buffers with retrieved data */
+	struct list_head ready_list;
+	unsigned int r_count;
+	unsigned int r_bcount;
+	/* Buffers available for use */
+	struct list_head idle_list;
+	unsigned int i_count;
+	unsigned int i_bcount;
+	/* Pointers to all buffers */
+	struct pvr2_buffer **buffers;
+	/* Array size of buffers */
+	unsigned int buffer_slot_count;
+	/* Total buffers actually in circulation */
+	unsigned int buffer_total_count;
+	/* Designed number of buffers to be in circulation */
+	unsigned int buffer_target_count;
+	/* Executed when ready list become non-empty */
+	pvr2_stream_callback callback_func;
+	void *callback_data;
+	/* Context for transfer endpoint */
+	struct usb_device *dev;
+	int endpoint;
+	/* Overhead for mutex enforcement */
+	spinlock_t list_lock;
+	struct mutex mutex;
+	/* Tracking state for tolerating errors */
+	unsigned int fail_count;
+	unsigned int fail_tolerance;
+};
+
+struct pvr2_buffer {
+	int id;
+	int signature;
+	enum pvr2_buffer_state state;
+	void *ptr;               /* Pointer to storage area */
+	unsigned int max_count;  /* Size of storage area */
+	unsigned int used_count; /* Amount of valid data in storage area */
+	int status;              /* Transfer result status */
+	struct pvr2_stream *stream;
+	struct list_head list_overhead;
+	struct urb *purb;
+};
+
+const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
+{
+	switch (st) {
+	case pvr2_buffer_state_none: return "none";
+	case pvr2_buffer_state_idle: return "idle";
+	case pvr2_buffer_state_queued: return "queued";
+	case pvr2_buffer_state_ready: return "ready";
+	}
+	return "unknown";
+}
+
+void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
+{
+	pvr2_trace(PVR2_TRACE_INFO,
+		   "buffer%s%s %p state=%s id=%d status=%d"
+		   " stream=%p purb=%p sig=0x%x",
+		   (msg ? " " : ""),
+		   (msg ? msg : ""),
+		   bp,
+		   (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
+		   (bp ? bp->id : 0),
+		   (bp ? bp->status : 0),
+		   (bp ? bp->stream : 0),
+		   (bp ? bp->purb : 0),
+		   (bp ? bp->signature : 0));
+}
+
+static void pvr2_buffer_remove(struct pvr2_buffer *bp)
+{
+	unsigned int *cnt;
+	unsigned int *bcnt;
+	unsigned int ccnt;
+	struct pvr2_stream *sp = bp->stream;
+	switch (bp->state) {
+	case pvr2_buffer_state_idle:
+		cnt = &sp->i_count;
+		bcnt = &sp->i_bcount;
+		ccnt = bp->max_count;
+		break;
+	case pvr2_buffer_state_queued:
+		cnt = &sp->q_count;
+		bcnt = &sp->q_bcount;
+		ccnt = bp->max_count;
+		break;
+	case pvr2_buffer_state_ready:
+		cnt = &sp->r_count;
+		bcnt = &sp->r_bcount;
+		ccnt = bp->used_count;
+		break;
+	default:
+		return;
+	}
+	list_del_init(&bp->list_overhead);
+	(*cnt)--;
+	(*bcnt) -= ccnt;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/"
+		   " bufferPool     %8s dec cap=%07d cnt=%02d",
+		   pvr2_buffer_state_decode(bp->state),*bcnt,*cnt);
+	bp->state = pvr2_buffer_state_none;
+}
+
+static void pvr2_buffer_set_none(struct pvr2_buffer *bp)
+{
+	unsigned long irq_flags;
+	struct pvr2_stream *sp;
+	BUFFER_CHECK(bp);
+	sp = bp->stream;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+		   bp,
+		   pvr2_buffer_state_decode(bp->state),
+		   pvr2_buffer_state_decode(pvr2_buffer_state_none));
+	spin_lock_irqsave(&sp->list_lock,irq_flags);
+	pvr2_buffer_remove(bp);
+	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static int pvr2_buffer_set_ready(struct pvr2_buffer *bp)
+{
+	int fl;
+	unsigned long irq_flags;
+	struct pvr2_stream *sp;
+	BUFFER_CHECK(bp);
+	sp = bp->stream;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+		   bp,
+		   pvr2_buffer_state_decode(bp->state),
+		   pvr2_buffer_state_decode(pvr2_buffer_state_ready));
+	spin_lock_irqsave(&sp->list_lock,irq_flags);
+	fl = (sp->r_count == 0);
+	pvr2_buffer_remove(bp);
+	list_add_tail(&bp->list_overhead,&sp->ready_list);
+	bp->state = pvr2_buffer_state_ready;
+	(sp->r_count)++;
+	sp->r_bcount += bp->used_count;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/"
+		   " bufferPool     %8s inc cap=%07d cnt=%02d",
+		   pvr2_buffer_state_decode(bp->state),
+		   sp->r_bcount,sp->r_count);
+	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+	return fl;
+}
+
+static void pvr2_buffer_set_idle(struct pvr2_buffer *bp)
+{
+	unsigned long irq_flags;
+	struct pvr2_stream *sp;
+	BUFFER_CHECK(bp);
+	sp = bp->stream;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+		   bp,
+		   pvr2_buffer_state_decode(bp->state),
+		   pvr2_buffer_state_decode(pvr2_buffer_state_idle));
+	spin_lock_irqsave(&sp->list_lock,irq_flags);
+	pvr2_buffer_remove(bp);
+	list_add_tail(&bp->list_overhead,&sp->idle_list);
+	bp->state = pvr2_buffer_state_idle;
+	(sp->i_count)++;
+	sp->i_bcount += bp->max_count;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/"
+		   " bufferPool     %8s inc cap=%07d cnt=%02d",
+		   pvr2_buffer_state_decode(bp->state),
+		   sp->i_bcount,sp->i_count);
+	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static void pvr2_buffer_set_queued(struct pvr2_buffer *bp)
+{
+	unsigned long irq_flags;
+	struct pvr2_stream *sp;
+	BUFFER_CHECK(bp);
+	sp = bp->stream;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/ bufferState    %p %6s --> %6s",
+		   bp,
+		   pvr2_buffer_state_decode(bp->state),
+		   pvr2_buffer_state_decode(pvr2_buffer_state_queued));
+	spin_lock_irqsave(&sp->list_lock,irq_flags);
+	pvr2_buffer_remove(bp);
+	list_add_tail(&bp->list_overhead,&sp->queued_list);
+	bp->state = pvr2_buffer_state_queued;
+	(sp->q_count)++;
+	sp->q_bcount += bp->max_count;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/"
+		   " bufferPool     %8s inc cap=%07d cnt=%02d",
+		   pvr2_buffer_state_decode(bp->state),
+		   sp->q_bcount,sp->q_count);
+	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+}
+
+static void pvr2_buffer_wipe(struct pvr2_buffer *bp)
+{
+	if (bp->state == pvr2_buffer_state_queued) {
+		usb_kill_urb(bp->purb);
+	}
+}
+
+static int pvr2_buffer_init(struct pvr2_buffer *bp,
+			    struct pvr2_stream *sp,
+			    unsigned int id)
+{
+	memset(bp,0,sizeof(*bp));
+	bp->signature = BUFFER_SIG;
+	bp->id = id;
+	pvr2_trace(PVR2_TRACE_BUF_POOL,
+		   "/*---TRACE_FLOW---*/ bufferInit     %p stream=%p",bp,sp);
+	bp->stream = sp;
+	bp->state = pvr2_buffer_state_none;
+	INIT_LIST_HEAD(&bp->list_overhead);
+	bp->purb = usb_alloc_urb(0,GFP_KERNEL);
+	if (! bp->purb) return -ENOMEM;
+#ifdef SANITY_CHECK_BUFFERS
+	pvr2_buffer_describe(bp,"create");
+#endif
+	return 0;
+}
+
+static void pvr2_buffer_done(struct pvr2_buffer *bp)
+{
+#ifdef SANITY_CHECK_BUFFERS
+	pvr2_buffer_describe(bp,"delete");
+#endif
+	pvr2_buffer_wipe(bp);
+	pvr2_buffer_set_none(bp);
+	bp->signature = 0;
+	bp->stream = 0;
+	if (bp->purb) usb_free_urb(bp->purb);
+	pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
+		   " bufferDone     %p",bp);
+}
+
+static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
+{
+	int ret;
+	unsigned int scnt;
+
+	/* Allocate buffers pointer array in multiples of 32 entries */
+	if (cnt == sp->buffer_total_count) return 0;
+
+	pvr2_trace(PVR2_TRACE_BUF_POOL,
+		   "/*---TRACE_FLOW---*/ poolResize    "
+		   " stream=%p cur=%d adj=%+d",
+		   sp,
+		   sp->buffer_total_count,
+		   cnt-sp->buffer_total_count);
+
+	scnt = cnt & ~0x1f;
+	if (cnt > scnt) scnt += 0x20;
+
+	if (cnt > sp->buffer_total_count) {
+		if (scnt > sp->buffer_slot_count) {
+			struct pvr2_buffer **nb;
+			nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
+			if (!nb) return -ENOMEM;
+			if (sp->buffer_slot_count) {
+				memcpy(nb,sp->buffers,
+				       sp->buffer_slot_count * sizeof(*nb));
+				kfree(sp->buffers);
+			}
+			sp->buffers = nb;
+			sp->buffer_slot_count = scnt;
+		}
+		while (sp->buffer_total_count < cnt) {
+			struct pvr2_buffer *bp;
+			bp = kmalloc(sizeof(*bp),GFP_KERNEL);
+			if (!bp) return -ENOMEM;
+			ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count);
+			if (ret) {
+				kfree(bp);
+				return -ENOMEM;
+			}
+			sp->buffers[sp->buffer_total_count] = bp;
+			(sp->buffer_total_count)++;
+			pvr2_buffer_set_idle(bp);
+		}
+	} else {
+		while (sp->buffer_total_count > cnt) {
+			struct pvr2_buffer *bp;
+			bp = sp->buffers[sp->buffer_total_count - 1];
+			/* Paranoia */
+			sp->buffers[sp->buffer_total_count - 1] = 0;
+			(sp->buffer_total_count)--;
+			pvr2_buffer_done(bp);
+			kfree(bp);
+		}
+		if (scnt < sp->buffer_slot_count) {
+			struct pvr2_buffer **nb = 0;
+			if (scnt) {
+				nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
+				if (!nb) return -ENOMEM;
+				memcpy(nb,sp->buffers,scnt * sizeof(*nb));
+			}
+			kfree(sp->buffers);
+			sp->buffers = nb;
+			sp->buffer_slot_count = scnt;
+		}
+	}
+	return 0;
+}
+
+static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp)
+{
+	struct pvr2_buffer *bp;
+	unsigned int cnt;
+
+	if (sp->buffer_total_count == sp->buffer_target_count) return 0;
+
+	pvr2_trace(PVR2_TRACE_BUF_POOL,
+		   "/*---TRACE_FLOW---*/"
+		   " poolCheck      stream=%p cur=%d tgt=%d",
+		   sp,sp->buffer_total_count,sp->buffer_target_count);
+
+	if (sp->buffer_total_count < sp->buffer_target_count) {
+		return pvr2_stream_buffer_count(sp,sp->buffer_target_count);
+	}
+
+	cnt = 0;
+	while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {
+		bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];
+		if (bp->state != pvr2_buffer_state_idle) break;
+		cnt++;
+	}
+	if (cnt) {
+		pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt);
+	}
+
+	return 0;
+}
+
+static void pvr2_stream_internal_flush(struct pvr2_stream *sp)
+{
+	struct list_head *lp;
+	struct pvr2_buffer *bp1;
+	while ((lp = sp->queued_list.next) != &sp->queued_list) {
+		bp1 = list_entry(lp,struct pvr2_buffer,list_overhead);
+		pvr2_buffer_wipe(bp1);
+		/* At this point, we should be guaranteed that no
+		   completion callback may happen on this buffer.  But it's
+		   possible that it might have completed after we noticed
+		   it but before we wiped it.  So double check its status
+		   here first. */
+		if (bp1->state != pvr2_buffer_state_queued) continue;
+		pvr2_buffer_set_idle(bp1);
+	}
+	if (sp->buffer_total_count != sp->buffer_target_count) {
+		pvr2_stream_achieve_buffer_count(sp);
+	}
+}
+
+static void pvr2_stream_init(struct pvr2_stream *sp)
+{
+	spin_lock_init(&sp->list_lock);
+	mutex_init(&sp->mutex);
+	INIT_LIST_HEAD(&sp->queued_list);
+	INIT_LIST_HEAD(&sp->ready_list);
+	INIT_LIST_HEAD(&sp->idle_list);
+}
+
+static void pvr2_stream_done(struct pvr2_stream *sp)
+{
+	mutex_lock(&sp->mutex); do {
+		pvr2_stream_internal_flush(sp);
+		pvr2_stream_buffer_count(sp,0);
+	} while (0); mutex_unlock(&sp->mutex);
+}
+
+static void buffer_complete(struct urb *urb, struct pt_regs *regs)
+{
+	struct pvr2_buffer *bp = urb->context;
+	struct pvr2_stream *sp;
+	unsigned long irq_flags;
+	BUFFER_CHECK(bp);
+	sp = bp->stream;
+	bp->used_count = 0;
+	bp->status = 0;
+	pvr2_trace(PVR2_TRACE_BUF_FLOW,
+		   "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",
+		   bp,urb->status,urb->actual_length);
+	spin_lock_irqsave(&sp->list_lock,irq_flags);
+	if ((!(urb->status)) ||
+	    (urb->status == -ENOENT) ||
+	    (urb->status == -ECONNRESET) ||
+	    (urb->status == -ESHUTDOWN)) {
+		bp->used_count = urb->actual_length;
+		if (sp->fail_count) {
+			pvr2_trace(PVR2_TRACE_TOLERANCE,
+				   "stream %p transfer ok"
+				   " - fail count reset",sp);
+			sp->fail_count = 0;
+		}
+	} else if (sp->fail_count < sp->fail_tolerance) {
+		// We can tolerate this error, because we're below the
+		// threshold...
+		(sp->fail_count)++;
+		pvr2_trace(PVR2_TRACE_TOLERANCE,
+			   "stream %p ignoring error %d"
+			   " - fail count increased to %u",
+			   sp,urb->status,sp->fail_count);
+	} else {
+		bp->status = urb->status;
+	}
+	spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+	pvr2_buffer_set_ready(bp);
+	if (sp && sp->callback_func) {
+		sp->callback_func(sp->callback_data);
+	}
+}
+
+struct pvr2_stream *pvr2_stream_create(void)
+{
+	struct pvr2_stream *sp;
+	sp = kmalloc(sizeof(*sp),GFP_KERNEL);
+	if (!sp) return sp;
+	memset(sp,0,sizeof(*sp));
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
+	pvr2_stream_init(sp);
+	return sp;
+}
+
+void pvr2_stream_destroy(struct pvr2_stream *sp)
+{
+	if (!sp) return;
+	pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp);
+	pvr2_stream_done(sp);
+	kfree(sp);
+}
+
+void pvr2_stream_setup(struct pvr2_stream *sp,
+		       struct usb_device *dev,
+		       int endpoint,
+		       unsigned int tolerance)
+{
+	mutex_lock(&sp->mutex); do {
+		pvr2_stream_internal_flush(sp);
+		sp->dev = dev;
+		sp->endpoint = endpoint;
+		sp->fail_tolerance = tolerance;
+	} while(0); mutex_unlock(&sp->mutex);
+}
+
+void pvr2_stream_set_callback(struct pvr2_stream *sp,
+			      pvr2_stream_callback func,
+			      void *data)
+{
+	unsigned long irq_flags;
+	mutex_lock(&sp->mutex); do {
+		spin_lock_irqsave(&sp->list_lock,irq_flags);
+		sp->callback_data = data;
+		sp->callback_func = func;
+		spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+	} while(0); mutex_unlock(&sp->mutex);
+}
+
+/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
+{
+	return sp->buffer_target_count;
+}
+
+int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
+{
+	int ret;
+	if (sp->buffer_target_count == cnt) return 0;
+	mutex_lock(&sp->mutex); do {
+		sp->buffer_target_count = cnt;
+		ret = pvr2_stream_achieve_buffer_count(sp);
+	} while(0); mutex_unlock(&sp->mutex);
+	return ret;
+}
+
+struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
+{
+	struct list_head *lp = sp->idle_list.next;
+	if (lp == &sp->idle_list) return 0;
+	return list_entry(lp,struct pvr2_buffer,list_overhead);
+}
+
+struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
+{
+	struct list_head *lp = sp->ready_list.next;
+	if (lp == &sp->ready_list) return 0;
+	return list_entry(lp,struct pvr2_buffer,list_overhead);
+}
+
+struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
+{
+	if (id < 0) return 0;
+	if (id >= sp->buffer_total_count) return 0;
+	return sp->buffers[id];
+}
+
+int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
+{
+	return sp->r_count;
+}
+
+int pvr2_stream_get_idle_count(struct pvr2_stream *sp)
+{
+	return sp->i_count;
+}
+
+void pvr2_stream_flush(struct pvr2_stream *sp)
+{
+	mutex_lock(&sp->mutex); do {
+		pvr2_stream_internal_flush(sp);
+	} while(0); mutex_unlock(&sp->mutex);
+}
+
+void pvr2_stream_kill(struct pvr2_stream *sp)
+{
+	struct pvr2_buffer *bp;
+	mutex_lock(&sp->mutex); do {
+		pvr2_stream_internal_flush(sp);
+		while ((bp = pvr2_stream_get_ready_buffer(sp)) != 0) {
+			pvr2_buffer_set_idle(bp);
+		}
+		if (sp->buffer_total_count != sp->buffer_target_count) {
+			pvr2_stream_achieve_buffer_count(sp);
+		}
+	} while(0); mutex_unlock(&sp->mutex);
+}
+
+int pvr2_buffer_queue(struct pvr2_buffer *bp)
+{
+#undef SEED_BUFFER
+#ifdef SEED_BUFFER
+	unsigned int idx;
+	unsigned int val;
+#endif
+	int ret = 0;
+	struct pvr2_stream *sp;
+	if (!bp) return -EINVAL;
+	sp = bp->stream;
+	mutex_lock(&sp->mutex); do {
+		pvr2_buffer_wipe(bp);
+		if (!sp->dev) {
+			ret = -EIO;
+			break;
+		}
+		pvr2_buffer_set_queued(bp);
+#ifdef SEED_BUFFER
+		for (idx = 0; idx < (bp->max_count) / 4; idx++) {
+			val = bp->id << 24;
+			val |= idx;
+			((unsigned int *)(bp->ptr))[idx] = val;
+		}
+#endif
+		bp->status = -EINPROGRESS;
+		usb_fill_bulk_urb(bp->purb,      // struct urb *urb
+				  sp->dev,       // struct usb_device *dev
+				  // endpoint (below)
+				  usb_rcvbulkpipe(sp->dev,sp->endpoint),
+				  bp->ptr,       // void *transfer_buffer
+				  bp->max_count, // int buffer_length
+				  buffer_complete,
+				  bp);
+		usb_submit_urb(bp->purb,GFP_KERNEL);
+	} while(0); mutex_unlock(&sp->mutex);
+	return ret;
+}
+
+int pvr2_buffer_idle(struct pvr2_buffer *bp)
+{
+	struct pvr2_stream *sp;
+	if (!bp) return -EINVAL;
+	sp = bp->stream;
+	mutex_lock(&sp->mutex); do {
+		pvr2_buffer_wipe(bp);
+		pvr2_buffer_set_idle(bp);
+		if (sp->buffer_total_count != sp->buffer_target_count) {
+			pvr2_stream_achieve_buffer_count(sp);
+		}
+	} while(0); mutex_unlock(&sp->mutex);
+	return 0;
+}
+
+int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
+{
+	int ret = 0;
+	unsigned long irq_flags;
+	struct pvr2_stream *sp;
+	if (!bp) return -EINVAL;
+	sp = bp->stream;
+	mutex_lock(&sp->mutex); do {
+		spin_lock_irqsave(&sp->list_lock,irq_flags);
+		if (bp->state != pvr2_buffer_state_idle) {
+			ret = -EPERM;
+		} else {
+			bp->ptr = ptr;
+			bp->stream->i_bcount -= bp->max_count;
+			bp->max_count = cnt;
+			bp->stream->i_bcount += bp->max_count;
+			pvr2_trace(PVR2_TRACE_BUF_FLOW,
+				   "/*---TRACE_FLOW---*/ bufferPool    "
+				   " %8s cap cap=%07d cnt=%02d",
+				   pvr2_buffer_state_decode(
+					   pvr2_buffer_state_idle),
+				   bp->stream->i_bcount,bp->stream->i_count);
+		}
+		spin_unlock_irqrestore(&sp->list_lock,irq_flags);
+	} while(0); mutex_unlock(&sp->mutex);
+	return ret;
+}
+
+unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
+{
+	return bp->used_count;
+}
+
+int pvr2_buffer_get_status(struct pvr2_buffer *bp)
+{
+	return bp->status;
+}
+
+enum pvr2_buffer_state pvr2_buffer_get_state(struct pvr2_buffer *bp)
+{
+	return bp->state;
+}
+
+int pvr2_buffer_get_id(struct pvr2_buffer *bp)
+{
+	return bp->id;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h
new file mode 100644
index 0000000..65e1138
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-io.h
@@ -0,0 +1,102 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_IO_H
+#define __PVRUSB2_IO_H
+
+#include <linux/usb.h>
+#include <linux/list.h>
+
+typedef void (*pvr2_stream_callback)(void *);
+
+enum pvr2_buffer_state {
+	pvr2_buffer_state_none = 0,   // Not on any list
+	pvr2_buffer_state_idle = 1,   // Buffer is ready to be used again
+	pvr2_buffer_state_queued = 2, // Buffer has been queued for filling
+	pvr2_buffer_state_ready = 3,  // Buffer has data available
+};
+
+struct pvr2_stream;
+struct pvr2_buffer;
+
+const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
+
+/* Initialize / tear down stream structure */
+struct pvr2_stream *pvr2_stream_create(void);
+void pvr2_stream_destroy(struct pvr2_stream *);
+void pvr2_stream_setup(struct pvr2_stream *,
+		       struct usb_device *dev,int endpoint,
+		       unsigned int tolerance);
+void pvr2_stream_set_callback(struct pvr2_stream *,
+			      pvr2_stream_callback func,
+			      void *data);
+
+/* Query / set the nominal buffer count */
+int pvr2_stream_get_buffer_count(struct pvr2_stream *);
+int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int);
+
+/* Get a pointer to a buffer that is either idle, ready, or is specified
+   named. */
+struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *);
+struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *);
+struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id);
+
+/* Find out how many buffers are idle or ready */
+int pvr2_stream_get_idle_count(struct pvr2_stream *);
+int pvr2_stream_get_ready_count(struct pvr2_stream *);
+
+/* Kill all pending operations */
+void pvr2_stream_flush(struct pvr2_stream *);
+
+/* Kill all pending buffers and throw away any ready buffers as well */
+void pvr2_stream_kill(struct pvr2_stream *);
+
+/* Set up the actual storage for a buffer */
+int pvr2_buffer_set_buffer(struct pvr2_buffer *,void *ptr,unsigned int cnt);
+
+/* Find out size of data in the given ready buffer */
+unsigned int pvr2_buffer_get_count(struct pvr2_buffer *);
+
+/* Retrieve completion code for given ready buffer */
+int pvr2_buffer_get_status(struct pvr2_buffer *);
+
+/* Retrieve state of given buffer */
+enum pvr2_buffer_state pvr2_buffer_get_state(struct pvr2_buffer *);
+
+/* Retrieve ID of given buffer */
+int pvr2_buffer_get_id(struct pvr2_buffer *);
+
+/* Start reading into given buffer (kill it if needed) */
+int pvr2_buffer_queue(struct pvr2_buffer *);
+
+/* Move buffer back to idle pool (kill it if needed) */
+int pvr2_buffer_idle(struct pvr2_buffer *);
+
+#endif /* __PVRUSB2_IO_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
new file mode 100644
index 0000000..49da062
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c
@@ -0,0 +1,513 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-ioread.h"
+#include "pvrusb2-debug.h"
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+
+#define BUFFER_COUNT 32
+#define BUFFER_SIZE PAGE_ALIGN(0x4000)
+
+struct pvr2_ioread {
+	struct pvr2_stream *stream;
+	char *buffer_storage[BUFFER_COUNT];
+	char *sync_key_ptr;
+	unsigned int sync_key_len;
+	unsigned int sync_buf_offs;
+	unsigned int sync_state;
+	unsigned int sync_trashed_count;
+	int enabled;         // Streaming is on
+	int spigot_open;     // OK to pass data to client
+	int stream_running;  // Passing data to client now
+
+	/* State relevant to current buffer being read */
+	struct pvr2_buffer *c_buf;
+	char *c_data_ptr;
+	unsigned int c_data_len;
+	unsigned int c_data_offs;
+	struct mutex mutex;
+};
+
+static int pvr2_ioread_init(struct pvr2_ioread *cp)
+{
+	unsigned int idx;
+
+	cp->stream = 0;
+	mutex_init(&cp->mutex);
+
+	for (idx = 0; idx < BUFFER_COUNT; idx++) {
+		cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL);
+		if (!(cp->buffer_storage[idx])) break;
+	}
+
+	if (idx < BUFFER_COUNT) {
+		// An allocation appears to have failed
+		for (idx = 0; idx < BUFFER_COUNT; idx++) {
+			if (!(cp->buffer_storage[idx])) continue;
+			kfree(cp->buffer_storage[idx]);
+		}
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void pvr2_ioread_done(struct pvr2_ioread *cp)
+{
+	unsigned int idx;
+
+	pvr2_ioread_setup(cp,0);
+	for (idx = 0; idx < BUFFER_COUNT; idx++) {
+		if (!(cp->buffer_storage[idx])) continue;
+		kfree(cp->buffer_storage[idx]);
+	}
+}
+
+struct pvr2_ioread *pvr2_ioread_create(void)
+{
+	struct pvr2_ioread *cp;
+	cp = kmalloc(sizeof(*cp),GFP_KERNEL);
+	if (!cp) return 0;
+	pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp);
+	memset(cp,0,sizeof(*cp));
+	if (pvr2_ioread_init(cp) < 0) {
+		kfree(cp);
+		return 0;
+	}
+	return cp;
+}
+
+void pvr2_ioread_destroy(struct pvr2_ioread *cp)
+{
+	if (!cp) return;
+	pvr2_ioread_done(cp);
+	pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp);
+	if (cp->sync_key_ptr) {
+		kfree(cp->sync_key_ptr);
+		cp->sync_key_ptr = 0;
+	}
+	kfree(cp);
+}
+
+void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp,
+			      const char *sync_key_ptr,
+			      unsigned int sync_key_len)
+{
+	if (!cp) return;
+
+	if (!sync_key_ptr) sync_key_len = 0;
+	if ((sync_key_len == cp->sync_key_len) &&
+	    ((!sync_key_len) ||
+	     (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return;
+
+	if (sync_key_len != cp->sync_key_len) {
+		if (cp->sync_key_ptr) {
+			kfree(cp->sync_key_ptr);
+			cp->sync_key_ptr = 0;
+		}
+		cp->sync_key_len = 0;
+		if (sync_key_len) {
+			cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL);
+			if (cp->sync_key_ptr) {
+				cp->sync_key_len = sync_key_len;
+			}
+		}
+	}
+	if (!cp->sync_key_len) return;
+	memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len);
+}
+
+static void pvr2_ioread_stop(struct pvr2_ioread *cp)
+{
+	if (!(cp->enabled)) return;
+	pvr2_trace(PVR2_TRACE_START_STOP,
+		   "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp);
+	pvr2_stream_kill(cp->stream);
+	cp->c_buf = 0;
+	cp->c_data_ptr = 0;
+	cp->c_data_len = 0;
+	cp->c_data_offs = 0;
+	cp->enabled = 0;
+	cp->stream_running = 0;
+	cp->spigot_open = 0;
+	if (cp->sync_state) {
+		pvr2_trace(PVR2_TRACE_DATA_FLOW,
+			   "/*---TRACE_READ---*/ sync_state <== 0");
+		cp->sync_state = 0;
+	}
+}
+
+static int pvr2_ioread_start(struct pvr2_ioread *cp)
+{
+	int stat;
+	struct pvr2_buffer *bp;
+	if (cp->enabled) return 0;
+	if (!(cp->stream)) return 0;
+	pvr2_trace(PVR2_TRACE_START_STOP,
+		   "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp);
+	while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != 0) {
+		stat = pvr2_buffer_queue(bp);
+		if (stat < 0) {
+			pvr2_trace(PVR2_TRACE_DATA_FLOW,
+				   "/*---TRACE_READ---*/"
+				   " pvr2_ioread_start id=%p"
+				   " error=%d",
+				   cp,stat);
+			pvr2_ioread_stop(cp);
+			return stat;
+		}
+	}
+	cp->enabled = !0;
+	cp->c_buf = 0;
+	cp->c_data_ptr = 0;
+	cp->c_data_len = 0;
+	cp->c_data_offs = 0;
+	cp->stream_running = 0;
+	if (cp->sync_key_len) {
+		pvr2_trace(PVR2_TRACE_DATA_FLOW,
+			   "/*---TRACE_READ---*/ sync_state <== 1");
+		cp->sync_state = 1;
+		cp->sync_trashed_count = 0;
+		cp->sync_buf_offs = 0;
+	}
+	cp->spigot_open = 0;
+	return 0;
+}
+
+struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp)
+{
+	return cp->stream;
+}
+
+int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp)
+{
+	int ret;
+	unsigned int idx;
+	struct pvr2_buffer *bp;
+
+	mutex_lock(&cp->mutex); do {
+		if (cp->stream) {
+			pvr2_trace(PVR2_TRACE_START_STOP,
+				   "/*---TRACE_READ---*/"
+				   " pvr2_ioread_setup (tear-down) id=%p",cp);
+			pvr2_ioread_stop(cp);
+			pvr2_stream_kill(cp->stream);
+			pvr2_stream_set_buffer_count(cp->stream,0);
+			cp->stream = 0;
+		}
+		if (sp) {
+			pvr2_trace(PVR2_TRACE_START_STOP,
+				   "/*---TRACE_READ---*/"
+				   " pvr2_ioread_setup (setup) id=%p",cp);
+			pvr2_stream_kill(sp);
+			ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT);
+			if (ret < 0) return ret;
+			for (idx = 0; idx < BUFFER_COUNT; idx++) {
+				bp = pvr2_stream_get_buffer(sp,idx);
+				pvr2_buffer_set_buffer(bp,
+						       cp->buffer_storage[idx],
+						       BUFFER_SIZE);
+			}
+			cp->stream = sp;
+		}
+	} while (0); mutex_unlock(&cp->mutex);
+
+	return 0;
+}
+
+int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl)
+{
+	int ret = 0;
+	if ((!fl) == (!(cp->enabled))) return ret;
+
+	mutex_lock(&cp->mutex); do {
+		if (fl) {
+			ret = pvr2_ioread_start(cp);
+		} else {
+			pvr2_ioread_stop(cp);
+		}
+	} while (0); mutex_unlock(&cp->mutex);
+	return ret;
+}
+
+int pvr2_ioread_get_enabled(struct pvr2_ioread *cp)
+{
+	return cp->enabled != 0;
+}
+
+int pvr2_ioread_get_buffer(struct pvr2_ioread *cp)
+{
+	int stat;
+
+	while (cp->c_data_len <= cp->c_data_offs) {
+		if (cp->c_buf) {
+			// Flush out current buffer first.
+			stat = pvr2_buffer_queue(cp->c_buf);
+			if (stat < 0) {
+				// Streaming error...
+				pvr2_trace(PVR2_TRACE_DATA_FLOW,
+					   "/*---TRACE_READ---*/"
+					   " pvr2_ioread_read id=%p"
+					   " queue_error=%d",
+					   cp,stat);
+				pvr2_ioread_stop(cp);
+				return 0;
+			}
+			cp->c_buf = 0;
+			cp->c_data_ptr = 0;
+			cp->c_data_len = 0;
+			cp->c_data_offs = 0;
+		}
+		// Now get a freshly filled buffer.
+		cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream);
+		if (!cp->c_buf) break; // Nothing ready; done.
+		cp->c_data_len = pvr2_buffer_get_count(cp->c_buf);
+		if (!cp->c_data_len) {
+			// Nothing transferred.  Was there an error?
+			stat = pvr2_buffer_get_status(cp->c_buf);
+			if (stat < 0) {
+				// Streaming error...
+				pvr2_trace(PVR2_TRACE_DATA_FLOW,
+					   "/*---TRACE_READ---*/"
+					   " pvr2_ioread_read id=%p"
+					   " buffer_error=%d",
+					   cp,stat);
+				pvr2_ioread_stop(cp);
+				// Give up.
+				return 0;
+			}
+			// Start over...
+			continue;
+		}
+		cp->c_data_offs = 0;
+		cp->c_data_ptr = cp->buffer_storage[
+			pvr2_buffer_get_id(cp->c_buf)];
+	}
+	return !0;
+}
+
+void pvr2_ioread_filter(struct pvr2_ioread *cp)
+{
+	unsigned int idx;
+	if (!cp->enabled) return;
+	if (cp->sync_state != 1) return;
+
+	// Search the stream for our synchronization key.  This is made
+	// complicated by the fact that in order to be honest with
+	// ourselves here we must search across buffer boundaries...
+	mutex_lock(&cp->mutex); while (1) {
+		// Ensure we have a buffer
+		if (!pvr2_ioread_get_buffer(cp)) break;
+		if (!cp->c_data_len) break;
+
+		// Now walk the buffer contents until we match the key or
+		// run out of buffer data.
+		for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) {
+			if (cp->sync_buf_offs >= cp->sync_key_len) break;
+			if (cp->c_data_ptr[idx] ==
+			    cp->sync_key_ptr[cp->sync_buf_offs]) {
+				// Found the next key byte
+				(cp->sync_buf_offs)++;
+			} else {
+				// Whoops, mismatched.  Start key over...
+				cp->sync_buf_offs = 0;
+			}
+		}
+
+		// Consume what we've walked through
+		cp->c_data_offs += idx;
+		cp->sync_trashed_count += idx;
+
+		// If we've found the key, then update state and get out.
+		if (cp->sync_buf_offs >= cp->sync_key_len) {
+			cp->sync_trashed_count -= cp->sync_key_len;
+			pvr2_trace(PVR2_TRACE_DATA_FLOW,
+				   "/*---TRACE_READ---*/"
+				   " sync_state <== 2 (skipped %u bytes)",
+				   cp->sync_trashed_count);
+			cp->sync_state = 2;
+			cp->sync_buf_offs = 0;
+			break;
+		}
+
+		if (cp->c_data_offs < cp->c_data_len) {
+			// Sanity check - should NEVER get here
+			pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+				   "ERROR: pvr2_ioread filter sync problem"
+				   " len=%u offs=%u",
+				   cp->c_data_len,cp->c_data_offs);
+			// Get out so we don't get stuck in an infinite
+			// loop.
+			break;
+		}
+
+		continue; // (for clarity)
+	} mutex_unlock(&cp->mutex);
+}
+
+int pvr2_ioread_avail(struct pvr2_ioread *cp)
+{
+	int ret;
+	if (!(cp->enabled)) {
+		// Stream is not enabled; so this is an I/O error
+		return -EIO;
+	}
+
+	if (cp->sync_state == 1) {
+		pvr2_ioread_filter(cp);
+		if (cp->sync_state == 1) return -EAGAIN;
+	}
+
+	ret = 0;
+	if (cp->stream_running) {
+		if (!pvr2_stream_get_ready_count(cp->stream)) {
+			// No data available at all right now.
+			ret = -EAGAIN;
+		}
+	} else {
+		if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) {
+			// Haven't buffered up enough yet; try again later
+			ret = -EAGAIN;
+		}
+	}
+
+	if ((!(cp->spigot_open)) != (!(ret == 0))) {
+		cp->spigot_open = (ret == 0);
+		pvr2_trace(PVR2_TRACE_DATA_FLOW,
+			   "/*---TRACE_READ---*/ data is %s",
+			   cp->spigot_open ? "available" : "pending");
+	}
+
+	return ret;
+}
+
+int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt)
+{
+	unsigned int copied_cnt;
+	unsigned int bcnt;
+	const char *src;
+	int stat;
+	int ret = 0;
+	unsigned int req_cnt = cnt;
+
+	if (!cnt) {
+		pvr2_trace(PVR2_TRACE_TRAP,
+			   "/*---TRACE_READ---*/ pvr2_ioread_read id=%p"
+			   " ZERO Request? Returning zero.",cp);
+		return 0;
+	}
+
+	stat = pvr2_ioread_avail(cp);
+	if (stat < 0) return stat;
+
+	cp->stream_running = !0;
+
+	mutex_lock(&cp->mutex); do {
+
+		// Suck data out of the buffers and copy to the user
+		copied_cnt = 0;
+		if (!buf) cnt = 0;
+		while (1) {
+			if (!pvr2_ioread_get_buffer(cp)) {
+				ret = -EIO;
+				break;
+			}
+
+			if (!cnt) break;
+
+			if (cp->sync_state == 2) {
+				// We're repeating the sync key data into
+				// the stream.
+				src = cp->sync_key_ptr + cp->sync_buf_offs;
+				bcnt = cp->sync_key_len - cp->sync_buf_offs;
+			} else {
+				// Normal buffer copy
+				src = cp->c_data_ptr + cp->c_data_offs;
+				bcnt = cp->c_data_len - cp->c_data_offs;
+			}
+
+			if (!bcnt) break;
+
+			// Don't run past user's buffer
+			if (bcnt > cnt) bcnt = cnt;
+
+			if (copy_to_user(buf,src,bcnt)) {
+				// User supplied a bad pointer?
+				// Give up - this *will* cause data
+				// to be lost.
+				ret = -EFAULT;
+				break;
+			}
+			cnt -= bcnt;
+			buf += bcnt;
+			copied_cnt += bcnt;
+
+			if (cp->sync_state == 2) {
+				// Update offset inside sync key that we're
+				// repeating back out.
+				cp->sync_buf_offs += bcnt;
+				if (cp->sync_buf_offs >= cp->sync_key_len) {
+					// Consumed entire key; switch mode
+					// to normal.
+					pvr2_trace(PVR2_TRACE_DATA_FLOW,
+						   "/*---TRACE_READ---*/"
+						   " sync_state <== 0");
+					cp->sync_state = 0;
+				}
+			} else {
+				// Update buffer offset.
+				cp->c_data_offs += bcnt;
+			}
+		}
+
+	} while (0); mutex_unlock(&cp->mutex);
+
+	if (!ret) {
+		if (copied_cnt) {
+			// If anything was copied, return that count
+			ret = copied_cnt;
+		} else {
+			// Nothing copied; suggest to caller that another
+			// attempt should be tried again later
+			ret = -EAGAIN;
+		}
+	}
+
+	pvr2_trace(PVR2_TRACE_DATA_FLOW,
+		   "/*---TRACE_READ---*/ pvr2_ioread_read"
+		   " id=%p request=%d result=%d",
+		   cp,req_cnt,ret);
+	return ret;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/drivers/media/video/pvrusb2/pvrusb2-ioread.h
new file mode 100644
index 0000000..6b00259
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.h
@@ -0,0 +1,50 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_IOREAD_H
+#define __PVRUSB2_IOREAD_H
+
+#include "pvrusb2-io.h"
+
+struct pvr2_ioread;
+
+struct pvr2_ioread *pvr2_ioread_create(void);
+void pvr2_ioread_destroy(struct pvr2_ioread *);
+int pvr2_ioread_setup(struct pvr2_ioread *,struct pvr2_stream *);
+struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *);
+void pvr2_ioread_set_sync_key(struct pvr2_ioread *,
+			      const char *sync_key_ptr,
+			      unsigned int sync_key_len);
+int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl);
+int pvr2_ioread_get_enabled(struct pvr2_ioread *);
+int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt);
+int pvr2_ioread_avail(struct pvr2_ioread *);
+
+#endif /* __PVRUSB2_IOREAD_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c
new file mode 100644
index 0000000..b952482
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-main.c
@@ -0,0 +1,172 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/smp_lock.h>
+#include <linux/usb.h>
+#include <linux/videodev2.h>
+
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-context.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-v4l2.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+#include "pvrusb2-sysfs.h"
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+#define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>"
+#define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner"
+#define DRIVER_VERSION "V4L in-tree version"
+
+#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \
+			    PVR2_TRACE_INFO| \
+			    PVR2_TRACE_TOLERANCE| \
+			    PVR2_TRACE_TRAP| \
+			    0)
+
+int pvrusb2_debug = DEFAULT_DEBUG_MASK;
+
+module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug trace mask");
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+static struct pvr2_sysfs_class *class_ptr = 0;
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+static void pvr_setup_attach(struct pvr2_context *pvr)
+{
+	/* Create association with v4l layer */
+	pvr2_v4l2_create(pvr);
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+	pvr2_sysfs_create(pvr,class_ptr);
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+}
+
+static int pvr_probe(struct usb_interface *intf,
+		     const struct usb_device_id *devid)
+{
+	struct pvr2_context *pvr;
+
+	/* Create underlying hardware interface */
+	pvr = pvr2_context_create(intf,devid,pvr_setup_attach);
+	if (!pvr) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "Failed to create hdw handler");
+		return -ENOMEM;
+	}
+
+	pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr);
+
+	usb_set_intfdata(intf, pvr);
+
+	return 0;
+}
+
+/*
+ * pvr_disconnect()
+ *
+ */
+static void pvr_disconnect(struct usb_interface *intf)
+{
+	struct pvr2_context *pvr = usb_get_intfdata(intf);
+
+	pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr);
+
+	usb_set_intfdata (intf, NULL);
+	pvr2_context_disconnect(pvr);
+
+	pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) DONE",pvr);
+
+}
+
+static struct usb_driver pvr_driver = {
+	name:           "pvrusb2",
+	id_table:       pvr2_device_table,
+	probe:          pvr_probe,
+	disconnect:     pvr_disconnect
+};
+
+/*
+ * pvr_init() / pvr_exit()
+ *
+ * This code is run to initialize/exit the driver.
+ *
+ */
+static int __init pvr_init(void)
+{
+	int ret;
+
+	pvr2_trace(PVR2_TRACE_INIT,"pvr_init");
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+	class_ptr = pvr2_sysfs_class_create();
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+	ret = usb_register(&pvr_driver);
+
+	if (ret == 0)
+		info(DRIVER_DESC " : " DRIVER_VERSION);
+	if (pvrusb2_debug) info("Debug mask is %d (0x%x)",
+				pvrusb2_debug,pvrusb2_debug);
+
+	return ret;
+}
+
+static void __exit pvr_exit(void)
+{
+
+	pvr2_trace(PVR2_TRACE_INIT,"pvr_exit");
+
+#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS
+	pvr2_sysfs_class_destroy(class_ptr);
+#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */
+
+	usb_deregister(&pvr_driver);
+}
+
+module_init(pvr_init);
+module_exit(pvr_exit);
+
+/* Mike Isely <mcisely@pobox.com> 11-Mar-2006: See pvrusb2-hdw.c for
+   MODULE_DEVICE_TABLE().  We have to declare that attribute there
+   because that's where the device table actually is now and it seems
+   that certain gcc configurations get angry if MODULE_DEVICE_TABLE()
+   is used on what ends up being an external symbol. */
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c
new file mode 100644
index 0000000..1340636
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-std.c
@@ -0,0 +1,408 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2-std.h"
+#include "pvrusb2-debug.h"
+#include <asm/string.h>
+#include <linux/slab.h>
+
+struct std_name {
+	const char *name;
+	v4l2_std_id id;
+};
+
+
+#define CSTD_PAL \
+	(V4L2_STD_PAL_B| \
+	 V4L2_STD_PAL_B1| \
+	 V4L2_STD_PAL_G| \
+	 V4L2_STD_PAL_H| \
+	 V4L2_STD_PAL_I| \
+	 V4L2_STD_PAL_D| \
+	 V4L2_STD_PAL_D1| \
+	 V4L2_STD_PAL_K| \
+	 V4L2_STD_PAL_M| \
+	 V4L2_STD_PAL_N| \
+	 V4L2_STD_PAL_Nc| \
+	 V4L2_STD_PAL_60)
+
+#define CSTD_NTSC \
+	(V4L2_STD_NTSC_M| \
+	 V4L2_STD_NTSC_M_JP| \
+	 V4L2_STD_NTSC_M_KR| \
+	 V4L2_STD_NTSC_443)
+
+#define CSTD_SECAM \
+	(V4L2_STD_SECAM_B| \
+	 V4L2_STD_SECAM_D| \
+	 V4L2_STD_SECAM_G| \
+	 V4L2_STD_SECAM_H| \
+	 V4L2_STD_SECAM_K| \
+	 V4L2_STD_SECAM_K1| \
+	 V4L2_STD_SECAM_L| \
+	 V4L2_STD_SECAM_LC)
+
+#define TSTD_B   (V4L2_STD_PAL_B|V4L2_STD_SECAM_B)
+#define TSTD_B1  (V4L2_STD_PAL_B1)
+#define TSTD_D   (V4L2_STD_PAL_D|V4L2_STD_SECAM_D)
+#define TSTD_D1  (V4L2_STD_PAL_D1)
+#define TSTD_G   (V4L2_STD_PAL_G|V4L2_STD_SECAM_G)
+#define TSTD_H   (V4L2_STD_PAL_H|V4L2_STD_SECAM_H)
+#define TSTD_I   (V4L2_STD_PAL_I)
+#define TSTD_K   (V4L2_STD_PAL_K|V4L2_STD_SECAM_K)
+#define TSTD_K1  (V4L2_STD_SECAM_K1)
+#define TSTD_L   (V4L2_STD_SECAM_L)
+#define TSTD_M   (V4L2_STD_PAL_M|V4L2_STD_NTSC_M)
+#define TSTD_N   (V4L2_STD_PAL_N)
+#define TSTD_Nc  (V4L2_STD_PAL_Nc)
+#define TSTD_60  (V4L2_STD_PAL_60)
+
+#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM)
+
+/* Mapping of standard bits to color system */
+const static struct std_name std_groups[] = {
+	{"PAL",CSTD_PAL},
+	{"NTSC",CSTD_NTSC},
+	{"SECAM",CSTD_SECAM},
+};
+
+/* Mapping of standard bits to modulation system */
+const static struct std_name std_items[] = {
+	{"B",TSTD_B},
+	{"B1",TSTD_B1},
+	{"D",TSTD_D},
+	{"D1",TSTD_D1},
+	{"G",TSTD_G},
+	{"H",TSTD_H},
+	{"I",TSTD_I},
+	{"K",TSTD_K},
+	{"K1",TSTD_K1},
+	{"L",TSTD_L},
+	{"LC",V4L2_STD_SECAM_LC},
+	{"M",TSTD_M},
+	{"Mj",V4L2_STD_NTSC_M_JP},
+	{"443",V4L2_STD_NTSC_443},
+	{"Mk",V4L2_STD_NTSC_M_KR},
+	{"N",TSTD_N},
+	{"Nc",TSTD_Nc},
+	{"60",TSTD_60},
+};
+
+
+// Search an array of std_name structures and return a pointer to the
+// element with the matching name.
+static const struct std_name *find_std_name(const struct std_name *arrPtr,
+					    unsigned int arrSize,
+					    const char *bufPtr,
+					    unsigned int bufSize)
+{
+	unsigned int idx;
+	const struct std_name *p;
+	for (idx = 0; idx < arrSize; idx++) {
+		p = arrPtr + idx;
+		if (strlen(p->name) != bufSize) continue;
+		if (!memcmp(bufPtr,p->name,bufSize)) return p;
+	}
+	return 0;
+}
+
+
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+		       unsigned int bufSize)
+{
+	v4l2_std_id id = 0;
+	v4l2_std_id cmsk = 0;
+	v4l2_std_id t;
+	int mMode = 0;
+	unsigned int cnt;
+	char ch;
+	const struct std_name *sp;
+
+	while (bufSize) {
+		if (!mMode) {
+			cnt = 0;
+			while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
+			if (cnt >= bufSize) return 0; // No more characters
+			sp = find_std_name(
+				std_groups,
+				sizeof(std_groups)/sizeof(std_groups[0]),
+				bufPtr,cnt);
+			if (!sp) return 0; // Illegal color system name
+			cnt++;
+			bufPtr += cnt;
+			bufSize -= cnt;
+			mMode = !0;
+			cmsk = sp->id;
+			continue;
+		}
+		cnt = 0;
+		while (cnt < bufSize) {
+			ch = bufPtr[cnt];
+			if (ch == ';') {
+				mMode = 0;
+				break;
+			}
+			if (ch == '/') break;
+			cnt++;
+		}
+		sp = find_std_name(std_items,
+				   sizeof(std_items)/sizeof(std_items[0]),
+				   bufPtr,cnt);
+		if (!sp) return 0; // Illegal modulation system ID
+		t = sp->id & cmsk;
+		if (!t) return 0; // Specific color + modulation system illegal
+		id |= t;
+		if (cnt < bufSize) cnt++;
+		bufPtr += cnt;
+		bufSize -= cnt;
+	}
+
+	if (idPtr) *idPtr = id;
+	return !0;
+}
+
+
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+				v4l2_std_id id)
+{
+	unsigned int idx1,idx2;
+	const struct std_name *ip,*gp;
+	int gfl,cfl;
+	unsigned int c1,c2;
+	cfl = 0;
+	c1 = 0;
+	for (idx1 = 0;
+	     idx1 < sizeof(std_groups)/sizeof(std_groups[0]);
+	     idx1++) {
+		gp = std_groups + idx1;
+		gfl = 0;
+		for (idx2 = 0;
+		     idx2 < sizeof(std_items)/sizeof(std_items[0]);
+		     idx2++) {
+			ip = std_items + idx2;
+			if (!(gp->id & ip->id & id)) continue;
+			if (!gfl) {
+				if (cfl) {
+					c2 = scnprintf(bufPtr,bufSize,";");
+					c1 += c2;
+					bufSize -= c2;
+					bufPtr += c2;
+				}
+				cfl = !0;
+				c2 = scnprintf(bufPtr,bufSize,
+					       "%s-",gp->name);
+				gfl = !0;
+			} else {
+				c2 = scnprintf(bufPtr,bufSize,"/");
+			}
+			c1 += c2;
+			bufSize -= c2;
+			bufPtr += c2;
+			c2 = scnprintf(bufPtr,bufSize,
+				       ip->name);
+			c1 += c2;
+			bufSize -= c2;
+			bufPtr += c2;
+		}
+	}
+	return c1;
+}
+
+
+// Template data for possible enumerated video standards.  Here we group
+// standards which share common frame rates and resolution.
+static struct v4l2_standard generic_standards[] = {
+	{
+		.id             = (TSTD_B|TSTD_B1|
+				   TSTD_D|TSTD_D1|
+				   TSTD_G|
+				   TSTD_H|
+				   TSTD_I|
+				   TSTD_K|TSTD_K1|
+				   TSTD_L|
+				   V4L2_STD_SECAM_LC |
+				   TSTD_N|TSTD_Nc),
+		.frameperiod    =
+		{
+			.numerator  = 1,
+			.denominator= 25
+		},
+		.framelines     = 625,
+		.reserved       = {0,0,0,0}
+	}, {
+		.id             = (TSTD_M|
+				   V4L2_STD_NTSC_M_JP|
+				   V4L2_STD_NTSC_M_KR),
+		.frameperiod    =
+		{
+			.numerator  = 1001,
+			.denominator= 30000
+		},
+		.framelines     = 525,
+		.reserved       = {0,0,0,0}
+	}, { // This is a total wild guess
+		.id             = (TSTD_60),
+		.frameperiod    =
+		{
+			.numerator  = 1001,
+			.denominator= 30000
+		},
+		.framelines     = 525,
+		.reserved       = {0,0,0,0}
+	}, { // This is total wild guess
+		.id             = V4L2_STD_NTSC_443,
+		.frameperiod    =
+		{
+			.numerator  = 1001,
+			.denominator= 30000
+		},
+		.framelines     = 525,
+		.reserved       = {0,0,0,0}
+	}
+};
+
+#define generic_standards_cnt (sizeof(generic_standards)/sizeof(generic_standards[0]))
+
+static struct v4l2_standard *match_std(v4l2_std_id id)
+{
+	unsigned int idx;
+	for (idx = 0; idx < generic_standards_cnt; idx++) {
+		if (generic_standards[idx].id & id) {
+			return generic_standards + idx;
+		}
+	}
+	return 0;
+}
+
+static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
+{
+	struct v4l2_standard *template;
+	int idx;
+	unsigned int bcnt;
+	template = match_std(id);
+	if (!template) return 0;
+	idx = std->index;
+	memcpy(std,template,sizeof(*template));
+	std->index = idx;
+	std->id = id;
+	bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
+	std->name[bcnt] = 0;
+	pvr2_trace(PVR2_TRACE_INIT,"Set up standard idx=%u name=%s",
+		   std->index,std->name);
+	return !0;
+}
+
+/* These are special cases of combined standards that we should enumerate
+   separately if the component pieces are present. */
+static v4l2_std_id std_mixes[] = {
+	V4L2_STD_PAL_B | V4L2_STD_PAL_G,
+	V4L2_STD_PAL_D | V4L2_STD_PAL_K,
+	V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
+	V4L2_STD_SECAM_D | V4L2_STD_SECAM_K,
+};
+
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+					   v4l2_std_id id)
+{
+	unsigned int std_cnt = 0;
+	unsigned int idx,bcnt,idx2;
+	v4l2_std_id idmsk,cmsk,fmsk;
+	struct v4l2_standard *stddefs;
+
+	if (pvrusb2_debug & PVR2_TRACE_INIT) {
+		char buf[50];
+		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
+		pvr2_trace(
+			PVR2_TRACE_INIT,"Mapping standards mask=0x%x (%.*s)",
+			(int)id,bcnt,buf);
+	}
+
+	*countptr = 0;
+	std_cnt = 0;
+	fmsk = 0;
+	for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) {
+		if (!(idmsk & cmsk)) continue;
+		cmsk &= ~idmsk;
+		if (match_std(idmsk)) {
+			std_cnt++;
+			continue;
+		}
+		fmsk |= idmsk;
+	}
+
+	for (idx2 = 0; idx2 < sizeof(std_mixes)/sizeof(std_mixes[0]); idx2++) {
+		if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
+	}
+
+	if (fmsk) {
+		char buf[50];
+		bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"WARNING:"
+			" Failed to classify the following standard(s): %.*s",
+			bcnt,buf);
+	}
+
+	pvr2_trace(PVR2_TRACE_INIT,"Setting up %u unique standard(s)",
+		   std_cnt);
+	if (!std_cnt) return 0; // paranoia
+
+	stddefs = kmalloc(sizeof(struct v4l2_standard) * std_cnt,
+			  GFP_KERNEL);
+	memset(stddefs,0,sizeof(struct v4l2_standard) * std_cnt);
+	for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx;
+
+	idx = 0;
+
+	/* Enumerate potential special cases */
+	for (idx2 = 0; ((idx2 < sizeof(std_mixes)/sizeof(std_mixes[0])) &&
+			(idx < std_cnt)); idx2++) {
+		if (!(id & std_mixes[idx2])) continue;
+		if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
+	}
+	/* Now enumerate individual pieces */
+	for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) {
+		if (!(idmsk & cmsk)) continue;
+		cmsk &= ~idmsk;
+		if (!pvr2_std_fill(stddefs+idx,idmsk)) continue;
+		idx++;
+	}
+
+	*countptr = std_cnt;
+	return stddefs;
+}
+
+v4l2_std_id pvr2_std_get_usable(void)
+{
+	return CSTD_ALL;
+}
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.h b/drivers/media/video/pvrusb2/pvrusb2-std.h
new file mode 100644
index 0000000..07c3993
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-std.h
@@ -0,0 +1,60 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_STD_H
+#define __PVRUSB2_STD_H
+
+#include <linux/videodev2.h>
+
+// Convert string describing one or more video standards into a mask of V4L
+// standard bits.  Return true if conversion succeeds otherwise return
+// false.  String is expected to be of the form: C1-x/y;C2-a/b where C1 and
+// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are
+// modulation schemes (e.g. "M", "B", "G", etc).
+int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
+		       unsigned int bufSize);
+
+// Convert any arbitrary set of video standard bits into an unambiguous
+// readable string.  Return value is the number of bytes consumed in the
+// buffer.  The formatted string is of a form that can be parsed by our
+// sibling std_std_to_id() function.
+unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
+				v4l2_std_id id);
+
+// Create an array of suitable v4l2_standard structures given a bit mask of
+// video standards to support.  The array is allocated from the heap, and
+// the number of elements is returned in the first argument.
+struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
+					   v4l2_std_id id);
+
+// Return mask of which video standard bits are valid
+v4l2_std_id pvr2_std_get_usable(void);
+
+#endif /* __PVRUSB2_STD_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
new file mode 100644
index 0000000..c6e6523
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
@@ -0,0 +1,865 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/semaphore.h>
+#include "pvrusb2-sysfs.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2-debug.h"
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+#include "pvrusb2-debugifc.h"
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__)
+
+struct pvr2_sysfs {
+	struct pvr2_channel channel;
+	struct class_device *class_dev;
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+	struct pvr2_sysfs_debugifc *debugifc;
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+	struct pvr2_sysfs_ctl_item *item_first;
+	struct pvr2_sysfs_ctl_item *item_last;
+	struct sysfs_ops kops;
+	struct kobj_type ktype;
+	struct class_device_attribute attr_v4l_minor_number;
+	struct class_device_attribute attr_unit_number;
+};
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+struct pvr2_sysfs_debugifc {
+	struct class_device_attribute attr_debugcmd;
+	struct class_device_attribute attr_debuginfo;
+};
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+struct pvr2_sysfs_ctl_item {
+	struct class_device_attribute attr_name;
+	struct class_device_attribute attr_type;
+	struct class_device_attribute attr_min;
+	struct class_device_attribute attr_max;
+	struct class_device_attribute attr_enum;
+	struct class_device_attribute attr_bits;
+	struct class_device_attribute attr_val;
+	struct class_device_attribute attr_custom;
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *chptr;
+	struct pvr2_sysfs_ctl_item *item_next;
+	struct attribute *attr_gen[7];
+	struct attribute_group grp;
+	char name[80];
+};
+
+struct pvr2_sysfs_class {
+	struct class class;
+};
+
+static ssize_t show_name(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	const char *name;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+
+	name = pvr2_ctrl_get_desc(cptr);
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name);
+
+	if (!name) return -EINVAL;
+
+	return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+}
+
+static ssize_t show_type(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	const char *name;
+	enum pvr2_ctl_type tp;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+
+	tp = pvr2_ctrl_get_type(cptr);
+	switch (tp) {
+	case pvr2_ctl_int: name = "integer"; break;
+	case pvr2_ctl_enum: name = "enum"; break;
+	case pvr2_ctl_bitmask: name = "bitmask"; break;
+	case pvr2_ctl_bool: name = "boolean"; break;
+	default: name = "?"; break;
+	}
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name);
+
+	if (!name) return -EINVAL;
+
+	return scnprintf(buf,PAGE_SIZE,"%s\n",name);
+}
+
+static ssize_t show_min(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	long val;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+	val = pvr2_ctrl_get_min(cptr);
+
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val);
+
+	return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+}
+
+static ssize_t show_max(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	long val;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+	val = pvr2_ctrl_get_max(cptr);
+
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val);
+
+	return scnprintf(buf,PAGE_SIZE,"%ld\n",val);
+}
+
+static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	int val,ret;
+	unsigned int cnt = 0;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+
+	ret = pvr2_ctrl_get_value(cptr,&val);
+	if (ret < 0) return ret;
+
+	ret = pvr2_ctrl_value_to_sym(cptr,~0,val,
+				     buf,PAGE_SIZE-1,&cnt);
+
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)",
+			 sfp,id,cnt,buf,val);
+	buf[cnt] = '\n';
+	return cnt+1;
+}
+
+static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	int val,ret;
+	unsigned int cnt = 0;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+
+	ret = pvr2_ctrl_get_value(cptr,&val);
+	if (ret < 0) return ret;
+
+	ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val,
+					    buf,PAGE_SIZE-1,&cnt);
+
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)",
+			 sfp,id,cnt,buf,val);
+	buf[cnt] = '\n';
+	return cnt+1;
+}
+
+static ssize_t show_enum(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	long val;
+	unsigned int bcnt,ccnt,ecnt;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+	ecnt = pvr2_ctrl_get_cnt(cptr);
+	bcnt = 0;
+	for (val = 0; val < ecnt; val++) {
+		pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+		if (!ccnt) continue;
+		bcnt += ccnt;
+		if (bcnt >= PAGE_SIZE) break;
+		buf[bcnt] = '\n';
+		bcnt++;
+	}
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id);
+	return bcnt;
+}
+
+static ssize_t show_bits(int id,struct class_device *class_dev,char *buf)
+{
+	struct pvr2_ctrl *cptr;
+	struct pvr2_sysfs *sfp;
+	int valid_bits,msk;
+	unsigned int bcnt,ccnt;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (!cptr) return -EINVAL;
+	valid_bits = pvr2_ctrl_get_mask(cptr);
+	bcnt = 0;
+	for (msk = 1; valid_bits; msk <<= 1) {
+		if (!(msk & valid_bits)) continue;
+		valid_bits &= ~msk;
+		pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt);
+		bcnt += ccnt;
+		if (bcnt >= PAGE_SIZE) break;
+		buf[bcnt] = '\n';
+		bcnt++;
+	}
+	pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id);
+	return bcnt;
+}
+
+static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp,
+			 const char *buf,unsigned int count)
+{
+	struct pvr2_ctrl *cptr;
+	int ret;
+	int mask,val;
+
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id);
+	if (customfl) {
+		ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val);
+	} else {
+		ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val);
+	}
+	if (ret < 0) return ret;
+	ret = pvr2_ctrl_set_mask_value(cptr,mask,val);
+	pvr2_hdw_commit_ctl(sfp->channel.hdw);
+	return ret;
+}
+
+static ssize_t store_val_norm(int id,struct class_device *class_dev,
+			     const char *buf,size_t count)
+{
+	struct pvr2_sysfs *sfp;
+	int ret;
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	ret = store_val_any(id,0,sfp,buf,count);
+	if (!ret) ret = count;
+	return ret;
+}
+
+static ssize_t store_val_custom(int id,struct class_device *class_dev,
+				const char *buf,size_t count)
+{
+	struct pvr2_sysfs *sfp;
+	int ret;
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	ret = store_val_any(id,1,sfp,buf,count);
+	if (!ret) ret = count;
+	return ret;
+}
+
+/*
+  Mike Isely <isely@pobox.com> 30-April-2005
+
+  This next batch of horrible preprocessor hackery is needed because the
+  kernel's class_device_attribute mechanism fails to pass the actual
+  attribute through to the show / store functions, which means we have no
+  way to package up any attribute-specific parameters, like for example the
+  control id.  So we work around this brain-damage by encoding the control
+  id into the show / store functions themselves and pick the function based
+  on the control id we're setting up.  These macros try to ease the pain.
+  Yuck.
+*/
+
+#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \
+static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,char *buf) \
+{ return sf_name(ctl_id,class_dev,buf); }
+
+#define CREATE_STORE_INSTANCE(sf_name,ctl_id) \
+static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf,size_t count) \
+{ return sf_name(ctl_id,class_dev,buf,count); }
+
+#define CREATE_BATCH(ctl_id) \
+CREATE_SHOW_INSTANCE(show_name,ctl_id) \
+CREATE_SHOW_INSTANCE(show_type,ctl_id) \
+CREATE_SHOW_INSTANCE(show_min,ctl_id) \
+CREATE_SHOW_INSTANCE(show_max,ctl_id) \
+CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \
+CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \
+CREATE_SHOW_INSTANCE(show_enum,ctl_id) \
+CREATE_SHOW_INSTANCE(show_bits,ctl_id) \
+CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \
+CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \
+
+CREATE_BATCH(0)
+CREATE_BATCH(1)
+CREATE_BATCH(2)
+CREATE_BATCH(3)
+CREATE_BATCH(4)
+CREATE_BATCH(5)
+CREATE_BATCH(6)
+CREATE_BATCH(7)
+CREATE_BATCH(8)
+CREATE_BATCH(9)
+CREATE_BATCH(10)
+CREATE_BATCH(11)
+CREATE_BATCH(12)
+CREATE_BATCH(13)
+CREATE_BATCH(14)
+CREATE_BATCH(15)
+CREATE_BATCH(16)
+CREATE_BATCH(17)
+CREATE_BATCH(18)
+CREATE_BATCH(19)
+CREATE_BATCH(20)
+CREATE_BATCH(21)
+CREATE_BATCH(22)
+CREATE_BATCH(23)
+CREATE_BATCH(24)
+CREATE_BATCH(25)
+CREATE_BATCH(26)
+CREATE_BATCH(27)
+CREATE_BATCH(28)
+CREATE_BATCH(29)
+CREATE_BATCH(30)
+CREATE_BATCH(31)
+CREATE_BATCH(32)
+CREATE_BATCH(33)
+CREATE_BATCH(34)
+CREATE_BATCH(35)
+CREATE_BATCH(36)
+CREATE_BATCH(37)
+CREATE_BATCH(38)
+CREATE_BATCH(39)
+CREATE_BATCH(40)
+CREATE_BATCH(41)
+CREATE_BATCH(42)
+CREATE_BATCH(43)
+CREATE_BATCH(44)
+CREATE_BATCH(45)
+CREATE_BATCH(46)
+CREATE_BATCH(47)
+CREATE_BATCH(48)
+CREATE_BATCH(49)
+CREATE_BATCH(50)
+CREATE_BATCH(51)
+CREATE_BATCH(52)
+CREATE_BATCH(53)
+CREATE_BATCH(54)
+CREATE_BATCH(55)
+CREATE_BATCH(56)
+CREATE_BATCH(57)
+CREATE_BATCH(58)
+CREATE_BATCH(59)
+
+struct pvr2_sysfs_func_set {
+	ssize_t (*show_name)(struct class_device *,char *);
+	ssize_t (*show_type)(struct class_device *,char *);
+	ssize_t (*show_min)(struct class_device *,char *);
+	ssize_t (*show_max)(struct class_device *,char *);
+	ssize_t (*show_enum)(struct class_device *,char *);
+	ssize_t (*show_bits)(struct class_device *,char *);
+	ssize_t (*show_val_norm)(struct class_device *,char *);
+	ssize_t (*store_val_norm)(struct class_device *,
+				  const char *,size_t);
+	ssize_t (*show_val_custom)(struct class_device *,char *);
+	ssize_t (*store_val_custom)(struct class_device *,
+				    const char *,size_t);
+};
+
+#define INIT_BATCH(ctl_id) \
+[ctl_id] = { \
+    .show_name = show_name_##ctl_id, \
+    .show_type = show_type_##ctl_id, \
+    .show_min = show_min_##ctl_id, \
+    .show_max = show_max_##ctl_id, \
+    .show_enum = show_enum_##ctl_id, \
+    .show_bits = show_bits_##ctl_id, \
+    .show_val_norm = show_val_norm_##ctl_id, \
+    .store_val_norm = store_val_norm_##ctl_id, \
+    .show_val_custom = show_val_custom_##ctl_id, \
+    .store_val_custom = store_val_custom_##ctl_id, \
+} \
+
+static struct pvr2_sysfs_func_set funcs[] = {
+	INIT_BATCH(0),
+	INIT_BATCH(1),
+	INIT_BATCH(2),
+	INIT_BATCH(3),
+	INIT_BATCH(4),
+	INIT_BATCH(5),
+	INIT_BATCH(6),
+	INIT_BATCH(7),
+	INIT_BATCH(8),
+	INIT_BATCH(9),
+	INIT_BATCH(10),
+	INIT_BATCH(11),
+	INIT_BATCH(12),
+	INIT_BATCH(13),
+	INIT_BATCH(14),
+	INIT_BATCH(15),
+	INIT_BATCH(16),
+	INIT_BATCH(17),
+	INIT_BATCH(18),
+	INIT_BATCH(19),
+	INIT_BATCH(20),
+	INIT_BATCH(21),
+	INIT_BATCH(22),
+	INIT_BATCH(23),
+	INIT_BATCH(24),
+	INIT_BATCH(25),
+	INIT_BATCH(26),
+	INIT_BATCH(27),
+	INIT_BATCH(28),
+	INIT_BATCH(29),
+	INIT_BATCH(30),
+	INIT_BATCH(31),
+	INIT_BATCH(32),
+	INIT_BATCH(33),
+	INIT_BATCH(34),
+	INIT_BATCH(35),
+	INIT_BATCH(36),
+	INIT_BATCH(37),
+	INIT_BATCH(38),
+	INIT_BATCH(39),
+	INIT_BATCH(40),
+	INIT_BATCH(41),
+	INIT_BATCH(42),
+	INIT_BATCH(43),
+	INIT_BATCH(44),
+	INIT_BATCH(45),
+	INIT_BATCH(46),
+	INIT_BATCH(47),
+	INIT_BATCH(48),
+	INIT_BATCH(49),
+	INIT_BATCH(50),
+	INIT_BATCH(51),
+	INIT_BATCH(52),
+	INIT_BATCH(53),
+	INIT_BATCH(54),
+	INIT_BATCH(55),
+	INIT_BATCH(56),
+	INIT_BATCH(57),
+	INIT_BATCH(58),
+	INIT_BATCH(59),
+};
+
+
+static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id)
+{
+	struct pvr2_sysfs_ctl_item *cip;
+	struct pvr2_sysfs_func_set *fp;
+	struct pvr2_ctrl *cptr;
+	unsigned int cnt,acnt;
+
+	if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) {
+		return;
+	}
+
+	fp = funcs + ctl_id;
+	cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id);
+	if (!cptr) return;
+
+	cip = kmalloc(sizeof(*cip),GFP_KERNEL);
+	if (!cip) return;
+	memset(cip,0,sizeof(*cip));
+	pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip);
+
+	cip->cptr = cptr;
+
+	cip->chptr = sfp;
+	cip->item_next = 0;
+	if (sfp->item_last) {
+		sfp->item_last->item_next = cip;
+	} else {
+		sfp->item_first = cip;
+	}
+	sfp->item_last = cip;
+
+	cip->attr_name.attr.owner = THIS_MODULE;
+	cip->attr_name.attr.name = "name";
+	cip->attr_name.attr.mode = S_IRUGO;
+	cip->attr_name.show = fp->show_name;
+
+	cip->attr_type.attr.owner = THIS_MODULE;
+	cip->attr_type.attr.name = "type";
+	cip->attr_type.attr.mode = S_IRUGO;
+	cip->attr_type.show = fp->show_type;
+
+	cip->attr_min.attr.owner = THIS_MODULE;
+	cip->attr_min.attr.name = "min_val";
+	cip->attr_min.attr.mode = S_IRUGO;
+	cip->attr_min.show = fp->show_min;
+
+	cip->attr_max.attr.owner = THIS_MODULE;
+	cip->attr_max.attr.name = "max_val";
+	cip->attr_max.attr.mode = S_IRUGO;
+	cip->attr_max.show = fp->show_max;
+
+	cip->attr_val.attr.owner = THIS_MODULE;
+	cip->attr_val.attr.name = "cur_val";
+	cip->attr_val.attr.mode = S_IRUGO;
+
+	cip->attr_custom.attr.owner = THIS_MODULE;
+	cip->attr_custom.attr.name = "custom_val";
+	cip->attr_custom.attr.mode = S_IRUGO;
+
+	cip->attr_enum.attr.owner = THIS_MODULE;
+	cip->attr_enum.attr.name = "enum_val";
+	cip->attr_enum.attr.mode = S_IRUGO;
+	cip->attr_enum.show = fp->show_enum;
+
+	cip->attr_bits.attr.owner = THIS_MODULE;
+	cip->attr_bits.attr.name = "bit_val";
+	cip->attr_bits.attr.mode = S_IRUGO;
+	cip->attr_bits.show = fp->show_bits;
+
+	if (pvr2_ctrl_is_writable(cptr)) {
+		cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP;
+		cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP;
+	}
+
+	acnt = 0;
+	cip->attr_gen[acnt++] = &cip->attr_name.attr;
+	cip->attr_gen[acnt++] = &cip->attr_type.attr;
+	cip->attr_gen[acnt++] = &cip->attr_val.attr;
+	cip->attr_val.show = fp->show_val_norm;
+	cip->attr_val.store = fp->store_val_norm;
+	if (pvr2_ctrl_has_custom_symbols(cptr)) {
+		cip->attr_gen[acnt++] = &cip->attr_custom.attr;
+		cip->attr_custom.show = fp->show_val_custom;
+		cip->attr_custom.store = fp->store_val_custom;
+	}
+	switch (pvr2_ctrl_get_type(cptr)) {
+	case pvr2_ctl_enum:
+		// Control is an enumeration
+		cip->attr_gen[acnt++] = &cip->attr_enum.attr;
+		break;
+	case pvr2_ctl_int:
+		// Control is an integer
+		cip->attr_gen[acnt++] = &cip->attr_min.attr;
+		cip->attr_gen[acnt++] = &cip->attr_max.attr;
+		break;
+	case pvr2_ctl_bitmask:
+		// Control is an bitmask
+		cip->attr_gen[acnt++] = &cip->attr_bits.attr;
+		break;
+	default: break;
+	}
+
+	cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s",
+			pvr2_ctrl_get_name(cptr));
+	cip->name[cnt] = 0;
+	cip->grp.name = cip->name;
+	cip->grp.attrs = cip->attr_gen;
+
+	sysfs_create_group(&sfp->class_dev->kobj,&cip->grp);
+}
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+static ssize_t debuginfo_show(struct class_device *,char *);
+static ssize_t debugcmd_show(struct class_device *,char *);
+static ssize_t debugcmd_store(struct class_device *,const char *,size_t count);
+
+static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp)
+{
+	struct pvr2_sysfs_debugifc *dip;
+	dip = kmalloc(sizeof(*dip),GFP_KERNEL);
+	if (!dip) return;
+	memset(dip,0,sizeof(*dip));
+	dip->attr_debugcmd.attr.owner = THIS_MODULE;
+	dip->attr_debugcmd.attr.name = "debugcmd";
+	dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP;
+	dip->attr_debugcmd.show = debugcmd_show;
+	dip->attr_debugcmd.store = debugcmd_store;
+	dip->attr_debuginfo.attr.owner = THIS_MODULE;
+	dip->attr_debuginfo.attr.name = "debuginfo";
+	dip->attr_debuginfo.attr.mode = S_IRUGO;
+	dip->attr_debuginfo.show = debuginfo_show;
+	sfp->debugifc = dip;
+	class_device_create_file(sfp->class_dev,&dip->attr_debugcmd);
+	class_device_create_file(sfp->class_dev,&dip->attr_debuginfo);
+}
+
+
+static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp)
+{
+	if (!sfp->debugifc) return;
+	class_device_remove_file(sfp->class_dev,
+				 &sfp->debugifc->attr_debuginfo);
+	class_device_remove_file(sfp->class_dev,&sfp->debugifc->attr_debugcmd);
+	kfree(sfp->debugifc);
+	sfp->debugifc = 0;
+}
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+
+static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp)
+{
+	unsigned int idx,cnt;
+	cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw);
+	for (idx = 0; idx < cnt; idx++) {
+		pvr2_sysfs_add_control(sfp,idx);
+	}
+}
+
+
+static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp)
+{
+	struct pvr2_sysfs_ctl_item *cip1,*cip2;
+	for (cip1 = sfp->item_first; cip1; cip1 = cip2) {
+		cip2 = cip1->item_next;
+		sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp);
+		pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1);
+		kfree(cip1);
+	}
+}
+
+
+static void pvr2_sysfs_class_release(struct class *class)
+{
+	struct pvr2_sysfs_class *clp;
+	clp = container_of(class,struct pvr2_sysfs_class,class);
+	pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp);
+	kfree(clp);
+}
+
+
+static void pvr2_sysfs_release(struct class_device *class_dev)
+{
+	pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev);
+	kfree(class_dev);
+}
+
+
+static void class_dev_destroy(struct pvr2_sysfs *sfp)
+{
+	if (!sfp->class_dev) return;
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+	pvr2_sysfs_tear_down_debugifc(sfp);
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+	pvr2_sysfs_tear_down_controls(sfp);
+	class_device_remove_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
+	class_device_remove_file(sfp->class_dev,&sfp->attr_unit_number);
+	pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev);
+	sfp->class_dev->class_data = 0;
+	class_device_unregister(sfp->class_dev);
+	sfp->class_dev = 0;
+}
+
+
+static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf)
+{
+	struct pvr2_sysfs *sfp;
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	return scnprintf(buf,PAGE_SIZE,"%d\n",
+			 pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw));
+}
+
+
+static ssize_t unit_number_show(struct class_device *class_dev,char *buf)
+{
+	struct pvr2_sysfs *sfp;
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	return scnprintf(buf,PAGE_SIZE,"%d\n",
+			 pvr2_hdw_get_unit_number(sfp->channel.hdw));
+}
+
+
+static void class_dev_create(struct pvr2_sysfs *sfp,
+			     struct pvr2_sysfs_class *class_ptr)
+{
+	struct usb_device *usb_dev;
+	struct class_device *class_dev;
+	usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw);
+	if (!usb_dev) return;
+	class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL);
+	if (!class_dev) return;
+	memset(class_dev,0,sizeof(*class_dev));
+
+	pvr2_sysfs_trace("Creating class_dev id=%p",class_dev);
+
+	class_dev->class = &class_ptr->class;
+	if (pvr2_hdw_get_sn(sfp->channel.hdw)) {
+		snprintf(class_dev->class_id,BUS_ID_SIZE,"sn-%lu",
+			 pvr2_hdw_get_sn(sfp->channel.hdw));
+	} else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) {
+		snprintf(class_dev->class_id,BUS_ID_SIZE,"unit-%c",
+			 pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a');
+	} else {
+		kfree(class_dev);
+		return;
+	}
+
+	class_dev->dev = &usb_dev->dev;
+
+	sfp->class_dev = class_dev;
+	class_dev->class_data = sfp;
+	class_device_register(class_dev);
+
+	sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE;
+	sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number";
+	sfp->attr_v4l_minor_number.attr.mode = S_IRUGO;
+	sfp->attr_v4l_minor_number.show = v4l_minor_number_show;
+	sfp->attr_v4l_minor_number.store = 0;
+	class_device_create_file(sfp->class_dev,&sfp->attr_v4l_minor_number);
+	sfp->attr_unit_number.attr.owner = THIS_MODULE;
+	sfp->attr_unit_number.attr.name = "unit_number";
+	sfp->attr_unit_number.attr.mode = S_IRUGO;
+	sfp->attr_unit_number.show = unit_number_show;
+	sfp->attr_unit_number.store = 0;
+	class_device_create_file(sfp->class_dev,&sfp->attr_unit_number);
+
+	pvr2_sysfs_add_controls(sfp);
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+	pvr2_sysfs_add_debugifc(sfp);
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+}
+
+
+static void pvr2_sysfs_internal_check(struct pvr2_channel *chp)
+{
+	struct pvr2_sysfs *sfp;
+	sfp = container_of(chp,struct pvr2_sysfs,channel);
+	if (!sfp->channel.mc_head->disconnect_flag) return;
+	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp);
+	class_dev_destroy(sfp);
+	pvr2_channel_done(&sfp->channel);
+	kfree(sfp);
+}
+
+
+struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp,
+				     struct pvr2_sysfs_class *class_ptr)
+{
+	struct pvr2_sysfs *sfp;
+	sfp = kmalloc(sizeof(*sfp),GFP_KERNEL);
+	if (!sfp) return sfp;
+	memset(sfp,0,sizeof(*sfp));
+	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp);
+	pvr2_channel_init(&sfp->channel,mp);
+	sfp->channel.check_func = pvr2_sysfs_internal_check;
+
+	class_dev_create(sfp,class_ptr);
+	return sfp;
+}
+
+
+static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp,
+			      int numenvp,char *buf,int size)
+{
+	/* Even though we don't do anything here, we still need this function
+	   because sysfs will still try to call it. */
+	return 0;
+}
+
+struct pvr2_sysfs_class *pvr2_sysfs_class_create(void)
+{
+	struct pvr2_sysfs_class *clp;
+	clp = kmalloc(sizeof(*clp),GFP_KERNEL);
+	if (!clp) return clp;
+	memset(clp,0,sizeof(*clp));
+	pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp);
+	clp->class.name = "pvrusb2";
+	clp->class.class_release = pvr2_sysfs_class_release;
+	clp->class.release = pvr2_sysfs_release;
+	clp->class.uevent = pvr2_sysfs_hotplug;
+	if (class_register(&clp->class)) {
+		pvr2_sysfs_trace(
+			"Registration failed for pvr2_sysfs_class id=%p",clp);
+		kfree(clp);
+		clp = 0;
+	}
+	return clp;
+}
+
+
+void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp)
+{
+	class_unregister(&clp->class);
+}
+
+
+#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC
+static ssize_t debuginfo_show(struct class_device *class_dev,char *buf)
+{
+	struct pvr2_sysfs *sfp;
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	pvr2_hdw_trigger_module_log(sfp->channel.hdw);
+	return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE);
+}
+
+
+static ssize_t debugcmd_show(struct class_device *class_dev,char *buf)
+{
+	struct pvr2_sysfs *sfp;
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+	return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE);
+}
+
+
+static ssize_t debugcmd_store(struct class_device *class_dev,
+			      const char *buf,size_t count)
+{
+	struct pvr2_sysfs *sfp;
+	int ret;
+
+	sfp = (struct pvr2_sysfs *)class_dev->class_data;
+	if (!sfp) return -EINVAL;
+
+	ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count);
+	if (ret < 0) return ret;
+	return count;
+}
+#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
new file mode 100644
index 0000000..ff9373b
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h
@@ -0,0 +1,47 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_SYSFS_H
+#define __PVRUSB2_SYSFS_H
+
+#include <linux/list.h>
+#include <linux/sysfs.h>
+#include "pvrusb2-context.h"
+
+struct pvr2_sysfs;
+struct pvr2_sysfs_class;
+
+struct pvr2_sysfs_class *pvr2_sysfs_class_create(void);
+void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *);
+
+struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *,
+				     struct pvr2_sysfs_class *);
+
+#endif /* __PVRUSB2_SYSFS_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
new file mode 100644
index 0000000..f4aba81
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.c
@@ -0,0 +1,122 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "pvrusb2.h"
+#include "pvrusb2-util.h"
+#include "pvrusb2-tuner.h"
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/tuner.h>
+#include <media/v4l2-common.h>
+
+struct pvr2_tuner_handler {
+	struct pvr2_hdw *hdw;
+	struct pvr2_i2c_client *client;
+	struct pvr2_i2c_handler i2c_handler;
+	int type_update_fl;
+};
+
+
+static void set_type(struct pvr2_tuner_handler *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	struct tuner_setup setup;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type);
+	if (((int)(hdw->tuner_type)) < 0) return;
+
+	setup.addr = ADDR_UNSET;
+	setup.type = hdw->tuner_type;
+	setup.mode_mask = T_RADIO | T_ANALOG_TV;
+	/* We may really want mode_mask to be T_ANALOG_TV for now */
+	pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup);
+	ctxt->type_update_fl = 0;
+}
+
+
+static int tuner_check(struct pvr2_tuner_handler *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	if (hdw->tuner_updated) ctxt->type_update_fl = !0;
+	return ctxt->type_update_fl != 0;
+}
+
+
+static void tuner_update(struct pvr2_tuner_handler *ctxt)
+{
+	if (ctxt->type_update_fl) set_type(ctxt);
+}
+
+
+static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt)
+{
+	ctxt->client->handler = 0;
+	kfree(ctxt);
+}
+
+
+static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt)
+{
+	return scnprintf(buf,cnt,"handler: pvrusb2-tuner");
+}
+
+
+const static struct pvr2_i2c_handler_functions tuner_funcs = {
+	.detach = (void (*)(void *))pvr2_tuner_detach,
+	.check = (int (*)(void *))tuner_check,
+	.update = (void (*)(void *))tuner_update,
+	.describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe,
+};
+
+
+int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+	struct pvr2_tuner_handler *ctxt;
+	if (cp->handler) return 0;
+
+	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	if (!ctxt) return 0;
+	memset(ctxt,0,sizeof(*ctxt));
+
+	ctxt->i2c_handler.func_data = ctxt;
+	ctxt->i2c_handler.func_table = &tuner_funcs;
+	ctxt->type_update_fl = !0;
+	ctxt->client = cp;
+	ctxt->hdw = hdw;
+	cp->handler = &ctxt->i2c_handler;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up",
+		   cp->client->addr);
+	return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-tuner.h
new file mode 100644
index 0000000..556f12aa
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.h
@@ -0,0 +1,38 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_TUNER_H
+#define __PVRUSB2_TUNER_H
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+#endif /* __PVRUSB2_TUNER_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-util.h b/drivers/media/video/pvrusb2/pvrusb2-util.h
new file mode 100644
index 0000000..e53aee4
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-util.h
@@ -0,0 +1,63 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_UTIL_H
+#define __PVRUSB2_UTIL_H
+
+#define PVR2_DECOMPOSE_LE(t,i,d) \
+    do {    \
+	(t)[i] = (d) & 0xff;\
+	(t)[i+1] = ((d) >> 8) & 0xff;\
+	(t)[i+2] = ((d) >> 16) & 0xff;\
+	(t)[i+3] = ((d) >> 24) & 0xff;\
+    } while(0)
+
+#define PVR2_DECOMPOSE_BE(t,i,d) \
+    do {    \
+	(t)[i+3] = (d) & 0xff;\
+	(t)[i+2] = ((d) >> 8) & 0xff;\
+	(t)[i+1] = ((d) >> 16) & 0xff;\
+	(t)[i] = ((d) >> 24) & 0xff;\
+    } while(0)
+
+#define PVR2_COMPOSE_LE(t,i) \
+    ((((u32)((t)[i+3])) << 24) | \
+     (((u32)((t)[i+2])) << 16) | \
+     (((u32)((t)[i+1])) << 8) | \
+     ((u32)((t)[i])))
+
+#define PVR2_COMPOSE_BE(t,i) \
+    ((((u32)((t)[i])) << 24) | \
+     (((u32)((t)[i+1])) << 16) | \
+     (((u32)((t)[i+2])) << 8) | \
+     ((u32)((t)[i+3])))
+
+
+#endif /* __PVRUSB2_UTIL_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
new file mode 100644
index 0000000..9619510
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
@@ -0,0 +1,1126 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include "pvrusb2-context.h"
+#include "pvrusb2-hdw.h"
+#include "pvrusb2.h"
+#include "pvrusb2-debug.h"
+#include "pvrusb2-v4l2.h"
+#include "pvrusb2-ioread.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+
+struct pvr2_v4l2_dev;
+struct pvr2_v4l2_fh;
+struct pvr2_v4l2;
+
+/* V4L no longer provide the ability to set / get a private context pointer
+   (i.e. video_get_drvdata / video_set_drvdata), which means we have to
+   concoct our own context locating mechanism.  Supposedly this is intended
+   to simplify driver implementation.  It's not clear to me how that can
+   possibly be true.  Our solution here is to maintain a lookup table of
+   our context instances, indexed by the minor device number of the V4L
+   device.  See pvr2_v4l2_open() for some implications of this approach. */
+static struct pvr2_v4l2_dev *devices[256];
+static DEFINE_MUTEX(device_lock);
+
+struct pvr2_v4l2_dev {
+	struct pvr2_v4l2 *v4lp;
+	struct video_device *vdev;
+	struct pvr2_context_stream *stream;
+	int ctxt_idx;
+	enum pvr2_config config;
+};
+
+struct pvr2_v4l2_fh {
+	struct pvr2_channel channel;
+	struct pvr2_v4l2_dev *dev_info;
+	enum v4l2_priority prio;
+	struct pvr2_ioread *rhp;
+	struct file *file;
+	struct pvr2_v4l2 *vhead;
+	struct pvr2_v4l2_fh *vnext;
+	struct pvr2_v4l2_fh *vprev;
+	wait_queue_head_t wait_data;
+	int fw_mode_flag;
+};
+
+struct pvr2_v4l2 {
+	struct pvr2_channel channel;
+	struct pvr2_v4l2_fh *vfirst;
+	struct pvr2_v4l2_fh *vlast;
+
+	struct v4l2_prio_state prio;
+
+	/* streams */
+	struct pvr2_v4l2_dev video_dev;
+};
+
+static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
+module_param_array(video_nr, int, NULL, 0444);
+MODULE_PARM_DESC(video_nr, "Offset for device's minor");
+
+struct v4l2_capability pvr_capability ={
+	.driver         = "pvrusb2",
+	.card           = "Hauppauge WinTV pvr-usb2",
+	.bus_info       = "usb",
+	.version        = KERNEL_VERSION(0,8,0),
+	.capabilities   = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+			   V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
+			   V4L2_CAP_READWRITE),
+	.reserved       = {0,0,0,0}
+};
+
+static struct v4l2_tuner pvr_v4l2_tuners[]= {
+	{
+		.index      = 0,
+		.name       = "TV Tuner",
+		.type           = V4L2_TUNER_ANALOG_TV,
+		.capability     = (V4L2_TUNER_CAP_NORM |
+				   V4L2_TUNER_CAP_STEREO |
+				   V4L2_TUNER_CAP_LANG1 |
+				   V4L2_TUNER_CAP_LANG2),
+		.rangelow   = 0,
+		.rangehigh  = 0,
+		.rxsubchans     = V4L2_TUNER_SUB_STEREO,
+		.audmode        = V4L2_TUNER_MODE_STEREO,
+		.signal         = 0,
+		.afc            = 0,
+		.reserved       = {0,0,0,0}
+	}
+};
+
+struct v4l2_fmtdesc pvr_fmtdesc [] = {
+	{
+		.index          = 0,
+		.type           = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+		.flags          = V4L2_FMT_FLAG_COMPRESSED,
+		.description    = "MPEG1/2",
+		// This should really be V4L2_PIX_FMT_MPEG, but xawtv
+		// breaks when I do that.
+		.pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
+		.reserved       = { 0, 0, 0, 0 }
+	}
+};
+
+#define PVR_FORMAT_PIX  0
+#define PVR_FORMAT_VBI  1
+
+struct v4l2_format pvr_format [] = {
+	[PVR_FORMAT_PIX] = {
+		.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
+		.fmt    = {
+			.pix        = {
+				.width          = 720,
+				.height             = 576,
+				// This should really be V4L2_PIX_FMT_MPEG,
+				// but xawtv breaks when I do that.
+				.pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
+				.field          = V4L2_FIELD_INTERLACED,
+				.bytesperline   = 0,  // doesn't make sense
+						      // here
+				//FIXME : Don't know what to put here...
+				.sizeimage          = (32*1024),
+				.colorspace     = 0, // doesn't make sense here
+				.priv           = 0
+			}
+		}
+	},
+	[PVR_FORMAT_VBI] = {
+		.type   = V4L2_BUF_TYPE_VBI_CAPTURE,
+		.fmt    = {
+			.vbi        = {
+				.sampling_rate = 27000000,
+				.offset = 248,
+				.samples_per_line = 1443,
+				.sample_format = V4L2_PIX_FMT_GREY,
+				.start = { 0, 0 },
+				.count = { 0, 0 },
+				.flags = 0,
+				.reserved = { 0, 0 }
+			}
+		}
+	}
+};
+
+/*
+ * pvr_ioctl()
+ *
+ * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
+ *
+ */
+static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
+			      unsigned int cmd, void *arg)
+{
+	struct pvr2_v4l2_fh *fh = file->private_data;
+	struct pvr2_v4l2 *vp = fh->vhead;
+	struct pvr2_v4l2_dev *dev_info = fh->dev_info;
+	struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+	int ret = -EINVAL;
+
+	if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+		v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
+	}
+
+	if (!pvr2_hdw_dev_ok(hdw)) {
+		pvr2_trace(PVR2_TRACE_ERROR_LEGS,
+			   "ioctl failed - bad or no context");
+		return -EFAULT;
+	}
+
+	/* check priority */
+	switch (cmd) {
+	case VIDIOC_S_CTRL:
+	case VIDIOC_S_STD:
+	case VIDIOC_S_INPUT:
+	case VIDIOC_S_TUNER:
+	case VIDIOC_S_FREQUENCY:
+		ret = v4l2_prio_check(&vp->prio, &fh->prio);
+		if (ret)
+			return ret;
+	}
+
+	switch (cmd) {
+	case VIDIOC_QUERYCAP:
+	{
+		struct v4l2_capability *cap = arg;
+
+		memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
+
+		ret = 0;
+		break;
+	}
+
+	case VIDIOC_G_PRIORITY:
+	{
+		enum v4l2_priority *p = arg;
+
+		*p = v4l2_prio_max(&vp->prio);
+		ret = 0;
+		break;
+	}
+
+	case VIDIOC_S_PRIORITY:
+	{
+		enum v4l2_priority *prio = arg;
+
+		ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
+		break;
+	}
+
+	case VIDIOC_ENUMSTD:
+	{
+		struct v4l2_standard *vs = (struct v4l2_standard *)arg;
+		int idx = vs->index;
+		ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
+		break;
+	}
+
+	case VIDIOC_G_STD:
+	{
+		int val = 0;
+		ret = pvr2_ctrl_get_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
+		*(v4l2_std_id *)arg = val;
+		break;
+	}
+
+	case VIDIOC_S_STD:
+	{
+		ret = pvr2_ctrl_set_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
+			*(v4l2_std_id *)arg);
+		break;
+	}
+
+	case VIDIOC_ENUMINPUT:
+	{
+		struct pvr2_ctrl *cptr;
+		struct v4l2_input *vi = (struct v4l2_input *)arg;
+		struct v4l2_input tmp;
+		unsigned int cnt;
+
+		cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+
+		memset(&tmp,0,sizeof(tmp));
+		tmp.index = vi->index;
+		ret = 0;
+		switch (vi->index) {
+		case PVR2_CVAL_INPUT_TV:
+		case PVR2_CVAL_INPUT_RADIO:
+			tmp.type = V4L2_INPUT_TYPE_TUNER;
+			break;
+		case PVR2_CVAL_INPUT_SVIDEO:
+		case PVR2_CVAL_INPUT_COMPOSITE:
+			tmp.type = V4L2_INPUT_TYPE_CAMERA;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		if (ret < 0) break;
+
+		cnt = 0;
+		pvr2_ctrl_get_valname(cptr,vi->index,
+				      tmp.name,sizeof(tmp.name)-1,&cnt);
+		tmp.name[cnt] = 0;
+
+		/* Don't bother with audioset, since this driver currently
+		   always switches the audio whenever the video is
+		   switched. */
+
+		/* Handling std is a tougher problem.  It doesn't make
+		   sense in cases where a device might be multi-standard.
+		   We could just copy out the current value for the
+		   standard, but it can change over time.  For now just
+		   leave it zero. */
+
+		memcpy(vi, &tmp, sizeof(tmp));
+
+		ret = 0;
+		break;
+	}
+
+	case VIDIOC_G_INPUT:
+	{
+		struct pvr2_ctrl *cptr;
+		struct v4l2_input *vi = (struct v4l2_input *)arg;
+		int val;
+		cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
+		val = 0;
+		ret = pvr2_ctrl_get_value(cptr,&val);
+		vi->index = val;
+		break;
+	}
+
+	case VIDIOC_S_INPUT:
+	{
+		struct v4l2_input *vi = (struct v4l2_input *)arg;
+		ret = pvr2_ctrl_set_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
+			vi->index);
+		break;
+	}
+
+	case VIDIOC_ENUMAUDIO:
+	{
+		ret = -EINVAL;
+		break;
+	}
+
+	case VIDIOC_G_AUDIO:
+	{
+		ret = -EINVAL;
+		break;
+	}
+
+	case VIDIOC_S_AUDIO:
+	{
+		ret = -EINVAL;
+		break;
+	}
+	case VIDIOC_G_TUNER:
+	{
+		struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
+		unsigned int status_mask;
+		int val;
+		if (vt->index !=0) break;
+
+		status_mask = pvr2_hdw_get_signal_status(hdw);
+
+		memcpy(vt, &pvr_v4l2_tuners[vt->index],
+		       sizeof(struct v4l2_tuner));
+
+		vt->signal = 0;
+		if (status_mask & PVR2_SIGNAL_OK) {
+			if (status_mask & PVR2_SIGNAL_STEREO) {
+				vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
+			} else {
+				vt->rxsubchans = V4L2_TUNER_SUB_MONO;
+			}
+			if (status_mask & PVR2_SIGNAL_SAP) {
+				vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 |
+						   V4L2_TUNER_SUB_LANG2);
+			}
+			vt->signal = 65535;
+		}
+
+		val = 0;
+		ret = pvr2_ctrl_get_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
+			&val);
+		vt->audmode = val;
+		break;
+	}
+
+	case VIDIOC_S_TUNER:
+	{
+		struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
+
+		if (vt->index != 0)
+			break;
+
+		ret = pvr2_ctrl_set_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
+			vt->audmode);
+	}
+
+	case VIDIOC_S_FREQUENCY:
+	{
+		const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
+		ret = pvr2_ctrl_set_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
+			vf->frequency * 62500);
+		break;
+	}
+
+	case VIDIOC_G_FREQUENCY:
+	{
+		struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
+		int val = 0;
+		ret = pvr2_ctrl_get_value(
+			pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
+			&val);
+		val /= 62500;
+		vf->frequency = val;
+		break;
+	}
+
+	case VIDIOC_ENUM_FMT:
+	{
+		struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
+
+		/* Only one format is supported : mpeg.*/
+		if (fd->index != 0)
+			break;
+
+		memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
+		ret = 0;
+		break;
+	}
+
+	case VIDIOC_G_FMT:
+	{
+		struct v4l2_format *vf = (struct v4l2_format *)arg;
+		int val;
+		switch(vf->type) {
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+			memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
+			       sizeof(struct v4l2_format));
+			val = 0;
+			pvr2_ctrl_get_value(
+				pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
+				&val);
+			vf->fmt.pix.width = val;
+			val = 0;
+			pvr2_ctrl_get_value(
+				pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
+				&val);
+			vf->fmt.pix.height = val;
+			ret = 0;
+			break;
+		case V4L2_BUF_TYPE_VBI_CAPTURE:
+			// ????? Still need to figure out to do VBI correctly
+			ret = -EINVAL;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	}
+
+	case VIDIOC_TRY_FMT:
+	case VIDIOC_S_FMT:
+	{
+		struct v4l2_format *vf = (struct v4l2_format *)arg;
+
+		ret = 0;
+		switch(vf->type) {
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+			int h = vf->fmt.pix.height;
+			int w = vf->fmt.pix.width;
+
+			if (h < 200) {
+				h = 200;
+			} else if (h > 625) {
+				h = 625;
+			}
+			if (w < 320) {
+				w = 320;
+			} else if (w > 720) {
+				w = 720;
+			}
+
+			memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
+			       sizeof(struct v4l2_format));
+			vf->fmt.pix.width = w;
+			vf->fmt.pix.height = h;
+
+			if (cmd == VIDIOC_S_FMT) {
+				pvr2_ctrl_set_value(
+					pvr2_hdw_get_ctrl_by_id(hdw,
+								PVR2_CID_HRES),
+					vf->fmt.pix.width);
+				pvr2_ctrl_set_value(
+					pvr2_hdw_get_ctrl_by_id(hdw,
+								PVR2_CID_VRES),
+					vf->fmt.pix.height);
+			}
+		} break;
+		case V4L2_BUF_TYPE_VBI_CAPTURE:
+			// ????? Still need to figure out to do VBI correctly
+			ret = -EINVAL;
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	}
+
+	case VIDIOC_STREAMON:
+	{
+		ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
+		if (ret < 0) return ret;
+		ret = pvr2_hdw_set_streaming(hdw,!0);
+		break;
+	}
+
+	case VIDIOC_STREAMOFF:
+	{
+		ret = pvr2_hdw_set_streaming(hdw,0);
+		break;
+	}
+
+	case VIDIOC_QUERYCTRL:
+	{
+		struct pvr2_ctrl *cptr;
+		struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
+		ret = 0;
+		if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
+			cptr = pvr2_hdw_get_ctrl_nextv4l(
+				hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
+			if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
+		} else {
+			cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
+		}
+		if (!cptr) {
+			pvr2_trace(PVR2_TRACE_V4LIOCTL,
+				   "QUERYCTRL id=0x%x not implemented here",
+				   vc->id);
+			ret = -EINVAL;
+			break;
+		}
+
+		pvr2_trace(PVR2_TRACE_V4LIOCTL,
+			   "QUERYCTRL id=0x%x mapping name=%s (%s)",
+			   vc->id,pvr2_ctrl_get_name(cptr),
+			   pvr2_ctrl_get_desc(cptr));
+		strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
+		vc->flags = pvr2_ctrl_get_v4lflags(cptr);
+		vc->default_value = pvr2_ctrl_get_def(cptr);
+		switch (pvr2_ctrl_get_type(cptr)) {
+		case pvr2_ctl_enum:
+			vc->type = V4L2_CTRL_TYPE_MENU;
+			vc->minimum = 0;
+			vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
+			vc->step = 1;
+			break;
+		case pvr2_ctl_bool:
+			vc->type = V4L2_CTRL_TYPE_BOOLEAN;
+			vc->minimum = 0;
+			vc->maximum = 1;
+			vc->step = 1;
+			break;
+		case pvr2_ctl_int:
+			vc->type = V4L2_CTRL_TYPE_INTEGER;
+			vc->minimum = pvr2_ctrl_get_min(cptr);
+			vc->maximum = pvr2_ctrl_get_max(cptr);
+			vc->step = 1;
+			break;
+		default:
+			pvr2_trace(PVR2_TRACE_V4LIOCTL,
+				   "QUERYCTRL id=0x%x name=%s not mappable",
+				   vc->id,pvr2_ctrl_get_name(cptr));
+			ret = -EINVAL;
+			break;
+		}
+		break;
+	}
+
+	case VIDIOC_QUERYMENU:
+	{
+		struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
+		unsigned int cnt = 0;
+		ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
+					    vm->index,
+					    vm->name,sizeof(vm->name)-1,
+					    &cnt);
+		vm->name[cnt] = 0;
+		break;
+	}
+
+	case VIDIOC_G_CTRL:
+	{
+		struct v4l2_control *vc = (struct v4l2_control *)arg;
+		int val = 0;
+		ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
+					  &val);
+		vc->value = val;
+		break;
+	}
+
+	case VIDIOC_S_CTRL:
+	{
+		struct v4l2_control *vc = (struct v4l2_control *)arg;
+		ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
+					  vc->value);
+		break;
+	}
+
+	case VIDIOC_G_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctls =
+			(struct v4l2_ext_controls *)arg;
+		struct v4l2_ext_control *ctrl;
+		unsigned int idx;
+		int val;
+		for (idx = 0; idx < ctls->count; idx++) {
+			ctrl = ctls->controls + idx;
+			ret = pvr2_ctrl_get_value(
+				pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
+			if (ret) {
+				ctls->error_idx = idx;
+				break;
+			}
+			/* Ensure that if read as a 64 bit value, the user
+			   will still get a hopefully sane value */
+			ctrl->value64 = 0;
+			ctrl->value = val;
+		}
+		break;
+	}
+
+	case VIDIOC_S_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctls =
+			(struct v4l2_ext_controls *)arg;
+		struct v4l2_ext_control *ctrl;
+		unsigned int idx;
+		for (idx = 0; idx < ctls->count; idx++) {
+			ctrl = ctls->controls + idx;
+			ret = pvr2_ctrl_set_value(
+				pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
+				ctrl->value);
+			if (ret) {
+				ctls->error_idx = idx;
+				break;
+			}
+		}
+		break;
+	}
+
+	case VIDIOC_TRY_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *ctls =
+			(struct v4l2_ext_controls *)arg;
+		struct v4l2_ext_control *ctrl;
+		struct pvr2_ctrl *pctl;
+		unsigned int idx;
+		/* For the moment just validate that the requested control
+		   actually exists. */
+		for (idx = 0; idx < ctls->count; idx++) {
+			ctrl = ctls->controls + idx;
+			pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
+			if (!pctl) {
+				ret = -EINVAL;
+				ctls->error_idx = idx;
+				break;
+			}
+		}
+		break;
+	}
+
+	case VIDIOC_LOG_STATUS:
+	{
+		pvr2_hdw_trigger_module_log(hdw);
+		ret = 0;
+		break;
+	}
+
+	default :
+		ret = v4l_compat_translate_ioctl(inode,file,cmd,
+						 arg,pvr2_v4l2_do_ioctl);
+	}
+
+	pvr2_hdw_commit_ctl(hdw);
+
+	if (ret < 0) {
+		if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+			pvr2_trace(PVR2_TRACE_V4LIOCTL,
+				   "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
+		} else {
+			if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
+				pvr2_trace(PVR2_TRACE_V4LIOCTL,
+					   "pvr2_v4l2_do_ioctl failure, ret=%d"
+					   " command was:",ret);
+				v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
+						cmd);
+			}
+		}
+	} else {
+		pvr2_trace(PVR2_TRACE_V4LIOCTL,
+			   "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
+			   ret,ret);
+	}
+	return ret;
+}
+
+
+static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
+{
+	pvr2_trace(PVR2_TRACE_INIT,
+		   "unregistering device video%d [%s]",
+		   dip->vdev->minor,pvr2_config_get_name(dip->config));
+	if (dip->ctxt_idx >= 0) {
+		mutex_lock(&device_lock);
+		devices[dip->ctxt_idx] = NULL;
+		dip->ctxt_idx = -1;
+		mutex_unlock(&device_lock);
+	}
+	video_unregister_device(dip->vdev);
+}
+
+
+static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
+{
+	pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1);
+	pvr2_v4l2_dev_destroy(&vp->video_dev);
+
+	pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
+	pvr2_channel_done(&vp->channel);
+	kfree(vp);
+}
+
+
+void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
+{
+	struct pvr2_v4l2 *vp;
+	vp = container_of(chp,struct pvr2_v4l2,channel);
+	if (!vp->channel.mc_head->disconnect_flag) return;
+	if (vp->vfirst) return;
+	pvr2_v4l2_destroy_no_lock(vp);
+}
+
+
+int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
+		    unsigned int cmd, unsigned long arg)
+{
+
+/* Temporary hack : use ivtv api until a v4l2 one is available. */
+#define IVTV_IOC_G_CODEC        0xFFEE7703
+#define IVTV_IOC_S_CODEC        0xFFEE7704
+	if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
+	return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
+}
+
+
+int pvr2_v4l2_release(struct inode *inode, struct file *file)
+{
+	struct pvr2_v4l2_fh *fhp = file->private_data;
+	struct pvr2_v4l2 *vp = fhp->vhead;
+	struct pvr2_context *mp = fhp->vhead->channel.mc_head;
+
+	pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
+
+	if (fhp->rhp) {
+		struct pvr2_stream *sp;
+		struct pvr2_hdw *hdw;
+		hdw = fhp->channel.mc_head->hdw;
+		pvr2_hdw_set_streaming(hdw,0);
+		sp = pvr2_ioread_get_stream(fhp->rhp);
+		if (sp) pvr2_stream_set_callback(sp,0,0);
+		pvr2_ioread_destroy(fhp->rhp);
+		fhp->rhp = 0;
+	}
+	v4l2_prio_close(&vp->prio, &fhp->prio);
+	file->private_data = NULL;
+
+	pvr2_context_enter(mp); do {
+		if (fhp->vnext) {
+			fhp->vnext->vprev = fhp->vprev;
+		} else {
+			vp->vlast = fhp->vprev;
+		}
+		if (fhp->vprev) {
+			fhp->vprev->vnext = fhp->vnext;
+		} else {
+			vp->vfirst = fhp->vnext;
+		}
+		fhp->vnext = 0;
+		fhp->vprev = 0;
+		fhp->vhead = 0;
+		pvr2_channel_done(&fhp->channel);
+		pvr2_trace(PVR2_TRACE_STRUCT,
+			   "Destroying pvr_v4l2_fh id=%p",fhp);
+		kfree(fhp);
+		if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
+			pvr2_v4l2_destroy_no_lock(vp);
+		}
+	} while (0); pvr2_context_exit(mp);
+	return 0;
+}
+
+
+int pvr2_v4l2_open(struct inode *inode, struct file *file)
+{
+	struct pvr2_v4l2_dev *dip = 0; /* Our own context pointer */
+	struct pvr2_v4l2_fh *fhp;
+	struct pvr2_v4l2 *vp;
+	struct pvr2_hdw *hdw;
+
+	mutex_lock(&device_lock);
+	/* MCI 7-Jun-2006 Even though we're just doing what amounts to an
+	   atomic read of the device mapping array here, we still need the
+	   mutex.  The problem is that there is a tiny race possible when
+	   we register the device.  We can't update the device mapping
+	   array until after the device has been registered, owing to the
+	   fact that we can't know the minor device number until after the
+	   registration succeeds.  And if another thread tries to open the
+	   device in the window of time after registration but before the
+	   map is updated, then it will get back an erroneous null pointer
+	   and the open will result in a spurious failure.  The only way to
+	   prevent that is to (a) be inside the mutex here before we access
+	   the array, and (b) cover the entire registration process later
+	   on with this same mutex.  Thus if we get inside the mutex here,
+	   then we can be assured that the registration process actually
+	   completed correctly.  This is an unhappy complication from the
+	   use of global data in a driver that lives in a preemptible
+	   environment.  It sure would be nice if the video device itself
+	   had a means for storing and retrieving a local context pointer.
+	   Oh wait.  It did.  But now it's gone.  Silly me. */
+	{
+		unsigned int midx = iminor(file->f_dentry->d_inode);
+		if (midx < sizeof(devices)/sizeof(devices[0])) {
+			dip = devices[midx];
+		}
+	}
+	mutex_unlock(&device_lock);
+
+	if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */
+
+	vp = dip->v4lp;
+	hdw = vp->channel.hdw;
+
+	pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
+
+	if (!pvr2_hdw_dev_ok(hdw)) {
+		pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
+			   "pvr2_v4l2_open: hardware not ready");
+		return -EIO;
+	}
+
+	fhp = kmalloc(sizeof(*fhp),GFP_KERNEL);
+	if (!fhp) {
+		return -ENOMEM;
+	}
+	memset(fhp,0,sizeof(*fhp));
+
+	init_waitqueue_head(&fhp->wait_data);
+	fhp->dev_info = dip;
+
+	pvr2_context_enter(vp->channel.mc_head); do {
+		pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
+		pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
+		fhp->vnext = 0;
+		fhp->vprev = vp->vlast;
+		if (vp->vlast) {
+			vp->vlast->vnext = fhp;
+		} else {
+			vp->vfirst = fhp;
+		}
+		vp->vlast = fhp;
+		fhp->vhead = vp;
+	} while (0); pvr2_context_exit(vp->channel.mc_head);
+
+	fhp->file = file;
+	file->private_data = fhp;
+	v4l2_prio_open(&vp->prio,&fhp->prio);
+
+	fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
+
+	return 0;
+}
+
+
+static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
+{
+	wake_up(&fhp->wait_data);
+}
+
+static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
+{
+	int ret;
+	struct pvr2_stream *sp;
+	struct pvr2_hdw *hdw;
+	if (fh->rhp) return 0;
+
+	/* First read() attempt.  Try to claim the stream and start
+	   it... */
+	if ((ret = pvr2_channel_claim_stream(&fh->channel,
+					     fh->dev_info->stream)) != 0) {
+		/* Someone else must already have it */
+		return ret;
+	}
+
+	fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
+	if (!fh->rhp) {
+		pvr2_channel_claim_stream(&fh->channel,0);
+		return -ENOMEM;
+	}
+
+	hdw = fh->channel.mc_head->hdw;
+	sp = fh->dev_info->stream->stream;
+	pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
+	pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
+	pvr2_hdw_set_streaming(hdw,!0);
+	ret = pvr2_ioread_set_enabled(fh->rhp,!0);
+
+	return ret;
+}
+
+
+static ssize_t pvr2_v4l2_read(struct file *file,
+			      char __user *buff, size_t count, loff_t *ppos)
+{
+	struct pvr2_v4l2_fh *fh = file->private_data;
+	int ret;
+
+	if (fh->fw_mode_flag) {
+		struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
+		char *tbuf;
+		int c1,c2;
+		int tcnt = 0;
+		unsigned int offs = *ppos;
+
+		tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
+		if (!tbuf) return -ENOMEM;
+
+		while (count) {
+			c1 = count;
+			if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
+			c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
+			if (c2 < 0) {
+				tcnt = c2;
+				break;
+			}
+			if (!c2) break;
+			if (copy_to_user(buff,tbuf,c2)) {
+				tcnt = -EFAULT;
+				break;
+			}
+			offs += c2;
+			tcnt += c2;
+			buff += c2;
+			count -= c2;
+			*ppos += c2;
+		}
+		kfree(tbuf);
+		return tcnt;
+	}
+
+	if (!fh->rhp) {
+		ret = pvr2_v4l2_iosetup(fh);
+		if (ret) {
+			return ret;
+		}
+	}
+
+	for (;;) {
+		ret = pvr2_ioread_read(fh->rhp,buff,count);
+		if (ret >= 0) break;
+		if (ret != -EAGAIN) break;
+		if (file->f_flags & O_NONBLOCK) break;
+		/* Doing blocking I/O.  Wait here. */
+		ret = wait_event_interruptible(
+			fh->wait_data,
+			pvr2_ioread_avail(fh->rhp) >= 0);
+		if (ret < 0) break;
+	}
+
+	return ret;
+}
+
+
+static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
+{
+	unsigned int mask = 0;
+	struct pvr2_v4l2_fh *fh = file->private_data;
+	int ret;
+
+	if (fh->fw_mode_flag) {
+		mask |= POLLIN | POLLRDNORM;
+		return mask;
+	}
+
+	if (!fh->rhp) {
+		ret = pvr2_v4l2_iosetup(fh);
+		if (ret) return POLLERR;
+	}
+
+	poll_wait(file,&fh->wait_data,wait);
+
+	if (pvr2_ioread_avail(fh->rhp) >= 0) {
+		mask |= POLLIN | POLLRDNORM;
+	}
+
+	return mask;
+}
+
+
+static struct file_operations vdev_fops = {
+	.owner      = THIS_MODULE,
+	.open       = pvr2_v4l2_open,
+	.release    = pvr2_v4l2_release,
+	.read       = pvr2_v4l2_read,
+	.ioctl      = pvr2_v4l2_ioctl,
+	.llseek     = no_llseek,
+	.poll       = pvr2_v4l2_poll,
+};
+
+
+#define VID_HARDWARE_PVRUSB2    38  /* FIXME : need a good value */
+
+static struct video_device vdev_template = {
+	.owner      = THIS_MODULE,
+	.type       = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
+	.type2      = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
+		       | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
+		       | V4L2_CAP_READWRITE),
+	.hardware   = VID_HARDWARE_PVRUSB2,
+	.fops       = &vdev_fops,
+};
+
+
+static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
+			       struct pvr2_v4l2 *vp,
+			       enum pvr2_config cfg)
+{
+	int mindevnum;
+	int unit_number;
+	int v4l_type;
+	dip->v4lp = vp;
+	dip->config = cfg;
+
+
+	switch (cfg) {
+	case pvr2_config_mpeg:
+		v4l_type = VFL_TYPE_GRABBER;
+		dip->stream = &vp->channel.mc_head->video_stream;
+		break;
+	case pvr2_config_vbi:
+		v4l_type = VFL_TYPE_VBI;
+		break;
+	case pvr2_config_radio:
+		v4l_type = VFL_TYPE_RADIO;
+		break;
+	default:
+		/* Bail out (this should be impossible) */
+		err("Failed to set up pvrusb2 v4l dev"
+		    " due to unrecognized config");
+		return;
+	}
+
+	if (!dip->stream) {
+		err("Failed to set up pvrusb2 v4l dev"
+		    " due to missing stream instance");
+		return;
+	}
+
+	dip->vdev = video_device_alloc();
+	if (!dip->vdev) {
+		err("Alloc of pvrusb2 v4l video device failed");
+		return;
+	}
+
+	memcpy(dip->vdev,&vdev_template,sizeof(vdev_template));
+	dip->vdev->release = video_device_release;
+	mutex_lock(&device_lock);
+
+	mindevnum = -1;
+	unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
+	if ((unit_number >= 0) && (unit_number < PVR_NUM)) {
+		mindevnum = video_nr[unit_number];
+	}
+	if ((video_register_device(dip->vdev, v4l_type, mindevnum) < 0) &&
+	    (video_register_device(dip->vdev, v4l_type, -1) < 0)) {
+		err("Failed to register pvrusb2 v4l video device");
+	} else {
+		pvr2_trace(PVR2_TRACE_INIT,
+			   "registered device video%d [%s]",
+			   dip->vdev->minor,pvr2_config_get_name(dip->config));
+	}
+
+	if ((dip->vdev->minor < sizeof(devices)/sizeof(devices[0])) &&
+	    (devices[dip->vdev->minor] == NULL)) {
+		dip->ctxt_idx = dip->vdev->minor;
+		devices[dip->ctxt_idx] = dip;
+	}
+	mutex_unlock(&device_lock);
+
+	pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
+					dip->vdev->minor);
+}
+
+
+struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
+{
+	struct pvr2_v4l2 *vp;
+
+	vp = kmalloc(sizeof(*vp),GFP_KERNEL);
+	if (!vp) return vp;
+	memset(vp,0,sizeof(*vp));
+	vp->video_dev.ctxt_idx = -1;
+	pvr2_channel_init(&vp->channel,mnp);
+	pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
+
+	vp->channel.check_func = pvr2_v4l2_internal_check;
+
+	/* register streams */
+	pvr2_v4l2_dev_init(&vp->video_dev,vp,pvr2_config_mpeg);
+
+
+	return vp;
+}
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
new file mode 100644
index 0000000..9a995e2
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h
@@ -0,0 +1,40 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifndef __PVRUSB2_V4L2_H
+#define __PVRUSB2_V4L2_H
+
+#include "pvrusb2-context.h"
+
+struct pvr2_v4l2;
+
+struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *);
+
+#endif /* __PVRUSB2_V4L2_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 75 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
new file mode 100644
index 0000000..e4ec7f2
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c
@@ -0,0 +1,253 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   saa711x support that is available in the v4l available starting
+   with linux 2.6.15.
+
+*/
+
+#include "pvrusb2-video-v4l.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/saa7115.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+struct pvr2_v4l_decoder {
+	struct pvr2_i2c_handler handler;
+	struct pvr2_decoder_ctrl ctrl;
+	struct pvr2_i2c_client *client;
+	struct pvr2_hdw *hdw;
+	unsigned long stale_mask;
+};
+
+
+static void set_input(struct pvr2_v4l_decoder *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	struct v4l2_routing route;
+
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val);
+	switch(hdw->input_val) {
+	case PVR2_CVAL_INPUT_TV:
+		route.input = SAA7115_COMPOSITE4;
+		break;
+	case PVR2_CVAL_INPUT_COMPOSITE:
+		route.input = SAA7115_COMPOSITE5;
+		break;
+	case PVR2_CVAL_INPUT_SVIDEO:
+		route.input = SAA7115_SVIDEO2;
+		break;
+	case PVR2_CVAL_INPUT_RADIO:
+		// ????? No idea yet what to do here
+	default:
+		return;
+	}
+	route.output = 0;
+	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route);
+}
+
+
+static int check_input(struct pvr2_v4l_decoder *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	return hdw->input_dirty != 0;
+}
+
+
+static void set_audio(struct pvr2_v4l_decoder *ctxt)
+{
+	u32 val;
+	struct pvr2_hdw *hdw = ctxt->hdw;
+
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d",
+		   hdw->srate_val);
+	switch (hdw->srate_val) {
+	default:
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000:
+		val = 48000;
+		break;
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100:
+		val = 44100;
+		break;
+	case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000:
+		val = 32000;
+		break;
+	}
+	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val);
+}
+
+
+static int check_audio(struct pvr2_v4l_decoder *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	return hdw->srate_dirty != 0;
+}
+
+
+struct pvr2_v4l_decoder_ops {
+	void (*update)(struct pvr2_v4l_decoder *);
+	int (*check)(struct pvr2_v4l_decoder *);
+};
+
+
+static const struct pvr2_v4l_decoder_ops decoder_ops[] = {
+	{ .update = set_input, .check = check_input},
+	{ .update = set_audio, .check = check_audio},
+};
+
+
+static void decoder_detach(struct pvr2_v4l_decoder *ctxt)
+{
+	ctxt->client->handler = 0;
+	ctxt->hdw->decoder_ctrl = 0;
+	kfree(ctxt);
+}
+
+
+static int decoder_check(struct pvr2_v4l_decoder *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (ctxt->stale_mask & msk) continue;
+		if (decoder_ops[idx].check(ctxt)) {
+			ctxt->stale_mask |= msk;
+		}
+	}
+	return ctxt->stale_mask != 0;
+}
+
+
+static void decoder_update(struct pvr2_v4l_decoder *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (!(ctxt->stale_mask & msk)) continue;
+		ctxt->stale_mask &= ~msk;
+		decoder_ops[idx].update(ctxt);
+	}
+}
+
+
+static int decoder_detect(struct pvr2_i2c_client *cp)
+{
+	/* Attempt to query the decoder - let's see if it will answer */
+	struct v4l2_tuner vt;
+	int ret;
+
+	memset(&vt,0,sizeof(vt));
+	ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt);
+	return ret == 0; /* Return true if it answered */
+}
+
+
+static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl)
+{
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl);
+	pvr2_v4l2_cmd_stream(ctxt->client,fl);
+}
+
+
+static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt)
+{
+	struct v4l2_tuner vt;
+	int ret;
+
+	memset(&vt,0,sizeof(vt));
+	ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt);
+	if (ret < 0) return -EINVAL;
+	return vt.signal ? 1 : 0;
+}
+
+
+static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt)
+{
+	return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l");
+}
+
+
+const static struct pvr2_i2c_handler_functions hfuncs = {
+	.detach = (void (*)(void *))decoder_detach,
+	.check = (int (*)(void *))decoder_check,
+	.update = (void (*)(void *))decoder_update,
+	.describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe,
+};
+
+
+int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw,
+			       struct pvr2_i2c_client *cp)
+{
+	struct pvr2_v4l_decoder *ctxt;
+
+	if (hdw->decoder_ctrl) return 0;
+	if (cp->handler) return 0;
+	if (!decoder_detect(cp)) return 0;
+
+	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	if (!ctxt) return 0;
+	memset(ctxt,0,sizeof(*ctxt));
+
+	ctxt->handler.func_data = ctxt;
+	ctxt->handler.func_table = &hfuncs;
+	ctxt->ctrl.ctxt = ctxt;
+	ctxt->ctrl.detach = (void (*)(void *))decoder_detach;
+	ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable;
+	ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned;
+	ctxt->client = cp;
+	ctxt->hdw = hdw;
+	ctxt->stale_mask = (1 << (sizeof(decoder_ops)/
+				  sizeof(decoder_ops[0]))) - 1;
+	hdw->decoder_ctrl = &ctxt->ctrl;
+	cp->handler = &ctxt->handler;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up",
+		   cp->client->addr);
+	return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
new file mode 100644
index 0000000..2b917fd
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h
@@ -0,0 +1,52 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_VIDEO_V4L_H
+#define __PVRUSB2_VIDEO_V4L_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which handles device video processing.  This interface is
+   used internally by the driver; higher level code should only
+   interact through the interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+
+#endif /* __PVRUSB2_VIDEO_V4L_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
new file mode 100644
index 0000000..fcad346
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c
@@ -0,0 +1,170 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*
+
+   This source file is specifically designed to interface with the
+   wm8775.
+
+*/
+
+#include "pvrusb2-wm8775.h"
+#include "pvrusb2-i2c-cmd-v4l2.h"
+
+
+#include "pvrusb2-hdw-internal.h"
+#include "pvrusb2-debug.h"
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+struct pvr2_v4l_wm8775 {
+	struct pvr2_i2c_handler handler;
+	struct pvr2_i2c_client *client;
+	struct pvr2_hdw *hdw;
+	unsigned long stale_mask;
+};
+
+
+static void set_input(struct pvr2_v4l_wm8775 *ctxt)
+{
+	struct v4l2_routing route;
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	int msk = 0;
+
+	memset(&route,0,sizeof(route));
+
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d msk=0x%x)",
+		   hdw->input_val,msk);
+
+	// Always point to input #1 no matter what
+	route.input = 2;
+	pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route);
+}
+
+static int check_input(struct pvr2_v4l_wm8775 *ctxt)
+{
+	struct pvr2_hdw *hdw = ctxt->hdw;
+	return hdw->input_dirty != 0;
+}
+
+
+struct pvr2_v4l_wm8775_ops {
+	void (*update)(struct pvr2_v4l_wm8775 *);
+	int (*check)(struct pvr2_v4l_wm8775 *);
+};
+
+
+static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = {
+	{ .update = set_input, .check = check_input},
+};
+
+
+static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt,
+				     char *buf,unsigned int cnt)
+{
+	return scnprintf(buf,cnt,"handler: pvrusb2-wm8775");
+}
+
+
+static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt)
+{
+	ctxt->client->handler = 0;
+	kfree(ctxt);
+}
+
+
+static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (ctxt->stale_mask & msk) continue;
+		if (wm8775_ops[idx].check(ctxt)) {
+			ctxt->stale_mask |= msk;
+		}
+	}
+	return ctxt->stale_mask != 0;
+}
+
+
+static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt)
+{
+	unsigned long msk;
+	unsigned int idx;
+
+	for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]);
+	     idx++) {
+		msk = 1 << idx;
+		if (!(ctxt->stale_mask & msk)) continue;
+		ctxt->stale_mask &= ~msk;
+		wm8775_ops[idx].update(ctxt);
+	}
+}
+
+
+const static struct pvr2_i2c_handler_functions hfuncs = {
+	.detach = (void (*)(void *))wm8775_detach,
+	.check = (int (*)(void *))wm8775_check,
+	.update = (void (*)(void *))wm8775_update,
+	.describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe,
+};
+
+
+int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp)
+{
+	struct pvr2_v4l_wm8775 *ctxt;
+
+	if (cp->handler) return 0;
+
+	ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL);
+	if (!ctxt) return 0;
+	memset(ctxt,0,sizeof(*ctxt));
+
+	ctxt->handler.func_data = ctxt;
+	ctxt->handler.func_table = &hfuncs;
+	ctxt->client = cp;
+	ctxt->hdw = hdw;
+	ctxt->stale_mask = (1 << (sizeof(wm8775_ops)/
+				  sizeof(wm8775_ops[0]))) - 1;
+	cp->handler = &ctxt->handler;
+	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up",
+		   cp->client->addr);
+	return !0;
+}
+
+
+
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
new file mode 100644
index 0000000..8aaeff4
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h
@@ -0,0 +1,53 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_WM8775_H
+#define __PVRUSB2_WM8775_H
+
+/*
+
+   This module connects the pvrusb2 driver to the I2C chip level
+   driver which performs analog -> digital audio conversion for
+   external audio inputs.  This interface is used internally by the
+   driver; higher level code should only interact through the
+   interface provided by pvrusb2-hdw.h.
+
+*/
+
+
+
+#include "pvrusb2-i2c-core.h"
+
+int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *);
+
+
+#endif /* __PVRUSB2_WM8775_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pvrusb2/pvrusb2.h b/drivers/media/video/pvrusb2/pvrusb2.h
new file mode 100644
index 0000000..074533e
--- /dev/null
+++ b/drivers/media/video/pvrusb2/pvrusb2.h
@@ -0,0 +1,43 @@
+/*
+ *
+ *  $Id$
+ *
+ *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
+ *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __PVRUSB2_H
+#define __PVRUSB2_H
+
+/* Maximum number of pvrusb2 instances we can track at once.  You
+   might want to increase this - however the driver operation will not
+   be impaired if it is too small.  Instead additional units just
+   won't have an ID assigned and it might not be possible to specify
+   module paramters for those extra units. */
+#define PVR_NUM 20
+
+#endif /* __PVRUSB2_H */
+
+/*
+  Stuff for Emacs to see, in order to encourage consistent editing style:
+  *** Local Variables: ***
+  *** mode: c ***
+  *** fill-column: 70 ***
+  *** tab-width: 8 ***
+  *** c-basic-offset: 8 ***
+  *** End: ***
+  */
diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig
index 53cbc95..697145e 100644
--- a/drivers/media/video/pwc/Kconfig
+++ b/drivers/media/video/pwc/Kconfig
@@ -7,6 +7,7 @@
 	   * Philips PCA645, PCA646
 	   * Philips PCVC675, PCVC680, PCVC690
 	   * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+	   * Philips SPC900NC
 	   * Askey VC010
 	   * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro'
 	     and 'Orbit'/'Sphere'
@@ -19,10 +20,18 @@
 	  and never will be, but the 665 and 720/20 are supported by other
 	  drivers.
 
-	  See <file:Documentation/usb/philips.txt> for more information and
-	  installation instructions.
+	  Some newer logitech webcams are not handled by this driver but by the
+	  Usb Video Class driver (linux-uvc).
 
 	  The built-in microphone is enabled by selecting USB Audio support.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called pwc.
+
+config USB_PWC_DEBUG
+	bool "USB Philips Cameras verbose debug"
+	depends USB_PWC
+	help
+	  Say Y here in order to have the pwc driver generate verbose debugging
+	  messages.
+	  A special module options 'trace' is used to control the verbosity.
diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile
index 33d6012..9db2260 100644
--- a/drivers/media/video/pwc/Makefile
+++ b/drivers/media/video/pwc/Makefile
@@ -1,3 +1,12 @@
-pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o
+pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
+pwc-objs	+= pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
 
 obj-$(CONFIG_USB_PWC) += pwc.o
+
+ifeq ($(CONFIG_USB_PWC_DEBUG),y)
+EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=1
+else
+EXTRA_CFLAGS += -DCONFIG_PWC_DEBUG=0
+endif
+
+
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 4ba549b..0bd1155 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -2,7 +2,7 @@
    Functions that send various control messages to the webcam, including
    video modes.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -41,12 +41,14 @@
 #include <asm/uaccess.h>
 #endif
 #include <asm/errno.h>
+#include <linux/version.h>
 
 #include "pwc.h"
-#include "pwc-ioctl.h"
 #include "pwc-uncompress.h"
 #include "pwc-kiara.h"
 #include "pwc-timon.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 /* Request types: video */
 #define SET_LUM_CTL			0x01
@@ -57,6 +59,10 @@
 #define GET_STATUS_CTL			0x06
 #define SET_EP_STREAM_CTL		0x07
 #define GET_EP_STREAM_CTL		0x08
+#define GET_XX_CTL			0x09
+#define SET_XX_CTL			0x0A
+#define GET_XY_CTL			0x0B
+#define SET_XY_CTL			0x0C
 #define SET_MPT_CTL			0x0D
 #define GET_MPT_CTL			0x0E
 
@@ -93,12 +99,20 @@
 #define READ_SHUTTER_FORMATTER			0x0600
 #define READ_RED_GAIN_FORMATTER			0x0700
 #define READ_BLUE_GAIN_FORMATTER		0x0800
+#define GET_STATUS_B00				0x0B00
 #define SENSOR_TYPE_FORMATTER1			0x0C00
+#define GET_STATUS_3000				0x3000
 #define READ_RAW_Y_MEAN_FORMATTER		0x3100
 #define SET_POWER_SAVE_MODE_FORMATTER		0x3200
 #define MIRROR_IMAGE_FORMATTER			0x3300
 #define LED_FORMATTER				0x3400
+#define LOWLIGHT				0x3500
+#define GET_STATUS_3600				0x3600
 #define SENSOR_TYPE_FORMATTER2			0x3700
+#define GET_STATUS_3800				0x3800
+#define GET_STATUS_4000				0x4000
+#define GET_STATUS_4100				0x4100	/* Get */
+#define CTL_STATUS_4200				0x4200	/* [GS] 1 */
 
 /* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
 #define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
@@ -138,6 +152,7 @@
 #include "pwc-nala.h"
 };
 
+static void pwc_set_image_buffer_size(struct pwc_device *pdev);
 
 /****************************************************************************/
 
@@ -159,31 +174,7 @@
 		&buf, buflen, 500)
 
 
-#if PWC_DEBUG
-void pwc_hexdump(void *p, int len)
-{
-	int i;
-	unsigned char *s;
-	char buf[100], *d;
-
-	s = (unsigned char *)p;
-	d = buf;
-	*d = '\0';
-	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
-	for (i = 0; i < len; i++) {
-		d += sprintf(d, "%02X ", *s++);
-		if ((i & 0xF) == 0xF) {
-			Debug("%s\n", buf);
-			d = buf;
-			*d = '\0';
-		}
-	}
-	if ((i & 0xF) != 0)
-		Debug("%s\n", buf);
-}
-#endif
-
-static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+static int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
 {
 	return usb_control_msg(udev,
 		usb_sndctrlpipe(udev, 0),
@@ -196,7 +187,7 @@
 
 
 
-static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
 {
 	unsigned char buf[3];
 	int ret, fps;
@@ -229,34 +220,14 @@
 	if (pEntry->alternate == 0)
 		return -EINVAL;
 
-	if (pEntry->compressed)
-		return -ENOENT; /* Not supported. */
-
 	memcpy(buf, pEntry->mode, 3);
 	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
 	if (ret < 0) {
-		Debug("Failed to send video command... %d\n", ret);
+		PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
 		return ret;
 	}
 	if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
-	 {
-	   switch(pdev->type) {
-	     case 645:
-	     case 646:
-/*	       pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
-	       break;
-
-	     case 675:
-	     case 680:
-	     case 690:
-	     case 720:
-	     case 730:
-	     case 740:
-	     case 750:
-/*	       pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
-	       break;
-	   }
-	}
+		pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
 
 	pdev->cmd_len = 3;
 	memcpy(pdev->cmd_buf, buf, 3);
@@ -283,7 +254,7 @@
 }
 
 
-static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
 {
 	unsigned char buf[13];
 	const struct Timon_table_entry *pChoose;
@@ -315,8 +286,8 @@
 	if (ret < 0)
 		return ret;
 
-/* 	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-	   pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
+	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+		pwc_dec23_init(pdev, pdev->type, buf);
 
 	pdev->cmd_len = 13;
 	memcpy(pdev->cmd_buf, buf, 13);
@@ -336,7 +307,7 @@
 }
 
 
-static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
 {
 	const struct Kiara_table_entry *pChoose = NULL;
 	int fps, ret;
@@ -350,21 +321,14 @@
 	fps = (frames / 5) - 1;
 
 	/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
-	if (size == PSZ_VGA && frames == 5 && snapshot)
+	if (size == PSZ_VGA && frames == 5 && snapshot && pdev->vpalette == VIDEO_PALETTE_RAW)
 	{
 		/* Only available in case the raw palette is selected or
 		   we have the decompressor available. This mode is
 		   only available in compressed form
 		*/
-		if (pdev->vpalette == VIDEO_PALETTE_RAW)
-		{
-			Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
-			pChoose = &RawEntry;
-		}
-		else
-		{
-			Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n");
-		}
+		PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n");
+		pChoose = &RawEntry;
 	}
 	else
 	{
@@ -372,6 +336,7 @@
 		   if the preferred ratio is not available.
 		   Skip this step when using RAW modes.
 		*/
+		snapshot = 0;
 		while (compression <= 3) {
 			pChoose = &Kiara_table[size][fps][compression];
 			if (pChoose->alternate != 0)
@@ -382,7 +347,7 @@
 	if (pChoose == NULL || pChoose->alternate == 0)
 		return -ENOENT; /* Not supported. */
 
-	Debug("Using alternate setting %d.\n", pChoose->alternate);
+	PWC_TRACE("Using alternate setting %d.\n", pChoose->alternate);
 
 	/* usb_control_msg won't take staticly allocated arrays as argument?? */
 	memcpy(buf, pChoose->mode, 12);
@@ -394,8 +359,8 @@
 	if (ret < 0)
 		return ret;
 
-/*	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
-	  pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
+	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+		pwc_dec23_init(pdev, pdev->type, buf);
 
 	pdev->cmd_len = 12;
 	memcpy(pdev->cmd_buf, buf, 12);
@@ -410,49 +375,13 @@
 		pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
 	else
 		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n",
+	    pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength);
 	return 0;
 }
 
 
 
-static void pwc_set_image_buffer_size(struct pwc_device *pdev)
-{
-	int i, factor = 0, filler = 0;
-
-	/* for PALETTE_YUV420P */
-	switch(pdev->vpalette)
-	{
-	case VIDEO_PALETTE_YUV420P:
-		factor = 6;
-		filler = 128;
-		break;
-	case VIDEO_PALETTE_RAW:
-		factor = 6; /* can be uncompressed YUV420P */
-		filler = 0;
-		break;
-	}
-
-	/* Set sizes in bytes */
-	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
-	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
-
-	/* Align offset, or you'll get some very weird results in
-	   YUV420 mode... x must be multiple of 4 (to get the Y's in
-	   place), and y even (or you'll mixup U & V). This is less of a
-	   problem for YUV420P.
-	 */
-	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
-	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
-
-	/* Fill buffers with gray or black */
-	for (i = 0; i < MAX_IMAGES; i++) {
-		if (pdev->image_ptr[i] != NULL)
-			memset(pdev->image_ptr[i], filler, pdev->view.size);
-	}
-}
-
-
-
 /**
    @pdev: device structure
    @width: viewport width
@@ -465,50 +394,78 @@
 {
 	int ret, size;
 
-	Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
+	PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
 	size = pwc_decode_size(pdev, width, height);
 	if (size < 0) {
-		Debug("Could not find suitable size.\n");
+		PWC_DEBUG_MODULE("Could not find suitable size.\n");
 		return -ERANGE;
 	}
-	Debug("decode_size = %d.\n", size);
+	PWC_TRACE("decode_size = %d.\n", size);
 
-	ret = -EINVAL;
-	switch(pdev->type) {
-	case 645:
-	case 646:
+	if (DEVICE_USE_CODEC1(pdev->type)) {
 		ret = set_video_mode_Nala(pdev, size, frames);
-		break;
 
-	case 675:
-	case 680:
-	case 690:
-		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
-		break;
-
-	case 720:
-	case 730:
-	case 740:
-	case 750:
+	} else if (DEVICE_USE_CODEC3(pdev->type)) {
 		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
-		break;
+
+	} else {
+		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
 	}
 	if (ret < 0) {
-		if (ret == -ENOENT)
-			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
-		else {
-			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
-		}
+		PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
 		return ret;
 	}
 	pdev->view.x = width;
 	pdev->view.y = height;
 	pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
 	pwc_set_image_buffer_size(pdev);
-	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
+	PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
 	return 0;
 }
 
+#define BLACK_Y 0
+#define BLACK_U 128
+#define BLACK_V 128
+
+static void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+	int i, factor = 0;
+
+	/* for PALETTE_YUV420P */
+	switch(pdev->vpalette)
+	{
+	case VIDEO_PALETTE_YUV420P:
+		factor = 6;
+		break;
+	case VIDEO_PALETTE_RAW:
+		factor = 6; /* can be uncompressed YUV420P */
+		break;
+	}
+
+	/* Set sizes in bytes */
+	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
+
+	/* Align offset, or you'll get some very weird results in
+	   YUV420 mode... x must be multiple of 4 (to get the Y's in
+	   place), and y even (or you'll mixup U & V). This is less of a
+	   problem for YUV420P.
+	 */
+	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
+	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
+
+	/* Fill buffers with black colors */
+	for (i = 0; i < pwc_mbufs; i++) {
+		unsigned char *p = pdev->image_data + pdev->images[i].offset;
+		memset(p, BLACK_Y, pdev->view.x * pdev->view.y);
+		p += pdev->view.x * pdev->view.y;
+		memset(p, BLACK_U, pdev->view.x * pdev->view.y/4);
+		p += pdev->view.x * pdev->view.y/4;
+		memset(p, BLACK_V, pdev->view.x * pdev->view.y/4);
+	}
+}
+
+
 
 /* BRIGHTNESS */
 
@@ -520,7 +477,7 @@
 	ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	return buf << 9;
+	return buf;
 }
 
 int pwc_set_brightness(struct pwc_device *pdev, int value)
@@ -545,7 +502,7 @@
 	ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	return buf << 10;
+	return buf;
 }
 
 int pwc_set_contrast(struct pwc_device *pdev, int value)
@@ -570,7 +527,7 @@
 	ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	return buf << 11;
+	return buf;
 }
 
 int pwc_set_gamma(struct pwc_device *pdev, int value)
@@ -588,37 +545,47 @@
 
 /* SATURATION */
 
-int pwc_get_saturation(struct pwc_device *pdev)
+/* return a value between [-100 , 100] */
+int pwc_get_saturation(struct pwc_device *pdev, int *value)
 {
 	char buf;
-	int ret;
-
-	if (pdev->type < 675)
-		return -1;
-	ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
-	if (ret < 0)
-		return ret;
-	return 32768 + buf * 327;
-}
-
-int pwc_set_saturation(struct pwc_device *pdev, int value)
-{
-	char buf;
+	int ret, saturation_register;
 
 	if (pdev->type < 675)
 		return -EINVAL;
-	if (value < 0)
-		value = 0;
-	if (value > 0xffff)
-		value = 0xffff;
-	/* saturation ranges from -100 to +100 */
-	buf = (value - 32768) / 327;
-	return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
+	if (pdev->type < 730)
+		saturation_register = SATURATION_MODE_FORMATTER2;
+	else
+		saturation_register = SATURATION_MODE_FORMATTER1;
+	ret = RecvControlMsg(GET_CHROM_CTL, saturation_register, 1);
+	if (ret < 0)
+		return ret;
+	*value = (signed)buf;
+	return 0;
+}
+
+/* @param value saturation color between [-100 , 100] */
+int pwc_set_saturation(struct pwc_device *pdev, int value)
+{
+	char buf;
+	int saturation_register;
+
+	if (pdev->type < 675)
+		return -EINVAL;
+	if (value < -100)
+		value = -100;
+	if (value > 100)
+		value = 100;
+	if (pdev->type < 730)
+		saturation_register = SATURATION_MODE_FORMATTER2;
+	else
+		saturation_register = SATURATION_MODE_FORMATTER1;
+	return SendControlMsg(SET_CHROM_CTL, saturation_register, 1);
 }
 
 /* AGC */
 
-static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
 {
 	char buf;
 	int ret;
@@ -643,7 +610,7 @@
 	return 0;
 }
 
-static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+int pwc_get_agc(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -673,7 +640,7 @@
 	return 0;
 }
 
-static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
 {
 	char buf[2];
 	int speed, ret;
@@ -691,23 +658,16 @@
 			value = 0;
 		if (value > 0xffff)
 			value = 0xffff;
-		switch(pdev->type) {
-		case 675:
-		case 680:
-		case 690:
+
+		if (DEVICE_USE_CODEC2(pdev->type)) {
 			/* speed ranges from 0x0 to 0x290 (656) */
 			speed = (value / 100);
 			buf[1] = speed >> 8;
 			buf[0] = speed & 0xff;
-			break;
-		case 720:
-		case 730:
-		case 740:
-		case 750:
+		} else if (DEVICE_USE_CODEC3(pdev->type)) {
 			/* speed seems to range from 0x0 to 0xff */
 			buf[1] = 0;
 			buf[0] = value >> 8;
-			break;
 		}
 
 		ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
@@ -715,6 +675,25 @@
 	return ret;
 }
 
+/* This function is not exported to v4l1, so output values between 0 -> 256 */
+int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf[2];
+	int ret;
+
+	ret = RecvControlMsg(GET_STATUS_CTL, READ_SHUTTER_FORMATTER, 2);
+	if (ret < 0)
+		return ret;
+	*value = buf[0] + (buf[1] << 8);
+	if (DEVICE_USE_CODEC2(pdev->type)) {
+		/* speed ranges from 0x0 to 0x290 (656) */
+		*value *= 256/656;
+	} else if (DEVICE_USE_CODEC3(pdev->type)) {
+		/* speed seems to range from 0x0 to 0xff */
+	}
+	return 0;
+}
+
 
 /* POWER */
 
@@ -736,19 +715,19 @@
 
 /* private calls */
 
-static inline int pwc_restore_user(struct pwc_device *pdev)
+int pwc_restore_user(struct pwc_device *pdev)
 {
 	char buf; /* dummy */
 	return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
 }
 
-static inline int pwc_save_user(struct pwc_device *pdev)
+int pwc_save_user(struct pwc_device *pdev)
 {
 	char buf; /* dummy */
 	return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
 }
 
-static inline int pwc_restore_factory(struct pwc_device *pdev)
+int pwc_restore_factory(struct pwc_device *pdev)
 {
 	char buf; /* dummy */
 	return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
@@ -766,7 +745,7 @@
   * 03: manual
   * 04: auto
   */
-static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
+int pwc_set_awb(struct pwc_device *pdev, int mode)
 {
 	char buf;
 	int ret;
@@ -786,7 +765,7 @@
 	return 0;
 }
 
-static inline int pwc_get_awb(struct pwc_device *pdev)
+int pwc_get_awb(struct pwc_device *pdev)
 {
 	unsigned char buf;
 	int ret;
@@ -798,7 +777,7 @@
 	return buf;
 }
 
-static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
+int pwc_set_red_gain(struct pwc_device *pdev, int value)
 {
 	unsigned char buf;
 
@@ -811,7 +790,7 @@
 	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
 }
 
-static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
+int pwc_get_red_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -824,7 +803,7 @@
 }
 
 
-static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
+int pwc_set_blue_gain(struct pwc_device *pdev, int value)
 {
 	unsigned char buf;
 
@@ -837,7 +816,7 @@
 	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
 }
 
-static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
+int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -854,7 +833,7 @@
    internal red/blue gains, which may be different from the manual
    gains set or read above.
  */
-static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
+static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -866,7 +845,7 @@
 	return 0;
 }
 
-static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
+static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -879,7 +858,7 @@
 }
 
 
-static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
+static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
 {
 	unsigned char buf;
 
@@ -888,7 +867,7 @@
 	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
 }
 
-static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
+static int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -901,7 +880,7 @@
 }
 
 
-static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
+static int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
 {
 	unsigned char buf;
 
@@ -910,7 +889,7 @@
 	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
 }
 
-static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
+static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
 {
 	unsigned char buf;
 	int ret;
@@ -965,7 +944,7 @@
 	return 0;
 }
 
-static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
+int pwc_set_contour(struct pwc_device *pdev, int contour)
 {
 	unsigned char buf;
 	int ret;
@@ -990,7 +969,7 @@
 	return 0;
 }
 
-static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
+int pwc_get_contour(struct pwc_device *pdev, int *contour)
 {
 	unsigned char buf;
 	int ret;
@@ -1012,7 +991,7 @@
 }
 
 
-static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
+int pwc_set_backlight(struct pwc_device *pdev, int backlight)
 {
 	unsigned char buf;
 
@@ -1023,7 +1002,7 @@
 	return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
 }
 
-static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
+int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
 {
 	int ret;
 	unsigned char buf;
@@ -1031,12 +1010,35 @@
 	ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	*backlight = buf;
+	*backlight = !!buf;
+	return 0;
+}
+
+int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
+{
+	unsigned char buf;
+
+	if (colour)
+		buf = 0xff;
+	else
+		buf = 0x0;
+	return SendControlMsg(SET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+}
+
+int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
+{
+	int ret;
+	unsigned char buf;
+
+	ret = RecvControlMsg(GET_CHROM_CTL, COLOUR_MODE_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*colour = !!buf;
 	return 0;
 }
 
 
-static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
+int pwc_set_flicker(struct pwc_device *pdev, int flicker)
 {
 	unsigned char buf;
 
@@ -1047,7 +1049,7 @@
 	return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
 }
 
-static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
+int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
 {
 	int ret;
 	unsigned char buf;
@@ -1055,12 +1057,11 @@
 	ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
 	if (ret < 0)
 		return ret;
-	*flicker = buf;
+	*flicker = !!buf;
 	return 0;
 }
 
-
-static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
+int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
 {
 	unsigned char buf;
 
@@ -1072,7 +1073,7 @@
 	return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
 }
 
-static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
+int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
 {
 	int ret;
 	unsigned char buf;
@@ -1084,7 +1085,7 @@
 	return 0;
 }
 
-static int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
 {
 	unsigned char buf;
 
@@ -1092,7 +1093,18 @@
 	return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
 }
 
-static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+{
+	int ret;
+	ret = _pwc_mpt_reset(pdev, flags);
+	if (ret >= 0) {
+		pdev->pan_angle = 0;
+		pdev->tilt_angle = 0;
+	}
+	return ret;
+}
+
+static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
 {
 	unsigned char buf[4];
 
@@ -1110,7 +1122,35 @@
 	return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
 }
 
-static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
+int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+{
+	int ret;
+
+	/* check absolute ranges */
+	if (pan  < pdev->angle_range.pan_min  ||
+	    pan  > pdev->angle_range.pan_max  ||
+	    tilt < pdev->angle_range.tilt_min ||
+	    tilt > pdev->angle_range.tilt_max)
+		return -ERANGE;
+
+	/* go to relative range, check again */
+	pan  -= pdev->pan_angle;
+	tilt -= pdev->tilt_angle;
+	/* angles are specified in degrees * 100, thus the limit = 36000 */
+	if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000)
+		return -ERANGE;
+
+	ret = _pwc_mpt_set_angle(pdev, pan, tilt);
+	if (ret >= 0) {
+		pdev->pan_angle  += pan;
+		pdev->tilt_angle += tilt;
+	}
+	if (ret == -EPIPE) /* stall -> out of range */
+		ret = -ERANGE;
+	return ret;
+}
+
+static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
 {
 	int ret;
 	unsigned char buf[5];
@@ -1151,6 +1191,26 @@
  /* End of Add-Ons                                    */
  /* ************************************************* */
 
+/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
+   ioctl() calls. With 2.4, you have to do tedious copy_from_user()
+   and copy_to_user() calls. With these macros we circumvent this,
+   and let me maintain only one source file. The functionality is
+   exactly the same otherwise.
+ */
+
+
+/* define local variable for arg */
+#define ARG_DEF(ARG_type, ARG_name)\
+	ARG_type *ARG_name = arg;
+/* copy arg to local variable */
+#define ARG_IN(ARG_name) /* nothing */
+/* argument itself (referenced) */
+#define ARGR(ARG_name) (*ARG_name)
+/* argument address */
+#define ARGA(ARG_name) ARG_name
+/* copy local variable to arg */
+#define ARG_OUT(ARG_name) /* nothing */
+
 
 int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
 {
@@ -1180,206 +1240,243 @@
 
 	case VIDIOCPWCSCQUAL:
 	{
-		int *qual = arg;
+		ARG_DEF(int, qual)
 
-		if (*qual < 0 || *qual > 3)
+		ARG_IN(qual)
+		if (ARGR(qual) < 0 || ARGR(qual) > 3)
 			ret = -EINVAL;
 		else
-			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot);
+			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
 		if (ret >= 0)
-			pdev->vcompression = *qual;
+			pdev->vcompression = ARGR(qual);
 		break;
 	}
 
 	case VIDIOCPWCGCQUAL:
 	{
-		int *qual = arg;
-		*qual = pdev->vcompression;
+		ARG_DEF(int, qual)
+
+		ARGR(qual) = pdev->vcompression;
+		ARG_OUT(qual)
 		break;
 	}
 
 	case VIDIOCPWCPROBE:
 	{
-		struct pwc_probe *probe = arg;
-		strcpy(probe->name, pdev->vdev->name);
-		probe->type = pdev->type;
+		ARG_DEF(struct pwc_probe, probe)
+
+		strcpy(ARGR(probe).name, pdev->vdev->name);
+		ARGR(probe).type = pdev->type;
+		ARG_OUT(probe)
 		break;
 	}
 
 	case VIDIOCPWCGSERIAL:
 	{
-		struct pwc_serial *serial = arg;
-		strcpy(serial->serial, pdev->serial);
+		ARG_DEF(struct pwc_serial, serial)
+
+		strcpy(ARGR(serial).serial, pdev->serial);
+		ARG_OUT(serial)
 		break;
 	}
 
 	case VIDIOCPWCSAGC:
 	{
-		int *agc = arg;
-		if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc))
+		ARG_DEF(int, agc)
+
+		ARG_IN(agc)
+		if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
 			ret = -EINVAL;
 		break;
 	}
 
 	case VIDIOCPWCGAGC:
 	{
-		int *agc = arg;
+		ARG_DEF(int, agc)
 
-		if (pwc_get_agc(pdev, agc))
+		if (pwc_get_agc(pdev, ARGA(agc)))
 			ret = -EINVAL;
+		ARG_OUT(agc)
 		break;
 	}
 
 	case VIDIOCPWCSSHUTTER:
 	{
-		int *shutter_speed = arg;
-		ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed);
+		ARG_DEF(int, shutter_speed)
+
+		ARG_IN(shutter_speed)
+		ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
 		break;
 	}
 
 	case VIDIOCPWCSAWB:
 	{
-		struct pwc_whitebalance *wb = arg;
+		ARG_DEF(struct pwc_whitebalance, wb)
 
-		ret = pwc_set_awb(pdev, wb->mode);
-		if (ret >= 0 && wb->mode == PWC_WB_MANUAL) {
-			pwc_set_red_gain(pdev, wb->manual_red);
-			pwc_set_blue_gain(pdev, wb->manual_blue);
+		ARG_IN(wb)
+		ret = pwc_set_awb(pdev, ARGR(wb).mode);
+		if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
+			pwc_set_red_gain(pdev, ARGR(wb).manual_red);
+			pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
 		}
 		break;
 	}
 
 	case VIDIOCPWCGAWB:
 	{
-		struct pwc_whitebalance *wb = arg;
+		ARG_DEF(struct pwc_whitebalance, wb)
 
-		memset(wb, 0, sizeof(struct pwc_whitebalance));
-		wb->mode = pwc_get_awb(pdev);
-		if (wb->mode < 0)
+		memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
+		ARGR(wb).mode = pwc_get_awb(pdev);
+		if (ARGR(wb).mode < 0)
 			ret = -EINVAL;
 		else {
-			if (wb->mode == PWC_WB_MANUAL) {
-				ret = pwc_get_red_gain(pdev, &wb->manual_red);
+			if (ARGR(wb).mode == PWC_WB_MANUAL) {
+				ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
 				if (ret < 0)
 					break;
-				ret = pwc_get_blue_gain(pdev, &wb->manual_blue);
+				ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
 				if (ret < 0)
 					break;
 			}
-			if (wb->mode == PWC_WB_AUTO) {
-				ret = pwc_read_red_gain(pdev, &wb->read_red);
+			if (ARGR(wb).mode == PWC_WB_AUTO) {
+				ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
 				if (ret < 0)
 					break;
-				ret = pwc_read_blue_gain(pdev, &wb->read_blue);
+				ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
 				if (ret < 0)
 					break;
 			}
 		}
+		ARG_OUT(wb)
 		break;
 	}
 
 	case VIDIOCPWCSAWBSPEED:
 	{
-		struct pwc_wb_speed *wbs = arg;
+		ARG_DEF(struct pwc_wb_speed, wbs)
 
-		if (wbs->control_speed > 0) {
-			ret = pwc_set_wb_speed(pdev, wbs->control_speed);
+		if (ARGR(wbs).control_speed > 0) {
+			ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
 		}
-		if (wbs->control_delay > 0) {
-			ret = pwc_set_wb_delay(pdev, wbs->control_delay);
+		if (ARGR(wbs).control_delay > 0) {
+			ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
 		}
 		break;
 	}
 
 	case VIDIOCPWCGAWBSPEED:
 	{
-		struct pwc_wb_speed *wbs = arg;
+		ARG_DEF(struct pwc_wb_speed, wbs)
 
-		ret = pwc_get_wb_speed(pdev, &wbs->control_speed);
+		ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
 		if (ret < 0)
 			break;
-		ret = pwc_get_wb_delay(pdev, &wbs->control_delay);
+		ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
 		if (ret < 0)
 			break;
+		ARG_OUT(wbs)
 		break;
 	}
 
 	case VIDIOCPWCSLED:
 	{
-		struct pwc_leds *leds = arg;
-		ret = pwc_set_leds(pdev, leds->led_on, leds->led_off);
-	    	break;
+		ARG_DEF(struct pwc_leds, leds)
+
+		ARG_IN(leds)
+		ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
+		break;
 	}
 
 
 	case VIDIOCPWCGLED:
 	{
-		struct pwc_leds *leds = arg;
-		ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off);
+		ARG_DEF(struct pwc_leds, leds)
+
+		ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
+		ARG_OUT(leds)
 		break;
 	}
 
 	case VIDIOCPWCSCONTOUR:
 	{
-		int *contour = arg;
-		ret = pwc_set_contour(pdev, *contour);
+		ARG_DEF(int, contour)
+
+		ARG_IN(contour)
+		ret = pwc_set_contour(pdev, ARGR(contour));
 		break;
 	}
 
 	case VIDIOCPWCGCONTOUR:
 	{
-		int *contour = arg;
-		ret = pwc_get_contour(pdev, contour);
+		ARG_DEF(int, contour)
+
+		ret = pwc_get_contour(pdev, ARGA(contour));
+		ARG_OUT(contour)
 		break;
 	}
 
 	case VIDIOCPWCSBACKLIGHT:
 	{
-		int *backlight = arg;
-		ret = pwc_set_backlight(pdev, *backlight);
+		ARG_DEF(int, backlight)
+
+		ARG_IN(backlight)
+		ret = pwc_set_backlight(pdev, ARGR(backlight));
 		break;
 	}
 
 	case VIDIOCPWCGBACKLIGHT:
 	{
-		int *backlight = arg;
-		ret = pwc_get_backlight(pdev, backlight);
+		ARG_DEF(int, backlight)
+
+		ret = pwc_get_backlight(pdev, ARGA(backlight));
+		ARG_OUT(backlight)
 		break;
 	}
 
 	case VIDIOCPWCSFLICKER:
 	{
-		int *flicker = arg;
-		ret = pwc_set_flicker(pdev, *flicker);
+		ARG_DEF(int, flicker)
+
+		ARG_IN(flicker)
+		ret = pwc_set_flicker(pdev, ARGR(flicker));
 		break;
 	}
 
 	case VIDIOCPWCGFLICKER:
 	{
-		int *flicker = arg;
-		ret = pwc_get_flicker(pdev, flicker);
+		ARG_DEF(int, flicker)
+
+		ret = pwc_get_flicker(pdev, ARGA(flicker));
+		ARG_OUT(flicker)
 		break;
 	}
 
 	case VIDIOCPWCSDYNNOISE:
 	{
-		int *dynnoise = arg;
-		ret = pwc_set_dynamic_noise(pdev, *dynnoise);
+		ARG_DEF(int, dynnoise)
+
+		ARG_IN(dynnoise)
+		ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
 		break;
 	}
 
 	case VIDIOCPWCGDYNNOISE:
 	{
-		int *dynnoise = arg;
-		ret = pwc_get_dynamic_noise(pdev, dynnoise);
+		ARG_DEF(int, dynnoise)
+
+		ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
+		ARG_OUT(dynnoise);
 		break;
 	}
 
 	case VIDIOCPWCGREALSIZE:
 	{
-		struct pwc_imagesize *size = arg;
-		size->width = pdev->image.x;
-		size->height = pdev->image.y;
+		ARG_DEF(struct pwc_imagesize, size)
+
+		ARGR(size).width = pdev->image.x;
+		ARGR(size).height = pdev->image.y;
+		ARG_OUT(size)
 		break;
 	}
 
@@ -1387,14 +1484,10 @@
 	{
 		if (pdev->features & FEATURE_MOTOR_PANTILT)
 		{
-			int *flags = arg;
+			ARG_DEF(int, flags)
 
-			ret = pwc_mpt_reset(pdev, *flags);
-			if (ret >= 0)
-			{
-				pdev->pan_angle = 0;
-				pdev->tilt_angle = 0;
-			}
+			ARG_IN(flags)
+			ret = pwc_mpt_reset(pdev, ARGR(flags));
 		}
 		else
 		{
@@ -1407,8 +1500,10 @@
 	{
 		if (pdev->features & FEATURE_MOTOR_PANTILT)
 		{
-			struct pwc_mpt_range *range = arg;
-			*range = pdev->angle_range;
+			ARG_DEF(struct pwc_mpt_range, range)
+
+			ARGR(range) = pdev->angle_range;
+			ARG_OUT(range)
 		}
 		else
 		{
@@ -1423,48 +1518,23 @@
 
 		if (pdev->features & FEATURE_MOTOR_PANTILT)
 		{
-			struct pwc_mpt_angles *angles = arg;
+			ARG_DEF(struct pwc_mpt_angles, angles)
+
+			ARG_IN(angles)
 			/* The camera can only set relative angles, so
 			   do some calculations when getting an absolute angle .
 			 */
-			if (angles->absolute)
+			if (ARGR(angles).absolute)
 			{
-				new_pan  = angles->pan;
-				new_tilt = angles->tilt;
+				new_pan  = ARGR(angles).pan;
+				new_tilt = ARGR(angles).tilt;
 			}
 			else
 			{
-				new_pan  = pdev->pan_angle  + angles->pan;
-				new_tilt = pdev->tilt_angle + angles->tilt;
+				new_pan  = pdev->pan_angle  + ARGR(angles).pan;
+				new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
 			}
-			/* check absolute ranges */
-			if (new_pan  < pdev->angle_range.pan_min  ||
-			    new_pan  > pdev->angle_range.pan_max  ||
-			    new_tilt < pdev->angle_range.tilt_min ||
-			    new_tilt > pdev->angle_range.tilt_max)
-			{
-				ret = -ERANGE;
-			}
-			else
-			{
-				/* go to relative range, check again */
-				new_pan  -= pdev->pan_angle;
-				new_tilt -= pdev->tilt_angle;
-				/* angles are specified in degrees * 100, thus the limit = 36000 */
-				if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
-					ret = -ERANGE;
-			}
-			if (ret == 0) /* no errors so far */
-			{
-				ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
-				if (ret >= 0)
-				{
-					pdev->pan_angle  += new_pan;
-					pdev->tilt_angle += new_tilt;
-				}
-				if (ret == -EPIPE) /* stall -> out of range */
-					ret = -ERANGE;
-			}
+			ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
 		}
 		else
 		{
@@ -1478,11 +1548,12 @@
 
 		if (pdev->features & FEATURE_MOTOR_PANTILT)
 		{
-			struct pwc_mpt_angles *angles = arg;
+			ARG_DEF(struct pwc_mpt_angles, angles)
 
-			angles->absolute = 1;
-			angles->pan  = pdev->pan_angle;
-			angles->tilt = pdev->tilt_angle;
+			ARGR(angles).absolute = 1;
+			ARGR(angles).pan  = pdev->pan_angle;
+			ARGR(angles).tilt = pdev->tilt_angle;
+			ARG_OUT(angles)
 		}
 		else
 		{
@@ -1495,8 +1566,10 @@
 	{
 		if (pdev->features & FEATURE_MOTOR_PANTILT)
 		{
-			struct pwc_mpt_status *status = arg;
-			ret = pwc_mpt_get_status(pdev, status);
+			ARG_DEF(struct pwc_mpt_status, status)
+
+			ret = pwc_mpt_get_status(pdev, ARGA(status));
+			ARG_OUT(status)
 		}
 		else
 		{
@@ -1507,22 +1580,24 @@
 
 	case VIDIOCPWCGVIDCMD:
 	{
-		struct pwc_video_command *cmd = arg;
+		ARG_DEF(struct pwc_video_command, cmd);
 
-		cmd->type = pdev->type;
-		cmd->release = pdev->release;
-		cmd->command_len = pdev->cmd_len;
-		memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len);
-		cmd->bandlength = pdev->vbandlength;
-		cmd->frame_size = pdev->frame_size;
+		ARGR(cmd).type = pdev->type;
+		ARGR(cmd).release = pdev->release;
+		ARGR(cmd).command_len = pdev->cmd_len;
+		memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
+		ARGR(cmd).bandlength = pdev->vbandlength;
+		ARGR(cmd).frame_size = pdev->frame_size;
+		ARG_OUT(cmd)
 		break;
 	}
        /*
 	case VIDIOCPWCGVIDTABLE:
 	{
-		struct pwc_table_init_buffer *table = arg;
-		table->len = pdev->cmd_len;
-		memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size);
+		ARG_DEF(struct pwc_table_init_buffer, table);
+		ARGR(table).len = pdev->cmd_len;
+		memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
+		ARG_OUT(table)
 		break;
 	}
 	*/
@@ -1538,4 +1613,4 @@
 }
 
 
-
+/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c
new file mode 100644
index 0000000..c29593f
--- /dev/null
+++ b/drivers/media/video/pwc/pwc-dec1.c
@@ -0,0 +1,50 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 1
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+
+#include "pwc-dec1.h"
+
+
+void pwc_dec1_init(int type, int release, void *buffer, void *table)
+{
+
+}
+
+void pwc_dec1_exit(void)
+{
+
+
+
+}
+
+int pwc_dec1_alloc(struct pwc_device *pwc)
+{
+	pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
+	if (pwc->decompress_data == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h
new file mode 100644
index 0000000..8b62ddc
--- /dev/null
+++ b/drivers/media/video/pwc/pwc-dec1.h
@@ -0,0 +1,43 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+
+
+#ifndef PWC_DEC1_H
+#define PWC_DEC1_H
+
+#include "pwc.h"
+
+struct pwc_dec1_private
+{
+	int version;
+
+};
+
+int  pwc_dec1_alloc(struct pwc_device *pwc);
+void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
+void pwc_dec1_exit(void);
+
+#endif
+
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
new file mode 100644
index 0000000..9e2d91f
--- /dev/null
+++ b/drivers/media/video/pwc/pwc-dec23.c
@@ -0,0 +1,941 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 2 et 3
+   (C) 2004-2006  Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+#include <media/pwc-ioctl.h>
+
+#include <linux/string.h>
+
+/*
+ * USE_LOOKUP_TABLE_TO_CLAMP
+ *   0: use a C version of this tests:  {  a<0?0:(a>255?255:a) }
+ *   1: use a faster lookup table for cpu with a big cache (intel)
+ */
+#define USE_LOOKUP_TABLE_TO_CLAMP	1
+/*
+ * UNROLL_LOOP_FOR_COPYING_BLOCK
+ *   0: use a loop for a smaller code (but little slower)
+ *   1: when unrolling the loop, gcc produces some faster code (perhaps only
+ *   valid for intel processor class). Activating this option, automaticaly
+ *   activate USE_LOOKUP_TABLE_TO_CLAMP
+ */
+#define UNROLL_LOOP_FOR_COPY		1
+#if UNROLL_LOOP_FOR_COPY
+# undef USE_LOOKUP_TABLE_TO_CLAMP
+# define USE_LOOKUP_TABLE_TO_CLAMP 1
+#endif
+
+/*
+ * ENABLE_BAYER_DECODER
+ *   0: bayer decoder is not build (save some space)
+ *   1: bayer decoder is build and can be used
+ */
+#define ENABLE_BAYER_DECODER 0
+
+static void build_subblock_pattern(struct pwc_dec23_private *pdec)
+{
+	static const unsigned int initial_values[12] = {
+		-0x526500, -0x221200, 0x221200, 0x526500,
+			   -0x3de200, 0x3de200,
+		-0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480,
+			   -0x12c200, 0x12c200
+
+	};
+	static const unsigned int values_derivated[12] = {
+		0xa4ca, 0x4424, -0x4424, -0xa4ca,
+			0x7bc4, -0x7bc4,
+		0xdb69, 0x5aba, -0x5aba, -0xdb69,
+			0x2584, -0x2584
+	};
+	unsigned int temp_values[12];
+	int i, j;
+
+	memcpy(temp_values, initial_values, sizeof(initial_values));
+	for (i = 0; i < 256; i++) {
+		for (j = 0; j < 12; j++) {
+			pdec->table_subblock[i][j] = temp_values[j];
+			temp_values[j] += values_derivated[j];
+		}
+	}
+}
+
+static void build_bit_powermask_table(struct pwc_dec23_private *pdec)
+{
+	unsigned char *p;
+	unsigned int bit, byte, mask, val;
+	unsigned int bitpower = 1;
+
+	for (bit = 0; bit < 8; bit++) {
+		mask = bitpower - 1;
+		p = pdec->table_bitpowermask[bit];
+		for (byte = 0; byte < 256; byte++) {
+			val = (byte & mask);
+			if (byte & bitpower)
+				val = -val;
+			*p++ = val;
+		}
+		bitpower<<=1;
+	}
+}
+
+
+static void build_table_color(const unsigned int romtable[16][8],
+			      unsigned char p0004[16][1024],
+			      unsigned char p8004[16][256])
+{
+	int compression_mode, j, k, bit, pw;
+	unsigned char *p0, *p8;
+	const unsigned int *r;
+
+	/* We have 16 compressions tables */
+	for (compression_mode = 0; compression_mode < 16; compression_mode++) {
+		p0 = p0004[compression_mode];
+		p8 = p8004[compression_mode];
+		r  = romtable[compression_mode];
+
+		for (j = 0; j < 8; j++, r++, p0 += 128) {
+
+			for (k = 0; k < 16; k++) {
+				if (k == 0)
+					bit = 1;
+				else if (k >= 1 && k < 3)
+					bit = (r[0] >> 15) & 7;
+				else if (k >= 3 && k < 6)
+					bit = (r[0] >> 12) & 7;
+				else if (k >= 6 && k < 10)
+					bit = (r[0] >> 9) & 7;
+				else if (k >= 10 && k < 13)
+					bit = (r[0] >> 6) & 7;
+				else if (k >= 13 && k < 15)
+					bit = (r[0] >> 3) & 7;
+				else
+					bit = (r[0]) & 7;
+				if (k == 0)
+					*p8++ = 8;
+				else
+					*p8++ = j - bit;
+				*p8++ = bit;
+
+				pw = 1 << bit;
+				p0[k + 0x00] = (1 * pw) + 0x80;
+				p0[k + 0x10] = (2 * pw) + 0x80;
+				p0[k + 0x20] = (3 * pw) + 0x80;
+				p0[k + 0x30] = (4 * pw) + 0x80;
+				p0[k + 0x40] = (-1 * pw) + 0x80;
+				p0[k + 0x50] = (-2 * pw) + 0x80;
+				p0[k + 0x60] = (-3 * pw) + 0x80;
+				p0[k + 0x70] = (-4 * pw) + 0x80;
+			}	/* end of for (k=0; k<16; k++, p8++) */
+		}	/* end of for (j=0; j<8; j++ , table++) */
+	} /* end of foreach compression_mode */
+}
+
+/*
+ *
+ */
+static void fill_table_dc00_d800(struct pwc_dec23_private *pdec)
+{
+#define SCALEBITS 15
+#define ONE_HALF  (1UL << (SCALEBITS - 1))
+	int i;
+	unsigned int offset1 = ONE_HALF;
+	unsigned int offset2 = 0x0000;
+
+	for (i=0; i<256; i++) {
+		pdec->table_dc00[i] = offset1 & ~(ONE_HALF);
+		pdec->table_d800[i] = offset2;
+
+		offset1 += 0x7bc4;
+		offset2 += 0x7bc4;
+	}
+}
+
+/*
+ * To decode the stream:
+ *   if look_bits(2) == 0:	# op == 2 in the lookup table
+ *      skip_bits(2)
+ *      end of the stream
+ *   elif look_bits(3) == 7:	# op == 1 in the lookup table
+ *      skip_bits(3)
+ *      yyyy = get_bits(4)
+ *      xxxx = get_bits(8)
+ *   else:			# op == 0 in the lookup table
+ *      skip_bits(x)
+ *
+ * For speedup processing, we build a lookup table and we takes the first 6 bits.
+ *
+ * struct {
+ *   unsigned char op;	    // operation to execute
+ *   unsigned char bits;    // bits use to perform operation
+ *   unsigned char offset1; // offset to add to access in the table_0004 % 16
+ *   unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ * How to build this table ?
+ *   op == 2 when (i%4)==0
+ *   op == 1 when (i%8)==7
+ *   op == 0 otherwise
+ *
+ */
+static const unsigned char hash_table_ops[64*4] = {
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x01, 0x30,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x20,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x00,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x02, 0x10,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x60,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x40,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x40,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x01, 0x70,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x20,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x00,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x10,
+	0x00, 0x06, 0x02, 0x50,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x01, 0x60,
+	0x01, 0x00, 0x00, 0x00,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x00,
+	0x00, 0x04, 0x01, 0x50,
+	0x00, 0x05, 0x02, 0x40,
+	0x02, 0x00, 0x00, 0x00,
+	0x00, 0x03, 0x01, 0x40,
+	0x00, 0x05, 0x03, 0x40,
+	0x01, 0x00, 0x00, 0x00
+};
+
+/*
+ *
+ */
+static const unsigned int MulIdx[16][16] = {
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,},
+	{0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,},
+	{0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,},
+	{4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,},
+	{6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,},
+	{4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,},
+	{1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,},
+	{0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,},
+	{0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,},
+	{1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,},
+	{7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,},
+	{4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,},
+	{7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,},
+	{1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,},
+	{1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,},
+	{10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10}
+};
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+#define MAX_OUTER_CROP_VALUE	(512)
+static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE];
+#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)])
+#else
+#define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+#endif
+
+
+/* If the type or the command change, we rebuild the lookup table */
+int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd)
+{
+	int flags, version, shift, i;
+	struct pwc_dec23_private *pdec;
+
+	if (pwc->decompress_data == NULL) {
+		pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+		if (pdec == NULL)
+			return -ENOMEM;
+		pwc->decompress_data = pdec;
+	}
+	pdec = pwc->decompress_data;
+
+	if (DEVICE_USE_CODEC3(type)) {
+		flags = cmd[2] & 0x18;
+		if (flags == 8)
+			pdec->nbits = 7;	/* More bits, mean more bits to encode the stream, but better quality */
+		else if (flags == 0x10)
+			pdec->nbits = 8;
+		else
+			pdec->nbits = 6;
+
+		version = cmd[2] >> 5;
+		build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+		build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+
+	} else {
+
+		flags = cmd[2] & 6;
+		if (flags == 2)
+			pdec->nbits = 7;
+		else if (flags == 4)
+			pdec->nbits = 8;
+		else
+			pdec->nbits = 6;
+
+		version = cmd[2] >> 3;
+		build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1);
+		build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2);
+	}
+
+	/* Informations can be coded on a variable number of bits but never less than 8 */
+	shift = 8 - pdec->nbits;
+	pdec->scalebits = SCALEBITS - shift;
+	pdec->nbitsmask = 0xFF >> shift;
+
+	fill_table_dc00_d800(pdec);
+	build_subblock_pattern(pdec);
+	build_bit_powermask_table(pdec);
+
+#if USE_LOOKUP_TABLE_TO_CLAMP
+	/* Build the static table to clamp value [0-255] */
+	for (i=0;i<MAX_OUTER_CROP_VALUE;i++)
+		pwc_crop_table[i] = 0;
+	for (i=0; i<256; i++)
+		pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i;
+	for (i=0; i<MAX_OUTER_CROP_VALUE; i++)
+		pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255;
+#endif
+
+	return 0;
+}
+
+/*
+ * Copy the 4x4 image block to Y plane buffer
+ */
+static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+	const int *c = src;
+	unsigned char *d = dst;
+
+	*d++ = cm[c[0] >> scalebits];
+	*d++ = cm[c[1] >> scalebits];
+	*d++ = cm[c[2] >> scalebits];
+	*d++ = cm[c[3] >> scalebits];
+
+	d = dst + bytes_per_line;
+	*d++ = cm[c[4] >> scalebits];
+	*d++ = cm[c[5] >> scalebits];
+	*d++ = cm[c[6] >> scalebits];
+	*d++ = cm[c[7] >> scalebits];
+
+	d = dst + bytes_per_line*2;
+	*d++ = cm[c[8] >> scalebits];
+	*d++ = cm[c[9] >> scalebits];
+	*d++ = cm[c[10] >> scalebits];
+	*d++ = cm[c[11] >> scalebits];
+
+	d = dst + bytes_per_line*3;
+	*d++ = cm[c[12] >> scalebits];
+	*d++ = cm[c[13] >> scalebits];
+	*d++ = cm[c[14] >> scalebits];
+	*d++ = cm[c[15] >> scalebits];
+#else
+	int i;
+	const int *c = src;
+	unsigned char *d = dst;
+	for (i = 0; i < 4; i++, c++)
+		*d++ = CLAMP((*c) >> scalebits);
+
+	d = dst + bytes_per_line;
+	for (i = 0; i < 4; i++, c++)
+		*d++ = CLAMP((*c) >> scalebits);
+
+	d = dst + bytes_per_line*2;
+	for (i = 0; i < 4; i++, c++)
+		*d++ = CLAMP((*c) >> scalebits);
+
+	d = dst + bytes_per_line*3;
+	for (i = 0; i < 4; i++, c++)
+		*d++ = CLAMP((*c) >> scalebits);
+#endif
+}
+
+/*
+ * Copy the 4x4 image block to a CrCb plane buffer
+ *
+ */
+static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+	/* Unroll all loops */
+	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+	const int *c = src;
+	unsigned char *d = dst;
+
+	*d++ = cm[c[0] >> scalebits];
+	*d++ = cm[c[4] >> scalebits];
+	*d++ = cm[c[1] >> scalebits];
+	*d++ = cm[c[5] >> scalebits];
+	*d++ = cm[c[2] >> scalebits];
+	*d++ = cm[c[6] >> scalebits];
+	*d++ = cm[c[3] >> scalebits];
+	*d++ = cm[c[7] >> scalebits];
+
+	d = dst + bytes_per_line;
+	*d++ = cm[c[12] >> scalebits];
+	*d++ = cm[c[8] >> scalebits];
+	*d++ = cm[c[13] >> scalebits];
+	*d++ = cm[c[9] >> scalebits];
+	*d++ = cm[c[14] >> scalebits];
+	*d++ = cm[c[10] >> scalebits];
+	*d++ = cm[c[15] >> scalebits];
+	*d++ = cm[c[11] >> scalebits];
+#else
+	int i;
+	const int *c1 = src;
+	const int *c2 = src + 4;
+	unsigned char *d = dst;
+
+	for (i = 0; i < 4; i++, c1++, c2++) {
+		*d++ = CLAMP((*c1) >> scalebits);
+		*d++ = CLAMP((*c2) >> scalebits);
+	}
+	c1 = src + 12;
+	d = dst + bytes_per_line;
+	for (i = 0; i < 4; i++, c1++, c2++) {
+		*d++ = CLAMP((*c1) >> scalebits);
+		*d++ = CLAMP((*c2) >> scalebits);
+	}
+#endif
+}
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Format: 8x2 pixels
+ *   . G . G . G . G . G . G . G
+ *   . . . . . . . . . . . . . .
+ *   . G . G . G . G . G . G . G
+ *   . . . . . . . . . . . . . .
+ *   or
+ *   . . . . . . . . . . . . . .
+ *   G . G . G . G . G . G . G .
+ *   . . . . . . . . . . . . . .
+ *   G . G . G . G . G . G . G .
+*/
+static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+	/* Unroll all loops */
+	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+	unsigned char *d = dst;
+	const int *c = src;
+
+	d[0] = cm[c[0] >> scalebits];
+	d[2] = cm[c[1] >> scalebits];
+	d[4] = cm[c[2] >> scalebits];
+	d[6] = cm[c[3] >> scalebits];
+	d[8] = cm[c[4] >> scalebits];
+	d[10] = cm[c[5] >> scalebits];
+	d[12] = cm[c[6] >> scalebits];
+	d[14] = cm[c[7] >> scalebits];
+
+	d = dst + bytes_per_line;
+	d[0] = cm[c[8] >> scalebits];
+	d[2] = cm[c[9] >> scalebits];
+	d[4] = cm[c[10] >> scalebits];
+	d[6] = cm[c[11] >> scalebits];
+	d[8] = cm[c[12] >> scalebits];
+	d[10] = cm[c[13] >> scalebits];
+	d[12] = cm[c[14] >> scalebits];
+	d[14] = cm[c[15] >> scalebits];
+#else
+	int i;
+	unsigned char *d;
+	const int *c = src;
+
+	d = dst;
+	for (i = 0; i < 8; i++, c++)
+		d[i*2] = CLAMP((*c) >> scalebits);
+
+	d = dst + bytes_per_line;
+	for (i = 0; i < 8; i++, c++)
+		d[i*2] = CLAMP((*c) >> scalebits);
+#endif
+}
+#endif
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Format: 4x4 pixels
+ *   R . R . R . R
+ *   . B . B . B .
+ *   R . R . R . R
+ *   . B . B . B .
+ */
+static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits)
+{
+#if UNROLL_LOOP_FOR_COPY
+	/* Unroll all loops */
+	const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE;
+	unsigned char *d = dst;
+	const int *c = src;
+
+	d[0] = cm[c[0] >> scalebits];
+	d[2] = cm[c[1] >> scalebits];
+	d[4] = cm[c[2] >> scalebits];
+	d[6] = cm[c[3] >> scalebits];
+
+	d = dst + bytes_per_line;
+	d[1] = cm[c[4] >> scalebits];
+	d[3] = cm[c[5] >> scalebits];
+	d[5] = cm[c[6] >> scalebits];
+	d[7] = cm[c[7] >> scalebits];
+
+	d = dst + bytes_per_line*2;
+	d[0] = cm[c[8] >> scalebits];
+	d[2] = cm[c[9] >> scalebits];
+	d[4] = cm[c[10] >> scalebits];
+	d[6] = cm[c[11] >> scalebits];
+
+	d = dst + bytes_per_line*3;
+	d[1] = cm[c[12] >> scalebits];
+	d[3] = cm[c[13] >> scalebits];
+	d[5] = cm[c[14] >> scalebits];
+	d[7] = cm[c[15] >> scalebits];
+#else
+	int i;
+	unsigned char *d;
+	const int *c = src;
+
+	d = dst;
+	for (i = 0; i < 4; i++, c++)
+		d[i*2] = CLAMP((*c) >> scalebits);
+
+	d = dst + bytes_per_line;
+	for (i = 0; i < 4; i++, c++)
+		d[i*2+1] = CLAMP((*c) >> scalebits);
+
+	d = dst + bytes_per_line*2;
+	for (i = 0; i < 4; i++, c++)
+		d[i*2] = CLAMP((*c) >> scalebits);
+
+	d = dst + bytes_per_line*3;
+	for (i = 0; i < 4; i++, c++)
+		d[i*2+1] = CLAMP((*c) >> scalebits);
+#endif
+}
+#endif
+
+/*
+ * To manage the stream, we keep bits in a 32 bits register.
+ * fill_nbits(n): fill the reservoir with at least n bits
+ * skip_bits(n): discard n bits from the reservoir
+ * get_bits(n): fill the reservoir, returns the first n bits and discard the
+ *              bits from the reservoir.
+ * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir
+ *                 contains at least n bits. bits returned is discarded.
+ */
+#define fill_nbits(pdec, nbits_wanted) do { \
+   while (pdec->nbits_in_reservoir<(nbits_wanted)) \
+    { \
+      pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \
+      pdec->nbits_in_reservoir += 8; \
+    } \
+}  while(0);
+
+#define skip_nbits(pdec, nbits_to_skip) do { \
+   pdec->reservoir >>= (nbits_to_skip); \
+   pdec->nbits_in_reservoir -= (nbits_to_skip); \
+}  while(0);
+
+#define get_nbits(pdec, nbits_wanted, result) do { \
+   fill_nbits(pdec, nbits_wanted); \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define __get_nbits(pdec, nbits_wanted, result) do { \
+   result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \
+   skip_nbits(pdec, nbits_wanted); \
+}  while(0);
+
+#define look_nbits(pdec, nbits_wanted) \
+   ((pdec->reservoir) & ((1U<<(nbits_wanted))-1))
+
+/*
+ * Decode a 4x4 pixel block
+ */
+static void decode_block(struct pwc_dec23_private *pdec,
+			 const unsigned char *ptable0004,
+			 const unsigned char *ptable8004)
+{
+	unsigned int primary_color;
+	unsigned int channel_v, offset1, op;
+	int i;
+
+	fill_nbits(pdec, 16);
+	__get_nbits(pdec, pdec->nbits, primary_color);
+
+	if (look_nbits(pdec,2) == 0) {
+		skip_nbits(pdec, 2);
+		/* Very simple, the color is the same for all pixels of the square */
+		for (i = 0; i < 16; i++)
+			pdec->temp_colors[i] = pdec->table_dc00[primary_color];
+
+		return;
+	}
+
+	/* This block is encoded with small pattern */
+	for (i = 0; i < 16; i++)
+		pdec->temp_colors[i] = pdec->table_d800[primary_color];
+
+	__get_nbits(pdec, 3, channel_v);
+	channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2);
+
+	ptable0004 += (channel_v * 128);
+	ptable8004 += (channel_v * 32);
+
+	offset1 = 0;
+	do
+	{
+		unsigned int htable_idx, rows = 0;
+		const unsigned int *block;
+
+		/* [  zzzz y x x ]
+		 *     xx == 00 :=> end of the block def, remove the two bits from the stream
+		 *    yxx == 111
+		 *    yxx == any other value
+		 *
+		 */
+		fill_nbits(pdec, 16);
+		htable_idx = look_nbits(pdec, 6);
+		op = hash_table_ops[htable_idx * 4];
+
+		if (op == 2) {
+			skip_nbits(pdec, 2);
+
+		} else if (op == 1) {
+			/* 15bits [ xxxx xxxx yyyy 111 ]
+			 * yyy => offset in the table8004
+			 * xxx => offset in the tabled004 (tree)
+			 */
+			unsigned int mask, shift;
+			unsigned int nbits, col1;
+			unsigned int yyyy;
+
+			skip_nbits(pdec, 3);
+			/* offset1 += yyyy */
+			__get_nbits(pdec, 4, yyyy);
+			offset1 += 1 + yyyy;
+			offset1 &= 0x0F;
+			nbits = ptable8004[offset1 * 2];
+
+			/* col1 = xxxx xxxx */
+			__get_nbits(pdec, nbits+1, col1);
+
+			/* Bit mask table */
+			mask = pdec->table_bitpowermask[nbits][col1];
+			shift = ptable8004[offset1 * 2 + 1];
+			rows = ((mask << shift) + 0x80) & 0xFF;
+
+			block = pdec->table_subblock[rows];
+			for (i = 0; i < 16; i++)
+				pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+		} else {
+			/* op == 0
+			 * offset1 is coded on 3 bits
+			 */
+			unsigned int shift;
+
+			offset1 += hash_table_ops [htable_idx * 4 + 2];
+			offset1 &= 0x0F;
+
+			rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]];
+			block = pdec->table_subblock[rows];
+			for (i = 0; i < 16; i++)
+				pdec->temp_colors[i] += block[MulIdx[offset1][i]];
+
+			shift = hash_table_ops[htable_idx * 4 + 1];
+			skip_nbits(pdec, shift);
+		}
+
+	} while (op != 2);
+
+}
+
+static void DecompressBand23(struct pwc_dec23_private *pdec,
+			     const unsigned char *rawyuv,
+			     unsigned char *planar_y,
+			     unsigned char *planar_u,
+			     unsigned char *planar_v,
+			     unsigned int   compressed_image_width,
+			     unsigned int   real_image_width)
+{
+	int compression_index, nblocks;
+	const unsigned char *ptable0004;
+	const unsigned char *ptable8004;
+
+	pdec->reservoir = 0;
+	pdec->nbits_in_reservoir = 0;
+	pdec->stream = rawyuv + 1;	/* The first byte of the stream is skipped */
+
+	get_nbits(pdec, 4, compression_index);
+
+	/* pass 1: uncompress Y component */
+	nblocks = compressed_image_width / 4;
+
+	ptable0004 = pdec->table_0004_pass1[compression_index];
+	ptable8004 = pdec->table_8004_pass1[compression_index];
+
+	/* Each block decode a square of 4x4 */
+	while (nblocks) {
+		decode_block(pdec, ptable0004, ptable8004);
+		copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits);
+		planar_y += 4;
+		nblocks--;
+	}
+
+	/* pass 2: uncompress UV component */
+	nblocks = compressed_image_width / 8;
+
+	ptable0004 = pdec->table_0004_pass2[compression_index];
+	ptable8004 = pdec->table_8004_pass2[compression_index];
+
+	/* Each block decode a square of 4x4 */
+	while (nblocks) {
+		decode_block(pdec, ptable0004, ptable8004);
+		copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits);
+
+		decode_block(pdec, ptable0004, ptable8004);
+		copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits);
+
+		planar_v += 8;
+		planar_u += 8;
+		nblocks -= 2;
+	}
+
+}
+
+#if ENABLE_BAYER_DECODER
+/*
+ * Size need to be a multiple of 8 in width
+ *
+ * Return a block of four line encoded like this:
+ *
+ *   G R G R G R G R G R G R G R G R
+ *   B G B G B G B G B G B G B G B G
+ *   G R G R G R G R G R G R G R G R
+ *   B G B G B G B G B G B G B G B G
+ *
+ */
+static void DecompressBandBayer(struct pwc_dec23_private *pdec,
+				const unsigned char *rawyuv,
+				unsigned char *rgbbayer,
+				unsigned int   compressed_image_width,
+				unsigned int   real_image_width)
+{
+	int compression_index, nblocks;
+	const unsigned char *ptable0004;
+	const unsigned char *ptable8004;
+	unsigned char *dest;
+
+	pdec->reservoir = 0;
+	pdec->nbits_in_reservoir = 0;
+	pdec->stream = rawyuv + 1;	/* The first byte of the stream is skipped */
+
+	get_nbits(pdec, 4, compression_index);
+
+	/* pass 1: uncompress RB component */
+	nblocks = compressed_image_width / 4;
+
+	ptable0004 = pdec->table_0004_pass1[compression_index];
+	ptable8004 = pdec->table_8004_pass1[compression_index];
+	dest = rgbbayer;
+
+	/* Each block decode a square of 4x4 */
+	while (nblocks) {
+		decode_block(pdec, ptable0004, ptable8004);
+		copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits);
+		dest += 8;
+		nblocks--;
+	}
+
+	/* pass 2: uncompress G component */
+	nblocks = compressed_image_width / 8;
+
+	ptable0004 = pdec->table_0004_pass2[compression_index];
+	ptable8004 = pdec->table_8004_pass2[compression_index];
+
+	/* Each block decode a square of 4x4 */
+	while (nblocks) {
+		decode_block(pdec, ptable0004, ptable8004);
+		copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits);
+
+		decode_block(pdec, ptable0004, ptable8004);
+		copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits);
+
+		rgbbayer += 16;
+		nblocks -= 2;
+	}
+}
+#endif
+
+
+/**
+ *
+ * Uncompress a pwc23 buffer.
+ *
+ * pwc.view: size of the image wanted
+ * pwc.image: size of the image returned by the camera
+ * pwc.offset: (x,y) to displayer image in the view
+ *
+ * src: raw data
+ * dst: image output
+ * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER
+ */
+void pwc_dec23_decompress(const struct pwc_device *pwc,
+			  const void *src,
+			  void *dst,
+			  int flags)
+{
+	int bandlines_left, stride, bytes_per_block;
+
+	bandlines_left = pwc->image.y / 4;
+	bytes_per_block = pwc->view.x * 4;
+
+	if (flags & PWCX_FLAG_BAYER) {
+#if ENABLE_BAYER_DECODER
+		/* RGB Bayer format */
+		unsigned char *rgbout;
+
+		stride = pwc->view.x * pwc->offset.y;
+		rgbout = dst + stride + pwc->offset.x;
+
+
+		while (bandlines_left--) {
+
+			DecompressBandBayer(pwc->decompress_data,
+					    src,
+					    rgbout,
+					    pwc->image.x, pwc->view.x);
+
+			src += pwc->vbandlength;
+			rgbout += bytes_per_block;
+
+		}
+#else
+		memset(dst, 0, pwc->view.x * pwc->view.y);
+#endif
+
+	} else {
+		/* YUV420P image format */
+		unsigned char *pout_planar_y;
+		unsigned char *pout_planar_u;
+		unsigned char *pout_planar_v;
+		unsigned int   plane_size;
+
+		plane_size = pwc->view.x * pwc->view.y;
+
+		/* offset in Y plane */
+		stride = pwc->view.x * pwc->offset.y;
+		pout_planar_y = dst + stride + pwc->offset.x;
+
+		/* offsets in U/V planes */
+		stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2;
+		pout_planar_u = dst + plane_size + stride;
+		pout_planar_v = dst + plane_size + plane_size / 4 + stride;
+
+		while (bandlines_left--) {
+
+			DecompressBand23(pwc->decompress_data,
+					 src,
+					 pout_planar_y, pout_planar_u, pout_planar_v,
+					 pwc->image.x, pwc->view.x);
+			src += pwc->vbandlength;
+			pout_planar_y += bytes_per_block;
+			pout_planar_u += pwc->view.x;
+			pout_planar_v += pwc->view.x;
+
+		}
+
+	}
+
+}
+
+void pwc_dec23_exit(void)
+{
+	/* Do nothing */
+
+}
+
+/**
+ * Allocate a private structure used by lookup table.
+ * You must call kfree() to free the memory allocated.
+ */
+int pwc_dec23_alloc(struct pwc_device *pwc)
+{
+	pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+	if (pwc->decompress_data == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
new file mode 100644
index 0000000..1c55298
--- /dev/null
+++ b/drivers/media/video/pwc/pwc-dec23.h
@@ -0,0 +1,67 @@
+/* Linux driver for Philips webcam
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef PWC_DEC23_H
+#define PWC_DEC23_H
+
+#include "pwc.h"
+
+struct pwc_dec23_private
+{
+  unsigned int scalebits;
+  unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */
+
+  unsigned int reservoir;
+  unsigned int nbits_in_reservoir;
+  const unsigned char *stream;
+  int temp_colors[16];
+
+  unsigned char table_0004_pass1[16][1024];
+  unsigned char table_0004_pass2[16][1024];
+  unsigned char table_8004_pass1[16][256];
+  unsigned char table_8004_pass2[16][256];
+  unsigned int  table_subblock[256][12];
+
+  unsigned char table_bitpowermask[8][256];
+  unsigned int  table_d800[256];
+  unsigned int  table_dc00[256];
+
+};
+
+
+int pwc_dec23_alloc(struct pwc_device *pwc);
+int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
+void pwc_dec23_exit(void);
+void pwc_dec23_decompress(const struct pwc_device *pwc,
+			  const void *src,
+			  void *dst,
+			  int flags);
+
+
+
+#endif
+
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
+
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 4141829..47d0d83 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    USB and Video4Linux interface part.
    (C) 1999-2004 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -62,18 +62,21 @@
 #include <linux/poll.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
+#include <linux/version.h>
 #include <asm/io.h>
+#include <linux/moduleparam.h>
 
 #include "pwc.h"
-#include "pwc-ioctl.h"
 #include "pwc-kiara.h"
 #include "pwc-timon.h"
+#include "pwc-dec23.h"
+#include "pwc-dec1.h"
 #include "pwc-uncompress.h"
 
 /* Function prototypes and driver templates */
 
 /* hotplug device table support */
-static struct usb_device_id pwc_device_table [] = {
+static const struct usb_device_id pwc_device_table [] = {
 	{ USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
 	{ USB_DEVICE(0x0471, 0x0303) },
 	{ USB_DEVICE(0x0471, 0x0304) },
@@ -81,9 +84,10 @@
 	{ USB_DEVICE(0x0471, 0x0308) },
 	{ USB_DEVICE(0x0471, 0x030C) },
 	{ USB_DEVICE(0x0471, 0x0310) },
-	{ USB_DEVICE(0x0471, 0x0311) },
+	{ USB_DEVICE(0x0471, 0x0311) }, /* Philips ToUcam PRO II */
 	{ USB_DEVICE(0x0471, 0x0312) },
 	{ USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
+	{ USB_DEVICE(0x0471, 0x0329) }, /* Philips SPC 900NC PC Camera */
 	{ USB_DEVICE(0x069A, 0x0001) }, /* Askey */
 	{ USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
 	{ USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
@@ -94,8 +98,9 @@
 	{ USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */
 	{ USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */
 	{ USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
-	{ USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
-	{ USB_DEVICE(0x055D, 0x9001) },
+	{ USB_DEVICE(0x055D, 0x9000) }, /* Samsung MPC-C10 */
+	{ USB_DEVICE(0x055D, 0x9001) }, /* Samsung MPC-C30 */
+	{ USB_DEVICE(0x055D, 0x9002) },	/* Samsung SNC-35E (Ver3.0) */
 	{ USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
 	{ USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
 	{ USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
@@ -122,11 +127,13 @@
 static int default_size = PSZ_QCIF;
 static int default_fps = 10;
 static int default_fbufs = 3;   /* Default number of frame buffers */
-static int default_mbufs = 2;	/* Default number of mmap() buffers */
-       int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
+       int pwc_mbufs = 2;	/* Default number of mmap() buffers */
+#if CONFIG_PWC_DEBUG
+       int pwc_trace = PWC_DEBUG_LEVEL;
+#endif
 static int power_save = 0;
 static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
-static int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
 static struct {
 	int type;
 	char serial_number[30];
@@ -138,7 +145,7 @@
 
 static int pwc_video_open(struct inode *inode, struct file *file);
 static int pwc_video_close(struct inode *inode, struct file *file);
-static ssize_t pwc_video_read(struct file *file, char __user * buf,
+static ssize_t pwc_video_read(struct file *file, char __user *buf,
 			  size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
 static int  pwc_video_ioctl(struct inode *inode, struct file *file,
@@ -153,7 +160,6 @@
 	.poll =		pwc_video_poll,
 	.mmap =		pwc_video_mmap,
 	.ioctl =        pwc_video_ioctl,
-	.compat_ioctl = v4l_compat_ioctl32,
 	.llseek =       no_llseek,
 };
 static struct video_device pwc_template = {
@@ -203,52 +209,44 @@
 /* Here we want the physical address of the memory.
  * This is used when initializing the contents of the area.
  */
-static inline unsigned long kvirt_to_pa(unsigned long adr)
-{
-	unsigned long kva, ret;
 
-	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
-	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
-	ret = __pa(kva);
-	return ret;
-}
 
-static void * rvmalloc(unsigned long size)
+
+static void *pwc_rvmalloc(unsigned long size)
 {
 	void * mem;
 	unsigned long adr;
 
-	size=PAGE_ALIGN(size);
 	mem=vmalloc_32(size);
-	if (mem)
-	{
-		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
-		adr=(unsigned long) mem;
-		while (size > 0)
-		{
-			SetPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-	}
+	if (!mem)
+		return NULL;
+
+	memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	adr=(unsigned long) mem;
+	while (size > 0)
+	 {
+	   SetPageReserved(vmalloc_to_page((void *)adr));
+	   adr  += PAGE_SIZE;
+	   size -= PAGE_SIZE;
+	 }
 	return mem;
 }
 
-static void rvfree(void * mem, unsigned long size)
+static void pwc_rvfree(void * mem, unsigned long size)
 {
 	unsigned long adr;
 
-	if (mem)
-	{
-		adr=(unsigned long) mem;
-		while ((long) size > 0)
-		{
-			ClearPageReserved(vmalloc_to_page((void *)adr));
-			adr+=PAGE_SIZE;
-			size-=PAGE_SIZE;
-		}
-		vfree(mem);
-	}
+	if (!mem)
+		return;
+
+	adr=(unsigned long) mem;
+	while ((long) size > 0)
+	 {
+	   ClearPageReserved(vmalloc_to_page((void *)adr));
+	   adr  += PAGE_SIZE;
+	   size -= PAGE_SIZE;
+	 }
+	vfree(mem);
 }
 
 
@@ -256,100 +254,83 @@
 
 static int pwc_allocate_buffers(struct pwc_device *pdev)
 {
-	int i;
+	int i, err;
 	void *kbuf;
 
-	Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
+	PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
 
 	if (pdev == NULL)
 		return -ENXIO;
 
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("allocate_buffers(): magic failed.\n");
-		return -ENXIO;
-	}
-#endif
-	/* Allocate Isochronous pipe buffers */
+	/* Allocate Isochronuous pipe buffers */
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		if (pdev->sbuf[i].data == NULL) {
-			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+			kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
 			if (kbuf == NULL) {
-				Err("Failed to allocate iso buffer %d.\n", i);
+				PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
 				return -ENOMEM;
 			}
-			Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
+			PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
 			pdev->sbuf[i].data = kbuf;
-			memset(kbuf, 0, ISO_BUFFER_SIZE);
 		}
 	}
 
 	/* Allocate frame buffer structure */
 	if (pdev->fbuf == NULL) {
-		kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
+		kbuf = kzalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
 		if (kbuf == NULL) {
-			Err("Failed to allocate frame buffer structure.\n");
+			PWC_ERROR("Failed to allocate frame buffer structure.\n");
 			return -ENOMEM;
 		}
-		Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
+		PWC_DEBUG_MEMORY("Allocated frame buffer structure at %p.\n", kbuf);
 		pdev->fbuf = kbuf;
-		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
 	}
+
 	/* create frame buffers, and make circular ring */
 	for (i = 0; i < default_fbufs; i++) {
 		if (pdev->fbuf[i].data == NULL) {
 			kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
 			if (kbuf == NULL) {
-				Err("Failed to allocate frame buffer %d.\n", i);
+				PWC_ERROR("Failed to allocate frame buffer %d.\n", i);
 				return -ENOMEM;
 			}
-			Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
+			PWC_DEBUG_MEMORY("Allocated frame buffer %d at %p.\n", i, kbuf);
 			pdev->fbuf[i].data = kbuf;
-			memset(kbuf, 128, PWC_FRAME_SIZE);
+			memset(kbuf, 0, PWC_FRAME_SIZE);
 		}
 	}
 
 	/* Allocate decompressor table space */
-	kbuf = NULL;
-	switch (pdev->type)
-	 {
-	  case 675:
-	  case 680:
-	  case 690:
-	  case 720:
-	  case 730:
-	  case 740:
-	  case 750:
-#if 0
-	    Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private));
-	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);	/* Timon & Kiara */
-	    break;
-	  case 645:
-	  case 646:
-	    /* TODO & FIXME */
-	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
-	    break;
-#endif
-	;
-	 }
-	pdev->decompress_data = kbuf;
+	if (DEVICE_USE_CODEC1(pdev->type))
+		err = pwc_dec1_alloc(pdev);
+	else
+		err = pwc_dec23_alloc(pdev);
+
+	if (err) {
+		PWC_ERROR("Failed to allocate decompress table.\n");
+		return err;
+	}
 
 	/* Allocate image buffer; double buffer for mmap() */
-	kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
+	kbuf = pwc_rvmalloc(pwc_mbufs * pdev->len_per_image);
 	if (kbuf == NULL) {
-		Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image);
+		PWC_ERROR("Failed to allocate image buffer(s). needed (%d)\n",
+				pwc_mbufs * pdev->len_per_image);
 		return -ENOMEM;
 	}
-	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
+	PWC_DEBUG_MEMORY("Allocated image buffer at %p.\n", kbuf);
 	pdev->image_data = kbuf;
-	for (i = 0; i < default_mbufs; i++)
-		pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
-	for (; i < MAX_IMAGES; i++)
-		pdev->image_ptr[i] = NULL;
+	for (i = 0; i < pwc_mbufs; i++) {
+		pdev->images[i].offset = i * pdev->len_per_image;
+		pdev->images[i].vma_use_count = 0;
+	}
+	for (; i < MAX_IMAGES; i++) {
+		pdev->images[i].offset = 0;
+	}
 
 	kbuf = NULL;
 
-	Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
+	PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n");
 	return 0;
 }
 
@@ -357,21 +338,14 @@
 {
 	int i;
 
-	Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+	PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev);
 
 	if (pdev == NULL)
 		return;
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("free_buffers(): magic failed.\n");
-		return;
-	}
-#endif
-
 	/* Release Iso-pipe buffers */
 	for (i = 0; i < MAX_ISO_BUFS; i++)
 		if (pdev->sbuf[i].data != NULL) {
-			Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
+			PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
 			kfree(pdev->sbuf[i].data);
 			pdev->sbuf[i].data = NULL;
 		}
@@ -380,7 +354,7 @@
 	if (pdev->fbuf != NULL) {
 		for (i = 0; i < default_fbufs; i++) {
 			if (pdev->fbuf[i].data != NULL) {
-				Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
+				PWC_DEBUG_MEMORY("Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
 				vfree(pdev->fbuf[i].data);
 				pdev->fbuf[i].data = NULL;
 			}
@@ -391,20 +365,19 @@
 
 	/* Intermediate decompression buffer & tables */
 	if (pdev->decompress_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
+		PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data);
 		kfree(pdev->decompress_data);
 		pdev->decompress_data = NULL;
 	}
-	pdev->decompressor = NULL;
 
 	/* Release image buffers */
 	if (pdev->image_data != NULL) {
-		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
-		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
+		PWC_DEBUG_MEMORY("Freeing image buffer at %p.\n", pdev->image_data);
+		pwc_rvfree(pdev->image_data, pwc_mbufs * pdev->len_per_image);
 	}
 	pdev->image_data = NULL;
 
-	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+	PWC_DEBUG_MEMORY("Leaving free_buffers().\n");
 }
 
 /* The frame & image buffer mess.
@@ -464,7 +437,7 @@
 /**
   \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
  */
-static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+static int pwc_next_fill_frame(struct pwc_device *pdev)
 {
 	int ret;
 	unsigned long flags;
@@ -489,23 +462,17 @@
 	}
 	else {
 		/* Hmm. Take it from the full list */
-#if PWC_DEBUG
 		/* sanity check */
 		if (pdev->full_frames == NULL) {
-			Err("Neither empty or full frames available!\n");
+			PWC_ERROR("Neither empty or full frames available!\n");
 			spin_unlock_irqrestore(&pdev->ptrlock, flags);
 			return -EINVAL;
 		}
-#endif
 		pdev->fill_frame = pdev->full_frames;
 		pdev->full_frames = pdev->full_frames->next;
 		ret = 1;
 	}
 	pdev->fill_frame->next = NULL;
-#if PWC_DEBUG
-	Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
-	pdev->fill_frame->sequence = pdev->sequence++;
-#endif
 	spin_unlock_irqrestore(&pdev->ptrlock, flags);
 	return ret;
 }
@@ -521,6 +488,8 @@
 	int i;
 	unsigned long flags;
 
+	PWC_DEBUG_MEMORY(">> %s __enter__\n", __FUNCTION__);
+
 	spin_lock_irqsave(&pdev->ptrlock, flags);
 	pdev->full_frames = NULL;
 	pdev->full_frames_tail = NULL;
@@ -540,13 +509,15 @@
 	pdev->image_read_pos = 0;
 	pdev->fill_image = 0;
 	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+
+	PWC_DEBUG_MEMORY("<< %s __leaving__\n", __FUNCTION__);
 }
 
 
 /**
   \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
  */
-static int pwc_handle_frame(struct pwc_device *pdev)
+int pwc_handle_frame(struct pwc_device *pdev)
 {
 	int ret = 0;
 	unsigned long flags;
@@ -556,41 +527,40 @@
 	   we can release the lock after this without problems */
 	if (pdev->read_frame != NULL) {
 		/* This can't theoretically happen */
-		Err("Huh? Read frame still in use?\n");
+		PWC_ERROR("Huh? Read frame still in use?\n");
+		spin_unlock_irqrestore(&pdev->ptrlock, flags);
+		return ret;
+	}
+
+
+	if (pdev->full_frames == NULL) {
+		PWC_ERROR("Woops. No frames ready.\n");
 	}
 	else {
-		if (pdev->full_frames == NULL) {
-			Err("Woops. No frames ready.\n");
+		pdev->read_frame = pdev->full_frames;
+		pdev->full_frames = pdev->full_frames->next;
+		pdev->read_frame->next = NULL;
+	}
+
+	if (pdev->read_frame != NULL) {
+		/* Decompression is a lenghty process, so it's outside of the lock.
+		   This gives the isoc_handler the opportunity to fill more frames
+		   in the mean time.
+		*/
+		spin_unlock_irqrestore(&pdev->ptrlock, flags);
+		ret = pwc_decompress(pdev);
+		spin_lock_irqsave(&pdev->ptrlock, flags);
+
+		/* We're done with read_buffer, tack it to the end of the empty buffer list */
+		if (pdev->empty_frames == NULL) {
+			pdev->empty_frames = pdev->read_frame;
+			pdev->empty_frames_tail = pdev->empty_frames;
 		}
 		else {
-			pdev->read_frame = pdev->full_frames;
-			pdev->full_frames = pdev->full_frames->next;
-			pdev->read_frame->next = NULL;
+			pdev->empty_frames_tail->next = pdev->read_frame;
+			pdev->empty_frames_tail = pdev->read_frame;
 		}
-
-		if (pdev->read_frame != NULL) {
-#if PWC_DEBUG
-			Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
-#endif
-			/* Decompression is a lenghty process, so it's outside of the lock.
-			   This gives the isoc_handler the opportunity to fill more frames
-			   in the mean time.
-			*/
-			spin_unlock_irqrestore(&pdev->ptrlock, flags);
-			ret = pwc_decompress(pdev);
-			spin_lock_irqsave(&pdev->ptrlock, flags);
-
-			/* We're done with read_buffer, tack it to the end of the empty buffer list */
-			if (pdev->empty_frames == NULL) {
-				pdev->empty_frames = pdev->read_frame;
-				pdev->empty_frames_tail = pdev->empty_frames;
-			}
-			else {
-				pdev->empty_frames_tail->next = pdev->read_frame;
-				pdev->empty_frames_tail = pdev->read_frame;
-			}
-			pdev->read_frame = NULL;
-		}
+		pdev->read_frame = NULL;
 	}
 	spin_unlock_irqrestore(&pdev->ptrlock, flags);
 	return ret;
@@ -599,12 +569,114 @@
 /**
   \brief Advance pointers of image buffer (after each user request)
 */
-static inline void pwc_next_image(struct pwc_device *pdev)
+void pwc_next_image(struct pwc_device *pdev)
 {
 	pdev->image_used[pdev->fill_image] = 0;
-	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+	pdev->fill_image = (pdev->fill_image + 1) % pwc_mbufs;
 }
 
+/**
+ * Print debug information when a frame is discarded because all of our buffer
+ * is full
+ */
+static void pwc_frame_dumped(struct pwc_device *pdev)
+{
+	pdev->vframes_dumped++;
+	if (pdev->vframe_count < FRAME_LOWMARK)
+		return;
+
+	if (pdev->vframes_dumped < 20)
+		PWC_DEBUG_FLOW("Dumping frame %d\n", pdev->vframe_count);
+	else if (pdev->vframes_dumped == 20)
+		PWC_DEBUG_FLOW("Dumping frame %d (last message)\n",
+				pdev->vframe_count);
+}
+
+static int pwc_rcv_short_packet(struct pwc_device *pdev, const struct pwc_frame_buf *fbuf)
+{
+	int awake = 0;
+
+	/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
+	   frames on the USB wire after an exposure change. This conditition is
+	   however detected  in the cam and a bit is set in the header.
+	   */
+	if (pdev->type == 730) {
+		unsigned char *ptr = (unsigned char *)fbuf->data;
+
+		if (ptr[1] == 1 && ptr[0] & 0x10) {
+			PWC_TRACE("Hyundai CMOS sensor bug. Dropping frame.\n");
+			pdev->drop_frames += 2;
+			pdev->vframes_error++;
+		}
+		if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+			if (ptr[0] & 0x01) {
+				pdev->snapshot_button_status = 1;
+				PWC_TRACE("Snapshot button pressed.\n");
+			}
+			else {
+				PWC_TRACE("Snapshot button released.\n");
+			}
+		}
+		if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+			if (ptr[0] & 0x02)
+				PWC_TRACE("Image is mirrored.\n");
+			else
+				PWC_TRACE("Image is normal.\n");
+		}
+		pdev->vmirror = ptr[0] & 0x03;
+		/* Sometimes the trailer of the 730 is still sent as a 4 byte packet
+		   after a short frame; this condition is filtered out specifically. A 4 byte
+		   frame doesn't make sense anyway.
+		   So we get either this sequence:
+		   drop_bit set -> 4 byte frame -> short frame -> good frame
+		   Or this one:
+		   drop_bit set -> short frame -> good frame
+		   So we drop either 3 or 2 frames in all!
+		   */
+		if (fbuf->filled == 4)
+			pdev->drop_frames++;
+	}
+	else if (pdev->type == 740 || pdev->type == 720) {
+		unsigned char *ptr = (unsigned char *)fbuf->data;
+		if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+			if (ptr[0] & 0x01) {
+				pdev->snapshot_button_status = 1;
+				PWC_TRACE("Snapshot button pressed.\n");
+			}
+			else
+				PWC_TRACE("Snapshot button released.\n");
+		}
+		pdev->vmirror = ptr[0] & 0x03;
+	}
+
+	/* In case we were instructed to drop the frame, do so silently.
+	   The buffer pointers are not updated either (but the counters are reset below).
+	   */
+	if (pdev->drop_frames > 0)
+		pdev->drop_frames--;
+	else {
+		/* Check for underflow first */
+		if (fbuf->filled < pdev->frame_total_size) {
+			PWC_DEBUG_FLOW("Frame buffer underflow (%d bytes);"
+				       " discarded.\n", fbuf->filled);
+			pdev->vframes_error++;
+		}
+		else {
+			/* Send only once per EOF */
+			awake = 1; /* delay wake_ups */
+
+			/* Find our next frame to fill. This will always succeed, since we
+			 * nick a frame from either empty or full list, but if we had to
+			 * take it from the full list, it means a frame got dropped.
+			 */
+			if (pwc_next_fill_frame(pdev))
+				pwc_frame_dumped(pdev);
+
+		}
+	} /* !drop_frames */
+	pdev->vframe_count++;
+	return awake;
+}
 
 /* This gets called for the Isochronous pipe (video). This is done in
  * interrupt time, so it has to be fast, not crash, and not stall. Neat.
@@ -620,17 +692,12 @@
 	awake = 0;
 	pdev = (struct pwc_device *)urb->context;
 	if (pdev == NULL) {
-		Err("isoc_handler() called with NULL device?!\n");
+		PWC_ERROR("isoc_handler() called with NULL device?!\n");
 		return;
 	}
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("isoc_handler() called with bad magic!\n");
-		return;
-	}
-#endif
+
 	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
-		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
+		PWC_DEBUG_OPEN("URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
 		return;
 	}
 	if (urb->status != -EINPROGRESS && urb->status != 0) {
@@ -645,13 +712,13 @@
 			case -EILSEQ:		errmsg = "CRC/Timeout (could be anything)"; break;
 			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
 		}
-		Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
+		PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
 		/* Give up after a number of contiguous errors on the USB bus.
 		   Appearantly something is wrong so we simulate an unplug event.
 		 */
 		if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
 		{
-			Info("Too many ISOC errors, bailing out.\n");
+			PWC_INFO("Too many ISOC errors, bailing out.\n");
 			pdev->error_status = EIO;
 			awake = 1;
 			wake_up_interruptible(&pdev->frameq);
@@ -661,7 +728,7 @@
 
 	fbuf = pdev->fill_frame;
 	if (fbuf == NULL) {
-		Err("pwc_isoc_handler without valid fill frame.\n");
+		PWC_ERROR("pwc_isoc_handler without valid fill frame.\n");
 		awake = 1;
 		goto handler_end;
 	}
@@ -688,7 +755,7 @@
 
 					/* ...copy data to frame buffer, if possible */
 					if (flen + fbuf->filled > pdev->frame_total_size) {
-						Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
+						PWC_DEBUG_FLOW("Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
 						pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
 						pdev->vframes_error++;
 					}
@@ -704,96 +771,28 @@
 				/* Shorter packet... We probably have the end of an image-frame;
 				   wake up read() process and let select()/poll() do something.
 				   Decompression is done in user time over there.
-				 */
+				   */
 				if (pdev->vsync == 2) {
-					/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus
-					   frames on the USB wire after an exposure change. This conditition is
-					   however detected  in the cam and a bit is set in the header.
-					 */
-					if (pdev->type == 730) {
-						unsigned char *ptr = (unsigned char *)fbuf->data;
-
-						if (ptr[1] == 1 && ptr[0] & 0x10) {
-#if PWC_DEBUG
-							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
-#endif
-							pdev->drop_frames += 2;
-							pdev->vframes_error++;
-						}
-						if ((ptr[0] ^ pdev->vmirror) & 0x01) {
-							if (ptr[0] & 0x01)
-								Info("Snapshot button pressed.\n");
-							else
-								Info("Snapshot button released.\n");
-						}
-						if ((ptr[0] ^ pdev->vmirror) & 0x02) {
-							if (ptr[0] & 0x02)
-								Info("Image is mirrored.\n");
-							else
-								Info("Image is normal.\n");
-						}
-						pdev->vmirror = ptr[0] & 0x03;
-						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet
-						   after a short frame; this condition is filtered out specifically. A 4 byte
-						   frame doesn't make sense anyway.
-						   So we get either this sequence:
-							drop_bit set -> 4 byte frame -> short frame -> good frame
-						   Or this one:
-							drop_bit set -> short frame -> good frame
-						   So we drop either 3 or 2 frames in all!
-						 */
-						if (fbuf->filled == 4)
-							pdev->drop_frames++;
+					if (pwc_rcv_short_packet(pdev, fbuf)) {
+						awake = 1;
+						fbuf = pdev->fill_frame;
 					}
-
-					/* In case we were instructed to drop the frame, do so silently.
-					   The buffer pointers are not updated either (but the counters are reset below).
-					 */
-					if (pdev->drop_frames > 0)
-						pdev->drop_frames--;
-					else {
-						/* Check for underflow first */
-						if (fbuf->filled < pdev->frame_total_size) {
-							Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
-							pdev->vframes_error++;
-						}
-						else {
-							/* Send only once per EOF */
-							awake = 1; /* delay wake_ups */
-
-							/* Find our next frame to fill. This will always succeed, since we
-							 * nick a frame from either empty or full list, but if we had to
-							 * take it from the full list, it means a frame got dropped.
-							 */
-							if (pwc_next_fill_frame(pdev)) {
-								pdev->vframes_dumped++;
-								if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
-									if (pdev->vframes_dumped < 20)
-										Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
-									if (pdev->vframes_dumped == 20)
-										Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
-								}
-							}
-							fbuf = pdev->fill_frame;
-						}
-					} /* !drop_frames */
-					pdev->vframe_count++;
 				}
 				fbuf->filled = 0;
 				fillptr = fbuf->data;
 				pdev->vsync = 1;
-			} /* .. flen < last_packet_size */
+			}
+
 			pdev->vlast_packet_size = flen;
 		} /* ..status == 0 */
-#if PWC_DEBUG
-		/* This is normally not interesting to the user, unless you are really debugging something */
 		else {
+			/* This is normally not interesting to the user, unless
+			 * you are really debugging something */
 			static int iso_error = 0;
 			iso_error++;
 			if (iso_error < 20)
-				Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+				PWC_DEBUG_FLOW("Iso frame %d of USB has error %d\n", i, fst);
 		}
-#endif
 	}
 
 handler_end:
@@ -803,11 +802,11 @@
 	urb->dev = pdev->udev;
 	i = usb_submit_urb(urb, GFP_ATOMIC);
 	if (i != 0)
-		Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
+		PWC_ERROR("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
 }
 
 
-static int pwc_isoc_init(struct pwc_device *pdev)
+int pwc_isoc_init(struct pwc_device *pdev)
 {
 	struct usb_device *udev;
 	struct urb *urb;
@@ -826,7 +825,6 @@
 	/* Get the current alternate interface, adjust packet size */
 	if (!udev->actconfig)
 		return -EFAULT;
-
 	intf = usb_ifnum_to_if(udev, 0);
 	if (intf)
 		idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
@@ -836,20 +834,21 @@
 
 	/* Search video endpoint */
 	pdev->vmax_packet_size = -1;
-	for (i = 0; i < idesc->desc.bNumEndpoints; i++)
+	for (i = 0; i < idesc->desc.bNumEndpoints; i++) {
 		if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
 			pdev->vmax_packet_size = le16_to_cpu(idesc->endpoint[i].desc.wMaxPacketSize);
 			break;
 		}
+	}
 
 	if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
-		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+		PWC_ERROR("Failed to find packet size for video endpoint in current alternate setting.\n");
 		return -ENFILE; /* Odd error, that should be noticeable */
 	}
 
 	/* Set alternate interface */
 	ret = 0;
-	Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
+	PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
 	ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
 	if (ret < 0)
 		return ret;
@@ -857,12 +856,12 @@
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
 		if (urb == NULL) {
-			Err("Failed to allocate urb %d\n", i);
+			PWC_ERROR("Failed to allocate urb %d\n", i);
 			ret = -ENOMEM;
 			break;
 		}
 		pdev->sbuf[i].urb = urb;
-		Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
+		PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
 	}
 	if (ret) {
 		/* De-allocate in reverse order */
@@ -899,24 +898,26 @@
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
 		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
 		if (ret)
-			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+			PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
 		else
-			Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+			PWC_DEBUG_MEMORY("URB 0x%p submitted.\n", pdev->sbuf[i].urb);
 	}
 
 	/* All is done... */
 	pdev->iso_init = 1;
-	Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
+	PWC_DEBUG_OPEN("<< pwc_isoc_init()\n");
 	return 0;
 }
 
-static void pwc_isoc_cleanup(struct pwc_device *pdev)
+void pwc_isoc_cleanup(struct pwc_device *pdev)
 {
 	int i;
 
-	Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
+	PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
 	if (pdev == NULL)
 		return;
+	if (pdev->iso_init == 0)
+		return;
 
 	/* Unlinking ISOC buffers one by one */
 	for (i = 0; i < MAX_ISO_BUFS; i++) {
@@ -925,10 +926,10 @@
 		urb = pdev->sbuf[i].urb;
 		if (urb != 0) {
 			if (pdev->iso_init) {
-				Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
+				PWC_DEBUG_MEMORY("Unlinking URB %p\n", urb);
 				usb_kill_urb(urb);
 			}
-			Trace(TRACE_MEMORY, "Freeing URB\n");
+			PWC_DEBUG_MEMORY("Freeing URB\n");
 			usb_free_urb(urb);
 			pdev->sbuf[i].urb = NULL;
 		}
@@ -938,12 +939,12 @@
 	   is signalled by EPIPE)
 	 */
 	if (pdev->error_status && pdev->error_status != EPIPE) {
-		Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
+		PWC_DEBUG_OPEN("Setting alternate interface 0.\n");
 		usb_set_interface(pdev->udev, 0, 0);
 	}
 
 	pdev->iso_init = 0;
-	Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
+	PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
 }
 
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
@@ -957,18 +958,18 @@
 	/* Try to set video mode... */
 	start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
 	if (ret) {
-		Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
+		PWC_DEBUG_FLOW("pwc_set_video_mode attempt 1 failed.\n");
 		/* That failed... restore old mode (we know that worked) */
 		start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
 		if (start) {
-			Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
+			PWC_DEBUG_FLOW("pwc_set_video_mode attempt 2 failed.\n");
 		}
 	}
 	if (start == 0)
 	{
 		if (pwc_isoc_init(pdev) < 0)
 		{
-			Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
+			PWC_WARNING("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
 			ret = -EAGAIN; /* let's try again, who knows if it works a second time */
 		}
 	}
@@ -976,54 +977,129 @@
 	return ret; /* Return original error code */
 }
 
+/*********
+ * sysfs
+ *********/
+static struct pwc_device *cd_to_pwc(struct class_device *cd)
+{
+	struct video_device *vdev = to_video_device(cd);
+	return video_get_drvdata(vdev);
+}
+
+static ssize_t show_pan_tilt(struct class_device *class_dev, char *buf)
+{
+	struct pwc_device *pdev = cd_to_pwc(class_dev);
+	return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
+}
+
+static ssize_t store_pan_tilt(struct class_device *class_dev, const char *buf,
+			 size_t count)
+{
+	struct pwc_device *pdev = cd_to_pwc(class_dev);
+	int pan, tilt;
+	int ret = -EINVAL;
+
+	if (strncmp(buf, "reset", 5) == 0)
+		ret = pwc_mpt_reset(pdev, 0x3);
+
+	else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
+		ret = pwc_mpt_set_angle(pdev, pan, tilt);
+
+	if (ret < 0)
+		return ret;
+	return strlen(buf);
+}
+static CLASS_DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
+			 store_pan_tilt);
+
+static ssize_t show_snapshot_button_status(struct class_device *class_dev, char *buf)
+{
+	struct pwc_device *pdev = cd_to_pwc(class_dev);
+	int status = pdev->snapshot_button_status;
+	pdev->snapshot_button_status = 0;
+	return sprintf(buf, "%d\n", status);
+}
+
+static CLASS_DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
+			 NULL);
+
+static void pwc_create_sysfs_files(struct video_device *vdev)
+{
+	struct pwc_device *pdev = video_get_drvdata(vdev);
+	if (pdev->features & FEATURE_MOTOR_PANTILT)
+		video_device_create_file(vdev, &class_device_attr_pan_tilt);
+	video_device_create_file(vdev, &class_device_attr_button);
+}
+
+static void pwc_remove_sysfs_files(struct video_device *vdev)
+{
+	struct pwc_device *pdev = video_get_drvdata(vdev);
+	if (pdev->features & FEATURE_MOTOR_PANTILT)
+		video_device_remove_file(vdev, &class_device_attr_pan_tilt);
+	video_device_remove_file(vdev, &class_device_attr_button);
+}
+
+#if CONFIG_PWC_DEBUG
+static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
+{
+	switch(sensor_type) {
+		case 0x00:
+			return "Hyundai CMOS sensor";
+		case 0x20:
+			return "Sony CCD sensor + TDA8787";
+		case 0x2E:
+			return "Sony CCD sensor + Exas 98L59";
+		case 0x2F:
+			return "Sony CCD sensor + ADI 9804";
+		case 0x30:
+			return "Sharp CCD sensor + TDA8787";
+		case 0x3E:
+			return "Sharp CCD sensor + Exas 98L59";
+		case 0x3F:
+			return "Sharp CCD sensor + ADI 9804";
+		case 0x40:
+			return "UPA 1021 sensor";
+		case 0x100:
+			return "VGA sensor";
+		case 0x101:
+			return "PAL MR sensor";
+		default:
+			return "unknown type of sensor";
+	}
+}
+#endif
 
 /***************************************************************************/
 /* Video4Linux functions */
 
 static int pwc_video_open(struct inode *inode, struct file *file)
 {
-	int i;
+	int i, ret;
 	struct video_device *vdev = video_devdata(file);
 	struct pwc_device *pdev;
 
-	Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
+	PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
 
 	pdev = (struct pwc_device *)vdev->priv;
 	if (pdev == NULL)
 		BUG();
-	if (pdev->vopen)
+	if (pdev->vopen) {
+		PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n");
 		return -EBUSY;
+	}
 
 	down(&pdev->modlock);
 	if (!pdev->usb_init) {
-		Trace(TRACE_OPEN, "Doing first time initialization.\n");
+		PWC_DEBUG_OPEN("Doing first time initialization.\n");
 		pdev->usb_init = 1;
 
-		if (pwc_trace & TRACE_OPEN)
+		/* Query sensor type */
+		ret = pwc_get_cmos_sensor(pdev, &i);
+		if (ret >= 0)
 		{
-			/* Query sensor type */
-			const char *sensor_type = NULL;
-			int ret;
-
-			ret = pwc_get_cmos_sensor(pdev, &i);
-			if (ret >= 0)
-			{
-				switch(i) {
-				case 0x00:  sensor_type = "Hyundai CMOS sensor"; break;
-				case 0x20:  sensor_type = "Sony CCD sensor + TDA8787"; break;
-				case 0x2E:  sensor_type = "Sony CCD sensor + Exas 98L59"; break;
-				case 0x2F:  sensor_type = "Sony CCD sensor + ADI 9804"; break;
-				case 0x30:  sensor_type = "Sharp CCD sensor + TDA8787"; break;
-				case 0x3E:  sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
-				case 0x3F:  sensor_type = "Sharp CCD sensor + ADI 9804"; break;
-				case 0x40:  sensor_type = "UPA 1021 sensor"; break;
-				case 0x100: sensor_type = "VGA sensor"; break;
-				case 0x101: sensor_type = "PAL MR sensor"; break;
-				default:    sensor_type = "unknown type of sensor"; break;
-				}
-			}
-			if (sensor_type != NULL)
-				Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
+			PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
+					pdev->vdev->name,
+					pwc_sensor_type_to_string(i), i);
 		}
 	}
 
@@ -1031,34 +1107,32 @@
 	if (power_save) {
 		i = pwc_camera_power(pdev, 1);
 		if (i < 0)
-			Info("Failed to restore power to the camera! (%d)\n", i);
+			PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i);
 	}
 	/* Set LED on/off time */
 	if (pwc_set_leds(pdev, led_on, led_off) < 0)
-		Info("Failed to set LED on/off time.\n");
+		PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");
 
 	pwc_construct(pdev); /* set min/max sizes correct */
 
 	/* So far, so good. Allocate memory. */
 	i = pwc_allocate_buffers(pdev);
 	if (i < 0) {
-		Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
+		PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
+		pwc_free_buffers(pdev);
 		up(&pdev->modlock);
 		return i;
 	}
 
 	/* Reset buffers & parameters */
 	pwc_reset_buffers(pdev);
-	for (i = 0; i < default_mbufs; i++)
+	for (i = 0; i < pwc_mbufs; i++)
 		pdev->image_used[i] = 0;
 	pdev->vframe_count = 0;
 	pdev->vframes_dumped = 0;
 	pdev->vframes_error = 0;
 	pdev->visoc_errors = 0;
 	pdev->error_status = 0;
-#if PWC_DEBUG
-	pdev->sequence = 0;
-#endif
 	pwc_construct(pdev); /* set min/max sizes correct */
 
 	/* Set some defaults */
@@ -1070,29 +1144,44 @@
 	 */
 	i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
 	if (i)	{
-		Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
-		if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
+		unsigned int default_resolution;
+		PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");
+		if (pdev->type>= 730)
+			default_resolution = PSZ_QSIF;
 		else
-			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
+			default_resolution = PSZ_QCIF;
+
+		i = pwc_set_video_mode(pdev,
+				       pwc_image_sizes[default_resolution].x,
+				       pwc_image_sizes[default_resolution].y,
+				       10,
+				       pdev->vcompression,
+				       0);
 	}
 	if (i) {
-		Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+		PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
+		pwc_free_buffers(pdev);
 		up(&pdev->modlock);
 		return i;
 	}
 
 	i = pwc_isoc_init(pdev);
 	if (i) {
-		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+		PWC_DEBUG_OPEN("Failed to init ISOC stuff = %d.\n", i);
+		pwc_isoc_cleanup(pdev);
+		pwc_free_buffers(pdev);
 		up(&pdev->modlock);
 		return i;
 	}
 
+	/* Initialize the webcam to sane value */
+	pwc_set_brightness(pdev, 0x7fff);
+	pwc_set_agc(pdev, 1, 0);
+
 	pdev->vopen++;
 	file->private_data = vdev;
 	up(&pdev->modlock);
-	Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
+	PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
 	return 0;
 }
 
@@ -1103,35 +1192,23 @@
 	struct pwc_device *pdev;
 	int i;
 
-	Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
+	PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
 	pdev = (struct pwc_device *)vdev->priv;
 	if (pdev->vopen == 0)
-		Info("video_close() called on closed device?\n");
+		PWC_DEBUG_MODULE("video_close() called on closed device?\n");
 
 	/* Dump statistics, but only if a reasonable amount of frames were
 	   processed (to prevent endless log-entries in case of snap-shot
 	   programs)
 	 */
 	if (pdev->vframe_count > 20)
-		Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+		PWC_DEBUG_MODULE("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
 
-	switch (pdev->type)
-	 {
-	  case 675:
-	  case 680:
-	  case 690:
-	  case 720:
-	  case 730:
-	  case 740:
-	  case 750:
-/*	    pwc_dec23_exit();	*//* Timon & Kiara */
-	    break;
-	  case 645:
-	  case 646:
-/*	    pwc_dec1_exit(); */
-	    break;
-	 }
+	if (DEVICE_USE_CODEC1(pdev->type))
+	    pwc_dec1_exit();
+	else
+	    pwc_dec23_exit();
 
 	pwc_isoc_cleanup(pdev);
 	pwc_free_buffers(pdev);
@@ -1140,15 +1217,15 @@
 	if (pdev->error_status != EPIPE) {
 		/* Turn LEDs off */
 		if (pwc_set_leds(pdev, 0, 0) < 0)
-			Info("Failed to set LED on/off time.\n");
+			PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
 		if (power_save) {
 			i = pwc_camera_power(pdev, 0);
 			if (i < 0)
-				Err("Failed to power down camera (%d)\n", i);
+				PWC_ERROR("Failed to power down camera (%d)\n", i);
 		}
 	}
-	pdev->vopen = 0;
-	Trace(TRACE_OPEN, "<< video_close()\n");
+	pdev->vopen--;
+	PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
 	return 0;
 }
 
@@ -1164,7 +1241,7 @@
 		device is tricky anyhow.
  */
 
-static ssize_t pwc_video_read(struct file *file, char __user * buf,
+static ssize_t pwc_video_read(struct file *file, char __user *buf,
 			  size_t count, loff_t *ppos)
 {
 	struct video_device *vdev = file->private_data;
@@ -1172,8 +1249,10 @@
 	int noblock = file->f_flags & O_NONBLOCK;
 	DECLARE_WAITQUEUE(wait, current);
 	int bytes_to_read;
+	void *image_buffer_addr;
 
-	Trace(TRACE_READ, "video_read(0x%p, %p, %zu) called.\n", vdev, buf, count);
+	PWC_DEBUG_READ("pwc_video_read(vdev=0x%p, buf=%p, count=%zd) called.\n",
+			vdev, buf, count);
 	if (vdev == NULL)
 		return -EFAULT;
 	pdev = vdev->priv;
@@ -1214,16 +1293,19 @@
 			return -EFAULT;
 	}
 
-	Trace(TRACE_READ, "Copying data to user space.\n");
+	PWC_DEBUG_READ("Copying data to user space.\n");
 	if (pdev->vpalette == VIDEO_PALETTE_RAW)
-		bytes_to_read = pdev->frame_size;
+		bytes_to_read = pdev->frame_size + sizeof(struct pwc_raw_frame);
 	else
 		bytes_to_read = pdev->view.size;
 
 	/* copy bytes to user space; we allow for partial reads */
 	if (count + pdev->image_read_pos > bytes_to_read)
 		count = bytes_to_read - pdev->image_read_pos;
-	if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
+	image_buffer_addr = pdev->image_data;
+	image_buffer_addr += pdev->images[pdev->fill_image].offset;
+	image_buffer_addr += pdev->image_read_pos;
+	if (copy_to_user(buf, image_buffer_addr, count))
 		return -EFAULT;
 	pdev->image_read_pos += count;
 	if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
@@ -1253,370 +1335,56 @@
 	return 0;
 }
 
-static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
-			      unsigned int cmd, void *arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = vdev->priv;
-	if (pdev == NULL)
-		return -EFAULT;
-
-	switch (cmd) {
-		/* Query cabapilities */
-		case VIDIOCGCAP:
-		{
-			struct video_capability *caps = arg;
-
-			strcpy(caps->name, vdev->name);
-			caps->type = VID_TYPE_CAPTURE;
-			caps->channels = 1;
-			caps->audios = 1;
-			caps->minwidth  = pdev->view_min.x;
-			caps->minheight = pdev->view_min.y;
-			caps->maxwidth  = pdev->view_max.x;
-			caps->maxheight = pdev->view_max.y;
-			break;
-		}
-
-		/* Channel functions (simulate 1 channel) */
-		case VIDIOCGCHAN:
-		{
-			struct video_channel *v = arg;
-
-			if (v->channel != 0)
-				return -EINVAL;
-			v->flags = 0;
-			v->tuners = 0;
-			v->type = VIDEO_TYPE_CAMERA;
-			strcpy(v->name, "Webcam");
-			return 0;
-		}
-
-		case VIDIOCSCHAN:
-		{
-			/* The spec says the argument is an integer, but
-			   the bttv driver uses a video_channel arg, which
-			   makes sense becasue it also has the norm flag.
-			 */
-			struct video_channel *v = arg;
-			if (v->channel != 0)
-				return -EINVAL;
-			return 0;
-		}
-
-
-		/* Picture functions; contrast etc. */
-		case VIDIOCGPICT:
-		{
-			struct video_picture *p = arg;
-			int val;
-
-			val = pwc_get_brightness(pdev);
-			if (val >= 0)
-				p->brightness = val;
-			else
-				p->brightness = 0xffff;
-			val = pwc_get_contrast(pdev);
-			if (val >= 0)
-				p->contrast = val;
-			else
-				p->contrast = 0xffff;
-			/* Gamma, Whiteness, what's the difference? :) */
-			val = pwc_get_gamma(pdev);
-			if (val >= 0)
-				p->whiteness = val;
-			else
-				p->whiteness = 0xffff;
-			val = pwc_get_saturation(pdev);
-			if (val >= 0)
-				p->colour = val;
-			else
-				p->colour = 0xffff;
-			p->depth = 24;
-			p->palette = pdev->vpalette;
-			p->hue = 0xFFFF; /* N/A */
-			break;
-		}
-
-		case VIDIOCSPICT:
-		{
-			struct video_picture *p = arg;
-			/*
-			 *	FIXME:	Suppose we are mid read
-				ANSWER: No problem: the firmware of the camera
-					can handle brightness/contrast/etc
-					changes at _any_ time, and the palette
-					is used exactly once in the uncompress
-					routine.
-			 */
-			pwc_set_brightness(pdev, p->brightness);
-			pwc_set_contrast(pdev, p->contrast);
-			pwc_set_gamma(pdev, p->whiteness);
-			pwc_set_saturation(pdev, p->colour);
-			if (p->palette && p->palette != pdev->vpalette) {
-				switch (p->palette) {
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						pdev->vpalette = p->palette;
-						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-			break;
-		}
-
-		/* Window/size parameters */
-		case VIDIOCGWIN:
-		{
-			struct video_window *vw = arg;
-
-			vw->x = 0;
-			vw->y = 0;
-			vw->width = pdev->view.x;
-			vw->height = pdev->view.y;
-			vw->chromakey = 0;
-			vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
-				   (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
-			break;
-		}
-
-		case VIDIOCSWIN:
-		{
-			struct video_window *vw = arg;
-			int fps, snapshot, ret;
-
-			fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
-			snapshot = vw->flags & PWC_FPS_SNAPSHOT;
-			if (fps == 0)
-				fps = pdev->vframes;
-			if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
-				return 0;
-			ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
-			if (ret)
-				return ret;
-			break;
-		}
-
-		/* We don't have overlay support (yet) */
-		case VIDIOCGFBUF:
-		{
-			struct video_buffer *vb = arg;
-
-			memset(vb,0,sizeof(*vb));
-			break;
-		}
-
-		/* mmap() functions */
-		case VIDIOCGMBUF:
-		{
-			/* Tell the user program how much memory is needed for a mmap() */
-			struct video_mbuf *vm = arg;
-			int i;
-
-			memset(vm, 0, sizeof(*vm));
-			vm->size = default_mbufs * pdev->len_per_image;
-			vm->frames = default_mbufs; /* double buffering should be enough for most applications */
-			for (i = 0; i < default_mbufs; i++)
-				vm->offsets[i] = i * pdev->len_per_image;
-			break;
-		}
-
-		case VIDIOCMCAPTURE:
-		{
-			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
-			struct video_mmap *vm = arg;
-
-			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
-			if (vm->frame < 0 || vm->frame >= default_mbufs)
-				return -EINVAL;
-
-			/* xawtv is nasty. It probes the available palettes
-			   by setting a very small image size and trying
-			   various palettes... The driver doesn't support
-			   such small images, so I'm working around it.
-			 */
-			if (vm->format)
-			{
-				switch (vm->format)
-				{
-					case VIDEO_PALETTE_YUV420P:
-					case VIDEO_PALETTE_RAW:
-						break;
-					default:
-						return -EINVAL;
-						break;
-				}
-			}
-
-			if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
-			    (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
-				int ret;
-
-				Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
-				ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
-				if (ret)
-					return ret;
-			} /* ... size mismatch */
-
-			/* FIXME: should we lock here? */
-			if (pdev->image_used[vm->frame])
-				return -EBUSY;	/* buffer wasn't available. Bummer */
-			pdev->image_used[vm->frame] = 1;
-
-			/* Okay, we're done here. In the SYNC call we wait until a
-			   frame comes available, then expand image into the given
-			   buffer.
-			   In contrast to the CPiA cam the Philips cams deliver a
-			   constant stream, almost like a grabber card. Also,
-			   we have separate buffers for the rawdata and the image,
-			   meaning we can nearly always expand into the requested buffer.
-			 */
-			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
-			break;
-		}
-
-		case VIDIOCSYNC:
-		{
-			/* The doc says: "Whenever a buffer is used it should
-			   call VIDIOCSYNC to free this frame up and continue."
-
-			   The only odd thing about this whole procedure is
-			   that MCAPTURE flags the buffer as "in use", and
-			   SYNC immediately unmarks it, while it isn't
-			   after SYNC that you know that the buffer actually
-			   got filled! So you better not start a CAPTURE in
-			   the same frame immediately (use double buffering).
-			   This is not a problem for this cam, since it has
-			   extra intermediate buffers, but a hardware
-			   grabber card will then overwrite the buffer
-			   you're working on.
-			 */
-			int *mbuf = arg;
-			int ret;
-
-			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf);
-
-			/* bounds check */
-			if (*mbuf < 0 || *mbuf >= default_mbufs)
-				return -EINVAL;
-			/* check if this buffer was requested anyway */
-			if (pdev->image_used[*mbuf] == 0)
-				return -EINVAL;
-
-			/* Add ourselves to the frame wait-queue.
-
-			   FIXME: needs auditing for safety.
-			   QUESTION: In what respect? I think that using the
-				     frameq is safe now.
-			 */
-			add_wait_queue(&pdev->frameq, &wait);
-			while (pdev->full_frames == NULL) {
-				if (pdev->error_status) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -pdev->error_status;
-				}
-
-				if (signal_pending(current)) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -ERESTARTSYS;
-				}
-				schedule();
-				set_current_state(TASK_INTERRUPTIBLE);
-			}
-			remove_wait_queue(&pdev->frameq, &wait);
-			set_current_state(TASK_RUNNING);
-
-			/* The frame is ready. Expand in the image buffer
-			   requested by the user. I don't care if you
-			   mmap() 5 buffers and request data in this order:
-			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
-			   Grabber hardware may not be so forgiving.
-			 */
-			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
-			pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
-			/* Decompress, etc */
-			ret = pwc_handle_frame(pdev);
-			pdev->image_used[*mbuf] = 0;
-			if (ret)
-				return -EFAULT;
-			break;
-		}
-
-		case VIDIOCGAUDIO:
-		{
-			struct video_audio *v = arg;
-
-			strcpy(v->name, "Microphone");
-			v->audio = -1; /* unknown audio minor */
-			v->flags = 0;
-			v->mode = VIDEO_SOUND_MONO;
-			v->volume = 0;
-			v->bass = 0;
-			v->treble = 0;
-			v->balance = 0x8000;
-			v->step = 1;
-			break;
-		}
-
-		case VIDIOCSAUDIO:
-		{
-			/* Dummy: nothing can be set */
-			break;
-		}
-
-		case VIDIOCGUNIT:
-		{
-			struct video_unit *vu = arg;
-
-			vu->video = pdev->vdev->minor & 0x3F;
-			vu->audio = -1; /* not known yet */
-			vu->vbi = -1;
-			vu->radio = -1;
-			vu->teletext = -1;
-			break;
-		}
-		default:
-			return pwc_ioctl(pdev, cmd, arg);
-	} /* ..switch */
-	return 0;
-}
-
 static int pwc_video_ioctl(struct inode *inode, struct file *file,
 			   unsigned int cmd, unsigned long arg)
 {
 	return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
 }
 
-
 static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_device *vdev = file->private_data;
 	struct pwc_device *pdev;
-	unsigned long start = vma->vm_start;
-	unsigned long size  = vma->vm_end-vma->vm_start;
-	unsigned long page, pos;
+	unsigned long start;
+	unsigned long size;
+	unsigned long page, pos = 0;
+	int index;
 
-	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
+	PWC_DEBUG_MEMORY(">> %s\n", __FUNCTION__);
 	pdev = vdev->priv;
+	size = vma->vm_end - vma->vm_start;
+	start = vma->vm_start;
 
-	vma->vm_flags |= VM_IO;
+	/* Find the idx buffer for this mapping */
+	for (index = 0; index < pwc_mbufs; index++) {
+		pos = pdev->images[index].offset;
+		if ((pos>>PAGE_SHIFT) == vma->vm_pgoff)
+			break;
+	}
+	if (index == MAX_IMAGES)
+		return -EINVAL;
+	if (index == 0) {
+		/*
+		 * Special case for v4l1. In v4l1, we map only one big buffer,
+		 * but in v4l2 each buffer is mapped
+		 */
+		unsigned long total_size;
+		total_size = pwc_mbufs * pdev->len_per_image;
+		if (size != pdev->len_per_image && size != total_size) {
+			PWC_ERROR("Wrong size (%lu) needed to be len_per_image=%d or total_size=%lu\n",
+				   size, pdev->len_per_image, total_size);
+			return -EINVAL;
+		}
+	} else if (size > pdev->len_per_image)
+		return -EINVAL;
 
-	pos = (unsigned long)pdev->image_data;
+	vma->vm_flags |= VM_IO;	/* from 2.6.9-acX */
+
+	pos += (unsigned long)pdev->image_data;
 	while (size > 0) {
 		page = vmalloc_to_pfn((void *)pos);
 		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
 			return -EAGAIN;
-
 		start += PAGE_SIZE;
 		pos += PAGE_SIZE;
 		if (size > PAGE_SIZE)
@@ -1624,7 +1392,6 @@
 		else
 			size = 0;
 	}
-
 	return 0;
 }
 
@@ -1645,10 +1412,12 @@
 	int video_nr = -1; /* default: use next available device */
 	char serial_number[30], *name;
 
+	vendor_id = le16_to_cpu(udev->descriptor.idVendor);
+	product_id = le16_to_cpu(udev->descriptor.idProduct);
+
 	/* Check if we can handle this device */
-	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
-		le16_to_cpu(udev->descriptor.idVendor),
-		le16_to_cpu(udev->descriptor.idProduct),
+	PWC_DEBUG_PROBE("probe() called [%04X %04X], if %d\n",
+		vendor_id, product_id,
 		intf->altsetting->desc.bInterfaceNumber);
 
 	/* the interfaces are probed one by one. We are only interested in the
@@ -1658,61 +1427,63 @@
 	if (intf->altsetting->desc.bInterfaceNumber > 0)
 		return -ENODEV;
 
-	vendor_id = le16_to_cpu(udev->descriptor.idVendor);
-	product_id = le16_to_cpu(udev->descriptor.idProduct);
-
 	if (vendor_id == 0x0471) {
 		switch (product_id) {
 		case 0x0302:
-			Info("Philips PCA645VC USB webcam detected.\n");
+			PWC_INFO("Philips PCA645VC USB webcam detected.\n");
 			name = "Philips 645 webcam";
 			type_id = 645;
 			break;
 		case 0x0303:
-			Info("Philips PCA646VC USB webcam detected.\n");
+			PWC_INFO("Philips PCA646VC USB webcam detected.\n");
 			name = "Philips 646 webcam";
 			type_id = 646;
 			break;
 		case 0x0304:
-			Info("Askey VC010 type 2 USB webcam detected.\n");
+			PWC_INFO("Askey VC010 type 2 USB webcam detected.\n");
 			name = "Askey VC010 webcam";
 			type_id = 646;
 			break;
 		case 0x0307:
-			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC675K (Vesta) USB webcam detected.\n");
 			name = "Philips 675 webcam";
 			type_id = 675;
 			break;
 		case 0x0308:
-			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
 			name = "Philips 680 webcam";
 			type_id = 680;
 			break;
 		case 0x030C:
-			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
 			name = "Philips 690 webcam";
 			type_id = 690;
 			break;
 		case 0x0310:
-			Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
 			name = "Philips 730 webcam";
 			type_id = 730;
 			break;
 		case 0x0311:
-			Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
 			name = "Philips 740 webcam";
 			type_id = 740;
 			break;
 		case 0x0312:
-			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
 			name = "Philips 750 webcam";
 			type_id = 750;
 			break;
 		case 0x0313:
-			Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
+			PWC_INFO("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
 			name = "Philips 720K/40 webcam";
 			type_id = 720;
 			break;
+		case 0x0329:
+			PWC_INFO("Philips SPC 900NC USB webcam detected.\n");
+			name = "Philips SPC 900NC webcam";
+			type_id = 720;
+			break;
 		default:
 			return -ENODEV;
 			break;
@@ -1721,7 +1492,7 @@
 	else if (vendor_id == 0x069A) {
 		switch(product_id) {
 		case 0x0001:
-			Info("Askey VC010 type 1 USB webcam detected.\n");
+			PWC_INFO("Askey VC010 type 1 USB webcam detected.\n");
 			name = "Askey VC010 webcam";
 			type_id = 645;
 			break;
@@ -1733,32 +1504,33 @@
 	else if (vendor_id == 0x046d) {
 		switch(product_id) {
 		case 0x08b0:
-			Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Pro 3000 USB webcam detected.\n");
 			name = "Logitech QuickCam Pro 3000";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08b1:
-			Info("Logitech QuickCam Notebook Pro USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Notebook Pro USB webcam detected.\n");
 			name = "Logitech QuickCam Notebook Pro";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08b2:
-			Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam 4000 Pro USB webcam detected.\n");
 			name = "Logitech QuickCam Pro 4000";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08b3:
-			Info("Logitech QuickCam Zoom USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Zoom USB webcam detected.\n");
 			name = "Logitech QuickCam Zoom";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x08B4:
-			Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
 			name = "Logitech QuickCam Zoom";
 			type_id = 740; /* CCD sensor */
+			power_save = 1;
 			break;
 		case 0x08b5:
-			Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+			PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
 			name = "Logitech QuickCam Orbit";
 			type_id = 740; /* CCD sensor */
 			features |= FEATURE_MOTOR_PANTILT;
@@ -1766,7 +1538,7 @@
 		case 0x08b6:
 		case 0x08b7:
 		case 0x08b8:
-			Info("Logitech QuickCam detected (reserved ID).\n");
+			PWC_INFO("Logitech QuickCam detected (reserved ID).\n");
 			name = "Logitech QuickCam (res.)";
 			type_id = 730; /* Assuming CMOS */
 			break;
@@ -1782,15 +1554,20 @@
 		 */
 		switch(product_id) {
 		case 0x9000:
-			Info("Samsung MPC-C10 USB webcam detected.\n");
+			PWC_INFO("Samsung MPC-C10 USB webcam detected.\n");
 			name = "Samsung MPC-C10";
 			type_id = 675;
 			break;
 		case 0x9001:
-			Info("Samsung MPC-C30 USB webcam detected.\n");
+			PWC_INFO("Samsung MPC-C30 USB webcam detected.\n");
 			name = "Samsung MPC-C30";
 			type_id = 675;
 			break;
+		case 0x9002:
+			PWC_INFO("Samsung SNC-35E (v3.0) USB webcam detected.\n");
+			name = "Samsung MPC-C30";
+			type_id = 740;
+			break;
 		default:
 			return -ENODEV;
 			break;
@@ -1799,12 +1576,12 @@
 	else if (vendor_id == 0x041e) {
 		switch(product_id) {
 		case 0x400c:
-			Info("Creative Labs Webcam 5 detected.\n");
+			PWC_INFO("Creative Labs Webcam 5 detected.\n");
 			name = "Creative Labs Webcam 5";
 			type_id = 730;
 			break;
 		case 0x4011:
-			Info("Creative Labs Webcam Pro Ex detected.\n");
+			PWC_INFO("Creative Labs Webcam Pro Ex detected.\n");
 			name = "Creative Labs Webcam Pro Ex";
 			type_id = 740;
 			break;
@@ -1816,7 +1593,7 @@
 	else if (vendor_id == 0x04cc) {
 		switch(product_id) {
 		case 0x8116:
-			Info("Sotec Afina Eye USB webcam detected.\n");
+			PWC_INFO("Sotec Afina Eye USB webcam detected.\n");
 			name = "Sotec Afina Eye";
 			type_id = 730;
 			break;
@@ -1829,7 +1606,7 @@
 		switch(product_id) {
 		case 0x8116:
 			/* This is essentially the same cam as the Sotec Afina Eye */
-			Info("AME Co. Afina Eye USB webcam detected.\n");
+			PWC_INFO("AME Co. Afina Eye USB webcam detected.\n");
 			name = "AME Co. Afina Eye";
 			type_id = 750;
 			break;
@@ -1842,12 +1619,12 @@
 	else if (vendor_id == 0x0d81) {
 		switch(product_id) {
 		case 0x1900:
-			Info("Visionite VCS-UC300 USB webcam detected.\n");
+			PWC_INFO("Visionite VCS-UC300 USB webcam detected.\n");
 			name = "Visionite VCS-UC300";
 			type_id = 740; /* CCD sensor */
 			break;
 		case 0x1910:
-			Info("Visionite VCS-UM100 USB webcam detected.\n");
+			PWC_INFO("Visionite VCS-UM100 USB webcam detected.\n");
 			name = "Visionite VCS-UM100";
 			type_id = 730; /* CMOS sensor */
 			break;
@@ -1861,15 +1638,15 @@
 
 	memset(serial_number, 0, 30);
 	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
-	Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
+	PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
 
 	if (udev->descriptor.bNumConfigurations > 1)
-		Info("Warning: more than 1 configuration available.\n");
+		PWC_WARNING("Warning: more than 1 configuration available.\n");
 
 	/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
 	pdev = kzalloc(sizeof(struct pwc_device), GFP_KERNEL);
 	if (pdev == NULL) {
-		Err("Oops, could not allocate memory for pwc_device.\n");
+		PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
 		return -ENOMEM;
 	}
 	pdev->type = type_id;
@@ -1900,17 +1677,18 @@
 	pdev->vdev = video_device_alloc();
 	if (pdev->vdev == 0)
 	{
-		Err("Err, cannot allocate video_device struture. Failing probe.");
+		PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
 		kfree(pdev);
 		return -ENOMEM;
 	}
 	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
+	pdev->vdev->dev = &(udev->dev);
 	strcpy(pdev->vdev->name, name);
 	pdev->vdev->owner = THIS_MODULE;
 	video_set_drvdata(pdev->vdev, pdev);
 
 	pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
-	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+	PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
 
 	/* Now search device_hint[] table for a match, so we can hint a node number. */
 	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
@@ -1918,10 +1696,10 @@
 		     (device_hint[hint].pdev == NULL)) {
 			/* so far, so good... try serial number */
 			if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
-			    	/* match! */
-			    	video_nr = device_hint[hint].device_node;
-			    	Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
-			    	break;
+				/* match! */
+				video_nr = device_hint[hint].device_node;
+				PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
+				break;
 			}
 		}
 	}
@@ -1929,21 +1707,27 @@
 	pdev->vdev->release = video_device_release;
 	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
 	if (i < 0) {
-		Err("Failed to register as video device (%d).\n", i);
+		PWC_ERROR("Failed to register as video device (%d).\n", i);
 		video_device_release(pdev->vdev); /* Drip... drip... drip... */
 		kfree(pdev); /* Oops, no memory leaks please */
 		return -EIO;
 	}
 	else {
-		Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
+		PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
 	}
 
 	/* occupy slot */
 	if (hint < MAX_DEV_HINTS)
 		device_hint[hint].pdev = pdev;
 
-	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
+	PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
 	usb_set_intfdata (intf, pdev);
+	pwc_create_sysfs_files(pdev->vdev);
+
+	/* Set the leds off */
+	pwc_set_leds(pdev, 0, 0);
+	pwc_camera_power(pdev, 0);
+
 	return 0;
 }
 
@@ -1957,27 +1741,21 @@
 	pdev = usb_get_intfdata (intf);
 	usb_set_intfdata (intf, NULL);
 	if (pdev == NULL) {
-		Err("pwc_disconnect() Called without private pointer.\n");
+		PWC_ERROR("pwc_disconnect() Called without private pointer.\n");
 		goto disconnect_out;
 	}
 	if (pdev->udev == NULL) {
-		Err("pwc_disconnect() already called for %p\n", pdev);
+		PWC_ERROR("pwc_disconnect() already called for %p\n", pdev);
 		goto disconnect_out;
 	}
 	if (pdev->udev != interface_to_usbdev(intf)) {
-		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
+		PWC_ERROR("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
 		goto disconnect_out;
 	}
-#ifdef PWC_MAGIC
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
-		goto disconnect_out;
-	}
-#endif
 
 	/* We got unplugged; this is signalled by an EPIPE error code */
 	if (pdev->vopen) {
-		Info("Disconnected while webcam is in use!\n");
+		PWC_INFO("Disconnected while webcam is in use!\n");
 		pdev->error_status = EPIPE;
 	}
 
@@ -1987,7 +1765,8 @@
 	while (pdev->vopen)
 		schedule();
 	/* Device is now closed, so we can safely unregister it */
-	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
+	PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
+	pwc_remove_sysfs_files(pdev->vdev);
 	video_unregister_device(pdev->vdev);
 
 	/* Free memory (don't set pdev to 0 just yet) */
@@ -2021,58 +1800,64 @@
  * Initialization code & module stuff
  */
 
-static char size[10];
-static int fps = 0;
-static int fbufs = 0;
-static int mbufs = 0;
-static int trace = -1;
+static char *size;
+static int fps;
+static int fbufs;
+static int mbufs;
 static int compression = -1;
 static int leds[2] = { -1, -1 };
-static char *dev_hint[MAX_DEV_HINTS] = { };
+static int leds_nargs;
+static char *dev_hint[MAX_DEV_HINTS];
+static int dev_hint_nargs;
 
-module_param_string(size, size, sizeof(size), 0);
+module_param(size, charp, 0444);
+module_param(fps, int, 0444);
+module_param(fbufs, int, 0444);
+module_param(mbufs, int, 0444);
+#if CONFIG_PWC_DEBUG
+module_param_named(trace, pwc_trace, int, 0644);
+#endif
+module_param(power_save, int, 0444);
+module_param(compression, int, 0444);
+module_param_array(leds, int, &leds_nargs, 0444);
+module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
+
 MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
-module_param(fps, int, 0000);
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
-module_param(fbufs, int, 0000);
 MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
-module_param(mbufs, int, 0000);
 MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
-module_param(trace, int, 0000);
 MODULE_PARM_DESC(trace, "For debugging purposes");
-module_param(power_save, bool, 0000);
 MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
-module_param(compression, int, 0000);
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
-module_param_array(leds, int, NULL, 0000);
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-module_param_array(dev_hint, charp, NULL, 0000);
 MODULE_PARM_DESC(dev_hint, "Device node hints");
 
 MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
 MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("pwcx");
+MODULE_VERSION( PWC_VERSION );
 
 static int __init usb_pwc_init(void)
 {
 	int i, sz;
 	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
 
-	Info("Philips webcam module version " PWC_VERSION " loaded.\n");
-	Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
-	Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
-	Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
+	PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
+	PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
+	PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
+	PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
 
 	if (fps) {
 		if (fps < 4 || fps > 30) {
-			Err("Framerate out of bounds (4-30).\n");
+			PWC_ERROR("Framerate out of bounds (4-30).\n");
 			return -EINVAL;
 		}
 		default_fps = fps;
-		Info("Default framerate set to %d.\n", default_fps);
+		PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
 	}
 
-	if (size[0]) {
+	if (size) {
 		/* string; try matching with array */
 		for (sz = 0; sz < PSZ_MAX; sz++) {
 			if (!strcmp(sizenames[sz], size)) { /* Found! */
@@ -2081,41 +1866,42 @@
 			}
 		}
 		if (sz == PSZ_MAX) {
-			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+			PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
 			return -EINVAL;
 		}
-		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
+		PWC_DEBUG_MODULE("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
 	}
 	if (mbufs) {
 		if (mbufs < 1 || mbufs > MAX_IMAGES) {
-			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
+			PWC_ERROR("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
 			return -EINVAL;
 		}
-		default_mbufs = mbufs;
-		Info("Number of image buffers set to %d.\n", default_mbufs);
+		pwc_mbufs = mbufs;
+		PWC_DEBUG_MODULE("Number of image buffers set to %d.\n", pwc_mbufs);
 	}
 	if (fbufs) {
 		if (fbufs < 2 || fbufs > MAX_FRAMES) {
-			Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
+			PWC_ERROR("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
 			return -EINVAL;
 		}
 		default_fbufs = fbufs;
-		Info("Number of frame buffers set to %d.\n", default_fbufs);
+		PWC_DEBUG_MODULE("Number of frame buffers set to %d.\n", default_fbufs);
 	}
-	if (trace >= 0) {
-		Info("Trace options: 0x%04x\n", trace);
-		pwc_trace = trace;
+#if CONFIG_PWC_DEBUG
+	if (pwc_trace >= 0) {
+		PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
 	}
+#endif
 	if (compression >= 0) {
 		if (compression > 3) {
-			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
+			PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
 			return -EINVAL;
 		}
 		pwc_preferred_compression = compression;
-		Info("Preferred compression set to %d.\n", pwc_preferred_compression);
+		PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
 	}
 	if (power_save)
-		Info("Enabling power save on open/close.\n");
+		PWC_DEBUG_MODULE("Enabling power save on open/close.\n");
 	if (leds[0] >= 0)
 		led_on = leds[0];
 	if (leds[1] >= 0)
@@ -2146,14 +1932,14 @@
 				dot++;
 			/* Few sanity checks */
 			if (*dot != '\0' && dot > colon) {
-				Err("Malformed camera hint: the colon must be after the dot.\n");
+				PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
 				return -EINVAL;
 			}
 
 			if (*colon == '\0') {
 				/* No colon */
 				if (*dot != '\0') {
-					Err("Malformed camera hint: no colon + device node given.\n");
+					PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
 					return -EINVAL;
 				}
 				else {
@@ -2178,28 +1964,27 @@
 					device_hint[i].serial_number[k] = '\0';
 				}
 			}
-#if PWC_DEBUG
-			Debug("device_hint[%d]:\n", i);
-			Debug("  type    : %d\n", device_hint[i].type);
-			Debug("  serial# : %s\n", device_hint[i].serial_number);
-			Debug("  node    : %d\n", device_hint[i].device_node);
-#endif
+			PWC_TRACE("device_hint[%d]:\n", i);
+			PWC_TRACE("  type    : %d\n", device_hint[i].type);
+			PWC_TRACE("  serial# : %s\n", device_hint[i].serial_number);
+			PWC_TRACE("  node    : %d\n", device_hint[i].device_node);
 		}
 		else
 			device_hint[i].type = 0; /* not filled */
 	} /* ..for MAX_DEV_HINTS */
 
-	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+	PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
 	return usb_register(&pwc_driver);
 }
 
 static void __exit usb_pwc_exit(void)
 {
-	Trace(TRACE_MODULE, "Deregistering driver.\n");
+	PWC_DEBUG_MODULE("Deregistering driver.\n");
 	usb_deregister(&pwc_driver);
-	Info("Philips webcam module removed.\n");
+	PWC_INFO("Philips webcam module removed.\n");
 }
 
 module_init(usb_pwc_init);
 module_exit(usb_pwc_exit);
 
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-kiara.c b/drivers/media/video/pwc/pwc-kiara.c
index 4c96037..fec39cc 100644
--- a/drivers/media/video/pwc/pwc-kiara.c
+++ b/drivers/media/video/pwc/pwc-kiara.c
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -316,3 +316,576 @@
    },
 };
 
+
+/*
+ * Rom table for kiara chips
+ *
+ * 32 roms tables (one for each resolution ?)
+ *  2 tables per roms (one for each passes) (Y, and U&V)
+ * 128 bytes per passes
+ */
+
+const unsigned int KiaraRomTable [8][2][16][8] =
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009292,0x00009493,0x000124db},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009292,
+    0x00009492,0x00009493,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000126dc,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
+
diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h
index 12929ab..0bdb225 100644
--- a/drivers/media/video/pwc/pwc-kiara.h
+++ b/drivers/media/video/pwc/pwc-kiara.h
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -27,7 +27,7 @@
 #ifndef PWC_KIARA_H
 #define PWC_KIARA_H
 
-#include "pwc-ioctl.h"
+#include <media/pwc-ioctl.h>
 
 struct Kiara_table_entry
 {
@@ -37,8 +37,8 @@
 	unsigned char mode[12];		/* precomputed mode settings for cam */
 };
 
-const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
-const extern unsigned int KiaraRomTable[8][2][16][8];
+extern const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
+extern const unsigned int KiaraRomTable[8][2][16][8];
 
 #endif
 
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c
index 58fe797..589c687 100644
--- a/drivers/media/video/pwc/pwc-misc.c
+++ b/drivers/media/video/pwc/pwc-misc.c
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    Various miscellaneous functions and tables.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -24,18 +24,17 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-#include <linux/slab.h>
 
 #include "pwc.h"
 
-struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+const struct pwc_coord pwc_image_sizes[PSZ_MAX] =
 {
-	{ 128,  96, 0 },
-	{ 160, 120, 0 },
-	{ 176, 144, 0 },
-	{ 320, 240, 0 },
-	{ 352, 288, 0 },
-	{ 640, 480, 0 },
+	{ 128,  96, 0 }, /* sqcif */
+	{ 160, 120, 0 }, /* qsif */
+	{ 176, 144, 0 }, /* qcif */
+	{ 320, 240, 0 }, /* sif */
+	{ 352, 288, 0 }, /* cif */
+	{ 640, 480, 0 }, /* vga */
 };
 
 /* x,y -> PSZ_ */
@@ -52,7 +51,7 @@
 	{
 		if (width > pdev->abs_max.x || height > pdev->abs_max.y)
 		{
-			Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
+			PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
 			return -1;
 		}
 	}
@@ -60,7 +59,7 @@
 	{
 		if (width > pdev->view_max.x || height > pdev->view_max.y)
 		{
-			Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n");
+			PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n");
 			return -1;
 		}
 	}
@@ -81,9 +80,8 @@
 /* initialize variables depending on type and decompressor*/
 void pwc_construct(struct pwc_device *pdev)
 {
-	switch(pdev->type) {
-	case 645:
-	case 646:
+	if (DEVICE_USE_CODEC1(pdev->type)) {
+
 		pdev->view_min.x = 128;
 		pdev->view_min.y =  96;
 		pdev->view_max.x = 352;
@@ -95,10 +93,23 @@
 		pdev->vendpoint = 4;
 		pdev->frame_header_size = 0;
 		pdev->frame_trailer_size = 0;
-		break;
-	case 675:
-	case 680:
-	case 690:
+
+	} else if (DEVICE_USE_CODEC3(pdev->type)) {
+
+		pdev->view_min.x = 160;
+		pdev->view_min.y = 120;
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+		pdev->abs_max.x = 640;
+		pdev->abs_max.y = 480;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 5;
+		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+
+	} else /* if (DEVICE_USE_CODEC2(pdev->type)) */ {
+
 		pdev->view_min.x = 128;
 		pdev->view_min.y =  96;
 		/* Anthill bug #38: PWC always reports max size, even without PWCX */
@@ -111,30 +122,12 @@
 		pdev->vendpoint = 4;
 		pdev->frame_header_size = 0;
 		pdev->frame_trailer_size = 0;
-		break;
-	case 720:
-	case 730:
-	case 740:
-	case 750:
-		pdev->view_min.x = 160;
-		pdev->view_min.y = 120;
-		pdev->view_max.x = 640;
-		pdev->view_max.y = 480;
-		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
-		pdev->abs_max.x = 640;
-		pdev->abs_max.y = 480;
-		pdev->vcinterface = 3;
-		pdev->vendpoint = 5;
-		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
-		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
-		break;
 	}
-	Debug("type = %d\n",pdev->type);
 	pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
 	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
 	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
 	/* length of image, in YUV format; always allocate enough memory. */
-	pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2;
+	pdev->len_per_image = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
 }
 
 
diff --git a/drivers/media/video/pwc/pwc-timon.c b/drivers/media/video/pwc/pwc-timon.c
index 175250d..be65bdc 100644
--- a/drivers/media/video/pwc/pwc-timon.c
+++ b/drivers/media/video/pwc/pwc-timon.c
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -314,3 +314,1133 @@
    },
 };
 
+/*
+ * 16 versions:
+ *   2 tables  (one for Y, and one for U&V)
+ *   16 levels of details per tables
+ *   8 blocs
+ */
+
+const unsigned int TimonRomTable [16][2][16][8] =
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000001,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000001,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000049,0x00000249,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009292,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x000124db,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001b724,0x0001b925,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 8 */
+  { /* version 8, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 8, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 9 */
+  { /* version 9, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 9, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 10 */
+  { /* version 10, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 10, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x00009493,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 11 */
+  { /* version 11, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 11, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 12 */
+  { /* version 12, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 12, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 13 */
+  { /* version 13, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 13, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 14 */
+  { /* version 14, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 14, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 15 */
+  { /* version 15, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 15, passes 1 */
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000124db,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h
index a86b378..eef9e2c 100644
--- a/drivers/media/video/pwc/pwc-timon.h
+++ b/drivers/media/video/pwc/pwc-timon.h
@@ -1,5 +1,5 @@
 /* Linux driver for Philips webcam
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -42,7 +42,7 @@
 #ifndef PWC_TIMON_H
 #define PWC_TIMON_H
 
-#include "pwc-ioctl.h"
+#include <media/pwc-ioctl.h>
 
 struct Timon_table_entry
 {
@@ -52,8 +52,8 @@
 	unsigned char mode[13];		/* precomputed mode settings for cam */
 };
 
-const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
-const extern unsigned int TimonRomTable [16][2][16][8];
+extern const struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
+extern const unsigned int TimonRomTable [16][2][16][8];
 
 
 #endif
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c
index b37a89a..5d82028 100644
--- a/drivers/media/video/pwc/pwc-uncompress.c
+++ b/drivers/media/video/pwc/pwc-uncompress.c
@@ -1,7 +1,7 @@
 /* Linux driver for Philips webcam
    Decompression frontend.
    (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -22,6 +22,8 @@
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+   vim: set ts=8:
 */
 
 #include <asm/current.h>
@@ -29,6 +31,8 @@
 
 #include "pwc.h"
 #include "pwc-uncompress.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
 
 int pwc_decompress(struct pwc_device *pdev)
 {
@@ -40,107 +44,95 @@
 
 	if (pdev == NULL)
 		return -EFAULT;
-#if defined(__KERNEL__) && defined(PWC_MAGIC)
-	if (pdev->magic != PWC_MAGIC) {
-		Err("pwc_decompress(): magic failed.\n");
-		return -EFAULT;
-	}
-#endif
 
 	fbuf = pdev->read_frame;
 	if (fbuf == NULL)
 		return -EFAULT;
-	image = pdev->image_ptr[pdev->fill_image];
-	if (!image)
-		return -EFAULT;
+	image  = pdev->image_data;
+	image += pdev->images[pdev->fill_image].offset;
 
 	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
 
 	/* Raw format; that's easy... */
 	if (pdev->vpalette == VIDEO_PALETTE_RAW)
 	{
-		memcpy(image, yuv, pdev->frame_size);
+		struct pwc_raw_frame *raw_frame = image;
+		raw_frame->type = cpu_to_le16(pdev->type);
+		raw_frame->vbandlength = cpu_to_le16(pdev->vbandlength);
+			/* cmd_buf is always 4 bytes, but sometimes, only the
+			 * first 3 bytes is filled (Nala case). We can
+			 * determine this using the type of the webcam */
+		memcpy(raw_frame->cmd, pdev->cmd_buf, 4);
+		memcpy(raw_frame+1, yuv, pdev->frame_size);
 		return 0;
 	}
 
 	if (pdev->vbandlength == 0) {
-		/* Uncompressed mode. We copy the data into the output buffer,
-		   using the viewport size (which may be larger than the image
-		   size). Unfortunately we have to do a bit of byte stuffing
-		   to get the desired output format/size.
+		/* Uncompressed mode.
+		 * We copy the data into the output buffer, using the viewport
+		 * size (which may be larger than the image size).
+		 * Unfortunately we have to do a bit of byte stuffing to get
+		 * the desired output format/size.
+		 *
+		 * We do some byte shuffling here to go from the
+		 * native format to YUV420P.
 		 */
-			/*
-			 * We do some byte shuffling here to go from the
-			 * native format to YUV420P.
-			 */
-			src = (u16 *)yuv;
-			n = pdev->view.x * pdev->view.y;
+		src = (u16 *)yuv;
+		n = pdev->view.x * pdev->view.y;
 
-			/* offset in Y plane */
-			stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
-			dsty = (u16 *)(image + stride);
+		/* offset in Y plane */
+		stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
+		dsty = (u16 *)(image + stride);
 
-			/* offsets in U/V planes */
-			stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
-			dstu = (u16 *)(image + n +         stride);
-			dstv = (u16 *)(image + n + n / 4 + stride);
+		/* offsets in U/V planes */
+		stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
+		dstu = (u16 *)(image + n +         stride);
+		dstv = (u16 *)(image + n + n / 4 + stride);
 
-			/* increment after each line */
-			stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
+		/* increment after each line */
+		stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
 
-			for (line = 0; line < pdev->image.y; line++) {
-				for (col = 0; col < pdev->image.x; col += 4) {
-					*dsty++ = *src++;
-					*dsty++ = *src++;
-					if (line & 1)
-						*dstv++ = *src++;
-					else
-						*dstu++ = *src++;
-				}
-				dsty += stride;
+		for (line = 0; line < pdev->image.y; line++) {
+			for (col = 0; col < pdev->image.x; col += 4) {
+				*dsty++ = *src++;
+				*dsty++ = *src++;
 				if (line & 1)
-					dstv += (stride >> 1);
+					*dstv++ = *src++;
 				else
-					dstu += (stride >> 1);
+					*dstu++ = *src++;
 			}
+			dsty += stride;
+			if (line & 1)
+				dstv += (stride >> 1);
+			else
+				dstu += (stride >> 1);
+		}
+
+		return 0;
 	}
-	else {
-		/* Compressed; the decompressor routines will write the data
-		   in planar format immediately.
-		 */
-		int flags;
 
-		flags = PWCX_FLAG_PLANAR;
-		if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
-		 {
-		   printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
-		   flags |= PWCX_FLAG_BAYER;
-		   return -ENXIO; /* No such device or address: missing decompressor */
-		 }
+	/*
+	 * Compressed;
+	 * the decompressor routines will write the data in planar format
+	 * immediately.
+	 */
+	if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) {
+		PWC_ERROR("Mode Bayer is not supported for now\n");
+		/* flags |= PWCX_FLAG_BAYER; */
+		return -ENXIO; /* No such device or address: missing decompressor */
+	}
 
-#if 0
-		switch (pdev->type)
-		 {
-		  case 675:
-		  case 680:
-		  case 690:
-		  case 720:
-		  case 730:
-		  case 740:
-		  case 750:
-		    pwc_dec23_decompress(&pdev->image, &pdev->view,
-				&pdev->offset, yuv, image, flags,
-				pdev->decompress_data, pdev->vbandlength);
-		    break;
-		  case 645:
-		  case 646:
-		    /* TODO & FIXME */
-		    return -ENXIO; /* Missing decompressor */
-		    break;
-		 }
-#endif
+	if (DEVICE_USE_CODEC1(pdev->type)) {
+
+		/* TODO & FIXME */
+		PWC_ERROR("This chipset is not supported for now\n");
+		return -ENXIO; /* No such device or address: missing decompressor */
+
+	} else {
+		pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR);
 	}
 	return 0;
 }
 
 
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-uncompress.h b/drivers/media/video/pwc/pwc-uncompress.h
index f75e1b6..041227f 100644
--- a/drivers/media/video/pwc/pwc-uncompress.h
+++ b/drivers/media/video/pwc/pwc-uncompress.h
@@ -1,5 +1,5 @@
 /* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -32,7 +32,7 @@
 
 #include <linux/config.h>
 
-#include "pwc-ioctl.h"
+#include <media/pwc-ioctl.h>
 
 /* from pwc-dec.h */
 #define PWCX_FLAG_PLANAR        0x0001
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
new file mode 100644
index 0000000..b7eb3ce
--- /dev/null
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -0,0 +1,1202 @@
+/* Linux driver for Philips webcam
+   USB and Video4Linux interface part.
+   (C) 1999-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+
+static struct v4l2_queryctrl pwc_controls[] = {
+	{
+	    .id      = V4L2_CID_BRIGHTNESS,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Brightness",
+	    .minimum = 0,
+	    .maximum = 128,
+	    .step    = 1,
+	    .default_value = 64,
+	},
+	{
+	    .id      = V4L2_CID_CONTRAST,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Contrast",
+	    .minimum = 0,
+	    .maximum = 64,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_SATURATION,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Saturation",
+	    .minimum = -100,
+	    .maximum = 100,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_GAMMA,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Gamma",
+	    .minimum = 0,
+	    .maximum = 32,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_RED_BALANCE,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Red Gain",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_BLUE_BALANCE,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Blue Gain",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_AUTO_WHITE_BALANCE,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Auto White Balance",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_EXPOSURE,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Shutter Speed (Exposure)",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 200,
+	},
+	{
+	    .id      = V4L2_CID_AUTOGAIN,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Auto Gain Enabled",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 1,
+	},
+	{
+	    .id      = V4L2_CID_GAIN,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Gain Level",
+	    .minimum = 0,
+	    .maximum = 256,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_SAVE_USER,
+	    .type    = V4L2_CTRL_TYPE_BUTTON,
+	    .name    = "Save User Settings",
+	    .minimum = 0,
+	    .maximum = 0,
+	    .step    = 0,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_RESTORE_USER,
+	    .type    = V4L2_CTRL_TYPE_BUTTON,
+	    .name    = "Restore User Settings",
+	    .minimum = 0,
+	    .maximum = 0,
+	    .step    = 0,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_RESTORE_FACTORY,
+	    .type    = V4L2_CTRL_TYPE_BUTTON,
+	    .name    = "Restore Factory Settings",
+	    .minimum = 0,
+	    .maximum = 0,
+	    .step    = 0,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_COLOUR_MODE,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Colour mode",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_AUTOCONTOUR,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Auto contour",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_CONTOUR,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Contour",
+	    .minimum = 0,
+	    .maximum = 63,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_BACKLIGHT,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Backlight compensation",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	  .id      = V4L2_CID_PRIVATE_FLICKERLESS,
+	    .type    = V4L2_CTRL_TYPE_BOOLEAN,
+	    .name    = "Flickerless",
+	    .minimum = 0,
+	    .maximum = 1,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+	{
+	    .id      = V4L2_CID_PRIVATE_NOISE_REDUCTION,
+	    .type    = V4L2_CTRL_TYPE_INTEGER,
+	    .name    = "Noise reduction",
+	    .minimum = 0,
+	    .maximum = 3,
+	    .step    = 1,
+	    .default_value = 0,
+	},
+};
+
+
+static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f)
+{
+	memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format));
+	f->fmt.pix.width        = pdev->view.x;
+	f->fmt.pix.height       = pdev->view.y;
+	f->fmt.pix.field        = V4L2_FIELD_NONE;
+	if (pdev->vpalette == VIDEO_PALETTE_YUV420P) {
+		f->fmt.pix.pixelformat  = V4L2_PIX_FMT_YUV420;
+		f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2;
+		f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+	} else {
+		/* vbandlength contains 4 lines ...  */
+		f->fmt.pix.bytesperline = pdev->vbandlength/4;
+		f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame);
+		if (DEVICE_USE_CODEC1(pdev->type))
+			f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC1;
+		else
+			f->fmt.pix.pixelformat  = V4L2_PIX_FMT_PWC2;
+	}
+	PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() "
+			"width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n",
+			f->fmt.pix.width,
+			f->fmt.pix.height,
+			f->fmt.pix.bytesperline,
+			f->fmt.pix.sizeimage,
+			(f->fmt.pix.pixelformat)&255,
+			(f->fmt.pix.pixelformat>>8)&255,
+			(f->fmt.pix.pixelformat>>16)&255,
+			(f->fmt.pix.pixelformat>>24)&255);
+}
+
+/* ioctl(VIDIOC_TRY_FMT) */
+static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+		return -EINVAL;
+	}
+
+	switch (f->fmt.pix.pixelformat) {
+		case V4L2_PIX_FMT_YUV420:
+			break;
+		case V4L2_PIX_FMT_PWC1:
+			if (DEVICE_USE_CODEC23(pdev->type)) {
+				PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n");
+				return -EINVAL;
+			}
+			break;
+		case V4L2_PIX_FMT_PWC2:
+			if (DEVICE_USE_CODEC1(pdev->type)) {
+				PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n");
+				return -EINVAL;
+			}
+			break;
+		default:
+			PWC_DEBUG_IOCTL("Unsupported pixel format\n");
+			return -EINVAL;
+
+	}
+
+	if (f->fmt.pix.width > pdev->view_max.x)
+		f->fmt.pix.width = pdev->view_max.x;
+	else if (f->fmt.pix.width < pdev->view_min.x)
+		f->fmt.pix.width = pdev->view_min.x;
+
+	if (f->fmt.pix.height > pdev->view_max.y)
+		f->fmt.pix.height = pdev->view_max.y;
+	else if (f->fmt.pix.height < pdev->view_min.y)
+		f->fmt.pix.height = pdev->view_min.y;
+
+	return 0;
+}
+
+/* ioctl(VIDIOC_SET_FMT) */
+static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f)
+{
+	int ret, fps, snapshot, compression, pixelformat;
+
+	ret = pwc_vidioc_try_fmt(pdev, f);
+	if (ret<0)
+		return ret;
+
+	pixelformat = f->fmt.pix.pixelformat;
+	compression = pdev->vcompression;
+	snapshot = 0;
+	fps = pdev->vframes;
+	if (f->fmt.pix.priv) {
+		compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT;
+		snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT);
+		fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+		if (fps == 0)
+			fps = pdev->vframes;
+	}
+
+	if (pixelformat == V4L2_PIX_FMT_YUV420)
+		pdev->vpalette = VIDEO_PALETTE_YUV420P;
+	else
+		pdev->vpalette = VIDEO_PALETTE_RAW;
+
+	PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d "
+			"compression=%d snapshot=%d format=%c%c%c%c\n",
+			f->fmt.pix.width, f->fmt.pix.height, fps,
+			compression, snapshot,
+			(pixelformat)&255,
+			(pixelformat>>8)&255,
+			(pixelformat>>16)&255,
+			(pixelformat>>24)&255);
+
+	ret = pwc_try_video_mode(pdev,
+				 f->fmt.pix.width,
+				 f->fmt.pix.height,
+				 fps,
+				 compression,
+				 snapshot);
+
+	PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret);
+
+	if (ret)
+		return ret;
+
+	pwc_vidioc_fill_fmt(pdev, f);
+
+	return 0;
+
+}
+
+int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+		       unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct pwc_device *pdev;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+
+#if CONFIG_PWC_DEBUG
+	if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace)
+		v4l_printk_ioctl(cmd);
+#endif
+
+
+	switch (cmd) {
+		/* Query cabapilities */
+		case VIDIOCGCAP:
+		{
+			struct video_capability *caps = arg;
+
+			strcpy(caps->name, vdev->name);
+			caps->type = VID_TYPE_CAPTURE;
+			caps->channels = 1;
+			caps->audios = 1;
+			caps->minwidth  = pdev->view_min.x;
+			caps->minheight = pdev->view_min.y;
+			caps->maxwidth  = pdev->view_max.x;
+			caps->maxheight = pdev->view_max.y;
+			break;
+		}
+
+		/* Channel functions (simulate 1 channel) */
+		case VIDIOCGCHAN:
+		{
+			struct video_channel *v = arg;
+
+			if (v->channel != 0)
+				return -EINVAL;
+			v->flags = 0;
+			v->tuners = 0;
+			v->type = VIDEO_TYPE_CAMERA;
+			strcpy(v->name, "Webcam");
+			return 0;
+		}
+
+		case VIDIOCSCHAN:
+		{
+			/* The spec says the argument is an integer, but
+			   the bttv driver uses a video_channel arg, which
+			   makes sense becasue it also has the norm flag.
+			 */
+			struct video_channel *v = arg;
+			if (v->channel != 0)
+				return -EINVAL;
+			return 0;
+		}
+
+
+		/* Picture functions; contrast etc. */
+		case VIDIOCGPICT:
+		{
+			struct video_picture *p = arg;
+			int val;
+
+			val = pwc_get_brightness(pdev);
+			if (val >= 0)
+				p->brightness = (val<<9);
+			else
+				p->brightness = 0xffff;
+			val = pwc_get_contrast(pdev);
+			if (val >= 0)
+				p->contrast = (val<<10);
+			else
+				p->contrast = 0xffff;
+			/* Gamma, Whiteness, what's the difference? :) */
+			val = pwc_get_gamma(pdev);
+			if (val >= 0)
+				p->whiteness = (val<<11);
+			else
+				p->whiteness = 0xffff;
+			if (pwc_get_saturation(pdev, &val)<0)
+				p->colour = 0xffff;
+			else
+				p->colour = 32768 + val * 327;
+			p->depth = 24;
+			p->palette = pdev->vpalette;
+			p->hue = 0xFFFF; /* N/A */
+			break;
+		}
+
+		case VIDIOCSPICT:
+		{
+			struct video_picture *p = arg;
+			/*
+			 *	FIXME:	Suppose we are mid read
+				ANSWER: No problem: the firmware of the camera
+					can handle brightness/contrast/etc
+					changes at _any_ time, and the palette
+					is used exactly once in the uncompress
+					routine.
+			 */
+			pwc_set_brightness(pdev, p->brightness);
+			pwc_set_contrast(pdev, p->contrast);
+			pwc_set_gamma(pdev, p->whiteness);
+			pwc_set_saturation(pdev, (p->colour-32768)/327);
+			if (p->palette && p->palette != pdev->vpalette) {
+				switch (p->palette) {
+					case VIDEO_PALETTE_YUV420P:
+					case VIDEO_PALETTE_RAW:
+						pdev->vpalette = p->palette;
+						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+						break;
+					default:
+						return -EINVAL;
+						break;
+				}
+			}
+			break;
+		}
+
+		/* Window/size parameters */
+		case VIDIOCGWIN:
+		{
+			struct video_window *vw = arg;
+
+			vw->x = 0;
+			vw->y = 0;
+			vw->width = pdev->view.x;
+			vw->height = pdev->view.y;
+			vw->chromakey = 0;
+			vw->flags = (pdev->vframes << PWC_FPS_SHIFT) |
+				   (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+			break;
+		}
+
+		case VIDIOCSWIN:
+		{
+			struct video_window *vw = arg;
+			int fps, snapshot, ret;
+
+			fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+			snapshot = vw->flags & PWC_FPS_SNAPSHOT;
+			if (fps == 0)
+				fps = pdev->vframes;
+			if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+				return 0;
+			ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
+			if (ret)
+				return ret;
+			break;
+		}
+
+		/* We don't have overlay support (yet) */
+		case VIDIOCGFBUF:
+		{
+			struct video_buffer *vb = arg;
+
+			memset(vb,0,sizeof(*vb));
+			break;
+		}
+
+		/* mmap() functions */
+		case VIDIOCGMBUF:
+		{
+			/* Tell the user program how much memory is needed for a mmap() */
+			struct video_mbuf *vm = arg;
+			int i;
+
+			memset(vm, 0, sizeof(*vm));
+			vm->size = pwc_mbufs * pdev->len_per_image;
+			vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */
+			for (i = 0; i < pwc_mbufs; i++)
+				vm->offsets[i] = i * pdev->len_per_image;
+			break;
+		}
+
+		case VIDIOCMCAPTURE:
+		{
+			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+			struct video_mmap *vm = arg;
+
+			PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
+			if (vm->frame < 0 || vm->frame >= pwc_mbufs)
+				return -EINVAL;
+
+			/* xawtv is nasty. It probes the available palettes
+			   by setting a very small image size and trying
+			   various palettes... The driver doesn't support
+			   such small images, so I'm working around it.
+			 */
+			if (vm->format)
+			{
+				switch (vm->format)
+				{
+					case VIDEO_PALETTE_YUV420P:
+					case VIDEO_PALETTE_RAW:
+						break;
+					default:
+						return -EINVAL;
+						break;
+				}
+			}
+
+			if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
+			    (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
+				int ret;
+
+				PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+				ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+				if (ret)
+					return ret;
+			} /* ... size mismatch */
+
+			/* FIXME: should we lock here? */
+			if (pdev->image_used[vm->frame])
+				return -EBUSY;	/* buffer wasn't available. Bummer */
+			pdev->image_used[vm->frame] = 1;
+
+			/* Okay, we're done here. In the SYNC call we wait until a
+			   frame comes available, then expand image into the given
+			   buffer.
+			   In contrast to the CPiA cam the Philips cams deliver a
+			   constant stream, almost like a grabber card. Also,
+			   we have separate buffers for the rawdata and the image,
+			   meaning we can nearly always expand into the requested buffer.
+			 */
+			PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n");
+			break;
+		}
+
+		case VIDIOCSYNC:
+		{
+			/* The doc says: "Whenever a buffer is used it should
+			   call VIDIOCSYNC to free this frame up and continue."
+
+			   The only odd thing about this whole procedure is
+			   that MCAPTURE flags the buffer as "in use", and
+			   SYNC immediately unmarks it, while it isn't
+			   after SYNC that you know that the buffer actually
+			   got filled! So you better not start a CAPTURE in
+			   the same frame immediately (use double buffering).
+			   This is not a problem for this cam, since it has
+			   extra intermediate buffers, but a hardware
+			   grabber card will then overwrite the buffer
+			   you're working on.
+			 */
+			int *mbuf = arg;
+			int ret;
+
+			PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf);
+
+			/* bounds check */
+			if (*mbuf < 0 || *mbuf >= pwc_mbufs)
+				return -EINVAL;
+			/* check if this buffer was requested anyway */
+			if (pdev->image_used[*mbuf] == 0)
+				return -EINVAL;
+
+			/* Add ourselves to the frame wait-queue.
+
+			   FIXME: needs auditing for safety.
+			   QUESTION: In what respect? I think that using the
+				     frameq is safe now.
+			 */
+			add_wait_queue(&pdev->frameq, &wait);
+			while (pdev->full_frames == NULL) {
+				/* Check for unplugged/etc. here */
+				if (pdev->error_status) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -pdev->error_status;
+				}
+
+				if (signal_pending(current)) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -ERESTARTSYS;
+				}
+				schedule();
+				set_current_state(TASK_INTERRUPTIBLE);
+			}
+			remove_wait_queue(&pdev->frameq, &wait);
+			set_current_state(TASK_RUNNING);
+
+			/* The frame is ready. Expand in the image buffer
+			   requested by the user. I don't care if you
+			   mmap() 5 buffers and request data in this order:
+			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+			   Grabber hardware may not be so forgiving.
+			 */
+			PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n");
+			pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
+			/* Decompress, etc */
+			ret = pwc_handle_frame(pdev);
+			pdev->image_used[*mbuf] = 0;
+			if (ret)
+				return -EFAULT;
+			break;
+		}
+
+		case VIDIOCGAUDIO:
+		{
+			struct video_audio *v = arg;
+
+			strcpy(v->name, "Microphone");
+			v->audio = -1; /* unknown audio minor */
+			v->flags = 0;
+			v->mode = VIDEO_SOUND_MONO;
+			v->volume = 0;
+			v->bass = 0;
+			v->treble = 0;
+			v->balance = 0x8000;
+			v->step = 1;
+			break;
+		}
+
+		case VIDIOCSAUDIO:
+		{
+			/* Dummy: nothing can be set */
+			break;
+		}
+
+		case VIDIOCGUNIT:
+		{
+			struct video_unit *vu = arg;
+
+			vu->video = pdev->vdev->minor & 0x3F;
+			vu->audio = -1; /* not known yet */
+			vu->vbi = -1;
+			vu->radio = -1;
+			vu->teletext = -1;
+			break;
+		}
+
+		/* V4L2 Layer */
+		case VIDIOC_QUERYCAP:
+		{
+		    struct v4l2_capability *cap = arg;
+
+		    PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\
+				       "try to use the v4l2 layer\n");
+		    strcpy(cap->driver,PWC_NAME);
+		    strlcpy(cap->card, vdev->name, sizeof(cap->card));
+		    usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
+		    cap->version = PWC_VERSION_CODE;
+		    cap->capabilities =
+			V4L2_CAP_VIDEO_CAPTURE	|
+			V4L2_CAP_STREAMING	|
+			V4L2_CAP_READWRITE;
+		    return 0;
+		}
+
+		case VIDIOC_ENUMINPUT:
+		{
+		    struct v4l2_input *i = arg;
+
+		    if ( i->index )	/* Only one INPUT is supported */
+			  return -EINVAL;
+
+		    memset(i, 0, sizeof(struct v4l2_input));
+		    strcpy(i->name, "usb");
+		    return 0;
+		}
+
+		case VIDIOC_G_INPUT:
+		{
+		    int *i = arg;
+		    *i = 0;	/* Only one INPUT is supported */
+		    return 0;
+		}
+		case VIDIOC_S_INPUT:
+		{
+			int *i = arg;
+
+			if ( *i ) {	/* Only one INPUT is supported */
+				PWC_DEBUG_IOCTL("Only one input source is"\
+					" supported with this webcam.\n");
+				return -EINVAL;
+			}
+			return 0;
+		}
+
+		/* TODO: */
+		case VIDIOC_QUERYCTRL:
+		{
+			struct v4l2_queryctrl *c = arg;
+			int i;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
+			for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
+				if (pwc_controls[i].id == c->id) {
+					PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
+					memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
+					return 0;
+				}
+			}
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
+
+			return -EINVAL;
+		}
+		case VIDIOC_G_CTRL:
+		{
+			struct v4l2_control *c = arg;
+			int ret;
+
+			switch (c->id)
+			{
+				case V4L2_CID_BRIGHTNESS:
+					c->value = pwc_get_brightness(pdev);
+					if (c->value<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_CONTRAST:
+					c->value = pwc_get_contrast(pdev);
+					if (c->value<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_SATURATION:
+					ret = pwc_get_saturation(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_GAMMA:
+					c->value = pwc_get_gamma(pdev);
+					if (c->value<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_RED_BALANCE:
+					ret = pwc_get_red_gain(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value >>= 8;
+					return 0;
+				case V4L2_CID_BLUE_BALANCE:
+					ret = pwc_get_blue_gain(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value >>= 8;
+					return 0;
+				case V4L2_CID_AUTO_WHITE_BALANCE:
+					ret = pwc_get_awb(pdev);
+					if (ret<0)
+						return -EINVAL;
+					c->value = (ret == PWC_WB_MANUAL)?0:1;
+					return 0;
+				case V4L2_CID_GAIN:
+					ret = pwc_get_agc(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value >>= 8;
+					return 0;
+				case V4L2_CID_AUTOGAIN:
+					ret = pwc_get_agc(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					c->value = (c->value < 0)?1:0;
+					return 0;
+				case V4L2_CID_EXPOSURE:
+					ret = pwc_get_shutter_speed(pdev, &c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_COLOUR_MODE:
+					ret = pwc_get_colour_mode(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_AUTOCONTOUR:
+					ret = pwc_get_contour(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					c->value=(c->value == -1?1:0);
+					return 0;
+				case V4L2_CID_PRIVATE_CONTOUR:
+					ret = pwc_get_contour(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					c->value >>= 10;
+					return 0;
+				case V4L2_CID_PRIVATE_BACKLIGHT:
+					ret = pwc_get_backlight(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_FLICKERLESS:
+					ret = pwc_get_flicker(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					c->value=(c->value?1:0);
+					return 0;
+				case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+					ret = pwc_get_dynamic_noise(pdev, &c->value);
+					if (ret < 0)
+						return -EINVAL;
+					return 0;
+
+				case V4L2_CID_PRIVATE_SAVE_USER:
+				case V4L2_CID_PRIVATE_RESTORE_USER:
+				case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+					return -EINVAL;
+			}
+			return -EINVAL;
+		}
+		case VIDIOC_S_CTRL:
+		{
+			struct v4l2_control *c = arg;
+			int ret;
+
+			switch (c->id)
+			{
+				case V4L2_CID_BRIGHTNESS:
+					c->value <<= 9;
+					ret = pwc_set_brightness(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_CONTRAST:
+					c->value <<= 10;
+					ret = pwc_set_contrast(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_SATURATION:
+					ret = pwc_set_saturation(pdev, c->value);
+					if (ret<0)
+					  return -EINVAL;
+					return 0;
+				case V4L2_CID_GAMMA:
+					c->value <<= 11;
+					ret = pwc_set_gamma(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_RED_BALANCE:
+					c->value <<= 8;
+					ret = pwc_set_red_gain(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_BLUE_BALANCE:
+					c->value <<= 8;
+					ret = pwc_set_blue_gain(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_AUTO_WHITE_BALANCE:
+					c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
+					ret = pwc_set_awb(pdev, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_EXPOSURE:
+					c->value <<= 8;
+					ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_AUTOGAIN:
+					/* autogain off means nothing without a gain */
+					if (c->value == 0)
+						return 0;
+					ret = pwc_set_agc(pdev, c->value, 0);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_GAIN:
+					c->value <<= 8;
+					ret = pwc_set_agc(pdev, 0, c->value);
+					if (ret<0)
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_SAVE_USER:
+					if (pwc_save_user(pdev))
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_RESTORE_USER:
+					if (pwc_restore_user(pdev))
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+					if (pwc_restore_factory(pdev))
+						return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_COLOUR_MODE:
+					ret = pwc_set_colour_mode(pdev, c->value);
+					if (ret < 0)
+					  return -EINVAL;
+					return 0;
+				case V4L2_CID_PRIVATE_AUTOCONTOUR:
+				  c->value=(c->value == 1)?-1:0;
+				  ret = pwc_set_contour(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+				case V4L2_CID_PRIVATE_CONTOUR:
+				  c->value <<= 10;
+				  ret = pwc_set_contour(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+				case V4L2_CID_PRIVATE_BACKLIGHT:
+				  ret = pwc_set_backlight(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+				case V4L2_CID_PRIVATE_FLICKERLESS:
+				  ret = pwc_set_flicker(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+				  ret = pwc_set_dynamic_noise(pdev, c->value);
+				  if (ret < 0)
+				    return -EINVAL;
+				  return 0;
+
+			}
+			return -EINVAL;
+		}
+
+		case VIDIOC_ENUM_FMT:
+		{
+			struct v4l2_fmtdesc *f = arg;
+			int index;
+
+			if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			      return -EINVAL;
+
+			/* We only support two format: the raw format, and YUV */
+			index = f->index;
+			memset(f,0,sizeof(struct v4l2_fmtdesc));
+			f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			f->index = index;
+			switch(index)
+			{
+				case 0:
+					/* RAW format */
+					f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
+					f->flags = V4L2_FMT_FLAG_COMPRESSED;
+					strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
+					break;
+				case 1:
+					f->pixelformat = V4L2_PIX_FMT_YUV420;
+					strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
+					break;
+				default:
+					return -EINVAL;
+			}
+			return 0;
+		}
+
+		case VIDIOC_G_FMT:
+		{
+			struct v4l2_format *f = arg;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y);
+			if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			      return -EINVAL;
+
+			pwc_vidioc_fill_fmt(pdev, f);
+
+			return 0;
+		}
+
+		case VIDIOC_TRY_FMT:
+			return pwc_vidioc_try_fmt(pdev, arg);
+
+		case VIDIOC_S_FMT:
+			return pwc_vidioc_set_fmt(pdev, arg);
+
+		case VIDIOC_G_STD:
+		{
+			v4l2_std_id *std = arg;
+			*std = V4L2_STD_UNKNOWN;
+			return 0;
+		}
+
+		case VIDIOC_S_STD:
+		{
+			v4l2_std_id *std = arg;
+			if (*std != V4L2_STD_UNKNOWN)
+				return -EINVAL;
+			return 0;
+		}
+
+		case VIDIOC_ENUMSTD:
+		{
+			struct v4l2_standard *std = arg;
+			if (std->index != 0)
+				return -EINVAL;
+			std->id = V4L2_STD_UNKNOWN;
+			strncpy(std->name, "webcam", sizeof(std->name));
+			return 0;
+		}
+
+		case VIDIOC_REQBUFS:
+		{
+			struct v4l2_requestbuffers *rb = arg;
+			int nbuffers;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count);
+			if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+			if (rb->memory != V4L2_MEMORY_MMAP)
+				return -EINVAL;
+
+			nbuffers = rb->count;
+			if (nbuffers < 2)
+				nbuffers = 2;
+			else if (nbuffers > pwc_mbufs)
+				nbuffers = pwc_mbufs;
+			/* Force to use our # of buffers */
+			rb->count = pwc_mbufs;
+			return 0;
+		}
+
+		case VIDIOC_QUERYBUF:
+		{
+			struct v4l2_buffer *buf = arg;
+			int index;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index);
+			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+				PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
+				return -EINVAL;
+			}
+			if (buf->memory != V4L2_MEMORY_MMAP) {
+				PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n");
+				return -EINVAL;
+			}
+			index = buf->index;
+			if (index < 0 || index >= pwc_mbufs) {
+				PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
+				return -EINVAL;
+			}
+
+			memset(buf, 0, sizeof(struct v4l2_buffer));
+			buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			buf->index = index;
+			buf->m.offset = index * pdev->len_per_image;
+			if (pdev->vpalette == VIDEO_PALETTE_RAW)
+				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+			else
+				buf->bytesused = pdev->view.size;
+			buf->field = V4L2_FIELD_NONE;
+			buf->memory = V4L2_MEMORY_MMAP;
+			//buf->flags = V4L2_BUF_FLAG_MAPPED;
+			buf->length = pdev->len_per_image;
+
+			PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
+			PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
+			PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
+
+			return 0;
+		}
+
+		case VIDIOC_QBUF:
+		{
+			struct v4l2_buffer *buf = arg;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index);
+			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+			if (buf->memory != V4L2_MEMORY_MMAP)
+				return -EINVAL;
+			if (buf->index < 0 || buf->index >= pwc_mbufs)
+				return -EINVAL;
+
+			buf->flags |= V4L2_BUF_FLAG_QUEUED;
+			buf->flags &= ~V4L2_BUF_FLAG_DONE;
+
+			return 0;
+		}
+
+		case VIDIOC_DQBUF:
+		{
+			struct v4l2_buffer *buf = arg;
+			int ret;
+
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
+
+			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+				return -EINVAL;
+
+			/* Add ourselves to the frame wait-queue.
+
+			   FIXME: needs auditing for safety.
+			   QUESTION: In what respect? I think that using the
+				     frameq is safe now.
+			 */
+			add_wait_queue(&pdev->frameq, &wait);
+			while (pdev->full_frames == NULL) {
+				if (pdev->error_status) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -pdev->error_status;
+				}
+
+				if (signal_pending(current)) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -ERESTARTSYS;
+				}
+				schedule();
+				set_current_state(TASK_INTERRUPTIBLE);
+			}
+			remove_wait_queue(&pdev->frameq, &wait);
+			set_current_state(TASK_RUNNING);
+
+			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
+			/* Decompress data in pdev->images[pdev->fill_image] */
+			ret = pwc_handle_frame(pdev);
+			if (ret)
+				return -EFAULT;
+			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
+
+			buf->index = pdev->fill_image;
+			if (pdev->vpalette == VIDEO_PALETTE_RAW)
+				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+			else
+				buf->bytesused = pdev->view.size;
+			buf->flags = V4L2_BUF_FLAG_MAPPED;
+			buf->field = V4L2_FIELD_NONE;
+			do_gettimeofday(&buf->timestamp);
+			buf->sequence = 0;
+			buf->memory = V4L2_MEMORY_MMAP;
+			buf->m.offset = pdev->fill_image * pdev->len_per_image;
+			buf->length = buf->bytesused;
+			pwc_next_image(pdev);
+
+			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index);
+			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length);
+			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset);
+			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused);
+			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
+			return 0;
+
+		}
+
+		case VIDIOC_STREAMON:
+		{
+			/* WARNING: pwc_try_video_mode() called pwc_isoc_init */
+			pwc_isoc_init(pdev);
+			return 0;
+		}
+
+		case VIDIOC_STREAMOFF:
+		{
+			pwc_isoc_cleanup(pdev);
+			return 0;
+		}
+
+		default:
+			return pwc_ioctl(pdev, cmd, arg);
+	} /* ..switch */
+	return 0;
+}
+
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 1b0ee0c..629f79e 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -1,5 +1,5 @@
 /* (C) 1999-2003 Nemosoft Unv.
-   (C) 2004      Luc Saillard (luc@saillard.org)
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
 
    NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
    driver and thus may have bugs that are not present in the original version.
@@ -29,51 +29,87 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/spinlock.h>
-#include <linux/videodev.h>
 #include <linux/wait.h>
 #include <linux/smp_lock.h>
+#include <linux/version.h>
 #include <asm/semaphore.h>
 #include <asm/errno.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include "pwc-uncompress.h"
-#include "pwc-ioctl.h"
-
-/* Defines and structures for the Philips webcam */
-/* Used for checking memory corruption/pointer validation */
-#define PWC_MAGIC 0x89DC10ABUL
-#undef PWC_MAGIC
+#include <media/pwc-ioctl.h>
 
 /* Turn some debugging options on/off */
-#define PWC_DEBUG 0
+#ifndef CONFIG_PWC_DEBUG
+#define CONFIG_PWC_DEBUG 1
+#endif
+
+/* Version block */
+#define PWC_MAJOR	10
+#define PWC_MINOR	0
+#define PWC_EXTRAMINOR	12
+#define PWC_VERSION_CODE KERNEL_VERSION(PWC_MAJOR,PWC_MINOR,PWC_EXTRAMINOR)
+#define PWC_VERSION 	"10.0.12"
+#define PWC_NAME 	"pwc"
+#define PFX		PWC_NAME ": "
+
 
 /* Trace certain actions in the driver */
-#define TRACE_MODULE	0x0001
-#define TRACE_PROBE	0x0002
-#define TRACE_OPEN	0x0004
-#define TRACE_READ	0x0008
-#define TRACE_MEMORY	0x0010
-#define TRACE_FLOW	0x0020
-#define TRACE_SIZE	0x0040
-#define TRACE_PWCX	0x0080
-#define TRACE_SEQUENCE	0x1000
+#define PWC_DEBUG_LEVEL_MODULE	(1<<0)
+#define PWC_DEBUG_LEVEL_PROBE	(1<<1)
+#define PWC_DEBUG_LEVEL_OPEN	(1<<2)
+#define PWC_DEBUG_LEVEL_READ	(1<<3)
+#define PWC_DEBUG_LEVEL_MEMORY	(1<<4)
+#define PWC_DEBUG_LEVEL_FLOW	(1<<5)
+#define PWC_DEBUG_LEVEL_SIZE	(1<<6)
+#define PWC_DEBUG_LEVEL_IOCTL	(1<<7)
+#define PWC_DEBUG_LEVEL_TRACE	(1<<8)
 
-#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
-#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
-#define Info(A...)  printk(KERN_INFO  PWC_NAME " " A)
-#define Err(A...)   printk(KERN_ERR   PWC_NAME " " A)
+#define PWC_DEBUG_MODULE(fmt, args...) PWC_DEBUG(MODULE, fmt, ##args)
+#define PWC_DEBUG_PROBE(fmt, args...) PWC_DEBUG(PROBE, fmt, ##args)
+#define PWC_DEBUG_OPEN(fmt, args...) PWC_DEBUG(OPEN, fmt, ##args)
+#define PWC_DEBUG_READ(fmt, args...) PWC_DEBUG(READ, fmt, ##args)
+#define PWC_DEBUG_MEMORY(fmt, args...) PWC_DEBUG(MEMORY, fmt, ##args)
+#define PWC_DEBUG_FLOW(fmt, args...) PWC_DEBUG(FLOW, fmt, ##args)
+#define PWC_DEBUG_SIZE(fmt, args...) PWC_DEBUG(SIZE, fmt, ##args)
+#define PWC_DEBUG_IOCTL(fmt, args...) PWC_DEBUG(IOCTL, fmt, ##args)
+#define PWC_DEBUG_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
 
 
+#if CONFIG_PWC_DEBUG
+
+#define PWC_DEBUG_LEVEL	(PWC_DEBUG_LEVEL_MODULE)
+
+#define PWC_DEBUG(level, fmt, args...) do {\
+	  if ((PWC_DEBUG_LEVEL_ ##level) & pwc_trace) \
+	     printk(KERN_DEBUG PFX fmt, ##args); \
+	  } while(0)
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) PWC_DEBUG(TRACE, fmt, ##args)
+
+#else /* if ! CONFIG_PWC_DEBUG */
+
+#define PWC_ERROR(fmt, args...) printk(KERN_ERR PFX fmt, ##args)
+#define PWC_WARNING(fmt, args...) printk(KERN_WARNING PFX fmt, ##args)
+#define PWC_INFO(fmt, args...) printk(KERN_INFO PFX fmt, ##args)
+#define PWC_TRACE(fmt, args...) do { } while(0)
+#define PWC_DEBUG(level, fmt, args...) do { } while(0)
+
+#define pwc_trace 0
+
+#endif
+
 /* Defines for ToUCam cameras */
 #define TOUCAM_HEADER_SIZE		8
 #define TOUCAM_TRAILER_SIZE		4
 
 #define FEATURE_MOTOR_PANTILT		0x0001
-
-/* Version block */
-#define PWC_MAJOR	9
-#define PWC_MINOR	0
-#define PWC_VERSION 	"9.0.2-unofficial"
-#define PWC_NAME 	"pwc"
+#define FEATURE_CODEC1			0x0002
+#define FEATURE_CODEC2			0x0004
 
 /* Turn certain features on/off */
 #define PWC_INT_PIPE 0
@@ -95,6 +131,18 @@
 /* Absolute maximum number of buffers available for mmap() */
 #define MAX_IMAGES 		10
 
+/* Some macros to quickly find the type of a webcam */
+#define DEVICE_USE_CODEC1(x) ((x)<675)
+#define DEVICE_USE_CODEC2(x) ((x)>=675 && (x)<700)
+#define DEVICE_USE_CODEC3(x) ((x)>=700)
+#define DEVICE_USE_CODEC23(x) ((x)>=675)
+
+
+#ifndef V4L2_PIX_FMT_PWC1
+#define V4L2_PIX_FMT_PWC1	v4l2_fourcc('P','W','C','1')
+#define V4L2_PIX_FMT_PWC2	v4l2_fourcc('P','W','C','2')
+#endif
+
 /* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
 struct pwc_iso_buf
 {
@@ -110,17 +158,19 @@
    void *data;
    volatile int filled;		/* number of bytes filled */
    struct pwc_frame_buf *next;	/* list */
-#if PWC_DEBUG
-   int sequence;		/* Sequence number */
-#endif
+};
+
+/* additionnal informations used when dealing image between kernel and userland */
+struct pwc_imgbuf
+{
+	unsigned long offset;	/* offset of this buffer in the big array of image_data */
+	int   vma_use_count;	/* count the number of time this memory is mapped */
 };
 
 struct pwc_device
 {
    struct video_device *vdev;
-#ifdef PWC_MAGIC
-   int magic;
-#endif
+
    /* Pointer to our usb_device */
    struct usb_device *udev;
 
@@ -177,12 +227,8 @@
    int frame_size;
    int frame_total_size; /* including header & trailer */
    int drop_frames;
-#if PWC_DEBUG
-   int sequence;			/* Debugging aid */
-#endif
 
    /* 3: decompression */
-   struct pwc_decompressor *decompressor;	/* function block with decompression routines */
    void *decompress_data;		/* private data for decompression engine */
 
    /* 4: image */
@@ -198,7 +244,7 @@
    struct pwc_coord offset;		/* offset within the viewport */
 
    void *image_data;			/* total buffer, which is subdivided into ... */
-   void *image_ptr[MAX_IMAGES];		/* ...several images... */
+   struct pwc_imgbuf images[MAX_IMAGES];/* ...several images... */
    int fill_image;			/* ...which are rotated. */
    int len_per_image;			/* length per image */
    int image_read_pos;			/* In case we read data in pieces, keep track of were we are in the imagebuffer */
@@ -211,6 +257,7 @@
    struct pwc_mpt_range angle_range;
    int pan_angle;			/* in degrees * 100 */
    int tilt_angle;			/* absolute angle; 0,0 is home position */
+   int snapshot_button_status;		/* set to 1 when the user push the button, reset to 0 when this value is read */
 
    /*** Misc. data ***/
    wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
@@ -219,20 +266,26 @@
 #endif
 };
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* Global variable */
+/* Global variables */
+#if CONFIG_PWC_DEBUG
 extern int pwc_trace;
+#endif
+extern int pwc_mbufs;
 
 /** functions in pwc-if.c */
 int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
+int pwc_handle_frame(struct pwc_device *pdev);
+void pwc_next_image(struct pwc_device *pdev);
+int pwc_isoc_init(struct pwc_device *pdev);
+void pwc_isoc_cleanup(struct pwc_device *pdev);
 
 /** Functions in pwc-misc.c */
 /* sizes in pixels */
-extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+extern const struct pwc_coord pwc_image_sizes[PSZ_MAX];
 
 int pwc_decode_size(struct pwc_device *pdev, int width, int height);
 void pwc_construct(struct pwc_device *pdev);
@@ -240,6 +293,9 @@
 /** Functions in pwc-ctrl.c */
 /* Request a certain video mode. Returns < 0 if not possible */
 extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern int pwc_mpt_reset(struct pwc_device *pdev, int flags);
+extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt);
 
 /* Various controls; should be obvious. Value 0..65535, or < 0 on error */
 extern int pwc_get_brightness(struct pwc_device *pdev);
@@ -248,10 +304,36 @@
 extern int pwc_set_contrast(struct pwc_device *pdev, int value);
 extern int pwc_get_gamma(struct pwc_device *pdev);
 extern int pwc_set_gamma(struct pwc_device *pdev, int value);
-extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_get_saturation(struct pwc_device *pdev, int *value);
 extern int pwc_set_saturation(struct pwc_device *pdev, int value);
 extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
 extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+extern int pwc_restore_user(struct pwc_device *pdev);
+extern int pwc_save_user(struct pwc_device *pdev);
+extern int pwc_restore_factory(struct pwc_device *pdev);
+
+/* exported for use by v4l2 controls */
+extern int pwc_get_red_gain(struct pwc_device *pdev, int *value);
+extern int pwc_set_red_gain(struct pwc_device *pdev, int value);
+extern int pwc_get_blue_gain(struct pwc_device *pdev, int *value);
+extern int pwc_set_blue_gain(struct pwc_device *pdev, int value);
+extern int pwc_get_awb(struct pwc_device *pdev);
+extern int pwc_set_awb(struct pwc_device *pdev, int mode);
+extern int pwc_set_agc(struct pwc_device *pdev, int mode, int value);
+extern int pwc_get_agc(struct pwc_device *pdev, int *value);
+extern int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value);
+extern int pwc_get_shutter_speed(struct pwc_device *pdev, int *value);
+
+extern int pwc_set_colour_mode(struct pwc_device *pdev, int colour);
+extern int pwc_get_colour_mode(struct pwc_device *pdev, int *colour);
+extern int pwc_set_contour(struct pwc_device *pdev, int contour);
+extern int pwc_get_contour(struct pwc_device *pdev, int *contour);
+extern int pwc_set_backlight(struct pwc_device *pdev, int backlight);
+extern int pwc_get_backlight(struct pwc_device *pdev, int *backlight);
+extern int pwc_set_flicker(struct pwc_device *pdev, int flicker);
+extern int pwc_get_flicker(struct pwc_device *pdev, int *flicker);
+extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise);
+extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
 
 /* Power down or up the camera; not supported by all models */
 extern int pwc_camera_power(struct pwc_device *pdev, int power);
@@ -259,6 +341,9 @@
 /* Private ioctl()s; see pwc-ioctl.h */
 extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
 
+/** Functions in pwc-v4l.c */
+extern int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+			      unsigned int cmd, void *arg);
 
 /** pwc-uncompress.c */
 /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
@@ -270,3 +355,4 @@
 
 
 #endif
+/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index dd830e0..59a1872 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -46,6 +46,7 @@
 #include <linux/i2c.h>
 #include <linux/videotext.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 #include "saa5246a.h"
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index 531e946..19a8d65 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -56,6 +56,7 @@
 #include <linux/i2c.h>
 #include <linux/videotext.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/mutex.h>
 
 
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 41d951d..676b997 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -43,6 +43,7 @@
 #define I2C_NAME(s) (s)->name
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 
 static int debug = 0;
diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
index dceebc0..b59c117 100644
--- a/drivers/media/video/saa7115.c
+++ b/drivers/media/video/saa7115.c
@@ -72,6 +72,10 @@
 	int sat;
 	enum v4l2_chip_ident ident;
 	u32 audclk_freq;
+	u32 crystal_freq;
+	u8 ucgc;
+	u8 cgcdiv;
+	u8 apll;
 };
 
 /* ----------------------------------------------------------------------- */
@@ -375,10 +379,6 @@
 };
 
 static const unsigned char saa7115_init_misc[] = {
-	0x38, 0x03,		/* audio stuff */
-	0x39, 0x10,
-	0x3a, 0x08,
-
 	0x81, 0x01,		/* reg 0x15,0x16 define blanking window */
 	0x82, 0x00,
 	0x83, 0x01,		/* I port settings */
@@ -584,6 +584,7 @@
 	u32 acni;
 	u32 hz;
 	u64 f;
+	u8 acc = 0; 	/* reg 0x3a, audio clock control */
 
 	v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
 
@@ -591,18 +592,34 @@
 	if (freq < 32000 || freq > 48000)
 		return -EINVAL;
 
+	/* The saa7113 has no audio clock */
+	if (state->ident == V4L2_IDENT_SAA7113)
+		return 0;
+
 	/* hz is the refresh rate times 100 */
 	hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
 	/* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
 	acpf = (25600 * freq) / hz;
 	/* acni = (256 * freq * 2^23) / crystal_frequency =
 		  (freq * 2^(8+23)) / crystal_frequency =
-		  (freq << 31) / 32.11 MHz */
+		  (freq << 31) / crystal_frequency */
 	f = freq;
 	f = f << 31;
-	do_div(f, 32110000);
+	do_div(f, state->crystal_freq);
 	acni = f;
+	if (state->ucgc) {
+		acpf = acpf * state->cgcdiv / 16;
+		acni = acni * state->cgcdiv / 16;
+		acc = 0x80;
+		if (state->cgcdiv == 3)
+			acc |= 0x40;
+	}
+	if (state->apll)
+		acc |= 0x08;
 
+	saa7115_write(client, 0x38, 0x03);
+	saa7115_write(client, 0x39, 0x10);
+	saa7115_write(client, 0x3a, acc);
 	saa7115_write(client, 0x30, acpf & 0xff);
 	saa7115_write(client, 0x31, (acpf >> 8) & 0xff);
 	saa7115_write(client, 0x32, (acpf >> 16) & 0x03);
@@ -1073,48 +1090,6 @@
 
 /* ============ SAA7115 AUDIO settings (end) ============= */
 
-static struct v4l2_queryctrl saa7115_qctrl[] = {
-	{
-		.id            = V4L2_CID_BRIGHTNESS,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Brightness",
-		.minimum       = 0,
-		.maximum       = 255,
-		.step          = 1,
-		.default_value = 128,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_CONTRAST,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Contrast",
-		.minimum       = 0,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 64,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_SATURATION,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Saturation",
-		.minimum       = 0,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 64,
-		.flags         = 0,
-	}, {
-		.id            = V4L2_CID_HUE,
-		.type          = V4L2_CTRL_TYPE_INTEGER,
-		.name          = "Hue",
-		.minimum       = -128,
-		.maximum       = 127,
-		.step          = 1,
-		.default_value = 0,
-		.flags 	       = 0,
-	},
-};
-
-/* ----------------------------------------------------------------------- */
-
 static int saa7115_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	struct saa7115_state *state = i2c_get_clientdata(client);
@@ -1158,14 +1133,16 @@
 	case VIDIOC_QUERYCTRL:
 	{
 		struct v4l2_queryctrl *qc = arg;
-		int i;
 
-		for (i = 0; i < ARRAY_SIZE(saa7115_qctrl); i++)
-			if (qc->id && qc->id == saa7115_qctrl[i].id) {
-				memcpy(qc, &saa7115_qctrl[i], sizeof(*qc));
-				return 0;
-			}
-		return -EINVAL;
+		switch (qc->id) {
+			case V4L2_CID_BRIGHTNESS:
+			case V4L2_CID_CONTRAST:
+			case V4L2_CID_SATURATION:
+			case V4L2_CID_HUE:
+				return v4l2_ctrl_query_fill_std(qc);
+			default:
+				return -EINVAL;
+		}
 	}
 
 	case VIDIOC_G_STD:
@@ -1221,34 +1198,6 @@
 		break;
 	}
 
-	case VIDIOC_G_INPUT:
-		*(int *)arg = state->input;
-		break;
-
-	case VIDIOC_S_INPUT:
-		v4l_dbg(1, debug, client, "decoder set input %d\n", *iarg);
-		/* inputs from 0-9 are available */
-		if (*iarg < 0 || *iarg > 9) {
-			return -EINVAL;
-		}
-
-		if (state->input == *iarg)
-			break;
-		v4l_dbg(1, debug, client, "now setting %s input\n",
-			*iarg >= 6 ? "S-Video" : "Composite");
-		state->input = *iarg;
-
-		/* select mode */
-		saa7115_write(client, 0x02,
-			      (saa7115_read(client, 0x02) & 0xf0) |
-			       state->input);
-
-		/* bypass chrominance trap for modes 6..9 */
-		saa7115_write(client, 0x09,
-			      (saa7115_read(client, 0x09) & 0x7f) |
-			       (state->input < 6 ? 0x0 : 0x80));
-		break;
-
 	case VIDIOC_STREAMON:
 	case VIDIOC_STREAMOFF:
 		v4l_dbg(1, debug, client, "%s output\n",
@@ -1260,6 +1209,21 @@
 		}
 		break;
 
+	case VIDIOC_INT_S_CRYSTAL_FREQ:
+	{
+		struct v4l2_crystal_freq *freq = arg;
+
+		if (freq->freq != SAA7115_FREQ_32_11_MHZ &&
+		    freq->freq != SAA7115_FREQ_24_576_MHZ)
+			return -EINVAL;
+		state->crystal_freq = freq->freq;
+		state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
+		state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
+		state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
+		saa7115_set_audio_clock_freq(client, state->audclk_freq);
+		break;
+	}
+
 	case VIDIOC_INT_DECODE_VBI_LINE:
 		saa7115_decode_vbi_line(client, arg);
 		break;
@@ -1401,10 +1365,13 @@
 	v4l_dbg(1, debug, client, "writing init values\n");
 
 	/* init to 60hz/48khz */
-	if (state->ident == V4L2_IDENT_SAA7113)
+	if (state->ident == V4L2_IDENT_SAA7113) {
+		state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
 		saa7115_writeregs(client, saa7113_init_auto_input);
-	else
+	} else {
+		state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
 		saa7115_writeregs(client, saa7115_init_auto_input);
+	}
 	saa7115_writeregs(client, saa7115_init_misc);
 	saa7115_writeregs(client, saa7115_cfg_60hz_fullres_x);
 	saa7115_writeregs(client, saa7115_cfg_60hz_fullres_y);
diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c
index c271e2e..ad401bd 100644
--- a/drivers/media/video/saa7127.c
+++ b/drivers/media/video/saa7127.c
@@ -270,7 +270,7 @@
 	"letterbox 16:9 top",
 	"invalid",
 	"invalid",
-	"16:9 full format anamorphic"
+	"16:9 full format anamorphic",
 	"4:3 full format",
 	"invalid",
 	"invalid",
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 0e0ba50..afc8f35 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -39,6 +39,23 @@
 	SAA6752HS_VF_UNKNOWN,
 };
 
+struct saa6752hs_mpeg_params {
+	/* transport streams */
+	__u16				ts_pid_pmt;
+	__u16				ts_pid_audio;
+	__u16				ts_pid_video;
+	__u16				ts_pid_pcr;
+
+	/* audio */
+	enum v4l2_mpeg_audio_l2_bitrate au_l2_bitrate;
+
+	/* video */
+	enum v4l2_mpeg_video_aspect	vi_aspect;
+	enum v4l2_mpeg_video_bitrate_mode vi_bitrate_mode;
+	__u32 				vi_bitrate;
+	__u32 				vi_bitrate_peak;
+};
+
 static const struct v4l2_format v4l2_format_table[] =
 {
 	[SAA6752HS_VF_D1] =
@@ -55,18 +72,19 @@
 
 struct saa6752hs_state {
 	struct i2c_client             client;
-	struct v4l2_mpeg_compression  params;
+	struct v4l2_mpeg_compression  old_params;
+	struct saa6752hs_mpeg_params  params;
 	enum saa6752hs_videoformat    video_format;
 	v4l2_std_id                   standard;
 };
 
 enum saa6752hs_command {
 	SAA6752HS_COMMAND_RESET = 0,
-    	SAA6752HS_COMMAND_STOP = 1,
-    	SAA6752HS_COMMAND_START = 2,
-    	SAA6752HS_COMMAND_PAUSE = 3,
-    	SAA6752HS_COMMAND_RECONFIGURE = 4,
-    	SAA6752HS_COMMAND_SLEEP = 5,
+	SAA6752HS_COMMAND_STOP = 1,
+	SAA6752HS_COMMAND_START = 2,
+	SAA6752HS_COMMAND_PAUSE = 3,
+	SAA6752HS_COMMAND_RECONFIGURE = 4,
+	SAA6752HS_COMMAND_SLEEP = 5,
 	SAA6752HS_COMMAND_RECONFIGURE_FORCE = 6,
 
 	SAA6752HS_COMMAND_MAX
@@ -129,7 +147,22 @@
 	0x00, 0x00, 0x00, 0x00 /* CRC32 */
 };
 
-static struct v4l2_mpeg_compression param_defaults =
+static struct saa6752hs_mpeg_params param_defaults =
+{
+	.ts_pid_pmt      = 16,
+	.ts_pid_video    = 260,
+	.ts_pid_audio    = 256,
+	.ts_pid_pcr      = 259,
+
+	.vi_aspect       = V4L2_MPEG_VIDEO_ASPECT_4x3,
+	.vi_bitrate      = 4000,
+	.vi_bitrate_peak = 6000,
+	.vi_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+
+	.au_l2_bitrate   = V4L2_MPEG_AUDIO_L2_BITRATE_256K,
+};
+
+static struct v4l2_mpeg_compression old_param_defaults =
 {
 	.st_type         = V4L2_MPEG_TS_2,
 	.st_bitrate      = {
@@ -228,45 +261,57 @@
 
 
 static int saa6752hs_set_bitrate(struct i2c_client* client,
-				 struct v4l2_mpeg_compression* params)
+				 struct saa6752hs_mpeg_params* params)
 {
 	u8 buf[3];
+	int tot_bitrate;
 
 	/* set the bitrate mode */
 	buf[0] = 0x71;
-	buf[1] = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ? 0 : 1;
+	buf[1] = (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) ? 0 : 1;
 	i2c_master_send(client, buf, 2);
 
 	/* set the video bitrate */
-	if (params->vi_bitrate.mode == V4L2_BITRATE_VBR) {
+	if (params->vi_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
 		/* set the target bitrate */
 		buf[0] = 0x80;
-	    	buf[1] = params->vi_bitrate.target >> 8;
-		buf[2] = params->vi_bitrate.target & 0xff;
+		buf[1] = params->vi_bitrate >> 8;
+		buf[2] = params->vi_bitrate & 0xff;
 		i2c_master_send(client, buf, 3);
 
 		/* set the max bitrate */
 		buf[0] = 0x81;
-	    	buf[1] = params->vi_bitrate.max >> 8;
-		buf[2] = params->vi_bitrate.max & 0xff;
+		buf[1] = params->vi_bitrate_peak >> 8;
+		buf[2] = params->vi_bitrate_peak & 0xff;
 		i2c_master_send(client, buf, 3);
+		tot_bitrate = params->vi_bitrate_peak;
 	} else {
 		/* set the target bitrate (no max bitrate for CBR) */
 		buf[0] = 0x81;
-	    	buf[1] = params->vi_bitrate.target >> 8;
-		buf[2] = params->vi_bitrate.target & 0xff;
+		buf[1] = params->vi_bitrate >> 8;
+		buf[2] = params->vi_bitrate & 0xff;
 		i2c_master_send(client, buf, 3);
+		tot_bitrate = params->vi_bitrate;
 	}
 
 	/* set the audio bitrate */
 	buf[0] = 0x94;
-	buf[1] = (256 == params->au_bitrate.target) ? 0 : 1;
+	buf[1] = (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 0 : 1;
 	i2c_master_send(client, buf, 2);
+	tot_bitrate += (V4L2_MPEG_AUDIO_L2_BITRATE_256K == params->au_l2_bitrate) ? 256 : 384;
+
+	/* Note: the total max bitrate is determined by adding the video and audio
+	   bitrates together and also adding an extra 768kbit/s to stay on the
+	   safe side. If more control should be required, then an extra MPEG control
+	   should be added. */
+	tot_bitrate += 768;
+	if (tot_bitrate > MPEG_TOTAL_TARGET_BITRATE_MAX)
+		tot_bitrate = MPEG_TOTAL_TARGET_BITRATE_MAX;
 
 	/* set the total bitrate */
 	buf[0] = 0xb1;
-	buf[1] = params->st_bitrate.target >> 8;
-	buf[2] = params->st_bitrate.target & 0xff;
+	buf[1] = tot_bitrate >> 8;
+	buf[2] = tot_bitrate & 0xff;
 	i2c_master_send(client, buf, 3);
 
 	return 0;
@@ -318,50 +363,188 @@
 }
 
 
-static void saa6752hs_set_params(struct i2c_client* client,
+static void saa6752hs_old_set_params(struct i2c_client* client,
 				 struct v4l2_mpeg_compression* params)
 {
 	struct saa6752hs_state *h = i2c_get_clientdata(client);
 
 	/* check PIDs */
-	if (params->ts_pid_pmt <= MPEG_PID_MAX)
+	if (params->ts_pid_pmt <= MPEG_PID_MAX) {
+		h->old_params.ts_pid_pmt = params->ts_pid_pmt;
 		h->params.ts_pid_pmt = params->ts_pid_pmt;
-	if (params->ts_pid_pcr <= MPEG_PID_MAX)
+	}
+	if (params->ts_pid_pcr <= MPEG_PID_MAX) {
+		h->old_params.ts_pid_pcr = params->ts_pid_pcr;
 		h->params.ts_pid_pcr = params->ts_pid_pcr;
-	if (params->ts_pid_video <= MPEG_PID_MAX)
+	}
+	if (params->ts_pid_video <= MPEG_PID_MAX) {
+		h->old_params.ts_pid_video = params->ts_pid_video;
 		h->params.ts_pid_video = params->ts_pid_video;
-	if (params->ts_pid_audio <= MPEG_PID_MAX)
+	}
+	if (params->ts_pid_audio <= MPEG_PID_MAX) {
+		h->old_params.ts_pid_audio = params->ts_pid_audio;
 		h->params.ts_pid_audio = params->ts_pid_audio;
+	}
 
 	/* check bitrate parameters */
 	if ((params->vi_bitrate.mode == V4L2_BITRATE_CBR) ||
-	    (params->vi_bitrate.mode == V4L2_BITRATE_VBR))
-		h->params.vi_bitrate.mode = params->vi_bitrate.mode;
+	    (params->vi_bitrate.mode == V4L2_BITRATE_VBR)) {
+		h->old_params.vi_bitrate.mode = params->vi_bitrate.mode;
+		h->params.vi_bitrate_mode = (params->vi_bitrate.mode == V4L2_BITRATE_VBR) ?
+		       V4L2_MPEG_VIDEO_BITRATE_MODE_VBR : V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+	}
 	if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
-		h->params.st_bitrate.target = params->st_bitrate.target;
+		h->old_params.st_bitrate.target = params->st_bitrate.target;
 	if (params->vi_bitrate.mode != V4L2_BITRATE_NONE)
-		h->params.vi_bitrate.target = params->vi_bitrate.target;
+		h->old_params.vi_bitrate.target = params->vi_bitrate.target;
 	if (params->vi_bitrate.mode == V4L2_BITRATE_VBR)
-		h->params.vi_bitrate.max = params->vi_bitrate.max;
+		h->old_params.vi_bitrate.max = params->vi_bitrate.max;
 	if (params->au_bitrate.mode != V4L2_BITRATE_NONE)
-		h->params.au_bitrate.target = params->au_bitrate.target;
+		h->old_params.au_bitrate.target = params->au_bitrate.target;
 
 	/* aspect ratio */
 	if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3 ||
-	    params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9)
-		h->params.vi_aspect_ratio = params->vi_aspect_ratio;
+	    params->vi_aspect_ratio == V4L2_MPEG_ASPECT_16_9) {
+		h->old_params.vi_aspect_ratio = params->vi_aspect_ratio;
+		if (params->vi_aspect_ratio == V4L2_MPEG_ASPECT_4_3)
+			h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;
+		else
+			h->params.vi_aspect = V4L2_MPEG_VIDEO_ASPECT_16x9;
+	}
 
 	/* range checks */
-	if (h->params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX)
-		h->params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX;
-	if (h->params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX)
-		h->params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX;
-	if (h->params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX)
-		h->params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX;
-	if (h->params.au_bitrate.target <= 256)
-		h->params.au_bitrate.target = 256;
+	if (h->old_params.st_bitrate.target > MPEG_TOTAL_TARGET_BITRATE_MAX)
+		h->old_params.st_bitrate.target = MPEG_TOTAL_TARGET_BITRATE_MAX;
+	if (h->old_params.vi_bitrate.target > MPEG_VIDEO_TARGET_BITRATE_MAX)
+		h->old_params.vi_bitrate.target = MPEG_VIDEO_TARGET_BITRATE_MAX;
+	if (h->old_params.vi_bitrate.max > MPEG_VIDEO_MAX_BITRATE_MAX)
+		h->old_params.vi_bitrate.max = MPEG_VIDEO_MAX_BITRATE_MAX;
+	h->params.vi_bitrate = params->vi_bitrate.target;
+	h->params.vi_bitrate_peak = params->vi_bitrate.max;
+	if (h->old_params.au_bitrate.target <= 256) {
+		h->old_params.au_bitrate.target = 256;
+		h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
+	}
+	else {
+		h->old_params.au_bitrate.target = 384;
+		h->params.au_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
+	}
+}
+
+static int handle_ctrl(struct saa6752hs_mpeg_params *params,
+		struct v4l2_ext_control *ctrl, unsigned int cmd)
+{
+	int old = 0, new;
+	int set = (cmd == VIDIOC_S_EXT_CTRLS);
+
+	new = ctrl->value;
+	switch (ctrl->id) {
+		case V4L2_CID_MPEG_STREAM_TYPE:
+			old = V4L2_MPEG_STREAM_TYPE_MPEG2_TS;
+			if (set && new != old)
+				return -ERANGE;
+			new = old;
+			break;
+		case V4L2_CID_MPEG_STREAM_PID_PMT:
+			old = params->ts_pid_pmt;
+			if (set && new > MPEG_PID_MAX)
+				return -ERANGE;
+			if (new > MPEG_PID_MAX)
+				new = MPEG_PID_MAX;
+			params->ts_pid_pmt = new;
+			break;
+		case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+			old = params->ts_pid_audio;
+			if (set && new > MPEG_PID_MAX)
+				return -ERANGE;
+			if (new > MPEG_PID_MAX)
+				new = MPEG_PID_MAX;
+			params->ts_pid_audio = new;
+			break;
+		case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+			old = params->ts_pid_video;
+			if (set && new > MPEG_PID_MAX)
+				return -ERANGE;
+			if (new > MPEG_PID_MAX)
+				new = MPEG_PID_MAX;
+			params->ts_pid_video = new;
+			break;
+		case V4L2_CID_MPEG_STREAM_PID_PCR:
+			old = params->ts_pid_pcr;
+			if (set && new > MPEG_PID_MAX)
+				return -ERANGE;
+			if (new > MPEG_PID_MAX)
+				new = MPEG_PID_MAX;
+			params->ts_pid_pcr = new;
+			break;
+		case V4L2_CID_MPEG_AUDIO_ENCODING:
+			old = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;
+			if (set && new != old)
+				return -ERANGE;
+			new = old;
+			break;
+		case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+			old = params->au_l2_bitrate;
+			if (set && new != V4L2_MPEG_AUDIO_L2_BITRATE_256K &&
+				   new != V4L2_MPEG_AUDIO_L2_BITRATE_384K)
+				return -ERANGE;
+			if (new <= V4L2_MPEG_AUDIO_L2_BITRATE_256K)
+				new = V4L2_MPEG_AUDIO_L2_BITRATE_256K;
+			else
+				new = V4L2_MPEG_AUDIO_L2_BITRATE_384K;
+			params->au_l2_bitrate = new;
+			break;
+		case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+			old = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;
+			if (set && new != old)
+				return -ERANGE;
+			new = old;
+			break;
+		case V4L2_CID_MPEG_VIDEO_ENCODING:
+			old = V4L2_MPEG_VIDEO_ENCODING_MPEG_2;
+			if (set && new != old)
+				return -ERANGE;
+			new = old;
+			break;
+		case V4L2_CID_MPEG_VIDEO_ASPECT:
+			old = params->vi_aspect;
+			if (set && new != V4L2_MPEG_VIDEO_ASPECT_16x9 &&
+				   new != V4L2_MPEG_VIDEO_ASPECT_4x3)
+				return -ERANGE;
+			if (new != V4L2_MPEG_VIDEO_ASPECT_16x9)
+				new = V4L2_MPEG_VIDEO_ASPECT_4x3;
+			params->vi_aspect = new;
+			break;
+		case V4L2_CID_MPEG_VIDEO_BITRATE:
+			old = params->vi_bitrate * 1000;
+			new = 1000 * (new / 1000);
+			if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+				return -ERANGE;
+			if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+				new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+			params->vi_bitrate = new / 1000;
+			break;
+		case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+			old = params->vi_bitrate_peak * 1000;
+			new = 1000 * (new / 1000);
+			if (set && new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+				return -ERANGE;
+			if (new > MPEG_VIDEO_TARGET_BITRATE_MAX * 1000)
+				new = MPEG_VIDEO_TARGET_BITRATE_MAX * 1000;
+			params->vi_bitrate_peak = new / 1000;
+			break;
+		case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+			old = params->vi_bitrate_mode;
+			params->vi_bitrate_mode = new;
+			break;
+		default:
+			return -EINVAL;
+	}
+	if (cmd == VIDIOC_G_EXT_CTRLS)
+		ctrl->value = old;
 	else
-		h->params.au_bitrate.target = 384;
+		ctrl->value = new;
+	return 0;
 }
 
 static int saa6752hs_init(struct i2c_client* client)
@@ -395,22 +578,22 @@
 	buf[2] = 0x0D;
 	i2c_master_send(client,buf,3);
 
-    	/* Set minimum Q-scale {4} */
+	/* Set minimum Q-scale {4} */
 	buf[0] = 0x82;
 	buf[1] = 0x04;
 	i2c_master_send(client,buf,2);
 
-    	/* Set maximum Q-scale {12} */
+	/* Set maximum Q-scale {12} */
 	buf[0] = 0x83;
 	buf[1] = 0x0C;
 	i2c_master_send(client,buf,2);
 
-    	/* Set Output Protocol */
+	/* Set Output Protocol */
 	buf[0] = 0xD0;
 	buf[1] = 0x81;
 	i2c_master_send(client,buf,2);
 
-    	/* Set video output stream format {TS} */
+	/* Set video output stream format {TS} */
 	buf[0] = 0xB0;
 	buf[1] = 0x05;
 	i2c_master_send(client,buf,2);
@@ -441,7 +624,7 @@
 	localPMT[sizeof(PMT) - 2] = (crc >> 8) & 0xFF;
 	localPMT[sizeof(PMT) - 1] = crc & 0xFF;
 
-    	/* Set Audio PID */
+	/* Set Audio PID */
 	buf[0] = 0xC1;
 	buf[1] = (h->params.ts_pid_audio >> 8) & 0xFF;
 	buf[2] = h->params.ts_pid_audio & 0xFF;
@@ -489,11 +672,11 @@
 	buf[3] = 0x82;
 	buf[4] = 0xB0;
 	buf[5] = buf2[0];
-	switch(h->params.vi_aspect_ratio) {
-	case V4L2_MPEG_ASPECT_16_9:
+	switch(h->params.vi_aspect) {
+	case V4L2_MPEG_VIDEO_ASPECT_16x9:
 		buf[6] = buf2[1] | 0x40;
 		break;
-	case V4L2_MPEG_ASPECT_4_3:
+	case V4L2_MPEG_VIDEO_ASPECT_4x3:
 	default:
 		buf[6] = buf2[1] & 0xBF;
 		break;
@@ -515,6 +698,7 @@
 		return -ENOMEM;
 	h->client = client_template;
 	h->params = param_defaults;
+	h->old_params = old_param_defaults;
 	h->client.adapter = adap;
 	h->client.addr = addr;
 
@@ -550,20 +734,45 @@
 saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	struct saa6752hs_state *h = i2c_get_clientdata(client);
-	struct v4l2_mpeg_compression *params = arg;
+	struct v4l2_ext_controls *ctrls = arg;
+	struct v4l2_mpeg_compression *old_params = arg;
+	struct saa6752hs_mpeg_params params;
 	int err = 0;
+	int i;
 
 	switch (cmd) {
 	case VIDIOC_S_MPEGCOMP:
-		if (NULL == params) {
+		if (NULL == old_params) {
 			/* apply settings and start encoder */
 			saa6752hs_init(client);
 			break;
 		}
-		saa6752hs_set_params(client, params);
+		saa6752hs_old_set_params(client, old_params);
 		/* fall through */
 	case VIDIOC_G_MPEGCOMP:
-		*params = h->params;
+		*old_params = h->old_params;
+		break;
+	case VIDIOC_S_EXT_CTRLS:
+		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+			return -EINVAL;
+		if (ctrls->count == 0) {
+			/* apply settings and start encoder */
+			saa6752hs_init(client);
+			break;
+		}
+		/* fall through */
+	case VIDIOC_TRY_EXT_CTRLS:
+	case VIDIOC_G_EXT_CTRLS:
+		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+			return -EINVAL;
+		params = h->params;
+		for (i = 0; i < ctrls->count; i++) {
+			if ((err = handle_ctrl(&params, ctrls->controls + i, cmd))) {
+				ctrls->error_idx = i;
+				return err;
+			}
+		}
+		h->params = params;
 		break;
 	case VIDIOC_G_FMT:
 	{
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index bb3e0ba..d77e6a8 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -818,7 +818,7 @@
 				break;
 		}
 
-	    	/* output xbar always main channel */
+		/* output xbar always main channel */
 		saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10);
 
 		if (left || right) { // We've got data, turn the input on
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 86eae35..927413a 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -2160,7 +2160,7 @@
 		.radio = {
 			  .name = name_radio,
 			  .amux = LINE2,
-    		},
+		},
 	},
 	[SAA7134_BOARD_GOTVIEW_7135] = {
 		/* Mike Baikov <mike@baikov.com> */
@@ -2842,6 +2842,55 @@
 			.gpio = 0x000000,	/* GPIO21=Low for FM radio antenna */
 		},
 	},
+	[SAA7134_BOARD_FLYVIDEO3000_NTSC] = {
+		/* "Zac Bowling" <zac@zacbowling.com> */
+		.name           = "LifeView FlyVIDEO3000 (NTSC)",
+		.audio_clock    = 0x00200000,
+		.tuner_type     = TUNER_PHILIPS_NTSC,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+
+		.gpiomask       = 0xe000,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.gpio = 0x8000,
+			.tv   = 1,
+		},{
+			.name = name_tv_mono,
+			.vmux = 1,
+			.amux = LINE2,
+			.gpio = 0x0000,
+			.tv   = 1,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_comp2,
+			.vmux = 3,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		},{
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE2,
+			.gpio = 0x4000,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE2,
+			.gpio = 0x2000,
+		},
+			.mute = {
+			.name = name_mute,
+			.amux = TV,
+			.gpio = 0x8000,
+		},
+	},
 };
 
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -2901,6 +2950,12 @@
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x5169,
+		.subdevice    = 0x0138,
+		.driver_data  = SAA7134_BOARD_FLYVIDEO3000_NTSC,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x5168,
 		.subdevice    = 0x0138,
 		.driver_data  = SAA7134_BOARD_FLYVIDEO3000,
@@ -3459,6 +3514,7 @@
 	switch (dev->board) {
 	case SAA7134_BOARD_FLYVIDEO2000:
 	case SAA7134_BOARD_FLYVIDEO3000:
+	case SAA7134_BOARD_FLYVIDEO3000_NTSC:
 		dev->has_remote = SAA7134_REMOTE_GPIO;
 		board_flyvideo(dev);
 		break;
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index 222a36c..279828b 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -132,9 +132,8 @@
 	return 0;
 }
 
-static int mt352_pinnacle_pll_set(struct dvb_frontend* fe,
-				  struct dvb_frontend_parameters* params,
-				  u8* pllbuf)
+static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe,
+					   struct dvb_frontend_parameters* params)
 {
 	u8 off[] = { 0x00, 0xf1};
 	u8 on[]  = { 0x00, 0x71};
@@ -147,30 +146,31 @@
 	f.tuner     = 0;
 	f.type      = V4L2_TUNER_DIGITAL_TV;
 	f.frequency = params->frequency / 1000 * 16 / 1000;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
 	saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,&f);
 	msg.buf = on;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
 
 	pinnacle_antenna_pwr(dev, antenna_pwr);
 
 	/* mt352 setup */
-	mt352_pinnacle_init(fe);
-	pllbuf[0] = 0xc2;
-	pllbuf[1] = 0x00;
-	pllbuf[2] = 0x00;
-	pllbuf[3] = 0x80;
-	pllbuf[4] = 0x00;
-	return 0;
+	return mt352_pinnacle_init(fe);
 }
 
-static int mt352_aver777_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf)
+static int mt352_aver777_tuner_calc_regs(struct dvb_frontend *fe, struct dvb_frontend_parameters *params, u8* pllbuf, int buf_len)
 {
-	pllbuf[0] = 0xc2;
+	if (buf_len < 5)
+		return -EINVAL;
+
+	pllbuf[0] = 0x61;
 	dvb_pll_configure(&dvb_pll_philips_td1316, pllbuf+1,
 			  params->frequency,
 			  params->u.ofdm.bandwidth);
-	return 0;
+	return 5;
 }
 
 static struct mt352_config pinnacle_300i = {
@@ -179,13 +179,11 @@
 	.if2           = 36150,
 	.no_tuner      = 1,
 	.demod_init    = mt352_pinnacle_init,
-	.pll_set       = mt352_pinnacle_pll_set,
 };
 
 static struct mt352_config avermedia_777 = {
 	.demod_address = 0xf,
 	.demod_init    = mt352_aver777_init,
-	.pll_set       = mt352_aver777_pll_set,
 };
 #endif
 
@@ -268,6 +266,8 @@
 	tuner_buf[2] = 0xca;
 	tuner_buf[3] = (cp << 5) | (filter << 3) | band;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 	msleep(1);
@@ -281,6 +281,8 @@
 	struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tu1216_init,.len = sizeof(tu1216_init) };
 
 	/* setup PLL configuration */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 	msleep(1);
@@ -290,12 +292,12 @@
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tu1216_pll_60_init(struct dvb_frontend *fe)
+static int philips_tu1216_tuner_60_init(struct dvb_frontend *fe)
 {
 	return philips_tda6651_pll_init(0x60, fe);
 }
 
-static int philips_tu1216_pll_60_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_60_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	return philips_tda6651_pll_set(0x60, fe, params);
 }
@@ -315,20 +317,17 @@
 	.xtal_freq     = TDA10046_XTAL_4M,
 	.agc_config    = TDA10046_AGC_DEFAULT,
 	.if_freq       = TDA10046_FREQ_3617,
-	.pll_init      = philips_tu1216_pll_60_init,
-	.pll_set       = philips_tu1216_pll_60_set,
-	.pll_sleep     = NULL,
 	.request_firmware = philips_tu1216_request_firmware,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tu1216_pll_61_init(struct dvb_frontend *fe)
+static int philips_tu1216_tuner_61_init(struct dvb_frontend *fe)
 {
 	return philips_tda6651_pll_init(0x61, fe);
 }
 
-static int philips_tu1216_pll_61_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tu1216_tuner_61_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	return philips_tda6651_pll_set(0x61, fe, params);
 }
@@ -341,21 +340,20 @@
 	.xtal_freq     = TDA10046_XTAL_4M,
 	.agc_config    = TDA10046_AGC_DEFAULT,
 	.if_freq       = TDA10046_FREQ_3617,
-	.pll_init      = philips_tu1216_pll_61_init,
-	.pll_set       = philips_tu1216_pll_61_set,
-	.pll_sleep     = NULL,
 	.request_firmware = philips_tu1216_request_firmware,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int philips_europa_pll_init(struct dvb_frontend *fe)
+static int philips_europa_tuner_init(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	static u8 msg[] = { 0x0b, 0xf5, 0x86, 0xab };
 	struct i2c_msg init_msg = {.addr = 0x61,.flags = 0,.buf = msg,.len = sizeof(msg) };
 
 	/* setup PLL configuration */
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
 		return -EIO;
 	msleep(1);
@@ -365,18 +363,20 @@
 	init_msg.len  = 0x02;
 	msg[0] = 0x00;
 	msg[1] = 0x40;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &init_msg, 1) != 1)
 		return -EIO;
 
 	return 0;
 }
 
-static int philips_td1316_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	return philips_tda6651_pll_set(0x61, fe, params);
 }
 
-static void philips_europa_analog(struct dvb_frontend *fe)
+static int philips_europa_tuner_sleep(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	/* this message actually turns the tuner back to analog mode */
@@ -391,7 +391,20 @@
 	analog_msg.len  = 0x02;
 	msg[0] = 0x00;
 	msg[1] = 0x14;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &analog_msg, 1);
+	return 0;
+}
+
+static int philips_europa_demod_sleep(struct dvb_frontend *fe)
+{
+	struct saa7134_dev *dev = fe->dvb->priv;
+
+	if (dev->original_demod_sleep)
+		dev->original_demod_sleep(fe);
+	fe->ops.i2c_gate_ctrl(fe, 1);
+	return 0;
 }
 
 static struct tda1004x_config philips_europa_config = {
@@ -402,21 +415,20 @@
 	.xtal_freq     = TDA10046_XTAL_4M,
 	.agc_config    = TDA10046_AGC_IFO_AUTO_POS,
 	.if_freq       = TDA10046_FREQ_052,
-	.pll_init      = philips_europa_pll_init,
-	.pll_set       = philips_td1316_pll_set,
-	.pll_sleep     = philips_europa_analog,
 	.request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int philips_fmd1216_pll_init(struct dvb_frontend *fe)
+static int philips_fmd1216_tuner_init(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	/* this message is to set up ATC and ALC */
 	static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0xa0 };
 	struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 	msleep(1);
@@ -424,22 +436,27 @@
 	return 0;
 }
 
-static void philips_fmd1216_analog(struct dvb_frontend *fe)
+static int philips_fmd1216_tuner_sleep(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	/* this message actually turns the tuner back to analog mode */
 	static u8 fmd1216_init[] = { 0x0b, 0xdc, 0x9c, 0x60 };
 	struct i2c_msg tuner_msg = {.addr = 0x61,.flags = 0,.buf = fmd1216_init,.len = sizeof(fmd1216_init) };
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
 	msleep(1);
 	fmd1216_init[2] = 0x86;
 	fmd1216_init[3] = 0x54;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
 	msleep(1);
+	return 0;
 }
 
-static int philips_fmd1216_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_fmd1216_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	u8 tuner_buf[4];
@@ -516,6 +533,8 @@
 	tuner_buf[2] = 0x80 | (cp << 6) | (mode  << 3) | 4;
 	tuner_buf[3] = 0x40 | band;
 
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 	return 0;
@@ -528,9 +547,6 @@
 	.xtal_freq     = TDA10046_XTAL_16M,
 	.agc_config    = TDA10046_AGC_IFO_AUTO_NEG,
 	.if_freq       = TDA10046_FREQ_3613,
-	.pll_init      = philips_fmd1216_pll_init,
-	.pll_set       = philips_fmd1216_pll_set,
-	.pll_sleep	   = philips_fmd1216_analog,
 	.request_firmware = NULL,
 };
 
@@ -578,12 +594,12 @@
 	{ .lomax =         0, .spd = 0, .bs = 0, .bp = 0, .cp = 0, .gc3 = 0, .div1p5 = 0}
 };
 
-static int philips_tda827x_pll_init(struct dvb_frontend *fe)
+static int philips_tda827x_tuner_init(struct dvb_frontend *fe)
 {
 	return 0;
 }
 
-static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tda827x_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	u8 tuner_buf[14];
@@ -630,6 +646,8 @@
 	tuner_buf[13] = 0x40;
 
 	tuner_msg.len = 14;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &tuner_msg, 1) != 1)
 		return -EIO;
 
@@ -638,18 +656,23 @@
 	tuner_buf[0] = 0x30;
 	tuner_buf[1] = 0x50 + tda827x_dvbt[i].cp;
 	tuner_msg.len = 2;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
 
 	return 0;
 }
 
-static void philips_tda827x_pll_sleep(struct dvb_frontend *fe)
+static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	static u8 tda827x_sleep[] = { 0x30, 0xd0};
 	struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep,
 				    .len = sizeof(tda827x_sleep) };
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
+	return 0;
 }
 
 static struct tda1004x_config tda827x_lifeview_config = {
@@ -659,9 +682,6 @@
 	.xtal_freq     = TDA10046_XTAL_16M,
 	.agc_config    = TDA10046_AGC_TDA827X,
 	.if_freq       = TDA10046_FREQ_045,
-	.pll_init      = philips_tda827x_pll_init,
-	.pll_set       = philips_tda827x_pll_set,
-	.pll_sleep	   = philips_tda827x_pll_sleep,
 	.request_firmware = NULL,
 };
 
@@ -753,6 +773,8 @@
 	tuner_buf[12] = 0x00;
 	tuner_buf[13] = 0x39;  // lpsel
 	msg.len = 14;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	if (i2c_transfer(&dev->i2c_adap, &msg, 1) != 1)
 		return -EIO;
 
@@ -760,10 +782,14 @@
 	msg.len = 2;
 	reg2[0] = 0x60;
 	reg2[1] = 0x3c;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
 
 	reg2[0] = 0xa0;
 	reg2[1] = 0x40;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
 
 	msleep(2);
@@ -771,36 +797,43 @@
 	reg2[0] = 0x30;
 	reg2[1] = 0x10 + tda827xa_dvbt[i].scr;
 	msg.len = 2;
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
 
 	msleep(550);
 	reg2[0] = 0x50;
 	reg2[1] = 0x4f + (tda827xa_dvbt[i].gc3 << 4);
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
 
 	return 0;
 
 }
 
-static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe)
+static int philips_tda827xa_tuner_sleep(u8 addr, struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	static u8 tda827xa_sleep[] = { 0x30, 0x90};
 	struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep,
 				    .len = sizeof(tda827xa_sleep) };
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
 	i2c_transfer(&dev->i2c_adap, &tuner_msg, 1);
-
+	return 0;
 }
 
 /* ------------------------------------------------------------------ */
 
-static int philips_tiger_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int philips_tiger_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	int ret;
 	struct saa7134_dev *dev = fe->dvb->priv;
 	static u8 tda8290_close[] = { 0x21, 0xc0};
 	static u8 tda8290_open[]  = { 0x21, 0x80};
 	struct i2c_msg tda8290_msg = {.addr = 0x4b,.flags = 0, .len = 2};
+
 	/* close tda8290 i2c bridge */
 	tda8290_msg.buf = tda8290_close;
 	ret = i2c_transfer(&dev->i2c_adap, &tda8290_msg, 1);
@@ -816,7 +849,7 @@
 	return ret;
 }
 
-static int philips_tiger_dvb_mode(struct dvb_frontend *fe)
+static int philips_tiger_tuner_init(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	static u8 data[] = { 0x3c, 0x33, 0x6a};
@@ -827,14 +860,15 @@
 	return 0;
 }
 
-static void philips_tiger_analog_mode(struct dvb_frontend *fe)
+static int philips_tiger_tuner_sleep(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	static u8 data[] = { 0x3c, 0x33, 0x68};
 	struct i2c_msg msg = {.addr=0x08, .flags=0, .buf=data, .len = sizeof(data)};
 
 	i2c_transfer(&dev->i2c_adap, &msg, 1);
-	philips_tda827xa_pll_sleep( 0x61, fe);
+	philips_tda827xa_tuner_sleep( 0x61, fe);
+	return 0;
 }
 
 static struct tda1004x_config philips_tiger_config = {
@@ -844,15 +878,12 @@
 	.xtal_freq     = TDA10046_XTAL_16M,
 	.agc_config    = TDA10046_AGC_TDA827X,
 	.if_freq       = TDA10046_FREQ_045,
-	.pll_init      = philips_tiger_dvb_mode,
-	.pll_set       = philips_tiger_pll_set,
-	.pll_sleep     = philips_tiger_analog_mode,
 	.request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int lifeview_trio_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int lifeview_trio_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	int ret;
 
@@ -860,16 +891,12 @@
 	return ret;
 }
 
-static int lifeview_trio_dvb_mode(struct dvb_frontend *fe)
+static int lifeview_trio_tuner_sleep(struct dvb_frontend *fe)
 {
+	philips_tda827xa_tuner_sleep(0x60, fe);
 	return 0;
 }
 
-static void lifeview_trio_analog_mode(struct dvb_frontend *fe)
-{
-	philips_tda827xa_pll_sleep(0x60, fe);
-}
-
 static struct tda1004x_config lifeview_trio_config = {
 	.demod_address = 0x09,
 	.invert        = 1,
@@ -877,15 +904,12 @@
 	.xtal_freq     = TDA10046_XTAL_16M,
 	.agc_config    = TDA10046_AGC_TDA827X_GPL,
 	.if_freq       = TDA10046_FREQ_045,
-	.pll_init      = lifeview_trio_dvb_mode,
-	.pll_set       = lifeview_trio_pll_set,
-	.pll_sleep     = lifeview_trio_analog_mode,
 	.request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int ads_duo_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int ads_duo_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	int ret;
 
@@ -893,7 +917,7 @@
 	return ret;
 }
 
-static int ads_duo_dvb_mode(struct dvb_frontend *fe)
+static int ads_duo_tuner_init(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	/* route TDA8275a AGC input to the channel decoder */
@@ -901,12 +925,13 @@
 	return 0;
 }
 
-static void ads_duo_analog_mode(struct dvb_frontend *fe)
+static int ads_duo_tuner_sleep(struct dvb_frontend *fe)
 {
 	struct saa7134_dev *dev = fe->dvb->priv;
 	/* route TDA8275a AGC input to the analog IF chip*/
 	saa_writeb(SAA7134_GPIO_GPSTATUS2, 0x20);
-	philips_tda827xa_pll_sleep( 0x61, fe);
+	philips_tda827xa_tuner_sleep( 0x61, fe);
+	return 0;
 }
 
 static struct tda1004x_config ads_tech_duo_config = {
@@ -916,31 +941,24 @@
 	.xtal_freq     = TDA10046_XTAL_16M,
 	.agc_config    = TDA10046_AGC_TDA827X_GPL,
 	.if_freq       = TDA10046_FREQ_045,
-	.pll_init      = ads_duo_dvb_mode,
-	.pll_set       = ads_duo_pll_set,
-	.pll_sleep     = ads_duo_analog_mode,
 	.request_firmware = NULL,
 };
 
 /* ------------------------------------------------------------------ */
 
-static int tevion_dvb220rf_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
+static int tevion_dvb220rf_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params)
 {
 	int ret;
 	ret = philips_tda827xa_pll_set(0x60, fe, params);
 	return ret;
 }
 
-static int tevion_dvb220rf_pll_init(struct dvb_frontend *fe)
+static int tevion_dvb220rf_tuner_sleep(struct dvb_frontend *fe)
 {
+	philips_tda827xa_tuner_sleep( 0x61, fe);
 	return 0;
 }
 
-static void tevion_dvb220rf_pll_sleep(struct dvb_frontend *fe)
-{
-	philips_tda827xa_pll_sleep( 0x61, fe);
-}
-
 static struct tda1004x_config tevion_dvbt220rf_config = {
 	.demod_address = 0x08,
 	.invert        = 1,
@@ -948,9 +966,6 @@
 	.xtal_freq     = TDA10046_XTAL_16M,
 	.agc_config    = TDA10046_AGC_TDA827X,
 	.if_freq       = TDA10046_FREQ_045,
-	.pll_init      = tevion_dvb220rf_pll_init,
-	.pll_set       = tevion_dvb220rf_pll_set,
-	.pll_sleep     = tevion_dvb220rf_pll_sleep,
 	.request_firmware = NULL,
 };
 
@@ -961,8 +976,6 @@
 #ifdef HAVE_NXT200X
 static struct nxt200x_config avertvhda180 = {
 	.demod_address    = 0x0a,
-	.pll_address      = 0x61,
-	.pll_desc         = &dvb_pll_tdhu2,
 };
 
 static int nxt200x_set_pll_input(u8 *buf, int input)
@@ -976,8 +989,6 @@
 
 static struct nxt200x_config kworldatsc110 = {
 	.demod_address    = 0x0a,
-	.pll_address      = 0x61,
-	.pll_desc         = &dvb_pll_tuv1236d,
 	.set_pll_input    = nxt200x_set_pll_input,
 };
 #endif
@@ -1003,78 +1014,158 @@
 		printk("%s: pinnacle 300i dvb setup\n",dev->name);
 		dev->dvb.frontend = mt352_attach(&pinnacle_300i,
 						 &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.set_params = mt352_pinnacle_tuner_set_params;
+		}
 		break;
 
 	case SAA7134_BOARD_AVERMEDIA_777:
 		printk("%s: avertv 777 dvb setup\n",dev->name);
 		dev->dvb.frontend = mt352_attach(&avermedia_777,
 						 &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.calc_regs = mt352_aver777_tuner_calc_regs;
+		}
 		break;
 #endif
 #ifdef HAVE_TDA1004X
 	case SAA7134_BOARD_MD7134:
 		dev->dvb.frontend = tda10046_attach(&medion_cardbus,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_fmd1216_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_fmd1216_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_fmd1216_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_PHILIPS_TOUGH:
 		dev->dvb.frontend = tda10046_attach(&philips_tu1216_60_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_60_init;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_60_set_params;
+		}
 		break;
 	case SAA7134_BOARD_FLYDVBTDUO:
 		dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS:
 		dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_PHILIPS_EUROPA:
 		dev->dvb.frontend = tda10046_attach(&philips_europa_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->original_demod_sleep = dev->dvb.frontend->ops.sleep;
+			dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep;
+			dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_VIDEOMATE_DVBT_300:
 		dev->dvb.frontend = tda10046_attach(&philips_europa_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_VIDEOMATE_DVBT_200:
 		dev->dvb.frontend = tda10046_attach(&philips_tu1216_61_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_tu1216_tuner_61_init;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tu1216_tuner_61_set_params;
+		}
 		break;
 	case SAA7134_BOARD_PHILIPS_TIGER:
 		dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_ASUSTeK_P7131_DUAL:
 		dev->dvb.frontend = tda10046_attach(&philips_tiger_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_tiger_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_tiger_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tiger_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_FLYDVBT_LR301:
 		dev->dvb.frontend = tda10046_attach(&tda827x_lifeview_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = philips_tda827x_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = philips_tda827x_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = philips_tda827x_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_FLYDVB_TRIO:
 		dev->dvb.frontend = tda10046_attach(&lifeview_trio_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.sleep = lifeview_trio_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = lifeview_trio_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_ADS_DUO_CARDBUS_PTV331:
 		dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_TEVION_DVBT_220RF:
 		dev->dvb.frontend = tda10046_attach(&tevion_dvbt220rf_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.sleep = tevion_dvb220rf_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = tevion_dvb220rf_tuner_set_params;
+		}
 		break;
 	case SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS:
 		dev->dvb.frontend = tda10046_attach(&ads_tech_duo_config,
 						    &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dev->dvb.frontend->ops.tuner_ops.init = ads_duo_tuner_init;
+			dev->dvb.frontend->ops.tuner_ops.sleep = ads_duo_tuner_sleep;
+			dev->dvb.frontend->ops.tuner_ops.set_params = ads_duo_tuner_set_params;
+		}
 		break;
 #endif
 #ifdef HAVE_NXT200X
 	case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180:
 		dev->dvb.frontend = nxt200x_attach(&avertvhda180, &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tdhu2);
+		}
 		break;
 	case SAA7134_BOARD_KWORLD_ATSC110:
 		dev->dvb.frontend = nxt200x_attach(&kworldatsc110, &dev->i2c_adap);
+		if (dev->dvb.frontend) {
+			dvb_pll_attach(dev->dvb.frontend, 0x61, &dev->i2c_adap, &dvb_pll_tuv1236d);
+		}
 		break;
 #endif
 	default:
@@ -1088,7 +1179,7 @@
 	}
 
 	/* register everything else */
-	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
+	return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev);
 }
 
 static int dvb_fini(struct saa7134_dev *dev)
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index 1d972ed..65d0440 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -64,8 +64,10 @@
 
 static int ts_init_encoder(struct saa7134_dev* dev)
 {
+	struct v4l2_ext_controls ctrls = { V4L2_CTRL_CLASS_MPEG, 0 };
+
 	ts_reset_encoder(dev);
-	saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL);
+	saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, &ctrls);
 	dev->empress_started = 1;
 	return 0;
 }
@@ -162,6 +164,7 @@
 		       unsigned int cmd, void *arg)
 {
 	struct saa7134_dev *dev = file->private_data;
+	struct v4l2_ext_controls *ctrls = arg;
 
 	if (debug > 1)
 		v4l_print_ioctl(dev->name,cmd);
@@ -278,12 +281,31 @@
 		return saa7134_common_ioctl(dev, cmd, arg);
 
 	case VIDIOC_S_MPEGCOMP:
+		printk(KERN_WARNING "VIDIOC_S_MPEGCOMP is obsolete. "
+				    "Replace with VIDIOC_S_EXT_CTRLS!");
 		saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, arg);
 		ts_init_encoder(dev);
 		return 0;
 	case VIDIOC_G_MPEGCOMP:
+		printk(KERN_WARNING "VIDIOC_G_MPEGCOMP is obsolete. "
+				    "Replace with VIDIOC_G_EXT_CTRLS!");
 		saa7134_i2c_call_clients(dev, VIDIOC_G_MPEGCOMP, arg);
 		return 0;
+	case VIDIOC_S_EXT_CTRLS:
+		/* count == 0 is abused in saa6752hs.c, so that special
+		   case is handled here explicitly. */
+		if (ctrls->count == 0)
+			return 0;
+		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+			return -EINVAL;
+		saa7134_i2c_call_clients(dev, VIDIOC_S_EXT_CTRLS, arg);
+		ts_init_encoder(dev);
+		return 0;
+	case VIDIOC_G_EXT_CTRLS:
+		if (ctrls->ctrl_class != V4L2_CTRL_CLASS_MPEG)
+			return -EINVAL;
+		saa7134_i2c_call_clients(dev, VIDIOC_G_EXT_CTRLS, arg);
+		return 0;
 
 	default:
 		return -ENOIOCTLCMD;
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 1426e4c..7c59549 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -37,6 +37,10 @@
 module_param(ir_debug, int, 0644);
 MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]");
 
+static int pinnacle_remote = 0;
+module_param(pinnacle_remote, int, 0644);    /* Choose Pinnacle PCTV remote */
+MODULE_PARM_DESC(pinnacle_remote, "Specify Pinnacle PCTV remote: 0=coloured, 1=grey (defaults to 0)");
+
 #define dprintk(fmt, arg...)	if (ir_debug) \
 	printk(KERN_DEBUG "%s/ir: " fmt, dev->name , ## arg)
 #define i2cdprintk(fmt, arg...)    if (ir_debug) \
@@ -316,8 +320,13 @@
 	switch (dev->board) {
 	case SAA7134_BOARD_PINNACLE_PCTV_110i:
 		snprintf(ir->c.name, sizeof(ir->c.name), "Pinnacle PCTV");
-		ir->get_key   = get_key_pinnacle;
-		ir->ir_codes  = ir_codes_pinnacle;
+		if (pinnacle_remote == 0) {
+			ir->get_key   = get_key_pinnacle_color;
+			ir->ir_codes = ir_codes_pinnacle_color;
+		} else {
+			ir->get_key   = get_key_pinnacle_grey;
+			ir->ir_codes = ir_codes_pinnacle_grey;
+		}
 		break;
 	case SAA7134_BOARD_UPMOST_PURPLE_TV:
 		snprintf(ir->c.name, sizeof(ir->c.name), "Purple TV");
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index 353af3a..d5ee99c 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -33,6 +33,7 @@
 
 #include <asm/io.h>
 
+#include <media/v4l2-common.h>
 #include <media/tuner.h>
 #include <media/ir-common.h>
 #include <media/ir-kbd-i2c.h>
@@ -221,6 +222,7 @@
 #define SAA7134_BOARD_AVERMEDIA_A169_B1 92
 #define SAA7134_BOARD_MD7134_BRIDGE_2     93
 #define SAA7134_BOARD_FLYDVBT_HYBRID_CARDBUS 94
+#define SAA7134_BOARD_FLYVIDEO3000_NTSC 95
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -531,6 +533,7 @@
 
 	/* SAA7134_MPEG_DVB only */
 	struct videobuf_dvb        dvb;
+	int (*original_demod_sleep)(struct dvb_frontend* fe);
 };
 
 /* ----------------------------------------------------------- */
diff --git a/drivers/media/video/se401.h b/drivers/media/video/se401.h
index a7a216b..c0891b3 100644
--- a/drivers/media/video/se401.h
+++ b/drivers/media/video/se401.h
@@ -4,6 +4,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/smp_lock.h>
 #include <linux/mutex.h>
 
diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c
index ea4394d..48d138a 100644
--- a/drivers/media/video/sn9c102/sn9c102_core.c
+++ b/drivers/media/video/sn9c102/sn9c102_core.c
@@ -2608,11 +2608,9 @@
 	case VIDIOC_G_CTRL:
 		return sn9c102_vidioc_g_ctrl(cam, arg);
 
-	case VIDIOC_S_CTRL_OLD:
 	case VIDIOC_S_CTRL:
 		return sn9c102_vidioc_s_ctrl(cam, arg);
 
-	case VIDIOC_CROPCAP_OLD:
 	case VIDIOC_CROPCAP:
 		return sn9c102_vidioc_cropcap(cam, arg);
 
@@ -2659,7 +2657,6 @@
 	case VIDIOC_G_PARM:
 		return sn9c102_vidioc_g_parm(cam, arg);
 
-	case VIDIOC_S_PARM_OLD:
 	case VIDIOC_S_PARM:
 		return sn9c102_vidioc_s_parm(cam, arg);
 
diff --git a/drivers/media/video/stradis.c b/drivers/media/video/stradis.c
index 07476c7..c18b31d 100644
--- a/drivers/media/video/stradis.c
+++ b/drivers/media/video/stradis.c
@@ -42,6 +42,7 @@
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include "saa7146.h"
 #include "saa7146reg.h"
@@ -2189,7 +2190,7 @@
 	.remove = __devexit_p(stradis_remove)
 };
 
-int __init stradis_init(void)
+static int __init stradis_init(void)
 {
 	int retval;
 
@@ -2202,7 +2203,7 @@
 	return retval;
 }
 
-void __exit stradis_exit(void)
+static void __exit stradis_exit(void)
 {
 	pci_unregister_driver(&stradis_driver);
 	printk(KERN_INFO "stradis: module cleanup complete\n");
diff --git a/drivers/media/video/stv680.c b/drivers/media/video/stv680.c
index b38bda8..351b182 100644
--- a/drivers/media/video/stv680.c
+++ b/drivers/media/video/stv680.c
@@ -66,6 +66,7 @@
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 103ccb9..827633b 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -26,6 +26,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/init.h>
@@ -163,7 +164,7 @@
 	struct tda9875 *t = i2c_get_clientdata(client);
 	dprintk("In tda9875_init\n");
 	tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/
-    	tda9875_write(client, TDA9875_MSR, 0x03 );    /* Monitor 0b00000XXX*/
+	tda9875_write(client, TDA9875_MSR, 0x03 );    /* Monitor 0b00000XXX*/
 	tda9875_write(client, TDA9875_C1MSB, 0x00 );  /*Car1(FM) MSB XMHz*/
 	tda9875_write(client, TDA9875_C1MIB, 0x00 );  /*Car1(FM) MIB XMHz*/
 	tda9875_write(client, TDA9875_C1LSB, 0x00 );  /*Car1(FM) LSB XMHz*/
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index 0d54f6c..2fadabf 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -18,49 +18,21 @@
    TDA9886 (PAL, SECAM, NTSC)
    TDA9887 (PAL, SECAM, NTSC, FM Radio)
 
-   found on:
-   - Pinnacle PCTV (Jul.2002 Version with MT2032, bttv)
-      TDA9887 (world), TDA9885 (USA)
-      Note: OP2 of tda988x must be set to 1, else MT2032 is disabled!
-   - KNC One TV-Station RDS (saa7134)
-   - Hauppauge PVR-150/500 (possibly more)
+   Used as part of several tuners
 */
 
+#define tda9887_info(fmt, arg...) do {\
+	printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \
+			i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
+#define tda9887_dbg(fmt, arg...) do {\
+	if (tuner_debug) \
+		printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.name, \
+			i2c_adapter_id(t->i2c.adapter), t->i2c.addr , ##arg); } while (0)
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = {
-	0x84 >>1,
-	0x86 >>1,
-	0x96 >>1,
-	I2C_CLIENT_END,
-};
-I2C_CLIENT_INSMOD;
-
-/* insmod options */
-static unsigned int debug = 0;
-module_param(debug, int, 0644);
-MODULE_LICENSE("GPL");
 
 /* ---------------------------------------------------------------------- */
 
 #define UNSET       (-1U)
-#define tda9887_info(fmt, arg...) do {\
-	printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \
-			i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0)
-#define tda9887_dbg(fmt, arg...) do {\
-	if (debug) \
-		printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \
-			i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0)
-
-struct tda9887 {
-	struct i2c_client  client;
-	v4l2_std_id        std;
-	enum tuner_mode    mode;
-	unsigned int       config;
-	unsigned int       using_v4l2;
-	unsigned int 	   radio_mode;
-	unsigned char 	   data[4];
-};
 
 struct tvnorm {
 	v4l2_std_id       std;
@@ -70,9 +42,6 @@
 	unsigned char     e;
 };
 
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
 /* ---------------------------------------------------------------------- */
 
 //
@@ -115,8 +84,7 @@
 #define cAudioGain6             0x80    // bit c7
 
 #define cTopMask                0x1f    // bit c0:4
-#define cTopPalSecamDefault	0x14 	// bit c0:4
-#define cTopNtscRadioDefault 	0x10 	// bit c0:4
+#define cTopDefault		0x10 	// bit c0:4
 
 //// third reg (e)
 #define cAudioIF_4_5             0x00    // bit e0:1
@@ -154,7 +122,7 @@
 			   cQSS           ),
 		.c     = ( cDeemphasisON  |
 			   cDeemphasis50  |
-			   cTopPalSecamDefault),
+			   cTopDefault),
 		.e     = ( cGating_36     |
 			   cAudioIF_5_5   |
 			   cVideoIF_38_90 ),
@@ -165,7 +133,7 @@
 			   cQSS           ),
 		.c     = ( cDeemphasisON  |
 			   cDeemphasis50  |
-			   cTopPalSecamDefault),
+			   cTopDefault),
 		.e     = ( cGating_36     |
 			   cAudioIF_6_0   |
 			   cVideoIF_38_90 ),
@@ -176,7 +144,7 @@
 			   cQSS           ),
 		.c     = ( cDeemphasisON  |
 			   cDeemphasis50  |
-			   cTopPalSecamDefault),
+			   cTopDefault),
 		.e     = ( cGating_36     |
 			   cAudioIF_6_5   |
 			   cVideoIF_38_90 ),
@@ -187,7 +155,7 @@
 			   cQSS           ),
 		.c     = ( cDeemphasisON  |
 			   cDeemphasis75  |
-			   cTopNtscRadioDefault),
+			   cTopDefault),
 		.e     = ( cGating_36     |
 			   cAudioIF_4_5   |
 			   cVideoIF_45_75 ),
@@ -196,7 +164,7 @@
 		.name  = "SECAM-BGH",
 		.b     = ( cPositiveAmTV  |
 			   cQSS           ),
-		.c     = ( cTopPalSecamDefault),
+		.c     = ( cTopDefault),
 		.e     = ( cGating_36	  |
 			   cAudioIF_5_5   |
 			   cVideoIF_38_90 ),
@@ -205,7 +173,7 @@
 		.name  = "SECAM-L",
 		.b     = ( cPositiveAmTV  |
 			   cQSS           ),
-		.c     = ( cTopPalSecamDefault),
+		.c     = ( cTopDefault),
 		.e     = ( cGating_36	  |
 			   cAudioIF_6_5   |
 			   cVideoIF_38_90 ),
@@ -215,7 +183,7 @@
 		.b     = ( cOutputPort2Inactive |
 			   cPositiveAmTV  |
 			   cQSS           ),
-		.c     = ( cTopPalSecamDefault),
+		.c     = ( cTopDefault),
 		.e     = ( cGating_36	  |
 			   cAudioIF_6_5   |
 			   cVideoIF_33_90 ),
@@ -226,7 +194,7 @@
 			   cQSS           ),
 		.c     = ( cDeemphasisON  |
 			   cDeemphasis50  |
-			   cTopPalSecamDefault),
+			   cTopDefault),
 		.e     = ( cGating_36     |
 			   cAudioIF_6_5   |
 			   cVideoIF_38_90 ),
@@ -237,7 +205,7 @@
 			   cQSS           ),
 		.c     = ( cDeemphasisON  |
 			   cDeemphasis75  |
-			   cTopNtscRadioDefault),
+			   cTopDefault),
 		.e     = ( cGating_36     |
 			   cAudioIF_4_5   |
 			   cVideoIF_45_75 ),
@@ -248,7 +216,7 @@
 			   cQSS           ),
 		.c     = ( cDeemphasisON  |
 			   cDeemphasis50  |
-			   cTopNtscRadioDefault),
+			   cTopDefault),
 		.e     = ( cGating_36     |
 			   cAudioIF_4_5   |
 			   cVideoIF_58_75 ),
@@ -261,7 +229,7 @@
 		  cQSS           ),
 	.c    = ( cDeemphasisOFF |
 		  cAudioGain6    |
-		  cTopNtscRadioDefault),
+		  cTopDefault),
 	.e    = ( cTunerGainLow  |
 		  cAudioIF_5_5   |
 		  cRadioIF_38_90 ),
@@ -273,7 +241,7 @@
 		  cQSS           ),
 	.c    = ( cDeemphasisON  |
 		  cDeemphasis75  |
-		  cTopNtscRadioDefault),
+		  cTopDefault),
 	.e    = ( cTunerGainLow  |
 		  cAudioIF_5_5   |
 		  cRadioIF_38_90 ),
@@ -281,7 +249,7 @@
 
 /* ---------------------------------------------------------------------- */
 
-static void dump_read_message(struct tda9887 *t, unsigned char *buf)
+static void dump_read_message(struct tuner *t, unsigned char *buf)
 {
 	static char *afc[16] = {
 		"- 12.5 kHz",
@@ -309,7 +277,7 @@
 	tda9887_info("  vfi level      : %s\n", (buf[0] & 0x80) ? "high" : "low");
 }
 
-static void dump_write_message(struct tda9887 *t, unsigned char *buf)
+static void dump_write_message(struct tuner *t, unsigned char *buf)
 {
 	static char *sound[4] = {
 		"AM/TV",
@@ -405,13 +373,13 @@
 
 /* ---------------------------------------------------------------------- */
 
-static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
+static int tda9887_set_tvnorm(struct tuner *t, char *buf)
 {
 	struct tvnorm *norm = NULL;
 	int i;
 
-	if (t->mode == T_RADIO) {
-		if (t->radio_mode == V4L2_TUNER_MODE_MONO)
+	if (t->mode == V4L2_TUNER_RADIO) {
+		if (t->audmode == V4L2_TUNER_MODE_MONO)
 			norm = &radio_mono;
 		else
 			norm = &radio_stereo;
@@ -445,7 +413,7 @@
 module_param(qss, int, 0644);
 module_param(adjust, int, 0644);
 
-static int tda9887_set_insmod(struct tda9887 *t, char *buf)
+static int tda9887_set_insmod(struct tuner *t, char *buf)
 {
 	if (UNSET != port1) {
 		if (port1)
@@ -474,27 +442,27 @@
 	return 0;
 }
 
-static int tda9887_set_config(struct tda9887 *t, char *buf)
+static int tda9887_set_config(struct tuner *t, char *buf)
 {
-	if (t->config & TDA9887_PORT1_ACTIVE)
+	if (t->tda9887_config & TDA9887_PORT1_ACTIVE)
 		buf[1] &= ~cOutputPort1Inactive;
-	if (t->config & TDA9887_PORT1_INACTIVE)
+	if (t->tda9887_config & TDA9887_PORT1_INACTIVE)
 		buf[1] |= cOutputPort1Inactive;
-	if (t->config & TDA9887_PORT2_ACTIVE)
+	if (t->tda9887_config & TDA9887_PORT2_ACTIVE)
 		buf[1] &= ~cOutputPort2Inactive;
-	if (t->config & TDA9887_PORT2_INACTIVE)
+	if (t->tda9887_config & TDA9887_PORT2_INACTIVE)
 		buf[1] |= cOutputPort2Inactive;
 
-	if (t->config & TDA9887_QSS)
+	if (t->tda9887_config & TDA9887_QSS)
 		buf[1] |= cQSS;
-	if (t->config & TDA9887_INTERCARRIER)
+	if (t->tda9887_config & TDA9887_INTERCARRIER)
 		buf[1] &= ~cQSS;
 
-	if (t->config & TDA9887_AUTOMUTE)
+	if (t->tda9887_config & TDA9887_AUTOMUTE)
 		buf[1] |= cAutoMuteFmActive;
-	if (t->config & TDA9887_DEEMPHASIS_MASK) {
+	if (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
 		buf[2] &= ~0x60;
-		switch (t->config & TDA9887_DEEMPHASIS_MASK) {
+		switch (t->tda9887_config & TDA9887_DEEMPHASIS_MASK) {
 		case TDA9887_DEEMPHASIS_NONE:
 			buf[2] |= cDeemphasisOFF;
 			break;
@@ -506,153 +474,36 @@
 			break;
 		}
 	}
-	if (t->config & TDA9887_TOP_SET) {
+	if (t->tda9887_config & TDA9887_TOP_SET) {
 		buf[2] &= ~cTopMask;
-		buf[2] |= (t->config >> 8) & cTopMask;
+		buf[2] |= (t->tda9887_config >> 8) & cTopMask;
 	}
-	if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
+	if ((t->tda9887_config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
 		buf[1] &= ~cQSS;
 	return 0;
 }
 
 /* ---------------------------------------------------------------------- */
 
-static char pal[] = "--";
-static char secam[] = "--";
-static char ntsc[] = "-";
-
-module_param_string(pal, pal, sizeof(pal), 0644);
-module_param_string(secam, secam, sizeof(secam), 0644);
-module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
-
-static int tda9887_fixup_std(struct tda9887 *t)
-{
-	/* get more precise norm info from insmod option */
-	if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
-		switch (pal[0]) {
-		case 'b':
-		case 'B':
-		case 'g':
-		case 'G':
-		case 'h':
-		case 'H':
-		case 'n':
-		case 'N':
-			if (pal[1] == 'c' || pal[1] == 'C') {
-				tda9887_dbg("insmod fixup: PAL => PAL-Nc\n");
-				t->std = V4L2_STD_PAL_Nc;
-			} else {
-				tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n");
-				t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N;
-			}
-			break;
-		case 'i':
-		case 'I':
-			tda9887_dbg("insmod fixup: PAL => PAL-I\n");
-			t->std = V4L2_STD_PAL_I;
-			break;
-		case 'd':
-		case 'D':
-		case 'k':
-		case 'K':
-			tda9887_dbg("insmod fixup: PAL => PAL-DK\n");
-			t->std = V4L2_STD_PAL_DK;
-			break;
-		case 'm':
-		case 'M':
-			tda9887_dbg("insmod fixup: PAL => PAL-M\n");
-			t->std = V4L2_STD_PAL_M;
-			break;
-		case '-':
-			/* default parameter, do nothing */
-			break;
-		default:
-			tda9887_info("pal= argument not recognised\n");
-			break;
-		}
-	}
-	if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
-		switch (secam[0]) {
-		case 'b':
-		case 'B':
-		case 'g':
-		case 'G':
-		case 'h':
-		case 'H':
-			tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n");
-			t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
-			break;
-		case 'd':
-		case 'D':
-		case 'k':
-		case 'K':
-			tda9887_dbg("insmod fixup: SECAM => SECAM-DK\n");
-			t->std = V4L2_STD_SECAM_DK;
-			break;
-		case 'l':
-		case 'L':
-			if (secam[1] == 'c' || secam[1] == 'C') {
-				tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n");
-				t->std = V4L2_STD_SECAM_LC;
-			} else {
-				tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
-				t->std = V4L2_STD_SECAM_L;
-			}
-			break;
-		case '-':
-			/* default parameter, do nothing */
-			break;
-		default:
-			tda9887_info("secam= argument not recognised\n");
-			break;
-		}
-	}
-	if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) {
-		switch (ntsc[0]) {
-		case 'm':
-		case 'M':
-			tda9887_dbg("insmod fixup: NTSC => NTSC-M\n");
-			t->std = V4L2_STD_NTSC_M;
-			break;
-		case 'j':
-		case 'J':
-			tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n");
-			t->std = V4L2_STD_NTSC_M_JP;
-			break;
-		case 'k':
-		case 'K':
-			tda9887_dbg("insmod fixup: NTSC => NTSC_M_KR\n");
-			t->std = V4L2_STD_NTSC_M_KR;
-			break;
-		case '-':
-			/* default parameter, do nothing */
-			break;
-		default:
-			tda9887_info("ntsc= argument not recognised\n");
-			break;
-		}
-	}
-	return 0;
-}
-
-static int tda9887_status(struct tda9887 *t)
+static int tda9887_status(struct tuner *t)
 {
 	unsigned char buf[1];
 	int rc;
 
 	memset(buf,0,sizeof(buf));
-	if (1 != (rc = i2c_master_recv(&t->client,buf,1)))
+	if (1 != (rc = i2c_master_recv(&t->i2c,buf,1)))
 		tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc);
 	dump_read_message(t, buf);
 	return 0;
 }
 
-static int tda9887_configure(struct tda9887 *t)
+static void tda9887_configure(struct i2c_client *client)
 {
+	struct tuner *t = i2c_get_clientdata(client);
 	int rc;
 
-	memset(t->data,0,sizeof(t->data));
-	tda9887_set_tvnorm(t,t->data);
+	memset(t->tda9887_data,0,sizeof(t->tda9887_data));
+	tda9887_set_tvnorm(t,t->tda9887_data);
 
 	/* A note on the port settings:
 	   These settings tend to depend on the specifics of the board.
@@ -667,249 +518,84 @@
 	   the ports should be set to active (0), but, again, that may
 	   differ depending on the precise hardware configuration.
 	 */
-	t->data[1] |= cOutputPort1Inactive;
-	t->data[1] |= cOutputPort2Inactive;
+	t->tda9887_data[1] |= cOutputPort1Inactive;
+	t->tda9887_data[1] |= cOutputPort2Inactive;
 
-	tda9887_set_config(t,t->data);
-	tda9887_set_insmod(t,t->data);
+	tda9887_set_config(t,t->tda9887_data);
+	tda9887_set_insmod(t,t->tda9887_data);
 
 	if (t->mode == T_STANDBY) {
-		t->data[1] |= cForcedMuteAudioON;
+		t->tda9887_data[1] |= cForcedMuteAudioON;
 	}
 
 	tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
-		t->data[1],t->data[2],t->data[3]);
-	if (debug > 1)
-		dump_write_message(t, t->data);
+		t->tda9887_data[1],t->tda9887_data[2],t->tda9887_data[3]);
+	if (tuner_debug > 1)
+		dump_write_message(t, t->tda9887_data);
 
-	if (4 != (rc = i2c_master_send(&t->client,t->data,4)))
+	if (4 != (rc = i2c_master_send(&t->i2c,t->tda9887_data,4)))
 		tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc);
 
-	if (debug > 2) {
+	if (tuner_debug > 2) {
 		msleep_interruptible(1000);
 		tda9887_status(t);
 	}
-	return 0;
 }
 
 /* ---------------------------------------------------------------------- */
 
-static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
+static void tda9887_tuner_status(struct i2c_client *client)
 {
-	struct tda9887 *t;
+	struct tuner *t = i2c_get_clientdata(client);
+	tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->tda9887_data[1], t->tda9887_data[2], t->tda9887_data[3]);
+}
 
-	client_template.adapter = adap;
-	client_template.addr    = addr;
+static int tda9887_get_afc(struct i2c_client *client)
+{
+	struct tuner *t = i2c_get_clientdata(client);
+	static int AFC_BITS_2_kHz[] = {
+		-12500,  -37500,  -62500,  -97500,
+		-112500, -137500, -162500, -187500,
+		187500,  162500,  137500,  112500,
+		97500 ,  62500,   37500 ,  12500
+	};
+	int afc=0;
+	__u8 reg = 0;
 
-	if (NULL == (t = kzalloc(sizeof(*t), GFP_KERNEL)))
-		return -ENOMEM;
+	if (1 == i2c_master_recv(&t->i2c,&reg,1))
+		afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
 
-	t->client      = client_template;
-	t->std         = 0;
-	t->radio_mode = V4L2_TUNER_MODE_STEREO;
+	return afc;
+}
 
-	tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name);
+static void tda9887_standby(struct i2c_client *client)
+{
+	tda9887_configure(client);
+}
 
-	i2c_set_clientdata(&t->client, t);
-	i2c_attach_client(&t->client);
+static void tda9887_set_freq(struct i2c_client *client, unsigned int freq)
+{
+	tda9887_configure(client);
+}
+
+int tda9887_tuner_init(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	strlcpy(c->name, "tda9887", sizeof(c->name));
+
+	tda9887_info("tda988[5/6/7] found @ 0x%x (%s)\n", t->i2c.addr,
+						t->i2c.driver->driver.name);
+
+	t->set_tv_freq = tda9887_set_freq;
+	t->set_radio_freq = tda9887_set_freq;
+	t->standby = tda9887_standby;
+	t->tuner_status=tda9887_tuner_status;
+	t->get_afc=tda9887_get_afc;
 
 	return 0;
 }
 
-static int tda9887_probe(struct i2c_adapter *adap)
-{
-	if (adap->class & I2C_CLASS_TV_ANALOG)
-		return i2c_probe(adap, &addr_data, tda9887_attach);
-	return 0;
-}
-
-static int tda9887_detach(struct i2c_client *client)
-{
-	struct tda9887 *t = i2c_get_clientdata(client);
-
-	i2c_detach_client(client);
-	kfree(t);
-	return 0;
-}
-
-#define SWITCH_V4L2	if (!t->using_v4l2 && debug) \
-			  tda9887_info("switching to v4l2\n"); \
-			  t->using_v4l2 = 1;
-#define CHECK_V4L2	if (t->using_v4l2) { if (debug) \
-			  tda9887_info("ignore v4l1 call\n"); \
-			  return 0; }
-
-static int
-tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-	struct tda9887 *t = i2c_get_clientdata(client);
-
-	switch (cmd) {
-
-	/* --- configuration --- */
-	case AUDC_SET_RADIO:
-	{
-		t->mode = T_RADIO;
-		tda9887_configure(t);
-		break;
-	}
-	case TUNER_SET_STANDBY:
-	{
-		t->mode = T_STANDBY;
-		tda9887_configure(t);
-		break;
-	}
-	case TDA9887_SET_CONFIG:
-	{
-		int *i = arg;
-
-		t->config = *i;
-		tda9887_configure(t);
-		break;
-	}
-	/* --- v4l ioctls --- */
-	/* take care: bttv does userspace copying, we'll get a
-	   kernel pointer here... */
-	case VIDIOCSCHAN:
-	{
-		static const v4l2_std_id map[] = {
-			[ VIDEO_MODE_PAL   ] = V4L2_STD_PAL,
-			[ VIDEO_MODE_NTSC  ] = V4L2_STD_NTSC_M,
-			[ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
-			[ 4 /* bttv */     ] = V4L2_STD_PAL_M,
-			[ 5 /* bttv */     ] = V4L2_STD_PAL_N,
-			[ 6 /* bttv */     ] = V4L2_STD_NTSC_M_JP,
-		};
-		struct video_channel *vc = arg;
-
-		CHECK_V4L2;
-		t->mode = T_ANALOG_TV;
-		if (vc->norm < ARRAY_SIZE(map))
-			t->std = map[vc->norm];
-		tda9887_fixup_std(t);
-		tda9887_configure(t);
-		break;
-	}
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *id = arg;
-
-		SWITCH_V4L2;
-		t->mode = T_ANALOG_TV;
-		t->std   = *id;
-		tda9887_fixup_std(t);
-		tda9887_configure(t);
-		break;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		SWITCH_V4L2;
-		if (V4L2_TUNER_ANALOG_TV == f->type) {
-			if (t->mode == T_ANALOG_TV)
-				return 0;
-			t->mode = T_ANALOG_TV;
-		}
-		if (V4L2_TUNER_RADIO == f->type) {
-			if (t->mode == T_RADIO)
-				return 0;
-			t->mode = T_RADIO;
-		}
-		tda9887_configure(t);
-		break;
-	}
-	case VIDIOC_G_TUNER:
-	{
-		static int AFC_BITS_2_kHz[] = {
-			-12500,  -37500,  -62500,  -97500,
-			-112500, -137500, -162500, -187500,
-			187500,  162500,  137500,  112500,
-			97500 ,  62500,   37500 ,  12500
-		};
-		struct v4l2_tuner* tuner = arg;
-
-		if (t->mode == T_RADIO) {
-			__u8 reg = 0;
-			tuner->afc=0;
-			if (1 == i2c_master_recv(&t->client,&reg,1))
-				tuner->afc = AFC_BITS_2_kHz[(reg>>1)&0x0f];
-		}
-		break;
-	}
-	case VIDIOC_S_TUNER:
-	{
-		struct v4l2_tuner* tuner = arg;
-
-		if (t->mode == T_RADIO) {
-			t->radio_mode = tuner->audmode;
-			tda9887_configure (t);
-		}
-		break;
-	}
-	case VIDIOC_LOG_STATUS:
-	{
-		tda9887_info("Data bytes: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1], t->data[2], t->data[3]);
-		break;
-	}
-	default:
-		/* nothing */
-		break;
-	}
-	return 0;
-}
-
-static int tda9887_suspend(struct device * dev, pm_message_t state)
-{
-	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
-	struct tda9887 *t = i2c_get_clientdata(c);
-
-	tda9887_dbg("suspend\n");
-	return 0;
-}
-
-static int tda9887_resume(struct device * dev)
-{
-	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
-	struct tda9887 *t = i2c_get_clientdata(c);
-
-	tda9887_dbg("resume\n");
-	tda9887_configure(t);
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver driver = {
-	.id             = I2C_DRIVERID_TDA9887,
-	.attach_adapter = tda9887_probe,
-	.detach_client  = tda9887_detach,
-	.command        = tda9887_command,
-	.driver = {
-		.name    = "tda9887",
-		.suspend = tda9887_suspend,
-		.resume  = tda9887_resume,
-	},
-};
-static struct i2c_client client_template =
-{
-	.name      = "tda9887",
-	.driver    = &driver,
-};
-
-static int __init tda9887_init_module(void)
-{
-	return i2c_add_driver(&driver);
-}
-
-static void __exit tda9887_cleanup_module(void)
-{
-	i2c_del_driver(&driver);
-}
-
-module_init(tda9887_init_module);
-module_exit(tda9887_cleanup_module);
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * ---------------------------------------------------------------------------
diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c
index c2b98f8..d1c4178 100644
--- a/drivers/media/video/tea5767.c
+++ b/drivers/media/video/tea5767.c
@@ -3,7 +3,7 @@
  * I2C address is allways 0xC0.
  *
  *
- * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@brturbo.com.br)
+ * Copyright (c) 2005 Mauro Carvalho Chehab (mchehab@infradead.org)
  * This code is placed under the terms of the GNU General Public License
  *
  * tea5767 autodetection thanks to Torsten Seeboth and Atsushi Nakagawa
diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c
new file mode 100644
index 0000000..76b2e96
--- /dev/null
+++ b/drivers/media/video/tlv320aic23b.c
@@ -0,0 +1,217 @@
+/*
+ * tlv320aic23b - driver version 0.0.1
+ *
+ * Copyright (C) 2006 Scott Alfter <salfter@ssai.us>
+ *
+ * Based on wm8775 driver
+ *
+ * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to>
+ * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/videodev.h>
+#include <media/v4l2-common.h>
+
+MODULE_DESCRIPTION("tlv320aic23b driver");
+MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
+MODULE_LICENSE("GPL");
+
+static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END };
+
+
+I2C_CLIENT_INSMOD;
+
+/* ----------------------------------------------------------------------- */
+
+struct tlv320aic23b_state {
+	u8 muted;
+};
+
+static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val)
+{
+	int i;
+
+	if ((reg < 0 || reg > 9) && (reg != 15)) {
+		v4l_err(client, "Invalid register R%d\n", reg);
+		return -1;
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (i2c_smbus_write_byte_data(client, (reg << 1) |
+					(val >> 8), val & 0xff) == 0) {
+			return 0;
+		}
+	}
+	v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg);
+	return -1;
+}
+
+static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd,
+			  void *arg)
+{
+	struct tlv320aic23b_state *state = i2c_get_clientdata(client);
+	struct v4l2_control *ctrl = arg;
+	u32* freq = arg;
+
+	switch (cmd) {
+	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
+		switch (*freq) {
+			case 32000: /* set sample rate to 32 kHz */
+				tlv320aic23b_write(client, 8, 0x018);
+				break;
+			case 44100: /* set sample rate to 44.1 kHz */
+				tlv320aic23b_write(client, 8, 0x022);
+				break;
+			case 48000: /* set sample rate to 48 kHz */
+				tlv320aic23b_write(client, 8, 0x000);
+				break;
+			default:
+				return -EINVAL;
+		}
+		break;
+
+	case VIDIOC_G_CTRL:
+		if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+			return -EINVAL;
+		ctrl->value = state->muted;
+		break;
+
+	case VIDIOC_S_CTRL:
+		if (ctrl->id != V4L2_CID_AUDIO_MUTE)
+			return -EINVAL;
+		state->muted = ctrl->value;
+		tlv320aic23b_write(client, 0, 0x180); /* mute both channels */
+		/* set gain on both channels to +3.0 dB */
+		if (!state->muted)
+			tlv320aic23b_write(client, 0, 0x119);
+		break;
+
+	case VIDIOC_LOG_STATUS:
+		v4l_info(client, "Input: %s\n",
+			    state->muted ? "muted" : "active");
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+
+/*
+ * Generic i2c probe
+ * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
+ */
+
+static struct i2c_driver i2c_driver;
+
+static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct tlv320aic23b_state *state;
+
+	/* Check if the adapter supports the needed features */
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return 0;
+
+	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (client == 0)
+		return -ENOMEM;
+
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &i2c_driver;
+	snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b");
+
+	v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name);
+
+	state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL);
+	if (state == NULL) {
+		kfree(client);
+		return -ENOMEM;
+	}
+	state->muted = 0;
+	i2c_set_clientdata(client, state);
+
+	/* initialize tlv320aic23b */
+	tlv320aic23b_write(client, 15, 0x000);	/* RESET */
+	tlv320aic23b_write(client, 6, 0x00A);   /* turn off DAC & mic input */
+	tlv320aic23b_write(client, 7, 0x049);   /* left-justified, 24-bit, master mode */
+	tlv320aic23b_write(client, 0, 0x119);   /* set gain on both channels to +3.0 dB */
+	tlv320aic23b_write(client, 8, 0x000);   /* set sample rate to 48 kHz */
+	tlv320aic23b_write(client, 9, 0x001);   /* activate digital interface */
+
+	i2c_attach_client(client);
+
+	return 0;
+}
+
+static int tlv320aic23b_probe(struct i2c_adapter *adapter)
+{
+	if (adapter->class & I2C_CLASS_TV_ANALOG)
+		return i2c_probe(adapter, &addr_data, tlv320aic23b_attach);
+	return 0;
+}
+
+static int tlv320aic23b_detach(struct i2c_client *client)
+{
+	int err;
+
+	err = i2c_detach_client(client);
+	if (err) {
+		return err;
+	}
+	kfree(client);
+
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+/* i2c implementation */
+static struct i2c_driver i2c_driver = {
+	.driver = {
+		.name = "tlv320aic23b",
+	},
+	.id             = I2C_DRIVERID_TLV320AIC23B,
+	.attach_adapter = tlv320aic23b_probe,
+	.detach_client  = tlv320aic23b_detach,
+	.command        = tlv320aic23b_command,
+};
+
+
+static int __init tlv320aic23b_init_module(void)
+{
+	return i2c_add_driver(&i2c_driver);
+}
+
+static void __exit tlv320aic23b_cleanup_module(void)
+{
+	i2c_del_driver(&i2c_driver);
+}
+
+module_init(tlv320aic23b_init_module);
+module_exit(tlv320aic23b_cleanup_module);
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 74ab48c..bdf506e 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -25,6 +25,7 @@
 
 #include <linux/i2c.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include <media/tuner.h>
 
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 1013b4d..011413c 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -40,7 +40,6 @@
 static unsigned int show_i2c = 0;
 
 /* insmod options used at runtime => read/write */
-static unsigned int tuner_debug_old = 0;
 int tuner_debug = 0;
 
 static unsigned int tv_range[2] = { 44, 958 };
@@ -54,8 +53,6 @@
 module_param(addr, int, 0444);
 module_param(no_autodetect, int, 0444);
 module_param(show_i2c, int, 0444);
-/* Note: tuner_debug is deprecated and will be removed in 2.6.17 */
-module_param_named(tuner_debug,tuner_debug_old, int, 0444);
 module_param_named(debug,tuner_debug, int, 0644);
 module_param_string(pal, pal, sizeof(pal), 0644);
 module_param_string(secam, secam, sizeof(secam), 0644);
@@ -199,7 +196,7 @@
 		i2c_master_send(c, buffer, 4);
 		default_tuner_init(c);
 		break;
-	case TUNER_LG_TDVS_H062F:
+	case TUNER_LG_TDVS_H06XF:
 		/* Set the Auxiliary Byte. */
 		buffer[2] &= ~0x20;
 		buffer[2] |= 0x18;
@@ -215,6 +212,9 @@
 		i2c_master_send(c,buffer,4);
 		default_tuner_init(c);
 		break;
+	case TUNER_TDA9887:
+		tda9887_tuner_init(c);
+		break;
 	default:
 		default_tuner_init(c);
 		break;
@@ -241,6 +241,8 @@
 {
 	struct tuner *t = i2c_get_clientdata(c);
 
+	tuner_dbg("set addr for type %i\n", t->type);
+
 	if ( t->type == UNSET && ((tun_setup->addr == ADDR_UNSET &&
 		(t->mode_mask & tun_setup->mode_mask)) ||
 		tun_setup->addr == c->addr)) {
@@ -436,11 +438,7 @@
 	t->radio_if2 = 10700 * 1000;	/* 10.7MHz - FM radio */
 	t->audmode = V4L2_TUNER_MODE_STEREO;
 	t->mode_mask = T_UNINITIALIZED;
-	if (tuner_debug_old) {
-		tuner_debug = tuner_debug_old;
-		printk(KERN_ERR "tuner: tuner_debug is deprecated and will be removed in 2.6.17.\n");
-		printk(KERN_ERR "tuner: use the debug option instead.\n");
-	}
+	t->tuner_status = tuner_status;
 
 	if (show_i2c) {
 		unsigned char buffer[16];
@@ -462,10 +460,14 @@
 		case 0x4b:
 			/* If chip is not tda8290, don't register.
 			   since it can be tda9887*/
-			if (tda8290_probe(&t->i2c) != 0) {
-				tuner_dbg("chip at addr %x is not a tda8290\n", addr);
-				kfree(t);
-				return 0;
+			if (tda8290_probe(&t->i2c) == 0) {
+				tuner_dbg("chip at addr %x is a tda8290\n", addr);
+			} else {
+				/* Default is being tda9887 */
+				t->type = TUNER_TDA9887;
+				t->mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV;
+				t->mode = T_STANDBY;
+				goto register_client;
 			}
 			break;
 		case 0x60:
@@ -592,6 +594,7 @@
 	case TUNER_SET_STANDBY:
 		if (check_mode(t, "TUNER_SET_STANDBY") == EINVAL)
 			return 0;
+		t->mode = T_STANDBY;
 		if (t->standby)
 			t->standby (client);
 		break;
@@ -604,6 +607,14 @@
 		/* Should be implemented, since bttv calls it */
 		tuner_dbg("VIDIOCSAUDIO not implemented.\n");
 		break;
+	case TDA9887_SET_CONFIG:
+	{
+		int *i = arg;
+
+		t->tda9887_config = *i;
+		set_freq(client, t->tv_freq);
+		break;
+	}
 	/* --- v4l ioctls --- */
 	/* take care: bttv does userspace copying, we'll get a
 	   kernel pointer here... */
@@ -711,14 +722,10 @@
 		{
 			struct v4l2_frequency *f = arg;
 
+			if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
+					== EINVAL)
+				return 0;
 			switch_v4l2();
-			if ((V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode)
-				|| (V4L2_TUNER_DIGITAL_TV == f->type
-					&& V4L2_TUNER_DIGITAL_TV != t->mode)) {
-				if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY")
-					    == EINVAL)
-					return 0;
-			}
 			set_freq(client,f->frequency);
 
 			break;
@@ -744,6 +751,8 @@
 			switch_v4l2();
 
 			tuner->type = t->mode;
+			if (t->get_afc)
+				tuner->afc=t->get_afc(client);
 			if (t->mode == V4L2_TUNER_ANALOG_TV)
 				tuner->capability |= V4L2_TUNER_CAP_NORM;
 			if (t->mode != V4L2_TUNER_RADIO) {
@@ -787,7 +796,8 @@
 			break;
 		}
 	case VIDIOC_LOG_STATUS:
-		tuner_status(client);
+		if (t->tuner_status)
+			t->tuner_status(client);
 		break;
 	}
 
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 5d7abed..6da6f82 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -105,7 +105,7 @@
 
 	switch (t->type) {
 		case TUNER_PHILIPS_FM1216ME_MK3:
-    		case TUNER_PHILIPS_FM1236_MK3:
+		case TUNER_PHILIPS_FM1236_MK3:
 		case TUNER_PHILIPS_FM1256_IH3:
 			stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
 			break;
diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c
index a1ae036..9d9226c 100644
--- a/drivers/media/video/tuner-types.c
+++ b/drivers/media/video/tuner-types.c
@@ -874,7 +874,7 @@
 };
 
 
-/* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */
+/* ------ TUNER_LG_TDVS_H06XF - LG INNOTEK / INFINEON ATSC ----- */
 
 static struct tuner_range tuner_tua6034_ntsc_ranges[] = {
 	{ 16 * 165.00 /*MHz*/, 0x8e, 0x01 },
@@ -883,7 +883,7 @@
 };
 
 
-static struct tuner_params tuner_tua6034_params[] = {
+static struct tuner_params tuner_lg_tdvs_h06xf_params[] = {
 	{
 		.type   = TUNER_PARAM_TYPE_NTSC,
 		.ranges = tuner_tua6034_ntsc_ranges,
@@ -1024,6 +1024,22 @@
 	},
 };
 
+/* ------------ TUNER_SAMSUNG_TCPG_6121P30A - Samsung PAL ------------ */
+
+static struct tuner_range tuner_samsung_tcpg_6121p30a_pal_ranges[] = {
+	{ 16 * 146.25 /*MHz*/, 0xce, 0x01, },
+	{ 16 * 428.50 /*MHz*/, 0xce, 0x02, },
+	{ 16 * 999.99        , 0xce, 0x08, },
+};
+
+static struct tuner_params tuner_samsung_tcpg_6121p30a_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_PAL,
+		.ranges = tuner_samsung_tcpg_6121p30a_pal_ranges,
+		.count  = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_pal_ranges),
+	},
+};
+
 /* --------------------------------------------------------------------- */
 
 struct tunertype tuners[] = {
@@ -1354,10 +1370,10 @@
 		.params = tuner_philips_fmd1216me_mk3_params,
 		.count  = ARRAY_SIZE(tuner_philips_fmd1216me_mk3_params),
 	},
-	[TUNER_LG_TDVS_H062F] = { /* LGINNOTEK ATSC */
-		.name   = "LG TDVS-H062F/TUA6034",
-		.params = tuner_tua6034_params,
-		.count  = ARRAY_SIZE(tuner_tua6034_params),
+	[TUNER_LG_TDVS_H06XF] = { /* LGINNOTEK ATSC */
+		.name   = "LG TDVS-H06xF", /* H061F, H062F & H064F */
+		.params = tuner_lg_tdvs_h06xf_params,
+		.count  = ARRAY_SIZE(tuner_lg_tdvs_h06xf_params),
 	},
 	[TUNER_YMEC_TVF66T5_B_DFF] = { /* Philips PAL */
 		.name   = "Ymec TVF66T5-B/DFF",
@@ -1400,6 +1416,16 @@
 		.params = tuner_thomson_fe6600_params,
 		.count  = ARRAY_SIZE(tuner_thomson_fe6600_params),
 	},
+	[TUNER_SAMSUNG_TCPG_6121P30A] = { /* Samsung PAL */
+		.name   = "Samsung TCPG 6121P30A",
+		.params = tuner_samsung_tcpg_6121p30a_params,
+		.count  = ARRAY_SIZE(tuner_samsung_tcpg_6121p30a_params),
+	},
+	[TUNER_TDA9887] = { /* Philips TDA 9887 IF PLL Demodulator.
+				This chip is part of some modern tuners */
+		.name   = "Philips TDA988[5,6,7] IF PLL Demodulator",
+		/* see tda9887.c for details */
+	},
 };
 
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index b463e99..30f8d80 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -200,7 +200,7 @@
 	{ TUNER_ABSENT,        "Philips FQ1286A MK4"},
 	{ TUNER_ABSENT,        "Philips FQ1216ME MK5"},
 	{ TUNER_ABSENT,        "Philips FQ1236 MK5"},
-	{ TUNER_ABSENT,        "Samsung TCPG_6121P30A"},
+	{ TUNER_SAMSUNG_TCPG_6121P30A, "Samsung TCPG 6121P30A"},
 	{ TUNER_TCL_2002MB,    "TCL 2002MB_3H"},
 	{ TUNER_ABSENT,        "TCL 2002MI_3H"},
 	{ TUNER_TCL_2002N,     "TCL 2002N 5H"},
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index 9e86cae..1654576 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -198,10 +198,6 @@
 
 	/* lock bttv in memory while the mixer is in use  */
 	file->private_data = mix;
-#ifndef I2C_PEC
-	if (client->adapter->inc_use)
-		client->adapter->inc_use(client->adapter);
-#endif
 	if (client->adapter->owner)
 		try_module_get(client->adapter->owner);
 	return 0;
@@ -217,10 +213,6 @@
 		return -ENODEV;
 	}
 
-#ifndef I2C_PEC
-	if (client->adapter->dec_use)
-		client->adapter->dec_use(client->adapter);
-#endif
 	if (client->adapter->owner)
 		module_put(client->adapter->owner);
 	return 0;
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c
index dab4973..b167ffa 100644
--- a/drivers/media/video/tvp5150.c
+++ b/drivers/media/video/tvp5150.c
@@ -10,6 +10,7 @@
 #include <linux/delay.h>
 #include <linux/video_decoder.h>
 #include <media/v4l2-common.h>
+#include <media/tvp5150.h>
 
 #include "tvp5150_reg.h"
 
@@ -89,7 +90,7 @@
 	struct i2c_client *client;
 
 	v4l2_std_id norm;	/* Current set standard */
-	int input;
+	struct v4l2_routing route;
 	int enable;
 	int bright;
 	int contrast;
@@ -283,29 +284,26 @@
 /****************************************************************************
 			Basic functions
  ****************************************************************************/
-enum tvp5150_input {
-	TVP5150_ANALOG_CH0 = 0,
-	TVP5150_SVIDEO = 1,
-	TVP5150_ANALOG_CH1 = 2,
-	TVP5150_BLACK_SCREEN = 8
-};
 
-static inline void tvp5150_selmux(struct i2c_client *c,
-				  enum tvp5150_input input)
+static inline void tvp5150_selmux(struct i2c_client *c)
 {
 	int opmode=0;
-
 	struct tvp5150 *decoder = i2c_get_clientdata(c);
+	int input = 0;
 
-	if (!decoder->enable)
-		input |= TVP5150_BLACK_SCREEN;
+	if ((decoder->route.output & TVP5150_BLACK_SCREEN) || !decoder->enable)
+		input = 8;
 
 	switch (input) {
-	case TVP5150_ANALOG_CH0:
-	case TVP5150_ANALOG_CH1:
+	case TVP5150_COMPOSITE1:
+		input |= 2;
+		/* fall through */
+	case TVP5150_COMPOSITE0:
 		opmode=0x30;		/* TV Mode */
 		break;
+	case TVP5150_SVIDEO:
 	default:
+		input |= 1;
 		opmode=0;		/* Auto Mode */
 		break;
 	}
@@ -790,7 +788,7 @@
 	tvp5150_vdp_init(c, vbi_ram_default);
 
 	/* Selects decoder input */
-	tvp5150_selmux(c, decoder->input);
+	tvp5150_selmux(c);
 
 	/* Initializes TVP5150 to stream enabled values */
 	tvp5150_write_inittab(c, tvp5150_init_enable);
@@ -860,6 +858,21 @@
 	case VIDIOC_INT_RESET:
 		tvp5150_reset(c);
 		break;
+	case VIDIOC_INT_G_VIDEO_ROUTING:
+	{
+		struct v4l2_routing *route = arg;
+
+		*route = decoder->route;
+		break;
+	}
+	case VIDIOC_INT_S_VIDEO_ROUTING:
+	{
+		struct v4l2_routing *route = arg;
+
+		decoder->route = *route;
+		tvp5150_selmux(c);
+		break;
+	}
 	case VIDIOC_S_STD:
 		if (decoder->norm == *(v4l2_std_id *)arg)
 			break;
@@ -1063,7 +1076,7 @@
 	rv = i2c_attach_client(c);
 
 	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
-	core->input = 2;
+	core->route.input = TVP5150_COMPOSITE1;
 	core->enable = 1;
 	core->bright = 32768;
 	core->contrast = 32768;
diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig
index 39269a2..59fb899 100644
--- a/drivers/media/video/usbvideo/Kconfig
+++ b/drivers/media/video/usbvideo/Kconfig
@@ -36,3 +36,15 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called konicawc.
+
+config USB_QUICKCAM_MESSENGER
+	tristate "USB Logitech Quickcam Messenger"
+	depends on USB && VIDEO_DEV
+	select VIDEO_USBVIDEO
+	---help---
+	  Say Y or M here to enable support for the USB Logitech Quickcam
+	  Messenger webcam.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called quickcam_messenger.
+
diff --git a/drivers/media/video/usbvideo/Makefile b/drivers/media/video/usbvideo/Makefile
index bb52eb8..4a1b144 100644
--- a/drivers/media/video/usbvideo/Makefile
+++ b/drivers/media/video/usbvideo/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_USB_IBMCAM)        += ibmcam.o ultracam.o
 obj-$(CONFIG_USB_KONICAWC)      += konicawc.o
 obj-$(CONFIG_USB_VICAM)         += vicam.o
+obj-$(CONFIG_USB_QUICKCAM_MESSENGER)	+= quickcam_messenger.o
diff --git a/drivers/media/video/usbvideo/konicawc.c b/drivers/media/video/usbvideo/konicawc.c
index c11f5d4..6f31ecc 100644
--- a/drivers/media/video/usbvideo/konicawc.c
+++ b/drivers/media/video/usbvideo/konicawc.c
@@ -15,8 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/input.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #include "usbvideo.h"
 
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
new file mode 100644
index 0000000..56e01b6
--- /dev/null
+++ b/drivers/media/video/usbvideo/quickcam_messenger.c
@@ -0,0 +1,1120 @@
+/*
+ * Driver for Logitech Quickcam Messenger usb video camera
+ * Copyright (C) Jaya Kumar
+ *
+ * This work was sponsored by CIS(M) Sdn Bhd.
+ * History:
+ * 05/08/2006 - Jaya Kumar
+ * I wrote this based on the konicawc by Simon Evans.
+ * -
+ * Full credit for reverse engineering and creating an initial
+ * working linux driver for the VV6422 goes to the qce-ga project by
+ * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell,
+ * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as
+ * others.
+ * ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/usb/input.h>
+
+#include "usbvideo.h"
+#include "quickcam_messenger.h"
+
+/*
+ * Version Information
+ */
+
+#ifdef CONFIG_USB_DEBUG
+static int debug;
+#define DEBUG(n, format, arg...) \
+	if (n <= debug) {	 \
+		printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \
+	}
+#else
+#define DEBUG(n, arg...)
+static const int debug = 0;
+#endif
+
+#define DRIVER_VERSION "v0.01"
+#define DRIVER_DESC "Logitech Quickcam Messenger USB"
+
+#define USB_LOGITECH_VENDOR_ID	0x046D
+#define USB_QCM_PRODUCT_ID	0x08F0
+
+#define MAX_CAMERAS	1
+
+#define MAX_COLOUR	32768
+#define MAX_HUE		32768
+#define MAX_BRIGHTNESS	32768
+#define MAX_CONTRAST	32768
+#define MAX_WHITENESS	32768
+
+static int size = SIZE_320X240;
+static int colour = MAX_COLOUR;
+static int hue = MAX_HUE;
+static int brightness =	MAX_BRIGHTNESS;
+static int contrast =	MAX_CONTRAST;
+static int whiteness =	MAX_WHITENESS;
+
+static struct usbvideo *cams;
+
+static struct usb_device_id qcm_table [] = {
+	{ USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, qcm_table);
+
+#ifdef CONFIG_INPUT
+static void qcm_register_input(struct qcm *cam, struct usb_device *dev)
+{
+	struct input_dev *input_dev;
+
+	usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname));
+	strncat(cam->input_physname, "/input0", sizeof(cam->input_physname));
+
+	cam->input = input_dev = input_allocate_device();
+	if (!input_dev) {
+		warn("insufficient mem for cam input device");
+		return;
+	}
+
+	input_dev->name = "QCM button";
+	input_dev->phys = cam->input_physname;
+	usb_to_input_id(dev, &input_dev->id);
+	input_dev->cdev.dev = &dev->dev;
+
+	input_dev->evbit[0] = BIT(EV_KEY);
+	input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0);
+
+	input_dev->private = cam;
+
+	input_register_device(cam->input);
+}
+
+static void qcm_unregister_input(struct qcm *cam)
+{
+	if (cam->input) {
+		input_unregister_device(cam->input);
+		cam->input = NULL;
+	}
+}
+
+static void qcm_report_buttonstat(struct qcm *cam)
+{
+	if (cam->input) {
+		input_report_key(cam->input, BTN_0, cam->button_sts);
+		input_sync(cam->input);
+	}
+}
+
+static void qcm_int_irq(struct urb *urb, struct pt_regs *regs)
+{
+	int ret;
+	struct uvd *uvd = urb->context;
+	struct qcm *cam;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return;
+
+	if (!uvd->streaming)
+		return;
+
+	uvd->stats.urb_count++;
+
+	if (urb->status < 0)
+		uvd->stats.iso_err_count++;
+	else {
+		if (urb->actual_length > 0 ) {
+			cam = (struct qcm *) uvd->user_data;
+			if (cam->button_sts_buf == 0x88)
+				cam->button_sts = 0x0;
+			else if (cam->button_sts_buf == 0x80)
+				cam->button_sts = 0x1;
+			qcm_report_buttonstat(cam);
+		}
+	}
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret < 0)
+		err("usb_submit_urb error (%d)", ret);
+}
+
+static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd)
+{
+	int errflag;
+	usb_fill_int_urb(cam->button_urb, uvd->dev,
+			usb_rcvintpipe(uvd->dev, uvd->video_endp + 1),
+			&cam->button_sts_buf,
+			1,
+			qcm_int_irq,
+			uvd, 16);
+
+	errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL);
+	if (errflag)
+		err ("usb_submit_int ret %d", errflag);
+	return errflag;
+}
+
+static void qcm_stop_int_data(struct qcm *cam)
+{
+	usb_kill_urb(cam->button_urb);
+}
+
+static int qcm_alloc_int_urb(struct qcm *cam)
+{
+	cam->button_urb = usb_alloc_urb(0, GFP_KERNEL);
+
+	if (!cam->button_urb)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void qcm_free_int(struct qcm *cam)
+{
+	if (cam->button_urb)
+		usb_free_urb(cam->button_urb);
+}
+#endif /* CONFIG_INPUT */
+
+static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val)
+{
+	int ret;
+
+	/* we'll wait up to 3 slices but no more */
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+		reg, 0, &val, 1, 3*HZ);
+	return ret;
+}
+
+static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val)
+{
+	int ret;
+
+	/* we'll wait up to 3 slices but no more */
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
+		reg, 0, &val, 2, 3*HZ);
+	return ret;
+}
+
+static int qcm_stv_getw(struct usb_device *dev, unsigned short reg,
+							__le16 *val)
+{
+	int ret;
+
+	/* we'll wait up to 3 slices but no more */
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
+		reg, 0, val, 2, 3*HZ);
+	return ret;
+}
+
+static int qcm_camera_on(struct uvd *uvd)
+{
+	int ret;
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01));
+	return 0;
+}
+
+static int qcm_camera_off(struct uvd *uvd)
+{
+	int ret;
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
+	return 0;
+}
+
+static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b)
+{
+	unsigned int segment, valsat;
+	signed int   h = (signed int) hue;
+	unsigned int s = (sat - 32768) * 2;	/* rescale */
+	unsigned int v = val;
+	unsigned int p;
+
+	/*
+	the registers controling gain are 8 bit of which
+	we affect only the last 4 bits with our gain.
+	we know that if saturation is 0, (unsaturated) then
+	we're grayscale (center axis of the colour cone) so
+	we set rgb=value. we use a formula obtained from
+	wikipedia to map the cone to the RGB plane. it's
+	as follows for the human value case of h=0..360,
+	s=0..1, v=0..1
+	h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s)
+	q = v(1 - f*s) , t = v(1 - (1-f)s)
+	h_i==0 => r=v , g=t, b=p
+	h_i==1 => r=q , g=v, b=p
+	h_i==2 => r=p , g=v, b=t
+	h_i==3 => r=p , g=q, b=v
+	h_i==4 => r=t , g=p, b=v
+	h_i==5 => r=v , g=p, b=q
+	the bottom side (the point) and the stuff just up
+	of that is black so we simplify those two cases.
+	*/
+	if (sat < 32768) {
+		/* anything less than this is unsaturated */
+		*r = val;
+		*g = val;
+		*b = val;
+		return;
+	}
+	if (val <= (0xFFFF/8)) {
+		/* anything less than this is black */
+		*r = 0;
+		*g = 0;
+		*b = 0;
+		return;
+	}
+
+	/* the rest of this code is copying tukkat's
+	implementation of the hsv2rgb conversion as taken
+	from qc-usb-messenger code. the 10923 is 0xFFFF/6
+	to divide the cone into 6 sectors.  */
+
+	segment = (h + 10923) & 0xFFFF;
+	segment = segment*3 >> 16;		/* 0..2: 0=R, 1=G, 2=B */
+	hue -= segment * 21845;			/* -10923..10923 */
+	h = hue;
+	h *= 3;
+	valsat = v*s >> 16;			/* 0..65534 */
+	p = v - valsat;
+	if (h >= 0) {
+		unsigned int t = v - (valsat * (32769 - h) >> 15);
+		switch (segment) {
+		case 0:	/* R-> */
+			*r = v;
+			*g = t;
+			*b = p;
+			break;
+		case 1:	/* G-> */
+			*r = p;
+			*g = v;
+			*b = t;
+			break;
+		case 2:	/* B-> */
+			*r = t;
+			*g = p;
+			*b = v;
+			break;
+		}
+	} else {
+		unsigned int q = v - (valsat * (32769 + h) >> 15);
+		switch (segment) {
+		case 0:	/* ->R */
+			*r = v;
+			*g = p;
+			*b = q;
+			break;
+		case 1:	/* ->G */
+			*r = q;
+			*g = v;
+			*b = p;
+			break;
+		case 2:	/* ->B */
+			*r = p;
+			*g = q;
+			*b = v;
+			break;
+		}
+	}
+}
+
+static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue,
+	u16 saturation, u16 value)
+{
+	int ret;
+	u16 r=0,g=0,b=0;
+
+	/* this code is based on qc-usb-messenger */
+	qcm_hsv2rgb(hue, saturation, value, &r, &g, &b);
+
+	r >>= 12;
+	g >>= 12;
+	b >>= 12;
+
+	/* min val is 8 */
+	r = max((u16) 8, r);
+	g = max((u16) 8, g);
+	b = max((u16) 8, b);
+
+	r |= 0x30;
+	g |= 0x30;
+	b |= 0x30;
+
+	/* set the r,g,b gain registers */
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b));
+
+	/* doing as qc-usb did */
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+
+	return 0;
+}
+
+static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure)
+{
+	int ret;
+	int formedval;
+
+	/* calculation was from qc-usb-messenger driver */
+	formedval = ( exposure >> 12 );
+
+	/* max value for formedval is 14 */
+	formedval = min(formedval, 14);
+
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev,
+			0x143A, 0xF0 | formedval));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+	return 0;
+}
+
+static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast,
+					int hue, int colour)
+{
+	int ret;
+	/* brightness is exposure, contrast is gain, colour is saturation */
+	CHECK_RET(ret,
+		qcm_sensor_set_exposure(uvd, brightness));
+	CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast));
+
+	return 0;
+}
+
+static int qcm_sensor_setsize(struct uvd *uvd, u8 size)
+{
+	int ret;
+
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size));
+	return 0;
+}
+
+static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness)
+{
+	int ret;
+	/* some rescaling as done by the qc-usb-messenger code */
+	if (whiteness > 0xC000)
+		whiteness = 0xC000 + (whiteness & 0x3FFF)*8;
+
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D,
+				(whiteness >> 8) & 0xFF));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E,
+				(whiteness >> 16) & 0x03));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01));
+
+	return 0;
+}
+
+static int qcm_sensor_init(struct uvd *uvd)
+{
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+	int ret;
+	int i;
+
+	for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) {
+		CHECK_RET(ret, qcm_stv_setb(uvd->dev,
+					regval_table[i].reg,
+					regval_table[i].val));
+	}
+
+	CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1,
+				cpu_to_le16(ISOC_PACKET_SIZE)));
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08));
+	CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01));
+
+	CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00));
+
+	CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+
+	CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness,
+			uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour));
+
+	CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
+	CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+
+	return 0;
+}
+
+static int qcm_set_camera_size(struct uvd *uvd)
+{
+	int ret;
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+
+	CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd));
+	cam->width = camera_sizes[cam->size].width;
+	cam->height = camera_sizes[cam->size].height;
+	uvd->videosize = VIDEOSIZE(cam->width, cam->height);
+
+	return 0;
+}
+
+static int qcm_setup_on_open(struct uvd *uvd)
+{
+	int ret;
+
+	CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue,
+				uvd->vpic.colour, uvd->vpic.contrast));
+	CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness));
+	CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness));
+	CHECK_RET(ret, qcm_set_camera_size(uvd));
+	CHECK_RET(ret, qcm_camera_on(uvd));
+	return 0;
+}
+
+static void qcm_adjust_picture(struct uvd *uvd)
+{
+	int ret;
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+
+	ret = qcm_camera_off(uvd);
+	if (ret) {
+		err("can't turn camera off. abandoning pic adjustment");
+		return;
+	}
+
+	/* if there's been a change in contrast, hue, or
+	colour then we need to recalculate hsv in order
+	to update gains */
+	if ((cam->contrast != uvd->vpic.contrast) ||
+		(cam->hue != uvd->vpic.hue) ||
+		(cam->colour != uvd->vpic.colour)) {
+		cam->contrast = uvd->vpic.contrast;
+		cam->hue = uvd->vpic.hue;
+		cam->colour = uvd->vpic.colour;
+		ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour,
+						cam->contrast);
+		if (ret) {
+			err("can't set gains. abandoning pic adjustment");
+			return;
+		}
+	}
+
+	if (cam->brightness != uvd->vpic.brightness) {
+		cam->brightness = uvd->vpic.brightness;
+		ret = qcm_sensor_set_exposure(uvd, cam->brightness);
+		if (ret) {
+			err("can't set exposure. abandoning pic adjustment");
+			return;
+		}
+	}
+
+	if (cam->whiteness != uvd->vpic.whiteness) {
+		cam->whiteness = uvd->vpic.whiteness;
+		qcm_sensor_set_shutter(uvd, cam->whiteness);
+		if (ret) {
+			err("can't set shutter. abandoning pic adjustment");
+			return;
+		}
+	}
+
+	ret = qcm_camera_on(uvd);
+	if (ret) {
+		err("can't reenable camera. pic adjustment failed");
+		return;
+	}
+}
+
+static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen)
+{
+	int datalen;
+	int totaldata;
+	struct framehdr {
+		__be16 id;
+		__be16 len;
+	};
+	struct framehdr *fhdr;
+
+	totaldata = 0;
+	while (framelen) {
+		fhdr = (struct framehdr *) cdata;
+		datalen = be16_to_cpu(fhdr->len);
+		framelen -= 4;
+		cdata += 4;
+
+		if ((fhdr->id) == cpu_to_be16(0x8001)) {
+			RingQueue_Enqueue(&uvd->dp, marker, 4);
+			totaldata += 4;
+			continue;
+		}
+		if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) {
+			RingQueue_Enqueue(&uvd->dp, cdata, datalen);
+			totaldata += datalen;
+		}
+		framelen -= datalen;
+		cdata += datalen;
+	}
+	return totaldata;
+}
+
+static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb)
+{
+	int totlen;
+	int i;
+	unsigned char *cdata;
+
+	totlen=0;
+	for (i = 0; i < dataurb->number_of_packets; i++) {
+		int n = dataurb->iso_frame_desc[i].actual_length;
+		int st = dataurb->iso_frame_desc[i].status;
+
+		cdata = dataurb->transfer_buffer +
+			dataurb->iso_frame_desc[i].offset;
+
+		if (st < 0) {
+			warn("Data error: packet=%d. len=%d. status=%d.",
+			      i, n, st);
+			uvd->stats.iso_err_count++;
+			continue;
+		}
+		if (!n)
+			continue;
+
+		totlen += qcm_process_frame(uvd, cdata, n);
+	}
+	return totlen;
+}
+
+static void resubmit_urb(struct uvd *uvd, struct urb *urb)
+{
+	int ret;
+
+	urb->dev = uvd->dev;
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret)
+		err("usb_submit_urb error (%d)", ret);
+}
+
+static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs)
+{
+	int len;
+	struct uvd *uvd = urb->context;
+
+	if (!CAMERA_IS_OPERATIONAL(uvd))
+		return;
+
+	if (!uvd->streaming)
+		return;
+
+	uvd->stats.urb_count++;
+
+	if (!urb->actual_length) {
+		resubmit_urb(uvd, urb);
+		return;
+	}
+
+	len = qcm_compress_iso(uvd, urb);
+	resubmit_urb(uvd, urb);
+	uvd->stats.urb_length = len;
+	uvd->stats.data_count += len;
+	if (len)
+		RingQueue_WakeUpInterruptible(&uvd->dp);
+}
+
+static int qcm_start_data(struct uvd *uvd)
+{
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+	int i;
+	int errflag;
+	int pktsz;
+	int err;
+
+	pktsz = uvd->iso_packet_len;
+	if (!CAMERA_IS_OPERATIONAL(uvd)) {
+		err("Camera is not operational");
+		return -EFAULT;
+	}
+
+	err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive);
+	if (err < 0) {
+		err("usb_set_interface error");
+		uvd->last_error = err;
+		return -EBUSY;
+	}
+
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		int j, k;
+		struct urb *urb = uvd->sbuf[i].urb;
+		urb->dev = uvd->dev;
+		urb->context = uvd;
+		urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp);
+		urb->interval = 1;
+		urb->transfer_flags = URB_ISO_ASAP;
+		urb->transfer_buffer = uvd->sbuf[i].data;
+		urb->complete = qcm_isoc_irq;
+		urb->number_of_packets = FRAMES_PER_DESC;
+		urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC;
+		for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) {
+			urb->iso_frame_desc[j].offset = k;
+			urb->iso_frame_desc[j].length = pktsz;
+		}
+	}
+
+	uvd->streaming = 1;
+	uvd->curframe = -1;
+	for (i=0; i < USBVIDEO_NUMSBUF; i++) {
+		errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL);
+		if (errflag)
+			err ("usb_submit_isoc(%d) ret %d", i, errflag);
+	}
+
+	CHECK_RET(err, qcm_setup_input_int(cam, uvd));
+	CHECK_RET(err, qcm_camera_on(uvd));
+	return 0;
+}
+
+static void qcm_stop_data(struct uvd *uvd)
+{
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+	int i, j;
+	int ret;
+
+	if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL))
+		return;
+
+	ret = qcm_camera_off(uvd);
+	if (ret)
+		warn("couldn't turn the cam off.");
+
+	uvd->streaming = 0;
+
+	/* Unschedule all of the iso td's */
+	for (i=0; i < USBVIDEO_NUMSBUF; i++)
+		usb_kill_urb(uvd->sbuf[i].urb);
+
+	qcm_stop_int_data(cam);
+
+	if (!uvd->remove_pending) {
+		/* Set packet size to 0 */
+		j = usb_set_interface(uvd->dev, uvd->iface,
+					uvd->ifaceAltInactive);
+		if (j < 0) {
+			err("usb_set_interface() error %d.", j);
+			uvd->last_error = j;
+		}
+	}
+}
+
+static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame)
+{
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+	int x;
+	struct rgb *rgbL0;
+	struct rgb *rgbL1;
+	struct bayL0 *bayL0;
+	struct bayL1 *bayL1;
+	int hor,ver,hordel,verdel;
+	assert(frame != NULL);
+
+	switch (cam->size) {
+	case SIZE_160X120:
+		hor = 162; ver = 124; hordel = 1; verdel = 2;
+		break;
+	case SIZE_320X240:
+	default:
+		hor = 324; ver = 248; hordel = 2; verdel = 4;
+		break;
+	}
+
+	if (frame->scanstate == ScanState_Scanning) {
+		while (RingQueue_GetLength(&uvd->dp) >=
+			 4 + (hor*verdel + hordel)) {
+			if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) &&
+			    (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) {
+				frame->curline = 0;
+				frame->scanstate = ScanState_Lines;
+				frame->frameState = FrameState_Grabbing;
+				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4);
+			/*
+			* if we're starting, we need to discard the first
+			* 4 lines of y bayer data
+			* and the first 2 gr elements of x bayer data
+			*/
+				RING_QUEUE_DEQUEUE_BYTES(&uvd->dp,
+							(hor*verdel + hordel));
+				break;
+			}
+			RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1);
+		}
+	}
+
+	if (frame->scanstate == ScanState_Scanning)
+		return;
+
+	/* now we can start processing bayer data so long as we have at least
+	* 2 lines worth of data. this is the simplest demosaicing method that
+	* I could think of. I use each 2x2 bayer element without interpolation
+	* to generate 4 rgb pixels.
+	*/
+	while ( frame->curline < cam->height &&
+		(RingQueue_GetLength(&uvd->dp) >= hor*2)) {
+		/* get 2 lines of bayer for demosaicing
+		 * into 2 lines of RGB */
+		RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2);
+		bayL0 = (struct bayL0 *) cam->scratch;
+		bayL1 = (struct bayL1 *) (cam->scratch + hor);
+		/* frame->curline is the rgb y line */
+		rgbL0 = (struct rgb *)
+				( frame->data + (cam->width*3*frame->curline));
+		/* w/2 because we're already doing 2 pixels */
+		rgbL1 = rgbL0 + (cam->width/2);
+
+		for (x=0; x < cam->width; x+=2) {
+			rgbL0->r = bayL0->r;
+			rgbL0->g = bayL0->g;
+			rgbL0->b = bayL1->b;
+
+			rgbL0->r2 = bayL0->r;
+			rgbL0->g2 = bayL1->g;
+			rgbL0->b2 = bayL1->b;
+
+			rgbL1->r = bayL0->r;
+			rgbL1->g = bayL1->g;
+			rgbL1->b = bayL1->b;
+
+			rgbL1->r2 = bayL0->r;
+			rgbL1->g2 = bayL1->g;
+			rgbL1->b2 = bayL1->b;
+
+			rgbL0++;
+			rgbL1++;
+
+			bayL0++;
+			bayL1++;
+		}
+
+		frame->seqRead_Length += cam->width*3*2;
+		frame->curline += 2;
+	}
+	/* See if we filled the frame */
+	if (frame->curline == cam->height) {
+		frame->frameState = FrameState_Done_Hold;
+		frame->curline = 0;
+		uvd->curframe = -1;
+		uvd->stats.frame_num++;
+	}
+}
+
+/* taken from konicawc */
+static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw)
+{
+	int ret;
+	int newsize;
+	int oldsize;
+	int x = vw->width;
+	int y = vw->height;
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+
+	if (x > 0 && y > 0) {
+		DEBUG(2, "trying to find size %d,%d", x, y);
+		for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) {
+			if ((camera_sizes[newsize].width == x) &&
+				(camera_sizes[newsize].height == y))
+				break;
+		}
+	} else
+		newsize = cam->size;
+
+	if (newsize > MAX_FRAME_SIZE) {
+		DEBUG(1, "couldn't find size %d,%d", x, y);
+		return -EINVAL;
+	}
+
+	if (newsize == cam->size) {
+		DEBUG(1, "Nothing to do");
+		return 0;
+	}
+
+	qcm_stop_data(uvd);
+
+	if (cam->size != newsize) {
+		oldsize = cam->size;
+		cam->size = newsize;
+		ret = qcm_set_camera_size(uvd);
+		if (ret) {
+			err("Couldn't set camera size, err=%d",ret);
+			/* restore the original size */
+			cam->size = oldsize;
+			return ret;
+		}
+	}
+
+	/* Flush the input queue and clear any current frame in progress */
+
+	RingQueue_Flush(&uvd->dp);
+	if (uvd->curframe != -1) {
+		uvd->frame[uvd->curframe].curline = 0;
+		uvd->frame[uvd->curframe].seqRead_Length = 0;
+		uvd->frame[uvd->curframe].seqRead_Index = 0;
+	}
+
+	CHECK_RET(ret, qcm_start_data(uvd));
+	return 0;
+}
+
+static int qcm_configure_video(struct uvd *uvd)
+{
+	int ret;
+	memset(&uvd->vpic, 0, sizeof(uvd->vpic));
+	memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old));
+
+	uvd->vpic.colour = colour;
+	uvd->vpic.hue = hue;
+	uvd->vpic.brightness = brightness;
+	uvd->vpic.contrast = contrast;
+	uvd->vpic.whiteness = whiteness;
+	uvd->vpic.depth = 24;
+	uvd->vpic.palette = VIDEO_PALETTE_RGB24;
+
+	memset(&uvd->vcap, 0, sizeof(uvd->vcap));
+	strcpy(uvd->vcap.name, "QCM USB Camera");
+	uvd->vcap.type = VID_TYPE_CAPTURE;
+	uvd->vcap.channels = 1;
+	uvd->vcap.audios = 0;
+
+	uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width;
+	uvd->vcap.minheight = camera_sizes[SIZE_160X120].height;
+	uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width;
+	uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height;
+
+	memset(&uvd->vchan, 0, sizeof(uvd->vchan));
+	uvd->vchan.flags = 0 ;
+	uvd->vchan.tuners = 0;
+	uvd->vchan.channel = 0;
+	uvd->vchan.type = VIDEO_TYPE_CAMERA;
+	strcpy(uvd->vchan.name, "Camera");
+
+	CHECK_RET(ret, qcm_sensor_init(uvd));
+	return 0;
+}
+
+static int qcm_probe(struct usb_interface *intf,
+			const struct usb_device_id *devid)
+{
+	int err;
+	struct uvd *uvd;
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct qcm *cam;
+	size_t buffer_size;
+	unsigned char video_ep;
+	struct usb_host_interface *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	int i,j;
+	unsigned int ifacenum, ifacenum_inact=0;
+	__le16 sensor_id;
+
+	/* we don't support multiconfig cams */
+	if (dev->descriptor.bNumConfigurations != 1)
+		return -ENODEV;
+
+	/* first check for the video interface and not
+	* the audio interface */
+	interface = &intf->cur_altsetting[0];
+	if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+		|| (interface->desc.bInterfaceSubClass !=
+			USB_CLASS_VENDOR_SPEC))
+		return -ENODEV;
+
+	/*
+	walk through each endpoint in each setting in the interface
+	stop when we find the one that's an isochronous IN endpoint.
+	*/
+	for (i=0; i < intf->num_altsetting; i++) {
+		interface = &intf->cur_altsetting[i];
+		ifacenum = interface->desc.bAlternateSetting;
+		/* walk the end points */
+		for (j=0; j < interface->desc.bNumEndpoints; j++) {
+			endpoint = &interface->endpoint[j].desc;
+
+			if ((endpoint->bEndpointAddress &
+				USB_ENDPOINT_DIR_MASK) != USB_DIR_IN)
+				continue; /* not input then not good */
+
+			buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+			if (!buffer_size) {
+				ifacenum_inact = ifacenum;
+				continue; /* 0 pkt size is not what we want */
+			}
+
+			if ((endpoint->bmAttributes &
+				USB_ENDPOINT_XFERTYPE_MASK) ==
+				USB_ENDPOINT_XFER_ISOC) {
+				video_ep = endpoint->bEndpointAddress;
+				/* break out of the search */
+				goto good_videoep;
+			}
+		}
+	}
+	/* failed out since nothing useful was found */
+	err("No suitable endpoint was found\n");
+	return -ENODEV;
+
+good_videoep:
+	/* disable isochronous stream before doing anything else */
+	err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0);
+	if (err < 0) {
+		err("Failed to disable sensor stream");
+		return -EIO;
+	}
+
+	/*
+	Check that this is the same unknown sensor that is known to work. This
+	sensor is suspected to be the ST VV6422C001. I'll check the same value
+	that the qc-usb driver checks. This value is probably not even the
+	sensor ID since it matches the USB dev ID. Oh well. If it doesn't
+	match, it's probably a diff sensor so exit and apologize.
+	*/
+	err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id);
+	if (err < 0) {
+		err("Couldn't read sensor values. Err %d\n",err);
+		return err;
+	}
+	if (sensor_id != cpu_to_le16(0x08F0)) {
+		err("Sensor ID %x != %x. Unsupported. Sorry\n",
+			le16_to_cpu(sensor_id), (0x08F0));
+		return -ENODEV;
+	}
+
+	uvd = usbvideo_AllocateDevice(cams);
+	if (!uvd)
+		return -ENOMEM;
+
+	cam = (struct qcm *) uvd->user_data;
+
+	/* buf for doing demosaicing */
+	cam->scratch = kmalloc(324*2, GFP_KERNEL);
+	if (!cam->scratch) /* uvd freed in dereg */
+		return -ENOMEM;
+
+	/* yes, if we fail after here, cam->scratch gets freed
+	by qcm_free_uvd */
+
+	err = qcm_alloc_int_urb(cam);
+	if (err < 0)
+		return err;
+
+	/* yes, if we fail after here, int urb gets freed
+	by qcm_free_uvd */
+
+	RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240);
+	cam->width = camera_sizes[size].width;
+	cam->height = camera_sizes[size].height;
+	cam->size = size;
+
+	uvd->debug = debug;
+	uvd->flags = 0;
+	uvd->dev = dev;
+	uvd->iface = intf->altsetting->desc.bInterfaceNumber;
+	uvd->ifaceAltActive = ifacenum;
+	uvd->ifaceAltInactive = ifacenum_inact;
+	uvd->video_endp = video_ep;
+	uvd->iso_packet_len = buffer_size;
+	uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24;
+	uvd->defaultPalette = VIDEO_PALETTE_RGB24;
+	uvd->canvas = VIDEOSIZE(320, 240);
+	uvd->videosize = VIDEOSIZE(cam->width, cam->height);
+	err = qcm_configure_video(uvd);
+	if (err) {
+		err("failed to configure video settings");
+		return err;
+	}
+
+	err = usbvideo_RegisterVideoDevice(uvd);
+	if (err) { /* the uvd gets freed in Deregister */
+		err("usbvideo_RegisterVideoDevice() failed.");
+		return err;
+	}
+
+	uvd->max_frame_size = (320 * 240 * 3);
+	qcm_register_input(cam, dev);
+	usb_set_intfdata(intf, uvd);
+	return 0;
+}
+
+static void qcm_free_uvd(struct uvd *uvd)
+{
+	struct qcm *cam = (struct qcm *) uvd->user_data;
+
+	kfree(cam->scratch);
+	qcm_unregister_input(cam);
+	qcm_free_int(cam);
+}
+
+static struct usbvideo_cb qcm_driver = {
+	.probe = 		qcm_probe,
+	.setupOnOpen = 		qcm_setup_on_open,
+	.processData = 		qcm_process_isoc,
+	.setVideoMode = 	qcm_set_video_mode,
+	.startDataPump = 	qcm_start_data,
+	.stopDataPump = 	qcm_stop_data,
+	.adjustPicture = 	qcm_adjust_picture,
+	.userFree = 		qcm_free_uvd
+};
+
+static int __init qcm_init(void)
+{
+	info(DRIVER_DESC " " DRIVER_VERSION);
+
+	return usbvideo_register(
+		&cams,
+		MAX_CAMERAS,
+		sizeof(struct qcm),
+		"QCM",
+		&qcm_driver,
+		THIS_MODULE,
+		qcm_table);
+}
+
+static void __exit qcm_exit(void)
+{
+	usbvideo_Deregister(&cams);
+}
+
+module_param(size, int, 0);
+MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240");
+module_param(colour, int, 0);
+MODULE_PARM_DESC(colour, "Initial colour");
+module_param(hue, int, 0);
+MODULE_PARM_DESC(hue, "Initial hue");
+module_param(brightness, int, 0);
+MODULE_PARM_DESC(brightness, "Initial brightness");
+module_param(contrast, int, 0);
+MODULE_PARM_DESC(contrast, "Initial contrast");
+module_param(whiteness, int, 0);
+MODULE_PARM_DESC(whiteness, "Initial whiteness");
+
+#ifdef CONFIG_USB_DEBUG
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)");
+#endif
+
+module_init(qcm_init);
+module_exit(qcm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_DESCRIPTION("QCM USB Camera");
+MODULE_SUPPORTED_DEVICE("QCM USB Camera");
diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h
new file mode 100644
index 0000000..baab9c0
--- /dev/null
+++ b/drivers/media/video/usbvideo/quickcam_messenger.h
@@ -0,0 +1,126 @@
+#ifndef quickcam_messenger_h
+#define quickcam_messenger_h
+
+#ifndef CONFIG_INPUT
+/* if we're not using input we dummy out these functions */
+#define qcm_register_input(...)
+#define qcm_unregister_input(...)
+#define qcm_report_buttonstat(...)
+#define qcm_setup_input_int(...) 0
+#define qcm_stop_int_data(...)
+#define qcm_alloc_int_urb(...) 0
+#define qcm_free_int(...)
+#endif
+
+
+#define CHECK_RET(ret, expr) \
+	if ((ret = expr) < 0) return ret
+
+/* Control Registers for the STVV6422 ASIC
+ * - this define is taken from the qc-usb-messenger code
+ */
+#define STV_ISO_ENABLE		0x1440
+#define ISOC_PACKET_SIZE	1023
+
+/* Chip identification number including revision indicator */
+#define CMOS_SENSOR_IDREV	0xE00A
+
+struct rgb {
+	u8 b;
+	u8 g;
+	u8 r;
+	u8 b2;
+	u8 g2;
+	u8 r2;
+};
+
+struct bayL0 {
+#ifdef __BIG_ENDIAN
+	u8 r;
+	u8 g;
+#elif __LITTLE_ENDIAN
+	u8 g;
+	u8 r;
+#else
+#error not byte order defined
+#endif
+};
+
+struct bayL1 {
+#ifdef __BIG_ENDIAN
+	u8 g;
+	u8 b;
+#elif __LITTLE_ENDIAN
+	u8 b;
+	u8 g;
+#else
+#error not byte order defined
+#endif
+};
+
+struct cam_size {
+	u16	width;
+	u16	height;
+	u8	cmd;
+};
+
+static const struct cam_size camera_sizes[] = {
+	{ 160, 120, 0xf },
+	{ 320, 240, 0x2 },
+};
+
+enum frame_sizes {
+	SIZE_160X120	= 0,
+	SIZE_320X240	= 1,
+};
+
+#define MAX_FRAME_SIZE SIZE_320X240
+
+struct qcm {
+	u16 colour;
+	u16 hue;
+	u16 brightness;
+	u16 contrast;
+	u16 whiteness;
+
+	u8 size;
+	int height;
+	int width;
+	u8 *scratch;
+	struct urb *button_urb;
+	u8 button_sts;
+	u8 button_sts_buf;
+
+#ifdef CONFIG_INPUT
+	struct input_dev *input;
+	char input_physname[64];
+#endif
+};
+
+struct regval {
+	u16 reg;
+	u8 val;
+};
+/* this table is derived from the
+qc-usb-messenger code */
+static const struct regval regval_table[] = {
+	{ STV_ISO_ENABLE, 0x00 },
+	{ 0x1436, 0x00 }, { 0x1432, 0x03 },
+	{ 0x143a, 0xF9 }, { 0x0509, 0x38 },
+	{ 0x050a, 0x38 }, { 0x050b, 0x38 },
+	{ 0x050c, 0x2A }, { 0x050d, 0x01 },
+	{ 0x1431, 0x00 }, { 0x1433, 0x34 },
+	{ 0x1438, 0x18 }, { 0x1439, 0x00 },
+	{ 0x143b, 0x05 }, { 0x143c, 0x00 },
+	{ 0x143e, 0x01 }, { 0x143d, 0x00 },
+	{ 0x1442, 0xe2 }, { 0x1500, 0xd0 },
+	{ 0x1500, 0xd0 }, { 0x1500, 0x50 },
+	{ 0x1501, 0xaf }, { 0x1502, 0xc2 },
+	{ 0x1503, 0x45 }, { 0x1505, 0x02 },
+	{ 0x150e, 0x8e }, { 0x150f, 0x37 },
+	{ 0x15c0, 0x00 },
+};
+
+static const unsigned char marker[] = { 0x00, 0xff, 0x00, 0xFF };
+
+#endif /* quickcam_messenger_h */
diff --git a/drivers/media/video/usbvideo/usbvideo.h b/drivers/media/video/usbvideo/usbvideo.h
index 3cbf4fc..49dbee5 100644
--- a/drivers/media/video/usbvideo/usbvideo.h
+++ b/drivers/media/video/usbvideo/usbvideo.h
@@ -18,6 +18,7 @@
 
 #include <linux/config.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/usb.h>
 #include <linux/mutex.h>
 
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index 474a29b..19d3c20 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -32,6 +32,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c
index d330fa9..97f946db 100644
--- a/drivers/media/video/v4l2-common.c
+++ b/drivers/media/video/v4l2-common.c
@@ -59,6 +59,7 @@
 #include <asm/io.h>
 #include <asm/div64.h>
 #include <linux/video_decoder.h>
+#define __OLD_VIDIOC_ /* To allow fixing old calls*/
 #include <media/v4l2-common.h>
 
 #ifdef CONFIG_KMOD
@@ -293,7 +294,10 @@
 #if 1
 	[_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
 #endif
-	[_IOC_NR(VIDIOC_LOG_STATUS)]       = "VIDIOC_LOG_STATUS"
+	[_IOC_NR(VIDIOC_LOG_STATUS)]       = "VIDIOC_LOG_STATUS",
+	[_IOC_NR(VIDIOC_G_EXT_CTRLS)]      = "VIDIOC_G_EXT_CTRLS",
+	[_IOC_NR(VIDIOC_S_EXT_CTRLS)]      = "VIDIOC_S_EXT_CTRLS",
+	[_IOC_NR(VIDIOC_TRY_EXT_CTRLS)]    = "VIDIOC_TRY_EXT_CTRLS"
 };
 #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
 
@@ -331,7 +335,8 @@
 	[_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)]  = "VIDIOC_INT_S_AUDIO_ROUTING",
 	[_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)]  = "VIDIOC_INT_G_AUDIO_ROUTING",
 	[_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)]  = "VIDIOC_INT_S_VIDEO_ROUTING",
-	[_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING"
+	[_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)]  = "VIDIOC_INT_G_VIDEO_ROUTING",
+	[_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)]   = "VIDIOC_INT_S_CRYSTAL_FREQ"
 };
 #define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
 
@@ -423,7 +428,9 @@
 	case TUNER_SET_TYPE_ADDR:
 	case TUNER_SET_STANDBY:
 	case TDA9887_SET_CONFIG:
+#ifdef __OLD_VIDIOC_
 	case VIDIOC_OVERLAY_OLD:
+#endif
 	case VIDIOC_STREAMOFF:
 	case VIDIOC_G_OUTPUT:
 	case VIDIOC_S_OUTPUT:
@@ -439,7 +446,9 @@
 	case VIDIOC_G_AUDIO:
 	case VIDIOC_S_AUDIO:
 	case VIDIOC_ENUMAUDIO:
+#ifdef __OLD_VIDIOC_
 	case VIDIOC_G_AUDIO_OLD:
+#endif
 	{
 		struct v4l2_audio *p=arg;
 
@@ -450,7 +459,9 @@
 	case VIDIOC_G_AUDOUT:
 	case VIDIOC_S_AUDOUT:
 	case VIDIOC_ENUMAUDOUT:
+#ifdef __OLD_VIDIOC_
 	case VIDIOC_G_AUDOUT_OLD:
+#endif
 	{
 		struct v4l2_audioout *p=arg;
 		printk ("%s: index=%d, name=%s, capability=%d, mode=%d\n", s,
@@ -478,9 +489,9 @@
 				prt_names(p->memory,v4l2_memory_names),
 				p->m.userptr);
 		printk ("%s: timecode= %02d:%02d:%02d type=%d, "
-			"flags=0x%08x, frames=%d, userbits=0x%p\n",
+			"flags=0x%08x, frames=%d, userbits=0x%08x\n",
 				s,tc->hours,tc->minutes,tc->seconds,
-				tc->type, tc->flags, tc->frames, tc->userbits);
+				tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
 		break;
 	}
 	case VIDIOC_QUERYCAP:
@@ -495,12 +506,31 @@
 	}
 	case VIDIOC_G_CTRL:
 	case VIDIOC_S_CTRL:
+#ifdef __OLD_VIDIOC_
 	case VIDIOC_S_CTRL_OLD:
+#endif
 	{
 		struct v4l2_control *p=arg;
 		printk ("%s: id=%d, value=%d\n", s, p->id, p->value);
 		break;
 	}
+	case VIDIOC_G_EXT_CTRLS:
+	case VIDIOC_S_EXT_CTRLS:
+	case VIDIOC_TRY_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *p = arg;
+		int i;
+
+		printk("%s: ctrl_class=%d, count=%d\n", s, p->ctrl_class, p->count);
+		for (i = 0; i < p->count; i++) {
+			struct v4l2_ext_control *c = &p->controls[i];
+			if (cmd == VIDIOC_G_EXT_CTRLS)
+				printk("%s: id=%d\n", s, c->id);
+			else
+				printk("%s: id=%d, value=%d\n", s, c->id, c->value);
+		}
+		break;
+	}
 	case VIDIOC_G_CROP:
 	case VIDIOC_S_CROP:
 	{
@@ -510,7 +540,9 @@
 		break;
 	}
 	case VIDIOC_CROPCAP:
+#ifdef __OLD_VIDIOC_
 	case VIDIOC_CROPCAP_OLD:
+#endif
 	{
 		struct v4l2_cropcap *p=arg;
 		/*FIXME: Should also show rect structs */
@@ -667,6 +699,12 @@
 		printk ("%s: input=0x%x, output=0x%x\n", s, p->input, p->output);
 		break;
 	}
+	case VIDIOC_INT_S_CRYSTAL_FREQ:
+	{
+		struct v4l2_crystal_freq *p=arg;
+		printk ("%s: freq=%u, flags=0x%x\n", s, p->freq, p->flags);
+		break;
+	}
 	case VIDIOC_G_SLICED_VBI_CAP:
 	{
 		struct v4l2_sliced_vbi_cap *p=arg;
@@ -696,7 +734,9 @@
 	}
 	case VIDIOC_G_PARM:
 	case VIDIOC_S_PARM:
+#ifdef __OLD_VIDIOC_
 	case VIDIOC_S_PARM_OLD:
+#endif
 	{
 		struct v4l2_streamparm *p=arg;
 		printk ("%s: type=%d\n", s, p->type);
@@ -915,6 +955,498 @@
 
 /* ----------------------------------------------------------------- */
 
+/* Helper functions for control handling			     */
+
+/* Check for correctness of the ctrl's value based on the data from
+   struct v4l2_queryctrl and the available menu items. Note that
+   menu_items may be NULL, in that case it is ignored. */
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+		const char **menu_items)
+{
+	if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
+		return -EINVAL;
+	if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
+		return -EBUSY;
+	if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
+	    qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
+	    qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
+		return 0;
+	if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
+		return -ERANGE;
+	if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
+		if (menu_items[ctrl->value] == NULL ||
+		    menu_items[ctrl->value][0] == '\0')
+			return -EINVAL;
+	}
+	return 0;
+}
+
+/* Returns NULL or a character pointer array containing the menu for
+   the given control ID. The pointer array ends with a NULL pointer.
+   An empty string signifies a menu entry that is invalid. This allows
+   drivers to disable certain options if it is not supported. */
+const char **v4l2_ctrl_get_menu(u32 id)
+{
+	static const char *mpeg_audio_sampling_freq[] = {
+		"44.1 kHz",
+		"48 kHz",
+		"32 kHz",
+		NULL
+	};
+	static const char *mpeg_audio_encoding[] = {
+		"Layer I",
+		"Layer II",
+		"Layer III",
+		NULL
+	};
+	static const char *mpeg_audio_l1_bitrate[] = {
+		"32 kbps",
+		"64 kbps",
+		"96 kbps",
+		"128 kbps",
+		"160 kbps",
+		"192 kbps",
+		"224 kbps",
+		"256 kbps",
+		"288 kbps",
+		"320 kbps",
+		"352 kbps",
+		"384 kbps",
+		"416 kbps",
+		"448 kbps",
+		NULL
+	};
+	static const char *mpeg_audio_l2_bitrate[] = {
+		"32 kbps",
+		"48 kbps",
+		"56 kbps",
+		"64 kbps",
+		"80 kbps",
+		"96 kbps",
+		"112 kbps",
+		"128 kbps",
+		"160 kbps",
+		"192 kbps",
+		"224 kbps",
+		"256 kbps",
+		"320 kbps",
+		"384 kbps",
+		NULL
+	};
+	static const char *mpeg_audio_l3_bitrate[] = {
+		"32 kbps",
+		"40 kbps",
+		"48 kbps",
+		"56 kbps",
+		"64 kbps",
+		"80 kbps",
+		"96 kbps",
+		"112 kbps",
+		"128 kbps",
+		"160 kbps",
+		"192 kbps",
+		"224 kbps",
+		"256 kbps",
+		"320 kbps",
+		NULL
+	};
+	static const char *mpeg_audio_mode[] = {
+		"Stereo",
+		"Joint Stereo",
+		"Dual",
+		"Mono",
+		NULL
+	};
+	static const char *mpeg_audio_mode_extension[] = {
+		"Bound 4",
+		"Bound 8",
+		"Bound 12",
+		"Bound 16",
+		NULL
+	};
+	static const char *mpeg_audio_emphasis[] = {
+		"No Emphasis",
+		"50/15 us",
+		"CCITT J17",
+		NULL
+	};
+	static const char *mpeg_audio_crc[] = {
+		"No CRC",
+		"16-bit CRC",
+		NULL
+	};
+	static const char *mpeg_video_encoding[] = {
+		"MPEG-1",
+		"MPEG-2",
+		NULL
+	};
+	static const char *mpeg_video_aspect[] = {
+		"1x1",
+		"4x3",
+		"16x9",
+		"2.21x1",
+		NULL
+	};
+	static const char *mpeg_video_bitrate_mode[] = {
+		"Variable Bitrate",
+		"Constant Bitrate",
+		NULL
+	};
+	static const char *mpeg_stream_type[] = {
+		"MPEG-2 Program Stream",
+		"MPEG-2 Transport Stream",
+		"MPEG-1 System Stream",
+		"MPEG-2 DVD-compatible Stream",
+		"MPEG-1 VCD-compatible Stream",
+		"MPEG-2 SVCD-compatible Stream",
+		NULL
+	};
+	static const char *mpeg_stream_vbi_fmt[] = {
+		"No VBI",
+		"Private packet, IVTV format",
+		NULL
+	};
+
+	switch (id) {
+		case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+			return mpeg_audio_sampling_freq;
+		case V4L2_CID_MPEG_AUDIO_ENCODING:
+			return mpeg_audio_encoding;
+		case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+			return mpeg_audio_l1_bitrate;
+		case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+			return mpeg_audio_l2_bitrate;
+		case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+			return mpeg_audio_l3_bitrate;
+		case V4L2_CID_MPEG_AUDIO_MODE:
+			return mpeg_audio_mode;
+		case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+			return mpeg_audio_mode_extension;
+		case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+			return mpeg_audio_emphasis;
+		case V4L2_CID_MPEG_AUDIO_CRC:
+			return mpeg_audio_crc;
+		case V4L2_CID_MPEG_VIDEO_ENCODING:
+			return mpeg_video_encoding;
+		case V4L2_CID_MPEG_VIDEO_ASPECT:
+			return mpeg_video_aspect;
+		case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+			return mpeg_video_bitrate_mode;
+		case V4L2_CID_MPEG_STREAM_TYPE:
+			return mpeg_stream_type;
+		case V4L2_CID_MPEG_STREAM_VBI_FMT:
+			return mpeg_stream_vbi_fmt;
+		default:
+			return NULL;
+	}
+}
+
+/* Fill in a struct v4l2_queryctrl */
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+{
+	const char *name;
+
+	qctrl->flags = 0;
+	switch (qctrl->id) {
+	/* USER controls */
+	case V4L2_CID_USER_CLASS: 	name = "User Controls"; break;
+	case V4L2_CID_AUDIO_VOLUME: 	name = "Volume"; break;
+	case V4L2_CID_AUDIO_MUTE: 	name = "Mute"; break;
+	case V4L2_CID_AUDIO_BALANCE: 	name = "Balance"; break;
+	case V4L2_CID_AUDIO_BASS: 	name = "Bass"; break;
+	case V4L2_CID_AUDIO_TREBLE: 	name = "Treble"; break;
+	case V4L2_CID_AUDIO_LOUDNESS: 	name = "Loudness"; break;
+	case V4L2_CID_BRIGHTNESS: 	name = "Brightness"; break;
+	case V4L2_CID_CONTRAST: 	name = "Contrast"; break;
+	case V4L2_CID_SATURATION: 	name = "Saturation"; break;
+	case V4L2_CID_HUE: 		name = "Hue"; break;
+
+	/* MPEG controls */
+	case V4L2_CID_MPEG_CLASS: 		name = "MPEG Encoder Controls"; break;
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: name = "Audio Sampling Frequency"; break;
+	case V4L2_CID_MPEG_AUDIO_ENCODING: 	name = "Audio Encoding Layer"; break;
+	case V4L2_CID_MPEG_AUDIO_L1_BITRATE: 	name = "Audio Layer I Bitrate"; break;
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE: 	name = "Audio Layer II Bitrate"; break;
+	case V4L2_CID_MPEG_AUDIO_L3_BITRATE: 	name = "Audio Layer III Bitrate"; break;
+	case V4L2_CID_MPEG_AUDIO_MODE: 		name = "Audio Stereo Mode"; break;
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: name = "Audio Stereo Mode Extension"; break;
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS: 	name = "Audio Emphasis"; break;
+	case V4L2_CID_MPEG_AUDIO_CRC: 		name = "Audio CRC"; break;
+	case V4L2_CID_MPEG_VIDEO_ENCODING: 	name = "Video Encoding"; break;
+	case V4L2_CID_MPEG_VIDEO_ASPECT: 	name = "Video Aspect"; break;
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES: 	name = "Video B Frames"; break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE: 	name = "Video GOP Size"; break;
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: 	name = "Video GOP Closure"; break;
+	case V4L2_CID_MPEG_VIDEO_PULLDOWN: 	name = "Video Pulldown"; break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: 	name = "Video Bitrate Mode"; break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE: 	name = "Video Bitrate"; break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: 	name = "Video Peak Bitrate"; break;
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: name = "Video Temporal Decimation"; break;
+	case V4L2_CID_MPEG_STREAM_TYPE: 	name = "Stream Type"; break;
+	case V4L2_CID_MPEG_STREAM_PID_PMT: 	name = "Stream PMT Program ID"; break;
+	case V4L2_CID_MPEG_STREAM_PID_AUDIO: 	name = "Stream Audio Program ID"; break;
+	case V4L2_CID_MPEG_STREAM_PID_VIDEO: 	name = "Stream Video Program ID"; break;
+	case V4L2_CID_MPEG_STREAM_PID_PCR: 	name = "Stream PCR Program ID"; break;
+	case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: name = "Stream PES Audio ID"; break;
+	case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: name = "Stream PES Video ID"; break;
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:	name = "Stream VBI Format"; break;
+
+	default:
+		return -EINVAL;
+	}
+	switch (qctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+	case V4L2_CID_AUDIO_LOUDNESS:
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+		qctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
+		min = 0;
+		max = step = 1;
+		break;
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+	case V4L2_CID_MPEG_AUDIO_MODE:
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+	case V4L2_CID_MPEG_AUDIO_CRC:
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+	case V4L2_CID_MPEG_STREAM_TYPE:
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		qctrl->type = V4L2_CTRL_TYPE_MENU;
+		step = 1;
+		break;
+	case V4L2_CID_USER_CLASS:
+	case V4L2_CID_MPEG_CLASS:
+		qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS;
+		qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+		min = max = step = def = 0;
+		break;
+	default:
+		qctrl->type = V4L2_CTRL_TYPE_INTEGER;
+		break;
+	}
+	switch (qctrl->id) {
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+	case V4L2_CID_MPEG_AUDIO_MODE:
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		qctrl->flags |= V4L2_CTRL_FLAG_UPDATE;
+		break;
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+	case V4L2_CID_BRIGHTNESS:
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+	case V4L2_CID_HUE:
+		qctrl->flags |= V4L2_CTRL_FLAG_SLIDER;
+		break;
+	}
+	qctrl->minimum = min;
+	qctrl->maximum = max;
+	qctrl->step = step;
+	qctrl->default_value = def;
+	qctrl->reserved[0] = qctrl->reserved[1] = 0;
+	snprintf(qctrl->name, sizeof(qctrl->name), name);
+	return 0;
+}
+
+/* Fill in a struct v4l2_queryctrl with standard values based on
+   the control ID. */
+int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl)
+{
+	switch (qctrl->id) {
+	/* USER controls */
+	case V4L2_CID_USER_CLASS:
+	case V4L2_CID_MPEG_CLASS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 0, 0, 0);
+	case V4L2_CID_AUDIO_VOLUME:
+		return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 58880);
+	case V4L2_CID_AUDIO_MUTE:
+	case V4L2_CID_AUDIO_LOUDNESS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+	case V4L2_CID_AUDIO_BALANCE:
+	case V4L2_CID_AUDIO_BASS:
+	case V4L2_CID_AUDIO_TREBLE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 65535, 65535 / 100, 32768);
+	case V4L2_CID_BRIGHTNESS:
+		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128);
+	case V4L2_CID_CONTRAST:
+	case V4L2_CID_SATURATION:
+		return v4l2_ctrl_query_fill(qctrl, 0, 127, 1, 64);
+	case V4L2_CID_HUE:
+		return v4l2_ctrl_query_fill(qctrl, -128, 127, 1, 0);
+
+	/* MPEG controls */
+	case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000, 1,
+				V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000);
+	case V4L2_CID_MPEG_AUDIO_ENCODING:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_1,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_3, 1,
+				V4L2_MPEG_AUDIO_ENCODING_LAYER_2);
+	case V4L2_CID_MPEG_AUDIO_L1_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_L1_BITRATE_32K,
+				V4L2_MPEG_AUDIO_L1_BITRATE_448K, 1,
+				V4L2_MPEG_AUDIO_L1_BITRATE_256K);
+	case V4L2_CID_MPEG_AUDIO_L2_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_L2_BITRATE_32K,
+				V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1,
+				V4L2_MPEG_AUDIO_L2_BITRATE_224K);
+	case V4L2_CID_MPEG_AUDIO_L3_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_L3_BITRATE_32K,
+				V4L2_MPEG_AUDIO_L3_BITRATE_320K, 1,
+				V4L2_MPEG_AUDIO_L3_BITRATE_192K);
+	case V4L2_CID_MPEG_AUDIO_MODE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_MODE_STEREO,
+				V4L2_MPEG_AUDIO_MODE_MONO, 1,
+				V4L2_MPEG_AUDIO_MODE_STEREO);
+	case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4,
+				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16, 1,
+				V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4);
+	case V4L2_CID_MPEG_AUDIO_EMPHASIS:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_EMPHASIS_NONE,
+				V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17, 1,
+				V4L2_MPEG_AUDIO_EMPHASIS_NONE);
+	case V4L2_CID_MPEG_AUDIO_CRC:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_AUDIO_CRC_NONE,
+				V4L2_MPEG_AUDIO_CRC_CRC16, 1,
+				V4L2_MPEG_AUDIO_CRC_NONE);
+	case V4L2_CID_MPEG_VIDEO_ENCODING:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_1,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2, 1,
+				V4L2_MPEG_VIDEO_ENCODING_MPEG_2);
+	case V4L2_CID_MPEG_VIDEO_ASPECT:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_ASPECT_1x1,
+				V4L2_MPEG_VIDEO_ASPECT_221x100, 1,
+				V4L2_MPEG_VIDEO_ASPECT_4x3);
+	case V4L2_CID_MPEG_VIDEO_B_FRAMES:
+		return v4l2_ctrl_query_fill(qctrl, 0, 33, 1, 2);
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		return v4l2_ctrl_query_fill(qctrl, 1, 34, 1, 12);
+	case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
+	case V4L2_CID_MPEG_VIDEO_PULLDOWN:
+		return v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 0);
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 1,
+				V4L2_MPEG_VIDEO_BITRATE_MODE_VBR);
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 6000000);
+	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
+		return v4l2_ctrl_query_fill(qctrl, 0, 27000000, 1, 8000000);
+	case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION:
+		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+	case V4L2_CID_MPEG_STREAM_TYPE:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD, 1,
+				V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
+	case V4L2_CID_MPEG_STREAM_PID_PMT:
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 16);
+	case V4L2_CID_MPEG_STREAM_PID_AUDIO:
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 260);
+	case V4L2_CID_MPEG_STREAM_PID_VIDEO:
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 256);
+	case V4L2_CID_MPEG_STREAM_PID_PCR:
+		return v4l2_ctrl_query_fill(qctrl, 0, (1 << 14) - 1, 1, 259);
+	case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO:
+		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+	case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO:
+		return v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 0);
+	case V4L2_CID_MPEG_STREAM_VBI_FMT:
+		return v4l2_ctrl_query_fill(qctrl,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE,
+				V4L2_MPEG_STREAM_VBI_FMT_IVTV, 1,
+				V4L2_MPEG_STREAM_VBI_FMT_NONE);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
+   the menu. The qctrl pointer may be NULL, in which case it is ignored. */
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
+	       const char **menu_items)
+{
+	int i;
+
+	if (menu_items == NULL ||
+	    (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
+		return -EINVAL;
+	for (i = 0; i < qmenu->index && menu_items[i]; i++) ;
+	if (menu_items[i] == NULL || menu_items[i][0] == '\0')
+		return -EINVAL;
+	snprintf(qmenu->name, sizeof(qmenu->name), menu_items[qmenu->index]);
+	qmenu->reserved = 0;
+	return 0;
+}
+
+/* ctrl_classes points to an array of u32 pointers, the last element is
+   a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
+   Each array must be sorted low to high and belong to the same control
+   class. The array of u32 pointer must also be sorted, from low class IDs
+   to high class IDs.
+
+   This function returns the first ID that follows after the given ID.
+   When no more controls are available 0 is returned. */
+u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
+{
+	u32 ctrl_class;
+	const u32 *pctrl;
+
+	/* if no query is desired, then just return the control ID */
+	if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0)
+		return id;
+	if (ctrl_classes == NULL)
+		return 0;
+	id &= V4L2_CTRL_ID_MASK;
+	ctrl_class = V4L2_CTRL_ID2CLASS(id);
+	id++;	/* select next control */
+	/* find first class that matches (or is greater than) the class of
+	   the ID */
+	while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class)
+		ctrl_classes++;
+	/* no more classes */
+	if (*ctrl_classes == NULL)
+		return 0;
+	pctrl = *ctrl_classes;
+	/* find first ctrl within the class that is >= ID */
+	while (*pctrl && *pctrl < id) pctrl++;
+	if (*pctrl)
+		return *pctrl;
+	/* we are at the end of the controls of the current class. */
+	/* continue with next class if available */
+	ctrl_classes++;
+	if (*ctrl_classes == NULL)
+		return 0;
+	return **ctrl_classes;
+}
+
+/* ----------------------------------------------------------------- */
+
 EXPORT_SYMBOL(v4l2_video_std_construct);
 
 EXPORT_SYMBOL(v4l2_prio_init);
@@ -929,6 +1461,13 @@
 EXPORT_SYMBOL(v4l_printk_ioctl);
 EXPORT_SYMBOL(v4l_printk_ioctl_arg);
 
+EXPORT_SYMBOL(v4l2_ctrl_next);
+EXPORT_SYMBOL(v4l2_ctrl_check);
+EXPORT_SYMBOL(v4l2_ctrl_get_menu);
+EXPORT_SYMBOL(v4l2_ctrl_query_menu);
+EXPORT_SYMBOL(v4l2_ctrl_query_fill);
+EXPORT_SYMBOL(v4l2_ctrl_query_fill_std);
+
 /*
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index caf3e7e..7ee8a53 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -135,14 +135,15 @@
 
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
 			  struct module *module,
-			  void *adapter_priv)
+			  void *adapter_priv,
+			  struct device *device)
 {
 	int result;
 
 	mutex_init(&dvb->lock);
 
 	/* register adapter */
-	result = dvb_register_adapter(&dvb->adapter, dvb->name, module);
+	result = dvb_register_adapter(&dvb->adapter, dvb->name, module, device);
 	if (result < 0) {
 		printk(KERN_WARNING "%s: dvb_register_adapter failed (errno = %d)\n",
 		       dvb->name, result);
diff --git a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
index 5f87dd5..2dfa7f2 100644
--- a/drivers/media/video/videodev.c
+++ b/drivers/media/video/videodev.c
@@ -1,20 +1,31 @@
 /*
- * Video capture interface for Linux
+ * Video capture interface for Linux version 2
  *
- *		A generic video device interface for the LINUX operating system
- *		using a set of device structures/vectors for low level operations.
+ *	A generic video device interface for the LINUX operating system
+ *	using a set of device structures/vectors for low level operations.
  *
- *		This program is free software; you can redistribute it and/or
- *		modify it under the terms of the GNU General Public License
- *		as published by the Free Software Foundation; either version
- *		2 of the License, or (at your option) any later version.
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
  *
- * Author:	Alan Cox, <alan@redhat.com>
+ * Authors:	Alan Cox, <alan@redhat.com> (version 1)
+ *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
  *
  * Fixes:	20000516  Claudio Matsuoka <claudio@conectiva.com>
  *		- Added procfs support
  */
 
+#define dbgarg(cmd, fmt, arg...) \
+		if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)			\
+			printk (KERN_DEBUG "%s: ",  vfd->name);		\
+			v4l_printk_ioctl(cmd);				\
+			printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+
+#define dbgarg2(fmt, arg...) \
+		if (vfd->debug & V4L2_DEBUG_IOCTL_ARG)			\
+			printk (KERN_DEBUG "%s: " fmt, vfd->name, ## arg);
+
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -30,7 +41,13 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#define __OLD_VIDIOC_ /* To allow fixing old calls*/
+#include <linux/videodev2.h>
+
+#ifdef CONFIG_VIDEO_V4L1
 #include <linux/videodev.h>
+#endif
+#include <media/v4l2-common.h>
 
 #define VIDEO_NUM_DEVICES	256
 #define VIDEO_NAME              "video4linux"
@@ -41,7 +58,8 @@
 
 static ssize_t show_name(struct class_device *cd, char *buf)
 {
-	struct video_device *vfd = container_of(cd, struct video_device, class_dev);
+	struct video_device *vfd = container_of(cd, struct video_device,
+								class_dev);
 	return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name);
 }
 
@@ -62,7 +80,8 @@
 
 static void video_release(struct class_device *cd)
 {
-	struct video_device *vfd = container_of(cd, struct video_device, class_dev);
+	struct video_device *vfd = container_of(cd, struct video_device,
+								class_dev);
 
 #if 1
 	/* needed until all drivers are fixed */
@@ -90,7 +109,7 @@
 }
 
 /*
- *	Open a video device.
+ *	Open a video device - FIXME: Obsoleted
  */
 static int video_open(struct inode *inode, struct file *file)
 {
@@ -130,6 +149,7 @@
  * helper function -- handles userspace copying for ioctl arguments
  */
 
+#ifdef __OLD_VIDIOC_
 static unsigned int
 video_fix_command(unsigned int cmd)
 {
@@ -155,7 +175,11 @@
 	}
 	return cmd;
 }
+#endif
 
+/*
+ * Obsolete usercopy function - Should be removed soon
+ */
 int
 video_usercopy(struct inode *inode, struct file *file,
 	       unsigned int cmd, unsigned long arg,
@@ -166,8 +190,1218 @@
 	void    *mbuf = NULL;
 	void	*parg = NULL;
 	int	err  = -EINVAL;
+	int     is_ext_ctrl;
+	size_t  ctrls_size = 0;
+	void __user *user_ptr = NULL;
 
+#ifdef __OLD_VIDIOC_
 	cmd = video_fix_command(cmd);
+#endif
+	is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+		       cmd == VIDIOC_TRY_EXT_CTRLS);
+
+	/*  Copy arguments into temp kernel buffer  */
+	switch (_IOC_DIR(cmd)) {
+	case _IOC_NONE:
+		parg = NULL;
+		break;
+	case _IOC_READ:
+	case _IOC_WRITE:
+	case (_IOC_WRITE | _IOC_READ):
+		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+			parg = sbuf;
+		} else {
+			/* too big to allocate from stack */
+			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
+			if (NULL == mbuf)
+				return -ENOMEM;
+			parg = mbuf;
+		}
+
+		err = -EFAULT;
+		if (_IOC_DIR(cmd) & _IOC_WRITE)
+			if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
+				goto out;
+		break;
+	}
+	if (is_ext_ctrl) {
+		struct v4l2_ext_controls *p = parg;
+
+		/* In case of an error, tell the caller that it wasn't
+		   a specific control that caused it. */
+		p->error_idx = p->count;
+		user_ptr = (void __user *)p->controls;
+		if (p->count) {
+			ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
+			/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
+			mbuf = kmalloc(ctrls_size, GFP_KERNEL);
+			err = -ENOMEM;
+			if (NULL == mbuf)
+				goto out_ext_ctrl;
+			err = -EFAULT;
+			if (copy_from_user(mbuf, user_ptr, ctrls_size))
+				goto out_ext_ctrl;
+			p->controls = mbuf;
+		}
+	}
+
+	/* call driver */
+	err = func(inode, file, cmd, parg);
+	if (err == -ENOIOCTLCMD)
+		err = -EINVAL;
+	if (is_ext_ctrl) {
+		struct v4l2_ext_controls *p = parg;
+
+		p->controls = (void *)user_ptr;
+		if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+			err = -EFAULT;
+		goto out_ext_ctrl;
+	}
+	if (err < 0)
+		goto out;
+
+out_ext_ctrl:
+	/*  Copy results into user buffer  */
+	switch (_IOC_DIR(cmd))
+	{
+	case _IOC_READ:
+	case (_IOC_WRITE | _IOC_READ):
+		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
+			err = -EFAULT;
+		break;
+	}
+
+out:
+	kfree(mbuf);
+	return err;
+}
+
+/*
+ * open/release helper functions -- handle exclusive opens
+ * Should be removed soon
+ */
+int video_exclusive_open(struct inode *inode, struct file *file)
+{
+	struct  video_device *vfl = video_devdata(file);
+	int retval = 0;
+
+	mutex_lock(&vfl->lock);
+	if (vfl->users) {
+		retval = -EBUSY;
+	} else {
+		vfl->users++;
+	}
+	mutex_unlock(&vfl->lock);
+	return retval;
+}
+
+int video_exclusive_release(struct inode *inode, struct file *file)
+{
+	struct  video_device *vfl = video_devdata(file);
+
+	vfl->users--;
+	return 0;
+}
+
+static char *v4l2_memory_names[] = {
+	[V4L2_MEMORY_MMAP]    = "mmap",
+	[V4L2_MEMORY_USERPTR] = "userptr",
+	[V4L2_MEMORY_OVERLAY] = "overlay",
+};
+
+
+/* FIXME: Those stuff are replicated also on v4l2-common.c */
+static char *v4l2_type_names_FIXME[] = {
+	[V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "video-cap",
+	[V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "video-over",
+	[V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "video-out",
+	[V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
+	[V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
+	[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
+	[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-capture",
+	[V4L2_BUF_TYPE_PRIVATE]            = "private",
+};
+
+static char *v4l2_field_names_FIXME[] = {
+	[V4L2_FIELD_ANY]        = "any",
+	[V4L2_FIELD_NONE]       = "none",
+	[V4L2_FIELD_TOP]        = "top",
+	[V4L2_FIELD_BOTTOM]     = "bottom",
+	[V4L2_FIELD_INTERLACED] = "interlaced",
+	[V4L2_FIELD_SEQ_TB]     = "seq-tb",
+	[V4L2_FIELD_SEQ_BT]     = "seq-bt",
+	[V4L2_FIELD_ALTERNATE]  = "alternate",
+};
+
+#define prt_names(a,arr) (((a)>=0)&&((a)<ARRAY_SIZE(arr)))?arr[a]:"unknown"
+
+static void dbgbuf(unsigned int cmd, struct video_device *vfd,
+					struct v4l2_buffer *p)
+{
+	struct v4l2_timecode *tc=&p->timecode;
+
+	dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
+		"bytesused=%d, flags=0x%08d, "
+		"field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx\n",
+			(p->timestamp.tv_sec/3600),
+			(int)(p->timestamp.tv_sec/60)%60,
+			(int)(p->timestamp.tv_sec%60),
+			p->timestamp.tv_usec,
+			p->index,
+			prt_names(p->type,v4l2_type_names_FIXME),
+			p->bytesused,p->flags,
+			p->field,p->sequence,
+			prt_names(p->memory,v4l2_memory_names),
+			p->m.userptr);
+	dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "
+		"flags=0x%08d, frames=%d, userbits=0x%08x\n",
+			tc->hours,tc->minutes,tc->seconds,
+			tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);
+}
+
+static inline void dbgrect(struct video_device *vfd, char *s,
+							struct v4l2_rect *r)
+{
+	dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top,
+						r->width, r->height);
+};
+
+static inline void v4l_print_pix_fmt (struct video_device *vfd,
+						struct v4l2_pix_format *fmt)
+{
+	dbgarg2 ("width=%d, height=%d, format=0x%08x, field=%s, "
+		"bytesperline=%d sizeimage=%d, colorspace=%d\n",
+		fmt->width,fmt->height,fmt->pixelformat,
+		prt_names(fmt->field,v4l2_field_names_FIXME),
+		fmt->bytesperline,fmt->sizeimage,fmt->colorspace);
+};
+
+
+static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		if (vfd->vidioc_try_fmt_cap)
+			return (0);
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+		if (vfd->vidioc_try_fmt_overlay)
+			return (0);
+		break;
+	case V4L2_BUF_TYPE_VBI_CAPTURE:
+		if (vfd->vidioc_try_fmt_vbi)
+			return (0);
+		break;
+	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+		if (vfd->vidioc_try_fmt_vbi_output)
+			return (0);
+		break;
+	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+		if (vfd->vidioc_try_fmt_vbi_capture)
+			return (0);
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+		if (vfd->vidioc_try_fmt_video_output)
+			return (0);
+		break;
+	case V4L2_BUF_TYPE_VBI_OUTPUT:
+		if (vfd->vidioc_try_fmt_vbi_output)
+			return (0);
+		break;
+	case V4L2_BUF_TYPE_PRIVATE:
+		if (vfd->vidioc_try_fmt_type_private)
+			return (0);
+		break;
+	}
+	return (-EINVAL);
+}
+
+static int __video_do_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, void *arg)
+{
+	struct video_device *vfd = video_devdata(file);
+	void                 *fh = file->private_data;
+	int                  ret = -EINVAL;
+
+	if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&
+				!(vfd->debug | V4L2_DEBUG_IOCTL_ARG)) {
+		v4l_print_ioctl(vfd->name, cmd);
+	}
+
+	switch(cmd) {
+	/* --- capabilities ------------------------------------------ */
+	case VIDIOC_QUERYCAP:
+	{
+		struct v4l2_capability *cap = (struct v4l2_capability*)arg;
+		memset(cap, 0, sizeof(*cap));
+
+		if (!vfd->vidioc_querycap)
+			break;
+
+		ret=vfd->vidioc_querycap(file, fh, cap);
+		if (!ret)
+			dbgarg (cmd, "driver=%s, card=%s, bus=%s, "
+					"version=0x%08x, "
+					"capabilities=0x%08x\n",
+					cap->driver,cap->card,cap->bus_info,
+					cap->version,
+					cap->capabilities);
+		break;
+	}
+
+	/* --- priority ------------------------------------------ */
+	case VIDIOC_G_PRIORITY:
+	{
+		enum v4l2_priority *p=arg;
+
+		if (!vfd->vidioc_g_priority)
+			break;
+		ret=vfd->vidioc_g_priority(file, fh, p);
+		if (!ret)
+			dbgarg(cmd, "priority is %d\n", *p);
+		break;
+	}
+	case VIDIOC_S_PRIORITY:
+	{
+		enum v4l2_priority *p=arg;
+
+		if (!vfd->vidioc_s_priority)
+			break;
+		dbgarg(cmd, "setting priority to %d\n", *p);
+		ret=vfd->vidioc_s_priority(file, fh, *p);
+		break;
+	}
+
+	/* --- capture ioctls ---------------------------------------- */
+	case VIDIOC_ENUM_FMT:
+	{
+		struct v4l2_fmtdesc *f = arg;
+		enum v4l2_buf_type type;
+		unsigned int index;
+
+		index = f->index;
+		type  = f->type;
+		memset(f,0,sizeof(*f));
+		f->index = index;
+		f->type  = type;
+
+		switch (type) {
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+			if (vfd->vidioc_enum_fmt_cap)
+				ret=vfd->vidioc_enum_fmt_cap(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+			if (vfd->vidioc_enum_fmt_overlay)
+				ret=vfd->vidioc_enum_fmt_overlay(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_CAPTURE:
+			if (vfd->vidioc_enum_fmt_vbi)
+				ret=vfd->vidioc_enum_fmt_vbi(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+			if (vfd->vidioc_enum_fmt_vbi_output)
+				ret=vfd->vidioc_enum_fmt_vbi_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+			if (vfd->vidioc_enum_fmt_vbi_capture)
+				ret=vfd->vidioc_enum_fmt_vbi_capture(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+			if (vfd->vidioc_enum_fmt_video_output)
+				ret=vfd->vidioc_enum_fmt_video_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_OUTPUT:
+			if (vfd->vidioc_enum_fmt_vbi_output)
+				ret=vfd->vidioc_enum_fmt_vbi_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_PRIVATE:
+			if (vfd->vidioc_enum_fmt_type_private)
+				ret=vfd->vidioc_enum_fmt_type_private(file,
+								fh, f);
+			break;
+		}
+		if (!ret)
+			dbgarg (cmd, "index=%d, type=%d, flags=%d, "
+					"description=%s,"
+					" pixelformat=0x%8x\n",
+					f->index, f->type, f->flags,
+					f->description,
+					f->pixelformat);
+
+		break;
+	}
+	case VIDIOC_G_FMT:
+	{
+		struct v4l2_format *f = (struct v4l2_format *)arg;
+		enum v4l2_buf_type type=f->type;
+
+		memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
+		f->type=type;
+
+		/* FIXME: Should be one dump per type */
+		dbgarg (cmd, "type=%s\n", prt_names(type,
+					v4l2_type_names_FIXME));
+
+		switch (type) {
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+			if (vfd->vidioc_g_fmt_cap)
+				ret=vfd->vidioc_g_fmt_cap(file, fh, f);
+			if (!ret)
+				v4l_print_pix_fmt(vfd,&f->fmt.pix);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+			if (vfd->vidioc_g_fmt_overlay)
+				ret=vfd->vidioc_g_fmt_overlay(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_CAPTURE:
+			if (vfd->vidioc_g_fmt_vbi)
+				ret=vfd->vidioc_g_fmt_vbi(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+			if (vfd->vidioc_g_fmt_vbi_output)
+				ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+			if (vfd->vidioc_g_fmt_vbi_capture)
+				ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+			if (vfd->vidioc_g_fmt_video_output)
+				ret=vfd->vidioc_g_fmt_video_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_OUTPUT:
+			if (vfd->vidioc_g_fmt_vbi_output)
+				ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_PRIVATE:
+			if (vfd->vidioc_g_fmt_type_private)
+				ret=vfd->vidioc_g_fmt_type_private(file,
+								fh, f);
+			break;
+		}
+
+		break;
+	}
+	case VIDIOC_S_FMT:
+	{
+		struct v4l2_format *f = (struct v4l2_format *)arg;
+
+		/* FIXME: Should be one dump per type */
+		dbgarg (cmd, "type=%s\n", prt_names(f->type,
+					v4l2_type_names_FIXME));
+
+		switch (f->type) {
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+			v4l_print_pix_fmt(vfd,&f->fmt.pix);
+			if (vfd->vidioc_s_fmt_cap)
+				ret=vfd->vidioc_s_fmt_cap(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+			if (vfd->vidioc_s_fmt_overlay)
+				ret=vfd->vidioc_s_fmt_overlay(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_CAPTURE:
+			if (vfd->vidioc_s_fmt_vbi)
+				ret=vfd->vidioc_s_fmt_vbi(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+			if (vfd->vidioc_s_fmt_vbi_output)
+				ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+			if (vfd->vidioc_s_fmt_vbi_capture)
+				ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+			if (vfd->vidioc_s_fmt_video_output)
+				ret=vfd->vidioc_s_fmt_video_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_OUTPUT:
+			if (vfd->vidioc_s_fmt_vbi_output)
+				ret=vfd->vidioc_s_fmt_vbi_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_PRIVATE:
+			if (vfd->vidioc_s_fmt_type_private)
+				ret=vfd->vidioc_s_fmt_type_private(file,
+								fh, f);
+			break;
+		}
+		break;
+	}
+	case VIDIOC_TRY_FMT:
+	{
+		struct v4l2_format *f = (struct v4l2_format *)arg;
+
+		/* FIXME: Should be one dump per type */
+		dbgarg (cmd, "type=%s\n", prt_names(f->type,
+						v4l2_type_names_FIXME));
+		switch (f->type) {
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+			if (vfd->vidioc_try_fmt_cap)
+				ret=vfd->vidioc_try_fmt_cap(file, fh, f);
+			if (!ret)
+				v4l_print_pix_fmt(vfd,&f->fmt.pix);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+			if (vfd->vidioc_try_fmt_overlay)
+				ret=vfd->vidioc_try_fmt_overlay(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_CAPTURE:
+			if (vfd->vidioc_try_fmt_vbi)
+				ret=vfd->vidioc_try_fmt_vbi(file, fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+			if (vfd->vidioc_try_fmt_vbi_output)
+				ret=vfd->vidioc_try_fmt_vbi_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+			if (vfd->vidioc_try_fmt_vbi_capture)
+				ret=vfd->vidioc_try_fmt_vbi_capture(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+			if (vfd->vidioc_try_fmt_video_output)
+				ret=vfd->vidioc_try_fmt_video_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_VBI_OUTPUT:
+			if (vfd->vidioc_try_fmt_vbi_output)
+				ret=vfd->vidioc_try_fmt_vbi_output(file,
+								fh, f);
+			break;
+		case V4L2_BUF_TYPE_PRIVATE:
+			if (vfd->vidioc_try_fmt_type_private)
+				ret=vfd->vidioc_try_fmt_type_private(file,
+								fh, f);
+			break;
+		}
+
+		break;
+	}
+	/* FIXME: Those buf reqs could be handled here,
+	   with some changes on videobuf to allow its header to be included at
+	   videodev2.h or being merged at videodev2.
+	 */
+	case VIDIOC_REQBUFS:
+	{
+		struct v4l2_requestbuffers *p=arg;
+
+		if (!vfd->vidioc_reqbufs)
+			break;
+		ret = check_fmt (vfd, p->type);
+		if (ret)
+			break;
+
+		ret=vfd->vidioc_reqbufs(file, fh, p);
+		dbgarg (cmd, "count=%d, type=%s, memory=%s\n",
+				p->count,
+				prt_names(p->type,v4l2_type_names_FIXME),
+				prt_names(p->memory,v4l2_memory_names));
+		break;
+	}
+	case VIDIOC_QUERYBUF:
+	{
+		struct v4l2_buffer *p=arg;
+
+		if (!vfd->vidioc_querybuf)
+			break;
+		ret = check_fmt (vfd, p->type);
+		if (ret)
+			break;
+
+		ret=vfd->vidioc_querybuf(file, fh, p);
+		if (!ret)
+			dbgbuf(cmd,vfd,p);
+		break;
+	}
+	case VIDIOC_QBUF:
+	{
+		struct v4l2_buffer *p=arg;
+
+		if (!vfd->vidioc_qbuf)
+			break;
+		ret = check_fmt (vfd, p->type);
+		if (ret)
+			break;
+
+		ret=vfd->vidioc_qbuf(file, fh, p);
+		if (!ret)
+			dbgbuf(cmd,vfd,p);
+		break;
+	}
+	case VIDIOC_DQBUF:
+	{
+		struct v4l2_buffer *p=arg;
+		if (!vfd->vidioc_qbuf)
+			break;
+		ret = check_fmt (vfd, p->type);
+		if (ret)
+			break;
+
+		ret=vfd->vidioc_qbuf(file, fh, p);
+		if (!ret)
+			dbgbuf(cmd,vfd,p);
+		break;
+	}
+	case VIDIOC_OVERLAY:
+	{
+		int *i = arg;
+
+		if (!vfd->vidioc_overlay)
+			break;
+		dbgarg (cmd, "value=%d\n",*i);
+		ret=vfd->vidioc_overlay(file, fh, *i);
+		break;
+	}
+#ifdef HAVE_V4L1
+	/* --- streaming capture ------------------------------------- */
+	case VIDIOCGMBUF:
+	{
+		struct video_mbuf *p=arg;
+
+		memset(p,0,sizeof(p));
+
+		if (!vfd->vidiocgmbuf)
+			break;
+		ret=vfd->vidiocgmbuf(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
+						p->size, p->frames,
+						(unsigned long)p->offsets);
+		break;
+	}
+#endif
+	case VIDIOC_G_FBUF:
+	{
+		struct v4l2_framebuffer *p=arg;
+		if (!vfd->vidioc_g_fbuf)
+			break;
+		ret=vfd->vidioc_g_fbuf(file, fh, arg);
+		if (!ret) {
+			dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
+					p->capability,p->flags,
+					(unsigned long)p->base);
+			v4l_print_pix_fmt (vfd, &p->fmt);
+		}
+		break;
+	}
+	case VIDIOC_S_FBUF:
+	{
+		struct v4l2_framebuffer *p=arg;
+		if (!vfd->vidioc_s_fbuf)
+			break;
+
+		dbgarg (cmd, "capability=%d, flags=%d, base=0x%08lx\n",
+				p->capability,p->flags,(unsigned long)p->base);
+		v4l_print_pix_fmt (vfd, &p->fmt);
+		ret=vfd->vidioc_s_fbuf(file, fh, arg);
+
+		break;
+	}
+	case VIDIOC_STREAMON:
+	{
+		enum v4l2_buf_type i = *(int *)arg;
+		if (!vfd->vidioc_streamon)
+			break;
+		dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
+		ret=vfd->vidioc_streamon(file, fh,i);
+		break;
+	}
+	case VIDIOC_STREAMOFF:
+	{
+		enum v4l2_buf_type i = *(int *)arg;
+
+		if (!vfd->vidioc_streamoff)
+			break;
+		dbgarg (cmd, "type=%s\n", prt_names(i,v4l2_type_names_FIXME));
+		ret=vfd->vidioc_streamoff(file, fh, i);
+		break;
+	}
+	/* ---------- tv norms ---------- */
+	case VIDIOC_ENUMSTD:
+	{
+		struct v4l2_standard *p = arg;
+		unsigned int index = p->index;
+
+		if (!vfd->tvnormsize) {
+			printk (KERN_WARNING "%s: no TV norms defined!\n",
+						vfd->name);
+			break;
+		}
+
+		if (index<=0 || index >= vfd->tvnormsize) {
+			ret=-EINVAL;
+			break;
+		}
+		v4l2_video_std_construct(p, vfd->tvnorms[p->index].id,
+					 vfd->tvnorms[p->index].name);
+		p->index = index;
+
+		dbgarg (cmd, "index=%d, id=%Ld, name=%s, fps=%d/%d, "
+				"framelines=%d\n", p->index,
+				(unsigned long long)p->id, p->name,
+				p->frameperiod.numerator,
+				p->frameperiod.denominator,
+				p->framelines);
+
+		ret=0;
+		break;
+	}
+	case VIDIOC_G_STD:
+	{
+		v4l2_std_id *id = arg;
+
+		*id = vfd->current_norm;
+
+		dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
+
+		ret=0;
+		break;
+	}
+	case VIDIOC_S_STD:
+	{
+		v4l2_std_id *id = arg;
+		unsigned int i;
+
+		if (!vfd->tvnormsize) {
+			printk (KERN_WARNING "%s: no TV norms defined!\n",
+						vfd->name);
+			break;
+		}
+
+		dbgarg (cmd, "value=%Lu\n", (long long unsigned) *id);
+
+		/* First search for exact match */
+		for (i = 0; i < vfd->tvnormsize; i++)
+			if (*id == vfd->tvnorms[i].id)
+				break;
+		/* Then for a generic video std that contains desired std */
+		if (i == vfd->tvnormsize)
+			for (i = 0; i < vfd->tvnormsize; i++)
+				if (*id & vfd->tvnorms[i].id)
+					break;
+		if (i == vfd->tvnormsize) {
+			break;
+		}
+
+		/* Calls the specific handler */
+		if (vfd->vidioc_s_std)
+			ret=vfd->vidioc_s_std(file, fh, i);
+		else
+			ret=-EINVAL;
+
+		/* Updates standard information */
+		if (!ret)
+			vfd->current_norm=*id;
+
+		break;
+	}
+	case VIDIOC_QUERYSTD:
+	{
+		v4l2_std_id *p=arg;
+
+		if (!vfd->vidioc_querystd)
+			break;
+		ret=vfd->vidioc_querystd(file, fh, arg);
+		if (!ret)
+			dbgarg (cmd, "detected std=%Lu\n",
+						(unsigned long long)*p);
+		break;
+	}
+	/* ------ input switching ---------- */
+	/* FIXME: Inputs can be handled inside videodev2 */
+	case VIDIOC_ENUMINPUT:
+	{
+		struct v4l2_input *p=arg;
+		int i=p->index;
+
+		if (!vfd->vidioc_enum_input)
+			break;
+		memset(p, 0, sizeof(*p));
+		p->index=i;
+
+		ret=vfd->vidioc_enum_input(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "index=%d, name=%s, type=%d, "
+					"audioset=%d, "
+					"tuner=%d, std=%Ld, status=%d\n",
+					p->index,p->name,p->type,p->audioset,
+					p->tuner,
+					(unsigned long long)p->std,
+					p->status);
+		break;
+	}
+	case VIDIOC_G_INPUT:
+	{
+		unsigned int *i = arg;
+
+		if (!vfd->vidioc_g_input)
+			break;
+		ret=vfd->vidioc_g_input(file, fh, i);
+		if (!ret)
+			dbgarg (cmd, "value=%d\n",*i);
+		break;
+	}
+	case VIDIOC_S_INPUT:
+	{
+		unsigned int *i = arg;
+
+		if (!vfd->vidioc_s_input)
+			break;
+		dbgarg (cmd, "value=%d\n",*i);
+		ret=vfd->vidioc_s_input(file, fh, *i);
+		break;
+	}
+
+	/* ------ output switching ---------- */
+	case VIDIOC_G_OUTPUT:
+	{
+		unsigned int *i = arg;
+
+		if (!vfd->vidioc_g_output)
+			break;
+		ret=vfd->vidioc_g_output(file, fh, i);
+		if (!ret)
+			dbgarg (cmd, "value=%d\n",*i);
+		break;
+	}
+	case VIDIOC_S_OUTPUT:
+	{
+		unsigned int *i = arg;
+
+		if (!vfd->vidioc_s_output)
+			break;
+		dbgarg (cmd, "value=%d\n",*i);
+		ret=vfd->vidioc_s_output(file, fh, *i);
+		break;
+	}
+
+	/* --- controls ---------------------------------------------- */
+	case VIDIOC_QUERYCTRL:
+	{
+		struct v4l2_queryctrl *p=arg;
+
+		if (!vfd->vidioc_queryctrl)
+			break;
+		ret=vfd->vidioc_queryctrl(file, fh, p);
+
+		if (!ret)
+			dbgarg (cmd, "id=%d, type=%d, name=%s, "
+					"min/max=%d/%d,"
+					" step=%d, default=%d, flags=0x%08x\n",
+					p->id,p->type,p->name,p->minimum,
+					p->maximum,p->step,p->default_value,
+					p->flags);
+		break;
+	}
+	case VIDIOC_G_CTRL:
+	{
+		struct v4l2_control *p = arg;
+
+		if (!vfd->vidioc_g_ctrl)
+			break;
+		dbgarg(cmd, "Enum for index=%d\n", p->id);
+
+		ret=vfd->vidioc_g_ctrl(file, fh, p);
+		if (!ret)
+			dbgarg2 ( "id=%d, value=%d\n", p->id, p->value);
+		break;
+	}
+	case VIDIOC_S_CTRL:
+	{
+		struct v4l2_control *p = arg;
+
+		if (!vfd->vidioc_s_ctrl)
+			break;
+		dbgarg (cmd, "id=%d, value=%d\n", p->id, p->value);
+
+		ret=vfd->vidioc_s_ctrl(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *p = arg;
+
+		if (vfd->vidioc_g_ext_ctrls) {
+			dbgarg(cmd, "count=%d\n", p->count);
+
+			ret=vfd->vidioc_g_ext_ctrls(file, fh, p);
+		}
+		break;
+	}
+	case VIDIOC_S_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *p = arg;
+
+		if (vfd->vidioc_s_ext_ctrls) {
+			dbgarg(cmd, "count=%d\n", p->count);
+
+			ret=vfd->vidioc_s_ext_ctrls(file, fh, p);
+		}
+		break;
+	}
+	case VIDIOC_TRY_EXT_CTRLS:
+	{
+		struct v4l2_ext_controls *p = arg;
+
+		if (vfd->vidioc_try_ext_ctrls) {
+			dbgarg(cmd, "count=%d\n", p->count);
+
+			ret=vfd->vidioc_try_ext_ctrls(file, fh, p);
+		}
+		break;
+	}
+	case VIDIOC_QUERYMENU:
+	{
+		struct v4l2_querymenu *p=arg;
+		if (!vfd->vidioc_querymenu)
+			break;
+		ret=vfd->vidioc_querymenu(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "id=%d, index=%d, name=%s\n",
+						p->id,p->index,p->name);
+		break;
+	}
+	/* --- audio ---------------------------------------------- */
+	case VIDIOC_ENUMAUDIO:
+	{
+		struct v4l2_audio *p=arg;
+
+		if (!vfd->vidioc_enumaudio)
+			break;
+		dbgarg(cmd, "Enum for index=%d\n", p->index);
+		ret=vfd->vidioc_enumaudio(file, fh, p);
+		if (!ret)
+			dbgarg2("index=%d, name=%s, capability=%d, "
+					"mode=%d\n",p->index,p->name,
+					p->capability, p->mode);
+		break;
+	}
+	case VIDIOC_G_AUDIO:
+	{
+		struct v4l2_audio *p=arg;
+
+		if (!vfd->vidioc_g_audio)
+			break;
+		dbgarg(cmd, "Get for index=%d\n", p->index);
+		ret=vfd->vidioc_g_audio(file, fh, p);
+		if (!ret)
+			dbgarg2("index=%d, name=%s, capability=%d, "
+					"mode=%d\n",p->index,
+					p->name,p->capability, p->mode);
+		break;
+	}
+	case VIDIOC_S_AUDIO:
+	{
+		struct v4l2_audio *p=arg;
+
+		if (!vfd->vidioc_s_audio)
+			break;
+		dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+					"mode=%d\n", p->index, p->name,
+					p->capability, p->mode);
+		ret=vfd->vidioc_s_audio(file, fh, p);
+		break;
+	}
+	case VIDIOC_ENUMAUDOUT:
+	{
+		struct v4l2_audioout *p=arg;
+
+		if (!vfd->vidioc_enumaudout)
+			break;
+		dbgarg(cmd, "Enum for index=%d\n", p->index);
+		ret=vfd->vidioc_enumaudout(file, fh, p);
+		if (!ret)
+			dbgarg2("index=%d, name=%s, capability=%d, "
+					"mode=%d\n", p->index, p->name,
+					p->capability,p->mode);
+		break;
+	}
+	case VIDIOC_G_AUDOUT:
+	{
+		struct v4l2_audioout *p=arg;
+
+		if (!vfd->vidioc_g_audout)
+			break;
+		dbgarg(cmd, "Enum for index=%d\n", p->index);
+		ret=vfd->vidioc_g_audout(file, fh, p);
+		if (!ret)
+			dbgarg2("index=%d, name=%s, capability=%d, "
+					"mode=%d\n", p->index, p->name,
+					p->capability,p->mode);
+		break;
+	}
+	case VIDIOC_S_AUDOUT:
+	{
+		struct v4l2_audioout *p=arg;
+
+		if (!vfd->vidioc_s_audout)
+			break;
+		dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+					"mode=%d\n", p->index, p->name,
+					p->capability,p->mode);
+
+		ret=vfd->vidioc_s_audout(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_MODULATOR:
+	{
+		struct v4l2_modulator *p=arg;
+		if (!vfd->vidioc_g_modulator)
+			break;
+		ret=vfd->vidioc_g_modulator(file, fh, p);
+		if (!ret)
+			dbgarg(cmd, "index=%d, name=%s, "
+					"capability=%d, rangelow=%d,"
+					" rangehigh=%d, txsubchans=%d\n",
+					p->index, p->name,p->capability,
+					p->rangelow, p->rangehigh,
+					p->txsubchans);
+		break;
+	}
+	case VIDIOC_S_MODULATOR:
+	{
+		struct v4l2_modulator *p=arg;
+		if (!vfd->vidioc_s_modulator)
+			break;
+		dbgarg(cmd, "index=%d, name=%s, capability=%d, "
+				"rangelow=%d, rangehigh=%d, txsubchans=%d\n",
+				p->index, p->name,p->capability,p->rangelow,
+				p->rangehigh,p->txsubchans);
+			ret=vfd->vidioc_s_modulator(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_CROP:
+	{
+		struct v4l2_crop *p=arg;
+		if (!vfd->vidioc_g_crop)
+			break;
+		ret=vfd->vidioc_g_crop(file, fh, p);
+		if (!ret) {
+			dbgarg(cmd, "type=%d\n", p->type);
+			dbgrect(vfd, "", &p->c);
+		}
+		break;
+	}
+	case VIDIOC_S_CROP:
+	{
+		struct v4l2_crop *p=arg;
+		if (!vfd->vidioc_s_crop)
+			break;
+		dbgarg(cmd, "type=%d\n", p->type);
+		dbgrect(vfd, "", &p->c);
+		ret=vfd->vidioc_s_crop(file, fh, p);
+		break;
+	}
+	case VIDIOC_CROPCAP:
+	{
+		struct v4l2_cropcap *p=arg;
+		/*FIXME: Should also show v4l2_fract pixelaspect */
+		if (!vfd->vidioc_cropcap)
+			break;
+		dbgarg(cmd, "type=%d\n", p->type);
+		dbgrect(vfd, "bounds ", &p->bounds);
+		dbgrect(vfd, "defrect ", &p->defrect);
+		ret=vfd->vidioc_cropcap(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_MPEGCOMP:
+	{
+		struct v4l2_mpeg_compression *p=arg;
+
+		/*FIXME: Several fields not shown */
+		if (!vfd->vidioc_g_mpegcomp)
+			break;
+		ret=vfd->vidioc_g_mpegcomp(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d,"
+					" ts_pid_video=%d, ts_pid_pcr=%d, "
+					"ps_size=%d, au_sample_rate=%d, "
+					"au_pesid=%c, vi_frame_rate=%d, "
+					"vi_frames_per_gop=%d, "
+					"vi_bframes_count=%d, vi_pesid=%c\n",
+					p->ts_pid_pmt,p->ts_pid_audio,
+					p->ts_pid_video,p->ts_pid_pcr,
+					p->ps_size, p->au_sample_rate,
+					p->au_pesid, p->vi_frame_rate,
+					p->vi_frames_per_gop,
+					p->vi_bframes_count, p->vi_pesid);
+		break;
+	}
+	case VIDIOC_S_MPEGCOMP:
+	{
+		struct v4l2_mpeg_compression *p=arg;
+		/*FIXME: Several fields not shown */
+		if (!vfd->vidioc_s_mpegcomp)
+			break;
+		dbgarg (cmd, "ts_pid_pmt=%d, ts_pid_audio=%d, "
+				"ts_pid_video=%d, ts_pid_pcr=%d, ps_size=%d, "
+				"au_sample_rate=%d, au_pesid=%c, "
+				"vi_frame_rate=%d, vi_frames_per_gop=%d, "
+				"vi_bframes_count=%d, vi_pesid=%c\n",
+				p->ts_pid_pmt,p->ts_pid_audio, p->ts_pid_video,
+				p->ts_pid_pcr, p->ps_size, p->au_sample_rate,
+				p->au_pesid, p->vi_frame_rate,
+				p->vi_frames_per_gop, p->vi_bframes_count,
+				p->vi_pesid);
+		ret=vfd->vidioc_s_mpegcomp(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_JPEGCOMP:
+	{
+		struct v4l2_jpegcompression *p=arg;
+		if (!vfd->vidioc_g_jpegcomp)
+			break;
+		ret=vfd->vidioc_g_jpegcomp(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "quality=%d, APPn=%d, "
+						"APP_len=%d, COM_len=%d, "
+						"jpeg_markers=%d\n",
+						p->quality,p->APPn,p->APP_len,
+						p->COM_len,p->jpeg_markers);
+		break;
+	}
+	case VIDIOC_S_JPEGCOMP:
+	{
+		struct v4l2_jpegcompression *p=arg;
+		if (!vfd->vidioc_g_jpegcomp)
+			break;
+		dbgarg (cmd, "quality=%d, APPn=%d, APP_len=%d, "
+					"COM_len=%d, jpeg_markers=%d\n",
+					p->quality,p->APPn,p->APP_len,
+					p->COM_len,p->jpeg_markers);
+			ret=vfd->vidioc_s_jpegcomp(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_PARM:
+	{
+		struct v4l2_streamparm *p=arg;
+		if (!vfd->vidioc_g_parm)
+			break;
+		ret=vfd->vidioc_g_parm(file, fh, p);
+		dbgarg (cmd, "type=%d\n", p->type);
+		break;
+	}
+	case VIDIOC_S_PARM:
+	{
+		struct v4l2_streamparm *p=arg;
+		if (!vfd->vidioc_s_parm)
+			break;
+		dbgarg (cmd, "type=%d\n", p->type);
+		ret=vfd->vidioc_s_parm(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_TUNER:
+	{
+		struct v4l2_tuner *p=arg;
+		if (!vfd->vidioc_g_tuner)
+			break;
+		ret=vfd->vidioc_g_tuner(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "index=%d, name=%s, type=%d, "
+					"capability=%d, rangelow=%d, "
+					"rangehigh=%d, signal=%d, afc=%d, "
+					"rxsubchans=%d, audmode=%d\n",
+					p->index, p->name, p->type,
+					p->capability, p->rangelow,
+					p->rangehigh, p->rxsubchans,
+					p->audmode, p->signal, p->afc);
+		break;
+	}
+	case VIDIOC_S_TUNER:
+	{
+		struct v4l2_tuner *p=arg;
+		if (!vfd->vidioc_s_tuner)
+			break;
+		dbgarg (cmd, "index=%d, name=%s, type=%d, "
+				"capability=%d, rangelow=%d, rangehigh=%d, "
+				"signal=%d, afc=%d, rxsubchans=%d, "
+				"audmode=%d\n",p->index, p->name, p->type,
+				p->capability, p->rangelow,p->rangehigh,
+				p->rxsubchans, p->audmode, p->signal,
+				p->afc);
+		ret=vfd->vidioc_s_tuner(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_FREQUENCY:
+	{
+		struct v4l2_frequency *p=arg;
+		if (!vfd->vidioc_g_frequency)
+			break;
+		ret=vfd->vidioc_g_frequency(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
+						p->tuner,p->type,p->frequency);
+		break;
+	}
+	case VIDIOC_S_FREQUENCY:
+	{
+		struct v4l2_frequency *p=arg;
+		if (!vfd->vidioc_s_frequency)
+			break;
+		dbgarg (cmd, "tuner=%d, type=%d, frequency=%d\n",
+				p->tuner,p->type,p->frequency);
+		ret=vfd->vidioc_s_frequency(file, fh, p);
+		break;
+	}
+	case VIDIOC_G_SLICED_VBI_CAP:
+	{
+		struct v4l2_sliced_vbi_cap *p=arg;
+		if (!vfd->vidioc_g_sliced_vbi_cap)
+			break;
+		ret=vfd->vidioc_g_sliced_vbi_cap(file, fh, p);
+		if (!ret)
+			dbgarg (cmd, "service_set=%d\n", p->service_set);
+		break;
+	}
+	case VIDIOC_LOG_STATUS:
+	{
+		if (!vfd->vidioc_log_status)
+			break;
+		ret=vfd->vidioc_log_status(file, fh);
+		break;
+	}
+
+	/* --- Others --------------------------------------------- */
+
+	default:
+		ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,__video_do_ioctl);
+	}
+
+	if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
+		if (ret<0) {
+			printk ("%s: err:\n", vfd->name);
+			v4l_print_ioctl(vfd->name, cmd);
+		}
+	}
+
+	return ret;
+}
+
+int video_ioctl2 (struct inode *inode, struct file *file,
+	       unsigned int cmd, unsigned long arg)
+{
+	char	sbuf[128];
+	void    *mbuf = NULL;
+	void	*parg = NULL;
+	int	err  = -EINVAL;
+	int     is_ext_ctrl;
+	size_t  ctrls_size = 0;
+	void __user *user_ptr = NULL;
+
+#ifdef __OLD_VIDIOC_
+	cmd = video_fix_command(cmd);
+#endif
+	is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
+		       cmd == VIDIOC_TRY_EXT_CTRLS);
 
 	/*  Copy arguments into temp kernel buffer  */
 	switch (_IOC_DIR(cmd)) {
@@ -194,13 +1428,43 @@
 		break;
 	}
 
-	/* call driver */
-	err = func(inode, file, cmd, parg);
+	if (is_ext_ctrl) {
+		struct v4l2_ext_controls *p = parg;
+
+		/* In case of an error, tell the caller that it wasn't
+		   a specific control that caused it. */
+		p->error_idx = p->count;
+		user_ptr = (void __user *)p->controls;
+		if (p->count) {
+			ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
+			/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
+			mbuf = kmalloc(ctrls_size, GFP_KERNEL);
+			err = -ENOMEM;
+			if (NULL == mbuf)
+				goto out_ext_ctrl;
+			err = -EFAULT;
+			if (copy_from_user(mbuf, user_ptr, ctrls_size))
+				goto out_ext_ctrl;
+			p->controls = mbuf;
+		}
+	}
+
+	/* Handles IOCTL */
+	err = __video_do_ioctl(inode, file, cmd, parg);
 	if (err == -ENOIOCTLCMD)
 		err = -EINVAL;
+	if (is_ext_ctrl) {
+		struct v4l2_ext_controls *p = parg;
+
+		p->controls = (void *)user_ptr;
+		if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+			err = -EFAULT;
+		goto out_ext_ctrl;
+	}
 	if (err < 0)
 		goto out;
 
+out_ext_ctrl:
 	/*  Copy results into user buffer  */
 	switch (_IOC_DIR(cmd))
 	{
@@ -216,31 +1480,6 @@
 	return err;
 }
 
-/*
- * open/release helper functions -- handle exclusive opens
- */
-int video_exclusive_open(struct inode *inode, struct file *file)
-{
-	struct  video_device *vfl = video_devdata(file);
-	int retval = 0;
-
-	mutex_lock(&vfl->lock);
-	if (vfl->users) {
-		retval = -EBUSY;
-	} else {
-		vfl->users++;
-	}
-	mutex_unlock(&vfl->lock);
-	return retval;
-}
-
-int video_exclusive_release(struct inode *inode, struct file *file)
-{
-	struct  video_device *vfl = video_devdata(file);
-
-	vfl->users--;
-	return 0;
-}
 
 static struct file_operations video_fops;
 
@@ -371,7 +1610,9 @@
 	mutex_unlock(&videodev_lock);
 }
 
-
+/*
+ * Video fs operations
+ */
 static struct file_operations video_fops=
 {
 	.owner		= THIS_MODULE,
@@ -387,7 +1628,7 @@
 {
 	int ret;
 
-	printk(KERN_INFO "Linux video capture interface: v1.00\n");
+	printk(KERN_INFO "Linux video capture interface: v2.00\n");
 	if (register_chrdev(VIDEO_MAJOR, VIDEO_NAME, &video_fops)) {
 		printk(KERN_WARNING "video_dev: unable to get major %d\n", VIDEO_MAJOR);
 		return -EIO;
@@ -418,11 +1659,12 @@
 EXPORT_SYMBOL(video_usercopy);
 EXPORT_SYMBOL(video_exclusive_open);
 EXPORT_SYMBOL(video_exclusive_release);
+EXPORT_SYMBOL(video_ioctl2);
 EXPORT_SYMBOL(video_device_alloc);
 EXPORT_SYMBOL(video_device_release);
 
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("Device registrar for Video4Linux drivers");
+MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>");
+MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2");
 MODULE_LICENSE("GPL");
 
 
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c
index a8c1014..268e69f 100644
--- a/drivers/media/video/vino.c
+++ b/drivers/media/video/vino.c
@@ -40,7 +40,7 @@
 #include <linux/i2c-algo-sgi.h>
 
 #include <linux/videodev.h>
-#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 #include <linux/mutex.h>
 
diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c
index 779db26..41d23c8 100644
--- a/drivers/media/video/vivi.c
+++ b/drivers/media/video/vivi.c
@@ -48,34 +48,15 @@
 
 #include "font.h"
 
-#ifndef kzalloc
-#define kzalloc(size, flags)                            \
-({                                                      \
-	void *__ret = kmalloc(size, flags);             \
-	if (__ret)                                      \
-		memset(__ret, 0, size);                 \
-	__ret;                                          \
-})
-#endif
-
-MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
-MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
-MODULE_LICENSE("Dual BSD/GPL");
-
 #define VIVI_MAJOR_VERSION 0
 #define VIVI_MINOR_VERSION 4
 #define VIVI_RELEASE 0
 #define VIVI_VERSION KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
 
-static int video_nr = -1;        /* /dev/videoN, -1 for autodetect */
-module_param(video_nr, int, 0);
-
-static int debug = 0;
-module_param(debug, int, 0);
-
-static unsigned int vid_limit = 16;
-module_param(vid_limit,int,0644);
-MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+/* Declare static vars that will be used as parameters */
+static unsigned int vid_limit = 16;	/* Video memory limit, in Mb */
+static struct video_device vivi;	/* Video device */
+static int video_nr = -1;		/* /dev/videoN, -1 for autodetect */
 
 /* supported controls */
 static struct v4l2_queryctrl vivi_qctrl[] = {
@@ -129,10 +110,10 @@
 
 static int qctl_regs[ARRAY_SIZE(vivi_qctrl)];
 
-#define dprintk(level,fmt, arg...)			     \
-	do { 						     \
-		if (debug >= (level))			     \
-			printk(KERN_DEBUG "vivi: " fmt , ## arg);    \
+#define dprintk(level,fmt, arg...)					\
+	do {								\
+		if (vivi.debug >= (level))				\
+			printk(KERN_DEBUG "vivi: " fmt , ## arg);	\
 	} while (0)
 
 /* ------------------------------------------------------------------
@@ -190,7 +171,7 @@
 
 	/* various device info */
 	unsigned int               resources;
-	struct video_device        video_dev;
+	struct video_device        vfd;
 
 	struct vivi_dmaqueue       vidq;
 
@@ -248,7 +229,8 @@
 #define TSTAMP_MAX_Y TSTAMP_MIN_Y+15
 #define TSTAMP_MIN_X 64
 
-void prep_to_addr(struct sg_to_addr to_addr[],struct videobuf_buffer *vb)
+static void prep_to_addr(struct sg_to_addr to_addr[],
+			 struct videobuf_buffer *vb)
 {
 	int i, pos=0;
 
@@ -259,7 +241,7 @@
 	}
 }
 
-inline int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
+static int get_addr_pos(int pos, int pages, struct sg_to_addr to_addr[])
 {
 	int p1=0,p2=pages-1,p3=pages/2;
 
@@ -280,8 +262,8 @@
 	return (p1);
 }
 
-void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
-					int hmax, int line, char *timestr)
+static void gen_line(struct sg_to_addr to_addr[],int inipos,int pages,int wmax,
+		     int hmax, int line, char *timestr)
 {
 	int  w,i,j,pos=inipos,pgpos,oldpg,y;
 	char *p,*s,*basep;
@@ -491,7 +473,7 @@
 		dprintk(1,"%s: %d buffers handled (should be 1)\n",__FUNCTION__,bc);
 }
 
-void vivi_sleep(struct vivi_dmaqueue  *dma_q)
+static void vivi_sleep(struct vivi_dmaqueue  *dma_q)
 {
 	int timeout;
 	DECLARE_WAITQUEUE(wait, current);
@@ -526,7 +508,7 @@
 	try_to_freeze();
 }
 
-int vivi_thread(void *data)
+static int vivi_thread(void *data)
 {
 	struct vivi_dmaqueue  *dma_q=data;
 
@@ -542,7 +524,7 @@
 	return 0;
 }
 
-int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
+static int vivi_start_thread(struct vivi_dmaqueue  *dma_q)
 {
 	dma_q->frame=0;
 	dma_q->ini_jiffies=jiffies;
@@ -560,7 +542,7 @@
 	return 0;
 }
 
-void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
+static void vivi_stop_thread(struct vivi_dmaqueue  *dma_q)
 {
 	dprintk(1,"%s\n",__FUNCTION__);
 	/* shutdown control thread */
@@ -666,8 +648,7 @@
 	return 0;
 }
 
-void
-free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
+static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
 {
 	dprintk(1,"%s\n",__FUNCTION__);
 
@@ -791,8 +772,8 @@
 	free_buffer(vq,buf);
 }
 
-int vivi_map_sg (void *dev, struct scatterlist *sg, int nents,
-	   int direction)
+static int vivi_map_sg(void *dev, struct scatterlist *sg, int nents,
+		       int direction)
 {
 	int i;
 
@@ -808,15 +789,15 @@
 	return nents;
 }
 
-int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages,
-					int direction)
+static int vivi_unmap_sg(void *dev,struct scatterlist *sglist,int nr_pages,
+			 int direction)
 {
 	dprintk(1,"%s\n",__FUNCTION__);
 	return 0;
 }
 
-int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist,int nr_pages,
-					int direction)
+static int vivi_dma_sync_sg(void *dev,struct scatterlist *sglist, int nr_pages,
+			    int direction)
 {
 //	dprintk(1,"%s\n",__FUNCTION__);
 
@@ -840,7 +821,80 @@
 	IOCTL handling
    ------------------------------------------------------------------*/
 
-static int vivi_try_fmt(struct vivi_dev *dev, struct vivi_fh *fh,
+
+static int res_get(struct vivi_dev *dev, struct vivi_fh *fh)
+{
+	/* is it free? */
+	down(&dev->lock);
+	if (dev->resources) {
+		/* no, someone else uses it */
+		up(&dev->lock);
+		return 0;
+	}
+	/* it's free, grab it */
+	dev->resources =1;
+	dprintk(1,"res: get\n");
+	up(&dev->lock);
+	return 1;
+}
+
+static int res_locked(struct vivi_dev *dev)
+{
+	return (dev->resources);
+}
+
+static void res_free(struct vivi_dev *dev, struct vivi_fh *fh)
+{
+	down(&dev->lock);
+	dev->resources = 0;
+	dprintk(1,"res: put\n");
+	up(&dev->lock);
+}
+
+/* ------------------------------------------------------------------
+	IOCTL vidioc handling
+   ------------------------------------------------------------------*/
+static int vidioc_querycap (struct file *file, void  *priv,
+					struct v4l2_capability *cap)
+{
+	strcpy(cap->driver, "vivi");
+	strcpy(cap->card, "vivi");
+	cap->version = VIVI_VERSION;
+	cap->capabilities =	V4L2_CAP_VIDEO_CAPTURE |
+				V4L2_CAP_STREAMING     |
+				V4L2_CAP_READWRITE;
+	return 0;
+}
+
+static int vidioc_enum_fmt_cap (struct file *file, void  *priv,
+					struct v4l2_fmtdesc *f)
+{
+	if (f->index > 0)
+		return -EINVAL;
+
+	strlcpy(f->description,format.name,sizeof(f->description));
+	f->pixelformat = format.fourcc;
+	return 0;
+}
+
+static int vidioc_g_fmt_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
+{
+	struct vivi_fh  *fh=priv;
+
+	f->fmt.pix.width        = fh->width;
+	f->fmt.pix.height       = fh->height;
+	f->fmt.pix.field        = fh->vb_vidq.field;
+	f->fmt.pix.pixelformat  = fh->fmt->fourcc;
+	f->fmt.pix.bytesperline =
+		(f->fmt.pix.width * fh->fmt->depth) >> 3;
+	f->fmt.pix.sizeimage =
+		f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+	return (0);
+}
+
+static int vidioc_try_fmt_cap (struct file *file, void *priv,
 			struct v4l2_format *f)
 {
 	struct vivi_fmt *fmt;
@@ -848,7 +902,8 @@
 	unsigned int maxw, maxh;
 
 	if (format.fourcc != f->fmt.pix.pixelformat) {
-		dprintk(1,"Fourcc format invalid.\n");
+		dprintk(1,"Fourcc format (0x%08x) invalid. Driver accepts "
+			"only 0x%08x\n",f->fmt.pix.pixelformat,format.fourcc);
 		return -EINVAL;
 	}
 	fmt=&format;
@@ -884,356 +939,196 @@
 	return 0;
 }
 
-static int res_get(struct vivi_dev *dev, struct vivi_fh *fh)
+/*FIXME: This seems to be generic enough to be at videodev2 */
+static int vidioc_s_fmt_cap (struct file *file, void *priv,
+					struct v4l2_format *f)
 {
-	/* is it free? */
-	down(&dev->lock);
-	if (dev->resources) {
-		/* no, someone else uses it */
-		up(&dev->lock);
-		return 0;
-	}
-	/* it's free, grab it */
-	dev->resources =1;
-	dprintk(1,"res: get\n");
-	up(&dev->lock);
-	return 1;
+	struct vivi_fh  *fh=priv;
+	int ret = vidioc_try_fmt_cap(file,fh,f);
+	if (ret < 0)
+		return (ret);
+
+	fh->fmt           = &format;
+	fh->width         = f->fmt.pix.width;
+	fh->height        = f->fmt.pix.height;
+	fh->vb_vidq.field = f->fmt.pix.field;
+	fh->type          = f->type;
+
+	return (0);
 }
 
-static inline int res_locked(struct vivi_dev *dev)
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
 {
-	return (dev->resources);
+	struct vivi_fh  *fh=priv;
+
+	return (videobuf_reqbufs(&fh->vb_vidq, p));
 }
 
-static void res_free(struct vivi_dev *dev, struct vivi_fh *fh)
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
 {
-	down(&dev->lock);
-	dev->resources = 0;
-	dprintk(1,"res: put\n");
-	up(&dev->lock);
+	struct vivi_fh  *fh=priv;
+
+	return (videobuf_querybuf(&fh->vb_vidq, p));
 }
 
-static int vivi_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
 {
-	struct vivi_fh  *fh     = file->private_data;
-	struct vivi_dev *dev    = fh->dev;
-	int ret=0;
+	struct vivi_fh  *fh=priv;
 
-	if (debug) {
-		if (_IOC_DIR(cmd) & _IOC_WRITE)
-			v4l_printk_ioctl_arg("vivi(w)",cmd, arg);
-		else if (!_IOC_DIR(cmd) & _IOC_READ) {
-			v4l_print_ioctl("vivi", cmd);
-		}
-	}
+	return (videobuf_qbuf(&fh->vb_vidq, p));
+}
 
-	switch(cmd) {
-	/* --- capabilities ------------------------------------------ */
-	case VIDIOC_QUERYCAP:
-	{
-		struct v4l2_capability *cap = (struct v4l2_capability*)arg;
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+	struct vivi_fh  *fh=priv;
 
-		memset(cap, 0, sizeof(*cap));
+	return (videobuf_dqbuf(&fh->vb_vidq, p,
+				file->f_flags & O_NONBLOCK));
+}
 
-		strcpy(cap->driver, "vivi");
-		strcpy(cap->card, "vivi");
-		cap->version = VIVI_VERSION;
-		cap->capabilities =
-					V4L2_CAP_VIDEO_CAPTURE |
-					V4L2_CAP_STREAMING     |
-					V4L2_CAP_READWRITE;
-		break;
-	}
-	/* --- capture ioctls ---------------------------------------- */
-	case VIDIOC_ENUM_FMT:
-	{
-		struct v4l2_fmtdesc *f = arg;
-		enum v4l2_buf_type type;
-		unsigned int index;
-
-		index = f->index;
-		type  = f->type;
-
-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-
-		switch (type) {
-		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-			if (index > 0){
-				ret=-EINVAL;
-				break;
-			}
-			memset(f,0,sizeof(*f));
-
-			f->index = index;
-			f->type  = type;
-			strlcpy(f->description,format.name,sizeof(f->description));
-			f->pixelformat = format.fourcc;
-			break;
-		default:
-			ret=-EINVAL;
-		}
-		break;
-	}
-	case VIDIOC_G_FMT:
-	{
-		struct v4l2_format *f = (struct v4l2_format *)arg;
-
-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-
-		memset(&f->fmt.pix,0,sizeof(f->fmt.pix));
-		f->fmt.pix.width        = fh->width;
-		f->fmt.pix.height       = fh->height;
-		f->fmt.pix.field        = fh->vb_vidq.field;
-		f->fmt.pix.pixelformat  = fh->fmt->fourcc;
-		f->fmt.pix.bytesperline =
-			(f->fmt.pix.width * fh->fmt->depth) >> 3;
-		f->fmt.pix.sizeimage =
-			f->fmt.pix.height * f->fmt.pix.bytesperline;
-		break;
-	}
-	case VIDIOC_S_FMT:
-	{
-		struct v4l2_format *f = arg;
-
-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			dprintk(1,"Only capture supported.\n");
-			ret=-EINVAL;
-			break;
-		}
-
-		ret = vivi_try_fmt(dev,fh,f);
-		if (ret < 0)
-			break;
-
-		fh->fmt           = &format;
-		fh->width         = f->fmt.pix.width;
-		fh->height        = f->fmt.pix.height;
-		fh->vb_vidq.field = f->fmt.pix.field;
-		fh->type          = f->type;
-
-		break;
-	}
-	case VIDIOC_TRY_FMT:
-	{
-		struct v4l2_format *f = arg;
-		if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-
-		ret=vivi_try_fmt(dev,fh,f);
-		break;
-	}
-	case VIDIOC_REQBUFS:
-		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-		ret=videobuf_reqbufs(&fh->vb_vidq, arg);
-		break;
-	case VIDIOC_QUERYBUF:
-		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-		ret=videobuf_querybuf(&fh->vb_vidq, arg);
-		break;
-	case VIDIOC_QBUF:
-		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-		ret=videobuf_qbuf(&fh->vb_vidq, arg);
-		break;
-	case VIDIOC_DQBUF:
-		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-		ret=videobuf_dqbuf(&fh->vb_vidq, arg,
-					file->f_flags & O_NONBLOCK);
-		break;
 #ifdef HAVE_V4L1
-	/* --- streaming capture ------------------------------------- */
-	case VIDIOCGMBUF:
-	{
-		struct video_mbuf *mbuf = arg;
-		struct videobuf_queue *q=&fh->vb_vidq;
-		struct v4l2_requestbuffers req;
-		unsigned int i;
+static int vidiocgmbuf (struct file *file, void *priv, struct video_mbuf *mbuf)
+{
+	struct vivi_fh  *fh=priv;
+	struct videobuf_queue *q=&fh->vb_vidq;
+	struct v4l2_requestbuffers req;
+	unsigned int i, ret;
 
-		memset(&req,0,sizeof(req));
-		req.type   = q->type;
-		req.count  = 8;
-		req.memory = V4L2_MEMORY_MMAP;
-		ret = videobuf_reqbufs(q,&req);
-		if (ret < 0)
-			break;
-		memset(mbuf,0,sizeof(*mbuf));
-		mbuf->frames = req.count;
-		mbuf->size   = 0;
-		for (i = 0; i < mbuf->frames; i++) {
-			mbuf->offsets[i]  = q->bufs[i]->boff;
-			mbuf->size       += q->bufs[i]->bsize;
-		}
-		break;
+	req.type   = q->type;
+	req.count  = 8;
+	req.memory = V4L2_MEMORY_MMAP;
+	ret = videobuf_reqbufs(q,&req);
+	if (ret < 0)
+		return (ret);
+
+	mbuf->frames = req.count;
+	mbuf->size   = 0;
+	for (i = 0; i < mbuf->frames; i++) {
+		mbuf->offsets[i]  = q->bufs[i]->boff;
+		mbuf->size       += q->bufs[i]->bsize;
 	}
+	return (0);
+}
 #endif
-	case VIDIOC_STREAMON:
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct vivi_fh  *fh=priv;
+	struct vivi_dev *dev    = fh->dev;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	if (!res_get(dev,fh))
+		return -EBUSY;
+	return (videobuf_streamon(&fh->vb_vidq));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+	struct vivi_fh  *fh=priv;
+	struct vivi_dev *dev    = fh->dev;
+
+	if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (i != fh->type)
+		return -EINVAL;
+
+	videobuf_streamoff(&fh->vb_vidq);
+	res_free(dev,fh);
+
+	return (0);
+}
+
+static struct v4l2_tvnorm tvnorms[] = {
 	{
-		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			return -EINVAL;
-		if (!res_get(dev,fh))
-			return -EBUSY;
-		ret=videobuf_streamon(&fh->vb_vidq);
-		break;
+		.name      = "NTSC-M",
+		.id        = V4L2_STD_NTSC_M,
 	}
-	case VIDIOC_STREAMOFF:
-	{
-		if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-			ret=-EINVAL;
-			break;
-		}
-		ret = videobuf_streamoff(&fh->vb_vidq);
-		if (ret < 0)
-			break;
-		res_free(dev,fh);
-		break;
-	}
-	/* ---------- tv norms ---------- */
-	case VIDIOC_ENUMSTD:
-	{
-		struct v4l2_standard *e = arg;
+};
 
-		if (e->index>0) {
-			ret=-EINVAL;
-			break;
-		}
-		ret = v4l2_video_std_construct(e, V4L2_STD_NTSC_M, "NTSC-M");
+static int vidioc_s_std (struct file *file, void *priv, v4l2_std_id a)
+{
 
-		/* Allows vivi to use different fps from video std */
-		e->frameperiod.numerator = WAKE_NUMERATOR;
-		e->frameperiod.denominator = WAKE_DENOMINATOR;
+	return 0;
+}
 
-		break;
-	}
-	case VIDIOC_G_STD:
-	{
-		v4l2_std_id *id = arg;
+/* only one input in this sample driver */
+static int vidioc_enum_input (struct file *file, void *priv,
+				struct v4l2_input *inp)
+{
+	if (inp->index != 0)
+		return -EINVAL;
 
-		*id = V4L2_STD_NTSC_M;
-		break;
-	}
-	case VIDIOC_S_STD:
-	{
-		break;
-	}
-	/* ------ input switching ---------- */
-	case VIDIOC_ENUMINPUT:
-	{ /* only one input in this sample driver */
-		struct v4l2_input *inp = arg;
+	inp->type = V4L2_INPUT_TYPE_CAMERA;
+	inp->std = V4L2_STD_NTSC_M;
+	strcpy(inp->name,"Camera");
 
-		if (inp->index != 0) {
-			ret=-EINVAL;
-			break;
-		}
-		memset(inp, 0, sizeof(*inp));
+	return (0);
+}
 
-		inp->index = 0;
-		inp->type = V4L2_INPUT_TYPE_CAMERA;
-		inp->std = V4L2_STD_NTSC_M;
-		strcpy(inp->name,"Camera");
-		break;
-	}
-	case VIDIOC_G_INPUT:
-	{
-		unsigned int *i = arg;
+static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
+{
+	*i = 0;
 
-		*i = 0;
-		break;
-	}
-	case VIDIOC_S_INPUT:
-	{
-		unsigned int *i = arg;
+	return (0);
+}
+static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
+{
+	if (i > 0)
+		return -EINVAL;
 
-		if (*i > 0)
-			ret=-EINVAL;
-		break;
-	}
+	return (0);
+}
 
 	/* --- controls ---------------------------------------------- */
-	case VIDIOC_QUERYCTRL:
-	{
-		struct v4l2_queryctrl *qc = arg;
-		int i;
+static int vidioc_queryctrl (struct file *file, void *priv,
+				struct v4l2_queryctrl *qc)
+{
+	int i;
 
-		for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-			if (qc->id && qc->id == vivi_qctrl[i].id) {
-				memcpy(qc, &(vivi_qctrl[i]),
-					sizeof(*qc));
-				break;
-			}
+	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+		if (qc->id && qc->id == vivi_qctrl[i].id) {
+			memcpy(qc, &(vivi_qctrl[i]),
+				sizeof(*qc));
+			return (0);
+		}
 
-		ret=-EINVAL;
-		break;
-	}
-	case VIDIOC_G_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-		int i;
-
-		for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-			if (ctrl->id == vivi_qctrl[i].id) {
-				ctrl->value=qctl_regs[i];
-				break;
-			}
-
-		ret=-EINVAL;
-		break;
-	}
-	case VIDIOC_S_CTRL:
-	{
-		struct v4l2_control *ctrl = arg;
-		int i;
-		for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
-			if (ctrl->id == vivi_qctrl[i].id) {
-				if (ctrl->value <
-					vivi_qctrl[i].minimum
-					|| ctrl->value >
-					vivi_qctrl[i].maximum) {
-						ret=-ERANGE;
-						break;
-					}
-				qctl_regs[i]=ctrl->value;
-				break;
-			}
-		ret=-EINVAL;
-		break;
-	}
-	default:
-		ret=v4l_compat_translate_ioctl(inode,file,cmd,arg,vivi_do_ioctl);
-	}
-
-	if (debug) {
-		if (ret<0) {
-			v4l_print_ioctl("vivi(err)", cmd);
-			dprintk(1,"errcode=%d\n",ret);
-		} else if (_IOC_DIR(cmd) & _IOC_READ)
-			v4l_printk_ioctl_arg("vivi(r)",cmd, arg);
-	}
-
-	return ret;
+	return -EINVAL;
 }
 
-static int vivi_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int vidioc_g_ctrl (struct file *file, void *priv,
+				struct v4l2_control *ctrl)
 {
-	return video_usercopy(inode, file, cmd, arg, vivi_do_ioctl);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+		if (ctrl->id == vivi_qctrl[i].id) {
+			ctrl->value=qctl_regs[i];
+			return (0);
+		}
+
+	return -EINVAL;
+}
+static int vidioc_s_ctrl (struct file *file, void *priv,
+				struct v4l2_control *ctrl)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vivi_qctrl); i++)
+		if (ctrl->id == vivi_qctrl[i].id) {
+			if (ctrl->value <
+				vivi_qctrl[i].minimum
+				|| ctrl->value >
+				vivi_qctrl[i].maximum) {
+					return (-ERANGE);
+				}
+			qctl_regs[i]=ctrl->value;
+			return (0);
+		}
+	return -EINVAL;
 }
 
 /* ------------------------------------------------------------------
@@ -1255,7 +1150,7 @@
 
 	list_for_each(list,&vivi_devlist) {
 		h = list_entry(list, struct vivi_dev, vivi_devlist);
-		if (h->video_dev.minor == minor) {
+		if (h->vfd.minor == minor) {
 			dev  = h;
 			type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		}
@@ -1264,6 +1159,7 @@
 		return -ENODEV;
 
 
+
 	/* If more than one user, mutex should be added */
 	dev->users++;
 
@@ -1279,6 +1175,7 @@
 
 	file->private_data = fh;
 	fh->dev      = dev;
+
 	fh->type     = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 	fh->fmt      = &format;
 	fh->width    = 640;
@@ -1314,7 +1211,7 @@
 static ssize_t
 vivi_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
-	struct vivi_fh *fh = file->private_data;
+	struct vivi_fh        *fh = file->private_data;
 
 	if (fh->type==V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 		if (res_locked(fh->dev))
@@ -1328,8 +1225,8 @@
 static unsigned int
 vivi_poll(struct file *file, struct poll_table_struct *wait)
 {
-	struct vivi_fh *fh = file->private_data;
-	struct vivi_buffer *buf;
+	struct vivi_fh        *fh = file->private_data;
+	struct vivi_buffer    *buf;
 
 	dprintk(1,"%s\n",__FUNCTION__);
 
@@ -1358,8 +1255,8 @@
 
 static int vivi_release(struct inode *inode, struct file *file)
 {
-	struct vivi_fh  *fh     = file->private_data;
-	struct vivi_dev *dev    = fh->dev;
+	struct vivi_fh         *fh = file->private_data;
+	struct vivi_dev *dev       = fh->dev;
 	struct vivi_dmaqueue *vidq = &dev->vidq;
 
 	int minor = iminor(inode);
@@ -1379,7 +1276,7 @@
 static int
 vivi_mmap(struct file *file, struct vm_area_struct * vma)
 {
-	struct vivi_fh *fh = file->private_data;
+	struct vivi_fh        *fh = file->private_data;
 	int ret;
 
 	dprintk (1,"mmap called, vma=0x%08lx\n",(unsigned long)vma);
@@ -1400,20 +1297,44 @@
 	.release        = vivi_release,
 	.read           = vivi_read,
 	.poll		= vivi_poll,
-	.ioctl          = vivi_ioctl,
+	.ioctl          = video_ioctl2, /* V4L2 ioctl handler */
 	.mmap		= vivi_mmap,
 	.llseek         = no_llseek,
 };
 
 static struct video_device vivi = {
-	.name		= "VTM Virtual Video Capture Board",
+	.name		= "vivi",
 	.type		= VID_TYPE_CAPTURE,
 	.hardware	= 0,
 	.fops           = &vivi_fops,
 	.minor		= -1,
 //	.release	= video_device_release,
+
+	.vidioc_querycap      = vidioc_querycap,
+	.vidioc_enum_fmt_cap  = vidioc_enum_fmt_cap,
+	.vidioc_g_fmt_cap     = vidioc_g_fmt_cap,
+	.vidioc_try_fmt_cap   = vidioc_try_fmt_cap,
+	.vidioc_s_fmt_cap     = vidioc_s_fmt_cap,
+	.vidioc_reqbufs       = vidioc_reqbufs,
+	.vidioc_querybuf      = vidioc_querybuf,
+	.vidioc_qbuf          = vidioc_qbuf,
+	.vidioc_dqbuf         = vidioc_dqbuf,
+	.vidioc_s_std         = vidioc_s_std,
+	.vidioc_enum_input    = vidioc_enum_input,
+	.vidioc_g_input       = vidioc_g_input,
+	.vidioc_s_input       = vidioc_s_input,
+	.vidioc_queryctrl     = vidioc_queryctrl,
+	.vidioc_g_ctrl        = vidioc_g_ctrl,
+	.vidioc_s_ctrl        = vidioc_s_ctrl,
+	.vidioc_streamon      = vidioc_streamon,
+	.vidioc_streamoff     = vidioc_streamoff,
+#ifdef HAVE_V4L1
+	.vidiocgmbuf          = vidiocgmbuf,
+#endif
+	.tvnorms              = tvnorms,
+	.tvnormsize           = ARRAY_SIZE(tvnorms),
 };
-/* ------------------------------------------------------------------
+/* -----------------------------------------------------------------
 	Initialization and module stuff
    ------------------------------------------------------------------*/
 
@@ -1457,3 +1378,16 @@
 
 module_init(vivi_init);
 module_exit(vivi_exit);
+
+MODULE_DESCRIPTION("Video Technology Magazine Virtual Video Capture Board");
+MODULE_AUTHOR("Mauro Carvalho Chehab, Ted Walther and John Sokol");
+MODULE_LICENSE("Dual BSD/GPL");
+
+module_param(video_nr, int, 0);
+
+module_param_named(debug,vivi.debug, int, 0644);
+MODULE_PARM_DESC(debug,"activates debug info");
+
+module_param(vid_limit,int,0644);
+MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 40b205b..1eca7e6 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -34,6 +34,7 @@
 #define I2C_NAME(x) (x)->name
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/video_decoder.h>
 
 #define I2C_VPX3220        0x86
diff --git a/drivers/media/video/w9966.c b/drivers/media/video/w9966.c
index 80ef8a1..4bdc886 100644
--- a/drivers/media/video/w9966.c
+++ b/drivers/media/video/w9966.c
@@ -58,6 +58,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/parport.h>
 
 //#define DEBUG				// Undef me for production
diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig
index 115833e..a859a69 100644
--- a/drivers/media/video/zc0301/Kconfig
+++ b/drivers/media/video/zc0301/Kconfig
@@ -1,9 +1,9 @@
 config USB_ZC0301
-	tristate "USB ZC0301 Image Processor and Control Chip support"
+	tristate "USB ZC0301[P] Image Processor and Control Chip support"
 	depends on USB && VIDEO_V4L1
 	---help---
-	  Say Y here if you want support for cameras based on the ZC0301
-	  Image Processor and Control Chip.
+	  Say Y here if you want support for cameras based on the ZC0301 or
+	  ZC0301P Image Processors and Control Chips.
 
 	  See <file:Documentation/video4linux/zc0301.txt> for more info.
 
diff --git a/drivers/media/video/zc0301/Makefile b/drivers/media/video/zc0301/Makefile
index d749199..d9e6d97 100644
--- a/drivers/media/video/zc0301/Makefile
+++ b/drivers/media/video/zc0301/Makefile
@@ -1,3 +1,3 @@
-zc0301-objs     := zc0301_core.o zc0301_pas202bcb.o
+zc0301-objs     := zc0301_core.o zc0301_pb0330.o zc0301_pas202bcb.o
 
 obj-$(CONFIG_USB_ZC0301)        += zc0301.o
diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c
index 0fad397..1b2be2d 100644
--- a/drivers/media/video/zc0301/zc0301_core.c
+++ b/drivers/media/video/zc0301/zc0301_core.c
@@ -1,5 +1,5 @@
 /***************************************************************************
- * Video4Linux2 driver for ZC0301 Image Processor and Control Chip         *
+ * Video4Linux2 driver for ZC0301[P] Image Processor and Control Chip      *
  *                                                                         *
  * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
  *                                                                         *
@@ -47,13 +47,13 @@
 
 /*****************************************************************************/
 
-#define ZC0301_MODULE_NAME    "V4L2 driver for ZC0301 "                       \
+#define ZC0301_MODULE_NAME    "V4L2 driver for ZC0301[P] "                    \
 			      "Image Processor and Control Chip"
 #define ZC0301_MODULE_AUTHOR  "(C) 2006 Luca Risolia"
 #define ZC0301_AUTHOR_EMAIL   "<luca.risolia@studio.unibo.it>"
 #define ZC0301_MODULE_LICENSE "GPL"
-#define ZC0301_MODULE_VERSION "1:1.03"
-#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 3)
+#define ZC0301_MODULE_VERSION "1:1.05"
+#define ZC0301_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 5)
 
 /*****************************************************************************/
 
@@ -427,10 +427,11 @@
 static int zc0301_start_transfer(struct zc0301_device* cam)
 {
 	struct usb_device *udev = cam->usbdev;
+	struct usb_host_interface* altsetting = usb_altnum_to_altsetting(
+						     usb_ifnum_to_if(udev, 0),
+						     ZC0301_ALTERNATE_SETTING);
+	const unsigned int psz = altsetting->endpoint[0].desc.wMaxPacketSize;
 	struct urb* urb;
-	const unsigned int wMaxPacketSize[] = {0, 128, 192, 256, 384,
-					       512, 768, 1023};
-	const unsigned int psz = wMaxPacketSize[ZC0301_ALTERNATE_SETTING];
 	s8 i, j;
 	int err = 0;
 
@@ -1772,11 +1773,9 @@
 	case VIDIOC_G_CTRL:
 		return zc0301_vidioc_g_ctrl(cam, arg);
 
-	case VIDIOC_S_CTRL_OLD:
 	case VIDIOC_S_CTRL:
 		return zc0301_vidioc_s_ctrl(cam, arg);
 
-	case VIDIOC_CROPCAP_OLD:
 	case VIDIOC_CROPCAP:
 		return zc0301_vidioc_cropcap(cam, arg);
 
@@ -1823,7 +1822,6 @@
 	case VIDIOC_G_PARM:
 		return zc0301_vidioc_g_parm(cam, arg);
 
-	case VIDIOC_S_PARM_OLD:
 	case VIDIOC_S_PARM:
 		return zc0301_vidioc_s_parm(cam, arg);
 
@@ -1914,7 +1912,7 @@
 
 	mutex_init(&cam->dev_mutex);
 
-	DBG(2, "ZC0301 Image Processor and Control Chip detected "
+	DBG(2, "ZC0301[P] Image Processor and Control Chip detected "
 	       "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct);
 
 	for  (i = 0; zc0301_sensor_table[i]; i++) {
@@ -1936,7 +1934,7 @@
 		cam->state |= DEV_MISCONFIGURED;
 	}
 
-	strcpy(cam->v4ldev->name, "ZC0301 PC Camera");
+	strcpy(cam->v4ldev->name, "ZC0301[P] PC Camera");
 	cam->v4ldev->owner = THIS_MODULE;
 	cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
 	cam->v4ldev->hardware = 0;
diff --git a/drivers/media/video/zc0301/zc0301_pas202bcb.c b/drivers/media/video/zc0301/zc0301_pas202bcb.c
index eaadf02..ecfd39a 100644
--- a/drivers/media/video/zc0301/zc0301_pas202bcb.c
+++ b/drivers/media/video/zc0301/zc0301_pas202bcb.c
@@ -1,10 +1,10 @@
 /***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the ZC030! Image        *
+ * Plug-in for PAS202BCB image sensor connected to the ZC0301[P] Image     *
  * Processor and Control Chip                                              *
  *                                                                         *
  * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
  *                                                                         *
- * Initialization values of the ZC0301 have been taken from the SPCA5XX    *
+ * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
  * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
  *                                                                         *
  * This program is free software; you can redistribute it and/or modify    *
diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c
new file mode 100644
index 0000000..ed8542e
--- /dev/null
+++ b/drivers/media/video/zc0301/zc0301_pb0330.c
@@ -0,0 +1,187 @@
+/***************************************************************************
+ * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image       *
+ * Processor and Control Chip                                              *
+ *                                                                         *
+ * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
+ *                                                                         *
+ * Initialization values of the ZC0301[P] have been taken from the SPCA5XX *
+ * driver maintained by Michel Xhaard <mxhaard@magic.fr>                   *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 2 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program; if not, write to the Free Software             *
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               *
+ ***************************************************************************/
+
+#include <linux/delay.h>
+#include "zc0301_sensor.h"
+
+
+static struct zc0301_sensor pb0330;
+
+
+static int pb0330_init(struct zc0301_device* cam)
+{
+	int err = 0;
+
+	err += zc0301_write_reg(cam, 0x0000, 0x01);
+	err += zc0301_write_reg(cam, 0x0008, 0x03);
+	err += zc0301_write_reg(cam, 0x0010, 0x0A);
+	err += zc0301_write_reg(cam, 0x0002, 0x00);
+	err += zc0301_write_reg(cam, 0x0003, 0x02);
+	err += zc0301_write_reg(cam, 0x0004, 0x80);
+	err += zc0301_write_reg(cam, 0x0005, 0x01);
+	err += zc0301_write_reg(cam, 0x0006, 0xE0);
+	err += zc0301_write_reg(cam, 0x0001, 0x01);
+	err += zc0301_write_reg(cam, 0x0012, 0x05);
+	err += zc0301_write_reg(cam, 0x0012, 0x07);
+	err += zc0301_write_reg(cam, 0x0098, 0x00);
+	err += zc0301_write_reg(cam, 0x009A, 0x00);
+	err += zc0301_write_reg(cam, 0x011A, 0x00);
+	err += zc0301_write_reg(cam, 0x011C, 0x00);
+	err += zc0301_write_reg(cam, 0x0012, 0x05);
+
+	err += zc0301_i2c_write(cam, 0x01, 0x0006);
+	err += zc0301_i2c_write(cam, 0x02, 0x0011);
+	err += zc0301_i2c_write(cam, 0x03, 0x01E7);
+	err += zc0301_i2c_write(cam, 0x04, 0x0287);
+	err += zc0301_i2c_write(cam, 0x06, 0x0003);
+	err += zc0301_i2c_write(cam, 0x07, 0x3002);
+	err += zc0301_i2c_write(cam, 0x20, 0x1100);
+	err += zc0301_i2c_write(cam, 0x2F, 0xF7B0);
+	err += zc0301_i2c_write(cam, 0x30, 0x0005);
+	err += zc0301_i2c_write(cam, 0x31, 0x0000);
+	err += zc0301_i2c_write(cam, 0x34, 0x0100);
+	err += zc0301_i2c_write(cam, 0x35, 0x0060);
+	err += zc0301_i2c_write(cam, 0x3D, 0x068F);
+	err += zc0301_i2c_write(cam, 0x40, 0x01E0);
+	err += zc0301_i2c_write(cam, 0x58, 0x0078);
+	err += zc0301_i2c_write(cam, 0x62, 0x0411);
+
+	err += zc0301_write_reg(cam, 0x0087, 0x10);
+	err += zc0301_write_reg(cam, 0x0101, 0x37);
+	err += zc0301_write_reg(cam, 0x0012, 0x05);
+	err += zc0301_write_reg(cam, 0x0100, 0x0D);
+	err += zc0301_write_reg(cam, 0x0189, 0x06);
+	err += zc0301_write_reg(cam, 0x01AD, 0x00);
+	err += zc0301_write_reg(cam, 0x01C5, 0x03);
+	err += zc0301_write_reg(cam, 0x01CB, 0x13);
+	err += zc0301_write_reg(cam, 0x0250, 0x08);
+	err += zc0301_write_reg(cam, 0x0301, 0x08);
+	err += zc0301_write_reg(cam, 0x01A8, 0x60);
+	err += zc0301_write_reg(cam, 0x018D, 0x6C);
+	err += zc0301_write_reg(cam, 0x01AD, 0x09);
+	err += zc0301_write_reg(cam, 0x01AE, 0x15);
+	err += zc0301_write_reg(cam, 0x010A, 0x50);
+	err += zc0301_write_reg(cam, 0x010B, 0xF8);
+	err += zc0301_write_reg(cam, 0x010C, 0xF8);
+	err += zc0301_write_reg(cam, 0x010D, 0xF8);
+	err += zc0301_write_reg(cam, 0x010E, 0x50);
+	err += zc0301_write_reg(cam, 0x010F, 0xF8);
+	err += zc0301_write_reg(cam, 0x0110, 0xF8);
+	err += zc0301_write_reg(cam, 0x0111, 0xF8);
+	err += zc0301_write_reg(cam, 0x0112, 0x50);
+	err += zc0301_write_reg(cam, 0x0008, 0x03);
+	err += zc0301_write_reg(cam, 0x01C6, 0x08);
+	err += zc0301_write_reg(cam, 0x01CB, 0x0F);
+	err += zc0301_write_reg(cam, 0x010A, 0x50);
+	err += zc0301_write_reg(cam, 0x010B, 0xF8);
+	err += zc0301_write_reg(cam, 0x010C, 0xF8);
+	err += zc0301_write_reg(cam, 0x010D, 0xF8);
+	err += zc0301_write_reg(cam, 0x010E, 0x50);
+	err += zc0301_write_reg(cam, 0x010F, 0xF8);
+	err += zc0301_write_reg(cam, 0x0110, 0xF8);
+	err += zc0301_write_reg(cam, 0x0111, 0xF8);
+	err += zc0301_write_reg(cam, 0x0112, 0x50);
+	err += zc0301_write_reg(cam, 0x0180, 0x00);
+	err += zc0301_write_reg(cam, 0x0019, 0x00);
+
+	err += zc0301_i2c_write(cam, 0x05, 0x0066);
+	err += zc0301_i2c_write(cam, 0x09, 0x02B2);
+	err += zc0301_i2c_write(cam, 0x10, 0x0002);
+
+	err += zc0301_write_reg(cam, 0x011D, 0x60);
+	err += zc0301_write_reg(cam, 0x0190, 0x00);
+	err += zc0301_write_reg(cam, 0x0191, 0x07);
+	err += zc0301_write_reg(cam, 0x0192, 0x8C);
+	err += zc0301_write_reg(cam, 0x0195, 0x00);
+	err += zc0301_write_reg(cam, 0x0196, 0x00);
+	err += zc0301_write_reg(cam, 0x0197, 0x8A);
+	err += zc0301_write_reg(cam, 0x018C, 0x10);
+	err += zc0301_write_reg(cam, 0x018F, 0x20);
+	err += zc0301_write_reg(cam, 0x01A9, 0x14);
+	err += zc0301_write_reg(cam, 0x01AA, 0x24);
+	err += zc0301_write_reg(cam, 0x001D, 0xD7);
+	err += zc0301_write_reg(cam, 0x001E, 0xF0);
+	err += zc0301_write_reg(cam, 0x001F, 0xF8);
+	err += zc0301_write_reg(cam, 0x0020, 0xFF);
+	err += zc0301_write_reg(cam, 0x01AD, 0x09);
+	err += zc0301_write_reg(cam, 0x01AE, 0x15);
+	err += zc0301_write_reg(cam, 0x0180, 0x40);
+	err += zc0301_write_reg(cam, 0x0180, 0x42);
+
+	msleep(100);
+
+	return err;
+}
+
+
+static struct zc0301_sensor pb0330 = {
+	.name = "PB-0330",
+	.init = &pb0330_init,
+	.cropcap = {
+		.bounds = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+		.defrect = {
+			.left = 0,
+			.top = 0,
+			.width = 640,
+			.height = 480,
+		},
+	},
+	.pix_format = {
+		.width = 640,
+		.height = 480,
+		.pixelformat = V4L2_PIX_FMT_JPEG,
+		.priv = 8,
+	},
+};
+
+
+int zc0301_probe_pb0330(struct zc0301_device* cam)
+{
+	int r0, err = 0;
+
+	err += zc0301_write_reg(cam, 0x0000, 0x01);
+	err += zc0301_write_reg(cam, 0x0010, 0x0a);
+	err += zc0301_write_reg(cam, 0x0001, 0x01);
+	err += zc0301_write_reg(cam, 0x0012, 0x03);
+	err += zc0301_write_reg(cam, 0x0012, 0x01);
+
+	msleep(10);
+
+	r0 = zc0301_i2c_read(cam, 0x00, 2);
+
+	if (r0 < 0 || err)
+		return -EIO;
+
+	if (r0 != 0x8243)
+		return -ENODEV;
+
+	zc0301_attach_sensor(cam, &pb0330);
+
+	return 0;
+}
diff --git a/drivers/media/video/zc0301/zc0301_sensor.h b/drivers/media/video/zc0301/zc0301_sensor.h
index 1f95c28..4363a91 100644
--- a/drivers/media/video/zc0301/zc0301_sensor.h
+++ b/drivers/media/video/zc0301/zc0301_sensor.h
@@ -1,5 +1,5 @@
 /***************************************************************************
- * API for image sensors connected to the ZC030! Image Processor and       *
+ * API for image sensors connected to the ZC0301 Image Processor and       *
  * Control Chip                                                            *
  *                                                                         *
  * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it>       *
@@ -35,11 +35,13 @@
 /*****************************************************************************/
 
 extern int zc0301_probe_pas202bcb(struct zc0301_device* cam);
+extern int zc0301_probe_pb0330(struct zc0301_device* cam);
 
 #define ZC0301_SENSOR_TABLE                                                   \
 /* Weak detections must go at the end of the list */                          \
 static int (*zc0301_sensor_table[])(struct zc0301_device*) = {                \
 	&zc0301_probe_pas202bcb,                                              \
+	&zc0301_probe_pb0330,                                                 \
 	NULL,                                                                 \
 };
 
@@ -58,14 +60,28 @@
 
 #define ZC0301_ID_TABLE                                                       \
 static const struct usb_device_id zc0301_id_table[] =  {                      \
-	{ ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), },                         \
+	{ ZC0301_USB_DEVICE(0x041e, 0x4017, 0xff), }, /* ICM105 */            \
 	{ ZC0301_USB_DEVICE(0x041e, 0x401c, 0xff), }, /* PAS106 */            \
-	{ ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131B */           \
+	{ ZC0301_USB_DEVICE(0x041e, 0x401e, 0xff), }, /* HV7131 */            \
+	{ ZC0301_USB_DEVICE(0x041e, 0x401f, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x041e, 0x4022, 0xff), },                         \
 	{ ZC0301_USB_DEVICE(0x041e, 0x4034, 0xff), }, /* PAS106 */            \
 	{ ZC0301_USB_DEVICE(0x041e, 0x4035, 0xff), }, /* PAS106 */            \
-	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202BCB */         \
+	{ ZC0301_USB_DEVICE(0x041e, 0x4036, 0xff), }, /* HV7131 */            \
+	{ ZC0301_USB_DEVICE(0x041e, 0x403a, 0xff), }, /* HV7131 */            \
+	{ ZC0301_USB_DEVICE(0x0458, 0x7007, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x0458, 0x700C, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x0458, 0x700f, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
+	{ ZC0301_USB_DEVICE(0x055f, 0xd003, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x055f, 0xd004, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x046d, 0x08ae, 0xff), }, /* PAS202 */            \
 	{ ZC0301_USB_DEVICE(0x0ac8, 0x0301, 0xff), },                         \
-	{ ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130D */          \
+	{ ZC0301_USB_DEVICE(0x0ac8, 0x301b, 0xff), }, /* PB-0330/HV7131 */    \
+	{ ZC0301_USB_DEVICE(0x0ac8, 0x303b, 0xff), }, /* PB-0330 */           \
+	{ ZC0301_USB_DEVICE(0x10fd, 0x0128, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x10fd, 0x8050, 0xff), }, /* TAS5130 */           \
+	{ ZC0301_USB_DEVICE(0x10fd, 0x804e, 0xff), }, /* TAS5130 */           \
 	{ }                                                                   \
 };
 
diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h
index 0166f55..ffcda95 100644
--- a/drivers/media/video/zoran.h
+++ b/drivers/media/video/zoran.h
@@ -159,7 +159,7 @@
 #define BUZ_MAX_FRAME     256	/* Must be a power of 2 */
 #define BUZ_MASK_FRAME    255	/* Must be BUZ_MAX_FRAME-1 */
 
-#define BUZ_MAX_INPUT       8
+#define BUZ_MAX_INPUT       16
 
 #if VIDEO_MAX_FRAME <= 32
 #   define   V4L_MAX_FRAME   32
@@ -191,6 +191,9 @@
 	/* Iomega */
 	BUZ,
 
+	/* AverMedia */
+	AVS6EYES,
+
 	/* total number of cards */
 	NUM_CARDS
 };
@@ -379,6 +382,9 @@
 	/* is the /GWS line conected? */
 	u8 gws_not_connected;
 
+	/* avs6eyes mux setting */
+	u8 input_mux;
+
 	void (*init) (struct zoran * zr);
 };
 
diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
index 0a85c9e..958c1e6 100644
--- a/drivers/media/video/zoran_card.c
+++ b/drivers/media/video/zoran_card.c
@@ -27,6 +27,8 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/delay.h>
+
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -38,6 +40,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/spinlock.h>
 #include <linux/sem.h>
 #include <linux/kmod.h>
@@ -93,6 +96,11 @@
 MODULE_PARM_DESC(default_input,
 		 "Default input (0=Composite, 1=S-Video, 2=Internal)");
 
+static int default_mux = 1;	/* 6 Eyes input selection */
+module_param(default_mux, int, 0);
+MODULE_PARM_DESC(default_mux,
+		 "Default 6 Eyes mux setting (Input selection)");
+
 static int default_norm = 0;	/* 0=PAL, 1=NTSC 2=SECAM */
 module_param(default_norm, int, 0);
 MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)");
@@ -301,6 +309,30 @@
 	GPIO(zr, 2, 1);		// Set Composite input/output
 }
 
+static void
+avs6eyes_init (struct zoran *zr)
+{
+	// AverMedia 6-Eyes original driver by Christer Weinigel
+
+	// Lifted straight from Christer's old driver and
+	// modified slightly by Martin Samuelsson.
+
+	int mux = default_mux; /* 1 = BT866, 7 = VID1 */
+
+	GPIO(zr, 4, 1); /* Bt866 SLEEP on */
+	udelay(2);
+
+	GPIO(zr, 0, 1); /* ZR36060 /RESET on */
+	GPIO(zr, 1, 0); /* ZR36060 /SLEEP on */
+	GPIO(zr, 2, mux & 1);   /* MUX S0 */
+	GPIO(zr, 3, 0); /* /FRAME on */
+	GPIO(zr, 4, 0); /* Bt866 SLEEP off */
+	GPIO(zr, 5, mux & 2);   /* MUX S1 */
+	GPIO(zr, 6, 0); /* ? */
+	GPIO(zr, 7, mux & 4);   /* MUX S2 */
+
+}
+
 static char *
 i2cid_to_modulename (u16 i2c_id)
 {
@@ -391,6 +423,14 @@
 static struct tvnorm f50ccir601_lm33r10 = { 864, 720, 74+54, 804, 625, 576, 18 };
 static struct tvnorm f60ccir601_lm33r10 = { 858, 720, 56+54, 788, 525, 480, 16 };
 
+/* FIXME: The ks0127 seem incapable of swapping U and V, too, which is why I
+ * copy Maxim's left shift hack for the 6 Eyes.
+ *
+ * Christer's driver used the unshifted norms, though...
+ * /Sam  */
+static struct tvnorm f50ccir601_avs6eyes = { 864, 720, 74, 804, 625, 576, 18 };
+static struct tvnorm f60ccir601_avs6eyes = { 858, 720, 56, 788, 525, 480, 16 };
+
 static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
 	{
 		.type = DC10_old,
@@ -419,6 +459,7 @@
 		.gpcs = { -1, 0 },
 		.vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
 		.gws_not_connected = 0,
+		.input_mux = 0,
 		.init = &dc10_init,
 	}, {
 		.type = DC10_new,
@@ -445,6 +486,7 @@
 		.gpcs = { -1, 1},
 		.vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
 		.gws_not_connected = 0,
+		.input_mux = 0,
 		.init = &dc10plus_init,
 	}, {
 		.type = DC10plus,
@@ -474,6 +516,7 @@
 		.gpcs = { -1, 1 },
 		.vfe_pol = { 1, 1, 1, 1, 0, 0, 0, 0 },
 		.gws_not_connected = 0,
+		.input_mux = 0,
 		.init = &dc10plus_init,
 	}, {
 		.type = DC30,
@@ -502,6 +545,7 @@
 		.gpcs = { -1, 0 },
 		.vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
 		.gws_not_connected = 0,
+		.input_mux = 0,
 		.init = &dc10_init,
 	}, {
 		.type = DC30plus,
@@ -532,6 +576,7 @@
 		.gpcs = { -1, 0 },
 		.vfe_pol = { 0, 0, 0, 0, 0, 0, 0, 0 },
 		.gws_not_connected = 0,
+		.input_mux = 0,
 		.init = &dc10_init,
 	}, {
 		.type = LML33,
@@ -558,6 +603,7 @@
 		.gpcs = { 3, 1 },
 		.vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
 		.gws_not_connected = 1,
+		.input_mux = 0,
 		.init = &lml33_init,
 	}, {
 		.type = LML33R10,
@@ -586,6 +632,7 @@
 		.gpcs = { 3, 1 },
 		.vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
 		.gws_not_connected = 1,
+		.input_mux = 0,
 		.init = &lml33_init,
 	}, {
 		.type = BUZ,
@@ -614,8 +661,49 @@
 		.gpcs = { 3, 1 },
 		.vfe_pol = { 1, 1, 0, 0, 0, 1, 0, 0 },
 		.gws_not_connected = 1,
+		.input_mux = 0,
 		.init = &buz_init,
+	}, {
+		.type = AVS6EYES,
+		.name = "6-Eyes",
+		/* AverMedia chose not to brand the 6-Eyes. Thus it
+		   can't be autodetected, and requires card=x. */
+		.vendor_id = -1,
+		.device_id = -1,
+		.i2c_decoder = I2C_DRIVERID_KS0127,
+		.i2c_encoder = I2C_DRIVERID_BT866,
+		.video_codec = CODEC_TYPE_ZR36060,
+
+		.inputs = 10,
+		.input = {
+			{ 0, "Composite 1" },
+			{ 1, "Composite 2" },
+			{ 2, "Composite 3" },
+			{ 4, "Composite 4" },
+			{ 5, "Composite 5" },
+			{ 6, "Composite 6" },
+			{ 8, "S-Video 1" },
+			{ 9, "S-Video 2" },
+			{10, "S-Video 3" },
+			{15, "YCbCr" }
+		},
+		.norms = 2,
+		.tvn = {
+			&f50ccir601_avs6eyes,
+			&f60ccir601_avs6eyes,
+			NULL
+		},
+		.jpeg_int = ZR36057_ISR_GIRQ1,
+		.vsync_int = ZR36057_ISR_GIRQ0,
+		.gpio = { 1, 0, 3, -1, -1, -1, -1, -1 },// Validity unknown /Sam
+		.gpio_pol = { 0, 0, 0, 0, 0, 0, 0, 0 }, // Validity unknown /Sam
+		.gpcs = { 3, 1 },			// Validity unknown /Sam
+		.vfe_pol = { 1, 0, 0, 0, 0, 1, 0, 0 },  // Validity unknown /Sam
+		.gws_not_connected = 1,
+		.input_mux = 1,
+		.init = &avs6eyes_init,
 	}
+
 };
 
 /*
diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c
index c690b2e..02168d9 100644
--- a/drivers/media/video/zoran_device.c
+++ b/drivers/media/video/zoran_device.c
@@ -536,7 +536,7 @@
 		 * All error messages are internal driver checking only! */
 
 		/* video display top and bottom registers */
-		reg = (u32) zr->buffer.base +
+		reg = (long) zr->buffer.base +
 		    zr->overlay_settings.x *
 		    ((zr->overlay_settings.format->depth + 7) / 8) +
 		    zr->overlay_settings.y *
diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
index b5a576a..9711f62 100644
--- a/drivers/media/video/zoran_driver.c
+++ b/drivers/media/video/zoran_driver.c
@@ -73,6 +73,7 @@
 			     )
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include "videocodec.h"
 
 #include <asm/io.h>
@@ -2047,7 +2048,7 @@
 		dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr));
 
 		memset(vcap, 0, sizeof(struct video_capability));
-		strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name));
+		strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name)-1);
 		vcap->type = ZORAN_VID_TYPE;
 
 		vcap->channels = zr->card.inputs;
@@ -2689,8 +2690,8 @@
 		dprintk(3, KERN_DEBUG "%s: VIDIOC_QUERYCAP\n", ZR_DEVNAME(zr));
 
 		memset(cap, 0, sizeof(*cap));
-		strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
-		strncpy(cap->driver, "zoran", sizeof(cap->driver));
+		strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card)-1);
+		strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
 		snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
 			 pci_name(zr->pci_dev));
 		cap->version =
@@ -2742,7 +2743,7 @@
 		memset(fmt, 0, sizeof(*fmt));
 		fmt->index = index;
 		fmt->type = type;
-		strncpy(fmt->description, zoran_formats[i].name, 31);
+		strncpy(fmt->description, zoran_formats[i].name, sizeof(fmt->description)-1);
 		fmt->pixelformat = zoran_formats[i].fourcc;
 		if (zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)
 			fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
@@ -3566,16 +3567,16 @@
 
 		switch (ctrl->id) {
 		case V4L2_CID_BRIGHTNESS:
-			strncpy(ctrl->name, "Brightness", 31);
+			strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1);
 			break;
 		case V4L2_CID_CONTRAST:
-			strncpy(ctrl->name, "Contrast", 31);
+			strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1);
 			break;
 		case V4L2_CID_SATURATION:
-			strncpy(ctrl->name, "Saturation", 31);
+			strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1);
 			break;
 		case V4L2_CID_HUE:
-			strncpy(ctrl->name, "Hue", 31);
+			strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1);
 			break;
 		}
 
@@ -3693,7 +3694,7 @@
 					&caps);
 			if (caps.flags & VIDEO_DECODER_AUTO) {
 				std->id = V4L2_STD_ALL;
-				strncpy(std->name, "Autodetect", 31);
+				strncpy(std->name, "Autodetect", sizeof(std->name)-1);
 				return 0;
 			} else
 				return -EINVAL;
@@ -3701,21 +3702,21 @@
 		switch (std->index) {
 		case 0:
 			std->id = V4L2_STD_PAL;
-			strncpy(std->name, "PAL", 31);
+			strncpy(std->name, "PAL", sizeof(std->name)-1);
 			std->frameperiod.numerator = 1;
 			std->frameperiod.denominator = 25;
 			std->framelines = zr->card.tvn[0]->Ht;
 			break;
 		case 1:
 			std->id = V4L2_STD_NTSC;
-			strncpy(std->name, "NTSC", 31);
+			strncpy(std->name, "NTSC", sizeof(std->name)-1);
 			std->frameperiod.numerator = 1001;
 			std->frameperiod.denominator = 30000;
 			std->framelines = zr->card.tvn[1]->Ht;
 			break;
 		case 2:
 			std->id = V4L2_STD_SECAM;
-			strncpy(std->name, "SECAM", 31);
+			strncpy(std->name, "SECAM", sizeof(std->name)-1);
 			std->frameperiod.numerator = 1;
 			std->frameperiod.denominator = 25;
 			std->framelines = zr->card.tvn[2]->Ht;
@@ -3871,7 +3872,7 @@
 		memset(outp, 0, sizeof(*outp));
 		outp->index = 0;
 		outp->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
-		strncpy(outp->name, "Autodetect", 31);
+		strncpy(outp->name, "Autodetect", sizeof(outp->name)-1);
 
 		return 0;
 	}
diff --git a/drivers/media/video/zoran_procfs.c b/drivers/media/video/zoran_procfs.c
index a00fae9..f4ffe79 100644
--- a/drivers/media/video/zoran_procfs.c
+++ b/drivers/media/video/zoran_procfs.c
@@ -43,6 +43,7 @@
 #include <linux/seq_file.h>
 
 #include <linux/ctype.h>
+#include <linux/poll.h>
 #include <asm/io.h>
 
 #include "videocodec.h"
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index a300840..12dd8d4 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -63,9 +63,6 @@
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
-#ifdef __sparc__
-#include <asm/irq.h>			/* needed for __irq_itoa() proto */
-#endif
 
 #include "mptbase.h"
 
@@ -1188,7 +1185,6 @@
 	ioc->pcidev = pdev;
 	ioc->diagPending = 0;
 	spin_lock_init(&ioc->diagLock);
-	spin_lock_init(&ioc->fc_rescan_work_lock);
 	spin_lock_init(&ioc->initializing_hba_lock);
 
 	/* Initialize the event logging.
@@ -1386,39 +1382,6 @@
 	/* Set lookup ptr. */
 	list_add_tail(&ioc->list, &ioc_list);
 
-	ioc->pci_irq = -1;
-	if (pdev->irq) {
-		if (mpt_msi_enable && !pci_enable_msi(pdev))
-			printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", ioc->name);
-
-		r = request_irq(pdev->irq, mpt_interrupt, SA_SHIRQ, ioc->name, ioc);
-
-		if (r < 0) {
-#ifndef __sparc__
-			printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %d!\n",
-					ioc->name, pdev->irq);
-#else
-			printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
-					ioc->name, __irq_itoa(pdev->irq));
-#endif
-			list_del(&ioc->list);
-			iounmap(mem);
-			kfree(ioc);
-			return -EBUSY;
-		}
-
-		ioc->pci_irq = pdev->irq;
-
-		pci_set_master(pdev);			/* ?? */
-		pci_set_drvdata(pdev, ioc);
-
-#ifndef __sparc__
-		dprintk((KERN_INFO MYNAM ": %s installed at interrupt %d\n", ioc->name, pdev->irq));
-#else
-		dprintk((KERN_INFO MYNAM ": %s installed at interrupt %s\n", ioc->name, __irq_itoa(pdev->irq)));
-#endif
-	}
-
 	/* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
 	 */
 	mpt_detect_bound_ports(ioc, pdev);
@@ -1428,11 +1391,7 @@
 		printk(KERN_WARNING MYNAM
 		  ": WARNING - %s did not initialize properly! (%d)\n",
 		  ioc->name, r);
-
 		list_del(&ioc->list);
-		free_irq(ioc->pci_irq, ioc);
-		if (mpt_msi_enable)
-			pci_disable_msi(pdev);
 		if (ioc->alt_ioc)
 			ioc->alt_ioc->alt_ioc = NULL;
 		iounmap(mem);
@@ -1651,6 +1610,7 @@
 	int	 handlers;
 	int	 ret = 0;
 	int	 reset_alt_ioc_active = 0;
+	int	 irq_allocated = 0;
 
 	printk(KERN_INFO MYNAM ": Initiating %s %s\n",
 			ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");
@@ -1734,6 +1694,36 @@
 		}
 	}
 
+	/*
+	 * Device is reset now. It must have de-asserted the interrupt line
+	 * (if it was asserted) and it should be safe to register for the
+	 * interrupt now.
+	 */
+	if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP)) {
+		ioc->pci_irq = -1;
+		if (ioc->pcidev->irq) {
+			if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev))
+				printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n",
+					ioc->name);
+			rc = request_irq(ioc->pcidev->irq, mpt_interrupt,
+					SA_SHIRQ, ioc->name, ioc);
+			if (rc < 0) {
+				printk(MYIOC_s_ERR_FMT "Unable to allocate "
+					"interrupt %d!\n", ioc->name,
+					ioc->pcidev->irq);
+				if (mpt_msi_enable)
+					pci_disable_msi(ioc->pcidev);
+				return -EBUSY;
+			}
+			irq_allocated = 1;
+			ioc->pci_irq = ioc->pcidev->irq;
+			pci_set_master(ioc->pcidev);		/* ?? */
+			pci_set_drvdata(ioc->pcidev, ioc);
+			dprintk((KERN_INFO MYNAM ": %s installed at interrupt "
+				"%d\n", ioc->name, ioc->pcidev->irq));
+		}
+	}
+
 	/* Prime reply & request queues!
 	 * (mucho alloc's) Must be done prior to
 	 * init as upper addresses are needed for init.
@@ -1833,7 +1823,7 @@
 				ret = mptbase_sas_persist_operation(ioc,
 				    MPI_SAS_OP_CLEAR_NOT_PRESENT);
 				if(ret != 0)
-					return -1;
+					goto out;
 			}
 
 			/* Find IM volumes
@@ -1841,14 +1831,6 @@
 			mpt_findImVolumes(ioc);
 
 		} else if (ioc->bus_type == FC) {
-			/*
-			 *  Pre-fetch FC port WWN and stuff...
-			 *  (FCPortPage0_t stuff)
-			 */
-			for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-				(void) mptbase_GetFcPortPage0(ioc, ii);
-			}
-
 			if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
 			    (ioc->lan_cnfg_page0.Header.PageLength == 0)) {
 				/*
@@ -1914,6 +1896,12 @@
 		/* FIXME?  Examine results here? */
 	}
 
+out:
+	if ((ret != 0) && irq_allocated) {
+		free_irq(ioc->pci_irq, ioc);
+		if (mpt_msi_enable)
+			pci_disable_msi(ioc->pcidev);
+	}
 	return ret;
 }
 
@@ -2288,7 +2276,7 @@
 		}
 
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible(1);
+			msleep(1);
 		} else {
 			mdelay (1);	/* 1 msec delay */
 		}
@@ -2676,7 +2664,7 @@
 	state = mpt_GetIocState(ioc, 1);
 	while (state != MPI_IOC_STATE_OPERATIONAL && --cntdn) {
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible(1);
+			msleep(1);
 		} else {
 			mdelay(1);
 		}
@@ -2928,7 +2916,7 @@
 
 	/* wait 1 msec */
 	if (sleepFlag == CAN_SLEEP) {
-		msleep_interruptible(1);
+		msleep(1);
 	} else {
 		mdelay (1);
 	}
@@ -2945,7 +2933,7 @@
 		}
 		/* wait .1 sec */
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible (100);
+			msleep (100);
 		} else {
 			mdelay (100);
 		}
@@ -3035,7 +3023,7 @@
 
 		/* wait 1 msec */
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible (1);
+			msleep (1);
 		} else {
 			mdelay (1);
 		}
@@ -3083,7 +3071,7 @@
 			return 0;
 		}
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible (10);
+			msleep (10);
 		} else {
 			mdelay (10);
 		}
@@ -3134,7 +3122,7 @@
 		SendIocReset(ioc, MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET, sleepFlag);
 
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible (1000);
+			msleep (1000);
 		} else {
 			mdelay (1000);
 		}
@@ -3156,7 +3144,7 @@
 			return hard_reset_done;
 		}
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible (10);
+			msleep (10);
 		} else {
 			mdelay (10);
 		}
@@ -3227,7 +3215,7 @@
 
 			/* wait 100 msec */
 			if (sleepFlag == CAN_SLEEP) {
-				msleep_interruptible (100);
+				msleep (100);
 			} else {
 				mdelay (100);
 			}
@@ -3306,7 +3294,7 @@
 
 				/* wait 1 sec */
 				if (sleepFlag == CAN_SLEEP) {
-					msleep_interruptible (1000);
+					msleep (1000);
 				} else {
 					mdelay (1000);
 				}
@@ -3334,7 +3322,7 @@
 
 				/* wait 1 sec */
 				if (sleepFlag == CAN_SLEEP) {
-					msleep_interruptible (1000);
+					msleep (1000);
 				} else {
 					mdelay (1000);
 				}
@@ -3368,7 +3356,7 @@
 
 		/* wait 100 msec */
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible (100);
+			msleep (100);
 		} else {
 			mdelay (100);
 		}
@@ -3462,7 +3450,7 @@
 		}
 
 		if (sleepFlag == CAN_SLEEP) {
-			msleep_interruptible(1);
+			msleep(1);
 		} else {
 			mdelay (1);	/* 1 msec delay */
 		}
@@ -3902,7 +3890,7 @@
 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
 				break;
-			msleep_interruptible (1);
+			msleep (1);
 			count++;
 		}
 	} else {
@@ -3951,7 +3939,7 @@
 			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
 				break;
-			msleep_interruptible(1);
+			msleep(1);
 			count++;
 		}
 	} else {
@@ -4174,108 +4162,6 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
- *	@ioc: Pointer to MPT_ADAPTER structure
- *	@portnum: IOC Port number
- *
- *	Return: 0 for success
- *	-ENOMEM if no memory available
- *		-EPERM if not allowed due to ISR context
- *		-EAGAIN if no msg frames currently available
- *		-EFAULT for non-successful reply or no reply (timeout)
- */
-int
-mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
-{
-	ConfigPageHeader_t	 hdr;
-	CONFIGPARMS		 cfg;
-	FCPortPage0_t		*ppage0_alloc;
-	FCPortPage0_t		*pp0dest;
-	dma_addr_t		 page0_dma;
-	int			 data_sz;
-	int			 copy_sz;
-	int			 rc;
-	int			 count = 400;
-
-
-	/* Get FCPort Page 0 header */
-	hdr.PageVersion = 0;
-	hdr.PageLength = 0;
-	hdr.PageNumber = 0;
-	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
-	cfg.cfghdr.hdr = &hdr;
-	cfg.physAddr = -1;
-	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
-	cfg.dir = 0;
-	cfg.pageAddr = portnum;
-	cfg.timeout = 0;
-
-	if ((rc = mpt_config(ioc, &cfg)) != 0)
-		return rc;
-
-	if (hdr.PageLength == 0)
-		return 0;
-
-	data_sz = hdr.PageLength * 4;
-	rc = -ENOMEM;
-	ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
-	if (ppage0_alloc) {
-
- try_again:
-		memset((u8 *)ppage0_alloc, 0, data_sz);
-		cfg.physAddr = page0_dma;
-		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
-
-		if ((rc = mpt_config(ioc, &cfg)) == 0) {
-			/* save the data */
-			pp0dest = &ioc->fc_port_page0[portnum];
-			copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
-			memcpy(pp0dest, ppage0_alloc, copy_sz);
-
-			/*
-			 *	Normalize endianness of structure data,
-			 *	by byte-swapping all > 1 byte fields!
-			 */
-			pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
-			pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
-			pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
-			pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
-			pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
-			pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
-			pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
-			pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
-			pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
-			pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
-			pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
-			pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
-			pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
-			pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
-			pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
-			pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
-
-			/*
-			 * if still doing discovery,
-			 * hang loose a while until finished
-			 */
-			if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
-				if (count-- > 0) {
-					msleep_interruptible(100);
-					goto try_again;
-				}
-				printk(MYIOC_s_INFO_FMT "Firmware discovery not"
-							" complete.\n",
-						ioc->name);
-			}
-		}
-
-		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
-	}
-
-	return rc;
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
  *	mptbase_sas_persist_operation - Perform operation on SAS Persitent Table
  *	@ioc: Pointer to MPT_ADAPTER structure
  *	@sas_address: 64bit SAS Address for operation.
@@ -5647,11 +5533,7 @@
 			a[5], a[4], a[3], a[2], a[1], a[0]);
 	}
 
-#ifndef __sparc__
 	y += sprintf(buffer+len+y, ", IRQ=%d", ioc->pci_irq);
-#else
-	y += sprintf(buffer+len+y, ", IRQ=%s", __irq_itoa(ioc->pci_irq));
-#endif
 
 	if (!ioc->active)
 		y += sprintf(buffer+len+y, " (disabled)");
@@ -6483,7 +6365,6 @@
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
-EXPORT_SYMBOL(mptbase_GetFcPortPage0);
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index f673cca..4720f9a 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -76,8 +76,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.03.09"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.09"
+#define MPT_LINUX_VERSION_COMMON	"3.03.10"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.10"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -487,6 +487,15 @@
 	int		 isRaid;		/* bit field, 1 if RAID */
 }RaidCfgData;
 
+typedef struct _FcCfgData {
+	/* will ultimately hold fc_port_page0 also */
+	struct {
+		FCPortPage1_t	*data;
+		dma_addr_t	 dma;
+		int		 pg_sz;
+	}			 fc_port_page1[2];
+} FcCfgData;
+
 #define MPT_RPORT_INFO_FLAGS_REGISTERED	0x01	/* rport registered */
 #define MPT_RPORT_INFO_FLAGS_MISSING	0x02	/* missing from DevPage0 scan */
 
@@ -565,6 +574,7 @@
 	SpiCfgData		spi_data;	/* Scsi config. data */
 	RaidCfgData		raid_data;	/* Raid config. data */
 	SasCfgData		sas_data;	/* Sas config. data */
+	FcCfgData		fc_data;	/* Fc config. data */
 	MPT_IOCTL		*ioctl;		/* ioctl data pointer */
 	struct proc_dir_entry	*ioc_dentry;
 	struct _MPT_ADAPTER	*alt_ioc;	/* ptr to 929 bound adapter port */
@@ -625,6 +635,7 @@
 	int			 num_ports;
 	struct work_struct	 mptscsih_persistTask;
 
+	struct work_struct	 fc_setup_reset_work;
 	struct list_head	 fc_rports;
 	spinlock_t		 fc_rescan_work_lock;
 	int			 fc_rescan_work_count;
@@ -1027,7 +1038,6 @@
 extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc);
 extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
-extern int	 mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 
 /*
  *  Public data decl's...
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 8564877..3ff8378 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -169,13 +169,6 @@
 
 };
 
-/* FIXME! values controlling firmware RESCAN event
- * need to be set low to allow dev_loss_tmo to
- * work as expected.  Currently, firmware doesn't
- * notify driver of RESCAN event until some number
- * of seconds elapse.  This value can be set via
- * lsiutil.
- */
 static void
 mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
 {
@@ -312,10 +305,8 @@
 	}
 
  out:
-	if (pp0_array)
-		kfree(pp0_array);
-	if (p0_array)
-		kfree(p0_array);
+	kfree(pp0_array);
+	kfree(p0_array);
 	return rc;
 }
 
@@ -587,15 +578,266 @@
 #ifdef DMPT_DEBUG_FC
 	if (unlikely(err)) {
 		dfcprintk ((MYIOC_s_INFO_FMT
-			"mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero.\n",
+			"mptfc_qcmd.%d: %d:%d, mptscsih_qcmd returns non-zero, (%x).\n",
 			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->name,
 			((MPT_SCSI_HOST *) SCpnt->device->host->hostdata)->ioc->sh->host_no,
-			SCpnt->device->id,SCpnt->device->lun));
+			SCpnt->device->id,SCpnt->device->lun,err));
 	}
 #endif
 	return err;
 }
 
+/*
+ *	mptfc_GetFcPortPage0 - Fetch FCPort config Page0.
+ *	@ioc: Pointer to MPT_ADAPTER structure
+ *	@portnum: IOC Port number
+ *
+ *	Return: 0 for success
+ *	-ENOMEM if no memory available
+ *		-EPERM if not allowed due to ISR context
+ *		-EAGAIN if no msg frames currently available
+ *		-EFAULT for non-successful reply or no reply (timeout)
+ *		-EINVAL portnum arg out of range (hardwired to two elements)
+ */
+static int
+mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+{
+	ConfigPageHeader_t	 hdr;
+	CONFIGPARMS		 cfg;
+	FCPortPage0_t		*ppage0_alloc;
+	FCPortPage0_t		*pp0dest;
+	dma_addr_t		 page0_dma;
+	int			 data_sz;
+	int			 copy_sz;
+	int			 rc;
+	int			 count = 400;
+
+	if (portnum > 1)
+		return -EINVAL;
+
+	/* Get FCPort Page 0 header */
+	hdr.PageVersion = 0;
+	hdr.PageLength = 0;
+	hdr.PageNumber = 0;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.pageAddr = portnum;
+	cfg.timeout = 0;
+
+	if ((rc = mpt_config(ioc, &cfg)) != 0)
+		return rc;
+
+	if (hdr.PageLength == 0)
+		return 0;
+
+	data_sz = hdr.PageLength * 4;
+	rc = -ENOMEM;
+	ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
+	if (ppage0_alloc) {
+
+ try_again:
+		memset((u8 *)ppage0_alloc, 0, data_sz);
+		cfg.physAddr = page0_dma;
+		cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+		if ((rc = mpt_config(ioc, &cfg)) == 0) {
+			/* save the data */
+			pp0dest = &ioc->fc_port_page0[portnum];
+			copy_sz = min_t(int, sizeof(FCPortPage0_t), data_sz);
+			memcpy(pp0dest, ppage0_alloc, copy_sz);
+
+			/*
+			 *	Normalize endianness of structure data,
+			 *	by byte-swapping all > 1 byte fields!
+			 */
+			pp0dest->Flags = le32_to_cpu(pp0dest->Flags);
+			pp0dest->PortIdentifier = le32_to_cpu(pp0dest->PortIdentifier);
+			pp0dest->WWNN.Low = le32_to_cpu(pp0dest->WWNN.Low);
+			pp0dest->WWNN.High = le32_to_cpu(pp0dest->WWNN.High);
+			pp0dest->WWPN.Low = le32_to_cpu(pp0dest->WWPN.Low);
+			pp0dest->WWPN.High = le32_to_cpu(pp0dest->WWPN.High);
+			pp0dest->SupportedServiceClass = le32_to_cpu(pp0dest->SupportedServiceClass);
+			pp0dest->SupportedSpeeds = le32_to_cpu(pp0dest->SupportedSpeeds);
+			pp0dest->CurrentSpeed = le32_to_cpu(pp0dest->CurrentSpeed);
+			pp0dest->MaxFrameSize = le32_to_cpu(pp0dest->MaxFrameSize);
+			pp0dest->FabricWWNN.Low = le32_to_cpu(pp0dest->FabricWWNN.Low);
+			pp0dest->FabricWWNN.High = le32_to_cpu(pp0dest->FabricWWNN.High);
+			pp0dest->FabricWWPN.Low = le32_to_cpu(pp0dest->FabricWWPN.Low);
+			pp0dest->FabricWWPN.High = le32_to_cpu(pp0dest->FabricWWPN.High);
+			pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
+			pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
+
+			/*
+			 * if still doing discovery,
+			 * hang loose a while until finished
+			 */
+			if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+				if (count-- > 0) {
+					msleep(100);
+					goto try_again;
+				}
+				printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+							" complete.\n",
+						ioc->name);
+			}
+		}
+
+		pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
+	}
+
+	return rc;
+}
+
+static int
+mptfc_WriteFcPortPage1(MPT_ADAPTER *ioc, int portnum)
+{
+	ConfigPageHeader_t	 hdr;
+	CONFIGPARMS		 cfg;
+	int			 rc;
+
+	if (portnum > 1)
+		return -EINVAL;
+
+	if (!(ioc->fc_data.fc_port_page1[portnum].data))
+		return -EINVAL;
+
+	/* get fcport page 1 header */
+	hdr.PageVersion = 0;
+	hdr.PageLength = 0;
+	hdr.PageNumber = 1;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.pageAddr = portnum;
+	cfg.timeout = 0;
+
+	if ((rc = mpt_config(ioc, &cfg)) != 0)
+		return rc;
+
+	if (hdr.PageLength == 0)
+		return -ENODEV;
+
+	if (hdr.PageLength*4 != ioc->fc_data.fc_port_page1[portnum].pg_sz)
+		return -EINVAL;
+
+	cfg.physAddr = ioc->fc_data.fc_port_page1[portnum].dma;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+	cfg.dir = 1;
+
+	rc = mpt_config(ioc, &cfg);
+
+	return rc;
+}
+
+static int
+mptfc_GetFcPortPage1(MPT_ADAPTER *ioc, int portnum)
+{
+	ConfigPageHeader_t	 hdr;
+	CONFIGPARMS		 cfg;
+	FCPortPage1_t		*page1_alloc;
+	dma_addr_t		 page1_dma;
+	int			 data_sz;
+	int			 rc;
+
+	if (portnum > 1)
+		return -EINVAL;
+
+	/* get fcport page 1 header */
+	hdr.PageVersion = 0;
+	hdr.PageLength = 0;
+	hdr.PageNumber = 1;
+	hdr.PageType = MPI_CONFIG_PAGETYPE_FC_PORT;
+	cfg.cfghdr.hdr = &hdr;
+	cfg.physAddr = -1;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+	cfg.dir = 0;
+	cfg.pageAddr = portnum;
+	cfg.timeout = 0;
+
+	if ((rc = mpt_config(ioc, &cfg)) != 0)
+		return rc;
+
+	if (hdr.PageLength == 0)
+		return -ENODEV;
+
+start_over:
+
+	if (ioc->fc_data.fc_port_page1[portnum].data == NULL) {
+		data_sz = hdr.PageLength * 4;
+		if (data_sz < sizeof(FCPortPage1_t))
+			data_sz = sizeof(FCPortPage1_t);
+
+		page1_alloc = (FCPortPage1_t *) pci_alloc_consistent(ioc->pcidev,
+						data_sz,
+						&page1_dma);
+		if (!page1_alloc)
+			return -ENOMEM;
+	}
+	else {
+		page1_alloc = ioc->fc_data.fc_port_page1[portnum].data;
+		page1_dma = ioc->fc_data.fc_port_page1[portnum].dma;
+		data_sz = ioc->fc_data.fc_port_page1[portnum].pg_sz;
+		if (hdr.PageLength * 4 > data_sz) {
+			ioc->fc_data.fc_port_page1[portnum].data = NULL;
+			pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
+				page1_alloc, page1_dma);
+			goto start_over;
+		}
+	}
+
+	memset(page1_alloc,0,data_sz);
+
+	cfg.physAddr = page1_dma;
+	cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+	if ((rc = mpt_config(ioc, &cfg)) == 0) {
+		ioc->fc_data.fc_port_page1[portnum].data = page1_alloc;
+		ioc->fc_data.fc_port_page1[portnum].pg_sz = data_sz;
+		ioc->fc_data.fc_port_page1[portnum].dma = page1_dma;
+	}
+	else {
+		ioc->fc_data.fc_port_page1[portnum].data = NULL;
+		pci_free_consistent(ioc->pcidev, data_sz, (u8 *)
+			page1_alloc, page1_dma);
+	}
+
+	return rc;
+}
+
+static void
+mptfc_SetFcPortPage1_defaults(MPT_ADAPTER *ioc)
+{
+	int		ii;
+	FCPortPage1_t	*pp1;
+
+	#define MPTFC_FW_DEVICE_TIMEOUT	(1)
+	#define MPTFC_FW_IO_PEND_TIMEOUT (1)
+	#define ON_FLAGS  (MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY)
+	#define OFF_FLAGS (MPI_FCPORTPAGE1_FLAGS_VERBOSE_RESCAN_EVENTS)
+
+	for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
+		if (mptfc_GetFcPortPage1(ioc, ii) != 0)
+			continue;
+		pp1 = ioc->fc_data.fc_port_page1[ii].data;
+		if ((pp1->InitiatorDeviceTimeout == MPTFC_FW_DEVICE_TIMEOUT)
+		 && (pp1->InitiatorIoPendTimeout == MPTFC_FW_IO_PEND_TIMEOUT)
+		 && ((pp1->Flags & ON_FLAGS) == ON_FLAGS)
+		 && ((pp1->Flags & OFF_FLAGS) == 0))
+			continue;
+		pp1->InitiatorDeviceTimeout = MPTFC_FW_DEVICE_TIMEOUT;
+		pp1->InitiatorIoPendTimeout = MPTFC_FW_IO_PEND_TIMEOUT;
+		pp1->Flags &= ~OFF_FLAGS;
+		pp1->Flags |= ON_FLAGS;
+		mptfc_WriteFcPortPage1(ioc, ii);
+	}
+}
+
+
 static void
 mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
 {
@@ -629,6 +871,31 @@
 }
 
 static void
+mptfc_setup_reset(void *arg)
+{
+	MPT_ADAPTER		*ioc = (MPT_ADAPTER *)arg;
+	u64			pn;
+	struct mptfc_rport_info *ri;
+
+	/* reset about to happen, delete (block) all rports */
+	list_for_each_entry(ri, &ioc->fc_rports, list) {
+		if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+			ri->flags &= ~MPT_RPORT_INFO_FLAGS_REGISTERED;
+			fc_remote_port_delete(ri->rport);	/* won't sleep */
+			ri->rport = NULL;
+
+			pn = (u64)ri->pg0.WWPN.High << 32 |
+			     (u64)ri->pg0.WWPN.Low;
+			dfcprintk ((MYIOC_s_INFO_FMT
+				"mptfc_setup_reset.%d: %llx deleted\n",
+				ioc->name,
+				ioc->sh->host_no,
+				(unsigned long long)pn));
+		}
+	}
+}
+
+static void
 mptfc_rescan_devices(void *arg)
 {
 	MPT_ADAPTER		*ioc = (MPT_ADAPTER *)arg;
@@ -651,7 +918,7 @@
 		 * will reregister existing rports
 		 */
 		for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-			(void) mptbase_GetFcPortPage0(ioc, ii);
+			(void) mptfc_GetFcPortPage0(ioc, ii);
 			mptfc_init_host_attr(ioc,ii);	/* refresh */
 			mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
 		}
@@ -753,7 +1020,9 @@
 		goto out_mptfc_probe;
         }
 
+	spin_lock_init(&ioc->fc_rescan_work_lock);
 	INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
+	INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset, (void *)ioc);
 
 	spin_lock_irqsave(&ioc->FreeQlock, flags);
 
@@ -889,6 +1158,15 @@
 		goto out_mptfc_probe;
 
 	/*
+	 *  Pre-fetch FC port WWN and stuff...
+	 *  (FCPortPage0_t stuff)
+	 */
+	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+		(void) mptfc_GetFcPortPage0(ioc, ii);
+	}
+	mptfc_SetFcPortPage1_defaults(ioc);
+
+	/*
 	 * scan for rports -
 	 *	by doing it via the workqueue, some locking is eliminated
 	 */
@@ -917,6 +1195,81 @@
 #endif
 };
 
+static int
+mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
+{
+	MPT_SCSI_HOST *hd;
+	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+	unsigned long flags;
+	int rc=1;
+
+	devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
+			ioc->name, event));
+
+	if (ioc->sh == NULL ||
+		((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL))
+		return 1;
+
+	switch (event) {
+	case MPI_EVENT_RESCAN:
+		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+		if (ioc->fc_rescan_work_q) {
+			if (ioc->fc_rescan_work_count++ == 0) {
+				queue_work(ioc->fc_rescan_work_q,
+					   &ioc->fc_rescan_work);
+			}
+		}
+		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+		break;
+	default:
+		rc = mptscsih_event_process(ioc,pEvReply);
+		break;
+	}
+	return rc;
+}
+
+static int
+mptfc_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
+{
+	int		rc;
+	unsigned long	flags;
+
+	rc = mptscsih_ioc_reset(ioc,reset_phase);
+	if (rc == 0)
+		return rc;
+
+
+	dtmprintk((KERN_WARNING MYNAM
+		": IOC %s_reset routed to FC host driver!\n",
+		reset_phase==MPT_IOC_SETUP_RESET ? "setup" : (
+		reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post")));
+
+	if (reset_phase == MPT_IOC_SETUP_RESET) {
+		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+		if (ioc->fc_rescan_work_q) {
+			queue_work(ioc->fc_rescan_work_q,
+				   &ioc->fc_setup_reset_work);
+		}
+		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+	}
+
+	else if (reset_phase == MPT_IOC_PRE_RESET) {
+	}
+
+	else {	/* MPT_IOC_POST_RESET */
+		mptfc_SetFcPortPage1_defaults(ioc);
+		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+		if (ioc->fc_rescan_work_q) {
+			if (ioc->fc_rescan_work_count++ == 0) {
+				queue_work(ioc->fc_rescan_work_q,
+					   &ioc->fc_rescan_work);
+			}
+		}
+		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+	}
+	return 1;
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with
@@ -931,8 +1284,8 @@
 
 	show_mptmod_ver(my_NAME, my_VERSION);
 
-	/* sanity check module parameter */
-	if (mptfc_dev_loss_tmo == 0)
+	/* sanity check module parameters */
+	if (mptfc_dev_loss_tmo <= 0)
 		mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
 
 	mptfc_transport_template =
@@ -945,12 +1298,12 @@
 	mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
 	mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
 
-	if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
+	if (mpt_event_register(mptfcDoneCtx, mptfc_event_process) == 0) {
 		devtverboseprintk((KERN_INFO MYNAM
 		  ": Registered for IOC event notifications\n"));
 	}
 
-	if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
+	if (mpt_reset_register(mptfcDoneCtx, mptfc_ioc_reset) == 0) {
 		dprintk((KERN_INFO MYNAM
 		  ": Registered for IOC reset notifications\n"));
 	}
@@ -975,6 +1328,7 @@
 	struct mptfc_rport_info	*p, *n;
 	struct workqueue_struct *work_q;
 	unsigned long		flags;
+	int			ii;
 
 	/* destroy workqueue */
 	if ((work_q=ioc->fc_rescan_work_q)) {
@@ -991,6 +1345,16 @@
 		kfree(p);
 	}
 
+	for (ii=0; ii<ioc->facts.NumberOfPorts; ii++) {
+		if (ioc->fc_data.fc_port_page1[ii].data) {
+			pci_free_consistent(ioc->pcidev,
+				ioc->fc_data.fc_port_page1[ii].pg_sz,
+				(u8 *) ioc->fc_data.fc_port_page1[ii].data,
+				ioc->fc_data.fc_port_page1[ii].dma);
+			ioc->fc_data.fc_port_page1[ii].data = NULL;
+		}
+	}
+
 	mptscsih_remove(pdev);
 }
 
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index af6ec55..85689ab 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -1378,8 +1378,7 @@
 	return 0;
 
  out_free_port_info:
-	if (hba)
-		kfree(hba);
+	kfree(hba);
  out:
 	return error;
 }
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 84fa271..8242b16 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1922,7 +1922,7 @@
 			break;
 		}
 		spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags);
-		msleep_interruptible(250);
+		msleep(250);
 	} while (--loop_count);
 
 	return status;
@@ -2521,18 +2521,6 @@
 			hd->cmdPtr = NULL;
 		}
 
-		/* 7. FC: Rescan for blocked rports which might have returned.
-		 */
-		if (ioc->bus_type == FC) {
-			spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
-			if (ioc->fc_rescan_work_q) {
-				if (ioc->fc_rescan_work_count++ == 0) {
-					queue_work(ioc->fc_rescan_work_q,
-						   &ioc->fc_rescan_work);
-				}
-			}
-			spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
-		}
 		dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
 	}
@@ -2546,7 +2534,6 @@
 {
 	MPT_SCSI_HOST *hd;
 	u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
-	unsigned long flags;
 
 	devtverboseprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
 			ioc->name, event));
@@ -2569,14 +2556,6 @@
 		break;
 
 	case MPI_EVENT_RESCAN:				/* 06 */
-		spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
-		if (ioc->fc_rescan_work_q) {
-			if (ioc->fc_rescan_work_count++ == 0) {
-				queue_work(ioc->fc_rescan_work_q,
-					   &ioc->fc_rescan_work);
-			}
-		}
-		spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
 		break;
 
 		/*
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index c08ddac..6ebf382 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -65,9 +65,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_request.h>
 #include <scsi/sg.h>
-#include <scsi/sg_request.h>
 
 #define OSM_NAME	"scsi-osm"
 #define OSM_VERSION	"1.316"
@@ -588,6 +586,7 @@
 
 	mptr = &msg->body[0];
 
+#if 0 /* this code can't work */
 #ifdef CONFIG_I2O_EXT_ADAPTEC
 	if (c->adaptec) {
 		u32 adpt_flags = 0;
@@ -625,6 +624,7 @@
 		*mptr++ = cpu_to_le32(adpt_flags | tid);
 	}
 #endif
+#endif
 
 	msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
 	msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context);
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index febbdd4..c74e546 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -1239,7 +1239,6 @@
 EXPORT_SYMBOL(i2o_cntxt_list_get_ptr);
 #endif
 EXPORT_SYMBOL(i2o_msg_get_wait);
-EXPORT_SYMBOL(i2o_msg_nop);
 EXPORT_SYMBOL(i2o_find_iop);
 EXPORT_SYMBOL(i2o_iop_find_device);
 EXPORT_SYMBOL(i2o_event_register);
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index aff83f9..c8426a9 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -420,8 +420,10 @@
 	unsigned long mask;
 
 	mask = probe_irq_on();
-	if (!mask)
+	if (!mask) {
+		probe_irq_off(mask);
 		return NO_IRQ;
+	}
 
 	/*
 	 * Enable the ADC interrupt.
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 26a230b..4a35caf 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -90,10 +90,11 @@
 static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent);
 
 
-static struct super_block *ibmasmfs_get_super(struct file_system_type *fst,
-			int flags, const char *name, void *data)
+static int ibmasmfs_get_super(struct file_system_type *fst,
+			int flags, const char *name, void *data,
+			struct vfsmount *mnt)
 {
-	return get_sb_single(fst, flags, data, ibmasmfs_fill_super);
+	return get_sb_single(fst, flags, data, ibmasmfs_fill_super, mnt);
 }
 
 static struct super_operations ibmasmfs_s_ops = {
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 1fdf03f..9706cc1 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -85,7 +85,7 @@
 	}
 	memset(sp, 0, sizeof(struct service_processor));
 
-	sp->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&sp->lock);
 	INIT_LIST_HEAD(&sp->command_queue);
 
 	pci_set_drvdata(pdev, (void *)sp);
diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c
index 88f0eef..3228516 100644
--- a/drivers/mmc/at91_mci.c
+++ b/drivers/mmc/at91_mci.c
@@ -81,13 +81,6 @@
 
 #undef	SUPPORT_4WIRE
 
-#ifdef CONFIG_MMC_DEBUG
-#define DBG(fmt...)	\
-	printk(fmt)
-#else
-#define DBG(fmt...)	do { } while (0)
-#endif
-
 static struct clk *mci_clk;
 
 #define FL_SENT_COMMAND (1 << 0)
@@ -202,50 +195,50 @@
 	struct mmc_command *cmd;
 	struct mmc_data *data;
 
-	DBG("pre dma read\n");
+	pr_debug("pre dma read\n");
 
 	cmd = host->cmd;
 	if (!cmd) {
-		DBG("no command\n");
+		pr_debug("no command\n");
 		return;
 	}
 
 	data = cmd->data;
 	if (!data) {
-		DBG("no data\n");
+		pr_debug("no data\n");
 		return;
 	}
 
 	for (i = 0; i < 2; i++) {
 		/* nothing left to transfer */
 		if (host->transfer_index >= data->sg_len) {
-			DBG("Nothing left to transfer (index = %d)\n", host->transfer_index);
+			pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
 			break;
 		}
 
 		/* Check to see if this needs filling */
 		if (i == 0) {
 			if (at91_mci_read(AT91_PDC_RCR) != 0) {
-				DBG("Transfer active in current\n");
+				pr_debug("Transfer active in current\n");
 				continue;
 			}
 		}
 		else {
 			if (at91_mci_read(AT91_PDC_RNCR) != 0) {
-				DBG("Transfer active in next\n");
+				pr_debug("Transfer active in next\n");
 				continue;
 			}
 		}
 
 		/* Setup the next transfer */
-		DBG("Using transfer index %d\n", host->transfer_index);
+		pr_debug("Using transfer index %d\n", host->transfer_index);
 
 		sg = &data->sg[host->transfer_index++];
-		DBG("sg = %p\n", sg);
+		pr_debug("sg = %p\n", sg);
 
 		sg->dma_address = dma_map_page(NULL, sg->page, sg->offset, sg->length, DMA_FROM_DEVICE);
 
-		DBG("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
+		pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
 
 		if (i == 0) {
 			at91_mci_write(AT91_PDC_RPR, sg->dma_address);
@@ -257,7 +250,7 @@
 		}
 	}
 
-	DBG("pre dma read done\n");
+	pr_debug("pre dma read done\n");
 }
 
 /*
@@ -268,17 +261,17 @@
 	struct mmc_command *cmd;
 	struct mmc_data *data;
 
-	DBG("post dma read\n");
+	pr_debug("post dma read\n");
 
 	cmd = host->cmd;
 	if (!cmd) {
-		DBG("no command\n");
+		pr_debug("no command\n");
 		return;
 	}
 
 	data = cmd->data;
 	if (!data) {
-		DBG("no data\n");
+		pr_debug("no data\n");
 		return;
 	}
 
@@ -289,17 +282,17 @@
 
 		struct scatterlist *sg;
 
-		DBG("finishing index %d\n", host->in_use_index);
+		pr_debug("finishing index %d\n", host->in_use_index);
 
 		sg = &data->sg[host->in_use_index++];
 
-		DBG("Unmapping page %08X\n", sg->dma_address);
+		pr_debug("Unmapping page %08X\n", sg->dma_address);
 
 		dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
 
 		/* Swap the contents of the buffer */
 		buffer = kmap_atomic(sg->page, KM_BIO_SRC_IRQ) + sg->offset;
-		DBG("buffer = %p, length = %d\n", buffer, sg->length);
+		pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
 
 		data->bytes_xfered += sg->length;
 
@@ -320,7 +313,7 @@
 		at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
 	}
 
-	DBG("post dma read done\n");
+	pr_debug("post dma read done\n");
 }
 
 /*
@@ -331,7 +324,7 @@
 	struct mmc_command *cmd;
 	struct mmc_data *data;
 
-	DBG("Handling the transmit\n");
+	pr_debug("Handling the transmit\n");
 
 	/* Disable the transfer */
 	at91_mci_write(AT91_PDC_PTCR, AT91_PDC_RXTDIS | AT91_PDC_TXTDIS);
@@ -387,12 +380,12 @@
 	/* Not sure if this is needed */
 #if 0
 	if ((at91_mci_read(AT91_MCI_SR) & AT91_MCI_RTOE) && (cmd->opcode == 1)) {
-		DBG("Clearing timeout\n");
+		pr_debug("Clearing timeout\n");
 		at91_mci_write(AT91_MCI_ARGR, 0);
 		at91_mci_write(AT91_MCI_CMDR, AT91_MCI_OPDCMD);
 		while (!(at91_mci_read(AT91_MCI_SR) & AT91_MCI_CMDRDY)) {
 			/* spin */
-			DBG("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
+			pr_debug("Clearing: SR = %08X\n", at91_mci_read(AT91_MCI_SR));
 		}
 	}
 #endif
@@ -411,7 +404,7 @@
 	}
 
 	if (data) {
-		block_length = 1 << data->blksz_bits;
+		block_length = data->blksz;
 		blocks = data->blocks;
 
 		/* always set data start - also set direction flag for read */
@@ -439,7 +432,7 @@
 	/*
 	 * Set the arguments and send the command
 	 */
-	DBG("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
+	pr_debug("Sending command %d as %08X, arg = %08X, blocks = %d, length = %d (MR = %08lX)\n",
 		cmd->opcode, cmdr, cmd->arg, blocks, block_length, at91_mci_read(AT91_MCI_MR));
 
 	if (!data) {
@@ -491,7 +484,7 @@
 
 			at91mci_sg_to_dma(host, data);
 
-			DBG("Transmitting %d bytes\n", host->total_length);
+			pr_debug("Transmitting %d bytes\n", host->total_length);
 
 			at91_mci_write(AT91_PDC_TPR, host->physical_address);
 			at91_mci_write(AT91_PDC_TCR, host->total_length / 4);
@@ -525,7 +518,7 @@
 
 	ier = at91_mci_send_command(host, cmd);
 
-	DBG("setting ier to %08X\n", ier);
+	pr_debug("setting ier to %08X\n", ier);
 
 	/* Stop on errors or the required value */
 	at91_mci_write(AT91_MCI_IER, 0xffff0000 | ier);
@@ -570,7 +563,7 @@
 
 	status = at91_mci_read(AT91_MCI_SR);
 
-	DBG("Status = %08X [%08X %08X %08X %08X]\n",
+	pr_debug("Status = %08X [%08X %08X %08X %08X]\n",
 		 status, cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
 
 	if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
@@ -590,7 +583,7 @@
 			else
 				cmd->error = MMC_ERR_FAILED;
 
-			DBG("Error detected and set to %d (cmd = %d, retries = %d)\n",
+			pr_debug("Error detected and set to %d (cmd = %d, retries = %d)\n",
 				 cmd->error, cmd->opcode, cmd->retries);
 		}
 	}
@@ -621,10 +614,7 @@
 	struct at91mci_host *host = mmc_priv(mmc);
 	unsigned long at91_master_clock = clk_get_rate(mci_clk);
 
-	if (host)
-		host->bus_mode = ios->bus_mode;
-	else
-		printk("MMC: No host for bus_mode\n");
+	host->bus_mode = ios->bus_mode;
 
 	if (ios->clock == 0) {
 		/* Disable the MCI controller */
@@ -640,15 +630,15 @@
 		else
 			clkdiv = (at91_master_clock / ios->clock) / 2;
 
-		DBG("clkdiv = %d. mcck = %ld\n", clkdiv,
+		pr_debug("clkdiv = %d. mcck = %ld\n", clkdiv,
 			at91_master_clock / (2 * (clkdiv + 1)));
 	}
 	if (ios->bus_width == MMC_BUS_WIDTH_4 && host->board->wire4) {
-		DBG("MMC: Setting controller bus width to 4\n");
+		pr_debug("MMC: Setting controller bus width to 4\n");
 		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) | AT91_MCI_SDCBUS);
 	}
 	else {
-		DBG("MMC: Setting controller bus width to 1\n");
+		pr_debug("MMC: Setting controller bus width to 1\n");
 		at91_mci_write(AT91_MCI_SDCR, at91_mci_read(AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
 	}
 
@@ -656,7 +646,7 @@
 	at91_mci_write(AT91_MCI_MR, (at91_mci_read(AT91_MCI_MR) & ~AT91_MCI_CLKDIV) | clkdiv);
 
 	/* maybe switch power to the card */
-	if (host && host->board->vcc_pin) {
+	if (host->board->vcc_pin) {
 		switch (ios->power_mode) {
 			case MMC_POWER_OFF:
 				at91_set_gpio_output(host->board->vcc_pin, 0);
@@ -679,11 +669,8 @@
 
 	unsigned int int_status;
 
-	if (host == NULL)
-		return IRQ_HANDLED;
-
 	int_status = at91_mci_read(AT91_MCI_SR);
-	DBG("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
+	pr_debug("MCI irq: status = %08X, %08lX, %08lX\n", int_status, at91_mci_read(AT91_MCI_IMR),
 		int_status & at91_mci_read(AT91_MCI_IMR));
 
 	if ((int_status & at91_mci_read(AT91_MCI_IMR)) & 0xffff0000)
@@ -692,75 +679,75 @@
 	int_status &= at91_mci_read(AT91_MCI_IMR);
 
 	if (int_status & AT91_MCI_UNRE)
-		DBG("MMC: Underrun error\n");
+		pr_debug("MMC: Underrun error\n");
 	if (int_status & AT91_MCI_OVRE)
-		DBG("MMC: Overrun error\n");
+		pr_debug("MMC: Overrun error\n");
 	if (int_status & AT91_MCI_DTOE)
-		DBG("MMC: Data timeout\n");
+		pr_debug("MMC: Data timeout\n");
 	if (int_status & AT91_MCI_DCRCE)
-		DBG("MMC: CRC error in data\n");
+		pr_debug("MMC: CRC error in data\n");
 	if (int_status & AT91_MCI_RTOE)
-		DBG("MMC: Response timeout\n");
+		pr_debug("MMC: Response timeout\n");
 	if (int_status & AT91_MCI_RENDE)
-		DBG("MMC: Response end bit error\n");
+		pr_debug("MMC: Response end bit error\n");
 	if (int_status & AT91_MCI_RCRCE)
-		DBG("MMC: Response CRC error\n");
+		pr_debug("MMC: Response CRC error\n");
 	if (int_status & AT91_MCI_RDIRE)
-		DBG("MMC: Response direction error\n");
+		pr_debug("MMC: Response direction error\n");
 	if (int_status & AT91_MCI_RINDE)
-		DBG("MMC: Response index error\n");
+		pr_debug("MMC: Response index error\n");
 
 	/* Only continue processing if no errors */
 	if (!completed) {
 		if (int_status & AT91_MCI_TXBUFE) {
-			DBG("TX buffer empty\n");
+			pr_debug("TX buffer empty\n");
 			at91_mci_handle_transmitted(host);
 		}
 
 		if (int_status & AT91_MCI_RXBUFF) {
-			DBG("RX buffer full\n");
+			pr_debug("RX buffer full\n");
 			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
 		}
 
 		if (int_status & AT91_MCI_ENDTX) {
-			DBG("Transmit has ended\n");
+			pr_debug("Transmit has ended\n");
 		}
 
 		if (int_status & AT91_MCI_ENDRX) {
-			DBG("Receive has ended\n");
+			pr_debug("Receive has ended\n");
 			at91mci_post_dma_read(host);
 		}
 
 		if (int_status & AT91_MCI_NOTBUSY) {
-			DBG("Card is ready\n");
+			pr_debug("Card is ready\n");
 			at91_mci_write(AT91_MCI_IER, AT91_MCI_CMDRDY);
 		}
 
 		if (int_status & AT91_MCI_DTIP) {
-			DBG("Data transfer in progress\n");
+			pr_debug("Data transfer in progress\n");
 		}
 
 		if (int_status & AT91_MCI_BLKE) {
-			DBG("Block transfer has ended\n");
+			pr_debug("Block transfer has ended\n");
 		}
 
 		if (int_status & AT91_MCI_TXRDY) {
-			DBG("Ready to transmit\n");
+			pr_debug("Ready to transmit\n");
 		}
 
 		if (int_status & AT91_MCI_RXRDY) {
-			DBG("Ready to receive\n");
+			pr_debug("Ready to receive\n");
 		}
 
 		if (int_status & AT91_MCI_CMDRDY) {
-			DBG("Command ready\n");
+			pr_debug("Command ready\n");
 			completed = 1;
 		}
 	}
 	at91_mci_write(AT91_MCI_IDR, int_status);
 
 	if (completed) {
-		DBG("Completed command\n");
+		pr_debug("Completed command\n");
 		at91_mci_write(AT91_MCI_IDR, 0xffffffff);
 		at91mci_completed_command(host);
 	}
@@ -779,10 +766,10 @@
 	 */
 	if (present != host->present) {
 		host->present = present;
-		DBG("%s: card %s\n", mmc_hostname(host->mmc),
+		pr_debug("%s: card %s\n", mmc_hostname(host->mmc),
 			present ? "insert" : "remove");
 		if (!present) {
-			DBG("****** Resetting SD-card bus width ******\n");
+			pr_debug("****** Resetting SD-card bus width ******\n");
 			at91_mci_write(AT91_MCI_SDCR, 0);
 		}
 		mmc_detect_change(host->mmc, msecs_to_jiffies(100));
@@ -822,13 +809,13 @@
 	struct at91mci_host *host;
 	int ret;
 
-	DBG("Probe MCI devices\n");
+	pr_debug("Probe MCI devices\n");
 	at91_mci_disable();
 	at91_mci_enable();
 
 	mmc = mmc_alloc_host(sizeof(struct at91mci_host), &pdev->dev);
 	if (!mmc) {
-		DBG("Failed to allocate mmc host\n");
+		pr_debug("Failed to allocate mmc host\n");
 		return -ENOMEM;
 	}
 
@@ -854,8 +841,9 @@
 	 * Get Clock
 	 */
 	mci_clk = clk_get(&pdev->dev, "mci_clk");
-	if (!mci_clk) {
+	if (IS_ERR(mci_clk)) {
 		printk(KERN_ERR "AT91 MMC: no clock defined.\n");
+		mmc_free_host(mmc);
 		return -ENODEV;
 	}
 	clk_enable(mci_clk);			/* Enable the peripheral clock */
@@ -865,7 +853,10 @@
 	 */
 	ret = request_irq(AT91_ID_MCI, at91_mci_irq, SA_SHIRQ, DRIVER_NAME, host);
 	if (ret) {
-		DBG("Failed to request MCI interrupt\n");
+		printk(KERN_ERR "Failed to request MCI interrupt\n");
+		clk_disable(mci_clk);
+		clk_put(mci_clk);
+		mmc_free_host(mmc);
 		return ret;
 	}
 
@@ -886,12 +877,12 @@
 	 */
 	if (host->board->det_pin) {
 		ret = request_irq(host->board->det_pin, at91_mmc_det_irq,
-				SA_SAMPLE_RANDOM, DRIVER_NAME, host);
+				0, DRIVER_NAME, host);
 		if (ret)
-			DBG("couldn't allocate MMC detect irq\n");
+			printk(KERN_ERR "couldn't allocate MMC detect irq\n");
 	}
 
-	DBG(KERN_INFO "Added MCI driver\n");
+	pr_debug(KERN_INFO "Added MCI driver\n");
 
 	return 0;
 }
@@ -924,7 +915,7 @@
 
 	platform_set_drvdata(pdev, NULL);
 
-	DBG("Removed\n");
+	pr_debug("MCI Removed\n");
 
 	return 0;
 }
diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c
index a4eb1d0..5c62f4e 100644
--- a/drivers/mmc/imxmmc.c
+++ b/drivers/mmc/imxmmc.c
@@ -228,7 +228,7 @@
 static void imxmci_setup_data(struct imxmci_host *host, struct mmc_data *data)
 {
 	unsigned int nob = data->blocks;
-	unsigned int blksz = 1 << data->blksz_bits;
+	unsigned int blksz = data->blksz;
 	unsigned int datasz = nob * blksz;
 	int i;
 
diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c
index becb3c6..c25244b 100644
--- a/drivers/mmc/omap.c
+++ b/drivers/mmc/omap.c
@@ -584,10 +584,10 @@
 	int sync_dev = 0;
 
 	data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA;
-	frame = 1 << data->blksz_bits;
+	frame = data->blksz;
 	count = sg_dma_len(sg);
 
-	if ((data->blocks == 1) && (count > (1 << data->blksz_bits)))
+	if ((data->blocks == 1) && (count > data->blksz))
 		count = frame;
 
 	host->dma_len = count;
@@ -776,7 +776,7 @@
 	}
 
 
-	block_size = 1 << data->blksz_bits;
+	block_size = data->blksz;
 
 	OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1);
 	OMAP_MMC_WRITE(host->base, BLEN, block_size - 1);
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index b005328..8e9100b 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -268,7 +268,7 @@
 	}
 
 	DBG("blksz %04x blks %04x flags %08x\n",
-		1 << data->blksz_bits, data->blocks, data->flags);
+		data->blksz, data->blocks, data->flags);
 	DBG("tsac %d ms nsac %d clk\n",
 		data->timeout_ns / 1000000, data->timeout_clks);
 
@@ -282,7 +282,7 @@
 
 	writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
 
-	writew(1 << data->blksz_bits, host->ioaddr + SDHCI_BLOCK_SIZE);
+	writew(data->blksz, host->ioaddr + SDHCI_BLOCK_SIZE);
 	writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT);
 
 	if (host->flags & SDHCI_USE_DMA) {
@@ -294,7 +294,7 @@
 
 		writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS);
 	} else {
-		host->size = (1 << data->blksz_bits) * data->blocks;
+		host->size = data->blksz * data->blocks;
 
 		host->cur_sg = data->sg;
 		host->num_sg = data->sg_len;
@@ -335,7 +335,7 @@
 		blocks = 0;
 	else
 		blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
-	data->bytes_xfered = (1 << data->blksz_bits) * (data->blocks - blocks);
+	data->bytes_xfered = data->blksz * (data->blocks - blocks);
 
 	if ((data->error == MMC_ERR_NONE) && blocks) {
 		printk(KERN_ERR "%s: Controller signalled completion even "
@@ -1073,7 +1073,7 @@
 	tasklet_init(&host->finish_tasklet,
 		sdhci_tasklet_finish, (unsigned long)host);
 
-	setup_timer(&host->timer, sdhci_timeout_timer, (int)host);
+	setup_timer(&host->timer, sdhci_timeout_timer, (long)host);
 
 	ret = request_irq(host->irq, sdhci_irq, SA_SHIRQ,
 		host->slot_descr, host);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index f6b775e..1344ad7 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -78,7 +78,7 @@
 	  option.
 
 	  The option specifies which Flash sectors holds the RedBoot
-	  partition table.  A zero or positive value gives an absolete
+	  partition table.  A zero or positive value gives an absolute
 	  erase block number. A negative value specifies a number of
 	  sectors before the end of the device.
 
@@ -86,14 +86,14 @@
 	  block and "-2" means the penultimate block.
 
 config MTD_REDBOOT_PARTS_UNALLOCATED
-	bool "  Include unallocated flash regions"
+	bool "Include unallocated flash regions"
 	depends on MTD_REDBOOT_PARTS
 	help
 	  If you need to register each unallocated flash region as a MTD
 	  'partition', enable this option.
 
 config MTD_REDBOOT_PARTS_READONLY
-	bool "  Force read-only for RedBoot system images"
+	bool "Force read-only for RedBoot system images"
 	depends on MTD_REDBOOT_PARTS
 	help
 	  If you need to force read-only for 'RedBoot', 'RedBoot Config' and
@@ -103,7 +103,7 @@
 	bool "Command line partition table parsing"
 	depends on MTD_PARTITIONS = "y"
 	---help---
-	  Allow generic configuration of the MTD paritition tables via the kernel
+	  Allow generic configuration of the MTD partition tables via the kernel
 	  command line. Multiple flash resources are supported for hardware where
 	  different kinds of flash memory are available.
 
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index a7ec595..6d8f30d 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -30,7 +30,6 @@
 
 config MTD_GEN_PROBE
 	tristate
-	select OBSOLETE_INTERMODULE
 
 config MTD_CFI_ADV_OPTIONS
 	bool "Flash chip driver advanced configuration options"
diff --git a/drivers/mtd/chips/Makefile b/drivers/mtd/chips/Makefile
index 8afe309..75bc1c2 100644
--- a/drivers/mtd/chips/Makefile
+++ b/drivers/mtd/chips/Makefile
@@ -3,13 +3,6 @@
 #
 # $Id: Makefile.common,v 1.5 2005/11/07 11:14:22 gleixner Exp $
 
-#                       *** BIG UGLY NOTE ***
-#
-# The removal of get_module_symbol() and replacement with
-# inter_module_register() et al has introduced a link order dependency
-# here where previously there was none.  We now have to ensure that
-# the CFI command set drivers are linked before gen_probe.o
-
 obj-$(CONFIG_MTD)		+= chipreg.o
 obj-$(CONFIG_MTD_AMDSTD)	+= amd_flash.o
 obj-$(CONFIG_MTD_CFI)		+= cfi_probe.o
diff --git a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c
index 5711561..16eaca6 100644
--- a/drivers/mtd/chips/amd_flash.c
+++ b/drivers/mtd/chips/amd_flash.c
@@ -97,7 +97,6 @@
 	int interleave;
 	int numchips;
 	unsigned long chipshift;
-//	const char *im_name;
 	struct flchip chips[0];
 };
 
@@ -131,12 +130,6 @@
 	.module = THIS_MODULE
 };
 
-
-
-static const char im_name[] = "amd_flash";
-
-
-
 static inline __u32 wide_read(struct map_info *map, __u32 addr)
 {
 	if (map->buswidth == 1) {
@@ -737,6 +730,7 @@
 		offset += dev_size;
 	}
 	mtd->type = MTD_NORFLASH;
+	mtd->writesize = 1;
 	mtd->flags = MTD_CAP_NORFLASH;
 	mtd->name = map->name;
 	mtd->erase = amd_flash_erase;
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 1c074d6..39edb82 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -331,13 +331,6 @@
 	return extp;
 }
 
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in cfi are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
 struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
@@ -364,6 +357,7 @@
 	mtd->resume  = cfi_intelext_resume;
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->name    = map->name;
+	mtd->writesize = 1;
 
 	mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
 
@@ -406,7 +400,7 @@
 	for (i=0; i< cfi->numchips; i++) {
 		cfi->chips[i].word_write_time = 1<<cfi->cfiq->WordWriteTimeoutTyp;
 		cfi->chips[i].buffer_write_time = 1<<cfi->cfiq->BufWriteTimeoutTyp;
-		cfi->chips[i].erase_time = 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+		cfi->chips[i].erase_time = 1000<<cfi->cfiq->BlockEraseTimeoutTyp;
 		cfi->chips[i].ref_point_counter = 0;
 		init_waitqueue_head(&(cfi->chips[i].wq));
 	}
@@ -415,6 +409,11 @@
 
 	return cfi_intelext_setup(mtd);
 }
+struct mtd_info *cfi_cmdset_0003(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001")));
+struct mtd_info *cfi_cmdset_0200(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0001")));
+EXPORT_SYMBOL_GPL(cfi_cmdset_0001);
+EXPORT_SYMBOL_GPL(cfi_cmdset_0003);
+EXPORT_SYMBOL_GPL(cfi_cmdset_0200);
 
 static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
 {
@@ -547,12 +546,12 @@
 		if (extp->MinorVersion >= '4') {
 			struct cfi_intelext_programming_regioninfo *prinfo;
 			prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs];
-			MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift;
+			mtd->writesize = cfi->interleave << prinfo->ProgRegShift;
 			MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid;
 			MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid;
-			mtd->flags |= MTD_PROGRAM_REGIONS;
+			mtd->flags &= ~MTD_BIT_WRITEABLE;
 			printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n",
-			       map->name, MTD_PROGREGION_SIZE(mtd),
+			       map->name, mtd->writesize,
 			       MTD_PROGREGION_CTRLMODE_VALID(mtd),
 			       MTD_PROGREGION_CTRLMODE_INVALID(mtd));
 		}
@@ -896,26 +895,33 @@
 
 /*
  * When a delay is required for the flash operation to complete, the
- * xip_udelay() function is polling for both the given timeout and pending
- * (but still masked) hardware interrupts.  Whenever there is an interrupt
- * pending then the flash erase or write operation is suspended, array mode
- * restored and interrupts unmasked.  Task scheduling might also happen at that
- * point.  The CPU eventually returns from the interrupt or the call to
- * schedule() and the suspended flash operation is resumed for the remaining
- * of the delay period.
+ * xip_wait_for_operation() function is polling for both the given timeout
+ * and pending (but still masked) hardware interrupts.  Whenever there is an
+ * interrupt pending then the flash erase or write operation is suspended,
+ * array mode restored and interrupts unmasked.  Task scheduling might also
+ * happen at that point.  The CPU eventually returns from the interrupt or
+ * the call to schedule() and the suspended flash operation is resumed for
+ * the remaining of the delay period.
  *
  * Warning: this function _will_ fool interrupt latency tracing tools.
  */
 
-static void __xipram xip_udelay(struct map_info *map, struct flchip *chip,
-				unsigned long adr, int usec)
+static int __xipram xip_wait_for_operation(
+		struct map_info *map, struct flchip *chip,
+		unsigned long adr, int *chip_op_time )
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
 	map_word status, OK = CMD(0x80);
-	unsigned long suspended, start = xip_currtime();
+	unsigned long usec, suspended, start, done;
 	flstate_t oldstate, newstate;
 
+       	start = xip_currtime();
+	usec = *chip_op_time * 8;
+	if (usec == 0)
+		usec = 500000;
+	done = 0;
+
 	do {
 		cpu_relax();
 		if (xip_irqpending() && cfip &&
@@ -932,9 +938,9 @@
 			 * we resume the whole thing at once).  Yes, it
 			 * can happen!
 			 */
+			usec -= done;
 			map_write(map, CMD(0xb0), adr);
 			map_write(map, CMD(0x70), adr);
-			usec -= xip_elapsed_since(start);
 			suspended = xip_currtime();
 			do {
 				if (xip_elapsed_since(suspended) > 100000) {
@@ -944,7 +950,7 @@
 					 * This is a critical error but there
 					 * is not much we can do here.
 					 */
-					return;
+					return -EIO;
 				}
 				status = map_read(map, adr);
 			} while (!map_word_andequal(map, status, OK, OK));
@@ -1004,65 +1010,107 @@
 			xip_cpu_idle();
 		}
 		status = map_read(map, adr);
+		done = xip_elapsed_since(start);
 	} while (!map_word_andequal(map, status, OK, OK)
-		 && xip_elapsed_since(start) < usec);
-}
+		 && done < usec);
 
-#define UDELAY(map, chip, adr, usec)  xip_udelay(map, chip, adr, usec)
+	return (done >= usec) ? -ETIME : 0;
+}
 
 /*
  * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while
  * the flash is actively programming or erasing since we have to poll for
  * the operation to complete anyway.  We can't do that in a generic way with
  * a XIP setup so do it before the actual flash operation in this case
- * and stub it out from INVALIDATE_CACHE_UDELAY.
+ * and stub it out from INVAL_CACHE_AND_WAIT.
  */
 #define XIP_INVAL_CACHED_RANGE(map, from, size)  \
 	INVALIDATE_CACHED_RANGE(map, from, size)
 
-#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec)  \
-	UDELAY(map, chip, cmd_adr, usec)
-
-/*
- * Extra notes:
- *
- * Activating this XIP support changes the way the code works a bit.  For
- * example the code to suspend the current process when concurrent access
- * happens is never executed because xip_udelay() will always return with the
- * same chip state as it was entered with.  This is why there is no care for
- * the presence of add_wait_queue() or schedule() calls from within a couple
- * xip_disable()'d  areas of code, like in do_erase_oneblock for example.
- * The queueing and scheduling are always happening within xip_udelay().
- *
- * Similarly, get_chip() and put_chip() just happen to always be executed
- * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state
- * is in array mode, therefore never executing many cases therein and not
- * causing any problem with XIP.
- */
+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \
+	xip_wait_for_operation(map, chip, cmd_adr, p_usec)
 
 #else
 
 #define xip_disable(map, chip, adr)
 #define xip_enable(map, chip, adr)
 #define XIP_INVAL_CACHED_RANGE(x...)
+#define INVAL_CACHE_AND_WAIT inval_cache_and_wait_for_operation
 
-#define UDELAY(map, chip, adr, usec)  \
-do {  \
-	spin_unlock(chip->mutex);  \
-	cfi_udelay(usec);  \
-	spin_lock(chip->mutex);  \
-} while (0)
+static int inval_cache_and_wait_for_operation(
+		struct map_info *map, struct flchip *chip,
+		unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
+		int *chip_op_time )
+{
+	struct cfi_private *cfi = map->fldrv_priv;
+	map_word status, status_OK = CMD(0x80);
+	int z, chip_state = chip->state;
+	unsigned long timeo;
 
-#define INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr, adr, len, usec)  \
-do {  \
-	spin_unlock(chip->mutex);  \
-	INVALIDATE_CACHED_RANGE(map, adr, len);  \
-	cfi_udelay(usec);  \
-	spin_lock(chip->mutex);  \
-} while (0)
+	spin_unlock(chip->mutex);
+	if (inval_len)
+		INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
+	if (*chip_op_time)
+		cfi_udelay(*chip_op_time);
+	spin_lock(chip->mutex);
+
+	timeo = *chip_op_time * 8 * HZ / 1000000;
+	if (timeo < HZ/2)
+		timeo = HZ/2;
+	timeo += jiffies;
+
+	z = 0;
+	for (;;) {
+		if (chip->state != chip_state) {
+			/* Someone's suspended the operation: sleep */
+			DECLARE_WAITQUEUE(wait, current);
+
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			add_wait_queue(&chip->wq, &wait);
+			spin_unlock(chip->mutex);
+			schedule();
+			remove_wait_queue(&chip->wq, &wait);
+			timeo = jiffies + (HZ / 2); /* FIXME */
+			spin_lock(chip->mutex);
+			continue;
+		}
+
+		status = map_read(map, cmd_adr);
+		if (map_word_andequal(map, status, status_OK, status_OK))
+			break;
+
+		/* OK Still waiting */
+		if (time_after(jiffies, timeo)) {
+			map_write(map, CMD(0x70), cmd_adr);
+			chip->state = FL_STATUS;
+			return -ETIME;
+		}
+
+		/* Latency issues. Drop the lock, wait a while and retry */
+		z++;
+		spin_unlock(chip->mutex);
+		cfi_udelay(1);
+		spin_lock(chip->mutex);
+	}
+
+	if (!z) {
+		if (!--(*chip_op_time))
+			*chip_op_time = 1;
+	} else if (z > 1)
+		++(*chip_op_time);
+
+	/* Done and happy. */
+ 	chip->state = FL_STATUS;
+	return 0;
+}
 
 #endif
 
+#define WAIT_TIMEOUT(map, chip, adr, udelay) \
+	({ int __udelay = (udelay); \
+	   INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); })
+
+
 static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
 {
 	unsigned long cmd_addr;
@@ -1252,14 +1300,11 @@
 				     unsigned long adr, map_word datum, int mode)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
-	map_word status, status_OK, write_cmd;
-	unsigned long timeo;
-	int z, ret=0;
+	map_word status, write_cmd;
+	int ret=0;
 
 	adr += chip->start;
 
-	/* Let's determine those according to the interleave only once */
-	status_OK = CMD(0x80);
 	switch (mode) {
 	case FL_WRITING:
 		write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41);
@@ -1285,57 +1330,17 @@
 	map_write(map, datum, adr);
 	chip->state = mode;
 
-	INVALIDATE_CACHE_UDELAY(map, chip, adr,
-				adr, map_bankwidth(map),
-				chip->word_write_time);
-
-	timeo = jiffies + (HZ/2);
-	z = 0;
-	for (;;) {
-		if (chip->state != mode) {
-			/* Someone's suspended the write. Sleep */
-			DECLARE_WAITQUEUE(wait, current);
-
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			add_wait_queue(&chip->wq, &wait);
-			spin_unlock(chip->mutex);
-			schedule();
-			remove_wait_queue(&chip->wq, &wait);
-			timeo = jiffies + (HZ / 2); /* FIXME */
-			spin_lock(chip->mutex);
-			continue;
-		}
-
-		status = map_read(map, adr);
-		if (map_word_andequal(map, status, status_OK, status_OK))
-			break;
-
-		/* OK Still waiting */
-		if (time_after(jiffies, timeo)) {
-			map_write(map, CMD(0x70), adr);
-			chip->state = FL_STATUS;
-			xip_enable(map, chip, adr);
-			printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
-			ret = -EIO;
-			goto out;
-		}
-
-		/* Latency issues. Drop the lock, wait a while and retry */
-		z++;
-		UDELAY(map, chip, adr, 1);
+	ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
+				   adr, map_bankwidth(map),
+				   &chip->word_write_time);
+	if (ret) {
+		xip_enable(map, chip, adr);
+		printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
+		goto out;
 	}
-	if (!z) {
-		chip->word_write_time--;
-		if (!chip->word_write_time)
-			chip->word_write_time = 1;
-	}
-	if (z > 1)
-		chip->word_write_time++;
-
-	/* Done and happy. */
-	chip->state = FL_STATUS;
 
 	/* check for errors */
+	status = map_read(map, adr);
 	if (map_word_bitsset(map, status, CMD(0x1a))) {
 		unsigned long chipstatus = MERGESTATUS(status);
 
@@ -1452,9 +1457,9 @@
 				    unsigned long *pvec_seek, int len)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
-	map_word status, status_OK, write_cmd, datum;
-	unsigned long cmd_adr, timeo;
-	int wbufsize, z, ret=0, word_gap, words;
+	map_word status, write_cmd, datum;
+	unsigned long cmd_adr;
+	int ret, wbufsize, word_gap, words;
 	const struct kvec *vec;
 	unsigned long vec_seek;
 
@@ -1463,7 +1468,6 @@
 	cmd_adr = adr & ~(wbufsize-1);
 
 	/* Let's determine this according to the interleave only once */
-	status_OK = CMD(0x80);
 	write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9);
 
 	spin_lock(chip->mutex);
@@ -1477,12 +1481,14 @@
 	ENABLE_VPP(map);
 	xip_disable(map, chip, cmd_adr);
 
-	/* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
+	/* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set
 	   [...], the device will not accept any more Write to Buffer commands".
 	   So we must check here and reset those bits if they're set. Otherwise
 	   we're just pissing in the wind */
-	if (chip->state != FL_STATUS)
+	if (chip->state != FL_STATUS) {
 		map_write(map, CMD(0x70), cmd_adr);
+		chip->state = FL_STATUS;
+	}
 	status = map_read(map, cmd_adr);
 	if (map_word_bitsset(map, status, CMD(0x30))) {
 		xip_enable(map, chip, cmd_adr);
@@ -1493,32 +1499,20 @@
 	}
 
 	chip->state = FL_WRITING_TO_BUFFER;
-
-	z = 0;
-	for (;;) {
-		map_write(map, write_cmd, cmd_adr);
-
+	map_write(map, write_cmd, cmd_adr);
+	ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0);
+	if (ret) {
+		/* Argh. Not ready for write to buffer */
+		map_word Xstatus = map_read(map, cmd_adr);
+		map_write(map, CMD(0x70), cmd_adr);
+		chip->state = FL_STATUS;
 		status = map_read(map, cmd_adr);
-		if (map_word_andequal(map, status, status_OK, status_OK))
-			break;
-
-		UDELAY(map, chip, cmd_adr, 1);
-
-		if (++z > 20) {
-			/* Argh. Not ready for write to buffer */
-			map_word Xstatus;
-			map_write(map, CMD(0x70), cmd_adr);
-			chip->state = FL_STATUS;
-			Xstatus = map_read(map, cmd_adr);
-			/* Odd. Clear status bits */
-			map_write(map, CMD(0x50), cmd_adr);
-			map_write(map, CMD(0x70), cmd_adr);
-			xip_enable(map, chip, cmd_adr);
-			printk(KERN_ERR "%s: Chip not ready for buffer write. status = %lx, Xstatus = %lx\n",
-			       map->name, status.x[0], Xstatus.x[0]);
-			ret = -EIO;
-			goto out;
-		}
+		map_write(map, CMD(0x50), cmd_adr);
+		map_write(map, CMD(0x70), cmd_adr);
+		xip_enable(map, chip, cmd_adr);
+		printk(KERN_ERR "%s: Chip not ready for buffer write. Xstatus = %lx, status = %lx\n",
+				map->name, Xstatus.x[0], status.x[0]);
+		goto out;
 	}
 
 	/* Figure out the number of words to write */
@@ -1573,56 +1567,19 @@
 	map_write(map, CMD(0xd0), cmd_adr);
 	chip->state = FL_WRITING;
 
-	INVALIDATE_CACHE_UDELAY(map, chip, cmd_adr,
-				adr, len,
-				chip->buffer_write_time);
-
-	timeo = jiffies + (HZ/2);
-	z = 0;
-	for (;;) {
-		if (chip->state != FL_WRITING) {
-			/* Someone's suspended the write. Sleep */
-			DECLARE_WAITQUEUE(wait, current);
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			add_wait_queue(&chip->wq, &wait);
-			spin_unlock(chip->mutex);
-			schedule();
-			remove_wait_queue(&chip->wq, &wait);
-			timeo = jiffies + (HZ / 2); /* FIXME */
-			spin_lock(chip->mutex);
-			continue;
-		}
-
-		status = map_read(map, cmd_adr);
-		if (map_word_andequal(map, status, status_OK, status_OK))
-			break;
-
-		/* OK Still waiting */
-		if (time_after(jiffies, timeo)) {
-			map_write(map, CMD(0x70), cmd_adr);
-			chip->state = FL_STATUS;
-			xip_enable(map, chip, cmd_adr);
-			printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name);
-			ret = -EIO;
-			goto out;
-		}
-
-		/* Latency issues. Drop the lock, wait a while and retry */
-		z++;
-		UDELAY(map, chip, cmd_adr, 1);
+	ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
+				   adr, len,
+				   &chip->buffer_write_time);
+	if (ret) {
+		map_write(map, CMD(0x70), cmd_adr);
+		chip->state = FL_STATUS;
+		xip_enable(map, chip, cmd_adr);
+		printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name);
+		goto out;
 	}
-	if (!z) {
-		chip->buffer_write_time--;
-		if (!chip->buffer_write_time)
-			chip->buffer_write_time = 1;
-	}
-	if (z > 1)
-		chip->buffer_write_time++;
-
-	/* Done and happy. */
- 	chip->state = FL_STATUS;
 
 	/* check for errors */
+	status = map_read(map, cmd_adr);
 	if (map_word_bitsset(map, status, CMD(0x1a))) {
 		unsigned long chipstatus = MERGESTATUS(status);
 
@@ -1693,6 +1650,11 @@
 			if (chipnum == cfi->numchips)
 				return 0;
 		}
+
+		/* Be nice and reschedule with the chip in a usable state for other
+		   processes. */
+		cond_resched();
+
 	} while (len);
 
 	return 0;
@@ -1713,17 +1675,12 @@
 				      unsigned long adr, int len, void *thunk)
 {
 	struct cfi_private *cfi = map->fldrv_priv;
-	map_word status, status_OK;
-	unsigned long timeo;
+	map_word status;
 	int retries = 3;
-	DECLARE_WAITQUEUE(wait, current);
-	int ret = 0;
+	int ret;
 
 	adr += chip->start;
 
-	/* Let's determine this according to the interleave only once */
-	status_OK = CMD(0x80);
-
  retry:
 	spin_lock(chip->mutex);
 	ret = get_chip(map, chip, adr, FL_ERASING);
@@ -1745,48 +1702,15 @@
 	chip->state = FL_ERASING;
 	chip->erase_suspended = 0;
 
-	INVALIDATE_CACHE_UDELAY(map, chip, adr,
-				adr, len,
-				chip->erase_time*1000/2);
-
-	/* FIXME. Use a timer to check this, and return immediately. */
-	/* Once the state machine's known to be working I'll do that */
-
-	timeo = jiffies + (HZ*20);
-	for (;;) {
-		if (chip->state != FL_ERASING) {
-			/* Someone's suspended the erase. Sleep */
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			add_wait_queue(&chip->wq, &wait);
-			spin_unlock(chip->mutex);
-			schedule();
-			remove_wait_queue(&chip->wq, &wait);
-			spin_lock(chip->mutex);
-			continue;
-		}
-		if (chip->erase_suspended) {
-			/* This erase was suspended and resumed.
-			   Adjust the timeout */
-			timeo = jiffies + (HZ*20); /* FIXME */
-			chip->erase_suspended = 0;
-		}
-
-		status = map_read(map, adr);
-		if (map_word_andequal(map, status, status_OK, status_OK))
-			break;
-
-		/* OK Still waiting */
-		if (time_after(jiffies, timeo)) {
-			map_write(map, CMD(0x70), adr);
-			chip->state = FL_STATUS;
-			xip_enable(map, chip, adr);
-			printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name);
-			ret = -EIO;
-			goto out;
-		}
-
-		/* Latency issues. Drop the lock, wait a while and retry */
-		UDELAY(map, chip, adr, 1000000/HZ);
+	ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
+				   adr, len,
+				   &chip->erase_time);
+	if (ret) {
+		map_write(map, CMD(0x70), adr);
+		chip->state = FL_STATUS;
+		xip_enable(map, chip, adr);
+		printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name);
+		goto out;
 	}
 
 	/* We've broken this before. It doesn't hurt to be safe */
@@ -1815,7 +1739,6 @@
 			ret = -EIO;
 		} else if (chipstatus & 0x20 && retries--) {
 			printk(KERN_DEBUG "block erase failed at 0x%08lx: status 0x%lx. Retrying...\n", adr, chipstatus);
-			timeo = jiffies + HZ;
 			put_chip(map, chip, adr);
 			spin_unlock(chip->mutex);
 			goto retry;
@@ -1921,15 +1844,11 @@
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_pri_intelext *extp = cfi->cmdset_priv;
-	map_word status, status_OK;
-	unsigned long timeo = jiffies + HZ;
+	int udelay;
 	int ret;
 
 	adr += chip->start;
 
-	/* Let's determine this according to the interleave only once */
-	status_OK = CMD(0x80);
-
 	spin_lock(chip->mutex);
 	ret = get_chip(map, chip, adr, FL_LOCKING);
 	if (ret) {
@@ -1954,41 +1873,21 @@
 	 * If Instant Individual Block Locking supported then no need
 	 * to delay.
 	 */
+	udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0;
 
-	if (!extp || !(extp->FeatureSupport & (1 << 5)))
-		UDELAY(map, chip, adr, 1000000/HZ);
-
-	/* FIXME. Use a timer to check this, and return immediately. */
-	/* Once the state machine's known to be working I'll do that */
-
-	timeo = jiffies + (HZ*20);
-	for (;;) {
-
-		status = map_read(map, adr);
-		if (map_word_andequal(map, status, status_OK, status_OK))
-			break;
-
-		/* OK Still waiting */
-		if (time_after(jiffies, timeo)) {
-			map_write(map, CMD(0x70), adr);
-			chip->state = FL_STATUS;
-			xip_enable(map, chip, adr);
-			printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name);
-			put_chip(map, chip, adr);
-			spin_unlock(chip->mutex);
-			return -EIO;
-		}
-
-		/* Latency issues. Drop the lock, wait a while and retry */
-		UDELAY(map, chip, adr, 1);
+	ret = WAIT_TIMEOUT(map, chip, adr, udelay);
+	if (ret) {
+		map_write(map, CMD(0x70), adr);
+		chip->state = FL_STATUS;
+		xip_enable(map, chip, adr);
+		printk(KERN_ERR "%s: block unlock error: (status timeout)\n", map->name);
+		goto out;
 	}
 
-	/* Done and happy. */
-	chip->state = FL_STATUS;
 	xip_enable(map, chip, adr);
-	put_chip(map, chip, adr);
+out:	put_chip(map, chip, adr);
 	spin_unlock(chip->mutex);
-	return 0;
+	return ret;
 }
 
 static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
@@ -2445,28 +2344,8 @@
 	kfree(mtd->eraseregions);
 }
 
-static char im_name_0001[] = "cfi_cmdset_0001";
-static char im_name_0003[] = "cfi_cmdset_0003";
-static char im_name_0200[] = "cfi_cmdset_0200";
-
-static int __init cfi_intelext_init(void)
-{
-	inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001);
-	inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001);
-	inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001);
-	return 0;
-}
-
-static void __exit cfi_intelext_exit(void)
-{
-	inter_module_unregister(im_name_0001);
-	inter_module_unregister(im_name_0003);
-	inter_module_unregister(im_name_0200);
-}
-
-module_init(cfi_intelext_init);
-module_exit(cfi_intelext_exit);
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
 MODULE_DESCRIPTION("MTD chip driver for Intel/Sharp flash chips");
+MODULE_ALIAS("cfi_cmdset_0003");
+MODULE_ALIAS("cfi_cmdset_0200");
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index aed10bd..1e01ad3 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -236,6 +236,7 @@
 	mtd->resume  = cfi_amdstd_resume;
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->name    = map->name;
+	mtd->writesize = 1;
 
 	if (cfi->cfi_mode==CFI_MODE_CFI){
 		unsigned char bootloc;
@@ -326,7 +327,7 @@
 
 	return cfi_amdstd_setup(mtd);
 }
-
+EXPORT_SYMBOL_GPL(cfi_cmdset_0002);
 
 static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
 {
@@ -1758,25 +1759,6 @@
 	kfree(mtd->eraseregions);
 }
 
-static char im_name[]="cfi_cmdset_0002";
-
-
-static int __init cfi_amdstd_init(void)
-{
-	inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002);
-	return 0;
-}
-
-
-static void __exit cfi_amdstd_exit(void)
-{
-	inter_module_unregister(im_name);
-}
-
-
-module_init(cfi_amdstd_init);
-module_exit(cfi_amdstd_exit);
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp> et al.");
 MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips");
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index 0807c1c..fae70a5 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -162,6 +162,7 @@
 
 	return cfi_staa_setup(map);
 }
+EXPORT_SYMBOL_GPL(cfi_cmdset_0020);
 
 static struct mtd_info *cfi_staa_setup(struct map_info *map)
 {
@@ -237,9 +238,8 @@
 	mtd->unlock = cfi_staa_unlock;
 	mtd->suspend = cfi_staa_suspend;
 	mtd->resume = cfi_staa_resume;
-	mtd->flags = MTD_CAP_NORFLASH;
-	mtd->flags |= MTD_ECC; /* FIXME: Not all STMicro flashes have this */
-	mtd->eccsize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
+	mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
+	mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
 	map->fldrv = &cfi_staa_chipdrv;
 	__module_get(THIS_MODULE);
 	mtd->name = map->name;
@@ -1410,20 +1410,4 @@
 	kfree(cfi);
 }
 
-static char im_name[]="cfi_cmdset_0020";
-
-static int __init cfi_staa_init(void)
-{
-	inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0020);
-	return 0;
-}
-
-static void __exit cfi_staa_exit(void)
-{
-	inter_module_unregister(im_name);
-}
-
-module_init(cfi_staa_init);
-module_exit(cfi_staa_exit);
-
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c
index e636aa8..4bf9f8c 100644
--- a/drivers/mtd/chips/cfi_probe.c
+++ b/drivers/mtd/chips/cfi_probe.c
@@ -349,12 +349,12 @@
 	else
 		printk("No Vpp line\n");
 
-	printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
-	printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
+	printk("Typical byte/word write timeout: %d µs\n", 1<<cfip->WordWriteTimeoutTyp);
+	printk("Maximum byte/word write timeout: %d µs\n", (1<<cfip->WordWriteTimeoutMax) * (1<<cfip->WordWriteTimeoutTyp));
 
 	if (cfip->BufWriteTimeoutTyp || cfip->BufWriteTimeoutMax) {
-		printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
-		printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
+		printk("Typical full buffer write timeout: %d µs\n", 1<<cfip->BufWriteTimeoutTyp);
+		printk("Maximum full buffer write timeout: %d µs\n", (1<<cfip->BufWriteTimeoutMax) * (1<<cfip->BufWriteTimeoutTyp));
 	}
 	else
 		printk("Full buffer write not supported\n");
diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c
index 41bd59d..cdb0f59 100644
--- a/drivers/mtd/chips/gen_probe.c
+++ b/drivers/mtd/chips/gen_probe.c
@@ -37,8 +37,15 @@
 	if (!mtd)
 		mtd = check_cmd_set(map, 0); /* Then the secondary */
 
-	if (mtd)
+	if (mtd) {
+		if (mtd->size > map->size) {
+			printk(KERN_WARNING "Reducing visibility of %ldKiB chip to %ldKiB\n",
+			       (unsigned long)mtd->size >> 10, 
+			       (unsigned long)map->size >> 10);
+			mtd->size = map->size;
+		}
 		return mtd;
+	}
 
 	printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
 
@@ -100,7 +107,12 @@
 	 * Align bitmap storage size to full byte.
 	 */
 	max_chips = map->size >> cfi.chipshift;
-	mapsize = (max_chips / 8) + ((max_chips % 8) ? 1 : 0);
+	if (!max_chips) {
+		printk(KERN_WARNING "NOR chip too large to fit in mapping. Attempting to cope...\n");
+		max_chips = 1;
+	}
+
+	mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG;
 	chip_map = kmalloc(mapsize, GFP_KERNEL);
 	if (!chip_map) {
 		printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
@@ -194,25 +206,28 @@
 {
 	struct cfi_private *cfi = map->fldrv_priv;
 	__u16 type = primary?cfi->cfiq->P_ID:cfi->cfiq->A_ID;
-#if defined(CONFIG_MODULES) && defined(HAVE_INTER_MODULE)
-	char probename[32];
+#ifdef CONFIG_MODULES
+	char probename[16+sizeof(MODULE_SYMBOL_PREFIX)];
 	cfi_cmdset_fn_t *probe_function;
 
-	sprintf(probename, "cfi_cmdset_%4.4X", type);
+	sprintf(probename, MODULE_SYMBOL_PREFIX "cfi_cmdset_%4.4X", type);
 
-	probe_function = inter_module_get_request(probename, probename);
+	probe_function = __symbol_get(probename);
+	if (!probe_function) {
+		request_module(probename + sizeof(MODULE_SYMBOL_PREFIX) - 1);
+		probe_function = __symbol_get(probename);
+	}
 
 	if (probe_function) {
 		struct mtd_info *mtd;
 
 		mtd = (*probe_function)(map, primary);
 		/* If it was happy, it'll have increased its own use count */
-		inter_module_put(probename);
+		symbol_put_addr(probe_function);
 		return mtd;
 	}
 #endif
-	printk(KERN_NOTICE "Support for command set %04X not present\n",
-	       type);
+	printk(KERN_NOTICE "Support for command set %04X not present\n", type);
 
 	return NULL;
 }
@@ -226,12 +241,8 @@
 		return NULL;
 
 	switch(type){
-		/* Urgh. Ifdefs. The version with weak symbols was
-		 * _much_ nicer. Shame it didn't seem to work on
-		 * anything but x86, really.
-		 * But we can't rely in inter_module_get() because
-		 * that'd mean we depend on link order.
-		 */
+		/* We need these for the !CONFIG_MODULES case,
+		   because symbol_get() doesn't work there */
 #ifdef CONFIG_MTD_CFI_INTELEXT
 	case 0x0001:
 	case 0x0003:
@@ -246,9 +257,9 @@
         case 0x0020:
 		return cfi_cmdset_0020(map, primary);
 #endif
+	default:
+		return cfi_cmdset_unknown(map, primary);
 	}
-
-	return cfi_cmdset_unknown(map, primary);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/chips/jedec.c b/drivers/mtd/chips/jedec.c
index c40b48d..2c3f019 100644
--- a/drivers/mtd/chips/jedec.c
+++ b/drivers/mtd/chips/jedec.c
@@ -256,6 +256,7 @@
    MTD->name = map->name;
    MTD->type = MTD_NORFLASH;
    MTD->flags = MTD_CAP_NORFLASH;
+   MTD->writesize = 1;
    MTD->erasesize = SectorSize*(map->buswidth);
    //   printk("MTD->erasesize is %x\n",(unsigned int)MTD->erasesize);
    MTD->size = priv->size;
diff --git a/drivers/mtd/chips/map_absent.c b/drivers/mtd/chips/map_absent.c
index a611de9..ac01a94 100644
--- a/drivers/mtd/chips/map_absent.c
+++ b/drivers/mtd/chips/map_absent.c
@@ -64,7 +64,8 @@
 	mtd->write 	= map_absent_write;
 	mtd->sync 	= map_absent_sync;
 	mtd->flags 	= 0;
-	mtd->erasesize = PAGE_SIZE;
+	mtd->erasesize  = PAGE_SIZE;
+	mtd->writesize  = 1;
 
 	__module_get(THIS_MODULE);
 	return mtd;
diff --git a/drivers/mtd/chips/map_ram.c b/drivers/mtd/chips/map_ram.c
index bd2e876..3a66680 100644
--- a/drivers/mtd/chips/map_ram.c
+++ b/drivers/mtd/chips/map_ram.c
@@ -70,7 +70,8 @@
 	mtd->read = mapram_read;
 	mtd->write = mapram_write;
 	mtd->sync = mapram_nop;
-	mtd->flags = MTD_CAP_RAM | MTD_VOLATILE;
+	mtd->flags = MTD_CAP_RAM;
+	mtd->writesize = 1;
 
 	mtd->erasesize = PAGE_SIZE;
  	while(mtd->size & (mtd->erasesize - 1))
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 624c12c..1b328b1 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -46,9 +46,8 @@
 	mtd->write = maprom_write;
 	mtd->sync = maprom_nop;
 	mtd->flags = MTD_CAP_ROM;
-	mtd->erasesize = 131072;
- 	while(mtd->size & (mtd->erasesize - 1))
-		mtd->erasesize >>= 1;
+	mtd->erasesize = map->size;
+	mtd->writesize = 1;
 
 	__module_get(THIS_MODULE);
 	return mtd;
diff --git a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c
index 3cc0b23..967abbe 100644
--- a/drivers/mtd/chips/sharp.c
+++ b/drivers/mtd/chips/sharp.c
@@ -140,6 +140,7 @@
 	mtd->suspend = sharp_suspend;
 	mtd->resume = sharp_resume;
 	mtd->flags = MTD_CAP_NORFLASH;
+	mtd->writesize = 1;
 	mtd->name = map->name;
 
 	memset(sharp, 0, sizeof(*sharp));
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 7fac438..16c02b5 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -47,6 +47,11 @@
 	  accelerator.  Say Y here if you have a DECstation 5000/2x0 or a
 	  DECsystem 5900 equipped with such a module.
 
+	  If you want to compile this driver as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>.  The module will
+	  be called ms02-nv.o.
+
 config MTD_DATAFLASH
 	tristate "Support for AT45xxx DataFlash"
 	depends on MTD && SPI_MASTER && EXPERIMENTAL
@@ -209,7 +214,6 @@
 config MTD_DOCPROBE
 	tristate
 	select MTD_DOCECC
-	select OBSOLETE_INTERMODULE
 
 config MTD_DOCECC
 	tristate
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index b657367..0f788d5 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -3,13 +3,6 @@
 #
 # $Id: Makefile.common,v 1.7 2004/12/22 17:51:15 joern Exp $
 
-#                       *** BIG UGLY NOTE ***
-#
-# The removal of get_module_symbol() and replacement with
-# inter_module_register() et al has introduced a link order dependency
-# here where previously there was none.  We now have to ensure that
-# doc200[01].o are linked before docprobe.o
-
 obj-$(CONFIG_MTD_DOC2000)	+= doc2000.o
 obj-$(CONFIG_MTD_DOC2001)	+= doc2001.o
 obj-$(CONFIG_MTD_DOC2001PLUS)	+= doc2001plus.o
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 4160b83..be3f1c1 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -4,7 +4,7 @@
  * block2mtd.c - create an mtd from a block device
  *
  * Copyright (C) 2001,2002	Simon Evans <spse@secret.org.uk>
- * Copyright (C) 2004,2005	Jörn Engel <joern@wh.fh-wedel.de>
+ * Copyright (C) 2004-2006	Jörn Engel <joern@wh.fh-wedel.de>
  *
  * Licence: GPL
  */
@@ -324,6 +324,7 @@
 
 	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
 	dev->mtd.erasesize = erase_size;
+	dev->mtd.writesize = 1;
 	dev->mtd.type = MTD_RAM;
 	dev->mtd.flags = MTD_CAP_RAM;
 	dev->mtd.erase = block2mtd_erase;
@@ -331,7 +332,6 @@
 	dev->mtd.writev = default_mtd_writev;
 	dev->mtd.sync = block2mtd_sync;
 	dev->mtd.read = block2mtd_read;
-	dev->mtd.readv = default_mtd_readv;
 	dev->mtd.priv = dev;
 	dev->mtd.owner = THIS_MODULE;
 
@@ -351,6 +351,12 @@
 }
 
 
+/* This function works similar to reguler strtoul.  In addition, it
+ * allows some suffixes for a more human-readable number format:
+ * ki, Ki, kiB, KiB	- multiply result with 1024
+ * Mi, MiB		- multiply result with 1024^2
+ * Gi, GiB		- multiply result with 1024^3
+ */
 static int ustrtoul(const char *cp, char **endp, unsigned int base)
 {
 	unsigned long result = simple_strtoul(cp, endp, base);
@@ -359,11 +365,16 @@
 		result *= 1024;
 	case 'M':
 		result *= 1024;
+	case 'K':
 	case 'k':
 		result *= 1024;
 	/* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
-		if ((*endp)[1] == 'i')
-			(*endp) += 2;
+		if ((*endp)[1] == 'i') {
+			if ((*endp)[2] == 'B')
+				(*endp) += 3;
+			else
+				(*endp) += 2;
+		}
 	}
 	return result;
 }
@@ -418,7 +429,8 @@
 
 static int block2mtd_setup(const char *val, struct kernel_param *kp)
 {
-	char buf[80+12], *str=buf; /* 80 for device, 12 for erase size */
+	char buf[80+12]; /* 80 for device, 12 for erase size */
+	char *str = buf;
 	char *token[2];
 	char *name;
 	size_t erase_size = PAGE_SIZE;
@@ -430,7 +442,7 @@
 	strcpy(str, val);
 	kill_final_newline(str);
 
-	for (i=0; i<2; i++)
+	for (i = 0; i < 2; i++)
 		token[i] = strsep(&str, ",");
 
 	if (str)
@@ -449,8 +461,10 @@
 
 	if (token[1]) {
 		ret = parse_num(&erase_size, token[1]);
-		if (ret)
+		if (ret) {
+			kfree(name);
 			parse_err("illegal erase size");
+		}
 	}
 
 	add_device(name, erase_size);
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index 23e7a5c..c54e404 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -59,13 +59,10 @@
 			size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
 			 size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
-static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
-			  unsigned long count, loff_t to, size_t *retlen,
-			  u_char *eccbuf, struct nand_oobinfo *oobsel);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			 size_t *retlen, const u_char *buf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+			struct mtd_oob_ops *ops);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+			 struct mtd_oob_ops *ops);
 static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
 			 size_t *retlen, const u_char *buf);
 static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
@@ -517,16 +514,9 @@
 	return retval;
 }
 
-static const char im_name[] = "DoC2k_init";
-
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in mtd are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
-static void DoC2k_init(struct mtd_info *mtd)
+/* This routine is found from the docprobe code by symbol_get(),
+ * which will bump the use count of this module. */
+void DoC2k_init(struct mtd_info *mtd)
 {
 	struct DiskOnChip *this = mtd->priv;
 	struct DiskOnChip *old = NULL;
@@ -586,7 +576,7 @@
 	mtd->ecctype = MTD_ECC_RS_DiskOnChip;
 	mtd->size = 0;
 	mtd->erasesize = 0;
-	mtd->oobblock = 512;
+	mtd->writesize = 512;
 	mtd->oobsize = 16;
 	mtd->owner = THIS_MODULE;
 	mtd->erase = doc_erase;
@@ -594,9 +584,6 @@
 	mtd->unpoint = NULL;
 	mtd->read = doc_read;
 	mtd->write = doc_write;
-	mtd->read_ecc = doc_read_ecc;
-	mtd->write_ecc = doc_write_ecc;
-	mtd->writev_ecc = doc_writev_ecc;
 	mtd->read_oob = doc_read_oob;
 	mtd->write_oob = doc_write_oob;
 	mtd->sync = NULL;
@@ -623,6 +610,7 @@
 		return;
 	}
 }
+EXPORT_SYMBOL_GPL(DoC2k_init);
 
 static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 		    size_t * retlen, u_char * buf)
@@ -971,72 +959,18 @@
 	return 0;
 }
 
-static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
-			  unsigned long count, loff_t to, size_t *retlen,
-			  u_char *eccbuf, struct nand_oobinfo *oobsel)
-{
-	static char static_buf[512];
-	static DEFINE_MUTEX(writev_buf_mutex);
-
-	size_t totretlen = 0;
-	size_t thisvecofs = 0;
-	int ret= 0;
-
-	mutex_lock(&writev_buf_mutex);
-
-	while(count) {
-		size_t thislen, thisretlen;
-		unsigned char *buf;
-
-		buf = vecs->iov_base + thisvecofs;
-		thislen = vecs->iov_len - thisvecofs;
-
-
-		if (thislen >= 512) {
-			thislen = thislen & ~(512-1);
-			thisvecofs += thislen;
-		} else {
-			/* Not enough to fill a page. Copy into buf */
-			memcpy(static_buf, buf, thislen);
-			buf = &static_buf[thislen];
-
-			while(count && thislen < 512) {
-				vecs++;
-				count--;
-				thisvecofs = min((512-thislen), vecs->iov_len);
-				memcpy(buf, vecs->iov_base, thisvecofs);
-				thislen += thisvecofs;
-				buf += thisvecofs;
-			}
-			buf = static_buf;
-		}
-		if (count && thisvecofs == vecs->iov_len) {
-			thisvecofs = 0;
-			vecs++;
-			count--;
-		}
-		ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel);
-
-		totretlen += thisretlen;
-
-		if (ret || thisretlen != thislen)
-			break;
-
-		to += thislen;
-	}
-
-	mutex_unlock(&writev_buf_mutex);
-	*retlen = totretlen;
-	return ret;
-}
-
-
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			size_t * retlen, u_char * buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+			struct mtd_oob_ops *ops)
 {
 	struct DiskOnChip *this = mtd->priv;
 	int len256 = 0, ret;
 	struct Nand *mychip;
+	uint8_t *buf = ops->oobbuf;
+	size_t len = ops->len;
+
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+	ofs += ops->ooboffs;
 
 	mutex_lock(&this->lock);
 
@@ -1077,7 +1011,7 @@
 
 	DoC_ReadBuf(this, &buf[len256], len - len256);
 
-	*retlen = len;
+	ops->retlen = len;
 	/* Reading the full OOB data drops us off of the end of the page,
          * causing the flash device to go into busy mode, so we need
          * to wait until ready 11.4.1 and Toshiba TC58256FT docs */
@@ -1192,17 +1126,20 @@
 
 }
 
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
- 			 size_t * retlen, const u_char * buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+			 struct mtd_oob_ops *ops)
 {
- 	struct DiskOnChip *this = mtd->priv;
- 	int ret;
+	struct DiskOnChip *this = mtd->priv;
+	int ret;
 
- 	mutex_lock(&this->lock);
- 	ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf);
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
 
- 	mutex_unlock(&this->lock);
- 	return ret;
+	mutex_lock(&this->lock);
+	ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
+				   &ops->retlen, ops->oobbuf);
+
+	mutex_unlock(&this->lock);
+	return ret;
 }
 
 static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
@@ -1277,12 +1214,6 @@
  *
  ****************************************************************************/
 
-static int __init init_doc2000(void)
-{
-       inter_module_register(im_name, THIS_MODULE, &DoC2k_init);
-       return 0;
-}
-
 static void __exit cleanup_doc2000(void)
 {
 	struct mtd_info *mtd;
@@ -1298,11 +1229,9 @@
 		kfree(this->chips);
 		kfree(mtd);
 	}
-	inter_module_unregister(im_name);
 }
 
 module_exit(cleanup_doc2000);
-module_init(init_doc2000);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index 681a9c7..0cf022a 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -43,10 +43,10 @@
 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
 			 size_t *retlen, const u_char *buf, u_char *eccbuf,
 			 struct nand_oobinfo *oobsel);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			 size_t *retlen, const u_char *buf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+			struct mtd_oob_ops *ops);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+			 struct mtd_oob_ops *ops);
 static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
 
 static struct mtd_info *docmillist = NULL;
@@ -324,16 +324,9 @@
 	return retval;
 }
 
-static const char im_name[] = "DoCMil_init";
-
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in mtd are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
-static void DoCMil_init(struct mtd_info *mtd)
+/* This routine is found from the docprobe code by symbol_get(),
+ * which will bump the use count of this module. */
+void DoCMil_init(struct mtd_info *mtd)
 {
 	struct DiskOnChip *this = mtd->priv;
 	struct DiskOnChip *old = NULL;
@@ -368,7 +361,7 @@
 	/* FIXME: erase size is not always 8KiB */
 	mtd->erasesize = 0x2000;
 
-	mtd->oobblock = 512;
+	mtd->writesize = 512;
 	mtd->oobsize = 16;
 	mtd->owner = THIS_MODULE;
 	mtd->erase = doc_erase;
@@ -376,8 +369,6 @@
 	mtd->unpoint = NULL;
 	mtd->read = doc_read;
 	mtd->write = doc_write;
-	mtd->read_ecc = doc_read_ecc;
-	mtd->write_ecc = doc_write_ecc;
 	mtd->read_oob = doc_read_oob;
 	mtd->write_oob = doc_write_oob;
 	mtd->sync = NULL;
@@ -401,6 +392,7 @@
 		return;
 	}
 }
+EXPORT_SYMBOL_GPL(DoCMil_init);
 
 static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
 		     size_t *retlen, u_char *buf)
@@ -670,8 +662,8 @@
 	return ret;
 }
 
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			size_t *retlen, u_char *buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+			struct mtd_oob_ops *ops)
 {
 #ifndef USE_MEMCPY
 	int i;
@@ -680,6 +672,12 @@
 	struct DiskOnChip *this = mtd->priv;
 	void __iomem *docptr = this->virtadr;
 	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
+	uint8_t *buf = ops->oobbuf;
+	size_t len = ops->len;
+
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+	ofs += ops->ooboffs;
 
 	/* Find the chip which is to be used and select it */
 	if (this->curfloor != mychip->floor) {
@@ -716,13 +714,13 @@
 #endif
 	buf[len - 1] = ReadDOC(docptr, LastDataRead);
 
-	*retlen = len;
+	ops->retlen = len;
 
 	return 0;
 }
 
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			 size_t *retlen, const u_char *buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+			 struct mtd_oob_ops *ops)
 {
 #ifndef USE_MEMCPY
 	int i;
@@ -732,6 +730,12 @@
 	struct DiskOnChip *this = mtd->priv;
 	void __iomem *docptr = this->virtadr;
 	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
+	uint8_t *buf = ops->oobbuf;
+	size_t len = ops->len;
+
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+	ofs += ops->ooboffs;
 
 	/* Find the chip which is to be used and select it */
 	if (this->curfloor != mychip->floor) {
@@ -783,12 +787,12 @@
 	if (ReadDOC(docptr, Mil_CDSN_IO) & 1) {
 		printk("Error programming oob data\n");
 		/* FIXME: implement Bad Block Replacement (in nftl.c ??) */
-		*retlen = 0;
+		ops->retlen = 0;
 		ret = -EIO;
 	}
 	dummy = ReadDOC(docptr, LastDataRead);
 
-	*retlen = len;
+	ops->retlen = len;
 
 	return ret;
 }
@@ -856,12 +860,6 @@
  *
  ****************************************************************************/
 
-static int __init init_doc2001(void)
-{
-	inter_module_register(im_name, THIS_MODULE, &DoCMil_init);
-	return 0;
-}
-
 static void __exit cleanup_doc2001(void)
 {
 	struct mtd_info *mtd;
@@ -877,11 +875,9 @@
 		kfree(this->chips);
 		kfree(mtd);
 	}
-	inter_module_unregister(im_name);
 }
 
 module_exit(cleanup_doc2001);
-module_init(init_doc2001);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al.");
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 5f57f29..66cb1e5 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -47,10 +47,10 @@
 static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
 		size_t *retlen, const u_char *buf, u_char *eccbuf,
 		struct nand_oobinfo *oobsel);
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-		size_t *retlen, u_char *buf);
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-		size_t *retlen, const u_char *buf);
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+			struct mtd_oob_ops *ops);
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+			 struct mtd_oob_ops *ops);
 static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
 
 static struct mtd_info *docmilpluslist = NULL;
@@ -447,16 +447,9 @@
 	return retval;
 }
 
-static const char im_name[] = "DoCMilPlus_init";
-
-/* This routine is made available to other mtd code via
- * inter_module_register.  It must only be accessed through
- * inter_module_get which will bump the use count of this module.  The
- * addresses passed back in mtd are valid as long as the use count of
- * this module is non-zero, i.e. between inter_module_get and
- * inter_module_put.  Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
- */
-static void DoCMilPlus_init(struct mtd_info *mtd)
+/* This routine is found from the docprobe code by symbol_get(),
+ * which will bump the use count of this module. */
+void DoCMilPlus_init(struct mtd_info *mtd)
 {
 	struct DiskOnChip *this = mtd->priv;
 	struct DiskOnChip *old = NULL;
@@ -490,7 +483,7 @@
 	mtd->size = 0;
 
 	mtd->erasesize = 0;
-	mtd->oobblock = 512;
+	mtd->writesize = 512;
 	mtd->oobsize = 16;
 	mtd->owner = THIS_MODULE;
 	mtd->erase = doc_erase;
@@ -498,8 +491,6 @@
 	mtd->unpoint = NULL;
 	mtd->read = doc_read;
 	mtd->write = doc_write;
-	mtd->read_ecc = doc_read_ecc;
-	mtd->write_ecc = doc_write_ecc;
 	mtd->read_oob = doc_read_oob;
 	mtd->write_oob = doc_write_oob;
 	mtd->sync = NULL;
@@ -524,6 +515,7 @@
 		return;
 	}
 }
+EXPORT_SYMBOL_GPL(DoCMilPlus_init);
 
 #if 0
 static int doc_dumpblk(struct mtd_info *mtd, loff_t from)
@@ -876,14 +868,20 @@
 	return ret;
 }
 
-static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			size_t *retlen, u_char *buf)
+static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
+			struct mtd_oob_ops *ops)
 {
 	loff_t fofs, base;
 	struct DiskOnChip *this = mtd->priv;
 	void __iomem * docptr = this->virtadr;
 	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
 	size_t i, size, got, want;
+	uint8_t *buf = ops->oobbuf;
+	size_t len = ops->len;
+
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+	ofs += ops->ooboffs;
 
 	DoC_CheckASIC(docptr);
 
@@ -949,12 +947,12 @@
 	/* Disable flash internally */
 	WriteDOC(0, docptr, Mplus_FlashSelect);
 
-	*retlen = len;
+	ops->retlen = len;
 	return 0;
 }
 
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			 size_t *retlen, const u_char *buf)
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+			 struct mtd_oob_ops *ops)
 {
 	volatile char dummy;
 	loff_t fofs, base;
@@ -963,6 +961,12 @@
 	struct Nand *mychip = &this->chips[ofs >> this->chipshift];
 	size_t i, size, got, want;
 	int ret = 0;
+	uint8_t *buf = ops->oobbuf;
+	size_t len = ops->len;
+
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+	ofs += ops->ooboffs;
 
 	DoC_CheckASIC(docptr);
 
@@ -1038,7 +1042,7 @@
 			printk("MTD: Error 0x%x programming oob at 0x%x\n",
 				dummy, (int)ofs);
 			/* FIXME: implement Bad Block Replacement */
-			*retlen = 0;
+			ops->retlen = 0;
 			ret = -EIO;
 		}
 		dummy = ReadDOC(docptr, Mplus_LastDataRead);
@@ -1051,7 +1055,7 @@
 	/* Disable flash internally */
 	WriteDOC(0, docptr, Mplus_FlashSelect);
 
-	*retlen = len;
+	ops->retlen = len;
 	return ret;
 }
 
@@ -1122,12 +1126,6 @@
  *
  ****************************************************************************/
 
-static int __init init_doc2001plus(void)
-{
-	inter_module_register(im_name, THIS_MODULE, &DoCMilPlus_init);
-	return 0;
-}
-
 static void __exit cleanup_doc2001plus(void)
 {
 	struct mtd_info *mtd;
@@ -1143,11 +1141,9 @@
 		kfree(this->chips);
 		kfree(mtd);
 	}
-	inter_module_unregister(im_name);
 }
 
 module_exit(cleanup_doc2001plus);
-module_init(init_doc2001plus);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com> et al.");
diff --git a/drivers/mtd/devices/docprobe.c b/drivers/mtd/devices/docprobe.c
index 13178b9..593bb03 100644
--- a/drivers/mtd/devices/docprobe.c
+++ b/drivers/mtd/devices/docprobe.c
@@ -231,6 +231,10 @@
 
 static int docfound;
 
+extern void DoC2k_init(struct mtd_info *);
+extern void DoCMil_init(struct mtd_info *);
+extern void DoCMilPlus_init(struct mtd_info *);
+
 static void __init DoC_Probe(unsigned long physadr)
 {
 	void __iomem *docptr;
@@ -239,8 +243,6 @@
 	int ChipID;
 	char namebuf[15];
 	char *name = namebuf;
-	char *im_funcname = NULL;
-	char *im_modname = NULL;
 	void (*initroutine)(struct mtd_info *) = NULL;
 
 	docptr = ioremap(physadr, DOC_IOREMAP_LEN);
@@ -278,41 +280,33 @@
 		switch(ChipID) {
 		case DOC_ChipID_Doc2kTSOP:
 			name="2000 TSOP";
-			im_funcname = "DoC2k_init";
-			im_modname = "doc2000";
+			initroutine = symbol_request(DoC2k_init);
 			break;
 
 		case DOC_ChipID_Doc2k:
 			name="2000";
-			im_funcname = "DoC2k_init";
-			im_modname = "doc2000";
+			initroutine = symbol_request(DoC2k_init);
 			break;
 
 		case DOC_ChipID_DocMil:
 			name="Millennium";
 #ifdef DOC_SINGLE_DRIVER
-			im_funcname = "DoC2k_init";
-			im_modname = "doc2000";
+			initroutine = symbol_request(DoC2k_init);
 #else
-			im_funcname = "DoCMil_init";
-			im_modname = "doc2001";
+			initroutine = symbol_request(DoCMil_init);
 #endif /* DOC_SINGLE_DRIVER */
 			break;
 
 		case DOC_ChipID_DocMilPlus16:
 		case DOC_ChipID_DocMilPlus32:
 			name="MillenniumPlus";
-			im_funcname = "DoCMilPlus_init";
-			im_modname = "doc2001plus";
+			initroutine = symbol_request(DoCMilPlus_init);
 			break;
 		}
 
-		if (im_funcname)
-			initroutine = inter_module_get_request(im_funcname, im_modname);
-
 		if (initroutine) {
 			(*initroutine)(mtd);
-			inter_module_put(im_funcname);
+			symbol_put_addr(initroutine);
 			return;
 		}
 		printk(KERN_NOTICE "Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr);
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 29b0dda..4ea50a1 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -635,6 +635,7 @@
    printk ("%s: This looks like a LART board to me.\n",module_name);
    mtd.name = module_name;
    mtd.type = MTD_NORFLASH;
+   mtd.writesize = 1;
    mtd.flags = MTD_CAP_NORFLASH;
    mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
    mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 04e65d5..a846614 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -465,6 +465,7 @@
 		flash->mtd.name = spi->dev.bus_id;
 
 	flash->mtd.type = MTD_NORFLASH;
+	flash->mtd.writesize = 1;
 	flash->mtd.flags = MTD_CAP_NORFLASH;
 	flash->mtd.size = info->sector_size * info->n_sectors;
 	flash->mtd.erasesize = info->sector_size;
diff --git a/drivers/mtd/devices/ms02-nv.c b/drivers/mtd/devices/ms02-nv.c
index 485f663..08dfb89 100644
--- a/drivers/mtd/devices/ms02-nv.c
+++ b/drivers/mtd/devices/ms02-nv.c
@@ -219,12 +219,13 @@
 	mp->uaddr = phys_to_virt(fixaddr);
 
 	mtd->type = MTD_RAM;
-	mtd->flags = MTD_CAP_RAM | MTD_XIP;
+	mtd->flags = MTD_CAP_RAM;
 	mtd->size = fixsize;
 	mtd->name = (char *)ms02nv_name;
 	mtd->owner = THIS_MODULE;
 	mtd->read = ms02nv_read;
 	mtd->write = ms02nv_write;
+	mtd->writesize = 1;
 
 	ret = -EIO;
 	if (add_mtd_device(mtd)) {
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index a19480d..04271d0 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -478,6 +478,7 @@
 	device->name = (pdata && pdata->name) ? pdata->name : priv->name;
 	device->size = nr_pages * pagesize;
 	device->erasesize = pagesize;
+	device->writesize = pagesize;
 	device->owner = THIS_MODULE;
 	device->type = MTD_DATAFLASH;
 	device->flags = MTD_CAP_NORFLASH;
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c
index 1443117..b4438ea 100644
--- a/drivers/mtd/devices/mtdram.c
+++ b/drivers/mtd/devices/mtdram.c
@@ -106,6 +106,7 @@
 	mtd->type = MTD_RAM;
 	mtd->flags = MTD_CAP_RAM;
 	mtd->size = size;
+	mtd->writesize = 1;
 	mtd->erasesize = MTDRAM_ERASE_SIZE;
 	mtd->priv = mapped_address;
 
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c
index e8685ee..6c7337f 100644
--- a/drivers/mtd/devices/phram.c
+++ b/drivers/mtd/devices/phram.c
@@ -1,8 +1,8 @@
 /**
  * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $
  *
- * Copyright (c) ????		Jochen Schäuble <psionic@psionic.de>
- * Copyright (c) 2003-2004	Jörn Engel <joern@wh.fh-wedel.de>
+ * Copyright (c) ????		Jochen Schäuble <psionic@psionic.de>
+ * Copyright (c) 2003-2004	Jörn Engel <joern@wh.fh-wedel.de>
  *
  * Usage:
  *
@@ -142,7 +142,7 @@
 
 	new->mtd.name = name;
 	new->mtd.size = len;
-	new->mtd.flags = MTD_CAP_RAM | MTD_ERASEABLE | MTD_VOLATILE;
+	new->mtd.flags = MTD_CAP_RAM;
         new->mtd.erase = phram_erase;
 	new->mtd.point = phram_point;
 	new->mtd.unpoint = phram_unpoint;
@@ -151,6 +151,7 @@
 	new->mtd.owner = THIS_MODULE;
 	new->mtd.type = MTD_RAM;
 	new->mtd.erasesize = PAGE_SIZE;
+	new->mtd.writesize = 1;
 
 	ret = -EAGAIN;
 	if (add_mtd_device(&new->mtd)) {
@@ -266,12 +267,16 @@
 		return 0;
 
 	ret = parse_num32(&start, token[1]);
-	if (ret)
+	if (ret) {
+		kfree(name);
 		parse_err("illegal start address\n");
+	}
 
 	ret = parse_num32(&len, token[2]);
-	if (ret)
+	if (ret) {
+		kfree(name);
 		parse_err("illegal device length\n");
+	}
 
 	register_device(name, start, len);
 
@@ -296,5 +301,5 @@
 module_exit(cleanup_phram);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>");
+MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>");
 MODULE_DESCRIPTION("MTD driver for physical RAM");
diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c
index 666cce1..f620d74 100644
--- a/drivers/mtd/devices/pmc551.c
+++ b/drivers/mtd/devices/pmc551.c
@@ -778,7 +778,8 @@
                 mtd->type 	= MTD_RAM;
                 mtd->name 	= "PMC551 RAM board";
                 mtd->erasesize 	= 0x10000;
-		mtd->owner = THIS_MODULE;
+                mtd->writesize  = 1;
+                mtd->owner = THIS_MODULE;
 
                 if (add_mtd_device(mtd)) {
                         printk(KERN_NOTICE "pmc551: Failed to register new device\n");
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index 6faee6c..542a0c0 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -200,8 +200,7 @@
 
 	(*curmtd)->mtdinfo->name = name;
 	(*curmtd)->mtdinfo->size = length;
-	(*curmtd)->mtdinfo->flags = MTD_CLEAR_BITS | MTD_SET_BITS |
-					MTD_WRITEB_WRITEABLE | MTD_VOLATILE | MTD_CAP_RAM;
+	(*curmtd)->mtdinfo->flags = MTD_CAP_RAM;
         (*curmtd)->mtdinfo->erase = slram_erase;
 	(*curmtd)->mtdinfo->point = slram_point;
 	(*curmtd)->mtdinfo->unpoint = slram_unpoint;
@@ -210,6 +209,7 @@
 	(*curmtd)->mtdinfo->owner = THIS_MODULE;
 	(*curmtd)->mtdinfo->type = MTD_RAM;
 	(*curmtd)->mtdinfo->erasesize = SLRAM_BLK_SZ;
+	(*curmtd)->mtdinfo->writesize = 1;
 
 	if (add_mtd_device((*curmtd)->mtdinfo))	{
 		E("slram: Failed to register new device\n");
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index a3b9247..1e21a2c 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -36,6 +36,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nftl.h>
 #include <linux/mtd/inftl.h>
+#include <linux/mtd/nand.h>
 #include <asm/uaccess.h>
 #include <asm/errno.h>
 #include <asm/io.h>
@@ -79,14 +80,12 @@
 	inftl->mbd.devnum = -1;
 	inftl->mbd.blksize = 512;
 	inftl->mbd.tr = tr;
-	memcpy(&inftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
-	inftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
 
-        if (INFTL_mount(inftl) < 0) {
+	if (INFTL_mount(inftl) < 0) {
 		printk(KERN_WARNING "INFTL: could not mount device\n");
 		kfree(inftl);
 		return;
-        }
+	}
 
 	/* OK, it's a new one. Set up all the data structures. */
 
@@ -152,6 +151,69 @@
  */
 
 /*
+ * Read oob data from flash
+ */
+int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+		   size_t *retlen, uint8_t *buf)
+{
+	struct mtd_oob_ops ops;
+	int res;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooboffs = offs & (mtd->writesize - 1);
+	ops.ooblen = len;
+	ops.oobbuf = buf;
+	ops.datbuf = NULL;
+	ops.len = len;
+
+	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	*retlen = ops.retlen;
+	return res;
+}
+
+/*
+ * Write oob data to flash
+ */
+int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+		    size_t *retlen, uint8_t *buf)
+{
+	struct mtd_oob_ops ops;
+	int res;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooboffs = offs & (mtd->writesize - 1);
+	ops.ooblen = len;
+	ops.oobbuf = buf;
+	ops.datbuf = NULL;
+	ops.len = len;
+
+	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	*retlen = ops.retlen;
+	return res;
+}
+
+/*
+ * Write data and oob to flash
+ */
+static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
+		       size_t *retlen, uint8_t *buf, uint8_t *oob)
+{
+	struct mtd_oob_ops ops;
+	int res;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooboffs = offs;
+	ops.ooblen = mtd->oobsize;
+	ops.oobbuf = oob;
+	ops.datbuf = buf;
+	ops.len = len;
+
+	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	*retlen = ops.retlen;
+	return res;
+}
+
+/*
  * INFTL_findfreeblock: Find a free Erase Unit on the INFTL partition.
  *	This function is used when the give Virtual Unit Chain.
  */
@@ -198,10 +260,11 @@
 	u16 BlockMap[MAX_SECTORS_PER_UNIT];
 	unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT];
 	unsigned int thisEUN, prevEUN, status;
+	struct mtd_info *mtd = inftl->mbd.mtd;
 	int block, silly;
 	unsigned int targetEUN;
 	struct inftl_oob oob;
-        size_t retlen;
+	size_t retlen;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
 		"pending=%d)\n", inftl, thisVUC, pendingblock);
@@ -221,18 +284,18 @@
 	 * Scan to find the Erase Unit which holds the actual data for each
 	 * 512-byte block within the Chain.
 	 */
-        silly = MAX_LOOPS;
+	silly = MAX_LOOPS;
 	while (thisEUN < inftl->nb_blocks) {
 		for (block = 0; block < inftl->EraseSize/SECTORSIZE; block ++) {
 			if ((BlockMap[block] != 0xffff) || BlockDeleted[block])
 				continue;
 
-			if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize)
-			     + (block * SECTORSIZE), 16 , &retlen,
-			     (char *)&oob) < 0)
+			if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
+					   + (block * SECTORSIZE), 16, &retlen,
+					   (char *)&oob) < 0)
 				status = SECTOR_IGNORE;
 			else
-                        	status = oob.b.Status | oob.b.Status1;
+				status = oob.b.Status | oob.b.Status1;
 
 			switch(status) {
 			case SECTOR_FREE:
@@ -282,29 +345,31 @@
 			continue;
 		}
 
-                /*
+		/*
 		 * Copy only in non free block (free blocks can only
                  * happen in case of media errors or deleted blocks).
 		 */
-                if (BlockMap[block] == BLOCK_NIL)
-                        continue;
+		if (BlockMap[block] == BLOCK_NIL)
+			continue;
 
-                ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
-			BlockMap[block]) + (block * SECTORSIZE), SECTORSIZE,
-			&retlen, movebuf);
-                if (ret < 0) {
-			ret = MTD_READ(inftl->mbd.mtd, (inftl->EraseSize *
-				BlockMap[block]) + (block * SECTORSIZE),
-				SECTORSIZE, &retlen, movebuf);
+		ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) +
+				(block * SECTORSIZE), SECTORSIZE, &retlen,
+				movebuf);
+		if (ret < 0 && ret != -EUCLEAN) {
+			ret = mtd->read(mtd,
+					(inftl->EraseSize * BlockMap[block]) +
+					(block * SECTORSIZE), SECTORSIZE,
+					&retlen, movebuf);
 			if (ret != -EIO)
-                        	DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
-					"away on retry?\n");
-                }
-                memset(&oob, 0xff, sizeof(struct inftl_oob));
-                oob.b.Status = oob.b.Status1 = SECTOR_USED;
-                MTD_WRITEECC(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
-			(block * SECTORSIZE), SECTORSIZE, &retlen,
-			movebuf, (char *)&oob, &inftl->oobinfo);
+				DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
+				      "away on retry?\n");
+		}
+		memset(&oob, 0xff, sizeof(struct inftl_oob));
+		oob.b.Status = oob.b.Status1 = SECTOR_USED;
+
+		inftl_write(inftl->mbd.mtd, (inftl->EraseSize * targetEUN) +
+			    (block * SECTORSIZE), SECTORSIZE, &retlen,
+			    movebuf, (char *)&oob);
 	}
 
 	/*
@@ -329,17 +394,17 @@
 		if (thisEUN == targetEUN)
 			break;
 
-                if (INFTL_formatblock(inftl, thisEUN) < 0) {
+		if (INFTL_formatblock(inftl, thisEUN) < 0) {
 			/*
 			 * Could not erase : mark block as reserved.
 			 */
 			inftl->PUtable[thisEUN] = BLOCK_RESERVED;
-                } else {
+		} else {
 			/* Correctly erased : mark it as free */
 			inftl->PUtable[thisEUN] = BLOCK_FREE;
 			inftl->PUtable[prevEUN] = BLOCK_NIL;
 			inftl->numfreeEUNs++;
-                }
+		}
 	}
 
 	return targetEUN;
@@ -415,6 +480,7 @@
 	unsigned int thisVUC = block / (inftl->EraseSize / SECTORSIZE);
 	unsigned int thisEUN, writeEUN, prev_block, status;
 	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize -1);
+	struct mtd_info *mtd = inftl->mbd.mtd;
 	struct inftl_oob oob;
 	struct inftl_bci bci;
 	unsigned char anac, nacs, parity;
@@ -434,10 +500,10 @@
 		silly = MAX_LOOPS;
 
 		while (thisEUN <= inftl->lastEUN) {
-			MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
-				blockofs, 8, &retlen, (char *)&bci);
+			inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
+				       blockofs, 8, &retlen, (char *)&bci);
 
-                        status = bci.Status | bci.Status1;
+			status = bci.Status | bci.Status1;
 			DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
 				"EUN %d is %x\n", block , writeEUN, status);
 
@@ -522,8 +588,8 @@
 		nacs = 0;
 		thisEUN = inftl->VUtable[thisVUC];
 		if (thisEUN != BLOCK_NIL) {
-			MTD_READOOB(inftl->mbd.mtd, thisEUN * inftl->EraseSize
-				+ 8, 8, &retlen, (char *)&oob.u);
+			inftl_read_oob(mtd, thisEUN * inftl->EraseSize
+				       + 8, 8, &retlen, (char *)&oob.u);
 			anac = oob.u.a.ANAC + 1;
 			nacs = oob.u.a.NACs + 1;
 		}
@@ -544,8 +610,8 @@
 		oob.u.a.parityPerField = parity;
 		oob.u.a.discarded = 0xaa;
 
-		MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize + 8, 8,
-			&retlen, (char *)&oob.u);
+		inftl_write_oob(mtd, writeEUN * inftl->EraseSize + 8, 8,
+				&retlen, (char *)&oob.u);
 
 		/* Also back up header... */
 		oob.u.b.virtualUnitNo = cpu_to_le16(thisVUC);
@@ -555,8 +621,8 @@
 		oob.u.b.parityPerField = parity;
 		oob.u.b.discarded = 0xaa;
 
-		MTD_WRITEOOB(inftl->mbd.mtd, writeEUN * inftl->EraseSize +
-			SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
+		inftl_write_oob(mtd, writeEUN * inftl->EraseSize +
+				SECTORSIZE * 4 + 8, 8, &retlen, (char *)&oob.u);
 
 		inftl->PUtable[writeEUN] = inftl->VUtable[thisVUC];
 		inftl->VUtable[thisVUC] = writeEUN;
@@ -576,6 +642,7 @@
  */
 static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 {
+	struct mtd_info *mtd = inftl->mbd.mtd;
 	unsigned char BlockUsed[MAX_SECTORS_PER_UNIT];
 	unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT];
 	unsigned int thisEUN, status;
@@ -606,9 +673,9 @@
 			if (BlockUsed[block] || BlockDeleted[block])
 				continue;
 
-			if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize)
-			    + (block * SECTORSIZE), 8 , &retlen,
-			    (char *)&bci) < 0)
+			if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize)
+					   + (block * SECTORSIZE), 8 , &retlen,
+					  (char *)&bci) < 0)
 				status = SECTOR_IGNORE;
 			else
 				status = bci.Status | bci.Status1;
@@ -670,12 +737,12 @@
 		DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
 		      thisEUN, thisVUC);
 
-                if (INFTL_formatblock(inftl, thisEUN) < 0) {
+		if (INFTL_formatblock(inftl, thisEUN) < 0) {
 			/*
 			 * Could not erase : mark block as reserved.
 			 */
 			inftl->PUtable[thisEUN] = BLOCK_RESERVED;
-                } else {
+		} else {
 			/* Correctly erased : mark it as free */
 			inftl->PUtable[thisEUN] = BLOCK_FREE;
 			inftl->numfreeEUNs++;
@@ -697,6 +764,7 @@
 {
 	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
 	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
+	struct mtd_info *mtd = inftl->mbd.mtd;
 	unsigned int status;
 	int silly = MAX_LOOPS;
 	size_t retlen;
@@ -706,8 +774,8 @@
 		"block=%d)\n", inftl, block);
 
 	while (thisEUN < inftl->nb_blocks) {
-		if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
-		    blockofs, 8, &retlen, (char *)&bci) < 0)
+		if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
+				   blockofs, 8, &retlen, (char *)&bci) < 0)
 			status = SECTOR_IGNORE;
 		else
 			status = bci.Status | bci.Status1;
@@ -741,10 +809,10 @@
 	if (thisEUN != BLOCK_NIL) {
 		loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
 
-		if (MTD_READOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0)
+		if (inftl_read_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
 			return -EIO;
 		bci.Status = bci.Status1 = SECTOR_DELETED;
-		if (MTD_WRITEOOB(inftl->mbd.mtd, ptr, 8, &retlen, (char *)&bci) < 0)
+		if (inftl_write_oob(mtd, ptr, 8, &retlen, (char *)&bci) < 0)
 			return -EIO;
 		INFTL_trydeletechain(inftl, block / (inftl->EraseSize / SECTORSIZE));
 	}
@@ -784,9 +852,10 @@
 
 		memset(&oob, 0xff, sizeof(struct inftl_oob));
 		oob.b.Status = oob.b.Status1 = SECTOR_USED;
-		MTD_WRITEECC(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
-			blockofs, SECTORSIZE, &retlen, (char *)buffer,
-			(char *)&oob, &inftl->oobinfo);
+
+		inftl_write(inftl->mbd.mtd, (writeEUN * inftl->EraseSize) +
+			    blockofs, SECTORSIZE, &retlen, (char *)buffer,
+			    (char *)&oob);
 		/*
 		 * need to write SECTOR_USED flags since they are not written
 		 * in mtd_writeecc
@@ -804,17 +873,18 @@
 	struct INFTLrecord *inftl = (void *)mbd;
 	unsigned int thisEUN = inftl->VUtable[block / (inftl->EraseSize / SECTORSIZE)];
 	unsigned long blockofs = (block * SECTORSIZE) & (inftl->EraseSize - 1);
-        unsigned int status;
+	struct mtd_info *mtd = inftl->mbd.mtd;
+	unsigned int status;
 	int silly = MAX_LOOPS;
-        struct inftl_bci bci;
+	struct inftl_bci bci;
 	size_t retlen;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
 		"buffer=%p)\n", inftl, block, buffer);
 
 	while (thisEUN < inftl->nb_blocks) {
-		if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
-		     blockofs, 8, &retlen, (char *)&bci) < 0)
+		if (inftl_read_oob(mtd, (thisEUN * inftl->EraseSize) +
+				  blockofs, 8, &retlen, (char *)&bci) < 0)
 			status = SECTOR_IGNORE;
 		else
 			status = bci.Status | bci.Status1;
@@ -850,10 +920,12 @@
 		/* The requested block is not on the media, return all 0x00 */
 		memset(buffer, 0, SECTORSIZE);
 	} else {
-        	size_t retlen;
+		size_t retlen;
 		loff_t ptr = (thisEUN * inftl->EraseSize) + blockofs;
-		if (MTD_READ(inftl->mbd.mtd, ptr, SECTORSIZE, &retlen,
-		    buffer))
+		int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
+
+		/* Handle corrected bit flips gracefully */
+		if (ret < 0 && ret != -EUCLEAN)
 			return -EIO;
 	}
 	return 0;
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index 43fdc94..8f6006f 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -43,6 +43,11 @@
 
 char inftlmountrev[]="$Revision: 1.18 $";
 
+extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+			  size_t *retlen, uint8_t *buf);
+extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+			   size_t *retlen, uint8_t *buf);
+
 /*
  * find_boot_record: Find the INFTL Media Header and its Spare copy which
  *	contains the various device information of the INFTL partition and
@@ -57,6 +62,7 @@
 	unsigned int i, block;
 	u8 buf[SECTORSIZE];
 	struct INFTLMediaHeader *mh = &inftl->MediaHdr;
+	struct mtd_info *mtd = inftl->mbd.mtd;
 	struct INFTLPartition *ip;
 	size_t retlen;
 
@@ -80,8 +86,8 @@
 		 * Check for BNAND header first. Then whinge if it's found
 		 * but later checks fail.
 		 */
-		ret = MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize,
-		    SECTORSIZE, &retlen, buf);
+		ret = mtd->read(mtd, block * inftl->EraseSize,
+				SECTORSIZE, &retlen, buf);
 		/* We ignore ret in case the ECC of the MediaHeader is invalid
 		   (which is apparently acceptable) */
 		if (retlen != SECTORSIZE) {
@@ -106,8 +112,9 @@
 		}
 
 		/* To be safer with BIOS, also use erase mark as discriminant */
-		if ((ret = MTD_READOOB(inftl->mbd.mtd, block * inftl->EraseSize +
-		    SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0)) {
+		if ((ret = inftl_read_oob(mtd, block * inftl->EraseSize +
+					  SECTORSIZE + 8, 8, &retlen,
+					  (char *)&h1) < 0)) {
 			printk(KERN_WARNING "INFTL: ANAND header found at "
 				"0x%x in mtd%d, but OOB data read failed "
 				"(err %d)\n", block * inftl->EraseSize,
@@ -123,8 +130,8 @@
 		memcpy(mh, buf, sizeof(struct INFTLMediaHeader));
 
 		/* Read the spare media header at offset 4096 */
-		MTD_READ(inftl->mbd.mtd, block * inftl->EraseSize + 4096,
-		    SECTORSIZE, &retlen, buf);
+		mtd->read(mtd, block * inftl->EraseSize + 4096,
+			  SECTORSIZE, &retlen, buf);
 		if (retlen != SECTORSIZE) {
 			printk(KERN_WARNING "INFTL: Unable to read spare "
 			       "Media Header\n");
@@ -233,7 +240,7 @@
 				 */
 				instr->addr = ip->Reserved0 * inftl->EraseSize;
 				instr->len = inftl->EraseSize;
-				MTD_ERASE(inftl->mbd.mtd, instr);
+				mtd->erase(mtd, instr);
 			}
 			if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) {
 				printk(KERN_WARNING "INFTL: Media Header "
@@ -350,21 +357,21 @@
 	int len, int check_oob)
 {
 	u8 buf[SECTORSIZE + inftl->mbd.mtd->oobsize];
+	struct mtd_info *mtd = inftl->mbd.mtd;
 	size_t retlen;
 	int i;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=%p,"
-		"address=0x%x,len=%d,check_oob=%d)\n", inftl,
-		address, len, check_oob);
-
 	for (i = 0; i < len; i += SECTORSIZE) {
-		if (MTD_READECC(inftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &inftl->oobinfo) < 0)
+		if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
 			return -1;
 		if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
 			return -1;
 
 		if (check_oob) {
-			if (memcmpb(buf + SECTORSIZE, 0xff, inftl->mbd.mtd->oobsize) != 0)
+			if(inftl_read_oob(mtd, address, mtd->oobsize,
+					  &retlen, &buf[SECTORSIZE]) < 0)
+				return -1;
+			if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
 				return -1;
 		}
 		address += SECTORSIZE;
@@ -387,6 +394,7 @@
 	size_t retlen;
 	struct inftl_unittail uci;
 	struct erase_info *instr = &inftl->instr;
+	struct mtd_info *mtd = inftl->mbd.mtd;
 	int physblock;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
@@ -404,8 +412,9 @@
 	/* Erase one physical eraseblock at a time, even though the NAND api
 	   allows us to group them.  This way we if we have a failure, we can
 	   mark only the failed block in the bbt. */
-	for (physblock = 0; physblock < inftl->EraseSize; physblock += instr->len, instr->addr += instr->len) {
-		MTD_ERASE(inftl->mbd.mtd, instr);
+	for (physblock = 0; physblock < inftl->EraseSize;
+	     physblock += instr->len, instr->addr += instr->len) {
+		mtd->erase(inftl->mbd.mtd, instr);
 
 		if (instr->state == MTD_ERASE_FAILED) {
 			printk(KERN_WARNING "INFTL: error while formatting block %d\n",
@@ -414,10 +423,10 @@
 		}
 
 		/*
-	 	* Check the "freeness" of Erase Unit before updating metadata.
-	 	* FixMe: is this check really necessary? Since we have check the
-	 	*        return code after the erase operation.
-	 	*/
+		 * Check the "freeness" of Erase Unit before updating metadata.
+		 * FixMe: is this check really necessary? Since we have check
+		 * the return code after the erase operation.
+		 */
 		if (check_free_sectors(inftl, instr->addr, instr->len, 1) != 0)
 			goto fail;
 	}
@@ -429,8 +438,7 @@
 	uci.Reserved[2] = 0;
 	uci.Reserved[3] = 0;
 	instr->addr = block * inftl->EraseSize + SECTORSIZE * 2;
-	if (MTD_WRITEOOB(inftl->mbd.mtd, instr->addr +
-	    8, 8, &retlen, (char *)&uci) < 0)
+	if (inftl_write_oob(mtd, instr->addr + 8, 8, &retlen, (char *)&uci) < 0)
 		goto fail;
 	return 0;
 fail:
@@ -549,6 +557,7 @@
 
 int INFTL_mount(struct INFTLrecord *s)
 {
+	struct mtd_info *mtd = s->mbd.mtd;
 	unsigned int block, first_block, prev_block, last_block;
 	unsigned int first_logical_block, logical_block, erase_mark;
 	int chain_length, do_format_chain;
@@ -607,10 +616,11 @@
 				break;
 			}
 
-			if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8,
-			    8, &retlen, (char *)&h0) < 0 ||
-			    MTD_READOOB(s->mbd.mtd, block * s->EraseSize +
-			    2 * SECTORSIZE + 8, 8, &retlen, (char *)&h1) < 0) {
+			if (inftl_read_oob(mtd, block * s->EraseSize + 8,
+					   8, &retlen, (char *)&h0) < 0 ||
+			    inftl_read_oob(mtd, block * s->EraseSize +
+					   2 * SECTORSIZE + 8, 8, &retlen,
+					   (char *)&h1) < 0) {
 				/* Should never happen? */
 				do_format_chain++;
 				break;
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 7abd7fe..83d0b2a 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -37,7 +37,7 @@
 config MTD_PHYSMAP_LEN
 	hex "Physical length of flash mapping"
 	depends on MTD_PHYSMAP
-	default "0x4000000"
+	default "0"
 	help
 	  This is the total length of the mapping of the flash chips on
 	  your particular board. If there is space, or aliases, in the
@@ -78,7 +78,7 @@
 
 config MTD_SC520CDP
 	tristate "CFI Flash device mapped on AMD SC520 CDP"
-	depends on X86 && MTD_CFI
+	depends on X86 && MTD_CFI && MTD_CONCAT
 	help
 	  The SC520 CDP board has two banks of CFI-compliant chips and one
 	  Dual-in-line JEDEC chip. This 'mapping' driver supports that
@@ -109,7 +109,7 @@
 	  mtd1 allows you to reprogram your BIOS. BE VERY CAREFUL.
 
 	  Note that jumper 3 ("Write Enable Drive A") must be set
-	  otherwise detection won't succeeed.
+	  otherwise detection won't succeed.
 
 config MTD_SBC_GXX
 	tristate "CFI Flash device mapped on Arcom SBC-GXx boards"
@@ -200,8 +200,8 @@
 	  Support for the flash chip on Tsunami TIG bus.
 
 config MTD_LASAT
-	tristate "Flash chips on LASAT board"
-	depends on LASAT
+	tristate "LASAT flash device"
+	depends on LASAT && MTD_CFI
 	help
 	  Support for the flash chips on the Lasat 100 and 200 boards.
 
@@ -212,7 +212,7 @@
 	  Support for flash chips on NETtel/SecureEdge/SnapGear boards.
 
 config MTD_ALCHEMY
-	tristate '  AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support'
+	tristate "AMD Alchemy Pb1xxx/Db1xxx/RDK MTD support"
 	depends on SOC_AU1X00
 	help
 	  Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards
@@ -561,7 +561,6 @@
 config MTD_PCMCIA_ANONYMOUS
 	bool "Use PCMCIA MTD drivers for anonymous PCMCIA cards"
 	depends on MTD_PCMCIA
-	default N
 	help
 	  If this option is enabled, PCMCIA cards which do not report
 	  anything about themselves are assumed to be MTD cards.
diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c
index fd0f0d3..92b5d88 100644
--- a/drivers/mtd/maps/cfi_flagadm.c
+++ b/drivers/mtd/maps/cfi_flagadm.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson <kd@flaga.is>
+ *  Copyright © 2001 Flaga hf. Medical Devices, Kári Davíðsson <kd@flaga.is>
  *
  *  $Id: cfi_flagadm.c,v 1.15 2005/11/07 11:14:26 gleixner Exp $
  *
@@ -135,5 +135,5 @@
 
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>");
+MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>");
 MODULE_DESCRIPTION("MTD map driver for Flaga digital module");
diff --git a/drivers/mtd/maps/dbox2-flash.c b/drivers/mtd/maps/dbox2-flash.c
index 652813c..85c2a9e 100644
--- a/drivers/mtd/maps/dbox2-flash.c
+++ b/drivers/mtd/maps/dbox2-flash.c
@@ -122,5 +122,5 @@
 
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>, Bastian Blank <waldi@tuxbox.org>, Alexander Wild <wild@te-elektronik.com>");
+MODULE_AUTHOR("Kári Davíðsson <kd@flaga.is>, Bastian Blank <waldi@tuxbox.org>, Alexander Wild <wild@te-elektronik.com>");
 MODULE_DESCRIPTION("MTD map driver for D-Box 2 board");
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index 2c9cc7f..c26488a 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -42,7 +42,6 @@
 	struct		map_info map;
 	struct		mtd_partition *partitions;
 	struct		resource *res;
-	int		nr_banks;
 };
 
 static inline unsigned long flash_bank_setup(struct map_info *map, unsigned long ofs)
@@ -183,7 +182,6 @@
 	 */
 	info->map.phys = NO_XIP;
 
-	info->nr_banks = ixp_data->nr_banks;
 	info->map.size = ixp_data->nr_banks * window_size;
 	info->map.bankwidth = 1;
 
diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c
index d1e66e1..5c25d4e 100644
--- a/drivers/mtd/maps/mtx-1_flash.c
+++ b/drivers/mtd/maps/mtx-1_flash.c
@@ -4,7 +4,7 @@
  * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $
  *
  * (C) 2005 Bruno Randolf <bruno.randolf@4g-systems.biz>
- * (C) 2005 Jörn Engel <joern@wohnheim.fh-wedel.de>
+ * (C) 2005 Jörn Engel <joern@wohnheim.fh-wedel.de>
  *
  */
 
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c
index 54a3102..0994b5b 100644
--- a/drivers/mtd/maps/nettel.c
+++ b/drivers/mtd/maps/nettel.c
@@ -20,6 +20,8 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/cfi.h>
 #include <linux/reboot.h>
+#include <linux/kdev_t.h>
+#include <linux/root_dev.h>
 #include <asm/io.h>
 
 /****************************************************************************/
@@ -188,7 +190,7 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		add_wait_queue(&wait_q, &wait);
 
-		ret = MTD_ERASE(mtd, &nettel_erase);
+		ret = mtd->erase(mtd, &nettel_erase);
 		if (ret) {
 			set_current_state(TASK_RUNNING);
 			remove_wait_queue(&wait_q, &wait);
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c
index d27f412..c861134 100644
--- a/drivers/mtd/maps/pcmciamtd.c
+++ b/drivers/mtd/maps/pcmciamtd.c
@@ -713,6 +713,7 @@
 
 	if(dev->mtd_info) {
 		del_mtd_device(dev->mtd_info);
+		map_destroy(dev->mtd_info);
 		info("mtd%d: Removed", dev->mtd_info->index);
 	}
 
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index f49ebc3..d6301f0 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -14,113 +14,230 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <asm/io.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/config.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <asm/io.h>
 
-static struct mtd_info *mymtd;
-
-struct map_info physmap_map = {
-	.name = "phys_mapped_flash",
-	.phys = CONFIG_MTD_PHYSMAP_START,
-	.size = CONFIG_MTD_PHYSMAP_LEN,
-	.bankwidth = CONFIG_MTD_PHYSMAP_BANKWIDTH,
+struct physmap_flash_info {
+	struct mtd_info		*mtd;
+	struct map_info		map;
+	struct resource		*res;
+#ifdef CONFIG_MTD_PARTITIONS
+	int			nr_parts;
+	struct mtd_partition	*parts;
+#endif
 };
 
-#ifdef CONFIG_MTD_PARTITIONS
-static struct mtd_partition *mtd_parts;
-static int                   mtd_parts_nb;
 
-static int num_physmap_partitions;
-static struct mtd_partition *physmap_partitions;
-
-static const char *part_probes[] __initdata = {"cmdlinepart", "RedBoot", NULL};
-
-void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
+static int physmap_flash_remove(struct platform_device *dev)
 {
-	physmap_partitions=parts;
-	num_physmap_partitions=num_parts;
-}
-#endif /* CONFIG_MTD_PARTITIONS */
+	struct physmap_flash_info *info;
+	struct physmap_flash_data *physmap_data;
 
-static int __init init_physmap(void)
-{
-	static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
-	const char **type;
+	info = platform_get_drvdata(dev);
+	if (info == NULL)
+		return 0;
+	platform_set_drvdata(dev, NULL);
 
-       	printk(KERN_NOTICE "physmap flash device: %lx at %lx\n", physmap_map.size, physmap_map.phys);
-	physmap_map.virt = ioremap(physmap_map.phys, physmap_map.size);
+	physmap_data = dev->dev.platform_data;
 
-	if (!physmap_map.virt) {
-		printk("Failed to ioremap\n");
-		return -EIO;
-	}
-
-	simple_map_init(&physmap_map);
-
-	mymtd = NULL;
-	type = rom_probe_types;
-	for(; !mymtd && *type; type++) {
-		mymtd = do_map_probe(*type, &physmap_map);
-	}
-	if (mymtd) {
-		mymtd->owner = THIS_MODULE;
-
+	if (info->mtd != NULL) {
 #ifdef CONFIG_MTD_PARTITIONS
-		mtd_parts_nb = parse_mtd_partitions(mymtd, part_probes,
-						    &mtd_parts, 0);
-
-		if (mtd_parts_nb > 0)
-		{
-			add_mtd_partitions (mymtd, mtd_parts, mtd_parts_nb);
-			return 0;
+		if (info->nr_parts) {
+			del_mtd_partitions(info->mtd);
+			kfree(info->parts);
+		} else if (physmap_data->nr_parts) {
+			del_mtd_partitions(info->mtd);
+		} else {
+			del_mtd_device(info->mtd);
 		}
-
-		if (num_physmap_partitions != 0)
-		{
-			printk(KERN_NOTICE
-			       "Using physmap partition definition\n");
-			add_mtd_partitions (mymtd, physmap_partitions, num_physmap_partitions);
-			return 0;
-		}
-
+#else
+		del_mtd_device(info->mtd);
 #endif
-		add_mtd_device(mymtd);
+		map_destroy(info->mtd);
+	}
 
+	if (info->map.virt != NULL)
+		iounmap((void *)info->map.virt);
+
+	if (info->res != NULL) {
+		release_resource(info->res);
+		kfree(info->res);
+	}
+
+	return 0;
+}
+
+static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", NULL };
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
+#endif
+
+static int physmap_flash_probe(struct platform_device *dev)
+{
+	struct physmap_flash_data *physmap_data;
+	struct physmap_flash_info *info;
+	const char **probe_type;
+	int err;
+
+	physmap_data = dev->dev.platform_data;
+	if (physmap_data == NULL)
+		return -ENODEV;
+
+       	printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
+	    (unsigned long long)dev->resource->end - dev->resource->start + 1,
+	    (unsigned long long)dev->resource->start);
+
+	info = kmalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
+	if (info == NULL) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	memset(info, 0, sizeof(*info));
+
+	platform_set_drvdata(dev, info);
+
+	info->res = request_mem_region(dev->resource->start,
+			dev->resource->end - dev->resource->start + 1,
+			dev->dev.bus_id);
+	if (info->res == NULL) {
+		dev_err(&dev->dev, "Could not reserve memory region\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	info->map.name = dev->dev.bus_id;
+	info->map.phys = dev->resource->start;
+	info->map.size = dev->resource->end - dev->resource->start + 1;
+	info->map.bankwidth = physmap_data->width;
+	info->map.set_vpp = physmap_data->set_vpp;
+
+	info->map.virt = ioremap(info->map.phys, info->map.size);
+	if (info->map.virt == NULL) {
+		dev_err(&dev->dev, "Failed to ioremap flash region\n");
+		err = EIO;
+		goto err_out;
+	}
+
+	simple_map_init(&info->map);
+
+	probe_type = rom_probe_types;
+	for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
+		info->mtd = do_map_probe(*probe_type, &info->map);
+	if (info->mtd == NULL) {
+		dev_err(&dev->dev, "map_probe failed\n");
+		err = -ENXIO;
+		goto err_out;
+	}
+	info->mtd->owner = THIS_MODULE;
+
+#ifdef CONFIG_MTD_PARTITIONS
+	err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
+	if (err > 0) {
+		add_mtd_partitions(info->mtd, info->parts, err);
 		return 0;
 	}
 
-	iounmap(physmap_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_physmap(void)
-{
-#ifdef CONFIG_MTD_PARTITIONS
-	if (mtd_parts_nb) {
-		del_mtd_partitions(mymtd);
-		kfree(mtd_parts);
-	} else if (num_physmap_partitions) {
-		del_mtd_partitions(mymtd);
-	} else {
-		del_mtd_device(mymtd);
+	if (physmap_data->nr_parts) {
+		printk(KERN_NOTICE "Using physmap partition information\n");
+		add_mtd_partitions(info->mtd, physmap_data->parts,
+						physmap_data->nr_parts);
+		return 0;
 	}
-#else
-	del_mtd_device(mymtd);
 #endif
-	map_destroy(mymtd);
 
-	iounmap(physmap_map.virt);
-	physmap_map.virt = NULL;
+	add_mtd_device(info->mtd);
+	return 0;
+
+err_out:
+	physmap_flash_remove(dev);
+	return err;
 }
 
-module_init(init_physmap);
-module_exit(cleanup_physmap);
+static struct platform_driver physmap_flash_driver = {
+	.probe		= physmap_flash_probe,
+	.remove		= physmap_flash_remove,
+	.driver		= {
+		.name	= "physmap-flash",
+	},
+};
 
 
+#ifdef CONFIG_MTD_PHYSMAP_LEN
+#if CONFIG_MTD_PHYSMAP_LEN != 0
+#warning using PHYSMAP compat code
+#define PHYSMAP_COMPAT
+#endif
+#endif
+
+#ifdef PHYSMAP_COMPAT
+static struct physmap_flash_data physmap_flash_data = {
+	.width		= CONFIG_MTD_PHYSMAP_BANKWIDTH,
+};
+
+static struct resource physmap_flash_resource = {
+	.start		= CONFIG_MTD_PHYSMAP_START,
+	.end		= CONFIG_MTD_PHYSMAP_START + CONFIG_MTD_PHYSMAP_LEN - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device physmap_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &physmap_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &physmap_flash_resource,
+};
+
+void physmap_configure(unsigned long addr, unsigned long size,
+		int bankwidth, void (*set_vpp)(struct map_info *, int))
+{
+	physmap_flash_resource.start = addr;
+	physmap_flash_resource.end = addr + size - 1;
+	physmap_flash_data.width = bankwidth;
+	physmap_flash_data.set_vpp = set_vpp;
+}
+
+#ifdef CONFIG_MTD_PARTITIONS
+void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
+{
+	physmap_flash_data.nr_parts = num_parts;
+	physmap_flash_data.parts = parts;
+}
+#endif
+#endif
+
+static int __init physmap_init(void)
+{
+	int err;
+
+	err = platform_driver_register(&physmap_flash_driver);
+#ifdef PHYSMAP_COMPAT
+	if (err == 0)
+		platform_device_register(&physmap_flash);
+#endif
+
+	return err;
+}
+
+static void __exit physmap_exit(void)
+{
+#ifdef PHYSMAP_COMPAT
+	platform_device_unregister(&physmap_flash);
+#endif
+	platform_driver_unregister(&physmap_flash_driver);
+}
+
+module_init(physmap_init);
+module_exit(physmap_exit);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 MODULE_DESCRIPTION("Generic configurable MTD map driver");
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
index 0758cb1..24a0315 100644
--- a/drivers/mtd/maps/sun_uflash.c
+++ b/drivers/mtd/maps/sun_uflash.c
@@ -18,6 +18,7 @@
 #include <linux/ioport.h>
 #include <asm/ebus.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
@@ -30,146 +31,140 @@
 #define UFLASH_WINDOW_SIZE	0x200000
 #define UFLASH_BUSWIDTH		1			/* EBus is 8-bit */
 
-MODULE_AUTHOR
-	("Eric Brower <ebrower@usa.net>");
-MODULE_DESCRIPTION
-	("User-programmable flash device on Sun Microsystems boardsets");
-MODULE_SUPPORTED_DEVICE
-	("userflash");
-MODULE_LICENSE
-	("GPL");
+MODULE_AUTHOR("Eric Brower <ebrower@usa.net>");
+MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets");
+MODULE_SUPPORTED_DEVICE("userflash");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("2.0");
 
 static LIST_HEAD(device_list);
 struct uflash_dev {
-	char *			name;	/* device name */
+	char			*name;	/* device name */
 	struct map_info 	map;	/* mtd map info */
-	struct mtd_info *	mtd;	/* mtd info */
-	struct list_head	list;
+	struct mtd_info		*mtd;	/* mtd info */
 };
 
 
 struct map_info uflash_map_templ = {
-		.name =		"SUNW,???-????",
-		.size =		UFLASH_WINDOW_SIZE,
-		.bankwidth =	UFLASH_BUSWIDTH,
+	.name =		"SUNW,???-????",
+	.size =		UFLASH_WINDOW_SIZE,
+	.bankwidth =	UFLASH_BUSWIDTH,
 };
 
-int uflash_devinit(struct linux_ebus_device* edev)
+int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp)
 {
-	int iTmp, nregs;
-	struct linux_prom_registers regs[2];
-	struct uflash_dev *pdev;
+	struct uflash_dev *up;
+	struct resource *res;
 
-	iTmp = prom_getproperty(
-		edev->prom_node, "reg", (void *)regs, sizeof(regs));
-	if ((iTmp % sizeof(regs[0])) != 0) {
-		printk("%s: Strange reg property size %d\n",
-			UFLASH_DEVNAME, iTmp);
-		return -ENODEV;
-	}
+	res = &edev->resource[0];
 
-	nregs = iTmp / sizeof(regs[0]);
-
-	if (nregs != 1) {
+	if (edev->num_addrs != 1) {
 		/* Non-CFI userflash device-- once I find one we
 		 * can work on supporting it.
 		 */
 		printk("%s: unsupported device at 0x%lx (%d regs): " \
 			"email ebrower@usa.net\n",
-			UFLASH_DEVNAME, edev->resource[0].start, nregs);
+		       dp->full_name, res->start, edev->num_addrs);
+
 		return -ENODEV;
 	}
 
-	if(0 == (pdev = kmalloc(sizeof(struct uflash_dev), GFP_KERNEL))) {
-		printk("%s: unable to kmalloc new device\n", UFLASH_DEVNAME);
-		return(-ENOMEM);
-	}
+	up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL);
+	if (!up)
+		return -ENOMEM;
 
 	/* copy defaults and tweak parameters */
-	memcpy(&pdev->map, &uflash_map_templ, sizeof(uflash_map_templ));
-	pdev->map.size = regs[0].reg_size;
+	memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ));
+	up->map.size = (res->end - res->start) + 1UL;
 
-	iTmp = prom_getproplen(edev->prom_node, "model");
-	pdev->name = kmalloc(iTmp, GFP_KERNEL);
-	prom_getstring(edev->prom_node, "model", pdev->name, iTmp);
-	if(0 != pdev->name && 0 < strlen(pdev->name)) {
-		pdev->map.name = pdev->name;
-	}
-	pdev->map.phys = edev->resource[0].start;
-	pdev->map.virt = ioremap_nocache(edev->resource[0].start, pdev->map.size);
-	if(0 == pdev->map.virt) {
-		printk("%s: failed to map device\n", __FUNCTION__);
-		kfree(pdev->name);
-		kfree(pdev);
-		return(-1);
+	up->name = of_get_property(dp, "model", NULL);
+	if (up->name && 0 < strlen(up->name))
+		up->map.name = up->name;
+
+	up->map.phys = res->start;
+
+	up->map.virt = ioremap_nocache(res->start, up->map.size);
+	if (!up->map.virt) {
+		printk("%s: Failed to map device.\n", dp->full_name);
+		kfree(up);
+
+		return -EINVAL;
 	}
 
-	simple_map_init(&pdev->map);
+	simple_map_init(&up->map);
 
 	/* MTD registration */
-	pdev->mtd = do_map_probe("cfi_probe", &pdev->map);
-	if(0 == pdev->mtd) {
-		iounmap(pdev->map.virt);
-		kfree(pdev->name);
-		kfree(pdev);
-		return(-ENXIO);
+	up->mtd = do_map_probe("cfi_probe", &up->map);
+	if (!up->mtd) {
+		iounmap(up->map.virt);
+		kfree(up);
+
+		return -ENXIO;
 	}
 
-	list_add(&pdev->list, &device_list);
+	up->mtd->owner = THIS_MODULE;
 
-	pdev->mtd->owner = THIS_MODULE;
+	add_mtd_device(up->mtd);
 
-	add_mtd_device(pdev->mtd);
-	return(0);
+	dev_set_drvdata(&edev->ofdev.dev, up);
+
+	return 0;
 }
 
+static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct linux_ebus_device *edev = to_ebus_device(&dev->dev);
+	struct device_node *dp = dev->node;
+
+	if (of_find_property(dp, "user", NULL))
+		return -ENODEV;
+
+	return uflash_devinit(edev, dp);
+}
+
+static int __devexit uflash_remove(struct of_device *dev)
+{
+	struct uflash_dev *up = dev_get_drvdata(&dev->dev);
+
+	if (up->mtd) {
+		del_mtd_device(up->mtd);
+		map_destroy(up->mtd);
+	}
+	if (up->map.virt) {
+		iounmap(up->map.virt);
+		up->map.virt = NULL;
+	}
+
+	kfree(up);
+
+	return 0;
+}
+
+static struct of_device_id uflash_match[] = {
+	{
+		.name = UFLASH_OBPNAME,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, uflash_match);
+
+static struct of_platform_driver uflash_driver = {
+	.name		= UFLASH_DEVNAME,
+	.match_table	= uflash_match,
+	.probe		= uflash_probe,
+	.remove		= __devexit_p(uflash_remove),
+};
+
 static int __init uflash_init(void)
 {
-	struct linux_ebus *ebus = NULL;
-	struct linux_ebus_device *edev = NULL;
-
-	for_each_ebus(ebus) {
-		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, UFLASH_OBPNAME)) {
-				if(0 > prom_getproplen(edev->prom_node, "user")) {
-					DEBUG(2, "%s: ignoring device at 0x%lx\n",
-							UFLASH_DEVNAME, edev->resource[0].start);
-				} else {
-					uflash_devinit(edev);
-				}
-			}
-		}
-	}
-
-	if(list_empty(&device_list)) {
-		printk("%s: unable to locate device\n", UFLASH_DEVNAME);
-		return -ENODEV;
-	}
-	return(0);
+	return of_register_driver(&uflash_driver, &ebus_bus_type);
 }
 
-static void __exit uflash_cleanup(void)
+static void __exit uflash_exit(void)
 {
-	struct list_head *udevlist;
-	struct uflash_dev *udev;
-
-	list_for_each(udevlist, &device_list) {
-		udev = list_entry(udevlist, struct uflash_dev, list);
-		DEBUG(2, "%s: removing device %s\n",
-			UFLASH_DEVNAME, udev->name);
-
-		if(0 != udev->mtd) {
-			del_mtd_device(udev->mtd);
-			map_destroy(udev->mtd);
-		}
-		if(0 != udev->map.virt) {
-			iounmap(udev->map.virt);
-			udev->map.virt = NULL;
-		}
-		kfree(udev->name);
-		kfree(udev);
-	}
+	of_unregister_driver(&uflash_driver);
 }
 
 module_init(uflash_init);
-module_exit(uflash_cleanup);
+module_exit(uflash_exit);
diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index 2cef280..e5c7846 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -71,7 +71,7 @@
 	set_current_state(TASK_INTERRUPTIBLE);
 	add_wait_queue(&wait_q, &wait);
 
-	ret = MTD_ERASE(mtd, &erase);
+	ret = mtd->erase(mtd, &erase);
 	if (ret) {
 		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&wait_q, &wait);
@@ -88,7 +88,7 @@
 	 * Next, writhe data to flash.
 	 */
 
-	ret = MTD_WRITE (mtd, pos, len, &retlen, buf);
+	ret = mtd->write(mtd, pos, len, &retlen, buf);
 	if (ret)
 		return ret;
 	if (retlen != len)
@@ -138,7 +138,7 @@
 		mtd->name, pos, len);
 
 	if (!sect_size)
-		return MTD_WRITE (mtd, pos, len, &retlen, buf);
+		return mtd->write(mtd, pos, len, &retlen, buf);
 
 	while (len > 0) {
 		unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -170,7 +170,8 @@
 			    mtdblk->cache_offset != sect_start) {
 				/* fill the cache with the current sector */
 				mtdblk->cache_state = STATE_EMPTY;
-				ret = MTD_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data);
+				ret = mtd->read(mtd, sect_start, sect_size,
+						&retlen, mtdblk->cache_data);
 				if (ret)
 					return ret;
 				if (retlen != sect_size)
@@ -207,7 +208,7 @@
 			mtd->name, pos, len);
 
 	if (!sect_size)
-		return MTD_READ (mtd, pos, len, &retlen, buf);
+		return mtd->read(mtd, pos, len, &retlen, buf);
 
 	while (len > 0) {
 		unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -226,7 +227,7 @@
 		    mtdblk->cache_offset == sect_start) {
 			memcpy (buf, mtdblk->cache_data + offset, size);
 		} else {
-			ret = MTD_READ (mtd, pos, size, &retlen, buf);
+			ret = mtd->read(mtd, pos, size, &retlen, buf);
 			if (ret)
 				return ret;
 			if (retlen != size)
@@ -288,8 +289,7 @@
 
 	mutex_init(&mtdblk->cache_mutex);
 	mtdblk->cache_state = STATE_EMPTY;
-	if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM &&
-	    mtdblk->mtd->erasesize) {
+	if ( !(mtdblk->mtd->flags & MTD_NO_ERASE) && mtdblk->mtd->erasesize) {
 		mtdblk->cache_size = mtdblk->mtd->erasesize;
 		mtdblk->cache_data = NULL;
 	}
diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c
index 0c830ba..29563ed 100644
--- a/drivers/mtd/mtdblock_ro.c
+++ b/drivers/mtd/mtdblock_ro.c
@@ -45,9 +45,7 @@
 	dev->blksize = 512;
 	dev->size = mtd->size >> 9;
 	dev->tr = tr;
-	if ((mtd->flags & (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE)) !=
-	    (MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEABLE))
-		dev->readonly = 1;
+	dev->readonly = 1;
 
 	add_mtd_blktrans_dev(dev);
 }
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 6f04458..9a4b59d 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -49,24 +49,18 @@
 };
 
 /*
- * We use file->private_data to store a pointer to the MTDdevice.
- * Since alighment is at least 32 bits, we have 2 bits free for OTP
- * modes as well.
+ * Data structure to hold the pointer to the mtd device as well
+ * as mode information ofr various use cases.
  */
-
-#define TO_MTD(file) (struct mtd_info *)((long)((file)->private_data) & ~3L)
-
-#define MTD_MODE_OTP_FACT	1
-#define MTD_MODE_OTP_USER	2
-#define MTD_MODE(file)		((long)((file)->private_data) & 3)
-
-#define SET_MTD_MODE(file, mode) \
-	do { long __p = (long)((file)->private_data); \
-	     (file)->private_data = (void *)((__p & ~3L) | mode); } while (0)
+struct mtd_file_info {
+	struct mtd_info *mtd;
+	enum mtd_file_modes mode;
+};
 
 static loff_t mtd_lseek (struct file *file, loff_t offset, int orig)
 {
-	struct mtd_info *mtd = TO_MTD(file);
+	struct mtd_file_info *mfi = file->private_data;
+	struct mtd_info *mtd = mfi->mtd;
 
 	switch (orig) {
 	case 0:
@@ -84,7 +78,7 @@
 		return -EINVAL;
 	}
 
-	if (offset >= 0 && offset < mtd->size)
+	if (offset >= 0 && offset <= mtd->size)
 		return file->f_pos = offset;
 
 	return -EINVAL;
@@ -97,6 +91,7 @@
 	int minor = iminor(inode);
 	int devnum = minor >> 1;
 	struct mtd_info *mtd;
+	struct mtd_file_info *mfi;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
 
@@ -117,14 +112,20 @@
 		return -ENODEV;
 	}
 
-	file->private_data = mtd;
-
 	/* You can't open it RW if it's not a writeable device */
 	if ((file->f_mode & 2) && !(mtd->flags & MTD_WRITEABLE)) {
 		put_mtd_device(mtd);
 		return -EACCES;
 	}
 
+	mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
+	if (!mfi) {
+		put_mtd_device(mtd);
+		return -ENOMEM;
+	}
+	mfi->mtd = mtd;
+	file->private_data = mfi;
+
 	return 0;
 } /* mtd_open */
 
@@ -132,16 +133,17 @@
 
 static int mtd_close(struct inode *inode, struct file *file)
 {
-	struct mtd_info *mtd;
+	struct mtd_file_info *mfi = file->private_data;
+	struct mtd_info *mtd = mfi->mtd;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
 
-	mtd = TO_MTD(file);
-
 	if (mtd->sync)
 		mtd->sync(mtd);
 
 	put_mtd_device(mtd);
+	file->private_data = NULL;
+	kfree(mfi);
 
 	return 0;
 } /* mtd_close */
@@ -153,7 +155,8 @@
 
 static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos)
 {
-	struct mtd_info *mtd = TO_MTD(file);
+	struct mtd_file_info *mfi = file->private_data;
+	struct mtd_info *mtd = mfi->mtd;
 	size_t retlen=0;
 	size_t total_retlen=0;
 	int ret=0;
@@ -170,36 +173,58 @@
 
 	/* FIXME: Use kiovec in 2.5 to lock down the user's buffers
 	   and pass them directly to the MTD functions */
+
+	if (count > MAX_KMALLOC_SIZE)
+		kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
+	else
+		kbuf=kmalloc(count, GFP_KERNEL);
+
+	if (!kbuf)
+		return -ENOMEM;
+
 	while (count) {
+
 		if (count > MAX_KMALLOC_SIZE)
 			len = MAX_KMALLOC_SIZE;
 		else
 			len = count;
 
-		kbuf=kmalloc(len,GFP_KERNEL);
-		if (!kbuf)
-			return -ENOMEM;
-
-		switch (MTD_MODE(file)) {
-		case MTD_MODE_OTP_FACT:
+		switch (mfi->mode) {
+		case MTD_MODE_OTP_FACTORY:
 			ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
 		case MTD_MODE_OTP_USER:
 			ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
+		case MTD_MODE_RAW:
+		{
+			struct mtd_oob_ops ops;
+
+			ops.mode = MTD_OOB_RAW;
+			ops.datbuf = kbuf;
+			ops.oobbuf = NULL;
+			ops.len = len;
+
+			ret = mtd->read_oob(mtd, *ppos, &ops);
+			retlen = ops.retlen;
+			break;
+		}
 		default:
-			ret = MTD_READ(mtd, *ppos, len, &retlen, kbuf);
+			ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
 		}
 		/* Nand returns -EBADMSG on ecc errors, but it returns
 		 * the data. For our userspace tools it is important
 		 * to dump areas with ecc errors !
+		 * For kernel internal usage it also might return -EUCLEAN
+		 * to signal the caller that a bitflip has occured and has
+		 * been corrected by the ECC algorithm.
 		 * Userspace software which accesses NAND this way
 		 * must be aware of the fact that it deals with NAND
 		 */
-		if (!ret || (ret == -EBADMSG)) {
+		if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) {
 			*ppos += retlen;
 			if (copy_to_user(buf, kbuf, retlen)) {
-			        kfree(kbuf);
+				kfree(kbuf);
 				return -EFAULT;
 			}
 			else
@@ -215,15 +240,16 @@
 			return ret;
 		}
 
-		kfree(kbuf);
 	}
 
+	kfree(kbuf);
 	return total_retlen;
 } /* mtd_read */
 
 static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos)
 {
-	struct mtd_info *mtd = TO_MTD(file);
+	struct mtd_file_info *mfi = file->private_data;
+	struct mtd_info *mtd = mfi->mtd;
 	char *kbuf;
 	size_t retlen;
 	size_t total_retlen=0;
@@ -241,25 +267,28 @@
 	if (!count)
 		return 0;
 
+	if (count > MAX_KMALLOC_SIZE)
+		kbuf=kmalloc(MAX_KMALLOC_SIZE, GFP_KERNEL);
+	else
+		kbuf=kmalloc(count, GFP_KERNEL);
+
+	if (!kbuf)
+		return -ENOMEM;
+
 	while (count) {
+
 		if (count > MAX_KMALLOC_SIZE)
 			len = MAX_KMALLOC_SIZE;
 		else
 			len = count;
 
-		kbuf=kmalloc(len,GFP_KERNEL);
-		if (!kbuf) {
-			printk("kmalloc is null\n");
-			return -ENOMEM;
-		}
-
 		if (copy_from_user(kbuf, buf, len)) {
 			kfree(kbuf);
 			return -EFAULT;
 		}
 
-		switch (MTD_MODE(file)) {
-		case MTD_MODE_OTP_FACT:
+		switch (mfi->mode) {
+		case MTD_MODE_OTP_FACTORY:
 			ret = -EROFS;
 			break;
 		case MTD_MODE_OTP_USER:
@@ -269,6 +298,21 @@
 			}
 			ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
+
+		case MTD_MODE_RAW:
+		{
+			struct mtd_oob_ops ops;
+
+			ops.mode = MTD_OOB_RAW;
+			ops.datbuf = kbuf;
+			ops.oobbuf = NULL;
+			ops.len = len;
+
+			ret = mtd->write_oob(mtd, *ppos, &ops);
+			retlen = ops.retlen;
+			break;
+		}
+
 		default:
 			ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf);
 		}
@@ -282,10 +326,9 @@
 			kfree(kbuf);
 			return ret;
 		}
-
-		kfree(kbuf);
 	}
 
+	kfree(kbuf);
 	return total_retlen;
 } /* mtd_write */
 
@@ -299,13 +342,45 @@
 	wake_up((wait_queue_head_t *)instr->priv);
 }
 
+#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
+{
+	struct mtd_info *mtd = mfi->mtd;
+	int ret = 0;
+
+	switch (mode) {
+	case MTD_OTP_FACTORY:
+		if (!mtd->read_fact_prot_reg)
+			ret = -EOPNOTSUPP;
+		else
+			mfi->mode = MTD_MODE_OTP_FACTORY;
+		break;
+	case MTD_OTP_USER:
+		if (!mtd->read_fact_prot_reg)
+			ret = -EOPNOTSUPP;
+		else
+			mfi->mode = MTD_MODE_OTP_USER;
+		break;
+	default:
+		ret = -EINVAL;
+	case MTD_OTP_OFF:
+		break;
+	}
+	return ret;
+}
+#else
+# define otp_select_filemode(f,m)	-EOPNOTSUPP
+#endif
+
 static int mtd_ioctl(struct inode *inode, struct file *file,
 		     u_int cmd, u_long arg)
 {
-	struct mtd_info *mtd = TO_MTD(file);
+	struct mtd_file_info *mfi = file->private_data;
+	struct mtd_info *mtd = mfi->mtd;
 	void __user *argp = (void __user *)arg;
 	int ret = 0;
 	u_long size;
+	struct mtd_info_user info;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
 
@@ -341,7 +416,15 @@
 	}
 
 	case MEMGETINFO:
-		if (copy_to_user(argp, mtd, sizeof(struct mtd_info_user)))
+		info.type	= mtd->type;
+		info.flags	= mtd->flags;
+		info.size	= mtd->size;
+		info.erasesize	= mtd->erasesize;
+		info.writesize	= mtd->writesize;
+		info.oobsize	= mtd->oobsize;
+		info.ecctype	= mtd->ecctype;
+		info.eccsize	= mtd->eccsize;
+		if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 			return -EFAULT;
 		break;
 
@@ -400,8 +483,7 @@
 	case MEMWRITEOOB:
 	{
 		struct mtd_oob_buf buf;
-		void *databuf;
-		ssize_t retlen;
+		struct mtd_oob_ops ops;
 
 		if(!(file->f_mode & 2))
 			return -EPERM;
@@ -409,7 +491,7 @@
 		if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
 			return -EFAULT;
 
-		if (buf.length > 0x4096)
+		if (buf.length > 4096)
 			return -EINVAL;
 
 		if (!mtd->write_oob)
@@ -421,21 +503,32 @@
 		if (ret)
 			return ret;
 
-		databuf = kmalloc(buf.length, GFP_KERNEL);
-		if (!databuf)
+		ops.len = buf.length;
+		ops.ooblen = buf.length;
+		ops.ooboffs = buf.start & (mtd->oobsize - 1);
+		ops.datbuf = NULL;
+		ops.mode = MTD_OOB_PLACE;
+
+		if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs))
+			return -EINVAL;
+
+		ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
+		if (!ops.oobbuf)
 			return -ENOMEM;
 
-		if (copy_from_user(databuf, buf.ptr, buf.length)) {
-			kfree(databuf);
+		if (copy_from_user(ops.oobbuf, buf.ptr, buf.length)) {
+			kfree(ops.oobbuf);
 			return -EFAULT;
 		}
 
-		ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf);
+		buf.start &= ~(mtd->oobsize - 1);
+		ret = mtd->write_oob(mtd, buf.start, &ops);
 
-		if (copy_to_user(argp + sizeof(uint32_t), &retlen, sizeof(uint32_t)))
+		if (copy_to_user(argp + sizeof(uint32_t), &ops.retlen,
+				 sizeof(uint32_t)))
 			ret = -EFAULT;
 
-		kfree(databuf);
+		kfree(ops.oobbuf);
 		break;
 
 	}
@@ -443,13 +536,12 @@
 	case MEMREADOOB:
 	{
 		struct mtd_oob_buf buf;
-		void *databuf;
-		ssize_t retlen;
+		struct mtd_oob_ops ops;
 
 		if (copy_from_user(&buf, argp, sizeof(struct mtd_oob_buf)))
 			return -EFAULT;
 
-		if (buf.length > 0x4096)
+		if (buf.length > 4096)
 			return -EINVAL;
 
 		if (!mtd->read_oob)
@@ -457,22 +549,32 @@
 		else
 			ret = access_ok(VERIFY_WRITE, buf.ptr,
 					buf.length) ? 0 : -EFAULT;
-
 		if (ret)
 			return ret;
 
-		databuf = kmalloc(buf.length, GFP_KERNEL);
-		if (!databuf)
+		ops.len = buf.length;
+		ops.ooblen = buf.length;
+		ops.ooboffs = buf.start & (mtd->oobsize - 1);
+		ops.datbuf = NULL;
+		ops.mode = MTD_OOB_PLACE;
+
+		if (ops.ooboffs && ops.len > (mtd->oobsize - ops.ooboffs))
+			return -EINVAL;
+
+		ops.oobbuf = kmalloc(buf.length, GFP_KERNEL);
+		if (!ops.oobbuf)
 			return -ENOMEM;
 
-		ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf);
+		buf.start &= ~(mtd->oobsize - 1);
+		ret = mtd->read_oob(mtd, buf.start, &ops);
 
-		if (put_user(retlen, (uint32_t __user *)argp))
+		if (put_user(ops.retlen, (uint32_t __user *)argp))
 			ret = -EFAULT;
-		else if (retlen && copy_to_user(buf.ptr, databuf, retlen))
+		else if (ops.retlen && copy_to_user(buf.ptr, ops.oobbuf,
+						    ops.retlen))
 			ret = -EFAULT;
 
-		kfree(databuf);
+		kfree(ops.oobbuf);
 		break;
 	}
 
@@ -504,16 +606,22 @@
 		break;
 	}
 
-	case MEMSETOOBSEL:
-	{
-		if (copy_from_user(&mtd->oobinfo, argp, sizeof(struct nand_oobinfo)))
-			return -EFAULT;
-		break;
-	}
-
+	/* Legacy interface */
 	case MEMGETOOBSEL:
 	{
-		if (copy_to_user(argp, &(mtd->oobinfo), sizeof(struct nand_oobinfo)))
+		struct nand_oobinfo oi;
+
+		if (!mtd->ecclayout)
+			return -EOPNOTSUPP;
+		if (mtd->ecclayout->eccbytes > ARRAY_SIZE(oi.eccpos))
+			return -EINVAL;
+
+		oi.useecc = MTD_NANDECC_AUTOPLACE;
+		memcpy(&oi.eccpos, mtd->ecclayout->eccpos, sizeof(oi.eccpos));
+		memcpy(&oi.oobfree, mtd->ecclayout->oobfree,
+		       sizeof(oi.oobfree));
+
+		if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
 			return -EFAULT;
 		break;
 	}
@@ -544,31 +652,17 @@
 		break;
 	}
 
-#ifdef CONFIG_MTD_OTP
+#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
 	case OTPSELECT:
 	{
 		int mode;
 		if (copy_from_user(&mode, argp, sizeof(int)))
 			return -EFAULT;
-		SET_MTD_MODE(file, 0);
-		switch (mode) {
-		case MTD_OTP_FACTORY:
-			if (!mtd->read_fact_prot_reg)
-				ret = -EOPNOTSUPP;
-			else
-				SET_MTD_MODE(file, MTD_MODE_OTP_FACT);
-			break;
-		case MTD_OTP_USER:
-			if (!mtd->read_fact_prot_reg)
-				ret = -EOPNOTSUPP;
-			else
-				SET_MTD_MODE(file, MTD_MODE_OTP_USER);
-			break;
-		default:
-			ret = -EINVAL;
-		case MTD_OTP_OFF:
-			break;
-		}
+
+		mfi->mode = MTD_MODE_NORMAL;
+
+		ret = otp_select_filemode(mfi, mode);
+
 		file->f_pos = 0;
 		break;
 	}
@@ -580,8 +674,8 @@
 		if (!buf)
 			return -ENOMEM;
 		ret = -EOPNOTSUPP;
-		switch (MTD_MODE(file)) {
-		case MTD_MODE_OTP_FACT:
+		switch (mfi->mode) {
+		case MTD_MODE_OTP_FACTORY:
 			if (mtd->get_fact_prot_info)
 				ret = mtd->get_fact_prot_info(mtd, buf, 4096);
 			break;
@@ -589,6 +683,8 @@
 			if (mtd->get_user_prot_info)
 				ret = mtd->get_user_prot_info(mtd, buf, 4096);
 			break;
+		default:
+			break;
 		}
 		if (ret >= 0) {
 			if (cmd == OTPGETREGIONCOUNT) {
@@ -607,7 +703,7 @@
 	{
 		struct otp_info info;
 
-		if (MTD_MODE(file) != MTD_MODE_OTP_USER)
+		if (mfi->mode != MTD_MODE_OTP_USER)
 			return -EINVAL;
 		if (copy_from_user(&info, argp, sizeof(info)))
 			return -EFAULT;
@@ -618,6 +714,49 @@
 	}
 #endif
 
+	case ECCGETLAYOUT:
+	{
+		if (!mtd->ecclayout)
+			return -EOPNOTSUPP;
+
+		if (copy_to_user(argp, &mtd->ecclayout,
+				 sizeof(struct nand_ecclayout)))
+			return -EFAULT;
+		break;
+	}
+
+	case ECCGETSTATS:
+	{
+		if (copy_to_user(argp, &mtd->ecc_stats,
+				 sizeof(struct mtd_ecc_stats)))
+			return -EFAULT;
+		break;
+	}
+
+	case MTDFILEMODE:
+	{
+		mfi->mode = 0;
+
+		switch(arg) {
+		case MTD_MODE_OTP_FACTORY:
+		case MTD_MODE_OTP_USER:
+			ret = otp_select_filemode(mfi, arg);
+			break;
+
+		case MTD_MODE_RAW:
+			if (!mtd->read_oob || !mtd->write_oob)
+				return -EOPNOTSUPP;
+			mfi->mode = arg;
+
+		case MTD_MODE_NORMAL:
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		file->f_pos = 0;
+		break;
+	}
+
 	default:
 		ret = -ENOTTY;
 	}
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 9af8403..1fea631 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -19,6 +19,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/concat.h>
 
+#include <asm/div64.h>
+
 /*
  * Our storage structure:
  * Subdev points to an array of pointers to struct mtd_info objects
@@ -54,7 +56,7 @@
 	    size_t * retlen, u_char * buf)
 {
 	struct mtd_concat *concat = CONCAT(mtd);
-	int err = -EINVAL;
+	int ret = 0, err;
 	int i;
 
 	*retlen = 0;
@@ -78,19 +80,29 @@
 
 		err = subdev->read(subdev, from, size, &retsize, buf);
 
-		if (err)
-			break;
+		/* Save information about bitflips! */
+		if (unlikely(err)) {
+			if (err == -EBADMSG) {
+				mtd->ecc_stats.failed++;
+				ret = err;
+			} else if (err == -EUCLEAN) {
+				mtd->ecc_stats.corrected++;
+				/* Do not overwrite -EBADMSG !! */
+				if (!ret)
+					ret = err;
+			} else
+				return err;
+		}
 
 		*retlen += retsize;
 		len -= size;
 		if (len == 0)
-			break;
+			return ret;
 
-		err = -EINVAL;
 		buf += size;
 		from = 0;
 	}
-	return err;
+	return -EINVAL;
 }
 
 static int
@@ -141,211 +153,185 @@
 }
 
 static int
-concat_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
-		size_t * retlen, u_char * buf, u_char * eccbuf,
-		struct nand_oobinfo *oobsel)
+concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
+		unsigned long count, loff_t to, size_t * retlen)
 {
 	struct mtd_concat *concat = CONCAT(mtd);
-	int err = -EINVAL;
+	struct kvec *vecs_copy;
+	unsigned long entry_low, entry_high;
+	size_t total_len = 0;
 	int i;
-
-	*retlen = 0;
-
-	for (i = 0; i < concat->num_subdev; i++) {
-		struct mtd_info *subdev = concat->subdev[i];
-		size_t size, retsize;
-
-		if (from >= subdev->size) {
-			/* Not destined for this subdev */
-			size = 0;
-			from -= subdev->size;
-			continue;
-		}
-
-		if (from + len > subdev->size)
-			/* First part goes into this subdev */
-			size = subdev->size - from;
-		else
-			/* Entire transaction goes into this subdev */
-			size = len;
-
-		if (subdev->read_ecc)
-			err = subdev->read_ecc(subdev, from, size,
-					       &retsize, buf, eccbuf, oobsel);
-		else
-			err = -EINVAL;
-
-		if (err)
-			break;
-
-		*retlen += retsize;
-		len -= size;
-		if (len == 0)
-			break;
-
-		err = -EINVAL;
-		buf += size;
-		if (eccbuf) {
-			eccbuf += subdev->oobsize;
-			/* in nand.c at least, eccbufs are
-			   tagged with 2 (int)eccstatus'; we
-			   must account for these */
-			eccbuf += 2 * (sizeof (int));
-		}
-		from = 0;
-	}
-	return err;
-}
-
-static int
-concat_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
-		 size_t * retlen, const u_char * buf, u_char * eccbuf,
-		 struct nand_oobinfo *oobsel)
-{
-	struct mtd_concat *concat = CONCAT(mtd);
 	int err = -EINVAL;
-	int i;
 
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 
 	*retlen = 0;
 
+	/* Calculate total length of data */
+	for (i = 0; i < count; i++)
+		total_len += vecs[i].iov_len;
+
+	/* Do not allow write past end of device */
+	if ((to + total_len) > mtd->size)
+		return -EINVAL;
+
+	/* Check alignment */
+	if (mtd->writesize > 1) {
+		loff_t __to = to;
+		if (do_div(__to, mtd->writesize) || (total_len % mtd->writesize))
+			return -EINVAL;
+	}
+
+	/* make a copy of vecs */
+	vecs_copy = kmalloc(sizeof(struct kvec) * count, GFP_KERNEL);
+	if (!vecs_copy)
+		return -ENOMEM;
+	memcpy(vecs_copy, vecs, sizeof(struct kvec) * count);
+
+	entry_low = 0;
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		size_t size, retsize;
+		size_t size, wsize, retsize, old_iov_len;
 
 		if (to >= subdev->size) {
-			size = 0;
 			to -= subdev->size;
 			continue;
 		}
-		if (to + len > subdev->size)
-			size = subdev->size - to;
-		else
-			size = len;
+
+		size = min(total_len, (size_t)(subdev->size - to));
+		wsize = size; /* store for future use */
+
+		entry_high = entry_low;
+		while (entry_high < count) {
+			if (size <= vecs_copy[entry_high].iov_len)
+				break;
+			size -= vecs_copy[entry_high++].iov_len;
+		}
+
+		old_iov_len = vecs_copy[entry_high].iov_len;
+		vecs_copy[entry_high].iov_len = size;
 
 		if (!(subdev->flags & MTD_WRITEABLE))
 			err = -EROFS;
-		else if (subdev->write_ecc)
-			err = subdev->write_ecc(subdev, to, size,
-						&retsize, buf, eccbuf, oobsel);
 		else
-			err = -EINVAL;
+			err = subdev->writev(subdev, &vecs_copy[entry_low],
+				entry_high - entry_low + 1, to, &retsize);
+
+		vecs_copy[entry_high].iov_len = old_iov_len - size;
+		vecs_copy[entry_high].iov_base += size;
+
+		entry_low = entry_high;
 
 		if (err)
 			break;
 
 		*retlen += retsize;
-		len -= size;
-		if (len == 0)
+		total_len -= wsize;
+
+		if (total_len == 0)
 			break;
 
 		err = -EINVAL;
-		buf += size;
-		if (eccbuf)
-			eccbuf += subdev->oobsize;
 		to = 0;
 	}
+
+	kfree(vecs_copy);
 	return err;
 }
 
 static int
-concat_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-		size_t * retlen, u_char * buf)
+concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 {
 	struct mtd_concat *concat = CONCAT(mtd);
-	int err = -EINVAL;
-	int i;
+	struct mtd_oob_ops devops = *ops;
+	int i, err, ret = 0;
 
-	*retlen = 0;
+	ops->retlen = 0;
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		size_t size, retsize;
 
 		if (from >= subdev->size) {
-			/* Not destined for this subdev */
-			size = 0;
 			from -= subdev->size;
 			continue;
 		}
-		if (from + len > subdev->size)
-			/* First part goes into this subdev */
-			size = subdev->size - from;
-		else
-			/* Entire transaction goes into this subdev */
-			size = len;
 
-		if (subdev->read_oob)
-			err = subdev->read_oob(subdev, from, size,
-					       &retsize, buf);
-		else
-			err = -EINVAL;
+		/* partial read ? */
+		if (from + devops.len > subdev->size)
+			devops.len = subdev->size - from;
 
-		if (err)
-			break;
+		err = subdev->read_oob(subdev, from, &devops);
+		ops->retlen += devops.retlen;
 
-		*retlen += retsize;
-		len -= size;
-		if (len == 0)
-			break;
+		/* Save information about bitflips! */
+		if (unlikely(err)) {
+			if (err == -EBADMSG) {
+				mtd->ecc_stats.failed++;
+				ret = err;
+			} else if (err == -EUCLEAN) {
+				mtd->ecc_stats.corrected++;
+				/* Do not overwrite -EBADMSG !! */
+				if (!ret)
+					ret = err;
+			} else
+				return err;
+		}
 
-		err = -EINVAL;
-		buf += size;
+		devops.len = ops->len - ops->retlen;
+		if (!devops.len)
+			return ret;
+
+		if (devops.datbuf)
+			devops.datbuf += devops.retlen;
+		if (devops.oobbuf)
+			devops.oobbuf += devops.ooblen;
+
 		from = 0;
 	}
-	return err;
+	return -EINVAL;
 }
 
 static int
-concat_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
-		 size_t * retlen, const u_char * buf)
+concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
 {
 	struct mtd_concat *concat = CONCAT(mtd);
-	int err = -EINVAL;
-	int i;
+	struct mtd_oob_ops devops = *ops;
+	int i, err;
 
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 
-	*retlen = 0;
+	ops->retlen = 0;
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		size_t size, retsize;
 
 		if (to >= subdev->size) {
-			size = 0;
 			to -= subdev->size;
 			continue;
 		}
-		if (to + len > subdev->size)
-			size = subdev->size - to;
-		else
-			size = len;
 
-		if (!(subdev->flags & MTD_WRITEABLE))
-			err = -EROFS;
-		else if (subdev->write_oob)
-			err = subdev->write_oob(subdev, to, size, &retsize,
-						buf);
-		else
-			err = -EINVAL;
+		/* partial write ? */
+		if (to + devops.len > subdev->size)
+			devops.len = subdev->size - to;
 
+		err = subdev->write_oob(subdev, to, &devops);
+		ops->retlen += devops.retlen;
 		if (err)
-			break;
+			return err;
 
-		*retlen += retsize;
-		len -= size;
-		if (len == 0)
-			break;
+		devops.len = ops->len - ops->retlen;
+		if (!devops.len)
+			return 0;
 
-		err = -EINVAL;
-		buf += size;
+		if (devops.datbuf)
+			devops.datbuf += devops.retlen;
+		if (devops.oobbuf)
+			devops.oobbuf += devops.ooblen;
 		to = 0;
 	}
-	return err;
+	return -EINVAL;
 }
 
 static void concat_erase_callback(struct erase_info *instr)
@@ -636,6 +622,60 @@
 	}
 }
 
+static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct mtd_concat *concat = CONCAT(mtd);
+	int i, res = 0;
+
+	if (!concat->subdev[0]->block_isbad)
+		return res;
+
+	if (ofs > mtd->size)
+		return -EINVAL;
+
+	for (i = 0; i < concat->num_subdev; i++) {
+		struct mtd_info *subdev = concat->subdev[i];
+
+		if (ofs >= subdev->size) {
+			ofs -= subdev->size;
+			continue;
+		}
+
+		res = subdev->block_isbad(subdev, ofs);
+		break;
+	}
+
+	return res;
+}
+
+static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	struct mtd_concat *concat = CONCAT(mtd);
+	int i, err = -EINVAL;
+
+	if (!concat->subdev[0]->block_markbad)
+		return 0;
+
+	if (ofs > mtd->size)
+		return -EINVAL;
+
+	for (i = 0; i < concat->num_subdev; i++) {
+		struct mtd_info *subdev = concat->subdev[i];
+
+		if (ofs >= subdev->size) {
+			ofs -= subdev->size;
+			continue;
+		}
+
+		err = subdev->block_markbad(subdev, ofs);
+		if (!err)
+			mtd->ecc_stats.badblocks++;
+		break;
+	}
+
+	return err;
+}
+
 /*
  * This function constructs a virtual MTD device by concatenating
  * num_devs MTD devices. A pointer to the new device object is
@@ -677,18 +717,22 @@
 	concat->mtd.flags = subdev[0]->flags;
 	concat->mtd.size = subdev[0]->size;
 	concat->mtd.erasesize = subdev[0]->erasesize;
-	concat->mtd.oobblock = subdev[0]->oobblock;
+	concat->mtd.writesize = subdev[0]->writesize;
 	concat->mtd.oobsize = subdev[0]->oobsize;
 	concat->mtd.ecctype = subdev[0]->ecctype;
 	concat->mtd.eccsize = subdev[0]->eccsize;
-	if (subdev[0]->read_ecc)
-		concat->mtd.read_ecc = concat_read_ecc;
-	if (subdev[0]->write_ecc)
-		concat->mtd.write_ecc = concat_write_ecc;
+	if (subdev[0]->writev)
+		concat->mtd.writev = concat_writev;
 	if (subdev[0]->read_oob)
 		concat->mtd.read_oob = concat_read_oob;
 	if (subdev[0]->write_oob)
 		concat->mtd.write_oob = concat_write_oob;
+	if (subdev[0]->block_isbad)
+		concat->mtd.block_isbad = concat_block_isbad;
+	if (subdev[0]->block_markbad)
+		concat->mtd.block_markbad = concat_block_markbad;
+
+	concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
 
 	concat->subdev[0] = subdev[0];
 
@@ -717,12 +761,12 @@
 				    subdev[i]->flags & MTD_WRITEABLE;
 		}
 		concat->mtd.size += subdev[i]->size;
-		if (concat->mtd.oobblock   !=  subdev[i]->oobblock ||
+		concat->mtd.ecc_stats.badblocks +=
+			subdev[i]->ecc_stats.badblocks;
+		if (concat->mtd.writesize   !=  subdev[i]->writesize ||
 		    concat->mtd.oobsize    !=  subdev[i]->oobsize ||
 		    concat->mtd.ecctype    !=  subdev[i]->ecctype ||
 		    concat->mtd.eccsize    !=  subdev[i]->eccsize ||
-		    !concat->mtd.read_ecc  != !subdev[i]->read_ecc ||
-		    !concat->mtd.write_ecc != !subdev[i]->write_ecc ||
 		    !concat->mtd.read_oob  != !subdev[i]->read_oob ||
 		    !concat->mtd.write_oob != !subdev[i]->write_oob) {
 			kfree(concat);
@@ -734,14 +778,11 @@
 
 	}
 
+	concat->mtd.ecclayout = subdev[0]->ecclayout;
+
 	concat->num_subdev = num_devs;
 	concat->mtd.name = name;
 
-	/*
-	 * NOTE: for now, we do not provide any readv()/writev() methods
-	 *       because they are messy to implement and they are not
-	 *       used to a great extent anyway.
-	 */
 	concat->mtd.erase = concat_erase;
 	concat->mtd.read = concat_read;
 	concat->mtd.write = concat_write;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 9905870..16a952dd 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -47,6 +47,7 @@
 {
 	int i;
 
+	BUG_ON(mtd->writesize == 0);
 	mutex_lock(&mtd_table_mutex);
 
 	for (i=0; i < MAX_MTD_DEVICES; i++)
@@ -254,37 +255,6 @@
 	return ret;
 }
 
-
-/* default_mtd_readv - default mtd readv method for MTD devices that dont
- *		       implement their own
- */
-
-int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
-		      unsigned long count, loff_t from, size_t *retlen)
-{
-	unsigned long i;
-	size_t totlen = 0, thislen;
-	int ret = 0;
-
-	if(!mtd->read) {
-		ret = -EIO;
-	} else {
-		for (i=0; i<count; i++) {
-			if (!vecs[i].iov_len)
-				continue;
-			ret = mtd->read(mtd, from, vecs[i].iov_len, &thislen, vecs[i].iov_base);
-			totlen += thislen;
-			if (ret || thislen != vecs[i].iov_len)
-				break;
-			from += vecs[i].iov_len;
-		}
-	}
-	if (retlen)
-		*retlen = totlen;
-	return ret;
-}
-
-
 EXPORT_SYMBOL(add_mtd_device);
 EXPORT_SYMBOL(del_mtd_device);
 EXPORT_SYMBOL(get_mtd_device);
@@ -292,7 +262,6 @@
 EXPORT_SYMBOL(register_mtd_user);
 EXPORT_SYMBOL(unregister_mtd_user);
 EXPORT_SYMBOL(default_mtd_writev);
-EXPORT_SYMBOL(default_mtd_readv);
 
 #ifdef CONFIG_PROC_FS
 
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 9939591..77a7123 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -51,16 +51,21 @@
 			size_t *retlen, u_char *buf)
 {
 	struct mtd_part *part = PART(mtd);
+	int res;
+
 	if (from >= mtd->size)
 		len = 0;
 	else if (from + len > mtd->size)
 		len = mtd->size - from;
-	if (part->master->read_ecc == NULL)
-		return part->master->read (part->master, from + part->offset,
-					len, retlen, buf);
-	else
-		return part->master->read_ecc (part->master, from + part->offset,
-					len, retlen, buf, NULL, &mtd->oobinfo);
+	res = part->master->read (part->master, from + part->offset,
+				   len, retlen, buf);
+	if (unlikely(res)) {
+		if (res == -EUCLEAN)
+			mtd->ecc_stats.corrected++;
+		if (res == -EBADMSG)
+			mtd->ecc_stats.failed++;
+	}
+	return res;
 }
 
 static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
@@ -74,6 +79,7 @@
 	return part->master->point (part->master, from + part->offset,
 				    len, retlen, buf);
 }
+
 static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len)
 {
 	struct mtd_part *part = PART(mtd);
@@ -81,31 +87,25 @@
 	part->master->unpoint (part->master, addr, from + part->offset, len);
 }
 
-
-static int part_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-			size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int part_read_oob(struct mtd_info *mtd, loff_t from,
+			 struct mtd_oob_ops *ops)
 {
 	struct mtd_part *part = PART(mtd);
-	if (oobsel == NULL)
-		oobsel = &mtd->oobinfo;
-	if (from >= mtd->size)
-		len = 0;
-	else if (from + len > mtd->size)
-		len = mtd->size - from;
-	return part->master->read_ecc (part->master, from + part->offset,
-					len, retlen, buf, eccbuf, oobsel);
-}
+	int res;
 
-static int part_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
-			size_t *retlen, u_char *buf)
-{
-	struct mtd_part *part = PART(mtd);
 	if (from >= mtd->size)
-		len = 0;
-	else if (from + len > mtd->size)
-		len = mtd->size - from;
-	return part->master->read_oob (part->master, from + part->offset,
-					len, retlen, buf);
+		return -EINVAL;
+	if (from + ops->len > mtd->size)
+		return -EINVAL;
+	res = part->master->read_oob(part->master, from + part->offset, ops);
+
+	if (unlikely(res)) {
+		if (res == -EUCLEAN)
+			mtd->ecc_stats.corrected++;
+		if (res == -EBADMSG)
+			mtd->ecc_stats.failed++;
+	}
+	return res;
 }
 
 static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
@@ -148,44 +148,23 @@
 		len = 0;
 	else if (to + len > mtd->size)
 		len = mtd->size - to;
-	if (part->master->write_ecc == NULL)
-		return part->master->write (part->master, to + part->offset,
-					len, retlen, buf);
-	else
-		return part->master->write_ecc (part->master, to + part->offset,
-					len, retlen, buf, NULL, &mtd->oobinfo);
-
+	return part->master->write (part->master, to + part->offset,
+				    len, retlen, buf);
 }
 
-static int part_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-			size_t *retlen, const u_char *buf,
-			 u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int part_write_oob(struct mtd_info *mtd, loff_t to,
+			 struct mtd_oob_ops *ops)
 {
 	struct mtd_part *part = PART(mtd);
-	if (!(mtd->flags & MTD_WRITEABLE))
-		return -EROFS;
-	if (oobsel == NULL)
-		oobsel = &mtd->oobinfo;
-	if (to >= mtd->size)
-		len = 0;
-	else if (to + len > mtd->size)
-		len = mtd->size - to;
-	return part->master->write_ecc (part->master, to + part->offset,
-					len, retlen, buf, eccbuf, oobsel);
-}
 
-static int part_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
-			size_t *retlen, const u_char *buf)
-{
-	struct mtd_part *part = PART(mtd);
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
+
 	if (to >= mtd->size)
-		len = 0;
-	else if (to + len > mtd->size)
-		len = mtd->size - to;
-	return part->master->write_oob (part->master, to + part->offset,
-					len, retlen, buf);
+		return -EINVAL;
+	if (to + ops->len > mtd->size)
+		return -EINVAL;
+	return part->master->write_oob(part->master, to + part->offset, ops);
 }
 
 static int part_write_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
@@ -208,52 +187,8 @@
 	struct mtd_part *part = PART(mtd);
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
-	if (part->master->writev_ecc == NULL)
-		return part->master->writev (part->master, vecs, count,
+	return part->master->writev (part->master, vecs, count,
 					to + part->offset, retlen);
-	else
-		return part->master->writev_ecc (part->master, vecs, count,
-					to + part->offset, retlen,
-					NULL, &mtd->oobinfo);
-}
-
-static int part_readv (struct mtd_info *mtd,  struct kvec *vecs,
-			 unsigned long count, loff_t from, size_t *retlen)
-{
-	struct mtd_part *part = PART(mtd);
-	if (part->master->readv_ecc == NULL)
-		return part->master->readv (part->master, vecs, count,
-					from + part->offset, retlen);
-	else
-		return part->master->readv_ecc (part->master, vecs, count,
-					from + part->offset, retlen,
-					NULL, &mtd->oobinfo);
-}
-
-static int part_writev_ecc (struct mtd_info *mtd,  const struct kvec *vecs,
-			 unsigned long count, loff_t to, size_t *retlen,
-			 u_char *eccbuf,  struct nand_oobinfo *oobsel)
-{
-	struct mtd_part *part = PART(mtd);
-	if (!(mtd->flags & MTD_WRITEABLE))
-		return -EROFS;
-	if (oobsel == NULL)
-		oobsel = &mtd->oobinfo;
-	return part->master->writev_ecc (part->master, vecs, count,
-					to + part->offset, retlen,
-					eccbuf, oobsel);
-}
-
-static int part_readv_ecc (struct mtd_info *mtd,  struct kvec *vecs,
-			 unsigned long count, loff_t from, size_t *retlen,
-			 u_char *eccbuf,  struct nand_oobinfo *oobsel)
-{
-	struct mtd_part *part = PART(mtd);
-	if (oobsel == NULL)
-		oobsel = &mtd->oobinfo;
-	return part->master->readv_ecc (part->master, vecs, count,
-					from + part->offset, retlen,
-					eccbuf, oobsel);
 }
 
 static int part_erase (struct mtd_info *mtd, struct erase_info *instr)
@@ -329,12 +264,17 @@
 static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_part *part = PART(mtd);
+	int res;
+
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 	if (ofs >= mtd->size)
 		return -EINVAL;
 	ofs += part->offset;
-	return part->master->block_markbad(part->master, ofs);
+	res = part->master->block_markbad(part->master, ofs);
+	if (!res)
+		mtd->ecc_stats.badblocks++;
+	return res;
 }
 
 /*
@@ -398,7 +338,7 @@
 		slave->mtd.type = master->type;
 		slave->mtd.flags = master->flags & ~parts[i].mask_flags;
 		slave->mtd.size = parts[i].size;
-		slave->mtd.oobblock = master->oobblock;
+		slave->mtd.writesize = master->writesize;
 		slave->mtd.oobsize = master->oobsize;
 		slave->mtd.ecctype = master->ecctype;
 		slave->mtd.eccsize = master->eccsize;
@@ -415,10 +355,6 @@
 			slave->mtd.unpoint = part_unpoint;
 		}
 
-		if (master->read_ecc)
-			slave->mtd.read_ecc = part_read_ecc;
-		if (master->write_ecc)
-			slave->mtd.write_ecc = part_write_ecc;
 		if (master->read_oob)
 			slave->mtd.read_oob = part_read_oob;
 		if (master->write_oob)
@@ -443,12 +379,6 @@
 		}
 		if (master->writev)
 			slave->mtd.writev = part_writev;
-		if (master->readv)
-			slave->mtd.readv = part_readv;
-		if (master->writev_ecc)
-			slave->mtd.writev_ecc = part_writev_ecc;
-		if (master->readv_ecc)
-			slave->mtd.readv_ecc = part_readv_ecc;
 		if (master->lock)
 			slave->mtd.lock = part_lock;
 		if (master->unlock)
@@ -528,8 +458,17 @@
 				parts[i].name);
 		}
 
-		/* copy oobinfo from master */
-		memcpy(&slave->mtd.oobinfo, &master->oobinfo, sizeof(slave->mtd.oobinfo));
+		slave->mtd.ecclayout = master->ecclayout;
+		if (master->block_isbad) {
+			uint32_t offs = 0;
+
+			while(offs < slave->mtd.size) {
+				if (master->block_isbad(master,
+							offs + slave->offset))
+					slave->mtd.ecc_stats.badblocks++;
+				offs += slave->mtd.erasesize;
+			}
+		}
 
 		if(parts[i].mtdp)
 		{	/* store the object pointer (caller may or may not register it */
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index cfe288a..3db77ee 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -23,6 +23,14 @@
 	  device thinks the write was successful, a bit could have been
 	  flipped accidentaly due to device wear or something else.
 
+config MTD_NAND_ECC_SMC
+	bool "NAND ECC Smart Media byte order"
+	depends on MTD_NAND
+	default n
+	help
+	  Software ECC according to the Smart Media Specification.
+	  The original Linux implementation had byte 0 and 1 swapped.
+
 config MTD_NAND_AUTCPU12
 	tristate "SmartMediaCard on autronix autcpu12 board"
 	depends on MTD_NAND && ARCH_AUTCPU12
@@ -49,12 +57,24 @@
 	help
 	  If you had to ask, you don't have one. Say 'N'.
 
+config MTD_NAND_AMS_DELTA
+	tristate "NAND Flash device on Amstrad E3"
+	depends on MACH_AMS_DELTA && MTD_NAND
+	help
+	  Support for NAND flash on Amstrad E3 (Delta).
+
 config MTD_NAND_TOTO
 	tristate "NAND Flash device on TOTO board"
-	depends on ARCH_OMAP && MTD_NAND
+	depends on ARCH_OMAP && MTD_NAND && BROKEN
 	help
 	  Support for NAND flash on Texas Instruments Toto platform.
 
+config MTD_NAND_TS7250
+	tristate "NAND Flash device on TS-7250 board"
+	depends on MACH_TS72XX && MTD_NAND
+	help
+	  Support for NAND flash on Technologic Systems TS-7250 platform.
+
 config MTD_NAND_IDS
 	tristate
 
@@ -76,7 +96,7 @@
 
 config MTD_NAND_PPCHAMELEONEVB
 	tristate "NAND Flash device on PPChameleonEVB board"
-	depends on PPCHAMELEONEVB && MTD_NAND
+	depends on PPCHAMELEONEVB && MTD_NAND && BROKEN
 	help
 	  This enables the NAND flash driver on the PPChameleon EVB Board.
 
@@ -87,7 +107,7 @@
 	  This enables the NAND flash controller on the S3C2410 and S3C2440
 	  SoCs
 
-	  No board specfic support is done by this driver, each board
+	  No board specific support is done by this driver, each board
 	  must advertise a platform_device for the driver to attach.
 
 config MTD_NAND_S3C2410_DEBUG
@@ -109,6 +129,22 @@
 	  currently not be able to switch to software, as there is no
 	  implementation for ECC method used by the S3C2410
 
+config MTD_NAND_NDFC
+	tristate "NDFC NanD Flash Controller"
+	depends on MTD_NAND && 44x
+	help
+	 NDFC Nand Flash Controllers are integrated in EP44x SoCs
+
+config MTD_NAND_S3C2410_CLKSTOP
+	bool "S3C2410 NAND IDLE clock stop"
+	depends on MTD_NAND_S3C2410
+	default n
+	help
+	  Stop the clock to the NAND controller when there is no chip
+	  selected to save power. This will mean there is a small delay
+	  when the is NAND chip selected or released, but will save
+	  approximately 5mA of power when there is nothing happening.
+
 config MTD_NAND_DISKONCHIP
 	tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
 	depends on MTD_NAND && EXPERIMENTAL
@@ -183,11 +219,24 @@
 	tristate "Support for NAND Flash on Sharp SL Series (C7xx + others)"
 	depends on MTD_NAND && ARCH_PXA
 
+config MTD_NAND_CS553X
+	tristate "NAND support for CS5535/CS5536 (AMD Geode companion chip)"
+	depends on MTD_NAND && X86_32 && (X86_PC || X86_GENERICARCH)
+	help
+	  The CS553x companion chips for the AMD Geode processor
+	  include NAND flash controllers with built-in hardware ECC
+	  capabilities; enabling this option will allow you to use
+	  these. The driver will check the MSRs to verify that the
+	  controller is enabled for NAND, and currently requires that
+	  the controller be in MMIO mode.
+
+	  If you say "m", the module will be called "cs553x_nand.ko".
+
 config MTD_NAND_NANDSIM
 	tristate "Support for NAND Flash Simulator"
 	depends on MTD_NAND && MTD_PARTITIONS
 	help
-	  The simulator may simulate verious NAND flash chips for the
+	  The simulator may simulate various NAND flash chips for the
 	  MTD nand layer.
 
 endmenu
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 4174202..f747593 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_MTD_NAND_IDS)		+= nand_ids.o
 
 obj-$(CONFIG_MTD_NAND_SPIA)		+= spia.o
+obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
 obj-$(CONFIG_MTD_NAND_TOTO)		+= toto.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_EDB7312)		+= edb7312.o
@@ -17,6 +18,9 @@
 obj-$(CONFIG_MTD_NAND_H1900)		+= h1910.o
 obj-$(CONFIG_MTD_NAND_RTC_FROM4)	+= rtc_from4.o
 obj-$(CONFIG_MTD_NAND_SHARPSL)		+= sharpsl.o
+obj-$(CONFIG_MTD_NAND_TS7250)		+= ts7250.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)		+= nandsim.o
+obj-$(CONFIG_MTD_NAND_CS553X)		+= cs553x_nand.o
+obj-$(CONFIG_MTD_NAND_NDFC)		+= ndfc.o
 
 nand-objs = nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
new file mode 100644
index 0000000..d7897dc
--- /dev/null
+++ b/drivers/mtd/nand/ams-delta.c
@@ -0,0 +1,237 @@
+/*
+ *  drivers/mtd/nand/ams-delta.c
+ *
+ *  Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
+ *
+ *  Derived from drivers/mtd/toto.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   Amstrad E3 (Delta).
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/sizes.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/board-ams-delta.h>
+
+/*
+ * MTD structure for E3 (Delta)
+ */
+static struct mtd_info *ams_delta_mtd = NULL;
+
+#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP)
+
+/*
+ * Define partitions for flash devices
+ */
+
+static struct mtd_partition partition_info[] = {
+	{ .name		= "Kernel",
+	  .offset	= 0,
+	  .size		= 3 * SZ_1M + SZ_512K },
+	{ .name		= "u-boot",
+	  .offset	= 3 * SZ_1M + SZ_512K,
+	  .size		= SZ_256K },
+	{ .name		= "u-boot params",
+	  .offset	= 3 * SZ_1M + SZ_512K + SZ_256K,
+	  .size		= SZ_256K },
+	{ .name		= "Amstrad LDR",
+	  .offset	= 4 * SZ_1M,
+	  .size		= SZ_256K },
+	{ .name		= "File system",
+	  .offset	= 4 * SZ_1M + 1 * SZ_256K,
+	  .size		= 27 * SZ_1M },
+	{ .name		= "PBL reserved",
+	  .offset	= 32 * SZ_1M - 3 * SZ_256K,
+	  .size		=  3 * SZ_256K },
+};
+
+static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
+{
+	struct nand_chip *this = mtd->priv;
+
+	omap_writew(0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
+	omap_writew(byte, this->IO_ADDR_W);
+	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0);
+	ndelay(40);
+	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE,
+			       AMS_DELTA_LATCH2_NAND_NWE);
+}
+
+static u_char ams_delta_read_byte(struct mtd_info *mtd)
+{
+	u_char res;
+	struct nand_chip *this = mtd->priv;
+
+	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0);
+	ndelay(40);
+	omap_writew(~0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
+	res = omap_readw(this->IO_ADDR_R);
+	ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE,
+			       AMS_DELTA_LATCH2_NAND_NRE);
+
+	return res;
+}
+
+static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf,
+				int len)
+{
+	int i;
+
+	for (i=0; i<len; i++)
+		ams_delta_write_byte(mtd, buf[i]);
+}
+
+static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	int i;
+
+	for (i=0; i<len; i++)
+		buf[i] = ams_delta_read_byte(mtd);
+}
+
+static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf,
+				int len)
+{
+	int i;
+
+	for (i=0; i<len; i++)
+		if (buf[i] != ams_delta_read_byte(mtd))
+			return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Command control function
+ *
+ * ctrl:
+ * NAND_NCE: bit 0 -> bit 2
+ * NAND_CLE: bit 1 -> bit 7
+ * NAND_ALE: bit 2 -> bit 6
+ */
+static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
+				unsigned int ctrl)
+{
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		unsigned long bits;
+
+		bits = (~ctrl & NAND_NCE) << 2;
+		bits |= (ctrl & NAND_CLE) << 7;
+		bits |= (ctrl & NAND_ALE) << 6;
+
+		ams_delta_latch2_write(0xC2, bits);
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		ams_delta_write_byte(mtd, cmd);
+}
+
+static int ams_delta_nand_ready(struct mtd_info *mtd)
+{
+	return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB);
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init ams_delta_init(void)
+{
+	struct nand_chip *this;
+	int err = 0;
+
+	/* Allocate memory for MTD device structure and private data */
+	ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
+				sizeof(struct nand_chip), GFP_KERNEL);
+	if (!ams_delta_mtd) {
+		printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	ams_delta_mtd->owner = THIS_MODULE;
+
+	/* Get pointer to private data */
+	this = (struct nand_chip *) (&ams_delta_mtd[1]);
+
+	/* Initialize structures */
+	memset(ams_delta_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
+
+	/* Link the private data with the MTD structure */
+	ams_delta_mtd->priv = this;
+
+	/* Set address of NAND IO lines */
+	this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
+	this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
+	this->read_byte = ams_delta_read_byte;
+	this->write_buf = ams_delta_write_buf;
+	this->read_buf = ams_delta_read_buf;
+	this->verify_buf = ams_delta_verify_buf;
+	this->cmd_ctrl = ams_delta_hwcontrol;
+	if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) {
+		this->dev_ready = ams_delta_nand_ready;
+	} else {
+		this->dev_ready = NULL;
+		printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n");
+	}
+	/* 25 us command delay time */
+	this->chip_delay = 30;
+	this->ecc.mode = NAND_ECC_SOFT;
+
+	/* Set chip enabled, but  */
+	ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
+					  AMS_DELTA_LATCH2_NAND_NWE |
+					  AMS_DELTA_LATCH2_NAND_NCE |
+					  AMS_DELTA_LATCH2_NAND_NWP);
+
+	/* Scan to find existance of the device */
+	if (nand_scan(ams_delta_mtd, 1)) {
+		err = -ENXIO;
+		goto out_mtd;
+	}
+
+	/* Register the partitions */
+	add_mtd_partitions(ams_delta_mtd, partition_info,
+			   ARRAY_SIZE(partition_info));
+
+	goto out;
+
+ out_mtd:
+	kfree(ams_delta_mtd);
+ out:
+	return err;
+}
+
+module_init(ams_delta_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit ams_delta_cleanup(void)
+{
+	/* Release resources, unregister device */
+	nand_release(ams_delta_mtd);
+
+	/* Free the MTD device structure */
+	kfree(ams_delta_mtd);
+}
+module_exit(ams_delta_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
+MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)");
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index bde3550..3122833 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
@@ -38,22 +39,21 @@
  */
 static struct mtd_info *au1550_mtd = NULL;
 static void __iomem *p_nand;
-static int nand_width = 1; /* default x8*/
+static int nand_width = 1;	/* default x8 */
+static void (*au1550_write_byte)(struct mtd_info *, u_char);
 
 /*
  * Define partitions for flash device
  */
 static const struct mtd_partition partition_info[] = {
 	{
-		.name 	= "NAND FS 0",
-	  	.offset = 0,
-	  	.size 	= 8*1024*1024
-	},
+	 .name = "NAND FS 0",
+	 .offset = 0,
+	 .size = 8 * 1024 * 1024},
 	{
-		.name 	= "NAND FS 1",
-		.offset =  MTDPART_OFS_APPEND,
- 		.size 	=    MTDPART_SIZ_FULL
-	}
+	 .name = "NAND FS 1",
+	 .offset = MTDPART_OFS_APPEND,
+	 .size = MTDPART_SIZ_FULL}
 };
 
 /**
@@ -130,21 +130,6 @@
 }
 
 /**
- * au_write_word -  write one word to the chip
- * @mtd:	MTD device structure
- * @word:	data word to write
- *
- *  write function for 16bit buswith without
- * endianess conversion
- */
-static void au_write_word(struct mtd_info *mtd, u16 word)
-{
-	struct nand_chip *this = mtd->priv;
-	writew(word, this->IO_ADDR_W);
-	au_sync();
-}
-
-/**
  * au_write_buf -  write buffer to chip
  * @mtd:	MTD device structure
  * @buf:	data buffer
@@ -157,7 +142,7 @@
 	int i;
 	struct nand_chip *this = mtd->priv;
 
-	for (i=0; i<len; i++) {
+	for (i = 0; i < len; i++) {
 		writeb(buf[i], this->IO_ADDR_W);
 		au_sync();
 	}
@@ -176,7 +161,7 @@
 	int i;
 	struct nand_chip *this = mtd->priv;
 
-	for (i=0; i<len; i++) {
+	for (i = 0; i < len; i++) {
 		buf[i] = readb(this->IO_ADDR_R);
 		au_sync();
 	}
@@ -195,7 +180,7 @@
 	int i;
 	struct nand_chip *this = mtd->priv;
 
-	for (i=0; i<len; i++) {
+	for (i = 0; i < len; i++) {
 		if (buf[i] != readb(this->IO_ADDR_R))
 			return -EFAULT;
 		au_sync();
@@ -219,7 +204,7 @@
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
-	for (i=0; i<len; i++) {
+	for (i = 0; i < len; i++) {
 		writew(p[i], this->IO_ADDR_W);
 		au_sync();
 	}
@@ -241,7 +226,7 @@
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
-	for (i=0; i<len; i++) {
+	for (i = 0; i < len; i++) {
 		p[i] = readw(this->IO_ADDR_R);
 		au_sync();
 	}
@@ -262,7 +247,7 @@
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
-	for (i=0; i<len; i++) {
+	for (i = 0; i < len; i++) {
 		if (p[i] != readw(this->IO_ADDR_R))
 			return -EFAULT;
 		au_sync();
@@ -270,32 +255,52 @@
 	return 0;
 }
 
+/* Select the chip by setting nCE to low */
+#define NAND_CTL_SETNCE		1
+/* Deselect the chip by setting nCE to high */
+#define NAND_CTL_CLRNCE		2
+/* Select the command latch by setting CLE to high */
+#define NAND_CTL_SETCLE		3
+/* Deselect the command latch by setting CLE to low */
+#define NAND_CTL_CLRCLE		4
+/* Select the address latch by setting ALE to high */
+#define NAND_CTL_SETALE		5
+/* Deselect the address latch by setting ALE to low */
+#define NAND_CTL_CLRALE		6
 
 static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
 {
 	register struct nand_chip *this = mtd->priv;
 
-	switch(cmd){
+	switch (cmd) {
 
-	case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break;
-	case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break;
+	case NAND_CTL_SETCLE:
+		this->IO_ADDR_W = p_nand + MEM_STNAND_CMD;
+		break;
 
-	case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;
+	case NAND_CTL_CLRCLE:
+		this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
+		break;
+
+	case NAND_CTL_SETALE:
+		this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR;
+		break;
+
 	case NAND_CTL_CLRALE:
 		this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
-		/* FIXME: Nobody knows why this is neccecary,
+		/* FIXME: Nobody knows why this is necessary,
 		 * but it works only that way */
 		udelay(1);
 		break;
 
 	case NAND_CTL_SETNCE:
 		/* assert (force assert) chip enable */
-		au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break;
+		au_writel((1 << (4 + NAND_CS)), MEM_STNDCTL);
 		break;
 
 	case NAND_CTL_CLRNCE:
- 		/* deassert chip enable */
-		au_writel(0, MEM_STNDCTL); break;
+		/* deassert chip enable */
+		au_writel(0, MEM_STNDCTL);
 		break;
 	}
 
@@ -312,69 +317,200 @@
 	return ret;
 }
 
+/**
+ * au1550_select_chip - control -CE line
+ *	Forbid driving -CE manually permitting the NAND controller to do this.
+ *	Keeping -CE asserted during the whole sector reads interferes with the
+ *	NOR flash and PCMCIA drivers as it causes contention on the static bus.
+ *	We only have to hold -CE low for the NAND read commands since the flash
+ *	chip needs it to be asserted during chip not ready time but the NAND
+ *	controller keeps it released.
+ *
+ * @mtd:	MTD device structure
+ * @chip:	chipnumber to select, -1 for deselect
+ */
+static void au1550_select_chip(struct mtd_info *mtd, int chip)
+{
+}
+
+/**
+ * au1550_command - Send command to NAND device
+ * @mtd:	MTD device structure
+ * @command:	the command to be sent
+ * @column:	the column address for this command, -1 if none
+ * @page_addr:	the page address for this command, -1 if none
+ */
+static void au1550_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
+{
+	register struct nand_chip *this = mtd->priv;
+	int ce_override = 0, i;
+	ulong flags;
+
+	/* Begin command latch cycle */
+	au1550_hwcontrol(mtd, NAND_CTL_SETCLE);
+	/*
+	 * Write out the command to the device.
+	 */
+	if (command == NAND_CMD_SEQIN) {
+		int readcmd;
+
+		if (column >= mtd->writesize) {
+			/* OOB area */
+			column -= mtd->writesize;
+			readcmd = NAND_CMD_READOOB;
+		} else if (column < 256) {
+			/* First 256 bytes --> READ0 */
+			readcmd = NAND_CMD_READ0;
+		} else {
+			column -= 256;
+			readcmd = NAND_CMD_READ1;
+		}
+		au1550_write_byte(mtd, readcmd);
+	}
+	au1550_write_byte(mtd, command);
+
+	/* Set ALE and clear CLE to start address cycle */
+	au1550_hwcontrol(mtd, NAND_CTL_CLRCLE);
+
+	if (column != -1 || page_addr != -1) {
+		au1550_hwcontrol(mtd, NAND_CTL_SETALE);
+
+		/* Serially input address */
+		if (column != -1) {
+			/* Adjust columns for 16 bit buswidth */
+			if (this->options & NAND_BUSWIDTH_16)
+				column >>= 1;
+			au1550_write_byte(mtd, column);
+		}
+		if (page_addr != -1) {
+			au1550_write_byte(mtd, (u8)(page_addr & 0xff));
+
+			if (command == NAND_CMD_READ0 ||
+			    command == NAND_CMD_READ1 ||
+			    command == NAND_CMD_READOOB) {
+				/*
+				 * NAND controller will release -CE after
+				 * the last address byte is written, so we'll
+				 * have to forcibly assert it. No interrupts
+				 * are allowed while we do this as we don't
+				 * want the NOR flash or PCMCIA drivers to
+				 * steal our precious bytes of data...
+				 */
+				ce_override = 1;
+				local_irq_save(flags);
+				au1550_hwcontrol(mtd, NAND_CTL_SETNCE);
+			}
+
+			au1550_write_byte(mtd, (u8)(page_addr >> 8));
+
+			/* One more address cycle for devices > 32MiB */
+			if (this->chipsize > (32 << 20))
+				au1550_write_byte(mtd, (u8)((page_addr >> 16) & 0x0f));
+		}
+		/* Latch in address */
+		au1550_hwcontrol(mtd, NAND_CTL_CLRALE);
+	}
+
+	/*
+	 * Program and erase have their own busy handlers.
+	 * Status and sequential in need no delay.
+	 */
+	switch (command) {
+
+	case NAND_CMD_PAGEPROG:
+	case NAND_CMD_ERASE1:
+	case NAND_CMD_ERASE2:
+	case NAND_CMD_SEQIN:
+	case NAND_CMD_STATUS:
+		return;
+
+	case NAND_CMD_RESET:
+		break;
+
+	case NAND_CMD_READ0:
+	case NAND_CMD_READ1:
+	case NAND_CMD_READOOB:
+		/* Check if we're really driving -CE low (just in case) */
+		if (unlikely(!ce_override))
+			break;
+
+		/* Apply a short delay always to ensure that we do wait tWB. */
+		ndelay(100);
+		/* Wait for a chip to become ready... */
+		for (i = this->chip_delay; !this->dev_ready(mtd) && i > 0; --i)
+			udelay(1);
+
+		/* Release -CE and re-enable interrupts. */
+		au1550_hwcontrol(mtd, NAND_CTL_CLRNCE);
+		local_irq_restore(flags);
+		return;
+	}
+	/* Apply this short delay always to ensure that we do wait tWB. */
+	ndelay(100);
+
+	while(!this->dev_ready(mtd));
+}
+
+
 /*
  * Main initialization routine
  */
-int __init au1xxx_nand_init (void)
+static int __init au1xxx_nand_init(void)
 {
 	struct nand_chip *this;
-	u16 boot_swapboot = 0; /* default value */
+	u16 boot_swapboot = 0;	/* default value */
 	int retval;
 	u32 mem_staddr;
 	u32 nand_phys;
 
 	/* Allocate memory for MTD device structure and private data */
-	au1550_mtd = kmalloc (sizeof(struct mtd_info) +
-			sizeof (struct nand_chip), GFP_KERNEL);
+	au1550_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!au1550_mtd) {
-		printk ("Unable to allocate NAND MTD dev structure.\n");
+		printk("Unable to allocate NAND MTD dev structure.\n");
 		return -ENOMEM;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&au1550_mtd[1]);
+	this = (struct nand_chip *)(&au1550_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(au1550_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	au1550_mtd->priv = this;
+	au1550_mtd->owner = THIS_MODULE;
 
 
-	/* disable interrupts */
-	au_writel(au_readl(MEM_STNDCTL) & ~(1<<8), MEM_STNDCTL);
-
-	/* disable NAND boot */
-	au_writel(au_readl(MEM_STNDCTL) & ~(1<<0), MEM_STNDCTL);
+	/* MEM_STNDCTL: disable ints, disable nand boot */
+	au_writel(0, MEM_STNDCTL);
 
 #ifdef CONFIG_MIPS_PB1550
 	/* set gpio206 high */
-	au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
+	au_writel(au_readl(GPIO2_DIR) & ~(1 << 6), GPIO2_DIR);
 
-	boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
-		((bcsr->status >> 6)  & 0x1);
+	boot_swapboot = (au_readl(MEM_STSTAT) & (0x7 << 1)) | ((bcsr->status >> 6) & 0x1);
 	switch (boot_swapboot) {
-		case 0:
-		case 2:
-		case 8:
-		case 0xC:
-		case 0xD:
-			/* x16 NAND Flash */
-			nand_width = 0;
-			break;
-		case 1:
-		case 9:
-		case 3:
-		case 0xE:
-		case 0xF:
-			/* x8 NAND Flash */
-			nand_width = 1;
-			break;
-		default:
-			printk("Pb1550 NAND: bad boot:swap\n");
-			retval = -EINVAL;
-			goto outmem;
+	case 0:
+	case 2:
+	case 8:
+	case 0xC:
+	case 0xD:
+		/* x16 NAND Flash */
+		nand_width = 0;
+		break;
+	case 1:
+	case 9:
+	case 3:
+	case 0xE:
+	case 0xF:
+		/* x8 NAND Flash */
+		nand_width = 1;
+		break;
+	default:
+		printk("Pb1550 NAND: bad boot:swap\n");
+		retval = -EINVAL;
+		goto outmem;
 	}
 #endif
 
@@ -424,21 +560,22 @@
 
 	/* make controller and MTD agree */
 	if (NAND_CS == 0)
-		nand_width = au_readl(MEM_STCFG0) & (1<<22);
+		nand_width = au_readl(MEM_STCFG0) & (1 << 22);
 	if (NAND_CS == 1)
-		nand_width = au_readl(MEM_STCFG1) & (1<<22);
+		nand_width = au_readl(MEM_STCFG1) & (1 << 22);
 	if (NAND_CS == 2)
-		nand_width = au_readl(MEM_STCFG2) & (1<<22);
+		nand_width = au_readl(MEM_STCFG2) & (1 << 22);
 	if (NAND_CS == 3)
-		nand_width = au_readl(MEM_STCFG3) & (1<<22);
-
+		nand_width = au_readl(MEM_STCFG3) & (1 << 22);
 
 	/* Set address of hardware control function */
-	this->hwcontrol = au1550_hwcontrol;
 	this->dev_ready = au1550_device_ready;
+	this->select_chip = au1550_select_chip;
+	this->cmdfunc = au1550_command;
+
 	/* 30 us command delay time */
 	this->chip_delay = 30;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	this->options = NAND_NO_AUTOINCR;
 
@@ -446,15 +583,14 @@
 		this->options |= NAND_BUSWIDTH_16;
 
 	this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte;
-	this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
-	this->write_word = au_write_word;
+	au1550_write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
 	this->read_word = au_read_word;
 	this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf;
 	this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf;
 	this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
 
 	/* Scan to find existence of the device */
-	if (nand_scan (au1550_mtd, 1)) {
+	if (nand_scan(au1550_mtd, 1)) {
 		retval = -ENXIO;
 		goto outio;
 	}
@@ -465,10 +601,10 @@
 	return 0;
 
  outio:
-	iounmap ((void *)p_nand);
+	iounmap((void *)p_nand);
 
  outmem:
-	kfree (au1550_mtd);
+	kfree(au1550_mtd);
 	return retval;
 }
 
@@ -477,22 +613,21 @@
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit au1550_cleanup (void)
+static void __exit au1550_cleanup(void)
 {
-	struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
+	struct nand_chip *this = (struct nand_chip *)&au1550_mtd[1];
 
 	/* Release resources, unregister device */
-	nand_release (au1550_mtd);
+	nand_release(au1550_mtd);
 
 	/* Free the MTD device structure */
-	kfree (au1550_mtd);
+	kfree(au1550_mtd);
 
 	/* Unmap */
-	iounmap ((void *)p_nand);
+	iounmap((void *)p_nand);
 }
+
 module_exit(au1550_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Embedded Edge, LLC");
diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
index a3c7fea..fe94ae9a 100644
--- a/drivers/mtd/nand/autcpu12.c
+++ b/drivers/mtd/nand/autcpu12.c
@@ -4,7 +4,7 @@
  *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
  *
  *  Derived from drivers/mtd/spia.c
- * 	 Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
+ *	 Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
  *
  * $Id: autcpu12.c,v 1.23 2005/11/07 11:14:30 gleixner Exp $
  *
@@ -42,12 +42,7 @@
  * MTD structure for AUTCPU12 board
  */
 static struct mtd_info *autcpu12_mtd = NULL;
-
-static int autcpu12_io_base = CS89712_VIRT_BASE;
-static int autcpu12_fio_pbase = AUTCPU12_PHYS_SMC;
-static int autcpu12_fio_ctrl = AUTCPU12_SMC_SELECT_OFFSET;
-static int autcpu12_pedr = AUTCPU12_SMC_PORT_OFFSET;
-static void __iomem * autcpu12_fio_base;
+static void __iomem *autcpu12_fio_base;
 
 /*
  * Define partitions for flash devices
@@ -94,108 +89,131 @@
 #define NUM_PARTITIONS128K 2
 /*
  *	hardware specific access to control-lines
-*/
-static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd)
+ *
+ *	ALE bit 4 autcpu12_pedr
+ *	CLE bit 5 autcpu12_pedr
+ *	NCE bit 0 fio_ctrl
+ *
+ */
+static void autcpu12_hwcontrol(struct mtd_info *mtd, int cmd,
+			       unsigned int ctrl)
 {
+	struct nand_chip *chip = mtd->priv;
 
-	switch(cmd){
+	if (ctrl & NAND_CTRL_CHANGE) {
+		void __iomem *addr
+		unsigned char bits;
 
-		case NAND_CTL_SETCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |=  AUTCPU12_SMC_CLE; break;
-		case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_CLE; break;
+		addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
+		bits = (ctrl & NAND_CLE) << 4;
+		bits |= (ctrl & NAND_ALE) << 2;
+		writeb((readb(addr) & ~0x30) | bits, addr);
 
-		case NAND_CTL_SETALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) |=  AUTCPU12_SMC_ALE; break;
-		case NAND_CTL_CLRALE: (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) &= ~AUTCPU12_SMC_ALE; break;
-
-		case NAND_CTL_SETNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x01; break;
-		case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (autcpu12_fio_base + autcpu12_fio_ctrl)) = 0x00; break;
+		addr = autcpu12_fio_base + AUTCPU12_SMC_SELECT_OFFSET;
+		writeb((readb(addr) & ~0x1) | (ctrl & NAND_NCE), addr);
 	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
-*	read device ready pin
-*/
+ *	read device ready pin
+ */
 int autcpu12_device_ready(struct mtd_info *mtd)
 {
+	void __iomem *addr = CS89712_VIRT_BASE + AUTCPU12_SMC_PORT_OFFSET;
 
-	return ( (*(volatile unsigned char *) (autcpu12_io_base + autcpu12_pedr)) & AUTCPU12_SMC_RDY) ? 1 : 0;
-
+	return readb(addr) & AUTCPU12_SMC_RDY;
 }
 
 /*
  * Main initialization routine
  */
-int __init autcpu12_init (void)
+static int __init autcpu12_init(void)
 {
 	struct nand_chip *this;
 	int err = 0;
 
 	/* Allocate memory for MTD device structure and private data */
-	autcpu12_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
-				GFP_KERNEL);
+	autcpu12_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
+			       GFP_KERNEL);
 	if (!autcpu12_mtd) {
-		printk ("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
+		printk("Unable to allocate AUTCPU12 NAND MTD device structure.\n");
 		err = -ENOMEM;
 		goto out;
 	}
 
 	/* map physical adress */
-	autcpu12_fio_base = ioremap(autcpu12_fio_pbase,SZ_1K);
-	if(!autcpu12_fio_base){
+	autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
+	if (!autcpu12_fio_base) {
 		printk("Ioremap autcpu12 SmartMedia Card failed\n");
 		err = -EIO;
 		goto out_mtd;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&autcpu12_mtd[1]);
+	this = (struct nand_chip *)(&autcpu12_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) autcpu12_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(autcpu12_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	autcpu12_mtd->priv = this;
+	autcpu12_mtd->owner = THIS_MODULE;
 
 	/* Set address of NAND IO lines */
 	this->IO_ADDR_R = autcpu12_fio_base;
 	this->IO_ADDR_W = autcpu12_fio_base;
-	this->hwcontrol = autcpu12_hwcontrol;
+	this->cmd_ctrl = autcpu12_hwcontrol;
 	this->dev_ready = autcpu12_device_ready;
 	/* 20 us command delay time */
 	this->chip_delay = 20;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Enable the following for a flash based bad block table */
 	/*
-	this->options = NAND_USE_FLASH_BBT;
-	*/
+	   this->options = NAND_USE_FLASH_BBT;
+	 */
 	this->options = NAND_USE_FLASH_BBT;
 
 	/* Scan to find existance of the device */
-	if (nand_scan (autcpu12_mtd, 1)) {
+	if (nand_scan(autcpu12_mtd, 1)) {
 		err = -ENXIO;
 		goto out_ior;
 	}
 
 	/* Register the partitions */
-	switch(autcpu12_mtd->size){
-		case SZ_16M: add_mtd_partitions(autcpu12_mtd, partition_info16k, NUM_PARTITIONS16K); break;
-		case SZ_32M: add_mtd_partitions(autcpu12_mtd, partition_info32k, NUM_PARTITIONS32K); break;
-		case SZ_64M: add_mtd_partitions(autcpu12_mtd, partition_info64k, NUM_PARTITIONS64K); break;
-		case SZ_128M: add_mtd_partitions(autcpu12_mtd, partition_info128k, NUM_PARTITIONS128K); break;
-		default: {
-			printk ("Unsupported SmartMedia device\n");
+	switch (autcpu12_mtd->size) {
+		case SZ_16M:
+			add_mtd_partitions(autcpu12_mtd, partition_info16k,
+					   NUM_PARTITIONS16K);
+			break;
+		case SZ_32M:
+			add_mtd_partitions(autcpu12_mtd, partition_info32k,
+					   NUM_PARTITIONS32K);
+			break;
+		case SZ_64M:
+			add_mtd_partitions(autcpu12_mtd, partition_info64k,
+					   NUM_PARTITIONS64K);
+			break;
+		case SZ_128M:
+			add_mtd_partitions(autcpu12_mtd, partition_info128k,
+					   NUM_PARTITIONS128K);
+			break;
+		default:
+			printk("Unsupported SmartMedia device\n");
 			err = -ENXIO;
 			goto out_ior;
-		}
 	}
 	goto out;
 
-out_ior:
-	iounmap((void *)autcpu12_fio_base);
-out_mtd:
-	kfree (autcpu12_mtd);
-out:
+ out_ior:
+	iounmap(autcpu12_fio_base);
+ out_mtd:
+	kfree(autcpu12_mtd);
+ out:
 	return err;
 }
 
@@ -204,20 +222,19 @@
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit autcpu12_cleanup (void)
+static void __exit autcpu12_cleanup(void)
 {
 	/* Release resources, unregister device */
-	nand_release (autcpu12_mtd);
+	nand_release(autcpu12_mtd);
 
 	/* unmap physical adress */
-	iounmap((void *)autcpu12_fio_base);
+	iounmap(autcpu12_fio_base);
 
 	/* Free the MTD device structure */
-	kfree (autcpu12_mtd);
+	kfree(autcpu12_mtd);
 }
+
 module_exit(autcpu12_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
new file mode 100644
index 0000000..e0a1d38
--- /dev/null
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -0,0 +1,353 @@
+/*
+ * drivers/mtd/nand/cs553x_nand.c
+ *
+ * (C) 2005, 2006 Red Hat Inc.
+ *
+ * Author: David Woodhouse <dwmw2@infradead.org>
+ *	   Tom Sylla <tom.sylla@amd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Overview:
+ *   This is a device driver for the NAND flash controller found on 
+ *   the AMD CS5535/CS5536 companion chipsets for the Geode processor.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/msr.h>
+#include <asm/io.h>
+
+#define NR_CS553X_CONTROLLERS	4
+
+#define MSR_DIVIL_GLD_CAP	0x51400000	/* DIVIL capabilitiies */
+#define CAP_CS5535		0x2df000ULL
+#define CAP_CS5536		0x5df500ULL
+
+/* NAND Timing MSRs */
+#define MSR_NANDF_DATA		0x5140001b	/* NAND Flash Data Timing MSR */
+#define MSR_NANDF_CTL		0x5140001c	/* NAND Flash Control Timing */
+#define MSR_NANDF_RSVD		0x5140001d	/* Reserved */
+
+/* NAND BAR MSRs */
+#define MSR_DIVIL_LBAR_FLSH0	0x51400010	/* Flash Chip Select 0 */
+#define MSR_DIVIL_LBAR_FLSH1	0x51400011	/* Flash Chip Select 1 */
+#define MSR_DIVIL_LBAR_FLSH2	0x51400012	/* Flash Chip Select 2 */
+#define MSR_DIVIL_LBAR_FLSH3	0x51400013	/* Flash Chip Select 3 */
+	/* Each made up of... */
+#define FLSH_LBAR_EN		(1ULL<<32)
+#define FLSH_NOR_NAND		(1ULL<<33)	/* 1 for NAND */
+#define FLSH_MEM_IO		(1ULL<<34)	/* 1 for MMIO */
+	/* I/O BARs have BASE_ADDR in bits 15:4, IO_MASK in 47:36 */
+	/* MMIO BARs have BASE_ADDR in bits 31:12, MEM_MASK in 63:44 */
+
+/* Pin function selection MSR (IDE vs. flash on the IDE pins) */
+#define MSR_DIVIL_BALL_OPTS	0x51400015
+#define PIN_OPT_IDE		(1<<0)	/* 0 for flash, 1 for IDE */
+
+/* Registers within the NAND flash controller BAR -- memory mapped */
+#define MM_NAND_DATA		0x00	/* 0 to 0x7ff, in fact */
+#define MM_NAND_CTL		0x800	/* Any even address 0x800-0x80e */
+#define MM_NAND_IO		0x801	/* Any odd address 0x801-0x80f */
+#define MM_NAND_STS		0x810
+#define MM_NAND_ECC_LSB		0x811
+#define MM_NAND_ECC_MSB		0x812
+#define MM_NAND_ECC_COL		0x813
+#define MM_NAND_LAC		0x814
+#define MM_NAND_ECC_CTL		0x815
+
+/* Registers within the NAND flash controller BAR -- I/O mapped */
+#define IO_NAND_DATA		0x00	/* 0 to 3, in fact */
+#define IO_NAND_CTL		0x04
+#define IO_NAND_IO		0x05
+#define IO_NAND_STS		0x06
+#define IO_NAND_ECC_CTL		0x08
+#define IO_NAND_ECC_LSB		0x09
+#define IO_NAND_ECC_MSB		0x0a
+#define IO_NAND_ECC_COL		0x0b
+#define IO_NAND_LAC		0x0c
+
+#define CS_NAND_CTL_DIST_EN	(1<<4)	/* Enable NAND Distract interrupt */
+#define CS_NAND_CTL_RDY_INT_MASK	(1<<3)	/* Enable RDY/BUSY# interrupt */
+#define CS_NAND_CTL_ALE		(1<<2)
+#define CS_NAND_CTL_CLE		(1<<1)
+#define CS_NAND_CTL_CE		(1<<0)	/* Keep low; 1 to reset */
+
+#define CS_NAND_STS_FLASH_RDY	(1<<3)
+#define CS_NAND_CTLR_BUSY	(1<<2)
+#define CS_NAND_CMD_COMP	(1<<1)
+#define CS_NAND_DIST_ST		(1<<0)
+
+#define CS_NAND_ECC_PARITY	(1<<2)
+#define CS_NAND_ECC_CLRECC	(1<<1)
+#define CS_NAND_ECC_ENECC	(1<<0)
+
+static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct nand_chip *this = mtd->priv;
+
+	while (unlikely(len > 0x800)) {
+		memcpy_fromio(buf, this->IO_ADDR_R, 0x800);
+		buf += 0x800;
+		len -= 0x800;
+	}
+	memcpy_fromio(buf, this->IO_ADDR_R, len);
+}
+
+static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+	struct nand_chip *this = mtd->priv;
+
+	while (unlikely(len > 0x800)) {
+		memcpy_toio(this->IO_ADDR_R, buf, 0x800);
+		buf += 0x800;
+		len -= 0x800;
+	}
+	memcpy_toio(this->IO_ADDR_R, buf, len);
+}
+
+static unsigned char cs553x_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *this = mtd->priv;
+	return readb(this->IO_ADDR_R);
+}
+
+static void cs553x_write_byte(struct mtd_info *mtd, u_char byte)
+{
+	struct nand_chip *this = mtd->priv;
+	int i = 100000;
+
+	while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) {
+		udelay(1);
+		i--;
+	}
+	writeb(byte, this->IO_ADDR_W + 0x801);
+}
+
+static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd,
+			     unsigned int ctrl)
+{
+	struct nand_chip *this = mtd->priv;
+	void __iomem *mmio_base = this->IO_ADDR_R;
+	if (ctrl & NAND_CTRL_CHANGE) {
+		unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01;
+		writeb(ctl, mmio_base + MM_NAND_CTL);
+	}
+	if (cmd != NAND_CMD_NONE)
+		cs553x_write_byte(mtd, cmd);
+}
+
+static int cs553x_device_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *this = mtd->priv;
+	void __iomem *mmio_base = this->IO_ADDR_R;
+	unsigned char foo = readb(mmio_base + MM_NAND_STS);
+
+	return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY);
+}
+
+static void cs_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	struct nand_chip *this = mtd->priv;
+	void __iomem *mmio_base = this->IO_ADDR_R;
+
+	writeb(0x07, mmio_base + MM_NAND_ECC_CTL);
+}
+
+static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+{
+	uint32_t ecc;
+	struct nand_chip *this = mtd->priv;
+	void __iomem *mmio_base = this->IO_ADDR_R;
+
+	ecc = readl(mmio_base + MM_NAND_STS);
+
+	ecc_code[1] = ecc >> 8;
+	ecc_code[0] = ecc >> 16;
+	ecc_code[2] = ecc >> 24;
+	return 0;
+}
+
+static struct mtd_info *cs553x_mtd[4];
+
+static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
+{
+	int err = 0;
+	struct nand_chip *this;
+	struct mtd_info *new_mtd;
+
+	printk(KERN_NOTICE "Probing CS553x NAND controller CS#%d at %sIO 0x%08lx\n", cs, mmio?"MM":"P", adr);
+
+	if (!mmio) {
+		printk(KERN_NOTICE "PIO mode not yet implemented for CS553X NAND controller\n");
+		return -ENXIO;
+	}
+
+	/* Allocate memory for MTD device structure and private data */
+	new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+	if (!new_mtd) {
+		printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n");
+		err = -ENOMEM;
+		goto out;
+	}
+
+	/* Get pointer to private data */
+	this = (struct nand_chip *)(&new_mtd[1]);
+
+	/* Initialize structures */
+	memset(new_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
+
+	/* Link the private data with the MTD structure */
+	new_mtd->priv = this;
+	new_mtd->owner = THIS_MODULE;
+
+	/* map physical address */
+	this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096);
+	if (!this->IO_ADDR_R) {
+		printk(KERN_WARNING "ioremap cs553x NAND @0x%08lx failed\n", adr);
+		err = -EIO;
+		goto out_mtd;
+	}
+
+	this->cmd_ctrl = cs553x_hwcontrol;
+	this->dev_ready = cs553x_device_ready;
+	this->read_byte = cs553x_read_byte;
+	this->read_buf = cs553x_read_buf;
+	this->write_buf = cs553x_write_buf;
+
+	this->chip_delay = 0;
+
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 256;
+	this->ecc.bytes = 3;
+	this->ecc.hwctl  = cs_enable_hwecc;
+	this->ecc.calculate = cs_calculate_ecc;
+	this->ecc.correct  = nand_correct_data;
+
+	/* Enable the following for a flash based bad block table */
+	this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
+
+	/* Scan to find existance of the device */
+	if (nand_scan(new_mtd, 1)) {
+		err = -ENXIO;
+		goto out_ior;
+	}
+
+	cs553x_mtd[cs] = new_mtd;
+	goto out;
+
+out_ior:
+	iounmap((void *)this->IO_ADDR_R);
+out_mtd:
+	kfree(new_mtd);
+out:
+	return err;
+}
+
+static int is_geode(void)
+{
+	/* These are the CPUs which will have a CS553[56] companion chip */
+	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+	    boot_cpu_data.x86 == 5 &&
+	    boot_cpu_data.x86_model == 10)
+		return 1; /* Geode LX */
+
+	if ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC ||
+	     boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX) &&
+	    boot_cpu_data.x86 == 5 &&
+	    boot_cpu_data.x86_model == 5)
+		return 1; /* Geode GX (née GX2) */
+
+	return 0;
+}
+
+static int __init cs553x_init(void)
+{
+	int err = -ENXIO;
+	int i;
+	uint64_t val;
+
+	/* If the CPU isn't a Geode GX or LX, abort */
+	if (!is_geode())
+		return -ENXIO;
+
+	/* If it doesn't have the CS553[56], abort */
+	rdmsrl(MSR_DIVIL_GLD_CAP, val);
+	val &= ~0xFFULL;
+	if (val != CAP_CS5535 && val != CAP_CS5536)
+		return -ENXIO;
+
+	/* If it doesn't have the NAND controller enabled, abort */
+	rdmsrl(MSR_DIVIL_BALL_OPTS, val);
+	if (val & 1) {
+		printk(KERN_INFO "CS553x NAND controller: Flash I/O not enabled in MSR_DIVIL_BALL_OPTS.\n");
+		return -ENXIO;
+	}
+
+	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+		rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val);
+
+		if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND))
+			err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF);
+	}
+
+	/* Register all devices together here. This means we can easily hack it to 
+	   do mtdconcat etc. if we want to. */
+	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+		if (cs553x_mtd[i]) {
+			add_mtd_device(cs553x_mtd[i]);
+
+			/* If any devices registered, return success. Else the last error. */
+			err = 0;
+		}
+	}
+
+	return err;
+}
+
+module_init(cs553x_init);
+
+static void __exit cs553x_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
+		struct mtd_info *mtd = cs553x_mtd[i];
+		struct nand_chip *this;
+		void __iomem *mmio_base;
+
+		if (!mtd)
+			break;
+
+		this = cs553x_mtd[i]->priv;
+		mmio_base = this->IO_ADDR_R;
+
+		/* Release resources, unregister device */
+		nand_release(cs553x_mtd[i]);
+		cs553x_mtd[i] = NULL;
+
+		/* unmap physical adress */
+		iounmap(mmio_base);
+
+		/* Free the MTD device structure */
+		kfree(mtd);
+	}
+}
+
+module_exit(cs553x_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_DESCRIPTION("NAND controller driver for AMD CS5535/CS5536 companion chip");
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index ec5e45e..6107f53 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -58,10 +58,10 @@
 	0xe4000000,
 #elif defined(CONFIG_MOMENCO_OCELOT)
 	0x2f000000,
-        0xff000000,
+	0xff000000,
 #elif defined(CONFIG_MOMENCO_OCELOT_G) || defined (CONFIG_MOMENCO_OCELOT_C)
-        0xff000000,
-##else
+	0xff000000,
+#else
 #warning Unknown architecture for DiskOnChip. No default probe locations defined
 #endif
 	0xffffffff };
@@ -73,7 +73,7 @@
 	unsigned long physadr;
 	u_char ChipID;
 	u_char CDSNControl;
-	int chips_per_floor; /* The number of chips detected on each floor */
+	int chips_per_floor;	/* The number of chips detected on each floor */
 	int curfloor;
 	int curchip;
 	int mh0_page;
@@ -84,6 +84,7 @@
 /* This is the syndrome computed by the HW ecc generator upon reading an empty
    page, one with all 0xff for data and stored ecc code. */
 static u_char empty_read_syndrome[6] = { 0x26, 0xff, 0x6d, 0x47, 0x73, 0x7a };
+
 /* This is the ecc value computed by the HW ecc generator upon writing an empty
    page, one with all 0xff for data. */
 static u_char empty_write_ecc[6] = { 0x4b, 0x00, 0xe2, 0x0e, 0x93, 0xf7 };
@@ -94,28 +95,29 @@
 #define DoC_is_Millennium(doc) ((doc)->ChipID == DOC_ChipID_DocMil)
 #define DoC_is_2000(doc) ((doc)->ChipID == DOC_ChipID_Doc2k)
 
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd);
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+			      unsigned int bitmask);
 static void doc200x_select_chip(struct mtd_info *mtd, int chip);
 
-static int debug=0;
+static int debug = 0;
 module_param(debug, int, 0);
 
-static int try_dword=1;
+static int try_dword = 1;
 module_param(try_dword, int, 0);
 
-static int no_ecc_failures=0;
+static int no_ecc_failures = 0;
 module_param(no_ecc_failures, int, 0);
 
-static int no_autopart=0;
+static int no_autopart = 0;
 module_param(no_autopart, int, 0);
 
-static int show_firmware_partition=0;
+static int show_firmware_partition = 0;
 module_param(show_firmware_partition, int, 0);
 
 #ifdef MTD_NAND_DISKONCHIP_BBTWRITE
-static int inftl_bbt_write=1;
+static int inftl_bbt_write = 1;
 #else
-static int inftl_bbt_write=0;
+static int inftl_bbt_write = 0;
 #endif
 module_param(inftl_bbt_write, int, 0);
 
@@ -123,7 +125,6 @@
 module_param(doc_config_location, ulong, 0);
 MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChip");
 
-
 /* Sector size for HW ECC */
 #define SECTOR_SIZE 512
 /* The sector bytes are packed into NB_DATA 10 bit words */
@@ -147,7 +148,7 @@
  * some comments, improved a minor bit and converted it to make use
  * of the generic Reed-Solomon libary. tglx
  */
-static int doc_ecc_decode (struct rs_control *rs, uint8_t *data, uint8_t *ecc)
+static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 {
 	int i, j, nerr, errpos[8];
 	uint8_t parity;
@@ -168,18 +169,18 @@
 	 *  s[i] = ds[3]x^3 + ds[2]x^2 + ds[1]x^1 + ds[0]
 	 *  where x = alpha^(FCR + i)
 	 */
-	for(j = 1; j < NROOTS; j++) {
-		if(ds[j] == 0)
+	for (j = 1; j < NROOTS; j++) {
+		if (ds[j] == 0)
 			continue;
 		tmp = rs->index_of[ds[j]];
-		for(i = 0; i < NROOTS; i++)
+		for (i = 0; i < NROOTS; i++)
 			s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)];
 	}
 
 	/* Calc s[i] = s[i] / alpha^(v + i) */
 	for (i = 0; i < NROOTS; i++) {
 		if (syn[i])
- 			syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
+			syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i));
 	}
 	/* Call the decoder library */
 	nerr = decode_rs16(rs, NULL, NULL, 1019, syn, 0, errpos, 0, errval);
@@ -193,7 +194,7 @@
 	 * but they are given by the design of the de/encoder circuit
 	 * in the DoC ASIC's.
 	 */
-	for(i = 0;i < nerr; i++) {
+	for (i = 0; i < nerr; i++) {
 		int index, bitpos, pos = 1015 - errpos[i];
 		uint8_t val;
 		if (pos >= NB_DATA && pos < 1019)
@@ -205,8 +206,7 @@
 			   can be modified since pos is even */
 			index = (pos >> 3) ^ 1;
 			bitpos = pos & 7;
-			if ((index >= 0 && index < SECTOR_SIZE) ||
-			    index == (SECTOR_SIZE + 1)) {
+			if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
 				val = (uint8_t) (errval[i] >> (2 + bitpos));
 				parity ^= val;
 				if (index < SECTOR_SIZE)
@@ -216,9 +216,8 @@
 			bitpos = (bitpos + 10) & 7;
 			if (bitpos == 0)
 				bitpos = 8;
-			if ((index >= 0 && index < SECTOR_SIZE) ||
-			    index == (SECTOR_SIZE + 1)) {
-				val = (uint8_t)(errval[i] << (8 - bitpos));
+			if ((index >= 0 && index < SECTOR_SIZE) || index == (SECTOR_SIZE + 1)) {
+				val = (uint8_t) (errval[i] << (8 - bitpos));
 				parity ^= val;
 				if (index < SECTOR_SIZE)
 					data[index] ^= val;
@@ -250,10 +249,11 @@
 /* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */
 static int _DoC_WaitReady(struct doc_priv *doc)
 {
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	unsigned long timeo = jiffies + (HZ * 10);
 
-	if(debug) printk("_DoC_WaitReady...\n");
+	if (debug)
+		printk("_DoC_WaitReady...\n");
 	/* Out-of-line routine to wait for chip response */
 	if (DoC_is_MillenniumPlus(doc)) {
 		while ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
@@ -280,7 +280,7 @@
 
 static inline int DoC_WaitReady(struct doc_priv *doc)
 {
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int ret = 0;
 
 	if (DoC_is_MillenniumPlus(doc)) {
@@ -298,7 +298,8 @@
 		DoC_Delay(doc, 2);
 	}
 
-	if(debug) printk("DoC_WaitReady OK\n");
+	if (debug)
+		printk("DoC_WaitReady OK\n");
 	return ret;
 }
 
@@ -306,9 +307,10 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
-	if(debug)printk("write_byte %02x\n", datum);
+	if (debug)
+		printk("write_byte %02x\n", datum);
 	WriteDOC(datum, docptr, CDSNSlowIO);
 	WriteDOC(datum, docptr, 2k_CDSN_IO);
 }
@@ -317,77 +319,78 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	u_char ret;
 
 	ReadDOC(docptr, CDSNSlowIO);
 	DoC_Delay(doc, 2);
 	ret = ReadDOC(docptr, 2k_CDSN_IO);
-	if (debug) printk("read_byte returns %02x\n", ret);
+	if (debug)
+		printk("read_byte returns %02x\n", ret);
 	return ret;
 }
 
-static void doc2000_writebuf(struct mtd_info *mtd,
-			     const u_char *buf, int len)
+static void doc2000_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
-	if (debug)printk("writebuf of %d bytes: ", len);
-	for (i=0; i < len; i++) {
+	if (debug)
+		printk("writebuf of %d bytes: ", len);
+	for (i = 0; i < len; i++) {
 		WriteDOC_(buf[i], docptr, DoC_2k_CDSN_IO + i);
 		if (debug && i < 16)
 			printk("%02x ", buf[i]);
 	}
-	if (debug) printk("\n");
+	if (debug)
+		printk("\n");
 }
 
-static void doc2000_readbuf(struct mtd_info *mtd,
-			    u_char *buf, int len)
+static void doc2000_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
- 	int i;
+	void __iomem *docptr = doc->virtadr;
+	int i;
 
-	if (debug)printk("readbuf of %d bytes: ", len);
+	if (debug)
+		printk("readbuf of %d bytes: ", len);
 
-	for (i=0; i < len; i++) {
+	for (i = 0; i < len; i++) {
 		buf[i] = ReadDOC(docptr, 2k_CDSN_IO + i);
 	}
 }
 
-static void doc2000_readbuf_dword(struct mtd_info *mtd,
-			    u_char *buf, int len)
+static void doc2000_readbuf_dword(struct mtd_info *mtd, u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
- 	int i;
+	void __iomem *docptr = doc->virtadr;
+	int i;
 
-	if (debug) printk("readbuf_dword of %d bytes: ", len);
+	if (debug)
+		printk("readbuf_dword of %d bytes: ", len);
 
-	if (unlikely((((unsigned long)buf)|len) & 3)) {
-		for (i=0; i < len; i++) {
-			*(uint8_t *)(&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
+	if (unlikely((((unsigned long)buf) | len) & 3)) {
+		for (i = 0; i < len; i++) {
+			*(uint8_t *) (&buf[i]) = ReadDOC(docptr, 2k_CDSN_IO + i);
 		}
 	} else {
-		for (i=0; i < len; i+=4) {
-			*(uint32_t*)(&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
+		for (i = 0; i < len; i += 4) {
+			*(uint32_t *) (&buf[i]) = readl(docptr + DoC_2k_CDSN_IO + i);
 		}
 	}
 }
 
-static int doc2000_verifybuf(struct mtd_info *mtd,
-			      const u_char *buf, int len)
+static int doc2000_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 
-	for (i=0; i < len; i++)
+	for (i = 0; i < len; i++)
 		if (buf[i] != ReadDOC(docptr, 2k_CDSN_IO))
 			return -EFAULT;
 	return 0;
@@ -400,12 +403,10 @@
 	uint16_t ret;
 
 	doc200x_select_chip(mtd, nr);
-	doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
-	this->write_byte(mtd, NAND_CMD_READID);
-	doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
-	doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
-	this->write_byte(mtd, 0);
-	doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+	doc200x_hwcontrol(mtd, NAND_CMD_READID,
+			  NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+	doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+	doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	/* We cant' use dev_ready here, but at least we wait for the
 	 * command to complete
@@ -423,12 +424,11 @@
 		} ident;
 		void __iomem *docptr = doc->virtadr;
 
-		doc200x_hwcontrol(mtd, NAND_CTL_SETCLE);
-		doc2000_write_byte(mtd, NAND_CMD_READID);
-		doc200x_hwcontrol(mtd, NAND_CTL_CLRCLE);
-		doc200x_hwcontrol(mtd, NAND_CTL_SETALE);
-		doc2000_write_byte(mtd, 0);
-		doc200x_hwcontrol(mtd, NAND_CTL_CLRALE);
+		doc200x_hwcontrol(mtd, NAND_CMD_READID,
+				  NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+		doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
+		doc200x_hwcontrol(mtd, NAND_CMD_NONE,
+				  NAND_NCE | NAND_CTRL_CHANGE);
 
 		udelay(50);
 
@@ -464,7 +464,7 @@
 	printk(KERN_DEBUG "Detected %d chips per floor.\n", i);
 }
 
-static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int doc200x_wait(struct mtd_info *mtd, struct nand_chip *this)
 {
 	struct doc_priv *doc = this->priv;
 
@@ -482,7 +482,7 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 	WriteDOC(datum, docptr, CDSNSlowIO);
 	WriteDOC(datum, docptr, Mil_CDSN_IO);
@@ -493,7 +493,7 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 	//ReadDOC(docptr, CDSNSlowIO);
 	/* 11.4.5 -- delay twice to allow extended length cycle */
@@ -503,50 +503,47 @@
 	return ReadDOC(docptr, LastDataRead);
 }
 
-static void doc2001_writebuf(struct mtd_info *mtd,
-			     const u_char *buf, int len)
+static void doc2001_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 
-	for (i=0; i < len; i++)
+	for (i = 0; i < len; i++)
 		WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
 	/* Terminate write pipeline */
 	WriteDOC(0x00, docptr, WritePipeTerm);
 }
 
-static void doc2001_readbuf(struct mtd_info *mtd,
-			    u_char *buf, int len)
+static void doc2001_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 
 	/* Start read pipeline */
 	ReadDOC(docptr, ReadPipeInit);
 
-	for (i=0; i < len-1; i++)
+	for (i = 0; i < len - 1; i++)
 		buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff));
 
 	/* Terminate read pipeline */
 	buf[i] = ReadDOC(docptr, LastDataRead);
 }
 
-static int doc2001_verifybuf(struct mtd_info *mtd,
-			     const u_char *buf, int len)
+static int doc2001_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 
 	/* Start read pipeline */
 	ReadDOC(docptr, ReadPipeInit);
 
-	for (i=0; i < len-1; i++)
+	for (i = 0; i < len - 1; i++)
 		if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
 			ReadDOC(docptr, LastDataRead);
 			return i;
@@ -560,87 +557,90 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	u_char ret;
 
-        ReadDOC(docptr, Mplus_ReadPipeInit);
-        ReadDOC(docptr, Mplus_ReadPipeInit);
-        ret = ReadDOC(docptr, Mplus_LastDataRead);
-	if (debug) printk("read_byte returns %02x\n", ret);
+	ReadDOC(docptr, Mplus_ReadPipeInit);
+	ReadDOC(docptr, Mplus_ReadPipeInit);
+	ret = ReadDOC(docptr, Mplus_LastDataRead);
+	if (debug)
+		printk("read_byte returns %02x\n", ret);
 	return ret;
 }
 
-static void doc2001plus_writebuf(struct mtd_info *mtd,
-			     const u_char *buf, int len)
+static void doc2001plus_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 
-	if (debug)printk("writebuf of %d bytes: ", len);
-	for (i=0; i < len; i++) {
+	if (debug)
+		printk("writebuf of %d bytes: ", len);
+	for (i = 0; i < len; i++) {
 		WriteDOC_(buf[i], docptr, DoC_Mil_CDSN_IO + i);
 		if (debug && i < 16)
 			printk("%02x ", buf[i]);
 	}
-	if (debug) printk("\n");
+	if (debug)
+		printk("\n");
 }
 
-static void doc2001plus_readbuf(struct mtd_info *mtd,
-			    u_char *buf, int len)
+static void doc2001plus_readbuf(struct mtd_info *mtd, u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 
-	if (debug)printk("readbuf of %d bytes: ", len);
+	if (debug)
+		printk("readbuf of %d bytes: ", len);
 
 	/* Start read pipeline */
 	ReadDOC(docptr, Mplus_ReadPipeInit);
 	ReadDOC(docptr, Mplus_ReadPipeInit);
 
-	for (i=0; i < len-2; i++) {
+	for (i = 0; i < len - 2; i++) {
 		buf[i] = ReadDOC(docptr, Mil_CDSN_IO);
 		if (debug && i < 16)
 			printk("%02x ", buf[i]);
 	}
 
 	/* Terminate read pipeline */
-	buf[len-2] = ReadDOC(docptr, Mplus_LastDataRead);
+	buf[len - 2] = ReadDOC(docptr, Mplus_LastDataRead);
 	if (debug && i < 16)
-		printk("%02x ", buf[len-2]);
-	buf[len-1] = ReadDOC(docptr, Mplus_LastDataRead);
+		printk("%02x ", buf[len - 2]);
+	buf[len - 1] = ReadDOC(docptr, Mplus_LastDataRead);
 	if (debug && i < 16)
-		printk("%02x ", buf[len-1]);
-	if (debug) printk("\n");
+		printk("%02x ", buf[len - 1]);
+	if (debug)
+		printk("\n");
 }
 
-static int doc2001plus_verifybuf(struct mtd_info *mtd,
-			     const u_char *buf, int len)
+static int doc2001plus_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 
-	if (debug)printk("verifybuf of %d bytes: ", len);
+	if (debug)
+		printk("verifybuf of %d bytes: ", len);
 
 	/* Start read pipeline */
 	ReadDOC(docptr, Mplus_ReadPipeInit);
 	ReadDOC(docptr, Mplus_ReadPipeInit);
 
-	for (i=0; i < len-2; i++)
+	for (i = 0; i < len - 2; i++)
 		if (buf[i] != ReadDOC(docptr, Mil_CDSN_IO)) {
 			ReadDOC(docptr, Mplus_LastDataRead);
 			ReadDOC(docptr, Mplus_LastDataRead);
 			return i;
 		}
-	if (buf[len-2] != ReadDOC(docptr, Mplus_LastDataRead))
-		return len-2;
-	if (buf[len-1] != ReadDOC(docptr, Mplus_LastDataRead))
-		return len-1;
+	if (buf[len - 2] != ReadDOC(docptr, Mplus_LastDataRead))
+		return len - 2;
+	if (buf[len - 1] != ReadDOC(docptr, Mplus_LastDataRead))
+		return len - 1;
 	return 0;
 }
 
@@ -648,10 +648,11 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int floor = 0;
 
-	if(debug)printk("select chip (%d)\n", chip);
+	if (debug)
+		printk("select chip (%d)\n", chip);
 
 	if (chip == -1) {
 		/* Disable flash internally */
@@ -660,7 +661,7 @@
 	}
 
 	floor = chip / doc->chips_per_floor;
-	chip -= (floor *  doc->chips_per_floor);
+	chip -= (floor * doc->chips_per_floor);
 
 	/* Assert ChipEnable and deassert WriteProtect */
 	WriteDOC((DOC_FLASH_CE), docptr, Mplus_FlashSelect);
@@ -674,72 +675,61 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int floor = 0;
 
-	if(debug)printk("select chip (%d)\n", chip);
+	if (debug)
+		printk("select chip (%d)\n", chip);
 
 	if (chip == -1)
 		return;
 
 	floor = chip / doc->chips_per_floor;
-	chip -= (floor *  doc->chips_per_floor);
+	chip -= (floor * doc->chips_per_floor);
 
 	/* 11.4.4 -- deassert CE before changing chip */
-	doc200x_hwcontrol(mtd, NAND_CTL_CLRNCE);
+	doc200x_hwcontrol(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
 
 	WriteDOC(floor, docptr, FloorSelect);
 	WriteDOC(chip, docptr, CDSNDeviceSelect);
 
-	doc200x_hwcontrol(mtd, NAND_CTL_SETNCE);
+	doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	doc->curchip = chip;
 	doc->curfloor = floor;
 }
 
-static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd)
+#define CDSN_CTRL_MSK (CDSN_CTRL_CE | CDSN_CTRL_CLE | CDSN_CTRL_ALE)
+
+static void doc200x_hwcontrol(struct mtd_info *mtd, int cmd,
+			      unsigned int ctrl)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
-	switch(cmd) {
-	case NAND_CTL_SETNCE:
-		doc->CDSNControl |= CDSN_CTRL_CE;
-		break;
-	case NAND_CTL_CLRNCE:
-		doc->CDSNControl &= ~CDSN_CTRL_CE;
-		break;
-	case NAND_CTL_SETCLE:
-		doc->CDSNControl |= CDSN_CTRL_CLE;
-		break;
-	case NAND_CTL_CLRCLE:
-		doc->CDSNControl &= ~CDSN_CTRL_CLE;
-		break;
-	case NAND_CTL_SETALE:
-		doc->CDSNControl |= CDSN_CTRL_ALE;
-		break;
-	case NAND_CTL_CLRALE:
-		doc->CDSNControl &= ~CDSN_CTRL_ALE;
-		break;
-	case NAND_CTL_SETWP:
-		doc->CDSNControl |= CDSN_CTRL_WP;
-		break;
-	case NAND_CTL_CLRWP:
-		doc->CDSNControl &= ~CDSN_CTRL_WP;
-		break;
+	if (ctrl & NAND_CTRL_CHANGE) {
+		doc->CDSNControl &= ~CDSN_CTRL_MSK;
+		doc->CDSNControl |= ctrl & CDSN_CTRL_MSK;
+		if (debug)
+			printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
+		WriteDOC(doc->CDSNControl, docptr, CDSNControl);
+		/* 11.4.3 -- 4 NOPs after CSDNControl write */
+		DoC_Delay(doc, 4);
 	}
-	if (debug)printk("hwcontrol(%d): %02x\n", cmd, doc->CDSNControl);
-	WriteDOC(doc->CDSNControl, docptr, CDSNControl);
-	/* 11.4.3 -- 4 NOPs after CSDNControl write */
-	DoC_Delay(doc, 4);
+	if (cmd != NAND_CMD_NONE) {
+		if (DoC_is_2000(doc))
+			doc2000_write_byte(mtd, cmd);
+		else
+			doc2001_write_byte(mtd, cmd);
+	}
 }
 
-static void doc2001plus_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int column, int page_addr)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 	/*
 	 * Must terminate write pipeline before sending any commands
@@ -756,9 +746,9 @@
 	if (command == NAND_CMD_SEQIN) {
 		int readcmd;
 
-		if (column >= mtd->oobblock) {
+		if (column >= mtd->writesize) {
 			/* OOB area */
-			column -= mtd->oobblock;
+			column -= mtd->writesize;
 			readcmd = NAND_CMD_READOOB;
 		} else if (column < 256) {
 			/* First 256 bytes --> READ0 */
@@ -782,25 +772,26 @@
 			WriteDOC(column, docptr, Mplus_FlashAddress);
 		}
 		if (page_addr != -1) {
-			WriteDOC((unsigned char) (page_addr & 0xff), docptr, Mplus_FlashAddress);
-			WriteDOC((unsigned char) ((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
+			WriteDOC((unsigned char)(page_addr & 0xff), docptr, Mplus_FlashAddress);
+			WriteDOC((unsigned char)((page_addr >> 8) & 0xff), docptr, Mplus_FlashAddress);
 			/* One more address cycle for higher density devices */
 			if (this->chipsize & 0x0c000000) {
-				WriteDOC((unsigned char) ((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
+				WriteDOC((unsigned char)((page_addr >> 16) & 0x0f), docptr, Mplus_FlashAddress);
 				printk("high density\n");
 			}
 		}
 		WriteDOC(0, docptr, Mplus_WritePipeTerm);
 		WriteDOC(0, docptr, Mplus_WritePipeTerm);
 		/* deassert ALE */
-		if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 || command == NAND_CMD_READOOB || command == NAND_CMD_READID)
+		if (command == NAND_CMD_READ0 || command == NAND_CMD_READ1 ||
+		    command == NAND_CMD_READOOB || command == NAND_CMD_READID)
 			WriteDOC(0, docptr, Mplus_FlashControl);
 	}
 
 	/*
 	 * program and erase have their own busy handlers
 	 * status and sequential in needs no delay
-	*/
+	 */
 	switch (command) {
 
 	case NAND_CMD_PAGEPROG:
@@ -817,55 +808,57 @@
 		WriteDOC(NAND_CMD_STATUS, docptr, Mplus_FlashCmd);
 		WriteDOC(0, docptr, Mplus_WritePipeTerm);
 		WriteDOC(0, docptr, Mplus_WritePipeTerm);
-		while ( !(this->read_byte(mtd) & 0x40));
+		while (!(this->read_byte(mtd) & 0x40)) ;
 		return;
 
-	/* This applies to read commands */
+		/* This applies to read commands */
 	default:
 		/*
 		 * If we don't have access to the busy pin, we apply the given
 		 * command delay
-		*/
+		 */
 		if (!this->dev_ready) {
-			udelay (this->chip_delay);
+			udelay(this->chip_delay);
 			return;
 		}
 	}
 
 	/* Apply this short delay always to ensure that we do wait tWB in
 	 * any case on any machine. */
-	ndelay (100);
+	ndelay(100);
 	/* wait until command is processed */
-	while (!this->dev_ready(mtd));
+	while (!this->dev_ready(mtd)) ;
 }
 
 static int doc200x_dev_ready(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 	if (DoC_is_MillenniumPlus(doc)) {
 		/* 11.4.2 -- must NOP four times before checking FR/B# */
 		DoC_Delay(doc, 4);
 		if ((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) {
-			if(debug)
+			if (debug)
 				printk("not ready\n");
 			return 0;
 		}
-		if (debug)printk("was ready\n");
+		if (debug)
+			printk("was ready\n");
 		return 1;
 	} else {
 		/* 11.4.2 -- must NOP four times before checking FR/B# */
 		DoC_Delay(doc, 4);
 		if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
-			if(debug)
+			if (debug)
 				printk("not ready\n");
 			return 0;
 		}
 		/* 11.4.2 -- Must NOP twice if it's ready */
 		DoC_Delay(doc, 2);
-		if (debug)printk("was ready\n");
+		if (debug)
+			printk("was ready\n");
 		return 1;
 	}
 }
@@ -881,10 +874,10 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 	/* Prime the ECC engine */
-	switch(mode) {
+	switch (mode) {
 	case NAND_ECC_READ:
 		WriteDOC(DOC_ECC_RESET, docptr, ECCConf);
 		WriteDOC(DOC_ECC_EN, docptr, ECCConf);
@@ -900,10 +893,10 @@
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 
 	/* Prime the ECC engine */
-	switch(mode) {
+	switch (mode) {
 	case NAND_ECC_READ:
 		WriteDOC(DOC_ECC_RESET, docptr, Mplus_ECCConf);
 		WriteDOC(DOC_ECC_EN, docptr, Mplus_ECCConf);
@@ -916,12 +909,11 @@
 }
 
 /* This code is only called on write */
-static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
-				 unsigned char *ecc_code)
+static int doc200x_calculate_ecc(struct mtd_info *mtd, const u_char *dat, unsigned char *ecc_code)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
 	int i;
 	int emptymatch = 1;
 
@@ -961,7 +953,8 @@
 		   often.  It could be optimized away by examining the data in
 		   the writebuf routine, and remembering the result. */
 		for (i = 0; i < 512; i++) {
-			if (dat[i] == 0xff) continue;
+			if (dat[i] == 0xff)
+				continue;
 			emptymatch = 0;
 			break;
 		}
@@ -969,17 +962,20 @@
 	/* If emptymatch still =1, we do have an all-0xff data buffer.
 	   Return all-0xff ecc value instead of the computed one, so
 	   it'll look just like a freshly-erased page. */
-	if (emptymatch) memset(ecc_code, 0xff, 6);
+	if (emptymatch)
+		memset(ecc_code, 0xff, 6);
 #endif
 	return 0;
 }
 
-static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat,
+				u_char *read_ecc, u_char *isnull)
 {
 	int i, ret = 0;
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
-        void __iomem *docptr = doc->virtadr;
+	void __iomem *docptr = doc->virtadr;
+	uint8_t calc_ecc[6];
 	volatile u_char dummy;
 	int emptymatch = 1;
 
@@ -1012,18 +1008,20 @@
 		   all-0xff data and stored ecc block.  Check the stored ecc. */
 		if (emptymatch) {
 			for (i = 0; i < 6; i++) {
-				if (read_ecc[i] == 0xff) continue;
+				if (read_ecc[i] == 0xff)
+					continue;
 				emptymatch = 0;
 				break;
 			}
 		}
 		/* If emptymatch still =1, check the data block. */
 		if (emptymatch) {
-		/* Note: this somewhat expensive test should not be triggered
-		   often.  It could be optimized away by examining the data in
-		   the readbuf routine, and remembering the result. */
+			/* Note: this somewhat expensive test should not be triggered
+			   often.  It could be optimized away by examining the data in
+			   the readbuf routine, and remembering the result. */
 			for (i = 0; i < 512; i++) {
-				if (dat[i] == 0xff) continue;
+				if (dat[i] == 0xff)
+					continue;
 				emptymatch = 0;
 				break;
 			}
@@ -1032,7 +1030,8 @@
 		   erased block, in which case the ECC will not come out right.
 		   We'll suppress the error and tell the caller everything's
 		   OK.  Because it is. */
-		if (!emptymatch) ret = doc_ecc_decode (rs_decoder, dat, calc_ecc);
+		if (!emptymatch)
+			ret = doc_ecc_decode(rs_decoder, dat, calc_ecc);
 		if (ret > 0)
 			printk(KERN_ERR "doc200x_correct_data corrected %d errors\n", ret);
 	}
@@ -1059,11 +1058,10 @@
  * safer.  The only problem with it is that any code that parses oobfree must
  * be able to handle out-of-order segments.
  */
-static struct nand_oobinfo doc200x_oobinfo = {
-        .useecc = MTD_NANDECC_AUTOPLACE,
-        .eccbytes = 6,
-        .eccpos = {0, 1, 2, 3, 4, 5},
-        .oobfree = { {8, 8}, {6, 2} }
+static struct nand_ecclayout doc200x_oobinfo = {
+	.eccbytes = 6,
+	.eccpos = {0, 1, 2, 3, 4, 5},
+	.oobfree = {{8, 8}, {6, 2}}
 };
 
 /* Find the (I)NFTL Media Header, and optionally also the mirror media header.
@@ -1072,8 +1070,7 @@
    either "ANAND" or "BNAND".  If findmirror=1, also look for the mirror media
    header.  The page #s of the found media headers are placed in mh0_page and
    mh1_page in the DOC private structure. */
-static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
-				     const char *id, int findmirror)
+static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, const char *id, int findmirror)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
@@ -1082,17 +1079,19 @@
 	size_t retlen;
 
 	for (offs = 0; offs < mtd->size; offs += mtd->erasesize) {
-		ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
-		if (retlen != mtd->oobblock) continue;
+		ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+		if (retlen != mtd->writesize)
+			continue;
 		if (ret) {
-			printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n",
-				offs);
+			printk(KERN_WARNING "ECC error scanning DOC at 0x%x\n", offs);
 		}
-		if (memcmp(buf, id, 6)) continue;
+		if (memcmp(buf, id, 6))
+			continue;
 		printk(KERN_INFO "Found DiskOnChip %s Media Header at 0x%x\n", id, offs);
 		if (doc->mh0_page == -1) {
 			doc->mh0_page = offs >> this->page_shift;
-			if (!findmirror) return 1;
+			if (!findmirror)
+				return 1;
 			continue;
 		}
 		doc->mh1_page = offs >> this->page_shift;
@@ -1105,8 +1104,8 @@
 	/* Only one mediaheader was found.  We want buf to contain a
 	   mediaheader on return, so we'll have to re-read the one we found. */
 	offs = doc->mh0_page << this->page_shift;
-	ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
-	if (retlen != mtd->oobblock) {
+	ret = mtd->read(mtd, offs, mtd->writesize, &retlen, buf);
+	if (retlen != mtd->writesize) {
 		/* Insanity.  Give up. */
 		printk(KERN_ERR "Read DiskOnChip Media Header once, but can't reread it???\n");
 		return 0;
@@ -1114,8 +1113,7 @@
 	return 1;
 }
 
-static inline int __init nftl_partscan(struct mtd_info *mtd,
-				struct mtd_partition *parts)
+static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
@@ -1127,13 +1125,14 @@
 	unsigned blocks, maxblocks;
 	int offs, numheaders;
 
-	buf = kmalloc(mtd->oobblock, GFP_KERNEL);
+	buf = kmalloc(mtd->writesize, GFP_KERNEL);
 	if (!buf) {
 		printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
 		return 0;
 	}
-	if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) goto out;
-	mh = (struct NFTLMediaHeader *) buf;
+	if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1)))
+		goto out;
+	mh = (struct NFTLMediaHeader *)buf;
 
 	mh->NumEraseUnits = le16_to_cpu(mh->NumEraseUnits);
 	mh->FirstPhysicalEUN = le16_to_cpu(mh->FirstPhysicalEUN);
@@ -1155,8 +1154,8 @@
 		/* Auto-determine UnitSizeFactor.  The constraints are:
 		   - There can be at most 32768 virtual blocks.
 		   - There can be at most (virtual block size - page size)
-		     virtual blocks (because MediaHeader+BBT must fit in 1).
-		*/
+		   virtual blocks (because MediaHeader+BBT must fit in 1).
+		 */
 		mh->UnitSizeFactor = 0xff;
 		while (blocks > maxblocks) {
 			blocks >>= 1;
@@ -1211,14 +1210,13 @@
 	}
 
 	ret = numparts;
-out:
+ out:
 	kfree(buf);
 	return ret;
 }
 
 /* This is a stripped-down copy of the code in inftlmount.c */
-static inline int __init inftl_partscan(struct mtd_info *mtd,
-				 struct mtd_partition *parts)
+static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partition *parts)
 {
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
@@ -1235,15 +1233,16 @@
 	if (inftl_bbt_write)
 		end -= (INFTL_BBT_RESERVED_BLOCKS << this->phys_erase_shift);
 
-	buf = kmalloc(mtd->oobblock, GFP_KERNEL);
+	buf = kmalloc(mtd->writesize, GFP_KERNEL);
 	if (!buf) {
 		printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n");
 		return 0;
 	}
 
-	if (!find_media_headers(mtd, buf, "BNAND", 0)) goto out;
+	if (!find_media_headers(mtd, buf, "BNAND", 0))
+		goto out;
 	doc->mh1_page = doc->mh0_page + (4096 >> this->page_shift);
-	mh = (struct INFTLMediaHeader *) buf;
+	mh = (struct INFTLMediaHeader *)buf;
 
 	mh->NoOfBootImageBlocks = le32_to_cpu(mh->NoOfBootImageBlocks);
 	mh->NoOfBinaryPartitions = le32_to_cpu(mh->NoOfBinaryPartitions);
@@ -1319,8 +1318,10 @@
 		parts[numparts].offset = ip->firstUnit << vshift;
 		parts[numparts].size = (1 + ip->lastUnit - ip->firstUnit) << vshift;
 		numparts++;
-		if (ip->lastUnit > lastvunit) lastvunit = ip->lastUnit;
-		if (ip->flags & INFTL_LAST) break;
+		if (ip->lastUnit > lastvunit)
+			lastvunit = ip->lastUnit;
+		if (ip->flags & INFTL_LAST)
+			break;
 	}
 	lastvunit++;
 	if ((lastvunit << vshift) < end) {
@@ -1330,7 +1331,7 @@
 		numparts++;
 	}
 	ret = numparts;
-out:
+ out:
 	kfree(buf);
 	return ret;
 }
@@ -1342,11 +1343,12 @@
 	struct doc_priv *doc = this->priv;
 	struct mtd_partition parts[2];
 
-	memset((char *) parts, 0, sizeof(parts));
+	memset((char *)parts, 0, sizeof(parts));
 	/* On NFTL, we have to find the media headers before we can read the
 	   BBTs, since they're stored in the media header eraseblocks. */
 	numparts = nftl_partscan(mtd, parts);
-	if (!numparts) return -EIO;
+	if (!numparts)
+		return -EIO;
 	this->bbt_td->options = NAND_BBT_ABSPAGE | NAND_BBT_8BIT |
 				NAND_BBT_SAVECONTENT | NAND_BBT_WRITE |
 				NAND_BBT_VERSION;
@@ -1393,8 +1395,7 @@
 		this->bbt_td->pages[0] = 2;
 		this->bbt_md = NULL;
 	} else {
-		this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
-					NAND_BBT_VERSION;
+		this->bbt_td->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
 		if (inftl_bbt_write)
 			this->bbt_td->options |= NAND_BBT_WRITE;
 		this->bbt_td->offs = 8;
@@ -1404,8 +1405,7 @@
 		this->bbt_td->reserved_block_code = 0x01;
 		this->bbt_td->pattern = "MSYS_BBT";
 
-		this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT |
-					NAND_BBT_VERSION;
+		this->bbt_md->options = NAND_BBT_LASTBLOCK | NAND_BBT_8BIT | NAND_BBT_VERSION;
 		if (inftl_bbt_write)
 			this->bbt_md->options |= NAND_BBT_WRITE;
 		this->bbt_md->offs = 8;
@@ -1420,12 +1420,13 @@
 	   At least as nand_bbt.c is currently written. */
 	if ((ret = nand_scan_bbt(mtd, NULL)))
 		return ret;
-	memset((char *) parts, 0, sizeof(parts));
+	memset((char *)parts, 0, sizeof(parts));
 	numparts = inftl_partscan(mtd, parts);
 	/* At least for now, require the INFTL Media Header.  We could probably
 	   do without it for non-INFTL use, since all it gives us is
 	   autopartitioning, but I want to give it more thought. */
-	if (!numparts) return -EIO;
+	if (!numparts)
+		return -EIO;
 	add_mtd_device(mtd);
 #ifdef CONFIG_MTD_PARTITIONS
 	if (!no_autopart)
@@ -1439,7 +1440,6 @@
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 
-	this->write_byte = doc2000_write_byte;
 	this->read_byte = doc2000_read_byte;
 	this->write_buf = doc2000_writebuf;
 	this->read_buf = doc2000_readbuf;
@@ -1457,7 +1457,6 @@
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 
-	this->write_byte = doc2001_write_byte;
 	this->read_byte = doc2001_read_byte;
 	this->write_buf = doc2001_writebuf;
 	this->read_buf = doc2001_readbuf;
@@ -1489,16 +1488,15 @@
 	struct nand_chip *this = mtd->priv;
 	struct doc_priv *doc = this->priv;
 
-	this->write_byte = NULL;
 	this->read_byte = doc2001plus_read_byte;
 	this->write_buf = doc2001plus_writebuf;
 	this->read_buf = doc2001plus_readbuf;
 	this->verify_buf = doc2001plus_verifybuf;
 	this->scan_bbt = inftl_scan_bbt;
-	this->hwcontrol = NULL;
+	this->cmd_ctrl = NULL;
 	this->select_chip = doc2001plus_select_chip;
 	this->cmdfunc = doc2001plus_command;
-	this->enable_hwecc = doc2001plus_enable_hwecc;
+	this->ecc.hwctl = doc2001plus_enable_hwecc;
 
 	doc->chips_per_floor = 1;
 	mtd->name = "DiskOnChip Millennium Plus";
@@ -1535,20 +1533,16 @@
 	save_control = ReadDOC(virtadr, DOCControl);
 
 	/* Reset the DiskOnChip ASIC */
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
-		 virtadr, DOCControl);
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET,
-		 virtadr, DOCControl);
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, virtadr, DOCControl);
 
 	/* Enable the DiskOnChip ASIC */
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
-		 virtadr, DOCControl);
-	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL,
-		 virtadr, DOCControl);
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
+	WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, virtadr, DOCControl);
 
 	ChipID = ReadDOC(virtadr, ChipID);
 
-	switch(ChipID) {
+	switch (ChipID) {
 	case DOC_ChipID_Doc2k:
 		reg = DoC_2k_ECCStatus;
 		break;
@@ -1564,15 +1558,13 @@
 			ReadDOC(virtadr, Mplus_Power);
 
 		/* Reset the Millennium Plus ASIC */
-		tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
-			DOC_MODE_BDECT;
+		tmp = DOC_MODE_RESET | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
 		WriteDOC(tmp, virtadr, Mplus_DOCControl);
 		WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
 
 		mdelay(1);
 		/* Enable the Millennium Plus ASIC */
-		tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT |
-			DOC_MODE_BDECT;
+		tmp = DOC_MODE_NORMAL | DOC_MODE_MDWREN | DOC_MODE_RST_LAT | DOC_MODE_BDECT;
 		WriteDOC(tmp, virtadr, Mplus_DOCControl);
 		WriteDOC(~tmp, virtadr, Mplus_CtrlConfirm);
 		mdelay(1);
@@ -1596,7 +1588,7 @@
 		goto notfound;
 	}
 	/* Check the TOGGLE bit in the ECC register */
-	tmp  = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
+	tmp = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
 	tmpb = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
 	tmpc = ReadDOC_(virtadr, reg) & DOC_TOGGLE_BIT;
 	if ((tmp == tmpb) || (tmp != tmpc)) {
@@ -1626,11 +1618,11 @@
 		if (ChipID == DOC_ChipID_DocMilPlus16) {
 			WriteDOC(~newval, virtadr, Mplus_AliasResolution);
 			oldval = ReadDOC(doc->virtadr, Mplus_AliasResolution);
-			WriteDOC(newval, virtadr, Mplus_AliasResolution); // restore it
+			WriteDOC(newval, virtadr, Mplus_AliasResolution);	// restore it
 		} else {
 			WriteDOC(~newval, virtadr, AliasResolution);
 			oldval = ReadDOC(doc->virtadr, AliasResolution);
-			WriteDOC(newval, virtadr, AliasResolution); // restore it
+			WriteDOC(newval, virtadr, AliasResolution);	// restore it
 		}
 		newval = ~newval;
 		if (oldval == newval) {
@@ -1642,10 +1634,8 @@
 	printk(KERN_NOTICE "DiskOnChip found at 0x%lx\n", physadr);
 
 	len = sizeof(struct mtd_info) +
-	      sizeof(struct nand_chip) +
-	      sizeof(struct doc_priv) +
-	      (2 * sizeof(struct nand_bbt_descr));
-	mtd =  kmalloc(len, GFP_KERNEL);
+	    sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr));
+	mtd = kmalloc(len, GFP_KERNEL);
 	if (!mtd) {
 		printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len);
 		ret = -ENOMEM;
@@ -1663,17 +1653,19 @@
 
 	nand->priv		= doc;
 	nand->select_chip	= doc200x_select_chip;
-	nand->hwcontrol		= doc200x_hwcontrol;
+	nand->cmd_ctrl		= doc200x_hwcontrol;
 	nand->dev_ready		= doc200x_dev_ready;
 	nand->waitfunc		= doc200x_wait;
 	nand->block_bad		= doc200x_block_bad;
-	nand->enable_hwecc	= doc200x_enable_hwecc;
-	nand->calculate_ecc	= doc200x_calculate_ecc;
-	nand->correct_data	= doc200x_correct_data;
+	nand->ecc.hwctl		= doc200x_enable_hwecc;
+	nand->ecc.calculate	= doc200x_calculate_ecc;
+	nand->ecc.correct	= doc200x_correct_data;
 
-	nand->autooob		= &doc200x_oobinfo;
-	nand->eccmode		= NAND_ECC_HW6_512;
-	nand->options		= NAND_USE_FLASH_BBT | NAND_HWECC_SYNDROME;
+	nand->ecc.layout	= &doc200x_oobinfo;
+	nand->ecc.mode		= NAND_ECC_HW_SYNDROME;
+	nand->ecc.size		= 512;
+	nand->ecc.bytes		= 6;
+	nand->options		= NAND_USE_FLASH_BBT;
 
 	doc->physadr		= physadr;
 	doc->virtadr		= virtadr;
@@ -1707,18 +1699,18 @@
 	doclist = mtd;
 	return 0;
 
-notfound:
+ notfound:
 	/* Put back the contents of the DOCControl register, in case it's not
 	   actually a DiskOnChip.  */
 	WriteDOC(save_control, virtadr, DOCControl);
-fail:
+ fail:
 	iounmap(virtadr);
 	return ret;
 }
 
 static void release_nanddoc(void)
 {
- 	struct mtd_info *mtd, *nextmtd;
+	struct mtd_info *mtd, *nextmtd;
 	struct nand_chip *nand;
 	struct doc_priv *doc;
 
@@ -1747,8 +1739,8 @@
 	 * generator polinomial degree = 4
 	 */
 	rs_decoder = init_rs(10, 0x409, FCR, 1, NROOTS);
- 	if (!rs_decoder) {
-		printk (KERN_ERR "DiskOnChip: Could not create a RS decoder\n");
+	if (!rs_decoder) {
+		printk(KERN_ERR "DiskOnChip: Could not create a RS decoder\n");
 		return -ENOMEM;
 	}
 
@@ -1758,7 +1750,7 @@
 		if (ret < 0)
 			goto outerr;
 	} else {
-		for (i=0; (doc_locations[i] != 0xffffffff); i++) {
+		for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
 			doc_probe(doc_locations[i]);
 		}
 	}
@@ -1770,7 +1762,7 @@
 		goto outerr;
 	}
 	return 0;
-outerr:
+ outerr:
 	free_rs(rs_decoder);
 	return ret;
 }
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 9b1fd2f..516c0e5 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/mtd/nand/edb7312.c
  *
- *  Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
+ *  Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
  *
  *  Derived from drivers/mtd/nand/autcpu12.c
  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
@@ -25,7 +25,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
+#include <asm/arch/hardware.h>	/* for CLPS7111_VIRT_BASE */
 #include <asm/sizes.h>
 #include <asm/hardware/clps7111.h>
 
@@ -54,51 +54,45 @@
  */
 
 static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
-static void __iomem * ep7312_pxdr = (void __iomem *) EP7312_PXDR;
-static void __iomem * ep7312_pxddr = (void __iomem *) EP7312_PXDDR;
+static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
+static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
 
 #ifdef CONFIG_MTD_PARTITIONS
 /*
  * Define static partitions for flash device
  */
 static struct mtd_partition partition_info[] = {
-	{ .name = "EP7312 Nand Flash",
-		  .offset = 0,
-		  .size = 8*1024*1024 }
+	{.name = "EP7312 Nand Flash",
+	 .offset = 0,
+	 .size = 8 * 1024 * 1024}
 };
+
 #define NUM_PARTITIONS 1
 
 #endif
 
-
 /*
  *	hardware specific access to control-lines
+ *
+ *	NAND_NCE: bit 0 -> bit 7
+ *	NAND_CLE: bit 1 -> bit 4
+ *	NAND_ALE: bit 2 -> bit 5
  */
-static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd)
+static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
-	switch(cmd) {
+	struct nand_chip *chip = mtd->priv;
 
-	case NAND_CTL_SETCLE:
-		clps_writeb(clps_readb(ep7312_pxdr) | 0x10, ep7312_pxdr);
-		break;
-	case NAND_CTL_CLRCLE:
-		clps_writeb(clps_readb(ep7312_pxdr) & ~0x10, ep7312_pxdr);
-		break;
+	if (ctrl & NAND_CTRL_CHANGE) {
+		unsigned char bits;
 
-	case NAND_CTL_SETALE:
-		clps_writeb(clps_readb(ep7312_pxdr) | 0x20, ep7312_pxdr);
-		break;
-	case NAND_CTL_CLRALE:
-		clps_writeb(clps_readb(ep7312_pxdr) & ~0x20, ep7312_pxdr);
-		break;
+		bits = (ctrl & (NAND_CLE | NAND_ALE)) << 3;
+		bits = (ctrl & NAND_NCE) << 7;
 
-	case NAND_CTL_SETNCE:
-		clps_writeb((clps_readb(ep7312_pxdr) | 0x80) & ~0x40, ep7312_pxdr);
-		break;
-	case NAND_CTL_CLRNCE:
-		clps_writeb((clps_readb(ep7312_pxdr) | 0x80) | 0x40, ep7312_pxdr);
-		break;
+		clps_writeb((clps_readb(ep7312_pxdr)  & 0xB0) | 0x10,
+			    ep7312_pxdr);
 	}
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
@@ -108,6 +102,7 @@
 {
 	return 1;
 }
+
 #ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
@@ -115,18 +110,16 @@
 /*
  * Main initialization routine
  */
-static int __init ep7312_init (void)
+static int __init ep7312_init(void)
 {
 	struct nand_chip *this;
 	const char *part_type = 0;
 	int mtd_parts_nb = 0;
 	struct mtd_partition *mtd_parts = 0;
-	void __iomem * ep7312_fio_base;
+	void __iomem *ep7312_fio_base;
 
 	/* Allocate memory for MTD device structure and private data */
-	ep7312_mtd = kmalloc(sizeof(struct mtd_info) +
-			     sizeof(struct nand_chip),
-			     GFP_KERNEL);
+	ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!ep7312_mtd) {
 		printk("Unable to allocate EDB7312 NAND MTD device structure.\n");
 		return -ENOMEM;
@@ -134,21 +127,22 @@
 
 	/* map physical adress */
 	ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
-	if(!ep7312_fio_base) {
+	if (!ep7312_fio_base) {
 		printk("ioremap EDB7312 NAND flash failed\n");
 		kfree(ep7312_mtd);
 		return -EIO;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&ep7312_mtd[1]);
+	this = (struct nand_chip *)(&ep7312_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) ep7312_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(ep7312_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	ep7312_mtd->priv = this;
+	ep7312_mtd->owner = THIS_MODULE;
 
 	/*
 	 * Set GPIO Port B control register so that the pins are configured
@@ -159,22 +153,20 @@
 	/* insert callbacks */
 	this->IO_ADDR_R = ep7312_fio_base;
 	this->IO_ADDR_W = ep7312_fio_base;
-	this->hwcontrol = ep7312_hwcontrol;
+	this->cmd_ctrl = ep7312_hwcontrol;
 	this->dev_ready = ep7312_device_ready;
 	/* 15 us command delay time */
 	this->chip_delay = 15;
 
 	/* Scan to find existence of the device */
-	if (nand_scan (ep7312_mtd, 1)) {
+	if (nand_scan(ep7312_mtd, 1)) {
 		iounmap((void *)ep7312_fio_base);
-		kfree (ep7312_mtd);
+		kfree(ep7312_mtd);
 		return -ENXIO;
 	}
-
 #ifdef CONFIG_MTD_PARTITIONS
 	ep7312_mtd->name = "edb7312-nand";
-	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes,
-					    &mtd_parts, 0);
+	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
@@ -193,24 +185,23 @@
 	/* Return happy */
 	return 0;
 }
+
 module_init(ep7312_init);
 
 /*
  * Clean up routine
  */
-static void __exit ep7312_cleanup (void)
+static void __exit ep7312_cleanup(void)
 {
-	struct nand_chip *this = (struct nand_chip *) &ep7312_mtd[1];
+	struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1];
 
 	/* Release resources, unregister device */
-	nand_release (ap7312_mtd);
-
-	/* Free internal data buffer */
-	kfree (this->data_buf);
+	nand_release(ap7312_mtd);
 
 	/* Free the MTD device structure */
-	kfree (ep7312_mtd);
+	kfree(ep7312_mtd);
 }
+
 module_exit(ep7312_cleanup);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index f68f7a9..2d585d2 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -4,7 +4,7 @@
  *  Copyright (C) 2003 Joshua Wise (joshua@joshuawise.com)
  *
  *  Derived from drivers/mtd/nand/edb7312.c
- *       Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
+ *       Copyright (C) 2002 Marius Gröger (mag@sysgo.de)
  *       Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
  *
  * $Id: h1910.c,v 1.6 2005/11/07 11:14:30 gleixner Exp $
@@ -26,7 +26,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <asm/io.h>
-#include <asm/arch/hardware.h> /* for CLPS7111_VIRT_BASE */
+#include <asm/arch/hardware.h>	/* for CLPS7111_VIRT_BASE */
 #include <asm/sizes.h>
 #include <asm/arch/h1900-gpio.h>
 #include <asm/arch/ipaq.h>
@@ -45,47 +45,29 @@
  * Define static partitions for flash device
  */
 static struct mtd_partition partition_info[] = {
-	{ name: "h1910 NAND Flash",
-		  offset: 0,
-		  size: 16*1024*1024 }
+      {name:"h1910 NAND Flash",
+	      offset:0,
+      size:16 * 1024 * 1024}
 };
+
 #define NUM_PARTITIONS 1
 
 #endif
 
-
 /*
  *	hardware specific access to control-lines
+ *
+ *	NAND_NCE: bit 0 - don't care
+ *	NAND_CLE: bit 1 - address bit 2
+ *	NAND_ALE: bit 2 - address bit 3
  */
-static void h1910_hwcontrol(struct mtd_info *mtd, int cmd)
+static void h1910_hwcontrol(struct mtd_info *mtd, int cmd,
+			    unsigned int ctrl)
 {
-	struct nand_chip* this = (struct nand_chip *) (mtd->priv);
+	struct nand_chip *chip = mtd->priv;
 
-	switch(cmd) {
-
-	case NAND_CTL_SETCLE:
-		this->IO_ADDR_R |= (1 << 2);
-		this->IO_ADDR_W |= (1 << 2);
-		break;
-	case NAND_CTL_CLRCLE:
-		this->IO_ADDR_R &= ~(1 << 2);
-		this->IO_ADDR_W &= ~(1 << 2);
-		break;
-
-	case NAND_CTL_SETALE:
-		this->IO_ADDR_R |= (1 << 3);
-		this->IO_ADDR_W |= (1 << 3);
-		break;
-	case NAND_CTL_CLRALE:
-		this->IO_ADDR_R &= ~(1 << 3);
-		this->IO_ADDR_W &= ~(1 << 3);
-		break;
-
-	case NAND_CTL_SETNCE:
-		break;
-	case NAND_CTL_CLRNCE:
-		break;
-	}
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W | ((ctrl & 0x6) << 1));
 }
 
 /*
@@ -101,7 +83,7 @@
 /*
  * Main initialization routine
  */
-static int __init h1910_init (void)
+static int __init h1910_init(void)
 {
 	struct nand_chip *this;
 	const char *part_type = 0;
@@ -119,24 +101,23 @@
 	}
 
 	/* Allocate memory for MTD device structure and private data */
-	h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) +
-			     sizeof(struct nand_chip),
-			     GFP_KERNEL);
+	h1910_nand_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!h1910_nand_mtd) {
 		printk("Unable to allocate h1910 NAND MTD device structure.\n");
-		iounmap ((void *) nandaddr);
+		iounmap((void *)nandaddr);
 		return -ENOMEM;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&h1910_nand_mtd[1]);
+	this = (struct nand_chip *)(&h1910_nand_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) h1910_nand_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(h1910_nand_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	h1910_nand_mtd->priv = this;
+	h1910_nand_mtd->owner = THIS_MODULE;
 
 	/*
 	 * Enable VPEN
@@ -146,31 +127,28 @@
 	/* insert callbacks */
 	this->IO_ADDR_R = nandaddr;
 	this->IO_ADDR_W = nandaddr;
-	this->hwcontrol = h1910_hwcontrol;
+	this->cmd_ctrl = h1910_hwcontrol;
 	this->dev_ready = NULL;	/* unknown whether that was correct or not so we will just do it like this */
 	/* 15 us command delay time */
 	this->chip_delay = 50;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 	this->options = NAND_NO_AUTOINCR;
 
 	/* Scan to find existence of the device */
-	if (nand_scan (h1910_nand_mtd, 1)) {
+	if (nand_scan(h1910_nand_mtd, 1)) {
 		printk(KERN_NOTICE "No NAND device - returning -ENXIO\n");
-		kfree (h1910_nand_mtd);
-		iounmap ((void *) nandaddr);
+		kfree(h1910_nand_mtd);
+		iounmap((void *)nandaddr);
 		return -ENXIO;
 	}
-
 #ifdef CONFIG_MTD_CMDLINE_PARTS
-	mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts,
-						"h1910-nand");
+	mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand");
 	if (mtd_parts_nb > 0)
-	  part_type = "command line";
+		part_type = "command line";
 	else
-	  mtd_parts_nb = 0;
+		mtd_parts_nb = 0;
 #endif
-	if (mtd_parts_nb == 0)
-	{
+	if (mtd_parts_nb == 0) {
 		mtd_parts = partition_info;
 		mtd_parts_nb = NUM_PARTITIONS;
 		part_type = "static";
@@ -183,24 +161,26 @@
 	/* Return happy */
 	return 0;
 }
+
 module_init(h1910_init);
 
 /*
  * Clean up routine
  */
-static void __exit h1910_cleanup (void)
+static void __exit h1910_cleanup(void)
 {
-	struct nand_chip *this = (struct nand_chip *) &h1910_nand_mtd[1];
+	struct nand_chip *this = (struct nand_chip *)&h1910_nand_mtd[1];
 
 	/* Release resources, unregister device */
-	nand_release (h1910_nand_mtd);
+	nand_release(h1910_nand_mtd);
 
 	/* Release io resource */
-	iounmap ((void *) this->IO_ADDR_W);
+	iounmap((void *)this->IO_ADDR_W);
 
 	/* Free the MTD device structure */
-	kfree (h1910_nand_mtd);
+	kfree(h1910_nand_mtd);
 }
+
 module_exit(h1910_cleanup);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 95e96fa..80a7665 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -10,67 +10,31 @@
  *	http://www.linux-mtd.infradead.org/tech/nand.html
  *
  *  Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- * 		  2002 Thomas Gleixner (tglx@linutronix.de)
+ *		  2002-2006 Thomas Gleixner (tglx@linutronix.de)
  *
- *  02-08-2004  tglx: support for strange chips, which cannot auto increment
- *		pages on read / read_oob
- *
- *  03-17-2004  tglx: Check ready before auto increment check. Simon Bayes
- *		pointed this out, as he marked an auto increment capable chip
- *		as NOAUTOINCR in the board driver.
- *		Make reads over block boundaries work too
- *
- *  04-14-2004	tglx: first working version for 2k page size chips
- *
- *  05-19-2004  tglx: Basic support for Renesas AG-AND chips
- *
- *  09-24-2004  tglx: add support for hardware controllers (e.g. ECC) shared
- *		among multiple independend devices. Suggestions and initial patch
- *		from Ben Dooks <ben-mtd@fluff.org>
- *
- *  12-05-2004	dmarlin: add workaround for Renesas AG-AND chips "disturb" issue.
- *		Basically, any block not rewritten may lose data when surrounding blocks
- *		are rewritten many times.  JFFS2 ensures this doesn't happen for blocks
- *		it uses, but the Bad Block Table(s) may not be rewritten.  To ensure they
- *		do not lose data, force them to be rewritten when some of the surrounding
- *		blocks are erased.  Rather than tracking a specific nearby block (which
- *		could itself go bad), use a page address 'mask' to select several blocks
- *		in the same area, and rewrite the BBT when any of them are erased.
- *
- *  01-03-2005	dmarlin: added support for the device recovery command sequence for Renesas
- *		AG-AND chips.  If there was a sudden loss of power during an erase operation,
- * 		a "device recovery" operation must be performed when power is restored
- * 		to ensure correct operation.
- *
- *  01-20-2005	dmarlin: added support for optional hardware specific callback routine to
- *		perform extra error status checks on erase and write failures.  This required
- *		adding a wrapper function for nand_read_ecc.
- *
- * 08-20-2005	vwool: suspend/resume added
- *
- * Credits:
+ *  Credits:
  *	David Woodhouse for adding multichip support
  *
  *	Aleph One Ltd. and Toby Churchill Ltd. for supporting the
  *	rework for 2K page size chips
  *
- * TODO:
+ *  TODO:
  *	Enable cached programming for 2k page size chips
  *	Check, if mtd->ecctype should be set to MTD_ECC_HW
  *	if we have HW ecc support.
  *	The AG-AND chips have nice features for speed improvement,
  *	which are not supported yet. Read / program 4 pages in one go.
  *
- * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool Exp $
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
  */
 
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
+#include <linux/err.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/types.h>
@@ -88,75 +52,46 @@
 #endif
 
 /* Define default oob placement schemes for large and small page devices */
-static struct nand_oobinfo nand_oob_8 = {
-	.useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_8 = {
 	.eccbytes = 3,
 	.eccpos = {0, 1, 2},
-	.oobfree = { {3, 2}, {6, 2} }
+	.oobfree = {
+		{.offset = 3,
+		 .length = 2},
+		{.offset = 6,
+		 .length = 2}}
 };
 
-static struct nand_oobinfo nand_oob_16 = {
-	.useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_16 = {
 	.eccbytes = 6,
 	.eccpos = {0, 1, 2, 3, 6, 7},
-	.oobfree = { {8, 8} }
+	.oobfree = {
+		{.offset = 8,
+		 . length = 8}}
 };
 
-static struct nand_oobinfo nand_oob_64 = {
-	.useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout nand_oob_64 = {
 	.eccbytes = 24,
 	.eccpos = {
-		40, 41, 42, 43, 44, 45, 46, 47,
-		48, 49, 50, 51, 52, 53, 54, 55,
-		56, 57, 58, 59, 60, 61, 62, 63},
-	.oobfree = { {2, 38} }
+		   40, 41, 42, 43, 44, 45, 46, 47,
+		   48, 49, 50, 51, 52, 53, 54, 55,
+		   56, 57, 58, 59, 60, 61, 62, 63},
+	.oobfree = {
+		{.offset = 2,
+		 .length = 38}}
 };
 
-/* This is used for padding purposes in nand_write_oob */
-static u_char ffchars[] = {
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-};
+static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
+			   int new_state);
+
+static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+			     struct mtd_oob_ops *ops);
 
 /*
- * NAND low-level MTD interface functions
+ * For devices which display every fart in the system on a seperate LED. Is
+ * compiled away when LED support is disabled.
  */
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
-
-static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-			  size_t * retlen, u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
-static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
-static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-			   size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel);
-static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char *buf);
-static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
-			unsigned long count, loff_t to, size_t * retlen);
-static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs,
-			unsigned long count, loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
-static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
-static void nand_sync (struct mtd_info *mtd);
-
-/* Some internal functions */
-static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,
-		struct nand_oobinfo *oobsel, int mode);
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
-static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
-	u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode);
-#else
-#define nand_verify_pages(...) (0)
-#endif
-
-static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state);
+DEFINE_LED_TRIGGER(nand_led_trigger);
 
 /**
  * nand_release_device - [GENERIC] release chip
@@ -164,27 +99,19 @@
  *
  * Deselect, release chip lock and wake up anyone waiting on the device
  */
-static void nand_release_device (struct mtd_info *mtd)
+static void nand_release_device(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
 	/* De-select the NAND device */
-	this->select_chip(mtd, -1);
+	chip->select_chip(mtd, -1);
 
-	if (this->controller) {
-		/* Release the controller and the chip */
-		spin_lock(&this->controller->lock);
-		this->controller->active = NULL;
-		this->state = FL_READY;
-		wake_up(&this->controller->wq);
-		spin_unlock(&this->controller->lock);
-	} else {
-		/* Release the chip */
-		spin_lock(&this->chip_lock);
-		this->state = FL_READY;
-		wake_up(&this->wq);
-		spin_unlock(&this->chip_lock);
-	}
+	/* Release the controller and the chip */
+	spin_lock(&chip->controller->lock);
+	chip->controller->active = NULL;
+	chip->state = FL_READY;
+	wake_up(&chip->controller->wq);
+	spin_unlock(&chip->controller->lock);
 }
 
 /**
@@ -193,23 +120,10 @@
  *
  * Default read function for 8bit buswith
  */
-static u_char nand_read_byte(struct mtd_info *mtd)
+static uint8_t nand_read_byte(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
-	return readb(this->IO_ADDR_R);
-}
-
-/**
- * nand_write_byte - [DEFAULT] write one byte to the chip
- * @mtd:	MTD device structure
- * @byte:	pointer to data byte to write
- *
- * Default write function for 8it buswith
- */
-static void nand_write_byte(struct mtd_info *mtd, u_char byte)
-{
-	struct nand_chip *this = mtd->priv;
-	writeb(byte, this->IO_ADDR_W);
+	struct nand_chip *chip = mtd->priv;
+	return readb(chip->IO_ADDR_R);
 }
 
 /**
@@ -219,24 +133,10 @@
  * Default read function for 16bit buswith with
  * endianess conversion
  */
-static u_char nand_read_byte16(struct mtd_info *mtd)
+static uint8_t nand_read_byte16(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
-	return (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
-}
-
-/**
- * nand_write_byte16 - [DEFAULT] write one byte endianess aware to the chip
- * @mtd:	MTD device structure
- * @byte:	pointer to data byte to write
- *
- * Default write function for 16bit buswith with
- * endianess conversion
- */
-static void nand_write_byte16(struct mtd_info *mtd, u_char byte)
-{
-	struct nand_chip *this = mtd->priv;
-	writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
+	struct nand_chip *chip = mtd->priv;
+	return (uint8_t) cpu_to_le16(readw(chip->IO_ADDR_R));
 }
 
 /**
@@ -248,22 +148,8 @@
  */
 static u16 nand_read_word(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
-	return readw(this->IO_ADDR_R);
-}
-
-/**
- * nand_write_word - [DEFAULT] write one word to the chip
- * @mtd:	MTD device structure
- * @word:	data word to write
- *
- * Default write function for 16bit buswith without
- * endianess conversion
- */
-static void nand_write_word(struct mtd_info *mtd, u16 word)
-{
-	struct nand_chip *this = mtd->priv;
-	writew(word, this->IO_ADDR_W);
+	struct nand_chip *chip = mtd->priv;
+	return readw(chip->IO_ADDR_R);
 }
 
 /**
@@ -273,15 +159,15 @@
  *
  * Default select function for 1 chip devices.
  */
-static void nand_select_chip(struct mtd_info *mtd, int chip)
+static void nand_select_chip(struct mtd_info *mtd, int chipnr)
 {
-	struct nand_chip *this = mtd->priv;
-	switch(chip) {
+	struct nand_chip *chip = mtd->priv;
+
+	switch (chipnr) {
 	case -1:
-		this->hwcontrol(mtd, NAND_CTL_CLRNCE);
+		chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
 		break;
 	case 0:
-		this->hwcontrol(mtd, NAND_CTL_SETNCE);
 		break;
 
 	default:
@@ -297,13 +183,13 @@
  *
  * Default write function for 8bit buswith
  */
-static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
-	for (i=0; i<len; i++)
-		writeb(buf[i], this->IO_ADDR_W);
+	for (i = 0; i < len; i++)
+		writeb(buf[i], chip->IO_ADDR_W);
 }
 
 /**
@@ -314,13 +200,13 @@
  *
  * Default read function for 8bit buswith
  */
-static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
-	for (i=0; i<len; i++)
-		buf[i] = readb(this->IO_ADDR_R);
+	for (i = 0; i < len; i++)
+		buf[i] = readb(chip->IO_ADDR_R);
 }
 
 /**
@@ -331,15 +217,14 @@
  *
  * Default verify function for 8bit buswith
  */
-static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
-	for (i=0; i<len; i++)
-		if (buf[i] != readb(this->IO_ADDR_R))
+	for (i = 0; i < len; i++)
+		if (buf[i] != readb(chip->IO_ADDR_R))
 			return -EFAULT;
-
 	return 0;
 }
 
@@ -351,15 +236,15 @@
  *
  * Default write function for 16bit buswith
  */
-static void nand_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
+static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
-	for (i=0; i<len; i++)
-		writew(p[i], this->IO_ADDR_W);
+	for (i = 0; i < len; i++)
+		writew(p[i], chip->IO_ADDR_W);
 
 }
 
@@ -371,15 +256,15 @@
  *
  * Default read function for 16bit buswith
  */
-static void nand_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
+static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
-	for (i=0; i<len; i++)
-		p[i] = readw(this->IO_ADDR_R);
+	for (i = 0; i < len; i++)
+		p[i] = readw(chip->IO_ADDR_R);
 }
 
 /**
@@ -390,15 +275,15 @@
  *
  * Default verify function for 16bit buswith
  */
-static int nand_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
+static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
 	int i;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	u16 *p = (u16 *) buf;
 	len >>= 1;
 
-	for (i=0; i<len; i++)
-		if (p[i] != readw(this->IO_ADDR_R))
+	for (i = 0; i < len; i++)
+		if (p[i] != readw(chip->IO_ADDR_R))
 			return -EFAULT;
 
 	return 0;
@@ -415,38 +300,37 @@
 static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
 {
 	int page, chipnr, res = 0;
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	u16 bad;
 
 	if (getchip) {
-		page = (int)(ofs >> this->page_shift);
-		chipnr = (int)(ofs >> this->chip_shift);
+		page = (int)(ofs >> chip->page_shift);
+		chipnr = (int)(ofs >> chip->chip_shift);
 
-		/* Grab the lock and see if the device is available */
-		nand_get_device (this, mtd, FL_READING);
+		nand_get_device(chip, mtd, FL_READING);
 
 		/* Select the NAND device */
-		this->select_chip(mtd, chipnr);
+		chip->select_chip(mtd, chipnr);
 	} else
-		page = (int) ofs;
+		page = (int)ofs;
 
-	if (this->options & NAND_BUSWIDTH_16) {
-		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos & 0xFE, page & this->pagemask);
-		bad = cpu_to_le16(this->read_word(mtd));
-		if (this->badblockpos & 0x1)
+	if (chip->options & NAND_BUSWIDTH_16) {
+		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos & 0xFE,
+			      page & chip->pagemask);
+		bad = cpu_to_le16(chip->read_word(mtd));
+		if (chip->badblockpos & 0x1)
 			bad >>= 8;
 		if ((bad & 0xFF) != 0xff)
 			res = 1;
 	} else {
-		this->cmdfunc (mtd, NAND_CMD_READOOB, this->badblockpos, page & this->pagemask);
-		if (this->read_byte(mtd) != 0xff)
+		chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
+			      page & chip->pagemask);
+		if (chip->read_byte(mtd) != 0xff)
 			res = 1;
 	}
 
-	if (getchip) {
-		/* Deselect and wake up anyone waiting on the device */
+	if (getchip)
 		nand_release_device(mtd);
-	}
 
 	return res;
 }
@@ -461,23 +345,33 @@
 */
 static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *this = mtd->priv;
-	u_char buf[2] = {0, 0};
-	size_t	retlen;
-	int block;
+	struct nand_chip *chip = mtd->priv;
+	uint8_t buf[2] = { 0, 0 };
+	int block, ret;
 
 	/* Get block number */
-	block = ((int) ofs) >> this->bbt_erase_shift;
-	if (this->bbt)
-		this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
+	block = ((int)ofs) >> chip->bbt_erase_shift;
+	if (chip->bbt)
+		chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1);
 
 	/* Do we have a flash based bad block table ? */
-	if (this->options & NAND_USE_FLASH_BBT)
-		return nand_update_bbt (mtd, ofs);
+	if (chip->options & NAND_USE_FLASH_BBT)
+		ret = nand_update_bbt(mtd, ofs);
+	else {
+		/* We write two bytes, so we dont have to mess with 16 bit
+		 * access
+		 */
+		ofs += mtd->oobsize;
+		chip->ops.len = 2;
+		chip->ops.datbuf = NULL;
+		chip->ops.oobbuf = buf;
+		chip->ops.ooboffs = chip->badblockpos & ~0x01;
 
-	/* We write two bytes, so we dont have to mess with 16 bit access */
-	ofs += mtd->oobsize + (this->badblockpos & ~0x01);
-	return nand_write_oob (mtd, ofs , 2, &retlen, buf);
+		ret = nand_do_write_oob(mtd, ofs, &chip->ops);
+	}
+	if (!ret)
+		mtd->ecc_stats.badblocks++;
+	return ret;
 }
 
 /**
@@ -487,12 +381,12 @@
  *
  * The function expects, that the device is already selected
  */
-static int nand_check_wp (struct mtd_info *mtd)
+static int nand_check_wp(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	/* Check the WP bit */
-	this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
-	return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
+	chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+	return (chip->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1;
 }
 
 /**
@@ -505,32 +399,31 @@
  * Check, if the block is bad. Either by reading the bad block table or
  * calling of the scan function.
  */
-static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt)
+static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
+			       int allowbbt)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
-	if (!this->bbt)
-		return this->block_bad(mtd, ofs, getchip);
+	if (!chip->bbt)
+		return chip->block_bad(mtd, ofs, getchip);
 
 	/* Return info from the table */
-	return nand_isbad_bbt (mtd, ofs, allowbbt);
+	return nand_isbad_bbt(mtd, ofs, allowbbt);
 }
 
-DEFINE_LED_TRIGGER(nand_led_trigger);
-
 /*
  * Wait for the ready pin, after a command
  * The timeout is catched later.
  */
 static void nand_wait_ready(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
-	unsigned long	timeo = jiffies + 2;
+	struct nand_chip *chip = mtd->priv;
+	unsigned long timeo = jiffies + 2;
 
 	led_trigger_event(nand_led_trigger, LED_FULL);
 	/* wait until command is processed or timeout occures */
 	do {
-		if (this->dev_ready(mtd))
+		if (chip->dev_ready(mtd))
 			break;
 		touch_softlockup_watchdog();
 	} while (time_before(jiffies, timeo));
@@ -547,21 +440,21 @@
  * Send command to NAND device. This function is used for small page
  * devices (256/512 Bytes per page)
  */
-static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void nand_command(struct mtd_info *mtd, unsigned int command,
+			 int column, int page_addr)
 {
-	register struct nand_chip *this = mtd->priv;
+	register struct nand_chip *chip = mtd->priv;
+	int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
 
-	/* Begin command latch cycle */
-	this->hwcontrol(mtd, NAND_CTL_SETCLE);
 	/*
 	 * Write out the command to the device.
 	 */
 	if (command == NAND_CMD_SEQIN) {
 		int readcmd;
 
-		if (column >= mtd->oobblock) {
+		if (column >= mtd->writesize) {
 			/* OOB area */
-			column -= mtd->oobblock;
+			column -= mtd->writesize;
 			readcmd = NAND_CMD_READOOB;
 		} else if (column < 256) {
 			/* First 256 bytes --> READ0 */
@@ -570,38 +463,37 @@
 			column -= 256;
 			readcmd = NAND_CMD_READ1;
 		}
-		this->write_byte(mtd, readcmd);
+		chip->cmd_ctrl(mtd, readcmd, ctrl);
+		ctrl &= ~NAND_CTRL_CHANGE;
 	}
-	this->write_byte(mtd, command);
+	chip->cmd_ctrl(mtd, command, ctrl);
 
-	/* Set ALE and clear CLE to start address cycle */
-	this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-
-	if (column != -1 || page_addr != -1) {
-		this->hwcontrol(mtd, NAND_CTL_SETALE);
-
-		/* Serially input address */
-		if (column != -1) {
-			/* Adjust columns for 16 bit buswidth */
-			if (this->options & NAND_BUSWIDTH_16)
-				column >>= 1;
-			this->write_byte(mtd, column);
-		}
-		if (page_addr != -1) {
-			this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
-			this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
-			/* One more address cycle for devices > 32MiB */
-			if (this->chipsize > (32 << 20))
-				this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
-		}
-		/* Latch in address */
-		this->hwcontrol(mtd, NAND_CTL_CLRALE);
+	/*
+	 * Address cycle, when necessary
+	 */
+	ctrl = NAND_CTRL_ALE | NAND_CTRL_CHANGE;
+	/* Serially input address */
+	if (column != -1) {
+		/* Adjust columns for 16 bit buswidth */
+		if (chip->options & NAND_BUSWIDTH_16)
+			column >>= 1;
+		chip->cmd_ctrl(mtd, column, ctrl);
+		ctrl &= ~NAND_CTRL_CHANGE;
 	}
+	if (page_addr != -1) {
+		chip->cmd_ctrl(mtd, page_addr, ctrl);
+		ctrl &= ~NAND_CTRL_CHANGE;
+		chip->cmd_ctrl(mtd, page_addr >> 8, ctrl);
+		/* One more address cycle for devices > 32MiB */
+		if (chip->chipsize > (32 << 20))
+			chip->cmd_ctrl(mtd, page_addr >> 16, ctrl);
+	}
+	chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	/*
 	 * program and erase have their own busy handlers
 	 * status and sequential in needs no delay
-	*/
+	 */
 	switch (command) {
 
 	case NAND_CMD_PAGEPROG:
@@ -612,29 +504,30 @@
 		return;
 
 	case NAND_CMD_RESET:
-		if (this->dev_ready)
+		if (chip->dev_ready)
 			break;
-		udelay(this->chip_delay);
-		this->hwcontrol(mtd, NAND_CTL_SETCLE);
-		this->write_byte(mtd, NAND_CMD_STATUS);
-		this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-		while ( !(this->read_byte(mtd) & NAND_STATUS_READY));
+		udelay(chip->chip_delay);
+		chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
+			       NAND_CTRL_CLE | NAND_CTRL_CHANGE);
+		chip->cmd_ctrl(mtd,
+			       NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
+		while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
 		return;
 
-	/* This applies to read commands */
+		/* This applies to read commands */
 	default:
 		/*
 		 * If we don't have access to the busy pin, we apply the given
 		 * command delay
-		*/
-		if (!this->dev_ready) {
-			udelay (this->chip_delay);
+		 */
+		if (!chip->dev_ready) {
+			udelay(chip->chip_delay);
 			return;
 		}
 	}
 	/* Apply this short delay always to ensure that we do wait tWB in
 	 * any case on any machine. */
-	ndelay (100);
+	ndelay(100);
 
 	nand_wait_ready(mtd);
 }
@@ -646,50 +539,49 @@
  * @column:	the column address for this command, -1 if none
  * @page_addr:	the page address for this command, -1 if none
  *
- * Send command to NAND device. This is the version for the new large page devices
- * We dont have the seperate regions as we have in the small page devices.
- * We must emulate NAND_CMD_READOOB to keep the code compatible.
+ * Send command to NAND device. This is the version for the new large page
+ * devices We dont have the separate regions as we have in the small page
+ * devices.  We must emulate NAND_CMD_READOOB to keep the code compatible.
  *
  */
-static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr)
+static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
+			    int column, int page_addr)
 {
-	register struct nand_chip *this = mtd->priv;
+	register struct nand_chip *chip = mtd->priv;
 
 	/* Emulate NAND_CMD_READOOB */
 	if (command == NAND_CMD_READOOB) {
-		column += mtd->oobblock;
+		column += mtd->writesize;
 		command = NAND_CMD_READ0;
 	}
 
-
-	/* Begin command latch cycle */
-	this->hwcontrol(mtd, NAND_CTL_SETCLE);
-	/* Write out the command to the device. */
-	this->write_byte(mtd, (command & 0xff));
-	/* End command latch cycle */
-	this->hwcontrol(mtd, NAND_CTL_CLRCLE);
+	/* Command latch cycle */
+	chip->cmd_ctrl(mtd, command & 0xff,
+		       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
 
 	if (column != -1 || page_addr != -1) {
-		this->hwcontrol(mtd, NAND_CTL_SETALE);
+		int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE;
 
 		/* Serially input address */
 		if (column != -1) {
 			/* Adjust columns for 16 bit buswidth */
-			if (this->options & NAND_BUSWIDTH_16)
+			if (chip->options & NAND_BUSWIDTH_16)
 				column >>= 1;
-			this->write_byte(mtd, column & 0xff);
-			this->write_byte(mtd, column >> 8);
+			chip->cmd_ctrl(mtd, column, ctrl);
+			ctrl &= ~NAND_CTRL_CHANGE;
+			chip->cmd_ctrl(mtd, column >> 8, ctrl);
 		}
 		if (page_addr != -1) {
-			this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
-			this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
+			chip->cmd_ctrl(mtd, page_addr, ctrl);
+			chip->cmd_ctrl(mtd, page_addr >> 8,
+				       NAND_NCE | NAND_ALE);
 			/* One more address cycle for devices > 128MiB */
-			if (this->chipsize > (128 << 20))
-				this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff));
+			if (chip->chipsize > (128 << 20))
+				chip->cmd_ctrl(mtd, page_addr >> 16,
+					       NAND_NCE | NAND_ALE);
 		}
-		/* Latch in address */
-		this->hwcontrol(mtd, NAND_CTL_CLRALE);
 	}
+	chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
 	/*
 	 * program and erase have their own busy handlers
@@ -702,55 +594,62 @@
 	case NAND_CMD_ERASE1:
 	case NAND_CMD_ERASE2:
 	case NAND_CMD_SEQIN:
+	case NAND_CMD_RNDIN:
 	case NAND_CMD_STATUS:
 	case NAND_CMD_DEPLETE1:
 		return;
 
-	/*
-	 * read error status commands require only a short delay
-	 */
+		/*
+		 * read error status commands require only a short delay
+		 */
 	case NAND_CMD_STATUS_ERROR:
 	case NAND_CMD_STATUS_ERROR0:
 	case NAND_CMD_STATUS_ERROR1:
 	case NAND_CMD_STATUS_ERROR2:
 	case NAND_CMD_STATUS_ERROR3:
-		udelay(this->chip_delay);
+		udelay(chip->chip_delay);
 		return;
 
 	case NAND_CMD_RESET:
-		if (this->dev_ready)
+		if (chip->dev_ready)
 			break;
-		udelay(this->chip_delay);
-		this->hwcontrol(mtd, NAND_CTL_SETCLE);
-		this->write_byte(mtd, NAND_CMD_STATUS);
-		this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-		while ( !(this->read_byte(mtd) & NAND_STATUS_READY));
+		udelay(chip->chip_delay);
+		chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
+			       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+			       NAND_NCE | NAND_CTRL_CHANGE);
+		while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) ;
+		return;
+
+	case NAND_CMD_RNDOUT:
+		/* No ready / busy check necessary */
+		chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
+			       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+			       NAND_NCE | NAND_CTRL_CHANGE);
 		return;
 
 	case NAND_CMD_READ0:
-		/* Begin command latch cycle */
-		this->hwcontrol(mtd, NAND_CTL_SETCLE);
-		/* Write out the start read command */
-		this->write_byte(mtd, NAND_CMD_READSTART);
-		/* End command latch cycle */
-		this->hwcontrol(mtd, NAND_CTL_CLRCLE);
-		/* Fall through into ready check */
+		chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
+			       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
+		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+			       NAND_NCE | NAND_CTRL_CHANGE);
 
-	/* This applies to read commands */
+		/* This applies to read commands */
 	default:
 		/*
 		 * If we don't have access to the busy pin, we apply the given
 		 * command delay
-		*/
-		if (!this->dev_ready) {
-			udelay (this->chip_delay);
+		 */
+		if (!chip->dev_ready) {
+			udelay(chip->chip_delay);
 			return;
 		}
 	}
 
 	/* Apply this short delay always to ensure that we do wait tWB in
 	 * any case on any machine. */
-	ndelay (100);
+	ndelay(100);
 
 	nand_wait_ready(mtd);
 }
@@ -763,34 +662,28 @@
  *
  * Get the device and lock it for exclusive access
  */
-static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state)
+static int
+nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
 {
-	struct nand_chip *active;
-	spinlock_t *lock;
-	wait_queue_head_t *wq;
-	DECLARE_WAITQUEUE (wait, current);
-
-	lock = (this->controller) ? &this->controller->lock : &this->chip_lock;
-	wq = (this->controller) ? &this->controller->wq : &this->wq;
-retry:
-	active = this;
+	spinlock_t *lock = &chip->controller->lock;
+	wait_queue_head_t *wq = &chip->controller->wq;
+	DECLARE_WAITQUEUE(wait, current);
+ retry:
 	spin_lock(lock);
 
 	/* Hardware controller shared among independend devices */
-	if (this->controller) {
-		if (this->controller->active)
-			active = this->controller->active;
-		else
-			this->controller->active = this;
-	}
-	if (active == this && this->state == FL_READY) {
-		this->state = new_state;
+	/* Hardware controller shared among independend devices */
+	if (!chip->controller->active)
+		chip->controller->active = chip;
+
+	if (chip->controller->active == chip && chip->state == FL_READY) {
+		chip->state = new_state;
 		spin_unlock(lock);
 		return 0;
 	}
 	if (new_state == FL_PM_SUSPENDED) {
 		spin_unlock(lock);
-		return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
+		return (chip->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN;
 	}
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	add_wait_queue(wq, &wait);
@@ -804,265 +697,371 @@
  * nand_wait - [DEFAULT]  wait until the command is done
  * @mtd:	MTD device structure
  * @this:	NAND chip structure
- * @state:	state to select the max. timeout value
  *
  * Wait for command done. This applies to erase and program only
  * Erase can take up to 400ms and program up to 20ms according to
  * general NAND and SmartMedia specs
  *
 */
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state)
+static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 {
 
-	unsigned long	timeo = jiffies;
-	int	status;
+	unsigned long timeo = jiffies;
+	int status, state = chip->state;
 
 	if (state == FL_ERASING)
-		 timeo += (HZ * 400) / 1000;
+		timeo += (HZ * 400) / 1000;
 	else
-		 timeo += (HZ * 20) / 1000;
+		timeo += (HZ * 20) / 1000;
 
 	led_trigger_event(nand_led_trigger, LED_FULL);
 
 	/* Apply this short delay always to ensure that we do wait tWB in
 	 * any case on any machine. */
-	ndelay (100);
+	ndelay(100);
 
-	if ((state == FL_ERASING) && (this->options & NAND_IS_AND))
-		this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1);
+	if ((state == FL_ERASING) && (chip->options & NAND_IS_AND))
+		chip->cmdfunc(mtd, NAND_CMD_STATUS_MULTI, -1, -1);
 	else
-		this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1);
+		chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
 
 	while (time_before(jiffies, timeo)) {
-		/* Check, if we were interrupted */
-		if (this->state != state)
-			return 0;
-
-		if (this->dev_ready) {
-			if (this->dev_ready(mtd))
+		if (chip->dev_ready) {
+			if (chip->dev_ready(mtd))
 				break;
 		} else {
-			if (this->read_byte(mtd) & NAND_STATUS_READY)
+			if (chip->read_byte(mtd) & NAND_STATUS_READY)
 				break;
 		}
 		cond_resched();
 	}
 	led_trigger_event(nand_led_trigger, LED_OFF);
 
-	status = (int) this->read_byte(mtd);
+	status = (int)chip->read_byte(mtd);
 	return status;
 }
 
 /**
- * nand_write_page - [GENERIC] write one page
- * @mtd:	MTD device structure
- * @this:	NAND chip structure
- * @page: 	startpage inside the chip, must be called with (page & this->pagemask)
- * @oob_buf:	out of band data buffer
- * @oobsel:	out of band selecttion structre
- * @cached:	1 = enable cached programming if supported by chip
- *
- * Nand_page_program function is used for write and writev !
- * This function will always program a full page of data
- * If you call it with a non page aligned buffer, you're lost :)
- *
- * Cached programming is not supported yet.
+ * nand_read_page_raw - [Intern] read raw page data without ecc
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	buffer to store read data
  */
-static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page,
-	u_char *oob_buf,  struct nand_oobinfo *oobsel, int cached)
+static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+			      uint8_t *buf)
 {
-	int 	i, status;
-	u_char	ecc_code[32];
-	int	eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-	int  	*oob_config = oobsel->eccpos;
-	int	datidx = 0, eccidx = 0, eccsteps = this->eccsteps;
-	int	eccbytes = 0;
+	chip->read_buf(mtd, buf, mtd->writesize);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+	return 0;
+}
 
-	/* FIXME: Enable cached programming */
-	cached = 0;
+/**
+ * nand_read_page_swecc - {REPLACABLE] software ecc based page read function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	buffer to store read data
+ */
+static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
+				uint8_t *buf)
+{
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	uint8_t *ecc_calc = chip->buffers.ecccalc;
+	uint8_t *ecc_code = chip->buffers.ecccode;
+	int *eccpos = chip->ecc.layout->eccpos;
 
-	/* Send command to begin auto page programming */
-	this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page);
+	nand_read_page_raw(mtd, chip, buf);
 
-	/* Write out complete page of data, take care of eccmode */
-	switch (eccmode) {
-	/* No ecc, write all */
-	case NAND_ECC_NONE:
-		printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n");
-		this->write_buf(mtd, this->data_poi, mtd->oobblock);
-		break;
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
-	/* Software ecc 3/256, write all */
-	case NAND_ECC_SOFT:
-		for (; eccsteps; eccsteps--) {
-			this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
-			for (i = 0; i < 3; i++, eccidx++)
-				oob_buf[oob_config[eccidx]] = ecc_code[i];
-			datidx += this->eccsize;
-		}
-		this->write_buf(mtd, this->data_poi, mtd->oobblock);
-		break;
-	default:
-		eccbytes = this->eccbytes;
-		for (; eccsteps; eccsteps--) {
-			/* enable hardware ecc logic for write */
-			this->enable_hwecc(mtd, NAND_ECC_WRITE);
-			this->write_buf(mtd, &this->data_poi[datidx], this->eccsize);
-			this->calculate_ecc(mtd, &this->data_poi[datidx], ecc_code);
-			for (i = 0; i < eccbytes; i++, eccidx++)
-				oob_buf[oob_config[eccidx]] = ecc_code[i];
-			/* If the hardware ecc provides syndromes then
-			 * the ecc code must be written immidiately after
-			 * the data bytes (words) */
-			if (this->options & NAND_HWECC_SYNDROME)
-				this->write_buf(mtd, ecc_code, eccbytes);
-			datidx += this->eccsize;
-		}
-		break;
-	}
+	for (i = 0; i < chip->ecc.total; i++)
+		ecc_code[i] = chip->oob_poi[eccpos[i]];
 
-	/* Write out OOB data */
-	if (this->options & NAND_HWECC_SYNDROME)
-		this->write_buf(mtd, &oob_buf[oobsel->eccbytes], mtd->oobsize - oobsel->eccbytes);
-	else
-		this->write_buf(mtd, oob_buf, mtd->oobsize);
+	eccsteps = chip->ecc.steps;
+	p = buf;
 
-	/* Send command to actually program the data */
-	this->cmdfunc (mtd, cached ? NAND_CMD_CACHEDPROG : NAND_CMD_PAGEPROG, -1, -1);
+	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		int stat;
 
-	if (!cached) {
-		/* call wait ready function */
-		status = this->waitfunc (mtd, this, FL_WRITING);
-
-		/* See if operation failed and additional status checks are available */
-		if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
-			status = this->errstat(mtd, this, FL_WRITING, status, page);
-		}
-
-		/* See if device thinks it succeeded */
-		if (status & NAND_STATUS_FAIL) {
-			DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write, page 0x%08x, ", __FUNCTION__, page);
-			return -EIO;
-		}
-	} else {
-		/* FIXME: Implement cached programming ! */
-		/* wait until cache is ready*/
-		// status = this->waitfunc (mtd, this, FL_CACHEDRPG);
+		stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+		if (stat == -1)
+			mtd->ecc_stats.failed++;
+		else
+			mtd->ecc_stats.corrected += stat;
 	}
 	return 0;
 }
 
-#ifdef CONFIG_MTD_NAND_VERIFY_WRITE
 /**
- * nand_verify_pages - [GENERIC] verify the chip contents after a write
- * @mtd:	MTD device structure
- * @this:	NAND chip structure
- * @page: 	startpage inside the chip, must be called with (page & this->pagemask)
- * @numpages:	number of pages to verify
- * @oob_buf:	out of band data buffer
- * @oobsel:	out of band selecttion structre
- * @chipnr:	number of the current chip
- * @oobmode:	1 = full buffer verify, 0 = ecc only
+ * nand_read_page_hwecc - {REPLACABLE] hardware ecc based page read function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	buffer to store read data
  *
- * The NAND device assumes that it is always writing to a cleanly erased page.
- * Hence, it performs its internal write verification only on bits that
- * transitioned from 1 to 0. The device does NOT verify the whole page on a
- * byte by byte basis. It is possible that the page was not completely erased
- * or the page is becoming unusable due to wear. The read with ECC would catch
- * the error later when the ECC page check fails, but we would rather catch
- * it early in the page write stage. Better to write no data than invalid data.
+ * Not for syndrome calculating ecc controllers which need a special oob layout
  */
-static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int page, int numpages,
-	u_char *oob_buf, struct nand_oobinfo *oobsel, int chipnr, int oobmode)
+static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+				uint8_t *buf)
 {
-	int 	i, j, datidx = 0, oobofs = 0, res = -EIO;
-	int	eccsteps = this->eccsteps;
-	int	hweccbytes;
-	u_char 	oobdata[64];
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	uint8_t *ecc_calc = chip->buffers.ecccalc;
+	uint8_t *ecc_code = chip->buffers.ecccode;
+	int *eccpos = chip->ecc.layout->eccpos;
 
-	hweccbytes = (this->options & NAND_HWECC_SYNDROME) ? (oobsel->eccbytes / eccsteps) : 0;
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		chip->ecc.hwctl(mtd, NAND_ECC_READ);
+		chip->read_buf(mtd, p, eccsize);
+		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+	}
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 
-	/* Send command to read back the first page */
-	this->cmdfunc (mtd, NAND_CMD_READ0, 0, page);
+	for (i = 0; i < chip->ecc.total; i++)
+		ecc_code[i] = chip->oob_poi[eccpos[i]];
 
-	for(;;) {
-		for (j = 0; j < eccsteps; j++) {
-			/* Loop through and verify the data */
-			if (this->verify_buf(mtd, &this->data_poi[datidx], mtd->eccsize)) {
-				DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-				goto out;
-			}
-			datidx += mtd->eccsize;
-			/* Have we a hw generator layout ? */
-			if (!hweccbytes)
-				continue;
-			if (this->verify_buf(mtd, &this->oob_buf[oobofs], hweccbytes)) {
-				DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-				goto out;
-			}
-			oobofs += hweccbytes;
+	eccsteps = chip->ecc.steps;
+	p = buf;
+
+	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		int stat;
+
+		stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
+		if (stat == -1)
+			mtd->ecc_stats.failed++;
+		else
+			mtd->ecc_stats.corrected += stat;
+	}
+	return 0;
+}
+
+/**
+ * nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	buffer to store read data
+ *
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
+ */
+static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+				   uint8_t *buf)
+{
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	uint8_t *oob = chip->oob_poi;
+
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		int stat;
+
+		chip->ecc.hwctl(mtd, NAND_ECC_READ);
+		chip->read_buf(mtd, p, eccsize);
+
+		if (chip->ecc.prepad) {
+			chip->read_buf(mtd, oob, chip->ecc.prepad);
+			oob += chip->ecc.prepad;
 		}
 
-		/* check, if we must compare all data or if we just have to
-		 * compare the ecc bytes
-		 */
-		if (oobmode) {
-			if (this->verify_buf(mtd, &oob_buf[oobofs], mtd->oobsize - hweccbytes * eccsteps)) {
-				DEBUG (MTD_DEBUG_LEVEL0, "%s: " "Failed write verify, page 0x%08x ", __FUNCTION__, page);
-				goto out;
+		chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
+		chip->read_buf(mtd, oob, eccbytes);
+		stat = chip->ecc.correct(mtd, p, oob, NULL);
+
+		if (stat == -1)
+			mtd->ecc_stats.failed++;
+		else
+			mtd->ecc_stats.corrected += stat;
+
+		oob += eccbytes;
+
+		if (chip->ecc.postpad) {
+			chip->read_buf(mtd, oob, chip->ecc.postpad);
+			oob += chip->ecc.postpad;
+		}
+	}
+
+	/* Calculate remaining oob bytes */
+	i = mtd->oobsize - (oob - chip->oob_poi);
+	if (i)
+		chip->read_buf(mtd, oob, i);
+
+	return 0;
+}
+
+/**
+ * nand_transfer_oob - [Internal] Transfer oob to client buffer
+ * @chip:	nand chip structure
+ * @ops:	oob ops structure
+ */
+static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
+				  struct mtd_oob_ops *ops)
+{
+	size_t len = ops->ooblen;
+
+	switch(ops->mode) {
+
+	case MTD_OOB_PLACE:
+	case MTD_OOB_RAW:
+		memcpy(oob, chip->oob_poi + ops->ooboffs, len);
+		return oob + len;
+
+	case MTD_OOB_AUTO: {
+		struct nand_oobfree *free = chip->ecc.layout->oobfree;
+		uint32_t boffs = 0, roffs = ops->ooboffs;
+		size_t bytes = 0;
+
+		for(; free->length && len; free++, len -= bytes) {
+			/* Read request not from offset 0 ? */
+			if (unlikely(roffs)) {
+				if (roffs >= free->length) {
+					roffs -= free->length;
+					continue;
+				}
+				boffs = free->offset + roffs;
+				bytes = min_t(size_t, len,
+					      (free->length - roffs));
+				roffs = 0;
+			} else {
+				bytes = min_t(size_t, len, free->length);
+				boffs = free->offset;
+			}
+			memcpy(oob, chip->oob_poi + boffs, bytes);
+			oob += bytes;
+		}
+		return oob;
+	}
+	default:
+		BUG();
+	}
+	return NULL;
+}
+
+/**
+ * nand_do_read_ops - [Internal] Read data with ECC
+ *
+ * @mtd:	MTD device structure
+ * @from:	offset to read from
+ *
+ * Internal function. Called with chip held.
+ */
+static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
+			    struct mtd_oob_ops *ops)
+{
+	int chipnr, page, realpage, col, bytes, aligned;
+	struct nand_chip *chip = mtd->priv;
+	struct mtd_ecc_stats stats;
+	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+	int sndcmd = 1;
+	int ret = 0;
+	uint32_t readlen = ops->len;
+	uint8_t *bufpoi, *oob, *buf;
+
+	stats = mtd->ecc_stats;
+
+	chipnr = (int)(from >> chip->chip_shift);
+	chip->select_chip(mtd, chipnr);
+
+	realpage = (int)(from >> chip->page_shift);
+	page = realpage & chip->pagemask;
+
+	col = (int)(from & (mtd->writesize - 1));
+	chip->oob_poi = chip->buffers.oobrbuf;
+
+	buf = ops->datbuf;
+	oob = ops->oobbuf;
+
+	while(1) {
+		bytes = min(mtd->writesize - col, readlen);
+		aligned = (bytes == mtd->writesize);
+
+		/* Is the current page in the buffer ? */
+		if (realpage != chip->pagebuf || oob) {
+			bufpoi = aligned ? buf : chip->buffers.databuf;
+
+			if (likely(sndcmd)) {
+				chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+				sndcmd = 0;
+			}
+
+			/* Now read the page into the buffer */
+			ret = chip->ecc.read_page(mtd, chip, bufpoi);
+			if (ret < 0)
+				break;
+
+			/* Transfer not aligned data */
+			if (!aligned) {
+				chip->pagebuf = realpage;
+				memcpy(buf, chip->buffers.databuf + col, bytes);
+			}
+
+			buf += bytes;
+
+			if (unlikely(oob)) {
+				/* Raw mode does data:oob:data:oob */
+				if (ops->mode != MTD_OOB_RAW)
+					oob = nand_transfer_oob(chip, oob, ops);
+				else
+					buf = nand_transfer_oob(chip, buf, ops);
+			}
+
+			if (!(chip->options & NAND_NO_READRDY)) {
+				/*
+				 * Apply delay or wait for ready/busy pin. Do
+				 * this before the AUTOINCR check, so no
+				 * problems arise if a chip which does auto
+				 * increment is marked as NOAUTOINCR by the
+				 * board driver.
+				 */
+				if (!chip->dev_ready)
+					udelay(chip->chip_delay);
+				else
+					nand_wait_ready(mtd);
 			}
 		} else {
-			/* Read always, else autoincrement fails */
-			this->read_buf(mtd, oobdata, mtd->oobsize - hweccbytes * eccsteps);
-
-			if (oobsel->useecc != MTD_NANDECC_OFF && !hweccbytes) {
-				int ecccnt = oobsel->eccbytes;
-
-				for (i = 0; i < ecccnt; i++) {
-					int idx = oobsel->eccpos[i];
-					if (oobdata[idx] != oob_buf[oobofs + idx] ) {
-						DEBUG (MTD_DEBUG_LEVEL0,
-					       	"%s: Failed ECC write "
-						"verify, page 0x%08x, " "%6i bytes were succesful\n", __FUNCTION__, page, i);
-						goto out;
-					}
-				}
-			}
+			memcpy(buf, chip->buffers.databuf + col, bytes);
+			buf += bytes;
 		}
-		oobofs += mtd->oobsize - hweccbytes * eccsteps;
-		page++;
-		numpages--;
 
-		/* Apply delay or wait for ready/busy pin
-		 * Do this before the AUTOINCR check, so no problems
-		 * arise if a chip which does auto increment
-		 * is marked as NOAUTOINCR by the board driver.
-		 * Do this also before returning, so the chip is
-		 * ready for the next command.
-		*/
-		if (!this->dev_ready)
-			udelay (this->chip_delay);
-		else
-			nand_wait_ready(mtd);
+		readlen -= bytes;
 
-		/* All done, return happy */
-		if (!numpages)
-			return 0;
+		if (!readlen)
+			break;
 
+		/* For subsequent reads align to page boundary. */
+		col = 0;
+		/* Increment page address */
+		realpage++;
 
-		/* Check, if the chip supports auto page increment */
-		if (!NAND_CANAUTOINCR(this))
-			this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
+		page = realpage & chip->pagemask;
+		/* Check, if we cross a chip boundary */
+		if (!page) {
+			chipnr++;
+			chip->select_chip(mtd, -1);
+			chip->select_chip(mtd, chipnr);
+		}
+
+		/* Check, if the chip supports auto page increment
+		 * or if we have hit a block boundary.
+		 */
+		if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
+			sndcmd = 1;
 	}
-	/*
-	 * Terminate the read command. We come here in case of an error
-	 * So we must issue a reset command.
-	 */
-out:
-	this->cmdfunc (mtd, NAND_CMD_RESET, -1, -1);
-	return res;
+
+	ops->retlen = ops->len - (size_t) readlen;
+
+	if (ret)
+		return ret;
+
+	if (mtd->ecc_stats.failed - stats.failed)
+		return -EBADMSG;
+
+	return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
-#endif
 
 /**
  * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
@@ -1072,974 +1071,741 @@
  * @retlen:	pointer to variable to store the number of read bytes
  * @buf:	the databuffer to put data
  *
- * This function simply calls nand_do_read_ecc with oob buffer and oobsel = NULL
- * and flags = 0xff
+ * Get hold of the chip and call nand_do_read
  */
-static int nand_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
+		     size_t *retlen, uint8_t *buf)
 {
-	return nand_do_read_ecc (mtd, from, len, retlen, buf, NULL, &mtd->oobinfo, 0xff);
-}
-
-
-/**
- * nand_read_ecc - [MTD Interface] MTD compability function for nand_do_read_ecc
- * @mtd:	MTD device structure
- * @from:	offset to read from
- * @len:	number of bytes to read
- * @retlen:	pointer to variable to store the number of read bytes
- * @buf:	the databuffer to put data
- * @oob_buf:	filesystem supplied oob data buffer
- * @oobsel:	oob selection structure
- *
- * This function simply calls nand_do_read_ecc with flags = 0xff
- */
-static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-			  size_t * retlen, u_char * buf, u_char * oob_buf, struct nand_oobinfo *oobsel)
-{
-	/* use userspace supplied oobinfo, if zero */
-	if (oobsel == NULL)
-		oobsel = &mtd->oobinfo;
-	return nand_do_read_ecc(mtd, from, len, retlen, buf, oob_buf, oobsel, 0xff);
-}
-
-
-/**
- * nand_do_read_ecc - [MTD Interface] Read data with ECC
- * @mtd:	MTD device structure
- * @from:	offset to read from
- * @len:	number of bytes to read
- * @retlen:	pointer to variable to store the number of read bytes
- * @buf:	the databuffer to put data
- * @oob_buf:	filesystem supplied oob data buffer (can be NULL)
- * @oobsel:	oob selection structure
- * @flags:	flag to indicate if nand_get_device/nand_release_device should be preformed
- *		and how many corrected error bits are acceptable:
- *		  bits 0..7 - number of tolerable errors
- *		  bit  8    - 0 == do not get/release chip, 1 == get/release chip
- *
- * NAND read with ECC
- */
-int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-			     size_t * retlen, u_char * buf, u_char * oob_buf,
-			     struct nand_oobinfo *oobsel, int flags)
-{
-
-	int i, j, col, realpage, page, end, ecc, chipnr, sndcmd = 1;
-	int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0;
-	struct nand_chip *this = mtd->priv;
-	u_char *data_poi, *oob_data = oob_buf;
-	u_char ecc_calc[32];
-	u_char ecc_code[32];
-        int eccmode, eccsteps;
-	int	*oob_config, datidx;
-	int	blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
-	int	eccbytes;
-	int	compareecc = 1;
-	int	oobreadlen;
-
-
-	DEBUG (MTD_DEBUG_LEVEL3, "nand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+	struct nand_chip *chip = mtd->priv;
+	int ret;
 
 	/* Do not allow reads past end of device */
-	if ((from + len) > mtd->size) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: Attempt read beyond end of device\n");
-		*retlen = 0;
+	if ((from + len) > mtd->size)
 		return -EINVAL;
-	}
+	if (!len)
+		return 0;
 
-	/* Grab the lock and see if the device is available */
-	if (flags & NAND_GET_DEVICE)
-		nand_get_device (this, mtd, FL_READING);
+	nand_get_device(chip, mtd, FL_READING);
 
-	/* Autoplace of oob data ? Use the default placement scheme */
-	if (oobsel->useecc == MTD_NANDECC_AUTOPLACE)
-		oobsel = this->autooob;
+	chip->ops.len = len;
+	chip->ops.datbuf = buf;
+	chip->ops.oobbuf = NULL;
 
-	eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE;
-	oob_config = oobsel->eccpos;
+	ret = nand_do_read_ops(mtd, from, &chip->ops);
 
-	/* Select the NAND device */
-	chipnr = (int)(from >> this->chip_shift);
-	this->select_chip(mtd, chipnr);
+	nand_release_device(mtd);
 
-	/* First we calculate the starting page */
-	realpage = (int) (from >> this->page_shift);
-	page = realpage & this->pagemask;
-
-	/* Get raw starting column */
-	col = from & (mtd->oobblock - 1);
-
-	end = mtd->oobblock;
-	ecc = this->eccsize;
-	eccbytes = this->eccbytes;
-
-	if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME))
-		compareecc = 0;
-
-	oobreadlen = mtd->oobsize;
-	if (this->options & NAND_HWECC_SYNDROME)
-		oobreadlen -= oobsel->eccbytes;
-
-	/* Loop until all data read */
-	while (read < len) {
-
-		int aligned = (!col && (len - read) >= end);
-		/*
-		 * If the read is not page aligned, we have to read into data buffer
-		 * due to ecc, else we read into return buffer direct
-		 */
-		if (aligned)
-			data_poi = &buf[read];
-		else
-			data_poi = this->data_buf;
-
-		/* Check, if we have this page in the buffer
-		 *
-		 * FIXME: Make it work when we must provide oob data too,
-		 * check the usage of data_buf oob field
-		 */
-		if (realpage == this->pagebuf && !oob_buf) {
-			/* aligned read ? */
-			if (aligned)
-				memcpy (data_poi, this->data_buf, end);
-			goto readdata;
-		}
-
-		/* Check, if we must send the read command */
-		if (sndcmd) {
-			this->cmdfunc (mtd, NAND_CMD_READ0, 0x00, page);
-			sndcmd = 0;
-		}
-
-		/* get oob area, if we have no oob buffer from fs-driver */
-		if (!oob_buf || oobsel->useecc == MTD_NANDECC_AUTOPLACE ||
-			oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
-			oob_data = &this->data_buf[end];
-
-		eccsteps = this->eccsteps;
-
-		switch (eccmode) {
-		case NAND_ECC_NONE: {	/* No ECC, Read in a page */
-			static unsigned long lastwhinge = 0;
-			if ((lastwhinge / HZ) != (jiffies / HZ)) {
-				printk (KERN_WARNING "Reading data from NAND FLASH without ECC is not recommended\n");
-				lastwhinge = jiffies;
-			}
-			this->read_buf(mtd, data_poi, end);
-			break;
-		}
-
-		case NAND_ECC_SOFT:	/* Software ECC 3/256: Read in a page + oob data */
-			this->read_buf(mtd, data_poi, end);
-			for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc)
-				this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
-			break;
-
-		default:
-			for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) {
-				this->enable_hwecc(mtd, NAND_ECC_READ);
-				this->read_buf(mtd, &data_poi[datidx], ecc);
-
-				/* HW ecc with syndrome calculation must read the
-				 * syndrome from flash immidiately after the data */
-				if (!compareecc) {
-					/* Some hw ecc generators need to know when the
-					 * syndrome is read from flash */
-					this->enable_hwecc(mtd, NAND_ECC_READSYN);
-					this->read_buf(mtd, &oob_data[i], eccbytes);
-					/* We calc error correction directly, it checks the hw
-					 * generator for an error, reads back the syndrome and
-					 * does the error correction on the fly */
-					ecc_status = this->correct_data(mtd, &data_poi[datidx], &oob_data[i], &ecc_code[i]);
-					if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
-						DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: "
-							"Failed ECC read, page 0x%08x on chip %d\n", page, chipnr);
-						ecc_failed++;
-					}
-				} else {
-					this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]);
-				}
-			}
-			break;
-		}
-
-		/* read oobdata */
-		this->read_buf(mtd, &oob_data[mtd->oobsize - oobreadlen], oobreadlen);
-
-		/* Skip ECC check, if not requested (ECC_NONE or HW_ECC with syndromes) */
-		if (!compareecc)
-			goto readoob;
-
-		/* Pick the ECC bytes out of the oob data */
-		for (j = 0; j < oobsel->eccbytes; j++)
-			ecc_code[j] = oob_data[oob_config[j]];
-
-		/* correct data, if neccecary */
-		for (i = 0, j = 0, datidx = 0; i < this->eccsteps; i++, datidx += ecc) {
-			ecc_status = this->correct_data(mtd, &data_poi[datidx], &ecc_code[j], &ecc_calc[j]);
-
-			/* Get next chunk of ecc bytes */
-			j += eccbytes;
-
-			/* Check, if we have a fs supplied oob-buffer,
-			 * This is the legacy mode. Used by YAFFS1
-			 * Should go away some day
-			 */
-			if (oob_buf && oobsel->useecc == MTD_NANDECC_PLACE) {
-				int *p = (int *)(&oob_data[mtd->oobsize]);
-				p[i] = ecc_status;
-			}
-
-			if ((ecc_status == -1) || (ecc_status > (flags && 0xff))) {
-				DEBUG (MTD_DEBUG_LEVEL0, "nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page);
-				ecc_failed++;
-			}
-		}
-
-	readoob:
-		/* check, if we have a fs supplied oob-buffer */
-		if (oob_buf) {
-			/* without autoplace. Legacy mode used by YAFFS1 */
-			switch(oobsel->useecc) {
-			case MTD_NANDECC_AUTOPLACE:
-			case MTD_NANDECC_AUTOPL_USR:
-				/* Walk through the autoplace chunks */
-				for (i = 0; oobsel->oobfree[i][1]; i++) {
-					int from = oobsel->oobfree[i][0];
-					int num = oobsel->oobfree[i][1];
-					memcpy(&oob_buf[oob], &oob_data[from], num);
-					oob += num;
-				}
-				break;
-			case MTD_NANDECC_PLACE:
-				/* YAFFS1 legacy mode */
-				oob_data += this->eccsteps * sizeof (int);
-			default:
-				oob_data += mtd->oobsize;
-			}
-		}
-	readdata:
-		/* Partial page read, transfer data into fs buffer */
-		if (!aligned) {
-			for (j = col; j < end && read < len; j++)
-				buf[read++] = data_poi[j];
-			this->pagebuf = realpage;
-		} else
-			read += mtd->oobblock;
-
-		/* Apply delay or wait for ready/busy pin
-		 * Do this before the AUTOINCR check, so no problems
-		 * arise if a chip which does auto increment
-		 * is marked as NOAUTOINCR by the board driver.
-		*/
-		if (!this->dev_ready)
-			udelay (this->chip_delay);
-		else
-			nand_wait_ready(mtd);
-
-		if (read == len)
-			break;
-
-		/* For subsequent reads align to page boundary. */
-		col = 0;
-		/* Increment page address */
-		realpage++;
-
-		page = realpage & this->pagemask;
-		/* Check, if we cross a chip boundary */
-		if (!page) {
-			chipnr++;
-			this->select_chip(mtd, -1);
-			this->select_chip(mtd, chipnr);
-		}
-		/* Check, if the chip supports auto page increment
-		 * or if we have hit a block boundary.
-		*/
-		if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
-			sndcmd = 1;
-	}
-
-	/* Deselect and wake up anyone waiting on the device */
-	if (flags & NAND_GET_DEVICE)
-		nand_release_device(mtd);
-
-	/*
-	 * Return success, if no ECC failures, else -EBADMSG
-	 * fs driver will take care of that, because
-	 * retlen == desired len and result == -EBADMSG
-	 */
-	*retlen = read;
-	return ecc_failed ? -EBADMSG : 0;
+	*retlen = chip->ops.retlen;
+	return ret;
 }
 
 /**
- * nand_read_oob - [MTD Interface] NAND read out-of-band
+ * nand_read_oob_std - [REPLACABLE] the most common OOB data read function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @page:	page number to read
+ * @sndcmd:	flag whether to issue read command or not
+ */
+static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
+			     int page, int sndcmd)
+{
+	if (sndcmd) {
+		chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+		sndcmd = 0;
+	}
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+	return sndcmd;
+}
+
+/**
+ * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
+ *			    with syndromes
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @page:	page number to read
+ * @sndcmd:	flag whether to issue read command or not
+ */
+static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+				  int page, int sndcmd)
+{
+	uint8_t *buf = chip->oob_poi;
+	int length = mtd->oobsize;
+	int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+	int eccsize = chip->ecc.size;
+	uint8_t *bufpoi = buf;
+	int i, toread, sndrnd = 0, pos;
+
+	chip->cmdfunc(mtd, NAND_CMD_READ0, chip->ecc.size, page);
+	for (i = 0; i < chip->ecc.steps; i++) {
+		if (sndrnd) {
+			pos = eccsize + i * (eccsize + chunk);
+			if (mtd->writesize > 512)
+				chip->cmdfunc(mtd, NAND_CMD_RNDOUT, pos, -1);
+			else
+				chip->cmdfunc(mtd, NAND_CMD_READ0, pos, page);
+		} else
+			sndrnd = 1;
+		toread = min_t(int, length, chunk);
+		chip->read_buf(mtd, bufpoi, toread);
+		bufpoi += toread;
+		length -= toread;
+	}
+	if (length > 0)
+		chip->read_buf(mtd, bufpoi, length);
+
+	return 1;
+}
+
+/**
+ * nand_write_oob_std - [REPLACABLE] the most common OOB data write function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @page:	page number to write
+ */
+static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
+			      int page)
+{
+	int status = 0;
+	const uint8_t *buf = chip->oob_poi;
+	int length = mtd->oobsize;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	chip->write_buf(mtd, buf, length);
+	/* Send command to program the OOB data */
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	status = chip->waitfunc(mtd, chip);
+
+	return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
+
+/**
+ * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
+ *			     with syndrome - only for large page flash !
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @page:	page number to write
+ */
+static int nand_write_oob_syndrome(struct mtd_info *mtd,
+				   struct nand_chip *chip, int page)
+{
+	int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+	int eccsize = chip->ecc.size, length = mtd->oobsize;
+	int i, len, pos, status = 0, sndcmd = 0, steps = chip->ecc.steps;
+	const uint8_t *bufpoi = chip->oob_poi;
+
+	/*
+	 * data-ecc-data-ecc ... ecc-oob
+	 * or
+	 * data-pad-ecc-pad-data-pad .... ecc-pad-oob
+	 */
+	if (!chip->ecc.prepad && !chip->ecc.postpad) {
+		pos = steps * (eccsize + chunk);
+		steps = 0;
+	} else
+		pos = eccsize + chunk;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
+	for (i = 0; i < steps; i++) {
+		if (sndcmd) {
+			if (mtd->writesize <= 512) {
+				uint32_t fill = 0xFFFFFFFF;
+
+				len = eccsize;
+				while (len > 0) {
+					int num = min_t(int, len, 4);
+					chip->write_buf(mtd, (uint8_t *)&fill,
+							num);
+					len -= num;
+				}
+			} else {
+				pos = eccsize + i * (eccsize + chunk);
+				chip->cmdfunc(mtd, NAND_CMD_RNDIN, pos, -1);
+			}
+		} else
+			sndcmd = 1;
+		len = min_t(int, length, chunk);
+		chip->write_buf(mtd, bufpoi, len);
+		bufpoi += len;
+		length -= len;
+	}
+	if (length > 0)
+		chip->write_buf(mtd, bufpoi, length);
+
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+	status = chip->waitfunc(mtd, chip);
+
+	return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
+
+/**
+ * nand_do_read_oob - [Intern] NAND read out-of-band
  * @mtd:	MTD device structure
  * @from:	offset to read from
- * @len:	number of bytes to read
- * @retlen:	pointer to variable to store the number of read bytes
- * @buf:	the databuffer to put data
+ * @ops:	oob operations description structure
  *
  * NAND read out-of-band data from the spare area
  */
-static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
+			    struct mtd_oob_ops *ops)
 {
-	int i, col, page, chipnr;
-	struct nand_chip *this = mtd->priv;
-	int	blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
+	int page, realpage, chipnr, sndcmd = 1;
+	struct nand_chip *chip = mtd->priv;
+	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+	int readlen = ops->len;
+	uint8_t *buf = ops->oobbuf;
 
-	DEBUG (MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "nand_read_oob: from = 0x%08Lx, len = %i\n",
+	      (unsigned long long)from, readlen);
+
+	chipnr = (int)(from >> chip->chip_shift);
+	chip->select_chip(mtd, chipnr);
 
 	/* Shift to get page */
-	page = (int)(from >> this->page_shift);
-	chipnr = (int)(from >> this->chip_shift);
+	realpage = (int)(from >> chip->page_shift);
+	page = realpage & chip->pagemask;
 
-	/* Mask to get column */
-	col = from & (mtd->oobsize - 1);
+	chip->oob_poi = chip->buffers.oobrbuf;
 
-	/* Initialize return length value */
-	*retlen = 0;
+	while(1) {
+		sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd);
+		buf = nand_transfer_oob(chip, buf, ops);
 
-	/* Do not allow reads past end of device */
-	if ((from + len) > mtd->size) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_read_oob: Attempt read beyond end of device\n");
-		*retlen = 0;
-		return -EINVAL;
-	}
-
-	/* Grab the lock and see if the device is available */
-	nand_get_device (this, mtd , FL_READING);
-
-	/* Select the NAND device */
-	this->select_chip(mtd, chipnr);
-
-	/* Send the read command */
-	this->cmdfunc (mtd, NAND_CMD_READOOB, col, page & this->pagemask);
-	/*
-	 * Read the data, if we read more than one page
-	 * oob data, let the device transfer the data !
-	 */
-	i = 0;
-	while (i < len) {
-		int thislen = mtd->oobsize - col;
-		thislen = min_t(int, thislen, len);
-		this->read_buf(mtd, &buf[i], thislen);
-		i += thislen;
-
-		/* Read more ? */
-		if (i < len) {
-			page++;
-			col = 0;
-
-			/* Check, if we cross a chip boundary */
-			if (!(page & this->pagemask)) {
-				chipnr++;
-				this->select_chip(mtd, -1);
-				this->select_chip(mtd, chipnr);
-			}
-
-			/* Apply delay or wait for ready/busy pin
-			 * Do this before the AUTOINCR check, so no problems
-			 * arise if a chip which does auto increment
-			 * is marked as NOAUTOINCR by the board driver.
+		if (!(chip->options & NAND_NO_READRDY)) {
+			/*
+			 * Apply delay or wait for ready/busy pin. Do this
+			 * before the AUTOINCR check, so no problems arise if a
+			 * chip which does auto increment is marked as
+			 * NOAUTOINCR by the board driver.
 			 */
-			if (!this->dev_ready)
-				udelay (this->chip_delay);
+			if (!chip->dev_ready)
+				udelay(chip->chip_delay);
 			else
 				nand_wait_ready(mtd);
-
-			/* Check, if the chip supports auto page increment
-			 * or if we have hit a block boundary.
-			*/
-			if (!NAND_CANAUTOINCR(this) || !(page & blockcheck)) {
-				/* For subsequent page reads set offset to 0 */
-			        this->cmdfunc (mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
-			}
 		}
-	}
 
-	/* Deselect and wake up anyone waiting on the device */
-	nand_release_device(mtd);
+		readlen -= ops->ooblen;
+		if (!readlen)
+			break;
 
-	/* Return happy */
-	*retlen = len;
-	return 0;
-}
+		/* Increment page address */
+		realpage++;
 
-/**
- * nand_read_raw - [GENERIC] Read raw data including oob into buffer
- * @mtd:	MTD device structure
- * @buf:	temporary buffer
- * @from:	offset to read from
- * @len:	number of bytes to read
- * @ooblen:	number of oob data bytes to read
- *
- * Read raw data including oob into buffer
- */
-int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen)
-{
-	struct nand_chip *this = mtd->priv;
-	int page = (int) (from >> this->page_shift);
-	int chip = (int) (from >> this->chip_shift);
-	int sndcmd = 1;
-	int cnt = 0;
-	int pagesize = mtd->oobblock + mtd->oobsize;
-	int	blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1;
+		page = realpage & chip->pagemask;
+		/* Check, if we cross a chip boundary */
+		if (!page) {
+			chipnr++;
+			chip->select_chip(mtd, -1);
+			chip->select_chip(mtd, chipnr);
+		}
 
-	/* Do not allow reads past end of device */
-	if ((from + len) > mtd->size) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_read_raw: Attempt read beyond end of device\n");
-		return -EINVAL;
-	}
-
-	/* Grab the lock and see if the device is available */
-	nand_get_device (this, mtd , FL_READING);
-
-	this->select_chip (mtd, chip);
-
-	/* Add requested oob length */
-	len += ooblen;
-
-	while (len) {
-		if (sndcmd)
-			this->cmdfunc (mtd, NAND_CMD_READ0, 0, page & this->pagemask);
-		sndcmd = 0;
-
-		this->read_buf (mtd, &buf[cnt], pagesize);
-
-		len -= pagesize;
-		cnt += pagesize;
-		page++;
-
-		if (!this->dev_ready)
-			udelay (this->chip_delay);
-		else
-			nand_wait_ready(mtd);
-
-		/* Check, if the chip supports auto page increment */
-		if (!NAND_CANAUTOINCR(this) || !(page & blockcheck))
+		/* Check, if the chip supports auto page increment
+		 * or if we have hit a block boundary.
+		 */
+		if (!NAND_CANAUTOINCR(chip) || !(page & blkcheck))
 			sndcmd = 1;
 	}
 
-	/* Deselect and wake up anyone waiting on the device */
-	nand_release_device(mtd);
+	ops->retlen = ops->len;
 	return 0;
 }
 
-
 /**
- * nand_prepare_oobbuf - [GENERIC] Prepare the out of band buffer
+ * nand_read_oob - [MTD Interface] NAND read data and/or out-of-band
  * @mtd:	MTD device structure
- * @fsbuf:	buffer given by fs driver
- * @oobsel:	out of band selection structre
- * @autoplace:	1 = place given buffer into the oob bytes
- * @numpages:	number of pages to prepare
+ * @from:	offset to read from
+ * @ops:	oob operation description structure
  *
- * Return:
- * 1. Filesystem buffer available and autoplacement is off,
- *    return filesystem buffer
- * 2. No filesystem buffer or autoplace is off, return internal
- *    buffer
- * 3. Filesystem buffer is given and autoplace selected
- *    put data from fs buffer into internal buffer and
- *    retrun internal buffer
- *
- * Note: The internal buffer is filled with 0xff. This must
- * be done only once, when no autoplacement happens
- * Autoplacement sets the buffer dirty flag, which
- * forces the 0xff fill before using the buffer again.
- *
-*/
-static u_char * nand_prepare_oobbuf (struct mtd_info *mtd, u_char *fsbuf, struct nand_oobinfo *oobsel,
-		int autoplace, int numpages)
-{
-	struct nand_chip *this = mtd->priv;
-	int i, len, ofs;
-
-	/* Zero copy fs supplied buffer */
-	if (fsbuf && !autoplace)
-		return fsbuf;
-
-	/* Check, if the buffer must be filled with ff again */
-	if (this->oobdirty) {
-		memset (this->oob_buf, 0xff,
-			mtd->oobsize << (this->phys_erase_shift - this->page_shift));
-		this->oobdirty = 0;
-	}
-
-	/* If we have no autoplacement or no fs buffer use the internal one */
-	if (!autoplace || !fsbuf)
-		return this->oob_buf;
-
-	/* Walk through the pages and place the data */
-	this->oobdirty = 1;
-	ofs = 0;
-	while (numpages--) {
-		for (i = 0, len = 0; len < mtd->oobavail; i++) {
-			int to = ofs + oobsel->oobfree[i][0];
-			int num = oobsel->oobfree[i][1];
-			memcpy (&this->oob_buf[to], fsbuf, num);
-			len += num;
-			fsbuf += num;
-		}
-		ofs += mtd->oobavail;
-	}
-	return this->oob_buf;
-}
-
-#define NOTALIGNED(x) (x & (mtd->oobblock-1)) != 0
-
-/**
- * nand_write - [MTD Interface] compability function for nand_write_ecc
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @len:	number of bytes to write
- * @retlen:	pointer to variable to store the number of written bytes
- * @buf:	the data to write
- *
- * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
- *
-*/
-static int nand_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
-{
-	return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
-}
-
-/**
- * nand_write_ecc - [MTD Interface] NAND write with ECC
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @len:	number of bytes to write
- * @retlen:	pointer to variable to store the number of written bytes
- * @buf:	the data to write
- * @eccbuf:	filesystem supplied oob data buffer
- * @oobsel:	oob selection structure
- *
- * NAND write with ECC
+ * NAND read data and/or out-of-band data
  */
-static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
-			   size_t * retlen, const u_char * buf, u_char * eccbuf, struct nand_oobinfo *oobsel)
+static int nand_read_oob(struct mtd_info *mtd, loff_t from,
+			 struct mtd_oob_ops *ops)
 {
-	int startpage, page, ret = -EIO, oob = 0, written = 0, chipnr;
-	int autoplace = 0, numpages, totalpages;
-	struct nand_chip *this = mtd->priv;
-	u_char *oobbuf, *bufstart;
-	int	ppblock = (1 << (this->phys_erase_shift - this->page_shift));
+	int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			 uint8_t *buf) = NULL;
+	struct nand_chip *chip = mtd->priv;
+	int ret = -ENOTSUPP;
 
-	DEBUG (MTD_DEBUG_LEVEL3, "nand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+	ops->retlen = 0;
 
-	/* Initialize retlen, in case of early exit */
-	*retlen = 0;
-
-	/* Do not allow write past end of device */
-	if ((to + len) > mtd->size) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: Attempt to write past end of page\n");
+	/* Do not allow reads past end of device */
+	if ((from + ops->len) > mtd->size) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+		      "Attempt read beyond end of device\n");
 		return -EINVAL;
 	}
 
-	/* reject writes, which are not page aligned */
-	if (NOTALIGNED (to) || NOTALIGNED(len)) {
-		printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
-		return -EINVAL;
-	}
+	nand_get_device(chip, mtd, FL_READING);
 
-	/* Grab the lock and see if the device is available */
-	nand_get_device (this, mtd, FL_WRITING);
+	switch(ops->mode) {
+	case MTD_OOB_PLACE:
+	case MTD_OOB_AUTO:
+		break;
 
-	/* Calculate chipnr */
-	chipnr = (int)(to >> this->chip_shift);
-	/* Select the NAND device */
-	this->select_chip(mtd, chipnr);
+	case MTD_OOB_RAW:
+		/* Replace the read_page algorithm temporary */
+		read_page = chip->ecc.read_page;
+		chip->ecc.read_page = nand_read_page_raw;
+		break;
 
-	/* Check, if it is write protected */
-	if (nand_check_wp(mtd))
+	default:
 		goto out;
-
-	/* if oobsel is NULL, use chip defaults */
-	if (oobsel == NULL)
-		oobsel = &mtd->oobinfo;
-
-	/* Autoplace of oob data ? Use the default placement scheme */
-	if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
-		oobsel = this->autooob;
-		autoplace = 1;
 	}
-	if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
-		autoplace = 1;
 
-	/* Setup variables and oob buffer */
-	totalpages = len >> this->page_shift;
-	page = (int) (to >> this->page_shift);
-	/* Invalidate the page cache, if we write to the cached page */
-	if (page <= this->pagebuf && this->pagebuf < (page + totalpages))
-		this->pagebuf = -1;
-
-	/* Set it relative to chip */
-	page &= this->pagemask;
-	startpage = page;
-	/* Calc number of pages we can write in one go */
-	numpages = min (ppblock - (startpage  & (ppblock - 1)), totalpages);
-	oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel, autoplace, numpages);
-	bufstart = (u_char *)buf;
-
-	/* Loop until all data is written */
-	while (written < len) {
-
-		this->data_poi = (u_char*) &buf[written];
-		/* Write one page. If this is the last page to write
-		 * or the last page in this block, then use the
-		 * real pageprogram command, else select cached programming
-		 * if supported by the chip.
-		 */
-		ret = nand_write_page (mtd, this, page, &oobbuf[oob], oobsel, (--numpages > 0));
-		if (ret) {
-			DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: write_page failed %d\n", ret);
-			goto out;
-		}
-		/* Next oob page */
-		oob += mtd->oobsize;
-		/* Update written bytes count */
-		written += mtd->oobblock;
-		if (written == len)
-			goto cmp;
-
-		/* Increment page address */
-		page++;
-
-		/* Have we hit a block boundary ? Then we have to verify and
-		 * if verify is ok, we have to setup the oob buffer for
-		 * the next pages.
-		*/
-		if (!(page & (ppblock - 1))){
-			int ofs;
-			this->data_poi = bufstart;
-			ret = nand_verify_pages (mtd, this, startpage,
-				page - startpage,
-				oobbuf, oobsel, chipnr, (eccbuf != NULL));
-			if (ret) {
-				DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
-				goto out;
-			}
-			*retlen = written;
-
-			ofs = autoplace ? mtd->oobavail : mtd->oobsize;
-			if (eccbuf)
-				eccbuf += (page - startpage) * ofs;
-			totalpages -= page - startpage;
-			numpages = min (totalpages, ppblock);
-			page &= this->pagemask;
-			startpage = page;
-			oobbuf = nand_prepare_oobbuf (mtd, eccbuf, oobsel,
-					autoplace, numpages);
-			oob = 0;
-			/* Check, if we cross a chip boundary */
-			if (!page) {
-				chipnr++;
-				this->select_chip(mtd, -1);
-				this->select_chip(mtd, chipnr);
-			}
-		}
-	}
-	/* Verify the remaining pages */
-cmp:
-	this->data_poi = bufstart;
- 	ret = nand_verify_pages (mtd, this, startpage, totalpages,
-		oobbuf, oobsel, chipnr, (eccbuf != NULL));
-	if (!ret)
-		*retlen = written;
+	if (!ops->datbuf)
+		ret = nand_do_read_oob(mtd, from, ops);
 	else
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_write_ecc: verify_pages failed %d\n", ret);
+		ret = nand_do_read_ops(mtd, from, ops);
 
-out:
-	/* Deselect and wake up anyone waiting on the device */
+	if (unlikely(ops->mode == MTD_OOB_RAW))
+		chip->ecc.read_page = read_page;
+ out:
 	nand_release_device(mtd);
-
 	return ret;
 }
 
 
 /**
- * nand_write_oob - [MTD Interface] NAND write out-of-band
- * @mtd:	MTD device structure
- * @to:		offset to write to
- * @len:	number of bytes to write
- * @retlen:	pointer to variable to store the number of written bytes
- * @buf:	the data to write
- *
- * NAND write out-of-band
+ * nand_write_page_raw - [Intern] raw page write function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	data buffer
  */
-static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
+static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+				const uint8_t *buf)
 {
-	int column, page, status, ret = -EIO, chipnr;
-	struct nand_chip *this = mtd->priv;
+	chip->write_buf(mtd, buf, mtd->writesize);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
 
-	DEBUG (MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+/**
+ * nand_write_page_swecc - {REPLACABLE] software ecc based page write function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	data buffer
+ */
+static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
+				  const uint8_t *buf)
+{
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *ecc_calc = chip->buffers.ecccalc;
+	const uint8_t *p = buf;
+	int *eccpos = chip->ecc.layout->eccpos;
 
-	/* Shift to get page */
-	page = (int) (to >> this->page_shift);
-	chipnr = (int) (to >> this->chip_shift);
+	/* Software ecc calculation */
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
-	/* Mask to get column */
-	column = to & (mtd->oobsize - 1);
+	for (i = 0; i < chip->ecc.total; i++)
+		chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
-	/* Initialize return length value */
-	*retlen = 0;
+	nand_write_page_raw(mtd, chip, buf);
+}
 
-	/* Do not allow write past end of page */
-	if ((column + len) > mtd->oobsize) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: Attempt to write past end of page\n");
-		return -EINVAL;
+/**
+ * nand_write_page_hwecc - {REPLACABLE] hardware ecc based page write function
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	data buffer
+ */
+static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+				  const uint8_t *buf)
+{
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *ecc_calc = chip->buffers.ecccalc;
+	const uint8_t *p = buf;
+	int *eccpos = chip->ecc.layout->eccpos;
+
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+		chip->write_buf(mtd, p, eccsize);
+		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 	}
 
-	/* Grab the lock and see if the device is available */
-	nand_get_device (this, mtd, FL_WRITING);
+	for (i = 0; i < chip->ecc.total; i++)
+		chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
-	/* Select the NAND device */
-	this->select_chip(mtd, chipnr);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
 
-	/* Reset the chip. Some chips (like the Toshiba TC5832DC found
-	   in one of my DiskOnChip 2000 test units) will clear the whole
-	   data page too if we don't do this. I have no clue why, but
-	   I seem to have 'fixed' it in the doc2000 driver in
-	   August 1999.  dwmw2. */
-	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+/**
+ * nand_write_page_syndrome - {REPLACABLE] hardware ecc syndrom based page write
+ * @mtd:	mtd info structure
+ * @chip:	nand chip info structure
+ * @buf:	data buffer
+ *
+ * The hw generator calculates the error syndrome automatically. Therefor
+ * we need a special oob layout and handling.
+ */
+static void nand_write_page_syndrome(struct mtd_info *mtd,
+				    struct nand_chip *chip, const uint8_t *buf)
+{
+	int i, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	const uint8_t *p = buf;
+	uint8_t *oob = chip->oob_poi;
 
-	/* Check, if it is write protected */
-	if (nand_check_wp(mtd))
-		goto out;
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 
-	/* Invalidate the page cache, if we write to the cached page */
-	if (page == this->pagebuf)
-		this->pagebuf = -1;
+		chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+		chip->write_buf(mtd, p, eccsize);
 
-	if (NAND_MUST_PAD(this)) {
-		/* Write out desired data */
-		this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask);
-		/* prepad 0xff for partial programming */
-		this->write_buf(mtd, ffchars, column);
-		/* write data */
-		this->write_buf(mtd, buf, len);
-		/* postpad 0xff for partial programming */
-		this->write_buf(mtd, ffchars, mtd->oobsize - (len+column));
+		if (chip->ecc.prepad) {
+			chip->write_buf(mtd, oob, chip->ecc.prepad);
+			oob += chip->ecc.prepad;
+		}
+
+		chip->ecc.calculate(mtd, p, oob);
+		chip->write_buf(mtd, oob, eccbytes);
+		oob += eccbytes;
+
+		if (chip->ecc.postpad) {
+			chip->write_buf(mtd, oob, chip->ecc.postpad);
+			oob += chip->ecc.postpad;
+		}
+	}
+
+	/* Calculate remaining oob bytes */
+	i = mtd->oobsize - (oob - chip->oob_poi);
+	if (i)
+		chip->write_buf(mtd, oob, i);
+}
+
+/**
+ * nand_write_page - [INTERNAL] write one page
+ * @mtd:	MTD device structure
+ * @chip:	NAND chip descriptor
+ * @buf:	the data to write
+ * @page:	page number to write
+ * @cached:	cached programming
+ */
+static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+			   const uint8_t *buf, int page, int cached)
+{
+	int status;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+
+	chip->ecc.write_page(mtd, chip, buf);
+
+	/*
+	 * Cached progamming disabled for now, Not sure if its worth the
+	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s)
+	 */
+	cached = 0;
+
+	if (!cached || !(chip->options & NAND_CACHEPRG)) {
+
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
+		/*
+		 * See if operation failed and additional status checks are
+		 * available
+		 */
+		if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+			status = chip->errstat(mtd, chip, FL_WRITING, status,
+					       page);
+
+		if (status & NAND_STATUS_FAIL)
+			return -EIO;
 	} else {
-		/* Write out desired data */
-		this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock + column, page & this->pagemask);
-		/* write data */
-		this->write_buf(mtd, buf, len);
+		chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
 	}
-	/* Send command to program the OOB data */
-	this->cmdfunc (mtd, NAND_CMD_PAGEPROG, -1, -1);
-
-	status = this->waitfunc (mtd, this, FL_WRITING);
-
-	/* See if device thinks it succeeded */
-	if (status & NAND_STATUS_FAIL) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write, page 0x%08x\n", page);
-		ret = -EIO;
-		goto out;
-	}
-	/* Return happy */
-	*retlen = len;
 
 #ifdef CONFIG_MTD_NAND_VERIFY_WRITE
 	/* Send command to read back the data */
-	this->cmdfunc (mtd, NAND_CMD_READOOB, column, page & this->pagemask);
+	chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
 
-	if (this->verify_buf(mtd, buf, len)) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " "Failed write verify, page 0x%08x\n", page);
-		ret = -EIO;
-		goto out;
-	}
+	if (chip->verify_buf(mtd, buf, mtd->writesize))
+		return -EIO;
 #endif
-	ret = 0;
-out:
-	/* Deselect and wake up anyone waiting on the device */
-	nand_release_device(mtd);
-
-	return ret;
-}
-
-
-/**
- * nand_writev - [MTD Interface] compabilty function for nand_writev_ecc
- * @mtd:	MTD device structure
- * @vecs:	the iovectors to write
- * @count:	number of vectors
- * @to:		offset to write to
- * @retlen:	pointer to variable to store the number of written bytes
- *
- * NAND write with kvec. This just calls the ecc function
- */
-static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-		loff_t to, size_t * retlen)
-{
-	return (nand_writev_ecc (mtd, vecs, count, to, retlen, NULL, NULL));
+	return 0;
 }
 
 /**
- * nand_writev_ecc - [MTD Interface] write with iovec with ecc
- * @mtd:	MTD device structure
- * @vecs:	the iovectors to write
- * @count:	number of vectors
- * @to:		offset to write to
- * @retlen:	pointer to variable to store the number of written bytes
- * @eccbuf:	filesystem supplied oob data buffer
- * @oobsel:	oob selection structure
- *
- * NAND write with iovec with ecc
+ * nand_fill_oob - [Internal] Transfer client buffer to oob
+ * @chip:	nand chip structure
+ * @oob:	oob data buffer
+ * @ops:	oob ops structure
  */
-static int nand_writev_ecc (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count,
-		loff_t to, size_t * retlen, u_char *eccbuf, struct nand_oobinfo *oobsel)
+static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
+				  struct mtd_oob_ops *ops)
 {
-	int i, page, len, total_len, ret = -EIO, written = 0, chipnr;
-	int oob, numpages, autoplace = 0, startpage;
-	struct nand_chip *this = mtd->priv;
-	int	ppblock = (1 << (this->phys_erase_shift - this->page_shift));
-	u_char *oobbuf, *bufstart;
+	size_t len = ops->ooblen;
 
-	/* Preset written len for early exit */
-	*retlen = 0;
+	switch(ops->mode) {
 
-	/* Calculate total length of data */
-	total_len = 0;
-	for (i = 0; i < count; i++)
-		total_len += (int) vecs[i].iov_len;
+	case MTD_OOB_PLACE:
+	case MTD_OOB_RAW:
+		memcpy(chip->oob_poi + ops->ooboffs, oob, len);
+		return oob + len;
 
-	DEBUG (MTD_DEBUG_LEVEL3,
-	       "nand_writev: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
+	case MTD_OOB_AUTO: {
+		struct nand_oobfree *free = chip->ecc.layout->oobfree;
+		uint32_t boffs = 0, woffs = ops->ooboffs;
+		size_t bytes = 0;
 
-	/* Do not allow write past end of page */
-	if ((to + total_len) > mtd->size) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_writev: Attempted write past end of device\n");
-		return -EINVAL;
+		for(; free->length && len; free++, len -= bytes) {
+			/* Write request not from offset 0 ? */
+			if (unlikely(woffs)) {
+				if (woffs >= free->length) {
+					woffs -= free->length;
+					continue;
+				}
+				boffs = free->offset + woffs;
+				bytes = min_t(size_t, len,
+					      (free->length - woffs));
+				woffs = 0;
+			} else {
+				bytes = min_t(size_t, len, free->length);
+				boffs = free->offset;
+			}
+			memcpy(chip->oob_poi + woffs, oob, bytes);
+			oob += bytes;
+		}
+		return oob;
 	}
+	default:
+		BUG();
+	}
+	return NULL;
+}
+
+#define NOTALIGNED(x) (x & (mtd->writesize-1)) != 0
+
+/**
+ * nand_do_write_ops - [Internal] NAND write with ECC
+ * @mtd:	MTD device structure
+ * @to:		offset to write to
+ * @ops:	oob operations description structure
+ *
+ * NAND write with ECC
+ */
+static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
+			     struct mtd_oob_ops *ops)
+{
+	int chipnr, realpage, page, blockmask;
+	struct nand_chip *chip = mtd->priv;
+	uint32_t writelen = ops->len;
+	uint8_t *oob = ops->oobbuf;
+	uint8_t *buf = ops->datbuf;
+	int bytes = mtd->writesize;
+	int ret;
+
+	ops->retlen = 0;
 
 	/* reject writes, which are not page aligned */
-	if (NOTALIGNED (to) || NOTALIGNED(total_len)) {
-		printk (KERN_NOTICE "nand_write_ecc: Attempt to write not page aligned data\n");
+	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
+		printk(KERN_NOTICE "nand_write: "
+		       "Attempt to write not page aligned data\n");
 		return -EINVAL;
 	}
 
-	/* Grab the lock and see if the device is available */
-	nand_get_device (this, mtd, FL_WRITING);
+	if (!writelen)
+		return 0;
 
-	/* Get the current chip-nr */
-	chipnr = (int) (to >> this->chip_shift);
-	/* Select the NAND device */
-	this->select_chip(mtd, chipnr);
+	chipnr = (int)(to >> chip->chip_shift);
+	chip->select_chip(mtd, chipnr);
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd))
-		goto out;
+		return -EIO;
 
-	/* if oobsel is NULL, use chip defaults */
-	if (oobsel == NULL)
-		oobsel = &mtd->oobinfo;
+	realpage = (int)(to >> chip->page_shift);
+	page = realpage & chip->pagemask;
+	blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
 
-	/* Autoplace of oob data ? Use the default placement scheme */
-	if (oobsel->useecc == MTD_NANDECC_AUTOPLACE) {
-		oobsel = this->autooob;
-		autoplace = 1;
-	}
-	if (oobsel->useecc == MTD_NANDECC_AUTOPL_USR)
-		autoplace = 1;
+	/* Invalidate the page cache, when we write to the cached page */
+	if (to <= (chip->pagebuf << chip->page_shift) &&
+	    (chip->pagebuf << chip->page_shift) < (to + ops->len))
+		chip->pagebuf = -1;
 
-	/* Setup start page */
-	page = (int) (to >> this->page_shift);
-	/* Invalidate the page cache, if we write to the cached page */
-	if (page <= this->pagebuf && this->pagebuf < ((to + total_len) >> this->page_shift))
-		this->pagebuf = -1;
+	chip->oob_poi = chip->buffers.oobwbuf;
 
-	startpage = page & this->pagemask;
+	while(1) {
+		int cached = writelen > bytes && page != blockmask;
 
-	/* Loop until all kvec' data has been written */
-	len = 0;
-	while (count) {
-		/* If the given tuple is >= pagesize then
-		 * write it out from the iov
-		 */
-		if ((vecs->iov_len - len) >= mtd->oobblock) {
-			/* Calc number of pages we can write
-			 * out of this iov in one go */
-			numpages = (vecs->iov_len - len) >> this->page_shift;
-			/* Do not cross block boundaries */
-			numpages = min (ppblock - (startpage & (ppblock - 1)), numpages);
-			oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
-			bufstart = (u_char *)vecs->iov_base;
-			bufstart += len;
-			this->data_poi = bufstart;
-			oob = 0;
-			for (i = 1; i <= numpages; i++) {
-				/* Write one page. If this is the last page to write
-				 * then use the real pageprogram command, else select
-				 * cached programming if supported by the chip.
-				 */
-				ret = nand_write_page (mtd, this, page & this->pagemask,
-					&oobbuf[oob], oobsel, i != numpages);
-				if (ret)
-					goto out;
-				this->data_poi += mtd->oobblock;
-				len += mtd->oobblock;
-				oob += mtd->oobsize;
-				page++;
-			}
-			/* Check, if we have to switch to the next tuple */
-			if (len >= (int) vecs->iov_len) {
-				vecs++;
-				len = 0;
-				count--;
-			}
-		} else {
-			/* We must use the internal buffer, read data out of each
-			 * tuple until we have a full page to write
-			 */
-			int cnt = 0;
-			while (cnt < mtd->oobblock) {
-				if (vecs->iov_base != NULL && vecs->iov_len)
-					this->data_buf[cnt++] = ((u_char *) vecs->iov_base)[len++];
-				/* Check, if we have to switch to the next tuple */
-				if (len >= (int) vecs->iov_len) {
-					vecs++;
-					len = 0;
-					count--;
-				}
-			}
-			this->pagebuf = page;
-			this->data_poi = this->data_buf;
-			bufstart = this->data_poi;
-			numpages = 1;
-			oobbuf = nand_prepare_oobbuf (mtd, NULL, oobsel, autoplace, numpages);
-			ret = nand_write_page (mtd, this, page & this->pagemask,
-				oobbuf, oobsel, 0);
-			if (ret)
-				goto out;
-			page++;
-		}
+		if (unlikely(oob))
+			oob = nand_fill_oob(chip, oob, ops);
 
-		this->data_poi = bufstart;
-		ret = nand_verify_pages (mtd, this, startpage, numpages, oobbuf, oobsel, chipnr, 0);
+		ret = nand_write_page(mtd, chip, buf, page, cached);
 		if (ret)
-			goto out;
-
-		written += mtd->oobblock * numpages;
-		/* All done ? */
-		if (!count)
 			break;
 
-		startpage = page & this->pagemask;
+		writelen -= bytes;
+		if (!writelen)
+			break;
+
+		buf += bytes;
+		realpage++;
+
+		page = realpage & chip->pagemask;
 		/* Check, if we cross a chip boundary */
-		if (!startpage) {
+		if (!page) {
 			chipnr++;
-			this->select_chip(mtd, -1);
-			this->select_chip(mtd, chipnr);
+			chip->select_chip(mtd, -1);
+			chip->select_chip(mtd, chipnr);
 		}
 	}
-	ret = 0;
-out:
-	/* Deselect and wake up anyone waiting on the device */
+
+	if (unlikely(oob))
+		memset(chip->oob_poi, 0xff, mtd->oobsize);
+
+	ops->retlen = ops->len - writelen;
+	return ret;
+}
+
+/**
+ * nand_write - [MTD Interface] NAND write with ECC
+ * @mtd:	MTD device structure
+ * @to:		offset to write to
+ * @len:	number of bytes to write
+ * @retlen:	pointer to variable to store the number of written bytes
+ * @buf:	the data to write
+ *
+ * NAND write with ECC
+ */
+static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
+			  size_t *retlen, const uint8_t *buf)
+{
+	struct nand_chip *chip = mtd->priv;
+	int ret;
+
+	/* Do not allow reads past end of device */
+	if ((to + len) > mtd->size)
+		return -EINVAL;
+	if (!len)
+		return 0;
+
+	nand_get_device(chip, mtd, FL_WRITING);
+
+	chip->ops.len = len;
+	chip->ops.datbuf = (uint8_t *)buf;
+	chip->ops.oobbuf = NULL;
+
+	ret = nand_do_write_ops(mtd, to, &chip->ops);
+
 	nand_release_device(mtd);
 
-	*retlen = written;
+	*retlen = chip->ops.retlen;
+	return ret;
+}
+
+/**
+ * nand_do_write_oob - [MTD Interface] NAND write out-of-band
+ * @mtd:	MTD device structure
+ * @to:		offset to write to
+ * @ops:	oob operation description structure
+ *
+ * NAND write out-of-band
+ */
+static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+			     struct mtd_oob_ops *ops)
+{
+	int chipnr, page, status;
+	struct nand_chip *chip = mtd->priv;
+
+	DEBUG(MTD_DEBUG_LEVEL3, "nand_write_oob: to = 0x%08x, len = %i\n",
+	      (unsigned int)to, (int)ops->len);
+
+	/* Do not allow write past end of page */
+	if ((ops->ooboffs + ops->len) > mtd->oobsize) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_write_oob: "
+		      "Attempt to write past end of page\n");
+		return -EINVAL;
+	}
+
+	chipnr = (int)(to >> chip->chip_shift);
+	chip->select_chip(mtd, chipnr);
+
+	/* Shift to get page */
+	page = (int)(to >> chip->page_shift);
+
+	/*
+	 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one
+	 * of my DiskOnChip 2000 test units) will clear the whole data page too
+	 * if we don't do this. I have no clue why, but I seem to have 'fixed'
+	 * it in the doc2000 driver in August 1999.  dwmw2.
+	 */
+	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+	/* Check, if it is write protected */
+	if (nand_check_wp(mtd))
+		return -EROFS;
+
+	/* Invalidate the page cache, if we write to the cached page */
+	if (page == chip->pagebuf)
+		chip->pagebuf = -1;
+
+	chip->oob_poi = chip->buffers.oobwbuf;
+	memset(chip->oob_poi, 0xff, mtd->oobsize);
+	nand_fill_oob(chip, ops->oobbuf, ops);
+	status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
+	memset(chip->oob_poi, 0xff, mtd->oobsize);
+
+	if (status)
+		return status;
+
+	ops->retlen = ops->len;
+
+	return 0;
+}
+
+/**
+ * nand_write_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd:	MTD device structure
+ * @from:	offset to read from
+ * @ops:	oob operation description structure
+ */
+static int nand_write_oob(struct mtd_info *mtd, loff_t to,
+			  struct mtd_oob_ops *ops)
+{
+	void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			  const uint8_t *buf) = NULL;
+	struct nand_chip *chip = mtd->priv;
+	int ret = -ENOTSUPP;
+
+	ops->retlen = 0;
+
+	/* Do not allow writes past end of device */
+	if ((to + ops->len) > mtd->size) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_read_oob: "
+		      "Attempt read beyond end of device\n");
+		return -EINVAL;
+	}
+
+	nand_get_device(chip, mtd, FL_WRITING);
+
+	switch(ops->mode) {
+	case MTD_OOB_PLACE:
+	case MTD_OOB_AUTO:
+		break;
+
+	case MTD_OOB_RAW:
+		/* Replace the write_page algorithm temporary */
+		write_page = chip->ecc.write_page;
+		chip->ecc.write_page = nand_write_page_raw;
+		break;
+
+	default:
+		goto out;
+	}
+
+	if (!ops->datbuf)
+		ret = nand_do_write_oob(mtd, to, ops);
+	else
+		ret = nand_do_write_ops(mtd, to, ops);
+
+	if (unlikely(ops->mode == MTD_OOB_RAW))
+		chip->ecc.write_page = write_page;
+ out:
+	nand_release_device(mtd);
 	return ret;
 }
 
@@ -2050,12 +1816,12 @@
  *
  * Standard erase command for NAND chips
  */
-static void single_erase_cmd (struct mtd_info *mtd, int page)
+static void single_erase_cmd(struct mtd_info *mtd, int page)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	/* Send commands to erase a block */
-	this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
-	this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
 }
 
 /**
@@ -2066,15 +1832,15 @@
  * AND multi block erase command function
  * Erase 4 consecutive blocks
  */
-static void multi_erase_cmd (struct mtd_info *mtd, int page)
+static void multi_erase_cmd(struct mtd_info *mtd, int page)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	/* Send commands to erase a block */
-	this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
-	this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
-	this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page++);
-	this->cmdfunc (mtd, NAND_CMD_ERASE1, -1, page);
-	this->cmdfunc (mtd, NAND_CMD_ERASE2, -1, -1);
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page++);
+	chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+	chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
 }
 
 /**
@@ -2084,79 +1850,82 @@
  *
  * Erase one ore more blocks
  */
-static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
+static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
-	return nand_erase_nand (mtd, instr, 0);
+	return nand_erase_nand(mtd, instr, 0);
 }
 
 #define BBT_PAGE_MASK	0xffffff3f
 /**
- * nand_erase_intern - [NAND Interface] erase block(s)
+ * nand_erase_nand - [Internal] erase block(s)
  * @mtd:	MTD device structure
  * @instr:	erase instruction
  * @allowbbt:	allow erasing the bbt area
  *
  * Erase one ore more blocks
  */
-int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt)
+int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+		    int allowbbt)
 {
 	int page, len, status, pages_per_block, ret, chipnr;
-	struct nand_chip *this = mtd->priv;
-	int rewrite_bbt[NAND_MAX_CHIPS]={0};	/* flags to indicate the page, if bbt needs to be rewritten. */
-	unsigned int bbt_masked_page;		/* bbt mask to compare to page being erased. */
-						/* It is used to see if the current page is in the same */
-						/*   256 block group and the same bank as the bbt. */
+	struct nand_chip *chip = mtd->priv;
+	int rewrite_bbt[NAND_MAX_CHIPS]={0};
+	unsigned int bbt_masked_page = 0xffffffff;
 
-	DEBUG (MTD_DEBUG_LEVEL3,
-	       "nand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len);
+	DEBUG(MTD_DEBUG_LEVEL3, "nand_erase: start = 0x%08x, len = %i\n",
+	      (unsigned int)instr->addr, (unsigned int)instr->len);
 
 	/* Start address must align on block boundary */
-	if (instr->addr & ((1 << this->phys_erase_shift) - 1)) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
+	if (instr->addr & ((1 << chip->phys_erase_shift) - 1)) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: Unaligned address\n");
 		return -EINVAL;
 	}
 
 	/* Length must align on block boundary */
-	if (instr->len & ((1 << this->phys_erase_shift) - 1)) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Length not block aligned\n");
+	if (instr->len & ((1 << chip->phys_erase_shift) - 1)) {
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+		      "Length not block aligned\n");
 		return -EINVAL;
 	}
 
 	/* Do not allow erase past end of device */
 	if ((instr->len + instr->addr) > mtd->size) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Erase past end of device\n");
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+		      "Erase past end of device\n");
 		return -EINVAL;
 	}
 
 	instr->fail_addr = 0xffffffff;
 
 	/* Grab the lock and see if the device is available */
-	nand_get_device (this, mtd, FL_ERASING);
+	nand_get_device(chip, mtd, FL_ERASING);
 
 	/* Shift to get first page */
-	page = (int) (instr->addr >> this->page_shift);
-	chipnr = (int) (instr->addr >> this->chip_shift);
+	page = (int)(instr->addr >> chip->page_shift);
+	chipnr = (int)(instr->addr >> chip->chip_shift);
 
 	/* Calculate pages in each block */
-	pages_per_block = 1 << (this->phys_erase_shift - this->page_shift);
+	pages_per_block = 1 << (chip->phys_erase_shift - chip->page_shift);
 
 	/* Select the NAND device */
-	this->select_chip(mtd, chipnr);
+	chip->select_chip(mtd, chipnr);
 
-	/* Check the WP bit */
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: Device is write protected!!!\n");
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+		      "Device is write protected!!!\n");
 		instr->state = MTD_ERASE_FAILED;
 		goto erase_exit;
 	}
 
-	/* if BBT requires refresh, set the BBT page mask to see if the BBT should be rewritten */
-	if (this->options & BBT_AUTO_REFRESH) {
-		bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
-	} else {
-		bbt_masked_page = 0xffffffff;	/* should not match anything */
-	}
+	/*
+	 * If BBT requires refresh, set the BBT page mask to see if the BBT
+	 * should be rewritten. Otherwise the mask is set to 0xffffffff which
+	 * can not be matched. This is also done when the bbt is actually
+	 * erased to avoid recusrsive updates
+	 */
+	if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
+		bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
 
 	/* Loop through the pages */
 	len = instr->len;
@@ -2164,64 +1933,77 @@
 	instr->state = MTD_ERASING;
 
 	while (len) {
-		/* Check if we have a bad block, we do not erase bad blocks ! */
-		if (nand_block_checkbad(mtd, ((loff_t) page) << this->page_shift, 0, allowbbt)) {
-			printk (KERN_WARNING "nand_erase: attempt to erase a bad block at page 0x%08x\n", page);
+		/*
+		 * heck if we have a bad block, we do not erase bad blocks !
+		 */
+		if (nand_block_checkbad(mtd, ((loff_t) page) <<
+					chip->page_shift, 0, allowbbt)) {
+			printk(KERN_WARNING "nand_erase: attempt to erase a "
+			       "bad block at page 0x%08x\n", page);
 			instr->state = MTD_ERASE_FAILED;
 			goto erase_exit;
 		}
 
-		/* Invalidate the page cache, if we erase the block which contains
-		   the current cached page */
-		if (page <= this->pagebuf && this->pagebuf < (page + pages_per_block))
-			this->pagebuf = -1;
+		/*
+		 * Invalidate the page cache, if we erase the block which
+		 * contains the current cached page
+		 */
+		if (page <= chip->pagebuf && chip->pagebuf <
+		    (page + pages_per_block))
+			chip->pagebuf = -1;
 
-		this->erase_cmd (mtd, page & this->pagemask);
+		chip->erase_cmd(mtd, page & chip->pagemask);
 
-		status = this->waitfunc (mtd, this, FL_ERASING);
+		status = chip->waitfunc(mtd, chip);
 
-		/* See if operation failed and additional status checks are available */
-		if ((status & NAND_STATUS_FAIL) && (this->errstat)) {
-			status = this->errstat(mtd, this, FL_ERASING, status, page);
-		}
+		/*
+		 * See if operation failed and additional status checks are
+		 * available
+		 */
+		if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+			status = chip->errstat(mtd, chip, FL_ERASING,
+					       status, page);
 
 		/* See if block erase succeeded */
 		if (status & NAND_STATUS_FAIL) {
-			DEBUG (MTD_DEBUG_LEVEL0, "nand_erase: " "Failed erase, page 0x%08x\n", page);
+			DEBUG(MTD_DEBUG_LEVEL0, "nand_erase: "
+			      "Failed erase, page 0x%08x\n", page);
 			instr->state = MTD_ERASE_FAILED;
-			instr->fail_addr = (page << this->page_shift);
+			instr->fail_addr = (page << chip->page_shift);
 			goto erase_exit;
 		}
 
-		/* if BBT requires refresh, set the BBT rewrite flag to the page being erased */
-		if (this->options & BBT_AUTO_REFRESH) {
-			if (((page & BBT_PAGE_MASK) == bbt_masked_page) &&
-			     (page != this->bbt_td->pages[chipnr])) {
-				rewrite_bbt[chipnr] = (page << this->page_shift);
-			}
-		}
+		/*
+		 * If BBT requires refresh, set the BBT rewrite flag to the
+		 * page being erased
+		 */
+		if (bbt_masked_page != 0xffffffff &&
+		    (page & BBT_PAGE_MASK) == bbt_masked_page)
+			    rewrite_bbt[chipnr] = (page << chip->page_shift);
 
 		/* Increment page address and decrement length */
-		len -= (1 << this->phys_erase_shift);
+		len -= (1 << chip->phys_erase_shift);
 		page += pages_per_block;
 
 		/* Check, if we cross a chip boundary */
-		if (len && !(page & this->pagemask)) {
+		if (len && !(page & chip->pagemask)) {
 			chipnr++;
-			this->select_chip(mtd, -1);
-			this->select_chip(mtd, chipnr);
+			chip->select_chip(mtd, -1);
+			chip->select_chip(mtd, chipnr);
 
-			/* if BBT requires refresh and BBT-PERCHIP,
-			 *   set the BBT page mask to see if this BBT should be rewritten */
-			if ((this->options & BBT_AUTO_REFRESH) && (this->bbt_td->options & NAND_BBT_PERCHIP)) {
-				bbt_masked_page = this->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
-			}
-
+			/*
+			 * If BBT requires refresh and BBT-PERCHIP, set the BBT
+			 * page mask to see if this BBT should be rewritten
+			 */
+			if (bbt_masked_page != 0xffffffff &&
+			    (chip->bbt_td->options & NAND_BBT_PERCHIP))
+				bbt_masked_page = chip->bbt_td->pages[chipnr] &
+					BBT_PAGE_MASK;
 		}
 	}
 	instr->state = MTD_ERASE_DONE;
 
-erase_exit:
+ erase_exit:
 
 	ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
 	/* Do call back function */
@@ -2231,16 +2013,21 @@
 	/* Deselect and wake up anyone waiting on the device */
 	nand_release_device(mtd);
 
-	/* if BBT requires refresh and erase was successful, rewrite any selected bad block tables */
-	if ((this->options & BBT_AUTO_REFRESH) && (!ret)) {
-		for (chipnr = 0; chipnr < this->numchips; chipnr++) {
-			if (rewrite_bbt[chipnr]) {
-				/* update the BBT for chip */
-				DEBUG (MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt (%d:0x%0x 0x%0x)\n",
-					chipnr, rewrite_bbt[chipnr], this->bbt_td->pages[chipnr]);
-				nand_update_bbt (mtd, rewrite_bbt[chipnr]);
-			}
-		}
+	/*
+	 * If BBT requires refresh and erase was successful, rewrite any
+	 * selected bad block tables
+	 */
+	if (bbt_masked_page == 0xffffffff || ret)
+		return ret;
+
+	for (chipnr = 0; chipnr < chip->numchips; chipnr++) {
+		if (!rewrite_bbt[chipnr])
+			continue;
+		/* update the BBT for chip */
+		DEBUG(MTD_DEBUG_LEVEL0, "nand_erase_nand: nand_update_bbt "
+		      "(%d:0x%0x 0x%0x)\n", chipnr, rewrite_bbt[chipnr],
+		      chip->bbt_td->pages[chipnr]);
+		nand_update_bbt(mtd, rewrite_bbt[chipnr]);
 	}
 
 	/* Return more or less happy */
@@ -2253,51 +2040,50 @@
  *
  * Sync is actually a wait for chip ready function
  */
-static void nand_sync (struct mtd_info *mtd)
+static void nand_sync(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
-	DEBUG (MTD_DEBUG_LEVEL3, "nand_sync: called\n");
+	DEBUG(MTD_DEBUG_LEVEL3, "nand_sync: called\n");
 
 	/* Grab the lock and see if the device is available */
-	nand_get_device (this, mtd, FL_SYNCING);
+	nand_get_device(chip, mtd, FL_SYNCING);
 	/* Release it and go back */
-	nand_release_device (mtd);
+	nand_release_device(mtd);
 }
 
-
 /**
- * nand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad
+ * nand_block_isbad - [MTD Interface] Check if block at offset is bad
  * @mtd:	MTD device structure
  * @ofs:	offset relative to mtd start
  */
-static int nand_block_isbad (struct mtd_info *mtd, loff_t ofs)
+static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 {
 	/* Check for invalid offset */
-	if (ofs > mtd->size)
+	if (offs > mtd->size)
 		return -EINVAL;
 
-	return nand_block_checkbad (mtd, ofs, 1, 0);
+	return nand_block_checkbad(mtd, offs, 1, 0);
 }
 
 /**
- * nand_block_markbad - [MTD Interface] Mark the block at the given offset as bad
+ * nand_block_markbad - [MTD Interface] Mark block at the given offset as bad
  * @mtd:	MTD device structure
  * @ofs:	offset relative to mtd start
  */
-static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs)
+static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 	int ret;
 
-        if ((ret = nand_block_isbad(mtd, ofs))) {
-        	/* If it was bad already, return success and do nothing. */
+	if ((ret = nand_block_isbad(mtd, ofs))) {
+		/* If it was bad already, return success and do nothing. */
 		if (ret > 0)
 			return 0;
-        	return ret;
-        }
+		return ret;
+	}
 
-	return this->block_markbad(mtd, ofs);
+	return chip->block_markbad(mtd, ofs);
 }
 
 /**
@@ -2306,9 +2092,9 @@
  */
 static int nand_suspend(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
-	return nand_get_device (this, mtd, FL_PM_SUSPENDED);
+	return nand_get_device(chip, mtd, FL_PM_SUSPENDED);
 }
 
 /**
@@ -2317,373 +2103,385 @@
  */
 static void nand_resume(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
-	if (this->state == FL_PM_SUSPENDED)
+	if (chip->state == FL_PM_SUSPENDED)
 		nand_release_device(mtd);
 	else
-		printk(KERN_ERR "resume() called for the chip which is not "
-				"in suspended state\n");
+		printk(KERN_ERR "nand_resume() called for a chip which is not "
+		       "in suspended state\n");
+}
+
+/*
+ * Set default functions
+ */
+static void nand_set_defaults(struct nand_chip *chip, int busw)
+{
+	/* check for proper chip_delay setup, set 20us if not */
+	if (!chip->chip_delay)
+		chip->chip_delay = 20;
+
+	/* check, if a user supplied command function given */
+	if (chip->cmdfunc == NULL)
+		chip->cmdfunc = nand_command;
+
+	/* check, if a user supplied wait function given */
+	if (chip->waitfunc == NULL)
+		chip->waitfunc = nand_wait;
+
+	if (!chip->select_chip)
+		chip->select_chip = nand_select_chip;
+	if (!chip->read_byte)
+		chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
+	if (!chip->read_word)
+		chip->read_word = nand_read_word;
+	if (!chip->block_bad)
+		chip->block_bad = nand_block_bad;
+	if (!chip->block_markbad)
+		chip->block_markbad = nand_default_block_markbad;
+	if (!chip->write_buf)
+		chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
+	if (!chip->read_buf)
+		chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
+	if (!chip->verify_buf)
+		chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
+	if (!chip->scan_bbt)
+		chip->scan_bbt = nand_default_bbt;
+
+	if (!chip->controller) {
+		chip->controller = &chip->hwcontrol;
+		spin_lock_init(&chip->controller->lock);
+		init_waitqueue_head(&chip->controller->wq);
+	}
 
 }
 
+/*
+ * Get the flash and manufacturer id and lookup if the type is supported
+ */
+static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
+						  struct nand_chip *chip,
+						  int busw, int *maf_id)
+{
+	struct nand_flash_dev *type = NULL;
+	int i, dev_id, maf_idx;
+
+	/* Select the device */
+	chip->select_chip(mtd, 0);
+
+	/* Send the command for reading device ID */
+	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
+
+	/* Read manufacturer and device IDs */
+	*maf_id = chip->read_byte(mtd);
+	dev_id = chip->read_byte(mtd);
+
+	/* Lookup the flash id */
+	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
+		if (dev_id == nand_flash_ids[i].id) {
+			type =  &nand_flash_ids[i];
+			break;
+		}
+	}
+
+	if (!type)
+		return ERR_PTR(-ENODEV);
+
+	if (!mtd->name)
+		mtd->name = type->name;
+
+	chip->chipsize = type->chipsize << 20;
+
+	/* Newer devices have all the information in additional id bytes */
+	if (!type->pagesize) {
+		int extid;
+		/* The 3rd id byte contains non relevant data ATM */
+		extid = chip->read_byte(mtd);
+		/* The 4th id byte is the important one */
+		extid = chip->read_byte(mtd);
+		/* Calc pagesize */
+		mtd->writesize = 1024 << (extid & 0x3);
+		extid >>= 2;
+		/* Calc oobsize */
+		mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
+		extid >>= 2;
+		/* Calc blocksize. Blocksize is multiples of 64KiB */
+		mtd->erasesize = (64 * 1024) << (extid & 0x03);
+		extid >>= 2;
+		/* Get buswidth information */
+		busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+
+	} else {
+		/*
+		 * Old devices have chip data hardcoded in the device id table
+		 */
+		mtd->erasesize = type->erasesize;
+		mtd->writesize = type->pagesize;
+		mtd->oobsize = mtd->writesize / 32;
+		busw = type->options & NAND_BUSWIDTH_16;
+	}
+
+	/* Try to identify manufacturer */
+	for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_id++) {
+		if (nand_manuf_ids[maf_idx].id == *maf_id)
+			break;
+	}
+
+	/*
+	 * Check, if buswidth is correct. Hardware drivers should set
+	 * chip correct !
+	 */
+	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
+		printk(KERN_INFO "NAND device: Manufacturer ID:"
+		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
+		       dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
+		printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
+		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
+		       busw ? 16 : 8);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* Calculate the address shift from the page size */
+	chip->page_shift = ffs(mtd->writesize) - 1;
+	/* Convert chipsize to number of pages per chip -1. */
+	chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
+
+	chip->bbt_erase_shift = chip->phys_erase_shift =
+		ffs(mtd->erasesize) - 1;
+	chip->chip_shift = ffs(chip->chipsize) - 1;
+
+	/* Set the bad block position */
+	chip->badblockpos = mtd->writesize > 512 ?
+		NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
+
+	/* Get chip options, preserve non chip based options */
+	chip->options &= ~NAND_CHIPOPTIONS_MSK;
+	chip->options |= type->options & NAND_CHIPOPTIONS_MSK;
+
+	/*
+	 * Set chip as a default. Board drivers can override it, if necessary
+	 */
+	chip->options |= NAND_NO_AUTOINCR;
+
+	/* Check if chip is a not a samsung device. Do not clear the
+	 * options for chips which are not having an extended id.
+	 */
+	if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
+		chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
+
+	/* Check for AND chips with 4 page planes */
+	if (chip->options & NAND_4PAGE_ARRAY)
+		chip->erase_cmd = multi_erase_cmd;
+	else
+		chip->erase_cmd = single_erase_cmd;
+
+	/* Do not replace user supplied command function ! */
+	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
+		chip->cmdfunc = nand_command_lp;
+
+	printk(KERN_INFO "NAND device: Manufacturer ID:"
+	       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, dev_id,
+	       nand_manuf_ids[maf_idx].name, type->name);
+
+	return type;
+}
+
+/* module_text_address() isn't exported, and it's mostly a pointless
+   test if this is a module _anyway_ -- they'd have to try _really_ hard
+   to call us from in-kernel code if the core NAND support is modular. */
+#ifdef MODULE
+#define caller_is_module() (1)
+#else
+#define caller_is_module() \
+	module_text_address((unsigned long)__builtin_return_address(0))
+#endif
 
 /**
  * nand_scan - [NAND Interface] Scan for the NAND device
  * @mtd:	MTD device structure
  * @maxchips:	Number of chips to scan for
  *
- * This fills out all the not initialized function pointers
+ * This fills out all the uninitialized function pointers
  * with the defaults.
  * The flash ID is read and the mtd/chip structures are
- * filled with the appropriate values. Buffers are allocated if
- * they are not provided by the board driver
+ * filled with the appropriate values.
+ * The mtd->owner field must be set to the module of the caller
  *
  */
-int nand_scan (struct mtd_info *mtd, int maxchips)
+int nand_scan(struct mtd_info *mtd, int maxchips)
 {
-	int i, nand_maf_id, nand_dev_id, busw, maf_id;
-	struct nand_chip *this = mtd->priv;
+	int i, busw, nand_maf_id;
+	struct nand_chip *chip = mtd->priv;
+	struct nand_flash_dev *type;
 
-	/* Get buswidth to select the correct functions*/
-	busw = this->options & NAND_BUSWIDTH_16;
-
-	/* check for proper chip_delay setup, set 20us if not */
-	if (!this->chip_delay)
-		this->chip_delay = 20;
-
-	/* check, if a user supplied command function given */
-	if (this->cmdfunc == NULL)
-		this->cmdfunc = nand_command;
-
-	/* check, if a user supplied wait function given */
-	if (this->waitfunc == NULL)
-		this->waitfunc = nand_wait;
-
-	if (!this->select_chip)
-		this->select_chip = nand_select_chip;
-	if (!this->write_byte)
-		this->write_byte = busw ? nand_write_byte16 : nand_write_byte;
-	if (!this->read_byte)
-		this->read_byte = busw ? nand_read_byte16 : nand_read_byte;
-	if (!this->write_word)
-		this->write_word = nand_write_word;
-	if (!this->read_word)
-		this->read_word = nand_read_word;
-	if (!this->block_bad)
-		this->block_bad = nand_block_bad;
-	if (!this->block_markbad)
-		this->block_markbad = nand_default_block_markbad;
-	if (!this->write_buf)
-		this->write_buf = busw ? nand_write_buf16 : nand_write_buf;
-	if (!this->read_buf)
-		this->read_buf = busw ? nand_read_buf16 : nand_read_buf;
-	if (!this->verify_buf)
-		this->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
-	if (!this->scan_bbt)
-		this->scan_bbt = nand_default_bbt;
-
-	/* Select the device */
-	this->select_chip(mtd, 0);
-
-	/* Send the command for reading device ID */
-	this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
-
-	/* Read manufacturer and device IDs */
-	nand_maf_id = this->read_byte(mtd);
-	nand_dev_id = this->read_byte(mtd);
-
-	/* Print and store flash device information */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-
-		if (nand_dev_id != nand_flash_ids[i].id)
-			continue;
-
-		if (!mtd->name) mtd->name = nand_flash_ids[i].name;
-		this->chipsize = nand_flash_ids[i].chipsize << 20;
-
-		/* New devices have all the information in additional id bytes */
-		if (!nand_flash_ids[i].pagesize) {
-			int extid;
-			/* The 3rd id byte contains non relevant data ATM */
-			extid = this->read_byte(mtd);
-			/* The 4th id byte is the important one */
-			extid = this->read_byte(mtd);
-			/* Calc pagesize */
-			mtd->oobblock = 1024 << (extid & 0x3);
-			extid >>= 2;
-			/* Calc oobsize */
-			mtd->oobsize = (8 << (extid & 0x01)) * (mtd->oobblock >> 9);
-			extid >>= 2;
-			/* Calc blocksize. Blocksize is multiples of 64KiB */
-			mtd->erasesize = (64 * 1024)  << (extid & 0x03);
-			extid >>= 2;
-			/* Get buswidth information */
-			busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
-
-		} else {
-			/* Old devices have this data hardcoded in the
-			 * device id table */
-			mtd->erasesize = nand_flash_ids[i].erasesize;
-			mtd->oobblock = nand_flash_ids[i].pagesize;
-			mtd->oobsize = mtd->oobblock / 32;
-			busw = nand_flash_ids[i].options & NAND_BUSWIDTH_16;
-		}
-
-		/* Try to identify manufacturer */
-		for (maf_id = 0; nand_manuf_ids[maf_id].id != 0x0; maf_id++) {
-			if (nand_manuf_ids[maf_id].id == nand_maf_id)
-				break;
-		}
-
-		/* Check, if buswidth is correct. Hardware drivers should set
-		 * this correct ! */
-		if (busw != (this->options & NAND_BUSWIDTH_16)) {
-			printk (KERN_INFO "NAND device: Manufacturer ID:"
-				" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-				nand_manuf_ids[maf_id].name , mtd->name);
-			printk (KERN_WARNING
-				"NAND bus width %d instead %d bit\n",
-					(this->options & NAND_BUSWIDTH_16) ? 16 : 8,
-					busw ? 16 : 8);
-			this->select_chip(mtd, -1);
-			return 1;
-		}
-
-		/* Calculate the address shift from the page size */
-		this->page_shift = ffs(mtd->oobblock) - 1;
-		this->bbt_erase_shift = this->phys_erase_shift = ffs(mtd->erasesize) - 1;
-		this->chip_shift = ffs(this->chipsize) - 1;
-
-		/* Set the bad block position */
-		this->badblockpos = mtd->oobblock > 512 ?
-			NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS;
-
-		/* Get chip options, preserve non chip based options */
-		this->options &= ~NAND_CHIPOPTIONS_MSK;
-		this->options |= nand_flash_ids[i].options & NAND_CHIPOPTIONS_MSK;
-		/* Set this as a default. Board drivers can override it, if neccecary */
-		this->options |= NAND_NO_AUTOINCR;
-		/* Check if this is a not a samsung device. Do not clear the options
-		 * for chips which are not having an extended id.
-		 */
-		if (nand_maf_id != NAND_MFR_SAMSUNG && !nand_flash_ids[i].pagesize)
-			this->options &= ~NAND_SAMSUNG_LP_OPTIONS;
-
-		/* Check for AND chips with 4 page planes */
-		if (this->options & NAND_4PAGE_ARRAY)
-			this->erase_cmd = multi_erase_cmd;
-		else
-			this->erase_cmd = single_erase_cmd;
-
-		/* Do not replace user supplied command function ! */
-		if (mtd->oobblock > 512 && this->cmdfunc == nand_command)
-			this->cmdfunc = nand_command_lp;
-
-		printk (KERN_INFO "NAND device: Manufacturer ID:"
-			" 0x%02x, Chip ID: 0x%02x (%s %s)\n", nand_maf_id, nand_dev_id,
-			nand_manuf_ids[maf_id].name , nand_flash_ids[i].name);
-		break;
+	/* Many callers got this wrong, so check for it for a while... */
+	if (!mtd->owner && caller_is_module()) {
+		printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
+		BUG();
 	}
 
-	if (!nand_flash_ids[i].name) {
-		printk (KERN_WARNING "No NAND device found!!!\n");
-		this->select_chip(mtd, -1);
-		return 1;
+	/* Get buswidth to select the correct functions */
+	busw = chip->options & NAND_BUSWIDTH_16;
+	/* Set the default functions */
+	nand_set_defaults(chip, busw);
+
+	/* Read the flash type */
+	type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
+
+	if (IS_ERR(type)) {
+		printk(KERN_WARNING "No NAND device found!!!\n");
+		chip->select_chip(mtd, -1);
+		return PTR_ERR(type);
 	}
 
-	for (i=1; i < maxchips; i++) {
-		this->select_chip(mtd, i);
-
+	/* Check for a chip array */
+	for (i = 1; i < maxchips; i++) {
+		chip->select_chip(mtd, i);
 		/* Send the command for reading device ID */
-		this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);
-
+		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 		/* Read manufacturer and device IDs */
-		if (nand_maf_id != this->read_byte(mtd) ||
-		    nand_dev_id != this->read_byte(mtd))
+		if (nand_maf_id != chip->read_byte(mtd) ||
+		    type->id != chip->read_byte(mtd))
 			break;
 	}
 	if (i > 1)
 		printk(KERN_INFO "%d NAND chips detected\n", i);
 
-	/* Allocate buffers, if neccecary */
-	if (!this->oob_buf) {
-		size_t len;
-		len = mtd->oobsize << (this->phys_erase_shift - this->page_shift);
-		this->oob_buf = kmalloc (len, GFP_KERNEL);
-		if (!this->oob_buf) {
-			printk (KERN_ERR "nand_scan(): Cannot allocate oob_buf\n");
-			return -ENOMEM;
-		}
-		this->options |= NAND_OOBBUF_ALLOC;
-	}
-
-	if (!this->data_buf) {
-		size_t len;
-		len = mtd->oobblock + mtd->oobsize;
-		this->data_buf = kmalloc (len, GFP_KERNEL);
-		if (!this->data_buf) {
-			if (this->options & NAND_OOBBUF_ALLOC)
-				kfree (this->oob_buf);
-			printk (KERN_ERR "nand_scan(): Cannot allocate data_buf\n");
-			return -ENOMEM;
-		}
-		this->options |= NAND_DATABUF_ALLOC;
-	}
-
 	/* Store the number of chips and calc total size for mtd */
-	this->numchips = i;
-	mtd->size = i * this->chipsize;
-	/* Convert chipsize to number of pages per chip -1. */
-	this->pagemask = (this->chipsize >> this->page_shift) - 1;
-	/* Preset the internal oob buffer */
-	memset(this->oob_buf, 0xff, mtd->oobsize << (this->phys_erase_shift - this->page_shift));
+	chip->numchips = i;
+	mtd->size = i * chip->chipsize;
 
-	/* If no default placement scheme is given, select an
-	 * appropriate one */
-	if (!this->autooob) {
-		/* Select the appropriate default oob placement scheme for
-		 * placement agnostic filesystems */
+	/* Preset the internal oob write buffer */
+	memset(chip->buffers.oobwbuf, 0xff, mtd->oobsize);
+
+	/*
+	 * If no default placement scheme is given, select an appropriate one
+	 */
+	if (!chip->ecc.layout) {
 		switch (mtd->oobsize) {
 		case 8:
-			this->autooob = &nand_oob_8;
+			chip->ecc.layout = &nand_oob_8;
 			break;
 		case 16:
-			this->autooob = &nand_oob_16;
+			chip->ecc.layout = &nand_oob_16;
 			break;
 		case 64:
-			this->autooob = &nand_oob_64;
+			chip->ecc.layout = &nand_oob_64;
 			break;
 		default:
-			printk (KERN_WARNING "No oob scheme defined for oobsize %d\n",
-				mtd->oobsize);
+			printk(KERN_WARNING "No oob scheme defined for "
+			       "oobsize %d\n", mtd->oobsize);
 			BUG();
 		}
 	}
 
-	/* The number of bytes available for the filesystem to place fs dependend
-	 * oob data */
-	mtd->oobavail = 0;
-	for (i = 0; this->autooob->oobfree[i][1]; i++)
-		mtd->oobavail += this->autooob->oobfree[i][1];
+	/*
+	 * check ECC mode, default to software if 3byte/512byte hardware ECC is
+	 * selected and we have 256 byte pagesize fallback to software ECC
+	 */
+	switch (chip->ecc.mode) {
+	case NAND_ECC_HW:
+		/* Use standard hwecc read page function ? */
+		if (!chip->ecc.read_page)
+			chip->ecc.read_page = nand_read_page_hwecc;
+		if (!chip->ecc.write_page)
+			chip->ecc.write_page = nand_write_page_hwecc;
+		if (!chip->ecc.read_oob)
+			chip->ecc.read_oob = nand_read_oob_std;
+		if (!chip->ecc.write_oob)
+			chip->ecc.write_oob = nand_write_oob_std;
+
+	case NAND_ECC_HW_SYNDROME:
+		if (!chip->ecc.calculate || !chip->ecc.correct ||
+		    !chip->ecc.hwctl) {
+			printk(KERN_WARNING "No ECC functions supplied, "
+			       "Hardware ECC not possible\n");
+			BUG();
+		}
+		/* Use standard syndrome read/write page function ? */
+		if (!chip->ecc.read_page)
+			chip->ecc.read_page = nand_read_page_syndrome;
+		if (!chip->ecc.write_page)
+			chip->ecc.write_page = nand_write_page_syndrome;
+		if (!chip->ecc.read_oob)
+			chip->ecc.read_oob = nand_read_oob_syndrome;
+		if (!chip->ecc.write_oob)
+			chip->ecc.write_oob = nand_write_oob_syndrome;
+
+		if (mtd->writesize >= chip->ecc.size)
+			break;
+		printk(KERN_WARNING "%d byte HW ECC not possible on "
+		       "%d byte page size, fallback to SW ECC\n",
+		       chip->ecc.size, mtd->writesize);
+		chip->ecc.mode = NAND_ECC_SOFT;
+
+	case NAND_ECC_SOFT:
+		chip->ecc.calculate = nand_calculate_ecc;
+		chip->ecc.correct = nand_correct_data;
+		chip->ecc.read_page = nand_read_page_swecc;
+		chip->ecc.write_page = nand_write_page_swecc;
+		chip->ecc.read_oob = nand_read_oob_std;
+		chip->ecc.write_oob = nand_write_oob_std;
+		chip->ecc.size = 256;
+		chip->ecc.bytes = 3;
+		break;
+
+	case NAND_ECC_NONE:
+		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
+		       "This is not recommended !!\n");
+		chip->ecc.read_page = nand_read_page_raw;
+		chip->ecc.write_page = nand_write_page_raw;
+		chip->ecc.read_oob = nand_read_oob_std;
+		chip->ecc.write_oob = nand_write_oob_std;
+		chip->ecc.size = mtd->writesize;
+		chip->ecc.bytes = 0;
+		break;
+	default:
+		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
+		       chip->ecc.mode);
+		BUG();
+	}
 
 	/*
-	 * check ECC mode, default to software
-	 * if 3byte/512byte hardware ECC is selected and we have 256 byte pagesize
-	 * fallback to software ECC
-	*/
-	this->eccsize = 256;	/* set default eccsize */
-	this->eccbytes = 3;
+	 * The number of bytes available for a client to place data into
+	 * the out of band area
+	 */
+	chip->ecc.layout->oobavail = 0;
+	for (i = 0; chip->ecc.layout->oobfree[i].length; i++)
+		chip->ecc.layout->oobavail +=
+			chip->ecc.layout->oobfree[i].length;
 
-	switch (this->eccmode) {
-	case NAND_ECC_HW12_2048:
-		if (mtd->oobblock < 2048) {
-			printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n",
-			       mtd->oobblock);
-			this->eccmode = NAND_ECC_SOFT;
-			this->calculate_ecc = nand_calculate_ecc;
-			this->correct_data = nand_correct_data;
-		} else
-			this->eccsize = 2048;
-		break;
-
-	case NAND_ECC_HW3_512:
-	case NAND_ECC_HW6_512:
-	case NAND_ECC_HW8_512:
-		if (mtd->oobblock == 256) {
-			printk (KERN_WARNING "512 byte HW ECC not possible on 256 Byte pagesize, fallback to SW ECC \n");
-			this->eccmode = NAND_ECC_SOFT;
-			this->calculate_ecc = nand_calculate_ecc;
-			this->correct_data = nand_correct_data;
-		} else
-			this->eccsize = 512; /* set eccsize to 512 */
-		break;
-
-	case NAND_ECC_HW3_256:
-		break;
-
-	case NAND_ECC_NONE:
-		printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n");
-		this->eccmode = NAND_ECC_NONE;
-		break;
-
-	case NAND_ECC_SOFT:
-		this->calculate_ecc = nand_calculate_ecc;
-		this->correct_data = nand_correct_data;
-		break;
-
-	default:
-		printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode);
+	/*
+	 * Set the number of read / write steps for one page depending on ECC
+	 * mode
+	 */
+	chip->ecc.steps = mtd->writesize / chip->ecc.size;
+	if(chip->ecc.steps * chip->ecc.size != mtd->writesize) {
+		printk(KERN_WARNING "Invalid ecc parameters\n");
 		BUG();
 	}
+	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
 
-	/* Check hardware ecc function availability and adjust number of ecc bytes per
-	 * calculation step
-	*/
-	switch (this->eccmode) {
-	case NAND_ECC_HW12_2048:
-		this->eccbytes += 4;
-	case NAND_ECC_HW8_512:
-		this->eccbytes += 2;
-	case NAND_ECC_HW6_512:
-		this->eccbytes += 3;
-	case NAND_ECC_HW3_512:
-	case NAND_ECC_HW3_256:
-		if (this->calculate_ecc && this->correct_data && this->enable_hwecc)
-			break;
-		printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n");
-		BUG();
-	}
-
-	mtd->eccsize = this->eccsize;
-
-	/* Set the number of read / write steps for one page to ensure ECC generation */
-	switch (this->eccmode) {
-	case NAND_ECC_HW12_2048:
-		this->eccsteps = mtd->oobblock / 2048;
-		break;
-	case NAND_ECC_HW3_512:
-	case NAND_ECC_HW6_512:
-	case NAND_ECC_HW8_512:
-		this->eccsteps = mtd->oobblock / 512;
-		break;
-	case NAND_ECC_HW3_256:
-	case NAND_ECC_SOFT:
-		this->eccsteps = mtd->oobblock / 256;
-		break;
-
-	case NAND_ECC_NONE:
-		this->eccsteps = 1;
-		break;
-	}
-
-	/* Initialize state, waitqueue and spinlock */
-	this->state = FL_READY;
-	init_waitqueue_head (&this->wq);
-	spin_lock_init (&this->chip_lock);
+	/* Initialize state */
+	chip->state = FL_READY;
 
 	/* De-select the device */
-	this->select_chip(mtd, -1);
+	chip->select_chip(mtd, -1);
 
 	/* Invalidate the pagebuffer reference */
-	this->pagebuf = -1;
+	chip->pagebuf = -1;
 
 	/* Fill in remaining MTD driver data */
 	mtd->type = MTD_NANDFLASH;
-	mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
+	mtd->flags = MTD_CAP_NANDFLASH;
 	mtd->ecctype = MTD_ECC_SW;
 	mtd->erase = nand_erase;
 	mtd->point = NULL;
 	mtd->unpoint = NULL;
 	mtd->read = nand_read;
 	mtd->write = nand_write;
-	mtd->read_ecc = nand_read_ecc;
-	mtd->write_ecc = nand_write_ecc;
 	mtd->read_oob = nand_read_oob;
 	mtd->write_oob = nand_write_oob;
-	mtd->readv = NULL;
-	mtd->writev = nand_writev;
-	mtd->writev_ecc = nand_writev_ecc;
 	mtd->sync = nand_sync;
 	mtd->lock = NULL;
 	mtd->unlock = NULL;
@@ -2692,47 +2490,38 @@
 	mtd->block_isbad = nand_block_isbad;
 	mtd->block_markbad = nand_block_markbad;
 
-	/* and make the autooob the default one */
-	memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
-
-	mtd->owner = THIS_MODULE;
+	/* propagate ecc.layout to mtd_info */
+	mtd->ecclayout = chip->ecc.layout;
 
 	/* Check, if we should skip the bad block table scan */
-	if (this->options & NAND_SKIP_BBTSCAN)
+	if (chip->options & NAND_SKIP_BBTSCAN)
 		return 0;
 
 	/* Build bad block table */
-	return this->scan_bbt (mtd);
+	return chip->scan_bbt(mtd);
 }
 
 /**
  * nand_release - [NAND Interface] Free resources held by the NAND device
  * @mtd:	MTD device structure
 */
-void nand_release (struct mtd_info *mtd)
+void nand_release(struct mtd_info *mtd)
 {
-	struct nand_chip *this = mtd->priv;
+	struct nand_chip *chip = mtd->priv;
 
 #ifdef CONFIG_MTD_PARTITIONS
 	/* Deregister partitions */
-	del_mtd_partitions (mtd);
+	del_mtd_partitions(mtd);
 #endif
 	/* Deregister the device */
-	del_mtd_device (mtd);
+	del_mtd_device(mtd);
 
 	/* Free bad block table memory */
-	kfree (this->bbt);
-	/* Buffer allocated by nand_scan ? */
-	if (this->options & NAND_OOBBUF_ALLOC)
-		kfree (this->oob_buf);
-	/* Buffer allocated by nand_scan ? */
-	if (this->options & NAND_DATABUF_ALLOC)
-		kfree (this->data_buf);
+	kfree(chip->bbt);
 }
 
-EXPORT_SYMBOL_GPL (nand_scan);
-EXPORT_SYMBOL_GPL (nand_release);
-
+EXPORT_SYMBOL_GPL(nand_scan);
+EXPORT_SYMBOL_GPL(nand_release);
 
 static int __init nand_base_init(void)
 {
@@ -2748,6 +2537,6 @@
 module_init(nand_base_init);
 module_exit(nand_base_exit);
 
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION ("Generic NAND flash driver code");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Generic NAND flash driver code");
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ca28699..a612c4e 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -48,7 +48,7 @@
  *
  * Following assumptions are made:
  * - bbts start at a page boundary, if autolocated on a block boundary
- * - the space neccecary for a bbt in FLASH does not exceed a block boundary
+ * - the space necessary for a bbt in FLASH does not exceed a block boundary
  *
  */
 
@@ -60,7 +60,7 @@
 #include <linux/mtd/compatmac.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
-
+#include <linux/vmalloc.h>
 
 /**
  * check_pattern - [GENERIC] check if a pattern is in the buffer
@@ -75,7 +75,7 @@
  * pattern area contain 0xff
  *
 */
-static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
+static int check_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td)
 {
 	int i, end = 0;
 	uint8_t *p = buf;
@@ -116,7 +116,7 @@
  * no optional empty check
  *
 */
-static int check_short_pattern (uint8_t *buf, struct nand_bbt_descr *td)
+static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
 {
 	int i;
 	uint8_t *p = buf;
@@ -142,8 +142,8 @@
  * Read the bad block table starting from page.
  *
  */
-static int read_bbt (struct mtd_info *mtd, uint8_t *buf, int page, int num,
-	int bits, int offs, int reserved_block_code)
+static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
+		    int bits, int offs, int reserved_block_code)
 {
 	int res, i, j, act = 0;
 	struct nand_chip *this = mtd->priv;
@@ -152,17 +152,17 @@
 	uint8_t msk = (uint8_t) ((1 << bits) - 1);
 
 	totlen = (num * bits) >> 3;
-	from = ((loff_t)page) << this->page_shift;
+	from = ((loff_t) page) << this->page_shift;
 
 	while (totlen) {
-		len = min (totlen, (size_t) (1 << this->bbt_erase_shift));
-		res = mtd->read_ecc (mtd, from, len, &retlen, buf, NULL, this->autooob);
+		len = min(totlen, (size_t) (1 << this->bbt_erase_shift));
+		res = mtd->read(mtd, from, len, &retlen, buf);
 		if (res < 0) {
 			if (retlen != len) {
-				printk (KERN_INFO "nand_bbt: Error reading bad block table\n");
+				printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
 				return res;
 			}
-			printk (KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
+			printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
 		}
 
 		/* Analyse data */
@@ -172,22 +172,23 @@
 				uint8_t tmp = (dat >> j) & msk;
 				if (tmp == msk)
 					continue;
-				if (reserved_block_code &&
-				    (tmp == reserved_block_code)) {
-					printk (KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
-						((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+				if (reserved_block_code && (tmp == reserved_block_code)) {
+					printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%08x\n",
+					       ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
+					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
 				/* Leave it for now, if its matured we can move this
 				 * message to MTD_DEBUG_LEVEL0 */
-				printk (KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
-					((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+				printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%08x\n",
+				       ((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out ? */
 				if (tmp == 0)
 					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
 				else
 					this->bbt[offs + (act >> 3)] |= 0x1 << (act & 0x06);
+				mtd->ecc_stats.badblocks++;
 			}
 		}
 		totlen -= len;
@@ -207,7 +208,7 @@
  * Read the bad block table for all chips starting at a given page
  * We assume that the bbt bits are in consecutive order.
 */
-static int read_abs_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
+static int read_abs_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td, int chip)
 {
 	struct nand_chip *this = mtd->priv;
 	int res = 0, i;
@@ -231,6 +232,42 @@
 	return 0;
 }
 
+/*
+ * Scan read raw data from flash
+ */
+static int scan_read_raw(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
+			 size_t len)
+{
+	struct mtd_oob_ops ops;
+
+	ops.mode = MTD_OOB_RAW;
+	ops.ooboffs = 0;
+	ops.ooblen = mtd->oobsize;
+	ops.oobbuf = buf;
+	ops.datbuf = buf;
+	ops.len = len;
+
+	return mtd->read_oob(mtd, offs, &ops);
+}
+
+/*
+ * Scan write data with oob to flash
+ */
+static int scan_write_bbt(struct mtd_info *mtd, loff_t offs, size_t len,
+			  uint8_t *buf, uint8_t *oob)
+{
+	struct mtd_oob_ops ops;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooboffs = 0;
+	ops.ooblen = mtd->oobsize;
+	ops.datbuf = buf;
+	ops.oobbuf = oob;
+	ops.len = len;
+
+	return mtd->write_oob(mtd, offs, &ops);
+}
+
 /**
  * read_abs_bbts - [GENERIC] Read the bad block table(s) for all chips starting at a given page
  * @mtd:	MTD device structure
@@ -242,28 +279,85 @@
  * We assume that the bbt bits are in consecutive order.
  *
 */
-static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td,
-	struct nand_bbt_descr *md)
+static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
+			 struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
 	struct nand_chip *this = mtd->priv;
 
 	/* Read the primary version, if available */
 	if (td->options & NAND_BBT_VERSION) {
-		nand_read_raw (mtd, buf, td->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
-		td->version[0] = buf[mtd->oobblock + td->veroffs];
-		printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", td->pages[0], td->version[0]);
+		scan_read_raw(mtd, buf, td->pages[0] << this->page_shift,
+			      mtd->writesize);
+		td->version[0] = buf[mtd->writesize + td->veroffs];
+		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+		       td->pages[0], td->version[0]);
 	}
 
 	/* Read the mirror version, if available */
 	if (md && (md->options & NAND_BBT_VERSION)) {
-		nand_read_raw (mtd, buf, md->pages[0] << this->page_shift, mtd->oobblock, mtd->oobsize);
-		md->version[0] = buf[mtd->oobblock + md->veroffs];
-		printk (KERN_DEBUG "Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]);
+		scan_read_raw(mtd, buf, md->pages[0] << this->page_shift,
+			      mtd->writesize);
+		md->version[0] = buf[mtd->writesize + md->veroffs];
+		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+		       md->pages[0], md->version[0]);
 	}
-
 	return 1;
 }
 
+/*
+ * Scan a given block full
+ */
+static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+			   loff_t offs, uint8_t *buf, size_t readlen,
+			   int scanlen, int len)
+{
+	int ret, j;
+
+	ret = scan_read_raw(mtd, buf, offs, readlen);
+	if (ret)
+		return ret;
+
+	for (j = 0; j < len; j++, buf += scanlen) {
+		if (check_pattern(buf, scanlen, mtd->writesize, bd))
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Scan a given block partially
+ */
+static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
+			   loff_t offs, uint8_t *buf, int len)
+{
+	struct mtd_oob_ops ops;
+	int j, ret;
+
+	ops.len = mtd->oobsize;
+	ops.ooblen = mtd->oobsize;
+	ops.oobbuf = buf;
+	ops.ooboffs = 0;
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_PLACE;
+
+	for (j = 0; j < len; j++) {
+		/*
+		 * Read the full oob until read_oob is fixed to
+		 * handle single byte reads for 16 bit
+		 * buswidth
+		 */
+		ret = mtd->read_oob(mtd, offs, &ops);
+		if (ret)
+			return ret;
+
+		if (check_short_pattern(buf, bd))
+			return 1;
+
+		offs += mtd->writesize;
+	}
+	return 0;
+}
+
 /**
  * create_bbt - [GENERIC] Create a bad block table by scanning the device
  * @mtd:	MTD device structure
@@ -275,15 +369,16 @@
  * Create a bad block table by scanning the device
  * for the given good/bad block identify pattern
  */
-static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
+static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
+	struct nand_bbt_descr *bd, int chip)
 {
 	struct nand_chip *this = mtd->priv;
-	int i, j, numblocks, len, scanlen;
+	int i, numblocks, len, scanlen;
 	int startblock;
 	loff_t from;
-	size_t readlen, ooblen;
+	size_t readlen;
 
-	printk (KERN_INFO "Scanning device for bad blocks\n");
+	printk(KERN_INFO "Scanning device for bad blocks\n");
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
@@ -296,25 +391,24 @@
 
 	if (!(bd->options & NAND_BBT_SCANEMPTY)) {
 		/* We need only read few bytes from the OOB area */
-		scanlen = ooblen = 0;
+		scanlen = 0;
 		readlen = bd->len;
 	} else {
 		/* Full page content should be read */
-		scanlen	= mtd->oobblock + mtd->oobsize;
-		readlen = len * mtd->oobblock;
-		ooblen = len * mtd->oobsize;
+		scanlen = mtd->writesize + mtd->oobsize;
+		readlen = len * mtd->writesize;
 	}
 
 	if (chip == -1) {
-		/* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
-		 * makes shifting and masking less painful */
+		/* Note that numblocks is 2 * (real numblocks) here, see i+=2
+		 * below as it makes shifting and masking less painful */
 		numblocks = mtd->size >> (this->bbt_erase_shift - 1);
 		startblock = 0;
 		from = 0;
 	} else {
 		if (chip >= this->numchips) {
-			printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
-				chip + 1, this->numchips);
+			printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
+			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
 		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
@@ -326,36 +420,22 @@
 	for (i = startblock; i < numblocks;) {
 		int ret;
 
-		if (bd->options & NAND_BBT_SCANEMPTY)
-			if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen)))
-				return ret;
+		if (bd->options & NAND_BBT_SCANALLPAGES)
+			ret = scan_block_full(mtd, bd, from, buf, readlen,
+					      scanlen, len);
+		else
+			ret = scan_block_fast(mtd, bd, from, buf, len);
 
-		for (j = 0; j < len; j++) {
-			if (!(bd->options & NAND_BBT_SCANEMPTY)) {
-				size_t retlen;
+		if (ret < 0)
+			return ret;
 
-				/* Read the full oob until read_oob is fixed to
-				 * handle single byte reads for 16 bit buswidth */
-				ret = mtd->read_oob(mtd, from + j * mtd->oobblock,
-							mtd->oobsize, &retlen, buf);
-				if (ret)
-					return ret;
-
-				if (check_short_pattern (buf, bd)) {
-					this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-					printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
-						i >> 1, (unsigned int) from);
-					break;
-				}
-			} else {
-				if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
-					this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-					printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
-						i >> 1, (unsigned int) from);
-					break;
-				}
-			}
+		if (ret) {
+			this->bbt[i >> 3] |= 0x03 << (i & 0x6);
+			printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
+			       i >> 1, (unsigned int)from);
+			mtd->ecc_stats.badblocks++;
 		}
+
 		i += 2;
 		from += (1 << this->bbt_erase_shift);
 	}
@@ -374,22 +454,23 @@
  * block.
  * If the option NAND_BBT_PERCHIP is given, each chip is searched
  * for a bbt, which contains the bad block information of this chip.
- * This is neccecary to provide support for certain DOC devices.
+ * This is necessary to provide support for certain DOC devices.
  *
  * The bbt ident pattern resides in the oob area of the first page
  * in a block.
  */
-static int search_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
+static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *td)
 {
 	struct nand_chip *this = mtd->priv;
 	int i, chips;
 	int bits, startblock, block, dir;
-	int scanlen = mtd->oobblock + mtd->oobsize;
+	int scanlen = mtd->writesize + mtd->oobsize;
 	int bbtblocks;
+	int blocktopage = this->bbt_erase_shift - this->page_shift;
 
 	/* Search direction top -> down ? */
 	if (td->options & NAND_BBT_LASTBLOCK) {
-		startblock = (mtd->size >> this->bbt_erase_shift) -1;
+		startblock = (mtd->size >> this->bbt_erase_shift) - 1;
 		dir = -1;
 	} else {
 		startblock = 0;
@@ -415,13 +496,16 @@
 		td->pages[i] = -1;
 		/* Scan the maximum number of blocks */
 		for (block = 0; block < td->maxblocks; block++) {
+
 			int actblock = startblock + dir * block;
+			loff_t offs = actblock << this->bbt_erase_shift;
+
 			/* Read first page */
-			nand_read_raw (mtd, buf, actblock << this->bbt_erase_shift, mtd->oobblock, mtd->oobsize);
-			if (!check_pattern(buf, scanlen, mtd->oobblock, td)) {
-				td->pages[i] = actblock << (this->bbt_erase_shift - this->page_shift);
+			scan_read_raw(mtd, buf, offs, mtd->writesize);
+			if (!check_pattern(buf, scanlen, mtd->writesize, td)) {
+				td->pages[i] = actblock << blocktopage;
 				if (td->options & NAND_BBT_VERSION) {
-					td->version[i] = buf[mtd->oobblock + td->veroffs];
+					td->version[i] = buf[mtd->writesize + td->veroffs];
 				}
 				break;
 			}
@@ -431,9 +515,10 @@
 	/* Check, if we found a bbt for each requested chip */
 	for (i = 0; i < chips; i++) {
 		if (td->pages[i] == -1)
-			printk (KERN_WARNING "Bad block table not found for chip %d\n", i);
+			printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
 		else
-			printk (KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i], td->version[i]);
+			printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
+			       td->version[i]);
 	}
 	return 0;
 }
@@ -447,21 +532,19 @@
  *
  * Search and read the bad block table(s)
 */
-static int search_read_bbts (struct mtd_info *mtd, uint8_t *buf,
-	struct nand_bbt_descr *td, struct nand_bbt_descr *md)
+static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt_descr *td, struct nand_bbt_descr *md)
 {
 	/* Search the primary table */
-	search_bbt (mtd, buf, td);
+	search_bbt(mtd, buf, td);
 
 	/* Search the mirror table */
 	if (md)
-		search_bbt (mtd, buf, md);
+		search_bbt(mtd, buf, md);
 
 	/* Force result check */
 	return 1;
 }
 
-
 /**
  * write_bbt - [GENERIC] (Re)write the bad block table
  *
@@ -474,25 +557,31 @@
  * (Re)write the bad block table
  *
 */
-static int write_bbt (struct mtd_info *mtd, uint8_t *buf,
-	struct nand_bbt_descr *td, struct nand_bbt_descr *md, int chipsel)
+static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
+		     struct nand_bbt_descr *td, struct nand_bbt_descr *md,
+		     int chipsel)
 {
 	struct nand_chip *this = mtd->priv;
-	struct nand_oobinfo oobinfo;
 	struct erase_info einfo;
 	int i, j, res, chip = 0;
 	int bits, startblock, dir, page, offs, numblocks, sft, sftmsk;
-	int nrchips, bbtoffs, pageoffs;
+	int nrchips, bbtoffs, pageoffs, ooboffs;
 	uint8_t msk[4];
 	uint8_t rcode = td->reserved_block_code;
 	size_t retlen, len = 0;
 	loff_t to;
+	struct mtd_oob_ops ops;
+
+	ops.ooblen = mtd->oobsize;
+	ops.ooboffs = 0;
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_PLACE;
 
 	if (!rcode)
 		rcode = 0xff;
 	/* Write bad block table per chip rather than per device ? */
 	if (td->options & NAND_BBT_PERCHIP) {
-		numblocks = (int) (this->chipsize >> this->bbt_erase_shift);
+		numblocks = (int)(this->chipsize >> this->bbt_erase_shift);
 		/* Full device write or specific chip ? */
 		if (chipsel == -1) {
 			nrchips = this->numchips;
@@ -501,7 +590,7 @@
 			chip = chipsel;
 		}
 	} else {
-		numblocks = (int) (mtd->size >> this->bbt_erase_shift);
+		numblocks = (int)(mtd->size >> this->bbt_erase_shift);
 		nrchips = 1;
 	}
 
@@ -530,27 +619,38 @@
 		for (i = 0; i < td->maxblocks; i++) {
 			int block = startblock + dir * i;
 			/* Check, if the block is bad */
-			switch ((this->bbt[block >> 2] >> (2 * (block & 0x03))) & 0x03) {
+			switch ((this->bbt[block >> 2] >>
+				 (2 * (block & 0x03))) & 0x03) {
 			case 0x01:
 			case 0x03:
 				continue;
 			}
-			page = block << (this->bbt_erase_shift - this->page_shift);
+			page = block <<
+				(this->bbt_erase_shift - this->page_shift);
 			/* Check, if the block is used by the mirror table */
 			if (!md || md->pages[chip] != page)
 				goto write;
 		}
-		printk (KERN_ERR "No space left to write bad block table\n");
+		printk(KERN_ERR "No space left to write bad block table\n");
 		return -ENOSPC;
-write:
+	write:
 
 		/* Set up shift count and masks for the flash table */
 		bits = td->options & NAND_BBT_NRBITS_MSK;
+		msk[2] = ~rcode;
 		switch (bits) {
-		case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x01; break;
-		case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01; msk[2] = ~rcode; msk[3] = 0x03; break;
-		case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C; msk[2] = ~rcode; msk[3] = 0x0f; break;
-		case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F; msk[2] = ~rcode; msk[3] = 0xff; break;
+		case 1: sft = 3; sftmsk = 0x07; msk[0] = 0x00; msk[1] = 0x01;
+			msk[3] = 0x01;
+			break;
+		case 2: sft = 2; sftmsk = 0x06; msk[0] = 0x00; msk[1] = 0x01;
+			msk[3] = 0x03;
+			break;
+		case 4: sft = 1; sftmsk = 0x04; msk[0] = 0x00; msk[1] = 0x0C;
+			msk[3] = 0x0f;
+			break;
+		case 8: sft = 0; sftmsk = 0x00; msk[0] = 0x00; msk[1] = 0x0F;
+			msk[3] = 0xff;
+			break;
 		default: return -EINVAL;
 		}
 
@@ -558,82 +658,92 @@
 
 		to = ((loff_t) page) << this->page_shift;
 
-		memcpy (&oobinfo, this->autooob, sizeof(oobinfo));
-		oobinfo.useecc = MTD_NANDECC_PLACEONLY;
-
 		/* Must we save the block contents ? */
 		if (td->options & NAND_BBT_SAVECONTENT) {
 			/* Make it block aligned */
 			to &= ~((loff_t) ((1 << this->bbt_erase_shift) - 1));
 			len = 1 << this->bbt_erase_shift;
-			res = mtd->read_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
+			res = mtd->read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
 				if (retlen != len) {
-					printk (KERN_INFO "nand_bbt: Error reading block for writing the bad block table\n");
+					printk(KERN_INFO "nand_bbt: Error "
+					       "reading block for writing "
+					       "the bad block table\n");
 					return res;
 				}
-				printk (KERN_WARNING "nand_bbt: ECC error while reading block for writing bad block table\n");
+				printk(KERN_WARNING "nand_bbt: ECC error "
+				       "while reading block for writing "
+				       "bad block table\n");
 			}
+			/* Read oob data */
+			ops.len = (len >> this->page_shift) * mtd->oobsize;
+			ops.oobbuf = &buf[len];
+			res = mtd->read_oob(mtd, to + mtd->writesize, &ops);
+			if (res < 0 || ops.retlen != ops.len)
+				goto outerr;
+
 			/* Calc the byte offset in the buffer */
 			pageoffs = page - (int)(to >> this->page_shift);
 			offs = pageoffs << this->page_shift;
 			/* Preset the bbt area with 0xff */
-			memset (&buf[offs], 0xff, (size_t)(numblocks >> sft));
-			/* Preset the bbt's oob area with 0xff */
-			memset (&buf[len + pageoffs * mtd->oobsize], 0xff,
-				((len >> this->page_shift) - pageoffs) * mtd->oobsize);
-			if (td->options & NAND_BBT_VERSION) {
-				buf[len + (pageoffs * mtd->oobsize) + td->veroffs] = td->version[chip];
-			}
+			memset(&buf[offs], 0xff, (size_t) (numblocks >> sft));
+			ooboffs = len + (pageoffs * mtd->oobsize);
+
 		} else {
 			/* Calc length */
 			len = (size_t) (numblocks >> sft);
 			/* Make it page aligned ! */
-			len = (len + (mtd->oobblock-1)) & ~(mtd->oobblock-1);
+			len = (len + (mtd->writesize - 1)) &
+				~(mtd->writesize - 1);
 			/* Preset the buffer with 0xff */
-			memset (buf, 0xff, len + (len >> this->page_shift) * mtd->oobsize);
+			memset(buf, 0xff, len +
+			       (len >> this->page_shift)* mtd->oobsize);
 			offs = 0;
+			ooboffs = len;
 			/* Pattern is located in oob area of first page */
-			memcpy (&buf[len + td->offs], td->pattern, td->len);
-			if (td->options & NAND_BBT_VERSION) {
-				buf[len + td->veroffs] = td->version[chip];
-			}
+			memcpy(&buf[ooboffs + td->offs], td->pattern, td->len);
 		}
 
+		if (td->options & NAND_BBT_VERSION)
+			buf[ooboffs + td->veroffs] = td->version[chip];
+
 		/* walk through the memory table */
-		for (i = 0; i < numblocks; ) {
+		for (i = 0; i < numblocks;) {
 			uint8_t dat;
 			dat = this->bbt[bbtoffs + (i >> 2)];
-			for (j = 0; j < 4; j++ , i++) {
+			for (j = 0; j < 4; j++, i++) {
 				int sftcnt = (i << (3 - sft)) & sftmsk;
 				/* Do not store the reserved bbt blocks ! */
-				buf[offs + (i >> sft)] &= ~(msk[dat & 0x03] << sftcnt);
+				buf[offs + (i >> sft)] &=
+					~(msk[dat & 0x03] << sftcnt);
 				dat >>= 2;
 			}
 		}
 
-		memset (&einfo, 0, sizeof (einfo));
+		memset(&einfo, 0, sizeof(einfo));
 		einfo.mtd = mtd;
-		einfo.addr = (unsigned long) to;
+		einfo.addr = (unsigned long)to;
 		einfo.len = 1 << this->bbt_erase_shift;
-		res = nand_erase_nand (mtd, &einfo, 1);
-		if (res < 0) {
-			printk (KERN_WARNING "nand_bbt: Error during block erase: %d\n", res);
-			return res;
-		}
+		res = nand_erase_nand(mtd, &einfo, 1);
+		if (res < 0)
+			goto outerr;
 
-		res = mtd->write_ecc (mtd, to, len, &retlen, buf, &buf[len], &oobinfo);
-		if (res < 0) {
-			printk (KERN_WARNING "nand_bbt: Error while writing bad block table %d\n", res);
-			return res;
-		}
-		printk (KERN_DEBUG "Bad block table written to 0x%08x, version 0x%02X\n",
-			(unsigned int) to, td->version[chip]);
+		res = scan_write_bbt(mtd, to, len, buf, &buf[len]);
+		if (res < 0)
+			goto outerr;
+
+		printk(KERN_DEBUG "Bad block table written to 0x%08x, version "
+		       "0x%02X\n", (unsigned int)to, td->version[chip]);
 
 		/* Mark it as used */
 		td->pages[chip] = page;
 	}
 	return 0;
+
+ outerr:
+	printk(KERN_WARNING
+	       "nand_bbt: Error while writing bad block table %d\n", res);
+	return res;
 }
 
 /**
@@ -644,27 +754,27 @@
  * The function creates a memory based bbt by scanning the device
  * for manufacturer / software marked good / bad blocks
 */
-static inline int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
+static inline int nand_memory_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
 	struct nand_chip *this = mtd->priv;
 
 	bd->options &= ~NAND_BBT_SCANEMPTY;
-	return create_bbt (mtd, this->data_buf, bd, -1);
+	return create_bbt(mtd, this->buffers.databuf, bd, -1);
 }
 
 /**
- * check_create - [GENERIC] create and write bbt(s) if neccecary
+ * check_create - [GENERIC] create and write bbt(s) if necessary
  * @mtd:	MTD device structure
  * @buf:	temporary buffer
  * @bd:		descriptor for the good/bad block search pattern
  *
  * The function checks the results of the previous call to read_bbt
- * and creates / updates the bbt(s) if neccecary
- * Creation is neccecary if no bbt was found for the chip/device
- * Update is neccecary if one of the tables is missing or the
+ * and creates / updates the bbt(s) if necessary
+ * Creation is necessary if no bbt was found for the chip/device
+ * Update is necessary if one of the tables is missing or the
  * version nr. of one table is less than the other
 */
-static int check_create (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
+static int check_create(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd)
 {
 	int i, chips, writeops, chipsel, res;
 	struct nand_chip *this = mtd->priv;
@@ -732,35 +842,35 @@
 			rd = td;
 			goto writecheck;
 		}
-create:
+	create:
 		/* Create the bad block table by scanning the device ? */
 		if (!(td->options & NAND_BBT_CREATE))
 			continue;
 
 		/* Create the table in memory by scanning the chip(s) */
-		create_bbt (mtd, buf, bd, chipsel);
+		create_bbt(mtd, buf, bd, chipsel);
 
 		td->version[i] = 1;
 		if (md)
 			md->version[i] = 1;
-writecheck:
+	writecheck:
 		/* read back first ? */
 		if (rd)
-			read_abs_bbt (mtd, buf, rd, chipsel);
+			read_abs_bbt(mtd, buf, rd, chipsel);
 		/* If they weren't versioned, read both. */
 		if (rd2)
-			read_abs_bbt (mtd, buf, rd2, chipsel);
+			read_abs_bbt(mtd, buf, rd2, chipsel);
 
 		/* Write the bad block table to the device ? */
 		if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
-			res = write_bbt (mtd, buf, td, md, chipsel);
+			res = write_bbt(mtd, buf, td, md, chipsel);
 			if (res < 0)
 				return res;
 		}
 
 		/* Write the mirror bad block table to the device ? */
 		if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
-			res = write_bbt (mtd, buf, md, td, chipsel);
+			res = write_bbt(mtd, buf, md, td, chipsel);
 			if (res < 0)
 				return res;
 		}
@@ -777,7 +887,7 @@
  * accidental erasures / writes. The regions are identified by
  * the mark 0x02.
 */
-static void mark_bbt_region (struct mtd_info *mtd, struct nand_bbt_descr *td)
+static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
 {
 	struct nand_chip *this = mtd->priv;
 	int i, j, chips, block, nrblocks, update;
@@ -795,7 +905,8 @@
 	for (i = 0; i < chips; i++) {
 		if ((td->options & NAND_BBT_ABSPAGE) ||
 		    !(td->options & NAND_BBT_WRITE)) {
-		    	if (td->pages[i] == -1) continue;
+			if (td->pages[i] == -1)
+				continue;
 			block = td->pages[i] >> (this->bbt_erase_shift - this->page_shift);
 			block <<= 1;
 			oldval = this->bbt[(block >> 3)];
@@ -815,7 +926,8 @@
 			oldval = this->bbt[(block >> 3)];
 			newval = oldval | (0x2 << (block & 0x06));
 			this->bbt[(block >> 3)] = newval;
-			if (oldval != newval) update = 1;
+			if (oldval != newval)
+				update = 1;
 			block += 2;
 		}
 		/* If we want reserved blocks to be recorded to flash, and some
@@ -840,7 +952,7 @@
  * by calling the nand_free_bbt function.
  *
 */
-int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
+int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
 	struct nand_chip *this = mtd->priv;
 	int len, res = 0;
@@ -850,21 +962,21 @@
 
 	len = mtd->size >> (this->bbt_erase_shift + 2);
 	/* Allocate memory (2bit per block) */
-	this->bbt = kmalloc (len, GFP_KERNEL);
+	this->bbt = kmalloc(len, GFP_KERNEL);
 	if (!this->bbt) {
-		printk (KERN_ERR "nand_scan_bbt: Out of memory\n");
+		printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
 		return -ENOMEM;
 	}
 	/* Clear the memory bad block table */
-	memset (this->bbt, 0x00, len);
+	memset(this->bbt, 0x00, len);
 
 	/* If no primary table decriptor is given, scan the device
 	 * to build a memory based bad block table
 	 */
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
-			printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
-			kfree (this->bbt);
+			printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+			kfree(this->bbt);
 			this->bbt = NULL;
 		}
 		return res;
@@ -873,35 +985,34 @@
 	/* Allocate a temporary buffer for one eraseblock incl. oob */
 	len = (1 << this->bbt_erase_shift);
 	len += (len >> this->page_shift) * mtd->oobsize;
-	buf = kmalloc (len, GFP_KERNEL);
+	buf = vmalloc(len);
 	if (!buf) {
-		printk (KERN_ERR "nand_bbt: Out of memory\n");
-		kfree (this->bbt);
+		printk(KERN_ERR "nand_bbt: Out of memory\n");
+		kfree(this->bbt);
 		this->bbt = NULL;
 		return -ENOMEM;
 	}
 
 	/* Is the bbt at a given page ? */
 	if (td->options & NAND_BBT_ABSPAGE) {
-		res = read_abs_bbts (mtd, buf, td, md);
+		res = read_abs_bbts(mtd, buf, td, md);
 	} else {
 		/* Search the bad block table using a pattern in oob */
-		res = search_read_bbts (mtd, buf, td, md);
+		res = search_read_bbts(mtd, buf, td, md);
 	}
 
 	if (res)
-		res = check_create (mtd, buf, bd);
+		res = check_create(mtd, buf, bd);
 
 	/* Prevent the bbt regions from erasing / writing */
-	mark_bbt_region (mtd, td);
+	mark_bbt_region(mtd, td);
 	if (md)
-		mark_bbt_region (mtd, md);
+		mark_bbt_region(mtd, md);
 
-	kfree (buf);
+	vfree(buf);
 	return res;
 }
 
-
 /**
  * nand_update_bbt - [NAND Interface] update bad block table(s)
  * @mtd:	MTD device structure
@@ -909,7 +1020,7 @@
  *
  * The function updates the bad block table(s)
 */
-int nand_update_bbt (struct mtd_info *mtd, loff_t offs)
+int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 {
 	struct nand_chip *this = mtd->priv;
 	int len, res = 0, writeops = 0;
@@ -925,9 +1036,9 @@
 	/* Allocate a temporary buffer for one eraseblock incl. oob */
 	len = (1 << this->bbt_erase_shift);
 	len += (len >> this->page_shift) * mtd->oobsize;
-	buf = kmalloc (len, GFP_KERNEL);
+	buf = kmalloc(len, GFP_KERNEL);
 	if (!buf) {
-		printk (KERN_ERR "nand_update_bbt: Out of memory\n");
+		printk(KERN_ERR "nand_update_bbt: Out of memory\n");
 		return -ENOMEM;
 	}
 
@@ -935,7 +1046,7 @@
 
 	/* Do we have a bbt per chip ? */
 	if (td->options & NAND_BBT_PERCHIP) {
-		chip = (int) (offs >> this->chip_shift);
+		chip = (int)(offs >> this->chip_shift);
 		chipsel = chip;
 	} else {
 		chip = 0;
@@ -948,17 +1059,17 @@
 
 	/* Write the bad block table to the device ? */
 	if ((writeops & 0x01) && (td->options & NAND_BBT_WRITE)) {
-		res = write_bbt (mtd, buf, td, md, chipsel);
+		res = write_bbt(mtd, buf, td, md, chipsel);
 		if (res < 0)
 			goto out;
 	}
 	/* Write the mirror bad block table to the device ? */
 	if ((writeops & 0x02) && md && (md->options & NAND_BBT_WRITE)) {
-		res = write_bbt (mtd, buf, md, td, chipsel);
+		res = write_bbt(mtd, buf, md, td, chipsel);
 	}
 
-out:
-	kfree (buf);
+ out:
+	kfree(buf);
 	return res;
 }
 
@@ -981,14 +1092,14 @@
 };
 
 static struct nand_bbt_descr smallpage_flashbased = {
-	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = 5,
 	.len = 1,
 	.pattern = scan_ff_pattern
 };
 
 static struct nand_bbt_descr largepage_flashbased = {
-	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+	.options = NAND_BBT_SCAN2NDPAGE,
 	.offs = 0,
 	.len = 2,
 	.pattern = scan_ff_pattern
@@ -1036,7 +1147,7 @@
  * support for the device and calls the nand_scan_bbt function
  *
 */
-int nand_default_bbt (struct mtd_info *mtd)
+int nand_default_bbt(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
 
@@ -1046,7 +1157,7 @@
 	 * of the good / bad information, so we _must_ store
 	 * this information in a good / bad table during
 	 * startup
-	*/
+	 */
 	if (this->options & NAND_IS_AND) {
 		/* Use the default pattern descriptors */
 		if (!this->bbt_td) {
@@ -1054,10 +1165,9 @@
 			this->bbt_md = &bbt_mirror_descr;
 		}
 		this->options |= NAND_USE_FLASH_BBT;
-		return nand_scan_bbt (mtd, &agand_flashbased);
+		return nand_scan_bbt(mtd, &agand_flashbased);
 	}
 
-
 	/* Is a flash based bad block table requested ? */
 	if (this->options & NAND_USE_FLASH_BBT) {
 		/* Use the default pattern descriptors */
@@ -1066,18 +1176,17 @@
 			this->bbt_md = &bbt_mirror_descr;
 		}
 		if (!this->badblock_pattern) {
-			this->badblock_pattern = (mtd->oobblock > 512) ?
-				&largepage_flashbased : &smallpage_flashbased;
+			this->badblock_pattern = (mtd->writesize > 512) ? &largepage_flashbased : &smallpage_flashbased;
 		}
 	} else {
 		this->bbt_td = NULL;
 		this->bbt_md = NULL;
 		if (!this->badblock_pattern) {
-			this->badblock_pattern = (mtd->oobblock > 512) ?
-				&largepage_memorybased : &smallpage_memorybased;
+			this->badblock_pattern = (mtd->writesize > 512) ?
+			    &largepage_memorybased : &smallpage_memorybased;
 		}
 	}
-	return nand_scan_bbt (mtd, this->badblock_pattern);
+	return nand_scan_bbt(mtd, this->badblock_pattern);
 }
 
 /**
@@ -1087,26 +1196,29 @@
  * @allowbbt:	allow access to bad block table region
  *
 */
-int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
+int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 {
 	struct nand_chip *this = mtd->priv;
 	int block;
-	uint8_t	res;
+	uint8_t res;
 
 	/* Get block number * 2 */
-	block = (int) (offs >> (this->bbt_erase_shift - 1));
+	block = (int)(offs >> (this->bbt_erase_shift - 1));
 	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-	DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
-		(unsigned int)offs, block >> 1, res);
+	DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
+	      (unsigned int)offs, block >> 1, res);
 
 	switch ((int)res) {
-	case 0x00:	return 0;
-	case 0x01:	return 1;
-	case 0x02:	return allowbbt ? 0 : 1;
+	case 0x00:
+		return 0;
+	case 0x01:
+		return 1;
+	case 0x02:
+		return allowbbt ? 0 : 1;
 	}
 	return 1;
 }
 
-EXPORT_SYMBOL (nand_scan_bbt);
-EXPORT_SYMBOL (nand_default_bbt);
+EXPORT_SYMBOL(nand_scan_bbt);
+EXPORT_SYMBOL(nand_default_bbt);
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 40ac909..2a163e4 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -7,6 +7,8 @@
  * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
  *                         Toshiba America Electronics Components, Inc.
  *
+ * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
  * $Id: nand_ecc.c,v 1.15 2005/11/07 11:14:30 gleixner Exp $
  *
  * This file is free software; you can redistribute it and/or modify it
@@ -62,90 +64,76 @@
 	0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
 };
 
-
 /**
- * nand_trans_result - [GENERIC] create non-inverted ECC
- * @reg2:	line parity reg 2
- * @reg3:	line parity reg 3
- * @ecc_code:	ecc
- *
- * Creates non-inverted ECC code from line parity
- */
-static void nand_trans_result(u_char reg2, u_char reg3,
-	u_char *ecc_code)
-{
-	u_char a, b, i, tmp1, tmp2;
-
-	/* Initialize variables */
-	a = b = 0x80;
-	tmp1 = tmp2 = 0;
-
-	/* Calculate first ECC byte */
-	for (i = 0; i < 4; i++) {
-		if (reg3 & a)		/* LP15,13,11,9 --> ecc_code[0] */
-			tmp1 |= b;
-		b >>= 1;
-		if (reg2 & a)		/* LP14,12,10,8 --> ecc_code[0] */
-			tmp1 |= b;
-		b >>= 1;
-		a >>= 1;
-	}
-
-	/* Calculate second ECC byte */
-	b = 0x80;
-	for (i = 0; i < 4; i++) {
-		if (reg3 & a)		/* LP7,5,3,1 --> ecc_code[1] */
-			tmp2 |= b;
-		b >>= 1;
-		if (reg2 & a)		/* LP6,4,2,0 --> ecc_code[1] */
-			tmp2 |= b;
-		b >>= 1;
-		a >>= 1;
-	}
-
-	/* Store two of the ECC bytes */
-	ecc_code[0] = tmp1;
-	ecc_code[1] = tmp2;
-}
-
-/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code for 256 byte block
+ * nand_calculate_ecc - [NAND Interface] Calculate 3 byte ECC code
+ *			for 256 byte block
  * @mtd:	MTD block structure
  * @dat:	raw data
  * @ecc_code:	buffer for ECC
  */
-int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
+int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+		       u_char *ecc_code)
 {
-	u_char idx, reg1, reg2, reg3;
-	int j;
+	uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
+	int i;
 
 	/* Initialize variables */
 	reg1 = reg2 = reg3 = 0;
-	ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
 
 	/* Build up column parity */
-	for(j = 0; j < 256; j++) {
-
+	for(i = 0; i < 256; i++) {
 		/* Get CP0 - CP5 from table */
-		idx = nand_ecc_precalc_table[dat[j]];
+		idx = nand_ecc_precalc_table[*dat++];
 		reg1 ^= (idx & 0x3f);
 
 		/* All bit XOR = 1 ? */
 		if (idx & 0x40) {
-			reg3 ^= (u_char) j;
-			reg2 ^= ~((u_char) j);
+			reg3 ^= (uint8_t) i;
+			reg2 ^= ~((uint8_t) i);
 		}
 	}
 
 	/* Create non-inverted ECC code from line parity */
-	nand_trans_result(reg2, reg3, ecc_code);
+	tmp1  = (reg3 & 0x80) >> 0; /* B7 -> B7 */
+	tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
+	tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
+	tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
+	tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
+	tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
+	tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
+	tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
+
+	tmp2  = (reg3 & 0x08) << 4; /* B3 -> B7 */
+	tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
+	tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
+	tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
+	tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
+	tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
+	tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
+	tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
 
 	/* Calculate final ECC code */
-	ecc_code[0] = ~ecc_code[0];
-	ecc_code[1] = ~ecc_code[1];
+#ifdef CONFIG_NAND_ECC_SMC
+	ecc_code[0] = ~tmp2;
+	ecc_code[1] = ~tmp1;
+#else
+	ecc_code[0] = ~tmp1;
+	ecc_code[1] = ~tmp2;
+#endif
 	ecc_code[2] = ((~reg1) << 2) | 0x03;
+
 	return 0;
 }
+EXPORT_SYMBOL(nand_calculate_ecc);
+
+static inline int countbits(uint32_t byte)
+{
+	int res = 0;
+
+	for (;byte; byte >>= 1)
+		res += byte & 0x01;
+	return res;
+}
 
 /**
  * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
@@ -156,93 +144,54 @@
  *
  * Detect and correct a 1 bit error for 256 byte block
  */
-int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
+int nand_correct_data(struct mtd_info *mtd, u_char *dat,
+		      u_char *read_ecc, u_char *calc_ecc)
 {
-	u_char a, b, c, d1, d2, d3, add, bit, i;
+	uint8_t s0, s1, s2;
 
-	/* Do error detection */
-	d1 = calc_ecc[0] ^ read_ecc[0];
-	d2 = calc_ecc[1] ^ read_ecc[1];
-	d3 = calc_ecc[2] ^ read_ecc[2];
-
-	if ((d1 | d2 | d3) == 0) {
-		/* No errors */
+#ifdef CONFIG_NAND_ECC_SMC
+	s0 = calc_ecc[0] ^ read_ecc[0];
+	s1 = calc_ecc[1] ^ read_ecc[1];
+	s2 = calc_ecc[2] ^ read_ecc[2];
+#else
+	s1 = calc_ecc[0] ^ read_ecc[0];
+	s0 = calc_ecc[1] ^ read_ecc[1];
+	s2 = calc_ecc[2] ^ read_ecc[2];
+#endif
+	if ((s0 | s1 | s2) == 0)
 		return 0;
-	}
-	else {
-		a = (d1 ^ (d1 >> 1)) & 0x55;
-		b = (d2 ^ (d2 >> 1)) & 0x55;
-		c = (d3 ^ (d3 >> 1)) & 0x54;
 
-		/* Found and will correct single bit error in the data */
-		if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
-			c = 0x80;
-			add = 0;
-			a = 0x80;
-			for (i=0; i<4; i++) {
-				if (d1 & c)
-					add |= a;
-				c >>= 2;
-				a >>= 1;
-			}
-			c = 0x80;
-			for (i=0; i<4; i++) {
-				if (d2 & c)
-					add |= a;
-				c >>= 2;
-				a >>= 1;
-			}
-			bit = 0;
-			b = 0x04;
-			c = 0x80;
-			for (i=0; i<3; i++) {
-				if (d3 & c)
-					bit |= b;
-				c >>= 2;
-				b >>= 1;
-			}
-			b = 0x01;
-			a = dat[add];
-			a ^= (b << bit);
-			dat[add] = a;
-			return 1;
-		}
-		else {
-			i = 0;
-			while (d1) {
-				if (d1 & 0x01)
-					++i;
-				d1 >>= 1;
-			}
-			while (d2) {
-				if (d2 & 0x01)
-					++i;
-				d2 >>= 1;
-			}
-			while (d3) {
-				if (d3 & 0x01)
-					++i;
-				d3 >>= 1;
-			}
-			if (i == 1) {
-				/* ECC Code Error Correction */
-				read_ecc[0] = calc_ecc[0];
-				read_ecc[1] = calc_ecc[1];
-				read_ecc[2] = calc_ecc[2];
-				return 2;
-			}
-			else {
-				/* Uncorrectable Error */
-				return -1;
-			}
-		}
+	/* Check for a single bit error */
+	if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
+	    ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
+	    ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
+
+		uint32_t byteoffs, bitnum;
+
+		byteoffs = (s1 << 0) & 0x80;
+		byteoffs |= (s1 << 1) & 0x40;
+		byteoffs |= (s1 << 2) & 0x20;
+		byteoffs |= (s1 << 3) & 0x10;
+
+		byteoffs |= (s0 >> 4) & 0x08;
+		byteoffs |= (s0 >> 3) & 0x04;
+		byteoffs |= (s0 >> 2) & 0x02;
+		byteoffs |= (s0 >> 1) & 0x01;
+
+		bitnum = (s2 >> 5) & 0x04;
+		bitnum |= (s2 >> 4) & 0x02;
+		bitnum |= (s2 >> 3) & 0x01;
+
+		dat[byteoffs] ^= (1 << bitnum);
+
+		return 1;
 	}
 
-	/* Should never happen */
+	if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
+		return 1;
+
 	return -1;
 }
-
-EXPORT_SYMBOL(nand_calculate_ecc);
 EXPORT_SYMBOL(nand_correct_data);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c
index dbc7e55..2e2cdf2 100644
--- a/drivers/mtd/nand/nand_ids.c
+++ b/drivers/mtd/nand/nand_ids.c
@@ -18,99 +18,110 @@
 *	Name. ID code, pagesize, chipsize in MegaByte, eraseblock size,
 *	options
 *
-* 	Pagesize; 0, 256, 512
-*	0 	get this information from the extended chip ID
+*	Pagesize; 0, 256, 512
+*	0	get this information from the extended chip ID
 +	256	256 Byte page size
 *	512	512 Byte page size
 */
 struct nand_flash_dev nand_flash_ids[] = {
-	{"NAND 1MiB 5V 8-bit", 		0x6e, 256, 1, 0x1000, 0},
-	{"NAND 2MiB 5V 8-bit", 		0x64, 256, 2, 0x1000, 0},
-	{"NAND 4MiB 5V 8-bit", 		0x6b, 512, 4, 0x2000, 0},
-	{"NAND 1MiB 3,3V 8-bit", 	0xe8, 256, 1, 0x1000, 0},
-	{"NAND 1MiB 3,3V 8-bit", 	0xec, 256, 1, 0x1000, 0},
-	{"NAND 2MiB 3,3V 8-bit", 	0xea, 256, 2, 0x1000, 0},
-	{"NAND 4MiB 3,3V 8-bit", 	0xd5, 512, 4, 0x2000, 0},
-	{"NAND 4MiB 3,3V 8-bit", 	0xe3, 512, 4, 0x2000, 0},
-	{"NAND 4MiB 3,3V 8-bit", 	0xe5, 512, 4, 0x2000, 0},
-	{"NAND 8MiB 3,3V 8-bit", 	0xd6, 512, 8, 0x2000, 0},
+	{"NAND 1MiB 5V 8-bit",		0x6e, 256, 1, 0x1000, 0},
+	{"NAND 2MiB 5V 8-bit",		0x64, 256, 2, 0x1000, 0},
+	{"NAND 4MiB 5V 8-bit",		0x6b, 512, 4, 0x2000, 0},
+	{"NAND 1MiB 3,3V 8-bit",	0xe8, 256, 1, 0x1000, 0},
+	{"NAND 1MiB 3,3V 8-bit",	0xec, 256, 1, 0x1000, 0},
+	{"NAND 2MiB 3,3V 8-bit",	0xea, 256, 2, 0x1000, 0},
+	{"NAND 4MiB 3,3V 8-bit",	0xd5, 512, 4, 0x2000, 0},
+	{"NAND 4MiB 3,3V 8-bit",	0xe3, 512, 4, 0x2000, 0},
+	{"NAND 4MiB 3,3V 8-bit",	0xe5, 512, 4, 0x2000, 0},
+	{"NAND 8MiB 3,3V 8-bit",	0xd6, 512, 8, 0x2000, 0},
 
-	{"NAND 8MiB 1,8V 8-bit", 	0x39, 512, 8, 0x2000, 0},
-	{"NAND 8MiB 3,3V 8-bit", 	0xe6, 512, 8, 0x2000, 0},
-	{"NAND 8MiB 1,8V 16-bit", 	0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
-	{"NAND 8MiB 3,3V 16-bit", 	0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+	{"NAND 8MiB 1,8V 8-bit",	0x39, 512, 8, 0x2000, 0},
+	{"NAND 8MiB 3,3V 8-bit",	0xe6, 512, 8, 0x2000, 0},
+	{"NAND 8MiB 1,8V 16-bit",	0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+	{"NAND 8MiB 3,3V 16-bit",	0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
 
-	{"NAND 16MiB 1,8V 8-bit", 	0x33, 512, 16, 0x4000, 0},
-	{"NAND 16MiB 3,3V 8-bit", 	0x73, 512, 16, 0x4000, 0},
-	{"NAND 16MiB 1,8V 16-bit", 	0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 16MiB 3,3V 16-bit", 	0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 16MiB 1,8V 8-bit",	0x33, 512, 16, 0x4000, 0},
+	{"NAND 16MiB 3,3V 8-bit",	0x73, 512, 16, 0x4000, 0},
+	{"NAND 16MiB 1,8V 16-bit",	0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 16MiB 3,3V 16-bit",	0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
 
-	{"NAND 32MiB 1,8V 8-bit", 	0x35, 512, 32, 0x4000, 0},
-	{"NAND 32MiB 3,3V 8-bit", 	0x75, 512, 32, 0x4000, 0},
-	{"NAND 32MiB 1,8V 16-bit", 	0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 32MiB 3,3V 16-bit", 	0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 32MiB 1,8V 8-bit",	0x35, 512, 32, 0x4000, 0},
+	{"NAND 32MiB 3,3V 8-bit",	0x75, 512, 32, 0x4000, 0},
+	{"NAND 32MiB 1,8V 16-bit",	0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 32MiB 3,3V 16-bit",	0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
 
-	{"NAND 64MiB 1,8V 8-bit", 	0x36, 512, 64, 0x4000, 0},
-	{"NAND 64MiB 3,3V 8-bit", 	0x76, 512, 64, 0x4000, 0},
-	{"NAND 64MiB 1,8V 16-bit", 	0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 64MiB 3,3V 16-bit", 	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 64MiB 1,8V 8-bit",	0x36, 512, 64, 0x4000, 0},
+	{"NAND 64MiB 3,3V 8-bit",	0x76, 512, 64, 0x4000, 0},
+	{"NAND 64MiB 1,8V 16-bit",	0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 64MiB 3,3V 16-bit",	0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
 
-	{"NAND 128MiB 1,8V 8-bit", 	0x78, 512, 128, 0x4000, 0},
-	{"NAND 128MiB 1,8V 8-bit", 	0x39, 512, 128, 0x4000, 0},
-	{"NAND 128MiB 3,3V 8-bit", 	0x79, 512, 128, 0x4000, 0},
-	{"NAND 128MiB 1,8V 16-bit", 	0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 128MiB 1,8V 16-bit", 	0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 128MiB 3,3V 16-bit", 	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-	{"NAND 128MiB 3,3V 16-bit", 	0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 128MiB 1,8V 8-bit",	0x78, 512, 128, 0x4000, 0},
+	{"NAND 128MiB 1,8V 8-bit",	0x39, 512, 128, 0x4000, 0},
+	{"NAND 128MiB 3,3V 8-bit",	0x79, 512, 128, 0x4000, 0},
+	{"NAND 128MiB 1,8V 16-bit",	0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 128MiB 1,8V 16-bit",	0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 128MiB 3,3V 16-bit",	0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
+	{"NAND 128MiB 3,3V 16-bit",	0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
 
-	{"NAND 256MiB 3,3V 8-bit", 	0x71, 512, 256, 0x4000, 0},
+	{"NAND 256MiB 3,3V 8-bit",	0x71, 512, 256, 0x4000, 0},
 
-	/* These are the new chips with large page size. The pagesize
-	* and the erasesize is determined from the extended id bytes
-	*/
+	/*
+	 * These are the new chips with large page size. The pagesize and the
+	 * erasesize is determined from the extended id bytes
+	 */
+#define LP_OPTIONS (NAND_SAMSUNG_LP_OPTIONS | NAND_NO_READRDY | NAND_NO_AUTOINCR)
+#define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
+
 	/*512 Megabit */
-	{"NAND 64MiB 1,8V 8-bit", 	0xA2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 64MiB 3,3V 8-bit", 	0xF2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 64MiB 1,8V 16-bit", 	0xB2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	{"NAND 64MiB 3,3V 16-bit", 	0xC2, 0,  64, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+	{"NAND 64MiB 1,8V 8-bit",	0xA2, 0,  64, 0, LP_OPTIONS},
+	{"NAND 64MiB 3,3V 8-bit",	0xF2, 0,  64, 0, LP_OPTIONS},
+	{"NAND 64MiB 1,8V 16-bit",	0xB2, 0,  64, 0, LP_OPTIONS16},
+	{"NAND 64MiB 3,3V 16-bit",	0xC2, 0,  64, 0, LP_OPTIONS16},
 
 	/* 1 Gigabit */
-	{"NAND 128MiB 1,8V 8-bit", 	0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 128MiB 3,3V 8-bit", 	0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 128MiB 1,8V 16-bit", 	0xB1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	{"NAND 128MiB 3,3V 16-bit", 	0xC1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+	{"NAND 128MiB 1,8V 8-bit",	0xA1, 0, 128, 0, LP_OPTIONS},
+	{"NAND 128MiB 3,3V 8-bit",	0xF1, 0, 128, 0, LP_OPTIONS},
+	{"NAND 128MiB 1,8V 16-bit",	0xB1, 0, 128, 0, LP_OPTIONS16},
+	{"NAND 128MiB 3,3V 16-bit",	0xC1, 0, 128, 0, LP_OPTIONS16},
 
 	/* 2 Gigabit */
-	{"NAND 256MiB 1,8V 8-bit", 	0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 256MiB 3,3V 8-bit", 	0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 256MiB 1,8V 16-bit", 	0xBA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	{"NAND 256MiB 3,3V 16-bit", 	0xCA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+	{"NAND 256MiB 1,8V 8-bit",	0xAA, 0, 256, 0, LP_OPTIONS},
+	{"NAND 256MiB 3,3V 8-bit",	0xDA, 0, 256, 0, LP_OPTIONS},
+	{"NAND 256MiB 1,8V 16-bit",	0xBA, 0, 256, 0, LP_OPTIONS16},
+	{"NAND 256MiB 3,3V 16-bit",	0xCA, 0, 256, 0, LP_OPTIONS16},
 
 	/* 4 Gigabit */
-	{"NAND 512MiB 1,8V 8-bit", 	0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 512MiB 3,3V 8-bit", 	0xDC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 512MiB 1,8V 16-bit", 	0xBC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	{"NAND 512MiB 3,3V 16-bit", 	0xCC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+	{"NAND 512MiB 1,8V 8-bit",	0xAC, 0, 512, 0, LP_OPTIONS},
+	{"NAND 512MiB 3,3V 8-bit",	0xDC, 0, 512, 0, LP_OPTIONS},
+	{"NAND 512MiB 1,8V 16-bit",	0xBC, 0, 512, 0, LP_OPTIONS16},
+	{"NAND 512MiB 3,3V 16-bit",	0xCC, 0, 512, 0, LP_OPTIONS16},
 
 	/* 8 Gigabit */
-	{"NAND 1GiB 1,8V 8-bit", 	0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 1GiB 3,3V 8-bit", 	0xD3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 1GiB 1,8V 16-bit", 	0xB3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	{"NAND 1GiB 3,3V 16-bit", 	0xC3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+	{"NAND 1GiB 1,8V 8-bit",	0xA3, 0, 1024, 0, LP_OPTIONS},
+	{"NAND 1GiB 3,3V 8-bit",	0xD3, 0, 1024, 0, LP_OPTIONS},
+	{"NAND 1GiB 1,8V 16-bit",	0xB3, 0, 1024, 0, LP_OPTIONS16},
+	{"NAND 1GiB 3,3V 16-bit",	0xC3, 0, 1024, 0, LP_OPTIONS16},
 
 	/* 16 Gigabit */
-	{"NAND 2GiB 1,8V 8-bit", 	0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 2GiB 3,3V 8-bit", 	0xD5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR},
-	{"NAND 2GiB 1,8V 16-bit", 	0xB5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
-	{"NAND 2GiB 3,3V 16-bit", 	0xC5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_BUSWIDTH_16 | NAND_NO_AUTOINCR},
+	{"NAND 2GiB 1,8V 8-bit",	0xA5, 0, 2048, 0, LP_OPTIONS},
+	{"NAND 2GiB 3,3V 8-bit",	0xD5, 0, 2048, 0, LP_OPTIONS},
+	{"NAND 2GiB 1,8V 16-bit",	0xB5, 0, 2048, 0, LP_OPTIONS16},
+	{"NAND 2GiB 3,3V 16-bit",	0xC5, 0, 2048, 0, LP_OPTIONS16},
 
-	/* Renesas AND 1 Gigabit. Those chips do not support extended id and have a strange page/block layout !
-	 * The chosen minimum erasesize is 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page planes
-	 * 1 block = 2 pages, but due to plane arrangement the blocks 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7
-	 * Anyway JFFS2 would increase the eraseblock size so we chose a combined one which can be erased in one go
-	 * There are more speed improvements for reads and writes possible, but not implemented now
+	/*
+	 * Renesas AND 1 Gigabit. Those chips do not support extended id and
+	 * have a strange page/block layout !  The chosen minimum erasesize is
+	 * 4 * 2 * 2048 = 16384 Byte, as those chips have an array of 4 page
+	 * planes 1 block = 2 pages, but due to plane arrangement the blocks
+	 * 0-3 consists of page 0 + 4,1 + 5, 2 + 6, 3 + 7 Anyway JFFS2 would
+	 * increase the eraseblock size so we chose a combined one which can be
+	 * erased in one go There are more speed improvements for reads and
+	 * writes possible, but not implemented now
 	 */
-	{"AND 128MiB 3,3V 8-bit",	0x01, 2048, 128, 0x4000, NAND_IS_AND | NAND_NO_AUTOINCR | NAND_4PAGE_ARRAY | BBT_AUTO_REFRESH},
+	{"AND 128MiB 3,3V 8-bit",	0x01, 2048, 128, 0x4000,
+	 NAND_IS_AND | NAND_NO_AUTOINCR |NAND_NO_READRDY | NAND_4PAGE_ARRAY |
+	 BBT_AUTO_REFRESH
+	},
 
 	{NULL,}
 };
@@ -125,13 +136,13 @@
 	{NAND_MFR_NATIONAL, "National"},
 	{NAND_MFR_RENESAS, "Renesas"},
 	{NAND_MFR_STMICRO, "ST Micro"},
-        {NAND_MFR_HYNIX, "Hynix"},
+	{NAND_MFR_HYNIX, "Hynix"},
 	{0x0, "Unknown"}
 };
 
-EXPORT_SYMBOL (nand_manuf_ids);
-EXPORT_SYMBOL (nand_flash_ids);
+EXPORT_SYMBOL(nand_manuf_ids);
+EXPORT_SYMBOL(nand_flash_ids);
 
-MODULE_LICENSE ("GPL");
-MODULE_AUTHOR ("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION ("Nand device & manufacturer ID's");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Nand device & manufacturer IDs");
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
index a0af92c..ebd64ab 100644
--- a/drivers/mtd/nand/nandsim.c
+++ b/drivers/mtd/nand/nandsim.c
@@ -369,7 +369,7 @@
 	/* Initialize the NAND flash parameters */
 	ns->busw = chip->options & NAND_BUSWIDTH_16 ? 16 : 8;
 	ns->geom.totsz    = mtd->size;
-	ns->geom.pgsz     = mtd->oobblock;
+	ns->geom.pgsz     = mtd->writesize;
 	ns->geom.oobsz    = mtd->oobsize;
 	ns->geom.secsz    = mtd->erasesize;
 	ns->geom.pgszoob  = ns->geom.pgsz + ns->geom.oobsz;
@@ -1071,68 +1071,6 @@
 	}
 }
 
-static void
-ns_hwcontrol(struct mtd_info *mtd, int cmd)
-{
-	struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
-
-	switch (cmd) {
-
-	/* set CLE line high */
-	case NAND_CTL_SETCLE:
-		NS_DBG("ns_hwcontrol: start command latch cycles\n");
-		ns->lines.cle  = 1;
-		break;
-
-	/* set CLE line low */
-	case NAND_CTL_CLRCLE:
-		NS_DBG("ns_hwcontrol: stop command latch cycles\n");
-		ns->lines.cle  = 0;
-		break;
-
-	/* set ALE line high */
-	case NAND_CTL_SETALE:
-		NS_DBG("ns_hwcontrol: start address latch cycles\n");
-		ns->lines.ale   = 1;
-		break;
-
-	/* set ALE line low */
-	case NAND_CTL_CLRALE:
-		NS_DBG("ns_hwcontrol: stop address latch cycles\n");
-		ns->lines.ale  = 0;
-		break;
-
-	/* set WP line high */
-	case NAND_CTL_SETWP:
-		NS_DBG("ns_hwcontrol: enable write protection\n");
-		ns->lines.wp = 1;
-		break;
-
-	/* set WP line low */
-	case NAND_CTL_CLRWP:
-		NS_DBG("ns_hwcontrol: disable write protection\n");
-		ns->lines.wp = 0;
-		break;
-
-	/* set CE line low */
-	case NAND_CTL_SETNCE:
-		NS_DBG("ns_hwcontrol: enable chip\n");
-		ns->lines.ce = 1;
-		break;
-
-	/* set CE line high */
-	case NAND_CTL_CLRNCE:
-		NS_DBG("ns_hwcontrol: disable chip\n");
-		ns->lines.ce = 0;
-		break;
-
-	default:
-		NS_ERR("hwcontrol: unknown command\n");
-        }
-
-	return;
-}
-
 static u_char
 ns_nand_read_byte(struct mtd_info *mtd)
 {
@@ -1359,6 +1297,18 @@
 	return;
 }
 
+static void ns_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int bitmask)
+{
+	struct nandsim *ns = ((struct nand_chip *)mtd->priv)->priv;
+
+	ns->lines.cle = bitmask & NAND_CLE ? 1 : 0;
+	ns->lines.ale = bitmask & NAND_ALE ? 1 : 0;
+	ns->lines.ce = bitmask & NAND_NCE ? 1 : 0;
+
+	if (cmd != NAND_CMD_NONE)
+		ns_nand_write_byte(mtd, cmd);
+}
+
 static int
 ns_device_ready(struct mtd_info *mtd)
 {
@@ -1377,17 +1327,6 @@
 }
 
 static void
-ns_nand_write_word(struct mtd_info *mtd, uint16_t word)
-{
-	struct nand_chip *chip = (struct nand_chip *)mtd->priv;
-
-	NS_DBG("write_word\n");
-
-	chip->write_byte(mtd, word & 0xFF);
-	chip->write_byte(mtd, word >> 8);
-}
-
-static void
 ns_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
         struct nandsim *ns = (struct nandsim *)((struct nand_chip *)mtd->priv)->priv;
@@ -1514,16 +1453,14 @@
 	/*
 	 * Register simulator's callbacks.
 	 */
-	chip->hwcontrol  = ns_hwcontrol;
+	chip->cmd_ctrl	 = ns_hwcontrol;
 	chip->read_byte  = ns_nand_read_byte;
 	chip->dev_ready  = ns_device_ready;
-	chip->write_byte = ns_nand_write_byte;
 	chip->write_buf  = ns_nand_write_buf;
 	chip->read_buf   = ns_nand_read_buf;
 	chip->verify_buf = ns_nand_verify_buf;
-	chip->write_word = ns_nand_write_word;
 	chip->read_word  = ns_nand_read_word;
-	chip->eccmode    = NAND_ECC_SOFT;
+	chip->ecc.mode   = NAND_ECC_SOFT;
 	chip->options   |= NAND_SKIP_BBTSCAN;
 
 	/*
@@ -1546,6 +1483,8 @@
 		chip->options |= NAND_BUSWIDTH_16;
 	}
 
+	nsmtd->owner = THIS_MODULE;
+
 	if ((retval = nand_scan(nsmtd, 1)) != 0) {
 		NS_ERR("can't register NAND Simulator\n");
 		if (retval > 0)
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
new file mode 100644
index 0000000..e5bd88f
--- /dev/null
+++ b/drivers/mtd/nand/ndfc.c
@@ -0,0 +1,311 @@
+/*
+ *  drivers/mtd/ndfc.c
+ *
+ *  Overview:
+ *   Platform independend driver for NDFC (NanD Flash Controller)
+ *   integrated into EP440 cores
+ *
+ *  Author: Thomas Gleixner
+ *
+ *  Copyright 2006 IBM
+ *
+ *  This program is free software; you can redistribute	 it and/or modify it
+ *  under  the terms of	 the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the	License, or (at your
+ *  option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/ndfc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/ibm44x.h>
+
+struct ndfc_nand_mtd {
+	struct mtd_info			mtd;
+	struct nand_chip		chip;
+	struct platform_nand_chip	*pl_chip;
+};
+
+static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS];
+
+struct ndfc_controller {
+	void __iomem		*ndfcbase;
+	struct nand_hw_control	ndfc_control;
+	atomic_t		childs_active;
+};
+
+static struct ndfc_controller ndfc_ctrl;
+
+static void ndfc_select_chip(struct mtd_info *mtd, int chip)
+{
+	uint32_t ccr;
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *nandchip = mtd->priv;
+	struct ndfc_nand_mtd *nandmtd = nandchip->priv;
+	struct platform_nand_chip *pchip = nandmtd->pl_chip;
+
+	ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+	if (chip >= 0) {
+		ccr &= ~NDFC_CCR_BS_MASK;
+		ccr |= NDFC_CCR_BS(chip + pchip->chip_offset);
+	} else
+		ccr |= NDFC_CCR_RESET_CE;
+	writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+}
+
+static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+	if (cmd == NAND_CMD_NONE)
+		return;
+
+	if (ctrl & NAND_CLE)
+		writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD);
+	else
+		writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE);
+}
+
+static int ndfc_ready(struct mtd_info *mtd)
+{
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+	return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY;
+}
+
+static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+	uint32_t ccr;
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+
+	ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR);
+	ccr |= NDFC_CCR_RESET_ECC;
+	__raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR);
+	wmb();
+}
+
+static int ndfc_calculate_ecc(struct mtd_info *mtd,
+			      const u_char *dat, u_char *ecc_code)
+{
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	uint32_t ecc;
+	uint8_t *p = (uint8_t *)&ecc;
+
+	wmb();
+	ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC);
+	ecc_code[0] = p[1];
+	ecc_code[1] = p[2];
+	ecc_code[2] = p[3];
+
+	return 0;
+}
+
+/*
+ * Speedups for buffer read/write/verify
+ *
+ * NDFC allows 32bit read/write of data. So we can speed up the buffer
+ * functions. No further checking, as nand_base will always read/write
+ * page aligned.
+ */
+static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	uint32_t *p = (uint32_t *) buf;
+
+	for(;len > 0; len -= 4)
+		*p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA);
+}
+
+static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	uint32_t *p = (uint32_t *) buf;
+
+	for(;len > 0; len -= 4)
+		__raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA);
+}
+
+static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	uint32_t *p = (uint32_t *) buf;
+
+	for(;len > 0; len -= 4)
+		if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA))
+			return -EFAULT;
+	return 0;
+}
+
+/*
+ * Initialize chip structure
+ */
+static void ndfc_chip_init(struct ndfc_nand_mtd *mtd)
+{
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct nand_chip *chip = &mtd->chip;
+
+	chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
+	chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA;
+	chip->cmd_ctrl = ndfc_hwcontrol;
+	chip->dev_ready = ndfc_ready;
+	chip->select_chip = ndfc_select_chip;
+	chip->chip_delay = 50;
+	chip->priv = mtd;
+	chip->options = mtd->pl_chip->options;
+	chip->controller = &ndfc->ndfc_control;
+	chip->read_buf = ndfc_read_buf;
+	chip->write_buf = ndfc_write_buf;
+	chip->verify_buf = ndfc_verify_buf;
+	chip->ecc.correct = nand_correct_data;
+	chip->ecc.hwctl = ndfc_enable_hwecc;
+	chip->ecc.calculate = ndfc_calculate_ecc;
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = 256;
+	chip->ecc.bytes = 3;
+	chip->ecclayout = mtd->pl_chip->ecclayout;
+	mtd->mtd.priv = chip;
+	mtd->mtd.owner = THIS_MODULE;
+}
+
+static int ndfc_chip_probe(struct platform_device *pdev)
+{
+	struct platform_nand_chip *nc = pdev->dev.platform_data;
+	struct ndfc_chip_settings *settings = nc->priv;
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	struct ndfc_nand_mtd *nandmtd;
+
+	if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS)
+		return -EINVAL;
+
+	/* Set the bank settings */
+	__raw_writel(settings->bank_settings,
+		     ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2));
+
+	nandmtd = &ndfc_mtd[pdev->id];
+	if (nandmtd->pl_chip)
+		return -EBUSY;
+
+	nandmtd->pl_chip = nc;
+	ndfc_chip_init(nandmtd);
+
+	/* Scan for chips */
+	if (nand_scan(&nandmtd->mtd, nc->nr_chips)) {
+		nandmtd->pl_chip = NULL;
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	printk("Number of partitions %d\n", nc->nr_partitions);
+	if (nc->nr_partitions) {
+		/* Add the full device, so complete dumps can be made */
+		add_mtd_device(&nandmtd->mtd);
+		add_mtd_partitions(&nandmtd->mtd, nc->partitions,
+				   nc->nr_partitions);
+
+	} else
+#else
+		add_mtd_device(&nandmtd->mtd);
+#endif
+
+	atomic_inc(&ndfc->childs_active);
+	return 0;
+}
+
+static int ndfc_chip_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int ndfc_nand_probe(struct platform_device *pdev)
+{
+	struct platform_nand_ctrl *nc = pdev->dev.platform_data;
+	struct ndfc_controller_settings *settings = nc->priv;
+	struct resource *res = pdev->resource;
+	struct ndfc_controller *ndfc = &ndfc_ctrl;
+	unsigned long long phys = settings->ndfc_erpn | res->start;
+
+	ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
+	if (!ndfc->ndfcbase) {
+		printk(KERN_ERR "NDFC: ioremap failed\n");
+		return -EIO;
+	}
+
+	__raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR);
+
+	spin_lock_init(&ndfc->ndfc_control.lock);
+	init_waitqueue_head(&ndfc->ndfc_control.wq);
+
+	platform_set_drvdata(pdev, ndfc);
+
+	printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n",
+	       __raw_readl(ndfc->ndfcbase + NDFC_REVID));
+
+	return 0;
+}
+
+static int ndfc_nand_remove(struct platform_device *pdev)
+{
+	struct ndfc_controller *ndfc = platform_get_drvdata(pdev);
+
+	if (atomic_read(&ndfc->childs_active))
+		return -EBUSY;
+
+	if (ndfc) {
+		platform_set_drvdata(pdev, NULL);
+		iounmap(ndfc_ctrl.ndfcbase);
+		ndfc_ctrl.ndfcbase = NULL;
+	}
+	return 0;
+}
+
+/* driver device registration */
+
+static struct platform_driver ndfc_chip_driver = {
+	.probe		= ndfc_chip_probe,
+	.remove		= ndfc_chip_remove,
+	.driver		= {
+		.name	= "ndfc-chip",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static struct platform_driver ndfc_nand_driver = {
+	.probe		= ndfc_nand_probe,
+	.remove		= ndfc_nand_remove,
+	.driver		= {
+		.name	= "ndfc-nand",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ndfc_nand_init(void)
+{
+	int ret;
+
+	spin_lock_init(&ndfc_ctrl.ndfc_control.lock);
+	init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq);
+
+	ret = platform_driver_register(&ndfc_nand_driver);
+	if (!ret)
+		ret = platform_driver_register(&ndfc_chip_driver);
+	return ret;
+}
+
+static void __exit ndfc_nand_exit(void)
+{
+	platform_driver_unregister(&ndfc_chip_driver);
+	platform_driver_unregister(&ndfc_nand_driver);
+}
+
+module_init(ndfc_nand_init);
+module_exit(ndfc_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
+MODULE_DESCRIPTION("Platform driver for NDFC");
diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 91a95f3..22fa65c 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -58,21 +58,21 @@
 /*
  * MTD structure for PPChameleonEVB board
  */
-static struct mtd_info *ppchameleon_mtd 	= NULL;
+static struct mtd_info *ppchameleon_mtd = NULL;
 static struct mtd_info *ppchameleonevb_mtd = NULL;
 
 /*
  * Module stuff
  */
-static unsigned long ppchameleon_fio_pbase 	= CFG_NAND0_PADDR;
+static unsigned long ppchameleon_fio_pbase = CFG_NAND0_PADDR;
 static unsigned long ppchameleonevb_fio_pbase = CFG_NAND1_PADDR;
 
 #ifdef MODULE
 module_param(ppchameleon_fio_pbase, ulong, 0);
 module_param(ppchameleonevb_fio_pbase, ulong, 0);
 #else
-__setup("ppchameleon_fio_pbase=",ppchameleon_fio_pbase);
-__setup("ppchameleonevb_fio_pbase=",ppchameleonevb_fio_pbase);
+__setup("ppchameleon_fio_pbase=", ppchameleon_fio_pbase);
+__setup("ppchameleonevb_fio_pbase=", ppchameleonevb_fio_pbase);
 #endif
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -80,82 +80,96 @@
  * Define static partitions for flash devices
  */
 static struct mtd_partition partition_info_hi[] = {
-	{ name: "PPChameleon HI Nand Flash",
-		  offset: 0,
-		  size: 128*1024*1024 }
+      { .name = "PPChameleon HI Nand Flash",
+	offset = 0,
+	.size = 128 * 1024 * 1024
+      }
 };
 
 static struct mtd_partition partition_info_me[] = {
-	{ name: "PPChameleon ME Nand Flash",
-		  offset: 0,
-		  size: 32*1024*1024 }
+      { .name = "PPChameleon ME Nand Flash",
+	.offset = 0,
+	.size = 32 * 1024 * 1024
+      }
 };
 
 static struct mtd_partition partition_info_evb[] = {
-	{ name: "PPChameleonEVB Nand Flash",
-		  offset: 0,
-		  size: 32*1024*1024 }
+      { .name = "PPChameleonEVB Nand Flash",
+	.offset = 0,
+	.size = 32 * 1024 * 1024
+      }
 };
 
 #define NUM_PARTITIONS 1
 
-extern int parse_cmdline_partitions(struct mtd_info *master,
-				    struct mtd_partition **pparts,
-				    const char *mtd_id);
+extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
 #endif
 
-
 /*
  *	hardware specific access to control-lines
  */
-static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ppchameleon_hwcontrol(struct mtd_info *mtdinfo, int cmd,
+				  unsigned int ctrl)
 {
-	switch(cmd) {
+	struct nand_chip *chip = mtd->priv;
 
-	case NAND_CTL_SETCLE:
-        	MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
-		break;
-	case NAND_CTL_CLRCLE:
-        	MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
-		break;
-	case NAND_CTL_SETALE:
-        	MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
-		break;
-	case NAND_CTL_CLRALE:
-        	MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
-		break;
-	case NAND_CTL_SETNCE:
+	if (ctrl & NAND_CTRL_CHANGE) {
+#error Missing headerfiles. No way to fix this. -tglx
+		switch (cmd) {
+		case NAND_CTL_SETCLE:
+			MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND0_PADDR);
+			break;
+		case NAND_CTL_CLRCLE:
+			MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND0_PADDR);
+			break;
+		case NAND_CTL_SETALE:
+			MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND0_PADDR);
+			break;
+		case NAND_CTL_CLRALE:
+			MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND0_PADDR);
+			break;
+		case NAND_CTL_SETNCE:
 			MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND0_PADDR);
-		break;
-	case NAND_CTL_CLRNCE:
+			break;
+		case NAND_CTL_CLRNCE:
 			MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND0_PADDR);
-		break;
+			break;
+		}
 	}
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
 }
 
-static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
+static void ppchameleonevb_hwcontrol(struct mtd_info *mtdinfo, int cmd,
+				     unsigned int ctrl)
 {
-	switch(cmd) {
+	struct nand_chip *chip = mtd->priv;
 
-	case NAND_CTL_SETCLE:
-        	MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
-		break;
-	case NAND_CTL_CLRCLE:
-        	MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
-		break;
-	case NAND_CTL_SETALE:
-        	MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
-		break;
-	case NAND_CTL_CLRALE:
-        	MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
-		break;
-	case NAND_CTL_SETNCE:
-        	MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
-		break;
-	case NAND_CTL_CLRNCE:
-        	MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
-		break;
+	if (ctrl & NAND_CTRL_CHANGE) {
+#error Missing headerfiles. No way to fix this. -tglx
+		switch (cmd) {
+		case NAND_CTL_SETCLE:
+			MACRO_NAND_CTL_SETCLE((unsigned long)CFG_NAND1_PADDR);
+			break;
+		case NAND_CTL_CLRCLE:
+			MACRO_NAND_CTL_CLRCLE((unsigned long)CFG_NAND1_PADDR);
+			break;
+		case NAND_CTL_SETALE:
+			MACRO_NAND_CTL_SETALE((unsigned long)CFG_NAND1_PADDR);
+			break;
+		case NAND_CTL_CLRALE:
+			MACRO_NAND_CTL_CLRALE((unsigned long)CFG_NAND1_PADDR);
+			break;
+		case NAND_CTL_SETNCE:
+			MACRO_NAND_ENABLE_CE((unsigned long)CFG_NAND1_PADDR);
+			break;
+		case NAND_CTL_CLRNCE:
+			MACRO_NAND_DISABLE_CE((unsigned long)CFG_NAND1_PADDR);
+			break;
+		}
 	}
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
 }
 
 #ifdef USE_READY_BUSY_PIN
@@ -164,15 +178,15 @@
  */
 static int ppchameleon_device_ready(struct mtd_info *minfo)
 {
-	if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_RB_GPIO_PIN)
+	if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_RB_GPIO_PIN)
 		return 1;
 	return 0;
 }
 
 static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 {
-	if (in_be32((volatile unsigned*)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
-	return 1;
+	if (in_be32((volatile unsigned *)GPIO0_IR) & NAND_EVB_RB_GPIO_PIN)
+		return 1;
 	return 0;
 }
 #endif
@@ -185,7 +199,7 @@
 /*
  * Main initialization routine
  */
-static int __init ppchameleonevb_init (void)
+static int __init ppchameleonevb_init(void)
 {
 	struct nand_chip *this;
 	const char *part_type = 0;
@@ -194,13 +208,11 @@
 	void __iomem *ppchameleon_fio_base;
 	void __iomem *ppchameleonevb_fio_base;
 
-
 	/*********************************
 	* Processor module NAND (if any) *
 	*********************************/
 	/* Allocate memory for MTD device structure and private data */
-	ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) +
-						      sizeof(struct nand_chip), GFP_KERNEL);
+	ppchameleon_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!ppchameleon_mtd) {
 		printk("Unable to allocate PPChameleon NAND MTD device structure.\n");
 		return -ENOMEM;
@@ -208,63 +220,65 @@
 
 	/* map physical address */
 	ppchameleon_fio_base = ioremap(ppchameleon_fio_pbase, SZ_4M);
-	if(!ppchameleon_fio_base) {
+	if (!ppchameleon_fio_base) {
 		printk("ioremap PPChameleon NAND flash failed\n");
 		kfree(ppchameleon_mtd);
 		return -EIO;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&ppchameleon_mtd[1]);
+	this = (struct nand_chip *)(&ppchameleon_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) ppchameleon_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(ppchameleon_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	ppchameleon_mtd->priv = this;
+	ppchameleon_mtd->owner = THIS_MODULE;
 
-        /* Initialize GPIOs */
+	/* Initialize GPIOs */
 	/* Pin mapping for NAND chip */
 	/*
-		CE	GPIO_01
-		CLE	GPIO_02
-		ALE	GPIO_03
-		R/B	GPIO_04
-	*/
+	   CE   GPIO_01
+	   CLE  GPIO_02
+	   ALE  GPIO_03
+	   R/B  GPIO_04
+	 */
 	/* output select */
-	out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xC0FFFFFF);
+	out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xC0FFFFFF);
 	/* three-state select */
-	out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xC0FFFFFF);
+	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xC0FFFFFF);
 	/* enable output driver */
-	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
+	out_be32((volatile unsigned *)GPIO0_TCR,
+		 in_be32((volatile unsigned *)GPIO0_TCR) | NAND_nCE_GPIO_PIN | NAND_CLE_GPIO_PIN | NAND_ALE_GPIO_PIN);
 #ifdef USE_READY_BUSY_PIN
 	/* three-state select */
-	out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFF3FFFFF);
+	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFF3FFFFF);
 	/* high-impedecence */
-	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
+	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_RB_GPIO_PIN));
 	/* input select */
-	out_be32((volatile unsigned*)GPIO0_ISR1H, (in_be32((volatile unsigned*)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
+	out_be32((volatile unsigned *)GPIO0_ISR1H,
+		 (in_be32((volatile unsigned *)GPIO0_ISR1H) & 0xFF3FFFFF) | 0x00400000);
 #endif
 
 	/* insert callbacks */
 	this->IO_ADDR_R = ppchameleon_fio_base;
 	this->IO_ADDR_W = ppchameleon_fio_base;
-	this->hwcontrol = ppchameleon_hwcontrol;
+	this->cmd_ctrl = ppchameleon_hwcontrol;
 #ifdef USE_READY_BUSY_PIN
 	this->dev_ready = ppchameleon_device_ready;
 #endif
 	this->chip_delay = NAND_BIG_DELAY_US;
 	/* ECC mode */
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Scan to find existence of the device (it could not be mounted) */
-	if (nand_scan (ppchameleon_mtd, 1)) {
+	if (nand_scan(ppchameleon_mtd, 1)) {
 		iounmap((void *)ppchameleon_fio_base);
-		kfree (ppchameleon_mtd);
+		kfree(ppchameleon_mtd);
 		goto nand_evb_init;
 	}
-
 #ifndef USE_READY_BUSY_PIN
 	/* Adjust delay if necessary */
 	if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
@@ -275,12 +289,11 @@
 	ppchameleon_mtd->name = "ppchameleon-nand";
 	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
-	  part_type = "command line";
+		part_type = "command line";
 	else
-	  mtd_parts_nb = 0;
+		mtd_parts_nb = 0;
 #endif
-	if (mtd_parts_nb == 0)
-	{
+	if (mtd_parts_nb == 0) {
 		if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
 			mtd_parts = partition_info_me;
 		else
@@ -293,13 +306,12 @@
 	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
 	add_mtd_partitions(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
 
-nand_evb_init:
+ nand_evb_init:
 	/****************************
 	* EVB NAND (always present) *
 	****************************/
 	/* Allocate memory for MTD device structure and private data */
-	ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) +
-							 sizeof(struct nand_chip), GFP_KERNEL);
+	ppchameleonevb_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!ppchameleonevb_mtd) {
 		printk("Unable to allocate PPChameleonEVB NAND MTD device structure.\n");
 		return -ENOMEM;
@@ -307,77 +319,76 @@
 
 	/* map physical address */
 	ppchameleonevb_fio_base = ioremap(ppchameleonevb_fio_pbase, SZ_4M);
-	if(!ppchameleonevb_fio_base) {
+	if (!ppchameleonevb_fio_base) {
 		printk("ioremap PPChameleonEVB NAND flash failed\n");
 		kfree(ppchameleonevb_mtd);
 		return -EIO;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&ppchameleonevb_mtd[1]);
+	this = (struct nand_chip *)(&ppchameleonevb_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(ppchameleonevb_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	ppchameleonevb_mtd->priv = this;
 
-        /* Initialize GPIOs */
+	/* Initialize GPIOs */
 	/* Pin mapping for NAND chip */
 	/*
-		CE	GPIO_14
-		CLE	GPIO_15
-		ALE	GPIO_16
-		R/B	GPIO_31
-	*/
+	   CE   GPIO_14
+	   CLE  GPIO_15
+	   ALE  GPIO_16
+	   R/B  GPIO_31
+	 */
 	/* output select */
-	out_be32((volatile unsigned*)GPIO0_OSRH, in_be32((volatile unsigned*)GPIO0_OSRH) & 0xFFFFFFF0);
-	out_be32((volatile unsigned*)GPIO0_OSRL, in_be32((volatile unsigned*)GPIO0_OSRL) & 0x3FFFFFFF);
+	out_be32((volatile unsigned *)GPIO0_OSRH, in_be32((volatile unsigned *)GPIO0_OSRH) & 0xFFFFFFF0);
+	out_be32((volatile unsigned *)GPIO0_OSRL, in_be32((volatile unsigned *)GPIO0_OSRL) & 0x3FFFFFFF);
 	/* three-state select */
-	out_be32((volatile unsigned*)GPIO0_TSRH, in_be32((volatile unsigned*)GPIO0_TSRH) & 0xFFFFFFF0);
-	out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0x3FFFFFFF);
+	out_be32((volatile unsigned *)GPIO0_TSRH, in_be32((volatile unsigned *)GPIO0_TSRH) & 0xFFFFFFF0);
+	out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0x3FFFFFFF);
 	/* enable output driver */
-	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
+	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) | NAND_EVB_nCE_GPIO_PIN |
 		 NAND_EVB_CLE_GPIO_PIN | NAND_EVB_ALE_GPIO_PIN);
 #ifdef USE_READY_BUSY_PIN
 	/* three-state select */
-	out_be32((volatile unsigned*)GPIO0_TSRL, in_be32((volatile unsigned*)GPIO0_TSRL) & 0xFFFFFFFC);
+	out_be32((volatile unsigned *)GPIO0_TSRL, in_be32((volatile unsigned *)GPIO0_TSRL) & 0xFFFFFFFC);
 	/* high-impedecence */
-	out_be32((volatile unsigned*)GPIO0_TCR, in_be32((volatile unsigned*)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
+	out_be32((volatile unsigned *)GPIO0_TCR, in_be32((volatile unsigned *)GPIO0_TCR) & (~NAND_EVB_RB_GPIO_PIN));
 	/* input select */
-	out_be32((volatile unsigned*)GPIO0_ISR1L, (in_be32((volatile unsigned*)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
+	out_be32((volatile unsigned *)GPIO0_ISR1L,
+		 (in_be32((volatile unsigned *)GPIO0_ISR1L) & 0xFFFFFFFC) | 0x00000001);
 #endif
 
 	/* insert callbacks */
 	this->IO_ADDR_R = ppchameleonevb_fio_base;
 	this->IO_ADDR_W = ppchameleonevb_fio_base;
-	this->hwcontrol = ppchameleonevb_hwcontrol;
+	this->cmd_ctrl = ppchameleonevb_hwcontrol;
 #ifdef USE_READY_BUSY_PIN
 	this->dev_ready = ppchameleonevb_device_ready;
 #endif
 	this->chip_delay = NAND_SMALL_DELAY_US;
 
 	/* ECC mode */
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
 	/* Scan to find existence of the device */
-	if (nand_scan (ppchameleonevb_mtd, 1)) {
+	if (nand_scan(ppchameleonevb_mtd, 1)) {
 		iounmap((void *)ppchameleonevb_fio_base);
-		kfree (ppchameleonevb_mtd);
+		kfree(ppchameleonevb_mtd);
 		return -ENXIO;
 	}
-
 #ifdef CONFIG_MTD_PARTITIONS
 	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
 	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
-	  part_type = "command line";
+		part_type = "command line";
 	else
-	  mtd_parts_nb = 0;
+		mtd_parts_nb = 0;
 #endif
-	if (mtd_parts_nb == 0)
-	{
+	if (mtd_parts_nb == 0) {
 		mtd_parts = partition_info_evb;
 		mtd_parts_nb = NUM_PARTITIONS;
 		part_type = "static";
@@ -390,18 +401,19 @@
 	/* Return happy */
 	return 0;
 }
+
 module_init(ppchameleonevb_init);
 
 /*
  * Clean up routine
  */
-static void __exit ppchameleonevb_cleanup (void)
+static void __exit ppchameleonevb_cleanup(void)
 {
 	struct nand_chip *this;
 
 	/* Release resources, unregister device(s) */
-	nand_release (ppchameleon_mtd);
-	nand_release (ppchameleonevb_mtd);
+	nand_release(ppchameleon_mtd);
+	nand_release(ppchameleonevb_mtd);
 
 	/* Release iomaps */
 	this = (struct nand_chip *) &ppchameleon_mtd[1];
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index 4129c03..f8c4964 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -97,12 +97,12 @@
 static void __iomem *rtc_from4_fio_base = (void *)P2SEGADDR(RTC_FROM4_FIO_BASE);
 
 static const struct mtd_partition partition_info[] = {
-        {
-                .name   = "Renesas flash partition 1",
-                .offset = 0,
-                .size   = MTDPART_SIZ_FULL
-        },
+	{
+	 .name = "Renesas flash partition 1",
+	 .offset = 0,
+	 .size = MTDPART_SIZ_FULL},
 };
+
 #define NUM_PARTITIONS 1
 
 /*
@@ -111,8 +111,8 @@
  *		NAND_BBT_CREATE and/or NAND_BBT_WRITE
  *
  */
-static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
-static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
+static uint8_t bbt_pattern[] = { 'B', 'b', 't', '0' };
+static uint8_t mirror_pattern[] = { '1', 't', 'b', 'B' };
 
 static struct nand_bbt_descr rtc_from4_bbt_main_descr = {
 	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
@@ -134,8 +134,6 @@
 	.pattern = mirror_pattern
 };
 
-
-
 #ifdef RTC_FROM4_HWECC
 
 /* the Reed Solomon control structure */
@@ -144,15 +142,14 @@
 /*
  *      hardware specific Out Of Band information
  */
-static struct nand_oobinfo rtc_from4_nand_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout rtc_from4_nand_oobinfo = {
 	.eccbytes = 32,
 	.eccpos = {
-		 0,  1,  2,  3,  4,  5,  6,  7,
-		 8,  9, 10, 11, 12, 13, 14, 15,
-		16, 17, 18, 19, 20, 21, 22, 23,
-		24, 25, 26, 27, 28, 29, 30, 31},
-	.oobfree = { {32, 32} }
+		   0, 1, 2, 3, 4, 5, 6, 7,
+		   8, 9, 10, 11, 12, 13, 14, 15,
+		   16, 17, 18, 19, 20, 21, 22, 23,
+		   24, 25, 26, 27, 28, 29, 30, 31},
+	.oobfree = {{32, 32}}
 };
 
 /* Aargh. I missed the reversed bit order, when I
@@ -162,44 +159,42 @@
  * of the ecc byte which we get from the FPGA
  */
 static uint8_t revbits[256] = {
-        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
-        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
-        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
-        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
-        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
-        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
-        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
-        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
-        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
-        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
-        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
-        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
-        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
-        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
-        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
-        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
-        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
-        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
-        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
-        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
-        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
-        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
-        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
-        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
-        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
-        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
-        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
-        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
-        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
-        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
-        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
-        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
 };
 
 #endif
 
-
-
 /*
  * rtc_from4_hwcontrol - hardware specific access to control-lines
  * @mtd:	MTD device structure
@@ -212,35 +207,20 @@
  * Address lines (A24-A22), so no action is required here.
  *
  */
-static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd)
+static void rtc_from4_hwcontrol(struct mtd_info *mtd, int cmd,
+				unsigned int ctrl)
 {
-	struct nand_chip* this = (struct nand_chip *) (mtd->priv);
+	struct nand_chip *chip = (mtd->priv);
 
-	switch(cmd) {
+	if (cmd == NAND_CMD_NONE)
+		return;
 
-	case NAND_CTL_SETCLE:
-		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_CLE);
-		break;
-	case NAND_CTL_CLRCLE:
-		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_CLE);
-		break;
-
-	case NAND_CTL_SETALE:
-		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_ALE);
-		break;
-	case NAND_CTL_CLRALE:
-		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_ALE);
-		break;
-
-	case NAND_CTL_SETNCE:
-		break;
-	case NAND_CTL_CLRNCE:
-		break;
-
-	}
+	if (ctrl & NAND_CLE)
+		writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_CLE);
+	else
+		writeb(cmd, chip->IO_ADDR_W | RTC_FROM4_ALE);
 }
 
-
 /*
  * rtc_from4_nand_select_chip - hardware specific chip select
  * @mtd:	MTD device structure
@@ -252,26 +232,25 @@
  */
 static void rtc_from4_nand_select_chip(struct mtd_info *mtd, int chip)
 {
-        struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd->priv;
 
 	this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R & ~RTC_FROM4_NAND_ADDR_MASK);
 	this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W & ~RTC_FROM4_NAND_ADDR_MASK);
 
-        switch(chip) {
+	switch (chip) {
 
-        case 0:		/* select slot 3 chip */
+	case 0:		/* select slot 3 chip */
 		this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT3);
 		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT3);
-                break;
-        case 1:		/* select slot 4 chip */
+		break;
+	case 1:		/* select slot 4 chip */
 		this->IO_ADDR_R = (void __iomem *)((unsigned long)this->IO_ADDR_R | RTC_FROM4_NAND_ADDR_SLOT4);
 		this->IO_ADDR_W = (void __iomem *)((unsigned long)this->IO_ADDR_W | RTC_FROM4_NAND_ADDR_SLOT4);
-                break;
+		break;
 
-        }
+	}
 }
 
-
 /*
  * rtc_from4_nand_device_ready - hardware specific ready/busy check
  * @mtd:	MTD device structure
@@ -290,7 +269,6 @@
 
 }
 
-
 /*
  * deplete - code to perform device recovery in case there was a power loss
  * @mtd:	MTD device structure
@@ -306,24 +284,23 @@
  */
 static void deplete(struct mtd_info *mtd, int chip)
 {
-        struct nand_chip *this = mtd->priv;
+	struct nand_chip *this = mtd->priv;
 
-        /* wait until device is ready */
-        while (!this->dev_ready(mtd));
+	/* wait until device is ready */
+	while (!this->dev_ready(mtd)) ;
 
 	this->select_chip(mtd, chip);
 
 	/* Send the commands for device recovery, phase 1 */
-	this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
-	this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
+	this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0000);
+	this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
 
 	/* Send the commands for device recovery, phase 2 */
-	this->cmdfunc (mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
-	this->cmdfunc (mtd, NAND_CMD_DEPLETE2, -1, -1);
+	this->cmdfunc(mtd, NAND_CMD_DEPLETE1, 0x0000, 0x0004);
+	this->cmdfunc(mtd, NAND_CMD_DEPLETE2, -1, -1);
 
 }
 
-
 #ifdef RTC_FROM4_HWECC
 /*
  * rtc_from4_enable_hwecc - hardware specific hardware ECC enable function
@@ -335,39 +312,35 @@
  */
 static void rtc_from4_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	volatile unsigned short * rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
+	volatile unsigned short *rs_ecc_ctl = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CTL);
 	unsigned short status;
 
 	switch (mode) {
-	    case NAND_ECC_READ :
-		status =  RTC_FROM4_RS_ECC_CTL_CLR
-			| RTC_FROM4_RS_ECC_CTL_FD_E;
+	case NAND_ECC_READ:
+		status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_FD_E;
 
 		*rs_ecc_ctl = status;
 		break;
 
-	    case NAND_ECC_READSYN :
-		status =  0x00;
+	case NAND_ECC_READSYN:
+		status = 0x00;
 
 		*rs_ecc_ctl = status;
 		break;
 
-	    case NAND_ECC_WRITE :
-		status =  RTC_FROM4_RS_ECC_CTL_CLR
-			| RTC_FROM4_RS_ECC_CTL_GEN
-			| RTC_FROM4_RS_ECC_CTL_FD_E;
+	case NAND_ECC_WRITE:
+		status = RTC_FROM4_RS_ECC_CTL_CLR | RTC_FROM4_RS_ECC_CTL_GEN | RTC_FROM4_RS_ECC_CTL_FD_E;
 
 		*rs_ecc_ctl = status;
 		break;
 
-	    default:
+	default:
 		BUG();
 		break;
 	}
 
 }
 
-
 /*
  * rtc_from4_calculate_ecc - hardware specific code to read ECC code
  * @mtd:	MTD device structure
@@ -383,7 +356,7 @@
  */
 static void rtc_from4_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
-	volatile unsigned short * rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
+	volatile unsigned short *rs_eccn = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECCN);
 	unsigned short value;
 	int i;
 
@@ -395,7 +368,6 @@
 	ecc_code[7] |= 0x0f;	/* set the last four bits (not used) */
 }
 
-
 /*
  * rtc_from4_correct_data - hardware specific code to correct data using ECC code
  * @mtd:	MTD device structure
@@ -414,7 +386,7 @@
 	unsigned short status;
 	uint16_t par[6], syn[6];
 	uint8_t ecc[8];
-        volatile unsigned short *rs_ecc;
+	volatile unsigned short *rs_ecc;
 
 	status = *((volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC_CHK));
 
@@ -424,23 +396,18 @@
 
 	/* Read the syndrom pattern from the FPGA and correct the bitorder */
 	rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
-        for (i = 0; i < 8; i++) {
-                ecc[i] = revbits[(*rs_ecc) & 0xFF];
-                rs_ecc++;
-        }
+	for (i = 0; i < 8; i++) {
+		ecc[i] = revbits[(*rs_ecc) & 0xFF];
+		rs_ecc++;
+	}
 
 	/* convert into 6 10bit syndrome fields */
-	par[5] = rs_decoder->index_of[(((uint16_t)ecc[0] >> 0) & 0x0ff) |
-				      (((uint16_t)ecc[1] << 8) & 0x300)];
-	par[4] = rs_decoder->index_of[(((uint16_t)ecc[1] >> 2) & 0x03f) |
-				      (((uint16_t)ecc[2] << 6) & 0x3c0)];
-	par[3] = rs_decoder->index_of[(((uint16_t)ecc[2] >> 4) & 0x00f) |
-				      (((uint16_t)ecc[3] << 4) & 0x3f0)];
-	par[2] = rs_decoder->index_of[(((uint16_t)ecc[3] >> 6) & 0x003) |
-				      (((uint16_t)ecc[4] << 2) & 0x3fc)];
-	par[1] = rs_decoder->index_of[(((uint16_t)ecc[5] >> 0) & 0x0ff) |
-				      (((uint16_t)ecc[6] << 8) & 0x300)];
-	par[0] = (((uint16_t)ecc[6] >> 2) & 0x03f) | (((uint16_t)ecc[7] << 6) & 0x3c0);
+	par[5] = rs_decoder->index_of[(((uint16_t) ecc[0] >> 0) & 0x0ff) | (((uint16_t) ecc[1] << 8) & 0x300)];
+	par[4] = rs_decoder->index_of[(((uint16_t) ecc[1] >> 2) & 0x03f) | (((uint16_t) ecc[2] << 6) & 0x3c0)];
+	par[3] = rs_decoder->index_of[(((uint16_t) ecc[2] >> 4) & 0x00f) | (((uint16_t) ecc[3] << 4) & 0x3f0)];
+	par[2] = rs_decoder->index_of[(((uint16_t) ecc[3] >> 6) & 0x003) | (((uint16_t) ecc[4] << 2) & 0x3fc)];
+	par[1] = rs_decoder->index_of[(((uint16_t) ecc[5] >> 0) & 0x0ff) | (((uint16_t) ecc[6] << 8) & 0x300)];
+	par[0] = (((uint16_t) ecc[6] >> 2) & 0x03f) | (((uint16_t) ecc[7] << 6) & 0x3c0);
 
 	/* Convert to computable syndrome */
 	for (i = 0; i < 6; i++) {
@@ -453,16 +420,14 @@
 		syn[i] = rs_decoder->index_of[syn[i]];
 	}
 
-	/* Let the library code do its magic.*/
-	res = decode_rs8(rs_decoder, (uint8_t *)buf, par, 512, syn, 0, NULL, 0xff, NULL);
+	/* Let the library code do its magic. */
+	res = decode_rs8(rs_decoder, (uint8_t *) buf, par, 512, syn, 0, NULL, 0xff, NULL);
 	if (res > 0) {
-		DEBUG (MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: "
-			"ECC corrected %d errors on read\n", res);
+		DEBUG(MTD_DEBUG_LEVEL0, "rtc_from4_correct_data: " "ECC corrected %d errors on read\n", res);
 	}
 	return res;
 }
 
-
 /**
  * rtc_from4_errstat - perform additional error status checks
  * @mtd:	MTD device structure
@@ -478,54 +443,66 @@
  * note: see pages 34..37 of data sheet for details.
  *
  */
-static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page)
+static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
+			     int state, int status, int page)
 {
-	int	er_stat=0;
-	int	rtn, retlen;
-	size_t	len;
+	int er_stat = 0;
+	int rtn, retlen;
+	size_t len;
 	uint8_t *buf;
-	int	i;
+	int i;
 
-	this->cmdfunc (mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
+	this->cmdfunc(mtd, NAND_CMD_STATUS_CLEAR, -1, -1);
 
-        if (state == FL_ERASING) {
-		for (i=0; i<4; i++) {
-			if (status & 1<<(i+1)) {
-				this->cmdfunc (mtd, (NAND_CMD_STATUS_ERROR + i + 1), -1, -1);
-				rtn = this->read_byte(mtd);
-				this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
-				if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
-					er_stat |= 1<<(i+1);	/* err_ecc_not_avail */
-				}
-			}
+	if (state == FL_ERASING) {
+
+		for (i = 0; i < 4; i++) {
+			if (!(status & 1 << (i + 1)))
+				continue;
+			this->cmdfunc(mtd, (NAND_CMD_STATUS_ERROR + i + 1),
+				      -1, -1);
+			rtn = this->read_byte(mtd);
+			this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
+
+			/* err_ecc_not_avail */
+			if (!(rtn & ERR_STAT_ECC_AVAILABLE))
+				er_stat |= 1 << (i + 1);
 		}
+
 	} else if (state == FL_WRITING) {
+
+		unsigned long corrected = mtd->ecc_stats.corrected;
+
 		/* single bank write logic */
-		this->cmdfunc (mtd, NAND_CMD_STATUS_ERROR, -1, -1);
+		this->cmdfunc(mtd, NAND_CMD_STATUS_ERROR, -1, -1);
 		rtn = this->read_byte(mtd);
-		this->cmdfunc (mtd, NAND_CMD_STATUS_RESET, -1, -1);
+		this->cmdfunc(mtd, NAND_CMD_STATUS_RESET, -1, -1);
+
 		if (!(rtn & ERR_STAT_ECC_AVAILABLE)) {
-			er_stat |= 1<<1;	/* err_ecc_not_avail */
-		} else {
-			len = mtd->oobblock;
-			buf = kmalloc (len, GFP_KERNEL);
-			if (!buf) {
-				printk (KERN_ERR "rtc_from4_errstat: Out of memory!\n");
-				er_stat = 1;			/* if we can't check, assume failed */
-			} else {
-				/* recovery read */
-				/* page read */
-				rtn = nand_do_read_ecc (mtd, page, len, &retlen, buf, NULL, this->autooob, 1);
-				if (rtn) {	/* if read failed or > 1-bit error corrected */
-					er_stat |= 1<<1;	/* ECC read failed */
-				}
-				kfree(buf);
-			}
+			/* err_ecc_not_avail */
+			er_stat |= 1 << 1;
+			goto out;
 		}
+
+		len = mtd->writesize;
+		buf = kmalloc(len, GFP_KERNEL);
+		if (!buf) {
+			printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
+			er_stat = 1;
+			goto out;
+		}
+
+		/* recovery read */
+		rtn = nand_do_read(mtd, page, len, &retlen, buf);
+
+		/* if read failed or > 1-bit error corrected */
+		if (rtn || (mtd->ecc_stats.corrected - corrected) > 1) {
+			er_stat |= 1 << 1;
+		kfree(buf);
 	}
 
 	rtn = status;
-	if (er_stat == 0) {				/* if ECC is available   */
+	if (er_stat == 0) {	/* if ECC is available   */
 		rtn = (status & ~NAND_STATUS_FAIL);	/*   clear the error bit */
 	}
 
@@ -533,33 +510,32 @@
 }
 #endif
 
-
 /*
  * Main initialization routine
  */
-int __init rtc_from4_init (void)
+static int __init rtc_from4_init(void)
 {
 	struct nand_chip *this;
 	unsigned short bcr1, bcr2, wcr2;
 	int i;
 
 	/* Allocate memory for MTD device structure and private data */
-	rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof (struct nand_chip),
-				GFP_KERNEL);
+	rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!rtc_from4_mtd) {
-		printk ("Unable to allocate Renesas NAND MTD device structure.\n");
+		printk("Unable to allocate Renesas NAND MTD device structure.\n");
 		return -ENOMEM;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&rtc_from4_mtd[1]);
+	this = (struct nand_chip *)(&rtc_from4_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) rtc_from4_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(rtc_from4_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	rtc_from4_mtd->priv = this;
+	rtc_from4_mtd->owner = THIS_MODULE;
 
 	/* set area 5 as PCMCIA mode to clear the spec of tDH(Data hold time;9ns min) */
 	bcr1 = *SH77X9_BCR1 & ~0x0002;
@@ -580,9 +556,9 @@
 	this->IO_ADDR_R = rtc_from4_fio_base;
 	this->IO_ADDR_W = rtc_from4_fio_base;
 	/* Set address of hardware control function */
-	this->hwcontrol = rtc_from4_hwcontrol;
+	this->cmd_ctrl = rtc_from4_hwcontrol;
 	/* Set address of chip select function */
-        this->select_chip = rtc_from4_nand_select_chip;
+	this->select_chip = rtc_from4_nand_select_chip;
 	/* command delay time (in us) */
 	this->chip_delay = 100;
 	/* return the status of the Ready/Busy line */
@@ -591,19 +567,20 @@
 #ifdef RTC_FROM4_HWECC
 	printk(KERN_INFO "rtc_from4_init: using hardware ECC detection.\n");
 
-        this->eccmode = NAND_ECC_HW8_512;
-	this->options |= NAND_HWECC_SYNDROME;
+	this->ecc.mode = NAND_ECC_HW_SYNDROME;
+	this->ecc.size = 512;
+	this->ecc.bytes = 8;
 	/* return the status of extra status and ECC checks */
 	this->errstat = rtc_from4_errstat;
 	/* set the nand_oobinfo to support FPGA H/W error detection */
-	this->autooob = &rtc_from4_nand_oobinfo;
-	this->enable_hwecc = rtc_from4_enable_hwecc;
-	this->calculate_ecc = rtc_from4_calculate_ecc;
-	this->correct_data = rtc_from4_correct_data;
+	this->ecc.layout = &rtc_from4_nand_oobinfo;
+	this->ecc.hwctl = rtc_from4_enable_hwecc;
+	this->ecc.calculate = rtc_from4_calculate_ecc;
+	this->ecc.correct = rtc_from4_correct_data;
 #else
 	printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n");
 
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 #endif
 
 	/* set the bad block tables to support debugging */
@@ -617,7 +594,7 @@
 	}
 
 	/* Perform 'device recovery' for each chip in case there was a power loss. */
-	for (i=0; i < this->numchips; i++) {
+	for (i = 0; i < this->numchips; i++) {
 		deplete(rtc_from4_mtd, i);
 	}
 
@@ -643,7 +620,7 @@
 	 */
 	rs_decoder = init_rs(10, 0x409, 0, 1, 6);
 	if (!rs_decoder) {
-		printk (KERN_ERR "Could not create a RS decoder\n");
+		printk(KERN_ERR "Could not create a RS decoder\n");
 		nand_release(rtc_from4_mtd);
 		kfree(rtc_from4_mtd);
 		return -ENOMEM;
@@ -652,20 +629,19 @@
 	/* Return happy */
 	return 0;
 }
-module_init(rtc_from4_init);
 
+module_init(rtc_from4_init);
 
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit rtc_from4_cleanup (void)
+static void __exit rtc_from4_cleanup(void)
 {
 	/* Release resource, unregister partitions */
 	nand_release(rtc_from4_mtd);
 
 	/* Free the MTD device structure */
-	kfree (rtc_from4_mtd);
+	kfree(rtc_from4_mtd);
 
 #ifdef RTC_FROM4_HWECC
 	/* Free the reed solomon resources */
@@ -674,10 +650,9 @@
 	}
 #endif
 }
+
 module_exit(rtc_from4_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("d.marlin <dmarlin@redhat.com");
 MODULE_DESCRIPTION("Board-specific glue layer for AG-AND flash on Renesas FROM_BOARD4");
-
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 5b55599..ff5cef2 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -18,8 +18,9 @@
  *	20-Jun-2005  BJD  Updated s3c2440 support, fixed timing bug
  *	08-Jul-2005  BJD  Fix OOPS when no platform data supplied
  *	20-Oct-2005  BJD  Fix timing calculation bug
+ *	14-Jan-2006  BJD  Allow clock to be stopped when idle
  *
- * $Id: s3c2410.c,v 1.20 2005/11/07 11:14:31 gleixner Exp $
+ * $Id: s3c2410.c,v 1.23 2006/04/01 18:06:29 bjd Exp $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -36,9 +37,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
-#include <config/mtd/nand/s3c2410/hwecc.h>
-#include <config/mtd/nand/s3c2410/debug.h>
-
 #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
 #define DEBUG
 #endif
@@ -65,22 +63,26 @@
 #include <asm/arch/regs-nand.h>
 #include <asm/arch/nand.h>
 
-#define PFX "s3c2410-nand: "
-
 #ifdef CONFIG_MTD_NAND_S3C2410_HWECC
 static int hardware_ecc = 1;
 #else
 static int hardware_ecc = 0;
 #endif
 
+#ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
+static int clock_stop = 1;
+#else
+static const int clock_stop = 0;
+#endif
+
+
 /* new oob placement block for use with hardware ecc generation
  */
 
-static struct nand_oobinfo nand_hw_eccoob = {
-	.useecc		= MTD_NANDECC_AUTOPLACE,
-	.eccbytes	= 3,
-	.eccpos		= {0, 1, 2 },
-	.oobfree	= { {8, 8} }
+static struct nand_ecclayout nand_hw_eccoob = {
+	.eccbytes = 3,
+	.eccpos = {0, 1, 2},
+	.oobfree = {{8, 8}}
 };
 
 /* controller and mtd information */
@@ -95,6 +97,12 @@
 	int				scan_res;
 };
 
+enum s3c_cpu_type {
+	TYPE_S3C2410,
+	TYPE_S3C2412,
+	TYPE_S3C2440,
+};
+
 /* overview of the s3c2410 nand state */
 
 struct s3c2410_nand_info {
@@ -108,9 +116,11 @@
 	struct resource			*area;
 	struct clk			*clk;
 	void __iomem			*regs;
+	void __iomem			*sel_reg;
+	int				sel_bit;
 	int				mtd_count;
 
-	unsigned char			is_s3c2440;
+	enum s3c_cpu_type		cpu_type;
 };
 
 /* conversion functions */
@@ -135,11 +145,16 @@
 	return dev->dev.platform_data;
 }
 
+static inline int allow_clk_stop(struct s3c2410_nand_info *info)
+{
+	return clock_stop;
+}
+
 /* timing calculations */
 
 #define NS_IN_KHZ 1000000
 
-static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
+static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
 {
 	int result;
 
@@ -149,8 +164,7 @@
 	pr_debug("result %d from %ld, %d\n", result, clk, wanted);
 
 	if (result > max) {
-		printk("%d ns is too big for current clock rate %ld\n",
-		       wanted, clk);
+		printk("%d ns is too big for current clock rate %ld\n", wanted, clk);
 		return -1;
 	}
 
@@ -169,46 +183,53 @@
 {
 	struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
 	unsigned long clkrate = clk_get_rate(info->clk);
+	int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
 	int tacls, twrph0, twrph1;
-	unsigned long cfg;
+	unsigned long cfg = 0;
 
 	/* calculate the timing information for the controller */
 
 	clkrate /= 1000;	/* turn clock into kHz for ease of use */
 
 	if (plat != NULL) {
-		tacls  = s3c2410_nand_calc_rate(plat->tacls, clkrate, 4);
-		twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);
-		twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);
+		tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
+		twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
+		twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
 	} else {
 		/* default timings */
-		tacls = 4;
+		tacls = tacls_max;
 		twrph0 = 8;
 		twrph1 = 8;
 	}
 
 	if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
-		printk(KERN_ERR PFX "cannot get timings suitable for board\n");
+		dev_err(info->device, "cannot get suitable timings\n");
 		return -EINVAL;
 	}
 
-	printk(KERN_INFO PFX "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
-	       tacls, to_ns(tacls, clkrate),
-	       twrph0, to_ns(twrph0, clkrate),
-	       twrph1, to_ns(twrph1, clkrate));
+	dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
+	       tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
 
-	if (!info->is_s3c2440) {
-		cfg  = S3C2410_NFCONF_EN;
-		cfg |= S3C2410_NFCONF_TACLS(tacls-1);
-		cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1);
-		cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1);
-	} else {
-		cfg   = S3C2440_NFCONF_TACLS(tacls-1);
-		cfg  |= S3C2440_NFCONF_TWRPH0(twrph0-1);
-		cfg  |= S3C2440_NFCONF_TWRPH1(twrph1-1);
+ 	switch (info->cpu_type) {
+ 	case TYPE_S3C2410:
+		cfg = S3C2410_NFCONF_EN;
+		cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
+		cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
+		cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
+		break;
+
+ 	case TYPE_S3C2440:
+ 	case TYPE_S3C2412:
+		cfg = S3C2440_NFCONF_TACLS(tacls - 1);
+		cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
+		cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
+
+		/* enable the controller and de-assert nFCE */
+
+		writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
 	}
 
-	pr_debug(PFX "NF_CONF is 0x%lx\n", cfg);
+	dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
 
 	writel(cfg, info->regs + S3C2410_NFCONF);
 	return 0;
@@ -221,99 +242,71 @@
 	struct s3c2410_nand_info *info;
 	struct s3c2410_nand_mtd *nmtd;
 	struct nand_chip *this = mtd->priv;
-	void __iomem *reg;
 	unsigned long cur;
-	unsigned long bit;
 
 	nmtd = this->priv;
 	info = nmtd->info;
 
-	bit = (info->is_s3c2440) ? S3C2440_NFCONT_nFCE : S3C2410_NFCONF_nFCE;
-	reg = info->regs+((info->is_s3c2440) ? S3C2440_NFCONT:S3C2410_NFCONF);
+	if (chip != -1 && allow_clk_stop(info))
+		clk_enable(info->clk);
 
-	cur = readl(reg);
+	cur = readl(info->sel_reg);
 
 	if (chip == -1) {
-		cur |= bit;
+		cur |= info->sel_bit;
 	} else {
 		if (nmtd->set != NULL && chip > nmtd->set->nr_chips) {
-			printk(KERN_ERR PFX "chip %d out of range\n", chip);
+			dev_err(info->device, "invalid chip %d\n", chip);
 			return;
 		}
 
 		if (info->platform != NULL) {
 			if (info->platform->select_chip != NULL)
-				(info->platform->select_chip)(nmtd->set, chip);
+				(info->platform->select_chip) (nmtd->set, chip);
 		}
 
-		cur &= ~bit;
+		cur &= ~info->sel_bit;
 	}
 
-	writel(cur, reg);
+	writel(cur, info->sel_reg);
+
+	if (chip == -1 && allow_clk_stop(info))
+		clk_disable(info->clk);
 }
 
-/* command and control functions
+/* s3c2410_nand_hwcontrol
  *
- * Note, these all use tglx's method of changing the IO_ADDR_W field
- * to make the code simpler, and use the nand layer's code to issue the
- * command and address sequences via the proper IO ports.
- *
+ * Issue command and address cycles to the chip
 */
 
-static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+				   unsigned int ctrl)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-	struct nand_chip *chip = mtd->priv;
+	
+	if (cmd == NAND_CMD_NONE)
+		return;
 
-	switch (cmd) {
-	case NAND_CTL_SETNCE:
-	case NAND_CTL_CLRNCE:
-		printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
-		break;
-
-	case NAND_CTL_SETCLE:
-		chip->IO_ADDR_W = info->regs + S3C2410_NFCMD;
-		break;
-
-	case NAND_CTL_SETALE:
-		chip->IO_ADDR_W = info->regs + S3C2410_NFADDR;
-		break;
-
-		/* NAND_CTL_CLRCLE: */
-		/* NAND_CTL_CLRALE: */
-	default:
-		chip->IO_ADDR_W = info->regs + S3C2410_NFDATA;
-		break;
-	}
+	if (ctrl & NAND_CLE)
+		writeb(cmd, info->regs + S3C2410_NFCMD);
+	else
+		writeb(cmd, info->regs + S3C2410_NFADDR);
 }
 
 /* command and control functions */
 
-static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
+static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+				   unsigned int ctrl)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-	struct nand_chip *chip = mtd->priv;
 
-	switch (cmd) {
-	case NAND_CTL_SETNCE:
-	case NAND_CTL_CLRNCE:
-		printk(KERN_ERR "%s: called for NCE\n", __FUNCTION__);
-		break;
+	if (cmd == NAND_CMD_NONE)
+		return;
 
-	case NAND_CTL_SETCLE:
-		chip->IO_ADDR_W = info->regs + S3C2440_NFCMD;
-		break;
-
-	case NAND_CTL_SETALE:
-		chip->IO_ADDR_W = info->regs + S3C2440_NFADDR;
-		break;
-
-		/* NAND_CTL_CLRCLE: */
-		/* NAND_CTL_CLRALE: */
-	default:
-		chip->IO_ADDR_W = info->regs + S3C2440_NFDATA;
-		break;
-	}
+	if (ctrl & NAND_CLE)
+		writeb(cmd, info->regs + S3C2440_NFCMD);
+	else
+		writeb(cmd, info->regs + S3C2440_NFADDR);
 }
 
 /* s3c2410_nand_devready()
@@ -324,28 +317,32 @@
 static int s3c2410_nand_devready(struct mtd_info *mtd)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
-
-	if (info->is_s3c2440)
-		return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
 	return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
 }
 
+static int s3c2440_nand_devready(struct mtd_info *mtd)
+{
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+	return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
+}
+
+static int s3c2412_nand_devready(struct mtd_info *mtd)
+{
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
+	return readb(info->regs + S3C2412_NFSTAT) & S3C2412_NFSTAT_READY;
+}
 
 /* ECC handling functions */
 
 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
 				     u_char *read_ecc, u_char *calc_ecc)
 {
-	pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n",
-		 mtd, dat, read_ecc, calc_ecc);
+	pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n", mtd, dat, read_ecc, calc_ecc);
 
 	pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
-		 read_ecc[0], read_ecc[1], read_ecc[2],
-		 calc_ecc[0], calc_ecc[1], calc_ecc[2]);
+		 read_ecc[0], read_ecc[1], read_ecc[2], calc_ecc[0], calc_ecc[1], calc_ecc[2]);
 
-	if (read_ecc[0] == calc_ecc[0] &&
-	    read_ecc[1] == calc_ecc[1] &&
-	    read_ecc[2] == calc_ecc[2])
+	if (read_ecc[0] == calc_ecc[0] && read_ecc[1] == calc_ecc[1] && read_ecc[2] == calc_ecc[2])
 		return 0;
 
 	/* we curently have no method for correcting the error */
@@ -378,8 +375,7 @@
 	writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
 }
 
-static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,
-				      const u_char *dat, u_char *ecc_code)
+static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 
@@ -387,15 +383,12 @@
 	ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
 	ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
 
-	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",
-		 ecc_code[0], ecc_code[1], ecc_code[2]);
+	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
 
 	return 0;
 }
 
-
-static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd,
-				      const u_char *dat, u_char *ecc_code)
+static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
 	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 	unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
@@ -404,13 +397,11 @@
 	ecc_code[1] = ecc >> 8;
 	ecc_code[2] = ecc >> 16;
 
-	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",
-		 ecc_code[0], ecc_code[1], ecc_code[2]);
+	pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
 
 	return 0;
 }
 
-
 /* over-ride the standard functions for a little more speed. We can
  * use read/write block to move the data buffers to/from the controller
 */
@@ -421,8 +412,7 @@
 	readsb(this->IO_ADDR_R, buf, len);
 }
 
-static void s3c2410_nand_write_buf(struct mtd_info *mtd,
-				   const u_char *buf, int len)
+static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
 	struct nand_chip *this = mtd->priv;
 	writesb(this->IO_ADDR_W, buf, len);
@@ -459,7 +449,8 @@
 	/* free the common resources */
 
 	if (info->clk != NULL && !IS_ERR(info->clk)) {
-		clk_disable(info->clk);
+		if (!allow_clk_stop(info))
+			clk_disable(info->clk);
 		clk_put(info->clk);
 	}
 
@@ -488,9 +479,7 @@
 		return add_mtd_device(&mtd->mtd);
 
 	if (set->nr_partitions > 0 && set->partitions != NULL) {
-		return add_mtd_partitions(&mtd->mtd,
-					  set->partitions,
-					  set->nr_partitions);
+		return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
 	}
 
 	return add_mtd_device(&mtd->mtd);
@@ -514,11 +503,8 @@
 				   struct s3c2410_nand_set *set)
 {
 	struct nand_chip *chip = &nmtd->chip;
+	void __iomem *regs = info->regs;
 
-	chip->IO_ADDR_R	   = info->regs + S3C2410_NFDATA;
-	chip->IO_ADDR_W    = info->regs + S3C2410_NFDATA;
-	chip->hwcontrol    = s3c2410_nand_hwcontrol;
-	chip->dev_ready    = s3c2410_nand_devready;
 	chip->write_buf    = s3c2410_nand_write_buf;
 	chip->read_buf     = s3c2410_nand_read_buf;
 	chip->select_chip  = s3c2410_nand_select_chip;
@@ -527,29 +513,66 @@
 	chip->options	   = 0;
 	chip->controller   = &info->controller;
 
-	if (info->is_s3c2440) {
-		chip->IO_ADDR_R	 = info->regs + S3C2440_NFDATA;
-		chip->IO_ADDR_W  = info->regs + S3C2440_NFDATA;
-		chip->hwcontrol  = s3c2440_nand_hwcontrol;
-	}
+	switch (info->cpu_type) {
+	case TYPE_S3C2410:
+		chip->IO_ADDR_W = regs + S3C2410_NFDATA;
+		info->sel_reg   = regs + S3C2410_NFCONF;
+		info->sel_bit	= S3C2410_NFCONF_nFCE;
+		chip->cmd_ctrl  = s3c2410_nand_hwcontrol;
+		chip->dev_ready = s3c2410_nand_devready;
+		break;
+
+	case TYPE_S3C2440:
+		chip->IO_ADDR_W = regs + S3C2440_NFDATA;
+		info->sel_reg   = regs + S3C2440_NFCONT;
+		info->sel_bit	= S3C2440_NFCONT_nFCE;
+		chip->cmd_ctrl  = s3c2440_nand_hwcontrol;
+		chip->dev_ready = s3c2440_nand_devready;
+		break;
+
+	case TYPE_S3C2412:
+		chip->IO_ADDR_W = regs + S3C2440_NFDATA;
+		info->sel_reg   = regs + S3C2440_NFCONT;
+		info->sel_bit	= S3C2412_NFCONT_nFCE0;
+		chip->cmd_ctrl  = s3c2440_nand_hwcontrol;
+		chip->dev_ready = s3c2412_nand_devready;
+
+		if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT)
+			dev_info(info->device, "System booted from NAND\n");
+
+		break;
+  	}
+
+	chip->IO_ADDR_R = chip->IO_ADDR_W;
 
 	nmtd->info	   = info;
 	nmtd->mtd.priv	   = chip;
+	nmtd->mtd.owner    = THIS_MODULE;
 	nmtd->set	   = set;
 
 	if (hardware_ecc) {
-		chip->correct_data  = s3c2410_nand_correct_data;
-		chip->enable_hwecc  = s3c2410_nand_enable_hwecc;
-		chip->calculate_ecc = s3c2410_nand_calculate_ecc;
-		chip->eccmode	    = NAND_ECC_HW3_512;
-		chip->autooob       = &nand_hw_eccoob;
+		chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+		chip->ecc.correct   = s3c2410_nand_correct_data;
+		chip->ecc.mode	    = NAND_ECC_HW;
+		chip->ecc.size	    = 512;
+		chip->ecc.bytes	    = 3;
+		chip->ecc.layout    = &nand_hw_eccoob;
 
-		if (info->is_s3c2440) {
-			chip->enable_hwecc  = s3c2440_nand_enable_hwecc;
-			chip->calculate_ecc = s3c2440_nand_calculate_ecc;
+		switch (info->cpu_type) {
+		case TYPE_S3C2410:
+			chip->ecc.hwctl	    = s3c2410_nand_enable_hwecc;
+			chip->ecc.calculate = s3c2410_nand_calculate_ecc;
+			break;
+
+		case TYPE_S3C2412:
+		case TYPE_S3C2440:
+  			chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
+  			chip->ecc.calculate = s3c2440_nand_calculate_ecc;
+			break;
+
 		}
 	} else {
-		chip->eccmode	    = NAND_ECC_SOFT;
+		chip->ecc.mode	    = NAND_ECC_SOFT;
 	}
 }
 
@@ -561,7 +584,8 @@
  * nand layer to look for devices
 */
 
-static int s3c24xx_nand_probe(struct platform_device *pdev, int is_s3c2440)
+static int s3c24xx_nand_probe(struct platform_device *pdev,
+			      enum s3c_cpu_type cpu_type)
 {
 	struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
 	struct s3c2410_nand_info *info;
@@ -616,7 +640,7 @@
 	info->device     = &pdev->dev;
 	info->platform   = plat;
 	info->regs       = ioremap(res->start, size);
-	info->is_s3c2440 = is_s3c2440;
+	info->cpu_type   = cpu_type;
 
 	if (info->regs == NULL) {
 		dev_err(&pdev->dev, "cannot reserve register region\n");
@@ -654,13 +678,11 @@
 	nmtd = info->mtds;
 
 	for (setno = 0; setno < nr_sets; setno++, nmtd++) {
-		pr_debug("initialising set %d (%p, info %p)\n",
-			 setno, nmtd, info);
+		pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);
 
 		s3c2410_nand_init_chip(info, nmtd, sets);
 
-		nmtd->scan_res = nand_scan(&nmtd->mtd,
-					   (sets) ? sets->nr_chips : 1);
+		nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
 
 		if (nmtd->scan_res == 0) {
 			s3c2410_nand_add_partition(info, nmtd, sets);
@@ -670,6 +692,11 @@
 			sets++;
 	}
 
+	if (allow_clk_stop(info)) {
+		dev_info(&pdev->dev, "clock idle support enabled\n");
+		clk_disable(info->clk);
+	}
+
 	pr_debug("initialised ok\n");
 	return 0;
 
@@ -681,21 +708,63 @@
 	return err;
 }
 
+/* PM Support */
+#ifdef CONFIG_PM
+
+static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
+{
+	struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		if (!allow_clk_stop(info))
+			clk_disable(info->clk);
+	}
+
+	return 0;
+}
+
+static int s3c24xx_nand_resume(struct platform_device *dev)
+{
+	struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+
+	if (info) {
+		clk_enable(info->clk);
+		s3c2410_nand_inithw(info, dev);
+
+		if (allow_clk_stop(info))
+			clk_disable(info->clk);
+	}
+
+	return 0;
+}
+
+#else
+#define s3c24xx_nand_suspend NULL
+#define s3c24xx_nand_resume NULL
+#endif
+
 /* driver device registration */
 
 static int s3c2410_nand_probe(struct platform_device *dev)
 {
-	return s3c24xx_nand_probe(dev, 0);
+	return s3c24xx_nand_probe(dev, TYPE_S3C2410);
 }
 
 static int s3c2440_nand_probe(struct platform_device *dev)
 {
-	return s3c24xx_nand_probe(dev, 1);
+	return s3c24xx_nand_probe(dev, TYPE_S3C2440);
+}
+
+static int s3c2412_nand_probe(struct platform_device *dev)
+{
+	return s3c24xx_nand_probe(dev, TYPE_S3C2412);
 }
 
 static struct platform_driver s3c2410_nand_driver = {
 	.probe		= s3c2410_nand_probe,
 	.remove		= s3c2410_nand_remove,
+	.suspend	= s3c24xx_nand_suspend,
+	.resume		= s3c24xx_nand_resume,
 	.driver		= {
 		.name	= "s3c2410-nand",
 		.owner	= THIS_MODULE,
@@ -705,22 +774,37 @@
 static struct platform_driver s3c2440_nand_driver = {
 	.probe		= s3c2440_nand_probe,
 	.remove		= s3c2410_nand_remove,
+	.suspend	= s3c24xx_nand_suspend,
+	.resume		= s3c24xx_nand_resume,
 	.driver		= {
 		.name	= "s3c2440-nand",
 		.owner	= THIS_MODULE,
 	},
 };
 
+static struct platform_driver s3c2412_nand_driver = {
+	.probe		= s3c2412_nand_probe,
+	.remove		= s3c2410_nand_remove,
+	.suspend	= s3c24xx_nand_suspend,
+	.resume		= s3c24xx_nand_resume,
+	.driver		= {
+		.name	= "s3c2412-nand",
+		.owner	= THIS_MODULE,
+	},
+};
+
 static int __init s3c2410_nand_init(void)
 {
 	printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");
 
+	platform_driver_register(&s3c2412_nand_driver);
 	platform_driver_register(&s3c2440_nand_driver);
 	return platform_driver_register(&s3c2410_nand_driver);
 }
 
 static void __exit s3c2410_nand_exit(void)
 {
+	platform_driver_unregister(&s3c2412_nand_driver);
 	platform_driver_unregister(&s3c2440_nand_driver);
 	platform_driver_unregister(&s3c2410_nand_driver);
 }
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 1924a4f..2174365 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -46,7 +46,6 @@
 #define FLCLE		(1 << 1)
 #define FLCE0		(1 << 0)
 
-
 /*
  * MTD structure for SharpSL
  */
@@ -60,50 +59,44 @@
 static int nr_partitions;
 static struct mtd_partition sharpsl_nand_default_partition_info[] = {
 	{
-	.name = "System Area",
-	.offset = 0,
-	.size = 7 * 1024 * 1024,
-	},
+	 .name = "System Area",
+	 .offset = 0,
+	 .size = 7 * 1024 * 1024,
+	 },
 	{
-	.name = "Root Filesystem",
-	.offset = 7 * 1024 * 1024,
-	.size = 30 * 1024 * 1024,
-	},
+	 .name = "Root Filesystem",
+	 .offset = 7 * 1024 * 1024,
+	 .size = 30 * 1024 * 1024,
+	 },
 	{
-	.name = "Home Filesystem",
-	.offset = MTDPART_OFS_APPEND ,
-	.size = MTDPART_SIZ_FULL ,
-	},
+	 .name = "Home Filesystem",
+	 .offset = MTDPART_OFS_APPEND,
+	 .size = MTDPART_SIZ_FULL,
+	 },
 };
 
 /*
  *	hardware specific access to control-lines
+ *	ctrl:
+ *	NAND_CNE: bit 0 -> bit 0 & 4
+ *	NAND_CLE: bit 1 -> bit 1
+ *	NAND_ALE: bit 2 -> bit 2
+ *
  */
-static void
-sharpsl_nand_hwcontrol(struct mtd_info* mtd, int cmd)
+static void sharpsl_nand_hwcontrol(struct mtd_info *mtd, int cmd,
+				   unsigned int ctrl)
 {
-	switch (cmd) {
-	case NAND_CTL_SETCLE:
-		writeb(readb(FLASHCTL) | FLCLE, FLASHCTL);
-		break;
-	case NAND_CTL_CLRCLE:
-		writeb(readb(FLASHCTL) & ~FLCLE, FLASHCTL);
-		break;
+	struct nand_chip *chip = mtd->priv;
 
-	case NAND_CTL_SETALE:
-		writeb(readb(FLASHCTL) | FLALE, FLASHCTL);
-		break;
-	case NAND_CTL_CLRALE:
-		writeb(readb(FLASHCTL) & ~FLALE, FLASHCTL);
-		break;
+	if (ctrl & NAND_CTRL_CHANGE) {
+		unsigned char bits = ctrl & 0x07;
 
-	case NAND_CTL_SETNCE:
-		writeb(readb(FLASHCTL) & ~(FLCE0|FLCE1), FLASHCTL);
-		break;
-	case NAND_CTL_CLRNCE:
-		writeb(readb(FLASHCTL) | (FLCE0|FLCE1), FLASHCTL);
-		break;
+		bits |= (ctrl & 0x01) << 4;
+		writeb((readb(FLASHCTL) & 0x17) | bits, FLASHCTL);
 	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
 }
 
 static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
@@ -122,31 +115,26 @@
 	.pattern = scan_ff_pattern
 };
 
-static struct nand_oobinfo akita_oobinfo = {
-	.useecc = MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout akita_oobinfo = {
 	.eccbytes = 24,
 	.eccpos = {
-		0x5,  0x1,  0x2,  0x3,  0x6,  0x7,  0x15, 0x11,
-		0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
-		0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
-	.oobfree = { {0x08, 0x09} }
+		   0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
+		   0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
+		   0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
+	.oobfree = {{0x08, 0x09}}
 };
 
-static int
-sharpsl_nand_dev_ready(struct mtd_info* mtd)
+static int sharpsl_nand_dev_ready(struct mtd_info *mtd)
 {
 	return !((readb(FLASHCTL) & FLRYBY) == 0);
 }
 
-static void
-sharpsl_nand_enable_hwecc(struct mtd_info* mtd, int mode)
+static void sharpsl_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	writeb(0 ,ECCCLRR);
+	writeb(0, ECCCLRR);
 }
 
-static int
-sharpsl_nand_calculate_ecc(struct mtd_info* mtd, const u_char* dat,
-				u_char* ecc_code)
+static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat, u_char * ecc_code)
 {
 	ecc_code[0] = ~readb(ECCLPUB);
 	ecc_code[1] = ~readb(ECCLPLB);
@@ -154,47 +142,44 @@
 	return readb(ECCCNTR) != 0;
 }
 
-
 #ifdef CONFIG_MTD_PARTITIONS
 const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
-
 /*
  * Main initialization routine
  */
-int __init
-sharpsl_nand_init(void)
+static int __init sharpsl_nand_init(void)
 {
 	struct nand_chip *this;
-	struct mtd_partition* sharpsl_partition_info;
+	struct mtd_partition *sharpsl_partition_info;
 	int err = 0;
 
 	/* Allocate memory for MTD device structure and private data */
-	sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),
-				GFP_KERNEL);
+	sharpsl_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!sharpsl_mtd) {
-		printk ("Unable to allocate SharpSL NAND MTD device structure.\n");
+		printk("Unable to allocate SharpSL NAND MTD device structure.\n");
 		return -ENOMEM;
 	}
 
 	/* map physical adress */
 	sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000);
-	if(!sharpsl_io_base){
+	if (!sharpsl_io_base) {
 		printk("ioremap to access Sharp SL NAND chip failed\n");
 		kfree(sharpsl_mtd);
 		return -EIO;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&sharpsl_mtd[1]);
+	this = (struct nand_chip *)(&sharpsl_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) sharpsl_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(sharpsl_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	sharpsl_mtd->priv = this;
+	sharpsl_mtd->owner = THIS_MODULE;
 
 	/*
 	 * PXA initialize
@@ -205,23 +190,25 @@
 	this->IO_ADDR_R = FLASHIO;
 	this->IO_ADDR_W = FLASHIO;
 	/* Set address of hardware control function */
-	this->hwcontrol = sharpsl_nand_hwcontrol;
+	this->cmd_ctrl = sharpsl_nand_hwcontrol;
 	this->dev_ready = sharpsl_nand_dev_ready;
 	/* 15 us command delay time */
 	this->chip_delay = 15;
 	/* set eccmode using hardware ECC */
-	this->eccmode = NAND_ECC_HW3_256;
+	this->ecc.mode = NAND_ECC_HW;
+	this->ecc.size = 256;
+	this->ecc.bytes = 3;
 	this->badblock_pattern = &sharpsl_bbt;
 	if (machine_is_akita() || machine_is_borzoi()) {
 		this->badblock_pattern = &sharpsl_akita_bbt;
-		this->autooob = &akita_oobinfo;
+		this->ecc.layout = &akita_oobinfo;
 	}
-	this->enable_hwecc = sharpsl_nand_enable_hwecc;
-	this->calculate_ecc = sharpsl_nand_calculate_ecc;
-	this->correct_data = nand_correct_data;
+	this->ecc.hwctl = sharpsl_nand_enable_hwecc;
+	this->ecc.calculate = sharpsl_nand_calculate_ecc;
+	this->ecc.correct = nand_correct_data;
 
 	/* Scan to find existence of the device */
-	err=nand_scan(sharpsl_mtd,1);
+	err = nand_scan(sharpsl_mtd, 1);
 	if (err) {
 		iounmap(sharpsl_io_base);
 		kfree(sharpsl_mtd);
@@ -230,24 +217,23 @@
 
 	/* Register the partitions */
 	sharpsl_mtd->name = "sharpsl-nand";
-	nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes,
-						&sharpsl_partition_info, 0);
+	nr_partitions = parse_mtd_partitions(sharpsl_mtd, part_probes, &sharpsl_partition_info, 0);
 
 	if (nr_partitions <= 0) {
 		nr_partitions = DEFAULT_NUM_PARTITIONS;
 		sharpsl_partition_info = sharpsl_nand_default_partition_info;
 		if (machine_is_poodle()) {
-			sharpsl_partition_info[1].size=30 * 1024 * 1024;
+			sharpsl_partition_info[1].size = 22 * 1024 * 1024;
 		} else if (machine_is_corgi() || machine_is_shepherd()) {
-			sharpsl_partition_info[1].size=25 * 1024 * 1024;
+			sharpsl_partition_info[1].size = 25 * 1024 * 1024;
 		} else if (machine_is_husky()) {
-			sharpsl_partition_info[1].size=53 * 1024 * 1024;
+			sharpsl_partition_info[1].size = 53 * 1024 * 1024;
 		} else if (machine_is_spitz()) {
-			sharpsl_partition_info[1].size=5 * 1024 * 1024;
+			sharpsl_partition_info[1].size = 5 * 1024 * 1024;
 		} else if (machine_is_akita()) {
-			sharpsl_partition_info[1].size=58 * 1024 * 1024;
+			sharpsl_partition_info[1].size = 58 * 1024 * 1024;
 		} else if (machine_is_borzoi()) {
-			sharpsl_partition_info[1].size=32 * 1024 * 1024;
+			sharpsl_partition_info[1].size = 32 * 1024 * 1024;
 		}
 	}
 
@@ -261,15 +247,15 @@
 	/* Return happy */
 	return 0;
 }
+
 module_init(sharpsl_nand_init);
 
 /*
  * Clean up routine
  */
-#ifdef MODULE
 static void __exit sharpsl_nand_cleanup(void)
 {
-	struct nand_chip *this = (struct nand_chip *) &sharpsl_mtd[1];
+	struct nand_chip *this = (struct nand_chip *)&sharpsl_mtd[1];
 
 	/* Release resources, unregister device */
 	nand_release(sharpsl_mtd);
@@ -279,8 +265,8 @@
 	/* Free the MTD device structure */
 	kfree(sharpsl_mtd);
 }
+
 module_exit(sharpsl_nand_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
diff --git a/drivers/mtd/nand/spia.c b/drivers/mtd/nand/spia.c
index 9cf1ce7..1f6d429 100644
--- a/drivers/mtd/nand/spia.c
+++ b/drivers/mtd/nand/spia.c
@@ -39,16 +39,16 @@
  */
 #define SPIA_IO_BASE	0xd0000000	/* Start of EP7212 IO address space */
 #define SPIA_FIO_BASE	0xf0000000	/* Address where flash is mapped */
-#define SPIA_PEDR	0x0080		/*
-					 * IO offset to Port E data register
-					 * where the CLE, ALE and NCE pins
-					 * are wired to.
-					 */
-#define SPIA_PEDDR	0x00c0		/*
-					 * IO offset to Port E data direction
-					 * register so we can control the IO
-					 * lines.
-					 */
+#define SPIA_PEDR	0x0080	/*
+				 * IO offset to Port E data register
+				 * where the CLE, ALE and NCE pins
+				 * are wired to.
+				 */
+#define SPIA_PEDDR	0x00c0	/*
+				 * IO offset to Port E data direction
+				 * register so we can control the IO
+				 * lines.
+				 */
 
 /*
  * Module stuff
@@ -69,79 +69,84 @@
  */
 static const struct mtd_partition partition_info[] = {
 	{
-		.name	= "SPIA flash partition 1",
-		.offset	= 0,
-		.size	= 2*1024*1024
-	},
+	 .name = "SPIA flash partition 1",
+	 .offset = 0,
+	 .size = 2 * 1024 * 1024},
 	{
-		.name	= "SPIA flash partition 2",
-		.offset	= 2*1024*1024,
-		.size	= 6*1024*1024
-	}
+	 .name = "SPIA flash partition 2",
+	 .offset = 2 * 1024 * 1024,
+	 .size = 6 * 1024 * 1024}
 };
-#define NUM_PARTITIONS 2
 
+#define NUM_PARTITIONS 2
 
 /*
  *	hardware specific access to control-lines
-*/
-static void spia_hwcontrol(struct mtd_info *mtd, int cmd){
+ *
+ *	ctrl:
+ *	NAND_CNE: bit 0 -> bit 2
+ *	NAND_CLE: bit 1 -> bit 0
+ *	NAND_ALE: bit 2 -> bit 1
+ */
+static void spia_hwcontrol(struct mtd_info *mtd, int cmd)
+{
+	struct nand_chip *chip = mtd->priv;
 
-    switch(cmd){
+	if (ctrl & NAND_CTRL_CHANGE) {
+		void __iomem *addr = spia_io_base + spia_pedr;
+		unsigned char bits;
 
-	case NAND_CTL_SETCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |=  0x01; break;
-	case NAND_CTL_CLRCLE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x01; break;
+		bits = (ctrl & NAND_CNE) << 2;
+		bits |= (ctrl & NAND_CLE | NAND_ALE) >> 1;
+		writeb((readb(addr) & ~0x7) | bits, addr);
+	}
 
-	case NAND_CTL_SETALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |=  0x02; break;
-	case NAND_CTL_CLRALE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x02; break;
-
-	case NAND_CTL_SETNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) &= ~0x04; break;
-	case NAND_CTL_CLRNCE: (*(volatile unsigned char *) (spia_io_base + spia_pedr)) |=  0x04; break;
-    }
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
  * Main initialization routine
  */
-int __init spia_init (void)
+static int __init spia_init(void)
 {
 	struct nand_chip *this;
 
 	/* Allocate memory for MTD device structure and private data */
-	spia_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
-				GFP_KERNEL);
+	spia_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!spia_mtd) {
-		printk ("Unable to allocate SPIA NAND MTD device structure.\n");
+		printk("Unable to allocate SPIA NAND MTD device structure.\n");
 		return -ENOMEM;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&spia_mtd[1]);
+	this = (struct nand_chip *)(&spia_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) spia_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(spia_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	spia_mtd->priv = this;
+	spia_mtd->owner = THIS_MODULE;
 
 	/*
 	 * Set GPIO Port E control register so that the pins are configured
 	 * to be outputs for controlling the NAND flash.
 	 */
-	(*(volatile unsigned char *) (spia_io_base + spia_peddr)) = 0x07;
+	(*(volatile unsigned char *)(spia_io_base + spia_peddr)) = 0x07;
 
 	/* Set address of NAND IO lines */
-	this->IO_ADDR_R = (void __iomem *) spia_fio_base;
-	this->IO_ADDR_W = (void __iomem *) spia_fio_base;
+	this->IO_ADDR_R = (void __iomem *)spia_fio_base;
+	this->IO_ADDR_W = (void __iomem *)spia_fio_base;
 	/* Set address of hardware control function */
-	this->hwcontrol = spia_hwcontrol;
+	this->cmd_ctrl = spia_hwcontrol;
 	/* 15 us command delay time */
 	this->chip_delay = 15;
 
 	/* Scan to find existence of the device */
-	if (nand_scan (spia_mtd, 1)) {
-		kfree (spia_mtd);
+	if (nand_scan(spia_mtd, 1)) {
+		kfree(spia_mtd);
 		return -ENXIO;
 	}
 
@@ -151,22 +156,22 @@
 	/* Return happy */
 	return 0;
 }
+
 module_init(spia_init);
 
 /*
  * Clean up routine
  */
-#ifdef MODULE
-static void __exit spia_cleanup (void)
+static void __exit spia_cleanup(void)
 {
 	/* Release resources, unregister device */
-	nand_release (spia_mtd);
+	nand_release(spia_mtd);
 
 	/* Free the MTD device structure */
-	kfree (spia_mtd);
+	kfree(spia_mtd);
 }
+
 module_exit(spia_cleanup);
-#endif
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com");
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c
index 7609c43..f9e2d4a 100644
--- a/drivers/mtd/nand/toto.c
+++ b/drivers/mtd/nand/toto.c
@@ -32,6 +32,8 @@
 #include <asm/arch-omap1510/hardware.h>
 #include <asm/arch/gpio.h>
 
+#define CONFIG_NAND_WORKAROUND 1
+
 /*
  * MTD structure for TOTO board
  */
@@ -39,25 +41,6 @@
 
 static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
 
-#define CONFIG_NAND_WORKAROUND 1
-
-#define NAND_NCE 0x4000
-#define NAND_CLE 0x1000
-#define NAND_ALE 0x0002
-#define NAND_MASK (NAND_CLE | NAND_ALE | NAND_NCE)
-
-#define T_NAND_CTL_CLRALE(iob)  gpiosetout(NAND_ALE, 0)
-#define T_NAND_CTL_SETALE(iob)  gpiosetout(NAND_ALE, NAND_ALE)
-#ifdef CONFIG_NAND_WORKAROUND     /* "some" dev boards busted, blue wired to rts2 :( */
-#define T_NAND_CTL_CLRCLE(iob)  gpiosetout(NAND_CLE, 0); rts2setout(2, 2)
-#define T_NAND_CTL_SETCLE(iob)  gpiosetout(NAND_CLE, NAND_CLE); rts2setout(2, 0)
-#else
-#define T_NAND_CTL_CLRCLE(iob)  gpiosetout(NAND_CLE, 0)
-#define T_NAND_CTL_SETCLE(iob)  gpiosetout(NAND_CLE, NAND_CLE)
-#endif
-#define T_NAND_CTL_SETNCE(iob)  gpiosetout(NAND_NCE, 0)
-#define T_NAND_CTL_CLRNCE(iob)  gpiosetout(NAND_NCE, NAND_NCE)
-
 /*
  * Define partitions for flash devices
  */
@@ -91,91 +74,110 @@
 
 #define NUM_PARTITIONS32M 3
 #define NUM_PARTITIONS64M 4
+
 /*
  *	hardware specific access to control-lines
-*/
-
-static void toto_hwcontrol(struct mtd_info *mtd, int cmd)
+ *
+ *	ctrl:
+ *	NAND_NCE: bit 0 -> bit 14 (0x4000)
+ *	NAND_CLE: bit 1 -> bit 12 (0x1000)
+ *	NAND_ALE: bit 2 -> bit 1  (0x0002)
+ */
+static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
+			   unsigned int ctrl)
 {
+	struct nand_chip *chip = mtd->priv;
 
-	udelay(1); /* hopefully enough time for tc make proceding write to clear */
-	switch(cmd){
+	if (ctrl & NAND_CTRL_CHANGE) {
+		unsigned long bits;
 
-		case NAND_CTL_SETCLE: T_NAND_CTL_SETCLE(cmd); break;
-		case NAND_CTL_CLRCLE: T_NAND_CTL_CLRCLE(cmd); break;
+		/* hopefully enough time for tc make proceding write to clear */
+		udelay(1);
 
-		case NAND_CTL_SETALE: T_NAND_CTL_SETALE(cmd); break;
-		case NAND_CTL_CLRALE: T_NAND_CTL_CLRALE(cmd); break;
+		bits = (~ctrl & NAND_NCE) << 14;
+		bits |= (ctrl & NAND_CLE) << 12;
+		bits |= (ctrl & NAND_ALE) >> 1;
 
-		case NAND_CTL_SETNCE: T_NAND_CTL_SETNCE(cmd); break;
-		case NAND_CTL_CLRNCE: T_NAND_CTL_CLRNCE(cmd); break;
+#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
+		gpiosetout(0x5002, bits);
+
+#ifdef CONFIG_NAND_WORKAROUND
+		/* "some" dev boards busted, blue wired to rts2 :( */
+		rts2setout(2, (ctrl & NAND_CLE) << 1);
+#endif
+		/* allow time to ensure gpio state to over take memory write */
+		udelay(1);
 	}
-	udelay(1); /* allow time to ensure gpio state to over take memory write */
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
 }
 
 /*
  * Main initialization routine
  */
-int __init toto_init (void)
+static int __init toto_init(void)
 {
 	struct nand_chip *this;
 	int err = 0;
 
 	/* Allocate memory for MTD device structure and private data */
-	toto_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
-				GFP_KERNEL);
+	toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
 	if (!toto_mtd) {
-		printk (KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
+		printk(KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
 		err = -ENOMEM;
 		goto out;
 	}
 
 	/* Get pointer to private data */
-	this = (struct nand_chip *) (&toto_mtd[1]);
+	this = (struct nand_chip *)(&toto_mtd[1]);
 
 	/* Initialize structures */
-	memset((char *) toto_mtd, 0, sizeof(struct mtd_info));
-	memset((char *) this, 0, sizeof(struct nand_chip));
+	memset(toto_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
 
 	/* Link the private data with the MTD structure */
 	toto_mtd->priv = this;
+	toto_mtd->owner = THIS_MODULE;
 
 	/* Set address of NAND IO lines */
 	this->IO_ADDR_R = toto_io_base;
 	this->IO_ADDR_W = toto_io_base;
-	this->hwcontrol = toto_hwcontrol;
+	this->cmd_ctrl = toto_hwcontrol;
 	this->dev_ready = NULL;
 	/* 25 us command delay time */
 	this->chip_delay = 30;
-	this->eccmode = NAND_ECC_SOFT;
+	this->ecc.mode = NAND_ECC_SOFT;
 
-        /* Scan to find existance of the device */
-	if (nand_scan (toto_mtd, 1)) {
+	/* Scan to find existance of the device */
+	if (nand_scan(toto_mtd, 1)) {
 		err = -ENXIO;
 		goto out_mtd;
 	}
 
 	/* Register the partitions */
-	switch(toto_mtd->size){
-		case SZ_64M: add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M); break;
-		case SZ_32M: add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M); break;
-		default: {
-			printk (KERN_WARNING "Unsupported Nand device\n");
+	switch (toto_mtd->size) {
+	case SZ_64M:
+		add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M);
+		break;
+	case SZ_32M:
+		add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M);
+		break;
+	default:{
+			printk(KERN_WARNING "Unsupported Nand device\n");
 			err = -ENXIO;
 			goto out_buf;
 		}
 	}
 
-    	gpioreserve(NAND_MASK);  /* claim our gpios */
-    	archflashwp(0,0);	 /* open up flash for writing */
+	gpioreserve(NAND_MASK);	/* claim our gpios */
+	archflashwp(0, 0);	/* open up flash for writing */
 
 	goto out;
 
-out_buf:
-	kfree (this->data_buf);
-out_mtd:
-	kfree (toto_mtd);
-out:
+ out_mtd:
+	kfree(toto_mtd);
+ out:
 	return err;
 }
 
@@ -184,20 +186,21 @@
 /*
  * Clean up routine
  */
-static void __exit toto_cleanup (void)
+static void __exit toto_cleanup(void)
 {
 	/* Release resources, unregister device */
-	nand_release (toto_mtd);
+	nand_release(toto_mtd);
 
 	/* Free the MTD device structure */
-	kfree (toto_mtd);
+	kfree(toto_mtd);
 
 	/* stop flash writes */
-	 archflashwp(0,1);
+	archflashwp(0, 1);
 
 	/* release gpios to system */
-	 gpiorelease(NAND_MASK);
+	gpiorelease(NAND_MASK);
 }
+
 module_exit(toto_cleanup);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c
new file mode 100644
index 0000000..f400810
--- /dev/null
+++ b/drivers/mtd/nand/ts7250.c
@@ -0,0 +1,206 @@
+/*
+ * drivers/mtd/nand/ts7250.c
+ *
+ * Copyright (C) 2004 Technologic Systems (support@embeddedARM.com)
+ *
+ * Derived from drivers/mtd/nand/edb7312.c
+ *   Copyright (C) 2004 Marius Gröger (mag@sysgo.de)
+ *
+ * Derived from drivers/mtd/nand/autcpu12.c
+ *   Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ * $Id: ts7250.c,v 1.4 2004/12/30 22:02:07 joff Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Overview:
+ *   This is a device driver for the NAND flash device found on the
+ *   TS-7250 board which utilizes a Samsung 32 Mbyte part.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+/*
+ * MTD structure for TS7250 board
+ */
+static struct mtd_info *ts7250_mtd = NULL;
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+#define NUM_PARTITIONS 3
+
+/*
+ * Define static partitions for flash device
+ */
+static struct mtd_partition partition_info32[] = {
+	{
+		.name		= "TS-BOOTROM",
+		.offset		= 0x00000000,
+		.size		= 0x00004000,
+	}, {
+		.name		= "Linux",
+		.offset		= 0x00004000,
+		.size		= 0x01d00000,
+	}, {
+		.name		= "RedBoot",
+		.offset		= 0x01d04000,
+		.size		= 0x002fc000,
+	},
+};
+
+/*
+ * Define static partitions for flash device
+ */
+static struct mtd_partition partition_info128[] = {
+	{
+		.name		= "TS-BOOTROM",
+		.offset		= 0x00000000,
+		.size		= 0x00004000,
+	}, {
+		.name		= "Linux",
+		.offset		= 0x00004000,
+		.size		= 0x07d00000,
+	}, {
+		.name		= "RedBoot",
+		.offset		= 0x07d04000,
+		.size		= 0x002fc000,
+	},
+};
+#endif
+
+
+/*
+ *	hardware specific access to control-lines
+ *
+ *	ctrl:
+ *	NAND_NCE: bit 0 -> bit 2
+ *	NAND_CLE: bit 1 -> bit 1
+ *	NAND_ALE: bit 2 -> bit 0
+ */
+static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	if (ctrl & NAND_CTRL_CHANGE) {
+		unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE;
+		unsigned char bits;
+
+		bits = (ctrl & NAND_NCE) << 2;
+		bits |= ctrl & NAND_CLE;
+		bits |= (ctrl & NAND_ALE) >> 2;
+
+		__raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr);
+	}
+
+	if (cmd != NAND_CMD_NONE)
+		writeb(cmd, chip->IO_ADDR_W);
+}
+
+/*
+ *	read device ready pin
+ */
+static int ts7250_device_ready(struct mtd_info *mtd)
+{
+	return __raw_readb(TS72XX_NAND_BUSY_VIRT_BASE) & 0x20;
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init ts7250_init(void)
+{
+	struct nand_chip *this;
+	const char *part_type = 0;
+	int mtd_parts_nb = 0;
+	struct mtd_partition *mtd_parts = 0;
+
+	if (!machine_is_ts72xx() || board_is_ts7200())
+		return -ENXIO;
+
+	/* Allocate memory for MTD device structure and private data */
+	ts7250_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
+	if (!ts7250_mtd) {
+		printk("Unable to allocate TS7250 NAND MTD device structure.\n");
+		return -ENOMEM;
+	}
+
+	/* Get pointer to private data */
+	this = (struct nand_chip *)(&ts7250_mtd[1]);
+
+	/* Initialize structures */
+	memset(ts7250_mtd, 0, sizeof(struct mtd_info));
+	memset(this, 0, sizeof(struct nand_chip));
+
+	/* Link the private data with the MTD structure */
+	ts7250_mtd->priv = this;
+	ts7250_mtd->owner = THIS_MODULE;
+
+	/* insert callbacks */
+	this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE;
+	this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE;
+	this->cmd_ctrl = ts7250_hwcontrol;
+	this->dev_ready = ts7250_device_ready;
+	this->chip_delay = 15;
+	this->ecc.mode = NAND_ECC_SOFT;
+
+	printk("Searching for NAND flash...\n");
+	/* Scan to find existence of the device */
+	if (nand_scan(ts7250_mtd, 1)) {
+		kfree(ts7250_mtd);
+		return -ENXIO;
+	}
+#ifdef CONFIG_MTD_PARTITIONS
+	ts7250_mtd->name = "ts7250-nand";
+	mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, &mtd_parts, 0);
+	if (mtd_parts_nb > 0)
+		part_type = "command line";
+	else
+		mtd_parts_nb = 0;
+#endif
+	if (mtd_parts_nb == 0) {
+		mtd_parts = partition_info32;
+		if (ts7250_mtd->size >= (128 * 0x100000))
+			mtd_parts = partition_info128;
+		mtd_parts_nb = NUM_PARTITIONS;
+		part_type = "static";
+	}
+
+	/* Register the partitions */
+	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+	add_mtd_partitions(ts7250_mtd, mtd_parts, mtd_parts_nb);
+
+	/* Return happy */
+	return 0;
+}
+
+module_init(ts7250_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit ts7250_cleanup(void)
+{
+	/* Unregister the device */
+	del_mtd_device(ts7250_mtd);
+
+	/* Free the MTD device structure */
+	kfree(ts7250_mtd);
+}
+
+module_exit(ts7250_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jesse Off <joff@embeddedARM.com>");
+MODULE_DESCRIPTION("MTD map driver for Technologic Systems TS-7250 board");
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index d7cd5fa..dc75735 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -70,8 +70,6 @@
 	nftl->mbd.devnum = -1;
 	nftl->mbd.blksize = 512;
 	nftl->mbd.tr = tr;
-	memcpy(&nftl->oobinfo, &mtd->oobinfo, sizeof(struct nand_oobinfo));
-	nftl->oobinfo.useecc = MTD_NANDECC_PLACEONLY;
 
         if (NFTL_mount(nftl) < 0) {
 		printk(KERN_WARNING "NFTL: could not mount device\n");
@@ -136,6 +134,69 @@
 	kfree(nftl);
 }
 
+/*
+ * Read oob data from flash
+ */
+int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+		  size_t *retlen, uint8_t *buf)
+{
+	struct mtd_oob_ops ops;
+	int res;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooboffs = offs & (mtd->writesize - 1);
+	ops.ooblen = len;
+	ops.oobbuf = buf;
+	ops.datbuf = NULL;
+	ops.len = len;
+
+	res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	*retlen = ops.retlen;
+	return res;
+}
+
+/*
+ * Write oob data to flash
+ */
+int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+		   size_t *retlen, uint8_t *buf)
+{
+	struct mtd_oob_ops ops;
+	int res;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooboffs = offs & (mtd->writesize - 1);
+	ops.ooblen = len;
+	ops.oobbuf = buf;
+	ops.datbuf = NULL;
+	ops.len = len;
+
+	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	*retlen = ops.retlen;
+	return res;
+}
+
+/*
+ * Write data and oob to flash
+ */
+static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
+		      size_t *retlen, uint8_t *buf, uint8_t *oob)
+{
+	struct mtd_oob_ops ops;
+	int res;
+
+	ops.mode = MTD_OOB_PLACE;
+	ops.ooboffs = offs;
+	ops.ooblen = mtd->oobsize;
+	ops.oobbuf = oob;
+	ops.datbuf = buf;
+	ops.len = len;
+
+	res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops);
+	*retlen = ops.retlen;
+	return res;
+}
+
 #ifdef CONFIG_NFTL_RW
 
 /* Actual NFTL access routines */
@@ -185,6 +246,7 @@
 
 static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock )
 {
+	struct mtd_info *mtd = nftl->mbd.mtd;
 	u16 BlockMap[MAX_SECTORS_PER_UNIT];
 	unsigned char BlockLastState[MAX_SECTORS_PER_UNIT];
 	unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT];
@@ -194,7 +256,7 @@
 	unsigned int targetEUN;
 	struct nftl_oob oob;
 	int inplace = 1;
-        size_t retlen;
+	size_t retlen;
 
 	memset(BlockMap, 0xff, sizeof(BlockMap));
 	memset(BlockFreeFound, 0, sizeof(BlockFreeFound));
@@ -210,21 +272,21 @@
 	/* Scan to find the Erase Unit which holds the actual data for each
 	   512-byte block within the Chain.
 	*/
-        silly = MAX_LOOPS;
+	silly = MAX_LOOPS;
 	targetEUN = BLOCK_NIL;
 	while (thisEUN <= nftl->lastEUN ) {
-                unsigned int status, foldmark;
+		unsigned int status, foldmark;
 
 		targetEUN = thisEUN;
 		for (block = 0; block < nftl->EraseSize / 512; block ++) {
-			MTD_READOOB(nftl->mbd.mtd,
-				    (thisEUN * nftl->EraseSize) + (block * 512),
-				    16 , &retlen, (char *)&oob);
+			nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
+				      (block * 512), 16 , &retlen,
+				      (char *)&oob);
 			if (block == 2) {
-                                foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
-                                if (foldmark == FOLD_MARK_IN_PROGRESS) {
-                                        DEBUG(MTD_DEBUG_LEVEL1,
-                                              "Write Inhibited on EUN %d\n", thisEUN);
+				foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1;
+				if (foldmark == FOLD_MARK_IN_PROGRESS) {
+					DEBUG(MTD_DEBUG_LEVEL1,
+					      "Write Inhibited on EUN %d\n", thisEUN);
 					inplace = 0;
 				} else {
 					/* There's no other reason not to do inplace,
@@ -233,7 +295,7 @@
 					inplace = 1;
 				}
 			}
-                        status = oob.b.Status | oob.b.Status1;
+			status = oob.b.Status | oob.b.Status1;
 			BlockLastState[block] = status;
 
 			switch(status) {
@@ -328,15 +390,15 @@
 			return BLOCK_NIL;
 		}
 	} else {
-            /* We put a fold mark in the chain we are folding only if
-               we fold in place to help the mount check code. If we do
-               not fold in place, it is possible to find the valid
-               chain by selecting the longer one */
-            oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
-            oob.u.c.unused = 0xffffffff;
-            MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
-                         8, &retlen, (char *)&oob.u);
-        }
+		/* We put a fold mark in the chain we are folding only if we
+               fold in place to help the mount check code. If we do not fold in
+               place, it is possible to find the valid chain by selecting the
+               longer one */
+		oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS);
+		oob.u.c.unused = 0xffffffff;
+		nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8,
+			       8, &retlen, (char *)&oob.u);
+	}
 
 	/* OK. We now know the location of every block in the Virtual Unit Chain,
 	   and the Erase Unit into which we are supposed to be copying.
@@ -353,33 +415,33 @@
 			continue;
 		}
 
-                /* copy only in non free block (free blocks can only
+		/* copy only in non free block (free blocks can only
                    happen in case of media errors or deleted blocks) */
-                if (BlockMap[block] == BLOCK_NIL)
-                        continue;
+		if (BlockMap[block] == BLOCK_NIL)
+			continue;
 
-                ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
-				  512, &retlen, movebuf);
-                if (ret < 0) {
-                    ret = MTD_READ(nftl->mbd.mtd, (nftl->EraseSize * BlockMap[block])
-                                      + (block * 512), 512, &retlen,
-                                      movebuf);
-                    if (ret != -EIO)
-                        printk("Error went away on retry.\n");
-                }
+		ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block]) + (block * 512),
+				512, &retlen, movebuf);
+		if (ret < 0 && ret != -EUCLEAN) {
+			ret = mtd->read(mtd, (nftl->EraseSize * BlockMap[block])
+					+ (block * 512), 512, &retlen,
+					movebuf);
+			if (ret != -EIO)
+				printk("Error went away on retry.\n");
+		}
 		memset(&oob, 0xff, sizeof(struct nftl_oob));
 		oob.b.Status = oob.b.Status1 = SECTOR_USED;
-                MTD_WRITEECC(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + (block * 512),
-                             512, &retlen, movebuf, (char *)&oob, &nftl->oobinfo);
+
+		nftl_write(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) +
+			   (block * 512), 512, &retlen, movebuf, (char *)&oob);
 	}
 
-        /* add the header so that it is now a valid chain */
-        oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum
-                = cpu_to_le16(thisVUC);
-        oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
+	/* add the header so that it is now a valid chain */
+	oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
+	oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff;
 
-        MTD_WRITEOOB(nftl->mbd.mtd, (nftl->EraseSize * targetEUN) + 8,
-                     8, &retlen, (char *)&oob.u);
+	nftl_write_oob(mtd, (nftl->EraseSize * targetEUN) + 8,
+		       8, &retlen, (char *)&oob.u);
 
 	/* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */
 
@@ -396,18 +458,18 @@
 	while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) {
 		unsigned int EUNtmp;
 
-                EUNtmp = nftl->ReplUnitTable[thisEUN];
+		EUNtmp = nftl->ReplUnitTable[thisEUN];
 
-                if (NFTL_formatblock(nftl, thisEUN) < 0) {
+		if (NFTL_formatblock(nftl, thisEUN) < 0) {
 			/* could not erase : mark block as reserved
 			 */
 			nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED;
-                } else {
+		} else {
 			/* correctly erased : mark it as free */
 			nftl->ReplUnitTable[thisEUN] = BLOCK_FREE;
 			nftl->numfreeEUNs++;
-                }
-                thisEUN = EUNtmp;
+		}
+		thisEUN = EUNtmp;
 	}
 
 	/* Make this the new start of chain for thisVUC */
@@ -473,6 +535,7 @@
 {
 	u16 lastEUN;
 	u16 thisVUC = block / (nftl->EraseSize / 512);
+	struct mtd_info *mtd = nftl->mbd.mtd;
 	unsigned int writeEUN;
 	unsigned long blockofs = (block * 512) & (nftl->EraseSize -1);
 	size_t retlen;
@@ -489,21 +552,22 @@
 		*/
 		lastEUN = BLOCK_NIL;
 		writeEUN = nftl->EUNtable[thisVUC];
-                silly = MAX_LOOPS;
+		silly = MAX_LOOPS;
 		while (writeEUN <= nftl->lastEUN) {
 			struct nftl_bci bci;
 			size_t retlen;
-                        unsigned int status;
+			unsigned int status;
 
 			lastEUN = writeEUN;
 
-			MTD_READOOB(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
-				    8, &retlen, (char *)&bci);
+			nftl_read_oob(mtd,
+				      (writeEUN * nftl->EraseSize) + blockofs,
+				      8, &retlen, (char *)&bci);
 
 			DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n",
 			      block , writeEUN, le16_to_cpu(bci.Status));
 
-                        status = bci.Status | bci.Status1;
+			status = bci.Status | bci.Status1;
 			switch(status) {
 			case SECTOR_FREE:
 				return writeEUN;
@@ -574,10 +638,10 @@
 		/* We've found a free block. Insert it into the chain. */
 
 		if (lastEUN != BLOCK_NIL) {
-                    thisVUC |= 0x8000; /* It's a replacement block */
+			thisVUC |= 0x8000; /* It's a replacement block */
 		} else {
-                    /* The first block in a new chain */
-                    nftl->EUNtable[thisVUC] = writeEUN;
+			/* The first block in a new chain */
+			nftl->EUNtable[thisVUC] = writeEUN;
 		}
 
 		/* set up the actual EUN we're writing into */
@@ -585,29 +649,29 @@
 		nftl->ReplUnitTable[writeEUN] = BLOCK_NIL;
 
 		/* ... and on the flash itself */
-		MTD_READOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8,
-			    &retlen, (char *)&oob.u);
+		nftl_read_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
+			      &retlen, (char *)&oob.u);
 
 		oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC);
 
-		MTD_WRITEOOB(nftl->mbd.mtd, writeEUN * nftl->EraseSize + 8, 8,
-                             &retlen, (char *)&oob.u);
+		nftl_write_oob(mtd, writeEUN * nftl->EraseSize + 8, 8,
+			       &retlen, (char *)&oob.u);
 
-                /* we link the new block to the chain only after the
+		/* we link the new block to the chain only after the
                    block is ready. It avoids the case where the chain
                    could point to a free block */
-                if (lastEUN != BLOCK_NIL) {
+		if (lastEUN != BLOCK_NIL) {
 			/* Both in our cache... */
 			nftl->ReplUnitTable[lastEUN] = writeEUN;
 			/* ... and on the flash itself */
-			MTD_READOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8,
-				    8, &retlen, (char *)&oob.u);
+			nftl_read_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
+				      8, &retlen, (char *)&oob.u);
 
 			oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum
 				= cpu_to_le16(writeEUN);
 
-			MTD_WRITEOOB(nftl->mbd.mtd, (lastEUN * nftl->EraseSize) + 8,
-				     8, &retlen, (char *)&oob.u);
+			nftl_write_oob(mtd, (lastEUN * nftl->EraseSize) + 8,
+				       8, &retlen, (char *)&oob.u);
 		}
 
 		return writeEUN;
@@ -639,10 +703,9 @@
 
 	memset(&oob, 0xff, sizeof(struct nftl_oob));
 	oob.b.Status = oob.b.Status1 = SECTOR_USED;
-	MTD_WRITEECC(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
-		     512, &retlen, (char *)buffer, (char *)&oob, &nftl->oobinfo);
-        /* need to write SECTOR_USED flags since they are not written in mtd_writeecc */
 
+	nftl_write(nftl->mbd.mtd, (writeEUN * nftl->EraseSize) + blockofs,
+		   512, &retlen, (char *)buffer, (char *)&oob);
 	return 0;
 }
 #endif /* CONFIG_NFTL_RW */
@@ -651,20 +714,22 @@
 			  char *buffer)
 {
 	struct NFTLrecord *nftl = (void *)mbd;
+	struct mtd_info *mtd = nftl->mbd.mtd;
 	u16 lastgoodEUN;
 	u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];
 	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);
-        unsigned int status;
+	unsigned int status;
 	int silly = MAX_LOOPS;
-        size_t retlen;
-        struct nftl_bci bci;
+	size_t retlen;
+	struct nftl_bci bci;
 
 	lastgoodEUN = BLOCK_NIL;
 
-        if (thisEUN != BLOCK_NIL) {
+	if (thisEUN != BLOCK_NIL) {
 		while (thisEUN < nftl->nb_blocks) {
-			if (MTD_READOOB(nftl->mbd.mtd, (thisEUN * nftl->EraseSize) + blockofs,
-					8, &retlen, (char *)&bci) < 0)
+			if (nftl_read_oob(mtd, (thisEUN * nftl->EraseSize) +
+					  blockofs, 8, &retlen,
+					  (char *)&bci) < 0)
 				status = SECTOR_IGNORE;
 			else
 				status = bci.Status | bci.Status1;
@@ -694,7 +759,7 @@
 			}
 			thisEUN = nftl->ReplUnitTable[thisEUN];
 		}
-        }
+	}
 
  the_end:
 	if (lastgoodEUN == BLOCK_NIL) {
@@ -703,7 +768,9 @@
 	} else {
 		loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;
 		size_t retlen;
-		if (MTD_READ(nftl->mbd.mtd, ptr, 512, &retlen, buffer))
+		int res = mtd->read(mtd, ptr, 512, &retlen, buffer);
+
+		if (res < 0 && res != -EUCLEAN)
 			return -EIO;
 	}
 	return 0;
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index 3b104eb..067262ee 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -33,6 +33,11 @@
 
 char nftlmountrev[]="$Revision: 1.41 $";
 
+extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+			 size_t *retlen, uint8_t *buf);
+extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
+			  size_t *retlen, uint8_t *buf);
+
 /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the
  *	various device information of the NFTL partition and Bad Unit Table. Update
  *	the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[]
@@ -45,6 +50,7 @@
 	size_t retlen;
 	u8 buf[SECTORSIZE];
 	struct NFTLMediaHeader *mh = &nftl->MediaHdr;
+	struct mtd_info *mtd = nftl->mbd.mtd;
 	unsigned int i;
 
         /* Assume logical EraseSize == physical erasesize for starting the scan.
@@ -65,7 +71,8 @@
 
 		/* Check for ANAND header first. Then can whinge if it's found but later
 		   checks fail */
-		ret = MTD_READ(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE, &retlen, buf);
+		ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE,
+				&retlen, buf);
 		/* We ignore ret in case the ECC of the MediaHeader is invalid
 		   (which is apparently acceptable) */
 		if (retlen != SECTORSIZE) {
@@ -90,8 +97,9 @@
 		}
 
 		/* To be safer with BIOS, also use erase mark as discriminant */
-		if ((ret = MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
-				8, &retlen, (char *)&h1) < 0)) {
+		if ((ret = nftl_read_oob(mtd, block * nftl->EraseSize +
+					 SECTORSIZE + 8, 8, &retlen,
+					 (char *)&h1) < 0)) {
 			printk(KERN_WARNING "ANAND header found at 0x%x in mtd%d, but OOB data read failed (err %d)\n",
 			       block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
 			continue;
@@ -109,8 +117,8 @@
 		}
 
 		/* Finally reread to check ECC */
-		if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize, SECTORSIZE,
-				&retlen, buf, (char *)&oob, NULL) < 0)) {
+		if ((ret = mtd->read(mtd, block * nftl->EraseSize, SECTORSIZE,
+				     &retlen, buf) < 0)) {
 			printk(KERN_NOTICE "ANAND header found at 0x%x in mtd%d, but ECC read failed (err %d)\n",
 			       block * nftl->EraseSize, nftl->mbd.mtd->index, ret);
 			continue;
@@ -228,9 +236,9 @@
 The new DiskOnChip driver already scanned the bad block table.  Just query it.
 			if ((i & (SECTORSIZE - 1)) == 0) {
 				/* read one sector for every SECTORSIZE of blocks */
-				if ((ret = MTD_READECC(nftl->mbd.mtd, block * nftl->EraseSize +
-						       i + SECTORSIZE, SECTORSIZE, &retlen, buf,
-						       (char *)&oob, NULL)) < 0) {
+				if ((ret = mtd->read(nftl->mbd.mtd, block * nftl->EraseSize +
+						     i + SECTORSIZE, SECTORSIZE, &retlen,
+						     buf)) < 0) {
 					printk(KERN_NOTICE "Read of bad sector table failed (err %d)\n",
 					       ret);
 					kfree(nftl->ReplUnitTable);
@@ -268,18 +276,22 @@
 static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len,
 			      int check_oob)
 {
-	int i;
-	size_t retlen;
 	u8 buf[SECTORSIZE + nftl->mbd.mtd->oobsize];
+	struct mtd_info *mtd = nftl->mbd.mtd;
+	size_t retlen;
+	int i;
 
 	for (i = 0; i < len; i += SECTORSIZE) {
-		if (MTD_READECC(nftl->mbd.mtd, address, SECTORSIZE, &retlen, buf, &buf[SECTORSIZE], &nftl->oobinfo) < 0)
+		if (mtd->read(mtd, address, SECTORSIZE, &retlen, buf))
 			return -1;
 		if (memcmpb(buf, 0xff, SECTORSIZE) != 0)
 			return -1;
 
 		if (check_oob) {
-			if (memcmpb(buf + SECTORSIZE, 0xff, nftl->mbd.mtd->oobsize) != 0)
+			if(nftl_read_oob(mtd, address, mtd->oobsize,
+					 &retlen, &buf[SECTORSIZE]) < 0)
+				return -1;
+			if (memcmpb(buf + SECTORSIZE, 0xff, mtd->oobsize) != 0)
 				return -1;
 		}
 		address += SECTORSIZE;
@@ -301,10 +313,11 @@
 	unsigned int nb_erases, erase_mark;
 	struct nftl_uci1 uci;
 	struct erase_info *instr = &nftl->instr;
+	struct mtd_info *mtd = nftl->mbd.mtd;
 
 	/* Read the Unit Control Information #1 for Wear-Leveling */
-	if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8,
-			8, &retlen, (char *)&uci) < 0)
+	if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8,
+			  8, &retlen, (char *)&uci) < 0)
 		goto default_uci1;
 
 	erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1));
@@ -321,7 +334,7 @@
 	instr->mtd = nftl->mbd.mtd;
 	instr->addr = block * nftl->EraseSize;
 	instr->len = nftl->EraseSize;
-	MTD_ERASE(nftl->mbd.mtd, instr);
+	mtd->erase(mtd, instr);
 
 	if (instr->state == MTD_ERASE_FAILED) {
 		printk("Error while formatting block %d\n", block);
@@ -343,8 +356,8 @@
 			goto fail;
 
 		uci.WearInfo = le32_to_cpu(nb_erases);
-		if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
-				 &retlen, (char *)&uci) < 0)
+		if (nftl_write_oob(mtd, block * nftl->EraseSize + SECTORSIZE +
+				   8, 8, &retlen, (char *)&uci) < 0)
 			goto fail;
 		return 0;
 fail:
@@ -365,6 +378,7 @@
  *	case. */
 static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block)
 {
+	struct mtd_info *mtd = nftl->mbd.mtd;
 	unsigned int block, i, status;
 	struct nftl_bci bci;
 	int sectors_per_block;
@@ -374,8 +388,9 @@
 	block = first_block;
 	for (;;) {
 		for (i = 0; i < sectors_per_block; i++) {
-			if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i * SECTORSIZE,
-					8, &retlen, (char *)&bci) < 0)
+			if (nftl_read_oob(mtd,
+					  block * nftl->EraseSize + i * SECTORSIZE,
+					  8, &retlen, (char *)&bci) < 0)
 				status = SECTOR_IGNORE;
 			else
 				status = bci.Status | bci.Status1;
@@ -394,9 +409,10 @@
 					/* sector not free actually : mark it as SECTOR_IGNORE  */
 					bci.Status = SECTOR_IGNORE;
 					bci.Status1 = SECTOR_IGNORE;
-					MTD_WRITEOOB(nftl->mbd.mtd,
-						     block * nftl->EraseSize + i * SECTORSIZE,
-						     8, &retlen, (char *)&bci);
+					nftl_write_oob(mtd, block *
+						       nftl->EraseSize +
+						       i * SECTORSIZE, 8,
+						       &retlen, (char *)&bci);
 				}
 				break;
 			default:
@@ -481,13 +497,14 @@
  *	1. */
 static int check_and_mark_free_block(struct NFTLrecord *nftl, int block)
 {
+	struct mtd_info *mtd = nftl->mbd.mtd;
 	struct nftl_uci1 h1;
 	unsigned int erase_mark;
 	size_t retlen;
 
 	/* check erase mark. */
-	if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
-			&retlen, (char *)&h1) < 0)
+	if (nftl_read_oob(mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
+			  &retlen, (char *)&h1) < 0)
 		return -1;
 
 	erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1));
@@ -501,8 +518,9 @@
 		h1.EraseMark = cpu_to_le16(ERASE_MARK);
 		h1.EraseMark1 = cpu_to_le16(ERASE_MARK);
 		h1.WearInfo = cpu_to_le32(0);
-		if (MTD_WRITEOOB(nftl->mbd.mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8,
-				 &retlen, (char *)&h1) < 0)
+		if (nftl_write_oob(mtd,
+				   block * nftl->EraseSize + SECTORSIZE + 8, 8,
+				   &retlen, (char *)&h1) < 0)
 			return -1;
 	} else {
 #if 0
@@ -513,8 +531,8 @@
 						SECTORSIZE, 0) != 0)
 				return -1;
 
-			if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + i,
-					16, &retlen, buf) < 0)
+			if (nftl_read_oob(mtd, block * nftl->EraseSize + i,
+					  16, &retlen, buf) < 0)
 				return -1;
 			if (i == SECTORSIZE) {
 				/* skip erase mark */
@@ -540,11 +558,12 @@
  */
 static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block)
 {
+	struct mtd_info *mtd = nftl->mbd.mtd;
 	struct nftl_uci2 uci;
 	size_t retlen;
 
-	if (MTD_READOOB(nftl->mbd.mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
-			8, &retlen, (char *)&uci) < 0)
+	if (nftl_read_oob(mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8,
+			  8, &retlen, (char *)&uci) < 0)
 		return 0;
 
 	return le16_to_cpu((uci.FoldMark | uci.FoldMark1));
@@ -558,6 +577,7 @@
 	int chain_length, do_format_chain;
 	struct nftl_uci0 h0;
 	struct nftl_uci1 h1;
+	struct mtd_info *mtd = s->mbd.mtd;
 	size_t retlen;
 
 	/* search for NFTL MediaHeader and Spare NFTL Media Header */
@@ -582,10 +602,13 @@
 
 			for (;;) {
 				/* read the block header. If error, we format the chain */
-				if (MTD_READOOB(s->mbd.mtd, block * s->EraseSize + 8, 8,
-						&retlen, (char *)&h0) < 0 ||
-				    MTD_READOOB(s->mbd.mtd, block * s->EraseSize + SECTORSIZE + 8, 8,
-						&retlen, (char *)&h1) < 0) {
+				if (nftl_read_oob(mtd,
+						  block * s->EraseSize + 8, 8,
+						  &retlen, (char *)&h0) < 0 ||
+				    nftl_read_oob(mtd,
+						  block * s->EraseSize +
+						  SECTORSIZE + 8, 8,
+						  &retlen, (char *)&h1) < 0) {
 					s->ReplUnitTable[block] = BLOCK_NIL;
 					do_format_chain = 1;
 					break;
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig
index 126ff6b..5930a03 100644
--- a/drivers/mtd/onenand/Kconfig
+++ b/drivers/mtd/onenand/Kconfig
@@ -29,6 +29,20 @@
 	help
 	  Support for OneNAND flash via platform device driver.
 
+config MTD_ONENAND_OTP
+	bool "OneNAND OTP Support"
+	depends on MTD_ONENAND
+	help
+	  One Block of the NAND Flash Array memory is reserved as
+	  a One-Time Programmable Block memory area.
+	  Also, 1st Block of NAND Flash Array can be used as OTP.
+
+	  The OTP block can be read, programmed and locked using the same
+	  operations as any other NAND Flash Array memory block.
+	  OTP block cannot be erased.
+
+	  OTP block is fully-guaranteed to be a valid block.
+
 config MTD_ONENAND_SYNC_READ
 	bool "OneNAND Sync. Burst Read Support"
 	depends on ARCH_OMAP
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index a53a73f..84ec40d 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -23,8 +23,7 @@
 /**
  * onenand_oob_64 - oob info for large (2KB) page
  */
-static struct nand_oobinfo onenand_oob_64 = {
-	.useecc		= MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout onenand_oob_64 = {
 	.eccbytes	= 20,
 	.eccpos		= {
 		8, 9, 10, 11, 12,
@@ -34,14 +33,14 @@
 		},
 	.oobfree	= {
 		{2, 3}, {14, 2}, {18, 3}, {30, 2},
-		{24, 3}, {46, 2}, {40, 3}, {62, 2} }
+		{34, 3}, {46, 2}, {50, 3}, {62, 2}
+	}
 };
 
 /**
  * onenand_oob_32 - oob info for middle (1KB) page
  */
-static struct nand_oobinfo onenand_oob_32 = {
-	.useecc		= MTD_NANDECC_AUTOPLACE,
+static struct nand_ecclayout onenand_oob_32 = {
 	.eccbytes	= 10,
 	.eccpos		= {
 		8, 9, 10, 11, 12,
@@ -190,7 +189,7 @@
 static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len)
 {
 	struct onenand_chip *this = mtd->priv;
-	int value, readcmd = 0;
+	int value, readcmd = 0, block_cmd = 0;
 	int block, page;
 	/* Now we use page size operation */
 	int sectors = 4, count = 4;
@@ -206,6 +205,8 @@
 
 	case ONENAND_CMD_ERASE:
 	case ONENAND_CMD_BUFFERRAM:
+	case ONENAND_CMD_OTP_ACCESS:
+		block_cmd = 1;
 		block = (int) (addr >> this->erase_shift);
 		page = -1;
 		break;
@@ -233,6 +234,12 @@
 		/* Write 'DFS, FBA' of Flash */
 		value = onenand_block_address(this, block);
 		this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
+
+		if (block_cmd) {
+			/* Select DataRAM for DDP */
+			value = onenand_bufferram_address(this, block);
+			this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
+		}
 	}
 
 	if (page != -1) {
@@ -301,6 +308,7 @@
 
 		if (state != FL_READING)
 			cond_resched();
+		touch_softlockup_watchdog();
 	}
 	/* To get correct interrupt status in timeout case */
 	interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
@@ -344,7 +352,7 @@
 
 	if (ONENAND_CURRENT_BUFFERRAM(this)) {
 		if (area == ONENAND_DATARAM)
-			return mtd->oobblock;
+			return mtd->writesize;
 		if (area == ONENAND_SPARERAM)
 			return mtd->oobsize;
 	}
@@ -372,6 +380,17 @@
 
 	bufferram += onenand_bufferram_offset(mtd, area);
 
+	if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+		unsigned short word;
+
+		/* Align with word(16-bit) size */
+		count--;
+
+		/* Read word and save byte */
+		word = this->read_word(bufferram + offset + count);
+		buffer[count] = (word & 0xff);
+	}
+
 	memcpy(buffer, bufferram + offset, count);
 
 	return 0;
@@ -399,6 +418,17 @@
 
 	this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ);
 
+	if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+		unsigned short word;
+
+		/* Align with word(16-bit) size */
+		count--;
+
+		/* Read word and save byte */
+		word = this->read_word(bufferram + offset + count);
+		buffer[count] = (word & 0xff);
+	}
+
 	memcpy(buffer, bufferram + offset, count);
 
 	this->mmcontrol(mtd, 0);
@@ -426,6 +456,22 @@
 
 	bufferram += onenand_bufferram_offset(mtd, area);
 
+	if (ONENAND_CHECK_BYTE_ACCESS(count)) {
+		unsigned short word;
+		int byte_offset;
+
+		/* Align with word(16-bit) size */
+		count--;
+
+		/* Calculate byte access offset */
+		byte_offset = offset + count;
+
+		/* Read word and save byte */
+		word = this->read_word(bufferram + byte_offset);
+		word = (word & ~0xff) | buffer[count];
+		this->write_word(word, bufferram + byte_offset);
+	}
+
 	memcpy(bufferram + offset, buffer, count);
 
 	return 0;
@@ -549,31 +595,28 @@
 }
 
 /**
- * onenand_read_ecc - [MTD Interface] Read data with ECC
+ * onenand_read - [MTD Interface] Read data from flash
  * @param mtd		MTD device structure
  * @param from		offset to read from
  * @param len		number of bytes to read
  * @param retlen	pointer to variable to store the number of read bytes
  * @param buf		the databuffer to put data
- * @param oob_buf	filesystem supplied oob data buffer
- * @param oobsel	oob selection structure
  *
- * OneNAND read with ECC
- */
-static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
-	size_t *retlen, u_char *buf,
-	u_char *oob_buf, struct nand_oobinfo *oobsel)
+ * Read with ecc
+*/
+static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
+	size_t *retlen, u_char *buf)
 {
 	struct onenand_chip *this = mtd->priv;
 	int read = 0, column;
 	int thislen;
 	int ret = 0;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);
 
 	/* Do not allow reads past end of device */
 	if ((from + len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n");
+		DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: Attempt read beyond end of device\n");
 		*retlen = 0;
 		return -EINVAL;
 	}
@@ -584,14 +627,14 @@
 	/* TODO handling oob */
 
 	while (read < len) {
-		thislen = min_t(int, mtd->oobblock, len - read);
+		thislen = min_t(int, mtd->writesize, len - read);
 
-		column = from & (mtd->oobblock - 1);
-		if (column + thislen > mtd->oobblock)
-			thislen = mtd->oobblock - column;
+		column = from & (mtd->writesize - 1);
+		if (column + thislen > mtd->writesize)
+			thislen = mtd->writesize - column;
 
 		if (!onenand_check_bufferram(mtd, from)) {
-			this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock);
+			this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);
 
 			ret = this->wait(mtd, FL_READING);
 			/* First copy data and check return value for ECC handling */
@@ -606,7 +649,7 @@
 			break;
 
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret);
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);
 			goto out;
 		}
 
@@ -628,23 +671,7 @@
 }
 
 /**
- * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc
- * @param mtd		MTD device structure
- * @param from		offset to read from
- * @param len		number of bytes to read
- * @param retlen	pointer to variable to store the number of read bytes
- * @param buf		the databuffer to put data
- *
- * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL
-*/
-static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
-	size_t *retlen, u_char *buf)
-{
-	return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
-}
-
-/**
- * onenand_read_oob - [MTD Interface] OneNAND read out-of-band
+ * onenand_do_read_oob - [MTD Interface] OneNAND read out-of-band
  * @param mtd		MTD device structure
  * @param from		offset to read from
  * @param len		number of bytes to read
@@ -653,8 +680,8 @@
  *
  * OneNAND read out-of-band data from the spare area
  */
-static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
-	size_t *retlen, u_char *buf)
+int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u_char *buf)
 {
 	struct onenand_chip *this = mtd->priv;
 	int read = 0, thislen, column;
@@ -704,7 +731,7 @@
 		/* Read more? */
 		if (read < len) {
 			/* Page size */
-			from += mtd->oobblock;
+			from += mtd->writesize;
 			column = 0;
 		}
 	}
@@ -717,8 +744,53 @@
 	return ret;
 }
 
+/**
+ * onenand_read_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd:	MTD device structure
+ * @from:	offset to read from
+ * @ops:	oob operation description structure
+ */
+static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
+			    struct mtd_oob_ops *ops)
+{
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
+
+	return onenand_do_read_oob(mtd, from + ops->ooboffs, ops->len,
+				   &ops->retlen, ops->oobbuf);
+}
+
 #ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE
 /**
+ * onenand_verify_oob - [GENERIC] verify the oob contents after a write
+ * @param mtd		MTD device structure
+ * @param buf		the databuffer to verify
+ * @param to		offset to read from
+ * @param len		number of bytes to read and compare
+ *
+ */
+static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to, int len)
+{
+	struct onenand_chip *this = mtd->priv;
+	char *readp = this->page_buf;
+	int column = to & (mtd->oobsize - 1);
+	int status, i;
+
+	this->command(mtd, ONENAND_CMD_READOOB, to, mtd->oobsize);
+	onenand_update_bufferram(mtd, to, 0);
+	status = this->wait(mtd, FL_READING);
+	if (status)
+		return status;
+
+	this->read_bufferram(mtd, ONENAND_SPARERAM, readp, column, len);
+
+	for(i = 0; i < len; i++)
+		if (buf[i] != 0xFF && buf[i] != readp[i])
+			return -EBADMSG;
+
+	return 0;
+}
+
+/**
  * onenand_verify_page - [GENERIC] verify the chip contents after a write
  * @param mtd		MTD device structure
  * @param buf		the databuffer to verify
@@ -731,7 +803,7 @@
 	void __iomem *dataram0, *dataram1;
 	int ret = 0;
 
-	this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock);
+	this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);
 
 	ret = this->wait(mtd, FL_READING);
 	if (ret)
@@ -741,53 +813,51 @@
 
 	/* Check, if the two dataram areas are same */
 	dataram0 = this->base + ONENAND_DATARAM;
-	dataram1 = dataram0 + mtd->oobblock;
+	dataram1 = dataram0 + mtd->writesize;
 
-	if (memcmp(dataram0, dataram1, mtd->oobblock))
+	if (memcmp(dataram0, dataram1, mtd->writesize))
 		return -EBADMSG;
 
 	return 0;
 }
 #else
 #define onenand_verify_page(...)	(0)
+#define onenand_verify_oob(...)		(0)
 #endif
 
-#define NOTALIGNED(x)	((x & (mtd->oobblock - 1)) != 0)
+#define NOTALIGNED(x)	((x & (mtd->writesize - 1)) != 0)
 
 /**
- * onenand_write_ecc - [MTD Interface] OneNAND write with ECC
+ * onenand_write - [MTD Interface] write buffer to FLASH
  * @param mtd		MTD device structure
  * @param to		offset to write to
  * @param len		number of bytes to write
  * @param retlen	pointer to variable to store the number of written bytes
  * @param buf		the data to write
- * @param eccbuf	filesystem supplied oob data buffer
- * @param oobsel	oob selection structure
  *
- * OneNAND write with ECC
+ * Write with ECC
  */
-static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
-	size_t *retlen, const u_char *buf,
-	u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
+	size_t *retlen, const u_char *buf)
 {
 	struct onenand_chip *this = mtd->priv;
 	int written = 0;
 	int ret = 0;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
+	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
 
 	/* Initialize retlen, in case of early exit */
 	*retlen = 0;
 
 	/* Do not allow writes past end of device */
 	if (unlikely((to + len) > mtd->size)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n");
+		DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt write to past end of device\n");
 		return -EINVAL;
 	}
 
 	/* Reject writes, which are not page aligned */
         if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) {
-                DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n");
+                DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: Attempt to write not page aligned data\n");
                 return -EINVAL;
         }
 
@@ -796,20 +866,20 @@
 
 	/* Loop until all data write */
 	while (written < len) {
-		int thislen = min_t(int, mtd->oobblock, len - written);
+		int thislen = min_t(int, mtd->writesize, len - written);
 
-		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
+		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);
 
 		this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);
 		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
 
-		this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
+		this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
 
 		onenand_update_bufferram(mtd, to, 1);
 
 		ret = this->wait(mtd, FL_WRITING);
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret);
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);
 			goto out;
 		}
 
@@ -818,7 +888,7 @@
 		/* Only check verify write turn on */
 		ret = onenand_verify_page(mtd, (u_char *) buf, to);
 		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret);
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);
 			goto out;
 		}
 
@@ -839,24 +909,7 @@
 }
 
 /**
- * onenand_write - [MTD Interface] compability function for onenand_write_ecc
- * @param mtd		MTD device structure
- * @param to		offset to write to
- * @param len		number of bytes to write
- * @param retlen	pointer to variable to store the number of written bytes
- * @param buf		the data to write
- *
- * This function simply calls onenand_write_ecc
- * with oob buffer and oobsel = NULL
- */
-static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len,
-	size_t *retlen, const u_char *buf)
-{
-	return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL);
-}
-
-/**
- * onenand_write_oob - [MTD Interface] OneNAND write out-of-band
+ * onenand_do_write_oob - [Internal] OneNAND write out-of-band
  * @param mtd		MTD device structure
  * @param to		offset to write to
  * @param len		number of bytes to write
@@ -865,11 +918,11 @@
  *
  * OneNAND write out-of-band
  */
-static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
-	size_t *retlen, const u_char *buf)
+static int onenand_do_write_oob(struct mtd_info *mtd, loff_t to, size_t len,
+				size_t *retlen, const u_char *buf)
 {
 	struct onenand_chip *this = mtd->priv;
-	int column, status;
+	int column, ret = 0;
 	int written = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);
@@ -894,16 +947,27 @@
 
 		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize);
 
-		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
-		this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);
+		/* We send data to spare ram with oobsize
+		 * to prevent byte access */
+		memset(this->page_buf, 0xff, mtd->oobsize);
+		memcpy(this->page_buf + column, buf, thislen);
+		this->write_bufferram(mtd, ONENAND_SPARERAM, this->page_buf, 0, mtd->oobsize);
 
 		this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize);
 
 		onenand_update_bufferram(mtd, to, 0);
 
-		status = this->wait(mtd, FL_WRITING);
-		if (status)
+		ret = this->wait(mtd, FL_WRITING);
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: write filaed %d\n", ret);
 			goto out;
+		}
+
+		ret = onenand_verify_oob(mtd, buf, to, thislen);
+		if (ret) {
+			DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: verify failed %d\n", ret);
+			goto out;
+		}
 
 		written += thislen;
 
@@ -920,145 +984,22 @@
 
 	*retlen = written;
 
-	return 0;
+	return ret;
 }
 
 /**
- * onenand_writev_ecc - [MTD Interface] write with iovec with ecc
- * @param mtd		MTD device structure
- * @param vecs		the iovectors to write
- * @param count		number of vectors
- * @param to		offset to write to
- * @param retlen	pointer to variable to store the number of written bytes
- * @param eccbuf	filesystem supplied oob data buffer
- * @param oobsel	oob selection structure
- *
- * OneNAND write with iovec with ecc
+ * onenand_write_oob - [MTD Interface] NAND write data and/or out-of-band
+ * @mtd:	MTD device structure
+ * @from:	offset to read from
+ * @ops:	oob operation description structure
  */
-static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
-	unsigned long count, loff_t to, size_t *retlen,
-	u_char *eccbuf, struct nand_oobinfo *oobsel)
+static int onenand_write_oob(struct mtd_info *mtd, loff_t to,
+			     struct mtd_oob_ops *ops)
 {
-	struct onenand_chip *this = mtd->priv;
-	unsigned char *pbuf;
-	size_t total_len, len;
-	int i, written = 0;
-	int ret = 0;
+	BUG_ON(ops->mode != MTD_OOB_PLACE);
 
-	/* Preset written len for early exit */
-	*retlen = 0;
-
-	/* Calculate total length of data */
-	total_len = 0;
-	for (i = 0; i < count; i++)
-		total_len += vecs[i].iov_len;
-
-	DEBUG(MTD_DEBUG_LEVEL3, "onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count);
-
-	/* Do not allow write past end of the device */
-	if (unlikely((to + total_len) > mtd->size)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempted write past end of device\n");
-		return -EINVAL;
-	}
-
-	/* Reject writes, which are not page aligned */
-        if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(total_len))) {
-                DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempt to write not page aligned data\n");
-                return -EINVAL;
-        }
-
-	/* Grab the lock and see if the device is available */
-	onenand_get_device(mtd, FL_WRITING);
-
-	/* TODO handling oob */
-
-	/* Loop until all keve's data has been written */
-	len = 0;
-	while (count) {
-		pbuf = this->page_buf;
-		/*
-		 * If the given tuple is >= pagesize then
-		 * write it out from the iov
-		 */
-		if ((vecs->iov_len - len) >= mtd->oobblock) {
-			pbuf = vecs->iov_base + len;
-
-			len += mtd->oobblock;
-
-			/* Check, if we have to switch to the next tuple */
-			if (len >= (int) vecs->iov_len) {
-				vecs++;
-				len = 0;
-				count--;
-			}
-		} else {
-			int cnt = 0, thislen;
-			while (cnt < mtd->oobblock) {
-				thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len);
-				memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen);
-				cnt += thislen;
-				len += thislen;
-
-				/* Check, if we have to switch to the next tuple */
-				if (len >= (int) vecs->iov_len) {
-					vecs++;
-					len = 0;
-					count--;
-				}
-			}
-		}
-
-		this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock);
-
-		this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock);
-		this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);
-
-		this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock);
-
-		onenand_update_bufferram(mtd, to, 1);
-
-		ret = this->wait(mtd, FL_WRITING);
-		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: write failed %d\n", ret);
-			goto out;
-		}
-
-
-		/* Only check verify write turn on */
-		ret = onenand_verify_page(mtd, (u_char *) pbuf, to);
-		if (ret) {
-			DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret);
-			goto out;
-		}
-
-		written += mtd->oobblock;
-
-		to += mtd->oobblock;
-	}
-
-out:
-	/* Deselect and wakt up anyone waiting on the device */
-	onenand_release_device(mtd);
-
-	*retlen = written;
-
-	return 0;
-}
-
-/**
- * onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc
- * @param mtd		MTD device structure
- * @param vecs		the iovectors to write
- * @param count		number of vectors
- * @param to		offset to write to
- * @param retlen	pointer to variable to store the number of written bytes
- *
- * OneNAND write with kvec. This just calls the ecc function
- */
-static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs,
-	unsigned long count, loff_t to, size_t *retlen)
-{
-	return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL);
+	return onenand_do_write_oob(mtd, to + ops->ooboffs, ops->len,
+				    &ops->retlen, ops->oobbuf);
 }
 
 /**
@@ -1227,7 +1168,7 @@
 
         /* We write two bytes, so we dont have to mess with 16 bit access */
         ofs += mtd->oobsize + (bbm->badblockpos & ~0x01);
-        return mtd->write_oob(mtd, ofs , 2, &retlen, buf);
+        return onenand_do_write_oob(mtd, ofs , 2, &retlen, buf);
 }
 
 /**
@@ -1324,6 +1265,304 @@
 	return 0;
 }
 
+#ifdef CONFIG_MTD_ONENAND_OTP
+
+/* Interal OTP operation */
+typedef int (*otp_op_t)(struct mtd_info *mtd, loff_t form, size_t len,
+		size_t *retlen, u_char *buf);
+
+/**
+ * do_otp_read - [DEFAULT] Read OTP block area
+ * @param mtd		MTD device structure
+ * @param from		The offset to read
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of readbytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Read OTP block area.
+ */
+static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	int ret;
+
+	/* Enter OTP access mode */
+	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+	this->wait(mtd, FL_OTPING);
+
+	ret = mtd->read(mtd, from, len, retlen, buf);
+
+	/* Exit OTP access mode */
+	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+	this->wait(mtd, FL_RESETING);
+
+	return ret;
+}
+
+/**
+ * do_otp_write - [DEFAULT] Write OTP block area
+ * @param mtd		MTD device structure
+ * @param from		The offset to write
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of write bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Write OTP block area.
+ */
+static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	unsigned char *pbuf = buf;
+	int ret;
+
+	/* Force buffer page aligned */
+	if (len < mtd->writesize) {
+		memcpy(this->page_buf, buf, len);
+		memset(this->page_buf + len, 0xff, mtd->writesize - len);
+		pbuf = this->page_buf;
+		len = mtd->writesize;
+	}
+
+	/* Enter OTP access mode */
+	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+	this->wait(mtd, FL_OTPING);
+
+	ret = mtd->write(mtd, from, len, retlen, pbuf);
+
+	/* Exit OTP access mode */
+	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+	this->wait(mtd, FL_RESETING);
+
+	return ret;
+}
+
+/**
+ * do_otp_lock - [DEFAULT] Lock OTP block area
+ * @param mtd		MTD device structure
+ * @param from		The offset to lock
+ * @param len		number of bytes to lock
+ * @param retlen	pointer to variable to store the number of lock bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Lock OTP block area.
+ */
+static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
+		size_t *retlen, u_char *buf)
+{
+	struct onenand_chip *this = mtd->priv;
+	int ret;
+
+	/* Enter OTP access mode */
+	this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
+	this->wait(mtd, FL_OTPING);
+
+	ret = onenand_do_write_oob(mtd, from, len, retlen, buf);
+
+	/* Exit OTP access mode */
+	this->command(mtd, ONENAND_CMD_RESET, 0, 0);
+	this->wait(mtd, FL_RESETING);
+
+	return ret;
+}
+
+/**
+ * onenand_otp_walk - [DEFAULT] Handle OTP operation
+ * @param mtd		MTD device structure
+ * @param from		The offset to read/write
+ * @param len		number of bytes to read/write
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put/get data
+ * @param action	do given action
+ * @param mode		specify user and factory
+ *
+ * Handle OTP operation.
+ */
+static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t *retlen, u_char *buf,
+			otp_op_t action, int mode)
+{
+	struct onenand_chip *this = mtd->priv;
+	int otp_pages;
+	int density;
+	int ret = 0;
+
+	*retlen = 0;
+
+	density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
+	if (density < ONENAND_DEVICE_DENSITY_512Mb)
+		otp_pages = 20;
+	else
+		otp_pages = 10;
+
+	if (mode == MTD_OTP_FACTORY) {
+		from += mtd->writesize * otp_pages;
+		otp_pages = 64 - otp_pages;
+	}
+
+	/* Check User/Factory boundary */
+	if (((mtd->writesize * otp_pages) - (from + len)) < 0)
+		return 0;
+
+	while (len > 0 && otp_pages > 0) {
+		if (!action) {	/* OTP Info functions */
+			struct otp_info *otpinfo;
+
+			len -= sizeof(struct otp_info);
+			if (len <= 0)
+				return -ENOSPC;
+
+			otpinfo = (struct otp_info *) buf;
+			otpinfo->start = from;
+			otpinfo->length = mtd->writesize;
+			otpinfo->locked = 0;
+
+			from += mtd->writesize;
+			buf += sizeof(struct otp_info);
+			*retlen += sizeof(struct otp_info);
+		} else {
+			size_t tmp_retlen;
+			int size = len;
+
+			ret = action(mtd, from, len, &tmp_retlen, buf);
+
+			buf += size;
+			len -= size;
+			*retlen += size;
+
+			if (ret < 0)
+				return ret;
+		}
+		otp_pages--;
+	}
+
+	return 0;
+}
+
+/**
+ * onenand_get_fact_prot_info - [MTD Interface] Read factory OTP info
+ * @param mtd		MTD device structure
+ * @param buf		the databuffer to put/get data
+ * @param len		number of bytes to read
+ *
+ * Read factory OTP info.
+ */
+static int onenand_get_fact_prot_info(struct mtd_info *mtd,
+			struct otp_info *buf, size_t len)
+{
+	size_t retlen;
+	int ret;
+
+	ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_FACTORY);
+
+	return ret ? : retlen;
+}
+
+/**
+ * onenand_read_fact_prot_reg - [MTD Interface] Read factory OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to read
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Read factory OTP area.
+ */
+static int onenand_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len, size_t *retlen, u_char *buf)
+{
+	return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_FACTORY);
+}
+
+/**
+ * onenand_get_user_prot_info - [MTD Interface] Read user OTP info
+ * @param mtd		MTD device structure
+ * @param buf		the databuffer to put/get data
+ * @param len		number of bytes to read
+ *
+ * Read user OTP info.
+ */
+static int onenand_get_user_prot_info(struct mtd_info *mtd,
+			struct otp_info *buf, size_t len)
+{
+	size_t retlen;
+	int ret;
+
+	ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_USER);
+
+	return ret ? : retlen;
+}
+
+/**
+ * onenand_read_user_prot_reg - [MTD Interface] Read user OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to read
+ * @param len		number of bytes to read
+ * @param retlen	pointer to variable to store the number of read bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Read user OTP area.
+ */
+static int onenand_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len, size_t *retlen, u_char *buf)
+{
+	return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_USER);
+}
+
+/**
+ * onenand_write_user_prot_reg - [MTD Interface] Write user OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to write
+ * @param len		number of bytes to write
+ * @param retlen	pointer to variable to store the number of write bytes
+ * @param buf		the databuffer to put/get data
+ *
+ * Write user OTP area.
+ */
+static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len, size_t *retlen, u_char *buf)
+{
+	return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_write, MTD_OTP_USER);
+}
+
+/**
+ * onenand_lock_user_prot_reg - [MTD Interface] Lock user OTP area
+ * @param mtd		MTD device structure
+ * @param from		The offset to lock
+ * @param len		number of bytes to unlock
+ *
+ * Write lock mark on spare area in page 0 in OTP block
+ */
+static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
+			size_t len)
+{
+	unsigned char oob_buf[64];
+	size_t retlen;
+	int ret;
+
+	memset(oob_buf, 0xff, mtd->oobsize);
+	/*
+	 * Note: OTP lock operation
+	 *       OTP block : 0xXXFC
+	 *       1st block : 0xXXF3 (If chip support)
+	 *       Both      : 0xXXF0 (If chip support)
+	 */
+	oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
+
+	/*
+	 * Write lock mark to 8th word of sector0 of page0 of the spare0.
+	 * We write 16 bytes spare area instead of 2 bytes.
+	 */
+	from = 0;
+	len = 16;
+
+	ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER);
+
+	return ret ? : retlen;
+}
+#endif	/* CONFIG_MTD_ONENAND_OTP */
+
 /**
  * onenand_print_device_info - Print device ID
  * @param device        device ID
@@ -1423,15 +1662,15 @@
 
 	/* OneNAND page size & block size */
 	/* The data buffer size is equal to page size */
-	mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
-	mtd->oobsize = mtd->oobblock >> 5;
+	mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
+	mtd->oobsize = mtd->writesize >> 5;
 	/* Pagers per block is always 64 in OneNAND */
-	mtd->erasesize = mtd->oobblock << 6;
+	mtd->erasesize = mtd->writesize << 6;
 
 	this->erase_shift = ffs(mtd->erasesize) - 1;
-	this->page_shift = ffs(mtd->oobblock) - 1;
+	this->page_shift = ffs(mtd->writesize) - 1;
 	this->ppb_shift = (this->erase_shift - this->page_shift);
-	this->page_mask = (mtd->erasesize / mtd->oobblock) - 1;
+	this->page_mask = (mtd->erasesize / mtd->writesize) - 1;
 
 	/* REVIST: Multichip handling */
 
@@ -1475,7 +1714,6 @@
 				"in suspended state\n");
 }
 
-
 /**
  * onenand_scan - [OneNAND Interface] Scan for the OneNAND device
  * @param mtd		MTD device structure
@@ -1522,7 +1760,7 @@
 	/* Allocate buffers, if necessary */
 	if (!this->page_buf) {
 		size_t len;
-		len = mtd->oobblock + mtd->oobsize;
+		len = mtd->writesize + mtd->oobsize;
 		this->page_buf = kmalloc(len, GFP_KERNEL);
 		if (!this->page_buf) {
 			printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
@@ -1537,40 +1775,42 @@
 
 	switch (mtd->oobsize) {
 	case 64:
-		this->autooob = &onenand_oob_64;
+		this->ecclayout = &onenand_oob_64;
 		break;
 
 	case 32:
-		this->autooob = &onenand_oob_32;
+		this->ecclayout = &onenand_oob_32;
 		break;
 
 	default:
 		printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",
 			mtd->oobsize);
 		/* To prevent kernel oops */
-		this->autooob = &onenand_oob_32;
+		this->ecclayout = &onenand_oob_32;
 		break;
 	}
 
-	memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo));
+	mtd->ecclayout = this->ecclayout;
 
 	/* Fill in remaining MTD driver data */
 	mtd->type = MTD_NANDFLASH;
-	mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC;
+	mtd->flags = MTD_CAP_NANDFLASH;
 	mtd->ecctype = MTD_ECC_SW;
 	mtd->erase = onenand_erase;
 	mtd->point = NULL;
 	mtd->unpoint = NULL;
 	mtd->read = onenand_read;
 	mtd->write = onenand_write;
-	mtd->read_ecc = onenand_read_ecc;
-	mtd->write_ecc = onenand_write_ecc;
 	mtd->read_oob = onenand_read_oob;
 	mtd->write_oob = onenand_write_oob;
-	mtd->readv = NULL;
-	mtd->readv_ecc = NULL;
-	mtd->writev = onenand_writev;
-	mtd->writev_ecc = onenand_writev_ecc;
+#ifdef CONFIG_MTD_ONENAND_OTP
+	mtd->get_fact_prot_info = onenand_get_fact_prot_info;
+	mtd->read_fact_prot_reg = onenand_read_fact_prot_reg;
+	mtd->get_user_prot_info = onenand_get_user_prot_info;
+	mtd->read_user_prot_reg = onenand_read_user_prot_reg;
+	mtd->write_user_prot_reg = onenand_write_user_prot_reg;
+	mtd->lock_user_prot_reg = onenand_lock_user_prot_reg;
+#endif
 	mtd->sync = onenand_sync;
 	mtd->lock = NULL;
 	mtd->unlock = onenand_unlock;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index 4510d33..1b00dac 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -17,6 +17,9 @@
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/compatmac.h>
 
+extern int onenand_do_read_oob(struct mtd_info *mtd, loff_t from, size_t len,
+			       size_t *retlen, u_char *buf);
+
 /**
  * check_short_pattern - [GENERIC] check if a pattern is in the buffer
  * @param buf		the buffer to search
@@ -87,13 +90,13 @@
 
 			/* No need to read pages fully,
 			 * just read required OOB bytes */
-			ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs,
-						readlen, &retlen, &buf[0]);
+			ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,
+						  readlen, &retlen, &buf[0]);
 
 			if (ret)
 				return ret;
 
-			if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) {
+			if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
 				bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
 				printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
 					i >> 1, (unsigned int) from);
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index c077d2e..5b58523 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -1,5 +1,5 @@
 /*
- * $Id: redboot.c,v 1.19 2005/12/01 10:03:51 dwmw2 Exp $
+ * $Id: redboot.c,v 1.21 2006/03/30 18:34:37 bjd Exp $
  *
  * Parse RedBoot-style Flash Image System (FIS) tables and
  * produce a Linux partition array to match.
@@ -15,14 +15,14 @@
 
 struct fis_image_desc {
     unsigned char name[16];      // Null terminated name
-    unsigned long flash_base;    // Address within FLASH of image
-    unsigned long mem_base;      // Address in memory where it executes
-    unsigned long size;          // Length of image
-    unsigned long entry_point;   // Execution entry point
-    unsigned long data_length;   // Length of actual data
-    unsigned char _pad[256-(16+7*sizeof(unsigned long))];
-    unsigned long desc_cksum;    // Checksum over image descriptor
-    unsigned long file_cksum;    // Checksum over image data
+    uint32_t	  flash_base;    // Address within FLASH of image
+    uint32_t	  mem_base;      // Address in memory where it executes
+    uint32_t	  size;          // Length of image
+    uint32_t	  entry_point;   // Execution entry point
+    uint32_t	  data_length;   // Length of actual data
+    unsigned char _pad[256-(16+7*sizeof(uint32_t))];
+    uint32_t	  desc_cksum;    // Checksum over image descriptor
+    uint32_t	  file_cksum;    // Checksum over image data
 };
 
 struct fis_list {
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index a3e00a4..fa4362f 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005  Sean Young <sean@mess.org>
  *
- * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $
+ * $Id: rfd_ftl.c,v 1.8 2006/01/15 12:51:44 sean Exp $
  *
  * This type of flash translation layer (FTL) is used by the Embedded BIOS
  * by General Software. It is known as the Resident Flash Disk (RFD), see:
@@ -61,6 +61,7 @@
 		BLOCK_OK,
 		BLOCK_ERASING,
 		BLOCK_ERASED,
+		BLOCK_UNUSED,
 		BLOCK_FAILED
 	} state;
 	int free_sectors;
@@ -99,10 +100,8 @@
 	block->offset = part->block_size * block_no;
 
 	if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) {
-		block->state = BLOCK_ERASED; /* assumption */
-		block->free_sectors = part->data_sectors_per_block;
-		part->reserved_block = block_no;
-		return 1;
+		block->state = BLOCK_UNUSED;
+		return -ENOENT;
 	}
 
 	block->state = BLOCK_OK;
@@ -124,7 +123,7 @@
 			entry = 0;
 
 		if (entry >= part->sector_count) {
-			printk(KERN_NOTICE PREFIX
+			printk(KERN_WARNING PREFIX
 				"'%s': unit #%d: entry %d corrupt, "
 				"sector %d out of range\n",
 				part->mbd.mtd->name, block_no, i, entry);
@@ -132,7 +131,7 @@
 		}
 
 		if (part->sector_map[entry] != -1) {
-			printk(KERN_NOTICE PREFIX
+			printk(KERN_WARNING PREFIX
 				"'%s': more than one entry for sector %d\n",
 				part->mbd.mtd->name, entry);
 			part->errors = 1;
@@ -167,7 +166,7 @@
 	/* each erase block has three bytes header, followed by the map */
 	part->header_sectors_per_block =
 			((HEADER_MAP_OFFSET + sectors_per_block) *
-		 	sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
+			sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
 
 	part->data_sectors_per_block = sectors_per_block -
 			part->header_sectors_per_block;
@@ -226,7 +225,7 @@
 	}
 
 	if (part->reserved_block == -1) {
-		printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n",
+		printk(KERN_WARNING PREFIX "'%s': no empty erase unit found\n",
 				part->mbd.mtd->name);
 
 		part->errors = 1;
@@ -315,7 +314,7 @@
 		rc = -EIO;
 
 	if (rc) {
-		printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "
+		printk(KERN_ERR PREFIX "'%s': unable to write RFD "
 				"header at 0x%lx\n",
 				part->mbd.mtd->name,
 				part->blocks[i].offset);
@@ -348,7 +347,7 @@
 	rc = part->mbd.mtd->erase(part->mbd.mtd, erase);
 
 	if (rc) {
-		printk(KERN_WARNING PREFIX "erase of region %x,%x on '%s' "
+		printk(KERN_ERR PREFIX "erase of region %x,%x on '%s' "
 				"failed\n", erase->addr, erase->len,
 				part->mbd.mtd->name);
 		kfree(erase);
@@ -383,7 +382,7 @@
 		rc = -EIO;
 
 	if (rc) {
-		printk(KERN_NOTICE PREFIX "error reading '%s' at "
+		printk(KERN_ERR PREFIX "error reading '%s' at "
 			"0x%lx\n", part->mbd.mtd->name,
 			part->blocks[block_no].offset);
 
@@ -423,7 +422,7 @@
 			rc = -EIO;
 
 		if (rc) {
-			printk(KERN_NOTICE PREFIX "'%s': Unable to "
+			printk(KERN_ERR PREFIX "'%s': Unable to "
 				"read sector for relocation\n",
 				part->mbd.mtd->name);
 
@@ -520,7 +519,7 @@
  * because if we fill that one up first it'll have the most chance of having
  * the least live sectors at reclaim.
  */
-static int find_free_block(const struct partition *part)
+static int find_free_block(struct partition *part)
 {
 	int block, stop;
 
@@ -533,6 +532,9 @@
 				block != part->reserved_block)
 			return block;
 
+		if (part->blocks[block].state == BLOCK_UNUSED)
+			erase_block(part, block);
+
 		if (++block >= part->total_blocks)
 			block = 0;
 
@@ -541,7 +543,7 @@
 	return -1;
 }
 
-static int find_writeable_block(struct partition *part, u_long *old_sector)
+static int find_writable_block(struct partition *part, u_long *old_sector)
 {
 	int rc, block;
 	size_t retlen;
@@ -570,7 +572,7 @@
 		rc = -EIO;
 
 	if (rc) {
-		printk(KERN_NOTICE PREFIX "'%s': unable to read header at "
+		printk(KERN_ERR PREFIX "'%s': unable to read header at "
 				"0x%lx\n", part->mbd.mtd->name,
 				part->blocks[block].offset);
 		goto err;
@@ -602,7 +604,7 @@
 		rc = -EIO;
 
 	if (rc) {
-		printk(KERN_WARNING PREFIX "error writing '%s' at "
+		printk(KERN_ERR PREFIX "error writing '%s' at "
 			"0x%lx\n", part->mbd.mtd->name, addr);
 		if (rc)
 			goto err;
@@ -652,7 +654,7 @@
 	if (part->current_block == -1 ||
 		!part->blocks[part->current_block].free_sectors) {
 
-		rc = find_writeable_block(part, old_addr);
+		rc = find_writable_block(part, old_addr);
 		if (rc)
 			goto err;
 	}
@@ -675,7 +677,7 @@
 		rc = -EIO;
 
 	if (rc) {
-		printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
+		printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
 				part->mbd.mtd->name, addr);
 		if (rc)
 			goto err;
@@ -695,7 +697,7 @@
 		rc = -EIO;
 
 	if (rc) {
-		printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
+		printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
 				part->mbd.mtd->name, addr);
 		if (rc)
 			goto err;
@@ -776,7 +778,7 @@
 		part->block_size = block_size;
 	else {
 		if (!mtd->erasesize) {
-			printk(KERN_NOTICE PREFIX "please provide block_size");
+			printk(KERN_WARNING PREFIX "please provide block_size");
 			return;
 		}
 		else
@@ -791,8 +793,8 @@
 		if (!(mtd->flags & MTD_WRITEABLE))
 			part->mbd.readonly = 1;
 		else if (part->errors) {
-			printk(KERN_NOTICE PREFIX "'%s': errors found, "
-					"setting read-only", mtd->name);
+			printk(KERN_WARNING PREFIX "'%s': errors found, "
+					"setting read-only\n", mtd->name);
 			part->mbd.readonly = 1;
 		}
 
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index f6d51ce..07136ec 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -508,11 +508,11 @@
  * speak of. We simply pull the packet out of its PIO buffer (which is slow)
  * and queue it for the kernel. Then we reset the card for the next packet.
  *
- * We sometimes get suprise interrupts late both because the SMP IRQ delivery
+ * We sometimes get surprise interrupts late both because the SMP IRQ delivery
  * is message passing and because the card sometimes seems to deliver late. I
  * think if it is part way through a receive and the mode is changed it carries
  * on receiving and sends us an interrupt. We have to band aid all these cases
- * to get a sensible 150kbytes/second performance. Even then you want a small
+ * to get a sensible 150kBytes/second performance. Even then you want a small
  * TCP window.
  */
 
@@ -909,7 +909,7 @@
  * here also causes the module to be unloaded
  */
  
-int init_module(void)
+int __init init_module(void)
 {
 	dev_3c501 = el1_probe(-1);
 	if (IS_ERR(dev_3c501))
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index dcc98af..cb5ef75 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -688,7 +688,7 @@
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
 	struct net_device *dev;
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index 111601c..19c0b85 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -1633,7 +1633,7 @@
 MODULE_PARM_DESC(irq, "EtherLink Plus IRQ number(s) (assigned)");
 MODULE_PARM_DESC(dma, "EtherLink Plus DMA channel(s)");
 
-int init_module(void)
+int __init init_module(void)
 {
 	int this_dev, found = 0;
 
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 4db8289..6039049 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -932,7 +932,7 @@
 MODULE_PARM_DESC(io, "EtherLink16 I/O base address");
 MODULE_PARM_DESC(irq, "(ignored)");
 
-int init_module(void)
+int __init init_module(void)
 {
 	if (io == 0)
 		printk("3c507: You should not use auto-probing with insmod!\n");
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index b40885d4..4bf8510 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -1277,7 +1277,7 @@
 MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)");
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int __init init_module(void)
 {
 	int this_dev,found = 0;
 
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index 6db3301..157eda5 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -1031,8 +1031,7 @@
 		return 1;
 	}
 
-	skb = skb_padto(skb, ETH_ZLEN);
-	if (skb == NULL) {
+	if (skb_padto(skb, ETH_ZLEN)) {
 		netif_wake_queue(dev);
 		return 0;
 	}
@@ -1646,7 +1645,7 @@
  *	insmod multiple modules for now but it's a hack.
  */
 
-int init_module(void)
+int __init init_module(void)
 {
 	this_device = mc32_probe(-1);
 	if (IS_ERR(this_device))
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 274b0138..b467c38 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -375,8 +375,7 @@
    of the drivers, and will likely be provided by some future kernel.
 */
 enum pci_flags_bit {
-	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+	PCI_USES_MASTER=4,
 };
 
 enum {	IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
@@ -446,95 +445,95 @@
 	int io_size;
 } vortex_info_tbl[] __devinitdata = {
 	{"3c590 Vortex 10Mbps",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
 	{"3c592 EISA 10Mbps Demon/Vortex",					/* AKPM: from Don's 3c59x_cb.c 0.49H */
-	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
 	{"3c597 EISA Fast Demon/Vortex",					/* AKPM: from Don's 3c59x_cb.c 0.49H */
-	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
 	{"3c595 Vortex 100baseTx",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
 	{"3c595 Vortex 100baseT4",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
 
 	{"3c595 Vortex 100base-MII",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
+	 PCI_USES_MASTER, IS_VORTEX, 32, },
 	{"3c900 Boomerang 10baseT",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
+	 PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
 	{"3c900 Boomerang 10Mbps Combo",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
+	 PCI_USES_MASTER, IS_BOOMERANG|EEPROM_RESET, 64, },
 	{"3c900 Cyclone 10Mbps TPO",						/* AKPM: from Don's 0.99M */
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 	{"3c900 Cyclone 10Mbps Combo",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 
 	{"3c900 Cyclone 10Mbps TPC",						/* AKPM: from Don's 0.99M */
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 	{"3c900B-FL Cyclone 10base-FL",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 	{"3c905 Boomerang 100baseTx",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
+	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
 	{"3c905 Boomerang 100baseT4",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
+	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_RESET, 64, },
 	{"3c905B Cyclone 100baseTx",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 
 	{"3c905B Cyclone 10/100/BNC",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3c905B-FX Cyclone 100baseFx",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 	{"3c905C Tornado",
-	PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 	{"3c920B-EMB-WNM (ATI Radeon 9100 IGP)",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_MII|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_TORNADO|HAS_MII|HAS_HWCKSM, 128, },
 	{"3c980 Cyclone",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_HWCKSM, 128, },
 
 	{"3c980C Python-T",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3cSOHO100-TX Hurricane",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3c555 Laptop Hurricane",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT|HAS_HWCKSM, 128, },
 	{"3c556 Laptop Tornado",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR|
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR|
 									HAS_HWCKSM, 128, },
 	{"3c556B Laptop Hurricane",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR|
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR|
 	                                WNO_XCVR_PWR|HAS_HWCKSM, 128, },
 
 	{"3c575 [Megahertz] 10/100 LAN 	CardBus",
-	PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
+	PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
 	{"3c575 Boomerang CardBus",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
+	 PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, },
 	{"3CCFE575BT Cyclone CardBus",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|
 									INVERT_LED_PWR|HAS_HWCKSM, 128, },
 	{"3CCFE575CT Tornado CardBus",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
 									MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
 	{"3CCFE656 Cyclone CardBus",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
 									INVERT_LED_PWR|HAS_HWCKSM, 128, },
 
 	{"3CCFEM656B Cyclone+Winmodem CardBus",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
 									INVERT_LED_PWR|HAS_HWCKSM, 128, },
 	{"3CXFEM656C Tornado+Winmodem CardBus",			/* From pcmcia-cs-3.1.5 */
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|
 									MAX_COLLISION_RESET|HAS_HWCKSM, 128, },
 	{"3c450 HomePNA Tornado",						/* AKPM: from Don's 0.99Q */
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3c920 Tornado",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
 	{"3c982 Hydra Dual Port A",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
+	 PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
 
 	{"3c982 Hydra Dual Port B",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
+	 PCI_USES_MASTER, IS_TORNADO|HAS_HWCKSM|HAS_NWAY, 128, },
 	{"3c905B-T4",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
+	 PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_HWCKSM|EXTRA_PREAMBLE, 128, },
 	{"3c920B-EMB-WNM Tornado",
-	 PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
+	 PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_HWCKSM, 128, },
 
 	{NULL,}, /* NULL terminated list. */
 };
@@ -1382,17 +1381,12 @@
 	for (i = 0; i < 6; i++)
 		iowrite8(dev->dev_addr[i], ioaddr + i);
 
-#ifdef __sparc__
-	if (print_info)
-		printk(", IRQ %s\n", __irq_itoa(dev->irq));
-#else
 	if (print_info)
 		printk(", IRQ %d\n", dev->irq);
 	/* Tell them about an invalid IRQ. */
 	if (dev->irq <= 0 || dev->irq >= NR_IRQS)
 		printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
 			   dev->irq);
-#endif
 
 	EL3WINDOW(4);
 	step = (ioread8(ioaddr + Wn4_NetDiag) & 0x1e) >> 1;
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 066e22b01..0cdc830 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -19,11 +19,11 @@
 	See the file COPYING in this distribution for more information.
 
 	Contributors:
-	
+
 		Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
 		PCI suspend/resume  - Felipe Damasio <felipewd@terra.com.br>
 		LinkChg interrupt   - Felipe Damasio <felipewd@terra.com.br>
-			
+
 	TODO:
 	* Test Tx checksumming thoroughly
 	* Implement dev->tx_timeout
@@ -401,6 +401,11 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void cp_poll_controller(struct net_device *dev);
 #endif
+static int cp_get_eeprom_len(struct net_device *dev);
+static int cp_get_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data);
+static int cp_set_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data);
 
 static struct pci_device_id cp_pci_tbl[] = {
 	{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
@@ -461,7 +466,7 @@
 static inline void cp_set_rxbufsize (struct cp_private *cp)
 {
 	unsigned int mtu = cp->dev->mtu;
-	
+
 	if (mtu > ETH_DATA_LEN)
 		/* MTU + ethernet header + FCS + optional VLAN tag */
 		cp->rx_buf_sz = mtu + ETH_HLEN + 8;
@@ -510,7 +515,7 @@
 static inline unsigned int cp_rx_csum_ok (u32 status)
 {
 	unsigned int protocol = (status >> 16) & 0x3;
-	
+
 	if (likely((protocol == RxProtoTCP) && (!(status & TCPFail))))
 		return 1;
 	else if ((protocol == RxProtoUDP) && (!(status & UDPFail)))
@@ -792,7 +797,7 @@
 	entry = cp->tx_head;
 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 	if (dev->features & NETIF_F_TSO)
-		mss = skb_shinfo(skb)->tso_size;
+		mss = skb_shinfo(skb)->gso_size;
 
 	if (skb_shinfo(skb)->nr_frags == 0) {
 		struct cp_desc *txd = &cp->tx_ring[entry];
@@ -1061,7 +1066,7 @@
 	cpw8(Config3, PARMEnable);
 	cp->wol_enabled = 0;
 
-	cpw8(Config5, cpr8(Config5) & PMEStatus); 
+	cpw8(Config5, cpr8(Config5) & PMEStatus);
 
 	cpw32_f(HiTxRingAddr, 0);
 	cpw32_f(HiTxRingAddr + 4, 0);
@@ -1351,7 +1356,7 @@
 		         WAKE_MCAST | WAKE_UCAST;
 	/* We don't need to go on if WOL is disabled */
 	if (!cp->wol_enabled) return;
-	
+
 	options        = cpr8 (Config3);
 	if (options & LinkUp)        wol->wolopts |= WAKE_PHY;
 	if (options & MagicPacket)   wol->wolopts |= WAKE_MAGIC;
@@ -1577,6 +1582,9 @@
 	.get_strings		= cp_get_strings,
 	.get_ethtool_stats	= cp_get_ethtool_stats,
 	.get_perm_addr		= ethtool_op_get_perm_addr,
+	.get_eeprom_len		= cp_get_eeprom_len,
+	.get_eeprom		= cp_get_eeprom,
+	.set_eeprom		= cp_set_eeprom,
 };
 
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1612,24 +1620,32 @@
 #define eeprom_delay()	readl(ee_addr)
 
 /* The EEPROM commands include the alway-set leading bit. */
+#define EE_EXTEND_CMD	(4)
 #define EE_WRITE_CMD	(5)
 #define EE_READ_CMD		(6)
 #define EE_ERASE_CMD	(7)
 
-static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
-{
-	int i;
-	unsigned retval = 0;
-	void __iomem *ee_addr = ioaddr + Cfg9346;
-	int read_cmd = location | (EE_READ_CMD << addr_len);
+#define EE_EWDS_ADDR	(0)
+#define EE_WRAL_ADDR	(1)
+#define EE_ERAL_ADDR	(2)
+#define EE_EWEN_ADDR	(3)
 
+#define CP_EEPROM_MAGIC PCI_DEVICE_ID_REALTEK_8139
+
+static void eeprom_cmd_start(void __iomem *ee_addr)
+{
 	writeb (EE_ENB & ~EE_CS, ee_addr);
 	writeb (EE_ENB, ee_addr);
 	eeprom_delay ();
+}
 
-	/* Shift the read command bits out. */
-	for (i = 4 + addr_len; i >= 0; i--) {
-		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+static void eeprom_cmd(void __iomem *ee_addr, int cmd, int cmd_len)
+{
+	int i;
+
+	/* Shift the command bits out. */
+	for (i = cmd_len - 1; i >= 0; i--) {
+		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
 		writeb (EE_ENB | dataval, ee_addr);
 		eeprom_delay ();
 		writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
@@ -1637,6 +1653,33 @@
 	}
 	writeb (EE_ENB, ee_addr);
 	eeprom_delay ();
+}
+
+static void eeprom_cmd_end(void __iomem *ee_addr)
+{
+	writeb (~EE_CS, ee_addr);
+	eeprom_delay ();
+}
+
+static void eeprom_extend_cmd(void __iomem *ee_addr, int extend_cmd,
+			      int addr_len)
+{
+	int cmd = (EE_EXTEND_CMD << addr_len) | (extend_cmd << (addr_len - 2));
+
+	eeprom_cmd_start(ee_addr);
+	eeprom_cmd(ee_addr, cmd, 3 + addr_len);
+	eeprom_cmd_end(ee_addr);
+}
+
+static u16 read_eeprom (void __iomem *ioaddr, int location, int addr_len)
+{
+	int i;
+	u16 retval = 0;
+	void __iomem *ee_addr = ioaddr + Cfg9346;
+	int read_cmd = location | (EE_READ_CMD << addr_len);
+
+	eeprom_cmd_start(ee_addr);
+	eeprom_cmd(ee_addr, read_cmd, 3 + addr_len);
 
 	for (i = 16; i > 0; i--) {
 		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
@@ -1648,13 +1691,125 @@
 		eeprom_delay ();
 	}
 
-	/* Terminate the EEPROM access. */
-	writeb (~EE_CS, ee_addr);
-	eeprom_delay ();
+	eeprom_cmd_end(ee_addr);
 
 	return retval;
 }
 
+static void write_eeprom(void __iomem *ioaddr, int location, u16 val,
+			 int addr_len)
+{
+	int i;
+	void __iomem *ee_addr = ioaddr + Cfg9346;
+	int write_cmd = location | (EE_WRITE_CMD << addr_len);
+
+	eeprom_extend_cmd(ee_addr, EE_EWEN_ADDR, addr_len);
+
+	eeprom_cmd_start(ee_addr);
+	eeprom_cmd(ee_addr, write_cmd, 3 + addr_len);
+	eeprom_cmd(ee_addr, val, 16);
+	eeprom_cmd_end(ee_addr);
+
+	eeprom_cmd_start(ee_addr);
+	for (i = 0; i < 20000; i++)
+		if (readb(ee_addr) & EE_DATA_READ)
+			break;
+	eeprom_cmd_end(ee_addr);
+
+	eeprom_extend_cmd(ee_addr, EE_EWDS_ADDR, addr_len);
+}
+
+static int cp_get_eeprom_len(struct net_device *dev)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	int size;
+
+	spin_lock_irq(&cp->lock);
+	size = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 256 : 128;
+	spin_unlock_irq(&cp->lock);
+
+	return size;
+}
+
+static int cp_get_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned int addr_len;
+	u16 val;
+	u32 offset = eeprom->offset >> 1;
+	u32 len = eeprom->len;
+	u32 i = 0;
+
+	eeprom->magic = CP_EEPROM_MAGIC;
+
+	spin_lock_irq(&cp->lock);
+
+	addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
+
+	if (eeprom->offset & 1) {
+		val = read_eeprom(cp->regs, offset, addr_len);
+		data[i++] = (u8)(val >> 8);
+		offset++;
+	}
+
+	while (i < len - 1) {
+		val = read_eeprom(cp->regs, offset, addr_len);
+		data[i++] = (u8)val;
+		data[i++] = (u8)(val >> 8);
+		offset++;
+	}
+
+	if (i < len) {
+		val = read_eeprom(cp->regs, offset, addr_len);
+		data[i] = (u8)val;
+	}
+
+	spin_unlock_irq(&cp->lock);
+	return 0;
+}
+
+static int cp_set_eeprom(struct net_device *dev,
+			 struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned int addr_len;
+	u16 val;
+	u32 offset = eeprom->offset >> 1;
+	u32 len = eeprom->len;
+	u32 i = 0;
+
+	if (eeprom->magic != CP_EEPROM_MAGIC)
+		return -EINVAL;
+
+	spin_lock_irq(&cp->lock);
+
+	addr_len = read_eeprom(cp->regs, 0, 8) == 0x8129 ? 8 : 6;
+
+	if (eeprom->offset & 1) {
+		val = read_eeprom(cp->regs, offset, addr_len) & 0xff;
+		val |= (u16)data[i++] << 8;
+		write_eeprom(cp->regs, offset, val, addr_len);
+		offset++;
+	}
+
+	while (i < len - 1) {
+		val = (u16)data[i++];
+		val |= (u16)data[i++] << 8;
+		write_eeprom(cp->regs, offset, val, addr_len);
+		offset++;
+	}
+
+	if (i < len) {
+		val = read_eeprom(cp->regs, offset, addr_len) & 0xff00;
+		val |= (u16)data[i];
+		write_eeprom(cp->regs, offset, val, addr_len);
+	}
+
+	spin_unlock_irq(&cp->lock);
+	return 0;
+}
+
 /* Put the board into D3cold state and wait for WakeUp signal */
 static void cp_set_d3_state (struct cp_private *cp)
 {
@@ -1919,7 +2074,7 @@
 	mii_check_media(&cp->mii_if, netif_msg_link(cp), FALSE);
 
 	spin_unlock_irqrestore (&cp->lock, flags);
-	
+
 	return 0;
 }
 #endif /* CONFIG_PM */
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index feae783..abd6261 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -165,7 +165,7 @@
 static int debug = -1;
 
 /*
- * Receive ring size 
+ * Receive ring size
  * Warning: 64K ring has hardware issues and may lock up.
  */
 #if defined(CONFIG_SH_DREAMCAST)
@@ -257,7 +257,7 @@
 	{0x018a, 0x0106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x126c, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 	{0x1743, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
-	{0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 }, 
+	{0x021b, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
 
 #ifdef CONFIG_SH_SECUREEDGE5410
 	/* Bogus 8139 silicon reports 8129 without external PROM :-( */
@@ -1824,7 +1824,7 @@
 	int tmp_work;
 #endif
 
-	if (netif_msg_rx_err (tp)) 
+	if (netif_msg_rx_err (tp))
 		printk(KERN_DEBUG "%s: Ethernet frame had errors, status %8.8x.\n",
 			dev->name, rx_status);
 	tp->stats.rx_errors++;
@@ -1944,7 +1944,7 @@
 		 RTL_R16 (RxBufAddr),
 		 RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
 
-	while (netif_running(dev) && received < budget 
+	while (netif_running(dev) && received < budget
 	       && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
 		u32 ring_offset = cur_rx % RX_BUF_LEN;
 		u32 rx_status;
@@ -2031,7 +2031,7 @@
 
 			netif_receive_skb (skb);
 		} else {
-			if (net_ratelimit()) 
+			if (net_ratelimit())
 				printk (KERN_WARNING
 					"%s: Memory squeeze, dropping packet.\n",
 					dev->name);
@@ -2158,13 +2158,13 @@
 	status = RTL_R16 (IntrStatus);
 
 	/* shared irq? */
-	if (unlikely((status & rtl8139_intr_mask) == 0)) 
+	if (unlikely((status & rtl8139_intr_mask) == 0))
 		goto out;
 
 	handled = 1;
 
 	/* h/w no longer present (hotplug?) or major error, bail */
-	if (unlikely(status == 0xFFFF)) 
+	if (unlikely(status == 0xFFFF))
 		goto out;
 
 	/* close possible race's with dev_close */
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index da0c878..8a9f7d6 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -1070,8 +1070,7 @@
 				skb->len, (unsigned int)skb->data));
 
 	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index f870274..86be96a 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -275,12 +275,14 @@
 	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
 	int send_length = skb->len, output_page;
 	unsigned long flags;
+	char buf[ETH_ZLEN];
+	char *data = skb->data;
 
 	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
+		memset(buf, 0, ETH_ZLEN);	/* more efficient than doing just the needed bits */
+		memcpy(buf, data, skb->len);
 		send_length = ETH_ZLEN;
+		data = buf;
 	}
 
 	/* Mask interrupts from the ethercard. 
@@ -347,7 +349,7 @@
 	 * trigger the send later, upon receiving a Tx done interrupt.
 	 */
 	 
-	ei_block_output(dev, send_length, skb->data, output_page);
+	ei_block_output(dev, send_length, data, output_page);
 		
 	if (! ei_local->txing) 
 	{
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index bdaaad8..3918990 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -447,6 +447,7 @@
 config MIPS_AU1X00_ENET
 	bool "MIPS AU1000 Ethernet support"
 	depends on NET_ETHERNET && SOC_AU1X00
+	select PHYLIB
 	select CRC32
 	help
 	  If you have an Alchemy Semi AU1X00 based system
@@ -853,6 +854,17 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called smc9194.
 
+config NET_NETX
+	tristate "NetX Ethernet support"
+	select MII
+	depends on NET_ETHERNET && ARCH_NETX
+	help
+	  This is support for the Hilscher netX builtin Ethernet ports
+
+	  To compile this driver as a module, choose M here and read
+	  <file:Documentation/networking/net-modules.txt>. The module
+	  will be called netx-eth.
+
 config DM9000
 	tristate "DM9000 support"
 	depends on (ARM || MIPS) && NET_ETHERNET
@@ -865,6 +877,22 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module will be
 	  called dm9000.
 
+config SMC911X
+	tristate "SMSC LAN911[5678] support"
+	select CRC32
+	select MII
+	depends on NET_ETHERNET && ARCH_PXA
+	help
+	  This is a driver for SMSC's LAN911x series of Ethernet chipsets
+	  including the new LAN9115, LAN9116, LAN9117, and LAN9118.
+	  Say Y if you want it compiled into the kernel, 
+	  and read the Ethernet-HOWTO, available from
+	  <http://www.linuxdoc.org/docs.html#howto>.
+
+	  This driver is also available as a module. The module will be 
+	  called smc911x.  If you want to compile it as a module, say M 
+	  here and read <file:Documentation/modules.txt>
+
 config NET_VENDOR_RACAL
 	bool "Racal-Interlan (Micom) NI cards"
 	depends on NET_ETHERNET && ISA
@@ -1359,8 +1387,8 @@
 	  called apricot.
 
 config B44
-	tristate "Broadcom 4400 ethernet support (EXPERIMENTAL)"
-	depends on NET_PCI && PCI && EXPERIMENTAL
+	tristate "Broadcom 4400 ethernet support"
+	depends on NET_PCI && PCI
 	select MII
 	help
 	  If you have a network (Ethernet) controller of this type, say Y and
@@ -2163,6 +2191,8 @@
 config BNX2
 	tristate "Broadcom NetXtremeII support"
 	depends on PCI
+	select CRC32
+	select ZLIB_INFLATE
 	help
 	  This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
 
@@ -2171,7 +2201,7 @@
 
 config SPIDER_NET
 	tristate "Spider Gigabit Ethernet driver"
-	depends on PCI && PPC_CELL
+	depends on PCI && PPC_IBM_CELL_BLADE
 	select FW_LOADER
 	help
 	  This driver supports the Gigabit Ethernet chips present on the
@@ -2179,11 +2209,11 @@
 
 config GIANFAR
 	tristate "Gianfar Ethernet"
-	depends on 85xx || 83xx
+	depends on 85xx || 83xx || PPC_86xx
 	select PHYLIB
 	help
-	  This driver supports the Gigabit TSEC on the MPC85xx 
-	  family of chips, and the FEC on the 8540
+	  This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
+	  and MPC86xx family of chips, and the FEC on the 8540.
 
 config GFAR_NAPI
 	bool "NAPI Support"
@@ -2311,6 +2341,23 @@
 
 	  If in doubt, say N.
 
+config MYRI10GE
+	tristate "Myricom Myri-10G Ethernet support"
+	depends on PCI
+	select FW_LOADER
+	select CRC32
+	---help---
+	  This driver supports Myricom Myri-10G Dual Protocol interface in
+	  Ethernet mode. If the eeprom on your board is not recent enough,
+	  you will need a newer firmware image.
+	  You may get this image or more information, at:
+
+	  <http://www.myri.com/Myri-10G/>
+
+	  To compile this driver as a module, choose M here and read
+	  <file:Documentation/networking/net-modules.txt>.  The module
+	  will be called myri10ge.
+
 endmenu
 
 source "drivers/net/tokenring/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b90468a..c91e951 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -187,12 +187,15 @@
 obj-$(CONFIG_MACMACE) += macmace.o
 obj-$(CONFIG_MAC89x0) += mac89x0.o
 obj-$(CONFIG_TUN) += tun.o
+obj-$(CONFIG_NET_NETX) += netx-eth.o
 obj-$(CONFIG_DL2K) += dl2k.o
 obj-$(CONFIG_R8169) += r8169.o
 obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
 obj-$(CONFIG_IBMVETH) += ibmveth.o
 obj-$(CONFIG_S2IO) += s2io.o
+obj-$(CONFIG_MYRI10GE) += myri10ge/
 obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_SMC911X) += smc911x.o
 obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
 
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 79bb56b..71165ac 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -573,8 +573,7 @@
 	
 	if (len < ETH_ZLEN) {
 		len = ETH_ZLEN;
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 	}
 
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index b508812..23ff22b 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -579,11 +579,7 @@
 	}
 
 	printk("Gigabit Ethernet at 0x%08lx, ", dev->base_addr);
-#ifdef __sparc__
-	printk("irq %s\n", __irq_itoa(pdev->irq));
-#else
-	printk("irq %i\n", pdev->irq);
-#endif
+	printk("irq %d\n", pdev->irq);
 
 #ifdef CONFIG_ACENIC_OMIT_TIGON_I
 	if ((readl(&ap->regs->HostCtrl) >> 28) == 4) {
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index d1b6b1f..a9bb7a4 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -607,8 +607,7 @@
     /* FIXME: is the 79C960 new enough to do its own padding right ? */
     if (skb->len < ETH_ZLEN)
     {
-    	skb = skb_padto(skb, ETH_ZLEN);
-    	if (skb == NULL)
+    	if (skb_padto(skb, ETH_ZLEN))
     	    return 0;
     	len = ETH_ZLEN;
     }
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 5503dc8..613005a 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -43,7 +43,9 @@
 #define DRV_VERSION	"1.0"
 
 static struct net_device *at91_dev;
-static struct clk *ether_clk;
+
+static struct timer_list check_timer;
+#define LINK_POLL_INTERVAL	(HZ)
 
 /* ..................................................................... */
 
@@ -143,7 +145,7 @@
  * MAC accordingly.
  * If no link or auto-negotiation is busy, then no changes are made.
  */
-static void update_linkspeed(struct net_device *dev)
+static void update_linkspeed(struct net_device *dev, int silent)
 {
 	struct at91_private *lp = (struct at91_private *) dev->priv;
 	unsigned int bmsr, bmcr, lpa, mac_cfg;
@@ -151,7 +153,8 @@
 
 	if (!mii_link_ok(&lp->mii)) {		/* no link */
 		netif_carrier_off(dev);
-		printk(KERN_INFO "%s: Link down.\n", dev->name);
+		if (!silent)
+			printk(KERN_INFO "%s: Link down.\n", dev->name);
 		return;
 	}
 
@@ -186,7 +189,8 @@
 	}
 	at91_emac_write(AT91_EMAC_CFG, mac_cfg);
 
-	printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
+	if (!silent)
+		printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
 	netif_carrier_on(dev);
 }
 
@@ -226,7 +230,7 @@
 			goto done;
 	}
 
-	update_linkspeed(dev);
+	update_linkspeed(dev, 0);
 
 done:
 	disable_mdi();
@@ -243,14 +247,17 @@
 	unsigned int dsintr, irq_number;
 	int status;
 
-	if (lp->phy_type == MII_RTL8201_ID)	/* RTL8201 does not have an interrupt */
-		return;
-	if (lp->phy_type == MII_DP83847_ID)	/* DP83847 does not have an interrupt */
-		return;
-	if (lp->phy_type == MII_AC101L_ID)	/* AC101L interrupt not supported yet */
-		return;
-
 	irq_number = lp->board_data.phy_irq_pin;
+	if (!irq_number) {
+		/*
+		 * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
+		 * or board does not have it connected.
+		 */
+		check_timer.expires = jiffies + LINK_POLL_INTERVAL;
+		add_timer(&check_timer);
+		return;
+	}
+
 	status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
 	if (status) {
 		printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
@@ -292,12 +299,11 @@
 	unsigned int dsintr;
 	unsigned int irq_number;
 
-	if (lp->phy_type == MII_RTL8201_ID) 	/* RTL8201 does not have an interrupt */
+	irq_number = lp->board_data.phy_irq_pin;
+	if (!irq_number) {
+		del_timer_sync(&check_timer);
 		return;
-	if (lp->phy_type == MII_DP83847_ID)	/* DP83847 does not have an interrupt */
-		return;
-	if (lp->phy_type == MII_AC101L_ID)	/* AC101L interrupt not supported yet */
-		return;
+	}
 
 	spin_lock_irq(&lp->lock);
 	enable_mdi();
@@ -326,7 +332,6 @@
 	disable_mdi();
 	spin_unlock_irq(&lp->lock);
 
-	irq_number = lp->board_data.phy_irq_pin;
 	free_irq(irq_number, dev);			/* Free interrupt handler */
 }
 
@@ -355,6 +360,18 @@
 }
 #endif
 
+static void at91ether_check_link(unsigned long dev_id)
+{
+	struct net_device *dev = (struct net_device *) dev_id;
+
+	enable_mdi();
+	update_linkspeed(dev, 1);
+	disable_mdi();
+
+	check_timer.expires = jiffies + LINK_POLL_INTERVAL;
+	add_timer(&check_timer);
+}
+
 /* ......................... ADDRESS MANAGEMENT ........................ */
 
 /*
@@ -501,7 +518,7 @@
 		hash_index |= (bitval << j);
 	}
 
-        return hash_index;
+	return hash_index;
 }
 
 /*
@@ -557,10 +574,8 @@
 	at91_emac_write(AT91_EMAC_CFG, cfg);
 }
 
-
 /* ......................... ETHTOOL SUPPORT ........................... */
 
-
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
 	unsigned int value;
@@ -642,6 +657,22 @@
 	.get_link	= ethtool_op_get_link,
 };
 
+static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct at91_private *lp = (struct at91_private *) dev->priv;
+	int res;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_irq(&lp->lock);
+	enable_mdi();
+	res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
+	disable_mdi();
+	spin_unlock_irq(&lp->lock);
+
+	return res;
+}
 
 /* ................................ MAC ................................ */
 
@@ -685,10 +716,10 @@
 	struct at91_private *lp = (struct at91_private *) dev->priv;
 	unsigned long ctl;
 
-        if (!is_valid_ether_addr(dev->dev_addr))
-        	return -EADDRNOTAVAIL;
+	if (!is_valid_ether_addr(dev->dev_addr))
+		return -EADDRNOTAVAIL;
 
-	clk_enable(ether_clk);			/* Re-enable Peripheral clock */
+	clk_enable(lp->ether_clk);		/* Re-enable Peripheral clock */
 
 	/* Clear internal statistics */
 	ctl = at91_emac_read(AT91_EMAC_CTL);
@@ -708,7 +739,7 @@
 	/* Determine current link speed */
 	spin_lock_irq(&lp->lock);
 	enable_mdi();
-	update_linkspeed(dev);
+	update_linkspeed(dev, 0);
 	disable_mdi();
 	spin_unlock_irq(&lp->lock);
 
@@ -722,6 +753,7 @@
  */
 static int at91ether_close(struct net_device *dev)
 {
+	struct at91_private *lp = (struct at91_private *) dev->priv;
 	unsigned long ctl;
 
 	/* Disable Receiver and Transmitter */
@@ -738,7 +770,7 @@
 
 	netif_stop_queue(dev);
 
-	clk_disable(ether_clk);			/* Disable Peripheral clock */
+	clk_disable(lp->ether_clk);		/* Disable Peripheral clock */
 
 	return 0;
 }
@@ -870,7 +902,7 @@
 	if (intstatus & AT91_EMAC_RCOM)		/* Receive complete */
 		at91ether_rx(dev);
 
-	if (intstatus & AT91_EMAC_TCOM) {		/* Transmit complete */
+	if (intstatus & AT91_EMAC_TCOM) {	/* Transmit complete */
 		/* The TCOM bit is set even if the transmission failed. */
 		if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
 			lp->stats.tx_errors += 1;
@@ -899,7 +931,8 @@
 /*
  * Initialize the ethernet interface
  */
-static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address, struct platform_device *pdev)
+static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_address,
+			struct platform_device *pdev, struct clk *ether_clk)
 {
 	struct at91_eth_data *board_data = pdev->dev.platform_data;
 	struct net_device *dev;
@@ -933,6 +966,7 @@
 		return -ENOMEM;
 	}
 	lp->board_data = *board_data;
+	lp->ether_clk = ether_clk;
 	platform_set_drvdata(pdev, dev);
 
 	spin_lock_init(&lp->lock);
@@ -945,6 +979,7 @@
 	dev->set_multicast_list = at91ether_set_rx_mode;
 	dev->set_mac_address = set_mac_address;
 	dev->ethtool_ops = &at91ether_ethtool_ops;
+	dev->do_ioctl = at91ether_ioctl;
 
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
@@ -975,6 +1010,9 @@
 	lp->mii.dev = dev;		/* Support for ethtool */
 	lp->mii.mdio_read = mdio_read;
 	lp->mii.mdio_write = mdio_write;
+	lp->mii.phy_id = phy_address;
+	lp->mii.phy_id_mask = 0x1f;
+	lp->mii.reg_num_mask = 0x1f;
 
 	lp->phy_type = phy_type;	/* Type of PHY connected */
 	lp->phy_address = phy_address;	/* MDI address of PHY */
@@ -992,11 +1030,18 @@
 	/* Determine current link speed */
 	spin_lock_irq(&lp->lock);
 	enable_mdi();
-	update_linkspeed(dev);
+	update_linkspeed(dev, 0);
 	disable_mdi();
 	spin_unlock_irq(&lp->lock);
 	netif_carrier_off(dev);		/* will be enabled in open() */
 
+	/* If board has no PHY IRQ, use a timer to poll the PHY */
+	if (!lp->board_data.phy_irq_pin) {
+		init_timer(&check_timer);
+		check_timer.data = (unsigned long)dev;
+		check_timer.function = at91ether_check_link;
+	}
+
 	/* Display ethernet banner */
 	printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%02x:%02x:%02x:%02x:%02x:%02x)\n",
 		dev->name, (uint) dev->base_addr, dev->irq,
@@ -1005,7 +1050,7 @@
 		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
 		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 	if ((phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
-		printk(KERN_INFO "%s: Davicom 9196 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
+		printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
 	else if (phy_type == MII_LXT971A_ID)
 		printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
 	else if (phy_type == MII_RTL8201_ID)
@@ -1031,9 +1076,10 @@
 	int detected = -1;
 	unsigned long phy_id;
 	unsigned short phy_address = 0;
+	struct clk *ether_clk;
 
 	ether_clk = clk_get(&pdev->dev, "ether_clk");
-	if (!ether_clk) {
+	if (IS_ERR(ether_clk)) {
 		printk(KERN_ERR "at91_ether: no clock defined\n");
 		return -ENODEV;
 	}
@@ -1056,7 +1102,7 @@
 			case MII_DP83847_ID:		/* National Semiconductor DP83847:  */
 			case MII_AC101L_ID:		/* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
 			case MII_KS8721_ID:		/* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-				detected = at91ether_setup(phy_id, phy_address, pdev);
+				detected = at91ether_setup(phy_id, phy_address, pdev, ether_clk);
 				break;
 		}
 
@@ -1075,17 +1121,61 @@
 	unregister_netdev(at91_dev);
 	free_irq(at91_dev->irq, at91_dev);
 	dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-	clk_put(ether_clk);
+	clk_put(lp->ether_clk);
 
 	free_netdev(at91_dev);
 	at91_dev = NULL;
 	return 0;
 }
 
+#ifdef CONFIG_PM
+
+static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+	struct at91_private *lp = (struct at91_private *) at91_dev->priv;
+	struct net_device *net_dev = platform_get_drvdata(pdev);
+	int phy_irq = lp->board_data.phy_irq_pin;
+
+	if (netif_running(net_dev)) {
+		if (phy_irq)
+			disable_irq(phy_irq);
+
+		netif_stop_queue(net_dev);
+		netif_device_detach(net_dev);
+
+		clk_disable(lp->ether_clk);
+	}
+	return 0;
+}
+
+static int at91ether_resume(struct platform_device *pdev)
+{
+	struct at91_private *lp = (struct at91_private *) at91_dev->priv;
+	struct net_device *net_dev = platform_get_drvdata(pdev);
+	int phy_irq = lp->board_data.phy_irq_pin;
+
+	if (netif_running(net_dev)) {
+		clk_enable(lp->ether_clk);
+
+		netif_device_attach(net_dev);
+		netif_start_queue(net_dev);
+
+		if (phy_irq)
+			enable_irq(phy_irq);
+	}
+	return 0;
+}
+
+#else
+#define at91ether_suspend	NULL
+#define at91ether_resume	NULL
+#endif
+
 static struct platform_driver at91ether_driver = {
 	.probe		= at91ether_probe,
 	.remove		= __devexit_p(at91ether_remove),
-	/* FIXME:  support suspend and resume */
+	.suspend	= at91ether_suspend,
+	.resume		= at91ether_resume,
 	.driver		= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/net/arm/at91_ether.h b/drivers/net/arm/at91_ether.h
index 9885735..d1e72e0 100644
--- a/drivers/net/arm/at91_ether.h
+++ b/drivers/net/arm/at91_ether.h
@@ -80,6 +80,7 @@
 	struct net_device_stats stats;
 	struct mii_if_info mii;			/* ethtool support */
 	struct at91_eth_data board_data;	/* board-specific configuration */
+	struct clk *ether_clk;			/* clock */
 
 	/* PHY */
 	unsigned long phy_type;			/* type of PHY (PHY_ID) */
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index 36475eb..312955d 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -700,8 +700,7 @@
 	}
 
 	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			goto out;
 	}
 
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index f1d5b10..0810741 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -518,8 +518,7 @@
 
 	length = (length + 1) & ~1;
 	if (length != skb->len) {
-		skb = skb_padto(skb, length);
-		if (skb == NULL)
+		if (skb_padto(skb, length))
 			goto out;
 	}
 
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index 442b2cb..91783a8 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -804,8 +804,7 @@
 		++len;
 		
 	if (len > skb->len) {
-		skb = skb_padto(skb, len);
-		if (skb == NULL)
+		if (skb_padto(skb, len))
 			return 0;
 	}
 		
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 14dbad1..038d5fc 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -2,13 +2,16 @@
  *
  * Alchemy Au1x00 ethernet driver
  *
- * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Copyright 2001-2003, 2006 MontaVista Software Inc.
  * Copyright 2002 TimeSys Corp.
  * Added ethtool/mii-tool support,
  * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
  * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de 
  * or riemer@riemer-nt.de: fixed the link beat detection with 
  * ioctls (SIOCGMIIPHY)
+ * Copyright 2006 Herbert Valerio Riedel <hvr@gnu.org>
+ *  converted to use linux-2.6.x's PHY framework
+ *
  * Author: MontaVista Software, Inc.
  *         	ppopov@mvista.com or source@mvista.com
  *
@@ -53,6 +56,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/crc32.h>
+#include <linux/phy.h>
 #include <asm/mipsregs.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -68,7 +72,7 @@
 static int au1000_debug = 3;
 #endif
 
-#define DRV_NAME	"au1000eth"
+#define DRV_NAME	"au1000_eth"
 #define DRV_VERSION	"1.5"
 #define DRV_AUTHOR	"Pete Popov <ppopov@embeddedalley.com>"
 #define DRV_DESC	"Au1xxx on-chip Ethernet driver"
@@ -80,7 +84,7 @@
 // prototypes
 static void hard_stop(struct net_device *);
 static void enable_rx_tx(struct net_device *dev);
-static struct net_device * au1000_probe(u32 ioaddr, int irq, int port_num);
+static struct net_device * au1000_probe(int port_num);
 static int au1000_init(struct net_device *);
 static int au1000_open(struct net_device *);
 static int au1000_close(struct net_device *);
@@ -88,17 +92,15 @@
 static int au1000_rx(struct net_device *);
 static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *);
 static void au1000_tx_timeout(struct net_device *);
-static int au1000_set_config(struct net_device *dev, struct ifmap *map);
 static void set_rx_mode(struct net_device *);
 static struct net_device_stats *au1000_get_stats(struct net_device *);
-static void au1000_timer(unsigned long);
 static int au1000_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *, int, int);
 static void mdio_write(struct net_device *, int, int, u16);
-static void dump_mii(struct net_device *dev, int phy_id);
+static void au1000_adjust_link(struct net_device *);
+static void enable_mac(struct net_device *, int);
 
 // externs
-extern  void ack_rise_edge_irq(unsigned int);
 extern int get_ethernet_addr(char *ethernet_addr);
 extern void str2eaddr(unsigned char *ea, unsigned char *str);
 extern char * __init prom_getcmdline(void);
@@ -126,705 +128,83 @@
 	0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
 };
 
-#define nibswap(x) ((((x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
-#define RUN_AT(x) (jiffies + (x))
-
-// For reading/writing 32-bit words from/to DMA memory
-#define cpu_to_dma32 cpu_to_be32
-#define dma32_to_cpu be32_to_cpu
-
 struct au1000_private *au_macs[NUM_ETH_INTERFACES];
 
-/* FIXME 
- * All of the PHY code really should be detached from the MAC 
- * code.
+/*
+ * board-specific configurations
+ *
+ * PHY detection algorithm
+ *
+ * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is
+ * autodetected:
+ *
+ * mii_probe() first searches the current MAC's MII bus for a PHY,
+ * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is
+ * defined) PHY address not already claimed by another netdev.
+ *
+ * If nothing was found that way when searching for the 2nd ethernet
+ * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then
+ * the first MII bus is searched as well for an unclaimed PHY; this is
+ * needed in case of a dual-PHY accessible only through the MAC0's MII
+ * bus.
+ *
+ * Finally, if no PHY is found, then the corresponding ethernet
+ * controller is not registered to the network subsystem.
  */
 
-/* Default advertise */
-#define GENMII_DEFAULT_ADVERTISE \
-	ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
-	ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-	ADVERTISED_Autoneg
+/* autodetection defaults */
+#undef  AU1XXX_PHY_SEARCH_HIGHEST_ADDR
+#define AU1XXX_PHY1_SEARCH_ON_MAC0
 
-#define GENMII_DEFAULT_FEATURES \
-	SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
-	SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-	SUPPORTED_Autoneg
+/* static PHY setup
+ *
+ * most boards PHY setup should be detectable properly with the
+ * autodetection algorithm in mii_probe(), but in some cases (e.g. if
+ * you have a switch attached, or want to use the PHY's interrupt
+ * notification capabilities) you can provide a static PHY
+ * configuration here
+ *
+ * IRQs may only be set, if a PHY address was configured
+ * If a PHY address is given, also a bus id is required to be set
+ *
+ * ps: make sure the used irqs are configured properly in the board
+ * specific irq-map
+ */
 
-int bcm_5201_init(struct net_device *dev, int phy_addr)
-{
-	s16 data;
-	
-	/* Stop auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+#if defined(CONFIG_MIPS_BOSPORUS)
+/*
+ * Micrel/Kendin 5 port switch attached to MAC0,
+ * MAC0 is associated with PHY address 5 (== WAN port)
+ * MAC1 is not associated with any PHY, since it's connected directly
+ * to the switch.
+ * no interrupts are used
+ */
+# define AU1XXX_PHY_STATIC_CONFIG
 
-	/* Set advertisement to 10/100 and Half/Full duplex
-	 * (full capabilities) */
-	data = mdio_read(dev, phy_addr, MII_ANADV);
-	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-	mdio_write(dev, phy_addr, MII_ANADV, data);
-	
-	/* Restart auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-	mdio_write(dev, phy_addr, MII_CONTROL, data);
+# define AU1XXX_PHY0_ADDR  5
+# define AU1XXX_PHY0_BUSID 0
+#  undef AU1XXX_PHY0_IRQ
 
-	if (au1000_debug > 4) 
-		dump_mii(dev, phy_addr);
-	return 0;
-}
-
-int bcm_5201_reset(struct net_device *dev, int phy_addr)
-{
-	s16 mii_control, timeout;
-	
-	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-	mdelay(1);
-	for (timeout = 100; timeout > 0; --timeout) {
-		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-		if ((mii_control & MII_CNTL_RESET) == 0)
-			break;
-		mdelay(1);
-	}
-	if (mii_control & MII_CNTL_RESET) {
-		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-		return -1;
-	}
-	return 0;
-}
-
-int 
-bcm_5201_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	u16 mii_data;
-	struct au1000_private *aup;
-
-	if (!dev) {
-		printk(KERN_ERR "bcm_5201_status error: NULL dev\n");
-		return -1;
-	}
-	aup = (struct au1000_private *) dev->priv;
-
-	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-	if (mii_data & MII_STAT_LINK) {
-		*link = 1;
-		mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
-		if (mii_data & MII_AUX_100) {
-			if (mii_data & MII_AUX_FDX) {
-				*speed = IF_PORT_100BASEFX;
-				dev->if_port = IF_PORT_100BASEFX;
-			}
-			else {
-				*speed = IF_PORT_100BASETX;
-				dev->if_port = IF_PORT_100BASETX;
-			}
-		}
-		else  {
-			*speed = IF_PORT_10BASET;
-			dev->if_port = IF_PORT_10BASET;
-		}
-
-	}
-	else {
-		*link = 0;
-		*speed = 0;
-		dev->if_port = IF_PORT_UNKNOWN;
-	}
-	return 0;
-}
-
-int lsi_80227_init(struct net_device *dev, int phy_addr)
-{
-	if (au1000_debug > 4)
-		printk("lsi_80227_init\n");
-
-	/* restart auto-negotiation */
-	mdio_write(dev, phy_addr, MII_CONTROL,
-		   MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); // | MII_CNTL_FDX);
-	mdelay(1);
-
-	/* set up LEDs to correct display */
-#ifdef CONFIG_MIPS_MTX1
-	mdio_write(dev, phy_addr, 17, 0xff80);
-#else
-	mdio_write(dev, phy_addr, 17, 0xffc0);
+#  undef AU1XXX_PHY1_ADDR
+#  undef AU1XXX_PHY1_BUSID
+#  undef AU1XXX_PHY1_IRQ
 #endif
 
-	if (au1000_debug > 4)
-		dump_mii(dev, phy_addr);
-	return 0;
-}
-
-int lsi_80227_reset(struct net_device *dev, int phy_addr)
-{
-	s16 mii_control, timeout;
-	
-	if (au1000_debug > 4) {
-		printk("lsi_80227_reset\n");
-		dump_mii(dev, phy_addr);
-	}
-
-	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-	mdelay(1);
-	for (timeout = 100; timeout > 0; --timeout) {
-		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-		if ((mii_control & MII_CNTL_RESET) == 0)
-			break;
-		mdelay(1);
-	}
-	if (mii_control & MII_CNTL_RESET) {
-		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-		return -1;
-	}
-	return 0;
-}
-
-int
-lsi_80227_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	u16 mii_data;
-	struct au1000_private *aup;
-
-	if (!dev) {
-		printk(KERN_ERR "lsi_80227_status error: NULL dev\n");
-		return -1;
-	}
-	aup = (struct au1000_private *) dev->priv;
-
-	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-	if (mii_data & MII_STAT_LINK) {
-		*link = 1;
-		mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_PHY_STAT);
-		if (mii_data & MII_LSI_PHY_STAT_SPD) {
-			if (mii_data & MII_LSI_PHY_STAT_FDX) {
-				*speed = IF_PORT_100BASEFX;
-				dev->if_port = IF_PORT_100BASEFX;
-			}
-			else {
-				*speed = IF_PORT_100BASETX;
-				dev->if_port = IF_PORT_100BASETX;
-			}
-		}
-		else  {
-			*speed = IF_PORT_10BASET;
-			dev->if_port = IF_PORT_10BASET;
-		}
-
-	}
-	else {
-		*link = 0;
-		*speed = 0;
-		dev->if_port = IF_PORT_UNKNOWN;
-	}
-	return 0;
-}
-
-int am79c901_init(struct net_device *dev, int phy_addr)
-{
-	printk("am79c901_init\n");
-	return 0;
-}
-
-int am79c901_reset(struct net_device *dev, int phy_addr)
-{
-	printk("am79c901_reset\n");
-	return 0;
-}
-
-int 
-am79c901_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	return 0;
-}
-
-int am79c874_init(struct net_device *dev, int phy_addr)
-{
-	s16 data;
-
-	/* 79c874 has quit resembled bit assignments to BCM5201 */
-	if (au1000_debug > 4)
-		printk("am79c847_init\n");
-
-	/* Stop auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-	/* Set advertisement to 10/100 and Half/Full duplex
-	 * (full capabilities) */
-	data = mdio_read(dev, phy_addr, MII_ANADV);
-	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-	mdio_write(dev, phy_addr, MII_ANADV, data);
-	
-	/* Restart auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-
-	mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-	if (au1000_debug > 4) dump_mii(dev, phy_addr);
-	return 0;
-}
-
-int am79c874_reset(struct net_device *dev, int phy_addr)
-{
-	s16 mii_control, timeout;
-	
-	if (au1000_debug > 4)
-		printk("am79c874_reset\n");
-
-	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-	mdelay(1);
-	for (timeout = 100; timeout > 0; --timeout) {
-		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-		if ((mii_control & MII_CNTL_RESET) == 0)
-			break;
-		mdelay(1);
-	}
-	if (mii_control & MII_CNTL_RESET) {
-		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-		return -1;
-	}
-	return 0;
-}
-
-int 
-am79c874_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	u16 mii_data;
-	struct au1000_private *aup;
-
-	// printk("am79c874_status\n");
-	if (!dev) {
-		printk(KERN_ERR "am79c874_status error: NULL dev\n");
-		return -1;
-	}
-
-	aup = (struct au1000_private *) dev->priv;
-	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-
-	if (mii_data & MII_STAT_LINK) {
-		*link = 1;
-		mii_data = mdio_read(dev, aup->phy_addr, MII_AMD_PHY_STAT);
-		if (mii_data & MII_AMD_PHY_STAT_SPD) {
-			if (mii_data & MII_AMD_PHY_STAT_FDX) {
-				*speed = IF_PORT_100BASEFX;
-				dev->if_port = IF_PORT_100BASEFX;
-			}
-			else {
-				*speed = IF_PORT_100BASETX;
-				dev->if_port = IF_PORT_100BASETX;
-			}
-		}
-		else {
-			*speed = IF_PORT_10BASET;
-			dev->if_port = IF_PORT_10BASET;
-		}
-
-	}
-	else {
-		*link = 0;
-		*speed = 0;
-		dev->if_port = IF_PORT_UNKNOWN;
-	}
-	return 0;
-}
-
-int lxt971a_init(struct net_device *dev, int phy_addr)
-{
-	if (au1000_debug > 4)
-		printk("lxt971a_init\n");
-
-	/* restart auto-negotiation */
-	mdio_write(dev, phy_addr, MII_CONTROL,
-		   MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO | MII_CNTL_FDX);
-
-	/* set up LEDs to correct display */
-	mdio_write(dev, phy_addr, 20, 0x0422);
-
-	if (au1000_debug > 4)
-		dump_mii(dev, phy_addr);
-	return 0;
-}
-
-int lxt971a_reset(struct net_device *dev, int phy_addr)
-{
-	s16 mii_control, timeout;
-	
-	if (au1000_debug > 4) {
-		printk("lxt971a_reset\n");
-		dump_mii(dev, phy_addr);
-	}
-
-	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-	mdelay(1);
-	for (timeout = 100; timeout > 0; --timeout) {
-		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-		if ((mii_control & MII_CNTL_RESET) == 0)
-			break;
-		mdelay(1);
-	}
-	if (mii_control & MII_CNTL_RESET) {
-		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-		return -1;
-	}
-	return 0;
-}
-
-int
-lxt971a_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	u16 mii_data;
-	struct au1000_private *aup;
-
-	if (!dev) {
-		printk(KERN_ERR "lxt971a_status error: NULL dev\n");
-		return -1;
-	}
-	aup = (struct au1000_private *) dev->priv;
-
-	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-	if (mii_data & MII_STAT_LINK) {
-		*link = 1;
-		mii_data = mdio_read(dev, aup->phy_addr, MII_INTEL_PHY_STAT);
-		if (mii_data & MII_INTEL_PHY_STAT_SPD) {
-			if (mii_data & MII_INTEL_PHY_STAT_FDX) {
-				*speed = IF_PORT_100BASEFX;
-				dev->if_port = IF_PORT_100BASEFX;
-			}
-			else {
-				*speed = IF_PORT_100BASETX;
-				dev->if_port = IF_PORT_100BASETX;
-			}
-		}
-		else  {
-			*speed = IF_PORT_10BASET;
-			dev->if_port = IF_PORT_10BASET;
-		}
-
-	}
-	else {
-		*link = 0;
-		*speed = 0;
-		dev->if_port = IF_PORT_UNKNOWN;
-	}
-	return 0;
-}
-
-int ks8995m_init(struct net_device *dev, int phy_addr)
-{
-	s16 data;
-	
-//	printk("ks8995m_init\n");
-	/* Stop auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-	/* Set advertisement to 10/100 and Half/Full duplex
-	 * (full capabilities) */
-	data = mdio_read(dev, phy_addr, MII_ANADV);
-	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-	mdio_write(dev, phy_addr, MII_ANADV, data);
-	
-	/* Restart auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-	mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-	if (au1000_debug > 4) dump_mii(dev, phy_addr);
-
-	return 0;
-}
-
-int ks8995m_reset(struct net_device *dev, int phy_addr)
-{
-	s16 mii_control, timeout;
-	
-//	printk("ks8995m_reset\n");
-	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-	mdelay(1);
-	for (timeout = 100; timeout > 0; --timeout) {
-		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-		if ((mii_control & MII_CNTL_RESET) == 0)
-			break;
-		mdelay(1);
-	}
-	if (mii_control & MII_CNTL_RESET) {
-		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-		return -1;
-	}
-	return 0;
-}
-
-int ks8995m_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	u16 mii_data;
-	struct au1000_private *aup;
-
-	if (!dev) {
-		printk(KERN_ERR "ks8995m_status error: NULL dev\n");
-		return -1;
-	}
-	aup = (struct au1000_private *) dev->priv;
-
-	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-	if (mii_data & MII_STAT_LINK) {
-		*link = 1;
-		mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
-		if (mii_data & MII_AUX_100) {
-			if (mii_data & MII_AUX_FDX) {
-				*speed = IF_PORT_100BASEFX;
-				dev->if_port = IF_PORT_100BASEFX;
-			}
-			else {
-				*speed = IF_PORT_100BASETX;
-				dev->if_port = IF_PORT_100BASETX;
-			}
-		}
-		else  {											
-			*speed = IF_PORT_10BASET;
-			dev->if_port = IF_PORT_10BASET;
-		}
-
-	}
-	else {
-		*link = 0;
-		*speed = 0;
-		dev->if_port = IF_PORT_UNKNOWN;
-	}
-	return 0;
-}
-
-int
-smsc_83C185_init (struct net_device *dev, int phy_addr)
-{
-	s16 data;
-
-	if (au1000_debug > 4)
-		printk("smsc_83C185_init\n");
-
-	/* Stop auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-	/* Set advertisement to 10/100 and Half/Full duplex
-	 * (full capabilities) */
-	data = mdio_read(dev, phy_addr, MII_ANADV);
-	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-	mdio_write(dev, phy_addr, MII_ANADV, data);
-	
-	/* Restart auto-negotiation */
-	data = mdio_read(dev, phy_addr, MII_CONTROL);
-	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-
-	mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-	if (au1000_debug > 4) dump_mii(dev, phy_addr);
-	return 0;
-}
-
-int
-smsc_83C185_reset (struct net_device *dev, int phy_addr)
-{
-	s16 mii_control, timeout;
-	
-	if (au1000_debug > 4)
-		printk("smsc_83C185_reset\n");
-
-	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
-	mdelay(1);
-	for (timeout = 100; timeout > 0; --timeout) {
-		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
-		if ((mii_control & MII_CNTL_RESET) == 0)
-			break;
-		mdelay(1);
-	}
-	if (mii_control & MII_CNTL_RESET) {
-		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
-		return -1;
-	}
-	return 0;
-}
-
-int 
-smsc_83C185_status (struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	u16 mii_data;
-	struct au1000_private *aup;
-
-	if (!dev) {
-		printk(KERN_ERR "smsc_83C185_status error: NULL dev\n");
-		return -1;
-	}
-
-	aup = (struct au1000_private *) dev->priv;
-	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
-
-	if (mii_data & MII_STAT_LINK) {
-		*link = 1;
-		mii_data = mdio_read(dev, aup->phy_addr, 0x1f);
-		if (mii_data & (1<<3)) {
-			if (mii_data & (1<<4)) {
-				*speed = IF_PORT_100BASEFX;
-				dev->if_port = IF_PORT_100BASEFX;
-			}
-			else {
-				*speed = IF_PORT_100BASETX;
-				dev->if_port = IF_PORT_100BASETX;
-			}
-		}
-		else {
-			*speed = IF_PORT_10BASET;
-			dev->if_port = IF_PORT_10BASET;
-		}
-	}
-	else {
-		*link = 0;
-		*speed = 0;
-		dev->if_port = IF_PORT_UNKNOWN;
-	}
-	return 0;
-}
-
-
-#ifdef CONFIG_MIPS_BOSPORUS
-int stub_init(struct net_device *dev, int phy_addr)
-{
-	//printk("PHY stub_init\n");
-	return 0;
-}
-
-int stub_reset(struct net_device *dev, int phy_addr)
-{
-	//printk("PHY stub_reset\n");
-	return 0;
-}
-
-int 
-stub_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
-{
-	//printk("PHY stub_status\n");
-	*link = 1;
-	/* hmmm, revisit */
-	*speed = IF_PORT_100BASEFX;
-	dev->if_port = IF_PORT_100BASEFX;
-	return 0;
-}
+#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0)
+# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
 #endif
 
-struct phy_ops bcm_5201_ops = {
-	bcm_5201_init,
-	bcm_5201_reset,
-	bcm_5201_status,
-};
-
-struct phy_ops am79c874_ops = {
-	am79c874_init,
-	am79c874_reset,
-	am79c874_status,
-};
-
-struct phy_ops am79c901_ops = {
-	am79c901_init,
-	am79c901_reset,
-	am79c901_status,
-};
-
-struct phy_ops lsi_80227_ops = { 
-	lsi_80227_init,
-	lsi_80227_reset,
-	lsi_80227_status,
-};
-
-struct phy_ops lxt971a_ops = { 
-	lxt971a_init,
-	lxt971a_reset,
-	lxt971a_status,
-};
-
-struct phy_ops ks8995m_ops = {
-	ks8995m_init,
-	ks8995m_reset,
-	ks8995m_status,
-};
-
-struct phy_ops smsc_83C185_ops = {
-	smsc_83C185_init,
-	smsc_83C185_reset,
-	smsc_83C185_status,
-};
-
-#ifdef CONFIG_MIPS_BOSPORUS
-struct phy_ops stub_ops = {
-	stub_init,
-	stub_reset,
-	stub_status,
-};
-#endif
-
-static struct mii_chip_info {
-	const char * name;
-	u16 phy_id0;
-	u16 phy_id1;
-	struct phy_ops *phy_ops;	
-	int dual_phy;
-} mii_chip_table[] = {
-	{"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
-	{"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
-	{"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
-	{"NS DP83847 PHY", 0x2000, 0x5c30, &bcm_5201_ops ,0},
-	{"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
-	{"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
-	{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
-	{"Intel LXT971A Dual Speed PHY",0x0013,0x78e2, &lxt971a_ops,0},
-	{"Kendin KS8995M 10/100 BaseT PHY",0x0022,0x1450, &ks8995m_ops,0},
-	{"SMSC LAN83C185 10/100 BaseT PHY",0x0007,0xc0a3, &smsc_83C185_ops,0},
-#ifdef CONFIG_MIPS_BOSPORUS
-	{"Stub", 0x1234, 0x5678, &stub_ops },
-#endif
-	{0,},
-};
-
-static int mdio_read(struct net_device *dev, int phy_id, int reg)
+/*
+ * MII operations
+ */
+static int mdio_read(struct net_device *dev, int phy_addr, int reg)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
-	volatile u32 *mii_control_reg;
-	volatile u32 *mii_data_reg;
+	volatile u32 *const mii_control_reg = &aup->mac->mii_control;
+	volatile u32 *const mii_data_reg = &aup->mac->mii_data;
 	u32 timedout = 20;
 	u32 mii_control;
 
-	#ifdef CONFIG_BCM5222_DUAL_PHY
-	/* First time we probe, it's for the mac0 phy.
-	 * Since we haven't determined yet that we have a dual phy,
-	 * aup->mii->mii_control_reg won't be setup and we'll
-	 * default to the else statement.
-	 * By the time we probe for the mac1 phy, the mii_control_reg
-	 * will be setup to be the address of the mac0 phy control since
-	 * both phys are controlled through mac0.
-	 */
-	if (aup->mii && aup->mii->mii_control_reg) {
-		mii_control_reg = aup->mii->mii_control_reg;
-		mii_data_reg = aup->mii->mii_data_reg;
-	}
-	else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
-		/* assume both phys are controlled through mac0 */
-		mii_control_reg = au_macs[0]->mii->mii_control_reg;
-		mii_data_reg = au_macs[0]->mii->mii_data_reg;
-	}
-	else 
-	#endif
-	{
-		/* default control and data reg addresses */
-		mii_control_reg = &aup->mac->mii_control;
-		mii_data_reg = &aup->mac->mii_data;
-	}
-
 	while (*mii_control_reg & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
@@ -835,7 +215,7 @@
 	}
 
 	mii_control = MAC_SET_MII_SELECT_REG(reg) | 
-		MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_READ;
+		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_READ;
 
 	*mii_control_reg = mii_control;
 
@@ -851,32 +231,14 @@
 	return (int)*mii_data_reg;
 }
 
-static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
+static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 value)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
-	volatile u32 *mii_control_reg;
-	volatile u32 *mii_data_reg;
+	volatile u32 *const mii_control_reg = &aup->mac->mii_control;
+	volatile u32 *const mii_data_reg = &aup->mac->mii_data;
 	u32 timedout = 20;
 	u32 mii_control;
 
-	#ifdef CONFIG_BCM5222_DUAL_PHY
-	if (aup->mii && aup->mii->mii_control_reg) {
-		mii_control_reg = aup->mii->mii_control_reg;
-		mii_data_reg = aup->mii->mii_data_reg;
-	}
-	else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
-		/* assume both phys are controlled through mac0 */
-		mii_control_reg = au_macs[0]->mii->mii_control_reg;
-		mii_data_reg = au_macs[0]->mii->mii_data_reg;
-	}
-	else 
-	#endif
-	{
-		/* default control and data reg addresses */
-		mii_control_reg = &aup->mac->mii_control;
-		mii_data_reg = &aup->mac->mii_data;
-	}
-
 	while (*mii_control_reg & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
@@ -887,165 +249,145 @@
 	}
 
 	mii_control = MAC_SET_MII_SELECT_REG(reg) | 
-		MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_WRITE;
+		MAC_SET_MII_SELECT_PHY(phy_addr) | MAC_MII_WRITE;
 
 	*mii_data_reg = value;
 	*mii_control_reg = mii_control;
 }
 
-
-static void dump_mii(struct net_device *dev, int phy_id)
+static int mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
 {
-	int i, val;
+	/* WARNING: bus->phy_map[phy_addr].attached_dev == dev does
+	 * _NOT_ hold (e.g. when PHY is accessed through other MAC's MII bus) */
+	struct net_device *const dev = bus->priv;
 
-	for (i = 0; i < 7; i++) {
-		if ((val = mdio_read(dev, phy_id, i)) >= 0)
-			printk("%s: MII Reg %d=%x\n", dev->name, i, val);
-	}
-	for (i = 16; i < 25; i++) {
-		if ((val = mdio_read(dev, phy_id, i)) >= 0)
-			printk("%s: MII Reg %d=%x\n", dev->name, i, val);
-	}
+	enable_mac(dev, 0); /* make sure the MAC associated with this
+			     * mii_bus is enabled */
+	return mdio_read(dev, phy_addr, regnum);
 }
 
-static int mii_probe (struct net_device * dev)
+static int mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum,
+			 u16 value)
 {
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	struct net_device *const dev = bus->priv;
+
+	enable_mac(dev, 0); /* make sure the MAC associated with this
+			     * mii_bus is enabled */
+	mdio_write(dev, phy_addr, regnum, value);
+	return 0;
+}
+
+static int mdiobus_reset(struct mii_bus *bus)
+{
+	struct net_device *const dev = bus->priv;
+
+	enable_mac(dev, 0); /* make sure the MAC associated with this
+			     * mii_bus is enabled */
+	return 0;
+}
+
+static int mii_probe (struct net_device *dev)
+{
+	struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+	struct phy_device *phydev = NULL;
+
+#if defined(AU1XXX_PHY_STATIC_CONFIG)
+	BUG_ON(aup->mac_id < 0 || aup->mac_id > 1);
+
+	if(aup->mac_id == 0) { /* get PHY0 */
+# if defined(AU1XXX_PHY0_ADDR)
+		phydev = au_macs[AU1XXX_PHY0_BUSID]->mii_bus.phy_map[AU1XXX_PHY0_ADDR];
+# else
+		printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
+			dev->name);
+		return 0;
+# endif /* defined(AU1XXX_PHY0_ADDR) */
+	} else if (aup->mac_id == 1) { /* get PHY1 */
+# if defined(AU1XXX_PHY1_ADDR)
+		phydev = au_macs[AU1XXX_PHY1_BUSID]->mii_bus.phy_map[AU1XXX_PHY1_ADDR];
+# else
+		printk (KERN_INFO DRV_NAME ":%s: using PHY-less setup\n",
+			dev->name);
+		return 0;
+# endif /* defined(AU1XXX_PHY1_ADDR) */
+	}
+
+#else /* defined(AU1XXX_PHY_STATIC_CONFIG) */
 	int phy_addr;
-#ifdef CONFIG_MIPS_BOSPORUS
-	int phy_found=0;
-#endif
 
-	/* search for total of 32 possible mii phy addresses */
-	for (phy_addr = 0; phy_addr < 32; phy_addr++) {
-		u16 mii_status;
-		u16 phy_id0, phy_id1;
-		int i;
-
-		#ifdef CONFIG_BCM5222_DUAL_PHY
-		/* Mask the already found phy, try next one */
-		if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
-			if (au_macs[0]->phy_addr == phy_addr)
-				continue;
+	/* find the first (lowest address) PHY on the current MAC's MII bus */
+	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++)
+		if (aup->mii_bus.phy_map[phy_addr]) {
+			phydev = aup->mii_bus.phy_map[phy_addr];
+# if !defined(AU1XXX_PHY_SEARCH_HIGHEST_ADDR)
+			break; /* break out with first one found */
+# endif
 		}
-		#endif
 
-		mii_status = mdio_read(dev, phy_addr, MII_STATUS);
-		if (mii_status == 0xffff || mii_status == 0x0000)
-			/* the mii is not accessable, try next one */
-			continue;
+# if defined(AU1XXX_PHY1_SEARCH_ON_MAC0)
+	/* try harder to find a PHY */
+	if (!phydev && (aup->mac_id == 1)) {
+		/* no PHY found, maybe we have a dual PHY? */
+		printk (KERN_INFO DRV_NAME ": no PHY found on MAC1, "
+			"let's see if it's attached to MAC0...\n");
 
-		phy_id0 = mdio_read(dev, phy_addr, MII_PHY_ID0);
-		phy_id1 = mdio_read(dev, phy_addr, MII_PHY_ID1);
+		BUG_ON(!au_macs[0]);
 
-		/* search our mii table for the current mii */ 
-		for (i = 0; mii_chip_table[i].phy_id1; i++) {
-			if (phy_id0 == mii_chip_table[i].phy_id0 &&
-			    phy_id1 == mii_chip_table[i].phy_id1) {
-				struct mii_phy * mii_phy = aup->mii;
+		/* find the first (lowest address) non-attached PHY on
+		 * the MAC0 MII bus */
+		for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+			struct phy_device *const tmp_phydev =
+				au_macs[0]->mii_bus.phy_map[phy_addr];
 
-				printk(KERN_INFO "%s: %s at phy address %d\n",
-				       dev->name, mii_chip_table[i].name, 
-				       phy_addr);
-#ifdef CONFIG_MIPS_BOSPORUS
-				phy_found = 1;
-#endif
-				mii_phy->chip_info = mii_chip_table+i;
-				aup->phy_addr = phy_addr;
-				aup->want_autoneg = 1;
-				aup->phy_ops = mii_chip_table[i].phy_ops;
-				aup->phy_ops->phy_init(dev,phy_addr);
+			if (!tmp_phydev)
+				continue; /* no PHY here... */
 
-				// Check for dual-phy and then store required 
-				// values and set indicators. We need to do 
-				// this now since mdio_{read,write} need the 
-				// control and data register addresses.
-				#ifdef CONFIG_BCM5222_DUAL_PHY
-				if ( mii_chip_table[i].dual_phy) {
+			if (tmp_phydev->attached_dev)
+				continue; /* already claimed by MAC0 */
 
-					/* assume both phys are controlled 
-					 * through MAC0. Board specific? */
-					
-					/* sanity check */
-					if (!au_macs[0] || !au_macs[0]->mii)
-						return -1;
-					aup->mii->mii_control_reg = (u32 *)
-						&au_macs[0]->mac->mii_control;
-					aup->mii->mii_data_reg = (u32 *)
-						&au_macs[0]->mac->mii_data;
-				}
-				#endif
-				goto found;
-			}
+			phydev = tmp_phydev;
+			break; /* found it */
 		}
 	}
-found:
+# endif /* defined(AU1XXX_PHY1_SEARCH_OTHER_BUS) */
 
-#ifdef CONFIG_MIPS_BOSPORUS
-	/* This is a workaround for the Micrel/Kendin 5 port switch
-	   The second MAC doesn't see a PHY connected... so we need to
-	   trick it into thinking we have one.
-		
-	   If this kernel is run on another Au1500 development board
-	   the stub will be found as well as the actual PHY. However,
-	   the last found PHY will be used... usually at Addr 31 (Db1500).	
-	*/
-	if ( (!phy_found) )
-	{
-		u16 phy_id0, phy_id1;
-		int i;
-
-		phy_id0 = 0x1234;
-		phy_id1 = 0x5678;
-
-		/* search our mii table for the current mii */ 
-		for (i = 0; mii_chip_table[i].phy_id1; i++) {
-			if (phy_id0 == mii_chip_table[i].phy_id0 &&
-			    phy_id1 == mii_chip_table[i].phy_id1) {
-				struct mii_phy * mii_phy;
-
-				printk(KERN_INFO "%s: %s at phy address %d\n",
-				       dev->name, mii_chip_table[i].name, 
-				       phy_addr);
-				mii_phy = kmalloc(sizeof(struct mii_phy), 
-						GFP_KERNEL);
-				if (mii_phy) {
-					mii_phy->chip_info = mii_chip_table+i;
-					aup->phy_addr = phy_addr;
-					mii_phy->next = aup->mii;
-					aup->phy_ops = 
-						mii_chip_table[i].phy_ops;
-					aup->mii = mii_phy;
-					aup->phy_ops->phy_init(dev,phy_addr);
-				} else {
-					printk(KERN_ERR "%s: out of memory\n", 
-							dev->name);
-					return -1;
-				}
-				mii_phy->chip_info = mii_chip_table+i;
-				aup->phy_addr = phy_addr;
-				aup->phy_ops = mii_chip_table[i].phy_ops;
-				aup->phy_ops->phy_init(dev,phy_addr);
-				break;
-			}
-		}
-	}
-	if (aup->mac_id == 0) {
-		/* the Bosporus phy responds to addresses 0-5 but 
-		 * 5 is the correct one.
-		 */
-		aup->phy_addr = 5;
-	}
-#endif
-
-	if (aup->mii->chip_info == NULL) {
-		printk(KERN_ERR "%s: Au1x No known MII transceivers found!\n",
-				dev->name);
+#endif /* defined(AU1XXX_PHY_STATIC_CONFIG) */
+	if (!phydev) {
+		printk (KERN_ERR DRV_NAME ":%s: no PHY found\n", dev->name);
 		return -1;
 	}
 
-	printk(KERN_INFO "%s: Using %s as default\n", 
-			dev->name, aup->mii->chip_info->name);
+	/* now we are supposed to have a proper phydev, to attach to... */
+	BUG_ON(!phydev);
+	BUG_ON(phydev->attached_dev);
+
+	phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0);
+
+	if (IS_ERR(phydev)) {
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		return PTR_ERR(phydev);
+	}
+
+	/* mask with MAC supported features */
+	phydev->supported &= (SUPPORTED_10baseT_Half
+			      | SUPPORTED_10baseT_Full
+			      | SUPPORTED_100baseT_Half
+			      | SUPPORTED_100baseT_Full
+			      | SUPPORTED_Autoneg
+			      /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */
+			      | SUPPORTED_MII
+			      | SUPPORTED_TP);
+
+	phydev->advertising = phydev->supported;
+
+	aup->old_link = 0;
+	aup->old_speed = 0;
+	aup->old_duplex = -1;
+	aup->phy_dev = phydev;
+
+	printk(KERN_INFO "%s: attached PHY driver [%s] "
+	       "(mii_bus:phy_addr=%s, irq=%d)\n",
+	       dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
 
 	return 0;
 }
@@ -1097,35 +439,38 @@
 	au_sync_delay(10);
 }
 
-
-static void reset_mac(struct net_device *dev)
+static void enable_mac(struct net_device *dev, int force_reset)
 {
-	int i;
-	u32 flags;
+	unsigned long flags;
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
 
-	if (au1000_debug > 4) 
-		printk(KERN_INFO "%s: reset mac, aup %x\n", 
-				dev->name, (unsigned)aup);
-
 	spin_lock_irqsave(&aup->lock, flags);
-	if (aup->timer.function == &au1000_timer) {/* check if timer initted */
-		del_timer(&aup->timer);
-	}
 
-	hard_stop(dev);
-	#ifdef CONFIG_BCM5222_DUAL_PHY
-	if (aup->mac_id != 0) {
-	#endif
-		/* If BCM5222, we can't leave MAC0 in reset because then 
-		 * we can't access the dual phy for ETH1 */
+	if(force_reset || (!aup->mac_enabled)) {
 		*aup->enable = MAC_EN_CLOCK_ENABLE;
 		au_sync_delay(2);
-		*aup->enable = 0;
+		*aup->enable = (MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
+				| MAC_EN_CLOCK_ENABLE);
 		au_sync_delay(2);
-	#ifdef CONFIG_BCM5222_DUAL_PHY
+
+		aup->mac_enabled = 1;
 	}
-	#endif
+
+	spin_unlock_irqrestore(&aup->lock, flags);
+}
+
+static void reset_mac_unlocked(struct net_device *dev)
+{
+	struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+	int i;
+
+	hard_stop(dev);
+
+	*aup->enable = MAC_EN_CLOCK_ENABLE;
+	au_sync_delay(2);
+	*aup->enable = 0;
+	au_sync_delay(2);
+
 	aup->tx_full = 0;
 	for (i = 0; i < NUM_RX_DMA; i++) {
 		/* reset control bits */
@@ -1135,9 +480,26 @@
 		/* reset control bits */
 		aup->tx_dma_ring[i]->buff_stat &= ~0xf;
 	}
-	spin_unlock_irqrestore(&aup->lock, flags);
+
+	aup->mac_enabled = 0;
+
 }
 
+static void reset_mac(struct net_device *dev)
+{
+	struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+	unsigned long flags;
+
+	if (au1000_debug > 4)
+		printk(KERN_INFO "%s: reset mac, aup %x\n",
+		       dev->name, (unsigned)aup);
+
+	spin_lock_irqsave(&aup->lock, flags);
+
+	reset_mac_unlocked (dev);
+
+	spin_unlock_irqrestore(&aup->lock, flags);
+}
 
 /* 
  * Setup the receive and transmit "rings".  These pointers are the addresses
@@ -1160,12 +522,27 @@
 }
 
 static struct {
-	int port;
 	u32 base_addr;
 	u32 macen_addr;
 	int irq;
 	struct net_device *dev;
-} iflist[2];
+} iflist[2] = {
+#ifdef CONFIG_SOC_AU1000
+	{AU1000_ETH0_BASE, AU1000_MAC0_ENABLE, AU1000_MAC0_DMA_INT},
+	{AU1000_ETH1_BASE, AU1000_MAC1_ENABLE, AU1000_MAC1_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1100
+	{AU1100_ETH0_BASE, AU1100_MAC0_ENABLE, AU1100_MAC0_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1500
+	{AU1500_ETH0_BASE, AU1500_MAC0_ENABLE, AU1500_MAC0_DMA_INT},
+	{AU1500_ETH1_BASE, AU1500_MAC1_ENABLE, AU1500_MAC1_DMA_INT}
+#endif
+#ifdef CONFIG_SOC_AU1550
+	{AU1550_ETH0_BASE, AU1550_MAC0_ENABLE, AU1550_MAC0_DMA_INT},
+	{AU1550_ETH1_BASE, AU1550_MAC1_ENABLE, AU1550_MAC1_DMA_INT}
+#endif
+};
 
 static int num_ifs;
 
@@ -1176,58 +553,14 @@
  */
 static int __init au1000_init_module(void)
 {
-	struct cpuinfo_mips *c = &current_cpu_data;
 	int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
 	struct net_device *dev;
 	int i, found_one = 0;
 
-	switch (c->cputype) {
-#ifdef CONFIG_SOC_AU1000
-	case CPU_AU1000:
-		num_ifs = 2 - ni;
-		iflist[0].base_addr = AU1000_ETH0_BASE;
-		iflist[1].base_addr = AU1000_ETH1_BASE;
-		iflist[0].macen_addr = AU1000_MAC0_ENABLE;
-		iflist[1].macen_addr = AU1000_MAC1_ENABLE;
-		iflist[0].irq = AU1000_MAC0_DMA_INT;
-		iflist[1].irq = AU1000_MAC1_DMA_INT;
-		break;
-#endif
-#ifdef CONFIG_SOC_AU1100
-	case CPU_AU1100:
-		num_ifs = 1 - ni;
-		iflist[0].base_addr = AU1100_ETH0_BASE;
-		iflist[0].macen_addr = AU1100_MAC0_ENABLE;
-		iflist[0].irq = AU1100_MAC0_DMA_INT;
-		break;
-#endif
-#ifdef CONFIG_SOC_AU1500
-	case CPU_AU1500:
-		num_ifs = 2 - ni;
-		iflist[0].base_addr = AU1500_ETH0_BASE;
-		iflist[1].base_addr = AU1500_ETH1_BASE;
-		iflist[0].macen_addr = AU1500_MAC0_ENABLE;
-		iflist[1].macen_addr = AU1500_MAC1_ENABLE;
-		iflist[0].irq = AU1500_MAC0_DMA_INT;
-		iflist[1].irq = AU1500_MAC1_DMA_INT;
-		break;
-#endif
-#ifdef CONFIG_SOC_AU1550
-	case CPU_AU1550:
-		num_ifs = 2 - ni;
-		iflist[0].base_addr = AU1550_ETH0_BASE;
-		iflist[1].base_addr = AU1550_ETH1_BASE;
-		iflist[0].macen_addr = AU1550_MAC0_ENABLE;
-		iflist[1].macen_addr = AU1550_MAC1_ENABLE;
-		iflist[0].irq = AU1550_MAC0_DMA_INT;
-		iflist[1].irq = AU1550_MAC1_DMA_INT;
-		break;
-#endif
-	default:
-		num_ifs = 0;
-	}
+	num_ifs = NUM_ETH_INTERFACES - ni;
+
 	for(i = 0; i < num_ifs; i++) {
-		dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i);
+		dev = au1000_probe(i);
 		iflist[i].dev = dev;
 		if (dev)
 			found_one++;
@@ -1237,178 +570,31 @@
 	return 0;
 }
 
-static int au1000_setup_aneg(struct net_device *dev, u32 advertise)
-{
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
-	u16 ctl, adv;
-
-	/* Setup standard advertise */
-	adv = mdio_read(dev, aup->phy_addr, MII_ADVERTISE);
-	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
-	if (advertise & ADVERTISED_10baseT_Half)
-		adv |= ADVERTISE_10HALF;
-	if (advertise & ADVERTISED_10baseT_Full)
-		adv |= ADVERTISE_10FULL;
-	if (advertise & ADVERTISED_100baseT_Half)
-		adv |= ADVERTISE_100HALF;
-	if (advertise & ADVERTISED_100baseT_Full)
-		adv |= ADVERTISE_100FULL;
-	mdio_write(dev, aup->phy_addr, MII_ADVERTISE, adv);
-
-	/* Start/Restart aneg */
-	ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
-	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
-	mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
-
-	return 0;
-}
-
-static int au1000_setup_forced(struct net_device *dev, int speed, int fd)
-{
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
-	u16 ctl;
-
-	ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
-	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
-
-	/* First reset the PHY */
-	mdio_write(dev, aup->phy_addr, MII_BMCR, ctl | BMCR_RESET);
-
-	/* Select speed & duplex */
-	switch (speed) {
-		case SPEED_10:
-			break;
-		case SPEED_100:
-			ctl |= BMCR_SPEED100;
-			break;
-		case SPEED_1000:
-		default:
-			return -EINVAL;
-	}
-	if (fd == DUPLEX_FULL)
-		ctl |= BMCR_FULLDPLX;
-	mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
-
-	return 0;
-}
-
-
-static void
-au1000_start_link(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-	struct au1000_private *aup = (struct au1000_private *)dev->priv;
-	u32 advertise;
-	int autoneg;
-	int forced_speed;
-	int forced_duplex;
-
-	/* Default advertise */
-	advertise = GENMII_DEFAULT_ADVERTISE;
-	autoneg = aup->want_autoneg;
-	forced_speed = SPEED_100;
-	forced_duplex = DUPLEX_FULL;
-
-	/* Setup link parameters */
-	if (cmd) {
-		if (cmd->autoneg == AUTONEG_ENABLE) {
-			advertise = cmd->advertising;
-			autoneg = 1;
-		} else {
-			autoneg = 0;
-
-			forced_speed = cmd->speed;
-			forced_duplex = cmd->duplex;
-		}
-	}
-
-	/* Configure PHY & start aneg */
-	aup->want_autoneg = autoneg;
-	if (autoneg)
-		au1000_setup_aneg(dev, advertise);
-	else
-		au1000_setup_forced(dev, forced_speed, forced_duplex);
-	mod_timer(&aup->timer, jiffies + HZ);
-}
+/*
+ * ethtool operations
+ */
 
 static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct au1000_private *aup = (struct au1000_private *)dev->priv;
-	u16 link, speed;
 
-	cmd->supported = GENMII_DEFAULT_FEATURES;
-	cmd->advertising = GENMII_DEFAULT_ADVERTISE;
-	cmd->port = PORT_MII;
-	cmd->transceiver = XCVR_EXTERNAL;
-	cmd->phy_address = aup->phy_addr;
-	spin_lock_irq(&aup->lock);
-	cmd->autoneg = aup->want_autoneg;
-	aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
-	if ((speed == IF_PORT_100BASETX) || (speed == IF_PORT_100BASEFX))
-		cmd->speed = SPEED_100;
-	else if (speed == IF_PORT_10BASET)
-		cmd->speed = SPEED_10;
-	if (link && (dev->if_port == IF_PORT_100BASEFX))
-		cmd->duplex = DUPLEX_FULL;
-	else
-		cmd->duplex = DUPLEX_HALF;
-	spin_unlock_irq(&aup->lock);
-	return 0;
+	if (aup->phy_dev)
+		return phy_ethtool_gset(aup->phy_dev, cmd);
+
+	return -EINVAL;
 }
 
 static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	 struct au1000_private *aup = (struct au1000_private *)dev->priv;
-	  unsigned long features = GENMII_DEFAULT_FEATURES;
-
-	 if (!capable(CAP_NET_ADMIN))
-		 return -EPERM;
-
-	 if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
-		 return -EINVAL;
-	 if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
-		 return -EINVAL;
-	 if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
-		 return -EINVAL;
-	 if (cmd->autoneg == AUTONEG_DISABLE)
-		 switch (cmd->speed) {
-		 case SPEED_10:
-			 if (cmd->duplex == DUPLEX_HALF &&
-				 (features & SUPPORTED_10baseT_Half) == 0)
-				 return -EINVAL;
-			 if (cmd->duplex == DUPLEX_FULL &&
-				 (features & SUPPORTED_10baseT_Full) == 0)
-				 return -EINVAL;
-			 break;
-		 case SPEED_100:
-			 if (cmd->duplex == DUPLEX_HALF &&
-				 (features & SUPPORTED_100baseT_Half) == 0)
-				 return -EINVAL;
-			 if (cmd->duplex == DUPLEX_FULL &&
-				 (features & SUPPORTED_100baseT_Full) == 0)
-				 return -EINVAL;
-			 break;
-		 default:
-			 return -EINVAL;
-		 }
-	 else if ((features & SUPPORTED_Autoneg) == 0)
-		 return -EINVAL;
-
-	 spin_lock_irq(&aup->lock);
-	 au1000_start_link(dev, cmd);
-	 spin_unlock_irq(&aup->lock);
-	 return 0;
-}
-
-static int au1000_nway_reset(struct net_device *dev)
-{
 	struct au1000_private *aup = (struct au1000_private *)dev->priv;
 
-	if (!aup->want_autoneg)
-		return -EINVAL;
-	spin_lock_irq(&aup->lock);
-	au1000_start_link(dev, NULL);
-	spin_unlock_irq(&aup->lock);
-	return 0;
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	if (aup->phy_dev)
+		return phy_ethtool_sset(aup->phy_dev, cmd);
+
+	return -EINVAL;
 }
 
 static void
@@ -1423,21 +609,14 @@
 	info->regdump_len = 0;
 }
 
-static u32 au1000_get_link(struct net_device *dev)
-{
-	return netif_carrier_ok(dev);
-}
-
 static struct ethtool_ops au1000_ethtool_ops = {
 	.get_settings = au1000_get_settings,
 	.set_settings = au1000_set_settings,
 	.get_drvinfo = au1000_get_drvinfo,
-	.nway_reset = au1000_nway_reset,
-	.get_link = au1000_get_link
+	.get_link = ethtool_op_get_link,
 };
 
-static struct net_device *
-au1000_probe(u32 ioaddr, int irq, int port_num)
+static struct net_device * au1000_probe(int port_num)
 {
 	static unsigned version_printed = 0;
 	struct au1000_private *aup = NULL;
@@ -1445,106 +624,115 @@
 	db_dest_t *pDB, *pDBfree;
 	char *pmac, *argptr;
 	char ethaddr[6];
-	int i, err;
+	int irq, i, err;
+	u32 base, macen;
 
-	if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "Au1x00 ENET"))
+	if (port_num >= NUM_ETH_INTERFACES)
+ 		return NULL;
+
+	base  = CPHYSADDR(iflist[port_num].base_addr );
+	macen = CPHYSADDR(iflist[port_num].macen_addr);
+	irq = iflist[port_num].irq;
+
+	if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
+	    !request_mem_region(macen, 4, "Au1x00 ENET"))
 		return NULL;
 
-	if (version_printed++ == 0) 
+	if (version_printed++ == 0)
 		printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
 
 	dev = alloc_etherdev(sizeof(struct au1000_private));
 	if (!dev) {
-		printk (KERN_ERR "au1000 eth: alloc_etherdev failed\n");  
+		printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
 		return NULL;
 	}
 
-	if ((err = register_netdev(dev))) {
-		printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n",
-				err);
+	if ((err = register_netdev(dev)) != 0) {
+		printk(KERN_ERR "%s: Cannot register net device, error %d\n",
+				DRV_NAME, err);
 		free_netdev(dev);
 		return NULL;
 	}
 
-	printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", 
-			dev->name, ioaddr, irq);
+	printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
+		dev->name, base, irq);
 
 	aup = dev->priv;
 
 	/* Allocate the data buffers */
 	/* Snooping works fine with eth on all au1xxx */
-	aup->vaddr = (u32)dma_alloc_noncoherent(NULL,
-			MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-			&aup->dma_addr,
-			0);
+	aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
+						(NUM_TX_BUFFS + NUM_RX_BUFFS),
+						&aup->dma_addr,	0);
 	if (!aup->vaddr) {
 		free_netdev(dev);
-		release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+		release_mem_region( base, MAC_IOSIZE);
+		release_mem_region(macen, 4);
 		return NULL;
 	}
 
 	/* aup->mac is the base address of the MAC's registers */
-	aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
+	aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;
+
 	/* Setup some variables for quick register address access */
-	if (ioaddr == iflist[0].base_addr)
-	{
-		/* check env variables first */
-		if (!get_ethernet_addr(ethaddr)) { 
+	aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
+	aup->mac_id = port_num;
+	au_macs[port_num] = aup;
+
+	if (port_num == 0) {
+		/* Check the environment variables first */
+		if (get_ethernet_addr(ethaddr) == 0)
 			memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
-		} else {
+		else {
 			/* Check command line */
 			argptr = prom_getcmdline();
-			if ((pmac = strstr(argptr, "ethaddr=")) == NULL) {
-				printk(KERN_INFO "%s: No mac address found\n", 
-						dev->name);
-				/* use the hard coded mac addresses */
-			} else {
+			if ((pmac = strstr(argptr, "ethaddr=")) == NULL)
+				printk(KERN_INFO "%s: No MAC address found\n",
+						 dev->name);
+				/* Use the hard coded MAC addresses */
+			else {
 				str2eaddr(ethaddr, pmac + strlen("ethaddr="));
 				memcpy(au1000_mac_addr, ethaddr, 
-						sizeof(au1000_mac_addr));
+				       sizeof(au1000_mac_addr));
 			}
 		}
-			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[0].macen_addr);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+
 		setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-		aup->mac_id = 0;
-		au_macs[0] = aup;
-	}
-		else
-	if (ioaddr == iflist[1].base_addr)
-	{
-			aup->enable = (volatile u32 *) 
-				((unsigned long)iflist[1].macen_addr);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
-		dev->dev_addr[4] += 0x10;
+	} else if (port_num == 1)
 		setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
-		aup->mac_id = 1;
-		au_macs[1] = aup;
-	}
-	else
-	{
-		printk(KERN_ERR "%s: bad ioaddr\n", dev->name);
-	}
 
-	/* bring the device out of reset, otherwise probing the mii
-	 * will hang */
-	*aup->enable = MAC_EN_CLOCK_ENABLE;
-	au_sync_delay(2);
-	*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
-		MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
-	au_sync_delay(2);
+	/*
+	 * Assign to the Ethernet ports two consecutive MAC addresses
+	 * to match those that are printed on their stickers
+	 */
+	memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
+	dev->dev_addr[5] += port_num;
 
-	aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL);
-	if (!aup->mii) {
-		printk(KERN_ERR "%s: out of memory\n", dev->name);
-		goto err_out;
-	}
-	aup->mii->next = NULL;
-	aup->mii->chip_info = NULL;
-	aup->mii->status = 0;
-	aup->mii->mii_control_reg = 0;
-	aup->mii->mii_data_reg = 0;
+	*aup->enable = 0;
+	aup->mac_enabled = 0;
+
+	aup->mii_bus.priv = dev;
+	aup->mii_bus.read = mdiobus_read;
+	aup->mii_bus.write = mdiobus_write;
+	aup->mii_bus.reset = mdiobus_reset;
+	aup->mii_bus.name = "au1000_eth_mii";
+	aup->mii_bus.id = aup->mac_id;
+	aup->mii_bus.irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
+	for(i = 0; i < PHY_MAX_ADDR; ++i)
+		aup->mii_bus.irq[i] = PHY_POLL;
+
+	/* if known, set corresponding PHY IRQs */
+#if defined(AU1XXX_PHY_STATIC_CONFIG)
+# if defined(AU1XXX_PHY0_IRQ)
+	if (AU1XXX_PHY0_BUSID == aup->mii_bus.id)
+		aup->mii_bus.irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
+# endif
+# if defined(AU1XXX_PHY1_IRQ)
+	if (AU1XXX_PHY1_BUSID == aup->mii_bus.id)
+		aup->mii_bus.irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
+# endif
+#endif
+	mdiobus_register(&aup->mii_bus);
 
 	if (mii_probe(dev) != 0) {
 		goto err_out;
@@ -1581,7 +769,7 @@
 	}
 
 	spin_lock_init(&aup->lock);
-	dev->base_addr = ioaddr;
+	dev->base_addr = base;
 	dev->irq = irq;
 	dev->open = au1000_open;
 	dev->hard_start_xmit = au1000_tx;
@@ -1590,7 +778,6 @@
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &au1000_ioctl;
 	SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
-	dev->set_config = &au1000_set_config;
 	dev->tx_timeout = au1000_tx_timeout;
 	dev->watchdog_timeo = ETH_TX_TIMEOUT;
 
@@ -1606,7 +793,7 @@
 	/* here we should have a valid dev plus aup-> register addresses
 	 * so we can reset the mac properly.*/
 	reset_mac(dev);
-	kfree(aup->mii);
+
 	for (i = 0; i < NUM_RX_DMA; i++) {
 		if (aup->rx_db_inuse[i])
 			ReleaseDB(aup, aup->rx_db_inuse[i]);
@@ -1615,13 +802,12 @@
 		if (aup->tx_db_inuse[i])
 			ReleaseDB(aup, aup->tx_db_inuse[i]);
 	}
-	dma_free_noncoherent(NULL,
-			MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-			(void *)aup->vaddr,
-			aup->dma_addr);
+	dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+			     (void *)aup->vaddr, aup->dma_addr);
 	unregister_netdev(dev);
 	free_netdev(dev);
-	release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+	release_mem_region( base, MAC_IOSIZE);
+	release_mem_region(macen, 4);
 	return NULL;
 }
 
@@ -1640,19 +826,14 @@
 	u32 flags;
 	int i;
 	u32 control;
-	u16 link, speed;
 
 	if (au1000_debug > 4) 
 		printk("%s: au1000_init\n", dev->name);
 
-	spin_lock_irqsave(&aup->lock, flags);
-
 	/* bring the device out of reset */
-	*aup->enable = MAC_EN_CLOCK_ENABLE;
-        au_sync_delay(2);
-	*aup->enable = MAC_EN_RESET0 | MAC_EN_RESET1 | 
-		MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
-	au_sync_delay(20);
+	enable_mac(dev, 1);
+
+	spin_lock_irqsave(&aup->lock, flags);
 
 	aup->mac->control = 0;
 	aup->tx_head = (aup->tx_dma_ring[0]->buff_stat & 0xC) >> 2;
@@ -1668,12 +849,16 @@
 	}
 	au_sync();
 
-	aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
-	control = MAC_DISABLE_RX_OWN | MAC_RX_ENABLE | MAC_TX_ENABLE;
+	control = MAC_RX_ENABLE | MAC_TX_ENABLE;
 #ifndef CONFIG_CPU_LITTLE_ENDIAN
 	control |= MAC_BIG_ENDIAN;
 #endif
-	if (link && (dev->if_port == IF_PORT_100BASEFX)) {
+	if (aup->phy_dev) {
+		if (aup->phy_dev->link && (DUPLEX_FULL == aup->phy_dev->duplex))
+			control |= MAC_FULL_DUPLEX;
+		else
+			control |= MAC_DISABLE_RX_OWN;
+	} else { /* PHY-less op, assume full-duplex */
 		control |= MAC_FULL_DUPLEX;
 	}
 
@@ -1685,57 +870,84 @@
 	return 0;
 }
 
-static void au1000_timer(unsigned long data)
+static void
+au1000_adjust_link(struct net_device *dev)
 {
-	struct net_device *dev = (struct net_device *)data;
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
-	unsigned char if_port;
-	u16 link, speed;
+	struct phy_device *phydev = aup->phy_dev;
+	unsigned long flags;
 
-	if (!dev) {
-		/* fatal error, don't restart the timer */
-		printk(KERN_ERR "au1000_timer error: NULL dev\n");
-		return;
+	int status_change = 0;
+
+	BUG_ON(!aup->phy_dev);
+
+	spin_lock_irqsave(&aup->lock, flags);
+
+	if (phydev->link && (aup->old_speed != phydev->speed)) {
+		// speed changed
+
+		switch(phydev->speed) {
+		case SPEED_10:
+		case SPEED_100:
+			break;
+		default:
+			printk(KERN_WARNING
+			       "%s: Speed (%d) is not 10/100 ???\n",
+			       dev->name, phydev->speed);
+			break;
+		}
+
+		aup->old_speed = phydev->speed;
+
+		status_change = 1;
 	}
 
-	if_port = dev->if_port;
-	if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) {
-		if (link) {
-			if (!netif_carrier_ok(dev)) {
-				netif_carrier_on(dev);
-				printk(KERN_INFO "%s: link up\n", dev->name);
-			}
-		}
-		else {
-			if (netif_carrier_ok(dev)) {
-				netif_carrier_off(dev);
-				dev->if_port = 0;
-				printk(KERN_INFO "%s: link down\n", dev->name);
-			}
-		}
-	}
+	if (phydev->link && (aup->old_duplex != phydev->duplex)) {
+		// duplex mode changed
 
-	if (link && (dev->if_port != if_port) && 
-			(dev->if_port != IF_PORT_UNKNOWN)) {
+		/* switching duplex mode requires to disable rx and tx! */
 		hard_stop(dev);
-		if (dev->if_port == IF_PORT_100BASEFX) {
-			printk(KERN_INFO "%s: going to full duplex\n", 
-					dev->name);
-			aup->mac->control |= MAC_FULL_DUPLEX;
-			au_sync_delay(1);
-		}
-		else {
-			aup->mac->control &= ~MAC_FULL_DUPLEX;
-			au_sync_delay(1);
-		}
+
+		if (DUPLEX_FULL == phydev->duplex)
+			aup->mac->control = ((aup->mac->control
+					     | MAC_FULL_DUPLEX)
+					     & ~MAC_DISABLE_RX_OWN);
+		else
+			aup->mac->control = ((aup->mac->control
+					      & ~MAC_FULL_DUPLEX)
+					     | MAC_DISABLE_RX_OWN);
+		au_sync_delay(1);
+
 		enable_rx_tx(dev);
+		aup->old_duplex = phydev->duplex;
+
+		status_change = 1;
 	}
 
-	aup->timer.expires = RUN_AT((1*HZ)); 
-	aup->timer.data = (unsigned long)dev;
-	aup->timer.function = &au1000_timer; /* timer handler */
-	add_timer(&aup->timer);
+	if(phydev->link != aup->old_link) {
+		// link state changed
 
+		if (phydev->link) // link went up
+			netif_schedule(dev);
+		else { // link went down
+			aup->old_speed = 0;
+			aup->old_duplex = -1;
+		}
+
+		aup->old_link = phydev->link;
+		status_change = 1;
+	}
+
+	spin_unlock_irqrestore(&aup->lock, flags);
+
+	if (status_change) {
+		if (phydev->link)
+			printk(KERN_INFO "%s: link up (%d/%s)\n",
+			       dev->name, phydev->speed,
+			       DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
+		else
+			printk(KERN_INFO "%s: link down\n", dev->name);
+	}
 }
 
 static int au1000_open(struct net_device *dev)
@@ -1746,25 +958,26 @@
 	if (au1000_debug > 4)
 		printk("%s: open: dev=%p\n", dev->name, dev);
 
+	if ((retval = request_irq(dev->irq, &au1000_interrupt, 0,
+					dev->name, dev))) {
+		printk(KERN_ERR "%s: unable to get IRQ %d\n",
+				dev->name, dev->irq);
+		return retval;
+	}
+
 	if ((retval = au1000_init(dev))) {
 		printk(KERN_ERR "%s: error in au1000_init\n", dev->name);
 		free_irq(dev->irq, dev);
 		return retval;
 	}
-	netif_start_queue(dev);
 
-	if ((retval = request_irq(dev->irq, &au1000_interrupt, 0, 
-					dev->name, dev))) {
-		printk(KERN_ERR "%s: unable to get IRQ %d\n", 
-				dev->name, dev->irq);
-		return retval;
+	if (aup->phy_dev) {
+		/* cause the PHY state machine to schedule a link state check */
+		aup->phy_dev->state = PHY_CHANGELINK;
+		phy_start(aup->phy_dev);
 	}
 
-	init_timer(&aup->timer); /* used in ioctl() */
-	aup->timer.expires = RUN_AT((3*HZ)); 
-	aup->timer.data = (unsigned long)dev;
-	aup->timer.function = &au1000_timer; /* timer handler */
-	add_timer(&aup->timer);
+	netif_start_queue(dev);
 
 	if (au1000_debug > 4)
 		printk("%s: open: Initialization done.\n", dev->name);
@@ -1774,16 +987,19 @@
 
 static int au1000_close(struct net_device *dev)
 {
-	u32 flags;
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	unsigned long flags;
+	struct au1000_private *const aup = (struct au1000_private *) dev->priv;
 
 	if (au1000_debug > 4)
 		printk("%s: close: dev=%p\n", dev->name, dev);
 
-	reset_mac(dev);
+	if (aup->phy_dev)
+		phy_stop(aup->phy_dev);
 
 	spin_lock_irqsave(&aup->lock, flags);
-	
+
+	reset_mac_unlocked (dev);
+
 	/* stop the device */
 	netif_stop_queue(dev);
 
@@ -1805,21 +1021,18 @@
 		if (dev) {
 			aup = (struct au1000_private *) dev->priv;
 			unregister_netdev(dev);
-			kfree(aup->mii);
-			for (j = 0; j < NUM_RX_DMA; j++) {
+			for (j = 0; j < NUM_RX_DMA; j++)
 				if (aup->rx_db_inuse[j])
 					ReleaseDB(aup, aup->rx_db_inuse[j]);
-			}
-			for (j = 0; j < NUM_TX_DMA; j++) {
+			for (j = 0; j < NUM_TX_DMA; j++)
 				if (aup->tx_db_inuse[j])
 					ReleaseDB(aup, aup->tx_db_inuse[j]);
-			}
-			dma_free_noncoherent(NULL,
-					MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
-					(void *)aup->vaddr,
-					aup->dma_addr);
+ 			dma_free_noncoherent(NULL, MAX_BUF_SIZE *
+ 					     (NUM_TX_BUFFS + NUM_RX_BUFFS),
+ 					     (void *)aup->vaddr, aup->dma_addr);
+ 			release_mem_region(dev->base_addr, MAC_IOSIZE);
+ 			release_mem_region(CPHYSADDR(iflist[i].macen_addr), 4);
 			free_netdev(dev);
-			release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE);
 		}
 	}
 }
@@ -1830,7 +1043,7 @@
 	struct net_device_stats *ps = &aup->stats;
 
 	if (status & TX_FRAME_ABORTED) {
-		if (dev->if_port == IF_PORT_100BASEFX) {
+		if (!aup->phy_dev || (DUPLEX_FULL == aup->phy_dev->duplex)) {
 			if (status & (TX_JAB_TIMEOUT | TX_UNDERRUN)) {
 				/* any other tx errors are only valid
 				 * in half duplex mode */
@@ -2104,126 +1317,15 @@
 	}
 }
 
-
 static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct au1000_private *aup = (struct au1000_private *)dev->priv;
-	u16 *data = (u16 *)&rq->ifr_ifru;
 
-	switch(cmd) { 
-		case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
-		case SIOCGMIIPHY:
-		        if (!netif_running(dev)) return -EINVAL;
-			data[0] = aup->phy_addr;
-		case SIOCDEVPRIVATE+1:	/* Read the specified MII register. */
-		case SIOCGMIIREG:
-			data[3] =  mdio_read(dev, data[0], data[1]); 
-			return 0;
-		case SIOCDEVPRIVATE+2:	/* Write the specified MII register */
-		case SIOCSMIIREG: 
-			if (!capable(CAP_NET_ADMIN))
-				return -EPERM;
-			mdio_write(dev, data[0], data[1],data[2]);
-			return 0;
-		default:
-			return -EOPNOTSUPP;
-	}
+	if (!netif_running(dev)) return -EINVAL;
 
-}
+	if (!aup->phy_dev) return -EINVAL; // PHY not controllable
 
-
-static int au1000_set_config(struct net_device *dev, struct ifmap *map)
-{
-	struct au1000_private *aup = (struct au1000_private *) dev->priv;
-	u16 control;
-
-	if (au1000_debug > 4)  {
-		printk("%s: set_config called: dev->if_port %d map->port %x\n", 
-				dev->name, dev->if_port, map->port);
-	}
-
-	switch(map->port){
-		case IF_PORT_UNKNOWN: /* use auto here */   
-			printk(KERN_INFO "%s: config phy for aneg\n", 
-					dev->name);
-			dev->if_port = map->port;
-			/* Link Down: the timer will bring it up */
-			netif_carrier_off(dev);
-	
-			/* read current control */
-			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-			control &= ~(MII_CNTL_FDX | MII_CNTL_F100);
-
-			/* enable auto negotiation and reset the negotiation */
-			mdio_write(dev, aup->phy_addr, MII_CONTROL, 
-					control | MII_CNTL_AUTO | 
-					MII_CNTL_RST_AUTO);
-
-			break;
-    
-		case IF_PORT_10BASET: /* 10BaseT */         
-			printk(KERN_INFO "%s: config phy for 10BaseT\n", 
-					dev->name);
-			dev->if_port = map->port;
-	
-			/* Link Down: the timer will bring it up */
-			netif_carrier_off(dev);
-
-			/* set Speed to 10Mbps, Half Duplex */
-			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-			control &= ~(MII_CNTL_F100 | MII_CNTL_AUTO | 
-					MII_CNTL_FDX);
-	
-			/* disable auto negotiation and force 10M/HD mode*/
-			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
-			break;
-    
-		case IF_PORT_100BASET: /* 100BaseT */
-		case IF_PORT_100BASETX: /* 100BaseTx */ 
-			printk(KERN_INFO "%s: config phy for 100BaseTX\n", 
-					dev->name);
-			dev->if_port = map->port;
-	
-			/* Link Down: the timer will bring it up */
-			netif_carrier_off(dev);
-	
-			/* set Speed to 100Mbps, Half Duplex */
-			/* disable auto negotiation and enable 100MBit Mode */
-			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-			control &= ~(MII_CNTL_AUTO | MII_CNTL_FDX);
-			control |= MII_CNTL_F100;
-			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
-			break;
-    
-		case IF_PORT_100BASEFX: /* 100BaseFx */
-			printk(KERN_INFO "%s: config phy for 100BaseFX\n", 
-					dev->name);
-			dev->if_port = map->port;
-	
-			/* Link Down: the timer will bring it up */
-			netif_carrier_off(dev);
-	
-			/* set Speed to 100Mbps, Full Duplex */
-			/* disable auto negotiation and enable 100MBit Mode */
-			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-			control &= ~MII_CNTL_AUTO;
-			control |=  MII_CNTL_F100 | MII_CNTL_FDX;
-			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
-			break;
-		case IF_PORT_10BASE2: /* 10Base2 */
-		case IF_PORT_AUI: /* AUI */
-		/* These Modes are not supported (are they?)*/
-			printk(KERN_ERR "%s: 10Base2/AUI not supported", 
-					dev->name);
-			return -EOPNOTSUPP;
-			break;
-    
-		default:
-			printk(KERN_ERR "%s: Invalid media selected", 
-					dev->name);
-			return -EINVAL;
-	}
-	return 0;
+	return phy_mii_ioctl(aup->phy_dev, if_mii(rq), cmd);
 }
 
 static struct net_device_stats *au1000_get_stats(struct net_device *dev)
diff --git a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
index 7f9326e..41c2f84 100644
--- a/drivers/net/au1000_eth.h
+++ b/drivers/net/au1000_eth.h
@@ -40,120 +40,6 @@
 
 #define MULTICAST_FILTER_LIMIT 64
 
-/* FIXME 
- * The PHY defines should be in a separate file.
- */
-
-/* MII register offsets */
-#define	MII_CONTROL 0x0000
-#define MII_STATUS  0x0001
-#define MII_PHY_ID0 0x0002
-#define	MII_PHY_ID1 0x0003
-#define MII_ANADV   0x0004
-#define MII_ANLPAR  0x0005
-#define MII_AEXP    0x0006
-#define MII_ANEXT   0x0007
-#define MII_LSI_PHY_CONFIG 0x0011
-/* Status register */
-#define MII_LSI_PHY_STAT   0x0012
-#define MII_AMD_PHY_STAT   MII_LSI_PHY_STAT
-#define MII_INTEL_PHY_STAT 0x0011
-
-#define MII_AUX_CNTRL  0x0018
-/* mii registers specific to AMD 79C901 */
-#define	MII_STATUS_SUMMARY = 0x0018
-
-/* MII Control register bit definitions. */
-#define	MII_CNTL_FDX      0x0100
-#define MII_CNTL_RST_AUTO 0x0200
-#define	MII_CNTL_ISOLATE  0x0400
-#define MII_CNTL_PWRDWN   0x0800
-#define	MII_CNTL_AUTO     0x1000
-#define MII_CNTL_F100     0x2000
-#define	MII_CNTL_LPBK     0x4000
-#define MII_CNTL_RESET    0x8000
-
-/* MII Status register bit  */
-#define	MII_STAT_EXT        0x0001 
-#define MII_STAT_JAB        0x0002
-#define	MII_STAT_LINK       0x0004
-#define MII_STAT_CAN_AUTO   0x0008
-#define	MII_STAT_FAULT      0x0010 
-#define MII_STAT_AUTO_DONE  0x0020
-#define	MII_STAT_CAN_T      0x0800
-#define MII_STAT_CAN_T_FDX  0x1000
-#define	MII_STAT_CAN_TX     0x2000 
-#define MII_STAT_CAN_TX_FDX 0x4000
-#define	MII_STAT_CAN_T4     0x8000
-
-
-#define		MII_ID1_OUI_LO		0xFC00	/* low bits of OUI mask */
-#define		MII_ID1_MODEL		0x03F0	/* model number */
-#define		MII_ID1_REV		0x000F	/* model number */
-
-/* MII NWAY Register Bits ...
-   valid for the ANAR (Auto-Negotiation Advertisement) and
-   ANLPAR (Auto-Negotiation Link Partner) registers */
-#define	MII_NWAY_NODE_SEL 0x001f
-#define MII_NWAY_CSMA_CD  0x0001
-#define	MII_NWAY_T	  0x0020
-#define MII_NWAY_T_FDX    0x0040
-#define	MII_NWAY_TX       0x0080
-#define MII_NWAY_TX_FDX   0x0100
-#define	MII_NWAY_T4       0x0200 
-#define MII_NWAY_PAUSE    0x0400 
-#define	MII_NWAY_RF       0x2000 /* Remote Fault */
-#define MII_NWAY_ACK      0x4000 /* Remote Acknowledge */
-#define	MII_NWAY_NP       0x8000 /* Next Page (Enable) */
-
-/* mii stsout register bits */
-#define	MII_STSOUT_LINK_FAIL 0x4000
-#define	MII_STSOUT_SPD       0x0080
-#define MII_STSOUT_DPLX      0x0040
-
-/* mii stsics register bits */
-#define	MII_STSICS_SPD       0x8000
-#define MII_STSICS_DPLX      0x4000
-#define	MII_STSICS_LINKSTS   0x0001
-
-/* mii stssum register bits */
-#define	MII_STSSUM_LINK  0x0008
-#define MII_STSSUM_DPLX  0x0004
-#define	MII_STSSUM_AUTO  0x0002
-#define MII_STSSUM_SPD   0x0001
-
-/* lsi phy status register */
-#define MII_LSI_PHY_STAT_FDX	0x0040
-#define MII_LSI_PHY_STAT_SPD	0x0080
-
-/* amd phy status register */
-#define MII_AMD_PHY_STAT_FDX	0x0800
-#define MII_AMD_PHY_STAT_SPD	0x0400
-
-/* intel phy status register */
-#define MII_INTEL_PHY_STAT_FDX	0x0200
-#define MII_INTEL_PHY_STAT_SPD	0x4000
-
-/* Auxilliary Control/Status Register */
-#define MII_AUX_FDX      0x0001
-#define MII_AUX_100      0x0002
-#define MII_AUX_F100     0x0004
-#define MII_AUX_ANEG     0x0008
-
-typedef struct mii_phy {
-	struct mii_phy * next;
-	struct mii_chip_info * chip_info;
-	u16 status;
-	u32 *mii_control_reg;
-	u32 *mii_data_reg;
-} mii_phy_t;
-
-struct phy_ops {
-	int (*phy_init) (struct net_device *, int);
-	int (*phy_reset) (struct net_device *, int);
-	int (*phy_status) (struct net_device *, int, u16 *, u16 *);
-};
-
 /* 
  * Data Buffer Descriptor. Data buffers must be aligned on 32 byte 
  * boundary for both, receive and transmit.
@@ -200,7 +86,6 @@
 
 
 struct au1000_private {
-	
 	db_dest_t *pDBfree;
 	db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
 	volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
@@ -213,8 +98,15 @@
 	u32 tx_full;
 
 	int mac_id;
-	mii_phy_t *mii;
-	struct phy_ops *phy_ops;
+
+	int mac_enabled;       /* whether MAC is currently enabled and running (req. for mdio) */
+
+	int old_link;          /* used by au1000_adjust_link */
+	int old_speed;
+	int old_duplex;
+
+	struct phy_device *phy_dev;
+	struct mii_bus mii_bus;
 	
 	/* These variables are just for quick access to certain regs addresses. */
 	volatile mac_reg_t *mac;  /* mac registers                      */   
@@ -223,14 +115,6 @@
 	u32 vaddr;                /* virtual address of rx/tx buffers   */
 	dma_addr_t dma_addr;      /* dma address of rx/tx buffers       */
 
-	u8 *hash_table;
-	u32 hash_mode;
-	u32 intr_work_done; /* number of Rx and Tx pkts processed in the isr */
-	int phy_addr;          /* phy address */
-	u32 options;           /* User-settable misc. driver options. */
-	u32 drv_flags;
-	int want_autoneg;
 	struct net_device_stats stats;
-	struct timer_list timer;
 	spinlock_t lock;       /* Serialise access to device */
 };
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index d8233e0..a7e4ba5 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -29,8 +29,8 @@
 
 #define DRV_MODULE_NAME		"b44"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.00"
-#define DRV_MODULE_RELDATE	"Apr 7, 2006"
+#define DRV_MODULE_VERSION	"1.01"
+#define DRV_MODULE_RELDATE	"Jun 16, 2006"
 
 #define B44_DEF_MSG_ENABLE	  \
 	(NETIF_MSG_DRV		| \
@@ -75,6 +75,15 @@
 /* minimum number of free TX descriptors required to wake up TX process */
 #define B44_TX_WAKEUP_THRESH		(B44_TX_RING_SIZE / 4)
 
+/* b44 internal pattern match filter info */
+#define B44_PATTERN_BASE	0x400
+#define B44_PATTERN_SIZE	0x80
+#define B44_PMASK_BASE		0x600
+#define B44_PMASK_SIZE		0x10
+#define B44_MAX_PATTERNS	16
+#define B44_ETHIPV6UDP_HLEN	62
+#define B44_ETHIPV4UDP_HLEN	42
+
 static char version[] __devinitdata =
 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
@@ -101,7 +110,7 @@
 
 static void b44_halt(struct b44 *);
 static void b44_init_rings(struct b44 *);
-static void b44_init_hw(struct b44 *);
+static void b44_init_hw(struct b44 *, int);
 
 static int dma_desc_align_mask;
 static int dma_desc_sync_size;
@@ -873,7 +882,7 @@
 		spin_lock_irq(&bp->lock);
 		b44_halt(bp);
 		b44_init_rings(bp);
-		b44_init_hw(bp);
+		b44_init_hw(bp, 1);
 		netif_wake_queue(bp->dev);
 		spin_unlock_irq(&bp->lock);
 		done = 1;
@@ -942,7 +951,7 @@
 
 	b44_halt(bp);
 	b44_init_rings(bp);
-	b44_init_hw(bp);
+	b44_init_hw(bp, 1);
 
 	spin_unlock_irq(&bp->lock);
 
@@ -1059,7 +1068,7 @@
 	b44_halt(bp);
 	dev->mtu = new_mtu;
 	b44_init_rings(bp);
-	b44_init_hw(bp);
+	b44_init_hw(bp, 1);
 	spin_unlock_irq(&bp->lock);
 
 	b44_enable_ints(bp);
@@ -1356,13 +1365,15 @@
  * packet processing.  Invoked with bp->lock held.
  */
 static void __b44_set_rx_mode(struct net_device *);
-static void b44_init_hw(struct b44 *bp)
+static void b44_init_hw(struct b44 *bp, int full_reset)
 {
 	u32 val;
 
 	b44_chip_reset(bp);
-	b44_phy_reset(bp);
-	b44_setup_phy(bp);
+	if (full_reset) {
+		b44_phy_reset(bp);
+		b44_setup_phy(bp);
+	}
 
 	/* Enable CRC32, set proper LED modes and power on PHY */
 	bw32(bp, B44_MAC_CTRL, MAC_CTRL_CRC32_ENAB | MAC_CTRL_PHY_LEDCTRL);
@@ -1376,16 +1387,21 @@
 	bw32(bp, B44_TXMAXLEN, bp->dev->mtu + ETH_HLEN + 8 + RX_HEADER_LEN);
 
 	bw32(bp, B44_TX_WMARK, 56); /* XXX magic */
-	bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
-	bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
-	bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
-			      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
-	bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
+	if (full_reset) {
+		bw32(bp, B44_DMATX_CTRL, DMATX_CTRL_ENABLE);
+		bw32(bp, B44_DMATX_ADDR, bp->tx_ring_dma + bp->dma_offset);
+		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+		bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset);
 
-	bw32(bp, B44_DMARX_PTR, bp->rx_pending);
-	bp->rx_prod = bp->rx_pending;
+		bw32(bp, B44_DMARX_PTR, bp->rx_pending);
+		bp->rx_prod = bp->rx_pending;
 
-	bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+		bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ);
+	} else {
+		bw32(bp, B44_DMARX_CTRL, (DMARX_CTRL_ENABLE |
+				      (bp->rx_offset << DMARX_CTRL_ROSHIFT)));
+	}
 
 	val = br32(bp, B44_ENET_CTRL);
 	bw32(bp, B44_ENET_CTRL, (val | ENET_CTRL_ENABLE));
@@ -1401,7 +1417,7 @@
 		goto out;
 
 	b44_init_rings(bp);
-	b44_init_hw(bp);
+	b44_init_hw(bp, 1);
 
 	b44_check_phy(bp);
 
@@ -1450,6 +1466,140 @@
 }
 #endif
 
+static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset)
+{
+	u32 i;
+	u32 *pattern = (u32 *) pp;
+
+	for (i = 0; i < bytes; i += sizeof(u32)) {
+		bw32(bp, B44_FILT_ADDR, table_offset + i);
+		bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]);
+	}
+}
+
+static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
+{
+	int magicsync = 6;
+	int k, j, len = offset;
+	int ethaddr_bytes = ETH_ALEN;
+
+	memset(ppattern + offset, 0xff, magicsync);
+	for (j = 0; j < magicsync; j++)
+		set_bit(len++, (unsigned long *) pmask);
+
+	for (j = 0; j < B44_MAX_PATTERNS; j++) {
+		if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
+			ethaddr_bytes = ETH_ALEN;
+		else
+			ethaddr_bytes = B44_PATTERN_SIZE - len;
+		if (ethaddr_bytes <=0)
+			break;
+		for (k = 0; k< ethaddr_bytes; k++) {
+			ppattern[offset + magicsync +
+				(j * ETH_ALEN) + k] = macaddr[k];
+			len++;
+			set_bit(len, (unsigned long *) pmask);
+		}
+	}
+	return len - 1;
+}
+
+/* Setup magic packet patterns in the b44 WOL
+ * pattern matching filter.
+ */
+static void b44_setup_pseudo_magicp(struct b44 *bp)
+{
+
+	u32 val;
+	int plen0, plen1, plen2;
+	u8 *pwol_pattern;
+	u8 pwol_mask[B44_PMASK_SIZE];
+
+	pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL);
+	if (!pwol_pattern) {
+		printk(KERN_ERR PFX "Memory not available for WOL\n");
+		return;
+	}
+
+	/* Ipv4 magic packet pattern - pattern 0.*/
+	memset(pwol_pattern, 0, B44_PATTERN_SIZE);
+	memset(pwol_mask, 0, B44_PMASK_SIZE);
+	plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
+				  B44_ETHIPV4UDP_HLEN);
+
+   	bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, B44_PATTERN_BASE);
+   	bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, B44_PMASK_BASE);
+
+	/* Raw ethernet II magic packet pattern - pattern 1 */
+	memset(pwol_pattern, 0, B44_PATTERN_SIZE);
+	memset(pwol_mask, 0, B44_PMASK_SIZE);
+	plen1 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
+				  ETH_HLEN);
+
+   	bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
+		       B44_PATTERN_BASE + B44_PATTERN_SIZE);
+  	bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
+		       B44_PMASK_BASE + B44_PMASK_SIZE);
+
+	/* Ipv6 magic packet pattern - pattern 2 */
+	memset(pwol_pattern, 0, B44_PATTERN_SIZE);
+	memset(pwol_mask, 0, B44_PMASK_SIZE);
+	plen2 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
+				  B44_ETHIPV6UDP_HLEN);
+
+   	bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
+		       B44_PATTERN_BASE + B44_PATTERN_SIZE + B44_PATTERN_SIZE);
+  	bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
+		       B44_PMASK_BASE + B44_PMASK_SIZE + B44_PMASK_SIZE);
+
+	kfree(pwol_pattern);
+
+	/* set these pattern's lengths: one less than each real length */
+	val = plen0 | (plen1 << 8) | (plen2 << 16) | WKUP_LEN_ENABLE_THREE;
+	bw32(bp, B44_WKUP_LEN, val);
+
+	/* enable wakeup pattern matching */
+	val = br32(bp, B44_DEVCTRL);
+	bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE);
+
+}
+
+static void b44_setup_wol(struct b44 *bp)
+{
+	u32 val;
+	u16 pmval;
+
+	bw32(bp, B44_RXCONFIG, RXCONFIG_ALLMULTI);
+
+	if (bp->flags & B44_FLAG_B0_ANDLATER) {
+
+		bw32(bp, B44_WKUP_LEN, WKUP_LEN_DISABLE);
+
+		val = bp->dev->dev_addr[2] << 24 |
+			bp->dev->dev_addr[3] << 16 |
+			bp->dev->dev_addr[4] << 8 |
+			bp->dev->dev_addr[5];
+		bw32(bp, B44_ADDR_LO, val);
+
+		val = bp->dev->dev_addr[0] << 8 |
+			bp->dev->dev_addr[1];
+		bw32(bp, B44_ADDR_HI, val);
+
+		val = br32(bp, B44_DEVCTRL);
+		bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE);
+
+ 	} else {
+ 		b44_setup_pseudo_magicp(bp);
+ 	}
+
+	val = br32(bp, B44_SBTMSLOW);
+	bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE);
+
+	pci_read_config_word(bp->pdev, SSB_PMCSR, &pmval);
+	pci_write_config_word(bp->pdev, SSB_PMCSR, pmval | SSB_PE);
+
+}
+
 static int b44_close(struct net_device *dev)
 {
 	struct b44 *bp = netdev_priv(dev);
@@ -1475,6 +1625,11 @@
 
 	netif_poll_enable(dev);
 
+	if (bp->flags & B44_FLAG_WOL_ENABLE) {
+		b44_init_hw(bp, 0);
+		b44_setup_wol(bp);
+	}
+
 	b44_free_consistent(bp);
 
 	return 0;
@@ -1620,8 +1775,6 @@
 {
 	struct b44 *bp = netdev_priv(dev);
 
-	if (!netif_running(dev))
-		return -EAGAIN;
 	cmd->supported = (SUPPORTED_Autoneg);
 	cmd->supported |= (SUPPORTED_100baseT_Half |
 			  SUPPORTED_100baseT_Full |
@@ -1649,6 +1802,12 @@
 		XCVR_INTERNAL : XCVR_EXTERNAL;
 	cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
 		AUTONEG_DISABLE : AUTONEG_ENABLE;
+	if (cmd->autoneg == AUTONEG_ENABLE)
+		cmd->advertising |= ADVERTISED_Autoneg;
+	if (!netif_running(dev)){
+		cmd->speed = 0;
+		cmd->duplex = 0xff;
+	}
 	cmd->maxtxpkt = 0;
 	cmd->maxrxpkt = 0;
 	return 0;
@@ -1658,9 +1817,6 @@
 {
 	struct b44 *bp = netdev_priv(dev);
 
-	if (!netif_running(dev))
-		return -EAGAIN;
-
 	/* We do not support gigabit. */
 	if (cmd->autoneg == AUTONEG_ENABLE) {
 		if (cmd->advertising &
@@ -1677,28 +1833,39 @@
 	spin_lock_irq(&bp->lock);
 
 	if (cmd->autoneg == AUTONEG_ENABLE) {
-		bp->flags &= ~B44_FLAG_FORCE_LINK;
-		bp->flags &= ~(B44_FLAG_ADV_10HALF |
+		bp->flags &= ~(B44_FLAG_FORCE_LINK |
+			       B44_FLAG_100_BASE_T |
+			       B44_FLAG_FULL_DUPLEX |
+			       B44_FLAG_ADV_10HALF |
 			       B44_FLAG_ADV_10FULL |
 			       B44_FLAG_ADV_100HALF |
 			       B44_FLAG_ADV_100FULL);
-		if (cmd->advertising & ADVERTISE_10HALF)
-			bp->flags |= B44_FLAG_ADV_10HALF;
-		if (cmd->advertising & ADVERTISE_10FULL)
-			bp->flags |= B44_FLAG_ADV_10FULL;
-		if (cmd->advertising & ADVERTISE_100HALF)
-			bp->flags |= B44_FLAG_ADV_100HALF;
-		if (cmd->advertising & ADVERTISE_100FULL)
-			bp->flags |= B44_FLAG_ADV_100FULL;
+		if (cmd->advertising == 0) {
+			bp->flags |= (B44_FLAG_ADV_10HALF |
+				      B44_FLAG_ADV_10FULL |
+				      B44_FLAG_ADV_100HALF |
+				      B44_FLAG_ADV_100FULL);
+		} else {
+			if (cmd->advertising & ADVERTISED_10baseT_Half)
+				bp->flags |= B44_FLAG_ADV_10HALF;
+			if (cmd->advertising & ADVERTISED_10baseT_Full)
+				bp->flags |= B44_FLAG_ADV_10FULL;
+			if (cmd->advertising & ADVERTISED_100baseT_Half)
+				bp->flags |= B44_FLAG_ADV_100HALF;
+			if (cmd->advertising & ADVERTISED_100baseT_Full)
+				bp->flags |= B44_FLAG_ADV_100FULL;
+		}
 	} else {
 		bp->flags |= B44_FLAG_FORCE_LINK;
+		bp->flags &= ~(B44_FLAG_100_BASE_T | B44_FLAG_FULL_DUPLEX);
 		if (cmd->speed == SPEED_100)
 			bp->flags |= B44_FLAG_100_BASE_T;
 		if (cmd->duplex == DUPLEX_FULL)
 			bp->flags |= B44_FLAG_FULL_DUPLEX;
 	}
 
-	b44_setup_phy(bp);
+	if (netif_running(dev))
+		b44_setup_phy(bp);
 
 	spin_unlock_irq(&bp->lock);
 
@@ -1734,7 +1901,7 @@
 
 	b44_halt(bp);
 	b44_init_rings(bp);
-	b44_init_hw(bp);
+	b44_init_hw(bp, 1);
 	netif_wake_queue(bp->dev);
 	spin_unlock_irq(&bp->lock);
 
@@ -1777,7 +1944,7 @@
 	if (bp->flags & B44_FLAG_PAUSE_AUTO) {
 		b44_halt(bp);
 		b44_init_rings(bp);
-		b44_init_hw(bp);
+		b44_init_hw(bp, 1);
 	} else {
 		__b44_set_flow_ctrl(bp, bp->flags);
 	}
@@ -1819,12 +1986,40 @@
 	spin_unlock_irq(&bp->lock);
 }
 
+static void b44_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct b44 *bp = netdev_priv(dev);
+
+	wol->supported = WAKE_MAGIC;
+	if (bp->flags & B44_FLAG_WOL_ENABLE)
+		wol->wolopts = WAKE_MAGIC;
+	else
+		wol->wolopts = 0;
+	memset(&wol->sopass, 0, sizeof(wol->sopass));
+}
+
+static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct b44 *bp = netdev_priv(dev);
+
+	spin_lock_irq(&bp->lock);
+	if (wol->wolopts & WAKE_MAGIC)
+		bp->flags |= B44_FLAG_WOL_ENABLE;
+	else
+		bp->flags &= ~B44_FLAG_WOL_ENABLE;
+	spin_unlock_irq(&bp->lock);
+
+	return 0;
+}
+
 static struct ethtool_ops b44_ethtool_ops = {
 	.get_drvinfo		= b44_get_drvinfo,
 	.get_settings		= b44_get_settings,
 	.set_settings		= b44_set_settings,
 	.nway_reset		= b44_nway_reset,
 	.get_link		= ethtool_op_get_link,
+	.get_wol		= b44_get_wol,
+	.set_wol		= b44_set_wol,
 	.get_ringparam		= b44_get_ringparam,
 	.set_ringparam		= b44_set_ringparam,
 	.get_pauseparam		= b44_get_pauseparam,
@@ -1903,6 +2098,10 @@
 	/* XXX - really required?
 	   bp->flags |= B44_FLAG_BUGGY_TXPTR;
          */
+
+ 	if (ssb_get_core_rev(bp) >= 7)
+ 		bp->flags |= B44_FLAG_B0_ANDLATER;
+
 out:
 	return err;
 }
@@ -2103,6 +2302,10 @@
 	spin_unlock_irq(&bp->lock);
 
 	free_irq(dev->irq, dev);
+	if (bp->flags & B44_FLAG_WOL_ENABLE) {
+		b44_init_hw(bp, 0);
+		b44_setup_wol(bp);
+	}
 	pci_disable_device(pdev);
 	return 0;
 }
@@ -2125,7 +2328,7 @@
 	spin_lock_irq(&bp->lock);
 
 	b44_init_rings(bp);
-	b44_init_hw(bp);
+	b44_init_hw(bp, 1);
 	netif_device_attach(bp->dev);
 	spin_unlock_irq(&bp->lock);
 
diff --git a/drivers/net/b44.h b/drivers/net/b44.h
index b178662..4944507 100644
--- a/drivers/net/b44.h
+++ b/drivers/net/b44.h
@@ -24,6 +24,9 @@
 #define  WKUP_LEN_P3_MASK	0x7f000000 /* Pattern 3 */
 #define  WKUP_LEN_P3_SHIFT	24
 #define  WKUP_LEN_D3		0x80000000
+#define  WKUP_LEN_DISABLE	0x80808080
+#define  WKUP_LEN_ENABLE_TWO	0x80800000
+#define  WKUP_LEN_ENABLE_THREE	0x80000000
 #define B44_ISTAT	0x0020UL /* Interrupt Status */
 #define  ISTAT_LS		0x00000020 /* Link Change (B0 only) */
 #define  ISTAT_PME		0x00000040 /* Power Management Event */
@@ -264,6 +267,8 @@
 #define  SBIDHIGH_VC_SHIFT	16
 
 /* SSB PCI config space registers.  */
+#define SSB_PMCSR		0x44
+#define  SSB_PE			0x100
 #define	SSB_BAR0_WIN		0x80
 #define	SSB_BAR1_WIN		0x84
 #define	SSB_SPROM_CONTROL	0x88
@@ -420,6 +425,7 @@
 
 	u32			dma_offset;
 	u32			flags;
+#define B44_FLAG_B0_ANDLATER	0x00000001
 #define B44_FLAG_BUGGY_TXPTR	0x00000002
 #define B44_FLAG_REORDER_BUG	0x00000004
 #define B44_FLAG_PAUSE_AUTO	0x00008000
@@ -435,6 +441,7 @@
 #define B44_FLAG_INTERNAL_PHY	0x10000000
 #define B44_FLAG_RX_RING_HACK	0x20000000
 #define B44_FLAG_TX_RING_HACK	0x40000000
+#define B44_FLAG_WOL_ENABLE	0x80000000
 
 	u32			rx_offset;
 
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 54161ae..7635736 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -32,6 +32,7 @@
 #include <asm/irq.h>
 #include <linux/delay.h>
 #include <asm/byteorder.h>
+#include <asm/page.h>
 #include <linux/time.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -49,14 +50,15 @@
 #include <linux/crc32.h>
 #include <linux/prefetch.h>
 #include <linux/cache.h>
+#include <linux/zlib.h>
 
 #include "bnx2.h"
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME		"bnx2"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"1.4.40"
-#define DRV_MODULE_RELDATE	"May 22, 2006"
+#define DRV_MODULE_VERSION	"1.4.42"
+#define DRV_MODULE_RELDATE	"June 12, 2006"
 
 #define RUN_AT(x) (jiffies + (x))
 
@@ -1638,7 +1640,7 @@
 		skb = tx_buf->skb;
 #ifdef BCM_TSO 
 		/* partial BD completions possible with TSO packets */
-		if (skb_shinfo(skb)->tso_size) {
+		if (skb_shinfo(skb)->gso_size) {
 			u16 last_idx, last_ring_idx;
 
 			last_idx = sw_cons +
@@ -1820,7 +1822,7 @@
 		skb->protocol = eth_type_trans(skb, bp->dev);
 
 		if ((len > (bp->dev->mtu + ETH_HLEN)) &&
-			(htons(skb->protocol) != 0x8100)) {
+			(ntohs(skb->protocol) != 0x8100)) {
 
 			dev_kfree_skb_irq(skb);
 			goto next_rx;
@@ -2009,7 +2011,7 @@
 	return 1;
 }
 
-/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
+/* Called with rtnl_lock from vlan functions and also netif_tx_lock
  * from set_multicast.
  */
 static void
@@ -2083,6 +2085,92 @@
 	spin_unlock_bh(&bp->phy_lock);
 }
 
+#define FW_BUF_SIZE	0x8000
+
+static int
+bnx2_gunzip_init(struct bnx2 *bp)
+{
+	if ((bp->gunzip_buf = vmalloc(FW_BUF_SIZE)) == NULL)
+		goto gunzip_nomem1;
+
+	if ((bp->strm = kmalloc(sizeof(*bp->strm), GFP_KERNEL)) == NULL)
+		goto gunzip_nomem2;
+
+	bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
+	if (bp->strm->workspace == NULL)
+		goto gunzip_nomem3;
+
+	return 0;
+
+gunzip_nomem3:
+	kfree(bp->strm);
+	bp->strm = NULL;
+
+gunzip_nomem2:
+	vfree(bp->gunzip_buf);
+	bp->gunzip_buf = NULL;
+
+gunzip_nomem1:
+	printk(KERN_ERR PFX "%s: Cannot allocate firmware buffer for "
+			    "uncompression.\n", bp->dev->name);
+	return -ENOMEM;
+}
+
+static void
+bnx2_gunzip_end(struct bnx2 *bp)
+{
+	kfree(bp->strm->workspace);
+
+	kfree(bp->strm);
+	bp->strm = NULL;
+
+	if (bp->gunzip_buf) {
+		vfree(bp->gunzip_buf);
+		bp->gunzip_buf = NULL;
+	}
+}
+
+static int
+bnx2_gunzip(struct bnx2 *bp, u8 *zbuf, int len, void **outbuf, int *outlen)
+{
+	int n, rc;
+
+	/* check gzip header */
+	if ((zbuf[0] != 0x1f) || (zbuf[1] != 0x8b) || (zbuf[2] != Z_DEFLATED))
+		return -EINVAL;
+
+	n = 10;
+
+#define FNAME	0x8
+	if (zbuf[3] & FNAME)
+		while ((zbuf[n++] != 0) && (n < len));
+
+	bp->strm->next_in = zbuf + n;
+	bp->strm->avail_in = len - n;
+	bp->strm->next_out = bp->gunzip_buf;
+	bp->strm->avail_out = FW_BUF_SIZE;
+
+	rc = zlib_inflateInit2(bp->strm, -MAX_WBITS);
+	if (rc != Z_OK)
+		return rc;
+
+	rc = zlib_inflate(bp->strm, Z_FINISH);
+
+	*outlen = FW_BUF_SIZE - bp->strm->avail_out;
+	*outbuf = bp->gunzip_buf;
+
+	if ((rc != Z_OK) && (rc != Z_STREAM_END))
+		printk(KERN_ERR PFX "%s: Firmware decompression error: %s\n",
+		       bp->dev->name, bp->strm->msg);
+
+	zlib_inflateEnd(bp->strm);
+
+	if (rc == Z_STREAM_END)
+		return 0;
+
+	return rc;
+}
+
 static void
 load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
 	u32 rv2p_proc)
@@ -2092,9 +2180,9 @@
 
 
 	for (i = 0; i < rv2p_code_len; i += 8) {
-		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code);
+		REG_WR(bp, BNX2_RV2P_INSTR_HIGH, cpu_to_le32(*rv2p_code));
 		rv2p_code++;
-		REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code);
+		REG_WR(bp, BNX2_RV2P_INSTR_LOW, cpu_to_le32(*rv2p_code));
 		rv2p_code++;
 
 		if (rv2p_proc == RV2P_PROC1) {
@@ -2134,7 +2222,7 @@
 		int j;
 
 		for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
-			REG_WR_IND(bp, offset, fw->text[j]);
+			REG_WR_IND(bp, offset, cpu_to_le32(fw->text[j]));
 	        }
 	}
 
@@ -2190,15 +2278,32 @@
 	REG_WR_IND(bp, cpu_reg->mode, val);
 }
 
-static void
+static int
 bnx2_init_cpus(struct bnx2 *bp)
 {
 	struct cpu_reg cpu_reg;
 	struct fw_info fw;
+	int rc = 0;
+	void *text;
+	u32 text_len;
+
+	if ((rc = bnx2_gunzip_init(bp)) != 0)
+		return rc;
 
 	/* Initialize the RV2P processor. */
-	load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1);
-	load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2);
+	rc = bnx2_gunzip(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), &text,
+			 &text_len);
+	if (rc)
+		goto init_cpu_err;
+
+	load_rv2p_fw(bp, text, text_len, RV2P_PROC1);
+
+	rc = bnx2_gunzip(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), &text,
+			 &text_len);
+	if (rc)
+		goto init_cpu_err;
+
+	load_rv2p_fw(bp, text, text_len, RV2P_PROC2);
 
 	/* Initialize the RX Processor. */
 	cpu_reg.mode = BNX2_RXP_CPU_MODE;
@@ -2222,7 +2327,13 @@
 	fw.text_addr = bnx2_RXP_b06FwTextAddr;
 	fw.text_len = bnx2_RXP_b06FwTextLen;
 	fw.text_index = 0;
-	fw.text = bnx2_RXP_b06FwText;
+
+	rc = bnx2_gunzip(bp, bnx2_RXP_b06FwText, sizeof(bnx2_RXP_b06FwText),
+			 &text, &text_len);
+	if (rc)
+		goto init_cpu_err;
+
+	fw.text = text;
 
 	fw.data_addr = bnx2_RXP_b06FwDataAddr;
 	fw.data_len = bnx2_RXP_b06FwDataLen;
@@ -2268,7 +2379,13 @@
 	fw.text_addr = bnx2_TXP_b06FwTextAddr;
 	fw.text_len = bnx2_TXP_b06FwTextLen;
 	fw.text_index = 0;
-	fw.text = bnx2_TXP_b06FwText;
+
+	rc = bnx2_gunzip(bp, bnx2_TXP_b06FwText, sizeof(bnx2_TXP_b06FwText),
+			 &text, &text_len);
+	if (rc)
+		goto init_cpu_err;
+
+	fw.text = text;
 
 	fw.data_addr = bnx2_TXP_b06FwDataAddr;
 	fw.data_len = bnx2_TXP_b06FwDataLen;
@@ -2314,7 +2431,13 @@
 	fw.text_addr = bnx2_TPAT_b06FwTextAddr;
 	fw.text_len = bnx2_TPAT_b06FwTextLen;
 	fw.text_index = 0;
-	fw.text = bnx2_TPAT_b06FwText;
+
+	rc = bnx2_gunzip(bp, bnx2_TPAT_b06FwText, sizeof(bnx2_TPAT_b06FwText),
+			 &text, &text_len);
+	if (rc)
+		goto init_cpu_err;
+
+	fw.text = text;
 
 	fw.data_addr = bnx2_TPAT_b06FwDataAddr;
 	fw.data_len = bnx2_TPAT_b06FwDataLen;
@@ -2360,7 +2483,13 @@
 	fw.text_addr = bnx2_COM_b06FwTextAddr;
 	fw.text_len = bnx2_COM_b06FwTextLen;
 	fw.text_index = 0;
-	fw.text = bnx2_COM_b06FwText;
+
+	rc = bnx2_gunzip(bp, bnx2_COM_b06FwText, sizeof(bnx2_COM_b06FwText),
+			 &text, &text_len);
+	if (rc)
+		goto init_cpu_err;
+
+	fw.text = text;
 
 	fw.data_addr = bnx2_COM_b06FwDataAddr;
 	fw.data_len = bnx2_COM_b06FwDataLen;
@@ -2384,6 +2513,9 @@
 
 	load_cpu_fw(bp, &cpu_reg, &fw);
 
+init_cpu_err:
+	bnx2_gunzip_end(bp);
+	return rc;
 }
 
 static int
@@ -3256,7 +3388,9 @@
 	 * context block must have already been enabled. */
 	bnx2_init_context(bp);
 
-	bnx2_init_cpus(bp);
+	if ((rc = bnx2_init_cpus(bp)) != 0)
+		return rc;
+
 	bnx2_init_nvram(bp);
 
 	bnx2_set_mac_addr(bp);
@@ -3556,7 +3690,9 @@
 	if (rc)
 		return rc;
 
-	bnx2_init_chip(bp);
+	if ((rc = bnx2_init_chip(bp)) != 0)
+		return rc;
+
 	bnx2_init_tx_ring(bp);
 	bnx2_init_rx_ring(bp);
 	return 0;
@@ -4034,6 +4170,8 @@
 	msg = (u32) ++bp->fw_drv_pulse_wr_seq;
 	REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg);
 
+	bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT);
+
 	if ((bp->phy_flags & PHY_SERDES_FLAG) &&
 	    (CHIP_NUM(bp) == CHIP_NUM_5706)) {
 
@@ -4252,7 +4390,7 @@
 }
 #endif
 
-/* Called with dev->xmit_lock.
+/* Called with netif_tx_lock.
  * hard_start_xmit is pseudo-lockless - a lock is only required when
  * the tx queue is full. This way, we get the benefit of lockless
  * operations most of the time without the complexities to handle
@@ -4290,7 +4428,7 @@
 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
 	}
 #ifdef BCM_TSO 
-	if ((mss = skb_shinfo(skb)->tso_size) &&
+	if ((mss = skb_shinfo(skb)->gso_size) &&
 		(skb->len > (bp->dev->mtu + ETH_HLEN))) {
 		u32 tcp_opt_len, ip_tcp_len;
 
@@ -4310,7 +4448,7 @@
 		ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr);
 
 		skb->nh.iph->check = 0;
-		skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
+		skb->nh.iph->tot_len = htons(mss + ip_tcp_len + tcp_opt_len);
 		skb->h.th->check =
 			~csum_tcpudp_magic(skb->nh.iph->saddr,
 					    skb->nh.iph->daddr,
@@ -4504,6 +4642,10 @@
 		net_stats->tx_aborted_errors +
 		net_stats->tx_carrier_errors;
 
+	net_stats->rx_missed_errors =
+		(unsigned long) (stats_blk->stat_IfInMBUFDiscards +
+		stats_blk->stat_FwRxDrop);
+
 	return net_stats;
 }
 
@@ -4986,7 +5128,7 @@
 	return 0;
 }
 
-#define BNX2_NUM_STATS 45
+#define BNX2_NUM_STATS 46
 
 static struct {
 	char string[ETH_GSTRING_LEN];
@@ -5036,6 +5178,7 @@
 	{ "rx_mac_ctrl_frames" },
 	{ "rx_filtered_packets" },
 	{ "rx_discards" },
+	{ "rx_fw_discards" },
 };
 
 #define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
@@ -5086,6 +5229,7 @@
     STATS_OFFSET32(stat_MacControlFramesReceived),                    
     STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),                  
     STATS_OFFSET32(stat_IfInMBUFDiscards),                            
+    STATS_OFFSET32(stat_FwRxDrop),
 };
 
 /* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
@@ -5096,7 +5240,7 @@
 	4,0,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,
+	4,4,4,4,4,4,
 };
 
 static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = {
@@ -5104,7 +5248,7 @@
 	4,4,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
 	4,4,4,4,4,4,4,4,4,4,
-	4,4,4,4,4,
+	4,4,4,4,4,4,
 };
 
 #define BNX2_NUM_TESTS 6
@@ -5634,7 +5778,9 @@
 		}
 	}
 
-	if (CHIP_NUM(bp) == CHIP_NUM_5708)
+	if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
+	    (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
+	    (CHIP_ID(bp) == CHIP_ID_5708_B1))
 		bp->flags |= NO_WOL_FLAG;
 
 	if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index b87925f6..5845e33 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -231,6 +231,7 @@
 	u32 stat_GenStat13;
 	u32 stat_GenStat14;
 	u32 stat_GenStat15;
+	u32 stat_FwRxDrop;
 };
 
 
@@ -3481,6 +3482,8 @@
 
 #define BNX2_COM_SCRATCH				0x00120000
 
+#define BNX2_FW_RX_DROP_COUNT				 0x00120084
+
 
 /*
  *  cp_reg definition
@@ -3747,7 +3750,12 @@
 #define DMA_READ_CHANS	5
 #define DMA_WRITE_CHANS	3
 
-#define BCM_PAGE_BITS	12
+/* Use CPU native page size up to 16K for the ring sizes.  */
+#if (PAGE_SHIFT > 14)
+#define BCM_PAGE_BITS	14
+#else
+#define BCM_PAGE_BITS	PAGE_SHIFT
+#endif
 #define BCM_PAGE_SIZE	(1 << BCM_PAGE_BITS)
 
 #define TX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct tx_bd))
@@ -3770,7 +3778,7 @@
 
 #define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
 
-#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> 8)
+#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
 #define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
 
 /* Context size. */
@@ -4048,6 +4056,9 @@
 	u32			flash_size;
 
 	int			status_stats_size;
+
+	struct z_stream_s	*strm;
+	void			*gunzip_buf;
 };
 
 static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h
index 8158974..2d753dc 100644
--- a/drivers/net/bnx2_fw.h
+++ b/drivers/net/bnx2_fw.h
@@ -7,7 +7,7 @@
  * the Free Software Foundation, except as noted below.
  *
  * This file contains firmware data derived from proprietary unpublished
- * source code, Copyright (c) 2004, 2005 Broadcom Corporation.
+ * source code, Copyright (c) 2004, 2005, 2006 Broadcom Corporation.
  *
  * Permission is hereby granted for the distribution of this firmware data
  * in hexadecimal or equivalent format, provided this copyright notice is
@@ -28,943 +28,641 @@
 static const int bnx2_COM_b06FwBssLen = 0x88;
 static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840;
 static const int bnx2_COM_b06FwSbssLen = 0x1c;
-static u32 bnx2_COM_b06FwText[(0x57bc/4) + 1] = {
-	0x0a00022d, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x322e352e,
-	0x38000000, 0x02050802, 0x00000000, 0x00000003, 0x00000014, 0x00000032,
-	0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000010, 0x000003e8, 0x0000ea60, 0x00000001, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000002, 0x00000020, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24425840,
-	0x3c030800, 0x246358e8, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004,
-	0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261008b4, 0x3c1c0800,
-	0x279c5840, 0x0e0002f7, 0x00000000, 0x0000000d, 0x27bdffe8, 0x3c1a8000,
-	0x3c020008, 0x0342d825, 0x3c036010, 0xafbf0010, 0x8c655000, 0x3c020800,
-	0x24470f30, 0x3c040800, 0x24865860, 0x2402ff7f, 0x00a22824, 0x34a5380c,
-	0xac655000, 0x00002821, 0x24020037, 0x24030c80, 0xaf420008, 0xaf430024,
-	0xacc70000, 0x24a50001, 0x2ca20016, 0x1440fffc, 0x24c60004, 0x24845860,
-	0x3c020800, 0x24420f3c, 0x3c030800, 0x24630e2c, 0xac820004, 0x3c020800,
-	0x24420a2c, 0x3c050800, 0x24a51268, 0xac82000c, 0x3c020800, 0x244243dc,
-	0xac830008, 0x3c030800, 0x24633698, 0xac820014, 0x3c020800, 0x24423c24,
-	0xac830018, 0xac83001c, 0x3c030800, 0x24630f44, 0xac820024, 0x3c020800,
-	0x244243ac, 0xac83002c, 0x3c030800, 0x246343cc, 0xac820030, 0x3c020800,
-	0x244242f0, 0xac830034, 0x3c030800, 0x24633d78, 0xac82003c, 0x3c020800,
-	0x24420fd4, 0xac850010, 0xac850020, 0xac830040, 0x0e0010b7, 0xac820050,
-	0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafb00010, 0x27500100,
-	0xafbf0018, 0xafb10014, 0x9203000b, 0x24020003, 0x1462005b, 0x96110008,
-	0x32220001, 0x10400009, 0x27430080, 0x8e020000, 0x96040014, 0x000211c2,
-	0x00021040, 0x00621821, 0xa4640000, 0x0a0002d0, 0x3c020800, 0x3c020800,
-	0x8c430020, 0x1060002a, 0x3c030800, 0x0e00148e, 0x00000000, 0x97420108,
-	0x8f850018, 0x9743010c, 0x3042003e, 0x00021400, 0x00621825, 0xaca30000,
-	0x8f840018, 0x8f420100, 0xac820004, 0x97430116, 0x9742010e, 0x8f840018,
-	0x00031c00, 0x00431025, 0xac820008, 0x97430110, 0x97440112, 0x8f850018,
-	0x00031c00, 0x00832025, 0xaca4000c, 0x97420114, 0x8f840018, 0x3042ffff,
-	0xac820010, 0x8f830018, 0xac600014, 0x8f820018, 0x3c030800, 0xac400018,
-	0x946258ce, 0x8f840018, 0x3c032000, 0x00431025, 0xac82001c, 0x0e0014cc,
-	0x24040001, 0x3c030800, 0x8c620040, 0x24420001, 0xac620040, 0x3c020800,
-	0x8c430044, 0x32240004, 0x24630001, 0x10800017, 0xac430044, 0x8f4202b8,
-	0x04430007, 0x8e020020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001,
-	0x0a0002f2, 0xac830060, 0x3c060800, 0x8cc4005c, 0xaf420280, 0x96030016,
-	0x00001021, 0xa7430284, 0x8e050004, 0x24840001, 0x3c031000, 0xaf450288,
-	0xaf4302b8, 0x0a0002f2, 0xacc4005c, 0x32220002, 0x0a0002f2, 0x0002102b,
-	0x3c026000, 0xac400808, 0x0000000d, 0x00001021, 0x8fbf0018, 0x8fb10014,
-	0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffc8, 0xafbf0034, 0xafbe0030,
-	0xafb7002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c, 0xafb20018,
-	0xafb10014, 0x0e000244, 0xafb00010, 0x3c170800, 0x3c160800, 0x24110020,
-	0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800, 0x8f820004,
-	0x3c040800, 0x8c830020, 0x10430005, 0x8ee200a4, 0xaf830004, 0x0e001593,
-	0x00000000, 0x8ee200a4, 0x8ec300a0, 0x10430004, 0x26c400a0, 0x94820002,
-	0xa742009e, 0xaee300a4, 0x8f500000, 0x32020007, 0x1040ffee, 0x32020001,
-	0x1040002c, 0x32020002, 0x8f420100, 0xaf420020, 0x8f430104, 0xaf4300a8,
-	0x9342010b, 0x93630000, 0x306300ff, 0x10710005, 0x304400ff, 0x10750006,
-	0x2c820016, 0x0a000333, 0x00000000, 0xaf940000, 0x0a000334, 0x2c820016,
-	0xaf930000, 0x0a000334, 0x00000000, 0xaf800000, 0x14400005, 0x00041880,
-	0x0e0003cc, 0x00000000, 0x0a000340, 0x00000000, 0x3c020800, 0x24425860,
-	0x00621821, 0x8c620000, 0x0040f809, 0x00000000, 0x10400005, 0x3c030800,
-	0x8f420104, 0x3c016020, 0xac220014, 0x3c030800, 0x8c620034, 0xaf520138,
-	0x24420001, 0xac620034, 0x32020002, 0x1040001a, 0x32020004, 0x8f420140,
-	0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000, 0x10750006,
-	0x00000000, 0x0a00035d, 0x00000000, 0xaf940000, 0x0a00035e, 0x00000000,
-	0xaf930000, 0x0a00035e, 0x00000000, 0xaf800000, 0x0e000c7b, 0x00000000,
-	0x3c040800, 0x8c820038, 0xaf520178, 0x24420001, 0xac820038, 0x32020004,
-	0x1040ffa4, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff,
-	0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a000378, 0x00000000,
-	0xaf940000, 0x0a000379, 0x00000000, 0xaf930000, 0x0a000379, 0x00000000,
-	0xaf800000, 0x8f430180, 0x24020f00, 0x14620005, 0x00000000, 0x8f420188,
-	0xa742009c, 0x0a000387, 0x8fc2003c, 0x93620000, 0x14510004, 0x8fc2003c,
-	0x0e000bad, 0x00000000, 0x8fc2003c, 0xaf5201b8, 0x24420001, 0x0a00030b,
-	0xafc2003c, 0x27bdffe8, 0xafbf0010, 0x97420108, 0x24033000, 0x30447000,
-	0x10830016, 0x28823001, 0x10400007, 0x24024000, 0x1080000b, 0x24022000,
-	0x1082000c, 0x00000000, 0x0a0003b3, 0x00000000, 0x10820010, 0x24025000,
-	0x10820012, 0x00000000, 0x0a0003b3, 0x00000000, 0x0000000d, 0x0a0003b5,
-	0x00001021, 0x0e000442, 0x00000000, 0x0a0003b6, 0x8fbf0010, 0x0e00041a,
-	0x00000000, 0x0a0003b5, 0x00001021, 0x0e000669, 0x00000000, 0x0a0003b5,
-	0x00001021, 0x0e001467, 0x00000000, 0x0a0003b5, 0x00001021, 0x0000000d,
-	0x00001021, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x93620000, 0x24030020,
-	0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0003c9,
-	0x00000000, 0x2782000c, 0xaf820000, 0x03e00008, 0x00000000, 0x27820008,
-	0xaf820000, 0x03e00008, 0x00000000, 0xaf800000, 0x03e00008, 0x00000000,
-	0x0000000d, 0x03e00008, 0x00001021, 0x03e00008, 0x00001021, 0x27440100,
-	0x94830008, 0x30620004, 0x10400017, 0x30620002, 0x8f4202b8, 0x04430007,
-	0x8c820020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, 0x03e00008,
-	0xac830060, 0xaf420280, 0x94830016, 0x3c060800, 0xa7430284, 0x8c850004,
-	0x8cc4005c, 0x00001021, 0x3c031000, 0x24840001, 0xaf450288, 0xaf4302b8,
-	0x03e00008, 0xacc4005c, 0x14400003, 0x3c040800, 0x03e00008, 0x00001021,
-	0x8c830084, 0x24020001, 0x24630001, 0x03e00008, 0xac830084, 0x27450100,
-	0x3c040800, 0x8c820088, 0x94a3000c, 0x24420001, 0x007a1821, 0xac820088,
-	0x8ca40018, 0x90664000, 0xaf440038, 0x8ca2001c, 0x2403fff8, 0x00063600,
-	0x00431024, 0x34420004, 0x3c030005, 0xaf42003c, 0xaf430030, 0x00000000,
-	0x00000000, 0x00000000, 0xaf460404, 0x00000000, 0x00000000, 0x00000000,
-	0x3c020006, 0x34420001, 0xaf420030, 0x00000000, 0x00000000, 0x00000000,
-	0x8f420000, 0x30420010, 0x1040fffd, 0x00001021, 0x03e00008, 0x00000000,
-	0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x1060001e,
-	0xafbf0014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000,
-	0x8f840018, 0x9602000c, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018,
-	0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018,
-	0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce,
-	0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c,
-	0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010,
-	0x27500100, 0xafbf0014, 0x92020009, 0x14400003, 0x3c020800, 0x0a00046c,
-	0x24020001, 0x8c430020, 0x1060001f, 0x00001021, 0x0e00148e, 0x00000000,
-	0x8f830018, 0x8e020018, 0xac620000, 0x8f840018, 0x9602000c, 0xac820004,
-	0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-	0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448, 0xac830018,
-	0x96020008, 0x3c030800, 0x946458ce, 0x8f850018, 0x00021400, 0x00441025,
-	0x24040001, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf0014, 0x8fb00010,
-	0x03e00008, 0x27bd0018, 0x3c0b0800, 0x8d6808b0, 0x3c070800, 0x24e700b0,
-	0x00084900, 0x01271821, 0xac640000, 0x93620005, 0x97660008, 0x00e95021,
-	0x93630023, 0x9364003f, 0x25080001, 0x00021600, 0x00063400, 0x00461025,
-	0x00031a00, 0x00431025, 0x00822025, 0xad440004, 0x9362007e, 0x9366007f,
-	0x8f630178, 0x9364007a, 0x00021600, 0x00063400, 0x00461025, 0x00031a00,
-	0x00431025, 0x00822025, 0xad440008, 0x93620080, 0x9363007d, 0x3108007f,
-	0x01403821, 0xad6808b0, 0x00021600, 0x00031c00, 0x00431025, 0x00451025,
-	0x03e00008, 0xace2000c, 0x27bdffb8, 0xafb3002c, 0x00009821, 0xafbe0040,
-	0x0000f021, 0xafb50034, 0x27550100, 0xafbf0044, 0xafb7003c, 0xafb60038,
-	0xafb40030, 0xafb20028, 0xafb10024, 0xafb00020, 0xafa00010, 0xafa00014,
-	0x96a20008, 0x8f540100, 0x8eb10018, 0x30420001, 0x10400037, 0x02a0b821,
-	0x8f630054, 0x2622ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d,
-	0x00000000, 0x2400015c, 0x0a0004e5, 0x00002021, 0x8f62004c, 0x02221023,
-	0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c,
-	0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c,
-	0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001,
-	0x00021023, 0x30420005, 0x0a0004e5, 0x34440004, 0x27660100, 0x00041080,
-	0x00c21021, 0x8c430000, 0x02231823, 0x04600004, 0x24820001, 0x30440007,
-	0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094,
-	0x24040005, 0x24420001, 0x0a0004e5, 0xac620094, 0x24040004, 0x00809821,
-	0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010, 0x2c420001,
-	0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001, 0x38820014,
-	0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012, 0x14820002,
-	0x00001021, 0x24020001, 0x10400009, 0x00000000, 0x8ea20020, 0x8f630040,
-	0x0040b021, 0x00431023, 0x5c400010, 0x8f760040, 0x0a000511, 0x00000000,
-	0x9343010b, 0x24020004, 0x1462000a, 0x8eb60020, 0x8f630040, 0x3c021000,
-	0x00761823, 0x0043102a, 0x10400004, 0x00000000, 0x0000000d, 0x00000000,
-	0x240002fa, 0x9343010b, 0x24020004, 0x5462000b, 0x96a20008, 0x24020001,
-	0xafa20010, 0x96a20008, 0x24030001, 0xafa30018, 0x8eb2001c, 0x36730002,
-	0x30420020, 0x0a000526, 0xafa20014, 0x36730080, 0x30420002, 0x10400003,
-	0xafa00018, 0x0a000526, 0x8eb2001c, 0x8eb20014, 0x2402fffb, 0x02628024,
-	0x1200002a, 0x3c030800, 0x8c620030, 0x02021024, 0x10400026, 0x3c020800,
-	0x8c430020, 0x10600024, 0x32620004, 0x0e00148e, 0x00000000, 0x8f830018,
-	0x8f420100, 0xac620000, 0x8f840018, 0x02401821, 0x32620002, 0xac900004,
-	0x8f840018, 0x54400001, 0x02c01821, 0xac830008, 0x8f830018, 0x8ee20020,
-	0xac62000c, 0x8f840018, 0x8f620040, 0xac820010, 0x8f830018, 0x8ee20018,
-	0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
-	0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc,
-	0xaca3001c, 0x32620004, 0x10400063, 0x00003821, 0x3c029000, 0x34420001,
-	0x3c038000, 0x02821025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024,
-	0x1440fffd, 0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000,
-	0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821,
-	0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023,
-	0xaf710064, 0x3c023fff, 0x0a000580, 0x3442ffff, 0x8f62005c, 0x02221023,
-	0x04400011, 0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff,
-	0x3442ffff, 0xaf710064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004,
-	0x02251021, 0x3c053fff, 0x34a5ffff, 0x02251021, 0xaf62005c, 0x24070001,
-	0xaf71004c, 0x8f620054, 0x16220005, 0x00000000, 0x93620023, 0x30420040,
-	0x10400017, 0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001,
-	0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804,
-	0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b,
-	0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021,
-	0xaf62000c, 0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000,
-	0x34420001, 0x02821025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004,
-	0x00000000, 0x0e0013c4, 0x00000000, 0x00403821, 0x54e00001, 0x241e0001,
-	0x8f700040, 0x8f620040, 0x14520003, 0x00521023, 0x0a0005bf, 0x00001021,
-	0x28420001, 0x10400041, 0x8fa20010, 0x0e000fae, 0x02402021, 0xaf720040,
-	0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022, 0x24420001,
-	0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b, 0x14600027,
-	0x3c020800, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000,
-	0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
-	0x34420001, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020,
-	0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050273, 0x0a0005f2,
-	0x24050001, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
-	0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x24050001, 0x24020001, 0xa7620012,
-	0xa3600022, 0x0a0005fe, 0x2ca20001, 0x9743007a, 0x9444002a, 0x00002821,
-	0x00641821, 0x3063fffe, 0xa7630012, 0x2ca20001, 0x00021023, 0x03c2f024,
-	0x8fa20010, 0x10400004, 0x8fa30014, 0x0e0013c1, 0x00000000, 0x8fa30014,
-	0x10600003, 0x00000000, 0x0e0010eb, 0x00000000, 0x13c0001f, 0x3c029000,
-	0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-	0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074,
-	0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000, 0x02802021,
-	0x0e000470, 0x2405036c, 0x0a00062b, 0x8fa20018, 0x8f4201f8, 0x00431024,
-	0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8,
-	0x8fa20018, 0x5040002f, 0x96a20008, 0x8f620048, 0x8f630024, 0x00761821,
-	0xaf630048, 0x9764003c, 0x00501023, 0x0044102b, 0x10400025, 0x3c029000,
-	0x34420001, 0x3c040800, 0x8c830080, 0x8f450100, 0x3c068000, 0x24630001,
-	0x00a21025, 0xac830080, 0xaf420020, 0x8f420020, 0x00461024, 0x1440fffd,
-	0x00000000, 0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074,
-	0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021,
-	0x0e000470, 0x2405038a, 0x0a00065b, 0x96a20008, 0x8f4201f8, 0x00431024,
-	0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8,
-	0x96a20008, 0x8fbf0044, 0x8fbe0040, 0x8fb7003c, 0x8fb60038, 0x8fb50034,
-	0x8fb40030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x00021042,
-	0x30420001, 0x03e00008, 0x27bd0048, 0x27bdffe0, 0xafbf0018, 0x97420108,
-	0x24030019, 0x304400ff, 0x10830065, 0x2882001a, 0x1040001a, 0x2882000a,
-	0x1040000f, 0x28820008, 0x10400040, 0x24020001, 0x1082003a, 0x28820002,
-	0x50400005, 0x24020006, 0x10800032, 0x3c026000, 0x0a0006fb, 0x00000000,
-	0x1082003d, 0x00000000, 0x0a0006fb, 0x00000000, 0x2402000b, 0x10820044,
-	0x2882000b, 0x1440004b, 0x2402000e, 0x10820045, 0x00000000, 0x0a0006fb,
-	0x00000000, 0x24020020, 0x10820062, 0x28820021, 0x1040000e, 0x2402001c,
-	0x1082004c, 0x2882001d, 0x10400005, 0x2402001b, 0x10820043, 0x00000000,
-	0x0a0006fb, 0x00000000, 0x2402001f, 0x10820050, 0x00000000, 0x0a0006fb,
-	0x00000000, 0x240200c1, 0x10820042, 0x288200c2, 0x10400005, 0x24020080,
-	0x10820021, 0x00000000, 0x0a0006fb, 0x00000000, 0x240200c2, 0x1082003d,
-	0x240200c9, 0x50820049, 0xafa00010, 0x0a0006fb, 0x00000000, 0x0e001163,
-	0xac400808, 0x0a0006fd, 0x8fbf0018, 0x3c026000, 0x8c444448, 0x3c030800,
-	0xac640064, 0x0e001163, 0x00000000, 0x3c026000, 0x8c444448, 0x3c030800,
-	0x0a0006fc, 0xac640068, 0x8f440100, 0x0e0006ff, 0x00000000, 0x3c026000,
-	0x8c444448, 0x3c030800, 0x0a0006fc, 0xac64006c, 0x0e001191, 0x00000000,
-	0x0a0006fd, 0x8fbf0018, 0x8f440100, 0x0e0011bb, 0x00000000, 0x0a0006fd,
-	0x8fbf0018, 0x0e001202, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0000000d,
-	0x0a0006fd, 0x8fbf0018, 0x0e000826, 0x00000000, 0x0a0006fd, 0x8fbf0018,
-	0x8f440100, 0x0e001264, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00134e,
-	0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e00087c, 0x27440100, 0x0a0006fd,
-	0x8fbf0018, 0x8f640040, 0x0e000fae, 0x00000000, 0x0a0006fd, 0x8fbf0018,
-	0x8f440100, 0x0e001059, 0x00000000, 0x0a0006fd, 0x8fbf0018, 0x0e001417,
-	0x00000000, 0x0a0006fd, 0x8fbf0018, 0xafa00014, 0x8f440100, 0x8f450118,
-	0x8f46011c, 0x0e001439, 0x8f470120, 0x0a0006fd, 0x8fbf0018, 0x0000000d,
-	0x8fbf0018, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x9742010c,
-	0x1440005e, 0x00803821, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020,
-	0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023,
-	0x30420010, 0x14400026, 0x3c030800, 0x8f630074, 0x3c027fff, 0x3442ffff,
-	0x00621824, 0xaf630074, 0x93620005, 0x34420001, 0xa3620005, 0x8f63004c,
-	0x8f620054, 0x10620021, 0x24040001, 0x9762006a, 0x00022880, 0x50a00001,
-	0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821,
-	0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050,
-	0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824,
-	0x00a21021, 0xaf62000c, 0x0a00073d, 0x24040001, 0x8c6200a8, 0x00002021,
-	0x24420001, 0xac6200a8, 0x0000000d, 0x00000000, 0x2400044d, 0x3c028000,
-	0x34420001, 0x00e21025, 0xaf420020, 0x1080001f, 0x3c029000, 0x34420001,
-	0x00e21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
-	0x00e31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00e02021, 0x0e000470,
-	0x24050455, 0x0a000761, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
-	0x24020002, 0x3c031000, 0xaf4701c0, 0xa34201c4, 0xaf4301f8, 0x0e001163,
-	0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafbf0024,
-	0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x93630005,
-	0x00809821, 0x24020030, 0x30630030, 0x146200ac, 0x00a0a021, 0x3c020800,
-	0x8c430020, 0x106000a6, 0x00000000, 0x0e00148e, 0x00000000, 0x8f830018,
-	0xac730000, 0x936200c4, 0x30420002, 0x10400004, 0x24020001, 0x8f830018,
-	0x0a000784, 0x00000000, 0x8f830018, 0x24020003, 0xac620004, 0x8f6200dc,
-	0x8f630040, 0x00431023, 0x18400004, 0x00000000, 0x0000000d, 0x00000000,
-	0x24000509, 0x8f840018, 0x8f6200dc, 0xac820008, 0x8f830018, 0xac60000c,
-	0x8f820018, 0xac400010, 0x8f830018, 0x8f62004c, 0x3c100800, 0xac620014,
-	0x8f850018, 0x3c026000, 0x8c434448, 0x261258c0, 0x00002021, 0xaca30018,
-	0x9642000e, 0x8f850018, 0x3c034010, 0x00431025, 0x0e0014cc, 0xaca2001c,
-	0x8f830018, 0xac730000, 0x9362003e, 0x9363003f, 0x8f840018, 0x00021200,
-	0x00621825, 0xac830004, 0x93620081, 0x93630082, 0x8f840018, 0x00021600,
-	0x00031c00, 0x00431025, 0xac820008, 0x8f830018, 0x8f620040, 0xac62000c,
-	0x8f840018, 0x8f620048, 0xac820010, 0x8f71004c, 0x8f820018, 0xac510014,
-	0x8f620050, 0x8f850018, 0x00401821, 0x02221023, 0x5c400001, 0x02201821,
-	0x00002021, 0xaca30018, 0x9642000e, 0x8f850018, 0x3c03c00b, 0x00431025,
-	0x0e0014cc, 0xaca2001c, 0x8f620054, 0x8f840018, 0x00401821, 0x02221023,
-	0x5c400001, 0x02201821, 0xac830000, 0x8f840018, 0x8f630058, 0xac830004,
-	0x93620023, 0x30420010, 0x10400004, 0x00000000, 0x8f830018, 0x0a0007dd,
-	0x8f620148, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f830018, 0x8f620060,
-	0xac62000c, 0x8f840018, 0x8f620064, 0xac820010, 0x97630068, 0x9762006a,
-	0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f850018, 0x00002021,
-	0x2402ffff, 0x260358c0, 0xaca20018, 0x9462000e, 0x8f850018, 0x3c03c00c,
-	0x00431025, 0x0e0014cc, 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000,
-	0x936200c4, 0x30420002, 0x10400006, 0x00000000, 0x976200c8, 0x8f830018,
-	0x3042ffff, 0x0a000803, 0xac620004, 0x8f820018, 0xac400004, 0x8f830018,
-	0x8f62006c, 0xac620008, 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018,
-	0xac600010, 0x93620005, 0x8f830018, 0x00021600, 0x00541025, 0xac620014,
-	0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x260258c0, 0xaca30018,
-	0x9443000e, 0x8f850018, 0x3c02400d, 0x00621825, 0x0e0014cc, 0xaca3001c,
-	0x0e00122e, 0x02602021, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
-	0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb00010,
-	0x27500100, 0xafbf0018, 0xafb10014, 0x9603000c, 0x240200c1, 0x54620024,
-	0x8e040000, 0x3c029000, 0x8f450100, 0x34420001, 0x3c038000, 0x00a21025,
-	0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d,
-	0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x00a31825,
-	0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470, 0x240505b2,
-	0x0a000878, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002,
-	0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x0a000878, 0x8fbf0018,
-	0x8f65004c, 0x24060001, 0x0e0012a3, 0x240705be, 0x3c020800, 0x8c430020,
-	0x9611000c, 0x1060001d, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018,
-	0xac500000, 0x8f840018, 0x00111400, 0xac820004, 0x8f830018, 0xac600008,
-	0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018, 0x240205c1,
-	0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
-	0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc,
-	0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-	0x27bdffb0, 0xafb5003c, 0x0000a821, 0xafbe0048, 0x0000f021, 0xafb70044,
-	0x0000b821, 0xafb30034, 0x00009821, 0xafb60040, 0x0080b021, 0xafbf004c,
-	0xafb40038, 0xafb20030, 0xafb1002c, 0xafb00028, 0xafa00010, 0x8f620040,
-	0x8ec30014, 0x96d1000c, 0x00431023, 0x04410025, 0x8ed40000, 0x32220401,
-	0x1040030c, 0x3c029000, 0x34420001, 0x02821025, 0xaf420020, 0x3c038000,
-	0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
-	0x34420004, 0xa362007d, 0x8f640074, 0x34630001, 0x02831825, 0xaf430020,
-	0x04810006, 0x3c038000, 0x02802021, 0x0e000470, 0x24050664, 0x0a000ba2,
-	0x8fbf004c, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
-	0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x0a000ba2, 0x8fbf004c, 0x32220010,
-	0x1040006b, 0x00003021, 0x9362003f, 0x92c6000f, 0x304500ff, 0x24c3fff8,
-	0x2c62000f, 0x10400057, 0x3c020800, 0x244257c0, 0x00031880, 0x00621821,
-	0x8c640000, 0x00800008, 0x00000000, 0x38a20012, 0x0a000924, 0x0002a82b,
-	0x2402000e, 0x14a20004, 0x2402000c, 0x24150001, 0x0a000924, 0x24060010,
-	0x10a20049, 0x38a30010, 0x2c630001, 0x38a20016, 0x2c420001, 0x00621825,
-	0x1460004d, 0x0000a821, 0x24020014, 0x10a2004a, 0x00000000, 0x0000000d,
-	0x00000000, 0x2400069c, 0x0a000924, 0x0000a821, 0x24020016, 0x14a20005,
-	0x2402000c, 0x24150001, 0x24060010, 0x0a000924, 0x3231fffd, 0x10a20032,
-	0x38a30010, 0x2c630001, 0x38a2000e, 0x2c420001, 0x00621825, 0x14600036,
-	0x0000a821, 0x24020014, 0x14a20003, 0x24150001, 0x0a000924, 0x24060012,
-	0x0000000d, 0x00000000, 0x240006bc, 0x0a000924, 0x0000a821, 0x2402000e,
-	0x14a20004, 0x24020016, 0x24150001, 0x0a000924, 0x3231fffb, 0x14a20004,
-	0x24020014, 0x24150001, 0x0a000924, 0x3231fffd, 0x54a20013, 0x92c2000e,
-	0x24150001, 0x24060012, 0x0a000924, 0x3231fffd, 0x2402000c, 0x54a2000c,
-	0x92c2000e, 0x92c3000e, 0x2402000a, 0x10620005, 0x24150001, 0x0000000d,
-	0x00000000, 0x240006e8, 0x24150001, 0x0a000924, 0x24060014, 0x92c2000e,
-	0x14a20003, 0x00000000, 0x0a000924, 0x24150001, 0x10a6ffc1, 0x24020012,
-	0x10a20005, 0x0000a821, 0x0000000d, 0x00000000, 0x24000704, 0x0000a821,
-	0x12a00022, 0x32220004, 0x10400002, 0x24020001, 0xafa20010, 0x32230102,
-	0x24020002, 0x1462000f, 0x00000000, 0x92c2000a, 0x30420020, 0x1440000b,
-	0x00000000, 0x8f630048, 0x8f620040, 0x14620004, 0x00000000, 0x8f620048,
-	0x24420001, 0xaf620048, 0x8f620040, 0x24420001, 0xaf620040, 0xa366003f,
-	0x38c30012, 0x2c630001, 0x38c20010, 0x2c420001, 0x00621825, 0x10600005,
-	0x3c030800, 0x8c620074, 0x24420001, 0x0e00140d, 0xac620074, 0x32220040,
-	0x32230020, 0xafa30020, 0x32230080, 0xafa30024, 0x32230001, 0xafa30018,
-	0x32230008, 0xafa3001c, 0x32230100, 0x104000c4, 0xafa30014, 0x8ec60010,
-	0x8f630054, 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d,
-	0x00000000, 0x2400015c, 0x0a000989, 0x00009021, 0x8f62004c, 0x00c21023,
-	0x18400028, 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c,
-	0x308400ff, 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c,
-	0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001,
-	0x00021023, 0x30420005, 0x0a000989, 0x34520004, 0x27670100, 0x00041080,
-	0x00e21021, 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007,
-	0x1485fff9, 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094,
-	0x24120005, 0x24420001, 0x0a000989, 0xac620094, 0x24120004, 0x32420001,
-	0x10400021, 0x3c020800, 0x8c430020, 0x8ed00000, 0x1060001c, 0x8ed30010,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001,
-	0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-	0xac600010, 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448,
-	0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010,
-	0x00621825, 0x0e0014cc, 0xaca3001c, 0x24130001, 0x32420004, 0x10400068,
-	0x00003821, 0x3c029000, 0x8ec60010, 0x34420001, 0x3c038000, 0x02821025,
-	0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
-	0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c,
-	0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006,
-	0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff,
-	0x0a0009da, 0x3442ffff, 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000,
-	0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064,
-	0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff,
-	0x34a5ffff, 0x00c51021, 0xaf62005c, 0x24070001, 0xaf66004c, 0x8fa20010,
-	0x10400003, 0x00000000, 0xaf660050, 0xaf660054, 0x8f620054, 0x14c20005,
-	0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a,
-	0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800,
-	0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021,
-	0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074,
-	0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x93620082, 0x30420080,
-	0x50400001, 0xa3600081, 0x3c028000, 0x34420001, 0x02821025, 0xaf420020,
-	0x9363007e, 0x9362007a, 0x10620005, 0x00e0b821, 0x0e0013c4, 0x00000000,
-	0x00403821, 0x00e0b821, 0x8fa30020, 0x10600009, 0x8fa20010, 0x8ec20018,
-	0xaf620018, 0x8ec3001c, 0xaf63001c, 0x8ec20020, 0x24170001, 0xaf620058,
-	0x8fa20010, 0x10400057, 0x8fa30024, 0x93620023, 0x30420040, 0x10400053,
-	0x00000000, 0x16600021, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040001e,
-	0x24130001, 0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018,
-	0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
-	0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000,
-	0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-	0x3c024010, 0x00621825, 0xaca3001c, 0x0e0014cc, 0x24130001, 0x8e420020,
-	0x1040001c, 0x8ed00000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000,
-	0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c,
-	0x8f820018, 0xac400010, 0x8f830018, 0x24020798, 0xac620014, 0x8f850018,
-	0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce,
-	0x8f850018, 0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000,
-	0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-	0x1440fffd, 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001,
-	0x02821025, 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30024, 0x10600012,
-	0x8fa30018, 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a,
-	0x1462000b, 0x8fa30018, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b,
-	0x14400005, 0x8fa30018, 0x0e0013c4, 0x00000000, 0x02e2b825, 0x8fa30018,
-	0x3062ffff, 0x10400003, 0x32220200, 0x0a000a94, 0x241e0004, 0x10400003,
-	0x00000000, 0x241e0040, 0x24170001, 0x12a000d0, 0x32220002, 0x104000cf,
-	0x8fa2001c, 0x92c2000a, 0x30420002, 0x5040003b, 0x92c2000a, 0x93620023,
-	0x30420008, 0x54400037, 0x92c2000a, 0x3c020800, 0x8c430020, 0x10600023,
-	0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000,
-	0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040,
-	0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018,
-	0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018,
-	0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-	0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
-	0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630008,
-	0xa3630023, 0xaf420020, 0x92c2000a, 0x30420020, 0x1040008e, 0x8fa2001c,
-	0x93620023, 0x30420001, 0x14400035, 0x3c020800, 0x8c430020, 0x10600023,
-	0x3c029000, 0x0e00148e, 0x00000000, 0x8f840018, 0x8ec30000, 0xac830000,
-	0x92c2000a, 0x8f830018, 0x00021600, 0xac620004, 0x8f840018, 0x8f620040,
-	0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c, 0x9362003f, 0x8f840018,
-	0x304200ff, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f850018,
-	0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-	0x3c02401a, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
-	0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x34630001,
-	0xa3630023, 0xaf420020, 0x93620023, 0x30420040, 0x10400052, 0x8fa2001c,
-	0x16600020, 0x3c120800, 0x8e420020, 0x8f70004c, 0x1040003c, 0x3c029000,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x24020001,
-	0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-	0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448,
-	0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010,
-	0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x3c029000,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac540000, 0x8f840018, 0x3c02008d,
-	0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-	0xac600010, 0x8f840018, 0x240207ee, 0xac820014, 0x8f850018, 0x3c026000,
-	0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-	0x3c024019, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x3c029000, 0x34420001,
-	0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x93630023, 0x3c028000, 0x34420001, 0x02821025, 0x306300bf,
-	0xa3630023, 0xaf420020, 0x8fa2001c, 0x1040000e, 0x8fa20014, 0x92c2000a,
-	0xa3620082, 0x57c00005, 0x37de0008, 0x8fa30014, 0x10600004, 0x00000000,
-	0x37de0008, 0x0a000b75, 0x24170001, 0x0e0012cf, 0x02802021, 0x8fa20014,
-	0x10400003, 0x00000000, 0x37de0010, 0x24170001, 0x12e00020, 0x3c029000,
-	0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-	0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x03c21025, 0xa362007d,
-	0x8f640074, 0x34630001, 0x02831825, 0xaf430020, 0x04810006, 0x3c038000,
-	0x02802021, 0x0e000470, 0x2405082a, 0x0a000b9b, 0x00000000, 0x8f4201f8,
-	0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4,
-	0xaf4301f8, 0x9363003f, 0x24020012, 0x14620004, 0x8fbf004c, 0x0e00140d,
-	0x00000000, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c,
-	0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x03e00008,
-	0x27bd0050, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500180, 0x97420184,
-	0x30420200, 0x14400015, 0x00000000, 0x8f430188, 0x3c02ff00, 0x00621824,
-	0x3c020200, 0x10620031, 0x0043102b, 0x14400007, 0x3c020300, 0x1060000b,
-	0x3c020100, 0x1062000d, 0x00000000, 0x0a000c2c, 0x00000000, 0x10620027,
-	0x3c020400, 0x1062003e, 0x02002021, 0x0a000c2c, 0x00000000, 0x0e000c31,
-	0x02002021, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e,
-	0x8fbf0014, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000,
-	0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
-	0x34630001, 0x02031825, 0x34420020, 0xa3620005, 0xaf430020, 0x93620005,
-	0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000766,
-	0x24055854, 0x0a000c2e, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f,
-	0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020,
-	0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x34420004, 0xa3620023,
-	0x93630005, 0x3c048000, 0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020,
-	0x34840001, 0x02042025, 0x0a000c0a, 0xaf440020, 0x00002821, 0x00003021,
-	0x0e000fb1, 0x240708d9, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f,
-	0x8f840018, 0x00031a00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008,
-	0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014,
-	0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
-	0x944358ce, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e0014cc, 0xaca3001c,
-	0x0a000c2e, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008,
-	0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021, 0x93640000,
-	0x24030020, 0x00021402, 0x10830008, 0x304500ff, 0x3c036018, 0x8c625000,
-	0x34420400, 0xac625000, 0x0000000d, 0x00000000, 0x24000955, 0x9363003f,
-	0x24020012, 0x14620023, 0x3c029000, 0x34420001, 0x3c038000, 0x00c21025,
-	0xaf650178, 0xa365007a, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
-	0x00c31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00c02021, 0x0e000470,
-	0x24050963, 0x0a000c79, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd,
-	0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a000c79,
-	0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x8f620178, 0x1045000b,
-	0x00000000, 0x8f820000, 0xaf650178, 0x8f660178, 0x8f440180, 0x8f65004c,
-	0x8c430000, 0x0060f809, 0x30c600ff, 0x0a000c79, 0x8fbf0010, 0xaf650178,
-	0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93630000,
-	0x24020020, 0x10620005, 0x00000000, 0x93630000, 0x24020030, 0x1462004d,
-	0x8fbf0010, 0x93420148, 0x2444ffff, 0x2c830005, 0x10600047, 0x3c020800,
-	0x24425800, 0x00041880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000,
-	0x8f430144, 0x8f62000c, 0x14620006, 0x24020001, 0xaf62000c, 0x0e000d59,
-	0x00000000, 0x0a000cd1, 0x8fbf0010, 0x8f62000c, 0x0a000cca, 0x00000000,
-	0x97630010, 0x8f420144, 0x14430006, 0x24020001, 0xa7620010, 0x0e00137a,
-	0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620010, 0x0a000cca, 0x00000000,
-	0x97630012, 0x8f420144, 0x14430006, 0x24020001, 0xa7620012, 0x0e001395,
-	0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620012, 0x0a000cca, 0x00000000,
-	0x97630014, 0x8f420144, 0x14430006, 0x24020001, 0xa7620014, 0x0e0013bb,
-	0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620014, 0x0a000cca, 0x00000000,
-	0x97630016, 0x8f420144, 0x14430006, 0x24020001, 0xa7620016, 0x0e0013be,
-	0x00000000, 0x0a000cd1, 0x8fbf0010, 0x97620016, 0x14400006, 0x8fbf0010,
-	0x3c030800, 0x8c620070, 0x24420001, 0xac620070, 0x8fbf0010, 0x03e00008,
-	0x27bd0018, 0x27bdffe0, 0x3c029000, 0xafbf001c, 0xafb20018, 0xafb10014,
-	0xafb00010, 0x8f500140, 0x34420001, 0x3c038000, 0x02021025, 0xaf420020,
-	0x8f420020, 0x00431024, 0x1440fffd, 0x24020012, 0x24030080, 0xa362003f,
-	0xa3630082, 0x93620023, 0x30420040, 0x10400007, 0x00008821, 0x93620023,
-	0x24110001, 0x304200bf, 0xa3620023, 0x0a000cf0, 0x3c028000, 0x3c028000,
-	0x34420001, 0x3c039000, 0x34630001, 0x3c048000, 0x02021025, 0x02031825,
-	0xaf420020, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000,
-	0x9362007d, 0x3c038000, 0x34420020, 0xa362007d, 0x8f640074, 0x34630001,
-	0x02031825, 0xaf430020, 0x04810006, 0x3c038000, 0x02002021, 0x0e000470,
-	0x24050a63, 0x0a000d13, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
-	0x24020002, 0x3c031000, 0xaf5001c0, 0xa34201c4, 0xaf4301f8, 0x1220003f,
-	0x3c120800, 0x8e420020, 0x8f71004c, 0x1040003c, 0x8fbf001c, 0x0e00148e,
-	0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004,
-	0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-	0x8f820018, 0xac510014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
-	0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024010, 0x00621825,
-	0x0e0014cc, 0xaca3001c, 0x8e420020, 0x1040001e, 0x8fbf001c, 0x0e00148e,
-	0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004,
-	0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-	0x8f840018, 0x24020a6a, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448,
-	0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c024019,
-	0x00621825, 0x0e0014cc, 0xaca3001c, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-	0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010, 0x93620081,
-	0x3c030800, 0x8c640048, 0x0044102b, 0x14400005, 0x00000000, 0x0e000cd3,
-	0x00000000, 0x0a000da4, 0x8fbf0010, 0x93620081, 0x24420001, 0x0e0013c4,
-	0xa3620081, 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001,
-	0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804,
-	0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b,
-	0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021,
-	0xaf62000c, 0x10e00021, 0x3c029000, 0x8f450140, 0x34420001, 0x3c038000,
-	0x00a21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
-	0x9362007d, 0x3c038000, 0x34420004, 0xa362007d, 0x8f640074, 0x34630001,
-	0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021, 0x0e000470,
-	0x24050a92, 0x0a000da4, 0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd,
-	0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010,
-	0x03e00008, 0x27bd0018, 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024,
-	0xafb40020, 0xafb20018, 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800,
-	0x8f520100, 0x30420001, 0x104000da, 0x00000000, 0x8e700018, 0x8f630054,
-	0x2602ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000,
-	0x2400015c, 0x0a000dea, 0x00008821, 0x8f62004c, 0x02021023, 0x18400028,
-	0x00008821, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff,
-	0x24420001, 0x30a500ff, 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800,
-	0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023,
-	0x30420005, 0x0a000dea, 0x34510004, 0x27660100, 0x00041080, 0x00c21021,
-	0x8c430000, 0x02031823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9,
-	0x00041080, 0x10870007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005,
-	0x24420001, 0x0a000dea, 0xac620094, 0x24110004, 0x32220001, 0x1040001e,
-	0x8e820020, 0x1040001d, 0x32220004, 0x0e00148e, 0x00000000, 0x8f820018,
-	0xac520000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018, 0xac600008,
-	0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac500014,
-	0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
-	0x944358ce, 0x8f850018, 0x3c024010, 0x00621825, 0x0e0014cc, 0xaca3001c,
-	0x32220004, 0x10400081, 0x00003821, 0x3c029000, 0x34420001, 0x3c038000,
-	0x02421025, 0xa360007c, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x93620023, 0x30420080, 0x10400011, 0x00000000, 0x8f65005c,
-	0x8f63004c, 0x9764003c, 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b,
-	0x54400006, 0x3c023fff, 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064,
-	0x3c023fff, 0x0a000e37, 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011,
-	0x00000000, 0x8f65005c, 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff,
-	0xaf700064, 0x00a32823, 0x00852821, 0x0045102b, 0x10400004, 0x02051021,
-	0x3c053fff, 0x34a5ffff, 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c,
-	0x8f620054, 0x16020005, 0x00000000, 0x93620023, 0x30420040, 0x10400017,
-	0x24020001, 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068,
-	0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b,
-	0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001,
-	0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c,
-	0x93620082, 0x30420080, 0x50400001, 0xa3600081, 0x3c028000, 0x34420001,
-	0x02421025, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004, 0x00000000,
-	0x0e0013c4, 0x00000000, 0x00403821, 0x10e0001f, 0x3c029000, 0x34420001,
-	0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001,
-	0x02431825, 0xaf430020, 0x04810006, 0x3c038000, 0x02402021, 0x0e000470,
-	0x24050b3d, 0x0a000e8d, 0x00000000, 0x8f4201f8, 0x00431024, 0x1440fffd,
-	0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b,
-	0x9343010b, 0x8e820020, 0x27500100, 0x38630006, 0x10400029, 0x2c710001,
-	0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
-	0x96020008, 0xac820004, 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018,
-	0x3c026000, 0x8c434448, 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010,
-	0x8f850018, 0x8e030020, 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018,
-	0x00021400, 0x00431025, 0xac820018, 0x12200005, 0x3c020800, 0x944358ce,
-	0x8f840018, 0x0a000eb8, 0x3c024013, 0x944358ce, 0x8f840018, 0x3c024014,
-	0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8e700014, 0x8f620040,
-	0x14500003, 0x00501023, 0x0a000ec3, 0x00001021, 0x28420001, 0x1040003a,
-	0x00000000, 0x0e000fae, 0x02002021, 0xaf700040, 0x9362003e, 0x30420001,
-	0x1440000b, 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022,
-	0x3c020800, 0x8c440098, 0x0064182b, 0x14600025, 0x3c020800, 0x3c029000,
-	0x34420001, 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-	0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d,
-	0x8f640074, 0x34630001, 0x02431825, 0xaf430020, 0x04810006, 0x3c038000,
-	0x02402021, 0x0e000470, 0x24050273, 0x0a000ef6, 0x24020001, 0x8f4201f8,
-	0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5201c0, 0xa34201c4,
-	0xaf4301f8, 0x24020001, 0xa7620012, 0x0a000efe, 0xa3600022, 0x9743007a,
-	0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012, 0x97420108, 0x8fbf0024,
-	0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042,
-	0x30420001, 0x03e00008, 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800,
-	0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014,
-	0x0e00148e, 0x00000000, 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1,
-	0x936200c5, 0x8f850018, 0x00031e00, 0x00021400, 0x34420100, 0x00621825,
-	0xaca30004, 0x8f840018, 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048,
-	0xac62000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f830018, 0x8f620040,
-	0x24040001, 0xac620014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800,
-	0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825,
-	0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020,
-	0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000, 0x8f820018, 0xac500000,
-	0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c,
-	0x8f820018, 0xac400010, 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000,
-	0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015,
-	0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018,
-	0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018,
-	0x3c120800, 0x8e420020, 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041,
-	0xafb10014, 0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000,
-	0x8f840018, 0x24020100, 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008,
-	0x8f840018, 0x8e020018, 0xac82000c, 0x8f830018, 0x96020012, 0xac620010,
-	0x8f840018, 0x96020008, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448,
-	0x24040001, 0x3c020800, 0x245158c0, 0xaca30018, 0x9623000e, 0x8f850018,
-	0x3c024017, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x96030008, 0x30630010,
-	0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000, 0x0e00148e, 0x00000000,
-	0x8f820018, 0xac500000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008,
-	0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0xac600014,
-	0x8f850018, 0x3c036000, 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e,
-	0x8f850018, 0x3c034015, 0x00431025, 0x0e0014cc, 0xaca2001c, 0x00001021,
-	0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-	0x27bdfff0, 0x03e00008, 0x27bd0010, 0x27bdffd0, 0xafb10014, 0x00808821,
-	0xafb40020, 0x00c0a021, 0xafbf0028, 0xafb50024, 0xafb3001c, 0xafb20018,
-	0xafb00010, 0x93620023, 0x00e0a821, 0x30420040, 0x1040003e, 0x30b3ffff,
-	0x3c120800, 0x8e420020, 0x1040003a, 0x8f70004c, 0x0e00148e, 0x00000000,
-	0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018,
-	0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
-	0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800,
-	0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010, 0x00621825,
-	0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001b, 0x00000000, 0x0e00148e,
-	0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x3c02008d, 0xac820004,
-	0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-	0x8f820018, 0xac550014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001,
-	0xaca30018, 0x9602000e, 0x8f850018, 0x3c034019, 0x00431025, 0x0e0014cc,
-	0xaca2001c, 0x93620023, 0x30420020, 0x14400003, 0x3c120800, 0x1280003f,
-	0x3c029000, 0x8e420020, 0x8f70004c, 0x1040003b, 0x3c029000, 0x0e00148e,
-	0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x24020001, 0xac820004,
-	0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-	0x8f820018, 0x24040001, 0xac500014, 0x8f850018, 0x3c026000, 0x8c434448,
-	0x3c020800, 0x245058c0, 0xaca30018, 0x9603000e, 0x8f850018, 0x3c024010,
-	0x00621825, 0x0e0014cc, 0xaca3001c, 0x8e430020, 0x1060001c, 0x3c029000,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018, 0x00131400,
-	0xac820004, 0x8f830018, 0xac750008, 0x8f820018, 0xac40000c, 0x8f830018,
-	0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c036000, 0x8c634448,
-	0x24040001, 0xaca30018, 0x9602000e, 0x8f850018, 0x3c03401b, 0x00431025,
-	0x0e0014cc, 0xaca2001c, 0x3c029000, 0x34420001, 0x02221025, 0xaf420020,
-	0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023,
-	0x3c028000, 0x34420001, 0x02221025, 0x8fbf0028, 0x8fb50024, 0x8fb40020,
-	0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023,
-	0xaf420020, 0x03e00008, 0x27bd0030, 0x27bdffe0, 0xafb10014, 0x27510100,
-	0x3c029000, 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000,
-	0xafbf0018, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
-	0xa7600008, 0x8f63005c, 0x3c028000, 0x34420001, 0xaf630148, 0x8f640050,
-	0x02021025, 0x3c039000, 0xaf64017c, 0xaf420020, 0x8f450100, 0x34630001,
-	0x3c048000, 0x00a31825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd,
-	0x00000000, 0x9362007d, 0x3c038000, 0x34420001, 0xa362007d, 0x8f640074,
-	0x34630001, 0x00a31825, 0xaf430020, 0x04810006, 0x3c038000, 0x00a02021,
-	0x0e000470, 0x24050de5, 0x0a001093, 0x3c020800, 0x8f4201f8, 0x00431024,
-	0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0, 0xa34201c4, 0xaf4301f8,
-	0x3c020800, 0x8c430020, 0x1060001e, 0x8fbf0018, 0x0e00148e, 0x00000000,
-	0x8f830018, 0xac700000, 0x9622000c, 0x8f840018, 0x00021400, 0xac820004,
-	0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
-	0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
-	0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401f, 0x00621825,
-	0x0e0014cc, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008,
-	0x27bd0020, 0x3c020800, 0x24424c3c, 0xaf82000c, 0x03e00008, 0x00000000,
-	0x27bdffe8, 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003,
-	0x3c020800, 0x0000000d, 0x3c020800, 0x8c430020, 0x10600020, 0x00001021,
-	0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
-	0x8e02001c, 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018,
-	0xac82000c, 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c026000,
-	0xac600014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018, 0x944358ce,
-	0x8f840018, 0x3c024012, 0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001,
-	0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800,
-	0x97430078, 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008,
-	0xa7630010, 0x27bdfff0, 0x00001021, 0x03e00008, 0x27bd0010, 0x8f420100,
-	0x34420001, 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018,
-	0xafb10014, 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020031, 0x00808821,
-	0x8f620178, 0x1602002e, 0x00000000, 0x9362007f, 0x1602002b, 0x00000000,
-	0x9362007a, 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x240009d2,
-	0x0e0013e6, 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825,
-	0xa370007a, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000,
-	0x9362007d, 0x3c038000, 0xa362007d, 0x8f640074, 0x34630001, 0x02231825,
-	0xaf430020, 0x04810006, 0x3c038000, 0x02202021, 0x0e000470, 0x240509dd,
-	0x0a001138, 0x8fbf0018, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002,
-	0x3c031000, 0xaf5101c0, 0xa34201c4, 0xaf4301f8, 0x0a001138, 0x8fbf0018,
-	0x0000000d, 0x00000000, 0x240009e2, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
-	0x03e00008, 0x27bd0020, 0x27bdffe8, 0x30a500ff, 0x3c029000, 0x34420001,
-	0x00803821, 0x00e21025, 0x3c038000, 0xafbf0010, 0xaf420020, 0x8f420020,
-	0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x00a21025,
-	0xa362007d, 0x8f640074, 0x34630001, 0x00e31825, 0xaf430020, 0x04810006,
-	0x3c038000, 0x00e02021, 0x0e000470, 0x00c02821, 0x0a001161, 0x8fbf0010,
-	0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4701c0,
-	0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800,
-	0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x10600024, 0xafbf0014,
-	0x0e00148e, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
-	0x8e020004, 0xac820004, 0x8f830018, 0x8e020018, 0xac620008, 0x8f840018,
-	0x8e03001c, 0xac83000c, 0x9602000c, 0x9203000a, 0x8f840018, 0x00021400,
-	0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
-	0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018,
-	0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014,
-	0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8,
-	0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e00148e, 0x00000000,
-	0x8f820018, 0xac400000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008,
-	0x8f830018, 0xac60000c, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400,
-	0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
-	0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x946458ce, 0x8f850018,
-	0x00021400, 0x00441025, 0x24040001, 0x0e0014cc, 0xaca2001c, 0x8fbf0014,
-	0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, 0x27500100,
-	0xafbf0014, 0x9602000c, 0x10400024, 0x00802821, 0x3c020800, 0x8c430020,
-	0x1060003a, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f840018, 0x8e030000,
-	0xac830000, 0x9602000c, 0x8f840018, 0x00021400, 0xac820004, 0x8f830018,
-	0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
-	0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
-	0xaca30018, 0x944358ce, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e0014cc,
-	0xaca3001c, 0x0a0011ff, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015,
-	0x3c029000, 0x34420001, 0x00a21025, 0xaf420020, 0x3c038000, 0x8f420020,
-	0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x93620005, 0x34630001,
-	0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000766,
-	0xaf430020, 0x0a0011ff, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010,
-	0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010,
-	0x27500100, 0x10600022, 0xafbf0014, 0x0e00148e, 0x00000000, 0x8f840018,
-	0x8e020004, 0xac820000, 0x9603000c, 0x9762002c, 0x8f840018, 0x00031c00,
-	0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
-	0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000,
-	0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018,
-	0x3c02400e, 0x00621825, 0x0e0014cc, 0xaca3001c, 0x0e00122e, 0x8e040000,
-	0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c038000, 0x8f420278,
-	0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf440240, 0xa3420244,
-	0x03e00008, 0xaf430278, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014,
-	0x00808821, 0xafb20018, 0x00c09021, 0xafb00010, 0x30b0ffff, 0x1060001c,
-	0xafbf001c, 0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018,
-	0x00101400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
-	0x8f830018, 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000,
-	0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024019,
-	0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018,
-	0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x27450100,
-	0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620031, 0x00803021, 0x3c029000,
-	0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
-	0x1440fffd, 0x3c028000, 0x34420001, 0x3c049000, 0x34840001, 0x3c058000,
-	0x24030012, 0x00c21025, 0x00c42025, 0xa363003f, 0xaf420020, 0xaf440020,
-	0x8f420020, 0x00451024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000,
-	0x34420020, 0xa362007d, 0x8f640074, 0x34630001, 0x00c31825, 0xaf430020,
-	0x04810006, 0x3c038000, 0x00c02021, 0x0e000470, 0x24050906, 0x0a0012a1,
-	0x8fbf0010, 0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000,
-	0xaf4601c0, 0xa34201c4, 0xaf4301f8, 0x0a0012a1, 0x8fbf0010, 0x00c02021,
-	0x94a5000c, 0x24060001, 0x0e000fb1, 0x2407090e, 0x8fbf0010, 0x03e00008,
-	0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021,
-	0xafb20018, 0x00a09021, 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001,
-	0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-	0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448,
-	0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024010, 0x00621825,
-	0xac83001c, 0x0e0014cc, 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-	0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010,
-	0x93620005, 0x30420001, 0x10400036, 0x00808021, 0x3c029000, 0x34420001,
-	0x02021025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x93620023, 0x34420004, 0xa3620023, 0x93630005, 0x3c048000,
-	0x3c020800, 0x306300fe, 0xa3630005, 0x8c430020, 0x34840001, 0x02042025,
-	0xaf440020, 0x10600020, 0x8fbf0014, 0x0e00148e, 0x00000000, 0x8f820018,
-	0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00, 0x00431025,
-	0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018,
-	0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000, 0x8c434448,
-	0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c02400a, 0x00621825,
-	0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf0014, 0x8fb00010, 0x03e00008,
-	0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014, 0x00808821,
-	0xafb20018, 0x00a09021, 0xafb00010, 0x30d000ff, 0x1060002f, 0xafbf001c,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac510000, 0x8f830018, 0xac700004,
-	0x8f820018, 0xac520008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
-	0x9763006a, 0x00032880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081,
-	0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001,
-	0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021,
-	0x8f830018, 0x2402fffe, 0x00822824, 0x3c026000, 0xac650014, 0x8f840018,
-	0x8c434448, 0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c024011,
-	0x00621825, 0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018,
-	0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014,
-	0xafb00010, 0x8f440100, 0x27500100, 0x8f650050, 0x0e0010fc, 0x9206001b,
-	0x3c020800, 0x8c430020, 0x1060001d, 0x8e100018, 0x0e00148e, 0x00000000,
-	0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f840018,
-	0x8f620050, 0xac820008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
-	0x8f830018, 0x3c026000, 0xac600014, 0x8f850018, 0x8c434448, 0x24040001,
-	0x3c020800, 0xaca30018, 0x944358ce, 0x8f850018, 0x3c02401c, 0x00621825,
-	0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018,
-	0x8f430238, 0x3c020800, 0x04610013, 0x8c44009c, 0x2406fffe, 0x3c050800,
-	0x3c038000, 0x2484ffff, 0x14800009, 0x00000000, 0x97420078, 0x8ca3007c,
-	0x24420001, 0x00461024, 0x24630001, 0xa7620010, 0x03e00008, 0xaca3007c,
-	0x8f420238, 0x00431024, 0x1440fff3, 0x2484ffff, 0x8f420140, 0x3c031000,
-	0xaf420200, 0x03e00008, 0xaf430238, 0x27bdffe8, 0x3c029000, 0xafbf0010,
-	0x8f450140, 0x34420001, 0x3c038000, 0x00a21025, 0xaf420020, 0x8f420020,
-	0x00431024, 0x1440fffd, 0x00000000, 0x9362007d, 0x3c038000, 0x34420001,
-	0xa362007d, 0x8f640074, 0x34630001, 0x00a31825, 0xaf430020, 0x04810006,
-	0x3c038000, 0x00a02021, 0x0e000470, 0x24050ac7, 0x0a0013b9, 0x8fbf0010,
-	0x8f4201f8, 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4501c0,
-	0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x0000000d,
-	0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x24020001,
-	0x03e00008, 0xa7620010, 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001,
-	0x38820010, 0x2c420001, 0x00621825, 0x14600003, 0x24020012, 0x14820003,
-	0x00000000, 0x03e00008, 0x00001021, 0x9363007e, 0x9362007a, 0x14620006,
-	0x00000000, 0x9363007e, 0x24020001, 0x24630001, 0x03e00008, 0xa363007e,
-	0x9362007e, 0x8f630178, 0x304200ff, 0x14430006, 0x00000000, 0x9363000b,
-	0x24020001, 0x24630001, 0x03e00008, 0xa363000b, 0x03e00008, 0x00001021,
-	0x9362000b, 0x10400023, 0x00001021, 0xa360000b, 0x9362003f, 0x304400ff,
-	0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825, 0x14600017,
-	0x00001821, 0x24020012, 0x10820014, 0x00000000, 0x9363007e, 0x9362007a,
-	0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001, 0xa362007e,
-	0x03e00008, 0x00601021, 0x9362007e, 0x8f630178, 0x304200ff, 0x14430005,
-	0x00001821, 0x9362000b, 0x24030001, 0x24420001, 0xa362000b, 0x03e00008,
-	0x00601021, 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc,
-	0x8f6200cc, 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008,
-	0xa7640016, 0x3c020800, 0x8c430020, 0x27bdffe8, 0x1060001b, 0xafbf0010,
-	0x0e00148e, 0x00000000, 0x8f820018, 0xac400000, 0x8f830018, 0xac600004,
-	0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
-	0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448, 0x3c020800,
-	0xac830018, 0x944358ce, 0x8f840018, 0x3c024020, 0x00621825, 0xac83001c,
-	0x0e0014cc, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800,
-	0x8c430020, 0x27bdffe0, 0xafb00010, 0x00a08021, 0xafb10014, 0x00c08821,
-	0xafb20018, 0x00e09021, 0x1060001e, 0xafbf001c, 0x0e00148e, 0x00000000,
-	0x8f840018, 0x8f420100, 0xac820000, 0x8f830018, 0xac700004, 0x8f820018,
-	0xac510008, 0x8f830018, 0xac72000c, 0x8f840018, 0x8fa20030, 0xac820010,
-	0x8f830018, 0x8fa20034, 0xac620014, 0x8f840018, 0x3c026000, 0x8c434448,
-	0x3c020800, 0xac830018, 0x944358ce, 0x8f840018, 0x3c0240c9, 0x00621825,
-	0xac83001c, 0x0e0014cc, 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
-	0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x8c430020, 0x27bdffe8,
-	0xafb00010, 0x27500100, 0x1060001d, 0xafbf0014, 0x0e00148e, 0x00000000,
-	0x8f830018, 0x8e020004, 0xac620000, 0x8f840018, 0x8e020018, 0xac820004,
-	0x8f850018, 0x8e020000, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018,
-	0xac400010, 0x8f830018, 0xac600014, 0x8f820018, 0xac400018, 0x96030008,
-	0x3c020800, 0x944458ce, 0x8f850018, 0x00031c00, 0x00641825, 0x24040001,
-	0x0e0014cc, 0xaca3001c, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018,
-	0x3c060800, 0x24c558c0, 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a,
-	0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d,
-	0x00000000, 0x2400005a, 0x0a0014a3, 0x24020001, 0x8f820014, 0x0062102b,
-	0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400,
-	0x3c07000a, 0x3c020800, 0x244558c0, 0x94a9000a, 0x8f880014, 0x03471021,
-	0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023,
-	0x00021400, 0x00021403, 0x04410006, 0x0048102b, 0x0000000d, 0x00000000,
-	0x2400005a, 0x0a0014be, 0x24020001, 0x14400002, 0x00001021, 0x24020001,
-	0x304200ff, 0x1440ffec, 0x03471021, 0x24c458c0, 0x8c820010, 0xaf420038,
-	0x8c830014, 0x3c020005, 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018,
-	0x03e00008, 0x00000000, 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800,
-	0x24e858c0, 0xafbf001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a,
-	0x8d060014, 0x00009021, 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020,
-	0x24630001, 0xaf820010, 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000,
-	0x04c10007, 0xad030014, 0x00621024, 0x14400005, 0x262258c0, 0x8d020010,
-	0x24420001, 0xad020010, 0x262258c0, 0x9444000a, 0x94450018, 0x0010102b,
-	0x00a41826, 0x2c630001, 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010,
-	0x24120001, 0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000,
-	0x00000000, 0x27450400, 0x8f420000, 0x30420010, 0x1040fffd, 0x262258c0,
-	0x9444000a, 0x94430018, 0xaf800010, 0xaf850018, 0x14830012, 0x262758c0,
-	0x0e00155a, 0x00000000, 0x1600000e, 0x262758c0, 0x0e00148e, 0x00000000,
-	0x0a001517, 0x262758c0, 0x00041c00, 0x00031c03, 0x00051400, 0x00021403,
-	0x00621823, 0x18600002, 0x3c026000, 0xac400808, 0x262758c0, 0x94e2000e,
-	0x94e3000c, 0x24420001, 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e,
-	0x12000005, 0x3c02000a, 0x94e2000a, 0xa74200a2, 0x0a001554, 0x02401021,
-	0x03421821, 0x94640006, 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03,
-	0x04610006, 0xa4e40006, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001536,
-	0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021, 0x24020001,
-	0x304200ff, 0x1040001b, 0x3c020800, 0x3c06000a, 0x244558c0, 0x94a8000a,
-	0x8f870014, 0x03461021, 0x94430006, 0x00402021, 0xa4a30006, 0x94820006,
-	0xa4a20006, 0x01021023, 0x00021400, 0x00021403, 0x04410006, 0x0047102b,
-	0x0000000d, 0x00000000, 0x2400005a, 0x0a001550, 0x24020001, 0x14400002,
-	0x00001021, 0x24020001, 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021,
-	0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
-	0x3c020800, 0x244558c0, 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0,
-	0x00832021, 0xaf44003c, 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008,
-	0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x8f420000, 0x30420020,
-	0x1040fffd, 0x00000000, 0x8f430400, 0x24c658c0, 0xacc30010, 0x8f420404,
-	0x3c030020, 0xacc20014, 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a,
-	0x94c5001e, 0x00832021, 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002,
-	0xa4c40018, 0xa4c0001a, 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006,
-	0x00021140, 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000,
-	0x27430400, 0x8f420000, 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010,
-	0xaf830018, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800,
-	0x261058c0, 0x3c05000a, 0x02002021, 0x03452821, 0xafbf0014, 0x0e0015b0,
-	0x2406000a, 0x96020002, 0x9603001e, 0x3042000f, 0x24420003, 0x00431804,
-	0x24027fff, 0x0043102b, 0xaf830014, 0x10400004, 0x00000000, 0x0000000d,
-	0x00000000, 0x24000043, 0x0e00155a, 0x00000000, 0x8fbf0014, 0x8fb00010,
-	0x03e00008, 0x27bd0018, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff,
-	0x24a50004, 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000,
-	0x0a0015c1, 0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004,
-	0x00a01021, 0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c036000,
-	0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582, 0x00042302, 0x308403ff,
-	0x00052d82, 0x00441026, 0x0002102b, 0x0005282b, 0x00451025, 0x1440000d,
-	0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c, 0xaf420030, 0x00000000,
-	0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030,
-	0x0000000d, 0x03e00008, 0x00000000, 0x3c020050, 0x34420004, 0xaf440038,
-	0xaf45003c, 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020,
-	0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008, 0x00000000, 0x00000000};
+static u8 bnx2_COM_b06FwText[] = {
+	0x1f, 0x8b, 0x08, 0x08, 0x09, 0x83, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5b, 0x7d, 0x6c,
+	0x5b, 0xd7, 0x75, 0x3f, 0xef, 0xf1, 0x51, 0x7a, 0x96, 0x68, 0xf9, 0x99,
+	0x7e, 0x96, 0x59, 0x4f, 0xb1, 0x49, 0xf1, 0xc9, 0xd2, 0x62, 0x2d, 0x63,
+	0x34, 0x35, 0xd1, 0x3a, 0x26, 0x66, 0x48, 0xda, 0x71, 0x36, 0x67, 0xa0,
+	0x1d, 0x05, 0x51, 0x51, 0xaf, 0xd0, 0x48, 0xd9, 0xcd, 0xb2, 0x0c, 0x73,
+	0x96, 0xb4, 0x70, 0xbc, 0xb4, 0xa1, 0x25, 0x79, 0xf5, 0x06, 0x45, 0xcf,
+	0xb3, 0x34, 0x39, 0xc0, 0x82, 0x41, 0x10, 0x9d, 0x3a, 0x7f, 0x30, 0xa5,
+	0xed, 0x7c, 0x19, 0xe8, 0x12, 0x29, 0xb2, 0x93, 0xb5, 0x43, 0xd0, 0xa6,
+	0x68, 0xff, 0xe8, 0x8a, 0x6e, 0x30, 0x52, 0x0c, 0xf3, 0x3a, 0xa0, 0x30,
+	0xfa, 0xc7, 0xe6, 0x2d, 0x1f, 0xdc, 0xef, 0xdc, 0x77, 0x1f, 0xf9, 0x48,
+	0x51, 0x96, 0x1c, 0x34, 0x5d, 0xb7, 0x99, 0x80, 0xf0, 0xde, 0xbd, 0xf7,
+	0xbc, 0x7b, 0xcf, 0x3d, 0xdf, 0xe7, 0xdc, 0xab, 0x5f, 0x53, 0xa9, 0x85,
+	0xe4, 0x6f, 0x2d, 0xfe, 0xc2, 0x7f, 0xf4, 0xc7, 0xb9, 0xdb, 0x3e, 0x7d,
+	0x5b, 0x1f, 0x5e, 0x07, 0x54, 0xdd, 0xaf, 0x72, 0xbf, 0x0f, 0x7f, 0x26,
+	0xfe, 0xfa, 0xe4, 0x7b, 0xa3, 0x9f, 0x81, 0xbf, 0x2b, 0x18, 0x1c, 0xfe,
+	0x09, 0x91, 0xb2, 0x0c, 0x8c, 0xf7, 0x57, 0x2e, 0x5f, 0x7f, 0x9c, 0x17,
+	0x0e, 0xaf, 0x62, 0x9e, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf,
+	0x9b, 0xbf, 0x9b, 0xbf, 0x9b, 0xbf, 0xff, 0x3f, 0x3f, 0x9f, 0x13, 0x72,
+	0x88, 0x98, 0x85, 0xff, 0x48, 0x57, 0xe3, 0x89, 0xa1, 0xa4, 0x45, 0xba,
+	0x2f, 0x7e, 0x65, 0x28, 0x67, 0x11, 0x25, 0x8a, 0xdb, 0xc3, 0x29, 0xfa,
+	0xb0, 0x9c, 0x37, 0x35, 0xe2, 0xfe, 0x5b, 0xe2, 0x1f, 0x3c, 0xfd, 0xfa,
+	0x9d, 0x91, 0xab, 0xb3, 0x3e, 0xd2, 0x8d, 0xf8, 0xcb, 0xba, 0xb1, 0x8d,
+	0xf4, 0x0e, 0x7c, 0xf3, 0x5c, 0xf7, 0x7f, 0xa8, 0xd4, 0xe6, 0xce, 0x75,
+	0xa5, 0xfc, 0x7a, 0x37, 0xe5, 0x37, 0xc7, 0x75, 0x52, 0xe3, 0x5d, 0x3f,
+	0x48, 0xfa, 0x8c, 0x61, 0x5f, 0xdc, 0xa0, 0xf9, 0x12, 0x65, 0x0e, 0x4c,
+	0xf0, 0x1a, 0xb1, 0x75, 0xf7, 0x62, 0x2e, 0x2d, 0x3e, 0x3c, 0xf4, 0x67,
+	0xd6, 0xd3, 0x65, 0xd5, 0xb2, 0x7a, 0xe6, 0x28, 0x30, 0xf0, 0x7c, 0x3f,
+	0xc6, 0x8b, 0x91, 0x1e, 0xa2, 0x3b, 0x49, 0xb5, 0xf2, 0x01, 0x9f, 0xa5,
+	0x53, 0xb2, 0x64, 0x51, 0xaa, 0x44, 0xf4, 0x77, 0x45, 0x85, 0x9e, 0xb7,
+	0xda, 0x69, 0xae, 0xf7, 0x83, 0x72, 0x02, 0xb8, 0xbc, 0x6d, 0x0d, 0x0f,
+	0x8d, 0x5b, 0x3c, 0x57, 0x7c, 0x9d, 0x83, 0x6f, 0x6f, 0x5b, 0xce, 0xd2,
+	0x68, 0xb4, 0xc8, 0x7d, 0xbd, 0x2d, 0xdc, 0xe7, 0x8f, 0x3f, 0x1c, 0x7c,
+	0xde, 0x0a, 0xc8, 0xbe, 0x1f, 0xa5, 0x92, 0x98, 0x6f, 0xac, 0xc8, 0xb0,
+	0xcf, 0xde, 0x91, 0xb3, 0x4c, 0xd9, 0x6f, 0xc5, 0x93, 0x56, 0x08, 0xfd,
+	0x1d, 0x72, 0x2c, 0xbd, 0x2e, 0x67, 0x59, 0x72, 0xac, 0x88, 0x6f, 0x7a,
+	0x65, 0xff, 0x3b, 0xa9, 0x9c, 0x15, 0x93, 0xfd, 0x57, 0x93, 0x49, 0xab,
+	0x5f, 0xf6, 0x1f, 0xbe, 0x2b, 0x67, 0xc5, 0x65, 0xff, 0xf7, 0x81, 0x8b,
+	0x41, 0xc7, 0x8a, 0x61, 0xfc, 0x25, 0x30, 0xfe, 0x9a, 0x41, 0x6d, 0x19,
+	0x8c, 0x61, 0xef, 0xb6, 0x4e, 0x97, 0x7d, 0x21, 0x7a, 0xbd, 0xfb, 0x32,
+	0x68, 0x63, 0xd0, 0xd9, 0x12, 0x29, 0x99, 0xee, 0x10, 0x68, 0x62, 0xd2,
+	0xb9, 0x52, 0x2b, 0xf9, 0x4e, 0xfa, 0xb0, 0xe7, 0xcf, 0x51, 0xd6, 0xd4,
+	0x69, 0xfd, 0x8c, 0x42, 0x9d, 0x7d, 0x6b, 0x28, 0x61, 0xe4, 0x29, 0xd5,
+	0x8d, 0x28, 0x6e, 0xd2, 0x24, 0x6d, 0x66, 0x71, 0xbd, 0x8a, 0x1e, 0x95,
+	0x22, 0xa1, 0x2c, 0x28, 0x3c, 0x72, 0xfa, 0x5d, 0x8e, 0x39, 0xb1, 0x26,
+	0xff, 0x85, 0x29, 0x35, 0x71, 0x2b, 0x0d, 0x1b, 0x8c, 0x0f, 0x80, 0x05,
+	0x1f, 0x74, 0x25, 0x79, 0x2a, 0x44, 0xc7, 0xec, 0x80, 0x92, 0x3a, 0x75,
+	0x37, 0x25, 0x63, 0x64, 0xaa, 0xd4, 0x25, 0xbe, 0x2d, 0x14, 0x43, 0x34,
+	0x6e, 0x93, 0x92, 0xb4, 0x99, 0x5e, 0xed, 0x18, 0x6f, 0x13, 0xb0, 0xe8,
+	0xeb, 0xf0, 0x51, 0x97, 0x91, 0x22, 0x9d, 0x71, 0x46, 0x7f, 0x50, 0x49,
+	0x8b, 0x39, 0x44, 0x7f, 0x78, 0x8c, 0x02, 0x74, 0xba, 0x68, 0x4a, 0xd8,
+	0x72, 0x39, 0x19, 0x33, 0x00, 0x07, 0xda, 0xd9, 0x26, 0x0d, 0xe3, 0x39,
+	0x6a, 0xf3, 0xfa, 0x21, 0xc8, 0xcc, 0xb7, 0x87, 0xb2, 0xd3, 0x62, 0xbe,
+	0xb0, 0x2f, 0xce, 0xf3, 0x75, 0x00, 0xee, 0x1d, 0xe0, 0xa5, 0x90, 0x26,
+	0x78, 0x95, 0xa0, 0xec, 0x84, 0x02, 0x79, 0xc2, 0x53, 0xd0, 0x2d, 0x0d,
+	0xfc, 0x35, 0xb2, 0xfa, 0x14, 0xca, 0x59, 0x9b, 0x28, 0x6f, 0xa0, 0x5d,
+	0xbc, 0xa0, 0x26, 0xed, 0x66, 0x4a, 0x69, 0x61, 0xec, 0x5f, 0xc8, 0x0a,
+	0x8d, 0xe1, 0x1b, 0xd5, 0x62, 0x98, 0x9f, 0x61, 0xef, 0xc3, 0x82, 0xfe,
+	0x4d, 0xf1, 0xfd, 0x74, 0x69, 0x22, 0xaf, 0x26, 0x4b, 0xed, 0xe4, 0x9b,
+	0x89, 0x40, 0x9a, 0xc7, 0xd5, 0xd4, 0x19, 0x8d, 0xfc, 0x93, 0x0a, 0x41,
+	0x3e, 0x0c, 0x5f, 0xfc, 0xb8, 0xba, 0xb3, 0x74, 0x41, 0x4d, 0x95, 0xf8,
+	0x1b, 0xc0, 0x16, 0x55, 0xd0, 0x96, 0xdf, 0xb7, 0x83, 0x96, 0x34, 0xac,
+	0xc6, 0x75, 0x3d, 0x51, 0x64, 0x99, 0xe5, 0x6f, 0xc1, 0x0f, 0xec, 0xe5,
+	0x9c, 0x0d, 0xfe, 0x08, 0x7e, 0x85, 0xc1, 0xaf, 0x6f, 0x82, 0x5f, 0xfd,
+	0xe0, 0x53, 0x8c, 0xde, 0x28, 0xf5, 0xd2, 0x6b, 0xa5, 0x1e, 0x7a, 0x15,
+	0x32, 0xf9, 0x4a, 0x29, 0x4c, 0x2f, 0x97, 0x3a, 0xe8, 0xa5, 0x52, 0x88,
+	0xce, 0x0b, 0x1e, 0xa6, 0x21, 0xff, 0x82, 0xaf, 0xfa, 0x26, 0xf0, 0xa4,
+	0x1d, 0x3c, 0x59, 0x0f, 0x79, 0xd9, 0x08, 0xf9, 0x9b, 0xee, 0xd6, 0x69,
+	0xaa, 0x9b, 0x12, 0x41, 0xf4, 0x6f, 0x89, 0x6b, 0x82, 0x4e, 0x1a, 0xc6,
+	0xc7, 0x26, 0xfc, 0x94, 0x32, 0x4e, 0xd3, 0x7b, 0x93, 0x1a, 0x8d, 0x95,
+	0xa6, 0x36, 0x3a, 0x7c, 0xe3, 0xf6, 0x2c, 0x5d, 0x44, 0x5f, 0xca, 0x98,
+	0xa5, 0x4b, 0xdb, 0x54, 0x1a, 0x9d, 0xfe, 0x1b, 0x4a, 0x9e, 0x39, 0x4d,
+	0x3f, 0xfe, 0x3a, 0x51, 0x06, 0x34, 0x51, 0xfb, 0x7e, 0x5a, 0x4e, 0x18,
+	0xa0, 0x45, 0x5f, 0xaf, 0x90, 0x08, 0xb5, 0x8f, 0x79, 0x19, 0x86, 0xae,
+	0x68, 0x4a, 0xca, 0x7e, 0x01, 0xfa, 0xd2, 0xaa, 0x24, 0xa7, 0x88, 0x72,
+	0x53, 0x65, 0xca, 0xc5, 0xfc, 0xf4, 0x98, 0x51, 0xa6, 0x74, 0xac, 0x89,
+	0xbe, 0x68, 0xb4, 0xd3, 0x68, 0xef, 0x6f, 0xf8, 0xdc, 0x5c, 0x65, 0xba,
+	0xd4, 0x8f, 0x77, 0xee, 0x23, 0x9a, 0x12, 0xef, 0x4e, 0x7f, 0xbe, 0xe4,
+	0xa7, 0x84, 0x99, 0x0f, 0x69, 0xf4, 0x8e, 0xcf, 0xc1, 0x29, 0xe1, 0x8e,
+	0x81, 0x57, 0xc3, 0xb0, 0x0f, 0x8e, 0x0c, 0x66, 0x27, 0xd6, 0x5c, 0x4b,
+	0x88, 0x6e, 0xc0, 0x0b, 0xd9, 0xd3, 0x18, 0x8f, 0x61, 0x25, 0x6e, 0x52,
+	0xa7, 0xd0, 0x8d, 0x7e, 0xc0, 0x0c, 0x28, 0xfb, 0x4a, 0xcc, 0x6b, 0xbc,
+	0x17, 0x19, 0xd7, 0xcd, 0x80, 0xd5, 0xf0, 0x4c, 0x48, 0x9c, 0xbd, 0x78,
+	0xf2, 0x5c, 0x8c, 0x27, 0x3f, 0x7f, 0xcf, 0x83, 0xe7, 0xe7, 0x2b, 0xef,
+	0x53, 0x9e, 0xf7, 0x7c, 0xe9, 0x4f, 0x03, 0x0e, 0x7e, 0x4c, 0xcf, 0x01,
+	0x1a, 0x9d, 0x38, 0x2c, 0xd7, 0xc2, 0x7b, 0x91, 0xd7, 0x38, 0x0d, 0x3a,
+	0x09, 0xc8, 0x15, 0xd6, 0x3a, 0xec, 0x59, 0xeb, 0x49, 0xcf, 0x5a, 0x4f,
+	0x7a, 0xd6, 0xca, 0x83, 0xb6, 0xb4, 0x4e, 0xb5, 0xfc, 0xd0, 0x51, 0xee,
+	0x39, 0x8e, 0x39, 0x9f, 0x03, 0x5f, 0xbe, 0x0a, 0x98, 0x38, 0x2d, 0xda,
+	0xa0, 0xc7, 0x94, 0x46, 0x7b, 0x4d, 0x7e, 0x7f, 0xb1, 0xd5, 0xc1, 0x8b,
+	0xdf, 0x2f, 0x48, 0x9c, 0x5a, 0x1d, 0xb8, 0xd2, 0x15, 0xa1, 0xff, 0xf3,
+	0x25, 0xd6, 0x4f, 0x8a, 0xf9, 0x2c, 0x3a, 0x94, 0x8e, 0xb5, 0xd3, 0x98,
+	0xa1, 0xc4, 0x46, 0x7b, 0x9a, 0x99, 0x8e, 0x09, 0xd5, 0x6a, 0x85, 0x0e,
+	0x50, 0x58, 0x65, 0xdb, 0x25, 0xf0, 0x7b, 0x49, 0xe2, 0x61, 0x70, 0x3b,
+	0xa3, 0x5a, 0xc1, 0xba, 0x7e, 0x96, 0xdf, 0x57, 0xf0, 0xce, 0x32, 0x9c,
+	0xd4, 0x9c, 0xb5, 0x5f, 0x45, 0x9b, 0xed, 0xce, 0x66, 0xd9, 0x76, 0xc7,
+	0xff, 0xa0, 0xa9, 0xb6, 0xfd, 0x05, 0xb3, 0xb6, 0xed, 0xea, 0x82, 0xd7,
+	0x66, 0xf1, 0xde, 0xc2, 0xe4, 0xb3, 0x58, 0x8e, 0xfc, 0xc0, 0x35, 0x06,
+	0x3d, 0x6c, 0x96, 0x38, 0x7c, 0x4b, 0xe2, 0x00, 0x5c, 0x01, 0x37, 0x5a,
+	0xe2, 0x6f, 0x04, 0x4b, 0xea, 0xda, 0x4c, 0x43, 0xf7, 0x7d, 0xad, 0x18,
+	0xbf, 0xec, 0xe3, 0x75, 0xdc, 0x27, 0x29, 0x69, 0xe8, 0xc9, 0xd8, 0xb4,
+	0x46, 0xd9, 0xd8, 0x26, 0x21, 0xd7, 0xd9, 0x58, 0xd5, 0x06, 0x8c, 0x4e,
+	0xd4, 0xdb, 0x00, 0xfe, 0x8e, 0x6d, 0x80, 0xa3, 0xfb, 0x63, 0xd3, 0x6c,
+	0x0b, 0x1c, 0xdd, 0x3f, 0x36, 0xc1, 0x36, 0x41, 0xcc, 0x09, 0xfd, 0x67,
+	0x3b, 0xe0, 0xda, 0x00, 0xfe, 0x86, 0x6d, 0x80, 0x0f, 0xf2, 0xcd, 0xf3,
+	0xb9, 0x6b, 0x8f, 0xd7, 0xcd, 0x3b, 0xce, 0xb6, 0x45, 0xd9, 0xd9, 0xcd,
+	0x30, 0xc7, 0xb1, 0x76, 0x80, 0x0a, 0xd3, 0xcc, 0xc3, 0x48, 0xe8, 0x08,
+	0x1d, 0x17, 0x36, 0xef, 0xf4, 0x04, 0x25, 0x0e, 0x9e, 0x18, 0xa0, 0x34,
+	0x6c, 0xc0, 0xdc, 0xc4, 0xb5, 0x32, 0xf8, 0x78, 0x47, 0x13, 0x59, 0xb0,
+	0x75, 0xf0, 0x93, 0xfd, 0x7e, 0xf2, 0xc5, 0xe3, 0x90, 0xb7, 0x98, 0xf0,
+	0x5d, 0xd5, 0x9f, 0xa6, 0xed, 0xaa, 0x69, 0x37, 0xc1, 0x3f, 0x62, 0xde,
+	0xfe, 0x98, 0x90, 0x4d, 0xef, 0x2f, 0x09, 0x1b, 0x94, 0x8c, 0x7d, 0x08,
+	0xf9, 0x75, 0x69, 0xe4, 0xea, 0x1f, 0xdb, 0xfa, 0x2b, 0x1e, 0x1f, 0xb2,
+	0x05, 0x76, 0xdf, 0x84, 0x3c, 0xb9, 0x76, 0x9f, 0xed, 0x71, 0x88, 0x6d,
+	0x26, 0xf4, 0x8d, 0x6d, 0x70, 0x80, 0xd4, 0x19, 0x4d, 0xda, 0x69, 0x5d,
+	0xda, 0xe9, 0x00, 0x6c, 0x34, 0xb7, 0x0d, 0xd9, 0x36, 0x45, 0x1b, 0xf6,
+	0x1a, 0xf6, 0x70, 0x77, 0x3a, 0x35, 0xc1, 0xfe, 0x10, 0xbe, 0x7b, 0x86,
+	0x75, 0xf8, 0xdb, 0x43, 0x23, 0xd3, 0xc2, 0x07, 0xb0, 0xff, 0x80, 0x65,
+	0x66, 0x1b, 0xce, 0xb6, 0x1c, 0xfb, 0x2e, 0x62, 0xdd, 0x8a, 0xad, 0x64,
+	0x39, 0xf1, 0xe2, 0xc5, 0x38, 0xad, 0x21, 0xf5, 0xa4, 0x43, 0x6b, 0x35,
+	0xfe, 0xa8, 0x46, 0x2d, 0x4c, 0x63, 0xc6, 0x7f, 0x2b, 0x70, 0xe6, 0x7d,
+	0xfd, 0x4f, 0xe0, 0xcc, 0xeb, 0xd6, 0xe3, 0x4d, 0x7a, 0x6b, 0xfc, 0xac,
+	0xfe, 0xf0, 0x33, 0xa4, 0x37, 0xc7, 0xcf, 0xd2, 0xbf, 0x58, 0x74, 0x9f,
+	0x0e, 0x3f, 0xdb, 0xad, 0xc0, 0xcf, 0x16, 0xa1, 0xef, 0x53, 0x3a, 0x1d,
+	0x3c, 0x15, 0xc9, 0xfc, 0x2b, 0x45, 0x61, 0x3f, 0x76, 0xd0, 0xc8, 0x94,
+	0x42, 0x7a, 0x17, 0xb5, 0xc3, 0x7f, 0xf4, 0x37, 0x61, 0xfe, 0x5d, 0x44,
+	0x9b, 0x1d, 0xbf, 0xd9, 0x15, 0x1e, 0x05, 0xff, 0xd3, 0x2f, 0x7e, 0x05,
+	0xdf, 0x3c, 0x4d, 0x07, 0xa7, 0x0e, 0x2b, 0x39, 0xfb, 0x08, 0xe0, 0x97,
+	0x83, 0xd5, 0x01, 0x9b, 0x07, 0xec, 0x97, 0x31, 0xef, 0xd3, 0xa4, 0xdf,
+	0x1e, 0x19, 0x48, 0x28, 0xc0, 0xe3, 0x45, 0x01, 0x2f, 0x7d, 0x71, 0x97,
+	0xb1, 0x53, 0xf0, 0x3f, 0x40, 0xef, 0x15, 0x2f, 0x80, 0xbe, 0xbd, 0xf0,
+	0x39, 0x91, 0x67, 0x61, 0x93, 0xe1, 0x8f, 0x22, 0x57, 0x31, 0x2d, 0x7c,
+	0x11, 0x29, 0x0f, 0x76, 0xa7, 0x41, 0xef, 0x38, 0xfc, 0xd3, 0x00, 0xfc,
+	0x53, 0x0c, 0xbe, 0xa9, 0x07, 0x7e, 0xc9, 0x82, 0x5f, 0x0a, 0x83, 0x1f,
+	0x06, 0xcd, 0xc2, 0x47, 0xcd, 0x42, 0xfe, 0xe7, 0x66, 0x48, 0x19, 0x04,
+	0xad, 0xcf, 0xc1, 0x3f, 0x26, 0x63, 0x77, 0x42, 0xcf, 0x22, 0x17, 0x66,
+	0xd5, 0x41, 0xca, 0xc1, 0x9f, 0x77, 0x6e, 0x8b, 0x62, 0xbd, 0x26, 0x4a,
+	0x84, 0x5c, 0x1d, 0xe5, 0xdf, 0x7e, 0x85, 0xac, 0x7f, 0x06, 0xef, 0x22,
+	0x61, 0xa2, 0x3d, 0x94, 0xb5, 0xa3, 0x46, 0xa7, 0xda, 0x03, 0x18, 0x6e,
+	0x87, 0x95, 0x03, 0x53, 0x11, 0x05, 0xfb, 0x03, 0xcd, 0x27, 0x60, 0xeb,
+	0xcb, 0x34, 0x1e, 0x63, 0x3d, 0x29, 0xd3, 0xf3, 0xb1, 0xc8, 0x40, 0x9e,
+	0x5a, 0xe9, 0x98, 0x39, 0x21, 0x7c, 0xbc, 0x16, 0x3f, 0x21, 0x74, 0x2c,
+	0x67, 0xe1, 0x59, 0xec, 0x54, 0xb2, 0x53, 0xbc, 0x7e, 0x14, 0x5a, 0xee,
+	0xc7, 0x93, 0xe7, 0x07, 0xdd, 0xfa, 0x49, 0x39, 0xd8, 0x9d, 0x87, 0x77,
+	0x88, 0x18, 0x8b, 0x58, 0x39, 0x35, 0x11, 0x0d, 0x45, 0x55, 0x8d, 0x86,
+	0x35, 0x85, 0x46, 0x61, 0x6f, 0xd2, 0xb1, 0xff, 0x2c, 0x1f, 0x33, 0x79,
+	0xbc, 0x99, 0xbe, 0x2a, 0xfc, 0x0d, 0xd6, 0x2e, 0x4c, 0x63, 0x5d, 0x3f,
+	0xf8, 0xcb, 0xeb, 0xf2, 0x3c, 0x68, 0xc3, 0xf6, 0x6b, 0x56, 0xe4, 0xd9,
+	0x3c, 0xed, 0x00, 0x6d, 0xd9, 0x66, 0xc1, 0x3e, 0x0c, 0x60, 0xed, 0x5e,
+	0xd8, 0x4f, 0x3c, 0x93, 0xbd, 0x1c, 0x07, 0x05, 0x68, 0xd8, 0x64, 0x79,
+	0xd4, 0xe5, 0x98, 0xe9, 0x19, 0xf3, 0xcb, 0xb1, 0x20, 0xfe, 0xe0, 0x7f,
+	0x4d, 0x96, 0x19, 0x6e, 0x73, 0x4c, 0xc6, 0x34, 0x09, 0xd3, 0xdc, 0x64,
+	0x02, 0x34, 0x8b, 0x9c, 0x4d, 0x10, 0xd3, 0x0c, 0x46, 0x7b, 0x7f, 0x82,
+	0xbe, 0x64, 0xaf, 0xf7, 0x3b, 0xb6, 0xb0, 0x55, 0x49, 0xc1, 0x17, 0xa8,
+	0x56, 0x0b, 0x7c, 0x45, 0x98, 0x5e, 0x15, 0xb0, 0x64, 0xa8, 0xf1, 0x68,
+	0xe8, 0x4b, 0x74, 0xab, 0xb0, 0x11, 0x09, 0xc3, 0x4b, 0xe3, 0xff, 0x52,
+	0xc9, 0x72, 0xbf, 0x69, 0xa5, 0xec, 0x20, 0xf3, 0x89, 0xd7, 0x33, 0x68,
+	0xae, 0xe4, 0xbc, 0xfb, 0x10, 0xa3, 0x16, 0x60, 0x6b, 0xce, 0x4f, 0xaa,
+	0xf4, 0xf8, 0x1d, 0xf0, 0x65, 0xb1, 0x6d, 0x58, 0xcb, 0xc4, 0x78, 0x1e,
+	0x6d, 0x15, 0x6d, 0xe8, 0x99, 0x11, 0x02, 0x8f, 0xb9, 0x9f, 0xe1, 0x4c,
+	0xfc, 0xbd, 0xcf, 0xb1, 0x75, 0x3e, 0xab, 0xde, 0x4a, 0x14, 0x64, 0x7a,
+	0xc5, 0x40, 0x2b, 0xcb, 0x50, 0xd5, 0x6d, 0xc2, 0x5f, 0x3b, 0xb6, 0xc4,
+	0x82, 0x2e, 0xc2, 0xe6, 0xf6, 0x79, 0x75, 0x91, 0xe3, 0x09, 0x57, 0x17,
+	0x23, 0xa1, 0x84, 0x0a, 0x5b, 0xdc, 0xa7, 0xd1, 0x09, 0xd1, 0x56, 0x28,
+	0x31, 0x18, 0x09, 0x2d, 0xa8, 0x1c, 0x4b, 0x33, 0x6c, 0x18, 0xf1, 0x4a,
+	0x40, 0xc2, 0x22, 0x9e, 0xb3, 0xdd, 0x98, 0x30, 0x84, 0x7e, 0x53, 0xf4,
+	0x1f, 0xab, 0xe8, 0xa8, 0x13, 0xff, 0xa9, 0x88, 0x11, 0x0b, 0x88, 0x11,
+	0x53, 0x42, 0x47, 0x8d, 0x04, 0x72, 0x04, 0xd0, 0xdc, 0xd1, 0xcf, 0x42,
+	0x91, 0x71, 0xc9, 0xb1, 0x5c, 0x0e, 0x00, 0x99, 0x13, 0x8e, 0x7d, 0xa4,
+	0x3c, 0xc7, 0x91, 0xa3, 0xea, 0x53, 0x34, 0x5c, 0x60, 0x3f, 0x8e, 0x3f,
+	0x9b, 0x6d, 0x2d, 0xec, 0xa3, 0xf0, 0xc5, 0x51, 0xf0, 0x39, 0x0f, 0x1a,
+	0xac, 0x97, 0x74, 0xdd, 0x4f, 0x07, 0xec, 0x3d, 0xa0, 0x79, 0x9c, 0x46,
+	0x4e, 0x8d, 0xb0, 0xcc, 0xf6, 0x14, 0x28, 0xd2, 0x73, 0x8c, 0xb6, 0x1b,
+	0x73, 0x2c, 0xdf, 0x83, 0xe5, 0x1d, 0xe0, 0x85, 0xd0, 0x51, 0xc8, 0x20,
+	0x65, 0x0b, 0x23, 0xf4, 0x58, 0x89, 0xfb, 0xf2, 0xa0, 0x1d, 0xe2, 0xda,
+	0xfe, 0xfd, 0x52, 0xce, 0x31, 0x9f, 0xe6, 0xce, 0x37, 0x22, 0xe7, 0x63,
+	0x38, 0x86, 0xe1, 0x6f, 0xaa, 0xf3, 0xee, 0x14, 0x3c, 0x8d, 0x18, 0x5d,
+	0x6a, 0x79, 0x87, 0x1f, 0xe3, 0xcf, 0xf7, 0xf3, 0x3b, 0xe6, 0x81, 0xef,
+	0x6f, 0xb6, 0xf6, 0x00, 0x76, 0x10, 0x73, 0xfa, 0xa9, 0xb3, 0xdd, 0xc5,
+	0x37, 0x81, 0xb5, 0xd9, 0xcf, 0x31, 0x9f, 0x1f, 0xa1, 0xec, 0xa9, 0x7c,
+	0x8f, 0x0a, 0x19, 0x9b, 0xcd, 0x28, 0xe4, 0xb7, 0x1e, 0xa6, 0xdc, 0xa9,
+	0xa3, 0x6c, 0x37, 0x40, 0xab, 0x3d, 0xb4, 0x6b, 0x22, 0xd2, 0x73, 0x80,
+	0x34, 0xb1, 0xce, 0x5b, 0x24, 0xe8, 0x1f, 0x9b, 0x15, 0xbe, 0x20, 0x43,
+	0xe9, 0x89, 0xed, 0xa1, 0x4b, 0xe8, 0x1b, 0x1e, 0x8c, 0x84, 0x17, 0xe8,
+	0x09, 0xd0, 0xe5, 0x23, 0xf8, 0x22, 0xab, 0x67, 0x0c, 0x3a, 0x84, 0x9c,
+	0x0a, 0xeb, 0x8f, 0x4a, 0xda, 0xe0, 0xbb, 0xcc, 0x51, 0xd0, 0x8f, 0xf2,
+	0x0e, 0x4d, 0x99, 0x9e, 0x4c, 0xcb, 0xaf, 0xc0, 0xf6, 0x1c, 0x11, 0xb1,
+	0x4b, 0x56, 0xd0, 0xee, 0xd2, 0x06, 0x47, 0x0e, 0x60, 0x8b, 0x30, 0xef,
+	0xe5, 0x41, 0x85, 0xb6, 0x20, 0x4e, 0x3f, 0x24, 0x78, 0xeb, 0xa3, 0x7d,
+	0x66, 0xd4, 0xd8, 0x47, 0xf3, 0x7e, 0x27, 0x56, 0xc0, 0x3c, 0x3d, 0xf7,
+	0x60, 0x0f, 0x90, 0x53, 0xfb, 0xeb, 0xeb, 0xa8, 0x2d, 0x12, 0x4e, 0xa8,
+	0x09, 0xfa, 0x93, 0xd2, 0xdd, 0xe4, 0xe8, 0x77, 0x2b, 0xdb, 0x7e, 0xf0,
+	0xb0, 0xd3, 0x69, 0x5b, 0x78, 0x16, 0x3a, 0xb1, 0x1e, 0xe3, 0xfe, 0xac,
+	0xc0, 0x7d, 0x84, 0xba, 0xa1, 0x6b, 0x22, 0x8f, 0x39, 0x51, 0x8b, 0x17,
+	0xf3, 0xbc, 0x9e, 0xcf, 0x5f, 0xc6, 0x3c, 0xdc, 0xcf, 0x70, 0x78, 0x2f,
+	0x3c, 0x41, 0x23, 0x90, 0xc7, 0x5c, 0x7f, 0x57, 0x68, 0x0c, 0xdf, 0xa4,
+	0x4a, 0x4d, 0x74, 0x54, 0xe3, 0xf1, 0x48, 0x38, 0xaf, 0x1e, 0x42, 0xdc,
+	0xf3, 0xb8, 0xea, 0xb7, 0x7e, 0xe6, 0x67, 0xbf, 0xe3, 0xb7, 0xae, 0x29,
+	0xd5, 0xb9, 0x10, 0x87, 0x8a, 0xdc, 0x60, 0x41, 0x19, 0x2c, 0x5d, 0x52,
+	0x92, 0x85, 0x6b, 0x4a, 0xaa, 0xc4, 0x30, 0x8e, 0xce, 0x67, 0xcf, 0x74,
+	0x82, 0x4e, 0x1f, 0x89, 0xef, 0xe6, 0x7a, 0x8f, 0x50, 0xea, 0xd4, 0xad,
+	0x94, 0x9e, 0xe6, 0xbc, 0x34, 0x02, 0x7c, 0x3f, 0x2a, 0xe7, 0x62, 0x41,
+	0xca, 0x9d, 0xe1, 0x31, 0xb6, 0x5f, 0xd6, 0xd5, 0x45, 0x1f, 0xef, 0x9f,
+	0xf9, 0x6f, 0x52, 0xc1, 0x7e, 0x53, 0xd2, 0x8f, 0xdf, 0x7d, 0x9c, 0x93,
+	0xe1, 0xf7, 0x6f, 0x86, 0xd3, 0xb7, 0x95, 0x16, 0x36, 0xdc, 0xc8, 0x3e,
+	0x57, 0xb3, 0xc7, 0x47, 0x7d, 0x7e, 0x6b, 0x7b, 0x13, 0xb5, 0x84, 0x80,
+	0xc3, 0x4a, 0x7b, 0x64, 0x98, 0x5f, 0x87, 0x1c, 0xb0, 0x4d, 0xd9, 0x0d,
+	0x7e, 0x5a, 0x6c, 0xc3, 0x60, 0x93, 0x76, 0x53, 0xae, 0xc4, 0xb2, 0x1d,
+	0x35, 0x32, 0x90, 0xb1, 0x34, 0x75, 0xb1, 0x1e, 0xb9, 0xba, 0x07, 0xdb,
+	0x9d, 0x87, 0xed, 0x46, 0x3c, 0x64, 0x53, 0xbe, 0x29, 0xce, 0x36, 0xbc,
+	0x0b, 0xb2, 0x85, 0xbe, 0x62, 0x55, 0x17, 0x77, 0x2d, 0xc1, 0x5d, 0x5b,
+	0xc2, 0xa3, 0x02, 0xd5, 0xe2, 0x3f, 0x4b, 0x8c, 0xff, 0x5f, 0x00, 0xff,
+	0xcf, 0x01, 0x7f, 0xc6, 0xa9, 0x31, 0xfe, 0x3b, 0x2b, 0xf8, 0x33, 0x0c,
+	0xfc, 0x1c, 0x64, 0xf1, 0x0d, 0xe8, 0xe2, 0x6b, 0x36, 0x7c, 0x9d, 0x0d,
+	0xff, 0x67, 0xc3, 0xdf, 0xd9, 0xf0, 0x8b, 0x36, 0x7c, 0x1e, 0xf6, 0x74,
+	0x0e, 0x36, 0xe9, 0xac, 0x9d, 0x34, 0x58, 0x9f, 0x92, 0x31, 0xf6, 0x9d,
+	0xbb, 0x65, 0xde, 0x1d, 0x92, 0x71, 0xf7, 0xa7, 0x64, 0x2c, 0x7b, 0x00,
+	0xb1, 0xec, 0x66, 0x1a, 0xed, 0xe1, 0x9c, 0xa4, 0x05, 0xcf, 0x75, 0x78,
+	0x22, 0x6e, 0xed, 0x49, 0x48, 0xbd, 0xfc, 0x0c, 0x62, 0x5c, 0xd8, 0xff,
+	0x1e, 0xe4, 0x37, 0x19, 0xc4, 0x6a, 0x56, 0x1f, 0xc7, 0xe5, 0xb0, 0x65,
+	0xef, 0x37, 0x39, 0x76, 0xfe, 0x2e, 0x19, 0x03, 0xbb, 0xed, 0x56, 0xc0,
+	0xa4, 0xd1, 0xd7, 0x8a, 0x6f, 0x7e, 0x07, 0xb2, 0xdf, 0x86, 0xf6, 0xce,
+	0x3a, 0x18, 0xe4, 0xb3, 0x56, 0x16, 0x7d, 0x11, 0xc0, 0xb4, 0x61, 0x9d,
+	0x0e, 0xb4, 0xf7, 0xa0, 0x7d, 0x8b, 0xb3, 0x8e, 0xf1, 0x2b, 0x68, 0xa7,
+	0xea, 0xbe, 0xd9, 0x8a, 0xbe, 0x4c, 0x5d, 0xdf, 0x9b, 0xe8, 0x4b, 0xa2,
+	0x6f, 0x51, 0x7e, 0x97, 0x47, 0x3b, 0x52, 0x07, 0xb3, 0x88, 0x3e, 0xc6,
+	0xf1, 0x5b, 0x78, 0xde, 0x47, 0xa3, 0x19, 0x8e, 0x03, 0xdc, 0xb1, 0xdc,
+	0x7a, 0x6a, 0xe3, 0xdc, 0xf7, 0x43, 0x21, 0x3b, 0xf3, 0xd2, 0x46, 0xa7,
+	0x27, 0xd8, 0x4f, 0x8c, 0x20, 0xee, 0xe1, 0x71, 0xe1, 0x9c, 0x3c, 0xfd,
+	0x1f, 0x00, 0xf6, 0x61, 0x8c, 0x21, 0x56, 0xb7, 0xcb, 0x4d, 0x8d, 0xc7,
+	0x1f, 0xc5, 0xf8, 0x5f, 0xca, 0x6f, 0x2b, 0x73, 0x03, 0xfe, 0x1b, 0x75,
+	0x7d, 0x6a, 0xb0, 0xb6, 0xbd, 0xd6, 0xf3, 0xbe, 0x4d, 0x5f, 0xfa, 0xfd,
+	0x48, 0x1d, 0xfc, 0xef, 0x6e, 0xa8, 0x6d, 0x3f, 0xc5, 0xdf, 0x20, 0x87,
+	0x70, 0xdb, 0x09, 0xc8, 0x1d, 0xdb, 0xa4, 0xfa, 0x79, 0x3e, 0x6b, 0xd4,
+	0xf6, 0x6d, 0x32, 0x6b, 0xdb, 0x1c, 0x27, 0x31, 0x5c, 0x08, 0xf2, 0xde,
+	0xa1, 0xec, 0xb2, 0x7f, 0x13, 0xe3, 0x61, 0xe5, 0x5e, 0xdb, 0x8b, 0x67,
+	0x48, 0xe6, 0x46, 0xe1, 0x4a, 0xcc, 0x3b, 0x5f, 0x0a, 0x40, 0xae, 0x3e,
+	0x0f, 0x9e, 0x73, 0xdc, 0x53, 0xd5, 0xf1, 0xf7, 0x68, 0x39, 0x1d, 0x67,
+	0x1f, 0xc0, 0x31, 0xfe, 0x36, 0x11, 0x1f, 0xfb, 0xe2, 0x4f, 0x70, 0x0c,
+	0xf6, 0xb4, 0xe3, 0x5b, 0x2c, 0xf8, 0x43, 0xb4, 0x4b, 0x7e, 0xc7, 0x6e,
+	0x22, 0x9f, 0xc8, 0x16, 0xd8, 0x9f, 0xb1, 0x0f, 0x89, 0xc0, 0x4e, 0xb3,
+	0x1f, 0xfd, 0x24, 0x7d, 0xc6, 0x5d, 0xcd, 0x6c, 0xfb, 0x34, 0xeb, 0x05,
+	0xc4, 0x0b, 0x1c, 0xe7, 0xb1, 0xed, 0xc6, 0x7b, 0xd1, 0x8d, 0x57, 0xee,
+	0xd7, 0xc8, 0xaa, 0xfa, 0x11, 0x67, 0x8f, 0x5b, 0x59, 0x37, 0x56, 0xb1,
+	0xef, 0xc6, 0xb6, 0xed, 0xc7, 0x75, 0xb6, 0xe1, 0xb2, 0xb0, 0x0d, 0x0f,
+	0x6a, 0x7e, 0xeb, 0xf7, 0x9b, 0x1d, 0x79, 0x6d, 0x6c, 0x1b, 0xee, 0xad,
+	0xd8, 0x06, 0x57, 0x5e, 0xbd, 0x79, 0xeb, 0x0f, 0xc0, 0x1b, 0x0b, 0xbc,
+	0xa9, 0xaf, 0xd5, 0x70, 0x8e, 0xe2, 0x87, 0x1f, 0xe2, 0x18, 0x91, 0x73,
+	0xd9, 0x18, 0xe5, 0x62, 0x45, 0xc4, 0x6a, 0x91, 0xd9, 0xd9, 0x4a, 0x8e,
+	0xf5, 0x35, 0x69, 0xbb, 0x6b, 0xe2, 0x22, 0x7a, 0xbc, 0x78, 0x09, 0xf8,
+	0x73, 0xbc, 0xa5, 0x49, 0x1b, 0xc1, 0xfd, 0xe3, 0x12, 0x47, 0x7e, 0xe7,
+	0x3a, 0x1e, 0x7c, 0x69, 0xf1, 0x47, 0xe0, 0x15, 0xc7, 0x7d, 0x51, 0x27,
+	0xde, 0xab, 0x89, 0xa9, 0xd7, 0xf8, 0xc9, 0xe2, 0x78, 0x89, 0x61, 0x74,
+	0x19, 0x2f, 0x05, 0x64, 0x5e, 0x63, 0xc8, 0x3c, 0x87, 0x63, 0x6d, 0xae,
+	0xb1, 0xd6, 0xc7, 0x50, 0x0b, 0x43, 0xc1, 0x6d, 0xcc, 0x13, 0x8e, 0xa1,
+	0xda, 0x28, 0x39, 0xe3, 0xc4, 0x50, 0x4e, 0x9d, 0xcd, 0xcd, 0x71, 0x5c,
+	0x5c, 0xd9, 0x0f, 0xef, 0xc0, 0x3e, 0x45, 0x9e, 0x14, 0x74, 0xea, 0x7f,
+	0x1a, 0xec, 0xf6, 0x51, 0xf4, 0x8f, 0xba, 0xfd, 0x9e, 0x5c, 0xc3, 0xc5,
+	0x85, 0x7d, 0xbd, 0x1b, 0xd3, 0xed, 0x96, 0x31, 0x1d, 0x62, 0x18, 0xdb,
+	0xc9, 0xbb, 0xf6, 0x16, 0x33, 0xe8, 0xe3, 0x75, 0x11, 0x1b, 0x12, 0xc7,
+	0x49, 0x90, 0xaf, 0xfd, 0x91, 0x50, 0x58, 0xad, 0xc7, 0xab, 0x75, 0xa1,
+	0x16, 0xaf, 0x41, 0xf1, 0xdd, 0xf8, 0x92, 0xef, 0x48, 0xc4, 0x92, 0xe3,
+	0xf6, 0x10, 0xe8, 0xc5, 0xf8, 0xb9, 0xba, 0xe1, 0xc6, 0xc9, 0x8c, 0xd3,
+	0x3f, 0x82, 0xc6, 0xbb, 0x15, 0xfe, 0x7e, 0xcc, 0xde, 0x2f, 0xe8, 0x96,
+	0x15, 0xb8, 0x0e, 0x7b, 0x70, 0x1d, 0x91, 0xb8, 0xb2, 0x2e, 0xb0, 0x7e,
+	0x78, 0x6b, 0x9a, 0xa6, 0xd8, 0x1b, 0x70, 0x0e, 0xf3, 0xb9, 0xb9, 0x6a,
+	0x2d, 0x0c, 0xf9, 0xb6, 0xc1, 0x1f, 0x02, 0xd7, 0xac, 0x88, 0x43, 0x03,
+	0x0b, 0xf5, 0x34, 0x1c, 0xc7, 0x5a, 0x88, 0xdb, 0x81, 0x8f, 0xcb, 0xf3,
+	0x26, 0x89, 0xcf, 0x37, 0xc5, 0xdc, 0x63, 0xa2, 0x06, 0xea, 0xd3, 0x39,
+	0x77, 0xc9, 0x0a, 0xde, 0x69, 0x92, 0x77, 0x8f, 0x56, 0xf0, 0x73, 0x78,
+	0x1c, 0x90, 0x74, 0xe5, 0xdc, 0x95, 0x75, 0x5a, 0xf0, 0xa7, 0x9d, 0x73,
+	0xd3, 0x41, 0x6a, 0x14, 0x23, 0x2f, 0x0c, 0xa9, 0xdb, 0x1c, 0x3a, 0x3a,
+	0x31, 0xf2, 0xda, 0xba, 0x18, 0xf9, 0xb6, 0x20, 0xc7, 0x5a, 0xc3, 0x50,
+	0x82, 0x79, 0xf8, 0xba, 0x97, 0x6d, 0xc8, 0x36, 0x70, 0x3d, 0x5f, 0x53,
+	0xbb, 0xec, 0x59, 0xa6, 0xd6, 0x1c, 0x20, 0xdf, 0x0c, 0xfb, 0x0e, 0x0b,
+	0x79, 0x06, 0x91, 0x36, 0xc9, 0x3a, 0xcb, 0xbe, 0xbd, 0x1a, 0x67, 0xcf,
+	0x51, 0xa3, 0x18, 0xfb, 0x46, 0xfd, 0xfa, 0x79, 0xbf, 0xdf, 0x3a, 0xac,
+	0x3b, 0x36, 0x73, 0x25, 0xbf, 0xee, 0xc2, 0xed, 0x41, 0x9c, 0xad, 0x50,
+	0x93, 0x55, 0xc0, 0xfe, 0xde, 0xf0, 0x37, 0x5b, 0xae, 0x2e, 0x06, 0x68,
+	0xfd, 0xcc, 0x2d, 0x42, 0x1f, 0x8d, 0xc9, 0xaa, 0x3e, 0x8e, 0x82, 0x37,
+	0x19, 0xa7, 0x06, 0x60, 0xae, 0xa7, 0xeb, 0xd7, 0x0b, 0xc6, 0xed, 0x37,
+	0xfd, 0xaa, 0xe5, 0xca, 0xc0, 0xf5, 0xf2, 0x91, 0x4f, 0xd5, 0xd1, 0xba,
+	0x51, 0x4d, 0xf8, 0x2c, 0xe8, 0x1a, 0x47, 0xde, 0x1d, 0x79, 0x81, 0x10,
+	0x3b, 0x39, 0x79, 0x78, 0x1a, 0xb9, 0x77, 0xe4, 0x02, 0xe7, 0xe3, 0x6e,
+	0x7e, 0xfe, 0x6a, 0x29, 0x72, 0x36, 0x8f, 0x9c, 0x79, 0x1e, 0x39, 0xf9,
+	0xcb, 0xc8, 0xc9, 0xcf, 0x97, 0x7a, 0x41, 0xff, 0x1e, 0x99, 0x8f, 0xb3,
+	0x8e, 0x99, 0x74, 0x11, 0xb9, 0xd3, 0x77, 0x67, 0xd8, 0x46, 0x74, 0xd1,
+	0x3d, 0xc8, 0x35, 0xbe, 0x3f, 0xa9, 0x68, 0x9d, 0x7d, 0x01, 0x5f, 0xc2,
+	0xb8, 0x91, 0x38, 0x71, 0x29, 0x4f, 0x1a, 0xc7, 0x8a, 0x23, 0x4d, 0x7e,
+	0x6b, 0xae, 0x95, 0x5a, 0xf6, 0x2c, 0xcb, 0x93, 0x6a, 0xac, 0xe8, 0xc2,
+	0x19, 0xd4, 0xd9, 0xf7, 0x87, 0x9c, 0xdb, 0xc4, 0x48, 0xe4, 0xd3, 0xeb,
+	0xe8, 0xed, 0x93, 0x65, 0xda, 0x19, 0xbb, 0x56, 0xbe, 0x68, 0xad, 0xa3,
+	0x6c, 0xef, 0x43, 0x32, 0x97, 0x5c, 0x78, 0x28, 0x69, 0xe5, 0x43, 0x3e,
+	0xf7, 0x7c, 0x62, 0x42, 0x47, 0x84, 0xc8, 0xbf, 0x20, 0xcd, 0x0d, 0x20,
+	0x71, 0x6e, 0xd9, 0xfe, 0x02, 0x1f, 0x10, 0xb1, 0x6d, 0x9c, 0x33, 0x03,
+	0xa2, 0xd6, 0xb6, 0xd1, 0xe2, 0x7e, 0x03, 0xfc, 0xbe, 0x8f, 0xe6, 0x90,
+	0x43, 0x14, 0x44, 0x1e, 0xde, 0x0e, 0x78, 0x37, 0x0f, 0xbf, 0x1f, 0xb9,
+	0x01, 0xd3, 0xd8, 0x04, 0xfc, 0x6f, 0x03, 0xc6, 0x6b, 0x43, 0x9f, 0x6b,
+	0x22, 0xf1, 0x3d, 0x8f, 0xb7, 0x13, 0xd7, 0x65, 0xab, 0xf3, 0xf2, 0x9c,
+	0x3c, 0xf6, 0x61, 0xf9, 0xf6, 0xbe, 0x3e, 0xcf, 0xdc, 0x6d, 0x9e, 0xb9,
+	0xef, 0xf0, 0xcc, 0xed, 0xc3, 0xb7, 0x2e, 0x3e, 0x41, 0x7c, 0xeb, 0xae,
+	0xf1, 0xb7, 0x9e, 0x35, 0x5c, 0xdc, 0xdb, 0x3d, 0xb8, 0xbf, 0x8f, 0xf9,
+	0xb9, 0xcf, 0xf4, 0xf4, 0xf1, 0x9a, 0x1b, 0x68, 0x6e, 0xb0, 0x8d, 0x16,
+	0x4f, 0x72, 0x5f, 0xd0, 0x83, 0x0b, 0xe3, 0x17, 0x90, 0x63, 0x6d, 0x74,
+	0xf1, 0x64, 0x8b, 0xc0, 0x9b, 0xfd, 0xf9, 0xc6, 0xca, 0x9a, 0x57, 0xb0,
+	0xa6, 0x3b, 0x97, 0x89, 0x6f, 0x19, 0x96, 0xf1, 0xe3, 0x31, 0xee, 0xe3,
+	0xb1, 0x37, 0xcb, 0x5f, 0x33, 0x82, 0xce, 0x9e, 0x0d, 0xc6, 0xcd, 0xfd,
+	0x56, 0x6b, 0x26, 0x8b, 0xdb, 0x9d, 0x34, 0x1b, 0xd4, 0xc0, 0x37, 0x55,
+	0xfa, 0x28, 0xae, 0x23, 0xa8, 0x4a, 0xb4, 0x8f, 0xf9, 0xbc, 0x4e, 0xd6,
+	0xaf, 0x5b, 0x30, 0x6f, 0xd8, 0xcd, 0xd1, 0x88, 0xe5, 0x38, 0x27, 0xec,
+	0xbe, 0x26, 0xc7, 0xd9, 0xee, 0xb3, 0xdf, 0xc7, 0x53, 0xc8, 0xaa, 0x3c,
+	0xaf, 0x29, 0xed, 0xa0, 0x83, 0x50, 0xcf, 0x8b, 0xb2, 0x9e, 0xb2, 0xe8,
+	0xad, 0x99, 0x18, 0x4e, 0x1c, 0xe3, 0x9c, 0xed, 0xac, 0x85, 0xfe, 0xe0,
+	0xbd, 0x98, 0x00, 0x1e, 0x61, 0x8a, 0xe2, 0xaf, 0x50, 0xca, 0xe3, 0x69,
+	0xe1, 0xa9, 0xe0, 0xc9, 0xf5, 0x0c, 0x1d, 0x4f, 0xe8, 0x18, 0xec, 0x53,
+	0xb4, 0xef, 0x92, 0x93, 0x3f, 0x41, 0x37, 0xde, 0x9e, 0x74, 0xea, 0x51,
+	0x8b, 0xd6, 0x72, 0xf5, 0xa8, 0x3f, 0x67, 0x9e, 0x9c, 0x70, 0xeb, 0x51,
+	0x8b, 0x24, 0xea, 0x51, 0x27, 0x56, 0xa8, 0x47, 0x25, 0x56, 0x5f, 0x8f,
+	0xe2, 0xf9, 0x35, 0xda, 0xd7, 0x4f, 0xca, 0x17, 0x64, 0x3d, 0xea, 0x3d,
+	0x72, 0xea, 0x51, 0x17, 0xa9, 0x71, 0x3d, 0xea, 0x78, 0x5d, 0x3d, 0x2a,
+	0x28, 0xea, 0x51, 0x3c, 0x8f, 0x53, 0x8f, 0x12, 0xed, 0xbe, 0x88, 0xa7,
+	0xee, 0x42, 0xf4, 0xee, 0x64, 0x07, 0x68, 0x66, 0xd0, 0xf7, 0x1a, 0xda,
+	0x34, 0x45, 0xc8, 0xdb, 0x4a, 0x35, 0xd0, 0x07, 0x6e, 0xb8, 0xbe, 0xa2,
+	0xd0, 0x06, 0xcc, 0x9b, 0xec, 0x7b, 0xd8, 0x53, 0x63, 0x61, 0x9a, 0xff,
+	0x62, 0xea, 0x2c, 0x07, 0x45, 0x9d, 0xe5, 0x87, 0x6b, 0xbc, 0x75, 0x96,
+	0x45, 0xba, 0x7e, 0x9d, 0xe5, 0x60, 0x83, 0x3a, 0xcb, 0x5b, 0x54, 0xad,
+	0xb3, 0xbc, 0x45, 0xd5, 0x3a, 0xcb, 0xc1, 0x12, 0xe7, 0xe2, 0x3e, 0x89,
+	0x5f, 0x06, 0xed, 0x41, 0xf1, 0xc7, 0xb5, 0x97, 0xc5, 0xca, 0x1e, 0x7e,
+	0xd9, 0x6a, 0x2f, 0x6c, 0x03, 0x22, 0x17, 0x2e, 0xd7, 0xd4, 0x5e, 0xb8,
+	0x0d, 0x9d, 0xb1, 0xd7, 0x08, 0x19, 0x99, 0x83, 0x7f, 0x5f, 0x9c, 0x0c,
+	0x61, 0xce, 0x0e, 0xf8, 0x8c, 0x0e, 0xe4, 0x06, 0x61, 0xb4, 0x15, 0xda,
+	0x64, 0x0d, 0xa1, 0x8f, 0xc7, 0xd9, 0x0e, 0x43, 0xb7, 0x6c, 0x77, 0x7f,
+	0x0f, 0x48, 0x1a, 0x44, 0x68, 0xb8, 0x9d, 0xf4, 0x20, 0xfb, 0x8e, 0xc9,
+	0x3d, 0x74, 0xc8, 0xde, 0x22, 0xf6, 0xbd, 0xc1, 0xaa, 0x95, 0xb9, 0xc1,
+	0x1b, 0x90, 0xb9, 0xcc, 0xaa, 0x65, 0x8e, 0xe5, 0xcd, 0x39, 0xf7, 0xdd,
+	0x60, 0xf1, 0xfa, 0x1d, 0x02, 0xa7, 0x77, 0x1b, 0xc8, 0xfb, 0x18, 0xec,
+	0x8e, 0x33, 0xbf, 0x2e, 0xd7, 0xab, 0x8f, 0x87, 0x9f, 0x6d, 0x66, 0xff,
+	0xbd, 0x72, 0x3d, 0xb1, 0xde, 0x7f, 0xaf, 0xe4, 0x47, 0x15, 0x61, 0x93,
+	0xb3, 0x25, 0xae, 0xed, 0x7b, 0xf9, 0x33, 0x8f, 0x9c, 0x00, 0x7d, 0x42,
+	0x0f, 0x98, 0xae, 0x41, 0xf0, 0x01, 0xeb, 0xd8, 0x4f, 0xc9, 0x5a, 0x16,
+	0x9e, 0x05, 0x97, 0x7f, 0xad, 0xb0, 0x99, 0xee, 0x18, 0xdb, 0x01, 0x0b,
+	0xfe, 0x8f, 0xeb, 0x28, 0x7c, 0x8e, 0xca, 0xfd, 0x2e, 0x5f, 0xbb, 0x2e,
+	0xbc, 0xa7, 0x72, 0xbb, 0x5c, 0xce, 0x8a, 0x7a, 0x2d, 0xa9, 0x9d, 0x7d,
+	0xd3, 0x2d, 0x6c, 0x6b, 0xb6, 0x58, 0xae, 0xcc, 0x26, 0xf0, 0xce, 0x7c,
+	0x7d, 0x17, 0x36, 0x9c, 0xcf, 0xaa, 0xbf, 0x23, 0x6a, 0x04, 0x73, 0x36,
+	0xdb, 0x6b, 0x8e, 0x41, 0x7f, 0x0b, 0xb2, 0xc4, 0xef, 0x51, 0x71, 0x2e,
+	0x21, 0x6a, 0xf8, 0x83, 0xdc, 0x76, 0xed, 0x4a, 0x94, 0xed, 0x30, 0xf6,
+	0x5c, 0xa5, 0x31, 0xe2, 0x23, 0xc8, 0x0c, 0xc7, 0xb1, 0x0c, 0xe7, 0xc6,
+	0x9e, 0x9a, 0xa7, 0x66, 0xab, 0xcb, 0xb8, 0x88, 0x75, 0x39, 0x00, 0x9a,
+	0xed, 0x10, 0x31, 0xea, 0xb8, 0x5d, 0xa6, 0xea, 0x19, 0x3f, 0xd3, 0xdc,
+	0x39, 0xe7, 0x3f, 0x66, 0x2f, 0x47, 0xfb, 0xcd, 0x37, 0x48, 0x7b, 0x47,
+	0x1f, 0x6b, 0xe9, 0xae, 0x23, 0x7e, 0x71, 0xe9, 0xee, 0xfa, 0xa8, 0x49,
+	0x49, 0x83, 0xa8, 0xac, 0x2b, 0x7e, 0x5a, 0x9e, 0x29, 0xfd, 0x5f, 0xd8,
+	0xaf, 0xe2, 0xd9, 0xaf, 0xab, 0xbb, 0xfb, 0xe4, 0x7e, 0xc3, 0x75, 0xba,
+	0x1b, 0x97, 0x75, 0xb9, 0x5f, 0x84, 0xee, 0xba, 0x7b, 0xe2, 0xb5, 0xb7,
+	0x5c, 0x67, 0xdd, 0x67, 0x48, 0x8d, 0xaf, 0x14, 0x7b, 0xff, 0xb4, 0xf9,
+	0xe3, 0xc5, 0xde, 0x1f, 0x87, 0x9e, 0x5e, 0xbd, 0x65, 0x1a, 0xb6, 0x89,
+	0xb8, 0xc2, 0xd1, 0x1f, 0xd8, 0xe3, 0x82, 0x9f, 0x16, 0x1e, 0xd2, 0xe9,
+	0x9f, 0xee, 0xe4, 0xfa, 0xac, 0x26, 0x73, 0x7c, 0x6e, 0x7f, 0xb1, 0x95,
+	0x63, 0xab, 0x4d, 0xd6, 0x77, 0x44, 0x6e, 0x95, 0x57, 0x4d, 0x8f, 0x1f,
+	0x31, 0x30, 0xce, 0x63, 0x61, 0xba, 0x1c, 0xbc, 0x91, 0xb8, 0xbc, 0xcb,
+	0x58, 0xf4, 0xad, 0x26, 0x2e, 0xbf, 0x55, 0xf7, 0x5b, 0x7f, 0xdd, 0x7a,
+	0xbd, 0x3a, 0x47, 0x35, 0x2e, 0xe7, 0x7c, 0x3e, 0xe8, 0xd4, 0x18, 0x4c,
+	0x8e, 0xcf, 0xd7, 0x4a, 0x9e, 0xf0, 0x3b, 0x72, 0x11, 0x1b, 0x79, 0x08,
+	0x64, 0xfc, 0x55, 0xc8, 0xca, 0x2b, 0x36, 0xf2, 0x0e, 0x1b, 0xf9, 0x88,
+	0x8d, 0xdc, 0xc3, 0x46, 0xee, 0x61, 0xf7, 0xc8, 0x1c, 0x26, 0x23, 0xeb,
+	0x56, 0x7c, 0x46, 0xcb, 0xf9, 0x61, 0x5e, 0xc9, 0xd8, 0xe3, 0x7c, 0x1f,
+	0x41, 0x4d, 0xc6, 0x36, 0xca, 0x78, 0xf0, 0x38, 0xdf, 0x77, 0x28, 0xab,
+	0x71, 0xae, 0x45, 0x91, 0xaa, 0xc6, 0x6f, 0x87, 0x8f, 0xda, 0x0e, 0xbc,
+	0x9a, 0x79, 0xdc, 0xa7, 0xc6, 0x5b, 0x99, 0x76, 0x8a, 0x1a, 0x5f, 0x2b,
+	0xcf, 0x0d, 0x7a, 0x03, 0x0e, 0xfe, 0xdd, 0xdc, 0xd6, 0xd4, 0xf8, 0xdd,
+	0xec, 0xd3, 0xc2, 0xa4, 0xba, 0xfd, 0xb7, 0x07, 0x98, 0xae, 0xa4, 0xde,
+	0x16, 0xe0, 0xb8, 0x76, 0xde, 0xf6, 0x8b, 0x3b, 0x05, 0xc9, 0x18, 0xd7,
+	0xcc, 0xb8, 0x5d, 0xa5, 0xab, 0xba, 0x2c, 0x5d, 0xfd, 0x95, 0xfa, 0x3f,
+	0xd3, 0xd2, 0xc7, 0x70, 0xa2, 0x36, 0xc6, 0x34, 0x75, 0xe7, 0xe3, 0xf3,
+	0x66, 0x5e, 0x47, 0xdc, 0x63, 0xc0, 0xf3, 0x60, 0x33, 0xb5, 0x0d, 0x0e,
+	0xf9, 0x2d, 0xef, 0xba, 0x6c, 0x43, 0x76, 0x90, 0x37, 0xc7, 0x5a, 0x7e,
+	0xcd, 0xa8, 0x38, 0x1b, 0x49, 0xf6, 0x47, 0x85, 0xec, 0xb0, 0xac, 0x69,
+	0xe2, 0xce, 0xd5, 0x47, 0xe2, 0x1e, 0x09, 0xcb, 0x19, 0xcb, 0xf2, 0x78,
+	0x7f, 0x57, 0x58, 0x53, 0x5b, 0xb0, 0x46, 0x98, 0xd2, 0x25, 0x71, 0x56,
+	0x80, 0x7c, 0xe9, 0xdc, 0x3a, 0x6a, 0xfb, 0x07, 0xbd, 0x9a, 0xc7, 0x46,
+	0x9d, 0xb3, 0x7a, 0xbb, 0xde, 0xff, 0x8d, 0x8a, 0x73, 0x65, 0xc7, 0x06,
+	0xb9, 0xe7, 0xc3, 0xab, 0x3b, 0xff, 0xbe, 0xbe, 0x3e, 0xb5, 0xd4, 0xd7,
+	0x0d, 0x24, 0x0d, 0x98, 0x36, 0x8d, 0xcf, 0xee, 0xe7, 0x4b, 0x7c, 0xaf,
+	0x25, 0x12, 0xe3, 0xdc, 0x6d, 0x44, 0xdc, 0xf9, 0x50, 0x21, 0x85, 0x3a,
+	0x8d, 0x19, 0x9c, 0xf3, 0x85, 0x86, 0x7d, 0x71, 0xca, 0x64, 0x27, 0x48,
+	0x43, 0xac, 0x98, 0xa9, 0xd6, 0x03, 0x1f, 0x5c, 0x43, 0x96, 0x2b, 0x97,
+	0x51, 0xce, 0x1f, 0x6a, 0xce, 0xed, 0x16, 0xe9, 0xb0, 0x72, 0xa0, 0x74,
+	0x84, 0x0e, 0x34, 0x8c, 0x29, 0x1b, 0xd7, 0x03, 0x2f, 0xd6, 0xd5, 0x14,
+	0x16, 0x44, 0x4d, 0x21, 0xb7, 0xc6, 0x6f, 0x3d, 0x19, 0x70, 0xee, 0xb5,
+	0x34, 0xd6, 0x93, 0x5d, 0x15, 0x3d, 0x71, 0xe1, 0xf8, 0x2c, 0xbe, 0x8d,
+	0x76, 0x8a, 0xb5, 0x0e, 0x2b, 0x59, 0xbb, 0x95, 0x76, 0x1a, 0x0e, 0xd6,
+	0xa3, 0x36, 0xe3, 0x75, 0x58, 0x39, 0x68, 0xe7, 0x95, 0xb4, 0xa8, 0x3d,
+	0x70, 0x8c, 0xbf, 0xe6, 0xda, 0x30, 0x95, 0xe9, 0xed, 0x98, 0xfb, 0x3d,
+	0xc3, 0x78, 0x6b, 0x8a, 0x2e, 0x9d, 0xf8, 0x2e, 0x51, 0x58, 0xe6, 0x6f,
+	0xce, 0x7c, 0xb9, 0x29, 0xae, 0x25, 0xde, 0x8f, 0xfd, 0x33, 0xfc, 0x6e,
+	0x25, 0x39, 0x55, 0x2e, 0xa7, 0x31, 0x3e, 0xd6, 0x7b, 0xaf, 0xc8, 0x8d,
+	0xd4, 0x38, 0x0d, 0x71, 0x8e, 0xac, 0x2d, 0xc9, 0x91, 0xd3, 0xd0, 0x35,
+	0xc4, 0x20, 0x76, 0x13, 0xbe, 0x75, 0xe3, 0x91, 0xcf, 0xae, 0x75, 0x64,
+	0xe4, 0xbb, 0x12, 0x0f, 0x1e, 0xff, 0xfb, 0x80, 0x7b, 0x0f, 0x28, 0x77,
+	0x2a, 0x8d, 0xfd, 0x37, 0x51, 0xca, 0x74, 0xf2, 0xbb, 0xec, 0x99, 0x23,
+	0x1b, 0x6a, 0xe1, 0xd1, 0x77, 0xca, 0x85, 0x0f, 0xd6, 0xc1, 0xf3, 0x19,
+	0xd7, 0x5f, 0xd5, 0xc1, 0x07, 0x3d, 0xf0, 0x66, 0x1d, 0x3c, 0xe2, 0xae,
+	0x33, 0xdf, 0xa8, 0x83, 0x37, 0x3d, 0xf0, 0xed, 0x75, 0xf0, 0xed, 0x80,
+	0x7f, 0xa3, 0x0e, 0x1e, 0x7d, 0xa7, 0x90, 0x13, 0x08, 0xda, 0x70, 0x8c,
+	0x74, 0x48, 0xe6, 0x89, 0x78, 0x2e, 0xb9, 0x1f, 0xc9, 0xf2, 0xd3, 0x01,
+	0x1a, 0x7b, 0xeb, 0xb5, 0x09, 0xd8, 0xa8, 0xaa, 0x4c, 0x39, 0xfa, 0xea,
+	0x95, 0x25, 0x96, 0xbd, 0x3c, 0xe4, 0x15, 0x7a, 0x54, 0x80, 0x3e, 0x15,
+	0x5c, 0x5f, 0xca, 0x77, 0xaa, 0x22, 0xc7, 0x1d, 0x3d, 0x56, 0x68, 0xbd,
+	0x35, 0x2f, 0x73, 0x91, 0xab, 0x8c, 0x3b, 0xfc, 0x86, 0xeb, 0x3b, 0xe8,
+	0x84, 0x63, 0x57, 0x58, 0xbf, 0x79, 0x7e, 0x69, 0x5f, 0x4a, 0x2c, 0x87,
+	0xce, 0x3a, 0xe9, 0x25, 0x32, 0x1b, 0x5e, 0x52, 0x77, 0xf1, 0xd5, 0xd9,
+	0x77, 0x12, 0xf6, 0x3d, 0xd7, 0xe2, 0xb7, 0x36, 0xac, 0xbd, 0x9e, 0x7d,
+	0xcf, 0x78, 0xec, 0x7b, 0x38, 0x58, 0xf5, 0xf9, 0x8f, 0x09, 0x9f, 0xdf,
+	0xd1, 0xc0, 0x66, 0xac, 0xde, 0xe7, 0xef, 0xfd, 0xd8, 0x3e, 0x7f, 0xb9,
+	0x75, 0x57, 0xe3, 0xf3, 0x1f, 0x69, 0xf9, 0x78, 0x3e, 0x9f, 0xd7, 0xac,
+	0xaf, 0x65, 0x7a, 0xcf, 0x59, 0x8e, 0xca, 0x18, 0x7b, 0xb7, 0x27, 0xc6,
+	0x66, 0xfc, 0xbe, 0x27, 0xef, 0x02, 0x9e, 0x5e, 0xeb, 0xc8, 0xdb, 0x51,
+	0x19, 0xa7, 0x73, 0xec, 0x8d, 0xf7, 0xc2, 0x23, 0x90, 0xd1, 0x7c, 0x8f,
+	0x8f, 0x54, 0x9a, 0x35, 0x9d, 0xb3, 0xed, 0x9f, 0x6f, 0xae, 0x17, 0xa1,
+	0xcb, 0xc2, 0x9f, 0x24, 0x3e, 0x81, 0x5a, 0xea, 0x49, 0xc8, 0x8f, 0xbb,
+	0xaf, 0x95, 0x6a, 0xa9, 0xf5, 0xe7, 0x1f, 0x7c, 0xee, 0x41, 0xca, 0x03,
+	0x95, 0x73, 0x10, 0xaf, 0x4e, 0xe9, 0x94, 0x9d, 0x21, 0xdd, 0x8c, 0x93,
+	0xb2, 0x8f, 0x71, 0x8e, 0xfd, 0xb0, 0x52, 0x6f, 0x3f, 0x24, 0x6b, 0x30,
+	0xea, 0xb2, 0x77, 0x82, 0x7e, 0x02, 0x7c, 0x58, 0xaf, 0x9c, 0x1a, 0x8c,
+	0xea, 0xdc, 0x09, 0x3a, 0xfe, 0xf3, 0xbb, 0x13, 0xc4, 0xf3, 0x6b, 0xb4,
+	0xb7, 0xc1, 0x9d, 0x20, 0xdf, 0x2a, 0xef, 0x04, 0xad, 0x17, 0x35, 0x18,
+	0x9e, 0xc7, 0xa9, 0xc1, 0x70, 0xbb, 0xb3, 0x8f, 0xe5, 0x3a, 0x4c, 0xa3,
+	0x93, 0xb7, 0x88, 0x7b, 0xa8, 0x9d, 0x7d, 0xb5, 0xf2, 0xbd, 0xef, 0x13,
+	0x8d, 0xa5, 0x79, 0xbd, 0xa3, 0x0d, 0xef, 0xb6, 0x24, 0x3f, 0xc1, 0x9a,
+	0xcb, 0x21, 0x51, 0x73, 0xb9, 0xb3, 0xcd, 0x5b, 0x73, 0x51, 0x57, 0xb8,
+	0xdb, 0x72, 0xa8, 0x41, 0xcd, 0xc5, 0xef, 0xb9, 0xdb, 0xe2, 0xf7, 0xdc,
+	0x6d, 0x39, 0x24, 0xeb, 0x2b, 0xea, 0x2f, 0xd1, 0xdd, 0x96, 0xe4, 0x8a,
+	0x77, 0x5b, 0xb6, 0x4a, 0x7d, 0xf5, 0xc2, 0xaf, 0xfe, 0xbc, 0x32, 0x55,
+	0x67, 0xe7, 0x13, 0xc2, 0xce, 0xdf, 0xd5, 0xea, 0xb7, 0x9e, 0x69, 0xbb,
+	0x9e, 0x9d, 0xdf, 0x57, 0xd1, 0x53, 0xbe, 0xa3, 0xcd, 0x77, 0xbe, 0x58,
+	0x16, 0xf9, 0x7c, 0xa6, 0x89, 0x72, 0x03, 0xbf, 0x2a, 0x68, 0xf6, 0x58,
+	0x6f, 0xed, 0x99, 0x63, 0xf5, 0x5e, 0xa4, 0xee, 0xb9, 0x17, 0x69, 0xa2,
+	0x5f, 0xaf, 0xab, 0x87, 0x04, 0xe4, 0xdd, 0x7e, 0xf8, 0xc2, 0x19, 0x43,
+	0xda, 0x5e, 0xc4, 0x70, 0x98, 0xae, 0x50, 0xe4, 0x3b, 0x95, 0x6d, 0xe4,
+	0x9b, 0x71, 0xce, 0x4b, 0x54, 0x11, 0x63, 0x42, 0x8e, 0x8b, 0x7e, 0xe1,
+	0x6f, 0xd4, 0xb8, 0x23, 0xb3, 0xe3, 0xf6, 0x05, 0xe0, 0xbf, 0x21, 0x51,
+	0x6d, 0x9b, 0x95, 0x5a, 0xce, 0x58, 0xe5, 0x0e, 0xbf, 0x09, 0xfb, 0xe0,
+	0xdc, 0x07, 0xca, 0x98, 0x7c, 0x67, 0xe4, 0x62, 0x5b, 0xf5, 0x3e, 0xd0,
+	0x67, 0xa4, 0x9c, 0x3a, 0xf7, 0x81, 0x48, 0x4d, 0x40, 0x3e, 0x6e, 0xe4,
+	0x3e, 0x50, 0xd7, 0x92, 0xfb, 0x40, 0x2b, 0xf3, 0x66, 0xe9, 0x7d, 0xa0,
+	0xc6, 0xfc, 0xe1, 0xfb, 0x40, 0xff, 0xde, 0xe6, 0xdc, 0x43, 0x5d, 0x89,
+	0x3f, 0x6e, 0x9c, 0xf4, 0x11, 0xe0, 0xf9, 0x3e, 0x50, 0xe5, 0x1e, 0x90,
+	0xe7, 0x0e, 0x10, 0xdf, 0x25, 0x59, 0xee, 0x0c, 0xce, 0x7b, 0xff, 0xa4,
+	0xa7, 0x72, 0xff, 0xe4, 0x7c, 0xc9, 0xf5, 0xed, 0xee, 0xb9, 0x1c, 0xc7,
+	0x39, 0xbb, 0x44, 0x8e, 0x7a, 0xae, 0x54, 0x5b, 0xc3, 0x60, 0xbe, 0x8f,
+	0x16, 0xcf, 0x81, 0x3e, 0x6f, 0x89, 0xdc, 0x00, 0x7c, 0xde, 0xe2, 0x23,
+	0xe6, 0x1d, 0x29, 0xa0, 0x8b, 0x38, 0xcb, 0x75, 0xf8, 0xdd, 0x21, 0x64,
+	0xc1, 0x91, 0x8b, 0xdd, 0x9e, 0xf3, 0xd0, 0xaa, 0x1c, 0x38, 0x67, 0xba,
+	0x0e, 0xef, 0x6a, 0x65, 0x46, 0x9c, 0xdd, 0x0c, 0xed, 0xb5, 0x9c, 0xf3,
+	0xc6, 0xa8, 0x38, 0xb7, 0x6d, 0xaf, 0xb3, 0x5b, 0x3a, 0xe4, 0x06, 0x31,
+	0x67, 0x8c, 0xeb, 0xd5, 0x8c, 0xfb, 0x66, 0xc1, 0xe3, 0x46, 0x67, 0x71,
+	0x2b, 0xd7, 0xf1, 0xdc, 0x9a, 0x0a, 0x21, 0x97, 0xd8, 0x9d, 0xce, 0x09,
+	0xbb, 0xe9, 0xac, 0xdd, 0x29, 0xd6, 0xde, 0x58, 0x77, 0x96, 0xcd, 0x72,
+	0xb5, 0x5c, 0x4c, 0x70, 0x3d, 0x9a, 0xde, 0xb3, 0x84, 0xa6, 0xb5, 0xba,
+	0x84, 0xdc, 0xb5, 0x62, 0xe3, 0x3b, 0x2a, 0xba, 0x34, 0x2e, 0xee, 0x21,
+	0xbb, 0xe7, 0xb5, 0x0e, 0xfd, 0xaa, 0xba, 0xb7, 0x5c, 0x3c, 0x53, 0x4f,
+	0xbf, 0x4d, 0xff, 0x4b, 0xe8, 0x77, 0x15, 0xf4, 0xe3, 0x77, 0x03, 0xef,
+	0xef, 0x8a, 0x7a, 0xc0, 0xb9, 0x52, 0xe4, 0x78, 0x9e, 0x38, 0x4e, 0x88,
+	0xcc, 0x2e, 0x50, 0x0f, 0xe8, 0xc8, 0xff, 0xeb, 0xe2, 0xde, 0x9d, 0x60,
+	0xfa, 0xb2, 0x7d, 0x8f, 0xbc, 0x70, 0x99, 0xd8, 0xc6, 0xdf, 0x8d, 0x7d,
+	0x94, 0xcb, 0x2f, 0xc5, 0x5c, 0xfa, 0xb3, 0xee, 0x73, 0x9d, 0xaa, 0x76,
+	0x5f, 0x7b, 0x57, 0xed, 0x53, 0x1d, 0xf9, 0xcc, 0x34, 0x90, 0xcf, 0x8c,
+	0xdc, 0xa3, 0x6f, 0xa6, 0x71, 0xbc, 0x9a, 0x9a, 0xfc, 0xef, 0x5e, 0xae,
+	0x26, 0xb6, 0x8d, 0x22, 0x0a, 0xbf, 0xac, 0xd7, 0x4e, 0xe3, 0xa4, 0x61,
+	0x93, 0x3a, 0xad, 0x69, 0xd2, 0x60, 0xc7, 0x4b, 0x12, 0x29, 0xa5, 0xa4,
+	0x52, 0x55, 0x45, 0x60, 0xa9, 0x21, 0x4e, 0xda, 0x0a, 0x71, 0x70, 0x0b,
+	0x48, 0x51, 0xc5, 0x21, 0x4d, 0xd3, 0x7b, 0x85, 0x84, 0x54, 0xa1, 0x8a,
+	0x46, 0x4e, 0x02, 0x15, 0x4a, 0xe5, 0x0a, 0x96, 0x72, 0x41, 0xa2, 0xd8,
+	0x8e, 0x02, 0x52, 0x2a, 0xf7, 0xca, 0x85, 0xba, 0xbf, 0x08, 0x89, 0x03,
+	0x70, 0x06, 0x29, 0x2a, 0x3f, 0xe2, 0xc0, 0x8d, 0x1b, 0x54, 0x5d, 0xde,
+	0x37, 0xb3, 0x63, 0xaf, 0x77, 0xd7, 0x8e, 0x03, 0x11, 0x07, 0x27, 0xbb,
+	0xf6, 0xcc, 0xce, 0xec, 0xcc, 0x37, 0x6f, 0xbe, 0xf7, 0x37, 0xfd, 0xbe,
+	0x78, 0x8d, 0x5a, 0xdb, 0x5b, 0xf3, 0x55, 0xec, 0xe7, 0xaf, 0x37, 0x18,
+	0x57, 0xed, 0xba, 0xe4, 0xa9, 0xf5, 0xe3, 0x9a, 0x72, 0xd9, 0x1b, 0xf0,
+	0xfe, 0xc7, 0x68, 0x51, 0xd8, 0x86, 0x94, 0xad, 0xee, 0xc5, 0x40, 0x9b,
+	0xd9, 0xff, 0x33, 0x16, 0x03, 0x3e, 0x9b, 0x68, 0xad, 0x6d, 0x8a, 0xed,
+	0x71, 0xd9, 0x16, 0xde, 0xda, 0xc2, 0xb6, 0x10, 0x3c, 0x16, 0xfd, 0x9e,
+	0xb1, 0xa8, 0xc9, 0xea, 0xa1, 0x16, 0xed, 0x74, 0x88, 0x21, 0xbf, 0x9d,
+	0x67, 0x6c, 0x05, 0xca, 0xce, 0x4f, 0x5d, 0x36, 0x3c, 0xe0, 0x73, 0xdc,
+	0x59, 0xeb, 0xc0, 0x27, 0xb5, 0x9d, 0x1a, 0x51, 0xed, 0x01, 0x8f, 0xc9,
+	0xc5, 0x45, 0x82, 0xbe, 0x86, 0x36, 0xe3, 0x82, 0xe3, 0xfa, 0x39, 0x14,
+	0x8f, 0xf1, 0xfa, 0x1b, 0x88, 0xe5, 0x70, 0xda, 0x3f, 0xd9, 0x76, 0xae,
+	0x9c, 0xe5, 0xbd, 0x42, 0xd4, 0x63, 0xbd, 0xef, 0x52, 0xdb, 0x82, 0xa8,
+	0x27, 0xe3, 0x20, 0x1c, 0x1d, 0xd0, 0xe1, 0xe2, 0x8d, 0x74, 0x3f, 0xff,
+	0x9e, 0x13, 0xcc, 0xdd, 0x7f, 0xdd, 0x1d, 0x36, 0x3f, 0x34, 0x64, 0xae,
+	0xde, 0x56, 0xdc, 0x5d, 0xd9, 0x89, 0x06, 0x85, 0xaf, 0xc1, 0xad, 0x7b,
+	0x41, 0x76, 0x5d, 0xe0, 0x3d, 0x7c, 0xa8, 0xba, 0x7f, 0xef, 0x84, 0x7d,
+	0xe8, 0x99, 0x16, 0x62, 0x1d, 0x44, 0x8e, 0xe5, 0x2b, 0x53, 0xc8, 0x45,
+	0xaa, 0xe6, 0xef, 0x78, 0xf3, 0x3c, 0x20, 0x3f, 0x55, 0x9e, 0x87, 0xca,
+	0x23, 0xc5, 0x7b, 0x24, 0x02, 0xf2, 0x3c, 0xdc, 0x32, 0x18, 0xf5, 0xea,
+	0xdf, 0xc3, 0x2d, 0x7f, 0x57, 0x1c, 0xf9, 0x5b, 0xf0, 0xd8, 0xe3, 0x97,
+	0xf3, 0x6a, 0x2d, 0x20, 0xe7, 0x43, 0xf1, 0x94, 0xde, 0x00, 0x9e, 0x12,
+	0x9c, 0xeb, 0xa1, 0xa5, 0x2f, 0xf2, 0x5e, 0x7e, 0x08, 0x7b, 0xb9, 0x51,
+	0x8b, 0xe9, 0x95, 0x72, 0xf0, 0xdc, 0x3a, 0x64, 0xa2, 0xca, 0xb9, 0x81,
+	0x5c, 0x44, 0x2c, 0x3c, 0xe6, 0xba, 0xe4, 0x60, 0x11, 0xbf, 0xa9, 0x58,
+	0x52, 0xa5, 0x47, 0xbd, 0x23, 0xf2, 0x0c, 0xbe, 0x1b, 0x3f, 0xcc, 0x1c,
+	0x18, 0xf2, 0x13, 0x76, 0xa6, 0x43, 0x0e, 0x1f, 0xbe, 0xcc, 0xbf, 0x8d,
+	0x39, 0xd7, 0x92, 0x8b, 0xca, 0x6b, 0xa5, 0x4b, 0xfd, 0xd0, 0x41, 0xe6,
+	0x6f, 0x0e, 0x2f, 0xad, 0xb3, 0x41, 0xc4, 0x53, 0xda, 0xdb, 0x74, 0xa1,
+	0xd8, 0x0c, 0x83, 0xf5, 0xf8, 0x4b, 0x79, 0x38, 0x4f, 0x42, 0x70, 0x9e,
+	0x9f, 0x3a, 0xc2, 0xe6, 0x44, 0x4f, 0xb3, 0x38, 0x9c, 0x53, 0x55, 0xfc,
+	0xa9, 0x72, 0xaa, 0x6f, 0x8f, 0x3a, 0x10, 0xa7, 0xe6, 0xc7, 0x04, 0xe6,
+	0x1f, 0xfa, 0x9c, 0x5a, 0x87, 0xd0, 0xeb, 0x10, 0xf3, 0x87, 0x76, 0x8d,
+	0x06, 0x6b, 0xb0, 0x66, 0x13, 0x2f, 0x50, 0x2b, 0xb1, 0x7f, 0xc9, 0xd1,
+	0x0a, 0x9d, 0xed, 0x69, 0xa6, 0xf3, 0x9e, 0x08, 0xd4, 0x79, 0x83, 0x72,
+	0xa4, 0xcc, 0x80, 0x1c, 0x29, 0x37, 0x0e, 0x75, 0x17, 0x0e, 0xe3, 0x2e,
+	0x2e, 0x30, 0xc0, 0xdc, 0xb9, 0x8b, 0xf1, 0x04, 0xee, 0x1c, 0xa5, 0xd0,
+	0x07, 0x6e, 0xee, 0xec, 0xf7, 0x13, 0x49, 0x5c, 0xfe, 0xdb, 0xdc, 0xa9,
+	0xa0, 0x7e, 0x27, 0x7c, 0xfd, 0x86, 0x1c, 0x9f, 0x6c, 0xc8, 0x13, 0x82,
+	0x38, 0xfe, 0x4e, 0xf7, 0xd3, 0xbb, 0xf6, 0xd1, 0xa6, 0x09, 0xfd, 0x70,
+	0x74, 0xb1, 0xba, 0xee, 0x5f, 0xf0, 0xd9, 0xb9, 0xc1, 0x67, 0x43, 0xc2,
+	0x27, 0xd7, 0x25, 0xf6, 0x90, 0x9d, 0x93, 0x61, 0x9d, 0x1e, 0x19, 0x66,
+	0xf7, 0xd4, 0xec, 0xfc, 0x88, 0x21, 0xec, 0x73, 0x74, 0x0e, 0xb9, 0xef,
+	0x14, 0x1a, 0xc6, 0xa5, 0xe2, 0x3b, 0xe9, 0x1b, 0x38, 0x77, 0x04, 0xb2,
+	0x1b, 0xf2, 0xfc, 0xf4, 0x6c, 0xd8, 0x34, 0x1c, 0x1f, 0x03, 0xfc, 0x08,
+	0xc0, 0xa9, 0x7a, 0x7e, 0x90, 0x0d, 0x3d, 0x68, 0x0e, 0x87, 0x7c, 0x73,
+	0x28, 0xf1, 0x06, 0x6e, 0x8f, 0x58, 0xbc, 0x83, 0x9e, 0x38, 0xc5, 0x9d,
+	0x18, 0x93, 0xee, 0x80, 0x78, 0x41, 0xc4, 0xfa, 0xf9, 0xfa, 0xcb, 0xef,
+	0x7c, 0x51, 0xf3, 0xaf, 0xad, 0x49, 0x6d, 0xba, 0x3c, 0xad, 0x4d, 0x15,
+	0x51, 0xee, 0xa2, 0x56, 0xdb, 0x97, 0x36, 0x5d, 0x1c, 0x11, 0x7c, 0x30,
+	0x79, 0xad, 0x42, 0x78, 0x4f, 0xdb, 0xbe, 0x25, 0xb8, 0xed, 0x80, 0x0f,
+	0xab, 0x8a, 0x73, 0x18, 0x2d, 0xbc, 0x97, 0xb4, 0xbd, 0xb8, 0xb9, 0x8e,
+	0x5b, 0xbe, 0x3f, 0x1d, 0x20, 0xdf, 0x9b, 0xd9, 0x0a, 0x91, 0xbf, 0x29,
+	0xe2, 0xb2, 0xa9, 0x68, 0x21, 0xde, 0xf1, 0x30, 0xe2, 0x7b, 0xe1, 0xd7,
+	0xa8, 0x62, 0xe1, 0x6e, 0x30, 0x16, 0xaa, 0xf6, 0x60, 0x1d, 0xb9, 0xa3,
+	0x2c, 0x8b, 0xc3, 0xe9, 0x5e, 0x0a, 0x99, 0x28, 0xff, 0x6c, 0xe2, 0x3e,
+	0x1d, 0x73, 0x78, 0x09, 0xfc, 0x3c, 0xb2, 0xde, 0x4c, 0x0b, 0x76, 0xe1,
+	0x60, 0x7f, 0x46, 0x84, 0x65, 0xf3, 0x67, 0xbd, 0xad, 0xf9, 0x33, 0x54,
+	0x39, 0xd4, 0xed, 0xa2, 0x35, 0x0b, 0x71, 0x92, 0xf0, 0x2f, 0x75, 0x77,
+	0xb4, 0x9b, 0x41, 0xf2, 0x4f, 0xc5, 0x7e, 0x82, 0x1f, 0xc9, 0xb9, 0xba,
+	0x41, 0x98, 0x3b, 0x9b, 0xbe, 0x6f, 0x30, 0x57, 0xdb, 0xb1, 0x29, 0x37,
+	0x9f, 0x2b, 0xc3, 0x33, 0x57, 0xd8, 0x8b, 0x9a, 0xcd, 0x95, 0xf2, 0x43,
+	0x2a, 0xdf, 0xdc, 0x51, 0xc8, 0x93, 0x45, 0xf7, 0x5c, 0xed, 0x8c, 0x7f,
+	0x4e, 0xce, 0xd9, 0x4e, 0xfb, 0xe0, 0x1a, 0x8f, 0x43, 0x34, 0xd0, 0x76,
+	0x12, 0x2c, 0x33, 0xfc, 0x6b, 0xeb, 0x86, 0x5c, 0x5b, 0xcc, 0x2b, 0x9e,
+	0x6f, 0xb8, 0xb6, 0xb0, 0x0f, 0x5c, 0x70, 0xf6, 0x81, 0xd3, 0x3e, 0x7d,
+	0x51, 0xd9, 0xbc, 0xff, 0xab, 0xed, 0x0d, 0xcf, 0x7d, 0x22, 0xce, 0xe9,
+	0xc8, 0x91, 0xdc, 0x47, 0xce, 0x37, 0xe4, 0x61, 0x3d, 0xdb, 0x5c, 0xa7,
+	0x6a, 0xee, 0x91, 0x73, 0x01, 0x79, 0x99, 0xa5, 0xf3, 0xf9, 0xc7, 0x06,
+	0x75, 0xf7, 0x53, 0xa4, 0x1a, 0xd3, 0x72, 0x40, 0xf0, 0x61, 0xb7, 0xbe,
+	0xbc, 0xec, 0xe4, 0x28, 0xe6, 0x5c, 0x63, 0xb0, 0x9c, 0xcf, 0x36, 0x89,
+	0xa7, 0x6f, 0x25, 0x9e, 0x63, 0xc0, 0x23, 0x37, 0xbd, 0x73, 0x35, 0xa1,
+	0x65, 0xf2, 0xa8, 0xb3, 0x87, 0xce, 0xea, 0x9f, 0xf0, 0x18, 0x3d, 0xb1,
+	0x23, 0xe2, 0x9c, 0x11, 0xe0, 0xd2, 0xb6, 0x97, 0xcd, 0x0e, 0x5a, 0x94,
+	0x7e, 0x46, 0x9a, 0xfa, 0xf8, 0x12, 0x15, 0x85, 0x7f, 0x0b, 0xb9, 0x51,
+	0xb0, 0x71, 0xc3, 0x47, 0x87, 0xe7, 0xf0, 0xf7, 0x1b, 0x13, 0x8e, 0xcc,
+	0xfd, 0x93, 0x31, 0x8c, 0x7a, 0x38, 0x0b, 0x01, 0xeb, 0x9d, 0x34, 0xc9,
+	0x31, 0xb9, 0x1d, 0x71, 0x4e, 0x80, 0x8c, 0xcd, 0xbb, 0x5d, 0xde, 0x8e,
+	0x4f, 0xa1, 0x55, 0xbd, 0xe4, 0xeb, 0x68, 0xd8, 0xfc, 0x72, 0xcf, 0xf6,
+	0x7d, 0x0a, 0x2a, 0x77, 0x5f, 0x71, 0x58, 0x75, 0x2d, 0x73, 0x69, 0xc1,
+	0x99, 0xe7, 0xd7, 0x55, 0xde, 0x6d, 0x77, 0x40, 0xde, 0x6d, 0x88, 0xe6,
+	0x84, 0xaf, 0x2e, 0x44, 0x39, 0x47, 0x37, 0x93, 0x9c, 0x5a, 0xd9, 0x6a,
+	0x23, 0x4e, 0xfc, 0x29, 0xee, 0xdd, 0x39, 0xf9, 0x7c, 0x5f, 0x04, 0xcf,
+	0x46, 0x4e, 0xb5, 0x2d, 0x62, 0xf1, 0x33, 0xa2, 0x5c, 0xa7, 0xa7, 0x1c,
+	0xdf, 0x17, 0xd5, 0x33, 0x3b, 0xb9, 0x7c, 0x8a, 0x64, 0x0e, 0x7d, 0x27,
+	0xcd, 0x15, 0x9b, 0xf5, 0x6b, 0x1f, 0xe2, 0x81, 0xe3, 0xf0, 0x95, 0x0a,
+	0xbf, 0x95, 0xa1, 0xfa, 0x80, 0x3e, 0xb5, 0x57, 0xfb, 0x04, 0xf9, 0x14,
+	0x12, 0x7e, 0x05, 0xbe, 0x76, 0xda, 0x99, 0x23, 0x77, 0xbf, 0xc2, 0xdc,
+	0x2f, 0x3c, 0xa7, 0xd3, 0x55, 0xb6, 0xd3, 0x55, 0xb6, 0x36, 0x5e, 0x3a,
+	0xeb, 0x54, 0x0b, 0xe5, 0x1f, 0x59, 0x2f, 0xfd, 0x56, 0xd8, 0xe6, 0xe6,
+	0xb3, 0x06, 0x2d, 0xac, 0xf7, 0xf2, 0x27, 0xc6, 0x1f, 0x94, 0xdb, 0xcb,
+	0xff, 0xdd, 0x9c, 0xa2, 0x5f, 0xc4, 0x02, 0xb6, 0xce, 0x07, 0x83, 0xf1,
+	0x1f, 0xbc, 0x6e, 0x13, 0x01, 0xeb, 0xb6, 0xf9, 0xbe, 0x22, 0xf7, 0x93,
+	0xe4, 0x95, 0x8a, 0x23, 0xaf, 0x36, 0x69, 0xd0, 0x27, 0xa7, 0x82, 0xd6,
+	0x29, 0xfa, 0x78, 0xca, 0xe9, 0xe3, 0x9b, 0xa2, 0x3f, 0xe3, 0x54, 0xa8,
+	0xe6, 0x0d, 0x1f, 0xe1, 0xeb, 0x98, 0xb2, 0xd1, 0x35, 0x90, 0xab, 0xdf,
+	0x6c, 0x43, 0xc6, 0x04, 0x71, 0xb2, 0x03, 0x01, 0xfa, 0x80, 0xee, 0xd2,
+	0x07, 0xe2, 0x55, 0x7d, 0x60, 0x45, 0xe8, 0x09, 0xbb, 0x1c, 0x1d, 0x34,
+	0xd8, 0x16, 0x97, 0xcb, 0xe3, 0xcc, 0x1b, 0xd8, 0xf8, 0xa4, 0x1d, 0x7d,
+	0xda, 0xaa, 0x9e, 0x99, 0xc3, 0xba, 0x65, 0x8d, 0x4b, 0xfb, 0xe5, 0x09,
+	0xce, 0xac, 0xa8, 0xcc, 0x3e, 0x30, 0xa3, 0xa4, 0xa5, 0x93, 0xf1, 0xa9,
+	0x50, 0x84, 0x16, 0xac, 0x28, 0x15, 0xac, 0x14, 0x73, 0x70, 0xf0, 0xe3,
+	0xd0, 0x80, 0x46, 0x11, 0x96, 0x35, 0x11, 0x2a, 0x95, 0x94, 0x4e, 0x76,
+	0x86, 0xc8, 0x2c, 0xc6, 0xa4, 0x0d, 0x9b, 0x71, 0x9a, 0x1f, 0x33, 0xe6,
+	0x49, 0x43, 0xcc, 0x8b, 0x93, 0xa3, 0x0e, 0x0c, 0x8a, 0x38, 0x4b, 0xfd,
+	0xe5, 0x91, 0x28, 0xb5, 0xa7, 0xa5, 0xcd, 0x68, 0x86, 0xdb, 0xf8, 0xc2,
+	0x8a, 0xd1, 0x95, 0x7c, 0xd2, 0x38, 0xc1, 0xed, 0x64, 0xac, 0x64, 0x62,
+	0x92, 0x9f, 0x5d, 0x2c, 0x45, 0x28, 0x67, 0x45, 0xa8, 0x50, 0x4a, 0x19,
+	0x43, 0x6d, 0xa2, 0xcd, 0x18, 0xda, 0x7c, 0x49, 0x1f, 0x33, 0x4e, 0x92,
+	0xbb, 0xcd, 0xaf, 0x9c, 0x36, 0xbd, 0x6d, 0xfd, 0x61, 0xe3, 0xfe, 0x44,
+	0xa8, 0x32, 0x7b, 0x9f, 0xf1, 0x92, 0x5b, 0x9d, 0x60, 0xd9, 0x14, 0x13,
+	0x67, 0xdb, 0x68, 0xe9, 0x34, 0xcb, 0x1d, 0x9c, 0x6d, 0x61, 0xd0, 0x62,
+	0x39, 0x4e, 0xef, 0x57, 0xed, 0x07, 0x12, 0x43, 0x39, 0x91, 0x43, 0x84,
+	0x33, 0x17, 0x2a, 0xb3, 0xbf, 0x9b, 0x5e, 0x7f, 0x3f, 0xeb, 0x5b, 0x1f,
+	0xc5, 0x28, 0x72, 0x15, 0x71, 0xdd, 0x36, 0x5d, 0x1b, 0x4f, 0x5e, 0xd9,
+	0x14, 0x79, 0x68, 0x09, 0x5a, 0x33, 0xa5, 0x3c, 0xcd, 0x71, 0xf9, 0x15,
+	0x94, 0x5b, 0x4b, 0xd0, 0x3d, 0x91, 0x8f, 0xd6, 0x4e, 0x77, 0xf4, 0x18,
+	0x85, 0x6e, 0x9a, 0xc6, 0xbc, 0xf0, 0x0b, 0x57, 0x66, 0x87, 0x86, 0x0d,
+	0xd2, 0xae, 0xa2, 0x1e, 0xff, 0xbf, 0x89, 0xfb, 0x28, 0x61, 0x7e, 0x66,
+	0xac, 0x31, 0x5e, 0x49, 0xc3, 0xf1, 0x12, 0x64, 0xf3, 0x41, 0x89, 0xa5,
+	0x39, 0x23, 0x42, 0xd0, 0x5f, 0x61, 0x7b, 0xeb, 0x35, 0x27, 0x7b, 0xa4,
+	0xfe, 0xe4, 0x3b, 0x9b, 0x43, 0x9f, 0x19, 0x71, 0x9f, 0xcf, 0x51, 0x7b,
+	0x66, 0xc6, 0x92, 0xef, 0xb9, 0x52, 0xee, 0xa5, 0x25, 0x6e, 0x7b, 0x64,
+	0xf8, 0x8c, 0x73, 0xa6, 0x0f, 0xff, 0xd9, 0x8b, 0x7b, 0x85, 0xb7, 0x7d,
+	0x7d, 0x14, 0xc5, 0x3d, 0x0d, 0xe8, 0x3c, 0xc7, 0xb0, 0xe9, 0x87, 0xc5,
+	0xb8, 0xa7, 0xe2, 0x98, 0xcb, 0xb9, 0xb8, 0x3a, 0x97, 0x08, 0x65, 0xba,
+	0xe9, 0x91, 0xd5, 0x45, 0x3f, 0x8b, 0xf3, 0x47, 0xf8, 0xba, 0x84, 0x9c,
+	0xa3, 0x36, 0xca, 0x64, 0xbb, 0x69, 0xb3, 0x14, 0x66, 0x71, 0x05, 0xec,
+	0x44, 0xb9, 0x4c, 0x81, 0xa6, 0xd6, 0x5f, 0xeb, 0x83, 0x1f, 0x66, 0x52,
+	0xab, 0x61, 0xe9, 0x51, 0x00, 0x96, 0x7e, 0xa9, 0xc3, 0xd2, 0xd1, 0xbe,
+	0xe6, 0x58, 0xea, 0x77, 0x62, 0xd6, 0xa3, 0x14, 0x71, 0x70, 0xf4, 0x39,
+	0xe3, 0xe8, 0x3d, 0xc6, 0xd1, 0xf1, 0x06, 0x38, 0xd2, 0x3c, 0x38, 0x3a,
+	0x51, 0x87, 0xa3, 0x6c, 0x5f, 0x33, 0x1c, 0x1d, 0x0f, 0xa1, 0xff, 0xcd,
+	0xd6, 0x32, 0xfa, 0xb0, 0x9f, 0x39, 0xbd, 0x49, 0xa5, 0xd5, 0xe4, 0xf8,
+	0x24, 0x55, 0x90, 0x73, 0x92, 0x58, 0xa2, 0xb4, 0xe0, 0x76, 0x05, 0x81,
+	0xbf, 0x2c, 0x8f, 0xc9, 0xae, 0x06, 0xe7, 0xaa, 0x24, 0x9c, 0x79, 0x93,
+	0x73, 0x99, 0xc9, 0x57, 0x66, 0x1f, 0x32, 0x36, 0xee, 0x6d, 0xe8, 0x3a,
+	0x7e, 0x0b, 0xb1, 0x8c, 0xbc, 0xbb, 0x81, 0x73, 0x5b, 0xe2, 0x74, 0xdf,
+	0x1a, 0xa0, 0x7b, 0xd6, 0x7e, 0xba, 0x6b, 0x0d, 0xd2, 0x03, 0x0b, 0x6d,
+	0x60, 0x0e, 0xf8, 0x5e, 0xcc, 0x81, 0x46, 0x33, 0x31, 0x2e, 0x53, 0xda,
+	0x4f, 0x95, 0x92, 0xc2, 0x35, 0xb0, 0x03, 0x0c, 0x35, 0xc6, 0x4e, 0xa6,
+	0x0e, 0x3b, 0xb2, 0x0e, 0x30, 0xb3, 0xe4, 0xb7, 0xad, 0xed, 0x32, 0xf8,
+	0x5d, 0x0d, 0xc6, 0x56, 0x58, 0xc4, 0x91, 0x24, 0x47, 0x67, 0x42, 0x90,
+	0x59, 0xb7, 0x18, 0x53, 0x3c, 0x17, 0x3c, 0x7e, 0xda, 0xf5, 0x41, 0x96,
+	0x39, 0x4f, 0x09, 0x1b, 0xf4, 0x94, 0xa9, 0xc7, 0x33, 0x64, 0x5f, 0xd6,
+	0xcc, 0x31, 0x91, 0xeb, 0xb6, 0x54, 0xf6, 0x9e, 0x31, 0x91, 0xe1, 0xb1,
+	0x57, 0x78, 0xf4, 0xca, 0xa1, 0x76, 0xaa, 0x38, 0x31, 0x4c, 0x85, 0x55,
+	0xdb, 0x7e, 0xc8, 0xfc, 0x7f, 0xcd, 0x84, 0xcc, 0xfe, 0xdb, 0xae, 0xc4,
+	0x74, 0x5a, 0x36, 0x55, 0xdf, 0xee, 0x08, 0x7c, 0x31, 0x47, 0xa4, 0x77,
+	0x37, 0xaa, 0xaf, 0xc4, 0xbf, 0xe3, 0xbb, 0xbf, 0x04, 0x97, 0x59, 0xab,
+	0x96, 0x85, 0xed, 0xf8, 0xd2, 0xd8, 0xc2, 0x2a, 0xce, 0x7e, 0x7b, 0xfc,
+	0xea, 0xf9, 0xd5, 0x5c, 0x1f, 0x4b, 0xd8, 0x94, 0x4e, 0x76, 0x68, 0x79,
+	0x3c, 0xf7, 0x5c, 0x98, 0x86, 0x19, 0x97, 0x38, 0x83, 0x6b, 0x6c, 0x34,
+	0x2c, 0xce, 0x38, 0xd9, 0xcd, 0x78, 0xc8, 0x0a, 0x3b, 0xfd, 0xd4, 0x91,
+	0x09, 0x9a, 0x2c, 0xa7, 0xf9, 0x53, 0x3f, 0x7e, 0xb5, 0xb9, 0xe3, 0xe1,
+	0x48, 0xe3, 0x37, 0x37, 0xff, 0xa8, 0xd5, 0x9d, 0xe6, 0xba, 0x33, 0x5b,
+	0xd6, 0x55, 0xe7, 0x12, 0xfd, 0x03, 0x69, 0xae, 0x1b, 0xa3, 0xbc, 0x57,
+	0x00, 0x00, 0x00 };
 
 static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = {
@@ -989,952 +687,368 @@
 static int bnx2_RXP_b06FwBssLen = 0x13a4;
 static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0;
 static int bnx2_RXP_b06FwSbssLen = 0x1c;
-static u32 bnx2_RXP_b06FwText[(0x588c/4) + 1] = {
-	0x0a000c61, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x322e362e,
-	0x31000000, 0x02060103, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d,
-	0x3c020800, 0x244258e0, 0x3c030800, 0x24636ca4, 0xac400000, 0x0043202b,
-	0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800,
-	0x26103184, 0x3c1c0800, 0x279c58e0, 0x0e00104a, 0x00000000, 0x0000000d,
-	0x27bdffe8, 0xafb00010, 0xafbf0014, 0x0e000f1d, 0x00808021, 0x1440000d,
-	0x00000000, 0x8f820010, 0x10400005, 0x00000000, 0x9743011c, 0x9742011e,
-	0x0a000c89, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
-	0xaf830004, 0x8f840008, 0x3c020020, 0x34424000, 0x00821824, 0x54620004,
-	0x3c020020, 0x8f820014, 0x0a000c9a, 0x34421000, 0x34428000, 0x00821824,
-	0x14620004, 0x00000000, 0x8f820014, 0x34428000, 0xaf820014, 0x8f820008,
-	0x9743010c, 0x00403021, 0x30421000, 0x10400010, 0x3069ffff, 0x30c20020,
-	0x1440000e, 0x24070005, 0x3c021000, 0x00c21024, 0x10400009, 0x3c030dff,
-	0x3463ffff, 0x3c020e00, 0x00c21024, 0x0062182b, 0x50600004, 0x24070001,
-	0x0a000cb2, 0x3c020800, 0x24070001, 0x3c020800, 0x8c430034, 0x1460001d,
-	0x00405821, 0x8f820014, 0x30424000, 0x1440001a, 0x3c020001, 0x3c021f01,
-	0x00c24024, 0x3c031000, 0x15030015, 0x3c020001, 0x31220200, 0x14400012,
-	0x3c020001, 0x9744010e, 0x24020003, 0xa342018b, 0x97850016, 0x24020002,
-	0x34e30002, 0xaf400180, 0xa742018c, 0xa7430188, 0x24840004, 0x30a5bfff,
-	0xa744018e, 0xa74501a6, 0xaf4801b8, 0x0a000f19, 0x00001021, 0x3c020001,
-	0x00c21024, 0x1040002f, 0x00000000, 0x9742010e, 0x3c038000, 0x3046ffff,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9784000a,
-	0x8f850004, 0x8f870014, 0x24020080, 0x24030002, 0xaf420180, 0x24020003,
-	0xa743018c, 0xa746018e, 0xa7420188, 0x30e28000, 0xa7440190, 0x1040000c,
-	0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
-	0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014,
-	0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
-	0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19,
-	0x00001021, 0x8f820014, 0x30434000, 0x10600016, 0x00404021, 0x3c020f00,
-	0x00c21024, 0x14400012, 0x00000000, 0x93420116, 0x34424000, 0x03421821,
-	0x94650002, 0x2ca21389, 0x1040000b, 0x3c020800, 0x24425900, 0x00051942,
-	0x00031880, 0x00621821, 0x30a5001f, 0x8c640000, 0x24020001, 0x00a21004,
-	0x00822024, 0x02048025, 0x12000030, 0x3c021000, 0x9742010e, 0x34e80002,
-	0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180,
-	0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
-	0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
-	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-	0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
-	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-	0xaf4201b8, 0x0a000f19, 0x00001021, 0x00c21024, 0x104000c0, 0x3c020800,
-	0x8c430030, 0x10600037, 0x31024000, 0x10400035, 0x3c030f00, 0x00c31824,
-	0x3c020100, 0x0043102b, 0x14400031, 0x3c030800, 0x9742010e, 0x34e80002,
-	0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020080,
-	0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000,
-	0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
-	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-	0x00e21024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
-	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-	0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008,
-	0x10400035, 0x34ea0002, 0x3c020f00, 0x00c21024, 0x14400032, 0x8d620034,
-	0x31220200, 0x1040002f, 0x8d620034, 0x9742010e, 0x30e8fffb, 0x3c038000,
-	0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
-	0xa342018b, 0x9784000a, 0x8f850004, 0x8f870014, 0x24020180, 0x24030002,
-	0xaf420180, 0xa743018c, 0xa746018e, 0xa7480188, 0x30e28000, 0xa7440190,
-	0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00e21024,
-	0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
-	0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-	0x8d620034, 0x8f860008, 0x10400012, 0x30c20100, 0x10400010, 0x3c020f00,
-	0x00c21024, 0x3c030200, 0x1043000c, 0x3c020800, 0x8c430038, 0x8f840004,
-	0x3c020800, 0x2442003c, 0x2463ffff, 0x00832024, 0x00822021, 0x90830000,
-	0x24630004, 0x0a000de1, 0x000329c0, 0x00000000, 0x00061602, 0x3042000f,
-	0x000229c0, 0x3c04fc00, 0x00441021, 0x3c030300, 0x0062182b, 0x50600001,
-	0x24050800, 0x9742010e, 0x3148ffff, 0x3c038000, 0x24420004, 0x3046ffff,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
-	0x8f840004, 0x8f870014, 0x24020002, 0xaf450180, 0xa742018c, 0xa746018e,
-	0xa7480188, 0x30e28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
-	0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
-	0x3c02ffff, 0x34427fff, 0x00e21024, 0xaf820014, 0x97820016, 0x9743010c,
-	0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
-	0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x8f424000,
-	0x30420100, 0x104000d5, 0x3c020800, 0x8c440024, 0x24030001, 0x1483002f,
-	0x00405021, 0x9742010e, 0x34e70002, 0x3c038000, 0x24420004, 0x3045ffff,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
-	0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c, 0xa745018e,
-	0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116,
-	0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
-	0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016, 0x9743010c,
-	0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
-	0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x30820001,
-	0x1040002e, 0x30eb0004, 0x9742010e, 0x30e9fffb, 0x3c038000, 0x24420004,
-	0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
-	0x9783000a, 0x8f840004, 0x8f860014, 0x24020002, 0xaf400180, 0xa742018c,
-	0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190, 0x1040000c, 0xaf4401a8,
-	0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff,
-	0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024, 0xaf820014, 0x97820016,
-	0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825,
-	0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x3127ffff, 0x8d420024,
-	0x30420004, 0x10400030, 0x8d420024, 0x9742010e, 0x30e9fffb, 0x3c038000,
-	0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
-	0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020100, 0x24030002,
-	0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000, 0xa7440190,
-	0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x01021024,
-	0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
-	0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-	0x3127ffff, 0x8d420024, 0x30420008, 0x1040002d, 0x00000000, 0x9742010e,
-	0x3c038000, 0x24420004, 0x3046ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x24020003, 0xa342018b, 0x9784000a, 0x8f850004, 0x8f880014, 0x24020180,
-	0x24030002, 0xaf420180, 0xa743018c, 0xa746018e, 0xa7470188, 0x31028000,
-	0xa7440190, 0x1040000c, 0xaf4501a8, 0x93420116, 0x304200fc, 0x005a1021,
-	0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
-	0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff,
-	0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
-	0xaf4201b8, 0x15600041, 0x00001021, 0x27440180, 0x3c038000, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008, 0xa083000b,
-	0xa4800010, 0x3c021000, 0xaf4201b8, 0x0a000f19, 0x00001021, 0x3c030800,
-	0x8c620024, 0x30420001, 0x1040002e, 0x00001021, 0x9742010e, 0x34e70002,
-	0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x24020003, 0xa342018b, 0x9783000a, 0x8f840004, 0x8f860014, 0x24020002,
-	0xaf400180, 0xa742018c, 0xa745018e, 0xa7470188, 0x30c28000, 0xa7430190,
-	0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
-	0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00c21024,
-	0xaf820014, 0x97820016, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
-	0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
-	0x00001021, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x8f4b0070,
-	0x93420112, 0x8f840008, 0x00022882, 0x30820100, 0x14400003, 0x24a30003,
-	0x03e00008, 0x00001021, 0x30824000, 0x10400010, 0x27424000, 0x00031880,
-	0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
-	0x8c490000, 0x93430116, 0x27424000, 0x306300fc, 0x00431021, 0x8c4a0000,
-	0x0a000f45, 0x3c030800, 0x30822000, 0x1040ffea, 0x00031880, 0x27424000,
-	0x00431021, 0x8c470000, 0x24a30004, 0x00031880, 0x27424000, 0x00431021,
-	0x8c490000, 0x00005021, 0x3c030800, 0x24680100, 0x00071602, 0x00021080,
-	0x00481021, 0x8c460000, 0x00071b82, 0x306303fc, 0x01031821, 0x8c640400,
-	0x00071182, 0x304203fc, 0x01021021, 0x8c450800, 0x30e300ff, 0x00031880,
-	0x01031821, 0x00091602, 0x00021080, 0x01021021, 0x00c43026, 0x8c640c00,
-	0x8c431000, 0x00c53026, 0x00091382, 0x304203fc, 0x01021021, 0x8c451400,
-	0x312200ff, 0x00021080, 0x01021021, 0x00c43026, 0x00c33026, 0x00091982,
-	0x306303fc, 0x01031821, 0x8c641800, 0x8c431c00, 0x00c53026, 0x00c43026,
-	0x11400015, 0x00c33026, 0x000a1602, 0x00021080, 0x01021021, 0x8c432000,
-	0x000a1382, 0x304203fc, 0x01021021, 0x8c452400, 0x314200ff, 0x00021080,
-	0x01021021, 0x00c33026, 0x000a1982, 0x306303fc, 0x01031821, 0x8c642800,
-	0x8c432c00, 0x00c53026, 0x00c43026, 0x00c33026, 0x8f430070, 0x3c050800,
-	0x8ca43100, 0x2c820020, 0x10400008, 0x006b5823, 0x3c020800, 0x24423104,
-	0x00041880, 0x00621821, 0x24820001, 0xac6b0000, 0xaca23100, 0xaf860004,
-	0x03e00008, 0x24020001, 0x27bdffe8, 0xafbf0010, 0x8f460128, 0x8f840010,
-	0xaf460020, 0x8f450104, 0x8f420100, 0x24030800, 0xaf850008, 0xaf820014,
-	0xaf4301b8, 0x1080000a, 0x3c020800, 0x8c430034, 0x10600007, 0x30a22000,
-	0x10400005, 0x34a30100, 0x8f82000c, 0xaf830008, 0x24420001, 0xaf82000c,
-	0x3c020800, 0x8c4300c0, 0x10600006, 0x3c030800, 0x8c6200c4, 0x24040001,
-	0x24420001, 0x0a000fd5, 0xac6200c4, 0x8f820008, 0x3c030010, 0x00431024,
-	0x14400009, 0x3c02001f, 0x3c030800, 0x8c620020, 0x00002021, 0x24420001,
-	0x0e000c78, 0xac620020, 0x0a000fd5, 0x00402021, 0x3442ff00, 0x14c20009,
-	0x2403bfff, 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e000c78,
-	0xac620020, 0x0a000fd5, 0x00402021, 0x8f820014, 0x00431024, 0x14400006,
-	0x00000000, 0xaf400048, 0x0e0011a9, 0xaf400040, 0x0a000fd5, 0x00402021,
-	0x0e001563, 0x00000000, 0x00402021, 0x10800005, 0x3c024000, 0x8f430124,
-	0x3c026020, 0xac430014, 0x3c024000, 0xaf420138, 0x00000000, 0x8fbf0010,
-	0x03e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010,
-	0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000, 0x00621824, 0x3c023000,
-	0x10620021, 0x0043102b, 0x14400006, 0x3c024000, 0x3c022000, 0x10620009,
-	0x3c024000, 0x0a001040, 0x00000000, 0x10620045, 0x3c025000, 0x10620047,
-	0x3c024000, 0x0a001040, 0x00000000, 0x27440180, 0x3c038000, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x00000000, 0x8f420148, 0x24030002, 0xa083000b,
-	0x00021402, 0xa4820008, 0x8f430148, 0xa4830010, 0x8f420144, 0x3c031000,
-	0xac820024, 0xaf4301b8, 0x0a001040, 0x3c024000, 0x8f420148, 0x24030002,
-	0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
-	0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001027, 0x3c038000,
-	0x12020007, 0x00000000, 0x0a001034, 0x00000000, 0x0e00112c, 0x00000000,
-	0x0a001025, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
-	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
-	0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
-	0x0a001040, 0x3c024000, 0x0000000d, 0x00000000, 0x240002bf, 0x0a001040,
-	0x3c024000, 0x0e001441, 0x00000000, 0x0a001040, 0x3c024000, 0x0e0015ea,
-	0x00000000, 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014,
-	0x8fb00010, 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8,
-	0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
-	0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
-	0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
-	0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
-	0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
-	0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
-	0x8e021980, 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd,
-	0x32020001, 0x10400004, 0x32020002, 0x0e000f92, 0x00000000, 0x32020002,
-	0x1040fff6, 0x00000000, 0x0e000fe0, 0x00000000, 0x0a001071, 0x00000000,
-	0x27bdffe8, 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000,
-	0x2403ff7f, 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000,
-	0x3c020008, 0xaf430008, 0x8e040808, 0x0342d825, 0x8e020808, 0x3c030800,
-	0xac600020, 0x3084fff0, 0x2c840001, 0x3042fff0, 0x38420010, 0x2c420001,
-	0xaf840010, 0xaf820000, 0x0e00160c, 0x00000000, 0x0e001561, 0x00000000,
-	0x3c020400, 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c,
-	0x8e021980, 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008,
-	0x27bd0018, 0x00804821, 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x9783000a,
-	0x8f840004, 0x8f880014, 0xaf490180, 0xa745018c, 0xa746018e, 0xa7470188,
-	0x31028000, 0xa7430190, 0x1040000c, 0xaf4401a8, 0x93420116, 0x304200fc,
-	0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
-	0x34427fff, 0x01021024, 0xaf820014, 0x97820016, 0x9743010c, 0x8f440104,
-	0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
-	0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000, 0x27440180, 0x3c038000,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x24022000, 0x24030002, 0xa4820008,
-	0xa083000b, 0xa4800010, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00000000,
-	0x27440180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
-	0x8f420148, 0x24030002, 0xa083000b, 0x00021402, 0xa4820008, 0x8f430148,
-	0xa4830010, 0x8f420144, 0x3c031000, 0xac820024, 0x03e00008, 0xaf4301b8,
-	0x27bdffe0, 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002,
-	0x3044ffff, 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003,
-	0x10400005, 0x24020003, 0x0600001d, 0x36053000, 0x0a001117, 0x3c038000,
-	0x12020007, 0x00000000, 0x0a001124, 0x00000000, 0x0e00112c, 0x00000000,
-	0x0a001115, 0x00402021, 0x0e00113e, 0x00000000, 0x00402021, 0x36053000,
-	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008,
-	0xa222000b, 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8,
-	0x0a001128, 0x8fbf0018, 0x0000000d, 0x00000000, 0x240002bf, 0x8fbf0018,
-	0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389,
-	0x1040000d, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
-	0x00a32821, 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025,
-	0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389,
-	0x1040000e, 0x00001021, 0x3c030800, 0x24635900, 0x00042942, 0x00052880,
-	0x00a32821, 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827,
-	0x00832024, 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x9482000c,
-	0x24870014, 0x00021302, 0x00021080, 0x00824021, 0x00e8182b, 0x1060004f,
-	0x00000000, 0x90e30000, 0x2c620009, 0x10400047, 0x3c020800, 0x24425890,
-	0x00031880, 0x00621821, 0x8c640000, 0x00800008, 0x00000000, 0x0a0011a4,
-	0x24e70001, 0x90e30001, 0x2402000a, 0x54620024, 0x01003821, 0x01071023,
-	0x2c42000a, 0x54400020, 0x01003821, 0x3c050800, 0x8ca26c98, 0x24e70002,
-	0x34420100, 0xaca26c98, 0x90e30000, 0x90e20001, 0x90e40002, 0x90e60003,
-	0x24e70004, 0x24a56c98, 0x00031e00, 0x00021400, 0x00621825, 0x00042200,
-	0x00641825, 0x00661825, 0xaca30004, 0x90e20000, 0x90e30001, 0x90e40002,
-	0x90e60003, 0x24e70004, 0x00021600, 0x00031c00, 0x00431025, 0x00042200,
-	0x00441025, 0x00461025, 0x0a0011a4, 0xaca20008, 0x90e30001, 0x24020004,
-	0x1062000e, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020003,
-	0x10620008, 0x00601021, 0x0a00119e, 0x01001021, 0x90e30001, 0x24020002,
-	0x14620003, 0x01001021, 0x00601021, 0x00e21021, 0x0a0011a4, 0x00403821,
-	0x90e20001, 0x0a0011a4, 0x00e23821, 0x01003821, 0x00e8102b, 0x5440ffb4,
-	0x90e30000, 0x03e00008, 0x24020001, 0x27bdff90, 0x3c030800, 0xafbf006c,
-	0xafbe0068, 0xafb70064, 0xafb60060, 0xafb5005c, 0xafb40058, 0xafb30054,
-	0xafb20050, 0xafb1004c, 0xafb00048, 0xac606c98, 0x93620023, 0x30420010,
-	0x1440027c, 0x24020001, 0x93420116, 0x93630005, 0x34424000, 0x30630001,
-	0x14600005, 0x0342b021, 0x0e0015e0, 0x00000000, 0x0a001436, 0x8fbf006c,
-	0x93420112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x10600012,
-	0x03422821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x00000000, 0x8f420128, 0xaca20000, 0x8f640040, 0x24030008, 0x240240c1,
-	0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000, 0x0a0011f1, 0xa0a3000a,
-	0x8f420104, 0x3c030040, 0x00431024, 0x1040001d, 0x3c038000, 0x27450180,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
-	0x8f640040, 0x24030010, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a3000a,
-	0x24030008, 0xa0a2000b, 0x3c021000, 0xa4a30010, 0xa0a00012, 0xa0a00013,
-	0xaca00014, 0xaca00024, 0xaca00028, 0xaca0002c, 0xaca40018, 0x0e0015e0,
-	0xaf4201b8, 0x0a001436, 0x8fbf006c, 0x8f820000, 0x10400016, 0x00000000,
-	0x8f420104, 0x3c030001, 0x00431024, 0x10400011, 0x00000000, 0x8ca3000c,
-	0x8f620030, 0x1462022d, 0x24020001, 0x8ca30010, 0x8f62002c, 0x14620229,
-	0x24020001, 0x9763003a, 0x96c20000, 0x14430225, 0x24020001, 0x97630038,
-	0x96c20002, 0x14430221, 0x24020001, 0xaf400048, 0xaf400054, 0xaf400040,
-	0x8f740040, 0x8f650048, 0x00b43023, 0x04c10004, 0x00000000, 0x0000000d,
-	0x00000000, 0x240001af, 0x9742011a, 0x3052ffff, 0x12400004, 0x8ed30004,
-	0x02721021, 0x0a001228, 0x2451ffff, 0x02608821, 0x92d7000d, 0xa7a00020,
-	0xa3a0001a, 0xafa00028, 0x9362003f, 0x32e30004, 0x1060003a, 0x305000ff,
-	0x24040012, 0x16040006, 0x24020001, 0x3c040800, 0x8c830028, 0x24630001,
-	0x0a001328, 0xac830028, 0x8f620044, 0x16620010, 0x27a60010, 0x27450180,
-	0x3c038000, 0x2402001a, 0xa7a20020, 0x24020020, 0xafb40028, 0xa3b00022,
-	0xa3a40023, 0xa3a2001a, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000,
-	0x0a00130d, 0x00000000, 0x8f620044, 0x02621023, 0x0440001a, 0x02651023,
-	0x044100d9, 0x24020001, 0x3c020800, 0x8c4300d8, 0x10600004, 0x24020001,
-	0xa7a20020, 0x0a00125e, 0xafb40028, 0x2402001a, 0xa7a20020, 0x24020020,
-	0xafb40028, 0xa3b00022, 0xa3a40023, 0xa3a2001a, 0x27a60010, 0x27450180,
-	0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d,
-	0x00000000, 0x0a001328, 0x24020001, 0x0293f023, 0x1bc00016, 0x025e102a,
-	0x54400007, 0x32f700fe, 0x57d2000f, 0x027e9821, 0x32e20001, 0x5440000c,
-	0x027e9821, 0x32f700fe, 0x0240f021, 0x3c040800, 0x8c8300c8, 0x00009021,
-	0x24020001, 0xa7a20020, 0xafb40028, 0x24630001, 0x0a001282, 0xac8300c8,
-	0x025e1023, 0x0a001282, 0x3052ffff, 0x0000f021, 0x24a2ffff, 0x02221823,
-	0x1860001f, 0x0072102a, 0x54400019, 0x00a08821, 0x97a20020, 0x3c040800,
-	0x8c8300cc, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020, 0x02741026,
-	0x2c420001, 0xac8300cc, 0x2cc30001, 0x00431024, 0x1440000a, 0x02401821,
-	0x27a60010, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
-	0x00000000, 0x0a00130d, 0x00000000, 0x00a08821, 0x02431023, 0x3052ffff,
-	0x0a0012ae, 0x32f700f6, 0x02741023, 0x18400008, 0x97a20020, 0x3c040800,
-	0x8c8300d4, 0xafb30028, 0x34420400, 0x24630001, 0xa7a20020, 0xac8300d4,
-	0x32e20002, 0x1040001c, 0x32e20010, 0x8f620044, 0x1662000d, 0x27a60010,
-	0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
-	0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001, 0xa7a20020,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x0a00130d, 0x00000000,
-	0x54400003, 0x8ed50008, 0x0a001328, 0x24020001, 0x8f630054, 0x26a2ffff,
-	0x00431023, 0x18400011, 0x27a60010, 0x97a20020, 0x3c040800, 0x8c8300d0,
-	0x27450180, 0x3c078000, 0xafb40028, 0x34420001, 0x24630001, 0xa7a20020,
-	0xac8300d0, 0x8f4201b8, 0x00471024, 0x1440fffd, 0x00000000, 0x0a00130d,
-	0x00000000, 0x32e20020, 0x10400011, 0x00000000, 0x96c20012, 0x0052102b,
-	0x10400008, 0x97a20020, 0x96d20012, 0x12400003, 0x02721021, 0x0a0012f2,
-	0x2451ffff, 0x02608821, 0x97a20020, 0x93a3001a, 0x34420008, 0x34630004,
-	0xa7a20020, 0xa3a3001a, 0x8f420104, 0x3c030080, 0x00431024, 0x10400037,
-	0x3a03000a, 0x0e001151, 0x02c02021, 0x24030002, 0x1443002b, 0x3c030800,
-	0x27a60010, 0x97a20020, 0x27450180, 0x3c038000, 0xafb40028, 0x34420001,
-	0xa7a20020, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128,
-	0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a,
-	0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012,
-	0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024,
-	0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000,
-	0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a001436, 0x8fbf006c,
-	0x8c626c98, 0x30420100, 0x10400003, 0x24636c98, 0x8c620004, 0xaf62017c,
-	0x3a03000a, 0x2c630001, 0x3a02000c, 0x2c420001, 0x00621825, 0x14600003,
-	0x2402000e, 0x56020030, 0x00009021, 0x52400008, 0x96c4000e, 0x12400004,
-	0xa7b20040, 0x02721021, 0x0a001343, 0x2451ffff, 0x02608821, 0x96c4000e,
-	0x93630035, 0x8f62004c, 0x00642004, 0x00952021, 0x00821023, 0x18400015,
-	0x00000000, 0x8f620018, 0x02621023, 0x1c400015, 0x97a20020, 0x8f620018,
-	0x1662001c, 0x00000000, 0x8f62001c, 0x02a21023, 0x1c40000e, 0x97a20020,
-	0x8f62001c, 0x16a20015, 0x00000000, 0x8f620058, 0x00821023, 0x18400011,
-	0x97a20020, 0x0a001364, 0xafb10028, 0x8f620058, 0x00821023, 0x0441000b,
-	0x97a20020, 0xafb10028, 0xafb30034, 0xafb50038, 0xafa4003c, 0x34420020,
-	0x0a00136d, 0xa7a20020, 0x02809821, 0x02608821, 0x8f640058, 0x8f62004c,
-	0x02a21023, 0x18400009, 0x00000000, 0x8f620054, 0x02a21023, 0x1c400005,
-	0x97a20020, 0xafb10028, 0xafb50024, 0x0a001385, 0x34420040, 0x9742011a,
-	0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c,
-	0x8f620054, 0x10620004, 0x97a20020, 0xafb10028, 0x34420080, 0xa7a20020,
-	0x24020014, 0x1202000a, 0x2a020015, 0x10400005, 0x2402000c, 0x12020006,
-	0x32e20001, 0x0a0013c6, 0x00000000, 0x24020016, 0x16020035, 0x32e20001,
-	0x8f620084, 0x24420001, 0x16a20031, 0x32e20001, 0x24020014, 0x12020021,
-	0x2a020015, 0x10400005, 0x2402000c, 0x12020008, 0x32e20001, 0x0a0013c6,
-	0x00000000, 0x24020016, 0x1202000c, 0x32e20001, 0x0a0013c6, 0x00000000,
-	0x97a30020, 0x2402000e, 0xafb10028, 0xa3b00022, 0xa3a20023, 0xafb50024,
-	0x34630054, 0x0a0013c5, 0xa7a30020, 0x97a20020, 0x93a4001a, 0x24030010,
-	0xafb10028, 0xa3b00022, 0xa3a30023, 0xafb50024, 0x3442005d, 0x34840002,
-	0xa7a20020, 0x0a0013c5, 0xa3a4001a, 0x97a20020, 0x24030012, 0xa3a30023,
-	0x93a3001a, 0xafb10028, 0xa3b00022, 0xafb50024, 0x3042fffe, 0x3442005c,
-	0x34630002, 0xa7a20020, 0xa3a3001a, 0x32e20001, 0x10400030, 0x2402000c,
-	0x12020013, 0x2a02000d, 0x10400005, 0x2402000a, 0x12020008, 0x97a20020,
-	0x0a0013f8, 0x32e20009, 0x2402000e, 0x1202001b, 0x32e20009, 0x0a0013f9,
-	0x0002102b, 0x93a4001a, 0x24030008, 0xafb10028, 0xa3b00022, 0xa3a30023,
-	0x0a0013f4, 0x34420013, 0x97a30020, 0x30620004, 0x14400005, 0x93a2001a,
-	0x3463001b, 0xa7a30020, 0x0a0013e7, 0x24030016, 0x3463001b, 0xa7a30020,
-	0x24030010, 0xafb10028, 0xa3b00022, 0xa3a30023, 0x34420002, 0x0a0013f7,
-	0xa3a2001a, 0x97a20020, 0x93a4001a, 0x24030010, 0xafb10028, 0xa3b00022,
-	0xa3a30023, 0x3442001b, 0x34840002, 0xa7a20020, 0xa3a4001a, 0x32e20009,
-	0x0002102b, 0x00021023, 0x30420007, 0x12400015, 0x34450003, 0x8f820018,
-	0x24030800, 0x27440180, 0x24420001, 0xaf820018, 0x24020004, 0xaf4301b8,
-	0xa4850008, 0xa082000b, 0x93430120, 0x00003021, 0x3c021000, 0xa492000e,
-	0xac950024, 0xac930028, 0x007e1821, 0xa483000c, 0xaf4201b8, 0x0a001413,
-	0x97a20020, 0x24060001, 0x97a20020, 0x10400020, 0x27450180, 0x3c038000,
-	0x8f4201b8, 0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000,
-	0x8fa30028, 0x240240c1, 0xa4a20008, 0xaca30018, 0x93a4001a, 0x24020002,
-	0xa0a2000b, 0xa0a4000a, 0x97a20020, 0xa4a20010, 0x93a30022, 0xa0a30012,
-	0x93a20023, 0xa0a20013, 0x8fa30024, 0xaca30014, 0x8fa20034, 0xaca20024,
-	0x8fa30038, 0xaca30028, 0x8fa2003c, 0x3c031000, 0xaca2002c, 0xaf4301b8,
-	0x00c01021, 0x8fbf006c, 0x8fbe0068, 0x8fb70064, 0x8fb60060, 0x8fb5005c,
-	0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 0x03e00008,
-	0x27bd0070, 0x8f470140, 0x8f460148, 0x3c028000, 0x00c24024, 0x00062c02,
-	0x30a300ff, 0x24020019, 0x106200e7, 0x27440180, 0x2862001a, 0x1040001f,
-	0x24020008, 0x106200be, 0x28620009, 0x1040000d, 0x24020001, 0x10620046,
-	0x28620002, 0x50400005, 0x24020006, 0x1060002e, 0x00a01821, 0x0a00155e,
-	0x00000000, 0x1062005b, 0x00a01821, 0x0a00155e, 0x00000000, 0x2402000b,
-	0x10620084, 0x2862000c, 0x10400005, 0x24020009, 0x106200bc, 0x00061c02,
-	0x0a00155e, 0x00000000, 0x2402000e, 0x106200b7, 0x00061c02, 0x0a00155e,
-	0x00000000, 0x28620021, 0x10400009, 0x2862001f, 0x104000c1, 0x2402001b,
-	0x106200bf, 0x2402001c, 0x1062009a, 0x00061c02, 0x0a00155e, 0x00000000,
-	0x240200c2, 0x106200ca, 0x286200c3, 0x10400005, 0x24020080, 0x1062005a,
-	0x00a01821, 0x0a00155e, 0x00000000, 0x240200c9, 0x106200cd, 0x30c5ffff,
-	0x0a00155e, 0x00000000, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
-	0x24020001, 0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a,
-	0xa083000b, 0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024,
-	0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808, 0x11000009, 0x00a01821,
-	0x3c020800, 0x24030002, 0xa0436c88, 0x24426c88, 0xac470008, 0x8f430144,
-	0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd,
-	0x24020002, 0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b,
-	0xa4860010, 0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x3c026000,
-	0xaf4301b8, 0x03e00008, 0xac400808, 0x3c080800, 0x3c058000, 0x8f4201b8,
-	0x00451024, 0x1440fffd, 0x00000000, 0xac870000, 0x91026c88, 0x00002821,
-	0x10400002, 0x25076c88, 0x8ce50008, 0xac850004, 0xa4830008, 0x91036c88,
-	0x24020002, 0xa082000b, 0xa4860010, 0x34630001, 0xa083000a, 0x8f420144,
-	0xac820024, 0x91036c88, 0x10600002, 0x00001021, 0x8ce20004, 0xac820028,
-	0x3c021000, 0xaf4201b8, 0x3c026000, 0xa1006c88, 0x03e00008, 0xac400808,
-	0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b,
-	0xa4830008, 0xa4860010, 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008,
-	0xaf4301b8, 0x30c2ffff, 0x14400028, 0x00061c02, 0x93620005, 0x30420004,
-	0x14400020, 0x3c029000, 0x34420001, 0x00e21025, 0xaf420020, 0x3c038000,
-	0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
-	0x34630001, 0x00e31825, 0x34420004, 0xa3620005, 0xaf430020, 0x93620005,
-	0x30420004, 0x14400003, 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x24020005, 0x3c031000, 0xac870000, 0xa082000b,
-	0xaf4301b8, 0x0a00150d, 0x00061c02, 0x0000000d, 0x03e00008, 0x00000000,
-	0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
-	0xa4830008, 0x24030002, 0xac870000, 0xac800004, 0xa082000a, 0xa083000b,
-	0xa4860010, 0x8f430144, 0x3c021000, 0xac800028, 0xac830024, 0x03e00008,
-	0xaf4201b8, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
-	0xac800000, 0xac870004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4860010,
-	0xac800024, 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8,
-	0x00061c02, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001,
-	0xa4830008, 0x24030002, 0xa082000a, 0x3c021000, 0xac870000, 0xac800004,
-	0xa083000b, 0xa4860010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8,
-	0x00a01821, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002,
-	0xac870000, 0xac800004, 0xa4830008, 0xa080000a, 0x0a001518, 0xa082000b,
-	0x8f440144, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
-	0x240340c9, 0xaf470180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4401a4,
-	0xaf4501a8, 0xaf4001ac, 0x03e00008, 0xaf4201b8, 0x0000000d, 0x03e00008,
-	0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011,
-	0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000,
-	0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040,
-	0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008,
-	0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002,
-	0x240340c9, 0xaf440180, 0xa342018b, 0x3c021000, 0xa7430188, 0xaf4501a4,
-	0xaf4601a8, 0xaf4701ac, 0x03e00008, 0xaf4201b8, 0x3c029000, 0x34420001,
-	0x00822025, 0xaf440020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
-	0x00000000, 0x03e00008, 0x00000000, 0x3c028000, 0x34420001, 0x00822025,
-	0x03e00008, 0xaf440020, 0x308600ff, 0x27450180, 0x3c038000, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8f640040,
-	0x24030008, 0x240240c1, 0xa4a20008, 0x24020002, 0xa0a2000b, 0x3c021000,
-	0xa0a6000a, 0xa4a30010, 0xa0a00012, 0xa0a00013, 0xaca00014, 0xaca00024,
-	0xaca00028, 0xaca0002c, 0xaca40018, 0x03e00008, 0xaf4201b8, 0x24020001,
-	0xacc40000, 0x03e00008, 0xa4e50000, 0x24020001, 0xaf400044, 0x03e00008,
-	0xaf400050, 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024,
-	0x1440fffd, 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1,
-	0xa4a20008, 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a,
-	0x94c20010, 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013,
-	0x8cc30014, 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028,
-	0x8cc2002c, 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044,
-	0x03e00008, 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e001047, 0x00000000,
-	0x00002021, 0x0e000c78, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018,
-	0x8f460148, 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8,
-	0x00431024, 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff,
-	0x00061c02, 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b,
-	0xaca30024, 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001,
-	0x24020005, 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a001609, 0xa0a2000a,
-	0xa0a0000a, 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021,
-	0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
-	0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00161f, 0x00a01021,
-	0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa,
-	0x24a5ffff, 0x03e00008, 0x00000000, 0x00000000 }; 
+static u8 bnx2_RXP_b06FwText[] = {
+	0x1f, 0x8b, 0x08, 0x08, 0x07, 0x87, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x5d, 0x6c,
+	0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x71, 0x49, 0x91, 0xd4, 0x70, 0xb9,
+	0x62, 0x57, 0x12, 0x65, 0xed, 0x8a, 0x43, 0x71, 0x6d, 0x31, 0xce, 0x50,
+	0x58, 0xdb, 0x82, 0xb1, 0x48, 0xc7, 0xb3, 0xa4, 0xc8, 0x24, 0x02, 0x42,
+	0x1b, 0x42, 0xab, 0xa4, 0xa9, 0xc1, 0x90, 0x72, 0x91, 0x22, 0x2c, 0xa0,
+	0x1a, 0x79, 0xf0, 0x43, 0x10, 0x2f, 0x56, 0x3f, 0xa6, 0xd1, 0x8d, 0x96,
+	0xb6, 0x1c, 0x53, 0x08, 0x82, 0x82, 0xe5, 0x52, 0x52, 0x0b, 0x2c, 0xb4,
+	0x96, 0xed, 0x36, 0x7e, 0xa8, 0x23, 0x9a, 0x92, 0x8d, 0xa6, 0x68, 0x81,
+	0x22, 0xad, 0xd1, 0xf4, 0x4d, 0x95, 0x9a, 0x4a, 0x75, 0x5f, 0xd4, 0xa2,
+	0x48, 0xda, 0x46, 0xcd, 0xf4, 0xfb, 0xee, 0xcc, 0x88, 0xd4, 0x9a, 0xb2,
+	0x2c, 0x3b, 0x0d, 0x62, 0x74, 0x0e, 0x30, 0xd8, 0xb9, 0x7f, 0xe7, 0xef,
+	0x9e, 0x73, 0xee, 0x39, 0x77, 0x28, 0x7d, 0xa5, 0x43, 0xda, 0x25, 0x84,
+	0x4e, 0x3c, 0x99, 0xc3, 0xcf, 0x3c, 0xfd, 0xe0, 0xc3, 0x0f, 0xee, 0xc1,
+	0xeb, 0xb0, 0xa1, 0x6d, 0xd0, 0xa3, 0xfe, 0x18, 0x62, 0x88, 0x21, 0x86,
+	0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62,
+	0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21,
+	0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18,
+	0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88,
+	0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0xff, 0xef, 0x60, 0x88, 0x58,
+	0xfc, 0xed, 0x0c, 0x1f, 0x49, 0xe8, 0x85, 0xcb, 0x07, 0x3d, 0x5b, 0x12,
+	0x46, 0x61, 0x69, 0x66, 0xda, 0x16, 0x71, 0xeb, 0xbb, 0x33, 0x45, 0xf9,
+	0x1f, 0xbf, 0x94, 0x32, 0x85, 0xfd, 0xdb, 0x0b, 0x37, 0x9f, 0x7d, 0xf3,
+	0x91, 0xec, 0x8d, 0x05, 0x43, 0x12, 0x56, 0xe1, 0xe8, 0xb0, 0xb5, 0x4b,
+	0x12, 0x7d, 0x58, 0xf3, 0xdd, 0xc1, 0xcf, 0x59, 0xd2, 0x15, 0xe1, 0xba,
+	0xee, 0xbf, 0x39, 0x68, 0xc9, 0x2b, 0x8d, 0x94, 0x5c, 0x68, 0x6c, 0xdf,
+	0x24, 0x5d, 0xd9, 0x52, 0x09, 0xfd, 0x6e, 0x8a, 0xe3, 0x96, 0x94, 0xab,
+	0x2d, 0xe2, 0x2a, 0xba, 0x7d, 0x5a, 0x71, 0xfe, 0x3e, 0xcd, 0x9b, 0x7f,
+	0x9e, 0xff, 0x1e, 0x24, 0xa5, 0xcb, 0x7d, 0x68, 0xf7, 0xa1, 0xcd, 0xf7,
+	0x81, 0xf4, 0x94, 0x98, 0x72, 0xa4, 0x91, 0x90, 0xa3, 0xd5, 0x8c, 0xe8,
+	0x05, 0x71, 0xbd, 0xbc, 0x9d, 0x2e, 0xa3, 0x6f, 0xea, 0x00, 0xdb, 0x29,
+	0xe0, 0xf9, 0x0e, 0xd7, 0x59, 0x5e, 0x5e, 0x4a, 0xb7, 0xc6, 0x14, 0x0d,
+	0x8e, 0xb1, 0x0f, 0xbf, 0x58, 0x5f, 0xae, 0x76, 0x00, 0x6f, 0xd6, 0x71,
+	0x41, 0xdc, 0x73, 0x2c, 0xd0, 0xf6, 0xfd, 0xdf, 0x75, 0x32, 0xb2, 0xe2,
+	0x74, 0x81, 0xa7, 0x16, 0x69, 0xb5, 0xc5, 0xd2, 0x0b, 0xb6, 0xb5, 0x22,
+	0x6d, 0x1c, 0xeb, 0x34, 0x0a, 0xbe, 0x3f, 0x9d, 0x97, 0xae, 0xa0, 0x6f,
+	0xb7, 0xe2, 0x63, 0x72, 0x42, 0xc3, 0xbc, 0x57, 0x49, 0x0f, 0x3a, 0xe2,
+	0x3b, 0x7f, 0xf3, 0x52, 0xac, 0x6c, 0x97, 0xc9, 0x54, 0xf6, 0xa0, 0x1b,
+	0xd0, 0x74, 0x3d, 0x67, 0x2b, 0x70, 0x6a, 0xe0, 0x4f, 0xdb, 0x81, 0xf5,
+	0xee, 0x0a, 0x68, 0x1a, 0x85, 0xcd, 0x62, 0x6c, 0x66, 0x9f, 0xe8, 0x3b,
+	0x87, 0x93, 0xe1, 0x78, 0x97, 0x36, 0x32, 0x6f, 0x88, 0x6e, 0xff, 0x81,
+	0xe6, 0xd5, 0x7a, 0xe5, 0xd8, 0xbc, 0x8e, 0x77, 0x5d, 0xae, 0xe6, 0x4b,
+	0x9a, 0xdb, 0xa8, 0x68, 0xde, 0xd9, 0x59, 0xad, 0x78, 0xd6, 0x94, 0xa3,
+	0xb6, 0x7f, 0xe1, 0xb4, 0x73, 0x42, 0x1b, 0x39, 0x7b, 0x46, 0x1b, 0x3d,
+	0xfb, 0x86, 0x36, 0xde, 0xd8, 0xb2, 0x49, 0xda, 0xb3, 0xd0, 0x1e, 0x71,
+	0x90, 0xbf, 0x4f, 0x87, 0xba, 0xec, 0xa2, 0xde, 0x4a, 0xe4, 0x7d, 0x9f,
+	0xf3, 0x86, 0xe6, 0x55, 0x6d, 0x8b, 0xfb, 0xe6, 0xa6, 0x22, 0x1a, 0xed,
+	0x72, 0x74, 0xde, 0x94, 0x63, 0xd5, 0x94, 0x3c, 0x57, 0x2d, 0x29, 0x5a,
+	0x86, 0x5d, 0xd2, 0xbc, 0x06, 0xc7, 0x2b, 0xa0, 0x75, 0x42, 0xdb, 0x07,
+	0x9a, 0xde, 0x59, 0x29, 0x5d, 0x71, 0xe6, 0x40, 0xaf, 0x03, 0x78, 0xff,
+	0x58, 0x1b, 0x6d, 0xf4, 0x6a, 0xde, 0xc9, 0x9b, 0xe2, 0x39, 0x59, 0xeb,
+	0x4b, 0x62, 0xba, 0xb0, 0x01, 0xc8, 0x0c, 0xfd, 0x38, 0xd0, 0x49, 0xca,
+	0xf7, 0xf5, 0x82, 0xff, 0x2c, 0x74, 0x6f, 0x5d, 0xa1, 0xfc, 0x8d, 0x5e,
+	0x29, 0xcf, 0x53, 0xd7, 0xa6, 0x36, 0x52, 0xf5, 0x2f, 0x78, 0x8e, 0xf4,
+	0x19, 0xe2, 0xfb, 0x47, 0x9d, 0x81, 0xf4, 0x21, 0x39, 0x03, 0xdc, 0x75,
+	0xad, 0xd8, 0xa0, 0xae, 0xc1, 0xdf, 0x2d, 0x39, 0x02, 0xbd, 0x15, 0x9d,
+	0x5e, 0x99, 0xb4, 0xb2, 0x2e, 0xf6, 0x68, 0x53, 0x20, 0x57, 0x32, 0xb4,
+	0x17, 0xd2, 0xe7, 0xde, 0x67, 0xd3, 0x9e, 0xa1, 0xcb, 0x53, 0x2f, 0x3d,
+	0xdf, 0xb3, 0x38, 0xb4, 0x91, 0x32, 0x43, 0xff, 0xf2, 0x45, 0xcf, 0xf6,
+	0xb6, 0xb4, 0x48, 0x29, 0x6d, 0x48, 0x16, 0xfb, 0xb4, 0x43, 0x4e, 0x3b,
+	0x22, 0x87, 0x2a, 0xd0, 0x8d, 0x6d, 0x5a, 0x8b, 0x62, 0x67, 0xca, 0x32,
+	0x50, 0x32, 0x75, 0x74, 0x26, 0x49, 0x97, 0x3a, 0xd2, 0xe5, 0x7a, 0x9e,
+	0x7a, 0xa2, 0x3d, 0x7f, 0x28, 0x5d, 0x69, 0xab, 0xba, 0x5a, 0xd5, 0xd3,
+	0xf8, 0x2f, 0x5d, 0x4f, 0xd4, 0xc9, 0x72, 0x28, 0xb7, 0x03, 0xdc, 0x8f,
+	0x40, 0x5f, 0xe2, 0xea, 0xc3, 0x0f, 0xb1, 0x6f, 0x93, 0x51, 0xb0, 0xd3,
+	0x17, 0x61, 0x14, 0x7a, 0x61, 0x37, 0x64, 0x19, 0xa6, 0xee, 0xe0, 0xc3,
+	0x1f, 0x49, 0x5e, 0xf9, 0xd5, 0x90, 0x97, 0xfc, 0xdb, 0x32, 0x55, 0x49,
+	0x80, 0x06, 0x65, 0xd4, 0xe5, 0xbd, 0x7c, 0x64, 0x1b, 0x7b, 0x20, 0x5f,
+	0x5e, 0xa6, 0xbe, 0x45, 0x7f, 0xa2, 0xfd, 0xf3, 0x9d, 0xb2, 0xfe, 0xcc,
+	0xbf, 0xee, 0x7c, 0x92, 0xf6, 0x96, 0x7c, 0x27, 0xe4, 0x78, 0x35, 0xc9,
+	0x3d, 0xd4, 0x56, 0x54, 0x6c, 0x8a, 0x64, 0x14, 0xdd, 0x28, 0x74, 0x48,
+	0x51, 0xed, 0xf7, 0x5e, 0xd0, 0x43, 0x2c, 0xa8, 0xf2, 0xbd, 0xa0, 0x64,
+	0x9b, 0xb6, 0xed, 0xcc, 0x11, 0xc9, 0xc2, 0xbe, 0x45, 0x8e, 0xcc, 0x99,
+	0x32, 0x6d, 0xff, 0x63, 0xa7, 0xb4, 0x2f, 0xdf, 0x6f, 0xa8, 0xb8, 0xae,
+	0xf7, 0x6e, 0x90, 0x4d, 0xe0, 0x77, 0xf9, 0x7e, 0x5d, 0xe4, 0xa6, 0x59,
+	0xc8, 0x5a, 0x23, 0x08, 0xf6, 0x46, 0x81, 0xb1, 0x4c, 0x43, 0x2c, 0x93,
+	0x44, 0x8b, 0x4d, 0x7d, 0xf9, 0xfe, 0xf8, 0xf0, 0xdd, 0xf5, 0x75, 0x64,
+	0x9e, 0xb4, 0xa9, 0x2f, 0xc6, 0xa8, 0x12, 0xf4, 0xc1, 0xf8, 0x74, 0xbb,
+	0xae, 0x8a, 0xa1, 0xae, 0x46, 0xfe, 0xef, 0xed, 0xc2, 0xf5, 0xaa, 0xa2,
+	0x79, 0xce, 0xbb, 0xa1, 0x2f, 0xd8, 0x32, 0x02, 0x7f, 0x37, 0xec, 0x4f,
+	0xcb, 0x91, 0x54, 0x76, 0xc2, 0x95, 0xc0, 0xe6, 0xaf, 0xad, 0xb1, 0xf9,
+	0xd1, 0xbb, 0xc8, 0x75, 0x3c, 0x94, 0xcb, 0x0d, 0xe5, 0x1a, 0x85, 0x5c,
+	0x63, 0x90, 0x6b, 0xe5, 0x23, 0xc8, 0xb5, 0xf2, 0x91, 0xe5, 0xd2, 0xa4,
+	0xec, 0x3c, 0x08, 0x5a, 0xa6, 0xfc, 0xab, 0x13, 0xd8, 0xf2, 0xbf, 0x38,
+	0x9f, 0x14, 0x19, 0x7c, 0x7f, 0x70, 0xd8, 0x16, 0xef, 0x5b, 0xe0, 0xd5,
+	0x71, 0x40, 0x8b, 0xef, 0xef, 0x97, 0xe1, 0x6e, 0xfe, 0x38, 0x8b, 0x7d,
+	0x5d, 0xcf, 0x1f, 0x29, 0x87, 0x3e, 0x7c, 0xef, 0xfe, 0xa8, 0x6b, 0x1f,
+	0x55, 0x0e, 0xc6, 0x9c, 0x4f, 0x35, 0x9d, 0xab, 0x1f, 0x56, 0x86, 0xf5,
+	0x63, 0xca, 0x2f, 0x4f, 0x86, 0xc7, 0x64, 0x72, 0x33, 0xed, 0xa9, 0xa4,
+	0x8d, 0x0c, 0x92, 0xef, 0xb5, 0xfc, 0x4a, 0x26, 0xe0, 0x0d, 0x39, 0xd1,
+	0xd2, 0x46, 0x39, 0xb2, 0x60, 0x49, 0x69, 0xe9, 0x4e, 0x71, 0x57, 0x03,
+	0x6f, 0xb4, 0x47, 0xf6, 0x7d, 0xd2, 0x7c, 0x2a, 0xc8, 0x2b, 0x2e, 0x54,
+	0x91, 0x83, 0x56, 0x13, 0x72, 0xd9, 0x48, 0xcb, 0x9b, 0x83, 0x87, 0xe5,
+	0xf3, 0xd5, 0x24, 0xe8, 0x31, 0x9f, 0x2c, 0xe7, 0x10, 0x17, 0xb5, 0xb2,
+	0x63, 0x08, 0x79, 0xaf, 0xd9, 0x9c, 0x13, 0xc4, 0x96, 0x72, 0x10, 0x83,
+	0x5d, 0x6f, 0x50, 0xe5, 0x14, 0x90, 0x4f, 0x64, 0x0c, 0xb1, 0xb7, 0x66,
+	0xb3, 0xcd, 0xfe, 0xa0, 0xef, 0xb3, 0x95, 0x5e, 0xad, 0xc8, 0xbc, 0x64,
+	0xf0, 0xa6, 0x4c, 0x3b, 0x41, 0xdf, 0xe7, 0x2a, 0xa3, 0x9b, 0x98, 0x1f,
+	0x1a, 0x05, 0xc9, 0x94, 0x9d, 0xf7, 0x7c, 0xd7, 0xba, 0x7d, 0xcd, 0xfa,
+	0x78, 0xb2, 0x13, 0x81, 0xce, 0x45, 0xfb, 0xaa, 0xad, 0xf7, 0xb6, 0x4a,
+	0x09, 0x27, 0x5d, 0xd6, 0x1a, 0x47, 0xe7, 0xbe, 0x4a, 0x79, 0x5b, 0xab,
+	0xdc, 0x34, 0x80, 0x3f, 0x6d, 0x68, 0x62, 0x1e, 0xaa, 0x94, 0xbb, 0xd9,
+	0xa6, 0xbe, 0x74, 0x4d, 0x12, 0xa3, 0x15, 0x5f, 0xae, 0x3a, 0x41, 0xee,
+	0x63, 0x68, 0x7a, 0x6f, 0x5b, 0xb8, 0x56, 0xd7, 0x76, 0x39, 0x97, 0x44,
+	0x3a, 0x0e, 0x55, 0xc4, 0x2a, 0x56, 0x76, 0x39, 0x6f, 0x4b, 0xb9, 0xa7,
+	0x6d, 0x75, 0x5d, 0x8a, 0xeb, 0x76, 0x0e, 0xaf, 0x9d, 0xbb, 0xcb, 0xb9,
+	0x28, 0xe5, 0x2d, 0x6d, 0xab, 0xb4, 0xd2, 0x58, 0xdb, 0x17, 0xac, 0xe5,
+	0xf8, 0x66, 0x71, 0xbb, 0x39, 0x47, 0xef, 0x6d, 0xbf, 0x45, 0x43, 0x32,
+	0xc5, 0x4a, 0xb9, 0xa7, 0x7d, 0x15, 0xaf, 0x4d, 0xbc, 0xde, 0x1a, 0xbc,
+	0xc4, 0xd9, 0xbe, 0x8a, 0x33, 0x07, 0x9c, 0x43, 0xab, 0x38, 0x39, 0x7e,
+	0x58, 0x8a, 0x38, 0xd3, 0x5a, 0x0a, 0x32, 0xbc, 0x54, 0xc9, 0x48, 0x79,
+	0x28, 0x01, 0xdd, 0xf7, 0x1f, 0xfc, 0x9a, 0xaa, 0x43, 0xcc, 0x61, 0x0f,
+	0xba, 0x32, 0x55, 0x5e, 0x87, 0xd8, 0x08, 0xdb, 0xf8, 0x5a, 0x5d, 0x86,
+	0x17, 0xeb, 0xa6, 0x1c, 0x6f, 0x70, 0xbf, 0x98, 0xe3, 0x05, 0x75, 0xc6,
+	0x85, 0x46, 0x4e, 0xdb, 0x87, 0xbd, 0x66, 0x9d, 0xb0, 0xaf, 0x61, 0x6a,
+	0xa3, 0x3c, 0x1f, 0x80, 0x97, 0x76, 0x7e, 0xac, 0x41, 0xdb, 0x79, 0x03,
+	0xb6, 0x41, 0xce, 0xa3, 0x9c, 0xbd, 0x95, 0xb9, 0x53, 0x66, 0xd1, 0x51,
+	0x75, 0x88, 0x56, 0xcb, 0x77, 0x20, 0x07, 0x4d, 0xa0, 0xd6, 0x80, 0xcd,
+	0xdb, 0x78, 0x6f, 0x70, 0xde, 0x32, 0xe6, 0x6d, 0xe0, 0x3c, 0xec, 0xcd,
+	0x25, 0xe5, 0x0f, 0xa6, 0xcd, 0xf1, 0x77, 0xb1, 0xc7, 0x68, 0xd7, 0x59,
+	0x57, 0x58, 0x02, 0x5f, 0xc1, 0x3e, 0xa2, 0x6e, 0x48, 0xed, 0x60, 0x7e,
+	0x8f, 0xb9, 0x19, 0xcc, 0xcd, 0x66, 0x18, 0xcf, 0x3d, 0xfb, 0x99, 0x0e,
+	0xe9, 0x42, 0xbb, 0xce, 0x35, 0xd9, 0x0c, 0x72, 0x5b, 0xdf, 0xcb, 0xb7,
+	0xc9, 0x4a, 0xca, 0xbf, 0x60, 0xd8, 0xd1, 0xdc, 0x08, 0x6f, 0xf3, 0x5c,
+	0xe6, 0xc5, 0xc4, 0xbd, 0x21, 0xcc, 0x83, 0xc7, 0xc5, 0x6d, 0xfc, 0x49,
+	0xb7, 0x74, 0xb9, 0xf8, 0x8d, 0xe6, 0x4c, 0x6f, 0x0e, 0x6a, 0x2e, 0xbe,
+	0xb7, 0x50, 0x3e, 0x17, 0xe7, 0xa1, 0x56, 0xac, 0x66, 0x26, 0x59, 0x1f,
+	0x15, 0xeb, 0x6c, 0xef, 0x85, 0x3f, 0x04, 0x75, 0xd7, 0x85, 0x5b, 0xbe,
+	0x70, 0x19, 0x7a, 0x4b, 0x43, 0x6f, 0x29, 0x39, 0xdf, 0x60, 0x9d, 0xe6,
+	0x42, 0x5f, 0x19, 0xf1, 0x1a, 0xe3, 0x58, 0x2b, 0x87, 0x81, 0x03, 0x3a,
+	0x17, 0x47, 0x2f, 0x64, 0x65, 0xca, 0xda, 0x1d, 0xf1, 0x00, 0x5c, 0x88,
+	0x1f, 0x85, 0x36, 0xf4, 0xf1, 0x1d, 0x9a, 0x53, 0xff, 0x86, 0x7f, 0x94,
+	0xed, 0x09, 0xbd, 0x30, 0xd6, 0xd4, 0xbf, 0x6e, 0xfc, 0xa1, 0x1c, 0x68,
+	0x33, 0x06, 0x31, 0xfe, 0xe8, 0xa8, 0xf3, 0x18, 0x8b, 0x48, 0xd7, 0x92,
+	0x23, 0x4b, 0x23, 0xdc, 0x37, 0x8b, 0xf1, 0xa7, 0x5c, 0xe7, 0x9e, 0x29,
+	0x5c, 0xc0, 0x19, 0xad, 0xf1, 0xfd, 0x11, 0x87, 0x6b, 0x7c, 0x99, 0x70,
+	0x3a, 0xc4, 0x48, 0x96, 0xb4, 0xc7, 0x07, 0x11, 0x7b, 0x1e, 0xe0, 0x3e,
+	0x32, 0x06, 0x6d, 0x17, 0xb0, 0xea, 0xb4, 0x3c, 0x3c, 0xc8, 0x75, 0xa0,
+	0xdd, 0x2a, 0x7a, 0x92, 0x34, 0xf3, 0x21, 0x4f, 0x43, 0xdd, 0x81, 0xbe,
+	0x06, 0xac, 0x40, 0x7f, 0x9f, 0xe9, 0x5e, 0xd5, 0x1f, 0xd7, 0x35, 0xf3,
+	0xcb, 0x18, 0x96, 0x90, 0x81, 0x33, 0x1b, 0x65, 0xe7, 0xa2, 0x25, 0xf6,
+	0x99, 0x55, 0xfe, 0x76, 0x9e, 0x5b, 0xcb, 0x5f, 0xf4, 0x7f, 0x15, 0x5c,
+	0xd0, 0xc5, 0x8e, 0xfa, 0x1e, 0x4b, 0x05, 0xb8, 0xa3, 0xf6, 0x7b, 0xe1,
+	0x5e, 0xf1, 0xfd, 0x99, 0x70, 0x4f, 0xb0, 0x07, 0x88, 0x95, 0xe7, 0x6f,
+	0xc5, 0xa9, 0x0c, 0xf6, 0x06, 0xb6, 0xa7, 0xe2, 0x11, 0xe3, 0x18, 0xed,
+	0xbb, 0x63, 0xd2, 0x2c, 0xb0, 0x8e, 0xe6, 0x3e, 0xc9, 0x44, 0xb9, 0x22,
+	0xa5, 0xad, 0x85, 0x67, 0x7d, 0xd8, 0xcf, 0xa4, 0xa5, 0x6c, 0xaf, 0x63,
+	0xaf, 0x97, 0x37, 0xa0, 0x1b, 0x8c, 0xc1, 0x26, 0xf5, 0x42, 0x42, 0x8a,
+	0x8d, 0x44, 0xc2, 0x3c, 0x31, 0xf0, 0x23, 0xcf, 0x48, 0x24, 0xf4, 0x13,
+	0x81, 0x9d, 0x4d, 0xd6, 0x6f, 0x20, 0x56, 0x6a, 0x72, 0x74, 0xe8, 0x86,
+	0xcf, 0x1a, 0xd8, 0xdb, 0x0b, 0x9b, 0x1b, 0x82, 0xcf, 0x80, 0x8f, 0x72,
+	0xa3, 0xa3, 0x37, 0xe0, 0xed, 0x2b, 0x11, 0x8f, 0xa6, 0x8e, 0xdc, 0xd3,
+	0xcb, 0xfb, 0xbe, 0x51, 0xd8, 0x90, 0x98, 0xce, 0x8f, 0x6f, 0xd1, 0xcf,
+	0xed, 0xdf, 0x62, 0x9c, 0x2b, 0x6d, 0x01, 0x3e, 0xdd, 0xcb, 0xe3, 0xf7,
+	0x9c, 0xc8, 0x44, 0x15, 0x3a, 0xdf, 0x03, 0x3d, 0x59, 0xf0, 0xc5, 0x3d,
+	0xa6, 0xca, 0xd1, 0xf5, 0x3d, 0x2f, 0x6e, 0x0a, 0x70, 0xf0, 0xfd, 0x27,
+	0x7e, 0x70, 0x86, 0x5e, 0x0e, 0xfb, 0x7e, 0x3f, 0xdc, 0x87, 0x5f, 0x45,
+	0xb9, 0x78, 0x5e, 0x44, 0xb2, 0xad, 0x3d, 0x37, 0xb2, 0xe3, 0x25, 0x9c,
+	0x33, 0xa7, 0x1d, 0xdf, 0x7f, 0x07, 0xcf, 0x35, 0xa7, 0xd9, 0x46, 0xde,
+	0x7f, 0xf6, 0x31, 0x07, 0xf8, 0x2c, 0xce, 0xbd, 0xd1, 0xa6, 0xb3, 0xff,
+	0x5e, 0xcf, 0xbd, 0x7b, 0x3f, 0xfb, 0xc9, 0xf3, 0x1d, 0x7d, 0xef, 0x03,
+	0xce, 0xfe, 0x0f, 0x5c, 0x77, 0x0f, 0x3e, 0x1b, 0xd8, 0x6d, 0xb1, 0xd1,
+	0x1c, 0x5f, 0xee, 0xd5, 0x7f, 0x7f, 0xad, 0xfb, 0x76, 0xff, 0xb5, 0xbb,
+	0x6f, 0xf7, 0xdf, 0xcd, 0xdd, 0xbf, 0x18, 0xff, 0xcd, 0x01, 0x0f, 0x7d,
+	0x70, 0xad, 0xff, 0xae, 0xe7, 0x93, 0xd4, 0xf7, 0xf3, 0x3d, 0xe5, 0xa1,
+	0xce, 0x30, 0x1f, 0x52, 0xe7, 0xf5, 0x17, 0xa7, 0x6d, 0xef, 0x7e, 0x53,
+	0x4a, 0xb9, 0x16, 0xc9, 0xe6, 0x6a, 0xb2, 0x43, 0x8e, 0x3b, 0x22, 0x4b,
+	0xaa, 0x16, 0x31, 0x51, 0x8b, 0x0f, 0xa0, 0x3e, 0x0b, 0xf4, 0xba, 0xa4,
+	0xf4, 0xf2, 0x02, 0x78, 0x89, 0xf0, 0x74, 0xdd, 0x05, 0x0f, 0x71, 0x10,
+	0x17, 0xf1, 0x0c, 0xe2, 0x7c, 0xb7, 0xd7, 0xc1, 0x85, 0x73, 0xea, 0x25,
+	0xd4, 0x64, 0xb6, 0xde, 0xa3, 0x07, 0x67, 0xb2, 0x5b, 0x96, 0xdd, 0xe9,
+	0xeb, 0xf2, 0x05, 0x9e, 0x59, 0x0a, 0xae, 0xce, 0x21, 0x56, 0x0f, 0x8d,
+	0x85, 0x75, 0xd2, 0xdc, 0x41, 0xcf, 0x8e, 0xee, 0x49, 0x78, 0x47, 0x92,
+	0x90, 0x92, 0x9a, 0xb5, 0x04, 0x1d, 0x68, 0x72, 0x0d, 0x67, 0xd0, 0xd5,
+	0xb9, 0x76, 0xe0, 0x45, 0xee, 0x77, 0x20, 0xbb, 0x57, 0xb4, 0x7e, 0xab,
+	0x55, 0x6b, 0x87, 0x2f, 0x65, 0xc4, 0x55, 0x6d, 0x9e, 0xd3, 0xa7, 0x66,
+	0x16, 0x2b, 0xc8, 0x03, 0x6d, 0x9c, 0xaf, 0x79, 0xbc, 0xd7, 0x49, 0x43,
+	0x93, 0x2b, 0x73, 0xba, 0xfc, 0xd3, 0x9c, 0x21, 0xff, 0x8c, 0x3a, 0xf4,
+	0x9a, 0x7d, 0x6a, 0xe6, 0xb4, 0x2d, 0xf7, 0x81, 0xd5, 0xf0, 0x0e, 0x4f,
+	0x76, 0x9a, 0x42, 0x5b, 0x1d, 0x48, 0xff, 0x8e, 0x20, 0xff, 0xc1, 0x9a,
+	0x2b, 0x73, 0xa4, 0xb5, 0x76, 0x8d, 0xf4, 0x22, 0x1f, 0x83, 0x5d, 0x0f,
+	0x30, 0x27, 0xe2, 0x7c, 0xd4, 0xab, 0x03, 0xd6, 0x3e, 0xc5, 0x5b, 0x42,
+	0x16, 0xeb, 0x9c, 0x6f, 0x82, 0xb7, 0x2e, 0x9c, 0x31, 0x59, 0x6b, 0x52,
+	0xfe, 0xb0, 0x5b, 0xe5, 0xaa, 0x1a, 0xfb, 0x0d, 0xb5, 0xc7, 0xef, 0xef,
+	0xe7, 0xde, 0x1b, 0x32, 0x95, 0x62, 0x9b, 0x63, 0x59, 0xd4, 0x9c, 0xc4,
+	0x97, 0xdd, 0xeb, 0x0a, 0x79, 0x0e, 0xde, 0xaf, 0x08, 0x65, 0xdb, 0x6d,
+	0x5d, 0x97, 0xd7, 0x7d, 0xf7, 0x00, 0xe5, 0x89, 0x72, 0x8b, 0x39, 0x9f,
+	0xb1, 0xd8, 0x28, 0xcc, 0xc0, 0x8e, 0xbf, 0x2a, 0xdf, 0x6f, 0x1c, 0x92,
+	0xef, 0x35, 0x26, 0xe5, 0xcf, 0x1a, 0x5f, 0x96, 0x3f, 0x6d, 0x1c, 0x94,
+	0xd7, 0x1b, 0x07, 0xe4, 0xb5, 0xc6, 0x84, 0xbc, 0xda, 0xd8, 0x0f, 0x1b,
+	0x1f, 0x87, 0x8d, 0x9f, 0x9a, 0x99, 0xac, 0xf7, 0xcb, 0xd4, 0x49, 0xc4,
+	0x20, 0xe7, 0x1b, 0xba, 0xba, 0xe3, 0xb3, 0xe9, 0xe7, 0x2d, 0x32, 0xad,
+	0xee, 0xaf, 0x34, 0xe4, 0x89, 0x2d, 0xbc, 0x2b, 0x7c, 0xc5, 0x33, 0x2e,
+	0x87, 0xf1, 0xe8, 0xe1, 0x94, 0xb4, 0x03, 0xbf, 0xca, 0x4b, 0x4d, 0x9e,
+	0xdb, 0x62, 0x86, 0xf7, 0x9c, 0x87, 0x24, 0xc9, 0xfb, 0xb0, 0x9c, 0x67,
+	0xa0, 0xde, 0x5e, 0xd7, 0x27, 0x73, 0xb4, 0x65, 0xe8, 0xc6, 0x95, 0x43,
+	0xb0, 0x53, 0xc3, 0x7e, 0xcb, 0xa5, 0x1e, 0x16, 0x97, 0x28, 0xf7, 0x46,
+	0x59, 0x5c, 0xa0, 0x6f, 0xff, 0x1b, 0x64, 0x6c, 0x97, 0xda, 0x82, 0x89,
+	0xb9, 0x6e, 0x98, 0xab, 0x6c, 0xa7, 0x3d, 0x00, 0x1f, 0xf1, 0x7e, 0x10,
+	0x4e, 0xab, 0x09, 0x27, 0xf1, 0x24, 0x54, 0x0c, 0x08, 0x70, 0x5b, 0x52,
+	0x5b, 0x4a, 0xca, 0xc2, 0x42, 0x0f, 0x9e, 0x94, 0x2c, 0xd4, 0x6d, 0x3c,
+	0x39, 0x3c, 0x43, 0x78, 0xd2, 0xb0, 0x53, 0xca, 0xc8, 0xd8, 0x12, 0xc9,
+	0x88, 0x78, 0x5c, 0xed, 0x0d, 0x6b, 0x2a, 0xf2, 0xa3, 0x85, 0xfc, 0x74,
+	0x87, 0x7d, 0x1d, 0x52, 0xab, 0x38, 0x32, 0x55, 0xfd, 0x94, 0x3e, 0xa5,
+	0x74, 0x07, 0xfc, 0x95, 0x21, 0xb4, 0xef, 0x0f, 0xdb, 0x8f, 0xca, 0xf4,
+	0xbc, 0xc8, 0xca, 0xcb, 0x03, 0x7a, 0x51, 0xb5, 0xf7, 0xa2, 0xad, 0xa3,
+	0x9d, 0x0d, 0xdb, 0xcc, 0x8f, 0x0e, 0xe0, 0x71, 0xd5, 0xf3, 0xf5, 0xea,
+	0xb8, 0x3c, 0x55, 0xed, 0x77, 0x5e, 0x87, 0xcd, 0xbd, 0x65, 0x46, 0xf7,
+	0xd2, 0x04, 0x24, 0x79, 0xf6, 0x56, 0x75, 0xf7, 0xf1, 0x04, 0xe2, 0xad,
+	0x9b, 0x34, 0xe5, 0x6f, 0x4f, 0x64, 0xad, 0xa7, 0xf5, 0x5c, 0x52, 0xda,
+	0x7d, 0xff, 0x71, 0x3b, 0x3b, 0x3b, 0xa9, 0x77, 0xca, 0xdf, 0xbf, 0x98,
+	0x91, 0x85, 0xb3, 0x5b, 0x65, 0xa1, 0x06, 0x99, 0x1a, 0xbf, 0x8e, 0x7d,
+	0x35, 0xe5, 0xea, 0x9e, 0x47, 0xb1, 0x27, 0x8c, 0x5d, 0x49, 0xe4, 0x6c,
+	0x1b, 0xc4, 0xec, 0x25, 0x5d, 0x49, 0x98, 0x85, 0x9c, 0x1c, 0x81, 0xdf,
+	0x4f, 0xdb, 0xb9, 0x1e, 0x69, 0xc7, 0x7b, 0x7d, 0x04, 0x7c, 0x5b, 0x32,
+	0xd5, 0x6b, 0xc9, 0x99, 0xc1, 0x68, 0xff, 0xb6, 0x62, 0x6e, 0x46, 0x16,
+	0xcf, 0x66, 0xf0, 0x9b, 0x83, 0xfd, 0xec, 0x94, 0x57, 0x6a, 0xfd, 0xb2,
+	0x54, 0xdb, 0x2a, 0x8b, 0xb5, 0xe6, 0x7d, 0xe8, 0xec, 0x09, 0xe2, 0x1d,
+	0xf1, 0xf4, 0x5b, 0x53, 0xfa, 0x56, 0x71, 0xcd, 0x7e, 0xeb, 0x29, 0xfd,
+	0x1f, 0xe4, 0x31, 0x33, 0xa0, 0xa9, 0x17, 0x7e, 0xa4, 0xee, 0x84, 0x26,
+	0x79, 0xf6, 0x2a, 0xbc, 0x4f, 0x26, 0x49, 0xfb, 0xf5, 0xc6, 0x07, 0xd1,
+	0x59, 0xcb, 0xcf, 0x9d, 0x68, 0x52, 0x06, 0xe2, 0xec, 0xbf, 0x71, 0x52,
+	0xef, 0x95, 0xe5, 0x6d, 0x0f, 0x58, 0x4f, 0xea, 0xad, 0x88, 0x01, 0x3f,
+	0x97, 0x9f, 0xee, 0xd9, 0x24, 0x3f, 0xfc, 0xcd, 0xec, 0xa9, 0x6f, 0x22,
+	0xd9, 0xbf, 0xb2, 0xa7, 0x83, 0x71, 0x01, 0xef, 0xec, 0xcf, 0xde, 0x70,
+	0x75, 0xea, 0xe1, 0x2f, 0xa0, 0x87, 0xec, 0x9c, 0xba, 0x9b, 0x56, 0x3c,
+	0x90, 0x3e, 0xf5, 0x52, 0x06, 0x6f, 0x18, 0xab, 0xf7, 0x03, 0x57, 0x59,
+	0xe9, 0xf9, 0x09, 0x27, 0x7b, 0x03, 0xe9, 0xb0, 0xbf, 0x68, 0xf7, 0xa7,
+	0x77, 0xea, 0x3b, 0x64, 0x32, 0xfd, 0x80, 0xf5, 0xb4, 0x6c, 0x21, 0xce,
+	0xd9, 0x05, 0xc1, 0xda, 0x79, 0xe2, 0xfb, 0x2b, 0xe0, 0x0b, 0x70, 0x28,
+	0xff, 0x51, 0x38, 0x77, 0x59, 0x5f, 0xd7, 0x79, 0xc6, 0x63, 0x0c, 0x71,
+	0xe1, 0xe2, 0x10, 0x65, 0x40, 0x82, 0x95, 0xca, 0xa6, 0x5d, 0xfd, 0xc3,
+	0xc8, 0x47, 0xfc, 0xfd, 0x56, 0x51, 0x27, 0x0f, 0xe7, 0xc0, 0xcb, 0x4f,
+	0xc0, 0x7f, 0x3f, 0x70, 0xa2, 0xf6, 0x48, 0x47, 0x74, 0xff, 0x4e, 0xd1,
+	0x7d, 0xad, 0x21, 0xe6, 0x2a, 0x5d, 0xf4, 0xd5, 0x75, 0xc8, 0xdd, 0x07,
+	0x7b, 0xb5, 0xf0, 0xcb, 0xbd, 0xe9, 0x0c, 0xf7, 0x98, 0xeb, 0x22, 0xba,
+	0x11, 0xbf, 0x5c, 0x73, 0x27, 0x1e, 0xee, 0x75, 0x3e, 0xea, 0xd4, 0x03,
+	0x09, 0x79, 0xf7, 0x44, 0xb4, 0x37, 0x07, 0x64, 0xba, 0x0a, 0xdd, 0xed,
+	0xea, 0x0f, 0xfc, 0x27, 0x1d, 0xf1, 0x40, 0xde, 0xff, 0x06, 0xbc, 0x07,
+	0xb8, 0x5b, 0x0b, 0xcd, 0xba, 0xc3, 0x58, 0x3d, 0xa0, 0x31, 0xb6, 0x0e,
+	0x4f, 0x57, 0xf6, 0x44, 0xbe, 0x98, 0x84, 0x5f, 0xed, 0xb6, 0x9e, 0x10,
+	0xd6, 0x63, 0xc4, 0x9b, 0x94, 0x1f, 0xbe, 0x0c, 0x1e, 0x92, 0xf4, 0x93,
+	0x7f, 0x5f, 0xe3, 0x27, 0x1c, 0xdb, 0x2a, 0x35, 0xd4, 0xd4, 0x5e, 0xde,
+	0x94, 0x69, 0x25, 0x03, 0xda, 0x35, 0xfa, 0x77, 0x29, 0xf4, 0xef, 0x47,
+	0x80, 0xa3, 0x5d, 0x8c, 0x47, 0x1f, 0xc7, 0x59, 0x9d, 0xcd, 0x2c, 0xeb,
+	0xcc, 0x03, 0x76, 0x4b, 0x51, 0xdd, 0x4f, 0xdf, 0x8b, 0xee, 0xa2, 0xd8,
+	0x94, 0x96, 0x8b, 0x95, 0x28, 0x2e, 0xa5, 0x71, 0x9e, 0xb4, 0xcb, 0xa5,
+	0xb9, 0x28, 0xe6, 0xb5, 0xcb, 0x12, 0xf2, 0x9a, 0x95, 0x97, 0x2c, 0x8c,
+	0x25, 0xe5, 0xe2, 0x5c, 0x12, 0x31, 0xab, 0x47, 0x56, 0xe6, 0x7a, 0x30,
+	0x96, 0xc2, 0xba, 0x14, 0xe6, 0xdb, 0xb2, 0x52, 0xb1, 0x81, 0x27, 0x87,
+	0x76, 0x0e, 0xed, 0x21, 0xb9, 0xa4, 0xbe, 0x17, 0x30, 0x2f, 0x18, 0x42,
+	0xdc, 0x62, 0x5e, 0x30, 0x82, 0x18, 0x32, 0x81, 0x27, 0x8a, 0x5d, 0xa7,
+	0x66, 0xa6, 0x2a, 0xbc, 0x73, 0x84, 0x0e, 0xac, 0x53, 0x33, 0xd3, 0xb6,
+	0x89, 0xba, 0xed, 0x1b, 0xda, 0x54, 0x83, 0x72, 0x41, 0xb7, 0x43, 0x1d,
+	0xa2, 0x3f, 0x4a, 0x9b, 0xe4, 0x79, 0x67, 0x20, 0xc6, 0x77, 0x01, 0x9f,
+	0x23, 0xfa, 0x6f, 0xd0, 0x17, 0xa0, 0xc3, 0x27, 0xba, 0xe4, 0xd2, 0xcb,
+	0x8c, 0x35, 0xae, 0xbc, 0x7a, 0x96, 0x3a, 0x2c, 0xf6, 0xac, 0xea, 0x90,
+	0x63, 0x0f, 0xe1, 0x8c, 0xd8, 0x0f, 0x7b, 0x32, 0x33, 0x87, 0x90, 0xcb,
+	0x7c, 0x1b, 0xf6, 0x59, 0x66, 0xcd, 0x9d, 0x0e, 0x6a, 0x84, 0x20, 0x06,
+	0xa0, 0xdd, 0x47, 0x5d, 0xb1, 0xdd, 0x07, 0xbb, 0xe3, 0x58, 0x9f, 0x1a,
+	0x5b, 0x04, 0x8e, 0x60, 0x8c, 0xed, 0xcd, 0xb2, 0xa8, 0xc6, 0x0e, 0xaa,
+	0xb1, 0xb2, 0xb2, 0x0f, 0x8e, 0x1d, 0x52, 0xb1, 0xe9, 0x7c, 0x23, 0xea,
+	0xdf, 0x88, 0x58, 0xc2, 0x7e, 0xf6, 0xe5, 0x61, 0xeb, 0x7b, 0x71, 0xae,
+	0x15, 0x64, 0xa9, 0x81, 0x3a, 0x30, 0xff, 0x7b, 0x98, 0xcb, 0x3d, 0xc8,
+	0x9e, 0x2a, 0xe9, 0xe4, 0xf1, 0x20, 0xce, 0x83, 0xfd, 0x21, 0xad, 0xb6,
+	0x90, 0xaf, 0x03, 0x61, 0xbb, 0x25, 0xa4, 0x4d, 0x3c, 0x36, 0x70, 0x1c,
+	0xc3, 0x5a, 0x17, 0x38, 0x18, 0x63, 0x11, 0x23, 0x52, 0x29, 0xe8, 0x82,
+	0x34, 0xdb, 0xa4, 0xac, 0xde, 0xf7, 0xc3, 0x76, 0xb9, 0x16, 0x3a, 0xb4,
+	0xa2, 0x75, 0xa5, 0x70, 0xcf, 0x53, 0xea, 0x9c, 0xd1, 0x93, 0x9b, 0xc3,
+	0x9c, 0x10, 0x7a, 0x45, 0x9c, 0xd5, 0x93, 0x8c, 0x37, 0xef, 0x84, 0x76,
+	0xda, 0x8b, 0xbe, 0x87, 0x44, 0xef, 0x65, 0xdf, 0x51, 0xe0, 0x61, 0xed,
+	0x3c, 0x0c, 0x99, 0xd9, 0xe6, 0xfa, 0x6c, 0xd3, 0xfa, 0xc4, 0x3a, 0xeb,
+	0x3b, 0x9a, 0xfa, 0x32, 0x52, 0x9b, 0xef, 0x52, 0xf1, 0xf2, 0x7c, 0x18,
+	0x2f, 0x17, 0x6b, 0x94, 0x05, 0x7e, 0x96, 0x7f, 0x5b, 0xe9, 0xa2, 0x76,
+	0x36, 0xb0, 0xf5, 0xa5, 0x93, 0x3c, 0x17, 0x57, 0xe7, 0xd5, 0xd4, 0xbc,
+	0xdf, 0x06, 0xff, 0xba, 0x1c, 0x55, 0x32, 0x70, 0x3e, 0xe6, 0xd5, 0x02,
+	0xbf, 0x31, 0x6c, 0xce, 0xa1, 0x8f, 0x44, 0x6b, 0x38, 0xff, 0xe7, 0xa8,
+	0x55, 0xbe, 0xac, 0xd6, 0xac, 0xfa, 0x0c, 0xf9, 0x71, 0x42, 0x9e, 0x7b,
+	0xc0, 0x5f, 0x67, 0x28, 0x43, 0x7b, 0x28, 0x03, 0xf1, 0xfd, 0x27, 0x70,
+	0xb7, 0x61, 0x1e, 0x79, 0xdd, 0x86, 0x3e, 0xbe, 0xff, 0x17, 0xfa, 0x76,
+	0x23, 0xff, 0x23, 0x6f, 0x89, 0x26, 0xde, 0xfe, 0x03, 0x63, 0x3d, 0x4a,
+	0xb7, 0x35, 0xd4, 0x26, 0x53, 0xbc, 0xef, 0x48, 0xe1, 0x1c, 0x38, 0xb9,
+	0x4d, 0xd1, 0xad, 0x9d, 0xbd, 0x86, 0xf1, 0x5e, 0xac, 0x89, 0xda, 0xcd,
+	0xb2, 0xe9, 0x58, 0xfb, 0x53, 0x25, 0xcf, 0x62, 0xed, 0x4e, 0xf2, 0x6f,
+	0x5b, 0x23, 0x3b, 0xe5, 0x26, 0x4f, 0xe4, 0xa7, 0x1f, 0x4f, 0x2b, 0x72,
+	0x21, 0xd8, 0x6d, 0xd2, 0x90, 0xd1, 0x7c, 0x9a, 0xdf, 0xf9, 0x12, 0xbc,
+	0x17, 0x1d, 0x19, 0xe4, 0x9e, 0xa1, 0xdd, 0x60, 0x4e, 0x47, 0x7f, 0x4b,
+	0xc8, 0x31, 0xd4, 0x24, 0xe5, 0x85, 0x8c, 0x56, 0x3c, 0x99, 0x45, 0x16,
+	0xad, 0xbe, 0xd5, 0xc9, 0x8b, 0x4b, 0xb6, 0x7c, 0x1b, 0x7e, 0x7a, 0xb2,
+	0x9e, 0x4d, 0x7f, 0x13, 0xf9, 0xc1, 0x91, 0x25, 0xe6, 0x13, 0x3d, 0x29,
+	0x65, 0x9b, 0xf3, 0x9a, 0x6c, 0x60, 0x4c, 0x9b, 0x47, 0x7e, 0x6a, 0xdd,
+	0x2d, 0x47, 0x82, 0x9f, 0x57, 0xd7, 0xc6, 0x0c, 0xca, 0xb1, 0x36, 0x66,
+	0x10, 0x0f, 0x63, 0xc6, 0x4e, 0xec, 0x13, 0x63, 0x06, 0xf6, 0xff, 0x24,
+	0x63, 0x86, 0x8d, 0x75, 0x8c, 0x19, 0x79, 0x59, 0xac, 0x32, 0x66, 0xec,
+	0x45, 0x9b, 0x31, 0xa3, 0x80, 0x76, 0x10, 0x2f, 0x16, 0x55, 0xbc, 0xc8,
+	0x5a, 0xcb, 0xc2, 0x38, 0x81, 0x3c, 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c,
+	0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c, 0x11, 0xb6, 0xfe, 0x5a, 0x15, 0x79,
+	0x22, 0xfc, 0xe7, 0x3c, 0x72, 0x92, 0xa0, 0xa6, 0x38, 0x8c, 0x9a, 0xc2,
+	0xd5, 0xc6, 0xaa, 0xe3, 0xda, 0xbe, 0x2a, 0x6a, 0x43, 0xf5, 0x9d, 0x58,
+	0x1f, 0xda, 0x80, 0xba, 0xa8, 0xe6, 0x6c, 0x01, 0x5f, 0xd7, 0xe0, 0x1b,
+	0xd4, 0xd3, 0x56, 0x99, 0xca, 0xed, 0x80, 0x7c, 0xd8, 0x7f, 0xfb, 0xfb,
+	0xe8, 0x43, 0x3e, 0x9f, 0x63, 0x0d, 0xc2, 0x78, 0xb5, 0x0f, 0x6d, 0x1d,
+	0x6d, 0xec, 0xe9, 0x04, 0x7c, 0xc4, 0x7e, 0x90, 0xf9, 0x62, 0x7a, 0x41,
+	0x9e, 0xdc, 0x1c, 0xd8, 0xf4, 0x6f, 0x31, 0x27, 0x5e, 0xd3, 0xde, 0x88,
+	0x39, 0xf0, 0x17, 0xd8, 0x97, 0x5a, 0x03, 0x5c, 0xba, 0xfd, 0xe7, 0xc4,
+	0xd1, 0xb7, 0xe1, 0xd6, 0x1c, 0xda, 0xd5, 0xf7, 0x9a, 0xfa, 0xb2, 0x98,
+	0xcf, 0xef, 0xe2, 0x3b, 0xf0, 0xfb, 0x16, 0x7e, 0x61, 0x77, 0xf6, 0x05,
+	0xcc, 0xe9, 0xc3, 0xef, 0x77, 0x9a, 0xe6, 0x42, 0x0a, 0xfb, 0x2f, 0xd1,
+	0x77, 0x31, 0xa4, 0xc1, 0x6f, 0x89, 0x5f, 0x6a, 0xe2, 0xe3, 0x07, 0xe8,
+	0xfb, 0x6b, 0xf4, 0xf9, 0xfe, 0xdb, 0x4e, 0xd4, 0x27, 0xa5, 0x96, 0x70,
+	0xef, 0x46, 0xd5, 0xde, 0x69, 0xca, 0xe6, 0x8f, 0x2c, 0xe9, 0xaa, 0x0e,
+	0x7a, 0xae, 0x8e, 0xea, 0x08, 0x71, 0xbe, 0xbc, 0x10, 0xd4, 0xad, 0xc7,
+	0x51, 0x73, 0x16, 0xab, 0xb4, 0x91, 0x1c, 0xfa, 0x6d, 0x9c, 0x69, 0x32,
+	0x69, 0xdc, 0xaa, 0x63, 0x13, 0x89, 0xc9, 0x7a, 0x9b, 0x48, 0x37, 0x69,
+	0x32, 0x4f, 0x22, 0x8e, 0xd9, 0x99, 0xe2, 0xc2, 0xec, 0x8c, 0x07, 0x9c,
+	0x63, 0x75, 0xae, 0xe5, 0x3c, 0x93, 0xf7, 0x63, 0x4d, 0x74, 0x69, 0x13,
+	0x60, 0x06, 0xf4, 0x9e, 0xab, 0x93, 0x7e, 0x40, 0xb3, 0xac, 0x68, 0xda,
+	0xe8, 0x8f, 0xea, 0xc7, 0x1c, 0x6a, 0x5d, 0x99, 0x64, 0xed, 0x5c, 0x0c,
+	0x69, 0xba, 0x75, 0x49, 0x24, 0x0a, 0xcd, 0xf8, 0x82, 0x8c, 0xf3, 0xb9,
+	0xfa, 0xec, 0x8c, 0xfe, 0x42, 0x36, 0xc7, 0x3b, 0x11, 0xd7, 0x9a, 0x9d,
+	0x69, 0x1d, 0x48, 0xc8, 0x8f, 0x91, 0xbb, 0x1d, 0x53, 0x34, 0x66, 0x67,
+	0x8c, 0x17, 0x02, 0x5b, 0x0c, 0xe8, 0xe0, 0x3c, 0xc9, 0xb7, 0x43, 0x4e,
+	0xd2, 0x62, 0x4d, 0x1d, 0x8c, 0x4f, 0xaa, 0x7a, 0xd1, 0x94, 0x2b, 0x15,
+	0x45, 0x3b, 0xac, 0xdb, 0xc9, 0xc3, 0xec, 0x8c, 0xfc, 0xd1, 0x2d, 0x1e,
+	0xd6, 0x91, 0x87, 0x78, 0x49, 0x27, 0xd0, 0x5b, 0xc0, 0x7f, 0x12, 0xf5,
+	0x7b, 0x54, 0xab, 0xfb, 0xfe, 0x8a, 0x93, 0x43, 0x5c, 0xe0, 0x3e, 0xb6,
+	0xa8, 0x3c, 0xd7, 0x73, 0x32, 0xbc, 0xef, 0x9b, 0xe3, 0xdf, 0x39, 0x78,
+	0xf9, 0x01, 0xd4, 0x4d, 0xbc, 0x1b, 0xa4, 0x7f, 0xe1, 0xf7, 0x36, 0xff,
+	0xe2, 0x7c, 0xf6, 0x93, 0xe7, 0x81, 0xf4, 0x55, 0xf0, 0xe7, 0xe5, 0xd1,
+	0x87, 0x58, 0x51, 0x6c, 0x44, 0xb8, 0x78, 0xc7, 0xce, 0x39, 0x2a, 0xff,
+	0x6e, 0xf2, 0xd1, 0x96, 0xf0, 0xdc, 0xa5, 0x8e, 0xc8, 0x27, 0xf9, 0xe9,
+	0x84, 0x4d, 0x90, 0x17, 0xce, 0x8f, 0xee, 0x25, 0xd8, 0xfe, 0xb8, 0x36,
+	0x12, 0xdd, 0xa9, 0x7d, 0x9c, 0x3d, 0x8f, 0x74, 0x76, 0x37, 0x7e, 0x88,
+	0x83, 0xb4, 0x23, 0xbe, 0x22, 0x9e, 0x88, 0x8f, 0xfc, 0x44, 0xbc, 0x28,
+	0x1b, 0x5d, 0x97, 0x9f, 0x60, 0x5d, 0xc0, 0x4f, 0x69, 0x21, 0x0d, 0x9d,
+	0x90, 0xa7, 0x11, 0x6d, 0xa4, 0xba, 0xde, 0x1d, 0xc7, 0x0f, 0x5c, 0xc6,
+	0xd5, 0xb1, 0x06, 0xef, 0xa1, 0x48, 0x97, 0x7f, 0x3b, 0xb2, 0xa4, 0x8d,
+	0x34, 0xf8, 0x9d, 0xa9, 0xae, 0xb9, 0x8d, 0x88, 0xde, 0x5a, 0x9d, 0x46,
+	0xbf, 0xbc, 0x2b, 0xff, 0x0c, 0xf6, 0xa9, 0x3b, 0xf8, 0xbb, 0x14, 0x55,
+	0x47, 0xb1, 0x6f, 0xb9, 0xd5, 0x73, 0xa2, 0xbf, 0xd3, 0xd9, 0x1f, 0xe6,
+	0x43, 0x51, 0x6d, 0x1c, 0xd5, 0x59, 0xea, 0x9e, 0x7d, 0xaf, 0xe7, 0x68,
+	0xc8, 0x4f, 0x99, 0x33, 0x05, 0x3a, 0x08, 0xf1, 0xde, 0x91, 0xcf, 0x91,
+	0x26, 0x3e, 0x47, 0xc1, 0xe7, 0x3e, 0xf0, 0x39, 0x76, 0x8b, 0xcf, 0x5b,
+	0xb6, 0x97, 0x29, 0xc3, 0xf6, 0x46, 0xd6, 0xb5, 0xbd, 0x55, 0x3a, 0xab,
+	0x73, 0x83, 0xfb, 0x9a, 0x91, 0x86, 0x2f, 0xc7, 0x9d, 0x8f, 0x53, 0x37,
+	0xb7, 0xcb, 0x99, 0x85, 0xbb, 0xd5, 0xb7, 0x11, 0xaf, 0x2a, 0x77, 0x94,
+	0x4b, 0xf5, 0x80, 0x9f, 0x1f, 0x2f, 0xb1, 0x3d, 0x12, 0xea, 0x8a, 0x3a,
+	0xcb, 0x3a, 0x25, 0xb9, 0x1b, 0x2f, 0xbf, 0xf8, 0x9c, 0x76, 0xa5, 0x12,
+	0x9d, 0x4f, 0x5a, 0x78, 0xc6, 0xae, 0xe5, 0x29, 0xfa, 0x6e, 0x32, 0x66,
+	0x45, 0xf7, 0x67, 0x22, 0xfc, 0xfe, 0xc0, 0xef, 0x75, 0x6b, 0xbf, 0x13,
+	0xf0, 0x7c, 0x8a, 0x78, 0xd7, 0x53, 0x3c, 0x9f, 0xc6, 0x9c, 0x66, 0x19,
+	0x5c, 0xd8, 0xa4, 0x9e, 0xe4, 0x98, 0xe7, 0xd0, 0x2f, 0x4c, 0xd0, 0x0c,
+	0xee, 0xdd, 0x6a, 0x4b, 0xbe, 0x5c, 0x74, 0x36, 0x06, 0xe7, 0x28, 0x64,
+	0xba, 0x6c, 0xf1, 0xfe, 0x0a, 0x31, 0x8c, 0x67, 0x83, 0xb2, 0xb5, 0x16,
+	0xf5, 0x5c, 0x39, 0xd0, 0x0e, 0x1d, 0xb3, 0xdd, 0xd6, 0xcb, 0xfb, 0x0a,
+	0xca, 0xbc, 0xa0, 0xf6, 0x21, 0xd2, 0x71, 0xf4, 0x7d, 0xae, 0x55, 0x96,
+	0xc3, 0xbb, 0xad, 0xc5, 0x8a, 0xef, 0xbf, 0x83, 0x3c, 0xfc, 0x34, 0x74,
+	0x5f, 0xae, 0xff, 0xcc, 0x5f, 0x4e, 0xf1, 0x6f, 0xa5, 0x22, 0x9b, 0xd8,
+	0xd1, 0xcb, 0x7b, 0x20, 0xf8, 0x96, 0x1c, 0xaf, 0x87, 0x65, 0xbf, 0x70,
+	0x9c, 0x7d, 0xff, 0x0d, 0xbe, 0x7d, 0xff, 0xf4, 0xaa, 0x9d, 0x02, 0xfe,
+	0x17, 0x33, 0xe1, 0x9b, 0xdd, 0x90, 0x58, 0x00, 0x00, 0x00 };
 
 static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = {
@@ -1943,387 +1057,264 @@
 static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 };
 static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 };
 
-static u32 bnx2_rv2p_proc1[] = {
-	0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004,
-	0x00000010, 0x20bf002c, 0x00000010, 0x203f0143, 0x00000018, 0x8000fffd,
-	0x00000010, 0xb1b8b017, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
-	0x00000000, 0x2c380000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
-	0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x00000008, 0x02000002,
-	0x00000010, 0x91de0000, 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08,
-	0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000008, 0x2d800150,
-	0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000010, 0x2c620002,
-	0x00000018, 0x80000012, 0x0000000b, 0x2fdf0002, 0x0000000c, 0x1f800002,
-	0x00000000, 0x2c070000, 0x00000018, 0x8000ffe6, 0x00000008, 0x02000002,
-	0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, 0x00000008, 0x2c8000b0,
-	0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
-	0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000018, 0x80000004,
-	0x0000000c, 0x1f800002, 0x00000000, 0x00000000, 0x00000018, 0x8000ffd9,
-	0x0000000c, 0x29800002, 0x0000000c, 0x1f800002, 0x00000000, 0x2adf0000,
-	0x00000008, 0x2a000005, 0x00000018, 0x8000ffd4, 0x00000008, 0x02240030,
-	0x00000018, 0x00040000, 0x00000018, 0x80000015, 0x00000018, 0x80000017,
-	0x00000018, 0x8000001b, 0x00000018, 0x8000004c, 0x00000018, 0x8000008c,
-	0x00000018, 0x8000000f, 0x00000018, 0x8000000e, 0x00000018, 0x8000000d,
-	0x00000018, 0x8000000c, 0x00000018, 0x800000c2, 0x00000018, 0x8000000a,
-	0x00000018, 0x80000009, 0x00000018, 0x80000008, 0x00000018, 0x800000fd,
-	0x00000018, 0x80000006, 0x00000018, 0x80000005, 0x00000018, 0x800000ff,
-	0x00000018, 0x80000104, 0x00000018, 0x80000002, 0x00000018, 0x80000098,
-	0x00000018, 0x80000000, 0x0000000c, 0x1f800001, 0x00000000, 0x00000000,
-	0x00000018, 0x8000ffba, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
-	0x0000000c, 0x1f800001, 0x00000008, 0x2a000002, 0x00000018, 0x8000ffb5,
-	0x00000010, 0xb1a0b012, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000,
-	0x00000008, 0x2c800000, 0x00000008, 0x2d000000, 0x00000010, 0x91d40000,
-	0x00000008, 0x2d80011c, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-	0x0000000f, 0x47600008, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
-	0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-	0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000018, 0x80000013,
-	0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, 0x00000008, 0x2c800000,
-	0x00000008, 0x2d000000, 0x00000010, 0x91d40000, 0x00000008, 0x2d80011c,
-	0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, 0x00000000, 0x0f580000,
-	0x00000010, 0x91de0000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-	0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000000, 0x02620000,
-	0x0000000b, 0x2fdf0002, 0x00000000, 0x309a0000, 0x00000000, 0x31040000,
-	0x00000000, 0x0c961800, 0x00000009, 0x0c99ffff, 0x00000004, 0xcc993400,
-	0x00000010, 0xb1963202, 0x00000008, 0x0f800000, 0x0000000c, 0x29800001,
-	0x00000010, 0x00220002, 0x0000000c, 0x29520001, 0x0000000c, 0x29520000,
-	0x00000008, 0x22000001, 0x0000000c, 0x1f800001, 0x00000000, 0x2adf0000,
-	0x00000008, 0x2a000003, 0x00000018, 0x8000ff83, 0x00000010, 0xb1a0b01d,
-	0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
-	0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
-	0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
-	0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000000, 0x00000000,
-	0x00000010, 0x91de0000, 0x0000000f, 0x47600008, 0x00000000, 0x060e0000,
-	0x00000010, 0x001f0000, 0x00000000, 0x0f580000, 0x00000010, 0x91de0000,
-	0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000,
-	0x00000000, 0x0d620000, 0x00000000, 0x0ce71800, 0x00000009, 0x0c99ffff,
-	0x00000004, 0xcc993400, 0x00000010, 0xb1963220, 0x00000008, 0x0f800000,
-	0x00000018, 0x8000001e, 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002,
-	0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000010, 0x91d40000,
-	0x00000008, 0x2d80012c, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
-	0x00000000, 0x0f580000, 0x00000010, 0x91de0000, 0x00000000, 0x0a640000,
-	0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, 0x00000000, 0x0d620000,
-	0x00000000, 0x02630000, 0x0000000f, 0x47620010, 0x00000000, 0x0ce71800,
-	0x0000000b, 0x2fdf0002, 0x00000000, 0x311a0000, 0x00000000, 0x31840000,
-	0x0000000b, 0xc20000ff, 0x00000002, 0x42040000, 0x00000001, 0x31620800,
-	0x0000000f, 0x020e0010, 0x00000002, 0x31620800, 0x00000009, 0x0c99ffff,
-	0x00000004, 0xcc993400, 0x00000010, 0xb1963202, 0x00000008, 0x0f800000,
-	0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x0000000c, 0x61420006,
-	0x00000008, 0x22000008, 0x00000000, 0x2adf0000, 0x00000008, 0x2a000004,
-	0x00000018, 0x8000ff42, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
-	0x00000010, 0x91a0b008, 0x00000010, 0x91d40000, 0x0000000c, 0x31620018,
-	0x00000008, 0x2d800001, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-	0x00000008, 0xac000001, 0x00000018, 0x8000000e, 0x00000000, 0x0380b000,
-	0x0000000b, 0x2fdf0002, 0x00000000, 0x2c004000, 0x00000010, 0x91d40000,
-	0x00000008, 0x2d800101, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-	0x0000000c, 0x31620018, 0x00000008, 0x2d800001, 0x00000000, 0x00000000,
-	0x00000010, 0x91de0000, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c000e00,
-	0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000008, 0x2a000007,
-	0x00000018, 0x8000ff27, 0x00000010, 0xb1a0b016, 0x0000000b, 0x2fdf0002,
-	0x00000000, 0x03d80000, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
-	0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
-	0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
-	0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000008, 0x07000001,
-	0x00000010, 0xb5de1c00, 0x00000010, 0x2c620002, 0x00000018, 0x8000000a,
-	0x0000000b, 0x2fdf0002, 0x00000000, 0x2c070000, 0x0000000c, 0x1f800001,
-	0x00000010, 0x91de0000, 0x00000018, 0x8000ff11, 0x00000008, 0x2c8000b0,
-	0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
-	0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000010, 0x91de0000,
-	0x00000000, 0x2adf0000, 0x00000008, 0x2a00000a, 0x00000018, 0x8000ff07,
-	0x00000000, 0x82265600, 0x0000000f, 0x47220008, 0x00000009, 0x070e000f,
-	0x00000008, 0x070e0008, 0x00000008, 0x02800001, 0x00000007, 0x02851c00,
-	0x00000008, 0x82850001, 0x00000000, 0x02840a00, 0x00000007, 0x42851c00,
-	0x00000003, 0xc3aa5200, 0x00000000, 0x03b10e00, 0x00000010, 0x001f0000,
-	0x0000000f, 0x0f280007, 0x00000007, 0x4b071c00, 0x00000000, 0x00000000,
-	0x0000000f, 0x0a960003, 0x00000000, 0x0a955c00, 0x00000000, 0x4a005a00,
-	0x00000000, 0x0c960a00, 0x00000009, 0x0c99ffff, 0x00000008, 0x0d00ffff,
-	0x00000010, 0xb1963202, 0x00000008, 0x0f800005, 0x00000010, 0x00220020,
-	0x00000000, 0x02a70000, 0x00000010, 0xb1850002, 0x00000008, 0x82850200,
-	0x00000000, 0x02000000, 0x00000000, 0x03a60000, 0x00000018, 0x8000004e,
-	0x00000000, 0x072b0000, 0x00000001, 0x878c1c00, 0x00000000, 0x870e1e00,
-	0x00000000, 0x860c1e00, 0x00000000, 0x03061e00, 0x00000010, 0xb18e0003,
-	0x00000018, 0x80000047, 0x00000018, 0x8000fffa, 0x00000010, 0x918c0003,
-	0x00000010, 0xb1870002, 0x00000018, 0x80000043, 0x00000010, 0x91d40000,
-	0x0000000c, 0x29800001, 0x00000000, 0x2a860000, 0x00000000, 0x230c0000,
-	0x00000000, 0x2b070000, 0x00000010, 0xb187000e, 0x00000008, 0x2a000008,
-	0x00000018, 0x8000003b, 0x00000010, 0x91d40000, 0x00000000, 0x28d18c00,
-	0x00000000, 0x2a860000, 0x00000000, 0x230c0000, 0x00000000, 0x2b070000,
-	0x00000018, 0x8000fff8, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
-	0x00000000, 0x2aab0000, 0x00000000, 0xa3265600, 0x00000000, 0x2b000000,
-	0x0000000c, 0x1f800001, 0x00000008, 0x2a000008, 0x00000018, 0x8000fec8,
-	0x00000010, 0x91d40000, 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001,
-	0x00000008, 0x2a000009, 0x00000018, 0x8000fec3, 0x00000010, 0x91d40000,
-	0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000000, 0x29420000,
-	0x00000008, 0x2a000002, 0x00000018, 0x8000febd, 0x00000018, 0x8000febc,
-	0x00000010, 0xb1bcb016, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
-	0x00000000, 0x2c3c0000, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
-	0x00000010, 0x91d40000, 0x00000008, 0x2d800150, 0x00000000, 0x00000000,
-	0x00000010, 0x205f0000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
-	0x00000008, 0x2d800108, 0x00000008, 0x07000001, 0x00000010, 0xb5de1c00,
-	0x00000010, 0x2c620002, 0x00000018, 0x8000000a, 0x0000000b, 0x2fdf0002,
-	0x00000000, 0x2c070000, 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000,
-	0x00000018, 0x8000fea6, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
-	0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x0000000c, 0x29800000,
-	0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, 0x00000000, 0x2adf0000,
-	0x00000008, 0x2a000006, 0x00000018, 0x8000fe9c, 0x00000008, 0x03050004,
-	0x00000006, 0x83040c00, 0x00000008, 0x02850200, 0x00000000, 0x86050c00,
-	0x00000001, 0x860c0e00, 0x00000008, 0x02040004, 0x00000000, 0x02041800,
-	0x00000000, 0x83871800, 0x00000018, 0x00020000 };
+static u8 bnx2_rv2p_proc1[] = {
+	0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x56, 0xcf, 0x6b,
+	0x13, 0x51, 0x10, 0x9e, 0xec, 0x6e, 0xb2, 0xdb, 0x74, 0xbb, 0x1b, 0x2b,
+	0xda, 0xa0, 0xb1, 0x8d, 0x51, 0x6a, 0x7f, 0xa4, 0xb4, 0x11, 0x0f, 0x82,
+	0x42, 0x25, 0x3d, 0x04, 0x54, 0x44, 0x7a, 0x28, 0x22, 0x82, 0x36, 0x8a,
+	0xfe, 0x1b, 0xa1, 0x3f, 0xd2, 0x4b, 0x10, 0x7a, 0xb0, 0x58, 0xf1, 0x50,
+	0x10, 0x2a, 0x68, 0x0f, 0xc9, 0xa1, 0x20, 0x52, 0x11, 0xda, 0x8b, 0x07,
+	0x2f, 0x42, 0x0f, 0x7a, 0x69, 0xbd, 0xa8, 0xff, 0x82, 0x08, 0x4d, 0x7c,
+	0x6f, 0x66, 0x9e, 0xee, 0x6e, 0xb2, 0x4d, 0x15, 0xc1, 0x85, 0xf6, 0xe3,
+	0xbd, 0x9d, 0x79, 0x33, 0xf3, 0xcd, 0x37, 0xfb, 0x62, 0x01, 0x40, 0x04,
+	0x60, 0xcd, 0x46, 0x2c, 0x8d, 0x26, 0x04, 0x1a, 0x30, 0x7e, 0x52, 0x62,
+	0x16, 0xde, 0xa6, 0x25, 0x4e, 0x44, 0xc6, 0xd3, 0x49, 0x81, 0x7b, 0x0d,
+	0x28, 0xc9, 0x75, 0x4f, 0xf5, 0x55, 0xad, 0x53, 0xa0, 0x06, 0xbb, 0xa3,
+	0x80, 0xcf, 0x47, 0x9d, 0xf0, 0x7c, 0xd6, 0x42, 0x2c, 0x31, 0xc2, 0x48,
+	0x02, 0x61, 0x7b, 0x51, 0xae, 0xad, 0x48, 0x69, 0xc4, 0x42, 0x3f, 0xd0,
+	0x68, 0x7f, 0x67, 0xd1, 0x15, 0xff, 0x53, 0xf0, 0x39, 0x2f, 0xd7, 0x56,
+	0x7c, 0x0e, 0xed, 0xaa, 0xec, 0x2f, 0xfe, 0xd0, 0xfe, 0xba, 0xf0, 0x03,
+	0x7e, 0x94, 0x5f, 0x02, 0xcf, 0x29, 0x66, 0x65, 0x5e, 0xdd, 0x22, 0xa0,
+	0xca, 0xc7, 0x46, 0x2c, 0xf5, 0x91, 0xb5, 0x89, 0xef, 0xbf, 0x8a, 0xbc,
+	0x55, 0xdc, 0x76, 0xf1, 0x82, 0xf9, 0x06, 0xe3, 0x26, 0x91, 0x1f, 0x28,
+	0xf9, 0xe3, 0x00, 0xc8, 0xfd, 0x4f, 0x8d, 0x5f, 0xfb, 0x83, 0xfe, 0xf7,
+	0xbb, 0x43, 0xf2, 0xbc, 0x28, 0xc0, 0x90, 0xb4, 0xdb, 0xe6, 0x7c, 0xc6,
+	0xe0, 0xb4, 0x96, 0xc4, 0xf7, 0x06, 0xfa, 0x1f, 0x11, 0xe7, 0x4a, 0xec,
+	0x61, 0x3c, 0xce, 0x78, 0x95, 0xb1, 0xc2, 0xe8, 0x32, 0x3a, 0x8c, 0x5d,
+	0x8c, 0x36, 0xe3, 0x26, 0x63, 0x9c, 0xb1, 0x83, 0xd1, 0x62, 0xdc, 0x63,
+	0x8c, 0x31, 0x46, 0x19, 0x1b, 0x8c, 0x46, 0x84, 0x50, 0xe3, 0xf5, 0x63,
+	0x46, 0xe0, 0xba, 0x23, 0x81, 0xba, 0x5f, 0xb3, 0x2e, 0x24, 0x6f, 0xfc,
+	0x7e, 0x50, 0xd9, 0x31, 0xef, 0x58, 0xf7, 0x3a, 0xdb, 0x75, 0x57, 0x57,
+	0x02, 0xfa, 0x49, 0xef, 0xab, 0x9b, 0x54, 0x8b, 0x3e, 0xb8, 0x58, 0xcf,
+	0x9d, 0x82, 0x8b, 0x71, 0x9c, 0x18, 0xed, 0xab, 0xb4, 0x6e, 0xb8, 0x84,
+	0xf7, 0xe2, 0x84, 0x5f, 0x18, 0xef, 0x77, 0x12, 0x4e, 0x77, 0xc9, 0x7c,
+	0x0e, 0x8b, 0x80, 0xea, 0x1c, 0x95, 0x4f, 0xbb, 0x3c, 0xc2, 0xe2, 0xa9,
+	0xbc, 0xda, 0xc5, 0x25, 0x2c, 0x6a, 0xfe, 0xfa, 0x9f, 0x8c, 0x11, 0x1a,
+	0x39, 0x22, 0x75, 0xc9, 0x16, 0x3d, 0x83, 0x46, 0x63, 0xd9, 0x36, 0xe4,
+	0xfa, 0xdc, 0xf2, 0x7b, 0xd4, 0xfb, 0xd9, 0xa5, 0x1a, 0xe7, 0xe7, 0x2a,
+	0x9e, 0x69, 0x0e, 0x32, 0x40, 0xeb, 0x49, 0xe4, 0x1d, 0x04, 0x5a, 0xb8,
+	0x86, 0x8c, 0xbf, 0x5f, 0xa4, 0x43, 0x9d, 0xfb, 0x31, 0xcb, 0xfd, 0x38,
+	0x11, 0xd2, 0x8f, 0xb0, 0xb9, 0x68, 0x9e, 0xc7, 0xdb, 0xe9, 0x20, 0x6f,
+	0x61, 0xf3, 0xa3, 0xf8, 0xa6, 0xdd, 0x3f, 0xe5, 0xf1, 0x01, 0xf3, 0x58,
+	0x24, 0x1e, 0x93, 0xdf, 0x5a, 0xf2, 0x94, 0xf6, 0xf0, 0x24, 0xeb, 0xec,
+	0x0d, 0xe9, 0x73, 0x58, 0x7d, 0xd9, 0xbf, 0xee, 0x73, 0x20, 0x3f, 0xb8,
+	0x8b, 0xdf, 0x9b, 0x04, 0x14, 0x0b, 0x2a, 0x5f, 0x3f, 0xcf, 0xc7, 0xa8,
+	0xdf, 0x30, 0x97, 0x93, 0xfb, 0x62, 0xfe, 0x36, 0x35, 0x5c, 0x1b, 0xf9,
+	0x88, 0x04, 0xab, 0x98, 0x23, 0x7f, 0x47, 0xd3, 0x78, 0x7d, 0x50, 0x5d,
+	0xa8, 0xbe, 0x4b, 0x8c, 0x41, 0x7e, 0x9a, 0xeb, 0xcc, 0x50, 0x3c, 0xd2,
+	0x81, 0xc1, 0x3a, 0xc8, 0xf3, 0xf7, 0x28, 0xc8, 0x87, 0x55, 0x5d, 0x59,
+	0xf4, 0xce, 0x75, 0x12, 0x8a, 0x39, 0xd2, 0x55, 0x73, 0x5f, 0x59, 0x6f,
+	0x6b, 0xea, 0xbb, 0x84, 0xdb, 0xd5, 0x92, 0xee, 0xab, 0xf7, 0x12, 0x64,
+	0xbd, 0x3c, 0x47, 0x5a, 0xe8, 0xa3, 0x5d, 0x1c, 0xdf, 0x79, 0x0e, 0x64,
+	0x5b, 0x7d, 0x6f, 0x4c, 0xae, 0xeb, 0x0c, 0xeb, 0xfb, 0x68, 0x93, 0xbe,
+	0xd5, 0x7d, 0xf5, 0xef, 0x74, 0xce, 0xf5, 0x9b, 0x68, 0x97, 0xda, 0x59,
+	0xf7, 0xde, 0x4f, 0x71, 0xcf, 0xfd, 0x44, 0x6e, 0xa6, 0xca, 0xbb, 0xcf,
+	0x7b, 0xaf, 0x1c, 0x0a, 0xe9, 0x83, 0xf7, 0x3e, 0x0a, 0xd6, 0xeb, 0xd7,
+	0x23, 0xf5, 0x35, 0xce, 0xf5, 0x9b, 0x0d, 0xee, 0xc3, 0x54, 0xff, 0x0c,
+	0xe9, 0x3f, 0x53, 0x90, 0xfa, 0x71, 0xc1, 0x31, 0xe9, 0x7c, 0x42, 0x71,
+	0x8e, 0x66, 0x62, 0xde, 0xf3, 0x1a, 0xad, 0xe7, 0x67, 0xd0, 0x2f, 0x3e,
+	0xa7, 0xf6, 0xf3, 0x48, 0xd8, 0xe4, 0x8b, 0x2d, 0xe2, 0xbd, 0xa6, 0xab,
+	0xb9, 0x70, 0x91, 0xef, 0x01, 0x97, 0xec, 0xcc, 0x2b, 0x8a, 0x2f, 0xb9,
+	0xaf, 0xc3, 0x12, 0xcd, 0xc5, 0xad, 0x47, 0x84, 0x37, 0xe1, 0x32, 0x9d,
+	0xfb, 0xfb, 0xfb, 0x66, 0x21, 0x42, 0x97, 0x57, 0xc7, 0x51, 0xa1, 0x63,
+	0x9c, 0x63, 0x25, 0x57, 0x78, 0xae, 0x11, 0x9f, 0xf3, 0xa4, 0x73, 0x8d,
+	0xf3, 0xc3, 0xab, 0x45, 0x3e, 0xab, 0xba, 0xac, 0xf7, 0x9a, 0xd2, 0x1d,
+	0x0c, 0x9b, 0x38, 0x3f, 0xa9, 0xca, 0x02, 0x2e, 0x7b, 0x1d, 0x46, 0xbb,
+	0x4c, 0x18, 0xc3, 0xfc, 0x75, 0x78, 0x58, 0x93, 0x7e, 0x05, 0xbe, 0xdf,
+	0x7e, 0xb0, 0x5e, 0x74, 0xa8, 0xf0, 0xef, 0x8b, 0x05, 0x7c, 0x3f, 0x01,
+	0xcd, 0xf7, 0x1b, 0xc5, 0x29, 0x0f, 0x11, 0xda, 0xa7, 0xb8, 0xaf, 0xc3,
+	0xd2, 0xce, 0x11, 0x7e, 0xdc, 0x3f, 0xec, 0xc3, 0x05, 0x8f, 0x3f, 0x42,
+	0xe5, 0xc3, 0x40, 0x98, 0xbf, 0xb4, 0xff, 0xde, 0xe2, 0x3e, 0xa5, 0xf7,
+	0x2f, 0xc9, 0x7e, 0xaa, 0xff, 0x19, 0xd7, 0x3f, 0xec, 0xd5, 0xbd, 0x8a,
+	0xf7, 0xae, 0xbe, 0xff, 0x7d, 0xdc, 0xc1, 0x76, 0x5b, 0xfb, 0xd8, 0xd1,
+	0xf1, 0xf9, 0x41, 0xef, 0xfd, 0xfd, 0xa6, 0x4e, 0x3c, 0x6d, 0xd4, 0xd5,
+	0x5c, 0x6d, 0x84, 0xcc, 0xd5, 0xc5, 0xff, 0x3a, 0x57, 0x10, 0x98, 0xab,
+	0xd5, 0xfa, 0xc1, 0xe6, 0x0a, 0xb8, 0x7e, 0x08, 0x99, 0xab, 0x18, 0xf3,
+	0xf0, 0x94, 0xcf, 0x33, 0x20, 0xaa, 0xc7, 0xb0, 0x7d, 0xc6, 0x2c, 0xeb,
+	0x92, 0xf4, 0x68, 0x47, 0xcb, 0xa8, 0x3f, 0xc7, 0x2e, 0x93, 0x9d, 0x41,
+	0xfb, 0x49, 0x85, 0x0b, 0xb3, 0xf4, 0x7b, 0x4a, 0x83, 0x9f, 0x94, 0x15,
+	0x12, 0x3d, 0x80, 0x0b, 0x00, 0x00, 0x00 };
 
-static u32 bnx2_rv2p_proc2[] = {
-	0x00000000, 0x2a000000, 0x00000010, 0xb1d40000, 0x00000008, 0x02540003,
-	0x00000018, 0x00040000, 0x00000018, 0x8000000a, 0x00000018, 0x8000000a,
-	0x00000018, 0x8000000e, 0x00000018, 0x80000056, 0x00000018, 0x800001b9,
-	0x00000018, 0x800001e1, 0x00000018, 0x8000019b, 0x00000018, 0x800001f9,
-	0x00000018, 0x8000019f, 0x00000018, 0x800001a6, 0x00000018, 0x80000000,
-	0x0000000c, 0x29800001, 0x00000000, 0x2a000000, 0x0000000c, 0x29800000,
-	0x00000010, 0x20530000, 0x00000018, 0x8000ffee, 0x0000000c, 0x29800001,
-	0x00000010, 0x91de0000, 0x00000010, 0x001f0000, 0x00000000, 0x2f80aa00,
-	0x00000000, 0x2a000000, 0x00000000, 0x0d610000, 0x00000000, 0x03620000,
-	0x00000000, 0x2c400000, 0x00000000, 0x02638c00, 0x00000000, 0x26460000,
-	0x00000010, 0x00420002, 0x00000008, 0x02040012, 0x00000010, 0xb9060836,
-	0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-	0x00000000, 0x0b660000, 0x00000000, 0x0c000000, 0x00000000, 0x0b800000,
-	0x00000010, 0x00420009, 0x00000008, 0x0cc60012, 0x00000008, 0x0f800003,
-	0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000008, 0x27110012,
-	0x00000000, 0x66900000, 0x00000008, 0xa31b0012, 0x00000018, 0x80000008,
-	0x00000000, 0x0cc60000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
-	0x00000010, 0x009f0000, 0x00000000, 0x27110000, 0x00000000, 0x66900000,
-	0x00000000, 0x231b0000, 0x00000010, 0xb197320e, 0x00000000, 0x25960000,
-	0x00000000, 0x021b0000, 0x00000010, 0x001f0000, 0x00000008, 0x0f800003,
-	0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000000, 0x22c50800,
-	0x00000010, 0x009f0000, 0x00000000, 0x27002200, 0x00000000, 0x26802000,
-	0x00000000, 0x231b0000, 0x0000000c, 0x69520001, 0x00000018, 0x8000fff3,
-	0x00000010, 0x01130002, 0x00000010, 0xb1980003, 0x00000010, 0x001f0000,
-	0x00000008, 0x0f800004, 0x00000008, 0x22000003, 0x00000008, 0x2c80000c,
-	0x00000008, 0x2d00000c, 0x00000010, 0x009f0000, 0x00000000, 0x25960000,
-	0x0000000c, 0x29800000, 0x00000000, 0x32140000, 0x00000000, 0x32950000,
-	0x00000000, 0x33160000, 0x00000000, 0x31e32e00, 0x00000008, 0x2d800010,
-	0x00000010, 0x20530000, 0x00000018, 0x8000ffac, 0x00000000, 0x23000000,
-	0x00000000, 0x25e60000, 0x00000008, 0x2200000b, 0x0000000c, 0x69520000,
-	0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000018, 0x8000ffa5,
-	0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
-	0x00000010, 0x001f0000, 0x00000000, 0x02700000, 0x00000000, 0x0d620000,
-	0x00000000, 0xbb630800, 0x00000000, 0x2a000000, 0x00000009, 0x076000ff,
-	0x0000000f, 0x2c0e0007, 0x00000008, 0x2c800000, 0x00000008, 0x2d000064,
-	0x00000008, 0x2d80011c, 0x00000009, 0x06420002, 0x0000000c, 0x61420001,
-	0x00000000, 0x0f400000, 0x00000000, 0x02d08c00, 0x00000000, 0x23000000,
-	0x00000004, 0x826da000, 0x00000000, 0x8304a000, 0x00000000, 0x22c50c00,
-	0x00000000, 0x03760000, 0x00000004, 0x83860a00, 0x00000000, 0x83870c00,
-	0x00000010, 0x91de0000, 0x00000000, 0x037c0000, 0x00000000, 0x837b0c00,
-	0x00000001, 0x83060e00, 0x00000000, 0x83870c00, 0x00000000, 0x82850e00,
-	0x00000010, 0xb1860016, 0x0000000f, 0x47610018, 0x00000000, 0x068e0000,
-	0x0000000f, 0x47670010, 0x0000000f, 0x47e20010, 0x00000000, 0x870e1e00,
-	0x00000010, 0xb70e1a10, 0x00000010, 0x0ce7000e, 0x00000008, 0x22000009,
-	0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
-	0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
-	0x00000018, 0x8000023f, 0x00000000, 0x37ed0000, 0x0000000c, 0x73e7001a,
-	0x00000010, 0x20530000, 0x00000008, 0x22000008, 0x0000000c, 0x61420004,
-	0x00000000, 0x02f60000, 0x00000004, 0x82840a00, 0x00000010, 0xb1840a2b,
-	0x00000010, 0x2d67000a, 0x00000010, 0xb96d0804, 0x00000004, 0xb6ed0a00,
-	0x00000000, 0x37ed0000, 0x00000018, 0x80000029, 0x0000000c, 0x61420000,
-	0x00000000, 0x37040000, 0x00000000, 0x37850000, 0x0000000c, 0x33e7001a,
-	0x00000018, 0x80000024, 0x00000010, 0xb96d0809, 0x00000004, 0xb6ed0a00,
-	0x00000000, 0x036d0000, 0x00000004, 0xb76e0c00, 0x00000010, 0x91ee0c1f,
-	0x0000000c, 0x73e7001a, 0x00000004, 0xb6ef0c00, 0x00000000, 0x37ed0000,
-	0x00000018, 0x8000001b, 0x0000000c, 0x61420000, 0x00000010, 0xb7ee0a05,
-	0x00000010, 0xb96f0815, 0x00000003, 0xb76e0800, 0x00000004, 0xb7ef0a00,
-	0x00000018, 0x80000015, 0x00000010, 0x0ce7000c, 0x00000008, 0x22000009,
-	0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
-	0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
-	0x00000018, 0x80000215, 0x00000010, 0x20530000, 0x00000008, 0x22000008,
-	0x0000000c, 0x61420004, 0x00000000, 0x37040000, 0x00000000, 0x37850000,
-	0x00000000, 0x036d0000, 0x00000003, 0xb8f10c00, 0x00000018, 0x80000004,
-	0x00000000, 0x02840000, 0x00000002, 0x21421800, 0x0000000c, 0x61420000,
-	0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff,
-	0x00000000, 0x23000000, 0x00000010, 0xb1840a3d, 0x00000010, 0x01420002,
-	0x00000004, 0xb8f10a00, 0x00000003, 0x83760a00, 0x00000010, 0xb8040c39,
-	0x00000010, 0xb7e6080a, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
-	0x00000009, 0x0c68ffff, 0x00000009, 0x0b67ffff, 0x00000000, 0x0be60000,
-	0x00000000, 0x0c840000, 0x00000010, 0xb197320c, 0x00000008, 0x0f800002,
-	0x00000018, 0x8000000a, 0x00000000, 0x0a6a0000, 0x00000000, 0x0aeb0000,
-	0x00000000, 0x0c000000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0be90000,
-	0x00000000, 0x0c840000, 0x00000010, 0xb1973203, 0x00000008, 0x0f800002,
-	0x00000018, 0x80000001, 0x00000010, 0x001f0000, 0x00000000, 0x0c860000,
-	0x00000000, 0x06980000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
-	0x00000010, 0x009f0000, 0x00000010, 0xb1973210, 0x00000000, 0x231b0000,
-	0x00000000, 0x02043600, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-	0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
-	0x0000000c, 0x29000000, 0x00000018, 0x800001de, 0x00000000, 0x06980000,
-	0x00000010, 0x20530000, 0x00000000, 0x22c58c00, 0x00000010, 0x001f0000,
-	0x00000008, 0x0f800003, 0x00000018, 0x8000fff0, 0x00000000, 0x02043600,
-	0x00000000, 0x231b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-	0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
-	0x0000000c, 0x29000000, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-	0x00000000, 0x32140000, 0x00000000, 0x32950000, 0x00000005, 0x73e72c00,
-	0x00000005, 0x74683000, 0x00000000, 0x33170000, 0x00000018, 0x80000138,
-	0x00000010, 0x91c60004, 0x00000008, 0x07000004, 0x00000010, 0xb1c41c02,
-	0x00000010, 0x91840a04, 0x00000018, 0x800001c3, 0x00000010, 0x20530000,
-	0x00000000, 0x22c58c00, 0x00000010, 0xb1840a8e, 0x0000000c, 0x21420006,
-	0x00000010, 0x0ce7001a, 0x0000000f, 0x43680010, 0x00000000, 0x03f30c00,
-	0x00000010, 0x91870850, 0x0000000f, 0x46ec0010, 0x00000010, 0xb68d0c4e,
-	0x00000000, 0x838d0c00, 0x00000000, 0xa3050800, 0x00000001, 0xa3460e00,
-	0x00000000, 0x02048c00, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-	0x00000010, 0x001f0000, 0x00000008, 0x22000008, 0x00000003, 0x8384a000,
-	0x0000000f, 0x65870010, 0x00000009, 0x2607ffff, 0x00000000, 0x27750c00,
-	0x00000000, 0x66f40000, 0x0000000c, 0x29000000, 0x00000018, 0x800001aa,
-	0x00000000, 0x03068c00, 0x00000003, 0xf4680c00, 0x00000010, 0x20530000,
-	0x00000000, 0x22c58c00, 0x00000018, 0x8000ffe5, 0x00000000, 0x39760000,
-	0x00000000, 0x39840000, 0x0000000c, 0x33e70019, 0x00000010, 0x001f0000,
-	0x00000000, 0x031e0000, 0x00000000, 0x0760fe00, 0x0000000f, 0x0f0e0007,
-	0x00000000, 0x83850800, 0x00000000, 0x0a7d0000, 0x00000000, 0x0afe0000,
-	0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, 0x00000000, 0x0c000000,
-	0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
-	0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
-	0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
-	0x00000002, 0x33e70e00, 0x00000000, 0x28f30000, 0x00000010, 0x009f0000,
-	0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-	0x00000008, 0x22000006, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
-	0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-	0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
-	0x0000000c, 0x29000000, 0x00000018, 0x8000017e, 0x00000003, 0xf4683600,
-	0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
-	0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
-	0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
-	0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
-	0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
-	0x00000000, 0x22c53600, 0x00000018, 0x8000ffac, 0x00000010, 0x001f0000,
-	0x00000000, 0x031e0000, 0x00000000, 0x83850800, 0x00000009, 0x076000ff,
-	0x0000000f, 0x0f0e0007, 0x00000000, 0x0c000000, 0x00000000, 0x0a7d0000,
-	0x00000000, 0x0afe0000, 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000,
-	0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
-	0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
-	0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
-	0x00000002, 0x33e70e00, 0x00000000, 0x39840000, 0x00000003, 0xb9720800,
-	0x00000000, 0x28f30000, 0x0000000f, 0x65680010, 0x00000010, 0x009f0000,
-	0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
-	0x00000008, 0x22000007, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
-	0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
-	0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
-	0x0000000c, 0x29000000, 0x00000018, 0x80000145, 0x00000003, 0xf4683600,
-	0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
-	0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
-	0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
-	0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
-	0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
-	0x00000000, 0x22c53600, 0x00000018, 0x8000ff73, 0x00000010, 0x0ce70005,
-	0x00000008, 0x2c80000c, 0x00000008, 0x2d000070, 0x00000008, 0x2d800010,
-	0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000018, 0x8000011d,
-	0x00000000, 0x2c1e0000, 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010,
-	0x00000008, 0x2d800048, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
-	0x00000018, 0x8000fe5d, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
-	0x00000010, 0x001f0000, 0x00000000, 0x0f008000, 0x00000008, 0x0f800007,
-	0x00000018, 0x80000006, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
-	0x00000010, 0x001f0000, 0x0000000f, 0x0f470007, 0x00000008, 0x0f800008,
-	0x00000018, 0x80000119, 0x00000010, 0x20530000, 0x00000018, 0x8000fe4f,
-	0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
-	0x00000000, 0x2a000000, 0x00000009, 0x0261ffff, 0x0000000d, 0x70e10001,
-	0x00000018, 0x80000101, 0x00000000, 0x2c400000, 0x00000008, 0x2c8000c4,
-	0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, 0x00000005, 0x70e10800,
-	0x00000010, 0x91de0000, 0x00000018, 0x8000fe41, 0x0000000c, 0x29800001,
-	0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000,
-	0x00000000, 0x02700000, 0x00000000, 0x0d620000, 0x00000000, 0xbb630800,
-	0x00000000, 0x2a000000, 0x00000000, 0x0f400000, 0x00000000, 0x2c400000,
-	0x0000000c, 0x73e7001b, 0x00000010, 0x0ce7000e, 0x00000000, 0x286d0000,
-	0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, 0x00000018, 0x80000069,
-	0x00000008, 0x02000004, 0x00000010, 0x91c40803, 0x00000018, 0x800000f6,
-	0x00000010, 0x20530000, 0x00000018, 0x800000e5, 0x00000008, 0x2c8000b8,
-	0x00000008, 0x2d000010, 0x00000008, 0x2d800048, 0x00000018, 0x80000005,
-	0x00000008, 0x2c8000c4, 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001,
-	0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800048,
-	0x00000008, 0x2d000068, 0x00000008, 0x2d800104, 0x00000000, 0x00000000,
-	0x00000010, 0x91de0000, 0x00000000, 0x27f60000, 0x00000010, 0xb87a9e04,
-	0x00000008, 0x2200000d, 0x00000018, 0x800000e2, 0x00000010, 0x20530000,
-	0x00000018, 0x8000fe18, 0x0000000c, 0x29800001, 0x00000010, 0x91de0000,
-	0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, 0x00000000, 0x02700000,
-	0x00000000, 0x0d620000, 0x00000000, 0xbb630800, 0x00000000, 0x2a000000,
-	0x00000010, 0x0e670011, 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010,
-	0x00000009, 0x266dffff, 0x00000004, 0xb8f1a000, 0x00000000, 0x0f400000,
-	0x0000000c, 0x73e7001c, 0x00000018, 0x80000040, 0x00000008, 0x02000004,
-	0x00000010, 0x91c40802, 0x00000018, 0x800000cd, 0x00000000, 0x2c1e0000,
-	0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, 0x00000008, 0x2d800048,
-	0x00000010, 0x20530000, 0x00000010, 0x91de0000, 0x00000018, 0x8000fdfe,
-	0x0000000c, 0x29800001, 0x00000000, 0x03550000, 0x00000000, 0x06460000,
-	0x00000000, 0x03d60000, 0x00000000, 0x2a000000, 0x0000000f, 0x0f480007,
-	0x00000010, 0xb18c0027, 0x0000000f, 0x47420008, 0x00000009, 0x070e000f,
-	0x00000008, 0x070e0008, 0x00000010, 0x001f0000, 0x00000008, 0x09000001,
-	0x00000007, 0x09121c00, 0x00000003, 0xcbca9200, 0x00000000, 0x0b97a200,
-	0x00000007, 0x4b171c00, 0x0000000f, 0x0a960003, 0x00000000, 0x0a959c00,
-	0x00000000, 0x4a009a00, 0x00000008, 0x82120001, 0x00000001, 0x0c170800,
-	0x00000000, 0x02180000, 0x00000000, 0x0c971800, 0x00000008, 0x0d00ffff,
-	0x00000008, 0x0f800006, 0x0000000c, 0x29000000, 0x00000008, 0x22000001,
-	0x00000000, 0x22c50c00, 0x00000010, 0x009f0000, 0x00000010, 0xb197320b,
-	0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
-	0x00000018, 0x800000a4, 0x00000000, 0x02180000, 0x00000010, 0x20530000,
-	0x00000000, 0x22c53600, 0x00000010, 0x001f0000, 0x00000008, 0x0f800006,
-	0x00000018, 0x8000fff5, 0x00000010, 0x91870002, 0x00000008, 0x2200000a,
-	0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
-	0x00000018, 0x80000098, 0x00000008, 0x0200000a, 0x00000010, 0x91c40804,
-	0x00000010, 0x02c20003, 0x00000010, 0x001f0000, 0x00000008, 0x0f800008,
-	0x00000010, 0x20530000, 0x00000018, 0x8000fdc9, 0x00000000, 0x06820000,
-	0x00000010, 0x001f0000, 0x00000010, 0x0ce70028, 0x00000000, 0x03720000,
-	0x00000000, 0xa8760c00, 0x00000000, 0x0cf60000, 0x00000010, 0xb8723224,
-	0x00000000, 0x03440000, 0x00000008, 0x22000010, 0x00000000, 0x03ca0000,
-	0x0000000f, 0x65680010, 0x00000000, 0x0bcf0000, 0x00000000, 0x27f20000,
-	0x00000010, 0xb7ef3203, 0x0000000c, 0x21420004, 0x0000000c, 0x73e70019,
-	0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x8000007e,
-	0x00000004, 0xb9723200, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
-	0x0000000c, 0x61420004, 0x00000000, 0x25070000, 0x00000000, 0x27970000,
-	0x00000000, 0x290e0000, 0x00000010, 0x0ce70010, 0x00000010, 0xb873320f,
-	0x0000000f, 0x436c0010, 0x00000000, 0x03f30c00, 0x00000000, 0x03f30000,
-	0x00000000, 0x83990e00, 0x00000001, 0x83860e00, 0x00000000, 0x83060e00,
-	0x00000003, 0xf66c0c00, 0x00000000, 0x39f30e00, 0x00000000, 0x3af50e00,
-	0x00000000, 0x7a740000, 0x0000000f, 0x43680010, 0x00000001, 0x83860e00,
-	0x00000000, 0x83060e00, 0x00000003, 0xf4680c00, 0x00000000, 0x286d0000,
-	0x00000000, 0x03690000, 0x00000010, 0xb1f60c54, 0x00000000, 0x0a6a0000,
-	0x00000000, 0x0aeb0000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0c000000,
-	0x00000000, 0x0be90000, 0x00000003, 0x8cf6a000, 0x0000000c, 0x09800002,
-	0x00000010, 0x009f0000, 0x00000010, 0xb8173209, 0x00000000, 0x35140000,
-	0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34970000,
-	0x00000004, 0xb8f12e00, 0x00000010, 0x001f0000, 0x00000008, 0x0f800004,
-	0x00000018, 0x8000fff7, 0x00000000, 0x03e90000, 0x00000010, 0xb8f6a01a,
-	0x00000010, 0x20130019, 0x00000010, 0xb1f10e18, 0x00000000, 0x83973200,
-	0x00000000, 0x38700e00, 0x00000000, 0xbb760e00, 0x00000000, 0x37d00000,
-	0x0000000c, 0x73e7001a, 0x00000003, 0xb8f1a000, 0x00000000, 0x32140000,
-	0x00000000, 0x32950000, 0x00000005, 0x73e72c00, 0x00000000, 0x33190000,
-	0x00000005, 0x74680000, 0x00000010, 0x0ce7000d, 0x00000008, 0x22000009,
-	0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x0000000c, 0x73e70019,
-	0x0000000f, 0x65680010, 0x0000000c, 0x21420004, 0x00000018, 0x8000003c,
-	0x00000010, 0x20530000, 0x0000000c, 0x61420004, 0x00000000, 0x290e0000,
-	0x00000018, 0x80000002, 0x00000010, 0x91973206, 0x00000000, 0x35140000,
-	0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34990000,
-	0x00000004, 0xb8f13200, 0x00000000, 0x83690c00, 0x00000010, 0xb1860013,
-	0x00000000, 0x28e90000, 0x00000008, 0x22000004, 0x00000000, 0x23ec0000,
-	0x00000000, 0x03690000, 0x00000010, 0xb8660c07, 0x00000009, 0x036cffff,
-	0x00000000, 0x326a0000, 0x00000000, 0x32eb0000, 0x00000005, 0x73e70c00,
-	0x00000000, 0x33690000, 0x00000005, 0x74680000, 0x0000000c, 0x73e7001c,
-	0x00000000, 0x03690000, 0x00000010, 0xb1f60c12, 0x00000010, 0xb1d00c11,
-	0x0000000c, 0x21420005, 0x0000000c, 0x33e7001c, 0x00000018, 0x8000000e,
-	0x00000010, 0x2e67000d, 0x00000000, 0x03690000, 0x00000010, 0xb1f60c0b,
-	0x00000010, 0xb1d00c0a, 0x00000000, 0x03440000, 0x00000008, 0x2200000c,
-	0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x80000015,
-	0x0000000c, 0x33e7001c, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
-	0x00000000, 0x290e0000, 0x00000018, 0x000d0000, 0x00000000, 0x06820000,
-	0x00000010, 0x2de7000d, 0x00000010, 0x0ce7000c, 0x00000000, 0x27f20000,
-	0x00000010, 0xb96d9e0a, 0x00000000, 0xa86d9e00, 0x00000009, 0x0361ffff,
-	0x00000010, 0xb7500c07, 0x00000008, 0x2200000f, 0x0000000f, 0x65680010,
-	0x00000000, 0x29000000, 0x00000018, 0x80000004, 0x0000000c, 0x33e7001b,
-	0x00000010, 0x20530000, 0x00000018, 0x000d0000, 0x00000000, 0x2b820000,
-	0x00000010, 0x20d2002f, 0x00000010, 0x0052002e, 0x00000009, 0x054e0007,
-	0x00000010, 0xb18a002c, 0x00000000, 0x050a8c00, 0x00000008, 0x850a0008,
-	0x00000010, 0x918a0029, 0x00000003, 0xc5008800, 0x00000008, 0xa3460001,
-	0x00000010, 0xb1c60007, 0x00000008, 0x22000001, 0x0000000c, 0x29800000,
-	0x00000010, 0x20530000, 0x00000000, 0x274e8c00, 0x00000000, 0x66cd0000,
-	0x00000000, 0x22c58c00, 0x00000008, 0x22000014, 0x00000003, 0x22c58e00,
-	0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
-	0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
-	0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x0000000c, 0x69520000,
-	0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000003, 0x22c58e00,
-	0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
-	0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
-	0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x00000000, 0xa2c58c00,
-	0x00000000, 0xa74e8c00, 0x00000000, 0xe6cd0000, 0x0000000f, 0x620a0010,
-	0x00000008, 0x23460001, 0x0000000c, 0x29800000, 0x00000010, 0x20530000,
-	0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000,
-	0x00000018, 0x00570000 };
+static u8 bnx2_rv2p_proc2[] = {
+	0x1f, 0x8b, 0x08, 0x08, 0x7e, 0xd1, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x58, 0x5b, 0x6c,
+	0x54, 0x55, 0x14, 0x3d, 0xf3, 0xe8, 0xcc, 0x9d, 0xe9, 0xed, 0x9d, 0xf2,
+	0xb2, 0x03, 0xad, 0x08, 0xe5, 0xd1, 0x56, 0x29, 0xe8, 0x54, 0xab, 0x18,
+	0x15, 0x2c, 0x5a, 0x8c, 0x26, 0x68, 0xf0, 0xf9, 0x63, 0x14, 0x04, 0xda,
+	0x9a, 0x56, 0x9b, 0x16, 0xfb, 0x81, 0xaf, 0x09, 0x14, 0x6a, 0x4c, 0x25,
+	0xd6, 0x08, 0xc5, 0x47, 0xa0, 0x11, 0x1f, 0x84, 0xf0, 0xd3, 0x1f, 0x3b,
+	0x8d, 0x7f, 0x0a, 0x24, 0x6a, 0x88, 0xc4, 0xa8, 0x9f, 0x24, 0x68, 0xa0,
+	0x21, 0x0a, 0x58, 0x8b, 0x63, 0x4c, 0xb4, 0xf5, 0xec, 0xbd, 0xf6, 0xb9,
+	0x73, 0xef, 0x6d, 0x8b, 0x1a, 0xf9, 0x70, 0x3e, 0xba, 0x7b, 0xce, 0xd9,
+	0x67, 0x3f, 0xd6, 0xde, 0x67, 0x9f, 0x7d, 0xae, 0x52, 0xfc, 0xbb, 0xb6,
+	0x94, 0xc9, 0x37, 0x83, 0x96, 0xfe, 0x1b, 0x51, 0x0f, 0x85, 0xd3, 0x3c,
+	0x8e, 0x2a, 0xa2, 0x49, 0xa5, 0xb2, 0x5e, 0xea, 0x08, 0x7d, 0x44, 0xe8,
+	0x70, 0x08, 0xf4, 0xb4, 0xd0, 0x77, 0x84, 0xfe, 0x2e, 0xf4, 0x80, 0xd0,
+	0x0f, 0x85, 0xea, 0x5f, 0xd6, 0xd6, 0x7f, 0xf4, 0xb0, 0x46, 0x89, 0x7e,
+	0x1b, 0xd3, 0x35, 0xb0, 0xe3, 0xc1, 0x05, 0xc4, 0x77, 0x61, 0xa2, 0xc0,
+	0x87, 0xf9, 0x53, 0x7d, 0xa0, 0xd7, 0x60, 0xd7, 0xe1, 0xec, 0x0a, 0xb3,
+	0x1f, 0x64, 0x43, 0x09, 0xe8, 0xc6, 0x08, 0xe8, 0xea, 0x65, 0x4c, 0x7a,
+	0x9f, 0x0a, 0x63, 0xdc, 0xb8, 0x94, 0xf6, 0x87, 0x55, 0x83, 0x22, 0x3f,
+	0x67, 0xaa, 0x68, 0x98, 0xc6, 0xf5, 0x56, 0x6c, 0x18, 0xeb, 0x8f, 0xa5,
+	0x40, 0x37, 0x25, 0x41, 0xcf, 0x08, 0xdd, 0x52, 0x2c, 0x7a, 0x6c, 0x31,
+	0xbf, 0x98, 0xf6, 0x25, 0x5c, 0x39, 0xc7, 0x6d, 0xe0, 0x96, 0x95, 0xfd,
+	0x4a, 0xc1, 0xce, 0x03, 0xb2, 0x3e, 0xa3, 0x0a, 0xb3, 0xaf, 0x6f, 0xc1,
+	0xb8, 0xfc, 0x20, 0xf9, 0xa7, 0xff, 0xcf, 0x62, 0x7e, 0xfa, 0xfd, 0xf8,
+	0x15, 0xf6, 0x83, 0x96, 0x2f, 0xa2, 0x75, 0x27, 0xd3, 0x3f, 0x88, 0xf1,
+	0xde, 0x25, 0x32, 0x1f, 0x36, 0xf8, 0x18, 0x79, 0x41, 0x5c, 0x99, 0x58,
+	0xc7, 0x2a, 0x7d, 0xf2, 0x2b, 0x15, 0xe4, 0x2f, 0xc8, 0x2e, 0x35, 0xf2,
+	0x81, 0xfb, 0xfa, 0x16, 0xb2, 0x73, 0x4c, 0xc7, 0x01, 0xb8, 0xcd, 0x0a,
+	0x95, 0xb2, 0xdc, 0x7d, 0x83, 0x5e, 0x3d, 0x51, 0xad, 0x07, 0xfa, 0x54,
+	0xa5, 0xc5, 0x20, 0x65, 0x97, 0x81, 0xaa, 0x5a, 0xbf, 0x1f, 0x7b, 0x97,
+	0x18, 0x7b, 0x30, 0x9e, 0x9d, 0x01, 0xdd, 0x23, 0xf4, 0xaa, 0x3a, 0x26,
+	0xcb, 0x7f, 0xb8, 0xc1, 0x62, 0x0c, 0xb2, 0xb5, 0xde, 0x7c, 0x38, 0x32,
+	0x61, 0xf0, 0x52, 0x8b, 0x40, 0xce, 0x2e, 0x21, 0x3e, 0x1d, 0x9c, 0x4a,
+	0xc8, 0x5d, 0xdf, 0x32, 0x55, 0x1e, 0x7d, 0x30, 0x45, 0x1e, 0x61, 0xff,
+	0xb7, 0x2b, 0x7c, 0xf9, 0xa4, 0xda, 0x25, 0x4f, 0x36, 0x22, 0x8f, 0xac,
+	0xa7, 0x3e, 0x91, 0x85, 0x6b, 0x13, 0xfa, 0xcf, 0x84, 0x7a, 0x32, 0x4e,
+	0x01, 0x8a, 0x2b, 0x87, 0xfd, 0x53, 0xe2, 0xe7, 0x26, 0xed, 0x27, 0xd1,
+	0x8a, 0x50, 0xb6, 0x36, 0xc1, 0x38, 0x35, 0xc4, 0xa0, 0xaf, 0x61, 0x03,
+	0xb6, 0xaf, 0x46, 0x5c, 0x7b, 0x4f, 0x86, 0x8d, 0xfd, 0x51, 0xfa, 0x3b,
+	0xd0, 0xb6, 0x9d, 0x47, 0x03, 0xd1, 0x1d, 0x4c, 0xed, 0x63, 0x95, 0x58,
+	0xee, 0x8a, 0xf0, 0x7a, 0x72, 0x97, 0xcc, 0xf7, 0xec, 0xf0, 0xdb, 0xfd,
+	0x02, 0xf2, 0xdb, 0x7e, 0x7e, 0x47, 0x88, 0xa8, 0x13, 0x73, 0xf9, 0x98,
+	0x3a, 0x3b, 0xb7, 0x13, 0xff, 0x55, 0x6a, 0xd7, 0x20, 0x29, 0x4e, 0xab,
+	0x0d, 0x6b, 0xb1, 0x6f, 0x77, 0x2c, 0xc5, 0xb8, 0x36, 0xad, 0x05, 0xfd,
+	0x1e, 0xf3, 0xf3, 0x9d, 0x1e, 0xe2, 0x2f, 0x9d, 0xe7, 0x0c, 0x71, 0x5e,
+	0xa9, 0x11, 0xce, 0xc7, 0x04, 0x65, 0x06, 0xff, 0xda, 0xaa, 0xc1, 0xdf,
+	0xbc, 0x99, 0x15, 0xbf, 0xd9, 0x9a, 0xe7, 0x3c, 0x18, 0xe8, 0x18, 0x26,
+	0x3f, 0xe7, 0xaa, 0x91, 0x4e, 0xa2, 0x51, 0xd5, 0xb0, 0x90, 0xf0, 0x5e,
+	0x15, 0x36, 0x71, 0x3a, 0x7f, 0x33, 0xcd, 0xcf, 0xd3, 0xeb, 0x26, 0x1e,
+	0x24, 0xd7, 0x92, 0x78, 0x45, 0x5d, 0x7c, 0xf2, 0x61, 0xf8, 0xdb, 0xcd,
+	0x76, 0x5f, 0x97, 0xec, 0xe6, 0xfc, 0x4a, 0xaa, 0x26, 0x8e, 0x7f, 0xd4,
+	0x6a, 0x1b, 0xc6, 0xfa, 0xf9, 0x8f, 0x8d, 0x5c, 0xd2, 0x53, 0x23, 0x75,
+	0x44, 0xb9, 0x72, 0xa2, 0x37, 0x83, 0xee, 0x34, 0x7a, 0xeb, 0x88, 0x6f,
+	0xb1, 0x42, 0xfe, 0x26, 0x26, 0xc9, 0x69, 0x03, 0xce, 0xf6, 0x33, 0xec,
+	0xf7, 0x35, 0xf6, 0x85, 0x3e, 0x63, 0x2f, 0xe6, 0x2f, 0xfa, 0xf4, 0x95,
+	0x7b, 0xf4, 0x11, 0x7f, 0x51, 0xf2, 0x02, 0xef, 0x9b, 0x63, 0x3d, 0x3b,
+	0xcc, 0xb8, 0x58, 0xcf, 0x0c, 0x41, 0xfe, 0xc5, 0x21, 0xe2, 0x9f, 0x23,
+	0x7a, 0xed, 0xff, 0x88, 0xe7, 0x9c, 0x30, 0xe4, 0x4c, 0x8f, 0x5f, 0xc1,
+	0x6f, 0xe3, 0x17, 0xcb, 0xb5, 0x47, 0x73, 0x69, 0xe6, 0x33, 0xf1, 0xe8,
+	0x0e, 0x73, 0x02, 0xa6, 0x1b, 0x16, 0xfa, 0x71, 0x33, 0xf6, 0x9c, 0xdf,
+	0xcc, 0x79, 0x3e, 0xd1, 0x26, 0x75, 0x40, 0x71, 0x9d, 0xb9, 0x5d, 0xe2,
+	0xa1, 0xf3, 0x3a, 0x04, 0xff, 0x46, 0x73, 0x2c, 0x3f, 0xd9, 0xc5, 0x79,
+	0xb9, 0xd2, 0x8e, 0xe6, 0x38, 0x5e, 0xd6, 0xd9, 0x21, 0x6c, 0x2b, 0xd4,
+	0x4f, 0xc8, 0x6b, 0xb6, 0x41, 0x9b, 0xa4, 0x8e, 0x9e, 0x15, 0xda, 0x6d,
+	0x33, 0x3e, 0xba, 0x8e, 0x59, 0x2c, 0x3f, 0x9b, 0x32, 0xf7, 0x0c, 0xd6,
+	0x9f, 0x16, 0x39, 0x3f, 0x0a, 0x55, 0x22, 0xa7, 0x55, 0xf6, 0x9f, 0xf3,
+	0xc9, 0x89, 0x04, 0xe4, 0x84, 0x94, 0xc1, 0xcd, 0x9c, 0xef, 0x5d, 0x52,
+	0xbf, 0xf7, 0xc5, 0xa6, 0xab, 0xb7, 0x7c, 0x0e, 0xdc, 0xba, 0x5a, 0x8e,
+	0x3a, 0x53, 0x1f, 0x0d, 0xb3, 0xbf, 0x03, 0xdd, 0x3b, 0x80, 0x53, 0x8f,
+	0xe0, 0x14, 0x07, 0x4e, 0xf3, 0x0a, 0xf5, 0x59, 0x14, 0xd4, 0x90, 0xfe,
+	0x53, 0x21, 0xe3, 0xc7, 0xbe, 0x98, 0xaf, 0xfe, 0xf6, 0x9a, 0xfa, 0x5b,
+	0xa8, 0xd3, 0xc4, 0xff, 0xb3, 0xa9, 0x6f, 0x5a, 0x9f, 0xd1, 0xff, 0x6f,
+	0xf5, 0x72, 0x9c, 0x92, 0xdd, 0x7d, 0x26, 0xce, 0x98, 0x2e, 0xd4, 0xd9,
+	0x22, 0x22, 0xcb, 0x46, 0x3a, 0x99, 0x5e, 0xdf, 0xbc, 0x15, 0xf3, 0x65,
+	0x7c, 0x4e, 0x6e, 0x09, 0x01, 0xaf, 0xa8, 0x3a, 0xde, 0x87, 0xba, 0xae,
+	0xe2, 0x2c, 0xaf, 0xe2, 0x28, 0xc7, 0x3f, 0xaa, 0xe5, 0x12, 0xdf, 0x67,
+	0xa1, 0x42, 0x3e, 0x7a, 0xfd, 0xd9, 0xad, 0xf3, 0x84, 0xec, 0x88, 0xe9,
+	0xbc, 0xa5, 0xb1, 0x3e, 0x47, 0xb6, 0xe4, 0xf9, 0x1a, 0xe6, 0xb3, 0xc7,
+	0x22, 0x34, 0xff, 0x80, 0xd5, 0xd3, 0x87, 0xf9, 0x9f, 0x1a, 0x69, 0xbc,
+	0xce, 0x7e, 0x0d, 0xe7, 0xcc, 0x7e, 0x0d, 0xf5, 0xcb, 0x2a, 0x3a, 0x88,
+	0xba, 0xd6, 0x78, 0x10, 0xf2, 0x71, 0x4f, 0x7b, 0xfd, 0xf2, 0xe2, 0x47,
+	0xe7, 0xe1, 0xb2, 0x38, 0xd9, 0xcf, 0x09, 0x4e, 0x97, 0x7c, 0xf1, 0x39,
+	0x6c, 0xe2, 0xd3, 0x1b, 0x93, 0xf3, 0xd2, 0x7c, 0x29, 0xe8, 0x17, 0xf1,
+	0x9d, 0x71, 0xef, 0x9d, 0xae, 0x95, 0xa0, 0xdd, 0x2b, 0xe5, 0x9c, 0xd6,
+	0xf9, 0xf3, 0x6b, 0x3e, 0xea, 0xf2, 0xb8, 0x7b, 0x4f, 0x20, 0xbf, 0xac,
+	0x9d, 0xf0, 0x4b, 0xbd, 0x28, 0x79, 0x3c, 0x2e, 0xf4, 0x65, 0xc9, 0xdf,
+	0x6d, 0xd2, 0xb7, 0x98, 0xfe, 0xe2, 0x0f, 0xcc, 0x3b, 0xfd, 0x6e, 0x5f,
+	0x60, 0xea, 0x36, 0x8d, 0x43, 0xca, 0x89, 0x13, 0x83, 0x36, 0xeb, 0x33,
+	0x24, 0x4a, 0xcf, 0x1a, 0xe0, 0x35, 0x52, 0x07, 0xbe, 0xdd, 0x91, 0xb0,
+	0x8c, 0x21, 0x6f, 0xac, 0xda, 0x77, 0x0f, 0xd7, 0x4f, 0xc6, 0x93, 0xe4,
+	0xc6, 0xdc, 0xfa, 0x24, 0x79, 0xaf, 0x26, 0x84, 0x96, 0x2f, 0xbe, 0x2c,
+	0xbe, 0x85, 0xfe, 0x64, 0xa9, 0x17, 0xdf, 0x97, 0x34, 0xbe, 0xbc, 0xaf,
+	0xbe, 0xf9, 0x12, 0xa6, 0x4b, 0x6f, 0x05, 0xed, 0xbb, 0x95, 0xe7, 0x17,
+	0xa3, 0xee, 0x11, 0x7e, 0x9c, 0x5f, 0xf5, 0x6f, 0x0c, 0x9a, 0x7e, 0x42,
+	0xf0, 0x08, 0xf4, 0x41, 0x65, 0x77, 0x80, 0xbe, 0x29, 0x74, 0xce, 0x2a,
+	0xd0, 0xbd, 0xab, 0xfc, 0x71, 0x88, 0xa5, 0x7c, 0x71, 0xac, 0x47, 0x1c,
+	0x8f, 0x4c, 0x04, 0xeb, 0x81, 0xc4, 0x4b, 0xc7, 0x27, 0x70, 0xbf, 0x1b,
+	0xfd, 0xe2, 0xce, 0xdf, 0xc5, 0xed, 0x4a, 0xc7, 0xab, 0x7b, 0x25, 0xee,
+	0x93, 0x0e, 0xe9, 0x4b, 0xc7, 0xdc, 0xfb, 0xe2, 0x9f, 0xc4, 0x31, 0x7e,
+	0x85, 0xe3, 0x78, 0xf7, 0xff, 0x2c, 0x8e, 0x9d, 0x12, 0xc7, 0x22, 0xb9,
+	0x57, 0x4d, 0xbf, 0xd9, 0x2e, 0x7d, 0x18, 0xf5, 0x8d, 0x7e, 0xbd, 0x4f,
+	0x70, 0x1f, 0x78, 0xb5, 0x5b, 0x8f, 0xe7, 0x33, 0x7f, 0x4e, 0xf6, 0x95,
+	0xca, 0xbe, 0x7b, 0x26, 0xed, 0x3b, 0xc5, 0xf5, 0xee, 0xf1, 0xf1, 0xc9,
+	0xef, 0x15, 0x9f, 0x9d, 0x59, 0x95, 0x02, 0xee, 0xa8, 0xe3, 0xb1, 0x29,
+	0xde, 0x37, 0x86, 0x1f, 0xf9, 0xb5, 0x36, 0x85, 0xba, 0x05, 0xfe, 0xb9,
+	0x9e, 0x7a, 0x4a, 0xe3, 0xfb, 0xc7, 0xa7, 0xef, 0x57, 0x8d, 0x3c, 0xc4,
+	0x6d, 0x43, 0xb8, 0x84, 0xf9, 0x4e, 0xb7, 0xf3, 0x7d, 0xe7, 0xfa, 0xb7,
+	0x9a, 0xfd, 0x3a, 0x2a, 0xfe, 0x55, 0x88, 0x7f, 0x7a, 0xb9, 0x96, 0xeb,
+	0xbe, 0x75, 0xba, 0xdd, 0xeb, 0xdf, 0x9d, 0x97, 0xd1, 0xf7, 0x4f, 0xfb,
+	0x63, 0xd1, 0x9b, 0x32, 0xfa, 0x49, 0x5e, 0xb9, 0xf4, 0x7d, 0xd4, 0x4f,
+	0x62, 0x7e, 0x72, 0x9f, 0x41, 0xfa, 0x5b, 0x34, 0x5e, 0x72, 0xdf, 0x70,
+	0x3e, 0x47, 0xac, 0xa3, 0x6c, 0x57, 0x5e, 0xf9, 0x71, 0x39, 0x23, 0x7c,
+	0x53, 0xc5, 0x8d, 0xd6, 0x8b, 0x64, 0x7d, 0x2a, 0xbf, 0xc5, 0x4e, 0x37,
+	0x1f, 0x64, 0x1f, 0xf3, 0x35, 0x0b, 0x5f, 0x34, 0x34, 0x39, 0xfe, 0x18,
+	0xe5, 0xab, 0x38, 0xaf, 0xf7, 0x6f, 0xcb, 0x11, 0x9f, 0x76, 0x9e, 0xf3,
+	0xf0, 0xfb, 0x80, 0x7d, 0xe9, 0x2b, 0x80, 0x23, 0xf1, 0xcd, 0x50, 0x4d,
+	0xce, 0x74, 0x78, 0xe1, 0xdd, 0x30, 0x9a, 0x33, 0x78, 0xdb, 0xec, 0xe7,
+	0x48, 0x27, 0xe9, 0x5f, 0x1d, 0xc0, 0x31, 0x2c, 0x38, 0x9e, 0x50, 0x7f,
+	0x9f, 0xf7, 0xc6, 0x0f, 0x6f, 0x5e, 0x8c, 0xff, 0x19, 0xcc, 0xe3, 0x87,
+	0xe5, 0x5d, 0xdd, 0x18, 0x03, 0xfd, 0x2e, 0x62, 0xec, 0x46, 0x5e, 0xdf,
+	0xc3, 0xe7, 0xb5, 0x4a, 0xf5, 0xf2, 0xbb, 0xc3, 0x52, 0x0d, 0x6b, 0xc9,
+	0xee, 0x94, 0xae, 0x7f, 0xc8, 0x77, 0x27, 0xee, 0xbd, 0xb7, 0x75, 0x0d,
+	0x4c, 0xc4, 0x69, 0x58, 0x31, 0x33, 0xc1, 0x82, 0xde, 0xf8, 0xe2, 0x4b,
+	0x5e, 0x7e, 0xaf, 0xbf, 0x18, 0xf3, 0x65, 0xf7, 0x91, 0x9c, 0x88, 0xda,
+	0x8b, 0xba, 0xfb, 0xee, 0x1e, 0xd0, 0xb7, 0xd5, 0xbd, 0xd8, 0x3f, 0x73,
+	0x3b, 0xd7, 0x51, 0xab, 0x4c, 0xf2, 0x2b, 0x0d, 0x5c, 0xd3, 0xa8, 0xc3,
+	0x13, 0x13, 0xaa, 0x04, 0xf7, 0x9a, 0x79, 0x07, 0xab, 0x1a, 0xd1, 0x8b,
+	0xfa, 0x68, 0x17, 0xde, 0xc1, 0x44, 0x8b, 0x83, 0x7d, 0x9f, 0x55, 0xe8,
+	0xaf, 0x08, 0x8f, 0xf7, 0x5d, 0x1c, 0xd3, 0xe1, 0x60, 0x5d, 0xf2, 0xfa,
+	0x15, 0x93, 0x73, 0xfd, 0xab, 0xfb, 0x6e, 0xee, 0xe1, 0x7e, 0x2a, 0x19,
+	0xac, 0xcb, 0x01, 0xf9, 0xfb, 0x24, 0x7e, 0x49, 0x89, 0x5f, 0x54, 0xc7,
+	0x0f, 0xef, 0xed, 0x4f, 0x7d, 0xef, 0x7a, 0xaa, 0x1b, 0xde, 0xbc, 0xfb,
+	0xfc, 0x4f, 0x63, 0xd7, 0xf6, 0x98, 0xb7, 0x0e, 0x57, 0xbb, 0xe7, 0xae,
+	0x43, 0xde, 0x8b, 0x5d, 0x87, 0x30, 0xce, 0x73, 0xbf, 0xbc, 0x38, 0xd3,
+	0x21, 0x79, 0x74, 0x57, 0x44, 0xf2, 0x41, 0xec, 0xfb, 0x22, 0x62, 0xee,
+	0x1b, 0x8c, 0xbf, 0x92, 0xfb, 0xee, 0x97, 0x2a, 0xf4, 0xd9, 0x17, 0x87,
+	0xcc, 0xfb, 0xc4, 0xbc, 0x57, 0xb0, 0xbe, 0x3e, 0xae, 0x04, 0x67, 0xbe,
+	0xff, 0xb5, 0x3f, 0x9c, 0xaf, 0x99, 0x8e, 0x61, 0x1f, 0x5e, 0x2a, 0x16,
+	0x78, 0xbf, 0xc4, 0xe5, 0xfb, 0x45, 0xbf, 0xe0, 0xe1, 0xf0, 0xf9, 0x29,
+	0xd5, 0xf6, 0x13, 0x4d, 0x65, 0x3a, 0x73, 0xb0, 0xa7, 0xd5, 0xed, 0x23,
+	0xc1, 0x27, 0xd4, 0x79, 0x4b, 0xde, 0xc1, 0xf2, 0x5e, 0xd6, 0xef, 0x61,
+	0xf4, 0x73, 0xad, 0x79, 0x8c, 0xc7, 0xd0, 0xb7, 0x39, 0xbf, 0xca, 0xbd,
+	0xb5, 0x75, 0x9b, 0xe9, 0x4b, 0xa7, 0xde, 0x67, 0xee, 0xb9, 0xb6, 0x6a,
+	0xd0, 0x16, 0xee, 0x5b, 0x1f, 0xb2, 0xf3, 0x92, 0x1f, 0x85, 0x77, 0x89,
+	0xff, 0x3d, 0x62, 0xfa, 0x85, 0x73, 0xc5, 0xb8, 0x67, 0xf3, 0xbd, 0x34,
+	0xa1, 0xdf, 0x23, 0x09, 0x6f, 0x9e, 0x25, 0x32, 0x65, 0x82, 0xfb, 0xec,
+	0x9b, 0x40, 0xf7, 0xdc, 0x84, 0xbe, 0xbc, 0xb5, 0x4b, 0x70, 0xb8, 0x91,
+	0x71, 0x5b, 0x3e, 0x9a, 0x0b, 0x7e, 0x67, 0x21, 0x5c, 0x7f, 0x73, 0xfb,
+	0xd1, 0x73, 0x6c, 0xd7, 0xbc, 0x81, 0x3c, 0xf3, 0xcd, 0x55, 0xb3, 0xf8,
+	0xfc, 0xa6, 0x9d, 0x51, 0xd8, 0x99, 0xe9, 0x17, 0xbf, 0xda, 0x6f, 0x01,
+	0xed, 0x92, 0x3a, 0x73, 0xd2, 0x7d, 0x97, 0xc3, 0x4e, 0x53, 0x4f, 0x26,
+	0xbf, 0x13, 0x30, 0x9e, 0x5b, 0xc7, 0x63, 0xd5, 0xbc, 0x95, 0xe4, 0x97,
+	0x4c, 0x7a, 0xcf, 0x16, 0xe2, 0x6e, 0xf2, 0xc1, 0xe4, 0x8f, 0xf7, 0x1d,
+	0x7b, 0x9b, 0xa7, 0x5e, 0xfa, 0xe3, 0xef, 0x70, 0xbe, 0x84, 0x65, 0x3d,
+	0x96, 0xe9, 0xef, 0xbb, 0x3c, 0x3e, 0x6f, 0x01, 0x9f, 0x8c, 0xd8, 0x6d,
+	0xb7, 0xf0, 0x3b, 0x74, 0x96, 0xda, 0x25, 0xf1, 0x39, 0x57, 0x2d, 0x75,
+	0x50, 0xec, 0xfb, 0x49, 0xfa, 0x1f, 0xc4, 0x31, 0x6e, 0x6f, 0xc9, 0x49,
+	0xdc, 0x24, 0x8f, 0x9e, 0x16, 0xbf, 0x7f, 0x84, 0xdf, 0xb6, 0xf1, 0xbb,
+	0xc5, 0xf5, 0xdb, 0xd4, 0x59, 0xaf, 0x9c, 0x99, 0x3a, 0x1f, 0xb8, 0x5e,
+	0xdb, 0x27, 0xf9, 0xdd, 0x53, 0x24, 0xe7, 0xa1, 0x42, 0xbe, 0x3b, 0x38,
+	0xe2, 0x4f, 0x89, 0x6a, 0x5a, 0xee, 0xdd, 0x57, 0x2c, 0xfb, 0x92, 0x7a,
+	0x1f, 0xe6, 0x71, 0xfe, 0xec, 0x29, 0xf0, 0x34, 0xdf, 0x11, 0x8c, 0xdc,
+	0xe0, 0x39, 0xf2, 0xe2, 0xc7, 0x37, 0x13, 0xff, 0x50, 0x07, 0x74, 0x9c,
+	0x6a, 0xcd, 0xf7, 0x07, 0xcc, 0xe3, 0xfc, 0x26, 0xf7, 0xb7, 0xa1, 0xaf,
+	0xdc, 0xdf, 0x76, 0x48, 0xfa, 0x08, 0xc1, 0xe5, 0x81, 0x21, 0xb2, 0x43,
+	0xc7, 0xae, 0xd2, 0x7f, 0xfe, 0x61, 0x47, 0x54, 0xec, 0x28, 0xf7, 0xd8,
+	0x11, 0xd0, 0x7b, 0x1d, 0xcd, 0xaf, 0x50, 0x5f, 0x73, 0x1e, 0x2e, 0x57,
+	0xeb, 0x29, 0x47, 0xf4, 0xbd, 0xb0, 0xae, 0x88, 0xc6, 0xcb, 0xd4, 0xab,
+	0xf0, 0xb7, 0x37, 0x59, 0x84, 0x3a, 0x96, 0xdc, 0x49, 0xf3, 0x35, 0xea,
+	0xd5, 0x3e, 0x0e, 0xc4, 0x2b, 0xea, 0x18, 0xea, 0x73, 0xe3, 0x41, 0xb6,
+	0x47, 0x1d, 0x1f, 0x34, 0xf5, 0x7a, 0xca, 0xef, 0x98, 0xbd, 0xeb, 0xa4,
+	0x5e, 0x9c, 0xc0, 0x77, 0x51, 0xfd, 0x5e, 0x23, 0xfe, 0xd9, 0xe6, 0x3d,
+	0xb8, 0xfb, 0x98, 0xa1, 0x8b, 0x7c, 0xe3, 0xfd, 0x27, 0x96, 0x0a, 0xad,
+	0xf2, 0x8d, 0x07, 0xd6, 0x55, 0x09, 0xad, 0x36, 0xe3, 0xe9, 0xbe, 0x2b,
+	0x5e, 0x29, 0xf9, 0x62, 0xf7, 0x7b, 0xe2, 0xcf, 0x47, 0xe2, 0xcf, 0x59,
+	0xe0, 0x9f, 0xdc, 0x28, 0x78, 0x2c, 0x0a, 0xea, 0x17, 0xbb, 0xdc, 0x73,
+	0x63, 0xd6, 0x11, 0x8f, 0x47, 0xd5, 0x5f, 0x3f, 0x97, 0x8f, 0x31, 0xd8,
+	0x17, 0x00, 0x00, 0x00 };
 
 static const int bnx2_TPAT_b06FwReleaseMajor = 0x1;
 static const int bnx2_TPAT_b06FwReleaseMinor = 0x0;
@@ -2339,201 +1330,199 @@
 static const int bnx2_TPAT_b06FwBssLen = 0x250;
 static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60;
 static const int bnx2_TPAT_b06FwSbssLen = 0x34;
-static u32 bnx2_TPAT_b06FwText[(0x122c/4) + 1] = {
-	0x0a000218, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20322e35,
-	0x2e313100, 0x02050b01, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800,
-	0x24421a60, 0x3c030800, 0x24631cf0, 0xac400000, 0x0043202b, 0x1480fffd,
-	0x24420004, 0x3c1d0800, 0x37bd2ffc, 0x03a0f021, 0x3c100800, 0x26100860,
-	0x3c1c0800, 0x279c1a60, 0x0e000546, 0x00000000, 0x0000000d, 0x8f820010,
-	0x8c450008, 0x24030800, 0xaf430178, 0x97430104, 0x3c020008, 0xaf420140,
-	0x8f820024, 0x30420001, 0x10400007, 0x3069ffff, 0x24020002, 0x2523fffe,
-	0xa7420146, 0xa7430148, 0x0a000242, 0x3c020800, 0xa7400146, 0x3c020800,
-	0x8c43083c, 0x1460000e, 0x24020f00, 0x8f820024, 0x30430020, 0x0003182b,
-	0x00031823, 0x30650009, 0x30420c00, 0x24030400, 0x14430002, 0x34a40001,
-	0x34a40005, 0xa744014a, 0x0a000264, 0x3c020800, 0x8f830014, 0x14620008,
-	0x00000000, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023, 0x3042000d,
-	0x0a000262, 0x34420005, 0x8f820024, 0x30420020, 0x0002102b, 0x00021023,
-	0x30420009, 0x34420001, 0xa742014a, 0x3c020800, 0x8c430820, 0x8f840024,
-	0x3c020048, 0x00621825, 0x30840006, 0x24020002, 0x1082000d, 0x2c820003,
-	0x50400005, 0x24020004, 0x10800012, 0x3c020001, 0x0a000284, 0x00000000,
-	0x10820007, 0x24020006, 0x1482000f, 0x3c020111, 0x0a00027c, 0x00621025,
-	0x0a00027b, 0x3c020101, 0x3c020011, 0x00621025, 0x24030001, 0xaf421000,
-	0xaf830020, 0x0a000284, 0x00000000, 0x00621025, 0xaf421000, 0xaf800020,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f830020, 0x1060003f,
-	0x3c048000, 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039,
-	0x00000000, 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000,
-	0x97421014, 0x14400031, 0x00000000, 0x97421008, 0x8f840010, 0x24420006,
-	0x00024082, 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001,
-	0x10400004, 0x00000000, 0x0000000d, 0x0a0002c3, 0x00081080, 0x5460000f,
-	0x30a5ffff, 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b,
-	0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fb,
-	0x8ce20000, 0x0a0002c2, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b,
-	0x00621824, 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000205,
-	0x8ce20000, 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000,
-	0x8c620830, 0x24420001, 0xac620830, 0x8f840018, 0x01202821, 0x24820008,
-	0x30421fff, 0x24434000, 0x0343d821, 0x30a30007, 0xaf84000c, 0xaf820018,
-	0xaf420084, 0x10600002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000,
-	0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023,
-	0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000,
-	0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x8f830024, 0x27bdffe0,
-	0xafbf0018, 0xafb10014, 0x30620200, 0x14400004, 0xafb00010, 0x0000000d,
-	0x00000000, 0x24000242, 0x00031a82, 0x30630003, 0x000310c0, 0x00431021,
-	0x00021080, 0x00431021, 0x00021080, 0x3c030800, 0x24631aa0, 0x00438821,
-	0x8e240000, 0x10800004, 0x00000000, 0x0000000d, 0x00000000, 0x2400024d,
-	0x8f850010, 0x24020001, 0xae220000, 0x8ca70008, 0xa2200007, 0x8f620004,
-	0x26300014, 0x02002021, 0x00021402, 0xa2220004, 0x304600ff, 0x24c60005,
-	0x0e000673, 0x00063082, 0x8f620004, 0xa6220008, 0x8f430108, 0x3c021000,
-	0x00621824, 0x10600008, 0x00000000, 0x97420104, 0x92230007, 0x2442ffec,
-	0x3045ffff, 0x34630002, 0x0a000321, 0xa2230007, 0x97420104, 0x2442fff0,
-	0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x54400005, 0x92230007,
-	0x92220007, 0x34420001, 0xa2220007, 0x92230007, 0x24020001, 0x10620009,
-	0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003, 0x1062000a,
-	0x00000000, 0x0a000342, 0x00000000, 0x8f820010, 0x8c43000c, 0x3c04ffff,
-	0x00641824, 0x00651825, 0x0a000342, 0xac43000c, 0x8f820010, 0x8c430010,
-	0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004, 0x3042ffff,
-	0x24420002, 0x00021083, 0xa2220005, 0x304500ff, 0x8f820010, 0x3c04ffff,
-	0x00052880, 0x00a22821, 0x8ca70000, 0x96220008, 0x97430104, 0x00e42024,
-	0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x92240005, 0x00041080,
-	0x02021021, 0x90430000, 0x3c05fff6, 0x34a5ffff, 0x3063000f, 0x00832021,
-	0xa2240006, 0x308200ff, 0x24420003, 0x00021080, 0x02021021, 0x8c460000,
-	0x308300ff, 0x8f820010, 0x3c04ff3f, 0x00031880, 0x00c53824, 0x00621821,
-	0xae26000c, 0xac67000c, 0x8e22000c, 0x92230006, 0x3484ffff, 0x00441024,
-	0x24630003, 0x00031880, 0x02031821, 0x00e42024, 0xae22000c, 0xac640000,
-	0x92220006, 0x24420004, 0x00021080, 0x02021021, 0x94470002, 0xac470000,
-	0x92230006, 0x8f820010, 0x00031880, 0x00621821, 0x24020010, 0xac670010,
-	0x24030002, 0xa7420140, 0xa7400142, 0xa7400144, 0xa7430146, 0x97420104,
-	0x24030001, 0x2442fffe, 0xa7420148, 0xa743014a, 0x8f820024, 0x24030002,
-	0x30440006, 0x1083000d, 0x2c820003, 0x10400005, 0x24020004, 0x10800011,
-	0x3c020009, 0x0a0003a5, 0x00000000, 0x10820007, 0x24020006, 0x1482000d,
-	0x3c020119, 0x0a00039f, 0x24030001, 0x0a00039e, 0x3c020109, 0x3c020019,
-	0x24030001, 0xaf421000, 0xaf830020, 0x0a0003a5, 0x00000000, 0xaf421000,
-	0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x92220004,
-	0x24030008, 0x8f840020, 0x24420002, 0x30420007, 0x00621823, 0x30630007,
-	0x10800006, 0xae230010, 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd,
-	0x00000000, 0x8f820018, 0xaf82000c, 0x24420010, 0x30421fff, 0xaf820018,
-	0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007,
-	0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821,
-	0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030,
-	0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021,
-	0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008,
-	0x27bd0020, 0x8f830024, 0x27bdffe0, 0xafbf0018, 0xafb10014, 0x30620200,
-	0x14400004, 0xafb00010, 0x0000000d, 0x00000000, 0x240002e4, 0x00031a82,
-	0x30630003, 0x000310c0, 0x00431021, 0x00021080, 0x00431021, 0x00021080,
-	0x3c030800, 0x24631aa0, 0x00438021, 0x8e040000, 0x14800004, 0x00000000,
-	0x0000000d, 0x00000000, 0x240002e9, 0x8f620004, 0x04410008, 0x26050014,
-	0x92020006, 0x8e03000c, 0x24420003, 0x00021080, 0x00a21021, 0xac430000,
-	0xae000000, 0x92020005, 0x24420001, 0x00021080, 0x00a21021, 0x8c430000,
-	0x3c040001, 0x00641821, 0xac430000, 0x92060004, 0x27710008, 0x02202021,
-	0x24c60005, 0x0e000673, 0x00063082, 0x92040006, 0x3c057fff, 0x8f620004,
-	0x00042080, 0x00912021, 0x8c830004, 0x34a5ffff, 0x00451024, 0x00621821,
-	0xac830004, 0x92050005, 0x3c07ffff, 0x92040004, 0x00052880, 0x00b12821,
-	0x8ca30000, 0x97420104, 0x96060008, 0x00671824, 0x00441021, 0x00461023,
-	0x3042ffff, 0x00621825, 0xaca30000, 0x92030007, 0x24020001, 0x1062000a,
-	0x28620002, 0x1440001d, 0x2402000a, 0x24020002, 0x10620019, 0x24020003,
-	0x1062000e, 0x2402000a, 0x0a000447, 0x00000000, 0x92020004, 0x97430104,
-	0x8e24000c, 0x00621821, 0x2463fff2, 0x3063ffff, 0x00872024, 0x00832025,
-	0xae24000c, 0x0a000447, 0x2402000a, 0x92020004, 0x97430104, 0x8e240010,
-	0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025, 0xae240010,
-	0x2402000a, 0xa7420140, 0x96030012, 0x8f840024, 0xa7430142, 0x92020004,
-	0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001, 0xa7430148,
-	0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005, 0x24020004,
-	0x10800011, 0x3c020041, 0x0a00046c, 0x00000000, 0x10820007, 0x24020006,
-	0x1482000d, 0x3c020151, 0x0a000466, 0x24030001, 0x0a000465, 0x3c020141,
-	0x3c020051, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00046c, 0x00000000,
-	0xaf421000, 0xaf800020, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x8f820020, 0x8f840018, 0x10400006, 0x92030004, 0x3c058000, 0x8f421000,
-	0x00451024, 0x1040fffd, 0x00000000, 0x2463000a, 0x30620007, 0x10400002,
-	0x24620007, 0x304303f8, 0x00831021, 0x30421fff, 0xaf84000c, 0xaf820018,
-	0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff, 0x30620007,
-	0x10400002, 0x24620007, 0x3043fff8, 0x8f820030, 0x8f840000, 0x00431821,
-	0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023, 0xaf820030,
-	0x8f840030, 0x34028000, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x00821021,
-	0x03421821, 0x3c021000, 0xaf830010, 0xaf440080, 0xaf420178, 0x03e00008,
-	0x27bd0020, 0x8f620000, 0x97430104, 0x3c048000, 0x3045ffff, 0x3066ffff,
-	0x8f420178, 0x00441024, 0x1440fffd, 0x2402000a, 0x30a30007, 0xa7420140,
-	0x24020008, 0x00431023, 0x30420007, 0x24a3fffe, 0xa7420142, 0xa7430144,
-	0xa7400146, 0xa7460148, 0x8f420108, 0x8f830024, 0x30420020, 0x0002102b,
-	0x00021023, 0x30420009, 0x34420001, 0x30630006, 0xa742014a, 0x24020002,
-	0x1062000d, 0x2c620003, 0x10400005, 0x24020004, 0x10600011, 0x3c020041,
-	0x0a0004d6, 0x00000000, 0x10620007, 0x24020006, 0x1462000d, 0x3c020151,
-	0x0a0004d0, 0x24030001, 0x0a0004cf, 0x3c020141, 0x3c020051, 0x24030001,
-	0xaf421000, 0xaf830020, 0x0a0004d6, 0x00000000, 0xaf421000, 0xaf800020,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x8f820020, 0x24a30008,
-	0x8f850018, 0x10400006, 0x30c6ffff, 0x3c048000, 0x8f421000, 0x00441024,
-	0x1040fffd, 0x00000000, 0x3063ffff, 0x30620007, 0x10400002, 0x24620007,
-	0x3043fff8, 0x00a31021, 0x30421fff, 0x24434000, 0x0343d821, 0x00c02021,
-	0x30830007, 0xaf85000c, 0xaf820018, 0xaf420084, 0x10600002, 0x24820007,
-	0x3044fff8, 0x8f820030, 0x8f850000, 0x00441821, 0xaf82001c, 0x0065102b,
-	0xaf830030, 0x14400002, 0x00651023, 0xaf820030, 0x8f840030, 0x34028000,
-	0x3c030800, 0x8c650834, 0x00821021, 0x03421821, 0xaf830010, 0xaf440080,
-	0x10a00006, 0x2402000e, 0x9383002f, 0x14620004, 0x3c021000, 0x2402043f,
-	0xa7420148, 0x3c021000, 0x03e00008, 0xaf420178, 0x8f820024, 0x30424000,
-	0x10400005, 0x24020800, 0x0000000d, 0x00000000, 0x2400040e, 0x24020800,
-	0xaf420178, 0x97440104, 0x3c030008, 0xaf430140, 0x8f820024, 0x30420001,
-	0x10400006, 0x3085ffff, 0x24020002, 0x24a3fffe, 0xa7420146, 0x0a000526,
-	0xa7430148, 0xa7400146, 0x8f840018, 0x2402000d, 0xa742014a, 0x24830008,
-	0x30631fff, 0x24624000, 0x0342d821, 0x30a20007, 0xaf84000c, 0xaf830018,
-	0xaf430084, 0x10400002, 0x24a20007, 0x3045fff8, 0x8f820030, 0x8f840000,
-	0x00451821, 0xaf82001c, 0x0064102b, 0xaf830030, 0x14400002, 0x00641023,
-	0xaf820030, 0x8f840030, 0x34028000, 0x00821021, 0x03421821, 0x3c021000,
-	0xaf830010, 0xaf440080, 0x03e00008, 0xaf420178, 0x27bdffe8, 0x3c046008,
-	0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f, 0x375b4000,
-	0x00431024, 0x3442380c, 0xac825000, 0x8f430008, 0x3c100800, 0x37428000,
-	0x34630001, 0xaf430008, 0xaf820010, 0x3c02601c, 0xaf800018, 0xaf400080,
-	0xaf400084, 0x8c450008, 0x3c036000, 0x8c620808, 0x3c040800, 0x3c030080,
-	0xac830820, 0x3042fff0, 0x38420010, 0x2c420001, 0xaf850000, 0xaf820004,
-	0x0e000658, 0x00000000, 0x8f420000, 0x30420001, 0x1040fffb, 0x00000000,
-	0x8f430108, 0x8f440100, 0x30622000, 0xaf830024, 0xaf840014, 0x10400004,
-	0x8e02082c, 0x24420001, 0x0a0005c6, 0xae02082c, 0x30620200, 0x14400003,
-	0x24020f00, 0x14820027, 0x24020d00, 0x97420104, 0x1040001c, 0x30624000,
-	0x14400005, 0x00000000, 0x0e00022f, 0x00000000, 0x0a0005bb, 0x00000000,
-	0x8f620008, 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007,
-	0x28620031, 0x1440002f, 0x24020040, 0x10620007, 0x00000000, 0x0a0005bb,
-	0x00000000, 0x0e0002e8, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0003db,
-	0x00000000, 0x0a0005bb, 0x00000000, 0x30620040, 0x1440002b, 0x00000000,
-	0x0000000d, 0x00000000, 0x240004b2, 0x0a0005c6, 0x00000000, 0x1482000f,
-	0x30620006, 0x97420104, 0x10400005, 0x30620040, 0x0e000510, 0x00000000,
-	0x0a0005bb, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d, 0x00000000,
-	0x240004c4, 0x0a0005c6, 0x00000000, 0x1040000e, 0x30621000, 0x10400005,
-	0x00000000, 0x0e000688, 0x00000000, 0x0a0005bb, 0x00000000, 0x0e0004a1,
-	0x00000000, 0x8f82002c, 0x24420001, 0xaf82002c, 0x0a0005c6, 0x00000000,
-	0x30620040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000, 0x240004db,
-	0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a000566, 0x00000000,
-	0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000, 0x00621824,
-	0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c, 0x34420001,
-	0xaf420008, 0x37428000, 0xaf800018, 0xaf820010, 0xaf400080, 0xaf400084,
-	0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0,
-	0x38420010, 0x2c420001, 0xaf860000, 0xaf820004, 0x03e00008, 0x00000000,
-	0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8, 0x8f820018,
-	0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf82000c, 0xaf830018,
-	0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007,
-	0x3044fff8, 0x8f820030, 0x8f830000, 0x00442021, 0xaf82001c, 0x0083102b,
-	0xaf840030, 0x14400002, 0x00831023, 0xaf820030, 0x8f820030, 0x34038000,
-	0x00431821, 0x03432021, 0xaf840010, 0x03e00008, 0xaf420080, 0x8f830024,
-	0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005, 0x24020004,
-	0x10600012, 0x3c020001, 0x0a00062a, 0x00000000, 0x10620007, 0x24020006,
-	0x1462000f, 0x3c020111, 0x0a000622, 0x00821025, 0x0a000621, 0x3c020101,
-	0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830020, 0x0a00062a,
-	0x00000000, 0x00821025, 0xaf421000, 0xaf800020, 0x00000000, 0x00000000,
-	0x00000000, 0x03e00008, 0x00000000, 0x8f820020, 0x10400005, 0x3c038000,
-	0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008, 0x00000000,
-	0x8f820024, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010, 0x0e00022f,
-	0x00000000, 0x0a000656, 0x8fbf0010, 0x8f620008, 0x8f630000, 0x24020030,
-	0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d, 0x8fbf0010,
-	0x24020040, 0x10620007, 0x00000000, 0x0a000656, 0x00000000, 0x0e0002e8,
-	0x00000000, 0x0a000656, 0x8fbf0010, 0x0e0003db, 0x00000000, 0x8fbf0010,
-	0x03e00008, 0x27bd0018, 0x8f840028, 0x1080000f, 0x3c026000, 0x8c430c3c,
-	0x30630fff, 0xaf830008, 0x14600011, 0x3082000f, 0x10400005, 0x308200f0,
-	0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d, 0x00000000,
-	0x2400051a, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000, 0x2400051f,
-	0x03e00008, 0x00000000, 0xaf830028, 0x03e00008, 0x00000000, 0x10c00007,
-	0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb,
-	0x24840004, 0x03e00008, 0x00000000, 0x0a000684, 0x00a01021, 0xac860000,
-	0x00000000, 0x00000000, 0x24840004, 0x00a01021, 0x1440fffa, 0x24a5ffff,
-	0x03e00008, 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x00000000};
+static u8 bnx2_TPAT_b06FwText[] = {
+	0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68,
+	0x1c, 0xe7, 0x19, 0x7e, 0xe7, 0x77, 0x47, 0x62, 0x25, 0x8d, 0x93, 0x3d,
+	0xac, 0x5d, 0xa5, 0x99, 0x91, 0x46, 0x3f, 0x54, 0x26, 0x9e, 0x84, 0xa5,
+	0x56, 0x61, 0x20, 0xe3, 0x99, 0x95, 0x2c, 0x0c, 0x05, 0x07, 0x42, 0x08,
+	0xe4, 0xb2, 0x1d, 0x49, 0x36, 0x85, 0x1e, 0x5a, 0x9a, 0x43, 0xa0, 0x05,
+	0x0f, 0x33, 0xeb, 0x34, 0x87, 0xc5, 0xdb, 0xaa, 0xc5, 0xbe, 0x94, 0xd6,
+	0x95, 0xea, 0xe8, 0xb2, 0x68, 0xe2, 0x53, 0x0f, 0xc5, 0xd8, 0xb4, 0x54,
+	0xd0, 0x53, 0x7b, 0x0a, 0x85, 0x5c, 0x4c, 0x69, 0x20, 0x85, 0x12, 0x44,
+	0x0f, 0x21, 0xd4, 0xad, 0xa7, 0xcf, 0xfb, 0xcd, 0x8c, 0xbc, 0xbb, 0x95,
+	0x5b, 0x1f, 0x02, 0x15, 0xac, 0x66, 0xe6, 0xfb, 0xde, 0xf7, 0xfb, 0x79,
+	0x9f, 0xe7, 0x79, 0xbf, 0xf7, 0x6b, 0xca, 0x34, 0x49, 0xe5, 0xdf, 0x14,
+	0x7e, 0x6f, 0x7f, 0xe3, 0xdb, 0x6f, 0x7f, 0xf5, 0xa5, 0x57, 0x2c, 0xa2,
+	0x57, 0x5e, 0x92, 0x64, 0x5d, 0xa6, 0x2f, 0xe0, 0x4f, 0x21, 0x32, 0xab,
+	0xf1, 0xf9, 0x47, 0x86, 0xec, 0x75, 0xce, 0x04, 0x0e, 0x19, 0x8a, 0x77,
+	0x34, 0xbb, 0xe9, 0x10, 0xf9, 0x83, 0x15, 0x2b, 0xa4, 0x7f, 0xe5, 0x71,
+	0x43, 0x25, 0x6e, 0x7f, 0xc1, 0xfb, 0xe7, 0xb9, 0x7b, 0xe7, 0xed, 0xa3,
+	0xdb, 0x0a, 0x19, 0xa6, 0xd7, 0x31, 0xcc, 0x45, 0x32, 0x66, 0xe1, 0xf3,
+	0xd3, 0xa5, 0x75, 0x8d, 0xa6, 0xab, 0xb1, 0x4c, 0x4a, 0xfa, 0x06, 0xad,
+	0xf5, 0x30, 0x8e, 0xf3, 0x8e, 0x14, 0x66, 0xaa, 0x14, 0xde, 0x32, 0x48,
+	0xf6, 0x7c, 0x29, 0xc8, 0x1c, 0xf4, 0x49, 0x14, 0xb8, 0x35, 0xf2, 0xcd,
+	0x3c, 0xff, 0xa6, 0x2b, 0x93, 0xec, 0x3c, 0xce, 0xe7, 0x17, 0xd6, 0xa5,
+	0x60, 0x7f, 0x43, 0x0a, 0xf7, 0x03, 0xde, 0x37, 0xd6, 0xb1, 0x2e, 0xf9,
+	0xfb, 0xfc, 0xf4, 0x8c, 0xb0, 0x37, 0x4d, 0x9d, 0x06, 0xcd, 0xc8, 0x0e,
+	0xfb, 0x5a, 0x14, 0xba, 0x2b, 0x4d, 0x85, 0xe6, 0xf1, 0x9b, 0xa0, 0x6d,
+	0x97, 0xea, 0x81, 0x4b, 0xaa, 0xe2, 0xc8, 0x14, 0x36, 0x24, 0xfa, 0x65,
+	0x4b, 0xc3, 0xef, 0x92, 0xd4, 0xde, 0xdf, 0x2a, 0xc7, 0x69, 0x50, 0x8a,
+	0xb5, 0x44, 0x0d, 0x5e, 0x5b, 0xe1, 0x1f, 0xb8, 0x2b, 0xa6, 0x4c, 0xf3,
+	0xf8, 0x4d, 0xe1, 0x3d, 0x82, 0x9d, 0x46, 0x41, 0x6b, 0xbc, 0x6f, 0x02,
+	0xef, 0x58, 0x27, 0xc6, 0x0a, 0xc4, 0x3a, 0x2c, 0xac, 0xc3, 0xa1, 0x6e,
+	0x7f, 0x03, 0xfb, 0x58, 0x68, 0x46, 0xa4, 0x53, 0x57, 0xac, 0x7d, 0x8a,
+	0x12, 0x53, 0xa1, 0xe4, 0xac, 0x46, 0xfe, 0x65, 0x15, 0xdf, 0xcf, 0x51,
+	0x6c, 0x4a, 0xb0, 0xe9, 0x96, 0xf8, 0xd5, 0xd0, 0xaf, 0xa3, 0x7d, 0x86,
+	0x92, 0xc6, 0x29, 0x49, 0xf6, 0xbe, 0x8f, 0xf6, 0x05, 0x33, 0xa2, 0xef,
+	0xe1, 0x29, 0xe1, 0xfb, 0x14, 0x8f, 0x87, 0x6f, 0x89, 0x14, 0x87, 0xcc,
+	0x20, 0xb3, 0x28, 0xcd, 0x2a, 0x5f, 0x6e, 0x2f, 0xda, 0xe2, 0x6c, 0x1c,
+	0x3b, 0xd8, 0xf5, 0x5f, 0xa5, 0x8e, 0x49, 0xb1, 0xea, 0xc1, 0xa6, 0xef,
+	0x98, 0x6d, 0xe0, 0xe4, 0x0b, 0x3c, 0xbf, 0xc6, 0xed, 0xfc, 0x87, 0x76,
+	0x8b, 0x14, 0xcf, 0x31, 0x43, 0x6a, 0x51, 0xd1, 0xd7, 0x30, 0x83, 0x5b,
+	0x2f, 0x93, 0x2f, 0xe2, 0x61, 0xe0, 0xdd, 0xc4, 0x9e, 0x74, 0x60, 0x9b,
+	0xf8, 0x32, 0xc5, 0x4d, 0x83, 0xec, 0xd5, 0x2d, 0xf4, 0x7c, 0xdc, 0x53,
+	0x10, 0x67, 0xc6, 0x49, 0x2d, 0xfd, 0x18, 0xd7, 0xdf, 0x62, 0x5d, 0xb1,
+	0x69, 0xd0, 0x0c, 0x75, 0x5e, 0xcf, 0xf3, 0x3b, 0x6e, 0x9e, 0xeb, 0x9e,
+	0xb3, 0xfc, 0x3e, 0xad, 0x34, 0x35, 0x5a, 0x34, 0xf1, 0x44, 0xdc, 0x1c,
+	0xc4, 0x46, 0x2d, 0xe7, 0x9f, 0x2a, 0xd7, 0xfa, 0x48, 0x42, 0xe8, 0xe9,
+	0xcf, 0xbd, 0xdf, 0xf0, 0xde, 0x97, 0xd7, 0x85, 0x7d, 0x9e, 0xef, 0xae,
+	0x3e, 0xcd, 0x5e, 0x93, 0x0b, 0xfb, 0x3c, 0x5f, 0x6b, 0xf1, 0x7c, 0x36,
+	0xf6, 0xc6, 0x9c, 0x24, 0x5a, 0x1b, 0xb8, 0x46, 0xd4, 0xc3, 0xba, 0x1c,
+	0x3c, 0x07, 0x4d, 0xac, 0xdd, 0x5e, 0xb6, 0x24, 0x83, 0x12, 0x27, 0x7f,
+	0x11, 0x3c, 0xf0, 0x43, 0xc7, 0xfe, 0x53, 0xa8, 0xd4, 0x68, 0xcf, 0xad,
+	0x53, 0x37, 0x6b, 0x52, 0x92, 0x75, 0x29, 0xc8, 0x64, 0x8c, 0x5f, 0xa3,
+	0x5d, 0xe7, 0xf3, 0x7c, 0xcd, 0x75, 0x81, 0x33, 0xb1, 0x5f, 0x73, 0x8d,
+	0x66, 0xd1, 0xbf, 0x62, 0x6e, 0x91, 0x8b, 0x98, 0xcb, 0x88, 0xc9, 0xbc,
+	0x78, 0x4f, 0x32, 0x17, 0xfd, 0x14, 0xcb, 0x2d, 0xdb, 0x4c, 0xc8, 0x6e,
+	0x06, 0x0a, 0x99, 0xb2, 0x67, 0xc2, 0x26, 0xa6, 0x76, 0x66, 0xd0, 0x43,
+	0xe5, 0x1d, 0xc1, 0xe3, 0xb4, 0xff, 0x30, 0xbf, 0xb7, 0xd4, 0xa4, 0xfb,
+	0x59, 0x83, 0xee, 0x66, 0x24, 0x47, 0x1c, 0xab, 0x86, 0x49, 0x1f, 0x64,
+	0xd5, 0x3e, 0xc0, 0x65, 0x27, 0x39, 0xa3, 0x40, 0x67, 0x9b, 0xee, 0x03,
+	0xb0, 0xc4, 0x06, 0x0e, 0x31, 0xf6, 0x5c, 0x3d, 0x79, 0x4f, 0xb7, 0xcf,
+	0x6c, 0x3a, 0xf6, 0x7b, 0x21, 0xb3, 0xf3, 0x86, 0x8a, 0xd6, 0xe1, 0x38,
+	0x7c, 0x1d, 0xfe, 0x26, 0x5d, 0x87, 0x5e, 0x64, 0xc4, 0x63, 0xee, 0xc0,
+	0xa0, 0xfd, 0x5e, 0x8d, 0xac, 0x5d, 0x95, 0xa2, 0x7e, 0x83, 0xdc, 0x45,
+	0xdb, 0x22, 0x59, 0x6e, 0xc8, 0x88, 0xdf, 0xdc, 0x6e, 0x4e, 0xeb, 0xae,
+	0x46, 0x87, 0xce, 0x77, 0x75, 0x9a, 0x4e, 0x5c, 0x9d, 0xd8, 0xc6, 0xa0,
+	0xb9, 0xf7, 0x0d, 0x29, 0xec, 0xf3, 0xfa, 0x39, 0xce, 0x46, 0x19, 0x67,
+	0x55, 0x0a, 0x6e, 0xd5, 0x68, 0x7e, 0xe7, 0x6f, 0x79, 0xe0, 0x20, 0xc6,
+	0xe0, 0xf1, 0x66, 0xcb, 0x56, 0x68, 0x12, 0x6d, 0xbb, 0xdc, 0x77, 0x54,
+	0xb6, 0xf3, 0x18, 0x79, 0x1e, 0xb8, 0xcf, 0x53, 0xc0, 0xfc, 0x7e, 0x9d,
+	0x7d, 0x6a, 0x34, 0xb7, 0xc3, 0xba, 0xc0, 0x73, 0x97, 0xbf, 0x79, 0x6d,
+	0x13, 0x14, 0x61, 0x37, 0xd1, 0x72, 0x03, 0xfb, 0x97, 0x85, 0x06, 0x22,
+	0xec, 0x56, 0x76, 0x26, 0xf1, 0x14, 0x71, 0x50, 0x0a, 0x3e, 0x73, 0x5e,
+	0xa8, 0x53, 0x08, 0x5c, 0x55, 0xac, 0x67, 0x8b, 0x16, 0x9a, 0xdb, 0xa2,
+	0x0f, 0x6d, 0x03, 0xee, 0x33, 0xc7, 0xfa, 0xf0, 0x3d, 0xa8, 0xd6, 0x20,
+	0x03, 0xf3, 0x14, 0xb3, 0x68, 0x62, 0xaf, 0x6b, 0x2e, 0xdb, 0xb3, 0x6d,
+	0xbc, 0xac, 0x91, 0xbd, 0xbc, 0x8b, 0xd1, 0xf7, 0x7b, 0xd8, 0xef, 0x4d,
+	0xce, 0x35, 0x8e, 0xf5, 0x17, 0x62, 0xfb, 0x79, 0xec, 0x79, 0x61, 0x35,
+	0xe5, 0xbe, 0x81, 0x46, 0xce, 0x4e, 0x6c, 0xaa, 0x88, 0xbd, 0x8c, 0xc0,
+	0x87, 0x3f, 0xfc, 0x2c, 0xd7, 0x3c, 0x70, 0xb8, 0x35, 0x03, 0x6c, 0x6c,
+	0x2b, 0x85, 0x9e, 0x1d, 0x8c, 0x9b, 0xb8, 0x0a, 0xfc, 0x0a, 0x8c, 0xd8,
+	0x6e, 0xbd, 0x97, 0x53, 0x2a, 0xe6, 0xba, 0xc6, 0x73, 0x21, 0xe7, 0x38,
+	0xab, 0xbf, 0x03, 0x27, 0x22, 0xaa, 0xd3, 0xe2, 0x41, 0x9d, 0xae, 0x0e,
+	0xea, 0x34, 0x77, 0x43, 0x47, 0x1c, 0xf2, 0xbc, 0xdb, 0x62, 0x0d, 0x02,
+	0x6b, 0x87, 0xed, 0xec, 0xa6, 0x22, 0xf3, 0x3a, 0xd0, 0x7f, 0x40, 0xb4,
+	0x35, 0xd0, 0x11, 0x37, 0x75, 0x68, 0x6c, 0x99, 0x2e, 0xfe, 0x84, 0xe8,
+	0xe2, 0x80, 0x7d, 0x79, 0xfc, 0xc2, 0x27, 0xc2, 0x9e, 0x65, 0x60, 0x7e,
+	0x75, 0x20, 0x23, 0x1f, 0x20, 0x5f, 0xee, 0x07, 0xc8, 0x83, 0x6d, 0xfc,
+	0xd6, 0x91, 0x1b, 0x19, 0x1b, 0xce, 0x13, 0x8f, 0x81, 0xcf, 0x06, 0xfa,
+	0x2e, 0xa1, 0x8d, 0xf3, 0x16, 0xdb, 0xea, 0xd4, 0x76, 0xa7, 0x28, 0xad,
+	0x72, 0x91, 0xc9, 0xb9, 0xe8, 0x14, 0xf8, 0x34, 0x81, 0xfc, 0x72, 0x47,
+	0x19, 0xcd, 0x45, 0xc8, 0x59, 0x8d, 0xd3, 0xc8, 0x3d, 0x3f, 0x47, 0x3b,
+	0x8f, 0xf7, 0x33, 0x3c, 0x27, 0xf0, 0x7d, 0x1a, 0xb6, 0xc3, 0x79, 0xa8,
+	0xf2, 0x7b, 0x5a, 0x0e, 0x02, 0xef, 0x76, 0x0c, 0xd8, 0x5b, 0xd0, 0x0b,
+	0xc7, 0xbb, 0x86, 0x7c, 0xc1, 0x31, 0xaf, 0x21, 0xa6, 0x3a, 0xe6, 0x36,
+	0x69, 0xfe, 0x80, 0x62, 0xa5, 0xcc, 0x4f, 0xe1, 0x71, 0x7e, 0x6a, 0x0a,
+	0x1e, 0x24, 0x99, 0x09, 0x1f, 0xd6, 0x6d, 0xa5, 0x53, 0xc6, 0x8e, 0xfc,
+	0x00, 0x1a, 0x0e, 0x94, 0x3c, 0xdf, 0xc4, 0x19, 0x11, 0x01, 0x77, 0x1f,
+	0xda, 0x8d, 0xa0, 0xdd, 0x70, 0x48, 0xbb, 0xe1, 0xff, 0xd4, 0x2e, 0x74,
+	0x09, 0x8d, 0xdc, 0x05, 0xa7, 0x3e, 0xe8, 0x9f, 0xa4, 0x63, 0xd6, 0x30,
+	0x6b, 0xd9, 0xa2, 0x7b, 0x4b, 0xcf, 0xa2, 0xe5, 0xbf, 0x3e, 0xab, 0x96,
+	0x63, 0xd6, 0xb2, 0xca, 0x5a, 0x6e, 0x0c, 0x6b, 0xf9, 0x53, 0xf8, 0x17,
+	0x9a, 0xbc, 0xa0, 0x36, 0x48, 0x5b, 0x04, 0x0e, 0x3b, 0x75, 0x52, 0x6e,
+	0x3c, 0xe1, 0x1b, 0x73, 0x38, 0x1c, 0xe0, 0xdf, 0x81, 0x86, 0x3e, 0x69,
+	0xb4, 0x1d, 0x39, 0x4f, 0xf5, 0xec, 0xe6, 0x96, 0xb0, 0x51, 0x49, 0x47,
+	0xdc, 0xbf, 0xb3, 0x64, 0x5b, 0x96, 0x3c, 0xac, 0x79, 0xa8, 0x7e, 0x27,
+	0xbf, 0xa6, 0x79, 0x3c, 0x4f, 0x6c, 0x81, 0xeb, 0xd6, 0x8f, 0x80, 0x51,
+	0xda, 0x63, 0x9e, 0x3b, 0xe6, 0x9a, 0xe0, 0x17, 0xbe, 0xa1, 0x05, 0x0d,
+	0x7c, 0xad, 0xc1, 0x4e, 0xdd, 0x29, 0xf4, 0x73, 0x17, 0xe3, 0xee, 0xf5,
+	0x98, 0x5f, 0x06, 0xe9, 0x37, 0x9d, 0xe6, 0x55, 0x91, 0x73, 0xe7, 0xcd,
+	0x75, 0x62, 0xed, 0xf1, 0x79, 0x87, 0xfe, 0x41, 0x8d, 0x14, 0xa1, 0xf7,
+	0xc9, 0x52, 0xef, 0x2f, 0x20, 0x46, 0x93, 0xf8, 0x66, 0xcd, 0x9f, 0x2e,
+	0x35, 0x3f, 0x8d, 0x27, 0xb7, 0x5d, 0x54, 0x0b, 0xee, 0x80, 0x87, 0x3b,
+	0x8c, 0x6b, 0x1d, 0xf9, 0x8d, 0xe7, 0xff, 0x7b, 0xbe, 0xe9, 0x30, 0xb6,
+	0x8e, 0xf5, 0x03, 0x5a, 0x80, 0xee, 0xd0, 0x7e, 0xc0, 0xb6, 0xec, 0x53,
+	0xd9, 0x9a, 0xa5, 0xed, 0xa7, 0x63, 0xb6, 0x68, 0x3f, 0x60, 0x3b, 0xd6,
+	0xc5, 0x73, 0xa4, 0xdc, 0xe4, 0xf3, 0x38, 0x60, 0x5d, 0xc0, 0xaf, 0x8d,
+	0x36, 0xae, 0x19, 0xd8, 0x9f, 0xcf, 0x66, 0x5e, 0x27, 0xd7, 0x13, 0x7c,
+	0x7e, 0x8f, 0x9d, 0xd3, 0xc7, 0xda, 0xb8, 0x00, 0xbe, 0x7f, 0x4b, 0xfd,
+	0x4f, 0x6d, 0xbc, 0x06, 0x2d, 0x5c, 0x51, 0x0b, 0x6d, 0x6c, 0xe3, 0x79,
+	0x01, 0xdf, 0xaf, 0x8d, 0x69, 0xa3, 0xf2, 0x7b, 0xfa, 0xf9, 0x9c, 0xf4,
+	0x9b, 0xe2, 0x6c, 0xe5, 0xf9, 0x94, 0x1d, 0x8a, 0xb5, 0x52, 0x07, 0x6b,
+	0xc7, 0x3a, 0x98, 0x44, 0xae, 0x18, 0xe1, 0xb8, 0x12, 0xba, 0xb6, 0x99,
+	0x12, 0x6b, 0x62, 0xf8, 0xfc, 0xfa, 0x7f, 0xe9, 0x82, 0xc0, 0x23, 0x31,
+	0x37, 0x6a, 0x0c, 0x3e, 0x0f, 0xf2, 0xfc, 0x8a, 0x8b, 0xfe, 0xaa, 0xd6,
+	0x10, 0xd8, 0xf3, 0x59, 0xcb, 0x78, 0xa0, 0xbe, 0x73, 0xe6, 0xa1, 0x05,
+	0xce, 0x01, 0x8f, 0xf3, 0x3d, 0x27, 0x40, 0x5b, 0x1b, 0xf1, 0x67, 0x4c,
+	0x36, 0xa4, 0xf5, 0x7d, 0x83, 0xfd, 0xa0, 0xb3, 0x93, 0x6a, 0x2c, 0x1d,
+	0x9a, 0x7a, 0x82, 0x13, 0xf3, 0x28, 0x1a, 0xc2, 0xa9, 0x23, 0x70, 0xfa,
+	0xf0, 0x18, 0xa7, 0xa8, 0xc4, 0x29, 0x12, 0x38, 0xfd, 0xb1, 0xc4, 0xe9,
+	0x0f, 0x4f, 0xc1, 0xe9, 0xc3, 0x67, 0xc0, 0xc9, 0xa0, 0x3d, 0xa7, 0x89,
+	0x73, 0x56, 0x17, 0x35, 0xe9, 0xa1, 0x7b, 0x52, 0x4d, 0x75, 0x52, 0xdc,
+	0x6d, 0x73, 0x8f, 0x86, 0xeb, 0x0e, 0xdb, 0x7a, 0x80, 0xf5, 0xa5, 0xc0,
+	0xee, 0xfa, 0x58, 0xed, 0x91, 0xc0, 0xbe, 0x5d, 0xe2, 0x74, 0x1d, 0x38,
+	0xb5, 0x4b, 0x9c, 0xb6, 0x87, 0x70, 0xda, 0x1e, 0xc1, 0x89, 0xf3, 0x49,
+	0xcb, 0xd8, 0xee, 0x55, 0x18, 0x55, 0xf8, 0xe8, 0x74, 0xdb, 0x9c, 0xc6,
+	0xfe, 0xcf, 0x51, 0xfa, 0x63, 0x95, 0xeb, 0x5a, 0x60, 0xf7, 0xaa, 0x2a,
+	0x8b, 0xf3, 0x80, 0xdf, 0x9f, 0xd4, 0x27, 0x98, 0xcb, 0x0f, 0x5c, 0x8e,
+	0x23, 0xea, 0x57, 0xa7, 0xca, 0x43, 0xcf, 0xab, 0xa8, 0xad, 0xf0, 0xcd,
+	0x36, 0xaa, 0xd4, 0x86, 0xde, 0x15, 0xd4, 0xe5, 0xe1, 0x71, 0x5d, 0x5e,
+	0xc4, 0xe0, 0x7a, 0x59, 0x97, 0xef, 0x39, 0x5c, 0x97, 0x2f, 0x6a, 0x34,
+	0xb9, 0x51, 0x62, 0xc9, 0x9c, 0x9e, 0x42, 0xdf, 0x25, 0x81, 0x79, 0x8a,
+	0xfc, 0xbd, 0x89, 0xfd, 0x47, 0x82, 0x9b, 0xa8, 0xb1, 0x4a, 0xde, 0xa2,
+	0x86, 0xa5, 0x30, 0x2b, 0x62, 0xf5, 0xc5, 0xd6, 0x5d, 0x9f, 0x20, 0x4f,
+	0x1b, 0x1d, 0x15, 0x75, 0xfd, 0xfd, 0x8c, 0xf3, 0x33, 0x5d, 0x4e, 0x7a,
+	0x14, 0x9f, 0xf1, 0xae, 0xe5, 0xc0, 0xdc, 0x7f, 0xeb, 0x3c, 0x9f, 0x33,
+	0xf5, 0xd5, 0xa0, 0x85, 0xf6, 0x81, 0x41, 0xa8, 0x7d, 0x70, 0x4f, 0xa1,
+	0x38, 0x38, 0x2f, 0xa1, 0xc6, 0xc1, 0x37, 0x7c, 0x92, 0x6c, 0xb6, 0x23,
+	0x7b, 0x4d, 0x70, 0x21, 0x26, 0x1f, 0xeb, 0xf4, 0x33, 0x71, 0x57, 0xe9,
+	0x28, 0x9e, 0x81, 0xda, 0x92, 0x0c, 0x9c, 0xf3, 0x88, 0x89, 0x65, 0xa4,
+	0x03, 0xd4, 0x41, 0x38, 0xfb, 0x83, 0x55, 0xc4, 0xe5, 0x2c, 0x70, 0xcb,
+	0x54, 0xf8, 0xbe, 0xa9, 0x17, 0xf7, 0x1c, 0x54, 0x35, 0x22, 0x5e, 0x8f,
+	0x4a, 0x7e, 0x88, 0x3a, 0x4b, 0x6a, 0xf7, 0xc9, 0x8a, 0x5c, 0xf0, 0x1c,
+	0xe7, 0x48, 0x37, 0xe3, 0xda, 0xf9, 0xac, 0x21, 0xdf, 0xe0, 0x5c, 0x7e,
+	0x88, 0x18, 0xe2, 0xfd, 0x80, 0xcf, 0x16, 0x85, 0xeb, 0x6f, 0xdc, 0x67,
+	0x96, 0x90, 0x6b, 0x68, 0x0a, 0x79, 0x0f, 0x79, 0x77, 0x96, 0x71, 0xf2,
+	0x23, 0xc6, 0x4b, 0x9c, 0x1b, 0xe7, 0xe4, 0x62, 0x9e, 0x5f, 0x6b, 0x05,
+	0x7f, 0x71, 0x87, 0x41, 0xfc, 0x36, 0xfb, 0x2e, 0xe7, 0xdb, 0x2f, 0x2b,
+	0x74, 0x44, 0x82, 0x8f, 0xe6, 0xcb, 0xc8, 0xc3, 0xe7, 0xe0, 0xe3, 0x0b,
+	0x2d, 0x16, 0xf5, 0x56, 0xe5, 0xf3, 0xc9, 0xd8, 0x18, 0x1f, 0x29, 0xa3,
+	0xdf, 0x3e, 0xf8, 0xbc, 0x52, 0xce, 0x57, 0xf1, 0xe3, 0x57, 0xe0, 0xc7,
+	0x61, 0xd9, 0xcf, 0x77, 0x16, 0x1d, 0x36, 0xbc, 0x3e, 0xe6, 0x11, 0xdb,
+	0x9b, 0xda, 0xe8, 0x18, 0x5f, 0x1a, 0xf3, 0xff, 0xfd, 0x90, 0xff, 0x34,
+	0xef, 0xc9, 0x8c, 0x0a, 0x0e, 0xe2, 0xef, 0x3d, 0x7d, 0xd4, 0xf7, 0x17,
+	0x6a, 0xf1, 0x7d, 0xb6, 0xe0, 0x9e, 0x83, 0x67, 0x76, 0x38, 0xb4, 0x36,
+	0x75, 0x6c, 0xec, 0x87, 0x18, 0x7b, 0x15, 0x79, 0x84, 0x7c, 0x05, 0x77,
+	0xa6, 0x90, 0xf0, 0x9e, 0x5d, 0xa9, 0xe2, 0x03, 0x4e, 0xd0, 0xe5, 0xb4,
+	0xe4, 0x82, 0x5c, 0x70, 0x81, 0xeb, 0xb4, 0xd5, 0x4d, 0x70, 0x21, 0x05,
+	0x17, 0xe0, 0xd7, 0xd1, 0xbc, 0x59, 0xe0, 0xcc, 0x39, 0x07, 0xdf, 0x19,
+	0xf3, 0x82, 0x79, 0xc0, 0x9c, 0x78, 0xc2, 0x85, 0x2b, 0x3d, 0xc3, 0xd8,
+	0xfd, 0x2f, 0x3c, 0x78, 0x57, 0xf0, 0x80, 0xf9, 0x58, 0xe4, 0x85, 0x2e,
+	0x70, 0x48, 0xca, 0xbc, 0x50, 0xe8, 0x9c, 0xeb, 0x1b, 0xd6, 0x78, 0xa1,
+	0x8d, 0x2d, 0x68, 0xa3, 0xad, 0x70, 0xbd, 0xc3, 0xba, 0x60, 0x3f, 0xd6,
+	0xc6, 0x49, 0x7e, 0x85, 0x46, 0xd2, 0xbe, 0x6d, 0x55, 0xf9, 0x21, 0x85,
+	0x2e, 0xba, 0xa5, 0x46, 0xd2, 0x52, 0x23, 0xb0, 0x89, 0x95, 0x16, 0xe7,
+	0x7a, 0xdb, 0x0a, 0x91, 0x17, 0xba, 0x62, 0xcc, 0x98, 0x8a, 0x3b, 0x09,
+	0xeb, 0x96, 0xf3, 0xe9, 0x50, 0x1e, 0x2d, 0xef, 0xa5, 0x1d, 0x71, 0x2f,
+	0xfd, 0x8a, 0x3e, 0x9a, 0x47, 0x67, 0x90, 0x43, 0xf8, 0x5e, 0x3a, 0xa7,
+	0xf3, 0xbd, 0x14, 0xba, 0xd3, 0x87, 0xef, 0xa5, 0xc9, 0xc8, 0xbd, 0xb4,
+	0xf2, 0xe5, 0xf6, 0x93, 0xf2, 0x69, 0x15, 0x13, 0xce, 0xa9, 0x02, 0xf3,
+	0x13, 0x6a, 0xbf, 0xca, 0x86, 0xf3, 0x0d, 0x6b, 0xb9, 0xcc, 0x51, 0xa8,
+	0xb5, 0xee, 0x67, 0x15, 0xe7, 0xdf, 0xc0, 0x3c, 0xf8, 0xee, 0x9f, 0xc4,
+	0x79, 0xa3, 0xe4, 0xfc, 0x54, 0xe1, 0xd3, 0x1f, 0xe6, 0xfd, 0x1b, 0xfa,
+	0x28, 0xef, 0xab, 0x71, 0x2a, 0xde, 0x17, 0x63, 0x3e, 0x54, 0x9a, 0x38,
+	0xdb, 0x96, 0x91, 0x6b, 0x66, 0xf8, 0xbe, 0x85, 0x5c, 0xe0, 0xd5, 0x71,
+	0xef, 0x98, 0xe1, 0xb1, 0xd3, 0x0c, 0xe7, 0x4d, 0x03, 0xbc, 0x17, 0x9c,
+	0x3d, 0x12, 0xf7, 0x01, 0xac, 0x7b, 0x86, 0xab, 0xab, 0x51, 0x2e, 0xbe,
+	0x88, 0x0b, 0x45, 0xb5, 0x97, 0xaa, 0xcd, 0x19, 0x6a, 0x5b, 0x2e, 0xb1,
+	0x2e, 0x62, 0xfd, 0xa0, 0xb8, 0x8f, 0xd3, 0x2e, 0x6a, 0xb1, 0x43, 0xd4,
+	0x39, 0x77, 0x70, 0x9f, 0x4b, 0x06, 0x8f, 0xf2, 0x07, 0x0d, 0x95, 0xba,
+	0xc7, 0x3e, 0x5d, 0xac, 0xd7, 0x36, 0x6f, 0xe3, 0xed, 0xdd, 0x41, 0x15,
+	0x53, 0xee, 0xe7, 0xb6, 0x7f, 0xe0, 0xbc, 0x45, 0x1d, 0x37, 0x32, 0x67,
+	0xf5, 0xce, 0x7f, 0xff, 0x06, 0x63, 0xe1, 0x4b, 0x7b, 0x30, 0x12, 0x00,
+	0x00, 0x00 };
 
 static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 };
@@ -2554,939 +1543,422 @@
 static const int bnx2_TXP_b06FwBssLen = 0x1c4;
 static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760;
 static const int bnx2_TXP_b06FwSbssLen = 0x38;
-static u32 bnx2_TXP_b06FwText[(0x5748/4) + 1] = {
-	0x0a000d2c, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x322e352e,
-	0x38000000, 0x02050800, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800,
-	0x24425760, 0x3c030800, 0x24635964, 0xac400000, 0x0043202b, 0x1480fffd,
-	0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021, 0x3c100800, 0x261034b0,
-	0x3c1c0800, 0x279c5760, 0x0e000f5b, 0x00000000, 0x0000000d, 0x8f840014,
-	0x27bdffe8, 0xafb10014, 0xafb00010, 0x8f460104, 0x8f830008, 0x8c8500ac,
-	0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12, 0x8c8200ac,
-	0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0x00008021, 0xa7420e16,
-	0x8f430e18, 0x00006021, 0x00c53023, 0xaf430e1c, 0x10c001a2, 0x2d820001,
-	0x3c0e1000, 0x2419fff8, 0x24110010, 0x240f0f00, 0x3c188100, 0x93620008,
-	0x10400009, 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000,
-	0x97620010, 0x3042ffff, 0x0a000d6d, 0xaf420e00, 0xaf460e00, 0x8f420000,
-	0x30420008, 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff,
-	0x30820001, 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a000f34,
-	0x00000000, 0x0000000d, 0x3083a040, 0x24020040, 0x1462004f, 0x3082a000,
-	0x308a0036, 0x8f88000c, 0x30890008, 0x24020800, 0xaf420178, 0x01001821,
-	0x9742008a, 0x00431023, 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa,
-	0x00a06021, 0x8f820018, 0x00cc3023, 0x24070001, 0x8f830008, 0x304b00ff,
-	0x24420001, 0xaf820018, 0x25024000, 0x106f0005, 0x03422021, 0x93820012,
-	0x30420007, 0x00021240, 0x34470001, 0x000b1400, 0x3c030100, 0x00431025,
-	0xac820000, 0x8f830018, 0x00ea3825, 0x1120000f, 0xac830004, 0x97430e0a,
-	0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825, 0xaf430160, 0x25830006,
-	0x24840008, 0x30841fff, 0xa742015a, 0xa7430158, 0xaf84000c, 0x0a000db7,
-	0x00000000, 0x8f83000c, 0x25820002, 0xa7420158, 0x24630008, 0x30631fff,
-	0xaf83000c, 0x54c0000f, 0x8f420e14, 0x8f820008, 0x504f0002, 0x24100001,
-	0x34e70040, 0x97420e10, 0x97430e12, 0x8f850014, 0x00021400, 0x00621825,
-	0xaca300a8, 0x8f840014, 0x8f420e18, 0xac8200ac, 0x8f420e14, 0x8f430e1c,
-	0xaf420144, 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a000efb, 0xaf4e0178,
-	0x10400165, 0x00000000, 0x93620008, 0x50400008, 0xafa60008, 0x97620010,
-	0x00a2102b, 0x10400003, 0x30820040, 0x1040015c, 0x00000000, 0xafa60008,
-	0xa7840010, 0xaf850004, 0x93620008, 0x1440005f, 0x27ac0008, 0xaf60000c,
-	0x97820010, 0x30424000, 0x10400002, 0x2403000e, 0x24030016, 0xa363000a,
-	0x24034007, 0xaf630014, 0x93820012, 0x8f630014, 0x30420007, 0x00021240,
-	0x00621825, 0xaf630014, 0x97820010, 0x8f630014, 0x30420010, 0x00621825,
-	0xaf630014, 0x97820010, 0x30420008, 0x5040000e, 0x00002821, 0x8f620014,
-	0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e, 0x00781825, 0xaf630004,
-	0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004, 0x0a000e06, 0xa363000a,
-	0xaf600004, 0xa3600002, 0x97820010, 0x9363000a, 0x30421f00, 0x00021182,
-	0x24420028, 0x00621821, 0xa3630009, 0x97420e0c, 0xa7620010, 0x93630009,
-	0x24020008, 0x24630002, 0x30630007, 0x00431023, 0x30420007, 0xa362000b,
-	0x93640009, 0x97620010, 0x8f890004, 0x97830010, 0x00441021, 0x00a21021,
-	0x30630040, 0x10600007, 0x3045ffff, 0x00a9102b, 0x14400005, 0x0125102b,
-	0x3c068000, 0x0a000e3a, 0x00005821, 0x0125102b, 0x544000c7, 0x00006021,
-	0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c, 0xaf420e18,
-	0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000, 0x97420e08,
-	0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001, 0xaf830004,
-	0x97620010, 0x0a000e4c, 0x304dffff, 0x8f890004, 0x97820010, 0x30420040,
-	0x10400004, 0x01206821, 0x3c068000, 0x0a000e4c, 0x00005821, 0x97630010,
-	0x8f820004, 0x10430003, 0x00003021, 0x0a000eee, 0x00006021, 0x240b0001,
-	0x8d820000, 0x00491023, 0x1440000d, 0xad820000, 0x8f620014, 0x34420040,
-	0xaf620014, 0x97430e10, 0x97420e12, 0x8f840014, 0x00031c00, 0x00431025,
-	0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003e,
-	0x00000000, 0x25260002, 0x8f84000c, 0x9743008a, 0x3063ffff, 0xafa30000,
-	0x8fa20000, 0x00441023, 0x2442ffff, 0x30421fff, 0x2c420010, 0x1440fff7,
-	0x00000000, 0x8f82000c, 0x8f830018, 0x00021082, 0x00021080, 0x24424000,
-	0x03422821, 0x00605021, 0x24630001, 0x314200ff, 0x00021400, 0xaf830018,
-	0x3c033200, 0x00431025, 0xaca20000, 0x93630009, 0x9362000a, 0x00031c00,
-	0x00431025, 0xaca20004, 0x8f830018, 0xaca30008, 0x97820010, 0x30420008,
-	0x10400002, 0x00c04021, 0x25280006, 0x97430e14, 0x93640002, 0x8f450e1c,
-	0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0xa7420146,
-	0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a, 0xaf460160,
-	0xa7480158, 0xaf470154, 0xaf4e0178, 0x00511021, 0x30421fff, 0xaf82000c,
-	0x0a000ed9, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c, 0x2463000a,
-	0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff, 0xafa30000,
-	0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b, 0x1440fff7,
-	0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080, 0x24424000,
-	0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009, 0x310200ff,
-	0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025, 0xaca40000,
-	0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002, 0x8f450e1c,
-	0x8f660004, 0x8f670014, 0x3063ffff, 0xa7430144, 0x97420e16, 0x308400ff,
-	0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c, 0x25420007, 0x00591024,
-	0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154, 0xaf4e0178, 0x00621821,
-	0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005, 0x00000000, 0x8f620014,
-	0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c, 0x004d1021, 0xaf62000c,
-	0x93630008, 0x14600008, 0x00000000, 0x11600006, 0x00000000, 0x8f630014,
-	0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014, 0xa36b0008, 0x01206021,
-	0x1580000c, 0x8fa60008, 0x97420e14, 0x97430e16, 0x8f850014, 0x00021400,
-	0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c, 0xac8200ac, 0x0a000efd,
-	0x2d820001, 0x14c0fe65, 0x2d820001, 0x00501025, 0x10400058, 0x24020f00,
-	0x8f830008, 0x14620023, 0x3c048000, 0x11800009, 0x3c038000, 0x97420e08,
-	0x30420040, 0x14400005, 0x00000000, 0x0000000d, 0x00000000, 0x2400032c,
-	0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97420e10,
-	0x3c030500, 0x00431025, 0xaf42014c, 0x97430e14, 0xa7430144, 0x97420e16,
-	0xa7420146, 0x8f430e1c, 0x24022000, 0xaf430148, 0x3c031000, 0xa3400152,
-	0xa740015a, 0xaf400160, 0xa7400158, 0xaf420154, 0xaf430178, 0x8f830008,
-	0x3c048000, 0x8f420178, 0x00441024, 0x1440fffd, 0x24020f00, 0x10620016,
-	0x00000000, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c,
-	0x3c031000, 0xaf420148, 0x0a000f51, 0x24020240, 0x97420e14, 0x97430e16,
-	0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c,
-	0x00006021, 0xaca200ac, 0x0a000efd, 0x2d820001, 0xaf40014c, 0x11800007,
-	0x00000000, 0x97420e10, 0xa7420144, 0x97430e12, 0xa7430146, 0x0a000f4e,
-	0x8f420e18, 0x97420e14, 0xa7420144, 0x97430e16, 0xa7430146, 0x8f420e1c,
-	0xaf420148, 0x24020040, 0x3c031000, 0xa3400152, 0xa740015a, 0xaf400160,
-	0xa7400158, 0xaf420154, 0xaf430178, 0x8fb10014, 0x8fb00010, 0x03e00008,
-	0x27bd0018, 0x27bdffd0, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008,
-	0x03421821, 0xafbf002c, 0xafb60028, 0xafb50024, 0xafb40020, 0xafb3001c,
-	0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014, 0xaf440e00, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd,
-	0x3c046004, 0xaf420e00, 0x8c835000, 0x24160800, 0x24150d00, 0x3c140800,
-	0x24130f00, 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c,
-	0x24020009, 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e001559,
-	0x00000000, 0x0e000ff0, 0x00000000, 0x3c020800, 0x245057c0, 0x8f420000,
-	0x30420001, 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020,
-	0xaf560178, 0x93430108, 0xa3830012, 0x93820012, 0x30420001, 0x10400008,
-	0x00000000, 0x93820012, 0x30420006, 0x00021100, 0x0e000d43, 0x0050d821,
-	0x0a000fac, 0x00000000, 0x14950005, 0x00000000, 0x0e000d43, 0x269b5840,
-	0x0a000fac, 0x00000000, 0x14930005, 0x00000000, 0x0e000d43, 0x265b5860,
-	0x0a000fac, 0x00000000, 0x0e0010ea, 0x00000000, 0xaf510138, 0x0a000f89,
-	0x00000000, 0x27bdfff8, 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c,
-	0x9743008a, 0x3063ffff, 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff,
-	0x30421fff, 0x0044102b, 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082,
-	0x00021080, 0x24424000, 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff,
-	0x8f82000c, 0x24840007, 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c,
-	0x03e00008, 0x00000000, 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd,
-	0x3c020008, 0x03421821, 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd,
-	0x3c046004, 0xaf420e00, 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c,
-	0x24030009, 0xac825000, 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e001559,
-	0x00000000, 0x0e000ff0, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018,
-	0x27bdffe8, 0x3c02000a, 0x03421821, 0x3c040800, 0x24845880, 0x24050019,
-	0xafbf0010, 0xaf830024, 0x0e001565, 0x00003021, 0x3c050800, 0x3c020800,
-	0x24425330, 0xaca258e8, 0x24a558e8, 0x3c020800, 0x244254f8, 0x3c030800,
-	0x2463550c, 0x3c040800, 0xaca20004, 0x3c020800, 0x24425338, 0xaca30008,
-	0xac825900, 0x24845900, 0x3c020800, 0x244253c4, 0x3c070800, 0x24e75404,
-	0x3c060800, 0x24c65520, 0x3c050800, 0x24a55438, 0x3c030800, 0xac820004,
-	0x3c020800, 0x24425528, 0xac870008, 0xac86000c, 0xac850010, 0xac625920,
-	0x24635920, 0x8fbf0010, 0x3c020800, 0x24425540, 0xac620004, 0x3c020800,
-	0xac670008, 0xac66000c, 0xac650010, 0xac400048, 0x03e00008, 0x27bd0018,
-	0x974309da, 0x00804021, 0xad030000, 0x8f4209dc, 0xad020004, 0x8f4309e0,
-	0xad030008, 0x934409d9, 0x24020001, 0x30840003, 0x1082001f, 0x30a900ff,
-	0x28820002, 0x10400005, 0x24020002, 0x10800009, 0x3c0a0800, 0x0a001078,
-	0x93420934, 0x1082000b, 0x24020003, 0x10820026, 0x3c0a0800, 0x0a001078,
-	0x93420934, 0x974209e4, 0x00021400, 0x34420800, 0xad02000c, 0x0a001077,
-	0x25080010, 0x974209e4, 0x00021400, 0x34428100, 0xad02000c, 0x974309e8,
-	0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010, 0x0a001077, 0x25080014,
-	0x974409e4, 0x3c050800, 0x24a25880, 0x9443001c, 0x94460014, 0x94470010,
-	0x00a05021, 0x24020800, 0xad000010, 0xad020014, 0x00042400, 0x00661821,
-	0x00671823, 0x2463fff2, 0x00832025, 0xad04000c, 0x0a001077, 0x25080018,
-	0x974209e4, 0x3c050800, 0x00021400, 0x34428100, 0xad02000c, 0x974409e8,
-	0x24a25880, 0x9443001c, 0x94460014, 0x94470010, 0x00a05021, 0x24020800,
-	0xad000014, 0xad020018, 0x00042400, 0x00661821, 0x00671823, 0x2463ffee,
-	0x00832025, 0xad040010, 0x2508001c, 0x93420934, 0x93450921, 0x3c074000,
-	0x25445880, 0x94830018, 0x94860014, 0x00021082, 0x00021600, 0x00052c00,
-	0x00a72825, 0x00451025, 0x00661821, 0x00431025, 0xad020000, 0x9783002c,
-	0x974209ea, 0x00621821, 0x00031c00, 0xad030004, 0x9782002c, 0x24420001,
-	0x30427fff, 0xa782002c, 0x93430920, 0x3c020006, 0x00031e00, 0x00621825,
-	0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930, 0xad030010, 0x8f440938,
-	0x25080014, 0xad040000, 0x8f820020, 0x11200004, 0xad020004, 0x8f420940,
-	0x0a0010a1, 0x2442ffff, 0x8f420940, 0xad020008, 0x8f440948, 0x8f420940,
-	0x93430936, 0x00823023, 0x00663006, 0x3402ffff, 0x0046102b, 0x54400001,
-	0x3406ffff, 0x93420937, 0x25445880, 0x90830024, 0xad000010, 0x00021700,
-	0x34630010, 0x00031c00, 0x00431025, 0x00461025, 0xad02000c, 0x8c830008,
-	0x14600031, 0x25080014, 0x3c020800, 0x8c430048, 0x1060002d, 0x00000000,
-	0x9342010b, 0xad020000, 0x8f830000, 0x8c6200b0, 0xad020004, 0x8f830000,
-	0x8c6200b4, 0xad020008, 0x8f830000, 0x8c6200c0, 0xad02000c, 0x8f830000,
-	0x8c6200c4, 0xad020010, 0x8f830000, 0x8c6200c8, 0xad020014, 0x8f830000,
-	0x8c6200cc, 0xad020018, 0x8f830000, 0x8c6200e0, 0xad02001c, 0x8f830000,
-	0x8c6200e8, 0xad020020, 0x8f830000, 0x8c6200f0, 0x3c04600e, 0xad020024,
-	0x8c8200d0, 0xad020028, 0x8c8300d4, 0xad03002c, 0x8f820028, 0x3c046012,
-	0xad020030, 0x8c8200a8, 0xad020034, 0x8c8300ac, 0x3c026000, 0xad030038,
-	0x8c434448, 0xad03003c, 0x03e00008, 0x01001021, 0x27bdffa8, 0x3c020008,
-	0x03423021, 0xafbf0054, 0xafbe0050, 0xafb7004c, 0xafb60048, 0xafb50044,
-	0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034, 0xafb00030, 0xaf860000,
-	0x24020040, 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954,
-	0x8f45095c, 0xaf820034, 0xaf830020, 0xaf84001c, 0xaf850030, 0x90c20000,
-	0x24030020, 0x304400ff, 0x10830005, 0x24020030, 0x10820022, 0x3c030800,
-	0x0a001139, 0x8c62002c, 0x24020088, 0xaf420818, 0x3c020800, 0x244258e8,
-	0xafa20020, 0x93430109, 0x3c020800, 0x10600009, 0x24575900, 0x3c026000,
-	0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000,
-	0x24000376, 0x9342010a, 0x30420080, 0x14400021, 0x24020800, 0x3c026000,
-	0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000,
-	0x2400037d, 0x0a001141, 0x24020800, 0x93430109, 0x3063007f, 0x00031140,
-	0x000318c0, 0x00431021, 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800,
-	0x24425940, 0x3c030800, 0x24775950, 0x0a001140, 0xafa20020, 0x24420001,
-	0xac62002c, 0x0000000d, 0x00000000, 0x24000395, 0x0a0014c1, 0x8fbf0054,
-	0x24020800, 0xaf420178, 0x8f450104, 0x8f420988, 0x00a21023, 0x58400005,
-	0x8f4309a0, 0x0000000d, 0x00000000, 0x240003b1, 0x8f4309a0, 0x3c100800,
-	0xae0358b0, 0x8f4209a4, 0x8f830020, 0x260458b0, 0x2491ffd0, 0xae220034,
-	0x00a21023, 0xae230028, 0xac82ffd0, 0x8fa30020, 0x8c620000, 0x0040f809,
-	0x0200b021, 0x00409021, 0x32440010, 0x32420002, 0x10400007, 0xafa40024,
-	0x8e220020, 0x32530040, 0x2403ffbf, 0x00431024, 0x0a001493, 0xae220020,
-	0x32420020, 0x10400002, 0x3c020800, 0x24575920, 0x32420001, 0x14400007,
-	0x00000000, 0x8f820008, 0xaf420080, 0x8ec358b0, 0xaf430e10, 0x8e220034,
-	0xaf420e18, 0x9343010b, 0x93420905, 0x30420008, 0x1040003c, 0x307400ff,
-	0x8f820000, 0x8c430074, 0x0460000a, 0x00000000, 0x3c026000, 0x24030100,
-	0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003ed,
-	0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32530040, 0x00003821,
-	0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd,
-	0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100,
-	0xaf420148, 0x24020047, 0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000,
-	0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001, 0xad230030,
-	0x9342010a, 0x3c030047, 0xafa50014, 0x00021600, 0x00431025, 0x00471025,
-	0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b,
-	0x3c070100, 0x3c050800, 0x24a25880, 0x0a001250, 0x8c430020, 0x32820002,
-	0x10400050, 0x00000000, 0x0e0015b9, 0x32530040, 0x3c039000, 0x34630001,
-	0x8f820008, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024,
-	0x1440fffd, 0x00000000, 0x8f830000, 0x90620005, 0x34420008, 0xa0620005,
-	0x8f840000, 0x8c820074, 0x3c038000, 0x00431025, 0xac820074, 0x90830000,
-	0x24020020, 0x10620004, 0x00000000, 0x0000000d, 0x00000000, 0x2400040b,
-	0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x9084007b,
-	0x9342010a, 0x14820028, 0x3c030800, 0x00003821, 0x24052000, 0x3c090800,
-	0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0,
-	0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030100, 0xaf420148, 0x24020046,
-	0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154,
-	0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030046,
-	0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b,
-	0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070100, 0x3c030800,
-	0x24625880, 0x0a001250, 0x8c430020, 0x93420108, 0x30420010, 0x50400056,
-	0x9343093f, 0x8f860000, 0x90c2007f, 0x8cc30178, 0x304800ff, 0x15030004,
-	0x00000000, 0x0000000d, 0x00000000, 0x24000425, 0x90c2007e, 0x90c40080,
-	0x00081c00, 0x00021600, 0x00431025, 0x00042200, 0x90c3007a, 0x90c5000a,
-	0x00441025, 0x11050028, 0x00623825, 0xa0c8000a, 0x00004021, 0x24056000,
-	0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0,
-	0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034, 0xaf420148, 0x24020052,
-	0xaf47014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7480158, 0xaf450154,
-	0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030052,
-	0xafa50014, 0x00021600, 0x00431025, 0x00481025, 0xafa20010, 0x9343010b,
-	0xafa30018, 0x8f440100, 0x0e00159b, 0x8f450104, 0x0a00124a, 0x00000000,
-	0x3c026000, 0x24030100, 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d,
-	0x00000000, 0x2400043e, 0x16800009, 0x3c050800, 0x3c040800, 0x24825880,
-	0x8c430020, 0x32530040, 0x2404ffbf, 0x00641824, 0x0a001493, 0xac430020,
-	0x8ca25880, 0x10400005, 0x3c030800, 0x8c620034, 0xaca05880, 0x24420001,
-	0xac620034, 0x9343093f, 0x24020012, 0x5462000e, 0x97420908, 0x32820038,
-	0x14400009, 0x3c030800, 0x8f830000, 0x8c62004c, 0xac62005c, 0x3c020800,
-	0x24445880, 0x8c820020, 0x0a001285, 0x32530040, 0xac605880, 0x97420908,
-	0x5440001c, 0x97420908, 0x3c039000, 0x34630001, 0x8f820008, 0x32530040,
-	0x3c048000, 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd,
-	0x3c028000, 0x8f840000, 0x8f850008, 0x8c830050, 0x34420001, 0x00a22825,
-	0xaf830020, 0xac830070, 0xac83005c, 0xaf450020, 0x3c050800, 0x24a45880,
-	0x8c820020, 0x2403ffbf, 0x00431024, 0x0a001493, 0xac820020, 0x000211c0,
-	0xaf420024, 0x97420908, 0x3c030080, 0x34630003, 0x000211c0, 0xaf42080c,
-	0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa782002c, 0x3c020800, 0x24445880,
-	0xac83002c, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830018,
-	0x934209d8, 0x32850038, 0xafa50028, 0x00621821, 0xa483001a, 0x934209d8,
-	0x93430934, 0x3c1e0800, 0x00809821, 0x00431021, 0x24420010, 0xa4820016,
-	0x24020006, 0xae620020, 0x8fa20028, 0x10400003, 0x0000a821, 0x0a0012f0,
-	0x24120008, 0x8f420958, 0x8f830020, 0x8f840030, 0x00431023, 0x00832023,
-	0x04800003, 0xae620004, 0x04410003, 0x0082102b, 0x0a0012bc, 0xae600004,
-	0x54400001, 0xae640004, 0x8ee20000, 0x0040f809, 0x00000000, 0x00409021,
-	0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008, 0x1060002b, 0x3c02c000,
-	0x00621025, 0xaf420e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000,
-	0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008, 0xaf830004, 0x8f840004,
-	0x0044102b, 0x1040000b, 0x24150001, 0x24020100, 0x3c016000, 0xac22081c,
-	0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d, 0x00000000, 0x240004cd,
-	0x24150001, 0x8ee20004, 0x0040f809, 0x00000000, 0x02429025, 0x32420002,
-	0x5040001d, 0x8f470940, 0x12a00006, 0x8ec258b0, 0x8f830000, 0xac6200a8,
-	0x8f840000, 0x8e620034, 0xac8200ac, 0x32420004, 0x50400013, 0x8f470940,
-	0x3c020800, 0x3283007d, 0x10600110, 0x24575920, 0x32820001, 0x50400006,
-	0x36520002, 0x8f830034, 0x8f420940, 0x10620109, 0x00000000, 0x36520002,
-	0x24020008, 0xa6600010, 0xa6620012, 0xae600008, 0xa2600024, 0x8f470940,
-	0x3c030800, 0x24685880, 0x8d02002c, 0x8d050008, 0x95040010, 0x9506000a,
-	0x95030026, 0x00451021, 0x00862021, 0x00641821, 0xaf870034, 0xad02002c,
-	0x32820030, 0x10400008, 0xa5030014, 0x91020024, 0x32910040, 0x34420004,
-	0xa1020024, 0xaf400048, 0x0a001345, 0x3c040800, 0x93420923, 0x30420002,
-	0x10400029, 0x32910040, 0x8f830000, 0x8f840020, 0x8c620084, 0x00441023,
-	0x0442000a, 0x3c039000, 0x95020014, 0x8c630084, 0x00821021, 0x00621823,
-	0x1c600004, 0x3c039000, 0x91020024, 0x34420001, 0xa1020024, 0x34630001,
-	0x8f820008, 0x32910040, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020,
-	0x00441024, 0x1440fffd, 0x00000000, 0x8f840000, 0x9083003f, 0x2402000a,
-	0x10620005, 0x2402000c, 0x9083003f, 0x24020008, 0x14620002, 0x24020014,
-	0xa082003f, 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020,
-	0x3c040800, 0x24865880, 0x94c20010, 0x94c3001a, 0x8cc40008, 0x00432821,
-	0x14800006, 0xa4c5001c, 0x3c020800, 0x8c430048, 0x10600002, 0x24a20040,
-	0xa4c2001c, 0x27d05880, 0x9604001c, 0x96020012, 0x00822021, 0x24840002,
-	0x0e000faf, 0x3084ffff, 0x8f850018, 0x00a01821, 0xa2030025, 0x8ee60008,
-	0x00402021, 0x24a50001, 0xaf850018, 0x00c0f809, 0x00000000, 0x00402021,
-	0x0e001026, 0x02202821, 0x8ee3000c, 0x0060f809, 0x00402021, 0x9604001c,
-	0x96020012, 0x00822021, 0x24840002, 0x0e000fc5, 0x3084ffff, 0x8fc25880,
-	0x8e030008, 0x00431023, 0x14400012, 0xafc25880, 0x54600006, 0x8e020020,
-	0x3243004a, 0x24020002, 0x14620005, 0x00000000, 0x8e020020, 0x34420040,
-	0x0a001382, 0xae020020, 0x52a00006, 0x36520002, 0x8e020030, 0xaf420e10,
-	0x8e030034, 0xaf430e18, 0x36520002, 0x52a00008, 0x96670014, 0x8f830000,
-	0x8f420e10, 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670014,
-	0x92680024, 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821,
-	0x00621023, 0xaf830020, 0x18400008, 0x00000000, 0x8f820000, 0xaf83001c,
-	0xac430054, 0x54e00005, 0xaf400040, 0x0a0013a0, 0x8f42095c, 0x54e00001,
-	0xaf400044, 0x8f42095c, 0x31030008, 0xaf820030, 0x1060001a, 0x00000000,
-	0x8f840000, 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007,
-	0x24020007, 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122,
-	0x8f850000, 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001,
-	0x30630007, 0xac440000, 0x0a0013bd, 0xa0a30120, 0x90820122, 0x34420001,
-	0xa0820122, 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000,
-	0x8c43000c, 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008,
-	0x34420001, 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024,
-	0x1440fffd, 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018,
-	0x00000000, 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068,
-	0x90e40081, 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b,
-	0x54400001, 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001,
-	0x00c02021, 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c,
-	0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f820020,
-	0x3c050800, 0x24b05880, 0xae020028, 0x8ee30010, 0x0060f809, 0x00000000,
-	0x8f820028, 0x24420001, 0xaf820028, 0x12a00005, 0xaf40004c, 0x8f420e10,
-	0xae020030, 0x8f430e18, 0xae030034, 0x1220fea7, 0x24020006, 0x8f870024,
-	0x9786002c, 0x8f830000, 0x8f820034, 0x8f840020, 0x8f85001c, 0x32530040,
-	0xa4e6002c, 0xac620044, 0x32420008, 0xac640050, 0xac650054, 0x1040007a,
-	0x32820020, 0x10400027, 0x32910010, 0x00003821, 0x24052000, 0x3c090800,
-	0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec258b0, 0x26c458b0,
-	0x2484ffd0, 0xaf420144, 0x8c820034, 0x3c030400, 0xaf420148, 0x24020041,
-	0xaf43014c, 0xa3420152, 0x8d230030, 0x3c021000, 0xa7470158, 0xaf450154,
-	0xaf420178, 0x8c860034, 0x24630001, 0xad230030, 0x9342010a, 0x3c030041,
-	0xafa50014, 0x00021600, 0x00431025, 0x00471025, 0xafa20010, 0x9343010b,
-	0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x3c070400, 0x12200028,
-	0x00003821, 0x24052000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024,
-	0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034,
-	0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0xa3420152, 0x8d230030,
-	0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001,
-	0xad230030, 0x9342010a, 0x3c03004e, 0xafa50014, 0x00021600, 0x00431025,
-	0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104,
-	0x0e00159b, 0x3c070300, 0x0a00148b, 0x8fa20024, 0x32820008, 0x10400026,
-	0x24052000, 0x00003821, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024,
-	0x1440fffd, 0x8ec258b0, 0x26c458b0, 0x2484ffd0, 0xaf420144, 0x8c820034,
-	0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0xa3420152, 0x8d230030,
-	0x3c021000, 0xa7470158, 0xaf450154, 0xaf420178, 0x8c860034, 0x24630001,
-	0xad230030, 0x9342010a, 0x3c03004b, 0xafa50014, 0x00021600, 0x00431025,
-	0x00471025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100, 0x8f450104,
-	0x0e00159b, 0x3c070200, 0x8fa20024, 0x14400004, 0x8fa30020, 0x32420010,
-	0x10400004, 0x00000000, 0x8c620004, 0x0040f809, 0x00000000, 0x12600006,
-	0x8fa40020, 0x8c820008, 0x0040f809, 0x00000000, 0x0a0014c1, 0x8fbf0054,
-	0x3c030800, 0x8c6258a0, 0x30420040, 0x14400023, 0x8fbf0054, 0x00002821,
-	0x24040040, 0x8f870020, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd,
-	0x8ec258b0, 0x26c358b0, 0x2463ffd0, 0xaf420144, 0x8c620034, 0xaf420148,
-	0x24020049, 0xaf47014c, 0xa3420152, 0x3c021000, 0xa7450158, 0xaf440154,
-	0xaf420178, 0x8c660034, 0x9342010a, 0x3c030049, 0xafa40014, 0x00021600,
-	0x00431025, 0x00451025, 0xafa20010, 0x9343010b, 0xafa30018, 0x8f440100,
-	0x0e00159b, 0x8f450104, 0x8fbf0054, 0x8fbe0050, 0x8fb7004c, 0x8fb60048,
-	0x8fb50044, 0x8fb40040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030,
-	0x03e00008, 0x27bd0058, 0x03e00008, 0x00001021, 0x3c020800, 0x24435880,
-	0x8c650004, 0x8c445880, 0x0085182b, 0x10600002, 0x00403021, 0x00802821,
-	0x9744093c, 0x00a4102b, 0x54400001, 0x00a02021, 0x93420923, 0x0004182b,
-	0x00021042, 0x30420001, 0x00431024, 0x1040000d, 0x24c25880, 0x8f850000,
-	0x8f830020, 0x8ca20084, 0x00431023, 0x04420007, 0x24c25880, 0x8ca20084,
-	0x00641821, 0x00431023, 0x28420001, 0x00822023, 0x24c25880, 0xac440008,
-	0xa4400026, 0x03e00008, 0x00001021, 0x8f850004, 0x97840010, 0x3c030800,
-	0x24635880, 0x24020008, 0xa4620012, 0x8f820004, 0xa4600010, 0x000420c2,
-	0x30840008, 0x2c420001, 0x00021023, 0x30420006, 0xac650008, 0x03e00008,
-	0xa0640024, 0x3c020800, 0x24425880, 0x90450025, 0x9443001c, 0x3c021100,
-	0xac800004, 0x00052c00, 0x24630002, 0x00621825, 0x00a32825, 0x24820008,
-	0x03e00008, 0xac850000, 0x27bdffd8, 0x3c020800, 0x24425880, 0xafbf0020,
-	0x90480025, 0x8c440008, 0x8c460020, 0x8f870020, 0x3c030800, 0x3c058000,
-	0x8f420178, 0x00451024, 0x1440fffd, 0x8c6258b0, 0x246358b0, 0x2469ffd0,
-	0xaf420144, 0x8d220034, 0x30c32000, 0xaf420148, 0x3c021000, 0xaf47014c,
-	0xa3480152, 0xa7440158, 0xaf460154, 0xaf420178, 0x10600004, 0x3c030800,
-	0x8c620030, 0x24420001, 0xac620030, 0x9342010a, 0x00081c00, 0x3084ffff,
-	0xafa60014, 0x00021600, 0x00431025, 0x00441025, 0xafa20010, 0x9343010b,
-	0xafa30018, 0x8f440100, 0x8f450104, 0x0e00159b, 0x8d260034, 0x8fbf0020,
-	0x03e00008, 0x27bd0028, 0x0000000d, 0x00000000, 0x2400019d, 0x03e00008,
-	0x00000000, 0x0000000d, 0x00000000, 0x240001a9, 0x03e00008, 0x00000000,
-	0x03e00008, 0x00000000, 0x3c020800, 0x24425880, 0xac400008, 0xa4400026,
-	0x03e00008, 0x24020001, 0x3c020800, 0x24425880, 0x24030008, 0xac400008,
-	0xa4400010, 0xa4430012, 0xa0400024, 0x03e00008, 0x24020004, 0x03e00008,
-	0x00001021, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004,
-	0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a00156c,
-	0x00a01021, 0xac860000, 0x00000000, 0x00000000, 0x24840004, 0x00a01021,
-	0x1440fffa, 0x24a5ffff, 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068,
-	0x3c050800, 0x24a52098, 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04,
-	0x00a61021, 0xac440004, 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00,
-	0x00431025, 0xac820008, 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14,
-	0xac440010, 0x8f430e18, 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff,
-	0x25290001, 0xac470018, 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000,
-	0x24630001, 0xace3006c, 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068,
-	0x00042600, 0x00681824, 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010,
-	0x8fad0014, 0x8fae0018, 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080080,
-	0x000a4940, 0x01281021, 0x01091821, 0xac440000, 0x00601021, 0xac650004,
-	0xac460008, 0xac67000c, 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018,
-	0x8c654448, 0x3c040800, 0x8c820064, 0x254a0001, 0x314a00ff, 0x01094021,
-	0xad6a0060, 0x24420001, 0xac820064, 0x03e00008, 0xad05001c, 0x3c030800,
-	0x3c090800, 0x8d250070, 0x246330b0, 0x8f460100, 0x00053900, 0x00e31021,
-	0xac460000, 0x8f440104, 0x00671021, 0xac440004, 0x8f460108, 0x8f840014,
-	0x24a50001, 0xac460008, 0x8c880074, 0x3c060800, 0x8cc20074, 0x30a5003f,
-	0x00671821, 0xad250070, 0x24420001, 0xacc20074, 0x03e00008, 0xac68000c,
-	0x00000000 };
+static u8 bnx2_TXP_b06FwText[] = {
+	0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65,
+	0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c,
+	0x1b, 0xf7, 0x79, 0x7f, 0xee, 0x85, 0xd2, 0x51, 0x96, 0xe9, 0x93, 0xc2,
+	0x78, 0x6c, 0xc0, 0xa6, 0x77, 0xd6, 0x51, 0x66, 0x20, 0xb5, 0xa0, 0x05,
+	0x36, 0x55, 0x87, 0x43, 0x73, 0x3e, 0x52, 0x2f, 0x4e, 0x5c, 0x57, 0x71,
+	0x94, 0x86, 0x6e, 0x0d, 0x8c, 0xa0, 0xec, 0xd8, 0xeb, 0x5a, 0x2c, 0x1f,
+	0x8c, 0xd5, 0x68, 0xd1, 0x99, 0xa1, 0x68, 0xc7, 0xc9, 0x68, 0x51, 0xa9,
+	0xe5, 0xa8, 0x43, 0x57, 0x80, 0x95, 0x64, 0xcb, 0x29, 0x4e, 0x3a, 0x65,
+	0xcb, 0x16, 0x0c, 0x58, 0x16, 0xcd, 0x2f, 0x5d, 0x3f, 0x74, 0x80, 0x3f,
+	0xec, 0x43, 0x3a, 0xec, 0x83, 0x91, 0x14, 0xad, 0x11, 0x6c, 0x59, 0xb0,
+	0x2f, 0x33, 0xd6, 0x26, 0xb7, 0xdf, 0x73, 0x77, 0x94, 0x95, 0xc4, 0x4e,
+	0xab, 0x7d, 0xbe, 0x07, 0x20, 0xee, 0x7f, 0xff, 0xd7, 0xe7, 0xfd, 0xe5,
+	0x7f, 0x90, 0x06, 0xb7, 0x53, 0x17, 0x85, 0xb0, 0x1d, 0x3f, 0xed, 0x99,
+	0x93, 0x27, 0x3e, 0xf7, 0xf9, 0xcf, 0x0d, 0xa1, 0x39, 0x4c, 0x4a, 0x4c,
+	0xe4, 0xc1, 0x5b, 0x12, 0x51, 0xf9, 0x1d, 0x8a, 0x20, 0x82, 0x08, 0x22,
+	0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20,
+	0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08,
+	0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88,
+	0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82,
+	0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22, 0x88, 0x20, 0x82, 0x08, 0x22,
+	0xf8, 0x9d, 0x20, 0x11, 0xa9, 0xfc, 0xdc, 0x1e, 0xfe, 0x48, 0x11, 0xcd,
+	0xf2, 0x53, 0xb6, 0x41, 0x8a, 0x64, 0x1e, 0x39, 0x34, 0x65, 0x10, 0x59,
+	0xce, 0x80, 0x56, 0xa0, 0xf7, 0xbd, 0x6a, 0x52, 0x26, 0xee, 0xff, 0xb4,
+	0xf9, 0xdb, 0x53, 0xaf, 0x7f, 0x41, 0x7f, 0xaf, 0x25, 0x91, 0xa2, 0x9a,
+	0x6b, 0x79, 0xb5, 0x9f, 0x94, 0x34, 0xd6, 0xfc, 0xd5, 0xee, 0xaf, 0xef,
+	0xa0, 0x44, 0x7b, 0xaf, 0x24, 0xd5, 0x9b, 0xb7, 0xbc, 0xd7, 0x77, 0x27,
+	0xe9, 0x15, 0x57, 0xa5, 0x35, 0x57, 0x16, 0x46, 0x9b, 0x0a, 0x4d, 0x37,
+	0x1d, 0x3a, 0xdd, 0xa8, 0x52, 0xc1, 0xbd, 0x4c, 0xb5, 0x39, 0x35, 0x61,
+	0x2f, 0xff, 0x84, 0xa6, 0xe7, 0x7a, 0x13, 0x85, 0x65, 0x87, 0x6a, 0x8d,
+	0x54, 0xc2, 0x76, 0xd5, 0x44, 0x61, 0x3e, 0x89, 0xf7, 0xde, 0x84, 0x3d,
+	0xaf, 0x57, 0x89, 0x76, 0x62, 0x4e, 0x2a, 0x51, 0x68, 0xea, 0x65, 0xa2,
+	0xbe, 0xdc, 0x75, 0x4a, 0x27, 0x0a, 0xee, 0x82, 0xb0, 0xae, 0x0a, 0x54,
+	0xfb, 0x2c, 0xa9, 0x09, 0xf3, 0xb6, 0xf7, 0x29, 0x43, 0xa5, 0x1e, 0x83,
+	0x76, 0xec, 0x30, 0xe8, 0xd9, 0x94, 0xa9, 0x50, 0xe5, 0x7c, 0x9c, 0x2c,
+	0x9f, 0x26, 0x95, 0x2a, 0xf3, 0x03, 0xea, 0x15, 0x8a, 0x91, 0x95, 0x6c,
+	0xbf, 0x7b, 0x9e, 0x9d, 0xfb, 0x16, 0xff, 0x9d, 0x16, 0xce, 0xa2, 0xc4,
+	0xa8, 0x4b, 0x64, 0x03, 0x2f, 0x3b, 0xf7, 0xbe, 0x17, 0xac, 0x51, 0x70,
+	0xae, 0x9c, 0x18, 0x69, 0x7a, 0x5e, 0x31, 0x87, 0x33, 0x72, 0xed, 0xb5,
+	0x31, 0x6a, 0x25, 0xad, 0xd6, 0x74, 0x2e, 0xbf, 0x23, 0xf8, 0x1b, 0x2f,
+	0xa6, 0x91, 0xdf, 0x2d, 0x12, 0x8d, 0xaf, 0x50, 0x25, 0x49, 0xad, 0x5a,
+	0xee, 0x61, 0x7a, 0x21, 0xd7, 0x4d, 0x67, 0xb1, 0xdf, 0xf3, 0x39, 0xf0,
+	0xd1, 0x38, 0x29, 0xd8, 0xae, 0x9e, 0x22, 0xe1, 0x05, 0xb2, 0xe7, 0xfb,
+	0xd4, 0x02, 0xe1, 0x6c, 0xc3, 0xfb, 0x8c, 0x9d, 0xc3, 0x79, 0x83, 0xff,
+	0xeb, 0x59, 0x49, 0xbd, 0xdc, 0xa2, 0x14, 0xd5, 0x9a, 0x7d, 0xb9, 0x9f,
+	0x93, 0x40, 0x9d, 0x06, 0xf3, 0xc7, 0xa3, 0xc7, 0x70, 0xae, 0x6d, 0xa0,
+	0xdf, 0x25, 0x4b, 0xcc, 0xc4, 0xe8, 0x4f, 0x55, 0x5d, 0xb3, 0xa5, 0x5e,
+	0xaa, 0x9d, 0xef, 0x04, 0x9e, 0x56, 0xaf, 0x88, 0xb9, 0x63, 0x79, 0x4a,
+	0x6e, 0x23, 0x12, 0x24, 0x33, 0x83, 0x7d, 0x89, 0x6a, 0x4e, 0x0a, 0x6b,
+	0x33, 0xc3, 0xef, 0xd0, 0x0e, 0xd2, 0x7a, 0x64, 0x9a, 0x76, 0xba, 0xc0,
+	0xc7, 0x6e, 0xc8, 0x20, 0x33, 0xfc, 0x2e, 0x84, 0x22, 0x1a, 0x99, 0xd4,
+	0x49, 0x2a, 0x0b, 0x05, 0xb7, 0x83, 0xa6, 0x33, 0x0a, 0xd5, 0x81, 0x47,
+	0x3d, 0xf7, 0x35, 0xc1, 0x5e, 0x2e, 0x09, 0x85, 0x65, 0xcc, 0x73, 0x5f,
+	0x0b, 0xff, 0x76, 0xad, 0x1b, 0xfb, 0x88, 0x54, 0xcb, 0x94, 0x30, 0xa6,
+	0xd0, 0x14, 0xe6, 0x4d, 0x81, 0xa6, 0x69, 0x77, 0x07, 0xad, 0x4f, 0x26,
+	0x13, 0xcc, 0xab, 0x1a, 0xc6, 0xbf, 0x32, 0x21, 0x90, 0x6a, 0x58, 0xf4,
+	0xeb, 0x3c, 0x64, 0x38, 0xdf, 0xcb, 0x32, 0xa3, 0xd3, 0x4d, 0x4a, 0x8a,
+	0x94, 0x49, 0x55, 0xe8, 0x32, 0x2d, 0x3a, 0x2c, 0x7f, 0xc8, 0x13, 0xf2,
+	0xae, 0x39, 0xbc, 0x0e, 0x72, 0x6b, 0x16, 0xc1, 0x8f, 0x71, 0xe0, 0x70,
+	0x50, 0x78, 0x6c, 0x71, 0x52, 0x18, 0x73, 0x7f, 0x93, 0xa0, 0xae, 0x93,
+	0xc2, 0x01, 0xf7, 0xa8, 0x10, 0xf2, 0x1e, 0xb2, 0x53, 0xc8, 0x9a, 0x50,
+	0xe8, 0x92, 0x1b, 0xc8, 0x6e, 0x01, 0xfa, 0x69, 0xa9, 0x16, 0xe4, 0x70,
+	0x78, 0x63, 0x0e, 0x8f, 0xd5, 0x97, 0x65, 0x3a, 0xed, 0xf2, 0xfc, 0x3f,
+	0x82, 0x7c, 0x14, 0x72, 0x76, 0x77, 0x53, 0x19, 0xfd, 0xb5, 0x79, 0xb2,
+	0xec, 0x9c, 0x88, 0x35, 0x09, 0x92, 0x8c, 0x9d, 0xf8, 0x75, 0xd1, 0xd4,
+	0x62, 0xa7, 0x25, 0x19, 0x49, 0x9a, 0x72, 0x99, 0x87, 0x78, 0x36, 0xdb,
+	0x7c, 0x64, 0x5c, 0xb9, 0x9f, 0xd7, 0x71, 0xbf, 0x8a, 0xfe, 0xcd, 0x7d,
+	0xac, 0x17, 0x09, 0xe0, 0xa3, 0x67, 0x59, 0x9f, 0x2b, 0xcd, 0x8c, 0x7a,
+	0x80, 0x9f, 0x2e, 0xf3, 0xb6, 0xcd, 0x53, 0x19, 0x73, 0x45, 0xaa, 0x2c,
+	0xe2, 0x9c, 0xf3, 0xbf, 0xf5, 0x62, 0x79, 0xbc, 0x1b, 0x1d, 0xa0, 0x8b,
+	0xcf, 0x95, 0x81, 0x93, 0x48, 0xe5, 0x45, 0xde, 0x8b, 0xc7, 0x09, 0xb2,
+	0xaf, 0xf5, 0x88, 0x94, 0x85, 0x7c, 0x75, 0x9c, 0x13, 0xc7, 0x9c, 0x6e,
+	0xf0, 0x0f, 0xb4, 0x2e, 0xa3, 0x0d, 0xda, 0x45, 0x43, 0xc4, 0xfa, 0x4e,
+	0x9a, 0xca, 0xb1, 0xbe, 0x30, 0x9e, 0xdb, 0xb0, 0x77, 0x9c, 0x8e, 0x9c,
+	0x67, 0x7e, 0xc8, 0xf4, 0x3c, 0x70, 0x9c, 0x9e, 0xd7, 0xd5, 0x22, 0xe9,
+	0xe0, 0x8d, 0x85, 0x79, 0x9d, 0x54, 0x56, 0x3d, 0x6f, 0x24, 0x37, 0xa0,
+	0xbe, 0xec, 0xeb, 0xf9, 0x80, 0x9a, 0x11, 0xa8, 0xda, 0x61, 0xfe, 0x21,
+	0x70, 0xd0, 0x4b, 0x44, 0xfc, 0xfe, 0xcf, 0x64, 0x4d, 0xb2, 0xfd, 0x24,
+	0xf9, 0x2c, 0xd8, 0xd3, 0x4e, 0xe0, 0xcf, 0x36, 0x97, 0x86, 0x5c, 0x52,
+	0xbe, 0x1d, 0x8c, 0xdc, 0xd5, 0x0e, 0xf4, 0xf1, 0x16, 0x6c, 0xa6, 0xb6,
+	0x2c, 0xb3, 0xfd, 0xe5, 0xa0, 0x6e, 0xb4, 0xcd, 0x80, 0x6e, 0xf9, 0xb2,
+	0xd9, 0x8f, 0xfd, 0x3d, 0xef, 0xcb, 0xb9, 0x00, 0xa7, 0xda, 0xbc, 0x85,
+	0xb5, 0x32, 0xf8, 0xae, 0x1f, 0xd7, 0xfc, 0xf3, 0xf7, 0x87, 0xe7, 0xab,
+	0x34, 0x05, 0xbc, 0x6b, 0x4d, 0x89, 0x0a, 0x2a, 0xef, 0xf1, 0x2e, 0xf7,
+	0x97, 0x83, 0xbd, 0xa0, 0xb7, 0xe7, 0xfa, 0xd4, 0x7d, 0xb0, 0x25, 0xb6,
+	0xb1, 0xda, 0x0a, 0xf3, 0x18, 0xfb, 0xe4, 0x99, 0xc7, 0xaa, 0x8f, 0xa3,
+	0x3d, 0xcf, 0x7a, 0x44, 0x69, 0x89, 0x58, 0xcf, 0x2f, 0xb3, 0x2e, 0x41,
+	0x3f, 0x03, 0xbd, 0xaa, 0x38, 0x2c, 0xff, 0x2f, 0x85, 0xf6, 0x29, 0x52,
+	0x7f, 0x86, 0xf5, 0xfd, 0x05, 0x2a, 0xc0, 0xc6, 0xa7, 0x70, 0xd2, 0x22,
+	0x68, 0x5a, 0x68, 0xf6, 0x81, 0x57, 0x6d, 0xbb, 0x83, 0x7c, 0x07, 0xff,
+	0xc7, 0x0b, 0xe6, 0x77, 0x03, 0x27, 0xb6, 0x99, 0x9a, 0x2a, 0x52, 0x15,
+	0x3f, 0xe8, 0x8d, 0xa1, 0x67, 0x6d, 0x49, 0x9f, 0x28, 0x03, 0x37, 0xe8,
+	0x3d, 0xd9, 0x7b, 0x58, 0x9f, 0x31, 0xc7, 0xa5, 0xa1, 0xb6, 0x9d, 0x2d,
+	0x38, 0x2c, 0xa7, 0x2e, 0x9c, 0xdb, 0xc6, 0x49, 0x46, 0x1f, 0xef, 0xa3,
+	0x40, 0xe7, 0xdb, 0x3a, 0xc3, 0xfa, 0xa7, 0x5b, 0xeb, 0xd4, 0x41, 0xd9,
+	0x0c, 0x7c, 0xd9, 0xbc, 0x08, 0xf9, 0xa5, 0xe1, 0x53, 0x64, 0x7a, 0xba,
+	0x99, 0xa4, 0x63, 0x4d, 0xc6, 0xaf, 0x08, 0xbb, 0x83, 0x6f, 0x9b, 0x1f,
+	0x85, 0x9d, 0x8d, 0x0b, 0x23, 0xb0, 0x89, 0x47, 0x17, 0x19, 0x27, 0x8f,
+	0xd8, 0x2e, 0x8b, 0xcb, 0x65, 0x61, 0xd4, 0x2d, 0x09, 0xe3, 0xcb, 0x6c,
+	0x27, 0x6c, 0x23, 0xba, 0xfa, 0x38, 0x31, 0x0d, 0x98, 0xe3, 0xfe, 0x22,
+	0xc1, 0xb6, 0x5a, 0x3b, 0x17, 0x07, 0x1e, 0xdb, 0x80, 0x4f, 0x37, 0x6c,
+	0x0f, 0xfa, 0x65, 0xe8, 0x13, 0xac, 0x33, 0xc5, 0x8c, 0xa1, 0xfd, 0x25,
+	0x7d, 0x9c, 0x0f, 0x23, 0x1b, 0x7c, 0x18, 0x00, 0x4f, 0x3e, 0xcc, 0x87,
+	0xfa, 0xc7, 0xf9, 0x60, 0x55, 0xc1, 0x87, 0x3a, 0xfc, 0x50, 0xdd, 0x65,
+	0x9a, 0x3d, 0x12, 0xf7, 0x10, 0xb4, 0x93, 0xf6, 0x8a, 0x26, 0xeb, 0x28,
+	0xdb, 0x49, 0x46, 0x9b, 0xc6, 0x0e, 0x4b, 0x4e, 0xb7, 0x6f, 0x1b, 0xa3,
+	0x3e, 0x2f, 0x7e, 0x17, 0xbd, 0x4c, 0xdf, 0x1d, 0x9a, 0xc7, 0x17, 0xd9,
+	0xdf, 0x40, 0xcf, 0x33, 0x86, 0x7a, 0x88, 0xee, 0xd0, 0xbd, 0xef, 0x0e,
+	0xdd, 0x38, 0xa7, 0xed, 0x83, 0x98, 0xe6, 0xb6, 0x3f, 0x66, 0x5d, 0x79,
+	0xc3, 0x93, 0x0c, 0x03, 0x32, 0x60, 0x7d, 0x61, 0x1c, 0x74, 0xf5, 0xcb,
+	0xa0, 0xa7, 0x02, 0xbf, 0xc0, 0xb6, 0x54, 0xf6, 0xe7, 0x75, 0x50, 0xb9,
+	0x27, 0x98, 0x3f, 0xd5, 0xf4, 0xfe, 0x4b, 0x34, 0x3f, 0xf0, 0xec, 0xbc,
+	0x11, 0xda, 0xb8, 0x42, 0x7f, 0xb2, 0xa8, 0x97, 0x35, 0xa1, 0x9b, 0xaa,
+	0xf7, 0xc3, 0xaf, 0x34, 0xd9, 0x3e, 0x76, 0xde, 0xc3, 0x97, 0xa5, 0x43,
+	0x5f, 0xf6, 0x3e, 0x78, 0xcf, 0xb1, 0xe7, 0xe8, 0x07, 0xeb, 0x49, 0x7e,
+	0x66, 0xd4, 0x09, 0x2a, 0x71, 0xbc, 0xd9, 0x21, 0xfa, 0xfe, 0xbb, 0x8f,
+	0x63, 0x41, 0x55, 0x36, 0xe3, 0x54, 0xed, 0xa1, 0xaa, 0x64, 0xb2, 0x1d,
+	0xb1, 0x6d, 0xb4, 0xf1, 0xde, 0x1e, 0xc6, 0xdd, 0x41, 0x89, 0x0c, 0x1e,
+	0x47, 0x8c, 0x68, 0x32, 0x0d, 0xef, 0x87, 0xf2, 0x60, 0x7f, 0x4a, 0xb1,
+	0x40, 0xdf, 0xf6, 0xc3, 0x5f, 0x32, 0x3f, 0x37, 0xeb, 0x0a, 0xfb, 0x51,
+	0xd2, 0x44, 0x83, 0xfd, 0x28, 0xa9, 0x92, 0x79, 0x50, 0xb0, 0x16, 0xbf,
+	0x26, 0x58, 0xe0, 0x9b, 0x05, 0xbe, 0x59, 0xe0, 0x9b, 0x0d, 0xbe, 0x15,
+	0x5c, 0xc6, 0x85, 0xf1, 0x08, 0xf6, 0x2f, 0x06, 0xfb, 0x03, 0xc7, 0x9d,
+	0x54, 0xf1, 0xed, 0x9b, 0x69, 0x85, 0x3f, 0xf6, 0x7d, 0xc1, 0xa8, 0x10,
+	0xf8, 0x02, 0xde, 0x6f, 0x1c, 0xeb, 0x1f, 0x47, 0x8c, 0xb3, 0x44, 0xd1,
+	0xb8, 0xc3, 0x8f, 0xfa, 0x26, 0x7e, 0x4c, 0x3b, 0xcc, 0x1f, 0x9e, 0xcf,
+	0x76, 0xec, 0x40, 0xe6, 0x6d, 0x9e, 0xec, 0x07, 0x0e, 0x9d, 0x4c, 0x77,
+	0x48, 0x07, 0xef, 0xdf, 0x1b, 0xee, 0x7f, 0x00, 0x7b, 0xb2, 0xdd, 0xde,
+	0xed, 0x5c, 0x3e, 0x93, 0xe3, 0xe8, 0x27, 0xd1, 0x83, 0x3c, 0x02, 0x7e,
+	0x66, 0x0d, 0x76, 0x76, 0x53, 0x4a, 0xd1, 0xeb, 0xbb, 0x6f, 0x20, 0xb7,
+	0xa0, 0xea, 0x03, 0xa6, 0xa7, 0xc9, 0xe6, 0xfb, 0x5e, 0x3d, 0x0f, 0xdf,
+	0x69, 0xea, 0x29, 0x5b, 0x1a, 0xa4, 0x37, 0xdc, 0x2c, 0xfd, 0x9d, 0x6b,
+	0xd0, 0xdf, 0xba, 0x1a, 0xbd, 0xea, 0xa6, 0xe9, 0x6f, 0xdc, 0x14, 0xfd,
+	0xb5, 0xdb, 0xce, 0x43, 0x92, 0xac, 0x47, 0x89, 0xa2, 0x7b, 0xb7, 0x5c,
+	0x08, 0x3a, 0x8e, 0xbd, 0xec, 0xbc, 0x5c, 0x96, 0x4d, 0x3f, 0x3f, 0x98,
+	0x98, 0x6e, 0x90, 0xb2, 0xd3, 0xa0, 0xed, 0xf7, 0x23, 0xef, 0x49, 0x9a,
+	0xb4, 0xe3, 0x3e, 0x3c, 0x7b, 0x4d, 0xb2, 0x7a, 0xcc, 0x53, 0x9e, 0x68,
+	0xb0, 0x1e, 0x75, 0x0f, 0x4f, 0xe5, 0xe3, 0x8c, 0xfb, 0xc4, 0x34, 0xfc,
+	0x91, 0x8d, 0xb3, 0xaa, 0xd0, 0xc5, 0xaa, 0x7b, 0xe8, 0xfe, 0x20, 0x17,
+	0x7a, 0x2f, 0xcc, 0x89, 0x38, 0xaf, 0x5a, 0x7f, 0x6a, 0xc2, 0x60, 0x3f,
+	0x2b, 0x6c, 0xf2, 0xb3, 0x24, 0x14, 0x41, 0x53, 0x1d, 0xb8, 0x16, 0x41,
+	0xe7, 0x57, 0x5d, 0x45, 0x28, 0x9c, 0xef, 0xa5, 0xe9, 0x45, 0x8e, 0x55,
+	0x3c, 0x4f, 0x09, 0x73, 0x19, 0x7e, 0xef, 0xc0, 0x3b, 0x21, 0x7e, 0x14,
+	0xb6, 0x53, 0x42, 0x7f, 0x73, 0x82, 0x9c, 0x30, 0x17, 0x89, 0xd1, 0x05,
+	0x5f, 0x77, 0xb8, 0xdf, 0x2a, 0xfd, 0xb0, 0xff, 0x4e, 0xff, 0xf9, 0x8d,
+	0xfe, 0x72, 0xe9, 0xeb, 0x1b, 0xfd, 0xef, 0xa8, 0x01, 0x4e, 0xc3, 0xc2,
+	0xe3, 0xee, 0xf3, 0x61, 0xdf, 0x6d, 0xf0, 0xd3, 0xf3, 0xea, 0x88, 0x27,
+	0x35, 0xe3, 0x36, 0x72, 0x1f, 0xf6, 0x29, 0x5b, 0xf1, 0x21, 0x1f, 0xf2,
+	0x1f, 0xaa, 0x2d, 0xb1, 0x9c, 0x14, 0x0a, 0xf6, 0xe4, 0xf1, 0x4e, 0xf8,
+	0x92, 0xdb, 0x68, 0x73, 0xec, 0x6a, 0xfb, 0x31, 0x9e, 0xc3, 0xeb, 0x6f,
+	0xdd, 0x43, 0x96, 0x2a, 0x64, 0xb9, 0x35, 0x79, 0xd5, 0x1a, 0xa7, 0x42,
+	0x9f, 0xd0, 0x3d, 0x6c, 0x43, 0x2e, 0x12, 0xe4, 0x52, 0x83, 0x5c, 0x0a,
+	0xf7, 0x94, 0x0b, 0xce, 0xd8, 0xd0, 0x29, 0xc6, 0xa3, 0x2b, 0x3c, 0x9b,
+	0x14, 0xd9, 0xac, 0x96, 0xea, 0xc6, 0xa7, 0x28, 0x66, 0x30, 0x1e, 0x06,
+	0xf0, 0x38, 0x8a, 0xb5, 0x1c, 0xc3, 0x48, 0x89, 0x99, 0x2c, 0xcf, 0xdc,
+	0x13, 0xb6, 0x71, 0xab, 0xb4, 0xe0, 0xdc, 0x2a, 0x5d, 0x34, 0xf8, 0xfd,
+	0xf6, 0x64, 0x90, 0x37, 0x77, 0x3f, 0x89, 0xbc, 0x19, 0xeb, 0xd9, 0x1f,
+	0x72, 0xff, 0x30, 0xe6, 0x71, 0x7c, 0xa0, 0x43, 0x35, 0xfc, 0xea, 0xfe,
+	0xdc, 0x6b, 0x4f, 0xf0, 0xdc, 0x4e, 0x53, 0x9e, 0xfc, 0x35, 0x9e, 0x1d,
+	0xa6, 0xf6, 0xe4, 0x4f, 0x0d, 0xde, 0x77, 0x78, 0xf2, 0xa2, 0xbf, 0x07,
+	0x62, 0xa6, 0xbf, 0x36, 0xfb, 0x24, 0xaf, 0x7d, 0x0e, 0x3e, 0xf6, 0x0c,
+	0xe2, 0xcb, 0x69, 0x47, 0x3b, 0x54, 0xc1, 0x6f, 0x8a, 0x71, 0x6a, 0xf2,
+	0xb8, 0x85, 0x71, 0x19, 0xb1, 0x90, 0xdb, 0x0a, 0x1d, 0xc3, 0xbc, 0xa7,
+	0x31, 0xef, 0xa8, 0x33, 0x8e, 0xbc, 0xbd, 0x4d, 0xd7, 0xbf, 0xc5, 0x0b,
+	0xf3, 0xec, 0xcf, 0x91, 0xed, 0xaf, 0xfc, 0x7b, 0xdc, 0x86, 0x5f, 0x16,
+	0x57, 0x6e, 0xc6, 0x0b, 0xa0, 0x5b, 0x5a, 0xf9, 0x45, 0xbc, 0x08, 0x3d,
+	0x13, 0x0d, 0x09, 0x7e, 0xf9, 0x33, 0x54, 0x53, 0x3d, 0x7a, 0x19, 0xf1,
+	0xab, 0x96, 0x85, 0xbf, 0x82, 0x34, 0x45, 0x03, 0x7e, 0x4c, 0x25, 0xa5,
+	0xcb, 0x3c, 0xa9, 0x52, 0x57, 0x3e, 0x6e, 0x23, 0xde, 0xd4, 0x54, 0x09,
+	0xfd, 0xfd, 0x78, 0x6e, 0xee, 0xff, 0x65, 0x1c, 0x7e, 0x0b, 0x3e, 0x82,
+	0x14, 0x3b, 0xdf, 0x8d, 0xfd, 0xbf, 0x8d, 0x7e, 0x4c, 0xc8, 0x6c, 0xf4,
+	0x3f, 0x1b, 0xf4, 0xdf, 0x02, 0x2e, 0xbc, 0x8e, 0xe3, 0x27, 0x29, 0x53,
+	0x79, 0x15, 0x38, 0xf0, 0xdc, 0xa4, 0x3f, 0xb7, 0x38, 0xcf, 0x3c, 0xa8,
+	0x96, 0x16, 0x8c, 0x34, 0x15, 0xe6, 0x92, 0x34, 0x3a, 0xa7, 0xd2, 0xd8,
+	0x9c, 0x3e, 0xd1, 0x62, 0xfb, 0x01, 0xcd, 0x84, 0x1c, 0x41, 0x5c, 0x21,
+	0x50, 0xac, 0xa7, 0x9e, 0xa6, 0xbe, 0xd4, 0x31, 0xfa, 0x6f, 0x0f, 0xb1,
+	0x08, 0x71, 0xa8, 0x9b, 0x64, 0x7f, 0x9f, 0x54, 0xfb, 0x4c, 0x96, 0xd1,
+	0x87, 0xce, 0x2d, 0xce, 0xdf, 0x6b, 0x5f, 0x28, 0xf1, 0x4a, 0xea, 0x23,
+	0xfb, 0xbe, 0x1b, 0xee, 0xab, 0x62, 0xdf, 0x34, 0xf6, 0x64, 0x1a, 0xf5,
+	0xf8, 0xc8, 0x79, 0xb2, 0x3a, 0x81, 0x5f, 0x31, 0x83, 0x98, 0x8f, 0x7d,
+	0xce, 0xcc, 0xb1, 0xde, 0xd3, 0x4e, 0xfc, 0x06, 0x63, 0x94, 0xc9, 0x2e,
+	0x23, 0x27, 0x18, 0xf1, 0xf7, 0x08, 0xf2, 0x05, 0x71, 0x65, 0x10, 0xf9,
+	0xda, 0x3b, 0xc0, 0x87, 0xe3, 0x18, 0xd3, 0x2c, 0x83, 0xde, 0x41, 0xe4,
+	0x09, 0x9c, 0xe3, 0x7b, 0xa7, 0xec, 0x1c, 0xda, 0xcb, 0x5a, 0xbc, 0x00,
+	0xdb, 0x16, 0x4d, 0x7a, 0x50, 0xf2, 0x7d, 0x2c, 0xcb, 0x65, 0x10, 0x72,
+	0x62, 0xbc, 0x73, 0x90, 0x13, 0xf3, 0x68, 0x38, 0x5e, 0x6c, 0x32, 0x8f,
+	0x08, 0xf8, 0x68, 0xb0, 0x27, 0xd9, 0xcf, 0xf3, 0xc5, 0x15, 0x0b, 0xf3,
+	0x7e, 0xac, 0x72, 0x2e, 0x66, 0x1b, 0xdc, 0x86, 0xed, 0xac, 0x8c, 0x63,
+	0x2e, 0xb7, 0x1f, 0xc6, 0xbe, 0x7d, 0xb9, 0x1a, 0x75, 0xe4, 0x9e, 0x86,
+	0xdd, 0x8a, 0xf9, 0x01, 0xc4, 0x68, 0x01, 0xb9, 0xa0, 0xe7, 0x75, 0xe4,
+	0xbf, 0x00, 0x7a, 0x98, 0x0e, 0xe8, 0xf5, 0x2c, 0xf3, 0x95, 0xfe, 0x40,
+	0xe4, 0x5c, 0x2d, 0xdf, 0xce, 0x6b, 0x38, 0x9e, 0xf3, 0xf9, 0x88, 0x23,
+	0x8d, 0x3d, 0x88, 0xa5, 0xfe, 0xd9, 0xd0, 0xb1, 0x71, 0x2a, 0x34, 0x3e,
+	0x8b, 0x9c, 0x93, 0x6d, 0x67, 0x9b, 0x60, 0x9f, 0x67, 0x1a, 0x09, 0xb1,
+	0x66, 0x8d, 0x2a, 0x0d, 0x39, 0x6c, 0xbf, 0x8a, 0xb6, 0x12, 0xb6, 0xd7,
+	0xd1, 0xee, 0x0e, 0xdb, 0xd7, 0xd0, 0x56, 0xc3, 0xf6, 0xcf, 0xd0, 0x4e,
+	0x86, 0xed, 0x9f, 0xa3, 0x9d, 0x0a, 0xdb, 0x37, 0xd1, 0x4e, 0x87, 0xed,
+	0x5b, 0x68, 0x6b, 0x61, 0xfb, 0x3d, 0xb4, 0x13, 0xb0, 0x73, 0x03, 0xef,
+	0x37, 0x50, 0x2b, 0x66, 0xf1, 0xfc, 0x57, 0xe0, 0x36, 0x08, 0xde, 0x64,
+	0xc1, 0x8f, 0x5e, 0x8c, 0xe5, 0xd0, 0x87, 0x1c, 0xb1, 0x91, 0xc7, 0xd3,
+	0xc1, 0x18, 0x95, 0x61, 0x7b, 0x18, 0x1f, 0x2f, 0x16, 0x1a, 0x26, 0x9e,
+	0x6c, 0x0f, 0xba, 0x4a, 0xc2, 0x65, 0xd8, 0xb9, 0xef, 0x63, 0x72, 0xb6,
+	0x34, 0x09, 0xdb, 0x9e, 0xa0, 0x7f, 0x74, 0xf7, 0xd3, 0x6b, 0xee, 0x38,
+	0xe2, 0x46, 0x11, 0x71, 0xc3, 0x42, 0xdc, 0x30, 0x11, 0x37, 0x86, 0x11,
+	0x37, 0xf2, 0x88, 0x1b, 0x39, 0xc4, 0x0d, 0xa2, 0x33, 0x7e, 0x8c, 0x4a,
+	0x2a, 0xa8, 0x51, 0x15, 0xcb, 0x2d, 0x82, 0xbf, 0x13, 0x90, 0xcd, 0x24,
+	0x78, 0x7d, 0x38, 0x3e, 0xd2, 0xcc, 0xc3, 0x9f, 0x69, 0xf0, 0x11, 0x69,
+	0xf8, 0xf2, 0x1c, 0x6a, 0x13, 0xa2, 0x2b, 0xb3, 0x1a, 0xfc, 0x8f, 0x47,
+	0x45, 0xc4, 0xfe, 0x69, 0x15, 0xb8, 0x19, 0xbb, 0x7c, 0x9b, 0x91, 0xcc,
+	0x2f, 0xf6, 0x50, 0xd7, 0x20, 0xe8, 0x39, 0x8b, 0xbe, 0x14, 0xf6, 0x63,
+	0xbe, 0xde, 0x2a, 0xd9, 0x86, 0x46, 0x0b, 0x6e, 0x1c, 0xfe, 0x9f, 0xdf,
+	0xe3, 0xcc, 0xe3, 0x43, 0x4f, 0x19, 0x4c, 0x03, 0xea, 0x3c, 0x23, 0xad,
+	0x14, 0x1c, 0x81, 0x24, 0x93, 0x9f, 0xed, 0x1c, 0xe2, 0xcf, 0x90, 0x43,
+	0x74, 0x41, 0x06, 0x55, 0xc4, 0x05, 0x9d, 0xf3, 0x0b, 0xe8, 0xf2, 0x27,
+	0xcd, 0xff, 0x1e, 0xe6, 0xef, 0xc5, 0xd9, 0x3c, 0x8f, 0xcf, 0x39, 0x85,
+	0xfa, 0xc1, 0xea, 0x91, 0x68, 0x3d, 0x25, 0xa1, 0x9e, 0x28, 0xd0, 0x59,
+	0x2a, 0x00, 0x9f, 0x82, 0xdb, 0xbe, 0x07, 0xb0, 0x0e, 0x05, 0xfe, 0x6c,
+	0xe2, 0xd0, 0xb7, 0x0d, 0x0b, 0xeb, 0x18, 0x3f, 0xd6, 0x5b, 0xe0, 0xbe,
+	0xb1, 0xe7, 0x05, 0xec, 0xf9, 0x4f, 0x49, 0xea, 0x9a, 0x0c, 0xfc, 0x91,
+	0x5f, 0xf3, 0xca, 0xc2, 0x48, 0xf3, 0x2c, 0xf8, 0xd3, 0x87, 0x1a, 0x05,
+	0x7e, 0xa4, 0xd4, 0x02, 0x9f, 0xda, 0xf3, 0x5f, 0xc1, 0x7c, 0x7e, 0xf7,
+	0xef, 0x0e, 0x4a, 0xd2, 0xea, 0x12, 0xe6, 0x69, 0xac, 0x3f, 0x25, 0xb9,
+	0xff, 0x86, 0xf7, 0xa2, 0x91, 0xa7, 0x5d, 0xab, 0xbc, 0x2e, 0x4b, 0x7d,
+	0xab, 0x37, 0xbc, 0x9a, 0xa3, 0xd1, 0x62, 0x93, 0xc0, 0xab, 0xf8, 0x6d,
+	0x8b, 0xf4, 0x35, 0x12, 0xf5, 0x59, 0x0b, 0x7a, 0x5a, 0x1c, 0x12, 0xc9,
+	0x1e, 0xea, 0x84, 0x8f, 0x32, 0x68, 0x09, 0x7c, 0xdf, 0x35, 0x63, 0xd1,
+	0x13, 0x43, 0xed, 0x7c, 0x10, 0x51, 0x0f, 0xb8, 0xee, 0x5a, 0xd5, 0x30,
+	0x87, 0x73, 0x71, 0xa6, 0x45, 0x03, 0x2f, 0x85, 0x60, 0x8d, 0x1f, 0xb3,
+	0xb8, 0x8e, 0x05, 0xdf, 0xdc, 0xb5, 0xd2, 0xd5, 0x19, 0xd4, 0x1a, 0x90,
+	0xf3, 0xae, 0x19, 0xae, 0x85, 0xb6, 0x81, 0x2f, 0x31, 0xd8, 0x06, 0xe7,
+	0xf1, 0x08, 0xf4, 0xf0, 0x87, 0x27, 0xe0, 0xf1, 0x6b, 0xcd, 0x13, 0xd0,
+	0xfb, 0x2e, 0x2a, 0xcb, 0x3e, 0x11, 0x9f, 0xc0, 0xe3, 0xff, 0xe4, 0xbc,
+	0x0e, 0xf3, 0xbf, 0x4b, 0xc5, 0xd9, 0x2e, 0xec, 0xb5, 0x9b, 0xa6, 0x93,
+	0x8c, 0x9b, 0x3e, 0x8c, 0x41, 0x2d, 0x06, 0x7e, 0xc6, 0xcd, 0x8f, 0xe6,
+	0x7d, 0x6b, 0xa5, 0x2b, 0x33, 0x6b, 0xa5, 0x6b, 0xa0, 0xbf, 0x6e, 0x70,
+	0x8d, 0x0c, 0x5d, 0x6a, 0x70, 0x6d, 0xcf, 0x79, 0xd1, 0x18, 0x74, 0x64,
+	0xbf, 0x5f, 0x33, 0xdb, 0x8b, 0x39, 0xea, 0x3b, 0x47, 0xaa, 0x68, 0x96,
+	0x84, 0x31, 0xe4, 0x45, 0x23, 0xee, 0x49, 0x7f, 0xee, 0x99, 0x06, 0xd7,
+	0x2b, 0x18, 0x5b, 0x61, 0x5d, 0x18, 0x03, 0x3e, 0x49, 0xba, 0xe8, 0xb2,
+	0x4f, 0x0a, 0xec, 0x78, 0x0c, 0xfc, 0x5a, 0xf0, 0xe9, 0x4a, 0x71, 0x1c,
+	0x47, 0xbe, 0xc1, 0xf2, 0xf9, 0x21, 0xc7, 0x41, 0xa1, 0xd3, 0x6c, 0xfb,
+	0xdb, 0x89, 0x5e, 0xe6, 0x59, 0xa1, 0x01, 0xdf, 0x3f, 0x34, 0x11, 0xe6,
+	0x1c, 0x7f, 0x8f, 0x39, 0x8c, 0x3b, 0xcd, 0x4a, 0x26, 0xce, 0xc8, 0x33,
+	0xcf, 0x38, 0xa7, 0xe4, 0x7d, 0xc1, 0x5b, 0xf0, 0x7d, 0x53, 0x6e, 0xe9,
+	0xc3, 0x74, 0x33, 0x46, 0x95, 0x59, 0xf0, 0x2e, 0x8f, 0x27, 0x9c, 0x6b,
+	0x1d, 0x7c, 0x03, 0x2d, 0xd5, 0x20, 0x9f, 0x3d, 0xc1, 0x31, 0x0d, 0xfe,
+	0x06, 0x36, 0xcd, 0x31, 0x6b, 0xe3, 0xde, 0xc9, 0xf7, 0x25, 0x32, 0x19,
+	0x41, 0xce, 0x2a, 0xe2, 0x2c, 0x3b, 0xcf, 0x7e, 0x10, 0xf8, 0xb8, 0xdf,
+	0xa5, 0xfa, 0x2c, 0xd3, 0x05, 0x1b, 0x4f, 0xb2, 0x2e, 0xfe, 0x7f, 0xf9,
+	0x38, 0xba, 0x45, 0x3e, 0x8e, 0x6e, 0x99, 0x8f, 0x12, 0xf8, 0x58, 0xd9,
+	0xe0, 0xa3, 0x82, 0x3d, 0xf8, 0x3e, 0xe1, 0xab, 0x64, 0x4d, 0x3c, 0x02,
+	0x3f, 0x0c, 0xff, 0xd1, 0x3c, 0x05, 0x9f, 0x70, 0x52, 0xb8, 0xda, 0xf0,
+	0x68, 0x1c, 0xb5, 0xb2, 0x74, 0xff, 0x66, 0xfa, 0x33, 0xa0, 0xff, 0xcf,
+	0x31, 0x5e, 0xa5, 0x6b, 0xb3, 0x94, 0x56, 0xa8, 0x7d, 0x2e, 0xed, 0x92,
+	0xe9, 0x3b, 0x74, 0x75, 0xb6, 0x8b, 0xae, 0xcf, 0x66, 0xc0, 0xeb, 0x2c,
+	0xc5, 0x7a, 0x32, 0xc3, 0x15, 0x18, 0xf1, 0xcf, 0x5a, 0xba, 0xc5, 0xba,
+	0xf8, 0xfb, 0xf3, 0x82, 0xf9, 0x70, 0xd0, 0xe7, 0xc3, 0xd8, 0x47, 0xf8,
+	0x30, 0x7e, 0x4f, 0x3e, 0x1c, 0xfc, 0x18, 0x1f, 0xc6, 0x3f, 0xc6, 0x07,
+	0xe6, 0x01, 0xf3, 0xe2, 0xd1, 0xde, 0xf0, 0xff, 0x1f, 0x7d, 0x82, 0x7d,
+	0x7c, 0x09, 0x74, 0x22, 0xa7, 0xd8, 0x19, 0xe4, 0x50, 0x9c, 0x63, 0xd5,
+	0x0c, 0xe6, 0x57, 0x60, 0xbf, 0x32, 0x72, 0xea, 0x23, 0xa1, 0xfd, 0x16,
+	0x1c, 0xe8, 0x65, 0x23, 0xe6, 0xdb, 0xaf, 0x64, 0xe6, 0xe1, 0x03, 0xaa,
+	0xa5, 0x96, 0xc3, 0xfe, 0x07, 0x6d, 0x87, 0x79, 0xda, 0x0b, 0x5a, 0x12,
+	0x54, 0x99, 0x54, 0x10, 0x5f, 0x87, 0xa1, 0xb7, 0x71, 0xdf, 0x07, 0x4a,
+	0x26, 0xeb, 0xe1, 0x7e, 0xcc, 0x3f, 0x1c, 0xe6, 0x45, 0x88, 0x73, 0x38,
+	0xa3, 0xd6, 0x38, 0x0d, 0xfc, 0xf8, 0x9c, 0x6a, 0xa9, 0xec, 0xf0, 0x9a,
+	0x34, 0x62, 0x21, 0x3f, 0x37, 0xeb, 0xb7, 0xaf, 0xef, 0xf7, 0xd2, 0x71,
+	0xe8, 0x26, 0xeb, 0xb4, 0x82, 0xdc, 0x78, 0x02, 0xf1, 0xc5, 0xd7, 0xd3,
+	0xec, 0x02, 0xb1, 0xdf, 0x7f, 0x06, 0x75, 0xd1, 0x61, 0xfc, 0x34, 0x1a,
+	0x71, 0x03, 0x9b, 0x5a, 0xf2, 0xcf, 0xfc, 0xb0, 0x4f, 0xaa, 0x39, 0xeb,
+	0xc8, 0xdf, 0x0d, 0xec, 0xcb, 0xe7, 0x56, 0xc1, 0x1b, 0x09, 0xe7, 0x72,
+	0x5f, 0x37, 0xe2, 0x00, 0xf8, 0xe4, 0xfe, 0x07, 0xfa, 0x97, 0xe0, 0x1f,
+	0x39, 0x2f, 0x68, 0xe3, 0x8e, 0x1c, 0xc2, 0xe1, 0x78, 0x9d, 0x07, 0xcd,
+	0x9c, 0x63, 0x73, 0x2e, 0x81, 0xfc, 0x63, 0xe9, 0x4d, 0xf4, 0x0d, 0xd3,
+	0xe9, 0xa1, 0x2c, 0xe4, 0xc3, 0x7d, 0x0f, 0x84, 0x7d, 0x3c, 0x8f, 0x94,
+	0x07, 0x4d, 0xfd, 0x07, 0x55, 0xdf, 0xaf, 0x43, 0x0f, 0x51, 0xf7, 0xd5,
+	0x96, 0x90, 0x63, 0x00, 0xa7, 0xca, 0x6a, 0x16, 0xb9, 0x3c, 0xdf, 0xab,
+	0xe9, 0x97, 0x91, 0x07, 0x83, 0x27, 0x0a, 0xf5, 0x1a, 0xa5, 0xd0, 0x0f,
+	0xe7, 0x40, 0x1f, 0xdf, 0x3d, 0xf5, 0x21, 0xf7, 0x91, 0xc0, 0x08, 0xd8,
+	0xe9, 0xaa, 0x44, 0x7b, 0xe5, 0x01, 0xb5, 0x46, 0xff, 0x80, 0xb9, 0x32,
+	0x95, 0x57, 0x39, 0x87, 0x90, 0xe9, 0xc8, 0x2a, 0xd1, 0x5b, 0x33, 0xec,
+	0x97, 0x19, 0xd8, 0x2f, 0xb3, 0x7f, 0x7d, 0xd0, 0x1f, 0x7b, 0x6b, 0x06,
+	0x35, 0xf8, 0xcc, 0x00, 0xc7, 0xb0, 0x75, 0x11, 0xbc, 0x44, 0xee, 0xc3,
+	0xf9, 0xf9, 0x5d, 0xee, 0x98, 0xda, 0xf7, 0x4b, 0x0a, 0x55, 0x66, 0xf8,
+	0x6e, 0x49, 0xc6, 0xf9, 0x5c, 0x5b, 0x6c, 0x03, 0x7e, 0x02, 0xa1, 0xee,
+	0x12, 0x38, 0xa6, 0x09, 0xd0, 0xa1, 0x5d, 0x90, 0x3d, 0xf8, 0x1f, 0xb6,
+	0xdb, 0xfa, 0xf4, 0x2f, 0xd0, 0x27, 0x9e, 0x27, 0x6f, 0xc2, 0x25, 0x33,
+	0x6b, 0x8b, 0x1c, 0x1f, 0x3e, 0x0d, 0xdb, 0xb3, 0xe2, 0x63, 0xcd, 0x0e,
+	0x6a, 0xf5, 0xb2, 0x3d, 0xb0, 0x5e, 0x5c, 0x66, 0x9d, 0xc0, 0x19, 0xd0,
+	0xa1, 0x19, 0xae, 0xe7, 0x65, 0xcc, 0xbb, 0x2f, 0x9c, 0xc7, 0xfc, 0xfe,
+	0x1e, 0x4d, 0x0f, 0xa9, 0x42, 0x59, 0x0d, 0xe2, 0x45, 0x6d, 0xa8, 0x03,
+	0x63, 0x22, 0x1d, 0x7c, 0x38, 0x8f, 0xb5, 0x9c, 0x53, 0xc5, 0x85, 0xc0,
+	0x6f, 0x71, 0x1f, 0xdf, 0xd7, 0xa9, 0x54, 0xbe, 0xd4, 0x4b, 0x95, 0x4b,
+	0x0a, 0xf8, 0x02, 0x44, 0x17, 0x82, 0x7d, 0xd8, 0x17, 0x1c, 0x87, 0xdc,
+	0xc4, 0x73, 0x0a, 0xc5, 0xce, 0x21, 0x87, 0xbc, 0xd0, 0x45, 0x1d, 0x17,
+	0xfa, 0x49, 0xba, 0xa0, 0x73, 0x7e, 0xa8, 0x9d, 0x81, 0x0c, 0x8f, 0x50,
+	0x9e, 0x9e, 0x73, 0x07, 0x39, 0xc7, 0xc3, 0x39, 0x5c, 0xe7, 0x25, 0x49,
+	0x42, 0xf2, 0x2f, 0xbe, 0x68, 0xd1, 0x8b, 0x43, 0xc0, 0x2b, 0x8f, 0xf6,
+	0x8f, 0x91, 0xc7, 0xbb, 0x23, 0xf7, 0x71, 0xcc, 0x96, 0xcd, 0x3e, 0xc8,
+	0x16, 0x74, 0xe5, 0x1e, 0xf2, 0xef, 0x44, 0x5f, 0x1c, 0x62, 0x7a, 0x34,
+	0xd0, 0x52, 0x87, 0xae, 0xf3, 0x3d, 0x57, 0x17, 0xd9, 0x32, 0xeb, 0x32,
+	0xf2, 0xaa, 0x0b, 0x75, 0x9a, 0x6a, 0xe8, 0x90, 0x59, 0x1f, 0xf4, 0x02,
+	0x32, 0x4b, 0x73, 0x3f, 0xef, 0x2d, 0x84, 0xfb, 0xde, 0xd1, 0xf7, 0x17,
+	0xef, 0xad, 0xef, 0x3e, 0xd4, 0x9b, 0x8f, 0xc0, 0x67, 0xa3, 0x2e, 0x32,
+	0xe0, 0xd3, 0x55, 0xe4, 0x72, 0x06, 0xbf, 0x07, 0x77, 0x95, 0x15, 0xe4,
+	0x85, 0xfc, 0x5e, 0x6b, 0xdd, 0xcd, 0x77, 0x07, 0xf6, 0x7d, 0x06, 0x3c,
+	0xba, 0x32, 0xf7, 0x00, 0x5d, 0x9d, 0x53, 0xe8, 0x5a, 0x43, 0xcf, 0x16,
+	0xa8, 0x83, 0xaa, 0xc9, 0x34, 0x5d, 0x5f, 0x6a, 0xe7, 0x93, 0x22, 0xf4,
+	0xc4, 0x22, 0xce, 0xcd, 0xaf, 0x2c, 0x55, 0x4b, 0x37, 0x76, 0xa7, 0x49,
+	0x7e, 0x09, 0xb6, 0xfd, 0x92, 0xae, 0xd5, 0xc0, 0xe7, 0xba, 0xe1, 0xa2,
+	0x56, 0xe3, 0x3a, 0x32, 0x05, 0xbb, 0xd3, 0x53, 0x2d, 0xca, 0x90, 0xb4,
+	0xa0, 0xd0, 0xaf, 0x66, 0x74, 0x8d, 0x75, 0xee, 0xa2, 0x81, 0x7e, 0x37,
+	0x7e, 0x7b, 0x3d, 0xd0, 0x43, 0xf4, 0xf5, 0xa3, 0xbe, 0xd5, 0xb3, 0x9a,
+	0xd8, 0x4d, 0x6f, 0x43, 0x27, 0xca, 0x7e, 0xdf, 0x47, 0xf7, 0xbc, 0x1e,
+	0xee, 0x59, 0x2d, 0x5d, 0xe1, 0x3a, 0x68, 0x86, 0x75, 0xbe, 0x17, 0xfe,
+	0x03, 0xef, 0x6e, 0x07, 0x95, 0x27, 0x11, 0xa3, 0x66, 0x1e, 0xa5, 0xc2,
+	0x90, 0x18, 0xd0, 0xed, 0xf3, 0x82, 0xfb, 0xf8, 0x7e, 0xb2, 0x76, 0x1f,
+	0xdb, 0xb2, 0xb8, 0x0a, 0xbd, 0x3a, 0xc8, 0x7a, 0x80, 0xdc, 0x0e, 0x39,
+	0x04, 0xfb, 0x4e, 0x09, 0x39, 0x44, 0xc1, 0x0d, 0x74, 0xa3, 0x75, 0x30,
+	0x49, 0xc7, 0x5e, 0x62, 0x19, 0x61, 0x6c, 0x43, 0xef, 0x36, 0xee, 0xc4,
+	0x31, 0x66, 0xd0, 0xf1, 0xef, 0xb7, 0x73, 0x4a, 0xb6, 0xbd, 0x34, 0xe4,
+	0xa1, 0xa3, 0xf6, 0xe8, 0x53, 0x2b, 0xbe, 0x4f, 0x81, 0x4e, 0xa4, 0x02,
+	0x19, 0xd4, 0x30, 0x36, 0xed, 0x4e, 0xc2, 0x27, 0xc6, 0xe8, 0xe6, 0xa4,
+	0x05, 0x9d, 0x68, 0x01, 0x87, 0xc3, 0x71, 0xbe, 0x4b, 0xb8, 0x39, 0x59,
+	0xc4, 0xfb, 0x61, 0x3f, 0xf7, 0x97, 0xf6, 0x40, 0x97, 0xdc, 0x07, 0xc2,
+	0xfc, 0x9c, 0xcf, 0xd3, 0x84, 0xda, 0xac, 0x2e, 0x4c, 0xcf, 0x7a, 0x34,
+	0x9a, 0xeb, 0x4b, 0x5d, 0xa5, 0x4e, 0xff, 0xce, 0xd8, 0xf7, 0x9b, 0xfe,
+	0x9c, 0x5d, 0x18, 0xff, 0x00, 0x3a, 0x85, 0x27, 0xe2, 0xf5, 0xe9, 0x66,
+	0x35, 0xd5, 0x41, 0xac, 0x53, 0x24, 0x2c, 0x18, 0xec, 0x3b, 0x04, 0xba,
+	0xea, 0xdf, 0x47, 0x13, 0x15, 0x9d, 0xd7, 0x99, 0x6e, 0x61, 0xb1, 0xc5,
+	0x6b, 0x58, 0xce, 0xbc, 0x46, 0xa2, 0x9b, 0x49, 0xd8, 0xe5, 0x9e, 0x3d,
+	0x7e, 0xbd, 0xf8, 0xf8, 0x10, 0xe3, 0xda, 0x0d, 0x99, 0x42, 0xbf, 0x50,
+	0xdb, 0x94, 0x83, 0xbe, 0x59, 0xae, 0x4d, 0xa7, 0xf9, 0xde, 0x23, 0xef,
+	0xeb, 0x5a, 0xa8, 0x1f, 0x1f, 0xd7, 0xb5, 0xe7, 0xb0, 0xf6, 0x2d, 0xf6,
+	0xab, 0x90, 0x75, 0xe0, 0x23, 0xbe, 0x41, 0x6f, 0xcd, 0x55, 0xb3, 0xfc,
+	0xcd, 0xa3, 0x35, 0x21, 0xa0, 0x16, 0x3f, 0x4e, 0x6f, 0xcf, 0x3d, 0x4b,
+	0xbf, 0x9c, 0x65, 0xdd, 0x31, 0x68, 0x14, 0xfa, 0x74, 0x94, 0xe4, 0xec,
+	0x69, 0x1a, 0x50, 0xaf, 0xfb, 0xb5, 0x8d, 0x9e, 0xf3, 0x6b, 0x3a, 0x33,
+	0x4b, 0xc5, 0xc6, 0x40, 0xea, 0x1a, 0xfa, 0xca, 0x93, 0xba, 0xb6, 0x8e,
+	0xdc, 0xa3, 0xd0, 0xfc, 0x80, 0xef, 0x6c, 0xb2, 0x35, 0xd8, 0xde, 0x22,
+	0x6a, 0x9b, 0xb7, 0x9d, 0xbb, 0xe9, 0x2c, 0xd7, 0x56, 0x81, 0xff, 0x5e,
+	0x33, 0x50, 0x63, 0xac, 0xaa, 0xa1, 0x0e, 0x31, 0x70, 0x9d, 0xc1, 0xf1,
+	0x07, 0x4f, 0x37, 0x06, 0x9f, 0xb2, 0x1f, 0x7c, 0x67, 0xd9, 0x42, 0xfe,
+	0xab, 0xfc, 0x8d, 0x0a, 0xf2, 0x5f, 0x5d, 0xfe, 0x40, 0xeb, 0x65, 0x3f,
+	0x6b, 0x80, 0x96, 0x41, 0x3a, 0x33, 0xcf, 0xf2, 0x47, 0xec, 0xf5, 0xed,
+	0x34, 0x0d, 0xfe, 0x72, 0x7c, 0x19, 0xa4, 0x5f, 0x2d, 0x15, 0xfd, 0xfb,
+	0x6b, 0x1b, 0xb9, 0xd6, 0x11, 0x67, 0x12, 0xf5, 0xfa, 0x77, 0x40, 0x2f,
+	0xce, 0x1e, 0xda, 0x8d, 0xa7, 0x0a, 0x9b, 0xdc, 0x72, 0x9e, 0x23, 0x07,
+	0x79, 0xce, 0xde, 0x2d, 0xe6, 0x39, 0x7b, 0xb7, 0x92, 0xe7, 0xc8, 0x9d,
+	0xe0, 0xab, 0xd6, 0xbb, 0x65, 0xdc, 0xa4, 0x00, 0xb7, 0x03, 0x5b, 0xc4,
+	0xed, 0xc0, 0x56, 0x70, 0x93, 0x3a, 0xcd, 0xbf, 0x40, 0x8c, 0x35, 0x10,
+	0xdb, 0xe0, 0xd7, 0x86, 0xfa, 0x59, 0x7f, 0x80, 0xa3, 0x8f, 0xeb, 0xef,
+	0x8b, 0xa7, 0x18, 0xe0, 0xf9, 0xd8, 0x16, 0xf1, 0x7c, 0x6c, 0x2b, 0x78,
+	0x8a, 0x9d, 0x26, 0xe3, 0x28, 0xc3, 0xd7, 0x70, 0x6d, 0x83, 0xd8, 0x3c,
+	0x24, 0x87, 0xba, 0x2e, 0x87, 0x75, 0x0e, 0x03, 0x7c, 0x50, 0xaf, 0x46,
+	0x4b, 0x4c, 0xcb, 0x46, 0xdf, 0x9d, 0x3a, 0x4b, 0x32, 0x5b, 0xa5, 0x4a,
+	0x83, 0xef, 0x95, 0xfb, 0xb0, 0x0f, 0xf7, 0xf1, 0x37, 0x2a, 0x8b, 0x64,
+	0xc4, 0xf7, 0xe7, 0x9a, 0x77, 0xa7, 0xf5, 0x2a, 0x68, 0x9d, 0x0a, 0x69,
+	0xad, 0xf8, 0xb9, 0xe0, 0xbe, 0x4d, 0xb9, 0x60, 0x40, 0xe3, 0x08, 0x68,
+	0x2c, 0x86, 0x34, 0x3e, 0xdd, 0x60, 0xda, 0xf6, 0xf9, 0xb4, 0x2d, 0x6d,
+	0xa2, 0x6d, 0xe4, 0x9e, 0xf9, 0x1f, 0xe3, 0x81, 0x5a, 0x1a, 0xb9, 0xd7,
+	0x6b, 0x4d, 0xd4, 0xd2, 0x4d, 0xd4, 0xd2, 0xd0, 0xf7, 0x57, 0x9b, 0xa8,
+	0xa5, 0x9b, 0xa8, 0xa5, 0x61, 0x07, 0xaf, 0xc0, 0x56, 0x82, 0x3b, 0xdc,
+	0x12, 0x71, 0x0d, 0xee, 0xd7, 0xe3, 0x14, 0xe4, 0x39, 0x05, 0xc4, 0xf0,
+	0xa3, 0xc8, 0xf1, 0xd8, 0x6e, 0x4f, 0x13, 0xc7, 0x04, 0x3d, 0x87, 0x9a,
+	0x2f, 0x5b, 0x25, 0x33, 0x5e, 0x9c, 0x1f, 0x50, 0x97, 0x02, 0xfb, 0xd6,
+	0x5a, 0xc4, 0x71, 0x70, 0x20, 0x85, 0x08, 0xa9, 0xb2, 0x5f, 0xb0, 0x73,
+	0x4c, 0xe7, 0x76, 0xf0, 0x10, 0xbe, 0xdb, 0x60, 0x1f, 0xc6, 0xbe, 0xb4,
+	0x4e, 0x0b, 0x8d, 0xf0, 0x1b, 0x9a, 0xcc, 0xfd, 0xfc, 0xce, 0x31, 0xb7,
+	0xcf, 0xf7, 0x69, 0x76, 0xb6, 0x0f, 0x71, 0x80, 0xfb, 0x15, 0xf8, 0x35,
+	0xe8, 0xca, 0x52, 0x1b, 0x17, 0x19, 0xeb, 0x55, 0xaa, 0xcf, 0x07, 0x31,
+	0x7c, 0xca, 0xe0, 0x38, 0x87, 0xf8, 0xbe, 0xc4, 0xdf, 0xb0, 0x10, 0xeb,
+	0x97, 0xae, 0x68, 0x32, 0x6a, 0xc7, 0x3a, 0x7f, 0xa3, 0x1d, 0xec, 0xc3,
+	0xf9, 0x1d, 0xfe, 0x1d, 0xed, 0x51, 0xff, 0xae, 0xcd, 0xa0, 0x23, 0xad,
+	0x80, 0x16, 0xdb, 0xc8, 0xd0, 0xc8, 0x2c, 0xdf, 0x35, 0x51, 0x8f, 0x68,
+	0xca, 0x54, 0x75, 0xf8, 0x7e, 0x68, 0xe3, 0xbb, 0x49, 0x76, 0x91, 0xeb,
+	0x4f, 0x23, 0xb8, 0xff, 0x3c, 0xed, 0xbc, 0xc9, 0xf7, 0x9f, 0xe1, 0x3a,
+	0x8d, 0xde, 0x70, 0x33, 0x34, 0x8e, 0xf8, 0x5a, 0x6c, 0x68, 0xf0, 0x6f,
+	0xbe, 0x3c, 0x39, 0xa7, 0xad, 0xc6, 0x42, 0x99, 0x8e, 0x84, 0x32, 0xad,
+	0x34, 0xd6, 0x80, 0xdf, 0x0d, 0xef, 0x8f, 0x43, 0x99, 0xee, 0x3a, 0x47,
+	0xda, 0xd5, 0x1c, 0xcb, 0x95, 0x65, 0x19, 0xc8, 0x75, 0x7c, 0xb1, 0x24,
+	0x14, 0x21, 0xd3, 0x51, 0x5f, 0xa6, 0x32, 0xc7, 0x05, 0xec, 0x95, 0x83,
+	0xfc, 0xd9, 0x8f, 0xe1, 0xe9, 0xb0, 0x8c, 0xb9, 0xde, 0xe0, 0x58, 0x98,
+	0xa4, 0x4b, 0x9b, 0xe4, 0x5c, 0xbc, 0xa7, 0x0e, 0xe7, 0xa9, 0xff, 0x9c,
+	0x16, 0xde, 0x9b, 0x66, 0x21, 0xc7, 0x76, 0x2e, 0xf6, 0x23, 0x81, 0x8c,
+	0xf6, 0x9d, 0x6e, 0xbb, 0xef, 0xe5, 0x4d, 0x7d, 0xed, 0x67, 0x9b, 0x56,
+	0xc4, 0xb7, 0x0d, 0xde, 0xf3, 0x1d, 0xe4, 0x9d, 0x7e, 0xc9, 0x1f, 0x53,
+	0x31, 0xd6, 0x4b, 0x85, 0x25, 0x83, 0xac, 0x16, 0xcf, 0x91, 0x49, 0x34,
+	0xda, 0x72, 0xea, 0xa4, 0xf5, 0x30, 0xc6, 0x2d, 0x34, 0x3c, 0xef, 0xa7,
+	0xd0, 0x9d, 0x8b, 0x5c, 0x77, 0x3b, 0xbf, 0xf1, 0xd6, 0x93, 0xc8, 0x21,
+	0x37, 0xce, 0xfc, 0xe6, 0xfd, 0xd4, 0xa5, 0xab, 0x88, 0x09, 0x74, 0xc6,
+	0x09, 0x51, 0x22, 0x1e, 0xe7, 0x3e, 0xfe, 0x06, 0xef, 0x79, 0x17, 0x8d,
+	0x3b, 0x78, 0x75, 0x99, 0xc7, 0x69, 0xdf, 0x39, 0xf6, 0xff, 0x3f, 0xd0,
+	0x2e, 0x1a, 0xd6, 0x9e, 0x38, 0xf2, 0xe7, 0xeb, 0xc4, 0xb1, 0x4f, 0x4e,
+	0x14, 0x9b, 0xba, 0x7a, 0x09, 0x6b, 0x8b, 0x8e, 0xc2, 0xdf, 0xd6, 0xf9,
+	0xfb, 0xa8, 0x76, 0x89, 0xda, 0xf7, 0x65, 0x90, 0xa7, 0xa3, 0xf2, 0x77,
+	0x52, 0xb5, 0x8a, 0xd8, 0x52, 0x70, 0x92, 0x98, 0xaf, 0x62, 0x2e, 0xc7,
+	0x05, 0x8f, 0x14, 0xd8, 0x50, 0xc1, 0x49, 0x27, 0xc6, 0x9a, 0x9e, 0xa7,
+	0x7c, 0x5e, 0xa0, 0x87, 0x32, 0x29, 0x1a, 0x73, 0xf8, 0xfe, 0xf7, 0x9b,
+	0xf4, 0x36, 0xec, 0xac, 0x78, 0x9e, 0x6b, 0x26, 0xf6, 0x29, 0x78, 0x77,
+	0xf8, 0xbe, 0xea, 0x14, 0x3d, 0xb4, 0x47, 0xcf, 0x5e, 0x22, 0xe0, 0xb3,
+	0x42, 0xfd, 0x48, 0x72, 0x53, 0xc7, 0xfd, 0xef, 0x6d, 0x8c, 0x6b, 0x9a,
+	0x96, 0xc0, 0x1b, 0xa7, 0x99, 0xa4, 0x95, 0x66, 0x8a, 0x56, 0xa1, 0x1f,
+	0xdb, 0xcc, 0x32, 0x7d, 0x03, 0x78, 0x2b, 0x66, 0x95, 0x94, 0x8c, 0xb5,
+	0xaf, 0x0b, 0x78, 0x67, 0x05, 0x3d, 0x15, 0x17, 0x18, 0x77, 0x5d, 0x2d,
+	0x03, 0x6f, 0xd6, 0xd1, 0x51, 0xa7, 0x9b, 0x8e, 0x61, 0xed, 0x7e, 0xe4,
+	0x1f, 0xdf, 0x72, 0xa8, 0x2c, 0x99, 0x29, 0x3a, 0x80, 0xf3, 0x8e, 0x36,
+	0x38, 0x57, 0x3b, 0x02, 0x5f, 0x23, 0xd0, 0xa3, 0x19, 0x8f, 0x1e, 0xdd,
+	0xa3, 0x5b, 0x71, 0x01, 0x7b, 0xae, 0xb0, 0x9e, 0xa0, 0xdf, 0x09, 0xce,
+	0x8d, 0xad, 0xf8, 0xba, 0x08, 0x7f, 0xfa, 0x0c, 0x65, 0xce, 0xad, 0xe5,
+	0xa6, 0x90, 0x9f, 0x8f, 0x36, 0xe9, 0x8b, 0x31, 0x9c, 0xf7, 0x36, 0xf8,
+	0x34, 0xea, 0xc8, 0x02, 0xf3, 0xe9, 0x58, 0xc0, 0x27, 0x8c, 0xf1, 0xb7,
+	0x23, 0xce, 0xd1, 0xf8, 0xec, 0x13, 0x74, 0xb6, 0xc1, 0x77, 0xdd, 0x27,
+	0xe8, 0x4a, 0xe3, 0x11, 0xba, 0x98, 0xe3, 0x5c, 0x07, 0xfb, 0xf8, 0x67,
+	0xa0, 0xcf, 0x3f, 0xa3, 0x9b, 0x8e, 0xfb, 0x72, 0xfa, 0x3f, 0xc3, 0x06,
+	0xd0, 0x70, 0x4c, 0x57, 0x00, 0x00, 0x00 };
 
 static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 };
 static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 };
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 55d2367..8171cae 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1199,8 +1199,7 @@
 }
 
 #define BOND_INTERSECT_FEATURES \
-	(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
-	NETIF_F_TSO|NETIF_F_UFO)
+	(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
 
 /* 
  * Compute the common dev->feature set available to all slaves.  Some
@@ -1218,9 +1217,7 @@
 		features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
 
 	if ((features & NETIF_F_SG) && 
-	    !(features & (NETIF_F_IP_CSUM |
-			  NETIF_F_NO_CSUM |
-			  NETIF_F_HW_CSUM)))
+	    !(features & NETIF_F_ALL_CSUM))
 		features &= ~NETIF_F_SG;
 
 	/* 
@@ -4191,7 +4188,7 @@
 	 */
 	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
 
-	/* don't acquire bond device's xmit_lock when 
+	/* don't acquire bond device's netif_tx_lock when
 	 * transmitting */
 	bond_dev->features |= NETIF_F_LLTX;
 
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index ac48f75..565a54f 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -2915,8 +2915,7 @@
 	 */
 	static int ring; 
 
-	skb = skb_padto(skb, cp->min_frame_size);
-	if (!skb)
+	if (skb_padto(skb, cp->min_frame_size))
 		return 0;
 
 	/* XXX: we need some higher-level QoS hooks to steer packets to
@@ -4877,7 +4876,7 @@
 				  const struct pci_device_id *ent)
 {
 	static int cas_version_printed = 0;
-	unsigned long casreg_base, casreg_len;
+	unsigned long casreg_len;
 	struct net_device *dev;
 	struct cas *cp;
 	int i, err, pci_using_dac;
@@ -4972,7 +4971,6 @@
 		pci_using_dac = 0;
 	}
 
-	casreg_base = pci_resource_start(pdev, 0);
 	casreg_len = pci_resource_len(pdev, 0);
 
 	cp = netdev_priv(dev);
@@ -5024,7 +5022,7 @@
 	cp->timer_ticks = 0;
 
 	/* give us access to cassini registers */
-	cp->regs = ioremap(casreg_base, casreg_len);
+	cp->regs = pci_iomap(pdev, 0, casreg_len);
 	if (cp->regs == 0UL) {
 		printk(KERN_ERR PFX "Cannot map device registers, "
 		       "aborting.\n");
@@ -5123,7 +5121,7 @@
 		cas_shutdown(cp);
 	mutex_unlock(&cp->pm_mutex);
 
-	iounmap(cp->regs);
+	pci_iounmap(pdev, cp->regs);
 
 
 err_out_free_res:
@@ -5171,7 +5169,7 @@
 #endif
 	pci_free_consistent(pdev, sizeof(struct cas_init_block),
 			    cp->init_block, cp->block_dvma);
-	iounmap(cp->regs);
+	pci_iounmap(pdev, cp->regs);
 	free_netdev(dev);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 4391bf4..53efff6 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1418,7 +1418,7 @@
 	struct cpl_tx_pkt *cpl;
 
 #ifdef NETIF_F_TSO
-	if (skb_shinfo(skb)->tso_size) {
+	if (skb_shinfo(skb)->gso_size) {
 		int eth_type;
 		struct cpl_tx_pkt_lso *hdr;
 
@@ -1433,7 +1433,7 @@
 		hdr->ip_hdr_words = skb->nh.iph->ihl;
 		hdr->tcp_hdr_words = skb->h.th->doff;
 		hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
-						skb_shinfo(skb)->tso_size));
+						skb_shinfo(skb)->gso_size));
 		hdr->len = htonl(skb->len - sizeof(*hdr));
 		cpl = (struct cpl_tx_pkt *)hdr;
 		sge->stats.tx_lso_pkts++;
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index f130bda..d3d958e 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -885,8 +885,7 @@
 	len = skblen;
 	
 	if (len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		len = ETH_ZLEN;
 	}
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index 0941d40..e946c43d 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -938,11 +938,8 @@
 	if (skb->len < 1)
 		goto out;
 
-	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			goto out;
-	}
+	if (skb_padto(skb, ETH_ZLEN))
+		goto out;
 	
 	netif_stop_queue(dev);
 
diff --git a/drivers/net/dl2k.h b/drivers/net/dl2k.h
index 6e75482..5344920 100644
--- a/drivers/net/dl2k.h
+++ b/drivers/net/dl2k.h
@@ -683,11 +683,6 @@
 };
 
 /* The station address location in the EEPROM. */
-#ifdef MEM_MAPPING
-#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
-#else
-#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO  | PCI_ADDR0)
-#endif
 /* The struct pci_device_id consist of:
         vendor, device          Vendor and device ID to match (or PCI_ANY_ID)
         subvendor, subdevice    Subsystem vendor and device ID to match (or PCI_ANY_ID)
@@ -695,9 +690,10 @@
         class_mask              of the class are honored during the comparison.
         driver_data             Data private to the driver.
 */
-static struct pci_device_id rio_pci_tbl[] = {
-	{0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0,}
+
+static const struct pci_device_id rio_pci_tbl[] = {
+	{0x1186, 0x4000, PCI_ANY_ID, PCI_ANY_ID, },
+	{ }
 };
 MODULE_DEVICE_TABLE (pci, rio_pci_tbl);
 #define TX_TIMEOUT  (4*HZ)
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 24996da..7965a9b 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -410,10 +410,7 @@
 	if (pdev->num_resources < 2) {
 		ret = -ENODEV;
 		goto out;
-	}
-
-	switch (pdev->num_resources) {
-	case 2:
+	} else if (pdev->num_resources == 2) {
 		base = pdev->resource[0].start;
 
 		if (!request_mem_region(base, 4, ndev->name)) {
@@ -423,17 +420,16 @@
 
 		ndev->base_addr = base;
 		ndev->irq = pdev->resource[1].start;
-		db->io_addr = (void *)base;
-		db->io_data = (void *)(base + 4);
+		db->io_addr = (void __iomem *)base;
+		db->io_data = (void __iomem *)(base + 4);
 
-		break;
-
-	case 3:
+	} else {
 		db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 		db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 
-		if (db->addr_res == NULL || db->data_res == NULL) {
+		if (db->addr_res == NULL || db->data_res == NULL ||
+		    db->irq_res == NULL) {
 			printk(KERN_ERR PFX "insufficient resources\n");
 			ret = -ENOENT;
 			goto out;
@@ -482,7 +478,6 @@
 
 		/* ensure at least we have a default set of IO routines */
 		dm9000_set_io(db, iosize);
-
 	}
 
 	/* check to see if anything is being over-ridden */
@@ -564,6 +559,13 @@
 	for (i = 0; i < 6; i++)
 		ndev->dev_addr[i] = db->srom[i];
 
+	if (!is_valid_ether_addr(ndev->dev_addr)) {
+		/* try reading from mac */
+
+		for (i = 0; i < 6; i++)
+			ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
+	}
+
 	if (!is_valid_ether_addr(ndev->dev_addr))
 		printk("%s: Invalid ethernet MAC address.  Please "
 		       "set using ifconfig\n", ndev->name);
@@ -663,7 +665,6 @@
 	db->tx_pkt_cnt = 0;
 	db->queue_pkt_len = 0;
 	dev->trans_start = 0;
-	spin_lock_init(&db->lock);
 }
 
 /*
@@ -767,7 +768,7 @@
  * receive the packet to upper layer, free the transmitted packet
  */
 
-void
+static void
 dm9000_tx_done(struct net_device *dev, board_info_t * db)
 {
 	int tx_status = ior(db, DM9000_NSR);	/* Got TX status */
@@ -1187,13 +1188,14 @@
 }
 
 static struct platform_driver dm9000_driver = {
+	.driver	= {
+		.name    = "dm9000",
+		.owner	 = THIS_MODULE,
+	},
 	.probe   = dm9000_probe,
 	.remove  = dm9000_drv_remove,
 	.suspend = dm9000_drv_suspend,
 	.resume  = dm9000_drv_resume,
-	.driver	= {
-		.name	= "dm9000",
-	},
 };
 
 static int __init
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 31ac001..f37170c 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2780,6 +2780,80 @@
 		DPRINTK(PROBE,ERR, "Error enabling wake\n");
 }
 
+/* ------------------ PCI Error Recovery infrastructure  -------------- */
+/**
+ * e100_io_error_detected - called when PCI error is detected.
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ */
+static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+
+	/* Similar to calling e100_down(), but avoids adpater I/O. */
+	netdev->stop(netdev);
+
+	/* Detach; put netif into state similar to hotplug unplug. */
+	netif_poll_enable(netdev);
+	netif_device_detach(netdev);
+
+	/* Request a slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * e100_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch.
+ */
+static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev_priv(netdev);
+
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR "e100: Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_set_master(pdev);
+
+	/* Only one device per card can do a reset */
+	if (0 != PCI_FUNC(pdev->devfn))
+		return PCI_ERS_RESULT_RECOVERED;
+	e100_hw_reset(nic);
+	e100_phy_init(nic);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * e100_io_resume - resume normal operations
+ * @pdev: Pointer to PCI device
+ *
+ * Resume normal operations after an error recovery
+ * sequence has been completed.
+ */
+static void e100_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct nic *nic = netdev_priv(netdev);
+
+	/* ack any pending wake events, disable PME */
+	pci_enable_wake(pdev, 0, 0);
+
+	netif_device_attach(netdev);
+	if (netif_running(netdev)) {
+		e100_open(netdev);
+		mod_timer(&nic->watchdog, jiffies);
+	}
+}
+
+static struct pci_error_handlers e100_err_handler = {
+	.error_detected = e100_io_error_detected,
+	.slot_reset = e100_io_slot_reset,
+	.resume = e100_io_resume,
+};
 
 static struct pci_driver e100_driver = {
 	.name =         DRV_NAME,
@@ -2791,6 +2865,7 @@
 	.resume =       e100_resume,
 #endif
 	.shutdown =     e100_shutdown,
+	.err_handler = &e100_err_handler,
 };
 
 static int __init e100_init_module(void)
diff --git a/drivers/net/e1000/Makefile b/drivers/net/e1000/Makefile
index ca9f895..5dea2b7 100644
--- a/drivers/net/e1000/Makefile
+++ b/drivers/net/e1000/Makefile
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # 
-# Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved.
+# Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
 # 
 # This program is free software; you can redistribute it and/or modify it 
 # under the terms of the GNU General Public License as published by the Free 
@@ -22,6 +22,7 @@
 # 
 # Contact Information:
 # Linux NICS <linux.nics@intel.com>
+# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
 # Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 #
 ################################################################################
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 281de41..2bc34fb 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -114,6 +115,8 @@
 /* Supported Rx Buffer Sizes */
 #define E1000_RXBUFFER_128   128    /* Used for packet split */
 #define E1000_RXBUFFER_256   256    /* Used for packet split */
+#define E1000_RXBUFFER_512   512
+#define E1000_RXBUFFER_1024  1024
 #define E1000_RXBUFFER_2048  2048
 #define E1000_RXBUFFER_4096  4096
 #define E1000_RXBUFFER_8192  8192
@@ -334,7 +337,6 @@
 	boolean_t have_msi;
 #endif
 	/* to not mess up cache alignment, always add to the bottom */
-	boolean_t txb2b;
 #ifdef NETIF_F_TSO
 	boolean_t tso_force;
 #endif
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index d1c705b..6ed7f59 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -864,8 +865,8 @@
 e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
 {
 	struct net_device *netdev = adapter->netdev;
- 	uint32_t mask, i=0, shared_int = TRUE;
- 	uint32_t irq = adapter->pdev->irq;
+	uint32_t mask, i=0, shared_int = TRUE;
+	uint32_t irq = adapter->pdev->irq;
 
 	*data = 0;
 
@@ -891,22 +892,22 @@
 		/* Interrupt to test */
 		mask = 1 << i;
 
- 		if (!shared_int) {
- 			/* Disable the interrupt to be reported in
- 			 * the cause register and then force the same
- 			 * interrupt and see if one gets posted.  If
- 			 * an interrupt was posted to the bus, the
- 			 * test failed.
- 			 */
- 			adapter->test_icr = 0;
- 			E1000_WRITE_REG(&adapter->hw, IMC, mask);
- 			E1000_WRITE_REG(&adapter->hw, ICS, mask);
- 			msec_delay(10);
+		if (!shared_int) {
+			/* Disable the interrupt to be reported in
+			 * the cause register and then force the same
+			 * interrupt and see if one gets posted.  If
+			 * an interrupt was posted to the bus, the
+			 * test failed.
+			 */
+			adapter->test_icr = 0;
+			E1000_WRITE_REG(&adapter->hw, IMC, mask);
+			E1000_WRITE_REG(&adapter->hw, ICS, mask);
+			msec_delay(10);
 
- 			if (adapter->test_icr & mask) {
- 				*data = 3;
- 				break;
- 			}
+			if (adapter->test_icr & mask) {
+				*data = 3;
+				break;
+			}
 		}
 
 		/* Enable the interrupt to be reported in
@@ -925,7 +926,7 @@
 			break;
 		}
 
- 		if (!shared_int) {
+		if (!shared_int) {
 			/* Disable the other interrupts to be reported in
 			 * the cause register and then force the other
 			 * interrupts and see if any get posted.  If
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 523c2c9..3959039 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -764,7 +765,7 @@
     }
 
     if (hw->mac_type == e1000_82573) {
-        e1000_enable_tx_pkt_filtering(hw); 
+        e1000_enable_tx_pkt_filtering(hw);
     }
 
     switch (hw->mac_type) {
@@ -860,7 +861,7 @@
 
     if(eeprom_data != EEPROM_RESERVED_WORD) {
         /* Adjust SERDES output amplitude only. */
-        eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; 
+        eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
         ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
         if(ret_val)
             return ret_val;
@@ -1227,7 +1228,7 @@
 
     if (hw->phy_reset_disable)
         return E1000_SUCCESS;
-    
+
     ret_val = e1000_phy_reset(hw);
     if (ret_val) {
         DEBUGOUT("Error Resetting the PHY\n");
@@ -1369,7 +1370,7 @@
     DEBUGFUNC("e1000_copper_link_ggp_setup");
 
     if(!hw->phy_reset_disable) {
-        
+
         /* Enable CRS on TX for half-duplex operation. */
         ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
                                      &phy_data);
@@ -1518,7 +1519,7 @@
 
     if(hw->phy_reset_disable)
         return E1000_SUCCESS;
-    
+
     /* Enable CRS on TX. This must be set for half-duplex operation. */
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
     if(ret_val)
@@ -1664,7 +1665,7 @@
 *      collision distance in the Transmit Control Register.
 *   2) Set up flow control on the MAC to that established with
 *      the link partner.
-*   3) Config DSP to improve Gigabit link quality for some PHY revisions.    
+*   3) Config DSP to improve Gigabit link quality for some PHY revisions.
 *
 * hw - Struct containing variables accessed by shared code
 ******************************************************************************/
@@ -1673,7 +1674,7 @@
 {
     int32_t ret_val;
     DEBUGFUNC("e1000_copper_link_postconfig");
-    
+
     if(hw->mac_type >= e1000_82544) {
         e1000_config_collision_dist(hw);
     } else {
@@ -1697,7 +1698,7 @@
             return ret_val;
         }
     }
-                
+
     return E1000_SUCCESS;
 }
 
@@ -1753,11 +1754,11 @@
     }
 
     if(hw->autoneg) {
-        /* Setup autoneg and flow control advertisement 
-          * and perform autonegotiation */   
+        /* Setup autoneg and flow control advertisement
+          * and perform autonegotiation */
         ret_val = e1000_copper_link_autoneg(hw);
         if(ret_val)
-            return ret_val;           
+            return ret_val;
     } else {
         /* PHY will be set to 10H, 10F, 100H,or 100F
           * depending on value from forced_speed_duplex. */
@@ -1785,7 +1786,7 @@
             ret_val = e1000_copper_link_postconfig(hw);
             if(ret_val)
                 return ret_val;
-            
+
             DEBUGOUT("Valid link established!!!\n");
             return E1000_SUCCESS;
         }
@@ -1983,7 +1984,7 @@
 
     DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
 
-    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);    
+    ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
     if(ret_val)
         return ret_val;
 
@@ -2272,7 +2273,7 @@
 
     DEBUGFUNC("e1000_config_mac_to_phy");
 
-    /* 82544 or newer MAC, Auto Speed Detection takes care of 
+    /* 82544 or newer MAC, Auto Speed Detection takes care of
     * MAC speed/duplex configuration.*/
     if (hw->mac_type >= e1000_82544)
         return E1000_SUCCESS;
@@ -2291,9 +2292,9 @@
     if(ret_val)
         return ret_val;
 
-    if(phy_data & M88E1000_PSSR_DPLX) 
+    if(phy_data & M88E1000_PSSR_DPLX)
         ctrl |= E1000_CTRL_FD;
-    else 
+    else
         ctrl &= ~E1000_CTRL_FD;
 
     e1000_config_collision_dist(hw);
@@ -2492,10 +2493,10 @@
                  */
                 if(hw->original_fc == e1000_fc_full) {
                     hw->fc = e1000_fc_full;
-                    DEBUGOUT("Flow Control = FULL.\r\n");
+                    DEBUGOUT("Flow Control = FULL.\n");
                 } else {
                     hw->fc = e1000_fc_rx_pause;
-                    DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                    DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
                 }
             }
             /* For receiving PAUSE frames ONLY.
@@ -2511,7 +2512,7 @@
                     (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_tx_pause;
-                DEBUGOUT("Flow Control = TX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
             }
             /* For transmitting PAUSE frames ONLY.
              *
@@ -2526,7 +2527,7 @@
                     !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
                     (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
                 hw->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
             /* Per the IEEE spec, at this point flow control should be
              * disabled.  However, we want to consider that we could
@@ -2552,10 +2553,10 @@
                      hw->original_fc == e1000_fc_tx_pause) ||
                     hw->fc_strict_ieee) {
                 hw->fc = e1000_fc_none;
-                DEBUGOUT("Flow Control = NONE.\r\n");
+                DEBUGOUT("Flow Control = NONE.\n");
             } else {
                 hw->fc = e1000_fc_rx_pause;
-                DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n");
+                DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
             }
 
             /* Now we need to do one last check...  If we auto-
@@ -2580,7 +2581,7 @@
                 return ret_val;
             }
         } else {
-            DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n");
+            DEBUGOUT("Copper PHY and Auto Neg has not completed.\n");
         }
     }
     return E1000_SUCCESS;
@@ -2763,7 +2764,7 @@
             hw->autoneg_failed = 1;
             return 0;
         }
-        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\r\n");
+        DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
 
         /* Disable auto-negotiation in the TXCW register */
         E1000_WRITE_REG(hw, TXCW, (hw->txcw & ~E1000_TXCW_ANE));
@@ -2788,7 +2789,7 @@
     else if(((hw->media_type == e1000_media_type_fiber) ||
              (hw->media_type == e1000_media_type_internal_serdes)) &&
             (ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\r\n");
+        DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
         E1000_WRITE_REG(hw, TXCW, hw->txcw);
         E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -2851,13 +2852,13 @@
 
         if(status & E1000_STATUS_FD) {
             *duplex = FULL_DUPLEX;
-            DEBUGOUT("Full Duplex\r\n");
+            DEBUGOUT("Full Duplex\n");
         } else {
             *duplex = HALF_DUPLEX;
-            DEBUGOUT(" Half Duplex\r\n");
+            DEBUGOUT(" Half Duplex\n");
         }
     } else {
-        DEBUGOUT("1000 Mbs, Full Duplex\r\n");
+        DEBUGOUT("1000 Mbs, Full Duplex\n");
         *speed = SPEED_1000;
         *duplex = FULL_DUPLEX;
     }
@@ -2883,7 +2884,7 @@
         }
     }
 
-    if ((hw->mac_type == e1000_80003es2lan) && 
+    if ((hw->mac_type == e1000_80003es2lan) &&
         (hw->media_type == e1000_media_type_copper)) {
         if (*speed == SPEED_1000)
             ret_val = e1000_configure_kmrn_for_1000(hw);
@@ -3159,7 +3160,7 @@
     if (e1000_swfw_sync_acquire(hw, swfw))
         return -E1000_ERR_SWFW_SYNC;
 
-    if((hw->phy_type == e1000_phy_igp || 
+    if((hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3298,7 +3299,7 @@
     if (e1000_swfw_sync_acquire(hw, swfw))
         return -E1000_ERR_SWFW_SYNC;
 
-    if((hw->phy_type == e1000_phy_igp || 
+    if((hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) &&
        (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
         ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
@@ -3496,22 +3497,22 @@
         }
         /* Read the device control register and assert the E1000_CTRL_PHY_RST
          * bit. Then, take it out of reset.
-         * For pre-e1000_82571 hardware, we delay for 10ms between the assert 
+         * For pre-e1000_82571 hardware, we delay for 10ms between the assert
          * and deassert.  For e1000_82571 hardware and later, we instead delay
          * for 50us between and 10ms after the deassertion.
          */
         ctrl = E1000_READ_REG(hw, CTRL);
         E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PHY_RST);
         E1000_WRITE_FLUSH(hw);
-        
-        if (hw->mac_type < e1000_82571) 
+
+        if (hw->mac_type < e1000_82571)
             msec_delay(10);
         else
             udelay(100);
-        
+
         E1000_WRITE_REG(hw, CTRL, ctrl);
         E1000_WRITE_FLUSH(hw);
-        
+
         if (hw->mac_type >= e1000_82571)
             msec_delay(10);
         e1000_swfw_sync_release(hw, swfw);
@@ -3815,7 +3816,7 @@
     /* Check polarity status */
     ret_val = e1000_check_polarity(hw, &polarity);
     if(ret_val)
-        return ret_val; 
+        return ret_val;
     phy_info->cable_polarity = polarity;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
@@ -4540,14 +4541,14 @@
 
         E1000_WRITE_REG(hw, EERD, eerd);
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
-        
+
         if(error) {
             break;
         }
         data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
-      
+
     }
-    
+
     return error;
 }
 
@@ -4573,24 +4574,24 @@
         return -E1000_ERR_SWFW_SYNC;
 
     for (i = 0; i < words; i++) {
-        register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) | 
-                         ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) | 
+        register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) |
+                         ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) |
                          E1000_EEPROM_RW_REG_START;
 
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
         if(error) {
             break;
-        }       
+        }
 
         E1000_WRITE_REG(hw, EEWR, register_value);
-        
+
         error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
-        
+
         if(error) {
             break;
-        }       
+        }
     }
-    
+
     e1000_swfw_sync_release(hw, E1000_SWFW_EEP_SM);
     return error;
 }
@@ -4610,7 +4611,7 @@
     for(i = 0; i < attempts; i++) {
         if(eerd == E1000_EEPROM_POLL_READ)
             reg = E1000_READ_REG(hw, EERD);
-        else 
+        else
             reg = E1000_READ_REG(hw, EEWR);
 
         if(reg & E1000_EEPROM_RW_REG_DONE) {
@@ -5135,7 +5136,7 @@
     uint32_t i;
     uint32_t num_rar_entry;
     uint32_t num_mta_entry;
-    
+
     DEBUGFUNC("e1000_mc_addr_list_update");
 
     /* Set the new number of MC addresses that we are being requested to use. */
@@ -6240,7 +6241,7 @@
  *                                1 - Downshift ocured.
  *
  * returns: - E1000_ERR_XXX
- *            E1000_SUCCESS 
+ *            E1000_SUCCESS
  *
  * For phy's older then IGP, this function reads the Downshift bit in the Phy
  * Specific Status register.  For IGP phy's, it reads the Downgrade bit in the
@@ -6255,7 +6256,7 @@
 
     DEBUGFUNC("e1000_check_downshift");
 
-    if(hw->phy_type == e1000_phy_igp || 
+    if(hw->phy_type == e1000_phy_igp ||
         hw->phy_type == e1000_phy_igp_2) {
         ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
                                      &phy_data);
@@ -6684,8 +6685,8 @@
 
 
     } else {
- 
-            phy_data |= IGP02E1000_PM_D0_LPLU;   
+
+            phy_data |= IGP02E1000_PM_D0_LPLU;
             ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
             if (ret_val)
                 return ret_val;
@@ -6777,7 +6778,7 @@
 e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
 {
     uint8_t i;
-    uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET; 
+    uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
     uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
 
     length = (length >> 2);
@@ -6796,7 +6797,7 @@
  * and also checks whether the previous command is completed.
  * It busy waits in case of previous command is not completed.
  *
- * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or 
+ * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or
  *            timeout
  *          - E1000_SUCCESS for success.
  ****************************************************************************/
@@ -6820,7 +6821,7 @@
         msec_delay_irq(1);
     }
 
-    if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { 
+    if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
         DEBUGOUT("Previous command timeout failed .\n");
         return -E1000_ERR_HOST_INTERFACE_COMMAND;
     }
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index 150e45e..467c9ed 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
@@ -374,7 +375,7 @@
 };
 #endif
 
-int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, 
+int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
 							uint16_t length);
 boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
 boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
@@ -1801,7 +1802,7 @@
  *       value2 = [0..64512],    default=4096
  *       value3 = [0..64512],    default=0
  */
-    
+
 #define E1000_PSRCTL_BSIZE0_MASK   0x0000007F
 #define E1000_PSRCTL_BSIZE1_MASK   0x00003F00
 #define E1000_PSRCTL_BSIZE2_MASK   0x003F0000
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 97e71a4..32b7d44 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -22,51 +22,13 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
 
 #include "e1000.h"
 
-/* Change Log
- * 7.0.33      3-Feb-2006
- *   o Added another fix for the pass false carrier bit
- * 7.0.32      24-Jan-2006
- *   o Need to rebuild with noew version number for the pass false carrier 
- *     fix in e1000_hw.c
- * 7.0.30      18-Jan-2006
- *   o fixup for tso workaround to disable it for pci-x
- *   o fix mem leak on 82542
- *   o fixes for 10 Mb/s connections and incorrect stats
- * 7.0.28      01/06/2006
- *   o hardware workaround to only set "speed mode" bit for 1G link.
- * 7.0.26      12/23/2005
- *   o wake on lan support modified for device ID 10B5
- *   o fix dhcp + vlan issue not making it to the iAMT firmware
- * 7.0.24      12/9/2005
- *   o New hardware support for the Gigabit NIC embedded in the south bridge
- *   o Fixes to the recycling logic (skb->tail) from IBM LTC
- * 6.3.9	12/16/2005
- *   o incorporate fix for recycled skbs from IBM LTC
- * 6.3.7	11/18/2005
- *   o Honor eeprom setting for enabling/disabling Wake On Lan
- * 6.3.5 	11/17/2005
- *   o Fix memory leak in rx ring handling for PCI Express adapters
- * 6.3.4	11/8/05
- *   o Patch from Jesper Juhl to remove redundant NULL checks for kfree
- * 6.3.2	9/20/05
- *   o Render logic that sets/resets DRV_LOAD as inline functions to 
- *     avoid code replication. If f/w is AMT then set DRV_LOAD only when
- *     network interface is open.
- *   o Handle DRV_LOAD set/reset in cases where AMT uses VLANs.
- *   o Adjust PBA partioning for Jumbo frames using MTU size and not
- *     rx_buffer_len
- * 6.3.1	9/19/05
- *   o Use adapter->tx_timeout_factor in Tx Hung Detect logic 
- *      (e1000_clean_tx_irq)
- *   o Support for 8086:10B5 device (Quad Port)
- */
-
 char e1000_driver_name[] = "e1000";
 static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
 #ifndef CONFIG_E1000_NAPI
@@ -74,9 +36,9 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION "7.0.33-k2"DRIVERNAPI
+#define DRV_VERSION "7.0.38-k4"DRIVERNAPI
 char e1000_driver_version[] = DRV_VERSION;
-static char e1000_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
  *
@@ -208,8 +170,8 @@
 static void e1000_tx_timeout(struct net_device *dev);
 static void e1000_reset_task(struct net_device *dev);
 static void e1000_smartspeed(struct e1000_adapter *adapter);
-static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
-					      struct sk_buff *skb);
+static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter,
+                                       struct sk_buff *skb);
 
 static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp);
 static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
@@ -227,6 +189,16 @@
 static void e1000_netpoll (struct net_device *netdev);
 #endif
 
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
+                     pci_channel_state_t state);
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev);
+static void e1000_io_resume(struct pci_dev *pdev);
+
+static struct pci_error_handlers e1000_err_handler = {
+	.error_detected = e1000_io_error_detected,
+	.slot_reset = e1000_io_slot_reset,
+	.resume = e1000_io_resume,
+};
 
 static struct pci_driver e1000_driver = {
 	.name     = e1000_driver_name,
@@ -238,7 +210,8 @@
 	.suspend  = e1000_suspend,
 	.resume   = e1000_resume,
 #endif
-	.shutdown = e1000_shutdown
+	.shutdown = e1000_shutdown,
+	.err_handler = &e1000_err_handler
 };
 
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -293,7 +266,7 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_disable(struct e1000_adapter *adapter)
 {
 	atomic_inc(&adapter->irq_sem);
@@ -307,7 +280,7 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 e1000_irq_enable(struct e1000_adapter *adapter)
 {
 	if (likely(atomic_dec_and_test(&adapter->irq_sem))) {
@@ -348,10 +321,10 @@
  * For ASF and Pass Through versions of f/w this means that the
  * driver is no longer loaded. For AMT version (only with 82573) i
  * of the f/w this means that the netowrk i/f is closed.
- * 
+ *
  **/
 
-static inline void 
+static void
 e1000_release_hw_control(struct e1000_adapter *adapter)
 {
 	uint32_t ctrl_ext;
@@ -361,6 +334,7 @@
 	switch (adapter->hw.mac_type) {
 	case e1000_82571:
 	case e1000_82572:
+	case e1000_80003es2lan:
 		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
 		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
 				ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD);
@@ -379,13 +353,13 @@
  * @adapter: address of board private structure
  *
  * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit.
- * For ASF and Pass Through versions of f/w this means that 
- * the driver is loaded. For AMT version (only with 82573) 
+ * For ASF and Pass Through versions of f/w this means that
+ * the driver is loaded. For AMT version (only with 82573)
  * of the f/w this means that the netowrk i/f is open.
- * 
+ *
  **/
 
-static inline void 
+static void
 e1000_get_hw_control(struct e1000_adapter *adapter)
 {
 	uint32_t ctrl_ext;
@@ -394,6 +368,7 @@
 	switch (adapter->hw.mac_type) {
 	case e1000_82571:
 	case e1000_82572:
+	case e1000_80003es2lan:
 		ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT);
 		E1000_WRITE_REG(&adapter->hw, CTRL_EXT,
 				ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
@@ -421,7 +396,7 @@
 		uint16_t mii_reg;
 		e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
 		if (mii_reg & MII_CR_POWER_DOWN)
-			e1000_phy_reset(&adapter->hw);
+			e1000_phy_hw_reset(&adapter->hw);
 	}
 
 	e1000_set_multi(netdev);
@@ -711,8 +686,8 @@
 		DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
 
 	/* if ksp3, indicate if it's port a being setup */
-	if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 && 
-			e1000_ksp3_port_a == 0) 
+	if (pdev->device == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 &&
+			e1000_ksp3_port_a == 0)
 		adapter->ksp3_port_a = 1;
 	e1000_ksp3_port_a++;
 	/* Reset for multiple KP3 adapters */
@@ -740,9 +715,9 @@
 	if (pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
- 	/* hard_start_xmit is safe against parallel locking */
- 	netdev->features |= NETIF_F_LLTX; 
- 
+	/* hard_start_xmit is safe against parallel locking */
+	netdev->features |= NETIF_F_LLTX;
+
 	adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
 
 	/* before reading the EEPROM, reset the controller to
@@ -972,8 +947,8 @@
 
 	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
-	adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-	adapter->rx_ps_bsize0 = E1000_RXBUFFER_256;
+	adapter->rx_buffer_len = MAXIMUM_ETHERNET_FRAME_SIZE;
+	adapter->rx_ps_bsize0 = E1000_RXBUFFER_128;
 	hw->max_frame_size = netdev->mtu +
 			     ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
 	hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
@@ -1181,7 +1156,7 @@
  * @start: address of beginning of memory
  * @len: length of memory
  **/
-static inline boolean_t
+static boolean_t
 e1000_check_64k_bound(struct e1000_adapter *adapter,
 		      void *start, unsigned long len)
 {
@@ -1599,14 +1574,21 @@
 		rctl |= E1000_RCTL_LPE;
 
 	/* Setup buffer sizes */
-	if (adapter->hw.mac_type >= e1000_82571) {
-		/* We can now specify buffers in 1K increments.
-		 * BSIZE and BSEX are ignored in this case. */
-		rctl |= adapter->rx_buffer_len << 0x11;
-	} else {
-		rctl &= ~E1000_RCTL_SZ_4096;
-		rctl |= E1000_RCTL_BSEX; 
-		switch (adapter->rx_buffer_len) {
+	rctl &= ~E1000_RCTL_SZ_4096;
+	rctl |= E1000_RCTL_BSEX;
+	switch (adapter->rx_buffer_len) {
+		case E1000_RXBUFFER_256:
+			rctl |= E1000_RCTL_SZ_256;
+			rctl &= ~E1000_RCTL_BSEX;
+			break;
+		case E1000_RXBUFFER_512:
+			rctl |= E1000_RCTL_SZ_512;
+			rctl &= ~E1000_RCTL_BSEX;
+			break;
+		case E1000_RXBUFFER_1024:
+			rctl |= E1000_RCTL_SZ_1024;
+			rctl &= ~E1000_RCTL_BSEX;
+			break;
 		case E1000_RXBUFFER_2048:
 		default:
 			rctl |= E1000_RCTL_SZ_2048;
@@ -1621,7 +1603,6 @@
 		case E1000_RXBUFFER_16384:
 			rctl |= E1000_RCTL_SZ_16384;
 			break;
-		}
 	}
 
 #ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT
@@ -1715,7 +1696,7 @@
 	if (hw->mac_type >= e1000_82571) {
 		ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
 		/* Reset delay timers after every interrupt */
-		ctrl_ext |= E1000_CTRL_EXT_CANC;
+		ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR;
 #ifdef CONFIG_E1000_NAPI
 		/* Auto-Mask interrupts upon ICR read. */
 		ctrl_ext |= E1000_CTRL_EXT_IAME;
@@ -1807,7 +1788,7 @@
 		e1000_free_tx_resources(adapter, &adapter->tx_ring[i]);
 }
 
-static inline void
+static void
 e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
 			struct e1000_buffer *buffer_info)
 {
@@ -2247,6 +2228,7 @@
 
 	if (link) {
 		if (!netif_carrier_ok(netdev)) {
+			boolean_t txb2b = 1;
 			e1000_get_speed_and_duplex(&adapter->hw,
 			                           &adapter->link_speed,
 			                           &adapter->link_duplex);
@@ -2260,23 +2242,22 @@
 			 * and adjust the timeout factor */
 			netdev->tx_queue_len = adapter->tx_queue_len;
 			adapter->tx_timeout_factor = 1;
-			adapter->txb2b = 1;
 			switch (adapter->link_speed) {
 			case SPEED_10:
-				adapter->txb2b = 0;
+				txb2b = 0;
 				netdev->tx_queue_len = 10;
 				adapter->tx_timeout_factor = 8;
 				break;
 			case SPEED_100:
-				adapter->txb2b = 0;
+				txb2b = 0;
 				netdev->tx_queue_len = 100;
 				/* maybe add some timeout factor ? */
 				break;
 			}
 
-			if ((adapter->hw.mac_type == e1000_82571 || 
+			if ((adapter->hw.mac_type == e1000_82571 ||
 			     adapter->hw.mac_type == e1000_82572) &&
-			    adapter->txb2b == 0) {
+			    txb2b == 0) {
 #define SPEED_MODE_BIT (1 << 21)
 				uint32_t tarc0;
 				tarc0 = E1000_READ_REG(&adapter->hw, TARC0);
@@ -2400,7 +2381,7 @@
 #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
-static inline int
+static int
 e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
           struct sk_buff *skb)
 {
@@ -2413,7 +2394,7 @@
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 	int err;
 
-	if (skb_shinfo(skb)->tso_size) {
+	if (skb_shinfo(skb)->gso_size) {
 		if (skb_header_cloned(skb)) {
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			if (err)
@@ -2421,8 +2402,8 @@
 		}
 
 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-		mss = skb_shinfo(skb)->tso_size;
-		if (skb->protocol == ntohs(ETH_P_IP)) {
+		mss = skb_shinfo(skb)->gso_size;
+		if (skb->protocol == htons(ETH_P_IP)) {
 			skb->nh.iph->tot_len = 0;
 			skb->nh.iph->check = 0;
 			skb->h.th->check =
@@ -2480,7 +2461,7 @@
 	return FALSE;
 }
 
-static inline boolean_t
+static boolean_t
 e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
               struct sk_buff *skb)
 {
@@ -2516,7 +2497,7 @@
 #define E1000_MAX_TXD_PWR	12
 #define E1000_MAX_DATA_PER_TXD	(1<<E1000_MAX_TXD_PWR)
 
-static inline int
+static int
 e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
              struct sk_buff *skb, unsigned int first, unsigned int max_per_txd,
              unsigned int nr_frags, unsigned int mss)
@@ -2538,7 +2519,7 @@
 		 * tso gets written back prematurely before the data is fully
 		 * DMA'd to the controller */
 		if (!skb->data_len && tx_ring->last_tx_tso &&
-		    !skb_shinfo(skb)->tso_size) {
+		    !skb_shinfo(skb)->gso_size) {
 			tx_ring->last_tx_tso = 0;
 			size -= 4;
 		}
@@ -2625,7 +2606,7 @@
 	return count;
 }
 
-static inline void
+static void
 e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring,
                int tx_flags, int count)
 {
@@ -2689,7 +2670,7 @@
 #define E1000_FIFO_HDR			0x10
 #define E1000_82547_PAD_LEN		0x3E0
 
-static inline int
+static int
 e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
 	uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head;
@@ -2716,7 +2697,7 @@
 }
 
 #define MINIMUM_DHCP_PACKET_SIZE 282
-static inline int
+static int
 e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
 	struct e1000_hw *hw =  &adapter->hw;
@@ -2764,7 +2745,7 @@
 	unsigned int nr_frags = 0;
 	unsigned int mss = 0;
 	int count = 0;
- 	int tso;
+	int tso;
 	unsigned int f;
 	len -= skb->data_len;
 
@@ -2776,8 +2757,8 @@
 	}
 
 #ifdef NETIF_F_TSO
-	mss = skb_shinfo(skb)->tso_size;
-	/* The controller does a simple calculation to 
+	mss = skb_shinfo(skb)->gso_size;
+	/* The controller does a simple calculation to
 	 * make sure there is enough room in the FIFO before
 	 * initiating the DMA for each buffer.  The calc is:
 	 * 4 = ceil(buffer len/mss).  To make sure we don't
@@ -2800,7 +2781,7 @@
 			case e1000_82573:
 				pull_size = min((unsigned int)4, skb->data_len);
 				if (!__pskb_pull_tail(skb, pull_size)) {
-					printk(KERN_ERR 
+					printk(KERN_ERR
 						"__pskb_pull_tail failed.\n");
 					dev_kfree_skb_any(skb);
 					return NETDEV_TX_OK;
@@ -2826,7 +2807,7 @@
 #ifdef NETIF_F_TSO
 	/* Controller Erratum workaround */
 	if (!skb->data_len && tx_ring->last_tx_tso &&
-	    !skb_shinfo(skb)->tso_size)
+	    !skb_shinfo(skb)->gso_size)
 		count++;
 #endif
 
@@ -2901,7 +2882,7 @@
 	/* Old method was to assume IPv4 packet by default if TSO was enabled.
 	 * 82571 hardware supports TSO capabilities for IPv6 as well...
 	 * no longer assume, we must. */
-	if (likely(skb->protocol == ntohs(ETH_P_IP)))
+	if (likely(skb->protocol == htons(ETH_P_IP)))
 		tx_flags |= E1000_TX_FLAGS_IPV4;
 
 	e1000_tx_queue(adapter, tx_ring, tx_flags,
@@ -2982,8 +2963,7 @@
 
 	/* Adapter-specific max frame size limits. */
 	switch (adapter->hw.mac_type) {
-	case e1000_82542_rev2_0:
-	case e1000_82542_rev2_1:
+	case e1000_undefined ... e1000_82542_rev2_1:
 		if (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
 			DPRINTK(PROBE, ERR, "Jumbo Frames not supported.\n");
 			return -EINVAL;
@@ -3017,27 +2997,32 @@
 		break;
 	}
 
+	/* NOTE: dev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+	 * means we reserve 2 more, this pushes us to allocate from the next
+	 * larger slab size
+	 * i.e. RXBUFFER_2048 --> size-4096 slab */
 
-	if (adapter->hw.mac_type > e1000_82547_rev_2) {
-		adapter->rx_buffer_len = max_frame;
-		E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
-	} else {
-		if(unlikely((adapter->hw.mac_type < e1000_82543) &&
-		   (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
-			DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
-					    "on 82542\n");
-			return -EINVAL;
-		} else {
-			if(max_frame <= E1000_RXBUFFER_2048)
-				adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-			else if(max_frame <= E1000_RXBUFFER_4096)
-				adapter->rx_buffer_len = E1000_RXBUFFER_4096;
-			else if(max_frame <= E1000_RXBUFFER_8192)
-				adapter->rx_buffer_len = E1000_RXBUFFER_8192;
-			else if(max_frame <= E1000_RXBUFFER_16384)
-				adapter->rx_buffer_len = E1000_RXBUFFER_16384;
-		}
-	}
+	if (max_frame <= E1000_RXBUFFER_256)
+		adapter->rx_buffer_len = E1000_RXBUFFER_256;
+	else if (max_frame <= E1000_RXBUFFER_512)
+		adapter->rx_buffer_len = E1000_RXBUFFER_512;
+	else if (max_frame <= E1000_RXBUFFER_1024)
+		adapter->rx_buffer_len = E1000_RXBUFFER_1024;
+	else if (max_frame <= E1000_RXBUFFER_2048)
+		adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+	else if (max_frame <= E1000_RXBUFFER_4096)
+		adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+	else if (max_frame <= E1000_RXBUFFER_8192)
+		adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+	else if (max_frame <= E1000_RXBUFFER_16384)
+		adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+
+	/* adjust allocation if LPE protects us, and we aren't using SBP */
+#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
+	if (!adapter->hw.tbi_compatibility_on &&
+	    ((max_frame == MAXIMUM_ETHERNET_FRAME_SIZE) ||
+	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE)))
+		adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 
 	netdev->mtu = new_mtu;
 
@@ -3060,11 +3045,21 @@
 e1000_update_stats(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
+	struct pci_dev *pdev = adapter->pdev;
 	unsigned long flags;
 	uint16_t phy_tmp;
 
 #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF
 
+	/*
+	 * Prevent stats update while adapter is being reset, or if the pci
+	 * connection is down.
+	 */
+	if (adapter->link_speed == 0)
+		return;
+	if (pdev->error_state && pdev->error_state != pci_channel_io_normal)
+		return;
+
 	spin_lock_irqsave(&adapter->stats_lock, flags);
 
 	/* these counters are modified from e1000_adjust_tbi_stats,
@@ -3165,7 +3160,6 @@
 		adapter->stats.crcerrs + adapter->stats.algnerrc +
 		adapter->stats.ruc + adapter->stats.roc +
 		adapter->stats.cexterr;
-	adapter->net_stats.rx_dropped = 0;
 	adapter->net_stats.rx_length_errors = adapter->stats.ruc +
 	                                      adapter->stats.roc;
 	adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
@@ -3391,13 +3385,15 @@
 
 	tx_ring->next_to_clean = i;
 
-	spin_lock(&tx_ring->tx_lock);
-
+#define TX_WAKE_THRESHOLD 32
 	if (unlikely(cleaned && netif_queue_stopped(netdev) &&
-		    netif_carrier_ok(netdev)))
-		netif_wake_queue(netdev);
-
-	spin_unlock(&tx_ring->tx_lock);
+	             netif_carrier_ok(netdev))) {
+		spin_lock(&tx_ring->tx_lock);
+		if (netif_queue_stopped(netdev) &&
+		    (E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))
+			netif_wake_queue(netdev);
+		spin_unlock(&tx_ring->tx_lock);
+	}
 
 	if (adapter->detect_tx_hung) {
 		/* Detect a transmit hang in hardware, this serializes the
@@ -3445,7 +3441,7 @@
  * @sk_buff:     socket buffer with received data
  **/
 
-static inline void
+static void
 e1000_rx_checksum(struct e1000_adapter *adapter,
 		  uint32_t status_err, uint32_t csum,
 		  struct sk_buff *skb)
@@ -3567,7 +3563,8 @@
 				                       flags);
 				length--;
 			} else {
-				dev_kfree_skb_irq(skb);
+				/* recycle */
+				buffer_info->skb = skb;
 				goto next_desc;
 			}
 		}
@@ -3675,6 +3672,7 @@
 	i = rx_ring->next_to_clean;
 	rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
 	staterr = le32_to_cpu(rx_desc->wb.middle.status_error);
+	buffer_info = &rx_ring->buffer_info[i];
 
 	while (staterr & E1000_RXD_STAT_DD) {
 		buffer_info = &rx_ring->buffer_info[i];
@@ -3733,9 +3731,9 @@
 
 		/* page alloc/put takes too long and effects small packet
 		 * throughput, so unsplit small packets and save the alloc/put*/
-		if (l1 && ((length + l1) < E1000_CB_LENGTH)) {
+		if (l1 && ((length + l1) <= adapter->rx_ps_bsize0)) {
 			u8 *vaddr;
-			/* there is no documentation about how to call 
+			/* there is no documentation about how to call
 			 * kmap_atomic, so we can't hold the mapping
 			 * very long */
 			pci_dma_sync_single_for_cpu(pdev,
@@ -4155,7 +4153,7 @@
 			spin_unlock_irqrestore(&adapter->stats_lock, flags);
 			return -EIO;
 		}
-		if (adapter->hw.phy_type == e1000_media_type_copper) {
+		if (adapter->hw.media_type == e1000_media_type_copper) {
 			switch (data->reg_num) {
 			case PHY_CTRL:
 				if (mii_reg & MII_CR_POWER_DOWN)
@@ -4514,21 +4512,13 @@
 
 		E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
 		E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
-		retval = pci_enable_wake(pdev, PCI_D3hot, 1);
-		if (retval)
-			DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-		retval = pci_enable_wake(pdev, PCI_D3cold, 1);
-		if (retval)
-			DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+		pci_enable_wake(pdev, PCI_D3hot, 1);
+		pci_enable_wake(pdev, PCI_D3cold, 1);
 	} else {
 		E1000_WRITE_REG(&adapter->hw, WUC, 0);
 		E1000_WRITE_REG(&adapter->hw, WUFC, 0);
-		retval = pci_enable_wake(pdev, PCI_D3hot, 0);
-		if (retval)
-			DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-		retval = pci_enable_wake(pdev, PCI_D3cold, 0);
-		if (retval)
-			DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		pci_enable_wake(pdev, PCI_D3cold, 0);
 	}
 
 	if (adapter->hw.mac_type >= e1000_82540 &&
@@ -4537,13 +4527,8 @@
 		if (manc & E1000_MANC_SMBUS_EN) {
 			manc |= E1000_MANC_ARP_EN;
 			E1000_WRITE_REG(&adapter->hw, MANC, manc);
-			retval = pci_enable_wake(pdev, PCI_D3hot, 1);
-			if (retval)
-				DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-			retval = pci_enable_wake(pdev, PCI_D3cold, 1);
-			if (retval)
-				DPRINTK(PROBE, ERR,
-				        "Error enabling D3 cold wake\n");
+			pci_enable_wake(pdev, PCI_D3hot, 1);
+			pci_enable_wake(pdev, PCI_D3cold, 1);
 		}
 	}
 
@@ -4553,9 +4538,7 @@
 
 	pci_disable_device(pdev);
 
-	retval = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-	if (retval)
-		DPRINTK(PROBE, ERR, "Error in setting power state\n");
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
 	return 0;
 }
@@ -4566,22 +4549,15 @@
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	int retval;
 	uint32_t manc, ret_val;
 
-	retval = pci_set_power_state(pdev, PCI_D0);
-	if (retval)
-		DPRINTK(PROBE, ERR, "Error in setting power state\n");
+	pci_set_power_state(pdev, PCI_D0);
 	e1000_pci_restore_state(adapter);
 	ret_val = pci_enable_device(pdev);
 	pci_set_master(pdev);
 
-	retval = pci_enable_wake(pdev, PCI_D3hot, 0);
-	if (retval)
-		DPRINTK(PROBE, ERR, "Error enabling D3 wake\n");
-	retval = pci_enable_wake(pdev, PCI_D3cold, 0);
-	if (retval)
-		DPRINTK(PROBE, ERR, "Error enabling D3 cold wake\n");
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	e1000_reset(adapter);
 	E1000_WRITE_REG(&adapter->hw, WUS, ~0);
@@ -4635,4 +4611,101 @@
 }
 #endif
 
+/**
+ * e1000_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci conneection state
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct e1000_adapter *adapter = netdev->priv;
+
+	netif_device_detach(netdev);
+
+	if (netif_running(netdev))
+		e1000_down(adapter);
+
+	/* Request a slot slot reset. */
+	return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * e1000_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Restart the card from scratch, as if from a cold-boot. Implementation
+ * resembles the first-half of the e1000_resume routine.
+ */
+static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct e1000_adapter *adapter = netdev->priv;
+
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR "e1000: Cannot re-enable PCI device after reset.\n");
+		return PCI_ERS_RESULT_DISCONNECT;
+	}
+	pci_set_master(pdev);
+
+	pci_enable_wake(pdev, 3, 0);
+	pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
+
+	/* Perform card reset only on one instance of the card */
+	if (PCI_FUNC (pdev->devfn) != 0)
+		return PCI_ERS_RESULT_RECOVERED;
+
+	e1000_reset(adapter);
+	E1000_WRITE_REG(&adapter->hw, WUS, ~0);
+
+	return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * e1000_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation. Implementation resembles the
+ * second-half of the e1000_resume routine.
+ */
+static void e1000_io_resume(struct pci_dev *pdev)
+{
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct e1000_adapter *adapter = netdev->priv;
+	uint32_t manc, swsm;
+
+	if (netif_running(netdev)) {
+		if (e1000_up(adapter)) {
+			printk("e1000: can't bring device back up after reset\n");
+			return;
+		}
+	}
+
+	netif_device_attach(netdev);
+
+	if (adapter->hw.mac_type >= e1000_82540 &&
+	    adapter->hw.media_type == e1000_media_type_copper) {
+		manc = E1000_READ_REG(&adapter->hw, MANC);
+		manc &= ~(E1000_MANC_ARP_EN);
+		E1000_WRITE_REG(&adapter->hw, MANC, manc);
+	}
+
+	switch (adapter->hw.mac_type) {
+	case e1000_82573:
+		swsm = E1000_READ_REG(&adapter->hw, SWSM);
+		E1000_WRITE_REG(&adapter->hw, SWSM,
+				swsm | E1000_SWSM_DRV_LOAD);
+		break;
+	default:
+		break;
+	}
+
+	if (netif_running(netdev))
+		mod_timer(&adapter->watchdog_timer, jiffies);
+}
+
 /* e1000_main.c */
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 9790db9..048d052 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index e0a4d37..e55f896 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -22,6 +22,7 @@
   
   Contact Information:
   Linux NICS <linux.nics@intel.com>
+  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index a806dfe..e70f172 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -1154,8 +1154,7 @@
 		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
 
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index 467fc86..ecf5ad8 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -278,11 +278,6 @@
 
 static int speedo_found1(struct pci_dev *pdev, void __iomem *ioaddr, int fnd_cnt, int acpi_idle_state);
 
-enum pci_flags_bit {
-	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
-};
-
 /* Offsets to the various registers.
    All accesses need not be longword aligned. */
 enum speedo_offsets {
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index 82bd356..a74b207 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -677,8 +677,7 @@
 #endif
 
 	if (buf->len < ETH_ZLEN) {
-		buf = skb_padto(buf, ETH_ZLEN);
-		if (buf == NULL)
+		if (skb_padto(buf, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 2f7b868..ee34a16 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -21,15 +21,15 @@
 	http://www.scyld.com/network/epic100.html
 
 	---------------------------------------------------------------------
-	
+
 	Linux kernel-specific changes:
-	
+
 	LK1.1.2 (jgarzik):
 	* Merge becker version 1.09 (4/08/2000)
 
 	LK1.1.3:
 	* Major bugfix to 1.09 driver (Francis Romieu)
-	
+
 	LK1.1.4 (jgarzik):
 	* Merge becker test version 1.09 (5/29/2000)
 
@@ -66,7 +66,7 @@
 	LK1.1.14 (Kryzsztof Halasa):
 	* fix spurious bad initializations
 	* pound phy a la SMSC's app note on the subject
-	
+
 	AC1.1.14ac
 	* fix power up/down for ethtool that broke in 1.11
 
@@ -191,23 +191,10 @@
 */
 
 
-enum pci_id_flags_bits {
-        /* Set PCI command register bits before calling probe1(). */
-        PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-        /* Read and map the single following PCI BAR. */
-        PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
-        PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
-};
-
 enum chip_capability_flags { MII_PWRDWN=1, TYPE2_INTR=2, NO_MII=4 };
 
 #define EPIC_TOTAL_SIZE 0x100
 #define USE_IO_OPS 1
-#ifdef USE_IO_OPS
-#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR0
-#else
-#define EPIC_IOTYPE PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR1
-#endif
 
 typedef enum {
 	SMSC_83C170_0,
@@ -218,7 +205,6 @@
 
 struct epic_chip_info {
 	const char *name;
-	enum pci_id_flags_bits pci_flags;
         int io_size;                            /* Needed for I/O region check or ioremap(). */
         int drv_flags;                          /* Driver use, intended as capability flags. */
 };
@@ -227,11 +213,11 @@
 /* indexed by chip_t */
 static const struct epic_chip_info pci_id_tbl[] = {
 	{ "SMSC EPIC/100 83c170",
-	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN },
+	  EPIC_TOTAL_SIZE, TYPE2_INTR | NO_MII | MII_PWRDWN },
 	{ "SMSC EPIC/100 83c170",
-	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, TYPE2_INTR },
+	  EPIC_TOTAL_SIZE, TYPE2_INTR },
 	{ "SMSC EPIC/C 83c175",
-	 EPIC_IOTYPE, EPIC_TOTAL_SIZE, TYPE2_INTR | MII_PWRDWN },
+	  EPIC_TOTAL_SIZE, TYPE2_INTR | MII_PWRDWN },
 };
 
 
@@ -244,7 +230,7 @@
 };
 MODULE_DEVICE_TABLE (pci, epic_pci_tbl);
 
-	
+
 #ifndef USE_IO_OPS
 #undef inb
 #undef inw
@@ -370,7 +356,7 @@
 static struct net_device_stats *epic_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 
-
+
 
 static int __devinit epic_init_one (struct pci_dev *pdev,
 				    const struct pci_device_id *ent)
@@ -392,9 +378,9 @@
 		printk (KERN_INFO "%s" KERN_INFO "%s" KERN_INFO "%s",
 			version, version2, version3);
 #endif
-	
+
 	card_idx++;
-	
+
 	ret = pci_enable_device(pdev);
 	if (ret)
 		goto out;
@@ -405,7 +391,7 @@
 		ret = -ENODEV;
 		goto err_out_disable;
 	}
-	
+
 	pci_set_master(pdev);
 
 	ret = pci_request_regions(pdev, DRV_NAME);
@@ -498,7 +484,7 @@
 	ep->pci_dev = pdev;
 	ep->chip_id = chip_idx;
 	ep->chip_flags = pci_id_tbl[chip_idx].drv_flags;
-	ep->irq_mask = 
+	ep->irq_mask =
 		(ep->chip_flags & TYPE2_INTR ?  PCIBusErr175 : PCIBusErr170)
 		 | CntFull | TxUnderrun | EpicNapiEvent;
 
@@ -587,7 +573,7 @@
 	pci_disable_device(pdev);
 	goto out;
 }
-
+
 /* Serial EEPROM section. */
 
 /*  EEPROM_Ctrl bits. */
@@ -709,7 +695,7 @@
 
 	outw(value, ioaddr + MIIData);
 	outl((phy_id << 9) | (loc << 4) | MII_WRITEOP, ioaddr + MIICtrl);
-	for (i = 10000; i > 0; i--) { 
+	for (i = 10000; i > 0; i--) {
 		barrier();
 		if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
 			break;
@@ -717,7 +703,7 @@
 	return;
 }
 
-
+
 static int epic_open(struct net_device *dev)
 {
 	struct epic_private *ep = dev->priv;
@@ -760,7 +746,7 @@
 #endif
 
 	udelay(20); /* Looks like EPII needs that if you want reliable RX init. FIXME: pci posting bug? */
-	
+
 	for (i = 0; i < 3; i++)
 		outl(cpu_to_le16(((u16*)dev->dev_addr)[i]), ioaddr + LAN0 + i*4);
 
@@ -803,7 +789,7 @@
 
 	/* Enable interrupts by setting the interrupt mask. */
 	outl((ep->chip_flags & TYPE2_INTR ? PCIBusErr175 : PCIBusErr170)
-		 | CntFull | TxUnderrun 
+		 | CntFull | TxUnderrun
 		 | RxError | RxHeader | EpicNapiEvent, ioaddr + INTMASK);
 
 	if (debug > 1)
@@ -831,7 +817,7 @@
 	struct epic_private *ep = dev->priv;
 
 	netif_stop_queue (dev);
-	
+
 	/* Disable interrupts by clearing the interrupt mask. */
 	outl(0x00000000, ioaddr + INTMASK);
 	/* Stop the chip's Tx and Rx DMA processes. */
@@ -987,7 +973,7 @@
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		ep->rx_ring[i].rxstatus = 0;
 		ep->rx_ring[i].buflength = cpu_to_le32(ep->rx_buf_sz);
-		ep->rx_ring[i].next = ep->rx_ring_dma + 
+		ep->rx_ring[i].next = ep->rx_ring_dma +
 				      (i+1)*sizeof(struct epic_rx_desc);
 		ep->rx_skbuff[i] = NULL;
 	}
@@ -1002,7 +988,7 @@
 			break;
 		skb->dev = dev;			/* Mark as being used by this device. */
 		skb_reserve(skb, 2);	/* 16 byte align the IP header. */
-		ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev, 
+		ep->rx_ring[i].bufaddr = pci_map_single(ep->pci_dev,
 			skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		ep->rx_ring[i].rxstatus = cpu_to_le32(DescOwn);
 	}
@@ -1013,7 +999,7 @@
 	for (i = 0; i < TX_RING_SIZE; i++) {
 		ep->tx_skbuff[i] = NULL;
 		ep->tx_ring[i].txstatus = 0x0000;
-		ep->tx_ring[i].next = ep->tx_ring_dma + 
+		ep->tx_ring[i].next = ep->tx_ring_dma +
 			(i+1)*sizeof(struct epic_tx_desc);
 	}
 	ep->tx_ring[i-1].next = ep->tx_ring_dma;
@@ -1026,12 +1012,9 @@
 	int entry, free_count;
 	u32 ctrl_word;
 	unsigned long flags;
-	
-	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
-	}
+
+	if (skb_padto(skb, ETH_ZLEN))
+		return 0;
 
 	/* Caution: the write order is important here, set the field with the
 	   "ownership" bit last. */
@@ -1042,7 +1025,7 @@
 	entry = ep->cur_tx % TX_RING_SIZE;
 
 	ep->tx_skbuff[entry] = skb;
-	ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data, 
+	ep->tx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, skb->data,
 		 			            skb->len, PCI_DMA_TODEVICE);
 	if (free_count < TX_QUEUE_LEN/2) {/* Typical path */
 		ctrl_word = cpu_to_le32(0x100000); /* No interrupt */
@@ -1126,7 +1109,7 @@
 
 		/* Free the original skb. */
 		skb = ep->tx_skbuff[entry];
-		pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr, 
+		pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
 				 skb->len, PCI_DMA_TODEVICE);
 		dev_kfree_skb_irq(skb);
 		ep->tx_skbuff[entry] = NULL;
@@ -1281,8 +1264,8 @@
 							       ep->rx_buf_sz,
 							       PCI_DMA_FROMDEVICE);
 			} else {
-				pci_unmap_single(ep->pci_dev, 
-					ep->rx_ring[entry].bufaddr, 
+				pci_unmap_single(ep->pci_dev,
+					ep->rx_ring[entry].bufaddr,
 					ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 				skb_put(skb = ep->rx_skbuff[entry], pkt_len);
 				ep->rx_skbuff[entry] = NULL;
@@ -1307,7 +1290,7 @@
 				break;
 			skb->dev = dev;			/* Mark as being used by this device. */
 			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
-			ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev, 
+			ep->rx_ring[entry].bufaddr = pci_map_single(ep->pci_dev,
 				skb->data, ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 			work_done++;
 		}
@@ -1403,7 +1386,7 @@
 		ep->rx_ring[i].rxstatus = 0;		/* Not owned by Epic chip. */
 		ep->rx_ring[i].buflength = 0;
 		if (skb) {
-			pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr, 
+			pci_unmap_single(ep->pci_dev, ep->rx_ring[i].bufaddr,
 				 	 ep->rx_buf_sz, PCI_DMA_FROMDEVICE);
 			dev_kfree_skb(skb);
 		}
@@ -1414,7 +1397,7 @@
 		ep->tx_skbuff[i] = NULL;
 		if (!skb)
 			continue;
-		pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr, 
+		pci_unmap_single(ep->pci_dev, ep->tx_ring[i].bufaddr,
 				 skb->len, PCI_DMA_TODEVICE);
 		dev_kfree_skb(skb);
 	}
@@ -1607,7 +1590,7 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct epic_private *ep = dev->priv;
-	
+
 	pci_free_consistent(pdev, TX_TOTAL_SIZE, ep->tx_ring, ep->tx_ring_dma);
 	pci_free_consistent(pdev, RX_TOTAL_SIZE, ep->rx_ring, ep->rx_ring_dma);
 	unregister_netdev(dev);
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index b67545b..4bf76f8 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -1064,8 +1064,7 @@
 	unsigned long flags;
 
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index a844926..13eca7e 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -126,16 +126,6 @@
 
 #define MIN_REGION_SIZE 136
 
-enum pci_flags_bit {
-	PCI_USES_IO = 1,
-	PCI_USES_MEM = 2,
-	PCI_USES_MASTER = 4,
-	PCI_ADDR0 = 0x10 << 0,
-	PCI_ADDR1 = 0x10 << 1,
-	PCI_ADDR2 = 0x10 << 2,
-	PCI_ADDR3 = 0x10 << 3,
-};
-
 /* A chip capabilities table, matching the entries in pci_tbl[] above. */
 enum chip_capability_flags {
 	HAS_MII_XCVR,
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index bd6983d..db694c8 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -22,7 +22,7 @@
  * Copyright (c) 2001-2005 Greg Ungerer (gerg@snapgear.com)
  *
  * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
- * Copyright (c) 2004-2005 Macq Electronique SA.
+ * Copyright (c) 2004-2006 Macq Electronique SA.
  */
 
 #include <linux/config.h>
@@ -51,7 +51,7 @@
 
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
     defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x)
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
 #include "fec.h"
@@ -80,6 +80,8 @@
 	(MCF_MBAR + 0x1000),
 #elif defined(CONFIG_M520x)
 	(MCF_MBAR+0x30000),
+#elif defined(CONFIG_M532x)
+	(MCF_MBAR+0xfc030000),
 #else
 	&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
 #endif
@@ -143,7 +145,7 @@
 #define TX_RING_MOD_MASK	15	/*   for this to work */
 
 #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)
-#error "FEC: descriptor ring size contants too large"
+#error "FEC: descriptor ring size constants too large"
 #endif
 
 /* Interrupt events/masks.
@@ -167,12 +169,12 @@
 
 
 /*
- * The 5270/5271/5280/5282 RX control register also contains maximum frame
+ * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
  * size bits. Other FEC hardware does not, so we need to take that into
  * account when setting it.
  */
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x)
 #define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
 #else
 #define	OPT_FRAME_SIZE	0
@@ -308,6 +310,7 @@
 	struct fec_enet_private *fep;
 	volatile fec_t	*fecp;
 	volatile cbd_t	*bdp;
+	unsigned short	status;
 
 	fep = netdev_priv(dev);
 	fecp = (volatile fec_t*)dev->base_addr;
@@ -320,8 +323,9 @@
 	/* Fill in a Tx ring entry */
 	bdp = fep->cur_tx;
 
+	status = bdp->cbd_sc;
 #ifndef final_version
-	if (bdp->cbd_sc & BD_ENET_TX_READY) {
+	if (status & BD_ENET_TX_READY) {
 		/* Ooops.  All transmit buffers are full.  Bail out.
 		 * This should not happen, since dev->tbusy should be set.
 		 */
@@ -332,7 +336,7 @@
 
 	/* Clear all of the status flags.
 	 */
-	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+	status &= ~BD_ENET_TX_STATS;
 
 	/* Set buffer length and buffer pointer.
 	*/
@@ -366,21 +370,22 @@
 
 	spin_lock_irq(&fep->lock);
 
-	/* Send it on its way.  Tell FEC its ready, interrupt when done,
-	 * its the last BD of the frame, and to put the CRC on the end.
+	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
+	 * it's the last BD of the frame, and to put the CRC on the end.
 	 */
 
-	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
+	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
 			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
+	bdp->cbd_sc = status;
 
 	dev->trans_start = jiffies;
 
 	/* Trigger transmission start */
-	fecp->fec_x_des_active = 0x01000000;
+	fecp->fec_x_des_active = 0;
 
 	/* If this was the last BD in the ring, start at the beginning again.
 	*/
-	if (bdp->cbd_sc & BD_ENET_TX_WRAP) {
+	if (status & BD_ENET_TX_WRAP) {
 		bdp = fep->tx_bd_base;
 	} else {
 		bdp++;
@@ -491,43 +496,44 @@
 {
 	struct	fec_enet_private *fep;
 	volatile cbd_t	*bdp;
+	unsigned short status;
 	struct	sk_buff	*skb;
 
 	fep = netdev_priv(dev);
 	spin_lock(&fep->lock);
 	bdp = fep->dirty_tx;
 
-	while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) {
+	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
 		if (bdp == fep->cur_tx && fep->tx_full == 0) break;
 
 		skb = fep->tx_skbuff[fep->skb_dirty];
 		/* Check for errors. */
-		if (bdp->cbd_sc & (BD_ENET_TX_HB | BD_ENET_TX_LC |
+		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
 				   BD_ENET_TX_RL | BD_ENET_TX_UN |
 				   BD_ENET_TX_CSL)) {
 			fep->stats.tx_errors++;
-			if (bdp->cbd_sc & BD_ENET_TX_HB)  /* No heartbeat */
+			if (status & BD_ENET_TX_HB)  /* No heartbeat */
 				fep->stats.tx_heartbeat_errors++;
-			if (bdp->cbd_sc & BD_ENET_TX_LC)  /* Late collision */
+			if (status & BD_ENET_TX_LC)  /* Late collision */
 				fep->stats.tx_window_errors++;
-			if (bdp->cbd_sc & BD_ENET_TX_RL)  /* Retrans limit */
+			if (status & BD_ENET_TX_RL)  /* Retrans limit */
 				fep->stats.tx_aborted_errors++;
-			if (bdp->cbd_sc & BD_ENET_TX_UN)  /* Underrun */
+			if (status & BD_ENET_TX_UN)  /* Underrun */
 				fep->stats.tx_fifo_errors++;
-			if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */
+			if (status & BD_ENET_TX_CSL) /* Carrier lost */
 				fep->stats.tx_carrier_errors++;
 		} else {
 			fep->stats.tx_packets++;
 		}
 
 #ifndef final_version
-		if (bdp->cbd_sc & BD_ENET_TX_READY)
+		if (status & BD_ENET_TX_READY)
 			printk("HEY! Enet xmit interrupt and TX_READY.\n");
 #endif
 		/* Deferred means some collisions occurred during transmit,
 		 * but we eventually sent the packet OK.
 		 */
-		if (bdp->cbd_sc & BD_ENET_TX_DEF)
+		if (status & BD_ENET_TX_DEF)
 			fep->stats.collisions++;
 	    
 		/* Free the sk buffer associated with this last transmit.
@@ -538,7 +544,7 @@
 	    
 		/* Update pointer to next buffer descriptor to be transmitted.
 		 */
-		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		if (status & BD_ENET_TX_WRAP)
 			bdp = fep->tx_bd_base;
 		else
 			bdp++;
@@ -568,9 +574,14 @@
 	struct	fec_enet_private *fep;
 	volatile fec_t	*fecp;
 	volatile cbd_t *bdp;
+	unsigned short status;
 	struct	sk_buff	*skb;
 	ushort	pkt_len;
 	__u8 *data;
+	
+#ifdef CONFIG_M532x
+	flush_cache_all();
+#endif	
 
 	fep = netdev_priv(dev);
 	fecp = (volatile fec_t*)dev->base_addr;
@@ -580,13 +591,13 @@
 	 */
 	bdp = fep->cur_rx;
 
-while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) {
+while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
 
 #ifndef final_version
 	/* Since we have allocated space to hold a complete frame,
 	 * the last indicator should be set.
 	 */
-	if ((bdp->cbd_sc & BD_ENET_RX_LAST) == 0)
+	if ((status & BD_ENET_RX_LAST) == 0)
 		printk("FEC ENET: rcv is not +last\n");
 #endif
 
@@ -594,26 +605,26 @@
 		goto rx_processing_done;
 
 	/* Check for errors. */
-	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
+	if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
 			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
 		fep->stats.rx_errors++;       
-		if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
+		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
 		/* Frame too long or too short. */
 			fep->stats.rx_length_errors++;
 		}
-		if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
+		if (status & BD_ENET_RX_NO)	/* Frame alignment */
 			fep->stats.rx_frame_errors++;
-		if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
+		if (status & BD_ENET_RX_CR)	/* CRC Error */
 			fep->stats.rx_crc_errors++;
-		if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
-			fep->stats.rx_crc_errors++;
+		if (status & BD_ENET_RX_OV)	/* FIFO overrun */
+			fep->stats.rx_fifo_errors++;
 	}
 
 	/* Report late collisions as a frame error.
 	 * On this error, the BD is closed, but we don't know what we
 	 * have in the buffer.  So, just drop this frame on the floor.
 	 */
-	if (bdp->cbd_sc & BD_ENET_RX_CL) {
+	if (status & BD_ENET_RX_CL) {
 		fep->stats.rx_errors++;
 		fep->stats.rx_frame_errors++;
 		goto rx_processing_done;
@@ -639,9 +650,7 @@
 	} else {
 		skb->dev = dev;
 		skb_put(skb,pkt_len-4);	/* Make room */
-		eth_copy_and_sum(skb,
-				 (unsigned char *)__va(bdp->cbd_bufaddr),
-				 pkt_len-4, 0);
+		eth_copy_and_sum(skb, data, pkt_len-4, 0);
 		skb->protocol=eth_type_trans(skb,dev);
 		netif_rx(skb);
 	}
@@ -649,15 +658,16 @@
 
 	/* Clear the status flags for this buffer.
 	*/
-	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+	status &= ~BD_ENET_RX_STATS;
 
 	/* Mark the buffer empty.
 	*/
-	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+	status |= BD_ENET_RX_EMPTY;
+	bdp->cbd_sc = status;
 
 	/* Update BD pointer to next entry.
 	*/
-	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+	if (status & BD_ENET_RX_WRAP)
 		bdp = fep->rx_bd_base;
 	else
 		bdp++;
@@ -667,9 +677,9 @@
 	 * incoming frames.  On a heavily loaded network, we should be
 	 * able to keep up at the expense of system resources.
 	 */
-	fecp->fec_r_des_active = 0x01000000;
+	fecp->fec_r_des_active = 0;
 #endif
-   } /* while (!(bdp->cbd_sc & BD_ENET_RX_EMPTY)) */
+   } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */
 	fep->cur_rx = (cbd_t *)bdp;
 
 #if 0
@@ -680,11 +690,12 @@
 	 * our way back to the interrupt return only to come right back
 	 * here.
 	 */
-	fecp->fec_r_des_active = 0x01000000;
+	fecp->fec_r_des_active = 0;
 #endif
 }
 
 
+/* called from interrupt context */
 static void
 fec_enet_mii(struct net_device *dev)
 {
@@ -696,10 +707,12 @@
 	fep = netdev_priv(dev);
 	ep = fep->hwp;
 	mii_reg = ep->fec_mii_data;
+
+	spin_lock(&fep->lock);
 	
 	if ((mip = mii_head) == NULL) {
 		printk("MII and no head!\n");
-		return;
+		goto unlock;
 	}
 
 	if (mip->mii_func != NULL)
@@ -711,6 +724,9 @@
 
 	if ((mip = mii_head) != NULL)
 		ep->fec_mii_data = mip->mii_regval;
+
+unlock:
+	spin_unlock(&fep->lock);
 }
 
 static int
@@ -728,8 +744,7 @@
 
 	retval = 0;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&fep->lock,flags);
 
 	if ((mip = mii_free) != NULL) {
 		mii_free = mip->mii_next;
@@ -749,7 +764,7 @@
 		retval = 1;
 	}
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&fep->lock,flags);
 
 	return(retval);
 }
@@ -1216,7 +1231,7 @@
 };
 
 /* ------------------------------------------------------------------------- */
-
+#if !defined(CONFIG_M532x)
 #ifdef CONFIG_RPXCLASSIC
 static void
 mii_link_interrupt(void *dev_id);
@@ -1224,6 +1239,7 @@
 static irqreturn_t
 mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs);
 #endif
+#endif
 
 #if defined(CONFIG_M5272)
 
@@ -1384,13 +1400,13 @@
 	{
 		volatile unsigned char  *icrp;
 		volatile unsigned long  *imrp;
-		int i;
+		int i, ilip;
 
 		b = (fep->index) ? MCFICM_INTC1 : MCFICM_INTC0;
 		icrp = (volatile unsigned char *) (MCF_IPSBAR + b +
 			MCFINTC_ICR0);
-		for (i = 23; (i < 36); i++)
-			icrp[i] = 0x23;
+		for (i = 23, ilip = 0x28; (i < 36); i++)
+			icrp[i] = ilip--;
 
 		imrp = (volatile unsigned long *) (MCF_IPSBAR + b +
 			MCFINTC_IMRH);
@@ -1618,6 +1634,159 @@
 
 /* ------------------------------------------------------------------------- */
 
+#elif defined(CONFIG_M532x)
+/*
+ * Code specific for M532x
+ */
+static void __inline__ fec_request_intrs(struct net_device *dev)
+{
+	struct fec_enet_private *fep;
+	int b;
+	static const struct idesc {
+		char *name;
+		unsigned short irq;
+	} *idp, id[] = {
+	    { "fec(TXF)", 36 },
+	    { "fec(TXB)", 37 },
+	    { "fec(TXFIFO)", 38 },
+	    { "fec(TXCR)", 39 },
+	    { "fec(RXF)", 40 },
+	    { "fec(RXB)", 41 },
+	    { "fec(MII)", 42 },
+	    { "fec(LC)", 43 },
+	    { "fec(HBERR)", 44 },
+	    { "fec(GRA)", 45 },
+	    { "fec(EBERR)", 46 },
+	    { "fec(BABT)", 47 },
+	    { "fec(BABR)", 48 },
+	    { NULL },
+	};
+
+	fep = netdev_priv(dev);
+	b = (fep->index) ? 128 : 64;
+
+	/* Setup interrupt handlers. */
+	for (idp = id; idp->name; idp++) {
+		if (request_irq(b+idp->irq,fec_enet_interrupt,0,idp->name,dev)!=0)
+			printk("FEC: Could not allocate %s IRQ(%d)!\n", 
+				idp->name, b+idp->irq);
+	}
+
+	/* Unmask interrupts */
+	MCF_INTC0_ICR36 = 0x2;
+	MCF_INTC0_ICR37 = 0x2;
+	MCF_INTC0_ICR38 = 0x2;
+	MCF_INTC0_ICR39 = 0x2;
+	MCF_INTC0_ICR40 = 0x2;
+	MCF_INTC0_ICR41 = 0x2;
+	MCF_INTC0_ICR42 = 0x2;
+	MCF_INTC0_ICR43 = 0x2;
+	MCF_INTC0_ICR44 = 0x2;
+	MCF_INTC0_ICR45 = 0x2;
+	MCF_INTC0_ICR46 = 0x2;
+	MCF_INTC0_ICR47 = 0x2;
+	MCF_INTC0_ICR48 = 0x2;
+
+	MCF_INTC0_IMRH &= ~(
+		MCF_INTC_IMRH_INT_MASK36 |
+		MCF_INTC_IMRH_INT_MASK37 |
+		MCF_INTC_IMRH_INT_MASK38 |
+		MCF_INTC_IMRH_INT_MASK39 |
+		MCF_INTC_IMRH_INT_MASK40 |
+		MCF_INTC_IMRH_INT_MASK41 |
+		MCF_INTC_IMRH_INT_MASK42 |
+		MCF_INTC_IMRH_INT_MASK43 |
+		MCF_INTC_IMRH_INT_MASK44 |
+		MCF_INTC_IMRH_INT_MASK45 |
+		MCF_INTC_IMRH_INT_MASK46 |
+		MCF_INTC_IMRH_INT_MASK47 |
+		MCF_INTC_IMRH_INT_MASK48 );
+
+	/* Set up gpio outputs for MII lines */
+	MCF_GPIO_PAR_FECI2C |= (0 |
+		MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
+		MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
+	MCF_GPIO_PAR_FEC = (0 |
+		MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
+		MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
+}
+
+static void __inline__ fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
+{
+	volatile fec_t *fecp;
+
+	fecp = fep->hwp;
+	fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
+	fecp->fec_x_cntrl = 0x00;
+
+	/*
+	 * Set MII speed to 2.5 MHz
+	 */
+	fep->phy_speed = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
+	fecp->fec_mii_speed = fep->phy_speed;
+
+	fec_restart(dev, 0);
+}
+
+static void __inline__ fec_get_mac(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+	volatile fec_t *fecp;
+	unsigned char *iap, tmpaddr[ETH_ALEN];
+
+	fecp = fep->hwp;
+
+	if (FEC_FLASHMAC) {
+		/*
+		 * Get MAC address from FLASH.
+		 * If it is all 1's or 0's, use the default.
+		 */
+		iap = FEC_FLASHMAC;
+		if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
+		    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
+			iap = fec_mac_default;
+		if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&
+		    (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
+			iap = fec_mac_default;
+	} else {
+		*((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;
+		*((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);
+		iap = &tmpaddr[0];
+	}
+
+	memcpy(dev->dev_addr, iap, ETH_ALEN);
+
+	/* Adjust MAC if using default MAC address */
+	if (iap == fec_mac_default)
+		dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
+}
+
+static void __inline__ fec_enable_phy_intr(void)
+{
+}
+
+static void __inline__ fec_disable_phy_intr(void)
+{
+}
+
+static void __inline__ fec_phy_ack_intr(void)
+{
+}
+
+static void __inline__ fec_localhw_setup(void)
+{
+}
+
+/*
+ *	Do not need to make region uncached on 532x.
+ */
+static void __inline__ fec_uncache(unsigned long addr)
+{
+}
+
+/* ------------------------------------------------------------------------- */
+
+
 #else
 
 /*
@@ -1985,9 +2154,12 @@
 		mii_do_cmd(dev, fep->phy->config);
 		mii_do_cmd(dev, phy_cmd_config);  /* display configuration */
 
-		/* FIXME: use netif_carrier_{on,off} ; this polls
-		 * until link is up which is wrong...  could be
-		 * 30 seconds or more we are trapped in here. -jgarzik
+		/* Poll until the PHY tells us its configuration
+		 * (not link state).
+		 * Request is initiated by mii_do_cmd above, but answer
+		 * comes by interrupt.
+		 * This should take about 25 usec per register at 2.5 MHz,
+		 * and we read approximately 5 registers.
 		 */
 		while(!fep->sequence_done)
 			schedule();
@@ -2253,15 +2425,11 @@
 	*/
 	fec_request_intrs(dev);
 
-	/* Clear and enable interrupts */
-	fecp->fec_ievent = 0xffc00000;
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
-		FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
 	fecp->fec_hash_table_high = 0;
 	fecp->fec_hash_table_low = 0;
 	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
 	fecp->fec_ecntrl = 2;
-	fecp->fec_r_des_active = 0x01000000;
+	fecp->fec_r_des_active = 0;
 
 	dev->base_addr = (unsigned long)fecp;
 
@@ -2281,6 +2449,11 @@
 	/* setup MII interface */
 	fec_set_mii(dev, fep);
 
+	/* Clear and enable interrupts */
+	fecp->fec_ievent = 0xffc00000;
+	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
+		FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+
 	/* Queue up command to detect the PHY and initialize the
 	 * remainder of the interface.
 	 */
@@ -2312,11 +2485,6 @@
 	fecp->fec_ecntrl = 1;
 	udelay(10);
 
-	/* Enable interrupts we wish to service.
-	*/
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
-				FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
-
 	/* Clear any outstanding interrupt.
 	*/
 	fecp->fec_ievent = 0xffc00000;
@@ -2408,7 +2576,12 @@
 	/* And last, enable the transmit and receive processing.
 	*/
 	fecp->fec_ecntrl = 2;
-	fecp->fec_r_des_active = 0x01000000;
+	fecp->fec_r_des_active = 0;
+
+	/* Enable interrupts we wish to service.
+	*/
+	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
+		FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
 }
 
 static void
@@ -2420,9 +2593,16 @@
 	fep = netdev_priv(dev);
 	fecp = fep->hwp;
 
-	fecp->fec_x_cntrl = 0x01;	/* Graceful transmit stop */
-
-	while(!(fecp->fec_ievent & FEC_ENET_GRA));
+	/*
+	** We cannot expect a graceful transmit stop without link !!!
+	*/
+	if (fep->link)
+		{
+		fecp->fec_x_cntrl = 0x01;	/* Graceful transmit stop */
+		udelay(10);
+		if (!(fecp->fec_ievent & FEC_ENET_GRA))
+			printk("fec_stop : Graceful transmit stop did not complete !\n");
+		}
 
 	/* Whack a reset.  We should wait for this.
 	*/
diff --git a/drivers/net/fec.h b/drivers/net/fec.h
index 965c5c4..1d42160 100644
--- a/drivers/net/fec.h
+++ b/drivers/net/fec.h
@@ -14,7 +14,7 @@
 /****************************************************************************/
 
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x)
 /*
  *	Just figures, Motorola would have to change the offsets for
  *	registers in the same peripheral device on different models
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index feb5b22..21be4fa 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -107,6 +107,8 @@
  *	0.52: 20 Jan 2006: Add MSI/MSIX support.
  *	0.53: 19 Mar 2006: Fix init from low power mode and add hw reset.
  *	0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup.
+ *	0.55: 22 Mar 2006: Add flow control (pause frame).
+ *	0.56: 22 Mar 2006: Additional ethtool config and moduleparam support.
  *
  * Known bugs:
  * We suspect that on some hardware no TX done interrupts are generated.
@@ -118,7 +120,7 @@
  * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
  * superfluous timer interrupts from the nic.
  */
-#define FORCEDETH_VERSION		"0.54"
+#define FORCEDETH_VERSION		"0.56"
 #define DRV_NAME			"forcedeth"
 
 #include <linux/module.h>
@@ -163,6 +165,9 @@
 #define DEV_HAS_MSI             0x0040  /* device supports MSI */
 #define DEV_HAS_MSI_X           0x0080  /* device supports MSI-X */
 #define DEV_HAS_POWER_CNTRL     0x0100  /* device supports power savings */
+#define DEV_HAS_PAUSEFRAME_TX   0x0200  /* device supports tx pause frames */
+#define DEV_HAS_STATISTICS      0x0400  /* device supports hw statistics */
+#define DEV_HAS_TEST_EXTENDED   0x0800  /* device supports extended diagnostic test */
 
 enum {
 	NvRegIrqStatus = 0x000,
@@ -203,6 +208,7 @@
 	NvRegMSIIrqMask = 0x030,
 #define NVREG_MSI_VECTOR_0_ENABLED 0x01
 	NvRegMisc1 = 0x080,
+#define NVREG_MISC1_PAUSE_TX	0x01
 #define NVREG_MISC1_HD		0x02
 #define NVREG_MISC1_FORCE	0x3b0f3c
 
@@ -214,9 +220,11 @@
 #define NVREG_XMITSTAT_BUSY	0x01
 
 	NvRegPacketFilterFlags = 0x8c,
-#define NVREG_PFF_ALWAYS	0x7F0008
+#define NVREG_PFF_PAUSE_RX	0x08
+#define NVREG_PFF_ALWAYS	0x7F0000
 #define NVREG_PFF_PROMISC	0x80
 #define NVREG_PFF_MYADDR	0x20
+#define NVREG_PFF_LOOPBACK	0x10
 
 	NvRegOffloadConfig = 0x90,
 #define NVREG_OFFLOAD_HOMEPHY	0x601
@@ -277,6 +285,9 @@
 #define NVREG_TXRXCTL_VLANINS	0x00080
 	NvRegTxRingPhysAddrHigh = 0x148,
 	NvRegRxRingPhysAddrHigh = 0x14C,
+	NvRegTxPauseFrame = 0x170,
+#define NVREG_TX_PAUSEFRAME_DISABLE	0x1ff0080
+#define NVREG_TX_PAUSEFRAME_ENABLE	0x0c00030
 	NvRegMIIStatus = 0x180,
 #define NVREG_MIISTAT_ERROR		0x0001
 #define NVREG_MIISTAT_LINKCHANGE	0x0008
@@ -326,6 +337,33 @@
 #define NVREG_POWERSTATE_D1		0x0001
 #define NVREG_POWERSTATE_D2		0x0002
 #define NVREG_POWERSTATE_D3		0x0003
+	NvRegTxCnt = 0x280,
+	NvRegTxZeroReXmt = 0x284,
+	NvRegTxOneReXmt = 0x288,
+	NvRegTxManyReXmt = 0x28c,
+	NvRegTxLateCol = 0x290,
+	NvRegTxUnderflow = 0x294,
+	NvRegTxLossCarrier = 0x298,
+	NvRegTxExcessDef = 0x29c,
+	NvRegTxRetryErr = 0x2a0,
+	NvRegRxFrameErr = 0x2a4,
+	NvRegRxExtraByte = 0x2a8,
+	NvRegRxLateCol = 0x2ac,
+	NvRegRxRunt = 0x2b0,
+	NvRegRxFrameTooLong = 0x2b4,
+	NvRegRxOverflow = 0x2b8,
+	NvRegRxFCSErr = 0x2bc,
+	NvRegRxFrameAlignErr = 0x2c0,
+	NvRegRxLenErr = 0x2c4,
+	NvRegRxUnicast = 0x2c8,
+	NvRegRxMulticast = 0x2cc,
+	NvRegRxBroadcast = 0x2d0,
+	NvRegTxDef = 0x2d4,
+	NvRegTxFrame = 0x2d8,
+	NvRegRxCnt = 0x2dc,
+	NvRegTxPause = 0x2e0,
+	NvRegRxPause = 0x2e4,
+	NvRegRxDropFrame = 0x2e8,
 	NvRegVlanControl = 0x300,
 #define NVREG_VLANCONTROL_ENABLE	0x2000
 	NvRegMSIXMap0 = 0x3e0,
@@ -449,16 +487,18 @@
 /* General driver defaults */
 #define NV_WATCHDOG_TIMEO	(5*HZ)
 
-#define RX_RING		128
-#define TX_RING		256
-/* 
- * If your nic mysteriously hangs then try to reduce the limits
- * to 1/0: It might be required to set NV_TX_LASTPACKET in the
- * last valid ring entry. But this would be impossible to
- * implement - probably a disassembly error.
+#define RX_RING_DEFAULT		128
+#define TX_RING_DEFAULT		256
+#define RX_RING_MIN		128
+#define TX_RING_MIN		64
+#define RING_MAX_DESC_VER_1	1024
+#define RING_MAX_DESC_VER_2_3	16384
+/*
+ * Difference between the get and put pointers for the tx ring.
+ * This is used to throttle the amount of data outstanding in the
+ * tx ring.
  */
-#define TX_LIMIT_STOP	255
-#define TX_LIMIT_START	254
+#define TX_LIMIT_DIFFERENCE	1
 
 /* rx/tx mac addr + type + vlan + align + slack*/
 #define NV_RX_HEADERS		(64)
@@ -472,8 +512,9 @@
 #define OOM_REFILL	(1+HZ/20)
 #define POLL_WAIT	(1+HZ/100)
 #define LINK_TIMEOUT	(3*HZ)
+#define STATS_INTERVAL	(10*HZ)
 
-/* 
+/*
  * desc_ver values:
  * The nic supports three different descriptor types:
  * - DESC_VER_1: Original
@@ -506,13 +547,13 @@
 #define PHY_1000	0x2
 #define PHY_HALF	0x100
 
-/* FIXME: MII defines that should be added to <linux/mii.h> */
-#define MII_1000BT_CR	0x09
-#define MII_1000BT_SR	0x0a
-#define ADVERTISE_1000FULL	0x0200
-#define ADVERTISE_1000HALF	0x0100
-#define LPA_1000FULL	0x0800
-#define LPA_1000HALF	0x0400
+#define NV_PAUSEFRAME_RX_CAPABLE 0x0001
+#define NV_PAUSEFRAME_TX_CAPABLE 0x0002
+#define NV_PAUSEFRAME_RX_ENABLE  0x0004
+#define NV_PAUSEFRAME_TX_ENABLE  0x0008
+#define NV_PAUSEFRAME_RX_REQ     0x0010
+#define NV_PAUSEFRAME_TX_REQ     0x0020
+#define NV_PAUSEFRAME_AUTONEG    0x0040
 
 /* MSI/MSI-X defines */
 #define NV_MSI_X_MAX_VECTORS  8
@@ -527,15 +568,110 @@
 #define NV_MSI_X_VECTOR_TX    0x1
 #define NV_MSI_X_VECTOR_OTHER 0x2
 
+/* statistics */
+struct nv_ethtool_str {
+	char name[ETH_GSTRING_LEN];
+};
+
+static const struct nv_ethtool_str nv_estats_str[] = {
+	{ "tx_bytes" },
+	{ "tx_zero_rexmt" },
+	{ "tx_one_rexmt" },
+	{ "tx_many_rexmt" },
+	{ "tx_late_collision" },
+	{ "tx_fifo_errors" },
+	{ "tx_carrier_errors" },
+	{ "tx_excess_deferral" },
+	{ "tx_retry_error" },
+	{ "tx_deferral" },
+	{ "tx_packets" },
+	{ "tx_pause" },
+	{ "rx_frame_error" },
+	{ "rx_extra_byte" },
+	{ "rx_late_collision" },
+	{ "rx_runt" },
+	{ "rx_frame_too_long" },
+	{ "rx_over_errors" },
+	{ "rx_crc_errors" },
+	{ "rx_frame_align_error" },
+	{ "rx_length_error" },
+	{ "rx_unicast" },
+	{ "rx_multicast" },
+	{ "rx_broadcast" },
+	{ "rx_bytes" },
+	{ "rx_pause" },
+	{ "rx_drop_frame" },
+	{ "rx_packets" },
+	{ "rx_errors_total" }
+};
+
+struct nv_ethtool_stats {
+	u64 tx_bytes;
+	u64 tx_zero_rexmt;
+	u64 tx_one_rexmt;
+	u64 tx_many_rexmt;
+	u64 tx_late_collision;
+	u64 tx_fifo_errors;
+	u64 tx_carrier_errors;
+	u64 tx_excess_deferral;
+	u64 tx_retry_error;
+	u64 tx_deferral;
+	u64 tx_packets;
+	u64 tx_pause;
+	u64 rx_frame_error;
+	u64 rx_extra_byte;
+	u64 rx_late_collision;
+	u64 rx_runt;
+	u64 rx_frame_too_long;
+	u64 rx_over_errors;
+	u64 rx_crc_errors;
+	u64 rx_frame_align_error;
+	u64 rx_length_error;
+	u64 rx_unicast;
+	u64 rx_multicast;
+	u64 rx_broadcast;
+	u64 rx_bytes;
+	u64 rx_pause;
+	u64 rx_drop_frame;
+	u64 rx_packets;
+	u64 rx_errors_total;
+};
+
+/* diagnostics */
+#define NV_TEST_COUNT_BASE 3
+#define NV_TEST_COUNT_EXTENDED 4
+
+static const struct nv_ethtool_str nv_etests_str[] = {
+	{ "link      (online/offline)" },
+	{ "register  (offline)       " },
+	{ "interrupt (offline)       " },
+	{ "loopback  (offline)       " }
+};
+
+struct register_test {
+	u32 reg;
+	u32 mask;
+};
+
+static const struct register_test nv_registers_test[] = {
+	{ NvRegUnknownSetupReg6, 0x01 },
+	{ NvRegMisc1, 0x03c },
+	{ NvRegOffloadConfig, 0x03ff },
+	{ NvRegMulticastAddrA, 0xffffffff },
+	{ NvRegUnknownSetupReg3, 0x0ff },
+	{ NvRegWakeUpFlags, 0x07777 },
+	{ 0,0 }
+};
+
 /*
  * SMP locking:
  * All hardware access under dev->priv->lock, except the performance
  * critical parts:
  * - rx is (pseudo-) lockless: it relies on the single-threading provided
  *	by the arch code for interrupts.
- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
+ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
  *	needs dev->priv->lock :-(
- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
+ * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
  */
 
 /* in dev: base, irq */
@@ -545,6 +681,7 @@
 	/* General data:
 	 * Locking: spin_lock(&np->lock); */
 	struct net_device_stats stats;
+	struct nv_ethtool_stats estats;
 	int in_shutdown;
 	u32 linkspeed;
 	int duplex;
@@ -554,6 +691,7 @@
 	int wolenabled;
 	unsigned int phy_oui;
 	u16 gigabit;
+	int intr_test;
 
 	/* General data: RO fields */
 	dma_addr_t ring_addr;
@@ -573,13 +711,15 @@
 	 */
 	ring_type rx_ring;
 	unsigned int cur_rx, refill_rx;
-	struct sk_buff *rx_skbuff[RX_RING];
-	dma_addr_t rx_dma[RX_RING];
+	struct sk_buff **rx_skbuff;
+	dma_addr_t *rx_dma;
 	unsigned int rx_buf_sz;
 	unsigned int pkt_limit;
 	struct timer_list oom_kick;
 	struct timer_list nic_poll;
+	struct timer_list stats_poll;
 	u32 nic_poll_irq;
+	int rx_ring_size;
 
 	/* media detection workaround.
 	 * Locking: Within irq hander or disable_irq+spin_lock(&np->lock);
@@ -591,10 +731,13 @@
 	 */
 	ring_type tx_ring;
 	unsigned int next_tx, nic_tx;
-	struct sk_buff *tx_skbuff[TX_RING];
-	dma_addr_t tx_dma[TX_RING];
-	unsigned int tx_dma_len[TX_RING];
+	struct sk_buff **tx_skbuff;
+	dma_addr_t *tx_dma;
+	unsigned int *tx_dma_len;
 	u32 tx_flags;
+	int tx_ring_size;
+	int tx_limit_start;
+	int tx_limit_stop;
 
 	/* vlan fields */
 	struct vlan_group *vlangrp;
@@ -602,6 +745,9 @@
 	/* msi/msi-x fields */
 	u32 msi_flags;
 	struct msix_entry msi_x_entry[NV_MSI_X_MAX_VECTORS];
+
+	/* flow control */
+	u32 pause_flags;
 };
 
 /*
@@ -612,12 +758,14 @@
 
 /*
  * Optimization can be either throuput mode or cpu mode
- * 
+ *
  * Throughput Mode: Every tx and rx packet will generate an interrupt.
  * CPU Mode: Interrupts are controlled by a timer.
  */
-#define NV_OPTIMIZATION_MODE_THROUGHPUT 0
-#define NV_OPTIMIZATION_MODE_CPU        1
+enum {
+	NV_OPTIMIZATION_MODE_THROUGHPUT,
+	NV_OPTIMIZATION_MODE_CPU
+};
 static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT;
 
 /*
@@ -630,14 +778,31 @@
 static int poll_interval = -1;
 
 /*
- * Disable MSI interrupts
+ * MSI interrupts
  */
-static int disable_msi = 0;
+enum {
+	NV_MSI_INT_DISABLED,
+	NV_MSI_INT_ENABLED
+};
+static int msi = NV_MSI_INT_ENABLED;
 
 /*
- * Disable MSIX interrupts
+ * MSIX interrupts
  */
-static int disable_msix = 0;
+enum {
+	NV_MSIX_INT_DISABLED,
+	NV_MSIX_INT_ENABLED
+};
+static int msix = NV_MSIX_INT_ENABLED;
+
+/*
+ * DMA 64bit
+ */
+enum {
+	NV_DMA_64BIT_DISABLED,
+	NV_DMA_64BIT_ENABLED
+};
+static int dma_64bit = NV_DMA_64BIT_ENABLED;
 
 static inline struct fe_priv *get_nvpriv(struct net_device *dev)
 {
@@ -697,7 +862,7 @@
 			writel((u32) cpu_to_le64(np->ring_addr), base + NvRegRxRingPhysAddr);
 		}
 		if (rxtx_flags & NV_SETUP_TX_RING) {
-			writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
+			writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc)), base + NvRegTxRingPhysAddr);
 		}
 	} else {
 		if (rxtx_flags & NV_SETUP_RX_RING) {
@@ -705,12 +870,37 @@
 			writel((u32) (cpu_to_le64(np->ring_addr) >> 32), base + NvRegRxRingPhysAddrHigh);
 		}
 		if (rxtx_flags & NV_SETUP_TX_RING) {
-			writel((u32) cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
-			writel((u32) (cpu_to_le64(np->ring_addr + RX_RING*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);
+			writel((u32) cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)), base + NvRegTxRingPhysAddr);
+			writel((u32) (cpu_to_le64(np->ring_addr + np->rx_ring_size*sizeof(struct ring_desc_ex)) >> 32), base + NvRegTxRingPhysAddrHigh);
 		}
 	}
 }
 
+static void free_rings(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+
+	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+		if(np->rx_ring.orig)
+			pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
+					    np->rx_ring.orig, np->ring_addr);
+	} else {
+		if (np->rx_ring.ex)
+			pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size),
+					    np->rx_ring.ex, np->ring_addr);
+	}
+	if (np->rx_skbuff)
+		kfree(np->rx_skbuff);
+	if (np->rx_dma)
+		kfree(np->rx_dma);
+	if (np->tx_skbuff)
+		kfree(np->tx_skbuff);
+	if (np->tx_dma)
+		kfree(np->tx_dma);
+	if (np->tx_dma_len)
+		kfree(np->tx_dma_len);
+}
+
 static int using_multi_irqs(struct net_device *dev)
 {
 	struct fe_priv *np = get_nvpriv(dev);
@@ -860,7 +1050,7 @@
 
 	/* set advertise register */
 	reg = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-	reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|0x800|0x400);
+	reg |= (ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL|ADVERTISE_PAUSE_ASYM|ADVERTISE_PAUSE_CAP);
 	if (mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg)) {
 		printk(KERN_INFO "%s: phy write to advertise failed.\n", pci_name(np->pci_dev));
 		return PHY_ERROR;
@@ -873,14 +1063,14 @@
 	mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
 	if (mii_status & PHY_GIGABIT) {
 		np->gigabit = PHY_GIGABIT;
-		mii_control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+		mii_control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
 		mii_control_1000 &= ~ADVERTISE_1000HALF;
 		if (phyinterface & PHY_RGMII)
 			mii_control_1000 |= ADVERTISE_1000FULL;
 		else
 			mii_control_1000 &= ~ADVERTISE_1000FULL;
 
-		if (mii_rw(dev, np->phyaddr, MII_1000BT_CR, mii_control_1000)) {
+		if (mii_rw(dev, np->phyaddr, MII_CTRL1000, mii_control_1000)) {
 			printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev));
 			return PHY_ERROR;
 		}
@@ -918,6 +1108,8 @@
 			return PHY_ERROR;
 		}
 	}
+	/* some phys clear out pause advertisment on reset, set it back */
+	mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
 
 	/* restart auto negotiation */
 	mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
@@ -1047,7 +1239,7 @@
 	while (np->cur_rx != refill_rx) {
 		struct sk_buff *skb;
 
-		nr = refill_rx % RX_RING;
+		nr = refill_rx % np->rx_ring_size;
 		if (np->rx_skbuff[nr] == NULL) {
 
 			skb = dev_alloc_skb(np->rx_buf_sz + NV_RX_ALLOC_PAD);
@@ -1076,7 +1268,7 @@
 		refill_rx++;
 	}
 	np->refill_rx = refill_rx;
-	if (np->cur_rx - refill_rx == RX_RING)
+	if (np->cur_rx - refill_rx == np->rx_ring_size)
 		return 1;
 	return 0;
 }
@@ -1110,14 +1302,14 @@
 	}
 }
 
-static void nv_init_rx(struct net_device *dev) 
+static void nv_init_rx(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
 	int i;
 
-	np->cur_rx = RX_RING;
+	np->cur_rx = np->rx_ring_size;
 	np->refill_rx = 0;
-	for (i = 0; i < RX_RING; i++)
+	for (i = 0; i < np->rx_ring_size; i++)
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
 			np->rx_ring.orig[i].FlagLen = 0;
 	        else
@@ -1130,7 +1322,7 @@
 	int i;
 
 	np->next_tx = np->nic_tx = 0;
-	for (i = 0; i < TX_RING; i++) {
+	for (i = 0; i < np->tx_ring_size; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
 			np->tx_ring.orig[i].FlagLen = 0;
 	        else
@@ -1174,8 +1366,8 @@
 {
 	struct fe_priv *np = netdev_priv(dev);
 	unsigned int i;
-	
-	for (i = 0; i < TX_RING; i++) {
+
+	for (i = 0; i < np->tx_ring_size; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
 			np->tx_ring.orig[i].FlagLen = 0;
 		else
@@ -1189,7 +1381,7 @@
 {
 	struct fe_priv *np = netdev_priv(dev);
 	int i;
-	for (i = 0; i < RX_RING; i++) {
+	for (i = 0; i < np->rx_ring_size; i++) {
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
 			np->rx_ring.orig[i].FlagLen = 0;
 		else
@@ -1213,7 +1405,7 @@
 
 /*
  * nv_start_xmit: dev->hard_start_xmit function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
  */
 static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
@@ -1221,8 +1413,8 @@
 	u32 tx_flags = 0;
 	u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
 	unsigned int fragments = skb_shinfo(skb)->nr_frags;
-	unsigned int nr = (np->next_tx - 1) % TX_RING;
-	unsigned int start_nr = np->next_tx % TX_RING;
+	unsigned int nr = (np->next_tx - 1) % np->tx_ring_size;
+	unsigned int start_nr = np->next_tx % np->tx_ring_size;
 	unsigned int i;
 	u32 offset = 0;
 	u32 bcnt;
@@ -1238,7 +1430,7 @@
 
 	spin_lock_irq(&np->lock);
 
-	if ((np->next_tx - np->nic_tx + entries - 1) > TX_LIMIT_STOP) {
+	if ((np->next_tx - np->nic_tx + entries - 1) > np->tx_limit_stop) {
 		spin_unlock_irq(&np->lock);
 		netif_stop_queue(dev);
 		return NETDEV_TX_BUSY;
@@ -1247,7 +1439,7 @@
 	/* setup the header buffer */
 	do {
 		bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
-		nr = (nr + 1) % TX_RING;
+		nr = (nr + 1) % np->tx_ring_size;
 
 		np->tx_dma[nr] = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
 						PCI_DMA_TODEVICE);
@@ -1274,7 +1466,7 @@
 
 		do {
 			bcnt = (size > NV_TX2_TSO_MAX_SIZE) ? NV_TX2_TSO_MAX_SIZE : size;
-			nr = (nr + 1) % TX_RING;
+			nr = (nr + 1) % np->tx_ring_size;
 
 			np->tx_dma[nr] = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
 						      PCI_DMA_TODEVICE);
@@ -1303,8 +1495,8 @@
 	np->tx_skbuff[nr] = skb;
 
 #ifdef NETIF_F_TSO
-	if (skb_shinfo(skb)->tso_size)
-		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
+	if (skb_shinfo(skb)->gso_size)
+		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
 	else
 #endif
 	tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
@@ -1320,7 +1512,7 @@
 	} else {
 		np->tx_ring.ex[start_nr].TxVlan = cpu_to_le32(tx_flags_vlan);
 		np->tx_ring.ex[start_nr].FlagLen |= cpu_to_le32(tx_flags | tx_flags_extra);
-	}	
+	}
 
 	dprintk(KERN_DEBUG "%s: nv_start_xmit: packet %d (entries %d) queued for transmission. tx_flags_extra: %x\n",
 		dev->name, np->next_tx, entries, tx_flags_extra);
@@ -1356,7 +1548,7 @@
 	struct sk_buff *skb;
 
 	while (np->nic_tx != np->next_tx) {
-		i = np->nic_tx % TX_RING;
+		i = np->nic_tx % np->tx_ring_size;
 
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
 			Flags = le32_to_cpu(np->tx_ring.orig[i].FlagLen);
@@ -1395,19 +1587,19 @@
 				} else {
 					np->stats.tx_packets++;
 					np->stats.tx_bytes += skb->len;
-				}				
+				}
 			}
 		}
 		nv_release_txskb(dev, i);
 		np->nic_tx++;
 	}
-	if (np->next_tx - np->nic_tx < TX_LIMIT_START)
+	if (np->next_tx - np->nic_tx < np->tx_limit_start)
 		netif_wake_queue(dev);
 }
 
 /*
  * nv_tx_timeout: dev->tx_timeout function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
  */
 static void nv_tx_timeout(struct net_device *dev)
 {
@@ -1438,10 +1630,10 @@
 					readl(base + i + 24), readl(base + i + 28));
 		}
 		printk(KERN_INFO "%s: Dumping tx ring\n", dev->name);
-		for (i=0;i<TX_RING;i+= 4) {
+		for (i=0;i<np->tx_ring_size;i+= 4) {
 			if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
 				printk(KERN_INFO "%03x: %08x %08x // %08x %08x // %08x %08x // %08x %08x\n",
-				       i, 
+				       i,
 				       le32_to_cpu(np->tx_ring.orig[i].PacketBuffer),
 				       le32_to_cpu(np->tx_ring.orig[i].FlagLen),
 				       le32_to_cpu(np->tx_ring.orig[i+1].PacketBuffer),
@@ -1452,7 +1644,7 @@
 				       le32_to_cpu(np->tx_ring.orig[i+3].FlagLen));
 			} else {
 				printk(KERN_INFO "%03x: %08x %08x %08x // %08x %08x %08x // %08x %08x %08x // %08x %08x %08x\n",
-				       i, 
+				       i,
 				       le32_to_cpu(np->tx_ring.ex[i].PacketBufferHigh),
 				       le32_to_cpu(np->tx_ring.ex[i].PacketBufferLow),
 				       le32_to_cpu(np->tx_ring.ex[i].FlagLen),
@@ -1550,15 +1742,14 @@
 	u32 Flags;
 	u32 vlanflags = 0;
 
-
 	for (;;) {
 		struct sk_buff *skb;
 		int len;
 		int i;
-		if (np->cur_rx - np->refill_rx >= RX_RING)
+		if (np->cur_rx - np->refill_rx >= np->rx_ring_size)
 			break;	/* we scanned the whole ring - do not continue */
 
-		i = np->cur_rx % RX_RING;
+		i = np->cur_rx % np->rx_ring_size;
 		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
 			Flags = le32_to_cpu(np->rx_ring.orig[i].FlagLen);
 			len = nv_descr_getlength(&np->rx_ring.orig[i], np->desc_ver);
@@ -1665,14 +1856,16 @@
 					}
 				}
 			}
-			Flags &= NV_RX2_CHECKSUMMASK;
-			if (Flags == NV_RX2_CHECKSUMOK1 ||
-					Flags == NV_RX2_CHECKSUMOK2 ||
-					Flags == NV_RX2_CHECKSUMOK3) {
-				dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
-				np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
-			} else {
-				dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name);
+			if (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) {
+				Flags &= NV_RX2_CHECKSUMMASK;
+				if (Flags == NV_RX2_CHECKSUMOK1 ||
+				    Flags == NV_RX2_CHECKSUMOK2 ||
+				    Flags == NV_RX2_CHECKSUMOK3) {
+					dprintk(KERN_DEBUG "%s: hw checksum hit!.\n", dev->name);
+					np->rx_skbuff[i]->ip_summed = CHECKSUM_UNNECESSARY;
+				} else {
+					dprintk(KERN_DEBUG "%s: hwchecksum miss!.\n", dev->name);
+				}
 			}
 		}
 		/* got a valid packet - forward it to the network core */
@@ -1737,7 +1930,7 @@
 		 * Changing the MTU is a rare event, it shouldn't matter.
 		 */
 		nv_disable_irq(dev);
-		spin_lock_bh(&dev->xmit_lock);
+		netif_tx_lock_bh(dev);
 		spin_lock(&np->lock);
 		/* stop engines */
 		nv_stop_rx(dev);
@@ -1747,18 +1940,15 @@
 		nv_drain_rx(dev);
 		nv_drain_tx(dev);
 		/* reinit driver view of the rx queue */
-		nv_init_rx(dev);
-		nv_init_tx(dev);
-		/* alloc new rx buffers */
 		set_bufsize(dev);
-		if (nv_alloc_rx(dev)) {
+		if (nv_init_ring(dev)) {
 			if (!np->in_shutdown)
 				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
 		}
 		/* reinit nic view of the rx queue */
 		writel(np->rx_buf_sz, base + NvRegOffloadConfig);
 		setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-		writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+		writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 			base + NvRegRingSizes);
 		pci_push(base);
 		writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
@@ -1768,7 +1958,7 @@
 		nv_start_rx(dev);
 		nv_start_tx(dev);
 		spin_unlock(&np->lock);
-		spin_unlock_bh(&dev->xmit_lock);
+		netif_tx_unlock_bh(dev);
 		nv_enable_irq(dev);
 	}
 	return 0;
@@ -1803,7 +1993,7 @@
 	memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
 
 	if (netif_running(dev)) {
-		spin_lock_bh(&dev->xmit_lock);
+		netif_tx_lock_bh(dev);
 		spin_lock_irq(&np->lock);
 
 		/* stop rx engine */
@@ -1815,7 +2005,7 @@
 		/* restart rx engine */
 		nv_start_rx(dev);
 		spin_unlock_irq(&np->lock);
-		spin_unlock_bh(&dev->xmit_lock);
+		netif_tx_unlock_bh(dev);
 	} else {
 		nv_copy_mac_to_hw(dev);
 	}
@@ -1824,7 +2014,7 @@
 
 /*
  * nv_set_multicast: dev->set_multicast function
- * Called with dev->xmit_lock held.
+ * Called with netif_tx_lock held.
  */
 static void nv_set_multicast(struct net_device *dev)
 {
@@ -1832,16 +2022,16 @@
 	u8 __iomem *base = get_hwbase(dev);
 	u32 addr[2];
 	u32 mask[2];
-	u32 pff;
+	u32 pff = readl(base + NvRegPacketFilterFlags) & NVREG_PFF_PAUSE_RX;
 
 	memset(addr, 0, sizeof(addr));
 	memset(mask, 0, sizeof(mask));
 
 	if (dev->flags & IFF_PROMISC) {
 		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
-		pff = NVREG_PFF_PROMISC;
+		pff |= NVREG_PFF_PROMISC;
 	} else {
-		pff = NVREG_PFF_MYADDR;
+		pff |= NVREG_PFF_MYADDR;
 
 		if (dev->flags & IFF_ALLMULTI || dev->mc_list) {
 			u32 alwaysOff[2];
@@ -1886,6 +2076,35 @@
 	spin_unlock_irq(&np->lock);
 }
 
+static void nv_update_pause(struct net_device *dev, u32 pause_flags)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+
+	np->pause_flags &= ~(NV_PAUSEFRAME_TX_ENABLE | NV_PAUSEFRAME_RX_ENABLE);
+
+	if (np->pause_flags & NV_PAUSEFRAME_RX_CAPABLE) {
+		u32 pff = readl(base + NvRegPacketFilterFlags) & ~NVREG_PFF_PAUSE_RX;
+		if (pause_flags & NV_PAUSEFRAME_RX_ENABLE) {
+			writel(pff|NVREG_PFF_PAUSE_RX, base + NvRegPacketFilterFlags);
+			np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+		} else {
+			writel(pff, base + NvRegPacketFilterFlags);
+		}
+	}
+	if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE) {
+		u32 regmisc = readl(base + NvRegMisc1) & ~NVREG_MISC1_PAUSE_TX;
+		if (pause_flags & NV_PAUSEFRAME_TX_ENABLE) {
+			writel(NVREG_TX_PAUSEFRAME_ENABLE,  base + NvRegTxPauseFrame);
+			writel(regmisc|NVREG_MISC1_PAUSE_TX, base + NvRegMisc1);
+			np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+		} else {
+			writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
+			writel(regmisc, base + NvRegMisc1);
+		}
+	}
+}
+
 /**
  * nv_update_linkspeed: Setup the MAC according to the link partner
  * @dev: Network device to be configured
@@ -1901,12 +2120,14 @@
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
-	int adv, lpa;
+	int adv = 0;
+	int lpa = 0;
+	int adv_lpa, adv_pause, lpa_pause;
 	int newls = np->linkspeed;
 	int newdup = np->duplex;
 	int mii_status;
 	int retval = 0;
-	u32 control_1000, status_1000, phyreg;
+	u32 control_1000, status_1000, phyreg, pause_flags;
 
 	/* BMSR_LSTATUS is latched, read it twice:
 	 * we want the current value.
@@ -1952,10 +2173,15 @@
 		goto set_speed;
 	}
 
+	adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+	lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
+	dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
+				dev->name, adv, lpa);
+
 	retval = 1;
 	if (np->gigabit == PHY_GIGABIT) {
-		control_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
-		status_1000 = mii_rw(dev, np->phyaddr, MII_1000BT_SR, MII_READ);
+		control_1000 = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
+		status_1000 = mii_rw(dev, np->phyaddr, MII_STAT1000, MII_READ);
 
 		if ((control_1000 & ADVERTISE_1000FULL) &&
 			(status_1000 & LPA_1000FULL)) {
@@ -1967,27 +2193,22 @@
 		}
 	}
 
-	adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-	lpa = mii_rw(dev, np->phyaddr, MII_LPA, MII_READ);
-	dprintk(KERN_DEBUG "%s: nv_update_linkspeed: PHY advertises 0x%04x, lpa 0x%04x.\n",
-				dev->name, adv, lpa);
-
 	/* FIXME: handle parallel detection properly */
-	lpa = lpa & adv;
-	if (lpa & LPA_100FULL) {
+	adv_lpa = lpa & adv;
+	if (adv_lpa & LPA_100FULL) {
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
 		newdup = 1;
-	} else if (lpa & LPA_100HALF) {
+	} else if (adv_lpa & LPA_100HALF) {
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_100;
 		newdup = 0;
-	} else if (lpa & LPA_10FULL) {
+	} else if (adv_lpa & LPA_10FULL) {
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
 		newdup = 1;
-	} else if (lpa & LPA_10HALF) {
+	} else if (adv_lpa & LPA_10HALF) {
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
 		newdup = 0;
 	} else {
-		dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, lpa);
+		dprintk(KERN_DEBUG "%s: bad ability %04x - falling back to 10HD.\n", dev->name, adv_lpa);
 		newls = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10;
 		newdup = 0;
 	}
@@ -2030,6 +2251,46 @@
 	writel(np->linkspeed, base + NvRegLinkSpeed);
 	pci_push(base);
 
+	pause_flags = 0;
+	/* setup pause frame */
+	if (np->duplex != 0) {
+		if (np->autoneg && np->pause_flags & NV_PAUSEFRAME_AUTONEG) {
+			adv_pause = adv & (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM);
+			lpa_pause = lpa & (LPA_PAUSE_CAP| LPA_PAUSE_ASYM);
+
+			switch (adv_pause) {
+			case (ADVERTISE_PAUSE_CAP):
+				if (lpa_pause & LPA_PAUSE_CAP) {
+					pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+					if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+						pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+				}
+				break;
+			case (ADVERTISE_PAUSE_ASYM):
+				if (lpa_pause == (LPA_PAUSE_CAP| LPA_PAUSE_ASYM))
+				{
+					pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+				}
+				break;
+			case (ADVERTISE_PAUSE_CAP| ADVERTISE_PAUSE_ASYM):
+				if (lpa_pause & LPA_PAUSE_CAP)
+				{
+					pause_flags |=  NV_PAUSEFRAME_RX_ENABLE;
+					if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+						pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+				}
+				if (lpa_pause == LPA_PAUSE_ASYM)
+				{
+					pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+				}
+				break;
+			}
+		} else {
+			pause_flags = np->pause_flags;
+		}
+	}
+	nv_update_pause(dev, pause_flags);
+
 	return retval;
 }
 
@@ -2090,7 +2351,7 @@
 		spin_lock(&np->lock);
 		nv_tx_done(dev);
 		spin_unlock(&np->lock);
-		
+
 		nv_rx_process(dev);
 		if (nv_alloc_rx(dev)) {
 			spin_lock(&np->lock);
@@ -2098,7 +2359,7 @@
 				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
 			spin_unlock(&np->lock);
 		}
-		
+
 		if (events & NVREG_IRQ_LINK) {
 			spin_lock(&np->lock);
 			nv_link_irq(dev);
@@ -2163,7 +2424,7 @@
 		spin_lock_irq(&np->lock);
 		nv_tx_done(dev);
 		spin_unlock_irq(&np->lock);
-		
+
 		if (events & (NVREG_IRQ_TX_ERR)) {
 			dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n",
 						dev->name, events);
@@ -2206,7 +2467,7 @@
 		dprintk(KERN_DEBUG "%s: rx irq: %08x\n", dev->name, events);
 		if (!(events & np->irqmask))
 			break;
-		
+
 		nv_rx_process(dev);
 		if (nv_alloc_rx(dev)) {
 			spin_lock_irq(&np->lock);
@@ -2214,7 +2475,7 @@
 				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
 			spin_unlock_irq(&np->lock);
 		}
-		
+
 		if (i > max_interrupt_work) {
 			spin_lock_irq(&np->lock);
 			/* disable interrupts on the nic */
@@ -2253,7 +2514,7 @@
 		dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
 		if (!(events & np->irqmask))
 			break;
-		
+
 		if (events & NVREG_IRQ_LINK) {
 			spin_lock_irq(&np->lock);
 			nv_link_irq(dev);
@@ -2290,6 +2551,175 @@
 	return IRQ_RETVAL(i);
 }
 
+static irqreturn_t nv_nic_irq_test(int foo, void *data, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	u32 events;
+
+	dprintk(KERN_DEBUG "%s: nv_nic_irq_test\n", dev->name);
+
+	if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
+		events = readl(base + NvRegIrqStatus) & NVREG_IRQSTAT_MASK;
+		writel(NVREG_IRQ_TIMER, base + NvRegIrqStatus);
+	} else {
+		events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQSTAT_MASK;
+		writel(NVREG_IRQ_TIMER, base + NvRegMSIXIrqStatus);
+	}
+	pci_push(base);
+	dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, events);
+	if (!(events & NVREG_IRQ_TIMER))
+		return IRQ_RETVAL(0);
+
+	spin_lock(&np->lock);
+	np->intr_test = 1;
+	spin_unlock(&np->lock);
+
+	dprintk(KERN_DEBUG "%s: nv_nic_irq_test completed\n", dev->name);
+
+	return IRQ_RETVAL(1);
+}
+
+static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
+{
+	u8 __iomem *base = get_hwbase(dev);
+	int i;
+	u32 msixmap = 0;
+
+	/* Each interrupt bit can be mapped to a MSIX vector (4 bits).
+	 * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents
+	 * the remaining 8 interrupts.
+	 */
+	for (i = 0; i < 8; i++) {
+		if ((irqmask >> i) & 0x1) {
+			msixmap |= vector << (i << 2);
+		}
+	}
+	writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0);
+
+	msixmap = 0;
+	for (i = 0; i < 8; i++) {
+		if ((irqmask >> (i + 8)) & 0x1) {
+			msixmap |= vector << (i << 2);
+		}
+	}
+	writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
+}
+
+static int nv_request_irq(struct net_device *dev, int intr_test)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	int ret = 1;
+	int i;
+
+	if (np->msi_flags & NV_MSI_X_CAPABLE) {
+		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+			np->msi_x_entry[i].entry = i;
+		}
+		if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
+			np->msi_flags |= NV_MSI_X_ENABLED;
+			if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT && !intr_test) {
+				/* Request irq for rx handling */
+				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
+					printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
+					pci_disable_msix(np->pci_dev);
+					np->msi_flags &= ~NV_MSI_X_ENABLED;
+					goto out_err;
+				}
+				/* Request irq for tx handling */
+				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
+					printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
+					pci_disable_msix(np->pci_dev);
+					np->msi_flags &= ~NV_MSI_X_ENABLED;
+					goto out_free_rx;
+				}
+				/* Request irq for link and timer handling */
+				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
+					printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
+					pci_disable_msix(np->pci_dev);
+					np->msi_flags &= ~NV_MSI_X_ENABLED;
+					goto out_free_tx;
+				}
+				/* map interrupts to their respective vector */
+				writel(0, base + NvRegMSIXMap0);
+				writel(0, base + NvRegMSIXMap1);
+				set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
+				set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
+				set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
+			} else {
+				/* Request irq for all interrupts */
+				if ((!intr_test &&
+				     request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) ||
+				    (intr_test &&
+				     request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0)) {
+					printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+					pci_disable_msix(np->pci_dev);
+					np->msi_flags &= ~NV_MSI_X_ENABLED;
+					goto out_err;
+				}
+
+				/* map interrupts to vector 0 */
+				writel(0, base + NvRegMSIXMap0);
+				writel(0, base + NvRegMSIXMap1);
+			}
+		}
+	}
+	if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
+		if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
+			np->msi_flags |= NV_MSI_ENABLED;
+			if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) ||
+			    (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0)) {
+				printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
+				pci_disable_msi(np->pci_dev);
+				np->msi_flags &= ~NV_MSI_ENABLED;
+				goto out_err;
+			}
+
+			/* map interrupts to vector 0 */
+			writel(0, base + NvRegMSIMap0);
+			writel(0, base + NvRegMSIMap1);
+			/* enable msi vector 0 */
+			writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
+		}
+	}
+	if (ret != 0) {
+		if ((!intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) ||
+		    (intr_test && request_irq(np->pci_dev->irq, &nv_nic_irq_test, SA_SHIRQ, dev->name, dev) != 0))
+			goto out_err;
+
+	}
+
+	return 0;
+out_free_tx:
+	free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
+out_free_rx:
+	free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
+out_err:
+	return 1;
+}
+
+static void nv_free_irq(struct net_device *dev)
+{
+	struct fe_priv *np = get_nvpriv(dev);
+	int i;
+
+	if (np->msi_flags & NV_MSI_X_ENABLED) {
+		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
+			free_irq(np->msi_x_entry[i].vector, dev);
+		}
+		pci_disable_msix(np->pci_dev);
+		np->msi_flags &= ~NV_MSI_X_ENABLED;
+	} else {
+		free_irq(np->pci_dev->irq, dev);
+		if (np->msi_flags & NV_MSI_ENABLED) {
+			pci_disable_msi(np->pci_dev);
+			np->msi_flags &= ~NV_MSI_ENABLED;
+		}
+	}
+}
+
 static void nv_do_nic_poll(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
@@ -2326,7 +2756,7 @@
 	np->nic_poll_irq = 0;
 
 	/* FIXME: Do we need synchronize_irq(dev->irq) here? */
-	
+
 	writel(mask, base + NvRegIrqMask);
 	pci_push(base);
 
@@ -2359,6 +2789,56 @@
 }
 #endif
 
+static void nv_do_stats_poll(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+
+	np->estats.tx_bytes += readl(base + NvRegTxCnt);
+	np->estats.tx_zero_rexmt += readl(base + NvRegTxZeroReXmt);
+	np->estats.tx_one_rexmt += readl(base + NvRegTxOneReXmt);
+	np->estats.tx_many_rexmt += readl(base + NvRegTxManyReXmt);
+	np->estats.tx_late_collision += readl(base + NvRegTxLateCol);
+	np->estats.tx_fifo_errors += readl(base + NvRegTxUnderflow);
+	np->estats.tx_carrier_errors += readl(base + NvRegTxLossCarrier);
+	np->estats.tx_excess_deferral += readl(base + NvRegTxExcessDef);
+	np->estats.tx_retry_error += readl(base + NvRegTxRetryErr);
+	np->estats.tx_deferral += readl(base + NvRegTxDef);
+	np->estats.tx_packets += readl(base + NvRegTxFrame);
+	np->estats.tx_pause += readl(base + NvRegTxPause);
+	np->estats.rx_frame_error += readl(base + NvRegRxFrameErr);
+	np->estats.rx_extra_byte += readl(base + NvRegRxExtraByte);
+	np->estats.rx_late_collision += readl(base + NvRegRxLateCol);
+	np->estats.rx_runt += readl(base + NvRegRxRunt);
+	np->estats.rx_frame_too_long += readl(base + NvRegRxFrameTooLong);
+	np->estats.rx_over_errors += readl(base + NvRegRxOverflow);
+	np->estats.rx_crc_errors += readl(base + NvRegRxFCSErr);
+	np->estats.rx_frame_align_error += readl(base + NvRegRxFrameAlignErr);
+	np->estats.rx_length_error += readl(base + NvRegRxLenErr);
+	np->estats.rx_unicast += readl(base + NvRegRxUnicast);
+	np->estats.rx_multicast += readl(base + NvRegRxMulticast);
+	np->estats.rx_broadcast += readl(base + NvRegRxBroadcast);
+	np->estats.rx_bytes += readl(base + NvRegRxCnt);
+	np->estats.rx_pause += readl(base + NvRegRxPause);
+	np->estats.rx_drop_frame += readl(base + NvRegRxDropFrame);
+	np->estats.rx_packets =
+		np->estats.rx_unicast +
+		np->estats.rx_multicast +
+		np->estats.rx_broadcast;
+	np->estats.rx_errors_total =
+		np->estats.rx_crc_errors +
+		np->estats.rx_over_errors +
+		np->estats.rx_frame_error +
+		(np->estats.rx_frame_align_error - np->estats.rx_extra_byte) +
+		np->estats.rx_late_collision +
+		np->estats.rx_runt +
+		np->estats.rx_frame_too_long;
+
+	if (!np->in_shutdown)
+		mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
+}
+
 static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	struct fe_priv *np = netdev_priv(dev);
@@ -2382,17 +2862,19 @@
 {
 	struct fe_priv *np = netdev_priv(dev);
 	u8 __iomem *base = get_hwbase(dev);
+	u32 flags = 0;
 
-	spin_lock_irq(&np->lock);
 	if (wolinfo->wolopts == 0) {
-		writel(0, base + NvRegWakeUpFlags);
 		np->wolenabled = 0;
-	}
-	if (wolinfo->wolopts & WAKE_MAGIC) {
-		writel(NVREG_WAKEUPFLAGS_ENABLE, base + NvRegWakeUpFlags);
+	} else if (wolinfo->wolopts & WAKE_MAGIC) {
 		np->wolenabled = 1;
+		flags = NVREG_WAKEUPFLAGS_ENABLE;
 	}
-	spin_unlock_irq(&np->lock);
+	if (netif_running(dev)) {
+		spin_lock_irq(&np->lock);
+		writel(flags, base + NvRegWakeUpFlags);
+		spin_unlock_irq(&np->lock);
+	}
 	return 0;
 }
 
@@ -2406,9 +2888,17 @@
 	if (!netif_running(dev)) {
 		/* We do not track link speed / duplex setting if the
 		 * interface is disabled. Force a link check */
-		nv_update_linkspeed(dev);
+		if (nv_update_linkspeed(dev)) {
+			if (!netif_carrier_ok(dev))
+				netif_carrier_on(dev);
+		} else {
+			if (netif_carrier_ok(dev))
+				netif_carrier_off(dev);
+		}
 	}
-	switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
+
+	if (netif_carrier_ok(dev)) {
+		switch(np->linkspeed & (NVREG_LINKSPEED_MASK)) {
 		case NVREG_LINKSPEED_10:
 			ecmd->speed = SPEED_10;
 			break;
@@ -2418,10 +2908,14 @@
 		case NVREG_LINKSPEED_1000:
 			ecmd->speed = SPEED_1000;
 			break;
+		}
+		ecmd->duplex = DUPLEX_HALF;
+		if (np->duplex)
+			ecmd->duplex = DUPLEX_FULL;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
 	}
-	ecmd->duplex = DUPLEX_HALF;
-	if (np->duplex)
-		ecmd->duplex = DUPLEX_FULL;
 
 	ecmd->autoneg = np->autoneg;
 
@@ -2429,23 +2923,20 @@
 	if (np->autoneg) {
 		ecmd->advertising |= ADVERTISED_Autoneg;
 		adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-	} else {
-		adv = np->fixed_mode;
+		if (adv & ADVERTISE_10HALF)
+			ecmd->advertising |= ADVERTISED_10baseT_Half;
+		if (adv & ADVERTISE_10FULL)
+			ecmd->advertising |= ADVERTISED_10baseT_Full;
+		if (adv & ADVERTISE_100HALF)
+			ecmd->advertising |= ADVERTISED_100baseT_Half;
+		if (adv & ADVERTISE_100FULL)
+			ecmd->advertising |= ADVERTISED_100baseT_Full;
+		if (np->gigabit == PHY_GIGABIT) {
+			adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
+			if (adv & ADVERTISE_1000FULL)
+				ecmd->advertising |= ADVERTISED_1000baseT_Full;
+		}
 	}
-	if (adv & ADVERTISE_10HALF)
-		ecmd->advertising |= ADVERTISED_10baseT_Half;
-	if (adv & ADVERTISE_10FULL)
-		ecmd->advertising |= ADVERTISED_10baseT_Full;
-	if (adv & ADVERTISE_100HALF)
-		ecmd->advertising |= ADVERTISED_100baseT_Half;
-	if (adv & ADVERTISE_100FULL)
-		ecmd->advertising |= ADVERTISED_100baseT_Full;
-	if (np->autoneg && np->gigabit == PHY_GIGABIT) {
-		adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
-		if (adv & ADVERTISE_1000FULL)
-			ecmd->advertising |= ADVERTISED_1000baseT_Full;
-	}
-
 	ecmd->supported = (SUPPORTED_Autoneg |
 		SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
 		SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
@@ -2497,7 +2988,18 @@
 		return -EINVAL;
 	}
 
-	spin_lock_irq(&np->lock);
+	netif_carrier_off(dev);
+	if (netif_running(dev)) {
+		nv_disable_irq(dev);
+		netif_tx_lock_bh(dev);
+		spin_lock(&np->lock);
+		/* stop engines */
+		nv_stop_rx(dev);
+		nv_stop_tx(dev);
+		spin_unlock(&np->lock);
+		netif_tx_unlock_bh(dev);
+	}
+
 	if (ecmd->autoneg == AUTONEG_ENABLE) {
 		int adv, bmcr;
 
@@ -2505,7 +3007,7 @@
 
 		/* advertise only what has been requested */
 		adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-		adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+		adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
 		if (ecmd->advertising & ADVERTISED_10baseT_Half)
 			adv |= ADVERTISE_10HALF;
 		if (ecmd->advertising & ADVERTISED_10baseT_Full)
@@ -2514,16 +3016,22 @@
 			adv |= ADVERTISE_100HALF;
 		if (ecmd->advertising & ADVERTISED_100baseT_Full)
 			adv |= ADVERTISE_100FULL;
+		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ)  /* for rx we set both advertisments but disable tx pause */
+			adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+		if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+			adv |=  ADVERTISE_PAUSE_ASYM;
 		mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
 
 		if (np->gigabit == PHY_GIGABIT) {
-			adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+			adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
 			adv &= ~ADVERTISE_1000FULL;
 			if (ecmd->advertising & ADVERTISED_1000baseT_Full)
 				adv |= ADVERTISE_1000FULL;
-			mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
+			mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
 		}
 
+		if (netif_running(dev))
+			printk(KERN_INFO "%s: link down.\n", dev->name);
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
 		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
 		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
@@ -2534,7 +3042,7 @@
 		np->autoneg = 0;
 
 		adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
-		adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+		adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
 		if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF)
 			adv |= ADVERTISE_10HALF;
 		if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL)
@@ -2543,30 +3051,49 @@
 			adv |= ADVERTISE_100HALF;
 		if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL)
 			adv |= ADVERTISE_100FULL;
+		np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE);
+		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisments but disable tx pause */
+			adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+			np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+		}
+		if (np->pause_flags & NV_PAUSEFRAME_TX_REQ) {
+			adv |=  ADVERTISE_PAUSE_ASYM;
+			np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+		}
 		mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
 		np->fixed_mode = adv;
 
 		if (np->gigabit == PHY_GIGABIT) {
-			adv = mii_rw(dev, np->phyaddr, MII_1000BT_CR, MII_READ);
+			adv = mii_rw(dev, np->phyaddr, MII_CTRL1000, MII_READ);
 			adv &= ~ADVERTISE_1000FULL;
-			mii_rw(dev, np->phyaddr, MII_1000BT_CR, adv);
+			mii_rw(dev, np->phyaddr, MII_CTRL1000, adv);
 		}
 
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
-		bmcr |= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_FULLDPLX);
-		if (adv & (ADVERTISE_10FULL|ADVERTISE_100FULL))
+		bmcr &= ~(BMCR_ANENABLE|BMCR_SPEED100|BMCR_SPEED1000|BMCR_FULLDPLX);
+		if (np->fixed_mode & (ADVERTISE_10FULL|ADVERTISE_100FULL))
 			bmcr |= BMCR_FULLDPLX;
-		if (adv & (ADVERTISE_100HALF|ADVERTISE_100FULL))
+		if (np->fixed_mode & (ADVERTISE_100HALF|ADVERTISE_100FULL))
 			bmcr |= BMCR_SPEED100;
 		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
-
-		if (netif_running(dev)) {
+		if (np->phy_oui == PHY_OUI_MARVELL) {
+			/* reset the phy */
+			if (phy_reset(dev)) {
+				printk(KERN_INFO "%s: phy reset failed\n", dev->name);
+				return -EINVAL;
+			}
+		} else if (netif_running(dev)) {
 			/* Wait a bit and then reconfigure the nic. */
 			udelay(10);
 			nv_linkchange(dev);
 		}
 	}
-	spin_unlock_irq(&np->lock);
+
+	if (netif_running(dev)) {
+		nv_start_rx(dev);
+		nv_start_tx(dev);
+		nv_enable_irq(dev);
+	}
 
 	return 0;
 }
@@ -2598,24 +3125,39 @@
 	struct fe_priv *np = netdev_priv(dev);
 	int ret;
 
-	spin_lock_irq(&np->lock);
 	if (np->autoneg) {
 		int bmcr;
 
+		netif_carrier_off(dev);
+		if (netif_running(dev)) {
+			nv_disable_irq(dev);
+			netif_tx_lock_bh(dev);
+			spin_lock(&np->lock);
+			/* stop engines */
+			nv_stop_rx(dev);
+			nv_stop_tx(dev);
+			spin_unlock(&np->lock);
+			netif_tx_unlock_bh(dev);
+			printk(KERN_INFO "%s: link down.\n", dev->name);
+		}
+
 		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
 		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
 		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
 
+		if (netif_running(dev)) {
+			nv_start_rx(dev);
+			nv_start_tx(dev);
+			nv_enable_irq(dev);
+		}
 		ret = 0;
 	} else {
 		ret = -EINVAL;
 	}
-	spin_unlock_irq(&np->lock);
 
 	return ret;
 }
 
-#ifdef NETIF_F_TSO
 static int nv_set_tso(struct net_device *dev, u32 value)
 {
 	struct fe_priv *np = netdev_priv(dev);
@@ -2623,9 +3165,644 @@
 	if ((np->driver_data & DEV_HAS_CHECKSUM))
 		return ethtool_op_set_tso(dev, value);
 	else
-		return value ? -EOPNOTSUPP : 0;
+		return -EOPNOTSUPP;
 }
-#endif
+
+static void nv_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+{
+	struct fe_priv *np = netdev_priv(dev);
+
+	ring->rx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3;
+	ring->rx_mini_max_pending = 0;
+	ring->rx_jumbo_max_pending = 0;
+	ring->tx_max_pending = (np->desc_ver == DESC_VER_1) ? RING_MAX_DESC_VER_1 : RING_MAX_DESC_VER_2_3;
+
+	ring->rx_pending = np->rx_ring_size;
+	ring->rx_mini_pending = 0;
+	ring->rx_jumbo_pending = 0;
+	ring->tx_pending = np->tx_ring_size;
+}
+
+static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	u8 *rxtx_ring, *rx_skbuff, *tx_skbuff, *rx_dma, *tx_dma, *tx_dma_len;
+	dma_addr_t ring_addr;
+
+	if (ring->rx_pending < RX_RING_MIN ||
+	    ring->tx_pending < TX_RING_MIN ||
+	    ring->rx_mini_pending != 0 ||
+	    ring->rx_jumbo_pending != 0 ||
+	    (np->desc_ver == DESC_VER_1 &&
+	     (ring->rx_pending > RING_MAX_DESC_VER_1 ||
+	      ring->tx_pending > RING_MAX_DESC_VER_1)) ||
+	    (np->desc_ver != DESC_VER_1 &&
+	     (ring->rx_pending > RING_MAX_DESC_VER_2_3 ||
+	      ring->tx_pending > RING_MAX_DESC_VER_2_3))) {
+		return -EINVAL;
+	}
+
+	/* allocate new rings */
+	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+		rxtx_ring = pci_alloc_consistent(np->pci_dev,
+					    sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+					    &ring_addr);
+	} else {
+		rxtx_ring = pci_alloc_consistent(np->pci_dev,
+					    sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending),
+					    &ring_addr);
+	}
+	rx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->rx_pending, GFP_KERNEL);
+	rx_dma = kmalloc(sizeof(dma_addr_t) * ring->rx_pending, GFP_KERNEL);
+	tx_skbuff = kmalloc(sizeof(struct sk_buff*) * ring->tx_pending, GFP_KERNEL);
+	tx_dma = kmalloc(sizeof(dma_addr_t) * ring->tx_pending, GFP_KERNEL);
+	tx_dma_len = kmalloc(sizeof(unsigned int) * ring->tx_pending, GFP_KERNEL);
+	if (!rxtx_ring || !rx_skbuff || !rx_dma || !tx_skbuff || !tx_dma || !tx_dma_len) {
+		/* fall back to old rings */
+		if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+			if(rxtx_ring)
+				pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (ring->rx_pending + ring->tx_pending),
+						    rxtx_ring, ring_addr);
+		} else {
+			if (rxtx_ring)
+				pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (ring->rx_pending + ring->tx_pending),
+						    rxtx_ring, ring_addr);
+		}
+		if (rx_skbuff)
+			kfree(rx_skbuff);
+		if (rx_dma)
+			kfree(rx_dma);
+		if (tx_skbuff)
+			kfree(tx_skbuff);
+		if (tx_dma)
+			kfree(tx_dma);
+		if (tx_dma_len)
+			kfree(tx_dma_len);
+		goto exit;
+	}
+
+	if (netif_running(dev)) {
+		nv_disable_irq(dev);
+		netif_tx_lock_bh(dev);
+		spin_lock(&np->lock);
+		/* stop engines */
+		nv_stop_rx(dev);
+		nv_stop_tx(dev);
+		nv_txrx_reset(dev);
+		/* drain queues */
+		nv_drain_rx(dev);
+		nv_drain_tx(dev);
+		/* delete queues */
+		free_rings(dev);
+	}
+
+	/* set new values */
+	np->rx_ring_size = ring->rx_pending;
+	np->tx_ring_size = ring->tx_pending;
+	np->tx_limit_stop = ring->tx_pending - TX_LIMIT_DIFFERENCE;
+	np->tx_limit_start = ring->tx_pending - TX_LIMIT_DIFFERENCE - 1;
+	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+		np->rx_ring.orig = (struct ring_desc*)rxtx_ring;
+		np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size];
+	} else {
+		np->rx_ring.ex = (struct ring_desc_ex*)rxtx_ring;
+		np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size];
+	}
+	np->rx_skbuff = (struct sk_buff**)rx_skbuff;
+	np->rx_dma = (dma_addr_t*)rx_dma;
+	np->tx_skbuff = (struct sk_buff**)tx_skbuff;
+	np->tx_dma = (dma_addr_t*)tx_dma;
+	np->tx_dma_len = (unsigned int*)tx_dma_len;
+	np->ring_addr = ring_addr;
+
+	memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size);
+	memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size);
+	memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size);
+	memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size);
+	memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size);
+
+	if (netif_running(dev)) {
+		/* reinit driver view of the queues */
+		set_bufsize(dev);
+		if (nv_init_ring(dev)) {
+			if (!np->in_shutdown)
+				mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+		}
+
+		/* reinit nic view of the queues */
+		writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+		setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
+		writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+			base + NvRegRingSizes);
+		pci_push(base);
+		writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+		pci_push(base);
+
+		/* restart engines */
+		nv_start_rx(dev);
+		nv_start_tx(dev);
+		spin_unlock(&np->lock);
+		netif_tx_unlock_bh(dev);
+		nv_enable_irq(dev);
+	}
+	return 0;
+exit:
+	return -ENOMEM;
+}
+
+static void nv_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam* pause)
+{
+	struct fe_priv *np = netdev_priv(dev);
+
+	pause->autoneg = (np->pause_flags & NV_PAUSEFRAME_AUTONEG) != 0;
+	pause->rx_pause = (np->pause_flags & NV_PAUSEFRAME_RX_ENABLE) != 0;
+	pause->tx_pause = (np->pause_flags & NV_PAUSEFRAME_TX_ENABLE) != 0;
+}
+
+static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam* pause)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	int adv, bmcr;
+
+	if ((!np->autoneg && np->duplex == 0) ||
+	    (np->autoneg && !pause->autoneg && np->duplex == 0)) {
+		printk(KERN_INFO "%s: can not set pause settings when forced link is in half duplex.\n",
+		       dev->name);
+		return -EINVAL;
+	}
+	if (pause->tx_pause && !(np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)) {
+		printk(KERN_INFO "%s: hardware does not support tx pause frames.\n", dev->name);
+		return -EINVAL;
+	}
+
+	netif_carrier_off(dev);
+	if (netif_running(dev)) {
+		nv_disable_irq(dev);
+		netif_tx_lock_bh(dev);
+		spin_lock(&np->lock);
+		/* stop engines */
+		nv_stop_rx(dev);
+		nv_stop_tx(dev);
+		spin_unlock(&np->lock);
+		netif_tx_unlock_bh(dev);
+	}
+
+	np->pause_flags &= ~(NV_PAUSEFRAME_RX_REQ|NV_PAUSEFRAME_TX_REQ);
+	if (pause->rx_pause)
+		np->pause_flags |= NV_PAUSEFRAME_RX_REQ;
+	if (pause->tx_pause)
+		np->pause_flags |= NV_PAUSEFRAME_TX_REQ;
+
+	if (np->autoneg && pause->autoneg) {
+		np->pause_flags |= NV_PAUSEFRAME_AUTONEG;
+
+		adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
+		adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisments but disable tx pause */
+			adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+		if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
+			adv |=  ADVERTISE_PAUSE_ASYM;
+		mii_rw(dev, np->phyaddr, MII_ADVERTISE, adv);
+
+		if (netif_running(dev))
+			printk(KERN_INFO "%s: link down.\n", dev->name);
+		bmcr = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
+		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+		mii_rw(dev, np->phyaddr, MII_BMCR, bmcr);
+	} else {
+		np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE);
+		if (pause->rx_pause)
+			np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
+		if (pause->tx_pause)
+			np->pause_flags |= NV_PAUSEFRAME_TX_ENABLE;
+
+		if (!netif_running(dev))
+			nv_update_linkspeed(dev);
+		else
+			nv_update_pause(dev, np->pause_flags);
+	}
+
+	if (netif_running(dev)) {
+		nv_start_rx(dev);
+		nv_start_tx(dev);
+		nv_enable_irq(dev);
+	}
+	return 0;
+}
+
+static u32 nv_get_rx_csum(struct net_device *dev)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	return (np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) != 0;
+}
+
+static int nv_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	int retcode = 0;
+
+	if (np->driver_data & DEV_HAS_CHECKSUM) {
+
+		if (((np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && data) ||
+		    (!(np->txrxctl_bits & NVREG_TXRXCTL_RXCHECK) && !data)) {
+			/* already set or unset */
+			return 0;
+		}
+
+		if (data) {
+			np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK;
+		} else if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE)) {
+			np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK;
+		} else {
+			printk(KERN_INFO "Can not disable rx checksum if vlan is enabled\n");
+			return -EINVAL;
+		}
+
+		if (netif_running(dev)) {
+			spin_lock_irq(&np->lock);
+			writel(np->txrxctl_bits, base + NvRegTxRxControl);
+			spin_unlock_irq(&np->lock);
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return retcode;
+}
+
+static int nv_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct fe_priv *np = netdev_priv(dev);
+
+	if (np->driver_data & DEV_HAS_CHECKSUM)
+		return ethtool_op_set_tx_hw_csum(dev, data);
+	else
+		return -EOPNOTSUPP;
+}
+
+static int nv_set_sg(struct net_device *dev, u32 data)
+{
+	struct fe_priv *np = netdev_priv(dev);
+
+	if (np->driver_data & DEV_HAS_CHECKSUM)
+		return ethtool_op_set_sg(dev, data);
+	else
+		return -EOPNOTSUPP;
+}
+
+static int nv_get_stats_count(struct net_device *dev)
+{
+	struct fe_priv *np = netdev_priv(dev);
+
+	if (np->driver_data & DEV_HAS_STATISTICS)
+		return (sizeof(struct nv_ethtool_stats)/sizeof(u64));
+	else
+		return 0;
+}
+
+static void nv_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *estats, u64 *buffer)
+{
+	struct fe_priv *np = netdev_priv(dev);
+
+	/* update stats */
+	nv_do_stats_poll((unsigned long)dev);
+
+	memcpy(buffer, &np->estats, nv_get_stats_count(dev)*sizeof(u64));
+}
+
+static int nv_self_test_count(struct net_device *dev)
+{
+	struct fe_priv *np = netdev_priv(dev);
+
+	if (np->driver_data & DEV_HAS_TEST_EXTENDED)
+		return NV_TEST_COUNT_EXTENDED;
+	else
+		return NV_TEST_COUNT_BASE;
+}
+
+static int nv_link_test(struct net_device *dev)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	int mii_status;
+
+	mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
+	mii_status = mii_rw(dev, np->phyaddr, MII_BMSR, MII_READ);
+
+	/* check phy link status */
+	if (!(mii_status & BMSR_LSTATUS))
+		return 0;
+	else
+		return 1;
+}
+
+static int nv_register_test(struct net_device *dev)
+{
+	u8 __iomem *base = get_hwbase(dev);
+	int i = 0;
+	u32 orig_read, new_read;
+
+	do {
+		orig_read = readl(base + nv_registers_test[i].reg);
+
+		/* xor with mask to toggle bits */
+		orig_read ^= nv_registers_test[i].mask;
+
+		writel(orig_read, base + nv_registers_test[i].reg);
+
+		new_read = readl(base + nv_registers_test[i].reg);
+
+		if ((new_read & nv_registers_test[i].mask) != (orig_read & nv_registers_test[i].mask))
+			return 0;
+
+		/* restore original value */
+		orig_read ^= nv_registers_test[i].mask;
+		writel(orig_read, base + nv_registers_test[i].reg);
+
+	} while (nv_registers_test[++i].reg != 0);
+
+	return 1;
+}
+
+static int nv_interrupt_test(struct net_device *dev)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	int ret = 1;
+	int testcnt;
+	u32 save_msi_flags, save_poll_interval = 0;
+
+	if (netif_running(dev)) {
+		/* free current irq */
+		nv_free_irq(dev);
+		save_poll_interval = readl(base+NvRegPollingInterval);
+	}
+
+	/* flag to test interrupt handler */
+	np->intr_test = 0;
+
+	/* setup test irq */
+	save_msi_flags = np->msi_flags;
+	np->msi_flags &= ~NV_MSI_X_VECTORS_MASK;
+	np->msi_flags |= 0x001; /* setup 1 vector */
+	if (nv_request_irq(dev, 1))
+		return 0;
+
+	/* setup timer interrupt */
+	writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval);
+	writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
+
+	nv_enable_hw_interrupts(dev, NVREG_IRQ_TIMER);
+
+	/* wait for at least one interrupt */
+	msleep(100);
+
+	spin_lock_irq(&np->lock);
+
+	/* flag should be set within ISR */
+	testcnt = np->intr_test;
+	if (!testcnt)
+		ret = 2;
+
+	nv_disable_hw_interrupts(dev, NVREG_IRQ_TIMER);
+	if (!(np->msi_flags & NV_MSI_X_ENABLED))
+		writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+	else
+		writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
+
+	spin_unlock_irq(&np->lock);
+
+	nv_free_irq(dev);
+
+	np->msi_flags = save_msi_flags;
+
+	if (netif_running(dev)) {
+		writel(save_poll_interval, base + NvRegPollingInterval);
+		writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6);
+		/* restore original irq */
+		if (nv_request_irq(dev, 0))
+			return 0;
+	}
+
+	return ret;
+}
+
+static int nv_loopback_test(struct net_device *dev)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	struct sk_buff *tx_skb, *rx_skb;
+	dma_addr_t test_dma_addr;
+	u32 tx_flags_extra = (np->desc_ver == DESC_VER_1 ? NV_TX_LASTPACKET : NV_TX2_LASTPACKET);
+	u32 Flags;
+	int len, i, pkt_len;
+	u8 *pkt_data;
+	u32 filter_flags = 0;
+	u32 misc1_flags = 0;
+	int ret = 1;
+
+	if (netif_running(dev)) {
+		nv_disable_irq(dev);
+		filter_flags = readl(base + NvRegPacketFilterFlags);
+		misc1_flags = readl(base + NvRegMisc1);
+	} else {
+		nv_txrx_reset(dev);
+	}
+
+	/* reinit driver view of the rx queue */
+	set_bufsize(dev);
+	nv_init_ring(dev);
+
+	/* setup hardware for loopback */
+	writel(NVREG_MISC1_FORCE, base + NvRegMisc1);
+	writel(NVREG_PFF_ALWAYS | NVREG_PFF_LOOPBACK, base + NvRegPacketFilterFlags);
+
+	/* reinit nic view of the rx queue */
+	writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+	setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
+	writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+		base + NvRegRingSizes);
+	pci_push(base);
+
+	/* restart rx engine */
+	nv_start_rx(dev);
+	nv_start_tx(dev);
+
+	/* setup packet for tx */
+	pkt_len = ETH_DATA_LEN;
+	tx_skb = dev_alloc_skb(pkt_len);
+	pkt_data = skb_put(tx_skb, pkt_len);
+	for (i = 0; i < pkt_len; i++)
+		pkt_data[i] = (u8)(i & 0xff);
+	test_dma_addr = pci_map_single(np->pci_dev, tx_skb->data,
+				       tx_skb->end-tx_skb->data, PCI_DMA_FROMDEVICE);
+
+	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+		np->tx_ring.orig[0].PacketBuffer = cpu_to_le32(test_dma_addr);
+		np->tx_ring.orig[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+	} else {
+		np->tx_ring.ex[0].PacketBufferHigh = cpu_to_le64(test_dma_addr) >> 32;
+		np->tx_ring.ex[0].PacketBufferLow = cpu_to_le64(test_dma_addr) & 0x0FFFFFFFF;
+		np->tx_ring.ex[0].FlagLen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
+	}
+	writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+	pci_push(get_hwbase(dev));
+
+	msleep(500);
+
+	/* check for rx of the packet */
+	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
+		Flags = le32_to_cpu(np->rx_ring.orig[0].FlagLen);
+		len = nv_descr_getlength(&np->rx_ring.orig[0], np->desc_ver);
+
+	} else {
+		Flags = le32_to_cpu(np->rx_ring.ex[0].FlagLen);
+		len = nv_descr_getlength_ex(&np->rx_ring.ex[0], np->desc_ver);
+	}
+
+	if (Flags & NV_RX_AVAIL) {
+		ret = 0;
+	} else if (np->desc_ver == DESC_VER_1) {
+		if (Flags & NV_RX_ERROR)
+			ret = 0;
+	} else {
+		if (Flags & NV_RX2_ERROR) {
+			ret = 0;
+		}
+	}
+
+	if (ret) {
+		if (len != pkt_len) {
+			ret = 0;
+			dprintk(KERN_DEBUG "%s: loopback len mismatch %d vs %d\n",
+				dev->name, len, pkt_len);
+		} else {
+			rx_skb = np->rx_skbuff[0];
+			for (i = 0; i < pkt_len; i++) {
+				if (rx_skb->data[i] != (u8)(i & 0xff)) {
+					ret = 0;
+					dprintk(KERN_DEBUG "%s: loopback pattern check failed on byte %d\n",
+						dev->name, i);
+					break;
+				}
+			}
+		}
+	} else {
+		dprintk(KERN_DEBUG "%s: loopback - did not receive test packet\n", dev->name);
+	}
+
+	pci_unmap_page(np->pci_dev, test_dma_addr,
+		       tx_skb->end-tx_skb->data,
+		       PCI_DMA_TODEVICE);
+	dev_kfree_skb_any(tx_skb);
+
+	/* stop engines */
+	nv_stop_rx(dev);
+	nv_stop_tx(dev);
+	nv_txrx_reset(dev);
+	/* drain rx queue */
+	nv_drain_rx(dev);
+	nv_drain_tx(dev);
+
+	if (netif_running(dev)) {
+		writel(misc1_flags, base + NvRegMisc1);
+		writel(filter_flags, base + NvRegPacketFilterFlags);
+		nv_enable_irq(dev);
+	}
+
+	return ret;
+}
+
+static void nv_self_test(struct net_device *dev, struct ethtool_test *test, u64 *buffer)
+{
+	struct fe_priv *np = netdev_priv(dev);
+	u8 __iomem *base = get_hwbase(dev);
+	int result;
+	memset(buffer, 0, nv_self_test_count(dev)*sizeof(u64));
+
+	if (!nv_link_test(dev)) {
+		test->flags |= ETH_TEST_FL_FAILED;
+		buffer[0] = 1;
+	}
+
+	if (test->flags & ETH_TEST_FL_OFFLINE) {
+		if (netif_running(dev)) {
+			netif_stop_queue(dev);
+			netif_tx_lock_bh(dev);
+			spin_lock_irq(&np->lock);
+			nv_disable_hw_interrupts(dev, np->irqmask);
+			if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
+				writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
+			} else {
+				writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
+			}
+			/* stop engines */
+			nv_stop_rx(dev);
+			nv_stop_tx(dev);
+			nv_txrx_reset(dev);
+			/* drain rx queue */
+			nv_drain_rx(dev);
+			nv_drain_tx(dev);
+			spin_unlock_irq(&np->lock);
+			netif_tx_unlock_bh(dev);
+		}
+
+		if (!nv_register_test(dev)) {
+			test->flags |= ETH_TEST_FL_FAILED;
+			buffer[1] = 1;
+		}
+
+		result = nv_interrupt_test(dev);
+		if (result != 1) {
+			test->flags |= ETH_TEST_FL_FAILED;
+			buffer[2] = 1;
+		}
+		if (result == 0) {
+			/* bail out */
+			return;
+		}
+
+		if (!nv_loopback_test(dev)) {
+			test->flags |= ETH_TEST_FL_FAILED;
+			buffer[3] = 1;
+		}
+
+		if (netif_running(dev)) {
+			/* reinit driver view of the rx queue */
+			set_bufsize(dev);
+			if (nv_init_ring(dev)) {
+				if (!np->in_shutdown)
+					mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+			}
+			/* reinit nic view of the rx queue */
+			writel(np->rx_buf_sz, base + NvRegOffloadConfig);
+			setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
+			writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
+				base + NvRegRingSizes);
+			pci_push(base);
+			writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+			pci_push(base);
+			/* restart rx engine */
+			nv_start_rx(dev);
+			nv_start_tx(dev);
+			netif_start_queue(dev);
+			nv_enable_hw_interrupts(dev, np->irqmask);
+		}
+	}
+}
+
+static void nv_get_strings(struct net_device *dev, u32 stringset, u8 *buffer)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(buffer, &nv_estats_str, nv_get_stats_count(dev)*sizeof(struct nv_ethtool_str));
+		break;
+	case ETH_SS_TEST:
+		memcpy(buffer, &nv_etests_str, nv_self_test_count(dev)*sizeof(struct nv_ethtool_str));
+		break;
+	}
+}
 
 static struct ethtool_ops ops = {
 	.get_drvinfo = nv_get_drvinfo,
@@ -2638,10 +3815,23 @@
 	.get_regs = nv_get_regs,
 	.nway_reset = nv_nway_reset,
 	.get_perm_addr = ethtool_op_get_perm_addr,
-#ifdef NETIF_F_TSO
 	.get_tso = ethtool_op_get_tso,
-	.set_tso = nv_set_tso
-#endif
+	.set_tso = nv_set_tso,
+	.get_ringparam = nv_get_ringparam,
+	.set_ringparam = nv_set_ringparam,
+	.get_pauseparam = nv_get_pauseparam,
+	.set_pauseparam = nv_set_pauseparam,
+	.get_rx_csum = nv_get_rx_csum,
+	.set_rx_csum = nv_set_rx_csum,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = nv_set_tx_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = nv_set_sg,
+	.get_strings = nv_get_strings,
+	.get_stats_count = nv_get_stats_count,
+	.get_ethtool_stats = nv_get_ethtool_stats,
+	.self_test_count = nv_self_test_count,
+	.self_test = nv_self_test,
 };
 
 static void nv_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
@@ -2672,139 +3862,6 @@
 	/* nothing to do */
 };
 
-static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask)
-{
-	u8 __iomem *base = get_hwbase(dev);
-	int i;
-	u32 msixmap = 0;
-
-	/* Each interrupt bit can be mapped to a MSIX vector (4 bits).
-	 * MSIXMap0 represents the first 8 interrupts and MSIXMap1 represents
-	 * the remaining 8 interrupts.
-	 */
-	for (i = 0; i < 8; i++) {
-		if ((irqmask >> i) & 0x1) {
-			msixmap |= vector << (i << 2);
-		}
-	}
-	writel(readl(base + NvRegMSIXMap0) | msixmap, base + NvRegMSIXMap0);
-
-	msixmap = 0;
-	for (i = 0; i < 8; i++) {
-		if ((irqmask >> (i + 8)) & 0x1) {
-			msixmap |= vector << (i << 2);
-		}
-	}
-	writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1);
-}
-
-static int nv_request_irq(struct net_device *dev)
-{
-	struct fe_priv *np = get_nvpriv(dev);
-	u8 __iomem *base = get_hwbase(dev);
-	int ret = 1;
-	int i;
-
-	if (np->msi_flags & NV_MSI_X_CAPABLE) {
-		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
-			np->msi_x_entry[i].entry = i;
-		}
-		if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) {
-			np->msi_flags |= NV_MSI_X_ENABLED;
-			if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) {
-				/* Request irq for rx handling */
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret);
-					pci_disable_msix(np->pci_dev);
-					np->msi_flags &= ~NV_MSI_X_ENABLED;
-					goto out_err;
-				}
-				/* Request irq for tx handling */
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret);
-					pci_disable_msix(np->pci_dev);
-					np->msi_flags &= ~NV_MSI_X_ENABLED;
-					goto out_free_rx;
-				}
-				/* Request irq for link and timer handling */
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret);
-					pci_disable_msix(np->pci_dev);
-					np->msi_flags &= ~NV_MSI_X_ENABLED;
-					goto out_free_tx;
-				}
-				/* map interrupts to their respective vector */
-				writel(0, base + NvRegMSIXMap0);
-				writel(0, base + NvRegMSIXMap1);
-				set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL);
-				set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL);
-				set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER);
-			} else {
-				/* Request irq for all interrupts */
-				if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
-					printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
-					pci_disable_msix(np->pci_dev);
-					np->msi_flags &= ~NV_MSI_X_ENABLED;
-					goto out_err;
-				}
-
-				/* map interrupts to vector 0 */
-				writel(0, base + NvRegMSIXMap0);
-				writel(0, base + NvRegMSIXMap1);
-			}
-		}
-	}
-	if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) {
-		if ((ret = pci_enable_msi(np->pci_dev)) == 0) {
-			np->msi_flags |= NV_MSI_ENABLED;
-			if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) {
-				printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret);
-				pci_disable_msi(np->pci_dev);
-				np->msi_flags &= ~NV_MSI_ENABLED;
-				goto out_err;
-			}
-
-			/* map interrupts to vector 0 */
-			writel(0, base + NvRegMSIMap0);
-			writel(0, base + NvRegMSIMap1);
-			/* enable msi vector 0 */
-			writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask);
-		}
-	}
-	if (ret != 0) {
-		if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0)
-			goto out_err;
-	}
-
-	return 0;
-out_free_tx:
-	free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev);
-out_free_rx:
-	free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev);
-out_err:
-	return 1;
-}
-
-static void nv_free_irq(struct net_device *dev)
-{
-	struct fe_priv *np = get_nvpriv(dev);
-	int i;
-
-	if (np->msi_flags & NV_MSI_X_ENABLED) {
-		for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) {
-			free_irq(np->msi_x_entry[i].vector, dev);
-		}
-		pci_disable_msix(np->pci_dev);
-		np->msi_flags &= ~NV_MSI_X_ENABLED;
-	} else {
-		free_irq(np->pci_dev->irq, dev);
-		if (np->msi_flags & NV_MSI_ENABLED) {
-			pci_disable_msi(np->pci_dev);
-			np->msi_flags &= ~NV_MSI_ENABLED;
-		}
-	}
-}
-
 static int nv_open(struct net_device *dev)
 {
 	struct fe_priv *np = netdev_priv(dev);
@@ -2829,6 +3886,9 @@
 
 	writel(0, base + NvRegAdapterControl);
 
+	if (np->pause_flags & NV_PAUSEFRAME_TX_CAPABLE)
+		writel(NVREG_TX_PAUSEFRAME_DISABLE,  base + NvRegTxPauseFrame);
+
 	/* 2) initialize descriptor rings */
 	set_bufsize(dev);
 	oom = nv_init_ring(dev);
@@ -2845,7 +3905,7 @@
 
 	/* 4) give hw rings */
 	setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING);
-	writel( ((RX_RING-1) << NVREG_RINGSZ_RXSHIFT) + ((TX_RING-1) << NVREG_RINGSZ_TXSHIFT),
+	writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT),
 		base + NvRegRingSizes);
 
 	/* 5) continue setup */
@@ -2887,7 +3947,8 @@
 			base + NvRegAdapterControl);
 	writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed);
 	writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4);
-	writel(NVREG_WAKEUPFLAGS_VAL, base + NvRegWakeUpFlags);
+	if (np->wolenabled)
+		writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags);
 
 	i = readl(base + NvRegPowerState);
 	if ( (i & NVREG_POWERSTATE_POWEREDUP) == 0)
@@ -2903,7 +3964,7 @@
 	writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
 	pci_push(base);
 
-	if (nv_request_irq(dev)) {
+	if (nv_request_irq(dev, 0)) {
 		goto out_drain;
 	}
 
@@ -2940,6 +4001,11 @@
 	}
 	if (oom)
 		mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
+
+	/* start statistics timer */
+	if (np->driver_data & DEV_HAS_STATISTICS)
+		mod_timer(&np->stats_poll, jiffies + STATS_INTERVAL);
+
 	spin_unlock_irq(&np->lock);
 
 	return 0;
@@ -2960,6 +4026,7 @@
 
 	del_timer_sync(&np->oom_kick);
 	del_timer_sync(&np->nic_poll);
+	del_timer_sync(&np->stats_poll);
 
 	netif_stop_queue(dev);
 	spin_lock_irq(&np->lock);
@@ -3019,6 +4086,9 @@
 	init_timer(&np->nic_poll);
 	np->nic_poll.data = (unsigned long) dev;
 	np->nic_poll.function = &nv_do_nic_poll;	/* timer handler */
+	init_timer(&np->stats_poll);
+	np->stats_poll.data = (unsigned long) dev;
+	np->stats_poll.function = &nv_do_stats_poll;	/* timer handler */
 
 	err = pci_enable_device(pci_dev);
 	if (err) {
@@ -3033,7 +4103,7 @@
 	if (err < 0)
 		goto out_disable;
 
-	if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL))
+	if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_STATISTICS))
 		np->register_size = NV_PCI_REGSZ_VER2;
 	else
 		np->register_size = NV_PCI_REGSZ_VER1;
@@ -3065,16 +4135,18 @@
 		/* packet format 3: supports 40-bit addressing */
 		np->desc_ver = DESC_VER_3;
 		np->txrxctl_bits = NVREG_TXRXCTL_DESC_3;
-		if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
-			printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
-					pci_name(pci_dev));
-		} else {
-			dev->features |= NETIF_F_HIGHDMA;
-			printk(KERN_INFO "forcedeth: using HIGHDMA\n");
-		}
-		if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) {
-			printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n",
-			       pci_name(pci_dev));
+		if (dma_64bit) {
+			if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) {
+				printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n",
+				       pci_name(pci_dev));
+			} else {
+				dev->features |= NETIF_F_HIGHDMA;
+				printk(KERN_INFO "forcedeth: using HIGHDMA\n");
+			}
+			if (pci_set_consistent_dma_mask(pci_dev, DMA_39BIT_MASK)) {
+				printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed, using 32-bit ring buffers for device %s.\n",
+				       pci_name(pci_dev));
+			}
 		}
 	} else if (id->driver_data & DEV_HAS_LARGEDESC) {
 		/* packet format 2: supports jumbo frames */
@@ -3107,13 +4179,19 @@
 	}
 
 	np->msi_flags = 0;
-	if ((id->driver_data & DEV_HAS_MSI) && !disable_msi) {
+	if ((id->driver_data & DEV_HAS_MSI) && msi) {
 		np->msi_flags |= NV_MSI_CAPABLE;
 	}
-	if ((id->driver_data & DEV_HAS_MSI_X) && !disable_msix) {
+	if ((id->driver_data & DEV_HAS_MSI_X) && msix) {
 		np->msi_flags |= NV_MSI_X_CAPABLE;
 	}
 
+	np->pause_flags = NV_PAUSEFRAME_RX_CAPABLE | NV_PAUSEFRAME_RX_REQ | NV_PAUSEFRAME_AUTONEG;
+	if (id->driver_data & DEV_HAS_PAUSEFRAME_TX) {
+		np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ;
+	}
+
+
 	err = -ENOMEM;
 	np->base = ioremap(addr, np->register_size);
 	if (!np->base)
@@ -3122,21 +4200,38 @@
 
 	dev->irq = pci_dev->irq;
 
+	np->rx_ring_size = RX_RING_DEFAULT;
+	np->tx_ring_size = TX_RING_DEFAULT;
+	np->tx_limit_stop = np->tx_ring_size - TX_LIMIT_DIFFERENCE;
+	np->tx_limit_start = np->tx_ring_size - TX_LIMIT_DIFFERENCE - 1;
+
 	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
 		np->rx_ring.orig = pci_alloc_consistent(pci_dev,
-					sizeof(struct ring_desc) * (RX_RING + TX_RING),
+					sizeof(struct ring_desc) * (np->rx_ring_size + np->tx_ring_size),
 					&np->ring_addr);
 		if (!np->rx_ring.orig)
 			goto out_unmap;
-		np->tx_ring.orig = &np->rx_ring.orig[RX_RING];
+		np->tx_ring.orig = &np->rx_ring.orig[np->rx_ring_size];
 	} else {
 		np->rx_ring.ex = pci_alloc_consistent(pci_dev,
-					sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
+					sizeof(struct ring_desc_ex) * (np->rx_ring_size + np->tx_ring_size),
 					&np->ring_addr);
 		if (!np->rx_ring.ex)
 			goto out_unmap;
-		np->tx_ring.ex = &np->rx_ring.ex[RX_RING];
+		np->tx_ring.ex = &np->rx_ring.ex[np->rx_ring_size];
 	}
+	np->rx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->rx_ring_size, GFP_KERNEL);
+	np->rx_dma = kmalloc(sizeof(dma_addr_t) * np->rx_ring_size, GFP_KERNEL);
+	np->tx_skbuff = kmalloc(sizeof(struct sk_buff*) * np->tx_ring_size, GFP_KERNEL);
+	np->tx_dma = kmalloc(sizeof(dma_addr_t) * np->tx_ring_size, GFP_KERNEL);
+	np->tx_dma_len = kmalloc(sizeof(unsigned int) * np->tx_ring_size, GFP_KERNEL);
+	if (!np->rx_skbuff || !np->rx_dma || !np->tx_skbuff || !np->tx_dma || !np->tx_dma_len)
+		goto out_freering;
+	memset(np->rx_skbuff, 0, sizeof(struct sk_buff*) * np->rx_ring_size);
+	memset(np->rx_dma, 0, sizeof(dma_addr_t) * np->rx_ring_size);
+	memset(np->tx_skbuff, 0, sizeof(struct sk_buff*) * np->tx_ring_size);
+	memset(np->tx_dma, 0, sizeof(dma_addr_t) * np->tx_ring_size);
+	memset(np->tx_dma_len, 0, sizeof(unsigned int) * np->tx_ring_size);
 
 	dev->open = nv_open;
 	dev->stop = nv_close;
@@ -3258,9 +4353,9 @@
 	if (i == 33) {
 		printk(KERN_INFO "%s: open: Could not find a valid PHY.\n",
 		       pci_name(pci_dev));
-		goto out_freering;
+		goto out_error;
 	}
-	
+
 	/* reset it */
 	phy_init(dev);
 
@@ -3272,7 +4367,7 @@
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_INFO "forcedeth: unable to register netdev: %d\n", err);
-		goto out_freering;
+		goto out_error;
 	}
 	printk(KERN_INFO "%s: forcedeth.c: subsystem: %05x:%04x bound to %s\n",
 			dev->name, pci_dev->subsystem_vendor, pci_dev->subsystem_device,
@@ -3280,14 +4375,10 @@
 
 	return 0;
 
-out_freering:
-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-		pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING),
-				    np->rx_ring.orig, np->ring_addr);
-	else
-		pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING),
-				    np->rx_ring.ex, np->ring_addr);
+out_error:
 	pci_set_drvdata(pci_dev, NULL);
+out_freering:
+	free_rings(dev);
 out_unmap:
 	iounmap(get_hwbase(dev));
 out_relreg:
@@ -3303,15 +4394,11 @@
 static void __devexit nv_remove(struct pci_dev *pci_dev)
 {
 	struct net_device *dev = pci_get_drvdata(pci_dev);
-	struct fe_priv *np = netdev_priv(dev);
 
 	unregister_netdev(dev);
 
 	/* free all structures */
-	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2)
-		pci_free_consistent(np->pci_dev, sizeof(struct ring_desc) * (RX_RING + TX_RING), np->rx_ring.orig, np->ring_addr);
-	else
-		pci_free_consistent(np->pci_dev, sizeof(struct ring_desc_ex) * (RX_RING + TX_RING), np->rx_ring.ex, np->ring_addr);
+	free_rings(dev);
 	iounmap(get_hwbase(dev));
 	pci_release_regions(pci_dev);
 	pci_disable_device(pci_dev);
@@ -3374,11 +4461,43 @@
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
 	},
 	{	/* MCP55 Ethernet Controller */
 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15),
-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL,
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP61 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP61 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP61 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP61 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP65 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP65 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP65 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
+	},
+	{	/* MCP65 Ethernet Controller */
+		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23),
+		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED,
 	},
 	{0,},
 };
@@ -3408,10 +4527,12 @@
 MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer.");
 module_param(poll_interval, int, 0);
 MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535.");
-module_param(disable_msi, int, 0);
-MODULE_PARM_DESC(disable_msi, "Disable MSI interrupts by setting to 1.");
-module_param(disable_msix, int, 0);
-MODULE_PARM_DESC(disable_msix, "Disable MSIX interrupts by setting to 1.");
+module_param(msi, int, 0);
+MODULE_PARM_DESC(msi, "MSI interrupts are enabled by setting to 1 and disabled by setting to 0.");
+module_param(msix, int, 0);
+MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0.");
+module_param(dma_64bit, int, 0);
+MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0.");
 
 MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>");
 MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver");
diff --git a/drivers/net/fs_enet/fs_enet-mii.c b/drivers/net/fs_enet/fs_enet-mii.c
index c677037..0cd0715 100644
--- a/drivers/net/fs_enet/fs_enet-mii.c
+++ b/drivers/net/fs_enet/fs_enet-mii.c
@@ -431,8 +431,7 @@
 	return bus;
 
 err:
-	if (bus)
-		kfree(bus);
+	kfree(bus);
 	return ERR_PTR(ret);
 }
 
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 102c1f0..d12605f 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -308,9 +308,9 @@
 {
 	struct sockaddr_ax25 *sa = addr;
 
-	spin_lock_irq(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
-	spin_unlock_irq(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 
 	return 0;
 }
@@ -767,9 +767,9 @@
 			break;
 		}
 
-		spin_lock_irq(&dev->xmit_lock);
+		netif_tx_lock_bh(dev);
 		memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
-		spin_unlock_irq(&dev->xmit_lock);
+		netif_tx_unlock_bh(dev);
 
 		err = 0;
 		break;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index 0d5fccc..c9a46b8 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -436,7 +436,7 @@
 module_init(dmascc_init);
 module_exit(dmascc_exit);
 
-static void dev_setup(struct net_device *dev)
+static void __init dev_setup(struct net_device *dev)
 {
 	dev->type = ARPHRD_AX25;
 	dev->hard_header_len = AX25_MAX_HEADER_LEN;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index d81a8e1..3ebbbe5 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -357,9 +357,9 @@
 {
 	struct sockaddr_ax25 *sa = addr;
 
-	spin_lock_irq(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
-	spin_unlock_irq(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 
 	return 0;
 }
@@ -886,9 +886,9 @@
 			break;
 		}
 
-		spin_lock_irq(&dev->xmit_lock);
+		netif_tx_lock_bh(dev);
 		memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
-		spin_unlock_irq(&dev->xmit_lock);
+		netif_tx_unlock_bh(dev);
 
 		err = 0;
 		break;
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 0d7a625..e26a3e4 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -446,7 +446,7 @@
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
 	struct net_device *dev;
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index cf9fb36..551a71b 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -384,7 +384,7 @@
 }
 
 /* This function resets the ethercard if something screws up. */
-static void
+static void __init
 hp_init_card(struct net_device *dev)
 {
 	int irq = dev->irq;
@@ -409,7 +409,7 @@
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
 	struct net_device *dev;
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 247c8ca..dd1dc32 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -1487,11 +1487,8 @@
 	if (skb->len <= 0)
 		return 0;
 		
-	if (skb->len < ETH_ZLEN && lp->chip == HP100_CHIPID_SHASTA) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
-	}
+	if (lp->chip == HP100_CHIPID_SHASTA && skb_padto(skb, ETH_ZLEN))
+		return 0;
 
 	/* Get Tx ring tail pointer */
 	if (lp->txrtail->next == lp->txrhead) {
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index 01ad904..51fd516 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -1,4 +1,4 @@
-/* 
+/*
 net-3-driver for the IBM LAN Adapter/A
 
 This is an extension to the Linux operating system, and is covered by the
@@ -11,9 +11,9 @@
 SK_G16 and 3C523 driver.
 
 paper sources:
-  'PC Hardware: Aufbau, Funktionsweise, Programmierung' by 
+  'PC Hardware: Aufbau, Funktionsweise, Programmierung' by
   Hans-Peter Messmer for the basic Microchannel stuff
-  
+
   'Linux Geraetetreiber' by Allesandro Rubini, Kalle Dalheimer
   for help on Ethernet driver programming
 
@@ -27,14 +27,14 @@
 
 special acknowledgements to:
   - Bob Eager for helping me out with documentation from IBM
-  - Jim Shorney for his endless patience with me while I was using 
+  - Jim Shorney for his endless patience with me while I was using
     him as a beta tester to trace down the address filter bug ;-)
 
   Missing things:
 
   -> set debug level via ioctl instead of compile-time switches
   -> I didn't follow the development of the 2.1.x kernels, so my
-     assumptions about which things changed with which kernel version 
+     assumptions about which things changed with which kernel version
      are probably nonsense
 
 History:
@@ -275,7 +275,7 @@
 	priv->rrastart = raddr = priv->txbufstart + (TXBUFCNT * PKTSIZE);
 	priv->rdastart = addr = priv->rrastart + (priv->rxbufcnt * sizeof(rra_t));
 	priv->rxbufstart = baddr = priv->rdastart + (priv->rxbufcnt * sizeof(rda_t));
-	
+
 	for (z = 0; z < priv->rxbufcnt; z++) {
 		rra.startlo = baddr;
 		rra.starthi = 0;
@@ -570,7 +570,7 @@
 		lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t));
 		memcpy_fromio(&rda, priv->base + rdaaddr, sizeof(rda_t));
 
-		/* iron out upper word halves of fields we use - SONIC will duplicate 
+		/* iron out upper word halves of fields we use - SONIC will duplicate
 		   bits 0..15 to 16..31 */
 
 		rda.status &= 0xffff;
@@ -836,9 +836,9 @@
 	baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE);
 	memcpy_toio(priv->base + baddr, skb->data, skb->len);
 
-	/* copy filler into RAM - in case we're filling up... 
+	/* copy filler into RAM - in case we're filling up...
 	   we're filling a bit more than necessary, but that doesn't harm
-	   since the buffer is far larger... 
+	   since the buffer is far larger...
 	   Sorry Linus for the filler string but I couldn't resist ;-) */
 
 	if (tmplen > skb->len) {
@@ -952,7 +952,7 @@
 	priv->realirq = irq;
 	priv->medium = medium;
 	spin_lock_init(&priv->lock);
-		
+
 
 	/* set base + irq for this device (irq not allocated so far) */
 
diff --git a/drivers/net/ibmlana.h b/drivers/net/ibmlana.h
index 458ee22..6b58bab 100644
--- a/drivers/net/ibmlana.h
+++ b/drivers/net/ibmlana.h
@@ -17,7 +17,7 @@
 /* media enumeration - defined in a way that it fits onto the LAN/A's
    POS registers... */
 
-typedef enum { 
+typedef enum {
 	Media_10BaseT, Media_10Base5,
 	Media_Unknown, Media_10Base2, Media_Count
 } ibmlana_medium;
@@ -27,7 +27,7 @@
 typedef struct {
 	unsigned int slot;		/* MCA-Slot-#                       */
 	struct net_device_stats stat;	/* packet statistics            */
-	int realirq;			/* memorizes actual IRQ, even when 
+	int realirq;			/* memorizes actual IRQ, even when
 					   currently not allocated          */
 	ibmlana_medium medium;		/* physical cannector               */
 	u32 	tdastart, txbufstart,	/* addresses                        */
@@ -41,7 +41,7 @@
 	spinlock_t lock;
 } ibmlana_priv;
 
-/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes 
+/* this card uses quite a lot of I/O ports...luckily the MCA bus decodes
    a full 64K I/O range... */
 
 #define IBM_LANA_IORANGE 0xa0
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index 52d0102..4c2e727 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -24,7 +24,7 @@
 /* for use with IBM i/pSeries LPAR Linux.  It utilizes the logical LAN    */
 /* option of the RS/6000 Platform Architechture to interface with virtual */
 /* ethernet NICs that are presented to the partition by the hypervisor.   */
-/*                                                                        */ 
+/*                                                                        */
 /**************************************************************************/
 /*
   TODO:
@@ -61,7 +61,7 @@
 #undef DEBUG
 
 #define ibmveth_printk(fmt, args...) \
-  printk(KERN_INFO "%s: " fmt, __FILE__, ## args)
+  printk(KERN_DEBUG "%s: " fmt, __FILE__, ## args)
 
 #define ibmveth_error_printk(fmt, args...) \
   printk(KERN_ERR "(%s:%3.3d ua:%x) ERROR: " fmt, __FILE__, __LINE__ , adapter->vdev->unit_address, ## args)
@@ -79,7 +79,7 @@
 #else
 #define ibmveth_debug_printk_no_adapter(fmt, args...)
 #define ibmveth_debug_printk(fmt, args...)
-#define ibmveth_assert(expr) 
+#define ibmveth_assert(expr)
 #endif
 
 static int ibmveth_open(struct net_device *dev);
@@ -96,6 +96,7 @@
 static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter);
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 static inline void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
+static struct kobj_type ktype_veth_pool;
 
 #ifdef CONFIG_PROC_FS
 #define IBMVETH_PROC_DIR "net/ibmveth"
@@ -133,12 +134,13 @@
 }
 
 /* setup the initial settings for a buffer pool */
-static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size)
+static void ibmveth_init_buffer_pool(struct ibmveth_buff_pool *pool, u32 pool_index, u32 pool_size, u32 buff_size, u32 pool_active)
 {
 	pool->size = pool_size;
 	pool->index = pool_index;
 	pool->buff_size = buff_size;
 	pool->threshold = pool_size / 2;
+	pool->active = pool_active;
 }
 
 /* allocate and setup an buffer pool - called during open */
@@ -146,13 +148,13 @@
 {
 	int i;
 
-	pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL); 
+	pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL);
 
 	if(!pool->free_map) {
 		return -1;
 	}
 
-	pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL); 
+	pool->dma_addr = kmalloc(sizeof(dma_addr_t) * pool->size, GFP_KERNEL);
 	if(!pool->dma_addr) {
 		kfree(pool->free_map);
 		pool->free_map = NULL;
@@ -180,7 +182,6 @@
 	atomic_set(&pool->available, 0);
 	pool->producer_index = 0;
 	pool->consumer_index = 0;
-	pool->active = 0;
 
 	return 0;
 }
@@ -214,7 +215,7 @@
 
 		free_index = pool->consumer_index++ % pool->size;
 		index = pool->free_map[free_index];
-	
+
 		ibmveth_assert(index != IBM_VETH_INVALID_MAP);
 		ibmveth_assert(pool->skbuff[index] == NULL);
 
@@ -231,10 +232,10 @@
 		desc.desc = 0;
 		desc.fields.valid = 1;
 		desc.fields.length = pool->buff_size;
-		desc.fields.address = dma_addr; 
+		desc.fields.address = dma_addr;
 
 		lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
-		    
+
 		if(lpar_rc != H_SUCCESS) {
 			pool->free_map[free_index] = index;
 			pool->skbuff[index] = NULL;
@@ -250,13 +251,13 @@
 			adapter->replenish_add_buff_success++;
 		}
 	}
-    
+
 	mb();
 	atomic_add(buffers_added, &(pool->available));
 }
 
 /* replenish routine */
-static void ibmveth_replenish_task(struct ibmveth_adapter *adapter) 
+static void ibmveth_replenish_task(struct ibmveth_adapter *adapter)
 {
 	int i;
 
@@ -264,7 +265,7 @@
 
 	for(i = 0; i < IbmVethNumBufferPools; i++)
 		if(adapter->rx_buff_pool[i].active)
-			ibmveth_replenish_buffer_pool(adapter, 
+			ibmveth_replenish_buffer_pool(adapter,
 						     &adapter->rx_buff_pool[i]);
 
 	adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8);
@@ -301,7 +302,6 @@
 		kfree(pool->skbuff);
 		pool->skbuff = NULL;
 	}
-	pool->active = 0;
 }
 
 /* remove a buffer from a pool */
@@ -372,7 +372,7 @@
 	desc.fields.address = adapter->rx_buff_pool[pool].dma_addr[index];
 
 	lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc);
-		    
+
 	if(lpar_rc != H_SUCCESS) {
 		ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc);
 		ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
@@ -407,7 +407,7 @@
 		}
 		free_page((unsigned long)adapter->buffer_list_addr);
 		adapter->buffer_list_addr = NULL;
-	} 
+	}
 
 	if(adapter->filter_list_addr != NULL) {
 		if(!dma_mapping_error(adapter->filter_list_dma)) {
@@ -433,7 +433,9 @@
 	}
 
 	for(i = 0; i<IbmVethNumBufferPools; i++)
-		ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[i]);
+		if (adapter->rx_buff_pool[i].active)
+			ibmveth_free_buffer_pool(adapter,
+						 &adapter->rx_buff_pool[i]);
 }
 
 static int ibmveth_open(struct net_device *netdev)
@@ -450,10 +452,10 @@
 
 	for(i = 0; i<IbmVethNumBufferPools; i++)
 		rxq_entries += adapter->rx_buff_pool[i].size;
-    
+
 	adapter->buffer_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
 	adapter->filter_list_addr = (void*) get_zeroed_page(GFP_KERNEL);
- 
+
 	if(!adapter->buffer_list_addr || !adapter->filter_list_addr) {
 		ibmveth_error_printk("unable to allocate filter or buffer list pages\n");
 		ibmveth_cleanup(adapter);
@@ -489,9 +491,6 @@
 	adapter->rx_queue.num_slots = rxq_entries;
 	adapter->rx_queue.toggle = 1;
 
-	/* call change_mtu to init the buffer pools based in initial mtu */
-	ibmveth_change_mtu(netdev, netdev->mtu);
-
 	memcpy(&mac_address, netdev->dev_addr, netdev->addr_len);
 	mac_address = mac_address >> 16;
 
@@ -504,7 +503,7 @@
 	ibmveth_debug_printk("filter list @ 0x%p\n", adapter->filter_list_addr);
 	ibmveth_debug_printk("receive q   @ 0x%p\n", adapter->rx_queue.queue_addr);
 
-    
+
 	lpar_rc = h_register_logical_lan(adapter->vdev->unit_address,
 					 adapter->buffer_list_dma,
 					 rxq_desc.desc,
@@ -519,7 +518,18 @@
 				     rxq_desc.desc,
 				     mac_address);
 		ibmveth_cleanup(adapter);
-		return -ENONET; 
+		return -ENONET;
+	}
+
+	for(i = 0; i<IbmVethNumBufferPools; i++) {
+		if(!adapter->rx_buff_pool[i].active)
+			continue;
+		if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[i])) {
+			ibmveth_error_printk("unable to alloc pool\n");
+			adapter->rx_buff_pool[i].active = 0;
+			ibmveth_cleanup(adapter);
+			return -ENOMEM ;
+		}
 	}
 
 	ibmveth_debug_printk("registering irq 0x%x\n", netdev->irq);
@@ -547,10 +557,11 @@
 {
 	struct ibmveth_adapter *adapter = netdev->priv;
 	long lpar_rc;
-    
+
 	ibmveth_debug_printk("close starting\n");
 
-	netif_stop_queue(netdev);
+	if (!adapter->pool_config)
+		netif_stop_queue(netdev);
 
 	free_irq(netdev->irq, netdev);
 
@@ -694,7 +705,7 @@
 					     desc[5].desc,
 					     correlator);
 	} while ((lpar_rc == H_BUSY) && (retry_count--));
-    
+
 	if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) {
 		int i;
 		ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc);
@@ -780,7 +791,7 @@
 		/* more work to do - return that we are not done yet */
 		netdev->quota -= frames_processed;
 		*budget -= frames_processed;
-		return 1; 
+		return 1;
 	}
 
 	/* we think we are done - reenable interrupts, then check once more to make sure we are done */
@@ -806,7 +817,7 @@
 }
 
 static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
-{   
+{
 	struct net_device *netdev = dev_instance;
 	struct ibmveth_adapter *adapter = netdev->priv;
 	unsigned long lpar_rc;
@@ -862,7 +873,7 @@
 				ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc);
 			}
 		}
-	
+
 		/* re-enable filtering */
 		lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address,
 					   IbmVethMcastEnableFiltering,
@@ -876,46 +887,22 @@
 static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct ibmveth_adapter *adapter = dev->priv;
+	int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
 	int i;
-	int prev_smaller = 1;
 
-	if ((new_mtu < 68) || 
-	    (new_mtu > (pool_size[IbmVethNumBufferPools-1]) - IBMVETH_BUFF_OH))
+	if (new_mtu < IBMVETH_MAX_MTU)
 		return -EINVAL;
 
+	/* Look for an active buffer pool that can hold the new MTU */
 	for(i = 0; i<IbmVethNumBufferPools; i++) {
-		int activate = 0;
-		if (new_mtu > (pool_size[i]  - IBMVETH_BUFF_OH)) { 
-			activate = 1;
-			prev_smaller= 1;
-		} else {
-			if (prev_smaller)
-				activate = 1;
-			prev_smaller= 0;
+		if (!adapter->rx_buff_pool[i].active)
+			continue;
+		if (new_mtu_oh < adapter->rx_buff_pool[i].buff_size) {
+			dev->mtu = new_mtu;
+			return 0;
 		}
-
-		if (activate && !adapter->rx_buff_pool[i].active) {
-			struct ibmveth_buff_pool *pool = 
-						&adapter->rx_buff_pool[i];
-			if(ibmveth_alloc_buffer_pool(pool)) {
-				ibmveth_error_printk("unable to alloc pool\n");
-				return -ENOMEM;
-			}
-			adapter->rx_buff_pool[i].active = 1;
-		} else if (!activate && adapter->rx_buff_pool[i].active) {
-			adapter->rx_buff_pool[i].active = 0;
-			h_free_logical_lan_buffer(adapter->vdev->unit_address,
-					  (u64)pool_size[i]);
-		}
-
 	}
-
-	/* kick the interrupt handler so that the new buffer pools get
-	   replenished or deallocated */
-	ibmveth_interrupt(dev->irq, dev, NULL);
-
-	dev->mtu = new_mtu;
-	return 0;	
+	return -EINVAL;
 }
 
 static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
@@ -928,7 +915,7 @@
 	unsigned int *mcastFilterSize_p;
 
 
-	ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n", 
+	ibmveth_debug_printk_no_adapter("entering ibmveth_probe for UA 0x%x\n",
 					dev->unit_address);
 
 	mac_addr_p = (unsigned char *) vio_get_attribute(dev, VETH_MAC_ADDR, 0);
@@ -937,7 +924,7 @@
 				"attribute\n", __FILE__, __LINE__);
 		return 0;
 	}
-	
+
 	mcastFilterSize_p= (unsigned int *) vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, 0);
 	if(!mcastFilterSize_p) {
 		printk(KERN_ERR "(%s:%3.3d) ERROR: Can't find "
@@ -945,7 +932,7 @@
 				__FILE__, __LINE__);
 		return 0;
 	}
-	
+
 	netdev = alloc_etherdev(sizeof(struct ibmveth_adapter));
 
 	if(!netdev)
@@ -960,13 +947,14 @@
 	adapter->vdev = dev;
 	adapter->netdev = netdev;
 	adapter->mcastFilterSize= *mcastFilterSize_p;
-	
+	adapter->pool_config = 0;
+
 	/* 	Some older boxes running PHYP non-natively have an OF that
-		returns a 8-byte local-mac-address field (and the first 
+		returns a 8-byte local-mac-address field (and the first
 		2 bytes have to be ignored) while newer boxes' OF return
-		a 6-byte field. Note that IEEE 1275 specifies that 
+		a 6-byte field. Note that IEEE 1275 specifies that
 		local-mac-address must be a 6-byte field.
-		The RPA doc specifies that the first byte must be 10b, so 
+		The RPA doc specifies that the first byte must be 10b, so
 		we'll just look for it to solve this 8 vs. 6 byte field issue */
 
 	if ((*mac_addr_p & 0x3) != 0x02)
@@ -976,7 +964,7 @@
 	memcpy(&adapter->mac_addr, mac_addr_p, 6);
 
 	adapter->liobn = dev->iommu_table->it_index;
-	
+
 	netdev->irq = dev->irq;
 	netdev->open               = ibmveth_open;
 	netdev->poll               = ibmveth_poll;
@@ -989,14 +977,21 @@
 	netdev->ethtool_ops           = &netdev_ethtool_ops;
 	netdev->change_mtu         = ibmveth_change_mtu;
 	SET_NETDEV_DEV(netdev, &dev->dev);
- 	netdev->features |= NETIF_F_LLTX; 
+ 	netdev->features |= NETIF_F_LLTX;
 	spin_lock_init(&adapter->stats_lock);
 
 	memcpy(&netdev->dev_addr, &adapter->mac_addr, netdev->addr_len);
 
-	for(i = 0; i<IbmVethNumBufferPools; i++)
-		ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i, 
-					 pool_count[i], pool_size[i]);
+	for(i = 0; i<IbmVethNumBufferPools; i++) {
+		struct kobject *kobj = &adapter->rx_buff_pool[i].kobj;
+		ibmveth_init_buffer_pool(&adapter->rx_buff_pool[i], i,
+					 pool_count[i], pool_size[i],
+					 pool_active[i]);
+		kobj->parent = &dev->dev.kobj;
+		sprintf(kobj->name, "pool%d", i);
+		kobj->ktype = &ktype_veth_pool;
+		kobject_register(kobj);
+	}
 
 	ibmveth_debug_printk("adapter @ 0x%p\n", adapter);
 
@@ -1025,6 +1020,10 @@
 {
 	struct net_device *netdev = dev->dev.driver_data;
 	struct ibmveth_adapter *adapter = netdev->priv;
+	int i;
+
+	for(i = 0; i<IbmVethNumBufferPools; i++)
+		kobject_unregister(&adapter->rx_buff_pool[i].kobj);
 
 	unregister_netdev(netdev);
 
@@ -1048,7 +1047,7 @@
 	remove_proc_entry(IBMVETH_PROC_DIR, NULL);
 }
 
-static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos) 
+static void *ibmveth_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	if (*pos == 0) {
 		return (void *)1;
@@ -1063,18 +1062,18 @@
 	return NULL;
 }
 
-static void ibmveth_seq_stop(struct seq_file *seq, void *v) 
+static void ibmveth_seq_stop(struct seq_file *seq, void *v)
 {
 }
 
-static int ibmveth_seq_show(struct seq_file *seq, void *v) 
+static int ibmveth_seq_show(struct seq_file *seq, void *v)
 {
 	struct ibmveth_adapter *adapter = seq->private;
 	char *current_mac = ((char*) &adapter->netdev->dev_addr);
 	char *firmware_mac = ((char*) &adapter->mac_addr) ;
 
 	seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
-	
+
 	seq_printf(seq, "Unit Address:    0x%x\n", adapter->vdev->unit_address);
 	seq_printf(seq, "LIOBN:           0x%lx\n", adapter->liobn);
 	seq_printf(seq, "Current MAC:     %02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -1083,7 +1082,7 @@
 	seq_printf(seq, "Firmware MAC:    %02X:%02X:%02X:%02X:%02X:%02X\n",
 		   firmware_mac[0], firmware_mac[1], firmware_mac[2],
 		   firmware_mac[3], firmware_mac[4], firmware_mac[5]);
-	
+
 	seq_printf(seq, "\nAdapter Statistics:\n");
 	seq_printf(seq, "  TX:  skbuffs linearized:          %ld\n", adapter->tx_linearized);
 	seq_printf(seq, "       multi-descriptor sends:      %ld\n", adapter->tx_multidesc_send);
@@ -1095,7 +1094,7 @@
 	seq_printf(seq, "       add buffer failures:         %ld\n", adapter->replenish_add_buff_failure);
 	seq_printf(seq, "       invalid buffers:             %ld\n", adapter->rx_invalid_buffer);
 	seq_printf(seq, "       no buffers:                  %ld\n", adapter->rx_no_buffer);
-	
+
 	return 0;
 }
 static struct seq_operations ibmveth_seq_ops = {
@@ -1153,11 +1152,11 @@
 }
 
 #else /* CONFIG_PROC_FS */
-static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter) 
+static void ibmveth_proc_register_adapter(struct ibmveth_adapter *adapter)
 {
 }
 
-static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter) 
+static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapter)
 {
 }
 static void ibmveth_proc_register_driver(void)
@@ -1169,6 +1168,132 @@
 }
 #endif /* CONFIG_PROC_FS */
 
+static struct attribute veth_active_attr;
+static struct attribute veth_num_attr;
+static struct attribute veth_size_attr;
+
+static ssize_t veth_pool_show(struct kobject * kobj,
+                              struct attribute * attr, char * buf)
+{
+	struct ibmveth_buff_pool *pool = container_of(kobj,
+						      struct ibmveth_buff_pool,
+						      kobj);
+
+	if (attr == &veth_active_attr)
+		return sprintf(buf, "%d\n", pool->active);
+	else if (attr == &veth_num_attr)
+		return sprintf(buf, "%d\n", pool->size);
+	else if (attr == &veth_size_attr)
+		return sprintf(buf, "%d\n", pool->buff_size);
+	return 0;
+}
+
+static ssize_t veth_pool_store(struct kobject * kobj, struct attribute * attr,
+const char * buf, size_t count)
+{
+	struct ibmveth_buff_pool *pool = container_of(kobj,
+						      struct ibmveth_buff_pool,
+						      kobj);
+	struct net_device *netdev =
+	    container_of(kobj->parent, struct device, kobj)->driver_data;
+	struct ibmveth_adapter *adapter = netdev->priv;
+	long value = simple_strtol(buf, NULL, 10);
+	long rc;
+
+	if (attr == &veth_active_attr) {
+		if (value && !pool->active) {
+			if(ibmveth_alloc_buffer_pool(pool)) {
+                                ibmveth_error_printk("unable to alloc pool\n");
+                                return -ENOMEM;
+                        }
+			pool->active = 1;
+			adapter->pool_config = 1;
+			ibmveth_close(netdev);
+			adapter->pool_config = 0;
+			if ((rc = ibmveth_open(netdev)))
+				return rc;
+		} else if (!value && pool->active) {
+			int mtu = netdev->mtu + IBMVETH_BUFF_OH;
+			int i;
+			/* Make sure there is a buffer pool with buffers that
+			   can hold a packet of the size of the MTU */
+			for(i = 0; i<IbmVethNumBufferPools; i++) {
+				if (pool == &adapter->rx_buff_pool[i])
+					continue;
+				if (!adapter->rx_buff_pool[i].active)
+					continue;
+				if (mtu < adapter->rx_buff_pool[i].buff_size) {
+					pool->active = 0;
+					h_free_logical_lan_buffer(adapter->
+								  vdev->
+								  unit_address,
+								  pool->
+								  buff_size);
+				}
+			}
+			if (pool->active) {
+				ibmveth_error_printk("no active pool >= MTU\n");
+				return -EPERM;
+			}
+		}
+	} else if (attr == &veth_num_attr) {
+		if (value <= 0 || value > IBMVETH_MAX_POOL_COUNT)
+			return -EINVAL;
+		else {
+			adapter->pool_config = 1;
+			ibmveth_close(netdev);
+			adapter->pool_config = 0;
+			pool->size = value;
+			if ((rc = ibmveth_open(netdev)))
+				return rc;
+		}
+	} else if (attr == &veth_size_attr) {
+		if (value <= IBMVETH_BUFF_OH || value > IBMVETH_MAX_BUF_SIZE)
+			return -EINVAL;
+		else {
+			adapter->pool_config = 1;
+			ibmveth_close(netdev);
+			adapter->pool_config = 0;
+			pool->buff_size = value;
+			if ((rc = ibmveth_open(netdev)))
+				return rc;
+		}
+	}
+
+	/* kick the interrupt handler to allocate/deallocate pools */
+	ibmveth_interrupt(netdev->irq, netdev, NULL);
+	return count;
+}
+
+
+#define ATTR(_name, _mode)      \
+        struct attribute veth_##_name##_attr = {               \
+        .name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE \
+        };
+
+static ATTR(active, 0644);
+static ATTR(num, 0644);
+static ATTR(size, 0644);
+
+static struct attribute * veth_pool_attrs[] = {
+	&veth_active_attr,
+	&veth_num_attr,
+	&veth_size_attr,
+	NULL,
+};
+
+static struct sysfs_ops veth_pool_ops = {
+	.show   = veth_pool_show,
+	.store  = veth_pool_store,
+};
+
+static struct kobj_type ktype_veth_pool = {
+	.release        = NULL,
+	.sysfs_ops      = &veth_pool_ops,
+	.default_attrs  = veth_pool_attrs,
+};
+
+
 static struct vio_device_id ibmveth_device_table[] __devinitdata= {
 	{ "network", "IBM,l-lan"},
 	{ "", "" }
@@ -1198,7 +1323,7 @@
 {
 	vio_unregister_driver(&ibmveth_driver);
 	ibmveth_proc_unregister_driver();
-}	
+}
 
 module_init(ibmveth_module_init);
 module_exit(ibmveth_module_exit);
diff --git a/drivers/net/ibmveth.h b/drivers/net/ibmveth.h
index 46919a8..8385bf8 100644
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -75,10 +75,13 @@
 
 #define IbmVethNumBufferPools 5
 #define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque handle */
+#define IBMVETH_MAX_MTU 68
+#define IBMVETH_MAX_POOL_COUNT 4096
+#define IBMVETH_MAX_BUF_SIZE (1024 * 128)
 
-/* pool_size should be sorted */
 static int pool_size[] = { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 64 };
 static int pool_count[] = { 256, 768, 256, 256, 256 };
+static int pool_active[] = { 1, 1, 0, 0, 0};
 
 #define IBM_VETH_INVALID_MAP ((u16)0xffff)
 
@@ -94,6 +97,7 @@
     dma_addr_t *dma_addr;
     struct sk_buff **skbuff;
     int active;
+    struct kobject kobj;
 };
 
 struct ibmveth_rx_q {
@@ -118,6 +122,7 @@
     dma_addr_t filter_list_dma;
     struct ibmveth_buff_pool rx_buff_pool[IbmVethNumBufferPools];
     struct ibmveth_rx_q rx_queue;
+    int pool_config;
 
     /* adapter specific stats */
     u64 replenish_task_cycles;
@@ -134,7 +139,7 @@
     spinlock_t stats_lock;
 };
 
-struct ibmveth_buf_desc_fields {	
+struct ibmveth_buf_desc_fields {
     u32 valid : 1;
     u32 toggle : 1;
     u32 reserved : 6;
@@ -143,7 +148,7 @@
 };
 
 union ibmveth_buf_desc {
-    u64 desc;	
+    u64 desc;
     struct ibmveth_buf_desc_fields fields;
 };
 
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 31fb2d7..2e222ef 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -76,13 +76,13 @@
 	dp->st_task_enter++;
 	if ((skb = skb_peek(&dp->tq)) == NULL) {
 		dp->st_txq_refl_try++;
-		if (spin_trylock(&_dev->xmit_lock)) {
+		if (netif_tx_trylock(_dev)) {
 			dp->st_rxq_enter++;
 			while ((skb = skb_dequeue(&dp->rq)) != NULL) {
 				skb_queue_tail(&dp->tq, skb);
 				dp->st_rx2tx_tran++;
 			}
-			spin_unlock(&_dev->xmit_lock);
+			netif_tx_unlock(_dev);
 		} else {
 			/* reschedule */
 			dp->st_rxq_notenter++;
@@ -110,7 +110,7 @@
 		}
 	}
 
-	if (spin_trylock(&_dev->xmit_lock)) {
+	if (netif_tx_trylock(_dev)) {
 		dp->st_rxq_check++;
 		if ((skb = skb_peek(&dp->rq)) == NULL) {
 			dp->tasklet_pending = 0;
@@ -118,10 +118,10 @@
 				netif_wake_queue(_dev);
 		} else {
 			dp->st_rxq_rsch++;
-			spin_unlock(&_dev->xmit_lock);
+			netif_tx_unlock(_dev);
 			goto resched;
 		}
-		spin_unlock(&_dev->xmit_lock);
+		netif_tx_unlock(_dev);
 	} else {
 resched:
 		dp->tasklet_pending = 1;
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index ae71ed5..e76e6e7 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -145,7 +145,7 @@
 static inline unsigned long ioc3_map(void *ptr, unsigned long vdev)
 {
 #ifdef CONFIG_SGI_IP27
-	vdev <<= 58;   /* Shift to PCI64_ATTR_VIRTUAL */
+	vdev <<= 57;   /* Shift to PCI64_ATTR_VIRTUAL */
 
 	return vdev | (0xaUL << PCI64_ATTR_TARG_SHFT) | PCI64_ATTR_PREF |
 	       ((unsigned long)ptr & TO_PHYS_MASK);
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index cff8598..d2ce489 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -417,5 +417,20 @@
 	  available capabilities may vary from one PXA2xx target to
 	  another.
 
+config MCS_FIR
+	tristate "MosChip MCS7780 IrDA-USB dongle"
+	depends on IRDA && USB && EXPERIMENTAL
+	help
+	  Say Y or M here if you want to build support for the MosChip
+	  MCS7780 IrDA-USB bridge device driver.
+
+	  USB bridge based on the MosChip MCS7780 don't conform to the
+	  IrDA-USB device class specification, and therefore need their
+	  own specific driver. Those dongles support SIR and FIR (4Mbps)
+	  speeds.
+
+	  To compile it as a module, choose M here: the module will be called
+	  mcs7780.
+
 endmenu
 
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index c1ce239..5be09f1 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_VLSI_FIR)		+= vlsi_ir.o
 obj-$(CONFIG_VIA_FIR)		+= via-ircc.o
 obj-$(CONFIG_PXA_FICP)	        += pxaficp_ir.o
+obj-$(CONFIG_MCS_FIR)	        += mcs7780.o
 # Old dongle drivers for old SIR drivers
 obj-$(CONFIG_ESI_DONGLE_OLD)		+= esi.o
 obj-$(CONFIG_TEKRAM_DONGLE_OLD)	+= tekram.o
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 2e7882e..bf1fca5 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -34,14 +34,12 @@
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
 #include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 
-#include <linux/pm.h>
-#include <linux/pm_legacy.h>
-
 #include <net/irda/wrapper.h>
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>
@@ -51,7 +49,19 @@
 #define CHIP_IO_EXTENT 8
 #define BROKEN_DONGLE_ID
 
-static char *driver_name = "ali-ircc";
+#define ALI_IRCC_DRIVER_NAME "ali-ircc"
+
+/* Power Management */
+static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state);
+static int ali_ircc_resume(struct platform_device *dev);
+
+static struct platform_driver ali_ircc_driver = {
+	.suspend	= ali_ircc_suspend,
+	.resume		= ali_ircc_resume,
+	.driver		= {
+		.name	= ALI_IRCC_DRIVER_NAME,
+	},
+};
 
 /* Module parameters */
 static int qos_mtt_bits = 0x07;  /* 1 ms or more */
@@ -97,10 +107,7 @@
 static int  ali_ircc_net_open(struct net_device *dev);
 static int  ali_ircc_net_close(struct net_device *dev);
 static int  ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int  ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data);
 static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud);
-static void ali_ircc_suspend(struct ali_ircc_cb *self);
-static void ali_ircc_wakeup(struct ali_ircc_cb *self);
 static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev);
 
 /* SIR function */
@@ -145,6 +152,14 @@
 	int i = 0;
 	
 	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
+
+	ret = platform_driver_register(&ali_ircc_driver);
+        if (ret) {
+                IRDA_ERROR("%s, Can't register driver!\n",
+			   ALI_IRCC_DRIVER_NAME);
+                return ret;
+        }
+
 	
 	/* Probe for all the ALi chipsets we know about */
 	for (chip= chips; chip->name; chip++, i++) 
@@ -214,6 +229,10 @@
 	}		
 		
 	IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);					   		
+
+	if (ret)
+		platform_driver_unregister(&ali_ircc_driver);
+
 	return ret;
 }
 
@@ -228,14 +247,14 @@
 	int i;
 
 	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);	
-	
-	pm_unregister_all(ali_ircc_pmproc);
 
 	for (i=0; i < 4; i++) {
 		if (dev_self[i])
 			ali_ircc_close(dev_self[i]);
 	}
 	
+	platform_driver_unregister(&ali_ircc_driver);
+
 	IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
 }
 
@@ -249,7 +268,6 @@
 {
 	struct net_device *dev;
 	struct ali_ircc_cb *self;
-	struct pm_dev *pmdev;
 	int dongle_id;
 	int err;
 			
@@ -284,7 +302,8 @@
         self->io.fifo_size = 16;		/* SIR: 16, FIR: 32 Benjamin 2000/11/1 */
 	
 	/* Reserve the ioports that we need */
-	if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) {
+	if (!request_region(self->io.fir_base, self->io.fir_ext,
+			    ALI_IRCC_DRIVER_NAME)) {
 		IRDA_WARNING("%s(), can't get iobase of 0x%03x\n", __FUNCTION__,
 			self->io.fir_base);
 		err = -ENODEV;
@@ -354,13 +373,10 @@
 
 	/* Check dongle id */
 	dongle_id = ali_ircc_read_dongle_id(i, info);
-	IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__, driver_name, dongle_types[dongle_id]);
+	IRDA_MESSAGE("%s(), %s, Found dongle: %s\n", __FUNCTION__,
+		     ALI_IRCC_DRIVER_NAME, dongle_types[dongle_id]);
 		
 	self->io.dongle_id = dongle_id;
-	
-        pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, ali_ircc_pmproc);
-        if (pmdev)
-                pmdev->data = self;
 
 	IRDA_DEBUG(2, "%s(), ----------------- End -----------------\n", __FUNCTION__);
 	
@@ -548,12 +564,11 @@
 	/* Should be 0x00 in the M1535/M1535D */
 	if(version != 0x00)
 	{
-		IRDA_ERROR("%s, Wrong chip version %02x\n", driver_name, version);
+		IRDA_ERROR("%s, Wrong chip version %02x\n",
+			   ALI_IRCC_DRIVER_NAME, version);
 		return -1;
 	}
 	
-	// IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, info->cfg_base);
-	
 	/* Set FIR FIFO Threshold Register */
 	switch_bank(iobase, BANK1);
 	outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR);
@@ -583,7 +598,8 @@
 	/* Switch to SIR space */
 	FIR2SIR(iobase);
 	
-	IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n", driver_name);
+	IRDA_MESSAGE("%s, driver loaded (Benjamin Kong)\n",
+		     ALI_IRCC_DRIVER_NAME);
 	
 	/* Enable receive interrupts */ 
 	// outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM
@@ -647,7 +663,8 @@
 	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__);
 		
  	if (!dev) {
-		IRDA_WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
+		IRDA_WARNING("%s: irq %d for unknown device.\n",
+			     ALI_IRCC_DRIVER_NAME, irq);
 		return IRQ_NONE;
 	}	
 	
@@ -1328,7 +1345,8 @@
 	/* Request IRQ and install Interrupt Handler */
 	if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev)) 
 	{
-		IRDA_WARNING("%s, unable to allocate irq=%d\n", driver_name,
+		IRDA_WARNING("%s, unable to allocate irq=%d\n",
+			     ALI_IRCC_DRIVER_NAME,
 			     self->io.irq);
 		return -EAGAIN;
 	}
@@ -1338,7 +1356,8 @@
 	 * failure.
 	 */
 	if (request_dma(self->io.dma, dev->name)) {
-		IRDA_WARNING("%s, unable to allocate dma=%d\n", driver_name,
+		IRDA_WARNING("%s, unable to allocate dma=%d\n",
+			     ALI_IRCC_DRIVER_NAME,
 			     self->io.dma);
 		free_irq(self->io.irq, self);
 		return -EAGAIN;
@@ -2108,60 +2127,37 @@
 	return &self->stats;
 }
 
-static void ali_ircc_suspend(struct ali_ircc_cb *self)
+static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state)
 {
-	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
+	struct ali_ircc_cb *self = platform_get_drvdata(dev);
 	
-	IRDA_MESSAGE("%s, Suspending\n", driver_name);
+	IRDA_MESSAGE("%s, Suspending\n", ALI_IRCC_DRIVER_NAME);
 
 	if (self->io.suspended)
-		return;
+		return 0;
 
 	ali_ircc_net_close(self->netdev);
 
 	self->io.suspended = 1;
 	
-	IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	
-}
-
-static void ali_ircc_wakeup(struct ali_ircc_cb *self)
-{
-	IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
-	
-	if (!self->io.suspended)
-		return;
-	
-	ali_ircc_net_open(self->netdev);
-	
-	IRDA_MESSAGE("%s, Waking up\n", driver_name);
-
-	self->io.suspended = 0;
-	
-	IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	
-}
-
-static int ali_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data)
-{
-        struct ali_ircc_cb *self = (struct ali_ircc_cb*) dev->data;
-        
-        IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __FUNCTION__ );
-	
-        if (self) {
-                switch (rqst) {
-                case PM_SUSPEND:
-                        ali_ircc_suspend(self);
-                        break;
-                case PM_RESUME:
-                        ali_ircc_wakeup(self);
-                        break;
-                }
-        }
-        
-        IRDA_DEBUG(2, "%s(), ----------------- End ------------------\n", __FUNCTION__ );	
-        
 	return 0;
 }
 
+static int ali_ircc_resume(struct platform_device *dev)
+{
+	struct ali_ircc_cb *self = platform_get_drvdata(dev);
+	
+	if (!self->io.suspended)
+		return 0;
+	
+	ali_ircc_net_open(self->netdev);
+	
+	IRDA_MESSAGE("%s, Waking up\n", ALI_IRCC_DRIVER_NAME);
+
+	self->io.suspended = 0;
+
+	return 0;
+}
 
 /* ALi Chip Function */
 
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index cd87593..2a0d538 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -83,9 +83,9 @@
 	/* Extended Systems, Inc.,  XTNDAccess IrDA USB (ESI-9685) */
 	{ USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW },
 	/* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */
-	{ USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
-	{ USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
-	{ USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG },
+	{ USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR421X | IUC_SPEED_BUG },
+	{ USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR421X | IUC_SPEED_BUG },
+	{ USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR421X | IUC_SPEED_BUG },
 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
 	  USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 	  .bInterfaceClass = USB_CLASS_APP_SPEC,
@@ -154,7 +154,7 @@
 	 * and if either speed or xbofs (or both) needs
 	 * to be changed.
 	 */
-	if (self->capability & IUC_STIR_4210 &&
+	if (self->capability & IUC_STIR421X &&
 	    ((self->new_speed != -1) || (self->new_xbofs != -1))) {
 
 		/* With STIR421x, speed and xBOFs must be set at the same
@@ -318,7 +318,7 @@
 	/* Set the new speed and xbofs in this fake frame */
 	irda_usb_build_header(self, frame, 1);
 
-	if ( self->capability & IUC_STIR_4210 ) {
+	if (self->capability & IUC_STIR421X) {
 		if (frame[0] == 0) return ; // do nothing if no change
 		frame[1] = 0; // other parameters don't change here
 		frame[2] = 0;
@@ -455,7 +455,7 @@
 
 	/* Change setting for next frame */
 
-	if ( self->capability & IUC_STIR_4210 ) {
+	if (self->capability & IUC_STIR421X) {
 		__u8 turnaround_time;
 		__u8* frame;
 		turnaround_time = get_turnaround_time( skb );
@@ -897,10 +897,13 @@
 	docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);
 
 	/* Allocate a new skb */
-	if ( self->capability & IUC_STIR_4210 )
-		newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER);
+	if (self->capability & IUC_STIR421X)
+		newskb = dev_alloc_skb(docopy ? urb->actual_length :
+				       IRDA_SKB_MAX_MTU +
+				       USB_IRDA_STIR421X_HEADER);
 	else
-		newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);
+		newskb = dev_alloc_skb(docopy ? urb->actual_length :
+				       IRDA_SKB_MAX_MTU);
 
 	if (!newskb)  {
 		self->stats.rx_dropped++;
@@ -1022,188 +1025,140 @@
 	return 0; /* For now */
 }
 
-
-#define STIR421X_PATCH_PRODUCT_VERSION_STR       "Product Version: "
-#define STIR421X_PATCH_COMPONENT_VERSION_STR     "Component Version: "
-#define STIR421X_PATCH_DATA_TAG_STR              "STMP"
-#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET   512     /* version info is before here */
-#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET     512     /* patch image starts before here */
-#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG    0x1A    /* marks end of patch file header (PC DOS text file EOF character) */
+#define STIR421X_PATCH_PRODUCT_VER     "Product Version: "
+#define STIR421X_PATCH_STMP_TAG        "STMP"
+#define STIR421X_PATCH_CODE_OFFSET     512 /* patch image starts before here */
+/* marks end of patch file header (PC DOS text file EOF character) */
+#define STIR421X_PATCH_END_OF_HDR_TAG  0x1A
+#define STIR421X_PATCH_BLOCK_SIZE      1023
 
 /*
- * Known firmware patches for STIR421x dongles
+ * Function stir421x_fwupload (struct irda_usb_cb *self,
+ *                             unsigned char *patch,
+ *                             const unsigned int patch_len)
+ *
+ *   Upload firmware code to SigmaTel 421X IRDA-USB dongle
  */
-static char * stir421x_patches[] = {
-	"42101001.sb",
-	"42101002.sb",
-};
-
-static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len)
+static int stir421x_fw_upload(struct irda_usb_cb *self,
+			     unsigned char *patch,
+			     const unsigned int patch_len)
 {
-	unsigned int version_offset;
-	unsigned long version_major, version_minor, version_build;
-	unsigned char * version_start;
-	int version_found = 0;
+        int ret = -ENOMEM;
+        int actual_len = 0;
+        unsigned int i;
+        unsigned int block_size = 0;
+        unsigned char *patch_block;
 
-	for (version_offset = 0;
-	     version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG;
-	     version_offset++) {
-		if (!memcmp(patch + version_offset,
-			    STIR421X_PATCH_PRODUCT_VERSION_STR,
-			    sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) {
-				    version_found = 1;
-				    version_start = patch +
-					    version_offset +
-					    sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1;
-				    break;
-		}
+        patch_block = kzalloc(STIR421X_PATCH_BLOCK_SIZE, GFP_KERNEL);
+	if (patch_block == NULL)
+		return -ENOMEM;
+
+	/* break up patch into 1023-byte sections */
+	for (i = 0; i < patch_len; i += block_size) {
+		block_size = patch_len - i;
+
+		if (block_size > STIR421X_PATCH_BLOCK_SIZE)
+			block_size = STIR421X_PATCH_BLOCK_SIZE;
+
+		/* upload the patch section */
+		memcpy(patch_block, patch + i, block_size);
+
+		ret = usb_bulk_msg(self->usbdev,
+				   usb_sndbulkpipe(self->usbdev,
+						   self->bulk_out_ep),
+				   patch_block, block_size,
+				   &actual_len, msecs_to_jiffies(500));
+		IRDA_DEBUG(3,"%s(): Bulk send %u bytes, ret=%d\n",
+			   __FUNCTION__, actual_len, ret);
+
+		if (ret < 0)
+			break;
 	}
 
-	/* We couldn't find a product version on this patch */
-	if (!version_found)
-		return -EINVAL;
+	kfree(patch_block);
 
-	/* Let's check if the product version is dotted */
-	if (version_start[3] != '.' ||
-	    version_start[7] != '.')
-		return -EINVAL;
+        return ret;
+ }
 
-	version_major = simple_strtoul(version_start, NULL, 10);
-	version_minor = simple_strtoul(version_start + 4, NULL, 10);
-	version_build = simple_strtoul(version_start + 8, NULL, 10);
-
-	IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n",
-		   __FUNCTION__,
-		   version_major, version_minor, version_build);
-
-	return (((version_major) << 12) +
-		((version_minor) << 8) +
-		((version_build / 10) << 4) +
-		(version_build % 10));
-
-}
-
-
-static int stir421x_upload_patch (struct irda_usb_cb *self,
-				  unsigned char * patch,
-				  const unsigned int patch_len)
-{
-    int retval = 0;
-    int actual_len;
-    unsigned int i = 0, download_amount = 0;
-    unsigned char * patch_chunk;
-
-    IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__);
-
-    patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL);
-    if (patch_chunk == NULL)
-	    return -ENOMEM;
-
-    /* break up patch into 1023-byte sections */
-    for (i = 0; retval >= 0 && i < patch_len; i += download_amount) {
-	    download_amount = patch_len - i;
-	    if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE)
-		    download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE;
-
-	    /* download the patch section */
-	    memcpy(patch_chunk, patch + i, download_amount);
-
-	    retval = usb_bulk_msg (self->usbdev,
-				   usb_sndbulkpipe (self->usbdev,
-						    self->bulk_out_ep),
-				   patch_chunk, download_amount,
-				   &actual_len, msecs_to_jiffies (500));
-	    IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__,
-			actual_len);
-	    if (retval == 0)
-		    mdelay(10);
-    }
-
-    kfree(patch_chunk);
-
-    if (i != patch_len) {
-	    IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n",
-		       __FUNCTION__, i, patch_len);
-	    retval = -EIO;
-    }
-
-    if (retval < 0)
-	    /* todo - mark device as not ready */
-	    IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n",
-			__FUNCTION__, retval);
-
-    return retval;
-}
-
-
+/*
+ * Function stir421x_patch_device(struct irda_usb_cb *self)
+ *
+ * Get a firmware code from userspase using hotplug request_firmware() call
+  */
 static int stir421x_patch_device(struct irda_usb_cb *self)
 {
-	unsigned int i, patch_found = 0, data_found = 0, data_offset;
-	int patch_version, ret = 0;
-	const struct firmware *fw_entry;
+        unsigned int i;
+        int ret;
+        char stir421x_fw_name[11];
+        const struct firmware *fw;
+        unsigned char *fw_version_ptr; /* pointer to version string */
+	unsigned long fw_version = 0;
 
-	for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) {
-		if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) {
-			IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]);
-			continue;
-		}
+        /*
+         * Known firmware patch file names for STIR421x dongles
+         * are "42101001.sb" or "42101002.sb"
+         */
+        sprintf(stir421x_fw_name, "4210%4X.sb",
+                self->usbdev->descriptor.bcdDevice);
+        ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev);
+        if (ret < 0)
+                return ret;
 
-                /* We found a patch from userspace */
-		patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size);
+        /* We get a patch from userspace */
+        IRDA_MESSAGE("%s(): Received firmware %s (%zu bytes)\n",
+                     __FUNCTION__, stir421x_fw_name, fw->size);
 
-		if (patch_version < 0) {
-			/* Couldn't fetch a version, let's move on to the next file */
-			IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__);
-			ret = patch_version;
-			release_firmware(fw_entry);
-			continue;
-		}
+        ret = -EINVAL;
 
-		if (patch_version != self->usbdev->descriptor.bcdDevice) {
-			/* Patch version and device don't match */
-			IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n",
-				    __FUNCTION__,
-				    patch_version, self->usbdev->descriptor.bcdDevice);
-			ret = -EINVAL;
-			release_firmware(fw_entry);
-			continue;
-		}
+	/* Get the bcd product version */
+        if (!memcmp(fw->data, STIR421X_PATCH_PRODUCT_VER,
+                    sizeof(STIR421X_PATCH_PRODUCT_VER) - 1)) {
+                fw_version_ptr = fw->data +
+			sizeof(STIR421X_PATCH_PRODUCT_VER) - 1;
 
-		/* If we're here, we've found a correct patch */
-		patch_found = 1;
-		break;
+                /* Let's check if the product version is dotted */
+                if (fw_version_ptr[3] == '.' &&
+		    fw_version_ptr[7] == '.') {
+			unsigned long major, minor, build;
+			major = simple_strtoul(fw_version_ptr, NULL, 10);
+			minor = simple_strtoul(fw_version_ptr + 4, NULL, 10);
+			build = simple_strtoul(fw_version_ptr + 8, NULL, 10);
 
-	}
+			fw_version = (major << 12)
+				+ (minor << 8)
+				+ ((build / 10) << 4)
+				+ (build % 10);
 
-	/* We couldn't find a valid firmware, let's leave */
-	if (!patch_found)
-		return ret;
+			IRDA_DEBUG(3, "%s(): Firmware Product version %ld\n",
+                                   __FUNCTION__, fw_version);
+                }
+        }
 
-	/* The actual image starts after the "STMP" keyword */
-	for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) {
-		if (!memcmp(fw_entry->data + data_offset,
-			    STIR421X_PATCH_DATA_TAG_STR,
-			    sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) {
-			IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n",
-				   __FUNCTION__, data_offset);
-			data_found = 1;
-			break;
-		}
-	}
+        if (self->usbdev->descriptor.bcdDevice == fw_version) {
+                /*
+		 * If we're here, we've found a correct patch
+                 * The actual image starts after the "STMP" keyword
+                 * so forward to the firmware header tag
+                 */
+                for (i = 0; (fw->data[i] != STIR421X_PATCH_END_OF_HDR_TAG)
+			     && (i < fw->size); i++) ;
+                /* here we check for the out of buffer case */
+                if ((STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i])
+                    && (i < STIR421X_PATCH_CODE_OFFSET)) {
+                        if (!memcmp(fw->data + i + 1, STIR421X_PATCH_STMP_TAG,
+                                    sizeof(STIR421X_PATCH_STMP_TAG) - 1)) {
 
-	/* We couldn't find "STMP" from the header */
-	if (!data_found)
-		return -EINVAL;
+				/* We can upload the patch to the target */
+				i += sizeof(STIR421X_PATCH_STMP_TAG);
+                                ret = stir421x_fw_upload(self, &fw->data[i],
+							 fw->size - i);
+                        }
+                }
+        }
 
-	/* Let's upload the patch to the target */
-	ret = stir421x_upload_patch(self,
-				    &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)],
-				    fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)));
+        release_firmware(fw);
 
-	release_firmware(fw_entry);
-
-	return ret;
-
+        return ret;
 }
 
 
@@ -1702,12 +1657,12 @@
 	init_timer(&self->rx_defer_timer);
 
 	self->capability = id->driver_info;
-	self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ;
+	self->needspatch = ((self->capability & IUC_STIR421X) != 0);
 
 	/* Create all of the needed urbs */
-	if (self->capability & IUC_STIR_4210) {
+	if (self->capability & IUC_STIR421X) {
 		self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS;
-		self->header_length = USB_IRDA_SIGMATEL_HEADER;
+		self->header_length = USB_IRDA_STIR421X_HEADER;
 	} else {
 		self->max_rx_urb = IU_MAX_RX_URBS;
 		self->header_length = USB_IRDA_HEADER;
@@ -1813,8 +1768,8 @@
 		/* Now we fetch and upload the firmware patch */
 		ret = stir421x_patch_device(self);
 		self->needspatch = (ret < 0);
-		if (ret < 0) {
-			printk("patch_device failed\n");
+		if (self->needspatch) {
+			IRDA_ERROR("STIR421X: Couldn't upload patch\n");
 			goto err_out_5;
 		}
 
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h
index d833db5..6b2271f 100644
--- a/drivers/net/irda/irda-usb.h
+++ b/drivers/net/irda/irda-usb.h
@@ -34,9 +34,6 @@
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>      /* struct irlap_cb */
 
-#define PATCH_FILE_SIZE_MAX     65536
-#define PATCH_FILE_SIZE_MIN     80
-
 #define RX_COPY_THRESHOLD 200
 #define IRDA_USB_MAX_MTU 2051
 #define IRDA_USB_SPEED_MTU 64		/* Weird, but work like this */
@@ -107,14 +104,15 @@
 #define IUC_SMALL_PKT	0x10	/* Device doesn't behave with big Rx packets */
 #define IUC_MAX_WINDOW	0x20	/* Device underestimate the Rx window */
 #define IUC_MAX_XBOFS	0x40	/* Device need more xbofs than advertised */
-#define IUC_STIR_4210	0x80	/* SigmaTel 4210/4220/4116 VFIR */
+#define IUC_STIR421X	0x80	/* SigmaTel 4210/4220/4116 VFIR */
 
 /* USB class definitions */
 #define USB_IRDA_HEADER            0x01
 #define USB_CLASS_IRDA             0x02 /* USB_CLASS_APP_SPEC subclass */
 #define USB_DT_IRDA                0x21
-#define USB_IRDA_SIGMATEL_HEADER   0x03
-#define IU_SIGMATEL_MAX_RX_URBS    (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER)
+#define USB_IRDA_STIR421X_HEADER   0x03
+#define IU_SIGMATEL_MAX_RX_URBS    (IU_MAX_ACTIVE_RX_URBS + \
+                                    USB_IRDA_STIR421X_HEADER)
 
 struct irda_class_desc {
 	__u8  bLength;
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 98fa531..44efd49 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -386,7 +386,7 @@
 	/* Locking notes : this function may be called from irq context with
 	 * spinlock, via irport_write_wakeup(), or from non-interrupt without
 	 * spinlock (from the task timer). Yuck !
-	 * This is ugly, and unsafe is the spinlock is not already aquired.
+	 * This is ugly, and unsafe is the spinlock is not already acquired.
 	 * This will be fixed when irda-task get rewritten.
 	 * Jean II */
 	if (!spin_is_locked(&self->lock)) {
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
new file mode 100644
index 0000000..754297f
--- /dev/null
+++ b/drivers/net/irda/mcs7780.c
@@ -0,0 +1,1009 @@
+/*****************************************************************************
+*
+* Filename:      mcs7780.c
+* Version:       0.4-alpha
+* Description:   Irda MosChip USB Dongle Driver
+* Authors:       Lukasz Stelmach <stlman@poczta.fm>
+* 		 Brian Pugh <bpugh@cs.pdx.edu>
+*		 Judy Fischbach <jfisch@cs.pdx.edu>
+*
+*       Based on stir4200 driver, but some things done differently.
+*       Based on earlier driver by Paul Stewart <stewart@parc.com>
+*
+*       Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at>
+*       Copyright (C) 2001, Dag Brattli <dag@brattli.net>
+*       Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
+*       Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+*       Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+*       Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+*       Copyright (C) 2005, Judy Fischbach <jfisch@cs.pdx.edu>
+*
+*       This program is free software; you can redistribute it and/or modify
+*       it under the terms of the GNU General Public License as published by
+*       the Free Software Foundation; either version 2 of the License, or
+*       (at your option) any later version.
+*
+*       This program is distributed in the hope that it will be useful,
+*       but WITHOUT ANY WARRANTY; without even the implied warranty of
+*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*       GNU General Public License for more details.
+*
+*       You should have received a copy of the GNU General Public License
+*       along with this program; if not, write to the Free Software
+*       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+/*
+ * MCS7780 is a simple USB to IrDA bridge by MosChip. It is neither
+ * compatibile with irda-usb nor with stir4200. Although it is quite
+ * similar to the later as far as general idea of operation is concerned.
+ * That is it requires the software to do all the framing job at SIR speeds.
+ * The hardware does take care of the framing at MIR and FIR speeds.
+ * It supports all speeds from 2400 through 4Mbps
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+#include "mcs7780.h"
+
+#define MCS_VENDOR_ID 0x9710
+#define MCS_PRODUCT_ID 0x7780
+
+static struct usb_device_id mcs_table[] = {
+	/* MosChip Corp.,  MCS7780 FIR-USB Adapter */
+	{USB_DEVICE(MCS_VENDOR_ID, MCS_PRODUCT_ID)},
+	{},
+};
+
+MODULE_AUTHOR("Brian Pugh <bpugh@cs.pdx.edu>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for MosChip MCS7780");
+MODULE_VERSION("0.3alpha");
+MODULE_LICENSE("GPL");
+
+MODULE_DEVICE_TABLE(usb, mcs_table);
+
+static int qos_mtt_bits = 0x07 /* > 1ms */ ;
+module_param(qos_mtt_bits, int, 0);
+MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
+
+static int receive_mode = 0x1;
+module_param(receive_mode, int, 0);
+MODULE_PARM_DESC(receive_mode,
+		 "Receive mode of the device (1:fast, 0:slow, default:1)");
+
+static int sir_tweak = 1;
+module_param(sir_tweak, int, 0444);
+MODULE_PARM_DESC(sir_tweak,
+		 "Default pulse width (1:1.6us, 0:3/16 bit, default:1).");
+
+static int transceiver_type = MCS_TSC_VISHAY;
+module_param(transceiver_type, int, 0444);
+MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h.");
+
+struct usb_driver mcs_driver = {
+	.name = "mcs7780",
+	.probe = mcs_probe,
+	.disconnect = mcs_disconnect,
+	.id_table = mcs_table,
+};
+
+/* speed flag selection by direct addressing.
+addr = (speed >> 8) & 0x0f
+
+0x1   57600	 0x2  115200	 0x4 1152000	 0x5    9600
+0x6   38400	 0x9    2400	 0xa  576000	 0xb   19200
+
+4Mbps (or 2400) must be checked separately. Since it also has
+to be programmed in a different manner that is not a big problem.
+*/
+static __u16 mcs_speed_set[16] = { 0,
+	MCS_SPEED_57600,
+	MCS_SPEED_115200,
+	0,
+	MCS_SPEED_1152000,
+	MCS_SPEED_9600,
+	MCS_SPEED_38400,
+	0, 0,
+	MCS_SPEED_2400,
+	MCS_SPEED_576000,
+	MCS_SPEED_19200,
+	0, 0, 0,
+};
+
+/* Set given 16 bit register with a 16 bit value. Send control message
+ * to set dongle register. */
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val)
+{
+	struct usb_device *dev = mcs->usbdev;
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+			       MCS_WR_RTYPE, val, reg, NULL, 0,
+			       msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+}
+
+/* Get 16 bit register value. Send contol message to read dongle register. */
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val)
+{
+	struct usb_device *dev = mcs->usbdev;
+	int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+				  MCS_RD_RTYPE, 0, reg, val, 2,
+				  msecs_to_jiffies(MCS_CTRL_TIMEOUT));
+
+	return ret;
+}
+
+/* Setup a communication between mcs7780 and TFDU chips.  It is described
+ * in more detail in the data sheet.  The setup sequence puts the the
+ * vishay tranceiver into high speed mode.  It will also receive SIR speed
+ * packets but at reduced sensitivity.
+ */
+
+/* 0: OK 1:ERROR */
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs)
+{
+	int ret = 0;
+	__u16 rval;
+
+	/* mcs_get_reg should read exactly two bytes from the dongle */
+	ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+	if (unlikely(ret != 2)) {
+		ret = -EIO;
+		goto error;
+	}
+
+	/* The MCS_XCVR_CONF bit puts the transceiver into configuration
+	 * mode.  The MCS_MODE0 bit must start out high (1) and then
+	 * transition to low and the MCS_STFIR and MCS_MODE1 bits must
+	 * be low.
+	 */
+	rval |= (MCS_MODE0 | MCS_XCVR_CONF);
+	rval &= ~MCS_STFIR;
+	rval &= ~MCS_MODE1;
+	ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+	if (unlikely(ret))
+		goto error;
+
+	rval &= ~MCS_MODE0;
+	ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+	if (unlikely(ret))
+		goto error;
+
+	rval &= ~MCS_XCVR_CONF;
+	ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+	if (unlikely(ret))
+		goto error;
+
+	ret = 0;
+	error:
+		return ret;
+}
+
+/* Setup a communication between mcs7780 and agilent chip. */
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs)
+{
+	IRDA_WARNING("This transceiver type is not supported yet.");
+	return 1;
+}
+
+/* Setup a communication between mcs7780 and sharp chip. */
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs)
+{
+	IRDA_WARNING("This transceiver type is not supported yet.");
+	return 1;
+}
+
+/* Common setup for all transceivers */
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs)
+{
+	int ret = 0;
+	__u16 rval;
+	char *msg;
+
+	msg = "Basic transceiver setup error.";
+
+	/* read value of MODE Register, set the DRIVER and RESET bits
+	* and write value back out to MODE Register
+	*/
+	ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+	if(unlikely(ret != 2))
+		goto error;
+	rval |= MCS_DRIVER;	/* put the mcs7780 into configuration mode. */
+	ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+	if(unlikely(ret))
+		goto error;
+
+	rval = 0;		/* set min pulse width to 0 initially. */
+	ret = mcs_set_reg(mcs, MCS_MINRXPW_REG, rval);
+	if(unlikely(ret))
+		goto error;
+
+	ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+	if(unlikely(ret != 2))
+		goto error;
+
+	rval &= ~MCS_FIR;	/* turn off fir mode. */
+	if(mcs->sir_tweak)
+		rval |= MCS_SIR16US;	/* 1.6us pulse width */
+	else
+		rval &= ~MCS_SIR16US;	/* 3/16 bit time pulse width */
+
+	/* make sure ask mode and back to back packets are off. */
+	rval &= ~(MCS_BBTG | MCS_ASK);
+
+	rval &= ~MCS_SPEED_MASK;
+	rval |= MCS_SPEED_9600;		/* make sure initial speed is 9600. */
+	mcs->speed = 9600;
+	mcs->new_speed = 0;		/* new_speed is set to 0 */
+	rval &= ~MCS_PLLPWDN;		/* disable power down. */
+
+	/* make sure device determines direction and that the auto send sip
+	 * pulse are on.
+	 */
+	rval |= MCS_DTD | MCS_SIPEN;
+
+	ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+	if(unlikely(ret))
+		goto error;
+
+	msg = "transceiver model specific setup error.";
+	switch (mcs->transceiver_type) {
+	case MCS_TSC_VISHAY:
+		ret = mcs_setup_transceiver_vishay(mcs);
+		break;
+
+	case MCS_TSC_SHARP:
+		ret = mcs_setup_transceiver_sharp(mcs);
+		break;
+
+	case MCS_TSC_AGILENT:
+		ret = mcs_setup_transceiver_agilent(mcs);
+		break;
+
+	default:
+		IRDA_WARNING("Unknown transceiver type: %d",
+			     mcs->transceiver_type);
+		ret = 1;
+	}
+	if (unlikely(ret))
+		goto error;
+
+	/* If transceiver is not SHARP, then if receive mode set
+	* on the RXFAST bit in the XCVR Register otherwise unset it
+	*/
+	if (mcs->transceiver_type != MCS_TSC_SHARP) {
+
+		ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval);
+		if (unlikely(ret != 2))
+			goto error;
+		if (mcs->receive_mode)
+			rval |= MCS_RXFAST;
+		else
+			rval &= ~MCS_RXFAST;
+		ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval);
+		if (unlikely(ret))
+			goto error;
+	}
+
+	msg = "transceiver reset.";
+
+	ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+	if (unlikely(ret != 2))
+		goto error;
+
+	/* reset the mcs7780 so all changes take effect. */
+	rval &= ~MCS_RESET;
+	ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+	if (unlikely(ret))
+		goto error;
+	else
+		return ret;
+
+error:
+	IRDA_ERROR("%s", msg);
+	return ret;
+}
+
+/* Wraps the data in format for SIR */
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf)
+{
+	int wraplen;
+
+	/* 2: full frame length, including "the length" */
+	wraplen = async_wrap_skb(skb, buf + 2, 4094);
+
+	wraplen += 2;
+	buf[0] = wraplen & 0xff;
+	buf[1] = (wraplen >> 8) & 0xff;
+
+	return wraplen;
+}
+
+/* Wraps the data in format for FIR */
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+	unsigned int len = 0;
+	__u32 fcs = ~(crc32_le(~0, skb->data, skb->len));
+
+	/* add 2 bytes for length value and 4 bytes for fcs. */
+	len = skb->len + 6;
+
+	/* The mcs7780 requires that the first two bytes are the packet
+	 * length in little endian order.  Note: the length value includes
+	 * the two bytes for the length value itself.
+	 */
+	buf[0] = len & 0xff;
+	buf[1] = (len >> 8) & 0xff;
+	/* copy the data into the tx buffer. */
+	memcpy(buf+2, skb->data, skb->len);
+	/* put the fcs in the last four bytes in little endian order. */
+	buf[len - 4] = fcs & 0xff;
+	buf[len - 3] = (fcs >> 8) & 0xff;
+	buf[len - 2] = (fcs >> 16) & 0xff;
+	buf[len - 1] = (fcs >> 24) & 0xff;
+
+	return len;
+}
+
+/* Wraps the data in format for MIR */
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf)
+{
+	__u16 fcs = 0;
+	int len = skb->len + 4;
+
+	fcs = ~(irda_calc_crc16(~fcs, skb->data, skb->len));
+	/* put the total packet length in first.  Note: packet length
+	 * value includes the two bytes that hold the packet length
+	 * itself.
+	 */
+	buf[0] = len & 0xff;
+	buf[1] = (len >> 8) & 0xff;
+	/* copy the data */
+	memcpy(buf+2, skb->data, skb->len);
+	/* put the fcs in last two bytes in little endian order. */
+	buf[len - 2] = fcs & 0xff;
+	buf[len - 1] = (fcs >> 8) & 0xff;
+
+	return len;
+}
+
+/* Unwrap received packets at MIR speed.  A 16 bit crc_ccitt checksum is
+ * used for the fcs.  When performed over the entire packet the result
+ * should be GOOD_FCS = 0xf0b8.  Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+	__u16 fcs;
+	int new_len;
+	struct sk_buff *skb;
+
+	/* Assume that the frames are going to fill a single packet
+	 * rather than span multiple packets.
+	 */
+
+	new_len = len - 2;
+	if(unlikely(new_len <= 0)) {
+		IRDA_ERROR("%s short frame length %d\n",
+			     mcs->netdev->name, new_len);
+		++mcs->stats.rx_errors;
+		++mcs->stats.rx_length_errors;
+		return;
+	}
+	fcs = 0;
+	fcs = irda_calc_crc16(~fcs, buf, len);
+
+	if(fcs != GOOD_FCS) {
+		IRDA_ERROR("crc error calc 0x%x len %d\n",
+			   fcs, new_len);
+		mcs->stats.rx_errors++;
+		mcs->stats.rx_crc_errors++;
+		return;
+	}
+
+	skb = dev_alloc_skb(new_len + 1);
+	if(unlikely(!skb)) {
+		++mcs->stats.rx_dropped;
+		return;
+	}
+
+	skb_reserve(skb, 1);
+	memcpy(skb->data, buf, new_len);
+	skb_put(skb, new_len);
+	skb->mac.raw = skb->data;
+	skb->protocol = htons(ETH_P_IRDA);
+	skb->dev = mcs->netdev;
+
+	netif_rx(skb);
+
+	mcs->stats.rx_packets++;
+	mcs->stats.rx_bytes += new_len;
+
+	return;
+}
+
+/* Unwrap received packets at FIR speed.  A 32 bit crc_ccitt checksum is
+ * used for the fcs.  Hands the unwrapped data off to the IrDA
+ * layer via a sk_buff.
+ */
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len)
+{
+	__u32 fcs;
+	int new_len;
+	struct sk_buff *skb;
+
+	/* Assume that the frames are going to fill a single packet
+	 * rather than span multiple packets.  This is most likely a false
+	 * assumption.
+	 */
+
+	new_len = len - 4;
+	if(unlikely(new_len <= 0)) {
+		IRDA_ERROR("%s short frame length %d\n",
+			   mcs->netdev->name, new_len);
+		++mcs->stats.rx_errors;
+		++mcs->stats.rx_length_errors;
+		return;
+	}
+
+	fcs = ~(crc32_le(~0, buf, new_len));
+	if(fcs != le32_to_cpu(get_unaligned((u32 *)(buf+new_len)))) {
+		IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len);
+		mcs->stats.rx_errors++;
+		mcs->stats.rx_crc_errors++;
+		return;
+	}
+
+	skb = dev_alloc_skb(new_len + 1);
+	if(unlikely(!skb)) {
+		++mcs->stats.rx_dropped;
+		return;
+	}
+
+	skb_reserve(skb, 1);
+	memcpy(skb->data, buf, new_len);
+	skb_put(skb, new_len);
+	skb->mac.raw = skb->data;
+	skb->protocol = htons(ETH_P_IRDA);
+	skb->dev = mcs->netdev;
+
+	netif_rx(skb);
+
+	mcs->stats.rx_packets++;
+	mcs->stats.rx_bytes += new_len;
+
+	return;
+}
+
+
+/* Allocates urbs for both receive and transmit.
+ * If alloc fails return error code 0 (fail) otherwise
+ * return error code 1 (success).
+ */
+static inline int mcs_setup_urbs(struct mcs_cb *mcs)
+{
+	mcs->rx_urb = NULL;
+
+	mcs->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!mcs->tx_urb)
+		return 0;
+
+	mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!mcs->rx_urb)
+		return 0;
+
+	return 1;
+}
+
+/* Sets up state to be initially outside frame, gets receive urb,
+ * sets status to successful and then submits the urb to start
+ * receiving the data.
+ */
+static inline int mcs_receive_start(struct mcs_cb *mcs)
+{
+	mcs->rx_buff.in_frame = FALSE;
+	mcs->rx_buff.state = OUTSIDE_FRAME;
+
+	usb_fill_bulk_urb(mcs->rx_urb, mcs->usbdev,
+			  usb_rcvbulkpipe(mcs->usbdev, mcs->ep_in),
+			  mcs->in_buf, 4096, mcs_receive_irq, mcs);
+
+	mcs->rx_urb->status = 0;
+	return usb_submit_urb(mcs->rx_urb, GFP_KERNEL);
+}
+
+/* Finds the in and out endpoints for the mcs control block */
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+				     struct usb_host_endpoint *ep, int epnum)
+{
+	int i;
+	int ret = 0;
+
+	/* If no place to store the endpoints just return */
+	if (!ep)
+		return ret;
+
+	/* cycle through all endpoints, find the first two that are DIR_IN */
+	for (i = 0; i < epnum; i++) {
+		if (ep[i].desc.bEndpointAddress & USB_DIR_IN)
+			mcs->ep_in = ep[i].desc.bEndpointAddress;
+		else
+			mcs->ep_out = ep[i].desc.bEndpointAddress;
+
+		/* MosChip says that the chip has only two bulk
+		 * endpoints. Find one for each direction and move on.
+		 */
+		if ((mcs->ep_in != 0) && (mcs->ep_out != 0)) {
+			ret = 1;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+static void mcs_speed_work(void *arg)
+{
+	struct mcs_cb *mcs = arg;
+	struct net_device *netdev = mcs->netdev;
+
+	mcs_speed_change(mcs);
+	netif_wake_queue(netdev);
+}
+
+/* Function to change the speed of the mcs7780.  Fully supports SIR,
+ * MIR, and FIR speeds.
+ */
+static int mcs_speed_change(struct mcs_cb *mcs)
+{
+	int ret = 0;
+	int rst = 0;
+	int cnt = 0;
+	__u16 nspeed;
+	__u16 rval;
+
+	nspeed = mcs_speed_set[(mcs->new_speed >> 8) & 0x0f];
+
+	do {
+		mcs_get_reg(mcs, MCS_RESV_REG, &rval);
+	} while(cnt++ < 100 && (rval & MCS_IRINTX));
+
+	if(cnt >= 100) {
+		IRDA_ERROR("unable to change speed");
+		ret = -EIO;
+		goto error;
+	}
+
+	mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+
+	/* MINRXPW values recomended by MosChip */
+	if (mcs->new_speed <= 115200) {
+		rval &= ~MCS_FIR;
+
+		if ((rst = (mcs->speed > 115200)))
+			mcs_set_reg(mcs, MCS_MINRXPW_REG, 0);
+
+	} else if (mcs->new_speed <= 1152000) {
+		rval &= ~MCS_FIR;
+
+		if ((rst = !(mcs->speed == 576000 || mcs->speed == 1152000)))
+			mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+	} else {
+		rval |= MCS_FIR;
+
+		if ((rst = (mcs->speed != 4000000)))
+			mcs_set_reg(mcs, MCS_MINRXPW_REG, 5);
+
+	}
+
+	rval &= ~MCS_SPEED_MASK;
+	rval |= nspeed;
+
+	ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+	if (unlikely(ret))
+		goto error;
+
+	if (rst)
+		switch (mcs->transceiver_type) {
+		case MCS_TSC_VISHAY:
+			ret = mcs_setup_transceiver_vishay(mcs);
+			break;
+
+		case MCS_TSC_SHARP:
+			ret = mcs_setup_transceiver_sharp(mcs);
+			break;
+
+		case MCS_TSC_AGILENT:
+			ret = mcs_setup_transceiver_agilent(mcs);
+			break;
+
+		default:
+			ret = 1;
+			IRDA_WARNING("Unknown transceiver type: %d",
+				     mcs->transceiver_type);
+		}
+	if (unlikely(ret))
+		goto error;
+
+	mcs_get_reg(mcs, MCS_MODE_REG, &rval);
+	rval &= ~MCS_RESET;
+	ret = mcs_set_reg(mcs, MCS_MODE_REG, rval);
+
+	mcs->speed = mcs->new_speed;
+	error:
+		mcs->new_speed = 0;
+		return ret;
+}
+
+/* Ioctl calls not supported at this time.  Can be an area of future work. */
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+	/* struct if_irda_req *irq = (struct if_irda_req *)rq; */
+	/* struct mcs_cb *mcs = netdev_priv(netdev); */
+	int ret = 0;
+
+	switch (cmd) {
+	default:
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+/* Network device is taken down, done by "ifconfig irda0 down" */
+static int mcs_net_close(struct net_device *netdev)
+{
+	int ret = 0;
+	struct mcs_cb *mcs = netdev_priv(netdev);
+
+	/* Stop transmit processing */
+	netif_stop_queue(netdev);
+
+	/* kill and free the receive and transmit URBs */
+	usb_kill_urb(mcs->rx_urb);
+	usb_free_urb(mcs->rx_urb);
+	usb_kill_urb(mcs->tx_urb);
+	usb_free_urb(mcs->tx_urb);
+
+	/* Stop and remove instance of IrLAP */
+	if (mcs->irlap)
+		irlap_close(mcs->irlap);
+
+	mcs->irlap = NULL;
+	return ret;
+}
+
+/* Network device is taken up, done by "ifconfig irda0 up" */
+static int mcs_net_open(struct net_device *netdev)
+{
+	struct mcs_cb *mcs = netdev_priv(netdev);
+	char hwname[16];
+	int ret = 0;
+
+	ret = usb_clear_halt(mcs->usbdev,
+			     usb_sndbulkpipe(mcs->usbdev, mcs->ep_in));
+	if (ret)
+		goto error1;
+	ret = usb_clear_halt(mcs->usbdev,
+			     usb_rcvbulkpipe(mcs->usbdev, mcs->ep_out));
+	if (ret)
+		goto error1;
+
+	ret = mcs_setup_transceiver(mcs);
+	if (ret)
+		goto error1;
+
+	ret = -ENOMEM;
+
+	/* Initialize for SIR/FIR to copy data directly into skb.  */
+	mcs->receiving = 0;
+	mcs->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+	mcs->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+	if (!mcs->rx_buff.skb)
+		goto error1;
+
+	skb_reserve(mcs->rx_buff.skb, 1);
+	mcs->rx_buff.head = mcs->rx_buff.skb->data;
+	do_gettimeofday(&mcs->rx_time);
+
+	/*
+	 * Now that everything should be initialized properly,
+	 * Open new IrLAP layer instance to take care of us...
+	 * Note : will send immediately a speed change...
+	 */
+	sprintf(hwname, "usb#%d", mcs->usbdev->devnum);
+	mcs->irlap = irlap_open(netdev, &mcs->qos, hwname);
+	if (!mcs->irlap) {
+		IRDA_ERROR("mcs7780: irlap_open failed");
+		goto error2;
+	}
+
+	if (!mcs_setup_urbs(mcs))
+	goto error3;
+
+	ret = mcs_receive_start(mcs);
+	if (ret)
+		goto error3;
+
+	netif_start_queue(netdev);
+	return 0;
+
+	error3:
+		irlap_close(mcs->irlap);
+	error2:
+		kfree_skb(mcs->rx_buff.skb);
+	error1:
+		return ret;
+}
+
+
+/* Get device stats for /proc/net/dev and ifconfig */
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev)
+{
+	struct mcs_cb *mcs = netdev_priv(netdev);
+	return &mcs->stats;
+}
+
+/* Receive callback function.  */
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs)
+{
+	__u8 *bytes;
+	struct mcs_cb *mcs = urb->context;
+	int i;
+	int ret;
+
+	if (!netif_running(mcs->netdev))
+		return;
+
+	if (urb->status)
+		return;
+
+	if (urb->actual_length > 0) {
+		bytes = urb->transfer_buffer;
+
+		/* MCS returns frames without BOF and EOF
+		 * I assume it returns whole frames.
+		 */
+		/* SIR speed */
+		if(mcs->speed < 576000) {
+			async_unwrap_char(mcs->netdev, &mcs->stats,
+				  &mcs->rx_buff, 0xc0);
+
+			for (i = 0; i < urb->actual_length; i++)
+				async_unwrap_char(mcs->netdev, &mcs->stats,
+					  &mcs->rx_buff, bytes[i]);
+
+			async_unwrap_char(mcs->netdev, &mcs->stats,
+				  &mcs->rx_buff, 0xc1);
+		}
+		/* MIR speed */
+		else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+			mcs_unwrap_mir(mcs, urb->transfer_buffer,
+				urb->actual_length);
+		}
+		/* FIR speed */
+		else {
+			mcs_unwrap_fir(mcs, urb->transfer_buffer,
+				urb->actual_length);
+		}
+		mcs->netdev->last_rx = jiffies;
+		do_gettimeofday(&mcs->rx_time);
+	}
+
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/* Transmit callback funtion.  */
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct mcs_cb *mcs = urb->context;
+	struct net_device *ndev = mcs->netdev;
+
+	if (unlikely(mcs->new_speed))
+		schedule_work(&mcs->work);
+	else
+		netif_wake_queue(ndev);
+}
+
+/* Transmit callback funtion.  */
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	unsigned long flags;
+	struct mcs_cb *mcs;
+	int wraplen;
+	int ret = 0;
+
+
+	if (skb == NULL || ndev == NULL)
+		return -EINVAL;
+
+	netif_stop_queue(ndev);
+	mcs = netdev_priv(ndev);
+
+	spin_lock_irqsave(&mcs->lock, flags);
+
+	mcs->new_speed = irda_get_next_speed(skb);
+	if (likely(mcs->new_speed == mcs->speed))
+		mcs->new_speed = 0;
+
+	/* SIR speed */
+	if(mcs->speed < 576000) {
+		wraplen = mcs_wrap_sir_skb(skb, mcs->out_buf);
+	}
+	/* MIR speed */
+	else if(mcs->speed == 576000 || mcs->speed == 1152000) {
+		wraplen = mcs_wrap_mir_skb(skb, mcs->out_buf);
+	}
+	/* FIR speed */
+	else {
+		wraplen = mcs_wrap_fir_skb(skb, mcs->out_buf);
+	}
+	usb_fill_bulk_urb(mcs->tx_urb, mcs->usbdev,
+			  usb_sndbulkpipe(mcs->usbdev, mcs->ep_out),
+			  mcs->out_buf, wraplen, mcs_send_irq, mcs);
+
+	if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) {
+		IRDA_ERROR("failed tx_urb: %d", ret);
+		switch (ret) {
+		case -ENODEV:
+		case -EPIPE:
+			break;
+		default:
+			mcs->stats.tx_errors++;
+			netif_start_queue(ndev);
+		}
+	} else {
+		mcs->stats.tx_packets++;
+		mcs->stats.tx_bytes += skb->len;
+	}
+
+	dev_kfree_skb(skb);
+	spin_unlock_irqrestore(&mcs->lock, flags);
+	return ret;
+}
+
+/*
+ * This function is called by the USB subsystem for each new device in the
+ * system.  Need to verify the device and if it is, then start handling it.
+ */
+static int mcs_probe(struct usb_interface *intf,
+		     const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct net_device *ndev = NULL;
+	struct mcs_cb *mcs;
+	int ret = -ENOMEM;
+
+	ndev = alloc_irdadev(sizeof(*mcs));
+	if (!ndev)
+		goto error1;
+
+	IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.", udev->devnum);
+
+	/* what is it realy for? */
+	SET_MODULE_OWNER(ndev);
+	SET_NETDEV_DEV(ndev, &intf->dev);
+
+	ret = usb_reset_configuration(udev);
+	if (ret != 0) {
+		IRDA_ERROR("mcs7780: usb reset configuration failed");
+		goto error2;
+	}
+
+	mcs = netdev_priv(ndev);
+	mcs->usbdev = udev;
+	mcs->netdev = ndev;
+	spin_lock_init(&mcs->lock);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&mcs->qos);
+
+	/* That's the Rx capability. */
+	mcs->qos.baud_rate.bits &=
+	    IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200
+		| IR_576000 | IR_1152000 | (IR_4000000 << 8);
+
+
+	mcs->qos.min_turn_time.bits &= qos_mtt_bits;
+	irda_qos_bits_to_value(&mcs->qos);
+
+	/* Speed change work initialisation*/
+	INIT_WORK(&mcs->work, mcs_speed_work, mcs);
+
+	/* Override the network functions we need to use */
+	ndev->hard_start_xmit = mcs_hard_xmit;
+	ndev->open = mcs_net_open;
+	ndev->stop = mcs_net_close;
+	ndev->get_stats = mcs_net_get_stats;
+	ndev->do_ioctl = mcs_net_ioctl;
+
+	if (!intf->cur_altsetting)
+		goto error2;
+
+	ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint,
+				 intf->cur_altsetting->desc.bNumEndpoints);
+	if (!ret) {
+		ret = -ENODEV;
+		goto error2;
+	}
+
+	ret = register_netdev(ndev);
+	if (ret != 0)
+		goto error2;
+
+	IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s",
+		   ndev->name);
+
+	mcs->transceiver_type = transceiver_type;
+	mcs->sir_tweak = sir_tweak;
+	mcs->receive_mode = receive_mode;
+
+	usb_set_intfdata(intf, mcs);
+	return 0;
+
+	error2:
+		free_netdev(ndev);
+
+	error1:
+		return ret;
+}
+
+/* The current device is removed, the USB layer tells us to shut down. */
+static void mcs_disconnect(struct usb_interface *intf)
+{
+	struct mcs_cb *mcs = usb_get_intfdata(intf);
+
+	if (!mcs)
+		return;
+
+	flush_scheduled_work();
+
+	unregister_netdev(mcs->netdev);
+	free_netdev(mcs->netdev);
+
+	usb_set_intfdata(intf, NULL);
+	IRDA_DEBUG(0, "MCS7780 now disconnected.");
+}
+
+/* Module insertion */
+static int __init mcs_init(void)
+{
+	int result;
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&mcs_driver);
+	if (result)
+		IRDA_ERROR("usb_register failed. Error number %d", result);
+
+	return result;
+}
+module_init(mcs_init);
+
+/* Module removal */
+static void __exit mcs_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&mcs_driver);
+}
+module_exit(mcs_exit);
+
diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h
new file mode 100644
index 0000000..1a723d7
--- /dev/null
+++ b/drivers/net/irda/mcs7780.h
@@ -0,0 +1,167 @@
+/*****************************************************************************
+*
+* Filename:      mcs7780.h
+* Version:       0.2-alpha
+* Description:   Irda MosChip USB Dongle
+* Status:        Experimental
+* Authors:       Lukasz Stelmach <stlman@poczta.fm>
+*		 Brian Pugh <bpugh@cs.pdx.edu>
+*
+*       Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm>
+*       Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu>
+*
+*       This program is free software; you can redistribute it and/or modify
+*       it under the terms of the GNU General Public License as published by
+*       the Free Software Foundation; either version 2 of the License, or
+*       (at your option) any later version.
+*
+*       This program is distributed in the hope that it will be useful,
+*       but WITHOUT ANY WARRANTY; without even the implied warranty of
+*       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*       GNU General Public License for more details.
+*
+*       You should have received a copy of the GNU General Public License
+*       along with this program; if not, write to the Free Software
+*       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+#ifndef _MCS7780_H
+#define _MCS7780_H
+
+#define MCS_MODE_SIR		0
+#define MCS_MODE_MIR		1
+#define MCS_MODE_FIR		2
+
+#define MCS_CTRL_TIMEOUT	500
+#define MCS_XMIT_TIMEOUT	500
+/* Possible transceiver types */
+#define MCS_TSC_VISHAY		0	/* Vishay TFD, default choice */
+#define MCS_TSC_AGILENT		1	/* Agilent 3602/3600 */
+#define MCS_TSC_SHARP		2	/* Sharp GP2W1000YP */
+
+/* Requests */
+#define MCS_RD_RTYPE 0xC0
+#define MCS_WR_RTYPE 0x40
+#define MCS_RDREQ    0x0F
+#define MCS_WRREQ    0x0E
+
+/* Register 0x00 */
+#define MCS_MODE_REG	0
+#define MCS_FIR		((__u16)0x0001)
+#define MCS_SIR16US	((__u16)0x0002)
+#define MCS_BBTG	((__u16)0x0004)
+#define MCS_ASK		((__u16)0x0008)
+#define MCS_PARITY	((__u16)0x0010)
+
+/* SIR/MIR speed constants */
+#define MCS_SPEED_SHIFT	    5
+#define MCS_SPEED_MASK	    ((__u16)0x00E0)
+#define MCS_SPEED(x)	    ((x & MCS_SPEED_MASK) >> MCS_SPEED_SHIFT)
+#define MCS_SPEED_2400	    ((0 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_9600	    ((1 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_19200	    ((2 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_38400	    ((3 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_57600	    ((4 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_115200    ((5 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_576000    ((6 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+#define MCS_SPEED_1152000   ((7 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK)
+
+#define MCS_PLLPWDN	((__u16)0x0100)
+#define MCS_DRIVER	((__u16)0x0200)
+#define MCS_DTD		((__u16)0x0400)
+#define MCS_DIR		((__u16)0x0800)
+#define MCS_SIPEN	((__u16)0x1000)
+#define MCS_SENDSIP	((__u16)0x2000)
+#define MCS_CHGDIR	((__u16)0x4000)
+#define MCS_RESET	((__u16)0x8000)
+
+/* Register 0x02 */
+#define MCS_XCVR_REG	2
+#define MCS_MODE0	((__u16)0x0001)
+#define MCS_STFIR	((__u16)0x0002)
+#define MCS_XCVR_CONF	((__u16)0x0004)
+#define MCS_RXFAST	((__u16)0x0008)
+/* TXCUR [6:4] */
+#define MCS_TXCUR_SHIFT	4
+#define MCS_TXCUR_MASK	((__u16)0x0070)
+#define MCS_TXCUR(x)	((x & MCS_TXCUR_MASK) >> MCS_TXCUR_SHIFT)
+#define MCS_SETTXCUR(x,y) \
+	((x & ~MCS_TXCUR_MASK) | (y << MCS_TXCUR_SHIFT) & MCS_TXCUR_MASK)
+
+#define MCS_MODE1	((__u16)0x0080)
+#define MCS_SMODE0	((__u16)0x0100)
+#define MCS_SMODE1	((__u16)0x0200)
+#define MCS_INVTX	((__u16)0x0400)
+#define MCS_INVRX	((__u16)0x0800)
+
+#define MCS_MINRXPW_REG	4
+
+#define MCS_RESV_REG 7
+#define MCS_IRINTX	((__u16)0x0001)
+#define MCS_IRINRX	((__u16)0x0002)
+
+struct mcs_cb {
+	struct usb_device *usbdev;	/* init: probe_irda */
+	struct net_device *netdev;	/* network layer */
+	struct irlap_cb *irlap;	/* The link layer we are binded to */
+	struct net_device_stats stats;	/* network statistics */
+	struct qos_info qos;
+	unsigned int speed;	/* Current speed */
+	unsigned int new_speed;	/* new speed */
+
+	struct work_struct work; /* Change speed work */
+
+	struct sk_buff *tx_pending;
+	char in_buf[4096];	/* transmit/receive buffer */
+	char out_buf[4096];	/* transmit/receive buffer */
+	__u8 *fifo_status;
+
+	iobuff_t rx_buff;	/* receive unwrap state machine */
+	struct timeval rx_time;
+	spinlock_t lock;
+	int receiving;
+
+	__u8 ep_in;
+	__u8 ep_out;
+
+	struct urb *rx_urb;
+	struct urb *tx_urb;
+
+	int transceiver_type;
+	int sir_tweak;
+	int receive_mode;
+};
+
+static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val);
+static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val);
+
+static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs);
+static inline int mcs_setup_transceiver(struct mcs_cb *mcs);
+static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf);
+static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf);
+static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf);
+static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len);
+static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len);
+static inline int mcs_setup_urbs(struct mcs_cb *mcs);
+static inline int mcs_receive_start(struct mcs_cb *mcs);
+static inline int mcs_find_endpoints(struct mcs_cb *mcs,
+				     struct usb_host_endpoint *ep, int epnum);
+
+static int mcs_speed_change(struct mcs_cb *mcs);
+
+static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd);
+static int mcs_net_close(struct net_device *netdev);
+static int mcs_net_open(struct net_device *netdev);
+static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev);
+
+static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs);
+static void mcs_send_irq(struct urb *urb, struct pt_regs *regs);
+static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *netdev);
+
+static int mcs_probe(struct usb_interface *intf,
+		     const struct usb_device_id *id);
+static void mcs_disconnect(struct usb_interface *intf);
+
+#endif				/* _MCS7780_H */
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index cc7ff8f..cb62f2a 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -115,8 +115,12 @@
 	/* Contributed by Jan Frey - IBM A30/A31 */
 	{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, 
 	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
-	{ "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
- 	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
+	/* IBM ThinkPads using PC8738x (T60/X60/Z60) */
+	{ "IBM-PC8738x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
+	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
+	/* IBM ThinkPads using PC8394T (T43/R52/?) */
+	{ "IBM-PC8394T", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf9, 0xff,
+	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
 	{ NULL }
 };
 
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 31867e4..d61b208 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -50,6 +50,7 @@
 #include <linux/delay.h>
 #include <linux/usb.h>
 #include <linux/crc32.h>
+#include <linux/kthread.h>
 #include <net/irda/irda.h>
 #include <net/irda/irlap.h>
 #include <net/irda/irda_device.h>
@@ -173,9 +174,7 @@
         struct qos_info   qos;
 	unsigned 	  speed;	/* Current speed */
 
-	wait_queue_head_t thr_wait;	/* transmit thread wakeup */
-	struct completion thr_exited;
-	pid_t		  thr_pid;
+        struct task_struct *thread;     /* transmit thread */
 
 	struct sk_buff	  *tx_pending;
 	void		  *io_buf;	/* transmit/receive buffer */
@@ -577,7 +576,7 @@
 	SKB_LINEAR_ASSERT(skb);
 
 	skb = xchg(&stir->tx_pending, skb);
-	wake_up(&stir->thr_wait);
+        wake_up_process(stir->thread);
 	
 	/* this should never happen unless stop/wakeup problem */
 	if (unlikely(skb)) {
@@ -753,13 +752,7 @@
 	struct net_device *dev = stir->netdev;
 	struct sk_buff *skb;
 
-	daemonize("%s", dev->name);
-	allow_signal(SIGTERM);
-
-	while (netif_running(dev)
-	       && netif_device_present(dev)
-	       && !signal_pending(current))
-	{
+        while (!kthread_should_stop()) {
 #ifdef CONFIG_PM
 		/* if suspending, then power off and wait */
 		if (unlikely(freezing(current))) {
@@ -813,10 +806,11 @@
 		}
 
 		/* sleep if nothing to send */
-		wait_event_interruptible(stir->thr_wait, stir->tx_pending);
-	}
+                set_current_state(TASK_INTERRUPTIBLE);
+                schedule();
 
-	complete_and_exit (&stir->thr_exited, 0);
+	}
+        return 0;
 }
 
 
@@ -859,7 +853,7 @@
 		warn("%s: usb receive submit error: %d",
 			stir->netdev->name, err);
 		stir->receiving = 0;
-		wake_up(&stir->thr_wait);
+		wake_up_process(stir->thread);
 	}
 }
 
@@ -928,10 +922,10 @@
 	}
 
 	/** Start kernel thread for transmit.  */
-	stir->thr_pid = kernel_thread(stir_transmit_thread, stir,
-				      CLONE_FS|CLONE_FILES);
-	if (stir->thr_pid < 0) {
-		err = stir->thr_pid;
+	stir->thread = kthread_run(stir_transmit_thread, stir,
+				   "%s", stir->netdev->name);
+        if (IS_ERR(stir->thread)) {
+                err = PTR_ERR(stir->thread);
 		err("stir4200: unable to start kernel thread");
 		goto err_out6;
 	}
@@ -968,8 +962,7 @@
 	netif_stop_queue(netdev);
 
 	/* Kill transmit thread */
-	kill_proc(stir->thr_pid, SIGTERM, 1);
-	wait_for_completion(&stir->thr_exited);
+	kthread_stop(stir->thread);
 	kfree(stir->fifo_status);
 
 	/* Mop up receive urb's */
@@ -1084,9 +1077,6 @@
 	stir->qos.min_turn_time.bits   &= qos_mtt_bits;
 	irda_qos_bits_to_value(&stir->qos);
 
-	init_completion (&stir->thr_exited);
-	init_waitqueue_head (&stir->thr_wait);
-
 	/* Override the network functions we need to use */
 	net->hard_start_xmit = stir_hard_xmit;
 	net->open            = stir_net_open;
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 97a49e0..d70b9e8 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -959,7 +959,7 @@
 			    ||  (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
 			    	break;
 			udelay(100);
-			/* must not sleep here - we are called under xmit_lock! */
+			/* must not sleep here - called under netif_tx_lock! */
 		}
 	}
 
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index f0f04be..93394d7 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -69,6 +69,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/ethtool.h>
+#include <linux/if_ether.h>
 
 #include <asm/abs_addr.h>
 #include <asm/iseries/mf.h>
@@ -1035,11 +1036,22 @@
 	.get_link = veth_get_link,
 };
 
-static struct net_device * __init veth_probe_one(int vlan, struct device *vdev)
+static struct net_device * __init veth_probe_one(int vlan,
+		struct vio_dev *vio_dev)
 {
 	struct net_device *dev;
 	struct veth_port *port;
+	struct device *vdev = &vio_dev->dev;
 	int i, rc;
+	const unsigned char *mac_addr;
+
+	mac_addr = vio_get_attribute(vio_dev, "local-mac-address", NULL);
+	if (mac_addr == NULL)
+		mac_addr = vio_get_attribute(vio_dev, "mac-address", NULL);
+	if (mac_addr == NULL) {
+		veth_error("Unable to fetch MAC address from device tree.\n");
+		return NULL;
+	}
 
 	dev = alloc_etherdev(sizeof (struct veth_port));
 	if (! dev) {
@@ -1064,16 +1076,11 @@
 	}
 	port->dev = vdev;
 
-	dev->dev_addr[0] = 0x02;
-	dev->dev_addr[1] = 0x01;
-	dev->dev_addr[2] = 0xff;
-	dev->dev_addr[3] = vlan;
-	dev->dev_addr[4] = 0xff;
-	dev->dev_addr[5] = this_lp;
+	memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
 
 	dev->mtu = VETH_MAX_MTU;
 
-	memcpy(&port->mac_addr, dev->dev_addr, 6);
+	memcpy(&port->mac_addr, mac_addr, ETH_ALEN);
 
 	dev->open = veth_open;
 	dev->hard_start_xmit = veth_start_xmit;
@@ -1608,7 +1615,7 @@
 	struct net_device *dev;
 	struct veth_port *port;
 
-	dev = veth_probe_one(i, &vdev->dev);
+	dev = veth_probe_one(i, vdev);
 	if (dev == NULL) {
 		veth_remove(vdev);
 		return 1;
@@ -1641,7 +1648,7 @@
  * support.
  */
 static struct vio_device_id veth_device_table[] __devinitdata = {
-	{ "vlan", "" },
+	{ "network", "IBM,iSeries-l-lan" },
 	{ "", "" }
 };
 MODULE_DEVICE_TABLE(vio, veth_device_table);
diff --git a/drivers/net/ixgb/Makefile b/drivers/net/ixgb/Makefile
index 7c7aff1..a8a2d3d 100644
--- a/drivers/net/ixgb/Makefile
+++ b/drivers/net/ixgb/Makefile
@@ -1,7 +1,7 @@
 ################################################################################
 #
 # 
-# Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
+# Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
 # 
 # This program is free software; you can redistribute it and/or modify it 
 # under the terms of the GNU General Public License as published by the Free 
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index c83271b..a83ef28 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -84,7 +84,12 @@
 #define IXGB_DBG(args...)
 #endif
 
-#define IXGB_ERR(args...) printk(KERN_ERR "ixgb: " args)
+#define PFX "ixgb: "
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+	(void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \
+	printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \
+		__FUNCTION__ , ## args))
+
 
 /* TX/RX descriptor defines */
 #define DEFAULT_TXD	 256
@@ -175,6 +180,7 @@
 	uint64_t hw_csum_tx_good;
 	uint64_t hw_csum_tx_error;
 	uint32_t tx_int_delay;
+	uint32_t tx_timeout_count;
 	boolean_t tx_int_delay_enable;
 	boolean_t detect_tx_hung;
 
@@ -192,7 +198,9 @@
 
 	/* structs defined in ixgb_hw.h */
 	struct ixgb_hw hw;
+	u16 msg_enable;
 	struct ixgb_hw_stats stats;
+	uint32_t alloc_rx_buff_failed;
 #ifdef CONFIG_PCI_MSI
 	boolean_t have_msi;
 #endif
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 661a46b..8357c55 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff --git a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ixgb/ixgb_ee.h
index 5190aa8..bf6fa22 100644
--- a/drivers/net/ixgb/ixgb_ee.h
+++ b/drivers/net/ixgb/ixgb_ee.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index d38ade5..cf19b89 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -44,6 +44,8 @@
 extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
 extern void ixgb_update_stats(struct ixgb_adapter *adapter);
 
+#define IXGB_ALL_RAR_ENTRIES 16
+
 struct ixgb_stats {
 	char stat_string[ETH_GSTRING_LEN];
 	int sizeof_stat;
@@ -76,6 +78,7 @@
 	{"tx_heartbeat_errors", IXGB_STAT(net_stats.tx_heartbeat_errors)},
 	{"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
 	{"tx_deferred_ok", IXGB_STAT(stats.dc)},
+	{"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
 	{"rx_long_length_errors", IXGB_STAT(stats.roc)},
 	{"rx_short_length_errors", IXGB_STAT(stats.ruc)},
 #ifdef NETIF_F_TSO
@@ -117,6 +120,16 @@
 	return 0;
 }
 
+static void ixgb_set_speed_duplex(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev_priv(netdev);
+	/* be optimistic about our link, since we were up before */
+	adapter->link_speed = 10000;
+	adapter->link_duplex = FULL_DUPLEX;
+	netif_carrier_on(netdev);
+	netif_wake_queue(netdev);
+}
+
 static int
 ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
@@ -130,12 +143,7 @@
 		ixgb_down(adapter, TRUE);
 		ixgb_reset(adapter);
 		ixgb_up(adapter);
-		/* be optimistic about our link, since we were up before */
-		adapter->link_speed = 10000;
-		adapter->link_duplex = FULL_DUPLEX;
-		netif_carrier_on(netdev);
-		netif_wake_queue(netdev);
-		
+		ixgb_set_speed_duplex(netdev);
 	} else
 		ixgb_reset(adapter);
 
@@ -183,11 +191,7 @@
 	if(netif_running(adapter->netdev)) {
 		ixgb_down(adapter, TRUE);
 		ixgb_up(adapter);
-		/* be optimistic about our link, since we were up before */
-		adapter->link_speed = 10000;
-		adapter->link_duplex = FULL_DUPLEX;
-		netif_carrier_on(netdev);
-		netif_wake_queue(netdev);
+		ixgb_set_speed_duplex(netdev);
 	} else
 		ixgb_reset(adapter);
 		
@@ -212,11 +216,7 @@
 	if(netif_running(netdev)) {
 		ixgb_down(adapter,TRUE);
 		ixgb_up(adapter);
-		/* be optimistic about our link, since we were up before */
-		adapter->link_speed = 10000;
-		adapter->link_duplex = FULL_DUPLEX;
-		netif_carrier_on(netdev);
-		netif_wake_queue(netdev);
+		ixgb_set_speed_duplex(netdev);
 	} else
 		ixgb_reset(adapter);
 	return 0;
@@ -251,6 +251,19 @@
 } 
 #endif /* NETIF_F_TSO */
 
+static uint32_t
+ixgb_get_msglevel(struct net_device *netdev)
+{
+	struct ixgb_adapter *adapter = netdev_priv(netdev);
+	return adapter->msg_enable;
+}
+
+static void
+ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
+{
+	struct ixgb_adapter *adapter = netdev_priv(netdev);
+	adapter->msg_enable = data;
+}
 #define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
 
 static int 
@@ -303,7 +316,7 @@
 	*reg++ = IXGB_READ_REG(hw, RXCSUM);	/*  20 */
 
 	/* there are 16 RAR entries in hardware, we only use 3 */
-	for(i = 0; i < 16; i++) {
+	for(i = 0; i < IXGB_ALL_RAR_ENTRIES; i++) {
 		*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
 		*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
 	}
@@ -593,11 +606,7 @@
 		adapter->tx_ring = tx_new;
 		if((err = ixgb_up(adapter)))
 			return err;
-		/* be optimistic about our link, since we were up before */
-		adapter->link_speed = 10000;
-		adapter->link_duplex = FULL_DUPLEX;
-		netif_carrier_on(netdev);
-		netif_wake_queue(netdev);
+		ixgb_set_speed_duplex(netdev);
 	}
 
 	return 0;
@@ -714,6 +723,8 @@
 	.set_tx_csum = ixgb_set_tx_csum,
 	.get_sg	= ethtool_op_get_sg,
 	.set_sg	= ethtool_op_set_sg,
+	.get_msglevel = ixgb_get_msglevel,
+	.set_msglevel = ixgb_set_msglevel,
 #ifdef NETIF_F_TSO
 	.get_tso = ethtool_op_get_tso,
 	.set_tso = ixgb_set_tso,
diff --git a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
index 620cad4..f7fa10e 100644
--- a/drivers/net/ixgb/ixgb_hw.c
+++ b/drivers/net/ixgb/ixgb_hw.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff --git a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
index 382c630..cb45689 100644
--- a/drivers/net/ixgb/ixgb_hw.h
+++ b/drivers/net/ixgb/ixgb_hw.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -57,6 +57,7 @@
 typedef enum {
 	ixgb_media_type_unknown = 0,
 	ixgb_media_type_fiber = 1,
+	ixgb_media_type_copper = 2,
 	ixgb_num_media_types
 } ixgb_media_type;
 
diff --git a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h
index aee207e..40a085f 100644
--- a/drivers/net/ixgb/ixgb_ids.h
+++ b/drivers/net/ixgb/ixgb_ids.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -43,6 +43,8 @@
 #define IXGB_SUBDEVICE_ID_A11F      0xA11F   
 #define IXGB_SUBDEVICE_ID_A01F      0xA01F   
 
-#endif /* #ifndef _IXGB_IDS_H_ */
+#define IXGB_DEVICE_ID_82597EX_CX4   0x109E
+#define IXGB_SUBDEVICE_ID_A00C  0xA00C
 
+#endif /* #ifndef _IXGB_IDS_H_ */
 /* End of File */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index cfd67d8..8bb32f9 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -28,22 +28,6 @@
 
 #include "ixgb.h"
 
-/* Change Log
- * 1.0.96 04/19/05
- * - Make needlessly global code static -- bunk@stusta.de
- * - ethtool cleanup -- shemminger@osdl.org
- * - Support for MODULE_VERSION -- linville@tuxdriver.com
- * - add skb_header_cloned check to the tso path -- herbert@apana.org.au
- * 1.0.88 01/05/05
- * - include fix to the condition that determines when to quit NAPI - Robert Olsson
- * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
- * 1.0.84 10/26/04
- * - reset buffer_info->dma in Tx resource cleanup logic
- * 1.0.83 10/12/04
- * - sparse cleanup - shemminger@osdl.org
- * - fix tx resource cleanup logic
- */
-
 char ixgb_driver_name[] = "ixgb";
 static char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
 
@@ -52,9 +36,9 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-#define DRV_VERSION		"1.0.100-k2"DRIVERNAPI
+#define DRV_VERSION		"1.0.109-k2"DRIVERNAPI
 char ixgb_driver_version[] = DRV_VERSION;
-static char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
+static char ixgb_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
  *
@@ -67,6 +51,8 @@
 static struct pci_device_id ixgb_pci_tbl[] = {
 	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_CX4,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_SR,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{INTEL_VENDOR_ID, IXGB_DEVICE_ID_82597EX_LR,  
@@ -148,6 +134,11 @@
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+#define DEFAULT_DEBUG_LEVEL_SHIFT 3
+static int debug = DEFAULT_DEBUG_LEVEL_SHIFT;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
 /* some defines for controlling descriptor fetches in h/w */
 #define RXDCTL_WTHRESH_DEFAULT 16	/* chip writes back at this many or RXT0 */
 #define RXDCTL_PTHRESH_DEFAULT 0		/* chip considers prefech below
@@ -196,7 +187,7 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 ixgb_irq_disable(struct ixgb_adapter *adapter)
 {
 	atomic_inc(&adapter->irq_sem);
@@ -210,7 +201,7 @@
  * @adapter: board private structure
  **/
 
-static inline void
+static void
 ixgb_irq_enable(struct ixgb_adapter *adapter)
 {
 	if(atomic_dec_and_test(&adapter->irq_sem)) {
@@ -231,6 +222,7 @@
 
 	/* hardware has been reset, we need to reload some things */
 
+	ixgb_rar_set(hw, netdev->dev_addr, 0);
 	ixgb_set_multi(netdev);
 
 	ixgb_restore_vlan(adapter);
@@ -240,6 +232,9 @@
 	ixgb_configure_rx(adapter);
 	ixgb_alloc_rx_buffers(adapter);
 
+	/* disable interrupts and get the hardware into a known state */
+	IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
+
 #ifdef CONFIG_PCI_MSI
 	{
 	boolean_t pcix = (IXGB_READ_REG(&adapter->hw, STATUS) & 
@@ -249,7 +244,7 @@
 	if (!pcix)
 	   adapter->have_msi = FALSE;
 	else if((err = pci_enable_msi(adapter->pdev))) {
-		printk (KERN_ERR
+		DPRINTK(PROBE, ERR,
 		 "Unable to allocate MSI interrupt Error: %d\n", err);
 		adapter->have_msi = FALSE;
 		/* proceed to try to request regular interrupt */
@@ -259,11 +254,11 @@
 #endif
 	if((err = request_irq(adapter->pdev->irq, &ixgb_intr,
 				  SA_SHIRQ | SA_SAMPLE_RANDOM,
-				  netdev->name, netdev)))
+			          netdev->name, netdev))) {
+		DPRINTK(PROBE, ERR,
+		 "Unable to allocate interrupt Error: %d\n", err);
 		return err;
-
-	/* disable interrupts and get the hardware into a known state */
-	IXGB_WRITE_REG(&adapter->hw, IMC, 0xffffffff);
+	}
 
 	if((hw->max_frame_size != max_frame) ||
 		(hw->max_frame_size !=
@@ -285,11 +280,12 @@
 	}
 
 	mod_timer(&adapter->watchdog_timer, jiffies);
-	ixgb_irq_enable(adapter);
 
 #ifdef CONFIG_IXGB_NAPI
 	netif_poll_enable(netdev);
 #endif
+	ixgb_irq_enable(adapter);
+
 	return 0;
 }
 
@@ -326,7 +322,7 @@
 
 	ixgb_adapter_stop(&adapter->hw);
 	if(!ixgb_init_hw(&adapter->hw))
-		IXGB_DBG("ixgb_init_hw failed.\n");
+		DPRINTK(PROBE, ERR, "ixgb_init_hw failed.\n");
 }
 
 /**
@@ -363,7 +359,8 @@
 	} else {
 		if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) ||
 		   (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) {
-			IXGB_ERR("No usable DMA configuration, aborting\n");
+			printk(KERN_ERR
+			 "ixgb: No usable DMA configuration, aborting\n");
 			goto err_dma_mask;
 		}
 		pci_using_dac = 0;
@@ -388,6 +385,7 @@
 	adapter->netdev = netdev;
 	adapter->pdev = pdev;
 	adapter->hw.back = adapter;
+	adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT);
 
 	mmio_start = pci_resource_start(pdev, BAR_0);
 	mmio_len = pci_resource_len(pdev, BAR_0);
@@ -416,7 +414,7 @@
 	netdev->change_mtu = &ixgb_change_mtu;
 	ixgb_set_ethtool_ops(netdev);
 	netdev->tx_timeout = &ixgb_tx_timeout;
-	netdev->watchdog_timeo = HZ;
+	netdev->watchdog_timeo = 5 * HZ;
 #ifdef CONFIG_IXGB_NAPI
 	netdev->poll = &ixgb_clean;
 	netdev->weight = 64;
@@ -428,6 +426,7 @@
 	netdev->poll_controller = ixgb_netpoll;
 #endif
 
+	strcpy(netdev->name, pci_name(pdev));
 	netdev->mem_start = mmio_start;
 	netdev->mem_end = mmio_start + mmio_len;
 	netdev->base_addr = adapter->hw.io_base;
@@ -449,6 +448,9 @@
 #ifdef NETIF_F_TSO
 	netdev->features |= NETIF_F_TSO;
 #endif
+#ifdef NETIF_F_LLTX
+	netdev->features |= NETIF_F_LLTX;
+#endif
 
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
@@ -456,7 +458,7 @@
 	/* make sure the EEPROM is good */
 
 	if(!ixgb_validate_eeprom_checksum(&adapter->hw)) {
-		printk(KERN_ERR "The EEPROM Checksum Is Not Valid\n");
+		DPRINTK(PROBE, ERR, "The EEPROM Checksum Is Not Valid\n");
 		err = -EIO;
 		goto err_eeprom;
 	}
@@ -465,6 +467,7 @@
 	memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
 
 	if(!is_valid_ether_addr(netdev->perm_addr)) {
+		DPRINTK(PROBE, ERR, "Invalid MAC Address\n");
 		err = -EIO;
 		goto err_eeprom;
 	}
@@ -478,6 +481,7 @@
 	INIT_WORK(&adapter->tx_timeout_task,
 		  (void (*)(void *))ixgb_tx_timeout_task, netdev);
 
+	strcpy(netdev->name, "eth%d");
 	if((err = register_netdev(netdev)))
 		goto err_register;
 
@@ -486,8 +490,7 @@
 	netif_carrier_off(netdev);
 	netif_stop_queue(netdev);
 
-	printk(KERN_INFO "%s: Intel(R) PRO/10GbE Network Connection\n",
-		   netdev->name);
+	DPRINTK(PROBE, INFO, "Intel(R) PRO/10GbE Network Connection\n");
 	ixgb_check_options(adapter);
 	/* reset the hardware with the new settings */
 
@@ -557,17 +560,17 @@
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_id = pdev->subsystem_device;
 
-	adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
-
 	hw->max_frame_size = netdev->mtu + ENET_HEADER_SIZE + ENET_FCS_LENGTH;
+	adapter->rx_buffer_len = hw->max_frame_size;
 
 	if((hw->device_id == IXGB_DEVICE_ID_82597EX)
-	   ||(hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
-	   ||(hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
+	   || (hw->device_id == IXGB_DEVICE_ID_82597EX_CX4)
+	   || (hw->device_id == IXGB_DEVICE_ID_82597EX_LR)
+	   || (hw->device_id == IXGB_DEVICE_ID_82597EX_SR))
 			hw->mac_type = ixgb_82597;
 	else {
 		/* should never have loaded on this device */
-		printk(KERN_ERR "ixgb: unsupported device id\n");
+		DPRINTK(PROBE, ERR, "unsupported device id\n");
 	}
 
 	/* enable flow control to be programmed */
@@ -665,6 +668,8 @@
 	size = sizeof(struct ixgb_buffer) * txdr->count;
 	txdr->buffer_info = vmalloc(size);
 	if(!txdr->buffer_info) {
+		DPRINTK(PROBE, ERR,
+		 "Unable to allocate transmit descriptor ring memory\n");
 		return -ENOMEM;
 	}
 	memset(txdr->buffer_info, 0, size);
@@ -677,6 +682,8 @@
 	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
 	if(!txdr->desc) {
 		vfree(txdr->buffer_info);
+		DPRINTK(PROBE, ERR,
+		 "Unable to allocate transmit descriptor memory\n");
 		return -ENOMEM;
 	}
 	memset(txdr->desc, 0, txdr->size);
@@ -750,6 +757,8 @@
 	size = sizeof(struct ixgb_buffer) * rxdr->count;
 	rxdr->buffer_info = vmalloc(size);
 	if(!rxdr->buffer_info) {
+		DPRINTK(PROBE, ERR,
+		 "Unable to allocate receive descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(rxdr->buffer_info, 0, size);
@@ -763,6 +772,8 @@
 
 	if(!rxdr->desc) {
 		vfree(rxdr->buffer_info);
+		DPRINTK(PROBE, ERR,
+		 "Unable to allocate receive descriptors\n");
 		return -ENOMEM;
 	}
 	memset(rxdr->desc, 0, rxdr->size);
@@ -794,21 +805,14 @@
 
 	rctl |= IXGB_RCTL_SECRC;
 
-	switch (adapter->rx_buffer_len) {
-	case IXGB_RXBUFFER_2048:
-	default:
+	if (adapter->rx_buffer_len <= IXGB_RXBUFFER_2048)
 		rctl |= IXGB_RCTL_BSIZE_2048;
-		break;
-	case IXGB_RXBUFFER_4096:
+	else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_4096)
 		rctl |= IXGB_RCTL_BSIZE_4096;
-		break;
-	case IXGB_RXBUFFER_8192:
+	else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_8192)
 		rctl |= IXGB_RCTL_BSIZE_8192;
-		break;
-	case IXGB_RXBUFFER_16384:
+	else if (adapter->rx_buffer_len <= IXGB_RXBUFFER_16384)
 		rctl |= IXGB_RCTL_BSIZE_16384;
-		break;
-	}
 
 	IXGB_WRITE_REG(&adapter->hw, RCTL, rctl);
 }
@@ -898,22 +902,25 @@
 	adapter->tx_ring.desc = NULL;
 }
 
-static inline void
+static void
 ixgb_unmap_and_free_tx_resource(struct ixgb_adapter *adapter,
 					struct ixgb_buffer *buffer_info)
 {
 	struct pci_dev *pdev = adapter->pdev;
-	if(buffer_info->dma) {
-		pci_unmap_page(pdev,
-			   buffer_info->dma,
-			   buffer_info->length,
-			   PCI_DMA_TODEVICE);
-		buffer_info->dma = 0;
-	}
-	if(buffer_info->skb) {
+
+	if (buffer_info->dma)
+		pci_unmap_page(pdev, buffer_info->dma, buffer_info->length,
+		               PCI_DMA_TODEVICE);
+
+	if (buffer_info->skb)
 		dev_kfree_skb_any(buffer_info->skb);
-		buffer_info->skb = NULL;
-	}
+
+	buffer_info->skb = NULL;
+	buffer_info->dma = 0;
+	buffer_info->time_stamp = 0;
+	/* these fields must always be initialized in tx
+	 * buffer_info->length = 0;
+	 * buffer_info->next_to_watch = 0; */
 }
 
 /**
@@ -1112,8 +1119,8 @@
 
 	if(adapter->hw.link_up) {
 		if(!netif_carrier_ok(netdev)) {
-			printk(KERN_INFO "ixgb: %s NIC Link is Up %d Mbps %s\n",
-				   netdev->name, 10000, "Full Duplex");
+			DPRINTK(LINK, INFO,
+			        "NIC Link is Up 10000 Mbps Full Duplex\n");
 			adapter->link_speed = 10000;
 			adapter->link_duplex = FULL_DUPLEX;
 			netif_carrier_on(netdev);
@@ -1123,9 +1130,7 @@
 		if(netif_carrier_ok(netdev)) {
 			adapter->link_speed = 0;
 			adapter->link_duplex = 0;
-			printk(KERN_INFO
-				   "ixgb: %s NIC Link is Down\n",
-				   netdev->name);
+			DPRINTK(LINK, INFO, "NIC Link is Down\n");
 			netif_carrier_off(netdev);
 			netif_stop_queue(netdev);
 
@@ -1158,7 +1163,7 @@
 #define IXGB_TX_FLAGS_VLAN		0x00000002
 #define IXGB_TX_FLAGS_TSO		0x00000004
 
-static inline int
+static int
 ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
@@ -1168,7 +1173,7 @@
 	uint16_t ipcse, tucse, mss;
 	int err;
 
-	if(likely(skb_shinfo(skb)->tso_size)) {
+	if(likely(skb_shinfo(skb)->gso_size)) {
 		if (skb_header_cloned(skb)) {
 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 			if (err)
@@ -1176,7 +1181,7 @@
 		}
 
 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
-		mss = skb_shinfo(skb)->tso_size;
+		mss = skb_shinfo(skb)->gso_size;
 		skb->nh.iph->tot_len = 0;
 		skb->nh.iph->check = 0;
 		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
@@ -1220,7 +1225,7 @@
 	return 0;
 }
 
-static inline boolean_t
+static boolean_t
 ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
 	struct ixgb_context_desc *context_desc;
@@ -1258,7 +1263,7 @@
 #define IXGB_MAX_TXD_PWR	14
 #define IXGB_MAX_DATA_PER_TXD	(1<<IXGB_MAX_TXD_PWR)
 
-static inline int
+static int
 ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
 	    unsigned int first)
 {
@@ -1284,6 +1289,7 @@
 				size,
 				PCI_DMA_TODEVICE);
 		buffer_info->time_stamp = jiffies;
+		buffer_info->next_to_watch = 0;
 
 		len -= size;
 		offset += size;
@@ -1309,6 +1315,7 @@
 					size,
 					PCI_DMA_TODEVICE);
 			buffer_info->time_stamp = jiffies;
+			buffer_info->next_to_watch = 0;
 
 			len -= size;
 			offset += size;
@@ -1323,7 +1330,7 @@
 	return count;
 }
 
-static inline void
+static void
 ixgb_tx_queue(struct ixgb_adapter *adapter, int count, int vlan_id,int tx_flags)
 {
 	struct ixgb_desc_ring *tx_ring = &adapter->tx_ring;
@@ -1395,13 +1402,26 @@
 		return 0;
 	}
 
+#ifdef NETIF_F_LLTX
+	local_irq_save(flags);
+	if (!spin_trylock(&adapter->tx_lock)) {
+		/* Collision - tell upper layer to requeue */
+		local_irq_restore(flags);
+		return NETDEV_TX_LOCKED;
+	}
+#else
 	spin_lock_irqsave(&adapter->tx_lock, flags);
+#endif
+
 	if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED)) {
 		netif_stop_queue(netdev);
 		spin_unlock_irqrestore(&adapter->tx_lock, flags);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
+
+#ifndef NETIF_F_LLTX
 	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+#endif
 
 	if(adapter->vlgrp && vlan_tx_tag_present(skb)) {
 		tx_flags |= IXGB_TX_FLAGS_VLAN;
@@ -1413,10 +1433,13 @@
 	tso = ixgb_tso(adapter, skb);
 	if (tso < 0) {
 		dev_kfree_skb_any(skb);
+#ifdef NETIF_F_LLTX
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
+#endif
 		return NETDEV_TX_OK;
 	}
 
-	if (tso)
+	if (likely(tso))
 		tx_flags |= IXGB_TX_FLAGS_TSO;
 	else if(ixgb_tx_csum(adapter, skb))
 		tx_flags |= IXGB_TX_FLAGS_CSUM;
@@ -1426,7 +1449,15 @@
 
 	netdev->trans_start = jiffies;
 
-	return 0;
+#ifdef NETIF_F_LLTX
+	/* Make sure there is space in the ring for the next send. */
+	if(unlikely(IXGB_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED))
+		netif_stop_queue(netdev);
+
+	spin_unlock_irqrestore(&adapter->tx_lock, flags);
+
+#endif
+	return NETDEV_TX_OK;
 }
 
 /**
@@ -1448,6 +1479,7 @@
 {
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 
+	adapter->tx_timeout_count++;
 	ixgb_down(adapter, TRUE);
 	ixgb_up(adapter);
 }
@@ -1486,28 +1518,15 @@
 
 	if((max_frame < IXGB_MIN_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
 	   || (max_frame > IXGB_MAX_JUMBO_FRAME_SIZE + ENET_FCS_LENGTH)) {
-		IXGB_ERR("Invalid MTU setting\n");
+		DPRINTK(PROBE, ERR, "Invalid MTU setting %d\n", new_mtu);
 		return -EINVAL;
 	}
 
-	if((max_frame <= IXGB_MAX_ENET_FRAME_SIZE_WITHOUT_FCS + ENET_FCS_LENGTH)
-	   || (max_frame <= IXGB_RXBUFFER_2048)) {
-		adapter->rx_buffer_len = IXGB_RXBUFFER_2048;
-
-	} else if(max_frame <= IXGB_RXBUFFER_4096) {
-		adapter->rx_buffer_len = IXGB_RXBUFFER_4096;
-
-	} else if(max_frame <= IXGB_RXBUFFER_8192) {
-		adapter->rx_buffer_len = IXGB_RXBUFFER_8192;
-
-	} else {
-		adapter->rx_buffer_len = IXGB_RXBUFFER_16384;
-	}
+	adapter->rx_buffer_len = max_frame;
 
 	netdev->mtu = new_mtu;
 
-	if(old_max_frame != max_frame && netif_running(netdev)) {
-
+	if ((old_max_frame != max_frame) && netif_running(netdev)) {
 		ixgb_down(adapter, TRUE);
 		ixgb_up(adapter);
 	}
@@ -1765,23 +1784,43 @@
 
 	tx_ring->next_to_clean = i;
 
-	spin_lock(&adapter->tx_lock);
-	if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
-	   (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE)) {
-
-		netif_wake_queue(netdev);
+	if (unlikely(netif_queue_stopped(netdev))) {
+		spin_lock(&adapter->tx_lock);
+		if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev) &&
+		    (IXGB_DESC_UNUSED(tx_ring) > IXGB_TX_QUEUE_WAKE))
+			netif_wake_queue(netdev);
+		spin_unlock(&adapter->tx_lock);
 	}
-	spin_unlock(&adapter->tx_lock);
 
 	if(adapter->detect_tx_hung) {
 		/* detect a transmit hang in hardware, this serializes the
 		 * check with the clearing of time_stamp and movement of i */
 		adapter->detect_tx_hung = FALSE;
-		if(tx_ring->buffer_info[i].dma &&
-		   time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+		if (tx_ring->buffer_info[eop].dma &&
+		   time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + HZ)
 		   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
-			IXGB_STATUS_TXOFF))
+		        IXGB_STATUS_TXOFF)) {
+			/* detected Tx unit hang */
+			DPRINTK(DRV, ERR, "Detected Tx Unit Hang\n"
+					"  TDH                  <%x>\n"
+					"  TDT                  <%x>\n"
+					"  next_to_use          <%x>\n"
+					"  next_to_clean        <%x>\n"
+					"buffer_info[next_to_clean]\n"
+					"  time_stamp           <%lx>\n"
+					"  next_to_watch        <%x>\n"
+					"  jiffies              <%lx>\n"
+					"  next_to_watch.status <%x>\n",
+				IXGB_READ_REG(&adapter->hw, TDH),
+				IXGB_READ_REG(&adapter->hw, TDT),
+				tx_ring->next_to_use,
+				tx_ring->next_to_clean,
+				tx_ring->buffer_info[eop].time_stamp,
+				eop,
+				jiffies,
+				eop_desc->status);
 			netif_stop_queue(netdev);
+		}
 	}
 
 	return cleaned;
@@ -1794,7 +1833,7 @@
  * @sk_buff: socket buffer with received data
  **/
 
-static inline void
+static void
 ixgb_rx_checksum(struct ixgb_adapter *adapter,
 		 struct ixgb_rx_desc *rx_desc,
 		 struct sk_buff *skb)
@@ -1858,6 +1897,7 @@
 #endif
 		status = rx_desc->status;
 		skb = buffer_info->skb;
+		buffer_info->skb = NULL;
 
 		prefetch(skb->data);
 
@@ -1902,6 +1942,26 @@
 			goto rxdesc_done;
 		}
 
+		/* code added for copybreak, this should improve
+		 * performance for small packets with large amounts
+		 * of reassembly being done in the stack */
+#define IXGB_CB_LENGTH 256
+		if (length < IXGB_CB_LENGTH) {
+			struct sk_buff *new_skb =
+			    dev_alloc_skb(length + NET_IP_ALIGN);
+			if (new_skb) {
+				skb_reserve(new_skb, NET_IP_ALIGN);
+				new_skb->dev = netdev;
+				memcpy(new_skb->data - NET_IP_ALIGN,
+				       skb->data - NET_IP_ALIGN,
+				       length + NET_IP_ALIGN);
+				/* save the skb in buffer_info as good */
+				buffer_info->skb = skb;
+				skb = new_skb;
+			}
+		}
+		/* end copybreak code */
+
 		/* Good Receive */
 		skb_put(skb, length);
 
@@ -1931,7 +1991,6 @@
 rxdesc_done:
 		/* clean up descriptor, might be written over by hw */
 		rx_desc->status = 0;
-		buffer_info->skb = NULL;
 
 		/* use prefetched values */
 		rx_desc = next_rxd;
@@ -1971,12 +2030,18 @@
 
 	/* leave three descriptors unused */
 	while(--cleancount > 2) {
-		rx_desc = IXGB_RX_DESC(*rx_ring, i);
+		/* recycle! its good for you */
+		if (!(skb = buffer_info->skb))
+			skb = dev_alloc_skb(adapter->rx_buffer_len
+			                    + NET_IP_ALIGN);
+		else {
+			skb_trim(skb, 0);
+			goto map_skb;
+		}
 
-		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
-
-		if(unlikely(!skb)) {
+		if (unlikely(!skb)) {
 			/* Better luck next round */
+			adapter->alloc_rx_buff_failed++;
 			break;
 		}
 
@@ -1990,33 +2055,36 @@
 
 		buffer_info->skb = skb;
 		buffer_info->length = adapter->rx_buffer_len;
-		buffer_info->dma =
-			pci_map_single(pdev,
-				   skb->data,
-				   adapter->rx_buffer_len,
-				   PCI_DMA_FROMDEVICE);
+map_skb:
+		buffer_info->dma = pci_map_single(pdev,
+		                                  skb->data,
+		                                  adapter->rx_buffer_len,
+		                                  PCI_DMA_FROMDEVICE);
 
+		rx_desc = IXGB_RX_DESC(*rx_ring, i);
 		rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
 		/* guarantee DD bit not set now before h/w gets descriptor
 		 * this is the rest of the workaround for h/w double 
 		 * writeback. */
 		rx_desc->status = 0;
 
-		if((i & ~(num_group_tail_writes- 1)) == i) {
-			/* Force memory writes to complete before letting h/w
-			 * know there are new descriptors to fetch.  (Only
-			 * applicable for weak-ordered memory model archs,
-			 * such as IA-64). */
-			wmb();
-
-			IXGB_WRITE_REG(&adapter->hw, RDT, i);
-		}
 
 		if(++i == rx_ring->count) i = 0;
 		buffer_info = &rx_ring->buffer_info[i];
 	}
 
-	rx_ring->next_to_use = i;
+	if (likely(rx_ring->next_to_use != i)) {
+		rx_ring->next_to_use = i;
+		if (unlikely(i-- == 0))
+			i = (rx_ring->count - 1);
+
+		/* Force memory writes to complete before letting h/w
+		 * know there are new descriptors to fetch.  (Only
+		 * applicable for weak-ordered memory model archs, such
+		 * as IA-64). */
+		wmb();
+		IXGB_WRITE_REG(&adapter->hw, RDT, i);
+	}
 }
 
 /**
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
index dba2048..ee982fe 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
diff --git a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
index 8a83dfd..39fbed2 100644
--- a/drivers/net/ixgb/ixgb_param.c
+++ b/drivers/net/ixgb/ixgb_param.c
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2006 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -76,7 +76,7 @@
  *  - 2 - Tx only, generate PAUSE frames but ignore them on receive
  *  - 3 - Full Flow Control Support
  *
- * Default Value: Read flow control settings from the EEPROM
+ * Default Value: 2 - Tx only (silicon bug avoidance)
  */
 
 IXGB_PARAM(FlowControl, "Flow Control setting");
@@ -137,7 +137,7 @@
  *
  * Valid Range: 1 - 65535 
  *
- * Default Value:  256 (0x100)
+ * Default Value:  65535 (0xffff) (we'll send an xon if we recover)
  */
 
 IXGB_PARAM(FCReqTimeout, "Flow Control Request Timeout");
@@ -165,8 +165,6 @@
 
 #define XSUMRX_DEFAULT		 OPTION_ENABLED
 
-#define FLOW_CONTROL_FULL	   ixgb_fc_full
-#define FLOW_CONTROL_DEFAULT  FLOW_CONTROL_FULL
 #define DEFAULT_FCRTL	  		0x28000
 #define DEFAULT_FCRTH			0x30000
 #define MIN_FCRTL			      0
@@ -174,9 +172,9 @@
 #define MIN_FCRTH			      8
 #define MAX_FCRTH			0x3FFF0
 
-#define DEFAULT_FCPAUSE		  	0x100	/* this may be too long */
 #define MIN_FCPAUSE			      1
 #define MAX_FCPAUSE			 0xffff
+#define DEFAULT_FCPAUSE		  	 0xFFFF /* this may be too long */
 
 struct ixgb_option {
 	enum { enable_option, range_option, list_option } type;
@@ -336,7 +334,7 @@
 			.type = list_option,
 			.name = "Flow Control",
 			.err  = "reading default settings from EEPROM",
-			.def  = ixgb_fc_full,
+			.def  = ixgb_fc_tx_pause,
 			.arg  = { .l = { .nr = LIST_LEN(fc_list),
 					 .p = fc_list }}
 		};
@@ -365,8 +363,8 @@
 		} else {
 			adapter->hw.fc.high_water = opt.def;
 		}
-		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-			printk (KERN_INFO 
+		if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+			printk (KERN_INFO
 				"Ignoring RxFCHighThresh when no RxFC\n");
 	}
 	{ /* Receive Flow Control Low Threshold */
@@ -385,8 +383,8 @@
 		} else {
 			adapter->hw.fc.low_water = opt.def;
 		}
-		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-			printk (KERN_INFO 
+		if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+			printk (KERN_INFO
 				"Ignoring RxFCLowThresh when no RxFC\n");
 	}
 	{ /* Flow Control Pause Time Request*/
@@ -406,12 +404,12 @@
 		} else {
 			adapter->hw.fc.pause_time = opt.def;
 		}
-		if(!(adapter->hw.fc.type & ixgb_fc_rx_pause) )
-			printk (KERN_INFO 
+		if (!(adapter->hw.fc.type & ixgb_fc_tx_pause) )
+			printk (KERN_INFO
 				"Ignoring FCReqTimeout when no RxFC\n");
 	}
 	/* high low and spacing check for rx flow control thresholds */
-	if (adapter->hw.fc.type & ixgb_fc_rx_pause) {
+	if (adapter->hw.fc.type & ixgb_fc_tx_pause) {
 		/* high must be greater than low */
 		if (adapter->hw.fc.high_water < (adapter->hw.fc.low_water + 8)) {
 			/* set defaults */
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index bb5ad47..c1c3452 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -968,8 +968,7 @@
 	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
 	if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) {
 		if (skb->len < ETH_ZLEN) {
-			skb = skb_padto(skb, ETH_ZLEN);
-			if (skb == NULL)
+			if (skb_padto(skb, ETH_ZLEN))
 				goto out;
 			lp->tx_ring[entry].length = -ETH_ZLEN;
 		}
diff --git a/drivers/net/lasi_82596.c b/drivers/net/lasi_82596.c
index 957888d..1ab0944 100644
--- a/drivers/net/lasi_82596.c
+++ b/drivers/net/lasi_82596.c
@@ -1083,8 +1083,7 @@
 				skb->len, skb->data));
 
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b79d6e8..43fef7d 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -74,7 +74,7 @@
 	struct iphdr *iph = skb->nh.iph;
 	struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4));
 	unsigned int doffset = (iph->ihl + th->doff) * 4;
-	unsigned int mtu = skb_shinfo(skb)->tso_size + doffset;
+	unsigned int mtu = skb_shinfo(skb)->gso_size + doffset;
 	unsigned int offset = 0;
 	u32 seq = ntohl(th->seq);
 	u16 id  = ntohs(iph->id);
@@ -139,7 +139,7 @@
 #endif
 
 #ifdef LOOPBACK_TSO
-	if (skb_shinfo(skb)->tso_size) {
+	if (skb_shinfo(skb)->gso_size) {
 		BUG_ON(skb->protocol != htons(ETH_P_IP));
 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
 
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 94d5ea1..bf3f343 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -877,8 +877,7 @@
 	length = skb->len;
 	
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index 411f4d8..625ff61 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -1200,7 +1200,7 @@
 	}
 
 	if (has_tiny_unaligned_frags(skb)) {
-		if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
+		if (__skb_linearize(skb)) {
 			stats->tx_dropped++;
 			printk(KERN_DEBUG "%s: failed to linearize tiny "
 					"unaligned fragment\n", dev->name);
diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile
new file mode 100644
index 0000000..5df8916
--- /dev/null
+++ b/drivers/net/myri10ge/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Myricom Myri-10G ethernet driver
+#
+
+obj-$(CONFIG_MYRI10GE) += myri10ge.o
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
new file mode 100644
index 0000000..dbdf189
--- /dev/null
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -0,0 +1,2860 @@
+/*************************************************************************
+ * myri10ge.c: Myricom Myri-10G Ethernet driver.
+ *
+ * Copyright (C) 2005, 2006 Myricom, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Myricom, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * If the eeprom on your board is not recent enough, you will need to get a
+ * newer firmware image at:
+ *   http://www.myri.com/scs/download-Myri10GE.html
+ *
+ * Contact Information:
+ *   <help@myri.com>
+ *   Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006
+ *************************************************************************/
+
+#include <linux/tcp.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <linux/in.h>
+#include <linux/ethtool.h>
+#include <linux/firmware.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/timer.h>
+#include <linux/vmalloc.h>
+#include <linux/crc32.h>
+#include <linux/moduleparam.h>
+#include <linux/io.h>
+#include <net/checksum.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "myri10ge_mcp.h"
+#include "myri10ge_mcp_gen_header.h"
+
+#define MYRI10GE_VERSION_STR "1.0.0"
+
+MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
+MODULE_AUTHOR("Maintainer: help@myri.com");
+MODULE_VERSION(MYRI10GE_VERSION_STR);
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define MYRI10GE_MAX_ETHER_MTU 9014
+
+#define MYRI10GE_ETH_STOPPED 0
+#define MYRI10GE_ETH_STOPPING 1
+#define MYRI10GE_ETH_STARTING 2
+#define MYRI10GE_ETH_RUNNING 3
+#define MYRI10GE_ETH_OPEN_FAILED 4
+
+#define MYRI10GE_EEPROM_STRINGS_SIZE 256
+#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
+
+#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff
+#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
+
+struct myri10ge_rx_buffer_state {
+	struct sk_buff *skb;
+	 DECLARE_PCI_UNMAP_ADDR(bus)
+	 DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_tx_buffer_state {
+	struct sk_buff *skb;
+	int last;
+	 DECLARE_PCI_UNMAP_ADDR(bus)
+	 DECLARE_PCI_UNMAP_LEN(len)
+};
+
+struct myri10ge_cmd {
+	u32 data0;
+	u32 data1;
+	u32 data2;
+};
+
+struct myri10ge_rx_buf {
+	struct mcp_kreq_ether_recv __iomem *lanai;	/* lanai ptr for recv ring */
+	u8 __iomem *wc_fifo;	/* w/c rx dma addr fifo address */
+	struct mcp_kreq_ether_recv *shadow;	/* host shadow of recv ring */
+	struct myri10ge_rx_buffer_state *info;
+	int cnt;
+	int alloc_fail;
+	int mask;		/* number of rx slots -1 */
+};
+
+struct myri10ge_tx_buf {
+	struct mcp_kreq_ether_send __iomem *lanai;	/* lanai ptr for sendq */
+	u8 __iomem *wc_fifo;	/* w/c send fifo address */
+	struct mcp_kreq_ether_send *req_list;	/* host shadow of sendq */
+	char *req_bytes;
+	struct myri10ge_tx_buffer_state *info;
+	int mask;		/* number of transmit slots -1  */
+	int boundary;		/* boundary transmits cannot cross */
+	int req ____cacheline_aligned;	/* transmit slots submitted     */
+	int pkt_start;		/* packets started */
+	int done ____cacheline_aligned;	/* transmit slots completed     */
+	int pkt_done;		/* packets completed */
+};
+
+struct myri10ge_rx_done {
+	struct mcp_slot *entry;
+	dma_addr_t bus;
+	int cnt;
+	int idx;
+};
+
+struct myri10ge_priv {
+	int running;		/* running?             */
+	int csum_flag;		/* rx_csums?            */
+	struct myri10ge_tx_buf tx;	/* transmit ring        */
+	struct myri10ge_rx_buf rx_small;
+	struct myri10ge_rx_buf rx_big;
+	struct myri10ge_rx_done rx_done;
+	int small_bytes;
+	struct net_device *dev;
+	struct net_device_stats stats;
+	u8 __iomem *sram;
+	int sram_size;
+	unsigned long board_span;
+	unsigned long iomem_base;
+	u32 __iomem *irq_claim;
+	u32 __iomem *irq_deassert;
+	char *mac_addr_string;
+	struct mcp_cmd_response *cmd;
+	dma_addr_t cmd_bus;
+	struct mcp_irq_data *fw_stats;
+	dma_addr_t fw_stats_bus;
+	struct pci_dev *pdev;
+	int msi_enabled;
+	unsigned int link_state;
+	unsigned int rdma_tags_available;
+	int intr_coal_delay;
+	u32 __iomem *intr_coal_delay_ptr;
+	int mtrr;
+	int wake_queue;
+	int stop_queue;
+	int down_cnt;
+	wait_queue_head_t down_wq;
+	struct work_struct watchdog_work;
+	struct timer_list watchdog_timer;
+	int watchdog_tx_done;
+	int watchdog_resets;
+	int tx_linearized;
+	int pause;
+	char *fw_name;
+	char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE];
+	char fw_version[128];
+	u8 mac_addr[6];		/* eeprom mac address */
+	unsigned long serial_number;
+	int vendor_specific_offset;
+	u32 devctl;
+	u16 msi_flags;
+	u32 pm_state[16];
+	u32 read_dma;
+	u32 write_dma;
+	u32 read_write_dma;
+};
+
+static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat";
+static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat";
+
+static char *myri10ge_fw_name = NULL;
+module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n");
+
+static int myri10ge_ecrc_enable = 1;
+module_param(myri10ge_ecrc_enable, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n");
+
+static int myri10ge_max_intr_slots = 1024;
+module_param(myri10ge_max_intr_slots, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n");
+
+static int myri10ge_small_bytes = -1;	/* -1 == auto */
+module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n");
+
+static int myri10ge_msi = 1;	/* enable msi by default */
+module_param(myri10ge_msi, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n");
+
+static int myri10ge_intr_coal_delay = 25;
+module_param(myri10ge_intr_coal_delay, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n");
+
+static int myri10ge_flow_control = 1;
+module_param(myri10ge_flow_control, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n");
+
+static int myri10ge_deassert_wait = 1;
+module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_deassert_wait,
+		 "Wait when deasserting legacy interrupts\n");
+
+static int myri10ge_force_firmware = 0;
+module_param(myri10ge_force_firmware, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_force_firmware,
+		 "Force firmware to assume aligned completions\n");
+
+static int myri10ge_skb_cross_4k = 0;
+module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(myri10ge_skb_cross_4k,
+		 "Can a small skb cross a 4KB boundary?\n");
+
+static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+module_param(myri10ge_initial_mtu, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n");
+
+static int myri10ge_napi_weight = 64;
+module_param(myri10ge_napi_weight, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n");
+
+static int myri10ge_watchdog_timeout = 1;
+module_param(myri10ge_watchdog_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n");
+
+static int myri10ge_max_irq_loops = 1048576;
+module_param(myri10ge_max_irq_loops, int, S_IRUGO);
+MODULE_PARM_DESC(myri10ge_max_irq_loops,
+		 "Set stuck legacy IRQ detection threshold\n");
+
+#define MYRI10GE_FW_OFFSET 1024*1024
+#define MYRI10GE_HIGHPART_TO_U32(X) \
+(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0)
+#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X))
+
+#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8)
+
+static int
+myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
+		  struct myri10ge_cmd *data, int atomic)
+{
+	struct mcp_cmd *buf;
+	char buf_bytes[sizeof(*buf) + 8];
+	struct mcp_cmd_response *response = mgp->cmd;
+	char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET;
+	u32 dma_low, dma_high, result, value;
+	int sleep_total = 0;
+
+	/* ensure buf is aligned to 8 bytes */
+	buf = (struct mcp_cmd *)ALIGN((unsigned long)buf_bytes, 8);
+
+	buf->data0 = htonl(data->data0);
+	buf->data1 = htonl(data->data1);
+	buf->data2 = htonl(data->data2);
+	buf->cmd = htonl(cmd);
+	dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+	dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+	buf->response_addr.low = htonl(dma_low);
+	buf->response_addr.high = htonl(dma_high);
+	response->result = MYRI10GE_NO_RESPONSE_RESULT;
+	mb();
+	myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf));
+
+	/* wait up to 15ms. Longest command is the DMA benchmark,
+	 * which is capped at 5ms, but runs from a timeout handler
+	 * that runs every 7.8ms. So a 15ms timeout leaves us with
+	 * a 2.2ms margin
+	 */
+	if (atomic) {
+		/* if atomic is set, do not sleep,
+		 * and try to get the completion quickly
+		 * (1ms will be enough for those commands) */
+		for (sleep_total = 0;
+		     sleep_total < 1000
+		     && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+		     sleep_total += 10)
+			udelay(10);
+	} else {
+		/* use msleep for most command */
+		for (sleep_total = 0;
+		     sleep_total < 15
+		     && response->result == MYRI10GE_NO_RESPONSE_RESULT;
+		     sleep_total++)
+			msleep(1);
+	}
+
+	result = ntohl(response->result);
+	value = ntohl(response->data);
+	if (result != MYRI10GE_NO_RESPONSE_RESULT) {
+		if (result == 0) {
+			data->data0 = value;
+			return 0;
+		} else {
+			dev_err(&mgp->pdev->dev,
+				"command %d failed, result = %d\n",
+				cmd, result);
+			return -ENXIO;
+		}
+	}
+
+	dev_err(&mgp->pdev->dev, "command %d timed out, result = %d\n",
+		cmd, result);
+	return -EAGAIN;
+}
+
+/*
+ * The eeprom strings on the lanaiX have the format
+ * SN=x\0
+ * MAC=x:x:x:x:x:x\0
+ * PT:ddd mmm xx xx:xx:xx xx\0
+ * PV:ddd mmm xx xx:xx:xx xx\0
+ */
+static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp)
+{
+	char *ptr, *limit;
+	int i;
+
+	ptr = mgp->eeprom_strings;
+	limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE;
+
+	while (*ptr != '\0' && ptr < limit) {
+		if (memcmp(ptr, "MAC=", 4) == 0) {
+			ptr += 4;
+			mgp->mac_addr_string = ptr;
+			for (i = 0; i < 6; i++) {
+				if ((ptr + 2) > limit)
+					goto abort;
+				mgp->mac_addr[i] =
+				    simple_strtoul(ptr, &ptr, 16);
+				ptr += 1;
+			}
+		}
+		if (memcmp((const void *)ptr, "SN=", 3) == 0) {
+			ptr += 3;
+			mgp->serial_number = simple_strtoul(ptr, &ptr, 10);
+		}
+		while (ptr < limit && *ptr++) ;
+	}
+
+	return 0;
+
+abort:
+	dev_err(&mgp->pdev->dev, "failed to parse eeprom_strings\n");
+	return -ENXIO;
+}
+
+/*
+ * Enable or disable periodic RDMAs from the host to make certain
+ * chipsets resend dropped PCIe messages
+ */
+
+static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable)
+{
+	char __iomem *submit;
+	u32 buf[16];
+	u32 dma_low, dma_high;
+	int i;
+
+	/* clear confirmation addr */
+	mgp->cmd->data = 0;
+	mb();
+
+	/* send a rdma command to the PCIe engine, and wait for the
+	 * response in the confirmation address.  The firmware should
+	 * write a -1 there to indicate it is alive and well
+	 */
+	dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+	dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+	buf[0] = htonl(dma_high);	/* confirm addr MSW */
+	buf[1] = htonl(dma_low);	/* confirm addr LSW */
+	buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);	/* confirm data */
+	buf[3] = htonl(dma_high);	/* dummy addr MSW */
+	buf[4] = htonl(dma_low);	/* dummy addr LSW */
+	buf[5] = htonl(enable);	/* enable? */
+
+	submit = mgp->sram + 0xfc01c0;
+
+	myri10ge_pio_copy(submit, &buf, sizeof(buf));
+	for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++)
+		msleep(1);
+	if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA)
+		dev_err(&mgp->pdev->dev, "dummy rdma %s failed\n",
+			(enable ? "enable" : "disable"));
+}
+
+static int
+myri10ge_validate_firmware(struct myri10ge_priv *mgp,
+			   struct mcp_gen_header *hdr)
+{
+	struct device *dev = &mgp->pdev->dev;
+	int major, minor;
+
+	/* check firmware type */
+	if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) {
+		dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type));
+		return -EINVAL;
+	}
+
+	/* save firmware version for ethtool */
+	strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version));
+
+	sscanf(mgp->fw_version, "%d.%d", &major, &minor);
+
+	if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) {
+		dev_err(dev, "Found firmware version %s\n", mgp->fw_version);
+		dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR,
+			MXGEFW_VERSION_MINOR);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size)
+{
+	unsigned crc, reread_crc;
+	const struct firmware *fw;
+	struct device *dev = &mgp->pdev->dev;
+	struct mcp_gen_header *hdr;
+	size_t hdr_offset;
+	int status;
+
+	if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) {
+		dev_err(dev, "Unable to load %s firmware image via hotplug\n",
+			mgp->fw_name);
+		status = -EINVAL;
+		goto abort_with_nothing;
+	}
+
+	/* check size */
+
+	if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET ||
+	    fw->size < MCP_HEADER_PTR_OFFSET + 4) {
+		dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size);
+		status = -EINVAL;
+		goto abort_with_fw;
+	}
+
+	/* check id */
+	hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET));
+	if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) {
+		dev_err(dev, "Bad firmware file\n");
+		status = -EINVAL;
+		goto abort_with_fw;
+	}
+	hdr = (void *)(fw->data + hdr_offset);
+
+	status = myri10ge_validate_firmware(mgp, hdr);
+	if (status != 0)
+		goto abort_with_fw;
+
+	crc = crc32(~0, fw->data, fw->size);
+	if (mgp->tx.boundary == 2048) {
+		/* Avoid PCI burst on chipset with unaligned completions. */
+		int i;
+		__iomem u32 *ptr = (__iomem u32 *) (mgp->sram +
+						    MYRI10GE_FW_OFFSET);
+		for (i = 0; i < fw->size / 4; i++) {
+			__raw_writel(((u32 *) fw->data)[i], ptr + i);
+			wmb();
+		}
+	} else {
+		myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET, fw->data,
+				  fw->size);
+	}
+	/* corruption checking is good for parity recovery and buggy chipset */
+	memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size);
+	reread_crc = crc32(~0, fw->data, fw->size);
+	if (crc != reread_crc) {
+		dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n",
+			(unsigned)fw->size, reread_crc, crc);
+		status = -EIO;
+		goto abort_with_fw;
+	}
+	*size = (u32) fw->size;
+
+abort_with_fw:
+	release_firmware(fw);
+
+abort_with_nothing:
+	return status;
+}
+
+static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp)
+{
+	struct mcp_gen_header *hdr;
+	struct device *dev = &mgp->pdev->dev;
+	const size_t bytes = sizeof(struct mcp_gen_header);
+	size_t hdr_offset;
+	int status;
+
+	/* find running firmware header */
+	hdr_offset = ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET));
+
+	if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) {
+		dev_err(dev, "Running firmware has bad header offset (%d)\n",
+			(int)hdr_offset);
+		return -EIO;
+	}
+
+	/* copy header of running firmware from SRAM to host memory to
+	 * validate firmware */
+	hdr = kmalloc(bytes, GFP_KERNEL);
+	if (hdr == NULL) {
+		dev_err(dev, "could not malloc firmware hdr\n");
+		return -ENOMEM;
+	}
+	memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes);
+	status = myri10ge_validate_firmware(mgp, hdr);
+	kfree(hdr);
+	return status;
+}
+
+static int myri10ge_load_firmware(struct myri10ge_priv *mgp)
+{
+	char __iomem *submit;
+	u32 buf[16];
+	u32 dma_low, dma_high, size;
+	int status, i;
+
+	size = 0;
+	status = myri10ge_load_hotplug_firmware(mgp, &size);
+	if (status) {
+		dev_warn(&mgp->pdev->dev, "hotplug firmware loading failed\n");
+
+		/* Do not attempt to adopt firmware if there
+		 * was a bad crc */
+		if (status == -EIO)
+			return status;
+
+		status = myri10ge_adopt_running_firmware(mgp);
+		if (status != 0) {
+			dev_err(&mgp->pdev->dev,
+				"failed to adopt running firmware\n");
+			return status;
+		}
+		dev_info(&mgp->pdev->dev,
+			 "Successfully adopted running firmware\n");
+		if (mgp->tx.boundary == 4096) {
+			dev_warn(&mgp->pdev->dev,
+				 "Using firmware currently running on NIC"
+				 ".  For optimal\n");
+			dev_warn(&mgp->pdev->dev,
+				 "performance consider loading optimized "
+				 "firmware\n");
+			dev_warn(&mgp->pdev->dev, "via hotplug\n");
+		}
+
+		mgp->fw_name = "adopted";
+		mgp->tx.boundary = 2048;
+		return status;
+	}
+
+	/* clear confirmation addr */
+	mgp->cmd->data = 0;
+	mb();
+
+	/* send a reload command to the bootstrap MCP, and wait for the
+	 *  response in the confirmation address.  The firmware should
+	 * write a -1 there to indicate it is alive and well
+	 */
+	dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus);
+	dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus);
+
+	buf[0] = htonl(dma_high);	/* confirm addr MSW */
+	buf[1] = htonl(dma_low);	/* confirm addr LSW */
+	buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA);	/* confirm data */
+
+	/* FIX: All newest firmware should un-protect the bottom of
+	 * the sram before handoff. However, the very first interfaces
+	 * do not. Therefore the handoff copy must skip the first 8 bytes
+	 */
+	buf[3] = htonl(MYRI10GE_FW_OFFSET + 8);	/* where the code starts */
+	buf[4] = htonl(size - 8);	/* length of code */
+	buf[5] = htonl(8);	/* where to copy to */
+	buf[6] = htonl(0);	/* where to jump to */
+
+	submit = mgp->sram + 0xfc0000;
+
+	myri10ge_pio_copy(submit, &buf, sizeof(buf));
+	mb();
+	msleep(1);
+	mb();
+	i = 0;
+	while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20) {
+		msleep(1);
+		i++;
+	}
+	if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) {
+		dev_err(&mgp->pdev->dev, "handoff failed\n");
+		return -ENXIO;
+	}
+	dev_info(&mgp->pdev->dev, "handoff confirmed\n");
+	myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+
+	return 0;
+}
+
+static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr)
+{
+	struct myri10ge_cmd cmd;
+	int status;
+
+	cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
+		     | (addr[2] << 8) | addr[3]);
+
+	cmd.data1 = ((addr[4] << 8) | (addr[5]));
+
+	status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0);
+	return status;
+}
+
+static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause)
+{
+	struct myri10ge_cmd cmd;
+	int status, ctl;
+
+	ctl = pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL;
+	status = myri10ge_send_cmd(mgp, ctl, &cmd, 0);
+
+	if (status) {
+		printk(KERN_ERR
+		       "myri10ge: %s: Failed to set flow control mode\n",
+		       mgp->dev->name);
+		return status;
+	}
+	mgp->pause = pause;
+	return 0;
+}
+
+static void
+myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic)
+{
+	struct myri10ge_cmd cmd;
+	int status, ctl;
+
+	ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC;
+	status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic);
+	if (status)
+		printk(KERN_ERR "myri10ge: %s: Failed to set promisc mode\n",
+		       mgp->dev->name);
+}
+
+static int myri10ge_reset(struct myri10ge_priv *mgp)
+{
+	struct myri10ge_cmd cmd;
+	int status;
+	size_t bytes;
+	u32 len;
+
+	/* try to send a reset command to the card to see if it
+	 * is alive */
+	memset(&cmd, 0, sizeof(cmd));
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd, 0);
+	if (status != 0) {
+		dev_err(&mgp->pdev->dev, "failed reset\n");
+		return -ENXIO;
+	}
+
+	/* Now exchange information about interrupts  */
+
+	bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+	memset(mgp->rx_done.entry, 0, bytes);
+	cmd.data0 = (u32) bytes;
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0);
+	cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+	cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0);
+
+	status |=
+	    myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0);
+	mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0);
+	if (!mgp->msi_enabled) {
+		status |= myri10ge_send_cmd
+		    (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0);
+		mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0);
+
+	}
+	status |= myri10ge_send_cmd
+	    (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0);
+	mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0);
+	if (status != 0) {
+		dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n");
+		return status;
+	}
+	__raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+
+	/* Run a small DMA test.
+	 * The magic multipliers to the length tell the firmware
+	 * to do DMA read, write, or read+write tests.  The
+	 * results are returned in cmd.data0.  The upper 16
+	 * bits or the return is the number of transfers completed.
+	 * The lower 16 bits is the time in 0.5us ticks that the
+	 * transfers took to complete.
+	 */
+
+	len = mgp->tx.boundary;
+
+	cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+	cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+	cmd.data2 = len * 0x10000;
+	status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+	if (status == 0)
+		mgp->read_dma = ((cmd.data0 >> 16) * len * 2) /
+		    (cmd.data0 & 0xffff);
+	else
+		dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n",
+			 status);
+	cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+	cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+	cmd.data2 = len * 0x1;
+	status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+	if (status == 0)
+		mgp->write_dma = ((cmd.data0 >> 16) * len * 2) /
+		    (cmd.data0 & 0xffff);
+	else
+		dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n",
+			 status);
+
+	cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus);
+	cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus);
+	cmd.data2 = len * 0x10001;
+	status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0);
+	if (status == 0)
+		mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) /
+		    (cmd.data0 & 0xffff);
+	else
+		dev_warn(&mgp->pdev->dev,
+			 "DMA read/write benchmark failed: %d\n", status);
+
+	memset(mgp->rx_done.entry, 0, bytes);
+
+	/* reset mcp/driver shared state back to 0 */
+	mgp->tx.req = 0;
+	mgp->tx.done = 0;
+	mgp->tx.pkt_start = 0;
+	mgp->tx.pkt_done = 0;
+	mgp->rx_big.cnt = 0;
+	mgp->rx_small.cnt = 0;
+	mgp->rx_done.idx = 0;
+	mgp->rx_done.cnt = 0;
+	status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr);
+	myri10ge_change_promisc(mgp, 0, 0);
+	myri10ge_change_pause(mgp, mgp->pause);
+	return status;
+}
+
+static inline void
+myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
+		    struct mcp_kreq_ether_recv *src)
+{
+	u32 low;
+
+	low = src->addr_low;
+	src->addr_low = DMA_32BIT_MASK;
+	myri10ge_pio_copy(dst, src, 8 * sizeof(*src));
+	mb();
+	src->addr_low = low;
+	__raw_writel(low, &dst->addr_low);
+	mb();
+}
+
+/*
+ * Set of routines to get a new receive buffer.  Any buffer which
+ * crosses a 4KB boundary must start on a 4KB boundary due to PCIe
+ * wdma restrictions. We also try to align any smaller allocation to
+ * at least a 16 byte boundary for efficiency.  We assume the linux
+ * memory allocator works by powers of 2, and will not return memory
+ * smaller than 2KB which crosses a 4KB boundary.  If it does, we fall
+ * back to allocating 2x as much space as required.
+ *
+ * We intend to replace large (>4KB) skb allocations by using
+ * pages directly and building a fraglist in the near future.
+ */
+
+static inline struct sk_buff *myri10ge_alloc_big(int bytes)
+{
+	struct sk_buff *skb;
+	unsigned long data, roundup;
+
+	skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD);
+	if (skb == NULL)
+		return NULL;
+
+	/* Correct skb->truesize so that socket buffer
+	 * accounting is not confused the rounding we must
+	 * do to satisfy alignment constraints.
+	 */
+	skb->truesize -= 4096;
+
+	data = (unsigned long)(skb->data);
+	roundup = (-data) & (4095);
+	skb_reserve(skb, roundup);
+	return skb;
+}
+
+/* Allocate 2x as much space as required and use whichever portion
+ * does not cross a 4KB boundary */
+static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes)
+{
+	struct sk_buff *skb;
+	unsigned long data, boundary;
+
+	skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1);
+	if (unlikely(skb == NULL))
+		return NULL;
+
+	/* Correct skb->truesize so that socket buffer
+	 * accounting is not confused the rounding we must
+	 * do to satisfy alignment constraints.
+	 */
+	skb->truesize -= bytes + MXGEFW_PAD;
+
+	data = (unsigned long)(skb->data);
+	boundary = (data + 4095UL) & ~4095UL;
+	if ((boundary - data) >= (bytes + MXGEFW_PAD))
+		return skb;
+
+	skb_reserve(skb, boundary - data);
+	return skb;
+}
+
+/* Allocate just enough space, and verify that the allocated
+ * space does not cross a 4KB boundary */
+static inline struct sk_buff *myri10ge_alloc_small(int bytes)
+{
+	struct sk_buff *skb;
+	unsigned long roundup, data, end;
+
+	skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD);
+	if (unlikely(skb == NULL))
+		return NULL;
+
+	/* Round allocated buffer to 16 byte boundary */
+	data = (unsigned long)(skb->data);
+	roundup = (-data) & 15UL;
+	skb_reserve(skb, roundup);
+	/* Verify that the data buffer does not cross a page boundary */
+	data = (unsigned long)(skb->data);
+	end = data + bytes + MXGEFW_PAD - 1;
+	if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) {
+		printk(KERN_NOTICE
+		       "myri10ge_alloc_small: small skb crossed 4KB boundary\n");
+		myri10ge_skb_cross_4k = 1;
+		dev_kfree_skb_any(skb);
+		skb = myri10ge_alloc_small_safe(bytes);
+	}
+	return skb;
+}
+
+static inline int
+myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes,
+		int idx)
+{
+	struct sk_buff *skb;
+	dma_addr_t bus;
+	int len, retval = 0;
+
+	bytes += VLAN_HLEN;	/* account for 802.1q vlan tag */
+
+	if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ )
+		skb = myri10ge_alloc_big(bytes);
+	else if (myri10ge_skb_cross_4k)
+		skb = myri10ge_alloc_small_safe(bytes);
+	else
+		skb = myri10ge_alloc_small(bytes);
+
+	if (unlikely(skb == NULL)) {
+		rx->alloc_fail++;
+		retval = -ENOBUFS;
+		goto done;
+	}
+
+	/* set len so that it only covers the area we
+	 * need mapped for DMA */
+	len = bytes + MXGEFW_PAD;
+
+	bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE);
+	rx->info[idx].skb = skb;
+	pci_unmap_addr_set(&rx->info[idx], bus, bus);
+	pci_unmap_len_set(&rx->info[idx], len, len);
+	rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus));
+	rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
+
+done:
+	/* copy 8 descriptors (64-bytes) to the mcp at a time */
+	if ((idx & 7) == 7) {
+		if (rx->wc_fifo == NULL)
+			myri10ge_submit_8rx(&rx->lanai[idx - 7],
+					    &rx->shadow[idx - 7]);
+		else {
+			mb();
+			myri10ge_pio_copy(rx->wc_fifo,
+					  &rx->shadow[idx - 7], 64);
+		}
+	}
+	return retval;
+}
+
+static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum)
+{
+	struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data);
+
+	if ((skb->protocol == ntohs(ETH_P_8021Q)) &&
+	    (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) ||
+	     vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) {
+		skb->csum = hw_csum;
+		skb->ip_summed = CHECKSUM_HW;
+	}
+}
+
+static inline unsigned long
+myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
+		 int bytes, int len, int csum)
+{
+	dma_addr_t bus;
+	struct sk_buff *skb;
+	int idx, unmap_len;
+
+	idx = rx->cnt & rx->mask;
+	rx->cnt++;
+
+	/* save a pointer to the received skb */
+	skb = rx->info[idx].skb;
+	bus = pci_unmap_addr(&rx->info[idx], bus);
+	unmap_len = pci_unmap_len(&rx->info[idx], len);
+
+	/* try to replace the received skb */
+	if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) {
+		/* drop the frame -- the old skbuf is re-cycled */
+		mgp->stats.rx_dropped += 1;
+		return 0;
+	}
+
+	/* unmap the recvd skb */
+	pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE);
+
+	/* mcp implicitly skips 1st bytes so that packet is properly
+	 * aligned */
+	skb_reserve(skb, MXGEFW_PAD);
+
+	/* set the length of the frame */
+	skb_put(skb, len);
+
+	skb->protocol = eth_type_trans(skb, mgp->dev);
+	skb->dev = mgp->dev;
+	if (mgp->csum_flag) {
+		if ((skb->protocol == ntohs(ETH_P_IP)) ||
+		    (skb->protocol == ntohs(ETH_P_IPV6))) {
+			skb->csum = ntohs((u16) csum);
+			skb->ip_summed = CHECKSUM_HW;
+		} else
+			myri10ge_vlan_ip_csum(skb, ntohs((u16) csum));
+	}
+
+	netif_receive_skb(skb);
+	mgp->dev->last_rx = jiffies;
+	return 1;
+}
+
+static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index)
+{
+	struct pci_dev *pdev = mgp->pdev;
+	struct myri10ge_tx_buf *tx = &mgp->tx;
+	struct sk_buff *skb;
+	int idx, len;
+	int limit = 0;
+
+	while (tx->pkt_done != mcp_index) {
+		idx = tx->done & tx->mask;
+		skb = tx->info[idx].skb;
+
+		/* Mark as free */
+		tx->info[idx].skb = NULL;
+		if (tx->info[idx].last) {
+			tx->pkt_done++;
+			tx->info[idx].last = 0;
+		}
+		tx->done++;
+		len = pci_unmap_len(&tx->info[idx], len);
+		pci_unmap_len_set(&tx->info[idx], len, 0);
+		if (skb) {
+			mgp->stats.tx_bytes += skb->len;
+			mgp->stats.tx_packets++;
+			dev_kfree_skb_irq(skb);
+			if (len)
+				pci_unmap_single(pdev,
+						 pci_unmap_addr(&tx->info[idx],
+								bus), len,
+						 PCI_DMA_TODEVICE);
+		} else {
+			if (len)
+				pci_unmap_page(pdev,
+					       pci_unmap_addr(&tx->info[idx],
+							      bus), len,
+					       PCI_DMA_TODEVICE);
+		}
+
+		/* limit potential for livelock by only handling
+		 * 2 full tx rings per call */
+		if (unlikely(++limit > 2 * tx->mask))
+			break;
+	}
+	/* start the queue if we've stopped it */
+	if (netif_queue_stopped(mgp->dev)
+	    && tx->req - tx->done < (tx->mask >> 1)) {
+		mgp->wake_queue++;
+		netif_wake_queue(mgp->dev);
+	}
+}
+
+static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit)
+{
+	struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+	unsigned long rx_bytes = 0;
+	unsigned long rx_packets = 0;
+	unsigned long rx_ok;
+
+	int idx = rx_done->idx;
+	int cnt = rx_done->cnt;
+	u16 length;
+	u16 checksum;
+
+	while (rx_done->entry[idx].length != 0 && *limit != 0) {
+		length = ntohs(rx_done->entry[idx].length);
+		rx_done->entry[idx].length = 0;
+		checksum = ntohs(rx_done->entry[idx].checksum);
+		if (length <= mgp->small_bytes)
+			rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small,
+						 mgp->small_bytes,
+						 length, checksum);
+		else
+			rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big,
+						 mgp->dev->mtu + ETH_HLEN,
+						 length, checksum);
+		rx_packets += rx_ok;
+		rx_bytes += rx_ok * (unsigned long)length;
+		cnt++;
+		idx = cnt & (myri10ge_max_intr_slots - 1);
+
+		/* limit potential for livelock by only handling a
+		 * limited number of frames. */
+		(*limit)--;
+	}
+	rx_done->idx = idx;
+	rx_done->cnt = cnt;
+	mgp->stats.rx_packets += rx_packets;
+	mgp->stats.rx_bytes += rx_bytes;
+}
+
+static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp)
+{
+	struct mcp_irq_data *stats = mgp->fw_stats;
+
+	if (unlikely(stats->stats_updated)) {
+		if (mgp->link_state != stats->link_up) {
+			mgp->link_state = stats->link_up;
+			if (mgp->link_state) {
+				printk(KERN_INFO "myri10ge: %s: link up\n",
+				       mgp->dev->name);
+				netif_carrier_on(mgp->dev);
+			} else {
+				printk(KERN_INFO "myri10ge: %s: link down\n",
+				       mgp->dev->name);
+				netif_carrier_off(mgp->dev);
+			}
+		}
+		if (mgp->rdma_tags_available !=
+		    ntohl(mgp->fw_stats->rdma_tags_available)) {
+			mgp->rdma_tags_available =
+			    ntohl(mgp->fw_stats->rdma_tags_available);
+			printk(KERN_WARNING "myri10ge: %s: RDMA timed out! "
+			       "%d tags left\n", mgp->dev->name,
+			       mgp->rdma_tags_available);
+		}
+		mgp->down_cnt += stats->link_down;
+		if (stats->link_down)
+			wake_up(&mgp->down_wq);
+	}
+}
+
+static int myri10ge_poll(struct net_device *netdev, int *budget)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	struct myri10ge_rx_done *rx_done = &mgp->rx_done;
+	int limit, orig_limit, work_done;
+
+	/* process as many rx events as NAPI will allow */
+	limit = min(*budget, netdev->quota);
+	orig_limit = limit;
+	myri10ge_clean_rx_done(mgp, &limit);
+	work_done = orig_limit - limit;
+	*budget -= work_done;
+	netdev->quota -= work_done;
+
+	if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) {
+		netif_rx_complete(netdev);
+		__raw_writel(htonl(3), mgp->irq_claim);
+		return 0;
+	}
+	return 1;
+}
+
+static irqreturn_t myri10ge_intr(int irq, void *arg, struct pt_regs *regs)
+{
+	struct myri10ge_priv *mgp = arg;
+	struct mcp_irq_data *stats = mgp->fw_stats;
+	struct myri10ge_tx_buf *tx = &mgp->tx;
+	u32 send_done_count;
+	int i;
+
+	/* make sure it is our IRQ, and that the DMA has finished */
+	if (unlikely(!stats->valid))
+		return (IRQ_NONE);
+
+	/* low bit indicates receives are present, so schedule
+	 * napi poll handler */
+	if (stats->valid & 1)
+		netif_rx_schedule(mgp->dev);
+
+	if (!mgp->msi_enabled) {
+		__raw_writel(0, mgp->irq_deassert);
+		if (!myri10ge_deassert_wait)
+			stats->valid = 0;
+		mb();
+	} else
+		stats->valid = 0;
+
+	/* Wait for IRQ line to go low, if using INTx */
+	i = 0;
+	while (1) {
+		i++;
+		/* check for transmit completes and receives */
+		send_done_count = ntohl(stats->send_done_count);
+		if (send_done_count != tx->pkt_done)
+			myri10ge_tx_done(mgp, (int)send_done_count);
+		if (unlikely(i > myri10ge_max_irq_loops)) {
+			printk(KERN_WARNING "myri10ge: %s: irq stuck?\n",
+			       mgp->dev->name);
+			stats->valid = 0;
+			schedule_work(&mgp->watchdog_work);
+		}
+		if (likely(stats->valid == 0))
+			break;
+		cpu_relax();
+		barrier();
+	}
+
+	myri10ge_check_statblock(mgp);
+
+	__raw_writel(htonl(3), mgp->irq_claim + 1);
+	return (IRQ_HANDLED);
+}
+
+static int
+myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	cmd->autoneg = AUTONEG_DISABLE;
+	cmd->speed = SPEED_10000;
+	cmd->duplex = DUPLEX_FULL;
+	return 0;
+}
+
+static void
+myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	strlcpy(info->driver, "myri10ge", sizeof(info->driver));
+	strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
+	strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
+	strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
+}
+
+static int
+myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	coal->rx_coalesce_usecs = mgp->intr_coal_delay;
+	return 0;
+}
+
+static int
+myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	mgp->intr_coal_delay = coal->rx_coalesce_usecs;
+	__raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr);
+	return 0;
+}
+
+static void
+myri10ge_get_pauseparam(struct net_device *netdev,
+			struct ethtool_pauseparam *pause)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	pause->autoneg = 0;
+	pause->rx_pause = mgp->pause;
+	pause->tx_pause = mgp->pause;
+}
+
+static int
+myri10ge_set_pauseparam(struct net_device *netdev,
+			struct ethtool_pauseparam *pause)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	if (pause->tx_pause != mgp->pause)
+		return myri10ge_change_pause(mgp, pause->tx_pause);
+	if (pause->rx_pause != mgp->pause)
+		return myri10ge_change_pause(mgp, pause->tx_pause);
+	if (pause->autoneg != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static void
+myri10ge_get_ringparam(struct net_device *netdev,
+		       struct ethtool_ringparam *ring)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+
+	ring->rx_mini_max_pending = mgp->rx_small.mask + 1;
+	ring->rx_max_pending = mgp->rx_big.mask + 1;
+	ring->rx_jumbo_max_pending = 0;
+	ring->tx_max_pending = mgp->rx_small.mask + 1;
+	ring->rx_mini_pending = ring->rx_mini_max_pending;
+	ring->rx_pending = ring->rx_max_pending;
+	ring->rx_jumbo_pending = ring->rx_jumbo_max_pending;
+	ring->tx_pending = ring->tx_max_pending;
+}
+
+static u32 myri10ge_get_rx_csum(struct net_device *netdev)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	if (mgp->csum_flag)
+		return 1;
+	else
+		return 0;
+}
+
+static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	if (csum_enabled)
+		mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
+	else
+		mgp->csum_flag = 0;
+	return 0;
+}
+
+static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
+	"tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
+	"rx_length_errors", "rx_over_errors", "rx_crc_errors",
+	"rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
+	"tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
+	"tx_heartbeat_errors", "tx_window_errors",
+	/* device-specific stats */
+	"read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs",
+	"serial_number", "tx_pkt_start", "tx_pkt_done",
+	"tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt",
+	"wake_queue", "stop_queue", "watchdog_resets", "tx_linearized",
+	"link_up", "dropped_link_overflow", "dropped_link_error_or_filtered",
+	"dropped_runt", "dropped_overrun", "dropped_no_small_buffer",
+	"dropped_no_big_buffer"
+};
+
+#define MYRI10GE_NET_STATS_LEN      21
+#define MYRI10GE_STATS_LEN  sizeof(myri10ge_gstrings_stats) / ETH_GSTRING_LEN
+
+static void
+myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, *myri10ge_gstrings_stats,
+		       sizeof(myri10ge_gstrings_stats));
+		break;
+	}
+}
+
+static int myri10ge_get_stats_count(struct net_device *netdev)
+{
+	return MYRI10GE_STATS_LEN;
+}
+
+static void
+myri10ge_get_ethtool_stats(struct net_device *netdev,
+			   struct ethtool_stats *stats, u64 * data)
+{
+	struct myri10ge_priv *mgp = netdev_priv(netdev);
+	int i;
+
+	for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++)
+		data[i] = ((unsigned long *)&mgp->stats)[i];
+
+	data[i++] = (unsigned int)mgp->read_dma;
+	data[i++] = (unsigned int)mgp->write_dma;
+	data[i++] = (unsigned int)mgp->read_write_dma;
+	data[i++] = (unsigned int)mgp->serial_number;
+	data[i++] = (unsigned int)mgp->tx.pkt_start;
+	data[i++] = (unsigned int)mgp->tx.pkt_done;
+	data[i++] = (unsigned int)mgp->tx.req;
+	data[i++] = (unsigned int)mgp->tx.done;
+	data[i++] = (unsigned int)mgp->rx_small.cnt;
+	data[i++] = (unsigned int)mgp->rx_big.cnt;
+	data[i++] = (unsigned int)mgp->wake_queue;
+	data[i++] = (unsigned int)mgp->stop_queue;
+	data[i++] = (unsigned int)mgp->watchdog_resets;
+	data[i++] = (unsigned int)mgp->tx_linearized;
+	data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up);
+	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow);
+	data[i++] =
+	    (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered);
+	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt);
+	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun);
+	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer);
+	data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer);
+}
+
+static struct ethtool_ops myri10ge_ethtool_ops = {
+	.get_settings = myri10ge_get_settings,
+	.get_drvinfo = myri10ge_get_drvinfo,
+	.get_coalesce = myri10ge_get_coalesce,
+	.set_coalesce = myri10ge_set_coalesce,
+	.get_pauseparam = myri10ge_get_pauseparam,
+	.set_pauseparam = myri10ge_set_pauseparam,
+	.get_ringparam = myri10ge_get_ringparam,
+	.get_rx_csum = myri10ge_get_rx_csum,
+	.set_rx_csum = myri10ge_set_rx_csum,
+	.get_tx_csum = ethtool_op_get_tx_csum,
+	.set_tx_csum = ethtool_op_set_tx_hw_csum,
+	.get_sg = ethtool_op_get_sg,
+	.set_sg = ethtool_op_set_sg,
+#ifdef NETIF_F_TSO
+	.get_tso = ethtool_op_get_tso,
+	.set_tso = ethtool_op_set_tso,
+#endif
+	.get_strings = myri10ge_get_strings,
+	.get_stats_count = myri10ge_get_stats_count,
+	.get_ethtool_stats = myri10ge_get_ethtool_stats
+};
+
+static int myri10ge_allocate_rings(struct net_device *dev)
+{
+	struct myri10ge_priv *mgp;
+	struct myri10ge_cmd cmd;
+	int tx_ring_size, rx_ring_size;
+	int tx_ring_entries, rx_ring_entries;
+	int i, status;
+	size_t bytes;
+
+	mgp = netdev_priv(dev);
+
+	/* get ring sizes */
+
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0);
+	tx_ring_size = cmd.data0;
+	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0);
+	rx_ring_size = cmd.data0;
+
+	tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send);
+	rx_ring_entries = rx_ring_size / sizeof(struct mcp_dma_addr);
+	mgp->tx.mask = tx_ring_entries - 1;
+	mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1;
+
+	/* allocate the host shadow rings */
+
+	bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4)
+	    * sizeof(*mgp->tx.req_list);
+	mgp->tx.req_bytes = kzalloc(bytes, GFP_KERNEL);
+	if (mgp->tx.req_bytes == NULL)
+		goto abort_with_nothing;
+
+	/* ensure req_list entries are aligned to 8 bytes */
+	mgp->tx.req_list = (struct mcp_kreq_ether_send *)
+	    ALIGN((unsigned long)mgp->tx.req_bytes, 8);
+
+	bytes = rx_ring_entries * sizeof(*mgp->rx_small.shadow);
+	mgp->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);
+	if (mgp->rx_small.shadow == NULL)
+		goto abort_with_tx_req_bytes;
+
+	bytes = rx_ring_entries * sizeof(*mgp->rx_big.shadow);
+	mgp->rx_big.shadow = kzalloc(bytes, GFP_KERNEL);
+	if (mgp->rx_big.shadow == NULL)
+		goto abort_with_rx_small_shadow;
+
+	/* allocate the host info rings */
+
+	bytes = tx_ring_entries * sizeof(*mgp->tx.info);
+	mgp->tx.info = kzalloc(bytes, GFP_KERNEL);
+	if (mgp->tx.info == NULL)
+		goto abort_with_rx_big_shadow;
+
+	bytes = rx_ring_entries * sizeof(*mgp->rx_small.info);
+	mgp->rx_small.info = kzalloc(bytes, GFP_KERNEL);
+	if (mgp->rx_small.info == NULL)
+		goto abort_with_tx_info;
+
+	bytes = rx_ring_entries * sizeof(*mgp->rx_big.info);
+	mgp->rx_big.info = kzalloc(bytes, GFP_KERNEL);
+	if (mgp->rx_big.info == NULL)
+		goto abort_with_rx_small_info;
+
+	/* Fill the receive rings */
+
+	for (i = 0; i <= mgp->rx_small.mask; i++) {
+		status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev,
+					 mgp->small_bytes, i);
+		if (status) {
+			printk(KERN_ERR
+			       "myri10ge: %s: alloced only %d small bufs\n",
+			       dev->name, i);
+			goto abort_with_rx_small_ring;
+		}
+	}
+
+	for (i = 0; i <= mgp->rx_big.mask; i++) {
+		status =
+		    myri10ge_getbuf(&mgp->rx_big, mgp->pdev,
+				    dev->mtu + ETH_HLEN, i);
+		if (status) {
+			printk(KERN_ERR
+			       "myri10ge: %s: alloced only %d big bufs\n",
+			       dev->name, i);
+			goto abort_with_rx_big_ring;
+		}
+	}
+
+	return 0;
+
+abort_with_rx_big_ring:
+	for (i = 0; i <= mgp->rx_big.mask; i++) {
+		if (mgp->rx_big.info[i].skb != NULL)
+			dev_kfree_skb_any(mgp->rx_big.info[i].skb);
+		if (pci_unmap_len(&mgp->rx_big.info[i], len))
+			pci_unmap_single(mgp->pdev,
+					 pci_unmap_addr(&mgp->rx_big.info[i],
+							bus),
+					 pci_unmap_len(&mgp->rx_big.info[i],
+						       len),
+					 PCI_DMA_FROMDEVICE);
+	}
+
+abort_with_rx_small_ring:
+	for (i = 0; i <= mgp->rx_small.mask; i++) {
+		if (mgp->rx_small.info[i].skb != NULL)
+			dev_kfree_skb_any(mgp->rx_small.info[i].skb);
+		if (pci_unmap_len(&mgp->rx_small.info[i], len))
+			pci_unmap_single(mgp->pdev,
+					 pci_unmap_addr(&mgp->rx_small.info[i],
+							bus),
+					 pci_unmap_len(&mgp->rx_small.info[i],
+						       len),
+					 PCI_DMA_FROMDEVICE);
+	}
+	kfree(mgp->rx_big.info);
+
+abort_with_rx_small_info:
+	kfree(mgp->rx_small.info);
+
+abort_with_tx_info:
+	kfree(mgp->tx.info);
+
+abort_with_rx_big_shadow:
+	kfree(mgp->rx_big.shadow);
+
+abort_with_rx_small_shadow:
+	kfree(mgp->rx_small.shadow);
+
+abort_with_tx_req_bytes:
+	kfree(mgp->tx.req_bytes);
+	mgp->tx.req_bytes = NULL;
+	mgp->tx.req_list = NULL;
+
+abort_with_nothing:
+	return status;
+}
+
+static void myri10ge_free_rings(struct net_device *dev)
+{
+	struct myri10ge_priv *mgp;
+	struct sk_buff *skb;
+	struct myri10ge_tx_buf *tx;
+	int i, len, idx;
+
+	mgp = netdev_priv(dev);
+
+	for (i = 0; i <= mgp->rx_big.mask; i++) {
+		if (mgp->rx_big.info[i].skb != NULL)
+			dev_kfree_skb_any(mgp->rx_big.info[i].skb);
+		if (pci_unmap_len(&mgp->rx_big.info[i], len))
+			pci_unmap_single(mgp->pdev,
+					 pci_unmap_addr(&mgp->rx_big.info[i],
+							bus),
+					 pci_unmap_len(&mgp->rx_big.info[i],
+						       len),
+					 PCI_DMA_FROMDEVICE);
+	}
+
+	for (i = 0; i <= mgp->rx_small.mask; i++) {
+		if (mgp->rx_small.info[i].skb != NULL)
+			dev_kfree_skb_any(mgp->rx_small.info[i].skb);
+		if (pci_unmap_len(&mgp->rx_small.info[i], len))
+			pci_unmap_single(mgp->pdev,
+					 pci_unmap_addr(&mgp->rx_small.info[i],
+							bus),
+					 pci_unmap_len(&mgp->rx_small.info[i],
+						       len),
+					 PCI_DMA_FROMDEVICE);
+	}
+
+	tx = &mgp->tx;
+	while (tx->done != tx->req) {
+		idx = tx->done & tx->mask;
+		skb = tx->info[idx].skb;
+
+		/* Mark as free */
+		tx->info[idx].skb = NULL;
+		tx->done++;
+		len = pci_unmap_len(&tx->info[idx], len);
+		pci_unmap_len_set(&tx->info[idx], len, 0);
+		if (skb) {
+			mgp->stats.tx_dropped++;
+			dev_kfree_skb_any(skb);
+			if (len)
+				pci_unmap_single(mgp->pdev,
+						 pci_unmap_addr(&tx->info[idx],
+								bus), len,
+						 PCI_DMA_TODEVICE);
+		} else {
+			if (len)
+				pci_unmap_page(mgp->pdev,
+					       pci_unmap_addr(&tx->info[idx],
+							      bus), len,
+					       PCI_DMA_TODEVICE);
+		}
+	}
+	kfree(mgp->rx_big.info);
+
+	kfree(mgp->rx_small.info);
+
+	kfree(mgp->tx.info);
+
+	kfree(mgp->rx_big.shadow);
+
+	kfree(mgp->rx_small.shadow);
+
+	kfree(mgp->tx.req_bytes);
+	mgp->tx.req_bytes = NULL;
+	mgp->tx.req_list = NULL;
+}
+
+static int myri10ge_open(struct net_device *dev)
+{
+	struct myri10ge_priv *mgp;
+	struct myri10ge_cmd cmd;
+	int status, big_pow2;
+
+	mgp = netdev_priv(dev);
+
+	if (mgp->running != MYRI10GE_ETH_STOPPED)
+		return -EBUSY;
+
+	mgp->running = MYRI10GE_ETH_STARTING;
+	status = myri10ge_reset(mgp);
+	if (status != 0) {
+		printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name);
+		mgp->running = MYRI10GE_ETH_STOPPED;
+		return -ENXIO;
+	}
+
+	/* decide what small buffer size to use.  For good TCP rx
+	 * performance, it is important to not receive 1514 byte
+	 * frames into jumbo buffers, as it confuses the socket buffer
+	 * accounting code, leading to drops and erratic performance.
+	 */
+
+	if (dev->mtu <= ETH_DATA_LEN)
+		mgp->small_bytes = 128;	/* enough for a TCP header */
+	else
+		mgp->small_bytes = ETH_FRAME_LEN;	/* enough for an ETH_DATA_LEN frame */
+
+	/* Override the small buffer size? */
+	if (myri10ge_small_bytes > 0)
+		mgp->small_bytes = myri10ge_small_bytes;
+
+	/* If the user sets an obscenely small MTU, adjust the small
+	 * bytes down to nearly nothing */
+	if (mgp->small_bytes >= (dev->mtu + ETH_HLEN))
+		mgp->small_bytes = 64;
+
+	/* get the lanai pointers to the send and receive rings */
+
+	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
+	mgp->tx.lanai =
+	    (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0);
+
+	status |=
+	    myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0);
+	mgp->rx_small.lanai =
+	    (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+	status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0);
+	mgp->rx_big.lanai =
+	    (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0);
+
+	if (status != 0) {
+		printk(KERN_ERR
+		       "myri10ge: %s: failed to get ring sizes or locations\n",
+		       dev->name);
+		mgp->running = MYRI10GE_ETH_STOPPED;
+		return -ENXIO;
+	}
+
+	if (mgp->mtrr >= 0) {
+		mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000;
+		mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000;
+		mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000;
+	} else {
+		mgp->tx.wc_fifo = NULL;
+		mgp->rx_small.wc_fifo = NULL;
+		mgp->rx_big.wc_fifo = NULL;
+	}
+
+	status = myri10ge_allocate_rings(dev);
+	if (status != 0)
+		goto abort_with_nothing;
+
+	/* Firmware needs the big buff size as a power of 2.  Lie and
+	 * tell him the buffer is larger, because we only use 1
+	 * buffer/pkt, and the mtu will prevent overruns.
+	 */
+	big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD;
+	while ((big_pow2 & (big_pow2 - 1)) != 0)
+		big_pow2++;
+
+	/* now give firmware buffers sizes, and MTU */
+	cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN;
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0);
+	cmd.data0 = mgp->small_bytes;
+	status |=
+	    myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd, 0);
+	cmd.data0 = big_pow2;
+	status |=
+	    myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd, 0);
+	if (status) {
+		printk(KERN_ERR "myri10ge: %s: Couldn't set buffer sizes\n",
+		       dev->name);
+		goto abort_with_rings;
+	}
+
+	cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus);
+	cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus);
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0);
+	if (status) {
+		printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n",
+		       dev->name);
+		goto abort_with_rings;
+	}
+
+	mgp->link_state = -1;
+	mgp->rdma_tags_available = 15;
+
+	netif_poll_enable(mgp->dev);	/* must happen prior to any irq */
+
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0);
+	if (status) {
+		printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n",
+		       dev->name);
+		goto abort_with_rings;
+	}
+
+	mgp->wake_queue = 0;
+	mgp->stop_queue = 0;
+	mgp->running = MYRI10GE_ETH_RUNNING;
+	mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
+	add_timer(&mgp->watchdog_timer);
+	netif_wake_queue(dev);
+	return 0;
+
+abort_with_rings:
+	myri10ge_free_rings(dev);
+
+abort_with_nothing:
+	mgp->running = MYRI10GE_ETH_STOPPED;
+	return -ENOMEM;
+}
+
+static int myri10ge_close(struct net_device *dev)
+{
+	struct myri10ge_priv *mgp;
+	struct myri10ge_cmd cmd;
+	int status, old_down_cnt;
+
+	mgp = netdev_priv(dev);
+
+	if (mgp->running != MYRI10GE_ETH_RUNNING)
+		return 0;
+
+	if (mgp->tx.req_bytes == NULL)
+		return 0;
+
+	del_timer_sync(&mgp->watchdog_timer);
+	mgp->running = MYRI10GE_ETH_STOPPING;
+	netif_poll_disable(mgp->dev);
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+	old_down_cnt = mgp->down_cnt;
+	mb();
+	status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
+	if (status)
+		printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n",
+		       dev->name);
+
+	wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ);
+	if (old_down_cnt == mgp->down_cnt)
+		printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name);
+
+	netif_tx_disable(dev);
+
+	myri10ge_free_rings(dev);
+
+	mgp->running = MYRI10GE_ETH_STOPPED;
+	return 0;
+}
+
+/* copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * backwards one at a time and handle ring wraps */
+
+static inline void
+myri10ge_submit_req_backwards(struct myri10ge_tx_buf *tx,
+			      struct mcp_kreq_ether_send *src, int cnt)
+{
+	int idx, starting_slot;
+	starting_slot = tx->req;
+	while (cnt > 1) {
+		cnt--;
+		idx = (starting_slot + cnt) & tx->mask;
+		myri10ge_pio_copy(&tx->lanai[idx], &src[cnt], sizeof(*src));
+		mb();
+	}
+}
+
+/*
+ * copy an array of struct mcp_kreq_ether_send's to the mcp.  Copy
+ * at most 32 bytes at a time, so as to avoid involving the software
+ * pio handler in the nic.   We re-write the first segment's flags
+ * to mark them valid only after writing the entire chain.
+ */
+
+static inline void
+myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src,
+		    int cnt)
+{
+	int idx, i;
+	struct mcp_kreq_ether_send __iomem *dstp, *dst;
+	struct mcp_kreq_ether_send *srcp;
+	u8 last_flags;
+
+	idx = tx->req & tx->mask;
+
+	last_flags = src->flags;
+	src->flags = 0;
+	mb();
+	dst = dstp = &tx->lanai[idx];
+	srcp = src;
+
+	if ((idx + cnt) < tx->mask) {
+		for (i = 0; i < (cnt - 1); i += 2) {
+			myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src));
+			mb();	/* force write every 32 bytes */
+			srcp += 2;
+			dstp += 2;
+		}
+	} else {
+		/* submit all but the first request, and ensure
+		 * that it is submitted below */
+		myri10ge_submit_req_backwards(tx, src, cnt);
+		i = 0;
+	}
+	if (i < cnt) {
+		/* submit the first request */
+		myri10ge_pio_copy(dstp, srcp, sizeof(*src));
+		mb();		/* barrier before setting valid flag */
+	}
+
+	/* re-write the last 32-bits with the valid flags */
+	src->flags = last_flags;
+	__raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3);
+	tx->req += cnt;
+	mb();
+}
+
+static inline void
+myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx,
+		       struct mcp_kreq_ether_send *src, int cnt)
+{
+	tx->req += cnt;
+	mb();
+	while (cnt >= 4) {
+		myri10ge_pio_copy(tx->wc_fifo, src, 64);
+		mb();
+		src += 4;
+		cnt -= 4;
+	}
+	if (cnt > 0) {
+		/* pad it to 64 bytes.  The src is 64 bytes bigger than it
+		 * needs to be so that we don't overrun it */
+		myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64);
+		mb();
+	}
+}
+
+/*
+ * Transmit a packet.  We need to split the packet so that a single
+ * segment does not cross myri10ge->tx.boundary, so this makes segment
+ * counting tricky.  So rather than try to count segments up front, we
+ * just give up if there are too few segments to hold a reasonably
+ * fragmented packet currently available.  If we run
+ * out of segments while preparing a packet for DMA, we just linearize
+ * it and try again.
+ */
+
+static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct myri10ge_priv *mgp = netdev_priv(dev);
+	struct mcp_kreq_ether_send *req;
+	struct myri10ge_tx_buf *tx = &mgp->tx;
+	struct skb_frag_struct *frag;
+	dma_addr_t bus;
+	u32 low, high_swapped;
+	unsigned int len;
+	int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
+	u16 pseudo_hdr_offset, cksum_offset;
+	int cum_len, seglen, boundary, rdma_count;
+	u8 flags, odd_flag;
+
+again:
+	req = tx->req_list;
+	avail = tx->mask - 1 - (tx->req - tx->done);
+
+	mss = 0;
+	max_segments = MXGEFW_MAX_SEND_DESC;
+
+#ifdef NETIF_F_TSO
+	if (skb->len > (dev->mtu + ETH_HLEN)) {
+		mss = skb_shinfo(skb)->gso_size;
+		if (mss != 0)
+			max_segments = MYRI10GE_MAX_SEND_DESC_TSO;
+	}
+#endif				/*NETIF_F_TSO */
+
+	if ((unlikely(avail < max_segments))) {
+		/* we are out of transmit resources */
+		mgp->stop_queue++;
+		netif_stop_queue(dev);
+		return 1;
+	}
+
+	/* Setup checksum offloading, if needed */
+	cksum_offset = 0;
+	pseudo_hdr_offset = 0;
+	odd_flag = 0;
+	flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST);
+	if (likely(skb->ip_summed == CHECKSUM_HW)) {
+		cksum_offset = (skb->h.raw - skb->data);
+		pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data;
+		/* If the headers are excessively large, then we must
+		 * fall back to a software checksum */
+		if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) {
+			if (skb_checksum_help(skb, 0))
+				goto drop;
+			cksum_offset = 0;
+			pseudo_hdr_offset = 0;
+		} else {
+			pseudo_hdr_offset = htons(pseudo_hdr_offset);
+			odd_flag = MXGEFW_FLAGS_ALIGN_ODD;
+			flags |= MXGEFW_FLAGS_CKSUM;
+		}
+	}
+
+	cum_len = 0;
+
+#ifdef NETIF_F_TSO
+	if (mss) {		/* TSO */
+		/* this removes any CKSUM flag from before */
+		flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST);
+
+		/* negative cum_len signifies to the
+		 * send loop that we are still in the
+		 * header portion of the TSO packet.
+		 * TSO header must be at most 134 bytes long */
+		cum_len = -((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+
+		/* for TSO, pseudo_hdr_offset holds mss.
+		 * The firmware figures out where to put
+		 * the checksum by parsing the header. */
+		pseudo_hdr_offset = htons(mss);
+	} else
+#endif				/*NETIF_F_TSO */
+		/* Mark small packets, and pad out tiny packets */
+	if (skb->len <= MXGEFW_SEND_SMALL_SIZE) {
+		flags |= MXGEFW_FLAGS_SMALL;
+
+		/* pad frames to at least ETH_ZLEN bytes */
+		if (unlikely(skb->len < ETH_ZLEN)) {
+			if (skb_padto(skb, ETH_ZLEN)) {
+				/* The packet is gone, so we must
+				 * return 0 */
+				mgp->stats.tx_dropped += 1;
+				return 0;
+			}
+			/* adjust the len to account for the zero pad
+			 * so that the nic can know how long it is */
+			skb->len = ETH_ZLEN;
+		}
+	}
+
+	/* map the skb for DMA */
+	len = skb->len - skb->data_len;
+	idx = tx->req & tx->mask;
+	tx->info[idx].skb = skb;
+	bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	pci_unmap_addr_set(&tx->info[idx], bus, bus);
+	pci_unmap_len_set(&tx->info[idx], len, len);
+
+	frag_cnt = skb_shinfo(skb)->nr_frags;
+	frag_idx = 0;
+	count = 0;
+	rdma_count = 0;
+
+	/* "rdma_count" is the number of RDMAs belonging to the
+	 * current packet BEFORE the current send request. For
+	 * non-TSO packets, this is equal to "count".
+	 * For TSO packets, rdma_count needs to be reset
+	 * to 0 after a segment cut.
+	 *
+	 * The rdma_count field of the send request is
+	 * the number of RDMAs of the packet starting at
+	 * that request. For TSO send requests with one ore more cuts
+	 * in the middle, this is the number of RDMAs starting
+	 * after the last cut in the request. All previous
+	 * segments before the last cut implicitly have 1 RDMA.
+	 *
+	 * Since the number of RDMAs is not known beforehand,
+	 * it must be filled-in retroactively - after each
+	 * segmentation cut or at the end of the entire packet.
+	 */
+
+	while (1) {
+		/* Break the SKB or Fragment up into pieces which
+		 * do not cross mgp->tx.boundary */
+		low = MYRI10GE_LOWPART_TO_U32(bus);
+		high_swapped = htonl(MYRI10GE_HIGHPART_TO_U32(bus));
+		while (len) {
+			u8 flags_next;
+			int cum_len_next;
+
+			if (unlikely(count == max_segments))
+				goto abort_linearize;
+
+			boundary = (low + tx->boundary) & ~(tx->boundary - 1);
+			seglen = boundary - low;
+			if (seglen > len)
+				seglen = len;
+			flags_next = flags & ~MXGEFW_FLAGS_FIRST;
+			cum_len_next = cum_len + seglen;
+#ifdef NETIF_F_TSO
+			if (mss) {	/* TSO */
+				(req - rdma_count)->rdma_count = rdma_count + 1;
+
+				if (likely(cum_len >= 0)) {	/* payload */
+					int next_is_first, chop;
+
+					chop = (cum_len_next > mss);
+					cum_len_next = cum_len_next % mss;
+					next_is_first = (cum_len_next == 0);
+					flags |= chop * MXGEFW_FLAGS_TSO_CHOP;
+					flags_next |= next_is_first *
+					    MXGEFW_FLAGS_FIRST;
+					rdma_count |= -(chop | next_is_first);
+					rdma_count += chop & !next_is_first;
+				} else if (likely(cum_len_next >= 0)) {	/* header ends */
+					int small;
+
+					rdma_count = -1;
+					cum_len_next = 0;
+					seglen = -cum_len;
+					small = (mss <= MXGEFW_SEND_SMALL_SIZE);
+					flags_next = MXGEFW_FLAGS_TSO_PLD |
+					    MXGEFW_FLAGS_FIRST |
+					    (small * MXGEFW_FLAGS_SMALL);
+				}
+			}
+#endif				/* NETIF_F_TSO */
+			req->addr_high = high_swapped;
+			req->addr_low = htonl(low);
+			req->pseudo_hdr_offset = pseudo_hdr_offset;
+			req->pad = 0;	/* complete solid 16-byte block; does this matter? */
+			req->rdma_count = 1;
+			req->length = htons(seglen);
+			req->cksum_offset = cksum_offset;
+			req->flags = flags | ((cum_len & 1) * odd_flag);
+
+			low += seglen;
+			len -= seglen;
+			cum_len = cum_len_next;
+			flags = flags_next;
+			req++;
+			count++;
+			rdma_count++;
+			if (unlikely(cksum_offset > seglen))
+				cksum_offset -= seglen;
+			else
+				cksum_offset = 0;
+		}
+		if (frag_idx == frag_cnt)
+			break;
+
+		/* map next fragment for DMA */
+		idx = (count + tx->req) & tx->mask;
+		frag = &skb_shinfo(skb)->frags[frag_idx];
+		frag_idx++;
+		len = frag->size;
+		bus = pci_map_page(mgp->pdev, frag->page, frag->page_offset,
+				   len, PCI_DMA_TODEVICE);
+		pci_unmap_addr_set(&tx->info[idx], bus, bus);
+		pci_unmap_len_set(&tx->info[idx], len, len);
+	}
+
+	(req - rdma_count)->rdma_count = rdma_count;
+#ifdef NETIF_F_TSO
+	if (mss)
+		do {
+			req--;
+			req->flags |= MXGEFW_FLAGS_TSO_LAST;
+		} while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP |
+					 MXGEFW_FLAGS_FIRST)));
+#endif
+	idx = ((count - 1) + tx->req) & tx->mask;
+	tx->info[idx].last = 1;
+	if (tx->wc_fifo == NULL)
+		myri10ge_submit_req(tx, tx->req_list, count);
+	else
+		myri10ge_submit_req_wc(tx, tx->req_list, count);
+	tx->pkt_start++;
+	if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
+		mgp->stop_queue++;
+		netif_stop_queue(dev);
+	}
+	dev->trans_start = jiffies;
+	return 0;
+
+abort_linearize:
+	/* Free any DMA resources we've alloced and clear out the skb
+	 * slot so as to not trip up assertions, and to avoid a
+	 * double-free if linearizing fails */
+
+	last_idx = (idx + 1) & tx->mask;
+	idx = tx->req & tx->mask;
+	tx->info[idx].skb = NULL;
+	do {
+		len = pci_unmap_len(&tx->info[idx], len);
+		if (len) {
+			if (tx->info[idx].skb != NULL)
+				pci_unmap_single(mgp->pdev,
+						 pci_unmap_addr(&tx->info[idx],
+								bus), len,
+						 PCI_DMA_TODEVICE);
+			else
+				pci_unmap_page(mgp->pdev,
+					       pci_unmap_addr(&tx->info[idx],
+							      bus), len,
+					       PCI_DMA_TODEVICE);
+			pci_unmap_len_set(&tx->info[idx], len, 0);
+			tx->info[idx].skb = NULL;
+		}
+		idx = (idx + 1) & tx->mask;
+	} while (idx != last_idx);
+	if (skb_shinfo(skb)->gso_size) {
+		printk(KERN_ERR
+		       "myri10ge: %s: TSO but wanted to linearize?!?!?\n",
+		       mgp->dev->name);
+		goto drop;
+	}
+
+	if (skb_linearize(skb))
+		goto drop;
+
+	mgp->tx_linearized++;
+	goto again;
+
+drop:
+	dev_kfree_skb_any(skb);
+	mgp->stats.tx_dropped += 1;
+	return 0;
+
+}
+
+static struct net_device_stats *myri10ge_get_stats(struct net_device *dev)
+{
+	struct myri10ge_priv *mgp = netdev_priv(dev);
+	return &mgp->stats;
+}
+
+static void myri10ge_set_multicast_list(struct net_device *dev)
+{
+	/* can be called from atomic contexts,
+	 * pass 1 to force atomicity in myri10ge_send_cmd() */
+	myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1);
+}
+
+static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct sockaddr *sa = addr;
+	struct myri10ge_priv *mgp = netdev_priv(dev);
+	int status;
+
+	if (!is_valid_ether_addr(sa->sa_data))
+		return -EADDRNOTAVAIL;
+
+	status = myri10ge_update_mac_address(mgp, sa->sa_data);
+	if (status != 0) {
+		printk(KERN_ERR
+		       "myri10ge: %s: changing mac address failed with %d\n",
+		       dev->name, status);
+		return status;
+	}
+
+	/* change the dev structure */
+	memcpy(dev->dev_addr, sa->sa_data, 6);
+	return 0;
+}
+
+static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct myri10ge_priv *mgp = netdev_priv(dev);
+	int error = 0;
+
+	if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) {
+		printk(KERN_ERR "myri10ge: %s: new mtu (%d) is not valid\n",
+		       dev->name, new_mtu);
+		return -EINVAL;
+	}
+	printk(KERN_INFO "%s: changing mtu from %d to %d\n",
+	       dev->name, dev->mtu, new_mtu);
+	if (mgp->running) {
+		/* if we change the mtu on an active device, we must
+		 * reset the device so the firmware sees the change */
+		myri10ge_close(dev);
+		dev->mtu = new_mtu;
+		myri10ge_open(dev);
+	} else
+		dev->mtu = new_mtu;
+
+	return error;
+}
+
+/*
+ * Enable ECRC to align PCI-E Completion packets on an 8-byte boundary.
+ * Only do it if the bridge is a root port since we don't want to disturb
+ * any other device, except if forced with myri10ge_ecrc_enable > 1.
+ */
+
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_PCIE	0x005d
+
+static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp)
+{
+	struct pci_dev *bridge = mgp->pdev->bus->self;
+	struct device *dev = &mgp->pdev->dev;
+	unsigned cap;
+	unsigned err_cap;
+	u16 val;
+	u8 ext_type;
+	int ret;
+
+	if (!myri10ge_ecrc_enable || !bridge)
+		return;
+
+	/* check that the bridge is a root port */
+	cap = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+	pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val);
+	ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
+	if (ext_type != PCI_EXP_TYPE_ROOT_PORT) {
+		if (myri10ge_ecrc_enable > 1) {
+			struct pci_dev *old_bridge = bridge;
+
+			/* Walk the hierarchy up to the root port
+			 * where ECRC has to be enabled */
+			do {
+				bridge = bridge->bus->self;
+				if (!bridge) {
+					dev_err(dev,
+						"Failed to find root port"
+						" to force ECRC\n");
+					return;
+				}
+				cap =
+				    pci_find_capability(bridge, PCI_CAP_ID_EXP);
+				pci_read_config_word(bridge,
+						     cap + PCI_CAP_FLAGS, &val);
+				ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4;
+			} while (ext_type != PCI_EXP_TYPE_ROOT_PORT);
+
+			dev_info(dev,
+				 "Forcing ECRC on non-root port %s"
+				 " (enabling on root port %s)\n",
+				 pci_name(old_bridge), pci_name(bridge));
+		} else {
+			dev_err(dev,
+				"Not enabling ECRC on non-root port %s\n",
+				pci_name(bridge));
+			return;
+		}
+	}
+
+	cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR);
+	if (!cap)
+		return;
+
+	ret = pci_read_config_dword(bridge, cap + PCI_ERR_CAP, &err_cap);
+	if (ret) {
+		dev_err(dev, "failed reading ext-conf-space of %s\n",
+			pci_name(bridge));
+		dev_err(dev, "\t pci=nommconf in use? "
+			"or buggy/incomplete/absent ACPI MCFG attr?\n");
+		return;
+	}
+	if (!(err_cap & PCI_ERR_CAP_ECRC_GENC))
+		return;
+
+	err_cap |= PCI_ERR_CAP_ECRC_GENE;
+	pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap);
+	dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge));
+	mgp->tx.boundary = 4096;
+	mgp->fw_name = myri10ge_fw_aligned;
+}
+
+/*
+ * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput
+ * when the PCI-E Completion packets are aligned on an 8-byte
+ * boundary.  Some PCI-E chip sets always align Completion packets; on
+ * the ones that do not, the alignment can be enforced by enabling
+ * ECRC generation (if supported).
+ *
+ * When PCI-E Completion packets are not aligned, it is actually more
+ * efficient to limit Read-DMA transactions to 2KB, rather than 4KB.
+ *
+ * If the driver can neither enable ECRC nor verify that it has
+ * already been enabled, then it must use a firmware image which works
+ * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it
+ * should also ensure that it never gives the device a Read-DMA which is
+ * larger than 2KB by setting the tx.boundary to 2KB.  If ECRC is
+ * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat)
+ * firmware image, and set tx.boundary to 4KB.
+ */
+
+#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE	0x0132
+
+static void myri10ge_select_firmware(struct myri10ge_priv *mgp)
+{
+	struct pci_dev *bridge = mgp->pdev->bus->self;
+
+	mgp->tx.boundary = 2048;
+	mgp->fw_name = myri10ge_fw_unaligned;
+
+	if (myri10ge_force_firmware == 0) {
+		myri10ge_enable_ecrc(mgp);
+
+		/* Check to see if the upstream bridge is known to
+		 * provide aligned completions */
+		if (bridge
+		    /* ServerWorks HT2000/HT1000 */
+		    && bridge->vendor == PCI_VENDOR_ID_SERVERWORKS
+		    && bridge->device ==
+		    PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) {
+			dev_info(&mgp->pdev->dev,
+				 "Assuming aligned completions (0x%x:0x%x)\n",
+				 bridge->vendor, bridge->device);
+			mgp->tx.boundary = 4096;
+			mgp->fw_name = myri10ge_fw_aligned;
+		}
+	} else {
+		if (myri10ge_force_firmware == 1) {
+			dev_info(&mgp->pdev->dev,
+				 "Assuming aligned completions (forced)\n");
+			mgp->tx.boundary = 4096;
+			mgp->fw_name = myri10ge_fw_aligned;
+		} else {
+			dev_info(&mgp->pdev->dev,
+				 "Assuming unaligned completions (forced)\n");
+			mgp->tx.boundary = 2048;
+			mgp->fw_name = myri10ge_fw_unaligned;
+		}
+	}
+	if (myri10ge_fw_name != NULL) {
+		dev_info(&mgp->pdev->dev, "overriding firmware to %s\n",
+			 myri10ge_fw_name);
+		mgp->fw_name = myri10ge_fw_name;
+	}
+}
+
+static void myri10ge_save_state(struct myri10ge_priv *mgp)
+{
+	struct pci_dev *pdev = mgp->pdev;
+	int cap;
+
+	pci_save_state(pdev);
+	/* now save PCIe and MSI state that Linux will not
+	 * save for us */
+	cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &mgp->devctl);
+	cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+	pci_read_config_word(pdev, cap + PCI_MSI_FLAGS, &mgp->msi_flags);
+}
+
+static void myri10ge_restore_state(struct myri10ge_priv *mgp)
+{
+	struct pci_dev *pdev = mgp->pdev;
+	int cap;
+
+	/* restore PCIe and MSI state that linux will not */
+	cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	pci_write_config_dword(pdev, cap + PCI_CAP_ID_EXP, mgp->devctl);
+	cap = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+	pci_write_config_word(pdev, cap + PCI_MSI_FLAGS, mgp->msi_flags);
+
+	pci_restore_state(pdev);
+}
+
+#ifdef CONFIG_PM
+
+static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct myri10ge_priv *mgp;
+	struct net_device *netdev;
+
+	mgp = pci_get_drvdata(pdev);
+	if (mgp == NULL)
+		return -EINVAL;
+	netdev = mgp->dev;
+
+	netif_device_detach(netdev);
+	if (netif_running(netdev)) {
+		printk(KERN_INFO "myri10ge: closing %s\n", netdev->name);
+		rtnl_lock();
+		myri10ge_close(netdev);
+		rtnl_unlock();
+	}
+	myri10ge_dummy_rdma(mgp, 0);
+	free_irq(pdev->irq, mgp);
+	myri10ge_save_state(mgp);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	return 0;
+}
+
+static int myri10ge_resume(struct pci_dev *pdev)
+{
+	struct myri10ge_priv *mgp;
+	struct net_device *netdev;
+	int status;
+	u16 vendor;
+
+	mgp = pci_get_drvdata(pdev);
+	if (mgp == NULL)
+		return -EINVAL;
+	netdev = mgp->dev;
+	pci_set_power_state(pdev, 0);	/* zeros conf space as a side effect */
+	msleep(5);		/* give card time to respond */
+	pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor);
+	if (vendor == 0xffff) {
+		printk(KERN_ERR "myri10ge: %s: device disappeared!\n",
+		       mgp->dev->name);
+		return -EIO;
+	}
+	myri10ge_restore_state(mgp);
+	pci_enable_device(pdev);
+	pci_set_master(pdev);
+
+	status = request_irq(pdev->irq, myri10ge_intr, SA_SHIRQ,
+			     netdev->name, mgp);
+	if (status != 0) {
+		dev_err(&pdev->dev, "failed to allocate IRQ\n");
+		goto abort_with_msi;
+	}
+
+	myri10ge_reset(mgp);
+	myri10ge_dummy_rdma(mgp, mgp->tx.boundary != 4096);
+
+	/* Save configuration space to be restored if the
+	 * nic resets due to a parity error */
+	myri10ge_save_state(mgp);
+
+	if (netif_running(netdev)) {
+		rtnl_lock();
+		myri10ge_open(netdev);
+		rtnl_unlock();
+	}
+	netif_device_attach(netdev);
+
+	return 0;
+
+abort_with_msi:
+	return -EIO;
+
+}
+
+#endif				/* CONFIG_PM */
+
+static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp)
+{
+	struct pci_dev *pdev = mgp->pdev;
+	int vs = mgp->vendor_specific_offset;
+	u32 reboot;
+
+	/*enter read32 mode */
+	pci_write_config_byte(pdev, vs + 0x10, 0x3);
+
+	/*read REBOOT_STATUS (0xfffffff0) */
+	pci_write_config_dword(pdev, vs + 0x18, 0xfffffff0);
+	pci_read_config_dword(pdev, vs + 0x14, &reboot);
+	return reboot;
+}
+
+/*
+ * This watchdog is used to check whether the board has suffered
+ * from a parity error and needs to be recovered.
+ */
+static void myri10ge_watchdog(void *arg)
+{
+	struct myri10ge_priv *mgp = arg;
+	u32 reboot;
+	int status;
+	u16 cmd, vendor;
+
+	mgp->watchdog_resets++;
+	pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd);
+	if ((cmd & PCI_COMMAND_MASTER) == 0) {
+		/* Bus master DMA disabled?  Check to see
+		 * if the card rebooted due to a parity error
+		 * For now, just report it */
+		reboot = myri10ge_read_reboot(mgp);
+		printk(KERN_ERR
+		       "myri10ge: %s: NIC rebooted (0x%x), resetting\n",
+		       mgp->dev->name, reboot);
+		/*
+		 * A rebooted nic will come back with config space as
+		 * it was after power was applied to PCIe bus.
+		 * Attempt to restore config space which was saved
+		 * when the driver was loaded, or the last time the
+		 * nic was resumed from power saving mode.
+		 */
+		myri10ge_restore_state(mgp);
+	} else {
+		/* if we get back -1's from our slot, perhaps somebody
+		 * powered off our card.  Don't try to reset it in
+		 * this case */
+		if (cmd == 0xffff) {
+			pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor);
+			if (vendor == 0xffff) {
+				printk(KERN_ERR
+				       "myri10ge: %s: device disappeared!\n",
+				       mgp->dev->name);
+				return;
+			}
+		}
+		/* Perhaps it is a software error.  Try to reset */
+
+		printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n",
+		       mgp->dev->name);
+		printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
+		       mgp->dev->name, mgp->tx.req, mgp->tx.done,
+		       mgp->tx.pkt_start, mgp->tx.pkt_done,
+		       (int)ntohl(mgp->fw_stats->send_done_count));
+		msleep(2000);
+		printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n",
+		       mgp->dev->name, mgp->tx.req, mgp->tx.done,
+		       mgp->tx.pkt_start, mgp->tx.pkt_done,
+		       (int)ntohl(mgp->fw_stats->send_done_count));
+	}
+	rtnl_lock();
+	myri10ge_close(mgp->dev);
+	status = myri10ge_load_firmware(mgp);
+	if (status != 0)
+		printk(KERN_ERR "myri10ge: %s: failed to load firmware\n",
+		       mgp->dev->name);
+	else
+		myri10ge_open(mgp->dev);
+	rtnl_unlock();
+}
+
+/*
+ * We use our own timer routine rather than relying upon
+ * netdev->tx_timeout because we have a very large hardware transmit
+ * queue.  Due to the large queue, the netdev->tx_timeout function
+ * cannot detect a NIC with a parity error in a timely fashion if the
+ * NIC is lightly loaded.
+ */
+static void myri10ge_watchdog_timer(unsigned long arg)
+{
+	struct myri10ge_priv *mgp;
+
+	mgp = (struct myri10ge_priv *)arg;
+	if (mgp->tx.req != mgp->tx.done &&
+	    mgp->tx.done == mgp->watchdog_tx_done)
+		/* nic seems like it might be stuck.. */
+		schedule_work(&mgp->watchdog_work);
+	else
+		/* rearm timer */
+		mod_timer(&mgp->watchdog_timer,
+			  jiffies + myri10ge_watchdog_timeout * HZ);
+
+	mgp->watchdog_tx_done = mgp->tx.done;
+}
+
+static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	struct net_device *netdev;
+	struct myri10ge_priv *mgp;
+	struct device *dev = &pdev->dev;
+	size_t bytes;
+	int i;
+	int status = -ENXIO;
+	int cap;
+	int dac_enabled;
+	u16 val;
+
+	netdev = alloc_etherdev(sizeof(*mgp));
+	if (netdev == NULL) {
+		dev_err(dev, "Could not allocate ethernet device\n");
+		return -ENOMEM;
+	}
+
+	mgp = netdev_priv(netdev);
+	memset(mgp, 0, sizeof(*mgp));
+	mgp->dev = netdev;
+	mgp->pdev = pdev;
+	mgp->csum_flag = MXGEFW_FLAGS_CKSUM;
+	mgp->pause = myri10ge_flow_control;
+	mgp->intr_coal_delay = myri10ge_intr_coal_delay;
+	init_waitqueue_head(&mgp->down_wq);
+
+	if (pci_enable_device(pdev)) {
+		dev_err(&pdev->dev, "pci_enable_device call failed\n");
+		status = -ENODEV;
+		goto abort_with_netdev;
+	}
+	myri10ge_select_firmware(mgp);
+
+	/* Find the vendor-specific cap so we can check
+	 * the reboot register later on */
+	mgp->vendor_specific_offset
+	    = pci_find_capability(pdev, PCI_CAP_ID_VNDR);
+
+	/* Set our max read request to 4KB */
+	cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+	if (cap < 64) {
+		dev_err(&pdev->dev, "Bad PCI_CAP_ID_EXP location %d\n", cap);
+		goto abort_with_netdev;
+	}
+	status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val);
+	if (status != 0) {
+		dev_err(&pdev->dev, "Error %d reading PCI_EXP_DEVCTL\n",
+			status);
+		goto abort_with_netdev;
+	}
+	val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12);
+	status = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, val);
+	if (status != 0) {
+		dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n",
+			status);
+		goto abort_with_netdev;
+	}
+
+	pci_set_master(pdev);
+	dac_enabled = 1;
+	status = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+	if (status != 0) {
+		dac_enabled = 0;
+		dev_err(&pdev->dev,
+			"64-bit pci address mask was refused, trying 32-bit");
+		status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+	}
+	if (status != 0) {
+		dev_err(&pdev->dev, "Error %d setting DMA mask\n", status);
+		goto abort_with_netdev;
+	}
+	mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd),
+				      &mgp->cmd_bus, GFP_KERNEL);
+	if (mgp->cmd == NULL)
+		goto abort_with_netdev;
+
+	mgp->fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+					   &mgp->fw_stats_bus, GFP_KERNEL);
+	if (mgp->fw_stats == NULL)
+		goto abort_with_cmd;
+
+	mgp->board_span = pci_resource_len(pdev, 0);
+	mgp->iomem_base = pci_resource_start(pdev, 0);
+	mgp->mtrr = -1;
+#ifdef CONFIG_MTRR
+	mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span,
+			     MTRR_TYPE_WRCOMB, 1);
+#endif
+	/* Hack.  need to get rid of these magic numbers */
+	mgp->sram_size =
+	    2 * 1024 * 1024 - (2 * (48 * 1024) + (32 * 1024)) - 0x100;
+	if (mgp->sram_size > mgp->board_span) {
+		dev_err(&pdev->dev, "board span %ld bytes too small\n",
+			mgp->board_span);
+		goto abort_with_wc;
+	}
+	mgp->sram = ioremap(mgp->iomem_base, mgp->board_span);
+	if (mgp->sram == NULL) {
+		dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
+			mgp->board_span, mgp->iomem_base);
+		status = -ENXIO;
+		goto abort_with_wc;
+	}
+	memcpy_fromio(mgp->eeprom_strings,
+		      mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
+		      MYRI10GE_EEPROM_STRINGS_SIZE);
+	memset(mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2);
+	status = myri10ge_read_mac_addr(mgp);
+	if (status)
+		goto abort_with_ioremap;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		netdev->dev_addr[i] = mgp->mac_addr[i];
+
+	/* allocate rx done ring */
+	bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+	mgp->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
+						&mgp->rx_done.bus, GFP_KERNEL);
+	if (mgp->rx_done.entry == NULL)
+		goto abort_with_ioremap;
+	memset(mgp->rx_done.entry, 0, bytes);
+
+	status = myri10ge_load_firmware(mgp);
+	if (status != 0) {
+		dev_err(&pdev->dev, "failed to load firmware\n");
+		goto abort_with_rx_done;
+	}
+
+	status = myri10ge_reset(mgp);
+	if (status != 0) {
+		dev_err(&pdev->dev, "failed reset\n");
+		goto abort_with_firmware;
+	}
+
+	if (myri10ge_msi) {
+		status = pci_enable_msi(pdev);
+		if (status != 0)
+			dev_err(&pdev->dev,
+				"Error %d setting up MSI; falling back to xPIC\n",
+				status);
+		else
+			mgp->msi_enabled = 1;
+	}
+
+	status = request_irq(pdev->irq, myri10ge_intr, SA_SHIRQ,
+			     netdev->name, mgp);
+	if (status != 0) {
+		dev_err(&pdev->dev, "failed to allocate IRQ\n");
+		goto abort_with_firmware;
+	}
+
+	pci_set_drvdata(pdev, mgp);
+	if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU)
+		myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
+	if ((myri10ge_initial_mtu + ETH_HLEN) < 68)
+		myri10ge_initial_mtu = 68;
+	netdev->mtu = myri10ge_initial_mtu;
+	netdev->open = myri10ge_open;
+	netdev->stop = myri10ge_close;
+	netdev->hard_start_xmit = myri10ge_xmit;
+	netdev->get_stats = myri10ge_get_stats;
+	netdev->base_addr = mgp->iomem_base;
+	netdev->irq = pdev->irq;
+	netdev->change_mtu = myri10ge_change_mtu;
+	netdev->set_multicast_list = myri10ge_set_multicast_list;
+	netdev->set_mac_address = myri10ge_set_mac_address;
+	netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO;
+	if (dac_enabled)
+		netdev->features |= NETIF_F_HIGHDMA;
+	netdev->poll = myri10ge_poll;
+	netdev->weight = myri10ge_napi_weight;
+
+	/* Save configuration space to be restored if the
+	 * nic resets due to a parity error */
+	myri10ge_save_state(mgp);
+
+	/* Setup the watchdog timer */
+	setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer,
+		    (unsigned long)mgp);
+
+	SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops);
+	INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp);
+	status = register_netdev(netdev);
+	if (status != 0) {
+		dev_err(&pdev->dev, "register_netdev failed: %d\n", status);
+		goto abort_with_irq;
+	}
+
+	printk(KERN_INFO "myri10ge: %s: %s IRQ %d, tx bndry %d, fw %s, WC %s\n",
+	       netdev->name, (mgp->msi_enabled ? "MSI" : "xPIC"),
+	       pdev->irq, mgp->tx.boundary, mgp->fw_name,
+	       (mgp->mtrr >= 0 ? "Enabled" : "Disabled"));
+
+	return 0;
+
+abort_with_irq:
+	free_irq(pdev->irq, mgp);
+	if (mgp->msi_enabled)
+		pci_disable_msi(pdev);
+
+abort_with_firmware:
+	myri10ge_dummy_rdma(mgp, 0);
+
+abort_with_rx_done:
+	bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+	dma_free_coherent(&pdev->dev, bytes,
+			  mgp->rx_done.entry, mgp->rx_done.bus);
+
+abort_with_ioremap:
+	iounmap(mgp->sram);
+
+abort_with_wc:
+#ifdef CONFIG_MTRR
+	if (mgp->mtrr >= 0)
+		mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
+#endif
+	dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+			  mgp->fw_stats, mgp->fw_stats_bus);
+
+abort_with_cmd:
+	dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
+			  mgp->cmd, mgp->cmd_bus);
+
+abort_with_netdev:
+
+	free_netdev(netdev);
+	return status;
+}
+
+/*
+ * myri10ge_remove
+ *
+ * Does what is necessary to shutdown one Myrinet device. Called
+ *   once for each Myrinet card by the kernel when a module is
+ *   unloaded.
+ */
+static void myri10ge_remove(struct pci_dev *pdev)
+{
+	struct myri10ge_priv *mgp;
+	struct net_device *netdev;
+	size_t bytes;
+
+	mgp = pci_get_drvdata(pdev);
+	if (mgp == NULL)
+		return;
+
+	flush_scheduled_work();
+	netdev = mgp->dev;
+	unregister_netdev(netdev);
+	free_irq(pdev->irq, mgp);
+	if (mgp->msi_enabled)
+		pci_disable_msi(pdev);
+
+	myri10ge_dummy_rdma(mgp, 0);
+
+	bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry);
+	dma_free_coherent(&pdev->dev, bytes,
+			  mgp->rx_done.entry, mgp->rx_done.bus);
+
+	iounmap(mgp->sram);
+
+#ifdef CONFIG_MTRR
+	if (mgp->mtrr >= 0)
+		mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span);
+#endif
+	dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats),
+			  mgp->fw_stats, mgp->fw_stats_bus);
+
+	dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
+			  mgp->cmd, mgp->cmd_bus);
+
+	free_netdev(netdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 	0x0008
+
+static struct pci_device_id myri10ge_pci_tbl[] = {
+	{PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)},
+	{0},
+};
+
+static struct pci_driver myri10ge_driver = {
+	.name = "myri10ge",
+	.probe = myri10ge_probe,
+	.remove = myri10ge_remove,
+	.id_table = myri10ge_pci_tbl,
+#ifdef CONFIG_PM
+	.suspend = myri10ge_suspend,
+	.resume = myri10ge_resume,
+#endif
+};
+
+static __init int myri10ge_init_module(void)
+{
+	printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name,
+	       MYRI10GE_VERSION_STR);
+	return pci_register_driver(&myri10ge_driver);
+}
+
+module_init(myri10ge_init_module);
+
+static __exit void myri10ge_cleanup_module(void)
+{
+	pci_unregister_driver(&myri10ge_driver);
+}
+
+module_exit(myri10ge_cleanup_module);
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h
new file mode 100644
index 0000000..0a6cae6
--- /dev/null
+++ b/drivers/net/myri10ge/myri10ge_mcp.h
@@ -0,0 +1,205 @@
+#ifndef __MYRI10GE_MCP_H__
+#define __MYRI10GE_MCP_H__
+
+#define MXGEFW_VERSION_MAJOR	1
+#define MXGEFW_VERSION_MINOR	4
+
+/* 8 Bytes */
+struct mcp_dma_addr {
+	u32 high;
+	u32 low;
+};
+
+/* 4 Bytes */
+struct mcp_slot {
+	u16 checksum;
+	u16 length;
+};
+
+/* 64 Bytes */
+struct mcp_cmd {
+	u32 cmd;
+	u32 data0;		/* will be low portion if data > 32 bits */
+	/* 8 */
+	u32 data1;		/* will be high portion if data > 32 bits */
+	u32 data2;		/* currently unused.. */
+	/* 16 */
+	struct mcp_dma_addr response_addr;
+	/* 24 */
+	u8 pad[40];
+};
+
+/* 8 Bytes */
+struct mcp_cmd_response {
+	u32 data;
+	u32 result;
+};
+
+/*
+ * flags used in mcp_kreq_ether_send_t:
+ *
+ * The SMALL flag is only needed in the first segment. It is raised
+ * for packets that are total less or equal 512 bytes.
+ *
+ * The CKSUM flag must be set in all segments.
+ *
+ * The PADDED flags is set if the packet needs to be padded, and it
+ * must be set for all segments.
+ *
+ * The  MXGEFW_FLAGS_ALIGN_ODD must be set if the cumulative
+ * length of all previous segments was odd.
+ */
+
+#define MXGEFW_FLAGS_SMALL      0x1
+#define MXGEFW_FLAGS_TSO_HDR    0x1
+#define MXGEFW_FLAGS_FIRST      0x2
+#define MXGEFW_FLAGS_ALIGN_ODD  0x4
+#define MXGEFW_FLAGS_CKSUM      0x8
+#define MXGEFW_FLAGS_TSO_LAST   0x8
+#define MXGEFW_FLAGS_NO_TSO     0x10
+#define MXGEFW_FLAGS_TSO_CHOP   0x10
+#define MXGEFW_FLAGS_TSO_PLD    0x20
+
+#define MXGEFW_SEND_SMALL_SIZE  1520
+#define MXGEFW_MAX_MTU          9400
+
+union mcp_pso_or_cumlen {
+	u16 pseudo_hdr_offset;
+	u16 cum_len;
+};
+
+#define	MXGEFW_MAX_SEND_DESC 12
+#define MXGEFW_PAD	    2
+
+/* 16 Bytes */
+struct mcp_kreq_ether_send {
+	u32 addr_high;
+	u32 addr_low;
+	u16 pseudo_hdr_offset;
+	u16 length;
+	u8 pad;
+	u8 rdma_count;
+	u8 cksum_offset;	/* where to start computing cksum */
+	u8 flags;		/* as defined above */
+};
+
+/* 8 Bytes */
+struct mcp_kreq_ether_recv {
+	u32 addr_high;
+	u32 addr_low;
+};
+
+/* Commands */
+
+#define MXGEFW_CMD_OFFSET 0xf80000
+
+enum myri10ge_mcp_cmd_type {
+	MXGEFW_CMD_NONE = 0,
+	/* Reset the mcp, it is left in a safe state, waiting
+	 * for the driver to set all its parameters */
+	MXGEFW_CMD_RESET,
+
+	/* get the version number of the current firmware..
+	 * (may be available in the eeprom strings..? */
+	MXGEFW_GET_MCP_VERSION,
+
+	/* Parameters which must be set by the driver before it can
+	 * issue MXGEFW_CMD_ETHERNET_UP. They persist until the next
+	 * MXGEFW_CMD_RESET is issued */
+
+	MXGEFW_CMD_SET_INTRQ_DMA,
+	MXGEFW_CMD_SET_BIG_BUFFER_SIZE,	/* in bytes, power of 2 */
+	MXGEFW_CMD_SET_SMALL_BUFFER_SIZE,	/* in bytes */
+
+	/* Parameters which refer to lanai SRAM addresses where the
+	 * driver must issue PIO writes for various things */
+
+	MXGEFW_CMD_GET_SEND_OFFSET,
+	MXGEFW_CMD_GET_SMALL_RX_OFFSET,
+	MXGEFW_CMD_GET_BIG_RX_OFFSET,
+	MXGEFW_CMD_GET_IRQ_ACK_OFFSET,
+	MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
+
+	/* Parameters which refer to rings stored on the MCP,
+	 * and whose size is controlled by the mcp */
+
+	MXGEFW_CMD_GET_SEND_RING_SIZE,	/* in bytes */
+	MXGEFW_CMD_GET_RX_RING_SIZE,	/* in bytes */
+
+	/* Parameters which refer to rings stored in the host,
+	 * and whose size is controlled by the host.  Note that
+	 * all must be physically contiguous and must contain
+	 * a power of 2 number of entries.  */
+
+	MXGEFW_CMD_SET_INTRQ_SIZE,	/* in bytes */
+
+	/* command to bring ethernet interface up.  Above parameters
+	 * (plus mtu & mac address) must have been exchanged prior
+	 * to issuing this command  */
+	MXGEFW_CMD_ETHERNET_UP,
+
+	/* command to bring ethernet interface down.  No further sends
+	 * or receives may be processed until an MXGEFW_CMD_ETHERNET_UP
+	 * is issued, and all interrupt queues must be flushed prior
+	 * to ack'ing this command */
+
+	MXGEFW_CMD_ETHERNET_DOWN,
+
+	/* commands the driver may issue live, without resetting
+	 * the nic.  Note that increasing the mtu "live" should
+	 * only be done if the driver has already supplied buffers
+	 * sufficiently large to handle the new mtu.  Decreasing
+	 * the mtu live is safe */
+
+	MXGEFW_CMD_SET_MTU,
+	MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET,	/* in microseconds */
+	MXGEFW_CMD_SET_STATS_INTERVAL,	/* in microseconds */
+	MXGEFW_CMD_SET_STATS_DMA,
+
+	MXGEFW_ENABLE_PROMISC,
+	MXGEFW_DISABLE_PROMISC,
+	MXGEFW_SET_MAC_ADDRESS,
+
+	MXGEFW_ENABLE_FLOW_CONTROL,
+	MXGEFW_DISABLE_FLOW_CONTROL,
+
+	/* do a DMA test
+	 * data0,data1 = DMA address
+	 * data2       = RDMA length (MSH), WDMA length (LSH)
+	 * command return data = repetitions (MSH), 0.5-ms ticks (LSH)
+	 */
+	MXGEFW_DMA_TEST
+};
+
+enum myri10ge_mcp_cmd_status {
+	MXGEFW_CMD_OK = 0,
+	MXGEFW_CMD_UNKNOWN,
+	MXGEFW_CMD_ERROR_RANGE,
+	MXGEFW_CMD_ERROR_BUSY,
+	MXGEFW_CMD_ERROR_EMPTY,
+	MXGEFW_CMD_ERROR_CLOSED,
+	MXGEFW_CMD_ERROR_HASH_ERROR,
+	MXGEFW_CMD_ERROR_BAD_PORT,
+	MXGEFW_CMD_ERROR_RESOURCES
+};
+
+/* 40 Bytes */
+struct mcp_irq_data {
+	u32 send_done_count;
+
+	u32 link_up;
+	u32 dropped_link_overflow;
+	u32 dropped_link_error_or_filtered;
+	u32 dropped_runt;
+	u32 dropped_overrun;
+	u32 dropped_no_small_buffer;
+	u32 dropped_no_big_buffer;
+	u32 rdma_tags_available;
+
+	u8 tx_stopped;
+	u8 link_down;
+	u8 stats_updated;
+	u8 valid;
+};
+
+#endif				/* __MYRI10GE_MCP_H__ */
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
new file mode 100644
index 0000000..487f779
--- /dev/null
+++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
@@ -0,0 +1,58 @@
+#ifndef __MYRI10GE_MCP_GEN_HEADER_H__
+#define __MYRI10GE_MCP_GEN_HEADER_H__
+
+/* this file define a standard header used as a first entry point to
+ * exchange information between firmware/driver and driver.  The
+ * header structure can be anywhere in the mcp. It will usually be in
+ * the .data section, because some fields needs to be initialized at
+ * compile time.
+ * The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must
+ * contains the location of the header.
+ *
+ * Typically a MCP will start with the following:
+ * .text
+ * .space 52    ! to help catch MEMORY_INT errors
+ * bt start     ! jump to real code
+ * nop
+ * .long _gen_mcp_header
+ *
+ * The source will have a definition like:
+ *
+ * mcp_gen_header_t gen_mcp_header = {
+ * .header_length = sizeof(mcp_gen_header_t),
+ * .mcp_type = MCP_TYPE_XXX,
+ * .version = "something $Id: mcp_gen_header.h,v 1.2 2006/05/13 10:04:35 bgoglin Exp $",
+ * .mcp_globals = (unsigned)&Globals
+ * };
+ */
+
+#define MCP_HEADER_PTR_OFFSET  0x3c
+
+#define MCP_TYPE_MX 0x4d582020	/* "MX  " */
+#define MCP_TYPE_PCIE 0x70636965	/* "PCIE" pcie-only MCP */
+#define MCP_TYPE_ETH 0x45544820	/* "ETH " */
+#define MCP_TYPE_MCP0 0x4d435030	/* "MCP0" */
+
+struct mcp_gen_header {
+	/* the first 4 fields are filled at compile time */
+	unsigned header_length;
+	unsigned mcp_type;
+	char version[128];
+	unsigned mcp_globals;	/* pointer to mcp-type specific structure */
+
+	/* filled by the MCP at run-time */
+	unsigned sram_size;
+	unsigned string_specs;	/* either the original STRING_SPECS or a superset */
+	unsigned string_specs_len;
+
+	/* Fields above this comment are guaranteed to be present.
+	 *
+	 * Fields below this comment are extensions added in later versions
+	 * of this struct, drivers should compare the header_length against
+	 * offsetof(field) to check wether a given MCP implements them.
+	 *
+	 * Never remove any field.  Keep everything naturally align.
+	 */
+};
+
+#endif				/* __MYRI10GE_MCP_GEN_HEADER_H__ */
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 6c86dca6..d9f616f 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -1,10 +1,10 @@
-/* myri_sbus.h: MyriCOM MyriNET SBUS card driver.
+/* myri_sbus.c: MyriCOM MyriNET SBUS card driver.
  *
- * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1999, 2006 David S. Miller (davem@davemloft.net)
  */
 
 static char version[] =
-        "myri_sbus.c:v1.9 12/Sep/99 David S. Miller (davem@redhat.com)\n";
+        "myri_sbus.c:v2.0 June 23, 2006 David S. Miller (davem@davemloft.net)\n";
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -81,10 +81,6 @@
 #define DHDR(x)
 #endif
 
-#ifdef MODULE
-static struct myri_eth *root_myri_dev;
-#endif
-
 static void myri_reset_off(void __iomem *lp, void __iomem *cregs)
 {
 	/* Clear IRQ mask. */
@@ -896,8 +892,9 @@
 }
 #endif
 
-static int __init myri_ether_init(struct sbus_dev *sdev, int num)
+static int __init myri_ether_init(struct sbus_dev *sdev)
 {
+	static int num;
 	static unsigned version_printed;
 	struct net_device *dev;
 	struct myri_eth *mp;
@@ -913,6 +910,9 @@
 	if (version_printed++ == 0)
 		printk(version);
 
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
+
 	mp = (struct myri_eth *) dev->priv;
 	spin_lock_init(&mp->irq_lock);
 	mp->myri_sdev = sdev;
@@ -1092,10 +1092,9 @@
 		goto err_free_irq;
 	}
 
-#ifdef MODULE
-	mp->next_module = root_myri_dev;
-	root_myri_dev = mp;
-#endif
+	dev_set_drvdata(&sdev->ofdev.dev, mp);
+
+	num++;
 
 	printk("%s: MyriCOM MyriNET Ethernet ", dev->name);
 
@@ -1114,61 +1113,68 @@
 	return -ENODEV;
 }
 
-static int __init myri_sbus_match(struct sbus_dev *sdev)
-{
-	char *name = sdev->prom_name;
 
-	if (!strcmp(name, "MYRICOM,mlanai") ||
-	    !strcmp(name, "myri"))
-		return 1;
+static int __devinit myri_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+
+	return myri_ether_init(sdev);
+}
+
+static int __devexit myri_sbus_remove(struct of_device *dev)
+{
+	struct myri_eth *mp = dev_get_drvdata(&dev->dev);
+	struct net_device *net_dev = mp->dev;
+
+	unregister_netdevice(net_dev);
+
+	free_irq(net_dev->irq, net_dev);
+
+	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
+		sbus_iounmap(mp->regs, mp->reg_size);
+	} else {
+		sbus_iounmap(mp->cregs, PAGE_SIZE);
+		sbus_iounmap(mp->lregs, (256 * 1024));
+		sbus_iounmap(mp->lanai, (512 * 1024));
+	}
+
+	free_netdev(net_dev);
+
+	dev_set_drvdata(&dev->dev, NULL);
 
 	return 0;
 }
 
-static int __init myri_sbus_probe(void)
+static struct of_device_id myri_sbus_match[] = {
+	{
+		.name = "MYRICOM,mlanai",
+	},
+	{
+		.name = "myri",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, myri_sbus_match);
+
+static struct of_platform_driver myri_sbus_driver = {
+	.name		= "myri",
+	.match_table	= myri_sbus_match,
+	.probe		= myri_sbus_probe,
+	.remove		= __devexit_p(myri_sbus_remove),
+};
+
+static int __init myri_sbus_init(void)
 {
-	struct sbus_bus *bus;
-	struct sbus_dev *sdev = NULL;
-	static int called;
-	int cards = 0, v;
-
-#ifdef MODULE
-	root_myri_dev = NULL;
-#endif
-
-	if (called)
-		return -ENODEV;
-	called++;
-
-	for_each_sbus(bus) {
-		for_each_sbusdev(sdev, bus) {
-			if (myri_sbus_match(sdev)) {
-				cards++;
-				DET(("Found myricom myrinet as %s\n", sdev->prom_name));
-				if ((v = myri_ether_init(sdev, (cards - 1))))
-					return v;
-			}
-		}
-	}
-	if (!cards)
-		return -ENODEV;
-	return 0;
+	return of_register_driver(&myri_sbus_driver, &sbus_bus_type);
 }
 
-static void __exit myri_sbus_cleanup(void)
+static void __exit myri_sbus_exit(void)
 {
-#ifdef MODULE
-	while (root_myri_dev) {
-		struct myri_eth *next = root_myri_dev->next_module;
-
-		unregister_netdev(root_myri_dev->dev);
-		/* this will also free the co-allocated 'root_myri_dev' */
-		free_netdev(root_myri_dev->dev);
-		root_myri_dev = next;
-	}
-#endif /* MODULE */
+	of_unregister_driver(&myri_sbus_driver);
 }
 
-module_init(myri_sbus_probe);
-module_exit(myri_sbus_cleanup);
+module_init(myri_sbus_init);
+module_exit(myri_sbus_exit);
+
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h
index 47722f7..2f69ef7 100644
--- a/drivers/net/myri_sbus.h
+++ b/drivers/net/myri_sbus.h
@@ -290,7 +290,6 @@
 	unsigned int			reg_size;	/* Size of register space.    */
 	unsigned int			shmem_base;	/* Offset to shared ram.      */
 	struct sbus_dev			*myri_sdev;	/* Our SBUS device struct.    */
-	struct myri_eth			*next_module;	/* Next in adapter chain.     */
 };
 
 /* We use this to acquire receive skb's that we can DMA directly into. */
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 9062775..5657049 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -226,7 +226,6 @@
 				 NATSEMI_PG1_NREGS)
 #define NATSEMI_REGS_VER	1 /* v1 added RFDR registers */
 #define NATSEMI_REGS_SIZE	(NATSEMI_NREGS * sizeof(u32))
-#define NATSEMI_DEF_EEPROM_SIZE	24 /* 12 16-bit values */
 
 /* Buffer sizes:
  * The nic writes 32-bit values, even if the upper bytes of
@@ -318,12 +317,12 @@
 The rx process only runs in the interrupt handler. Access from outside
 the interrupt handler is only permitted after disable_irq().
 
-The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
+The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
 is set, then access is permitted under spin_lock_irq(&np->lock).
 
 Thus configuration functions that want to access everything must call
 	disable_irq(dev->irq);
-	spin_lock_bh(dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	spin_lock_irq(&np->lock);
 
 IV. Notes
@@ -344,18 +343,6 @@
 
 
 
-enum pcistuff {
-	PCI_USES_IO = 0x01,
-	PCI_USES_MEM = 0x02,
-	PCI_USES_MASTER = 0x04,
-	PCI_ADDR0 = 0x08,
-	PCI_ADDR1 = 0x10,
-};
-
-/* MMIO operations required */
-#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
-
-
 /*
  * Support for fibre connections on Am79C874:
  * This phy needs a special setup when connected to a fibre cable.
@@ -363,22 +350,25 @@
  */
 #define PHYID_AM79C874	0x0022561b
 
-#define MII_MCTRL	0x15	/* mode control register */
-#define MII_FX_SEL	0x0001	/* 100BASE-FX (fiber) */
-#define MII_EN_SCRM	0x0004	/* enable scrambler (tp) */
+enum {
+	MII_MCTRL	= 0x15,		/* mode control register */
+	MII_FX_SEL	= 0x0001,	/* 100BASE-FX (fiber) */
+	MII_EN_SCRM	= 0x0004,	/* enable scrambler (tp) */
+};
 
  
 /* array of board data directly indexed by pci_tbl[x].driver_data */
 static const struct {
 	const char *name;
 	unsigned long flags;
+	unsigned int eeprom_size;
 } natsemi_pci_info[] __devinitdata = {
-	{ "NatSemi DP8381[56]", PCI_IOTYPE },
+	{ "NatSemi DP8381[56]", 0, 24 },
 };
 
-static struct pci_device_id natsemi_pci_tbl[] = {
-	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83815, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, },
+static const struct pci_device_id natsemi_pci_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_NS, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ }	/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, natsemi_pci_tbl);
 
@@ -813,6 +803,42 @@
 	udelay(1);
 }
 
+static void __devinit natsemi_init_media (struct net_device *dev)
+{
+	struct netdev_private *np = netdev_priv(dev);
+	u32 tmp;
+
+	netif_carrier_off(dev);
+
+	/* get the initial settings from hardware */
+	tmp            = mdio_read(dev, MII_BMCR);
+	np->speed      = (tmp & BMCR_SPEED100)? SPEED_100     : SPEED_10;
+	np->duplex     = (tmp & BMCR_FULLDPLX)? DUPLEX_FULL   : DUPLEX_HALF;
+	np->autoneg    = (tmp & BMCR_ANENABLE)? AUTONEG_ENABLE: AUTONEG_DISABLE;
+	np->advertising= mdio_read(dev, MII_ADVERTISE);
+
+	if ((np->advertising & ADVERTISE_ALL) != ADVERTISE_ALL
+	 && netif_msg_probe(np)) {
+		printk(KERN_INFO "natsemi %s: Transceiver default autonegotiation %s "
+			"10%s %s duplex.\n",
+			pci_name(np->pci_dev),
+			(mdio_read(dev, MII_BMCR) & BMCR_ANENABLE)?
+			  "enabled, advertise" : "disabled, force",
+			(np->advertising &
+			  (ADVERTISE_100FULL|ADVERTISE_100HALF))?
+			    "0" : "",
+			(np->advertising &
+			  (ADVERTISE_100FULL|ADVERTISE_10FULL))?
+			    "full" : "half");
+	}
+	if (netif_msg_probe(np))
+		printk(KERN_INFO
+			"natsemi %s: Transceiver status %#04x advertising %#04x.\n",
+			pci_name(np->pci_dev), mdio_read(dev, MII_BMSR),
+			np->advertising);
+
+}
+
 static int __devinit natsemi_probe1 (struct pci_dev *pdev,
 	const struct pci_device_id *ent)
 {
@@ -852,8 +878,7 @@
 	iosize = pci_resource_len(pdev, pcibar);
 	irq = pdev->irq;
 
-	if (natsemi_pci_info[chip_idx].flags & PCI_USES_MASTER)
-		pci_set_master(pdev);
+	pci_set_master(pdev);
 
 	dev = alloc_etherdev(sizeof (struct netdev_private));
 	if (!dev)
@@ -892,7 +917,7 @@
 	np->msg_enable = (debug >= 0) ? (1<<debug)-1 : NATSEMI_DEF_MSG;
 	np->hands_off = 0;
 	np->intr_status = 0;
-	np->eeprom_size = NATSEMI_DEF_EEPROM_SIZE;
+	np->eeprom_size = natsemi_pci_info[chip_idx].eeprom_size;
 
 	/* Initial port:
 	 * - If the nic was configured to use an external phy and if find_mii
@@ -957,34 +982,7 @@
 	if (mtu)
 		dev->mtu = mtu;
 
-	netif_carrier_off(dev);
-
-	/* get the initial settings from hardware */
-	tmp            = mdio_read(dev, MII_BMCR);
-	np->speed      = (tmp & BMCR_SPEED100)? SPEED_100     : SPEED_10;
-	np->duplex     = (tmp & BMCR_FULLDPLX)? DUPLEX_FULL   : DUPLEX_HALF;
-	np->autoneg    = (tmp & BMCR_ANENABLE)? AUTONEG_ENABLE: AUTONEG_DISABLE;
-	np->advertising= mdio_read(dev, MII_ADVERTISE);
-
-	if ((np->advertising & ADVERTISE_ALL) != ADVERTISE_ALL
-	 && netif_msg_probe(np)) {
-		printk(KERN_INFO "natsemi %s: Transceiver default autonegotiation %s "
-			"10%s %s duplex.\n",
-			pci_name(np->pci_dev),
-			(mdio_read(dev, MII_BMCR) & BMCR_ANENABLE)?
-			  "enabled, advertise" : "disabled, force",
-			(np->advertising &
-			  (ADVERTISE_100FULL|ADVERTISE_100HALF))?
-			    "0" : "",
-			(np->advertising &
-			  (ADVERTISE_100FULL|ADVERTISE_10FULL))?
-			    "full" : "half");
-	}
-	if (netif_msg_probe(np))
-		printk(KERN_INFO
-			"natsemi %s: Transceiver status %#04x advertising %#04x.\n",
-			pci_name(np->pci_dev), mdio_read(dev, MII_BMSR),
-			np->advertising);
+	natsemi_init_media(dev);
 
 	/* save the silicon revision for later querying */
 	np->srr = readl(ioaddr + SiliconRev);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index b327652..963a11f 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -829,7 +829,7 @@
 is at boot) and so the probe will get confused by any other 8390 cards.
 ISA device autoprobes on a running machine are not recommended anyway. */
 
-int init_module(void)
+int __init init_module(void)
 {
 	int this_dev, found = 0;
 
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 2aa7b77f..eebf5f0 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -780,7 +780,7 @@
 
 /* Module code fixed by David Weinehall */
 
-int init_module(void)
+int __init init_module(void)
 {
 	struct net_device *dev;
 	int this_dev, found = 0;
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
new file mode 100644
index 0000000..b92430c
--- /dev/null
+++ b/drivers/net/netx-eth.c
@@ -0,0 +1,516 @@
+/*
+ * drivers/net/netx-eth.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/mii.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/netx-regs.h>
+#include <asm/arch/pfifo.h>
+#include <asm/arch/xc.h>
+#include <asm/arch/eth.h>
+
+/* XC Fifo Offsets */
+#define EMPTY_PTR_FIFO(xcno)    (0 + ((xcno) << 3))	/* Index of the empty pointer FIFO */
+#define IND_FIFO_PORT_HI(xcno)  (1 + ((xcno) << 3))	/* Index of the FIFO where received */
+							/* Data packages are indicated by XC */
+#define IND_FIFO_PORT_LO(xcno)  (2 + ((xcno) << 3))	/* Index of the FIFO where received */
+							/* Data packages are indicated by XC */
+#define REQ_FIFO_PORT_HI(xcno)  (3 + ((xcno) << 3))	/* Index of the FIFO where Data packages */
+							/* have to be indicated by ARM which */
+							/* shall be sent */
+#define REQ_FIFO_PORT_LO(xcno)  (4 + ((xcno) << 3))	/* Index of the FIFO where Data packages */
+							/* have to be indicated by ARM which shall */
+							/* be sent */
+#define CON_FIFO_PORT_HI(xcno)  (5 + ((xcno) << 3))	/* Index of the FIFO where sent Data packages */
+							/* are confirmed */
+#define CON_FIFO_PORT_LO(xcno)  (6 + ((xcno) << 3))	/* Index of the FIFO where sent Data */
+							/* packages are confirmed */
+#define PFIFO_MASK(xcno)        (0x7f << (xcno*8))
+
+#define FIFO_PTR_FRAMELEN_SHIFT 0
+#define FIFO_PTR_FRAMELEN_MASK  (0x7ff << 0)
+#define FIFO_PTR_FRAMELEN(len)  (((len) << 0) & FIFO_PTR_FRAMELEN_MASK)
+#define FIFO_PTR_TIMETRIG       (1<<11)
+#define FIFO_PTR_MULTI_REQ
+#define FIFO_PTR_ORIGIN         (1<<14)
+#define FIFO_PTR_VLAN           (1<<15)
+#define FIFO_PTR_FRAMENO_SHIFT  16
+#define FIFO_PTR_FRAMENO_MASK   (0x3f << 16)
+#define FIFO_PTR_FRAMENO(no)    (((no) << 16) & FIFO_PTR_FRAMENO_MASK)
+#define FIFO_PTR_SEGMENT_SHIFT  22
+#define FIFO_PTR_SEGMENT_MASK   (0xf << 22)
+#define FIFO_PTR_SEGMENT(seg)   (((seg) & 0xf) << 22)
+#define FIFO_PTR_ERROR_SHIFT    28
+#define FIFO_PTR_ERROR_MASK     (0xf << 28)
+
+#define ISR_LINK_STATUS_CHANGE (1<<4)
+#define ISR_IND_LO             (1<<3)
+#define ISR_CON_LO             (1<<2)
+#define ISR_IND_HI             (1<<1)
+#define ISR_CON_HI             (1<<0)
+
+#define ETH_MAC_LOCAL_CONFIG 0x1560
+#define ETH_MAC_4321         0x1564
+#define ETH_MAC_65           0x1568
+
+#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16
+#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT)
+#define MAC_TRAFFIC_CLASS_ARRANGEMENT(x) (((x)<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) & MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK)
+#define LOCAL_CONFIG_LINK_STATUS_IRQ_EN (1<<24)
+#define LOCAL_CONFIG_CON_LO_IRQ_EN (1<<23)
+#define LOCAL_CONFIG_CON_HI_IRQ_EN (1<<22)
+#define LOCAL_CONFIG_IND_LO_IRQ_EN (1<<21)
+#define LOCAL_CONFIG_IND_HI_IRQ_EN (1<<20)
+
+#define CARDNAME "netx-eth"
+
+/* LSB must be zero */
+#define INTERNAL_PHY_ADR 0x1c
+
+struct netx_eth_priv {
+	void                    __iomem *sram_base, *xpec_base, *xmac_base;
+	int                     id;
+	struct net_device_stats stats;
+	struct mii_if_info      mii;
+	u32                     msg_enable;
+	struct xc               *xc;
+	spinlock_t              lock;
+};
+
+static void netx_eth_set_multicast_list(struct net_device *ndev)
+{
+	/* implement me */
+}
+
+static int
+netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+	unsigned char *buf = skb->data;
+	unsigned int len = skb->len;
+
+	spin_lock_irq(&priv->lock);
+	memcpy_toio(priv->sram_base + 1560, (void *)buf, len);
+	if (len < 60) {
+		memset_io(priv->sram_base + 1560 + len, 0, 60 - len);
+		len = 60;
+	}
+
+	pfifo_push(REQ_FIFO_PORT_LO(priv->id),
+	           FIFO_PTR_SEGMENT(priv->id) |
+	           FIFO_PTR_FRAMENO(1) |
+	           FIFO_PTR_FRAMELEN(len));
+
+	ndev->trans_start = jiffies;
+	priv->stats.tx_packets++;
+	priv->stats.tx_bytes += skb->len;
+
+	netif_stop_queue(ndev);
+	spin_unlock_irq(&priv->lock);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+static void netx_eth_receive(struct net_device *ndev)
+{
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+	unsigned int val, frameno, seg, len;
+	unsigned char *data;
+	struct sk_buff *skb;
+
+	val = pfifo_pop(IND_FIFO_PORT_LO(priv->id));
+
+	frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT;
+	seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT;
+	len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT;
+
+	skb = dev_alloc_skb(len);
+	if (unlikely(skb == NULL)) {
+		printk(KERN_NOTICE "%s: Low memory, packet dropped.\n",
+			ndev->name);
+		priv->stats.rx_dropped++;
+		return;
+	}
+
+	data = skb_put(skb, len);
+
+	memcpy_fromio(data, priv->sram_base + frameno * 1560, len);
+
+	pfifo_push(EMPTY_PTR_FIFO(priv->id),
+		FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno));
+
+	ndev->last_rx = jiffies;
+	skb->dev = ndev;
+	skb->protocol = eth_type_trans(skb, ndev);
+	netif_rx(skb);
+	priv->stats.rx_packets++;
+	priv->stats.rx_bytes += len;
+}
+
+static irqreturn_t
+netx_eth_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *ndev = dev_id;
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+	int status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
+	while (status) {
+		int fill_level;
+		writel(status, NETX_PFIFO_XPEC_ISR(priv->id));
+
+		if ((status & ISR_CON_HI) || (status & ISR_IND_HI))
+			printk("%s: unexpected status: 0x%08x\n",
+			    __FUNCTION__, status);
+
+		fill_level =
+		    readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id)));
+		while (fill_level--)
+			netx_eth_receive(ndev);
+
+		if (status & ISR_CON_LO)
+			netif_wake_queue(ndev);
+
+		if (status & ISR_LINK_STATUS_CHANGE)
+			mii_check_media(&priv->mii, netif_msg_link(priv), 1);
+
+		status = readl(NETX_PFIFO_XPEC_ISR(priv->id));
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+}
+
+static struct net_device_stats *netx_eth_query_statistics(struct net_device *ndev)
+{
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+	return &priv->stats;
+}
+
+static int netx_eth_open(struct net_device *ndev)
+{
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+
+	if (request_irq
+	    (ndev->irq, &netx_eth_interrupt, SA_SHIRQ, ndev->name, ndev))
+		return -EAGAIN;
+
+	writel(ndev->dev_addr[0] |
+	       ndev->dev_addr[1]<<8 |
+	       ndev->dev_addr[2]<<16 |
+	       ndev->dev_addr[3]<<24,
+	       priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
+	writel(ndev->dev_addr[4] |
+	       ndev->dev_addr[5]<<8,
+	       priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
+
+	writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN |
+		LOCAL_CONFIG_CON_LO_IRQ_EN |
+		LOCAL_CONFIG_CON_HI_IRQ_EN |
+		LOCAL_CONFIG_IND_LO_IRQ_EN |
+		LOCAL_CONFIG_IND_HI_IRQ_EN,
+		priv->xpec_base + NETX_XPEC_RAM_START_OFS +
+		ETH_MAC_LOCAL_CONFIG);
+
+	mii_check_media(&priv->mii, netif_msg_link(priv), 1);
+	netif_start_queue(ndev);
+
+	return 0;
+}
+
+static int netx_eth_close(struct net_device *ndev)
+{
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+
+	netif_stop_queue(ndev);
+
+	writel(0,
+	    priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG);
+
+	free_irq(ndev->irq, ndev);
+
+	return 0;
+}
+
+static void netx_eth_timeout(struct net_device *ndev)
+{
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+	int i;
+
+	printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name);
+
+	spin_lock_irq(&priv->lock);
+
+	xc_reset(priv->xc);
+	xc_start(priv->xc);
+
+	for (i=2; i<=18; i++)
+		pfifo_push(EMPTY_PTR_FIFO(priv->id),
+			FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
+
+	spin_unlock_irq(&priv->lock);
+
+	netif_wake_queue(ndev);
+}
+
+static int
+netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg)
+{
+	unsigned int val;
+
+	val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
+	      MIIMU_REGADDR(reg) | MIIMU_PHY_NRES;
+
+	writel(val, NETX_MIIMU);
+	while (readl(NETX_MIIMU) & MIIMU_SNRDY);
+
+	return readl(NETX_MIIMU) >> 16;
+
+}
+
+static void
+netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value)
+{
+	unsigned int val;
+
+	val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) |
+	      MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE |
+	      MIIMU_DATA(value);
+
+	writel(val, NETX_MIIMU);
+	while (readl(NETX_MIIMU) & MIIMU_SNRDY);
+}
+
+static int netx_eth_enable(struct net_device *ndev)
+{
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+	unsigned int mac4321, mac65;
+	int running, i;
+
+	ether_setup(ndev);
+
+	ndev->open = netx_eth_open;
+	ndev->stop = netx_eth_close;
+	ndev->hard_start_xmit = netx_eth_hard_start_xmit;
+	ndev->tx_timeout = netx_eth_timeout;
+	ndev->watchdog_timeo = msecs_to_jiffies(5000);
+	ndev->get_stats = netx_eth_query_statistics;
+	ndev->set_multicast_list = netx_eth_set_multicast_list;
+
+	priv->msg_enable       = NETIF_MSG_LINK;
+	priv->mii.phy_id_mask  = 0x1f;
+	priv->mii.reg_num_mask = 0x1f;
+	priv->mii.force_media  = 0;
+	priv->mii.full_duplex  = 0;
+	priv->mii.dev	     = ndev;
+	priv->mii.mdio_read    = netx_eth_phy_read;
+	priv->mii.mdio_write   = netx_eth_phy_write;
+	priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id;
+
+	running = xc_running(priv->xc);
+	xc_stop(priv->xc);
+
+	/* if the xc engine is already running, assume the bootloader has
+	 * loaded the firmware for us
+	 */
+	if (running) {
+		/* get Node Address from hardware */
+		mac4321 = readl(priv->xpec_base +
+			NETX_XPEC_RAM_START_OFS + ETH_MAC_4321);
+		mac65 = readl(priv->xpec_base +
+			NETX_XPEC_RAM_START_OFS + ETH_MAC_65);
+
+		ndev->dev_addr[0] = mac4321 & 0xff;
+		ndev->dev_addr[1] = (mac4321 >> 8) & 0xff;
+		ndev->dev_addr[2] = (mac4321 >> 16) & 0xff;
+		ndev->dev_addr[3] = (mac4321 >> 24) & 0xff;
+		ndev->dev_addr[4] = mac65 & 0xff;
+		ndev->dev_addr[5] = (mac65 >> 8) & 0xff;
+	} else {
+		if (xc_request_firmware(priv->xc)) {
+			printk(CARDNAME ": requesting firmware failed\n");
+			return -ENODEV;
+		}
+	}
+
+	xc_reset(priv->xc);
+	xc_start(priv->xc);
+
+	if (!is_valid_ether_addr(ndev->dev_addr))
+		printk("%s: Invalid ethernet MAC address.  Please "
+		       "set using ifconfig\n", ndev->name);
+
+	for (i=2; i<=18; i++)
+		pfifo_push(EMPTY_PTR_FIFO(priv->id),
+			FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id));
+
+	return register_netdev(ndev);
+
+}
+
+static int netx_eth_drv_probe(struct platform_device *pdev)
+{
+	struct netx_eth_priv *priv;
+	struct net_device *ndev;
+	struct netxeth_platform_data *pdata;
+	int ret;
+
+	ndev = alloc_etherdev(sizeof (struct netx_eth_priv));
+	if (!ndev) {
+		printk("%s: could not allocate device.\n", CARDNAME);
+		ret = -ENOMEM;
+		goto exit;
+	}
+	SET_MODULE_OWNER(ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	platform_set_drvdata(pdev, ndev);
+
+	priv = netdev_priv(ndev);
+
+	pdata = (struct netxeth_platform_data *)pdev->dev.platform_data;
+	priv->xc = request_xc(pdata->xcno, &pdev->dev);
+	if (!priv->xc) {
+		dev_err(&pdev->dev, "unable to request xc engine\n");
+		ret = -ENODEV;
+		goto exit_free_netdev;
+	}
+
+	ndev->irq = priv->xc->irq;
+	priv->id = pdev->id;
+	priv->xpec_base = priv->xc->xpec_base;
+	priv->xmac_base = priv->xc->xmac_base;
+	priv->sram_base = priv->xc->sram_base;
+
+	ret = pfifo_request(PFIFO_MASK(priv->id));
+	if (ret) {
+		printk("unable to request PFIFO\n");
+		goto exit_free_xc;
+	}
+
+	ret = netx_eth_enable(ndev);
+	if (ret)
+		goto exit_free_pfifo;
+
+	return 0;
+exit_free_pfifo:
+	pfifo_free(PFIFO_MASK(priv->id));
+exit_free_xc:
+	free_xc(priv->xc);
+exit_free_netdev:
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(ndev);
+exit:
+	return ret;
+}
+
+static int netx_eth_drv_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = dev_get_drvdata(&pdev->dev);
+	struct netx_eth_priv *priv = netdev_priv(ndev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	unregister_netdev(ndev);
+	xc_stop(priv->xc);
+	free_xc(priv->xc);
+	free_netdev(ndev);
+	pfifo_free(PFIFO_MASK(priv->id));
+
+	return 0;
+}
+
+static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	dev_err(&pdev->dev, "suspend not implemented\n");
+	return 0;
+}
+
+static int netx_eth_drv_resume(struct platform_device *pdev)
+{
+	dev_err(&pdev->dev, "resume not implemented\n");
+	return 0;
+}
+
+static struct platform_driver netx_eth_driver = {
+	.probe		= netx_eth_drv_probe,
+	.remove		= netx_eth_drv_remove,
+	.suspend	= netx_eth_drv_suspend,
+	.resume		= netx_eth_drv_resume,
+	.driver		= {
+		.name	= CARDNAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init netx_eth_init(void)
+{
+	unsigned int phy_control, val;
+
+	printk("NetX Ethernet driver\n");
+
+	phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) |
+		      PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) |
+		      PHY_CONTROL_PHY1_AUTOMDIX |
+		      PHY_CONTROL_PHY1_EN |
+		      PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) |
+		      PHY_CONTROL_PHY0_AUTOMDIX |
+		      PHY_CONTROL_PHY0_EN |
+		      PHY_CONTROL_CLK_XLATIN;
+
+	val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+	writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+	writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL);
+	udelay(100);
+
+	val = readl(NETX_SYSTEM_IOC_ACCESS_KEY);
+	writel(val, NETX_SYSTEM_IOC_ACCESS_KEY);
+
+	writel(phy_control, NETX_SYSTEM_PHY_CONTROL);
+
+	return platform_driver_register(&netx_eth_driver);
+}
+
+static void __exit netx_eth_cleanup(void)
+{
+	platform_driver_unregister(&netx_eth_driver);
+}
+
+module_init(netx_eth_init);
+module_exit(netx_eth_cleanup);
+
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 09b1176..ea93b8f1 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -831,8 +831,7 @@
     
     if (length < ETH_ZLEN)
     {
-    	skb = skb_padto(skb, ETH_ZLEN);
-    	if (skb == NULL)
+    	if (skb_padto(skb, ETH_ZLEN))
     		return 0;
     	length = ETH_ZLEN;
     }
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index d090df4..661bfe5 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -12,7 +12,7 @@
     Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
 
     pcnet_cs.c 1.153 2003/11/09 18:53:09
-    
+
     The network driver code is based on Donald Becker's NE2000 code:
 
     Written 1992,1993 by Donald Becker.
@@ -146,7 +146,7 @@
 #define MII_PHYID_REG2		0x03
 
 static hw_info_t hw_info[] = {
-    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, 
+    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
     { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
     { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
     { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
@@ -193,7 +193,7 @@
     { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
     { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
       HAS_MISC_REG | HAS_IBM_MISC },
-    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, 
+    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
       HAS_MISC_REG | HAS_IBM_MISC },
     { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
     { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
@@ -330,7 +330,7 @@
 	for (j = 0; j < 6; j++)
 	    dev->dev_addr[j] = readb(base + (j<<1));
     }
-    
+
     iounmap(virt);
     j = pcmcia_release_window(link->win);
     if (j != CS_SUCCESS)
@@ -490,7 +490,7 @@
 	if (link->io.NumPorts2 > 0) {
 	    /* for master/slave multifunction cards */
 	    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
-	    link->irq.Attributes = 
+	    link->irq.Attributes =
 		IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
 	}
     } else {
@@ -543,19 +543,19 @@
 	manfid = le16_to_cpu(buf[0]);
 	prodid = le16_to_cpu(buf[1]);
     }
-    
+
     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
     tuple.Attributes = 0;
     CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
     while (last_ret == CS_SUCCESS) {
 	cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 	cistpl_io_t *io = &(parse.cftable_entry.io);
-	
+
 	if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
 			pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
 			cfg->index == 0 || cfg->io.nwin == 0)
 		goto next_entry;
-	
+
 	link->conf.ConfigIndex = cfg->index;
 	/* For multifunction cards, by convention, we configure the
 	   network function with window 0, and serial with window 1 */
@@ -584,7 +584,7 @@
     }
 
     CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
-    
+
     if (link->io.NumPorts2 == 8) {
 	link->conf.Attributes |= CONF_ENABLE_SPKR;
 	link->conf.Status = CCSR_AUDIO_ENA;
@@ -592,7 +592,7 @@
     if ((manfid == MANFID_IBM) &&
 	(prodid == PRODID_IBM_HOME_AND_AWAY))
 	link->conf.ConfigIndex |= 0x10;
-    
+
     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
@@ -614,7 +614,7 @@
 	hw_info = get_ax88190(link);
     if (hw_info == NULL)
 	hw_info = get_hwired(link);
-    
+
     if (hw_info == NULL) {
 	printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
 	       " address for io base %#3lx\n", dev->base_addr);
@@ -631,7 +631,7 @@
 	info->flags &= ~USE_BIG_BUF;
     if (!use_big_buf)
 	info->flags &= ~USE_BIG_BUF;
-    
+
     if (info->flags & USE_BIG_BUF) {
 	start_pg = SOCKET_START_PG;
 	stop_pg = SOCKET_STOP_PG;
@@ -929,7 +929,7 @@
     kio_addr_t nic_base = dev->base_addr;
     pcnet_dev_t *info = PRIV(dev);
     u_char tmp;
-    
+
     if (info->flags & HAS_MISC_REG) {
 	tmp = inb_p(nic_base + PCNET_MISC) & ~3;
 	if (dev->if_port == 2)
@@ -1022,7 +1022,7 @@
 
     ei_close(dev);
     free_irq(dev->irq, dev);
-    
+
     link->open--;
     netif_stop_queue(dev);
     del_timer_sync(&info->watchdog);
@@ -1054,12 +1054,12 @@
 	udelay(100);
     }
     outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
-    
+
     if (i == 100)
 	printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n",
 	       dev->name);
     set_misc_reg(dev);
-    
+
 } /* pcnet_reset_8390 */
 
 /*====================================================================*/
@@ -1233,7 +1233,7 @@
 	       dev->name, ei_status.dmaing, ei_status.irqlock);
 	return;
     }
-    
+
     ei_status.dmaing |= 0x01;
     outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
     outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
@@ -1458,7 +1458,7 @@
     void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
 				+ (ring_page << 8)
 				- (ei_status.rx_start_page << 8);
-    
+
     copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
     /* Fix for big endian systems */
     hdr->count = le16_to_cpu(hdr->count);
@@ -1473,7 +1473,7 @@
     unsigned long offset = (TX_PAGES<<8) + ring_offset
 				- (ei_status.rx_start_page << 8);
     char *buf = skb->data;
-    
+
     if (offset + count > ei_status.priv) {
 	/* We must wrap the input move. */
 	int semi_count = ei_status.priv - offset;
@@ -1541,7 +1541,7 @@
 	info->base = NULL; link->win = NULL;
 	goto failed;
     }
-    
+
     ei_status.mem = info->base + offset;
     ei_status.priv = req.Size;
     dev->mem_start = (u_long)ei_status.mem;
@@ -1768,6 +1768,8 @@
 	PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"),
 	PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"),
 	PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"),
+	PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
+		0xb4be14e3, 0x43ac239b, 0x0877b627),
 	PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index e74bf50..a73d545 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -1883,7 +1883,7 @@
     /* Set the Window 1 control, configuration and station addr registers.
        No point in writing the I/O base register ;-> */
     SMC_SELECT_BANK(1);
-    /* Automatically release succesfully transmitted packets,
+    /* Automatically release successfully transmitted packets,
        Accept link errors, counter and Tx error interrupts. */
     outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE,
 	 ioaddr + CONTROL);
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index 71f4505..9bae77c 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -1359,7 +1359,7 @@
     kio_addr_t ioaddr = dev->base_addr;
     int okay;
     unsigned freespace;
-    unsigned pktlen = skb? skb->len : 0;
+    unsigned pktlen = skb->len;
 
     DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",
 	  skb, dev, pktlen);
@@ -1374,8 +1374,7 @@
      */
     if (pktlen < ETH_ZLEN)
     {
-        skb = skb_padto(skb, ETH_ZLEN);
-        if (skb == NULL)
+        if (skb_padto(skb, ETH_ZLEN))
         	return 0;
 	pktlen = ETH_ZLEN;
     }
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index fc08c4a..0e01c75 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -309,12 +309,6 @@
 static void pcnet32_free_ring(struct net_device *dev);
 static void pcnet32_check_media(struct net_device *dev, int verbose);
 
-enum pci_flags_bit {
-	PCI_USES_IO = 1, PCI_USES_MEM = 2, PCI_USES_MASTER = 4,
-	PCI_ADDR0 = 0x10 << 0, PCI_ADDR1 = 0x10 << 1, PCI_ADDR2 =
-	    0x10 << 2, PCI_ADDR3 = 0x10 << 3,
-};
-
 static u16 pcnet32_wio_read_csr(unsigned long addr, int index)
 {
 	outw(index, addr + PCNET32_WIO_RAP);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index fa39b94..2ba6d3a 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -44,6 +44,17 @@
 	depends on PHYLIB
 	---help---
 	  Currently supports the cis8204
+config VITESSE_PHY
+        tristate "Drivers for the Vitesse PHYs"
+        depends on PHYLIB
+        ---help---
+          Currently supports the vsc8244
+
+config SMSC_PHY
+	tristate "Drivers for SMSC PHYs"
+	depends on PHYLIB
+	---help---
+	  Currently supports the LAN83C185 PHY
 
 endmenu
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e4116a5..a00e619 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -8,3 +8,5 @@
 obj-$(CONFIG_CICADA_PHY)	+= cicada.o
 obj-$(CONFIG_LXT_PHY)		+= lxt.o
 obj-$(CONFIG_QSEMI_PHY)		+= qsemi.o
+obj-$(CONFIG_SMSC_PHY)		+= smsc.o
+obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index bef79e4..3f702c5 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -123,9 +123,9 @@
 }
 
 static struct phy_driver lxt970_driver = {
-	.phy_id		= 0x07810000,
+	.phy_id		= 0x78100000,
 	.name		= "LXT970",
-	.phy_id_mask	= 0x0fffffff,
+	.phy_id_mask	= 0xfffffff0,
 	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_init	= lxt970_config_init,
@@ -137,9 +137,9 @@
 };
 
 static struct phy_driver lxt971_driver = {
-	.phy_id		= 0x0001378e,
+	.phy_id		= 0x001378e0,
 	.name		= "LXT971",
-	.phy_id_mask	= 0x0fffffff,
+	.phy_id_mask	= 0xfffffff0,
 	.features	= PHY_BASIC_FEATURES,
 	.flags		= PHY_HAS_INTERRUPT,
 	.config_aneg	= genphy_config_aneg,
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644
index 0000000..25e31fb
--- /dev/null
+++ b/drivers/net/phy/smsc.c
@@ -0,0 +1,101 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM  30 /* Interrupt Mask */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+	(MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4)
+
+
+static int lan83c185_config_intr(struct phy_device *phydev)
+{
+	int rc = phy_write (phydev, MII_LAN83C185_IM,
+			((PHY_INTERRUPT_ENABLED == phydev->interrupts)
+			? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
+			: 0));
+
+	return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_ack_interrupt(struct phy_device *phydev)
+{
+	int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+	return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_config_init(struct phy_device *phydev)
+{
+	return lan83c185_ack_interrupt (phydev);
+}
+
+
+static struct phy_driver lan83c185_driver = {
+	.phy_id		= 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+	.phy_id_mask	= 0xfffffff0,
+	.name		= "SMSC LAN83C185",
+
+	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
+				| SUPPORTED_Asym_Pause),
+	.flags		= PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+	/* basic functions */
+	.config_aneg	= genphy_config_aneg,
+	.read_status	= genphy_read_status,
+	.config_init	= lan83c185_config_init,
+
+	/* IRQ related */
+	.ack_interrupt	= lan83c185_ack_interrupt,
+	.config_intr	= lan83c185_config_intr,
+
+	.driver		= { .owner = THIS_MODULE, }
+};
+
+static int __init smsc_init(void)
+{
+	return phy_driver_register (&lan83c185_driver);
+}
+
+static void __exit smsc_exit(void)
+{
+	phy_driver_unregister (&lan83c185_driver);
+}
+
+MODULE_DESCRIPTION("SMSC PHY driver");
+MODULE_AUTHOR("Herbert Valerio Riedel");
+MODULE_LICENSE("GPL");
+
+module_init(smsc_init);
+module_exit(smsc_exit);
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
new file mode 100644
index 0000000..ffd215d
--- /dev/null
+++ b/drivers/net/phy/vitesse.c
@@ -0,0 +1,112 @@
+/*
+ * Driver for Vitesse PHYs
+ *
+ * Author: Kriston Carson
+ *
+ * Copyright (c) 2005 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+
+/* Vitesse Extended Control Register 1 */
+#define MII_VSC8244_EXT_CON1           0x17
+#define MII_VSC8244_EXTCON1_INIT       0x0000
+
+/* Vitesse Interrupt Mask Register */
+#define MII_VSC8244_IMASK		0x19
+#define MII_VSC8244_IMASK_IEN		0x8000
+#define MII_VSC8244_IMASK_SPEED		0x4000
+#define MII_VSC8244_IMASK_LINK		0x2000
+#define MII_VSC8244_IMASK_DUPLEX	0x1000
+#define MII_VSC8244_IMASK_MASK		0xf000
+
+/* Vitesse Interrupt Status Register */
+#define MII_VSC8244_ISTAT		0x1a
+#define MII_VSC8244_ISTAT_STATUS	0x8000
+#define MII_VSC8244_ISTAT_SPEED		0x4000
+#define MII_VSC8244_ISTAT_LINK		0x2000
+#define MII_VSC8244_ISTAT_DUPLEX	0x1000
+
+/* Vitesse Auxiliary Control/Status Register */
+#define MII_VSC8244_AUX_CONSTAT        	0x1c
+#define MII_VSC8244_AUXCONSTAT_INIT    	0x0004
+#define MII_VSC8244_AUXCONSTAT_DUPLEX  	0x0020
+#define MII_VSC8244_AUXCONSTAT_SPEED   	0x0018
+#define MII_VSC8244_AUXCONSTAT_GBIT    	0x0010
+#define MII_VSC8244_AUXCONSTAT_100     	0x0008
+
+MODULE_DESCRIPTION("Vitesse PHY driver");
+MODULE_AUTHOR("Kriston Carson");
+MODULE_LICENSE("GPL");
+
+static int vsc824x_config_init(struct phy_device *phydev)
+{
+	int err;
+
+	err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT,
+			MII_VSC8244_AUXCONSTAT_INIT);
+	if (err < 0)
+		return err;
+
+	err = phy_write(phydev, MII_VSC8244_EXT_CON1,
+			MII_VSC8244_EXTCON1_INIT);
+	return err;
+}
+
+static int vsc824x_ack_interrupt(struct phy_device *phydev)
+{
+	int err = phy_read(phydev, MII_VSC8244_ISTAT);
+
+	return (err < 0) ? err : 0;
+}
+
+static int vsc824x_config_intr(struct phy_device *phydev)
+{
+	int err;
+
+	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+		err = phy_write(phydev, MII_VSC8244_IMASK,
+				MII_VSC8244_IMASK_MASK);
+	else
+		err = phy_write(phydev, MII_VSC8244_IMASK, 0);
+	return err;
+}
+
+/* Vitesse 824x */
+static struct phy_driver vsc8244_driver = {
+	.phy_id		= 0x000fc6c2,
+	.name		= "Vitesse VSC8244",
+	.phy_id_mask	= 0x000fffc0,
+	.features	= PHY_GBIT_FEATURES,
+	.flags		= PHY_HAS_INTERRUPT,
+	.config_init	= &vsc824x_config_init,
+	.config_aneg	= &genphy_config_aneg,
+	.read_status	= &genphy_read_status,
+	.ack_interrupt	= &vsc824x_ack_interrupt,
+	.config_intr	= &vsc824x_config_intr,
+	.driver 	= { .owner = THIS_MODULE,},
+};
+
+static int __init vsc8244_init(void)
+{
+	return phy_driver_register(&vsc8244_driver);
+}
+
+static void __exit vsc8244_exit(void)
+{
+	phy_driver_unregister(&vsc8244_driver);
+}
+
+module_init(vsc8244_init);
+module_exit(vsc8244_exit);
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index b2073fc..d643a09 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -1609,8 +1609,6 @@
 			kfree_skb(skb);
 			skb = ns;
 		}
-		else if (!pskb_may_pull(skb, skb->len))
-			goto err;
 		else
 			skb->ip_summed = CHECKSUM_NONE;
 
@@ -2580,8 +2578,7 @@
 
 	list_for_each_entry(pch, &new_channels, list) {
 		if (pch->file.index == unit) {
-			list_del(&pch->list);
-			list_add(&pch->list, &all_channels);
+			list_move(&pch->list, &all_channels);
 			return pch;
 		}
 	}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 0ad3310..12d1cb2 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -184,6 +184,7 @@
 
 static struct pci_device_id rtl8169_pci_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8169), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8129), },
 	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK,	0x4300), },
 	{ PCI_DEVICE(0x16ec,			0x0116), },
 	{ PCI_VENDOR_ID_LINKSYS,		0x1032, PCI_ANY_ID, 0x0024, },
@@ -2171,7 +2172,7 @@
 static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
 {
 	if (dev->features & NETIF_F_TSO) {
-		u32 mss = skb_shinfo(skb)->tso_size;
+		u32 mss = skb_shinfo(skb)->gso_size;
 
 		if (mss)
 			return LargeSend | ((mss & MSSMask) << MSSShift);
@@ -2221,8 +2222,7 @@
 		len = skb->len;
 
 		if (unlikely(len < ETH_ZLEN)) {
-			skb = skb_padto(skb, ETH_ZLEN);
-			if (!skb)
+			if (skb_padto(skb, ETH_ZLEN))
 				goto err_update_stats;
 			len = ETH_ZLEN;
 		}
diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h
index 00179bc..0ef5258 100644
--- a/drivers/net/s2io-regs.h
+++ b/drivers/net/s2io-regs.h
@@ -167,6 +167,7 @@
 	u8 unused4[0x08];
 
 	u64 gpio_int_reg;
+#define GPIO_INT_REG_DP_ERR_INT                BIT(0)
 #define GPIO_INT_REG_LINK_DOWN                 BIT(1)
 #define GPIO_INT_REG_LINK_UP                   BIT(2)
 	u64 gpio_int_mask;
@@ -187,7 +188,7 @@
 /* PIC Control registers */
 	u64 pic_control;
 #define PIC_CNTL_RX_ALARM_MAP_1                BIT(0)
-#define PIC_CNTL_SHARED_SPLITS(n)              vBIT(n,11,4)
+#define PIC_CNTL_SHARED_SPLITS(n)              vBIT(n,11,5)
 
 	u64 swapper_ctrl;
 #define SWAPPER_CTRL_PIF_R_FE                  BIT(0)
@@ -267,6 +268,21 @@
 
 	/* General Configuration */
 	u64 mdio_control;
+#define MDIO_MMD_INDX_ADDR(val)		vBIT(val, 0, 16)
+#define MDIO_MMD_DEV_ADDR(val)		vBIT(val, 19, 5)
+#define MDIO_MMD_PMA_DEV_ADDR		0x1
+#define MDIO_MMD_PMD_DEV_ADDR		0x1
+#define MDIO_MMD_WIS_DEV_ADDR		0x2
+#define MDIO_MMD_PCS_DEV_ADDR		0x3
+#define MDIO_MMD_PHYXS_DEV_ADDR		0x4
+#define MDIO_MMS_PRT_ADDR(val)		vBIT(val, 27, 5)
+#define MDIO_CTRL_START_TRANS(val)	vBIT(val, 56, 4)
+#define MDIO_OP(val)			vBIT(val, 60, 2)
+#define MDIO_OP_ADDR_TRANS		0x0
+#define MDIO_OP_WRITE_TRANS		0x1
+#define MDIO_OP_READ_POST_INC_TRANS	0x2
+#define MDIO_OP_READ_TRANS		0x3
+#define MDIO_MDIO_DATA(val)		vBIT(val, 32, 16)
 
 	u64 dtx_control;
 
@@ -284,9 +300,13 @@
 	u64 gpio_control;
 #define GPIO_CTRL_GPIO_0		BIT(8)
 	u64 misc_control;
+#define EXT_REQ_EN			BIT(1)
 #define MISC_LINK_STABILITY_PRD(val)   vBIT(val,29,3)
 
-	u8 unused7_1[0x240 - 0x208];
+	u8 unused7_1[0x230 - 0x208];
+
+	u64 pic_control2;
+	u64 ini_dperr_ctrl;
 
 	u64 wreq_split_mask;
 #define	WREQ_SPLIT_MASK_SET_MASK(val)	vBIT(val, 52, 12)
@@ -493,6 +513,7 @@
 #define PRC_CTRL_NO_SNOOP_DESC                 BIT(22)
 #define PRC_CTRL_NO_SNOOP_BUFF                 BIT(23)
 #define PRC_CTRL_BIMODAL_INTERRUPT             BIT(37)
+#define PRC_CTRL_GROUP_READS                   BIT(38)
 #define PRC_CTRL_RXD_BACKOFF_INTERVAL(val)     vBIT(val,40,24)
 
 	u64 prc_alarm_action;
@@ -541,7 +562,12 @@
 #define RX_PA_CFG_IGNORE_LLC_CTRL          BIT(3)
 #define RX_PA_CFG_IGNORE_L2_ERR            BIT(6)
 
-	u8 unused12[0x700 - 0x1D8];
+	u64 unused_11_1;
+
+	u64 ring_bump_counter1;
+	u64 ring_bump_counter2;
+
+	u8 unused12[0x700 - 0x1F0];
 
 	u64 rxdma_debug_ctrl;
 
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 79208f4..3defe5d 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -26,15 +26,22 @@
  *
  * The module loadable parameters that are supported by the driver and a brief
  * explaination of all the variables.
+ *
  * rx_ring_num : This can be used to program the number of receive rings used
  * in the driver.
- * rx_ring_sz: This defines the number of descriptors each ring can have. This
- * is also an array of size 8.
+ * rx_ring_sz: This defines the number of receive blocks each ring can have.
+ *     This is also an array of size 8.
  * rx_ring_mode: This defines the operation mode of all 8 rings. The valid
  *		values are 1, 2 and 3.
  * tx_fifo_num: This defines the number of Tx FIFOs thats used int the driver.
  * tx_fifo_len: This too is an array of 8. Each element defines the number of
  * Tx descriptors that can be associated with each corresponding FIFO.
+ * intr_type: This defines the type of interrupt. The values can be 0(INTA),
+ *     1(MSI), 2(MSI_X). Default value is '0(INTA)'
+ * lro: Specifies whether to enable Large Receive Offload (LRO) or not.
+ *     Possible values '1' for enable '0' for disable. Default is '0'
+ * lro_max_pkts: This parameter defines maximum number of packets can be
+ *     aggregated as a single large packet
  ************************************************************************/
 
 #include <linux/config.h>
@@ -70,7 +77,7 @@
 #include "s2io.h"
 #include "s2io-regs.h"
 
-#define DRV_VERSION "2.0.11.2"
+#define DRV_VERSION "2.0.14.2"
 
 /* S2io Driver name & version. */
 static char s2io_driver_name[] = "Neterion";
@@ -106,18 +113,14 @@
 #define LOW	2
 static inline int rx_buffer_level(nic_t * sp, int rxb_size, int ring)
 {
-	int level = 0;
 	mac_info_t *mac_control;
 
 	mac_control = &sp->mac_control;
-	if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) {
-		level = LOW;
-		if (rxb_size <= rxd_count[sp->rxd_mode]) {
-			level = PANIC;
-		}
-	}
-
-	return level;
+	if (rxb_size <= rxd_count[sp->rxd_mode])
+		return PANIC;
+	else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16)
+		return  LOW;
+	return 0;
 }
 
 /* Ethtool related variables and Macros. */
@@ -136,7 +139,11 @@
 	{"tmac_mcst_frms"},
 	{"tmac_bcst_frms"},
 	{"tmac_pause_ctrl_frms"},
+	{"tmac_ttl_octets"},
+	{"tmac_ucst_frms"},
+	{"tmac_nucst_frms"},
 	{"tmac_any_err_frms"},
+	{"tmac_ttl_less_fb_octets"},
 	{"tmac_vld_ip_octets"},
 	{"tmac_vld_ip"},
 	{"tmac_drop_ip"},
@@ -151,13 +158,27 @@
 	{"rmac_vld_mcst_frms"},
 	{"rmac_vld_bcst_frms"},
 	{"rmac_in_rng_len_err_frms"},
+	{"rmac_out_rng_len_err_frms"},
 	{"rmac_long_frms"},
 	{"rmac_pause_ctrl_frms"},
+	{"rmac_unsup_ctrl_frms"},
+	{"rmac_ttl_octets"},
+	{"rmac_accepted_ucst_frms"},
+	{"rmac_accepted_nucst_frms"},
 	{"rmac_discarded_frms"},
+	{"rmac_drop_events"},
+	{"rmac_ttl_less_fb_octets"},
+	{"rmac_ttl_frms"},
 	{"rmac_usized_frms"},
 	{"rmac_osized_frms"},
 	{"rmac_frag_frms"},
 	{"rmac_jabber_frms"},
+	{"rmac_ttl_64_frms"},
+	{"rmac_ttl_65_127_frms"},
+	{"rmac_ttl_128_255_frms"},
+	{"rmac_ttl_256_511_frms"},
+	{"rmac_ttl_512_1023_frms"},
+	{"rmac_ttl_1024_1518_frms"},
 	{"rmac_ip"},
 	{"rmac_ip_octets"},
 	{"rmac_hdr_err_ip"},
@@ -166,12 +187,82 @@
 	{"rmac_tcp"},
 	{"rmac_udp"},
 	{"rmac_err_drp_udp"},
+	{"rmac_xgmii_err_sym"},
+	{"rmac_frms_q0"},
+	{"rmac_frms_q1"},
+	{"rmac_frms_q2"},
+	{"rmac_frms_q3"},
+	{"rmac_frms_q4"},
+	{"rmac_frms_q5"},
+	{"rmac_frms_q6"},
+	{"rmac_frms_q7"},
+	{"rmac_full_q0"},
+	{"rmac_full_q1"},
+	{"rmac_full_q2"},
+	{"rmac_full_q3"},
+	{"rmac_full_q4"},
+	{"rmac_full_q5"},
+	{"rmac_full_q6"},
+	{"rmac_full_q7"},
 	{"rmac_pause_cnt"},
+	{"rmac_xgmii_data_err_cnt"},
+	{"rmac_xgmii_ctrl_err_cnt"},
 	{"rmac_accepted_ip"},
 	{"rmac_err_tcp"},
+	{"rd_req_cnt"},
+	{"new_rd_req_cnt"},
+	{"new_rd_req_rtry_cnt"},
+	{"rd_rtry_cnt"},
+	{"wr_rtry_rd_ack_cnt"},
+	{"wr_req_cnt"},
+	{"new_wr_req_cnt"},
+	{"new_wr_req_rtry_cnt"},
+	{"wr_rtry_cnt"},
+	{"wr_disc_cnt"},
+	{"rd_rtry_wr_ack_cnt"},
+	{"txp_wr_cnt"},
+	{"txd_rd_cnt"},
+	{"txd_wr_cnt"},
+	{"rxd_rd_cnt"},
+	{"rxd_wr_cnt"},
+	{"txf_rd_cnt"},
+	{"rxf_wr_cnt"},
+	{"rmac_ttl_1519_4095_frms"},
+	{"rmac_ttl_4096_8191_frms"},
+	{"rmac_ttl_8192_max_frms"},
+	{"rmac_ttl_gt_max_frms"},
+	{"rmac_osized_alt_frms"},
+	{"rmac_jabber_alt_frms"},
+	{"rmac_gt_max_alt_frms"},
+	{"rmac_vlan_frms"},
+	{"rmac_len_discard"},
+	{"rmac_fcs_discard"},
+	{"rmac_pf_discard"},
+	{"rmac_da_discard"},
+	{"rmac_red_discard"},
+	{"rmac_rts_discard"},
+	{"rmac_ingm_full_discard"},
+	{"link_fault_cnt"},
 	{"\n DRIVER STATISTICS"},
 	{"single_bit_ecc_errs"},
 	{"double_bit_ecc_errs"},
+	{"parity_err_cnt"},
+	{"serious_err_cnt"},
+	{"soft_reset_cnt"},
+	{"fifo_full_cnt"},
+	{"ring_full_cnt"},
+	("alarm_transceiver_temp_high"),
+	("alarm_transceiver_temp_low"),
+	("alarm_laser_bias_current_high"),
+	("alarm_laser_bias_current_low"),
+	("alarm_laser_output_power_high"),
+	("alarm_laser_output_power_low"),
+	("warn_transceiver_temp_high"),
+	("warn_transceiver_temp_low"),
+	("warn_laser_bias_current_high"),
+	("warn_laser_bias_current_low"),
+	("warn_laser_output_power_high"),
+	("warn_laser_output_power_low"),
 	("lro_aggregated_pkts"),
 	("lro_flush_both_count"),
 	("lro_out_of_sequence_pkts"),
@@ -220,9 +311,7 @@
  * the XAUI.
  */
 
-#define SWITCH_SIGN	0xA5A5A5A5A5A5A5A5ULL
 #define	END_SIGN	0x0
-
 static const u64 herc_act_dtx_cfg[] = {
 	/* Set address */
 	0x8000051536750000ULL, 0x80000515367500E0ULL,
@@ -244,37 +333,19 @@
 	END_SIGN
 };
 
-static const u64 xena_mdio_cfg[] = {
-	/* Reset PMA PLL */
-	0xC001010000000000ULL, 0xC0010100000000E0ULL,
-	0xC0010100008000E4ULL,
-	/* Remove Reset from PMA PLL */
-	0xC001010000000000ULL, 0xC0010100000000E0ULL,
-	0xC0010100000000E4ULL,
-	END_SIGN
-};
-
 static const u64 xena_dtx_cfg[] = {
+	/* Set address */
 	0x8000051500000000ULL, 0x80000515000000E0ULL,
-	0x80000515D93500E4ULL, 0x8001051500000000ULL,
-	0x80010515000000E0ULL, 0x80010515001E00E4ULL,
+	/* Write data */
+	0x80000515D9350004ULL, 0x80000515D93500E4ULL,
+	/* Set address */
+	0x8001051500000000ULL, 0x80010515000000E0ULL,
+	/* Write data */
+	0x80010515001E0004ULL, 0x80010515001E00E4ULL,
+	/* Set address */
 	0x8002051500000000ULL, 0x80020515000000E0ULL,
-	0x80020515F21000E4ULL,
-	/* Set PADLOOPBACKN */
-	0x8002051500000000ULL, 0x80020515000000E0ULL,
-	0x80020515B20000E4ULL, 0x8003051500000000ULL,
-	0x80030515000000E0ULL, 0x80030515B20000E4ULL,
-	0x8004051500000000ULL, 0x80040515000000E0ULL,
-	0x80040515B20000E4ULL, 0x8005051500000000ULL,
-	0x80050515000000E0ULL, 0x80050515B20000E4ULL,
-	SWITCH_SIGN,
-	/* Remove PADLOOPBACKN */
-	0x8002051500000000ULL, 0x80020515000000E0ULL,
-	0x80020515F20000E4ULL, 0x8003051500000000ULL,
-	0x80030515000000E0ULL, 0x80030515F20000E4ULL,
-	0x8004051500000000ULL, 0x80040515000000E0ULL,
-	0x80040515F20000E4ULL, 0x8005051500000000ULL,
-	0x80050515000000E0ULL, 0x80050515F20000E4ULL,
+	/* Write data */
+	0x80020515F2100004ULL, 0x80020515F21000E4ULL,
 	END_SIGN
 };
 
@@ -303,15 +374,15 @@
 /* Module Loadable parameters. */
 static unsigned int tx_fifo_num = 1;
 static unsigned int tx_fifo_len[MAX_TX_FIFOS] =
-    {[0 ...(MAX_TX_FIFOS - 1)] = 0 };
+    {DEFAULT_FIFO_0_LEN, [1 ...(MAX_TX_FIFOS - 1)] = DEFAULT_FIFO_1_7_LEN};
 static unsigned int rx_ring_num = 1;
 static unsigned int rx_ring_sz[MAX_RX_RINGS] =
-    {[0 ...(MAX_RX_RINGS - 1)] = 0 };
+    {[0 ...(MAX_RX_RINGS - 1)] = SMALL_BLK_CNT};
 static unsigned int rts_frm_len[MAX_RX_RINGS] =
     {[0 ...(MAX_RX_RINGS - 1)] = 0 };
 static unsigned int rx_ring_mode = 1;
 static unsigned int use_continuous_tx_intrs = 1;
-static unsigned int rmac_pause_time = 65535;
+static unsigned int rmac_pause_time = 0x100;
 static unsigned int mc_pause_threshold_q0q3 = 187;
 static unsigned int mc_pause_threshold_q4q7 = 187;
 static unsigned int shared_splits;
@@ -549,11 +620,6 @@
 					rx_blocks->block_dma_addr +
 					(rxd_size[nic->rxd_mode] * l);
 			}
-
-			mac_control->rings[i].rx_blocks[j].block_virt_addr =
-				tmp_v_addr;
-			mac_control->rings[i].rx_blocks[j].block_dma_addr =
-				tmp_p_addr;
 		}
 		/* Interlinking all Rx Blocks */
 		for (j = 0; j < blk_cnt; j++) {
@@ -772,7 +838,21 @@
 	return mode;
 }
 
+#define NEC_VENID   0x1033
+#define NEC_DEVID   0x0125
+static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
+{
+	struct pci_dev *tdev = NULL;
+	while ((tdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
+		if ((tdev->vendor == NEC_VENID) && (tdev->device == NEC_DEVID)){
+			if (tdev->bus == s2io_pdev->bus->parent)
+				return 1;
+		}
+	}
+	return 0;
+}
 
+static int bus_speed[8] = {33, 133, 133, 200, 266, 133, 200, 266};
 /**
  * s2io_print_pci_mode -
  */
@@ -789,6 +869,14 @@
 	if ( val64 & PCI_MODE_UNKNOWN_MODE)
 		return -1;	/* Unknown PCI mode */
 
+	config->bus_speed = bus_speed[mode];
+
+	if (s2io_on_nec_bridge(nic->pdev)) {
+		DBG_PRINT(ERR_DBG, "%s: Device is on PCI-E bus\n",
+							nic->dev->name);
+		return mode;
+	}
+
 	if (val64 & PCI_MODE_32_BITS) {
 		DBG_PRINT(ERR_DBG, "%s: Device is on 32 bit ", nic->dev->name);
 	} else {
@@ -798,35 +886,27 @@
 	switch(mode) {
 		case PCI_MODE_PCI_33:
 			DBG_PRINT(ERR_DBG, "33MHz PCI bus\n");
-			config->bus_speed = 33;
 			break;
 		case PCI_MODE_PCI_66:
 			DBG_PRINT(ERR_DBG, "66MHz PCI bus\n");
-			config->bus_speed = 133;
 			break;
 		case PCI_MODE_PCIX_M1_66:
 			DBG_PRINT(ERR_DBG, "66MHz PCIX(M1) bus\n");
-			config->bus_speed = 133; /* Herc doubles the clock rate */
 			break;
 		case PCI_MODE_PCIX_M1_100:
 			DBG_PRINT(ERR_DBG, "100MHz PCIX(M1) bus\n");
-			config->bus_speed = 200;
 			break;
 		case PCI_MODE_PCIX_M1_133:
 			DBG_PRINT(ERR_DBG, "133MHz PCIX(M1) bus\n");
-			config->bus_speed = 266;
 			break;
 		case PCI_MODE_PCIX_M2_66:
 			DBG_PRINT(ERR_DBG, "133MHz PCIX(M2) bus\n");
-			config->bus_speed = 133;
 			break;
 		case PCI_MODE_PCIX_M2_100:
 			DBG_PRINT(ERR_DBG, "200MHz PCIX(M2) bus\n");
-			config->bus_speed = 200;
 			break;
 		case PCI_MODE_PCIX_M2_133:
 			DBG_PRINT(ERR_DBG, "266MHz PCIX(M2) bus\n");
-			config->bus_speed = 266;
 			break;
 		default:
 			return -1;	/* Unsupported bus speed */
@@ -854,7 +934,7 @@
 	int i, j;
 	mac_info_t *mac_control;
 	struct config_param *config;
-	int mdio_cnt = 0, dtx_cnt = 0;
+	int dtx_cnt = 0;
 	unsigned long long mem_share;
 	int mem_size;
 
@@ -901,20 +981,6 @@
 	val64 = dev->mtu;
 	writeq(vBIT(val64, 2, 14), &bar0->rmac_max_pyld_len);
 
-	/*
-	 * Configuring the XAUI Interface of Xena.
-	 * ***************************************
-	 * To Configure the Xena's XAUI, one has to write a series
-	 * of 64 bit values into two registers in a particular
-	 * sequence. Hence a macro 'SWITCH_SIGN' has been defined
-	 * which will be defined in the array of configuration values
-	 * (xena_dtx_cfg & xena_mdio_cfg) at appropriate places
-	 * to switch writing from one regsiter to another. We continue
-	 * writing these values until we encounter the 'END_SIGN' macro.
-	 * For example, After making a series of 21 writes into
-	 * dtx_control register the 'SWITCH_SIGN' appears and hence we
-	 * start writing into mdio_control until we encounter END_SIGN.
-	 */
 	if (nic->device_type & XFRAME_II_DEVICE) {
 		while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) {
 			SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt],
@@ -924,35 +990,11 @@
 			dtx_cnt++;
 		}
 	} else {
-		while (1) {
-		      dtx_cfg:
-			while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
-				if (xena_dtx_cfg[dtx_cnt] == SWITCH_SIGN) {
-					dtx_cnt++;
-					goto mdio_cfg;
-				}
-				SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
-						  &bar0->dtx_control, UF);
-				val64 = readq(&bar0->dtx_control);
-				dtx_cnt++;
-			}
-		      mdio_cfg:
-			while (xena_mdio_cfg[mdio_cnt] != END_SIGN) {
-				if (xena_mdio_cfg[mdio_cnt] == SWITCH_SIGN) {
-					mdio_cnt++;
-					goto dtx_cfg;
-				}
-				SPECIAL_REG_WRITE(xena_mdio_cfg[mdio_cnt],
-						  &bar0->mdio_control, UF);
-				val64 = readq(&bar0->mdio_control);
-				mdio_cnt++;
-			}
-			if ((xena_dtx_cfg[dtx_cnt] == END_SIGN) &&
-			    (xena_mdio_cfg[mdio_cnt] == END_SIGN)) {
-				break;
-			} else {
-				goto dtx_cfg;
-			}
+		while (xena_dtx_cfg[dtx_cnt] != END_SIGN) {
+			SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt],
+					  &bar0->dtx_control, UF);
+			val64 = readq(&bar0->dtx_control);
+			dtx_cnt++;
 		}
 	}
 
@@ -994,11 +1036,6 @@
 		}
 	}
 
-	/* Enable Tx FIFO partition 0. */
-	val64 = readq(&bar0->tx_fifo_partition_0);
-	val64 |= BIT(0);	/* To enable the FIFO partition. */
-	writeq(val64, &bar0->tx_fifo_partition_0);
-
 	/*
 	 * Disable 4 PCCs for Xena1, 2 and 3 as per H/W bug
 	 * SXE-008 TRANSMIT DMA ARBITRATION ISSUE.
@@ -1177,6 +1214,11 @@
 		break;
 	}
 
+	/* Enable Tx FIFO partition 0. */
+	val64 = readq(&bar0->tx_fifo_partition_0);
+	val64 |= (TX_FIFO_PARTITION_EN);
+	writeq(val64, &bar0->tx_fifo_partition_0);
+
 	/* Filling the Rx round robin registers as per the
 	 * number of Rings and steering based on QoS.
          */
@@ -1545,19 +1587,26 @@
 	val64 |= PIC_CNTL_SHARED_SPLITS(shared_splits);
 	writeq(val64, &bar0->pic_control);
 
+	if (nic->config.bus_speed == 266) {
+		writeq(TXREQTO_VAL(0x7f) | TXREQTO_EN, &bar0->txreqtimeout);
+		writeq(0x0, &bar0->read_retry_delay);
+		writeq(0x0, &bar0->write_retry_delay);
+	}
+
 	/*
 	 * Programming the Herc to split every write transaction
 	 * that does not start on an ADB to reduce disconnects.
 	 */
 	if (nic->device_type == XFRAME_II_DEVICE) {
-		val64 = WREQ_SPLIT_MASK_SET_MASK(255);
-		writeq(val64, &bar0->wreq_split_mask);
-	}
-
-	/* Setting Link stability period to 64 ms */ 
-	if (nic->device_type == XFRAME_II_DEVICE) {
-		val64 = MISC_LINK_STABILITY_PRD(3);
+		val64 = EXT_REQ_EN | MISC_LINK_STABILITY_PRD(3);
 		writeq(val64, &bar0->misc_control);
+		val64 = readq(&bar0->pic_control2);
+		val64 &= ~(BIT(13)|BIT(14)|BIT(15));
+		writeq(val64, &bar0->pic_control2);
+	}
+	if (strstr(nic->product_name, "CX4")) {
+		val64 = TMAC_AVG_IPG(0x17);
+		writeq(val64, &bar0->tmac_avg_ipg);
 	}
 
 	return SUCCESS;
@@ -1948,6 +1997,10 @@
 			val64 |= PRC_CTRL_RC_ENABLED;
 		else
 			val64 |= PRC_CTRL_RC_ENABLED | PRC_CTRL_RING_MODE_3;
+		if (nic->device_type == XFRAME_II_DEVICE)
+			val64 |= PRC_CTRL_GROUP_READS;
+		val64 &= ~PRC_CTRL_RXD_BACKOFF_INTERVAL(0xFFFFFF);
+		val64 |= PRC_CTRL_RXD_BACKOFF_INTERVAL(0x1000);
 		writeq(val64, &bar0->prc_ctrl_n[i]);
 	}
 
@@ -2018,6 +2071,13 @@
 	val64 |= ADAPTER_EOI_TX_ON;
 	writeq(val64, &bar0->adapter_control);
 
+	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
+		/*
+		 * Dont see link state interrupts initally on some switches,
+		 * so directly scheduling the link state task here.
+		 */
+		schedule_work(&nic->set_link_task);
+	}
 	/* SXE-002: Initialize link and activity LED */
 	subid = nic->pdev->subsystem_device;
 	if (((subid & 0xFF) >= 0x07) &&
@@ -2029,12 +2089,6 @@
 		writeq(val64, (void __iomem *)bar0 + 0x2700);
 	}
 
-	/*
-	 * Don't see link state interrupts on certain switches, so
-	 * directly scheduling a link state task from here.
-	 */
-	schedule_work(&nic->set_link_task);
-
 	return SUCCESS;
 }
 /**
@@ -2134,7 +2188,7 @@
 {
 	XENA_dev_config_t __iomem *bar0 = nic->bar0;
 	register u64 val64 = 0;
-	u16 interruptible, i;
+	u16 interruptible;
 	mac_info_t *mac_control;
 	struct config_param *config;
 
@@ -2147,12 +2201,10 @@
 	interruptible |= TX_MAC_INTR | RX_MAC_INTR;
 	en_dis_able_nic_intrs(nic, interruptible, DISABLE_INTRS);
 
-	/*  Disable PRCs */
-	for (i = 0; i < config->rx_ring_num; i++) {
-		val64 = readq(&bar0->prc_ctrl_n[i]);
-		val64 &= ~((u64) PRC_CTRL_RC_ENABLED);
-		writeq(val64, &bar0->prc_ctrl_n[i]);
-	}
+	/* Clearing Adapter_En bit of ADAPTER_CONTROL Register */
+	val64 = readq(&bar0->adapter_control);
+	val64 &= ~(ADAPTER_CNTL_EN);
+	writeq(val64, &bar0->adapter_control);
 }
 
 static int fill_rxd_3buf(nic_t *nic, RxD_t *rxdp, struct sk_buff *skb)
@@ -2231,13 +2283,12 @@
 	alloc_cnt = mac_control->rings[ring_no].pkt_cnt -
 	    atomic_read(&nic->rx_bufs_left[ring_no]);
 
+	block_no1 = mac_control->rings[ring_no].rx_curr_get_info.block_index;
+	off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
 	while (alloc_tab < alloc_cnt) {
 		block_no = mac_control->rings[ring_no].rx_curr_put_info.
 		    block_index;
-		block_no1 = mac_control->rings[ring_no].rx_curr_get_info.
-		    block_index;
 		off = mac_control->rings[ring_no].rx_curr_put_info.offset;
-		off1 = mac_control->rings[ring_no].rx_curr_get_info.offset;
 
 		rxdp = mac_control->rings[ring_no].
 				rx_blocks[block_no].rxds[off].virt_addr;
@@ -2307,9 +2358,9 @@
 			memset(rxdp, 0, sizeof(RxD1_t));
 			skb_reserve(skb, NET_IP_ALIGN);
 			((RxD1_t*)rxdp)->Buffer0_ptr = pci_map_single
-			    (nic->pdev, skb->data, size, PCI_DMA_FROMDEVICE);
-			rxdp->Control_2 &= (~MASK_BUFFER0_SIZE_1);
-			rxdp->Control_2 |= SET_BUFFER0_SIZE_1(size);
+			    (nic->pdev, skb->data, size - NET_IP_ALIGN,
+				PCI_DMA_FROMDEVICE);
+			rxdp->Control_2 = SET_BUFFER0_SIZE_1(size - NET_IP_ALIGN);
 
 		} else if (nic->rxd_mode >= RXD_MODE_3A) {
 			/*
@@ -2516,7 +2567,7 @@
 	mac_info_t *mac_control;
 	struct config_param *config;
 	XENA_dev_config_t __iomem *bar0 = nic->bar0;
-	u64 val64;
+	u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
 	int i;
 
 	atomic_inc(&nic->isr_cnt);
@@ -2528,8 +2579,8 @@
 		nic->pkts_to_process = dev->quota;
 	org_pkts_to_process = nic->pkts_to_process;
 
-	val64 = readq(&bar0->rx_traffic_int);
 	writeq(val64, &bar0->rx_traffic_int);
+	val64 = readl(&bar0->rx_traffic_int);
 
 	for (i = 0; i < config->rx_ring_num; i++) {
 		rx_intr_handler(&mac_control->rings[i]);
@@ -2554,7 +2605,8 @@
 		}
 	}
 	/* Re enable the Rx interrupts. */
-	en_dis_able_nic_intrs(nic, RX_TRAFFIC_INTR, ENABLE_INTRS);
+	writeq(0x0, &bar0->rx_traffic_mask);
+	val64 = readl(&bar0->rx_traffic_mask);
 	atomic_dec(&nic->isr_cnt);
 	return 0;
 
@@ -2575,6 +2627,50 @@
 #endif
 
 /**
+ * s2io_netpoll - Rx interrupt service handler for netpoll support
+ * @dev : pointer to the device structure.
+ * Description:
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void s2io_netpoll(struct net_device *dev)
+{
+	nic_t *nic = dev->priv;
+	mac_info_t *mac_control;
+	struct config_param *config;
+	XENA_dev_config_t __iomem *bar0 = nic->bar0;
+	u64 val64;
+	int i;
+
+	disable_irq(dev->irq);
+
+	atomic_inc(&nic->isr_cnt);
+	mac_control = &nic->mac_control;
+	config = &nic->config;
+
+	val64 = readq(&bar0->rx_traffic_int);
+	writeq(val64, &bar0->rx_traffic_int);
+
+	for (i = 0; i < config->rx_ring_num; i++)
+		rx_intr_handler(&mac_control->rings[i]);
+
+	for (i = 0; i < config->rx_ring_num; i++) {
+		if (fill_rx_buffers(nic, i) == -ENOMEM) {
+			DBG_PRINT(ERR_DBG, "%s:Out of memory", dev->name);
+			DBG_PRINT(ERR_DBG, " in Rx Netpoll!!\n");
+			break;
+		}
+	}
+	atomic_dec(&nic->isr_cnt);
+	enable_irq(dev->irq);
+	return;
+}
+#endif
+
+/**
  *  rx_intr_handler - Rx interrupt handler
  *  @nic: device private variable.
  *  Description:
@@ -2666,6 +2762,7 @@
 					 ((RxD3_t*)rxdp)->Buffer2_ptr,
 					 dev->mtu, PCI_DMA_FROMDEVICE);
 		}
+		prefetch(skb->data);
 		rx_osm_handler(ring_data, rxdp);
 		get_info.offset++;
 		ring_data->rx_curr_get_info.offset = get_info.offset;
@@ -2737,6 +2834,10 @@
 		if (txdlp->Control_1 & TXD_T_CODE) {
 			unsigned long long err;
 			err = txdlp->Control_1 & TXD_T_CODE;
+			if (err & 0x1) {
+				nic->mac_control.stats_info->sw_stat.
+						parity_err_cnt++;
+			}
 			if ((err >> 48) == 0xA) {
 				DBG_PRINT(TX_DBG, "TxD returned due \
 to loss of link\n");
@@ -2760,7 +2861,8 @@
 		dev_kfree_skb_irq(skb);
 
 		get_info.offset++;
-		get_info.offset %= get_info.fifo_len + 1;
+		if (get_info.offset == get_info.fifo_len + 1)
+			get_info.offset = 0;
 		txdlp = (TxD_t *) fifo_data->list_info
 		    [get_info.offset].list_virt_addr;
 		fifo_data->tx_curr_get_info.offset =
@@ -2774,6 +2876,256 @@
 }
 
 /**
+ *  s2io_mdio_write - Function to write in to MDIO registers
+ *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
+ *  @addr     : address value
+ *  @value    : data value
+ *  @dev      : pointer to net_device structure
+ *  Description:
+ *  This function is used to write values to the MDIO registers
+ *  NONE
+ */
+static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev)
+{
+	u64 val64 = 0x0;
+	nic_t *sp = dev->priv;
+	XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+
+	//address transaction
+	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+			| MDIO_MMD_DEV_ADDR(mmd_type)
+			| MDIO_MMS_PRT_ADDR(0x0);
+	writeq(val64, &bar0->mdio_control);
+	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+	writeq(val64, &bar0->mdio_control);
+	udelay(100);
+
+	//Data transaction
+	val64 = 0x0;
+	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+			| MDIO_MMD_DEV_ADDR(mmd_type)
+			| MDIO_MMS_PRT_ADDR(0x0)
+			| MDIO_MDIO_DATA(value)
+			| MDIO_OP(MDIO_OP_WRITE_TRANS);
+	writeq(val64, &bar0->mdio_control);
+	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+	writeq(val64, &bar0->mdio_control);
+	udelay(100);
+
+	val64 = 0x0;
+	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+	| MDIO_MMD_DEV_ADDR(mmd_type)
+	| MDIO_MMS_PRT_ADDR(0x0)
+	| MDIO_OP(MDIO_OP_READ_TRANS);
+	writeq(val64, &bar0->mdio_control);
+	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+	writeq(val64, &bar0->mdio_control);
+	udelay(100);
+
+}
+
+/**
+ *  s2io_mdio_read - Function to write in to MDIO registers
+ *  @mmd_type : MMD type value (PMA/PMD/WIS/PCS/PHYXS)
+ *  @addr     : address value
+ *  @dev      : pointer to net_device structure
+ *  Description:
+ *  This function is used to read values to the MDIO registers
+ *  NONE
+ */
+static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
+{
+	u64 val64 = 0x0;
+	u64 rval64 = 0x0;
+	nic_t *sp = dev->priv;
+	XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+
+	/* address transaction */
+	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+			| MDIO_MMD_DEV_ADDR(mmd_type)
+			| MDIO_MMS_PRT_ADDR(0x0);
+	writeq(val64, &bar0->mdio_control);
+	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+	writeq(val64, &bar0->mdio_control);
+	udelay(100);
+
+	/* Data transaction */
+	val64 = 0x0;
+	val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
+			| MDIO_MMD_DEV_ADDR(mmd_type)
+			| MDIO_MMS_PRT_ADDR(0x0)
+			| MDIO_OP(MDIO_OP_READ_TRANS);
+	writeq(val64, &bar0->mdio_control);
+	val64 = val64 | MDIO_CTRL_START_TRANS(0xE);
+	writeq(val64, &bar0->mdio_control);
+	udelay(100);
+
+	/* Read the value from regs */
+	rval64 = readq(&bar0->mdio_control);
+	rval64 = rval64 & 0xFFFF0000;
+	rval64 = rval64 >> 16;
+	return rval64;
+}
+/**
+ *  s2io_chk_xpak_counter - Function to check the status of the xpak counters
+ *  @counter      : couter value to be updated
+ *  @flag         : flag to indicate the status
+ *  @type         : counter type
+ *  Description:
+ *  This function is to check the status of the xpak counters value
+ *  NONE
+ */
+
+static void s2io_chk_xpak_counter(u64 *counter, u64 * regs_stat, u32 index, u16 flag, u16 type)
+{
+	u64 mask = 0x3;
+	u64 val64;
+	int i;
+	for(i = 0; i <index; i++)
+		mask = mask << 0x2;
+
+	if(flag > 0)
+	{
+		*counter = *counter + 1;
+		val64 = *regs_stat & mask;
+		val64 = val64 >> (index * 0x2);
+		val64 = val64 + 1;
+		if(val64 == 3)
+		{
+			switch(type)
+			{
+			case 1:
+				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+					  "service. Excessive temperatures may "
+					  "result in premature transceiver "
+					  "failure \n");
+			break;
+			case 2:
+				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+					  "service Excessive bias currents may "
+					  "indicate imminent laser diode "
+					  "failure \n");
+			break;
+			case 3:
+				DBG_PRINT(ERR_DBG, "Take Xframe NIC out of "
+					  "service Excessive laser output "
+					  "power may saturate far-end "
+					  "receiver\n");
+			break;
+			default:
+				DBG_PRINT(ERR_DBG, "Incorrect XPAK Alarm "
+					  "type \n");
+			}
+			val64 = 0x0;
+		}
+		val64 = val64 << (index * 0x2);
+		*regs_stat = (*regs_stat & (~mask)) | (val64);
+
+	} else {
+		*regs_stat = *regs_stat & (~mask);
+	}
+}
+
+/**
+ *  s2io_updt_xpak_counter - Function to update the xpak counters
+ *  @dev         : pointer to net_device struct
+ *  Description:
+ *  This function is to upate the status of the xpak counters value
+ *  NONE
+ */
+static void s2io_updt_xpak_counter(struct net_device *dev)
+{
+	u16 flag  = 0x0;
+	u16 type  = 0x0;
+	u16 val16 = 0x0;
+	u64 val64 = 0x0;
+	u64 addr  = 0x0;
+
+	nic_t *sp = dev->priv;
+	StatInfo_t *stat_info = sp->mac_control.stats_info;
+
+	/* Check the communication with the MDIO slave */
+	addr = 0x0000;
+	val64 = 0x0;
+	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+	if((val64 == 0xFFFF) || (val64 == 0x0000))
+	{
+		DBG_PRINT(ERR_DBG, "ERR: MDIO slave access failed - "
+			  "Returned %llx\n", (unsigned long long)val64);
+		return;
+	}
+
+	/* Check for the expecte value of 2040 at PMA address 0x0000 */
+	if(val64 != 0x2040)
+	{
+		DBG_PRINT(ERR_DBG, "Incorrect value at PMA address 0x0000 - ");
+		DBG_PRINT(ERR_DBG, "Returned: %llx- Expected: 0x2040\n",
+			  (unsigned long long)val64);
+		return;
+	}
+
+	/* Loading the DOM register to MDIO register */
+	addr = 0xA100;
+	s2io_mdio_write(MDIO_MMD_PMA_DEV_ADDR, addr, val16, dev);
+	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+	/* Reading the Alarm flags */
+	addr = 0xA070;
+	val64 = 0x0;
+	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+	flag = CHECKBIT(val64, 0x7);
+	type = 1;
+	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_transceiver_temp_high,
+				&stat_info->xpak_stat.xpak_regs_stat,
+				0x0, flag, type);
+
+	if(CHECKBIT(val64, 0x6))
+		stat_info->xpak_stat.alarm_transceiver_temp_low++;
+
+	flag = CHECKBIT(val64, 0x3);
+	type = 2;
+	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_bias_current_high,
+				&stat_info->xpak_stat.xpak_regs_stat,
+				0x2, flag, type);
+
+	if(CHECKBIT(val64, 0x2))
+		stat_info->xpak_stat.alarm_laser_bias_current_low++;
+
+	flag = CHECKBIT(val64, 0x1);
+	type = 3;
+	s2io_chk_xpak_counter(&stat_info->xpak_stat.alarm_laser_output_power_high,
+				&stat_info->xpak_stat.xpak_regs_stat,
+				0x4, flag, type);
+
+	if(CHECKBIT(val64, 0x0))
+		stat_info->xpak_stat.alarm_laser_output_power_low++;
+
+	/* Reading the Warning flags */
+	addr = 0xA074;
+	val64 = 0x0;
+	val64 = s2io_mdio_read(MDIO_MMD_PMA_DEV_ADDR, addr, dev);
+
+	if(CHECKBIT(val64, 0x7))
+		stat_info->xpak_stat.warn_transceiver_temp_high++;
+
+	if(CHECKBIT(val64, 0x6))
+		stat_info->xpak_stat.warn_transceiver_temp_low++;
+
+	if(CHECKBIT(val64, 0x3))
+		stat_info->xpak_stat.warn_laser_bias_current_high++;
+
+	if(CHECKBIT(val64, 0x2))
+		stat_info->xpak_stat.warn_laser_bias_current_low++;
+
+	if(CHECKBIT(val64, 0x1))
+		stat_info->xpak_stat.warn_laser_output_power_high++;
+
+	if(CHECKBIT(val64, 0x0))
+		stat_info->xpak_stat.warn_laser_output_power_low++;
+}
+
+/**
  *  alarm_intr_handler - Alarm Interrrupt handler
  *  @nic: device private variable
  *  Description: If the interrupt was neither because of Rx packet or Tx
@@ -2790,6 +3142,18 @@
 	struct net_device *dev = (struct net_device *) nic->dev;
 	XENA_dev_config_t __iomem *bar0 = nic->bar0;
 	register u64 val64 = 0, err_reg = 0;
+	u64 cnt;
+	int i;
+	nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
+	/* Handling the XPAK counters update */
+	if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
+		/* waiting for an hour */
+		nic->mac_control.stats_info->xpak_stat.xpak_timer_count++;
+	} else {
+		s2io_updt_xpak_counter(dev);
+		/* reset the count to zero */
+		nic->mac_control.stats_info->xpak_stat.xpak_timer_count = 0;
+	}
 
 	/* Handling link status change error Intr */
 	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
@@ -2816,6 +3180,8 @@
 					     MC_ERR_REG_MIRI_ECC_DB_ERR_1)) {
 					netif_stop_queue(dev);
 					schedule_work(&nic->rst_timer_task);
+					nic->mac_control.stats_info->sw_stat.
+							soft_reset_cnt++;
 				}
 			}
 		} else {
@@ -2827,11 +3193,13 @@
 	/* In case of a serious error, the device will be Reset. */
 	val64 = readq(&bar0->serr_source);
 	if (val64 & SERR_SOURCE_ANY) {
+		nic->mac_control.stats_info->sw_stat.serious_err_cnt++;
 		DBG_PRINT(ERR_DBG, "%s: Device indicates ", dev->name);
 		DBG_PRINT(ERR_DBG, "serious error %llx!!\n", 
 			  (unsigned long long)val64);
 		netif_stop_queue(dev);
 		schedule_work(&nic->rst_timer_task);
+		nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
 	}
 
 	/*
@@ -2849,6 +3217,35 @@
 		ac = readq(&bar0->adapter_control);
 		schedule_work(&nic->set_link_task);
 	}
+	/* Check for data parity error */
+	val64 = readq(&bar0->pic_int_status);
+	if (val64 & PIC_INT_GPIO) {
+		val64 = readq(&bar0->gpio_int_reg);
+		if (val64 & GPIO_INT_REG_DP_ERR_INT) {
+			nic->mac_control.stats_info->sw_stat.parity_err_cnt++;
+			schedule_work(&nic->rst_timer_task);
+			nic->mac_control.stats_info->sw_stat.soft_reset_cnt++;
+		}
+	}
+
+	/* Check for ring full counter */
+	if (nic->device_type & XFRAME_II_DEVICE) {
+		val64 = readq(&bar0->ring_bump_counter1);
+		for (i=0; i<4; i++) {
+			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
+			cnt >>= 64 - ((i+1)*16);
+			nic->mac_control.stats_info->sw_stat.ring_full_cnt
+				+= cnt;
+		}
+
+		val64 = readq(&bar0->ring_bump_counter2);
+		for (i=0; i<4; i++) {
+			cnt = ( val64 & vBIT(0xFFFF,(i*16),16));
+			cnt >>= 64 - ((i+1)*16);
+			nic->mac_control.stats_info->sw_stat.ring_full_cnt
+				+= cnt;
+		}
+	}
 
 	/* Other type of interrupts are not being handled now,  TODO */
 }
@@ -2864,23 +3261,26 @@
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(nic_t * sp)
+static int wait_for_cmd_complete(void *addr, u64 busy_bit)
 {
-	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	int ret = FAILURE, cnt = 0;
 	u64 val64;
 
 	while (TRUE) {
-		val64 = readq(&bar0->rmac_addr_cmd_mem);
-		if (!(val64 & RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
+		val64 = readq(addr);
+		if (!(val64 & busy_bit)) {
 			ret = SUCCESS;
 			break;
 		}
-		msleep(50);
+
+		if(in_interrupt())
+			mdelay(50);
+		else
+			msleep(50);
+
 		if (cnt++ > 10)
 			break;
 	}
-
 	return ret;
 }
 
@@ -2919,6 +3319,9 @@
 	 * PCI write to sw_reset register is done by this time.
 	 */
 	msleep(250);
+	if (strstr(sp->product_name, "CX4")) {
+		msleep(750);
+	}
 
 	/* Restore the PCI state saved during initialization. */
 	pci_restore_state(sp->pdev);
@@ -3137,7 +3540,7 @@
 	u64 val64;
 	int i;
 
-	for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+	for (i=0; i< nic->avail_msix_vectors; i++) {
 		writeq(nic->msix_info[i].addr, &bar0->xmsi_address);
 		writeq(nic->msix_info[i].data, &bar0->xmsi_data);
 		val64 = (BIT(7) | BIT(15) | vBIT(i, 26, 6));
@@ -3156,7 +3559,7 @@
 	int i;
 
 	/* Store and display */
-	for (i=0; i< MAX_REQUESTED_MSI_X; i++) {
+	for (i=0; i< nic->avail_msix_vectors; i++) {
 		val64 = (BIT(15) | vBIT(i, 26, 6));
 		writeq(val64, &bar0->xmsi_access);
 		if (wait_for_msix_trans(nic, i)) {
@@ -3284,15 +3687,24 @@
 		writeq(tx_mat, &bar0->tx_mat0_n[7]);
 	}
 
+	nic->avail_msix_vectors = 0;
 	ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X);
+	/* We fail init if error or we get less vectors than min required */
+	if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) {
+		nic->avail_msix_vectors = ret;
+		ret = pci_enable_msix(nic->pdev, nic->entries, ret);
+	}
 	if (ret) {
 		DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name);
 		kfree(nic->entries);
 		kfree(nic->s2io_entries);
 		nic->entries = NULL;
 		nic->s2io_entries = NULL;
+		nic->avail_msix_vectors = 0;
 		return -ENOMEM;
 	}
+	if (!nic->avail_msix_vectors)
+		nic->avail_msix_vectors = MAX_REQUESTED_MSI_X;
 
 	/*
 	 * To enable MSI-X, MSI also needs to be enabled, due to a bug
@@ -3325,8 +3737,6 @@
 {
 	nic_t *sp = dev->priv;
 	int err = 0;
-	int i;
-	u16 msi_control; /* Temp variable */
 
 	/*
 	 * Make sure you have link off by default every time
@@ -3336,11 +3746,14 @@
 	sp->last_link_state = 0;
 
 	/* Initialize H/W and enable interrupts */
-	if (s2io_card_up(sp)) {
+	err = s2io_card_up(sp);
+	if (err) {
 		DBG_PRINT(ERR_DBG, "%s: H/W initialization failed\n",
 			  dev->name);
-		err = -ENODEV;
-		goto hw_init_failed;
+		if (err == -ENODEV)
+			goto hw_init_failed;
+		else
+			goto hw_enable_failed;
 	}
 
 	/* Store the values of the MSIX table in the nic_t structure */
@@ -3357,6 +3770,8 @@
 		}
 	}
 	if (sp->intr_type == MSI_X) {
+		int i;
+
 		for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) {
 			if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) {
 				sprintf(sp->desc1, "%s:MSI-X-%d-TX",
@@ -3409,24 +3824,26 @@
 isr_registration_failed:
 	del_timer_sync(&sp->alarm_timer);
 	if (sp->intr_type == MSI_X) {
-		if (sp->device_type == XFRAME_II_DEVICE) {
-			for (i=1; (sp->s2io_entries[i].in_use == 
+		int i;
+		u16 msi_control; /* Temp variable */
+
+		for (i=1; (sp->s2io_entries[i].in_use == 
 				MSIX_REGISTERED_SUCCESS); i++) {
-				int vector = sp->entries[i].vector;
-				void *arg = sp->s2io_entries[i].arg;
+			int vector = sp->entries[i].vector;
+			void *arg = sp->s2io_entries[i].arg;
 
-				free_irq(vector, arg);
-			}
-			pci_disable_msix(sp->pdev);
-
-			/* Temp */
-			pci_read_config_word(sp->pdev, 0x42, &msi_control);
-			msi_control &= 0xFFFE; /* Disable MSI */
-			pci_write_config_word(sp->pdev, 0x42, msi_control);
+			free_irq(vector, arg);
 		}
+		pci_disable_msix(sp->pdev);
+
+		/* Temp */
+		pci_read_config_word(sp->pdev, 0x42, &msi_control);
+		msi_control &= 0xFFFE; /* Disable MSI */
+		pci_write_config_word(sp->pdev, 0x42, msi_control);
 	}
 	else if (sp->intr_type == MSI)
 		pci_disable_msi(sp->pdev);
+hw_enable_failed:
 	s2io_reset(sp);
 hw_init_failed:
 	if (sp->intr_type == MSI_X) {
@@ -3454,35 +3871,12 @@
 static int s2io_close(struct net_device *dev)
 {
 	nic_t *sp = dev->priv;
-	int i;
-	u16 msi_control;
 
 	flush_scheduled_work();
 	netif_stop_queue(dev);
 	/* Reset card, kill tasklet and free Tx and Rx buffers. */
-	s2io_card_down(sp);
+	s2io_card_down(sp, 1);
 
-	if (sp->intr_type == MSI_X) {
-		if (sp->device_type == XFRAME_II_DEVICE) {
-			for (i=1; (sp->s2io_entries[i].in_use == 
-					MSIX_REGISTERED_SUCCESS); i++) {
-				int vector = sp->entries[i].vector;
-				void *arg = sp->s2io_entries[i].arg;
-
-				free_irq(vector, arg);
-			}
-			pci_read_config_word(sp->pdev, 0x42, &msi_control);
-			msi_control &= 0xFFFE; /* Disable MSI */
-			pci_write_config_word(sp->pdev, 0x42, msi_control);
-
-			pci_disable_msix(sp->pdev);
-		}
-	}
-	else {
-		free_irq(sp->pdev->irq, dev);
-		if (sp->intr_type == MSI)
-			pci_disable_msi(sp->pdev);
-	}	
 	sp->device_close_flag = TRUE;	/* Device is shut down. */
 	return 0;
 }
@@ -3545,7 +3939,8 @@
 
 	queue_len = mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
 	/* Avoid "put" pointer going beyond "get" pointer */
-	if (txdp->Host_Control || (((put_off + 1) % queue_len) == get_off)) {
+	if (txdp->Host_Control ||
+		   ((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
 		DBG_PRINT(TX_DBG, "Error in xmit, No free TXDs.\n");
 		netif_stop_queue(dev);
 		dev_kfree_skb(skb);
@@ -3564,8 +3959,8 @@
 	txdp->Control_1 = 0;
 	txdp->Control_2 = 0;
 #ifdef NETIF_F_TSO
-	mss = skb_shinfo(skb)->tso_size;
-	if (mss) {
+	mss = skb_shinfo(skb)->gso_size;
+	if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) {
 		txdp->Control_1 |= TXD_TCP_LSO_EN;
 		txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
 	}
@@ -3585,10 +3980,10 @@
 	}
 
 	frg_len = skb->len - skb->data_len;
-	if (skb_shinfo(skb)->ufo_size) {
+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) {
 		int ufo_size;
 
-		ufo_size = skb_shinfo(skb)->ufo_size;
+		ufo_size = skb_shinfo(skb)->gso_size;
 		ufo_size &= ~7;
 		txdp->Control_1 |= TXD_UFO_EN;
 		txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
@@ -3614,7 +4009,7 @@
 	txdp->Host_Control = (unsigned long) skb;
 	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
 
-	if (skb_shinfo(skb)->ufo_size)
+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
 		txdp->Control_1 |= TXD_UFO_EN;
 
 	frg_cnt = skb_shinfo(skb)->nr_frags;
@@ -3629,12 +4024,12 @@
 		    (sp->pdev, frag->page, frag->page_offset,
 		     frag->size, PCI_DMA_TODEVICE);
 		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
-		if (skb_shinfo(skb)->ufo_size)
+		if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
 			txdp->Control_1 |= TXD_UFO_EN;
 	}
 	txdp->Control_1 |= TXD_GATHER_CODE_LAST;
 
-	if (skb_shinfo(skb)->ufo_size)
+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
 		frg_cnt++; /* as Txd0 was used for inband header */
 
 	tx_fifo = mac_control->tx_FIFO_start[queue];
@@ -3648,18 +4043,20 @@
 	if (mss)
 		val64 |= TX_FIFO_SPECIAL_FUNC;
 #endif
-	if (skb_shinfo(skb)->ufo_size)
+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
 		val64 |= TX_FIFO_SPECIAL_FUNC;
 	writeq(val64, &tx_fifo->List_Control);
 
 	mmiowb();
 
 	put_off++;
-	put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1;
+	if (put_off == mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1)
+		put_off = 0;
 	mac_control->fifos[queue].tx_curr_put_info.offset = put_off;
 
 	/* Avoid "put" pointer going beyond "get" pointer */
-	if (((put_off + 1) % queue_len) == get_off) {
+	if (((put_off+1) == queue_len ? 0 : (put_off+1)) == get_off) {
+		sp->mac_control.stats_info->sw_stat.fifo_full_cnt++;
 		DBG_PRINT(TX_DBG,
 			  "No free TxDs for xmit, Put: 0x%x Get:0x%x\n",
 			  put_off, get_off);
@@ -3795,7 +4192,6 @@
 	atomic_dec(&sp->isr_cnt);
 	return IRQ_HANDLED;
 }
-
 static void s2io_txpic_intr_handle(nic_t *sp)
 {
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -3806,41 +4202,56 @@
 		val64 = readq(&bar0->gpio_int_reg);
 		if ((val64 & GPIO_INT_REG_LINK_DOWN) &&
 		    (val64 & GPIO_INT_REG_LINK_UP)) {
+			/*
+			 * This is unstable state so clear both up/down
+			 * interrupt and adapter to re-evaluate the link state.
+			 */
 			val64 |=  GPIO_INT_REG_LINK_DOWN;
 			val64 |= GPIO_INT_REG_LINK_UP;
 			writeq(val64, &bar0->gpio_int_reg);
-			goto masking;
+			val64 = readq(&bar0->gpio_int_mask);
+			val64 &= ~(GPIO_INT_MASK_LINK_UP |
+				   GPIO_INT_MASK_LINK_DOWN);
+			writeq(val64, &bar0->gpio_int_mask);
 		}
+		else if (val64 & GPIO_INT_REG_LINK_UP) {
+			val64 = readq(&bar0->adapter_status);
+			if (verify_xena_quiescence(sp, val64,
+						   sp->device_enabled_once)) {
+				/* Enable Adapter */
+				val64 = readq(&bar0->adapter_control);
+				val64 |= ADAPTER_CNTL_EN;
+				writeq(val64, &bar0->adapter_control);
+				val64 |= ADAPTER_LED_ON;
+				writeq(val64, &bar0->adapter_control);
+				if (!sp->device_enabled_once)
+					sp->device_enabled_once = 1;
 
-		if (((sp->last_link_state == LINK_UP) &&
-			(val64 & GPIO_INT_REG_LINK_DOWN)) ||
-		((sp->last_link_state == LINK_DOWN) &&
-		(val64 & GPIO_INT_REG_LINK_UP))) {
-			val64 = readq(&bar0->gpio_int_mask);
-			val64 |=  GPIO_INT_MASK_LINK_DOWN;
-			val64 |= GPIO_INT_MASK_LINK_UP;
-			writeq(val64, &bar0->gpio_int_mask);
-			s2io_set_link((unsigned long)sp);
-		}
-masking:
-		if (sp->last_link_state == LINK_UP) {
-			/*enable down interrupt */
-			val64 = readq(&bar0->gpio_int_mask);
-			/* unmasks link down intr */
-			val64 &=  ~GPIO_INT_MASK_LINK_DOWN;
-			/* masks link up intr */
-			val64 |= GPIO_INT_MASK_LINK_UP;
-			writeq(val64, &bar0->gpio_int_mask);
-		} else {
-			/*enable UP Interrupt */
-			val64 = readq(&bar0->gpio_int_mask);
-			/* unmasks link up interrupt */
-			val64 &= ~GPIO_INT_MASK_LINK_UP;
-			/* masks link down interrupt */
-			val64 |=  GPIO_INT_MASK_LINK_DOWN;
-			writeq(val64, &bar0->gpio_int_mask);
+				s2io_link(sp, LINK_UP);
+				/*
+				 * unmask link down interrupt and mask link-up
+				 * intr
+				 */
+				val64 = readq(&bar0->gpio_int_mask);
+				val64 &= ~GPIO_INT_MASK_LINK_DOWN;
+				val64 |= GPIO_INT_MASK_LINK_UP;
+				writeq(val64, &bar0->gpio_int_mask);
+
+			}
+		}else if (val64 & GPIO_INT_REG_LINK_DOWN) {
+			val64 = readq(&bar0->adapter_status);
+			if (verify_xena_quiescence(sp, val64,
+						   sp->device_enabled_once)) {
+				s2io_link(sp, LINK_DOWN);
+				/* Link is down so unmaks link up interrupt */
+				val64 = readq(&bar0->gpio_int_mask);
+				val64 &= ~GPIO_INT_MASK_LINK_UP;
+				val64 |= GPIO_INT_MASK_LINK_DOWN;
+				writeq(val64, &bar0->gpio_int_mask);
+			}
 		}
 	}
+	val64 = readq(&bar0->gpio_int_mask);
 }
 
 /**
@@ -3863,7 +4274,7 @@
 	nic_t *sp = dev->priv;
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	int i;
-	u64 reason = 0, val64;
+	u64 reason = 0, val64, org_mask;
 	mac_info_t *mac_control;
 	struct config_param *config;
 
@@ -3887,43 +4298,41 @@
 		return IRQ_NONE;
 	}
 
+	val64 = 0xFFFFFFFFFFFFFFFFULL;
+	/* Store current mask before masking all interrupts */
+	org_mask = readq(&bar0->general_int_mask);
+	writeq(val64, &bar0->general_int_mask);
+
 #ifdef CONFIG_S2IO_NAPI
 	if (reason & GEN_INTR_RXTRAFFIC) {
 		if (netif_rx_schedule_prep(dev)) {
-			en_dis_able_nic_intrs(sp, RX_TRAFFIC_INTR,
-					      DISABLE_INTRS);
+			writeq(val64, &bar0->rx_traffic_mask);
 			__netif_rx_schedule(dev);
 		}
 	}
 #else
-	/* If Intr is because of Rx Traffic */
-	if (reason & GEN_INTR_RXTRAFFIC) {
-		/*
-		 * rx_traffic_int reg is an R1 register, writing all 1's
-		 * will ensure that the actual interrupt causing bit get's
-		 * cleared and hence a read can be avoided.
-		 */
-		val64 = 0xFFFFFFFFFFFFFFFFULL;
-		writeq(val64, &bar0->rx_traffic_int);
-		for (i = 0; i < config->rx_ring_num; i++) {
-			rx_intr_handler(&mac_control->rings[i]);
-		}
+	/*
+	 * Rx handler is called by default, without checking for the
+	 * cause of interrupt.
+	 * rx_traffic_int reg is an R1 register, writing all 1's
+	 * will ensure that the actual interrupt causing bit get's
+	 * cleared and hence a read can be avoided.
+	 */
+	writeq(val64, &bar0->rx_traffic_int);
+	for (i = 0; i < config->rx_ring_num; i++) {
+		rx_intr_handler(&mac_control->rings[i]);
 	}
 #endif
 
-	/* If Intr is because of Tx Traffic */
-	if (reason & GEN_INTR_TXTRAFFIC) {
-		/*
-		 * tx_traffic_int reg is an R1 register, writing all 1's
-		 * will ensure that the actual interrupt causing bit get's
-		 * cleared and hence a read can be avoided.
-		 */
-		val64 = 0xFFFFFFFFFFFFFFFFULL;
-		writeq(val64, &bar0->tx_traffic_int);
+	/*
+	 * tx_traffic_int reg is an R1 register, writing all 1's
+	 * will ensure that the actual interrupt causing bit get's
+	 * cleared and hence a read can be avoided.
+	 */
+	writeq(val64, &bar0->tx_traffic_int);
 
-		for (i = 0; i < config->tx_fifo_num; i++)
-			tx_intr_handler(&mac_control->fifos[i]);
-	}
+	for (i = 0; i < config->tx_fifo_num; i++)
+		tx_intr_handler(&mac_control->fifos[i]);
 
 	if (reason & GEN_INTR_TXPIC)
 		s2io_txpic_intr_handle(sp);
@@ -3949,6 +4358,7 @@
 					DBG_PRINT(ERR_DBG, " in ISR!!\n");
 					clear_bit(0, (&sp->tasklet_status));
 					atomic_dec(&sp->isr_cnt);
+					writeq(org_mask, &bar0->general_int_mask);
 					return IRQ_HANDLED;
 				}
 				clear_bit(0, (&sp->tasklet_status));
@@ -3964,7 +4374,7 @@
 		}
 	}
 #endif
-
+	writeq(org_mask, &bar0->general_int_mask);
 	atomic_dec(&sp->isr_cnt);
 	return IRQ_HANDLED;
 }
@@ -4067,7 +4477,8 @@
 		    RMAC_ADDR_CMD_MEM_OFFSET(MAC_MC_ALL_MC_ADDR_OFFSET);
 		writeq(val64, &bar0->rmac_addr_cmd_mem);
 		/* Wait till command completes */
-		wait_for_cmd_complete(sp);
+		wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+				      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
 
 		sp->m_cast_flg = 1;
 		sp->all_multi_pos = MAC_MC_ALL_MC_ADDR_OFFSET;
@@ -4082,7 +4493,8 @@
 		    RMAC_ADDR_CMD_MEM_OFFSET(sp->all_multi_pos);
 		writeq(val64, &bar0->rmac_addr_cmd_mem);
 		/* Wait till command completes */
-		wait_for_cmd_complete(sp);
+		wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+				      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
 
 		sp->m_cast_flg = 0;
 		sp->all_multi_pos = 0;
@@ -4147,7 +4559,8 @@
 			writeq(val64, &bar0->rmac_addr_cmd_mem);
 
 			/* Wait for command completes */
-			if (wait_for_cmd_complete(sp)) {
+			if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+				      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
 				DBG_PRINT(ERR_DBG, "%s: Adding ",
 					  dev->name);
 				DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4177,7 +4590,8 @@
 			writeq(val64, &bar0->rmac_addr_cmd_mem);
 
 			/* Wait for command completes */
-			if (wait_for_cmd_complete(sp)) {
+			if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+				      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
 				DBG_PRINT(ERR_DBG, "%s: Adding ",
 					  dev->name);
 				DBG_PRINT(ERR_DBG, "Multicasts failed\n");
@@ -4222,7 +4636,8 @@
 	    RMAC_ADDR_CMD_MEM_OFFSET(0);
 	writeq(val64, &bar0->rmac_addr_cmd_mem);
 	/* Wait till command completes */
-	if (wait_for_cmd_complete(sp)) {
+	if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+		      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING)) {
 		DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name);
 		return FAILURE;
 	}
@@ -4619,6 +5034,44 @@
 	}
 	return ret;
 }
+static void s2io_vpd_read(nic_t *nic)
+{
+	u8 vpd_data[256],data;
+	int i=0, cnt, fail = 0;
+	int vpd_addr = 0x80;
+
+	if (nic->device_type == XFRAME_II_DEVICE) {
+		strcpy(nic->product_name, "Xframe II 10GbE network adapter");
+		vpd_addr = 0x80;
+	}
+	else {
+		strcpy(nic->product_name, "Xframe I 10GbE network adapter");
+		vpd_addr = 0x50;
+	}
+
+	for (i = 0; i < 256; i +=4 ) {
+		pci_write_config_byte(nic->pdev, (vpd_addr + 2), i);
+		pci_read_config_byte(nic->pdev,  (vpd_addr + 2), &data);
+		pci_write_config_byte(nic->pdev, (vpd_addr + 3), 0);
+		for (cnt = 0; cnt <5; cnt++) {
+			msleep(2);
+			pci_read_config_byte(nic->pdev, (vpd_addr + 3), &data);
+			if (data == 0x80)
+				break;
+		}
+		if (cnt >= 5) {
+			DBG_PRINT(ERR_DBG, "Read of VPD data failed\n");
+			fail = 1;
+			break;
+		}
+		pci_read_config_dword(nic->pdev,  (vpd_addr + 4),
+				      (u32 *)&vpd_data[i]);
+	}
+	if ((!fail) && (vpd_data[1] < VPD_PRODUCT_NAME_LEN)) {
+		memset(nic->product_name, 0, vpd_data[1]);
+		memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
+	}
+}
 
 /**
  *  s2io_ethtool_geeprom  - reads the value stored in the Eeprom.
@@ -4931,8 +5384,10 @@
 	u64 val64;
 
 	val64 = readq(&bar0->adapter_status);
-	if (val64 & ADAPTER_STATUS_RMAC_LOCAL_FAULT)
+	if(!(LINK_IS_UP(val64)))
 		*data = 1;
+	else
+		*data = 0;
 
 	return 0;
 }
@@ -5112,7 +5567,6 @@
 	int i = 0;
 	nic_t *sp = dev->priv;
 	StatInfo_t *stat_info = sp->mac_control.stats_info;
-	u64 tmp;
 
 	s2io_updt_stats(sp);
 	tmp_stats[i++] =
@@ -5129,9 +5583,19 @@
 		(u64)le32_to_cpu(stat_info->tmac_bcst_frms_oflow) << 32 |
 		le32_to_cpu(stat_info->tmac_bcst_frms);
 	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_pause_ctrl_frms);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->tmac_ttl_octets_oflow) << 32 |
+                le32_to_cpu(stat_info->tmac_ttl_octets);
+	tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->tmac_ucst_frms_oflow) << 32 |
+                le32_to_cpu(stat_info->tmac_ucst_frms);
+	tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->tmac_nucst_frms_oflow) << 32 |
+                le32_to_cpu(stat_info->tmac_nucst_frms);
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->tmac_any_err_frms_oflow) << 32 |
 		le32_to_cpu(stat_info->tmac_any_err_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->tmac_ttl_less_fb_octets);
 	tmp_stats[i++] = le64_to_cpu(stat_info->tmac_vld_ip_octets);
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->tmac_vld_ip_oflow) << 32 |
@@ -5163,11 +5627,27 @@
 		(u64)le32_to_cpu(stat_info->rmac_vld_bcst_frms_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_vld_bcst_frms);
 	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_in_rng_len_err_frms);
+	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_out_rng_len_err_frms);
 	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_long_frms);
 	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_pause_ctrl_frms);
+	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_unsup_ctrl_frms);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_ttl_octets_oflow) << 32 |
+		le32_to_cpu(stat_info->rmac_ttl_octets);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_accepted_ucst_frms_oflow)
+		<< 32 | le32_to_cpu(stat_info->rmac_accepted_ucst_frms);
+	tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_accepted_nucst_frms_oflow)
+                 << 32 | le32_to_cpu(stat_info->rmac_accepted_nucst_frms);
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->rmac_discarded_frms_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_discarded_frms);
+        tmp_stats[i++] =
+                (u64)le32_to_cpu(stat_info->rmac_drop_events_oflow)
+                 << 32 | le32_to_cpu(stat_info->rmac_drop_events);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_less_fb_octets);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_frms);
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->rmac_usized_frms_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_usized_frms);
@@ -5180,40 +5660,129 @@
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->rmac_jabber_frms_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_jabber_frms);
-	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
+	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_64_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_65_127_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_128_255_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_256_511_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_512_1023_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1024_1518_frms);
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stat_info->rmac_ip_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_ip);
 	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ip_octets);
 	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_hdr_err_ip);
-	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stat_info->rmac_drop_ip_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_drop_ip);
-	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stat_info->rmac_icmp_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_icmp);
 	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_tcp);
-	tmp_stats[i++] = (u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
+	tmp_stats[i++] =
+		(u64)le32_to_cpu(stat_info->rmac_udp_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_udp);
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->rmac_err_drp_udp_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_err_drp_udp);
+	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_err_sym);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q0);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q1);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q2);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q3);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q4);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q5);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q6);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_frms_q7);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q0);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q1);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q2);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q3);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q4);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q5);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q6);
+        tmp_stats[i++] = le16_to_cpu(stat_info->rmac_full_q7);
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->rmac_pause_cnt_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_pause_cnt);
+	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_data_err_cnt);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_xgmii_ctrl_err_cnt);
 	tmp_stats[i++] =
 		(u64)le32_to_cpu(stat_info->rmac_accepted_ip_oflow) << 32 |
 		le32_to_cpu(stat_info->rmac_accepted_ip);
 	tmp_stats[i++] = le32_to_cpu(stat_info->rmac_err_tcp);
+	tmp_stats[i++] = le32_to_cpu(stat_info->rd_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->new_rd_req_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_rd_ack_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->wr_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->new_wr_req_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->wr_rtry_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->wr_disc_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->rd_rtry_wr_ack_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->txp_wr_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->txd_rd_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->txd_wr_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->rxd_rd_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->rxd_wr_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->txf_rd_cnt);
+	tmp_stats[i++] = le32_to_cpu(stat_info->rxf_wr_cnt);
+	tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_1519_4095_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_4096_8191_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_8192_max_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_ttl_gt_max_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_osized_alt_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_jabber_alt_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_gt_max_alt_frms);
+        tmp_stats[i++] = le64_to_cpu(stat_info->rmac_vlan_frms);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_len_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_fcs_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_pf_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_da_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_red_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_rts_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->rmac_ingm_full_discard);
+        tmp_stats[i++] = le32_to_cpu(stat_info->link_fault_cnt);
 	tmp_stats[i++] = 0;
 	tmp_stats[i++] = stat_info->sw_stat.single_ecc_errs;
 	tmp_stats[i++] = stat_info->sw_stat.double_ecc_errs;
+	tmp_stats[i++] = stat_info->sw_stat.parity_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.serious_err_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.soft_reset_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.fifo_full_cnt;
+	tmp_stats[i++] = stat_info->sw_stat.ring_full_cnt;
+	tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_high;
+	tmp_stats[i++] = stat_info->xpak_stat.alarm_transceiver_temp_low;
+	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_high;
+	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_bias_current_low;
+	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_high;
+	tmp_stats[i++] = stat_info->xpak_stat.alarm_laser_output_power_low;
+	tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_high;
+	tmp_stats[i++] = stat_info->xpak_stat.warn_transceiver_temp_low;
+	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_high;
+	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_bias_current_low;
+	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_high;
+	tmp_stats[i++] = stat_info->xpak_stat.warn_laser_output_power_low;
 	tmp_stats[i++] = stat_info->sw_stat.clubbed_frms_cnt;
 	tmp_stats[i++] = stat_info->sw_stat.sending_both;
 	tmp_stats[i++] = stat_info->sw_stat.outof_sequence_pkts;
 	tmp_stats[i++] = stat_info->sw_stat.flush_max_pkts;
-	tmp = 0;
 	if (stat_info->sw_stat.num_aggregations) {
-		tmp = stat_info->sw_stat.sum_avg_pkts_aggregated;
-		do_div(tmp, stat_info->sw_stat.num_aggregations);
+		u64 tmp = stat_info->sw_stat.sum_avg_pkts_aggregated;
+		int count = 0;
+		/* 
+		 * Since 64-bit divide does not work on all platforms,
+		 * do repeated subtraction.
+		 */
+		while (tmp >= stat_info->sw_stat.num_aggregations) {
+			tmp -= stat_info->sw_stat.num_aggregations;
+			count++;
+		}
+		tmp_stats[i++] = count;
 	}
-	tmp_stats[i++] = tmp;
+	else
+		tmp_stats[i++] = 0;
 }
 
 static int s2io_ethtool_get_regs_len(struct net_device *dev)
@@ -5351,7 +5920,7 @@
 
 	dev->mtu = new_mtu;
 	if (netif_running(dev)) {
-		s2io_card_down(sp);
+		s2io_card_down(sp, 0);
 		netif_stop_queue(dev);
 		if (s2io_card_up(sp)) {
 			DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
@@ -5489,12 +6058,172 @@
 	clear_bit(0, &(nic->link_state));
 }
 
-static void s2io_card_down(nic_t * sp)
+static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba,
+			   struct sk_buff **skb, u64 *temp0, u64 *temp1,
+			   u64 *temp2, int size)
+{
+	struct net_device *dev = sp->dev;
+	struct sk_buff *frag_list;
+
+	if ((sp->rxd_mode == RXD_MODE_1) && (rxdp->Host_Control == 0)) {
+		/* allocate skb */
+		if (*skb) {
+			DBG_PRINT(INFO_DBG, "SKB is not NULL\n");
+			/*
+			 * As Rx frame are not going to be processed,
+			 * using same mapped address for the Rxd
+			 * buffer pointer
+			 */
+			((RxD1_t*)rxdp)->Buffer0_ptr = *temp0;
+		} else {
+			*skb = dev_alloc_skb(size);
+			if (!(*skb)) {
+				DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name);
+				DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n");
+				return -ENOMEM ;
+			}
+			/* storing the mapped addr in a temp variable
+			 * such it will be used for next rxd whose
+			 * Host Control is NULL
+			 */
+			((RxD1_t*)rxdp)->Buffer0_ptr = *temp0 =
+				pci_map_single( sp->pdev, (*skb)->data,
+					size - NET_IP_ALIGN,
+					PCI_DMA_FROMDEVICE);
+			rxdp->Host_Control = (unsigned long) (*skb);
+		}
+	} else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) {
+		/* Two buffer Mode */
+		if (*skb) {
+			((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
+			((RxD3_t*)rxdp)->Buffer0_ptr = *temp0;
+			((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
+		} else {
+			*skb = dev_alloc_skb(size);
+			((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
+				pci_map_single(sp->pdev, (*skb)->data,
+					       dev->mtu + 4,
+					       PCI_DMA_FROMDEVICE);
+			((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
+				pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN,
+						PCI_DMA_FROMDEVICE);
+			rxdp->Host_Control = (unsigned long) (*skb);
+
+			/* Buffer-1 will be dummy buffer not used */
+			((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 =
+				pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN,
+					       PCI_DMA_FROMDEVICE);
+		}
+	} else if ((rxdp->Host_Control == 0)) {
+		/* Three buffer mode */
+		if (*skb) {
+			((RxD3_t*)rxdp)->Buffer0_ptr = *temp0;
+			((RxD3_t*)rxdp)->Buffer1_ptr = *temp1;
+			((RxD3_t*)rxdp)->Buffer2_ptr = *temp2;
+		} else {
+			*skb = dev_alloc_skb(size);
+
+			((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 =
+				pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN,
+					       PCI_DMA_FROMDEVICE);
+			/* Buffer-1 receives L3/L4 headers */
+			((RxD3_t*)rxdp)->Buffer1_ptr = *temp1 =
+				pci_map_single( sp->pdev, (*skb)->data,
+						l3l4hdr_size + 4,
+						PCI_DMA_FROMDEVICE);
+			/*
+			 * skb_shinfo(skb)->frag_list will have L4
+			 * data payload
+			 */
+			skb_shinfo(*skb)->frag_list = dev_alloc_skb(dev->mtu +
+								   ALIGN_SIZE);
+			if (skb_shinfo(*skb)->frag_list == NULL) {
+				DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb \
+					  failed\n ", dev->name);
+				return -ENOMEM ;
+			}
+			frag_list = skb_shinfo(*skb)->frag_list;
+			frag_list->next = NULL;
+			/*
+			 * Buffer-2 receives L4 data payload
+			 */
+			((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 =
+				pci_map_single( sp->pdev, frag_list->data,
+						dev->mtu, PCI_DMA_FROMDEVICE);
+		}
+	}
+	return 0;
+}
+static void set_rxd_buffer_size(nic_t *sp, RxD_t *rxdp, int size)
+{
+	struct net_device *dev = sp->dev;
+	if (sp->rxd_mode == RXD_MODE_1) {
+		rxdp->Control_2 = SET_BUFFER0_SIZE_1( size - NET_IP_ALIGN);
+	} else if (sp->rxd_mode == RXD_MODE_3B) {
+		rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
+		rxdp->Control_2 |= SET_BUFFER1_SIZE_3(1);
+		rxdp->Control_2 |= SET_BUFFER2_SIZE_3( dev->mtu + 4);
+	} else {
+		rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN);
+		rxdp->Control_2 |= SET_BUFFER1_SIZE_3(l3l4hdr_size + 4);
+		rxdp->Control_2 |= SET_BUFFER2_SIZE_3(dev->mtu);
+	}
+}
+
+static  int rxd_owner_bit_reset(nic_t *sp)
+{
+	int i, j, k, blk_cnt = 0, size;
+	mac_info_t * mac_control = &sp->mac_control;
+	struct config_param *config = &sp->config;
+	struct net_device *dev = sp->dev;
+	RxD_t *rxdp = NULL;
+	struct sk_buff *skb = NULL;
+	buffAdd_t *ba = NULL;
+	u64 temp0_64 = 0, temp1_64 = 0, temp2_64 = 0;
+
+	/* Calculate the size based on ring mode */
+	size = dev->mtu + HEADER_ETHERNET_II_802_3_SIZE +
+		HEADER_802_2_SIZE + HEADER_SNAP_SIZE;
+	if (sp->rxd_mode == RXD_MODE_1)
+		size += NET_IP_ALIGN;
+	else if (sp->rxd_mode == RXD_MODE_3B)
+		size = dev->mtu + ALIGN_SIZE + BUF0_LEN + 4;
+	else
+		size = l3l4hdr_size + ALIGN_SIZE + BUF0_LEN + 4;
+
+	for (i = 0; i < config->rx_ring_num; i++) {
+		blk_cnt = config->rx_cfg[i].num_rxd /
+			(rxd_count[sp->rxd_mode] +1);
+
+		for (j = 0; j < blk_cnt; j++) {
+			for (k = 0; k < rxd_count[sp->rxd_mode]; k++) {
+				rxdp = mac_control->rings[i].
+					rx_blocks[j].rxds[k].virt_addr;
+				if(sp->rxd_mode >= RXD_MODE_3A)
+					ba = &mac_control->rings[i].ba[j][k];
+				set_rxd_buffer_pointer(sp, rxdp, ba,
+						       &skb,(u64 *)&temp0_64,
+						       (u64 *)&temp1_64,
+						       (u64 *)&temp2_64, size);
+
+				set_rxd_buffer_size(sp, rxdp, size);
+				wmb();
+				/* flip the Ownership bit to Hardware */
+				rxdp->Control_1 |= RXD_OWN_XENA;
+			}
+		}
+	}
+	return 0;
+
+}
+
+static void s2io_card_down(nic_t * sp, int flag)
 {
 	int cnt = 0;
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	unsigned long flags;
 	register u64 val64 = 0;
+	struct net_device *dev = sp->dev;
 
 	del_timer_sync(&sp->alarm_timer);
 	/* If s2io_set_link task is executing, wait till it completes. */
@@ -5505,12 +6234,51 @@
 
 	/* disable Tx and Rx traffic on the NIC */
 	stop_nic(sp);
+	if (flag) {
+		if (sp->intr_type == MSI_X) {
+			int i;
+			u16 msi_control;
+
+			for (i=1; (sp->s2io_entries[i].in_use ==
+				MSIX_REGISTERED_SUCCESS); i++) {
+				int vector = sp->entries[i].vector;
+				void *arg = sp->s2io_entries[i].arg;
+
+				free_irq(vector, arg);
+			}
+			pci_read_config_word(sp->pdev, 0x42, &msi_control);
+			msi_control &= 0xFFFE; /* Disable MSI */
+			pci_write_config_word(sp->pdev, 0x42, msi_control);
+			pci_disable_msix(sp->pdev);
+		} else {
+			free_irq(sp->pdev->irq, dev);
+			if (sp->intr_type == MSI)
+				pci_disable_msi(sp->pdev);
+		}
+	}
+	/* Waiting till all Interrupt handlers are complete */
+	cnt = 0;
+	do {
+		msleep(10);
+		if (!atomic_read(&sp->isr_cnt))
+			break;
+		cnt++;
+	} while(cnt < 5);
 
 	/* Kill tasklet. */
 	tasklet_kill(&sp->task);
 
 	/* Check if the device is Quiescent and then Reset the NIC */
 	do {
+		/* As per the HW requirement we need to replenish the
+		 * receive buffer to avoid the ring bump. Since there is
+		 * no intention of processing the Rx frame at this pointwe are
+		 * just settting the ownership bit of rxd in Each Rx
+		 * ring to HW and set the appropriate buffer size
+		 * based on the ring mode
+		 */
+		rxd_owner_bit_reset(sp);
+
 		val64 = readq(&bar0->adapter_status);
 		if (verify_xena_quiescence(sp, val64, sp->device_enabled_once)) {
 			break;
@@ -5528,15 +6296,6 @@
 	} while (1);
 	s2io_reset(sp);
 
-	/* Waiting till all Interrupt handlers are complete */
-	cnt = 0;
-	do {
-		msleep(10);
-		if (!atomic_read(&sp->isr_cnt))
-			break;
-		cnt++;
-	} while(cnt < 5);
-
 	spin_lock_irqsave(&sp->tx_lock, flags);
 	/* Free all Tx buffers */
 	free_tx_buffers(sp);
@@ -5637,7 +6396,7 @@
 	struct net_device *dev = (struct net_device *) data;
 	nic_t *sp = dev->priv;
 
-	s2io_card_down(sp);
+	s2io_card_down(sp, 0);
 	if (s2io_card_up(sp)) {
 		DBG_PRINT(ERR_DBG, "%s: Device bring up failed\n",
 			  dev->name);
@@ -5667,6 +6426,7 @@
 
 	if (netif_carrier_ok(dev)) {
 		schedule_work(&sp->rst_timer_task);
+		sp->mac_control.stats_info->sw_stat.soft_reset_cnt++;
 	}
 }
 
@@ -5695,18 +6455,33 @@
 		((unsigned long) rxdp->Host_Control);
 	int ring_no = ring_data->ring_no;
 	u16 l3_csum, l4_csum;
+	unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
 	lro_t *lro;
 
 	skb->dev = dev;
-	if (rxdp->Control_1 & RXD_T_CODE) {
-		unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
-		DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
-			  dev->name, err);
-		dev_kfree_skb(skb);
-		sp->stats.rx_crc_errors++;
-		atomic_dec(&sp->rx_bufs_left[ring_no]);
-		rxdp->Host_Control = 0;
-		return 0;
+
+	if (err) {
+		/* Check for parity error */
+		if (err & 0x1) {
+			sp->mac_control.stats_info->sw_stat.parity_err_cnt++;
+		}
+
+		/*
+		* Drop the packet if bad transfer code. Exception being
+		* 0x5, which could be due to unsupported IPv6 extension header.
+		* In this case, we let stack handle the packet.
+		* Note that in this case, since checksum will be incorrect,
+		* stack will validate the same.
+		*/
+		if (err && ((err >> 48) != 0x5)) {
+			DBG_PRINT(ERR_DBG, "%s: Rx error Value: 0x%llx\n",
+				dev->name, err);
+			sp->stats.rx_crc_errors++;
+			dev_kfree_skb(skb);
+			atomic_dec(&sp->rx_bufs_left[ring_no]);
+			rxdp->Host_Control = 0;
+			return 0;
+		}
 	}
 
 	/* Updating statistics */
@@ -5792,6 +6567,9 @@
 						clear_lro_session(lro);
 						goto send_up;
 					case 0: /* sessions exceeded */
+					case -1: /* non-TCP or not
+						  * L2 aggregatable
+						  */
 					case 5: /*
 						 * First pkt in session not
 						 * L3/L4 aggregatable
@@ -5918,13 +6696,6 @@
 	pci_write_config_word(sp->pdev, PCI_COMMAND,
 			      (pci_cmd | PCI_COMMAND_PARITY));
 	pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd);
-
-	/* Forcibly disabling relaxed ordering capability of the card. */
-	pcix_cmd &= 0xfffd;
-	pci_write_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-			      pcix_cmd);
-	pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER,
-			     &(pcix_cmd));
 }
 
 MODULE_AUTHOR("Raghavendra Koushik <raghavendra.koushik@neterion.com>");
@@ -5954,6 +6725,55 @@
 module_param(lro, int, 0);
 module_param(lro_max_pkts, int, 0);
 
+static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type)
+{
+	if ( tx_fifo_num > 8) {
+		DBG_PRINT(ERR_DBG, "s2io: Requested number of Tx fifos not "
+			 "supported\n");
+		DBG_PRINT(ERR_DBG, "s2io: Default to 8 Tx fifos\n");
+		tx_fifo_num = 8;
+	}
+	if ( rx_ring_num > 8) {
+		DBG_PRINT(ERR_DBG, "s2io: Requested number of Rx rings not "
+			 "supported\n");
+		DBG_PRINT(ERR_DBG, "s2io: Default to 8 Rx rings\n");
+		rx_ring_num = 8;
+	}
+#ifdef CONFIG_S2IO_NAPI
+	if (*dev_intr_type != INTA) {
+		DBG_PRINT(ERR_DBG, "s2io: NAPI cannot be enabled when "
+			  "MSI/MSI-X is enabled. Defaulting to INTA\n");
+		*dev_intr_type = INTA;
+	}
+#endif
+#ifndef CONFIG_PCI_MSI
+	if (*dev_intr_type != INTA) {
+		DBG_PRINT(ERR_DBG, "s2io: This kernel does not support"
+			  "MSI/MSI-X. Defaulting to INTA\n");
+		*dev_intr_type = INTA;
+	}
+#else
+	if (*dev_intr_type > MSI_X) {
+		DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. "
+			  "Defaulting to INTA\n");
+		*dev_intr_type = INTA;
+	}
+#endif
+	if ((*dev_intr_type == MSI_X) &&
+			((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
+			(pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
+		DBG_PRINT(ERR_DBG, "s2io: Xframe I does not support MSI_X. " 
+					"Defaulting to INTA\n");
+		*dev_intr_type = INTA;
+	}
+	if (rx_ring_mode > 3) {
+		DBG_PRINT(ERR_DBG, "s2io: Requested ring mode not supported\n");
+		DBG_PRINT(ERR_DBG, "s2io: Defaulting to 3-buffer mode\n");
+		rx_ring_mode = 3;
+	}
+	return SUCCESS;
+}
+
 /**
  *  s2io_init_nic - Initialization of the adapter .
  *  @pdev : structure containing the PCI related information of the device.
@@ -5984,15 +6804,8 @@
 	int mode;
 	u8 dev_intr_type = intr_type;
 
-#ifdef CONFIG_S2IO_NAPI
-	if (dev_intr_type != INTA) {
-		DBG_PRINT(ERR_DBG, "NAPI cannot be enabled when MSI/MSI-X \
-is enabled. Defaulting to INTA\n");
-		dev_intr_type = INTA;
-	}
-	else
-		DBG_PRINT(ERR_DBG, "NAPI support has been enabled\n");
-#endif
+	if ((ret = s2io_verify_parm(pdev, &dev_intr_type)))
+		return ret;
 
 	if ((ret = pci_enable_device(pdev))) {
 		DBG_PRINT(ERR_DBG,
@@ -6017,14 +6830,6 @@
 		pci_disable_device(pdev);
 		return -ENOMEM;
 	}
-
-	if ((dev_intr_type == MSI_X) && 
-			((pdev->device != PCI_DEVICE_ID_HERC_WIN) &&
-			(pdev->device != PCI_DEVICE_ID_HERC_UNI))) {
-		DBG_PRINT(ERR_DBG, "Xframe I does not support MSI_X. \
-Defaulting to INTA\n");
-		dev_intr_type = INTA;
-	}
 	if (dev_intr_type != MSI_X) {
 		if (pci_request_regions(pdev, s2io_driver_name)) {
 			DBG_PRINT(ERR_DBG, "Request Regions failed\n"),
@@ -6100,8 +6905,6 @@
 	config = &sp->config;
 
 	/* Tx side parameters. */
-	if (tx_fifo_len[0] == 0)
-		tx_fifo_len[0] = DEFAULT_FIFO_LEN; /* Default value. */
 	config->tx_fifo_num = tx_fifo_num;
 	for (i = 0; i < MAX_TX_FIFOS; i++) {
 		config->tx_cfg[i].fifo_len = tx_fifo_len[i];
@@ -6125,8 +6928,6 @@
 	config->max_txds = MAX_SKB_FRAGS + 2;
 
 	/* Rx side parameters. */
-	if (rx_ring_sz[0] == 0)
-		rx_ring_sz[0] = SMALL_BLK_CNT; /* Default value. */
 	config->rx_ring_num = rx_ring_num;
 	for (i = 0; i < MAX_RX_RINGS; i++) {
 		config->rx_cfg[i].num_rxd = rx_ring_sz[i] *
@@ -6210,6 +7011,10 @@
 	dev->weight = 32;
 #endif
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = s2io_netpoll;
+#endif
+
 	dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
 	if (sp->high_dma_flag == TRUE)
 		dev->features |= NETIF_F_HIGHDMA;
@@ -6267,8 +7072,8 @@
 	val64 = RMAC_ADDR_CMD_MEM_RD | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD |
 	    RMAC_ADDR_CMD_MEM_OFFSET(0 + MAC_MAC_ADDR_START_OFFSET);
 	writeq(val64, &bar0->rmac_addr_cmd_mem);
-	wait_for_cmd_complete(sp);
-
+	wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem,
+		      RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING);
 	tmp64 = readq(&bar0->rmac_addr_data0_mem);
 	mac_down = (u32) tmp64;
 	mac_up = (u32) (tmp64 >> 32);
@@ -6322,82 +7127,63 @@
 		ret = -ENODEV;
 		goto register_failed;
 	}
-
-	if (sp->device_type & XFRAME_II_DEVICE) {
-		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe II 10GbE adapter ",
-			  dev->name);
-		DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
+	s2io_vpd_read(sp);
+	DBG_PRINT(ERR_DBG, "%s: Neterion %s",dev->name, sp->product_name);
+	DBG_PRINT(ERR_DBG, "(rev %d), Driver version %s\n",
 				get_xena_rev_id(sp->pdev),
 				s2io_driver_version);
-		switch(sp->intr_type) {
-			case INTA:
-				DBG_PRINT(ERR_DBG, ", Intr type INTA");
-				break;
-			case MSI:
-				DBG_PRINT(ERR_DBG, ", Intr type MSI");
-				break;
-			case MSI_X:
-				DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
-				break;
-		}
-
-		DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
-		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
+	DBG_PRINT(ERR_DBG, "Copyright(c) 2002-2005 Neterion Inc.\n");
+	DBG_PRINT(ERR_DBG, "%s: MAC ADDR: "
+			  "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
 			  sp->def_mac_addr[0].mac_addr[0],
 			  sp->def_mac_addr[0].mac_addr[1],
 			  sp->def_mac_addr[0].mac_addr[2],
 			  sp->def_mac_addr[0].mac_addr[3],
 			  sp->def_mac_addr[0].mac_addr[4],
 			  sp->def_mac_addr[0].mac_addr[5]);
+	if (sp->device_type & XFRAME_II_DEVICE) {
 		mode = s2io_print_pci_mode(sp);
 		if (mode < 0) {
-			DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode ");
+			DBG_PRINT(ERR_DBG, " Unsupported PCI bus mode\n");
 			ret = -EBADSLT;
+			unregister_netdev(dev);
 			goto set_swap_failed;
 		}
-	} else {
-		DBG_PRINT(ERR_DBG, "%s: Neterion Xframe I 10GbE adapter ",
-			  dev->name);
-		DBG_PRINT(ERR_DBG, "(rev %d), Version %s",
-					get_xena_rev_id(sp->pdev),
-					s2io_driver_version);
-		switch(sp->intr_type) {
-			case INTA:
-				DBG_PRINT(ERR_DBG, ", Intr type INTA");
-				break;
-			case MSI:
-				DBG_PRINT(ERR_DBG, ", Intr type MSI");
-				break;
-			case MSI_X:
-				DBG_PRINT(ERR_DBG, ", Intr type MSI-X");
-				break;
-		}
-		DBG_PRINT(ERR_DBG, "\nCopyright(c) 2002-2005 Neterion Inc.\n");
-		DBG_PRINT(ERR_DBG, "MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n",
-			  sp->def_mac_addr[0].mac_addr[0],
-			  sp->def_mac_addr[0].mac_addr[1],
-			  sp->def_mac_addr[0].mac_addr[2],
-			  sp->def_mac_addr[0].mac_addr[3],
-			  sp->def_mac_addr[0].mac_addr[4],
-			  sp->def_mac_addr[0].mac_addr[5]);
 	}
-	if (sp->rxd_mode == RXD_MODE_3B)
-		DBG_PRINT(ERR_DBG, "%s: 2-Buffer mode support has been "
-			  "enabled\n",dev->name);
-	if (sp->rxd_mode == RXD_MODE_3A)
-		DBG_PRINT(ERR_DBG, "%s: 3-Buffer mode support has been "
-			  "enabled\n",dev->name);
-
+	switch(sp->rxd_mode) {
+		case RXD_MODE_1:
+		    DBG_PRINT(ERR_DBG, "%s: 1-Buffer receive mode enabled\n",
+						dev->name);
+		    break;
+		case RXD_MODE_3B:
+		    DBG_PRINT(ERR_DBG, "%s: 2-Buffer receive mode enabled\n",
+						dev->name);
+		    break;
+		case RXD_MODE_3A:
+		    DBG_PRINT(ERR_DBG, "%s: 3-Buffer receive mode enabled\n",
+						dev->name);
+		    break;
+	}
+#ifdef CONFIG_S2IO_NAPI
+	DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name);
+#endif
+	switch(sp->intr_type) {
+		case INTA:
+		    DBG_PRINT(ERR_DBG, "%s: Interrupt type INTA\n", dev->name);
+		    break;
+		case MSI:
+		    DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI\n", dev->name);
+		    break;
+		case MSI_X:
+		    DBG_PRINT(ERR_DBG, "%s: Interrupt type MSI-X\n", dev->name);
+		    break;
+	}
 	if (sp->lro)
 		DBG_PRINT(ERR_DBG, "%s: Large receive offload enabled\n",
-			dev->name);
+			  dev->name);
 
 	/* Initialize device name */
-	strcpy(sp->name, dev->name);
-	if (sp->device_type & XFRAME_II_DEVICE)
-		strcat(sp->name, ": Neterion Xframe II 10GbE adapter");
-	else
-		strcat(sp->name, ": Neterion Xframe I 10GbE adapter");
+	sprintf(sp->name, "%s Neterion %s", dev->name, sp->product_name);
 
 	/* Initialize bimodal Interrupts */
 	sp->config.bimodal = bimodal;
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 0a0b5b2..3203732 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -31,6 +31,8 @@
 #define SUCCESS 0
 #define FAILURE -1
 
+#define CHECKBIT(value, nbit) (value & (1 << nbit))
+
 /* Maximum time to flicker LED when asked to identify NIC using ethtool */
 #define MAX_FLICKER_TIME	60000 /* 60 Secs */
 
@@ -78,6 +80,11 @@
 typedef struct {
 	unsigned long long single_ecc_errs;
 	unsigned long long double_ecc_errs;
+	unsigned long long parity_err_cnt;
+	unsigned long long serious_err_cnt;
+	unsigned long long soft_reset_cnt;
+	unsigned long long fifo_full_cnt;
+	unsigned long long ring_full_cnt;
 	/* LRO statistics */
 	unsigned long long clubbed_frms_cnt;
 	unsigned long long sending_both;
@@ -87,6 +94,25 @@
 	unsigned long long num_aggregations;
 } swStat_t;
 
+/* Xpak releated alarm and warnings */
+typedef struct {
+	u64 alarm_transceiver_temp_high;
+	u64 alarm_transceiver_temp_low;
+	u64 alarm_laser_bias_current_high;
+	u64 alarm_laser_bias_current_low;
+	u64 alarm_laser_output_power_high;
+	u64 alarm_laser_output_power_low;
+	u64 warn_transceiver_temp_high;
+	u64 warn_transceiver_temp_low;
+	u64 warn_laser_bias_current_high;
+	u64 warn_laser_bias_current_low;
+	u64 warn_laser_output_power_high;
+	u64 warn_laser_output_power_low;
+	u64 xpak_regs_stat;
+	u32 xpak_timer_count;
+} xpakStat_t;
+
+
 /* The statistics block of Xena */
 typedef struct stat_block {
 /* Tx MAC statistics counters. */
@@ -263,7 +289,9 @@
 	u32 rmac_accepted_ip_oflow;
 	u32 reserved_14;
 	u32 link_fault_cnt;
+	u8  buffer[20];
 	swStat_t sw_stat;
+	xpakStat_t xpak_stat;
 } StatInfo_t;
 
 /*
@@ -659,7 +687,8 @@
 } usr_addr_t;
 
 /* Default Tunable parameters of the NIC. */
-#define DEFAULT_FIFO_LEN 4096
+#define DEFAULT_FIFO_0_LEN 4096
+#define DEFAULT_FIFO_1_7_LEN 512
 #define SMALL_BLK_CNT	30
 #define LARGE_BLK_CNT	100
 
@@ -732,7 +761,7 @@
 	int device_close_flag;
 	int device_enabled_once;
 
-	char name[50];
+	char name[60];
 	struct tasklet_struct task;
 	volatile unsigned long tasklet_status;
 
@@ -803,6 +832,8 @@
 	char desc1[35];
 	char desc2[35];
 
+	int avail_msix_vectors; /* No. of MSI-X vectors granted by system */
+
 	struct msix_info_st msix_info[0x3f];
 
 #define XFRAME_I_DEVICE		1
@@ -824,6 +855,8 @@
 	spinlock_t	rx_lock;
 	atomic_t	isr_cnt;
 	u64 *ufo_in_band_v;
+#define VPD_PRODUCT_NAME_LEN 50
+	u8  product_name[VPD_PRODUCT_NAME_LEN];
 };
 
 #define RESET_ERROR 1;
@@ -848,28 +881,32 @@
 	writel((u32) (val), addr);
 	writel((u32) (val >> 32), (addr + 4));
 }
+#endif
 
-/* In 32 bit modes, some registers have to be written in a
- * particular order to expect correct hardware operation. The
- * macro SPECIAL_REG_WRITE is used to perform such ordered
- * writes. Defines UF (Upper First) and LF (Lower First) will
- * be used to specify the required write order.
+/* 
+ * Some registers have to be written in a particular order to 
+ * expect correct hardware operation. The macro SPECIAL_REG_WRITE 
+ * is used to perform such ordered writes. Defines UF (Upper First) 
+ * and LF (Lower First) will be used to specify the required write order.
  */
 #define UF	1
 #define LF	2
 static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
 {
+	u32 ret;
+
 	if (order == LF) {
 		writel((u32) (val), addr);
+		ret = readl(addr);
 		writel((u32) (val >> 32), (addr + 4));
+		ret = readl(addr + 4);
 	} else {
 		writel((u32) (val >> 32), (addr + 4));
+		ret = readl(addr + 4);
 		writel((u32) (val), addr);
+		ret = readl(addr);
 	}
 }
-#else
-#define SPECIAL_REG_WRITE(val, addr, dummy) writeq(val, addr)
-#endif
 
 /*  Interrupt related values of Xena */
 
@@ -965,7 +1002,7 @@
 static struct ethtool_ops netdev_ethtool_ops;
 static void s2io_set_link(unsigned long data);
 static int s2io_set_swapper(nic_t * sp);
-static void s2io_card_down(nic_t *nic);
+static void s2io_card_down(nic_t *nic, int flag);
 static int s2io_card_up(nic_t *nic);
 static int get_xena_rev_id(struct pci_dev *pdev);
 static void restore_xmsi_data(nic_t *nic);
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index bcef03f..efd0f23 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -396,8 +396,7 @@
 	unsigned char *buf;
 
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index 31dd3f0..df39f34 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -1156,8 +1156,7 @@
 	dma_addr_t mapping;
 
 	if (unlikely(skb->len < ETH_ZLEN)) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (!skb) {
+		if (skb_padto(skb, ETH_ZLEN)) {
 			tp->stats.tx_dropped++;
 			goto out;
 		}
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index f5a3bf4..d058741 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:	1.08.09 Sep. 19 2005
+   Revision:	1.08.10 Apr. 2 2006
    
    Modified from the driver which is originally written by Donald Becker.
    
@@ -17,9 +17,10 @@
    SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
    preliminary Rev. 1.0 Jan. 18, 1998
 
+   Rev 1.08.10 Apr.  2 2006 Daniele Venzano add vlan (jumbo packets) support
    Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support
    Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
-   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
+   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <venza@brownhat.org> add suspend/resume support
    Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
    Rev 1.08.05 Jun.  6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
@@ -77,7 +78,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005"
+#define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -1402,6 +1403,11 @@
 		rx_flags |= RxATX;
 	}
 
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+	/* Can accept Jumbo packet */
+	rx_flags |= RxAJAB;
+#endif
+
 	outl (tx_flags, ioaddr + txcfg);
 	outl (rx_flags, ioaddr + rxcfg);
 }
@@ -1714,18 +1720,26 @@
 
 	while (rx_status & OWN) {
 		unsigned int rx_size;
+		unsigned int data_size;
 
 		if (--rx_work_limit < 0)
 			break;
 
-		rx_size = (rx_status & DSIZE) - CRC_SIZE;
+		data_size = rx_status & DSIZE;
+		rx_size = data_size - CRC_SIZE;
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+		/* ``TOOLONG'' flag means jumbo packet recived. */
+		if ((rx_status & TOOLONG) && data_size <= MAX_FRAME_SIZE)
+			rx_status &= (~ ((unsigned int)TOOLONG));
+#endif
 
 		if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
 			/* corrupted packet received */
 			if (netif_msg_rx_err(sis_priv))
 				printk(KERN_DEBUG "%s: Corrupted packet "
-				       "received, buffer status = 0x%8.8x.\n",
-				       net_dev->name, rx_status);
+				       "received, buffer status = 0x%8.8x/%d.\n",
+				       net_dev->name, rx_status, data_size);
 			sis_priv->stats.rx_errors++;
 			if (rx_status & OVERRUN)
 				sis_priv->stats.rx_over_errors++;
diff --git a/drivers/net/sis900.h b/drivers/net/sis900.h
index 5032394..4834e3a 100644
--- a/drivers/net/sis900.h
+++ b/drivers/net/sis900.h
@@ -310,8 +310,14 @@
 #define CRC_SIZE                4
 #define MAC_HEADER_SIZE         14
 
-#define TX_BUF_SIZE     1536
-#define RX_BUF_SIZE     1536
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define MAX_FRAME_SIZE  (1518 + 4)
+#else
+#define MAX_FRAME_SIZE  1518
+#endif /* CONFIG_VLAN_802_1Q */
+
+#define TX_BUF_SIZE     (MAX_FRAME_SIZE+18)
+#define RX_BUF_SIZE     (MAX_FRAME_SIZE+18)
 
 #define NUM_TX_DESC     16      	/* Number of Tx descriptor registers. */
 #define NUM_RX_DESC     16       	/* Number of Rx descriptor registers. */
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 38a26df..f3efbd1 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -1525,7 +1525,7 @@
 	** This is to resolve faulty padding by the HW with 0xaa bytes.
 	*/
 	if (BytesSend < C_LEN_ETHERNET_MINSIZE) {
-		if ((pMessage = skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) == NULL) {
+		if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) {
 			spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags);
 			return 0;
 		}
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 5ca5a1b..19a4a16 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -44,12 +44,13 @@
 #include "skge.h"
 
 #define DRV_NAME		"skge"
-#define DRV_VERSION		"1.5"
+#define DRV_VERSION		"1.6"
 #define PFX			DRV_NAME " "
 
 #define DEFAULT_TX_RING_SIZE	128
 #define DEFAULT_RX_RING_SIZE	512
 #define MAX_TX_RING_SIZE	1024
+#define TX_LOW_WATER		(MAX_SKB_FRAGS + 1)
 #define MAX_RX_RING_SIZE	4096
 #define RX_COPY_THRESHOLD	128
 #define RX_BUF_SIZE		1536
@@ -401,7 +402,7 @@
 	int err;
 
 	if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
-	    p->tx_pending < MAX_SKB_FRAGS+1 || p->tx_pending > MAX_TX_RING_SIZE)
+	    p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE)
 		return -EINVAL;
 
 	skge->rx_ring.count = p->rx_pending;
@@ -603,7 +604,7 @@
 	struct skge_hw *hw = skge->hw;
 	int port = skge->port;
 
-	spin_lock_bh(&hw->phy_lock);
+	mutex_lock(&hw->phy_mutex);
 	if (hw->chip_id == CHIP_ID_GENESIS) {
 		switch (mode) {
 		case LED_MODE_OFF:
@@ -663,7 +664,7 @@
 				     PHY_M_LED_MO_RX(MO_LED_ON));
 		}
 	}
-	spin_unlock_bh(&hw->phy_lock);
+	mutex_unlock(&hw->phy_mutex);
 }
 
 /* blink LED's for finding board */
@@ -2038,7 +2039,7 @@
 	netif_stop_queue(skge->netdev);
 	netif_carrier_off(skge->netdev);
 
-	spin_lock_bh(&hw->phy_lock);
+	mutex_lock(&hw->phy_mutex);
 	if (hw->chip_id == CHIP_ID_GENESIS) {
 		genesis_reset(hw, port);
 		genesis_mac_init(hw, port);
@@ -2046,7 +2047,7 @@
 		yukon_reset(hw, port);
 		yukon_init(hw, port);
 	}
-	spin_unlock_bh(&hw->phy_lock);
+	mutex_unlock(&hw->phy_mutex);
 }
 
 /* Basic MII support */
@@ -2067,12 +2068,12 @@
 		/* fallthru */
 	case SIOCGMIIREG: {
 		u16 val = 0;
-		spin_lock_bh(&hw->phy_lock);
+		mutex_lock(&hw->phy_mutex);
 		if (hw->chip_id == CHIP_ID_GENESIS)
 			err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
 		else
 			err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val);
-		spin_unlock_bh(&hw->phy_lock);
+		mutex_unlock(&hw->phy_mutex);
 		data->val_out = val;
 		break;
 	}
@@ -2081,14 +2082,14 @@
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
-		spin_lock_bh(&hw->phy_lock);
+		mutex_lock(&hw->phy_mutex);
 		if (hw->chip_id == CHIP_ID_GENESIS)
 			err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f,
 				   data->val_in);
 		else
 			err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f,
 				   data->val_in);
-		spin_unlock_bh(&hw->phy_lock);
+		mutex_unlock(&hw->phy_mutex);
 		break;
 	}
 	return err;
@@ -2191,12 +2192,12 @@
 		goto free_rx_ring;
 
 	/* Initialize MAC */
-	spin_lock_bh(&hw->phy_lock);
+	mutex_lock(&hw->phy_mutex);
 	if (hw->chip_id == CHIP_ID_GENESIS)
 		genesis_mac_init(hw, port);
 	else
 		yukon_mac_init(hw, port);
-	spin_unlock_bh(&hw->phy_lock);
+	mutex_unlock(&hw->phy_mutex);
 
 	/* Configure RAMbuffers */
 	chunk = hw->ram_size / ((hw->ports + 1)*2);
@@ -2302,21 +2303,19 @@
 {
 	struct skge_port *skge = netdev_priv(dev);
 	struct skge_hw *hw = skge->hw;
-	struct skge_ring *ring = &skge->tx_ring;
 	struct skge_element *e;
 	struct skge_tx_desc *td;
 	int i;
 	u32 control, len;
 	u64 map;
+	unsigned long flags;
 
-	skb = skb_padto(skb, ETH_ZLEN);
-	if (!skb)
+	if (skb_padto(skb, ETH_ZLEN))
 		return NETDEV_TX_OK;
 
-	if (!spin_trylock(&skge->tx_lock)) {
+	if (!spin_trylock_irqsave(&skge->tx_lock, flags))
 		/* Collision - tell upper layer to requeue */
 		return NETDEV_TX_LOCKED;
-	}
 
 	if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) {
 		if (!netif_queue_stopped(dev)) {
@@ -2325,12 +2324,13 @@
 			printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
 			       dev->name);
 		}
-		spin_unlock(&skge->tx_lock);
+		spin_unlock_irqrestore(&skge->tx_lock, flags);
 		return NETDEV_TX_BUSY;
 	}
 
-	e = ring->to_use;
+	e = skge->tx_ring.to_use;
 	td = e->desc;
+	BUG_ON(td->control & BMU_OWN);
 	e->skb = skb;
 	len = skb_headlen(skb);
 	map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
@@ -2371,8 +2371,10 @@
 					   frag->size, PCI_DMA_TODEVICE);
 
 			e = e->next;
-			e->skb = NULL;
+			e->skb = skb;
 			tf = e->desc;
+			BUG_ON(tf->control & BMU_OWN);
+
 			tf->dma_lo = map;
 			tf->dma_hi = (u64) map >> 32;
 			pci_unmap_addr_set(e, mapaddr, map);
@@ -2389,56 +2391,68 @@
 
 	skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
 
-	if (netif_msg_tx_queued(skge))
+	if (unlikely(netif_msg_tx_queued(skge)))
 		printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n",
-		       dev->name, e - ring->start, skb->len);
+		       dev->name, e - skge->tx_ring.start, skb->len);
 
-	ring->to_use = e->next;
-	if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) {
+	skge->tx_ring.to_use = e->next;
+	if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) {
 		pr_debug("%s: transmit queue full\n", dev->name);
 		netif_stop_queue(dev);
 	}
 
-	mmiowb();
-	spin_unlock(&skge->tx_lock);
+	spin_unlock_irqrestore(&skge->tx_lock, flags);
 
 	dev->trans_start = jiffies;
 
 	return NETDEV_TX_OK;
 }
 
-static void skge_tx_complete(struct skge_port *skge, struct skge_element *last)
+
+/* Free resources associated with this reing element */
+static void skge_tx_free(struct skge_port *skge, struct skge_element *e,
+			 u32 control)
 {
 	struct pci_dev *pdev = skge->hw->pdev;
-	struct skge_element *e;
 
-	for (e = skge->tx_ring.to_clean; e != last; e = e->next) {
-		struct sk_buff *skb = e->skb;
-		int i;
+	BUG_ON(!e->skb);
 
-		e->skb = NULL;
+	/* skb header vs. fragment */
+	if (control & BMU_STF)
 		pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr),
-				 skb_headlen(skb), PCI_DMA_TODEVICE);
+				 pci_unmap_len(e, maplen),
+				 PCI_DMA_TODEVICE);
+	else
+		pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr),
+			       pci_unmap_len(e, maplen),
+			       PCI_DMA_TODEVICE);
 
-		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			e = e->next;
-			pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr),
-				       skb_shinfo(skb)->frags[i].size,
-				       PCI_DMA_TODEVICE);
-		}
+	if (control & BMU_EOF) {
+		if (unlikely(netif_msg_tx_done(skge)))
+			printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
+			       skge->netdev->name, e - skge->tx_ring.start);
 
-		dev_kfree_skb(skb);
+		dev_kfree_skb_any(e->skb);
 	}
-	skge->tx_ring.to_clean = e;
+	e->skb = NULL;
 }
 
+/* Free all buffers in transmit ring */
 static void skge_tx_clean(struct skge_port *skge)
 {
+	struct skge_element *e;
+	unsigned long flags;
 
-	spin_lock_bh(&skge->tx_lock);
-	skge_tx_complete(skge, skge->tx_ring.to_use);
+	spin_lock_irqsave(&skge->tx_lock, flags);
+	for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) {
+		struct skge_tx_desc *td = e->desc;
+		skge_tx_free(skge, e, td->control);
+		td->control = 0;
+	}
+
+	skge->tx_ring.to_clean = e;
 	netif_wake_queue(skge->netdev);
-	spin_unlock_bh(&skge->tx_lock);
+	spin_unlock_irqrestore(&skge->tx_lock, flags);
 }
 
 static void skge_tx_timeout(struct net_device *dev)
@@ -2664,32 +2678,28 @@
 	return NULL;
 }
 
-static void skge_tx_done(struct skge_port *skge)
+/* Free all buffers in Tx ring which are no longer owned by device */
+static void skge_txirq(struct net_device *dev)
 {
+	struct skge_port *skge = netdev_priv(dev);
 	struct skge_ring *ring = &skge->tx_ring;
-	struct skge_element *e, *last;
+	struct skge_element *e;
+
+	rmb();
 
 	spin_lock(&skge->tx_lock);
-	last = ring->to_clean;
 	for (e = ring->to_clean; e != ring->to_use; e = e->next) {
 		struct skge_tx_desc *td = e->desc;
 
 		if (td->control & BMU_OWN)
 			break;
 
-		if (td->control & BMU_EOF) {
-			last = e->next;
-			if (unlikely(netif_msg_tx_done(skge)))
-				printk(KERN_DEBUG PFX "%s: tx done slot %td\n",
-				       skge->netdev->name, e - ring->start);
-		}
+		skge_tx_free(skge, e, td->control);
 	}
+	skge->tx_ring.to_clean = e;
 
-	skge_tx_complete(skge, last);
-
-	skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
-
-	if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1)
+	if (netif_queue_stopped(skge->netdev)
+	    && skge_avail(&skge->tx_ring) > TX_LOW_WATER)
 		netif_wake_queue(skge->netdev);
 
 	spin_unlock(&skge->tx_lock);
@@ -2704,8 +2714,6 @@
 	int to_do = min(dev->quota, *budget);
 	int work_done = 0;
 
-	skge_tx_done(skge);
-
 	for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) {
 		struct skge_rx_desc *rd = e->desc;
 		struct sk_buff *skb;
@@ -2737,10 +2745,12 @@
 		return 1; /* not done */
 
 	netif_rx_complete(dev);
-	mmiowb();
 
-  	hw->intr_mask |= skge->port == 0 ? (IS_R1_F|IS_XA1_F) : (IS_R2_F|IS_XA2_F);
+	spin_lock_irq(&hw->hw_lock);
+	hw->intr_mask |= rxirqmask[skge->port];
   	skge_write32(hw, B0_IMSK, hw->intr_mask);
+	mmiowb();
+	spin_unlock_irq(&hw->hw_lock);
 
 	return 0;
 }
@@ -2847,16 +2857,16 @@
 }
 
 /*
- * Interrupt from PHY are handled in tasklet (soft irq)
+ * Interrupt from PHY are handled in work queue
  * because accessing phy registers requires spin wait which might
  * cause excess interrupt latency.
  */
-static void skge_extirq(unsigned long data)
+static void skge_extirq(void *arg)
 {
-	struct skge_hw *hw = (struct skge_hw *) data;
+	struct skge_hw *hw = arg;
 	int port;
 
-	spin_lock(&hw->phy_lock);
+	mutex_lock(&hw->phy_mutex);
 	for (port = 0; port < hw->ports; port++) {
 		struct net_device *dev = hw->dev[port];
 		struct skge_port *skge = netdev_priv(dev);
@@ -2868,10 +2878,12 @@
 				bcom_phy_intr(skge);
 		}
 	}
-	spin_unlock(&hw->phy_lock);
+	mutex_unlock(&hw->phy_mutex);
 
+	spin_lock_irq(&hw->hw_lock);
 	hw->intr_mask |= IS_EXT_REG;
 	skge_write32(hw, B0_IMSK, hw->intr_mask);
+	spin_unlock_irq(&hw->hw_lock);
 }
 
 static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
@@ -2884,54 +2896,68 @@
 	if (status == 0)
 		return IRQ_NONE;
 
+	spin_lock(&hw->hw_lock);
+	status &= hw->intr_mask;
 	if (status & IS_EXT_REG) {
 		hw->intr_mask &= ~IS_EXT_REG;
-		tasklet_schedule(&hw->ext_tasklet);
+		schedule_work(&hw->phy_work);
 	}
 
-	if (status & (IS_R1_F|IS_XA1_F)) {
+	if (status & IS_XA1_F) {
+		skge_write8(hw, Q_ADDR(Q_XA1, Q_CSR), CSR_IRQ_CL_F);
+		skge_txirq(hw->dev[0]);
+	}
+
+	if (status & IS_R1_F) {
 		skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F);
-		hw->intr_mask &= ~(IS_R1_F|IS_XA1_F);
+		hw->intr_mask &= ~IS_R1_F;
 		netif_rx_schedule(hw->dev[0]);
 	}
 
-	if (status & (IS_R2_F|IS_XA2_F)) {
-		skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
-		hw->intr_mask &= ~(IS_R2_F|IS_XA2_F);
-		netif_rx_schedule(hw->dev[1]);
-	}
-
-	if (likely((status & hw->intr_mask) == 0))
-		return IRQ_HANDLED;
-
-	if (status & IS_PA_TO_RX1) {
-		struct skge_port *skge = netdev_priv(hw->dev[0]);
-		++skge->net_stats.rx_over_errors;
-		skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1);
-	}
-
-	if (status & IS_PA_TO_RX2) {
-		struct skge_port *skge = netdev_priv(hw->dev[1]);
-		++skge->net_stats.rx_over_errors;
-		skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2);
-	}
-
 	if (status & IS_PA_TO_TX1)
 		skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1);
 
-	if (status & IS_PA_TO_TX2)
-		skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2);
+	if (status & IS_PA_TO_RX1) {
+		struct skge_port *skge = netdev_priv(hw->dev[0]);
+
+		++skge->net_stats.rx_over_errors;
+		skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1);
+	}
+
 
 	if (status & IS_MAC1)
 		skge_mac_intr(hw, 0);
 
-	if (status & IS_MAC2)
-		skge_mac_intr(hw, 1);
+	if (hw->dev[1]) {
+		if (status & IS_XA2_F) {
+			skge_write8(hw, Q_ADDR(Q_XA2, Q_CSR), CSR_IRQ_CL_F);
+			skge_txirq(hw->dev[1]);
+		}
+
+		if (status & IS_R2_F) {
+			skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F);
+			hw->intr_mask &= ~IS_R2_F;
+			netif_rx_schedule(hw->dev[1]);
+		}
+
+		if (status & IS_PA_TO_RX2) {
+			struct skge_port *skge = netdev_priv(hw->dev[1]);
+			++skge->net_stats.rx_over_errors;
+			skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2);
+		}
+
+		if (status & IS_PA_TO_TX2)
+			skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2);
+
+		if (status & IS_MAC2)
+			skge_mac_intr(hw, 1);
+	}
 
 	if (status & IS_HW_ERR)
 		skge_error_irq(hw);
 
 	skge_write32(hw, B0_IMSK, hw->intr_mask);
+	spin_unlock(&hw->hw_lock);
 
 	return IRQ_HANDLED;
 }
@@ -2957,7 +2983,7 @@
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	spin_lock_bh(&hw->phy_lock);
+	mutex_lock(&hw->phy_mutex);
 	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
 	memcpy_toio(hw->regs + B2_MAC_1 + port*8,
 		    dev->dev_addr, ETH_ALEN);
@@ -2970,7 +2996,7 @@
 		gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr);
 		gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr);
 	}
-	spin_unlock_bh(&hw->phy_lock);
+	mutex_unlock(&hw->phy_mutex);
 
 	return 0;
 }
@@ -3082,6 +3108,7 @@
 	else
 		hw->ram_size = t8 * 4096;
 
+	spin_lock_init(&hw->hw_lock);
 	hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
 	if (hw->ports > 1)
 		hw->intr_mask |= IS_PORT_2;
@@ -3150,14 +3177,14 @@
 
 	skge_write32(hw, B0_IMSK, hw->intr_mask);
 
-	spin_lock_bh(&hw->phy_lock);
+	mutex_lock(&hw->phy_mutex);
 	for (i = 0; i < hw->ports; i++) {
 		if (hw->chip_id == CHIP_ID_GENESIS)
 			genesis_reset(hw, i);
 		else
 			yukon_reset(hw, i);
 	}
-	spin_unlock_bh(&hw->phy_lock);
+	mutex_unlock(&hw->phy_mutex);
 
 	return 0;
 }
@@ -3305,8 +3332,8 @@
 	}
 
 	hw->pdev = pdev;
-	spin_lock_init(&hw->phy_lock);
-	tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw);
+	mutex_init(&hw->phy_mutex);
+	INIT_WORK(&hw->phy_work, skge_extirq, hw);
 
 	hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
 	if (!hw->regs) {
@@ -3334,6 +3361,14 @@
 	if ((dev = skge_devinit(hw, 0, using_dac)) == NULL)
 		goto err_out_led_off;
 
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		printk(KERN_ERR PFX "%s: bad (zero?) ethernet address in rom\n",
+		       pci_name(pdev));
+		err = -EIO;
+		goto err_out_free_netdev;
+	}
+
+
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR PFX "%s: cannot register net device\n",
@@ -3388,11 +3423,15 @@
 	dev0 = hw->dev[0];
 	unregister_netdev(dev0);
 
+	spin_lock_irq(&hw->hw_lock);
+	hw->intr_mask = 0;
 	skge_write32(hw, B0_IMSK, 0);
+	spin_unlock_irq(&hw->hw_lock);
+
 	skge_write16(hw, B0_LED, LED_STAT_OFF);
 	skge_write8(hw, B0_CTST, CS_RST_SET);
 
-	tasklet_kill(&hw->ext_tasklet);
+	flush_scheduled_work();
 
 	free_irq(pdev->irq, hw);
 	pci_release_regions(pdev);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 1f1ce88..ed19ff4 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2388,6 +2388,7 @@
 struct skge_hw {
 	void __iomem  	     *regs;
 	struct pci_dev	     *pdev;
+	spinlock_t	     hw_lock;
 	u32		     intr_mask;
 	struct net_device    *dev[2];
 
@@ -2399,9 +2400,8 @@
 	u32	     	     ram_size;
 	u32	     	     ram_offset;
 	u16		     phy_addr;
-
-	struct tasklet_struct ext_tasklet;
-	spinlock_t	     phy_lock;
+	struct work_struct   phy_work;
+	struct mutex	     phy_mutex;
 };
 
 enum {
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index fba1e4d4..d357787 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1160,7 +1160,7 @@
 	count = sizeof(dma_addr_t) / sizeof(u32);
 	count += skb_shinfo(skb)->nr_frags * count;
 
-	if (skb_shinfo(skb)->tso_size)
+	if (skb_shinfo(skb)->gso_size)
 		++count;
 
 	if (skb->ip_summed == CHECKSUM_HW)
@@ -1232,7 +1232,7 @@
 	}
 
 	/* Check for TCP Segmentation Offload */
-	mss = skb_shinfo(skb)->tso_size;
+	mss = skb_shinfo(skb)->gso_size;
 	if (mss != 0) {
 		/* just drop the packet if non-linear expansion fails */
 		if (skb_header_cloned(skb) &&
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 3db30cd..5b4e852 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -553,7 +553,7 @@
 
 /* This is set up so that only a single autoprobe takes place per call.
 ISA device autoprobes on a running machine are not recommended. */
-int
+int __init
 init_module(void)
 {
 	struct net_device *dev;
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index b3e397d..ff9bd97 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -421,7 +421,7 @@
 MODULE_DESCRIPTION("SMC Ultra32 EISA ethernet driver");
 MODULE_LICENSE("GPL");
 
-int init_module(void)
+int __init init_module(void)
 {
 	int this_dev, found = 0;
 
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
new file mode 100644
index 0000000..bdd8702
--- /dev/null
+++ b/drivers/net/smc911x.c
@@ -0,0 +1,2307 @@
+/*
+ * smc911x.c
+ * This is a driver for SMSC's LAN911{5,6,7,8} single-chip Ethernet devices.
+ *
+ * Copyright (C) 2005 Sensoria Corp
+ *	   Derived from the unified SMC91x driver by Nicolas Pitre
+ *	   and the smsc911x.c reference driver by SMSC
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Arguments:
+ *	 watchdog  = TX watchdog timeout
+ *	 tx_fifo_kb = Size of TX FIFO in KB
+ *
+ * History:
+ *	  04/16/05	Dustin McIntire		 Initial version
+ */
+static const char version[] =
+	 "smc911x.c: v1.0 04-16-2005 by Dustin McIntire <dustin@sensoria.com>\n";
+
+/* Debugging options */
+#define ENABLE_SMC_DEBUG_RX		0
+#define ENABLE_SMC_DEBUG_TX		0
+#define ENABLE_SMC_DEBUG_DMA		0
+#define ENABLE_SMC_DEBUG_PKTS		0
+#define ENABLE_SMC_DEBUG_MISC		0
+#define ENABLE_SMC_DEBUG_FUNC		0
+
+#define SMC_DEBUG_RX		((ENABLE_SMC_DEBUG_RX	? 1 : 0) << 0)
+#define SMC_DEBUG_TX		((ENABLE_SMC_DEBUG_TX	? 1 : 0) << 1)
+#define SMC_DEBUG_DMA		((ENABLE_SMC_DEBUG_DMA	? 1 : 0) << 2)
+#define SMC_DEBUG_PKTS		((ENABLE_SMC_DEBUG_PKTS ? 1 : 0) << 3)
+#define SMC_DEBUG_MISC		((ENABLE_SMC_DEBUG_MISC ? 1 : 0) << 4)
+#define SMC_DEBUG_FUNC		((ENABLE_SMC_DEBUG_FUNC ? 1 : 0) << 5)
+
+#ifndef SMC_DEBUG
+#define SMC_DEBUG	 ( SMC_DEBUG_RX	  | \
+			   SMC_DEBUG_TX	  | \
+			   SMC_DEBUG_DMA  | \
+			   SMC_DEBUG_PKTS | \
+			   SMC_DEBUG_MISC | \
+			   SMC_DEBUG_FUNC   \
+			 )
+#endif
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/workqueue.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "smc911x.h"
+
+/*
+ * Transmit timeout, default 5 seconds.
+ */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+static int tx_fifo_kb=8;
+module_param(tx_fifo_kb, int, 0400);
+MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)");
+
+MODULE_LICENSE("GPL");
+
+/*
+ * The internal workings of the driver.  If you are changing anything
+ * here with the SMC stuff, you should have the datasheet and know
+ * what you are doing.
+ */
+#define CARDNAME "smc911x"
+
+/*
+ * Use power-down feature of the chip
+ */
+#define POWER_DOWN		 1
+
+
+/* store this information for the driver.. */
+struct smc911x_local {
+	/*
+	 * If I have to wait until the DMA is finished and ready to reload a
+	 * packet, I will store the skbuff here. Then, the DMA will send it
+	 * out and free it.
+	 */
+	struct sk_buff *pending_tx_skb;
+
+	/*
+	 * these are things that the kernel wants me to keep, so users
+	 * can find out semi-useless statistics of how well the card is
+	 * performing
+	 */
+	struct net_device_stats stats;
+
+	/* version/revision of the SMC911x chip */
+	u16 version;
+	u16 revision;
+
+	/* FIFO sizes */
+	int tx_fifo_kb;
+	int tx_fifo_size;
+	int rx_fifo_size;
+	int afc_cfg;
+
+	/* Contains the current active receive/phy mode */
+	int ctl_rfduplx;
+	int ctl_rspeed;
+
+	u32 msg_enable;
+	u32 phy_type;
+	struct mii_if_info mii;
+
+	/* work queue */
+	struct work_struct phy_configure;
+	int work_pending;
+
+	int tx_throttle;
+	spinlock_t lock;
+
+#ifdef SMC_USE_DMA
+	/* DMA needs the physical address of the chip */
+	u_long physaddr;
+	int rxdma;
+	int txdma;
+	int rxdma_active;
+	int txdma_active;
+	struct sk_buff *current_rx_skb;
+	struct sk_buff *current_tx_skb;
+	struct device *dev;
+#endif
+};
+
+#if SMC_DEBUG > 0
+#define DBG(n, args...)				 \
+	do {					 \
+		if (SMC_DEBUG & (n))		 \
+			printk(args);		 \
+	} while (0)
+
+#define PRINTK(args...)   printk(args)
+#else
+#define DBG(n, args...)   do { } while (0)
+#define PRINTK(args...)   printk(KERN_DEBUG args)
+#endif
+
+#if SMC_DEBUG_PKTS > 0
+static void PRINT_PKT(u_char *buf, int length)
+{
+	int i;
+	int remainder;
+	int lines;
+
+	lines = length / 16;
+	remainder = length % 16;
+
+	for (i = 0; i < lines ; i ++) {
+		int cur;
+		for (cur = 0; cur < 8; cur++) {
+			u_char a, b;
+			a = *buf++;
+			b = *buf++;
+			printk("%02x%02x ", a, b);
+		}
+		printk("\n");
+	}
+	for (i = 0; i < remainder/2 ; i++) {
+		u_char a, b;
+		a = *buf++;
+		b = *buf++;
+		printk("%02x%02x ", a, b);
+	}
+	printk("\n");
+}
+#else
+#define PRINT_PKT(x...)  do { } while (0)
+#endif
+
+
+/* this enables an interrupt in the interrupt mask register */
+#define SMC_ENABLE_INT(x) do {				\
+	unsigned int  __mask;				\
+	unsigned long __flags;				\
+	spin_lock_irqsave(&lp->lock, __flags);		\
+	__mask = SMC_GET_INT_EN();			\
+	__mask |= (x);					\
+	SMC_SET_INT_EN(__mask);				\
+	spin_unlock_irqrestore(&lp->lock, __flags);	\
+} while (0)
+
+/* this disables an interrupt from the interrupt mask register */
+#define SMC_DISABLE_INT(x) do {				\
+	unsigned int  __mask;				\
+	unsigned long __flags;				\
+	spin_lock_irqsave(&lp->lock, __flags);		\
+	__mask = SMC_GET_INT_EN();			\
+	__mask &= ~(x);					\
+	SMC_SET_INT_EN(__mask);				\
+	spin_unlock_irqrestore(&lp->lock, __flags);	\
+} while (0)
+
+/*
+ * this does a soft reset on the device
+ */
+static void smc911x_reset(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned int reg, timeout=0, resets=1;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	/*	 Take out of PM setting first */
+	if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) {
+		/* Write to the bytetest will take out of powerdown */
+		SMC_SET_BYTE_TEST(0);
+		timeout=10;
+		do {
+			udelay(10);
+			reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_;
+		} while ( timeout-- && !reg);
+		if (timeout == 0) {
+			PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name);
+			return;
+		}
+	}
+
+	/* Disable all interrupts */
+	spin_lock_irqsave(&lp->lock, flags);
+	SMC_SET_INT_EN(0);
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	while (resets--) {
+		SMC_SET_HW_CFG(HW_CFG_SRST_);
+		timeout=10;
+		do {
+			udelay(10);
+			reg = SMC_GET_HW_CFG();
+			/* If chip indicates reset timeout then try again */
+			if (reg & HW_CFG_SRST_TO_) {
+				PRINTK("%s: chip reset timeout, retrying...\n", dev->name);
+				resets++;
+				break;
+			}
+		} while ( timeout-- && (reg & HW_CFG_SRST_));
+	}
+	if (timeout == 0) {
+		PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name);
+		return;
+	}
+
+	/* make sure EEPROM has finished loading before setting GPIO_CFG */
+	timeout=1000;
+	while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) {
+		udelay(10);
+	}
+	if (timeout == 0){
+		PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name);
+		return;
+	}
+
+	/* Initialize interrupts */
+	SMC_SET_INT_EN(0);
+	SMC_ACK_INT(-1);
+
+	/* Reset the FIFO level and flow control settings */
+	SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16);
+//TODO: Figure out what appropriate pause time is
+	SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_);
+	SMC_SET_AFC_CFG(lp->afc_cfg);
+
+
+	/* Set to LED outputs */
+	SMC_SET_GPIO_CFG(0x70070000);
+
+	/*
+	 * Deassert IRQ for 1*10us for edge type interrupts
+	 * and drive IRQ pin push-pull
+	 */
+	SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ );
+
+	/* clear anything saved */
+	if (lp->pending_tx_skb != NULL) {
+		dev_kfree_skb (lp->pending_tx_skb);
+		lp->pending_tx_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_aborted_errors++;
+	}
+}
+
+/*
+ * Enable Interrupts, Receive, and Transmit
+ */
+static void smc911x_enable(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned mask, cfg, cr;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	SMC_SET_MAC_ADDR(dev->dev_addr);
+
+	/* Enable TX */
+	cfg = SMC_GET_HW_CFG();
+	cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF;
+	cfg |= HW_CFG_SF_;
+	SMC_SET_HW_CFG(cfg);
+	SMC_SET_FIFO_TDA(0xFF);
+	/* Update TX stats on every 64 packets received or every 1 sec */
+	SMC_SET_FIFO_TSL(64);
+	SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	SMC_GET_MAC_CR(cr);
+	cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_;
+	SMC_SET_MAC_CR(cr);
+	SMC_SET_TX_CFG(TX_CFG_TX_ON_);
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	/* Add 2 byte padding to start of packets */
+	SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_);
+
+	/* Turn on receiver and enable RX */
+	if (cr & MAC_CR_RXEN_)
+		DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ );
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	/* Interrupt on every received packet */
+	SMC_SET_FIFO_RSA(0x01);
+	SMC_SET_FIFO_RSL(0x00);
+
+	/* now, enable interrupts */
+	mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ |
+		INT_EN_GPT_INT_EN_ | INT_EN_RXDFH_INT_EN_ | INT_EN_RXE_EN_ |
+		INT_EN_PHY_INT_EN_;
+	if (IS_REV_A(lp->revision))
+		mask|=INT_EN_RDFL_EN_;
+	else {
+		mask|=INT_EN_RDFO_EN_;
+	}
+	SMC_ENABLE_INT(mask);
+}
+
+/*
+ * this puts the device in an inactive state
+ */
+static void smc911x_shutdown(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned cr;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+
+	/* Disable IRQ's */
+	SMC_SET_INT_EN(0);
+
+	/* Turn of Rx and TX */
+	spin_lock_irqsave(&lp->lock, flags);
+	SMC_GET_MAC_CR(cr);
+	cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_);
+	SMC_SET_MAC_CR(cr);
+	SMC_SET_TX_CFG(TX_CFG_STOP_TX_);
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+static inline void smc911x_drop_pkt(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int fifo_count, timeout, reg;
+
+	DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__);
+	fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF;
+	if (fifo_count <= 4) {
+		/* Manually dump the packet data */
+		while (fifo_count--)
+			SMC_GET_RX_FIFO();
+	} else	 {
+		/* Fast forward through the bad packet */
+		SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_);
+		timeout=50;
+		do {
+			udelay(10);
+			reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_;
+		} while ( timeout-- && reg);
+		if (timeout == 0) {
+			PRINTK("%s: timeout waiting for RX fast forward\n", dev->name);
+		}
+	}
+}
+
+/*
+ * This is the procedure to handle the receipt of a packet.
+ * It should be called after checking for packet presence in
+ * the RX status FIFO.	 It must be called with the spin lock
+ * already held.
+ */
+static inline void	 smc911x_rcv(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int pkt_len, status;
+	struct sk_buff *skb;
+	unsigned char *data;
+
+	DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n",
+		dev->name, __FUNCTION__);
+	status = SMC_GET_RX_STS_FIFO();
+	DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n",
+		dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff);
+	pkt_len = (status & RX_STS_PKT_LEN_) >> 16;
+	if (status & RX_STS_ES_) {
+		/* Deal with a bad packet */
+		lp->stats.rx_errors++;
+		if (status & RX_STS_CRC_ERR_)
+			lp->stats.rx_crc_errors++;
+		else {
+			if (status & RX_STS_LEN_ERR_)
+				lp->stats.rx_length_errors++;
+			if (status & RX_STS_MCAST_)
+				lp->stats.multicast++;
+		}
+		/* Remove the bad packet data from the RX FIFO */
+		smc911x_drop_pkt(dev);
+	} else {
+		/* Receive a valid packet */
+		/* Alloc a buffer with extra room for DMA alignment */
+		skb=dev_alloc_skb(pkt_len+32);
+		if (unlikely(skb == NULL)) {
+			PRINTK( "%s: Low memory, rcvd packet dropped.\n",
+				dev->name);
+			lp->stats.rx_dropped++;
+			smc911x_drop_pkt(dev);
+			return;
+		}
+		/* Align IP header to 32 bits
+		 * Note that the device is configured to add a 2
+		 * byte padding to the packet start, so we really
+		 * want to write to the orignal data pointer */
+		data = skb->data;
+		skb_reserve(skb, 2);
+		skb_put(skb,pkt_len-4);
+#ifdef SMC_USE_DMA
+		{
+		unsigned int fifo;
+		/* Lower the FIFO threshold if possible */
+		fifo = SMC_GET_FIFO_INT();
+		if (fifo & 0xFF) fifo--;
+		DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n",
+			dev->name, fifo & 0xff);
+		SMC_SET_FIFO_INT(fifo);
+		/* Setup RX DMA */
+		SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_));
+		lp->rxdma_active = 1;
+		lp->current_rx_skb = skb;
+		SMC_PULL_DATA(data, (pkt_len+2+15) & ~15);
+		/* Packet processing deferred to DMA RX interrupt */
+		}
+#else
+		SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_));
+		SMC_PULL_DATA(data, pkt_len+2+3);
+
+		DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name,);
+		PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64);
+		dev->last_rx = jiffies;
+		skb->dev = dev;
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
+		lp->stats.rx_packets++;
+		lp->stats.rx_bytes += pkt_len-4;
+#endif
+	}
+}
+
+/*
+ * This is called to actually send a packet to the chip.
+ */
+static void smc911x_hardware_send_pkt(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	struct sk_buff *skb;
+	unsigned int cmdA, cmdB, len;
+	unsigned char *buf;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__);
+	BUG_ON(lp->pending_tx_skb == NULL);
+
+	skb = lp->pending_tx_skb;
+	lp->pending_tx_skb = NULL;
+
+	/* cmdA {25:24] data alignment [20:16] start offset [10:0] buffer length */
+	/* cmdB {31:16] pkt tag [10:0] length */
+#ifdef SMC_USE_DMA
+	/* 16 byte buffer alignment mode */
+	buf = (char*)((u32)(skb->data) & ~0xF);
+	len = (skb->len + 0xF + ((u32)skb->data & 0xF)) & ~0xF;
+	cmdA = (1<<24) | (((u32)skb->data & 0xF)<<16) |
+			TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ |
+			skb->len;
+#else
+	buf = (char*)((u32)skb->data & ~0x3);
+	len = (skb->len + 3 + ((u32)skb->data & 3)) & ~0x3;
+	cmdA = (((u32)skb->data & 0x3) << 16) |
+			TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ |
+			skb->len;
+#endif
+	/* tag is packet length so we can use this in stats update later */
+	cmdB = (skb->len  << 16) | (skb->len & 0x7FF);
+
+	DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n",
+		 dev->name, len, len, buf, cmdA, cmdB);
+	SMC_SET_TX_FIFO(cmdA);
+	SMC_SET_TX_FIFO(cmdB);
+
+	DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name);
+	PRINT_PKT(buf, len <= 64 ? len : 64);
+
+	/* Send pkt via PIO or DMA */
+#ifdef SMC_USE_DMA
+	lp->current_tx_skb = skb;
+	SMC_PUSH_DATA(buf, len);
+	/* DMA complete IRQ will free buffer and set jiffies */
+#else
+	SMC_PUSH_DATA(buf, len);
+	dev->trans_start = jiffies;
+	dev_kfree_skb(skb);
+#endif
+	spin_lock_irqsave(&lp->lock, flags);
+	if (!lp->tx_throttle) {
+		netif_wake_queue(dev);
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+	SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_);
+}
+
+/*
+ * Since I am not sure if I will have enough room in the chip's ram
+ * to store the packet, I call this routine which either sends it
+ * now, or set the card to generates an interrupt when ready
+ * for the packet.
+ */
+static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int free;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
+		dev->name, __FUNCTION__);
+
+	BUG_ON(lp->pending_tx_skb != NULL);
+
+	free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_;
+	DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free);
+
+	/* Turn off the flow when running out of space in FIFO */
+	if (free <= SMC911X_TX_FIFO_LOW_THRESHOLD) {
+		DBG(SMC_DEBUG_TX, "%s: Disabling data flow due to low FIFO space (%d)\n",
+			dev->name, free);
+		spin_lock_irqsave(&lp->lock, flags);
+		/* Reenable when at least 1 packet of size MTU present */
+		SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64);
+		lp->tx_throttle = 1;
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+
+	/* Drop packets when we run out of space in TX FIFO
+	 * Account for overhead required for:
+	 *
+	 *	  Tx command words			 8 bytes
+	 *	  Start offset				 15 bytes
+	 *	  End padding				 15 bytes
+	 */
+	if (unlikely(free < (skb->len + 8 + 15 + 15))) {
+		printk("%s: No Tx free space %d < %d\n",
+			dev->name, free, skb->len);
+		lp->pending_tx_skb = NULL;
+		lp->stats.tx_errors++;
+		lp->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return 0;
+	}
+
+#ifdef SMC_USE_DMA
+	{
+		/* If the DMA is already running then defer this packet Tx until
+		 * the DMA IRQ starts it
+		 */
+		spin_lock_irqsave(&lp->lock, flags);
+		if (lp->txdma_active) {
+			DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Tx DMA running, deferring packet\n", dev->name);
+			lp->pending_tx_skb = skb;
+			netif_stop_queue(dev);
+			spin_unlock_irqrestore(&lp->lock, flags);
+			return 0;
+		} else {
+			DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name);
+			lp->txdma_active = 1;
+		}
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+#endif
+	lp->pending_tx_skb = skb;
+	smc911x_hardware_send_pkt(dev);
+
+	return 0;
+}
+
+/*
+ * This handles a TX status interrupt, which is only called when:
+ * - a TX error occurred, or
+ * - TX of a packet completed.
+ */
+static void smc911x_tx(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned int tx_status;
+
+	DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n",
+		dev->name, __FUNCTION__);
+
+	/* Collect the TX status */
+	while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) {
+		DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n",
+			dev->name,
+			(SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16);
+		tx_status = SMC_GET_TX_STS_FIFO();
+		lp->stats.tx_packets++;
+		lp->stats.tx_bytes+=tx_status>>16;
+		DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n",
+			dev->name, (tx_status & 0xffff0000) >> 16,
+			tx_status & 0x0000ffff);
+		/* count Tx errors, but ignore lost carrier errors when in
+		 * full-duplex mode */
+		if ((tx_status & TX_STS_ES_) && !(lp->ctl_rfduplx &&
+		    !(tx_status & 0x00000306))) {
+			lp->stats.tx_errors++;
+		}
+		if (tx_status & TX_STS_MANY_COLL_) {
+			lp->stats.collisions+=16;
+			lp->stats.tx_aborted_errors++;
+		} else {
+			lp->stats.collisions+=(tx_status & TX_STS_COLL_CNT_) >> 3;
+		}
+		/* carrier error only has meaning for half-duplex communication */
+		if ((tx_status & (TX_STS_LOC_ | TX_STS_NO_CARR_)) &&
+		    !lp->ctl_rfduplx) {
+			lp->stats.tx_carrier_errors++;
+		}
+		if (tx_status & TX_STS_LATE_COLL_) {
+			lp->stats.collisions++;
+			lp->stats.tx_aborted_errors++;
+		}
+	}
+}
+
+
+/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/
+/*
+ * Reads a register from the MII Management serial interface
+ */
+
+static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int phydata;
+
+	SMC_GET_MII(phyreg, phyaddr, phydata);
+
+	DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n",
+		__FUNCTION__, phyaddr, phyreg, phydata);
+	return phydata;
+}
+
+
+/*
+ * Writes a register to the MII Management serial interface
+ */
+static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg,
+			int phydata)
+{
+	unsigned long ioaddr = dev->base_addr;
+
+	DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n",
+		__FUNCTION__, phyaddr, phyreg, phydata);
+
+	SMC_SET_MII(phyreg, phyaddr, phydata);
+}
+
+/*
+ * Finds and reports the PHY address (115 and 117 have external
+ * PHY interface 118 has internal only
+ */
+static void smc911x_phy_detect(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	int phyaddr;
+	unsigned int cfg, id1, id2;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	lp->phy_type = 0;
+
+	/*
+	 * Scan all 32 PHY addresses if necessary, starting at
+	 * PHY#1 to PHY#31, and then PHY#0 last.
+	 */
+	switch(lp->version) {
+		case 0x115:
+		case 0x117:
+			cfg = SMC_GET_HW_CFG();
+			if (cfg & HW_CFG_EXT_PHY_DET_) {
+				cfg &= ~HW_CFG_PHY_CLK_SEL_;
+				cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
+				SMC_SET_HW_CFG(cfg);
+				udelay(10); /* Wait for clocks to stop */
+
+				cfg |= HW_CFG_EXT_PHY_EN_;
+				SMC_SET_HW_CFG(cfg);
+				udelay(10); /* Wait for clocks to stop */
+
+				cfg &= ~HW_CFG_PHY_CLK_SEL_;
+				cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
+				SMC_SET_HW_CFG(cfg);
+				udelay(10); /* Wait for clocks to stop */
+
+				cfg |= HW_CFG_SMI_SEL_;
+				SMC_SET_HW_CFG(cfg);
+
+				for (phyaddr = 1; phyaddr < 32; ++phyaddr) {
+
+					/* Read the PHY identifiers */
+					SMC_GET_PHY_ID1(phyaddr & 31, id1);
+					SMC_GET_PHY_ID2(phyaddr & 31, id2);
+
+					/* Make sure it is a valid identifier */
+					if (id1 != 0x0000 && id1 != 0xffff &&
+					    id1 != 0x8000 && id2 != 0x0000 &&
+					    id2 != 0xffff && id2 != 0x8000) {
+						/* Save the PHY's address */
+						lp->mii.phy_id = phyaddr & 31;
+						lp->phy_type = id1 << 16 | id2;
+						break;
+					}
+				}
+			}
+		default:
+			/* Internal media only */
+			SMC_GET_PHY_ID1(1, id1);
+			SMC_GET_PHY_ID2(1, id2);
+			/* Save the PHY's address */
+			lp->mii.phy_id = 1;
+			lp->phy_type = id1 << 16 | id2;
+	}
+
+	DBG(SMC_DEBUG_MISC, "%s: phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%d\n",
+		dev->name, id1, id2, lp->mii.phy_id);
+}
+
+/*
+ * Sets the PHY to a configuration as determined by the user.
+ * Called with spin_lock held.
+ */
+static int smc911x_phy_fixed(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int phyaddr = lp->mii.phy_id;
+	int bmcr;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	/* Enter Link Disable state */
+	SMC_GET_PHY_BMCR(phyaddr, bmcr);
+	bmcr |= BMCR_PDOWN;
+	SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+	/*
+	 * Set our fixed capabilities
+	 * Disable auto-negotiation
+	 */
+	bmcr &= ~BMCR_ANENABLE;
+	if (lp->ctl_rfduplx)
+		bmcr |= BMCR_FULLDPLX;
+
+	if (lp->ctl_rspeed == 100)
+		bmcr |= BMCR_SPEED100;
+
+	/* Write our capabilities to the phy control register */
+	SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+	/* Re-Configure the Receive/Phy Control register */
+	bmcr &= ~BMCR_PDOWN;
+	SMC_SET_PHY_BMCR(phyaddr, bmcr);
+
+	return 1;
+}
+
+/*
+ * smc911x_phy_reset - reset the phy
+ * @dev: net device
+ * @phy: phy address
+ *
+ * Issue a software reset for the specified PHY and
+ * wait up to 100ms for the reset to complete.	 We should
+ * not access the PHY for 50ms after issuing the reset.
+ *
+ * The time to wait appears to be dependent on the PHY.
+ *
+ */
+static int smc911x_phy_reset(struct net_device *dev, int phy)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int timeout;
+	unsigned long flags;
+	unsigned int reg;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	reg = SMC_GET_PMT_CTRL();
+	reg &= ~0xfffff030;
+	reg |= PMT_CTRL_PHY_RST_;
+	SMC_SET_PMT_CTRL(reg);
+	spin_unlock_irqrestore(&lp->lock, flags);
+	for (timeout = 2; timeout; timeout--) {
+		msleep(50);
+		spin_lock_irqsave(&lp->lock, flags);
+		reg = SMC_GET_PMT_CTRL();
+		spin_unlock_irqrestore(&lp->lock, flags);
+		if (!(reg & PMT_CTRL_PHY_RST_)) {
+			/* extra delay required because the phy may
+			 * not be completed with its reset
+			 * when PHY_BCR_RESET_ is cleared. 256us
+			 * should suffice, but use 500us to be safe
+			 */
+			udelay(500);
+		break;
+		}
+	}
+
+	return reg & PMT_CTRL_PHY_RST_;
+}
+
+/*
+ * smc911x_phy_powerdown - powerdown phy
+ * @dev: net device
+ * @phy: phy address
+ *
+ * Power down the specified PHY
+ */
+static void smc911x_phy_powerdown(struct net_device *dev, int phy)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int bmcr;
+
+	/* Enter Link Disable state */
+	SMC_GET_PHY_BMCR(phy, bmcr);
+	bmcr |= BMCR_PDOWN;
+	SMC_SET_PHY_BMCR(phy, bmcr);
+}
+
+/*
+ * smc911x_phy_check_media - check the media status and adjust BMCR
+ * @dev: net device
+ * @init: set true for initialisation
+ *
+ * Select duplex mode depending on negotiation state.	This
+ * also updates our carrier state.
+ */
+static void smc911x_phy_check_media(struct net_device *dev, int init)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int phyaddr = lp->mii.phy_id;
+	unsigned int bmcr, cr;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
+		/* duplex state has changed */
+		SMC_GET_PHY_BMCR(phyaddr, bmcr);
+		SMC_GET_MAC_CR(cr);
+		if (lp->mii.full_duplex) {
+			DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name);
+			bmcr |= BMCR_FULLDPLX;
+			cr |= MAC_CR_RCVOWN_;
+		} else {
+			DBG(SMC_DEBUG_MISC, "%s: Configuring for half-duplex mode\n", dev->name);
+			bmcr &= ~BMCR_FULLDPLX;
+			cr &= ~MAC_CR_RCVOWN_;
+		}
+		SMC_SET_PHY_BMCR(phyaddr, bmcr);
+		SMC_SET_MAC_CR(cr);
+	}
+}
+
+/*
+ * Configures the specified PHY through the MII management interface
+ * using Autonegotiation.
+ * Calls smc911x_phy_fixed() if the user has requested a certain config.
+ * If RPC ANEG bit is set, the media selection is dependent purely on
+ * the selection by the MII (either in the MII BMCR reg or the result
+ * of autonegotiation.)  If the RPC ANEG bit is cleared, the selection
+ * is controlled by the RPC SPEED and RPC DPLX bits.
+ */
+static void smc911x_phy_configure(void *data)
+{
+	struct net_device *dev = data;
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int phyaddr = lp->mii.phy_id;
+	int my_phy_caps; /* My PHY capabilities */
+	int my_ad_caps; /* My Advertised capabilities */
+	int status;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__);
+
+	/*
+	 * We should not be called if phy_type is zero.
+	 */
+	if (lp->phy_type == 0)
+		 goto smc911x_phy_configure_exit;
+
+	if (smc911x_phy_reset(dev, phyaddr)) {
+		printk("%s: PHY reset timed out\n", dev->name);
+		goto smc911x_phy_configure_exit;
+	}
+	spin_lock_irqsave(&lp->lock, flags);
+
+	/*
+	 * Enable PHY Interrupts (for register 18)
+	 * Interrupts listed here are enabled
+	 */
+	SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ |
+		 PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ |
+		 PHY_INT_MASK_LINK_DOWN_);
+
+	/* If the user requested no auto neg, then go set his request */
+	if (lp->mii.force_media) {
+		smc911x_phy_fixed(dev);
+		goto smc911x_phy_configure_exit;
+	}
+
+	/* Copy our capabilities from MII_BMSR to MII_ADVERTISE */
+	SMC_GET_PHY_BMSR(phyaddr, my_phy_caps);
+	if (!(my_phy_caps & BMSR_ANEGCAPABLE)) {
+		printk(KERN_INFO "Auto negotiation NOT supported\n");
+		smc911x_phy_fixed(dev);
+		goto smc911x_phy_configure_exit;
+	}
+
+	/* CSMA capable w/ both pauses */
+	my_ad_caps = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+
+	if (my_phy_caps & BMSR_100BASE4)
+		my_ad_caps |= ADVERTISE_100BASE4;
+	if (my_phy_caps & BMSR_100FULL)
+		my_ad_caps |= ADVERTISE_100FULL;
+	if (my_phy_caps & BMSR_100HALF)
+		my_ad_caps |= ADVERTISE_100HALF;
+	if (my_phy_caps & BMSR_10FULL)
+		my_ad_caps |= ADVERTISE_10FULL;
+	if (my_phy_caps & BMSR_10HALF)
+		my_ad_caps |= ADVERTISE_10HALF;
+
+	/* Disable capabilities not selected by our user */
+	if (lp->ctl_rspeed != 100)
+		my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF);
+
+	 if (!lp->ctl_rfduplx)
+		my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL);
+
+	/* Update our Auto-Neg Advertisement Register */
+	SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps);
+	lp->mii.advertising = my_ad_caps;
+
+	/*
+	 * Read the register back.	 Without this, it appears that when
+	 * auto-negotiation is restarted, sometimes it isn't ready and
+	 * the link does not come up.
+	 */
+	udelay(10);
+	SMC_GET_PHY_MII_ADV(phyaddr, status);
+
+	DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps);
+	DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps);
+
+	/* Restart auto-negotiation process in order to advertise my caps */
+	SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART);
+
+	smc911x_phy_check_media(dev, 1);
+
+smc911x_phy_configure_exit:
+	spin_unlock_irqrestore(&lp->lock, flags);
+	lp->work_pending = 0;
+}
+
+/*
+ * smc911x_phy_interrupt
+ *
+ * Purpose:  Handle interrupts relating to PHY register 18. This is
+ *	 called from the "hard" interrupt handler under our private spinlock.
+ */
+static void smc911x_phy_interrupt(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int phyaddr = lp->mii.phy_id;
+	int status;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	if (lp->phy_type == 0)
+		return;
+
+	smc911x_phy_check_media(dev, 0);
+	/* read to clear status bits */
+	SMC_GET_PHY_INT_SRC(phyaddr,status);
+	DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n",
+		dev->name, status & 0xffff);
+	DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n",
+		dev->name, SMC_GET_AFC_CFG());
+}
+
+/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/
+
+/*
+ * This is the main routine of the driver, to handle the device when
+ * it needs some attention.
+ */
+static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned int status, mask, timeout;
+	unsigned int rx_overrun=0, cr, pkts;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	spin_lock_irqsave(&lp->lock, flags);
+
+	/* Spurious interrupt check */
+	if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) !=
+		(INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) {
+		return IRQ_NONE;
+	}
+
+	mask = SMC_GET_INT_EN();
+	SMC_SET_INT_EN(0);
+
+	/* set a timeout value, so I don't stay here forever */
+	timeout = 8;
+
+
+	do {
+		status = SMC_GET_INT();
+
+		DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n",
+			dev->name, status, mask, status & ~mask);
+
+		status &= mask;
+		if (!status)
+			break;
+
+		/* Handle SW interrupt condition */
+		if (status & INT_STS_SW_INT_) {
+			SMC_ACK_INT(INT_STS_SW_INT_);
+			mask &= ~INT_EN_SW_INT_EN_;
+		}
+		/* Handle various error conditions */
+		if (status & INT_STS_RXE_) {
+			SMC_ACK_INT(INT_STS_RXE_);
+			lp->stats.rx_errors++;
+		}
+		if (status & INT_STS_RXDFH_INT_) {
+			SMC_ACK_INT(INT_STS_RXDFH_INT_);
+			lp->stats.rx_dropped+=SMC_GET_RX_DROP();
+		 }
+		/* Undocumented interrupt-what is the right thing to do here? */
+		if (status & INT_STS_RXDF_INT_) {
+			SMC_ACK_INT(INT_STS_RXDF_INT_);
+		}
+
+		/* Rx Data FIFO exceeds set level */
+		if (status & INT_STS_RDFL_) {
+			if (IS_REV_A(lp->revision)) {
+				rx_overrun=1;
+				SMC_GET_MAC_CR(cr);
+				cr &= ~MAC_CR_RXEN_;
+				SMC_SET_MAC_CR(cr);
+				DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
+				lp->stats.rx_errors++;
+				lp->stats.rx_fifo_errors++;
+			}
+			SMC_ACK_INT(INT_STS_RDFL_);
+		}
+		if (status & INT_STS_RDFO_) {
+			if (!IS_REV_A(lp->revision)) {
+				SMC_GET_MAC_CR(cr);
+				cr &= ~MAC_CR_RXEN_;
+				SMC_SET_MAC_CR(cr);
+				rx_overrun=1;
+				DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name);
+				lp->stats.rx_errors++;
+				lp->stats.rx_fifo_errors++;
+			}
+			SMC_ACK_INT(INT_STS_RDFO_);
+		}
+		/* Handle receive condition */
+		if ((status & INT_STS_RSFL_) || rx_overrun) {
+			unsigned int fifo;
+			DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name);
+			fifo = SMC_GET_RX_FIFO_INF();
+			pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16;
+			DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n",
+				dev->name, pkts, fifo & 0xFFFF );
+			if (pkts != 0) {
+#ifdef SMC_USE_DMA
+				unsigned int fifo;
+				if (lp->rxdma_active){
+					DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA,
+						"%s: RX DMA active\n", dev->name);
+					/* The DMA is already running so up the IRQ threshold */
+					fifo = SMC_GET_FIFO_INT() & ~0xFF;
+					fifo |= pkts & 0xFF;
+					DBG(SMC_DEBUG_RX,
+						"%s: Setting RX stat FIFO threshold to %d\n",
+						dev->name, fifo & 0xff);
+					SMC_SET_FIFO_INT(fifo);
+				} else
+#endif
+				smc911x_rcv(dev);
+			}
+			SMC_ACK_INT(INT_STS_RSFL_);
+		}
+		/* Handle transmit FIFO available */
+		if (status & INT_STS_TDFA_) {
+			DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name);
+			SMC_SET_FIFO_TDA(0xFF);
+			lp->tx_throttle = 0;
+#ifdef SMC_USE_DMA
+			if (!lp->txdma_active)
+#endif
+				netif_wake_queue(dev);
+			SMC_ACK_INT(INT_STS_TDFA_);
+		}
+		/* Handle transmit done condition */
+#if 1
+		if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) {
+			DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC,
+				"%s: Tx stat FIFO limit (%d) /GPT irq\n",
+				dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16);
+			smc911x_tx(dev);
+			SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+			SMC_ACK_INT(INT_STS_TSFL_);
+			SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_);
+		}
+#else
+		if (status & INT_STS_TSFL_) {
+			DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, );
+			smc911x_tx(dev);
+			SMC_ACK_INT(INT_STS_TSFL_);
+		}
+
+		if (status & INT_STS_GPT_INT_) {
+			DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n",
+				dev->name,
+				SMC_GET_IRQ_CFG(),
+				SMC_GET_FIFO_INT(),
+				SMC_GET_RX_CFG());
+			DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x "
+				"Data FIFO Used 0x%04x Stat FIFO 0x%08x\n",
+				dev->name,
+				(SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16,
+				SMC_GET_RX_FIFO_INF() & 0xffff,
+				SMC_GET_RX_STS_FIFO_PEEK());
+			SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000);
+			SMC_ACK_INT(INT_STS_GPT_INT_);
+		}
+#endif
+
+		/* Handle PHY interupt condition */
+		if (status & INT_STS_PHY_INT_) {
+			DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name);
+			smc911x_phy_interrupt(dev);
+			SMC_ACK_INT(INT_STS_PHY_INT_);
+		}
+	} while (--timeout);
+
+	/* restore mask state */
+	SMC_SET_INT_EN(mask);
+
+	DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n",
+		dev->name, 8-timeout);
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef SMC_USE_DMA
+static void
+smc911x_tx_dma_irq(int dma, void *data, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct smc911x_local *lp = netdev_priv(dev);
+	struct sk_buff *skb = lp->current_tx_skb;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name);
+	/* Clear the DMA interrupt sources */
+	SMC_DMA_ACK_IRQ(dev, dma);
+	BUG_ON(skb == NULL);
+	dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE);
+	dev->trans_start = jiffies;
+	dev_kfree_skb_irq(skb);
+	lp->current_tx_skb = NULL;
+	if (lp->pending_tx_skb != NULL)
+		smc911x_hardware_send_pkt(dev);
+	else {
+		DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA,
+			"%s: No pending Tx packets. DMA disabled\n", dev->name);
+		spin_lock_irqsave(&lp->lock, flags);
+		lp->txdma_active = 0;
+		if (!lp->tx_throttle) {
+			netif_wake_queue(dev);
+		}
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+
+	DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA,
+		"%s: TX DMA irq completed\n", dev->name);
+}
+static void
+smc911x_rx_dma_irq(int dma, void *data, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)data;
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	struct sk_buff *skb = lp->current_rx_skb;
+	unsigned long flags;
+	unsigned int pkts;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+	DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name);
+	/* Clear the DMA interrupt sources */
+	SMC_DMA_ACK_IRQ(dev, dma);
+	dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE);
+	BUG_ON(skb == NULL);
+	lp->current_rx_skb = NULL;
+	PRINT_PKT(skb->data, skb->len);
+	dev->last_rx = jiffies;
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	netif_rx(skb);
+	lp->stats.rx_packets++;
+	lp->stats.rx_bytes += skb->len;
+
+	spin_lock_irqsave(&lp->lock, flags);
+	pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16;
+	if (pkts != 0) {
+		smc911x_rcv(dev);
+	}else {
+		lp->rxdma_active = 0;
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+	DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA,
+		"%s: RX DMA irq completed. DMA RX FIFO PKTS %d\n",
+		dev->name, pkts);
+}
+#endif	 /* SMC_USE_DMA */
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void smc911x_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	smc911x_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
+/* Our watchdog timed out. Called by the networking layer */
+static void smc911x_timeout(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int status, mask;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	status = SMC_GET_INT();
+	mask = SMC_GET_INT_EN();
+	spin_unlock_irqrestore(&lp->lock, flags);
+	DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n",
+		dev->name, status, mask);
+
+	/* Dump the current TX FIFO contents and restart */
+	mask = SMC_GET_TX_CFG();
+	SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_);
+	/*
+	 * Reconfiguring the PHY doesn't seem like a bad idea here, but
+	 * smc911x_phy_configure() calls msleep() which calls schedule_timeout()
+	 * which calls schedule().	 Hence we use a work queue.
+	 */
+	if (lp->phy_type != 0) {
+		if (schedule_work(&lp->phy_configure)) {
+			lp->work_pending = 1;
+		}
+	}
+
+	/* We can accept TX packets again */
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+}
+
+/*
+ * This routine will, depending on the values passed to it,
+ * either make it accept multicast packets, go into
+ * promiscuous mode (for TCPDUMP and cousins) or accept
+ * a select set of multicast packets
+ */
+static void smc911x_set_multicast_list(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int multicast_table[2];
+	unsigned int mcr, update_multicast = 0;
+	unsigned long flags;
+	/* table for flipping the order of 5 bits */
+	static const unsigned char invert5[] =
+		{0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C,
+		 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E,
+		 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D,
+		 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F};
+
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	spin_lock_irqsave(&lp->lock, flags);
+	SMC_GET_MAC_CR(mcr);
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	if (dev->flags & IFF_PROMISC) {
+
+		DBG(SMC_DEBUG_MISC, "%s: RCR_PRMS\n", dev->name);
+		mcr |= MAC_CR_PRMS_;
+	}
+	/*
+	 * Here, I am setting this to accept all multicast packets.
+	 * I don't need to zero the multicast table, because the flag is
+	 * checked before the table is
+	 */
+	else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) {
+		DBG(SMC_DEBUG_MISC, "%s: RCR_ALMUL\n", dev->name);
+		mcr |= MAC_CR_MCPAS_;
+	}
+
+	/*
+	 * This sets the internal hardware table to filter out unwanted
+	 * multicast packets before they take up memory.
+	 *
+	 * The SMC chip uses a hash table where the high 6 bits of the CRC of
+	 * address are the offset into the table.	If that bit is 1, then the
+	 * multicast packet is accepted.  Otherwise, it's dropped silently.
+	 *
+	 * To use the 6 bits as an offset into the table, the high 1 bit is
+	 * the number of the 32 bit register, while the low 5 bits are the bit
+	 * within that register.
+	 */
+	else if (dev->mc_count)  {
+		int i;
+		struct dev_mc_list *cur_addr;
+
+		/* Set the Hash perfec mode */
+		mcr |= MAC_CR_HPFILT_;
+
+		/* start with a table of all zeros: reject all */
+		memset(multicast_table, 0, sizeof(multicast_table));
+
+		cur_addr = dev->mc_list;
+		for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
+			int position;
+
+			/* do we have a pointer here? */
+			if (!cur_addr)
+				break;
+			/* make sure this is a multicast address -
+				shouldn't this be a given if we have it here ? */
+			if (!(*cur_addr->dmi_addr & 1))
+				 continue;
+
+			/* only use the low order bits */
+			position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f;
+
+			/* do some messy swapping to put the bit in the right spot */
+			multicast_table[invert5[position&0x1F]&0x1] |=
+				(1<<invert5[(position>>1)&0x1F]);
+		}
+
+		/* be sure I get rid of flags I might have set */
+		mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+		/* now, the table can be loaded into the chipset */
+		update_multicast = 1;
+	} else	 {
+		DBG(SMC_DEBUG_MISC, "%s: ~(MAC_CR_PRMS_|MAC_CR_MCPAS_)\n",
+			dev->name);
+		mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+		/*
+		 * since I'm disabling all multicast entirely, I need to
+		 * clear the multicast list
+		 */
+		memset(multicast_table, 0, sizeof(multicast_table));
+		update_multicast = 1;
+	}
+
+	spin_lock_irqsave(&lp->lock, flags);
+	SMC_SET_MAC_CR(mcr);
+	if (update_multicast) {
+		DBG(SMC_DEBUG_MISC,
+			"%s: update mcast hash table 0x%08x 0x%08x\n",
+			dev->name, multicast_table[0], multicast_table[1]);
+		SMC_SET_HASHL(multicast_table[0]);
+		SMC_SET_HASHH(multicast_table[1]);
+	}
+	spin_unlock_irqrestore(&lp->lock, flags);
+}
+
+
+/*
+ * Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc..
+ */
+static int
+smc911x_open(struct net_device *dev)
+{
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	/*
+	 * Check that the address is valid.  If its not, refuse
+	 * to bring the device up.	 The user must specify an
+	 * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
+	 */
+	if (!is_valid_ether_addr(dev->dev_addr)) {
+		PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	/* reset the hardware */
+	smc911x_reset(dev);
+
+	/* Configure the PHY, initialize the link state */
+	smc911x_phy_configure(dev);
+
+	/* Turn on Tx + Rx */
+	smc911x_enable(dev);
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+/*
+ * smc911x_close
+ *
+ * this makes the board clean up everything that it can
+ * and not talk to the outside world.	 Caused by
+ * an 'ifconfig ethX down'
+ */
+static int smc911x_close(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	/* clear everything */
+	smc911x_shutdown(dev);
+
+	if (lp->phy_type != 0) {
+		/* We need to ensure that no calls to
+		 * smc911x_phy_configure are pending.
+
+		 * flush_scheduled_work() cannot be called because we
+		 * are running with the netlink semaphore held (from
+		 * devinet_ioctl()) and the pending work queue
+		 * contains linkwatch_event() (scheduled by
+		 * netif_carrier_off() above). linkwatch_event() also
+		 * wants the netlink semaphore.
+		 */
+		while (lp->work_pending)
+			schedule();
+		smc911x_phy_powerdown(dev, lp->mii.phy_id);
+	}
+
+	if (lp->pending_tx_skb) {
+		dev_kfree_skb(lp->pending_tx_skb);
+		lp->pending_tx_skb = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *smc911x_query_statistics(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+
+	return &lp->stats;
+}
+
+/*
+ * Ethtool support
+ */
+static int
+smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long ioaddr = dev->base_addr;
+	int ret, status;
+	unsigned long flags;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+	cmd->maxtxpkt = 1;
+	cmd->maxrxpkt = 1;
+
+	if (lp->phy_type != 0) {
+		spin_lock_irqsave(&lp->lock, flags);
+		ret = mii_ethtool_gset(&lp->mii, cmd);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	} else {
+		cmd->supported = SUPPORTED_10baseT_Half |
+				SUPPORTED_10baseT_Full |
+				SUPPORTED_TP | SUPPORTED_AUI;
+
+		if (lp->ctl_rspeed == 10)
+			cmd->speed = SPEED_10;
+		else if (lp->ctl_rspeed == 100)
+			cmd->speed = SPEED_100;
+
+		cmd->autoneg = AUTONEG_DISABLE;
+		if (lp->mii.phy_id==1)
+			cmd->transceiver = XCVR_INTERNAL;
+		else
+			cmd->transceiver = XCVR_EXTERNAL;
+		cmd->port = 0;
+		SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status);
+		cmd->duplex =
+			(status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ?
+				DUPLEX_FULL : DUPLEX_HALF;
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int
+smc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	int ret;
+	unsigned long flags;
+
+	if (lp->phy_type != 0) {
+		spin_lock_irqsave(&lp->lock, flags);
+		ret = mii_ethtool_sset(&lp->mii, cmd);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	} else {
+		if (cmd->autoneg != AUTONEG_DISABLE ||
+			cmd->speed != SPEED_10 ||
+			(cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) ||
+			(cmd->port != PORT_TP && cmd->port != PORT_AUI))
+			return -EINVAL;
+
+		lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL;
+
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static void
+smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strncpy(info->driver, CARDNAME, sizeof(info->driver));
+	strncpy(info->version, version, sizeof(info->version));
+	strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info));
+}
+
+static int smc911x_ethtool_nwayreset(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	int ret = -EINVAL;
+	unsigned long flags;
+
+	if (lp->phy_type != 0) {
+		spin_lock_irqsave(&lp->lock, flags);
+		ret = mii_nway_restart(&lp->mii);
+		spin_unlock_irqrestore(&lp->lock, flags);
+	}
+
+	return ret;
+}
+
+static u32 smc911x_ethtool_getmsglevel(struct net_device *dev)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	return lp->msg_enable;
+}
+
+static void smc911x_ethtool_setmsglevel(struct net_device *dev, u32 level)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	lp->msg_enable = level;
+}
+
+static int smc911x_ethtool_getregslen(struct net_device *dev)
+{
+	/* System regs + MAC regs + PHY regs */
+	return (((E2P_CMD - ID_REV)/4 + 1) +
+			(WUCSR - MAC_CR)+1 + 32) * sizeof(u32);
+}
+
+static void smc911x_ethtool_getregs(struct net_device *dev,
+										 struct ethtool_regs* regs, void *buf)
+{
+	unsigned long ioaddr = dev->base_addr;
+	struct smc911x_local *lp = netdev_priv(dev);
+	unsigned long flags;
+	u32 reg,i,j=0;
+	u32 *data = (u32*)buf;
+
+	regs->version = lp->version;
+	for(i=ID_REV;i<=E2P_CMD;i+=4) {
+		data[j++] = SMC_inl(ioaddr,i);
+	}
+	for(i=MAC_CR;i<=WUCSR;i++) {
+		spin_lock_irqsave(&lp->lock, flags);
+		SMC_GET_MAC_CSR(i, reg);
+		spin_unlock_irqrestore(&lp->lock, flags);
+		data[j++] = reg;
+	}
+	for(i=0;i<=31;i++) {
+		spin_lock_irqsave(&lp->lock, flags);
+		SMC_GET_MII(i, lp->mii.phy_id, reg);
+		spin_unlock_irqrestore(&lp->lock, flags);
+		data[j++] = reg & 0xFFFF;
+	}
+}
+
+static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev)
+{
+	unsigned long ioaddr = dev->base_addr;
+	unsigned int timeout;
+	int e2p_cmd;
+
+	e2p_cmd = SMC_GET_E2P_CMD();
+	for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) {
+		if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) {
+			PRINTK("%s: %s timeout waiting for EEPROM to respond\n",
+				dev->name, __FUNCTION__);
+			return -EFAULT;
+		}
+		mdelay(1);
+		e2p_cmd = SMC_GET_E2P_CMD();
+	}
+	if (timeout == 0) {
+		PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n",
+			dev->name, __FUNCTION__);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev,
+													int cmd, int addr)
+{
+	unsigned long ioaddr = dev->base_addr;
+	int ret;
+
+	if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+		return ret;
+	SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ |
+		((cmd) & (0x7<<28)) |
+		((addr) & 0xFF));
+	return 0;
+}
+
+static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev,
+													u8 *data)
+{
+	unsigned long ioaddr = dev->base_addr;
+	int ret;
+
+	if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+		return ret;
+	*data = SMC_GET_E2P_DATA();
+	return 0;
+}
+
+static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev,
+													 u8 data)
+{
+	unsigned long ioaddr = dev->base_addr;
+	int ret;
+
+	if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0)
+		return ret;
+	SMC_SET_E2P_DATA(data);
+	return 0;
+}
+
+static int smc911x_ethtool_geteeprom(struct net_device *dev,
+									  struct ethtool_eeprom *eeprom, u8 *data)
+{
+	u8 eebuf[SMC911X_EEPROM_LEN];
+	int i, ret;
+
+	for(i=0;i<SMC911X_EEPROM_LEN;i++) {
+		if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ_, i ))!=0)
+			return ret;
+		if ((ret=smc911x_ethtool_read_eeprom_byte(dev, &eebuf[i]))!=0)
+			return ret;
+		}
+	memcpy(data, eebuf+eeprom->offset, eeprom->len);
+	return 0;
+}
+
+static int smc911x_ethtool_seteeprom(struct net_device *dev,
+									   struct ethtool_eeprom *eeprom, u8 *data)
+{
+	int i, ret;
+
+	/* Enable erase */
+	if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN_, 0 ))!=0)
+		return ret;
+	for(i=eeprom->offset;i<(eeprom->offset+eeprom->len);i++) {
+		/* erase byte */
+		if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE_, i ))!=0)
+			return ret;
+		/* write byte */
+		if ((ret=smc911x_ethtool_write_eeprom_byte(dev, *data))!=0)
+			 return ret;
+		if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE_, i ))!=0)
+			return ret;
+		}
+	 return 0;
+}
+
+static int smc911x_ethtool_geteeprom_len(struct net_device *dev)
+{
+	 return SMC911X_EEPROM_LEN;
+}
+
+static struct ethtool_ops smc911x_ethtool_ops = {
+	.get_settings	 = smc911x_ethtool_getsettings,
+	.set_settings	 = smc911x_ethtool_setsettings,
+	.get_drvinfo	 = smc911x_ethtool_getdrvinfo,
+	.get_msglevel	 = smc911x_ethtool_getmsglevel,
+	.set_msglevel	 = smc911x_ethtool_setmsglevel,
+	.nway_reset = smc911x_ethtool_nwayreset,
+	.get_link	 = ethtool_op_get_link,
+	.get_regs_len	 = smc911x_ethtool_getregslen,
+	.get_regs	 = smc911x_ethtool_getregs,
+	.get_eeprom_len = smc911x_ethtool_geteeprom_len,
+	.get_eeprom = smc911x_ethtool_geteeprom,
+	.set_eeprom = smc911x_ethtool_seteeprom,
+};
+
+/*
+ * smc911x_findirq
+ *
+ * This routine has a simple purpose -- make the SMC chip generate an
+ * interrupt, so an auto-detect routine can detect it, and find the IRQ,
+ */
+static int __init smc911x_findirq(unsigned long ioaddr)
+{
+	int timeout = 20;
+	unsigned long cookie;
+
+	DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+
+	cookie = probe_irq_on();
+
+	/*
+	 * Force a SW interrupt
+	 */
+
+	SMC_SET_INT_EN(INT_EN_SW_INT_EN_);
+
+	/*
+	 * Wait until positive that the interrupt has been generated
+	 */
+	do {
+		int int_status;
+		udelay(10);
+		int_status = SMC_GET_INT_EN();
+		if (int_status & INT_EN_SW_INT_EN_)
+			 break;		/* got the interrupt */
+	} while (--timeout);
+
+	/*
+	 * there is really nothing that I can do here if timeout fails,
+	 * as autoirq_report will return a 0 anyway, which is what I
+	 * want in this case.	 Plus, the clean up is needed in both
+	 * cases.
+	 */
+
+	/* and disable all interrupts again */
+	SMC_SET_INT_EN(0);
+
+	/* and return what I found */
+	return probe_irq_off(cookie);
+}
+
+/*
+ * Function: smc911x_probe(unsigned long ioaddr)
+ *
+ * Purpose:
+ *	 Tests to see if a given ioaddr points to an SMC911x chip.
+ *	 Returns a 0 on success
+ *
+ * Algorithm:
+ *	 (1) see if the endian word is OK
+ *	 (1) see if I recognize the chip ID in the appropriate register
+ *
+ * Here I do typical initialization tasks.
+ *
+ * o  Initialize the structure if needed
+ * o  print out my vanity message if not done so already
+ * o  print out what type of hardware is detected
+ * o  print out the ethernet address
+ * o  find the IRQ
+ * o  set up my private data
+ * o  configure the dev structure with my subroutines
+ * o  actually GRAB the irq.
+ * o  GRAB the region
+ */
+static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr)
+{
+	struct smc911x_local *lp = netdev_priv(dev);
+	int i, retval;
+	unsigned int val, chip_id, revision;
+	const char *version_string;
+
+	DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__);
+
+	/* First, see if the endian word is recognized */
+	val = SMC_GET_BYTE_TEST();
+	DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val);
+	if (val != 0x87654321) {
+		printk(KERN_ERR "Invalid chip endian 0x08%x\n",val);
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	/*
+	 * check if the revision register is something that I
+	 * recognize.	These might need to be added to later,
+	 * as future revisions could be added.
+	 */
+	chip_id = SMC_GET_PN();
+	DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id);
+	for(i=0;chip_ids[i].id != 0; i++) {
+		if (chip_ids[i].id == chip_id) break;
+	}
+	if (!chip_ids[i].id) {
+		printk(KERN_ERR "Unknown chip ID %04x\n", chip_id);
+		retval = -ENODEV;
+		goto err_out;
+	}
+	version_string = chip_ids[i].name;
+
+	revision = SMC_GET_REV();
+	DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision);
+
+	/* At this point I'll assume that the chip is an SMC911x. */
+	DBG(SMC_DEBUG_MISC, "%s: Found a %s\n", CARDNAME, chip_ids[i].name);
+
+	/* Validate the TX FIFO size requested */
+	if ((tx_fifo_kb < 2) || (tx_fifo_kb > 14)) {
+		printk(KERN_ERR "Invalid TX FIFO size requested %d\n", tx_fifo_kb);
+		retval = -EINVAL;
+		goto err_out;
+	}
+
+	/* fill in some of the fields */
+	dev->base_addr = ioaddr;
+	lp->version = chip_ids[i].id;
+	lp->revision = revision;
+	lp->tx_fifo_kb = tx_fifo_kb;
+	/* Reverse calculate the RX FIFO size from the TX */
+	lp->tx_fifo_size=(lp->tx_fifo_kb<<10) - 512;
+	lp->rx_fifo_size= ((0x4000 - 512 - lp->tx_fifo_size) / 16) * 15;
+
+	/* Set the automatic flow control values */
+	switch(lp->tx_fifo_kb) {
+		/*
+		 *	 AFC_HI is about ((Rx Data Fifo Size)*2/3)/64
+		 *	 AFC_LO is AFC_HI/2
+		 *	 BACK_DUR is about 5uS*(AFC_LO) rounded down
+		 */
+		case 2:/* 13440 Rx Data Fifo Size */
+			lp->afc_cfg=0x008C46AF;break;
+		case 3:/* 12480 Rx Data Fifo Size */
+			lp->afc_cfg=0x0082419F;break;
+		case 4:/* 11520 Rx Data Fifo Size */
+			lp->afc_cfg=0x00783C9F;break;
+		case 5:/* 10560 Rx Data Fifo Size */
+			lp->afc_cfg=0x006E374F;break;
+		case 6:/* 9600 Rx Data Fifo Size */
+			lp->afc_cfg=0x0064328F;break;
+		case 7:/* 8640 Rx Data Fifo Size */
+			lp->afc_cfg=0x005A2D7F;break;
+		case 8:/* 7680 Rx Data Fifo Size */
+			lp->afc_cfg=0x0050287F;break;
+		case 9:/* 6720 Rx Data Fifo Size */
+			lp->afc_cfg=0x0046236F;break;
+		case 10:/* 5760 Rx Data Fifo Size */
+			lp->afc_cfg=0x003C1E6F;break;
+		case 11:/* 4800 Rx Data Fifo Size */
+			lp->afc_cfg=0x0032195F;break;
+		/*
+		 *	 AFC_HI is ~1520 bytes less than RX Data Fifo Size
+		 *	 AFC_LO is AFC_HI/2
+		 *	 BACK_DUR is about 5uS*(AFC_LO) rounded down
+		 */
+		case 12:/* 3840 Rx Data Fifo Size */
+			lp->afc_cfg=0x0024124F;break;
+		case 13:/* 2880 Rx Data Fifo Size */
+			lp->afc_cfg=0x0015073F;break;
+		case 14:/* 1920 Rx Data Fifo Size */
+			lp->afc_cfg=0x0006032F;break;
+		 default:
+			 PRINTK("%s: ERROR -- no AFC_CFG setting found",
+				dev->name);
+			 break;
+	}
+
+	DBG(SMC_DEBUG_MISC | SMC_DEBUG_TX | SMC_DEBUG_RX,
+		"%s: tx_fifo %d rx_fifo %d afc_cfg 0x%08x\n", CARDNAME,
+		lp->tx_fifo_size, lp->rx_fifo_size, lp->afc_cfg);
+
+	spin_lock_init(&lp->lock);
+
+	/* Get the MAC address */
+	SMC_GET_MAC_ADDR(dev->dev_addr);
+
+	/* now, reset the chip, and put it into a known state */
+	smc911x_reset(dev);
+
+	/*
+	 * If dev->irq is 0, then the device has to be banged on to see
+	 * what the IRQ is.
+	 *
+	 * Specifying an IRQ is done with the assumption that the user knows
+	 * what (s)he is doing.  No checking is done!!!!
+	 */
+	if (dev->irq < 1) {
+		int trials;
+
+		trials = 3;
+		while (trials--) {
+			dev->irq = smc911x_findirq(ioaddr);
+			if (dev->irq)
+				break;
+			/* kick the card and try again */
+			smc911x_reset(dev);
+		}
+	}
+	if (dev->irq == 0) {
+		printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n",
+			dev->name);
+		retval = -ENODEV;
+		goto err_out;
+	}
+	dev->irq = irq_canonicalize(dev->irq);
+
+	/* Fill in the fields of the device structure with ethernet values. */
+	ether_setup(dev);
+
+	dev->open = smc911x_open;
+	dev->stop = smc911x_close;
+	dev->hard_start_xmit = smc911x_hard_start_xmit;
+	dev->tx_timeout = smc911x_timeout;
+	dev->watchdog_timeo = msecs_to_jiffies(watchdog);
+	dev->get_stats = smc911x_query_statistics;
+	dev->set_multicast_list = smc911x_set_multicast_list;
+	dev->ethtool_ops = &smc911x_ethtool_ops;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = smc911x_poll_controller;
+#endif
+
+	INIT_WORK(&lp->phy_configure, smc911x_phy_configure, dev);
+	lp->mii.phy_id_mask = 0x1f;
+	lp->mii.reg_num_mask = 0x1f;
+	lp->mii.force_media = 0;
+	lp->mii.full_duplex = 0;
+	lp->mii.dev = dev;
+	lp->mii.mdio_read = smc911x_phy_read;
+	lp->mii.mdio_write = smc911x_phy_write;
+
+	/*
+	 * Locate the phy, if any.
+	 */
+	smc911x_phy_detect(dev);
+
+	/* Set default parameters */
+	lp->msg_enable = NETIF_MSG_LINK;
+	lp->ctl_rfduplx = 1;
+	lp->ctl_rspeed = 100;
+
+	/* Grab the IRQ */
+	retval = request_irq(dev->irq, &smc911x_interrupt, SA_SHIRQ, dev->name, dev);
+	if (retval)
+		goto err_out;
+
+	set_irq_type(dev->irq, IRQT_FALLING);
+
+#ifdef SMC_USE_DMA
+	lp->rxdma = SMC_DMA_REQUEST(dev, smc911x_rx_dma_irq);
+	lp->txdma = SMC_DMA_REQUEST(dev, smc911x_tx_dma_irq);
+	lp->rxdma_active = 0;
+	lp->txdma_active = 0;
+	dev->dma = lp->rxdma;
+#endif
+
+	retval = register_netdev(dev);
+	if (retval == 0) {
+		/* now, print out the card info, in a short format.. */
+		printk("%s: %s (rev %d) at %#lx IRQ %d",
+			dev->name, version_string, lp->revision,
+			dev->base_addr, dev->irq);
+
+#ifdef SMC_USE_DMA
+		if (lp->rxdma != -1)
+			printk(" RXDMA %d ", lp->rxdma);
+
+		if (lp->txdma != -1)
+			printk("TXDMA %d", lp->txdma);
+#endif
+		printk("\n");
+		if (!is_valid_ether_addr(dev->dev_addr)) {
+			printk("%s: Invalid ethernet MAC address. Please "
+					"set using ifconfig\n", dev->name);
+		} else {
+			/* Print the Ethernet address */
+			printk("%s: Ethernet addr: ", dev->name);
+			for (i = 0; i < 5; i++)
+				printk("%2.2x:", dev->dev_addr[i]);
+			printk("%2.2x\n", dev->dev_addr[5]);
+		}
+
+		if (lp->phy_type == 0) {
+			PRINTK("%s: No PHY found\n", dev->name);
+		} else if ((lp->phy_type & ~0xff) == LAN911X_INTERNAL_PHY_ID) {
+			PRINTK("%s: LAN911x Internal PHY\n", dev->name);
+		} else {
+			PRINTK("%s: External PHY 0x%08x\n", dev->name, lp->phy_type);
+		}
+	}
+
+err_out:
+#ifdef SMC_USE_DMA
+	if (retval) {
+		if (lp->rxdma != -1) {
+			SMC_DMA_FREE(dev, lp->rxdma);
+		}
+		if (lp->txdma != -1) {
+			SMC_DMA_FREE(dev, lp->txdma);
+		}
+	}
+#endif
+	return retval;
+}
+
+/*
+ * smc911x_init(void)
+ *
+ *	  Output:
+ *	 0 --> there is a device
+ *	 anything else, error
+ */
+static int smc911x_drv_probe(struct platform_device *pdev)
+{
+	struct net_device *ndev;
+	struct resource *res;
+	unsigned int *addr;
+	int ret;
+
+	DBG(SMC_DEBUG_FUNC, "--> %s\n",  __FUNCTION__);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/*
+	 * Request the regions.
+	 */
+	if (!request_mem_region(res->start, SMC911X_IO_EXTENT, CARDNAME)) {
+		 ret = -EBUSY;
+		 goto out;
+	}
+
+	ndev = alloc_etherdev(sizeof(struct smc911x_local));
+	if (!ndev) {
+		printk("%s: could not allocate device.\n", CARDNAME);
+		ret = -ENOMEM;
+		goto release_1;
+	}
+	SET_MODULE_OWNER(ndev);
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	ndev->dma = (unsigned char)-1;
+	ndev->irq = platform_get_irq(pdev, 0);
+
+	addr = ioremap(res->start, SMC911X_IO_EXTENT);
+	if (!addr) {
+		ret = -ENOMEM;
+		goto release_both;
+	}
+
+	platform_set_drvdata(pdev, ndev);
+	ret = smc911x_probe(ndev, (unsigned long)addr);
+	if (ret != 0) {
+		platform_set_drvdata(pdev, NULL);
+		iounmap(addr);
+release_both:
+		free_netdev(ndev);
+release_1:
+		release_mem_region(res->start, SMC911X_IO_EXTENT);
+out:
+		printk("%s: not found (%d).\n", CARDNAME, ret);
+	}
+#ifdef SMC_USE_DMA
+	else {
+		struct smc911x_local *lp = netdev_priv(ndev);
+		lp->physaddr = res->start;
+		lp->dev = &pdev->dev;
+	}
+#endif
+
+	return ret;
+}
+
+static int smc911x_drv_remove(struct platform_device *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+	platform_set_drvdata(pdev, NULL);
+
+	unregister_netdev(ndev);
+
+	free_irq(ndev->irq, ndev);
+
+#ifdef SMC_USE_DMA
+	{
+		struct smc911x_local *lp = netdev_priv(ndev);
+		if (lp->rxdma != -1) {
+			SMC_DMA_FREE(dev, lp->rxdma);
+		}
+		if (lp->txdma != -1) {
+			SMC_DMA_FREE(dev, lp->txdma);
+		}
+	}
+#endif
+	iounmap((void *)ndev->base_addr);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, SMC911X_IO_EXTENT);
+
+	free_netdev(ndev);
+	return 0;
+}
+
+static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct net_device *ndev = platform_get_drvdata(dev);
+	unsigned long ioaddr = ndev->base_addr;
+
+	DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+	if (ndev) {
+		if (netif_running(ndev)) {
+			netif_device_detach(ndev);
+			smc911x_shutdown(ndev);
+#if POWER_DOWN
+			/* Set D2 - Energy detect only setting */
+			SMC_SET_PMT_CTRL(2<<12);
+#endif
+		}
+	}
+	return 0;
+}
+
+static int smc911x_drv_resume(struct platform_device *dev)
+{
+	struct net_device *ndev = platform_get_drvdata(dev);
+
+	DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__);
+	if (ndev) {
+		struct smc911x_local *lp = netdev_priv(ndev);
+
+		if (netif_running(ndev)) {
+			smc911x_reset(ndev);
+			smc911x_enable(ndev);
+			if (lp->phy_type != 0)
+				smc911x_phy_configure(ndev);
+			netif_device_attach(ndev);
+		}
+	}
+	return 0;
+}
+
+static struct platform_driver smc911x_driver = {
+	.probe		 = smc911x_drv_probe,
+	.remove	 = smc911x_drv_remove,
+	.suspend	 = smc911x_drv_suspend,
+	.resume	 = smc911x_drv_resume,
+	.driver	 = {
+		.name	 = CARDNAME,
+	},
+};
+
+static int __init smc911x_init(void)
+{
+	return platform_driver_register(&smc911x_driver);
+}
+
+static void __exit smc911x_cleanup(void)
+{
+	platform_driver_unregister(&smc911x_driver);
+}
+
+module_init(smc911x_init);
+module_exit(smc911x_cleanup);
diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h
new file mode 100644
index 0000000..962a710
--- /dev/null
+++ b/drivers/net/smc911x.h
@@ -0,0 +1,835 @@
+/*------------------------------------------------------------------------
+ . smc911x.h - macros for SMSC's LAN911{5,6,7,8} single-chip Ethernet device.
+ .
+ . Copyright (C) 2005 Sensoria Corp.
+ . Derived from the unified SMC91x driver by Nicolas Pitre
+ .
+ . This program is free software; you can redistribute it and/or modify
+ . it under the terms of the GNU General Public License as published by
+ . the Free Software Foundation; either version 2 of the License, or
+ . (at your option) any later version.
+ .
+ . This program is distributed in the hope that it will be useful,
+ . but WITHOUT ANY WARRANTY; without even the implied warranty of
+ . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ . GNU General Public License for more details.
+ .
+ . You should have received a copy of the GNU General Public License
+ . along with this program; if not, write to the Free Software
+ . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ .
+ . Information contained in this file was obtained from the LAN9118
+ . manual from SMC.  To get a copy, if you really want one, you can find
+ . information under www.smsc.com.
+ .
+ . Authors
+ .	 Dustin McIntire		 <dustin@sensoria.com>
+ .
+ ---------------------------------------------------------------------------*/
+#ifndef _SMC911X_H_
+#define _SMC911X_H_
+
+/*
+ * Use the DMA feature on PXA chips
+ */
+#ifdef CONFIG_ARCH_PXA
+  #define SMC_USE_PXA_DMA	1
+  #define SMC_USE_16BIT		0
+  #define SMC_USE_32BIT		1
+#endif
+
+
+/*
+ * Define the bus width specific IO macros
+ */
+
+#if	SMC_USE_16BIT
+#define SMC_inb(a, r)			 readb((a) + (r))
+#define SMC_inw(a, r)			 readw((a) + (r))
+#define SMC_inl(a, r)			 ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16))
+#define SMC_outb(v, a, r)		 writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)		 writew(v, (a) + (r))
+#define SMC_outl(v, a, r) 			 \
+	do{					 \
+		 writel(v & 0xFFFF, (a) + (r));	 \
+		 writel(v >> 16, (a) + (r) + 2); \
+	 } while (0)
+#define SMC_insl(a, r, p, l)	 readsw((short*)((a) + (r)), p, l*2)
+#define SMC_outsl(a, r, p, l)	 writesw((short*)((a) + (r)), p, l*2)
+
+#elif	SMC_USE_32BIT
+#define SMC_inb(a, r)		 readb((a) + (r))
+#define SMC_inw(a, r)		 readw((a) + (r))
+#define SMC_inl(a, r)		 readl((a) + (r))
+#define SMC_outb(v, a, r)	 writeb(v, (a) + (r))
+#define SMC_outl(v, a, r)	 writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)	 readsl((int*)((a) + (r)), p, l)
+#define SMC_outsl(a, r, p, l)	 writesl((int*)((a) + (r)), p, l)
+
+#endif /* SMC_USE_16BIT */
+
+
+
+#if	 SMC_USE_PXA_DMA
+#define SMC_USE_DMA
+
+/*
+ * Define the request and free functions
+ * These are unfortunately architecture specific as no generic allocation
+ * mechanism exits
+ */
+#define SMC_DMA_REQUEST(dev, handler) \
+	 pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev)
+
+#define SMC_DMA_FREE(dev, dma) \
+	 pxa_free_dma(dma)
+
+#define SMC_DMA_ACK_IRQ(dev, dma)					\
+{									\
+	if (DCSR(dma) & DCSR_BUSERR) {					\
+		printk("%s: DMA %d bus error!\n", dev->name, dma);	\
+	}								\
+	DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR;		\
+}
+
+/*
+ * Use a DMA for RX and TX packets.
+ */
+#include <linux/dma-mapping.h>
+#include <asm/dma.h>
+#include <asm/arch/pxa-regs.h>
+
+static dma_addr_t rx_dmabuf, tx_dmabuf;
+static int rx_dmalen, tx_dmalen;
+
+#ifdef SMC_insl
+#undef SMC_insl
+#define SMC_insl(a, r, p, l) \
+	smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
+
+static inline void
+smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr,
+		int reg, int dma, u_char *buf, int len)
+{
+	/* 64 bit alignment is required for memory to memory DMA */
+	if ((long)buf & 4) {
+		*((u32 *)buf) = SMC_inl(ioaddr, reg);
+		buf += 4;
+		len--;
+	}
+
+	len *= 4;
+	rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+	rx_dmalen = len;
+	DCSR(dma) = DCSR_NODESC;
+	DTADR(dma) = rx_dmabuf;
+	DSADR(dma) = physaddr + reg;
+	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+		DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_insw
+#undef SMC_insw
+#define SMC_insw(a, r, p, l) \
+	smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l)
+
+static inline void
+smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr,
+		int reg, int dma, u_char *buf, int len)
+{
+	/* 64 bit alignment is required for memory to memory DMA */
+	while ((long)buf & 6) {
+		*((u16 *)buf) = SMC_inw(ioaddr, reg);
+		buf += 2;
+		len--;
+	}
+
+	len *= 2;
+	rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+	rx_dmalen = len;
+	DCSR(dma) = DCSR_NODESC;
+	DTADR(dma) = rx_dmabuf;
+	DSADR(dma) = physaddr + reg;
+	DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 |
+		DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_outsl
+#undef SMC_outsl
+#define SMC_outsl(a, r, p, l) \
+	 smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
+
+static inline void
+smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr,
+		int reg, int dma, u_char *buf, int len)
+{
+	/* 64 bit alignment is required for memory to memory DMA */
+	if ((long)buf & 4) {
+		SMC_outl(*((u32 *)buf), ioaddr, reg);
+		buf += 4;
+		len--;
+	}
+
+	len *= 4;
+	tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
+	tx_dmalen = len;
+	DCSR(dma) = DCSR_NODESC;
+	DSADR(dma) = tx_dmabuf;
+	DTADR(dma) = physaddr + reg;
+	DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
+		DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#ifdef SMC_outsw
+#undef SMC_outsw
+#define SMC_outsw(a, r, p, l) \
+	smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l)
+
+static inline void
+smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr,
+		  int reg, int dma, u_char *buf, int len)
+{
+	/* 64 bit alignment is required for memory to memory DMA */
+	while ((long)buf & 6) {
+		SMC_outw(*((u16 *)buf), ioaddr, reg);
+		buf += 2;
+		len--;
+	}
+
+	len *= 2;
+	tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE);
+	tx_dmalen = len;
+	DCSR(dma) = DCSR_NODESC;
+	DSADR(dma) = tx_dmabuf;
+	DTADR(dma) = physaddr + reg;
+	DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 |
+		DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen));
+	DCSR(dma) = DCSR_NODESC | DCSR_RUN;
+}
+#endif
+
+#endif	 /* SMC_USE_PXA_DMA */
+
+
+/* Chip Parameters and Register Definitions */
+
+#define SMC911X_TX_FIFO_LOW_THRESHOLD	(1536*2)
+
+#define SMC911X_IO_EXTENT	 0x100
+
+#define SMC911X_EEPROM_LEN	 7
+
+/* Below are the register offsets and bit definitions
+ * of the Lan911x memory space
+ */
+#define RX_DATA_FIFO		 (0x00)
+
+#define TX_DATA_FIFO		 (0x20)
+#define	TX_CMD_A_INT_ON_COMP_		(0x80000000)
+#define	TX_CMD_A_INT_BUF_END_ALGN_	(0x03000000)
+#define	TX_CMD_A_INT_4_BYTE_ALGN_	(0x00000000)
+#define	TX_CMD_A_INT_16_BYTE_ALGN_	(0x01000000)
+#define	TX_CMD_A_INT_32_BYTE_ALGN_	(0x02000000)
+#define	TX_CMD_A_INT_DATA_OFFSET_	(0x001F0000)
+#define	TX_CMD_A_INT_FIRST_SEG_		(0x00002000)
+#define	TX_CMD_A_INT_LAST_SEG_		(0x00001000)
+#define	TX_CMD_A_BUF_SIZE_		(0x000007FF)
+#define	TX_CMD_B_PKT_TAG_		(0xFFFF0000)
+#define	TX_CMD_B_ADD_CRC_DISABLE_	(0x00002000)
+#define	TX_CMD_B_DISABLE_PADDING_	(0x00001000)
+#define	TX_CMD_B_PKT_BYTE_LENGTH_	(0x000007FF)
+
+#define RX_STATUS_FIFO		(0x40)
+#define	RX_STS_PKT_LEN_			(0x3FFF0000)
+#define	RX_STS_ES_			(0x00008000)
+#define	RX_STS_BCST_			(0x00002000)
+#define	RX_STS_LEN_ERR_			(0x00001000)
+#define	RX_STS_RUNT_ERR_		(0x00000800)
+#define	RX_STS_MCAST_			(0x00000400)
+#define	RX_STS_TOO_LONG_		(0x00000080)
+#define	RX_STS_COLL_			(0x00000040)
+#define	RX_STS_ETH_TYPE_		(0x00000020)
+#define	RX_STS_WDOG_TMT_		(0x00000010)
+#define	RX_STS_MII_ERR_			(0x00000008)
+#define	RX_STS_DRIBBLING_		(0x00000004)
+#define	RX_STS_CRC_ERR_			(0x00000002)
+#define RX_STATUS_FIFO_PEEK 	(0x44)
+#define TX_STATUS_FIFO		(0x48)
+#define	TX_STS_TAG_			(0xFFFF0000)
+#define	TX_STS_ES_			(0x00008000)
+#define	TX_STS_LOC_			(0x00000800)
+#define	TX_STS_NO_CARR_			(0x00000400)
+#define	TX_STS_LATE_COLL_		(0x00000200)
+#define	TX_STS_MANY_COLL_		(0x00000100)
+#define	TX_STS_COLL_CNT_		(0x00000078)
+#define	TX_STS_MANY_DEFER_		(0x00000004)
+#define	TX_STS_UNDERRUN_		(0x00000002)
+#define	TX_STS_DEFERRED_		(0x00000001)
+#define TX_STATUS_FIFO_PEEK	(0x4C)
+#define ID_REV			(0x50)
+#define	ID_REV_CHIP_ID_			(0xFFFF0000)  /* RO */
+#define	ID_REV_REV_ID_			(0x0000FFFF)  /* RO */
+
+#define INT_CFG			(0x54)
+#define	INT_CFG_INT_DEAS_		(0xFF000000)  /* R/W */
+#define	INT_CFG_INT_DEAS_CLR_		(0x00004000)
+#define	INT_CFG_INT_DEAS_STS_		(0x00002000)
+#define	INT_CFG_IRQ_INT_		(0x00001000)  /* RO */
+#define	INT_CFG_IRQ_EN_			(0x00000100)  /* R/W */
+#define	INT_CFG_IRQ_POL_		(0x00000010)  /* R/W Not Affected by SW Reset */
+#define	INT_CFG_IRQ_TYPE_		(0x00000001)  /* R/W Not Affected by SW Reset */
+
+#define INT_STS			(0x58)
+#define	INT_STS_SW_INT_			(0x80000000)  /* R/WC */
+#define	INT_STS_TXSTOP_INT_		(0x02000000)  /* R/WC */
+#define	INT_STS_RXSTOP_INT_		(0x01000000)  /* R/WC */
+#define	INT_STS_RXDFH_INT_		(0x00800000)  /* R/WC */
+#define	INT_STS_RXDF_INT_		(0x00400000)  /* R/WC */
+#define	INT_STS_TX_IOC_			(0x00200000)  /* R/WC */
+#define	INT_STS_RXD_INT_		(0x00100000)  /* R/WC */
+#define	INT_STS_GPT_INT_		(0x00080000)  /* R/WC */
+#define	INT_STS_PHY_INT_		(0x00040000)  /* RO */
+#define	INT_STS_PME_INT_		(0x00020000)  /* R/WC */
+#define	INT_STS_TXSO_			(0x00010000)  /* R/WC */
+#define	INT_STS_RWT_			(0x00008000)  /* R/WC */
+#define	INT_STS_RXE_			(0x00004000)  /* R/WC */
+#define	INT_STS_TXE_			(0x00002000)  /* R/WC */
+//#define	INT_STS_ERX_		(0x00001000)  /* R/WC */
+#define	INT_STS_TDFU_			(0x00000800)  /* R/WC */
+#define	INT_STS_TDFO_			(0x00000400)  /* R/WC */
+#define	INT_STS_TDFA_			(0x00000200)  /* R/WC */
+#define	INT_STS_TSFF_			(0x00000100)  /* R/WC */
+#define	INT_STS_TSFL_			(0x00000080)  /* R/WC */
+//#define	INT_STS_RXDF_		(0x00000040)  /* R/WC */
+#define	INT_STS_RDFO_			(0x00000040)  /* R/WC */
+#define	INT_STS_RDFL_			(0x00000020)  /* R/WC */
+#define	INT_STS_RSFF_			(0x00000010)  /* R/WC */
+#define	INT_STS_RSFL_			(0x00000008)  /* R/WC */
+#define	INT_STS_GPIO2_INT_		(0x00000004)  /* R/WC */
+#define	INT_STS_GPIO1_INT_		(0x00000002)  /* R/WC */
+#define	INT_STS_GPIO0_INT_		(0x00000001)  /* R/WC */
+
+#define INT_EN			(0x5C)
+#define	INT_EN_SW_INT_EN_		(0x80000000)  /* R/W */
+#define	INT_EN_TXSTOP_INT_EN_		(0x02000000)  /* R/W */
+#define	INT_EN_RXSTOP_INT_EN_		(0x01000000)  /* R/W */
+#define	INT_EN_RXDFH_INT_EN_		(0x00800000)  /* R/W */
+//#define	INT_EN_RXDF_INT_EN_		(0x00400000)  /* R/W */
+#define	INT_EN_TIOC_INT_EN_		(0x00200000)  /* R/W */
+#define	INT_EN_RXD_INT_EN_		(0x00100000)  /* R/W */
+#define	INT_EN_GPT_INT_EN_		(0x00080000)  /* R/W */
+#define	INT_EN_PHY_INT_EN_		(0x00040000)  /* R/W */
+#define	INT_EN_PME_INT_EN_		(0x00020000)  /* R/W */
+#define	INT_EN_TXSO_EN_			(0x00010000)  /* R/W */
+#define	INT_EN_RWT_EN_			(0x00008000)  /* R/W */
+#define	INT_EN_RXE_EN_			(0x00004000)  /* R/W */
+#define	INT_EN_TXE_EN_			(0x00002000)  /* R/W */
+//#define	INT_EN_ERX_EN_			(0x00001000)  /* R/W */
+#define	INT_EN_TDFU_EN_			(0x00000800)  /* R/W */
+#define	INT_EN_TDFO_EN_			(0x00000400)  /* R/W */
+#define	INT_EN_TDFA_EN_			(0x00000200)  /* R/W */
+#define	INT_EN_TSFF_EN_			(0x00000100)  /* R/W */
+#define	INT_EN_TSFL_EN_			(0x00000080)  /* R/W */
+//#define	INT_EN_RXDF_EN_			(0x00000040)  /* R/W */
+#define	INT_EN_RDFO_EN_			(0x00000040)  /* R/W */
+#define	INT_EN_RDFL_EN_			(0x00000020)  /* R/W */
+#define	INT_EN_RSFF_EN_			(0x00000010)  /* R/W */
+#define	INT_EN_RSFL_EN_			(0x00000008)  /* R/W */
+#define	INT_EN_GPIO2_INT_		(0x00000004)  /* R/W */
+#define	INT_EN_GPIO1_INT_		(0x00000002)  /* R/W */
+#define	INT_EN_GPIO0_INT_		(0x00000001)  /* R/W */
+
+#define BYTE_TEST		(0x64)
+#define FIFO_INT		(0x68)
+#define	FIFO_INT_TX_AVAIL_LEVEL_	(0xFF000000)  /* R/W */
+#define	FIFO_INT_TX_STS_LEVEL_		(0x00FF0000)  /* R/W */
+#define	FIFO_INT_RX_AVAIL_LEVEL_	(0x0000FF00)  /* R/W */
+#define	FIFO_INT_RX_STS_LEVEL_		(0x000000FF)  /* R/W */
+
+#define RX_CFG			(0x6C)
+#define	RX_CFG_RX_END_ALGN_		(0xC0000000)  /* R/W */
+#define		RX_CFG_RX_END_ALGN4_		(0x00000000)  /* R/W */
+#define		RX_CFG_RX_END_ALGN16_		(0x40000000)  /* R/W */
+#define		RX_CFG_RX_END_ALGN32_		(0x80000000)  /* R/W */
+#define	RX_CFG_RX_DMA_CNT_		(0x0FFF0000)  /* R/W */
+#define	RX_CFG_RX_DUMP_			(0x00008000)  /* R/W */
+#define	RX_CFG_RXDOFF_			(0x00001F00)  /* R/W */
+//#define	RX_CFG_RXBAD_			(0x00000001)  /* R/W */
+
+#define TX_CFG			(0x70)
+//#define	TX_CFG_TX_DMA_LVL_		(0xE0000000)	 /* R/W */
+//#define	TX_CFG_TX_DMA_CNT_		(0x0FFF0000)	 /* R/W Self Clearing */
+#define	TX_CFG_TXS_DUMP_		(0x00008000)  /* Self Clearing */
+#define	TX_CFG_TXD_DUMP_		(0x00004000)  /* Self Clearing */
+#define	TX_CFG_TXSAO_			(0x00000004)  /* R/W */
+#define	TX_CFG_TX_ON_			(0x00000002)  /* R/W */
+#define	TX_CFG_STOP_TX_			(0x00000001)  /* Self Clearing */
+
+#define HW_CFG			(0x74)
+#define	HW_CFG_TTM_			(0x00200000)  /* R/W */
+#define	HW_CFG_SF_			(0x00100000)  /* R/W */
+#define	HW_CFG_TX_FIF_SZ_		(0x000F0000)  /* R/W */
+#define	HW_CFG_TR_			(0x00003000)  /* R/W */
+#define	HW_CFG_PHY_CLK_SEL_		(0x00000060)  /* R/W */
+#define		 HW_CFG_PHY_CLK_SEL_INT_PHY_ 	(0x00000000) /* R/W */
+#define		 HW_CFG_PHY_CLK_SEL_EXT_PHY_ 	(0x00000020) /* R/W */
+#define		 HW_CFG_PHY_CLK_SEL_CLK_DIS_ 	(0x00000040) /* R/W */
+#define	HW_CFG_SMI_SEL_			(0x00000010)  /* R/W */
+#define	HW_CFG_EXT_PHY_DET_		(0x00000008)  /* RO */
+#define	HW_CFG_EXT_PHY_EN_		(0x00000004)  /* R/W */
+#define	HW_CFG_32_16_BIT_MODE_		(0x00000004)  /* RO */
+#define	HW_CFG_SRST_TO_			(0x00000002)  /* RO */
+#define	HW_CFG_SRST_			(0x00000001)  /* Self Clearing */
+
+#define RX_DP_CTRL		(0x78)
+#define	RX_DP_CTRL_RX_FFWD_		(0x80000000)  /* R/W */
+#define	RX_DP_CTRL_FFWD_BUSY_		(0x80000000)  /* RO */
+
+#define RX_FIFO_INF		(0x7C)
+#define	 RX_FIFO_INF_RXSUSED_		(0x00FF0000)  /* RO */
+#define	 RX_FIFO_INF_RXDUSED_		(0x0000FFFF)  /* RO */
+
+#define TX_FIFO_INF		(0x80)
+#define	TX_FIFO_INF_TSUSED_		(0x00FF0000)  /* RO */
+#define	TX_FIFO_INF_TDFREE_		(0x0000FFFF)  /* RO */
+
+#define PMT_CTRL		(0x84)
+#define	PMT_CTRL_PM_MODE_		(0x00003000)  /* Self Clearing */
+#define	PMT_CTRL_PHY_RST_		(0x00000400)  /* Self Clearing */
+#define	PMT_CTRL_WOL_EN_		(0x00000200)  /* R/W */
+#define	PMT_CTRL_ED_EN_			(0x00000100)  /* R/W */
+#define	PMT_CTRL_PME_TYPE_		(0x00000040)  /* R/W Not Affected by SW Reset */
+#define	PMT_CTRL_WUPS_			(0x00000030)  /* R/WC */
+#define		PMT_CTRL_WUPS_NOWAKE_		(0x00000000)  /* R/WC */
+#define		PMT_CTRL_WUPS_ED_		(0x00000010)  /* R/WC */
+#define		PMT_CTRL_WUPS_WOL_		(0x00000020)  /* R/WC */
+#define		PMT_CTRL_WUPS_MULTI_		(0x00000030)  /* R/WC */
+#define	PMT_CTRL_PME_IND_		(0x00000008)  /* R/W */
+#define	PMT_CTRL_PME_POL_		(0x00000004)  /* R/W */
+#define	PMT_CTRL_PME_EN_		(0x00000002)  /* R/W Not Affected by SW Reset */
+#define	PMT_CTRL_READY_			(0x00000001)  /* RO */
+
+#define GPIO_CFG		(0x88)
+#define	GPIO_CFG_LED3_EN_		(0x40000000)  /* R/W */
+#define	GPIO_CFG_LED2_EN_		(0x20000000)  /* R/W */
+#define	GPIO_CFG_LED1_EN_		(0x10000000)  /* R/W */
+#define	GPIO_CFG_GPIO2_INT_POL_		(0x04000000)  /* R/W */
+#define	GPIO_CFG_GPIO1_INT_POL_		(0x02000000)  /* R/W */
+#define	GPIO_CFG_GPIO0_INT_POL_		(0x01000000)  /* R/W */
+#define	GPIO_CFG_EEPR_EN_		(0x00700000)  /* R/W */
+#define	GPIO_CFG_GPIOBUF2_		(0x00040000)  /* R/W */
+#define	GPIO_CFG_GPIOBUF1_		(0x00020000)  /* R/W */
+#define	GPIO_CFG_GPIOBUF0_		(0x00010000)  /* R/W */
+#define	GPIO_CFG_GPIODIR2_		(0x00000400)  /* R/W */
+#define	GPIO_CFG_GPIODIR1_		(0x00000200)  /* R/W */
+#define	GPIO_CFG_GPIODIR0_		(0x00000100)  /* R/W */
+#define	GPIO_CFG_GPIOD4_		(0x00000010)  /* R/W */
+#define	GPIO_CFG_GPIOD3_		(0x00000008)  /* R/W */
+#define	GPIO_CFG_GPIOD2_		(0x00000004)  /* R/W */
+#define	GPIO_CFG_GPIOD1_		(0x00000002)  /* R/W */
+#define	GPIO_CFG_GPIOD0_		(0x00000001)  /* R/W */
+
+#define GPT_CFG			(0x8C)
+#define	GPT_CFG_TIMER_EN_		(0x20000000)  /* R/W */
+#define	GPT_CFG_GPT_LOAD_		(0x0000FFFF)  /* R/W */
+
+#define GPT_CNT			(0x90)
+#define	GPT_CNT_GPT_CNT_		(0x0000FFFF)  /* RO */
+
+#define ENDIAN			(0x98)
+#define FREE_RUN		(0x9C)
+#define RX_DROP			(0xA0)
+#define MAC_CSR_CMD		(0xA4)
+#define	 MAC_CSR_CMD_CSR_BUSY_		(0x80000000)  /* Self Clearing */
+#define	 MAC_CSR_CMD_R_NOT_W_		(0x40000000)  /* R/W */
+#define	 MAC_CSR_CMD_CSR_ADDR_		(0x000000FF)  /* R/W */
+
+#define MAC_CSR_DATA		(0xA8)
+#define AFC_CFG			(0xAC)
+#define		AFC_CFG_AFC_HI_			(0x00FF0000)  /* R/W */
+#define		AFC_CFG_AFC_LO_			(0x0000FF00)  /* R/W */
+#define		AFC_CFG_BACK_DUR_		(0x000000F0)  /* R/W */
+#define		AFC_CFG_FCMULT_			(0x00000008)  /* R/W */
+#define		AFC_CFG_FCBRD_			(0x00000004)  /* R/W */
+#define		AFC_CFG_FCADD_			(0x00000002)  /* R/W */
+#define		AFC_CFG_FCANY_			(0x00000001)  /* R/W */
+
+#define E2P_CMD			(0xB0)
+#define	E2P_CMD_EPC_BUSY_		(0x80000000)  /* Self Clearing */
+#define	E2P_CMD_EPC_CMD_			(0x70000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_READ_		(0x00000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_EWDS_		(0x10000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_EWEN_		(0x20000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_WRITE_		(0x30000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_WRAL_		(0x40000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_ERASE_		(0x50000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_ERAL_		(0x60000000)  /* R/W */
+#define		E2P_CMD_EPC_CMD_RELOAD_		(0x70000000)  /* R/W */
+#define	E2P_CMD_EPC_TIMEOUT_		(0x00000200)  /* RO */
+#define	E2P_CMD_MAC_ADDR_LOADED_	(0x00000100)  /* RO */
+#define	E2P_CMD_EPC_ADDR_		(0x000000FF)  /* R/W */
+
+#define E2P_DATA		(0xB4)
+#define	E2P_DATA_EEPROM_DATA_		(0x000000FF)  /* R/W */
+/* end of LAN register offsets and bit definitions */
+
+/*
+ ****************************************************************************
+ ****************************************************************************
+ * MAC Control and Status Register (Indirect Address)
+ * Offset (through the MAC_CSR CMD and DATA port)
+ ****************************************************************************
+ ****************************************************************************
+ *
+ */
+#define MAC_CR			(0x01)  /* R/W */
+
+/* MAC_CR - MAC Control Register */
+#define MAC_CR_RXALL_			(0x80000000)
+// TODO: delete this bit? It is not described in the data sheet.
+#define MAC_CR_HBDIS_			(0x10000000)
+#define MAC_CR_RCVOWN_			(0x00800000)
+#define MAC_CR_LOOPBK_			(0x00200000)
+#define MAC_CR_FDPX_			(0x00100000)
+#define MAC_CR_MCPAS_			(0x00080000)
+#define MAC_CR_PRMS_			(0x00040000)
+#define MAC_CR_INVFILT_			(0x00020000)
+#define MAC_CR_PASSBAD_			(0x00010000)
+#define MAC_CR_HFILT_			(0x00008000)
+#define MAC_CR_HPFILT_			(0x00002000)
+#define MAC_CR_LCOLL_			(0x00001000)
+#define MAC_CR_BCAST_			(0x00000800)
+#define MAC_CR_DISRTY_			(0x00000400)
+#define MAC_CR_PADSTR_			(0x00000100)
+#define MAC_CR_BOLMT_MASK_		(0x000000C0)
+#define MAC_CR_DFCHK_			(0x00000020)
+#define MAC_CR_TXEN_			(0x00000008)
+#define MAC_CR_RXEN_			(0x00000004)
+
+#define ADDRH			(0x02)	  /* R/W mask 0x0000FFFFUL */
+#define ADDRL			(0x03)	  /* R/W mask 0xFFFFFFFFUL */
+#define HASHH			(0x04)	  /* R/W */
+#define HASHL			(0x05)	  /* R/W */
+
+#define MII_ACC			(0x06)	  /* R/W */
+#define MII_ACC_PHY_ADDR_		(0x0000F800)
+#define MII_ACC_MIIRINDA_		(0x000007C0)
+#define MII_ACC_MII_WRITE_		(0x00000002)
+#define MII_ACC_MII_BUSY_		(0x00000001)
+
+#define MII_DATA		(0x07)	  /* R/W mask 0x0000FFFFUL */
+
+#define FLOW			(0x08)	  /* R/W */
+#define FLOW_FCPT_			(0xFFFF0000)
+#define FLOW_FCPASS_			(0x00000004)
+#define FLOW_FCEN_			(0x00000002)
+#define FLOW_FCBSY_			(0x00000001)
+
+#define VLAN1			(0x09)	  /* R/W mask 0x0000FFFFUL */
+#define VLAN1_VTI1_			(0x0000ffff)
+
+#define VLAN2			(0x0A)	  /* R/W mask 0x0000FFFFUL */
+#define VLAN2_VTI2_			(0x0000ffff)
+
+#define WUFF			(0x0B)	  /* WO */
+
+#define WUCSR			(0x0C)	  /* R/W */
+#define WUCSR_GUE_			(0x00000200)
+#define WUCSR_WUFR_			(0x00000040)
+#define WUCSR_MPR_			(0x00000020)
+#define WUCSR_WAKE_EN_			(0x00000004)
+#define WUCSR_MPEN_			(0x00000002)
+
+/*
+ ****************************************************************************
+ * Chip Specific MII Defines
+ ****************************************************************************
+ *
+ * Phy register offsets and bit definitions
+ *
+ */
+
+#define PHY_MODE_CTRL_STS	((u32)17)	/* Mode Control/Status Register */
+//#define MODE_CTRL_STS_FASTRIP_	  ((u16)0x4000)
+#define MODE_CTRL_STS_EDPWRDOWN_	 ((u16)0x2000)
+//#define MODE_CTRL_STS_LOWSQEN_	   ((u16)0x0800)
+//#define MODE_CTRL_STS_MDPREBP_	   ((u16)0x0400)
+//#define MODE_CTRL_STS_FARLOOPBACK_  ((u16)0x0200)
+//#define MODE_CTRL_STS_FASTEST_	   ((u16)0x0100)
+//#define MODE_CTRL_STS_REFCLKEN_	   ((u16)0x0010)
+//#define MODE_CTRL_STS_PHYADBP_	   ((u16)0x0008)
+//#define MODE_CTRL_STS_FORCE_G_LINK_ ((u16)0x0004)
+#define MODE_CTRL_STS_ENERGYON_	 	((u16)0x0002)
+
+#define PHY_INT_SRC			((u32)29)
+#define PHY_INT_SRC_ENERGY_ON_			((u16)0x0080)
+#define PHY_INT_SRC_ANEG_COMP_			((u16)0x0040)
+#define PHY_INT_SRC_REMOTE_FAULT_		((u16)0x0020)
+#define PHY_INT_SRC_LINK_DOWN_			((u16)0x0010)
+#define PHY_INT_SRC_ANEG_LP_ACK_		((u16)0x0008)
+#define PHY_INT_SRC_PAR_DET_FAULT_		((u16)0x0004)
+#define PHY_INT_SRC_ANEG_PGRX_			((u16)0x0002)
+
+#define PHY_INT_MASK			((u32)30)
+#define PHY_INT_MASK_ENERGY_ON_			((u16)0x0080)
+#define PHY_INT_MASK_ANEG_COMP_			((u16)0x0040)
+#define PHY_INT_MASK_REMOTE_FAULT_		((u16)0x0020)
+#define PHY_INT_MASK_LINK_DOWN_			((u16)0x0010)
+#define PHY_INT_MASK_ANEG_LP_ACK_		((u16)0x0008)
+#define PHY_INT_MASK_PAR_DET_FAULT_		((u16)0x0004)
+#define PHY_INT_MASK_ANEG_PGRX_			((u16)0x0002)
+
+#define PHY_SPECIAL			((u32)31)
+#define PHY_SPECIAL_ANEG_DONE_			((u16)0x1000)
+#define PHY_SPECIAL_RES_			((u16)0x0040)
+#define PHY_SPECIAL_RES_MASK_			((u16)0x0FE1)
+#define PHY_SPECIAL_SPD_			((u16)0x001C)
+#define PHY_SPECIAL_SPD_10HALF_			((u16)0x0004)
+#define PHY_SPECIAL_SPD_10FULL_			((u16)0x0014)
+#define PHY_SPECIAL_SPD_100HALF_		((u16)0x0008)
+#define PHY_SPECIAL_SPD_100FULL_		((u16)0x0018)
+
+#define LAN911X_INTERNAL_PHY_ID		(0x0007C000)
+
+/* Chip ID values */
+#define CHIP_9115	0x115
+#define CHIP_9116	0x116
+#define CHIP_9117	0x117
+#define CHIP_9118	0x118
+
+struct chip_id {
+	u16 id;
+	char *name;
+};
+
+static const struct chip_id chip_ids[] =  {
+	{ CHIP_9115, "LAN9115" },
+	{ CHIP_9116, "LAN9116" },
+	{ CHIP_9117, "LAN9117" },
+	{ CHIP_9118, "LAN9118" },
+	{ 0, NULL },
+};
+
+#define IS_REV_A(x)	((x & 0xFFFF)==0)
+
+/*
+ * Macros to abstract register access according to the data bus
+ * capabilities.  Please use those and not the in/out primitives.
+ */
+/* FIFO read/write macros */
+#define SMC_PUSH_DATA(p, l)	SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 )
+#define SMC_PULL_DATA(p, l)	SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 )
+#define SMC_SET_TX_FIFO(x) 	SMC_outl( x, ioaddr, TX_DATA_FIFO )
+#define SMC_GET_RX_FIFO()	SMC_inl( ioaddr, RX_DATA_FIFO )
+
+
+/* I/O mapped register read/write macros */
+#define SMC_GET_TX_STS_FIFO()		SMC_inl( ioaddr, TX_STATUS_FIFO )
+#define SMC_GET_RX_STS_FIFO()		SMC_inl( ioaddr, RX_STATUS_FIFO )
+#define SMC_GET_RX_STS_FIFO_PEEK()	SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK )
+#define SMC_GET_PN()			(SMC_inl( ioaddr, ID_REV ) >> 16)
+#define SMC_GET_REV()			(SMC_inl( ioaddr, ID_REV ) & 0xFFFF)
+#define SMC_GET_IRQ_CFG()		SMC_inl( ioaddr, INT_CFG )
+#define SMC_SET_IRQ_CFG(x)		SMC_outl( x, ioaddr, INT_CFG )
+#define SMC_GET_INT()			SMC_inl( ioaddr, INT_STS )
+#define SMC_ACK_INT(x)			SMC_outl( x, ioaddr, INT_STS )
+#define SMC_GET_INT_EN()		SMC_inl( ioaddr, INT_EN )
+#define SMC_SET_INT_EN(x)		SMC_outl( x, ioaddr, INT_EN )
+#define SMC_GET_BYTE_TEST()		SMC_inl( ioaddr, BYTE_TEST )
+#define SMC_SET_BYTE_TEST(x)		SMC_outl( x, ioaddr, BYTE_TEST )
+#define SMC_GET_FIFO_INT()		SMC_inl( ioaddr, FIFO_INT )
+#define SMC_SET_FIFO_INT(x)		SMC_outl( x, ioaddr, FIFO_INT )
+#define SMC_SET_FIFO_TDA(x)					\
+	do {							\
+		unsigned long __flags;				\
+		int __mask;					\
+		local_irq_save(__flags);			\
+		__mask = SMC_GET_FIFO_INT() & ~(0xFF<<24);	\
+		SMC_SET_FIFO_INT( __mask | (x)<<24 );		\
+		local_irq_restore(__flags);			\
+	} while (0)
+#define SMC_SET_FIFO_TSL(x)					\
+	do {							\
+		unsigned long __flags;				\
+		int __mask;					\
+		local_irq_save(__flags);			\
+		__mask = SMC_GET_FIFO_INT() & ~(0xFF<<16);	\
+		SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16));	\
+		local_irq_restore(__flags);			\
+	} while (0)
+#define SMC_SET_FIFO_RSA(x)					\
+	do {							\
+		unsigned long __flags;				\
+		int __mask;					\
+		local_irq_save(__flags);			\
+		__mask = SMC_GET_FIFO_INT() & ~(0xFF<<8);	\
+		SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8));	\
+		local_irq_restore(__flags);			\
+	} while (0)
+#define SMC_SET_FIFO_RSL(x)					\
+	do {							\
+		unsigned long __flags;				\
+		int __mask;					\
+		local_irq_save(__flags);			\
+		__mask = SMC_GET_FIFO_INT() & ~0xFF;		\
+		SMC_SET_FIFO_INT( __mask | ((x) & 0xFF));	\
+		local_irq_restore(__flags);			\
+	} while (0)
+#define SMC_GET_RX_CFG()		SMC_inl( ioaddr, RX_CFG )
+#define SMC_SET_RX_CFG(x)		SMC_outl( x, ioaddr, RX_CFG )
+#define SMC_GET_TX_CFG()		SMC_inl( ioaddr, TX_CFG )
+#define SMC_SET_TX_CFG(x)		SMC_outl( x, ioaddr, TX_CFG )
+#define SMC_GET_HW_CFG()		SMC_inl( ioaddr, HW_CFG )
+#define SMC_SET_HW_CFG(x)		SMC_outl( x, ioaddr, HW_CFG )
+#define SMC_GET_RX_DP_CTRL()		SMC_inl( ioaddr, RX_DP_CTRL )
+#define SMC_SET_RX_DP_CTRL(x)		SMC_outl( x, ioaddr, RX_DP_CTRL )
+#define SMC_GET_PMT_CTRL()		SMC_inl( ioaddr, PMT_CTRL )
+#define SMC_SET_PMT_CTRL(x)		SMC_outl( x, ioaddr, PMT_CTRL )
+#define SMC_GET_GPIO_CFG()		SMC_inl( ioaddr, GPIO_CFG )
+#define SMC_SET_GPIO_CFG(x)		SMC_outl( x, ioaddr, GPIO_CFG )
+#define SMC_GET_RX_FIFO_INF()		SMC_inl( ioaddr, RX_FIFO_INF )
+#define SMC_SET_RX_FIFO_INF(x)		SMC_outl( x, ioaddr, RX_FIFO_INF )
+#define SMC_GET_TX_FIFO_INF()		SMC_inl( ioaddr, TX_FIFO_INF )
+#define SMC_SET_TX_FIFO_INF(x)		SMC_outl( x, ioaddr, TX_FIFO_INF )
+#define SMC_GET_GPT_CFG()		SMC_inl( ioaddr, GPT_CFG )
+#define SMC_SET_GPT_CFG(x)		SMC_outl( x, ioaddr, GPT_CFG )
+#define SMC_GET_RX_DROP()		SMC_inl( ioaddr, RX_DROP )
+#define SMC_SET_RX_DROP(x)		SMC_outl( x, ioaddr, RX_DROP )
+#define SMC_GET_MAC_CMD()		SMC_inl( ioaddr, MAC_CSR_CMD )
+#define SMC_SET_MAC_CMD(x)		SMC_outl( x, ioaddr, MAC_CSR_CMD )
+#define SMC_GET_MAC_DATA()		SMC_inl( ioaddr, MAC_CSR_DATA )
+#define SMC_SET_MAC_DATA(x)		SMC_outl( x, ioaddr, MAC_CSR_DATA )
+#define SMC_GET_AFC_CFG()		SMC_inl( ioaddr, AFC_CFG )
+#define SMC_SET_AFC_CFG(x)		SMC_outl( x, ioaddr, AFC_CFG )
+#define SMC_GET_E2P_CMD()		SMC_inl( ioaddr, E2P_CMD )
+#define SMC_SET_E2P_CMD(x)		SMC_outl( x, ioaddr, E2P_CMD )
+#define SMC_GET_E2P_DATA()		SMC_inl( ioaddr, E2P_DATA )
+#define SMC_SET_E2P_DATA(x)		SMC_outl( x, ioaddr, E2P_DATA )
+
+/* MAC register read/write macros */
+#define SMC_GET_MAC_CSR(a,v)						\
+	do {								\
+		while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);	\
+		SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ |			\
+			MAC_CSR_CMD_R_NOT_W_ | (a) );			\
+		while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);	\
+		v = SMC_GET_MAC_DATA();					\
+	} while (0)
+#define SMC_SET_MAC_CSR(a,v)						\
+	do {								\
+		while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);	\
+		SMC_SET_MAC_DATA(v);					\
+		SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) );		\
+		while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);	\
+	} while (0)
+#define SMC_GET_MAC_CR(x)	SMC_GET_MAC_CSR( MAC_CR, x )
+#define SMC_SET_MAC_CR(x)	SMC_SET_MAC_CSR( MAC_CR, x )
+#define SMC_GET_ADDRH(x)	SMC_GET_MAC_CSR( ADDRH, x )
+#define SMC_SET_ADDRH(x)	SMC_SET_MAC_CSR( ADDRH, x )
+#define SMC_GET_ADDRL(x)	SMC_GET_MAC_CSR( ADDRL, x )
+#define SMC_SET_ADDRL(x)	SMC_SET_MAC_CSR( ADDRL, x )
+#define SMC_GET_HASHH(x)	SMC_GET_MAC_CSR( HASHH, x )
+#define SMC_SET_HASHH(x)	SMC_SET_MAC_CSR( HASHH, x )
+#define SMC_GET_HASHL(x)	SMC_GET_MAC_CSR( HASHL, x )
+#define SMC_SET_HASHL(x)	SMC_SET_MAC_CSR( HASHL, x )
+#define SMC_GET_MII_ACC(x)	SMC_GET_MAC_CSR( MII_ACC, x )
+#define SMC_SET_MII_ACC(x)	SMC_SET_MAC_CSR( MII_ACC, x )
+#define SMC_GET_MII_DATA(x)	SMC_GET_MAC_CSR( MII_DATA, x )
+#define SMC_SET_MII_DATA(x)	SMC_SET_MAC_CSR( MII_DATA, x )
+#define SMC_GET_FLOW(x)		SMC_GET_MAC_CSR( FLOW, x )
+#define SMC_SET_FLOW(x)		SMC_SET_MAC_CSR( FLOW, x )
+#define SMC_GET_VLAN1(x)	SMC_GET_MAC_CSR( VLAN1, x )
+#define SMC_SET_VLAN1(x)	SMC_SET_MAC_CSR( VLAN1, x )
+#define SMC_GET_VLAN2(x)	SMC_GET_MAC_CSR( VLAN2, x )
+#define SMC_SET_VLAN2(x)	SMC_SET_MAC_CSR( VLAN2, x )
+#define SMC_SET_WUFF(x)		SMC_SET_MAC_CSR( WUFF, x )
+#define SMC_GET_WUCSR(x)	SMC_GET_MAC_CSR( WUCSR, x )
+#define SMC_SET_WUCSR(x)	SMC_SET_MAC_CSR( WUCSR, x )
+
+/* PHY register read/write macros */
+#define SMC_GET_MII(a,phy,v)					\
+	do {							\
+		u32 __v;					\
+		do {						\
+			SMC_GET_MII_ACC(__v);			\
+		} while ( __v & MII_ACC_MII_BUSY_ );		\
+		SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |	\
+			MII_ACC_MII_BUSY_);			\
+		do {						\
+			SMC_GET_MII_ACC(__v);			\
+		} while ( __v & MII_ACC_MII_BUSY_ );		\
+		SMC_GET_MII_DATA(v);				\
+	} while (0)
+#define SMC_SET_MII(a,phy,v)					\
+	do {							\
+		u32 __v;					\
+		do {						\
+			SMC_GET_MII_ACC(__v);			\
+		} while ( __v & MII_ACC_MII_BUSY_ );		\
+		SMC_SET_MII_DATA(v);				\
+		SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) |	\
+			MII_ACC_MII_BUSY_	 |		\
+			MII_ACC_MII_WRITE_  );			\
+		do {						\
+			SMC_GET_MII_ACC(__v);			\
+		} while ( __v & MII_ACC_MII_BUSY_ );		\
+	} while (0)
+#define SMC_GET_PHY_BMCR(phy,x)		SMC_GET_MII( MII_BMCR, phy, x )
+#define SMC_SET_PHY_BMCR(phy,x)		SMC_SET_MII( MII_BMCR, phy, x )
+#define SMC_GET_PHY_BMSR(phy,x)		SMC_GET_MII( MII_BMSR, phy, x )
+#define SMC_GET_PHY_ID1(phy,x)		SMC_GET_MII( MII_PHYSID1, phy, x )
+#define SMC_GET_PHY_ID2(phy,x)		SMC_GET_MII( MII_PHYSID2, phy, x )
+#define SMC_GET_PHY_MII_ADV(phy,x)	SMC_GET_MII( MII_ADVERTISE, phy, x )
+#define SMC_SET_PHY_MII_ADV(phy,x)	SMC_SET_MII( MII_ADVERTISE, phy, x )
+#define SMC_GET_PHY_MII_LPA(phy,x)	SMC_GET_MII( MII_LPA, phy, x )
+#define SMC_SET_PHY_MII_LPA(phy,x)	SMC_SET_MII( MII_LPA, phy, x )
+#define SMC_GET_PHY_CTRL_STS(phy,x)	SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x )
+#define SMC_SET_PHY_CTRL_STS(phy,x)	SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x )
+#define SMC_GET_PHY_INT_SRC(phy,x)	SMC_GET_MII( PHY_INT_SRC, phy, x )
+#define SMC_SET_PHY_INT_SRC(phy,x)	SMC_SET_MII( PHY_INT_SRC, phy, x )
+#define SMC_GET_PHY_INT_MASK(phy,x)	SMC_GET_MII( PHY_INT_MASK, phy, x )
+#define SMC_SET_PHY_INT_MASK(phy,x)	SMC_SET_MII( PHY_INT_MASK, phy, x )
+#define SMC_GET_PHY_SPECIAL(phy,x)	SMC_GET_MII( PHY_SPECIAL, phy, x )
+
+
+
+/* Misc read/write macros */
+
+#ifndef SMC_GET_MAC_ADDR
+#define SMC_GET_MAC_ADDR(addr)					\
+	do {							\
+		unsigned int __v;				\
+								\
+		SMC_GET_MAC_CSR(ADDRL, __v);			\
+		addr[0] = __v; addr[1] = __v >> 8;		\
+		addr[2] = __v >> 16; addr[3] = __v >> 24;	\
+		SMC_GET_MAC_CSR(ADDRH, __v);			\
+		addr[4] = __v; addr[5] = __v >> 8;		\
+	} while (0)
+#endif
+
+#define SMC_SET_MAC_ADDR(addr)					\
+	do {							\
+		 SMC_SET_MAC_CSR(ADDRL,				\
+				 addr[0] |			\
+				(addr[1] << 8) |		\
+				(addr[2] << 16) |		\
+				(addr[3] << 24));		\
+		 SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\
+	} while (0)
+
+
+#define SMC_WRITE_EEPROM_CMD(cmd, addr)					\
+	do {								\
+		while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_);	\
+		SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a );		\
+		while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_);	\
+	} while (0)
+
+#endif	 /* _SMC911X_H_ */
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index f86697d..8b0321f 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -523,8 +523,7 @@
 	length = skb->len;
 
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL) {
+		if (skb_padto(skb, ETH_ZLEN)) {
 			netif_wake_queue(dev);
 			return 0;
 		}
@@ -732,12 +731,9 @@
 struct net_device * __init smc_init(int unit)
 {
 	struct net_device *dev = alloc_etherdev(sizeof(struct smc_local));
-	static struct devlist *smcdev = smc_devlist;
+	struct devlist *smcdev = smc_devlist;
 	int err = 0;
 
-#ifndef NO_AUTOPROBE
-	smcdev = smc_devlist;
-#endif
 	if (!dev)
 		return ERR_PTR(-ENODEV);
 
@@ -1607,7 +1603,7 @@
 MODULE_PARM_DESC(irq, "SMC 99194 IRQ number");
 MODULE_PARM_DESC(ifport, "SMC 99194 interface port (0-default, 1-TP, 2-AUI)");
 
-int init_module(void)
+int __init init_module(void)
 {
 	if (io == 0)
 		printk(KERN_WARNING
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index e1be1af..bf776125c 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -129,6 +129,24 @@
 #define SMC_insb(a, r, p, l)	readsb((a) + (r), p, (l))
 #define SMC_outsb(a, r, p, l)	writesb((a) + (r), p, (l))
 
+#elif	defined(CONFIG_MACH_LOGICPD_PXA270)
+
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+#define SMC_IO_SHIFT		0
+#define SMC_NOWAIT		1
+#define SMC_USE_PXA_DMA		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)	writew(v, (a) + (r))
+#define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
+
 #elif	defined(CONFIG_ARCH_INNOKOM) || \
 	defined(CONFIG_MACH_MAINSTONE) || \
 	defined(CONFIG_ARCH_PXA_IDP) || \
@@ -242,15 +260,17 @@
 #define RPC_LSA_DEFAULT		RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT		RPC_LED_100_10
 
-#elif	defined(CONFIG_MACH_LPD7A400) || defined(CONFIG_MACH_LPD7A404)
+#elif   defined(CONFIG_MACH_LPD79520) \
+     || defined(CONFIG_MACH_LPD7A400) \
+     || defined(CONFIG_MACH_LPD7A404)
 
-/* The LPD7A40X_IOBARRIER is necessary to overcome a mismatch between
- * the way that the CPU handles chip selects and the way that the SMC
- * chip expects the chip select to operate.  Refer to
+/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the
+ * way that the CPU handles chip selects and the way that the SMC chip
+ * expects the chip select to operate.  Refer to
  * Documentation/arm/Sharp-LH/IOBarrier for details.  The read from
- * IOBARRIER is a byte as a least-common denominator of possible
- * regions to use as the barrier.  It would be wasteful to read 32
- * bits from a byte oriented region.
+ * IOBARRIER is a byte, in order that we read the least-common
+ * denominator.  It would be wasteful to read 32 bits from an 8-bit
+ * accessible region.
  *
  * There is no explicit protection against interrupts intervening
  * between the writew and the IOBARRIER.  In SMC ISR there is a
@@ -269,25 +289,35 @@
 #define SMC_CAN_USE_16BIT	1
 #define SMC_CAN_USE_32BIT	0
 #define SMC_NOWAIT		0
-#define LPD7A40X_IOBARRIER	readb (IOBARRIER_VIRT)
+#define LPD7X_IOBARRIER		readb (IOBARRIER_VIRT)
 
-#define SMC_inw(a,r)		readw ((void*) ((a) + (r)))
-#define SMC_insw(a,r,p,l)	readsw ((void*) ((a) + (r)), p, l)
-#define SMC_outw(v,a,r)	     ({ writew ((v), (a) + (r)); LPD7A40X_IOBARRIER; })
+#define SMC_inw(a,r)\
+   ({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; })
+#define SMC_outw(v,a,r)	  ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; })
 
-#define SMC_outsw		LPD7A40X_SMC_outsw
+#define SMC_insw		LPD7_SMC_insw
+static inline void LPD7_SMC_insw (unsigned char* a, int r,
+				  unsigned char* p, int l)
+{
+	unsigned short* ps = (unsigned short*) p;
+	while (l-- > 0) {
+		*ps++ = readw (a + r);
+		LPD7X_IOBARRIER;
+	}
+}
 
-static inline void LPD7A40X_SMC_outsw(unsigned long a, int r,
-				     unsigned char* p, int l)
+#define SMC_outsw		LPD7_SMC_outsw
+static inline void LPD7_SMC_outsw (unsigned char* a, int r,
+				   unsigned char* p, int l)
 {
 	unsigned short* ps = (unsigned short*) p;
 	while (l-- > 0) {
 		writew (*ps++, a + r);
-		LPD7A40X_IOBARRIER;
+		LPD7X_IOBARRIER;
 	}
 }
 
-#define SMC_INTERRUPT_PREAMBLE	LPD7A40X_IOBARRIER
+#define SMC_INTERRUPT_PREAMBLE	LPD7X_IOBARRIER
 
 #define RPC_LSA_DEFAULT		RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT		RPC_LED_100_10
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index 90b818a..cab0dd9 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -231,8 +231,7 @@
 
 	length = skb->len;
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 9b7805b..c158eed 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -1349,8 +1349,7 @@
 
 #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
 	if (skb->ip_summed == CHECKSUM_HW) {
-		skb = skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK);
-		if (skb == NULL)
+		if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK))
 			return NETDEV_TX_OK;
 	}
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index d4c0002..a2fad50 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -55,7 +55,7 @@
 /* sun3/60 addr/irq for the lance chip.  If your sun is different,
    change this. */
 #define LANCE_OBIO 0x120000
-#define LANCE_IRQ IRQ3
+#define LANCE_IRQ IRQ_AUTO_3
 
 /* Debug level:
  *  0 = silent, print only serious errors
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index cfaf47c..7127f0f 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -72,8 +72,6 @@
 #define DIRQ(x)
 #endif
 
-static struct bigmac *root_bigmac_dev;
-
 #define DEFAULT_JAMSIZE    4 /* Toe jam */
 
 #define QEC_RESET_TRIES 200
@@ -491,7 +489,7 @@
 	}
 }
 
-static int bigmac_init(struct bigmac *, int);
+static int bigmac_init_hw(struct bigmac *, int);
 
 static int try_next_permutation(struct bigmac *bp, void __iomem *tregs)
 {
@@ -551,7 +549,7 @@
 				if (ret == -1) {
 					printk(KERN_ERR "%s: Link down, cable problem?\n",
 					       bp->dev->name);
-					ret = bigmac_init(bp, 0);
+					ret = bigmac_init_hw(bp, 0);
 					if (ret) {
 						printk(KERN_ERR "%s: Error, cannot re-init the "
 						       "BigMAC.\n", bp->dev->name);
@@ -621,7 +619,7 @@
 	add_timer(&bp->bigmac_timer);
 }
 
-static int bigmac_init(struct bigmac *bp, int from_irq)
+static int bigmac_init_hw(struct bigmac *bp, int from_irq)
 {
 	void __iomem *gregs        = bp->gregs;
 	void __iomem *cregs        = bp->creg;
@@ -752,7 +750,7 @@
 	}
 
 	printk(" RESET\n");
-	bigmac_init(bp, 1);
+	bigmac_init_hw(bp, 1);
 }
 
 /* BigMAC transmit complete service routines. */
@@ -926,7 +924,7 @@
 		return ret;
 	}
 	init_timer(&bp->bigmac_timer);
-	ret = bigmac_init(bp, 0);
+	ret = bigmac_init_hw(bp, 0);
 	if (ret)
 		free_irq(dev->irq, bp);
 	return ret;
@@ -950,7 +948,7 @@
 {
 	struct bigmac *bp = (struct bigmac *) dev->priv;
 
-	bigmac_init(bp, 0);
+	bigmac_init_hw(bp, 0);
 	netif_wake_queue(dev);
 }
 
@@ -1104,6 +1102,8 @@
 	bp->qec_sdev = qec_sdev;
 	bp->bigmac_sdev = qec_sdev->child;
 
+	SET_NETDEV_DEV(dev, &bp->bigmac_sdev->ofdev.dev);
+
 	spin_lock_init(&bp->lock);
 
 	/* Verify the registers we expect, are actually there. */
@@ -1226,11 +1226,7 @@
 		goto fail_and_cleanup;
 	}
 
-	/* Put us into the list of instances attached for later driver
-	 * exit.
-	 */
-	bp->next_module = root_bigmac_dev;
-	root_bigmac_dev = bp;
+	dev_set_drvdata(&bp->bigmac_sdev->ofdev.dev, bp);
 
 	printk(KERN_INFO "%s: BigMAC 100baseT Ethernet ", dev->name);
 	for (i = 0; i < 6; i++)
@@ -1266,69 +1262,68 @@
 /* QEC can be the parent of either QuadEthernet or
  * a BigMAC.  We want the latter.
  */
-static int __init bigmac_match(struct sbus_dev *sdev)
+static int __devinit bigmac_sbus_probe(struct of_device *dev, const struct of_device_id *match)
 {
-	struct sbus_dev *child = sdev->child;
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+	struct device_node *dp = dev->node;
 
-	if (strcmp(sdev->prom_name, "qec") != 0)
-		return 0;
+	if (!strcmp(dp->name, "be"))
+		sdev = sdev->parent;
 
-	if (child == NULL)
-		return 0;
-
-	if (strcmp(child->prom_name, "be") != 0)
-		return 0;
-
-	return 1;
+	return bigmac_ether_init(sdev);
 }
 
-static int __init bigmac_probe(void)
+static int __devexit bigmac_sbus_remove(struct of_device *dev)
 {
-	struct sbus_bus *sbus;
-	struct sbus_dev *sdev = NULL;
-	static int called;
-	int cards = 0, v;
+	struct bigmac *bp = dev_get_drvdata(&dev->dev);
+	struct net_device *net_dev = bp->dev;
 
-	root_bigmac_dev = NULL;
+	unregister_netdevice(net_dev);
 
-	if (called)
-		return -ENODEV;
-	called++;
+	sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
+	sbus_iounmap(bp->creg, CREG_REG_SIZE);
+	sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
+	sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
+	sbus_free_consistent(bp->bigmac_sdev,
+			     PAGE_SIZE,
+			     bp->bmac_block,
+			     bp->bblock_dvma);
 
-	for_each_sbus(sbus) {
-		for_each_sbusdev(sdev, sbus) {
-			if (bigmac_match(sdev)) {
-				cards++;
-				if ((v = bigmac_ether_init(sdev)))
-					return v;
-			}
-		}
-	}
-	if (!cards)
-		return -ENODEV;
+	free_netdev(net_dev);
+
+	dev_set_drvdata(&dev->dev, NULL);
+
 	return 0;
 }
 
-static void __exit bigmac_cleanup(void)
+static struct of_device_id bigmac_sbus_match[] = {
+	{
+		.name = "qec",
+	},
+	{
+		.name = "be",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, bigmac_sbus_match);
+
+static struct of_platform_driver bigmac_sbus_driver = {
+	.name		= "sunbmac",
+	.match_table	= bigmac_sbus_match,
+	.probe		= bigmac_sbus_probe,
+	.remove		= __devexit_p(bigmac_sbus_remove),
+};
+
+static int __init bigmac_init(void)
 {
-	while (root_bigmac_dev) {
-		struct bigmac *bp = root_bigmac_dev;
-		struct bigmac *bp_nxt = root_bigmac_dev->next_module;
-
-		sbus_iounmap(bp->gregs, GLOB_REG_SIZE);
-		sbus_iounmap(bp->creg, CREG_REG_SIZE);
-		sbus_iounmap(bp->bregs, BMAC_REG_SIZE);
-		sbus_iounmap(bp->tregs, TCVR_REG_SIZE);
-		sbus_free_consistent(bp->bigmac_sdev,
-				     PAGE_SIZE,
-				     bp->bmac_block,
-				     bp->bblock_dvma);
-
-		unregister_netdev(bp->dev);
-		free_netdev(bp->dev);
-		root_bigmac_dev = bp_nxt;
-	}
+	return of_register_driver(&bigmac_sbus_driver, &sbus_bus_type);
 }
 
-module_init(bigmac_probe);
-module_exit(bigmac_cleanup);
+static void __exit bigmac_exit(void)
+{
+	of_unregister_driver(&bigmac_sbus_driver);
+}
+
+module_init(bigmac_init);
+module_exit(bigmac_exit);
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h
index b0dbc51..b563d3c 100644
--- a/drivers/net/sunbmac.h
+++ b/drivers/net/sunbmac.h
@@ -332,7 +332,6 @@
 	struct sbus_dev		*qec_sdev;
 	struct sbus_dev		*bigmac_sdev;
 	struct net_device	*dev;
-	struct bigmac		*next_module;
 };
 
 /* We use this to acquire receive skb's that we can DMA directly into. */
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index 61eec46..f13b2a1 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -94,11 +94,13 @@
 	Version LK1.10 (Philippe De Muyter phdm@macqel.be):
 	- Make 'unblock interface after Tx underrun' work
 
+	Version LK1.11 (Pedro Alejandro Lopez-Valencia palopezv at gmail.com):
+	- Add support for IC Plus Corporation IP100A chipset
 */
 
 #define DRV_NAME	"sundance"
-#define DRV_VERSION	"1.01+LK1.10"
-#define DRV_RELDATE	"28-Oct-2005"
+#define DRV_VERSION	"1.01+LK1.11"
+#define DRV_RELDATE	"14-Jun-2006"
 
 
 /* The user-configurable values.
@@ -287,6 +289,7 @@
 	{0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3},
 	{0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
 	{0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5},
+	{0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, sundance_pci_tbl);
@@ -305,6 +308,7 @@
 	{"D-Link DFE-530TXS FAST Ethernet Adapter"},
 	{"D-Link DL10050-based FAST Ethernet Adapter"},
 	{"Sundance Technology Alta"},
+	{"IC Plus Corporation IP100A FAST Ethernet Adapter"},
 	{NULL,},			/* 0 terminated list. */
 };
 
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 38cd30c..5248670 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2880,17 +2880,20 @@
 #if defined(__sparc__)
 	struct pci_dev *pdev = gp->pdev;
 	struct pcidev_cookie *pcp = pdev->sysdata;
-	int node = -1;
+	int use_idprom = 1;
 
 	if (pcp != NULL) {
-		node = pcp->prom_node;
-		if (prom_getproplen(node, "local-mac-address") == 6)
-			prom_getproperty(node, "local-mac-address",
-					 dev->dev_addr, 6);
-		else
-			node = -1;
+		unsigned char *addr;
+		int len;
+
+		addr = of_get_property(pcp->prom_node, "local-mac-address",
+				       &len);
+		if (addr && len == 6) {
+			use_idprom = 0;
+			memcpy(dev->dev_addr, addr, 6);
+		}
 	}
-	if (node == -1)
+	if (use_idprom)
 		memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
 #elif defined(CONFIG_PPC_PMAC)
 	unsigned char *addr;
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
index b2ddd5e..9282b4b 100644
--- a/drivers/net/sungem_phy.c
+++ b/drivers/net/sungem_phy.c
@@ -345,9 +345,9 @@
 
 static int bcm5461_enable_fiber(struct mii_phy* phy)
 {
-        phy_write(phy, MII_NCONFIG, 0xfc0c);
-        phy_write(phy, MII_BMCR, 0x4140);
-        phy_write(phy, MII_NCONFIG, 0xfc0b);
+	phy_write(phy, MII_NCONFIG, 0xfc0c);
+	phy_write(phy, MII_BMCR, 0x4140);
+	phy_write(phy, MII_NCONFIG, 0xfc0b);
 	phy_write(phy, MII_BMCR, 0x0140);
 
 	return 0;
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index 9f046ca..c33ead3 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1,9 +1,9 @@
-/* $Id: sunhme.c,v 1.124 2002/01/15 06:25:51 davem Exp $
- * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
+/* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
  *
- * Copyright (C) 1996, 1998, 1999, 2002, 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1998, 1999, 2002, 2003,
+		 2006 David S. Miller (davem@davemloft.net)
  *
  * Changes :
  * 2000/11/11 Willy Tarreau <willy AT meta-x.org>
@@ -40,15 +40,13 @@
 #include <asm/dma.h>
 #include <asm/byteorder.h>
 
-#ifdef __sparc__
+#ifdef CONFIG_SPARC
 #include <asm/idprom.h>
 #include <asm/sbus.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/auxio.h>
-#ifndef __sparc_v9__
-#include <asm/io-unit.h>
-#endif
 #endif
 #include <asm/uaccess.h>
 
@@ -57,7 +55,7 @@
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
-#ifdef __sparc__
+#ifdef CONFIG_SPARC
 #include <asm/pbm.h>
 #endif
 #endif
@@ -65,9 +63,9 @@
 #include "sunhme.h"
 
 #define DRV_NAME	"sunhme"
-#define DRV_VERSION	"2.02"
-#define DRV_RELDATE	"8/24/03"
-#define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
+#define DRV_VERSION	"3.00"
+#define DRV_RELDATE	"June 23, 2006"
+#define DRV_AUTHOR	"David S. Miller (davem@davemloft.net)"
 
 static char version[] =
 	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
@@ -83,8 +81,6 @@
 module_param_array(macaddr, int, NULL, 0);
 MODULE_PARM_DESC(macaddr, "Happy Meal MAC address to set");
 
-static struct happy_meal *root_happy_dev;
-
 #ifdef CONFIG_SBUS
 static struct quattro *qfe_sbus_list;
 #endif
@@ -181,26 +177,6 @@
 #define DEFAULT_IPG2       4 /* For all modes */
 #define DEFAULT_JAMSIZE    4 /* Toe jam */
 
-#if defined(CONFIG_PCI) && defined(MODULE)
-/* This happy_pci_ids is declared __initdata because it is only used
-   as an advisory to depmod.  If this is ported to the new PCI interface
-   where it could be referenced at any time due to hot plugging,
-   the __initdata reference should be removed. */
-
-static struct pci_device_id happymeal_pci_ids[] = {
-	{
-	  .vendor	= PCI_VENDOR_ID_SUN,
-	  .device	= PCI_DEVICE_ID_SUN_HAPPYMEAL,
-	  .subvendor	= PCI_ANY_ID,
-	  .subdevice	= PCI_ANY_ID,
-	},
-	{ }			/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(pci, happymeal_pci_ids);
-
-#endif
-
 /* NOTE: In the descriptor writes one _must_ write the address
  *	 member _first_.  The card must not be allowed to see
  *	 the updated descriptor flags until the address is
@@ -1610,7 +1586,7 @@
 	HMD(("happy_meal_init: old[%08x] bursts<",
 	     hme_read32(hp, gregs + GREG_CFG)));
 
-#ifndef __sparc__
+#ifndef CONFIG_SPARC
 	/* It is always PCI and can handle 64byte bursts. */
 	hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST64);
 #else
@@ -1647,7 +1623,7 @@
 		HMD(("XXX>"));
 		hme_write32(hp, gregs + GREG_CFG, 0);
 	}
-#endif /* __sparc__ */
+#endif /* CONFIG_SPARC */
 
 	/* Turn off interrupts we do not want to hear. */
 	HMD((", enable global interrupts, "));
@@ -2221,13 +2197,8 @@
 		if (request_irq(dev->irq, &happy_meal_interrupt,
 				SA_SHIRQ, dev->name, (void *)dev)) {
 			HMD(("EAGAIN\n"));
-#ifdef __sparc__
-			printk(KERN_ERR "happy_meal(SBUS): Can't order irq %s to go.\n",
-			       __irq_itoa(dev->irq));
-#else
 			printk(KERN_ERR "happy_meal(SBUS): Can't order irq %d to go.\n",
 			       dev->irq);
-#endif
 
 			return -EAGAIN;
 		}
@@ -2597,14 +2568,10 @@
  */
 static struct quattro * __init quattro_sbus_find(struct sbus_dev *goal_sdev)
 {
-	struct sbus_bus *sbus;
 	struct sbus_dev *sdev;
 	struct quattro *qp;
 	int i;
 
-	if (qfe_sbus_list == NULL)
-		goto found;
-
 	for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
 		for (i = 0, sdev = qp->quattro_dev;
 		     (sdev != NULL) && (i < 4);
@@ -2613,17 +2580,7 @@
 				return qp;
 		}
 	}
-	for_each_sbus(sbus) {
-		for_each_sbusdev(sdev, sbus) {
-			if (sdev == goal_sdev)
-				goto found;
-		}
-	}
 
-	/* Cannot find quattro parent, fail. */
-	return NULL;
-
-found:
 	qp = kmalloc(sizeof(struct quattro), GFP_KERNEL);
 	if (qp != NULL) {
 		int i;
@@ -2660,6 +2617,17 @@
 		}
 	}
 }
+
+static void __devexit quattro_sbus_free_irqs(void)
+{
+	struct quattro *qp;
+
+	for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) {
+		struct sbus_dev *sdev = qp->quattro_dev;
+
+		free_irq(sdev->irqs[0], qp);
+	}
+}
 #endif /* CONFIG_SBUS */
 
 #ifdef CONFIG_PCI
@@ -2694,8 +2662,9 @@
 #endif /* CONFIG_PCI */
 
 #ifdef CONFIG_SBUS
-static int __init happy_meal_sbus_init(struct sbus_dev *sdev, int is_qfe)
+static int __init happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe)
 {
+	struct device_node *dp = sdev->ofdev.node;
 	struct quattro *qp = NULL;
 	struct happy_meal *hp;
 	struct net_device *dev;
@@ -2718,6 +2687,7 @@
 	if (!dev)
 		goto err_out;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
 
 	if (hme_version_printed++ == 0)
 		printk(KERN_INFO "%s", version);
@@ -2733,13 +2703,16 @@
 		for (i = 0; i < 6; i++)
 			dev->dev_addr[i] = macaddr[i];
 		macaddr[5]++;
-	} else if (qfe_slot != -1 &&
-		   prom_getproplen(sdev->prom_node,
-				   "local-mac-address") == 6) {
-		prom_getproperty(sdev->prom_node, "local-mac-address",
-				 dev->dev_addr, 6);
 	} else {
-		memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
+		unsigned char *addr;
+		int len;
+
+		addr = of_get_property(dp, "local-mac-address", &len);
+
+		if (qfe_slot != -1 && addr && len == 6)
+			memcpy(dev->dev_addr, addr, 6);
+		else
+			memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
 	}
 
 	hp = dev->priv;
@@ -2750,9 +2723,8 @@
 
 	err = -ENODEV;
 	if (sdev->num_registers != 5) {
-		printk(KERN_ERR "happymeal: Device does not have 5 regs, it has %d.\n",
+		printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n",
 		       sdev->num_registers);
-		printk(KERN_ERR "happymeal: Would you like that for here or to go?\n");
 		goto err_out_free_netdev;
 	}
 
@@ -2766,39 +2738,39 @@
 	hp->gregs = sbus_ioremap(&sdev->resource[0], 0,
 				 GREG_REG_SIZE, "HME Global Regs");
 	if (!hp->gregs) {
-		printk(KERN_ERR "happymeal: Cannot map Happy Meal global registers.\n");
+		printk(KERN_ERR "happymeal: Cannot map global registers.\n");
 		goto err_out_free_netdev;
 	}
 
 	hp->etxregs = sbus_ioremap(&sdev->resource[1], 0,
 				   ETX_REG_SIZE, "HME TX Regs");
 	if (!hp->etxregs) {
-		printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Transmit registers.\n");
+		printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n");
 		goto err_out_iounmap;
 	}
 
 	hp->erxregs = sbus_ioremap(&sdev->resource[2], 0,
 				   ERX_REG_SIZE, "HME RX Regs");
 	if (!hp->erxregs) {
-		printk(KERN_ERR "happymeal: Cannot map Happy Meal MAC Receive registers.\n");
+		printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n");
 		goto err_out_iounmap;
 	}
 
 	hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0,
 				      BMAC_REG_SIZE, "HME BIGMAC Regs");
 	if (!hp->bigmacregs) {
-		printk(KERN_ERR "happymeal: Cannot map Happy Meal BIGMAC registers.\n");
+		printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n");
 		goto err_out_iounmap;
 	}
 
 	hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0,
 				   TCVR_REG_SIZE, "HME Tranceiver Regs");
 	if (!hp->tcvregs) {
-		printk(KERN_ERR "happymeal: Cannot map Happy Meal Tranceiver registers.\n");
+		printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n");
 		goto err_out_iounmap;
 	}
 
-	hp->hm_revision = prom_getintdefault(sdev->prom_node, "hm-rev", 0xff);
+	hp->hm_revision = of_getintprop_default(dp, "hm-rev", 0xff);
 	if (hp->hm_revision == 0xff)
 		hp->hm_revision = 0xa0;
 
@@ -2812,8 +2784,8 @@
 		hp->happy_flags |= HFLAG_QUATTRO;
 
 	/* Get the supported DVMA burst sizes from our Happy SBUS. */
-	hp->happy_bursts = prom_getintdefault(sdev->bus->prom_node,
-					      "burst-sizes", 0x00);
+	hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node,
+						 "burst-sizes", 0x00);
 
 	hp->happy_block = sbus_alloc_consistent(hp->happy_dev,
 						PAGE_SIZE,
@@ -2876,6 +2848,8 @@
 		goto err_out_free_consistent;
 	}
 
+	dev_set_drvdata(&sdev->ofdev.dev, hp);
+
 	if (qfe_slot != -1)
 		printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ",
 		       dev->name, qfe_slot);
@@ -2888,12 +2862,6 @@
 		       dev->dev_addr[i], i == 5 ? ' ' : ':');
 	printk("\n");
 
-	/* We are home free at this point, link us in to the happy
-	 * device list.
-	 */
-	hp->next_module = root_happy_dev;
-	root_happy_dev = hp;
-
 	return 0;
 
 err_out_free_consistent:
@@ -2923,7 +2891,7 @@
 #endif
 
 #ifdef CONFIG_PCI
-#ifndef __sparc__
+#ifndef CONFIG_SPARC
 static int is_quattro_p(struct pci_dev *pdev)
 {
 	struct pci_dev *busdev = pdev->bus->self;
@@ -3011,14 +2979,14 @@
 	get_random_bytes(&dev_addr[3], 3);
 	return;
 }
-#endif /* !(__sparc__) */
+#endif /* !(CONFIG_SPARC) */
 
-static int __init happy_meal_pci_init(struct pci_dev *pdev)
+static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
+					  const struct pci_device_id *ent)
 {
 	struct quattro *qp = NULL;
-#ifdef __sparc__
+#ifdef CONFIG_SPARC
 	struct pcidev_cookie *pcp;
-	int node;
 #endif
 	struct happy_meal *hp;
 	struct net_device *dev;
@@ -3029,15 +2997,14 @@
 	int err;
 
 	/* Now make sure pci_dev cookie is there. */
-#ifdef __sparc__
+#ifdef CONFIG_SPARC
 	pcp = pdev->sysdata;
-	if (pcp == NULL || pcp->prom_node == -1) {
+	if (pcp == NULL) {
 		printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n");
 		return -ENODEV;
 	}
-	node = pcp->prom_node;
 	
-	prom_getstring(node, "name", prom_name, sizeof(prom_name));
+	strcpy(prom_name, pcp->prom_node->name);
 #else
 	if (is_quattro_p(pdev))
 		strcpy(prom_name, "SUNW,qfe");
@@ -3108,11 +3075,15 @@
 			dev->dev_addr[i] = macaddr[i];
 		macaddr[5]++;
 	} else {
-#ifdef __sparc__
+#ifdef CONFIG_SPARC
+		unsigned char *addr;
+		int len;
+
 		if (qfe_slot != -1 &&
-		    prom_getproplen(node, "local-mac-address") == 6) {
-			prom_getproperty(node, "local-mac-address",
-					 dev->dev_addr, 6);
+		    (addr = of_get_property(pcp->prom_node,
+					    "local-mac-address", &len)) != NULL
+		    && len == 6) {
+			memcpy(dev->dev_addr, addr, 6);
 		} else {
 			memcpy(dev->dev_addr, idprom->id_ethaddr, 6);
 		}
@@ -3128,8 +3099,8 @@
 	hp->bigmacregs = (hpreg_base + 0x6000UL);
 	hp->tcvregs    = (hpreg_base + 0x7000UL);
 
-#ifdef __sparc__
-	hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff);
+#ifdef CONFIG_SPARC
+	hp->hm_revision = of_getintprop_default(pcp->prom_node, "hm-rev", 0xff);
 	if (hp->hm_revision == 0xff) {
 		unsigned char prev;
 
@@ -3153,7 +3124,7 @@
 	/* And of course, indicate this is PCI. */
 	hp->happy_flags |= HFLAG_PCI;
 
-#ifdef __sparc__
+#ifdef CONFIG_SPARC
 	/* Assume PCI happy meals can handle all burst sizes. */
 	hp->happy_bursts = DMA_BURSTBITS;
 #endif
@@ -3216,6 +3187,8 @@
 		goto err_out_iounmap;
 	}
 
+	dev_set_drvdata(&pdev->dev, hp);
+
 	if (!qfe_slot) {
 		struct pci_dev *qpdev = qp->quattro_dev;
 
@@ -3245,12 +3218,6 @@
 
 	printk("\n");
 
-	/* We are home free at this point, link us in to the happy
-	 * device list.
-	 */
-	hp->next_module = root_happy_dev;
-	root_happy_dev = hp;
-
 	return 0;
 
 err_out_iounmap:
@@ -3268,146 +3235,54 @@
 err_out:
 	return err;
 }
-#endif
 
-#ifdef CONFIG_SBUS
-static int __init happy_meal_sbus_probe(void)
+static void __devexit happy_meal_pci_remove(struct pci_dev *pdev)
 {
-	struct sbus_bus *sbus;
-	struct sbus_dev *sdev;
-	int cards = 0;
-	char model[128];
+	struct happy_meal *hp = dev_get_drvdata(&pdev->dev);
+	struct net_device *net_dev = hp->dev;
 
-	for_each_sbus(sbus) {
-		for_each_sbusdev(sdev, sbus) {
-			char *name = sdev->prom_name;
+	unregister_netdev(net_dev);
 
-			if (!strcmp(name, "SUNW,hme")) {
-				cards++;
-				prom_getstring(sdev->prom_node, "model",
-					       model, sizeof(model));
-				if (!strcmp(model, "SUNW,sbus-qfe"))
-					happy_meal_sbus_init(sdev, 1);
-				else
-					happy_meal_sbus_init(sdev, 0);
-			} else if (!strcmp(name, "qfe") ||
-				   !strcmp(name, "SUNW,qfe")) {
-				cards++;
-				happy_meal_sbus_init(sdev, 1);
-			}
-		}
-	}
-	if (cards != 0)
-		quattro_sbus_register_irqs();
-	return cards;
-}
-#endif
+	pci_free_consistent(hp->happy_dev,
+			    PAGE_SIZE,
+			    hp->happy_block,
+			    hp->hblock_dvma);
+	iounmap(hp->gregs);
+	pci_release_regions(hp->happy_dev);
 
-#ifdef CONFIG_PCI
-static int __init happy_meal_pci_probe(void)
-{
-	struct pci_dev *pdev = NULL;
-	int cards = 0;
+	free_netdev(net_dev);
 
-	while ((pdev = pci_find_device(PCI_VENDOR_ID_SUN,
-				       PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) {
-		if (pci_enable_device(pdev))
-			continue;
-		pci_set_master(pdev);
-		cards++;
-		happy_meal_pci_init(pdev);
-	}
-	return cards;
-}
-#endif
-
-static int __init happy_meal_probe(void)
-{
-	static int called = 0;
-	int cards;
-
-	root_happy_dev = NULL;
-
-	if (called)
-		return -ENODEV;
-	called++;
-
-	cards = 0;
-#ifdef CONFIG_SBUS
-	cards += happy_meal_sbus_probe();
-#endif
-#ifdef CONFIG_PCI
-	cards += happy_meal_pci_probe();
-#endif
-	if (!cards)
-		return -ENODEV;
-	return 0;
+	dev_set_drvdata(&pdev->dev, NULL);
 }
 
+static struct pci_device_id happymeal_pci_ids[] = {
+	{
+	  .vendor	= PCI_VENDOR_ID_SUN,
+	  .device	= PCI_DEVICE_ID_SUN_HAPPYMEAL,
+	  .subvendor	= PCI_ANY_ID,
+	  .subdevice	= PCI_ANY_ID,
+	},
+	{ }			/* Terminating entry */
+};
 
-static void __exit happy_meal_cleanup_module(void)
+MODULE_DEVICE_TABLE(pci, happymeal_pci_ids);
+
+static struct pci_driver hme_pci_driver = {
+	.name		= "hme",
+	.id_table	= happymeal_pci_ids,
+	.probe		= happy_meal_pci_probe,
+	.remove		= __devexit_p(happy_meal_pci_remove),
+};
+
+static int __init happy_meal_pci_init(void)
 {
-#ifdef CONFIG_SBUS
-	struct quattro *last_seen_qfe = NULL;
-#endif
+	return pci_module_init(&hme_pci_driver);
+}
 
-	while (root_happy_dev) {
-		struct happy_meal *hp = root_happy_dev;
-		struct happy_meal *next = root_happy_dev->next_module;
-		struct net_device *dev = hp->dev;
+static void happy_meal_pci_exit(void)
+{
+	pci_unregister_driver(&hme_pci_driver);
 
-		/* Unregister netdev before unmapping registers as this
-		 * call can end up trying to access those registers.
-		 */
-		unregister_netdev(dev);
-
-#ifdef CONFIG_SBUS
-		if (!(hp->happy_flags & HFLAG_PCI)) {
-			if (hp->happy_flags & HFLAG_QUATTRO) {
-				if (hp->qfe_parent != last_seen_qfe) {
-					free_irq(dev->irq, hp->qfe_parent);
-					last_seen_qfe = hp->qfe_parent;
-				}
-			}
-
-			sbus_iounmap(hp->gregs, GREG_REG_SIZE);
-			sbus_iounmap(hp->etxregs, ETX_REG_SIZE);
-			sbus_iounmap(hp->erxregs, ERX_REG_SIZE);
-			sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE);
-			sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE);
-			sbus_free_consistent(hp->happy_dev,
-					     PAGE_SIZE,
-					     hp->happy_block,
-					     hp->hblock_dvma);
-		}
-#endif
-#ifdef CONFIG_PCI
-		if ((hp->happy_flags & HFLAG_PCI)) {
-			pci_free_consistent(hp->happy_dev,
-					    PAGE_SIZE,
-					    hp->happy_block,
-					    hp->hblock_dvma);
-			iounmap(hp->gregs);
-			pci_release_regions(hp->happy_dev);
-		}
-#endif
-		free_netdev(dev);
-
-		root_happy_dev = next;
-	}
-
-	/* Now cleanup the quattro lists. */
-#ifdef CONFIG_SBUS
-	while (qfe_sbus_list) {
-		struct quattro *qfe = qfe_sbus_list;
-		struct quattro *next = qfe->next;
-
-		kfree(qfe);
-
-		qfe_sbus_list = next;
-	}
-#endif
-#ifdef CONFIG_PCI
 	while (qfe_pci_list) {
 		struct quattro *qfe = qfe_pci_list;
 		struct quattro *next = qfe->next;
@@ -3416,8 +3291,131 @@
 
 		qfe_pci_list = next;
 	}
+}
+
+#endif
+
+#ifdef CONFIG_SBUS
+static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+	struct device_node *dp = dev->node;
+	char *model = of_get_property(dp, "model", NULL);
+	int is_qfe = (match->data != NULL);
+
+	if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe"))
+		is_qfe = 1;
+
+	return happy_meal_sbus_probe_one(sdev, is_qfe);
+}
+
+static int __devexit hme_sbus_remove(struct of_device *dev)
+{
+	struct happy_meal *hp = dev_get_drvdata(&dev->dev);
+	struct net_device *net_dev = hp->dev;
+
+	unregister_netdevice(net_dev);
+
+	/* XXX qfe parent interrupt... */
+
+	sbus_iounmap(hp->gregs, GREG_REG_SIZE);
+	sbus_iounmap(hp->etxregs, ETX_REG_SIZE);
+	sbus_iounmap(hp->erxregs, ERX_REG_SIZE);
+	sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE);
+	sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE);
+	sbus_free_consistent(hp->happy_dev,
+			     PAGE_SIZE,
+			     hp->happy_block,
+			     hp->hblock_dvma);
+
+	free_netdev(net_dev);
+
+	dev_set_drvdata(&dev->dev, NULL);
+
+	return 0;
+}
+
+static struct of_device_id hme_sbus_match[] = {
+	{
+		.name = "SUNW,hme",
+	},
+	{
+		.name = "SUNW,qfe",
+		.data = (void *) 1,
+	},
+	{
+		.name = "qfe",
+		.data = (void *) 1,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, hme_sbus_match);
+
+static struct of_platform_driver hme_sbus_driver = {
+	.name		= "hme",
+	.match_table	= hme_sbus_match,
+	.probe		= hme_sbus_probe,
+	.remove		= __devexit_p(hme_sbus_remove),
+};
+
+static int __init happy_meal_sbus_init(void)
+{
+	int err;
+
+	err = of_register_driver(&hme_sbus_driver, &sbus_bus_type);
+	if (!err)
+		quattro_sbus_register_irqs();
+
+	return err;
+}
+
+static void happy_meal_sbus_exit(void)
+{
+	of_unregister_driver(&hme_sbus_driver);
+	quattro_sbus_free_irqs();
+
+	while (qfe_sbus_list) {
+		struct quattro *qfe = qfe_sbus_list;
+		struct quattro *next = qfe->next;
+
+		kfree(qfe);
+
+		qfe_sbus_list = next;
+	}
+}
+#endif
+
+static int __init happy_meal_probe(void)
+{
+	int err = 0;
+
+#ifdef CONFIG_SBUS
+	err = happy_meal_sbus_init();
+#endif
+#ifdef CONFIG_PCI
+	if (!err) {
+		err = happy_meal_pci_init();
+#ifdef CONFIG_SBUS
+		if (err)
+			happy_meal_sbus_exit();
+#endif
+	}
+#endif
+
+	return err;
+}
+
+
+static void __exit happy_meal_exit(void)
+{
+#ifdef CONFIG_SBUS
+	happy_meal_sbus_exit();
+#endif
+#ifdef CONFIG_PCI
+	happy_meal_pci_exit();
 #endif
 }
 
 module_init(happy_meal_probe);
-module_exit(happy_meal_cleanup_module);
+module_exit(happy_meal_exit);
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h
index 34e9f95..9b7ccae 100644
--- a/drivers/net/sunhme.h
+++ b/drivers/net/sunhme.h
@@ -461,7 +461,6 @@
 	struct net_device	 *dev;		/* Backpointer                       */
 	struct quattro		 *qfe_parent;	/* For Quattro cards                 */
 	int			  qfe_ent;	/* Which instance on quattro         */
-	struct happy_meal         *next_module;
 };
 
 /* Here are the happy flags. */
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index b7d87d4..2c239ab 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -266,7 +266,6 @@
 	char	       	       *name;
 	dma_addr_t		init_block_dvma;
 	struct net_device      *dev;		  /* Backpointer	*/
-	struct lance_private   *next_module;
 	struct sbus_dev	       *sdev;
 	struct timer_list       multicast_timer;
 };
@@ -298,8 +297,6 @@
 
 #define LANCE_ADDR(x) ((long)(x) & ~0xff000000)
 
-static struct lance_private *root_lance_dev;
-
 /* Load the CSR registers */
 static void load_csrs(struct lance_private *lp)
 {
@@ -936,7 +933,7 @@
 
 	if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ,
 			lancestr, (void *) dev)) {
-		printk(KERN_ERR "Lance: Can't get irq %s\n", __irq_itoa(dev->irq));
+		printk(KERN_ERR "Lance: Can't get irq %d\n", dev->irq);
 		return -EAGAIN;
 	}
 
@@ -1327,9 +1324,9 @@
 	.get_link		= sparc_lance_get_link,
 };
 
-static int __init sparc_lance_init(struct sbus_dev *sdev,
-				   struct sbus_dma *ledma,
-				   struct sbus_dev *lebuffer)
+static int __init sparc_lance_probe_one(struct sbus_dev *sdev,
+					struct sbus_dma *ledma,
+					struct sbus_dev *lebuffer)
 {
 	static unsigned version_printed;
 	struct net_device *dev;
@@ -1473,6 +1470,7 @@
 
 	lp->dev = dev;
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
 	dev->open = &lance_open;
 	dev->stop = &lance_close;
 	dev->hard_start_xmit = &lance_start_xmit;
@@ -1500,8 +1498,7 @@
 		goto fail;
 	}
 
-	lp->next_module = root_lance_dev;
-	root_lance_dev = lp;
+	dev_set_drvdata(&sdev->ofdev.dev, lp);
 
 	printk(KERN_INFO "%s: LANCE ", dev->name);
 
@@ -1536,88 +1533,112 @@
 #include <asm/machines.h>
 
 /* Find all the lance cards on the system and initialize them */
-static int __init sparc_lance_probe(void)
+static struct sbus_dev sun4_sdev;
+static int __init sparc_lance_init(void)
 {
-	static struct sbus_dev sdev;
-	static int called;
-
-	root_lance_dev = NULL;
-
-	if (called)
-		return -ENODEV;
-	called++;
-
 	if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) ||
 	    (idprom->id_machtype == (SM_SUN4|SM_4_470))) {
-		memset(&sdev, 0, sizeof(sdev));
-		sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
-		sdev.irqs[0] = 6;
-		return sparc_lance_init(&sdev, NULL, NULL);
+		memset(&sun4_sdev, 0, sizeof(sdev));
+		sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr;
+		sun4_sdev.irqs[0] = 6;
+		return sparc_lance_probe_one(&sun4_sdev, NULL, NULL);
 	}
 	return -ENODEV;
 }
 
+static int __exit sunlance_sun4_remove(void)
+{
+	struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev);
+	struct net_device *net_dev = lp->dev;
+
+	unregister_netdevice(net_dev);
+
+	lance_free_hwresources(root_lance_dev);
+
+	free_netdev(net_dev);
+
+	dev_set_drvdata(&sun4_sdev->dev, NULL);
+
+	return 0;
+}
+
 #else /* !CONFIG_SUN4 */
 
-/* Find all the lance cards on the system and initialize them */
-static int __init sparc_lance_probe(void)
+static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match)
 {
-	struct sbus_bus *bus;
-	struct sbus_dev *sdev = NULL;
-	struct sbus_dma *ledma = NULL;
-	static int called;
-	int cards = 0, v;
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+	struct device_node *dp = dev->node;
+	int err;
 
-	root_lance_dev = NULL;
+	if (!strcmp(dp->name, "le")) {
+		err = sparc_lance_probe_one(sdev, NULL, NULL);
+	} else if (!strcmp(dp->name, "ledma")) {
+		struct sbus_dma *ledma = find_ledma(sdev);
 
-	if (called)
-		return -ENODEV;
-	called++;
+		err = sparc_lance_probe_one(sdev->child, ledma, NULL);
+	} else {
+		BUG_ON(strcmp(dp->name, "lebuffer"));
 
-	for_each_sbus (bus) {
-		for_each_sbusdev (sdev, bus) {
-			if (strcmp(sdev->prom_name, "le") == 0) {
-				cards++;
-				if ((v = sparc_lance_init(sdev, NULL, NULL)))
-					return v;
-				continue;
-			}
-			if (strcmp(sdev->prom_name, "ledma") == 0) {
-				cards++;
-				ledma = find_ledma(sdev);
-				if ((v = sparc_lance_init(sdev->child,
-							  ledma, NULL)))
-					return v;
-				continue;
-			}
-			if (strcmp(sdev->prom_name, "lebuffer") == 0){
-				cards++;
-				if ((v = sparc_lance_init(sdev->child,
-							  NULL, sdev)))
-					return v;
-				continue;
-			}
-		} /* for each sbusdev */
-	} /* for each sbus */
-	if (!cards)
-		return -ENODEV;
+		err = sparc_lance_probe_one(sdev->child, NULL, sdev);
+	}
+
+	return err;
+}
+
+static int __devexit sunlance_sbus_remove(struct of_device *dev)
+{
+	struct lance_private *lp = dev_get_drvdata(&dev->dev);
+	struct net_device *net_dev = lp->dev;
+
+	unregister_netdevice(net_dev);
+
+	lance_free_hwresources(lp);
+
+	free_netdev(net_dev);
+
+	dev_set_drvdata(&dev->dev, NULL);
+
 	return 0;
 }
+
+static struct of_device_id sunlance_sbus_match[] = {
+	{
+		.name = "le",
+	},
+	{
+		.name = "ledma",
+	},
+	{
+		.name = "lebuffer",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, sunlance_sbus_match);
+
+static struct of_platform_driver sunlance_sbus_driver = {
+	.name		= "sunlance",
+	.match_table	= sunlance_sbus_match,
+	.probe		= sunlance_sbus_probe,
+	.remove		= __devexit_p(sunlance_sbus_remove),
+};
+
+
+/* Find all the lance cards on the system and initialize them */
+static int __init sparc_lance_init(void)
+{
+	return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type);
+}
 #endif /* !CONFIG_SUN4 */
 
-static void __exit sparc_lance_cleanup(void)
+static void __exit sparc_lance_exit(void)
 {
-	struct lance_private *lp;
-
-	while (root_lance_dev) {
-		lp = root_lance_dev->next_module;
-
-		unregister_netdev(root_lance_dev->dev);
-		lance_free_hwresources(root_lance_dev);
-		free_netdev(root_lance_dev->dev);
-		root_lance_dev = lp;
-	}
+#ifdef CONFIG_SUN4
+	sunlance_sun4_remove();
+#else
+	of_unregister_driver(&sunlance_sbus_driver);
+#endif
 }
 
-module_init(sparc_lance_probe);
-module_exit(sparc_lance_cleanup);
+module_init(sparc_lance_init);
+module_exit(sparc_lance_exit);
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 1f2323b..9da6d5b 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -1,10 +1,9 @@
-/* $Id: sunqe.c,v 1.55 2002/01/15 06:48:55 davem Exp $
- * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
+/* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
  *          Once again I am out to prove that every ethernet
  *          controller out there can be most efficiently programmed
  *          if you make it look like a LANCE.
  *
- * Copyright (C) 1996, 1999, 2003 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1999, 2003, 2006 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/module.h>
@@ -41,9 +40,9 @@
 #include "sunqe.h"
 
 #define DRV_NAME	"sunqe"
-#define DRV_VERSION	"3.0"
-#define DRV_RELDATE	"8/24/03"
-#define DRV_AUTHOR	"David S. Miller (davem@redhat.com)"
+#define DRV_VERSION	"4.0"
+#define DRV_RELDATE	"June 23, 2006"
+#define DRV_AUTHOR	"David S. Miller (davem@davemloft.net)"
 
 static char version[] =
 	DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n";
@@ -755,298 +754,269 @@
 		    qecp->gregs + GLOB_RSIZE);
 }
 
-/* Four QE's per QEC card. */
-static int __init qec_ether_init(struct net_device *dev, struct sbus_dev *sdev)
+static u8 __init qec_get_burst(struct device_node *dp)
 {
-	static unsigned version_printed;
-	struct net_device *qe_devs[4];
-	struct sunqe *qeps[4];
-	struct sbus_dev *qesdevs[4];
-	struct sbus_dev *child;
-	struct sunqec *qecp = NULL;
 	u8 bsizes, bsizes_more;
-	int i, j, res = -ENOMEM;
 
-	for (i = 0; i < 4; i++) {
-		qe_devs[i] = alloc_etherdev(sizeof(struct sunqe));
-		if (!qe_devs[i])
-			goto out;
-	}
-
-	if (version_printed++ == 0)
-		printk(KERN_INFO "%s", version);
-
-	for (i = 0; i < 4; i++) {
-		qeps[i] = (struct sunqe *) qe_devs[i]->priv;
-		for (j = 0; j < 6; j++)
-			qe_devs[i]->dev_addr[j] = idprom->id_ethaddr[j];
-		qeps[i]->channel = i;
-		spin_lock_init(&qeps[i]->lock);
-	}
-
-	qecp = kmalloc(sizeof(struct sunqec), GFP_KERNEL);
-	if (qecp == NULL)
-		goto out1;
-	qecp->qec_sdev = sdev;
-
-	for (i = 0; i < 4; i++) {
-		qecp->qes[i] = qeps[i];
-		qeps[i]->dev = qe_devs[i];
-		qeps[i]->parent = qecp;
-	}
-
-	res = -ENODEV;
-
-	for (i = 0, child = sdev->child; i < 4; i++, child = child->next) {
-		/* Link in channel */
-		j = prom_getintdefault(child->prom_node, "channel#", -1);
-		if (j == -1)
-			goto out2;
-		qesdevs[j] = child;
-	}
-
-	for (i = 0; i < 4; i++)
-		qeps[i]->qe_sdev = qesdevs[i];
-
-	/* Now map in the registers, QEC globals first. */
-	qecp->gregs = sbus_ioremap(&sdev->resource[0], 0,
-				   GLOB_REG_SIZE, "QEC Global Registers");
-	if (!qecp->gregs) {
-		printk(KERN_ERR "QuadEther: Cannot map QEC global registers.\n");
-		goto out2;
-	}
-
-	/* Make sure the QEC is in MACE mode. */
-	if ((sbus_readl(qecp->gregs + GLOB_CTRL) & 0xf0000000) != GLOB_CTRL_MMODE) {
-		printk(KERN_ERR "QuadEther: AIEEE, QEC is not in MACE mode!\n");
-		goto out3;
-	}
-
-	/* Reset the QEC. */
-	if (qec_global_reset(qecp->gregs))
-		goto out3;
-
-	/* Find and set the burst sizes for the QEC, since it does
-	 * the actual dma for all 4 channels.
+	/* Find and set the burst sizes for the QEC, since it
+	 * does the actual dma for all 4 channels.
 	 */
-	bsizes = prom_getintdefault(sdev->prom_node, "burst-sizes", 0xff);
+	bsizes = of_getintprop_default(dp, "burst-sizes", 0xff);
 	bsizes &= 0xff;
-	bsizes_more = prom_getintdefault(sdev->bus->prom_node, "burst-sizes", 0xff);
+	bsizes_more = of_getintprop_default(dp->parent, "burst-sizes", 0xff);
 
 	if (bsizes_more != 0xff)
 		bsizes &= bsizes_more;
 	if (bsizes == 0xff || (bsizes & DMA_BURST16) == 0 ||
-	   (bsizes & DMA_BURST32)==0)
+	    (bsizes & DMA_BURST32)==0)
 		bsizes = (DMA_BURST32 - 1);
 
-	qecp->qec_bursts = bsizes;
+	return bsizes;
+}
 
-	/* Perform one time QEC initialization, we never touch the QEC
-	 * globals again after this.
-	 */
-	qec_init_once(qecp, sdev);
+static struct sunqec * __init get_qec(struct sbus_dev *child_sdev)
+{
+	struct sbus_dev *qec_sdev = child_sdev->parent;
+	struct sunqec *qecp;
 
-	for (i = 0; i < 4; i++) {
-		struct sunqe *qe = qeps[i];
-		/* Map in QEC per-channel control registers. */
-		qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0,
-				       CREG_REG_SIZE, "QEC Channel Registers");
-		if (!qe->qcregs) {
-			printk(KERN_ERR "QuadEther: Cannot map QE %d's channel registers.\n", i);
-			goto out4;
+	for (qecp = root_qec_dev; qecp; qecp = qecp->next_module) {
+		if (qecp->qec_sdev == qec_sdev)
+			break;
+	}
+	if (!qecp) {
+		qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL);
+		if (qecp) {
+			u32 ctrl;
+
+			qecp->qec_sdev = qec_sdev;
+			qecp->gregs = sbus_ioremap(&qec_sdev->resource[0], 0,
+						   GLOB_REG_SIZE,
+						   "QEC Global Registers");
+			if (!qecp->gregs)
+				goto fail;
+
+			/* Make sure the QEC is in MACE mode. */
+			ctrl = sbus_readl(qecp->gregs + GLOB_CTRL);
+			ctrl &= 0xf0000000;
+			if (ctrl != GLOB_CTRL_MMODE) {
+				printk(KERN_ERR "qec: Not in MACE mode!\n");
+				goto fail;
+			}
+
+			if (qec_global_reset(qecp->gregs))
+				goto fail;
+
+			qecp->qec_bursts = qec_get_burst(qec_sdev->ofdev.node);
+
+			qec_init_once(qecp, qec_sdev);
+
+			if (request_irq(qec_sdev->irqs[0], &qec_interrupt,
+					SA_SHIRQ, "qec", (void *) qecp)) {
+				printk(KERN_ERR "qec: Can't register irq.\n");
+				goto fail;
+			}
+
+			qecp->next_module = root_qec_dev;
+			root_qec_dev = qecp;
 		}
+	}
 
-		/* Map in per-channel AMD MACE registers. */
-		qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0,
-				      MREGS_REG_SIZE, "QE MACE Registers");
-		if (!qe->mregs) {
-			printk(KERN_ERR "QuadEther: Cannot map QE %d's MACE registers.\n", i);
-			goto out4;
+	return qecp;
+
+fail:
+	if (qecp->gregs)
+		sbus_iounmap(qecp->gregs, GLOB_REG_SIZE);
+	kfree(qecp);
+	return NULL;
+}
+
+static int __init qec_ether_init(struct sbus_dev *sdev)
+{
+	static unsigned version_printed;
+	struct net_device *dev;
+	struct sunqe *qe;
+	struct sunqec *qecp;
+	int i, res;
+
+	if (version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+
+	dev = alloc_etherdev(sizeof(struct sunqe));
+	if (!dev)
+		return -ENOMEM;
+
+	qe = netdev_priv(dev);
+
+	i = of_getintprop_default(sdev->ofdev.node, "channel#", -1);
+	if (i == -1) {
+		struct sbus_dev *td = sdev->parent->child;
+		i = 0;
+		while (td != sdev) {
+			td = td->next;
+			i++;
 		}
+	}
+	qe->channel = i;
+	spin_lock_init(&qe->lock);
+	
+	res = -ENODEV;
+	qecp = get_qec(sdev);
+	if (!qecp)
+		goto fail;
 
-		qe->qe_block = sbus_alloc_consistent(qe->qe_sdev,
-						  PAGE_SIZE,
-						  &qe->qblock_dvma);
-		qe->buffers = sbus_alloc_consistent(qe->qe_sdev,
-						 sizeof(struct sunqe_buffers),
-						 &qe->buffers_dvma);
-		if (qe->qe_block == NULL || qe->qblock_dvma == 0 ||
-		    qe->buffers == NULL || qe->buffers_dvma == 0) {
-			goto out4;
-		}
+	qecp->qes[qe->channel] = qe;
+	qe->dev = dev;
+	qe->parent = qecp;
+	qe->qe_sdev = sdev;
 
-		/* Stop this QE. */
-		qe_stop(qe);
+	res = -ENOMEM;
+	qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0,
+				  CREG_REG_SIZE, "QEC Channel Registers");
+	if (!qe->qcregs) {
+		printk(KERN_ERR "qe: Cannot map channel registers.\n");
+		goto fail;
 	}
 
-	for (i = 0; i < 4; i++) {
-		SET_MODULE_OWNER(qe_devs[i]);
-		qe_devs[i]->open = qe_open;
-		qe_devs[i]->stop = qe_close;
-		qe_devs[i]->hard_start_xmit = qe_start_xmit;
-		qe_devs[i]->get_stats = qe_get_stats;
-		qe_devs[i]->set_multicast_list = qe_set_multicast;
-		qe_devs[i]->tx_timeout = qe_tx_timeout;
-		qe_devs[i]->watchdog_timeo = 5*HZ;
-		qe_devs[i]->irq = sdev->irqs[0];
-		qe_devs[i]->dma = 0;
-		qe_devs[i]->ethtool_ops = &qe_ethtool_ops;
+	qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0,
+				 MREGS_REG_SIZE, "QE MACE Registers");
+	if (!qe->mregs) {
+		printk(KERN_ERR "qe: Cannot map MACE registers.\n");
+		goto fail;
 	}
 
-	/* QEC receives interrupts from each QE, then it sends the actual
-	 * IRQ to the cpu itself.  Since QEC is the single point of
-	 * interrupt for all QE channels we register the IRQ handler
-	 * for it now.
-	 */
-	if (request_irq(sdev->irqs[0], &qec_interrupt,
-			SA_SHIRQ, "QuadEther", (void *) qecp)) {
-		printk(KERN_ERR "QuadEther: Can't register QEC master irq handler.\n");
-		res = -EAGAIN;
-		goto out4;
-	}
+	qe->qe_block = sbus_alloc_consistent(qe->qe_sdev,
+					     PAGE_SIZE,
+					     &qe->qblock_dvma);
+	qe->buffers = sbus_alloc_consistent(qe->qe_sdev,
+					    sizeof(struct sunqe_buffers),
+					    &qe->buffers_dvma);
+	if (qe->qe_block == NULL || qe->qblock_dvma == 0 ||
+	    qe->buffers == NULL || qe->buffers_dvma == 0)
+		goto fail;
 
-	for (i = 0; i < 4; i++) {
-		if (register_netdev(qe_devs[i]) != 0)
-			goto out5;
-	}
+	/* Stop this QE. */
+	qe_stop(qe);
 
-	/* Report the QE channels. */
-	for (i = 0; i < 4; i++) {
-		printk(KERN_INFO "%s: QuadEthernet channel[%d] ", qe_devs[i]->name, i);
-		for (j = 0; j < 6; j++)
-			printk ("%2.2x%c",
-				qe_devs[i]->dev_addr[j],
-				j == 5 ? ' ': ':');
-		printk("\n");
-	}
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &sdev->ofdev.dev);
 
-	/* We are home free at this point, link the qe's into
-	 * the master list for later driver exit.
-	 */
-	qecp->next_module = root_qec_dev;
-	root_qec_dev = qecp;
+	dev->open = qe_open;
+	dev->stop = qe_close;
+	dev->hard_start_xmit = qe_start_xmit;
+	dev->get_stats = qe_get_stats;
+	dev->set_multicast_list = qe_set_multicast;
+	dev->tx_timeout = qe_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
+	dev->irq = sdev->irqs[0];
+	dev->dma = 0;
+	dev->ethtool_ops = &qe_ethtool_ops;
+
+	res = register_netdev(dev);
+	if (res)
+		goto fail;
+
+	dev_set_drvdata(&sdev->ofdev.dev, qe);
+
+	printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel);
+	for (i = 0; i < 6; i++)
+		printk ("%2.2x%c",
+			dev->dev_addr[i],
+			i == 5 ? ' ': ':');
+	printk("\n");
+
 
 	return 0;
 
-out5:
-	while (i--)
-		unregister_netdev(qe_devs[i]);
-	free_irq(sdev->irqs[0], (void *)qecp);
-out4:
-	for (i = 0; i < 4; i++) {
-		struct sunqe *qe = (struct sunqe *)qe_devs[i]->priv;
+fail:
+	if (qe->qcregs)
+		sbus_iounmap(qe->qcregs, CREG_REG_SIZE);
+	if (qe->mregs)
+		sbus_iounmap(qe->mregs, MREGS_REG_SIZE);
+	if (qe->qe_block)
+		sbus_free_consistent(qe->qe_sdev,
+				     PAGE_SIZE,
+				     qe->qe_block,
+				     qe->qblock_dvma);
+	if (qe->buffers)
+		sbus_free_consistent(qe->qe_sdev,
+				     sizeof(struct sunqe_buffers),
+				     qe->buffers,
+				     qe->buffers_dvma);
 
-		if (qe->qcregs)
-			sbus_iounmap(qe->qcregs, CREG_REG_SIZE);
-		if (qe->mregs)
-			sbus_iounmap(qe->mregs, MREGS_REG_SIZE);
-		if (qe->qe_block)
-			sbus_free_consistent(qe->qe_sdev,
-					     PAGE_SIZE,
-					     qe->qe_block,
-					     qe->qblock_dvma);
-		if (qe->buffers)
-			sbus_free_consistent(qe->qe_sdev,
-					     sizeof(struct sunqe_buffers),
-					     qe->buffers,
-					     qe->buffers_dvma);
-	}
-out3:
-	sbus_iounmap(qecp->gregs, GLOB_REG_SIZE);
-out2:
-	kfree(qecp);
-out1:
-	i = 4;
-out:
-	while (i--)
-		free_netdev(qe_devs[i]);
+	free_netdev(dev);
+
 	return res;
 }
 
-static int __init qec_match(struct sbus_dev *sdev)
+static int __devinit qec_sbus_probe(struct of_device *dev, const struct of_device_id *match)
 {
-	struct sbus_dev *sibling;
-	int i;
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
 
-	if (strcmp(sdev->prom_name, "qec") != 0)
-		return 0;
-
-	/* QEC can be parent of either QuadEthernet or BigMAC
-	 * children.  Do not confuse this with qfe/SUNW,qfe
-	 * which is a quad-happymeal card and handled by
-	 * a different driver.
-	 */
-	sibling = sdev->child;
-	for (i = 0; i < 4; i++) {
-		if (sibling == NULL)
-			return 0;
-		if (strcmp(sibling->prom_name, "qe") != 0)
-			return 0;
-		sibling = sibling->next;
-	}
-	return 1;
+	return qec_ether_init(sdev);
 }
 
-static int __init qec_probe(void)
+static int __devexit qec_sbus_remove(struct of_device *dev)
 {
-	struct net_device *dev = NULL;
-	struct sbus_bus *bus;
-	struct sbus_dev *sdev = NULL;
-	static int called;
-	int cards = 0, v;
+	struct sunqe *qp = dev_get_drvdata(&dev->dev);
+	struct net_device *net_dev = qp->dev;
 
-	root_qec_dev = NULL;
+	unregister_netdevice(net_dev);
 
-	if (called)
-		return -ENODEV;
-	called++;
+	sbus_iounmap(qp->qcregs, CREG_REG_SIZE);
+	sbus_iounmap(qp->mregs, MREGS_REG_SIZE);
+	sbus_free_consistent(qp->qe_sdev,
+			     PAGE_SIZE,
+			     qp->qe_block,
+			     qp->qblock_dvma);
+	sbus_free_consistent(qp->qe_sdev,
+			     sizeof(struct sunqe_buffers),
+			     qp->buffers,
+			     qp->buffers_dvma);
 
-	for_each_sbus(bus) {
-		for_each_sbusdev(sdev, bus) {
-			if (cards)
-				dev = NULL;
+	free_netdev(net_dev);
 
-			if (qec_match(sdev)) {
-				cards++;
-				if ((v = qec_ether_init(dev, sdev)))
-					return v;
-			}
-		}
-	}
-	if (!cards)
-		return -ENODEV;
+	dev_set_drvdata(&dev->dev, NULL);
+
 	return 0;
 }
 
-static void __exit qec_cleanup(void)
+static struct of_device_id qec_sbus_match[] = {
+	{
+		.name = "qe",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, qec_sbus_match);
+
+static struct of_platform_driver qec_sbus_driver = {
+	.name		= "qec",
+	.match_table	= qec_sbus_match,
+	.probe		= qec_sbus_probe,
+	.remove		= __devexit_p(qec_sbus_remove),
+};
+
+static int __init qec_init(void)
 {
-	struct sunqec *next_qec;
-	int i;
+	return of_register_driver(&qec_sbus_driver, &sbus_bus_type);
+}
+
+static void __exit qec_exit(void)
+{
+	of_unregister_driver(&qec_sbus_driver);
 
 	while (root_qec_dev) {
-		next_qec = root_qec_dev->next_module;
+		struct sunqec *next = root_qec_dev->next_module;
 
-		/* Release all four QE channels, then the QEC itself. */
-		for (i = 0; i < 4; i++) {
-			unregister_netdev(root_qec_dev->qes[i]->dev);
-			sbus_iounmap(root_qec_dev->qes[i]->qcregs, CREG_REG_SIZE);
-			sbus_iounmap(root_qec_dev->qes[i]->mregs, MREGS_REG_SIZE);
-			sbus_free_consistent(root_qec_dev->qes[i]->qe_sdev,
-					     PAGE_SIZE,
-					     root_qec_dev->qes[i]->qe_block,
-					     root_qec_dev->qes[i]->qblock_dvma);
-			sbus_free_consistent(root_qec_dev->qes[i]->qe_sdev,
-					     sizeof(struct sunqe_buffers),
-					     root_qec_dev->qes[i]->buffers,
-					     root_qec_dev->qes[i]->buffers_dvma);
-			free_netdev(root_qec_dev->qes[i]->dev);
-		}
-		free_irq(root_qec_dev->qec_sdev->irqs[0], (void *)root_qec_dev);
+		free_irq(root_qec_dev->qec_sdev->irqs[0],
+			 (void *) root_qec_dev);
 		sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE);
+
 		kfree(root_qec_dev);
-		root_qec_dev = next_qec;
+
+		root_qec_dev = next;
 	}
 }
 
-module_init(qec_probe);
-module_exit(qec_cleanup);
+module_init(qec_init);
+module_exit(qec_exit);
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 862c226..35f9316 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -69,8 +69,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.59"
-#define DRV_MODULE_RELDATE	"June 8, 2006"
+#define DRV_MODULE_VERSION	"3.60"
+#define DRV_MODULE_RELDATE	"June 17, 2006"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -229,6 +229,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M,
@@ -2965,6 +2967,27 @@
 	return err;
 }
 
+/* This is called whenever we suspect that the system chipset is re-
+ * ordering the sequence of MMIO to the tx send mailbox. The symptom
+ * is bogus tx completions. We try to recover by setting the
+ * TG3_FLAG_MBOX_WRITE_REORDER flag and resetting the chip later
+ * in the workqueue.
+ */
+static void tg3_tx_recover(struct tg3 *tp)
+{
+	BUG_ON((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) ||
+	       tp->write32_tx_mbox == tg3_write_indirect_mbox);
+
+	printk(KERN_WARNING PFX "%s: The system may be re-ordering memory-"
+	       "mapped I/O cycles to the network device, attempting to "
+	       "recover. Please report the problem to the driver maintainer "
+	       "and include system chipset information.\n", tp->dev->name);
+
+	spin_lock(&tp->lock);
+	tp->tg3_flags |= TG3_FLAG_TX_RECOVERY_PENDING;
+	spin_unlock(&tp->lock);
+}
+
 /* Tigon3 never reports partial packet sends.  So we do not
  * need special logic to handle SKBs that have not had all
  * of their frags sent yet, like SunGEM does.
@@ -2977,9 +3000,13 @@
 	while (sw_idx != hw_idx) {
 		struct tx_ring_info *ri = &tp->tx_buffers[sw_idx];
 		struct sk_buff *skb = ri->skb;
-		int i;
+		int i, tx_bug = 0;
 
-		BUG_ON(skb == NULL);
+		if (unlikely(skb == NULL)) {
+			tg3_tx_recover(tp);
+			return;
+		}
+
 		pci_unmap_single(tp->pdev,
 				 pci_unmap_addr(ri, mapping),
 				 skb_headlen(skb),
@@ -2990,10 +3017,9 @@
 		sw_idx = NEXT_TX(sw_idx);
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			BUG_ON(sw_idx == hw_idx);
-
 			ri = &tp->tx_buffers[sw_idx];
-			BUG_ON(ri->skb != NULL);
+			if (unlikely(ri->skb != NULL || sw_idx == hw_idx))
+				tx_bug = 1;
 
 			pci_unmap_page(tp->pdev,
 				       pci_unmap_addr(ri, mapping),
@@ -3004,6 +3030,11 @@
 		}
 
 		dev_kfree_skb(skb);
+
+		if (unlikely(tx_bug)) {
+			tg3_tx_recover(tp);
+			return;
+		}
 	}
 
 	tp->tx_cons = sw_idx;
@@ -3331,6 +3362,11 @@
 	/* run TX completion thread */
 	if (sblk->idx[0].tx_consumer != tp->tx_cons) {
 		tg3_tx(tp);
+		if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) {
+			netif_rx_complete(netdev);
+			schedule_work(&tp->reset_task);
+			return 0;
+		}
 	}
 
 	/* run RX thread, within the bounds set by NAPI.
@@ -3391,12 +3427,10 @@
 	if (irq_sync)
 		tg3_irq_quiesce(tp);
 	spin_lock_bh(&tp->lock);
-	spin_lock(&tp->tx_lock);
 }
 
 static inline void tg3_full_unlock(struct tg3 *tp)
 {
-	spin_unlock(&tp->tx_lock);
 	spin_unlock_bh(&tp->lock);
 }
 
@@ -3579,6 +3613,13 @@
 	restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
 	tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
 
+	if (tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING) {
+		tp->write32_tx_mbox = tg3_write32_tx_mbox;
+		tp->write32_rx_mbox = tg3_write_flush_reg32;
+		tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
+		tp->tg3_flags &= ~TG3_FLAG_TX_RECOVERY_PENDING;
+	}
+
 	tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
 	tg3_init_hw(tp, 1);
 
@@ -3718,14 +3759,11 @@
 
 	len = skb_headlen(skb);
 
-	/* No BH disabling for tx_lock here.  We are running in BH disabled
-	 * context and TX reclaim runs via tp->poll inside of a software
+	/* We are running in BH disabled context with netif_tx_lock
+	 * and TX reclaim runs via tp->poll inside of a software
 	 * interrupt.  Furthermore, IRQ processing runs lockless so we have
 	 * no IRQ context deadlocks to worry about either.  Rejoice!
 	 */
-	if (!spin_trylock(&tp->tx_lock))
-		return NETDEV_TX_LOCKED;
-
 	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
 		if (!netif_queue_stopped(dev)) {
 			netif_stop_queue(dev);
@@ -3734,7 +3772,6 @@
 			printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
 			       "queue awake!\n", dev->name);
 		}
-		spin_unlock(&tp->tx_lock);
 		return NETDEV_TX_BUSY;
 	}
 
@@ -3743,7 +3780,7 @@
 #if TG3_TSO_SUPPORT != 0
 	mss = 0;
 	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
-	    (mss = skb_shinfo(skb)->tso_size) != 0) {
+	    (mss = skb_shinfo(skb)->gso_size) != 0) {
 		int tcp_opt_len, ip_tcp_len;
 
 		if (skb_header_cloned(skb) &&
@@ -3817,15 +3854,16 @@
 	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
 	tp->tx_prod = entry;
-	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
+	if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
+		spin_lock(&tp->tx_lock);
 		netif_stop_queue(dev);
 		if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
 			netif_wake_queue(tp->dev);
+		spin_unlock(&tp->tx_lock);
 	}
 
 out_unlock:
     	mmiowb();
-	spin_unlock(&tp->tx_lock);
 
 	dev->trans_start = jiffies;
 
@@ -3844,14 +3882,11 @@
 
 	len = skb_headlen(skb);
 
-	/* No BH disabling for tx_lock here.  We are running in BH disabled
-	 * context and TX reclaim runs via tp->poll inside of a software
+	/* We are running in BH disabled context with netif_tx_lock
+	 * and TX reclaim runs via tp->poll inside of a software
 	 * interrupt.  Furthermore, IRQ processing runs lockless so we have
 	 * no IRQ context deadlocks to worry about either.  Rejoice!
 	 */
-	if (!spin_trylock(&tp->tx_lock))
-		return NETDEV_TX_LOCKED; 
-
 	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
 		if (!netif_queue_stopped(dev)) {
 			netif_stop_queue(dev);
@@ -3860,7 +3895,6 @@
 			printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
 			       "queue awake!\n", dev->name);
 		}
-		spin_unlock(&tp->tx_lock);
 		return NETDEV_TX_BUSY;
 	}
 
@@ -3871,7 +3905,7 @@
 #if TG3_TSO_SUPPORT != 0
 	mss = 0;
 	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
-	    (mss = skb_shinfo(skb)->tso_size) != 0) {
+	    (mss = skb_shinfo(skb)->gso_size) != 0) {
 		int tcp_opt_len, ip_tcp_len;
 
 		if (skb_header_cloned(skb) &&
@@ -3998,15 +4032,16 @@
 	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
 	tp->tx_prod = entry;
-	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1)) {
+	if (unlikely(TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))) {
+		spin_lock(&tp->tx_lock);
 		netif_stop_queue(dev);
 		if (TX_BUFFS_AVAIL(tp) > TG3_TX_WAKEUP_THRESH)
 			netif_wake_queue(tp->dev);
+		spin_unlock(&tp->tx_lock);
 	}
 
 out_unlock:
     	mmiowb();
-	spin_unlock(&tp->tx_lock);
 
 	dev->trans_start = jiffies;
 
@@ -10514,11 +10549,13 @@
 	struct pcidev_cookie *pcp = pdev->sysdata;
 
 	if (pcp != NULL) {
-		int node = pcp->prom_node;
+		unsigned char *addr;
+		int len;
 
-		if (prom_getproplen(node, "local-mac-address") == 6) {
-			prom_getproperty(node, "local-mac-address",
-					 dev->dev_addr, 6);
+		addr = of_get_property(pcp->prom_node, "local-mac-address",
+					&len);
+		if (addr && len == 6) {
+			memcpy(dev->dev_addr, addr, 6);
 			memcpy(dev->perm_addr, dev->dev_addr, 6);
 			return 0;
 		}
@@ -11243,7 +11280,6 @@
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	dev->features |= NETIF_F_LLTX;
 #if TG3_VLAN_TAG_USED
 	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
 	dev->vlan_rx_register = tg3_vlan_rx_register;
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index ff0faab..8209da5 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2074,12 +2074,22 @@
 
 	/* SMP locking strategy:
 	 *
-	 * lock: Held during all operations except TX packet
-	 *       processing.
+	 * lock: Held during reset, PHY access, timer, and when
+	 *       updating tg3_flags and tg3_flags2.
 	 *
-	 * tx_lock: Held during tg3_start_xmit and tg3_tx
+	 * tx_lock: Held during tg3_start_xmit and tg3_tx only
+	 *          when calling netif_[start|stop]_queue.
+	 *          tg3_start_xmit is protected by netif_tx_lock.
 	 *
 	 * Both of these locks are to be held with BH safety.
+	 *
+	 * Because the IRQ handler, tg3_poll, and tg3_start_xmit
+	 * are running lockless, it is necessary to completely
+	 * quiesce the chip with tg3_netif_stop and tg3_full_lock
+	 * before reconfiguring the device.
+	 *
+	 * indirect_lock: Held when accessing registers indirectly
+	 *                with IRQ disabling.
 	 */
 	spinlock_t			lock;
 	spinlock_t			indirect_lock;
@@ -2155,11 +2165,7 @@
 #define TG3_FLAG_ENABLE_ASF		0x00000020
 #define TG3_FLAG_5701_REG_WRITE_BUG	0x00000040
 #define TG3_FLAG_POLL_SERDES		0x00000080
-#if defined(CONFIG_X86)
 #define TG3_FLAG_MBOX_WRITE_REORDER	0x00000100
-#else
-#define TG3_FLAG_MBOX_WRITE_REORDER	0	/* disables code too */
-#endif
 #define TG3_FLAG_PCIX_TARGET_HWBUG	0x00000200
 #define TG3_FLAG_WOL_SPEED_100MB	0x00000400
 #define TG3_FLAG_WOL_ENABLE		0x00000800
@@ -2172,6 +2178,7 @@
 #define TG3_FLAG_PCI_HIGH_SPEED		0x00040000
 #define TG3_FLAG_PCI_32BIT		0x00080000
 #define TG3_FLAG_SRAM_USE_CONFIG	0x00100000
+#define TG3_FLAG_TX_RECOVERY_PENDING	0x00200000
 #define TG3_FLAG_SERDES_WOL_CAP		0x00400000
 #define TG3_FLAG_JUMBO_RING_ENABLE	0x00800000
 #define TG3_FLAG_10_100_ONLY		0x01000000
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 23032a7..c3cb8d2 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -217,7 +217,7 @@
 	dev = alloc_trdev(sizeof(struct olympic_private)) ; 
 	if (!dev) {
 		i = -ENOMEM; 
-		goto op_free_dev;
+		goto op_release_dev;
 	}
 
 	olympic_priv = dev->priv ;
@@ -282,8 +282,8 @@
 	if (olympic_priv->olympic_lap)
 		iounmap(olympic_priv->olympic_lap);
 
-op_free_dev:
 	free_netdev(dev);
+op_release_dev:
 	pci_release_regions(pdev); 
 
 op_disable_dev:
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index e3dd144..5f743b9 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -227,12 +227,12 @@
 	SROMC0InfoLeaf		= 27,
 	MediaBlockMask		= 0x3f,
 	MediaCustomCSRs		= (1 << 6),
-	
+
 	/* PCIPM bits */
 	PM_Sleep		= (1 << 31),
 	PM_Snooze		= (1 << 30),
 	PM_Mask			= PM_Sleep | PM_Snooze,
-	
+
 	/* SIAStatus bits */
 	NWayState		= (1 << 14) | (1 << 13) | (1 << 12),
 	NWayRestart		= (1 << 12),
@@ -858,7 +858,7 @@
 			return;
 		cpu_relax();
 	}
-	
+
 	printk(KERN_WARNING "%s: timeout expired stopping DMA\n", de->dev->name);
 }
 
@@ -931,7 +931,7 @@
 		macmode |= FullDuplex;
 	else
 		macmode &= ~FullDuplex;
-	
+
 	if (netif_msg_link(de)) {
 		printk(KERN_INFO "%s: set link %s\n"
 		       KERN_INFO "%s:    mode 0x%x, sia 0x%x,0x%x,0x%x,0x%x\n"
@@ -966,9 +966,9 @@
 	u32 status = dr32(SIAStatus);
 	unsigned int carrier;
 	unsigned long flags;
-	
+
 	carrier = (status & NetCxnErr) ? 0 : 1;
-		
+
 	if (carrier) {
 		if (de->media_type != DE_MEDIA_AUI && (status & LinkFailStatus))
 			goto no_link_yet;
@@ -985,7 +985,7 @@
 		return;
 	}
 
-	de_link_down(de);	
+	de_link_down(de);
 
 	if (de->media_lock)
 		return;
@@ -1039,7 +1039,7 @@
 			return 0;
 		break;
 	}
-	
+
 	return 1;
 }
 
@@ -1050,9 +1050,9 @@
 	u32 status = dr32(SIAStatus);
 	unsigned int carrier;
 	unsigned long flags;
-	
+
 	carrier = (status & NetCxnErr) ? 0 : 1;
-		
+
 	if (carrier) {
 		if ((de->media_type == DE_MEDIA_TP_AUTO ||
 		     de->media_type == DE_MEDIA_TP ||
@@ -1072,7 +1072,7 @@
 		return;
 	}
 
-	de_link_down(de);	
+	de_link_down(de);
 
 	/* if media type locked, don't switch media */
 	if (de->media_lock)
@@ -1124,7 +1124,7 @@
 		u32 next_states[] = { DE_MEDIA_AUI, DE_MEDIA_BNC, DE_MEDIA_TP_AUTO };
 		de_next_media(de, next_states, ARRAY_SIZE(next_states));
 	}
-	
+
 set_media:
 	spin_lock_irqsave(&de->lock, flags);
 	de_stop_rxtx(de);
@@ -1148,7 +1148,7 @@
 		mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK);
 		return;
 	}
-	
+
 	BUG_ON(!(status & LinkFail));
 
 	if (netif_carrier_ok(de->dev)) {
@@ -1227,7 +1227,7 @@
 	int rc;
 
 	de_adapter_wake(de);
-	
+
 	macmode = dr32(MacMode) & ~MacModeClear;
 
 	rc = de_reset_mac(de);
@@ -1413,7 +1413,7 @@
 	netif_stop_queue(dev);
 	netif_carrier_off(dev);
 	spin_unlock_irqrestore(&de->lock, flags);
-	
+
 	free_irq(dev->irq, dev);
 
 	de_free_rings(de);
@@ -1441,7 +1441,7 @@
 
 	spin_unlock_irq(&de->lock);
 	enable_irq(dev->irq);
-		
+
 	/* Update the error counts. */
 	__de_get_stats(de);
 
@@ -1451,7 +1451,7 @@
 	de_init_rings(de);
 
 	de_init_hw(de);
-	
+
 	netif_wake_queue(dev);
 }
 
@@ -1459,7 +1459,7 @@
 {
 	int i;
 	u32 *rbuf = (u32 *)buf;
-	
+
 	/* read all CSRs */
 	for (i = 0; i < DE_NUM_REGS; i++)
 		rbuf[i] = dr32(i * 8);
@@ -1474,7 +1474,7 @@
 	ecmd->transceiver = XCVR_INTERNAL;
 	ecmd->phy_address = 0;
 	ecmd->advertising = de->media_advertise;
-	
+
 	switch (de->media_type) {
 	case DE_MEDIA_AUI:
 		ecmd->port = PORT_AUI;
@@ -1489,7 +1489,7 @@
 		ecmd->speed = SPEED_10;
 		break;
 	}
-	
+
 	if (dr32(MacMode) & FullDuplex)
 		ecmd->duplex = DUPLEX_FULL;
 	else
@@ -1529,7 +1529,7 @@
 	if (ecmd->autoneg == AUTONEG_ENABLE &&
 	    (!(ecmd->advertising & ADVERTISED_Autoneg)))
 		return -EINVAL;
-	
+
 	switch (ecmd->port) {
 	case PORT_AUI:
 		new_media = DE_MEDIA_AUI;
@@ -1554,22 +1554,22 @@
 			return -EINVAL;
 		break;
 	}
-	
+
 	media_lock = (ecmd->autoneg == AUTONEG_ENABLE) ? 0 : 1;
-	
+
 	if ((new_media == de->media_type) &&
 	    (media_lock == de->media_lock) &&
 	    (ecmd->advertising == de->media_advertise))
 		return 0; /* nothing to change */
-	    
+
 	de_link_down(de);
 	de_stop_rxtx(de);
-	
+
 	de->media_type = new_media;
 	de->media_lock = media_lock;
 	de->media_advertise = ecmd->advertising;
 	de_set_media(de);
-	
+
 	return 0;
 }
 
@@ -1817,7 +1817,7 @@
 	case 0x0204:  de->media_type = DE_MEDIA_TP_FD; break;
 	default: de->media_type = DE_MEDIA_TP_AUTO; break;
 	}
-	
+
 	if (netif_msg_probe(de))
 		printk(KERN_INFO "de%d: SROM leaf offset %u, default media %s\n",
 		       de->board_idx, ofs,
@@ -1886,7 +1886,7 @@
 				       de->media[idx].csr13,
 				       de->media[idx].csr14,
 				       de->media[idx].csr15);
-				       
+
 		} else if (netif_msg_probe(de))
 			printk("\n");
 
@@ -2118,7 +2118,7 @@
 
 		spin_unlock_irq(&de->lock);
 		enable_irq(dev->irq);
-		
+
 		/* Update the error counts. */
 		__de_get_stats(de);
 
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index f560941..da8bd0d 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -41,11 +41,11 @@
     Digital Semiconductor   SROM   Specification.    The  driver   currently
     recognises the following chips:
 
-        DC21040  (no SROM) 
-	DC21041[A]  
-	DC21140[A] 
-	DC21142 
-	DC21143 
+        DC21040  (no SROM)
+	DC21041[A]
+	DC21140[A]
+	DC21142
+	DC21143
 
     So far the driver is known to work with the following cards:
 
@@ -55,7 +55,7 @@
 	SMC8432
 	SMC9332 (w/new SROM)
 	ZNYX31[45]
-	ZNYX346 10/100 4 port (can act as a 10/100 bridge!) 
+	ZNYX346 10/100 4 port (can act as a 10/100 bridge!)
 
     The driver has been tested on a relatively busy network using the DE425,
     DE434, DE435 and DE500 cards and benchmarked with 'ttcp': it transferred
@@ -106,7 +106,7 @@
     loading by:
 
                    insmod de4x5 io=0xghh           where g = bus number
-		                                        hh = device number   
+		                                        hh = device number
 
        NB: autoprobing for modules is now supported by default. You may just
            use:
@@ -120,11 +120,11 @@
     4) if you are wanting to add a new  card, goto 5. Otherwise, recompile a
     kernel with the de4x5 configuration turned off and reboot.
     5) insmod de4x5 [io=0xghh]
-    6) run the net startup bits for your new eth?? interface(s) manually 
-    (usually /etc/rc.inet[12] at boot time). 
+    6) run the net startup bits for your new eth?? interface(s) manually
+    (usually /etc/rc.inet[12] at boot time).
     7) enjoy!
 
-    To unload a module, turn off the associated interface(s) 
+    To unload a module, turn off the associated interface(s)
     'ifconfig eth?? down' then 'rmmod de4x5'.
 
     Automedia detection is included so that in  principal you can disconnect
@@ -135,7 +135,7 @@
     By  default,  the driver will  now   autodetect any  DECchip based card.
     Should you have a need to restrict the driver to DIGITAL only cards, you
     can compile with a  DEC_ONLY define, or if  loading as a module, use the
-    'dec_only=1'  parameter. 
+    'dec_only=1'  parameter.
 
     I've changed the timing routines to  use the kernel timer and scheduling
     functions  so that the  hangs  and other assorted problems that occurred
@@ -204,7 +204,7 @@
     following parameters are allowed:
 
             fdx        for full duplex
-	    autosense  to set the media/speed; with the following 
+	    autosense  to set the media/speed; with the following
 	               sub-parameters:
 		       TP, TP_NW, BNC, AUI, BNC_AUI, 100Mb, 10Mb, AUTO
 
@@ -235,14 +235,14 @@
     this  automatically  or include  #define DE4X5_FORCE_EISA  on or  before
     line 1040 in the driver.
 
-    TO DO: 
+    TO DO:
     ------
 
     Revision History
     ----------------
 
     Version   Date        Description
-  
+
       0.1     17-Nov-94   Initial writing. ALPHA code release.
       0.2     13-Jan-95   Added PCI support for DE435's.
       0.21    19-Jan-95   Added auto media detection.
@@ -251,7 +251,7 @@
 			  Add request/release_region code.
 			  Add loadable modules support for PCI.
 			  Clean up loadable modules support.
-      0.23    28-Feb-95   Added DC21041 and DC21140 support. 
+      0.23    28-Feb-95   Added DC21041 and DC21140 support.
                           Fix missed frame counter value and initialisation.
 			  Fixed EISA probe.
       0.24    11-Apr-95   Change delay routine to use <linux/udelay>.
@@ -280,7 +280,7 @@
                           Add kernel timer code (h/w is too flaky).
 			  Add MII based PHY autosense.
 			  Add new multicasting code.
-			  Add new autosense algorithms for media/mode 
+			  Add new autosense algorithms for media/mode
 			  selection using kernel scheduling/timing.
 			  Re-formatted.
 			  Made changes suggested by <jeff@router.patch.net>:
@@ -307,10 +307,10 @@
                           Add Accton to the list of broken cards.
 			  Fix TX under-run bug for non DC21140 chips.
 			  Fix boot command probe bug in alloc_device() as
-			   reported by <koen.gadeyne@barco.com> and 
+			   reported by <koen.gadeyne@barco.com> and
 			   <orava@nether.tky.hut.fi>.
 			  Add cache locks to prevent a race condition as
-			   reported by <csd@microplex.com> and 
+			   reported by <csd@microplex.com> and
 			   <baba@beckman.uiuc.edu>.
 			  Upgraded alloc_device() code.
       0.431  28-Jun-96    Fix potential bug in queue_pkt() from discussion
@@ -322,7 +322,7 @@
                            with a loopback packet.
       0.442   9-Sep-96    Include AUI in dc21041 media printout. Bug reported
                            by <bhat@mundook.cs.mu.OZ.AU>
-      0.45    8-Dec-96    Include endian functions for PPC use, from work 
+      0.45    8-Dec-96    Include endian functions for PPC use, from work
                            by <cort@cs.nmt.edu> and <g.thomas@opengroup.org>.
       0.451  28-Dec-96    Added fix to allow autoprobe for modules after
                            suggestion from <mjacob@feral.com>.
@@ -346,14 +346,14 @@
 			   <paubert@iram.es>.
       0.52   26-Apr-97    Some changes may not credit the right people -
                            a disk crash meant I lost some mail.
-			  Change RX interrupt routine to drop rather than 
-			   defer packets to avoid hang reported by 
+			  Change RX interrupt routine to drop rather than
+			   defer packets to avoid hang reported by
 			   <g.thomas@opengroup.org>.
 			  Fix srom_exec() to return for COMPACT and type 1
 			   infoblocks.
 			  Added DC21142 and DC21143 functions.
 			  Added byte counters from <phil@tazenda.demon.co.uk>
-			  Added SA_INTERRUPT temporary fix from 
+			  Added SA_INTERRUPT temporary fix from
 			   <mjacob@feral.com>.
       0.53   12-Nov-97    Fix the *_probe() to include 'eth??' name during
                            module load: bug reported by
@@ -363,10 +363,10 @@
 			  Make above search independent of BIOS device scan
 			   direction.
 			  Completed DC2114[23] autosense functions.
-      0.531  21-Dec-97    Fix DE500-XA 100Mb/s bug reported by 
+      0.531  21-Dec-97    Fix DE500-XA 100Mb/s bug reported by
                            <robin@intercore.com
 			  Fix type1_infoblock() bug introduced in 0.53, from
-			   problem reports by 
+			   problem reports by
 			   <parmee@postecss.ncrfran.france.ncr.com> and
 			   <jo@ice.dillingen.baynet.de>.
 			  Added argument list to set up each board from either
@@ -374,7 +374,7 @@
 			  Added generic MII PHY functionality to deal with
 			   newer PHY chips.
 			  Fix the mess in 2.1.67.
-      0.532   5-Jan-98    Fix bug in mii_get_phy() reported by 
+      0.532   5-Jan-98    Fix bug in mii_get_phy() reported by
                            <redhat@cococo.net>.
                           Fix bug in pci_probe() for 64 bit systems reported
 			   by <belliott@accessone.com>.
@@ -398,7 +398,7 @@
 			   version. I hope nothing is broken...
           		  Add TX done interrupt modification from suggestion
 			   by <Austin.Donnelly@cl.cam.ac.uk>.
-			  Fix is_anc_capable() bug reported by 
+			  Fix is_anc_capable() bug reported by
 			   <Austin.Donnelly@cl.cam.ac.uk>.
 			  Fix type[13]_infoblock() bug: during MII search, PHY
 			   lp->rst not run because lp->ibn not initialised -
@@ -413,7 +413,7 @@
 			  Add an_exception() for old ZYNX346 and fix compile
 			   warning on PPC & SPARC, from <ecd@skynet.be>.
 			  Fix lastPCI to correctly work with compiled in
-			   kernels and modules from bug report by 
+			   kernels and modules from bug report by
 			   <Zlatko.Calusic@CARNet.hr> et al.
       0.542  15-Sep-98    Fix dc2114x_autoconf() to stop multiple messages
                            when media is unconnected.
@@ -425,7 +425,7 @@
       0.544   8-May-99    Fix for buggy SROM in Motorola embedded boards using
                            a 21143 by <mmporter@home.com>.
 			  Change PCI/EISA bus probing order.
-      0.545  28-Nov-99    Further Moto SROM bug fix from 
+      0.545  28-Nov-99    Further Moto SROM bug fix from
                            <mporter@eng.mcd.mot.com>
                           Remove double checking for DEBUG_RX in de4x5_dbg_rx()
 			   from report by <geert@linux-m68k.org>
@@ -434,8 +434,8 @@
                            variable 'pb', on a non de4x5 PCI device, in this
                            case a PCI bridge (DEC chip 21152). The value of
                            'pb' is now only initialized if a de4x5 chip is
-                           present. 
-                           <france@handhelds.org>  
+                           present.
+                           <france@handhelds.org>
       0.547  08-Nov-01    Use library crc32 functions by <Matt_Domsch@dell.com>
       0.548  30-Aug-03    Big 2.6 cleanup. Ported to PCI/EISA probing and
                            generic DMA APIs. Fixed DE425 support on Alpha.
@@ -584,7 +584,7 @@
 
 /*
 ** Allow per adapter set up. For modules this is simply a command line
-** parameter, e.g.: 
+** parameter, e.g.:
 ** insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
 **
 ** For a compiled in driver, place e.g.
@@ -655,7 +655,7 @@
 ** Memory Alignment. Each descriptor is 4 longwords long. To force a
 ** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
 ** DESC_ALIGN. ALIGN aligns the start address of the private memory area
-** and hence the RX descriptor ring's first entry. 
+** and hence the RX descriptor ring's first entry.
 */
 #define DE4X5_ALIGN4      ((u_long)4 - 1)     /* 1 longword align */
 #define DE4X5_ALIGN8      ((u_long)8 - 1)     /* 2 longword align */
@@ -1081,8 +1081,8 @@
     mdelay(2);                           /* Wait for 2ms */\
 }
 
-
-static int __devinit 
+
+static int __devinit
 de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
 {
     char name[DE4X5_NAME_LENGTH + 1];
@@ -1102,12 +1102,12 @@
     mdelay(10);
 
     RESET_DE4X5;
-    
+
     if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) != 0) {
 	return -ENXIO;                       /* Hardware could not reset */
     }
-    
-    /* 
+
+    /*
     ** Now find out what kind of DC21040/DC21041/DC21140 board we have.
     */
     lp->useSROM = FALSE;
@@ -1116,21 +1116,21 @@
     } else {
 	EISA_signature(name, gendev);
     }
-    
+
     if (*name == '\0') {                     /* Not found a board signature */
 	return -ENXIO;
     }
-    
+
     dev->base_addr = iobase;
     printk ("%s: %s at 0x%04lx", gendev->bus_id, name, iobase);
-    
+
     printk(", h/w address ");
     status = get_hw_addr(dev);
     for (i = 0; i < ETH_ALEN - 1; i++) {     /* get the ethernet addr. */
 	printk("%2.2x:", dev->dev_addr[i]);
     }
     printk("%2.2x,\n", dev->dev_addr[i]);
-    
+
     if (status != 0) {
 	printk("      which has an Ethernet PROM CRC error.\n");
 	return -ENXIO;
@@ -1171,10 +1171,10 @@
 	}
 
 	lp->tx_ring = lp->rx_ring + NUM_RX_DESC;
-	    
+
 	/*
 	** Set up the RX descriptor ring (Intels)
-	** Allocate contiguous receive buffers, long word aligned (Alphas) 
+	** Allocate contiguous receive buffers, long word aligned (Alphas)
 	*/
 #if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY)
 	for (i=0; i<NUM_RX_DESC; i++) {
@@ -1210,7 +1210,7 @@
 
 	lp->rxRingSize = NUM_RX_DESC;
 	lp->txRingSize = NUM_TX_DESC;
-	    
+
 	/* Write the end of list marker to the descriptor lists */
 	lp->rx_ring[lp->rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
 	lp->tx_ring[lp->txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
@@ -1219,7 +1219,7 @@
 	outl(lp->dma_rings, DE4X5_RRBA);
 	outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
 	     DE4X5_TRBA);
-	    
+
 	/* Initialise the IRQ mask and Enable/Disable */
 	lp->irq_mask = IMR_RIM | IMR_TIM | IMR_TUM | IMR_UNM;
 	lp->irq_en   = IMR_NIM | IMR_AIM;
@@ -1252,7 +1252,7 @@
 	if ((lp->chipset != DC21040) && (lp->chipset != DC21041)) {
 	    mii_get_phy(dev);
 	}
-	
+
 #ifndef __sparc_v9__
 	printk("      and requires IRQ%d (provided by %s).\n", dev->irq,
 #else
@@ -1260,11 +1260,11 @@
 #endif
 	       ((lp->bus == PCI) ? "PCI BIOS" : "EISA CNFG"));
     }
-    
+
     if (de4x5_debug & DEBUG_VERSION) {
 	printk(version);
     }
-    
+
     /* The DE4X5-specific entries in the device structure. */
     SET_MODULE_OWNER(dev);
     SET_NETDEV_DEV(dev, gendev);
@@ -1274,23 +1274,23 @@
     dev->get_stats = &de4x5_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     dev->do_ioctl = &de4x5_ioctl;
-    
+
     dev->mem_start = 0;
-    
+
     /* Fill in the generic fields of the device structure. */
     if ((status = register_netdev (dev))) {
 	    dma_free_coherent (gendev, lp->dma_size,
 			       lp->rx_ring, lp->dma_rings);
 	    return status;
     }
-    
+
     /* Let the adapter sleep to save power */
     yawn(dev, SLEEP);
-    
+
     return status;
 }
 
-
+
 static int
 de4x5_open(struct net_device *dev)
 {
@@ -1312,15 +1312,15 @@
     */
     yawn(dev, WAKEUP);
 
-    /* 
-    ** Re-initialize the DE4X5... 
+    /*
+    ** Re-initialize the DE4X5...
     */
     status = de4x5_init(dev);
     spin_lock_init(&lp->lock);
     lp->state = OPEN;
     de4x5_dbg_open(dev);
-    
-    if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ, 
+
+    if (request_irq(dev->irq, (void *)de4x5_interrupt, SA_SHIRQ,
 		                                     lp->adapter_name, dev)) {
 	printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
 	if (request_irq(dev->irq, de4x5_interrupt, SA_INTERRUPT | SA_SHIRQ,
@@ -1340,11 +1340,11 @@
 
     lp->interrupt = UNMASK_INTERRUPTS;
     dev->trans_start = jiffies;
-    
+
     START_DE4X5;
-	
+
     de4x5_setup_intr(dev);
-    
+
     if (de4x5_debug & DEBUG_OPEN) {
 	printk("\tsts:  0x%08x\n", inl(DE4X5_STS));
 	printk("\tbmr:  0x%08x\n", inl(DE4X5_BMR));
@@ -1355,7 +1355,7 @@
 	printk("\tstrr: 0x%08x\n", inl(DE4X5_STRR));
 	printk("\tsigr: 0x%08x\n", inl(DE4X5_SIGR));
     }
-    
+
     return status;
 }
 
@@ -1369,15 +1369,15 @@
 */
 static int
 de4x5_init(struct net_device *dev)
-{  
+{
     /* Lock out other processes whilst setting up the hardware */
     netif_stop_queue(dev);
-    
+
     de4x5_sw_reset(dev);
-    
+
     /* Autoconfigure the connected port */
     autoconf_media(dev);
-    
+
     return 0;
 }
 
@@ -1388,7 +1388,7 @@
     u_long iobase = dev->base_addr;
     int i, j, status = 0;
     s32 bmr, omr;
-    
+
     /* Select the MII or SRL port now and RESET the MAC */
     if (!lp->useSROM) {
 	if (lp->phy[lp->active].id != 0) {
@@ -1399,7 +1399,7 @@
 	de4x5_switch_mac_port(dev);
     }
 
-    /* 
+    /*
     ** Set the programmable burst length to 8 longwords for all the DC21140
     ** Fasternet chips and 4 longwords for all others: DMA errors result
     ** without these values. Cache align 16 long.
@@ -1416,23 +1416,23 @@
     outl(lp->dma_rings, DE4X5_RRBA);
     outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
 	 DE4X5_TRBA);
-    
+
     lp->rx_new = lp->rx_old = 0;
     lp->tx_new = lp->tx_old = 0;
-    
+
     for (i = 0; i < lp->rxRingSize; i++) {
 	lp->rx_ring[i].status = cpu_to_le32(R_OWN);
     }
-    
+
     for (i = 0; i < lp->txRingSize; i++) {
 	lp->tx_ring[i].status = cpu_to_le32(0);
     }
-    
+
     barrier();
 
     /* Build the setup frame depending on filtering mode */
     SetMulticastFilter(dev);
-    
+
     load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, (struct sk_buff *)1);
     outl(omr|OMR_ST, DE4X5_OMR);
 
@@ -1445,18 +1445,18 @@
     outl(omr, DE4X5_OMR);                        /* Stop everything! */
 
     if (j == 0) {
-	printk("%s: Setup frame timed out, status %08x\n", dev->name, 
+	printk("%s: Setup frame timed out, status %08x\n", dev->name,
 	       inl(DE4X5_STS));
 	status = -EIO;
     }
-    
+
     lp->tx_new = (++lp->tx_new) % lp->txRingSize;
     lp->tx_old = lp->tx_new;
 
     return status;
 }
 
-/* 
+/*
 ** Writes a socket buffer address to the next available transmit descriptor.
 */
 static int
@@ -1469,9 +1469,9 @@
 
     netif_stop_queue(dev);
     if (lp->tx_enable == NO) {                   /* Cannot send for now */
-	return -1;                                
+	return -1;
     }
-    
+
     /*
     ** Clean out the TX ring asynchronously to interrupts - sometimes the
     ** interrupts are lost by delayed descriptor status updates relative to
@@ -1482,7 +1482,7 @@
     spin_unlock_irqrestore(&lp->lock, flags);
 
     /* Test if cache is already locked - requeue skb if so */
-    if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt) 
+    if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt)
 	return -1;
 
     /* Transmit descriptor ring full or stale skb */
@@ -1509,10 +1509,10 @@
 	    load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb);
  	    lp->stats.tx_bytes += skb->len;
 	    outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */
-		
+
 	    lp->tx_new = (++lp->tx_new) % lp->txRingSize;
 	    dev->trans_start = jiffies;
-		    
+
 	    if (TX_BUFFS_AVAIL) {
 		netif_start_queue(dev);         /* Another pkt may be queued */
 	    }
@@ -1521,15 +1521,15 @@
 	}
 	if (skb) de4x5_putb_cache(dev, skb);
     }
-    
+
     lp->cache.lock = 0;
 
     return status;
 }
 
 /*
-** The DE4X5 interrupt handler. 
-** 
+** The DE4X5 interrupt handler.
+**
 ** I/O Read/Writes through intermediate PCI bridges are never 'posted',
 ** so that the asserted interrupt always has some real data to work with -
 ** if these I/O accesses are ever changed to memory accesses, ensure the
@@ -1546,7 +1546,7 @@
     s32 imr, omr, sts, limit;
     u_long iobase;
     unsigned int handled = 0;
-    
+
     if (dev == NULL) {
 	printk ("de4x5_interrupt(): irq %d for unknown device.\n", irq);
 	return IRQ_NONE;
@@ -1554,35 +1554,35 @@
     lp = netdev_priv(dev);
     spin_lock(&lp->lock);
     iobase = dev->base_addr;
-	
+
     DISABLE_IRQs;                        /* Ensure non re-entrancy */
 
     if (test_and_set_bit(MASK_INTERRUPTS, (void*) &lp->interrupt))
 	printk("%s: Re-entering the interrupt handler.\n", dev->name);
 
     synchronize_irq(dev->irq);
-	
+
     for (limit=0; limit<8; limit++) {
 	sts = inl(DE4X5_STS);            /* Read IRQ status */
 	outl(sts, DE4X5_STS);            /* Reset the board interrupts */
-	    
+
 	if (!(sts & lp->irq_mask)) break;/* All done */
 	handled = 1;
-	    
+
 	if (sts & (STS_RI | STS_RU))     /* Rx interrupt (packet[s] arrived) */
 	  de4x5_rx(dev);
-	    
+
 	if (sts & (STS_TI | STS_TU))     /* Tx interrupt (packet sent) */
-	  de4x5_tx(dev); 
-	    
+	  de4x5_tx(dev);
+
 	if (sts & STS_LNF) {             /* TP Link has failed */
 	    lp->irq_mask &= ~IMR_LFM;
 	}
-	    
+
 	if (sts & STS_UNF) {             /* Transmit underrun */
 	    de4x5_txur(dev);
 	}
-	    
+
 	if (sts & STS_SE) {              /* Bus Error */
 	    STOP_DE4X5;
 	    printk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",
@@ -1603,7 +1603,7 @@
     lp->interrupt = UNMASK_INTERRUPTS;
     ENABLE_IRQs;
     spin_unlock(&lp->lock);
-    
+
     return IRQ_RETVAL(handled);
 }
 
@@ -1614,11 +1614,11 @@
     u_long iobase = dev->base_addr;
     int entry;
     s32 status;
-    
+
     for (entry=lp->rx_new; (s32)le32_to_cpu(lp->rx_ring[entry].status)>=0;
 	                                                    entry=lp->rx_new) {
 	status = (s32)le32_to_cpu(lp->rx_ring[entry].status);
-	
+
 	if (lp->rx_ovf) {
 	    if (inl(DE4X5_MFC) & MFC_FOCM) {
 		de4x5_rx_ovfc(dev);
@@ -1629,7 +1629,7 @@
 	if (status & RD_FS) {                 /* Remember the start of frame */
 	    lp->rx_old = entry;
 	}
-	
+
 	if (status & RD_LS) {                 /* Valid frame status */
 	    if (lp->tx_enable) lp->linkOK++;
 	    if (status & RD_ES) {	      /* There was an error. */
@@ -1646,9 +1646,9 @@
 		struct sk_buff *skb;
 		short pkt_len = (short)(le32_to_cpu(lp->rx_ring[entry].status)
 					                            >> 16) - 4;
-		
+
 		if ((skb = de4x5_alloc_rx_buff(dev, entry, pkt_len)) == NULL) {
-		    printk("%s: Insufficient memory; nuking packet.\n", 
+		    printk("%s: Insufficient memory; nuking packet.\n",
 			                                            dev->name);
 		    lp->stats.rx_dropped++;
 		} else {
@@ -1658,14 +1658,14 @@
 		    skb->protocol=eth_type_trans(skb,dev);
 		    de4x5_local_stats(dev, skb->data, pkt_len);
 		    netif_rx(skb);
-		    
+
 		    /* Update stats */
 		    dev->last_rx = jiffies;
 		    lp->stats.rx_packets++;
  		    lp->stats.rx_bytes += pkt_len;
 		}
 	    }
-	    
+
 	    /* Change buffer ownership for this frame, back to the adapter */
 	    for (;lp->rx_old!=entry;lp->rx_old=(++lp->rx_old)%lp->rxRingSize) {
 		lp->rx_ring[lp->rx_old].status = cpu_to_le32(R_OWN);
@@ -1674,13 +1674,13 @@
 	    lp->rx_ring[entry].status = cpu_to_le32(R_OWN);
 	    barrier();
 	}
-	
+
 	/*
 	** Update entry information
 	*/
 	lp->rx_new = (++lp->rx_new) % lp->rxRingSize;
     }
-    
+
     return 0;
 }
 
@@ -1705,20 +1705,20 @@
     u_long iobase = dev->base_addr;
     int entry;
     s32 status;
-    
+
     for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {
 	status = (s32)le32_to_cpu(lp->tx_ring[entry].status);
 	if (status < 0) {                     /* Buffer not sent yet */
 	    break;
 	} else if (status != 0x7fffffff) {    /* Not setup frame */
 	    if (status & TD_ES) {             /* An error happened */
-		lp->stats.tx_errors++; 
+		lp->stats.tx_errors++;
 		if (status & TD_NC) lp->stats.tx_carrier_errors++;
 		if (status & TD_LC) lp->stats.tx_window_errors++;
 		if (status & TD_UF) lp->stats.tx_fifo_errors++;
 		if (status & TD_EC) lp->pktStats.excessive_collisions++;
 		if (status & TD_DE) lp->stats.tx_aborted_errors++;
-	    
+
 		if (TX_PKT_PENDING) {
 		    outl(POLL_DEMAND, DE4X5_TPD);/* Restart a stalled TX */
 		}
@@ -1727,14 +1727,14 @@
 		if (lp->tx_enable) lp->linkOK++;
 	    }
 	    /* Update the collision counter */
-	    lp->stats.collisions += ((status & TD_EC) ? 16 : 
+	    lp->stats.collisions += ((status & TD_EC) ? 16 :
 				                      ((status & TD_CC) >> 3));
 
 	    /* Free the buffer. */
 	    if (lp->tx_skb[entry] != NULL)
 	    	de4x5_free_tx_buff(lp, entry);
 	}
-	
+
 	/* Update all the pointers */
 	lp->tx_old = (++lp->tx_old) % lp->txRingSize;
     }
@@ -1746,7 +1746,7 @@
 	else
 	    netif_start_queue(dev);
     }
-	
+
     return 0;
 }
 
@@ -1755,9 +1755,9 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int next_tick = DE4X5_AUTOSENSE_MS;
-    
+
     disable_ast(dev);
-    
+
     if (lp->useSROM) {
 	next_tick = srom_autoconf(dev);
     } else if (lp->chipset == DC21140) {
@@ -1769,7 +1769,7 @@
     }
     lp->linkOK = 0;
     enable_ast(dev, next_tick);
-    
+
     return 0;
 }
 
@@ -1792,11 +1792,11 @@
 	}
 	outl(omr | OMR_ST | OMR_SR, DE4X5_OMR);
     }
-    
+
     return 0;
 }
 
-static int 
+static int
 de4x5_rx_ovfc(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -1813,7 +1813,7 @@
     }
 
     outl(omr, DE4X5_OMR);
-    
+
     return 0;
 }
 
@@ -1823,22 +1823,22 @@
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 imr, omr;
-    
+
     disable_ast(dev);
 
     netif_stop_queue(dev);
-    
+
     if (de4x5_debug & DEBUG_CLOSE) {
 	printk("%s: Shutting down ethercard, status was %8.8x.\n",
 	       dev->name, inl(DE4X5_STS));
     }
-    
-    /* 
+
+    /*
     ** We stop the DE4X5 here... mask interrupts and stop TX & RX
     */
     DISABLE_IRQs;
     STOP_DE4X5;
-    
+
     /* Free the associated irq */
     free_irq(dev->irq, dev);
     lp->state = CLOSED;
@@ -1846,10 +1846,10 @@
     /* Free any socket buffers */
     de4x5_free_rx_buffs(dev);
     de4x5_free_tx_buffs(dev);
-    
+
     /* Put the adapter to sleep to save power */
     yawn(dev, SLEEP);
-    
+
     return 0;
 }
 
@@ -1858,9 +1858,9 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     lp->stats.rx_missed_errors = (int)(inl(DE4X5_MFC) & (MFC_OVFL | MFC_CNTR));
-    
+
     return &lp->stats;
 }
 
@@ -1886,7 +1886,7 @@
 	       (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {
         lp->pktStats.unicast++;
     }
-		
+
     lp->pktStats.bins[0]++;       /* Duplicates stats.rx_packets */
     if (lp->pktStats.bins[0] == 0) { /* Reset counters */
         memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats));
@@ -1937,11 +1937,11 @@
 	    omr = inl(DE4X5_OMR);
 	    omr |= OMR_PR;
 	    outl(omr, DE4X5_OMR);
-	} else { 
+	} else {
 	    SetMulticastFilter(dev);
-	    load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
+	    load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
 			                                SETUP_FRAME_LEN, (struct sk_buff *)1);
-	    
+
 	    lp->tx_new = (++lp->tx_new) % lp->txRingSize;
 	    outl(POLL_DEMAND, DE4X5_TPD);       /* Start the TX */
 	    dev->trans_start = jiffies;
@@ -1969,20 +1969,20 @@
     omr = inl(DE4X5_OMR);
     omr &= ~(OMR_PR | OMR_PM);
     pa = build_setup_frame(dev, ALL);        /* Build the basic frame */
-    
+
     if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 14)) {
 	omr |= OMR_PM;                       /* Pass all multicasts */
     } else if (lp->setup_f == HASH_PERF) {   /* Hash Filtering */
 	for (i=0;i<dev->mc_count;i++) {      /* for each address in the list */
 	    addrs=dmi->dmi_addr;
 	    dmi=dmi->next;
-	    if ((*addrs & 0x01) == 1) {      /* multicast address? */ 
+	    if ((*addrs & 0x01) == 1) {      /* multicast address? */
 		crc = ether_crc_le(ETH_ALEN, addrs);
 		hashcode = crc & HASH_BITS;  /* hashcode is 9 LSb of CRC */
-		
+
 		byte = hashcode >> 3;        /* bit[3-8] -> byte in filter */
 		bit = 1 << (hashcode & 0x07);/* bit[0-2] -> bit in byte */
-		
+
 		byte <<= 1;                  /* calc offset into setup frame */
 		if (byte & 0x02) {
 		    byte -= 1;
@@ -1994,14 +1994,14 @@
 	for (j=0; j<dev->mc_count; j++) {
 	    addrs=dmi->dmi_addr;
 	    dmi=dmi->next;
-	    for (i=0; i<ETH_ALEN; i++) { 
+	    for (i=0; i<ETH_ALEN; i++) {
 		*(pa + (i&1)) = *addrs++;
 		if (i & 0x01) pa += 4;
 	    }
 	}
     }
     outl(omr, DE4X5_OMR);
-    
+
     return;
 }
 
@@ -2031,18 +2031,18 @@
 		status = -EBUSY;
 		goto release_reg_1;
 	}
-	
+
 	if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
 		status = -ENOMEM;
 		goto release_reg_2;
 	}
 	lp = netdev_priv(dev);
-	
+
 	cfid = (u32) inl(PCI_CFID);
 	lp->cfrv = (u_short) inl(PCI_CFRV);
 	device = (cfid >> 8) & 0x00ffff00;
 	vendor = (u_short) cfid;
-	    
+
 	/* Read the EISA Configuration Registers */
 	regval = inb(EISA_REG0) & (ER0_INTL | ER0_INTT);
 #ifdef CONFIG_ALPHA
@@ -2050,7 +2050,7 @@
 	 * care about the EISA configuration, and thus doesn't
 	 * configure the PLX bridge properly. Oh well... Simply mimic
 	 * the EISA config file to sort it out. */
-	
+
 	/* EISA REG1: Assert DecChip 21040 HW Reset */
 	outb (ER1_IAM | 1, EISA_REG1);
 	mdelay (1);
@@ -2061,12 +2061,12 @@
 
 	/* EISA REG3: R/W Burst Transfer Enable */
 	outb (ER3_BWE | ER3_BRE, EISA_REG3);
-	
+
 	/* 32_bit slave/master, Preempt Time=23 bclks, Unlatched Interrupt */
 	outb (ER0_BSW | ER0_BMW | ER0_EPT | regval, EISA_REG0);
 #endif
 	irq = de4x5_irq[(regval >> 1) & 0x03];
-	
+
 	if (is_DC2114x) {
 	    device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
 	}
@@ -2077,7 +2077,7 @@
 	outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
 	outl(0x00006000, PCI_CFLT);
 	outl(iobase, PCI_CBIO);
-	    
+
 	DevicePresent(dev, EISA_APROM);
 
 	dev->irq = irq;
@@ -2102,7 +2102,7 @@
 
 	dev = device->driver_data;
 	iobase = dev->base_addr;
-	
+
 	unregister_netdev (dev);
 	free_netdev (dev);
 	release_region (iobase + DE4X5_EISA_IO_PORTS, DE4X5_EISA_TOTAL_SIZE);
@@ -2131,11 +2131,11 @@
 
 /*
 ** This function searches the current bus (which is >0) for a DECchip with an
-** SROM, so that in multiport cards that have one SROM shared between multiple 
+** SROM, so that in multiport cards that have one SROM shared between multiple
 ** DECchips, we can find the base SROM irrespective of the BIOS scan direction.
 ** For single port cards this is a time waster...
 */
-static void __devinit 
+static void __devinit
 srom_search(struct net_device *dev, struct pci_dev *pdev)
 {
     u_char pb;
@@ -2163,7 +2163,7 @@
 	/* Set the device number information */
 	lp->device = PCI_SLOT(this_dev->devfn);
 	lp->bus_num = pb;
-	    
+
 	/* Set the chipset information */
 	if (is_DC2114x) {
 	    device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
@@ -2176,7 +2176,7 @@
 	/* Fetch the IRQ to be used */
 	irq = this_dev->irq;
 	if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
-	    
+
 	/* Check if I/O accesses are enabled */
 	pci_read_config_word(this_dev, PCI_COMMAND, &status);
 	if (!(status & PCI_COMMAND_IO)) continue;
@@ -2254,7 +2254,7 @@
 	lp = netdev_priv(dev);
 	lp->bus = PCI;
 	lp->bus_num = 0;
-	
+
 	/* Search for an SROM on this bus */
 	if (lp->bus_num != pb) {
 	    lp->bus_num = pb;
@@ -2267,7 +2267,7 @@
 	/* Set the device number information */
 	lp->device = dev_num;
 	lp->bus_num = pb;
-	
+
 	/* Set the chipset information */
 	if (is_DC2114x) {
 	    device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
@@ -2283,7 +2283,7 @@
 		error = -ENODEV;
 		goto free_dev;
 	}
-	    
+
 	/* Check if I/O accesses and Bus Mastering are enabled */
 	pci_read_config_word(pdev, PCI_COMMAND, &status);
 #ifdef __powerpc__
@@ -2322,7 +2322,7 @@
 	}
 
 	dev->irq = irq;
-	
+
 	if ((error = de4x5_hw_init(dev, iobase, &pdev->dev))) {
 		goto release;
 	}
@@ -2377,7 +2377,7 @@
 ** Auto configure the media here rather than setting the port at compile
 ** time. This routine is called by de4x5_init() and when a loss of media is
 ** detected (excessive collisions, loss of carrier, no carrier or link fail
-** [TP] or no recent receive activity) to check whether the user has been 
+** [TP] or no recent receive activity) to check whether the user has been
 ** sneaky and changed the port on us.
 */
 static int
@@ -2405,7 +2405,7 @@
     }
 
     enable_ast(dev, next_tick);
-    
+
     return (lp->media);
 }
 
@@ -2428,7 +2428,7 @@
     u_long iobase = dev->base_addr;
     int next_tick = DE4X5_AUTOSENSE_MS;
     s32 imr;
-    
+
     switch (lp->media) {
     case INIT:
 	DISABLE_IRQs;
@@ -2447,36 +2447,36 @@
 	lp->local_state = 0;
 	next_tick = dc21040_autoconf(dev);
 	break;
-	
+
     case TP:
-	next_tick = dc21040_state(dev, 0x8f01, 0xffff, 0x0000, 3000, BNC_AUI, 
+	next_tick = dc21040_state(dev, 0x8f01, 0xffff, 0x0000, 3000, BNC_AUI,
 		                                         TP_SUSPECT, test_tp);
 	break;
-	
+
     case TP_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21040_autoconf);
 	break;
-	
+
     case BNC:
     case AUI:
     case BNC_AUI:
-	next_tick = dc21040_state(dev, 0x8f09, 0x0705, 0x0006, 3000, EXT_SIA, 
+	next_tick = dc21040_state(dev, 0x8f09, 0x0705, 0x0006, 3000, EXT_SIA,
 		                                  BNC_AUI_SUSPECT, ping_media);
 	break;
-	
+
     case BNC_AUI_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, BNC_AUI, ping_media, dc21040_autoconf);
 	break;
-	
+
     case EXT_SIA:
-	next_tick = dc21040_state(dev, 0x3041, 0x0000, 0x0006, 3000, 
+	next_tick = dc21040_state(dev, 0x3041, 0x0000, 0x0006, 3000,
 		                              NC, EXT_SIA_SUSPECT, ping_media);
 	break;
-	
+
     case EXT_SIA_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, EXT_SIA, ping_media, dc21040_autoconf);
 	break;
-	
+
     case NC:
 	/* default to TP for all */
 	reset_init_sia(dev, 0x8f01, 0xffff, 0x0000);
@@ -2488,13 +2488,13 @@
 	lp->tx_enable = NO;
 	break;
     }
-    
+
     return next_tick;
 }
 
 static int
 dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeout,
-	      int next_state, int suspect_state, 
+	      int next_state, int suspect_state,
 	      int (*fn)(struct net_device *, int))
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -2507,7 +2507,7 @@
 	lp->local_state++;
 	next_tick = 500;
 	break;
-	    
+
     case 1:
 	if (!lp->tx_enable) {
 	    linkBad = fn(dev, timeout);
@@ -2527,7 +2527,7 @@
 	}
 	break;
     }
-    
+
     return next_tick;
 }
 
@@ -2582,7 +2582,7 @@
     u_long iobase = dev->base_addr;
     s32 sts, irqs, irq_mask, imr, omr;
     int next_tick = DE4X5_AUTOSENSE_MS;
-    
+
     switch (lp->media) {
     case INIT:
 	DISABLE_IRQs;
@@ -2603,7 +2603,7 @@
 	lp->local_state = 0;
 	next_tick = dc21041_autoconf(dev);
 	break;
-	
+
     case TP_NW:
 	if (lp->timeout < 0) {
 	    omr = inl(DE4X5_OMR);/* Set up full duplex for the autonegotiate */
@@ -2623,7 +2623,7 @@
 	    next_tick = dc21041_autoconf(dev);
 	}
 	break;
-	
+
     case ANS:
 	if (!lp->tx_enable) {
 	    irqs = STS_LNP;
@@ -2645,11 +2645,11 @@
 	    next_tick = 3000;
 	}
 	break;
-	
+
     case ANS_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, ANS, test_tp, dc21041_autoconf);
 	break;
-	
+
     case TP:
 	if (!lp->tx_enable) {
 	    if (lp->timeout < 0) {
@@ -2679,11 +2679,11 @@
 	    next_tick = 3000;
 	}
 	break;
-	
+
     case TP_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21041_autoconf);
 	break;
-	
+
     case AUI:
 	if (!lp->tx_enable) {
 	    if (lp->timeout < 0) {
@@ -2709,11 +2709,11 @@
 	    next_tick = 3000;
 	}
 	break;
-	
+
     case AUI_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc21041_autoconf);
 	break;
-	
+
     case BNC:
 	switch (lp->local_state) {
 	case 0:
@@ -2731,7 +2731,7 @@
 		next_tick = dc21041_autoconf(dev);
 	    }
 	    break;
-	    
+
 	case 1:
 	    if (!lp->tx_enable) {
 		if ((sts = ping_media(dev, 3000)) < 0) {
@@ -2751,11 +2751,11 @@
 	    break;
 	}
 	break;
-	
+
     case BNC_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc21041_autoconf);
 	break;
-	
+
     case NC:
 	omr = inl(DE4X5_OMR);    /* Set up full duplex for the autonegotiate */
 	outl(omr | OMR_FDX, DE4X5_OMR);
@@ -2768,7 +2768,7 @@
 	lp->tx_enable = NO;
 	break;
     }
-    
+
     return next_tick;
 }
 
@@ -2784,9 +2784,9 @@
     int ana, anlpa, cap, cr, slnk, sr;
     int next_tick = DE4X5_AUTOSENSE_MS;
     u_long imr, omr, iobase = dev->base_addr;
-    
+
     switch(lp->media) {
-    case INIT: 
+    case INIT:
         if (lp->timeout < 0) {
 	    DISABLE_IRQs;
 	    lp->tx_enable = FALSE;
@@ -2813,7 +2813,7 @@
 		    lp->media = _100Mb;
 		} else if (lp->autosense == _10Mb) {
 		    lp->media = _10Mb;
-		} else if ((lp->autosense == AUTO) && 
+		} else if ((lp->autosense == AUTO) &&
 			            ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
 		    ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
 		    ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
@@ -2831,7 +2831,7 @@
 	    next_tick = dc21140m_autoconf(dev);
 	}
 	break;
-	
+
     case ANS:
 	switch (lp->local_state) {
 	case 0:
@@ -2851,7 +2851,7 @@
 		next_tick = dc21140m_autoconf(dev);
 	    }
 	    break;
-	    
+
 	case 1:
 	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
 		next_tick = sr & ~TIMER_CB;
@@ -2862,7 +2862,7 @@
 		    lp->tmp = MII_SR_ASSC;
 		    anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII);
 		    ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
-		    if (!(anlpa & MII_ANLPA_RF) && 
+		    if (!(anlpa & MII_ANLPA_RF) &&
 			 (cap = anlpa & MII_ANLPA_TAF & ana)) {
 			if (cap & MII_ANA_100M) {
 			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
@@ -2879,10 +2879,10 @@
 	    break;
 	}
 	break;
-	
+
     case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
         if (lp->timeout < 0) {
-	    lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS : 
+	    lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS :
 		                                  (~gep_rd(dev) & GEP_LNP));
 	    SET_100Mb_PDET;
 	}
@@ -2899,7 +2899,7 @@
 	    next_tick = dc21140m_autoconf(dev);
 	}
 	break;
-	
+
     case _100Mb:                               /* Set 100Mb/s */
         next_tick = 3000;
 	if (!lp->tx_enable) {
@@ -2933,7 +2933,7 @@
 	    }
 	}
 	break;
-	
+
     case NC:
         if (lp->media != lp->c_media) {
 	    de4x5_dbg_media(dev);
@@ -2943,7 +2943,7 @@
 	lp->tx_enable = FALSE;
 	break;
     }
-    
+
     return next_tick;
 }
 
@@ -3002,7 +3002,7 @@
 		lp->media = AUI;
 	    } else {
 		lp->media = SPD_DET;
-		if ((lp->infoblock_media == ANS) && 
+		if ((lp->infoblock_media == ANS) &&
 		                    ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
 		    ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
 		    ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
@@ -3014,7 +3014,7 @@
 	    next_tick = dc2114x_autoconf(dev);
         }
 	break;
-	
+
     case ANS:
 	switch (lp->local_state) {
 	case 0:
@@ -3034,7 +3034,7 @@
 		next_tick = dc2114x_autoconf(dev);
 	    }
 	    break;
-	    
+
 	case 1:
 	    if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
 		next_tick = sr & ~TIMER_CB;
@@ -3045,7 +3045,7 @@
 		    lp->tmp = MII_SR_ASSC;
 		    anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII);
 		    ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
-		    if (!(anlpa & MII_ANLPA_RF) && 
+		    if (!(anlpa & MII_ANLPA_RF) &&
 			 (cap = anlpa & MII_ANLPA_TAF & ana)) {
 			if (cap & MII_ANA_100M) {
 			    lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
@@ -3087,11 +3087,11 @@
 	    next_tick = 3000;
 	}
 	break;
-	
+
     case AUI_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc2114x_autoconf);
 	break;
-	
+
     case BNC:
 	switch (lp->local_state) {
 	case 0:
@@ -3109,7 +3109,7 @@
 		next_tick = dc2114x_autoconf(dev);
 	    }
 	    break;
-	    
+
 	case 1:
 	    if (!lp->tx_enable) {
 		if ((sts = ping_media(dev, 3000)) < 0) {
@@ -3130,11 +3130,11 @@
 	    break;
 	}
 	break;
-	
+
     case BNC_SUSPECT:
 	next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc2114x_autoconf);
 	break;
-	
+
     case SPD_DET:                              /* Choose 10Mb/s or 100Mb/s */
 	  if (srom_map_media(dev) < 0) {
 	      lp->tcount++;
@@ -3161,7 +3161,7 @@
 	      next_tick = dc2114x_autoconf(dev);
 	  } else if (((lp->media == _100Mb) && is_100_up(dev)) ||
 		     (((lp->media == _10Mb) || (lp->media == TP) ||
-		       (lp->media == BNC)   || (lp->media == AUI)) && 
+		       (lp->media == BNC)   || (lp->media == AUI)) &&
 		      is_10_up(dev))) {
 	      next_tick = dc2114x_autoconf(dev);
 	  } else {
@@ -3169,7 +3169,7 @@
 	      lp->media = INIT;
 	  }
 	  break;
-	
+
     case _10Mb:
         next_tick = 3000;
 	if (!lp->tx_enable) {
@@ -3208,7 +3208,7 @@
 	lp->media = INIT;
 	break;
     }
-    
+
     return next_tick;
 }
 
@@ -3231,7 +3231,7 @@
     struct de4x5_private *lp = netdev_priv(dev);
 
     lp->fdx = 0;
-    if (lp->infoblock_media == lp->media) 
+    if (lp->infoblock_media == lp->media)
       return 0;
 
     switch(lp->infoblock_media) {
@@ -3270,7 +3270,7 @@
       case SROM_100BASEFF:
 	if (!lp->params.fdx) return -1;
 	lp->fdx = TRUE;
-      case SROM_100BASEF: 
+      case SROM_100BASEF:
 	if (lp->params.fdx && !lp->fdx) return -1;
 	lp->media = _100Mb;
 	break;
@@ -3280,8 +3280,8 @@
 	lp->fdx = lp->params.fdx;
 	break;
 
-      default: 
-	printk("%s: Bad media code [%d] detected in SROM!\n", dev->name, 
+      default:
+	printk("%s: Bad media code [%d] detected in SROM!\n", dev->name,
 	                                                  lp->infoblock_media);
 	return -1;
 	break;
@@ -3359,7 +3359,7 @@
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 sts, csr12;
-    
+
     if (lp->timeout < 0) {
 	lp->timeout = msec/100;
 	if (!lp->useSROM) {      /* Already done if by SROM, else dc2104[01] */
@@ -3372,22 +3372,22 @@
 	/* clear all pending interrupts */
 	sts = inl(DE4X5_STS);
 	outl(sts, DE4X5_STS);
-	
+
 	/* clear csr12 NRA and SRA bits */
 	if ((lp->chipset == DC21041) || lp->useSROM) {
 	    csr12 = inl(DE4X5_SISR);
 	    outl(csr12, DE4X5_SISR);
 	}
     }
-    
+
     sts = inl(DE4X5_STS) & ~TIMER_CB;
-    
+
     if (!(sts & irqs) && --lp->timeout) {
 	sts = 100 | TIMER_CB;
     } else {
 	lp->timeout = -1;
     }
-    
+
     return sts;
 }
 
@@ -3397,11 +3397,11 @@
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     int sisr;
-    
+
     if (lp->timeout < 0) {
 	lp->timeout = msec/100;
     }
-    
+
     sisr = (inl(DE4X5_SISR) & ~TIMER_CB) & (SISR_LKF | SISR_NCR);
 
     if (sisr && --lp->timeout) {
@@ -3409,7 +3409,7 @@
     } else {
 	lp->timeout = -1;
     }
-    
+
     return sisr;
 }
 
@@ -3436,7 +3436,7 @@
 	    lp->timeout = msec/SAMPLE_INTERVAL;
 	}
     }
-    
+
     if (lp->phy[lp->active].id || lp->useSROM) {
 	gep = is_100_up(dev) | is_spd_100(dev);
     } else {
@@ -3447,7 +3447,7 @@
     } else {
 	lp->timeout = -1;
     }
-    
+
     return gep;
 }
 
@@ -3459,13 +3459,13 @@
     if (lp->timeout < 0) {
 	lp->timeout = 1;
     }
-    
+
     if (lp->timeout--) {
 	return TIMER_CB;
     } else {
 	lp->timeout = -1;
     }
-    
+
     return 0;
 }
 
@@ -3479,21 +3479,21 @@
     struct de4x5_private *lp = netdev_priv(dev);
     int test;
     u_long iobase = dev->base_addr;
-    
+
     if (lp->timeout < 0) {
 	lp->timeout = msec/100;
     }
-    
+
     if (pol) pol = ~0;
     reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
     test = (reg ^ pol) & mask;
-    
+
     if (test && --lp->timeout) {
 	reg = 100 | TIMER_CB;
     } else {
 	lp->timeout = -1;
     }
-    
+
     return reg;
 }
 
@@ -3503,7 +3503,7 @@
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     int spd;
-    
+
     if (lp->useMII) {
 	spd = mii_rd(lp->phy[lp->active].spd.reg, lp->phy[lp->active].addr, DE4X5_MII);
 	spd = ~(spd ^ lp->phy[lp->active].spd.value);
@@ -3517,7 +3517,7 @@
 	spd = (lp->asBitValid & (lp->asPolarity ^ (gep_rd(dev) & lp->asBit))) |
 	          (lp->linkOK & ~lp->asBitValid);
     }
-    
+
     return spd;
 }
 
@@ -3526,7 +3526,7 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (lp->useMII) {
 	/* Double read for sticky bits & temporary drops */
 	mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
@@ -3547,7 +3547,7 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (lp->useMII) {
 	/* Double read for sticky bits & temporary drops */
 	mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
@@ -3570,7 +3570,7 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
 	return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII));
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
@@ -3590,24 +3590,24 @@
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     int sisr;
-    
+
     if (lp->timeout < 0) {
 	lp->timeout = msec/100;
-	
+
 	lp->tmp = lp->tx_new;                /* Remember the ring position */
 	load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1);
 	lp->tx_new = (++lp->tx_new) % lp->txRingSize;
 	outl(POLL_DEMAND, DE4X5_TPD);
     }
-    
+
     sisr = inl(DE4X5_SISR);
 
-    if ((!(sisr & SISR_NCR)) && 
-	((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) && 
+    if ((!(sisr & SISR_NCR)) &&
+	((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) &&
 	 (--lp->timeout)) {
 	sisr = 100 | TIMER_CB;
     } else {
-	if ((!(sisr & SISR_NCR)) && 
+	if ((!(sisr & SISR_NCR)) &&
 	    !(le32_to_cpu(lp->tx_ring[lp->tmp].status) & (T_OWN | TD_ES)) &&
 	    lp->timeout) {
 	    sisr = 0;
@@ -3616,7 +3616,7 @@
 	}
 	lp->timeout = -1;
     }
-    
+
     return sisr;
 }
 
@@ -3668,7 +3668,7 @@
     } else {                                           /* Linear buffer */
 	memcpy(skb_put(p,len),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,len);
     }
-		    
+
     return p;
 #endif
 }
@@ -3751,23 +3751,23 @@
 	outl(lp->dma_rings, DE4X5_RRBA);
 	outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
 	     DE4X5_TRBA);
-    
+
 	lp->rx_new = lp->rx_old = 0;
 	lp->tx_new = lp->tx_old = 0;
-    
+
 	for (i = 0; i < lp->rxRingSize; i++) {
 	    lp->rx_ring[i].status = cpu_to_le32(R_OWN);
 	}
-    
+
 	for (i = 0; i < lp->txRingSize; i++) {
 	    lp->tx_ring[i].status = cpu_to_le32(0);
 	}
-    
+
 	barrier();
 	lp->cache.save_cnt--;
 	START_DE4X5;
     }
-        
+
     return;
 }
 
@@ -3792,7 +3792,7 @@
 	    gep_wr(lp->cache.gepc, dev);
 	    gep_wr(lp->cache.gep, dev);
 	} else {
-	    reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14, 
+	    reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14,
 			                                      lp->cache.csr15);
 	}
 	break;
@@ -3854,25 +3854,25 @@
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 sts, ans;
-    
+
     if (lp->timeout < 0) {
 	lp->timeout = msec/100;
 	outl(irq_mask, DE4X5_IMR);
-	
+
 	/* clear all pending interrupts */
 	sts = inl(DE4X5_STS);
 	outl(sts, DE4X5_STS);
     }
-    
+
     ans = inl(DE4X5_SISR) & SISR_ANS;
     sts = inl(DE4X5_STS) & ~TIMER_CB;
-    
+
     if (!(sts & irqs) && (ans ^ ANS_NWOK) && --lp->timeout) {
 	sts = 100 | TIMER_CB;
     } else {
 	lp->timeout = -1;
     }
-    
+
     return sts;
 }
 
@@ -3882,7 +3882,7 @@
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
     s32 imr, sts;
-    
+
     if (inl(DE4X5_OMR) & OMR_SR) {   /* Only unmask if TX/RX is enabled */
 	imr = 0;
 	UNMASK_IRQs;
@@ -3890,7 +3890,7 @@
 	outl(sts, DE4X5_STS);
 	ENABLE_IRQs;
     }
-    
+
     return;
 }
 
@@ -3936,17 +3936,17 @@
 {
     int i;
     char *buf = frame;
-    
+
     for (i=0; i<ETH_ALEN; i++) {             /* Use this source address */
 	*buf++ = dev->dev_addr[i];
     }
     for (i=0; i<ETH_ALEN; i++) {             /* Use this destination address */
 	*buf++ = dev->dev_addr[i];
     }
-    
+
     *buf++ = 0;                              /* Packet length (2 bytes) */
     *buf++ = 1;
-    
+
     return;
 }
 
@@ -3978,7 +3978,7 @@
 PCI_signature(char *name, struct de4x5_private *lp)
 {
     int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *);
-    
+
     if (lp->chipset == DC21040) {
 	strcpy(name, "DE434/5");
 	return status;
@@ -4007,7 +4007,7 @@
     } else if ((lp->chipset & ~0x00ff) == DC2114x) {
 	lp->useSROM = TRUE;
     }
-    
+
     return status;
 }
 
@@ -4024,7 +4024,7 @@
 {
     int i, j=0;
     struct de4x5_private *lp = netdev_priv(dev);
-    
+
     if (lp->chipset == DC21040) {
 	if (lp->bus == EISA) {
 	    enet_addr_rst(aprom_addr); /* Reset Ethernet Address ROM Pointer */
@@ -4049,7 +4049,7 @@
 	}
 	de4x5_dbg_srom((struct de4x5_srom *)&lp->srom);
     }
-    
+
     return;
 }
 
@@ -4071,11 +4071,11 @@
     short sigLength=0;
     s8 data;
     int i, j;
-    
+
     dev.llsig.a = ETH_PROM_SIG;
     dev.llsig.b = ETH_PROM_SIG;
     sigLength = sizeof(u32) << 1;
-    
+
     for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
 	data = inb(aprom_addr);
 	if (dev.Sig[j] == data) {    /* track signature */
@@ -4088,7 +4088,7 @@
 	    }
 	}
     }
-    
+
     return;
 }
 
@@ -4111,7 +4111,7 @@
     for (i=0,k=0,j=0;j<3;j++) {
 	k <<= 1;
 	if (k > 0xffff) k-=0xffff;
-	
+
 	if (lp->bus == PCI) {
 	    if (lp->chipset == DC21040) {
 		while ((tmp = inl(DE4X5_APROM)) < 0);
@@ -4133,11 +4133,11 @@
 	    k += (u_short) ((tmp = inb(EISA_APROM)) << 8);
 	    dev->dev_addr[i++] = (u_char) tmp;
 	}
-	
+
 	if (k > 0xffff) k-=0xffff;
     }
     if (k == 0xffff) k=0;
-    
+
     if (lp->bus == PCI) {
 	if (lp->chipset == DC21040) {
 	    while ((tmp = inl(DE4X5_APROM)) < 0);
@@ -4156,7 +4156,7 @@
     srom_repair(dev, broken);
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-    /* 
+    /*
     ** If the address starts with 00 a0, we have to bit-reverse
     ** each byte of the address.
     */
@@ -4245,7 +4245,7 @@
 
     for (tmp=0,i=0; i<ETH_ALEN; i++) tmp += (u_char)dev->dev_addr[i];
     if ((tmp == 0) || (tmp == 0x5fa)) {
-	if ((lp->chipset == last.chipset) && 
+	if ((lp->chipset == last.chipset) &&
 	    (lp->bus_num == last.bus) && (lp->bus_num > 0)) {
 	    for (i=0; i<ETH_ALEN; i++) dev->dev_addr[i] = last.addr[i];
 	    for (i=ETH_ALEN-1; i>2; --i) {
@@ -4275,7 +4275,7 @@
 static int
 an_exception(struct de4x5_private *lp)
 {
-    if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) && 
+    if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) &&
 	(*(u_short *)lp->srom.sub_system_id == 0x95e0)) {
 	return -1;
     }
@@ -4290,11 +4290,11 @@
 srom_rd(u_long addr, u_char offset)
 {
     sendto_srom(SROM_RD | SROM_SR, addr);
-    
+
     srom_latch(SROM_RD | SROM_SR | DT_CS, addr);
     srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr);
     srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset);
-    
+
     return srom_data(SROM_RD | SROM_SR | DT_CS, addr);
 }
 
@@ -4304,7 +4304,7 @@
     sendto_srom(command, addr);
     sendto_srom(command | DT_CLK, addr);
     sendto_srom(command, addr);
-    
+
     return;
 }
 
@@ -4314,7 +4314,7 @@
     srom_latch(command, addr);
     srom_latch(command, addr);
     srom_latch((command & 0x0000ff00) | DT_CS, addr);
-    
+
     return;
 }
 
@@ -4322,15 +4322,15 @@
 srom_address(u_int command, u_long addr, u_char offset)
 {
     int i, a;
-    
+
     a = offset << 2;
     for (i=0; i<6; i++, a <<= 1) {
 	srom_latch(command | ((a & 0x80) ? DT_IN : 0), addr);
     }
     udelay(1);
-    
+
     i = (getfrom_srom(addr) >> 3) & 0x01;
-    
+
     return;
 }
 
@@ -4340,17 +4340,17 @@
     int i;
     short word = 0;
     s32 tmp;
-    
+
     for (i=0; i<16; i++) {
 	sendto_srom(command  | DT_CLK, addr);
 	tmp = getfrom_srom(addr);
 	sendto_srom(command, addr);
-	
+
 	word = (word << 1) | ((tmp >> 3) & 0x01);
     }
-    
+
     sendto_srom(command & 0x0000ff00, addr);
-    
+
     return word;
 }
 
@@ -4359,13 +4359,13 @@
 srom_busy(u_int command, u_long addr)
 {
    sendto_srom((command & 0x0000ff00) | DT_CS, addr);
-   
+
    while (!((getfrom_srom(addr) >> 3) & 0x01)) {
        mdelay(1);
    }
-   
+
    sendto_srom(command & 0x0000ff00, addr);
-   
+
    return;
 }
 */
@@ -4375,7 +4375,7 @@
 {
     outl(command, addr);
     udelay(1);
-    
+
     return;
 }
 
@@ -4383,10 +4383,10 @@
 getfrom_srom(u_long addr)
 {
     s32 tmp;
-    
+
     tmp = inl(addr);
     udelay(1);
-    
+
     return tmp;
 }
 
@@ -4403,7 +4403,7 @@
     }
     if (i == INFOLEAF_SIZE) {
 	lp->useSROM = FALSE;
-	printk("%s: Cannot find correct chipset for SROM decoding!\n", 
+	printk("%s: Cannot find correct chipset for SROM decoding!\n",
 	                                                          dev->name);
 	return -ENXIO;
     }
@@ -4420,7 +4420,7 @@
 	}
 	if (i == 0) {
 	    lp->useSROM = FALSE;
-	    printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n", 
+	    printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
 	                                               dev->name, lp->device);
 	    return -ENXIO;
 	}
@@ -4494,9 +4494,9 @@
     if (((lp->ibn != 1) && (lp->ibn != 3) && (lp->ibn != 5)) || !count) return;
 
     if (lp->chipset != DC21140) RESET_SIA;
- 
+
     while (count--) {
-	gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ? 
+	gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ?
 		                                   *p++ : TWIDDLE(w++)), dev);
 	mdelay(2);                          /* 2ms per action */
     }
@@ -4514,13 +4514,13 @@
 ** unless I implement the DC21041 SROM functions. There's no need
 ** since the existing code will be satisfactory for all boards.
 */
-static int 
+static int
 dc21041_infoleaf(struct net_device *dev)
 {
     return DE4X5_AUTOSENSE_MS;
 }
 
-static int 
+static int
 dc21140_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4558,7 +4558,7 @@
     return next_tick & ~TIMER_CB;
 }
 
-static int 
+static int
 dc21142_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4593,7 +4593,7 @@
     return next_tick & ~TIMER_CB;
 }
 
-static int 
+static int
 dc21143_infoleaf(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4631,7 +4631,7 @@
 ** The compact infoblock is only designed for DC21140[A] chips, so
 ** we'll reuse the dc21140m_autoconf function. Non MII media only.
 */
-static int 
+static int
 compact_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4671,7 +4671,7 @@
 /*
 ** This block describes non MII media for the DC21140[A] only.
 */
-static int 
+static int
 type0_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4711,7 +4711,7 @@
 
 /* These functions are under construction! */
 
-static int 
+static int
 type1_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4750,7 +4750,7 @@
     return dc21140m_autoconf(dev);
 }
 
-static int 
+static int
 type2_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4791,7 +4791,7 @@
     return dc2114x_autoconf(dev);
 }
 
-static int 
+static int
 type3_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4833,7 +4833,7 @@
     return dc2114x_autoconf(dev);
 }
 
-static int 
+static int
 type4_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4878,7 +4878,7 @@
 ** This block type provides information for resetting external devices
 ** (chips) through the General Purpose Register.
 */
-static int 
+static int
 type5_infoblock(struct net_device *dev, u_char count, u_char *p)
 {
     struct de4x5_private *lp = netdev_priv(dev);
@@ -4916,7 +4916,7 @@
     mii_address(phyaddr, ioaddr);          /* PHY address to be accessed     */
     mii_address(phyreg, ioaddr);           /* PHY Register to read           */
     mii_ta(MII_STRD, ioaddr);              /* Turn around time - 2 MDC       */
-    
+
     return mii_rdata(ioaddr);              /* Read data                      */
 }
 
@@ -4931,7 +4931,7 @@
     mii_ta(MII_STWR, ioaddr);              /* Turn around time - 2 MDC       */
     data = mii_swap(data, 16);             /* Swap data bit ordering         */
     mii_wdata(data, 16, ioaddr);           /* Write data                     */
-    
+
     return;
 }
 
@@ -4940,12 +4940,12 @@
 {
     int i;
     s32 tmp = 0;
-    
+
     for (i=0; i<16; i++) {
 	tmp <<= 1;
 	tmp |= getfrom_mii(MII_MRD | MII_RD, ioaddr);
     }
-    
+
     return tmp;
 }
 
@@ -4953,12 +4953,12 @@
 mii_wdata(int data, int len, u_long ioaddr)
 {
     int i;
-    
+
     for (i=0; i<len; i++) {
 	sendto_mii(MII_MWR | MII_WR, data, ioaddr);
 	data >>= 1;
     }
-    
+
     return;
 }
 
@@ -4966,13 +4966,13 @@
 mii_address(u_char addr, u_long ioaddr)
 {
     int i;
-    
+
     addr = mii_swap(addr, 5);
     for (i=0; i<5; i++) {
 	sendto_mii(MII_MWR | MII_WR, addr, ioaddr);
 	addr >>= 1;
     }
-    
+
     return;
 }
 
@@ -4980,12 +4980,12 @@
 mii_ta(u_long rw, u_long ioaddr)
 {
     if (rw == MII_STWR) {
-	sendto_mii(MII_MWR | MII_WR, 1, ioaddr);  
-	sendto_mii(MII_MWR | MII_WR, 0, ioaddr);  
+	sendto_mii(MII_MWR | MII_WR, 1, ioaddr);
+	sendto_mii(MII_MWR | MII_WR, 0, ioaddr);
     } else {
 	getfrom_mii(MII_MRD | MII_RD, ioaddr);        /* Tri-state MDIO */
     }
-    
+
     return;
 }
 
@@ -4993,13 +4993,13 @@
 mii_swap(int data, int len)
 {
     int i, tmp = 0;
-    
+
     for (i=0; i<len; i++) {
 	tmp <<= 1;
 	tmp |= (data & 1);
 	data >>= 1;
     }
-    
+
     return tmp;
 }
 
@@ -5007,13 +5007,13 @@
 sendto_mii(u32 command, int data, u_long ioaddr)
 {
     u32 j;
-    
+
     j = (data & 1) << 17;
     outl(command | j, ioaddr);
     udelay(1);
     outl(command | MII_MDC | j, ioaddr);
     udelay(1);
-    
+
     return;
 }
 
@@ -5024,7 +5024,7 @@
     udelay(1);
     outl(command | MII_MDC, ioaddr);
     udelay(1);
-    
+
     return ((inl(ioaddr) >> 19) & 1);
 }
 
@@ -5085,7 +5085,7 @@
     u_long iobase = dev->base_addr;
     int i, j, k, n, limit=sizeof(phy_info)/sizeof(struct phy_table);
     int id;
-    
+
     lp->active = 0;
     lp->useMII = TRUE;
 
@@ -5094,7 +5094,7 @@
 	lp->phy[lp->active].addr = i;
 	if (i==0) n++;                             /* Count cycles */
 	while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */
-	id = mii_get_oui(i, DE4X5_MII); 
+	id = mii_get_oui(i, DE4X5_MII);
 	if ((id == 0) || (id == 65535)) continue;  /* Valid ID? */
 	for (j=0; j<limit; j++) {                  /* Search PHY table */
 	    if (id != phy_info[j].id) continue;    /* ID match? */
@@ -5133,7 +5133,7 @@
 	for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++) { /*For each PHY*/
 	    mii_wr(MII_CR_RST, MII_CR, lp->phy[k].addr, DE4X5_MII);
 	    while (mii_rd(MII_CR, lp->phy[k].addr, DE4X5_MII) & MII_CR_RST);
-	    
+
 	    de4x5_dbg_mii(dev, k);
 	}
     }
@@ -5148,12 +5148,12 @@
     struct de4x5_private *lp = netdev_priv(dev);
     int i;
     char *pa = lp->setup_frame;
-    
+
     /* Initialise the setup frame */
     if (mode == ALL) {
 	memset(lp->setup_frame, 0, SETUP_FRAME_LEN);
     }
-    
+
     if (lp->setup_f == HASH_PERF) {
 	for (pa=lp->setup_frame+IMPERF_PA_OFFSET, i=0; i<ETH_ALEN; i++) {
 	    *(pa + i) = dev->dev_addr[i];                 /* Host address */
@@ -5170,7 +5170,7 @@
 	    if (i & 0x01) pa += 4;
 	}
     }
-    
+
     return pa;                     /* Points to the next entry */
 }
 
@@ -5178,7 +5178,7 @@
 enable_ast(struct net_device *dev, u32 time_out)
 {
     timeout(dev, (void *)&de4x5_ast, (u_long)dev, time_out);
-    
+
     return;
 }
 
@@ -5186,9 +5186,9 @@
 disable_ast(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
-    
+
     del_timer(&lp->timer);
-    
+
     return;
 }
 
@@ -5207,10 +5207,10 @@
     omr |= lp->infoblock_csr6;
     if (omr & OMR_PS) omr |= OMR_HBD;
     outl(omr, DE4X5_OMR);
-    
+
     /* Soft Reset */
     RESET_DE4X5;
-    
+
     /* Restore the GEP - especially for COMPACT and Type 0 Infoblocks */
     if (lp->chipset == DC21140) {
 	gep_wr(lp->cache.gepc, dev);
@@ -5263,21 +5263,21 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int dt;
-    
+
     /* First, cancel any pending timer events */
     del_timer(&lp->timer);
-    
+
     /* Convert msec to ticks */
     dt = (msec * HZ) / 1000;
     if (dt==0) dt=1;
-    
+
     /* Set up timer */
     init_timer(&lp->timer);
     lp->timer.expires = jiffies + dt;
     lp->timer.function = fn;
     lp->timer.data = data;
     add_timer(&lp->timer);
-    
+
     return;
 }
 
@@ -5375,7 +5375,7 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     int i;
-    
+
     if (de4x5_debug & DEBUG_OPEN) {
 	printk("%s: de4x5 opening with irq %d\n",dev->name,dev->irq);
 	printk("\tphysical address: ");
@@ -5413,11 +5413,11 @@
 	    }
 	}
 	printk("...0x%8.8x\n", le32_to_cpu(lp->tx_ring[i].buf));
-	printk("Ring size: \nRX: %d\nTX: %d\n", 
-	       (short)lp->rxRingSize, 
-	       (short)lp->txRingSize); 
+	printk("Ring size: \nRX: %d\nTX: %d\n",
+	       (short)lp->rxRingSize,
+	       (short)lp->txRingSize);
     }
-    
+
     return;
 }
 
@@ -5426,7 +5426,7 @@
 {
     struct de4x5_private *lp = netdev_priv(dev);
     u_long iobase = dev->base_addr;
-    
+
     if (de4x5_debug & DEBUG_MII) {
 	printk("\nMII device address: %d\n", lp->phy[k].addr);
 	printk("MII CR:  %x\n",mii_rd(MII_CR,lp->phy[k].addr,DE4X5_MII));
@@ -5445,7 +5445,7 @@
 	    printk("MII 20:  %x\n",mii_rd(0x14,lp->phy[k].addr,DE4X5_MII));
 	}
     }
-    
+
     return;
 }
 
@@ -5453,17 +5453,17 @@
 de4x5_dbg_media(struct net_device *dev)
 {
     struct de4x5_private *lp = netdev_priv(dev);
-    
+
     if (lp->media != lp->c_media) {
 	if (de4x5_debug & DEBUG_MEDIA) {
 	    printk("%s: media is %s%s\n", dev->name,
 		   (lp->media == NC  ? "unconnected, link down or incompatible connection" :
 		    (lp->media == TP  ? "TP" :
 		     (lp->media == ANS ? "TP/Nway" :
-		      (lp->media == BNC ? "BNC" : 
-		       (lp->media == AUI ? "AUI" : 
-			(lp->media == BNC_AUI ? "BNC/AUI" : 
-			 (lp->media == EXT_SIA ? "EXT SIA" : 
+		      (lp->media == BNC ? "BNC" :
+		       (lp->media == AUI ? "AUI" :
+			(lp->media == BNC_AUI ? "BNC/AUI" :
+			 (lp->media == EXT_SIA ? "EXT SIA" :
 			  (lp->media == _100Mb  ? "100Mb/s" :
 			   (lp->media == _10Mb   ? "10Mb/s" :
 			    "???"
@@ -5471,7 +5471,7 @@
 	}
 	lp->c_media = lp->media;
     }
-    
+
     return;
 }
 
@@ -5554,7 +5554,7 @@
 	u32 lval[36];
     } tmp;
     u_long flags = 0;
-    
+
     switch(ioc->cmd) {
     case DE4X5_GET_HWADDR:           /* Get the hardware address */
 	ioc->len = ETH_ALEN;
@@ -5575,7 +5575,7 @@
 	}
 	build_setup_frame(dev, PHYS_ADDR_ONLY);
 	/* Set up the descriptor and give ownership to the card */
-	load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET | 
+	load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
 		                                       SETUP_FRAME_LEN, (struct sk_buff *)1);
 	lp->tx_new = (++lp->tx_new) % lp->txRingSize;
 	outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
@@ -5617,8 +5617,8 @@
 	spin_lock_irqsave(&lp->lock, flags);
 	memcpy(&statbuf, &lp->pktStats, ioc->len);
 	spin_unlock_irqrestore(&lp->lock, flags);
-	if (copy_to_user(ioc->data, &statbuf, ioc->len)) 
-		return -EFAULT; 
+	if (copy_to_user(ioc->data, &statbuf, ioc->len))
+		return -EFAULT;
 	break;
     }
     case DE4X5_CLR_STATS:            /* Zero out the driver statistics */
@@ -5652,9 +5652,9 @@
 	ioc->len = j;
 	if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
 	break;
-	
+
 #define DE4X5_DUMP              0x0f /* Dump the DE4X5 Status */
-/*	
+/*
       case DE4X5_DUMP:
 	j = 0;
 	tmp.addr[j++] = dev->irq;
@@ -5664,7 +5664,7 @@
 	tmp.addr[j++] = lp->rxRingSize;
 	tmp.lval[j>>2] = (long)lp->rx_ring; j+=4;
 	tmp.lval[j>>2] = (long)lp->tx_ring; j+=4;
-	
+
 	for (i=0;i<lp->rxRingSize-1;i++){
 	    if (i < 3) {
 		tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4;
@@ -5677,7 +5677,7 @@
 	    }
 	}
 	tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4;
-	
+
 	for (i=0;i<lp->rxRingSize-1;i++){
 	    if (i < 3) {
 		tmp.lval[j>>2] = (s32)le32_to_cpu(lp->rx_ring[i].buf); j+=4;
@@ -5690,14 +5690,14 @@
 	    }
 	}
 	tmp.lval[j>>2] = (s32)le32_to_cpu(lp->tx_ring[i].buf); j+=4;
-	
+
 	for (i=0;i<lp->rxRingSize;i++){
 	    tmp.lval[j>>2] = le32_to_cpu(lp->rx_ring[i].status); j+=4;
 	}
 	for (i=0;i<lp->txRingSize;i++){
 	    tmp.lval[j>>2] = le32_to_cpu(lp->tx_ring[i].status); j+=4;
 	}
-	
+
 	tmp.lval[j>>2] = inl(DE4X5_BMR);  j+=4;
 	tmp.lval[j>>2] = inl(DE4X5_TPD);  j+=4;
 	tmp.lval[j>>2] = inl(DE4X5_RPD);  j+=4;
@@ -5706,18 +5706,18 @@
 	tmp.lval[j>>2] = inl(DE4X5_STS);  j+=4;
 	tmp.lval[j>>2] = inl(DE4X5_OMR);  j+=4;
 	tmp.lval[j>>2] = inl(DE4X5_IMR);  j+=4;
-	tmp.lval[j>>2] = lp->chipset; j+=4; 
+	tmp.lval[j>>2] = lp->chipset; j+=4;
 	if (lp->chipset == DC21140) {
 	    tmp.lval[j>>2] = gep_rd(dev);  j+=4;
 	} else {
 	    tmp.lval[j>>2] = inl(DE4X5_SISR); j+=4;
 	    tmp.lval[j>>2] = inl(DE4X5_SICR); j+=4;
 	    tmp.lval[j>>2] = inl(DE4X5_STRR); j+=4;
-	    tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4; 
+	    tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4;
 	}
-	tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4; 
+	tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4;
 	if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
-	    tmp.lval[j>>2] = lp->active; j+=4; 
+	    tmp.lval[j>>2] = lp->active; j+=4;
 	    tmp.lval[j>>2]=mii_rd(MII_CR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
 	    tmp.lval[j>>2]=mii_rd(MII_SR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
 	    tmp.lval[j>>2]=mii_rd(MII_ID0,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
@@ -5734,10 +5734,10 @@
 		tmp.lval[j>>2]=mii_rd(0x14,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
 	    }
 	}
-	
+
 	tmp.addr[j++] = lp->txRingSize;
 	tmp.addr[j++] = netif_queue_stopped(dev);
-	
+
 	ioc->len = j;
 	if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
 	break;
@@ -5746,7 +5746,7 @@
     default:
 	return -EOPNOTSUPP;
     }
-    
+
     return status;
 }
 
diff --git a/drivers/net/tulip/de4x5.h b/drivers/net/tulip/de4x5.h
index ad37a40..57226e5 100644
--- a/drivers/net/tulip/de4x5.h
+++ b/drivers/net/tulip/de4x5.h
@@ -38,11 +38,11 @@
 /*
 ** EISA Register Address Map
 */
-#define EISA_ID      iobase+0x0c80   /* EISA ID Registers */ 
-#define EISA_ID0     iobase+0x0c80   /* EISA ID Register 0 */ 
-#define EISA_ID1     iobase+0x0c81   /* EISA ID Register 1 */ 
-#define EISA_ID2     iobase+0x0c82   /* EISA ID Register 2 */ 
-#define EISA_ID3     iobase+0x0c83   /* EISA ID Register 3 */ 
+#define EISA_ID      iobase+0x0c80   /* EISA ID Registers */
+#define EISA_ID0     iobase+0x0c80   /* EISA ID Register 0 */
+#define EISA_ID1     iobase+0x0c81   /* EISA ID Register 1 */
+#define EISA_ID2     iobase+0x0c82   /* EISA ID Register 2 */
+#define EISA_ID3     iobase+0x0c83   /* EISA ID Register 3 */
 #define EISA_CR      iobase+0x0c84   /* EISA Control Register */
 #define EISA_REG0    iobase+0x0c88   /* EISA Configuration Register 0 */
 #define EISA_REG1    iobase+0x0c89   /* EISA Configuration Register 1 */
@@ -1008,8 +1008,8 @@
 	unsigned char  __user *data;       /* Pointer to the data buffer */
 };
 
-/* 
-** Recognised commands for the driver 
+/*
+** Recognised commands for the driver
 */
 #define DE4X5_GET_HWADDR	0x01 /* Get the hardware address */
 #define DE4X5_SET_HWADDR	0x02 /* Set the hardware address */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index 74e9075..ba5b112 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -50,7 +50,7 @@
     forget to unmap PCI mapped skbs.
 
     Alan Cox <alan@redhat.com>
-    Added new PCI identifiers provided by Clear Zhang at ALi 
+    Added new PCI identifiers provided by Clear Zhang at ALi
     for their 1563 ethernet device.
 
     TODO
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
index fbd9ab6..5ffbd5b 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/tulip/eeprom.c
@@ -96,11 +96,11 @@
  * tulip_build_fake_mediatable - Build a fake mediatable entry.
  * @tp: Ptr to the tulip private data.
  *
- * Some cards like the 3x5 HSC cards (J3514A) do not have a standard 
+ * Some cards like the 3x5 HSC cards (J3514A) do not have a standard
  * srom and can not be handled under the fixup routine.  These cards
- * still need a valid mediatable entry for correct csr12 setup and 
+ * still need a valid mediatable entry for correct csr12 setup and
  * mii handling.
- * 
+ *
  * Since this is currently a parisc-linux specific function, the
  * #ifdef __hppa__ should completely optimize this function away for
  * non-parisc hardware.
@@ -140,7 +140,7 @@
 		tp->flags |= HAS_PHY_IRQ;
 		tp->csr12_shadow = -1;
 	}
-#endif 
+#endif
 }
 
 void __devinit tulip_parse_eeprom(struct net_device *dev)
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index bb35581..da4f759 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -139,22 +139,22 @@
 		}
                /* Acknowledge current RX interrupt sources. */
                iowrite32((RxIntr | RxNoBuf), tp->base_addr + CSR5);
- 
- 
+
+
                /* If we own the next entry, it is a new packet. Send it up. */
                while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
                        s32 status = le32_to_cpu(tp->rx_ring[entry].status);
- 
- 
+
+
                        if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
                                break;
- 
+
                        if (tulip_debug > 5)
                                printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
                                       dev->name, entry, status);
                        if (--rx_work_limit < 0)
                                goto not_done;
- 
+
                        if ((status & 0x38008300) != 0x0300) {
                                if ((status & 0x38000300) != 0x0300) {
                                 /* Ingore earlier buffers. */
@@ -180,7 +180,7 @@
                                /* Omit the four octet CRC from the length. */
                                short pkt_len = ((status >> 16) & 0x7ff) - 4;
                                struct sk_buff *skb;
-  
+
 #ifndef final_version
                                if (pkt_len > 1518) {
                                        printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
@@ -213,7 +213,7 @@
                                } else {        /* Pass up the skb already on the Rx ring. */
                                        char *temp = skb_put(skb = tp->rx_buffers[entry].skb,
                                                             pkt_len);
-  
+
 #ifndef final_version
                                        if (tp->rx_buffers[entry].mapping !=
                                            le32_to_cpu(tp->rx_ring[entry].buffer1)) {
@@ -225,17 +225,17 @@
                                                       skb->head, temp);
                                        }
 #endif
-  
+
                                        pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping,
                                                         PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
-  
+
                                        tp->rx_buffers[entry].skb = NULL;
                                        tp->rx_buffers[entry].mapping = 0;
                                }
                                skb->protocol = eth_type_trans(skb, dev);
-  
+
                                netif_receive_skb(skb);
- 
+
                                dev->last_rx = jiffies;
                                tp->stats.rx_packets++;
                                tp->stats.rx_bytes += pkt_len;
@@ -245,12 +245,12 @@
                        entry = (++tp->cur_rx) % RX_RING_SIZE;
                        if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/4)
                                tulip_refill_rx(dev);
- 
+
                 }
- 
+
                /* New ack strategy... irq does not ack Rx any longer
                   hopefully this helps */
- 
+
                /* Really bad things can happen here... If new packet arrives
                 * and an irq arrives (tx or just due to occasionally unset
                 * mask), it will be acked by irq handler, but new thread
@@ -259,28 +259,28 @@
                 * tomorrow (night 011029). If it will not fail, we won
                 * finally: amount of IO did not increase at all. */
        } while ((ioread32(tp->base_addr + CSR5) & RxIntr));
- 
+
 done:
- 
+
  #ifdef CONFIG_TULIP_NAPI_HW_MITIGATION
-  
+
           /* We use this simplistic scheme for IM. It's proven by
              real life installations. We can have IM enabled
-            continuesly but this would cause unnecessary latency. 
-            Unfortunely we can't use all the NET_RX_* feedback here. 
-            This would turn on IM for devices that is not contributing 
-            to backlog congestion with unnecessary latency. 
-  
+            continuesly but this would cause unnecessary latency.
+            Unfortunely we can't use all the NET_RX_* feedback here.
+            This would turn on IM for devices that is not contributing
+            to backlog congestion with unnecessary latency.
+
              We monitor the the device RX-ring and have:
-  
+
              HW Interrupt Mitigation either ON or OFF.
-  
-            ON:  More then 1 pkt received (per intr.) OR we are dropping 
+
+            ON:  More then 1 pkt received (per intr.) OR we are dropping
              OFF: Only 1 pkt received
-            
+
              Note. We only use min and max (0, 15) settings from mit_table */
-  
-  
+
+
           if( tp->flags &  HAS_INTR_MITIGATION) {
                  if( received > 1 ) {
                          if( ! tp->mit_on ) {
@@ -297,20 +297,20 @@
           }
 
 #endif /* CONFIG_TULIP_NAPI_HW_MITIGATION */
- 
+
          dev->quota -= received;
          *budget -= received;
- 
+
          tulip_refill_rx(dev);
-         
+
          /* If RX ring is not full we are out of memory. */
          if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
- 
+
          /* Remove us from polling list and enable RX intr. */
- 
+
          netif_rx_complete(dev);
          iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7);
- 
+
          /* The last op happens after poll completion. Which means the following:
           * 1. it can race with disabling irqs in irq handler
           * 2. it can race with dise/enabling irqs in other poll threads
@@ -321,9 +321,9 @@
           * due to races in masking and due to too late acking of already
           * processed irqs. But it must not result in losing events.
           */
- 
+
          return 0;
- 
+
  not_done:
          if (!received) {
 
@@ -331,29 +331,29 @@
          }
          dev->quota -= received;
          *budget -= received;
- 
+
          if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
              tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
                  tulip_refill_rx(dev);
- 
+
          if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) goto oom;
- 
+
          return 1;
- 
- 
+
+
  oom:    /* Executed with RX ints disabled */
- 
-         
+
+
          /* Start timer, stop polling, but do not enable rx interrupts. */
          mod_timer(&tp->oom_timer, jiffies+1);
-       
+
          /* Think: timer_pending() was an explicit signature of bug.
           * Timer can be pending now but fired and completed
           * before we did netif_rx_complete(). See? We would lose it. */
- 
+
          /* remove ourselves from the polling list */
          netif_rx_complete(dev);
- 
+
          return 0;
 }
 
@@ -521,9 +521,9 @@
 	/* Let's see whether the interrupt really is for us */
 	csr5 = ioread32(ioaddr + CSR5);
 
-        if (tp->flags & HAS_PHY_IRQ) 
+        if (tp->flags & HAS_PHY_IRQ)
 	        handled = phy_interrupt (dev);
-    
+
 	if ((csr5 & (NormalIntr|AbnormalIntr)) == 0)
 		return IRQ_RETVAL(handled);
 
@@ -538,17 +538,17 @@
 			/* Mask RX intrs and add the device to poll list. */
 			iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
 			netif_rx_schedule(dev);
-			
+
 			if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
                                break;
 		}
-		
+
                /* Acknowledge the interrupt sources we handle here ASAP
                   the poll function does Rx and RxNoBuf acking */
-		
+
 		iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5);
 
-#else 
+#else
 		/* Acknowledge all of the current interrupt sources ASAP. */
 		iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5);
 
@@ -559,11 +559,11 @@
 		}
 
 #endif /*  CONFIG_TULIP_NAPI */
-		
+
 		if (tulip_debug > 4)
 			printk(KERN_DEBUG "%s: interrupt  csr5=%#8.8x new csr5=%#8.8x.\n",
 			       dev->name, csr5, ioread32(ioaddr + CSR5));
-		
+
 
 		if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) {
 			unsigned int dirty_tx;
@@ -737,17 +737,17 @@
 #ifdef CONFIG_TULIP_NAPI
 		if (rxd)
 			csr5 &= ~RxPollInt;
-	} while ((csr5 & (TxNoBuf | 
-			  TxDied | 
-			  TxIntr | 
+	} while ((csr5 & (TxNoBuf |
+			  TxDied |
+			  TxIntr |
 			  TimerInt |
 			  /* Abnormal intr. */
-			  RxDied | 
-			  TxFIFOUnderflow | 
-			  TxJabber | 
-			  TPLnkFail |  
+			  RxDied |
+			  TxFIFOUnderflow |
+			  TxJabber |
+			  TPLnkFail |
 			  SytemError )) != 0);
-#else 
+#else
 	} while ((csr5 & (NormalIntr|AbnormalIntr)) != 0);
 
 	tulip_refill_rx(dev);
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index f53396f..e9bc2a9 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -140,7 +140,7 @@
 		spin_unlock_irqrestore(&tp->mii_lock, flags);
 		return;
 	}
-		
+
 	/* Establish sync by sending 32 logic ones. */
 	for (i = 32; i >= 0; i--) {
 		iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 05d2d96..d25020d 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -259,7 +259,7 @@
    There are no ill effects from too-large receive rings. */
 
 #define TX_RING_SIZE	32
-#define RX_RING_SIZE	128 
+#define RX_RING_SIZE	128
 #define MEDIA_MASK     31
 
 #define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index c67c912..e0de667 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1224,7 +1224,7 @@
  *	Chips that have the MRM/reserved bit quirk and the burst quirk. That
  *	is the DM910X and the on chip ULi devices
  */
- 
+
 static int tulip_uli_dm_quirk(struct pci_dev *pdev)
 {
 	if (pdev->vendor == 0x1282 && pdev->device == 0x9102)
@@ -1297,7 +1297,7 @@
 	 */
 
 	/* 1. Intel Saturn. Switch to 8 long words burst, 8 long word cache
-	      aligned.  Aries might need this too. The Saturn errata are not 
+	      aligned.  Aries might need this too. The Saturn errata are not
 	      pretty reading but thankfully it's an old 486 chipset.
 
 	   2. The dreaded SiS496 486 chipset. Same workaround as Intel
@@ -1483,14 +1483,6 @@
 			sa_offset = 2;		/* Grrr, damn Matrox boards. */
 			multiport_cnt = 4;
 		}
-#ifdef CONFIG_DDB5476
-		if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 6)) {
-			/* DDB5476 MAC address in first EEPROM locations. */
-                       sa_offset = 0;
-                       /* No media table either */
-                       tp->flags &= ~HAS_MEDIA_TABLE;
-               }
-#endif
 #ifdef CONFIG_DDB5477
                if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) {
                        /* DDB5477 MAC address in first EEPROM locations. */
@@ -1500,7 +1492,7 @@
                }
 #endif
 #ifdef CONFIG_MIPS_COBALT
-               if ((pdev->bus->number == 0) && 
+               if ((pdev->bus->number == 0) &&
                    ((PCI_SLOT(pdev->devfn) == 7) ||
                     (PCI_SLOT(pdev->devfn) == 12))) {
                        /* Cobalt MAC address in first EEPROM locations. */
@@ -1558,10 +1550,14 @@
 			dev->dev_addr[i] = last_phys_addr[i];
 		dev->dev_addr[i] = last_phys_addr[i] + 1;
 #if defined(__sparc__)
-		if ((pcp != NULL) && prom_getproplen(pcp->prom_node,
-			"local-mac-address") == 6) {
-			prom_getproperty(pcp->prom_node, "local-mac-address",
-			    dev->dev_addr, 6);
+		if (pcp) {
+			unsigned char *addr;
+			int len;
+		  
+			addr = of_get_property(pcp->prom_node,
+					       "local-mac-address", &len);
+			if (addr && len == 6)
+				memcpy(dev->dev_addr, addr, 6);
 		}
 #endif
 #if defined(__i386__) || defined(__x86_64__)	/* Patch up x86 BIOS bug. */
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index 238e9c7..8b3a28f 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -9,7 +9,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    
+
 */
 
 #define DRV_NAME	"uli526x"
@@ -185,7 +185,7 @@
 
 	/* NIC SROM data */
 	unsigned char srom[128];
-	u8 init;	
+	u8 init;
 };
 
 enum uli526x_offsets {
@@ -258,7 +258,7 @@
 	struct uli526x_board_info *db;	/* board information structure */
 	struct net_device *dev;
 	int i, err;
-	
+
 	ULI526X_DBUG(0, "uli526x_init_one()", 0);
 
 	if (!printed_version++)
@@ -316,7 +316,7 @@
 		err = -ENOMEM;
 		goto err_out_nomem;
 	}
-	
+
 	db->first_tx_desc = (struct tx_desc *) db->desc_pool_ptr;
 	db->first_tx_desc_dma = db->desc_pool_dma_ptr;
 	db->buf_pool_start = db->buf_pool_ptr;
@@ -324,14 +324,14 @@
 
 	db->chip_id = ent->driver_data;
 	db->ioaddr = pci_resource_start(pdev, 0);
-	
+
 	db->pdev = pdev;
 	db->init = 1;
-	
+
 	dev->base_addr = db->ioaddr;
 	dev->irq = pdev->irq;
 	pci_set_drvdata(pdev, dev);
-	
+
 	/* Register some necessary functions */
 	dev->open = &uli526x_open;
 	dev->hard_start_xmit = &uli526x_start_xmit;
@@ -341,7 +341,7 @@
 	dev->ethtool_ops = &netdev_ethtool_ops;
 	spin_lock_init(&db->lock);
 
-		
+
 	/* read 64 word srom data */
 	for (i = 0; i < 64; i++)
 		((u16 *) db->srom)[i] = cpu_to_le16(read_srom_word(db->ioaddr, i));
@@ -374,7 +374,7 @@
 		goto err_out_res;
 
 	printk(KERN_INFO "%s: ULi M%04lx at pci%s,",dev->name,ent->driver_data >> 16,pci_name(pdev));
-	
+
 	for (i = 0; i < 6; i++)
 		printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
 	printk(", irq %d.\n", dev->irq);
@@ -389,7 +389,7 @@
 	if(db->desc_pool_ptr)
 		pci_free_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20,
 			db->desc_pool_ptr, db->desc_pool_dma_ptr);
-			
+
 	if(db->buf_pool_ptr != NULL)
 		pci_free_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4,
 			db->buf_pool_ptr, db->buf_pool_dma_ptr);
@@ -433,7 +433,7 @@
 {
 	int ret;
 	struct uli526x_board_info *db = netdev_priv(dev);
-	
+
 	ULI526X_DBUG(0, "uli526x_open", 0);
 
 	ret = request_irq(dev->irq, &uli526x_interrupt, SA_SHIRQ, dev->name, dev);
@@ -454,7 +454,7 @@
 	/* CR6 operation mode decision */
 	db->cr6_data |= ULI526X_TXTH_256;
 	db->cr0_data = CR0_DEFAULT;
-	
+
 	/* Initialize ULI526X board */
 	uli526x_init(dev);
 
@@ -604,7 +604,7 @@
 	/* Restore CR7 to enable interrupt */
 	spin_unlock_irqrestore(&db->lock, flags);
 	outl(db->cr7_data, dev->base_addr + DCR7);
-	
+
 	/* free this SKB */
 	dev_kfree_skb(skb);
 
@@ -782,7 +782,7 @@
 	struct sk_buff *skb;
 	int rxlen;
 	u32 rdes0;
-	
+
 	rxptr = db->rx_ready_ptr;
 
 	while(db->rx_avail_cnt) {
@@ -821,7 +821,7 @@
 			if ( !(rdes0 & 0x8000) ||
 				((db->cr6_data & CR6_PM) && (rxlen>6)) ) {
 				skb = rxptr->rx_skb_ptr;
-		
+
 				/* Good packet, send to upper layer */
 				/* Shorst packet used new SKB */
 				if ( (rxlen < RX_COPY_SIZE) &&
@@ -841,7 +841,7 @@
 				dev->last_rx = jiffies;
 				db->stats.rx_packets++;
 				db->stats.rx_bytes += rxlen;
-				
+
 			} else {
 				/* Reuse SKB buffer when the packet is error */
 				ULI526X_DBUG(0, "Reuse SK buffer, rdes0", rdes0);
@@ -911,7 +911,7 @@
 	                   SUPPORTED_100baseT_Full |
 	                   SUPPORTED_Autoneg |
 	                   SUPPORTED_MII);
-		
+
 	ecmd->advertising = (ADVERTISED_10baseT_Half |
 	                   ADVERTISED_10baseT_Full |
 	                   ADVERTISED_100baseT_Half |
@@ -924,13 +924,13 @@
 	ecmd->phy_address = db->phy_addr;
 
 	ecmd->transceiver = XCVR_EXTERNAL;
-		
+
 	ecmd->speed = 10;
 	ecmd->duplex = DUPLEX_HALF;
-	
+
 	if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
 	{
-		ecmd->speed = 100;               
+		ecmd->speed = 100;
 	}
 	if(db->op_mode==ULI526X_10MFD || db->op_mode==ULI526X_100MFD)
 	{
@@ -939,11 +939,11 @@
 	if(db->link_failed)
 	{
 		ecmd->speed = -1;
-		ecmd->duplex = -1;	
+		ecmd->duplex = -1;
 	}
-	
+
 	if (db->media_mode & ULI526X_AUTO)
-	{	
+	{
 		ecmd->autoneg = AUTONEG_ENABLE;
 	}
 }
@@ -964,15 +964,15 @@
 
 static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) {
 	struct uli526x_board_info *np = netdev_priv(dev);
-	
+
 	ULi_ethtool_gset(np, cmd);
-	
+
 	return 0;
 }
 
 static u32 netdev_get_link(struct net_device *dev) {
 	struct uli526x_board_info *np = netdev_priv(dev);
-		
+
 	if(np->link_failed)
 		return 0;
 	else
@@ -1005,11 +1005,11 @@
 	struct uli526x_board_info *db = netdev_priv(dev);
  	unsigned long flags;
 	u8 TmpSpeed=10;
-	
+
 	//ULI526X_DBUG(0, "uli526x_timer()", 0);
 	spin_lock_irqsave(&db->lock, flags);
 
-	
+
 	/* Dynamic reset ULI526X : system error or transmit time-out */
 	tmp_cr8 = inl(db->ioaddr + DCR8);
 	if ( (db->interval_rx_cnt==0) && (tmp_cr8) ) {
@@ -1021,9 +1021,9 @@
 	/* TX polling kick monitor */
 	if ( db->tx_packet_cnt &&
 	     time_after(jiffies, dev->trans_start + ULI526X_TX_KICK) ) {
-		outl(0x1, dev->base_addr + DCR1);   // Tx polling again 
+		outl(0x1, dev->base_addr + DCR1);   // Tx polling again
 
-		// TX Timeout 
+		// TX Timeout
 		if ( time_after(jiffies, dev->trans_start + ULI526X_TX_TIMEOUT) ) {
 			db->reset_TXtimeout++;
 			db->wait_reset = 1;
@@ -1073,7 +1073,7 @@
 				uli526x_sense_speed(db) )
 				db->link_failed = 1;
 			uli526x_process_mode(db);
-			
+
 			if(db->link_failed==0)
 			{
 				if(db->op_mode==ULI526X_100MHF || db->op_mode==ULI526X_100MFD)
@@ -1404,7 +1404,7 @@
 	phy_mode = phy_read(db->ioaddr, db->phy_addr, 1, db->chip_id);
 
 	if ( (phy_mode & 0x24) == 0x24 ) {
-		
+
 		phy_mode = ((phy_read(db->ioaddr, db->phy_addr, 5, db->chip_id) & 0x01e0)<<7);
 		if(phy_mode&0x8000)
 			phy_mode = 0x8000;
@@ -1414,7 +1414,7 @@
 			phy_mode = 0x2000;
 		else
 			phy_mode = 0x1000;
-		
+
 		/* printk(DRV_NAME ": Phy_mode %x ",phy_mode); */
 		switch (phy_mode) {
 		case 0x1000: db->op_mode = ULI526X_10MHF; break;
@@ -1442,7 +1442,7 @@
 static void uli526x_set_phyxcer(struct uli526x_board_info *db)
 {
 	u16 phy_reg;
-	
+
 	/* Phyxcer capability setting */
 	phy_reg = phy_read(db->ioaddr, db->phy_addr, 4, db->chip_id) & ~0x01e0;
 
@@ -1457,7 +1457,7 @@
 		case ULI526X_100MHF: phy_reg |= 0x80; break;
 		case ULI526X_100MFD: phy_reg |= 0x100; break;
 		}
-		
+
 	}
 
   	/* Write new capability to Phyxcer Reg4 */
@@ -1556,7 +1556,7 @@
 	/* Write a word data to PHY controller */
 	for ( i = 0x8000; i > 0; i >>= 1)
 		phy_write_1bit(ioaddr, phy_data & i ? PHY_DATA_1 : PHY_DATA_0, chip_id);
-	
+
 }
 
 
@@ -1574,7 +1574,7 @@
 		return phy_readby_cr10(iobase, phy_addr, offset);
 	/* M5261/M5263 Chip */
 	ioaddr = iobase + DCR9;
-	
+
 	/* Send 33 synchronization clock to Phy controller */
 	for (i = 0; i < 35; i++)
 		phy_write_1bit(ioaddr, PHY_DATA_1, chip_id);
@@ -1610,7 +1610,7 @@
 static u16 phy_readby_cr10(unsigned long iobase, u8 phy_addr, u8 offset)
 {
 	unsigned long ioaddr,cr10_value;
-	
+
 	ioaddr = iobase + DCR10;
 	cr10_value = phy_addr;
 	cr10_value = (cr10_value<<5) + offset;
@@ -1629,7 +1629,7 @@
 static void phy_writeby_cr10(unsigned long iobase, u8 phy_addr, u8 offset, u16 phy_data)
 {
 	unsigned long ioaddr,cr10_value;
-	
+
 	ioaddr = iobase + DCR10;
 	cr10_value = phy_addr;
 	cr10_value = (cr10_value<<5) + offset;
@@ -1659,7 +1659,7 @@
 static u16 phy_read_1bit(unsigned long ioaddr, u32 chip_id)
 {
 	u16 phy_data;
-	
+
 	outl(0x50000 , ioaddr);
 	udelay(1);
 	phy_data = ( inl(ioaddr) >> 19 ) & 0x1;
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 136a70c..602a6e5 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -38,12 +38,12 @@
 			Copyright (C) 2001 Manfred Spraul
   	* ethtool support (jgarzik)
 	* Replace some MII-related magic numbers with constants (jgarzik)
-  
+
 	TODO:
 	* enable pci_power_off
 	* Wake-On-LAN
 */
-  
+
 #define DRV_NAME	"winbond-840"
 #define DRV_VERSION	"1.01-d"
 #define DRV_RELDATE	"Nov-17-2001"
@@ -57,7 +57,7 @@
 c-help-symbol: CONFIG_WINBOND_840
 c-help: This driver is for the Winbond W89c840 chip.  It also works with
 c-help: the TX9882 chip on the Compex RL100-ATX board.
-c-help: More specific information and updates are available from 
+c-help: More specific information and updates are available from
 c-help: http://www.scyld.com/network/drivers.html
 */
 
@@ -207,31 +207,20 @@
 
 */
 
-
+
 
 /*
   PCI probe table.
 */
-enum pci_id_flags_bits {
-        /* Set PCI command register bits before calling probe1(). */
-        PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-        /* Read and map the single following PCI BAR. */
-        PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
-        PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
-};
 enum chip_capability_flags {
-	CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8,};
-#ifdef USE_IO_OPS
-#define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
-#else
-#define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
-#endif
+	CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8,
+};
 
-static struct pci_device_id w840_pci_tbl[] = {
+static const struct pci_device_id w840_pci_tbl[] = {
 	{ 0x1050, 0x0840, PCI_ANY_ID, 0x8153,     0, 0, 0 },
 	{ 0x1050, 0x0840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
 	{ 0x11f6, 0x2011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
-	{ 0, }
+	{ }
 };
 MODULE_DEVICE_TABLE(pci, w840_pci_tbl);
 
@@ -241,18 +230,17 @@
                 int     pci, pci_mask, subsystem, subsystem_mask;
                 int revision, revision_mask;                            /* Only 8 bits. */
         } id;
-        enum pci_id_flags_bits pci_flags;
         int io_size;                            /* Needed for I/O region check or ioremap(). */
         int drv_flags;                          /* Driver use, intended as capability flags. */
 };
 static struct pci_id_info pci_id_tbl[] = {
 	{"Winbond W89c840",			/* Sometime a Level-One switch card. */
 	 { 0x08401050, 0xffffffff, 0x81530000, 0xffff0000 },
-	 W840_FLAGS, 128, CanHaveMII | HasBrokenTx | FDXOnNoMII},
+	   128, CanHaveMII | HasBrokenTx | FDXOnNoMII},
 	{"Winbond W89c840", { 0x08401050, 0xffffffff, },
-	 W840_FLAGS, 128, CanHaveMII | HasBrokenTx},
+	   128, CanHaveMII | HasBrokenTx},
 	{"Compex RL100-ATX", { 0x201111F6, 0xffffffff,},
-	 W840_FLAGS, 128, CanHaveMII | HasBrokenTx},
+	   128, CanHaveMII | HasBrokenTx},
 	{NULL,},					/* 0 terminated list. */
 };
 
@@ -374,7 +362,7 @@
 static struct ethtool_ops netdev_ethtool_ops;
 static int  netdev_close(struct net_device *dev);
 
-
+
 
 static int __devinit w840_probe1 (struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
@@ -434,7 +422,7 @@
 	np->mii_if.mdio_read = mdio_read;
 	np->mii_if.mdio_write = mdio_write;
 	np->base_addr = ioaddr;
-	
+
 	pci_set_drvdata(pdev, dev);
 
 	if (dev->mem_start)
@@ -510,7 +498,7 @@
 	return -ENODEV;
 }
 
-
+
 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.  These are
    often serial bit streams generated by the host processor.
    The example below is for the common 93c46 EEPROM, 64 16 bit words. */
@@ -660,7 +648,7 @@
 	return;
 }
 
-
+
 static int netdev_open(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
@@ -731,7 +719,7 @@
 				dev->name, np->phys[0]);
 		netif_carrier_on(dev);
 	}
-	
+
 	if ((np->mii & ~0xf) == MII_DAVICOM_DM9101) {
 		/* If the link partner doesn't support autonegotiation
 		 * the MII detects it's abilities with the "parallel detection".
@@ -761,7 +749,7 @@
 		result |= 0x20000000;
 	if (result != np->csr6 && debug)
 		printk(KERN_INFO "%s: Setting %dMBit-%s-duplex based on MII#%d\n",
-				 dev->name, fasteth ? 100 : 10, 
+				 dev->name, fasteth ? 100 : 10,
 			   	duplex ? "full" : "half", np->phys[0]);
 	return result;
 }
@@ -947,7 +935,7 @@
 	iowrite32(i, ioaddr + PCIBusCfg);
 
 	np->csr6 = 0;
-	/* 128 byte Tx threshold; 
+	/* 128 byte Tx threshold;
 		Transmit on; Receive on; */
 	update_csr6(dev, 0x00022002 | update_link(dev) | __set_rx_mode(dev));
 
@@ -1584,7 +1572,7 @@
 static void __devexit w840_remove1 (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
-	
+
 	if (dev) {
 		struct netdev_private *np = netdev_priv(dev);
 		unregister_netdev(dev);
@@ -1605,11 +1593,11 @@
  * - get_stats:
  * 	spin_lock_irq(np->lock), doesn't touch hw if not present
  * - hard_start_xmit:
- * 	netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
+ * 	synchronize_irq + netif_tx_disable;
  * - tx_timeout:
- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ * 	netif_device_detach + netif_tx_disable;
  * - set_multicast_list
- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
+ * 	netif_device_detach + netif_tx_disable;
  * - interrupt handler
  * 	doesn't touch hw if not present, synchronize_irq waits for
  * 	running instances of the interrupt handler.
@@ -1635,11 +1623,10 @@
 		netif_device_detach(dev);
 		update_csr6(dev, 0);
 		iowrite32(0, ioaddr + IntrEnable);
-		netif_stop_queue(dev);
 		spin_unlock_irq(&np->lock);
 
-		spin_unlock_wait(&dev->xmit_lock);
 		synchronize_irq(dev->irq);
+		netif_tx_disable(dev);
 	
 		np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
 
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 5634410..63c2175 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -1,11 +1,11 @@
 /*
- * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards 
+ * xircom_cb: A driver for the (tulip-like) Xircom Cardbus ethernet cards
  *
  * This software is (C) by the respective authors, and licensed under the GPL
  * License.
  *
  * Written by Arjan van de Ven for Red Hat, Inc.
- * Based on work by Jeff Garzik, Doug Ledford and Donald Becker 
+ * Based on work by Jeff Garzik, Doug Ledford and Donald Becker
  *
  *  	This software may be used and distributed according to the terms
  *      of the GNU General Public License, incorporated herein by reference.
@@ -93,7 +93,7 @@
 
 	unsigned long io_port;
 	int open;
-	
+
 	/* transmit_used is the rotating counter that indicates which transmit
 	   descriptor has to be used next */
 	int transmit_used;
@@ -153,10 +153,10 @@
 MODULE_DEVICE_TABLE(pci, xircom_pci_table);
 
 static struct pci_driver xircom_ops = {
-	.name		= "xircom_cb", 
-	.id_table	= xircom_pci_table, 
-	.probe		= xircom_probe, 
-	.remove		= xircom_remove, 
+	.name		= "xircom_cb",
+	.id_table	= xircom_pci_table,
+	.probe		= xircom_probe,
+	.remove		= xircom_remove,
 	.suspend =NULL,
 	.resume =NULL
 };
@@ -174,7 +174,7 @@
 			buffer[i2++]='1';
 		else
 			buffer[i2++]='0';
-		if ((i&3)==0) 
+		if ((i&3)==0)
 			buffer[i2++]=' ';
 	}
 	printk("%s\n",buffer);
@@ -196,10 +196,10 @@
 
 /* xircom_probe is the code that gets called on device insertion.
    it sets up the hardware and registers the device to the networklayer.
-   
+
    TODO: Send 1 or 2 "dummy" packets here as the card seems to discard the
          first two packets that get send, and pump hates that.
-         
+
  */
 static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -209,7 +209,7 @@
 	unsigned long flags;
 	unsigned short tmp16;
 	enter("xircom_probe");
-	
+
 	/* First do the PCI initialisation */
 
 	if (pci_enable_device(pdev))
@@ -217,24 +217,24 @@
 
 	/* disable all powermanagement */
 	pci_write_config_dword(pdev, PCI_POWERMGMT, 0x0000);
-	
+
 	pci_set_master(pdev); /* Why isn't this done by pci_enable_device ?*/
 
-	/* clear PCI status, if any */ 
-	pci_read_config_word (pdev,PCI_STATUS, &tmp16); 
+	/* clear PCI status, if any */
+	pci_read_config_word (pdev,PCI_STATUS, &tmp16);
 	pci_write_config_word (pdev, PCI_STATUS,tmp16);
-	
+
 	pci_read_config_byte(pdev, PCI_REVISION_ID, &chip_rev);
-	
+
 	if (!request_region(pci_resource_start(pdev, 0), 128, "xircom_cb")) {
 		printk(KERN_ERR "xircom_probe: failed to allocate io-region\n");
 		return -ENODEV;
 	}
 
-	/* 
+	/*
 	   Before changing the hardware, allocate the memory.
 	   This way, we can fail gracefully if not enough memory
-	   is available. 
+	   is available.
 	 */
 	dev = alloc_etherdev(sizeof(struct xircom_private));
 	if (!dev) {
@@ -242,13 +242,13 @@
 		goto device_fail;
 	}
 	private = netdev_priv(dev);
-	
+
 	/* Allocate the send/receive buffers */
 	private->rx_buffer = pci_alloc_consistent(pdev,8192,&private->rx_dma_handle);
 	if (private->rx_buffer == NULL) {
  		printk(KERN_ERR "xircom_probe: no memory for rx buffer \n");
 		goto rx_buf_fail;
-	}	
+	}
 	private->tx_buffer = pci_alloc_consistent(pdev,8192,&private->tx_dma_handle);
 	if (private->tx_buffer == NULL) {
 		printk(KERN_ERR "xircom_probe: no memory for tx buffer \n");
@@ -265,11 +265,11 @@
 	spin_lock_init(&private->lock);
 	dev->irq = pdev->irq;
 	dev->base_addr = private->io_port;
-	
+
 	initialize_card(private);
 	read_mac_address(private);
 	setup_descriptors(private);
-	
+
 	dev->open = &xircom_open;
 	dev->hard_start_xmit = &xircom_start_xmit;
 	dev->stop = &xircom_close;
@@ -285,19 +285,19 @@
 		printk(KERN_ERR "xircom_probe: netdevice registration failed.\n");
 		goto reg_fail;
 	}
-		
+
 	printk(KERN_INFO "%s: Xircom cardbus revision %i at irq %i \n", dev->name, chip_rev, pdev->irq);
 	/* start the transmitter to get a heartbeat */
 	/* TODO: send 2 dummy packets here */
 	transceiver_voodoo(private);
-	
+
 	spin_lock_irqsave(&private->lock,flags);
 	activate_transmitter(private);
 	activate_receiver(private);
 	spin_unlock_irqrestore(&private->lock,flags);
-	
+
 	trigger_receive(private);
-	
+
 	leave("xircom_probe");
 	return 0;
 
@@ -332,7 +332,7 @@
 	free_netdev(dev);
 	pci_set_drvdata(pdev, NULL);
 	leave("xircom_remove");
-} 
+}
 
 static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
@@ -346,11 +346,11 @@
 	spin_lock(&card->lock);
 	status = inl(card->io_port+CSR5);
 
-#ifdef DEBUG	
+#ifdef DEBUG
 	print_binary(status);
 	printk("tx status 0x%08x 0x%08x \n",card->tx_buffer[0],card->tx_buffer[4]);
 	printk("rx status 0x%08x 0x%08x \n",card->rx_buffer[0],card->rx_buffer[4]);
-#endif	
+#endif
 	/* Handle shared irq and hotplug */
 	if (status == 0 || status == 0xffffffff) {
 		spin_unlock(&card->lock);
@@ -366,21 +366,21 @@
 			netif_carrier_on(dev);
 		else
 			netif_carrier_off(dev);
-		
+
 	}
 
-	/* Clear all remaining interrupts */	
+	/* Clear all remaining interrupts */
 	status |= 0xffffffff; /* FIXME: make this clear only the
 				        real existing bits */
 	outl(status,card->io_port+CSR5);
-	
 
-	for (i=0;i<NUMDESCRIPTORS;i++) 
+
+	for (i=0;i<NUMDESCRIPTORS;i++)
 		investigate_write_descriptor(dev,card,i,bufferoffsets[i]);
-	for (i=0;i<NUMDESCRIPTORS;i++) 
+	for (i=0;i<NUMDESCRIPTORS;i++)
 		investigate_read_descriptor(dev,card,i,bufferoffsets[i]);
 
-	
+
 	spin_unlock(&card->lock);
 	leave("xircom_interrupt");
 	return IRQ_HANDLED;
@@ -393,38 +393,38 @@
 	int nextdescriptor;
 	int desc;
 	enter("xircom_start_xmit");
-	
+
 	card = netdev_priv(dev);
 	spin_lock_irqsave(&card->lock,flags);
-	
+
 	/* First see if we can free some descriptors */
-	for (desc=0;desc<NUMDESCRIPTORS;desc++) 
+	for (desc=0;desc<NUMDESCRIPTORS;desc++)
 		investigate_write_descriptor(dev,card,desc,bufferoffsets[desc]);
-	
-	
+
+
 	nextdescriptor = (card->transmit_used +1) % (NUMDESCRIPTORS);
 	desc = card->transmit_used;
-	
+
 	/* only send the packet if the descriptor is free */
 	if (card->tx_buffer[4*desc]==0) {
 			/* Copy the packet data; zero the memory first as the card
 			   sometimes sends more than you ask it to. */
-			
+
 			memset(&card->tx_buffer[bufferoffsets[desc]/4],0,1536);
 			memcpy(&(card->tx_buffer[bufferoffsets[desc]/4]),skb->data,skb->len);
-	
-	
+
+
 			/* FIXME: The specification tells us that the length we send HAS to be a multiple of
 			   4 bytes. */
-			   
+
 			card->tx_buffer[4*desc+1] = skb->len;
 			if (desc == NUMDESCRIPTORS-1)
 				card->tx_buffer[4*desc+1] |= (1<<25);  /* bit 25: last descriptor of the ring */
 
 			card->tx_buffer[4*desc+1] |= 0xF0000000;
-						 /* 0xF0... means want interrupts*/ 
+						 /* 0xF0... means want interrupts*/
 			card->tx_skb[desc] = skb;
-			
+
 			wmb();
 			/* This gives the descriptor to the card */
 			card->tx_buffer[4*desc] = 0x80000000;
@@ -433,18 +433,18 @@
 				netif_stop_queue(dev);
 			}
 			card->transmit_used = nextdescriptor;
-			leave("xircom-start_xmit - sent");	
+			leave("xircom-start_xmit - sent");
 			spin_unlock_irqrestore(&card->lock,flags);
 			return 0;
 	}
-	
+
 
 
 	/* Uh oh... no free descriptor... drop the packet */
 	netif_stop_queue(dev);
 	spin_unlock_irqrestore(&card->lock,flags);
 	trigger_transmit(card);
-	
+
 	return -EIO;
 }
 
@@ -462,7 +462,7 @@
 		leave("xircom_open - No IRQ");
 		return retval;
 	}
-	
+
 	xircom_up(xp);
 	xp->open = 1;
 	leave("xircom_open");
@@ -473,31 +473,31 @@
 {
 	struct xircom_private *card;
 	unsigned long flags;
-	
+
 	enter("xircom_close");
 	card = netdev_priv(dev);
 	netif_stop_queue(dev); /* we don't want new packets */
 
-	
+
 	spin_lock_irqsave(&card->lock,flags);
-	
+
 	disable_all_interrupts(card);
-#if 0	
+#if 0
 	/* We can enable this again once we send dummy packets on ifconfig ethX up */
 	deactivate_receiver(card);
 	deactivate_transmitter(card);
-#endif	
+#endif
 	remove_descriptors(card);
-	
+
 	spin_unlock_irqrestore(&card->lock,flags);
-	
+
 	card->open = 0;
 	free_irq(dev->irq,dev);
-	
+
 	leave("xircom_close");
-	
+
 	return 0;
-	
+
 }
 
 
@@ -506,8 +506,8 @@
 {
         struct xircom_private *card = netdev_priv(dev);
         return &card->stats;
-} 
-                                                 
+}
+
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void xircom_poll_controller(struct net_device *dev)
@@ -540,7 +540,7 @@
 	outl(val, card->io_port + CSR0);
 
 
-	val = 0;		/* Value 0x00 is a safe and conservative value 
+	val = 0;		/* Value 0x00 is a safe and conservative value
 				   for the PCI configuration settings */
 	outl(val, card->io_port + CSR0);
 
@@ -617,23 +617,23 @@
 
 		/* Rx Descr2: address of the buffer
 		   we store the buffer at the 2nd half of the page */
-	
+
 		address = (unsigned long) card->rx_dma_handle;
 		card->rx_buffer[i*4 + 2] = cpu_to_le32(address + bufferoffsets[i]);
 		/* Rx Desc3: address of 2nd buffer -> 0 */
 		card->rx_buffer[i*4 + 3] = 0;
 	}
-	
+
 	wmb();
 	/* Write the receive descriptor ring address to the card */
 	address = (unsigned long) card->rx_dma_handle;
-	val = cpu_to_le32(address); 
+	val = cpu_to_le32(address);
 	outl(val, card->io_port + CSR3);	/* Receive descr list address */
 
 
 	/* transmit descriptors */
 	memset(card->tx_buffer, 0, 128);	/* clear the descriptors */
-	
+
 	for (i=0;i<NUMDESCRIPTORS;i++ ) {
 		/* Tx Descr0: Empty, we own it, no errors -> 0x00000000 */
 		card->tx_buffer[i*4 + 0] = 0x00000000;
@@ -641,7 +641,7 @@
 		card->tx_buffer[i*4 + 1] = 1536;
 		if (i==NUMDESCRIPTORS-1)
 			card->tx_buffer[i*4 + 1] |= (1 << 25); /* bit 25 is "last descriptor" */
-		
+
 		/* Tx Descr2: address of the buffer
 		   we store the buffer at the 2nd half of the page */
 		address = (unsigned long) card->tx_dma_handle;
@@ -748,7 +748,7 @@
 activate_receiver enables the receiver on the card.
 Before being allowed to active the receiver, the receiver
 must be completely de-activated. To achieve this,
-this code actually disables the receiver first; then it waits for the 
+this code actually disables the receiver first; then it waits for the
 receiver to become inactive, then it activates the receiver and then
 it waits for the receiver to be active.
 
@@ -762,13 +762,13 @@
 
 
 	val = inl(card->io_port + CSR6);	/* Operation mode */
-	
+
 	/* If the "active" bit is set and the receiver is already
 	   active, no need to do the expensive thing */
 	if ((val&2) && (receive_active(card)))
 		return;
-	
-	
+
+
 	val = val & ~2;		/* disable the receiver */
 	outl(val, card->io_port + CSR6);
 
@@ -805,7 +805,7 @@
 
 /*
 deactivate_receiver disables the receiver on the card.
-To achieve this this code disables the receiver first; 
+To achieve this this code disables the receiver first;
 then it waits for the receiver to become inactive.
 
 must be called with the lock held and interrupts disabled.
@@ -840,7 +840,7 @@
 activate_transmitter enables the transmitter on the card.
 Before being allowed to active the transmitter, the transmitter
 must be completely de-activated. To achieve this,
-this code actually disables the transmitter first; then it waits for the 
+this code actually disables the transmitter first; then it waits for the
 transmitter to become inactive, then it activates the transmitter and then
 it waits for the transmitter to be active again.
 
@@ -856,7 +856,7 @@
 	val = inl(card->io_port + CSR6);	/* Operation mode */
 
 	/* If the "active" bit is set and the receiver is already
-	   active, no need to do the expensive thing */	 
+	   active, no need to do the expensive thing */
 	if ((val&(1<<13)) && (transmit_active(card)))
 		return;
 
@@ -896,7 +896,7 @@
 
 /*
 deactivate_transmitter disables the transmitter on the card.
-To achieve this this code disables the transmitter first; 
+To achieve this this code disables the transmitter first;
 then it waits for the transmitter to become inactive.
 
 must be called with the lock held and interrupts disabled.
@@ -990,7 +990,7 @@
 {
 	unsigned int val;
 	enter("enable_all_interrupts");
-	
+
 	val = 0;				/* disable all interrupts */
 	outl(val, card->io_port + CSR7);
 
@@ -1031,8 +1031,8 @@
 	unsigned int val;
 	enter("enable_promisc");
 
-	val = inl(card->io_port + CSR6);	
-	val = val | (1 << 6);	
+	val = inl(card->io_port + CSR6);
+	val = val | (1 << 6);
 	outl(val, card->io_port + CSR6);
 
 	leave("enable_promisc");
@@ -1042,7 +1042,7 @@
 
 
 
-/* 
+/*
 link_status() checks the the links status and will return 0 for no link, 10 for 10mbit link and 100 for.. guess what.
 
 Must be called in locked state with interrupts disabled
@@ -1051,15 +1051,15 @@
 {
 	unsigned int val;
 	enter("link_status");
-	
+
 	val = inb(card->io_port + CSR12);
-	
+
 	if (!(val&(1<<2)))  /* bit 2 is 0 for 10mbit link, 1 for not an 10mbit link */
 		return 10;
 	if (!(val&(1<<1)))  /* bit 1 is 0 for 100mbit link, 1 for not an 100mbit link */
 		return 100;
-		
-	/* If we get here -> no link at all */	
+
+	/* If we get here -> no link at all */
 
 	leave("link_status");
 	return 0;
@@ -1071,7 +1071,7 @@
 
 /*
   read_mac_address() reads the MAC address from the NIC and stores it in the "dev" structure.
- 
+
   This function will take the spinlock itself and can, as a result, not be called with the lock helt.
  */
 static void read_mac_address(struct xircom_private *card)
@@ -1081,7 +1081,7 @@
 	int i;
 
 	enter("read_mac_address");
-		
+
 	spin_lock_irqsave(&card->lock, flags);
 
 	outl(1 << 12, card->io_port + CSR9);	/* enable boot rom access */
@@ -1095,7 +1095,7 @@
 		outl(i + 3, card->io_port + CSR10);
 		data_count = inl(card->io_port + CSR9) & 0xff;
 		if ((tuple == 0x22) && (data_id == 0x04) && (data_count == 0x06)) {
-			/* 
+			/*
 			 * This is it.  We have the data we want.
 			 */
 			for (j = 0; j < 6; j++) {
@@ -1136,12 +1136,12 @@
 	spin_lock_irqsave(&card->lock, flags);
 
 	outl(0x0008, card->io_port + CSR15);
-        udelay(25);  
+        udelay(25);
         outl(0xa8050000, card->io_port + CSR15);
         udelay(25);
         outl(0xa00f0000, card->io_port + CSR15);
         udelay(25);
-        
+
         spin_unlock_irqrestore(&card->lock, flags);
 
 	netif_start_queue(card->dev);
@@ -1163,15 +1163,15 @@
 
 	spin_lock_irqsave(&card->lock, flags);
 
-	
+
 	enable_link_interrupt(card);
 	enable_transmit_interrupt(card);
 	enable_receive_interrupt(card);
 	enable_common_interrupts(card);
 	enable_promisc(card);
-	
+
 	/* The card can have received packets already, read them away now */
-	for (i=0;i<NUMDESCRIPTORS;i++) 
+	for (i=0;i<NUMDESCRIPTORS;i++)
 		investigate_read_descriptor(card->dev,card,i,bufferoffsets[i]);
 
 
@@ -1185,15 +1185,15 @@
 /* Bufferoffset is in BYTES */
 static void investigate_read_descriptor(struct net_device *dev,struct xircom_private *card, int descnr, unsigned int bufferoffset)
 {
-		int status;		
-		
+		int status;
+
 		enter("investigate_read_descriptor");
 		status = card->rx_buffer[4*descnr];
-		
+
 		if ((status > 0)) {	/* packet received */
-		
+
 			/* TODO: discard error packets */
-			
+
 			short pkt_len = ((status >> 16) & 0x7ff) - 4;	/* minus 4, we don't want the CRC */
 			struct sk_buff *skb;
 
@@ -1216,7 +1216,7 @@
 			dev->last_rx = jiffies;
 			card->stats.rx_packets++;
 			card->stats.rx_bytes += pkt_len;
-			
+
 		      out:
 			/* give the buffer back to the card */
 			card->rx_buffer[4*descnr] =  0x80000000;
@@ -1234,9 +1234,9 @@
 		int status;
 
 		enter("investigate_write_descriptor");
-		
+
 		status = card->tx_buffer[4*descnr];
-#if 0		
+#if 0
 		if (status & 0x8000) {	/* Major error */
 			printk(KERN_ERR "Major transmit error status %x \n", status);
 			card->tx_buffer[4*descnr] = 0;
@@ -1258,7 +1258,7 @@
 		}
 
 		leave("investigate_write_descriptor");
-		
+
 }
 
 
@@ -1271,8 +1271,8 @@
 static void __exit xircom_exit(void)
 {
 	pci_unregister_driver(&xircom_ops);
-} 
+}
 
-module_init(xircom_init) 
+module_init(xircom_init)
 module_exit(xircom_exit)
 
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a1ed2d9..6c62d5c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -490,6 +490,9 @@
 
 		err = -EINVAL;
 
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
 		/* Set dev type */
 		if (ifr->ifr_flags & IFF_TUN) {
 			/* TUN device */
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index d9258d4..e49e8b5 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -340,7 +340,7 @@
 #endif
 
 #if defined(NETIF_F_TSO)
-#define skb_tso_size(x)		(skb_shinfo(x)->tso_size)
+#define skb_tso_size(x)		(skb_shinfo(x)->gso_size)
 #define TSO_NUM_DESCRIPTORS	2
 #define TSO_OFFLOAD_ON		TYPHOON_OFFLOAD_TCP_SEGMENT
 #else
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index fdc2103..c80a4f1 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -1284,11 +1284,8 @@
 	/* Calculate the next Tx descriptor entry. */
 	entry = rp->cur_tx % TX_RING_SIZE;
 
-	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
-	}
+	if (skb_padto(skb, ETH_ZLEN))
+		return 0;
 
 	rp->tx_skbuff[entry] = skb;
 
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index ed1f837..09e05fe 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -248,6 +248,7 @@
 static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_info *);
 static int velocity_soft_reset(struct velocity_info *vptr);
 static void mii_init(struct velocity_info *vptr, u32 mii_status);
+static u32 velocity_get_link(struct net_device *dev);
 static u32 velocity_get_opt_media_mode(struct velocity_info *vptr);
 static void velocity_print_link_status(struct velocity_info *vptr);
 static void safe_disable_mii_autopoll(struct mac_regs __iomem * regs);
@@ -798,6 +799,9 @@
 	if (ret < 0)
 		goto err_iounmap;
 
+	if (velocity_get_link(dev))
+		netif_carrier_off(dev);
+
 	velocity_print_info(vptr);
 	pci_set_drvdata(pdev, dev);
 	
@@ -1653,8 +1657,10 @@
 
 		if (linked) {
 			vptr->mii_status &= ~VELOCITY_LINK_FAIL;
+			netif_carrier_on(vptr->dev);
 		} else {
 			vptr->mii_status |= VELOCITY_LINK_FAIL;
+			netif_carrier_off(vptr->dev);
 		}
 
 		velocity_print_link_status(vptr);
@@ -1899,6 +1905,13 @@
 
 	int pktlen = skb->len;
 
+#ifdef VELOCITY_ZERO_COPY_SUPPORT
+	if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
+		kfree_skb(skb);
+		return 0;
+	}
+#endif
+
 	spin_lock_irqsave(&vptr->lock, flags);
 
 	index = vptr->td_curr[qnum];
@@ -1914,8 +1927,6 @@
 	 */
 	if (pktlen < ETH_ZLEN) {
 		/* Cannot occur until ZC support */
-		if(skb_linearize(skb, GFP_ATOMIC))
-			return 0; 
 		pktlen = ETH_ZLEN;
 		memcpy(tdinfo->buf, skb->data, skb->len);
 		memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
@@ -1933,7 +1944,6 @@
 		int nfrags = skb_shinfo(skb)->nr_frags;
 		tdinfo->skb = skb;
 		if (nfrags > 6) {
-			skb_linearize(skb, GFP_ATOMIC);
 			memcpy(tdinfo->buf, skb->data, skb->len);
 			tdinfo->skb_dma[0] = tdinfo->buf_dma;
 			td_ptr->tdesc0.pktsize = 
diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
index d9a774b..f1b2640 100644
--- a/drivers/net/via-velocity.h
+++ b/drivers/net/via-velocity.h
@@ -307,7 +307,7 @@
 #define TX_QUEUE_NO         4
 
 #define MAX_HW_MIB_COUNTER  32
-#define VELOCITY_MIN_MTU    (1514-14)
+#define VELOCITY_MIN_MTU    (64)
 #define VELOCITY_MAX_MTU    (9000)
 
 /*
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index 43d854a..c92ac9f 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -7,7 +7,7 @@
  * under the terms of version 2 of the GNU General Public License
  * as published by the Free Software Foundation.
  *
- * For information see http://hq.pm.waw.pl/hdlc/
+ * For information see <http://www.kernel.org/pub/linux/utils/net/hdlc/>
  *
  * Sources of information:
  *    Hitachi HD64570 SCA User's Manual
@@ -326,21 +326,21 @@
 	if (request_irq(irq, sca_intr, 0, devname, card)) {
 		printk(KERN_ERR "c101: could not allocate IRQ\n");
 		c101_destroy_card(card);
-		return(-EBUSY);
+		return -EBUSY;
 	}
 	card->irq = irq;
 
 	if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
 		printk(KERN_ERR "c101: could not request RAM window\n");
 		c101_destroy_card(card);
-		return(-EBUSY);
+		return -EBUSY;
 	}
 	card->phy_winbase = winbase;
 	card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
 	if (!card->win0base) {
 		printk(KERN_ERR "c101: could not map I/O address\n");
 		c101_destroy_card(card);
-		return -EBUSY;
+		return -EFAULT;
 	}
 
 	card->tx_ring_buffers = TX_RING_BUFFERS;
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index 46cef8f..57f9538 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -259,7 +259,7 @@
 	}
 }
 
-static void hdlc_setup(struct net_device *dev)
+void hdlc_setup(struct net_device *dev)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 
@@ -288,26 +288,6 @@
 	return dev;
 }
 
-int register_hdlc_device(struct net_device *dev)
-{
-	int result = dev_alloc_name(dev, "hdlc%d");
-	if (result < 0)
-		return result;
-
-	result = register_netdev(dev);
-	if (result != 0)
-		return -EIO;
-
-#if 0
-	if (netif_carrier_ok(dev))
-		netif_carrier_off(dev); /* no carrier until DCD goes up */
-#endif
-
-	return 0;
-}
-
-
-
 void unregister_hdlc_device(struct net_device *dev)
 {
 	rtnl_lock();
@@ -326,8 +306,8 @@
 EXPORT_SYMBOL(hdlc_close);
 EXPORT_SYMBOL(hdlc_set_carrier);
 EXPORT_SYMBOL(hdlc_ioctl);
+EXPORT_SYMBOL(hdlc_setup);
 EXPORT_SYMBOL(alloc_hdlcdev);
-EXPORT_SYMBOL(register_hdlc_device);
 EXPORT_SYMBOL(unregister_hdlc_device);
 
 static struct packet_type hdlc_packet_type = {
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index cd32751..e013b81 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -7,7 +7,7 @@
  * under the terms of version 2 of the GNU General Public License
  * as published by the Free Software Foundation.
  *
- * For information see http://hq.pm.waw.pl/hdlc/
+ * For information see <http://www.kernel.org/pub/linux/utils/net/hdlc/>
  *
  * Note: integrated CSU/DSU/DDS are not supported by this driver
  *
@@ -387,6 +387,11 @@
 	}
 	card->phy_winbase = winbase;
 	card->winbase = ioremap(winbase, USE_WINDOWSIZE);
+	if (!card->winbase) {
+		printk(KERN_ERR "n2: ioremap() failed\n");
+		n2_destroy_card(card);
+		return -EFAULT;
+	}
 
 	outb(0, io + N2_PCR);
 	outb(winbase >> 12, io + N2_BAR);
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index eba8e5c..24c3c57 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -7,7 +7,7 @@
  * under the terms of version 2 of the GNU General Public License
  * as published by the Free Software Foundation.
  *
- * For information see http://hq.pm.waw.pl/hdlc/
+ * For information see <http://www.kernel.org/pub/linux/utils/net/hdlc/>
  *
  * Sources of information:
  *    Hitachi HD64572 SCA-II User's Manual
@@ -50,10 +50,6 @@
 static int pci_clock_freq = 33000000;
 #define CLOCK_BASE pci_clock_freq
 
-#define PCI_VENDOR_ID_GORAMO	0x10B5	/* uses PLX:9050 ID - this card	*/
-#define PCI_DEVICE_ID_PCI200SYN	0x9050	/* doesn't have its own ID	*/
-
-
 /*
  *      PLX PCI9052 local configuration and shared runtime registers.
  *      This structure can be used to access 9052 registers (memory mapped).
@@ -262,7 +258,7 @@
 	int i;
 	card_t *card = pci_get_drvdata(pdev);
 
-	for(i = 0; i < 2; i++)
+	for (i = 0; i < 2; i++)
 		if (card->ports[i].card) {
 			struct net_device *dev = port_to_dev(&card->ports[i]);
 			unregister_hdlc_device(dev);
@@ -358,6 +354,7 @@
 	    card->rambase == NULL) {
 		printk(KERN_ERR "pci200syn: ioremap() failed\n");
 		pci200_pci_remove_one(pdev);
+		return -EFAULT;
 	}
 
 	/* Reset PLX */
@@ -385,6 +382,15 @@
 	       " %u RX packets rings\n", ramsize / 1024, ramphys,
 	       pdev->irq, card->tx_ring_buffers, card->rx_ring_buffers);
 
+	if (pdev->subsystem_device == PCI_DEVICE_ID_PLX_9050) {
+		printk(KERN_ERR "Detected PCI200SYN card with old "
+		       "configuration data.\n");
+		printk(KERN_ERR "See <http://www.kernel.org/pub/"
+		       "linux/utils/net/hdlc/pci200syn/> for update.\n");
+		printk(KERN_ERR "The card will stop working with"
+		       " future versions of Linux if not updated.\n");
+	}
+
 	if (card->tx_ring_buffers < 1) {
 		printk(KERN_ERR "pci200syn: RAM test failed\n");
 		pci200_pci_remove_one(pdev);
@@ -396,7 +402,7 @@
 	writew(readw(p) | 0x0040, p);
 
 	/* Allocate IRQ */
-	if(request_irq(pdev->irq, sca_intr, SA_SHIRQ, devname, card)) {
+	if (request_irq(pdev->irq, sca_intr, SA_SHIRQ, devname, card)) {
 		printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
 		       pdev->irq);
 		pci200_pci_remove_one(pdev);
@@ -406,7 +412,7 @@
 
 	sca_init(card, 0);
 
-	for(i = 0; i < 2; i++) {
+	for (i = 0; i < 2; i++) {
 		port_t *port = &card->ports[i];
 		struct net_device *dev = port_to_dev(port);
 		hdlc_device *hdlc = dev_to_hdlc(dev);
@@ -425,7 +431,7 @@
 		hdlc->xmit = sca_xmit;
 		port->settings.clock_type = CLOCK_EXT;
 		port->card = card;
-		if(register_hdlc_device(dev)) {
+		if (register_hdlc_device(dev)) {
 			printk(KERN_ERR "pci200syn: unable to register hdlc "
 			       "device\n");
 			port->card = NULL;
@@ -445,8 +451,10 @@
 
 
 static struct pci_device_id pci200_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_GORAMO, PCI_DEVICE_ID_PCI200SYN, PCI_ANY_ID,
-	  PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
+	  PCI_DEVICE_ID_PLX_9050, 0, 0, 0 },
+	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
+	  PCI_DEVICE_ID_PLX_PCI200SYN, 0, 0, 0 },
 	{ 0, }
 };
 
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 22e7940..7628c2d 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -60,9 +60,9 @@
 
 static const char* version = "SDLA driver v0.30, 12 Sep 1996, mike.mclagan@linux.org";
 
-static unsigned int valid_port[] __initdata = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390};
+static unsigned int valid_port[] = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390};
 
-static unsigned int valid_mem[]  __initdata = {
+static unsigned int valid_mem[] = {
 				    0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, 
                                     0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
                                     0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 29a756d..437e0e9 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -634,7 +634,13 @@
 
 	/* set up PLX mapping */
 	plx_phy = pci_resource_start(pdev, 0);
+
 	card->plx = ioremap_nocache(plx_phy, 0x70);
+	if (!card->plx) {
+		printk(KERN_ERR "wanxl: ioremap() failed\n");
+ 		wanxl_pci_remove_one(pdev);
+		return -EFAULT;
+	}
 
 #if RESET_WHILE_LOADING
 	wanxl_reset(card);
@@ -700,6 +706,12 @@
 	}
 
 	mem = ioremap_nocache(mem_phy, PDM_OFFSET + sizeof(firmware));
+	if (!mem) {
+		printk(KERN_ERR "wanxl: ioremap() failed\n");
+ 		wanxl_pci_remove_one(pdev);
+		return -EFAULT;
+	}
+
 	for (i = 0; i < sizeof(firmware); i += 4)
 		writel(htonl(*(u32*)(firmware + i)), mem + PDM_OFFSET + i);
 
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index e0874cb..30ec235 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -235,7 +235,35 @@
 	  promiscuous mode via the Wireless Tool's Monitor mode.  While in this
 	  mode, no packets can be sent.
 
-config IPW_QOS
+config IPW2200_RADIOTAP
+	bool "Enable radiotap format 802.11 raw packet support"
+	depends on IPW2200_MONITOR
+
+config IPW2200_PROMISCUOUS
+	bool "Enable creation of a RF radiotap promiscuous interface"
+	depends on IPW2200_MONITOR
+	select IPW2200_RADIOTAP
+	---help---
+          Enables the creation of a second interface prefixed 'rtap'. 
+          This second interface will provide every received in radiotap
+	  format.
+
+          This is useful for performing wireless network analysis while
+          maintaining an active association.
+
+          Example usage:
+
+            % modprobe ipw2200 rtap_iface=1
+            % ifconfig rtap0 up
+            % tethereal -i rtap0
+
+          If you do not specify 'rtap_iface=1' as a module parameter then 
+          the rtap interface will not be created and you will need to turn 
+          it on via sysfs:
+	
+            % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
+
+config IPW2200_QOS
         bool "Enable QoS support"
         depends on IPW2200 && EXPERIMENTAL
 
@@ -503,6 +531,23 @@
 	  say M here and read <file:Documentation/modules.txt>.  The module
 	  will be called prism54.ko.
 
+config USB_ZD1201
+	tristate "USB ZD1201 based Wireless device support"
+	depends on USB && NET_RADIO
+	select FW_LOADER
+	---help---
+	  Say Y if you want to use wireless LAN adapters based on the ZyDAS
+	  ZD1201 chip.
+
+	  This driver makes the adapter appear as a normal Ethernet interface,
+	  typically on wlan0.
+
+	  The zd1201 device requires external firmware to be loaded.
+	  This can be found at http://linux-lc100020.sourceforge.net/
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called zd1201.
+
 source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/bcm43xx/Kconfig"
 
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index c867798..512603d 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -40,3 +40,5 @@
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
 obj-$(CONFIG_PCMCIA_WL3501)	+= wl3501_cs.o
+
+obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 00764dd..4069b79 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -47,6 +47,7 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <asm/uaccess.h>
+#include <net/ieee80211.h>
 
 #include "airo.h"
 
@@ -467,6 +468,8 @@
 #define RID_ECHOTEST_RESULTS 0xFF71
 #define RID_BSSLISTFIRST 0xFF72
 #define RID_BSSLISTNEXT  0xFF73
+#define RID_WPA_BSSLISTFIRST 0xFF74
+#define RID_WPA_BSSLISTNEXT  0xFF75
 
 typedef struct {
 	u16 cmd;
@@ -739,6 +742,14 @@
 	u16 extSoftCap;
 } CapabilityRid;
 
+
+/* Only present on firmware >= 5.30.17 */
+typedef struct {
+  u16 unknown[4];
+  u8 fixed[12]; /* WLAN management frame */
+  u8 iep[624];
+} BSSListRidExtra;
+
 typedef struct {
   u16 len;
   u16 index; /* First is 0 and 0xffff means end of list */
@@ -767,6 +778,9 @@
   } fh;
   u16 dsChannel;
   u16 atimWindow;
+
+  /* Only present on firmware >= 5.30.17 */
+  BSSListRidExtra extra;
 } BSSListRid;
 
 typedef struct {
@@ -1140,8 +1154,6 @@
 	char defindex; // Used with auto wep
 	struct proc_dir_entry *proc_entry;
         spinlock_t aux_lock;
-        unsigned long flags;
-#define FLAG_PROMISC	8	/* IFF_PROMISC 0x100 - include/linux/if.h */
 #define FLAG_RADIO_OFF	0	/* User disabling of MAC */
 #define FLAG_RADIO_DOWN	1	/* ifup/ifdown disabling of MAC */
 #define FLAG_RADIO_MASK 0x03
@@ -1151,6 +1163,7 @@
 #define FLAG_UPDATE_MULTI 5
 #define FLAG_UPDATE_UNI 6
 #define FLAG_802_11	7
+#define FLAG_PROMISC	8	/* IFF_PROMISC 0x100 - include/linux/if.h */
 #define FLAG_PENDING_XMIT 9
 #define FLAG_PENDING_XMIT11 10
 #define FLAG_MPI	11
@@ -1158,17 +1171,19 @@
 #define FLAG_COMMIT	13
 #define FLAG_RESET	14
 #define FLAG_FLASHING	15
-#define JOB_MASK	0x2ff0000
-#define JOB_DIE		16
-#define JOB_XMIT	17
-#define JOB_XMIT11	18
-#define JOB_STATS	19
-#define JOB_PROMISC	20
-#define JOB_MIC		21
-#define JOB_EVENT	22
-#define JOB_AUTOWEP	23
-#define JOB_WSTATS	24
-#define JOB_SCAN_RESULTS  25
+#define FLAG_WPA_CAPABLE	16
+	unsigned long flags;
+#define JOB_DIE	0
+#define JOB_XMIT	1
+#define JOB_XMIT11	2
+#define JOB_STATS	3
+#define JOB_PROMISC	4
+#define JOB_MIC	5
+#define JOB_EVENT	6
+#define JOB_AUTOWEP	7
+#define JOB_WSTATS	8
+#define JOB_SCAN_RESULTS  9
+	unsigned long jobs;
 	int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
 			int whichbap);
 	unsigned short *flash;
@@ -1208,6 +1223,11 @@
 #define	PCI_SHARED_LEN		2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
 	char			proc_name[IFNAMSIZ];
 
+	/* WPA-related stuff */
+	unsigned int bssListFirst;
+	unsigned int bssListNext;
+	unsigned int bssListRidLen;
+
 	struct list_head network_list;
 	struct list_head network_free_list;
 	BSSListElement *networks;
@@ -1264,7 +1284,7 @@
 {
 	MICRid mic_rid;
 
-	clear_bit(JOB_MIC, &ai->flags);
+	clear_bit(JOB_MIC, &ai->jobs);
 	PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
 	up(&ai->sem);
 
@@ -1705,24 +1725,24 @@
 static int readBSSListRid(struct airo_info *ai, int first,
 		      BSSListRid *list) {
 	int rc;
-			Cmd cmd;
-			Resp rsp;
+	Cmd cmd;
+	Resp rsp;
 
 	if (first == 1) {
-			if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
-			memset(&cmd, 0, sizeof(cmd));
-			cmd.cmd=CMD_LISTBSS;
-			if (down_interruptible(&ai->sem))
-				return -ERESTARTSYS;
-			issuecommand(ai, &cmd, &rsp);
-			up(&ai->sem);
-			/* Let the command take effect */
-			ai->task = current;
-			ssleep(3);
-			ai->task = NULL;
-		}
-	rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT,
-			    list, sizeof(*list), 1);
+		if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.cmd=CMD_LISTBSS;
+		if (down_interruptible(&ai->sem))
+			return -ERESTARTSYS;
+		issuecommand(ai, &cmd, &rsp);
+		up(&ai->sem);
+		/* Let the command take effect */
+		ai->task = current;
+		ssleep(3);
+		ai->task = NULL;
+	}
+	rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
+			    list, ai->bssListRidLen, 1);
 
 	list->len = le16_to_cpu(list->len);
 	list->index = le16_to_cpu(list->index);
@@ -2112,7 +2132,7 @@
 	int fid = priv->xmit.fid;
 	u32 *fids = priv->fids;
 
-	clear_bit(JOB_XMIT, &priv->flags);
+	clear_bit(JOB_XMIT, &priv->jobs);
 	clear_bit(FLAG_PENDING_XMIT, &priv->flags);
 	status = transmit_802_3_packet (priv, fids[fid], skb->data);
 	up(&priv->sem);
@@ -2162,7 +2182,7 @@
 	if (down_trylock(&priv->sem) != 0) {
 		set_bit(FLAG_PENDING_XMIT, &priv->flags);
 		netif_stop_queue(dev);
-		set_bit(JOB_XMIT, &priv->flags);
+		set_bit(JOB_XMIT, &priv->jobs);
 		wake_up_interruptible(&priv->thr_wait);
 	} else
 		airo_end_xmit(dev);
@@ -2177,7 +2197,7 @@
 	int fid = priv->xmit11.fid;
 	u32 *fids = priv->fids;
 
-	clear_bit(JOB_XMIT11, &priv->flags);
+	clear_bit(JOB_XMIT11, &priv->jobs);
 	clear_bit(FLAG_PENDING_XMIT11, &priv->flags);
 	status = transmit_802_11_packet (priv, fids[fid], skb->data);
 	up(&priv->sem);
@@ -2233,7 +2253,7 @@
 	if (down_trylock(&priv->sem) != 0) {
 		set_bit(FLAG_PENDING_XMIT11, &priv->flags);
 		netif_stop_queue(dev);
-		set_bit(JOB_XMIT11, &priv->flags);
+		set_bit(JOB_XMIT11, &priv->jobs);
 		wake_up_interruptible(&priv->thr_wait);
 	} else
 		airo_end_xmit11(dev);
@@ -2244,7 +2264,7 @@
 	StatsRid stats_rid;
 	u32 *vals = stats_rid.vals;
 
-	clear_bit(JOB_STATS, &ai->flags);
+	clear_bit(JOB_STATS, &ai->jobs);
 	if (ai->power.event) {
 		up(&ai->sem);
 		return;
@@ -2272,10 +2292,10 @@
 {
 	struct airo_info *local =  dev->priv;
 
-	if (!test_bit(JOB_STATS, &local->flags)) {
+	if (!test_bit(JOB_STATS, &local->jobs)) {
 		/* Get stats out of the card if available */
 		if (down_trylock(&local->sem) != 0) {
-			set_bit(JOB_STATS, &local->flags);
+			set_bit(JOB_STATS, &local->jobs);
 			wake_up_interruptible(&local->thr_wait);
 		} else
 			airo_read_stats(local);
@@ -2290,7 +2310,7 @@
 
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.cmd=CMD_SETMODE;
-	clear_bit(JOB_PROMISC, &ai->flags);
+	clear_bit(JOB_PROMISC, &ai->jobs);
 	cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;
 	issuecommand(ai, &cmd, &rsp);
 	up(&ai->sem);
@@ -2302,7 +2322,7 @@
 	if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
 		change_bit(FLAG_PROMISC, &ai->flags);
 		if (down_trylock(&ai->sem) != 0) {
-			set_bit(JOB_PROMISC, &ai->flags);
+			set_bit(JOB_PROMISC, &ai->jobs);
 			wake_up_interruptible(&ai->thr_wait);
 		} else
 			airo_set_promisc(ai);
@@ -2380,7 +2400,7 @@
 		}
 		clear_bit(FLAG_REGISTERED, &ai->flags);
 	}
-	set_bit(JOB_DIE, &ai->flags);
+	set_bit(JOB_DIE, &ai->jobs);
 	kill_proc(ai->thr_pid, SIGTERM, 1);
 	wait_for_completion(&ai->thr_exited);
 
@@ -2701,14 +2721,14 @@
 	return 0;
 }
 
-#define MAX_NETWORK_COUNT	64
+#define AIRO_MAX_NETWORK_COUNT	64
 static int airo_networks_allocate(struct airo_info *ai)
 {
 	if (ai->networks)
 		return 0;
 
 	ai->networks =
-	    kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement),
+	    kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement),
 		    GFP_KERNEL);
 	if (!ai->networks) {
 		airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
@@ -2732,11 +2752,33 @@
 
 	INIT_LIST_HEAD(&ai->network_free_list);
 	INIT_LIST_HEAD(&ai->network_list);
-	for (i = 0; i < MAX_NETWORK_COUNT; i++)
+	for (i = 0; i < AIRO_MAX_NETWORK_COUNT; i++)
 		list_add_tail(&ai->networks[i].list,
 			      &ai->network_free_list);
 }
 
+static int airo_test_wpa_capable(struct airo_info *ai)
+{
+	int status;
+	CapabilityRid cap_rid;
+	const char *name = ai->dev->name;
+
+	status = readCapabilityRid(ai, &cap_rid, 1);
+	if (status != SUCCESS) return 0;
+
+	/* Only firmware versions 5.30.17 or better can do WPA */
+	if ((cap_rid.softVer > 0x530)
+	  || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
+		airo_print_info(name, "WPA is supported.");
+		return 1;
+	}
+
+	/* No WPA support */
+	airo_print_info(name, "WPA unsupported (only firmware versions 5.30.17"
+		" and greater support WPA.  Detected %s)", cap_rid.prodVer);
+	return 0;
+}
+
 static struct net_device *_init_airo_card( unsigned short irq, int port,
 					   int is_pcmcia, struct pci_dev *pci,
 					   struct device *dmdev )
@@ -2759,6 +2801,7 @@
 	ai = dev->priv;
 	ai->wifidev = NULL;
 	ai->flags = 0;
+	ai->jobs = 0;
 	ai->dev = dev;
 	if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
 		airo_print_dbg(dev->name, "Found an MPI350 card");
@@ -2838,6 +2881,18 @@
 		set_bit(FLAG_FLASHING, &ai->flags);
 	}
 
+	/* Test for WPA support */
+	if (airo_test_wpa_capable(ai)) {
+		set_bit(FLAG_WPA_CAPABLE, &ai->flags);
+		ai->bssListFirst = RID_WPA_BSSLISTFIRST;
+		ai->bssListNext = RID_WPA_BSSLISTNEXT;
+		ai->bssListRidLen = sizeof(BSSListRid);
+	} else {
+		ai->bssListFirst = RID_BSSLISTFIRST;
+		ai->bssListNext = RID_BSSLISTNEXT;
+		ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
+	}
+
 	rc = register_netdev(dev);
 	if (rc) {
 		airo_print_err(dev->name, "Couldn't register_netdev");
@@ -2875,7 +2930,7 @@
 err_out_unlink:
 	del_airo_dev(dev);
 err_out_thr:
-	set_bit(JOB_DIE, &ai->flags);
+	set_bit(JOB_DIE, &ai->jobs);
 	kill_proc(ai->thr_pid, SIGTERM, 1);
 	wait_for_completion(&ai->thr_exited);
 err_out_free:
@@ -2933,7 +2988,7 @@
 	union iwreq_data wrqu;
 	StatusRid status_rid;
 
-	clear_bit(JOB_EVENT, &ai->flags);
+	clear_bit(JOB_EVENT, &ai->jobs);
 	PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0);
 	up(&ai->sem);
 	wrqu.data.length = 0;
@@ -2947,7 +3002,7 @@
 
 static void airo_process_scan_results (struct airo_info *ai) {
 	union iwreq_data	wrqu;
-	BSSListRid BSSList;
+	BSSListRid bss;
 	int rc;
 	BSSListElement * loop_net;
 	BSSListElement * tmp_net;
@@ -2960,15 +3015,15 @@
 	}
 
 	/* Try to read the first entry of the scan result */
-	rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0);
-	if((rc) || (BSSList.index == 0xffff)) {
+	rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0);
+	if((rc) || (bss.index == 0xffff)) {
 		/* No scan results */
 		goto out;
 	}
 
 	/* Read and parse all entries */
 	tmp_net = NULL;
-	while((!rc) && (BSSList.index != 0xffff)) {
+	while((!rc) && (bss.index != 0xffff)) {
 		/* Grab a network off the free list */
 		if (!list_empty(&ai->network_free_list)) {
 			tmp_net = list_entry(ai->network_free_list.next,
@@ -2977,19 +3032,19 @@
 		}
 
 		if (tmp_net != NULL) {
-			memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss));
+			memcpy(tmp_net, &bss, sizeof(tmp_net->bss));
 			list_add_tail(&tmp_net->list, &ai->network_list);
 			tmp_net = NULL;
 		}
 
 		/* Read next entry */
-		rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
-				    &BSSList, sizeof(BSSList), 0);
+		rc = PC4500_readrid(ai, ai->bssListNext,
+				    &bss, ai->bssListRidLen, 0);
 	}
 
 out:
 	ai->scan_timeout = 0;
-	clear_bit(JOB_SCAN_RESULTS, &ai->flags);
+	clear_bit(JOB_SCAN_RESULTS, &ai->jobs);
 	up(&ai->sem);
 
 	/* Send an empty event to user space.
@@ -3019,10 +3074,10 @@
 		/* make swsusp happy with our thread */
 		try_to_freeze();
 
-		if (test_bit(JOB_DIE, &ai->flags))
+		if (test_bit(JOB_DIE, &ai->jobs))
 			break;
 
-		if (ai->flags & JOB_MASK) {
+		if (ai->jobs) {
 			locked = down_interruptible(&ai->sem);
 		} else {
 			wait_queue_t wait;
@@ -3031,16 +3086,16 @@
 			add_wait_queue(&ai->thr_wait, &wait);
 			for (;;) {
 				set_current_state(TASK_INTERRUPTIBLE);
-				if (ai->flags & JOB_MASK)
+				if (ai->jobs)
 					break;
 				if (ai->expires || ai->scan_timeout) {
 					if (ai->scan_timeout &&
 							time_after_eq(jiffies,ai->scan_timeout)){
-						set_bit(JOB_SCAN_RESULTS,&ai->flags);
+						set_bit(JOB_SCAN_RESULTS, &ai->jobs);
 						break;
 					} else if (ai->expires &&
 							time_after_eq(jiffies,ai->expires)){
-						set_bit(JOB_AUTOWEP,&ai->flags);
+						set_bit(JOB_AUTOWEP, &ai->jobs);
 						break;
 					}
 					if (!signal_pending(current)) {
@@ -3069,7 +3124,7 @@
 		if (locked)
 			continue;
 
-		if (test_bit(JOB_DIE, &ai->flags)) {
+		if (test_bit(JOB_DIE, &ai->jobs)) {
 			up(&ai->sem);
 			break;
 		}
@@ -3079,23 +3134,23 @@
 			continue;
 		}
 
-		if (test_bit(JOB_XMIT, &ai->flags))
+		if (test_bit(JOB_XMIT, &ai->jobs))
 			airo_end_xmit(dev);
-		else if (test_bit(JOB_XMIT11, &ai->flags))
+		else if (test_bit(JOB_XMIT11, &ai->jobs))
 			airo_end_xmit11(dev);
-		else if (test_bit(JOB_STATS, &ai->flags))
+		else if (test_bit(JOB_STATS, &ai->jobs))
 			airo_read_stats(ai);
-		else if (test_bit(JOB_WSTATS, &ai->flags))
+		else if (test_bit(JOB_WSTATS, &ai->jobs))
 			airo_read_wireless_stats(ai);
-		else if (test_bit(JOB_PROMISC, &ai->flags))
+		else if (test_bit(JOB_PROMISC, &ai->jobs))
 			airo_set_promisc(ai);
-		else if (test_bit(JOB_MIC, &ai->flags))
+		else if (test_bit(JOB_MIC, &ai->jobs))
 			micinit(ai);
-		else if (test_bit(JOB_EVENT, &ai->flags))
+		else if (test_bit(JOB_EVENT, &ai->jobs))
 			airo_send_event(dev);
-		else if (test_bit(JOB_AUTOWEP, &ai->flags))
+		else if (test_bit(JOB_AUTOWEP, &ai->jobs))
 			timer_func(dev);
-		else if (test_bit(JOB_SCAN_RESULTS, &ai->flags))
+		else if (test_bit(JOB_SCAN_RESULTS, &ai->jobs))
 			airo_process_scan_results(ai);
 		else  /* Shouldn't get here, but we make sure to unlock */
 			up(&ai->sem);
@@ -3133,7 +3188,7 @@
 		if ( status & EV_MIC ) {
 			OUT4500( apriv, EVACK, EV_MIC );
 			if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
-				set_bit(JOB_MIC, &apriv->flags);
+				set_bit(JOB_MIC, &apriv->jobs);
 				wake_up_interruptible(&apriv->thr_wait);
 			}
 		}
@@ -3187,7 +3242,7 @@
 				set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
 
 				if (down_trylock(&apriv->sem) != 0) {
-					set_bit(JOB_EVENT, &apriv->flags);
+					set_bit(JOB_EVENT, &apriv->jobs);
 					wake_up_interruptible(&apriv->thr_wait);
 				} else
 					airo_send_event(dev);
@@ -5485,7 +5540,7 @@
 	up(&apriv->sem);
 
 /* Schedule check to see if the change worked */
-	clear_bit(JOB_AUTOWEP, &apriv->flags);
+	clear_bit(JOB_AUTOWEP, &apriv->jobs);
 	apriv->expires = RUN_AT(HZ*3);
 }
 
@@ -6876,7 +6931,7 @@
 	}
 	range->num_txpower = i;
 	range->txpower_capa = IW_TXPOW_MWATT;
-	range->we_version_source = 12;
+	range->we_version_source = 19;
 	range->we_version_compiled = WIRELESS_EXT;
 	range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
 	range->retry_flags = IW_RETRY_LIMIT;
@@ -7152,6 +7207,7 @@
 	u16			capabilities;
 	char *			current_val;	/* For rates */
 	int			i;
+	char *		buf;
 
 	/* First entry *MUST* be the AP MAC address */
 	iwe.cmd = SIOCGIWAP;
@@ -7238,8 +7294,69 @@
 	if((current_val - current_ev) > IW_EV_LCP_LEN)
 		current_ev = current_val;
 
-	/* The other data in the scan result are not really
-	 * interesting, so for now drop it - Jean II */
+	/* Beacon interval */
+	buf = kmalloc(30, GFP_KERNEL);
+	if (buf) {
+		iwe.cmd = IWEVCUSTOM;
+		sprintf(buf, "bcn_int=%d", bss->beaconInterval);
+		iwe.u.data.length = strlen(buf);
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, buf);
+		kfree(buf);
+	}
+
+	/* Put WPA/RSN Information Elements into the event stream */
+	if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
+		unsigned int num_null_ies = 0;
+		u16 length = sizeof (bss->extra.iep);
+		struct ieee80211_info_element *info_element =
+			(struct ieee80211_info_element *) &bss->extra.iep;
+
+		while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
+			if (sizeof(*info_element) + info_element->len > length) {
+				/* Invalid element, don't continue parsing IE */
+				break;
+			}
+
+			switch (info_element->id) {
+			case MFIE_TYPE_SSID:
+				/* Two zero-length SSID elements
+				 * mean we're done parsing elements */
+				if (!info_element->len)
+					num_null_ies++;
+				break;
+
+			case MFIE_TYPE_GENERIC:
+				if (info_element->len >= 4 &&
+				    info_element->data[0] == 0x00 &&
+				    info_element->data[1] == 0x50 &&
+				    info_element->data[2] == 0xf2 &&
+				    info_element->data[3] == 0x01) {
+					iwe.cmd = IWEVGENIE;
+					iwe.u.data.length = min(info_element->len + 2,
+								  MAX_WPA_IE_LEN);
+					current_ev = iwe_stream_add_point(current_ev, end_buf,
+							&iwe, (char *) info_element);
+				}
+				break;
+
+			case MFIE_TYPE_RSN:
+				iwe.cmd = IWEVGENIE;
+				iwe.u.data.length = min(info_element->len + 2,
+							  MAX_WPA_IE_LEN);
+				current_ev = iwe_stream_add_point(current_ev, end_buf,
+						&iwe, (char *) info_element);
+				break;
+
+			default:
+				break;
+			}
+
+			length -= sizeof(*info_element) + info_element->len;
+			info_element =
+			    (struct ieee80211_info_element *)&info_element->
+			    data[info_element->len];
+		}
+	}
 	return current_ev;
 }
 
@@ -7521,7 +7638,7 @@
 	u32 *vals = stats_rid.vals;
 
 	/* Get stats out of the card */
-	clear_bit(JOB_WSTATS, &local->flags);
+	clear_bit(JOB_WSTATS, &local->jobs);
 	if (local->power.event) {
 		up(&local->sem);
 		return;
@@ -7565,10 +7682,10 @@
 {
 	struct airo_info *local =  dev->priv;
 
-	if (!test_bit(JOB_WSTATS, &local->flags)) {
+	if (!test_bit(JOB_WSTATS, &local->jobs)) {
 		/* Get stats out of the card if available */
 		if (down_trylock(&local->sem) != 0) {
-			set_bit(JOB_WSTATS, &local->flags);
+			set_bit(JOB_WSTATS, &local->jobs);
 			wake_up_interruptible(&local->thr_wait);
 		} else
 			airo_read_wireless_stats(local);
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
index 25ea474..533993f 100644
--- a/drivers/net/wireless/bcm43xx/Kconfig
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -2,6 +2,7 @@
 	tristate "Broadcom BCM43xx wireless support"
 	depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL
 	select FW_LOADER
+	select HW_RANDOM
 	---help---
 	  This is an experimental driver for the Broadcom 43xx wireless chip,
 	  found in the Apple Airport Extreme and various other devices.
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 2e83083..17a5682 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -1,6 +1,7 @@
 #ifndef BCM43xx_H_
 #define BCM43xx_H_
 
+#include <linux/hw_random.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
@@ -82,6 +83,7 @@
 #define BCM43xx_MMIO_TSF_1		0x634 /* core rev < 3 only */
 #define BCM43xx_MMIO_TSF_2		0x636 /* core rev < 3 only */
 #define BCM43xx_MMIO_TSF_3		0x638 /* core rev < 3 only */
+#define BCM43xx_MMIO_RNG		0x65A
 #define BCM43xx_MMIO_POWERUP_DELAY	0x6A8
 
 /* SPROM offsets. */
@@ -636,6 +638,17 @@
 	u8 algorithm;
 };
 
+/* Driver initialization status. */
+enum {
+	BCM43xx_STAT_UNINIT,		/* Uninitialized. */
+	BCM43xx_STAT_INITIALIZING,	/* init_board() in progress. */
+	BCM43xx_STAT_INITIALIZED,	/* Fully operational. */
+	BCM43xx_STAT_SHUTTINGDOWN,	/* free_board() in progress. */
+	BCM43xx_STAT_RESTARTING,	/* controller_restart() called. */
+};
+#define bcm43xx_status(bcm)		atomic_read(&(bcm)->init_status)
+#define bcm43xx_set_status(bcm, stat)	atomic_set(&(bcm)->init_status, (stat))
+
 struct bcm43xx_private {
 	struct ieee80211_device *ieee;
 	struct ieee80211softmac_device *softmac;
@@ -645,20 +658,18 @@
 	unsigned int irq;
 
 	void __iomem *mmio_addr;
-	unsigned int mmio_len;
 
-	/* Do not use the lock directly. Use the bcm43xx_lock* helper
-	 * functions, to be MMIO-safe. */
-	spinlock_t _lock;
+	/* Locking, see "theory of locking" text below. */
+	spinlock_t irq_lock;
+	struct mutex mutex;
 
-	/* Driver status flags. */
-	u32 initialized:1,		/* init_board() succeed */
-	    was_initialized:1,		/* for PCI suspend/resume. */
-	    shutting_down:1,		/* free_board() in progress */
+	/* Driver initialization status BCM43xx_STAT_*** */
+	atomic_t init_status;
+
+	u16 was_initialized:1,		/* for PCI suspend/resume. */
 	    __using_pio:1,		/* Internal, use bcm43xx_using_pio(). */
 	    bad_frames_preempt:1,	/* Use "Bad Frames Preemption" (default off) */
 	    reg124_set_0x4:1,		/* Some variable to keep track of IRQ stuff. */
-	    powersaving:1,		/* TRUE if we are in PowerSaving mode. FALSE otherwise. */
 	    short_preamble:1,		/* TRUE, if short preamble is enabled. */
 	    firmware_norelease:1;	/* Do not release the firmware. Used on suspend. */
 
@@ -722,7 +733,7 @@
 	struct tasklet_struct isr_tasklet;
 
 	/* Periodic tasks */
-	struct timer_list periodic_tasks;
+	struct work_struct periodic_work;
 	unsigned int periodic_state;
 
 	struct work_struct restart_work;
@@ -741,27 +752,65 @@
 	const struct firmware *initvals0;
 	const struct firmware *initvals1;
 
+	/* Random Number Generator. */
+	struct hwrng rng;
+	char rng_name[20 + 1];
+
 	/* Debugging stuff follows. */
 #ifdef CONFIG_BCM43XX_DEBUG
 	struct bcm43xx_dfsentry *dfsentry;
 #endif
 };
 
-/* bcm43xx_(un)lock() protect struct bcm43xx_private.
- * Note that _NO_ MMIO writes are allowed. If you want to
- * write to the device through MMIO in the critical section, use
- * the *_mmio lock functions.
- * MMIO read-access is allowed, though.
+
+/*    *** THEORY OF LOCKING ***
+ *
+ * We have two different locks in the bcm43xx driver.
+ * => bcm->mutex:    General sleeping mutex. Protects struct bcm43xx_private
+ *                   and the device registers.
+ * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency.
+ *
+ * We have three types of helper function pairs to utilize these locks.
+ *     (Always use the helper functions.)
+ * 1) bcm43xx_{un}lock_noirq():
+ *     Takes bcm->mutex. Does _not_ protect against IRQ concurrency,
+ *     so it is almost always unsafe, if device IRQs are enabled.
+ *     So only use this, if device IRQs are masked.
+ *     Locking may sleep.
+ *     You can sleep within the critical section.
+ * 2) bcm43xx_{un}lock_irqonly():
+ *     Takes bcm->irq_lock. Does _not_ protect against
+ *     bcm43xx_lock_noirq() critical sections.
+ *     Does only protect against the IRQ handler path and other
+ *     irqonly() critical sections.
+ *     Locking does not sleep.
+ *     You must not sleep within the critical section.
+ * 3) bcm43xx_{un}lock_irqsafe():
+ *     This is the cummulative lock and takes both, mutex and irq_lock.
+ *     Protects against noirq() and irqonly() critical sections (and
+ *     the IRQ handler path).
+ *     Locking may sleep.
+ *     You must not sleep within the critical section.
  */
-#define bcm43xx_lock(bcm, flags)	spin_lock_irqsave(&(bcm)->_lock, flags)
-#define bcm43xx_unlock(bcm, flags)	spin_unlock_irqrestore(&(bcm)->_lock, flags)
-/* bcm43xx_(un)lock_mmio() protect struct bcm43xx_private and MMIO.
- * MMIO write-access to the device is allowed.
- * All MMIO writes are flushed on unlock, so it is guaranteed to not
- * interfere with other threads writing MMIO registers.
- */
-#define bcm43xx_lock_mmio(bcm, flags)	bcm43xx_lock(bcm, flags)
-#define bcm43xx_unlock_mmio(bcm, flags)	do { mmiowb(); bcm43xx_unlock(bcm, flags); } while (0)
+
+/* Lock type 1 */
+#define bcm43xx_lock_noirq(bcm)		mutex_lock(&(bcm)->mutex)
+#define bcm43xx_unlock_noirq(bcm)	mutex_unlock(&(bcm)->mutex)
+/* Lock type 2 */
+#define bcm43xx_lock_irqonly(bcm, flags)	\
+	spin_lock_irqsave(&(bcm)->irq_lock, flags)
+#define bcm43xx_unlock_irqonly(bcm, flags)	\
+	spin_unlock_irqrestore(&(bcm)->irq_lock, flags)
+/* Lock type 3 */
+#define bcm43xx_lock_irqsafe(bcm, flags) do {	\
+	bcm43xx_lock_noirq(bcm);		\
+	bcm43xx_lock_irqonly(bcm, flags);	\
+		} while (0)
+#define bcm43xx_unlock_irqsafe(bcm, flags) do {	\
+	bcm43xx_unlock_irqonly(bcm, flags);	\
+	bcm43xx_unlock_noirq(bcm);		\
+		} while (0)
+
 
 static inline
 struct bcm43xx_private * bcm43xx_priv(struct net_device *dev)
@@ -844,16 +893,6 @@
 	return &(bcm->core_80211_ext[bcm->current_80211_core_idx].radio);
 }
 
-/* Are we running in init_board() context? */
-static inline
-int bcm43xx_is_initializing(struct bcm43xx_private *bcm)
-{
-	if (bcm->initialized)
-		return 0;
-	if (bcm->shutting_down)
-		return 0;
-	return 1;
-}
 
 static inline
 struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
index 35a4fcb..ce2e40b 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
@@ -77,8 +77,8 @@
 
 	down(&big_buffer_sem);
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
 	}
@@ -92,7 +92,7 @@
 	fappend("subsystem_vendor: 0x%04x   subsystem_device: 0x%04x\n",
 		pci_dev->subsystem_vendor, pci_dev->subsystem_device);
 	fappend("IRQ: %d\n", bcm->irq);
-	fappend("mmio_addr: 0x%p   mmio_len: %u\n", bcm->mmio_addr, bcm->mmio_len);
+	fappend("mmio_addr: 0x%p\n", bcm->mmio_addr);
 	fappend("chip_id: 0x%04x   chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev);
 	if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16)))
 		fappend("Radio disabled by hardware!\n");
@@ -121,7 +121,7 @@
 	fappend("\n");
 
 out:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -159,8 +159,8 @@
 	unsigned long flags;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
 	}
@@ -169,7 +169,7 @@
 	fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags);
 
 out:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -188,8 +188,8 @@
 	u64 tsf;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		fappend("Board not initialized.\n");
 		goto out;
 	}
@@ -199,7 +199,7 @@
 		(unsigned int)(tsf & 0xFFFFFFFFULL));
 
 out:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	up(&big_buffer_sem);
 	return res;
@@ -221,8 +221,8 @@
 	        res = -EFAULT;
 		goto out_up;
 	}
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) {
 		printk(KERN_INFO PFX "debugfs: Board not initialized.\n");
 		res = -EFAULT;
 		goto out_unlock;
@@ -233,10 +233,11 @@
 		goto out_unlock;
 	}
 	bcm43xx_tsf_write(bcm, tsf);
+	mmiowb();
 	res = buf_size;
 	
 out_unlock:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 out_up:
 	up(&big_buffer_sem);
 	return res;
@@ -257,7 +258,7 @@
 	int i, cnt, j = 0;
 
 	down(&big_buffer_sem);
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	fappend("Last %d logged xmitstatus blobs (Latest first):\n\n",
 		BCM43xx_NR_LOGGED_XMITSTATUS);
@@ -293,14 +294,14 @@
 			i = BCM43xx_NR_LOGGED_XMITSTATUS - 1;
 	}
 
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	if (*ppos == pos) {
 		/* Done. Drop the copied data. */
 		e->xmitstatus_printing = 0;
 	}
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	up(&big_buffer_sem);
 	return res;
 }
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
index 4b2c02c0..ec80692 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c
@@ -51,12 +51,12 @@
 	struct bcm43xx_private *bcm = led->bcm;
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	if (led->blink_interval) {
 		bcm43xx_led_changestate(led);
 		mod_timer(&led->blink_timer, jiffies + led->blink_interval);
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 static void bcm43xx_led_blink_start(struct bcm43xx_led *led,
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 7ed18ca..27bcf47 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -128,13 +128,15 @@
 	static struct pci_device_id bcm43xx_pci_tbl[] = {
 	/* Broadcom 4303 802.11b */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-		/* Broadcom 4307 802.11b */
+	/* Broadcom 4307 802.11b */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-		/* Broadcom 4318 802.11b/g */
+	/* Broadcom 4318 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4319 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4306 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-		/* Broadcom 4306 802.11a */
+	/* Broadcom 4306 802.11a */
 //	{ PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4309 802.11a/b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
@@ -496,20 +498,31 @@
 	return old_mask;
 }
 
+/* Synchronize IRQ top- and bottom-half.
+ * IRQs must be masked before calling this.
+ * This must not be called with the irq_lock held.
+ */
+static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm)
+{
+	synchronize_irq(bcm->irq);
+	tasklet_disable(&bcm->isr_tasklet);
+}
+
 /* Make sure we don't receive more data from the device. */
 static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm, u32 *oldstate)
 {
-	u32 old;
 	unsigned long flags;
+	u32 old;
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (bcm43xx_is_initializing(bcm) || bcm->shutting_down) {
-		bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
+	if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) {
+		bcm43xx_unlock_irqonly(bcm, flags);
 		return -EBUSY;
 	}
 	old = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
-	tasklet_disable(&bcm->isr_tasklet);
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
+	bcm43xx_synchronize_irq(bcm);
+
 	if (oldstate)
 		*oldstate = old;
 
@@ -1387,7 +1400,7 @@
 			bcm43xx_dmacontroller_rx_reset(bcm, BCM43xx_MMIO_DMA4_BASE);
 #endif
 	}
-	if (bcm->shutting_down) {
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) {
 		bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD,
 		                bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD)
 				& ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002));
@@ -1707,7 +1720,7 @@
 # define bcmirq_handled(irq)	do { /* nothing */ } while (0)
 #endif /* CONFIG_BCM43XX_DEBUG*/
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	reason = bcm->irq_reason;
 	dma_reason[0] = bcm->dma_reason[0];
 	dma_reason[1] = bcm->dma_reason[1];
@@ -1732,7 +1745,8 @@
 		        dma_reason[0], dma_reason[1],
 			dma_reason[2], dma_reason[3]);
 		bcm43xx_controller_restart(bcm, "DMA error");
-		bcm43xx_unlock_mmio(bcm, flags);
+		mmiowb();
+		bcm43xx_unlock_irqonly(bcm, flags);
 		return;
 	}
 	if (unlikely((dma_reason[0] & BCM43xx_DMAIRQ_NONFATALMASK) |
@@ -1819,7 +1833,8 @@
 	if (!modparam_noleds)
 		bcm43xx_leds_update(bcm, activity);
 	bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate);
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 static void pio_irq_workaround(struct bcm43xx_private *bcm,
@@ -1868,7 +1883,7 @@
 	if (!bcm)
 		return IRQ_NONE;
 
-	spin_lock(&bcm->_lock);
+	spin_lock(&bcm->irq_lock);
 
 	reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff) {
@@ -1897,7 +1912,7 @@
 	 * completely, but some careful work is needed to fix this. I think it
 	 * is best to stay with this cheap workaround for now... .
 	 */
-	if (likely(bcm->initialized)) {
+	if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
 		/* disable all IRQs. They are enabled again in the bottom half. */
 		bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 		/* save the reason code and call our bottom half. */
@@ -1907,7 +1922,7 @@
 
 out:
 	mmiowb();
-	spin_unlock(&bcm->_lock);
+	spin_unlock(&bcm->irq_lock);
 
 	return ret;
 }
@@ -2131,6 +2146,13 @@
 	return err;
 }
 
+#ifdef CONFIG_BCM947XX
+static struct pci_device_id bcm43xx_47xx_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
+	{ 0 }
+};
+#endif
+
 static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm)
 {
 	int res;
@@ -2140,11 +2162,15 @@
 	bcm->irq = bcm->pci_dev->irq;
 #ifdef CONFIG_BCM947XX
 	if (bcm->pci_dev->bus->number == 0) {
-		struct pci_dev *d = NULL;
-		/* FIXME: we will probably need more device IDs here... */
-		d = pci_find_device(PCI_VENDOR_ID_BROADCOM, 0x4324, NULL);
-		if (d != NULL) {
-			bcm->irq = d->irq;
+		struct pci_dev *d;
+		struct pci_device_id *id;
+		for (id = bcm43xx_47xx_ids; id->vendor; id++) {
+			d = pci_get_device(id->vendor, id->device, NULL);
+			if (d != NULL) {
+				bcm->irq = d->irq;
+				pci_dev_put(d);
+				break;
+			}
 		}
 	}
 #endif
@@ -3104,15 +3130,10 @@
 	//TODO for APHY (temperature?)
 }
 
-static void bcm43xx_periodic_task_handler(unsigned long d)
+static void do_periodic_work(struct bcm43xx_private *bcm)
 {
-	struct bcm43xx_private *bcm = (struct bcm43xx_private *)d;
-	unsigned long flags;
 	unsigned int state;
 
-	bcm43xx_lock_mmio(bcm, flags);
-
-	assert(bcm->initialized);
 	state = bcm->periodic_state;
 	if (state % 8 == 0)
 		bcm43xx_periodic_every120sec(bcm);
@@ -3120,29 +3141,93 @@
 		bcm43xx_periodic_every60sec(bcm);
 	if (state % 2 == 0)
 		bcm43xx_periodic_every30sec(bcm);
-	bcm43xx_periodic_every15sec(bcm);
+	if (state % 1 == 0)
+		bcm43xx_periodic_every15sec(bcm);
 	bcm->periodic_state = state + 1;
 
-	mod_timer(&bcm->periodic_tasks, jiffies + (HZ * 15));
+	schedule_delayed_work(&bcm->periodic_work, HZ * 15);
+}
 
-	bcm43xx_unlock_mmio(bcm, flags);
+/* Estimate a "Badness" value based on the periodic work
+ * state-machine state. "Badness" is worse (bigger), if the
+ * periodic work will take longer.
+ */
+static int estimate_periodic_work_badness(unsigned int state)
+{
+	int badness = 0;
+
+	if (state % 8 == 0) /* every 120 sec */
+		badness += 10;
+	if (state % 4 == 0) /* every 60 sec */
+		badness += 5;
+	if (state % 2 == 0) /* every 30 sec */
+		badness += 1;
+	if (state % 1 == 0) /* every 15 sec */
+		badness += 1;
+
+#define BADNESS_LIMIT	4
+	return badness;
+}
+
+static void bcm43xx_periodic_work_handler(void *d)
+{
+	struct bcm43xx_private *bcm = d;
+	unsigned long flags;
+	u32 savedirqs = 0;
+	int badness;
+
+	badness = estimate_periodic_work_badness(bcm->periodic_state);
+	if (badness > BADNESS_LIMIT) {
+		/* Periodic work will take a long time, so we want it to
+		 * be preemtible.
+		 */
+		bcm43xx_lock_irqonly(bcm, flags);
+		netif_stop_queue(bcm->net_dev);
+		if (bcm43xx_using_pio(bcm))
+			bcm43xx_pio_freeze_txqueues(bcm);
+		savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
+		bcm43xx_unlock_irqonly(bcm, flags);
+		bcm43xx_lock_noirq(bcm);
+		bcm43xx_synchronize_irq(bcm);
+	} else {
+		/* Periodic work should take short time, so we want low
+		 * locking overhead.
+		 */
+		bcm43xx_lock_irqsafe(bcm, flags);
+	}
+
+	do_periodic_work(bcm);
+
+	if (badness > BADNESS_LIMIT) {
+		bcm43xx_lock_irqonly(bcm, flags);
+		if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) {
+			tasklet_enable(&bcm->isr_tasklet);
+			bcm43xx_interrupt_enable(bcm, savedirqs);
+			if (bcm43xx_using_pio(bcm))
+				bcm43xx_pio_thaw_txqueues(bcm);
+		}
+		netif_wake_queue(bcm->net_dev);
+		mmiowb();
+		bcm43xx_unlock_irqonly(bcm, flags);
+		bcm43xx_unlock_noirq(bcm);
+	} else {
+		mmiowb();
+		bcm43xx_unlock_irqsafe(bcm, flags);
+	}
 }
 
 static void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
 {
-	del_timer_sync(&bcm->periodic_tasks);
+	cancel_rearming_delayed_work(&bcm->periodic_work);
 }
 
 static void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
-	struct timer_list *timer = &(bcm->periodic_tasks);
+	struct work_struct *work = &(bcm->periodic_work);
 
-	assert(bcm->initialized);
-	setup_timer(timer,
-		    bcm43xx_periodic_task_handler,
-		    (unsigned long)bcm);
-	timer->expires = jiffies;
-	add_timer(timer);
+	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+	INIT_WORK(work, bcm43xx_periodic_work_handler, bcm);
+	schedule_work(work);
 }
 
 static void bcm43xx_security_init(struct bcm43xx_private *bcm)
@@ -3152,21 +3237,51 @@
 	bcm43xx_clear_keys(bcm);
 }
 
+static int bcm43xx_rng_read(struct hwrng *rng, u32 *data)
+{
+	struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv;
+	unsigned long flags;
+
+	bcm43xx_lock_irqonly(bcm, flags);
+	*data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG);
+	bcm43xx_unlock_irqonly(bcm, flags);
+
+	return (sizeof(u16));
+}
+
+static void bcm43xx_rng_exit(struct bcm43xx_private *bcm)
+{
+	hwrng_unregister(&bcm->rng);
+}
+
+static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
+{
+	int err;
+
+	snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name),
+		 "%s_%s", KBUILD_MODNAME, bcm->net_dev->name);
+	bcm->rng.name = bcm->rng_name;
+	bcm->rng.data_read = bcm43xx_rng_read;
+	bcm->rng.priv = (unsigned long)bcm;
+	err = hwrng_register(&bcm->rng);
+	if (err)
+		printk(KERN_ERR PFX "RNG init failed (%d)\n", err);
+
+	return err;
+}
+
 /* This is the opposite of bcm43xx_init_board() */
 static void bcm43xx_free_board(struct bcm43xx_private *bcm)
 {
 	int i, err;
-	unsigned long flags;
 
+	bcm43xx_lock_noirq(bcm);
 	bcm43xx_sysfs_unregister(bcm);
-
 	bcm43xx_periodic_tasks_delete(bcm);
 
-	bcm43xx_lock(bcm, flags);
-	bcm->initialized = 0;
-	bcm->shutting_down = 1;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN);
 
+	bcm43xx_rng_exit(bcm);
 	for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) {
 		if (!bcm->core_80211[i].available)
 			continue;
@@ -3180,23 +3295,19 @@
 
 	bcm43xx_pctl_set_crystal(bcm, 0);
 
-	bcm43xx_lock(bcm, flags);
-	bcm->shutting_down = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+	bcm43xx_unlock_noirq(bcm);
 }
 
 static int bcm43xx_init_board(struct bcm43xx_private *bcm)
 {
 	int i, err;
 	int connect_phy;
-	unsigned long flags;
 
 	might_sleep();
 
-	bcm43xx_lock(bcm, flags);
-	bcm->initialized = 0;
-	bcm->shutting_down = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_lock_noirq(bcm);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING);
 
 	err = bcm43xx_pctl_set_crystal(bcm, 1);
 	if (err)
@@ -3248,6 +3359,9 @@
 		bcm43xx_switch_core(bcm, &bcm->core_80211[0]);
 		bcm43xx_mac_enable(bcm);
 	}
+	err = bcm43xx_rng_init(bcm);
+	if (err)
+		goto err_80211_unwind;
 	bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC);
 	bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr));
 	dprintk(KERN_INFO PFX "80211 cores initialized\n");
@@ -3263,9 +3377,7 @@
 	}
 
 	/* Initialization of the board is done. Flag it as such. */
-	bcm43xx_lock(bcm, flags);
-	bcm->initialized = 1;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED);
 
 	bcm43xx_periodic_tasks_setup(bcm);
 	bcm43xx_sysfs_register(bcm);
@@ -3276,6 +3388,8 @@
 
 	assert(err == 0);
 out:
+	bcm43xx_unlock_noirq(bcm);
+
 	return err;
 
 err_80211_unwind:
@@ -3299,8 +3413,7 @@
 
 	bcm43xx_chipset_detach(bcm);
 	/* Do _not_ access the chip, after it is detached. */
-	iounmap(bcm->mmio_addr);
-	
+	pci_iounmap(pci_dev, bcm->mmio_addr);
 	pci_release_regions(pci_dev);
 	pci_disable_device(pci_dev);
 
@@ -3390,40 +3503,26 @@
 	struct net_device *net_dev = bcm->net_dev;
 	int err;
 	int i;
-	unsigned long mmio_start, mmio_flags, mmio_len;
 	u32 coremask;
 
 	err = pci_enable_device(pci_dev);
 	if (err) {
-		printk(KERN_ERR PFX "unable to wake up pci device (%i)\n", err);
+		printk(KERN_ERR PFX "pci_enable_device() failed\n");
 		goto out;
 	}
-	mmio_start = pci_resource_start(pci_dev, 0);
-	mmio_flags = pci_resource_flags(pci_dev, 0);
-	mmio_len = pci_resource_len(pci_dev, 0);
-	if (!(mmio_flags & IORESOURCE_MEM)) {
-		printk(KERN_ERR PFX
-		       "%s, region #0 not an MMIO resource, aborting\n",
-		       pci_name(pci_dev));
-		err = -ENODEV;
-		goto err_pci_disable;
-	}
 	err = pci_request_regions(pci_dev, KBUILD_MODNAME);
 	if (err) {
-		printk(KERN_ERR PFX
-		       "could not access PCI resources (%i)\n", err);
+		printk(KERN_ERR PFX "pci_request_regions() failed\n");
 		goto err_pci_disable;
 	}
 	/* enable PCI bus-mastering */
 	pci_set_master(pci_dev);
-	bcm->mmio_addr = ioremap(mmio_start, mmio_len);
+	bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL);
 	if (!bcm->mmio_addr) {
-		printk(KERN_ERR PFX "%s: cannot remap MMIO, aborting\n",
-		       pci_name(pci_dev));
+		printk(KERN_ERR PFX "pci_iomap() failed\n");
 		err = -EIO;
 		goto err_pci_release;
 	}
-	bcm->mmio_len = mmio_len;
 	net_dev->base_addr = (unsigned long)bcm->mmio_addr;
 
 	bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID,
@@ -3517,7 +3616,7 @@
 err_chipset_detach:
 	bcm43xx_chipset_detach(bcm);
 err_iounmap:
-	iounmap(bcm->mmio_addr);
+	pci_iounmap(pci_dev, bcm->mmio_addr);
 err_pci_release:
 	pci_release_regions(pci_dev);
 err_pci_disable:
@@ -3547,8 +3646,8 @@
 	struct bcm43xx_radioinfo *radio;
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		bcm43xx_mac_suspend(bcm);
 		bcm43xx_radio_selectchannel(bcm, channel, 0);
 		bcm43xx_mac_enable(bcm);
@@ -3556,7 +3655,7 @@
 		radio = bcm43xx_current_radio(bcm);
 		radio->initial_channel = channel;
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 }
 
 /* set_security() callback in struct ieee80211_device */
@@ -3568,9 +3667,9 @@
 	unsigned long flags;
 	int keyidx;
 	
-	dprintk(KERN_INFO PFX "set security called\n");
+	dprintk(KERN_INFO PFX "set security called");
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
 		if (sec->flags & (1<<keyidx)) {
@@ -3581,25 +3680,27 @@
 	
 	if (sec->flags & SEC_ACTIVE_KEY) {
 		secinfo->active_key = sec->active_key;
-		dprintk(KERN_INFO PFX "   .active_key = %d\n", sec->active_key);
+		dprintk(", .active_key = %d", sec->active_key);
 	}
 	if (sec->flags & SEC_UNICAST_GROUP) {
 		secinfo->unicast_uses_group = sec->unicast_uses_group;
-		dprintk(KERN_INFO PFX "   .unicast_uses_group = %d\n", sec->unicast_uses_group);
+		dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group);
 	}
 	if (sec->flags & SEC_LEVEL) {
 		secinfo->level = sec->level;
-		dprintk(KERN_INFO PFX "   .level = %d\n", sec->level);
+		dprintk(", .level = %d", sec->level);
 	}
 	if (sec->flags & SEC_ENABLED) {
 		secinfo->enabled = sec->enabled;
-		dprintk(KERN_INFO PFX "   .enabled = %d\n", sec->enabled);
+		dprintk(", .enabled = %d", sec->enabled);
 	}
 	if (sec->flags & SEC_ENCRYPT) {
 		secinfo->encrypt = sec->encrypt;
-		dprintk(KERN_INFO PFX "   .encrypt = %d\n", sec->encrypt);
+		dprintk(", .encrypt = %d", sec->encrypt);
 	}
-	if (bcm->initialized && !bcm->ieee->host_encrypt) {
+	dprintk("\n");
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED &&
+	    !bcm->ieee->host_encrypt) {
 		if (secinfo->enabled) {
 			/* upload WEP keys to hardware */
 			char null_address[6] = { 0 };
@@ -3633,7 +3734,7 @@
 		} else
 				bcm43xx_clear_keys(bcm);
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 }
 
 /* hard_start_xmit() callback in struct ieee80211_device */
@@ -3645,10 +3746,10 @@
 	int err = -ENODEV;
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (likely(bcm->initialized))
+	bcm43xx_lock_irqonly(bcm, flags);
+	if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED))
 		err = bcm43xx_tx(bcm, txb);
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 
 	return err;
 }
@@ -3663,9 +3764,9 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 	bcm43xx_controller_restart(bcm, "TX timeout");
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3690,9 +3791,11 @@
 static int bcm43xx_net_stop(struct net_device *net_dev)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
+	int err;
 
 	ieee80211softmac_stop(net_dev);
-	bcm43xx_disable_interrupts_sync(bcm, NULL);
+	err = bcm43xx_disable_interrupts_sync(bcm, NULL);
+	assert(!err);
 	bcm43xx_free_board(bcm);
 
 	return 0;
@@ -3704,6 +3807,7 @@
 {
 	int err;
 
+	bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
 	bcm->ieee = netdev_priv(net_dev);
 	bcm->softmac = ieee80211_priv(net_dev);
 	bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan;
@@ -3712,7 +3816,8 @@
 	bcm->pci_dev = pci_dev;
 	bcm->net_dev = net_dev;
 	bcm->bad_frames_preempt = modparam_bad_frames_preempt;
-	spin_lock_init(&bcm->_lock);
+	spin_lock_init(&bcm->irq_lock);
+	mutex_init(&bcm->mutex);
 	tasklet_init(&bcm->isr_tasklet,
 		     (void (*)(unsigned long))bcm43xx_interrupt_tasklet,
 		     (unsigned long)bcm);
@@ -3843,7 +3948,7 @@
 	struct net_device *net_dev = bcm->net_dev;
 	struct pci_dev *pci_dev = bcm->pci_dev;
 	int err;
-	int was_initialized = bcm->initialized;
+	int was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
 
 	netif_stop_queue(bcm->net_dev);
 	tasklet_disable(&bcm->isr_tasklet);
@@ -3878,6 +3983,7 @@
 */
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason)
 {
+	bcm43xx_set_status(bcm, BCM43xx_STAT_RESTARTING);
 	bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL);
 	bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */
 	printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason);
@@ -3896,11 +4002,11 @@
 
 	dprintk(KERN_INFO PFX "Suspending...\n");
 
-	bcm43xx_lock(bcm, flags);
-	bcm->was_initialized = bcm->initialized;
-	if (bcm->initialized)
+	bcm43xx_lock_irqsafe(bcm, flags);
+	bcm->was_initialized = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
+	if (bcm->was_initialized)
 		try_to_shutdown = 1;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	netif_device_detach(net_dev);
 	if (try_to_shutdown) {
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
index b0abac5..f8200de 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c
@@ -1410,7 +1410,10 @@
 u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control)
 {
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
+	u16 ret;
+	unsigned long flags;
 
+	local_irq_save(flags);
 	if (phy->connected) {
 		bcm43xx_phy_write(bcm, 0x15, 0xE300);
 		control <<= 8;
@@ -1430,8 +1433,10 @@
 		bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0);
 		udelay(8);
 	}
+	ret = bcm43xx_phy_read(bcm, 0x002D);
+	local_irq_restore(flags);
 
-	return bcm43xx_phy_read(bcm, 0x002D);
+	return ret;
 }
 
 static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control)
@@ -1648,7 +1653,7 @@
 void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm)
 {
 	static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 };
-	const int is_initializing = bcm43xx_is_initializing(bcm);
+	const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING);
 	struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
 	struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm);
 	u16 h, i, oldi = 0, j;
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index 0aa1bd2..574085c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -262,8 +262,10 @@
 	int err;
 	u16 txctl;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqonly(bcm, flags);
 
+	if (queue->tx_frozen)
+		goto out_unlock;
 	txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL);
 	if (txctl & BCM43xx_PIO_TXCTL_SUSPEND)
 		goto out_unlock;
@@ -298,7 +300,7 @@
 		continue;
 	}
 out_unlock:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqonly(bcm, flags);
 }
 
 static void setup_txqueues(struct bcm43xx_pioqueue *queue)
@@ -374,7 +376,6 @@
 	struct bcm43xx_pio_txpacket *packet, *tmp_packet;
 
 	netif_tx_disable(queue->bcm->net_dev);
-	assert(queue->bcm->shutting_down);
 	tasklet_disable(&queue->txtask);
 
 	list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
@@ -634,5 +635,40 @@
 			  bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL)
 			  & ~BCM43xx_PIO_TXCTL_SUSPEND);
 	bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1);
-	tasklet_schedule(&queue->txtask);
+	if (!list_empty(&queue->txqueue))
+		tasklet_schedule(&queue->txtask);
 }
+
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_pio *pio;
+
+	assert(bcm43xx_using_pio(bcm));
+	pio = bcm43xx_current_pio(bcm);
+	pio->queue0->tx_frozen = 1;
+	pio->queue1->tx_frozen = 1;
+	pio->queue2->tx_frozen = 1;
+	pio->queue3->tx_frozen = 1;
+}
+
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+{
+	struct bcm43xx_pio *pio;
+
+	assert(bcm43xx_using_pio(bcm));
+	pio = bcm43xx_current_pio(bcm);
+	pio->queue0->tx_frozen = 0;
+	pio->queue1->tx_frozen = 0;
+	pio->queue2->tx_frozen = 0;
+	pio->queue3->tx_frozen = 0;
+	if (!list_empty(&pio->queue0->txqueue))
+		tasklet_schedule(&pio->queue0->txtask);
+	if (!list_empty(&pio->queue1->txqueue))
+		tasklet_schedule(&pio->queue1->txtask);
+	if (!list_empty(&pio->queue2->txqueue))
+		tasklet_schedule(&pio->queue2->txtask);
+	if (!list_empty(&pio->queue3->txqueue))
+		tasklet_schedule(&pio->queue3->txtask);
+}
+
+
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
index dfc7820..bc78a3c 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h
@@ -54,6 +54,7 @@
 	u16 mmio_base;
 
 	u8 tx_suspended:1,
+	   tx_frozen:1,
 	   need_workarounds:1; /* Workarounds needed for core.rev < 3 */
 
 	/* Adjusted size of the device internal TX buffer. */
@@ -108,8 +109,12 @@
 				   struct bcm43xx_xmitstatus *status);
 void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue);
 
+/* Suspend a TX queue on hardware level. */
 void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue);
 void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue);
+/* Suspend (freeze) the TX tasklet (software level). */
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm);
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm);
 
 #else /* CONFIG_BCM43XX_PIO */
 
@@ -145,6 +150,14 @@
 void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue)
 {
 }
+static inline
+void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm)
+{
+}
+static inline
+void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm)
+{
+}
 
 #endif /* CONFIG_BCM43XX_PIO */
 #endif /* BCM43xx_PIO_H_ */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
index b438f48..6a23bdc 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
@@ -120,12 +120,12 @@
 			GFP_KERNEL);
 	if (!sprom)
 		return -ENOMEM;
-	bcm43xx_lock_mmio(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	err = bcm43xx_sprom_read(bcm, sprom);
 	if (!err)
 		err = sprom2hex(sprom, buf, PAGE_SIZE);
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	kfree(sprom);
 
 	return err;
@@ -150,10 +150,10 @@
 	err = hex2sprom(sprom, buf, count);
 	if (err)
 		goto out_kfree;
-	bcm43xx_lock_mmio(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	err = bcm43xx_sprom_write(bcm, sprom);
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqsafe(bcm, flags);
 out_kfree:
 	kfree(sprom);
 
@@ -170,15 +170,13 @@
 					    char *buf)
 {
 	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	unsigned long flags;
 	int err;
 	ssize_t count = 0;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	bcm43xx_lock(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_noirq(bcm);
 
 	switch (bcm43xx_current_radio(bcm)->interfmode) {
 	case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -195,7 +193,7 @@
 	}
 	err = 0;
 
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_noirq(bcm);
 
 	return err ? err : count;
 
@@ -231,16 +229,15 @@
 		return -EINVAL;
 	}
 
-	bcm43xx_lock_mmio(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
 	if (err) {
 		printk(KERN_ERR PFX "Interference Mitigation not "
 				    "supported by device\n");
 	}
-
-	bcm43xx_unlock_mmio(bcm, flags);
+	mmiowb();
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err ? err : count;
 }
@@ -254,15 +251,13 @@
 					  char *buf)
 {
 	struct bcm43xx_private *bcm = dev_to_bcm(dev);
-	unsigned long flags;
 	int err;
 	ssize_t count;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	bcm43xx_lock(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_noirq(bcm);
 
 	if (bcm->short_preamble)
 		count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n");
@@ -270,7 +265,7 @@
 		count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n");
 
 	err = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_noirq(bcm);
 
 	return err ? err : count;
 }
@@ -290,13 +285,12 @@
 	value = get_boolean(buf, count);
 	if (value < 0)
 		return value;
-	bcm43xx_lock(bcm, flags);
-	assert(bcm->initialized);
+	bcm43xx_lock_irqsafe(bcm, flags);
 
 	bcm->short_preamble = !!value;
 
 	err = 0;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err ? err : count;
 }
@@ -310,7 +304,7 @@
 	struct device *dev = &bcm->pci_dev->dev;
 	int err;
 
-	assert(bcm->initialized);
+	assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED);
 
 	err = device_create_file(dev, &dev_attr_sprom);
 	if (err)
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
index b450639..c35cb3a 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c
@@ -55,13 +55,13 @@
 			       char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 	int i;
+	unsigned long flags;
 	struct bcm43xx_phyinfo *phy;
 	char suffix[7] = { 0 };
 	int have_a = 0, have_b = 0, have_g = 0;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	for (i = 0; i < bcm->nr_80211_available; i++) {
 		phy = &(bcm->core_80211_ext[i].phy);
 		switch (phy->type) {
@@ -77,7 +77,7 @@
 			assert(0);
 		}
 	}
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	i = 0;
 	if (have_a) {
@@ -111,7 +111,7 @@
 	int freq;
 	int err = -EINVAL;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	if ((data->freq.m >= 0) && (data->freq.m <= 1000)) {
 		channel = data->freq.m;
 		freq = bcm43xx_channel_to_freq(bcm, channel);
@@ -121,7 +121,7 @@
 	}
 	if (!bcm43xx_is_valid_channel(bcm, channel))
 		goto out_unlock;
-	if (bcm->initialized) {
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		//ieee80211softmac_disassoc(softmac, $REASON);
 		bcm43xx_mac_suspend(bcm);
 		err = bcm43xx_radio_selectchannel(bcm, channel, 0);
@@ -131,7 +131,7 @@
 		err = 0;
 	}
 out_unlock:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -147,11 +147,10 @@
 	int err = -ENODEV;
 	u16 channel;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	radio = bcm43xx_current_radio(bcm);
 	channel = radio->channel;
 	if (channel == 0xFF) {
-		assert(!bcm->initialized);
 		channel = radio->initial_channel;
 		if (channel == 0xFF)
 			goto out_unlock;
@@ -163,7 +162,7 @@
 
 	err = 0;
 out_unlock:
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -181,13 +180,13 @@
 	if (mode == IW_MODE_AUTO)
 		mode = BCM43xx_INITIAL_IWMODE;
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		if (bcm->ieee->iw_mode != mode)
 			bcm43xx_set_iwmode(bcm, mode);
 	} else
 		bcm->ieee->iw_mode = mode;
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -200,9 +199,9 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	data->mode = bcm->ieee->iw_mode;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -255,7 +254,7 @@
 			  IW_ENC_CAPA_CIPHER_TKIP |
 			  IW_ENC_CAPA_CIPHER_CCMP;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	phy = bcm43xx_current_phy(bcm);
 
 	range->num_bitrates = 0;
@@ -302,7 +301,7 @@
 	}
 	range->num_frequency = j;
 
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -313,14 +312,13 @@
 			       char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 	size_t len;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_noirq(bcm);
 	len =  min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE);
 	memcpy(bcm->nick, extra, len);
 	bcm->nick[len] = '\0';
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_noirq(bcm);
 
 	return 0;
 }
@@ -331,15 +329,14 @@
 			       char *extra)
 {
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
-	unsigned long flags;
 	size_t len;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_noirq(bcm);
 	len = strlen(bcm->nick) + 1;
 	memcpy(extra, bcm->nick, len);
 	data->data.length = (__u16)len;
 	data->data.flags = 1;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_noirq(bcm);
 
 	return 0;
 }
@@ -353,7 +350,7 @@
 	unsigned long flags;
 	int err = -EINVAL;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	if (data->rts.disabled) {
 		bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD;
 		err = 0;
@@ -364,7 +361,7 @@
 			err = 0;
 		}
 	}
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -377,11 +374,11 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	data->rts.value = bcm->rts_threshold;
 	data->rts.fixed = 0;
 	data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD);
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -395,7 +392,7 @@
 	unsigned long flags;
 	int err = -EINVAL;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	if (data->frag.disabled) {
 		bcm->ieee->fts = MAX_FRAG_THRESHOLD;
 		err = 0;
@@ -406,7 +403,7 @@
 			err = 0;
 		}
 	}
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -419,11 +416,11 @@
 	struct bcm43xx_private *bcm = bcm43xx_priv(net_dev);
 	unsigned long flags;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	data->frag.value = bcm->ieee->fts;
 	data->frag.fixed = 0;
 	data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD);
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -445,8 +442,8 @@
 		return -EOPNOTSUPP;
 	}
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (!bcm->initialized)
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
 		goto out_unlock;
 	radio = bcm43xx_current_radio(bcm);
 	phy = bcm43xx_current_phy(bcm);
@@ -469,7 +466,7 @@
 	err = 0;
 
 out_unlock:
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -484,8 +481,8 @@
 	unsigned long flags;
 	int err = -ENODEV;
 
-	bcm43xx_lock(bcm, flags);
-	if (!bcm->initialized)
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)
 		goto out_unlock;
 	radio = bcm43xx_current_radio(bcm);
 	/* desired dBm value is in Q5.2 */
@@ -496,7 +493,7 @@
 
 	err = 0;
 out_unlock:
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -583,8 +580,8 @@
 		return -EINVAL;
 	}
 
-	bcm43xx_lock_mmio(bcm, flags);
-	if (bcm->initialized) {
+	bcm43xx_lock_irqsafe(bcm, flags);
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
 		err = bcm43xx_radio_set_interference_mitigation(bcm, mode);
 		if (err) {
 			printk(KERN_ERR PFX "Interference Mitigation not "
@@ -598,7 +595,7 @@
 		} else
 			bcm43xx_current_radio(bcm)->interfmode = mode;
 	}
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return err;
 }
@@ -612,9 +609,9 @@
 	unsigned long flags;
 	int mode;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	mode = bcm43xx_current_radio(bcm)->interfmode;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	switch (mode) {
 	case BCM43xx_RADIO_INTERFMODE_NONE:
@@ -644,9 +641,9 @@
 	int on;
 
 	on = *((int *)extra);
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	bcm->short_preamble = !!on;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -660,9 +657,9 @@
 	unsigned long flags;
 	int on;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	on = bcm->short_preamble;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	if (on)
 		strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING);
@@ -684,11 +681,11 @@
 	
 	on = *((int *)extra);
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	bcm->ieee->host_encrypt = !!on;
 	bcm->ieee->host_decrypt = !!on;
 	bcm->ieee->host_build_iv = !on;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	return 0;
 }
@@ -702,9 +699,9 @@
 	unsigned long flags;
 	int on;
 
-	bcm43xx_lock(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	on = bcm->ieee->host_encrypt;
-	bcm43xx_unlock(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 
 	if (on)
 		strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING);
@@ -767,11 +764,11 @@
 	if (!sprom)
 		goto out;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	err = -ENODEV;
-	if (bcm->initialized)
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
 		err = bcm43xx_sprom_read(bcm, sprom);
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 	if (!err)
 		data->data.length = sprom2hex(sprom, extra);
 	kfree(sprom);
@@ -812,11 +809,11 @@
 	if (err)
 		goto out_kfree;
 
-	bcm43xx_lock_mmio(bcm, flags);
+	bcm43xx_lock_irqsafe(bcm, flags);
 	err = -ENODEV;
-	if (bcm->initialized)
+	if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)
 		err = bcm43xx_sprom_write(bcm, sprom);
-	bcm43xx_unlock_mmio(bcm, flags);
+	bcm43xx_unlock_irqsafe(bcm, flags);
 out_kfree:
 	kfree(sprom);
 out:
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
index 346c6fe..2aa2f38 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/hermes.c
@@ -121,12 +121,6 @@
 	hw->iobase = address;
 	hw->reg_spacing = reg_spacing;
 	hw->inten = 0x0;
-
-#ifdef HERMES_DEBUG_BUFFER
-	hw->dbufp = 0;
-	memset(&hw->dbuf, 0xff, sizeof(hw->dbuf));
-	memset(&hw->profile, 0, sizeof(hw->profile));
-#endif
 }
 
 int hermes_init(hermes_t *hw)
@@ -347,19 +341,6 @@
 		reg = hermes_read_reg(hw, oreg);
 	}
 
-#ifdef HERMES_DEBUG_BUFFER
-	hw->profile[HERMES_BAP_BUSY_TIMEOUT - k]++;
-
-	if (k < HERMES_BAP_BUSY_TIMEOUT) {
-		struct hermes_debug_entry *e = 
-			&hw->dbuf[(hw->dbufp++) % HERMES_DEBUG_BUFSIZE];
-		e->bap = bap;
-		e->id = id;
-		e->offset = offset;
-		e->cycles = HERMES_BAP_BUSY_TIMEOUT - k;
-	}
-#endif
-
 	if (reg & HERMES_OFFSET_BUSY)
 		return -ETIMEDOUT;
 
@@ -419,8 +400,7 @@
 }
 
 /* Write a block of data to the chip's buffer, via the
- * BAP. Synchronization/serialization is the caller's problem. len
- * must be even.
+ * BAP. Synchronization/serialization is the caller's problem.
  *
  * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
  */
@@ -430,7 +410,7 @@
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int err = 0;
 
-	if ( (len < 0) || (len % 2) )
+	if (len < 0)
 		return -EINVAL;
 
 	err = hermes_bap_seek(hw, bap, id, offset);
@@ -438,49 +418,12 @@
 		goto out;
 	
 	/* Actually do the transfer */
-	hermes_write_words(hw, dreg, buf, len/2);
+	hermes_write_bytes(hw, dreg, buf, len);
 
  out:	
 	return err;
 }
 
-/* Write a block of data to the chip's buffer with padding if
- * neccessary, via the BAP. Synchronization/serialization is the
- * caller's problem. len must be even.
- *
- * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
- */
-int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf, unsigned data_len, int len,
-		      u16 id, u16 offset)
-{
-	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
-	int err = 0;
-
-	if (len < 0 || len % 2 || data_len > len)
-		return -EINVAL;
-
-	err = hermes_bap_seek(hw, bap, id, offset);
-	if (err)
-		goto out;
-
-	/* Transfer all the complete words of data */
-	hermes_write_words(hw, dreg, buf, data_len/2);
-	/* If there is an odd byte left over pad and transfer it */
-	if (data_len & 1) {
-		u8 end[2];
-		end[1] = 0;
-		end[0] = ((unsigned char *)buf)[data_len - 1];
-		hermes_write_words(hw, dreg, end, 1);
-		data_len ++;
-	}
-	/* Now send zeros for the padding */
-	if (data_len < len)
-		hermes_clear_words(hw, dreg, (len - data_len) / 2);
-	/* Complete */
- out:
-	return err;
-}
-
 /* Read a Length-Type-Value record from the card.
  *
  * If length is NULL, we ignore the length read from the card, and
@@ -553,7 +496,7 @@
 
 	count = length - 1;
 
-	hermes_write_words(hw, dreg, value, count);
+	hermes_write_bytes(hw, dreg, value, count << 1);
 
 	err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, 
 				rid, NULL);
@@ -568,7 +511,6 @@
 
 EXPORT_SYMBOL(hermes_bap_pread);
 EXPORT_SYMBOL(hermes_bap_pwrite);
-EXPORT_SYMBOL(hermes_bap_pwrite_pad);
 EXPORT_SYMBOL(hermes_read_ltv);
 EXPORT_SYMBOL(hermes_write_ltv);
 
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 7644f72..8e3f0e3 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -328,16 +328,6 @@
 	u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
 } __attribute__ ((packed));
 
-// #define HERMES_DEBUG_BUFFER 1
-#define HERMES_DEBUG_BUFSIZE 4096
-struct hermes_debug_entry {
-	int bap;
-	u16 id, offset;
-	int cycles;
-};
-
-#ifdef __KERNEL__
-
 /* Timeouts */
 #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
 
@@ -347,14 +337,7 @@
 	int reg_spacing;
 #define HERMES_16BIT_REGSPACING	0
 #define HERMES_32BIT_REGSPACING	1
-
 	u16 inten; /* Which interrupts should be enabled? */
-
-#ifdef HERMES_DEBUG_BUFFER
-	struct hermes_debug_entry dbuf[HERMES_DEBUG_BUFSIZE];
-	unsigned long dbufp;
-	unsigned long profile[HERMES_BAP_BUSY_TIMEOUT+1];
-#endif
 } hermes_t;
 
 /* Register access convenience macros */
@@ -376,8 +359,6 @@
 		       u16 id, u16 offset);
 int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
 			u16 id, u16 offset);
-int hermes_bap_pwrite_pad(hermes_t *hw, int bap, const void *buf,
-			unsigned data_len, int len, u16 id, u16 offset);
 int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
 		    u16 *length, void *buf);
 int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
@@ -425,10 +406,13 @@
 	ioread16_rep(hw->iobase + off, buf, count);
 }
 
-static inline void hermes_write_words(struct hermes *hw, int off, const void *buf, unsigned count)
+static inline void hermes_write_bytes(struct hermes *hw, int off,
+				      const char *buf, unsigned count)
 {
 	off = off << hw->reg_spacing;
-	iowrite16_rep(hw->iobase + off, buf, count);
+	iowrite16_rep(hw->iobase + off, buf, count >> 1);
+	if (unlikely(count & 1))
+		iowrite8(buf[count - 1], hw->iobase + off);
 }
 
 static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count)
@@ -462,21 +446,4 @@
 	return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
 }
 
-#else /* ! __KERNEL__ */
-
-/* These are provided for the benefit of userspace drivers and testing programs
-   which use ioperm() or iopl() */
-
-#define hermes_read_reg(base, off) (inw((base) + (off)))
-#define hermes_write_reg(base, off, val) (outw((val), (base) + (off)))
-
-#define hermes_read_regn(base, name) (hermes_read_reg((base), HERMES_##name))
-#define hermes_write_regn(base, name, val) (hermes_write_reg((base), HERMES_##name, (val)))
-
-/* Note that for the next two, the count is in 16-bit words, not bytes */
-#define hermes_read_data(base, off, buf, count) (insw((base) + (off), (buf), (count)))
-#define hermes_write_data(base, off, buf, count) (outsw((base) + (off), (buf), (count)))
-
-#endif /* ! __KERNEL__ */
-
 #endif  /* _HERMES_H */
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 06a5214..4a5be70 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -534,5 +534,4 @@
 }
 
 
-EXPORT_SYMBOL(hostap_dump_tx_80211);
 EXPORT_SYMBOL(hostap_master_start_xmit);
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 06c3fa3..ba13125 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -3276,17 +3276,6 @@
 EXPORT_SYMBOL(hostap_init_ap_proc);
 EXPORT_SYMBOL(hostap_free_data);
 EXPORT_SYMBOL(hostap_check_sta_fw_version);
-EXPORT_SYMBOL(hostap_handle_sta_tx);
-EXPORT_SYMBOL(hostap_handle_sta_release);
 EXPORT_SYMBOL(hostap_handle_sta_tx_exc);
-EXPORT_SYMBOL(hostap_update_sta_ps);
-EXPORT_SYMBOL(hostap_handle_sta_rx);
-EXPORT_SYMBOL(hostap_is_sta_assoc);
-EXPORT_SYMBOL(hostap_is_sta_authorized);
-EXPORT_SYMBOL(hostap_add_sta);
-EXPORT_SYMBOL(hostap_update_rates);
-EXPORT_SYMBOL(hostap_add_wds_links);
-EXPORT_SYMBOL(hostap_wds_link_oper);
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-EXPORT_SYMBOL(hostap_deauth_all_stas);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 55bed92..db03dc2 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -881,6 +881,12 @@
 	PCMCIA_DEVICE_PROD_ID12(
 		"ZoomAir 11Mbps High", "Rate wireless Networking",
 		0x273fe3db, 0x32a1eaee),
+	PCMCIA_DEVICE_PROD_ID123(
+		"Pretec", "CompactWLAN Card 802.11b", "2.5",
+		0x1cadd3e5, 0xe697636c, 0x7a5bfcf1),
+	PCMCIA_DEVICE_PROD_ID123(
+		"U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02",
+		0xc7b8df9d, 0x1700d087, 0x4b74baa0),
 	PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 8dd4c44..93786f4 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -1125,11 +1125,9 @@
 EXPORT_SYMBOL(hostap_dump_rx_header);
 EXPORT_SYMBOL(hostap_dump_tx_header);
 EXPORT_SYMBOL(hostap_80211_header_parse);
-EXPORT_SYMBOL(hostap_80211_prism_header_parse);
 EXPORT_SYMBOL(hostap_80211_get_hdrlen);
 EXPORT_SYMBOL(hostap_get_stats);
 EXPORT_SYMBOL(hostap_setup_dev);
-EXPORT_SYMBOL(hostap_proc);
 EXPORT_SYMBOL(hostap_set_multicast_list_queue);
 EXPORT_SYMBOL(hostap_set_hostapd);
 EXPORT_SYMBOL(hostap_set_hostapd_sta);
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index 72335c8..94aeb23 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -1485,7 +1485,7 @@
 		 *
 		 * Sending the PREPARE_FOR_POWER_DOWN will restrict the
 		 * hardware from going into standby mode and will transition
-		 * out of D0-standy if it is already in that state.
+		 * out of D0-standby if it is already in that state.
 		 *
 		 * STATUS_PREPARE_POWER_DOWN_COMPLETE will be sent by the
 		 * driver upon completion.  Once received, the driver can
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index bca89cf..a8a8f97 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -33,7 +33,44 @@
 #include "ipw2200.h"
 #include <linux/version.h>
 
-#define IPW2200_VERSION "git-1.1.1"
+
+#ifndef KBUILD_EXTMOD
+#define VK "k"
+#else
+#define VK
+#endif
+
+#ifdef CONFIG_IPW2200_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+#ifdef CONFIG_IPW2200_MONITOR
+#define VM "m"
+#else
+#define VM
+#endif
+
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+#define VP "p"
+#else
+#define VP
+#endif
+
+#ifdef CONFIG_IPW2200_RADIOTAP
+#define VR "r"
+#else
+#define VR
+#endif
+
+#ifdef CONFIG_IPW2200_QOS
+#define VQ "q"
+#else
+#define VQ
+#endif
+
+#define IPW2200_VERSION "1.1.2" VK VD VM VP VR VQ
 #define DRV_DESCRIPTION	"Intel(R) PRO/Wireless 2200/2915 Network Driver"
 #define DRV_COPYRIGHT	"Copyright(c) 2003-2006 Intel Corporation"
 #define DRV_VERSION     IPW2200_VERSION
@@ -46,7 +83,9 @@
 MODULE_LICENSE("GPL");
 
 static int cmdlog = 0;
+#ifdef CONFIG_IPW2200_DEBUG
 static int debug = 0;
+#endif
 static int channel = 0;
 static int mode = 0;
 
@@ -61,8 +100,14 @@
 static const char ipw_modes[] = {
 	'a', 'b', 'g', '?'
 };
+static int antenna = CFG_SYS_ANTENNA_BOTH;
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static int rtap_iface = 0;     /* def: 0 -- do not create rtap interface */
+#endif
+
+
+#ifdef CONFIG_IPW2200_QOS
 static int qos_enable = 0;
 static int qos_burst_enable = 0;
 static int qos_no_ack_mask = 0;
@@ -126,7 +171,7 @@
 				       *qos_param);
 static int ipw_send_qos_info_command(struct ipw_priv *priv, struct ieee80211_qos_information_element
 				     *qos_param);
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev);
 static void ipw_remove_current_network(struct ipw_priv *priv);
@@ -488,7 +533,7 @@
 	ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask);
 }
 
-static inline void ipw_enable_interrupts(struct ipw_priv *priv)
+static inline void __ipw_enable_interrupts(struct ipw_priv *priv)
 {
 	if (priv->status & STATUS_INT_ENABLED)
 		return;
@@ -496,7 +541,7 @@
 	ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL);
 }
 
-static inline void ipw_disable_interrupts(struct ipw_priv *priv)
+static inline void __ipw_disable_interrupts(struct ipw_priv *priv)
 {
 	if (!(priv->status & STATUS_INT_ENABLED))
 		return;
@@ -504,6 +549,24 @@
 	ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL);
 }
 
+static inline void ipw_enable_interrupts(struct ipw_priv *priv)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->irq_lock, flags);
+	__ipw_enable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
+static inline void ipw_disable_interrupts(struct ipw_priv *priv)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->irq_lock, flags);
+	__ipw_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->irq_lock, flags);
+}
+
 #ifdef CONFIG_IPW2200_DEBUG
 static char *ipw_error_desc(u32 val)
 {
@@ -1166,12 +1229,6 @@
 	return error;
 }
 
-static void ipw_free_error_log(struct ipw_fw_error *error)
-{
-	if (error)
-		kfree(error);
-}
-
 static ssize_t show_event_log(struct device *d,
 			      struct device_attribute *attr, char *buf)
 {
@@ -1233,10 +1290,9 @@
 			   const char *buf, size_t count)
 {
 	struct ipw_priv *priv = dev_get_drvdata(d);
-	if (priv->error) {
-		ipw_free_error_log(priv->error);
-		priv->error = NULL;
-	}
+
+	kfree(priv->error);
+	priv->error = NULL;
 	return count;
 }
 
@@ -1269,6 +1325,105 @@
 
 static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL);
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static void ipw_prom_free(struct ipw_priv *priv);
+static int ipw_prom_alloc(struct ipw_priv *priv);
+static ssize_t store_rtap_iface(struct device *d,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct ipw_priv *priv = dev_get_drvdata(d);
+	int rc = 0;
+
+	if (count < 1)
+		return -EINVAL;
+
+	switch (buf[0]) {
+	case '0':
+		if (!rtap_iface)
+			return count;
+
+		if (netif_running(priv->prom_net_dev)) {
+			IPW_WARNING("Interface is up.  Cannot unregister.\n");
+			return count;
+		}
+
+		ipw_prom_free(priv);
+		rtap_iface = 0;
+		break;
+
+	case '1':
+		if (rtap_iface)
+			return count;
+
+		rc = ipw_prom_alloc(priv);
+		if (!rc)
+			rtap_iface = 1;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (rc) {
+		IPW_ERROR("Failed to register promiscuous network "
+			  "device (error %d).\n", rc);
+	}
+
+	return count;
+}
+
+static ssize_t show_rtap_iface(struct device *d,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct ipw_priv *priv = dev_get_drvdata(d);
+	if (rtap_iface)
+		return sprintf(buf, "%s", priv->prom_net_dev->name);
+	else {
+		buf[0] = '-';
+		buf[1] = '1';
+		buf[2] = '\0';
+		return 3;
+	}
+}
+
+static DEVICE_ATTR(rtap_iface, S_IWUSR | S_IRUSR, show_rtap_iface,
+		   store_rtap_iface);
+
+static ssize_t store_rtap_filter(struct device *d,
+			 struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct ipw_priv *priv = dev_get_drvdata(d);
+
+	if (!priv->prom_priv) {
+		IPW_ERROR("Attempting to set filter without "
+			  "rtap_iface enabled.\n");
+		return -EPERM;
+	}
+
+	priv->prom_priv->filter = simple_strtol(buf, NULL, 0);
+
+	IPW_DEBUG_INFO("Setting rtap filter to " BIT_FMT16 "\n",
+		       BIT_ARG16(priv->prom_priv->filter));
+
+	return count;
+}
+
+static ssize_t show_rtap_filter(struct device *d,
+			struct device_attribute *attr,
+			char *buf)
+{
+	struct ipw_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "0x%04X",
+		       priv->prom_priv ? priv->prom_priv->filter : 0);
+}
+
+static DEVICE_ATTR(rtap_filter, S_IWUSR | S_IRUSR, show_rtap_filter,
+		   store_rtap_filter);
+#endif
+
 static ssize_t show_scan_age(struct device *d, struct device_attribute *attr,
 			     char *buf)
 {
@@ -1712,7 +1867,7 @@
 	unsigned long flags;
 	int rc = 0;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&priv->irq_lock, flags);
 
 	inta = ipw_read32(priv, IPW_INTA_RW);
 	inta_mask = ipw_read32(priv, IPW_INTA_MASK_R);
@@ -1721,6 +1876,10 @@
 	/* Add any cached INTA values that need to be handled */
 	inta |= priv->isr_inta;
 
+	spin_unlock_irqrestore(&priv->irq_lock, flags);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
 	/* handle all the justifications for the interrupt */
 	if (inta & IPW_INTA_BIT_RX_TRANSFER) {
 		ipw_rx(priv);
@@ -1804,8 +1963,7 @@
 				struct ipw_fw_error *error =
 				    ipw_alloc_error_log(priv);
 				ipw_dump_error_log(priv, error);
-				if (error)
-					ipw_free_error_log(error);
+				kfree(error);
 			}
 #endif
 		} else {
@@ -1849,10 +2007,10 @@
 		IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled);
 	}
 
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	/* enable all interrupts */
 	ipw_enable_interrupts(priv);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 #define IPW_CMD(x) case IPW_CMD_ ## x : return #x
@@ -2025,16 +2183,11 @@
 	return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE);
 }
 
-static int ipw_send_system_config(struct ipw_priv *priv,
-				  struct ipw_sys_config *config)
+static int ipw_send_system_config(struct ipw_priv *priv)
 {
-	if (!priv || !config) {
-		IPW_ERROR("Invalid args\n");
-		return -1;
-	}
-
-	return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, sizeof(*config),
-				config);
+	return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG,
+				sizeof(priv->sys_config),
+				&priv->sys_config);
 }
 
 static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len)
@@ -3104,10 +3257,10 @@
 
 
 struct ipw_fw {
-	u32 ver;
-	u32 boot_size;
-	u32 ucode_size;
-	u32 fw_size;
+	__le32 ver;
+	__le32 boot_size;
+	__le32 ucode_size;
+	__le32 fw_size;
 	u8 data[0];
 };
 
@@ -3131,8 +3284,8 @@
 
 	fw = (void *)(*raw)->data;
 
-	if ((*raw)->size < sizeof(*fw) +
-	    fw->boot_size + fw->ucode_size + fw->fw_size) {
+	if ((*raw)->size < sizeof(*fw) + le32_to_cpu(fw->boot_size) +
+	    le32_to_cpu(fw->ucode_size) + le32_to_cpu(fw->fw_size)) {
 		IPW_ERROR("%s is too small or corrupt (%zd)\n",
 			  name, (*raw)->size);
 		return -EINVAL;
@@ -3237,8 +3390,9 @@
 
 	fw = (void *)raw->data;
 	boot_img = &fw->data[0];
-	ucode_img = &fw->data[fw->boot_size];
-	fw_img = &fw->data[fw->boot_size + fw->ucode_size];
+	ucode_img = &fw->data[le32_to_cpu(fw->boot_size)];
+	fw_img = &fw->data[le32_to_cpu(fw->boot_size) +
+			   le32_to_cpu(fw->ucode_size)];
 
 	if (rc < 0)
 		goto error;
@@ -3272,7 +3426,7 @@
 			IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND);
 
 	/* DMA the initial boot firmware into the device */
-	rc = ipw_load_firmware(priv, boot_img, fw->boot_size);
+	rc = ipw_load_firmware(priv, boot_img, le32_to_cpu(fw->boot_size));
 	if (rc < 0) {
 		IPW_ERROR("Unable to load boot firmware: %d\n", rc);
 		goto error;
@@ -3294,7 +3448,7 @@
 	ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE);
 
 	/* DMA the ucode into the device */
-	rc = ipw_load_ucode(priv, ucode_img, fw->ucode_size);
+	rc = ipw_load_ucode(priv, ucode_img, le32_to_cpu(fw->ucode_size));
 	if (rc < 0) {
 		IPW_ERROR("Unable to load ucode: %d\n", rc);
 		goto error;
@@ -3304,7 +3458,7 @@
 	ipw_stop_nic(priv);
 
 	/* DMA bss firmware into the device */
-	rc = ipw_load_firmware(priv, fw_img, fw->fw_size);
+	rc = ipw_load_firmware(priv, fw_img, le32_to_cpu(fw->fw_size));
 	if (rc < 0) {
 		IPW_ERROR("Unable to load firmware: %d\n", rc);
 		goto error;
@@ -3700,7 +3854,17 @@
 static void ipw_system_config(void *data)
 {
 	struct ipw_priv *priv = data;
-	ipw_send_system_config(priv, &priv->sys_config);
+
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) {
+		priv->sys_config.accept_all_data_frames = 1;
+		priv->sys_config.accept_non_directed_frames = 1;
+		priv->sys_config.accept_all_mgmt_bcpr = 1;
+		priv->sys_config.accept_all_mgmt_frames = 1;
+	}
+#endif
+
+	ipw_send_system_config(priv);
 }
 
 struct ipw_status_code {
@@ -3771,6 +3935,13 @@
 	memset(avg, 0, sizeof(*avg));
 }
 
+#define DEPTH_RSSI 8
+#define DEPTH_NOISE 16
+static s16 exponential_average(s16 prev_avg, s16 val, u8 depth)
+{
+	return ((depth-1)*prev_avg +  val)/depth;
+}
+
 static void average_add(struct average *avg, s16 val)
 {
 	avg->sum -= avg->entries[avg->pos];
@@ -3800,8 +3971,8 @@
 	priv->quality = 0;
 
 	average_init(&priv->average_missed_beacons);
-	average_init(&priv->average_rssi);
-	average_init(&priv->average_noise);
+	priv->exp_avg_rssi = -60;
+	priv->exp_avg_noise = -85 + 0x100;
 
 	priv->last_rate = 0;
 	priv->last_missed_beacons = 0;
@@ -4008,7 +4179,7 @@
 	IPW_DEBUG_STATS("Tx quality   : %3d%% (%u errors, %u packets)\n",
 			tx_quality, tx_failures_delta, tx_packets_delta);
 
-	rssi = average_value(&priv->average_rssi);
+	rssi = priv->exp_avg_rssi;
 	signal_quality =
 	    (100 *
 	     (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) *
@@ -4185,7 +4356,7 @@
 					queue_work(priv->workqueue,
 						   &priv->system_config);
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \
 			 le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl))
 					if ((priv->status & STATUS_AUTH) &&
@@ -4482,6 +4653,24 @@
 				 && priv->status & STATUS_ASSOCIATED)
 				queue_delayed_work(priv->workqueue,
 						   &priv->request_scan, HZ);
+
+			/* Send an empty event to user space.
+			 * We don't send the received data on the event because
+			 * it would require us to do complex transcoding, and
+			 * we want to minimise the work done in the irq handler
+			 * Use a request to extract the data.
+			 * Also, we generate this even for any scan, regardless
+			 * on how the scan was initiated. User space can just
+			 * sync on periodic scan to get fresh data...
+			 * Jean II */
+			if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) {
+				union iwreq_data wrqu;
+
+				wrqu.data.length = 0;
+				wrqu.data.flags = 0;
+				wireless_send_event(priv->net_dev, SIOCGIWSCAN,
+						    &wrqu, NULL);
+			}
 			break;
 		}
 
@@ -4577,11 +4766,10 @@
 
 	case HOST_NOTIFICATION_NOISE_STATS:{
 			if (notif->size == sizeof(u32)) {
-				priv->last_noise =
-				    (u8) (le32_to_cpu(notif->u.noise.value) &
-					  0xff);
-				average_add(&priv->average_noise,
-					    priv->last_noise);
+				priv->exp_avg_noise =
+				    exponential_average(priv->exp_avg_noise,
+				    (u8) (le32_to_cpu(notif->u.noise.value) & 0xff),
+				    DEPTH_NOISE);
 				break;
 			}
 
@@ -6170,8 +6358,6 @@
 {
 	/* make sure WPA is enabled */
 	ipw_wpa_enable(priv, 1);
-
-	ipw_disassociate(priv);
 }
 
 static int ipw_set_rsn_capa(struct ipw_priv *priv,
@@ -6365,6 +6551,7 @@
 
 	case IW_AUTH_WPA_ENABLED:
 		ret = ipw_wpa_enable(priv, param->value);
+		ipw_disassociate(priv);
 		break;
 
 	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
@@ -6506,7 +6693,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 
 /* QoS */
 /*
@@ -6853,61 +7040,55 @@
 	return from_priority_to_tx_queue[priority] - 1;
 }
 
-/*
-* add QoS parameter to the TX command
-*/
-static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
-					u16 priority,
-					struct tfd_data *tfd, u8 unicast)
+static int ipw_is_qos_active(struct net_device *dev,
+			     struct sk_buff *skb)
 {
-	int ret = 0;
-	int tx_queue_id = 0;
+	struct ipw_priv *priv = ieee80211_priv(dev);
 	struct ieee80211_qos_data *qos_data = NULL;
 	int active, supported;
-	unsigned long flags;
+	u8 *daddr = skb->data + ETH_ALEN;
+	int unicast = !is_multicast_ether_addr(daddr);
 
 	if (!(priv->status & STATUS_ASSOCIATED))
 		return 0;
 
 	qos_data = &priv->assoc_network->qos_data;
 
-	spin_lock_irqsave(&priv->ieee->lock, flags);
-
 	if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
 		if (unicast == 0)
 			qos_data->active = 0;
 		else
 			qos_data->active = qos_data->supported;
 	}
-
 	active = qos_data->active;
 	supported = qos_data->supported;
-
-	spin_unlock_irqrestore(&priv->ieee->lock, flags);
-
 	IPW_DEBUG_QOS("QoS  %d network is QoS active %d  supported %d  "
 		      "unicast %d\n",
 		      priv->qos_data.qos_enable, active, supported, unicast);
-	if (active && priv->qos_data.qos_enable) {
-		ret = from_priority_to_tx_queue[priority];
-		tx_queue_id = ret - 1;
-		IPW_DEBUG_QOS("QoS packet priority is %d \n", priority);
-		if (priority <= 7) {
-			tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
-			tfd->tfd.tfd_26.mchdr.qos_ctrl = priority;
-			tfd->tfd.tfd_26.mchdr.frame_ctl |=
-			    IEEE80211_STYPE_QOS_DATA;
+	if (active && priv->qos_data.qos_enable)
+		return 1;
 
-			if (priv->qos_data.qos_no_ack_mask &
-			    (1UL << tx_queue_id)) {
-				tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
-				tfd->tfd.tfd_26.mchdr.qos_ctrl |=
-				    CTRL_QOS_NO_ACK;
-			}
-		}
+	return 0;
+
+}
+/*
+* add QoS parameter to the TX command
+*/
+static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv,
+					u16 priority,
+					struct tfd_data *tfd)
+{
+	int tx_queue_id = 0;
+
+
+	tx_queue_id = from_priority_to_tx_queue[priority] - 1;
+	tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED;
+
+	if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) {
+		tfd->tx_flags &= ~DCT_FLAG_ACK_REQD;
+		tfd->tfd.tfd_26.mchdr.qos_ctrl |= CTRL_QOS_NO_ACK;
 	}
-
-	return ret;
+	return 0;
 }
 
 /*
@@ -6977,7 +7158,7 @@
 				qos_param);
 }
 
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 static int ipw_associate_network(struct ipw_priv *priv,
 				 struct ieee80211_network *network,
@@ -7116,7 +7297,7 @@
 	else
 		priv->sys_config.answer_broadcast_ssid_probe = 0;
 
-	err = ipw_send_system_config(priv, &priv->sys_config);
+	err = ipw_send_system_config(priv);
 	if (err) {
 		IPW_DEBUG_HC("Attempt to send sys config command failed.\n");
 		return err;
@@ -7141,7 +7322,7 @@
 
 	priv->assoc_network = network;
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 	ipw_qos_association(priv, network);
 #endif
 
@@ -7415,7 +7596,7 @@
 	}
 }
 
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
 static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
 					   struct ipw_rx_mem_buffer *rxb,
 					   struct ieee80211_rx_stats *stats)
@@ -7432,15 +7613,7 @@
 	/* Magic struct that slots into the radiotap header -- no reason
 	 * to build this manually element by element, we can write it much
 	 * more efficiently than we can parse it. ORDER MATTERS HERE */
-	struct ipw_rt_hdr {
-		struct ieee80211_radiotap_header rt_hdr;
-		u8 rt_flags;	/* radiotap packet flags */
-		u8 rt_rate;	/* rate in 500kb/s */
-		u16 rt_channel;	/* channel in mhz */
-		u16 rt_chbitmask;	/* channel bitfield */
-		s8 rt_dbmsignal;	/* signal in dbM, kluged to signed */
-		u8 rt_antenna;	/* antenna number */
-	} *ipw_rt;
+	struct ipw_rt_hdr *ipw_rt;
 
 	short len = le16_to_cpu(pkt->u.frame.length);
 
@@ -7494,9 +7667,11 @@
 	/* Big bitfield of all the fields we provide in radiotap */
 	ipw_rt->rt_hdr.it_present =
 	    ((1 << IEEE80211_RADIOTAP_FLAGS) |
+	     (1 << IEEE80211_RADIOTAP_TSFT) |
 	     (1 << IEEE80211_RADIOTAP_RATE) |
 	     (1 << IEEE80211_RADIOTAP_CHANNEL) |
 	     (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+	     (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
 	     (1 << IEEE80211_RADIOTAP_ANTENNA));
 
 	/* Zero the flags, we'll add to them as we go */
@@ -7582,6 +7757,217 @@
 }
 #endif
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+#define ieee80211_is_probe_response(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && \
+    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP )
+
+#define ieee80211_is_management(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
+
+#define ieee80211_is_control(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL)
+
+#define ieee80211_is_data(fc) \
+   ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+
+#define ieee80211_is_assoc_request(fc) \
+   ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ)
+
+#define ieee80211_is_reassoc_request(fc) \
+   ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
+
+static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
+				      struct ipw_rx_mem_buffer *rxb,
+				      struct ieee80211_rx_stats *stats)
+{
+	struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data;
+	struct ipw_rx_frame *frame = &pkt->u.frame;
+	struct ipw_rt_hdr *ipw_rt;
+
+	/* First cache any information we need before we overwrite
+	 * the information provided in the skb from the hardware */
+	struct ieee80211_hdr *hdr;
+	u16 channel = frame->received_channel;
+	u8 phy_flags = frame->antennaAndPhy;
+	s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM;
+	s8 noise = frame->noise;
+	u8 rate = frame->rate;
+	short len = le16_to_cpu(pkt->u.frame.length);
+	u64 tsf = 0;
+	struct sk_buff *skb;
+	int hdr_only = 0;
+	u16 filter = priv->prom_priv->filter;
+
+	/* If the filter is set to not include Rx frames then return */
+	if (filter & IPW_PROM_NO_RX)
+		return;
+
+	/* We received data from the HW, so stop the watchdog */
+	priv->prom_net_dev->trans_start = jiffies;
+
+	if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
+		priv->prom_priv->ieee->stats.rx_errors++;
+		IPW_DEBUG_DROP("Corruption detected! Oh no!\n");
+		return;
+	}
+
+	/* We only process data packets if the interface is open */
+	if (unlikely(!netif_running(priv->prom_net_dev))) {
+		priv->prom_priv->ieee->stats.rx_dropped++;
+		IPW_DEBUG_DROP("Dropping packet while interface is not up.\n");
+		return;
+	}
+
+	/* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use
+	 * that now */
+	if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) {
+		/* FIXME: Should alloc bigger skb instead */
+		priv->prom_priv->ieee->stats.rx_dropped++;
+		IPW_DEBUG_DROP("Dropping too large packet in monitor\n");
+		return;
+	}
+
+	hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE;
+	if (ieee80211_is_management(hdr->frame_ctl)) {
+		if (filter & IPW_PROM_NO_MGMT)
+			return;
+		if (filter & IPW_PROM_MGMT_HEADER_ONLY)
+			hdr_only = 1;
+	} else if (ieee80211_is_control(hdr->frame_ctl)) {
+		if (filter & IPW_PROM_NO_CTL)
+			return;
+		if (filter & IPW_PROM_CTL_HEADER_ONLY)
+			hdr_only = 1;
+	} else if (ieee80211_is_data(hdr->frame_ctl)) {
+		if (filter & IPW_PROM_NO_DATA)
+			return;
+		if (filter & IPW_PROM_DATA_HEADER_ONLY)
+			hdr_only = 1;
+	}
+
+	/* Copy the SKB since this is for the promiscuous side */
+	skb = skb_copy(rxb->skb, GFP_ATOMIC);
+	if (skb == NULL) {
+		IPW_ERROR("skb_clone failed for promiscuous copy.\n");
+		return;
+	}
+
+	/* copy the frame data to write after where the radiotap header goes */
+	ipw_rt = (void *)skb->data;
+
+	if (hdr_only)
+		len = ieee80211_get_hdrlen(hdr->frame_ctl);
+
+	memcpy(ipw_rt->payload, hdr, len);
+
+	/* Zero the radiotap static buffer  ...  We only need to zero the bytes
+	 * NOT part of our real header, saves a little time.
+	 *
+	 * No longer necessary since we fill in all our data.  Purge before
+	 * merging patch officially.
+	 * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0,
+	 *        IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr));
+	 */
+
+	ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+	ipw_rt->rt_hdr.it_pad = 0;	/* always good to zero */
+	ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt);	/* total header+data */
+
+	/* Set the size of the skb to the size of the frame */
+	skb_put(skb, ipw_rt->rt_hdr.it_len + len);
+
+	/* Big bitfield of all the fields we provide in radiotap */
+	ipw_rt->rt_hdr.it_present =
+	    ((1 << IEEE80211_RADIOTAP_FLAGS) |
+	     (1 << IEEE80211_RADIOTAP_TSFT) |
+	     (1 << IEEE80211_RADIOTAP_RATE) |
+	     (1 << IEEE80211_RADIOTAP_CHANNEL) |
+	     (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+	     (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+	     (1 << IEEE80211_RADIOTAP_ANTENNA));
+
+	/* Zero the flags, we'll add to them as we go */
+	ipw_rt->rt_flags = 0;
+
+	ipw_rt->rt_tsf = tsf;
+
+	/* Convert to DBM */
+	ipw_rt->rt_dbmsignal = signal;
+	ipw_rt->rt_dbmnoise = noise;
+
+	/* Convert the channel data and set the flags */
+	ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(channel));
+	if (channel > 14) {	/* 802.11a */
+		ipw_rt->rt_chbitmask =
+		    cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
+	} else if (phy_flags & (1 << 5)) {	/* 802.11b */
+		ipw_rt->rt_chbitmask =
+		    cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
+	} else {		/* 802.11g */
+		ipw_rt->rt_chbitmask =
+		    (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ);
+	}
+
+	/* set the rate in multiples of 500k/s */
+	switch (rate) {
+	case IPW_TX_RATE_1MB:
+		ipw_rt->rt_rate = 2;
+		break;
+	case IPW_TX_RATE_2MB:
+		ipw_rt->rt_rate = 4;
+		break;
+	case IPW_TX_RATE_5MB:
+		ipw_rt->rt_rate = 10;
+		break;
+	case IPW_TX_RATE_6MB:
+		ipw_rt->rt_rate = 12;
+		break;
+	case IPW_TX_RATE_9MB:
+		ipw_rt->rt_rate = 18;
+		break;
+	case IPW_TX_RATE_11MB:
+		ipw_rt->rt_rate = 22;
+		break;
+	case IPW_TX_RATE_12MB:
+		ipw_rt->rt_rate = 24;
+		break;
+	case IPW_TX_RATE_18MB:
+		ipw_rt->rt_rate = 36;
+		break;
+	case IPW_TX_RATE_24MB:
+		ipw_rt->rt_rate = 48;
+		break;
+	case IPW_TX_RATE_36MB:
+		ipw_rt->rt_rate = 72;
+		break;
+	case IPW_TX_RATE_48MB:
+		ipw_rt->rt_rate = 96;
+		break;
+	case IPW_TX_RATE_54MB:
+		ipw_rt->rt_rate = 108;
+		break;
+	default:
+		ipw_rt->rt_rate = 0;
+		break;
+	}
+
+	/* antenna number */
+	ipw_rt->rt_antenna = (phy_flags & 3);
+
+	/* set the preamble flag if we have it */
+	if (phy_flags & (1 << 6))
+		ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+	IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len);
+
+	if (!ieee80211_rx(priv->prom_priv->ieee, skb, stats)) {
+		priv->prom_priv->ieee->stats.rx_errors++;
+		dev_kfree_skb_any(skb);
+	}
+}
+#endif
+
 static int is_network_packet(struct ipw_priv *priv,
 				    struct ieee80211_hdr_4addr *header)
 {
@@ -7808,15 +8194,21 @@
 
 				priv->rx_packets++;
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	if (priv->prom_net_dev && netif_running(priv->prom_net_dev))
+		ipw_handle_promiscuous_rx(priv, rxb, &stats);
+#endif
+
 #ifdef CONFIG_IPW2200_MONITOR
 				if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
-#ifdef CONFIG_IEEE80211_RADIOTAP
-					ipw_handle_data_packet_monitor(priv,
-								       rxb,
-								       &stats);
+#ifdef CONFIG_IPW2200_RADIOTAP
+
+                ipw_handle_data_packet_monitor(priv,
+					       rxb,
+					       &stats);
 #else
-					ipw_handle_data_packet(priv, rxb,
-							       &stats);
+		ipw_handle_data_packet(priv, rxb,
+				       &stats);
 #endif
 					break;
 				}
@@ -7837,9 +8229,9 @@
 				if (network_packet && priv->assoc_network) {
 					priv->assoc_network->stats.rssi =
 					    stats.rssi;
-					average_add(&priv->average_rssi,
-						    stats.rssi);
-					priv->last_rx_rssi = stats.rssi;
+					priv->exp_avg_rssi =
+					    exponential_average(priv->exp_avg_rssi,
+					    stats.rssi, DEPTH_RSSI);
 				}
 
 				IPW_DEBUG_RX("Frame: len=%u\n",
@@ -7982,10 +8374,10 @@
 		IPW_DEBUG_INFO("Bind to static channel %d\n", channel);
 		/* TODO: Validate that provided channel is in range */
 	}
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 	ipw_qos_init(priv, qos_enable, qos_burst_enable,
 		     burst_duration_CCK, burst_duration_OFDM);
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 	switch (mode) {
 	case 1:
@@ -7996,7 +8388,7 @@
 #ifdef CONFIG_IPW2200_MONITOR
 	case 2:
 		priv->ieee->iw_mode = IW_MODE_MONITOR;
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
 		priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
 #else
 		priv->net_dev->type = ARPHRD_IEEE80211;
@@ -8251,7 +8643,7 @@
 		priv->net_dev->type = ARPHRD_ETHER;
 
 	if (wrqu->mode == IW_MODE_MONITOR)
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
 		priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
 #else
 		priv->net_dev->type = ARPHRD_IEEE80211;
@@ -8379,7 +8771,8 @@
 	/* Event capability (kernel + driver) */
 	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
 				IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
-				IW_EVENT_CAPA_MASK(SIOCGIWAP));
+				IW_EVENT_CAPA_MASK(SIOCGIWAP) |
+				IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
 	range->event_capa[1] = IW_EVENT_CAPA_K_1;
 
 	range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
@@ -8734,6 +9127,7 @@
 	struct ipw_priv *priv = ieee80211_priv(dev);
 	mutex_lock(&priv->mutex);
 	wrqu->bitrate.value = priv->last_rate;
+	wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0;
 	mutex_unlock(&priv->mutex);
 	IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value);
 	return 0;
@@ -9351,7 +9745,7 @@
 	IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]);
 	if (enable) {
 		if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
-#ifdef CONFIG_IEEE80211_RADIOTAP
+#ifdef CONFIG_IPW2200_RADIOTAP
 			priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
 #else
 			priv->net_dev->type = ARPHRD_IEEE80211;
@@ -9579,8 +9973,8 @@
 	}
 
 	wstats->qual.qual = priv->quality;
-	wstats->qual.level = average_value(&priv->average_rssi);
-	wstats->qual.noise = average_value(&priv->average_noise);
+	wstats->qual.level = priv->exp_avg_rssi;
+	wstats->qual.noise = priv->exp_avg_noise;
 	wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
 	    IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM;
 
@@ -9608,7 +10002,9 @@
 	sys_config->disable_unicast_decryption = 1;
 	sys_config->exclude_multicast_unencrypted = 0;
 	sys_config->disable_multicast_decryption = 1;
-	sys_config->antenna_diversity = CFG_SYS_ANTENNA_SLOW_DIV;
+	if (antenna < CFG_SYS_ANTENNA_BOTH || antenna > CFG_SYS_ANTENNA_B)
+		antenna = CFG_SYS_ANTENNA_BOTH;
+	sys_config->antenna_diversity = antenna;
 	sys_config->pass_crc_to_host = 0;	/* TODO: See if 1 gives us FCS */
 	sys_config->dot11g_auto_detection = 0;
 	sys_config->enable_cts_to_self = 0;
@@ -9647,11 +10043,11 @@
 static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
 			     int pri)
 {
-	struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)
+	struct ieee80211_hdr_3addrqos *hdr = (struct ieee80211_hdr_3addrqos *)
 	    txb->fragments[0]->data;
 	int i = 0;
 	struct tfd_frame *tfd;
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 	int tx_id = ipw_get_tx_queue_number(priv, pri);
 	struct clx2_tx_queue *txq = &priv->txq[tx_id];
 #else
@@ -9662,9 +10058,9 @@
 	u16 remaining_bytes;
 	int fc;
 
+	hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 	switch (priv->ieee->iw_mode) {
 	case IW_MODE_ADHOC:
-		hdr_len = IEEE80211_3ADDR_LEN;
 		unicast = !is_multicast_ether_addr(hdr->addr1);
 		id = ipw_find_station(priv, hdr->addr1);
 		if (id == IPW_INVALID_STATION) {
@@ -9681,7 +10077,6 @@
 	case IW_MODE_INFRA:
 	default:
 		unicast = !is_multicast_ether_addr(hdr->addr3);
-		hdr_len = IEEE80211_3ADDR_LEN;
 		id = 0;
 		break;
 	}
@@ -9759,9 +10154,10 @@
 		/* No hardware encryption */
 		tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP;
 
-#ifdef CONFIG_IPW_QOS
-	ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data), unicast);
-#endif				/* CONFIG_IPW_QOS */
+#ifdef CONFIG_IPW2200_QOS
+	if (fc & IEEE80211_STYPE_QOS_DATA)
+		ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data));
+#endif				/* CONFIG_IPW2200_QOS */
 
 	/* payload */
 	tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2),
@@ -9841,12 +10237,12 @@
 static int ipw_net_is_queue_full(struct net_device *dev, int pri)
 {
 	struct ipw_priv *priv = ieee80211_priv(dev);
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 	int tx_id = ipw_get_tx_queue_number(priv, pri);
 	struct clx2_tx_queue *txq = &priv->txq[tx_id];
 #else
 	struct clx2_tx_queue *txq = &priv->txq[0];
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 	if (ipw_queue_space(&txq->q) < txq->q.high_mark)
 		return 1;
@@ -9854,6 +10250,88 @@
 	return 0;
 }
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
+				      struct ieee80211_txb *txb)
+{
+	struct ieee80211_rx_stats dummystats;
+	struct ieee80211_hdr *hdr;
+	u8 n;
+	u16 filter = priv->prom_priv->filter;
+	int hdr_only = 0;
+
+	if (filter & IPW_PROM_NO_TX)
+		return;
+
+	memset(&dummystats, 0, sizeof(dummystats));
+
+	/* Filtering of fragment chains is done agains the first fragment */
+	hdr = (void *)txb->fragments[0]->data;
+	if (ieee80211_is_management(hdr->frame_ctl)) {
+		if (filter & IPW_PROM_NO_MGMT)
+			return;
+		if (filter & IPW_PROM_MGMT_HEADER_ONLY)
+			hdr_only = 1;
+	} else if (ieee80211_is_control(hdr->frame_ctl)) {
+		if (filter & IPW_PROM_NO_CTL)
+			return;
+		if (filter & IPW_PROM_CTL_HEADER_ONLY)
+			hdr_only = 1;
+	} else if (ieee80211_is_data(hdr->frame_ctl)) {
+		if (filter & IPW_PROM_NO_DATA)
+			return;
+		if (filter & IPW_PROM_DATA_HEADER_ONLY)
+			hdr_only = 1;
+	}
+
+	for(n=0; n<txb->nr_frags; ++n) {
+		struct sk_buff *src = txb->fragments[n];
+		struct sk_buff *dst;
+		struct ieee80211_radiotap_header *rt_hdr;
+		int len;
+
+		if (hdr_only) {
+			hdr = (void *)src->data;
+			len = ieee80211_get_hdrlen(hdr->frame_ctl);
+		} else
+			len = src->len;
+
+		dst = alloc_skb(
+			len + IEEE80211_RADIOTAP_HDRLEN, GFP_ATOMIC);
+		if (!dst) continue;
+
+		rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr));
+
+		rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION;
+		rt_hdr->it_pad = 0;
+		rt_hdr->it_present = 0; /* after all, it's just an idea */
+		rt_hdr->it_present |=  (1 << IEEE80211_RADIOTAP_CHANNEL);
+
+		*(u16*)skb_put(dst, sizeof(u16)) = cpu_to_le16(
+			ieee80211chan2mhz(priv->channel));
+		if (priv->channel > 14) 	/* 802.11a */
+			*(u16*)skb_put(dst, sizeof(u16)) =
+				cpu_to_le16(IEEE80211_CHAN_OFDM |
+					     IEEE80211_CHAN_5GHZ);
+		else if (priv->ieee->mode == IEEE_B) /* 802.11b */
+			*(u16*)skb_put(dst, sizeof(u16)) =
+				cpu_to_le16(IEEE80211_CHAN_CCK |
+					     IEEE80211_CHAN_2GHZ);
+		else 		/* 802.11g */
+			*(u16*)skb_put(dst, sizeof(u16)) =
+				cpu_to_le16(IEEE80211_CHAN_OFDM |
+				 IEEE80211_CHAN_2GHZ);
+
+		rt_hdr->it_len = dst->len;
+
+		memcpy(skb_put(dst, len), src->data, len);
+
+		if (!ieee80211_rx(priv->prom_priv->ieee, dst, &dummystats))
+			dev_kfree_skb_any(dst);
+	}
+}
+#endif
+
 static int ipw_net_hard_start_xmit(struct ieee80211_txb *txb,
 				   struct net_device *dev, int pri)
 {
@@ -9871,6 +10349,11 @@
 		goto fail_unlock;
 	}
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	if (rtap_iface && netif_running(priv->prom_net_dev))
+		ipw_handle_promiscuous_tx(priv, txb);
+#endif
+
 	ret = ipw_tx_skb(priv, txb, pri);
 	if (ret == NETDEV_TX_OK)
 		__ipw_led_activity_on(priv);
@@ -9991,7 +10474,7 @@
 	if (!priv)
 		return IRQ_NONE;
 
-	spin_lock(&priv->lock);
+	spin_lock(&priv->irq_lock);
 
 	if (!(priv->status & STATUS_INT_ENABLED)) {
 		/* Shared IRQ */
@@ -10013,7 +10496,7 @@
 	}
 
 	/* tell the device to stop sending interrupts */
-	ipw_disable_interrupts(priv);
+	__ipw_disable_interrupts(priv);
 
 	/* ack current interrupts */
 	inta &= (IPW_INTA_MASK_ALL & inta_mask);
@@ -10024,11 +10507,11 @@
 
 	tasklet_schedule(&priv->irq_tasklet);
 
-	spin_unlock(&priv->lock);
+	spin_unlock(&priv->irq_lock);
 
 	return IRQ_HANDLED;
       none:
-	spin_unlock(&priv->lock);
+	spin_unlock(&priv->irq_lock);
 	return IRQ_NONE;
 }
 
@@ -10169,10 +10652,10 @@
 	INIT_WORK(&priv->merge_networks,
 		  (void (*)(void *))ipw_merge_adhoc_network, priv);
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 	INIT_WORK(&priv->qos_activate, (void (*)(void *))ipw_bg_qos_activate,
 		  priv);
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
 		     ipw_irq_tasklet, (unsigned long)priv);
@@ -10318,12 +10801,21 @@
 			    |= CFG_BT_COEXISTENCE_OOB;
 	}
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) {
+		priv->sys_config.accept_all_data_frames = 1;
+		priv->sys_config.accept_non_directed_frames = 1;
+		priv->sys_config.accept_all_mgmt_bcpr = 1;
+		priv->sys_config.accept_all_mgmt_frames = 1;
+	}
+#endif
+
 	if (priv->ieee->iw_mode == IW_MODE_ADHOC)
 		priv->sys_config.answer_broadcast_ssid_probe = 1;
 	else
 		priv->sys_config.answer_broadcast_ssid_probe = 0;
 
-	if (ipw_send_system_config(priv, &priv->sys_config))
+	if (ipw_send_system_config(priv))
 		goto error;
 
 	init_supported_rates(priv, &priv->rates);
@@ -10335,10 +10827,10 @@
 		if (ipw_send_rts_threshold(priv, priv->rts_threshold))
 			goto error;
 	}
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
 	IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n");
 	ipw_qos_activate(priv, NULL);
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 	if (ipw_set_random_seed(priv))
 		goto error;
@@ -10639,6 +11131,7 @@
 		if (priv->cmdlog == NULL) {
 			IPW_ERROR("Error allocating %d command log entries.\n",
 				  cmdlog);
+			return -ENOMEM;
 		} else {
 			memset(priv->cmdlog, 0, sizeof(*priv->cmdlog) * cmdlog);
 			priv->cmdlog_len = cmdlog;
@@ -10860,6 +11353,10 @@
 	&dev_attr_led.attr,
 	&dev_attr_speed_scan.attr,
 	&dev_attr_net_stats.attr,
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	&dev_attr_rtap_iface.attr,
+	&dev_attr_rtap_filter.attr,
+#endif
 	NULL
 };
 
@@ -10868,6 +11365,109 @@
 	.attrs = ipw_sysfs_entries,
 };
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+static int ipw_prom_open(struct net_device *dev)
+{
+	struct ipw_prom_priv *prom_priv = ieee80211_priv(dev);
+	struct ipw_priv *priv = prom_priv->priv;
+
+	IPW_DEBUG_INFO("prom dev->open\n");
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+
+	if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
+		priv->sys_config.accept_all_data_frames = 1;
+		priv->sys_config.accept_non_directed_frames = 1;
+		priv->sys_config.accept_all_mgmt_bcpr = 1;
+		priv->sys_config.accept_all_mgmt_frames = 1;
+
+		ipw_send_system_config(priv);
+	}
+
+	return 0;
+}
+
+static int ipw_prom_stop(struct net_device *dev)
+{
+	struct ipw_prom_priv *prom_priv = ieee80211_priv(dev);
+	struct ipw_priv *priv = prom_priv->priv;
+
+	IPW_DEBUG_INFO("prom dev->stop\n");
+
+	if (priv->ieee->iw_mode != IW_MODE_MONITOR) {
+		priv->sys_config.accept_all_data_frames = 0;
+		priv->sys_config.accept_non_directed_frames = 0;
+		priv->sys_config.accept_all_mgmt_bcpr = 0;
+		priv->sys_config.accept_all_mgmt_frames = 0;
+
+		ipw_send_system_config(priv);
+	}
+
+	return 0;
+}
+
+static int ipw_prom_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	IPW_DEBUG_INFO("prom dev->xmit\n");
+	netif_stop_queue(dev);
+	return -EOPNOTSUPP;
+}
+
+static struct net_device_stats *ipw_prom_get_stats(struct net_device *dev)
+{
+	struct ipw_prom_priv *prom_priv = ieee80211_priv(dev);
+	return &prom_priv->ieee->stats;
+}
+
+static int ipw_prom_alloc(struct ipw_priv *priv)
+{
+	int rc = 0;
+
+	if (priv->prom_net_dev)
+		return -EPERM;
+
+	priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv));
+	if (priv->prom_net_dev == NULL)
+		return -ENOMEM;
+
+	priv->prom_priv = ieee80211_priv(priv->prom_net_dev);
+	priv->prom_priv->ieee = netdev_priv(priv->prom_net_dev);
+	priv->prom_priv->priv = priv;
+
+	strcpy(priv->prom_net_dev->name, "rtap%d");
+
+	priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
+	priv->prom_net_dev->open = ipw_prom_open;
+	priv->prom_net_dev->stop = ipw_prom_stop;
+	priv->prom_net_dev->get_stats = ipw_prom_get_stats;
+	priv->prom_net_dev->hard_start_xmit = ipw_prom_hard_start_xmit;
+
+	priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR;
+
+	rc = register_netdev(priv->prom_net_dev);
+	if (rc) {
+		free_ieee80211(priv->prom_net_dev);
+		priv->prom_net_dev = NULL;
+		return rc;
+	}
+
+	return 0;
+}
+
+static void ipw_prom_free(struct ipw_priv *priv)
+{
+	if (!priv->prom_net_dev)
+		return;
+
+	unregister_netdev(priv->prom_net_dev);
+	free_ieee80211(priv->prom_net_dev);
+
+	priv->prom_net_dev = NULL;
+}
+
+#endif
+
+
 static int ipw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	int err = 0;
@@ -10891,6 +11491,7 @@
 #ifdef CONFIG_IPW2200_DEBUG
 	ipw_debug_level = debug;
 #endif
+	spin_lock_init(&priv->irq_lock);
 	spin_lock_init(&priv->lock);
 	for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++)
 		INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
@@ -10959,11 +11560,12 @@
 	priv->ieee->set_security = shim__set_security;
 	priv->ieee->is_queue_full = ipw_net_is_queue_full;
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_QOS
+	priv->ieee->is_qos_active = ipw_is_qos_active;
 	priv->ieee->handle_probe_response = ipw_handle_beacon;
 	priv->ieee->handle_beacon = ipw_handle_probe_response;
 	priv->ieee->handle_assoc_response = ipw_handle_assoc_response;
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 	priv->ieee->perfect_rssi = -20;
 	priv->ieee->worst_rssi = -85;
@@ -10997,6 +11599,18 @@
 		goto out_remove_sysfs;
 	}
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	if (rtap_iface) {
+	        err = ipw_prom_alloc(priv);
+		if (err) {
+			IPW_ERROR("Failed to register promiscuous network "
+				  "device (error %d).\n", err);
+			unregister_netdev(priv->net_dev);
+			goto out_remove_sysfs;
+		}
+	}
+#endif
+
 	printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg "
 	       "channels, %d 802.11a channels)\n",
 	       priv->ieee->geo.name, priv->ieee->geo.bg_channels,
@@ -11071,10 +11685,12 @@
 		}
 	}
 
-	if (priv->error) {
-		ipw_free_error_log(priv->error);
-		priv->error = NULL;
-	}
+	kfree(priv->error);
+	priv->error = NULL;
+
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	ipw_prom_free(priv);
+#endif
 
 	free_irq(pdev->irq, priv);
 	iounmap(priv->hw_base);
@@ -11200,7 +11816,12 @@
 module_param(channel, int, 0444);
 MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])");
 
-#ifdef CONFIG_IPW_QOS
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+module_param(rtap_iface, int, 0444);
+MODULE_PARM_DESC(rtap_iface, "create the rtap interface (1 - create, default 0)");
+#endif
+
+#ifdef CONFIG_IPW2200_QOS
 module_param(qos_enable, int, 0444);
 MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis");
 
@@ -11215,7 +11836,7 @@
 
 module_param(burst_duration_OFDM, int, 0444);
 MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value");
-#endif				/* CONFIG_IPW_QOS */
+#endif				/* CONFIG_IPW2200_QOS */
 
 #ifdef CONFIG_IPW2200_MONITOR
 module_param(mode, int, 0444);
@@ -11238,5 +11859,8 @@
 module_param(roaming, int, 0444);
 MODULE_PARM_DESC(roaming, "enable roaming support (default on)");
 
+module_param(antenna, int, 0444);
+MODULE_PARM_DESC(antenna, "select antenna 1=Main, 3=Aux, default 0 [both], 2=slow_diversity (choose the one with lower background noise)");
+
 module_exit(ipw_exit);
 module_init(ipw_init);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index 4b98049..ea12ad6 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -789,7 +789,7 @@
 	u8 bt_coexist_collision_thr;
 	u8 silence_threshold;
 	u8 accept_all_mgmt_bcpr;
-	u8 accept_all_mgtm_frames;
+	u8 accept_all_mgmt_frames;
 	u8 pass_noise_stats_to_host;
 	u8 reserved3;
 } __attribute__ ((packed));
@@ -1122,17 +1122,70 @@
 	u8 payload[0];
 } __attribute__ ((packed));
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+
+enum ipw_prom_filter {
+	IPW_PROM_CTL_HEADER_ONLY = (1 << 0),
+	IPW_PROM_MGMT_HEADER_ONLY = (1 << 1),
+	IPW_PROM_DATA_HEADER_ONLY = (1 << 2),
+	IPW_PROM_ALL_HEADER_ONLY = 0xf, /* bits 0..3 */
+	IPW_PROM_NO_TX = (1 << 4),
+	IPW_PROM_NO_RX = (1 << 5),
+	IPW_PROM_NO_CTL = (1 << 6),
+	IPW_PROM_NO_MGMT = (1 << 7),
+	IPW_PROM_NO_DATA = (1 << 8),
+};
+
+struct ipw_priv;
+struct ipw_prom_priv {
+	struct ipw_priv *priv;
+	struct ieee80211_device *ieee;
+	enum ipw_prom_filter filter;
+	int tx_packets;
+	int rx_packets;
+};
+#endif
+
+#if defined(CONFIG_IPW2200_RADIOTAP) || defined(CONFIG_IPW2200_PROMISCUOUS)
+/* Magic struct that slots into the radiotap header -- no reason
+ * to build this manually element by element, we can write it much
+ * more efficiently than we can parse it. ORDER MATTERS HERE
+ *
+ * When sent to us via the simulated Rx interface in sysfs, the entire
+ * structure is provided regardless of any bits unset.
+ */
+struct ipw_rt_hdr {
+	struct ieee80211_radiotap_header rt_hdr;
+	u64 rt_tsf;      /* TSF */
+	u8 rt_flags;	/* radiotap packet flags */
+	u8 rt_rate;	/* rate in 500kb/s */
+	u16 rt_channel;	/* channel in mhz */
+	u16 rt_chbitmask;	/* channel bitfield */
+	s8 rt_dbmsignal;	/* signal in dbM, kluged to signed */
+	s8 rt_dbmnoise;
+	u8 rt_antenna;	/* antenna number */
+	u8 payload[0];  /* payload... */
+} __attribute__ ((packed));
+#endif
+
 struct ipw_priv {
 	/* ieee device used by generic ieee processing code */
 	struct ieee80211_device *ieee;
 
 	spinlock_t lock;
+	spinlock_t irq_lock;
 	struct mutex mutex;
 
 	/* basic pci-network driver stuff */
 	struct pci_dev *pci_dev;
 	struct net_device *net_dev;
 
+#ifdef CONFIG_IPW2200_PROMISCUOUS
+	/* Promiscuous mode */
+	struct ipw_prom_priv *prom_priv;
+	struct net_device *prom_net_dev;
+#endif
+
 	/* pci hardware address support */
 	void __iomem *hw_base;
 	unsigned long hw_len;
@@ -1153,11 +1206,9 @@
 	u32 config;
 	u32 capability;
 
-	u8 last_rx_rssi;
-	u8 last_noise;
 	struct average average_missed_beacons;
-	struct average average_rssi;
-	struct average average_noise;
+	s16 exp_avg_rssi;
+	s16 exp_avg_noise;
 	u32 port_type;
 	int rx_bufs_min;	  /**< minimum number of bufs in Rx queue */
 	int rx_pend_max;	  /**< maximum pending buffers for one IRQ */
@@ -1308,6 +1359,29 @@
 
 /* debug macros */
 
+/* Debug and printf string expansion helpers for printing bitfields */
+#define BIT_FMT8 "%c%c%c%c-%c%c%c%c"
+#define BIT_FMT16 BIT_FMT8 ":" BIT_FMT8
+#define BIT_FMT32 BIT_FMT16 " " BIT_FMT16
+
+#define BITC(x,y) (((x>>y)&1)?'1':'0')
+#define BIT_ARG8(x) \
+BITC(x,7),BITC(x,6),BITC(x,5),BITC(x,4),\
+BITC(x,3),BITC(x,2),BITC(x,1),BITC(x,0)
+
+#define BIT_ARG16(x) \
+BITC(x,15),BITC(x,14),BITC(x,13),BITC(x,12),\
+BITC(x,11),BITC(x,10),BITC(x,9),BITC(x,8),\
+BIT_ARG8(x)
+
+#define BIT_ARG32(x) \
+BITC(x,31),BITC(x,30),BITC(x,29),BITC(x,28),\
+BITC(x,27),BITC(x,26),BITC(x,25),BITC(x,24),\
+BITC(x,23),BITC(x,22),BITC(x,21),BITC(x,20),\
+BITC(x,19),BITC(x,18),BITC(x,17),BITC(x,16),\
+BIT_ARG16(x)
+
+
 #ifdef CONFIG_IPW2200_DEBUG
 #define IPW_DEBUG(level, fmt, args...) \
 do { if (ipw_debug_level & (level)) \
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index c2d0b09..8a31b59 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -201,41 +201,12 @@
 /* Data types                                                       */
 /********************************************************************/
 
-/* Used in Event handling.
- * We avoid nested structures as they break on ARM -- Moustafa */
-struct hermes_tx_descriptor_802_11 {
-	/* hermes_tx_descriptor */
-	__le16 status;
-	__le16 reserved1;
-	__le16 reserved2;
-	__le32 sw_support;
-	u8 retry_count;
-	u8 tx_rate;
-	__le16 tx_control;
-
-	/* ieee80211_hdr */
+/* Beginning of the Tx descriptor, used in TxExc handling */
+struct hermes_txexc_data {
+	struct hermes_tx_descriptor desc;
 	__le16 frame_ctl;
 	__le16 duration_id;
 	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-	u8 addr3[ETH_ALEN];
-	__le16 seq_ctl;
-	u8 addr4[ETH_ALEN];
-
-	__le16 data_len;
-
-	/* ethhdr */
-	u8 h_dest[ETH_ALEN];	/* destination eth addr */
-	u8 h_source[ETH_ALEN];	/* source ether addr    */
-	__be16 h_proto;		/* packet type ID field */
-
-	/* p8022_hdr */
-	u8 dsap;
-	u8 ssap;
-	u8 ctrl;
-	u8 oui[3];
-
-	__be16 ethertype;
 } __attribute__ ((packed));
 
 /* Rx frame header except compatibility 802.3 header */
@@ -450,53 +421,39 @@
 	hermes_t *hw = &priv->hw;
 	int err = 0;
 	u16 txfid = priv->txfid;
-	char *p;
 	struct ethhdr *eh;
-	int len, data_len, data_off;
+	int data_off;
 	struct hermes_tx_descriptor desc;
 	unsigned long flags;
 
-	TRACE_ENTER(dev->name);
-
 	if (! netif_running(dev)) {
 		printk(KERN_ERR "%s: Tx on stopped device!\n",
 		       dev->name);
-		TRACE_EXIT(dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	
 	if (netif_queue_stopped(dev)) {
 		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", 
 		       dev->name);
-		TRACE_EXIT(dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 	
 	if (orinoco_lock(priv, &flags) != 0) {
 		printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
 		       dev->name);
-		TRACE_EXIT(dev->name);
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
 	if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
 		/* Oops, the firmware hasn't established a connection,
                    silently drop the packet (this seems to be the
                    safest approach). */
-		stats->tx_errors++;
-		orinoco_unlock(priv, &flags);
-		dev_kfree_skb(skb);
-		TRACE_EXIT(dev->name);
-		return 0;
+		goto drop;
 	}
 
-	/* Length of the packet body */
-	/* FIXME: what if the skb is smaller than this? */
-	len = max_t(int, ALIGN(skb->len, 2), ETH_ZLEN);
-	skb = skb_padto(skb, len);
-	if (skb == NULL)
-		goto fail;
-	len -= ETH_HLEN;
+	/* Check packet length */
+	if (skb->len < ETH_HLEN)
+		goto drop;
 
 	eh = (struct ethhdr *)skb->data;
 
@@ -507,8 +464,7 @@
 		if (net_ratelimit())
 			printk(KERN_ERR "%s: Error %d writing Tx descriptor "
 			       "to BAP\n", dev->name, err);
-		stats->tx_errors++;
-		goto fail;
+		goto busy;
 	}
 
 	/* Clear the 802.11 header and data length fields - some
@@ -519,50 +475,38 @@
 
 	/* Encapsulate Ethernet-II frames */
 	if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
-		struct header_struct hdr;
-		data_len = len;
-		data_off = HERMES_802_3_OFFSET + sizeof(hdr);
-		p = skb->data + ETH_HLEN;
+		struct header_struct {
+			struct ethhdr eth;	/* 802.3 header */
+			u8 encap[6];		/* 802.2 header */
+		} __attribute__ ((packed)) hdr;
 
-		/* 802.3 header */
-		memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
-		memcpy(hdr.src, eh->h_source, ETH_ALEN);
-		hdr.len = htons(data_len + ENCAPS_OVERHEAD);
-		
-		/* 802.2 header */
-		memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
-			
-		hdr.ethertype = eh->h_proto;
-		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
-					 txfid, HERMES_802_3_OFFSET);
+		/* Strip destination and source from the data */
+		skb_pull(skb, 2 * ETH_ALEN);
+		data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);
+
+		/* And move them to a separate header */
+		memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
+		hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
+		memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
+
+		err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
+					txfid, HERMES_802_3_OFFSET);
 		if (err) {
 			if (net_ratelimit())
 				printk(KERN_ERR "%s: Error %d writing packet "
 				       "header to BAP\n", dev->name, err);
-			stats->tx_errors++;
-			goto fail;
+			goto busy;
 		}
-		/* Actual xfer length - allow for padding */
-		len = ALIGN(data_len, 2);
-		if (len < ETH_ZLEN - ETH_HLEN)
-			len = ETH_ZLEN - ETH_HLEN;
 	} else { /* IEEE 802.3 frame */
-		data_len = len + ETH_HLEN;
 		data_off = HERMES_802_3_OFFSET;
-		p = skb->data;
-		/* Actual xfer length - round up for odd length packets */
-		len = ALIGN(data_len, 2);
-		if (len < ETH_ZLEN)
-			len = ETH_ZLEN;
 	}
 
-	err = hermes_bap_pwrite_pad(hw, USER_BAP, p, data_len, len,
+	err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
 				txfid, data_off);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
 		       dev->name, err);
-		stats->tx_errors++;
-		goto fail;
+		goto busy;
 	}
 
 	/* Finally, we actually initiate the send */
@@ -575,25 +519,27 @@
 		if (net_ratelimit())
 			printk(KERN_ERR "%s: Error %d transmitting packet\n",
 				dev->name, err);
-		stats->tx_errors++;
-		goto fail;
+		goto busy;
 	}
 
 	dev->trans_start = jiffies;
-	stats->tx_bytes += data_off + data_len;
+	stats->tx_bytes += data_off + skb->len;
+	goto ok;
 
+ drop:
+	stats->tx_errors++;
+	stats->tx_dropped++;
+
+ ok:
 	orinoco_unlock(priv, &flags);
-
 	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
 
-	TRACE_EXIT(dev->name);
-
-	return 0;
- fail:
-	TRACE_EXIT(dev->name);
-
+ busy:
+	if (err == -EIO)
+		schedule_work(&priv->reset_work);
 	orinoco_unlock(priv, &flags);
-	return err;
+	return NETDEV_TX_BUSY;
 }
 
 static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
@@ -629,7 +575,7 @@
 	struct net_device_stats *stats = &priv->stats;
 	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
 	u16 status;
-	struct hermes_tx_descriptor_802_11 hdr;
+	struct hermes_txexc_data hdr;
 	int err = 0;
 
 	if (fid == DUMMY_FID)
@@ -637,8 +583,7 @@
 
 	/* Read part of the frame header - we need status and addr1 */
 	err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
-			       offsetof(struct hermes_tx_descriptor_802_11,
-					addr2),
+			       sizeof(struct hermes_txexc_data),
 			       fid, 0);
 
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
@@ -658,7 +603,7 @@
 	 * exceeded, because that's the only status that really mean
 	 * that this particular node went away.
 	 * Other errors means that *we* screwed up. - Jean II */
-	status = le16_to_cpu(hdr.status);
+	status = le16_to_cpu(hdr.desc.status);
 	if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
 		union iwreq_data	wrqu;
 
@@ -1398,16 +1343,12 @@
 	return 0;
 }
 
-int orinoco_reinit_firmware(struct net_device *dev)
+static int orinoco_allocate_fid(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct hermes *hw = &priv->hw;
 	int err;
 
-	err = hermes_init(hw);
-	if (err)
-		return err;
-
 	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
 	if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
 		/* Try workaround for old Symbol firmware bug */
@@ -1426,6 +1367,19 @@
 	return err;
 }
 
+int orinoco_reinit_firmware(struct net_device *dev)
+{
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct hermes *hw = &priv->hw;
+	int err;
+
+	err = hermes_init(hw);
+	if (!err)
+		err = orinoco_allocate_fid(dev);
+
+	return err;
+}
+
 static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
 {
 	hermes_t *hw = &priv->hw;
@@ -1833,7 +1787,9 @@
 	/* Set promiscuity / multicast*/
 	priv->promiscuous = 0;
 	priv->mc_count = 0;
-	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
+
+	/* FIXME: what about netif_tx_lock */
+	__orinoco_set_multicast_list(dev);
 
 	return 0;
 }
@@ -2272,14 +2228,12 @@
 	u16 reclen;
 	int len;
 
-	TRACE_ENTER(dev->name);
-
 	/* No need to lock, the hw_unavailable flag is already set in
 	 * alloc_orinocodev() */
 	priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
 
 	/* Initialize the firmware */
-	err = orinoco_reinit_firmware(dev);
+	err = hermes_init(hw);
 	if (err != 0) {
 		printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
 		       dev->name, err);
@@ -2337,6 +2291,13 @@
 
 	printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);
 
+	err = orinoco_allocate_fid(dev);
+	if (err) {
+		printk(KERN_ERR "%s: failed to allocate NIC buffer!\n",
+		       dev->name);
+		goto out;
+	}
+
 	/* Get allowed channels */
 	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
 				  &priv->channel_mask);
@@ -2427,7 +2388,6 @@
 	printk(KERN_DEBUG "%s: ready\n", dev->name);
 
  out:
-	TRACE_EXIT(dev->name);
 	return err;
 }
 
@@ -2795,8 +2755,6 @@
 	int numrates;
 	int i, k;
 
-	TRACE_ENTER(dev->name);
-
 	rrq->length = sizeof(struct iw_range);
 	memset(range, 0, sizeof(struct iw_range));
 
@@ -2886,8 +2844,6 @@
 	IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
 	IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
 
-	TRACE_EXIT(dev->name);
-
 	return 0;
 }
 
@@ -3069,8 +3025,6 @@
 	int err = 0;
 	unsigned long flags;
 
-	TRACE_ENTER(dev->name);
-
 	if (netif_running(dev)) {
 		err = orinoco_hw_get_essid(priv, &active, essidbuf);
 		if (err)
@@ -3085,8 +3039,6 @@
 	erq->flags = 1;
 	erq->length = strlen(essidbuf) + 1;
 
-	TRACE_EXIT(dev->name);
-	
 	return 0;
 }
 
@@ -4347,69 +4299,6 @@
 };
 
 /********************************************************************/
-/* Debugging                                                        */
-/********************************************************************/
-
-#if 0
-static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
-{
-	printk(KERN_DEBUG "RX descriptor:\n");
-	printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
-	printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);
-	printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);
-	printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);
-	printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);
-	printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);
-	printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);
-
-	printk(KERN_DEBUG "IEEE 802.11 header:\n");
-	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
-	       frame->p80211.frame_ctl);
-	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
-	       frame->p80211.duration_id);
-	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr1[0], frame->p80211.addr1[1],
-	       frame->p80211.addr1[2], frame->p80211.addr1[3],
-	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
-	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr2[0], frame->p80211.addr2[1],
-	       frame->p80211.addr2[2], frame->p80211.addr2[3],
-	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
-	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr3[0], frame->p80211.addr3[1],
-	       frame->p80211.addr3[2], frame->p80211.addr3[3],
-	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
-	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
-	       frame->p80211.seq_ctl);
-	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr4[0], frame->p80211.addr4[1],
-	       frame->p80211.addr4[2], frame->p80211.addr4[3],
-	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
-	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
-	       frame->p80211.data_len);
-
-	printk(KERN_DEBUG "IEEE 802.3 header:\n");
-	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
-	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
-	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
-	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_source[0], frame->p8023.h_source[1],
-	       frame->p8023.h_source[2], frame->p8023.h_source[3],
-	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
-	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
-
-	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
-	printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
-	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
-	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
-	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
-	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
-	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
-}
-#endif /* 0 */
-
-/********************************************************************/
 /* Module initialization                                            */
 /********************************************************************/
 
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index f5d856d..16db3e1 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -7,7 +7,7 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
-#define DRIVER_VERSION "0.15rc3"
+#define DRIVER_VERSION "0.15"
 
 #include <linux/netdevice.h>
 #include <linux/wireless.h>
@@ -30,20 +30,6 @@
 	char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
-struct header_struct {
-	/* 802.3 */
-	u8 dest[ETH_ALEN];
-	u8 src[ETH_ALEN];
-	__be16 len;
-	/* 802.2 */
-	u8 dsap;
-	u8 ssap;
-	u8 ctrl;
-	/* SNAP */
-	u8 oui[3];
-	unsigned short ethertype;
-} __attribute__ ((packed));
-
 typedef enum {
 	FIRMWARE_TYPE_AGERE,
 	FIRMWARE_TYPE_INTERSIL,
@@ -132,9 +118,6 @@
 #define DEBUG(n, args...) do { } while (0)
 #endif	/* ORINOCO_DEBUG */
 
-#define TRACE_ENTER(devname) DEBUG(2, "%s: -> %s()\n", devname, __FUNCTION__);
-#define TRACE_EXIT(devname)  DEBUG(2, "%s: <- %s()\n", devname, __FUNCTION__);
-
 /********************************************************************/
 /* Exported prototypes                                              */
 /********************************************************************/
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index 434f7d7..b2aec4d 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -147,14 +147,11 @@
 {
 	struct net_device *dev = link->priv;
 
+	if (link->dev_node)
+		unregister_netdev(dev);
+
 	orinoco_cs_release(link);
 
-	DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
-	if (link->dev_node) {
-		DEBUG(0, PFX "About to unregister net device %p\n",
-		      dev);
-		unregister_netdev(dev);
-	}
 	free_orinocodev(dev);
 }				/* orinoco_cs_detach */
 
@@ -178,13 +175,10 @@
 	int last_fn, last_ret;
 	u_char buf[64];
 	config_info_t conf;
-	cisinfo_t info;
 	tuple_t tuple;
 	cisparse_t parse;
 	void __iomem *mem;
 
-	CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
-
 	/*
 	 * This reads the card's CONFIG tuple to find its
 	 * configuration registers.
@@ -234,12 +228,6 @@
 			goto next_entry;
 		link->conf.ConfigIndex = cfg->index;
 
-		/* Does this card need audio output? */
-		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-			link->conf.Attributes |= CONF_ENABLE_SPKR;
-			link->conf.Status = CCSR_AUDIO_ENA;
-		}
-
 		/* Use power settings for Vcc and Vpp if present */
 		/* Note that the CIS values need to be rescaled */
 		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
@@ -355,19 +343,10 @@
                                     net_device has been registered */
 
 	/* Finally, report what we've done */
-	printk(KERN_DEBUG "%s: index 0x%02x: ",
-	       dev->name, link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp / 10,
-		       link->conf.Vpp % 10);
-	printk(", irq %d", link->irq.AssignedIRQ);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
-	printk("\n");
+	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
+	       "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+	       link->irq.AssignedIRQ, link->io.BasePort1,
+	       link->io.BasePort1 + link->io.NumPorts1 - 1);
 
 	return 0;
 
@@ -436,7 +415,6 @@
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct orinoco_pccard *card = priv->card;
 	int err = 0;
-	unsigned long flags;
 
 	if (! test_bit(0, &card->hard_reset_in_progress)) {
 		err = orinoco_reinit_firmware(dev);
@@ -446,7 +424,7 @@
 			return -EIO;
 		}
 
-		spin_lock_irqsave(&priv->lock, flags);
+		spin_lock(&priv->lock);
 
 		netif_device_attach(dev);
 		priv->hw_unavailable--;
@@ -458,10 +436,10 @@
 				       dev->name, err);
 		}
 
-		spin_unlock_irqrestore(&priv->lock, flags);
+		spin_unlock(&priv->lock);
 	}
 
-	return 0;
+	return err;
 }
 
 
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index d1a670b..74b9d5b 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -1,9 +1,8 @@
 /* orinoco_nortel.c
- * 
+ *
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in
  * Nortel emobility, Symbol LA-4113 and Symbol LA-4123.
- * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter. 
  *
  * Copyright (C) 2002 Tobias Hoffmann
  *           (C) 2003 Christoph Jungegger <disdos@traum404.de>
@@ -50,67 +49,62 @@
 #include <pcmcia/cisreg.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
 #define COR_OFFSET    (0xe0)	/* COR attribute offset of Prism2 PC card */
 #define COR_VALUE     (COR_LEVEL_REQ | COR_FUNC_ENA)	/* Enable PC card with interrupt in level trigger */
 
 
-/* Nortel specific data */
-struct nortel_pci_card {
-	unsigned long iobase1;
-	unsigned long iobase2;
-};
-
 /*
- * Do a soft reset of the PCI card using the Configuration Option Register
+ * Do a soft reset of the card using the Configuration Option Register
  * We need this to get going...
  * This is the part of the code that is strongly inspired from wlan-ng
  *
  * Note bis : Don't try to access HERMES_CMD during the reset phase.
  * It just won't work !
  */
-static int nortel_pci_cor_reset(struct orinoco_private *priv)
+static int orinoco_nortel_cor_reset(struct orinoco_private *priv)
 {
-	struct nortel_pci_card *card = priv->card;
+	struct orinoco_pci_card *card = priv->card;
 
-	/* Assert the reset until the card notice */
-	outw_p(8, card->iobase1 + 2);
-	inw(card->iobase2 + COR_OFFSET);
-	outw_p(0x80, card->iobase2 + COR_OFFSET);
+	/* Assert the reset until the card notices */
+	iowrite16(8, card->bridge_io + 2);
+	ioread16(card->attr_io + COR_OFFSET);
+	iowrite16(0x80, card->attr_io + COR_OFFSET);
 	mdelay(1);
 
 	/* Give time for the card to recover from this hard effort */
-	outw_p(0, card->iobase2 + COR_OFFSET);
-	outw_p(0, card->iobase2 + COR_OFFSET);
+	iowrite16(0, card->attr_io + COR_OFFSET);
+	iowrite16(0, card->attr_io + COR_OFFSET);
 	mdelay(1);
 
-	/* set COR as usual */
-	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
-	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+	/* Set COR as usual */
+	iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
+	iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
 	mdelay(1);
 
-	outw_p(0x228, card->iobase1 + 2);
+	iowrite16(0x228, card->bridge_io + 2);
 
 	return 0;
 }
 
-static int nortel_pci_hw_init(struct nortel_pci_card *card)
+static int orinoco_nortel_hw_init(struct orinoco_pci_card *card)
 {
 	int i;
 	u32 reg;
 
-	/* setup bridge */
-	if (inw(card->iobase1) & 1) {
+	/* Setup bridge */
+	if (ioread16(card->bridge_io) & 1) {
 		printk(KERN_ERR PFX "brg1 answer1 wrong\n");
 		return -EBUSY;
 	}
-	outw_p(0x118, card->iobase1 + 2);
-	outw_p(0x108, card->iobase1 + 2);
+	iowrite16(0x118, card->bridge_io + 2);
+	iowrite16(0x108, card->bridge_io + 2);
 	mdelay(30);
-	outw_p(0x8, card->iobase1 + 2);
+	iowrite16(0x8, card->bridge_io + 2);
 	for (i = 0; i < 30; i++) {
 		mdelay(30);
-		if (inw(card->iobase1) & 0x10) {
+		if (ioread16(card->bridge_io) & 0x10) {
 			break;
 		}
 	}
@@ -118,42 +112,42 @@
 		printk(KERN_ERR PFX "brg1 timed out\n");
 		return -EBUSY;
 	}
-	if (inw(card->iobase2 + 0xe0) & 1) {
+	if (ioread16(card->attr_io + COR_OFFSET) & 1) {
 		printk(KERN_ERR PFX "brg2 answer1 wrong\n");
 		return -EBUSY;
 	}
-	if (inw(card->iobase2 + 0xe2) & 1) {
+	if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) {
 		printk(KERN_ERR PFX "brg2 answer2 wrong\n");
 		return -EBUSY;
 	}
-	if (inw(card->iobase2 + 0xe4) & 1) {
+	if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) {
 		printk(KERN_ERR PFX "brg2 answer3 wrong\n");
 		return -EBUSY;
 	}
 
-	/* set the PCMCIA COR-Register */
-	outw_p(COR_VALUE, card->iobase2 + COR_OFFSET);
+	/* Set the PCMCIA COR register */
+	iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
 	mdelay(1);
-	reg = inw(card->iobase2 + COR_OFFSET);
+	reg = ioread16(card->attr_io + COR_OFFSET);
 	if (reg != COR_VALUE) {
 		printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
 		       reg);
 		return -EBUSY;
 	}
 
-	/* set leds */
-	outw_p(1, card->iobase1 + 10);
+	/* Set LEDs */
+	iowrite16(1, card->bridge_io + 10);
 	return 0;
 }
 
-static int nortel_pci_init_one(struct pci_dev *pdev,
-			       const struct pci_device_id *ent)
+static int orinoco_nortel_init_one(struct pci_dev *pdev,
+				   const struct pci_device_id *ent)
 {
 	int err;
 	struct orinoco_private *priv;
-	struct nortel_pci_card *card;
+	struct orinoco_pci_card *card;
 	struct net_device *dev;
-	void __iomem *iomem;
+	void __iomem *hermes_io, *bridge_io, *attr_io;
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -162,19 +156,34 @@
 	}
 
 	err = pci_request_regions(pdev, DRIVER_NAME);
-	if (err != 0) {
+	if (err) {
 		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
 		goto fail_resources;
 	}
 
-	iomem = pci_iomap(pdev, 2, 0);
-	if (!iomem) {
-		err = -ENOMEM;
-		goto fail_map_io;
+	bridge_io = pci_iomap(pdev, 0, 0);
+	if (!bridge_io) {
+		printk(KERN_ERR PFX "Cannot map bridge registers\n");
+		err = -EIO;
+		goto fail_map_bridge;
+	}
+
+	attr_io = pci_iomap(pdev, 1, 0);
+	if (!attr_io) {
+		printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
+		err = -EIO;
+		goto fail_map_attr;
+	}
+
+	hermes_io = pci_iomap(pdev, 2, 0);
+	if (!hermes_io) {
+		printk(KERN_ERR PFX "Cannot map chipset registers\n");
+		err = -EIO;
+		goto fail_map_hermes;
 	}
 
 	/* Allocate network device */
-	dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset);
+	dev = alloc_orinocodev(sizeof(*card), orinoco_nortel_cor_reset);
 	if (!dev) {
 		printk(KERN_ERR PFX "Cannot allocate network device\n");
 		err = -ENOMEM;
@@ -183,16 +192,12 @@
 
 	priv = netdev_priv(dev);
 	card = priv->card;
-	card->iobase1 = pci_resource_start(pdev, 0);
-	card->iobase2 = pci_resource_start(pdev, 1);
-	dev->base_addr = pci_resource_start(pdev, 2);
+	card->bridge_io = bridge_io;
+	card->attr_io = attr_io;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING);
-
-	printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, "
-	       "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr);
+	hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
 
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
@@ -201,21 +206,19 @@
 		err = -EBUSY;
 		goto fail_irq;
 	}
-	dev->irq = pdev->irq;
 
-	err = nortel_pci_hw_init(card);
+	err = orinoco_nortel_hw_init(card);
 	if (err) {
 		printk(KERN_ERR PFX "Hardware initialization failed\n");
 		goto fail;
 	}
 
-	err = nortel_pci_cor_reset(priv);
+	err = orinoco_nortel_cor_reset(priv);
 	if (err) {
 		printk(KERN_ERR PFX "Initial reset failed\n");
 		goto fail;
 	}
 
-
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR PFX "Cannot register network device\n");
@@ -223,6 +226,8 @@
 	}
 
 	pci_set_drvdata(pdev, dev);
+	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+	       pci_name(pdev));
 
 	return 0;
 
@@ -234,9 +239,15 @@
 	free_orinocodev(dev);
 
  fail_alloc:
-	pci_iounmap(pdev, iomem);
+	pci_iounmap(pdev, hermes_io);
 
- fail_map_io:
+ fail_map_hermes:
+	pci_iounmap(pdev, attr_io);
+
+ fail_map_attr:
+	pci_iounmap(pdev, bridge_io);
+
+ fail_map_bridge:
 	pci_release_regions(pdev);
 
  fail_resources:
@@ -245,26 +256,27 @@
 	return err;
 }
 
-static void __devexit nortel_pci_remove_one(struct pci_dev *pdev)
+static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct orinoco_private *priv = netdev_priv(dev);
-	struct nortel_pci_card *card = priv->card;
+	struct orinoco_pci_card *card = priv->card;
 
-	/* clear leds */
-	outw_p(0, card->iobase1 + 10);
+	/* Clear LEDs */
+	iowrite16(0, card->bridge_io + 10);
 
 	unregister_netdev(dev);
-	free_irq(dev->irq, dev);
+	free_irq(pdev->irq, dev);
 	pci_set_drvdata(pdev, NULL);
 	free_orinocodev(dev);
 	pci_iounmap(pdev, priv->hw.iobase);
+	pci_iounmap(pdev, card->attr_io);
+	pci_iounmap(pdev, card->bridge_io);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
-
-static struct pci_device_id nortel_pci_id_table[] = {
+static struct pci_device_id orinoco_nortel_id_table[] = {
 	/* Nortel emobility PCI */
 	{0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
 	/* Symbol LA-4123 PCI */
@@ -272,13 +284,15 @@
 	{0,},
 };
 
-MODULE_DEVICE_TABLE(pci, nortel_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table);
 
-static struct pci_driver nortel_pci_driver = {
-	.name = DRIVER_NAME,
-	.id_table = nortel_pci_id_table,
-	.probe = nortel_pci_init_one,
-	.remove = __devexit_p(nortel_pci_remove_one),
+static struct pci_driver orinoco_nortel_driver = {
+	.name		= DRIVER_NAME,
+	.id_table	= orinoco_nortel_id_table,
+	.probe		= orinoco_nortel_init_one,
+	.remove		= __devexit_p(orinoco_nortel_remove_one),
+	.suspend	= orinoco_pci_suspend,
+	.resume		= orinoco_pci_resume,
 };
 
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -288,20 +302,19 @@
     ("Driver for wireless LAN cards using the Nortel PCI bridge");
 MODULE_LICENSE("Dual MPL/GPL");
 
-static int __init nortel_pci_init(void)
+static int __init orinoco_nortel_init(void)
 {
 	printk(KERN_DEBUG "%s\n", version);
-	return pci_module_init(&nortel_pci_driver);
+	return pci_module_init(&orinoco_nortel_driver);
 }
 
-static void __exit nortel_pci_exit(void)
+static void __exit orinoco_nortel_exit(void)
 {
-	pci_unregister_driver(&nortel_pci_driver);
-	ssleep(1);
+	pci_unregister_driver(&orinoco_nortel_driver);
 }
 
-module_init(nortel_pci_init);
-module_exit(nortel_pci_exit);
+module_init(orinoco_nortel_init);
+module_exit(orinoco_nortel_exit);
 
 /*
  * Local variables:
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 5362c21..1c105f4 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -1,11 +1,11 @@
 /* orinoco_pci.c
  * 
- * Driver for Prism II devices that have a direct PCI interface
- * (i.e., not in a Pcmcia or PLX bridge)
+ * Driver for Prism 2.5/3 devices that have a direct PCI interface
+ * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge).
+ * The card contains only one PCI region, which contains all the usual
+ * hermes registers, as well as the COR register.
  *
- * Specifically here we're talking about the Linksys WMP11
- *
- * Current maintainers (as of 29 September 2003) are:
+ * Current maintainers are:
  * 	Pavel Roskin <proski AT gnu.org>
  * and	David Gibson <hermes AT gibson.dropbear.id.au>
  *
@@ -41,54 +41,6 @@
  * under either the MPL or the GPL.
  */
 
-/*
- * Theory of operation...
- * -------------------
- * Maybe you had a look in orinoco_plx. Well, this is totally different...
- *
- * The card contains only one PCI region, which contains all the usual
- * hermes registers.
- *
- * The driver will memory map this region in normal memory. Because
- * the hermes registers are mapped in normal memory and not in ISA I/O
- * post space, we can't use the usual inw/outw macros and we need to
- * use readw/writew.
- * This slight difference force us to compile our own version of
- * hermes.c with the register access macro changed. That's a bit
- * hackish but works fine.
- *
- * Note that the PCI region is pretty big (4K). That's much more than
- * the usual set of hermes register (0x0 -> 0x3E). I've got a strong
- * suspicion that the whole memory space of the adapter is in fact in
- * this region. Accessing directly the adapter memory instead of going
- * through the usual register would speed up significantely the
- * operations...
- *
- * Finally, the card looks like this :
------------------------
-  Bus  0, device  14, function  0:
-    Network controller: PCI device 1260:3873 (Harris Semiconductor) (rev 1).
-      IRQ 11.
-      Master Capable.  Latency=248.  
-      Prefetchable 32 bit memory at 0xffbcc000 [0xffbccfff].
------------------------
-00:0e.0 Network controller: Harris Semiconductor: Unknown device 3873 (rev 01)
-        Subsystem: Unknown device 1737:3874
-        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B-
-        Status: Cap+ 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR-
-        Latency: 248 set, cache line size 08
-        Interrupt: pin A routed to IRQ 11
-        Region 0: Memory at ffbcc000 (32-bit, prefetchable) [size=4K]
-        Capabilities: [dc] Power Management version 2
-                Flags: PMEClk- AuxPwr- DSI- D1+ D2+ PME+
-                Status: D0 PME-Enable- DSel=0 DScale=0 PME-
------------------------
- *
- * That's all..
- *
- * Jean II
- */
-
 #define DRIVER_NAME "orinoco_pci"
 #define PFX DRIVER_NAME ": "
 
@@ -100,12 +52,14 @@
 #include <linux/pci.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
-/* All the magic there is from wlan-ng */
-/* Magic offset of the reset register of the PCI card */
+/* Offset of the COR register of the PCI card */
 #define HERMES_PCI_COR		(0x26)
-/* Magic bitmask to reset the card */
+
+/* Bitmask to reset the card */
 #define HERMES_PCI_COR_MASK	(0x0080)
+
 /* Magic timeouts for doing the reset.
  * Those times are straight from wlan-ng, and it is claimed that they
  * are necessary. Alan will kill me. Take your time and grab a coffee. */
@@ -113,13 +67,8 @@
 #define HERMES_PCI_COR_OFFT	(500)		/* ms */
 #define HERMES_PCI_COR_BUSYT	(500)		/* ms */
 
-/* Orinoco PCI specific data */
-struct orinoco_pci_card {
-	void __iomem *pci_ioaddr;
-};
-
 /*
- * Do a soft reset of the PCI card using the Configuration Option Register
+ * Do a soft reset of the card using the Configuration Option Register
  * We need this to get going...
  * This is the part of the code that is strongly inspired from wlan-ng
  *
@@ -131,14 +80,13 @@
  * Note bis : Don't try to access HERMES_CMD during the reset phase.
  * It just won't work !
  */
-static int
-orinoco_pci_cor_reset(struct orinoco_private *priv)
+static int orinoco_pci_cor_reset(struct orinoco_private *priv)
 {
 	hermes_t *hw = &priv->hw;
-	unsigned long	timeout;
-	u16	reg;
+	unsigned long timeout;
+	u16 reg;
 
-	/* Assert the reset until the card notice */
+	/* Assert the reset until the card notices */
 	hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
 	mdelay(HERMES_PCI_COR_ONT);
 
@@ -163,19 +111,14 @@
 	return 0;
 }
 
-/*
- * Initialise a card. Mostly similar to PLX code.
- */
 static int orinoco_pci_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
-	int err = 0;
-	unsigned long pci_iorange;
-	u16 __iomem *pci_ioaddr = NULL;
-	unsigned long pci_iolen;
-	struct orinoco_private *priv = NULL;
+	int err;
+	struct orinoco_private *priv;
 	struct orinoco_pci_card *card;
-	struct net_device *dev = NULL;
+	struct net_device *dev;
+	void __iomem *hermes_io;
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -184,39 +127,32 @@
 	}
 
 	err = pci_request_regions(pdev, DRIVER_NAME);
-	if (err != 0) {
+	if (err) {
 		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
 		goto fail_resources;
 	}
 
-	/* Resource 0 is mapped to the hermes registers */
-	pci_iorange = pci_resource_start(pdev, 0);
-	pci_iolen = pci_resource_len(pdev, 0);
-	pci_ioaddr = ioremap(pci_iorange, pci_iolen);
-	if (!pci_iorange) {
-		printk(KERN_ERR PFX "Cannot remap hardware registers\n");
-		goto fail_map;
+	hermes_io = pci_iomap(pdev, 0, 0);
+	if (!hermes_io) {
+		printk(KERN_ERR PFX "Cannot remap chipset registers\n");
+		err = -EIO;
+		goto fail_map_hermes;
 	}
 
 	/* Allocate network device */
 	dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
-	if (! dev) {
+	if (!dev) {
+		printk(KERN_ERR PFX "Cannot allocate network device\n");
 		err = -ENOMEM;
 		goto fail_alloc;
 	}
 
 	priv = netdev_priv(dev);
 	card = priv->card;
-	card->pci_ioaddr = pci_ioaddr;
-	dev->mem_start = pci_iorange;
-	dev->mem_end = pci_iorange + pci_iolen - 1;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING);
-
-	printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n",
-	       pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq);
+	hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
 
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
@@ -225,9 +161,7 @@
 		err = -EBUSY;
 		goto fail_irq;
 	}
-	dev->irq = pdev->irq;
 
-	/* Perform a COR reset to start the card */
 	err = orinoco_pci_cor_reset(priv);
 	if (err) {
 		printk(KERN_ERR PFX "Initial reset failed\n");
@@ -236,11 +170,13 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		printk(KERN_ERR PFX "Failed to register net device\n");
+		printk(KERN_ERR PFX "Cannot register network device\n");
 		goto fail;
 	}
 
 	pci_set_drvdata(pdev, dev);
+	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+	       pci_name(pdev));
 
 	return 0;
 
@@ -252,9 +188,9 @@
 	free_orinocodev(dev);
 
  fail_alloc:
-	iounmap(pci_ioaddr);
+	pci_iounmap(pdev, hermes_io);
 
- fail_map:
+ fail_map_hermes:
 	pci_release_regions(pdev);
 
  fail_resources:
@@ -267,87 +203,17 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct orinoco_private *priv = netdev_priv(dev);
-	struct orinoco_pci_card *card = priv->card;
 
 	unregister_netdev(dev);
-	free_irq(dev->irq, dev);
+	free_irq(pdev->irq, dev);
 	pci_set_drvdata(pdev, NULL);
 	free_orinocodev(dev);
-	iounmap(card->pci_ioaddr);
+	pci_iounmap(pdev, priv->hw.iobase);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
-static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = netdev_priv(dev);
-	unsigned long flags;
-	int err;
-	
-
-	err = orinoco_lock(priv, &flags);
-	if (err) {
-		printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n",
-		       dev->name);
-		return err;
-	}
-
-	err = __orinoco_down(dev);
-	if (err)
-		printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n",
-		       dev->name, err);
-	
-	netif_device_detach(dev);
-
-	priv->hw_unavailable++;
-	
-	orinoco_unlock(priv, &flags);
-
-	pci_save_state(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
-	return 0;
-}
-
-static int orinoco_pci_resume(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-	struct orinoco_private *priv = netdev_priv(dev);
-	unsigned long flags;
-	int err;
-
-	printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);
-
-	pci_set_power_state(pdev, 0);
-	pci_restore_state(pdev);
-
-	err = orinoco_reinit_firmware(dev);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n",
-		       dev->name, err);
-		return err;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	netif_device_attach(dev);
-
-	priv->hw_unavailable--;
-
-	if (priv->open && (! priv->hw_unavailable)) {
-		err = __orinoco_up(dev);
-		if (err)
-			printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n",
-			       dev->name, err);
-	}
-	
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
-}
-
-static struct pci_device_id orinoco_pci_pci_id_table[] = {
+static struct pci_device_id orinoco_pci_id_table[] = {
 	/* Intersil Prism 3 */
 	{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
 	/* Intersil Prism 2.5 */
@@ -357,11 +223,11 @@
 	{0,},
 };
 
-MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);
 
 static struct pci_driver orinoco_pci_driver = {
 	.name		= DRIVER_NAME,
-	.id_table	= orinoco_pci_pci_id_table,
+	.id_table	= orinoco_pci_id_table,
 	.probe		= orinoco_pci_init_one,
 	.remove		= __devexit_p(orinoco_pci_remove_one),
 	.suspend	= orinoco_pci_suspend,
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h
new file mode 100644
index 0000000..7eb1e08
--- /dev/null
+++ b/drivers/net/wireless/orinoco_pci.h
@@ -0,0 +1,104 @@
+/* orinoco_pci.h
+ * 
+ * Common code for all Orinoco drivers for PCI devices, including
+ * both native PCI and PCMCIA-to-PCI bridges.
+ *
+ * Copyright (C) 2005, Pavel Roskin.
+ * See orinoco.c for license.
+ */
+
+#ifndef _ORINOCO_PCI_H
+#define _ORINOCO_PCI_H
+
+#include <linux/netdevice.h>
+
+/* Driver specific data */
+struct orinoco_pci_card {
+	void __iomem *bridge_io;
+	void __iomem *attr_io;
+};
+
+#ifdef CONFIG_PM
+static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct orinoco_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	int err;
+
+	err = orinoco_lock(priv, &flags);
+	if (err) {
+		printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
+		       dev->name);
+		return err;
+	}
+
+	err = __orinoco_down(dev);
+	if (err)
+		printk(KERN_WARNING "%s: error %d bringing interface down "
+		       "for suspend\n", dev->name, err);
+	
+	netif_device_detach(dev);
+
+	priv->hw_unavailable++;
+	
+	orinoco_unlock(priv, &flags);
+
+	free_irq(pdev->irq, dev);
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
+}
+
+static int orinoco_pci_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct orinoco_private *priv = netdev_priv(dev);
+	unsigned long flags;
+	int err;
+
+	pci_set_power_state(pdev, 0);
+	pci_enable_device(pdev);
+	pci_restore_state(pdev);
+
+	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
+			  dev->name, dev);
+	if (err) {
+		printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
+		       dev->name);
+		pci_disable_device(pdev);
+		return -EBUSY;
+	}
+
+	err = orinoco_reinit_firmware(dev);
+	if (err) {
+		printk(KERN_ERR "%s: error %d re-initializing firmware "
+		       "on resume\n", dev->name, err);
+		return err;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	netif_device_attach(dev);
+
+	priv->hw_unavailable--;
+
+	if (priv->open && (! priv->hw_unavailable)) {
+		err = __orinoco_up(dev);
+		if (err)
+			printk(KERN_ERR "%s: Error %d restarting card on resume\n",
+			       dev->name, err);
+	}
+	
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+#else
+#define orinoco_pci_suspend NULL
+#define orinoco_pci_resume NULL
+#endif
+
+#endif /* _ORINOCO_PCI_H */
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 210e737..84f696c 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -3,7 +3,7 @@
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a PLX9052.
  *
- * Current maintainers (as of 29 September 2003) are:
+ * Current maintainers are:
  * 	Pavel Roskin <proski AT gnu.org>
  * and	David Gibson <hermes AT gibson.dropbear.id.au>
  *
@@ -30,38 +30,18 @@
  * other provisions required by the GPL.  If you do not delete the
  * provisions above, a recipient may use your version of this file
  * under either the MPL or the GPL.
-
- * Caution: this is experimental and probably buggy.  For success and
- * failure reports for different cards and adaptors, see
- * orinoco_plx_pci_id_table near the end of the file.  If you have a
- * card we don't have the PCI id for, and looks like it should work,
- * drop me mail with the id and "it works"/"it doesn't work".
  *
- * Note: if everything gets detected fine but it doesn't actually send
- * or receive packets, your first port of call should probably be to
- * try newer firmware in the card.  Especially if you're doing Ad-Hoc
- * modes.
- *
- * The actual driving is done by orinoco.c, this is just resource
- * allocation stuff.  The explanation below is courtesy of Ryan Niemi
- * on the linux-wlan-ng list at
- * http://archives.neohapsis.com/archives/dev/linux-wlan/2001-q1/0026.html
- *
- * The PLX9052-based cards (WL11000 and several others) are a
- * different beast than the usual PCMCIA-based PRISM2 configuration
- * expected by wlan-ng.  Here's the general details on how the WL11000
- * PCI adapter works:
+ * Here's the general details on how the PLX9052 adapter works:
  *
  * - Two PCI I/O address spaces, one 0x80 long which contains the
  * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA
  * slot I/O address space.
  *
- * - One PCI memory address space, mapped to the PCMCIA memory space
+ * - One PCI memory address space, mapped to the PCMCIA attribute space
  * (containing the CIS).
  *
- * After identifying the I/O and memory space, you can read through
- * the memory space to confirm the CIS's device ID or manufacturer ID
- * to make sure it's the expected card.  qKeep in mind that the PCMCIA
+ * Using the later, you can read through the CIS data to make sure the
+ * card is compatible with the driver. Keep in mind that the PCMCIA
  * spec specifies the CIS as the lower 8 bits of each word read from
  * the CIS, so to read the bytes of the CIS, read every other byte
  * (0,2,4,...). Passing that test, you need to enable the I/O address
@@ -71,7 +51,7 @@
  * within the PCI memory space. Write 0x41 to the COR register to
  * enable I/O mode and to select level triggered interrupts. To
  * confirm you actually succeeded, read the COR register back and make
- * sure it actually got set to 0x41, incase you have an unexpected
+ * sure it actually got set to 0x41, in case you have an unexpected
  * card inserted.
  *
  * Following that, you can treat the second PCI I/O address space (the
@@ -101,16 +81,6 @@
  * that, I've hot-swapped a number of times during debugging and
  * driver development for various reasons (stuck WAIT# line after the
  * radio card's firmware locks up).
- *
- * Hope this is enough info for someone to add PLX9052 support to the
- * wlan-ng card. In the case of the WL11000, the PCI ID's are
- * 0x1639/0x0200, with matching subsystem ID's. Other PLX9052-based
- * manufacturers other than Eumitcom (or on cards other than the
- * WL11000) may have different PCI ID's.
- *
- * If anyone needs any more specific info, let me know. I haven't had
- * time to implement support myself yet, and with the way things are
- * going, might not have time for a while..
  */
 
 #define DRIVER_NAME "orinoco_plx"
@@ -125,6 +95,7 @@
 #include <pcmcia/cisreg.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
 #define COR_OFFSET	(0x3e0)	/* COR attribute offset of Prism2 PC card */
 #define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
@@ -134,30 +105,20 @@
 #define PLX_INTCSR		0x4c /* Interrupt Control & Status Register */
 #define PLX_INTCSR_INTEN	(1<<6) /* Interrupt Enable bit */
 
-static const u8 cis_magic[] = {
-	0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
-};
-
-/* Orinoco PLX specific data */
-struct orinoco_plx_card {
-	void __iomem *attr_mem;
-};
-
 /*
  * Do a soft reset of the card using the Configuration Option Register
  */
 static int orinoco_plx_cor_reset(struct orinoco_private *priv)
 {
 	hermes_t *hw = &priv->hw;
-	struct orinoco_plx_card *card = priv->card;
-	u8 __iomem *attr_mem = card->attr_mem;
+	struct orinoco_pci_card *card = priv->card;
 	unsigned long timeout;
 	u16 reg;
 
-	writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET);
+	iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET);
 	mdelay(1);
 
-	writeb(COR_VALUE, attr_mem + COR_OFFSET);
+	iowrite8(COR_VALUE, card->attr_io + COR_OFFSET);
 	mdelay(1);
 
 	/* Just in case, wait more until the card is no longer busy */
@@ -168,7 +129,7 @@
 		reg = hermes_read_regn(hw, CMD);
 	}
 
-	/* Did we timeout ? */
+	/* Still busy? */
 	if (reg & HERMES_CMD_BUSY) {
 		printk(KERN_ERR PFX "Busy timeout\n");
 		return -ETIMEDOUT;
@@ -177,20 +138,55 @@
 	return 0;
 }
 
+static int orinoco_plx_hw_init(struct orinoco_pci_card *card)
+{
+	int i;
+	u32 csr_reg;
+	static const u8 cis_magic[] = {
+		0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
+	};
+
+	printk(KERN_DEBUG PFX "CIS: ");
+	for (i = 0; i < 16; i++) {
+		printk("%02X:", ioread8(card->attr_io + (i << 1)));
+	}
+	printk("\n");
+
+	/* Verify whether a supported PC card is present */
+	/* FIXME: we probably need to be smarted about this */
+	for (i = 0; i < sizeof(cis_magic); i++) {
+		if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) {
+			printk(KERN_ERR PFX "The CIS value of Prism2 PC "
+			       "card is unexpected\n");
+			return -ENODEV;
+		}
+	}
+
+	/* bjoern: We need to tell the card to enable interrupts, in
+	   case the serial eprom didn't do this already.  See the
+	   PLX9052 data book, p8-1 and 8-24 for reference. */
+	csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
+	if (!(csr_reg & PLX_INTCSR_INTEN)) {
+		csr_reg |= PLX_INTCSR_INTEN;
+		iowrite32(csr_reg, card->bridge_io + PLX_INTCSR);
+		csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
+		if (!(csr_reg & PLX_INTCSR_INTEN)) {
+			printk(KERN_ERR PFX "Cannot enable interrupts\n");
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
 
 static int orinoco_plx_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
-	int err = 0;
-	u8 __iomem *attr_mem = NULL;
-	u32 csr_reg, plx_addr;
-	struct orinoco_private *priv = NULL;
-	struct orinoco_plx_card *card;
-	unsigned long pccard_ioaddr = 0;
-	unsigned long pccard_iolen = 0;
-	struct net_device *dev = NULL;
-	void __iomem *mem;
-	int i;
+	int err;
+	struct orinoco_private *priv;
+	struct orinoco_pci_card *card;
+	struct net_device *dev;
+	void __iomem *hermes_io, *attr_io, *bridge_io;
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -199,30 +195,30 @@
 	}
 
 	err = pci_request_regions(pdev, DRIVER_NAME);
-	if (err != 0) {
+	if (err) {
 		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
 		goto fail_resources;
 	}
 
-	/* Resource 1 is mapped to PLX-specific registers */
-	plx_addr = pci_resource_start(pdev, 1);
+	bridge_io = pci_iomap(pdev, 1, 0);
+	if (!bridge_io) {
+		printk(KERN_ERR PFX "Cannot map bridge registers\n");
+		err = -EIO;
+		goto fail_map_bridge;
+	}
 
-	/* Resource 2 is mapped to the PCMCIA attribute memory */
-	attr_mem = ioremap(pci_resource_start(pdev, 2),
-			   pci_resource_len(pdev, 2));
-	if (!attr_mem) {
-		printk(KERN_ERR PFX "Cannot remap PCMCIA space\n");
+	attr_io = pci_iomap(pdev, 2, 0);
+	if (!attr_io) {
+		printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
+		err = -EIO;
 		goto fail_map_attr;
 	}
 
-	/* Resource 3 is mapped to the PCMCIA I/O address space */
-	pccard_ioaddr = pci_resource_start(pdev, 3);
-	pccard_iolen = pci_resource_len(pdev, 3);
-
-	mem = pci_iomap(pdev, 3, 0);
-	if (!mem) {
-		err = -ENOMEM;
-		goto fail_map_io;
+	hermes_io = pci_iomap(pdev, 3, 0);
+	if (!hermes_io) {
+		printk(KERN_ERR PFX "Cannot map chipset registers\n");
+		err = -EIO;
+		goto fail_map_hermes;
 	}
 
 	/* Allocate network device */
@@ -235,16 +231,12 @@
 
 	priv = netdev_priv(dev);
 	card = priv->card;
-	card->attr_mem = attr_mem;
-	dev->base_addr = pccard_ioaddr;
+	card->bridge_io = bridge_io;
+	card->attr_io = attr_io;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
-
-	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device "
-	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
-	       pccard_ioaddr);
+	hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
 
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
@@ -253,20 +245,11 @@
 		err = -EBUSY;
 		goto fail_irq;
 	}
-	dev->irq = pdev->irq;
 
-	/* bjoern: We need to tell the card to enable interrupts, in
-	   case the serial eprom didn't do this already.  See the
-	   PLX9052 data book, p8-1 and 8-24 for reference. */
-	csr_reg = inl(plx_addr + PLX_INTCSR);
-	if (!(csr_reg & PLX_INTCSR_INTEN)) {
-		csr_reg |= PLX_INTCSR_INTEN;
-		outl(csr_reg, plx_addr + PLX_INTCSR);
-		csr_reg = inl(plx_addr + PLX_INTCSR);
-		if (!(csr_reg & PLX_INTCSR_INTEN)) {
-			printk(KERN_ERR PFX "Cannot enable interrupts\n");
-			goto fail;
-		}
+	err = orinoco_plx_hw_init(card);
+	if (err) {
+		printk(KERN_ERR PFX "Hardware initialization failed\n");
+		goto fail;
 	}
 
 	err = orinoco_plx_cor_reset(priv);
@@ -275,23 +258,6 @@
 		goto fail;
 	}
 
-	printk(KERN_DEBUG PFX "CIS: ");
-	for (i = 0; i < 16; i++) {
-		printk("%02X:", readb(attr_mem + 2*i));
-	}
-	printk("\n");
-
-	/* Verify whether a supported PC card is present */
-	/* FIXME: we probably need to be smarted about this */
-	for (i = 0; i < sizeof(cis_magic); i++) {
-		if (cis_magic[i] != readb(attr_mem +2*i)) {
-			printk(KERN_ERR PFX "The CIS value of Prism2 PC "
-			       "card is unexpected\n");
-			err = -EIO;
-			goto fail;
-		}
-	}
-
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR PFX "Cannot register network device\n");
@@ -299,6 +265,8 @@
 	}
 
 	pci_set_drvdata(pdev, dev);
+	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+	       pci_name(pdev));
 
 	return 0;
 
@@ -310,12 +278,15 @@
 	free_orinocodev(dev);
 
  fail_alloc:
-	pci_iounmap(pdev, mem);
+	pci_iounmap(pdev, hermes_io);
 
- fail_map_io:
-	iounmap(attr_mem);
+ fail_map_hermes:
+	pci_iounmap(pdev, attr_io);
 
  fail_map_attr:
+	pci_iounmap(pdev, bridge_io);
+
+ fail_map_bridge:
 	pci_release_regions(pdev);
 
  fail_resources:
@@ -328,23 +299,20 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct orinoco_private *priv = netdev_priv(dev);
-	struct orinoco_plx_card *card = priv->card;
-	u8 __iomem *attr_mem = card->attr_mem;
-
-	BUG_ON(! dev);
+	struct orinoco_pci_card *card = priv->card;
 
 	unregister_netdev(dev);
-	free_irq(dev->irq, dev);
+	free_irq(pdev->irq, dev);
 	pci_set_drvdata(pdev, NULL);
 	free_orinocodev(dev);
 	pci_iounmap(pdev, priv->hw.iobase);
-	iounmap(attr_mem);
+	pci_iounmap(pdev, card->attr_io);
+	pci_iounmap(pdev, card->bridge_io);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
-
-static struct pci_device_id orinoco_plx_pci_id_table[] = {
+static struct pci_device_id orinoco_plx_id_table[] = {
 	{0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,},	/* Siemens SpeedStream SS1023 */
 	{0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,},	/* Netgear MA301 */
 	{0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,},	/* Correga  - does this work? */
@@ -362,13 +330,15 @@
 	{0,},
 };
 
-MODULE_DEVICE_TABLE(pci, orinoco_plx_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table);
 
 static struct pci_driver orinoco_plx_driver = {
 	.name		= DRIVER_NAME,
-	.id_table	= orinoco_plx_pci_id_table,
+	.id_table	= orinoco_plx_id_table,
 	.probe		= orinoco_plx_init_one,
 	.remove		= __devexit_p(orinoco_plx_remove_one),
+	.suspend	= orinoco_pci_suspend,
+	.resume		= orinoco_pci_resume,
 };
 
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -388,7 +358,6 @@
 static void __exit orinoco_plx_exit(void)
 {
 	pci_unregister_driver(&orinoco_plx_driver);
-	ssleep(1);
 }
 
 module_init(orinoco_plx_init);
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index 5e68b70..d2b4dec 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -1,5 +1,5 @@
 /* orinoco_tmd.c
- * 
+ *
  * Driver for Prism II devices which would usually be driven by orinoco_cs,
  * but are connected to the PCI bus by a TMD7160. 
  *
@@ -26,25 +26,13 @@
  * other provisions required by the GPL.  If you do not delete the
  * provisions above, a recipient may use your version of this file
  * under either the MPL or the GPL.
-
- * Caution: this is experimental and probably buggy.  For success and
- * failure reports for different cards and adaptors, see
- * orinoco_tmd_pci_id_table near the end of the file.  If you have a
- * card we don't have the PCI id for, and looks like it should work,
- * drop me mail with the id and "it works"/"it doesn't work".
- *
- * Note: if everything gets detected fine but it doesn't actually send
- * or receive packets, your first port of call should probably be to   
- * try newer firmware in the card.  Especially if you're doing Ad-Hoc
- * modes
  *
  * The actual driving is done by orinoco.c, this is just resource
  * allocation stuff.
  *
  * This driver is modeled after the orinoco_plx driver. The main
- * difference is that the TMD chip has only IO port ranges and no
- * memory space, i.e.  no access to the CIS. Compared to the PLX chip,
- * the io range functionalities are exchanged.
+ * difference is that the TMD chip has only IO port ranges and doesn't
+ * provide access to the PCMCIA attribute space.
  *
  * Pheecom sells cards with the TMD chip as "ASIC version"
  */
@@ -61,32 +49,26 @@
 #include <pcmcia/cisreg.h>
 
 #include "orinoco.h"
+#include "orinoco_pci.h"
 
 #define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
 #define COR_RESET     (0x80)	/* reset bit in the COR register */
 #define TMD_RESET_TIME	(500)	/* milliseconds */
 
-/* Orinoco TMD specific data */
-struct orinoco_tmd_card {
-	u32 tmd_io;
-};
-
-
 /*
  * Do a soft reset of the card using the Configuration Option Register
  */
 static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
 {
 	hermes_t *hw = &priv->hw;
-	struct orinoco_tmd_card *card = priv->card;
-	u32 addr = card->tmd_io;
+	struct orinoco_pci_card *card = priv->card;
 	unsigned long timeout;
 	u16 reg;
 
-	outb(COR_VALUE | COR_RESET, addr);
+	iowrite8(COR_VALUE | COR_RESET, card->bridge_io);
 	mdelay(1);
 
-	outb(COR_VALUE, addr);
+	iowrite8(COR_VALUE, card->bridge_io);
 	mdelay(1);
 
 	/* Just in case, wait more until the card is no longer busy */
@@ -97,7 +79,7 @@
 		reg = hermes_read_regn(hw, CMD);
 	}
 
-	/* Did we timeout ? */
+	/* Still busy? */
 	if (reg & HERMES_CMD_BUSY) {
 		printk(KERN_ERR PFX "Busy timeout\n");
 		return -ETIMEDOUT;
@@ -110,11 +92,11 @@
 static int orinoco_tmd_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
-	int err = 0;
-	struct orinoco_private *priv = NULL;
-	struct orinoco_tmd_card *card;
-	struct net_device *dev = NULL;
-	void __iomem *mem;
+	int err;
+	struct orinoco_private *priv;
+	struct orinoco_pci_card *card;
+	struct net_device *dev;
+	void __iomem *hermes_io, *bridge_io;
 
 	err = pci_enable_device(pdev);
 	if (err) {
@@ -123,20 +105,28 @@
 	}
 
 	err = pci_request_regions(pdev, DRIVER_NAME);
-	if (err != 0) {
+	if (err) {
 		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
 		goto fail_resources;
 	}
 
-	mem = pci_iomap(pdev, 2, 0);
-	if (! mem) {
-		err = -ENOMEM;
-		goto fail_iomap;
+	bridge_io = pci_iomap(pdev, 1, 0);
+	if (!bridge_io) {
+		printk(KERN_ERR PFX "Cannot map bridge registers\n");
+		err = -EIO;
+		goto fail_map_bridge;
+	}
+
+	hermes_io = pci_iomap(pdev, 2, 0);
+	if (!hermes_io) {
+		printk(KERN_ERR PFX "Cannot map chipset registers\n");
+		err = -EIO;
+		goto fail_map_hermes;
 	}
 
 	/* Allocate network device */
 	dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
-	if (! dev) {
+	if (!dev) {
 		printk(KERN_ERR PFX "Cannot allocate network device\n");
 		err = -ENOMEM;
 		goto fail_alloc;
@@ -144,16 +134,11 @@
 
 	priv = netdev_priv(dev);
 	card = priv->card;
-	card->tmd_io = pci_resource_start(pdev, 1);
-	dev->base_addr = pci_resource_start(pdev, 2);
+	card->bridge_io = bridge_io;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
-
-	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
-	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
-	       dev->base_addr);
+	hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
 
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
@@ -162,7 +147,6 @@
 		err = -EBUSY;
 		goto fail_irq;
 	}
-	dev->irq = pdev->irq;
 
 	err = orinoco_tmd_cor_reset(priv);
 	if (err) {
@@ -177,6 +161,8 @@
 	}
 
 	pci_set_drvdata(pdev, dev);
+	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+	       pci_name(pdev));
 
 	return 0;
 
@@ -188,9 +174,12 @@
 	free_orinocodev(dev);
 
  fail_alloc:
-	pci_iounmap(pdev, mem);
+	pci_iounmap(pdev, hermes_io);
 
- fail_iomap:
+ fail_map_hermes:
+	pci_iounmap(pdev, bridge_io);
+
+ fail_map_bridge:
 	pci_release_regions(pdev);
 
  fail_resources:
@@ -203,31 +192,32 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct orinoco_private *priv = dev->priv;
-
-	BUG_ON(! dev);
+	struct orinoco_pci_card *card = priv->card;
 
 	unregister_netdev(dev);
-	free_irq(dev->irq, dev);
+	free_irq(pdev->irq, dev);
 	pci_set_drvdata(pdev, NULL);
 	free_orinocodev(dev);
 	pci_iounmap(pdev, priv->hw.iobase);
+	pci_iounmap(pdev, card->bridge_io);
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
-
-static struct pci_device_id orinoco_tmd_pci_id_table[] = {
+static struct pci_device_id orinoco_tmd_id_table[] = {
 	{0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,},      /* NDC and OEMs, e.g. pheecom */
 	{0,},
 };
 
-MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table);
+MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table);
 
 static struct pci_driver orinoco_tmd_driver = {
 	.name		= DRIVER_NAME,
-	.id_table	= orinoco_tmd_pci_id_table,
+	.id_table	= orinoco_tmd_id_table,
 	.probe		= orinoco_tmd_init_one,
 	.remove		= __devexit_p(orinoco_tmd_remove_one),
+	.suspend	= orinoco_pci_suspend,
+	.resume		= orinoco_pci_resume,
 };
 
 static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
@@ -245,7 +235,6 @@
 static void __exit orinoco_tmd_exit(void)
 {
 	pci_unregister_driver(&orinoco_tmd_driver);
-	ssleep(1);
 }
 
 module_init(orinoco_tmd_init);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 879eb42..a915fe6 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -924,8 +924,7 @@
 
     if (length < ETH_ZLEN)
     {
-    	skb = skb_padto(skb, ETH_ZLEN);
-    	if (skb == NULL)
+    	if (skb_padto(skb, ETH_ZLEN))
     		return 0;
     	length = ETH_ZLEN;
     }
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index f7b77ce..7f9aa13 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -1,6 +1,6 @@
 /*
  * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
- * Symbol Wireless Networker LA4100, CompactFlash cards by Socket
+ * Symbol Wireless Networker LA4137, CompactFlash cards by Socket
  * Communications and Intel PRO/Wireless 2011B.
  *
  * The driver implements Symbol firmware download.  The rest is handled
@@ -120,8 +120,8 @@
  * Each block has the following structure.
  */
 struct dblock {
-	__le32 _addr;		/* adapter address where to write the block */
-	__le16 _len;		/* length of the data only, in bytes */
+	__le32 addr;		/* adapter address where to write the block */
+	__le16 len;		/* length of the data only, in bytes */
 	char data[0];		/* data to be written */
 } __attribute__ ((packed));
 
@@ -131,9 +131,9 @@
  * items with matching ID should be written.
  */
 struct pdr {
-	__le32 _id;		/* record ID */
-	__le32 _addr;		/* adapter address where to write the data */
-	__le32 _len;		/* expected length of the data, in bytes */
+	__le32 id;		/* record ID */
+	__le32 addr;		/* adapter address where to write the data */
+	__le32 len;		/* expected length of the data, in bytes */
 	char next[0];		/* next PDR starts here */
 } __attribute__ ((packed));
 
@@ -144,8 +144,8 @@
  * be plugged into the secondary firmware.
  */
 struct pdi {
-	__le16 _len;		/* length of ID and data, in words */
-	__le16 _id;		/* record ID */
+	__le16 len;		/* length of ID and data, in words */
+	__le16 id;		/* record ID */
 	char data[0];		/* plug data */
 } __attribute__ ((packed));
 
@@ -154,44 +154,44 @@
 static inline u32
 dblock_addr(const struct dblock *blk)
 {
-	return le32_to_cpu(blk->_addr);
+	return le32_to_cpu(blk->addr);
 }
 
 static inline u32
 dblock_len(const struct dblock *blk)
 {
-	return le16_to_cpu(blk->_len);
+	return le16_to_cpu(blk->len);
 }
 
 static inline u32
 pdr_id(const struct pdr *pdr)
 {
-	return le32_to_cpu(pdr->_id);
+	return le32_to_cpu(pdr->id);
 }
 
 static inline u32
 pdr_addr(const struct pdr *pdr)
 {
-	return le32_to_cpu(pdr->_addr);
+	return le32_to_cpu(pdr->addr);
 }
 
 static inline u32
 pdr_len(const struct pdr *pdr)
 {
-	return le32_to_cpu(pdr->_len);
+	return le32_to_cpu(pdr->len);
 }
 
 static inline u32
 pdi_id(const struct pdi *pdi)
 {
-	return le16_to_cpu(pdi->_id);
+	return le16_to_cpu(pdi->id);
 }
 
 /* Return length of the data only, in bytes */
 static inline u32
 pdi_len(const struct pdi *pdi)
 {
-	return 2 * (le16_to_cpu(pdi->_len) - 1);
+	return 2 * (le16_to_cpu(pdi->len) - 1);
 }
 
 
@@ -343,8 +343,7 @@
 
 	/* do the actual plugging */
 	spectrum_aux_setaddr(hw, pdr_addr(pdr));
-	hermes_write_words(hw, HERMES_AUXDATA, pdi->data,
-			   pdi_len(pdi) / 2);
+	hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
 
 	return 0;
 }
@@ -424,8 +423,8 @@
 
 	while (dblock_addr(blk) != BLOCK_END) {
 		spectrum_aux_setaddr(hw, blkaddr);
-		hermes_write_words(hw, HERMES_AUXDATA, blk->data,
-				   blklen / 2);
+		hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
+				   blklen);
 
 		blk = (struct dblock *) &blk->data[blklen];
 		blkaddr = dblock_addr(blk);
@@ -626,14 +625,11 @@
 {
 	struct net_device *dev = link->priv;
 
+	if (link->dev_node)
+		unregister_netdev(dev);
+
 	spectrum_cs_release(link);
 
-	DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
-	if (link->dev_node) {
-		DEBUG(0, PFX "About to unregister net device %p\n",
-		      dev);
-		unregister_netdev(dev);
-	}
 	free_orinocodev(dev);
 }				/* spectrum_cs_detach */
 
@@ -653,13 +649,10 @@
 	int last_fn, last_ret;
 	u_char buf[64];
 	config_info_t conf;
-	cisinfo_t info;
 	tuple_t tuple;
 	cisparse_t parse;
 	void __iomem *mem;
 
-	CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info));
-
 	/*
 	 * This reads the card's CONFIG tuple to find its
 	 * configuration registers.
@@ -709,12 +702,6 @@
 			goto next_entry;
 		link->conf.ConfigIndex = cfg->index;
 
-		/* Does this card need audio output? */
-		if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
-			link->conf.Attributes |= CONF_ENABLE_SPKR;
-			link->conf.Status = CCSR_AUDIO_ENA;
-		}
-
 		/* Use power settings for Vcc and Vpp if present */
 		/* Note that the CIS values need to be rescaled */
 		if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
@@ -835,19 +822,10 @@
                                     net_device has been registered */
 
 	/* Finally, report what we've done */
-	printk(KERN_DEBUG "%s: index 0x%02x: ",
-	       dev->name, link->conf.ConfigIndex);
-	if (link->conf.Vpp)
-		printk(", Vpp %d.%d", link->conf.Vpp / 10,
-		       link->conf.Vpp % 10);
-	printk(", irq %d", link->irq.AssignedIRQ);
-	if (link->io.NumPorts1)
-		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-		       link->io.BasePort1 + link->io.NumPorts1 - 1);
-	if (link->io.NumPorts2)
-		printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-		       link->io.BasePort2 + link->io.NumPorts2 - 1);
-	printk("\n");
+	printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
+	       "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+	       link->irq.AssignedIRQ, link->io.BasePort1,
+	       link->io.BasePort1 + link->io.NumPorts1 - 1);
 
 	return 0;
 
@@ -888,11 +866,10 @@
 {
 	struct net_device *dev = link->priv;
 	struct orinoco_private *priv = netdev_priv(dev);
-	unsigned long flags;
 	int err = 0;
 
 	/* Mark the device as stopped, to block IO until later */
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock(&priv->lock);
 
 	err = __orinoco_down(dev);
 	if (err)
@@ -902,9 +879,9 @@
 	netif_device_detach(dev);
 	priv->hw_unavailable++;
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock(&priv->lock);
 
-	return 0;
+	return err;
 }
 
 static int
@@ -932,7 +909,7 @@
 	" David Gibson <hermes@gibson.dropbear.id.au>, et al)";
 
 static struct pcmcia_device_id spectrum_cs_ids[] = {
-	PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */
+	PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
 	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
 	PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
 	PCMCIA_DEVICE_NULL,
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index dade4b9..5b69befd 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -1695,8 +1695,8 @@
 		/* Look in the table if the frequency is allowed */
 		if (table[9 - (freq / 16)] & (1 << (freq % 16))) {
 			/* Compute approximate channel number */
-			while ((((channel_bands[c] >> 1) - 24) < freq) &&
-			       (c < NELS(channel_bands)))
+			while ((c < NELS(channel_bands)) &&
+				(((channel_bands[c] >> 1) - 24) < freq)) 
 				c++;
 			list[i].i = c;	/* Set the list index */
 
@@ -2903,6 +2903,7 @@
 {
 	net_local *lp = (net_local *) dev->priv;
 	unsigned long flags;
+	char data[ETH_ZLEN];
 
 #ifdef DEBUG_TX_TRACE
 	printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name,
@@ -2937,15 +2938,16 @@
 	 * able to detect collisions, therefore in theory we don't really
 	 * need to pad. Jean II */
 	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
+		memset(data, 0, ETH_ZLEN);
+		memcpy(data, skb->data, skb->len);
+		/* Write packet on the card */
+		if(wv_packet_write(dev, data, ETH_ZLEN))
+			return 1;	/* We failed */
 	}
-
-	/* Write packet on the card */
-	if(wv_packet_write(dev, skb->data, skb->len))
+	else if(wv_packet_write(dev, skb->data, skb->len))
 		return 1;	/* We failed */
 
+
 	dev_kfree_skb(skb);
 
 #ifdef DEBUG_TX_TRACE
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index f7724eb..561250f 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -3194,11 +3194,8 @@
 	 * and we don't have the Ethernet specific requirement of beeing
 	 * able to detect collisions, therefore in theory we don't really
 	 * need to pad. Jean II */
-	if (skb->len < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
-	}
+	if (skb_padto(skb, ETH_ZLEN))
+		return 0;
 
   wv_packet_write(dev, skb->data, skb->len);
 
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
new file mode 100644
index 0000000..662ecc8
--- /dev/null
+++ b/drivers/net/wireless/zd1201.c
@@ -0,0 +1,1929 @@
+/*
+ *	Driver for ZyDAS zd1201 based wireless USB devices.
+ *
+ *	Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	version 2 as published by the Free Software Foundation.
+ *
+ *	Parts of this driver have been derived from a wlan-ng version
+ *	modified by ZyDAS. They also made documentation available, thanks!
+ *	Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/string.h>
+#include <linux/if_arp.h>
+#include <linux/firmware.h>
+#include <net/ieee80211.h>
+#include "zd1201.h"
+
+static struct usb_device_id zd1201_table[] = {
+	{USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
+	{USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
+	{USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb  adapter */
+	{USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb  adapter */
+	{USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */
+	{}
+};
+
+static int ap;	/* Are we an AP or a normal station? */
+
+#define ZD1201_VERSION	"0.15"
+
+MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
+MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters");
+MODULE_VERSION(ZD1201_VERSION);
+MODULE_LICENSE("GPL");
+module_param(ap, int, 0);
+MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded");
+MODULE_DEVICE_TABLE(usb, zd1201_table);
+
+
+static int zd1201_fw_upload(struct usb_device *dev, int apfw)
+{
+	const struct firmware *fw_entry;
+	char *data;
+	unsigned long len;
+	int err;
+	unsigned char ret;
+	char *buf;
+	char *fwfile;
+
+	if (apfw)
+		fwfile = "zd1201-ap.fw";
+	else
+		fwfile = "zd1201.fw";
+
+	err = request_firmware(&fw_entry, fwfile, &dev->dev);
+	if (err) {
+		dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
+		dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
+		dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n");
+		return err;
+	}
+
+	data = fw_entry->data;
+        len = fw_entry->size;
+
+	buf = kmalloc(1024, GFP_ATOMIC);
+	if (!buf)
+		goto exit;
+	
+	while (len > 0) {
+		int translen = (len > 1024) ? 1024 : len;
+		memcpy(buf, data, translen);
+
+		err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0,
+		    USB_DIR_OUT | 0x40, 0, 0, buf, translen,
+		    ZD1201_FW_TIMEOUT);
+		if (err < 0)
+			goto exit;
+
+		len -= translen;
+		data += translen;
+	}
+                                        
+	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2,
+	    USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
+	if (err < 0)
+		goto exit;
+
+	err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
+	    USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+	if (err < 0)
+		goto exit;
+
+	if (ret & 0x80) {
+		err = -EIO;
+		goto exit;
+	}
+
+	err = 0;
+exit:
+	kfree(buf);
+	release_firmware(fw_entry);
+	return err;
+}
+
+static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
+{
+	struct zd1201 *zd = urb->context;
+
+	switch(urb->status) {
+		case -EILSEQ:
+		case -ENODEV:
+		case -ETIMEDOUT:
+		case -ENOENT:
+		case -EPIPE:
+		case -EOVERFLOW:
+		case -ESHUTDOWN:
+			dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", 
+			    zd->dev->name, urb->status);
+	}
+
+	kfree(urb->transfer_buffer);
+	usb_free_urb(urb);
+	return;
+}
+
+/* cmdreq message: 
+	u32 type
+	u16 cmd
+	u16 parm0
+	u16 parm1
+	u16 parm2
+	u8  pad[4]
+
+	total: 4 + 2 + 2 + 2 + 2 + 4 = 16
+*/
+static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
+			int parm1, int parm2)
+{
+	unsigned char *command;
+	int ret;
+	struct urb *urb;
+
+	command = kmalloc(16, GFP_ATOMIC);
+	if (!command)
+		return -ENOMEM;
+
+	*((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ);
+	*((__le16*)&command[4]) = cpu_to_le16(cmd);
+	*((__le16*)&command[6]) = cpu_to_le16(parm0);
+	*((__le16*)&command[8]) = cpu_to_le16(parm1);
+	*((__le16*)&command[10])= cpu_to_le16(parm2);
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree(command);
+		return -ENOMEM;
+	}
+	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+			  command, 16, zd1201_usbfree, zd);
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret) {
+		kfree(command);
+		usb_free_urb(urb);
+	}
+
+	return ret;
+}
+
+/* Callback after sending out a packet */
+static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
+{
+	struct zd1201 *zd = urb->context;
+	netif_wake_queue(zd->dev);
+	return;
+}
+
+/* Incoming data */
+static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
+{
+	struct zd1201 *zd = urb->context;
+	int free = 0;
+	unsigned char *data = urb->transfer_buffer;
+	struct sk_buff *skb;
+	unsigned char type;
+
+	if (!zd) {
+		free = 1;
+		goto exit;
+	}
+
+	switch(urb->status) {
+		case -EILSEQ:
+		case -ENODEV:
+		case -ETIMEDOUT:
+		case -ENOENT:
+		case -EPIPE:
+		case -EOVERFLOW:
+		case -ESHUTDOWN:
+			dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n",
+			    zd->dev->name, urb->status);
+			free = 1;
+			goto exit;
+	}
+	
+	if (urb->status != 0 || urb->actual_length == 0)
+		goto resubmit;
+
+	type = data[0];
+	if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) {
+		memcpy(zd->rxdata, data, urb->actual_length);
+		zd->rxlen = urb->actual_length;
+		zd->rxdatas = 1;
+		wake_up(&zd->rxdataq);
+	}
+	/* Info frame */
+	if (type == ZD1201_PACKET_INQUIRE) {
+		int i = 0;
+		unsigned short infotype, framelen, copylen;
+		framelen = le16_to_cpu(*(__le16*)&data[4]);
+		infotype = le16_to_cpu(*(__le16*)&data[6]);
+
+		if (infotype == ZD1201_INF_LINKSTATUS) {
+			short linkstatus;
+
+			linkstatus = le16_to_cpu(*(__le16*)&data[8]);
+			switch(linkstatus) {
+				case 1:
+					netif_carrier_on(zd->dev);
+					break;
+				case 2:
+					netif_carrier_off(zd->dev);
+					break;
+				case 3:
+					netif_carrier_off(zd->dev);
+					break;
+				case 4:
+					netif_carrier_on(zd->dev);
+					break;
+				default:
+					netif_carrier_off(zd->dev);
+			}
+			goto resubmit;
+		}
+		if (infotype == ZD1201_INF_ASSOCSTATUS) {
+			short status = le16_to_cpu(*(__le16*)(data+8));
+			int event;
+			union iwreq_data wrqu;
+
+			switch (status) {
+				case ZD1201_ASSOCSTATUS_STAASSOC:
+				case ZD1201_ASSOCSTATUS_REASSOC:
+					event = IWEVREGISTERED;
+					break;
+				case ZD1201_ASSOCSTATUS_DISASSOC:
+				case ZD1201_ASSOCSTATUS_ASSOCFAIL:
+				case ZD1201_ASSOCSTATUS_AUTHFAIL:
+				default:
+					event = IWEVEXPIRED;
+			}
+			memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN);
+			wrqu.addr.sa_family = ARPHRD_ETHER;
+
+			/* Send event to user space */
+			wireless_send_event(zd->dev, event, &wrqu, NULL);
+
+			goto resubmit;
+		}
+		if (infotype == ZD1201_INF_AUTHREQ) {
+			union iwreq_data wrqu;
+
+			memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN);
+			wrqu.addr.sa_family = ARPHRD_ETHER;
+			/* There isn't a event that trully fits this request.
+			   We assume that userspace will be smart enough to
+			   see a new station being expired and sends back a
+			   authstation ioctl to authorize it. */
+			wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL);
+			goto resubmit;
+		}
+		/* Other infotypes are handled outside this handler */
+		zd->rxlen = 0;
+		while (i < urb->actual_length) {
+			copylen = le16_to_cpu(*(__le16*)&data[i+2]);
+			/* Sanity check, sometimes we get junk */
+			if (copylen+zd->rxlen > sizeof(zd->rxdata))
+				break;
+			memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen);
+			zd->rxlen += copylen;
+			i += 64;
+		}
+		if (i >= urb->actual_length) {
+			zd->rxdatas = 1;
+			wake_up(&zd->rxdataq);
+		}
+		goto  resubmit;
+	}
+	/* Actual data */
+	if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) {
+		int datalen = urb->actual_length-1;
+		unsigned short len, fc, seq;
+		struct hlist_node *node;
+
+		len = ntohs(*(__be16 *)&data[datalen-2]);
+		if (len>datalen)
+			len=datalen;
+		fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
+		seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
+
+		if (zd->monitor) {
+			if (datalen < 24)
+				goto resubmit;
+			if (!(skb = dev_alloc_skb(datalen+24)))
+				goto resubmit;
+			
+			memcpy(skb_put(skb, 2), &data[datalen-16], 2);
+			memcpy(skb_put(skb, 2), &data[datalen-2], 2);
+			memcpy(skb_put(skb, 6), &data[datalen-14], 6);
+			memcpy(skb_put(skb, 6), &data[datalen-22], 6);
+			memcpy(skb_put(skb, 6), &data[datalen-8], 6);
+			memcpy(skb_put(skb, 2), &data[datalen-24], 2);
+			memcpy(skb_put(skb, len), data, len);
+			skb->dev = zd->dev;
+			skb->dev->last_rx = jiffies;
+			skb->protocol = eth_type_trans(skb, zd->dev);
+			zd->stats.rx_packets++;
+			zd->stats.rx_bytes += skb->len;
+			netif_rx(skb);
+			goto resubmit;
+		}
+			
+		if ((seq & IEEE80211_SCTL_FRAG) ||
+		    (fc & IEEE80211_FCTL_MOREFRAGS)) {
+			struct zd1201_frag *frag = NULL;
+			char *ptr;
+
+			if (datalen<14)
+				goto resubmit;
+			if ((seq & IEEE80211_SCTL_FRAG) == 0) {
+				frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
+				if (!frag)
+					goto resubmit;
+				skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
+				if (!skb) {
+					kfree(frag);
+					goto resubmit;
+				}
+				frag->skb = skb;
+				frag->seq = seq & IEEE80211_SCTL_SEQ;
+				skb_reserve(skb, 2);
+				memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+				memcpy(skb_put(skb, 2), &data[6], 2);
+				memcpy(skb_put(skb, len), data+8, len);
+				hlist_add_head(&frag->fnode, &zd->fraglist);
+				goto resubmit;
+			}
+			hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
+				if (frag->seq == (seq&IEEE80211_SCTL_SEQ))
+					break;
+			if (!frag)
+				goto resubmit;
+			skb = frag->skb;
+			ptr = skb_put(skb, len);
+			if (ptr)
+				memcpy(ptr, data+8, len);
+			if (fc & IEEE80211_FCTL_MOREFRAGS)
+				goto resubmit;
+			hlist_del_init(&frag->fnode);
+			kfree(frag);
+		} else {
+			if (datalen<14)
+				goto resubmit;
+			skb = dev_alloc_skb(len + 14 + 2);
+			if (!skb)
+				goto resubmit;
+			skb_reserve(skb, 2);
+			memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+			memcpy(skb_put(skb, 2), &data[6], 2);
+			memcpy(skb_put(skb, len), data+8, len);
+		}
+		skb->dev = zd->dev;
+		skb->dev->last_rx = jiffies;
+		skb->protocol = eth_type_trans(skb, zd->dev);
+		zd->stats.rx_packets++;
+		zd->stats.rx_bytes += skb->len;
+		netif_rx(skb);
+	}
+resubmit:
+	memset(data, 0, ZD1201_RXSIZE);
+
+	urb->status = 0;
+	urb->dev = zd->usb;
+	if(usb_submit_urb(urb, GFP_ATOMIC))
+		free = 1;
+
+exit:
+	if (free) {
+		zd->rxlen = 0;
+		zd->rxdatas = 1;
+		wake_up(&zd->rxdataq);
+		kfree(urb->transfer_buffer);
+	}
+	return;
+}
+
+static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
+	unsigned int riddatalen)
+{
+	int err;
+	int i = 0;
+	int code;
+	int rid_fid;
+	int length;
+	unsigned char *pdata;
+
+	zd->rxdatas = 0;
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
+	if (err)
+		return err;
+
+	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+	if (!zd->rxlen)
+		return -EIO;
+
+	code = le16_to_cpu(*(__le16*)(&zd->rxdata[4]));
+	rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6]));
+	length = le16_to_cpu(*(__le16*)(&zd->rxdata[8]));
+	if (length > zd->rxlen)
+		length = zd->rxlen-6;
+
+	/* If access bit is not on, then error */
+	if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid )
+		return -EINVAL;
+
+	/* Not enough buffer for allocating data */
+	if (riddatalen != (length - 4)) {
+		dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n",
+		    riddatalen, zd->rxlen, length, rid, rid_fid);
+		return -ENODATA;
+	}
+
+	zd->rxdatas = 0;
+	/* Issue SetRxRid commnd */			
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length);
+	if (err)
+		return err;
+
+	/* Receive RID record from resource packets */
+	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+	if (!zd->rxlen)
+		return -EIO;
+
+	if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) {
+		dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n",
+		    zd->rxdata[zd->rxlen-1]);
+		return -EINVAL;
+	}
+
+	/* Set the data pointer and received data length */
+	pdata = zd->rxdata;
+	length = zd->rxlen;
+
+	do {
+		int actual_length;
+
+		actual_length = (length > 64) ? 64 : length;
+
+		if (pdata[0] != 0x3) {
+			dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
+			    pdata[0]);
+			return -EINVAL;
+		}
+
+		if (actual_length != 64) {
+			/* Trim the last packet type byte */
+			actual_length--;
+		}
+
+		/* Skip the 4 bytes header (RID length and RID) */
+		if (i == 0) {
+			pdata += 8;
+			actual_length -= 8;
+		} else {
+			pdata += 4;
+			actual_length -= 4;
+		}
+		
+		memcpy(riddata, pdata, actual_length);
+		riddata += actual_length;
+		pdata += actual_length;
+		length -= 64;
+		i++;
+	} while (length > 0);
+
+	return 0;
+}
+
+/*
+ *	resreq:
+ *		byte	type
+ *		byte	sequence
+ *		u16	reserved
+ *		byte	data[12]
+ *	total: 16
+ */
+static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait)
+{
+	int err;
+	unsigned char *request;
+	int reqlen;
+	char seq=0;
+	struct urb *urb;
+	gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+
+	len += 4;			/* first 4 are for header */
+
+	zd->rxdatas = 0;
+	zd->rxlen = 0;
+	for (seq=0; len > 0; seq++) {
+		request = kmalloc(16, gfp_mask);
+		if (!request)
+			return -ENOMEM;
+		urb = usb_alloc_urb(0, gfp_mask);
+		if (!urb) {
+			kfree(request);
+			return -ENOMEM;
+		}
+		memset(request, 0, 16);
+		reqlen = len>12 ? 12 : len;
+		request[0] = ZD1201_USB_RESREQ;
+		request[1] = seq;
+		request[2] = 0;
+		request[3] = 0;
+		if (request[1] == 0) {
+			/* add header */
+			*(__le16*)&request[4] = cpu_to_le16((len-2+1)/2);
+			*(__le16*)&request[6] = cpu_to_le16(rid);
+			memcpy(request+8, buf, reqlen-4);
+			buf += reqlen-4;
+		} else {
+			memcpy(request+4, buf, reqlen);
+			buf += reqlen;
+		}
+
+		len -= reqlen;
+
+		usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb,
+		    zd->endp_out2), request, 16, zd1201_usbfree, zd);
+		err = usb_submit_urb(urb, gfp_mask);
+		if (err)
+			goto err;
+	}
+
+	request = kmalloc(16, gfp_mask);
+	if (!request)
+		return -ENOMEM;
+	urb = usb_alloc_urb(0, gfp_mask);
+	if (!urb) {
+		kfree(request);
+		return -ENOMEM;
+	}
+	*((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ);
+	*((__le16*)&request[4]) = 
+	    cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT);
+	*((__le16*)&request[6]) = cpu_to_le16(rid);
+	*((__le16*)&request[8]) = cpu_to_le16(0);
+	*((__le16*)&request[10]) = cpu_to_le16(0);
+	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+	     request, 16, zd1201_usbfree, zd);
+	err = usb_submit_urb(urb, gfp_mask);
+	if (err)
+		goto err;
+	
+	if (wait) {
+		wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+		if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) {
+			dev_dbg(&zd->usb->dev, "wrong or no RID received\n");
+		}
+	}
+
+	return 0;
+err:
+	kfree(request);
+	usb_free_urb(urb);
+	return err;
+}
+
+static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val)
+{
+	int err;
+	__le16 zdval;
+
+	err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16));
+	if (err)
+		return err;
+	*val = le16_to_cpu(zdval);
+	return 0;
+}
+
+static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val)
+{
+	__le16 zdval = cpu_to_le16(val);
+	return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1));
+}
+
+static int zd1201_drvr_start(struct zd1201 *zd)
+{
+	int err, i;
+	short max;
+	__le16 zdmax;
+	unsigned char *buffer;
+
+	buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	usb_fill_bulk_urb(zd->rx_urb, zd->usb, 
+	    usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE,
+	    zd1201_usbrx, zd);
+
+	err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
+	if (err)
+		goto err_buffer;
+
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+	if (err)
+		goto err_urb;
+
+	err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax,
+	    sizeof(__le16));
+	if (err)
+		goto err_urb;
+
+	max = le16_to_cpu(zdmax);
+	for (i=0; i<max; i++) {
+		err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0);
+		if (err)
+			goto err_urb;
+	}
+
+	return 0;
+
+err_urb:
+	usb_kill_urb(zd->rx_urb);
+	return err;
+err_buffer:
+	kfree(buffer);
+	return err;
+}
+
+/*	Magic alert: The firmware doesn't seem to like the MAC state being
+ *	toggled in promisc (aka monitor) mode.
+ *	(It works a number of times, but will halt eventually)
+ *	So we turn it of before disabling and on after enabling if needed.
+ */
+static int zd1201_enable(struct zd1201 *zd)
+{
+	int err;
+
+	if (zd->mac_enabled)
+		return 0;
+
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0);
+	if (!err)
+		zd->mac_enabled = 1;
+
+	if (zd->monitor)
+		err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1);
+
+	return err;
+}
+
+static int zd1201_disable(struct zd1201 *zd)
+{
+	int err;
+
+	if (!zd->mac_enabled)
+		return 0;
+	if (zd->monitor) {
+		err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+		if (err)
+			return err;
+	}
+
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0);
+	if (!err)
+		zd->mac_enabled = 0;
+	return err;
+}
+
+static int zd1201_mac_reset(struct zd1201 *zd)
+{
+	if (!zd->mac_enabled)
+		return 0;
+	zd1201_disable(zd);
+	return zd1201_enable(zd);
+}
+
+static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen)
+{
+	int err, val;
+	char buf[IW_ESSID_MAX_SIZE+2];
+
+	err = zd1201_disable(zd);
+	if (err)
+		return err;
+
+	val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+	val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val);
+	if (err)
+		return err;
+
+	*(__le16 *)buf = cpu_to_le16(essidlen);
+	memcpy(buf+2, essid, essidlen);
+	if (!zd->ap) {	/* Normal station */
+		err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+		    IW_ESSID_MAX_SIZE+2, 1);
+		if (err)
+			return err;
+	} else {	/* AP */
+		err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf,
+		    IW_ESSID_MAX_SIZE+2, 1);
+		if (err)
+			return err;
+	}
+
+	err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+	    zd->dev->dev_addr, zd->dev->addr_len, 1);
+	if (err)
+		return err;
+
+	err = zd1201_enable(zd);
+	if (err)
+		return err;
+
+	msleep(100);
+	return 0;
+}
+
+static int zd1201_net_open(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	/* Start MAC with wildcard if no essid set */
+	if (!zd->mac_enabled)
+		zd1201_join(zd, zd->essid, zd->essidlen);
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int zd1201_net_stop(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	return 0;
+}
+
+/*
+	RFC 1042 encapsulates Ethernet frames in 802.11 frames
+	by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0
+	(0x00, 0x00, 0x00). Zd requires an additional padding, copy
+	of ethernet addresses, length of the standard RFC 1042 packet
+	and a command byte (which is nul for tx).
+	
+	tx frame (from Wlan NG):
+	RFC 1042:
+		llc		0xAA 0xAA 0x03 (802.2 LLC)
+		snap		0x00 0x00 0x00 (Ethernet encapsulated)
+		type		2 bytes, Ethernet type field
+		payload		(minus eth header)
+	Zydas specific:
+		padding		1B if (skb->len+8+1)%64==0
+		Eth MAC addr	12 bytes, Ethernet MAC addresses
+		length		2 bytes, RFC 1042 packet length 
+				(llc+snap+type+payload)
+		zd		1 null byte, zd1201 packet type
+ */
+static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	unsigned char *txbuf = zd->txdata;
+	int txbuflen, pad = 0, err;
+	struct urb *urb = zd->tx_urb;
+
+	if (!zd->mac_enabled || zd->monitor) {
+		zd->stats.tx_dropped++;
+		kfree_skb(skb);
+		return 0;
+	}
+	netif_stop_queue(dev);
+
+	txbuflen = skb->len + 8 + 1;
+	if (txbuflen%64 == 0) {
+		pad = 1;
+		txbuflen++;
+	}
+	txbuf[0] = 0xAA;
+	txbuf[1] = 0xAA;
+	txbuf[2] = 0x03;
+	txbuf[3] = 0x00;	/* rfc1042 */
+	txbuf[4] = 0x00;
+	txbuf[5] = 0x00;
+
+	memcpy(txbuf+6, skb->data+12, skb->len-12);
+	if (pad)
+		txbuf[skb->len-12+6]=0;
+	memcpy(txbuf+skb->len-12+6+pad, skb->data, 12);
+	*(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6);
+	txbuf[txbuflen-1] = 0;
+
+	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out),
+	    txbuf, txbuflen, zd1201_usbtx, zd);
+
+	err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC);
+	if (err) {
+		zd->stats.tx_errors++;
+		netif_start_queue(dev);
+		return err;
+	}
+	zd->stats.tx_packets++;
+	zd->stats.tx_bytes += skb->len;
+	dev->trans_start = jiffies;
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static void zd1201_tx_timeout(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	if (!zd)
+		return;
+	dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
+	    dev->name);
+	usb_unlink_urb(zd->tx_urb);
+	zd->stats.tx_errors++;
+	/* Restart the timeout to quiet the watchdog: */
+	dev->trans_start = jiffies;
+}
+
+static int zd1201_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+
+	if (!zd)
+		return -ENODEV;
+
+	err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+	    addr->sa_data, dev->addr_len, 1);
+	if (err)
+		return err;
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	return zd1201_mac_reset(zd);
+}
+
+static struct net_device_stats *zd1201_get_stats(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	return &zd->stats;
+}
+
+static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	return &zd->iwstats;
+}
+
+static void zd1201_set_multicast(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	struct dev_mc_list *mc = dev->mc_list;
+	unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI];
+	int i;
+
+	if (dev->mc_count > ZD1201_MAXMULTI)
+		return;
+
+	for (i=0; i<dev->mc_count; i++) {
+		memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN);
+		mc = mc->next;
+	}
+	zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf,
+	    dev->mc_count*ETH_ALEN, 0);
+	
+}
+
+static int zd1201_config_commit(struct net_device *dev, 
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_name(struct net_device *dev,
+    struct iw_request_info *info, char *name, char *extra)
+{
+	strcpy(name, "IEEE 802.11b");
+	return 0;
+}
+
+static int zd1201_set_freq(struct net_device *dev,
+    struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short channel = 0;
+	int err;
+
+	if (freq->e == 0)
+		channel = freq->m;
+	else {
+		if (freq->m >= 2482)
+			channel = 14;
+		if (freq->m >= 2407)
+			channel = (freq->m-2407)/5;
+	}
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
+	if (err)
+		return err;
+
+	zd1201_mac_reset(zd);
+
+	return 0;
+}
+
+static int zd1201_get_freq(struct net_device *dev,
+    struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short channel;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel);
+	if (err)
+		return err;
+	freq->e = 0;
+	freq->m = channel;
+
+	return 0;
+}
+
+static int zd1201_set_mode(struct net_device *dev,
+    struct iw_request_info *info, __u32 *mode, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short porttype, monitor = 0;
+	unsigned char buffer[IW_ESSID_MAX_SIZE+2];
+	int err;
+
+	if (zd->ap) {
+		if (*mode != IW_MODE_MASTER)
+			return -EINVAL;
+		return 0;
+	}
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+	if (err)
+		return err;
+	zd->dev->type = ARPHRD_ETHER;
+	switch(*mode) {
+		case IW_MODE_MONITOR:
+			monitor = 1;
+			zd->dev->type = ARPHRD_IEEE80211;
+			/* Make sure we are no longer associated with by
+			   setting an 'impossible' essid.
+			   (otherwise we mess up firmware)
+			 */
+			zd1201_join(zd, "\0-*#\0", 5);
+			/* Put port in pIBSS */
+		case 8: /* No pseudo-IBSS in wireless extensions (yet) */
+			porttype = ZD1201_PORTTYPE_PSEUDOIBSS;
+			break;
+		case IW_MODE_ADHOC:
+			porttype = ZD1201_PORTTYPE_IBSS;
+			break;
+		case IW_MODE_INFRA:
+			porttype = ZD1201_PORTTYPE_BSS;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+	if (err)
+		return err;
+	if (zd->monitor && !monitor) {
+			zd1201_disable(zd);
+			*(__le16 *)buffer = cpu_to_le16(zd->essidlen);
+			memcpy(buffer+2, zd->essid, zd->essidlen);
+			err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID,
+			    buffer, IW_ESSID_MAX_SIZE+2, 1);
+			if (err)
+				return err;
+	}
+	zd->monitor = monitor;
+	/* If monitor mode is set we don't actually turn it on here since it
+	 * is done during mac reset anyway (see zd1201_mac_enable).
+	 */
+	zd1201_mac_reset(zd);
+
+	return 0;
+}
+
+static int zd1201_get_mode(struct net_device *dev,
+    struct iw_request_info *info, __u32 *mode, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short porttype;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype);
+	if (err)
+		return err;
+	switch(porttype) {
+		case ZD1201_PORTTYPE_IBSS:
+			*mode = IW_MODE_ADHOC;
+			break;
+		case ZD1201_PORTTYPE_BSS:
+			*mode = IW_MODE_INFRA;
+			break;
+		case ZD1201_PORTTYPE_WDS:
+			*mode = IW_MODE_REPEAT;
+			break;
+		case ZD1201_PORTTYPE_PSEUDOIBSS:
+			*mode = 8;/* No Pseudo-IBSS... */
+			break;
+		case ZD1201_PORTTYPE_AP:
+			*mode = IW_MODE_MASTER;
+			break;
+		default:
+			dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n",
+			    porttype);
+			*mode = IW_MODE_AUTO;
+	}
+	if (zd->monitor)
+		*mode = IW_MODE_MONITOR;
+
+	return 0;
+}
+
+static int zd1201_get_range(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *wrq, char *extra)
+{
+	struct iw_range *range = (struct iw_range *)extra;
+
+	wrq->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(struct iw_range));
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = WIRELESS_EXT;
+
+	range->max_qual.qual = 128;
+	range->max_qual.level = 128;
+	range->max_qual.noise = 128;
+	range->max_qual.updated = 7;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = ZD1201_NUMKEYS;
+
+	range->num_bitrates = 4;
+	range->bitrate[0] = 1000000;
+	range->bitrate[1] = 2000000;
+	range->bitrate[2] = 5500000;
+	range->bitrate[3] = 11000000;
+
+	range->min_rts = 0;
+	range->min_frag = ZD1201_FRAGMIN;
+	range->max_rts = ZD1201_RTSMAX;
+	range->min_frag = ZD1201_FRAGMAX;
+
+	return 0;
+}
+
+/*	Little bit of magic here: we only get the quality if we poll
+ *	for it, and we never get an actual request to trigger such
+ *	a poll. Therefore we 'assume' that the user will soon ask for
+ *	the stats after asking the bssid.
+ */
+static int zd1201_get_wap(struct net_device *dev,
+    struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	unsigned char buffer[6];
+
+	if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) {
+		/* Unfortunately the quality and noise reported is useless.
+		   they seem to be accumulators that increase until you
+		   read them, unless we poll on a fixed interval we can't
+		   use them
+		 */
+		/*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/
+		zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]);
+		/*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/
+		zd->iwstats.qual.updated = 2;
+	}
+
+	return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6);
+}
+
+static int zd1201_set_scan(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+	/* We do everything in get_scan */
+	return 0;
+}
+
+static int zd1201_get_scan(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err, i, j, enabled_save;
+	struct iw_event iwe;
+	char *cev = extra;
+	char *end_buf = extra + IW_SCAN_MAX_DATA;
+
+	/* No scanning in AP mode */
+	if (zd->ap)
+		return -EOPNOTSUPP;
+
+	/* Scan doesn't seem to work if disabled */
+	enabled_save = zd->mac_enabled;
+	zd1201_enable(zd);
+
+	zd->rxdatas = 0;
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, 
+	     ZD1201_INQ_SCANRESULTS, 0, 0);
+	if (err)
+		return err;
+
+	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+	if (!zd->rxlen)
+		return -EIO;
+
+	if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS)
+		return -EIO;
+
+	for(i=8; i<zd->rxlen; i+=62) {
+		iwe.cmd = SIOCGIWAP;
+		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+		memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6);
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+		iwe.cmd = SIOCGIWESSID;
+		iwe.u.data.length = zd->rxdata[i+16];
+		iwe.u.data.flags = 1;
+		cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18);
+
+		iwe.cmd = SIOCGIWMODE;
+		if (zd->rxdata[i+14]&0x01)
+			iwe.u.mode = IW_MODE_MASTER;
+		else
+			iwe.u.mode = IW_MODE_ADHOC;
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+		
+		iwe.cmd = SIOCGIWFREQ;
+		iwe.u.freq.m = zd->rxdata[i+0];
+		iwe.u.freq.e = 0;
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+		
+		iwe.cmd = SIOCGIWRATE;
+		iwe.u.bitrate.fixed = 0;
+		iwe.u.bitrate.disabled = 0;
+		for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) {
+			iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000;
+			cev=iwe_stream_add_event(cev, end_buf, &iwe,
+			    IW_EV_PARAM_LEN);
+		}
+		
+		iwe.cmd = SIOCGIWENCODE;
+		iwe.u.data.length = 0;
+		if (zd->rxdata[i+14]&0x10)
+			iwe.u.data.flags = IW_ENCODE_ENABLED;
+		else
+			iwe.u.data.flags = IW_ENCODE_DISABLED;
+		cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
+		
+		iwe.cmd = IWEVQUAL;
+		iwe.u.qual.qual = zd->rxdata[i+4];
+		iwe.u.qual.noise= zd->rxdata[i+2]/10-100;
+		iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100;
+		iwe.u.qual.updated = 7;
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+	}
+
+	if (!enabled_save)
+		zd1201_disable(zd);
+
+	srq->length = cev - extra;
+	srq->flags = 0;
+
+	return 0;
+}
+
+static int zd1201_set_essid(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	if (data->length > IW_ESSID_MAX_SIZE)
+		return -EINVAL;
+	if (data->length < 1)
+		data->length = 1;
+	zd->essidlen = data->length-1;
+	memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
+	memcpy(zd->essid, essid, data->length);
+	return zd1201_join(zd, zd->essid, zd->essidlen);
+}
+
+static int zd1201_get_essid(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	memcpy(essid, zd->essid, zd->essidlen);
+	data->flags = 1;
+	data->length = zd->essidlen;
+
+	return 0;
+}
+
+static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info,
+    struct iw_point *data, char *nick)
+{
+	strcpy(nick, "zd1201");
+	data->flags = 1;
+	data->length = strlen(nick);
+	return 0;
+}
+
+static int zd1201_set_rate(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short rate;
+	int err;
+
+	switch (rrq->value) {
+		case 1000000:
+			rate = ZD1201_RATEB1;
+			break;
+		case 2000000:
+			rate = ZD1201_RATEB2;
+			break;
+		case 5500000:
+			rate = ZD1201_RATEB5;
+			break;
+		case 11000000:
+		default:
+			rate = ZD1201_RATEB11;
+			break;
+	}
+	if (!rrq->fixed) { /* Also enable all lower bitrates */
+		rate |= rate-1;
+	}
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
+	if (err)
+		return err;
+
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rate(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short rate;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate);
+	if (err)
+		return err;
+
+	switch(rate) {
+		case 1:
+			rrq->value = 1000000;
+			break;
+		case 2:
+			rrq->value = 2000000;
+			break;
+		case 5:
+			rrq->value = 5500000;
+			break;
+		case 11:
+			rrq->value = 11000000;
+			break;
+		default:
+			rrq->value = 0;
+	}
+	rrq->fixed = 0;
+	rrq->disabled = 0;
+
+	return 0;
+}
+
+static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *rts, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+	short val = rts->value;
+
+	if (rts->disabled || !rts->fixed)
+		val = ZD1201_RTSMAX;
+	if (val > ZD1201_RTSMAX)
+		return -EINVAL;
+	if (val < 0)
+		return -EINVAL;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val);
+	if (err)
+		return err;
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *rts, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short rtst;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst);
+	if (err)
+		return err;
+	rts->value = rtst;
+	rts->disabled = (rts->value == ZD1201_RTSMAX);
+	rts->fixed = 1;
+
+	return 0;
+}
+
+static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *frag, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+	short val = frag->value;
+
+	if (frag->disabled || !frag->fixed)
+		val = ZD1201_FRAGMAX;
+	if (val > ZD1201_FRAGMAX)
+		return -EINVAL;
+	if (val < ZD1201_FRAGMIN)
+		return -EINVAL;
+	if (val & 1)
+		return -EINVAL;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val);
+	if (err)
+		return err;
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *frag, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short fragt;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt);
+	if (err)
+		return err;
+	frag->value = fragt;
+	frag->disabled = (frag->value == ZD1201_FRAGMAX);
+	frag->fixed = 1;
+
+	return 0;
+}
+
+static int zd1201_set_retry(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	return 0;
+}
+
+static int zd1201_get_retry(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	return 0;
+}
+
+static int zd1201_set_encode(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short i;
+	int err, rid;
+
+	if (erq->length > ZD1201_MAXKEYLEN)
+		return -EINVAL;
+
+	i = (erq->flags & IW_ENCODE_INDEX)-1;
+	if (i == -1) {
+		err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i);
+		if (err)
+			return err;
+	} else {
+		err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i);
+		if (err)
+			return err;
+	}
+
+	if (i < 0 || i >= ZD1201_NUMKEYS)
+		return -EINVAL;
+
+	rid = ZD1201_RID_CNFDEFAULTKEY0 + i;
+	err = zd1201_setconfig(zd, rid, key, erq->length, 1);
+	if (err)
+		return err;
+	zd->encode_keylen[i] = erq->length;
+	memcpy(zd->encode_keys[i], key, erq->length);
+
+	i=0;
+	if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) {
+		i |= 0x01;
+		zd->encode_enabled = 1;
+	} else
+		zd->encode_enabled = 0;
+	if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) {
+		i |= 0x02;
+		zd->encode_restricted = 1;
+	} else
+		zd->encode_restricted = 0;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i);
+	if (err)
+		return err;
+
+	if (zd->encode_enabled)
+		i = ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+	else
+		i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i);
+	if (err)
+		return err;
+
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_encode(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short i;
+	int err;
+
+	if (zd->encode_enabled)
+		erq->flags = IW_ENCODE_ENABLED;
+	else
+		erq->flags = IW_ENCODE_DISABLED;
+	if (zd->encode_restricted)
+		erq->flags |= IW_ENCODE_RESTRICTED;
+	else
+		erq->flags |= IW_ENCODE_OPEN;
+
+	i = (erq->flags & IW_ENCODE_INDEX) -1;
+	if (i == -1) {
+		err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i);
+		if (err)
+			return err;
+	}
+	if (i<0 || i>= ZD1201_NUMKEYS)
+		return -EINVAL;
+
+	erq->flags |= i+1;
+
+	erq->length = zd->encode_keylen[i];
+	memcpy(key, zd->encode_keys[i], erq->length);
+
+	return 0;
+}
+
+static int zd1201_set_power(struct net_device *dev, 
+    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short enabled, duration, level;
+	int err;
+
+	enabled = vwrq->disabled ? 0 : 1;
+	if (enabled) {
+		if (vwrq->flags & IW_POWER_PERIOD) {
+			duration = vwrq->value;
+			err = zd1201_setconfig16(zd, 
+			    ZD1201_RID_CNFMAXSLEEPDURATION, duration);
+			if (err)
+				return err;
+			goto out;
+		}
+		if (vwrq->flags & IW_POWER_TIMEOUT) {
+			err = zd1201_getconfig16(zd, 
+			    ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+			if (err)
+				return err;
+			level = vwrq->value * 4 / duration;
+			if (level > 4)
+				level = 4;
+			if (level < 0)
+				level = 0;
+			err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS,
+			    level);
+			if (err)
+				return err;
+			goto out;
+		}
+		return -EINVAL;
+	}
+out:
+	return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
+}
+
+static int zd1201_get_power(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short enabled, level, duration;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled);
+	if (err)
+		return err;
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level);
+	if (err)
+		return err;
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+	if (err)
+		return err;
+	vwrq->disabled = enabled ? 0 : 1;
+	if (vwrq->flags & IW_POWER_TYPE) {
+		if (vwrq->flags & IW_POWER_PERIOD) {
+			vwrq->value = duration;
+			vwrq->flags = IW_POWER_PERIOD;
+		} else {
+			vwrq->value = duration * level / 4;
+			vwrq->flags = IW_POWER_TIMEOUT;
+		}
+	}
+	if (vwrq->flags & IW_POWER_MODE) {
+		if (enabled && level)
+			vwrq->flags = IW_POWER_UNICAST_R;
+		else
+			vwrq->flags = IW_POWER_ALL_R;
+	}
+
+	return 0;
+}
+
+
+static const iw_handler zd1201_iw_handler[] =
+{
+	(iw_handler) zd1201_config_commit,	/* SIOCSIWCOMMIT */
+	(iw_handler) zd1201_get_name,    	/* SIOCGIWNAME */
+	(iw_handler) NULL,			/* SIOCSIWNWID */
+	(iw_handler) NULL,			/* SIOCGIWNWID */
+	(iw_handler) zd1201_set_freq,		/* SIOCSIWFREQ */
+	(iw_handler) zd1201_get_freq,		/* SIOCGIWFREQ */
+	(iw_handler) zd1201_set_mode,		/* SIOCSIWMODE */
+	(iw_handler) zd1201_get_mode,		/* SIOCGIWMODE */
+	(iw_handler) NULL,                  	/* SIOCSIWSENS */
+	(iw_handler) NULL,           		/* SIOCGIWSENS */
+	(iw_handler) NULL,			/* SIOCSIWRANGE */
+	(iw_handler) zd1201_get_range,           /* SIOCGIWRANGE */
+	(iw_handler) NULL,			/* SIOCSIWPRIV */
+	(iw_handler) NULL,			/* SIOCGIWPRIV */
+	(iw_handler) NULL,			/* SIOCSIWSTATS */
+	(iw_handler) NULL,			/* SIOCGIWSTATS */
+	(iw_handler) NULL,			/* SIOCSIWSPY */
+	(iw_handler) NULL,			/* SIOCGIWSPY */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL/*zd1201_set_wap*/,		/* SIOCSIWAP */
+	(iw_handler) zd1201_get_wap,		/* SIOCGIWAP */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,       		/* SIOCGIWAPLIST */
+	(iw_handler) zd1201_set_scan,		/* SIOCSIWSCAN */
+	(iw_handler) zd1201_get_scan,		/* SIOCGIWSCAN */
+	(iw_handler) zd1201_set_essid,		/* SIOCSIWESSID */
+	(iw_handler) zd1201_get_essid,		/* SIOCGIWESSID */
+	(iw_handler) NULL,         		/* SIOCSIWNICKN */
+	(iw_handler) zd1201_get_nick, 		/* SIOCGIWNICKN */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) zd1201_set_rate,		/* SIOCSIWRATE */
+	(iw_handler) zd1201_get_rate,		/* SIOCGIWRATE */
+	(iw_handler) zd1201_set_rts,		/* SIOCSIWRTS */
+	(iw_handler) zd1201_get_rts,		/* SIOCGIWRTS */
+	(iw_handler) zd1201_set_frag,		/* SIOCSIWFRAG */
+	(iw_handler) zd1201_get_frag,		/* SIOCGIWFRAG */
+	(iw_handler) NULL,         		/* SIOCSIWTXPOW */
+	(iw_handler) NULL,          		/* SIOCGIWTXPOW */
+	(iw_handler) zd1201_set_retry,		/* SIOCSIWRETRY */
+	(iw_handler) zd1201_get_retry,		/* SIOCGIWRETRY */
+	(iw_handler) zd1201_set_encode,		/* SIOCSIWENCODE */
+	(iw_handler) zd1201_get_encode,		/* SIOCGIWENCODE */
+	(iw_handler) zd1201_set_power,		/* SIOCSIWPOWER */
+	(iw_handler) zd1201_get_power,		/* SIOCGIWPOWER */
+};
+
+static int zd1201_set_hostauth(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
+}
+
+static int zd1201_get_hostauth(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short hostauth;
+	int err;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth);
+	if (err)
+		return err;
+	rrq->value = hostauth;
+	rrq->fixed = 1;
+
+	return 0;
+}
+
+static int zd1201_auth_sta(struct net_device *dev,
+    struct iw_request_info *info, struct sockaddr *sta, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	unsigned char buffer[10];
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	memcpy(buffer, sta->sa_data, ETH_ALEN);
+	*(short*)(buffer+6) = 0;	/* 0==success, 1==failure */
+	*(short*)(buffer+8) = 0;
+
+	return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1);
+}
+
+static int zd1201_set_maxassoc(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int zd1201_get_maxassoc(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short maxassoc;
+	int err;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc);
+	if (err)
+		return err;
+	rrq->value = maxassoc;
+	rrq->fixed = 1;
+
+	return 0;
+}
+
+static const iw_handler zd1201_private_handler[] = {
+	(iw_handler) zd1201_set_hostauth,	/* ZD1201SIWHOSTAUTH */
+	(iw_handler) zd1201_get_hostauth,	/* ZD1201GIWHOSTAUTH */
+	(iw_handler) zd1201_auth_sta,		/* ZD1201SIWAUTHSTA */
+	(iw_handler) NULL,			/* nothing to get */
+	(iw_handler) zd1201_set_maxassoc,	/* ZD1201SIMAXASSOC */
+	(iw_handler) zd1201_get_maxassoc,	/* ZD1201GIMAXASSOC */
+};
+
+static const struct iw_priv_args zd1201_private_args[] = {
+	{ ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	    IW_PRIV_TYPE_NONE, "sethostauth" },
+	{ ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE,
+	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" },
+	{ ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1,
+	    IW_PRIV_TYPE_NONE, "authstation" },
+	{ ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	    IW_PRIV_TYPE_NONE, "setmaxassoc" },
+	{ ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE,
+	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" },
+};
+
+static const struct iw_handler_def zd1201_iw_handlers = {
+	.num_standard 		= ARRAY_SIZE(zd1201_iw_handler),
+	.num_private 		= ARRAY_SIZE(zd1201_private_handler),
+	.num_private_args 	= ARRAY_SIZE(zd1201_private_args),
+	.standard 		= (iw_handler *)zd1201_iw_handler,
+	.private 		= (iw_handler *)zd1201_private_handler,
+	.private_args 		= (struct iw_priv_args *) zd1201_private_args,
+	.get_wireless_stats	= zd1201_get_wireless_stats,
+};
+
+static int zd1201_probe(struct usb_interface *interface,
+			const struct usb_device_id *id)
+{
+	struct zd1201 *zd;
+	struct usb_device *usb;
+	int err;
+	short porttype;
+	char buf[IW_ESSID_MAX_SIZE+2];
+
+	usb = interface_to_usbdev(interface);
+
+	zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL);
+	if (!zd)
+		return -ENOMEM;
+	zd->ap = ap;
+	zd->usb = usb;
+	zd->removed = 0;
+	init_waitqueue_head(&zd->rxdataq);
+	INIT_HLIST_HEAD(&zd->fraglist);
+	
+	err = zd1201_fw_upload(usb, zd->ap);
+	if (err) {
+		dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err);
+		goto err_zd;
+	}
+	
+	zd->endp_in = 1;
+	zd->endp_out = 1;
+	zd->endp_out2 = 2;
+	zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!zd->rx_urb || !zd->tx_urb)
+		goto err_zd;
+
+	mdelay(100);
+	err = zd1201_drvr_start(zd);
+	if (err)
+		goto err_zd;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312);
+	if (err)
+		goto err_start;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL,
+	    ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11);
+	if (err)
+		goto err_start;
+
+	zd->dev = alloc_etherdev(0);
+	if (!zd->dev)
+		goto err_start;
+
+	zd->dev->priv = zd;
+	zd->dev->open = zd1201_net_open;
+	zd->dev->stop = zd1201_net_stop;
+	zd->dev->get_stats = zd1201_get_stats;
+	zd->dev->wireless_handlers =
+	    (struct iw_handler_def *)&zd1201_iw_handlers;
+	zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
+	zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT;
+	zd->dev->tx_timeout = zd1201_tx_timeout;
+	zd->dev->set_multicast_list = zd1201_set_multicast;
+	zd->dev->set_mac_address = zd1201_set_mac_address;
+	strcpy(zd->dev->name, "wlan%d");
+
+	err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+	    zd->dev->dev_addr, zd->dev->addr_len);
+	if (err)
+		goto err_net;
+
+	/* Set wildcard essid to match zd->essid */
+	*(__le16 *)buf = cpu_to_le16(0);
+	err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+	    IW_ESSID_MAX_SIZE+2, 1);
+	if (err)
+		goto err_net;
+
+	if (zd->ap)
+		porttype = ZD1201_PORTTYPE_AP;
+	else
+		porttype = ZD1201_PORTTYPE_BSS;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+	if (err)
+		goto err_net;
+
+	SET_NETDEV_DEV(zd->dev, &usb->dev);
+
+	err = register_netdev(zd->dev);
+	if (err)
+		goto err_net;
+	dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
+	    zd->dev->name);
+
+	usb_set_intfdata(interface, zd);
+	return 0;
+
+err_net:
+	free_netdev(zd->dev);
+err_start:
+	/* Leave the device in reset state */
+	zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+err_zd:
+	if (zd->tx_urb)
+		usb_free_urb(zd->tx_urb);
+	if (zd->rx_urb)
+		usb_free_urb(zd->rx_urb);
+	kfree(zd);
+	return err;
+}
+
+static void zd1201_disconnect(struct usb_interface *interface)
+{
+	struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface);
+	struct hlist_node *node, *node2;
+	struct zd1201_frag *frag;
+
+	if (!zd)
+		return;
+	usb_set_intfdata(interface, NULL);
+	if (zd->dev) {
+		unregister_netdev(zd->dev);
+		free_netdev(zd->dev);
+	}
+
+	hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) {
+		hlist_del_init(&frag->fnode);
+		kfree_skb(frag->skb);
+		kfree(frag);
+	}
+
+	if (zd->tx_urb) {
+		usb_kill_urb(zd->tx_urb);
+		usb_free_urb(zd->tx_urb);
+	}
+	if (zd->rx_urb) {
+		usb_kill_urb(zd->rx_urb);
+		usb_free_urb(zd->rx_urb);
+	}
+	kfree(zd);
+}
+
+#ifdef CONFIG_PM
+
+static int zd1201_suspend(struct usb_interface *interface,
+			   pm_message_t message)
+{
+	struct zd1201 *zd = usb_get_intfdata(interface);
+
+	netif_device_detach(zd->dev);
+
+	zd->was_enabled = zd->mac_enabled;
+
+	if (zd->was_enabled)
+		return zd1201_disable(zd);
+	else
+		return 0;
+}
+
+static int zd1201_resume(struct usb_interface *interface)
+{
+	struct zd1201 *zd = usb_get_intfdata(interface);
+
+	if (!zd || !zd->dev)
+		return -ENODEV;
+
+	netif_device_attach(zd->dev);
+
+	if (zd->was_enabled)
+		return zd1201_enable(zd);
+	else
+		return 0;
+}
+
+#else
+
+#define zd1201_suspend NULL
+#define zd1201_resume  NULL
+
+#endif
+
+static struct usb_driver zd1201_usb = {
+	.name = "zd1201",
+	.probe = zd1201_probe,
+	.disconnect = zd1201_disconnect,
+	.id_table = zd1201_table,
+	.suspend = zd1201_suspend,
+	.resume = zd1201_resume,
+};
+
+static int __init zd1201_init(void)
+{
+	return usb_register(&zd1201_usb);
+}
+
+static void __exit zd1201_cleanup(void)
+{
+	usb_deregister(&zd1201_usb);
+}
+
+module_init(zd1201_init);
+module_exit(zd1201_cleanup);
diff --git a/drivers/usb/net/zd1201.h b/drivers/net/wireless/zd1201.h
similarity index 100%
rename from drivers/usb/net/zd1201.h
rename to drivers/net/wireless/zd1201.h
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index fd0f43b..569305f 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -234,14 +234,6 @@
 
 
 
-enum pci_id_flags_bits {
-	/* Set PCI command register bits before calling probe1(). */
-	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-	/* Read and map the single following PCI BAR. */
-	PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
-	PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
-	PCI_UNUSED_IRQ=0x800,
-};
 enum capability_flags {
 	HasMII=1, FullTxStatus=2, IsGigabit=4, HasMulticastBug=8, FullRxStatus=16,
 	HasMACAddrBug=32, /* Only on early revs.  */
@@ -249,11 +241,6 @@
 };
 /* The PCI I/O space extent. */
 #define YELLOWFIN_SIZE 0x100
-#ifdef USE_IO_OPS
-#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_IO  | PCI_ADDR0)
-#else
-#define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1)
-#endif
 
 struct pci_id_info {
         const char *name;
@@ -261,24 +248,23 @@
                 int     pci, pci_mask, subsystem, subsystem_mask;
                 int revision, revision_mask;                            /* Only 8 bits. */
         } id;
-        enum pci_id_flags_bits pci_flags;
         int io_size;                            /* Needed for I/O region check or ioremap(). */
         int drv_flags;                          /* Driver use, intended as capability flags. */
 };
 
 static const struct pci_id_info pci_id_tbl[] = {
 	{"Yellowfin G-NIC Gigabit Ethernet", { 0x07021000, 0xffffffff},
-	 PCI_IOTYPE, YELLOWFIN_SIZE,
+	 YELLOWFIN_SIZE,
 	 FullTxStatus | IsGigabit | HasMulticastBug | HasMACAddrBug | DontUseEeprom},
 	{"Symbios SYM83C885", { 0x07011000, 0xffffffff},
-	 PCI_IOTYPE, YELLOWFIN_SIZE, HasMII | DontUseEeprom },
-	{NULL,},
+	 YELLOWFIN_SIZE, HasMII | DontUseEeprom },
+	{ }
 };
 
-static struct pci_device_id yellowfin_pci_tbl[] = {
+static const struct pci_device_id yellowfin_pci_tbl[] = {
 	{ 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
-	{ 0, }
+	{ }
 };
 MODULE_DEVICE_TABLE (pci, yellowfin_pci_tbl);
 
@@ -862,13 +848,11 @@
 		/* Fix GX chipset errata. */
 		if (cacheline_end > 24  || cacheline_end == 0) {
 			len = skb->len + 32 - cacheline_end + 1;
-			if (len != skb->len)
-				skb = skb_padto(skb, len);
-		}
-		if (skb == NULL) {
-			yp->tx_skbuff[entry] = NULL;
-			netif_wake_queue(dev);
-			return 0;
+			if (skb_padto(skb, len)) {
+				yp->tx_skbuff[entry] = NULL;
+				netif_wake_queue(dev);
+				return 0;
+			}
 		}
 	}
 	yp->tx_skbuff[entry] = skb;
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index 3ac047b..a7c089d 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -544,8 +544,7 @@
 		printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name);
 
 	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
+		if (skb_padto(skb, ETH_ZLEN))
 			return 0;
 		length = ETH_ZLEN;
 	}
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index b2e8e49..43e521e 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -108,10 +108,10 @@
 		return 0;
 
 	/* FIXME: should we process all CPU buffers ? */
-	down(&buffer_sem);
+	mutex_lock(&buffer_mutex);
 	add_event_entry(ESCAPE_CODE);
 	add_event_entry(MODULE_LOADED_CODE);
-	up(&buffer_sem);
+	mutex_unlock(&buffer_mutex);
 #endif
 	return 0;
 }
@@ -501,7 +501,7 @@
 	sync_buffer_state state = sb_buffer_start;
 	unsigned long available;
 
-	down(&buffer_sem);
+	mutex_lock(&buffer_mutex);
  
 	add_cpu_switch(cpu);
 
@@ -550,5 +550,5 @@
 
 	mark_done(cpu);
 
-	up(&buffer_sem);
+	mutex_unlock(&buffer_mutex);
 }
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index b80318f..04d6417 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -24,7 +24,7 @@
 #include "event_buffer.h"
 #include "oprofile_stats.h"
 
-DECLARE_MUTEX(buffer_sem);
+DEFINE_MUTEX(buffer_mutex);
  
 static unsigned long buffer_opened;
 static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
@@ -32,7 +32,7 @@
 static unsigned long buffer_size;
 static unsigned long buffer_watershed;
 static size_t buffer_pos;
-/* atomic_t because wait_event checks it outside of buffer_sem */
+/* atomic_t because wait_event checks it outside of buffer_mutex */
 static atomic_t buffer_ready = ATOMIC_INIT(0);
 
 /* Add an entry to the event buffer. When we
@@ -60,10 +60,10 @@
  */
 void wake_up_buffer_waiter(void)
 {
-	down(&buffer_sem);
+	mutex_lock(&buffer_mutex);
 	atomic_set(&buffer_ready, 1);
 	wake_up(&buffer_wait);
-	up(&buffer_sem);
+	mutex_unlock(&buffer_mutex);
 }
 
  
@@ -162,7 +162,7 @@
 	if (!atomic_read(&buffer_ready))
 		return -EAGAIN;
 
-	down(&buffer_sem);
+	mutex_lock(&buffer_mutex);
 
 	atomic_set(&buffer_ready, 0);
 
@@ -177,7 +177,7 @@
 	buffer_pos = 0;
  
 out:
-	up(&buffer_sem);
+	mutex_unlock(&buffer_mutex);
 	return retval;
 }
  
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 0180236..9241627 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -11,7 +11,7 @@
 #define EVENT_BUFFER_H
 
 #include <linux/types.h> 
-#include <asm/semaphore.h>
+#include <asm/mutex.h>
  
 int alloc_event_buffer(void);
 
@@ -46,6 +46,6 @@
 /* mutex between sync_cpu_buffers() and the
  * file reading code.
  */
-extern struct semaphore buffer_sem;
+extern struct mutex buffer_mutex;
  
 #endif /* EVENT_BUFFER_H */
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
index b3f1cd6..e5162a6 100644
--- a/drivers/oprofile/oprof.c
+++ b/drivers/oprofile/oprof.c
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/oprofile.h>
 #include <linux/moduleparam.h>
-#include <asm/semaphore.h>
+#include <asm/mutex.h>
 
 #include "oprof.h"
 #include "event_buffer.h"
@@ -25,7 +25,7 @@
 unsigned long oprofile_started;
 unsigned long backtrace_depth;
 static unsigned long is_setup;
-static DECLARE_MUTEX(start_sem);
+static DEFINE_MUTEX(start_mutex);
 
 /* timer
    0 - use performance monitoring hardware if available
@@ -37,7 +37,7 @@
 {
 	int err;
  
-	down(&start_sem);
+	mutex_lock(&start_mutex);
 
 	if ((err = alloc_cpu_buffers()))
 		goto out;
@@ -57,7 +57,7 @@
 		goto out3;
 
 	is_setup = 1;
-	up(&start_sem);
+	mutex_unlock(&start_mutex);
 	return 0;
  
 out3:
@@ -68,7 +68,7 @@
 out1:
 	free_cpu_buffers();
 out:
-	up(&start_sem);
+	mutex_unlock(&start_mutex);
 	return err;
 }
 
@@ -78,7 +78,7 @@
 {
 	int err = -EINVAL;
  
-	down(&start_sem);
+	mutex_lock(&start_mutex);
  
 	if (!is_setup)
 		goto out;
@@ -95,7 +95,7 @@
 
 	oprofile_started = 1;
 out:
-	up(&start_sem); 
+	mutex_unlock(&start_mutex);
 	return err;
 }
 
@@ -103,7 +103,7 @@
 /* echo 0>/dev/oprofile/enable */
 void oprofile_stop(void)
 {
-	down(&start_sem);
+	mutex_lock(&start_mutex);
 	if (!oprofile_started)
 		goto out;
 	oprofile_ops.stop();
@@ -111,20 +111,20 @@
 	/* wake up the daemon to read what remains */
 	wake_up_buffer_waiter();
 out:
-	up(&start_sem);
+	mutex_unlock(&start_mutex);
 }
 
 
 void oprofile_shutdown(void)
 {
-	down(&start_sem);
+	mutex_lock(&start_mutex);
 	sync_stop();
 	if (oprofile_ops.shutdown)
 		oprofile_ops.shutdown();
 	is_setup = 0;
 	free_event_buffer();
 	free_cpu_buffers();
-	up(&start_sem);
+	mutex_unlock(&start_mutex);
 }
 
 
@@ -132,7 +132,7 @@
 {
 	int err = 0;
 
-	down(&start_sem);
+	mutex_lock(&start_mutex);
 
 	if (oprofile_started) {
 		err = -EBUSY;
@@ -147,7 +147,7 @@
 	backtrace_depth = val;
 
 out:
-	up(&start_sem);
+	mutex_unlock(&start_mutex);
 	return err;
 }
 
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index b62da9b..71c2da2 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -272,10 +272,10 @@
 }
 
 
-static struct super_block *oprofilefs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int oprofilefs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, oprofilefs_fill_super);
+	return get_sb_single(fs_type, flags, data, oprofilefs_fill_super, mnt);
 }
 
 
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index f63c387..c7fa28a 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -48,7 +48,7 @@
 
 config PARPORT_SERIAL
 	tristate "Multi-IO cards (parallel and serial)"
-	depends on SERIAL_8250 && PARPORT_PC && PCI
+	depends on SERIAL_8250_PCI && PARPORT_PC && PCI
 	help
 	  This adds support for multi-IO PCI cards that have parallel and
 	  serial ports.  You should say Y or M here.  If you say M, the module
@@ -85,11 +85,6 @@
 config PARPORT_NOT_PC
 	bool
 
-config PARPORT_ARC
-	tristate "Archimedes hardware"
-	depends on ARM && PARPORT
-	select PARPORT_NOT_PC
-
 config PARPORT_IP32
 	tristate "SGI IP32 builtin port (EXPERIMENTAL)"
 	depends on SGI_IP32 && PARPORT && EXPERIMENTAL
@@ -141,6 +136,18 @@
 	  found on many Sun machines. Note that many of the newer Ultras
 	  actually have pc style hardware instead.
 
+config PARPORT_AX88796
+	tristate "AX88796 Parallel Port"
+	depends on PARPORT
+	select PARPORT_NOT_PC
+	help
+	  Say Y here if you need support for the parallel port hardware on
+	  the AX88796 network controller chip. This code is also available
+	  as a module (say M), called parport_ax88796.
+
+	  The driver is not dependant on the AX88796 network driver, and
+	  should not interfere with the networking functions of the chip.
+
 config PARPORT_1284
 	bool "IEEE 1284 transfer modes"
 	depends on PARPORT
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile
index a19de35..696b8d4 100644
--- a/drivers/parport/Makefile
+++ b/drivers/parport/Makefile
@@ -17,4 +17,5 @@
 obj-$(CONFIG_PARPORT_ATARI)	+= parport_atari.o
 obj-$(CONFIG_PARPORT_SUNBPP)	+= parport_sunbpp.o
 obj-$(CONFIG_PARPORT_GSC)	+= parport_gsc.o
-obj-$(CONFIG_PARPORT_IP32)	+= parport_ip32.o
+obj-$(CONFIG_PARPORT_AX88796)	+= parport_ax88796.o
+obj-$(CONFIG_PARPORT_IP32)	+= parport_ip32.o
\ No newline at end of file
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 9ee6732..fd41e28 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -283,7 +283,7 @@
  *
  *	This tries to locate a device on the given parallel port,
  *	multiplexor port and daisy chain address, and returns its
- *	device number or -NXIO if no device with those coordinates
+ *	device number or %-ENXIO if no device with those coordinates
  *	exists.
  **/
 
diff --git a/drivers/parport/parport_arc.c b/drivers/parport/parport_arc.c
deleted file mode 100644
index b35bb4f..0000000
--- a/drivers/parport/parport_arc.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Low-level parallel port routines for Archimedes onboard hardware
- *
- * Author: Phil Blundell <philb@gnu.org>
- */
-
-/* This driver is for the parallel port hardware found on Acorn's old
- * range of Archimedes machines.  The A5000 and newer systems have PC-style
- * I/O hardware and should use the parport_pc driver instead.
- *
- * The Acorn printer port hardware is very simple.  There is a single 8-bit
- * write-only latch for the data port and control/status bits are handled
- * with various auxilliary input and output lines.  The port is not
- * bidirectional, does not support any modes other than SPP, and has only
- * a subset of the standard printer control lines connected.
- */
-
-#include <linux/threads.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/parport.h>
-
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/arch/oldlatches.h>
-#include <asm/arch/irqs.h>
-
-#define DATA_ADDRESS    0x3350010
-
-/* This is equivalent to the above and only used for request_region. */
-#define PORT_BASE       0x80000000 | ((DATA_ADDRESS - IO_BASE) >> 2)
-
-/* The hardware can't read from the data latch, so we must use a soft
-   copy. */
-static unsigned char data_copy;
-
-/* These are pretty simple. We know the irq is never shared and the
-   kernel does all the magic that's required. */
-static void arc_enable_irq(struct parport *p)
-{
-	enable_irq(p->irq);
-}
-
-static void arc_disable_irq(struct parport *p)
-{
-	disable_irq(p->irq);
-}
-
-static void arc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	parport_generic_irq(irq, (struct parport *) dev_id, regs);
-}
-
-static void arc_write_data(struct parport *p, unsigned char data)
-{
-	data_copy = data;
-	outb_t(data, DATA_LATCH);
-}
-
-static unsigned char arc_read_data(struct parport *p)
-{
-	return data_copy;
-}
-
-static struct parport_operations parport_arc_ops = 
-{
-	.write_data	= arc_write_data,
-	.read_data	= arc_read_data,
-
-	.write_control	= arc_write_control,
-	.read_control	= arc_read_control,
-	.frob_control	= arc_frob_control,
-
-	.read_status	= arc_read_status,
-
-	.enable_irq	= arc_enable_irq,
-	.disable_irq	= arc_disable_irq,
-
-	.data_forward	= arc_data_forward,
-	.data_reverse	= arc_data_reverse,
-
-	.init_state	= arc_init_state,
-	.save_state	= arc_save_state,
-	.restore_state	= arc_restore_state,
-
-	.epp_write_data	= parport_ieee1284_epp_write_data,
-	.epp_read_data	= parport_ieee1284_epp_read_data,
-	.epp_write_addr	= parport_ieee1284_epp_write_addr,
-	.epp_read_addr	= parport_ieee1284_epp_read_addr,
-
-	.ecp_write_data	= parport_ieee1284_ecp_write_data,
-	.ecp_read_data	= parport_ieee1284_ecp_read_data,
-	.ecp_write_addr	= parport_ieee1284_ecp_write_addr,
-	
-	.compat_write_data	= parport_ieee1284_write_compat,
-	.nibble_read_data	= parport_ieee1284_read_nibble,
-	.byte_read_data		= parport_ieee1284_read_byte,
-
-	.owner		= THIS_MODULE,
-};
-
-/* --- Initialisation code -------------------------------- */
-
-static int parport_arc_init(void)
-{
-	/* Archimedes hardware provides only one port, at a fixed address */
-	struct parport *p;
-	struct resource res;
-	char *fake_name = "parport probe");
-
-	res = request_region(PORT_BASE, 1, fake_name);
-	if (res == NULL)
-		return 0;
-
-	p = parport_register_port (PORT_BASE, IRQ_PRINTERACK,
-				   PARPORT_DMA_NONE, &parport_arc_ops);
-
-	if (!p) {
-		release_region(PORT_BASE, 1);
-		return 0;
-	}
-
-	p->modes = PARPORT_MODE_ARCSPP;
-	p->size = 1;
-	rename_region(res, p->name);
-
-	printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n",
-	       p->irq);
-
-	/* Tell the high-level drivers about the port. */
-	parport_announce_port (p);
-
-	return 1;
-}
-
-module_init(parport_arc_init)
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
new file mode 100644
index 0000000..4baa719
--- /dev/null
+++ b/drivers/parport/parport_ax88796.c
@@ -0,0 +1,443 @@
+/* linux/drivers/parport/parport_ax88796.c
+ *
+ * (c) 2005,2006 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/parport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define AX_SPR_BUSY		(1<<7)
+#define AX_SPR_ACK		(1<<6)
+#define AX_SPR_PE		(1<<5)
+#define AX_SPR_SLCT		(1<<4)
+#define AX_SPR_ERR		(1<<3)
+
+#define AX_CPR_nDOE		(1<<5)
+#define AX_CPR_SLCTIN		(1<<3)
+#define AX_CPR_nINIT		(1<<2)
+#define AX_CPR_ATFD		(1<<1)
+#define AX_CPR_STRB		(1<<0)
+
+struct ax_drvdata {
+	struct parport		*parport;
+	struct parport_state	 suspend;
+
+	struct device		*dev;
+	struct resource		*io;
+
+	unsigned char		 irq_enabled;
+
+	void __iomem		*base;
+	void __iomem		*spp_data;
+	void __iomem		*spp_spr;
+	void __iomem		*spp_cpr;
+};
+
+static inline struct ax_drvdata *pp_to_drv(struct parport *p)
+{
+	return p->private_data;
+}
+
+static unsigned char
+parport_ax88796_read_data(struct parport *p)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+
+	return readb(dd->spp_data);
+}
+
+static void
+parport_ax88796_write_data(struct parport *p, unsigned char data)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+
+	writeb(data, dd->spp_data);
+}
+
+static unsigned char
+parport_ax88796_read_control(struct parport *p)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	unsigned int cpr = readb(dd->spp_cpr);
+	unsigned int ret = 0;
+
+	if (!(cpr & AX_CPR_STRB))
+		ret |= PARPORT_CONTROL_STROBE;
+
+	if (!(cpr & AX_CPR_ATFD))
+		ret |= PARPORT_CONTROL_AUTOFD;
+
+	if (cpr & AX_CPR_nINIT)
+		ret |= PARPORT_CONTROL_INIT;
+
+	if (!(cpr & AX_CPR_SLCTIN))
+		ret |= PARPORT_CONTROL_SELECT;
+
+	return ret;
+}
+
+static void
+parport_ax88796_write_control(struct parport *p, unsigned char control)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	unsigned int cpr = readb(dd->spp_cpr);
+
+	cpr &= AX_CPR_nDOE;
+
+	if (!(control & PARPORT_CONTROL_STROBE))
+		cpr |= AX_CPR_STRB;
+
+	if (!(control & PARPORT_CONTROL_AUTOFD))
+		cpr |= AX_CPR_ATFD;
+
+	if (control & PARPORT_CONTROL_INIT)
+		cpr |= AX_CPR_nINIT;
+
+	if (!(control & PARPORT_CONTROL_SELECT))
+		cpr |= AX_CPR_SLCTIN;
+
+	dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr);
+	writeb(cpr, dd->spp_cpr);
+
+	if (parport_ax88796_read_control(p) != control) {
+		dev_err(dd->dev, "write_control: read != set (%02x, %02x)\n",
+			parport_ax88796_read_control(p), control);
+	}
+}
+
+static unsigned char
+parport_ax88796_read_status(struct parport *p)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	unsigned int status = readb(dd->spp_spr);
+	unsigned int ret = 0;
+
+	if (status & AX_SPR_BUSY)
+		ret |= PARPORT_STATUS_BUSY;
+
+	if (status & AX_SPR_ACK)
+		ret |= PARPORT_STATUS_ACK;
+
+	if (status & AX_SPR_ERR)
+		ret |= PARPORT_STATUS_ERROR;
+
+	if (status & AX_SPR_SLCT)
+		ret |= PARPORT_STATUS_SELECT;
+
+	if (status & AX_SPR_PE)
+		ret |= PARPORT_STATUS_PAPEROUT;
+
+	return ret;
+}
+
+static unsigned char
+parport_ax88796_frob_control(struct parport *p, unsigned char mask,
+			     unsigned char val)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	unsigned char old = parport_ax88796_read_control(p);
+
+	dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n",
+		mask, val, old);
+
+	parport_ax88796_write_control(p, (old & ~mask) | val);
+	return old;
+}
+
+static void
+parport_ax88796_enable_irq(struct parport *p)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (!dd->irq_enabled) {
+		enable_irq(p->irq);
+		dd->irq_enabled = 1;
+	}
+	local_irq_restore(flags);
+}
+
+static void
+parport_ax88796_disable_irq(struct parport *p)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (dd->irq_enabled) {
+		disable_irq(p->irq);
+		dd->irq_enabled = 0;
+	}
+	local_irq_restore(flags);
+}
+
+static void
+parport_ax88796_data_forward(struct parport *p)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	void __iomem *cpr = dd->spp_cpr;
+
+	writeb((readb(cpr) & ~AX_CPR_nDOE), cpr);
+}
+
+static void
+parport_ax88796_data_reverse(struct parport *p)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+	void __iomem *cpr = dd->spp_cpr;
+
+	writeb(readb(cpr) | AX_CPR_nDOE, cpr);
+}
+
+static void
+parport_ax88796_init_state(struct pardevice *d, struct parport_state *s)
+{
+	struct ax_drvdata *dd = pp_to_drv(d->port);
+
+	memset(s, 0, sizeof(struct parport_state));
+
+	dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s);
+	s->u.ax88796.cpr = readb(dd->spp_cpr);
+}
+
+static void
+parport_ax88796_save_state(struct parport *p, struct parport_state *s)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+
+	dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s);
+	s->u.ax88796.cpr = readb(dd->spp_cpr);
+}
+
+static void
+parport_ax88796_restore_state(struct parport *p, struct parport_state *s)
+{
+	struct ax_drvdata *dd = pp_to_drv(p);
+
+	dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s);
+	writeb(s->u.ax88796.cpr, dd->spp_cpr);
+}
+
+static irqreturn_t
+parport_ax88796_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+        parport_generic_irq(irq, dev_id, regs);
+        return IRQ_HANDLED;
+}
+
+
+static struct parport_operations parport_ax88796_ops = {
+	.write_data	= parport_ax88796_write_data,
+	.read_data	= parport_ax88796_read_data,
+
+	.write_control	= parport_ax88796_write_control,
+	.read_control	= parport_ax88796_read_control,
+	.frob_control	= parport_ax88796_frob_control,
+
+	.read_status	= parport_ax88796_read_status,
+
+	.enable_irq	= parport_ax88796_enable_irq,
+	.disable_irq	= parport_ax88796_disable_irq,
+
+	.data_forward	= parport_ax88796_data_forward,
+	.data_reverse	= parport_ax88796_data_reverse,
+
+	.init_state	= parport_ax88796_init_state,
+	.save_state	= parport_ax88796_save_state,
+	.restore_state	= parport_ax88796_restore_state,
+
+	.epp_write_data	= parport_ieee1284_epp_write_data,
+	.epp_read_data	= parport_ieee1284_epp_read_data,
+	.epp_write_addr	= parport_ieee1284_epp_write_addr,
+	.epp_read_addr	= parport_ieee1284_epp_read_addr,
+
+	.ecp_write_data	= parport_ieee1284_ecp_write_data,
+	.ecp_read_data	= parport_ieee1284_ecp_read_data,
+	.ecp_write_addr	= parport_ieee1284_ecp_write_addr,
+
+	.compat_write_data	= parport_ieee1284_write_compat,
+	.nibble_read_data	= parport_ieee1284_read_nibble,
+	.byte_read_data		= parport_ieee1284_read_byte,
+
+	.owner		= THIS_MODULE,
+};
+
+static int parport_ax88796_probe(struct platform_device *pdev)
+{
+	struct device *_dev = &pdev->dev;
+	struct ax_drvdata *dd;
+	struct parport *pp = NULL;
+	struct resource *res;
+	unsigned long size;
+	int spacing;
+	int irq;
+	int ret;
+
+	dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL);
+	if (dd == NULL) {
+		dev_err(_dev, "no memory for private data\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(_dev, "no MEM specified\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	size = (res->end - res->start) + 1;
+	spacing = size / 3;
+
+	dd->io = request_mem_region(res->start, size, pdev->name);
+	if (dd->io == NULL) {
+		dev_err(_dev, "cannot reserve memory\n");
+		ret = -ENXIO;
+		goto exit_mem;
+	}
+
+	dd->base = ioremap(res->start, size);
+	if (dd->base == NULL) {
+		dev_err(_dev, "cannot ioremap region\n");
+		ret = -ENXIO;
+		goto exit_res;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		irq = PARPORT_IRQ_NONE;
+
+	pp = parport_register_port((unsigned long)dd->base, irq,
+				   PARPORT_DMA_NONE,
+				   &parport_ax88796_ops);
+
+	if (pp == NULL) {
+		dev_err(_dev, "failed to register parallel port\n");
+		ret = -ENOMEM;
+		goto exit_unmap;
+	}
+
+	pp->private_data = dd;
+	dd->parport = pp;
+	dd->dev = _dev;
+
+	dd->spp_data = dd->base;
+	dd->spp_spr  = dd->base + (spacing * 1);
+	dd->spp_cpr  = dd->base + (spacing * 2);
+
+	/* initialise the port controls */
+	writeb(AX_CPR_STRB, dd->spp_cpr);
+
+	if (irq >= 0) {
+		/* request irq */
+		ret = request_irq(irq, parport_ax88796_interrupt,
+				  SA_TRIGGER_FALLING, pdev->name, pp);
+
+		if (ret < 0)
+			goto exit_port;
+
+		dd->irq_enabled = 1;
+	}
+
+	platform_set_drvdata(pdev, pp);
+
+	dev_info(_dev, "attached parallel port driver\n");
+	parport_announce_port(pp);
+
+	return 0;
+
+ exit_port:
+	parport_remove_port(pp);
+ exit_unmap:
+	iounmap(dd->base);
+ exit_res:
+	release_resource(dd->io);
+	kfree(dd->io);
+ exit_mem:
+	kfree(dd);
+	return ret;
+}
+
+static int parport_ax88796_remove(struct platform_device *pdev)
+{
+	struct parport *p = platform_get_drvdata(pdev);
+	struct ax_drvdata *dd = pp_to_drv(p);
+
+	free_irq(p->irq, p);
+	parport_remove_port(p);
+	iounmap(dd->base);
+	release_resource(dd->io);
+	kfree(dd->io);
+	kfree(dd);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int parport_ax88796_suspend(struct platform_device *dev,
+				   pm_message_t state)
+{
+	struct parport *p = platform_get_drvdata(dev);
+	struct ax_drvdata *dd = pp_to_drv(p);
+
+	parport_ax88796_save_state(p, &dd->suspend);
+	writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr);
+	return 0;
+}
+
+static int parport_ax88796_resume(struct platform_device *dev)
+{
+	struct parport *p = platform_get_drvdata(dev);
+	struct ax_drvdata *dd = pp_to_drv(p);
+
+	parport_ax88796_restore_state(p, &dd->suspend);
+	return 0;
+}
+
+#else
+#define parport_ax88796_suspend NULL
+#define parport_ax88796_resume  NULL
+#endif
+
+static struct platform_driver axdrv = {
+	.driver		= {
+		.name	= "ax88796-pp",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= parport_ax88796_probe,
+	.remove		= parport_ax88796_remove,
+	.suspend	= parport_ax88796_suspend,
+	.resume		= parport_ax88796_resume,
+};
+
+static int __init parport_ax88796_init(void)
+{
+	return platform_driver_register(&axdrv);
+}
+
+static void __exit parport_ax88796_exit(void)
+{
+	platform_driver_unregister(&axdrv);
+}
+
+module_init(parport_ax88796_init)
+module_exit(parport_ax88796_exit)
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("AX88796 Parport parallel port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 1de52d9..7352104 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -15,7 +15,7 @@
  * 	    Phil Blundell <philb@gnu.org>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  *	    Jose Renau <renau@acm.org>
- *          David Campbell <campbell@torque.net>
+ *          David Campbell
  *          Andrea Arcangeli
  */
 
diff --git a/drivers/parport/parport_gsc.h b/drivers/parport/parport_gsc.h
index 662f6c1..fc9c37c 100644
--- a/drivers/parport/parport_gsc.h
+++ b/drivers/parport/parport_gsc.h
@@ -24,7 +24,7 @@
  * 	    Phil Blundell <Philip.Blundell@pobox.com>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  *	    Jose Renau <renau@acm.org>
- *          David Campbell <campbell@torque.net>
+ *          David Campbell
  *          Andrea Arcangeli
  */
 
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 48bbf32..7318e4a 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -3,7 +3,7 @@
  * Authors: Phil Blundell <philb@gnu.org>
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  *	    Jose Renau <renau@acm.org>
- *          David Campbell <campbell@torque.net>
+ *          David Campbell
  *          Andrea Arcangeli
  *
  * based on work by Grant Guenther <grant@torque.net> and Phil Blundell.
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 36a1556..7c43c53 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -1,5 +1,4 @@
-/* $Id: parport_sunbpp.c,v 1.12 2001/05/26 03:01:42 davem Exp $
- * Parallel-port routines for Sun architecture
+/* parport_sunbpp.c: Parallel-port routines for SBUS
  * 
  * Author: Derrick J. Brashear <shadow@dementia.org>
  *
@@ -14,6 +13,9 @@
  *          Gus Baldauf (gbaldauf@ix.netcom.com)
  *          Peter Zaitcev
  *          Tom Dyas
+ *
+ * Updated to new SBUS device framework: David S. Miller <davem@davemloft.net>
+ * 
  */
 
 #include <linux/string.h>
@@ -287,14 +289,7 @@
 	.owner		= THIS_MODULE,
 };
 
-typedef struct {
-	struct list_head list;
-	struct parport *port;
-} Node;
-/* no locks, everything's serialized */
-static LIST_HEAD(port_list);
-
-static int __init init_one_port(struct sbus_dev *sdev)
+static int __devinit init_one_port(struct sbus_dev *sdev)
 {
 	struct parport *p;
 	/* at least in theory there may be a "we don't dma" case */
@@ -303,109 +298,120 @@
 	int irq, dma, err = 0, size;
 	struct bpp_regs __iomem *regs;
 	unsigned char value_tcr;
-	Node *node;
-
-	dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev));
-	node = kmalloc(sizeof(Node), GFP_KERNEL);
-	if (!node)
-		goto out0;
 
 	irq = sdev->irqs[0];
 	base = sbus_ioremap(&sdev->resource[0], 0,
 			    sdev->reg_addrs[0].reg_size, 
 			    "sunbpp");
 	if (!base)
-		goto out1;
+		return -ENODEV;
 
 	size = sdev->reg_addrs[0].reg_size;
 	dma = PARPORT_DMA_NONE;
 
-	dprintk(("alloc(ppops), "));
-	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
+	ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL);
         if (!ops)
-		goto out2;
+		goto out_unmap;
 
         memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations));
 
 	dprintk(("register_port\n"));
 	if (!(p = parport_register_port((unsigned long)base, irq, dma, ops)))
-		goto out3;
+		goto out_free_ops;
 
 	p->size = size;
 
-	dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ",
-		p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p));
 	if ((err = request_irq(p->irq, parport_sunbpp_interrupt,
 			       SA_SHIRQ, p->name, p)) != 0) {
-		dprintk(("ERROR %d\n", err));
-		goto out4;
+		goto out_put_port;
 	}
-	dprintk(("OK\n"));
+
 	parport_sunbpp_enable_irq(p);
 
 	regs = (struct bpp_regs __iomem *)p->base;
-	dprintk((KERN_DEBUG "forward\n"));
+
 	value_tcr = sbus_readb(&regs->p_tcr);
 	value_tcr &= ~P_TCR_DIR;
 	sbus_writeb(value_tcr, &regs->p_tcr);
 
 	printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base);
-	node->port = p;
-	list_add(&node->list, &port_list);
-	parport_announce_port (p);
 
-	return 1;
+	dev_set_drvdata(&sdev->ofdev.dev, p);
 
-out4:
+	parport_announce_port(p);
+
+	return 0;
+
+out_put_port:
 	parport_put_port(p);
-out3:
+
+out_free_ops:
 	kfree(ops);
-out2:
+
+out_unmap:
 	sbus_iounmap(base, size);
-out1:
-	kfree(node);
-out0:
+
 	return err;
 }
 
+static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+
+	return init_one_port(sdev);
+}
+
+static int __devexit bpp_remove(struct of_device *dev)
+{
+	struct parport *p = dev_get_drvdata(&dev->dev);
+	struct parport_operations *ops = p->ops;
+
+	parport_remove_port(p);
+
+	if (p->irq != PARPORT_IRQ_NONE) {
+		parport_sunbpp_disable_irq(p);
+		free_irq(p->irq, p);
+	}
+
+	sbus_iounmap((void __iomem *) p->base, p->size);
+	parport_put_port(p);
+	kfree(ops);
+
+	dev_set_drvdata(&dev->dev, NULL);
+
+	return 0;
+}
+
+static struct of_device_id bpp_match[] = {
+	{
+		.name = "SUNW,bpp",
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, bpp_match);
+
+static struct of_platform_driver bpp_sbus_driver = {
+	.name		= "bpp",
+	.match_table	= bpp_match,
+	.probe		= bpp_probe,
+	.remove		= __devexit_p(bpp_remove),
+};
+
 static int __init parport_sunbpp_init(void)
 {
-        struct sbus_bus *sbus;
-        struct sbus_dev *sdev;
-	int count = 0;
-
-	for_each_sbus(sbus) {
-		for_each_sbusdev(sdev, sbus) {
-			if (!strcmp(sdev->prom_name, "SUNW,bpp"))
-				count += init_one_port(sdev);
-		}
-	}
-	return count ? 0 : -ENODEV;
+	return of_register_driver(&bpp_sbus_driver, &sbus_bus_type);
 }
 
 static void __exit parport_sunbpp_exit(void)
 {
-	while (!list_empty(&port_list)) {
-		Node *node = list_entry(port_list.next, Node, list);
-		struct parport *p = node->port;
-		struct parport_operations *ops = p->ops;
-		parport_remove_port(p);
-
-		if (p->irq != PARPORT_IRQ_NONE) {
-			parport_sunbpp_disable_irq(p);
-			free_irq(p->irq, p);
-		}
-		sbus_iounmap((void __iomem *)p->base, p->size);
-		parport_put_port(p);
-		kfree (ops);
-		list_del(&node->list);
-		kfree (node);
-	}
+	of_unregister_driver(&bpp_sbus_driver);
 }
 
 MODULE_AUTHOR("Derrick J Brashear");
 MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
 MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
+MODULE_VERSION("2.0");
 MODULE_LICENSE("GPL");
 
 module_init(parport_sunbpp_init)
diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c
index cbe1718..8610ae8 100644
--- a/drivers/parport/procfs.c
+++ b/drivers/parport/procfs.c
@@ -1,6 +1,6 @@
 /* Sysctl interface for parport devices.
  * 
- * Authors: David Campbell <campbell@torque.net>
+ * Authors: David Campbell
  *          Tim Waugh <tim@cyberelk.demon.co.uk>
  *          Philip Blundell <philb@gnu.org>
  *          Andrea Arcangeli
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index bbbfd79..2cb22c8 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -218,7 +218,7 @@
  *	parport_get_port - increment a port's reference count
  *	@port: the port
  *
- *	This ensure's that a struct parport pointer remains valid
+ *	This ensures that a struct parport pointer remains valid
  *	until the matching parport_put_port() call.
  **/
 
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 6707df9..f2d152b 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -26,7 +26,11 @@
 obj-$(CONFIG_PPC64) += setup-bus.o
 obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
 obj-$(CONFIG_X86_VISWS) += setup-irq.o
-obj-$(CONFIG_PCI_MSI) += msi.o
+
+msiobj-y := msi.o msi-apic.o
+msiobj-$(CONFIG_IA64_GENERIC) += msi-altix.o
+msiobj-$(CONFIG_IA64_SGI_SN2) += msi-altix.o
+obj-$(CONFIG_PCI_MSI) += $(msiobj-y)
 
 #
 # ACPI Related PCI FW Functions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index eed67d9..7230926 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -81,9 +81,9 @@
 {
 	device_add(&dev->dev);
 
-	spin_lock(&pci_bus_lock);
+	down_write(&pci_bus_sem);
 	list_add_tail(&dev->global_list, &pci_devices);
-	spin_unlock(&pci_bus_lock);
+	up_write(&pci_bus_sem);
 
 	pci_proc_attach_device(dev);
 	pci_create_sysfs_dev_files(dev);
@@ -125,10 +125,10 @@
 		 */
 		if (dev->subordinate) {
 		       if (list_empty(&dev->subordinate->node)) {
-			       spin_lock(&pci_bus_lock);
+			       down_write(&pci_bus_sem);
 			       list_add_tail(&dev->subordinate->node,
 					       &dev->bus->children);
-			       spin_unlock(&pci_bus_lock);
+			       up_write(&pci_bus_sem);
 		       }
 			pci_bus_add_devices(dev->subordinate);
 
@@ -168,7 +168,7 @@
 	struct list_head *next;
 
 	bus = top;
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 	next = top->devices.next;
 	for (;;) {
 		if (next == &bus->devices) {
@@ -180,22 +180,19 @@
 			continue;
 		}
 		dev = list_entry(next, struct pci_dev, bus_list);
-		pci_dev_get(dev);
 		if (dev->subordinate) {
 			/* this is a pci-pci bridge, do its devices next */
 			next = dev->subordinate->devices.next;
 			bus = dev->subordinate;
 		} else
 			next = dev->bus_list.next;
-		spin_unlock(&pci_bus_lock);
 
-		/* Run device routines with the bus unlocked */
+		/* Run device routines with the device locked */
+		down(&dev->dev.sem);
 		cb(dev, userdata);
-
-		spin_lock(&pci_bus_lock);
-		pci_dev_put(dev);
+		up(&dev->dev.sem);
 	}
-	spin_unlock(&pci_bus_lock);
+	up_read(&pci_bus_sem);
 }
 EXPORT_SYMBOL_GPL(pci_walk_bus);
 
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index 39af9c3..51cb9f8 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -25,6 +25,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
@@ -33,10 +34,184 @@
 #include <acpi/actypes.h>
 #include "pci_hotplug.h"
 
+#define MY_NAME	"acpi_pcihp"
+
+#define dbg(fmt, arg...) do { if (debug_acpi) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
+
 #define	METHOD_NAME__SUN	"_SUN"
 #define	METHOD_NAME__HPP	"_HPP"
 #define	METHOD_NAME_OSHP	"OSHP"
 
+static int debug_acpi;
+
+static acpi_status
+decode_type0_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+{
+	int i;
+	union acpi_object *fields = record->package.elements;
+	u32 revision = fields[1].integer.value;
+
+	switch (revision) {
+	case 1:
+		if (record->package.count != 6)
+			return AE_ERROR;
+		for (i = 2; i < 6; i++)
+			if (fields[i].type != ACPI_TYPE_INTEGER)
+				return AE_ERROR;
+		hpx->t0 = &hpx->type0_data;
+		hpx->t0->revision        = revision;
+		hpx->t0->cache_line_size = fields[2].integer.value;
+		hpx->t0->latency_timer   = fields[3].integer.value;
+		hpx->t0->enable_serr     = fields[4].integer.value;
+		hpx->t0->enable_perr     = fields[5].integer.value;
+		break;
+	default:
+		printk(KERN_WARNING
+		       "%s: Type 0 Revision %d record not supported\n",
+		       __FUNCTION__, revision);
+		return AE_ERROR;
+	}
+	return AE_OK;
+}
+
+static acpi_status
+decode_type1_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+{
+	int i;
+	union acpi_object *fields = record->package.elements;
+	u32 revision = fields[1].integer.value;
+
+	switch (revision) {
+	case 1:
+		if (record->package.count != 5)
+			return AE_ERROR;
+		for (i = 2; i < 5; i++)
+			if (fields[i].type != ACPI_TYPE_INTEGER)
+				return AE_ERROR;
+		hpx->t1 = &hpx->type1_data;
+		hpx->t1->revision      = revision;
+		hpx->t1->max_mem_read  = fields[2].integer.value;
+		hpx->t1->avg_max_split = fields[3].integer.value;
+		hpx->t1->tot_max_split = fields[4].integer.value;
+		break;
+	default:
+		printk(KERN_WARNING
+		       "%s: Type 1 Revision %d record not supported\n",
+		       __FUNCTION__, revision);
+		return AE_ERROR;
+	}
+	return AE_OK;
+}
+
+static acpi_status
+decode_type2_hpx_record(union acpi_object *record, struct hotplug_params *hpx)
+{
+	int i;
+	union acpi_object *fields = record->package.elements;
+	u32 revision = fields[1].integer.value;
+
+	switch (revision) {
+	case 1:
+		if (record->package.count != 18)
+			return AE_ERROR;
+		for (i = 2; i < 18; i++)
+			if (fields[i].type != ACPI_TYPE_INTEGER)
+				return AE_ERROR;
+		hpx->t2 = &hpx->type2_data;
+		hpx->t2->revision      = revision;
+		hpx->t2->unc_err_mask_and      = fields[2].integer.value;
+		hpx->t2->unc_err_mask_or       = fields[3].integer.value;
+		hpx->t2->unc_err_sever_and     = fields[4].integer.value;
+		hpx->t2->unc_err_sever_or      = fields[5].integer.value;
+		hpx->t2->cor_err_mask_and      = fields[6].integer.value;
+		hpx->t2->cor_err_mask_or       = fields[7].integer.value;
+		hpx->t2->adv_err_cap_and       = fields[8].integer.value;
+		hpx->t2->adv_err_cap_or        = fields[9].integer.value;
+		hpx->t2->pci_exp_devctl_and    = fields[10].integer.value;
+		hpx->t2->pci_exp_devctl_or     = fields[11].integer.value;
+		hpx->t2->pci_exp_lnkctl_and    = fields[12].integer.value;
+		hpx->t2->pci_exp_lnkctl_or     = fields[13].integer.value;
+		hpx->t2->sec_unc_err_sever_and = fields[14].integer.value;
+		hpx->t2->sec_unc_err_sever_or  = fields[15].integer.value;
+		hpx->t2->sec_unc_err_mask_and  = fields[16].integer.value;
+		hpx->t2->sec_unc_err_mask_or   = fields[17].integer.value;
+		break;
+	default:
+		printk(KERN_WARNING
+		       "%s: Type 2 Revision %d record not supported\n",
+		       __FUNCTION__, revision);
+		return AE_ERROR;
+	}
+	return AE_OK;
+}
+
+static acpi_status
+acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx)
+{
+	acpi_status status;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *package, *record, *fields;
+	u32 type;
+	int i;
+
+	/* Clear the return buffer with zeros */
+	memset(hpx, 0, sizeof(struct hotplug_params));
+
+	status = acpi_evaluate_object(handle, "_HPX", NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return status;
+
+	package = (union acpi_object *)buffer.pointer;
+	if (package->type != ACPI_TYPE_PACKAGE) {
+		status = AE_ERROR;
+		goto exit;
+	}
+
+	for (i = 0; i < package->package.count; i++) {
+		record = &package->package.elements[i];
+		if (record->type != ACPI_TYPE_PACKAGE) {
+			status = AE_ERROR;
+			goto exit;
+		}
+
+		fields = record->package.elements;
+		if (fields[0].type != ACPI_TYPE_INTEGER ||
+		    fields[1].type != ACPI_TYPE_INTEGER) {
+			status = AE_ERROR;
+			goto exit;
+		}
+
+		type = fields[0].integer.value;
+		switch (type) {
+		case 0:
+			status = decode_type0_hpx_record(record, hpx);
+			if (ACPI_FAILURE(status))
+				goto exit;
+			break;
+		case 1:
+			status = decode_type1_hpx_record(record, hpx);
+			if (ACPI_FAILURE(status))
+				goto exit;
+			break;
+		case 2:
+			status = decode_type2_hpx_record(record, hpx);
+			if (ACPI_FAILURE(status))
+				goto exit;
+			break;
+		default:
+			printk(KERN_ERR "%s: Type %d record not supported\n",
+			       __FUNCTION__, type);
+			status = AE_ERROR;
+			goto exit;
+		}
+	}
+ exit:
+	kfree(buffer.pointer);
+	return status;
+}
 
 static acpi_status
 acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
@@ -50,6 +225,9 @@
 
 	acpi_get_name(handle, ACPI_FULL_PATHNAME, &string);
 
+	/* Clear the return buffer with zeros */
+	memset(hpp, 0, sizeof(struct hotplug_params));
+
 	/* get _hpp */
 	status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
 	switch (status) {
@@ -58,7 +236,7 @@
 		if (!ret_buf.pointer) {
 			printk(KERN_ERR "%s:%s alloc for _HPP fail\n",
 				__FUNCTION__, (char *)string.pointer);
-			acpi_os_free(string.pointer);
+			kfree(string.pointer);
 			return AE_NO_MEMORY;
 		}
 		status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
@@ -69,7 +247,7 @@
 		if (ACPI_FAILURE(status)) {
 			pr_debug("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
 				(char *)string.pointer, status);
-			acpi_os_free(string.pointer);
+			kfree(string.pointer);
 			return status;
 		}
 	}
@@ -98,19 +276,20 @@
 		}
 	}
 
-	hpp->cache_line_size = nui[0];
-	hpp->latency_timer = nui[1];
-	hpp->enable_serr = nui[2];
-	hpp->enable_perr = nui[3];
+	hpp->t0 = &hpp->type0_data;
+	hpp->t0->cache_line_size = nui[0];
+	hpp->t0->latency_timer = nui[1];
+	hpp->t0->enable_serr = nui[2];
+	hpp->t0->enable_perr = nui[3];
 
-	pr_debug("  _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
-	pr_debug("  _HPP: latency timer  =0x%x\n", hpp->latency_timer);
-	pr_debug("  _HPP: enable SERR    =0x%x\n", hpp->enable_serr);
-	pr_debug("  _HPP: enable PERR    =0x%x\n", hpp->enable_perr);
+	pr_debug("  _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size);
+	pr_debug("  _HPP: latency timer  =0x%x\n", hpp->t0->latency_timer);
+	pr_debug("  _HPP: enable SERR    =0x%x\n", hpp->t0->enable_serr);
+	pr_debug("  _HPP: enable PERR    =0x%x\n", hpp->t0->enable_perr);
 
 free_and_return:
-	acpi_os_free(string.pointer);
-	acpi_os_free(ret_buf.pointer);
+	kfree(string.pointer);
+	kfree(ret_buf.pointer);
 	return status;
 }
 
@@ -130,13 +309,17 @@
 	/* run OSHP */
 	status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
 	if (ACPI_FAILURE(status))
-		printk(KERN_ERR "%s:%s OSHP fails=0x%x\n", __FUNCTION__,
-			(char *)string.pointer, status);
+		if (status != AE_NOT_FOUND)
+			printk(KERN_ERR "%s:%s OSHP fails=0x%x\n",
+			       __FUNCTION__, (char *)string.pointer, status);
+		else
+			dbg("%s:%s OSHP not found\n",
+			    __FUNCTION__, (char *)string.pointer);
 	else
 		pr_debug("%s:%s OSHP passes\n", __FUNCTION__,
 			(char *)string.pointer);
 
-	acpi_os_free(string.pointer);
+	kfree(string.pointer);
 	return status;
 }
 EXPORT_SYMBOL_GPL(acpi_run_oshp);
@@ -145,14 +328,27 @@
 
 /* acpi_get_hp_params_from_firmware
  *
- * @dev - the pci_dev of the newly added device
+ * @bus - the pci_bus of the bus on which the device is newly added
  * @hpp - allocated by the caller
  */
-acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
 		struct hotplug_params *hpp)
 {
 	acpi_status status = AE_NOT_FOUND;
-	struct pci_dev *pdev = dev;
+	acpi_handle handle, phandle;
+	struct pci_bus *pbus = bus;
+	struct pci_dev *pdev;
+
+	do {
+		pdev = pbus->self;
+		if (!pdev) {
+			handle = acpi_get_pci_rootbridge_handle(
+				pci_domain_nr(pbus), pbus->number);
+			break;
+		}
+		handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+		pbus = pbus->parent;
+	} while (!handle);
 
 	/*
 	 * _HPP settings apply to all child buses, until another _HPP is
@@ -160,15 +356,19 @@
 	 * look for it in the parent device scope since that would apply to
 	 * this pci dev. If we don't find any _HPP, use hardcoded defaults
 	 */
-	while (pdev && (ACPI_FAILURE(status))) {
-		acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
-		if (!handle)
+	while (handle) {
+		status = acpi_run_hpx(handle, hpp);
+		if (ACPI_SUCCESS(status))
 			break;
 		status = acpi_run_hpp(handle, hpp);
-		if (!(pdev->bus->parent))
+		if (ACPI_SUCCESS(status))
 			break;
-		/* Check if a parent object supports _HPP */
-		pdev = pdev->bus->parent->self;
+		if (acpi_root_bridge(handle))
+			break;
+		status = acpi_get_parent(handle, &phandle);
+		if (ACPI_FAILURE(status))
+			break;
+		handle = phandle;
 	}
 	return status;
 }
@@ -192,20 +392,23 @@
 		if ((info->valid & ACPI_VALID_HID) &&
 			!strcmp(PCI_ROOT_HID_STRING,
 					info->hardware_id.value)) {
-			acpi_os_free(buffer.pointer);
+			kfree(buffer.pointer);
 			return 1;
 		}
 		if (info->valid & ACPI_VALID_CID) {
 			for (i=0; i < info->compatibility_id.count; i++) {
 				if (!strcmp(PCI_ROOT_HID_STRING,
 					info->compatibility_id.id[i].value)) {
-					acpi_os_free(buffer.pointer);
+					kfree(buffer.pointer);
 					return 1;
 				}
 			}
 		}
-		acpi_os_free(buffer.pointer);
+		kfree(buffer.pointer);
 	}
 	return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_root_bridge);
+
+module_param(debug_acpi, bool, 0644);
+MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 467ac70..17a93f8 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -75,6 +75,10 @@
 	struct list_head list;
 	acpi_handle handle;
 	struct acpiphp_slot *slots;
+
+	/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
+	struct acpiphp_func *func;
+
 	int type;
 	int nr_slots;
 
@@ -122,6 +126,7 @@
  */
 struct acpiphp_func {
 	struct acpiphp_slot *slot;	/* parent */
+	struct acpiphp_bridge *bridge;	/* Ejectable PCI-to-PCI bridge */
 
 	struct list_head sibling;
 	struct pci_dev *pci_dev;
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 053ee84..d370f99 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -286,13 +286,19 @@
 {
 	acpi_status status;
 
-	status = acpi_get_hp_params_from_firmware(bridge->pci_dev, &bridge->hpp);
-	if (ACPI_FAILURE(status)) {
+	status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp);
+	if (ACPI_FAILURE(status) ||
+	    !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) {
 		/* use default numbers */
-		bridge->hpp.cache_line_size = 0x10;
-		bridge->hpp.latency_timer = 0x40;
-		bridge->hpp.enable_serr = 0;
-		bridge->hpp.enable_perr = 0;
+		printk(KERN_WARNING
+		       "%s: Could not get hotplug parameters. Use defaults\n",
+		       __FUNCTION__);
+		bridge->hpp.t0 = &bridge->hpp.type0_data;
+		bridge->hpp.t0->revision = 0;
+		bridge->hpp.t0->cache_line_size = 0x10;
+		bridge->hpp.t0->latency_timer = 0x40;
+		bridge->hpp.t0->enable_serr = 0;
+		bridge->hpp.t0->enable_perr = 0;
 	}
 }
 
@@ -319,6 +325,13 @@
 
 	/* install notify handler */
 	if (bridge->type != BRIDGE_TYPE_HOST) {
+		if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
+			status = acpi_remove_notify_handler(bridge->func->handle,
+						ACPI_SYSTEM_NOTIFY,
+						handle_hotplug_event_func);
+			if (ACPI_FAILURE(status))
+				err("failed to remove notify handler\n");
+		}
 		status = acpi_install_notify_handler(bridge->handle,
 					     ACPI_SYSTEM_NOTIFY,
 					     handle_hotplug_event_bridge,
@@ -331,6 +344,66 @@
 }
 
 
+/* find acpiphp_func from acpiphp_bridge */
+static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
+{
+	struct list_head *node, *l;
+	struct acpiphp_bridge *bridge;
+	struct acpiphp_slot *slot;
+	struct acpiphp_func *func;
+
+	list_for_each(node, &bridge_list) {
+		bridge = list_entry(node, struct acpiphp_bridge, list);
+		for (slot = bridge->slots; slot; slot = slot->next) {
+			list_for_each(l, &slot->funcs) {
+				func = list_entry(l, struct acpiphp_func,
+							sibling);
+				if (func->handle == handle)
+					return func;
+			}
+		}
+	}
+
+	return NULL;
+}
+
+
+static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
+{
+	acpi_handle dummy_handle;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_STA", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_STA;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_EJ0", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_EJ0;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_PS0", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_PS0;
+
+	if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+					"_PS3", &dummy_handle)))
+		bridge->flags |= BRIDGE_HAS_PS3;
+
+	/* is this ejectable p2p bridge? */
+	if (bridge->flags & BRIDGE_HAS_EJ0) {
+		struct acpiphp_func *func;
+
+		dbg("found ejectable p2p bridge\n");
+
+		/* make link between PCI bridge and PCI function */
+		func = acpiphp_bridge_handle_to_function(bridge->handle);
+		if (!func)
+			return;
+		bridge->func = func;
+		func->bridge = bridge;
+	}
+}
+
+
 /* allocate and initialize host bridge data structure */
 static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)
 {
@@ -364,6 +437,7 @@
 
 	bridge->type = BRIDGE_TYPE_P2P;
 	bridge->handle = handle;
+	config_p2p_bridge_flags(bridge);
 
 	bridge->pci_dev = pci_dev_get(pci_dev);
 	bridge->pci_bus = pci_dev->subordinate;
@@ -423,7 +497,7 @@
 	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
 				     find_p2p_bridge, dev->subordinate, NULL);
 	if (ACPI_FAILURE(status))
-		warn("find_p2p_bridge faied (error code = 0x%x)\n", status);
+		warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
 
  out:
 	pci_dev_put(dev);
@@ -478,7 +552,6 @@
 	if (detect_ejectable_slots(handle) > 0) {
 		dbg("found PCI host-bus bridge with hot-pluggable slots\n");
 		add_host_bridge(handle, pci_bus);
-		return 0;
 	}
 
 	/* search P2P bridges under this host bridge */
@@ -486,7 +559,7 @@
 				     find_p2p_bridge, pci_bus, NULL);
 
 	if (ACPI_FAILURE(status))
-		warn("find_p2p_bridge faied (error code = 0x%x)\n",status);
+		warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
 
 	return 0;
 }
@@ -516,6 +589,16 @@
 	if (ACPI_FAILURE(status))
 		err("failed to remove notify handler\n");
 
+	if ((bridge->type != BRIDGE_TYPE_HOST) &&
+	    ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
+		status = acpi_install_notify_handler(bridge->func->handle,
+						ACPI_SYSTEM_NOTIFY,
+						handle_hotplug_event_func,
+						bridge->func);
+		if (ACPI_FAILURE(status))
+			err("failed to install interrupt notify handler\n");
+	}
+
 	slot = bridge->slots;
 	while (slot) {
 		struct acpiphp_slot *next = slot->next;
@@ -549,6 +632,11 @@
 {
 	struct acpiphp_bridge *bridge;
 
+	/* cleanup p2p bridges under this P2P bridge
+	   in a depth-first manner */
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+				cleanup_p2p_bridge, NULL, NULL);
+
 	if (!(bridge = acpiphp_handle_to_bridge(handle)))
 		return AE_OK;
 	cleanup_bridge(bridge);
@@ -559,15 +647,14 @@
 {
 	struct acpiphp_bridge *bridge;
 
+	/* cleanup p2p bridges under this host bridge
+	   in a depth-first manner */
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+				(u32)1, cleanup_p2p_bridge, NULL, NULL);
+
 	bridge = acpiphp_handle_to_bridge(handle);
-	if (bridge) {
+	if (bridge)
 		cleanup_bridge(bridge);
-	} else {
-		/* clean-up p2p bridges under this host bridge */
-		acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
-				    ACPI_UINT32_MAX, cleanup_p2p_bridge,
-				    NULL, NULL);
-	}
 }
 
 static struct pci_dev * get_apic_pci_info(acpi_handle handle)
@@ -634,7 +721,7 @@
 		break;
 	}
  out:
-	acpi_os_free(buffer.pointer);
+	kfree(buffer.pointer);
 	return result;
 }
 
@@ -797,36 +884,6 @@
 }
 
 
-
-/**
- *  get_func - get a pointer to acpiphp_func given a slot, device
- *  @slot: slot to search
- *  @dev:  pci_dev struct to match.
- *
- *  This function will increase the reference count of pci_dev,
- *  so callers should call pci_dev_put when complete.
- *
- */
-static struct acpiphp_func *
-get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
-{
-	struct acpiphp_func *func = NULL;
-	struct pci_bus *bus = slot->bridge->pci_bus;
-	struct pci_dev *pdev;
-
-	list_for_each_entry(func, &slot->funcs, sibling) {
-		pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
-					func->function));
-		if (pdev) {
-			if (pdev == dev)
-				break;
-			pci_dev_put(pdev);
-		}
-	}
-	return func;
-}
-
-
 /**
  * acpiphp_bus_add - add a new bus to acpi subsystem
  * @func: acpiphp_func of the bridge
@@ -872,6 +929,28 @@
 }
 
 
+/**
+ * acpiphp_bus_trim - trim a bus from acpi subsystem
+ * @handle: handle to acpi namespace
+ *
+ */
+int acpiphp_bus_trim(acpi_handle handle)
+{
+	struct acpi_device *device;
+	int retval;
+
+	retval = acpi_bus_get_device(handle, &device);
+	if (retval) {
+		dbg("acpi_device not found\n");
+		return retval;
+	}
+
+	retval = acpi_bus_trim(device, 1);
+	if (retval)
+		err("cannot remove from acpi list\n");
+
+	return retval;
+}
 
 /**
  * enable_device - enable, configure a slot
@@ -889,6 +968,7 @@
 	struct acpiphp_func *func;
 	int retval = 0;
 	int num, max, pass;
+	acpi_status status;
 
 	if (slot->flags & SLOT_ENABLED)
 		goto err_exit;
@@ -918,19 +998,17 @@
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 				max = pci_scan_bridge(bus, dev, max, pass);
-				if (pass && dev->subordinate) {
+				if (pass && dev->subordinate)
 					pci_bus_size_bridges(dev->subordinate);
-					func = get_func(slot, dev);
-					if (func) {
-						acpiphp_bus_add(func);
-						/* side effect of get_func */
-						pci_dev_put(dev);
-					}
-				}
 			}
 		}
 	}
 
+	list_for_each (l, &slot->funcs) {
+		func = list_entry(l, struct acpiphp_func, sibling);
+		acpiphp_bus_add(func);
+	}
+
 	pci_bus_assign_resources(bus);
 	acpiphp_sanitize_bus(bus);
 	pci_enable_bridges(bus);
@@ -943,6 +1021,17 @@
 		func = list_entry(l, struct acpiphp_func, sibling);
 		func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
 							func->function));
+		if (!func->pci_dev)
+			continue;
+
+		if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
+		    func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS)
+			continue;
+
+		status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
+		if (ACPI_FAILURE(status))
+			warn("find_p2p_bridge failed (error code = 0x%x)\n",
+				status);
 	}
 
 	slot->flags |= SLOT_ENABLED;
@@ -967,6 +1056,18 @@
 
 	list_for_each (l, &slot->funcs) {
 		func = list_entry(l, struct acpiphp_func, sibling);
+
+		if (func->bridge) {
+			/* cleanup p2p bridges under this P2P bridge */
+			cleanup_p2p_bridge(func->bridge->handle,
+						(u32)1, NULL, NULL);
+			func->bridge = NULL;
+		}
+
+		acpiphp_bus_trim(func->handle);
+		/* try to remove anyway.
+		 * acpiphp_bus_add might have been failed */
+
 		if (!func->pci_dev)
 			continue;
 
@@ -1111,16 +1212,17 @@
 			(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
 			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
 		return;
+
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
-			bridge->hpp.cache_line_size);
+			bridge->hpp.t0->cache_line_size);
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER,
-			bridge->hpp.latency_timer);
+			bridge->hpp.t0->latency_timer);
 	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-	if (bridge->hpp.enable_serr)
+	if (bridge->hpp.t0->enable_serr)
 		pci_cmd |= PCI_COMMAND_SERR;
 	else
 		pci_cmd &= ~PCI_COMMAND_SERR;
-	if (bridge->hpp.enable_perr)
+	if (bridge->hpp.t0->enable_perr)
 		pci_cmd |= PCI_COMMAND_PARITY;
 	else
 		pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -1129,13 +1231,13 @@
 	/* Program bridge control value and child devices */
 	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
 		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
-				bridge->hpp.latency_timer);
+				bridge->hpp.t0->latency_timer);
 		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
-		if (bridge->hpp.enable_serr)
+		if (bridge->hpp.t0->enable_serr)
 			pci_bctl |= PCI_BRIDGE_CTL_SERR;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
-		if (bridge->hpp.enable_perr)
+		if (bridge->hpp.t0->enable_perr)
 			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
@@ -1155,6 +1257,7 @@
 
 	memset(&bridge, 0, sizeof(bridge));
 	bridge.handle = handle;
+	bridge.pci_bus = bus;
 	bridge.pci_dev = bus->self;
 	decode_hpp(&bridge);
 	list_for_each_entry(dev, &bus->devices, bus_list)
@@ -1297,6 +1400,13 @@
 	case ACPI_NOTIFY_EJECT_REQUEST:
 		/* request device eject */
 		dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);
+		if ((bridge->type != BRIDGE_TYPE_HOST) &&
+		    (bridge->flags & BRIDGE_HAS_EJ0)) {
+			struct acpiphp_slot *slot;
+			slot = bridge->func->slot;
+			if (!acpiphp_disable_slot(slot))
+				acpiphp_eject_slot(slot);
+		}
 		break;
 
 	case ACPI_NOTIFY_FREQUENCY_MISMATCH:
@@ -1490,9 +1600,15 @@
 	if (retval)
 		goto err_exit;
 
-	if (get_slot_status(slot) == ACPI_STA_ALL)
+	if (get_slot_status(slot) == ACPI_STA_ALL) {
 		/* configure all functions */
 		retval = enable_device(slot);
+		if (retval)
+			power_off_slot(slot);
+	} else {
+		dbg("%s: Slot status is not ACPI_STA_ALL\n", __FUNCTION__);
+		power_off_slot(slot);
+	}
 
  err_exit:
 	mutex_unlock(&slot->crit_sect);
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index e13d5b8..5939294 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -285,7 +285,7 @@
 					(ulong) hotplug_slot, (ulong) value);
         
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -315,7 +315,7 @@
 	debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
 					(ulong) hotplug_slot, (ulong) value);
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -342,7 +342,7 @@
 	debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
 					(ulong) hotplug_slot, (ulong) value);
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -369,7 +369,7 @@
 	debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
 					(ulong) hotplug_slot, (ulong) value);
 	ibmphp_lock_operations();
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			memcpy(&myslot, pslot, sizeof(struct slot));
@@ -401,7 +401,7 @@
 
 	ibmphp_lock_operations();
 
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			rc = 0;
@@ -441,7 +441,7 @@
 
 	ibmphp_lock_operations();
 
-	if (hotplug_slot && value) {
+	if (hotplug_slot) {
 		pslot = hotplug_slot->private;
 		if (pslot) {
 			rc = get_cur_bus_info(&pslot);
diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h
index eb0d01d..e929b7c 100644
--- a/drivers/pci/hotplug/pci_hotplug.h
+++ b/drivers/pci/hotplug/pci_hotplug.h
@@ -176,11 +176,51 @@
 					 struct hotplug_slot_info *info);
 extern struct subsystem pci_hotplug_slots_subsys;
 
+/* PCI Setting Record (Type 0) */
+struct hpp_type0 {
+	u32 revision;
+	u8  cache_line_size;
+	u8  latency_timer;
+	u8  enable_serr;
+	u8  enable_perr;
+};
+
+/* PCI-X Setting Record (Type 1) */
+struct hpp_type1 {
+	u32 revision;
+	u8  max_mem_read;
+	u8  avg_max_split;
+	u16 tot_max_split;
+};
+
+/* PCI Express Setting Record (Type 2) */
+struct hpp_type2 {
+	u32 revision;
+	u32 unc_err_mask_and;
+	u32 unc_err_mask_or;
+	u32 unc_err_sever_and;
+	u32 unc_err_sever_or;
+	u32 cor_err_mask_and;
+	u32 cor_err_mask_or;
+	u32 adv_err_cap_and;
+	u32 adv_err_cap_or;
+	u16 pci_exp_devctl_and;
+	u16 pci_exp_devctl_or;
+	u16 pci_exp_lnkctl_and;
+	u16 pci_exp_lnkctl_or;
+	u32 sec_unc_err_sever_and;
+	u32 sec_unc_err_sever_or;
+	u32 sec_unc_err_mask_and;
+	u32 sec_unc_err_mask_or;
+};
+
 struct hotplug_params {
-	u8 cache_line_size;
-	u8 latency_timer;
-	u8 enable_serr;
-	u8 enable_perr;
+	struct hpp_type0 *t0;		/* Type0: NULL if not available */
+	struct hpp_type1 *t1;		/* Type1: NULL if not available */
+	struct hpp_type2 *t2;		/* Type2: NULL if not available */
+	struct hpp_type0 type0_data;
+	struct hpp_type1 type1_data;
+	struct hpp_type2 type2_data;
 };
 
 #ifdef CONFIG_ACPI
@@ -188,7 +228,7 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/actypes.h>
 extern acpi_status acpi_run_oshp(acpi_handle handle);
-extern acpi_status acpi_get_hp_params_from_firmware(struct pci_dev *dev,
+extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus,
 				struct hotplug_params *hpp);
 int acpi_root_bridge(acpi_handle handle);
 #endif
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 92c1f0f..ce89f58 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -284,7 +284,7 @@
 static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
 			struct hotplug_params *hpp)
 {
-	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
 		return -ENODEV;
 	return 0;
 }
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 601cf90..c67b7c3 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -69,6 +69,7 @@
 static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
 static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
+static int get_address		(struct hotplug_slot *slot, u32 *value);
 static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 
@@ -81,6 +82,7 @@
 	.get_attention_status =	get_attention_status,
 	.get_latch_status =	get_latch_status,
 	.get_adapter_status =	get_adapter_status,
+	.get_address =		get_address,
   	.get_max_bus_speed =	get_max_bus_speed,
   	.get_cur_bus_speed =	get_cur_bus_speed,
 };
@@ -331,6 +333,18 @@
 	return 0;
 }
 
+static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)
+{
+	struct slot *slot = hotplug_slot->private;
+	struct pci_bus *bus = slot->ctrl->pci_dev->subordinate;
+
+	dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
+
+	*value = (pci_domain_nr(bus) << 16) | (slot->bus << 8) | slot->device;
+
+	return 0;
+}
+
 static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 {
 	struct slot *slot = hotplug_slot->private;
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 6c14d9e..d77138e 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -1288,7 +1288,7 @@
 		if (ACPI_SUCCESS(status)) {
 			dbg("Gained control for hotplug HW for pci %s (%s)\n",
 				pci_name(dev), (char *)string.pointer);
-			acpi_os_free(string.pointer);
+			kfree(string.pointer);
 			return 0;
 		}
 		if (acpi_root_bridge(handle))
@@ -1302,7 +1302,7 @@
 	err("Cannot get control of hotplug hardware for pci %s\n",
 			pci_name(dev));
 
-	acpi_os_free(string.pointer);
+	kfree(string.pointer);
 	return -1;
 }
 #endif
@@ -1404,9 +1404,6 @@
 	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, 
 		pdev->subsystem_vendor, pdev->subsystem_device);
 
-	if (pci_enable_device(pdev))
-		goto abort_free_ctlr;
-	
 	mutex_init(&ctrl->crit_sect);
 	/* setup wait queue */
 	init_waitqueue_head(&ctrl->queue);
@@ -1474,7 +1471,7 @@
 	rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
 	if (rc) {
 		err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_free_irq;
 	}
 
 	intr_enable = intr_enable | PRSN_DETECT_ENABLE;
@@ -1500,19 +1497,19 @@
 	rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
 	if (rc) {
 		err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_free_irq;
 	}
 	rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
 	if (rc) {
 		err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_disable_intr;
 	}
 	
 	temp_word =  0x1F; /* Clear all events */
 	rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
 	if (rc) {
 		err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
-		goto abort_free_ctlr;
+		goto abort_disable_intr;
 	}
 	
 	if (pciehp_force) {
@@ -1521,7 +1518,7 @@
 	} else {
 		rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
 		if (rc)
-			goto abort_free_ctlr;
+			goto abort_disable_intr;
 	}
 
 	/*  Add this HPC instance into the HPC list */
@@ -1548,6 +1545,21 @@
 	return 0;
 
 	/* We end up here for the many possible ways to fail this API.  */
+abort_disable_intr:
+	rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
+	if (!rc) {
+		temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+		rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
+	}
+	if (rc)
+		err("%s : disabling interrupts failed\n", __FUNCTION__);
+
+abort_free_irq:
+	if (pciehp_poll_mode)
+		del_timer_sync(&php_ctlr->int_poll_timer);
+	else
+		free_irq(php_ctlr->irq, ctrl);
+
 abort_free_ctlr:
 	pcie_cap_base = saved_cap_base;
 	kfree(php_ctlr);
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 4017fb0..854aaea 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -34,6 +34,144 @@
 #include "../pci.h"
 #include "pciehp.h"
 
+static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
+{
+	u16 pci_cmd, pci_bctl;
+
+	if (hpp->revision > 1) {
+		printk(KERN_WARNING "%s: Rev.%d type0 record not supported\n",
+		       __FUNCTION__, hpp->revision);
+		return;
+	}
+
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer);
+	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+	if (hpp->enable_serr)
+		pci_cmd |= PCI_COMMAND_SERR;
+	else
+		pci_cmd &= ~PCI_COMMAND_SERR;
+	if (hpp->enable_perr)
+		pci_cmd |= PCI_COMMAND_PARITY;
+	else
+		pci_cmd &= ~PCI_COMMAND_PARITY;
+	pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+
+	/* Program bridge control value */
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
+				      hpp->latency_timer);
+		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
+		if (hpp->enable_serr)
+			pci_bctl |= PCI_BRIDGE_CTL_SERR;
+		else
+			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
+		if (hpp->enable_perr)
+			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
+		else
+			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
+		pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);
+	}
+}
+
+static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
+{
+	int pos;
+	u16 reg16;
+	u32 reg32;
+
+	if (hpp->revision > 1) {
+		printk(KERN_WARNING "%s: Rev.%d type2 record not supported\n",
+		       __FUNCTION__, hpp->revision);
+		return;
+	}
+
+	/* Find PCI Express capability */
+	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+	if (!pos)
+		return;
+
+	/* Initialize Device Control Register */
+	pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &reg16);
+	reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or;
+	pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16);
+
+	/* Initialize Link Control Register */
+	if (dev->subordinate) {
+		pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &reg16);
+		reg16 = (reg16 & hpp->pci_exp_lnkctl_and)
+			| hpp->pci_exp_lnkctl_or;
+		pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16);
+	}
+
+	/* Find Advanced Error Reporting Enhanced Capability */
+	pos = 256;
+	do {
+		pci_read_config_dword(dev, pos, &reg32);
+		if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
+			break;
+	} while ((pos = PCI_EXT_CAP_NEXT(reg32)));
+	if (!pos)
+		return;
+
+	/* Initialize Uncorrectable Error Mask Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &reg32);
+	reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32);
+
+	/* Initialize Uncorrectable Error Severity Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &reg32);
+	reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32);
+
+	/* Initialize Correctable Error Mask Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg32);
+	reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32);
+
+	/* Initialize Advanced Error Capabilities and Control Register */
+	pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+	reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or;
+	pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+	/*
+	 * FIXME: The following two registers are not supported yet.
+	 *
+	 *   o Secondary Uncorrectable Error Severity Register
+	 *   o Secondary Uncorrectable Error Mask Register
+	 */
+}
+
+static void program_fw_provided_values(struct pci_dev *dev)
+{
+	struct pci_dev *cdev;
+	struct hotplug_params hpp;
+
+	/* Program hpp values for this device */
+	if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||
+			(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
+			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+		return;
+
+	if (pciehp_get_hp_params_from_firmware(dev, &hpp)) {
+		printk(KERN_WARNING "%s: Could not get hotplug parameters\n",
+		       __FUNCTION__);
+		return;
+	}
+
+	if (hpp.t2)
+		program_hpp_type2(dev, hpp.t2);
+	if (hpp.t0)
+		program_hpp_type0(dev, hpp.t0);
+
+	/* Program child devices */
+	if (dev->subordinate) {
+		list_for_each_entry(cdev, &dev->subordinate->devices,
+				    bus_list)
+			program_fw_provided_values(cdev);
+	}
+}
+
 static int pciehp_add_bridge(struct pci_dev *dev)
 {
 	struct pci_bus *parent = dev->bus;
@@ -66,10 +204,11 @@
 	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 	int num, fn;
 
-	dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+	dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
 	if (dev) {
 		err("Device %s already exists at %x:%x, cannot hot-add\n",
 				pci_name(dev), p_slot->bus, p_slot->device);
+		pci_dev_put(dev);
 		return -EINVAL;
 	}
 
@@ -86,14 +225,15 @@
 		if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
 			err("Cannot hot-add display device %s\n",
 					pci_name(dev));
+			pci_dev_put(dev);
 			continue;
 		}
 		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
 				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
 			pciehp_add_bridge(dev);
 		}
-		/* TBD: program firmware provided _HPP values */
-		/* program_fw_provided_values(dev); */
+		program_fw_provided_values(dev);
+		pci_dev_put(dev);
 	}
 
 	pci_bus_assign_resources(parent);
@@ -106,18 +246,20 @@
 	int rc = 0;
 	int j;
 	u8 bctl = 0;
+	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 
 	dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
 				p_slot->device);
 
 	for (j=0; j<8 ; j++) {
-		struct pci_dev* temp = pci_find_slot(p_slot->bus,
+		struct pci_dev* temp = pci_get_slot(parent,
 				(p_slot->device << 3) | j);
 		if (!temp)
 			continue;
 		if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
 			err("Cannot remove display device %s\n",
 					pci_name(temp));
+			pci_dev_put(temp);
 			continue;
 		}
 		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
@@ -125,10 +267,12 @@
 			if (bctl & PCI_BRIDGE_CTL_VGA) {
 				err("Cannot remove display device %s\n",
 						pci_name(temp));
+				pci_dev_put(temp);
 				continue;
 			}
 		}
 		pci_remove_bus_device(temp);
+		pci_dev_put(temp);
 	}
 	/* 
 	 * Some PCI Express root ports require fixup after hot-plug operation.
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 8cb9abd..f31d83c 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -18,11 +18,13 @@
 #include <linux/mutex.h>
 
 #include <asm/sn/addrs.h>
+#include <asm/sn/geo.h>
 #include <asm/sn/l1.h>
 #include <asm/sn/module.h>
 #include <asm/sn/pcibr_provider.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
+#include <asm/sn/sn_feature_sets.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/types.h>
 
@@ -102,8 +104,7 @@
 static int sn_pci_slot_valid(struct pci_bus *pci_bus, int device)
 {
 	struct pcibus_info *pcibus_info;
-	int bricktype;
-	int bus_num;
+	u16 busnum, segment, ioboard_type;
 
 	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
 
@@ -111,12 +112,14 @@
 	if (!(pcibus_info->pbi_valid_devices & (1 << device)))
 		return -EPERM;
 
-	bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
-	bus_num = pcibus_info->pbi_buscommon.bs_persist_busnum & 0xf;
+	ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
+	busnum = pcibus_info->pbi_buscommon.bs_persist_busnum;
+	segment = pci_domain_nr(pci_bus) & 0xf;
 
 	/* Do not allow hotplug operations on base I/O cards */
-	if ((bricktype == L1_BRICKTYPE_IX ||  bricktype == L1_BRICKTYPE_IA) &&
-	    (bus_num == 1 && device != 1))
+	if ((ioboard_type == L1_BRICKTYPE_IX ||
+	     ioboard_type == L1_BRICKTYPE_IA) &&
+	    (segment == 1 && busnum == 0 && device != 1))
 		return -EPERM;
 
 	return 1;
@@ -125,23 +128,23 @@
 static int sn_pci_bus_valid(struct pci_bus *pci_bus)
 {
 	struct pcibus_info *pcibus_info;
-	int asic_type;
-	int bricktype;
-
-	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
+	u32 asic_type;
+	u16 ioboard_type;
 
 	/* Don't register slots hanging off the TIOCA bus */
+	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(pci_bus);
 	asic_type = pcibus_info->pbi_buscommon.bs_asic_type;
 	if (asic_type == PCIIO_ASIC_TYPE_TIOCA)
 		return -EPERM;
 
 	/* Only register slots in I/O Bricks that support hotplug */
-	bricktype = MODULE_GET_BTYPE(pcibus_info->pbi_moduleid);
-	switch (bricktype) {
+	ioboard_type = sn_ioboard_to_pci_bus(pci_bus);
+	switch (ioboard_type) {
 		case L1_BRICKTYPE_IX:
 		case L1_BRICKTYPE_PX:
 		case L1_BRICKTYPE_IA:
 		case L1_BRICKTYPE_PA:
+		case L1_BOARDTYPE_PCIX3SLOT:
 			return 1;
 			break;
 		default:
@@ -175,14 +178,11 @@
 	slot->pci_bus = pci_bus;
 	sprintf(bss_hotplug_slot->name, "%04x:%02x:%02x",
 		pci_domain_nr(pci_bus),
-		((int)pcibus_info->pbi_buscommon.bs_persist_busnum) & 0xf,
+		((u16)pcibus_info->pbi_buscommon.bs_persist_busnum),
 		device + 1);
-	sprintf(slot->physical_path, "module_%c%c%c%c%.2d",
-		'0'+RACK_GET_CLASS(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
-		'0'+RACK_GET_GROUP(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
-		'0'+RACK_GET_NUM(MODULE_GET_RACK(pcibus_info->pbi_moduleid)),
-		MODULE_GET_BTCHAR(pcibus_info->pbi_moduleid),
-		MODULE_GET_BPOS(pcibus_info->pbi_moduleid));
+
+	sn_generate_path(pci_bus, slot->physical_path);
+
 	slot->hotplug_slot = bss_hotplug_slot;
 	list_add(&slot->hp_list, &sn_hp_list);
 
@@ -461,10 +461,12 @@
 {
 	struct slot *slot = bss_hotplug_slot->private;
 	struct pcibus_info *pcibus_info;
+	u32 power;
 
 	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);
 	mutex_lock(&sn_hotplug_mutex);
-	*value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
+	power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);
+	*value = power ? 1 : 0;
 	mutex_unlock(&sn_hotplug_mutex);
 	return 0;
 }
@@ -553,8 +555,8 @@
 	int rc;
 	int registered = 0;
 
-	if (sn_sal_rev() < SGI_HOTPLUG_PROM_REV) {
-		printk(KERN_ERR "%s: PROM version must be greater than 4.30\n",
+	if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) {
+		printk(KERN_ERR "%s: PROM version does not support hotplug.\n",
 		       __FUNCTION__);
 		return -EPERM;
 	}
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 5c70f43..7208b95 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -168,9 +168,9 @@
  * error Messages
  */
 #define msg_initialization_err	"Initialization failure, error=%d\n"
-#define msg_button_on		"PCI slot #%d - powering on due to button press.\n"
-#define msg_button_off		"PCI slot #%d - powering off due to button press.\n"
-#define msg_button_cancel	"PCI slot #%d - action canceled due to button press.\n"
+#define msg_button_on		"PCI slot #%s - powering on due to button press.\n"
+#define msg_button_off		"PCI slot #%s - powering off due to button press.\n"
+#define msg_button_cancel	"PCI slot #%s - action canceled due to button press.\n"
 
 /* sysfs functions for the hotplug controller info */
 extern void shpchp_create_ctrl_files	(struct controller *ctrl);
@@ -196,7 +196,7 @@
 static inline int get_hp_params_from_firmware(struct pci_dev *dev,
 			struct hotplug_params *hpp)
 {
-	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev, hpp)))
+	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
 			return -ENODEV;
 	return 0;
 }
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 3be4d49..a14e7de 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -491,16 +491,9 @@
 	shpchp_poll_mode = 1;
 #endif
 
-	shpchp_wq = create_singlethread_workqueue("shpchpd");
-	if (!shpchp_wq)
-		return -ENOMEM;
-
 	retval = pci_register_driver(&shpc_driver);
 	dbg("%s: pci_register_driver = %d\n", __FUNCTION__, retval);
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	if (retval) {
-		destroy_workqueue(shpchp_wq);
-	}
 	return retval;
 }
 
@@ -508,7 +501,6 @@
 {
 	dbg("unload_shpchpd()\n");
 	pci_unregister_driver(&shpc_driver);
-	destroy_workqueue(shpchp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 4e63814..c39901d 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -72,7 +72,7 @@
 	/*
 	 *  Button pressed - See if need to TAKE ACTION!!!
 	 */
-	info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot);
+	info("Button pressed on Slot(%s)\n", p_slot->name);
 	event_type = INT_BUTTON_PRESS;
 
 	queue_interrupt_event(p_slot, event_type);
@@ -101,7 +101,7 @@
 		/*
 		 * Switch opened
 		 */
-		info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Latch open on Slot(%s)\n", p_slot->name);
 		event_type = INT_SWITCH_OPEN;
 		if (p_slot->pwr_save && p_slot->presence_save) {
 			event_type = INT_POWER_FAULT;
@@ -111,7 +111,7 @@
 		/*
 		 *  Switch closed
 		 */
-		info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Latch close on Slot(%s)\n", p_slot->name);
 		event_type = INT_SWITCH_CLOSE;
 	}
 
@@ -139,13 +139,13 @@
 		/*
 		 * Card Present
 		 */
-		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Card present on Slot(%s)\n", p_slot->name);
 		event_type = INT_PRESENCE_ON;
 	} else {
 		/*
 		 * Not Present
 		 */
-		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Card not present on Slot(%s)\n", p_slot->name);
 		event_type = INT_PRESENCE_OFF;
 	}
 
@@ -169,14 +169,14 @@
 		/*
 		 * Power fault Cleared
 		 */
-		info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Power fault cleared on Slot(%s)\n", p_slot->name);
 		p_slot->status = 0x00;
 		event_type = INT_POWER_FAULT_CLEAR;
 	} else {
 		/*
 		 *   Power fault
 		 */
-		info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
+		info("Power fault on Slot(%s)\n", p_slot->name);
 		event_type = INT_POWER_FAULT;
 		/* set power fault status for this board */
 		p_slot->status = 0xFF;
@@ -496,10 +496,10 @@
 		p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 		if (getstatus) {
 			p_slot->state = BLINKINGOFF_STATE;
-			info(msg_button_off, p_slot->number);
+			info(msg_button_off, p_slot->name);
 		} else {
 			p_slot->state = BLINKINGON_STATE;
-			info(msg_button_on, p_slot->number);
+			info(msg_button_on, p_slot->name);
 		}
 		/* blink green LED and turn off amber */
 		p_slot->hpc_ops->green_led_blink(p_slot);
@@ -522,7 +522,7 @@
 		else
 			p_slot->hpc_ops->green_led_off(p_slot);
 		p_slot->hpc_ops->set_attention_status(p_slot, 0);
-		info(msg_button_cancel, p_slot->number);
+		info(msg_button_cancel, p_slot->name);
 		p_slot->state = STATIC_STATE;
 		break;
 	case POWEROFF_STATE:
@@ -575,17 +575,17 @@
 	mutex_lock(&p_slot->ctrl->crit_sect);
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
-		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("No adapter on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (rc || getstatus) {
-		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Latch open on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (rc || getstatus) {
-		info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Already enabled on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 
@@ -634,17 +634,17 @@
 
 	rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
-		info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("No adapter on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
 	if (rc || getstatus) {
-		info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Latch open on slot(%s)\n", p_slot->name);
 		goto out;
 	}
 	rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
 	if (rc || !getstatus) {
-		info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
+		info("Already disabled slot(%s)\n", p_slot->name);
 		goto out;
 	}
 
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 66123cf..45facaa 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -90,77 +90,94 @@
 #define	MRLSENSOR		0x40000000
 #define ATTN_BUTTON		0x80000000
 
-/* Slot Status Field Definitions */
-/* Slot State */
-#define PWR_ONLY		0x0001
-#define ENABLED			0x0002
-#define DISABLED		0x0003
+/*
+ * Interrupt Locator Register definitions
+ */
+#define CMD_INTR_PENDING	(1 << 0)
+#define SLOT_INTR_PENDING(i)	(1 << (i + 1))
 
-/* Power Indicator State */
-#define PWR_LED_ON		0x0004
-#define PWR_LED_BLINK		0x0008
-#define PWR_LED_OFF		0x000c
+/*
+ * Controller SERR-INT Register
+ */
+#define GLOBAL_INTR_MASK	(1 << 0)
+#define GLOBAL_SERR_MASK	(1 << 1)
+#define COMMAND_INTR_MASK	(1 << 2)
+#define ARBITER_SERR_MASK	(1 << 3)
+#define COMMAND_DETECTED	(1 << 16)
+#define ARBITER_DETECTED	(1 << 17)
+#define SERR_INTR_RSVDZ_MASK	0xfffc0000
 
-/* Attention Indicator State */
-#define ATTEN_LED_ON		0x0010
-#define	ATTEN_LED_BLINK		0x0020
-#define ATTEN_LED_OFF		0x0030
+/*
+ * Logical Slot Register definitions
+ */
+#define SLOT_REG(i)		(SLOT1 + (4 * i))
 
-/* Power Fault */
-#define pwr_fault		0x0040
+#define SLOT_STATE_SHIFT	(0)
+#define SLOT_STATE_MASK		(3 << 0)
+#define SLOT_STATE_PWRONLY	(1)
+#define SLOT_STATE_ENABLED	(2)
+#define SLOT_STATE_DISABLED	(3)
+#define PWR_LED_STATE_SHIFT	(2)
+#define PWR_LED_STATE_MASK	(3 << 2)
+#define ATN_LED_STATE_SHIFT	(4)
+#define ATN_LED_STATE_MASK	(3 << 4)
+#define ATN_LED_STATE_ON	(1)
+#define ATN_LED_STATE_BLINK	(2)
+#define ATN_LED_STATE_OFF	(3)
+#define POWER_FAULT		(1 << 6)
+#define ATN_BUTTON		(1 << 7)
+#define MRL_SENSOR		(1 << 8)
+#define MHZ66_CAP		(1 << 9)
+#define PRSNT_SHIFT		(10)
+#define PRSNT_MASK		(3 << 10)
+#define PCIX_CAP_SHIFT		(12)
+#define PCIX_CAP_MASK_PI1	(3 << 12)
+#define PCIX_CAP_MASK_PI2	(7 << 12)
+#define PRSNT_CHANGE_DETECTED	(1 << 16)
+#define ISO_PFAULT_DETECTED	(1 << 17)
+#define BUTTON_PRESS_DETECTED	(1 << 18)
+#define MRL_CHANGE_DETECTED	(1 << 19)
+#define CON_PFAULT_DETECTED	(1 << 20)
+#define PRSNT_CHANGE_INTR_MASK	(1 << 24)
+#define ISO_PFAULT_INTR_MASK	(1 << 25)
+#define BUTTON_PRESS_INTR_MASK	(1 << 26)
+#define MRL_CHANGE_INTR_MASK	(1 << 27)
+#define CON_PFAULT_INTR_MASK	(1 << 28)
+#define MRL_CHANGE_SERR_MASK	(1 << 29)
+#define CON_PFAULT_SERR_MASK	(1 << 30)
+#define SLOT_REG_RSVDZ_MASK	(1 << 15) | (7 << 21)
 
-/* Attention Button */
-#define ATTEN_BUTTON		0x0080
-
-/* MRL Sensor */
-#define MRL_SENSOR		0x0100
-
-/* 66 MHz Capable */
-#define IS_66MHZ_CAP		0x0200
-
-/* PRSNT1#/PRSNT2# */
-#define SLOT_EMP		0x0c00
-
-/* PCI-X Capability */
-#define NON_PCIX		0x0000
-#define PCIX_66			0x1000
-#define PCIX_133		0x3000
-#define PCIX_266		0x4000  /* For PI = 2 only */
-#define PCIX_533		0x5000	/* For PI = 2 only */
-
-/* SHPC 'write' operations/commands */
-
-/* Slot operation - 0x00h to 0x3Fh */
-
-#define NO_CHANGE		0x00
-
-/* Slot state - Bits 0 & 1 of controller command register */
-#define SET_SLOT_PWR		0x01	
-#define SET_SLOT_ENABLE		0x02	
-#define SET_SLOT_DISABLE	0x03	
-
-/* Power indicator state - Bits 2 & 3 of controller command register*/
-#define SET_PWR_ON		0x04	
-#define SET_PWR_BLINK		0x08	
-#define SET_PWR_OFF		0x0C	
-
-/* Attention indicator state - Bits 4 & 5 of controller command register*/
-#define SET_ATTN_ON		0x010	
-#define SET_ATTN_BLINK		0x020
-#define SET_ATTN_OFF		0x030	
-
-/* Set bus speed/mode A - 0x40h to 0x47h */
-#define SETA_PCI_33MHZ		0x40
+/*
+ * SHPC Command Code definitnions
+ *
+ *     Slot Operation				00h - 3Fh
+ *     Set Bus Segment Speed/Mode A		40h - 47h
+ *     Power-Only All Slots			48h
+ *     Enable All Slots				49h
+ *     Set Bus Segment Speed/Mode B (PI=2)	50h - 5Fh
+ *     Reserved Command Codes			60h - BFh
+ *     Vendor Specific Commands			C0h - FFh
+ */
+#define SET_SLOT_PWR		0x01	/* Slot Operation */
+#define SET_SLOT_ENABLE		0x02
+#define SET_SLOT_DISABLE	0x03
+#define SET_PWR_ON		0x04
+#define SET_PWR_BLINK		0x08
+#define SET_PWR_OFF		0x0c
+#define SET_ATTN_ON		0x10
+#define SET_ATTN_BLINK		0x20
+#define SET_ATTN_OFF		0x30
+#define SETA_PCI_33MHZ		0x40	/* Set Bus Segment Speed/Mode A */
 #define SETA_PCI_66MHZ		0x41
 #define SETA_PCIX_66MHZ		0x42
 #define SETA_PCIX_100MHZ	0x43
 #define SETA_PCIX_133MHZ	0x44
-#define RESERV_1		0x45
-#define RESERV_2		0x46
-#define RESERV_3		0x47
-
-/* Set bus speed/mode B - 0x50h to 0x5fh */
-#define	SETB_PCI_33MHZ		0x50
+#define SETA_RESERVED1		0x45
+#define SETA_RESERVED2		0x46
+#define SETA_RESERVED3		0x47
+#define SET_PWR_ONLY_ALL	0x48	/* Power-Only All Slots */
+#define SET_ENABLE_ALL		0x49	/* Enable All Slots */
+#define	SETB_PCI_33MHZ		0x50	/* Set Bus Segment Speed/Mode B */
 #define SETB_PCI_66MHZ		0x51
 #define SETB_PCIX_66MHZ_PM	0x52
 #define SETB_PCIX_100MHZ_PM	0x53
@@ -174,81 +191,115 @@
 #define SETB_PCIX_66MHZ_533	0x5b
 #define SETB_PCIX_100MHZ_533	0x5c
 #define SETB_PCIX_133MHZ_533	0x5d
+#define SETB_RESERVED1		0x5e
+#define SETB_RESERVED2		0x5f
 
-
-/* Power-on all slots - 0x48h */
-#define SET_PWR_ON_ALL		0x48
-
-/* Enable all slots	- 0x49h */
-#define SET_ENABLE_ALL		0x49
-
-/*  SHPC controller command error code */
+/*
+ * SHPC controller command error code
+ */
 #define SWITCH_OPEN		0x1
 #define INVALID_CMD		0x2
 #define INVALID_SPEED_MODE	0x4
 
-/* For accessing SHPC Working Register Set */
+/*
+ * For accessing SHPC Working Register Set via PCI Configuration Space
+ */
 #define DWORD_SELECT		0x2
 #define DWORD_DATA		0x4
-#define BASE_OFFSET		0x0
 
 /* Field Offset in Logical Slot Register - byte boundary */
 #define SLOT_EVENT_LATCH	0x2
 #define SLOT_SERR_INT_MASK	0x3
 
-static spinlock_t hpc_event_lock;
-
 DEFINE_DBG_BUFFER		/* Debug string buffer for entire HPC defined here */
 static struct php_ctlr_state_s *php_ctlr_list_head;	/* HPC state linked list */
 static int ctlr_seq_num = 0;	/* Controller sequenc # */
 static spinlock_t list_lock;
 
-static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs);
+static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
 
-static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds);
+static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs);
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec);
 static int hpc_check_cmd_status(struct controller *ctrl);
 
-/* This is the interrupt polling timeout function. */
-static void int_poll_timeout(unsigned long lphp_ctlr)
+static inline u8 shpc_readb(struct controller *ctrl, int reg)
 {
-    struct php_ctlr_state_s *php_ctlr = (struct php_ctlr_state_s *)lphp_ctlr;
-
-    DBG_ENTER_ROUTINE
-
-    if ( !php_ctlr ) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return;
-    }
-
-    /* Poll for interrupt events.  regs == NULL => polling */
-    shpc_isr( 0, (void *)php_ctlr, NULL );
-
-    init_timer(&php_ctlr->int_poll_timer);
-	if (!shpchp_poll_time)
-		shpchp_poll_time = 2; /* reset timer to poll in 2 secs if user doesn't specify at module installation*/
-
-    start_int_poll_timer(php_ctlr, shpchp_poll_time);  
-	
-	return;
+	return readb(ctrl->hpc_ctlr_handle->creg + reg);
 }
 
-/* This function starts the interrupt polling timer. */
-static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int seconds)
+static inline void shpc_writeb(struct controller *ctrl, int reg, u8 val)
 {
-    if (!php_ctlr) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return;
-	}
+	writeb(val, ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-    if ( ( seconds <= 0 ) || ( seconds > 60 ) )
-        seconds = 2;            /* Clamp to sane value */
+static inline u16 shpc_readw(struct controller *ctrl, int reg)
+{
+	return readw(ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-    php_ctlr->int_poll_timer.function = &int_poll_timeout;
-    php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;    /* Instance data */
-    php_ctlr->int_poll_timer.expires = jiffies + seconds * HZ;
-    add_timer(&php_ctlr->int_poll_timer);
+static inline void shpc_writew(struct controller *ctrl, int reg, u16 val)
+{
+	writew(val, ctrl->hpc_ctlr_handle->creg + reg);
+}
 
-	return;
+static inline u32 shpc_readl(struct controller *ctrl, int reg)
+{
+	return readl(ctrl->hpc_ctlr_handle->creg + reg);
+}
+
+static inline void shpc_writel(struct controller *ctrl, int reg, u32 val)
+{
+	writel(val, ctrl->hpc_ctlr_handle->creg + reg);
+}
+
+static inline int shpc_indirect_read(struct controller *ctrl, int index,
+				     u32 *value)
+{
+	int rc;
+	u32 cap_offset = ctrl->cap_offset;
+	struct pci_dev *pdev = ctrl->pci_dev;
+
+	rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
+	if (rc)
+		return rc;
+	return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
+}
+
+/*
+ * This is the interrupt polling timeout function.
+ */
+static void int_poll_timeout(unsigned long lphp_ctlr)
+{
+	struct php_ctlr_state_s *php_ctlr =
+		(struct php_ctlr_state_s *)lphp_ctlr;
+
+	DBG_ENTER_ROUTINE
+
+	/* Poll for interrupt events.  regs == NULL => polling */
+	shpc_isr(0, php_ctlr->callback_instance_id, NULL);
+
+	init_timer(&php_ctlr->int_poll_timer);
+	if (!shpchp_poll_time)
+		shpchp_poll_time = 2; /* default polling interval is 2 sec */
+
+	start_int_poll_timer(php_ctlr, shpchp_poll_time);
+
+	DBG_LEAVE_ROUTINE
+}
+
+/*
+ * This function starts the interrupt polling timer.
+ */
+static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec)
+{
+	/* Clamp to sane value */
+	if ((sec <= 0) || (sec > 60))
+		sec = 2;
+
+	php_ctlr->int_poll_timer.function = &int_poll_timeout;
+	php_ctlr->int_poll_timer.data = (unsigned long)php_ctlr;
+	php_ctlr->int_poll_timer.expires = jiffies + sec * HZ;
+	add_timer(&php_ctlr->int_poll_timer);
 }
 
 static inline int shpc_wait_cmd(struct controller *ctrl)
@@ -272,7 +323,7 @@
 
 static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u16 cmd_status;
 	int retval = 0;
 	u16 temp_word;
@@ -282,14 +333,8 @@
 
 	mutex_lock(&slot->ctrl->cmd_lock);
 
-	if (!php_ctlr) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		retval = -EINVAL;
-		goto out;
-	}
-
 	for (i = 0; i < 10; i++) {
-		cmd_status = readw(php_ctlr->creg + CMD_STATUS);
+		cmd_status = shpc_readw(ctrl, CMD_STATUS);
 		
 		if (!(cmd_status & 0x1))
 			break;
@@ -297,7 +342,7 @@
 		msleep(100);
 	}
 
-	cmd_status = readw(php_ctlr->creg + CMD_STATUS);
+	cmd_status = shpc_readw(ctrl, CMD_STATUS);
 	
 	if (cmd_status & 0x1) { 
 		/* After 1 sec and and the controller is still busy */
@@ -314,7 +359,7 @@
 	 * command. 
 	 */
 	slot->ctrl->cmd_busy = 1;
-	writew(temp_word, php_ctlr->creg + CMD);
+	shpc_writew(ctrl, CMD, temp_word);
 
 	/*
 	 * Wait for command completion.
@@ -338,18 +383,12 @@
 
 static int hpc_check_cmd_status(struct controller *ctrl)
 {
-	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	u16 cmd_status;
 	int retval = 0;
 
 	DBG_ENTER_ROUTINE 
-	
-	if (!ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
 
-	cmd_status = readw(php_ctlr->creg + CMD_STATUS) & 0x000F;
+	cmd_status = shpc_readw(ctrl, CMD_STATUS) & 0x000F;
 	
 	switch (cmd_status >> 1) {
 	case 0:
@@ -378,37 +417,27 @@
 
 static int hpc_get_attention_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 atten_led_state;
+	u8 state;
 	
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	state = (slot_reg & ATN_LED_STATE_MASK) >> ATN_LED_STATE_SHIFT;
 
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16) slot_reg;
-	atten_led_state = (slot_status & 0x0030) >> 4;
-
-	switch (atten_led_state) {
-	case 0:
-		*status = 0xFF;	/* Reserved */
-		break;
-	case 1:
+	switch (state) {
+	case ATN_LED_STATE_ON:
 		*status = 1;	/* On */
 		break;
-	case 2:
+	case ATN_LED_STATE_BLINK:
 		*status = 2;	/* Blink */
 		break;
-	case 3:
+	case ATN_LED_STATE_OFF:
 		*status = 0;	/* Off */
 		break;
 	default:
-		*status = 0xFF;
+		*status = 0xFF;	/* Reserved */
 		break;
 	}
 
@@ -418,64 +447,44 @@
 
 static int hpc_get_power_status(struct slot * slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 slot_state;
-	int	retval = 0;
+	u8 state;
 	
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	state = (slot_reg & SLOT_STATE_MASK) >> SLOT_STATE_SHIFT;
 
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16) slot_reg;
-	slot_state = (slot_status & 0x0003);
-
-	switch (slot_state) {
-	case 0:
-		*status = 0xFF;
-		break;
-	case 1:
+	switch (state) {
+	case SLOT_STATE_PWRONLY:
 		*status = 2;	/* Powered only */
 		break;
-	case 2:
+	case SLOT_STATE_ENABLED:
 		*status = 1;	/* Enabled */
 		break;
-	case 3:
+	case SLOT_STATE_DISABLED:
 		*status = 0;	/* Disabled */
 		break;
 	default:
-		*status = 0xFF;
+		*status = 0xFF;	/* Reserved */
 		break;
 	}
 
 	DBG_LEAVE_ROUTINE 
-	return retval;
+	return 0;
 }
 
 
 static int hpc_get_latch_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16)slot_reg;
-
-	*status = ((slot_status & 0x0100) == 0) ? 0 : 1;   /* 0 -> close; 1 -> open */
-
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	*status = !!(slot_reg & MRL_SENSOR);	/* 0 -> close; 1 -> open */
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -483,22 +492,15 @@
 
 static int hpc_get_adapter_status(struct slot *slot, u8 *status)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 card_state;
+	u8 state;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16)slot_reg;
-	card_state = (u8)((slot_status & 0x0C00) >> 10);
-	*status = (card_state != 0x3) ? 1 : 0;
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	state = (slot_reg & PRSNT_MASK) >> PRSNT_SHIFT;
+	*status = (state != 0x3) ? 1 : 0;
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -506,16 +508,11 @@
 
 static int hpc_get_prog_int(struct slot *slot, u8 *prog_int)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 
 	DBG_ENTER_ROUTINE 
-	
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
 
-	*prog_int = readb(php_ctlr->creg + PROG_INTERFACE);
+	*prog_int = shpc_readb(ctrl, PROG_INTERFACE);
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -524,13 +521,27 @@
 static int hpc_get_adapter_speed(struct slot *slot, enum pci_bus_speed *value)
 {
 	int retval = 0;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u32 slot_reg = readl(php_ctlr->creg + SLOT1 + 4 * slot->hp_slot);
-	u8 pcix_cap = (slot_reg >> 12) & 7;
-	u8 m66_cap  = (slot_reg >> 9) & 1;
+	struct controller *ctrl = slot->ctrl;
+	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
+	u8 m66_cap  = !!(slot_reg & MHZ66_CAP);
+	u8 pi, pcix_cap;
 
 	DBG_ENTER_ROUTINE 
 
+	if ((retval = hpc_get_prog_int(slot, &pi)))
+		return retval;
+
+	switch (pi) {
+	case 1:
+		pcix_cap = (slot_reg & PCIX_CAP_MASK_PI1) >> PCIX_CAP_SHIFT;
+		break;
+	case 2:
+		pcix_cap = (slot_reg & PCIX_CAP_MASK_PI2) >> PCIX_CAP_SHIFT;
+		break;
+	default:
+		return -ENODEV;
+	}
+
 	dbg("%s: slot_reg = %x, pcix_cap = %x, m66_cap = %x\n",
 	    __FUNCTION__, slot_reg, pcix_cap, m66_cap);
 
@@ -564,20 +575,15 @@
 
 static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u16 sec_bus_status;
 	u8 pi;
 	int retval = 0;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	sec_bus_status = readw(php_ctlr->creg + SEC_BUS_CONFIG);
+	pi = shpc_readb(ctrl, PROG_INTERFACE);
+	sec_bus_status = shpc_readw(ctrl, SEC_BUS_CONFIG);
 
 	if (pi == 2) {
 		*mode = (sec_bus_status & 0x0100) >> 8;
@@ -593,128 +599,53 @@
 
 static int hpc_query_power_fault(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u32 slot_reg;
-	u16 slot_status;
-	u8 pwr_fault_state, status;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	slot_reg = readl(php_ctlr->creg + SLOT1 + 4*(slot->hp_slot));
-	slot_status = (u16) slot_reg;
-	pwr_fault_state = (slot_status & 0x0040) >> 7;
-	status = (pwr_fault_state == 1) ? 0 : 1;
+	slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
 
 	DBG_LEAVE_ROUTINE
 	/* Note: Logic 0 => fault */
-	return status;
+	return !(slot_reg & POWER_FAULT);
 }
 
 static int hpc_set_attention_status(struct slot *slot, u8 value)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
 	u8 slot_cmd = 0;
-	int rc = 0;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
 
 	switch (value) {
 		case 0 :	
-			slot_cmd = 0x30;	/* OFF */
+			slot_cmd = SET_ATTN_OFF;	/* OFF */
 			break;
 		case 1:
-			slot_cmd = 0x10;	/* ON */
+			slot_cmd = SET_ATTN_ON;		/* ON */
 			break;
 		case 2:
-			slot_cmd = 0x20;	/* BLINK */
+			slot_cmd = SET_ATTN_BLINK;	/* BLINK */
 			break;
 		default:
 			return -1;
 	}
 
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-	
-	return rc;
+	return shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
 }
 
 
 static void hpc_set_green_led_on(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return ;
-	}
-
-	slot_cmd = 0x04;
-
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
-	return;
+	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_ON);
 }
 
 static void hpc_set_green_led_off(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return ;
-	}
-
-	slot_cmd = 0x0C;
-
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
-	return;
+	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_OFF);
 }
 
 static void hpc_set_green_led_blink(struct slot *slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return ;
-	}
-
-	slot_cmd = 0x08;
-
-	shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
-	return;
+	shpc_write_cmd(slot, slot->hp_slot, SET_PWR_BLINK);
 }
 
 int shpc_get_ctlr_slot_config(struct controller *ctrl,
@@ -724,21 +655,17 @@
 	int *updown,		/* physical_slot_num increament: 1 or -1	*/
 	int *flags)
 {
-	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
+	u32 slot_config;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
+	slot_config = shpc_readl(ctrl, SLOT_CONFIG);
+	*first_device_num = (slot_config & FIRST_DEV_NUM) >> 8;
+	*num_ctlr_slots = slot_config & SLOT_NUM;
+	*physical_slot_num = (slot_config & PSN) >> 16;
+	*updown = ((slot_config & UPDOWN) >> 29) ? 1 : -1;
 
-	*first_device_num = php_ctlr->slot_device_offset;	/* Obtained in shpc_init() */
-	*num_ctlr_slots = php_ctlr->num_slots;			/* Obtained in shpc_init() */
-
-	*physical_slot_num = (readl(php_ctlr->creg + SLOT_CONFIG) & PSN) >> 16;
 	dbg("%s: physical_slot_num = %x\n", __FUNCTION__, *physical_slot_num);
-	*updown = ((readl(php_ctlr->creg + SLOT_CONFIG) & UPDOWN ) >> 29) ? 1 : -1;	
 
 	DBG_LEAVE_ROUTINE 
 	return 0;
@@ -749,22 +676,34 @@
 	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
 	struct php_ctlr_state_s *p, *p_prev;
 	int i;
+	u32 slot_reg, serr_int;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return ;
+	/*
+	 * Mask event interrupts and SERRs of all slots
+	 */
+	for (i = 0; i < ctrl->num_slots; i++) {
+		slot_reg = shpc_readl(ctrl, SLOT_REG(i));
+		slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+			     BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+			     CON_PFAULT_INTR_MASK   | MRL_CHANGE_SERR_MASK |
+			     CON_PFAULT_SERR_MASK);
+		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
+		shpc_writel(ctrl, SLOT_REG(i), slot_reg);
 	}
 
-	/*
-	 * Mask all slot event interrupts
-	 */
-	for (i = 0; i < ctrl->num_slots; i++)
-		writel(0xffff3fff, php_ctlr->creg + SLOT1 + (4 * i));
-
 	cleanup_slots(ctrl);
 
+	/*
+	 * Mask SERR and System Interrut generation
+	 */
+	serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+	serr_int |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
+		     COMMAND_INTR_MASK | ARBITER_SERR_MASK);
+	serr_int &= ~SERR_INTR_RSVDZ_MASK;
+	shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
+
 	if (shpchp_poll_mode) {
 	    del_timer(&php_ctlr->int_poll_timer);
 	} else {	
@@ -800,113 +739,79 @@
 
 	kfree(php_ctlr);
 
+	/*
+	 * If this is the last controller to be released, destroy the
+	 * shpchpd work queue
+	 */
+	if (atomic_dec_and_test(&shpchp_num_controllers))
+		destroy_workqueue(shpchp_wq);
+
 DBG_LEAVE_ROUTINE
 			  
 }
 
 static int hpc_power_on_slot(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-	int retval = 0;
+	int retval;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-	slot_cmd = 0x01;
-
-	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
+	retval = shpc_write_cmd(slot, slot->hp_slot, SET_SLOT_PWR);
 	if (retval) {
 		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
+		return retval;
 	}
 
 	DBG_LEAVE_ROUTINE
 
-	return retval;
+	return 0;
 }
 
 static int hpc_slot_enable(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-	int retval = 0;
+	int retval;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-	/* 3A => Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
-	slot_cmd = 0x3A;  
-
-	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
+	/* Slot - Enable, Power Indicator - Blink, Attention Indicator - Off */
+	retval = shpc_write_cmd(slot, slot->hp_slot,
+			SET_SLOT_ENABLE | SET_PWR_BLINK | SET_ATTN_OFF);
 	if (retval) {
 		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
+		return retval;
 	}
 
 	DBG_LEAVE_ROUTINE
-	return retval;
+	return 0;
 }
 
 static int hpc_slot_disable(struct slot * slot)
 {
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
-	u8 slot_cmd;
-	int retval = 0;
+	int retval;
 
 	DBG_ENTER_ROUTINE 
 
-	if (!slot->ctrl->hpc_ctlr_handle) {
-		err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
-		return -1;
-	}
-
-	if (slot->hp_slot >= php_ctlr->num_slots) {
-		err("%s: Invalid HPC slot number!\n", __FUNCTION__);
-		return -1;
-	}
-
-	/* 1F => Slot - Disable, Power Indicator - Off, Attention Indicator - On */
-	slot_cmd = 0x1F;
-
-	retval = shpc_write_cmd(slot, slot->hp_slot, slot_cmd);
-
+	/* Slot - Disable, Power Indicator - Off, Attention Indicator - On */
+	retval = shpc_write_cmd(slot, slot->hp_slot,
+			SET_SLOT_DISABLE | SET_PWR_OFF | SET_ATTN_ON);
 	if (retval) {
 		err("%s: Write command failed!\n", __FUNCTION__);
-		return -1;
+		return retval;
 	}
 
 	DBG_LEAVE_ROUTINE
-	return retval;
+	return 0;
 }
 
 static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 {
 	int retval;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	u8 pi, cmd;
 
 	DBG_ENTER_ROUTINE 
 
-	pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	pi = shpc_readb(ctrl, PROG_INTERFACE);
 	if ((pi == 1) && (value > PCI_SPEED_133MHz_PCIX))
 		return -EINVAL;
 
@@ -965,100 +870,86 @@
 	return retval;
 }
 
-static irqreturn_t shpc_isr(int IRQ, void *dev_id, struct pt_regs *regs)
+static irqreturn_t shpc_isr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct controller *ctrl = NULL;
-	struct php_ctlr_state_s *php_ctlr;
-	u8 schedule_flag = 0;
-	u8 temp_byte;
-	u32 temp_dword, intr_loc, intr_loc2;
+	struct controller *ctrl = (struct controller *)dev_id;
+	struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
+	u32 serr_int, slot_reg, intr_loc, intr_loc2;
 	int hp_slot;
 
-	if (!dev_id)
-		return IRQ_NONE;
-
-	if (!shpchp_poll_mode) { 
-		ctrl = (struct controller *)dev_id;
-		php_ctlr = ctrl->hpc_ctlr_handle;
-	} else { 
-		php_ctlr = (struct php_ctlr_state_s *) dev_id;
-		ctrl = (struct controller *)php_ctlr->callback_instance_id;
-	}
-
-	if (!ctrl)
-		return IRQ_NONE;
-	
-	if (!php_ctlr || !php_ctlr->creg)
-		return IRQ_NONE;
-
 	/* Check to see if it was our interrupt */
-	intr_loc = readl(php_ctlr->creg + INTR_LOC);  
-
+	intr_loc = shpc_readl(ctrl, INTR_LOC);
 	if (!intr_loc)
 		return IRQ_NONE;
+
 	dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 
 
 	if(!shpchp_poll_mode) {
-		/* Mask Global Interrupt Mask - see implementation note on p. 139 */
-		/* of SHPC spec rev 1.0*/
-		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		temp_dword |= 0x00000001;
-		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+		/*
+		 * Mask Global Interrupt Mask - see implementation
+		 * note on p. 139 of SHPC spec rev 1.0
+		 */
+		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		serr_int |= GLOBAL_INTR_MASK;
+		serr_int &= ~SERR_INTR_RSVDZ_MASK;
+		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
 
-		intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
+		intr_loc2 = shpc_readl(ctrl, INTR_LOC);
 		dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
 	}
 
-	if (intr_loc & 0x0001) {
+	if (intr_loc & CMD_INTR_PENDING) {
 		/* 
 		 * Command Complete Interrupt Pending 
 		 * RO only - clear by writing 1 to the Command Completion
 		 * Detect bit in Controller SERR-INT register
 		 */
-		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		temp_dword &= 0xfffdffff;
-		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		serr_int &= ~SERR_INTR_RSVDZ_MASK;
+		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
+
 		ctrl->cmd_busy = 0;
 		wake_up_interruptible(&ctrl->queue);
 	}
 
-	if ((intr_loc = (intr_loc >> 1)) == 0)
+	if (!(intr_loc & ~CMD_INTR_PENDING))
 		goto out;
 
 	for (hp_slot = 0; hp_slot < ctrl->num_slots; hp_slot++) { 
-	/* To find out which slot has interrupt pending */
-		if ((intr_loc >> hp_slot) & 0x01) {
-			temp_dword = readl(php_ctlr->creg + SLOT1 + (4*hp_slot));
-			dbg("%s: Slot %x with intr, slot register = %x\n",
-				__FUNCTION__, hp_slot, temp_dword);
-			temp_byte = (temp_dword >> 16) & 0xFF;
-			if ((php_ctlr->switch_change_callback) && (temp_byte & 0x08))
-				schedule_flag += php_ctlr->switch_change_callback(
-					hp_slot, php_ctlr->callback_instance_id);
-			if ((php_ctlr->attention_button_callback) && (temp_byte & 0x04))
-				schedule_flag += php_ctlr->attention_button_callback(
-					hp_slot, php_ctlr->callback_instance_id);
-			if ((php_ctlr->presence_change_callback) && (temp_byte & 0x01))
-				schedule_flag += php_ctlr->presence_change_callback(
-					hp_slot , php_ctlr->callback_instance_id);
-			if ((php_ctlr->power_fault_callback) && (temp_byte & 0x12))
-				schedule_flag += php_ctlr->power_fault_callback(
-					hp_slot, php_ctlr->callback_instance_id);
-			
-			/* Clear all slot events */
-			temp_dword = 0xe01f3fff;
-			writel(temp_dword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+		/* To find out which slot has interrupt pending */
+		if (!(intr_loc & SLOT_INTR_PENDING(hp_slot)))
+			continue;
 
-			intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
-			dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
-		}
+		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
+		dbg("%s: Slot %x with intr, slot register = %x\n",
+		    __FUNCTION__, hp_slot, slot_reg);
+
+		if (slot_reg & MRL_CHANGE_DETECTED)
+			php_ctlr->switch_change_callback(
+				hp_slot, php_ctlr->callback_instance_id);
+
+		if (slot_reg & BUTTON_PRESS_DETECTED)
+			php_ctlr->attention_button_callback(
+				hp_slot, php_ctlr->callback_instance_id);
+
+		if (slot_reg & PRSNT_CHANGE_DETECTED)
+			php_ctlr->presence_change_callback(
+				hp_slot , php_ctlr->callback_instance_id);
+
+		if (slot_reg & (ISO_PFAULT_DETECTED | CON_PFAULT_DETECTED))
+			php_ctlr->power_fault_callback(
+				hp_slot, php_ctlr->callback_instance_id);
+
+		/* Clear all slot events */
+		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
+		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
 	}
  out:
 	if (!shpchp_poll_mode) {
 		/* Unmask Global Interrupt Mask */
-		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		temp_dword &= 0xfffffffe;
-		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+		serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		serr_int &= ~(GLOBAL_INTR_MASK | SERR_INTR_RSVDZ_MASK);
+		shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int);
 	}
 	
 	return IRQ_HANDLED;
@@ -1067,11 +958,11 @@
 static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	int retval = 0;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
-	u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
-	u32 slot_avail1 = readl(php_ctlr->creg + SLOT_AVAIL1);
-	u32 slot_avail2 = readl(php_ctlr->creg + SLOT_AVAIL2);
+	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
+	u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1);
+	u32 slot_avail2 = shpc_readl(ctrl, SLOT_AVAIL2);
 
 	DBG_ENTER_ROUTINE 
 
@@ -1114,10 +1005,10 @@
 static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 {
 	int retval = 0;
-	struct php_ctlr_state_s *php_ctlr = slot->ctrl->hpc_ctlr_handle;
+	struct controller *ctrl = slot->ctrl;
 	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
-	u16 sec_bus_reg = readw(php_ctlr->creg + SEC_BUS_CONFIG);
-	u8 pi = readb(php_ctlr->creg + PROG_INTERFACE);
+	u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG);
+	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
 	u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
 
 	DBG_ENTER_ROUTINE 
@@ -1206,28 +1097,14 @@
 	.release_ctlr			= hpc_release_ctlr,
 };
 
-inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
-					  u32 *value)
-{
-	int rc;
-	u32 cap_offset = ctrl->cap_offset;
-	struct pci_dev *pdev = ctrl->pci_dev;
-
-	rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
-	if (rc)
-		return rc;
-	return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
-}
-
 int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
 {
 	struct php_ctlr_state_s *php_ctlr, *p;
 	void *instance_id = ctrl;
 	int rc, num_slots = 0;
 	u8 hp_slot;
-	static int first = 1;
 	u32 shpc_base_offset;
-	u32 tempdword, slot_reg;
+	u32 tempdword, slot_reg, slot_config;
 	u8 i;
 
 	DBG_ENTER_ROUTINE
@@ -1257,13 +1134,13 @@
 		}
 		dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);
 
-		rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset);
+		rc = shpc_indirect_read(ctrl, 0, &shpc_base_offset);
 		if (rc) {
 			err("%s: cannot read base_offset\n", __FUNCTION__);
 			goto abort_free_ctlr;
 		}
 
-		rc = shpc_indirect_creg_read(ctrl, 3, &tempdword);
+		rc = shpc_indirect_read(ctrl, 3, &tempdword);
 		if (rc) {
 			err("%s: cannot read slot config\n", __FUNCTION__);
 			goto abort_free_ctlr;
@@ -1272,7 +1149,7 @@
 		dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);
 
 		for (i = 0; i < 9 + num_slots; i++) {
-			rc = shpc_indirect_creg_read(ctrl, i, &tempdword);
+			rc = shpc_indirect_read(ctrl, i, &tempdword);
 			if (rc) {
 				err("%s: cannot read creg (index = %d)\n",
 				    __FUNCTION__, i);
@@ -1287,11 +1164,6 @@
 		ctrl->mmio_size = 0x24 + 0x4 * num_slots;
 	}
 
-	if (first) {
-		spin_lock_init(&hpc_event_lock);
-		first = 0;
-	}
-
 	info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, 
 		pdev->subsystem_device);
 	
@@ -1326,29 +1198,39 @@
 	php_ctlr->power_fault_callback = shpchp_handle_power_fault;
 	php_ctlr->callback_instance_id = instance_id;
 
+	ctrl->hpc_ctlr_handle = php_ctlr;
+	ctrl->hpc_ops = &shpchp_hpc_ops;
+
 	/* Return PCI Controller Info */
-	php_ctlr->slot_device_offset = (readl(php_ctlr->creg + SLOT_CONFIG) & FIRST_DEV_NUM ) >> 8;
-	php_ctlr->num_slots = readl(php_ctlr->creg + SLOT_CONFIG) & SLOT_NUM;
+	slot_config = shpc_readl(ctrl, SLOT_CONFIG);
+	php_ctlr->slot_device_offset = (slot_config & FIRST_DEV_NUM) >> 8;
+	php_ctlr->num_slots = slot_config & SLOT_NUM;
 	dbg("%s: slot_device_offset %x\n", __FUNCTION__, php_ctlr->slot_device_offset);
 	dbg("%s: num_slots %x\n", __FUNCTION__, php_ctlr->num_slots);
 
 	/* Mask Global Interrupt Mask & Command Complete Interrupt Mask */
-	tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
 	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
-	tempdword = 0x0003000f;   
-	writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE);
-	tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+	tempdword |= (GLOBAL_INTR_MASK  | GLOBAL_SERR_MASK |
+		      COMMAND_INTR_MASK | ARBITER_SERR_MASK);
+	tempdword &= ~SERR_INTR_RSVDZ_MASK;
+	shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+	tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
 	dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
 
 	/* Mask the MRL sensor SERR Mask of individual slot in
 	 * Slot SERR-INT Mask & clear all the existing event if any
 	 */
 	for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
-		slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot );
+		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
 		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
 			hp_slot, slot_reg);
-		tempdword = 0xffff3fff;  
-		writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+		slot_reg |= (PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+			     BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+			     CON_PFAULT_INTR_MASK   | MRL_CHANGE_SERR_MASK |
+			     CON_PFAULT_SERR_MASK);
+		slot_reg &= ~SLOT_REG_RSVDZ_MASK;
+		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
 	}
 	
 	if (shpchp_poll_mode)  {/* Install interrupt polling code */
@@ -1392,24 +1274,37 @@
 	}
 	spin_unlock(&list_lock);
 
-
 	ctlr_seq_num++;
-	ctrl->hpc_ctlr_handle = php_ctlr;
-	ctrl->hpc_ops = &shpchp_hpc_ops;
 
+	/*
+	 * If this is the first controller to be initialized,
+	 * initialize the shpchpd work queue
+	 */
+	if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
+		shpchp_wq = create_singlethread_workqueue("shpchpd");
+		if (!shpchp_wq)
+			return -ENOMEM;
+	}
+
+	/*
+	 * Unmask all event interrupts of all slots
+	 */
 	for (hp_slot = 0; hp_slot < php_ctlr->num_slots; hp_slot++) {
-		slot_reg = readl(php_ctlr->creg + SLOT1 + 4*hp_slot );
+		slot_reg = shpc_readl(ctrl, SLOT_REG(hp_slot));
 		dbg("%s: Default Logical Slot Register %d value %x\n", __FUNCTION__,
 			hp_slot, slot_reg);
-		tempdword = 0xe01f3fff;  
-		writel(tempdword, php_ctlr->creg + SLOT1 + (4*hp_slot));
+		slot_reg &= ~(PRSNT_CHANGE_INTR_MASK | ISO_PFAULT_INTR_MASK |
+			      BUTTON_PRESS_INTR_MASK | MRL_CHANGE_INTR_MASK |
+			      CON_PFAULT_INTR_MASK | SLOT_REG_RSVDZ_MASK);
+		shpc_writel(ctrl, SLOT_REG(hp_slot), slot_reg);
 	}
 	if (!shpchp_poll_mode) {
 		/* Unmask all general input interrupts and SERR */
-		tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-		tempdword = 0x0000000a;
-		writel(tempdword, php_ctlr->creg + SERR_INTR_ENABLE);
-		tempdword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
+		tempdword &= ~(GLOBAL_INTR_MASK | COMMAND_INTR_MASK |
+			       SERR_INTR_RSVDZ_MASK);
+		shpc_writel(ctrl, SERR_INTR_ENABLE, tempdword);
+		tempdword = shpc_readl(ctrl, SERR_INTR_ENABLE);
 		dbg("%s: SERR_INTR_ENABLE = %x\n", __FUNCTION__, tempdword);
 	}
 
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index 257adc2..0a6b25e 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -47,21 +47,28 @@
 		return;
 
 	/* use default values if we can't get them from firmware */
-	if (get_hp_params_from_firmware(dev, &hpp)) {
-		hpp.cache_line_size = 8;
-		hpp.latency_timer = 0x40;
-		hpp.enable_serr = 0;
-		hpp.enable_perr = 0;
+	if (get_hp_params_from_firmware(dev, &hpp) ||
+	    !hpp.t0 || (hpp.t0->revision > 1)) {
+		printk(KERN_WARNING
+		       "%s: Could not get hotplug parameters. Use defaults\n",
+		       __FUNCTION__);
+		hpp.t0 = &hpp.type0_data;
+		hpp.t0->revision = 0;
+		hpp.t0->cache_line_size = 8;
+		hpp.t0->latency_timer = 0x40;
+		hpp.t0->enable_serr = 0;
+		hpp.t0->enable_perr = 0;
 	}
 
-	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp.cache_line_size);
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.latency_timer);
+	pci_write_config_byte(dev,
+			      PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer);
 	pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
-	if (hpp.enable_serr)
+	if (hpp.t0->enable_serr)
 		pci_cmd |= PCI_COMMAND_SERR;
 	else
 		pci_cmd &= ~PCI_COMMAND_SERR;
-	if (hpp.enable_perr)
+	if (hpp.t0->enable_perr)
 		pci_cmd |= PCI_COMMAND_PARITY;
 	else
 		pci_cmd &= ~PCI_COMMAND_PARITY;
@@ -70,13 +77,13 @@
 	/* Program bridge control value and child devices */
 	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
 		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,
-				hpp.latency_timer);
+				hpp.t0->latency_timer);
 		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);
-		if (hpp.enable_serr)
+		if (hpp.t0->enable_serr)
 			pci_bctl |= PCI_BRIDGE_CTL_SERR;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_SERR;
-		if (hpp.enable_perr)
+		if (hpp.t0->enable_perr)
 			pci_bctl |= PCI_BRIDGE_CTL_PARITY;
 		else
 			pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;
diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c
new file mode 100644
index 0000000..bed4183
--- /dev/null
+++ b/drivers/pci/msi-altix.c
@@ -0,0 +1,210 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/cpumask.h>
+
+#include <asm/sn/addrs.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/nodepda.h>
+
+#include "msi.h"
+
+struct sn_msi_info {
+	u64 pci_addr;
+	struct sn_irq_info *sn_irq_info;
+};
+
+static struct sn_msi_info *sn_msi_info;
+
+static void
+sn_msi_teardown(unsigned int vector)
+{
+	nasid_t nasid;
+	int widget;
+	struct pci_dev *pdev;
+	struct pcidev_info *sn_pdev;
+	struct sn_irq_info *sn_irq_info;
+	struct pcibus_bussoft *bussoft;
+	struct sn_pcibus_provider *provider;
+
+	sn_irq_info = sn_msi_info[vector].sn_irq_info;
+	if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+		return;
+
+	sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+	pdev = sn_pdev->pdi_linux_pcidev;
+	provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+	(*provider->dma_unmap)(pdev,
+			       sn_msi_info[vector].pci_addr,
+			       PCI_DMA_FROMDEVICE);
+	sn_msi_info[vector].pci_addr = 0;
+
+	bussoft = SN_PCIDEV_BUSSOFT(pdev);
+	nasid = NASID_GET(bussoft->bs_base);
+	widget = (nasid & 1) ?
+			TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+			SWIN_WIDGETNUM(bussoft->bs_base);
+
+	sn_intr_free(nasid, widget, sn_irq_info);
+	sn_msi_info[vector].sn_irq_info = NULL;
+
+	return;
+}
+
+int
+sn_msi_setup(struct pci_dev *pdev, unsigned int vector,
+	     u32 *addr_hi, u32 *addr_lo, u32 *data)
+{
+	int widget;
+	int status;
+	nasid_t nasid;
+	u64 bus_addr;
+	struct sn_irq_info *sn_irq_info;
+	struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
+	struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+	if (bussoft == NULL)
+		return -EINVAL;
+
+	if (provider == NULL || provider->dma_map_consistent == NULL)
+		return -EINVAL;
+
+	/*
+	 * Set up the vector plumbing.  Let the prom (via sn_intr_alloc)
+	 * decide which cpu to direct this msi at by default.
+	 */
+
+	nasid = NASID_GET(bussoft->bs_base);
+	widget = (nasid & 1) ?
+			TIO_SWIN_WIDGETNUM(bussoft->bs_base) :
+			SWIN_WIDGETNUM(bussoft->bs_base);
+
+	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+	if (! sn_irq_info)
+		return -ENOMEM;
+
+	status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1);
+	if (status) {
+		kfree(sn_irq_info);
+		return -ENOMEM;
+	}
+
+	sn_irq_info->irq_int_bit = -1;		/* mark this as an MSI irq */
+	sn_irq_fixup(pdev, sn_irq_info);
+
+	/* Prom probably should fill these in, but doesn't ... */
+	sn_irq_info->irq_bridge_type = bussoft->bs_asic_type;
+	sn_irq_info->irq_bridge = (void *)bussoft->bs_base;
+
+	/*
+	 * Map the xio address into bus space
+	 */
+	bus_addr = (*provider->dma_map_consistent)(pdev,
+					sn_irq_info->irq_xtalkaddr,
+					sizeof(sn_irq_info->irq_xtalkaddr),
+					SN_DMA_MSI|SN_DMA_ADDR_XIO);
+	if (! bus_addr) {
+		sn_intr_free(nasid, widget, sn_irq_info);
+		kfree(sn_irq_info);
+		return -ENOMEM;
+	}
+
+	sn_msi_info[vector].sn_irq_info = sn_irq_info;
+	sn_msi_info[vector].pci_addr = bus_addr;
+
+	*addr_hi = (u32)(bus_addr >> 32);
+	*addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+
+	/*
+	 * In the SN platform, bit 16 is a "send vector" bit which
+	 * must be present in order to move the vector through the system.
+	 */
+	*data = 0x100 + (unsigned int)vector;
+
+#ifdef CONFIG_SMP
+	set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0);
+#endif
+
+	return 0;
+}
+
+static void
+sn_msi_target(unsigned int vector, unsigned int cpu,
+	      u32 *addr_hi, u32 *addr_lo)
+{
+	int slice;
+	nasid_t nasid;
+	u64 bus_addr;
+	struct pci_dev *pdev;
+	struct pcidev_info *sn_pdev;
+	struct sn_irq_info *sn_irq_info;
+	struct sn_irq_info *new_irq_info;
+	struct sn_pcibus_provider *provider;
+
+	sn_irq_info = sn_msi_info[vector].sn_irq_info;
+	if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
+		return;
+
+	/*
+	 * Release XIO resources for the old MSI PCI address
+	 */
+
+        sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+	pdev = sn_pdev->pdi_linux_pcidev;
+	provider = SN_PCIDEV_BUSPROVIDER(pdev);
+
+	bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo);
+	(*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
+	sn_msi_info[vector].pci_addr = 0;
+
+	nasid = cpuid_to_nasid(cpu);
+	slice = cpuid_to_slice(cpu);
+
+	new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
+	sn_msi_info[vector].sn_irq_info = new_irq_info;
+	if (new_irq_info == NULL)
+		return;
+
+	/*
+	 * Map the xio address into bus space
+	 */
+
+	bus_addr = (*provider->dma_map_consistent)(pdev,
+					new_irq_info->irq_xtalkaddr,
+					sizeof(new_irq_info->irq_xtalkaddr),
+					SN_DMA_MSI|SN_DMA_ADDR_XIO);
+
+	sn_msi_info[vector].pci_addr = bus_addr;
+	*addr_hi = (u32)(bus_addr >> 32);
+	*addr_lo = (u32)(bus_addr & 0x00000000ffffffff);
+}
+
+struct msi_ops sn_msi_ops = {
+	.setup = sn_msi_setup,
+	.teardown = sn_msi_teardown,
+#ifdef CONFIG_SMP
+	.target = sn_msi_target,
+#endif
+};
+
+int
+sn_msi_init(void)
+{
+	sn_msi_info =
+		kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL);
+	if (! sn_msi_info)
+		return -ENOMEM;
+
+	msi_register(&sn_msi_ops);
+	return 0;
+}
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c
new file mode 100644
index 0000000..5ed798b3
--- /dev/null
+++ b/drivers/pci/msi-apic.c
@@ -0,0 +1,101 @@
+/*
+ * MSI hooks for standard x86 apic
+ */
+
+#include <linux/pci.h>
+#include <linux/irq.h>
+#include <asm/smp.h>
+
+#include "msi.h"
+
+/*
+ * Shifts for APIC-based data
+ */
+
+#define MSI_DATA_VECTOR_SHIFT		0
+#define	    MSI_DATA_VECTOR(v)		(((u8)v) << MSI_DATA_VECTOR_SHIFT)
+
+#define MSI_DATA_DELIVERY_SHIFT		8
+#define     MSI_DATA_DELIVERY_FIXED	(0 << MSI_DATA_DELIVERY_SHIFT)
+#define     MSI_DATA_DELIVERY_LOWPRI	(1 << MSI_DATA_DELIVERY_SHIFT)
+
+#define MSI_DATA_LEVEL_SHIFT		14
+#define     MSI_DATA_LEVEL_DEASSERT	(0 << MSI_DATA_LEVEL_SHIFT)
+#define     MSI_DATA_LEVEL_ASSERT	(1 << MSI_DATA_LEVEL_SHIFT)
+
+#define MSI_DATA_TRIGGER_SHIFT		15
+#define     MSI_DATA_TRIGGER_EDGE	(0 << MSI_DATA_TRIGGER_SHIFT)
+#define     MSI_DATA_TRIGGER_LEVEL	(1 << MSI_DATA_TRIGGER_SHIFT)
+
+/*
+ * Shift/mask fields for APIC-based bus address
+ */
+
+#define MSI_ADDR_HEADER			0xfee00000
+
+#define MSI_ADDR_DESTID_MASK		0xfff0000f
+#define     MSI_ADDR_DESTID_CPU(cpu)	((cpu) << MSI_TARGET_CPU_SHIFT)
+
+#define MSI_ADDR_DESTMODE_SHIFT		2
+#define     MSI_ADDR_DESTMODE_PHYS	(0 << MSI_ADDR_DESTMODE_SHIFT)
+#define	    MSI_ADDR_DESTMODE_LOGIC	(1 << MSI_ADDR_DESTMODE_SHIFT)
+
+#define MSI_ADDR_REDIRECTION_SHIFT	3
+#define     MSI_ADDR_REDIRECTION_CPU	(0 << MSI_ADDR_REDIRECTION_SHIFT)
+#define     MSI_ADDR_REDIRECTION_LOWPRI	(1 << MSI_ADDR_REDIRECTION_SHIFT)
+
+
+static void
+msi_target_apic(unsigned int vector,
+		unsigned int dest_cpu,
+		u32 *address_hi,	/* in/out */
+		u32 *address_lo)	/* in/out */
+{
+	u32 addr = *address_lo;
+
+	addr &= MSI_ADDR_DESTID_MASK;
+	addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu));
+
+	*address_lo = addr;
+}
+
+static int
+msi_setup_apic(struct pci_dev *pdev,	/* unused in generic */
+		unsigned int vector,
+		u32 *address_hi,
+		u32 *address_lo,
+		u32 *data)
+{
+	unsigned long	dest_phys_id;
+
+	dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
+
+	*address_hi = 0;
+	*address_lo =	MSI_ADDR_HEADER |
+			MSI_ADDR_DESTMODE_PHYS |
+			MSI_ADDR_REDIRECTION_CPU |
+			MSI_ADDR_DESTID_CPU(dest_phys_id);
+
+	*data = MSI_DATA_TRIGGER_EDGE |
+		MSI_DATA_LEVEL_ASSERT |
+		MSI_DATA_DELIVERY_FIXED |
+		MSI_DATA_VECTOR(vector);
+
+	return 0;
+}
+
+static void
+msi_teardown_apic(unsigned int vector)
+{
+	return;		/* no-op */
+}
+
+/*
+ * Generic ops used on most IA archs/platforms.  Set with msi_register()
+ */
+
+struct msi_ops msi_apic_ops = {
+	.setup = msi_setup_apic,
+	.teardown = msi_teardown_apic,
+	.target = msi_target_apic,
+};
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 9855c4c..7f84292 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -23,8 +23,6 @@
 #include "pci.h"
 #include "msi.h"
 
-#define MSI_TARGET_CPU		first_cpu(cpu_online_map)
-
 static DEFINE_SPINLOCK(msi_lock);
 static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
 static kmem_cache_t* msi_cachep;
@@ -37,9 +35,17 @@
 
 #ifndef CONFIG_X86_IO_APIC
 int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};
-u8 irq_vector[NR_IRQ_VECTORS] = { FIRST_DEVICE_VECTOR , 0 };
 #endif
 
+static struct msi_ops *msi_ops;
+
+int
+msi_register(struct msi_ops *ops)
+{
+	msi_ops = ops;
+	return 0;
+}
+
 static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
 {
 	memset(p, 0, NR_IRQS * sizeof(struct msi_desc));
@@ -92,7 +98,7 @@
 static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
 {
 	struct msi_desc *entry;
-	struct msg_address address;
+	u32 address_hi, address_lo;
 	unsigned int irq = vector;
 	unsigned int dest_cpu = first_cpu(cpu_mask);
 
@@ -108,28 +114,36 @@
 		if (!pos)
 			return;
 
+		pci_read_config_dword(entry->dev, msi_upper_address_reg(pos),
+			&address_hi);
 		pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
-			&address.lo_address.value);
-		address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
-		address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
-									MSI_TARGET_CPU_SHIFT);
-		entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
+			&address_lo);
+
+		msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+		pci_write_config_dword(entry->dev, msi_upper_address_reg(pos),
+			address_hi);
 		pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
-			address.lo_address.value);
+			address_lo);
 		set_native_irq_info(irq, cpu_mask);
 		break;
 	}
 	case PCI_CAP_ID_MSIX:
 	{
-		int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
-			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
+		int offset_hi =
+			entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+				PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET;
+		int offset_lo =
+			entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE +
+				PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET;
 
-		address.lo_address.value = readl(entry->mask_base + offset);
-		address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
-		address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
-									MSI_TARGET_CPU_SHIFT);
-		entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
-		writel(address.lo_address.value, entry->mask_base + offset);
+		address_hi = readl(entry->mask_base + offset_hi);
+		address_lo = readl(entry->mask_base + offset_lo);
+
+		msi_ops->target(vector, dest_cpu, &address_hi, &address_lo);
+
+		writel(address_hi, entry->mask_base + offset_hi);
+		writel(address_lo, entry->mask_base + offset_lo);
 		set_native_irq_info(irq, cpu_mask);
 		break;
 	}
@@ -251,30 +265,6 @@
 	.set_affinity	= set_msi_affinity
 };
 
-static void msi_data_init(struct msg_data *msi_data,
-			  unsigned int vector)
-{
-	memset(msi_data, 0, sizeof(struct msg_data));
-	msi_data->vector = (u8)vector;
-	msi_data->delivery_mode = MSI_DELIVERY_MODE;
-	msi_data->level = MSI_LEVEL_MODE;
-	msi_data->trigger = MSI_TRIGGER_MODE;
-}
-
-static void msi_address_init(struct msg_address *msi_address)
-{
-	unsigned int	dest_id;
-	unsigned long	dest_phys_id = cpu_physical_id(MSI_TARGET_CPU);
-
-	memset(msi_address, 0, sizeof(struct msg_address));
-	msi_address->hi_address = (u32)0;
-	dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT);
-	msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE;
-	msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
-	msi_address->lo_address.u.dest_id = dest_id;
-	msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT);
-}
-
 static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
 static int assign_msi_vector(void)
 {
@@ -369,13 +359,29 @@
 		return status;
 	}
 
+	status = msi_arch_init();
+	if (status < 0) {
+		pci_msi_enable = 0;
+		printk(KERN_WARNING
+		       "PCI: MSI arch init failed.  MSI disabled.\n");
+		return status;
+	}
+
+	if (! msi_ops) {
+		printk(KERN_WARNING
+		       "PCI: MSI ops not registered. MSI disabled.\n");
+		status = -EINVAL;
+		return status;
+	}
+
+	last_alloc_vector = assign_irq_vector(AUTO_ASSIGN);
 	status = msi_cache_init();
 	if (status < 0) {
 		pci_msi_enable = 0;
 		printk(KERN_WARNING "PCI: MSI cache init failed\n");
 		return status;
 	}
-	last_alloc_vector = assign_irq_vector(AUTO_ASSIGN);
+
 	if (last_alloc_vector < 0) {
 		pci_msi_enable = 0;
 		printk(KERN_WARNING "PCI: No interrupt vectors available for MSI\n");
@@ -442,9 +448,11 @@
 		/* Set enabled bits to single MSI & enable MSI_enable bit */
 		msi_enable(control, 1);
 		pci_write_config_word(dev, msi_control_reg(pos), control);
+		dev->msi_enabled = 1;
 	} else {
 		msix_enable(control);
 		pci_write_config_word(dev, msi_control_reg(pos), control);
+		dev->msix_enabled = 1;
 	}
     	if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
 		/* PCI Express Endpoint device detected */
@@ -461,9 +469,11 @@
 		/* Set enabled bits to single MSI & enable MSI_enable bit */
 		msi_disable(control);
 		pci_write_config_word(dev, msi_control_reg(pos), control);
+		dev->msi_enabled = 0;
 	} else {
 		msix_disable(control);
 		pci_write_config_word(dev, msi_control_reg(pos), control);
+		dev->msix_enabled = 0;
 	}
     	if (pci_find_capability(dev, PCI_CAP_ID_EXP)) {
 		/* PCI Express Endpoint device detected */
@@ -538,7 +548,6 @@
 		pci_read_config_dword(dev, pos + PCI_MSI_DATA_32, &cap[i++]);
 	if (control & PCI_MSI_FLAGS_MASKBIT)
 		pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT, &cap[i++]);
-	disable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
 	save_state->cap_nr = PCI_CAP_ID_MSI;
 	pci_add_saved_cap(dev, save_state);
 	return 0;
@@ -575,6 +584,8 @@
 int pci_save_msix_state(struct pci_dev *dev)
 {
 	int pos;
+	int temp;
+	int vector, head, tail = 0;
 	u16 control;
 	struct pci_cap_saved_state *save_state;
 
@@ -582,6 +593,7 @@
 	if (pos <= 0 || dev->no_msi)
 		return 0;
 
+	/* save the capability */
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
 	if (!(control & PCI_MSIX_FLAGS_ENABLE))
 		return 0;
@@ -593,7 +605,38 @@
 	}
 	*((u16 *)&save_state->data[0]) = control;
 
-	disable_msi_mode(dev, pos, PCI_CAP_ID_MSIX);
+	/* save the table */
+	temp = dev->irq;
+	if (msi_lookup_vector(dev, PCI_CAP_ID_MSIX)) {
+		kfree(save_state);
+		return -EINVAL;
+	}
+
+	vector = head = dev->irq;
+	while (head != tail) {
+		int j;
+		void __iomem *base;
+		struct msi_desc *entry;
+
+		entry = msi_desc[vector];
+		base = entry->mask_base;
+		j = entry->msi_attrib.entry_nr;
+
+		entry->address_lo_save =
+			readl(base + j * PCI_MSIX_ENTRY_SIZE +
+			      PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
+		entry->address_hi_save =
+			readl(base + j * PCI_MSIX_ENTRY_SIZE +
+			      PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
+		entry->data_save =
+			readl(base + j * PCI_MSIX_ENTRY_SIZE +
+			      PCI_MSIX_ENTRY_DATA_OFFSET);
+
+		tail = msi_desc[vector]->link.tail;
+		vector = tail;
+	}
+	dev->irq = temp;
+
 	save_state->cap_nr = PCI_CAP_ID_MSIX;
 	pci_add_saved_cap(dev, save_state);
 	return 0;
@@ -606,8 +649,6 @@
 	int vector, head, tail = 0;
 	void __iomem *base;
 	int j;
-	struct msg_address address;
-	struct msg_data data;
 	struct msi_desc *entry;
 	int temp;
 	struct pci_cap_saved_state *save_state;
@@ -633,20 +674,13 @@
 		base = entry->mask_base;
 		j = entry->msi_attrib.entry_nr;
 
-		msi_address_init(&address);
-		msi_data_init(&data, vector);
-
-		address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
-		address.lo_address.value |= entry->msi_attrib.current_cpu <<
-					MSI_TARGET_CPU_SHIFT;
-
-		writel(address.lo_address.value,
+		writel(entry->address_lo_save,
 			base + j * PCI_MSIX_ENTRY_SIZE +
 			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
-		writel(address.hi_address,
+		writel(entry->address_hi_save,
 			base + j * PCI_MSIX_ENTRY_SIZE +
 			PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
-		writel(*(u32*)&data,
+		writel(entry->data_save,
 			base + j * PCI_MSIX_ENTRY_SIZE +
 			PCI_MSIX_ENTRY_DATA_OFFSET);
 
@@ -660,30 +694,32 @@
 }
 #endif
 
-static void msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
+static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
 {
-	struct msg_address address;
-	struct msg_data data;
+	int status;
+	u32 address_hi;
+	u32 address_lo;
+	u32 data;
 	int pos, vector = dev->irq;
 	u16 control;
 
    	pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
 	pci_read_config_word(dev, msi_control_reg(pos), &control);
+
 	/* Configure MSI capability structure */
-	msi_address_init(&address);
-	msi_data_init(&data, vector);
-	entry->msi_attrib.current_cpu = ((address.lo_address.u.dest_id >>
-				MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
-	pci_write_config_dword(dev, msi_lower_address_reg(pos),
-			address.lo_address.value);
+	status = msi_ops->setup(dev, vector, &address_hi, &address_lo, &data);
+	if (status < 0)
+		return status;
+
+	pci_write_config_dword(dev, msi_lower_address_reg(pos), address_lo);
 	if (is_64bit_address(control)) {
 		pci_write_config_dword(dev,
-			msi_upper_address_reg(pos), address.hi_address);
+			msi_upper_address_reg(pos), address_hi);
 		pci_write_config_word(dev,
-			msi_data_reg(pos, 1), *((u32*)&data));
+			msi_data_reg(pos, 1), data);
 	} else
 		pci_write_config_word(dev,
-			msi_data_reg(pos, 0), *((u32*)&data));
+			msi_data_reg(pos, 0), data);
 	if (entry->msi_attrib.maskbit) {
 		unsigned int maskbits, temp;
 		/* All MSIs are unmasked by default, Mask them all */
@@ -697,6 +733,8 @@
 			msi_mask_bits_reg(pos, is_64bit_address(control)),
 			maskbits);
 	}
+
+	return 0;
 }
 
 /**
@@ -710,6 +748,7 @@
  **/
 static int msi_capability_init(struct pci_dev *dev)
 {
+	int status;
 	struct msi_desc *entry;
 	int pos, vector;
 	u16 control;
@@ -742,7 +781,12 @@
 	/* Replace with MSI handler */
 	irq_handler_init(PCI_CAP_ID_MSI, vector, entry->msi_attrib.maskbit);
 	/* Configure MSI capability structure */
-	msi_register_init(dev, entry);
+	status = msi_register_init(dev, entry);
+	if (status != 0) {
+		dev->irq = entry->msi_attrib.default_vector;
+		kmem_cache_free(msi_cachep, entry);
+		return status;
+	}
 
 	attach_msi_entry(entry, vector);
 	/* Set MSI enabled bits	 */
@@ -765,8 +809,10 @@
 				struct msix_entry *entries, int nvec)
 {
 	struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
-	struct msg_address address;
-	struct msg_data data;
+	u32 address_hi;
+	u32 address_lo;
+	u32 data;
+	int status;
 	int vector, pos, i, j, nr_entries, temp = 0;
 	unsigned long phys_addr;
 	u32 table_offset;
@@ -822,18 +868,20 @@
 		/* Replace with MSI-X handler */
 		irq_handler_init(PCI_CAP_ID_MSIX, vector, 1);
 		/* Configure MSI-X capability structure */
-		msi_address_init(&address);
-		msi_data_init(&data, vector);
-		entry->msi_attrib.current_cpu =
-			((address.lo_address.u.dest_id >>
-			MSI_TARGET_CPU_SHIFT) & MSI_TARGET_CPU_MASK);
-		writel(address.lo_address.value,
+		status = msi_ops->setup(dev, vector,
+					&address_hi,
+					&address_lo,
+					&data);
+		if (status < 0)
+			break;
+
+		writel(address_lo,
 			base + j * PCI_MSIX_ENTRY_SIZE +
 			PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET);
-		writel(address.hi_address,
+		writel(address_hi,
 			base + j * PCI_MSIX_ENTRY_SIZE +
 			PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET);
-		writel(*(u32*)&data,
+		writel(data,
 			base + j * PCI_MSIX_ENTRY_SIZE +
 			PCI_MSIX_ENTRY_DATA_OFFSET);
 		attach_msi_entry(entry, vector);
@@ -865,6 +913,7 @@
  **/
 int pci_enable_msi(struct pci_dev* dev)
 {
+	struct pci_bus *bus;
 	int pos, temp, status = -EINVAL;
 	u16 control;
 
@@ -874,8 +923,9 @@
 	if (dev->no_msi)
 		return status;
 
-	if (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
-		return -EINVAL;
+	for (bus = dev->bus; bus; bus = bus->parent)
+		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+			return -EINVAL;
 
 	temp = dev->irq;
 
@@ -887,23 +937,23 @@
 	if (!pos)
 		return -EINVAL;
 
-	pci_read_config_word(dev, msi_control_reg(pos), &control);
-	if (control & PCI_MSI_FLAGS_ENABLE)
-		return 0;			/* Already in MSI mode */
-
 	if (!msi_lookup_vector(dev, PCI_CAP_ID_MSI)) {
 		/* Lookup Sucess */
 		unsigned long flags;
 
+		pci_read_config_word(dev, msi_control_reg(pos), &control);
+		if (control & PCI_MSI_FLAGS_ENABLE)
+			return 0;	/* Already in MSI mode */
 		spin_lock_irqsave(&msi_lock, flags);
 		if (!vector_irq[dev->irq]) {
 			msi_desc[dev->irq]->msi_attrib.state = 0;
 			vector_irq[dev->irq] = -1;
 			nr_released_vectors--;
 			spin_unlock_irqrestore(&msi_lock, flags);
-			msi_register_init(dev, msi_desc[dev->irq]);
-			enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
-			return 0;
+			status = msi_register_init(dev, msi_desc[dev->irq]);
+			if (status == 0)
+				enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
+			return status;
 		}
 		spin_unlock_irqrestore(&msi_lock, flags);
 		dev->irq = temp;
@@ -980,6 +1030,8 @@
 	void __iomem *base;
 	unsigned long flags;
 
+	msi_ops->teardown(vector);
+
 	spin_lock_irqsave(&msi_lock, flags);
 	entry = msi_desc[vector];
 	if (!entry || entry->dev != dev) {
@@ -1008,33 +1060,8 @@
 				entry_nr * PCI_MSIX_ENTRY_SIZE +
 				PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET);
 
-		if (head == vector) {
-			/*
-			 * Detect last MSI-X vector to be released.
-			 * Release the MSI-X memory-mapped table.
-			 */
-#if 0
-			int pos, nr_entries;
-			unsigned long phys_addr;
-			u32 table_offset;
-			u16 control;
-			u8 bir;
-
-   			pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
-			pci_read_config_word(dev, msi_control_reg(pos),
-				&control);
-			nr_entries = multi_msix_capable(control);
-			pci_read_config_dword(dev, msix_table_offset_reg(pos),
-				&table_offset);
-			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-			table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
-			phys_addr = pci_resource_start(dev, bir) + table_offset;
-/*
- * FIXME!  and what did you want to do with phys_addr?
- */
-#endif
+		if (head == vector)
 			iounmap(base);
-		}
 	}
 
 	return 0;
@@ -1108,6 +1135,7 @@
  **/
 int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 {
+	struct pci_bus *bus;
 	int status, pos, nr_entries, free_vectors;
 	int i, j, temp;
 	u16 control;
@@ -1116,6 +1144,13 @@
 	if (!pci_msi_enable || !dev || !entries)
  		return -EINVAL;
 
+	if (dev->no_msi)
+		return -EINVAL;
+
+	for (bus = dev->bus; bus; bus = bus->parent)
+		if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+			return -EINVAL;
+
 	status = msi_init();
 	if (status < 0)
 		return status;
@@ -1300,24 +1335,6 @@
 		}
 		msi_free_vector(dev, vector, 0);
 		if (warning) {
-			/* Force to release the MSI-X memory-mapped table */
-#if 0
-			unsigned long phys_addr;
-			u32 table_offset;
-			u16 control;
-			u8 bir;
-
-			pci_read_config_word(dev, msi_control_reg(pos),
-				&control);
-			pci_read_config_dword(dev, msix_table_offset_reg(pos),
-				&table_offset);
-			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
-			table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
-			phys_addr = pci_resource_start(dev, bir) + table_offset;
-/*
- * FIXME! and what did you want to do with phys_addr?
- */
-#endif
 			iounmap(base);
 			printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
 			       "called without free_irq() on all MSI-X vectors\n",
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 4ac52d4..56951c3 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -6,6 +6,68 @@
 #ifndef MSI_H
 #define MSI_H
 
+/*
+ * MSI operation vector.  Used by the msi core code (drivers/pci/msi.c)
+ * to abstract platform-specific tasks relating to MSI address generation
+ * and resource management.
+ */
+struct msi_ops {
+	/**
+	 * setup - generate an MSI bus address and data for a given vector
+	 * @pdev: PCI device context (in)
+	 * @vector: vector allocated by the msi core (in)
+	 * @addr_hi: upper 32 bits of PCI bus MSI address (out)
+	 * @addr_lo: lower 32 bits of PCI bus MSI address (out)
+	 * @data: MSI data payload (out)
+	 *
+	 * Description: The setup op is used to generate a PCI bus addres and
+	 * data which the msi core will program into the card MSI capability
+	 * registers.  The setup routine is responsible for picking an initial
+	 * cpu to target the MSI at.  The setup routine is responsible for
+	 * examining pdev to determine the MSI capabilities of the card and
+	 * generating a suitable address/data.  The setup routine is
+	 * responsible for allocating and tracking any system resources it
+	 * needs to route the MSI to the cpu it picks, and for associating
+	 * those resources with the passed in vector.
+	 *
+	 * Returns 0 if the MSI address/data was successfully setup.
+	 **/
+
+	int	(*setup)    (struct pci_dev *pdev, unsigned int vector,
+			     u32 *addr_hi, u32 *addr_lo, u32 *data);
+
+	/**
+	 * teardown - release resources allocated by setup
+	 * @vector: vector context for resources (in)
+	 *
+	 * Description:  The teardown op is used to release any resources
+	 * that were allocated in the setup routine associated with the passed
+	 * in vector.
+	 **/
+
+	void	(*teardown) (unsigned int vector);
+
+	/**
+	 * target - retarget an MSI at a different cpu
+	 * @vector: vector context for resources (in)
+	 * @cpu:  new cpu to direct vector at (in)
+	 * @addr_hi: new value of PCI bus upper 32 bits (in/out)
+	 * @addr_lo: new value of PCI bus lower 32 bits (in/out)
+	 *
+	 * Description:  The target op is used to redirect an MSI vector
+	 * at a different cpu.  addr_hi/addr_lo coming in are the existing
+	 * values that the MSI core has programmed into the card.  The
+	 * target code is responsible for freeing any resources (if any)
+	 * associated with the old address, and generating a new PCI bus
+	 * addr_hi/addr_lo that will redirect the vector at the indicated cpu.
+	 **/
+
+	void	(*target)   (unsigned int vector, unsigned int cpu,
+			     u32 *addr_hi, u32 *addr_lo);
+};
+
+extern int msi_register(struct msi_ops *ops);
+
 #include <asm/msi.h>
 
 /*
@@ -63,67 +125,6 @@
 #define msix_mask(address)		(address | PCI_MSIX_FLAGS_BITMASK)
 #define msix_is_pending(address) 	(address & PCI_MSIX_FLAGS_PENDMASK)
 
-/*
- * MSI Defined Data Structures
- */
-#define MSI_ADDRESS_HEADER		0xfee
-#define MSI_ADDRESS_HEADER_SHIFT	12
-#define MSI_ADDRESS_HEADER_MASK		0xfff000
-#define MSI_ADDRESS_DEST_ID_MASK	0xfff0000f
-#define MSI_TARGET_CPU_MASK		0xff
-#define MSI_DELIVERY_MODE		0
-#define MSI_LEVEL_MODE			1	/* Edge always assert */
-#define MSI_TRIGGER_MODE		0	/* MSI is edge sensitive */
-#define MSI_PHYSICAL_MODE		0
-#define MSI_LOGICAL_MODE		1
-#define MSI_REDIRECTION_HINT_MODE	0
-
-struct msg_data {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u32	vector		:  8;
-	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
-	__u32	reserved_1	:  3;
-	__u32	level		:  1;	/* 0: deassert | 1: assert */
-	__u32	trigger		:  1;	/* 0: edge | 1: level */
-	__u32	reserved_2	: 16;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-	__u32	reserved_2	: 16;
-	__u32	trigger		:  1;	/* 0: edge | 1: level */
-	__u32	level		:  1;	/* 0: deassert | 1: assert */
-	__u32	reserved_1	:  3;
-	__u32	delivery_mode	:  3;	/* 000b: FIXED | 001b: lowest prior */
-	__u32	vector		:  8;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
-} __attribute__ ((packed));
-
-struct msg_address {
-	union {
-		struct {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-			__u32	reserved_1	:  2;
-			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
-			__u32	redirection_hint:  1;  	/*0: dedicated CPU
-							  1: lowest priority */
-			__u32	reserved_2	:  4;
- 			__u32	dest_id		: 24;	/* Destination ID */
-#elif defined(__BIG_ENDIAN_BITFIELD)
- 			__u32	dest_id		: 24;	/* Destination ID */
-			__u32	reserved_2	:  4;
-			__u32	redirection_hint:  1;  	/*0: dedicated CPU
-							  1: lowest priority */
-			__u32	dest_mode	:  1;	/*0:physic | 1:logic */
-			__u32	reserved_1	:  2;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
-      		}u;
-       		__u32  value;
-	}lo_address;
-	__u32 	hi_address;
-} __attribute__ ((packed));
-
 struct msi_desc {
 	struct {
 		__u8	type	: 5; 	/* {0: unused, 5h:MSI, 11h:MSI-X} */
@@ -132,7 +133,7 @@
 		__u8	reserved: 1; 	/* reserved			  */
 		__u8	entry_nr;    	/* specific enabled entry 	  */
 		__u8	default_vector; /* default pre-assigned vector    */
-		__u8	current_cpu; 	/* current destination cpu	  */
+		__u8	unused; 	/* formerly unused destination cpu*/
 	}msi_attrib;
 
 	struct {
@@ -142,6 +143,14 @@
 
 	void __iomem *mask_base;
 	struct pci_dev *dev;
+
+#ifdef CONFIG_PM
+	/* PM save area for MSIX address/data */
+
+	u32	address_hi_save;
+	u32	address_lo_save;
+	u32	data_save;
+#endif
 };
 
 #endif /* MSI_H */
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index c2ecae5..bb7456c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -267,7 +267,7 @@
 
 
 /* ACPI bus type */
-static int pci_acpi_find_device(struct device *dev, acpi_handle *handle)
+static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
 {
 	struct pci_dev * pci_dev;
 	acpi_integer	addr;
@@ -281,7 +281,7 @@
 	return 0;
 }
 
-static int pci_acpi_find_root_bridge(struct device *dev, acpi_handle *handle)
+static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
 {
 	int num;
 	unsigned int seg, bus;
@@ -299,21 +299,21 @@
 	return 0;
 }
 
-static struct acpi_bus_type pci_acpi_bus = {
+static struct acpi_bus_type acpi_pci_bus = {
 	.bus = &pci_bus_type,
-	.find_device = pci_acpi_find_device,
-	.find_bridge = pci_acpi_find_root_bridge,
+	.find_device = acpi_pci_find_device,
+	.find_bridge = acpi_pci_find_root_bridge,
 };
 
-static int __init pci_acpi_init(void)
+static int __init acpi_pci_init(void)
 {
 	int ret;
 
-	ret = register_acpi_bus_type(&pci_acpi_bus);
+	ret = register_acpi_bus_type(&acpi_pci_bus);
 	if (ret)
 		return 0;
 	platform_pci_choose_state = acpi_pci_choose_state;
 	platform_pci_set_power_state = acpi_pci_set_power_state;
 	return 0;
 }
-arch_initcall(pci_acpi_init);
+arch_initcall(acpi_pci_init);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 56ac2bc..bc405c0 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -43,6 +43,29 @@
 pci_config_attr(subsystem_device, "0x%04x\n");
 pci_config_attr(class, "0x%06x\n");
 pci_config_attr(irq, "%u\n");
+pci_config_attr(is_enabled, "%u\n");
+
+static ssize_t broken_parity_status_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	return sprintf (buf, "%u\n", pdev->broken_parity_status);
+}
+
+static ssize_t broken_parity_status_store(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	ssize_t consumed = -EINVAL;
+
+	if ((count > 0) && (*buf == '0' || *buf == '1')) {
+		pdev->broken_parity_status = *buf == '1' ? 1 : 0;
+		consumed = count;
+	}
+	return consumed;
+}
 
 static ssize_t local_cpus_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
@@ -90,6 +113,25 @@
 		       (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
 		       (u8)(pci_dev->class));
 }
+static ssize_t
+is_enabled_store(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	/* this can crash the machine when done on the "wrong" device */
+	if (!capable(CAP_SYS_ADMIN))
+		return count;
+
+	if (*buf == '0')
+		pci_disable_device(pdev);
+
+	if (*buf == '1')
+		pci_enable_device(pdev);
+
+	return count;
+}
+
 
 struct device_attribute pci_dev_attrs[] = {
 	__ATTR_RO(resource),
@@ -101,6 +143,9 @@
 	__ATTR_RO(irq),
 	__ATTR_RO(local_cpus),
 	__ATTR_RO(modalias),
+	__ATTR(enable, 0600, is_enabled_show, is_enabled_store),
+	__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
+		broken_parity_status_show,broken_parity_status_store),
 	__ATTR_NULL,
 };
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1228627..23d3b17 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -164,7 +164,6 @@
 	return __pci_bus_find_cap(bus, devfn, hdr_type & 0x7f, cap);
 }
 
-#if 0
 /**
  * pci_find_ext_capability - Find an extended capability
  * @dev: PCI device to query
@@ -212,7 +211,7 @@
 
 	return 0;
 }
-#endif  /*  0  */
+EXPORT_SYMBOL_GPL(pci_find_ext_capability);
 
 /**
  * pci_find_parent_resource - return resource region of parent bus of given region
@@ -370,7 +369,7 @@
 
 	/*
 	 * Give firmware a chance to be called, such as ACPI _PRx, _PSx
-	 * Firmware method after natice method ?
+	 * Firmware method after native method ?
 	 */
 	if (platform_pci_set_power_state)
 		platform_pci_set_power_state(dev, state);
@@ -518,7 +517,12 @@
 int
 pci_enable_device(struct pci_dev *dev)
 {
-	int err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+	int err;
+
+	if (dev->is_enabled)
+		return 0;
+
+	err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
 	if (err)
 		return err;
 	pci_fixup_device(pci_fixup_enable, dev);
@@ -547,7 +551,14 @@
 pci_disable_device(struct pci_dev *dev)
 {
 	u16 pci_command;
-	
+
+	if (dev->msi_enabled)
+		disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
+			PCI_CAP_ID_MSI);
+	if (dev->msix_enabled)
+		disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI),
+			PCI_CAP_ID_MSIX);
+
 	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
 	if (pci_command & PCI_COMMAND_MASTER) {
 		pci_command &= ~PCI_COMMAND_MASTER;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 30630cb..29bdeca 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -40,7 +40,7 @@
 extern void pci_remove_legacy_files(struct pci_bus *bus);
 
 /* Lock for read/write access to pci device and bus lists */
-extern spinlock_t pci_bus_lock;
+extern struct rw_semaphore pci_bus_sem;
 
 #ifdef CONFIG_X86_IO_APIC
 extern int pci_msi_quirk;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a10ed9d..f89dbc3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -180,25 +180,31 @@
 		res->flags |= pci_calc_resource_flags(l);
 		if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
 		    == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
-			pci_read_config_dword(dev, reg+4, &l);
+			u32 szhi, lhi;
+			pci_read_config_dword(dev, reg+4, &lhi);
+			pci_write_config_dword(dev, reg+4, ~0);
+			pci_read_config_dword(dev, reg+4, &szhi);
+			pci_write_config_dword(dev, reg+4, lhi);
+			szhi = pci_size(lhi, szhi, 0xffffffff);
 			next++;
 #if BITS_PER_LONG == 64
-			res->start |= ((unsigned long) l) << 32;
+			res->start |= ((unsigned long) lhi) << 32;
 			res->end = res->start + sz;
-			pci_write_config_dword(dev, reg+4, ~0);
-			pci_read_config_dword(dev, reg+4, &sz);
-			pci_write_config_dword(dev, reg+4, l);
-			sz = pci_size(l, sz, 0xffffffff);
-			if (sz) {
+			if (szhi) {
 				/* This BAR needs > 4GB?  Wow. */
-				res->end |= (unsigned long)sz<<32;
+				res->end |= (unsigned long)szhi<<32;
 			}
 #else
-			if (l) {
-				printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev));
+			if (szhi) {
+				printk(KERN_ERR "PCI: Unable to handle 64-bit BAR for device %s\n", pci_name(dev));
 				res->start = 0;
 				res->flags = 0;
-				continue;
+			} else if (lhi) {
+				/* 64-bit wide address, treat as disabled */
+				pci_write_config_dword(dev, reg, l & ~(u32)PCI_BASE_ADDRESS_MEM_MASK);
+				pci_write_config_dword(dev, reg+4, 0);
+				res->start = 0;
+				res->end = sz;
 			}
 #endif
 		}
@@ -377,9 +383,9 @@
 
 	child = pci_alloc_child_bus(parent, dev, busnr);
 	if (child) {
-		spin_lock(&pci_bus_lock);
+		down_write(&pci_bus_sem);
 		list_add_tail(&child->node, &parent->children);
-		spin_unlock(&pci_bus_lock);
+		up_write(&pci_bus_sem);
 	}
 	return child;
 }
@@ -838,9 +844,9 @@
 	 * and the bus list for fixup functions, etc.
 	 */
 	INIT_LIST_HEAD(&dev->global_list);
-	spin_lock(&pci_bus_lock);
+	down_write(&pci_bus_sem);
 	list_add_tail(&dev->bus_list, &bus->devices);
-	spin_unlock(&pci_bus_lock);
+	up_write(&pci_bus_sem);
 }
 
 struct pci_dev * __devinit
@@ -975,9 +981,10 @@
 		pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);
 		goto err_out;
 	}
-	spin_lock(&pci_bus_lock);
+
+	down_write(&pci_bus_sem);
 	list_add_tail(&b->node, &pci_root_buses);
-	spin_unlock(&pci_bus_lock);
+	up_write(&pci_bus_sem);
 
 	memset(dev, 0, sizeof(*dev));
 	dev->parent = parent;
@@ -1017,9 +1024,9 @@
 class_dev_reg_err:
 	device_unregister(dev);
 dev_reg_err:
-	spin_lock(&pci_bus_lock);
+	down_write(&pci_bus_sem);
 	list_del(&b->node);
-	spin_unlock(&pci_bus_lock);
+	up_write(&pci_bus_sem);
 err_out:
 	kfree(dev);
 	kfree(b);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index d378478..4364d79 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -24,6 +24,17 @@
 #include <linux/acpi.h>
 #include "pci.h"
 
+/* The Mellanox Tavor device gives false positive parity errors
+ * Mark this device with a broken_parity_status, to allow
+ * PCI scanning code to "skip" this now blacklisted device.
+ */
+static void __devinit quirk_mellanox_tavor(struct pci_dev *dev)
+{
+	dev->broken_parity_status = 1;	/* This device gives false positives */
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor);
+
 /* Deal with broken BIOS'es that neglect to enable passive release,
    which can cause problems in combination with the 82441FX/PPro MTRRs */
 static void __devinit quirk_passive_release(struct pci_dev *dev)
@@ -878,27 +889,30 @@
  * when a PCI-Soundcard is added. The BIOS only gives Options
  * "Disabled" and "AUTO". This Quirk Sets the corresponding
  * Register-Value to enable the Soundcard.
+ *
+ * FIXME: Presently this quirk will run on anything that has an 8237
+ * which isn't correct, we need to check DMI tables or something in
+ * order to make sure it only runs on the MSI-K8T-Neo2Fir.  Because it
+ * runs everywhere at present we suppress the printk output in most
+ * irrelevant cases.
  */
 static void __init k8t_sound_hostbridge(struct pci_dev *dev)
 {
 	unsigned char val;
 
-	printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n");
 	pci_read_config_byte(dev, 0x50, &val);
 	if (val == 0x88 || val == 0xc8) {
+		/* Assume it's probably a MSI-K8T-Neo2Fir */
+		printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, attempting to turn soundcard ON\n");
 		pci_write_config_byte(dev, 0x50, val & (~0x40));
 
 		/* Verify the Change for Status output */
 		pci_read_config_byte(dev, 0x50, &val);
 		if (val & 0x40)
-			printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n");
+			printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard still off\n");
 		else
-			printk(KERN_INFO "PCI: MSI-K8T soundcard on\n");
-	} else {
-		printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: "
-					"no Change!\n");
+			printk(KERN_INFO "PCI: MSI-K8T-Neo2Fir, soundcard on\n");
 	}
-
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
 
@@ -1485,6 +1499,25 @@
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	0x1460,		quirk_p64h2_1k_io);
 
+/* Under some circumstances, AER is not linked with extended capabilities.
+ * Force it to be linked by setting the corresponding control bit in the
+ * config space.
+ */
+static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
+{
+	uint8_t b;
+	if (pci_read_config_byte(dev, 0xf41, &b) == 0) {
+		if (!(b & 0x20)) {
+			pci_write_config_byte(dev, 0xf41, b | 0x20);
+			printk(KERN_INFO
+			       "PCI: Linking AER extended capability on %s\n",
+			       pci_name(dev));
+		}
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
+			quirk_nvidia_ck804_pcie_aer_ext_cap);
+
 EXPORT_SYMBOL(pcie_mch_quirk);
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pci_fixup_device);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 1a6bf9d..99ffbd4 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -22,18 +22,18 @@
 		pci_proc_detach_device(dev);
 		pci_remove_sysfs_dev_files(dev);
 		device_unregister(&dev->dev);
-		spin_lock(&pci_bus_lock);
+		down_write(&pci_bus_sem);
 		list_del(&dev->global_list);
 		dev->global_list.next = dev->global_list.prev = NULL;
-		spin_unlock(&pci_bus_lock);
+		up_write(&pci_bus_sem);
 	}
 
 	/* Remove the device from the device lists, and prevent any further
 	 * list accesses from this device */
-	spin_lock(&pci_bus_lock);
+	down_write(&pci_bus_sem);
 	list_del(&dev->bus_list);
 	dev->bus_list.next = dev->bus_list.prev = NULL;
-	spin_unlock(&pci_bus_lock);
+	up_write(&pci_bus_sem);
 
 	pci_free_resources(dev);
 	pci_dev_put(dev);
@@ -62,9 +62,9 @@
 {
 	pci_proc_detach_bus(pci_bus);
 
-	spin_lock(&pci_bus_lock);
+	down_write(&pci_bus_sem);
 	list_del(&pci_bus->node);
-	spin_unlock(&pci_bus_lock);
+	up_write(&pci_bus_sem);
 	pci_remove_legacy_files(pci_bus);
 	class_device_remove_file(&pci_bus->class_dev,
 		&class_device_attr_cpuaffinity);
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index ce7dd6e..622b3f8 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -13,7 +13,7 @@
 #include <linux/interrupt.h>
 #include "pci.h"
 
-DEFINE_SPINLOCK(pci_bus_lock);
+DECLARE_RWSEM(pci_bus_sem);
 
 static struct pci_bus * __devinit
 pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
@@ -72,11 +72,11 @@
 	struct pci_bus *b = NULL;
 
 	WARN_ON(in_interrupt());
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 	n = from ? from->node.next : pci_root_buses.next;
 	if (n != &pci_root_buses)
 		b = pci_bus_b(n);
-	spin_unlock(&pci_bus_lock);
+	up_read(&pci_bus_sem);
 	return b;
 }
 
@@ -124,7 +124,7 @@
 	struct pci_dev *dev;
 
 	WARN_ON(in_interrupt());
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 
 	list_for_each(tmp, &bus->devices) {
 		dev = pci_dev_b(tmp);
@@ -135,7 +135,7 @@
 	dev = NULL;
  out:
 	pci_dev_get(dev);
-	spin_unlock(&pci_bus_lock);
+	up_read(&pci_bus_sem);
 	return dev;
 }
 
@@ -167,7 +167,7 @@
 	struct pci_dev *dev;
 
 	WARN_ON(in_interrupt());
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
 
 	while (n && (n != &pci_devices)) {
@@ -181,7 +181,7 @@
 	}
 	dev = NULL;
 exit:
-	spin_unlock(&pci_bus_lock);
+	up_read(&pci_bus_sem);
 	return dev;
 }
 
@@ -232,7 +232,7 @@
 	struct pci_dev *dev;
 
 	WARN_ON(in_interrupt());
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
 
 	while (n && (n != &pci_devices)) {
@@ -247,7 +247,7 @@
 	dev = NULL;
 exit:
 	dev = pci_dev_get(dev);
-	spin_unlock(&pci_bus_lock);
+	up_read(&pci_bus_sem);
 	pci_dev_put(from);
 	return dev;
 }
@@ -292,7 +292,7 @@
 	struct pci_dev *dev;
 
 	WARN_ON(in_interrupt());
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 	n = from ? from->global_list.prev : pci_devices.prev;
 
 	while (n && (n != &pci_devices)) {
@@ -304,7 +304,7 @@
 	}
 	dev = NULL;
 exit:
-	spin_unlock(&pci_bus_lock);
+	up_read(&pci_bus_sem);
 	return dev;
 }
 
@@ -328,7 +328,7 @@
 	struct pci_dev *dev;
 
 	WARN_ON(in_interrupt());
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 	n = from ? from->global_list.next : pci_devices.next;
 
 	while (n && (n != &pci_devices)) {
@@ -340,7 +340,7 @@
 	dev = NULL;
 exit:
 	dev = pci_dev_get(dev);
-	spin_unlock(&pci_bus_lock);
+	up_read(&pci_bus_sem);
 	pci_dev_put(from);
 	return dev;
 }
@@ -362,7 +362,7 @@
 	int found = 0;
 
 	WARN_ON(in_interrupt());
-	spin_lock(&pci_bus_lock);
+	down_read(&pci_bus_sem);
 	while (ids->vendor || ids->subvendor || ids->class_mask) {
 		list_for_each_entry(dev, &pci_devices, global_list) {
 			if (pci_match_one_device(ids, dev)) {
@@ -372,8 +372,8 @@
 		}
 		ids++;
 	}
-exit:				
-	spin_unlock(&pci_bus_lock);
+exit:
+	up_read(&pci_bus_sem);
 	return found;
 }
 EXPORT_SYMBOL(pci_dev_present);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 28ce3a7..35086e8 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -55,9 +55,10 @@
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		u16 class = dev->class >> 8;
 
-		/* Don't touch classless devices and host bridges.  */
+		/* Don't touch classless devices or host bridges or ioapics.  */
 		if (class == PCI_CLASS_NOT_DEFINED ||
-		    class == PCI_CLASS_BRIDGE_HOST)
+		    class == PCI_CLASS_BRIDGE_HOST ||
+		    class == PCI_CLASS_SYSTEM_PIC)
 			continue;
 
 		pdev_sort_resources(dev, &head);
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index ea9277b..577f4b5 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -155,6 +155,46 @@
 	return ret;
 }
 
+#ifdef CONFIG_EMBEDDED
+int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
+{
+	struct pci_bus *bus = dev->bus;
+	struct resource *res = dev->resource + resno;
+	unsigned int type_mask;
+	int i, ret = -EBUSY;
+
+	type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH;
+
+	for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
+		struct resource *r = bus->resource[i];
+		if (!r)
+			continue;
+
+		/* type_mask must match */
+		if ((res->flags ^ r->flags) & type_mask)
+			continue;
+
+		ret = request_resource(r, res);
+
+		if (ret == 0)
+			break;
+	}
+
+	if (ret) {
+		printk(KERN_ERR "PCI: Failed to allocate %s resource "
+				"#%d:%llx@%llx for %s\n",
+			res->flags & IORESOURCE_IO ? "I/O" : "mem",
+			resno, (unsigned long long)(res->end - res->start + 1),
+			(unsigned long long)res->start, pci_name(dev));
+	} else if (resno < PCI_BRIDGE_RESOURCES) {
+		pci_update_resource(dev, res, resno);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pci_assign_resource_fixed);
+#endif
+
 /* Sort resources by alignment */
 void __devinit
 pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index 0e07d95..d0f68ab 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -157,7 +157,7 @@
 
 static int pcmcia_schlvl = PCMCIA_SCHLVL;
 
-static spinlock_t events_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(events_lock);
 
 
 #define PCMCIA_SOCKET_KEY_5V 1
@@ -644,7 +644,7 @@
 };
 
 static u32 pending_events[PCMCIA_SOCKETS_NO];
-static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(pending_event_lock);
 
 static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
 {
diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c
index c6b262b..19b1e12 100644
--- a/drivers/pcmcia/sa1100_badge4.c
+++ b/drivers/pcmcia/sa1100_badge4.c
@@ -128,8 +128,8 @@
 
 static struct pcmcia_low_level badge4_pcmcia_ops = {
 	.owner			= THIS_MODULE,
-	.init			= sa1111_pcmcia_hw_init,
-	.shutdown		= sa1111_pcmcia_hw_shutdown,
+	.hw_init		= sa1111_pcmcia_hw_init,
+	.hw_shutdown		= sa1111_pcmcia_hw_shutdown,
 	.socket_state		= sa1111_pcmcia_socket_state,
 	.configure_socket	= badge4_pcmcia_configure_socket,
 
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index bb19c64..0b4adcb 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -60,30 +60,34 @@
 	card_remove(dev);
 }
 
-static int card_probe(struct pnp_card * card, struct pnp_card_driver * drv)
+static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
 {
-	const struct pnp_card_device_id *id = match_card(drv,card);
-	if (id) {
-		struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link));
-		if (!clink)
-			return 0;
-		clink->card = card;
-		clink->driver = drv;
-		clink->pm_state = PMSG_ON;
-		if (drv->probe) {
-			if (drv->probe(clink, id)>=0)
-				return 1;
-			else {
-				struct pnp_dev * dev;
-				card_for_each_dev(card, dev) {
-					if (dev->card_link == clink)
-						pnp_release_card_device(dev);
-				}
-				kfree(clink);
-			}
-		} else
-			return 1;
+	const struct pnp_card_device_id *id;
+	struct pnp_card_link *clink;
+	struct pnp_dev *dev;
+
+	if (!drv->probe)
+		return 0;
+	id = match_card(drv,card);
+	if (!id)
+		return 0;
+
+	clink = pnp_alloc(sizeof(*clink));
+	if (!clink)
+		return 0;
+	clink->card = card;
+	clink->driver = drv;
+	clink->pm_state = PMSG_ON;
+
+	if (drv->probe(clink, id) >= 0)
+		return 1;
+
+	/* Recovery */
+	card_for_each_dev(card, dev) {
+		if (dev->card_link == clink)
+			pnp_release_card_device(dev);
 	}
+	kfree(clink);
 	return 0;
 }
 
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 407b4ea..3a4a644 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -36,13 +36,13 @@
 {
 	int flag;
 	if (triggering == ACPI_LEVEL_SENSITIVE) {
-		if(polarity == ACPI_ACTIVE_LOW)
+		if (polarity == ACPI_ACTIVE_LOW)
 			flag = IORESOURCE_IRQ_LOWLEVEL;
 		else
 			flag = IORESOURCE_IRQ_HIGHLEVEL;
 	}
 	else {
-		if(polarity == ACPI_ACTIVE_LOW)
+		if (polarity == ACPI_ACTIVE_LOW)
 			flag = IORESOURCE_IRQ_LOWEDGE;
 		else
 			flag = IORESOURCE_IRQ_HIGHEDGE;
@@ -57,7 +57,7 @@
 		*triggering = ACPI_LEVEL_SENSITIVE;
 		*polarity = ACPI_ACTIVE_LOW;
 		break;
-	case IORESOURCE_IRQ_HIGHLEVEL:	
+	case IORESOURCE_IRQ_HIGHLEVEL:
 		*triggering = ACPI_LEVEL_SENSITIVE;
 		*polarity = ACPI_ACTIVE_HIGH;
 		break;
@@ -73,7 +73,7 @@
 }
 
 static void
-pnpacpi_parse_allocated_irqresource(struct pnp_resource_table * res, u32 gsi,
+pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, u32 gsi,
 	int triggering, int polarity)
 {
 	int i = 0;
@@ -101,7 +101,7 @@
 }
 
 static void
-pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table * res, u32 dma)
+pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res, u32 dma)
 {
 	int i = 0;
 	while (i < PNP_MAX_DMA &&
@@ -119,8 +119,8 @@
 }
 
 static void
-pnpacpi_parse_allocated_ioresource(struct pnp_resource_table * res,
-	u32 io, u32 len)
+pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
+	u64 io, u64 len)
 {
 	int i = 0;
 	while (!(res->port_resource[i].flags & IORESOURCE_UNSET) &&
@@ -138,7 +138,7 @@
 }
 
 static void
-pnpacpi_parse_allocated_memresource(struct pnp_resource_table * res,
+pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
 	u64 mem, u64 len)
 {
 	int i = 0;
@@ -156,11 +156,32 @@
 	}
 }
 
+static void
+pnpacpi_parse_allocated_address_space(struct pnp_resource_table *res_table,
+	struct acpi_resource *res)
+{
+	struct acpi_resource_address64 addr, *p = &addr;
+	acpi_status status;
+
+	status = acpi_resource_to_address64(res, p);
+	if (!ACPI_SUCCESS(status)) {
+		pnp_warn("PnPACPI: failed to convert resource type %d",
+			res->type);
+		return;
+	}
+
+	if (p->resource_type == ACPI_MEMORY_RANGE)
+		pnpacpi_parse_allocated_memresource(res_table,
+				p->minimum, p->address_length);
+	else if (p->resource_type == ACPI_IO_RANGE)
+		pnpacpi_parse_allocated_ioresource(res_table,
+				p->minimum, p->address_length);
+}
 
 static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
 	void *data)
 {
-	struct pnp_resource_table * res_table = (struct pnp_resource_table *)data;
+	struct pnp_resource_table *res_table = (struct pnp_resource_table *)data;
 	int i;
 
 	switch (res->type) {
@@ -221,19 +242,9 @@
 				res->data.fixed_memory32.address_length);
 		break;
 	case ACPI_RESOURCE_TYPE_ADDRESS16:
-		pnpacpi_parse_allocated_memresource(res_table,
-				res->data.address16.minimum,
-				res->data.address16.address_length);
-		break;
 	case ACPI_RESOURCE_TYPE_ADDRESS32:
-		pnpacpi_parse_allocated_memresource(res_table,
-				res->data.address32.minimum,
-				res->data.address32.address_length);
-		break;
 	case ACPI_RESOURCE_TYPE_ADDRESS64:
-		pnpacpi_parse_allocated_memresource(res_table,
-		res->data.address64.minimum,
-		res->data.address64.address_length);
+		pnpacpi_parse_allocated_address_space(res_table, res);
 		break;
 
 	case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64:
@@ -255,11 +266,11 @@
 		pnp_warn("PnPACPI: unknown resource type %d", res->type);
 		return AE_ERROR;
 	}
-			
+
 	return AE_OK;
 }
 
-acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res)
+acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table *res)
 {
 	/* Blank the resource table values */
 	pnp_init_resource_table(res);
@@ -317,17 +328,17 @@
 		pnp_err("Invalid DMA transfer type");
 	}
 
-	pnp_register_dma_resource(option,dma);
+	pnp_register_dma_resource(option, dma);
 	return;
 }
 
-	
+
 static void pnpacpi_parse_irq_option(struct pnp_option *option,
 	struct acpi_resource_irq *p)
 {
 	int i;
-	struct pnp_irq * irq;
-	
+	struct pnp_irq *irq;
+
 	if (p->interrupt_count == 0)
 		return;
 	irq = kcalloc(1, sizeof(struct pnp_irq), GFP_KERNEL);
@@ -347,7 +358,7 @@
 	struct acpi_resource_extended_irq *p)
 {
 	int i;
-	struct pnp_irq * irq;
+	struct pnp_irq *irq;
 
 	if (p->interrupt_count == 0)
 		return;
@@ -368,7 +379,7 @@
 pnpacpi_parse_port_option(struct pnp_option *option,
 	struct acpi_resource_io *io)
 {
-	struct pnp_port * port;
+	struct pnp_port *port;
 
 	if (io->address_length == 0)
 		return;
@@ -381,7 +392,7 @@
 	port->size = io->address_length;
 	port->flags = ACPI_DECODE_16 == io->io_decode ?
 		PNP_PORT_FLAG_16BITADDR : 0;
-	pnp_register_port_resource(option,port);
+	pnp_register_port_resource(option, port);
 	return;
 }
 
@@ -389,7 +400,7 @@
 pnpacpi_parse_fixed_port_option(struct pnp_option *option,
 	struct acpi_resource_fixed_io *io)
 {
-	struct pnp_port * port;
+	struct pnp_port *port;
 
 	if (io->address_length == 0)
 		return;
@@ -400,7 +411,7 @@
 	port->size = io->address_length;
 	port->align = 0;
 	port->flags = PNP_PORT_FLAG_FIXED;
-	pnp_register_port_resource(option,port);
+	pnp_register_port_resource(option, port);
 	return;
 }
 
@@ -408,7 +419,7 @@
 pnpacpi_parse_mem24_option(struct pnp_option *option,
 	struct acpi_resource_memory24 *p)
 {
-	struct pnp_mem * mem;
+	struct pnp_mem *mem;
 
 	if (p->address_length == 0)
 		return;
@@ -423,7 +434,7 @@
 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 			IORESOURCE_MEM_WRITEABLE : 0;
 
-	pnp_register_mem_resource(option,mem);
+	pnp_register_mem_resource(option, mem);
 	return;
 }
 
@@ -431,7 +442,7 @@
 pnpacpi_parse_mem32_option(struct pnp_option *option,
 	struct acpi_resource_memory32 *p)
 {
-	struct pnp_mem * mem;
+	struct pnp_mem *mem;
 
 	if (p->address_length == 0)
 		return;
@@ -446,7 +457,7 @@
 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 			IORESOURCE_MEM_WRITEABLE : 0;
 
-	pnp_register_mem_resource(option,mem);
+	pnp_register_mem_resource(option, mem);
 	return;
 }
 
@@ -454,7 +465,7 @@
 pnpacpi_parse_fixed_mem32_option(struct pnp_option *option,
 	struct acpi_resource_fixed_memory32 *p)
 {
-	struct pnp_mem * mem;
+	struct pnp_mem *mem;
 
 	if (p->address_length == 0)
 		return;
@@ -468,7 +479,7 @@
 	mem->flags = (ACPI_READ_WRITE_MEMORY == p->write_protect) ?
 			IORESOURCE_MEM_WRITEABLE : 0;
 
-	pnp_register_mem_resource(option,mem);
+	pnp_register_mem_resource(option, mem);
 	return;
 }
 
@@ -477,8 +488,8 @@
 {
 	struct acpi_resource_address64 addr, *p = &addr;
 	acpi_status status;
-	struct pnp_mem * mem;
-	struct pnp_port * port;
+	struct pnp_mem *mem;
+	struct pnp_port *port;
 
 	status = acpi_resource_to_address64(r, p);
 	if (!ACPI_SUCCESS(status)) {
@@ -498,7 +509,7 @@
 		mem->align = 0;
 		mem->flags = (p->info.mem.write_protect ==
 		    ACPI_READ_WRITE_MEMORY) ? IORESOURCE_MEM_WRITEABLE : 0;
-		pnp_register_mem_resource(option,mem);
+		pnp_register_mem_resource(option, mem);
 	} else if (p->resource_type == ACPI_IO_RANGE) {
 		port = kcalloc(1, sizeof(struct pnp_port), GFP_KERNEL);
 		if (!port)
@@ -507,7 +518,7 @@
 		port->size = p->address_length;
 		port->align = 0;
 		port->flags = PNP_PORT_FLAG_FIXED;
-		pnp_register_port_resource(option,port);
+		pnp_register_port_resource(option, port);
 	}
 }
 
@@ -531,7 +542,7 @@
 			break;
 
 		case ACPI_RESOURCE_TYPE_DMA:
-			pnpacpi_parse_dma_option(option, &res->data.dma);	
+			pnpacpi_parse_dma_option(option, &res->data.dma);
 			break;
 
 		case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -539,7 +550,7 @@
 				case ACPI_GOOD_CONFIGURATION:
 					priority = PNP_RES_PRIORITY_PREFERRED;
 					break;
-					
+
 				case ACPI_ACCEPTABLE_CONFIGURATION:
 					priority = PNP_RES_PRIORITY_ACCEPTABLE;
 					break;
@@ -555,7 +566,7 @@
 			option = pnp_register_dependent_option(dev, priority);
 			if (!option)
 				return AE_ERROR;
-			parse_data->option = option;	
+			parse_data->option = option;
 			break;
 
 		case ACPI_RESOURCE_TYPE_END_DEPENDENT:
@@ -615,7 +626,7 @@
 			pnp_warn("PnPACPI: unknown resource type %d", res->type);
 			return AE_ERROR;
 	}
-			
+
 	return AE_OK;
 }
 
@@ -636,6 +647,25 @@
 	return status;
 }
 
+static int pnpacpi_supported_resource(struct acpi_resource *res)
+{
+	switch (res->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
+	case ACPI_RESOURCE_TYPE_DMA:
+	case ACPI_RESOURCE_TYPE_IO:
+	case ACPI_RESOURCE_TYPE_FIXED_IO:
+	case ACPI_RESOURCE_TYPE_MEMORY24:
+	case ACPI_RESOURCE_TYPE_MEMORY32:
+	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
+	case ACPI_RESOURCE_TYPE_ADDRESS16:
+	case ACPI_RESOURCE_TYPE_ADDRESS32:
+	case ACPI_RESOURCE_TYPE_ADDRESS64:
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+		return 1;
+	}
+	return 0;
+}
+
 /*
  * Set resource
  */
@@ -643,55 +673,20 @@
 	void *data)
 {
 	int *res_cnt = (int *)data;
-	switch (res->type) {
-	case ACPI_RESOURCE_TYPE_IRQ:
-	case ACPI_RESOURCE_TYPE_DMA:
-	case ACPI_RESOURCE_TYPE_IO:
-	case ACPI_RESOURCE_TYPE_FIXED_IO:
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
-		(*res_cnt) ++;
-	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
-	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
-	case ACPI_RESOURCE_TYPE_VENDOR:
-	case ACPI_RESOURCE_TYPE_END_TAG:
-	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
-	default:
-		return AE_OK;
-	}
+
+	if (pnpacpi_supported_resource(res))
+		(*res_cnt)++;
 	return AE_OK;
 }
 
-static acpi_status pnpacpi_type_resources(struct acpi_resource *res,
-	void *data)
+static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
 {
-	struct acpi_resource **resource = (struct acpi_resource **)data;	
-	switch (res->type) {
-	case ACPI_RESOURCE_TYPE_IRQ:
-	case ACPI_RESOURCE_TYPE_DMA:
-	case ACPI_RESOURCE_TYPE_IO:
-	case ACPI_RESOURCE_TYPE_FIXED_IO:
-	case ACPI_RESOURCE_TYPE_MEMORY24:
-	case ACPI_RESOURCE_TYPE_MEMORY32:
-	case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
-	case ACPI_RESOURCE_TYPE_ADDRESS16:
-	case ACPI_RESOURCE_TYPE_ADDRESS32:
-	case ACPI_RESOURCE_TYPE_ADDRESS64:
-	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+	struct acpi_resource **resource = (struct acpi_resource **)data;
+
+	if (pnpacpi_supported_resource(res)) {
 		(*resource)->type = res->type;
+		(*resource)->length = sizeof(struct acpi_resource);
 		(*resource)++;
-	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
-	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
-	case ACPI_RESOURCE_TYPE_VENDOR:
-	case ACPI_RESOURCE_TYPE_END_TAG:
-	case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
-	default:
-		return AE_OK;
 	}
 
 	return AE_OK;
@@ -735,11 +730,8 @@
 	struct resource *p)
 {
 	int triggering, polarity;
-	
-	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
-		&polarity);
-	resource->type = ACPI_RESOURCE_TYPE_IRQ;
-	resource->length = sizeof(struct acpi_resource);
+
+	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
 	resource->data.irq.triggering = triggering;
 	resource->data.irq.polarity = polarity;
 	if (triggering == ACPI_EDGE_SENSITIVE)
@@ -754,11 +746,8 @@
 	struct resource *p)
 {
 	int triggering, polarity;
-	
-	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering,
-		&polarity);
-	resource->type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
-	resource->length = sizeof(struct acpi_resource);
+
+	decode_irq_flags(p->flags & IORESOURCE_BITS, &triggering, &polarity);
 	resource->data.extended_irq.producer_consumer = ACPI_CONSUMER;
 	resource->data.extended_irq.triggering = triggering;
 	resource->data.extended_irq.polarity = polarity;
@@ -773,8 +762,6 @@
 static void pnpacpi_encode_dma(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->type = ACPI_RESOURCE_TYPE_DMA;
-	resource->length = sizeof(struct acpi_resource);
 	/* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */
 	if (p->flags & IORESOURCE_DMA_COMPATIBLE)
 		resource->data.dma.type = ACPI_COMPATIBILITY;
@@ -798,8 +785,6 @@
 static void pnpacpi_encode_io(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->type = ACPI_RESOURCE_TYPE_IO;
-	resource->length = sizeof(struct acpi_resource);
 	/* Note: pnp_assign_port will copy pnp_port->flags into p->flags */
 	resource->data.io.io_decode = (p->flags & PNP_PORT_FLAG_16BITADDR)?
 		ACPI_DECODE_16 : ACPI_DECODE_10;
@@ -812,8 +797,6 @@
 static void pnpacpi_encode_fixed_io(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->type = ACPI_RESOURCE_TYPE_FIXED_IO;
-	resource->length = sizeof(struct acpi_resource);
 	resource->data.fixed_io.address = p->start;
 	resource->data.fixed_io.address_length = p->end - p->start + 1;
 }
@@ -821,8 +804,6 @@
 static void pnpacpi_encode_mem24(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->type = ACPI_RESOURCE_TYPE_MEMORY24;
-	resource->length = sizeof(struct acpi_resource);
 	/* Note: pnp_assign_mem will copy pnp_mem->flags into p->flags */
 	resource->data.memory24.write_protect =
 		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
@@ -836,8 +817,6 @@
 static void pnpacpi_encode_mem32(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->type = ACPI_RESOURCE_TYPE_MEMORY32;
-	resource->length = sizeof(struct acpi_resource);
 	resource->data.memory32.write_protect =
 		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
 		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
@@ -850,8 +829,6 @@
 static void pnpacpi_encode_fixed_mem32(struct acpi_resource *resource,
 	struct resource *p)
 {
-	resource->type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32;
-	resource->length = sizeof(struct acpi_resource);
 	resource->data.fixed_memory32.write_protect =
 		(p->flags & IORESOURCE_MEM_WRITEABLE) ?
 		ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY;
@@ -882,37 +859,37 @@
 			pnp_dbg("Encode dma");
 			pnpacpi_encode_dma(resource,
 				&res_table->dma_resource[dma]);
-			dma ++;
+			dma++;
 			break;
 		case ACPI_RESOURCE_TYPE_IO:
 			pnp_dbg("Encode io");
 			pnpacpi_encode_io(resource,
 				&res_table->port_resource[port]);
-			port ++;
+			port++;
 			break;
 		case ACPI_RESOURCE_TYPE_FIXED_IO:
 			pnp_dbg("Encode fixed io");
 			pnpacpi_encode_fixed_io(resource,
 				&res_table->port_resource[port]);
-			port ++;
+			port++;
 			break;
 		case ACPI_RESOURCE_TYPE_MEMORY24:
 			pnp_dbg("Encode mem24");
 			pnpacpi_encode_mem24(resource,
 				&res_table->mem_resource[mem]);
-			mem ++;
+			mem++;
 			break;
 		case ACPI_RESOURCE_TYPE_MEMORY32:
 			pnp_dbg("Encode mem32");
 			pnpacpi_encode_mem32(resource,
 				&res_table->mem_resource[mem]);
-			mem ++;
+			mem++;
 			break;
 		case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
 			pnp_dbg("Encode fixed mem32");
 			pnpacpi_encode_fixed_mem32(resource,
 				&res_table->mem_resource[mem]);
-			mem ++;
+			mem++;
 			break;
 		case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
 			pnp_dbg("Encode ext irq");
@@ -933,8 +910,8 @@
 			pnp_warn("unknown resource type %d", resource->type);
 			return -EINVAL;
 		}
-		resource ++;
-		i ++;
+		resource++;
+		i++;
 	}
 	return 0;
 }
diff --git a/drivers/rapidio/rio-access.c b/drivers/rapidio/rio-access.c
index b9fab2a..8b56bbd 100644
--- a/drivers/rapidio/rio-access.c
+++ b/drivers/rapidio/rio-access.c
@@ -17,8 +17,8 @@
  * These interrupt-safe spinlocks protect all accesses to RIO
  * configuration space and doorbell access.
  */
-static spinlock_t rio_config_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t rio_doorbell_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rio_config_lock);
+static DEFINE_SPINLOCK(rio_doorbell_lock);
 
 /*
  *  Wrappers for all RIO configuration access functions.  They just check
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 65d090d..f2fc81a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -73,6 +73,13 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-dev.
 
+config RTC_INTF_DEV_UIE_EMUL
+	bool "RTC UIE emulation on dev interface"
+	depends on RTC_INTF_DEV
+	help
+	  Provides an emulation for RTC_UIE if the underlaying rtc chip
+	  driver did not provide RTC_UIE ioctls.
+
 comment "RTC drivers"
 	depends on RTC_CLASS
 
@@ -86,6 +93,34 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-x1205.
 
+config RTC_DRV_DS1307
+	tristate "Dallas/Maxim DS1307 and similar I2C RTC chips"
+	depends on RTC_CLASS && I2C
+	help
+	  If you say yes here you get support for various compatible RTC
+	  chips (often with battery backup) connected with I2C.  This driver
+	  should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00,
+	  and probably other chips.  In some cases the RTC must already
+	  have been initialized (by manufacturing or a bootloader).
+
+	  The first seven registers on these chips hold an RTC, and other
+	  registers may add features such as NVRAM, a trickle charger for
+	  the RTC/NVRAM backup power, and alarms.  This driver may not
+	  expose all those available chip features.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-ds1307.
+
+config RTC_DRV_DS1553
+	tristate "Dallas DS1553"
+	depends on RTC_CLASS
+	help
+	  If you say yes here you get support for the
+	  Dallas DS1553 timekeeping chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-ds1553.
+
 config RTC_DRV_DS1672
 	tristate "Dallas/Maxim DS1672"
 	depends on RTC_CLASS && I2C
@@ -96,6 +131,16 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1672.
 
+config RTC_DRV_DS1742
+	tristate "Dallas DS1742"
+	depends on RTC_CLASS
+	help
+	  If you say yes here you get support for the
+	  Dallas DS1742 timekeeping chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-ds1742.
+
 config RTC_DRV_PCF8563
 	tristate "Philips PCF8563/Epson RTC8564"
 	depends on RTC_CLASS && I2C
@@ -107,6 +152,26 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-pcf8563.
 
+config RTC_DRV_PCF8583
+	tristate "Philips PCF8583"
+	depends on RTC_CLASS && I2C
+	help
+	  If you say yes here you get support for the
+	  Philips PCF8583 RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-pcf8583.
+
+config RTC_DRV_RS5C348
+	tristate "Ricoh RS5C348A/B"
+	depends on RTC_CLASS && SPI
+	help
+	  If you say yes here you get support for the
+	  Ricoh RS5C348A and RS5C348B RTC chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-rs5c348.
+
 config RTC_DRV_RS5C372
 	tristate "Ricoh RS5C372A/B"
 	depends on RTC_CLASS && I2C
@@ -157,6 +222,22 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called rtc-vr41xx.
 
+config RTC_DRV_PL031
+	tristate "ARM AMBA PL031 RTC"
+	depends on RTC_CLASS && ARM_AMBA
+	help
+	  If you say Y here you will get access to ARM AMBA
+	  PrimeCell PL031 UART found on certain ARM SOCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rtc-pl031.
+
+config RTC_DRV_AT91
+	tristate "AT91RM9200"
+	depends on RTC_CLASS && ARCH_AT91RM9200
+	help
+	  Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock).
+
 config RTC_DRV_TEST
 	tristate "Test driver/device"
 	depends on RTC_CLASS
@@ -172,4 +253,24 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-test.
 
+config RTC_DRV_MAX6902
+	tristate "Maxim 6902"
+	depends on RTC_CLASS && SPI
+	help
+	  If you say yes here you will get support for the
+	  Maxim MAX6902 spi RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-max6902.
+
+config RTC_DRV_V3020
+	tristate "EM Microelectronic V3020"
+	depends on RTC_CLASS
+	help
+	  If you say yes here you will get support for the
+	  EM Microelectronic v3020 RTC chip.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-v3020.
+
 endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index a9ca0f1..da5e387 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -13,10 +13,19 @@
 
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
+obj-$(CONFIG_RTC_DRV_DS1307)	+= rtc-ds1307.o
 obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o
+obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o
 obj-$(CONFIG_RTC_DRV_PCF8563)	+= rtc-pcf8563.o
+obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_RS5C372)	+= rtc-rs5c372.o
+obj-$(CONFIG_RTC_DRV_RS5C348)	+= rtc-rs5c348.o
 obj-$(CONFIG_RTC_DRV_M48T86)	+= rtc-m48t86.o
+obj-$(CONFIG_RTC_DRV_DS1553)	+= rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_SA1100)	+= rtc-sa1100.o
 obj-$(CONFIG_RTC_DRV_VR41XX)	+= rtc-vr41xx.o
+obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
+obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_V3020)	+= rtc-v3020.o
+obj-$(CONFIG_RTC_DRV_AT91)	+= rtc-at91.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 413c7d5..1cb61a7 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -69,6 +69,7 @@
 	rtc->id = id;
 	rtc->ops = ops;
 	rtc->owner = owner;
+	rtc->max_user_freq = 64;
 	rtc->class_dev.dev = dev;
 	rtc->class_dev.class = rtc_class;
 	rtc->class_dev.release = rtc_device_release;
@@ -93,7 +94,9 @@
 	kfree(rtc);
 
 exit_idr:
+	mutex_lock(&idr_lock);
 	idr_remove(&rtc_idr, id);
+	mutex_unlock(&idr_lock);
 
 exit:
 	dev_err(dev, "rtc core: unable to register %s, err = %d\n",
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 56e4907..579cd66 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -229,6 +229,9 @@
 	unsigned long flags;
 	struct rtc_device *rtc = to_rtc_device(class_dev);
 
+	if (rtc->ops->irq_set_state == NULL)
+		return -ENXIO;
+
 	spin_lock_irqsave(&rtc->irq_task_lock, flags);
 	if (rtc->irq_task != task)
 		err = -ENXIO;
@@ -243,25 +246,12 @@
 
 int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq)
 {
-	int err = 0, tmp = 0;
+	int err = 0;
 	unsigned long flags;
 	struct rtc_device *rtc = to_rtc_device(class_dev);
 
-	/* allowed range is 2-8192 */
-	if (freq < 2 || freq > 8192)
-		return -EINVAL;
-/*
-	FIXME: this does not belong here, will move where appropriate
-	at a later stage. It cannot hurt right now, trust me :)
-	if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE)))
-		return -EACCES;
-*/
-	/* check if freq is a power of 2 */
-	while (freq > (1 << tmp))
-		tmp++;
-
-	if (freq != (1 << tmp))
-		return -EINVAL;
+	if (rtc->ops->irq_set_freq == NULL)
+		return -ENXIO;
 
 	spin_lock_irqsave(&rtc->irq_task_lock, flags);
 	if (rtc->irq_task != task)
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c
new file mode 100644
index 0000000..b676f44
--- /dev/null
+++ b/drivers/rtc/rtc-at91.c
@@ -0,0 +1,407 @@
+/*
+ *	Real Time Clock interface for Linux on Atmel AT91RM9200
+ *
+ *	Copyright (C) 2002 Rick Bronson
+ *
+ *	Converted to RTC class model by Andrew Victor
+ *
+ *	Ported to Linux 2.6 by Steven Scholz
+ *	Based on s3c2410-rtc.c Simtec Electronics
+ *
+ *	Based on sa1100-rtc.c by Nils Faerber
+ *	Based on rtc.c by Paul Gortmaker
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/completion.h>
+
+#include <asm/uaccess.h>
+#include <asm/rtc.h>
+
+#include <asm/mach/time.h>
+
+
+#define AT91_RTC_FREQ		1
+#define AT91_RTC_EPOCH		1900UL	/* just like arch/arm/common/rtctime.c */
+
+static DECLARE_COMPLETION(at91_rtc_updated);
+static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
+
+/*
+ * Decode time/date into rtc_time structure
+ */
+static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
+				struct rtc_time *tm)
+{
+	unsigned int time, date;
+
+	/* must read twice in case it changes */
+	do {
+		time = at91_sys_read(timereg);
+		date = at91_sys_read(calreg);
+	} while ((time != at91_sys_read(timereg)) ||
+			(date != at91_sys_read(calreg)));
+
+	tm->tm_sec  = BCD2BIN((time & AT91_RTC_SEC) >> 0);
+	tm->tm_min  = BCD2BIN((time & AT91_RTC_MIN) >> 8);
+	tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16);
+
+	/*
+	 * The Calendar Alarm register does not have a field for
+	 * the year - so these will return an invalid value.  When an
+	 * alarm is set, at91_alarm_year wille store the current year.
+	 */
+	tm->tm_year  = BCD2BIN(date & AT91_RTC_CENT) * 100;	/* century */
+	tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8);	/* year */
+
+	tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1;	/* day of the week [0-6], Sunday=0 */
+	tm->tm_mon  = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1;
+	tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24);
+}
+
+/*
+ * Read current time and date in RTC
+ */
+static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm);
+	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+	tm->tm_year = tm->tm_year - 1900;
+
+	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	return 0;
+}
+
+/*
+ * Set current time and date in RTC
+ */
+static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	unsigned long cr;
+
+	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	/* Stop Time/Calendar from counting */
+	cr = at91_sys_read(AT91_RTC_CR);
+	at91_sys_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
+
+	at91_sys_write(AT91_RTC_IER, AT91_RTC_ACKUPD);
+	wait_for_completion(&at91_rtc_updated);	/* wait for ACKUPD interrupt */
+	at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
+
+	at91_sys_write(AT91_RTC_TIMR,
+			  BIN2BCD(tm->tm_sec) << 0
+			| BIN2BCD(tm->tm_min) << 8
+			| BIN2BCD(tm->tm_hour) << 16);
+
+	at91_sys_write(AT91_RTC_CALR,
+			  BIN2BCD((tm->tm_year + 1900) / 100)	/* century */
+			| BIN2BCD(tm->tm_year % 100) << 8	/* year */
+			| BIN2BCD(tm->tm_mon + 1) << 16		/* tm_mon starts at zero */
+			| BIN2BCD(tm->tm_wday + 1) << 21	/* day of the week [0-6], Sunday=0 */
+			| BIN2BCD(tm->tm_mday) << 24);
+
+	/* Restart Time/Calendar */
+	cr = at91_sys_read(AT91_RTC_CR);
+	at91_sys_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM));
+
+	return 0;
+}
+
+/*
+ * Read alarm time and date in RTC
+ */
+static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_time *tm = &alrm->time;
+
+	at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
+	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+	tm->tm_year = at91_alarm_year - 1900;
+
+	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+		1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	return 0;
+}
+
+/*
+ * Set alarm time and date in RTC
+ */
+static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_time tm;
+
+	at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);
+
+	at91_alarm_year = tm.tm_year;
+
+	tm.tm_hour = alrm->time.tm_hour;
+	tm.tm_min = alrm->time.tm_min;
+	tm.tm_sec = alrm->time.tm_sec;
+
+	at91_sys_write(AT91_RTC_TIMALR,
+		  BIN2BCD(tm.tm_sec) << 0
+		| BIN2BCD(tm.tm_min) << 8
+		| BIN2BCD(tm.tm_hour) << 16
+		| AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
+	at91_sys_write(AT91_RTC_CALALR,
+		  BIN2BCD(tm.tm_mon + 1) << 16		/* tm_mon starts at zero */
+		| BIN2BCD(tm.tm_mday) << 24
+		| AT91_RTC_DATEEN | AT91_RTC_MTHEN);
+
+	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+		at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
+		tm.tm_min, tm.tm_sec);
+
+	return 0;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
+			unsigned long arg)
+{
+	int ret = 0;
+
+	pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __FUNCTION__, cmd, arg);
+
+	switch (cmd) {
+	case RTC_AIE_OFF:	/* alarm off */
+		at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
+		break;
+	case RTC_AIE_ON:	/* alarm on */
+		at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+		break;
+	case RTC_UIE_OFF:	/* update off */
+	case RTC_PIE_OFF:	/* periodic off */
+		at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
+		break;
+	case RTC_UIE_ON:	/* update on */
+	case RTC_PIE_ON:	/* periodic on */
+		at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
+		break;
+	case RTC_IRQP_READ:	/* read periodic alarm frequency */
+		ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
+		break;
+	case RTC_IRQP_SET:	/* set periodic alarm frequency */
+		if (arg != AT91_RTC_FREQ)
+			ret = -EINVAL;
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * Provide additional RTC information in /proc/driver/rtc
+ */
+static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	unsigned long imr = at91_sys_read(AT91_RTC_IMR);
+
+	seq_printf(seq, "alarm_IRQ\t: %s\n",
+			(imr & AT91_RTC_ALARM) ? "yes" : "no");
+	seq_printf(seq, "update_IRQ\t: %s\n",
+			(imr & AT91_RTC_ACKUPD) ? "yes" : "no");
+	seq_printf(seq, "periodic_IRQ\t: %s\n",
+			(imr & AT91_RTC_SECEV) ? "yes" : "no");
+	seq_printf(seq, "periodic_freq\t: %ld\n",
+			(unsigned long) AT91_RTC_FREQ);
+
+	return 0;
+}
+
+/*
+ * IRQ handler for the RTC
+ */
+static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id,
+					struct pt_regs *regs)
+{
+	struct platform_device *pdev = dev_id;
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+	unsigned int rtsr;
+	unsigned long events = 0;
+
+	rtsr = at91_sys_read(AT91_RTC_SR) & at91_sys_read(AT91_RTC_IMR);
+	if (rtsr) {		/* this interrupt is shared!  Is it ours? */
+		if (rtsr & AT91_RTC_ALARM)
+			events |= (RTC_AF | RTC_IRQF);
+		if (rtsr & AT91_RTC_SECEV)
+			events |= (RTC_UF | RTC_IRQF);
+		if (rtsr & AT91_RTC_ACKUPD)
+			complete(&at91_rtc_updated);
+
+		at91_sys_write(AT91_RTC_SCCR, rtsr);	/* clear status reg */
+
+		rtc_update_irq(&rtc->class_dev, 1, events);
+
+		pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__,
+			events >> 8, events & 0x000000FF);
+
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;		/* not handled */
+}
+
+static struct rtc_class_ops at91_rtc_ops = {
+	.ioctl		= at91_rtc_ioctl,
+	.read_time	= at91_rtc_readtime,
+	.set_time	= at91_rtc_settime,
+	.read_alarm	= at91_rtc_readalarm,
+	.set_alarm	= at91_rtc_setalarm,
+	.proc		= at91_rtc_proc,
+};
+
+/*
+ * Initialize and install RTC driver
+ */
+static int __init at91_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	int ret;
+
+	at91_sys_write(AT91_RTC_CR, 0);
+	at91_sys_write(AT91_RTC_MR, 0);		/* 24 hour mode */
+
+	/* Disable all interrupts */
+	at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+					AT91_RTC_SECEV | AT91_RTC_TIMEV |
+					AT91_RTC_CALEV);
+
+	ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
+				SA_SHIRQ, "at91_rtc", pdev);
+	if (ret) {
+		printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n",
+				AT91_ID_SYS);
+		return ret;
+	}
+
+	rtc = rtc_device_register(pdev->name, &pdev->dev,
+				&at91_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		free_irq(AT91_ID_SYS, pdev);
+		return PTR_ERR(rtc);
+	}
+	platform_set_drvdata(pdev, rtc);
+
+	printk(KERN_INFO "AT91 Real Time Clock driver.\n");
+	return 0;
+}
+
+/*
+ * Disable and remove the RTC driver
+ */
+static int __devexit at91_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+	/* Disable all interrupts */
+	at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+					AT91_RTC_SECEV | AT91_RTC_TIMEV |
+					AT91_RTC_CALEV);
+	free_irq(AT91_ID_SYS, pdev);
+
+	rtc_device_unregister(rtc);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* AT91RM9200 RTC Power management control */
+
+static struct timespec at91_rtc_delta;
+
+static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct rtc_time tm;
+	struct timespec time;
+
+	time.tv_nsec = 0;
+
+	/* calculate time delta for suspend */
+	at91_rtc_readtime(&pdev->dev, &tm);
+	rtc_tm_to_time(&tm, &time.tv_sec);
+	save_time_delta(&at91_rtc_delta, &time);
+
+	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+		1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
+		tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+	return 0;
+}
+
+static int at91_rtc_resume(struct platform_device *pdev)
+{
+	struct rtc_time tm;
+	struct timespec time;
+
+	time.tv_nsec = 0;
+
+	at91_rtc_readtime(&pdev->dev, &tm);
+	rtc_tm_to_time(&tm, &time.tv_sec);
+	restore_time_delta(&at91_rtc_delta, &time);
+
+	pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+		1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
+		tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+	return 0;
+}
+#else
+#define at91_rtc_suspend NULL
+#define at91_rtc_resume  NULL
+#endif
+
+static struct platform_driver at91_rtc_driver = {
+	.probe		= at91_rtc_probe,
+	.remove		= at91_rtc_remove,
+	.suspend	= at91_rtc_suspend,
+	.resume		= at91_rtc_resume,
+	.driver		= {
+		.name	= "at91_rtc",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_rtc_init(void)
+{
+	return platform_driver_register(&at91_rtc_driver);
+}
+
+static void __exit at91_rtc_exit(void)
+{
+	platform_driver_unregister(&at91_rtc_driver);
+}
+
+module_init(at91_rtc_init);
+module_exit(at91_rtc_exit);
+
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 2011567..61a5825 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -48,6 +48,93 @@
 	return err;
 }
 
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+/*
+ * Routine to poll RTC seconds field for change as often as possible,
+ * after first RTC_UIE use timer to reduce polling
+ */
+static void rtc_uie_task(void *data)
+{
+	struct rtc_device *rtc = data;
+	struct rtc_time tm;
+	int num = 0;
+	int err;
+
+	err = rtc_read_time(&rtc->class_dev, &tm);
+	spin_lock_irq(&rtc->irq_lock);
+	if (rtc->stop_uie_polling || err) {
+		rtc->uie_task_active = 0;
+	} else if (rtc->oldsecs != tm.tm_sec) {
+		num = (tm.tm_sec + 60 - rtc->oldsecs) % 60;
+		rtc->oldsecs = tm.tm_sec;
+		rtc->uie_timer.expires = jiffies + HZ - (HZ/10);
+		rtc->uie_timer_active = 1;
+		rtc->uie_task_active = 0;
+		add_timer(&rtc->uie_timer);
+	} else if (schedule_work(&rtc->uie_task) == 0) {
+		rtc->uie_task_active = 0;
+	}
+	spin_unlock_irq(&rtc->irq_lock);
+	if (num)
+		rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF);
+}
+
+static void rtc_uie_timer(unsigned long data)
+{
+	struct rtc_device *rtc = (struct rtc_device *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc->irq_lock, flags);
+	rtc->uie_timer_active = 0;
+	rtc->uie_task_active = 1;
+	if ((schedule_work(&rtc->uie_task) == 0))
+		rtc->uie_task_active = 0;
+	spin_unlock_irqrestore(&rtc->irq_lock, flags);
+}
+
+static void clear_uie(struct rtc_device *rtc)
+{
+	spin_lock_irq(&rtc->irq_lock);
+	if (rtc->irq_active) {
+		rtc->stop_uie_polling = 1;
+		if (rtc->uie_timer_active) {
+			spin_unlock_irq(&rtc->irq_lock);
+			del_timer_sync(&rtc->uie_timer);
+			spin_lock_irq(&rtc->irq_lock);
+			rtc->uie_timer_active = 0;
+		}
+		if (rtc->uie_task_active) {
+			spin_unlock_irq(&rtc->irq_lock);
+			flush_scheduled_work();
+			spin_lock_irq(&rtc->irq_lock);
+		}
+		rtc->irq_active = 0;
+	}
+	spin_unlock_irq(&rtc->irq_lock);
+}
+
+static int set_uie(struct rtc_device *rtc)
+{
+	struct rtc_time tm;
+	int err;
+
+	err = rtc_read_time(&rtc->class_dev, &tm);
+	if (err)
+		return err;
+	spin_lock_irq(&rtc->irq_lock);
+	if (!rtc->irq_active) {
+		rtc->irq_active = 1;
+		rtc->stop_uie_polling = 0;
+		rtc->oldsecs = tm.tm_sec;
+		rtc->uie_task_active = 1;
+		if (schedule_work(&rtc->uie_task) == 0)
+			rtc->uie_task_active = 0;
+	}
+	rtc->irq_data = 0;
+	spin_unlock_irq(&rtc->irq_lock);
+	return 0;
+}
+#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */
 
 static ssize_t
 rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
@@ -127,6 +214,28 @@
 	struct rtc_wkalrm alarm;
 	void __user *uarg = (void __user *) arg;
 
+	/* check that the calles has appropriate permissions
+	 * for certain ioctls. doing this check here is useful
+	 * to avoid duplicate code in each driver.
+	 */
+	switch (cmd) {
+	case RTC_EPOCH_SET:
+	case RTC_SET_TIME:
+		if (!capable(CAP_SYS_TIME))
+			return -EACCES;
+		break;
+
+	case RTC_IRQP_SET:
+		if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
+			return -EACCES;
+		break;
+
+	case RTC_PIE_ON:
+		if (!capable(CAP_SYS_RESOURCE))
+			return -EACCES;
+		break;
+	}
+
 	/* avoid conflicting IRQ users */
 	if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
 		spin_lock(&rtc->irq_task_lock);
@@ -185,9 +294,6 @@
 		break;
 
 	case RTC_SET_TIME:
-		if (!capable(CAP_SYS_TIME))
-			return -EACCES;
-
 		if (copy_from_user(&tm, uarg, sizeof(tm)))
 			return -EFAULT;
 
@@ -203,10 +309,6 @@
 			err = -EINVAL;
 			break;
 		}
-		if (!capable(CAP_SYS_TIME)) {
-			err = -EACCES;
-			break;
-		}
 		rtc_epoch = arg;
 		err = 0;
 #endif
@@ -232,6 +334,14 @@
 			return -EFAULT;
 		break;
 
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+	case RTC_UIE_OFF:
+		clear_uie(rtc);
+		return 0;
+
+	case RTC_UIE_ON:
+		return set_uie(rtc);
+#endif
 	default:
 		err = -ENOTTY;
 		break;
@@ -244,6 +354,9 @@
 {
 	struct rtc_device *rtc = to_rtc_device(file->private_data);
 
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+	clear_uie(rtc);
+#endif
 	if (rtc->ops->release)
 		rtc->ops->release(rtc->class_dev.dev);
 
@@ -284,6 +397,10 @@
 	mutex_init(&rtc->char_lock);
 	spin_lock_init(&rtc->irq_lock);
 	init_waitqueue_head(&rtc->irq_queue);
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+	INIT_WORK(&rtc->uie_task, rtc_uie_task, rtc);
+	setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc);
+#endif
 
 	cdev_init(&rtc->char_dev, &rtc_dev_fops);
 	rtc->char_dev.owner = rtc->owner;
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
new file mode 100644
index 0000000..e8afb93
--- /dev/null
+++ b/drivers/rtc/rtc-ds1307.c
@@ -0,0 +1,388 @@
+/*
+ * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips.
+ *
+ *  Copyright (C) 2005 James Chapman (ds1337 core)
+ *  Copyright (C) 2006 David Brownell
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+
+
+/* We can't determine type by probing, but if we expect pre-Linux code
+ * to have set the chip up as a clock (turning on the oscillator and
+ * setting the date and time), Linux can ignore the non-clock features.
+ * That's a natural job for a factory or repair bench.
+ *
+ * If the I2C "force" mechanism is used, we assume the chip is a ds1337.
+ * (Much better would be board-specific tables of I2C devices, along with
+ * the platform_data drivers would use to sort such issues out.)
+ */
+enum ds_type {
+	unknown = 0,
+	ds_1307,		/* or ds1338, ... */
+	ds_1337,		/* or ds1339, ... */
+	ds_1340,		/* or st m41t00, ... */
+	// rs5c372 too?  different address...
+};
+
+static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+
+
+/* RTC registers don't differ much, except for the century flag */
+#define DS1307_REG_SECS		0x00	/* 00-59 */
+#	define DS1307_BIT_CH		0x80
+#define DS1307_REG_MIN		0x01	/* 00-59 */
+#define DS1307_REG_HOUR		0x02	/* 00-23, or 1-12{am,pm} */
+#	define DS1340_BIT_CENTURY_EN	0x80	/* in REG_HOUR */
+#	define DS1340_BIT_CENTURY	0x40	/* in REG_HOUR */
+#define DS1307_REG_WDAY		0x03	/* 01-07 */
+#define DS1307_REG_MDAY		0x04	/* 01-31 */
+#define DS1307_REG_MONTH	0x05	/* 01-12 */
+#	define DS1337_BIT_CENTURY	0x80	/* in REG_MONTH */
+#define DS1307_REG_YEAR		0x06	/* 00-99 */
+
+/* Other registers (control, status, alarms, trickle charge, NVRAM, etc)
+ * start at 7, and they differ a lot. Only control and status matter for RTC;
+ * be careful using them.
+ */
+#define DS1307_REG_CONTROL	0x07
+#	define DS1307_BIT_OUT		0x80
+#	define DS1307_BIT_SQWE		0x10
+#	define DS1307_BIT_RS1		0x02
+#	define DS1307_BIT_RS0		0x01
+#define DS1337_REG_CONTROL	0x0e
+#	define DS1337_BIT_nEOSC		0x80
+#	define DS1337_BIT_RS2		0x10
+#	define DS1337_BIT_RS1		0x08
+#	define DS1337_BIT_INTCN		0x04
+#	define DS1337_BIT_A2IE		0x02
+#	define DS1337_BIT_A1IE		0x01
+#define DS1337_REG_STATUS	0x0f
+#	define DS1337_BIT_OSF		0x80
+#	define DS1337_BIT_A2I		0x02
+#	define DS1337_BIT_A1I		0x01
+#define DS1339_REG_TRICKLE	0x10
+
+
+
+struct ds1307 {
+	u8			reg_addr;
+	u8			regs[8];
+	enum ds_type		type;
+	struct i2c_msg		msg[2];
+	struct i2c_client	client;
+	struct rtc_device	*rtc;
+};
+
+
+static int ds1307_get_time(struct device *dev, struct rtc_time *t)
+{
+	struct ds1307	*ds1307 = dev_get_drvdata(dev);
+	int		tmp;
+
+	/* read the RTC registers all at once */
+	ds1307->msg[1].flags = I2C_M_RD;
+	ds1307->msg[1].len = 7;
+
+	tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2);
+	if (tmp != 2) {
+		dev_err(dev, "%s error %d\n", "read", tmp);
+		return -EIO;
+	}
+
+	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+			"read",
+			ds1307->regs[0], ds1307->regs[1],
+			ds1307->regs[2], ds1307->regs[3],
+			ds1307->regs[4], ds1307->regs[5],
+			ds1307->regs[6]);
+
+	t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f);
+	t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+	tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
+	t->tm_hour = BCD2BIN(tmp);
+	t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
+	t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+	tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
+	t->tm_mon = BCD2BIN(tmp) - 1;
+
+	/* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
+	t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100;
+
+	dev_dbg(dev, "%s secs=%d, mins=%d, "
+		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+		"read", t->tm_sec, t->tm_min,
+		t->tm_hour, t->tm_mday,
+		t->tm_mon, t->tm_year, t->tm_wday);
+
+	return 0;
+}
+
+static int ds1307_set_time(struct device *dev, struct rtc_time *t)
+{
+	struct ds1307	*ds1307 = dev_get_drvdata(dev);
+	int		result;
+	int		tmp;
+	u8		*buf = ds1307->regs;
+
+	dev_dbg(dev, "%s secs=%d, mins=%d, "
+		"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+		"write", dt->tm_sec, dt->tm_min,
+		dt->tm_hour, dt->tm_mday,
+		dt->tm_mon, dt->tm_year, dt->tm_wday);
+
+	*buf++ = 0;		/* first register addr */
+	buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec);
+	buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min);
+	buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour);
+	buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1);
+	buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday);
+	buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1);
+
+	/* assume 20YY not 19YY */
+	tmp = t->tm_year - 100;
+	buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
+
+	if (ds1307->type == ds_1337)
+		buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
+	else if (ds1307->type == ds_1340)
+		buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
+				| DS1340_BIT_CENTURY;
+
+	ds1307->msg[1].flags = 0;
+	ds1307->msg[1].len = 8;
+
+	dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+		"write", buf[0], buf[1], buf[2], buf[3],
+		buf[4], buf[5], buf[6]);
+
+	result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1);
+	if (result != 1) {
+		dev_err(dev, "%s error %d\n", "write", tmp);
+		return -EIO;
+	}
+	return 0;
+}
+
+static struct rtc_class_ops ds13xx_rtc_ops = {
+	.read_time	= ds1307_get_time,
+	.set_time	= ds1307_set_time,
+};
+
+static struct i2c_driver ds1307_driver;
+
+static int __devinit
+ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct ds1307		*ds1307;
+	int			err = -ENODEV;
+	struct i2c_client	*client;
+	int			tmp;
+
+	if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &ds1307->client;
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &ds1307_driver;
+	client->flags = 0;
+
+	i2c_set_clientdata(client, ds1307);
+
+	ds1307->msg[0].addr = client->addr;
+	ds1307->msg[0].flags = 0;
+	ds1307->msg[0].len = 1;
+	ds1307->msg[0].buf = &ds1307->reg_addr;
+
+	ds1307->msg[1].addr = client->addr;
+	ds1307->msg[1].flags = I2C_M_RD;
+	ds1307->msg[1].len = sizeof(ds1307->regs);
+	ds1307->msg[1].buf = ds1307->regs;
+
+	/* HACK: "force" implies "needs ds1337-style-oscillator setup" */
+	if (kind >= 0) {
+		ds1307->type = ds_1337;
+
+		ds1307->reg_addr = DS1337_REG_CONTROL;
+		ds1307->msg[1].len = 2;
+
+		tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+		if (tmp != 2) {
+			pr_debug("read error %d\n", tmp);
+			err = -EIO;
+			goto exit_free;
+		}
+
+		ds1307->reg_addr = 0;
+		ds1307->msg[1].len = sizeof(ds1307->regs);
+
+		/* oscillator is off; need to turn it on */
+		if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
+				|| (ds1307->regs[1] & DS1337_BIT_OSF)) {
+			printk(KERN_ERR "no ds1337 oscillator code\n");
+			goto exit_free;
+		}
+	} else
+		ds1307->type = ds_1307;
+
+read_rtc:
+	/* read RTC registers */
+
+	tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+	if (tmp != 2) {
+		pr_debug("read error %d\n", tmp);
+		err = -EIO;
+		goto exit_free;
+	}
+
+	/* minimal sanity checking; some chips (like DS1340) don't
+	 * specify the extra bits as must-be-zero, but there are
+	 * still a few values that are clearly out-of-range.
+	 */
+	tmp = ds1307->regs[DS1307_REG_SECS];
+	if (tmp & DS1307_BIT_CH) {
+		if (ds1307->type && ds1307->type != ds_1307) {
+			pr_debug("not a ds1307?\n");
+			goto exit_free;
+		}
+		ds1307->type = ds_1307;
+
+		/* this partial initialization should work for ds1307,
+		 * ds1338, ds1340, st m41t00, and more.
+		 */
+		dev_warn(&client->dev, "oscillator started; SET TIME!\n");
+		i2c_smbus_write_byte_data(client, 0, 0);
+		goto read_rtc;
+	}
+	tmp = BCD2BIN(tmp & 0x7f);
+	if (tmp > 60)
+		goto exit_free;
+	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+	if (tmp > 60)
+		goto exit_free;
+
+	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+	if (tmp == 0 || tmp > 31)
+		goto exit_free;
+
+	tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
+	if (tmp == 0 || tmp > 12)
+		goto exit_free;
+
+	/* force into in 24 hour mode (most chips) or
+	 * disable century bit (ds1340)
+	 */
+	tmp = ds1307->regs[DS1307_REG_HOUR];
+	if (tmp & (1 << 6)) {
+		if (tmp & (1 << 5))
+			tmp = BCD2BIN(tmp & 0x1f) + 12;
+		else
+			tmp = BCD2BIN(tmp);
+		i2c_smbus_write_byte_data(client,
+				DS1307_REG_HOUR,
+				BIN2BCD(tmp));
+	}
+
+	/* FIXME chips like 1337 can generate alarm irqs too; those are
+	 * worth exposing through the API (especially when the irq is
+	 * wakeup-capable).
+	 */
+
+	switch (ds1307->type) {
+	case unknown:
+		strlcpy(client->name, "unknown", I2C_NAME_SIZE);
+		break;
+	case ds_1307:
+		strlcpy(client->name, "ds1307", I2C_NAME_SIZE);
+		break;
+	case ds_1337:
+		strlcpy(client->name, "ds1337", I2C_NAME_SIZE);
+		break;
+	case ds_1340:
+		strlcpy(client->name, "ds1340", I2C_NAME_SIZE);
+		break;
+	}
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto exit_free;
+
+	ds1307->rtc = rtc_device_register(client->name, &client->dev,
+				&ds13xx_rtc_ops, THIS_MODULE);
+	if (IS_ERR(ds1307->rtc)) {
+		err = PTR_ERR(ds1307->rtc);
+		dev_err(&client->dev,
+			"unable to register the class device\n");
+		goto exit_detach;
+	}
+
+	return 0;
+
+exit_detach:
+	i2c_detach_client(client);
+exit_free:
+	kfree(ds1307);
+exit:
+	return err;
+}
+
+static int __devinit
+ds1307_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+		return 0;
+	return i2c_probe(adapter, &addr_data, ds1307_detect);
+}
+
+static int __devexit ds1307_detach_client(struct i2c_client *client)
+{
+	int		err;
+	struct ds1307	*ds1307 = i2c_get_clientdata(client);
+
+	rtc_device_unregister(ds1307->rtc);
+	if ((err = i2c_detach_client(client)))
+		return err;
+	kfree(ds1307);
+	return 0;
+}
+
+static struct i2c_driver ds1307_driver = {
+	.driver = {
+		.name	= "ds1307",
+		.owner	= THIS_MODULE,
+	},
+	.attach_adapter	= ds1307_attach_adapter,
+	.detach_client	= __devexit_p(ds1307_detach_client),
+};
+
+static int __init ds1307_init(void)
+{
+	return i2c_add_driver(&ds1307_driver);
+}
+module_init(ds1307_init);
+
+static void __exit ds1307_exit(void)
+{
+	i2c_del_driver(&ds1307_driver);
+}
+module_exit(ds1307_exit);
+
+MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
new file mode 100644
index 0000000..762521a
--- /dev/null
+++ b/drivers/rtc/rtc-ds1553.c
@@ -0,0 +1,414 @@
+/*
+ * An rtc driver for the Dallas DS1553
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "0.1"
+
+#define RTC_REG_SIZE		0x2000
+#define RTC_OFFSET		0x1ff0
+
+#define RTC_FLAGS		(RTC_OFFSET + 0)
+#define RTC_SECONDS_ALARM	(RTC_OFFSET + 2)
+#define RTC_MINUTES_ALARM	(RTC_OFFSET + 3)
+#define RTC_HOURS_ALARM		(RTC_OFFSET + 4)
+#define RTC_DATE_ALARM		(RTC_OFFSET + 5)
+#define RTC_INTERRUPTS		(RTC_OFFSET + 6)
+#define RTC_WATCHDOG		(RTC_OFFSET + 7)
+#define RTC_CONTROL		(RTC_OFFSET + 8)
+#define RTC_CENTURY		(RTC_OFFSET + 8)
+#define RTC_SECONDS		(RTC_OFFSET + 9)
+#define RTC_MINUTES		(RTC_OFFSET + 10)
+#define RTC_HOURS		(RTC_OFFSET + 11)
+#define RTC_DAY			(RTC_OFFSET + 12)
+#define RTC_DATE		(RTC_OFFSET + 13)
+#define RTC_MONTH		(RTC_OFFSET + 14)
+#define RTC_YEAR		(RTC_OFFSET + 15)
+
+#define RTC_CENTURY_MASK	0x3f
+#define RTC_SECONDS_MASK	0x7f
+#define RTC_DAY_MASK		0x07
+
+/* Bits in the Control/Century register */
+#define RTC_WRITE		0x80
+#define RTC_READ		0x40
+
+/* Bits in the Seconds register */
+#define RTC_STOP		0x80
+
+/* Bits in the Flags register */
+#define RTC_FLAGS_AF		0x40
+#define RTC_FLAGS_BLF		0x10
+
+/* Bits in the Interrupts register */
+#define RTC_INTS_AE		0x80
+
+struct rtc_plat_data {
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;
+	unsigned long baseaddr;
+	unsigned long last_jiffies;
+	int irq;
+	unsigned int irqen;
+	int alrm_sec;
+	int alrm_min;
+	int alrm_hour;
+	int alrm_mday;
+};
+
+static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	u8 century;
+
+	century = BIN2BCD((tm->tm_year + 1900) / 100);
+
+	writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL);
+
+	writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
+	writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+	writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+	writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
+	writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
+	writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
+	writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+
+	/* RTC_CENTURY and RTC_CONTROL share same register */
+	writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
+	writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+	return 0;
+}
+
+static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	unsigned int year, month, day, hour, minute, second, week;
+	unsigned int century;
+
+	/* give enough time to update RTC in case of continuous read */
+	if (pdata->last_jiffies == jiffies)
+		msleep(1);
+	pdata->last_jiffies = jiffies;
+	writeb(RTC_READ, ioaddr + RTC_CONTROL);
+	second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
+	minute = readb(ioaddr + RTC_MINUTES);
+	hour = readb(ioaddr + RTC_HOURS);
+	day = readb(ioaddr + RTC_DATE);
+	week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
+	month = readb(ioaddr + RTC_MONTH);
+	year = readb(ioaddr + RTC_YEAR);
+	century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+	writeb(0, ioaddr + RTC_CONTROL);
+	tm->tm_sec = BCD2BIN(second);
+	tm->tm_min = BCD2BIN(minute);
+	tm->tm_hour = BCD2BIN(hour);
+	tm->tm_mday = BCD2BIN(day);
+	tm->tm_wday = BCD2BIN(week);
+	tm->tm_mon = BCD2BIN(month) - 1;
+	/* year is 1900 + tm->tm_year */
+	tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+
+	if (rtc_valid_tm(tm) < 0) {
+		dev_err(dev, "retrieved date/time is not valid.\n");
+		rtc_time_to_tm(0, tm);
+	}
+	return 0;
+}
+
+static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
+{
+	void __iomem *ioaddr = pdata->ioaddr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
+	writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_mday),
+	       ioaddr + RTC_DATE_ALARM);
+	writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_hour),
+	       ioaddr + RTC_HOURS_ALARM);
+	writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_min),
+	       ioaddr + RTC_MINUTES_ALARM);
+	writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
+	       0x80 : BIN2BCD(pdata->alrm_sec),
+	       ioaddr + RTC_SECONDS_ALARM);
+	writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS);
+	readb(ioaddr + RTC_FLAGS);	/* clear interrupts */
+	spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
+}
+
+static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq < 0)
+		return -EINVAL;
+	pdata->alrm_mday = alrm->time.tm_mday;
+	pdata->alrm_hour = alrm->time.tm_hour;
+	pdata->alrm_min = alrm->time.tm_min;
+	pdata->alrm_sec = alrm->time.tm_sec;
+	if (alrm->enabled)
+		pdata->irqen |= RTC_AF;
+	ds1553_rtc_update_alarm(pdata);
+	return 0;
+}
+
+static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq < 0)
+		return -EINVAL;
+	alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
+	alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
+	alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
+	alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec;
+	alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0;
+	return 0;
+}
+
+static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id,
+					struct pt_regs *regs)
+{
+	struct platform_device *pdev = dev_id;
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	unsigned long events = RTC_IRQF;
+
+	/* read and clear interrupt */
+	if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF))
+		return IRQ_NONE;
+	if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
+		events |= RTC_UF;
+	else
+		events |= RTC_AF;
+	rtc_update_irq(&pdata->rtc->class_dev, 1, events);
+	return IRQ_HANDLED;
+}
+
+static void ds1553_rtc_release(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq >= 0) {
+		pdata->irqen = 0;
+		ds1553_rtc_update_alarm(pdata);
+	}
+}
+
+static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
+			    unsigned long arg)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	if (pdata->irq < 0)
+		return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
+	switch (cmd) {
+	case RTC_AIE_OFF:
+		pdata->irqen &= ~RTC_AF;
+		ds1553_rtc_update_alarm(pdata);
+		break;
+	case RTC_AIE_ON:
+		pdata->irqen |= RTC_AF;
+		ds1553_rtc_update_alarm(pdata);
+		break;
+	case RTC_UIE_OFF:
+		pdata->irqen &= ~RTC_UF;
+		ds1553_rtc_update_alarm(pdata);
+		break;
+	case RTC_UIE_ON:
+		pdata->irqen |= RTC_UF;
+		ds1553_rtc_update_alarm(pdata);
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static struct rtc_class_ops ds1553_rtc_ops = {
+	.read_time	= ds1553_rtc_read_time,
+	.set_time	= ds1553_rtc_set_time,
+	.read_alarm	= ds1553_rtc_read_alarm,
+	.set_alarm	= ds1553_rtc_set_alarm,
+	.release	= ds1553_rtc_release,
+	.ioctl		= ds1553_rtc_ioctl,
+};
+
+static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
+				 loff_t pos, size_t size)
+{
+	struct platform_device *pdev =
+		to_platform_device(container_of(kobj, struct device, kobj));
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	ssize_t count;
+
+	for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+		*buf++ = readb(ioaddr + pos++);
+	return count;
+}
+
+static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
+				  loff_t pos, size_t size)
+{
+	struct platform_device *pdev =
+		to_platform_device(container_of(kobj, struct device, kobj));
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	ssize_t count;
+
+	for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+		writeb(*buf++, ioaddr + pos++);
+	return count;
+}
+
+static struct bin_attribute ds1553_nvram_attr = {
+	.attr = {
+		.name = "nvram",
+		.mode = S_IRUGO | S_IWUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = RTC_OFFSET,
+	.read = ds1553_nvram_read,
+	.write = ds1553_nvram_write,
+};
+
+static int __init ds1553_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+	unsigned int cen, sec;
+	struct rtc_plat_data *pdata = NULL;
+	void __iomem *ioaddr = NULL;
+	int ret = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	pdata->irq = -1;
+	if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	pdata->baseaddr = res->start;
+	ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
+	if (!ioaddr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	pdata->ioaddr = ioaddr;
+	pdata->irq = platform_get_irq(pdev, 0);
+
+	/* turn RTC on if it was not on */
+	sec = readb(ioaddr + RTC_SECONDS);
+	if (sec & RTC_STOP) {
+		sec &= RTC_SECONDS_MASK;
+		cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+		writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+		writeb(sec, ioaddr + RTC_SECONDS);
+		writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+	}
+	if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF)
+		dev_warn(&pdev->dev, "voltage-low detected.\n");
+
+	if (pdata->irq >= 0) {
+		writeb(0, ioaddr + RTC_INTERRUPTS);
+		if (request_irq(pdata->irq, ds1553_rtc_interrupt, SA_SHIRQ,
+				pdev->name, pdev) < 0) {
+			dev_warn(&pdev->dev, "interrupt not available.\n");
+			pdata->irq = -1;
+		}
+	}
+
+	rtc = rtc_device_register(pdev->name, &pdev->dev,
+				  &ds1553_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		ret = PTR_ERR(rtc);
+		goto out;
+	}
+	pdata->rtc = rtc;
+	pdata->last_jiffies = jiffies;
+	platform_set_drvdata(pdev, pdata);
+	sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+	return 0;
+ out:
+	if (pdata->irq >= 0)
+		free_irq(pdata->irq, pdev);
+	if (ioaddr)
+		iounmap(ioaddr);
+	if (pdata->baseaddr)
+		release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+	kfree(pdata);
+	return ret;
+}
+
+static int __devexit ds1553_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+	rtc_device_unregister(pdata->rtc);
+	if (pdata->irq >= 0) {
+		writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
+		free_irq(pdata->irq, pdev);
+	}
+	iounmap(pdata->ioaddr);
+	release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+	kfree(pdata);
+	return 0;
+}
+
+static struct platform_driver ds1553_rtc_driver = {
+	.probe		= ds1553_rtc_probe,
+	.remove		= __devexit_p(ds1553_rtc_remove),
+	.driver		= {
+		.name	= "ds1553",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int ds1553_init(void)
+{
+	return platform_driver_register(&ds1553_rtc_driver);
+}
+
+static __exit void ds1553_exit(void)
+{
+	return platform_driver_unregister(&ds1553_rtc_driver);
+}
+
+module_init(ds1553_init);
+module_exit(ds1553_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Dallas DS1553 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
new file mode 100644
index 0000000..8e47e5a
--- /dev/null
+++ b/drivers/rtc/rtc-ds1742.c
@@ -0,0 +1,259 @@
+/*
+ * An rtc driver for the Dallas DS1742
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "0.1"
+
+#define RTC_REG_SIZE		0x800
+#define RTC_OFFSET		0x7f8
+
+#define RTC_CONTROL		(RTC_OFFSET + 0)
+#define RTC_CENTURY		(RTC_OFFSET + 0)
+#define RTC_SECONDS		(RTC_OFFSET + 1)
+#define RTC_MINUTES		(RTC_OFFSET + 2)
+#define RTC_HOURS		(RTC_OFFSET + 3)
+#define RTC_DAY			(RTC_OFFSET + 4)
+#define RTC_DATE		(RTC_OFFSET + 5)
+#define RTC_MONTH		(RTC_OFFSET + 6)
+#define RTC_YEAR		(RTC_OFFSET + 7)
+
+#define RTC_CENTURY_MASK	0x3f
+#define RTC_SECONDS_MASK	0x7f
+#define RTC_DAY_MASK		0x07
+
+/* Bits in the Control/Century register */
+#define RTC_WRITE		0x80
+#define RTC_READ		0x40
+
+/* Bits in the Seconds register */
+#define RTC_STOP		0x80
+
+/* Bits in the Day register */
+#define RTC_BATT_FLAG		0x80
+
+struct rtc_plat_data {
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;
+	unsigned long baseaddr;
+	unsigned long last_jiffies;
+};
+
+static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	u8 century;
+
+	century = BIN2BCD((tm->tm_year + 1900) / 100);
+
+	writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+
+	writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
+	writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+	writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+	writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
+	writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
+	writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
+	writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+
+	/* RTC_CENTURY and RTC_CONTROL share same register */
+	writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
+	writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+	return 0;
+}
+
+static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	unsigned int year, month, day, hour, minute, second, week;
+	unsigned int century;
+
+	/* give enough time to update RTC in case of continuous read */
+	if (pdata->last_jiffies == jiffies)
+		msleep(1);
+	pdata->last_jiffies = jiffies;
+	writeb(RTC_READ, ioaddr + RTC_CONTROL);
+	second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
+	minute = readb(ioaddr + RTC_MINUTES);
+	hour = readb(ioaddr + RTC_HOURS);
+	day = readb(ioaddr + RTC_DATE);
+	week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
+	month = readb(ioaddr + RTC_MONTH);
+	year = readb(ioaddr + RTC_YEAR);
+	century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+	writeb(0, ioaddr + RTC_CONTROL);
+	tm->tm_sec = BCD2BIN(second);
+	tm->tm_min = BCD2BIN(minute);
+	tm->tm_hour = BCD2BIN(hour);
+	tm->tm_mday = BCD2BIN(day);
+	tm->tm_wday = BCD2BIN(week);
+	tm->tm_mon = BCD2BIN(month) - 1;
+	/* year is 1900 + tm->tm_year */
+	tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+
+	if (rtc_valid_tm(tm) < 0) {
+		dev_err(dev, "retrieved date/time is not valid.\n");
+		rtc_time_to_tm(0, tm);
+	}
+	return 0;
+}
+
+static struct rtc_class_ops ds1742_rtc_ops = {
+	.read_time	= ds1742_rtc_read_time,
+	.set_time	= ds1742_rtc_set_time,
+};
+
+static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
+				 loff_t pos, size_t size)
+{
+	struct platform_device *pdev =
+		to_platform_device(container_of(kobj, struct device, kobj));
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	ssize_t count;
+
+	for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+		*buf++ = readb(ioaddr + pos++);
+	return count;
+}
+
+static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
+				  loff_t pos, size_t size)
+{
+	struct platform_device *pdev =
+		to_platform_device(container_of(kobj, struct device, kobj));
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+	void __iomem *ioaddr = pdata->ioaddr;
+	ssize_t count;
+
+	for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+		writeb(*buf++, ioaddr + pos++);
+	return count;
+}
+
+static struct bin_attribute ds1742_nvram_attr = {
+	.attr = {
+		.name = "nvram",
+		.mode = S_IRUGO | S_IWUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = RTC_OFFSET,
+	.read = ds1742_nvram_read,
+	.write = ds1742_nvram_write,
+};
+
+static int __init ds1742_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+	unsigned int cen, sec;
+	struct rtc_plat_data *pdata = NULL;
+	void __iomem *ioaddr = NULL;
+	int ret = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
+		ret = -EBUSY;
+		goto out;
+	}
+	pdata->baseaddr = res->start;
+	ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
+	if (!ioaddr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	pdata->ioaddr = ioaddr;
+
+	/* turn RTC on if it was not on */
+	sec = readb(ioaddr + RTC_SECONDS);
+	if (sec & RTC_STOP) {
+		sec &= RTC_SECONDS_MASK;
+		cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+		writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+		writeb(sec, ioaddr + RTC_SECONDS);
+		writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+	}
+	if (readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)
+		dev_warn(&pdev->dev, "voltage-low detected.\n");
+
+	rtc = rtc_device_register(pdev->name, &pdev->dev,
+				  &ds1742_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		ret = PTR_ERR(rtc);
+		goto out;
+	}
+	pdata->rtc = rtc;
+	pdata->last_jiffies = jiffies;
+	platform_set_drvdata(pdev, pdata);
+	sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+	return 0;
+ out:
+	if (ioaddr)
+		iounmap(ioaddr);
+	if (pdata->baseaddr)
+		release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+	kfree(pdata);
+	return ret;
+}
+
+static int __devexit ds1742_rtc_remove(struct platform_device *pdev)
+{
+	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+	sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+	rtc_device_unregister(pdata->rtc);
+	iounmap(pdata->ioaddr);
+	release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+	kfree(pdata);
+	return 0;
+}
+
+static struct platform_driver ds1742_rtc_driver = {
+	.probe		= ds1742_rtc_probe,
+	.remove		= __devexit_p(ds1742_rtc_remove),
+	.driver		= {
+		.name	= "ds1742",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int ds1742_init(void)
+{
+	return platform_driver_register(&ds1742_rtc_driver);
+}
+
+static __exit void ds1742_exit(void)
+{
+	return platform_driver_unregister(&ds1742_rtc_driver);
+}
+
+module_init(ds1742_init);
+module_exit(ds1742_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index cfedc1d..9812120 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -18,9 +18,19 @@
 	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 };
 
+static const unsigned short rtc_ydays[2][13] = {
+	/* Normal years */
+	{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+	/* Leap years */
+	{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
+
 #define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
 #define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
 
+/*
+ * The number of days in the month.
+ */
 int rtc_month_days(unsigned int month, unsigned int year)
 {
 	return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1);
@@ -28,6 +38,15 @@
 EXPORT_SYMBOL(rtc_month_days);
 
 /*
+ * The number of days since January 1. (0 to 365)
+ */
+int rtc_year_days(unsigned int day, unsigned int month, unsigned int year)
+{
+	return rtc_ydays[LEAP_YEAR(year)][month] + day-1;
+}
+EXPORT_SYMBOL(rtc_year_days);
+
+/*
  * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
  */
 void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
new file mode 100644
index 0000000..2c97395
--- /dev/null
+++ b/drivers/rtc/rtc-max6902.c
@@ -0,0 +1,286 @@
+/* drivers/char/max6902.c
+ *
+ * Copyright (C) 2006 8D Technologies inc.
+ * Copyright (C) 2004 Compulab Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver for MAX6902 spi RTC
+ *
+ * Changelog:
+ *
+ * 24-May-2006: Raphael Assenat <raph@8d.com>
+ *                - Major rework
+ *   				Converted to rtc_device and uses the SPI layer.
+ *
+ * ??-???-2005: Someone at Compulab
+ *                - Initial driver creation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+#include <linux/delay.h>
+
+#define MAX6902_REG_SECONDS		0x01
+#define MAX6902_REG_MINUTES		0x03
+#define MAX6902_REG_HOURS		0x05
+#define MAX6902_REG_DATE		0x07
+#define MAX6902_REG_MONTH		0x09
+#define MAX6902_REG_DAY			0x0B
+#define MAX6902_REG_YEAR		0x0D
+#define MAX6902_REG_CONTROL		0x0F
+#define MAX6902_REG_CENTURY		0x13
+
+#undef MAX6902_DEBUG
+
+struct max6902 {
+	struct rtc_device *rtc;
+	u8 buf[9]; /* Burst read cmd + 8 registers */
+	u8 tx_buf[2];
+	u8 rx_buf[2];
+};
+
+static void max6902_set_reg(struct device *dev, unsigned char address,
+				unsigned char data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	unsigned char buf[2];
+
+	/* MSB must be '0' to write */
+	buf[0] = address & 0x7f;
+	buf[1] = data;
+
+	spi_write(spi, buf, 2);
+}
+
+static int max6902_get_reg(struct device *dev, unsigned char address,
+				unsigned char *data)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct max6902 *chip = dev_get_drvdata(dev);
+	struct spi_message message;
+	struct spi_transfer xfer;
+	int status;
+
+	if (!data)
+		return -EINVAL;
+
+	/* Build our spi message */
+	spi_message_init(&message);
+	memset(&xfer, 0, sizeof(xfer));
+	xfer.len = 2;
+	/* Can tx_buf and rx_buf be equal? The doc in spi.h is not sure... */
+	xfer.tx_buf = chip->tx_buf;
+	xfer.rx_buf = chip->rx_buf;
+
+	/* Set MSB to indicate read */
+	chip->tx_buf[0] = address | 0x80;
+
+	spi_message_add_tail(&xfer, &message);
+
+	/* do the i/o */
+	status = spi_sync(spi, &message);
+	if (status == 0)
+		status = message.status;
+	else
+		return status;
+
+	*data = chip->rx_buf[1];
+
+	return status;
+}
+
+static int max6902_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+	unsigned char tmp;
+	int century;
+	int err;
+	struct spi_device *spi = to_spi_device(dev);
+	struct max6902 *chip = dev_get_drvdata(dev);
+	struct spi_message message;
+	struct spi_transfer xfer;
+	int status;
+
+	err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &tmp);
+	if (err)
+		return err;
+
+	/* build the message */
+	spi_message_init(&message);
+	memset(&xfer, 0, sizeof(xfer));
+	xfer.len = 1 + 7;	/* Burst read command + 7 registers */
+	xfer.tx_buf = chip->buf;
+	xfer.rx_buf = chip->buf;
+	chip->buf[0] = 0xbf;	/* Burst read */
+	spi_message_add_tail(&xfer, &message);
+
+	/* do the i/o */
+	status = spi_sync(spi, &message);
+	if (status == 0)
+		status = message.status;
+	else
+		return status;
+
+	/* The chip sends data in this order:
+	 * Seconds, Minutes, Hours, Date, Month, Day, Year */
+	dt->tm_sec	= BCD2BIN(chip->buf[1]);
+	dt->tm_min	= BCD2BIN(chip->buf[2]);
+	dt->tm_hour	= BCD2BIN(chip->buf[3]);
+	dt->tm_mday	= BCD2BIN(chip->buf[4]);
+	dt->tm_mon	= BCD2BIN(chip->buf[5] - 1);
+	dt->tm_wday	= BCD2BIN(chip->buf[6]);
+	dt->tm_year = BCD2BIN(chip->buf[7]);
+
+	century = BCD2BIN(tmp) * 100;
+
+	dt->tm_year += century;
+	dt->tm_year -= 1900;
+
+#ifdef MAX6902_DEBUG
+	printk("\n%s : Read RTC values\n",__FUNCTION__);
+	printk("tm_hour: %i\n",dt->tm_hour);
+	printk("tm_min : %i\n",dt->tm_min);
+	printk("tm_sec : %i\n",dt->tm_sec);
+	printk("tm_year: %i\n",dt->tm_year);
+	printk("tm_mon : %i\n",dt->tm_mon);
+	printk("tm_mday: %i\n",dt->tm_mday);
+	printk("tm_wday: %i\n",dt->tm_wday);
+#endif
+
+	return 0;
+}
+
+static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+	dt->tm_year = dt->tm_year+1900;
+
+#ifdef MAX6902_DEBUG
+	printk("\n%s : Setting RTC values\n",__FUNCTION__);
+	printk("tm_sec : %i\n",dt->tm_sec);
+	printk("tm_min : %i\n",dt->tm_min);
+	printk("tm_hour: %i\n",dt->tm_hour);
+	printk("tm_mday: %i\n",dt->tm_mday);
+	printk("tm_wday: %i\n",dt->tm_wday);
+	printk("tm_year: %i\n",dt->tm_year);
+#endif
+
+	/* Remove write protection */
+	max6902_set_reg(dev, 0xF, 0);
+
+	max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec));
+	max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min));
+	max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour));
+
+	max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday));
+	max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1));
+	max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday));
+	max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100));
+	max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100));
+
+	/* Compulab used a delay here. However, the datasheet
+	 * does not mention a delay being required anywhere... */
+	/* delay(2000); */
+
+	/* Write protect */
+	max6902_set_reg(dev, 0xF, 0x80);
+
+	return 0;
+}
+
+static int max6902_read_time(struct device *dev, struct rtc_time *tm)
+{
+	return max6902_get_datetime(dev, tm);
+}
+
+static int max6902_set_time(struct device *dev, struct rtc_time *tm)
+{
+	return max6902_set_datetime(dev, tm);
+}
+
+static struct rtc_class_ops max6902_rtc_ops = {
+	.read_time	= max6902_read_time,
+	.set_time	= max6902_set_time,
+};
+
+static int __devinit max6902_probe(struct spi_device *spi)
+{
+	struct rtc_device *rtc;
+	unsigned char tmp;
+	struct max6902 *chip;
+	int res;
+
+	rtc = rtc_device_register("max6902",
+				&spi->dev, &max6902_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	spi->mode = SPI_MODE_3;
+	spi->bits_per_word = 8;
+	spi_setup(spi);
+
+	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	if (!chip) {
+		rtc_device_unregister(rtc);
+		return -ENOMEM;
+	}
+	chip->rtc = rtc;
+	dev_set_drvdata(&spi->dev, chip);
+
+	res = max6902_get_reg(&spi->dev, MAX6902_REG_SECONDS, &tmp);
+	if (res) {
+		rtc_device_unregister(rtc);
+		return res;
+	}
+
+	return 0;
+}
+
+static int __devexit max6902_remove(struct spi_device *spi)
+{
+	struct max6902 *chip = platform_get_drvdata(spi);
+	struct rtc_device *rtc = chip->rtc;
+
+	if (rtc)
+		rtc_device_unregister(rtc);
+
+	kfree(chip);
+
+	return 0;
+}
+
+static struct spi_driver max6902_driver = {
+	.driver = {
+		.name 	= "max6902",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe 	= max6902_probe,
+	.remove = __devexit_p(max6902_remove),
+};
+
+static __init int max6902_init(void)
+{
+	printk("max6902 spi driver\n");
+	return spi_register_driver(&max6902_driver);
+}
+module_init(max6902_init);
+
+static __exit void max6902_exit(void)
+{
+	spi_unregister_driver(&max6902_driver);
+}
+module_exit(max6902_exit);
+
+MODULE_DESCRIPTION ("max6902 spi RTC driver");
+MODULE_AUTHOR ("Raphael Assenat");
+MODULE_LICENSE ("GPL");
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
new file mode 100644
index 0000000..b235a30
--- /dev/null
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -0,0 +1,394 @@
+/*
+ *  drivers/rtc/rtc-pcf8583.c
+ *
+ *  Copyright (C) 2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Driver for PCF8583 RTC & RAM chip
+ *
+ *  Converted to the generic RTC susbsystem by G. Liakhovetski (2006)
+ */
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/bcd.h>
+
+struct rtc_mem {
+	unsigned int	loc;
+	unsigned int	nr;
+	unsigned char	*data;
+};
+
+struct pcf8583 {
+	struct i2c_client client;
+	struct rtc_device *rtc;
+	unsigned char ctrl;
+};
+
+#define CTRL_STOP	0x80
+#define CTRL_HOLD	0x40
+#define CTRL_32KHZ	0x00
+#define CTRL_MASK	0x08
+#define CTRL_ALARMEN	0x04
+#define CTRL_ALARM	0x02
+#define CTRL_TIMER	0x01
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Module parameters */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver pcf8583_driver;
+
+#define get_ctrl(x)    ((struct pcf8583 *)i2c_get_clientdata(x))->ctrl
+#define set_ctrl(x, v) get_ctrl(x) = v
+
+#define CMOS_YEAR	(64 + 128)
+#define CMOS_CHECKSUM	(63)
+
+static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+	unsigned char buf[8], addr[1] = { 1 };
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = 6,
+			.buf = buf,
+		}
+	};
+	int ret;
+
+	memset(buf, 0, sizeof(buf));
+
+	ret = i2c_transfer(client->adapter, msgs, 2);
+	if (ret == 2) {
+		dt->tm_year = buf[4] >> 6;
+		dt->tm_wday = buf[5] >> 5;
+
+		buf[4] &= 0x3f;
+		buf[5] &= 0x1f;
+
+		dt->tm_sec = BCD_TO_BIN(buf[1]);
+		dt->tm_min = BCD_TO_BIN(buf[2]);
+		dt->tm_hour = BCD_TO_BIN(buf[3]);
+		dt->tm_mday = BCD_TO_BIN(buf[4]);
+		dt->tm_mon = BCD_TO_BIN(buf[5]);
+	}
+
+	return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
+{
+	unsigned char buf[8];
+	int ret, len = 6;
+
+	buf[0] = 0;
+	buf[1] = get_ctrl(client) | 0x80;
+	buf[2] = 0;
+	buf[3] = BIN_TO_BCD(dt->tm_sec);
+	buf[4] = BIN_TO_BCD(dt->tm_min);
+	buf[5] = BIN_TO_BCD(dt->tm_hour);
+
+	if (datetoo) {
+		len = 8;
+		buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6);
+		buf[7] = BIN_TO_BCD(dt->tm_mon)  | (dt->tm_wday << 5);
+	}
+
+	ret = i2c_master_send(client, (char *)buf, len);
+	if (ret != len)
+		return -EIO;
+
+	buf[1] = get_ctrl(client);
+	ret = i2c_master_send(client, (char *)buf, 2);
+
+	return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+	*ctrl = get_ctrl(client);
+	return 0;
+}
+
+static int pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+	unsigned char buf[2];
+
+	buf[0] = 0;
+	buf[1] = *ctrl;
+	set_ctrl(client, *ctrl);
+
+	return i2c_master_send(client, (char *)buf, 2);
+}
+
+static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+			.len = mem->nr,
+			.buf = mem->data,
+		}
+	};
+
+	if (mem->loc < 8)
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+	unsigned char addr[1];
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = client->addr,
+			.flags = 0,
+			.len = 1,
+			.buf = addr,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_NOSTART,
+			.len = mem->nr,
+			.buf = mem->data,
+		}
+	};
+
+	if (mem->loc < 8)
+		return -EINVAL;
+
+	addr[0] = mem->loc;
+
+	return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char ctrl, year[2];
+	struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year };
+	int real_year, year_offset, err;
+
+	/*
+	 * Ensure that the RTC is running.
+	 */
+	pcf8583_get_ctrl(client, &ctrl);
+	if (ctrl & (CTRL_STOP | CTRL_HOLD)) {
+		unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD);
+
+		printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n",
+		       ctrl, new_ctrl);
+
+		if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0)
+			return err;
+	}
+
+	if (pcf8583_get_datetime(client, tm) ||
+	    pcf8583_read_mem(client, &mem))
+		return -EIO;
+
+	real_year = year[0];
+
+	/*
+	 * The RTC year holds the LSB two bits of the current
+	 * year, which should reflect the LSB two bits of the
+	 * CMOS copy of the year.  Any difference indicates
+	 * that we have to correct the CMOS version.
+	 */
+	year_offset = tm->tm_year - (real_year & 3);
+	if (year_offset < 0)
+		/*
+		 * RTC year wrapped.  Adjust it appropriately.
+		 */
+		year_offset += 4;
+
+	tm->tm_year = real_year + year_offset + year[1] * 100;
+
+	return 0;
+}
+
+static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned char year[2], chk;
+	struct rtc_mem cmos_year  = { CMOS_YEAR, sizeof(year), year };
+	struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
+	int ret;
+
+	/*
+	 * The RTC's own 2-bit year must reflect the least
+	 * significant two bits of the CMOS year.
+	 */
+
+	ret = pcf8583_set_datetime(client, tm, 1);
+	if (ret)
+		return ret;
+
+	ret = pcf8583_read_mem(client, &cmos_check);
+	if (ret)
+		return ret;
+
+	ret = pcf8583_read_mem(client, &cmos_year);
+	if (ret)
+		return ret;
+
+	chk -= year[1] + year[0];
+
+	year[1] = tm->tm_year / 100;
+	year[0] = tm->tm_year % 100;
+
+	chk += year[1] + year[0];
+
+	ret = pcf8583_write_mem(client, &cmos_year);
+
+	if (ret)
+		return ret;
+
+	ret = pcf8583_write_mem(client, &cmos_check);
+
+	return ret;
+}
+
+static struct rtc_class_ops pcf8583_rtc_ops = {
+	.read_time	= pcf8583_rtc_read_time,
+	.set_time	= pcf8583_rtc_set_time,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind);
+
+static int pcf8583_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, pcf8583_probe);
+}
+
+static int pcf8583_detach(struct i2c_client *client)
+{
+	int err;
+	struct pcf8583 *pcf = i2c_get_clientdata(client);
+	struct rtc_device *rtc = pcf->rtc;
+
+	if (rtc)
+		rtc_device_unregister(rtc);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(pcf);
+	return 0;
+}
+
+static struct i2c_driver pcf8583_driver = {
+	.driver = {
+		.name	= "pcf8583",
+	},
+	.id		= I2C_DRIVERID_PCF8583,
+	.attach_adapter	= pcf8583_attach,
+	.detach_client	= pcf8583_detach,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct pcf8583 *pcf;
+	struct i2c_client *client;
+	struct rtc_device *rtc;
+	unsigned char buf[1], ad[1] = { 0 };
+	int err;
+	struct i2c_msg msgs[2] = {
+		{
+			.addr = addr,
+			.flags = 0,
+			.len = 1,
+			.buf = ad,
+		}, {
+			.addr = addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = buf,
+		}
+	};
+
+	pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
+	if (!pcf)
+		return -ENOMEM;
+
+	client = &pcf->client;
+
+	client->addr		= addr;
+	client->adapter	= adap;
+	client->driver	= &pcf8583_driver;
+
+	strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE);
+
+	if (i2c_transfer(client->adapter, msgs, 2) != 2) {
+		err = -EIO;
+		goto exit_kfree;
+	}
+
+	err = i2c_attach_client(client);
+
+	if (err)
+		goto exit_kfree;
+
+	rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev,
+				  &pcf8583_rtc_ops, THIS_MODULE);
+
+	if (IS_ERR(rtc)) {
+		err = PTR_ERR(rtc);
+		goto exit_detach;
+	}
+
+	pcf->rtc = rtc;
+	i2c_set_clientdata(client, pcf);
+	set_ctrl(client, buf[0]);
+
+	return 0;
+
+exit_detach:
+	i2c_detach_client(client);
+
+exit_kfree:
+	kfree(pcf);
+
+	return err;
+}
+
+static __init int pcf8583_init(void)
+{
+	return i2c_add_driver(&pcf8583_driver);
+}
+
+static __exit void pcf8583_exit(void)
+{
+	i2c_del_driver(&pcf8583_driver);
+}
+
+module_init(pcf8583_init);
+module_exit(pcf8583_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
new file mode 100644
index 0000000..ee53863
--- /dev/null
+++ b/drivers/rtc/rtc-pl031.c
@@ -0,0 +1,233 @@
+/*
+ * drivers/rtc/rtc-pl031.c
+ *
+ * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2006 (c) MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+
+#include <linux/amba/bus.h>
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+
+/*
+ * Register definitions
+ */
+#define	RTC_DR		0x00	/* Data read register */
+#define	RTC_MR		0x04	/* Match register */
+#define	RTC_LR		0x08	/* Data load register */
+#define	RTC_CR		0x0c	/* Control register */
+#define	RTC_IMSC	0x10	/* Interrupt mask and set register */
+#define	RTC_RIS		0x14	/* Raw interrupt status register */
+#define	RTC_MIS		0x18	/* Masked interrupt status register */
+#define	RTC_ICR		0x1c	/* Interrupt clear register */
+
+struct pl031_local {
+	struct rtc_device *rtc;
+	void __iomem *base;
+};
+
+static irqreturn_t pl031_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct rtc_device *rtc = dev_id;
+
+	rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
+
+	return IRQ_HANDLED;
+}
+
+static int pl031_open(struct device *dev)
+{
+	/*
+	 * We request IRQ in pl031_probe, so nothing to do here...
+	 */
+	return 0;
+}
+
+static void pl031_release(struct device *dev)
+{
+}
+
+static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+	struct pl031_local *ldata = dev_get_drvdata(dev);
+
+	switch (cmd) {
+	case RTC_AIE_OFF:
+		__raw_writel(1, ldata->base + RTC_MIS);
+		return 0;
+	case RTC_AIE_ON:
+		__raw_writel(0, ldata->base + RTC_MIS);
+		return 0;
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static int pl031_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct pl031_local *ldata = dev_get_drvdata(dev);
+
+	rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm);
+
+	return 0;
+}
+
+static int pl031_set_time(struct device *dev, struct rtc_time *tm)
+{
+	unsigned long time;
+	struct pl031_local *ldata = dev_get_drvdata(dev);
+
+	rtc_tm_to_time(tm, &time);
+	__raw_writel(time, ldata->base + RTC_LR);
+
+	return 0;
+}
+
+static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct pl031_local *ldata = dev_get_drvdata(dev);
+
+	rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time);
+	alarm->pending = __raw_readl(ldata->base + RTC_RIS);
+	alarm->enabled = __raw_readl(ldata->base + RTC_IMSC);
+
+	return 0;
+}
+
+static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct pl031_local *ldata = dev_get_drvdata(dev);
+	unsigned long time;
+
+	rtc_tm_to_time(&alarm->time, &time);
+
+	__raw_writel(time, ldata->base + RTC_MR);
+	__raw_writel(!alarm->enabled, ldata->base + RTC_MIS);
+
+	return 0;
+}
+
+static struct rtc_class_ops pl031_ops = {
+	.open = pl031_open,
+	.release = pl031_release,
+	.ioctl = pl031_ioctl,
+	.read_time = pl031_read_time,
+	.set_time = pl031_set_time,
+	.read_alarm = pl031_read_alarm,
+	.set_alarm = pl031_set_alarm,
+};
+
+static int pl031_remove(struct amba_device *adev)
+{
+	struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
+
+	if (ldata) {
+		dev_set_drvdata(&adev->dev, NULL);
+		free_irq(adev->irq[0], ldata->rtc);
+		rtc_device_unregister(ldata->rtc);
+		iounmap(ldata->base);
+		kfree(ldata);
+	}
+
+	return 0;
+}
+
+static int pl031_probe(struct amba_device *adev, void *id)
+{
+	int ret;
+	struct pl031_local *ldata;
+
+
+	ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL);
+	if (!ldata) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	dev_set_drvdata(&adev->dev, ldata);
+
+	ldata->base = ioremap(adev->res.start,
+			      adev->res.end - adev->res.start + 1);
+	if (!ldata->base) {
+		ret = -ENOMEM;
+		goto out_no_remap;
+	}
+
+	if (request_irq(adev->irq[0], pl031_interrupt, SA_INTERRUPT,
+			"rtc-pl031", ldata->rtc)) {
+		ret = -EIO;
+		goto out_no_irq;
+	}
+
+	ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops,
+					 THIS_MODULE);
+	if (IS_ERR(ldata->rtc)) {
+		ret = PTR_ERR(ldata->rtc);
+		goto out_no_rtc;
+	}
+
+	return 0;
+
+out_no_rtc:
+	free_irq(adev->irq[0], ldata->rtc);
+out_no_irq:
+	iounmap(ldata->base);
+out_no_remap:
+	dev_set_drvdata(&adev->dev, NULL);
+	kfree(ldata);
+out:
+	return ret;
+}
+
+static struct amba_id pl031_ids[] __initdata = {
+	{
+		 .id = 0x00041031,
+	 	.mask = 0x000fffff, },
+	{0, 0},
+};
+
+static struct amba_driver pl031_driver = {
+	.drv = {
+		.name = "rtc-pl031",
+	},
+	.id_table = pl031_ids,
+	.probe = pl031_probe,
+	.remove = pl031_remove,
+};
+
+static int __init pl031_init(void)
+{
+	return amba_driver_register(&pl031_driver);
+}
+
+static void __exit pl031_exit(void)
+{
+	amba_driver_unregister(&pl031_driver);
+}
+
+module_init(pl031_init);
+module_exit(pl031_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net");
+MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c
new file mode 100644
index 0000000..0964d1d
--- /dev/null
+++ b/drivers/rtc/rtc-rs5c348.c
@@ -0,0 +1,246 @@
+/*
+ * A SPI driver for the Ricoh RS5C348 RTC
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The board specific init code should provide characteristics of this
+ * device:
+ *     Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS
+ */
+
+#include <linux/bcd.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+
+#define DRV_VERSION "0.1"
+
+#define RS5C348_REG_SECS	0
+#define RS5C348_REG_MINS	1
+#define RS5C348_REG_HOURS	2
+#define RS5C348_REG_WDAY	3
+#define RS5C348_REG_DAY	4
+#define RS5C348_REG_MONTH	5
+#define RS5C348_REG_YEAR	6
+#define RS5C348_REG_CTL1	14
+#define RS5C348_REG_CTL2	15
+
+#define RS5C348_SECS_MASK	0x7f
+#define RS5C348_MINS_MASK	0x7f
+#define RS5C348_HOURS_MASK	0x3f
+#define RS5C348_WDAY_MASK	0x03
+#define RS5C348_DAY_MASK	0x3f
+#define RS5C348_MONTH_MASK	0x1f
+
+#define RS5C348_BIT_PM	0x20	/* REG_HOURS */
+#define RS5C348_BIT_Y2K	0x80	/* REG_MONTH */
+#define RS5C348_BIT_24H	0x20	/* REG_CTL1 */
+#define RS5C348_BIT_XSTP	0x10	/* REG_CTL2 */
+#define RS5C348_BIT_VDET	0x40	/* REG_CTL2 */
+
+#define RS5C348_CMD_W(addr)	(((addr) << 4) | 0x08)	/* single write */
+#define RS5C348_CMD_R(addr)	(((addr) << 4) | 0x0c)	/* single read */
+#define RS5C348_CMD_MW(addr)	(((addr) << 4) | 0x00)	/* burst write */
+#define RS5C348_CMD_MR(addr)	(((addr) << 4) | 0x04)	/* burst read */
+
+struct rs5c348_plat_data {
+	struct rtc_device *rtc;
+	int rtc_24h;
+};
+
+static int
+rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+	u8 txbuf[5+7], *txp;
+	int ret;
+
+	/* Transfer 5 bytes before writing SEC.  This gives 31us for carry. */
+	txp = txbuf;
+	txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+	txbuf[1] = 0;	/* dummy */
+	txbuf[2] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+	txbuf[3] = 0;	/* dummy */
+	txbuf[4] = RS5C348_CMD_MW(RS5C348_REG_SECS); /* cmd, sec, ... */
+	txp = &txbuf[5];
+	txp[RS5C348_REG_SECS] = BIN2BCD(tm->tm_sec);
+	txp[RS5C348_REG_MINS] = BIN2BCD(tm->tm_min);
+	if (pdata->rtc_24h) {
+		txp[RS5C348_REG_HOURS] = BIN2BCD(tm->tm_hour);
+	} else {
+		/* hour 0 is AM12, noon is PM12 */
+		txp[RS5C348_REG_HOURS] = BIN2BCD((tm->tm_hour + 11) % 12 + 1) |
+			(tm->tm_hour >= 12 ? RS5C348_BIT_PM : 0);
+	}
+	txp[RS5C348_REG_WDAY] = BIN2BCD(tm->tm_wday);
+	txp[RS5C348_REG_DAY] = BIN2BCD(tm->tm_mday);
+	txp[RS5C348_REG_MONTH] = BIN2BCD(tm->tm_mon + 1) |
+		(tm->tm_year >= 100 ? RS5C348_BIT_Y2K : 0);
+	txp[RS5C348_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+	/* write in one transfer to avoid data inconsistency */
+	ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), NULL, 0);
+	udelay(62);	/* Tcsr 62us */
+	return ret;
+}
+
+static int
+rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+	u8 txbuf[5], rxbuf[7];
+	int ret;
+
+	/* Transfer 5 byte befores reading SEC.  This gives 31us for carry. */
+	txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+	txbuf[1] = 0;	/* dummy */
+	txbuf[2] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */
+	txbuf[3] = 0;	/* dummy */
+	txbuf[4] = RS5C348_CMD_MR(RS5C348_REG_SECS); /* cmd, sec, ... */
+
+	/* read in one transfer to avoid data inconsistency */
+	ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
+				  rxbuf, sizeof(rxbuf));
+	udelay(62);	/* Tcsr 62us */
+	if (ret < 0)
+		return ret;
+
+	tm->tm_sec = BCD2BIN(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK);
+	tm->tm_min = BCD2BIN(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
+	tm->tm_hour = BCD2BIN(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
+	if (!pdata->rtc_24h) {
+		tm->tm_hour %= 12;
+		if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM)
+			tm->tm_hour += 12;
+	}
+	tm->tm_wday = BCD2BIN(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
+	tm->tm_mday = BCD2BIN(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
+	tm->tm_mon =
+		BCD2BIN(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1;
+	/* year is 1900 + tm->tm_year */
+	tm->tm_year = BCD2BIN(rxbuf[RS5C348_REG_YEAR]) +
+		((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0);
+
+	if (rtc_valid_tm(tm) < 0) {
+		dev_err(&spi->dev, "retrieved date/time is not valid.\n");
+		rtc_time_to_tm(0, tm);
+	}
+
+	return 0;
+}
+
+static struct rtc_class_ops rs5c348_rtc_ops = {
+	.read_time	= rs5c348_rtc_read_time,
+	.set_time	= rs5c348_rtc_set_time,
+};
+
+static struct spi_driver rs5c348_driver;
+
+static int __devinit rs5c348_probe(struct spi_device *spi)
+{
+	int ret;
+	struct rtc_device *rtc;
+	struct rs5c348_plat_data *pdata;
+
+	pdata = kzalloc(sizeof(struct rs5c348_plat_data), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+	spi->dev.platform_data = pdata;
+
+	/* Check D7 of SECOND register */
+	ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_SECS));
+	if (ret < 0 || (ret & 0x80)) {
+		dev_err(&spi->dev, "not found.\n");
+		goto kfree_exit;
+	}
+
+	dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n");
+	dev_info(&spi->dev, "spiclk %u KHz.\n",
+		 (spi->max_speed_hz + 500) / 1000);
+
+	/* turn RTC on if it was not on */
+	ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2));
+	if (ret < 0)
+		goto kfree_exit;
+	if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) {
+		u8 buf[2];
+		if (ret & RS5C348_BIT_VDET)
+			dev_warn(&spi->dev, "voltage-low detected.\n");
+		buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2);
+		buf[1] = 0;
+		ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0);
+		if (ret < 0)
+			goto kfree_exit;
+	}
+
+	ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL1));
+	if (ret < 0)
+		goto kfree_exit;
+	if (ret & RS5C348_BIT_24H)
+		pdata->rtc_24h = 1;
+
+	rtc = rtc_device_register(rs5c348_driver.driver.name, &spi->dev,
+				  &rs5c348_rtc_ops, THIS_MODULE);
+
+	if (IS_ERR(rtc)) {
+		ret = PTR_ERR(rtc);
+		goto kfree_exit;
+	}
+
+	pdata->rtc = rtc;
+
+	return 0;
+ kfree_exit:
+	kfree(pdata);
+	return ret;
+}
+
+static int __devexit rs5c348_remove(struct spi_device *spi)
+{
+	struct rs5c348_plat_data *pdata = spi->dev.platform_data;
+	struct rtc_device *rtc = pdata->rtc;
+
+	if (rtc)
+		rtc_device_unregister(rtc);
+	kfree(pdata);
+	return 0;
+}
+
+static struct spi_driver rs5c348_driver = {
+	.driver = {
+		.name	= "rs5c348",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+	.probe	= rs5c348_probe,
+	.remove	= __devexit_p(rs5c348_remove),
+};
+
+static __init int rs5c348_init(void)
+{
+	return spi_register_driver(&rs5c348_driver);
+}
+
+static __exit void rs5c348_exit(void)
+{
+	spi_unregister_driver(&rs5c348_driver);
+}
+
+module_init(rs5c348_init);
+module_exit(rs5c348_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index a997529..9cd1cb3 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -45,7 +45,7 @@
 
 static unsigned long rtc_freq = 1024;
 static struct rtc_time rtc_alarm;
-static spinlock_t sa1100_rtc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(sa1100_rtc_lock);
 
 static int rtc_update_alarm(struct rtc_time *alrm)
 {
@@ -229,8 +229,6 @@
 		spin_unlock_irq(&sa1100_rtc_lock);
 		return 0;
 	case RTC_PIE_ON:
-		if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
-			return -EACCES;
 		spin_lock_irq(&sa1100_rtc_lock);
 		OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
 		OIER |= OIER_E1;
@@ -242,8 +240,6 @@
 	case RTC_IRQP_SET:
 		if (arg < 1 || arg > TIMER_FREQ)
 			return -EINVAL;
-		if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
-			return -EACCES;
 		rtc_freq = arg;
 		return 0;
 	}
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
new file mode 100644
index 0000000..a40f400
--- /dev/null
+++ b/drivers/rtc/rtc-v3020.c
@@ -0,0 +1,264 @@
+/* drivers/rtc/rtc-v3020.c
+ *
+ * Copyright (C) 2006 8D Technologies inc.
+ * Copyright (C) 2004 Compulab Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Driver for the V3020 RTC
+ *
+ * Changelog:
+ *
+ *  10-May-2006: Raphael Assenat <raph@8d.com>
+ *				- Converted to platform driver
+ *				- Use the generic rtc class
+ *
+ *  ??-???-2004: Someone at Compulab
+ *  			- Initial driver creation.
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/types.h>
+#include <linux/bcd.h>
+#include <linux/rtc-v3020.h>
+
+#include <asm/io.h>
+
+#undef DEBUG
+
+struct v3020 {
+	void __iomem *ioaddress;
+	int leftshift;
+	struct rtc_device *rtc;
+};
+
+static void v3020_set_reg(struct v3020 *chip, unsigned char address,
+			unsigned char data)
+{
+	int i;
+	unsigned char tmp;
+
+	tmp = address;
+	for (i = 0; i < 4; i++) {
+		writel((tmp & 1) << chip->leftshift, chip->ioaddress);
+		tmp >>= 1;
+	}
+
+	/* Commands dont have data */
+	if (!V3020_IS_COMMAND(address)) {
+		for (i = 0; i < 8; i++) {
+			writel((data & 1) << chip->leftshift, chip->ioaddress);
+			data >>= 1;
+		}
+	}
+}
+
+static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address)
+{
+	unsigned int data=0;
+	int i;
+
+	for (i = 0; i < 4; i++) {
+		writel((address & 1) << chip->leftshift, chip->ioaddress);
+		address >>= 1;
+	}
+
+	for (i = 0; i < 8; i++) {
+		data >>= 1;
+		if (readl(chip->ioaddress) & (1 << chip->leftshift))
+			data |= 0x80;
+	}
+
+	return data;
+}
+
+static int v3020_read_time(struct device *dev, struct rtc_time *dt)
+{
+	struct v3020 *chip = dev_get_drvdata(dev);
+	int tmp;
+
+	/* Copy the current time to ram... */
+	v3020_set_reg(chip, V3020_CMD_CLOCK2RAM, 0);
+
+	/* ...and then read constant values. */
+	tmp = v3020_get_reg(chip, V3020_SECONDS);
+	dt->tm_sec	= BCD2BIN(tmp);
+	tmp = v3020_get_reg(chip, V3020_MINUTES);
+	dt->tm_min	= BCD2BIN(tmp);
+	tmp = v3020_get_reg(chip, V3020_HOURS);
+	dt->tm_hour	= BCD2BIN(tmp);
+	tmp = v3020_get_reg(chip, V3020_MONTH_DAY);
+	dt->tm_mday	= BCD2BIN(tmp);
+	tmp = v3020_get_reg(chip, V3020_MONTH);
+	dt->tm_mon	= BCD2BIN(tmp);
+	tmp = v3020_get_reg(chip, V3020_WEEK_DAY);
+	dt->tm_wday	= BCD2BIN(tmp);
+	tmp = v3020_get_reg(chip, V3020_YEAR);
+	dt->tm_year = BCD2BIN(tmp)+100;
+
+#ifdef DEBUG
+	printk("\n%s : Read RTC values\n",__FUNCTION__);
+	printk("tm_hour: %i\n",dt->tm_hour);
+	printk("tm_min : %i\n",dt->tm_min);
+	printk("tm_sec : %i\n",dt->tm_sec);
+	printk("tm_year: %i\n",dt->tm_year);
+	printk("tm_mon : %i\n",dt->tm_mon);
+	printk("tm_mday: %i\n",dt->tm_mday);
+	printk("tm_wday: %i\n",dt->tm_wday);
+#endif
+
+	return 0;
+}
+
+
+static int v3020_set_time(struct device *dev, struct rtc_time *dt)
+{
+	struct v3020 *chip = dev_get_drvdata(dev);
+
+#ifdef DEBUG
+	printk("\n%s : Setting RTC values\n",__FUNCTION__);
+	printk("tm_sec : %i\n",dt->tm_sec);
+	printk("tm_min : %i\n",dt->tm_min);
+	printk("tm_hour: %i\n",dt->tm_hour);
+	printk("tm_mday: %i\n",dt->tm_mday);
+	printk("tm_wday: %i\n",dt->tm_wday);
+	printk("tm_year: %i\n",dt->tm_year);
+#endif
+
+	/* Write all the values to ram... */
+	v3020_set_reg(chip, V3020_SECONDS, 	BIN2BCD(dt->tm_sec));
+	v3020_set_reg(chip, V3020_MINUTES, 	BIN2BCD(dt->tm_min));
+	v3020_set_reg(chip, V3020_HOURS, 	BIN2BCD(dt->tm_hour));
+	v3020_set_reg(chip, V3020_MONTH_DAY,	BIN2BCD(dt->tm_mday));
+	v3020_set_reg(chip, V3020_MONTH, 	BIN2BCD(dt->tm_mon));
+	v3020_set_reg(chip, V3020_WEEK_DAY, 	BIN2BCD(dt->tm_wday));
+	v3020_set_reg(chip, V3020_YEAR, 	BIN2BCD(dt->tm_year % 100));
+
+	/* ...and set the clock. */
+	v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0);
+
+	/* Compulab used this delay here. I dont know why,
+	 * the datasheet does not specify a delay. */
+	/*mdelay(5);*/
+
+	return 0;
+}
+
+static struct rtc_class_ops v3020_rtc_ops = {
+	.read_time	= v3020_read_time,
+	.set_time	= v3020_set_time,
+};
+
+static int rtc_probe(struct platform_device *pdev)
+{
+	struct v3020_platform_data *pdata = pdev->dev.platform_data;
+	struct v3020 *chip;
+	struct rtc_device *rtc;
+	int retval = -EBUSY;
+	int i;
+	int temp;
+
+	if (pdev->num_resources != 1)
+		return -EBUSY;
+
+	if (pdev->resource[0].flags != IORESOURCE_MEM)
+		return -EBUSY;
+
+	if (pdev == NULL)
+		return -EBUSY;
+
+	chip = kzalloc(sizeof *chip, GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->leftshift = pdata->leftshift;
+	chip->ioaddress = ioremap(pdev->resource[0].start, 1);
+	if (chip->ioaddress == NULL)
+		goto err_chip;
+
+	/* Make sure the v3020 expects a communication cycle
+	 * by reading 8 times */
+	for (i = 0; i < 8; i++)
+		temp = readl(chip->ioaddress);
+
+	/* Test chip by doing a write/read sequence
+	 * to the chip ram */
+	v3020_set_reg(chip, V3020_SECONDS, 0x33);
+	if(v3020_get_reg(chip, V3020_SECONDS) != 0x33) {
+		retval = -ENODEV;
+		goto err_io;
+	}
+
+	/* Make sure frequency measurment mode, test modes, and lock
+	 * are all disabled */
+	v3020_set_reg(chip, V3020_STATUS_0, 0x0);
+
+	dev_info(&pdev->dev, "Chip available at physical address 0x%p,"
+		"data connected to D%d\n",
+		(void*)pdev->resource[0].start,
+		chip->leftshift);
+
+	platform_set_drvdata(pdev, chip);
+
+	rtc = rtc_device_register("v3020",
+				&pdev->dev, &v3020_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		retval = PTR_ERR(rtc);
+		goto err_io;
+	}
+	chip->rtc = rtc;
+
+	return 0;
+
+err_io:
+	iounmap(chip->ioaddress);
+err_chip:
+	kfree(chip);
+
+	return retval;
+}
+
+static int rtc_remove(struct platform_device *dev)
+{
+	struct v3020 *chip = platform_get_drvdata(dev);
+	struct rtc_device *rtc = chip->rtc;
+
+	if (rtc)
+		rtc_device_unregister(rtc);
+
+	iounmap(chip->ioaddress);
+	kfree(chip);
+
+	return 0;
+}
+
+static struct platform_driver rtc_device_driver = {
+	.probe	= rtc_probe,
+	.remove = rtc_remove,
+	.driver = {
+		.name	= "v3020",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static __init int v3020_init(void)
+{
+	return platform_driver_register(&rtc_device_driver);
+}
+
+static __exit void v3020_exit(void)
+{
+	platform_driver_unregister(&rtc_device_driver);
+}
+
+module_init(v3020_init);
+module_exit(v3020_exit);
+
+MODULE_DESCRIPTION("V3020 RTC");
+MODULE_AUTHOR("Raphael Assenat");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 277596c..4b9291d 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -81,7 +81,6 @@
 
 #define RTC_FREQUENCY		32768
 #define MAX_PERIODIC_RATE	6553
-#define MAX_USER_PERIODIC_RATE	64
 
 static void __iomem *rtc1_base;
 static void __iomem *rtc2_base;
@@ -94,7 +93,7 @@
 
 static unsigned long epoch = 1970;	/* Jan 1 1970 00:00:00 */
 
-static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(rtc_lock);
 static char rtc_name[] = "RTC";
 static unsigned long periodic_frequency;
 static unsigned long periodic_count;
@@ -240,9 +239,6 @@
 		if (arg > MAX_PERIODIC_RATE)
 			return -EINVAL;
 
-		if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
-			return -EACCES;
-
 		periodic_frequency = arg;
 
 		count = RTC_FREQUENCY;
@@ -263,10 +259,6 @@
 		/* Doesn't support before 1900 */
 		if (arg < 1900)
 			return -EINVAL;
-
-		if (capable(CAP_SYS_TIME) == 0)
-			return -EACCES;
-
 		epoch = arg;
 		break;
 	default:
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index 2d946b6..2d8af70 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -89,7 +89,7 @@
 };
 
 static LIST_HEAD(bufferlist);
-static spinlock_t bufferlock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(bufferlock);
 static DECLARE_WAIT_QUEUE_HEAD(dasd_eer_read_wait_queue);
 
 /*
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 56fa691..a4c53c1 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -13,6 +13,7 @@
 #include <linux/cpumask.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/reboot.h>
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/sigp.h>
@@ -66,8 +67,6 @@
 }
 #endif
 
-extern void ctrl_alt_del(void);
-
 /* Handler for quiesce event. Start shutdown procedure. */
 static void
 sclp_quiesce_handler(struct evbuf_header *evbuf)
diff --git a/drivers/s390/crypto/z90crypt.h b/drivers/s390/crypto/z90crypt.h
index 5e6b1f53..0ca1d12 100644
--- a/drivers/s390/crypto/z90crypt.h
+++ b/drivers/s390/crypto/z90crypt.h
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/s390/crypto/z90crypt.h
  *
- *  z90crypt 1.3.3
+ *  z90crypt 1.3.3 (kernel-private header)
  *
  *  Copyright (C)  2001, 2005 IBM Corporation
  *  Author(s): Robert Burroughs (burrough@us.ibm.com)
@@ -27,188 +27,7 @@
 #ifndef _Z90CRYPT_H_
 #define _Z90CRYPT_H_
 
-#include <linux/ioctl.h>
-
-#define z90crypt_VERSION 1
-#define z90crypt_RELEASE 3	// 2 = PCIXCC, 3 = rewrite for coding standards
-#define z90crypt_VARIANT 3	// 3 = CEX2A support
-
-/**
- * struct ica_rsa_modexpo
- *
- * Requirements:
- * - outputdatalength is at least as large as inputdatalength.
- * - All key parts are right justified in their fields, padded on
- *   the left with zeroes.
- * - length(b_key) = inputdatalength
- * - length(n_modulus) = inputdatalength
- */
-struct ica_rsa_modexpo {
-	char __user *	inputdata;
-	unsigned int	inputdatalength;
-	char __user *	outputdata;
-	unsigned int	outputdatalength;
-	char __user *	b_key;
-	char __user *	n_modulus;
-};
-
-/**
- * struct ica_rsa_modexpo_crt
- *
- * Requirements:
- * - inputdatalength is even.
- * - outputdatalength is at least as large as inputdatalength.
- * - All key parts are right justified in their fields, padded on
- *   the left with zeroes.
- * - length(bp_key)	= inputdatalength/2 + 8
- * - length(bq_key)	= inputdatalength/2
- * - length(np_key)	= inputdatalength/2 + 8
- * - length(nq_key)	= inputdatalength/2
- * - length(u_mult_inv) = inputdatalength/2 + 8
- */
-struct ica_rsa_modexpo_crt {
-	char __user *	inputdata;
-	unsigned int	inputdatalength;
-	char __user *	outputdata;
-	unsigned int	outputdatalength;
-	char __user *	bp_key;
-	char __user *	bq_key;
-	char __user *	np_prime;
-	char __user *	nq_prime;
-	char __user *	u_mult_inv;
-};
-
-#define Z90_IOCTL_MAGIC 'z'  // NOTE:  Need to allocate from linux folks
-
-/**
- * Interface notes:
- *
- * The ioctl()s which are implemented (along with relevant details)
- * are:
- *
- *   ICARSAMODEXPO
- *     Perform an RSA operation using a Modulus-Exponent pair
- *     This takes an ica_rsa_modexpo struct as its arg.
- *
- *     NOTE: please refer to the comments preceding this structure
- *           for the implementation details for the contents of the
- *           block
- *
- *   ICARSACRT
- *     Perform an RSA operation using a Chinese-Remainder Theorem key
- *     This takes an ica_rsa_modexpo_crt struct as its arg.
- *
- *     NOTE: please refer to the comments preceding this structure
- *           for the implementation details for the contents of the
- *           block
- *
- *   Z90STAT_TOTALCOUNT
- *     Return an integer count of all device types together.
- *
- *   Z90STAT_PCICACOUNT
- *     Return an integer count of all PCICAs.
- *
- *   Z90STAT_PCICCCOUNT
- *     Return an integer count of all PCICCs.
- *
- *   Z90STAT_PCIXCCMCL2COUNT
- *     Return an integer count of all MCL2 PCIXCCs.
- *
- *   Z90STAT_PCIXCCMCL3COUNT
- *     Return an integer count of all MCL3 PCIXCCs.
- *
- *   Z90STAT_CEX2CCOUNT
- *     Return an integer count of all CEX2Cs.
- *
- *   Z90STAT_CEX2ACOUNT
- *     Return an integer count of all CEX2As.
- *
- *   Z90STAT_REQUESTQ_COUNT
- *     Return an integer count of the number of entries waiting to be
- *     sent to a device.
- *
- *   Z90STAT_PENDINGQ_COUNT
- *     Return an integer count of the number of entries sent to a
- *     device awaiting the reply.
- *
- *   Z90STAT_TOTALOPEN_COUNT
- *     Return an integer count of the number of open file handles.
- *
- *   Z90STAT_DOMAIN_INDEX
- *     Return the integer value of the Cryptographic Domain.
- *
- *   Z90STAT_STATUS_MASK
- *     Return an 64 element array of unsigned chars for the status of
- *     all devices.
- *       0x01: PCICA
- *       0x02: PCICC
- *       0x03: PCIXCC_MCL2
- *       0x04: PCIXCC_MCL3
- *       0x05: CEX2C
- *       0x06: CEX2A
- *       0x0d: device is disabled via the proc filesystem
- *
- *   Z90STAT_QDEPTH_MASK
- *     Return an 64 element array of unsigned chars for the queue
- *     depth of all devices.
- *
- *   Z90STAT_PERDEV_REQCNT
- *     Return an 64 element array of unsigned integers for the number
- *     of successfully completed requests per device since the device
- *     was detected and made available.
- *
- *   ICAZ90STATUS (deprecated)
- *     Return some device driver status in a ica_z90_status struct
- *     This takes an ica_z90_status struct as its arg.
- *
- *     NOTE: this ioctl() is deprecated, and has been replaced with
- *           single ioctl()s for each type of status being requested
- *
- *   Z90STAT_PCIXCCCOUNT (deprecated)
- *     Return an integer count of all PCIXCCs (MCL2 + MCL3).
- *     This is DEPRECATED now that MCL3 PCIXCCs are treated differently from
- *     MCL2 PCIXCCs.
- *
- *   Z90QUIESCE (not recommended)
- *     Quiesce the driver.  This is intended to stop all new
- *     requests from being processed.  Its use is NOT recommended,
- *     except in circumstances where there is no other way to stop
- *     callers from accessing the driver.  Its original use was to
- *     allow the driver to be "drained" of work in preparation for
- *     a system shutdown.
- *
- *     NOTE: once issued, this ban on new work cannot be undone
- *           except by unloading and reloading the driver.
- */
-
-/**
- * Supported ioctl calls
- */
-#define ICARSAMODEXPO	_IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0)
-#define ICARSACRT	_IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0)
-
-/* DEPRECATED status calls (bound for removal at some point) */
-#define ICAZ90STATUS	_IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status)
-#define Z90STAT_PCIXCCCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x43, int)
-
-/* unrelated to ICA callers */
-#define Z90QUIESCE	_IO(Z90_IOCTL_MAGIC, 0x11)
-
-/* New status calls */
-#define Z90STAT_TOTALCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x40, int)
-#define Z90STAT_PCICACOUNT	_IOR(Z90_IOCTL_MAGIC, 0x41, int)
-#define Z90STAT_PCICCCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x42, int)
-#define Z90STAT_PCIXCCMCL2COUNT	_IOR(Z90_IOCTL_MAGIC, 0x4b, int)
-#define Z90STAT_PCIXCCMCL3COUNT	_IOR(Z90_IOCTL_MAGIC, 0x4c, int)
-#define Z90STAT_CEX2CCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x4d, int)
-#define Z90STAT_CEX2ACOUNT	_IOR(Z90_IOCTL_MAGIC, 0x4e, int)
-#define Z90STAT_REQUESTQ_COUNT	_IOR(Z90_IOCTL_MAGIC, 0x44, int)
-#define Z90STAT_PENDINGQ_COUNT	_IOR(Z90_IOCTL_MAGIC, 0x45, int)
-#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
-#define Z90STAT_DOMAIN_INDEX	_IOR(Z90_IOCTL_MAGIC, 0x47, int)
-#define Z90STAT_STATUS_MASK	_IOR(Z90_IOCTL_MAGIC, 0x48, char[64])
-#define Z90STAT_QDEPTH_MASK	_IOR(Z90_IOCTL_MAGIC, 0x49, char[64])
-#define Z90STAT_PERDEV_REQCNT	_IOR(Z90_IOCTL_MAGIC, 0x4a, int[64])
+#include <asm/z90crypt.h>
 
 /**
  * local errno definitions
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 90d4d0e..6775a83 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -2,7 +2,7 @@
 # S/390 network devices
 #
 
-ctc-objs := ctcmain.o ctctty.o ctcdbug.o
+ctc-objs := ctcmain.o ctcdbug.o
 
 obj-$(CONFIG_IUCV) += iucv.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
@@ -10,6 +10,7 @@
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
 obj-$(CONFIG_LCS) += lcs.o cu3088.o
 obj-$(CONFIG_CLAW) += claw.o cu3088.o
+obj-$(CONFIG_MPC) += ctcmpc.o fsm.o cu3088.o
 qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o 
 qeth-$(CONFIG_PROC_FS) += qeth_proc.o
 obj-$(CONFIG_QETH) += qeth.o
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index fe986af..20c8eb1 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -6,7 +6,7 @@
  * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
  *            Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 	      Peter Tiedemann (ptiedem@de.ibm.com)
- * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com>
+ * Driver Model stuff by : Cornelia Huck <cornelia.huck@de.ibm.com>
  *
  * Documentation used:
  *  - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -65,7 +65,6 @@
 
 #include <asm/idals.h>
 
-#include "ctctty.h"
 #include "fsm.h"
 #include "cu3088.h"
 
@@ -479,10 +478,7 @@
 		skb->dev = pskb->dev;
 		skb->protocol = pskb->protocol;
 		pskb->ip_summed = CHECKSUM_UNNECESSARY;
-		if (ch->protocol == CTC_PROTO_LINUX_TTY)
-			ctc_tty_netif_rx(skb);
-		else
-			netif_rx_ni(skb);
+		netif_rx_ni(skb);
 		/**
 		 * Successful rx; reset logflags
 		 */
@@ -557,8 +553,7 @@
 	DBF_TEXT(trace, 5, __FUNCTION__);
 	if (sense & SNS0_INTERVENTION_REQ) {
 		if (sense & 0x01) {
-			if (ch->protocol != CTC_PROTO_LINUX_TTY)
-				ctc_pr_debug("%s: Interface disc. or Sel. reset "
+			ctc_pr_debug("%s: Interface disc. or Sel. reset "
 					"(remote)\n", ch->id);
 			fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
 		} else {
@@ -2034,7 +2029,6 @@
 dev_action_chup(fsm_instance * fi, int event, void *arg)
 {
 	struct net_device *dev = (struct net_device *) arg;
-	struct ctc_priv *privptr = dev->priv;
 
 	DBF_TEXT(trace, 3, __FUNCTION__);
 	switch (fsm_getstate(fi)) {
@@ -2049,8 +2043,6 @@
 				fsm_newstate(fi, DEV_STATE_RUNNING);
 				ctc_pr_info("%s: connected with remote side\n",
 					    dev->name);
-				if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-					ctc_tty_setcarrier(dev, 1);
 				ctc_clear_busy(dev);
 			}
 			break;
@@ -2059,8 +2051,6 @@
 				fsm_newstate(fi, DEV_STATE_RUNNING);
 				ctc_pr_info("%s: connected with remote side\n",
 					    dev->name);
-				if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-					ctc_tty_setcarrier(dev, 1);
 				ctc_clear_busy(dev);
 			}
 			break;
@@ -2086,14 +2076,10 @@
 static void
 dev_action_chdown(fsm_instance * fi, int event, void *arg)
 {
-	struct net_device *dev = (struct net_device *) arg;
-	struct ctc_priv *privptr = dev->priv;
 
 	DBF_TEXT(trace, 3, __FUNCTION__);
 	switch (fsm_getstate(fi)) {
 		case DEV_STATE_RUNNING:
-			if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-				ctc_tty_setcarrier(dev, 0);
 			if (event == DEV_EVENT_TXDOWN)
 				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
 			else
@@ -2397,8 +2383,6 @@
 	 */
 	if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
 		fsm_event(privptr->fsm, DEV_EVENT_START, dev);
-		if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-			return -EBUSY;
 		dev_kfree_skb(skb);
 		privptr->stats.tx_dropped++;
 		privptr->stats.tx_errors++;
@@ -2608,20 +2592,13 @@
 	if (!dev)
 		return;
 	privptr = (struct ctc_priv *) dev->priv;
-	if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-		unregister_netdev(dev);
-	else
-		ctc_tty_unregister_netdev(dev);
+	unregister_netdev(dev);
 }
 
 static int
 ctc_netdev_register(struct net_device * dev)
 {
-	struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
-	if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-		return register_netdev(dev);
-	else
-		return ctc_tty_register_netdev(dev);
+	return register_netdev(dev);
 }
 
 static void
@@ -2667,7 +2644,9 @@
 	if (!priv)
 		return -ENODEV;
 	sscanf(buf, "%u", &value);
-	if ((value < 0) || (value > CTC_PROTO_MAX))
+	if (!((value == CTC_PROTO_S390)  ||
+	      (value == CTC_PROTO_LINUX) ||
+	      (value == CTC_PROTO_OS390)))
 		return -EINVAL;
 	priv->protocol = value;
 
@@ -2897,10 +2876,7 @@
 		goto out;
 	}
 
-	if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-		strlcpy(dev->name, "ctctty%d", IFNAMSIZ);
-	else
-		strlcpy(dev->name, "ctc%d", IFNAMSIZ);
+	strlcpy(dev->name, "ctc%d", IFNAMSIZ);
 
 	for (direction = READ; direction <= WRITE; direction++) {
 		privptr->channel[direction] =
@@ -3046,7 +3022,6 @@
 {
 	DBF_TEXT(setup, 3, __FUNCTION__);
 	unregister_cu3088_discipline(&ctc_group_driver);
-	ctc_tty_cleanup();
 	ctc_unregister_dbf_views();
 	ctc_pr_info("CTC driver unloaded\n");
 }
@@ -3073,10 +3048,8 @@
 		ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret);
 		return ret;
 	}
-	ctc_tty_init();
 	ret = register_cu3088_discipline(&ctc_group_driver);
 	if (ret) {
-		ctc_tty_cleanup();
 		ctc_unregister_dbf_views();
 	}
 	return ret;
diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
index d2e835c..7f305d1 100644
--- a/drivers/s390/net/ctcmain.h
+++ b/drivers/s390/net/ctcmain.h
@@ -35,7 +35,9 @@
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 
-#include "ctctty.h"
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
 #include "fsm.h"
 #include "cu3088.h"
 
@@ -50,9 +52,7 @@
 
 #define CTC_PROTO_S390          0
 #define CTC_PROTO_LINUX         1
-#define CTC_PROTO_LINUX_TTY     2
 #define CTC_PROTO_OS390         3
-#define CTC_PROTO_MAX           3
 
 #define CTC_BUFSIZE_LIMIT       65535
 #define CTC_BUFSIZE_DEFAULT     32768
@@ -257,15 +257,13 @@
 ctc_clear_busy(struct net_device * dev)
 {
 	clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
-	if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
-		netif_wake_queue(dev);
+	netif_wake_queue(dev);
 }
 
 static __inline__ int
 ctc_test_and_set_busy(struct net_device * dev)
 {
-	if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
-		netif_stop_queue(dev);
+	netif_stop_queue(dev);
 	return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
 }
 
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
deleted file mode 100644
index af54d1d..0000000
--- a/drivers/s390/net/ctctty.c
+++ /dev/null
@@ -1,1259 +0,0 @@
-/*
- * CTC / ESCON network driver, tty interface.
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include <linux/devfs_fs_kernel.h>
-#include "ctctty.h"
-#include "ctcdbug.h"
-
-#define CTC_TTY_MAJOR       43
-#define CTC_TTY_MAX_DEVICES 64
-
-#define CTC_ASYNC_MAGIC          0x49344C01 /* for paranoia-checking        */
-#define CTC_ASYNC_INITIALIZED    0x80000000 /* port was initialized         */
-#define CTC_ASYNC_NORMAL_ACTIVE  0x20000000 /* Normal device active         */
-#define CTC_ASYNC_CLOSING        0x08000000 /* Serial port is closing       */
-#define CTC_ASYNC_CTS_FLOW       0x04000000 /* Do CTS flow control          */
-#define CTC_ASYNC_CHECK_CD       0x02000000 /* i.e., CLOCAL                 */
-#define CTC_ASYNC_HUP_NOTIFY         0x0001 /* Notify tty on hangups/closes */
-#define CTC_ASYNC_NETDEV_OPEN        0x0002 /* Underlying netdev is open    */
-#define CTC_ASYNC_TX_LINESTAT        0x0004 /* Must send line status        */
-#define CTC_ASYNC_SPLIT_TERMIOS      0x0008 /* Sep. termios for dialin/out  */
-#define CTC_TTY_XMIT_SIZE              1024 /* Default bufsize for write    */
-#define CTC_SERIAL_XMIT_MAX            4000 /* Maximum bufsize for write    */
-
-/* Private data (similar to async_struct in <linux/serial.h>) */
-typedef struct {
-  int			magic;
-  int			flags;		 /* defined in tty.h               */
-  int			mcr;		 /* Modem control register         */
-  int                   msr;             /* Modem status register          */
-  int                   lsr;             /* Line status register           */
-  int			line;
-  int			count;		 /* # of fd on device              */
-  int			blocked_open;	 /* # of blocked opens             */
-  struct net_device     *netdev;
-  struct sk_buff_head   tx_queue;        /* transmit queue                 */
-  struct sk_buff_head   rx_queue;        /* receive queue                  */
-  struct tty_struct 	*tty;            /* Pointer to corresponding tty   */
-  wait_queue_head_t	open_wait;
-  wait_queue_head_t	close_wait;
-  struct semaphore      write_sem;
-  struct tasklet_struct tasklet;
-  struct timer_list     stoptimer;
-} ctc_tty_info;
-
-/* Description of one CTC-tty */
-typedef struct {
-  struct tty_driver  *ctc_tty_device;		   /* tty-device             */
-  ctc_tty_info       info[CTC_TTY_MAX_DEVICES];	   /* Private data           */
-} ctc_tty_driver;
-
-static ctc_tty_driver *driver;
-
-/* Leave this unchanged unless you know what you do! */
-#define MODEM_PARANOIA_CHECK
-#define MODEM_DO_RESTART
-
-#define CTC_TTY_NAME "ctctty"
-
-static __u32 ctc_tty_magic = CTC_ASYNC_MAGIC;
-static int ctc_tty_shuttingdown = 0;
-
-static spinlock_t ctc_tty_lock;
-
-/* ctc_tty_try_read() is called from within ctc_tty_rcv_skb()
- * to stuff incoming data directly into a tty's flip-buffer. If the
- * flip buffer is full, the packet gets queued up.
- *
- * Return:
- *  1 = Success
- *  0 = Failure, data has to be buffered and later processed by
- *      ctc_tty_readmodem().
- */
-static int
-ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
-{
-	int len;
-	struct tty_struct *tty;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if ((tty = info->tty)) {
-		if (info->mcr & UART_MCR_RTS) {
-			len = skb->len;
-			tty_insert_flip_string(tty, skb->data, len);
-			tty_flip_buffer_push(tty);
-			kfree_skb(skb);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/* ctc_tty_readmodem() is called periodically from within timer-interrupt.
- * It tries getting received data from the receive queue an stuff it into
- * the tty's flip-buffer.
- */
-static int
-ctc_tty_readmodem(ctc_tty_info *info)
-{
-	int ret = 1;
-	struct tty_struct *tty;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if ((tty = info->tty)) {
-		if (info->mcr & UART_MCR_RTS) {
-			struct sk_buff *skb;
-
-			if ((skb = skb_dequeue(&info->rx_queue))) {
-				int len = skb->len;
-				tty_insert_flip_string(tty, skb->data, len);
-				skb_pull(skb, len);
-				tty_flip_buffer_push(tty);
-				if (skb->len > 0)
-					skb_queue_head(&info->rx_queue, skb);
-				else {
-					kfree_skb(skb);
-					ret = !skb_queue_empty(&info->rx_queue);
-				}
-			}
-		}
-	}
-	return ret;
-}
-
-void
-ctc_tty_setcarrier(struct net_device *netdev, int on)
-{
-	int i;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if ((!driver) || ctc_tty_shuttingdown)
-		return;
-	for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-		if (driver->info[i].netdev == netdev) {
-			ctc_tty_info *info = &driver->info[i];
-			if (on)
-				info->msr |= UART_MSR_DCD;
-			else
-				info->msr &= ~UART_MSR_DCD;
-			if ((info->flags & CTC_ASYNC_CHECK_CD) && (!on))
-				tty_hangup(info->tty);
-		}
-}
-
-void
-ctc_tty_netif_rx(struct sk_buff *skb)
-{
-	int i;
-	ctc_tty_info *info = NULL;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if (!skb)
-		return;
-	if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) {
-		dev_kfree_skb(skb);
-		return;
-	}
-	for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-		if (driver->info[i].netdev == skb->dev) {
-			info = &driver->info[i];
-			break;
-		}
-	if (!info) {
-		dev_kfree_skb(skb);
-		return;
-	}
-	if (skb->len < 6) {
-		dev_kfree_skb(skb);
-		return;
-	}
-	if (memcmp(skb->data, &ctc_tty_magic, sizeof(__u32))) {
-		dev_kfree_skb(skb);
-		return;
-	}
-	skb_pull(skb, sizeof(__u32));
-
-	i = *((int *)skb->data);
-	skb_pull(skb, sizeof(info->mcr));
-	if (i & UART_MCR_RTS) {
-		info->msr |= UART_MSR_CTS;
-		if (info->flags & CTC_ASYNC_CTS_FLOW)
-			info->tty->hw_stopped = 0;
-	} else {
-		info->msr &= ~UART_MSR_CTS;
-		if (info->flags & CTC_ASYNC_CTS_FLOW)
-			info->tty->hw_stopped = 1;
-	}
-	if (i & UART_MCR_DTR)
-		info->msr |= UART_MSR_DSR;
-	else
-		info->msr &= ~UART_MSR_DSR;
-	if (skb->len <= 0) {
-		kfree_skb(skb);
-		return;
-	}
-	/* Try to deliver directly via tty-flip-buf if queue is empty */
-	if (skb_queue_empty(&info->rx_queue))
-		if (ctc_tty_try_read(info, skb))
-			return;
-	/* Direct deliver failed or queue wasn't empty.
-	 * Queue up for later dequeueing via timer-irq.
-	 */
-	skb_queue_tail(&info->rx_queue, skb);
-	/* Schedule dequeuing */
-	tasklet_schedule(&info->tasklet);
-}
-
-static int
-ctc_tty_tint(ctc_tty_info * info)
-{
-	struct sk_buff *skb = skb_dequeue(&info->tx_queue);
-	int stopped = (info->tty->hw_stopped || info->tty->stopped);
-	int wake = 1;
-	int rc;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (!info->netdev) {
-		if (skb)
-			kfree_skb(skb);
-		return 0;
-	}
-	if (info->flags & CTC_ASYNC_TX_LINESTAT) {
-		int skb_res = info->netdev->hard_header_len +
-			sizeof(info->mcr) + sizeof(__u32);
-		/* If we must update line status,
-		 * create an empty dummy skb and insert it.
-		 */
-		if (skb)
-			skb_queue_head(&info->tx_queue, skb);
-
-		skb = dev_alloc_skb(skb_res);
-		if (!skb) {
-			printk(KERN_WARNING
-			       "ctc_tty: Out of memory in %s%d tint\n",
-			       CTC_TTY_NAME, info->line);
-			return 1;
-		}
-		skb_reserve(skb, skb_res);
-		stopped = 0;
-		wake = 0;
-	}
-	if (!skb)
-		return 0;
-	if (stopped) {
-		skb_queue_head(&info->tx_queue, skb);
-		return 1;
-	}
-#if 0
-	if (skb->len > 0)
-		printk(KERN_DEBUG "tint: %d %02x\n", skb->len, *(skb->data));
-	else
-		printk(KERN_DEBUG "tint: %d STAT\n", skb->len);
-#endif
-	memcpy(skb_push(skb, sizeof(info->mcr)), &info->mcr, sizeof(info->mcr));
-	memcpy(skb_push(skb, sizeof(__u32)), &ctc_tty_magic, sizeof(__u32));
-	rc = info->netdev->hard_start_xmit(skb, info->netdev);
-	if (rc) {
-		skb_pull(skb, sizeof(info->mcr) + sizeof(__u32));
-		if (skb->len > 0)
-			skb_queue_head(&info->tx_queue, skb);
-		else
-			kfree_skb(skb);
-	} else {
-		struct tty_struct *tty = info->tty;
-
-		info->flags &= ~CTC_ASYNC_TX_LINESTAT;
-		if (tty) {
-			tty_wakeup(tty);
-		}
-	}
-	return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
-}
-
-/************************************************************
- *
- * Modem-functions
- *
- * mostly "stolen" from original Linux-serial.c and friends.
- *
- ************************************************************/
-
-static inline int
-ctc_tty_paranoia_check(ctc_tty_info * info, char *name, const char *routine)
-{
-#ifdef MODEM_PARANOIA_CHECK
-	if (!info) {
-		printk(KERN_WARNING "ctc_tty: null info_struct for %s in %s\n",
-		       name, routine);
-		return 1;
-	}
-	if (info->magic != CTC_ASYNC_MAGIC) {
-		printk(KERN_WARNING "ctc_tty: bad magic for info struct %s in %s\n",
-		       name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-static void
-ctc_tty_inject(ctc_tty_info *info, char c)
-{
-	int skb_res;
-	struct sk_buff *skb;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ctc_tty_shuttingdown)
-		return;
-	skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
-		sizeof(__u32) + 1;
-	skb = dev_alloc_skb(skb_res);
-	if (!skb) {
-		printk(KERN_WARNING
-		       "ctc_tty: Out of memory in %s%d tx_inject\n",
-		       CTC_TTY_NAME, info->line);
-		return;
-	}
-	skb_reserve(skb, skb_res);
-	*(skb_put(skb, 1)) = c;
-	skb_queue_head(&info->tx_queue, skb);
-	tasklet_schedule(&info->tasklet);
-}
-
-static void
-ctc_tty_transmit_status(ctc_tty_info *info)
-{
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if (ctc_tty_shuttingdown)
-		return;
-	info->flags |= CTC_ASYNC_TX_LINESTAT;
-	tasklet_schedule(&info->tasklet);
-}
-
-static void
-ctc_tty_change_speed(ctc_tty_info * info)
-{
-	unsigned int cflag;
-	unsigned int quot;
-	int i;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	if (!info->tty || !info->tty->termios)
-		return;
-	cflag = info->tty->termios->c_cflag;
-
-	quot = i = cflag & CBAUD;
-	if (i & CBAUDEX) {
-		i &= ~CBAUDEX;
-		if (i < 1 || i > 2)
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			i += 15;
-	}
-	if (quot) {
-		info->mcr |= UART_MCR_DTR;
-		info->mcr |= UART_MCR_RTS;
-		ctc_tty_transmit_status(info);
-	} else {
-		info->mcr &= ~UART_MCR_DTR;
-		info->mcr &= ~UART_MCR_RTS;
-		ctc_tty_transmit_status(info);
-		return;
-	}
-
-	/* CTS flow control flag and modem status interrupts */
-	if (cflag & CRTSCTS) {
-		info->flags |= CTC_ASYNC_CTS_FLOW;
-	} else
-		info->flags &= ~CTC_ASYNC_CTS_FLOW;
-	if (cflag & CLOCAL)
-		info->flags &= ~CTC_ASYNC_CHECK_CD;
-	else {
-		info->flags |= CTC_ASYNC_CHECK_CD;
-	}
-}
-
-static int
-ctc_tty_startup(ctc_tty_info * info)
-{
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	if (info->flags & CTC_ASYNC_INITIALIZED)
-		return 0;
-#ifdef CTC_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line);
-#endif
-	/*
-	 * Now, initialize the UART
-	 */
-	info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
-	if (info->tty)
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	/*
-	 * and set the speed of the serial port
-	 */
-	ctc_tty_change_speed(info);
-
-	info->flags |= CTC_ASYNC_INITIALIZED;
-	if (!(info->flags & CTC_ASYNC_NETDEV_OPEN))
-		info->netdev->open(info->netdev);
-	info->flags |= CTC_ASYNC_NETDEV_OPEN;
-	return 0;
-}
-
-static void
-ctc_tty_stopdev(unsigned long data)
-{
-	ctc_tty_info *info = (ctc_tty_info *)data;
-
-	if ((!info) || (!info->netdev) ||
-	    (info->flags & CTC_ASYNC_INITIALIZED))
-		return;
-	info->netdev->stop(info->netdev);
-	info->flags &= ~CTC_ASYNC_NETDEV_OPEN;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void
-ctc_tty_shutdown(ctc_tty_info * info)
-{
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	if (!(info->flags & CTC_ASYNC_INITIALIZED))
-		return;
-#ifdef CTC_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line);
-#endif
-	info->msr &= ~UART_MSR_RI;
-	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-		info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-	mod_timer(&info->stoptimer, jiffies + (10 * HZ));
-	skb_queue_purge(&info->tx_queue);
-	skb_queue_purge(&info->rx_queue);
-	info->flags &= ~CTC_ASYNC_INITIALIZED;
-}
-
-/* ctc_tty_write() is the main send-routine. It is called from the upper
- * levels within the kernel to perform sending data. Depending on the
- * online-flag it either directs output to the at-command-interpreter or
- * to the lower level. Additional tasks done here:
- *  - If online, check for escape-sequence (+++)
- *  - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes.
- *  - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed.
- *  - If dialing, abort dial.
- */
-static int
-ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
-{
-	int c;
-	int total = 0;
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-	DBF_TEXT(trace, 5, __FUNCTION__);
-	if (ctc_tty_shuttingdown)
-		goto ex;
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write"))
-		goto ex;
-	if (!tty)
-		goto ex;
-	if (!info->netdev) {
-		total = -ENODEV;
-		goto ex;
-	}
-	while (1) {
-		struct sk_buff *skb;
-		int skb_res;
-
-		c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE;
-		if (c <= 0)
-			break;
-
-		skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
-			+ sizeof(__u32);
-		skb = dev_alloc_skb(skb_res + c);
-		if (!skb) {
-			printk(KERN_WARNING
-			       "ctc_tty: Out of memory in %s%d write\n",
-			       CTC_TTY_NAME, info->line);
-			break;
-		}
-		skb_reserve(skb, skb_res);
-		memcpy(skb_put(skb, c), buf, c);
-		skb_queue_tail(&info->tx_queue, skb);
-		buf += c;
-		total += c;
-		count -= c;
-	}
-	if (!skb_queue_empty(&info->tx_queue)) {
-		info->lsr &= ~UART_LSR_TEMT;
-		tasklet_schedule(&info->tasklet);
-	}
-ex:
-	DBF_TEXT(trace, 6, __FUNCTION__);
-	return total;
-}
-
-static int
-ctc_tty_write_room(struct tty_struct *tty)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write_room"))
-		return 0;
-	return CTC_TTY_XMIT_SIZE;
-}
-
-static int
-ctc_tty_chars_in_buffer(struct tty_struct *tty)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_chars_in_buffer"))
-		return 0;
-	return 0;
-}
-
-static void
-ctc_tty_flush_buffer(struct tty_struct *tty)
-{
-	ctc_tty_info *info;
-	unsigned long flags;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (!tty)
-		goto ex;
-	spin_lock_irqsave(&ctc_tty_lock, flags);
-	info = (ctc_tty_info *) tty->driver_data;
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) {
-		spin_unlock_irqrestore(&ctc_tty_lock, flags);
-		goto ex;
-	}
-	skb_queue_purge(&info->tx_queue);
-	info->lsr |= UART_LSR_TEMT;
-	spin_unlock_irqrestore(&ctc_tty_lock, flags);
-	wake_up_interruptible(&tty->write_wait);
-	tty_wakeup(tty);
-ex:
-	DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
-	return;
-}
-
-static void
-ctc_tty_flush_chars(struct tty_struct *tty)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ctc_tty_shuttingdown)
-		return;
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
-		return;
-	if (tty->stopped || tty->hw_stopped || skb_queue_empty(&info->tx_queue))
-		return;
-	tasklet_schedule(&info->tasklet);
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void
-ctc_tty_throttle(struct tty_struct *tty)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle"))
-		return;
-	info->mcr &= ~UART_MCR_RTS;
-	if (I_IXOFF(tty))
-		ctc_tty_inject(info, STOP_CHAR(tty));
-	ctc_tty_transmit_status(info);
-}
-
-static void
-ctc_tty_unthrottle(struct tty_struct *tty)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle"))
-		return;
-	info->mcr |= UART_MCR_RTS;
-	if (I_IXOFF(tty))
-		ctc_tty_inject(info, START_CHAR(tty));
-	ctc_tty_transmit_status(info);
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-/*
- * ctc_tty_get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *          is emptied.  On bus types like RS485, the transmitter must
- *          release the bus after transmitting. This must be done when
- *          the transmit shift register is empty, not be done when the
- *          transmit holding register is empty.  This functionality
- *          allows RS485 driver to be written in user space.
- */
-static int
-ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value)
-{
-	u_char status;
-	uint result;
-	ulong flags;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	spin_lock_irqsave(&ctc_tty_lock, flags);
-	status = info->lsr;
-	spin_unlock_irqrestore(&ctc_tty_lock, flags);
-	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	put_user(result, value);
-	return 0;
-}
-
-
-static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-	u_char control,
-	 status;
-	uint result;
-	ulong flags;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	control = info->mcr;
-	spin_lock_irqsave(&ctc_tty_lock, flags);
-	status = info->msr;
-	spin_unlock_irqrestore(&ctc_tty_lock, flags);
-	result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
-	    | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-	    | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
-	    | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
-	    | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
-	    | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-	return result;
-}
-
-static int
-ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
-		 unsigned int set, unsigned int clear)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if (set & TIOCM_RTS)
-		info->mcr |= UART_MCR_RTS;
-	if (set & TIOCM_DTR)
-		info->mcr |= UART_MCR_DTR;
-
-	if (clear & TIOCM_RTS)
-		info->mcr &= ~UART_MCR_RTS;
-	if (clear & TIOCM_DTR)
-		info->mcr &= ~UART_MCR_DTR;
-
-	if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
-		ctc_tty_transmit_status(info);
-	return 0;
-}
-
-static int
-ctc_tty_ioctl(struct tty_struct *tty, struct file *file,
-	       uint cmd, ulong arg)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-	int error;
-	int retval;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-	switch (cmd) {
-		case TCSBRK:   /* SVID version: non-zero arg --> no break */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line);
-#endif
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			return 0;
-		case TCSBRKP:  /* support for POSIX tcsendbreak() */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line);
-#endif
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			return 0;
-		case TIOCGSOFTCAR:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME,
-			       info->line);
-#endif
-			error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
-			return error;
-		case TIOCSSOFTCAR:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME,
-			       info->line);
-#endif
-			error = get_user(arg, (ulong __user *) arg);
-			if (error)
-				return error;
-			tty->termios->c_cflag =
-			    ((tty->termios->c_cflag & ~CLOCAL) |
-			     (arg ? CLOCAL : 0));
-			return 0;
-		case TIOCSERGETLSR:	/* Get line status register */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
-			       info->line);
-#endif
-			if (access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(uint)))
-				return ctc_tty_get_lsr_info(info, (uint __user *) arg);
-			else
-				return -EFAULT;
-		default:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-			printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd,
-			       CTC_TTY_NAME, info->line);
-#endif
-			return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static void
-ctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-	unsigned int cflag = tty->termios->c_cflag;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	ctc_tty_change_speed(info);
-
-	/* Handle transition to B0 */
-	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {
-		info->mcr &= ~(UART_MCR_DTR|UART_MCR_RTS);
-		ctc_tty_transmit_status(info);
-	}
-
-	/* Handle transition from B0 to other */
-	if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-		info->mcr |= UART_MCR_DTR;
-		if (!(tty->termios->c_cflag & CRTSCTS) ||
-                    !test_bit(TTY_THROTTLED, &tty->flags)) {
-                        info->mcr |= UART_MCR_RTS;
-                }
-		ctc_tty_transmit_status(info);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) &&
-            !(tty->termios->c_cflag & CRTSCTS))
-                tty->hw_stopped = 0;
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_open() and friends
- * ------------------------------------------------------------
- */
-static int
-ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info *info)
-{
-	DECLARE_WAITQUEUE(wait, NULL);
-	int do_clocal = 0;
-	unsigned long flags;
-	int retval;
-
-	DBF_TEXT(trace, 4, __FUNCTION__);
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->flags & CTC_ASYNC_CLOSING)) {
-		if (info->flags & CTC_ASYNC_CLOSING)
-			wait_event(info->close_wait,
-				   !(info->flags & CTC_ASYNC_CLOSING));
-#ifdef MODEM_DO_RESTART
-		if (info->flags & CTC_ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-#else
-		return -EAGAIN;
-#endif
-	}
-	/*
-	 * If non-blocking mode is set, then make the check up front
-	 * and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = 1;
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, info->count is dropped by one, so that
-	 * ctc_tty_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&info->open_wait, &wait);
-#ifdef CTC_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "ctc_tty_block_til_ready before block: %s%d, count = %d\n",
-	       CTC_TTY_NAME, info->line, info->count);
-#endif
-	spin_lock_irqsave(&ctc_tty_lock, flags);
-	if (!(tty_hung_up_p(filp)))
-		info->count--;
-	spin_unlock_irqrestore(&ctc_tty_lock, flags);
-	info->blocked_open++;
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(info->flags & CTC_ASYNC_INITIALIZED)) {
-#ifdef MODEM_DO_RESTART
-			if (info->flags & CTC_ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-		if (!(info->flags & CTC_ASYNC_CLOSING) &&
-		    (do_clocal || (info->msr & UART_MSR_DCD))) {
-			break;
-		}
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef CTC_DEBUG_MODEM_OPEN
-		printk(KERN_DEBUG "ctc_tty_block_til_ready blocking: %s%d, count = %d\n",
-		       CTC_TTY_NAME, info->line, info->count);
-#endif
-		schedule();
-	}
-	current->state = TASK_RUNNING;
-	remove_wait_queue(&info->open_wait, &wait);
-	if (!tty_hung_up_p(filp))
-		info->count++;
-	info->blocked_open--;
-#ifdef CTC_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "ctc_tty_block_til_ready after blocking: %s%d, count = %d\n",
-	       CTC_TTY_NAME, info->line, info->count);
-#endif
-	if (retval)
-		return retval;
-	info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
-	return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int
-ctc_tty_open(struct tty_struct *tty, struct file *filp)
-{
-	ctc_tty_info *info;
-	unsigned long saveflags;
-	int retval,
-	 line;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	line = tty->index;
-	if (line < 0 || line > CTC_TTY_MAX_DEVICES)
-		return -ENODEV;
-	info = &driver->info[line];
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_open"))
-		return -ENODEV;
-	if (!info->netdev)
-		return -ENODEV;
-#ifdef CTC_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "ctc_tty_open %s, count = %d\n", tty->name,
-	       info->count);
-#endif
-	spin_lock_irqsave(&ctc_tty_lock, saveflags);
-	info->count++;
-	tty->driver_data = info;
-	info->tty = tty;
-	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-	/*
-	 * Start up serial port
-	 */
-	retval = ctc_tty_startup(info);
-	if (retval) {
-#ifdef CTC_DEBUG_MODEM_OPEN
-		printk(KERN_DEBUG "ctc_tty_open return after startup\n");
-#endif
-		return retval;
-	}
-	retval = ctc_tty_block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef CTC_DEBUG_MODEM_OPEN
-		printk(KERN_DEBUG "ctc_tty_open return after ctc_tty_block_til_ready \n");
-#endif
-		return retval;
-	}
-#ifdef CTC_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "ctc_tty_open %s successful...\n", tty->name);
-#endif
-	return 0;
-}
-
-static void
-ctc_tty_close(struct tty_struct *tty, struct file *filp)
-{
-	ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-	ulong flags;
-	ulong timeout;
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	if (!info || ctc_tty_paranoia_check(info, tty->name, "ctc_tty_close"))
-		return;
-	spin_lock_irqsave(&ctc_tty_lock, flags);
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&ctc_tty_lock, flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-		printk(KERN_DEBUG "ctc_tty_close return after tty_hung_up_p\n");
-#endif
-		return;
-	}
-	if ((tty->count == 1) && (info->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Info->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk(KERN_ERR "ctc_tty_close: bad port count; tty->count is 1, "
-		       "info->count is %d\n", info->count);
-		info->count = 1;
-	}
-	if (--info->count < 0) {
-		printk(KERN_ERR "ctc_tty_close: bad port count for %s%d: %d\n",
-		       CTC_TTY_NAME, info->line, info->count);
-		info->count = 0;
-	}
-	if (info->count) {
-		local_irq_restore(flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-		printk(KERN_DEBUG "ctc_tty_close after info->count != 0\n");
-#endif
-		return;
-	}
-	info->flags |= CTC_ASYNC_CLOSING;
-	tty->closing = 1;
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	if (info->flags & CTC_ASYNC_INITIALIZED) {
-		tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		timeout = jiffies + HZ;
-		while (!(info->lsr & UART_LSR_TEMT)) {
-			spin_unlock_irqrestore(&ctc_tty_lock, flags);
-			msleep(500);
-			spin_lock_irqsave(&ctc_tty_lock, flags);
-			if (time_after(jiffies,timeout))
-				break;
-		}
-	}
-	ctc_tty_shutdown(info);
-	if (tty->driver->flush_buffer) {
-		skb_queue_purge(&info->tx_queue);
-		info->lsr |= UART_LSR_TEMT;
-	}
-	tty_ldisc_flush(tty);
-	info->tty = 0;
-	tty->closing = 0;
-	if (info->blocked_open) {
-		msleep_interruptible(500);
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-	spin_unlock_irqrestore(&ctc_tty_lock, flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-	printk(KERN_DEBUG "ctc_tty_close normal exit\n");
-#endif
-}
-
-/*
- * ctc_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void
-ctc_tty_hangup(struct tty_struct *tty)
-{
-	ctc_tty_info *info = (ctc_tty_info *)tty->driver_data;
-	unsigned long saveflags;
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_hangup"))
-		return;
-	ctc_tty_shutdown(info);
-	info->count = 0;
-	info->flags &= ~CTC_ASYNC_NORMAL_ACTIVE;
-	spin_lock_irqsave(&ctc_tty_lock, saveflags);
-	info->tty = 0;
-	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-	wake_up_interruptible(&info->open_wait);
-}
-
-
-/*
- * For all online tty's, try sending data to
- * the lower levels.
- */
-static void
-ctc_tty_task(unsigned long arg)
-{
-	ctc_tty_info *info = (void *)arg;
-	unsigned long saveflags;
-	int again;
-
-	DBF_TEXT(trace, 3, __FUNCTION__);
-	spin_lock_irqsave(&ctc_tty_lock, saveflags);
-	if ((!ctc_tty_shuttingdown) && info) {
-		again = ctc_tty_tint(info);
-		if (!again)
-			info->lsr |= UART_LSR_TEMT;
-		again |= ctc_tty_readmodem(info);
-		if (again) {
-			tasklet_schedule(&info->tasklet);
-		}
-	}
-	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-}
-
-static struct tty_operations ctc_ops = {
-	.open = ctc_tty_open,
-	.close = ctc_tty_close,
-	.write = ctc_tty_write,
-	.flush_chars = ctc_tty_flush_chars,
-	.write_room = ctc_tty_write_room,
-	.chars_in_buffer = ctc_tty_chars_in_buffer,
-	.flush_buffer = ctc_tty_flush_buffer,
-	.ioctl = ctc_tty_ioctl,
-	.throttle = ctc_tty_throttle,
-	.unthrottle = ctc_tty_unthrottle,
-	.set_termios = ctc_tty_set_termios,
-	.hangup = ctc_tty_hangup,
-	.tiocmget = ctc_tty_tiocmget,
-	.tiocmset = ctc_tty_tiocmset,
-};
-
-int
-ctc_tty_init(void)
-{
-	int i;
-	ctc_tty_info *info;
-	struct tty_driver *device;
-
-	DBF_TEXT(trace, 2, __FUNCTION__);
-	driver = kmalloc(sizeof(ctc_tty_driver), GFP_KERNEL);
-	if (driver == NULL) {
-		printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
-		return -ENOMEM;
-	}
-	memset(driver, 0, sizeof(ctc_tty_driver));
-	device = alloc_tty_driver(CTC_TTY_MAX_DEVICES);
-	if (!device) {
-		kfree(driver);
-		printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
-		return -ENOMEM;
-	}
-
-	device->devfs_name = "ctc/" CTC_TTY_NAME;
-	device->name = CTC_TTY_NAME;
-	device->major = CTC_TTY_MAJOR;
-	device->minor_start = 0;
-	device->type = TTY_DRIVER_TYPE_SERIAL;
-	device->subtype = SERIAL_TYPE_NORMAL;
-	device->init_termios = tty_std_termios;
-	device->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	device->flags = TTY_DRIVER_REAL_RAW;
-	device->driver_name = "ctc_tty",
-	tty_set_operations(device, &ctc_ops);
-	if (tty_register_driver(device)) {
-		printk(KERN_WARNING "ctc_tty: Couldn't register serial-device\n");
-		put_tty_driver(device);
-		kfree(driver);
-		return -1;
-	}
-	driver->ctc_tty_device = device;
-	for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) {
-		info = &driver->info[i];
-		init_MUTEX(&info->write_sem);
-		tasklet_init(&info->tasklet, ctc_tty_task,
-				(unsigned long) info);
-		info->magic = CTC_ASYNC_MAGIC;
-		info->line = i;
-		info->tty = 0;
-		info->count = 0;
-		info->blocked_open = 0;
-		init_waitqueue_head(&info->open_wait);
-		init_waitqueue_head(&info->close_wait);
-		skb_queue_head_init(&info->tx_queue);
-		skb_queue_head_init(&info->rx_queue);
-		init_timer(&info->stoptimer);
-		info->stoptimer.function = ctc_tty_stopdev;
-		info->stoptimer.data = (unsigned long)info;
-		info->mcr = UART_MCR_RTS;
-	}
-	return 0;
-}
-
-int
-ctc_tty_register_netdev(struct net_device *dev) {
-	int ttynum;
-	char *err;
-	char *p;
-
-	DBF_TEXT(trace, 2, __FUNCTION__);
-	if ((!dev) || (!dev->name)) {
-		printk(KERN_WARNING
-		       "ctc_tty_register_netdev called "
-		       "with NULL dev or NULL dev-name\n");
-		return -1;
-	}
-
-	/*
-	 *	If the name is a format string the caller wants us to
-	 *	do a name allocation : format string must end with %d
-	 */
-	if (strchr(dev->name, '%'))
-	{
-		int err = dev_alloc_name(dev, dev->name);	// dev->name is changed by this
-		if (err < 0) {
-			printk(KERN_DEBUG "dev_alloc returned error %d\n", err);
-			return err;
-		}
-
-	}
-
-	for (p = dev->name; p && ((*p < '0') || (*p > '9')); p++);
-	ttynum = simple_strtoul(p, &err, 0);
-	if ((ttynum < 0) || (ttynum >= CTC_TTY_MAX_DEVICES) ||
-	    (err && *err)) {
-		printk(KERN_WARNING
-		       "ctc_tty_register_netdev called "
-		       "with number in name '%s'\n", dev->name);
-		return -1;
-	}
-	if (driver->info[ttynum].netdev) {
-		printk(KERN_WARNING
-		       "ctc_tty_register_netdev called "
-		       "for already registered device '%s'\n",
-		       dev->name);
-		return -1;
-	}
-	driver->info[ttynum].netdev = dev;
-	return 0;
-}
-
-void
-ctc_tty_unregister_netdev(struct net_device *dev) {
-	int i;
-	unsigned long saveflags;
-	ctc_tty_info *info = NULL;
-
-	DBF_TEXT(trace, 2, __FUNCTION__);
-	spin_lock_irqsave(&ctc_tty_lock, saveflags);
-	for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-		if (driver->info[i].netdev == dev) {
-			info = &driver->info[i];
-			break;
-		}
-	if (info) {
-		info->netdev = NULL;
-		skb_queue_purge(&info->tx_queue);
-		skb_queue_purge(&info->rx_queue);
-	}
-	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-}
-
-void
-ctc_tty_cleanup(void) {
-	unsigned long saveflags;
-
-	DBF_TEXT(trace, 2, __FUNCTION__);
-	spin_lock_irqsave(&ctc_tty_lock, saveflags);
-	ctc_tty_shuttingdown = 1;
-	spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-	tty_unregister_driver(driver->ctc_tty_device);
-	put_tty_driver(driver->ctc_tty_device);
-	kfree(driver);
-	driver = NULL;
-}
diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h
deleted file mode 100644
index 7254dc0..0000000
--- a/drivers/s390/net/ctctty.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * CTC / ESCON network driver, tty interface.
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _CTCTTY_H_
-#define _CTCTTY_H_
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-extern int  ctc_tty_register_netdev(struct net_device *);
-extern void ctc_tty_unregister_netdev(struct net_device *);
-extern void ctc_tty_netif_rx(struct sk_buff *);
-extern int  ctc_tty_init(void);
-extern void ctc_tty_cleanup(void);
-extern void ctc_tty_setcarrier(struct net_device *, int);
-
-#endif
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index f94419b..2eded55 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -1140,10 +1140,9 @@
 		}
 	}
 	/* re-insert all entries from the failed_list into ipm_list */
-	list_for_each_entry_safe(ipm, tmp, &failed_list, list) {
-		list_del_init(&ipm->list);
-		list_add_tail(&ipm->list, &card->ipm_list);
-	}
+	list_for_each_entry_safe(ipm, tmp, &failed_list, list)
+		list_move_tail(&ipm->list, &card->ipm_list);
+
 	spin_unlock_irqrestore(&card->ipm_lock, flags);
 }
 
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 0bab60a2..38aad83 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -420,7 +420,7 @@
        }
 	tcph = eddp->skb->h.th;
 	while (eddp->skb_offset < eddp->skb->len) {
-		data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
+		data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
 			       (int)(eddp->skb->len - eddp->skb_offset));
 		/* prepare qdio hdr */
 		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
@@ -515,20 +515,20 @@
 
 	QETH_DBF_TEXT(trace, 5, "eddpcanp");
 	/* can we put multiple skbs in one page? */
-	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
+	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
 	if (skbs_per_page > 1){
-		ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) /
+		ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
 				 skbs_per_page + 1;
 		ctx->elements_per_skb = 1;
 	} else {
 		/* no -> how many elements per skb? */
-		ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len +
+		ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
 				     PAGE_SIZE) >> PAGE_SHIFT;
 		ctx->num_pages = ctx->elements_per_skb *
-				 (skb_shinfo(skb)->tso_segs + 1);
+				 (skb_shinfo(skb)->gso_segs + 1);
 	}
 	ctx->num_elements = ctx->elements_per_skb *
-			    (skb_shinfo(skb)->tso_segs + 1);
+			    (skb_shinfo(skb)->gso_segs + 1);
 }
 
 static inline struct qeth_eddp_context *
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 9e671a4..56009d7 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -4417,7 +4417,7 @@
 	struct qeth_eddp_context *ctx = NULL;
 	int tx_bytes = skb->len;
 	unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
-	unsigned short tso_size = skb_shinfo(skb)->tso_size;
+	unsigned short tso_size = skb_shinfo(skb)->gso_size;
 	int rc;
 
 	QETH_DBF_TEXT(trace, 6, "sendpkt");
@@ -4453,7 +4453,7 @@
 	queue = card->qdio.out_qs
 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
 
-	if (skb_shinfo(skb)->tso_size)
+	if (skb_shinfo(skb)->gso_size)
 		large_send = card->options.large_send;
 
 	/*are we able to do TSO ? If so ,prepare and send it from here */
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 24ef40c..593f298 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -51,7 +51,7 @@
 	hdr->ext.hdr_version = 1;
 	hdr->ext.hdr_len     = 28;
 	/*insert non-fix values */
-	hdr->ext.mss = skb_shinfo(skb)->tso_size;
+	hdr->ext.mss = skb_shinfo(skb)->gso_size;
 	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
 	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
 				       sizeof(struct qeth_hdr_tso));
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 395cfc6..9cd789b 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -1,18 +1,8 @@
 /*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * linux/drivers/s390/scsi/zfcp_aux.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- *            Raimund Schroeder <raimund.schroeder@de.ibm.com>
- *            Aron Zeh
- *            Wolfgang Taphorn
- *            Stefan Bader <stefan.bader@de.ibm.com>
- *            Heiko Carstens <heiko.carstens@de.ibm.com>
- *            Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,6 +19,20 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/*
+ * Driver authors:
+ *            Martin Peschke (originator of the driver)
+ *            Raimund Schroeder
+ *            Aron Zeh
+ *            Wolfgang Taphorn
+ *            Stefan Bader
+ *            Heiko Carstens (kernel 2.6 port of the driver)
+ *            Andreas Herrmann
+ *            Maxim Shchetynin
+ *            Volker Sameske
+ *            Ralph Wuerthner
+ */
+
 #include "zfcp_ext.h"
 
 /* accumulated log level (module parameter) */
@@ -75,15 +79,9 @@
 /* declare driver module init/cleanup functions */
 module_init(zfcp_module_init);
 
-MODULE_AUTHOR("Heiko Carstens <heiko.carstens@de.ibm.com>, "
-	      "Andreas Herrman <aherrman@de.ibm.com>, "
-	      "Martin Peschke <mpeschke@de.ibm.com>, "
-	      "Raimund Schroeder <raimund.schroeder@de.ibm.com>, "
-	      "Wolfgang Taphorn <taphorn@de.ibm.com>, "
-	      "Aron Zeh <arzeh@de.ibm.com>, "
-	      "IBM Deutschland Entwicklung GmbH");
+MODULE_AUTHOR("IBM Deutschland Entwicklung GmbH - linux390@de.ibm.com");
 MODULE_DESCRIPTION
-    ("FCP (SCSI over Fibre Channel) HBA driver for IBM eServer zSeries");
+    ("FCP (SCSI over Fibre Channel) HBA driver for IBM System z9 and zSeries");
 MODULE_LICENSE("GPL");
 
 module_param(device, charp, 0400);
@@ -291,12 +289,11 @@
 		goto out;
 	}
 
-	sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
+	sg_list = kzalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
 	if (sg_list == NULL) {
 		retval = -ENOMEM;
 		goto out;
 	}
-	memset(sg_list, 0, sizeof(*sg_list));
 
 	if (command != ZFCP_CFDC_IOC) {
 		ZFCP_LOG_INFO("IOC request code 0x%x invalid\n", command);
@@ -478,14 +475,13 @@
 	sg_list->count = size >> PAGE_SHIFT;
 	if (size & ~PAGE_MASK)
 		sg_list->count++;
-	sg_list->sg = kmalloc(sg_list->count * sizeof(struct scatterlist),
+	sg_list->sg = kcalloc(sg_list->count, sizeof(struct scatterlist),
 			      GFP_KERNEL);
 	if (sg_list->sg == NULL) {
 		sg_list->count = 0;
 		retval = -ENOMEM;
 		goto out;
 	}
-	memset(sg_list->sg, 0, sg_list->count * sizeof(struct scatterlist));
 
 	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
 		sg->length = min(size, PAGE_SIZE);
@@ -744,7 +740,7 @@
 zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
 {
 	struct zfcp_unit *unit, *tmp_unit;
-	scsi_lun_t scsi_lun;
+	unsigned int scsi_lun;
 	int found;
 
 	/*
@@ -758,10 +754,9 @@
 	if (unit)
 		return NULL;
 
-	unit = kmalloc(sizeof (struct zfcp_unit), GFP_KERNEL);
+	unit = kzalloc(sizeof (struct zfcp_unit), GFP_KERNEL);
 	if (!unit)
 		return NULL;
-	memset(unit, 0, sizeof (struct zfcp_unit));
 
 	/* initialise reference count stuff */
 	atomic_set(&unit->refcount, 0);
@@ -929,13 +924,12 @@
 	 */
 
 	/* try to allocate new adapter data structure (zeroed) */
-	adapter = kmalloc(sizeof (struct zfcp_adapter), GFP_KERNEL);
+	adapter = kzalloc(sizeof (struct zfcp_adapter), GFP_KERNEL);
 	if (!adapter) {
 		ZFCP_LOG_INFO("error: allocation of base adapter "
 			      "structure failed\n");
 		goto out;
 	}
-	memset(adapter, 0, sizeof (struct zfcp_adapter));
 
 	ccw_device->handler = NULL;
 
@@ -997,12 +991,6 @@
 	/* intitialise SCSI ER timer */
 	init_timer(&adapter->scsi_er_timer);
 
-	/* set FC service class used per default */
-	adapter->fc_service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT;
-
-	sprintf(adapter->name, "%s", zfcp_get_busid_by_adapter(adapter));
-	ASCEBC(adapter->name, strlen(adapter->name));
-
 	/* mark adapter unusable as long as sysfs registration is not complete */
 	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
 
@@ -1139,10 +1127,9 @@
 			return NULL;
 	}
 
-	port = kmalloc(sizeof (struct zfcp_port), GFP_KERNEL);
+	port = kzalloc(sizeof (struct zfcp_port), GFP_KERNEL);
 	if (!port)
 		return NULL;
-	memset(port, 0, sizeof (struct zfcp_port));
 
 	/* initialise reference count stuff */
 	atomic_set(&port->refcount, 0);
@@ -1354,18 +1341,19 @@
 zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
 			    struct fsf_status_read_buffer *status_buffer)
 {
-	logi *els_logi = (logi *) status_buffer->payload;
+	struct fsf_plogi *els_plogi;
 	struct zfcp_port *port;
 	unsigned long flags;
 
+	els_plogi = (struct fsf_plogi *) status_buffer->payload;
 	read_lock_irqsave(&zfcp_data.config_lock, flags);
 	list_for_each_entry(port, &adapter->port_list_head, list) {
-		if (port->wwpn == (*(wwn_t *) & els_logi->nport_wwn))
+		if (port->wwpn == (*(wwn_t *) &els_plogi->serv_param.wwpn))
 			break;
 	}
 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 
-	if (!port || (port->wwpn != (*(wwn_t *) & els_logi->nport_wwn))) {
+	if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) {
 		ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port "
 			       "with d_id 0x%08x on adapter %s\n",
 			       status_buffer->d_id,
@@ -1760,4 +1748,25 @@
 	return ret;
 }
 
+/**
+ * zfcp_plogi_evaluate - evaluate PLOGI playload and copy important fields
+ * into zfcp_port structure
+ * @port: zfcp_port structure
+ * @plogi: plogi payload
+ */
+void
+zfcp_plogi_evaluate(struct zfcp_port *port, struct fsf_plogi *plogi)
+{
+	port->maxframe_size = plogi->serv_param.common_serv_param[7] |
+		((plogi->serv_param.common_serv_param[6] & 0x0F) << 8);
+	if (plogi->serv_param.class1_serv_param[0] & 0x80)
+		port->supported_classes |= FC_COS_CLASS1;
+	if (plogi->serv_param.class2_serv_param[0] & 0x80)
+		port->supported_classes |= FC_COS_CLASS2;
+	if (plogi->serv_param.class3_serv_param[0] & 0x80)
+		port->supported_classes |= FC_COS_CLASS3;
+	if (plogi->serv_param.class4_serv_param[0] & 0x80)
+		port->supported_classes |= FC_COS_CLASS4;
+}
+
 #undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c
index 241136d..57d8e4b 100644
--- a/drivers/s390/scsi/zfcp_ccw.c
+++ b/drivers/s390/scsi/zfcp_ccw.c
@@ -1,16 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_ccw.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * CCW driver related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *	Heiko Carstens <heiko.carstens@de.ibm.com>
- *      Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index a5f2ba9..c033145 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -1,12 +1,8 @@
 /*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * linux/drivers/s390/scsi/zfcp_dbf.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * Debugging facilities
- *
- * (C) Copyright IBM Corp. 2005
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 6eba56c..2df512a 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -1,19 +1,8 @@
 /* 
- * 
- * linux/drivers/s390/scsi/zfcp_def.h
- * 
- * FCP adapter driver for IBM eServer zSeries 
- * 
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
- *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh
- *            Wolfgang Taphorn
- *            Stefan Bader <stefan.bader@de.ibm.com> 
- *            Heiko Carstens <heiko.carstens@de.ibm.com> 
- *            Andreas Herrmann <aherrman@de.ibm.com>
- *            Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  * 
  * This program is free software; you can redistribute it and/or modify 
  * it under the terms of the GNU General Public License as published by 
@@ -50,7 +39,6 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_transport_fc.h>
-#include "../../fc4/fc.h"
 #include "zfcp_fsf.h"
 #include <asm/ccwdev.h>
 #include <asm/qdio.h>
@@ -64,7 +52,7 @@
 /********************* GENERAL DEFINES *********************************/
 
 /* zfcp version number, it consists of major, minor, and patch-level number */
-#define ZFCP_VERSION		"4.5.0"
+#define ZFCP_VERSION		"4.7.0"
 
 /**
  * zfcp_sg_to_address - determine kernel address from struct scatterlist
@@ -89,13 +77,9 @@
 	list->offset = ((unsigned long) address) & (PAGE_SIZE - 1);
 }
 
+#define REQUEST_LIST_SIZE 128
+
 /********************* SCSI SPECIFIC DEFINES *********************************/
-
-/* 32 bit for SCSI ID and LUN as long as the SCSI stack uses this type */
-typedef u32 scsi_id_t;
-typedef u32 scsi_lun_t;
-
-#define ZFCP_ERP_SCSI_LOW_MEM_TIMEOUT           (100*HZ)
 #define ZFCP_SCSI_ER_TIMEOUT                    (100*HZ)
 
 /********************* CIO/QDIO SPECIFIC DEFINES *****************************/
@@ -233,8 +217,9 @@
 #define RSP_CODE_TASKMAN_FAILED	 5
 
 /* see fc-fs */
-#define LS_FAN 0x60000000
-#define LS_RSCN 0x61040000
+#define LS_RSCN  0x61040000
+#define LS_LOGO  0x05000000
+#define LS_PLOGI 0x03000000
 
 struct fcp_rscn_head {
         u8  command;
@@ -263,13 +248,6 @@
 #define ZFCP_NO_PORTS_PER_DOMAIN  0x10000
 #define ZFCP_NO_PORTS_PER_FABRIC  0x1000000
 
-struct fcp_fan {
-        u32 command;
-        u32 fport_did;
-        wwn_t fport_wwpn;
-        wwn_t fport_wwname;
-} __attribute__((packed));
-
 /* see fc-ph */
 struct fcp_logo {
         u32 command;
@@ -507,9 +485,6 @@
 
 #define ZFCP_NAME               "zfcp"
 
-/* read-only LUN sharing switch initial value */
-#define ZFCP_RO_LUN_SHARING_DEFAULTS 0
-
 /* independent log areas */
 #define ZFCP_LOG_AREA_OTHER	0
 #define ZFCP_LOG_AREA_SCSI	1
@@ -608,7 +583,6 @@
  * and unit
  */
 #define ZFCP_COMMON_FLAGS			0xfff00000
-#define ZFCP_SPECIFIC_FLAGS			0x000fffff
 
 /* common status bits */
 #define ZFCP_STATUS_COMMON_REMOVE		0x80000000
@@ -633,11 +607,6 @@
 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED	0x00000200
 #define ZFCP_STATUS_ADAPTER_XPORT_OK		0x00000800
 
-#define ZFCP_STATUS_ADAPTER_SCSI_UP			\
-		(ZFCP_STATUS_COMMON_UNBLOCKED |	\
-		 ZFCP_STATUS_ADAPTER_REGISTERED)
-
-
 /* FC-PH/FC-GS well-known address identifiers for generic services */
 #define ZFCP_DID_MANAGEMENT_SERVICE		0xFFFFFA
 #define ZFCP_DID_TIME_SERVICE			0xFFFFFB
@@ -652,7 +621,6 @@
 #define ZFCP_STATUS_PORT_NO_WWPN		0x00000008
 #define ZFCP_STATUS_PORT_NO_SCSI_ID		0x00000010
 #define ZFCP_STATUS_PORT_INVALID_WWPN		0x00000020
-#define ZFCP_STATUS_PORT_ACCESS_DENIED		0x00000040
 
 /* for ports with well known addresses */
 #define ZFCP_STATUS_PORT_WKA \
@@ -908,15 +876,12 @@
 	wwn_t			peer_wwpn;	   /* P2P peer WWPN */
 	u32			peer_d_id;	   /* P2P peer D_ID */
 	struct ccw_device       *ccw_device;	   /* S/390 ccw device */
-	u8			fc_service_class;
 	u32			hydra_version;	   /* Hydra version */
 	u32			fsf_lic_version;
 	u32			adapter_features;  /* FCP channel features */
 	u32			connection_features; /* host connection features */
         u32			hardware_version;  /* of FCP channel */
 	struct Scsi_Host	*scsi_host;	   /* Pointer to mid-layer */
-	unsigned short          scsi_host_no;      /* Assigned host number */
-	unsigned char		name[9];
 	struct list_head	port_list_head;	   /* remote port list */
 	struct list_head        port_remove_lh;    /* head of ports to be
 						      removed */
@@ -994,6 +959,8 @@
 	u32		       handle;	       /* handle assigned by FSF */
 	struct zfcp_erp_action erp_action;     /* pending error recovery */
         atomic_t               erp_counter;
+	u32                    maxframe_size;
+	u32                    supported_classes;
 };
 
 /* the struct device sysfs_device must be at the beginning of this structure.
@@ -1008,7 +975,7 @@
 						  refcount drop to zero */
 	struct zfcp_port       *port;	       /* remote port of unit */
 	atomic_t	       status;	       /* status of this logical unit */
-	scsi_lun_t	       scsi_lun;       /* own SCSI LUN */
+	unsigned int	       scsi_lun;       /* own SCSI LUN */
 	fcp_lun_t	       fcp_lun;	       /* own FCP_LUN */
 	u32		       handle;	       /* handle assigned by FSF */
         struct scsi_device     *device;        /* scsi device struct pointer */
@@ -1052,11 +1019,6 @@
 	struct list_head	adapter_list_head;  /* head of adapter list */
 	struct list_head	adapter_remove_lh;  /* head of adapters to be
 						       removed */
-        rwlock_t                status_read_lock;   /* for status read thread */
-        struct list_head        status_read_receive_head;
-        struct list_head        status_read_send_head;
-        struct semaphore        status_read_sema;
-	wait_queue_head_t	status_read_thread_wqh;
 	u32			adapters;	    /* # of adapters in list */
 	rwlock_t                config_lock;        /* serialises changes
 						       to adapter/port/unit
@@ -1095,9 +1057,6 @@
 
 /********************** ZFCP SPECIFIC DEFINES ********************************/
 
-#define ZFCP_FSFREQ_CLEANUP_TIMEOUT	HZ/10
-
-#define ZFCP_KNOWN              0x00000001
 #define ZFCP_REQ_AUTO_CLEANUP	0x00000002
 #define ZFCP_WAIT_FOR_SBAL	0x00000004
 #define ZFCP_REQ_NO_QTCB	0x00000008
@@ -1105,9 +1064,6 @@
 #define ZFCP_SET                0x00000100
 #define ZFCP_CLEAR              0x00000200
 
-#define ZFCP_INTERRUPTIBLE	1
-#define ZFCP_UNINTERRUPTIBLE	0
-
 #ifndef atomic_test_mask
 #define atomic_test_mask(mask, target) \
            ((atomic_read(target) & mask) == mask)
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 57cb628..909731b 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1,18 +1,8 @@
 /* 
- * 
- * linux/drivers/s390/scsi/zfcp_erp.c 
- * 
- * FCP adapter driver for IBM eServer zSeries 
- * 
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
- *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh
- *            Wolfgang Taphorn
- *            Stefan Bader <stefan.bader@de.ibm.com> 
- *            Heiko Carstens <heiko.carstens@de.ibm.com> 
- *            Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  * 
  * This program is free software; you can redistribute it and/or modify 
  * it under the terms of the GNU General Public License as published by 
@@ -177,7 +167,7 @@
  *		initiates adapter recovery which is done
  *		asynchronously
  *
- * returns:	0	- initiated action succesfully
+ * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
 int
@@ -213,7 +203,7 @@
  * purpose:	Wrappper for zfcp_erp_adapter_reopen_internal
  *              used to ensure the correct locking
  *
- * returns:	0	- initiated action succesfully
+ * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
 int
@@ -231,13 +221,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 int
 zfcp_erp_adapter_shutdown(struct zfcp_adapter *adapter, int clear_mask)
 {
@@ -251,13 +234,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 int
 zfcp_erp_port_shutdown(struct zfcp_port *port, int clear_mask)
 {
@@ -271,13 +247,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 int
 zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
 {
@@ -306,20 +275,17 @@
 	int retval = 0;
 	struct timer_list *timer;
 
-	send_els = kmalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
+	send_els = kzalloc(sizeof(struct zfcp_send_els), GFP_ATOMIC);
 	if (send_els == NULL)
 		goto nomem;
-	memset(send_els, 0, sizeof(*send_els));
 
-	send_els->req = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+	send_els->req = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC);
 	if (send_els->req == NULL)
 		goto nomem;
-	memset(send_els->req, 0, sizeof(*send_els->req));
 
-	send_els->resp = kmalloc(sizeof(struct scatterlist), GFP_ATOMIC);
+	send_els->resp = kzalloc(sizeof(struct scatterlist), GFP_ATOMIC);
 	if (send_els->resp == NULL)
 		goto nomem;
-	memset(send_els->resp, 0, sizeof(*send_els->resp));
 
 	address = (void *) get_zeroed_page(GFP_ATOMIC);
 	if (address == NULL)
@@ -503,7 +469,7 @@
  *		initiates Forced Reopen recovery which is done
  *		asynchronously
  *
- * returns:	0	- initiated action succesfully
+ * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
 static int
@@ -543,7 +509,7 @@
  * purpose:	Wrappper for zfcp_erp_port_forced_reopen_internal
  *              used to ensure the correct locking
  *
- * returns:	0	- initiated action succesfully
+ * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
 int
@@ -570,7 +536,7 @@
  *		initiates Reopen recovery which is done
  *		asynchronously
  *
- * returns:	0	- initiated action succesfully
+ * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
 static int
@@ -639,7 +605,7 @@
  *		initiates Reopen recovery which is done
  *		asynchronously
  *
- * returns:	0	- initiated action succesfully
+ * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
 static int
@@ -812,13 +778,6 @@
 	atomic_set_mask(ZFCP_STATUS_COMMON_UNBLOCKED, &unit->status);
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static void
 zfcp_erp_action_ready(struct zfcp_erp_action *erp_action)
 {
@@ -1356,13 +1315,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action)
 {
@@ -1538,13 +1490,6 @@
 	return result;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_strategy_statechange(int action,
 			      u32 status,
@@ -1586,13 +1531,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static inline int
 zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status)
 {
@@ -1605,13 +1543,6 @@
 	     !(ZFCP_STATUS_ERP_CLOSE_ONLY & erp_status));
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_strategy_check_unit(struct zfcp_unit *unit, int result)
 {
@@ -1642,13 +1573,6 @@
 	return result;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_strategy_check_port(struct zfcp_port *port, int result)
 {
@@ -1678,13 +1602,6 @@
 	return result;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
 {
@@ -1764,13 +1681,6 @@
 	return 0;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_strategy_check_queues(struct zfcp_adapter *adapter)
 {
@@ -1809,12 +1719,6 @@
 	return retval;
 }
 
-/*
- * function:	zfcp_erp_modify_adapter_status
- *
- * purpose:	
- *
- */
 void
 zfcp_erp_modify_adapter_status(struct zfcp_adapter *adapter,
 			       u32 mask, int set_or_clear)
@@ -1901,7 +1805,7 @@
  * purpose:	Wrappper for zfcp_erp_port_reopen_all_internal
  *              used to ensure the correct locking
  *
- * returns:	0	- initiated action succesfully
+ * returns:	0	- initiated action successfully
  *		<0	- failed to initiate action
  */
 int
@@ -1919,13 +1823,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:	FIXME
- */
 static int
 zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask)
 {
@@ -2370,13 +2267,6 @@
 	return ret;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action
 					      *erp_action)
@@ -2545,13 +2435,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_port_strategy_open(struct zfcp_erp_action *erp_action)
 {
@@ -2566,15 +2449,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- *
- * FIXME(design):	currently only prepared for fabric (nameserver!)
- */
 static int
 zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
 {
@@ -2690,13 +2564,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
 {
@@ -2813,13 +2680,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_port_strategy_clearstati(struct zfcp_port *port)
 {
@@ -3022,13 +2882,6 @@
 	return retval;
 }
 
-/*
- * function:
- *
- * purpose:
- *
- * returns:
- */
 static int
 zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit)
 {
@@ -3129,13 +2982,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static inline void
 zfcp_erp_timeout_init(struct zfcp_erp_action *erp_action)
 {
@@ -3331,13 +3177,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 static int
 zfcp_erp_action_dequeue(struct zfcp_erp_action *erp_action)
 {
@@ -3402,9 +3241,13 @@
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
 	case ZFCP_ERP_ACTION_REOPEN_PORT:
+		if (atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
+				     &port->status)) {
+			zfcp_port_put(port);
+			break;
+		}
+
 		if ((result == ZFCP_ERP_SUCCEEDED)
-		    && !atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN,
-					 &port->status)
 		    && !port->rport) {
 			struct fc_rport_identifiers ids;
 			ids.node_name = port->wwnn;
@@ -3418,12 +3261,30 @@
 						"(adapter %s, wwpn=0x%016Lx)\n",
 						zfcp_get_busid_by_port(port),
 						port->wwpn);
-			else
+			else {
 				scsi_flush_work(adapter->scsi_host);
+				port->rport->maxframe_size = port->maxframe_size;
+				port->rport->supported_classes =
+					port->supported_classes;
+			}
+		}
+		if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) {
+			fc_remote_port_delete(port->rport);
+			port->rport = NULL;
 		}
 		zfcp_port_put(port);
 		break;
 	case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+		if (result != ZFCP_ERP_SUCCEEDED) {
+			struct zfcp_port *port;
+			list_for_each_entry(port, &adapter->port_list_head, list)
+				if (port->rport &&
+				    !atomic_test_mask(ZFCP_STATUS_PORT_WKA,
+						      &port->status)) {
+					fc_remote_port_delete(port->rport);
+					port->rport = NULL;
+				}
+		}
 		zfcp_adapter_put(adapter);
 		break;
 	default:
@@ -3432,13 +3293,6 @@
 }
 
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:	FIXME
- */
 static int
 zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
 {
@@ -3455,13 +3309,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:	FIXME
- */
 static int
 zfcp_erp_action_dismiss_port(struct zfcp_port *port)
 {
@@ -3480,13 +3327,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:	FIXME
- */
 static int
 zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit)
 {
@@ -3501,13 +3341,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	moves erp_action to 'erp running list'
- *
- * returns:
- */
 static inline void
 zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action)
 {
@@ -3518,13 +3351,6 @@
 	list_move(&erp_action->list, &erp_action->adapter->erp_running_head);
 }
 
-/*
- * function:	
- *
- * purpose:	moves erp_action to 'erp ready list'
- *
- * returns:
- */
 static inline void
 zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
 {
@@ -3535,11 +3361,6 @@
 	list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
 }
 
-/*
- * function:	zfcp_erp_port_boxed
- *
- * purpose:
- */
 void
 zfcp_erp_port_boxed(struct zfcp_port *port)
 {
@@ -3556,11 +3377,6 @@
 	zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
 }
 
-/*
- * function:	zfcp_erp_unit_boxed
- *
- * purpose:
- */
 void
 zfcp_erp_unit_boxed(struct zfcp_unit *unit)
 {
@@ -3574,11 +3390,6 @@
 	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
 }
 
-/*
- * function:	zfcp_erp_port_access_denied
- *
- * purpose:
- */
 void
 zfcp_erp_port_access_denied(struct zfcp_port *port)
 {
@@ -3595,11 +3406,6 @@
 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
-/*
- * function:	zfcp_erp_unit_access_denied
- *
- * purpose:
- */
 void
 zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
 {
@@ -3613,11 +3419,6 @@
 			ZFCP_SET);
 }
 
-/*
- * function:	zfcp_erp_adapter_access_changed
- *
- * purpose:
- */
 void
 zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
 {
@@ -3628,7 +3429,7 @@
 		return;
 
 	debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
-	debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
+	debug_event(adapter->erp_dbf, 3, zfcp_get_busid_by_adapter(adapter), 8);
 
 	read_lock_irqsave(&zfcp_data.config_lock, flags);
 	if (adapter->nameserver_port)
@@ -3639,11 +3440,6 @@
 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
-/*
- * function:	zfcp_erp_port_access_changed
- *
- * purpose:
- */
 void
 zfcp_erp_port_access_changed(struct zfcp_port *port)
 {
@@ -3672,11 +3468,6 @@
 				zfcp_get_busid_by_adapter(adapter), port->wwpn);
 }
 
-/*
- * function:	zfcp_erp_unit_access_changed
- *
- * purpose:
- */
 void
 zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
 {
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 700f540..d023660 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -1,18 +1,8 @@
 /* 
- * 
- * linux/drivers/s390/scsi/zfcp_ext.h
- * 
- * FCP adapter driver for IBM eServer zSeries 
- * 
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
- *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh
- *            Wolfgang Taphorn
- *            Stefan Bader <stefan.bader@de.ibm.com> 
- *            Heiko Carstens <heiko.carstens@de.ibm.com> 
- *            Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  * 
  * This program is free software; you can redistribute it and/or modify 
  * it under the terms of the GNU General Public License as published by 
@@ -125,6 +115,7 @@
 extern int  zfcp_ns_gid_pn_request(struct zfcp_erp_action *);
 extern int  zfcp_check_ct_response(struct ct_hdr *);
 extern int  zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *);
+extern void zfcp_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
 
 /******************************* SCSI ****************************************/
 extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
@@ -141,8 +132,6 @@
 				   struct scsi_cmnd *, struct timer_list *);
 extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
 				  struct timer_list *);
-extern void zfcp_set_fc_host_attrs(struct zfcp_adapter *);
-extern void zfcp_set_fc_rport_attrs(struct zfcp_port *);
 extern struct scsi_transport_template *zfcp_transport_template;
 extern struct fc_function_template zfcp_transport_functions;
 
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 662ec57..6335f92 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1,19 +1,8 @@
 /*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * linux/drivers/s390/scsi/zfcp_fsf.c
- *
- * FCP adapter driver for IBM eServer zSeries
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com>
- *            Raimund Schroeder <raimund.schroeder@de.ibm.com>
- *            Aron Zeh
- *            Wolfgang Taphorn
- *            Stefan Bader <stefan.bader@de.ibm.com>
- *            Heiko Carstens <heiko.carstens@de.ibm.com>
- *            Andreas Herrmann <aherrman@de.ibm.com>
- *            Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -877,6 +866,7 @@
 	struct zfcp_adapter *adapter = fsf_req->adapter;
 	struct fsf_status_read_buffer *status_buffer =
 		(struct fsf_status_read_buffer *) fsf_req->data;
+	struct fsf_bit_error_payload *fsf_bit_error;
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
 		zfcp_hba_dbf_event_fsf_unsol("dism", adapter, status_buffer);
@@ -903,10 +893,37 @@
 		break;
 
 	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
-		ZFCP_LOG_NORMAL("Bit error threshold data received:\n");
-		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
-			      (char *) status_buffer,
-			      sizeof (struct fsf_status_read_buffer));
+		fsf_bit_error = (struct fsf_bit_error_payload *)
+			status_buffer->payload;
+		ZFCP_LOG_NORMAL("Warning: bit error threshold data "
+		    "received (adapter %s, "
+		    "link failures = %i, loss of sync errors = %i, "
+		    "loss of signal errors = %i, "
+		    "primitive sequence errors = %i, "
+		    "invalid transmission word errors = %i, "
+		    "CRC errors = %i)\n",
+		    zfcp_get_busid_by_adapter(adapter),
+		    fsf_bit_error->link_failure_error_count,
+		    fsf_bit_error->loss_of_sync_error_count,
+		    fsf_bit_error->loss_of_signal_error_count,
+		    fsf_bit_error->primitive_sequence_error_count,
+		    fsf_bit_error->invalid_transmission_word_error_count,
+		    fsf_bit_error->crc_error_count);
+		ZFCP_LOG_INFO("Additional bit error threshold data "
+		    "(adapter %s, "
+		    "primitive sequence event time-outs = %i, "
+		    "elastic buffer overrun errors = %i, "
+		    "advertised receive buffer-to-buffer credit = %i, "
+		    "current receice buffer-to-buffer credit = %i, "
+		    "advertised transmit buffer-to-buffer credit = %i, "
+		    "current transmit buffer-to-buffer credit = %i)\n",
+		    zfcp_get_busid_by_adapter(adapter),
+		    fsf_bit_error->primitive_sequence_event_timeout_count,
+		    fsf_bit_error->elastic_buffer_overrun_error_count,
+		    fsf_bit_error->advertised_receive_b2b_credit,
+		    fsf_bit_error->current_receive_b2b_credit,
+		    fsf_bit_error->advertised_transmit_b2b_credit,
+		    fsf_bit_error->current_transmit_b2b_credit);
 		break;
 
 	case FSF_STATUS_READ_LINK_DOWN:
@@ -1427,7 +1444,8 @@
 
 	/* settings in QTCB */
 	fsf_req->qtcb->header.port_handle = port->handle;
-	fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
+	fsf_req->qtcb->bottom.support.service_class =
+		ZFCP_FC_SERVICE_CLASS_DEFAULT;
 	fsf_req->qtcb->bottom.support.timeout = ct->timeout;
         fsf_req->data = (unsigned long) ct;
 
@@ -1496,18 +1514,10 @@
 		break;
 
         case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		if (adapter->fc_service_class <= 3) {
-			ZFCP_LOG_INFO("error: adapter %s does not support fc "
-				      "class %d.\n",
-				      zfcp_get_busid_by_port(port),
-				      adapter->fc_service_class);
-		} else {
-			ZFCP_LOG_INFO("bug: The fibre channel class at the "
-				      "adapter %s is invalid. "
-				      "(debug info %d)\n",
-				      zfcp_get_busid_by_port(port),
-				      adapter->fc_service_class);
-		}
+		ZFCP_LOG_INFO("error: adapter %s does not support fc "
+			      "class %d.\n",
+			      zfcp_get_busid_by_port(port),
+			      ZFCP_FC_SERVICE_CLASS_DEFAULT);
 		/* stop operation for this adapter */
 		debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
 		zfcp_erp_adapter_shutdown(adapter, 0);
@@ -1730,7 +1740,8 @@
 
 	/* settings in QTCB */
 	fsf_req->qtcb->bottom.support.d_id = d_id;
-	fsf_req->qtcb->bottom.support.service_class = adapter->fc_service_class;
+	fsf_req->qtcb->bottom.support.service_class =
+		ZFCP_FC_SERVICE_CLASS_DEFAULT;
 	fsf_req->qtcb->bottom.support.timeout = ZFCP_ELS_TIMEOUT;
 	fsf_req->data = (unsigned long) els;
 
@@ -1800,18 +1811,10 @@
 		break;
 
 	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		if (adapter->fc_service_class <= 3) {
-			ZFCP_LOG_INFO("error: adapter %s does "
-				      "not support fibrechannel class %d.\n",
-				      zfcp_get_busid_by_adapter(adapter),
-				      adapter->fc_service_class);
-		} else {
-			ZFCP_LOG_INFO("bug: The fibrechannel class at "
-				      "adapter %s is invalid. "
-				      "(debug info %d)\n",
-				      zfcp_get_busid_by_adapter(adapter),
-				      adapter->fc_service_class);
-		}
+		ZFCP_LOG_INFO("error: adapter %s does not support fc "
+			      "class %d.\n",
+			      zfcp_get_busid_by_adapter(adapter),
+			      ZFCP_FC_SERVICE_CLASS_DEFAULT);
 		/* stop operation for this adapter */
 		debug_text_exception(adapter->erp_dbf, 0, "fsf_s_class_nsup");
 		zfcp_erp_adapter_shutdown(adapter, 0);
@@ -1940,14 +1943,6 @@
 	return retval;
 }
 
-/*
- * function:
- *
- * purpose:
- *
- * returns:	address of initiated FSF request
- *		NULL - request could not be initiated
- */
 int
 zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
 {
@@ -2565,8 +2560,7 @@
 		if (!atomic_test_mask(ZFCP_STATUS_PORT_NO_WWPN, &port->status))
 		{
 			if (fsf_req->qtcb->bottom.support.els1_length <
-			    ((((unsigned long) &plogi->serv_param.wwpn) -
-			      ((unsigned long) plogi)) + sizeof (u64))) {
+			    sizeof (struct fsf_plogi)) {
 				ZFCP_LOG_INFO(
 					"warning: insufficient length of "
 					"PLOGI payload (%i)\n",
@@ -2585,8 +2579,10 @@
 					atomic_clear_mask(
 						ZFCP_STATUS_PORT_DID_DID,
 						&port->status);
-				} else
+				} else {
 					port->wwnn = plogi->serv_param.wwnn;
+					zfcp_plogi_evaluate(port, plogi);
+				}
 			}
 		}
 		break;
@@ -2993,8 +2989,8 @@
 	erp_action->fsf_req->qtcb->bottom.support.fcp_lun =
 		erp_action->unit->fcp_lun;
 	if (!(erp_action->adapter->connection_features & FSF_FEATURE_NPIV_MODE))
-	erp_action->fsf_req->qtcb->bottom.support.option =
-		FSF_OPEN_LUN_SUPPRESS_BOXING;
+		erp_action->fsf_req->qtcb->bottom.support.option =
+			FSF_OPEN_LUN_SUPPRESS_BOXING;
 	atomic_set_mask(ZFCP_STATUS_COMMON_OPENING, &erp_action->unit->status);
 	erp_action->fsf_req->data = (unsigned long) erp_action->unit;
 	erp_action->fsf_req->erp_action = erp_action;
@@ -3569,7 +3565,7 @@
 	}
 
 	/* set FC service class in QTCB (3 per default) */
-	fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class;
+	fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT;
 
 	/* set FCP_LUN in FCP_CMND IU in QTCB */
 	fcp_cmnd_iu->fcp_lun = unit->fcp_lun;
@@ -3667,18 +3663,6 @@
 	return retval;
 }
 
-/*
- * function:    zfcp_fsf_send_fcp_command_task_management
- *
- * purpose:
- *
- * returns:
- *
- * FIXME(design): should be watched by a timeout!!!
- * FIXME(design) shouldn't this be modified to return an int
- *               also...don't know how though
- *
- */
 struct zfcp_fsf_req *
 zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
 					  struct zfcp_unit *unit,
@@ -3720,7 +3704,7 @@
 	fsf_req->qtcb->header.lun_handle = unit->handle;
 	fsf_req->qtcb->header.port_handle = unit->port->handle;
 	fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
-	fsf_req->qtcb->bottom.io.service_class = adapter->fc_service_class;
+	fsf_req->qtcb->bottom.io.service_class = ZFCP_FC_SERVICE_CLASS_DEFAULT;
 	fsf_req->qtcb->bottom.io.fcp_cmnd_length =
 		sizeof (struct fcp_cmnd_iu) + sizeof (fcp_dl_t);
 
@@ -3843,18 +3827,10 @@
 		break;
 
 	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		if (fsf_req->adapter->fc_service_class <= 3) {
-			ZFCP_LOG_NORMAL("error: The adapter %s does "
-					"not support fibrechannel class %d.\n",
-					zfcp_get_busid_by_unit(unit),
-					fsf_req->adapter->fc_service_class);
-		} else {
-			ZFCP_LOG_NORMAL("bug: The fibrechannel class at "
-					"adapter %s is invalid. "
-					"(debug info %d)\n",
-					zfcp_get_busid_by_unit(unit),
-					fsf_req->adapter->fc_service_class);
-		}
+		ZFCP_LOG_INFO("error: adapter %s does not support fc "
+			      "class %d.\n",
+			      zfcp_get_busid_by_unit(unit),
+			      ZFCP_FC_SERVICE_CLASS_DEFAULT);
 		/* stop operation for this adapter */
 		debug_text_exception(fsf_req->adapter->erp_dbf, 0,
 				     "fsf_s_class_nsup");
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index e734415..7118661 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -1,19 +1,8 @@
 /* 
- * 
- * linux/drivers/s390/scsi/zfcp_fsf.h
- * 
- * FCP adapter driver for IBM eServer zSeries 
- * 
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
- *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh
- *            Wolfgang Taphorn
- *            Stefan Bader <stefan.bader@de.ibm.com> 
- *            Heiko Carstens <heiko.carstens@de.ibm.com>
- *            Andreas Herrmann <aherrman@de.ibm.com>
- *            Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  * 
  * This program is free software; you can redistribute it and/or modify 
  * it under the terms of the GNU General Public License as published by 
@@ -33,8 +22,7 @@
 #ifndef FSF_H
 #define FSF_H
 
-#define FSF_QTCB_VERSION1			0x00000001
-#define FSF_QTCB_CURRENT_VERSION		FSF_QTCB_VERSION1
+#define FSF_QTCB_CURRENT_VERSION		0x00000001
 
 /* FSF commands */
 #define	FSF_QTCB_FCP_CMND			0x00000001
@@ -64,7 +52,7 @@
 #define FSF_CFDC_OPTION_FULL_ACCESS		0x00000002
 #define FSF_CFDC_OPTION_RESTRICTED_ACCESS	0x00000004
 
-/* FSF protocol stati */
+/* FSF protocol states */
 #define FSF_PROT_GOOD				0x00000001
 #define FSF_PROT_QTCB_VERSION_ERROR		0x00000010
 #define FSF_PROT_SEQ_NUMB_ERROR			0x00000020
@@ -76,7 +64,7 @@
 #define FSF_PROT_REEST_QUEUE                    0x00000800
 #define FSF_PROT_ERROR_STATE			0x01000000
 
-/* FSF stati */
+/* FSF states */
 #define FSF_GOOD				0x00000000
 #define FSF_PORT_ALREADY_OPEN			0x00000001
 #define FSF_LUN_ALREADY_OPEN			0x00000002
@@ -269,20 +257,6 @@
 #define FSF_UNIT_ACCESS_EXCLUSIVE		0x02000000
 #define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER	0x10000000
 
-struct fsf_queue_designator;
-struct fsf_status_read_buffer;
-struct fsf_port_closed_payload;
-struct fsf_bit_error_payload;
-union  fsf_prot_status_qual;
-struct fsf_qual_version_error;
-struct fsf_qual_sequence_error;
-struct fsf_qtcb_prefix;
-struct fsf_qtcb_header;
-struct fsf_qtcb_bottom_config;
-struct fsf_qtcb_bottom_support;
-struct fsf_qtcb_bottom_io;
-union  fsf_qtcb_bottom;
-
 struct fsf_queue_designator {
 	u8  cssid;
 	u8  chpid;
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 1c32751..345a191 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -1,18 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_qdio.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * QDIO related routines
- *
- * (C) Copyright IBM Corp. 2002, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *      Raimund Schroeder <raimund.schroeder@de.ibm.com>
- *      Wolfgang Taphorn
- *      Heiko Carstens <heiko.carstens@de.ibm.com>
- *      Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -178,7 +168,8 @@
 
 	init_data->cdev = adapter->ccw_device;
 	init_data->q_format = QDIO_SCSI_QFMT;
-	memcpy(init_data->adapter_name, &adapter->name, 8);
+	memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 8);
+	ASCEBC(init_data->adapter_name, 8);
 	init_data->qib_param_field_format = 0;
 	init_data->qib_param_field = NULL;
 	init_data->input_slib_elements = NULL;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 9e6d07d..46e14f2 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -1,18 +1,8 @@
 /* 
- * 
- * linux/drivers/s390/scsi/zfcp_scsi.c
- * 
- * FCP adapter driver for IBM eServer zSeries 
- * 
- * (C) Copyright IBM Corp. 2002, 2004
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * Author(s): Martin Peschke <mpeschke@de.ibm.com> 
- *            Raimund Schroeder <raimund.schroeder@de.ibm.com> 
- *            Aron Zeh
- *            Wolfgang Taphorn
- *            Stefan Bader <stefan.bader@de.ibm.com> 
- *            Heiko Carstens <heiko.carstens@de.ibm.com> 
- *            Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  * 
  * This program is free software; you can redistribute it and/or modify 
  * it under the terms of the GNU General Public License as published by 
@@ -45,8 +35,8 @@
 static int zfcp_task_management_function(struct zfcp_unit *, u8,
 					 struct scsi_cmnd *);
 
-static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
-					  scsi_lun_t);
+static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
+					  unsigned int, unsigned int);
 
 static struct device_attribute *zfcp_sysfs_sdev_attrs[];
 
@@ -161,14 +151,6 @@
 	set_byte(result, status, 3);
 }
 
-/*
- * function:	zfcp_scsi_slave_alloc
- *
- * purpose:
- *
- * returns:
- */
-
 static int
 zfcp_scsi_slave_alloc(struct scsi_device *sdp)
 {
@@ -195,14 +177,6 @@
 	return retval;
 }
 
-/*
- * function:	zfcp_scsi_slave_destroy
- *
- * purpose:
- *
- * returns:
- */
-
 static void
 zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
 {
@@ -374,18 +348,9 @@
 	return zfcp_scsi_command_async(adapter, unit, scpnt, NULL);
 }
 
-/*
- * function:    zfcp_unit_lookup
- *
- * purpose:
- *
- * returns:
- *
- * context:	
- */
 static struct zfcp_unit *
-zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
-		 scsi_lun_t lun)
+zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id,
+		 unsigned int lun)
 {
 	struct zfcp_port *port;
 	struct zfcp_unit *unit, *retval = NULL;
@@ -491,13 +456,6 @@
 	return retval;
 }
 
-/*
- * function:	zfcp_scsi_eh_device_reset_handler
- *
- * purpose:
- *
- * returns:
- */
 int
 zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
 {
@@ -625,13 +583,6 @@
 	return SUCCESS;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 int
 zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
 {
@@ -657,10 +608,6 @@
 	adapter->scsi_host->unique_id = unique_id++;	/* FIXME */
 	adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH;
 	adapter->scsi_host->transportt = zfcp_transport_template;
-	/*
-	 * Reverse mapping of the host number to avoid race condition
-	 */
-	adapter->scsi_host_no = adapter->scsi_host->host_no;
 
 	/*
 	 * save a pointer to our own adapter data structure within
@@ -678,13 +625,6 @@
 	return retval;
 }
 
-/*
- * function:	
- *
- * purpose:	
- *
- * returns:
- */
 void
 zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
 {
@@ -703,7 +643,6 @@
 	scsi_remove_host(shost);
 	scsi_host_put(shost);
 	adapter->scsi_host = NULL;
-	adapter->scsi_host_no = 0;
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);
 
 	return;
@@ -817,10 +756,9 @@
 	if (!fc_stats)
 		return NULL;
 
-	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return NULL;
-	memset(data, 0, sizeof(*data));
 
 	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
 	if (ret) {
@@ -848,10 +786,9 @@
 	int ret;
 
 	adapter = (struct zfcp_adapter *)shost->hostdata[0];
-	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return;
-	memset(data, 0, sizeof(*data));
 
 	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
 	if (ret == 0) {
@@ -863,11 +800,18 @@
 	}
 }
 
+static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+{
+	rport->dev_loss_tmo = timeout;
+}
+
 struct fc_function_template zfcp_transport_functions = {
 	.show_starget_port_id = 1,
 	.show_starget_port_name = 1,
 	.show_starget_node_name = 1,
 	.show_rport_supported_classes = 1,
+	.show_rport_maxframe_size = 1,
+	.show_rport_dev_loss_tmo = 1,
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
 	.show_host_permanent_port_name = 1,
@@ -877,6 +821,7 @@
 	.show_host_serial_number = 1,
 	.get_fc_host_stats = zfcp_get_fc_host_stats,
 	.reset_fc_host_stats = zfcp_reset_fc_host_stats,
+	.set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
 	/* no functions registered for following dynamic attributes but
 	   directly set by LLDD */
 	.show_host_port_type = 1,
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index b29ac25..705c6d4 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -1,16 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_sysfs_adapter.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs adapter related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *	Heiko Carstens <heiko.carstens@de.ibm.com>
- *      Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c
index 6622d55..005e62f 100644
--- a/drivers/s390/scsi/zfcp_sysfs_driver.c
+++ b/drivers/s390/scsi/zfcp_sysfs_driver.c
@@ -1,16 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_sysfs_driver.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs driver related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *	Heiko Carstens <heiko.carstens@de.ibm.com>
- *      Andreas Herrmann <aherrman@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index f401d42..1320c05 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -1,17 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_sysfs_port.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs port related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *	Heiko Carstens <heiko.carstens@de.ibm.com>
- *      Andreas Herrmann <aherrman@de.ibm.com>
- *      Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index ad5dfb8..81a4841 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -1,17 +1,8 @@
 /*
- * linux/drivers/s390/scsi/zfcp_sysfs_unit.c
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
  *
- * FCP adapter driver for IBM eServer zSeries
- *
- * sysfs unit related routines
- *
- * (C) Copyright IBM Corp. 2003, 2004
- *
- * Authors:
- *      Martin Peschke <mpeschke@de.ibm.com>
- *	Heiko Carstens <heiko.carstens@de.ibm.com>
- *      Andreas Herrmann <aherrman@de.ibm.com>
- *      Volker Sameske <sameske@de.ibm.com>
+ * (C) Copyright IBM Corp. 2002, 2006
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index d89f83f..1cc706e 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -575,9 +575,9 @@
 	int devidx = 0;
 
 	while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
-		if (!strcmp(echild->prom_name, "temperature"))
+		if (!strcmp(echild->prom_node->name, "temperature"))
 			attach_one_temp(echild, temp_index++);
-		if (!strcmp(echild->prom_name, "fan-control"))
+		if (!strcmp(echild->prom_node->name, "fan-control"))
 			attach_one_fan(echild, fan_index++);
 	}
 	if (temp_index != 0 && fan_index != 0) {
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index 3e156e0..7363437 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -423,7 +423,7 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "bbc"))
+			if (!strcmp(edev->prom_node->name, "bbc"))
 				return 1;
 		}
 	}
@@ -446,7 +446,7 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "i2c")) {
+			if (!strcmp(edev->prom_node->name, "i2c")) {
 				if (!attach_one_i2c(edev, index))
 					index++;
 			}
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index fd2cc77..21737b7 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -304,8 +304,8 @@
 						SA_SHIRQ,
 						WD_OBPNAME,
 						(void *)wd_dev.regs)) {
-			printk("%s: Cannot register IRQ %s\n", 
-				WD_OBPNAME, __irq_itoa(wd_dev.irq));
+			printk("%s: Cannot register IRQ %d\n", 
+				WD_OBPNAME, wd_dev.irq);
 			return(-EBUSY);
 		}
 		wd_dev.initialized = 1;
@@ -755,7 +755,7 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, WD_OBPNAME))
+			if (!strcmp(edev->ofdev.node->name, WD_OBPNAME))
 				goto ebus_done;
 		}
 	}
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index c3a51d1..d92bc88 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -184,7 +184,7 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, D7S_OBPNAME))
+			if (!strcmp(edev->prom_node->name, D7S_OBPNAME))
 				goto ebus_done;
 		}
 	}
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index 19e8edd..cf97e9e 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -768,16 +768,14 @@
  *                       decoding tables, monitor type, optional properties.
  * Return: None.
  */
-static void envctrl_init_adc(struct i2c_child_t *pchild, int node)
+static void envctrl_init_adc(struct i2c_child_t *pchild, struct device_node *dp)
 {
-	char chnls_desc[CHANNEL_DESC_SZ];
 	int i = 0, len;
-	char *pos = chnls_desc;
+	char *pos;
+	unsigned int *pval;
 
 	/* Firmware describe channels into a stream separated by a '\0'. */
-	len = prom_getproperty(node, "channels-description", chnls_desc,
-			       CHANNEL_DESC_SZ);
-	chnls_desc[CHANNEL_DESC_SZ - 1] = '\0';
+	pos = of_get_property(dp, "channels-description", &len);
 
 	while (len > 0) {
 		int l = strlen(pos) + 1;
@@ -787,10 +785,13 @@
 	}
 
 	/* Get optional properties. */
-        len = prom_getproperty(node, "warning-temp", (char *)&warning_temperature,
-			       sizeof(warning_temperature));
-        len = prom_getproperty(node, "shutdown-temp", (char *)&shutdown_temperature,
-			       sizeof(shutdown_temperature));
+	pval = of_get_property(dp, "warning-temp", NULL);
+	if (pval)
+		warning_temperature = *pval;
+
+	pval = of_get_property(dp, "shutdown-temp", NULL);
+	if (pval)
+		shutdown_temperature = *pval;
 }
 
 /* Function Description: Initialize child device monitoring fan status.
@@ -864,21 +865,18 @@
 static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child,
 				   struct i2c_child_t *pchild)
 {
-	int node, len, i, tbls_size = 0;
-
-	node = edev_child->prom_node;
+	int len, i, tbls_size = 0;
+	struct device_node *dp = edev_child->prom_node;
+	void *pval;
 
 	/* Get device address. */
-	len = prom_getproperty(node, "reg",
-			       (char *) &(pchild->addr),
-			       sizeof(pchild->addr));
+	pval = of_get_property(dp, "reg", &len);
+	memcpy(&pchild->addr, pval, len);
 
 	/* Get tables property.  Read firmware temperature tables. */
-	len = prom_getproperty(node, "translation",
-			       (char *) pchild->tblprop_array,
-			       (PCF8584_MAX_CHANNELS *
-				sizeof(struct pcf8584_tblprop)));
-	if (len > 0) {
+	pval = of_get_property(dp, "translation", &len);
+	if (pval && len > 0) {
+		memcpy(pchild->tblprop_array, pval, len);
                 pchild->total_tbls = len / sizeof(struct pcf8584_tblprop);
 		for (i = 0; i < pchild->total_tbls; i++) {
 			if ((pchild->tblprop_array[i].size + pchild->tblprop_array[i].offset) > tbls_size) {
@@ -891,12 +889,12 @@
 			printk("envctrl: Failed to allocate table.\n");
 			return;
 		}
-                len = prom_getproperty(node, "tables",
-				       (char *) pchild->tables, tbls_size);
-                if (len <= 0) {
+		pval = of_get_property(dp, "tables", &len);
+                if (!pval || len <= 0) {
 			printk("envctrl: Failed to get table.\n");
 			return;
 		}
+		memcpy(pchild->tables, pval, len);
 	}
 
 	/* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04)
@@ -907,12 +905,11 @@
 	 * 'NULL' monitor type.
 	 */
 	if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) {
+		struct device_node *root_node;
 		int len;
-		char prop[56];
 
-		len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
-		if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len)))
-		{
+		root_node = of_find_node_by_path("/");
+		if (!strcmp(root_node->name, "SUNW,UltraSPARC-IIi-cEngine")) {
 			for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {
 				pchild->mon_type[len] = ENVCTRL_NOMON;
 			}
@@ -921,16 +918,14 @@
 	}
 
 	/* Get the monitor channels. */
-	len = prom_getproperty(node, "channels-in-use",
-			       (char *) pchild->chnl_array,
-			       (PCF8584_MAX_CHANNELS *
-				sizeof(struct pcf8584_channel)));
+	pval = of_get_property(dp, "channels-in-use", &len);
+	memcpy(pchild->chnl_array, pval, len);
 	pchild->total_chnls = len / sizeof(struct pcf8584_channel);
 
 	for (i = 0; i < pchild->total_chnls; i++) {
 		switch (pchild->chnl_array[i].type) {
 		case PCF8584_TEMP_TYPE:
-			envctrl_init_adc(pchild, node);
+			envctrl_init_adc(pchild, dp);
 			break;
 
 		case PCF8584_GLOBALADDR_TYPE:
@@ -945,7 +940,7 @@
 
 		case PCF8584_VOLTAGE_TYPE:
 			if (pchild->i2ctype == I2C_ADC) {
-				envctrl_init_adc(pchild,node);
+				envctrl_init_adc(pchild,dp);
 			} else {
 				envctrl_init_voltage_status(pchild);
 			}
@@ -1046,7 +1041,7 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "bbc")) {
+			if (!strcmp(edev->prom_node->name, "bbc")) {
 				/* If we find a boot-bus controller node,
 				 * then this envctrl driver is not for us.
 				 */
@@ -1060,14 +1055,14 @@
 	 */
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "i2c")) {
+			if (!strcmp(edev->prom_node->name, "i2c")) {
 				i2c = ioremap(edev->resource[0].start, 0x2);
 				for_each_edevchild(edev, edev_child) {
-					if (!strcmp("gpio", edev_child->prom_name)) {
+					if (!strcmp("gpio", edev_child->prom_node->name)) {
 						i2c_childlist[i].i2ctype = I2C_GPIO;
 						envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
 					}
-					if (!strcmp("adc", edev_child->prom_name)) {
+					if (!strcmp("adc", edev_child->prom_node->name)) {
 						i2c_childlist[i].i2ctype = I2C_ADC;
 						envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++]));
 					}
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 2beb3dd..31b8a5f 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -71,7 +71,6 @@
 	if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size)
 		size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT));
 
-	vma->vm_flags |= (VM_SHM | VM_LOCKED);
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 
 	if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot))
@@ -192,9 +191,11 @@
 	}
 	if (!sdev) {
 #ifdef CONFIG_PCI
+		struct linux_prom_registers *ebus_regs;
+
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
-				if (!strcmp(edev->prom_name, "flashprom"))
+				if (!strcmp(edev->prom_node->name, "flashprom"))
 					goto ebus_done;
 			}
 		}
@@ -202,23 +203,23 @@
 		if (!edev)
 			return -ENODEV;
 
-		len = prom_getproperty(edev->prom_node, "reg", (void *)regs, sizeof(regs));
-		if ((len % sizeof(regs[0])) != 0) {
+		ebus_regs = of_get_property(edev->prom_node, "reg", &len);
+		if (!ebus_regs || (len % sizeof(regs[0])) != 0) {
 			printk("flash: Strange reg property size %d\n", len);
 			return -ENODEV;
 		}
 
-		nregs = len / sizeof(regs[0]);
+		nregs = len / sizeof(ebus_regs[0]);
 
 		flash.read_base = edev->resource[0].start;
-		flash.read_size = regs[0].reg_size;
+		flash.read_size = ebus_regs[0].reg_size;
 
 		if (nregs == 1) {
 			flash.write_base = edev->resource[0].start;
-			flash.write_size = regs[0].reg_size;
+			flash.write_size = ebus_regs[0].reg_size;
 		} else if (nregs == 2) {
 			flash.write_base = edev->resource[1].start;
-			flash.write_size = regs[1].reg_size;
+			flash.write_size = ebus_regs[1].reg_size;
 		} else {
 			printk("flash: Strange number of regs %d\n", nregs);
 			return -ENODEV;
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 239e108..d7e4bb4 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -29,8 +29,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  */
 
-#define PROMLIB_INTERNAL
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -39,10 +37,10 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/miscdevice.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/openpromio.h>
@@ -51,15 +49,20 @@
 #include <asm/pbm.h>
 #endif
 
+MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost  (ecd@skynet.be)");
+MODULE_DESCRIPTION("OPENPROM Configuration Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+
 /* Private data kept by the driver for each descriptor. */
 typedef struct openprom_private_data
 {
-	int current_node;	/* Current node for SunOS ioctls. */
-	int lastnode;		/* Last valid node used by BSD ioctls. */
+	struct device_node *current_node; /* Current node for SunOS ioctls. */
+	struct device_node *lastnode; /* Last valid node used by BSD ioctls. */
 } DATA;
 
 /* ID of the PROM node containing all of the EEPROM options. */
-static int options_node = 0;
+static struct device_node *options_node;
 
 /*
  * Copy an openpromio structure into kernel space from user space.
@@ -87,9 +90,8 @@
 	if (bufsize > OPROMMAXPARAM)
 		bufsize = OPROMMAXPARAM;
 
-	if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
+	if (!(*opp_p = kzalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
 		return -ENOMEM;
-	memset(*opp_p, 0, sizeof(int) + bufsize + 1);
 
 	if (copy_from_user(&(*opp_p)->oprom_array,
 			   &info->oprom_array, bufsize)) {
@@ -107,10 +109,9 @@
 	if (!info || !opp_p)
 		return -EFAULT;
 
-	if (!(*opp_p = kmalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL)))
+	if (!(*opp_p = kzalloc(sizeof(int) + OPROMMAXPARAM + 1, GFP_KERNEL)))
 		return -ENOMEM;
 
-	memset(*opp_p, 0, sizeof(int) + OPROMMAXPARAM + 1);
 	(*opp_p)->oprom_size = 0;
 
 	n = bufsize = 0;
@@ -140,16 +141,164 @@
 	return 0;
 }
 
+static int opromgetprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize)
+{
+	void *pval;
+	int len;
+
+	pval = of_get_property(dp, op->oprom_array, &len);
+	if (!pval || len <= 0 || len > bufsize)
+		return copyout(argp, op, sizeof(int));
+
+	memcpy(op->oprom_array, pval, len);
+	op->oprom_array[len] = '\0';
+	op->oprom_size = len;
+
+	return copyout(argp, op, sizeof(int) + bufsize);
+}
+
+static int opromnxtprop(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize)
+{
+	struct property *prop;
+	int len;
+
+	if (op->oprom_array[0] == '\0') {
+		prop = dp->properties;
+		if (!prop)
+			return copyout(argp, op, sizeof(int));
+		len = strlen(prop->name);
+	} else {
+		prop = of_find_property(dp, op->oprom_array, NULL);
+
+		if (!prop ||
+		    !prop->next ||
+		    (len = strlen(prop->next->name)) + 1 > bufsize)
+			return copyout(argp, op, sizeof(int));
+
+		prop = prop->next;
+	}
+
+	memcpy(op->oprom_array, prop->name, len);
+	op->oprom_array[len] = '\0';
+	op->oprom_size = ++len;
+
+	return copyout(argp, op, sizeof(int) + bufsize);
+}
+
+static int opromsetopt(struct device_node *dp, struct openpromio *op, int bufsize)
+{
+	char *buf = op->oprom_array + strlen(op->oprom_array) + 1;
+	int len = op->oprom_array + bufsize - buf;
+
+	return of_set_property(options_node, op->oprom_array, buf, len);
+}
+
+static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
+{
+	phandle ph;
+
+	BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
+
+	if (bufsize < sizeof(phandle))
+		return -EINVAL;
+
+	ph = *((int *) op->oprom_array);
+	if (ph) {
+		dp = of_find_node_by_phandle(ph);
+		if (!dp)
+			return -EINVAL;
+
+		switch (cmd) {
+		case OPROMNEXT:
+			dp = dp->sibling;
+			break;
+
+		case OPROMCHILD:
+			dp = dp->child;
+			break;
+
+		case OPROMSETCUR:
+		default:
+			break;
+		};
+	} else {
+		/* Sibling of node zero is the root node.  */
+		if (cmd != OPROMNEXT)
+			return -EINVAL;
+
+		dp = of_find_node_by_path("/");
+	}
+
+	ph = 0;
+	if (dp)
+		ph = dp->node;
+
+	data->current_node = dp;
+	*((int *) op->oprom_array) = ph;
+	op->oprom_size = sizeof(phandle);
+
+	return copyout(argp, op, bufsize + sizeof(int));
+}
+
+static int oprompci2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
+{
+	int err = -EINVAL;
+
+	if (bufsize >= 2*sizeof(int)) {
+#ifdef CONFIG_PCI
+		struct pci_dev *pdev;
+		struct pcidev_cookie *pcp;
+		pdev = pci_find_slot (((int *) op->oprom_array)[0],
+				      ((int *) op->oprom_array)[1]);
+
+		pcp = pdev->sysdata;
+		if (pcp != NULL) {
+			dp = pcp->prom_node;
+			data->current_node = dp;
+			*((int *)op->oprom_array) = dp->node;
+			op->oprom_size = sizeof(int);
+			err = copyout(argp, op, bufsize + sizeof(int));
+		}
+#endif
+	}
+
+	return err;
+}
+
+static int oprompath2node(void __user *argp, struct device_node *dp, struct openpromio *op, int bufsize, DATA *data)
+{
+	dp = of_find_node_by_path(op->oprom_array);
+	data->current_node = dp;
+	*((int *)op->oprom_array) = dp->node;
+	op->oprom_size = sizeof(int);
+
+	return copyout(argp, op, bufsize + sizeof(int));
+}
+
+static int opromgetbootargs(void __user *argp, struct openpromio *op, int bufsize)
+{
+	char *buf = saved_command_line;
+	int len = strlen(buf);
+
+	if (len > bufsize)
+		return -EINVAL;
+
+	strcpy(op->oprom_array, buf);
+	op->oprom_size = len;
+
+	return copyout(argp, op, bufsize + sizeof(int));
+}
+
 /*
  *	SunOS and Solaris /dev/openprom ioctl calls.
  */
 static int openprom_sunos_ioctl(struct inode * inode, struct file * file,
-				unsigned int cmd, unsigned long arg, int node)
+				unsigned int cmd, unsigned long arg,
+				struct device_node *dp)
 {
-	DATA *data = (DATA *) file->private_data;
-	char buffer[OPROMMAXPARAM+1], *buf;
+	DATA *data = file->private_data;
 	struct openpromio *opp;
-	int bufsize, len, error = 0;
+	int bufsize, error = 0;
 	static int cnt;
 	void __user *argp = (void __user *)arg;
 
@@ -164,119 +313,35 @@
 	switch (cmd) {
 	case OPROMGETOPT:
 	case OPROMGETPROP:
-		len = prom_getproplen(node, opp->oprom_array);
-
-		if (len <= 0 || len > bufsize) {
-			error = copyout(argp, opp, sizeof(int));
-			break;
-		}
-
-		len = prom_getproperty(node, opp->oprom_array, buffer, bufsize);
-
-		memcpy(opp->oprom_array, buffer, len);
-		opp->oprom_array[len] = '\0';
-		opp->oprom_size = len;
-
-		error = copyout(argp, opp, sizeof(int) + bufsize);
+		error = opromgetprop(argp, dp, opp, bufsize);
 		break;
 
 	case OPROMNXTOPT:
 	case OPROMNXTPROP:
-		buf = prom_nextprop(node, opp->oprom_array, buffer);
-
-		len = strlen(buf);
-		if (len == 0 || len + 1 > bufsize) {
-			error = copyout(argp, opp, sizeof(int));
-			break;
-		}
-
-		memcpy(opp->oprom_array, buf, len);
-		opp->oprom_array[len] = '\0';
-		opp->oprom_size = ++len;
-
-		error = copyout(argp, opp, sizeof(int) + bufsize);
+		error = opromnxtprop(argp, dp, opp, bufsize);
 		break;
 
 	case OPROMSETOPT:
 	case OPROMSETOPT2:
-		buf = opp->oprom_array + strlen(opp->oprom_array) + 1;
-		len = opp->oprom_array + bufsize - buf;
-
-		error = prom_setprop(options_node, opp->oprom_array,
-				     buf, len);
-
-		if (error < 0)
-			error = -EINVAL;
+		error = opromsetopt(dp, opp, bufsize);
 		break;
 
 	case OPROMNEXT:
 	case OPROMCHILD:
 	case OPROMSETCUR:
-		if (bufsize < sizeof(int)) {
-			error = -EINVAL;
-			break;
-		}
-
-		node = *((int *) opp->oprom_array);
-
-		switch (cmd) {
-		case OPROMNEXT: node = __prom_getsibling(node); break;
-		case OPROMCHILD: node = __prom_getchild(node); break;
-		case OPROMSETCUR: break;
-		}
-
-		data->current_node = node;
-		*((int *)opp->oprom_array) = node;
-		opp->oprom_size = sizeof(int);
-
-		error = copyout(argp, opp, bufsize + sizeof(int));
+		error = opromnext(argp, cmd, dp, opp, bufsize, data);
 		break;
 
 	case OPROMPCI2NODE:
-		error = -EINVAL;
-
-		if (bufsize >= 2*sizeof(int)) {
-#ifdef CONFIG_PCI
-			struct pci_dev *pdev;
-			struct pcidev_cookie *pcp;
-			pdev = pci_find_slot (((int *) opp->oprom_array)[0],
-					      ((int *) opp->oprom_array)[1]);
-
-			pcp = pdev->sysdata;
-			if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) {
-				node = pcp->prom_node;
-				data->current_node = node;
-				*((int *)opp->oprom_array) = node;
-				opp->oprom_size = sizeof(int);
-				error = copyout(argp, opp, bufsize + sizeof(int));
-			}
-#endif
-		}
+		error = oprompci2node(argp, dp, opp, bufsize, data);
 		break;
 
 	case OPROMPATH2NODE:
-		node = prom_finddevice(opp->oprom_array);
-		data->current_node = node;
-		*((int *)opp->oprom_array) = node;
-		opp->oprom_size = sizeof(int);
-
-		error = copyout(argp, opp, bufsize + sizeof(int));
+		error = oprompath2node(argp, dp, opp, bufsize, data);
 		break;
 
 	case OPROMGETBOOTARGS:
-		buf = saved_command_line;
-
-		len = strlen(buf);
-
-		if (len > bufsize) {
-			error = -EINVAL;
-			break;
-		}
-
-		strcpy(opp->oprom_array, buf);
-		opp->oprom_size = len;
-
-		error = copyout(argp, opp, bufsize + sizeof(int));
+		error = opromgetbootargs(argp, opp, bufsize);
 		break;
 
 	case OPROMU2P:
@@ -297,25 +362,14 @@
 	return error;
 }
 
-
-/* Return nonzero if a specific node is in the PROM device tree. */
-static int intree(int root, int node)
+static struct device_node *get_node(phandle n, DATA *data)
 {
-	for (; root != 0; root = prom_getsibling(root))
-		if (root == node || intree(prom_getchild(root),node))
-			return 1;
-	return 0;
-}
+	struct device_node *dp = of_find_node_by_phandle(n);
 
-/* Return nonzero if a specific node is "valid". */
-static int goodnode(int n, DATA *data)
-{
-	if (n == data->lastnode || n == prom_root_node || n == options_node)
-		return 1;
-	if (n == 0 || n == -1 || !intree(prom_root_node,n))
-		return 0;
-	data->lastnode = n;
-	return 1;
+	if (dp)
+		data->lastnode = dp;
+
+	return dp;
 }
 
 /* Copy in a whole string from userspace into kernelspace. */
@@ -330,7 +384,7 @@
 	if (!tmp)
 		return -ENOMEM;
 
-	if(copy_from_user(tmp, user, len)) {
+	if (copy_from_user(tmp, user, len)) {
 		kfree(tmp);
 		return -EFAULT;
 	}
@@ -345,162 +399,187 @@
 /*
  *	NetBSD /dev/openprom ioctl calls.
  */
+static int opiocget(void __user *argp, DATA *data)
+{
+	struct opiocdesc op;
+	struct device_node *dp;
+	char *str;
+	void *pval;
+	int err, len;
+
+	if (copy_from_user(&op, argp, sizeof(op)))
+		return -EFAULT;
+
+	dp = get_node(op.op_nodeid, data);
+
+	err = copyin_string(op.op_name, op.op_namelen, &str);
+	if (err)
+		return err;
+
+	pval = of_get_property(dp, str, &len);
+	err = 0;
+	if (!pval || len > op.op_buflen) {
+		err = -EINVAL;
+	} else {
+		op.op_buflen = len;
+		if (copy_to_user(argp, &op, sizeof(op)) ||
+		    copy_to_user(op.op_buf, pval, len))
+			err = -EFAULT;
+	}
+	kfree(str);
+
+	return err;
+}
+
+static int opiocnextprop(void __user *argp, DATA *data)
+{
+	struct opiocdesc op;
+	struct device_node *dp;
+	struct property *prop;
+	char *str;
+	int err, len;
+
+	if (copy_from_user(&op, argp, sizeof(op)))
+		return -EFAULT;
+
+	dp = get_node(op.op_nodeid, data);
+	if (!dp)
+		return -EINVAL;
+
+	err = copyin_string(op.op_name, op.op_namelen, &str);
+	if (err)
+		return err;
+
+	if (str[0] == '\0') {
+		prop = dp->properties;
+	} else {
+		prop = of_find_property(dp, str, NULL);
+		if (prop)
+			prop = prop->next;
+	}
+	kfree(str);
+
+	if (!prop)
+		len = 0;
+	else
+		len = prop->length;
+
+	if (len > op.op_buflen)
+		len = op.op_buflen;
+
+	if (copy_to_user(argp, &op, sizeof(op)))
+		return -EFAULT;
+
+	if (len &&
+	    copy_to_user(op.op_buf, prop->value, len))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int opiocset(void __user *argp, DATA *data)
+{
+	struct opiocdesc op;
+	struct device_node *dp;
+	char *str, *tmp;
+	int err;
+
+	if (copy_from_user(&op, argp, sizeof(op)))
+		return -EFAULT;
+
+	dp = get_node(op.op_nodeid, data);
+	if (!dp)
+		return -EINVAL;
+
+	err = copyin_string(op.op_name, op.op_namelen, &str);
+	if (err)
+		return err;
+
+	err = copyin_string(op.op_buf, op.op_buflen, &tmp);
+	if (err) {
+		kfree(str);
+		return err;
+	}
+
+	err = of_set_property(dp, str, tmp, op.op_buflen);
+
+	kfree(str);
+	kfree(tmp);
+
+	return err;
+}
+
+static int opiocgetnext(unsigned int cmd, void __user *argp)
+{
+	struct device_node *dp;
+	phandle nd;
+
+	BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
+
+	if (copy_from_user(&nd, argp, sizeof(phandle)))
+		return -EFAULT;
+
+	if (nd == 0) {
+		if (cmd != OPIOCGETNEXT)
+			return -EINVAL;
+		dp = of_find_node_by_path("/");
+	} else {
+		dp = of_find_node_by_phandle(nd);
+		nd = 0;
+		if (dp) {
+			if (cmd == OPIOCGETNEXT)
+				dp = dp->sibling;
+			else
+				dp = dp->child;
+		}
+	}
+	if (dp)
+		nd = dp->node;
+	if (copy_to_user(argp, &nd, sizeof(phandle)))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
 			      unsigned int cmd, unsigned long arg)
 {
 	DATA *data = (DATA *) file->private_data;
 	void __user *argp = (void __user *)arg;
-	struct opiocdesc op;
-	int error, node, len;
-	char *str, *tmp;
-	char buffer[64];
-	static int cnt;
+	int err;
 
 	switch (cmd) {
 	case OPIOCGET:
-		if (copy_from_user(&op, argp, sizeof(op)))
-			return -EFAULT;
-
-		if (!goodnode(op.op_nodeid,data))
-			return -EINVAL;
-
-		error = copyin_string(op.op_name, op.op_namelen, &str);
-		if (error)
-			return error;
-
-		len = prom_getproplen(op.op_nodeid,str);
-
-		if (len > op.op_buflen) {
-			kfree(str);
-			return -ENOMEM;
-		}
-
-		op.op_buflen = len;
-
-		if (len <= 0) {
-			kfree(str);
-			/* Verified by the above copy_from_user */
-			if (__copy_to_user(argp, &op,
-				       sizeof(op)))
-				return -EFAULT;
-			return 0;
-		}
-
-		tmp = kmalloc(len + 1, GFP_KERNEL);
-		if (!tmp) {
-			kfree(str);
-			return -ENOMEM;
-		}
-
-		cnt = prom_getproperty(op.op_nodeid, str, tmp, len);
-		if (cnt <= 0) {
-			error = -EINVAL;
-		} else {
-			tmp[len] = '\0';
-
-			if (__copy_to_user(argp, &op, sizeof(op)) != 0 ||
-			    copy_to_user(op.op_buf, tmp, len) != 0)
-				error = -EFAULT;
-		}
-
-		kfree(tmp);
-		kfree(str);
-
-		return error;
+		err = opiocget(argp, data);
+		break;
 
 	case OPIOCNEXTPROP:
-		if (copy_from_user(&op, argp, sizeof(op)))
-			return -EFAULT;
-
-		if (!goodnode(op.op_nodeid,data))
-			return -EINVAL;
-
-		error = copyin_string(op.op_name, op.op_namelen, &str);
-		if (error)
-			return error;
-
-		tmp = prom_nextprop(op.op_nodeid,str,buffer);
-
-		if (tmp) {
-			len = strlen(tmp);
-			if (len > op.op_buflen)
-				len = op.op_buflen;
-			else
-				op.op_buflen = len;
-		} else {
-			len = op.op_buflen = 0;
-		}
-
-		if (!access_ok(VERIFY_WRITE, argp, sizeof(op))) {
-			kfree(str);
-			return -EFAULT;
-		}
-
-		if (!access_ok(VERIFY_WRITE, op.op_buf, len)) {
-			kfree(str);
-			return -EFAULT;
-		}
-
-		error = __copy_to_user(argp, &op, sizeof(op));
-		if (!error) error = __copy_to_user(op.op_buf, tmp, len);
-
-		kfree(str);
-
-		return error;
+		err = opiocnextprop(argp, data);
+		break;
 
 	case OPIOCSET:
-		if (copy_from_user(&op, argp, sizeof(op)))
-			return -EFAULT;
-
-		if (!goodnode(op.op_nodeid,data))
-			return -EINVAL;
-
-		error = copyin_string(op.op_name, op.op_namelen, &str);
-		if (error)
-			return error;
-
-		error = copyin_string(op.op_buf, op.op_buflen, &tmp);
-		if (error) {
-			kfree(str);
-			return error;
-		}
-
-		len = prom_setprop(op.op_nodeid,str,tmp,op.op_buflen+1);
-
-		if (len != op.op_buflen)
-			return -EINVAL;
-
-		kfree(str);
-		kfree(tmp);
-
-		return 0;
+		err = opiocset(argp, data);
+		break;
 
 	case OPIOCGETOPTNODE:
-		if (copy_to_user(argp, &options_node, sizeof(int)))
+		BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
+
+		if (copy_to_user(argp, &options_node->node, sizeof(phandle)))
 			return -EFAULT;
+
 		return 0;
 
 	case OPIOCGETNEXT:
 	case OPIOCGETCHILD:
-		if (copy_from_user(&node, argp, sizeof(int)))
-			return -EFAULT;
-
-		if (cmd == OPIOCGETNEXT)
-			node = __prom_getsibling(node);
-		else
-			node = __prom_getchild(node);
-
-		if (__copy_to_user(argp, &node, sizeof(int)))
-			return -EFAULT;
-
-		return 0;
+		err = opiocgetnext(cmd, argp);
+		break;
 
 	default:
-		if (cnt++ < 10)
-			printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd);
 		return -EINVAL;
 
-	}
+	};
+
+	return err;
 }
 
 
@@ -511,7 +590,6 @@
 			  unsigned int cmd, unsigned long arg)
 {
 	DATA *data = (DATA *) file->private_data;
-	static int cnt;
 
 	switch (cmd) {
 	case OPROMGETOPT:
@@ -563,10 +641,8 @@
 		return openprom_bsd_ioctl(inode,file,cmd,arg);
 
 	default:
-		if (cnt++ < 10)
-			printk("openprom_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg);
 		return -EINVAL;
-	}
+	};
 }
 
 static long openprom_compat_ioctl(struct file *file, unsigned int cmd,
@@ -594,9 +670,7 @@
 	case OPROMSETCUR:
 	case OPROMPCI2NODE:
 	case OPROMPATH2NODE:
-		lock_kernel();
 		rval = openprom_ioctl(file->f_dentry->d_inode, file, cmd, arg);
-		lock_kernel();
 		break;
 	}
 
@@ -607,13 +681,13 @@
 {
 	DATA *data;
 
-	data = (DATA *) kmalloc(sizeof(DATA), GFP_KERNEL);
+	data = kmalloc(sizeof(DATA), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	data->current_node = prom_root_node;
-	data->lastnode = prom_root_node;
-	file->private_data = (void *)data;
+	data->current_node = of_find_node_by_path("/");
+	data->lastnode = data->current_node;
+	file->private_data = (void *) data;
 
 	return 0;
 }
@@ -634,24 +708,30 @@
 };
 
 static struct miscdevice openprom_dev = {
-	SUN_OPENPROM_MINOR, "openprom", &openprom_fops
+	.minor		= SUN_OPENPROM_MINOR,
+	.name		= "openprom",
+	.fops		= &openprom_fops,
 };
 
 static int __init openprom_init(void)
 {
-	int error;
+	struct device_node *dp;
+	int err;
 
-	error = misc_register(&openprom_dev);
-	if (error) {
-		printk(KERN_ERR "openprom: unable to get misc minor\n");
-		return error;
+	err = misc_register(&openprom_dev);
+	if (err)
+		return err;
+
+	dp = of_find_node_by_path("/");
+	dp = dp->child;
+	while (dp) {
+		if (!strcmp(dp->name, "options"))
+			break;
+		dp = dp->sibling;
 	}
+	options_node = dp;
 
-	options_node = prom_getchild(prom_root_node);
-	options_node = prom_searchsiblings(options_node,"options");
-
-	if (options_node == 0 || options_node == -1) {
-		printk(KERN_ERR "openprom: unable to find options node\n");
+	if (!options_node) {
 		misc_deregister(&openprom_dev);
 		return -EIO;
 	}
@@ -666,4 +746,3 @@
 
 module_init(openprom_init);
 module_exit(openprom_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/sbus/char/riowatchdog.c
index d1babff..2a9cc82 100644
--- a/drivers/sbus/char/riowatchdog.c
+++ b/drivers/sbus/char/riowatchdog.c
@@ -211,7 +211,7 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "bbc"))
+			if (!strcmp(edev->ofdev.node->name, "bbc"))
 				goto found_bbc;
 		}
 	}
@@ -238,7 +238,7 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, RIOWD_NAME))
+			if (!strcmp(edev->ofdev.node->name, RIOWD_NAME))
 				goto ebus_done;
 		}
 	}
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index e2d9a7c..575b1f7 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -400,7 +400,7 @@
 	}
 
 	driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK;
-	printk("uctrl: 0x%x (irq %s)\n", driver->regs, __irq_itoa(driver->irq));
+	printk("uctrl: 0x%x (irq %d)\n", driver->regs, driver->irq);
 	uctrl_get_event_status();
 	uctrl_get_external_status();
         return 0;
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index dfdd6be..ddcd330 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -623,7 +623,7 @@
 		map_size = sizeof(struct vfc_regs);
 
 	vma->vm_flags |=
-		(VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
+		(VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
 	map_offset = (unsigned int) (long)dev->phys_regs;
 	ret = io_remap_pfn_range(vma, vma->vm_start,
 				  MK_IOSPACE_PFN(dev->which_io,
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c
index 5d30a3e..387a6aa 100644
--- a/drivers/sbus/sbus.c
+++ b/drivers/sbus/sbus.c
@@ -1,7 +1,6 @@
-/* $Id: sbus.c,v 1.100 2002/01/24 15:36:24 davem Exp $
- * sbus.c:  SBus support routines.
+/* sbus.c: SBus support routines.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/kernel.h>
@@ -14,237 +13,76 @@
 #include <asm/sbus.h>
 #include <asm/dma.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
 #include <asm/bpp.h>
 #include <asm/irq.h>
 
-struct sbus_bus *sbus_root = NULL;
+struct sbus_bus *sbus_root;
 
-static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } };
-#ifdef CONFIG_SPARC32
-static int interrupts[PROMINTR_MAX] __initdata = { 0 };
-#endif
-
-#ifdef CONFIG_PCI
-extern int pcic_present(void);
-#endif
-
-/* Perhaps when I figure out more about the iommu we'll put a
- * device registration routine here that probe_sbus() calls to
- * setup the iommu for each Sbus.
- */
-
-/* We call this for each SBus device, and fill the structure based
- * upon the prom device tree.  We return the start of memory after
- * the things we have allocated.
- */
-
-/* #define DEBUG_FILL */
-
-static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
+static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev)
 {
-	unsigned long address, base;
+	unsigned long base;
+	void *pval;
 	int len;
 
-	sdev->prom_node = prom_node;
-	prom_getstring(prom_node, "name",
-		       sdev->prom_name, sizeof(sdev->prom_name));
-	address = prom_getint(prom_node, "address");
-	len = prom_getproperty(prom_node, "reg",
-			       (char *) sdev->reg_addrs,
-			       sizeof(sdev->reg_addrs));
-	if (len == -1) {
-		sdev->num_registers = 0;
-		goto no_regs;
+	sdev->prom_node = dp->node;
+	strcpy(sdev->prom_name, dp->name);
+
+	pval = of_get_property(dp, "reg", &len);
+	sdev->num_registers = 0;
+	if (pval) {
+		memcpy(sdev->reg_addrs, pval, len);
+
+		sdev->num_registers =
+			len / sizeof(struct linux_prom_registers);
+
+		base = (unsigned long) sdev->reg_addrs[0].phys_addr;
+
+		/* Compute the slot number. */
+		if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m)
+			sdev->slot = sbus_dev_slot(base);
+		else
+			sdev->slot = sdev->reg_addrs[0].which_io;
 	}
 
-	if (len % sizeof(struct linux_prom_registers)) {
-		prom_printf("fill_sbus_device: proplen for regs of %s "
-			    " was %d, need multiple of %d\n",
-			    sdev->prom_name, len,
-			    (int) sizeof(struct linux_prom_registers));
-		prom_halt();
-	}
-	if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
-		prom_printf("fill_sbus_device: Too many register properties "
-			    "for device %s, len=%d\n",
-			    sdev->prom_name, len);
-		prom_halt();
-	}
-	sdev->num_registers = len / sizeof(struct linux_prom_registers);
-	sdev->ranges_applied = 0;
-
-	base = (unsigned long) sdev->reg_addrs[0].phys_addr;
-
-	/* Compute the slot number. */
-	if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
-		sdev->slot = sbus_dev_slot(base);
-	} else {
-		sdev->slot = sdev->reg_addrs[0].which_io;
+	pval = of_get_property(dp, "ranges", &len);
+	sdev->num_device_ranges = 0;
+	if (pval) {
+		memcpy(sdev->device_ranges, pval, len);
+		sdev->num_device_ranges =
+			len / sizeof(struct linux_prom_ranges);
 	}
 
-no_regs:
-	len = prom_getproperty(prom_node, "ranges",
-			       (char *)sdev->device_ranges,
-			       sizeof(sdev->device_ranges));
-	if (len == -1) {
-		sdev->num_device_ranges = 0;
-		goto no_ranges;
-	}
-	if (len % sizeof(struct linux_prom_ranges)) {
-		prom_printf("fill_sbus_device: proplen for ranges of %s "
-			    " was %d, need multiple of %d\n",
-			    sdev->prom_name, len,
-			    (int) sizeof(struct linux_prom_ranges));
-		prom_halt();
-	}
-	if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
-		prom_printf("fill_sbus_device: Too many range properties "
-			    "for device %s, len=%d\n",
-			    sdev->prom_name, len);
-		prom_halt();
-	}
-	sdev->num_device_ranges =
-		len / sizeof(struct linux_prom_ranges);
+	sbus_fill_device_irq(sdev);
 
-no_ranges:
-	/* XXX Unfortunately, IRQ issues are very arch specific.
-	 * XXX Pull this crud out into an arch specific area
-	 * XXX at some point. -DaveM
-	 */
-#ifdef CONFIG_SPARC64
-	len = prom_getproperty(prom_node, "interrupts",
-			       (char *) irqs, sizeof(irqs));
-	if (len == -1 || len == 0) {
-		sdev->irqs[0] = 0;
-		sdev->num_irqs = 0;
-	} else {
-		unsigned int pri = irqs[0].pri;
+	sdev->ofdev.node = dp;
+	if (sdev->parent)
+		sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev;
+	else
+		sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev;
+	sdev->ofdev.dev.bus = &sbus_bus_type;
+	strcpy(sdev->ofdev.dev.bus_id, dp->path_component_name);
 
-		sdev->num_irqs = 1;
-		if (pri < 0x20)
-			pri += sdev->slot * 8;
-
-		sdev->irqs[0] =	sbus_build_irq(sdev->bus, pri);
-	}
-#endif /* CONFIG_SPARC64 */
-
-#ifdef CONFIG_SPARC32
-	len = prom_getproperty(prom_node, "intr",
-			       (char *)irqs, sizeof(irqs));
-	if (len != -1) {
-		sdev->num_irqs = len / 8;
-		if (sdev->num_irqs == 0) {
-			sdev->irqs[0] = 0;
-		} else if (sparc_cpu_model == sun4d) {
-			extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
-
-			for (len = 0; len < sdev->num_irqs; len++)
-				sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
-		} else {
-			for (len = 0; len < sdev->num_irqs; len++)
-				sdev->irqs[len] = irqs[len].pri;
-		}
-	} else {
-		/* No "intr" node found-- check for "interrupts" node.
-		 * This node contains SBus interrupt levels, not IPLs
-		 * as in "intr", and no vector values.  We convert 
-		 * SBus interrupt levels to PILs (platform specific).
-		 */
-		len = prom_getproperty(prom_node, "interrupts", 
-					(char *)interrupts, sizeof(interrupts));
-		if (len == -1) {
-			sdev->irqs[0] = 0;
-			sdev->num_irqs = 0;
-		} else {
-			sdev->num_irqs = len / sizeof(int);
-			for (len = 0; len < sdev->num_irqs; len++) {
-				sdev->irqs[len] = sbint_to_irq(sdev, interrupts[len]);
-			}
-		}
-	} 
-#endif /* CONFIG_SPARC32 */
+	if (of_device_register(&sdev->ofdev) != 0)
+		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
+		       sdev->ofdev.dev.bus_id);
 }
 
-/* This routine gets called from whoever needs the sbus first, to scan
- * the SBus device tree.  Currently it just prints out the devices
- * found on the bus and builds trees of SBUS structs and attached
- * devices.
- */
-
-extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
-extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus);
-void sun4_init(void);
-#ifdef CONFIG_SUN_AUXIO
-extern void auxio_probe(void);
-#endif
-
-static void __init sbus_do_child_siblings(int start_node,
-					  struct sbus_dev *child,
-					  struct sbus_dev *parent,
-					  struct sbus_bus *sbus)
+static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus)
 {
-	struct sbus_dev *this_dev = child;
-	int this_node = start_node;
-
-	/* Child already filled in, just need to traverse siblings. */
-	child->child = NULL;
-	child->parent = parent;
-	while((this_node = prom_getsibling(this_node)) != 0) {
-		this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
-		this_dev = this_dev->next;
-		this_dev->next = NULL;
-		this_dev->parent = parent;
-
-		this_dev->bus = sbus;
-		fill_sbus_device(this_node, this_dev);
-
-		if(prom_getchild(this_node)) {
-			this_dev->child = kmalloc(sizeof(struct sbus_dev),
-						  GFP_ATOMIC);
-			this_dev->child->bus = sbus;
-			this_dev->child->next = NULL;
-			fill_sbus_device(prom_getchild(this_node), this_dev->child);
-			sbus_do_child_siblings(prom_getchild(this_node),
-					       this_dev->child, this_dev, sbus);
-		} else {
-			this_dev->child = NULL;
-		}
-	}
-}
-
-/*
- * XXX This functions appears to be a distorted version of
- * prom_sbus_ranges_init(), with all sun4d stuff cut away.
- * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
- */
-/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
-
-static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus)
-{
+	void *pval;
 	int len;
 
-	len = prom_getproperty(sbus->prom_node, "ranges",
-			       (char *) sbus->sbus_ranges,
-			       sizeof(sbus->sbus_ranges));
-	if (len == -1 || len == 0) {
-		sbus->num_sbus_ranges = 0;
-		return;
-	}
-	sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges);
-#ifdef CONFIG_SPARC32
-	if (sparc_cpu_model == sun4d) {
-		struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
-		int num_iounit_ranges;
+	pval = of_get_property(dp, "ranges", &len);
+	sbus->num_sbus_ranges = 0;
+	if (pval) {
+		memcpy(sbus->sbus_ranges, pval, len);
+		sbus->num_sbus_ranges =
+			len / sizeof(struct linux_prom_ranges);
 
-		len = prom_getproperty(parent_node, "ranges",
-				       (char *) iounit_ranges,
-				       sizeof (iounit_ranges));
-		if (len != -1) {
-			num_iounit_ranges = (len/sizeof(struct linux_prom_ranges));
-			prom_adjust_ranges (sbus->sbus_ranges, sbus->num_sbus_ranges, iounit_ranges, num_iounit_ranges);
-		}
+		sbus_arch_bus_ranges_init(dp->parent, sbus);
 	}
-#endif
 }
 
 static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
@@ -322,241 +160,127 @@
 	}
 }
 
-extern void register_proc_sparc_ioport(void);
-extern void firetruck_init(void);
+/* We preserve the "probe order" of these bus and device lists to give
+ * the same ordering as the old code.
+ */
+static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root)
+{
+	while (*root)
+		root = &(*root)->next;
+	*root = sbus;
+	sbus->next = NULL;
+}
 
-#ifdef CONFIG_SUN4
-extern void sun4_dvma_init(void);
-#endif
+static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root)
+{
+	while (*root)
+		root = &(*root)->next;
+	*root = sdev;
+	sdev->next = NULL;
+}
+
+static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus)
+{
+	dp = dp->child;
+	while (dp) {
+		struct sbus_dev *sdev;
+
+		sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
+		if (sdev) {
+			sdev_insert(sdev, &parent->child);
+
+			sdev->bus = sbus;
+			sdev->parent = parent;
+
+			fill_sbus_device(dp, sdev);
+
+			walk_children(dp, sdev, sbus);
+		}
+		dp = dp->sibling;
+	}
+}
+
+static void __init build_one_sbus(struct device_node *dp, int num_sbus)
+{
+	struct sbus_bus *sbus;
+	unsigned int sbus_clock;
+	struct device_node *dev_dp;
+
+	sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
+	if (!sbus)
+		return;
+
+	sbus_insert(sbus, &sbus_root);
+	sbus->prom_node = dp->node;
+
+	sbus_setup_iommu(sbus, dp);
+
+	printk("sbus%d: ", num_sbus);
+
+	sbus_clock = of_getintprop_default(dp, "clock-frequency",
+					   (25*1000*1000));
+	sbus->clock_freq = sbus_clock;
+
+	printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
+	       (int) (((sbus_clock/1000)%1000 != 0) ? 
+		      (((sbus_clock/1000)%1000) + 1000) : 0));
+
+	strcpy(sbus->prom_name, dp->name);
+
+	sbus_setup_arch_props(sbus, dp);
+
+	sbus_bus_ranges_init(dp, sbus);
+
+	sbus->ofdev.node = dp;
+	sbus->ofdev.dev.parent = NULL;
+	sbus->ofdev.dev.bus = &sbus_bus_type;
+	strcpy(sbus->ofdev.dev.bus_id, dp->path_component_name);
+
+	if (of_device_register(&sbus->ofdev) != 0)
+		printk(KERN_DEBUG "sbus: device registration error for %s!\n",
+		       sbus->ofdev.dev.bus_id);
+
+	dev_dp = dp->child;
+	while (dev_dp) {
+		struct sbus_dev *sdev;
+
+		sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
+		if (sdev) {
+			sdev_insert(sdev, &sbus->devices);
+
+			sdev->bus = sbus;
+			sdev->parent = NULL;
+			fill_sbus_device(dev_dp, sdev);
+
+			walk_children(dev_dp, sdev, sbus);
+		}
+		dev_dp = dev_dp->sibling;
+	}
+
+	sbus_fixup_all_regs(sbus->devices);
+
+	dvma_init(sbus);
+}
 
 static int __init sbus_init(void)
 {
-	int nd, this_sbus, sbus_devs, topnd, iommund;
-	unsigned int sbus_clock;
-	struct sbus_bus *sbus;
-	struct sbus_dev *this_dev;
-	int num_sbus = 0;  /* How many did we find? */
+	struct device_node *dp;
+	const char *sbus_name = "sbus";
+	int num_sbus = 0;
 
-#ifdef CONFIG_SPARC32
-	register_proc_sparc_ioport();
-#endif
+	if (sbus_arch_preinit())
+		return 0;
 
-#ifdef CONFIG_SUN4
-	sun4_dvma_init();
-	return 0;
-#endif
+	if (sparc_cpu_model == sun4d)
+		sbus_name = "sbi";
 
-	topnd = prom_getchild(prom_root_node);
-	
-	/* Finding the first sbus is a special case... */
-	iommund = 0;
-	if(sparc_cpu_model == sun4u) {
-		nd = prom_searchsiblings(topnd, "sbus");
-		if(nd == 0) {
-#ifdef CONFIG_PCI
-			if (!pcic_present()) {
-				prom_printf("Neither SBUS nor PCI found.\n");
-				prom_halt();
-			} else {
-#ifdef CONFIG_SPARC64
-				firetruck_init();
-#endif
-			}
-			return 0;
-#else
-			prom_printf("YEEE, UltraSparc sbus not found\n");
-			prom_halt();
-#endif
-		}
-	} else if(sparc_cpu_model == sun4d) {
-		if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 ||
-		   (nd = prom_getchild(iommund)) == 0 ||
-		   (nd = prom_searchsiblings(nd, "sbi")) == 0) {
-		   	panic("sbi not found");
-		}
-	} else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) {
-		if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 ||
-		   (nd = prom_getchild(iommund)) == 0 ||
-		   (nd = prom_searchsiblings(nd, "sbus")) == 0) {
-#ifdef CONFIG_PCI
-                        if (!pcic_present()) {
-                                prom_printf("Neither SBUS nor PCI found.\n");
-                                prom_halt();
-                        }
-                        return 0;
-#else
-			/* No reason to run further - the data access trap will occur. */
-			panic("sbus not found");
-#endif
-		}
-	}
-
-	/* Ok, we've found the first one, allocate first SBus struct
-	 * and place in chain.
-	 */
-	sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
-	sbus->next = NULL;
-	sbus->prom_node = nd;
-	this_sbus = nd;
-
-	if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
-		iommu_init(iommund, sbus);
-
-	/* Loop until we find no more SBUS's */
-	while(this_sbus) {
-#ifdef CONFIG_SPARC64
-		/* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
-		if(sparc_cpu_model == sun4u) {
-			extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus);
-
-			sbus_iommu_init(this_sbus, sbus);
-		}
-#endif /* CONFIG_SPARC64 */
-
-#ifdef CONFIG_SPARC32
-		if (sparc_cpu_model == sun4d)
-			iounit_init(this_sbus, iommund, sbus);
-#endif /* CONFIG_SPARC32 */
-		printk("sbus%d: ", num_sbus);
-		sbus_clock = prom_getint(this_sbus, "clock-frequency");
-		if(sbus_clock == -1)
-			sbus_clock = (25*1000*1000);
-		printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000),
-		       (int) (((sbus_clock/1000)%1000 != 0) ? 
-			      (((sbus_clock/1000)%1000) + 1000) : 0));
-
-		prom_getstring(this_sbus, "name",
-			       sbus->prom_name, sizeof(sbus->prom_name));
-		sbus->clock_freq = sbus_clock;
-#ifdef CONFIG_SPARC32
-		if (sparc_cpu_model == sun4d) {
-			sbus->devid = prom_getint(iommund, "device-id");
-			sbus->board = prom_getint(iommund, "board#");
-		}
-#endif
-		
-		sbus_bus_ranges_init(iommund, sbus);
-
-		sbus_devs = prom_getchild(this_sbus);
-		if (!sbus_devs) {
-			sbus->devices = NULL;
-			goto next_bus;
-		}
-
-		sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
-
-		this_dev = sbus->devices;
-		this_dev->next = NULL;
-
-		this_dev->bus = sbus;
-		this_dev->parent = NULL;
-		fill_sbus_device(sbus_devs, this_dev);
-
-		/* Should we traverse for children? */
-		if(prom_getchild(sbus_devs)) {
-			/* Allocate device node */
-			this_dev->child = kmalloc(sizeof(struct sbus_dev),
-						  GFP_ATOMIC);
-			/* Fill it */
-			this_dev->child->bus = sbus;
-			this_dev->child->next = NULL;
-			fill_sbus_device(prom_getchild(sbus_devs),
-					 this_dev->child);
-			sbus_do_child_siblings(prom_getchild(sbus_devs),
-					       this_dev->child,
-					       this_dev,
-					       sbus);
-		} else {
-			this_dev->child = NULL;
-		}
-
-		while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
-			/* Allocate device node */
-			this_dev->next = kmalloc(sizeof(struct sbus_dev),
-						 GFP_ATOMIC);
-			this_dev = this_dev->next;
-			this_dev->next = NULL;
-
-			/* Fill it */
-			this_dev->bus = sbus;
-			this_dev->parent = NULL;
-			fill_sbus_device(sbus_devs, this_dev);
-
-			/* Is there a child node hanging off of us? */
-			if(prom_getchild(sbus_devs)) {
-				/* Get new device struct */
-				this_dev->child = kmalloc(sizeof(struct sbus_dev),
-							  GFP_ATOMIC);
-				/* Fill it */
-				this_dev->child->bus = sbus;
-				this_dev->child->next = NULL;
-				fill_sbus_device(prom_getchild(sbus_devs),
-						 this_dev->child);
-				sbus_do_child_siblings(prom_getchild(sbus_devs),
-						       this_dev->child,
-						       this_dev,
-						       sbus);
-			} else {
-				this_dev->child = NULL;
-			}
-		}
-
-		/* Walk all devices and apply parent ranges. */
-		sbus_fixup_all_regs(sbus->devices);
-
-		dvma_init(sbus);
-	next_bus:
+	for_each_node_by_name(dp, sbus_name) {
+		build_one_sbus(dp, num_sbus);
 		num_sbus++;
-		if(sparc_cpu_model == sun4u) {
-			this_sbus = prom_getsibling(this_sbus);
-			if(!this_sbus)
-				break;
-			this_sbus = prom_searchsiblings(this_sbus, "sbus");
-		} else if(sparc_cpu_model == sun4d) {
-			iommund = prom_getsibling(iommund);
-			if(!iommund)
-				break;
-			iommund = prom_searchsiblings(iommund, "io-unit");
-			if(!iommund)
-				break;
-			this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
-		} else {
-			this_sbus = prom_getsibling(this_sbus);
-			if(!this_sbus)
-				break;
-			this_sbus = prom_searchsiblings(this_sbus, "sbus");
-		}
-		if(this_sbus) {
-			sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
-			sbus = sbus->next;
-			sbus->next = NULL;
-			sbus->prom_node = this_sbus;
-		} else {
-			break;
-		}
-	} /* while(this_sbus) */
 
-	if (sparc_cpu_model == sun4d) {
-		extern void sun4d_init_sbi_irq(void);
-		sun4d_init_sbi_irq();
 	}
-	
-#ifdef CONFIG_SPARC64
-	if (sparc_cpu_model == sun4u) {
-		firetruck_init();
-	}
-#endif
-#ifdef CONFIG_SUN_AUXIO
-	if (sparc_cpu_model == sun4u)
-		auxio_probe ();
-#endif
-#ifdef CONFIG_SPARC64
-	if (sparc_cpu_model == sun4u) {
-		extern void clock_probe(void);
 
-		clock_probe();
-	}
-#endif
+	sbus_arch_postinit();
 
 	return 0;
 }
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index caeb6d2..b003baf 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1388,7 +1388,7 @@
 	if (cmd->use_sg == 0)
 		goto out;
 
-	use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
+	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
 
 	if (use_sg == 0) {
 		TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index e8e41e6..17dbd4a 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -405,7 +405,7 @@
 	/* Attempt to return intelligent sense information */
 	if (fill_sense) {
 		if ((command->status == 0xc7) || (command->status == 0xcb)) {
-			for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) {
+			for (i = 0; i < ARRAY_SIZE(tw_sense_table); i++) {
 				if (command->flags == tw_sense_table[i][0]) {
 
 					/* Valid bit and 'current errors' */
@@ -625,7 +625,7 @@
 	if (aen == 0x0ff) {
 		printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no);
 	} else {
-		table_max = sizeof(tw_aen_string)/sizeof(char *);
+		table_max = ARRAY_SIZE(tw_aen_string);
 		if ((aen & 0x0ff) < table_max) {
 			if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
 				printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
@@ -786,7 +786,7 @@
 					if (aen == 0x0ff) {
 						printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n");
 					} else {
-						table_max = sizeof(tw_aen_string)/sizeof(char *);
+						table_max = ARRAY_SIZE(tw_aen_string);
 						if ((aen & 0x0ff) < table_max) {
 							if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
 								printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);
@@ -1286,7 +1286,7 @@
 	if (cmd->use_sg == 0)
 		return 0;
 
-	use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
+	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
 	
 	if (use_sg == 0) {
 		printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 6a0f950..3c683dc 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -183,6 +183,10 @@
 
 STATIC struct scsi_transport_template *NCR_700_transport_template = NULL;
 
+struct NCR_700_sense {
+	unsigned char cmnd[MAX_COMMAND_SIZE];
+};
+
 static char *NCR_700_phase[] = {
 	"",
 	"after selection",
@@ -316,7 +320,7 @@
 	BUG_ON(!dma_is_consistent(pScript) && L1_CACHE_BYTES < dma_get_cache_alignment());
 	hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET);
 	hostdata->dev = dev;
-		
+
 	pSlots = pScript + SLOTS_OFFSET;
 
 	/* Fill in the missing routines from the host template */
@@ -332,19 +336,18 @@
 	tpnt->slave_destroy = NCR_700_slave_destroy;
 	tpnt->change_queue_depth = NCR_700_change_queue_depth;
 	tpnt->change_queue_type = NCR_700_change_queue_type;
-	
+
 	if(tpnt->name == NULL)
 		tpnt->name = "53c700";
 	if(tpnt->proc_name == NULL)
 		tpnt->proc_name = "53c700";
-	
 
 	host = scsi_host_alloc(tpnt, 4);
 	if (!host)
 		return NULL;
 	memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot)
 	       * NCR_700_COMMAND_SLOTS_PER_HOST);
-	for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) {
+	for (j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) {
 		dma_addr_t offset = (dma_addr_t)((unsigned long)&hostdata->slots[j].SG[0]
 					  - (unsigned long)&hostdata->slots[0].SG[0]);
 		hostdata->slots[j].pSG = (struct NCR_700_SG_List *)((unsigned long)(pSlots + offset));
@@ -355,14 +358,12 @@
 		hostdata->slots[j].state = NCR_700_SLOT_FREE;
 	}
 
-	for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) {
+	for (j = 0; j < ARRAY_SIZE(SCRIPT); j++)
 		script[j] = bS_to_host(SCRIPT[j]);
-	}
 
 	/* adjust all labels to be bus physical */
-	for(j = 0; j < PATCHES; j++) {
+	for (j = 0; j < PATCHES; j++)
 		script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]);
-	}
 	/* now patch up fixed addresses. */
 	script_patch_32(script, MessageLocation,
 			pScript + MSGOUT_OFFSET);
@@ -376,7 +377,7 @@
 	dma_sync_single_for_device(hostdata->dev, pScript, sizeof(SCRIPT), DMA_TO_DEVICE);
 	hostdata->state = NCR_700_HOST_FREE;
 	hostdata->cmd = NULL;
-	host->max_id = 7;
+	host->max_id = 8;
 	host->max_lun = NCR_700_MAX_LUNS;
 	BUG_ON(NCR_700_transport_template == NULL);
 	host->transportt = NCR_700_transport_template;
@@ -385,17 +386,17 @@
 	host->hostdata[0] = (unsigned long)hostdata;
 	/* kick the chip */
 	NCR_700_writeb(0xff, host, CTEST9_REG);
-	if(hostdata->chip710) 
+	if (hostdata->chip710)
 		hostdata->rev = (NCR_700_readb(host, CTEST8_REG)>>4) & 0x0f;
 	else
 		hostdata->rev = (NCR_700_readb(host, CTEST7_REG)>>4) & 0x0f;
 	hostdata->fast = (NCR_700_readb(host, CTEST9_REG) == 0);
-	if(banner == 0) {
+	if (banner == 0) {
 		printk(KERN_NOTICE "53c700: Version " NCR_700_VERSION " By James.Bottomley@HansenPartnership.com\n");
 		banner = 1;
 	}
 	printk(KERN_NOTICE "scsi%d: %s rev %d %s\n", host->host_no,
-	       hostdata->chip710 ? "53c710" : 
+	       hostdata->chip710 ? "53c710" :
 	       (hostdata->fast ? "53c700-66" : "53c700"),
 	       hostdata->rev, hostdata->differential ?
 	       "(Differential)" : "");
@@ -540,6 +541,7 @@
 	 * finish routine.  If we cannot queue the command when it
 	 * is properly build, we then change to NCR_700_SLOT_QUEUED */
 	slot->state = NCR_700_SLOT_BUSY;
+	slot->flags = 0;
 	hostdata->command_slot_count++;
 	
 	return slot;
@@ -589,7 +591,7 @@
 	if(SCp->sc_data_direction != DMA_NONE &&
 	   SCp->sc_data_direction != DMA_BIDIRECTIONAL) {
 		if(SCp->use_sg) {
-			dma_unmap_sg(hostdata->dev, SCp->buffer,
+			dma_unmap_sg(hostdata->dev, SCp->request_buffer,
 				     SCp->use_sg, SCp->sc_data_direction);
 		} else {
 			dma_unmap_single(hostdata->dev, slot->dma_handle,
@@ -611,30 +613,23 @@
 			(struct NCR_700_command_slot *)SCp->host_scribble;
 		
 		NCR_700_unmap(hostdata, SCp, slot);
-		dma_unmap_single(hostdata->dev, slot->pCmd,
-				 sizeof(SCp->cmnd), DMA_TO_DEVICE);
-		if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) {
+		if (slot->flags == NCR_700_FLAG_AUTOSENSE) {
+			struct NCR_700_sense *sense = SCp->device->hostdata;
 #ifdef NCR_700_DEBUG
 			printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n",
 			       SCp, SCp->cmnd[7], result);
 			scsi_print_sense("53c700", SCp);
 
 #endif
+			dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
 			/* restore the old result if the request sense was
 			 * successful */
 			if(result == 0)
-				result = SCp->cmnd[7];
-			/* now restore the original command */
-			memcpy((void *) SCp->cmnd, (void *) SCp->data_cmnd,
-			       sizeof(SCp->data_cmnd));
-			SCp->request_buffer = SCp->buffer;
-			SCp->request_bufflen = SCp->bufflen;
-			SCp->use_sg = SCp->old_use_sg;
-			SCp->cmd_len = SCp->old_cmd_len;
-			SCp->sc_data_direction = SCp->sc_old_data_direction;
-			SCp->underflow = SCp->old_underflow;
-			
-		}
+				result = sense->cmnd[7];
+		} else
+			dma_unmap_single(hostdata->dev, slot->pCmd,
+					 sizeof(SCp->cmnd), DMA_TO_DEVICE);
+
 		free_slot(slot, hostdata);
 #ifdef NCR_700_DEBUG
 		if(NCR_700_get_depth(SCp->device) == 0 ||
@@ -982,6 +977,7 @@
 					"broken device is looping in contingent allegiance: ignoring\n");
 				NCR_700_scsi_done(hostdata, SCp, hostdata->status[0]);
 			} else {
+				struct NCR_700_sense *sense = SCp->device->hostdata;
 #ifdef NCR_DEBUG
 				scsi_print_command(SCp);
 				printk("  cmd %p has status %d, requesting sense\n",
@@ -995,27 +991,25 @@
 				 * data associated with the command
 				 * here */
 				NCR_700_unmap(hostdata, SCp, slot);
+				dma_unmap_single(hostdata->dev, slot->pCmd,
+						 sizeof(SCp->cmnd),
+						 DMA_TO_DEVICE);
 
-				SCp->cmnd[0] = REQUEST_SENSE;
-				SCp->cmnd[1] = (SCp->device->lun & 0x7) << 5;
-				SCp->cmnd[2] = 0;
-				SCp->cmnd[3] = 0;
-				SCp->cmnd[4] = sizeof(SCp->sense_buffer);
-				SCp->cmnd[5] = 0;
-				SCp->cmd_len = 6;
+				sense->cmnd[0] = REQUEST_SENSE;
+				sense->cmnd[1] = (SCp->device->lun & 0x7) << 5;
+				sense->cmnd[2] = 0;
+				sense->cmnd[3] = 0;
+				sense->cmnd[4] = sizeof(SCp->sense_buffer);
+				sense->cmnd[5] = 0;
 				/* Here's a quiet hack: the
 				 * REQUEST_SENSE command is six bytes,
 				 * so store a flag indicating that
 				 * this was an internal sense request
 				 * and the original status at the end
 				 * of the command */
-				SCp->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC;
-				SCp->cmnd[7] = hostdata->status[0];
-				SCp->use_sg = 0;
-				SCp->sc_data_direction = DMA_FROM_DEVICE;
-				dma_sync_single_for_device(hostdata->dev, slot->pCmd,
-							   SCp->cmd_len, DMA_TO_DEVICE);
-				SCp->request_bufflen = sizeof(SCp->sense_buffer);
+				sense->cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC;
+				sense->cmnd[7] = hostdata->status[0];
+				slot->pCmd = dma_map_single(hostdata->dev, sense->cmnd, sizeof(sense->cmnd), DMA_TO_DEVICE);
 				slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
 				slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer));
 				slot->SG[0].pAddr = bS_to_host(slot->dma_handle);
@@ -1027,6 +1021,7 @@
 				
 				/* queue the command for reissue */
 				slot->state = NCR_700_SLOT_QUEUED;
+				slot->flags = NCR_700_FLAG_AUTOSENSE;
 				hostdata->state = NCR_700_HOST_FREE;
 				hostdata->cmd = NULL;
 			}
@@ -1247,7 +1242,7 @@
 
 			if(SCp->use_sg) {
 				for(i = 0; i < SCp->use_sg + 1; i++) {
-					printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
+					printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->request_buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);
 				}
 			}
 		}	       
@@ -1406,12 +1401,14 @@
 	/* keep interrupts disabled until we have the command correctly
 	 * set up so we cannot take a selection interrupt */
 
-	hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE,
+	hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE &&
+						slot->flags != NCR_700_FLAG_AUTOSENSE),
 					       SCp->device->lun);
 	/* for INQUIRY or REQUEST_SENSE commands, we cannot be sure
 	 * if the negotiated transfer parameters still hold, so
 	 * always renegotiate them */
-	if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) {
+	if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE ||
+	   slot->flags == NCR_700_FLAG_AUTOSENSE) {
 		NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC);
 	}
 
@@ -1420,7 +1417,8 @@
 	 * will refuse all tags, so send the request sense as untagged
 	 * */
 	if((hostdata->tag_negotiated & (1<<scmd_id(SCp)))
-	   && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) {
+	   && (slot->tag != SCSI_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE &&
+	       slot->flags != NCR_700_FLAG_AUTOSENSE)) {
 		count += scsi_populate_tag_msg(SCp, &hostdata->msgout[count]);
 	}
 
@@ -1866,8 +1864,9 @@
 		__u32 count = 0;
 
 		if(SCp->use_sg) {
-			sg_count = dma_map_sg(hostdata->dev, SCp->buffer,
-					      SCp->use_sg, direction);
+			sg_count = dma_map_sg(hostdata->dev,
+					      SCp->request_buffer, SCp->use_sg,
+					      direction);
 		} else {
 			vPtr = dma_map_single(hostdata->dev,
 					      SCp->request_buffer, 
@@ -1882,7 +1881,7 @@
 		for(i = 0; i < sg_count; i++) {
 
 			if(SCp->use_sg) {
-				struct scatterlist *sg = SCp->buffer;
+				struct scatterlist *sg = SCp->request_buffer;
 
 				vPtr = sg_dma_address(&sg[i]);
 				count = sg_dma_len(&sg[i]);
@@ -2045,6 +2044,11 @@
 	struct NCR_700_Host_Parameters *hostdata = 
 		(struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
 
+	SDp->hostdata = kmalloc(GFP_KERNEL, sizeof(struct NCR_700_sense));
+
+	if (!SDp->hostdata)
+		return -ENOMEM;
+
 	/* to do here: allocate memory; build a queue_full list */
 	if(SDp->tagged_supported) {
 		scsi_set_tag_type(SDp, MSG_ORDERED_TAG);
@@ -2068,7 +2072,8 @@
 STATIC void
 NCR_700_slave_destroy(struct scsi_device *SDp)
 {
-	/* to do here: deallocate memory */
+	kfree(SDp->hostdata);
+	SDp->hostdata = NULL;
 }
 
 static int
diff --git a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
index a8c83bb..7f22a06 100644
--- a/drivers/scsi/53c700.h
+++ b/drivers/scsi/53c700.h
@@ -163,6 +163,8 @@
 	#define NCR_700_SLOT_BUSY (1|NCR_700_SLOT_MAGIC) /* slot has command active on HA */
 	#define NCR_700_SLOT_QUEUED (2|NCR_700_SLOT_MAGIC) /* slot has command to be made active on HA */
 	__u8	state;
+	#define NCR_700_FLAG_AUTOSENSE	0x01
+	__u8	flags;
 	int	tag;
 	__u32	resume_offset;
 	struct scsi_cmnd *cmnd;
@@ -472,8 +474,7 @@
 		ioread32(hostdata->base + reg);
 #if 1
 	/* sanity check the register */
-	if((reg & 0x3) != 0)
-		BUG();
+	BUG_ON((reg & 0x3) != 0);
 #endif
 
 	return value;
@@ -496,8 +497,7 @@
 
 #if 1
 	/* sanity check the register */
-	if((reg & 0x3) != 0)
-		BUG();
+	BUG_ON((reg & 0x3) != 0);
 #endif
 
 	bEBus ? iowrite32be(value, hostdata->base + reg): 
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 7894b8e..765769a 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -361,7 +361,7 @@
 static char *setup_strings[] =
 	{"","","","","","","",""};
 
-#define MAX_SETUP_STRINGS (sizeof(setup_strings) / sizeof(char *))
+#define MAX_SETUP_STRINGS ARRAY_SIZE(setup_strings)
 #define SETUP_BUFFER_SIZE 200
 static char setup_buffer[SETUP_BUFFER_SIZE];
 static char setup_used[MAX_SETUP_STRINGS];
@@ -709,7 +709,7 @@
 	printk (KERN_ALERT "target %d is host ID\n", target);
 	return -1;
     } 
-    else if (target > h->max_id) {
+    else if (target >= h->max_id) {
 	printk (KERN_ALERT "target %d exceeds maximum of %d\n", target,
 	    h->max_id);
 	return -1;
@@ -2190,15 +2190,15 @@
  */
 
 
-static void 
+static void
 synchronous (struct Scsi_Host *host, int target, char *msg) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
 	host->hostdata[0];
     int desire, divisor, i, limit;
     unsigned char scntl3, sxfer;
 /* The diagnostic message fits on one line, even with max. width integers */
-    char buf[80];	
-   
+    char buf[80];
+
 /* Desired transfer clock in Hz */
     desire = 1000000000L / (msg[3] * 4);
 /* Scale the available SCSI clock by 10 so we get tenths */
@@ -2209,14 +2209,14 @@
 	msg[4] = 8;
 
     if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : optimal synchronous divisor of %d.%01d\n", 
+    	printk("scsi%d : optimal synchronous divisor of %d.%01d\n",
 	    host->host_no, divisor / 10, divisor % 10);
 
-    limit = (sizeof(syncs) / sizeof(syncs[0]) -1);
+    limit = ARRAY_SIZE(syncs) - 1;
     for (i = 0; (i < limit) && (divisor > syncs[i].div); ++i);
 
     if (hostdata->options & OPTION_DEBUG_SDTR)
-    	printk("scsi%d : selected synchronous divisor of %d.%01d\n", 
+    	printk("scsi%d : selected synchronous divisor of %d.%01d\n",
 	    host->host_no, syncs[i].div / 10, syncs[i].div % 10);
 
     msg[3] = ((1000000000L / hostdata->scsi_clock) * syncs[i].div / 10 / 4);
@@ -3622,7 +3622,7 @@
 #ifdef LINUX_1_2
 	|| cmd->device->id > 7
 #else
-	|| cmd->device->id > host->max_id
+	|| cmd->device->id >= host->max_id
 #endif
 	|| cmd->device->id == host->this_id
 	|| hostdata->state == STATE_DISABLED) {
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index a480a37..96a81cd 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -501,7 +501,7 @@
 	tristate "Intel PIIX/ICH SATA support"
 	depends on SCSI_SATA && PCI
 	help
-	  This option enables support for ICH5 Serial ATA.
+	  This option enables support for ICH5/6/7/8 Serial ATA.
 	  If PATA support was enabled previously, this enables
 	  support for select Intel PIIX/ICH PATA host controllers.
 
@@ -532,6 +532,16 @@
 
 	  If unsure, say N.
 
+config SCSI_HPTIOP
+	tristate "HighPoint RocketRAID 3xxx Controller support"
+	depends on SCSI && PCI
+	help
+	  This option enables support for HighPoint RocketRAID 3xxx
+	  controllers.
+
+	  To compile this driver as a module, choose M here; the module
+	  will be called hptiop. If unsure, say N.
+
 config SCSI_SATA_QSTOR
 	tristate "Pacific Digital SATA QStor support"
 	depends on SCSI_SATA && PCI
@@ -1159,7 +1169,7 @@
 	  you do not have this SCSI card, so say N.
 
 config SCSI_NCR53C8XX_DEFAULT_TAGS
-	int "  default tagged command queue depth"
+	int "default tagged command queue depth"
 	depends on SCSI_ZALON || SCSI_NCR_Q720
 	default "8"
 	---help---
@@ -1185,7 +1195,7 @@
 	  There is no safe option other than using good SCSI devices.
 
 config SCSI_NCR53C8XX_MAX_TAGS
-	int "  maximum number of queued commands"
+	int "maximum number of queued commands"
 	depends on SCSI_ZALON || SCSI_NCR_Q720
 	default "32"
 	---help---
@@ -1202,7 +1212,7 @@
 	  There is no safe option and the default answer is recommended.
 
 config SCSI_NCR53C8XX_SYNC
-	int "  synchronous transfers frequency in MHz"
+	int "synchronous transfers frequency in MHz"
 	depends on SCSI_ZALON || SCSI_NCR_Q720
 	default "20"
 	---help---
@@ -1236,7 +1246,7 @@
 	  terminations and SCSI conformant devices.
 
 config SCSI_NCR53C8XX_PROFILE
-	bool "  enable profiling"
+	bool "enable profiling"
 	depends on SCSI_ZALON || SCSI_NCR_Q720
 	help
 	  This option allows you to enable profiling information gathering.
@@ -1247,7 +1257,7 @@
 	  The normal answer therefore is N.
 
 config SCSI_NCR53C8XX_NO_DISCONNECT
-	bool "  not allow targets to disconnect"
+	bool "not allow targets to disconnect"
 	depends on (SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0
 	help
 	  This option is only provided for safety if you suspect some SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 81803a1..ebd0cf0 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -33,7 +33,8 @@
 obj-$(CONFIG_SCSI_ISCSI_ATTRS)	+= scsi_transport_iscsi.o
 obj-$(CONFIG_SCSI_SAS_ATTRS)	+= scsi_transport_sas.o
 
-obj-$(CONFIG_ISCSI_TCP) 	+= iscsi_tcp.o
+obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	iscsi_tcp.o
+obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
 obj-$(CONFIG_SCSI_AMIGA7XX)	+= amiga7xx.o	53c7xx.o
 obj-$(CONFIG_A3000_SCSI)	+= a3000.o	wd33c93.o
 obj-$(CONFIG_A2091_SCSI)	+= a2091.o	wd33c93.o
@@ -136,6 +137,7 @@
 obj-$(CONFIG_SCSI_SATA_ULI)	+= libata.o sata_uli.o
 obj-$(CONFIG_SCSI_SATA_MV)	+= libata.o sata_mv.o
 obj-$(CONFIG_SCSI_PDC_ADMA)	+= libata.o pdc_adma.o
+obj-$(CONFIG_SCSI_HPTIOP)	+= hptiop.o
 
 obj-$(CONFIG_ARM)		+= arm/
 
@@ -164,7 +166,7 @@
 CFLAGS_ncr53c8xx.o	:= $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
 zalon7xx-objs	:= zalon.o ncr53c8xx.o
 NCR_Q720_mod-objs	:= NCR_Q720.o ncr53c8xx.o
-libata-objs	:= libata-core.o libata-scsi.o libata-bmdma.o
+libata-objs	:= libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o
 oktagon_esp_mod-objs	:= oktagon_esp.o oktagon_io.o
 
 # Files generated that shall be removed upon make clean
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 9f0ddbe..75f2f7a 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -296,7 +296,7 @@
 	 */
 
 	if (cmd->use_sg) {
-		cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+		cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
 		cmd->SCp.buffers_residual = cmd->use_sg - 1;
 		cmd->SCp.ptr = page_address(cmd->SCp.buffer->page)+
 			       cmd->SCp.buffer->offset;
@@ -500,7 +500,7 @@
 /* 
  * Function : int should_disconnect (unsigned char cmd)
  *
- * Purpose : decide weather a command would normally disconnect or 
+ * Purpose : decide whether a command would normally disconnect or 
  *      not, since if it won't disconnect we should go to sleep.
  *
  * Input : cmd - opcode of SCSI command
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index ae37d3a..8472c53 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -213,16 +213,16 @@
 	(void *) 0xd8000,
 	(void *) 0xc8000
 };
-#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
+#define ADDRESS_COUNT ARRAY_SIZE(addresses)
 #endif				/* USE_BIOS */
 
 /* possible i/o port addresses */
 static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 };
-#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
+#define PORT_COUNT ARRAY_SIZE(ports)
 
 /* possible interrupt channels */
 static unsigned short intrs[] = { 10, 11, 12, 15 };
-#define INTR_COUNT (sizeof( intrs ) / sizeof( unsigned short ))
+#define INTR_COUNT ARRAY_SIZE(intrs)
 
 /* signatures for NCR 53c406a based controllers */
 #if USE_BIOS
@@ -236,7 +236,7 @@
 	{
 "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82},};
 
-#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
+#define SIGNATURE_COUNT ARRAY_SIZE(signatures)
 #endif				/* USE_BIOS */
 
 /* ============================================================ */
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 642a3b4..83b5c7d0 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -148,6 +148,8 @@
 static int dacmode = -1;
 
 static int commit = -1;
+int startup_timeout = 180;
+int aif_timeout = 120;
 
 module_param(nondasd, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
@@ -155,6 +157,10 @@
 MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");
 module_param(commit, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
+module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for adapter to have it's kernel up and\nrunning. This is typically adjusted for large systems that do not have a BIOS.");
+module_param(aif_timeout, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for applications to pick up AIFs before\nderegistering them. This is typically adjusted for heavily burdened systems.");
 
 int numacb = -1;
 module_param(numacb, int, S_IRUGO|S_IWUSR);
@@ -390,8 +396,7 @@
 	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 
 	dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));
-	if (fibptr == NULL)
-		BUG();
+	BUG_ON(fibptr == NULL);
 
 	get_name_reply = (struct aac_get_name_resp *) fib_data(fibptr);
 	/* Failure is irrelevant, using default value instead */
@@ -635,13 +640,13 @@
 			cp[sizeof(str->pid)] = c;
 	} else {
 		struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype);
-   
-		inqstrcpy (mp->vname, str->vid); 
+
+		inqstrcpy (mp->vname, str->vid);
 		/* last six chars reserved for vol type */
 		inqstrcpy (mp->model, str->pid);
 	}
 
-	if (tindex < (sizeof(container_types)/sizeof(char *))){
+	if (tindex < ARRAY_SIZE(container_types)){
 		char *findit = str->pid;
 
 		for ( ; *findit != ' '; findit++); /* walk till we find a space */
@@ -950,12 +955,11 @@
 		  smp_processor_id(), (unsigned long long)lba, jiffies);
 	}
 
-	if (fibptr == NULL)
-		BUG();
+	BUG_ON(fibptr == NULL);
 		
 	if(scsicmd->use_sg)
 		pci_unmap_sg(dev->pdev, 
-			(struct scatterlist *)scsicmd->buffer,
+			(struct scatterlist *)scsicmd->request_buffer,
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
@@ -1086,8 +1090,7 @@
 		
 		aac_build_sgraw(scsicmd, &readcmd->sg);
 		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
-		if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
-			BUG();
+		BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)));
 		/*
 		 *	Now send the Fib to the adapter
 		 */
@@ -1255,8 +1258,7 @@
 		
 		aac_build_sgraw(scsicmd, &writecmd->sg);
 		fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
-		if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))
-			BUG();
+		BUG_ON(fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)));
 		/*
 		 *	Now send the Fib to the adapter
 		 */
@@ -1570,7 +1572,7 @@
 		 *	see: <vendor>.c i.e. aac.c
 		 */
 		if (scmd_id(scsicmd) == host->this_id) {
-			setinqstr(dev, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *)));
+			setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
 			inq_data.inqd_pdt = INQD_PDT_PROC;	/* Processor device */
 			aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
 			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
@@ -1898,8 +1900,7 @@
 	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
-	if (fibptr == NULL)
-		BUG();
+	BUG_ON(fibptr == NULL);
 
 	srbreply = (struct aac_srb_reply *) fib_data(fibptr);
 
@@ -1913,7 +1914,7 @@
 
 	if(scsicmd->use_sg)
 		pci_unmap_sg(dev->pdev, 
-			(struct scatterlist *)scsicmd->buffer,
+			(struct scatterlist *)scsicmd->request_buffer,
 			scsicmd->use_sg,
 			scsicmd->sc_data_direction);
 	else if(scsicmd->request_bufflen)
@@ -2218,15 +2219,15 @@
 		}
 	}
 	else if(scsicmd->request_bufflen) {
-		dma_addr_t addr; 
-		addr = pci_map_single(dev->pdev,
+		u32 addr;
+		scsicmd->SCp.dma_handle = pci_map_single(dev->pdev,
 				scsicmd->request_buffer,
 				scsicmd->request_bufflen,
 				scsicmd->sc_data_direction);
+		addr = scsicmd->SCp.dma_handle;
 		psg->count = cpu_to_le32(1);
 		psg->sg[0].addr = cpu_to_le32(addr);
 		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
-		scsicmd->SCp.dma_handle = addr;
 		byte_count = scsicmd->request_bufflen;
 	}
 	return byte_count;
@@ -2375,7 +2376,7 @@
 	{ SRB_STATUS_SUCCESS,		"Success"},
 	{ SRB_STATUS_ABORTED,		"Aborted Command"},
 	{ SRB_STATUS_ABORT_FAILED,	"Abort Failed"},
-	{ SRB_STATUS_ERROR,		"Error Event"}, 
+	{ SRB_STATUS_ERROR,		"Error Event"},
 	{ SRB_STATUS_BUSY,		"Device Busy"},
 	{ SRB_STATUS_INVALID_REQUEST,	"Invalid Request"},
 	{ SRB_STATUS_INVALID_PATH_ID,	"Invalid Path ID"},
@@ -2394,7 +2395,7 @@
 	{ SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"},
 	{ SRB_STATUS_REQUEST_FLUSHED,	"Request Flushed"},
 	{ SRB_STATUS_DELAYED_RETRY,	"Delayed Retry"},
-	{ SRB_STATUS_INVALID_LUN,	"Invalid LUN"}, 
+	{ SRB_STATUS_INVALID_LUN,	"Invalid LUN"},
 	{ SRB_STATUS_INVALID_TARGET_ID,	"Invalid TARGET ID"},
 	{ SRB_STATUS_BAD_FUNCTION,	"Bad Function"},
 	{ SRB_STATUS_ERROR_RECOVERY,	"Error Recovery"},
@@ -2409,11 +2410,9 @@
 {
 	int i;
 
-	for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){
-		if(srb_status_info[i].status == status){
+	for (i = 0; i < ARRAY_SIZE(srb_status_info); i++)
+		if (srb_status_info[i].status == status)
 			return srb_status_info[i].str;
-		}
-	}
 
 	return "Bad Status Code";
 }
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index f773b0d..d0eecd4 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,7 +12,7 @@
 
 #ifndef AAC_DRIVER_BUILD
 # define AAC_DRIVER_BUILD 2409
-# define AAC_DRIVER_BRANCH "-mh1"
+# define AAC_DRIVER_BRANCH "-mh2"
 #endif
 #define MAXIMUM_NUM_CONTAINERS	32
 
@@ -563,7 +563,6 @@
 	spinlock_t		lockdata;	/* Actual lock (used only on one side of the lock) */
 	struct list_head 	cmdq;	   	/* A queue of FIBs which need to be prcessed by the FS thread. This is */
                                 		/* only valid for command queues which receive entries from the adapter. */
-	struct list_head	pendingq;	/* A queue of outstanding fib's to the adapter. */
 	u32			numpending;	/* Number of entries on outstanding queue. */
 	struct aac_dev *	dev;		/* Back pointer to adapter structure */
 };
@@ -823,11 +822,6 @@
 	void 			*callback_data;
 	u32			flags; // u32 dmb was ulong
 	/*
-	 *	The following is used to put this fib context onto the 
-	 *	Outstanding I/O queue.
-	 */
-	struct list_head	queue;
-	/*
 	 *	And for the internal issue/reply queues (we may be able
 	 *	to merge these two)
 	 */
@@ -1815,3 +1809,5 @@
 extern int numacb;
 extern int acbsize;
 extern char aac_driver_version[];
+extern int startup_timeout;
+extern int aif_timeout;
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 9f75144..255421d 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -535,7 +535,7 @@
 	default:
 		data_dir = DMA_NONE;
 	}
-	if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) {
+	if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) {
 		dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
 		  le32_to_cpu(srbcmd->sg.count)));
 		rcode = -EINVAL;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 1939745..7cea514 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -103,9 +103,12 @@
 	 * This assumes the memory is mapped zero->n, which isnt
 	 * always true on real computers. It also has some slight problems
 	 * with the GART on x86-64. I've btw never tried DMA from PCI space
-	 * on this platform but don't be suprised if its problematic.
+	 * on this platform but don't be surprised if its problematic.
+	 * [AK: something is very very wrong when a driver tests this symbol.
+ 	 *  Someone should figure out what the comment writer really meant here and fix
+	 *  the code. Or just remove that bad code. ]
 	 */
-#ifndef CONFIG_GART_IOMMU
+#ifndef CONFIG_IOMMU
 	if ((num_physpages << (PAGE_SHIFT - 12)) <= AAC_MAX_HOSTPHYSMEMPAGES) {
 		init->HostPhysMemPages = 
 			cpu_to_le32(num_physpages << (PAGE_SHIFT-12));
@@ -159,7 +162,6 @@
 {
 	q->numpending = 0;
 	q->dev = dev;
-	INIT_LIST_HEAD(&q->pendingq);
 	init_waitqueue_head(&q->cmdready);
 	INIT_LIST_HEAD(&q->cmdq);
 	init_waitqueue_head(&q->qfull);
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 9f9f4aa..3f27419 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -229,8 +229,7 @@
 static void fib_dealloc(struct fib * fibptr)
 {
 	struct hw_fib *hw_fib = fibptr->hw_fib;
-	if(hw_fib->header.StructType != FIB_MAGIC) 
-		BUG();
+	BUG_ON(hw_fib->header.StructType != FIB_MAGIC);
 	hw_fib->header.XferState = 0;        
 }
 
@@ -472,7 +471,6 @@
 	spin_lock_irqsave(q->lock, qflags);
 	if (dev->new_comm_interface) {
 		unsigned long count = 10000000L; /* 50 seconds */
-		list_add_tail(&fibptr->queue, &q->pendingq);
 		q->numpending++;
 		spin_unlock_irqrestore(q->lock, qflags);
 		while (aac_adapter_send(fibptr) != 0) {
@@ -481,7 +479,6 @@
 					spin_unlock_irqrestore(&fibptr->event_lock, flags);
 				spin_lock_irqsave(q->lock, qflags);
 				q->numpending--;
-				list_del(&fibptr->queue);
 				spin_unlock_irqrestore(q->lock, qflags);
 				return -ETIMEDOUT;
 			}
@@ -492,7 +489,6 @@
 		unsigned long nointr = 0;
 		aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
 
-		list_add_tail(&fibptr->queue, &q->pendingq);
 		q->numpending++;
 		*(q->headers.producer) = cpu_to_le32(index + 1);
 		spin_unlock_irqrestore(q->lock, qflags);
@@ -520,7 +516,6 @@
 				if (--count == 0) {
 					spin_lock_irqsave(q->lock, qflags);
 					q->numpending--;
-					list_del(&fibptr->queue);
 					spin_unlock_irqrestore(q->lock, qflags);
 					if (wait == -1) {
 	        				printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n"
@@ -534,8 +529,7 @@
 			}
 		} else
 			down(&fibptr->event_wait);
-		if(fibptr->done == 0)
-			BUG();
+		BUG_ON(fibptr->done == 0);
 			
 		if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){
 			return -ETIMEDOUT;
@@ -1214,7 +1208,7 @@
 						 * since the last read off
 						 * the queue?
 						 */
-						if ((time_now - time_last) > 120) {
+						if ((time_now - time_last) > aif_timeout) {
 							entry = entry->next;
 							aac_close_fib_context(dev, fibctx);
 							continue;
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index f6bcb94..b2a5c72 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -85,10 +85,9 @@
 		 *	continue. The caller has already been notified that
 		 *	the fib timed out.
 		 */
-		if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
-			list_del(&fib->queue);
+		if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
 			dev->queues->queue[AdapNormCmdQueue].numpending--;
-		} else {
+		else {
 			printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
 			printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
 			continue;
@@ -284,7 +283,6 @@
 			return 0;
 		}
 
-		list_del(&fib->queue);
 		dev->queues->queue[AdapNormCmdQueue].numpending--;
 
 		if (fast) {
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 6ef89c9..e42a479 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -119,7 +119,7 @@
 	{ 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014R0 (Lancer) */
 	{ 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */
 	{ 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */
-	{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */
+	{ 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5445AU (Hurricane44) */
 	{ 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */
 	{ 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */
 	{ 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */
@@ -143,7 +143,7 @@
 	{ 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
 	{ 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
 	{ 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
-	{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */
+	{ 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800SAS (Hurricane44) */
 
 	{ 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
 	{ 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
@@ -195,7 +195,7 @@
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9014R0       ", 1 }, /* ICP9014R0 (Lancer) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9047MA       ", 1 }, /* ICP9047MA (Lancer) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9087MA       ", 1 }, /* ICP9087MA (Lancer) */
-	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP5085AU       ", 1 }, /* ICP5085AU (Hurricane) */
+	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP5445AU       ", 1 }, /* ICP5445AU (Hurricane44) */
 	{ aac_rx_init, "aacraid",  "ICP     ", "ICP9085LI       ", 1 }, /* ICP9085LI (Marauder-X) */
 	{ aac_rx_init, "aacraid",  "ICP     ", "ICP5085BR       ", 1 }, /* ICP5085BR (Marauder-E) */
 	{ aac_rkt_init, "aacraid",  "ICP     ", "ICP9067MA       ", 1 }, /* ICP9067MA (Intruder-6) */
@@ -217,7 +217,7 @@
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4000SAS     ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4800SAS     ", 1 }, /* ASR-4800SAS (Marauder-X) */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4805SAS     ", 1 }, /* ASR-4805SAS (Marauder-E) */
-	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-4810SAS     ", 1 }, /* ASR-4810SAS (Hurricane) */
+	{ aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-3800SAS     ", 1 }, /* ASR-3800SAS (Hurricane44) */
 
 	{ aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
 	{ aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
@@ -453,15 +453,10 @@
 
 	printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", 
 					AAC_DRIVERNAME);
-
-
-	spin_lock_irq(host->host_lock);
-
 	aac = (struct aac_dev *)host->hostdata;
 	if (aac_adapter_check_health(aac)) {
 		printk(KERN_ERR "%s: Host adapter appears dead\n", 
 				AAC_DRIVERNAME);
-		spin_unlock_irq(host->host_lock);
 		return -ENODEV;
 	}
 	/*
@@ -487,13 +482,10 @@
 		/*
 		 * We can exit If all the commands are complete
 		 */
-		spin_unlock_irq(host->host_lock);
 		if (active == 0)
 			return SUCCESS;
 		ssleep(1);
-		spin_lock_irq(host->host_lock);
 	}
-	spin_unlock_irq(host->host_lock);
 	printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
 	return -ETIMEDOUT;
 }
@@ -572,7 +564,7 @@
 		
 		f = compat_alloc_user_space(sizeof(*f));
 		ret = 0;
-		if (clear_user(f, sizeof(*f)) != sizeof(*f))
+		if (clear_user(f, sizeof(*f)))
 			ret = -EFAULT;
 		if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
 			ret = -EFAULT;
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 7a23e02..5b52966 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -444,14 +444,14 @@
 	 */
 	while (!(rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING))
 	{
-		if(time_after(jiffies, start+180*HZ))
+		if(time_after(jiffies, start+startup_timeout*HZ))
 		{
 			status = rkt_readl(dev, MUnit.OMRx[0]);
 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 
 					dev->name, instance, status);
 			goto error_iounmap;
 		}
-		schedule_timeout_uninterruptible(1);
+		msleep(1);
 	}
 	if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) 
 	{
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 729b9eb..9dadfb2 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -444,14 +444,14 @@
 	while ((!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING))
 		|| (!(rx_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING)))
 	{
-		if(time_after(jiffies, start+180*HZ))
+		if(time_after(jiffies, start+startup_timeout*HZ))
 		{
 			status = rx_readl(dev, IndexRegs.Mailbox[7]);
 			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 
 					dev->name, instance, status);
 			goto error_iounmap;
 		}
-		schedule_timeout_uninterruptible(1);
+		msleep(1);
 	}
 	if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) 
 	{
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index a534549..88d400f 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -66,11 +66,11 @@
 			sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
 			sa_writew(dev, DoorbellReg_s, PrintfDone);
 		} else if (intstat & DOORBELL_1) {	// dev -> Host Normal Command Ready
-			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
 			sa_writew(dev, DoorbellClrReg_p, DOORBELL_1);
+			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
 		} else if (intstat & DOORBELL_2) {	// dev -> Host Normal Response Ready
-			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
 			sa_writew(dev, DoorbellClrReg_p, DOORBELL_2);
+			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
 		} else if (intstat & DOORBELL_3) {	// dev -> Host Normal Command Not Full
 			sa_writew(dev, DoorbellClrReg_p, DOORBELL_3);
 		} else if (intstat & DOORBELL_4) {	// dev -> Host Normal Response Not Full
@@ -318,13 +318,13 @@
 	 *	Wait for the adapter to be up and running. Wait up to 3 minutes.
 	 */
 	while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
-		if (time_after(jiffies, start+180*HZ)) {
+		if (time_after(jiffies, start+startup_timeout*HZ)) {
 			status = sa_readl(dev, Mailbox7);
 			printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %lx.\n", 
 					name, instance, status);
 			goto error_iounmap;
 		}
-		schedule_timeout_uninterruptible(1);
+		msleep(1);
 	}
 
 	if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) {
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 2a41963..dd9fb3d 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -12374,7 +12374,7 @@
                 ASC_PRINT1(
 "AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", i);
         } else {
-                ASC_PRINT("AscInitFromEEP: Succesfully re-wrote EEPROM.");
+                ASC_PRINT("AscInitFromEEP: Successfully re-wrote EEPROM.\n");
         }
     }
     return (warn_code);
@@ -17316,7 +17316,7 @@
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void
+void __init
 AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
 {
     ushort *wbuf;
@@ -17383,7 +17383,7 @@
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void
+void __init
 AdvSet38C0800EEPConfig(AdvPortAddr iop_base,
                        ADVEEP_38C0800_CONFIG *cfg_buf)
 {
@@ -17451,7 +17451,7 @@
 /*
  * Write the EEPROM from 'cfg_buf'.
  */
-void
+void __init
 AdvSet38C1600EEPConfig(AdvPortAddr iop_base,
                        ADVEEP_38C1600_CONFIG *cfg_buf)
 {
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 51bad7a..86c6bd2 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -1011,7 +1011,7 @@
 
 	int count=setup_idx;
 
-	get_options(str, sizeof(ints)/sizeof(int), ints);
+	get_options(str, ARRAY_SIZE(ints), ints);
 	aha1542_setup(str,ints);
 
 	return count<setup_idx;
@@ -1072,8 +1072,7 @@
 		int slot = 0;
 		int pos = 0;
 
-		for (indx = 0; (slot !=  MCA_NOTFOUND) && 
-			     (indx < sizeof(bases)/sizeof(bases[0])); indx++) {
+		for (indx = 0; (slot != MCA_NOTFOUND) && (indx < ARRAY_SIZE(bases)); indx++) {
 
 			if (bases[indx])
 				continue;
@@ -1083,10 +1082,9 @@
 			if (slot == MCA_NOTFOUND)
 				break;
 
-			
 			/* Found one */
 			pos = mca_read_stored_pos(slot, 3);
-			
+
 			/* Decode address */
 			if (pos & 0x80) {
 				if (pos & 0x02) {
@@ -1118,23 +1116,22 @@
 			mca_set_adapter_name(slot, "Adapter AHA-1640");
 			mca_set_adapter_procfn(slot, NULL, NULL);
 			mca_mark_as_used(slot);
-			
+
 			/* Go on */
 			slot++;
 		}
-		
+
 	}
 #endif
 
 	/*
 	 *	Hunt for ISA Plug'n'Pray Adaptecs (AHA1535)
 	 */
-	 
+
 	if(isapnp)
 	{
 		struct pnp_dev *pdev = NULL;
-		for(indx = 0; indx <sizeof(bases)/sizeof(bases[0]);indx++)
-		{
+		for(indx = 0; indx < ARRAY_SIZE(bases); indx++) {
 			if(bases[indx])
 				continue;
 			pdev = pnp_find_dev(NULL, ISAPNP_VENDOR('A', 'D', 'P'), 
@@ -1144,29 +1141,29 @@
 			/*
 			 *	Activate the PnP card
 			 */
-			 
+
 			if(pnp_device_attach(pdev)<0)
 				continue;
-			
+
 			if(pnp_activate_dev(pdev)<0) {
 				pnp_device_detach(pdev);
 				continue;
 			}
-			
+
 			if(!pnp_port_valid(pdev, 0)) {
 				pnp_device_detach(pdev);
 				continue;
 			}
-				
+
 			bases[indx] = pnp_port_start(pdev, 0);
-			
+
 			/* The card can be queried for its DMA, we have 
 			   the DMA set up that is enough */
-			   
+
 			printk(KERN_INFO "ISAPnP found an AHA1535 at I/O 0x%03X\n", bases[indx]);
 		}
 	}
-	for (indx = 0; indx < sizeof(bases) / sizeof(bases[0]); indx++)
+	for (indx = 0; indx < ARRAY_SIZE(bases); indx++)
 		if (bases[indx] != 0 && request_region(bases[indx], 4, "aha1542")) {
 			shpnt = scsi_register(tpnt,
 					sizeof(struct aha1542_hostdata));
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index b4f8fb1..f059467 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -48,7 +48,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ahci"
-#define DRV_VERSION	"1.2"
+#define DRV_VERSION	"2.0"
 
 
 enum {
@@ -56,12 +56,15 @@
 	AHCI_MAX_SG		= 168, /* hardware max is 64K */
 	AHCI_DMA_BOUNDARY	= 0xffffffff,
 	AHCI_USE_CLUSTERING	= 0,
-	AHCI_CMD_SLOT_SZ	= 32 * 32,
+	AHCI_MAX_CMDS		= 32,
+	AHCI_CMD_SZ		= 32,
+	AHCI_CMD_SLOT_SZ	= AHCI_MAX_CMDS * AHCI_CMD_SZ,
 	AHCI_RX_FIS_SZ		= 256,
-	AHCI_CMD_TBL_HDR	= 0x80,
 	AHCI_CMD_TBL_CDB	= 0x40,
-	AHCI_CMD_TBL_SZ		= AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16),
-	AHCI_PORT_PRIV_DMA_SZ	= AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ +
+	AHCI_CMD_TBL_HDR_SZ	= 0x80,
+	AHCI_CMD_TBL_SZ		= AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16),
+	AHCI_CMD_TBL_AR_SZ	= AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS,
+	AHCI_PORT_PRIV_DMA_SZ	= AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ +
 				  AHCI_RX_FIS_SZ,
 	AHCI_IRQ_ON_SG		= (1 << 31),
 	AHCI_CMD_ATAPI		= (1 << 5),
@@ -71,8 +74,10 @@
 	AHCI_CMD_CLR_BUSY	= (1 << 10),
 
 	RX_FIS_D2H_REG		= 0x40,	/* offset of D2H Register FIS data */
+	RX_FIS_UNK		= 0x60, /* offset of Unknown FIS data */
 
 	board_ahci		= 0,
+	board_ahci_vt8251	= 1,
 
 	/* global controller registers */
 	HOST_CAP		= 0x00, /* host capabilities */
@@ -87,8 +92,9 @@
 	HOST_AHCI_EN		= (1 << 31), /* AHCI enabled */
 
 	/* HOST_CAP bits */
-	HOST_CAP_64		= (1 << 31), /* PCI DAC (64-bit DMA) support */
 	HOST_CAP_CLO		= (1 << 24), /* Command List Override support */
+	HOST_CAP_NCQ		= (1 << 30), /* Native Command Queueing */
+	HOST_CAP_64		= (1 << 31), /* PCI DAC (64-bit DMA) support */
 
 	/* registers for each SATA port */
 	PORT_LST_ADDR		= 0x00, /* command list DMA addr */
@@ -127,15 +133,17 @@
 	PORT_IRQ_PIOS_FIS	= (1 << 1), /* PIO Setup FIS rx'd */
 	PORT_IRQ_D2H_REG_FIS	= (1 << 0), /* D2H Register FIS rx'd */
 
-	PORT_IRQ_FATAL		= PORT_IRQ_TF_ERR |
-				  PORT_IRQ_HBUS_ERR |
-				  PORT_IRQ_HBUS_DATA_ERR |
-				  PORT_IRQ_IF_ERR,
-	DEF_PORT_IRQ		= PORT_IRQ_FATAL | PORT_IRQ_PHYRDY |
-				  PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE |
-				  PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS |
-				  PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS |
-				  PORT_IRQ_D2H_REG_FIS,
+	PORT_IRQ_FREEZE		= PORT_IRQ_HBUS_ERR |
+				  PORT_IRQ_IF_ERR |
+				  PORT_IRQ_CONNECT |
+				  PORT_IRQ_PHYRDY |
+				  PORT_IRQ_UNK_FIS,
+	PORT_IRQ_ERROR		= PORT_IRQ_FREEZE |
+				  PORT_IRQ_TF_ERR |
+				  PORT_IRQ_HBUS_DATA_ERR,
+	DEF_PORT_IRQ		= PORT_IRQ_ERROR | PORT_IRQ_SG_DONE |
+				  PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS |
+				  PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
 
 	/* PORT_CMD bits */
 	PORT_CMD_ATAPI		= (1 << 24), /* Device is ATAPI */
@@ -153,6 +161,10 @@
 
 	/* hpriv->flags bits */
 	AHCI_FLAG_MSI		= (1 << 0),
+
+	/* ap->flags bits */
+	AHCI_FLAG_RESET_NEEDS_CLO	= (1 << 24),
+	AHCI_FLAG_NO_NCQ		= (1 << 25),
 };
 
 struct ahci_cmd_hdr {
@@ -181,7 +193,6 @@
 	dma_addr_t		cmd_slot_dma;
 	void			*cmd_tbl;
 	dma_addr_t		cmd_tbl_dma;
-	struct ahci_sg		*cmd_tbl_sg;
 	void			*rx_fis;
 	dma_addr_t		rx_fis_dma;
 };
@@ -191,15 +202,16 @@
 static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static unsigned int ahci_qc_issue(struct ata_queued_cmd *qc);
 static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
-static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void ahci_irq_clear(struct ata_port *ap);
-static void ahci_eng_timeout(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static u8 ahci_check_status(struct ata_port *ap);
-static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+static void ahci_freeze(struct ata_port *ap);
+static void ahci_thaw(struct ata_port *ap);
+static void ahci_error_handler(struct ata_port *ap);
+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static void ahci_remove_one (struct pci_dev *pdev);
 
 static struct scsi_host_template ahci_sht = {
@@ -207,7 +219,8 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.can_queue		= ATA_DEF_QUEUE,
+	.change_queue_depth	= ata_scsi_change_queue_depth,
+	.can_queue		= AHCI_MAX_CMDS - 1,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= AHCI_MAX_SG,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
@@ -216,6 +229,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= AHCI_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -228,19 +242,21 @@
 
 	.tf_read		= ahci_tf_read,
 
-	.probe_reset		= ahci_probe_reset,
-
 	.qc_prep		= ahci_qc_prep,
 	.qc_issue		= ahci_qc_issue,
 
-	.eng_timeout		= ahci_eng_timeout,
-
 	.irq_handler		= ahci_interrupt,
 	.irq_clear		= ahci_irq_clear,
 
 	.scr_read		= ahci_scr_read,
 	.scr_write		= ahci_scr_write,
 
+	.freeze			= ahci_freeze,
+	.thaw			= ahci_thaw,
+
+	.error_handler		= ahci_error_handler,
+	.post_internal_cmd	= ahci_post_internal_cmd,
+
 	.port_start		= ahci_port_start,
 	.port_stop		= ahci_port_stop,
 };
@@ -250,7 +266,19 @@
 	{
 		.sht		= &ahci_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+				  ATA_FLAG_SKIP_D2H_BSY,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &ahci_ops,
+	},
+	/* board_ahci_vt8251 */
+	{
+		.sht		= &ahci_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+				  ATA_FLAG_SKIP_D2H_BSY |
+				  AHCI_FLAG_RESET_NEEDS_CLO | AHCI_FLAG_NO_NCQ,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &ahci_ops,
@@ -258,6 +286,7 @@
 };
 
 static const struct pci_device_id ahci_pci_tbl[] = {
+	/* Intel */
 	{ PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ICH6 */
 	{ PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -288,14 +317,39 @@
 	  board_ahci }, /* ICH8M */
 	{ PCI_VENDOR_ID_INTEL, 0x282a, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ICH8M */
+
+	/* JMicron */
 	{ 0x197b, 0x2360, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* JMicron JMB360 */
+	{ 0x197b, 0x2361, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* JMicron JMB361 */
 	{ 0x197b, 0x2363, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* JMicron JMB363 */
+	{ 0x197b, 0x2365, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* JMicron JMB365 */
+	{ 0x197b, 0x2366, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci }, /* JMicron JMB366 */
+
+	/* ATI */
 	{ PCI_VENDOR_ID_ATI, 0x4380, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ATI SB600 non-raid */
 	{ PCI_VENDOR_ID_ATI, 0x4381, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_ahci }, /* ATI SB600 raid */
+
+	/* VIA */
+	{ PCI_VENDOR_ID_VIA, 0x3349, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci_vt8251 }, /* VIA VT8251 */
+
+	/* NVIDIA */
+	{ PCI_VENDOR_ID_NVIDIA, 0x044c, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci },		/* MCP65 */
+	{ PCI_VENDOR_ID_NVIDIA, 0x044d, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci },		/* MCP65 */
+	{ PCI_VENDOR_ID_NVIDIA, 0x044e, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci },		/* MCP65 */
+	{ PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_ahci },		/* MCP65 */
+
 	{ }	/* terminate list */
 };
 
@@ -374,8 +428,6 @@
 	pp->cmd_tbl = mem;
 	pp->cmd_tbl_dma = mem_dma;
 
-	pp->cmd_tbl_sg = mem + AHCI_CMD_TBL_HDR;
-
 	ap->private_data = pp;
 
 	if (hpriv->cap & HOST_CAP_64)
@@ -508,46 +560,71 @@
 	return ata_dev_classify(&tf);
 }
 
-static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts)
+static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
+			       u32 opts)
 {
-	pp->cmd_slot[0].opts = cpu_to_le32(opts);
-	pp->cmd_slot[0].status = 0;
-	pp->cmd_slot[0].tbl_addr = cpu_to_le32(pp->cmd_tbl_dma & 0xffffffff);
-	pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16);
+	dma_addr_t cmd_tbl_dma;
+
+	cmd_tbl_dma = pp->cmd_tbl_dma + tag * AHCI_CMD_TBL_SZ;
+
+	pp->cmd_slot[tag].opts = cpu_to_le32(opts);
+	pp->cmd_slot[tag].status = 0;
+	pp->cmd_slot[tag].tbl_addr = cpu_to_le32(cmd_tbl_dma & 0xffffffff);
+	pp->cmd_slot[tag].tbl_addr_hi = cpu_to_le32((cmd_tbl_dma >> 16) >> 16);
 }
 
-static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val,
-			      unsigned long interval_msec,
-			      unsigned long timeout_msec)
+static int ahci_clo(struct ata_port *ap)
 {
-	unsigned long timeout;
+	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
+	struct ahci_host_priv *hpriv = ap->host_set->private_data;
 	u32 tmp;
 
-	timeout = jiffies + (timeout_msec * HZ) / 1000;
-	do {
-		tmp = readl(reg);
-		if ((tmp & mask) == val)
-			return 0;
-		msleep(interval_msec);
-	} while (time_before(jiffies, timeout));
+	if (!(hpriv->cap & HOST_CAP_CLO))
+		return -EOPNOTSUPP;
 
-	return -1;
+	tmp = readl(port_mmio + PORT_CMD);
+	tmp |= PORT_CMD_CLO;
+	writel(tmp, port_mmio + PORT_CMD);
+
+	tmp = ata_wait_register(port_mmio + PORT_CMD,
+				PORT_CMD_CLO, PORT_CMD_CLO, 1, 500);
+	if (tmp & PORT_CMD_CLO)
+		return -EIO;
+
+	return 0;
 }
 
-static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class)
+static int ahci_prereset(struct ata_port *ap)
 {
-	struct ahci_host_priv *hpriv = ap->host_set->private_data;
+	if ((ap->flags & AHCI_FLAG_RESET_NEEDS_CLO) &&
+	    (ata_busy_wait(ap, ATA_BUSY, 1000) & ATA_BUSY)) {
+		/* ATA_BUSY hasn't cleared, so send a CLO */
+		ahci_clo(ap);
+	}
+
+	return ata_std_prereset(ap);
+}
+
+static int ahci_softreset(struct ata_port *ap, unsigned int *class)
+{
 	struct ahci_port_priv *pp = ap->private_data;
 	void __iomem *mmio = ap->host_set->mmio_base;
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	const u32 cmd_fis_len = 5; /* five dwords */
 	const char *reason = NULL;
 	struct ata_taskfile tf;
+	u32 tmp;
 	u8 *fis;
 	int rc;
 
 	DPRINTK("ENTER\n");
 
+	if (ata_port_offline(ap)) {
+		DPRINTK("PHY reports no device\n");
+		*class = ATA_DEV_NONE;
+		return 0;
+	}
+
 	/* prepare for SRST (AHCI-1.1 10.4.1) */
 	rc = ahci_stop_engine(ap);
 	if (rc) {
@@ -558,23 +635,13 @@
 	/* check BUSY/DRQ, perform Command List Override if necessary */
 	ahci_tf_read(ap, &tf);
 	if (tf.command & (ATA_BUSY | ATA_DRQ)) {
-		u32 tmp;
+		rc = ahci_clo(ap);
 
-		if (!(hpriv->cap & HOST_CAP_CLO)) {
-			rc = -EIO;
-			reason = "port busy but no CLO";
+		if (rc == -EOPNOTSUPP) {
+			reason = "port busy but CLO unavailable";
 			goto fail_restart;
-		}
-
-		tmp = readl(port_mmio + PORT_CMD);
-		tmp |= PORT_CMD_CLO;
-		writel(tmp, port_mmio + PORT_CMD);
-		readl(port_mmio + PORT_CMD); /* flush */
-
-		if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0,
-				       1, 500)) {
-			rc = -EIO;
-			reason = "CLO failed";
+		} else if (rc) {
+			reason = "port busy but CLO failed";
 			goto fail_restart;
 		}
 	}
@@ -582,20 +649,21 @@
 	/* restart engine */
 	ahci_start_engine(ap);
 
-	ata_tf_init(ap, &tf, 0);
+	ata_tf_init(ap->device, &tf);
 	fis = pp->cmd_tbl;
 
 	/* issue the first D2H Register FIS */
-	ahci_fill_cmd_slot(pp, cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
+	ahci_fill_cmd_slot(pp, 0,
+			   cmd_fis_len | AHCI_CMD_RESET | AHCI_CMD_CLR_BUSY);
 
 	tf.ctl |= ATA_SRST;
 	ata_tf_to_fis(&tf, fis, 0);
 	fis[1] &= ~(1 << 7);	/* turn off Command FIS bit */
 
 	writel(1, port_mmio + PORT_CMD_ISSUE);
-	readl(port_mmio + PORT_CMD_ISSUE);	/* flush */
 
-	if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) {
+	tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500);
+	if (tmp & 0x1) {
 		rc = -EIO;
 		reason = "1st FIS failed";
 		goto fail;
@@ -605,7 +673,7 @@
 	msleep(1);
 
 	/* issue the second D2H Register FIS */
-	ahci_fill_cmd_slot(pp, cmd_fis_len);
+	ahci_fill_cmd_slot(pp, 0, cmd_fis_len);
 
 	tf.ctl &= ~ATA_SRST;
 	ata_tf_to_fis(&tf, fis, 0);
@@ -625,7 +693,7 @@
 	msleep(150);
 
 	*class = ATA_DEV_NONE;
-	if (sata_dev_present(ap)) {
+	if (ata_port_online(ap)) {
 		if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
 			rc = -EIO;
 			reason = "device not ready";
@@ -640,25 +708,31 @@
  fail_restart:
 	ahci_start_engine(ap);
  fail:
-	if (verbose)
-		printk(KERN_ERR "ata%u: softreset failed (%s)\n",
-		       ap->id, reason);
-	else
-		DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason);
+	ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
 	return rc;
 }
 
-static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
+static int ahci_hardreset(struct ata_port *ap, unsigned int *class)
 {
+	struct ahci_port_priv *pp = ap->private_data;
+	u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+	struct ata_taskfile tf;
 	int rc;
 
 	DPRINTK("ENTER\n");
 
 	ahci_stop_engine(ap);
-	rc = sata_std_hardreset(ap, verbose, class);
+
+	/* clear D2H reception area to properly wait for D2H FIS */
+	ata_tf_init(ap->device, &tf);
+	tf.command = 0xff;
+	ata_tf_to_fis(&tf, d2h_fis, 0);
+
+	rc = sata_std_hardreset(ap, class);
+
 	ahci_start_engine(ap);
 
-	if (rc == 0)
+	if (rc == 0 && ata_port_online(ap))
 		*class = ahci_dev_classify(ap);
 	if (*class == ATA_DEV_UNKNOWN)
 		*class = ATA_DEV_NONE;
@@ -686,13 +760,6 @@
 	}
 }
 
-static int ahci_probe_reset(struct ata_port *ap, unsigned int *classes)
-{
-	return ata_drive_probe_reset(ap, ata_std_probeinit,
-				     ahci_softreset, ahci_hardreset,
-				     ahci_postreset, classes);
-}
-
 static u8 ahci_check_status(struct ata_port *ap)
 {
 	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
@@ -708,9 +775,8 @@
 	ata_tf_from_fis(d2h_fis, tf);
 }
 
-static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc)
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
 {
-	struct ahci_port_priv *pp = qc->ap->private_data;
 	struct scatterlist *sg;
 	struct ahci_sg *ahci_sg;
 	unsigned int n_sg = 0;
@@ -720,7 +786,7 @@
 	/*
 	 * Next, the S/G list.
 	 */
-	ahci_sg = pp->cmd_tbl_sg;
+	ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
 	ata_for_each_sg(sg, qc) {
 		dma_addr_t addr = sg_dma_address(sg);
 		u32 sg_len = sg_dma_len(sg);
@@ -741,6 +807,7 @@
 	struct ata_port *ap = qc->ap;
 	struct ahci_port_priv *pp = ap->private_data;
 	int is_atapi = is_atapi_taskfile(&qc->tf);
+	void *cmd_tbl;
 	u32 opts;
 	const u32 cmd_fis_len = 5; /* five dwords */
 	unsigned int n_elem;
@@ -749,16 +816,17 @@
 	 * Fill in command table information.  First, the header,
 	 * a SATA Register - Host to Device command FIS.
 	 */
-	ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
+	cmd_tbl = pp->cmd_tbl + qc->tag * AHCI_CMD_TBL_SZ;
+
+	ata_tf_to_fis(&qc->tf, cmd_tbl, 0);
 	if (is_atapi) {
-		memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
-		memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb,
-		       qc->dev->cdb_len);
+		memset(cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+		memcpy(cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, qc->dev->cdb_len);
 	}
 
 	n_elem = 0;
 	if (qc->flags & ATA_QCFLAG_DMAMAP)
-		n_elem = ahci_fill_sg(qc);
+		n_elem = ahci_fill_sg(qc, cmd_tbl);
 
 	/*
 	 * Fill in command slot information.
@@ -769,112 +837,122 @@
 	if (is_atapi)
 		opts |= AHCI_CMD_ATAPI | AHCI_CMD_PREFETCH;
 
-	ahci_fill_cmd_slot(pp, opts);
+	ahci_fill_cmd_slot(pp, qc->tag, opts);
 }
 
-static void ahci_restart_port(struct ata_port *ap, u32 irq_stat)
+static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
 {
-	void __iomem *mmio = ap->host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-	u32 tmp;
+	struct ahci_port_priv *pp = ap->private_data;
+	struct ata_eh_info *ehi = &ap->eh_info;
+	unsigned int err_mask = 0, action = 0;
+	struct ata_queued_cmd *qc;
+	u32 serror;
 
-	if ((ap->device[0].class != ATA_DEV_ATAPI) ||
-	    ((irq_stat & PORT_IRQ_TF_ERR) == 0))
-		printk(KERN_WARNING "ata%u: port reset, "
-		       "p_is %x is %x pis %x cmd %x tf %x ss %x se %x\n",
-			ap->id,
-			irq_stat,
-			readl(mmio + HOST_IRQ_STAT),
-			readl(port_mmio + PORT_IRQ_STAT),
-			readl(port_mmio + PORT_CMD),
-			readl(port_mmio + PORT_TFDATA),
-			readl(port_mmio + PORT_SCR_STAT),
-			readl(port_mmio + PORT_SCR_ERR));
+	ata_ehi_clear_desc(ehi);
 
-	/* stop DMA */
-	ahci_stop_engine(ap);
+	/* AHCI needs SError cleared; otherwise, it might lock up */
+	serror = ahci_scr_read(ap, SCR_ERROR);
+	ahci_scr_write(ap, SCR_ERROR, serror);
 
-	/* clear SATA phy error, if any */
-	tmp = readl(port_mmio + PORT_SCR_ERR);
-	writel(tmp, port_mmio + PORT_SCR_ERR);
+	/* analyze @irq_stat */
+	ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
 
-	/* if DRQ/BSY is set, device needs to be reset.
-	 * if so, issue COMRESET
-	 */
-	tmp = readl(port_mmio + PORT_TFDATA);
-	if (tmp & (ATA_BUSY | ATA_DRQ)) {
-		writel(0x301, port_mmio + PORT_SCR_CTL);
-		readl(port_mmio + PORT_SCR_CTL); /* flush */
-		udelay(10);
-		writel(0x300, port_mmio + PORT_SCR_CTL);
-		readl(port_mmio + PORT_SCR_CTL); /* flush */
+	if (irq_stat & PORT_IRQ_TF_ERR)
+		err_mask |= AC_ERR_DEV;
+
+	if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
+		err_mask |= AC_ERR_HOST_BUS;
+		action |= ATA_EH_SOFTRESET;
 	}
 
-	/* re-start DMA */
-	ahci_start_engine(ap);
-}
+	if (irq_stat & PORT_IRQ_IF_ERR) {
+		err_mask |= AC_ERR_ATA_BUS;
+		action |= ATA_EH_SOFTRESET;
+		ata_ehi_push_desc(ehi, ", interface fatal error");
+	}
 
-static void ahci_eng_timeout(struct ata_port *ap)
-{
-	struct ata_host_set *host_set = ap->host_set;
-	void __iomem *mmio = host_set->mmio_base;
-	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-	struct ata_queued_cmd *qc;
-	unsigned long flags;
+	if (irq_stat & (PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY)) {
+		ata_ehi_hotplugged(ehi);
+		ata_ehi_push_desc(ehi, ", %s", irq_stat & PORT_IRQ_CONNECT ?
+			"connection status changed" : "PHY RDY changed");
+	}
 
-	printk(KERN_WARNING "ata%u: handling error/timeout\n", ap->id);
+	if (irq_stat & PORT_IRQ_UNK_FIS) {
+		u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
 
-	spin_lock_irqsave(&host_set->lock, flags);
+		err_mask |= AC_ERR_HSM;
+		action |= ATA_EH_SOFTRESET;
+		ata_ehi_push_desc(ehi, ", unknown FIS %08x %08x %08x %08x",
+				  unk[0], unk[1], unk[2], unk[3]);
+	}
 
-	ahci_restart_port(ap, readl(port_mmio + PORT_IRQ_STAT));
+	/* okay, let's hand over to EH */
+	ehi->serror |= serror;
+	ehi->action |= action;
+
 	qc = ata_qc_from_tag(ap, ap->active_tag);
-	qc->err_mask |= AC_ERR_TIMEOUT;
+	if (qc)
+		qc->err_mask |= err_mask;
+	else
+		ehi->err_mask |= err_mask;
 
-	spin_unlock_irqrestore(&host_set->lock, flags);
-
-	ata_eh_qc_complete(qc);
+	if (irq_stat & PORT_IRQ_FREEZE)
+		ata_port_freeze(ap);
+	else
+		ata_port_abort(ap);
 }
 
-static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+static void ahci_host_intr(struct ata_port *ap)
 {
 	void __iomem *mmio = ap->host_set->mmio_base;
 	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
-	u32 status, serr, ci;
-
-	serr = readl(port_mmio + PORT_SCR_ERR);
-	writel(serr, port_mmio + PORT_SCR_ERR);
+	struct ata_eh_info *ehi = &ap->eh_info;
+	u32 status, qc_active;
+	int rc;
 
 	status = readl(port_mmio + PORT_IRQ_STAT);
 	writel(status, port_mmio + PORT_IRQ_STAT);
 
-	ci = readl(port_mmio + PORT_CMD_ISSUE);
-	if (likely((ci & 0x1) == 0)) {
-		if (qc) {
-			WARN_ON(qc->err_mask);
-			ata_qc_complete(qc);
-			qc = NULL;
-		}
+	if (unlikely(status & PORT_IRQ_ERROR)) {
+		ahci_error_intr(ap, status);
+		return;
 	}
 
-	if (status & PORT_IRQ_FATAL) {
-		unsigned int err_mask;
-		if (status & PORT_IRQ_TF_ERR)
-			err_mask = AC_ERR_DEV;
-		else if (status & PORT_IRQ_IF_ERR)
-			err_mask = AC_ERR_ATA_BUS;
-		else
-			err_mask = AC_ERR_HOST_BUS;
+	if (ap->sactive)
+		qc_active = readl(port_mmio + PORT_SCR_ACT);
+	else
+		qc_active = readl(port_mmio + PORT_CMD_ISSUE);
 
-		/* command processing has stopped due to error; restart */
-		ahci_restart_port(ap, status);
-
-		if (qc) {
-			qc->err_mask |= err_mask;
-			ata_qc_complete(qc);
-		}
+	rc = ata_qc_complete_multiple(ap, qc_active, NULL);
+	if (rc > 0)
+		return;
+	if (rc < 0) {
+		ehi->err_mask |= AC_ERR_HSM;
+		ehi->action |= ATA_EH_SOFTRESET;
+		ata_port_freeze(ap);
+		return;
 	}
 
-	return 1;
+	/* hmmm... a spurious interupt */
+
+	/* some devices send D2H reg with I bit set during NCQ command phase */
+	if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS)
+		return;
+
+	/* ignore interim PIO setup fis interrupts */
+	if (ata_tag_valid(ap->active_tag)) {
+		struct ata_queued_cmd *qc =
+			ata_qc_from_tag(ap, ap->active_tag);
+
+		if (qc && qc->tf.protocol == ATA_PROT_PIO &&
+		    (status & PORT_IRQ_PIOS_FIS))
+			return;
+	}
+
+	if (ata_ratelimit())
+		ata_port_printk(ap, KERN_INFO, "spurious interrupt "
+				"(irq_stat 0x%x active_tag %d sactive 0x%x)\n",
+				status, ap->active_tag, ap->sactive);
 }
 
 static void ahci_irq_clear(struct ata_port *ap)
@@ -882,7 +960,7 @@
 	/* TODO */
 }
 
-static irqreturn_t ahci_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t ahci_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
 	struct ata_host_set *host_set = dev_instance;
 	struct ahci_host_priv *hpriv;
@@ -911,14 +989,7 @@
 
 		ap = host_set->ports[i];
 		if (ap) {
-			struct ata_queued_cmd *qc;
-			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (!ahci_host_intr(ap, qc))
-				if (ata_ratelimit())
-					dev_printk(KERN_WARNING, host_set->dev,
-					  "unhandled interrupt on port %u\n",
-					  i);
-
+			ahci_host_intr(ap);
 			VPRINTK("port %u\n", i);
 		} else {
 			VPRINTK("port %u (no irq)\n", i);
@@ -935,7 +1006,7 @@
 		handled = 1;
 	}
 
-        spin_unlock(&host_set->lock);
+	spin_unlock(&host_set->lock);
 
 	VPRINTK("EXIT\n");
 
@@ -947,12 +1018,65 @@
 	struct ata_port *ap = qc->ap;
 	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
 
-	writel(1, port_mmio + PORT_CMD_ISSUE);
+	if (qc->tf.protocol == ATA_PROT_NCQ)
+		writel(1 << qc->tag, port_mmio + PORT_SCR_ACT);
+	writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
 	readl(port_mmio + PORT_CMD_ISSUE);	/* flush */
 
 	return 0;
 }
 
+static void ahci_freeze(struct ata_port *ap)
+{
+	void __iomem *mmio = ap->host_set->mmio_base;
+	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+
+	/* turn IRQ off */
+	writel(0, port_mmio + PORT_IRQ_MASK);
+}
+
+static void ahci_thaw(struct ata_port *ap)
+{
+	void __iomem *mmio = ap->host_set->mmio_base;
+	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+	u32 tmp;
+
+	/* clear IRQ */
+	tmp = readl(port_mmio + PORT_IRQ_STAT);
+	writel(tmp, port_mmio + PORT_IRQ_STAT);
+	writel(1 << ap->id, mmio + HOST_IRQ_STAT);
+
+	/* turn IRQ back on */
+	writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
+}
+
+static void ahci_error_handler(struct ata_port *ap)
+{
+	if (!(ap->flags & ATA_FLAG_FROZEN)) {
+		/* restart engine */
+		ahci_stop_engine(ap);
+		ahci_start_engine(ap);
+	}
+
+	/* perform recovery */
+	ata_do_eh(ap, ahci_prereset, ahci_softreset, ahci_hardreset,
+		  ahci_postreset);
+}
+
+static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (qc->flags & ATA_QCFLAG_FAILED)
+		qc->err_mask |= AC_ERR_OTHER;
+
+	if (qc->err_mask) {
+		/* make DMA engine forget about the failed command */
+		ahci_stop_engine(ap);
+		ahci_start_engine(ap);
+	}
+}
+
 static void ahci_setup_port(struct ata_ioports *port, unsigned long base,
 			    unsigned int port_idx)
 {
@@ -1097,9 +1221,6 @@
 			writel(tmp, port_mmio + PORT_IRQ_STAT);
 
 		writel(1 << i, mmio + HOST_IRQ_STAT);
-
-		/* set irq mask (enables interrupts) */
-		writel(DEF_PORT_IRQ, port_mmio + PORT_IRQ_MASK);
 	}
 
 	tmp = readl(mmio + HOST_CTL);
@@ -1197,6 +1318,8 @@
 
 	VPRINTK("ENTER\n");
 
+	WARN_ON(ATA_MAX_QUEUE > AHCI_MAX_CMDS);
+
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
@@ -1264,6 +1387,10 @@
 	if (rc)
 		goto err_out_hpriv;
 
+	if (!(probe_ent->host_flags & AHCI_FLAG_NO_NCQ) &&
+	    (hpriv->cap & HOST_CAP_NCQ))
+		probe_ent->host_flags |= ATA_FLAG_NCQ;
+
 	ahci_print_info(probe_ent);
 
 	/* FIXME: check ata_device_add return value */
@@ -1295,21 +1422,17 @@
 	struct device *dev = pci_dev_to_dev(pdev);
 	struct ata_host_set *host_set = dev_get_drvdata(dev);
 	struct ahci_host_priv *hpriv = host_set->private_data;
-	struct ata_port *ap;
 	unsigned int i;
 	int have_msi;
 
-	for (i = 0; i < host_set->n_ports; i++) {
-		ap = host_set->ports[i];
-
-		scsi_remove_host(ap->host);
-	}
+	for (i = 0; i < host_set->n_ports; i++)
+		ata_port_detach(host_set->ports[i]);
 
 	have_msi = hpriv->flags & AHCI_FLAG_MSI;
 	free_irq(host_set->irq, host_set);
 
 	for (i = 0; i < host_set->n_ports; i++) {
-		ap = host_set->ports[i];
+		struct ata_port *ap = host_set->ports[i];
 
 		ata_scsi_release(ap->host);
 		scsi_host_put(ap->host);
diff --git a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c
index 527efd3..c4d1723 100644
--- a/drivers/scsi/aic7xxx/aic7770.c
+++ b/drivers/scsi/aic7xxx/aic7770.c
@@ -107,7 +107,7 @@
 		ahc_aic7770_EISA_setup
 	}
 };
-const int ahc_num_aic7770_devs = NUM_ELEMENTS(aic7770_ident_table);
+const int ahc_num_aic7770_devs = ARRAY_SIZE(aic7770_ident_table);
 
 struct aic7770_identity *
 aic7770_find_device(uint32_t id)
diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h
index bb5166d..eb77456 100644
--- a/drivers/scsi/aic7xxx/aic79xx.h
+++ b/drivers/scsi/aic7xxx/aic79xx.h
@@ -68,8 +68,6 @@
 #define FALSE 0
 #endif
 
-#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array))
-
 #define ALL_CHANNELS '\0'
 #define ALL_TARGETS_MASK 0xFFFF
 #define INITIATOR_WILDCARD	(~0)
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 08771f6..801fc81 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -59,7 +59,7 @@
 	"aic7902",
 	"aic7901A"
 };
-static const u_int num_chip_names = NUM_ELEMENTS(ahd_chip_names);
+static const u_int num_chip_names = ARRAY_SIZE(ahd_chip_names);
 
 /*
  * Hardware error codes.
@@ -77,7 +77,7 @@
 	{ MPARERR,	"Scratch or SCB Memory Parity Error" },
 	{ CIOPARERR,	"CIOBUS Parity Error" },
 };
-static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors);
+static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors);
 
 static struct ahd_phase_table_entry ahd_phase_table[] =
 {
@@ -97,7 +97,7 @@
  * In most cases we only wish to itterate over real phases, so
  * exclude the last element from the count.
  */
-static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1;
+static const u_int num_phases = ARRAY_SIZE(ahd_phase_table) - 1;
 
 /* Our Sequencer Program */
 #include "aic79xx_seq.h"
@@ -7259,7 +7259,7 @@
 		return (wrap_qinfifonext - wrap_qinpos);
 	else
 		return (wrap_qinfifonext
-		      + NUM_ELEMENTS(ahd->qinfifo) - wrap_qinpos);
+		      + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos);
 }
 
 void
@@ -8619,7 +8619,7 @@
 	struct	patch *last_patch;
 	u_int	num_patches;
 
-	num_patches = sizeof(patches)/sizeof(struct patch);
+	num_patches = ARRAY_SIZE(patches);
 	last_patch = &patches[num_patches];
 	cur_patch = *start_patch;
 
@@ -9396,8 +9396,8 @@
 	} else {
 		u_int max_id;
 
-		max_id = (ahd->features & AHD_WIDE) ? 15 : 7;
-		if (ccb->ccb_h.target_id > max_id)
+		max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
+		if (ccb->ccb_h.target_id >= max_id)
 			return (CAM_TID_INVALID);
 
 		if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS)
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 66e4a47..e0ccdf3 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -916,7 +916,7 @@
 {
 
 	if ((instance >= 0)
-	 && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) {
+	 && (instance < ARRAY_SIZE(aic79xx_iocell_info))) {
 		uint8_t *iocell_info;
 
 		iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];
@@ -934,7 +934,7 @@
 	tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
 	printf("Setting Global Tags= %d\n", tags);
 
-	for (i = 0; i < NUM_ELEMENTS(aic79xx_tag_info); i++) {
+	for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) {
 		for (j = 0; j < AHD_NUM_TARGETS; j++) {
 			aic79xx_tag_info[i].tag_commands[j] = tags;
 		}
@@ -946,7 +946,7 @@
 {
 
 	if ((instance >= 0) && (targ >= 0)
-	 && (instance < NUM_ELEMENTS(aic79xx_tag_info))
+	 && (instance < ARRAY_SIZE(aic79xx_tag_info))
 	 && (targ < AHD_NUM_TARGETS)) {
 		aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
 		if (bootverbose)
@@ -1072,21 +1072,21 @@
 	end = strchr(s, '\0');
 
 	/*
-	 * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS
+	 * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE
 	 * will never be 0 in this case.
-	 */      
-	n = 0;  
+	 */
+	n = 0;
 
 	while ((p = strsep(&s, ",.")) != NULL) {
 		if (*p == '\0')
 			continue;
-		for (i = 0; i < NUM_ELEMENTS(options); i++) {
+		for (i = 0; i < ARRAY_SIZE(options); i++) {
 
 			n = strlen(options[i].name);
 			if (strncmp(options[i].name, p, n) == 0)
 				break;
 		}
-		if (i == NUM_ELEMENTS(options))
+		if (i == ARRAY_SIZE(options))
 			continue;
 
 		if (strncmp(p, "global_tag_depth", n) == 0) {
@@ -1294,7 +1294,7 @@
 	/*
 	 * Lookup and commit any modified IO Cell options.
 	 */
-	if (ahd->unit < NUM_ELEMENTS(aic79xx_iocell_info)) {
+	if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
 		struct ahd_linux_iocell_opts *iocell_opts;
 
 		iocell_opts = &aic79xx_iocell_info[ahd->unit];
@@ -1426,7 +1426,7 @@
 
 	tags = 0;
 	if ((ahd->user_discenable & devinfo->target_mask) != 0) {
-		if (ahd->unit >= NUM_ELEMENTS(aic79xx_tag_info)) {
+		if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) {
 
 			if (warned_user == 0) {
 				printf(KERN_WARNING
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index 757242e5..14850f3 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -201,7 +201,7 @@
 	}
 };
 
-const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table);
+const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table);
 		
 #define	DEVCONFIG		0x40
 #define		PCIXINITPAT	0x0000E000ul
diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c
index 39a2784..24fd59a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_proc.c
+++ b/drivers/scsi/aic7xxx/aic79xx_proc.c
@@ -76,11 +76,9 @@
 ahd_calc_syncsrate(u_int period_factor)
 {
 	int i;
-	int num_syncrates;
 
-	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
 	/* See if the period is in the "exception" table */
-	for (i = 0; i < num_syncrates; i++) {
+	for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) {
 
 		if (period_factor == scsi_syncrates[i].period_factor) {
 			/* Period in kHz */
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 91d294c..62ff8c3 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -69,8 +69,6 @@
 #define FALSE 0
 #endif
 
-#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array))
-
 #define ALL_CHANNELS '\0'
 #define ALL_TARGETS_MASK 0xFFFF
 #define INITIATOR_WILDCARD	(~0)
@@ -233,6 +231,7 @@
 	AHC_TARGETMODE	= 0x20000,	/* Has tested target mode support */
 	AHC_MULTIROLE	= 0x40000,	/* Space for two roles at a time */
 	AHC_REMOVABLE	= 0x80000,	/* Hot-Swap supported */
+	AHC_HVD		= 0x100000,	/* HVD rather than SE */
 	AHC_AIC7770_FE	= AHC_FENONE,
 	/*
 	 * The real 7850 does not support Ultra modes, but there are
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index d375669..93e4e409 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -68,7 +68,7 @@
 	"aic7892",
 	"aic7899"
 };
-static const u_int num_chip_names = NUM_ELEMENTS(ahc_chip_names);
+static const u_int num_chip_names = ARRAY_SIZE(ahc_chip_names);
 
 /*
  * Hardware error codes.
@@ -88,7 +88,7 @@
 	{ PCIERRSTAT,	"PCI Error detected" },
 	{ CIOPARERR,	"CIOBUS Parity Error" },
 };
-static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors);
+static const u_int num_errors = ARRAY_SIZE(ahc_hard_errors);
 
 static struct ahc_phase_table_entry ahc_phase_table[] =
 {
@@ -108,7 +108,7 @@
  * In most cases we only wish to itterate over real phases, so
  * exclude the last element from the count.
  */
-static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1;
+static const u_int num_phases = ARRAY_SIZE(ahc_phase_table) - 1;
 
 /*
  * Valid SCSIRATE values.  (p. 3-17)
@@ -6367,7 +6367,7 @@
 	struct	patch *last_patch;
 	u_int	num_patches;
 
-	num_patches = sizeof(patches)/sizeof(struct patch);
+	num_patches = ARRAY_SIZE(patches);
 	last_patch = &patches[num_patches];
 	cur_patch = *start_patch;
 
@@ -6774,8 +6774,8 @@
 	} else {
 		u_int max_id;
 
-		max_id = (ahc->features & AHC_WIDE) ? 15 : 7;
-		if (ccb->ccb_h.target_id > max_id)
+		max_id = (ahc->features & AHC_WIDE) ? 16 : 8;
+		if (ccb->ccb_h.target_id >= max_id)
 			return (CAM_TID_INVALID);
 
 		if (ccb->ccb_h.target_lun >= AHC_NUM_LUNS)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index 2c80167..debf3e2 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -886,7 +886,7 @@
 	tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
 	printf("Setting Global Tags= %d\n", tags);
 
-	for (i = 0; i < NUM_ELEMENTS(aic7xxx_tag_info); i++) {
+	for (i = 0; i < ARRAY_SIZE(aic7xxx_tag_info); i++) {
 		for (j = 0; j < AHC_NUM_TARGETS; j++) {
 			aic7xxx_tag_info[i].tag_commands[j] = tags;
 		}
@@ -898,7 +898,7 @@
 {
 
 	if ((instance >= 0) && (targ >= 0)
-	 && (instance < NUM_ELEMENTS(aic7xxx_tag_info))
+	 && (instance < ARRAY_SIZE(aic7xxx_tag_info))
 	 && (targ < AHC_NUM_TARGETS)) {
 		aic7xxx_tag_info[instance].tag_commands[targ] = value & 0xff;
 		if (bootverbose)
@@ -1020,7 +1020,7 @@
 	end = strchr(s, '\0');
 
 	/*
-	 * XXX ia64 gcc isn't smart enough to know that NUM_ELEMENTS
+	 * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE
 	 * will never be 0 in this case.
 	 */
 	n = 0;
@@ -1028,13 +1028,13 @@
 	while ((p = strsep(&s, ",.")) != NULL) {
 		if (*p == '\0')
 			continue;
-		for (i = 0; i < NUM_ELEMENTS(options); i++) {
+		for (i = 0; i < ARRAY_SIZE(options); i++) {
 
 			n = strlen(options[i].name);
 			if (strncmp(options[i].name, p, n) == 0)
 				break;
 		}
-		if (i == NUM_ELEMENTS(options))
+		if (i == ARRAY_SIZE(options))
 			continue;
 
 		if (strncmp(p, "global_tag_depth", n) == 0) {
@@ -1360,7 +1360,7 @@
 
 	tags = 0;
 	if ((ahc->user_discenable & devinfo->target_mask) != 0) {
-		if (ahc->unit >= NUM_ELEMENTS(aic7xxx_tag_info)) {
+		if (ahc->unit >= ARRAY_SIZE(aic7xxx_tag_info)) {
 			if (warned_user == 0) {
 
 				printf(KERN_WARNING
@@ -2537,6 +2537,22 @@
 }
 #endif
 
+static void ahc_linux_get_signalling(struct Scsi_Host *shost)
+{
+	struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
+	u8 mode = ahc_inb(ahc, SBLKCTL);
+
+	if (mode & ENAB40)
+		spi_signalling(shost) = SPI_SIGNAL_LVD;
+	else if (mode & ENAB20)
+		spi_signalling(shost) = 
+			ahc->features & AHC_HVD ?
+			SPI_SIGNAL_HVD :
+			SPI_SIGNAL_SE;
+	else
+		spi_signalling(shost) = SPI_SIGNAL_UNKNOWN;
+}
+
 static struct spi_function_template ahc_linux_transport_functions = {
 	.set_offset	= ahc_linux_set_offset,
 	.show_offset	= 1,
@@ -2552,6 +2568,7 @@
 	.set_qas	= ahc_linux_set_qas,
 	.show_qas	= 1,
 #endif
+	.get_signalling	= ahc_linux_get_signalling,
 };
 
 
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index 3adecef..63cab2d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -144,16 +144,22 @@
 static ahc_device_setup_t ahc_aic7860_setup;
 static ahc_device_setup_t ahc_apa1480_setup;
 static ahc_device_setup_t ahc_aic7870_setup;
+static ahc_device_setup_t ahc_aic7870h_setup;
 static ahc_device_setup_t ahc_aha394X_setup;
+static ahc_device_setup_t ahc_aha394Xh_setup;
 static ahc_device_setup_t ahc_aha494X_setup;
+static ahc_device_setup_t ahc_aha494Xh_setup;
 static ahc_device_setup_t ahc_aha398X_setup;
 static ahc_device_setup_t ahc_aic7880_setup;
+static ahc_device_setup_t ahc_aic7880h_setup;
 static ahc_device_setup_t ahc_aha2940Pro_setup;
 static ahc_device_setup_t ahc_aha394XU_setup;
+static ahc_device_setup_t ahc_aha394XUh_setup;
 static ahc_device_setup_t ahc_aha398XU_setup;
 static ahc_device_setup_t ahc_aic7890_setup;
 static ahc_device_setup_t ahc_aic7892_setup;
 static ahc_device_setup_t ahc_aic7895_setup;
+static ahc_device_setup_t ahc_aic7895h_setup;
 static ahc_device_setup_t ahc_aic7896_setup;
 static ahc_device_setup_t ahc_aic7899_setup;
 static ahc_device_setup_t ahc_aha29160C_setup;
@@ -225,19 +231,19 @@
 		ID_AHA_2944,
 		ID_ALL_MASK,
 		"Adaptec 2944 SCSI adapter",
-		ahc_aic7870_setup
+		ahc_aic7870h_setup
 	},
 	{
 		ID_AHA_3944,
 		ID_ALL_MASK,
 		"Adaptec 3944 SCSI adapter",
-		ahc_aha394X_setup
+		ahc_aha394Xh_setup
 	},
 	{
 		ID_AHA_4944,
 		ID_ALL_MASK,
 		"Adaptec 4944 SCSI adapter",
-		ahc_aha494X_setup
+		ahc_aha494Xh_setup
 	},
 	/* aic7880 based controllers */
 	{
@@ -256,13 +262,13 @@
 		ID_AHA_2944U & ID_DEV_VENDOR_MASK,
 		ID_DEV_VENDOR_MASK,
 		"Adaptec 2944 Ultra SCSI adapter",
-		ahc_aic7880_setup
+		ahc_aic7880h_setup
 	},
 	{
 		ID_AHA_3944U & ID_DEV_VENDOR_MASK,
 		ID_DEV_VENDOR_MASK,
 		"Adaptec 3944 Ultra SCSI adapter",
-		ahc_aha394XU_setup
+		ahc_aha394XUh_setup
 	},
 	{
 		ID_AHA_398XU & ID_DEV_VENDOR_MASK,
@@ -278,7 +284,7 @@
 		ID_AHA_4944U & ID_DEV_VENDOR_MASK,
 		ID_DEV_VENDOR_MASK,
 		"Adaptec 4944 Ultra SCSI adapter",
-		ahc_aic7880_setup
+		ahc_aic7880h_setup
 	},
 	{
 		ID_AHA_2930U & ID_DEV_VENDOR_MASK,
@@ -414,7 +420,7 @@
 		ID_AHA_3944AU,
 		ID_ALL_MASK,
 		"Adaptec 3944A Ultra SCSI adapter",
-		ahc_aic7895_setup
+		ahc_aic7895h_setup
 	},
 	{
 		ID_AIC7895_ARO,
@@ -553,7 +559,7 @@
 	}
 };
 
-const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
+const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table);
 		
 #define AHC_394X_SLOT_CHANNEL_A	4
 #define AHC_394X_SLOT_CHANNEL_B	5
@@ -2121,6 +2127,16 @@
 }
 
 static int
+ahc_aic7870h_setup(struct ahc_softc *ahc)
+{
+	int error = ahc_aic7870_setup(ahc);
+
+	ahc->features |= AHC_HVD;
+
+	return error;
+}
+
+static int
 ahc_aha394X_setup(struct ahc_softc *ahc)
 {
 	int error;
@@ -2132,6 +2148,16 @@
 }
 
 static int
+ahc_aha394Xh_setup(struct ahc_softc *ahc)
+{
+	int error = ahc_aha394X_setup(ahc);
+
+	ahc->features |= AHC_HVD;
+
+	return error;
+}
+
+static int
 ahc_aha398X_setup(struct ahc_softc *ahc)
 {
 	int error;
@@ -2154,6 +2180,16 @@
 }
 
 static int
+ahc_aha494Xh_setup(struct ahc_softc *ahc)
+{
+	int error = ahc_aha494X_setup(ahc);
+
+	ahc->features |= AHC_HVD;
+
+	return error;
+}
+
+static int
 ahc_aic7880_setup(struct ahc_softc *ahc)
 {
 	ahc_dev_softc_t pci;
@@ -2175,6 +2211,17 @@
 }
 
 static int
+ahc_aic7880h_setup(struct ahc_softc *ahc)
+{
+	int error = ahc_aic7880_setup(ahc);
+
+	ahc->features |= AHC_HVD;
+
+	return error;
+}
+
+
+static int
 ahc_aha2940Pro_setup(struct ahc_softc *ahc)
 {
 
@@ -2194,6 +2241,16 @@
 }
 
 static int
+ahc_aha394XUh_setup(struct ahc_softc *ahc)
+{
+	int error = ahc_aha394XU_setup(ahc);
+
+	ahc->features |= AHC_HVD;
+
+	return error;
+}
+
+static int
 ahc_aha398XU_setup(struct ahc_softc *ahc)
 {
 	int error;
@@ -2292,6 +2349,16 @@
 }
 
 static int
+ahc_aic7895h_setup(struct ahc_softc *ahc)
+{
+	int error = ahc_aic7895_setup(ahc);
+
+	ahc->features |= AHC_HVD;
+
+	return error;
+}
+
+static int
 ahc_aic7896_setup(struct ahc_softc *ahc)
 {
 	ahc_dev_softc_t pci;
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index 04a3506..5914b4a 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -77,11 +77,9 @@
 ahc_calc_syncsrate(u_int period_factor)
 {
 	int i;
-	int num_syncrates;
 
-	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
 	/* See if the period is in the "exception" table */
-	for (i = 0; i < num_syncrates; i++) {
+	for (i = 0; i < ARRAY_SIZE(scsi_syncrates); i++) {
 
 		if (period_factor == scsi_syncrates[i].period_factor) {
 			/* Period in kHz */
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 770f164..5dba1c6 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -1565,7 +1565,7 @@
   struct sequencer_patch *last_patch;
   int num_patches;
 
-  num_patches = sizeof(sequencer_patches)/sizeof(struct sequencer_patch);
+  num_patches = ARRAY_SIZE(sequencer_patches);
   last_patch = &sequencer_patches[num_patches];
   cur_patch = *start_patch;
 
diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c
index b10750b..8caa590 100644
--- a/drivers/scsi/arm/queue.c
+++ b/drivers/scsi/arm/queue.c
@@ -118,8 +118,7 @@
 	list_del(l);
 
 	q = list_entry(l, QE_t, list);
-	if (BAD_MAGIC(q, QUEUE_MAGIC_FREE))
-		BUG();
+	BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_FREE));
 
 	SET_MAGIC(q, QUEUE_MAGIC_USED);
 	q->SCpnt = SCpnt;
@@ -144,8 +143,7 @@
 	 */
 	list_del(ent);
 	q = list_entry(ent, QE_t, list);
-	if (BAD_MAGIC(q, QUEUE_MAGIC_USED))
-		BUG();
+	BUG_ON(BAD_MAGIC(q, QUEUE_MAGIC_USED));
 
 	SET_MAGIC(q, QUEUE_MAGIC_FREE);
 	list_add(ent, &queue->free);
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 6dc8814..94b1261 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -93,7 +93,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"ata_piix"
-#define DRV_VERSION	"1.05"
+#define DRV_VERSION	"2.00"
 
 enum {
 	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
@@ -146,11 +146,10 @@
 
 static int piix_init_one (struct pci_dev *pdev,
 				    const struct pci_device_id *ent);
-
-static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes);
-static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
 static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
+static void piix_pata_error_handler(struct ata_port *ap);
+static void piix_sata_error_handler(struct ata_port *ap);
 
 static unsigned int in_module_init = 1;
 
@@ -159,6 +158,7 @@
 	{ 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata },
 	{ 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
 	{ 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
+	{ 0x8086, 0x27df, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata },
 #endif
 
 	/* NOTE: The following PCI ids must be kept in sync with the
@@ -218,6 +218,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 	.resume			= ata_scsi_device_resume,
 	.suspend		= ata_scsi_device_suspend,
@@ -227,6 +228,7 @@
 	.port_disable		= ata_port_disable,
 	.set_piomode		= piix_set_piomode,
 	.set_dmamode		= piix_set_dmamode,
+	.mode_filter		= ata_pci_default_filter,
 
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
@@ -234,16 +236,18 @@
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
 
-	.probe_reset		= piix_pata_probe_reset,
-
 	.bmdma_setup		= ata_bmdma_setup,
 	.bmdma_start		= ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= piix_pata_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
@@ -262,16 +266,18 @@
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
 
-	.probe_reset		= piix_sata_probe_reset,
-
 	.bmdma_setup		= ata_bmdma_setup,
 	.bmdma_start		= ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= piix_sata_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
@@ -455,59 +461,51 @@
 }
 
 /**
- *	piix_pata_probeinit - probeinit for PATA host controller
+ *	piix_pata_prereset - prereset for PATA host controller
  *	@ap: Target port
  *
- *	Probeinit including cable detection.
+ *	Prereset including cable detection.
  *
  *	LOCKING:
  *	None (inherited from caller).
  */
-static void piix_pata_probeinit(struct ata_port *ap)
-{
-	piix_pata_cbl_detect(ap);
-	ata_std_probeinit(ap);
-}
-
-/**
- *	piix_pata_probe_reset - Perform reset on PATA port and classify
- *	@ap: Port to reset
- *	@classes: Resulting classes of attached devices
- *
- *	Reset PATA phy and classify attached devices.
- *
- *	LOCKING:
- *	None (inherited from caller).
- */
-static int piix_pata_probe_reset(struct ata_port *ap, unsigned int *classes)
+static int piix_pata_prereset(struct ata_port *ap)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 
 	if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) {
-		printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
+		ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n");
+		ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
 		return 0;
 	}
 
-	return ata_drive_probe_reset(ap, piix_pata_probeinit,
-				     ata_std_softreset, NULL,
-				     ata_std_postreset, classes);
+	piix_pata_cbl_detect(ap);
+
+	return ata_std_prereset(ap);
+}
+
+static void piix_pata_error_handler(struct ata_port *ap)
+{
+	ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL,
+			   ata_std_postreset);
 }
 
 /**
- *	piix_sata_probe - Probe PCI device for present SATA devices
- *	@ap: Port associated with the PCI device we wish to probe
+ *	piix_sata_prereset - prereset for SATA host controller
+ *	@ap: Target port
  *
  *	Reads and configures SATA PCI device's PCI config register
  *	Port Configuration and Status (PCS) to determine port and
- *	device availability.
+ *	device availability.  Return -ENODEV to skip reset if no
+ *	device is present.
  *
  *	LOCKING:
  *	None (inherited from caller).
  *
  *	RETURNS:
- *	Mask of avaliable devices on the port.
+ *	0 if device is present, -ENODEV otherwise.
  */
-static unsigned int piix_sata_probe (struct ata_port *ap)
+static int piix_sata_prereset(struct ata_port *ap)
 {
 	struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
 	const unsigned int *map = ap->host_set->private_data;
@@ -549,29 +547,19 @@
 	DPRINTK("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n",
 		ap->id, pcs, present_mask);
 
-	return present_mask;
-}
-
-/**
- *	piix_sata_probe_reset - Perform reset on SATA port and classify
- *	@ap: Port to reset
- *	@classes: Resulting classes of attached devices
- *
- *	Reset SATA phy and classify attached devices.
- *
- *	LOCKING:
- *	None (inherited from caller).
- */
-static int piix_sata_probe_reset(struct ata_port *ap, unsigned int *classes)
-{
-	if (!piix_sata_probe(ap)) {
-		printk(KERN_INFO "ata%u: SATA port has no device.\n", ap->id);
+	if (!present_mask) {
+		ata_port_printk(ap, KERN_INFO, "SATA port has no device.\n");
+		ap->eh_context.i.action &= ~ATA_EH_RESET_MASK;
 		return 0;
 	}
 
-	return ata_drive_probe_reset(ap, ata_std_probeinit,
-				     ata_std_softreset, NULL,
-				     ata_std_postreset, classes);
+	return ata_std_prereset(ap);
+}
+
+static void piix_sata_error_handler(struct ata_port *ap)
+{
+	ata_bmdma_drive_eh(ap, piix_sata_prereset, ata_std_softreset, NULL,
+			   ata_std_postreset);
 }
 
 /**
@@ -760,15 +748,15 @@
 		pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
 		pci_read_config_word(pdev, 0x41, &cfg);
 		/* Only on the original revision: IDE DMA can hang */
-		if(rev == 0x00)
+		if (rev == 0x00)
 			no_piix_dma = 1;
 		/* On all revisions below 5 PXB bus lock must be disabled for IDE */
-		else if(cfg & (1<<14) && rev < 5)
+		else if (cfg & (1<<14) && rev < 5)
 			no_piix_dma = 2;
 	}
-	if(no_piix_dma)
+	if (no_piix_dma)
 		dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n");
-	if(no_piix_dma == 2)
+	if (no_piix_dma == 2)
 		dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n");
 	return no_piix_dma;
 }
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index a198d86..3ee4d4d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -473,7 +473,7 @@
 			 */
 			if (workreq->use_sg) {
 				pci_unmap_sg(dev->pdev,
-					(struct scatterlist *)workreq->buffer,
+					(struct scatterlist *)workreq->request_buffer,
 					workreq->use_sg,
 					workreq->sc_data_direction);
 			} else if (workreq->request_bufflen &&
@@ -3047,7 +3047,7 @@
 		if (atp_dev.chip_ver == 4)
 			shpnt->max_id = 16;
 		else		
-			shpnt->max_id = 7;
+			shpnt->max_id = 8;
 		shpnt->this_id = host_id;
 		shpnt->unique_id = base_io;
 		shpnt->io_port = base_io;
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 30a3353..d92d504 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -13,9 +13,9 @@
 #include <linux/kernel.h>
 
 #include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
-#include <scsi/scsi_request.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dbg.h>
 
@@ -114,8 +114,7 @@
 	{0xd, "Report supported task management functions"},
 	{0xe, "Report priority"},
 };
-#define MAINT_IN_SZ \
-        (int)(sizeof(maint_in_arr) / sizeof(maint_in_arr[0]))
+#define MAINT_IN_SZ ARRAY_SIZE(maint_in_arr)
 
 static const struct value_name_pair maint_out_arr[] = {
 	{0x6, "Set device identifier"},
@@ -123,34 +122,29 @@
 	{0xb, "Change aliases"},
 	{0xe, "Set priority"},
 };
-#define MAINT_OUT_SZ \
-        (int)(sizeof(maint_out_arr) / sizeof(maint_out_arr[0]))
+#define MAINT_OUT_SZ ARRAY_SIZE(maint_out_arr)
 
 static const struct value_name_pair serv_in12_arr[] = {
 	{0x1, "Read media serial number"},
 };
-#define SERV_IN12_SZ  \
-        (int)(sizeof(serv_in12_arr) / sizeof(serv_in12_arr[0]))
+#define SERV_IN12_SZ ARRAY_SIZE(serv_in12_arr)
 
 static const struct value_name_pair serv_out12_arr[] = {
 	{-1, "dummy entry"},
 };
-#define SERV_OUT12_SZ \
-        (int)(sizeof(serv_out12_arr) / sizeof(serv_in12_arr[0]))
+#define SERV_OUT12_SZ ARRAY_SIZE(serv_out12_arr)
 
 static const struct value_name_pair serv_in16_arr[] = {
 	{0x10, "Read capacity(16)"},
 	{0x11, "Read long(16)"},
 };
-#define SERV_IN16_SZ  \
-        (int)(sizeof(serv_in16_arr) / sizeof(serv_in16_arr[0]))
+#define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr)
 
 static const struct value_name_pair serv_out16_arr[] = {
 	{0x11, "Write long(16)"},
 	{0x1f, "Notify data transfer device(16)"},
 };
-#define SERV_OUT16_SZ \
-        (int)(sizeof(serv_out16_arr) / sizeof(serv_in16_arr[0]))
+#define SERV_OUT16_SZ ARRAY_SIZE(serv_out16_arr)
 
 static const struct value_name_pair variable_length_arr[] = {
 	{0x1, "Rebuild(32)"},
@@ -190,8 +184,7 @@
 	{0x8f7e, "Perform SCSI command (osd)"},
 	{0x8f7f, "Perform task management function (osd)"},
 };
-#define VARIABLE_LENGTH_SZ \
-        (int)(sizeof(variable_length_arr) / sizeof(variable_length_arr[0]))
+#define VARIABLE_LENGTH_SZ ARRAY_SIZE(variable_length_arr)
 
 static const char * get_sa_name(const struct value_name_pair * arr,
 			        int arr_sz, int service_action)
@@ -1268,16 +1261,6 @@
 }
 EXPORT_SYMBOL(scsi_print_sense);
 
-void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
-{
-	const char *name = devclass;
-
-	if (sreq->sr_request->rq_disk)
-		name = sreq->sr_request->rq_disk->disk_name;
-	__scsi_print_sense(name, sreq->sr_sense_buffer, SCSI_SENSE_BUFFERSIZE);
-}
-EXPORT_SYMBOL(scsi_print_req_sense);
-
 void scsi_print_command(struct scsi_cmnd *cmd)
 {
 	/* Assume appended output (i.e. not at start of line) */
@@ -1290,10 +1273,10 @@
 #ifdef CONFIG_SCSI_CONSTANTS
 
 static const char * const hostbyte_table[]={
-"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", 
+"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET",
 "DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
 "DID_PASSTHROUGH", "DID_SOFT_ERROR", "DID_IMM_RETRY"};
-#define NUM_HOSTBYTE_STRS (sizeof(hostbyte_table) / sizeof(const char *))
+#define NUM_HOSTBYTE_STRS ARRAY_SIZE(hostbyte_table)
 
 void scsi_print_hostbyte(int scsiresult)
 {
@@ -1303,7 +1286,7 @@
 	if (hb < NUM_HOSTBYTE_STRS)
 		printk("(%s) ", hostbyte_table[hb]);
 	else
-		printk("is invalid "); 
+		printk("is invalid ");
 }
 #else
 void scsi_print_hostbyte(int scsiresult)
@@ -1315,14 +1298,14 @@
 #ifdef CONFIG_SCSI_CONSTANTS
 
 static const char * const driverbyte_table[]={
-"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR", 
+"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR",
 "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
-#define NUM_DRIVERBYTE_STRS (sizeof(driverbyte_table) / sizeof(const char *))
+#define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table)
 
 static const char * const driversuggest_table[]={"SUGGEST_OK",
 "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
 "SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
-#define NUM_SUGGEST_STRS (sizeof(driversuggest_table) / sizeof(const char *))
+#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table)
 
 void scsi_print_driverbyte(int scsiresult)
 {
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index cbf8252..58b0748 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -230,13 +230,12 @@
 	struct scsi_cmnd *cmd;
 
 	struct SGentry *segment_x;	/* Linear array of hw sg entries (up to 64 entries) */
-	u32 sg_bus_addr;	        /* Bus address of sg list (ie, of segment_x) */
+	dma_addr_t sg_bus_addr;	        /* Bus address of sg list (ie, of segment_x) */
 
 	u8 sg_count;			/* No of HW sg entries for this request */
 	u8 sg_index;			/* Index of HW sg entry for this request */
-	u32 total_xfer_length;		/* Total number of bytes remaining to be transfered */
-	unsigned char *virt_addr;	/* Virtual address of current transfer position */
-
+	size_t total_xfer_length;	/* Total number of bytes remaining to be transfered */
+	size_t request_length;		/* Total number of bytes in this request */
 	/*
 	 * The sense buffer handling function, request_sense, uses
 	 * the first hw sg entry (segment_x[0]) and the transfer
@@ -246,8 +245,7 @@
 	 * total_xfer_length in xferred. These values are restored in
 	 * pci_unmap_srb_sense. This is the only place xferred is used.
 	 */
-	unsigned char *virt_addr_req;	/* Saved virtual address of the request buffer */
-	u32 xferred;		        /* Saved copy of total_xfer_length */
+	size_t xferred;		        /* Saved copy of total_xfer_length */
 
 	u16 state;
 
@@ -977,17 +975,6 @@
 	}
 }
 
-static inline void pio_trigger(void)
-{
-	static int feedback_requested;
-
-	if (!feedback_requested) {
-		feedback_requested = 1;
-		printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> "
-		       "to help improve support for your system.\n", __FILE__);
-	}
-}
-
 /* Prepare SRB for being sent to Device DCB w/ command *cmd */
 static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb)
@@ -1001,7 +988,6 @@
 	srb->sg_count = 0;
 	srb->total_xfer_length = 0;
 	srb->sg_bus_addr = 0;
-	srb->virt_addr = NULL;
 	srb->sg_index = 0;
 	srb->adapter_status = 0;
 	srb->target_status = 0;
@@ -1032,7 +1018,6 @@
 			reqlen, cmd->request_buffer, cmd->use_sg,
 			srb->sg_count);
 
-		srb->virt_addr = page_address(sl->page);
 		for (i = 0; i < srb->sg_count; i++) {
 			u32 busaddr = (u32)sg_dma_address(&sl[i]);
 			u32 seglen = (u32)sl[i].length;
@@ -1077,12 +1062,14 @@
 			srb->total_xfer_length++;
 
 		srb->segment_x[0].length = srb->total_xfer_length;
-		srb->virt_addr = cmd->request_buffer;
+
 		dprintkdbg(DBG_0,
 			"build_srb: [1] len=%d buf=%p use_sg=%d map=%08x\n",
 			srb->total_xfer_length, cmd->request_buffer,
 			cmd->use_sg, srb->segment_x[0].address);
 	}
+
+	srb->request_length = srb->total_xfer_length;
 }
 
 
@@ -1414,10 +1401,10 @@
 	}
 	srb = find_cmd(cmd, &dcb->srb_going_list);
 	if (srb) {
-		dprintkl(KERN_DEBUG, "eh_abort: Command in progress");
+		dprintkl(KERN_DEBUG, "eh_abort: Command in progress\n");
 		/* XXX: Should abort the command here */
 	} else {
-		dprintkl(KERN_DEBUG, "eh_abort: Command not found");
+		dprintkl(KERN_DEBUG, "eh_abort: Command not found\n");
 	}
 	return FAILED;
 }
@@ -1976,14 +1963,11 @@
 
 /*
  * Compute the next Scatter Gather list index and adjust its length
- * and address if necessary; also compute virt_addr
+ * and address if necessary
  */
 static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
 {
 	u8 idx;
-	struct scatterlist *sg;
-	struct scsi_cmnd *cmd = srb->cmd;
-	int segment = cmd->use_sg;
 	u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
 	struct SGentry *psge = srb->segment_x + srb->sg_index;
 
@@ -2016,29 +2000,6 @@
 		psge++;
 	}
 	sg_verify_length(srb);
-
-	/* we need the corresponding virtual address */
-	if (!segment || (srb->flag & AUTO_REQSENSE)) {
-		srb->virt_addr += xferred;
-		return;
-	}
-
-	/* We have to walk the scatterlist to find it */
-	sg = (struct scatterlist *)cmd->request_buffer;
-	while (segment--) {
-		unsigned long mask =
-		    ~((unsigned long)sg->length - 1) & PAGE_MASK;
-		if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
-			srb->virt_addr = (page_address(sg->page)
-					   + psge->address -
-					   (psge->address & PAGE_MASK));
-			return;
-		}
-		++sg;
-	}
-
-	dprintkl(KERN_ERR, "sg_update_list: sg_to_virt failed\n");
-	srb->virt_addr = NULL;
 }
 
 
@@ -2050,15 +2011,7 @@
  */
 static void sg_subtract_one(struct ScsiReqBlk *srb)
 {
-	srb->total_xfer_length--;
-	srb->segment_x[srb->sg_index].length--;
-	if (srb->total_xfer_length &&
-	    !srb->segment_x[srb->sg_index].length) {
-		if (debug_enabled(DBG_PIO))
-			printk(" (next segment)");
-		srb->sg_index++;
-		sg_update_list(srb, srb->total_xfer_length);
-	}
+	sg_update_list(srb, srb->total_xfer_length - 1);
 }
 
 
@@ -2118,7 +2071,7 @@
 	 * If we need more data, the DMA SG list will be freshly set up, anyway
 	 */
 	dprintkdbg(DBG_PIO, "data_out_phase0: "
-		"DMA{fifcnt=0x%02x fifostat=0x%02x} "
+		"DMA{fifocnt=0x%02x fifostat=0x%02x} "
 		"SCSI{fifocnt=0x%02x cnt=0x%06x status=0x%04x} total=0x%06x\n",
 		DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT),
 		DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT),
@@ -2239,12 +2192,11 @@
 	data_io_transfer(acb, srb, XFERDATAOUT);
 }
 
-
 static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
 		u16 *pscsi_status)
 {
 	u16 scsi_status = *pscsi_status;
-	u32 d_left_counter = 0;
+
 	dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n",
 		srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun);
 
@@ -2262,6 +2214,9 @@
 	 * seem to be a bad idea, actually.
 	 */
 	if (!(srb->state & SRB_XFERPAD)) {
+		u32 d_left_counter;
+		unsigned int sc, fc;
+
 		if (scsi_status & PARITYERROR) {
 			dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) "
 				"Parity Error\n", srb->cmd->pid);
@@ -2298,18 +2253,19 @@
 				DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT));
 		}
 		/* Now: Check remainig data: The SCSI counters should tell us ... */
-		d_left_counter = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER)
-		    + ((DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f)
+		sc = DC395x_read32(acb, TRM_S1040_SCSI_COUNTER);
+		fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT);
+		d_left_counter = sc + ((fc & 0x1f)
 		       << ((srb->dcb->sync_period & WIDE_SYNC) ? 1 :
 			   0));
 		dprintkdbg(DBG_KG, "data_in_phase0: "
 			"SCSI{fifocnt=0x%02x%s ctr=0x%08x} "
 			"DMA{fifocnt=0x%02x fifostat=0x%02x ctr=0x%08x} "
 			"Remain{totxfer=%i scsi_fifo+ctr=%i}\n",
-			DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT),
+			fc,
 			(srb->dcb->sync_period & WIDE_SYNC) ? "words" : "bytes",
-			DC395x_read32(acb, TRM_S1040_SCSI_COUNTER),
-			DC395x_read8(acb, TRM_S1040_DMA_FIFOCNT),
+			sc,
+			fc,
 			DC395x_read8(acb, TRM_S1040_DMA_FIFOSTAT),
 			DC395x_read32(acb, TRM_S1040_DMA_CXCNT),
 			srb->total_xfer_length, d_left_counter);
@@ -2317,40 +2273,79 @@
 		/* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */
 		if (d_left_counter
 		    && srb->total_xfer_length <= DC395x_LASTPIO) {
+			size_t left_io = srb->total_xfer_length;
+
 			/*u32 addr = (srb->segment_x[srb->sg_index].address); */
 			/*sg_update_list (srb, d_left_counter); */
-			dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) to "
-				"%p for remaining %i bytes:",
-				DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & 0x1f,
+			dprintkdbg(DBG_PIO, "data_in_phase0: PIO (%i %s) "
+				   "for remaining %i bytes:",
+				fc & 0x1f,
 				(srb->dcb->sync_period & WIDE_SYNC) ?
 				    "words" : "bytes",
-				srb->virt_addr,
 				srb->total_xfer_length);
 			if (srb->dcb->sync_period & WIDE_SYNC)
 				DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
 					      CFG2_WIDEFIFO);
-			while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) {
-				u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
-				pio_trigger();
-				*(srb->virt_addr)++ = byte;
-				if (debug_enabled(DBG_PIO))
-					printk(" %02x", byte);
-				d_left_counter--;
-				sg_subtract_one(srb);
-			}
-			if (srb->dcb->sync_period & WIDE_SYNC) {
-#if 1
-                /* Read the last byte ... */
-				if (srb->total_xfer_length > 0) {
-					u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
-					pio_trigger();
-					*(srb->virt_addr)++ = byte;
-					srb->total_xfer_length--;
+			while (left_io) {
+				unsigned char *virt, *base = NULL;
+				unsigned long flags = 0;
+				size_t len = left_io;
+
+				if (srb->cmd->use_sg) {
+					size_t offset = srb->request_length - left_io;
+					local_irq_save(flags);
+					/* Assumption: it's inside one page as it's at most 4 bytes and
+					   I just assume it's on a 4-byte boundary */
+					base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
+								     srb->sg_count, &offset, &len);
+					virt = base + offset;
+				} else {
+					virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
+					len = left_io;
+				}
+				left_io -= len;
+
+				while (len) {
+					u8 byte;
+					byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
+					*virt++ = byte;
+
 					if (debug_enabled(DBG_PIO))
 						printk(" %02x", byte);
+
+					d_left_counter--;
+					sg_subtract_one(srb);
+
+					len--;
+
+					fc = DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT);
+
+					if (fc == 0x40) {
+						left_io = 0;
+						break;
+					}
 				}
-#endif
-				DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
+
+				WARN_ON((fc != 0x40) == !d_left_counter);
+
+				if (fc == 0x40 && (srb->dcb->sync_period & WIDE_SYNC)) {
+					/* Read the last byte ... */
+					if (srb->total_xfer_length > 0) {
+						u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
+
+						*virt++ = byte;
+						srb->total_xfer_length--;
+						if (debug_enabled(DBG_PIO))
+							printk(" %02x", byte);
+					}
+
+					DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
+				}
+
+				if (srb->cmd->use_sg) {
+					scsi_kunmap_atomic_sg(base);
+					local_irq_restore(flags);
+				}
 			}
 			/*printk(" %08x", *(u32*)(bus_to_virt (addr))); */
 			/*srb->total_xfer_length = 0; */
@@ -2509,22 +2504,43 @@
 				      SCMD_FIFO_IN);
 		} else {	/* write */
 			int ln = srb->total_xfer_length;
+			size_t left_io = srb->total_xfer_length;
+
 			if (srb->dcb->sync_period & WIDE_SYNC)
 				DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
 				     CFG2_WIDEFIFO);
-			dprintkdbg(DBG_PIO,
-				"data_io_transfer: PIO %i bytes from %p:",
-				srb->total_xfer_length, srb->virt_addr);
 
-			while (srb->total_xfer_length) {
-				if (debug_enabled(DBG_PIO))
-					printk(" %02x", (unsigned char) *(srb->virt_addr));
+			while (left_io) {
+				unsigned char *virt, *base = NULL;
+				unsigned long flags = 0;
+				size_t len = left_io;
 
-				pio_trigger();
-				DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 
-				     *(srb->virt_addr)++);
+				if (srb->cmd->use_sg) {
+					size_t offset = srb->request_length - left_io;
+					local_irq_save(flags);
+					/* Again, max 4 bytes */
+					base = scsi_kmap_atomic_sg((struct scatterlist *)srb->cmd->request_buffer,
+								     srb->sg_count, &offset, &len);
+					virt = base + offset;
+				} else {
+					virt = srb->cmd->request_buffer + srb->cmd->request_bufflen - left_io;
+					len = left_io;
+				}
+				left_io -= len;
 
-				sg_subtract_one(srb);
+				while (len--) {
+					if (debug_enabled(DBG_PIO))
+						printk(" %02x", *virt);
+
+					DC395x_write8(acb, TRM_S1040_SCSI_FIFO, *virt++);
+
+					sg_subtract_one(srb);
+				}
+
+				if (srb->cmd->use_sg) {
+					scsi_kunmap_atomic_sg(base);
+					local_irq_restore(flags);
+				}
 			}
 			if (srb->dcb->sync_period & WIDE_SYNC) {
 				if (ln % 2) {
@@ -3319,7 +3335,6 @@
 	    srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].address;
 	srb->segment_x[0].length =
 	    srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1].length;
-	srb->virt_addr = srb->virt_addr_req;
 }
 
 
@@ -3332,21 +3347,14 @@
 {
 	u8 tempcnt, status;
 	struct scsi_cmnd *cmd = srb->cmd;
-	struct ScsiInqData *ptr;
 	enum dma_data_direction dir = cmd->sc_data_direction;
-
-	if (cmd->use_sg) {
-		struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
-		ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
-	} else {
-		ptr = (struct ScsiInqData *)(cmd->request_buffer);
-	}
+	int ckc_only = 1;
 
 	dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid,
 		srb->cmd->device->id, srb->cmd->device->lun);
-	dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p addr=%p\n",
+	dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n",
 		srb, cmd->use_sg, srb->sg_index, srb->sg_count,
-		cmd->request_buffer, ptr);
+		cmd->request_buffer);
 	status = srb->target_status;
 	if (srb->flag & AUTO_REQSENSE) {
 		dprintkdbg(DBG_0, "srb_done: AUTO_REQSENSE1\n");
@@ -3485,29 +3493,47 @@
 					    srb->segment_x[0].address,
 					    cmd->request_bufflen, dir);
 	}
-
-	if ((cmd->result & RES_DID) == 0 && cmd->cmnd[0] == INQUIRY
-	    && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8
-	    && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
-		dcb->inquiry7 = ptr->Flags;
+	ckc_only = 0;
 /* Check Error Conditions */
       ckc_e:
 
+	if (cmd->cmnd[0] == INQUIRY) {
+		unsigned char *base = NULL;
+		struct ScsiInqData *ptr;
+		unsigned long flags = 0;
+
+		if (cmd->use_sg) {
+			struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
+			size_t offset = 0, len = sizeof(struct ScsiInqData);
+
+			local_irq_save(flags);
+			base = scsi_kmap_atomic_sg(sg, cmd->use_sg, &offset, &len);
+			ptr = (struct ScsiInqData *)(base + offset);
+		} else
+			ptr = (struct ScsiInqData *)(cmd->request_buffer);
+
+		if (!ckc_only && (cmd->result & RES_DID) == 0
+		    && cmd->cmnd[2] == 0 && cmd->request_bufflen >= 8
+		    && dir != PCI_DMA_NONE && ptr && (ptr->Vers & 0x07) >= 2)
+			dcb->inquiry7 = ptr->Flags;
+
 	/*if( srb->cmd->cmnd[0] == INQUIRY && */
 	/*  (host_byte(cmd->result) == DID_OK || status_byte(cmd->result) & CHECK_CONDITION) ) */
-	if (cmd->cmnd[0] == INQUIRY && (cmd->result == (DID_OK << 16)
-					 || status_byte(cmd->
-							result) &
-					 CHECK_CONDITION)) {
-
-		if (!dcb->init_tcq_flag) {
-			add_dev(acb, dcb, ptr);
-			dcb->init_tcq_flag = 1;
+		if ((cmd->result == (DID_OK << 16)
+		     || status_byte(cmd->result) &
+		     CHECK_CONDITION)) {
+			if (!dcb->init_tcq_flag) {
+				add_dev(acb, dcb, ptr);
+				dcb->init_tcq_flag = 1;
+			}
 		}
 
+		if (cmd->use_sg) {
+			scsi_kunmap_atomic_sg(base);
+			local_irq_restore(flags);
+		}
 	}
 
-
 	/* Here is the info for Doug Gilbert's sg3 ... */
 	cmd->resid = srb->total_xfer_length;
 	/* This may be interpreted by sb. or not ... */
@@ -3713,8 +3739,6 @@
 	srb->xferred = srb->total_xfer_length;
 	/* srb->segment_x : a one entry of S/G list table */
 	srb->total_xfer_length = sizeof(cmd->sense_buffer);
-	srb->virt_addr_req = srb->virt_addr;
-	srb->virt_addr = cmd->sense_buffer;
 	srb->segment_x[0].length = sizeof(cmd->sense_buffer);
 	/* Map sense buffer */
 	srb->segment_x[0].address =
@@ -3747,7 +3771,7 @@
  * @target: The target for the new device.
  * @lun: The lun for the new device.
  *
- * Return the new device if succesfull or NULL on failure.
+ * Return the new device if successful or NULL on failure.
  **/
 static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb,
 		u8 target, u8 lun)
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index 310d2f4..c5108c8 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -145,35 +145,35 @@
 0, IRQ_AUTO}};
 #endif
 
-#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
+#define NO_OVERRIDES ARRAY_SIZE(overrides)
 
 static struct base {
 	unsigned long address;
 	int noauto;
-} bases[] __initdata = { 
-	{ 0xcc000, 0 }, 
-	{ 0xc8000, 0 }, 
-	{ 0xdc000, 0 }, 
+} bases[] __initdata = {
+	{ 0xcc000, 0 },
+	{ 0xc8000, 0 },
+	{ 0xdc000, 0 },
 	{ 0xd8000, 0 }
 };
 
-#define NO_BASES (sizeof (bases) / sizeof (struct base))
+#define NO_BASES ARRAY_SIZE(bases)
 
 static const struct signature {
 	const char *string;
 	int offset;
-} signatures[] = { 
+} signatures[] = {
 	{"DATA TECHNOLOGY CORPORATION BIOS", 0x25},
 };
 
-#define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
+#define NO_SIGNATURES ARRAY_SIZE(signatures)
 
 #ifndef MODULE
 /*
  * Function : dtc_setup(char *str, int *ints)
  *
  * Purpose : LILO command line initialization of the overrides array,
- * 
+ *
  * Inputs : str - unused, ints - array of integer parameters with ints[0]
  *	equal to the number of ints.
  *
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index 87a8c3d..ddb5124 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1,7 +1,6 @@
-/* $Id: esp.c,v 1.101 2002/01/15 06:48:55 davem Exp $
- * esp.c:  EnhancedScsiProcessor Sun SCSI driver code.
+/* esp.c: ESP Sun SCSI driver.
  *
- * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 1998, 2006 David S. Miller (davem@davemloft.net)
  */
 
 /* TODO:
@@ -185,11 +184,6 @@
 /*5*/	do_intr_end
 };
 
-/* The master ring of all esp hosts we are managing in this driver. */
-static struct esp *espchain;
-static DEFINE_SPINLOCK(espchain_lock);
-static int esps_running = 0;
-
 /* Forward declarations. */
 static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
 
@@ -694,36 +688,6 @@
 	sbus_readb(esp->eregs + ESP_INTRPT);
 }
 
-static void esp_chain_add(struct esp *esp)
-{
-	spin_lock_irq(&espchain_lock);
-	if (espchain) {
-		struct esp *elink = espchain;
-		while (elink->next)
-			elink = elink->next;
-		elink->next = esp;
-	} else {
-		espchain = esp;
-	}
-	esp->next = NULL;
-	spin_unlock_irq(&espchain_lock);
-}
-
-static void esp_chain_del(struct esp *esp)
-{
-	spin_lock_irq(&espchain_lock);
-	if (espchain == esp) {
-		espchain = esp->next;
-	} else {
-		struct esp *elink = espchain;
-		while (elink->next != esp)
-			elink = elink->next;
-		elink->next = esp->next;
-	}
-	esp->next = NULL;
-	spin_unlock_irq(&espchain_lock);
-}
-
 static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev)
 {
 	struct sbus_dev *sdev = esp->sdev;
@@ -821,8 +785,8 @@
 		return -1;
 	}
 
-	printk("esp%d: IRQ %s ", esp->esp_id,
-	       __irq_itoa(esp->ehost->irq));
+	printk("esp%d: IRQ %d ", esp->esp_id,
+	       esp->ehost->irq);
 
 	return 0;
 }
@@ -830,19 +794,20 @@
 static void __init esp_get_scsi_id(struct esp *esp)
 {
 	struct sbus_dev *sdev = esp->sdev;
+	struct device_node *dp = sdev->ofdev.node;
 
-	esp->scsi_id = prom_getintdefault(esp->prom_node,
-					  "initiator-id",
-					  -1);
+	esp->scsi_id = of_getintprop_default(dp,
+					     "initiator-id",
+					     -1);
 	if (esp->scsi_id == -1)
-		esp->scsi_id = prom_getintdefault(esp->prom_node,
-						  "scsi-initiator-id",
-						  -1);
+		esp->scsi_id = of_getintprop_default(dp,
+						     "scsi-initiator-id",
+						     -1);
 	if (esp->scsi_id == -1)
 		esp->scsi_id = (sdev->bus == NULL) ? 7 :
-			prom_getintdefault(sdev->bus->prom_node,
-					   "scsi-initiator-id",
-					   7);
+			of_getintprop_default(sdev->bus->ofdev.node,
+					      "scsi-initiator-id",
+					      7);
 	esp->ehost->this_id = esp->scsi_id;
 	esp->scsi_id_mask = (1 << esp->scsi_id);
 
@@ -1067,28 +1032,30 @@
 	esp->prev_hme_dmacsr = 0xffffffff;
 }
 
-static int __init detect_one_esp(struct scsi_host_template *tpnt, struct sbus_dev *esp_dev,
-				 struct sbus_dev *espdma, struct sbus_bus *sbus,
-				 int id, int hme)
+static int __init detect_one_esp(struct scsi_host_template *tpnt,
+				 struct device *dev,
+				 struct sbus_dev *esp_dev,
+				 struct sbus_dev *espdma,
+				 struct sbus_bus *sbus,
+				 int hme)
 {
-	struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp));
+	static int instance;
+	struct Scsi_Host *esp_host = scsi_host_alloc(tpnt, sizeof(struct esp));
 	struct esp *esp;
 	
-	if (!esp_host) {
-		printk("ESP: Cannot register SCSI host\n");
-		return -1;
-	}
+	if (!esp_host)
+		return -ENOMEM;
+
 	if (hme)
 		esp_host->max_id = 16;
 	esp = (struct esp *) esp_host->hostdata;
 	esp->ehost = esp_host;
 	esp->sdev = esp_dev;
-	esp->esp_id = id;
+	esp->esp_id = instance;
 	esp->prom_node = esp_dev->prom_node;
 	prom_getstring(esp->prom_node, "name", esp->prom_name,
 		       sizeof(esp->prom_name));
 
-	esp_chain_add(esp);
 	if (esp_find_dvma(esp, espdma) < 0)
 		goto fail_unlink;
 	if (esp_map_regs(esp, hme) < 0) {
@@ -1115,8 +1082,19 @@
 
 	esp_bootup_reset(esp);
 
+	if (scsi_add_host(esp_host, dev))
+		goto fail_free_irq;
+
+	dev_set_drvdata(&esp_dev->ofdev.dev, esp);
+
+	scsi_scan_host(esp_host);
+	instance++;
+
 	return 0;
 
+fail_free_irq:
+	free_irq(esp->ehost->irq, esp);
+
 fail_unmap_cmdarea:
 	sbus_free_consistent(esp->sdev, 16,
 			     (void *) esp->esp_command,
@@ -1129,102 +1107,18 @@
 	esp->dma->allocated = 0;
 
 fail_unlink:
-	esp_chain_del(esp);
-	scsi_unregister(esp_host);
+	scsi_host_put(esp_host);
 	return -1;
 }
 
 /* Detecting ESP chips on the machine.  This is the simple and easy
  * version.
  */
-
-#ifdef CONFIG_SUN4
-
-#include <asm/sun4paddr.h>
-
-static int __init esp_detect(struct scsi_host_template *tpnt)
+static int __devexit esp_remove_common(struct esp *esp)
 {
-	static struct sbus_dev esp_dev;
-	int esps_in_use = 0;
+	unsigned int irq = esp->ehost->irq;
 
-	espchain = NULL;
-
-	if (sun4_esp_physaddr) {
-		memset (&esp_dev, 0, sizeof(esp_dev));
-		esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
-		esp_dev.irqs[0] = 4;
-		esp_dev.resource[0].start = sun4_esp_physaddr;
-		esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1;
-		esp_dev.resource[0].flags = IORESOURCE_IO;
-
-		if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0))
-			esps_in_use++;
-		printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use);
-		esps_running =  esps_in_use;
-	}
-	return esps_in_use;
-}
-
-#else /* !CONFIG_SUN4 */
-
-static int __init esp_detect(struct scsi_host_template *tpnt)
-{
-	struct sbus_bus *sbus;
-	struct sbus_dev *esp_dev, *sbdev_iter;
-	int nesps = 0, esps_in_use = 0;
-
-	espchain = 0;
-	if (!sbus_root) {
-#ifdef CONFIG_PCI
-		return 0;
-#else
-		panic("No SBUS in esp_detect()");
-#endif
-	}
-	for_each_sbus(sbus) {
-		for_each_sbusdev(sbdev_iter, sbus) {
-			struct sbus_dev *espdma = NULL;
-			int hme = 0;
-
-			/* Is it an esp sbus device? */
-			esp_dev = sbdev_iter;
-			if (strcmp(esp_dev->prom_name, "esp") &&
-			    strcmp(esp_dev->prom_name, "SUNW,esp")) {
-				if (!strcmp(esp_dev->prom_name, "SUNW,fas")) {
-					hme = 1;
-					espdma = esp_dev;
-				} else {
-					if (!esp_dev->child ||
-					    (strcmp(esp_dev->prom_name, "espdma") &&
-					     strcmp(esp_dev->prom_name, "dma")))
-						continue; /* nope... */
-					espdma = esp_dev;
-					esp_dev = esp_dev->child;
-					if (strcmp(esp_dev->prom_name, "esp") &&
-					    strcmp(esp_dev->prom_name, "SUNW,esp"))
-						continue; /* how can this happen? */
-				}
-			}
-			
-			if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0)
-				continue;
-				
-			esps_in_use++;
-		} /* for each sbusdev */
-	} /* for each sbus */
-	printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
-	       esps_in_use);
-	esps_running = esps_in_use;
-	return esps_in_use;
-}
-
-#endif /* !CONFIG_SUN4 */
-
-/*
- */
-static int esp_release(struct Scsi_Host *host)
-{
-	struct esp *esp = (struct esp *) host->hostdata;
+	scsi_remove_host(esp->ehost);
 
 	ESP_INTSOFF(esp->dregs);
 #if 0
@@ -1232,16 +1126,79 @@
 	esp_reset_esp(esp);
 #endif
 
-	free_irq(esp->ehost->irq, esp);
+	free_irq(irq, esp);
 	sbus_free_consistent(esp->sdev, 16,
 			     (void *) esp->esp_command, esp->esp_command_dvma);
 	sbus_iounmap(esp->eregs, ESP_REG_SIZE);
 	esp->dma->allocated = 0;
-	esp_chain_del(esp);
 
-        return 0;
+	scsi_host_put(esp->ehost);
+
+	return 0;
 }
 
+
+#ifdef CONFIG_SUN4
+
+#include <asm/sun4paddr.h>
+
+static struct sbus_dev sun4_esp_dev;
+
+static int __init esp_sun4_probe(struct scsi_host_template *tpnt)
+{
+	if (sun4_esp_physaddr) {
+		memset(&sun4_esp_dev, 0, sizeof(esp_dev));
+		sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
+		sun4_esp_dev.irqs[0] = 4;
+		sun4_esp_dev.resource[0].start = sun4_esp_physaddr;
+		sun4_esp_dev.resource[0].end =
+			sun4_esp_physaddr + ESP_REG_SIZE - 1;
+		sun4_esp_dev.resource[0].flags = IORESOURCE_IO;
+
+		return detect_one_esp(tpnt, NULL,
+				      &sun4_esp_dev, NULL, NULL, 0);
+	}
+	return 0;
+}
+
+static int __devexit esp_sun4_remove(void)
+{
+	struct esp *esp = dev_get_drvdata(&dev->dev);
+
+	return esp_remove_common(esp);
+}
+
+#else /* !CONFIG_SUN4 */
+
+static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+	struct device_node *dp = dev->node;
+	struct sbus_dev *dma_sdev = NULL;
+	int hme = 0;
+
+	if (dp->parent &&
+	    (!strcmp(dp->parent->name, "espdma") ||
+	     !strcmp(dp->parent->name, "dma")))
+		dma_sdev = sdev->parent;
+	else if (!strcmp(dp->name, "SUNW,fas")) {
+		dma_sdev = sdev;
+		hme = 1;
+	}
+
+	return detect_one_esp(match->data, &dev->dev,
+			      sdev, dma_sdev, sdev->bus, hme);
+}
+
+static int __devexit esp_sbus_remove(struct of_device *dev)
+{
+	struct esp *esp = dev_get_drvdata(&dev->dev);
+
+	return esp_remove_common(esp);
+}
+
+#endif /* !CONFIG_SUN4 */
+
 /* The info function will return whatever useful
  * information the developer sees fit.  If not provided, then
  * the name field will be used instead.
@@ -1415,18 +1372,11 @@
 static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 			 int length, int inout)
 {
-	struct esp *esp;
+	struct esp *esp = (struct esp *) host->hostdata;
 
 	if (inout)
 		return -EINVAL; /* not yet */
 
-	for_each_esp(esp) {
-		if (esp->ehost == host)
-			break;
-	}
-	if (!esp)
-		return -EINVAL;
-
 	if (start)
 		*start = buffer;
 
@@ -4377,15 +4327,12 @@
 	SDptr->hostdata = NULL;
 }
 
-static struct scsi_host_template driver_template = {
-	.proc_name		= "esp",
-	.proc_info		= esp_proc_info,
-	.name			= "Sun ESP 100/100a/200",
-	.detect			= esp_detect,
+static struct scsi_host_template esp_template = {
+	.module			= THIS_MODULE,
+	.name			= "esp",
+	.info			= esp_info,
 	.slave_alloc		= esp_slave_alloc,
 	.slave_destroy		= esp_slave_destroy,
-	.release		= esp_release,
-	.info			= esp_info,
 	.queuecommand		= esp_queue,
 	.eh_abort_handler	= esp_abort,
 	.eh_bus_reset_handler	= esp_reset,
@@ -4394,12 +4341,58 @@
 	.sg_tablesize		= SG_ALL,
 	.cmd_per_lun		= 1,
 	.use_clustering		= ENABLE_CLUSTERING,
+	.proc_name		= "esp",
+	.proc_info		= esp_proc_info,
 };
 
-#include "scsi_module.c"
+#ifndef CONFIG_SUN4
+static struct of_device_id esp_match[] = {
+	{
+		.name = "SUNW,esp",
+		.data = &esp_template,
+	},
+	{
+		.name = "SUNW,fas",
+		.data = &esp_template,
+	},
+	{
+		.name = "esp",
+		.data = &esp_template,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, esp_match);
 
-MODULE_DESCRIPTION("EnhancedScsiProcessor Sun SCSI driver");
-MODULE_AUTHOR("David S. Miller (davem@redhat.com)");
+static struct of_platform_driver esp_sbus_driver = {
+	.name		= "esp",
+	.match_table	= esp_match,
+	.probe		= esp_sbus_probe,
+	.remove		= __devexit_p(esp_sbus_remove),
+};
+#endif
+
+static int __init esp_init(void)
+{
+#ifdef CONFIG_SUN4
+	return esp_sun4_probe(&esp_template);
+#else
+	return of_register_driver(&esp_sbus_driver, &sbus_bus_type);
+#endif
+}
+
+static void __exit esp_exit(void)
+{
+#ifdef CONFIG_SUN4
+	esp_sun4_remove();
+#else
+	of_unregister_driver(&esp_sbus_driver);
+#endif
+}
+
+MODULE_DESCRIPTION("ESP Sun SCSI driver");
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 
+module_init(esp_init);
+module_exit(esp_exit);
diff --git a/drivers/scsi/esp.h b/drivers/scsi/esp.h
index 73f7d69..a98cda9 100644
--- a/drivers/scsi/esp.h
+++ b/drivers/scsi/esp.h
@@ -403,8 +403,4 @@
 #define ESP_MHZ_TO_CYCLE(mhertz)  ((1000000000) / ((mhertz) / 1000))
 #define ESP_TICK(ccf, cycle)  ((7682 * (ccf) * (cycle) / 1000))
 
-/* For our interrupt engine. */
-#define for_each_esp(esp) \
-        for((esp) = espchain; (esp); (esp) = (esp)->next)
-
 #endif /* !(_SPARC_ESP_H) */
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index cca485a..70a1606 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -279,7 +279,7 @@
 	 2},
 };
 
-#define FD_BRDS sizeof(fd_mcs_adapters)/sizeof(struct fd_mcs_adapters_struct)
+#define FD_BRDS ARRAY_SIZE(fd_mcs_adapters)
 
 static irqreturn_t fd_mcs_intr(int irq, void *dev_id, struct pt_regs *regs);
 
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index 7334244..e16013f 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -420,10 +420,10 @@
    0xd0000,
    0xe0000,
 };
-#define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned ))
-		       
+#define ADDRESS_COUNT ARRAY_SIZE(addresses)
+
 static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
-#define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short ))
+#define PORT_COUNT ARRAY_SIZE(ports)
 
 static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
 
@@ -502,7 +502,7 @@
     geometry location are verified). */
 };
 
-#define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature ))
+#define SIGNATURE_COUNT ARRAY_SIZE(signatures)
 
 static void print_banner( struct Scsi_Host *shpnt )
 {
@@ -519,7 +519,7 @@
 
       if (bios_minor >= 0) printk("%d", bios_minor);
       else                 printk("?.");
-   
+
       printk( " at 0x%lx using scsi id %d\n",
 	      bios_base, shpnt->this_id );
    }
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index e6bcfe9..5f313c9 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -138,10 +138,9 @@
 [1] __initdata = { { 0,},};
 #endif
 
+#define NO_OVERRIDES ARRAY_SIZE(overrides)
 
-#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
-
-#ifndef MODULE 
+#ifndef MODULE
 
 /**
  *	internal_setup		-	handle lilo command string override
@@ -210,7 +209,7 @@
 {
 	int ints[10];
 
-	get_options(str, sizeof(ints) / sizeof(int), ints);
+	get_options(str, ARRAY_SIZE(ints), ints);
 	internal_setup(BOARD_NCR5380, str, ints);
 	return 1;
 }
@@ -218,7 +217,7 @@
 /**
  * 	do_NCR53C400_setup		-	set up entry point
  *	@str: unused
- *	@ints: integer parameters from kernel setup code 
+ *	@ints: integer parameters from kernel setup code
  *
  *	Setup function invoked at boot to parse the ncr53c400= command
  *	line.
@@ -228,7 +227,7 @@
 {
 	int ints[10];
 
-	get_options(str, sizeof(ints) / sizeof(int), ints);
+	get_options(str, ARRAY_SIZE(ints), ints);
 	internal_setup(BOARD_NCR53C400, str, ints);
 	return 1;
 }
@@ -236,7 +235,7 @@
 /**
  * 	do_NCR53C400A_setup	-	set up entry point
  *	@str: unused
- *	@ints: integer parameters from kernel setup code 
+ *	@ints: integer parameters from kernel setup code
  *
  *	Setup function invoked at boot to parse the ncr53c400a= command
  *	line.
@@ -246,7 +245,7 @@
 {
 	int ints[10];
 
-	get_options(str, sizeof(ints) / sizeof(int), ints);
+	get_options(str, ARRAY_SIZE(ints), ints);
 	internal_setup(BOARD_NCR53C400A, str, ints);
 	return 1;
 }
@@ -254,7 +253,7 @@
 /**
  * 	do_DTC3181E_setup	-	set up entry point
  *	@str: unused
- *	@ints: integer parameters from kernel setup code 
+ *	@ints: integer parameters from kernel setup code
  *
  *	Setup function invoked at boot to parse the dtc3181e= command
  *	line.
@@ -264,7 +263,7 @@
 {
 	int ints[10];
 
-	get_options(str, sizeof(ints) / sizeof(int), ints);
+	get_options(str, ARRAY_SIZE(ints), ints);
 	internal_setup(BOARD_DTC3181E, str, ints);
 	return 1;
 }
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index d5740bb..76071a1 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4,9 +4,9 @@
  * Intel Corporation:  Storage RAID Controllers                         *
  *                                                                      *
  * gdth.c                                                               *
- * Copyright (C) 1995-04 ICP vortex GmbH, Achim Leubner                 *
+ * Copyright (C) 1995-06 ICP vortex GmbH, Achim Leubner                 *
  * Copyright (C) 2002-04 Intel Corporation                              *
- * Copyright (C) 2003-04 Adaptec Inc.                                   *
+ * Copyright (C) 2003-06 Adaptec Inc.                                   *
  * <achim_leubner@adaptec.com>                                          *
  *                                                                      *
  * Additions/Fixes:                                                     *
@@ -27,9 +27,14 @@
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Linux kernel 2.2.x, 2.4.x, 2.6.x supported                           *
+ * Linux kernel 2.4.x, 2.6.x supported                                  *
  *                                                                      *
  * $Log: gdth.c,v $
+ * Revision 1.74  2006/04/10 13:44:47  achim
+ * Community changes for 2.6.x
+ * Kernel 2.2.x no longer supported
+ * scsi_request interface removed, thanks to Christoph Hellwig
+ *
  * Revision 1.73  2004/03/31 13:33:03  achim
  * Special command 0xfd implemented to detect 64-bit DMA support
  *
@@ -94,7 +99,7 @@
  * Bugfix free_irq()
  *
  * Revision 1.56  2001/08/09 11:19:39  achim
- * struct scsi_host_template changes
+ * Scsi_Host_Template changes
  *
  * Revision 1.55  2001/08/09 10:11:28  achim
  * Command HOST_UNFREEZE_IO before cache service init.
@@ -388,7 +393,13 @@
 #include <linux/proc_fs.h>
 #include <linux/time.h>
 #include <linux/timer.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
 #include <linux/dma-mapping.h>
+#else
+#define DMA_32BIT_MASK	0x00000000ffffffffULL
+#define DMA_64BIT_MASK	0xffffffffffffffffULL
+#endif
+
 #ifdef GDTH_RTC
 #include <linux/mc146818rtc.h>
 #endif
@@ -408,8 +419,8 @@
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "gdth.h"
 #include "gdth_kcompat.h"
+#include "gdth.h"
 
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
@@ -464,6 +475,8 @@
 
 static void gdth_flush(int hanum);
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
+static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
+static void gdth_scsi_done(struct scsi_cmnd *scp);
 
 #ifdef DEBUG_GDTH
 static unchar   DebugState = DEBUG_GDTH;
@@ -556,8 +569,8 @@
 #endif
 
 #define PTR2USHORT(a)   (ushort)(ulong)(a)
-#define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)   
-#define INDEX_OK(i,t)   ((i)<sizeof(t)/sizeof((t)[0]))
+#define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)
+#define INDEX_OK(i,t)   ((i)<ARRAY_SIZE(t))
 
 #define NUMDATA(a)      ( (gdth_num_str  *)((a)->hostdata))
 #define HADATA(a)       (&((gdth_ext_str *)((a)->hostdata))->haext)
@@ -643,6 +656,7 @@
 static int force_dma32 = 0;
 
 /* parameters for modprobe/insmod */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
 module_param_array(irq, int, NULL, 0);
 module_param(disable, int, 0);
 module_param(reserve_mode, int, 0);
@@ -655,6 +669,20 @@
 module_param(shared_access, int, 0);
 module_param(probe_eisa_isa, int, 0);
 module_param(force_dma32, int, 0);
+#else
+MODULE_PARM(irq, "i");
+MODULE_PARM(disable, "i");
+MODULE_PARM(reserve_mode, "i");
+MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
+MODULE_PARM(reverse_scan, "i");
+MODULE_PARM(hdr_channel, "i");
+MODULE_PARM(max_ids, "i");
+MODULE_PARM(rescan, "i");
+MODULE_PARM(virt_ctr, "i");
+MODULE_PARM(shared_access, "i");
+MODULE_PARM(probe_eisa_isa, "i");
+MODULE_PARM(force_dma32, "i");
+#endif
 MODULE_AUTHOR("Achim Leubner");
 MODULE_LICENSE("GPL");
 
@@ -683,6 +711,91 @@
     }
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static void gdth_scsi_done(struct scsi_cmnd *scp)
+{
+    TRACE2(("gdth_scsi_done()\n"));
+
+    if (scp->request)
+        complete((struct completion *)scp->request);
+}
+
+int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
+                   int timeout, u32 *info)
+{
+    Scsi_Cmnd *scp;
+    DECLARE_COMPLETION(wait);
+    int rval;
+
+    scp = kmalloc(sizeof(*scp), GFP_KERNEL);
+    if (!scp)
+        return -ENOMEM;
+    memset(scp, 0, sizeof(*scp));
+    scp->device = sdev;
+    /* use request field to save the ptr. to completion struct. */
+    scp->request = (struct request *)&wait;
+    scp->timeout_per_command = timeout*HZ;
+    scp->request_buffer = gdtcmd;
+    scp->cmd_len = 12;
+    memcpy(scp->cmnd, cmnd, 12);
+    scp->SCp.this_residual = IOCTL_PRI;   /* priority */
+    scp->done = gdth_scsi_done; /* some fn. test this */
+    gdth_queuecommand(scp, gdth_scsi_done);
+    wait_for_completion(&wait);
+
+    rval = scp->SCp.Status;
+    if (info)
+        *info = scp->SCp.Message;
+    kfree(scp);
+    return rval;
+}
+#else
+static void gdth_scsi_done(Scsi_Cmnd *scp)
+{
+    TRACE2(("gdth_scsi_done()\n"));
+
+    scp->request.rq_status = RQ_SCSI_DONE;
+    if (scp->request.waiting)
+        complete(scp->request.waiting);
+}
+
+int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
+                   int timeout, u32 *info)
+{
+    Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE);
+    unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0;
+    DECLARE_COMPLETION(wait);
+    int rval;
+
+    if (!scp)
+        return -ENOMEM;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+    scp->SCp.this_residual = IOCTL_PRI;   /* priority */
+    scp->request.rq_status = RQ_SCSI_BUSY;
+    scp->request.waiting = &wait;
+    scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
+    wait_for_completion(&wait);
+
+    rval = scp->SCp.Status;
+    if (info)
+        *info = scp->SCp.Message;
+
+    scsi_release_command(scp);
+    return rval;
+}
+#endif
+
+int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
+                 int timeout, u32 *info)
+{
+    struct scsi_device *sdev = scsi_get_host_dev(shost);
+    int rval = __gdth_execute(sdev, gdtcmd, cmnd, timeout, info);
+
+    scsi_free_host_dev(sdev);
+    return rval;
+}
+
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs)
 {
     *cyls = size /HEADS/SECS;
@@ -773,7 +886,7 @@
 MODULE_DEVICE_TABLE(pci,gdthtable);
 
 static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
-                                           ushort vendor, ushort device)
+                                   ushort vendor, ushort device)
 {
     ulong base0, base1, base2;
     struct pci_dev *pdev;
@@ -2248,14 +2361,16 @@
     ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
-    scp->SCp.this_residual = (int)priority;
-    b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-    t = scp->device->id;
-    if (priority >= DEFAULT_PRI) {
-        if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
-            (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
-            TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
-            scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+    if (scp->done != gdth_scsi_done) {
+        scp->SCp.this_residual = (int)priority;
+        b = virt_ctr ? NUMDATA(scp->device->host)->busnum:scp->device->channel;
+        t = scp->device->id;
+        if (priority >= DEFAULT_PRI) {
+            if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+                (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) {
+                TRACE2(("gdth_putq(): locked IO ->update_timeout()\n"));
+                scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+            }
         }
     }
 
@@ -2309,14 +2424,18 @@
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
             pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
-        b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
-        t = nscp->device->id;
-        l = nscp->device->lun;
-        if (nscp->SCp.this_residual >= DEFAULT_PRI) {
-            if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
-                (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) 
-                continue;
-        }
+        if (nscp->done != gdth_scsi_done) {
+            b = virt_ctr ?
+                NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
+            t = nscp->device->id;
+            l = nscp->device->lun;
+            if (nscp->SCp.this_residual >= DEFAULT_PRI) {
+                if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+                    (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
+                    continue;
+            }
+        } else
+            b = t = l = 0;
 
         if (firsttime) {
             if (gdth_test_busy(hanum)) {        /* controller busy ? */
@@ -2331,7 +2450,7 @@
             firsttime = FALSE;
         }
 
-        if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) {        
+        if (nscp->done != gdth_scsi_done) {
         if (nscp->SCp.phase == -1) {
             nscp->SCp.phase = CACHESERVICE;           /* default: cache svc. */ 
             if (nscp->cmnd[0] == TEST_UNIT_READY) {
@@ -2394,7 +2513,7 @@
                 else
                     nscp->scsi_done(nscp);
             }
-        } else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
+        } else if (nscp->done == gdth_scsi_done) {
             if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
                 this_cmd = FALSE;
             next_cmd = FALSE;
@@ -2542,13 +2661,13 @@
     gdth_ha_str *ha;
     char *address;
 
-    cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
+    cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen;
     ha = HADATA(gdth_ctr_tab[hanum]);
 
     if (scp->use_sg) {
         sl = (struct scatterlist *)scp->request_buffer;
         for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
-	    unsigned long flags;
+            unsigned long flags;
             cpnow = (ushort)sl->length;
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
                           cpnow,cpsum,cpcount,(ushort)scp->bufflen));
@@ -2560,12 +2679,19 @@
                        hanum);
                 return;
             }
-	    local_irq_save(flags);
-	    address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
+            local_irq_save(flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
             memcpy(address,buffer,cpnow);
-	    flush_dcache_page(sl->page);
-	    kunmap_atomic(address, KM_BIO_SRC_IRQ);
-	    local_irq_restore(flags);
+            flush_dcache_page(sl->page);
+            kunmap_atomic(address, KM_BIO_SRC_IRQ);
+#else
+            address = kmap_atomic(sl->page, KM_BH_IRQ) + sl->offset;
+            memcpy(address,buffer,cpnow);
+            flush_dcache_page(sl->page);
+            kunmap_atomic(address, KM_BH_IRQ);
+#endif
+            local_irq_restore(flags);
             if (cpsum == cpcount)
                 break;
             buffer += cpnow;
@@ -2946,9 +3072,9 @@
         offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
         sense_paddr = pci_map_page(ha->pdev,page,offset,
                                    16,PCI_DMA_FROMDEVICE);
-        scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr);
+        *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr;
         /* high part, if 64bit */
-        scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32);
+        *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32);
         cmdp->OpCode           = GDT_WRITE;             /* always */
         cmdp->BoardNode        = LOCALBOARD;
         if (mode64) { 
@@ -3022,7 +3148,7 @@
             }
 #endif
 
-        } else {
+        } else if (scp->request_bufflen) {
             scp->SCp.Status = GDTH_MAP_SINGLE;
             scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
             page = virt_to_page(scp->request_buffer);
@@ -3309,7 +3435,7 @@
     }
 
     if (!gdth_polling)
-	spin_lock_irqsave(&ha2->smp_lock, flags);
+        spin_lock_irqsave(&ha2->smp_lock, flags);
     wait_index = 0;
 
     /* search controller */
@@ -3642,9 +3768,10 @@
                            scp->request_bufflen,scp->SCp.Message);
         if (scp->SCp.buffer) {
             dma_addr_t addr;
-            addr = (dma_addr_t)(ulong32)scp->SCp.buffer;
+            addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer;
             if (scp->host_scribble)
-                addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32);               
+                addr += (dma_addr_t)
+                    ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32);
             pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
         }
 
@@ -4154,7 +4281,11 @@
     return 1;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static int __init gdth_detect(struct scsi_host_template *shtp)
+#else
+static int __init gdth_detect(Scsi_Host_Template *shtp)
+#endif
 {
     struct Scsi_Host *shp;
     gdth_pci_str pcistr[MAXHA];
@@ -4188,7 +4319,7 @@
         return 0;
     }
 
-    printk("GDT-HA: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR);
+    printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",GDTH_VERSION_STR);
     /* initializations */
     gdth_polling = TRUE; b = 0;
     gdth_clear_events();
@@ -4751,7 +4882,7 @@
         gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
                           BUS_L2P(ha,b), 0, 0);
         gdth_polling = FALSE;
-	spin_unlock_irqrestore(&ha->smp_lock, flags);
+        spin_unlock_irqrestore(&ha->smp_lock, flags);
     }
     return SUCCESS;
 }
@@ -4819,7 +4950,9 @@
     priority = DEFAULT_PRI;
     if (scp->done == gdth_scsi_done)
         priority = scp->SCp.this_residual;
-    gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
+    else
+        gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
+
     gdth_putq( hanum, scp, priority );
     gdth_next( hanum );
     return 0;
@@ -4922,11 +5055,7 @@
     gdth_cmd_str cmd;
     int hanum;
     gdth_ha_str *ha;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    Scsi_Request *srp;
-#else
-    Scsi_Cmnd *scp;
-#endif
+    int rval;
 
     if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
         res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES)
@@ -4943,25 +5072,11 @@
         cmd.u.cache64.DeviceNo = res.number;
     else
         cmd.u.cache.DeviceNo = res.number;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
-    if (!srp)
-        return -ENOMEM;
-    srp->sr_cmd_len = 12;
-    srp->sr_use_sg = 0;
-    gdth_do_req(srp, &cmd, cmnd, 30);
-    res.status = (ushort)srp->sr_command->SCp.Status;
-    scsi_release_request(srp);
-#else
-    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
-    if (!scp)
-        return -ENOMEM;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-    gdth_do_cmd(scp, &cmd, cmnd, 30);
-    res.status = (ushort)scp->SCp.Status;
-    scsi_release_command(scp);
-#endif
+
+    rval = __gdth_execute(ha->sdev, &cmd, cmnd, 30, NULL);
+    if (rval < 0)
+        return rval;
+    res.status = rval;
 
     if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset)))
         return -EFAULT;
@@ -4974,12 +5089,8 @@
     char *buf = NULL;
     ulong64 paddr; 
     int hanum;
-        gdth_ha_str *ha; 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        Scsi_Request *srp;
-#else
-        Scsi_Cmnd *scp;
-#endif
+    gdth_ha_str *ha;
+    int rval;
         
     if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) ||
         gen.ionode >= gdth_ctr_count)
@@ -5071,27 +5182,10 @@
         }
     }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
-    if (!srp)
-        return -ENOMEM;
-    srp->sr_cmd_len = 12;
-    srp->sr_use_sg = 0;
-    gdth_do_req(srp, &gen.command, cmnd, gen.timeout);
-    gen.status = srp->sr_command->SCp.Status;
-    gen.info = srp->sr_command->SCp.Message;
-    scsi_release_request(srp);
-#else
-    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
-    if (!scp)
-        return -ENOMEM;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-    gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout);
-    gen.status = scp->SCp.Status;
-    gen.info = scp->SCp.Message;
-    scsi_release_command(scp);
-#endif
+    rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info);
+    if (rval < 0)
+        return rval;
+    gen.status = rval;
 
     if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, 
                      gen.data_len + gen.sense_len)) {
@@ -5114,40 +5208,22 @@
     gdth_ha_str *ha;
     unchar i;
     int hanum, rc = -ENOMEM;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    Scsi_Request *srp;
-#else
-    Scsi_Cmnd *scp;
-#endif
-        
+    u32 cluster_type = 0;
+
     rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
     cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
     if (!rsc || !cmd)
-	goto free_fail;
+        goto free_fail;
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
         rsc->ionode >= gdth_ctr_count) {
         rc = -EFAULT;
-	goto free_fail;
+        goto free_fail;
     }
     hanum = rsc->ionode;
     ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
    
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
-    if (!srp)
-        goto free_fail;
-    srp->sr_cmd_len = 12;
-    srp->sr_use_sg = 0;
-#else
-    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
-    if (!scp)
-        goto free_fail;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-#endif
-
     for (i = 0; i < MAX_HDRIVES; ++i) { 
         if (!ha->hdr[i].present) {
             rsc->hdr_list[i].bus = 0xff; 
@@ -5164,27 +5240,15 @@
                 cmd->u.cache64.DeviceNo = i;
             else
                 cmd->u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-            gdth_do_req(srp, cmd, cmnd, 30);
-            if (srp->sr_command->SCp.Status == S_OK)
-                rsc->hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
-#else
-            gdth_do_cmd(scp, cmd, cmnd, 30);
-            if (scp->SCp.Status == S_OK)
-                rsc->hdr_list[i].cluster_type = scp->SCp.Message;
-#endif
+            if (__gdth_execute(ha->sdev, cmd, cmnd, 30, &cluster_type) == S_OK)
+                rsc->hdr_list[i].cluster_type = cluster_type;
         }
     } 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    scsi_release_request(srp);
-#else
-    scsi_release_command(scp);
-#endif       
- 
+
     if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
         rc = -EFAULT;
     else
-	rc = 0;
+        rc = 0;
 
 free_fail:
     kfree(rsc);
@@ -5202,40 +5266,21 @@
     int rc = -ENOMEM;
     ulong flags;
     gdth_ha_str *ha; 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    Scsi_Request *srp;
-#else
-    Scsi_Cmnd *scp;
-#endif
 
     rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
     cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
     if (!cmd || !rsc)
-	goto free_fail;
+        goto free_fail;
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
         rsc->ionode >= gdth_ctr_count) {
-	rc = -EFAULT;
-	goto free_fail;
+        rc = -EFAULT;
+        goto free_fail;
     }
     hanum = rsc->ionode;
     ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
-    if (!srp)
-        goto free_fail;
-    srp->sr_cmd_len = 12;
-    srp->sr_use_sg = 0;
-#else
-    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
-    if (!scp)
-        goto free_fail;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-#endif
-     
     if (rsc->flag == 0) {
         /* old method: re-init. cache service */
         cmd->Service = CACHESERVICE;
@@ -5246,19 +5291,8 @@
             cmd->OpCode = GDT_INIT;
             cmd->u.cache.DeviceNo = LINUX_OS;
         }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        gdth_do_req(srp, cmd, cmnd, 30);
-        status = (ushort)srp->sr_command->SCp.Status;
-        info = (ulong32)srp->sr_command->SCp.Message;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-        gdth_do_cmd(scp, cmd, cmnd, 30);
-        status = (ushort)scp->SCp.Status;
-        info = (ulong32)scp->SCp.Message;
-#else
-        gdth_do_cmd(&scp, cmd, cmnd, 30);
-        status = (ushort)scp.SCp.Status;
-        info = (ulong32)scp.SCp.Message;
-#endif
+
+        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
         i = 0;
         hdr_cnt = (status == S_OK ? (ushort)info : 0);
     } else {
@@ -5273,15 +5307,9 @@
             cmd->u.cache64.DeviceNo = i;
         else 
             cmd->u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        gdth_do_req(srp, cmd, cmnd, 30);
-        status = (ushort)srp->sr_command->SCp.Status;
-        info = (ulong32)srp->sr_command->SCp.Message;
-#else
-        gdth_do_cmd(scp, cmd, cmnd, 30);
-        status = (ushort)scp->SCp.Status;
-        info = (ulong32)scp->SCp.Message;
-#endif
+
+        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
+
         spin_lock_irqsave(&ha->smp_lock, flags);
         rsc->hdr_list[i].bus = ha->virt_bus;
         rsc->hdr_list[i].target = i;
@@ -5313,15 +5341,9 @@
             cmd->u.cache64.DeviceNo = i;
         else
             cmd->u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        gdth_do_req(srp, cmd, cmnd, 30);
-        status = (ushort)srp->sr_command->SCp.Status;
-        info = (ulong32)srp->sr_command->SCp.Message;
-#else
-        gdth_do_cmd(scp, cmd, cmnd, 30);
-        status = (ushort)scp->SCp.Status;
-        info = (ulong32)scp->SCp.Message;
-#endif
+
+        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
+
         spin_lock_irqsave(&ha->smp_lock, flags);
         ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
         spin_unlock_irqrestore(&ha->smp_lock, flags);
@@ -5332,15 +5354,9 @@
             cmd->u.cache64.DeviceNo = i;
         else
             cmd->u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        gdth_do_req(srp, cmd, cmnd, 30);
-        status = (ushort)srp->sr_command->SCp.Status;
-        info = (ulong32)srp->sr_command->SCp.Message;
-#else
-        gdth_do_cmd(scp, cmd, cmnd, 30);
-        status = (ushort)scp->SCp.Status;
-        info = (ulong32)scp->SCp.Message;
-#endif
+
+        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
+
         spin_lock_irqsave(&ha->smp_lock, flags);
         ha->hdr[i].cluster_type = 
             ((status == S_OK && !shared_access) ? (ushort)info : 0);
@@ -5353,29 +5369,18 @@
             cmd->u.cache64.DeviceNo = i;
         else
             cmd->u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        gdth_do_req(srp, cmd, cmnd, 30);
-        status = (ushort)srp->sr_command->SCp.Status;
-        info = (ulong32)srp->sr_command->SCp.Message;
-#else
-        gdth_do_cmd(scp, cmd, cmnd, 30);
-        status = (ushort)scp->SCp.Status;
-        info = (ulong32)scp->SCp.Message;
-#endif
+
+        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
+
         spin_lock_irqsave(&ha->smp_lock, flags);
         ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
         spin_unlock_irqrestore(&ha->smp_lock, flags);
     }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    scsi_release_request(srp);
-#else
-    scsi_release_command(scp);
-#endif       
  
     if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
         rc = -EFAULT;
     else
-	rc = 0;
+        rc = 0;
 
 free_fail:
     kfree(rsc);
@@ -5515,17 +5520,18 @@
         hanum = res.ionode; 
         ha = HADATA(gdth_ctr_tab[hanum]);
 
-        /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.6.x */        
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        scp  = scsi_get_command(ha->sdev, GFP_KERNEL);
+        scp  = kmalloc(sizeof(*scp), GFP_KERNEL);
         if (!scp)
             return -ENOMEM;
+        memset(scp, 0, sizeof(*scp));
+        scp->device = ha->sdev;
         scp->cmd_len = 12;
         scp->use_sg = 0;
         scp->device->channel = virt_ctr ? 0 : res.number;
         rval = gdth_eh_bus_reset(scp);
         res.status = (rval == SUCCESS ? S_OK : S_GENERR);
-        scsi_put_command(scp);
+        kfree(scp);
 #else
         scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
         if (!scp)
@@ -5558,34 +5564,12 @@
     int             i;
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    Scsi_Request    *srp;
-#else
-    Scsi_Cmnd       *scp;
-#endif
-    struct scsi_device     *sdev;
     char            cmnd[MAX_COMMAND_SIZE];   
     memset(cmnd, 0xff, MAX_COMMAND_SIZE);
 
     TRACE2(("gdth_flush() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-    srp  = scsi_allocate_request(sdev, GFP_KERNEL);
-    if (!srp)
-        return;
-    srp->sr_cmd_len = 12;
-    srp->sr_use_sg = 0;
-#else
-    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-    scp  = scsi_allocate_device(sdev, 1, FALSE);
-    if (!scp)
-        return;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-#endif
-
     for (i = 0; i < MAX_HDRIVES; ++i) {
         if (ha->hdr[i].present) {
             gdtcmd.BoardNode = LOCALBOARD;
@@ -5601,20 +5585,10 @@
                 gdtcmd.u.cache.sg_canz = 0;
             }
             TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-            gdth_do_req(srp, &gdtcmd, cmnd, 30);
-#else
-            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-#endif
+
+            gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL);
         }
     }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    scsi_release_request(srp);
-    scsi_free_host_dev(sdev);
-#else
-    scsi_release_command(scp);
-    scsi_free_host_dev(sdev);
-#endif
 }
 
 /* shutdown routine */
@@ -5623,18 +5597,11 @@
     int             hanum;
 #ifndef __alpha__
     gdth_cmd_str    gdtcmd;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    Scsi_Request    *srp;
-    struct scsi_device     *sdev;
-#else
-    Scsi_Cmnd       *scp;
-    struct scsi_device     *sdev;
-#endif
     char            cmnd[MAX_COMMAND_SIZE];   
 #endif
 
     if (notifier_disabled)
-    	return NOTIFY_OK;
+        return NOTIFY_OK;
 
     TRACE2(("gdth_halt() event %d\n",(int)event));
     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
@@ -5652,31 +5619,7 @@
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_RESET;
         TRACE2(("gdth_halt(): reset controller %d\n", hanum));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-        srp  = scsi_allocate_request(sdev, GFP_KERNEL);
-        if (!srp) {
-            unregister_reboot_notifier(&gdth_notifier);
-            return NOTIFY_OK;
-        }
-        srp->sr_cmd_len = 12;
-        srp->sr_use_sg = 0;
-        gdth_do_req(srp, &gdtcmd, cmnd, 10);
-        scsi_release_request(srp);
-        scsi_free_host_dev(sdev);
-#else
-        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
-        scp  = scsi_allocate_device(sdev, 1, FALSE);
-        if (!scp) {
-            unregister_reboot_notifier(&gdth_notifier);
-            return NOTIFY_OK;
-        }
-        scp->cmd_len = 12;
-        scp->use_sg = 0;
-        gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
-        scsi_release_command(scp);
-        scsi_free_host_dev(sdev);
-#endif
+        gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL);
 #endif
     }
     printk("Done.\n");
@@ -5687,7 +5630,22 @@
     return NOTIFY_OK;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+/* configure lun */
+static int gdth_slave_configure(struct scsi_device *sdev)
+{
+    scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+    sdev->skip_ms_page_3f = 1;
+    sdev->skip_ms_page_8 = 1;
+    return 0;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static struct scsi_host_template driver_template = {
+#else
+static Scsi_Host_Template driver_template = {
+#endif
         .proc_name              = "gdth", 
         .proc_info              = gdth_proc_info,
         .name                   = "GDT SCSI Disk Array Controller",
@@ -5698,6 +5656,9 @@
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
         .bios_param             = gdth_bios_param,
         .can_queue              = GDTH_MAXCMDS,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        .slave_configure        = gdth_slave_configure,
+#endif
         .this_id                = -1,
         .sg_tablesize           = GDTH_MAXSG,
         .cmd_per_lun            = GDTH_MAXC_P_L,
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
index cc4882f..47eae02 100644
--- a/drivers/scsi/gdth.h
+++ b/drivers/scsi/gdth.h
@@ -4,13 +4,13 @@
 /*
  * Header file for the GDT Disk Array/Storage RAID controllers driver for Linux
  * 
- * gdth.h Copyright (C) 1995-03 ICP vortex, Achim Leubner
+ * gdth.h Copyright (C) 1995-06 ICP vortex, Achim Leubner
  * See gdth.c for further informations and 
  * below for supported controller types
  *
  * <achim_leubner@adaptec.com>
  *
- * $Id: gdth.h,v 1.57 2004/03/31 11:52:09 achim Exp $
+ * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $
  */
 
 #include <linux/version.h>
@@ -26,9 +26,9 @@
 /* defines, macros */
 
 /* driver version */
-#define GDTH_VERSION_STR        "3.04"
+#define GDTH_VERSION_STR        "3.05"
 #define GDTH_VERSION            3
-#define GDTH_SUBVERSION         4
+#define GDTH_SUBVERSION         5
 
 /* protocol version */
 #define PROTOCOL_VERSION        1
diff --git a/drivers/scsi/gdth_kcompat.h b/drivers/scsi/gdth_kcompat.h
index e6cf0ed..2a302ee 100644
--- a/drivers/scsi/gdth_kcompat.h
+++ b/drivers/scsi/gdth_kcompat.h
@@ -1,5 +1,3 @@
-
-
 #ifndef IRQ_HANDLED
 typedef void irqreturn_t;
 #define IRQ_NONE
@@ -10,6 +8,18 @@
 #define MODULE_LICENSE(x)
 #endif
 
+#ifndef __iomem
+#define __iomem
+#endif
+
+#ifndef __attribute_used__
+#define __attribute_used__	__devinitdata
+#endif
+
+#ifndef __user
+#define __user
+#endif
+
 #ifndef SERVICE_ACTION_IN
 #define SERVICE_ACTION_IN	0x9e
 #endif
diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
index 5e8657f..32982eb 100644
--- a/drivers/scsi/gdth_proc.c
+++ b/drivers/scsi/gdth_proc.c
@@ -1,5 +1,5 @@
 /* gdth_proc.c 
- * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $
+ * $Id: gdth_proc.c,v 1.43 2006/01/11 16:15:00 achim Exp $
  */
 
 #include <linux/completion.h>
@@ -51,57 +51,26 @@
 static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
                          int hanum,int busnum)
 {
-    int             ret_val = -EINVAL;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    Scsi_Request    *scp;
-    struct scsi_device     *sdev;
-#else
-    Scsi_Cmnd       *scp;
-    struct scsi_device     *sdev;
-#endif
-    TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
+    int ret_val = -EINVAL;
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    sdev = scsi_get_host_dev(host);
-    scp  = scsi_allocate_request(sdev, GFP_KERNEL);
-    if (!scp)
-        return -ENOMEM;
-    scp->sr_cmd_len = 12;
-    scp->sr_use_sg = 0;
-#else
-    sdev = scsi_get_host_dev(host);
-    scp  = scsi_allocate_device(sdev, 1, FALSE);
-    if (!scp)
-        return -ENOMEM;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-#endif
+    TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
 
     if (length >= 4) {
         if (strncmp(buffer,"gdth",4) == 0) {
             buffer += 5;
             length -= 5;
-            ret_val = gdth_set_asc_info( buffer, length, hanum, scp );
+            ret_val = gdth_set_asc_info(host, buffer, length, hanum);
         }
     }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    scsi_release_request(scp);
-    scsi_free_host_dev(sdev);
-#else
-    scsi_release_command(scp);
-    scsi_free_host_dev(sdev);
-#endif
+
     return ret_val;
 }
          
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp)
-#else
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
-#endif
+static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
+                        int length,int hanum)
 {
-    int             orig_length, drive, wb_mode;
-    int             i, found;
+    int orig_length, drive, wb_mode;
+    int i, found;
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     gdth_cpar_str   *pcpar;
@@ -146,11 +115,8 @@
                     gdtcmd.u.cache.DeviceNo = i;
                     gdtcmd.u.cache.BlockNo = 1;
                 }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-                gdth_do_req(scp, &gdtcmd, cmnd, 30);
-#else
-                gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-#endif
+
+                gdth_execute(host, &gdtcmd, cmnd, 30, NULL);
             }
         }
         if (!found)
@@ -202,11 +168,9 @@
         gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
         gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
         pcpar->write_back = wb_mode==1 ? 0:1;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        gdth_do_req(scp, &gdtcmd, cmnd, 30);
-#else
-        gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-#endif
+
+        gdth_execute(host, &gdtcmd, cmnd, 30, NULL);
+
         gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
         printk("Done.\n");
         return(orig_length);
@@ -230,13 +194,6 @@
 
     gdth_cmd_str *gdtcmd;
     gdth_evt_str *estr;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    Scsi_Request *scp;
-    struct scsi_device *sdev;
-#else
-    Scsi_Cmnd *scp;
-    struct scsi_device *sdev;
-#endif
     char hrec[161];
     struct timeval tv;
 
@@ -252,7 +209,7 @@
     gdtcmd = kmalloc(sizeof(*gdtcmd), GFP_KERNEL);
     estr = kmalloc(sizeof(*estr), GFP_KERNEL);
     if (!gdtcmd || !estr)
-	goto free_fail;
+        goto free_fail;
 
     memset(cmnd, 0xff, 12);
     memset(gdtcmd, 0, sizeof(gdth_cmd_str));
@@ -260,28 +217,6 @@
     TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    sdev = scsi_get_host_dev(host);
-    scp  = scsi_allocate_request(sdev, GFP_KERNEL);
-    if (!scp)
-        goto free_fail;
-    scp->sr_cmd_len = 12;
-    scp->sr_use_sg = 0;
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
-    sdev = scsi_get_host_dev(host);
-    scp  = scsi_allocate_device(sdev, 1, FALSE);
-    if (!scp)
-        goto free_fail;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-#else
-    memset(&sdev,0,sizeof(struct scsi_device));
-    memset(&scp, 0,sizeof(Scsi_Cmnd));
-    sdev.host = scp.host = host;
-    sdev.id = scp.target = sdev.host->this_id;
-    scp.device = &sdev;
-#endif
-    
     
     /* request is i.e. "cat /proc/scsi/gdth/0" */ 
     /* format: %-15s\t%-10s\t%-15s\t%s */
@@ -386,16 +321,9 @@
                 sizeof(pds->list[0]);
             if (pds->entries > cnt)
                 pds->entries = cnt;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-            gdth_do_req(scp, gdtcmd, cmnd, 30);
-            if (scp->sr_command->SCp.Status != S_OK) 
-#else
-            gdth_do_cmd(scp, gdtcmd, cmnd, 30);
-            if (scp->SCp.Status != S_OK) 
-#endif
-            { 
+
+            if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK)
                 pds->count = 0;
-            }
 
             /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
             for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
@@ -410,14 +338,8 @@
                 gdtcmd->u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
                 gdtcmd->u.ioctl.channel = 
                     ha->raw[i].address | ha->raw[i].id_list[j];
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-                gdth_do_req(scp, gdtcmd, cmnd, 30);
-                if (scp->sr_command->SCp.Status == S_OK) 
-#else
-                gdth_do_cmd(scp, gdtcmd, cmnd, 30);
-                if (scp->SCp.Status == S_OK) 
-#endif
-                {
+
+                if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
                     strncpy(hrec,pdi->vendor,8);
                     strncpy(hrec+8,pdi->product,16);
                     strncpy(hrec+24,pdi->revision,4);
@@ -466,14 +388,8 @@
                     gdtcmd->u.ioctl.channel = 
                         ha->raw[i].address | ha->raw[i].id_list[j];
                     pdef->sddc_type = 0x08;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-                    gdth_do_req(scp, gdtcmd, cmnd, 30);
-                    if (scp->sr_command->SCp.Status == S_OK) 
-#else
-                    gdth_do_cmd(scp, gdtcmd, cmnd, 30);
-                    if (scp->SCp.Status == S_OK) 
-#endif
-                    {
+
+                    if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
                         size = sprintf(buffer+len,
                                        " Grown Defects:\t%d\n",
                                        pdef->sddc_cnt);
@@ -519,16 +435,8 @@
                 gdtcmd->u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
                 gdtcmd->u.ioctl.subfunc = CACHE_DRV_INFO;
                 gdtcmd->u.ioctl.channel = drv_no;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-                gdth_do_req(scp, gdtcmd, cmnd, 30);
-                if (scp->sr_command->SCp.Status != S_OK) 
-#else
-                gdth_do_cmd(scp, gdtcmd, cmnd, 30);
-                if (scp->SCp.Status != S_OK)
-#endif
-                {
+                if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) != S_OK)
                     break;
-                }
                 pcdi->ld_dtype >>= 16;
                 j++;
                 if (pcdi->ld_dtype > 2) {
@@ -629,14 +537,7 @@
             gdtcmd->u.ioctl.param_size = sizeof(gdth_arrayinf_str);
             gdtcmd->u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
             gdtcmd->u.ioctl.channel = i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-            gdth_do_req(scp, gdtcmd, cmnd, 30);
-            if (scp->sr_command->SCp.Status == S_OK) 
-#else
-            gdth_do_cmd(scp, gdtcmd, cmnd, 30);
-            if (scp->SCp.Status == S_OK) 
-#endif
-            {
+            if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
                 if (pai->ai_state == 0)
                     strcpy(hrec, "idle");
                 else if (pai->ai_state == 2)
@@ -710,14 +611,7 @@
             gdtcmd->u.ioctl.channel = i;
             phg->entries = MAX_HDRIVES;
             phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-            gdth_do_req(scp, gdtcmd, cmnd, 30);
-            if (scp->sr_command->SCp.Status != S_OK) 
-#else
-            gdth_do_cmd(scp, gdtcmd, cmnd, 30);
-            if (scp->SCp.Status != S_OK) 
-#endif
-            {
+            if (gdth_execute(host, gdtcmd, cmnd, 30, NULL) == S_OK) {
                 ha->hdr[i].ldr_no = i;
                 ha->hdr[i].rw_attribs = 0;
                 ha->hdr[i].start_sec = 0;
@@ -791,13 +685,6 @@
     }
 
 stop_output:
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    scsi_release_request(scp);
-    scsi_free_host_dev(sdev);
-#else
-    scsi_release_command(scp);
-    scsi_free_host_dev(sdev);
-#endif
     *start = buffer +(offset-begin);
     len -= (offset-begin);
     if (len > length)
@@ -812,64 +699,6 @@
     return rc;
 }
 
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, 
-                        char *cmnd, int timeout)
-{
-    unsigned bufflen;
-    DECLARE_COMPLETION(wait);
-
-    TRACE2(("gdth_do_req()\n"));
-    if (gdtcmd != NULL) { 
-        bufflen = sizeof(gdth_cmd_str);
-    } else {
-        bufflen = 0;
-    }
-    scp->sr_request->rq_status = RQ_SCSI_BUSY;
-    scp->sr_request->waiting = &wait;
-    scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
-    wait_for_completion(&wait);
-}
-
-#else
-static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, 
-                        char *cmnd, int timeout)
-{
-    unsigned bufflen;
-    DECLARE_COMPLETION(wait);
-
-    TRACE2(("gdth_do_cmd()\n"));
-    if (gdtcmd != NULL) { 
-        scp->SCp.this_residual = IOCTL_PRI;
-        bufflen = sizeof(gdth_cmd_str);
-    } else {
-        scp->SCp.this_residual = DEFAULT_PRI;
-        bufflen = 0;
-    }
-
-    scp->request.rq_status = RQ_SCSI_BUSY;
-    scp->request.waiting = &wait;
-    scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
-    wait_for_completion(&wait);
-}
-#endif
-
-void gdth_scsi_done(Scsi_Cmnd *scp)
-{
-    TRACE2(("gdth_scsi_done()\n"));
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-    scp->request->rq_status = RQ_SCSI_DONE;
-    if (scp->request->waiting != NULL)
-        complete(scp->request->waiting);
-#else
-    scp->request.rq_status = RQ_SCSI_DONE;
-    if (scp->request.waiting != NULL)
-        complete(scp->request.waiting);
-#endif
-}
-
 static char *gdth_ioctl_alloc(int hanum, int size, int scratch, 
                               ulong64 *paddr)
 {
@@ -976,11 +805,14 @@
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-        t = scp->device->id;
-        if (t == (unchar)id && b == (unchar)busnum) {
-            TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
-            scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+        if (scp->done != gdth_scsi_done) {
+            b = virt_ctr ?
+                NUMDATA(scp->device->host)->busnum : scp->device->channel;
+            t = scp->device->id;
+            if (t == (unchar)id && b == (unchar)busnum) {
+                TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
+                scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
+            }
         }
     }
     spin_unlock_irqrestore(&ha->smp_lock, flags);
@@ -997,11 +829,14 @@
     spin_lock_irqsave(&ha->smp_lock, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
-        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
-        t = scp->device->id;
-        if (t == (unchar)id && b == (unchar)busnum) {
-            TRACE2(("gdth_start_timeout(): update_timeout()\n"));
-            gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
+        if (scp->done != gdth_scsi_done) {
+            b = virt_ctr ?
+                NUMDATA(scp->device->host)->busnum : scp->device->channel;
+            t = scp->device->id;
+            if (t == (unchar)id && b == (unchar)busnum) {
+                TRACE2(("gdth_start_timeout(): update_timeout()\n"));
+                gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
+            }
         }
     }
     spin_unlock_irqrestore(&ha->smp_lock, flags);
diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
index 295e825..a679eeb 100644
--- a/drivers/scsi/gdth_proc.h
+++ b/drivers/scsi/gdth_proc.h
@@ -5,20 +5,16 @@
  * $Id: gdth_proc.h,v 1.16 2004/01/14 13:09:01 achim Exp $
  */
 
+int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
+                 int timeout, u32 *info);
+
 static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
                          int hanum,int busnum);
 static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
                          struct Scsi_Host *host,int hanum,int busnum);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd, 
-                        char *cmnd, int timeout);
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp);
-#else
-static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, 
-                        char *cmnd, int timeout);
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
-#endif
+static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer,
+                             int length, int hanum);
 
 static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
                               ulong64 *paddr);  
@@ -28,7 +24,5 @@
 static void gdth_start_timeout(int hanum, int busnum, int id);
 static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout);
 
-void gdth_scsi_done(Scsi_Cmnd *scp);
-
 #endif
 
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
new file mode 100644
index 0000000..f778083
--- /dev/null
+++ b/drivers/scsi/hptiop.c
@@ -0,0 +1,1493 @@
+/*
+ * HighPoint RR3xxx controller driver for Linux
+ * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Please report bugs/comments/suggestions to linux@highpoint-tech.com
+ *
+ * For more information, visit http://www.highpoint-tech.com
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <linux/hdreg.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_host.h>
+
+#include "hptiop.h"
+
+MODULE_AUTHOR("HighPoint Technologies, Inc.");
+MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver");
+
+static char driver_name[] = "hptiop";
+static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver";
+static const char driver_ver[] = "v1.0 (060426)";
+
+static DEFINE_SPINLOCK(hptiop_hba_list_lock);
+static LIST_HEAD(hptiop_hba_list);
+static int hptiop_cdev_major = -1;
+
+static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag);
+static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag);
+static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg);
+
+static inline void hptiop_pci_posting_flush(struct hpt_iopmu __iomem *iop)
+{
+	readl(&iop->outbound_intstatus);
+}
+
+static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec)
+{
+	u32 req = 0;
+	int i;
+
+	for (i = 0; i < millisec; i++) {
+		req = readl(&iop->inbound_queue);
+		if (req != IOPMU_QUEUE_EMPTY)
+			break;
+		msleep(1);
+	}
+
+	if (req != IOPMU_QUEUE_EMPTY) {
+		writel(req, &iop->outbound_queue);
+		hptiop_pci_posting_flush(iop);
+		return 0;
+	}
+
+	return -1;
+}
+
+static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag)
+{
+	if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT)
+		return hptiop_host_request_callback(hba,
+				tag & ~IOPMU_QUEUE_ADDR_HOST_BIT);
+	else
+		return hptiop_iop_request_callback(hba, tag);
+}
+
+static inline void hptiop_drain_outbound_queue(struct hptiop_hba *hba)
+{
+	u32 req;
+
+	while ((req = readl(&hba->iop->outbound_queue)) != IOPMU_QUEUE_EMPTY) {
+
+		if (req & IOPMU_QUEUE_MASK_HOST_BITS)
+			hptiop_request_callback(hba, req);
+		else {
+			struct hpt_iop_request_header __iomem * p;
+
+			p = (struct hpt_iop_request_header __iomem *)
+				((char __iomem *)hba->iop + req);
+
+			if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) {
+				if (readl(&p->context))
+					hptiop_request_callback(hba, req);
+				else
+					writel(1, &p->context);
+			}
+			else
+				hptiop_request_callback(hba, req);
+		}
+	}
+}
+
+static int __iop_intr(struct hptiop_hba *hba)
+{
+	struct hpt_iopmu __iomem *iop = hba->iop;
+	u32 status;
+	int ret = 0;
+
+	status = readl(&iop->outbound_intstatus);
+
+	if (status & IOPMU_OUTBOUND_INT_MSG0) {
+		u32 msg = readl(&iop->outbound_msgaddr0);
+		dprintk("received outbound msg %x\n", msg);
+		writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus);
+		hptiop_message_callback(hba, msg);
+		ret = 1;
+	}
+
+	if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
+		hptiop_drain_outbound_queue(hba);
+		ret = 1;
+	}
+
+	return ret;
+}
+
+static int iop_send_sync_request(struct hptiop_hba *hba,
+					void __iomem *_req, u32 millisec)
+{
+	struct hpt_iop_request_header __iomem *req = _req;
+	u32 i;
+
+	writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST,
+			&req->flags);
+
+	writel(0, &req->context);
+
+	writel((unsigned long)req - (unsigned long)hba->iop,
+			&hba->iop->inbound_queue);
+
+	hptiop_pci_posting_flush(hba->iop);
+
+	for (i = 0; i < millisec; i++) {
+		__iop_intr(hba);
+		if (readl(&req->context))
+			return 0;
+		msleep(1);
+	}
+
+	return -1;
+}
+
+static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec)
+{
+	u32 i;
+
+	hba->msg_done = 0;
+
+	writel(msg, &hba->iop->inbound_msgaddr0);
+
+	hptiop_pci_posting_flush(hba->iop);
+
+	for (i = 0; i < millisec; i++) {
+		spin_lock_irq(hba->host->host_lock);
+		__iop_intr(hba);
+		spin_unlock_irq(hba->host->host_lock);
+		if (hba->msg_done)
+			break;
+		msleep(1);
+	}
+
+	return hba->msg_done? 0 : -1;
+}
+
+static int iop_get_config(struct hptiop_hba *hba,
+				struct hpt_iop_request_get_config *config)
+{
+	u32 req32;
+	struct hpt_iop_request_get_config __iomem *req;
+
+	req32 = readl(&hba->iop->inbound_queue);
+	if (req32 == IOPMU_QUEUE_EMPTY)
+		return -1;
+
+	req = (struct hpt_iop_request_get_config __iomem *)
+			((unsigned long)hba->iop + req32);
+
+	writel(0, &req->header.flags);
+	writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type);
+	writel(sizeof(struct hpt_iop_request_get_config), &req->header.size);
+	writel(IOP_RESULT_PENDING, &req->header.result);
+
+	if (iop_send_sync_request(hba, req, 20000)) {
+		dprintk("Get config send cmd failed\n");
+		return -1;
+	}
+
+	memcpy_fromio(config, req, sizeof(*config));
+	writel(req32, &hba->iop->outbound_queue);
+	return 0;
+}
+
+static int iop_set_config(struct hptiop_hba *hba,
+				struct hpt_iop_request_set_config *config)
+{
+	u32 req32;
+	struct hpt_iop_request_set_config __iomem *req;
+
+	req32 = readl(&hba->iop->inbound_queue);
+	if (req32 == IOPMU_QUEUE_EMPTY)
+		return -1;
+
+	req = (struct hpt_iop_request_set_config __iomem *)
+			((unsigned long)hba->iop + req32);
+
+	memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header),
+		(u8 *)config + sizeof(struct hpt_iop_request_header),
+		sizeof(struct hpt_iop_request_set_config) -
+			sizeof(struct hpt_iop_request_header));
+
+	writel(0, &req->header.flags);
+	writel(IOP_REQUEST_TYPE_SET_CONFIG, &req->header.type);
+	writel(sizeof(struct hpt_iop_request_set_config), &req->header.size);
+	writel(IOP_RESULT_PENDING, &req->header.result);
+
+	if (iop_send_sync_request(hba, req, 20000)) {
+		dprintk("Set config send cmd failed\n");
+		return -1;
+	}
+
+	writel(req32, &hba->iop->outbound_queue);
+	return 0;
+}
+
+static int hptiop_initialize_iop(struct hptiop_hba *hba)
+{
+	struct hpt_iopmu __iomem *iop = hba->iop;
+
+	/* enable interrupts */
+	writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0),
+			&iop->outbound_intmask);
+
+	hba->initialized = 1;
+
+	/* start background tasks */
+	if (iop_send_sync_msg(hba,
+			IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
+		printk(KERN_ERR "scsi%d: fail to start background task\n",
+			hba->host->host_no);
+		return -1;
+	}
+	return 0;
+}
+
+static int hptiop_map_pci_bar(struct hptiop_hba *hba)
+{
+	u32 mem_base_phy, length;
+	void __iomem *mem_base_virt;
+	struct pci_dev *pcidev = hba->pcidev;
+
+	if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
+		printk(KERN_ERR "scsi%d: pci resource invalid\n",
+				hba->host->host_no);
+		return -1;
+	}
+
+	mem_base_phy = pci_resource_start(pcidev, 0);
+	length = pci_resource_len(pcidev, 0);
+	mem_base_virt = ioremap(mem_base_phy, length);
+
+	if (!mem_base_virt) {
+		printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n",
+				hba->host->host_no);
+		return -1;
+	}
+
+	hba->iop = mem_base_virt;
+	dprintk("hptiop_map_pci_bar: iop=%p\n", hba->iop);
+	return 0;
+}
+
+static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg)
+{
+	dprintk("iop message 0x%x\n", msg);
+
+	if (!hba->initialized)
+		return;
+
+	if (msg == IOPMU_INBOUND_MSG0_RESET) {
+		atomic_set(&hba->resetting, 0);
+		wake_up(&hba->reset_wq);
+	}
+	else if (msg <= IOPMU_INBOUND_MSG0_MAX)
+		hba->msg_done = 1;
+}
+
+static inline struct hptiop_request *get_req(struct hptiop_hba *hba)
+{
+	struct hptiop_request *ret;
+
+	dprintk("get_req : req=%p\n", hba->req_list);
+
+	ret = hba->req_list;
+	if (ret)
+		hba->req_list = ret->next;
+
+	return ret;
+}
+
+static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req)
+{
+	dprintk("free_req(%d, %p)\n", req->index, req);
+	req->next = hba->req_list;
+	hba->req_list = req;
+}
+
+static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag)
+{
+	struct hpt_iop_request_scsi_command *req;
+	struct scsi_cmnd *scp;
+
+	req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt;
+	dprintk("hptiop_host_request_callback: req=%p, type=%d, "
+			"result=%d, context=0x%x tag=%d\n",
+			req, req->header.type, req->header.result,
+			req->header.context, tag);
+
+	BUG_ON(!req->header.result);
+	BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND));
+
+	scp = hba->reqs[tag].scp;
+
+	if (HPT_SCP(scp)->mapped) {
+		if (scp->use_sg)
+			pci_unmap_sg(hba->pcidev,
+				(struct scatterlist *)scp->request_buffer,
+				scp->use_sg,
+				scp->sc_data_direction
+			);
+		else
+			pci_unmap_single(hba->pcidev,
+				HPT_SCP(scp)->dma_handle,
+				scp->request_bufflen,
+				scp->sc_data_direction
+			);
+	}
+
+	switch (le32_to_cpu(req->header.result)) {
+	case IOP_RESULT_SUCCESS:
+		scp->result = (DID_OK<<16);
+		break;
+	case IOP_RESULT_BAD_TARGET:
+		scp->result = (DID_BAD_TARGET<<16);
+		break;
+	case IOP_RESULT_BUSY:
+		scp->result = (DID_BUS_BUSY<<16);
+		break;
+	case IOP_RESULT_RESET:
+		scp->result = (DID_RESET<<16);
+		break;
+	case IOP_RESULT_FAIL:
+		scp->result = (DID_ERROR<<16);
+		break;
+	case IOP_RESULT_INVALID_REQUEST:
+		scp->result = (DID_ABORT<<16);
+		break;
+	case IOP_RESULT_MODE_SENSE_CHECK_CONDITION:
+		scp->result = SAM_STAT_CHECK_CONDITION;
+		memset(&scp->sense_buffer,
+				0, sizeof(scp->sense_buffer));
+		memcpy(&scp->sense_buffer,
+			&req->sg_list, le32_to_cpu(req->dataxfer_length));
+		break;
+
+	default:
+		scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) |
+					(DID_ABORT<<16);
+		break;
+	}
+
+	dprintk("scsi_done(%p)\n", scp);
+	scp->scsi_done(scp);
+	free_req(hba, &hba->reqs[tag]);
+}
+
+void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag)
+{
+	struct hpt_iop_request_header __iomem *req;
+	struct hpt_iop_request_ioctl_command __iomem *p;
+	struct hpt_ioctl_k *arg;
+
+	req = (struct hpt_iop_request_header __iomem *)
+			((unsigned long)hba->iop + tag);
+	dprintk("hptiop_iop_request_callback: req=%p, type=%d, "
+			"result=%d, context=0x%x tag=%d\n",
+			req, readl(&req->type), readl(&req->result),
+			readl(&req->context), tag);
+
+	BUG_ON(!readl(&req->result));
+	BUG_ON(readl(&req->type) != IOP_REQUEST_TYPE_IOCTL_COMMAND);
+
+	p = (struct hpt_iop_request_ioctl_command __iomem *)req;
+	arg = (struct hpt_ioctl_k *)(unsigned long)
+		(readl(&req->context) |
+			((u64)readl(&req->context_hi32)<<32));
+
+	if (readl(&req->result) == IOP_RESULT_SUCCESS) {
+		arg->result = HPT_IOCTL_RESULT_OK;
+
+		if (arg->outbuf_size)
+			memcpy_fromio(arg->outbuf,
+				&p->buf[(readl(&p->inbuf_size) + 3)& ~3],
+				arg->outbuf_size);
+
+		if (arg->bytes_returned)
+			*arg->bytes_returned = arg->outbuf_size;
+	}
+	else
+		arg->result = HPT_IOCTL_RESULT_FAILED;
+
+	arg->done(arg);
+	writel(tag, &hba->iop->outbound_queue);
+}
+
+static irqreturn_t hptiop_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct hptiop_hba  *hba = dev_id;
+	int  handled;
+	unsigned long flags;
+
+	spin_lock_irqsave(hba->host->host_lock, flags);
+	handled = __iop_intr(hba);
+	spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+	return handled;
+}
+
+static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg)
+{
+	struct Scsi_Host *host = scp->device->host;
+	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+	struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer;
+
+	/*
+	 * though we'll not get non-use_sg fields anymore,
+	 * keep use_sg checking anyway
+	 */
+	if (scp->use_sg) {
+		int idx;
+
+		HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev,
+				sglist, scp->use_sg,
+				scp->sc_data_direction);
+		HPT_SCP(scp)->mapped = 1;
+		BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors);
+
+		for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) {
+			psg[idx].pci_address =
+				cpu_to_le64(sg_dma_address(&sglist[idx]));
+			psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx]));
+			psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ?
+				cpu_to_le32(1) : 0;
+		}
+
+		return HPT_SCP(scp)->sgcnt;
+	} else {
+		HPT_SCP(scp)->dma_handle = pci_map_single(
+				hba->pcidev,
+				scp->request_buffer,
+				scp->request_bufflen,
+				scp->sc_data_direction
+			);
+		HPT_SCP(scp)->mapped = 1;
+		psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle);
+		psg->size = cpu_to_le32(scp->request_bufflen);
+		psg->eot = cpu_to_le32(1);
+		return 1;
+	}
+}
+
+static int hptiop_queuecommand(struct scsi_cmnd *scp,
+				void (*done)(struct scsi_cmnd *))
+{
+	struct Scsi_Host *host = scp->device->host;
+	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+	struct hpt_iop_request_scsi_command *req;
+	int sg_count = 0;
+	struct hptiop_request *_req;
+
+	BUG_ON(!done);
+	scp->scsi_done = done;
+
+	_req = get_req(hba);
+	if (_req == NULL) {
+		dprintk("hptiop_queuecmd : no free req\n");
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	_req->scp = scp;
+
+	dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) "
+			"req_index=%d, req=%p\n",
+			scp,
+			host->host_no, scp->device->channel,
+			scp->device->id, scp->device->lun,
+			*((u32 *)&scp->cmnd),
+			*((u32 *)&scp->cmnd + 1),
+			*((u32 *)&scp->cmnd + 2),
+			_req->index, _req->req_virt);
+
+	scp->result = 0;
+
+	if (scp->device->channel || scp->device->lun ||
+			scp->device->id > hba->max_devices) {
+		scp->result = DID_BAD_TARGET << 16;
+		free_req(hba, _req);
+		goto cmd_done;
+	}
+
+	req = (struct hpt_iop_request_scsi_command *)_req->req_virt;
+
+	/* build S/G table */
+	if (scp->request_bufflen)
+		sg_count = hptiop_buildsgl(scp, req->sg_list);
+	else
+		HPT_SCP(scp)->mapped = 0;
+
+	req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT);
+	req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND);
+	req->header.result = cpu_to_le32(IOP_RESULT_PENDING);
+	req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT |
+							(u32)_req->index);
+	req->header.context_hi32 = 0;
+	req->dataxfer_length = cpu_to_le32(scp->request_bufflen);
+	req->channel = scp->device->channel;
+	req->target = scp->device->id;
+	req->lun = scp->device->lun;
+	req->header.size = cpu_to_le32(
+				sizeof(struct hpt_iop_request_scsi_command)
+				 - sizeof(struct hpt_iopsg)
+				 + sg_count * sizeof(struct hpt_iopsg));
+
+	memcpy(req->cdb, scp->cmnd, sizeof(req->cdb));
+
+	writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy,
+			&hba->iop->inbound_queue);
+
+	return 0;
+
+cmd_done:
+	dprintk("scsi_done(scp=%p)\n", scp);
+	scp->scsi_done(scp);
+	return 0;
+}
+
+static const char *hptiop_info(struct Scsi_Host *host)
+{
+	return driver_name_long;
+}
+
+static int hptiop_reset_hba(struct hptiop_hba *hba)
+{
+	if (atomic_xchg(&hba->resetting, 1) == 0) {
+		atomic_inc(&hba->reset_count);
+		writel(IOPMU_INBOUND_MSG0_RESET,
+				&hba->iop->outbound_msgaddr0);
+		hptiop_pci_posting_flush(hba->iop);
+	}
+
+	wait_event_timeout(hba->reset_wq,
+			atomic_read(&hba->resetting) == 0, 60 * HZ);
+
+	if (atomic_read(&hba->resetting)) {
+		/* IOP is in unkown state, abort reset */
+		printk(KERN_ERR "scsi%d: reset failed\n", hba->host->host_no);
+		return -1;
+	}
+
+	if (iop_send_sync_msg(hba,
+		IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
+		dprintk("scsi%d: fail to start background task\n",
+				hba->host->host_no);
+	}
+
+	return 0;
+}
+
+static int hptiop_reset(struct scsi_cmnd *scp)
+{
+	struct Scsi_Host * host = scp->device->host;
+	struct hptiop_hba * hba = (struct hptiop_hba *)host->hostdata;
+
+	printk(KERN_WARNING "hptiop_reset(%d/%d/%d) scp=%p\n",
+			scp->device->host->host_no, scp->device->channel,
+			scp->device->id, scp);
+
+	return hptiop_reset_hba(hba)? FAILED : SUCCESS;
+}
+
+static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev,
+						int queue_depth)
+{
+	if(queue_depth > 256)
+		queue_depth = 256;
+	scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+	return queue_depth;
+}
+
+struct hptiop_getinfo {
+	char __user *buffer;
+	loff_t buflength;
+	loff_t bufoffset;
+	loff_t buffillen;
+	loff_t filpos;
+};
+
+static void hptiop_copy_mem_info(struct hptiop_getinfo *pinfo,
+					char *data, int datalen)
+{
+	if (pinfo->filpos < pinfo->bufoffset) {
+		if (pinfo->filpos + datalen <= pinfo->bufoffset) {
+			pinfo->filpos += datalen;
+			return;
+		} else {
+			data += (pinfo->bufoffset - pinfo->filpos);
+			datalen  -= (pinfo->bufoffset - pinfo->filpos);
+			pinfo->filpos = pinfo->bufoffset;
+		}
+	}
+
+	pinfo->filpos += datalen;
+	if (pinfo->buffillen == pinfo->buflength)
+		return;
+
+	if (pinfo->buflength - pinfo->buffillen < datalen)
+		datalen = pinfo->buflength - pinfo->buffillen;
+
+	if (copy_to_user(pinfo->buffer + pinfo->buffillen, data, datalen))
+		return;
+
+	pinfo->buffillen += datalen;
+}
+
+static int hptiop_copy_info(struct hptiop_getinfo *pinfo, char *fmt, ...)
+{
+	va_list args;
+	char buf[128];
+	int len;
+
+	va_start(args, fmt);
+	len = vsnprintf(buf, sizeof(buf), fmt, args);
+	va_end(args);
+	hptiop_copy_mem_info(pinfo, buf, len);
+	return len;
+}
+
+static void hptiop_ioctl_done(struct hpt_ioctl_k *arg)
+{
+	arg->done = NULL;
+	wake_up(&arg->hba->ioctl_wq);
+}
+
+static void hptiop_do_ioctl(struct hpt_ioctl_k *arg)
+{
+	struct hptiop_hba *hba = arg->hba;
+	u32 val;
+	struct hpt_iop_request_ioctl_command __iomem *req;
+	int ioctl_retry = 0;
+
+	dprintk("scsi%d: hptiop_do_ioctl\n", hba->host->host_no);
+
+	/*
+	 * check (in + out) buff size from application.
+	 * outbuf must be dword aligned.
+	 */
+	if (((arg->inbuf_size + 3) & ~3) + arg->outbuf_size >
+			hba->max_request_size
+				- sizeof(struct hpt_iop_request_header)
+				- 4 * sizeof(u32)) {
+		dprintk("scsi%d: ioctl buf size (%d/%d) is too large\n",
+				hba->host->host_no,
+				arg->inbuf_size, arg->outbuf_size);
+		arg->result = HPT_IOCTL_RESULT_FAILED;
+		return;
+	}
+
+retry:
+	spin_lock_irq(hba->host->host_lock);
+
+	val = readl(&hba->iop->inbound_queue);
+	if (val == IOPMU_QUEUE_EMPTY) {
+		spin_unlock_irq(hba->host->host_lock);
+		dprintk("scsi%d: no free req for ioctl\n", hba->host->host_no);
+		arg->result = -1;
+		return;
+	}
+
+	req = (struct hpt_iop_request_ioctl_command __iomem *)
+			((unsigned long)hba->iop + val);
+
+	writel(HPT_CTL_CODE_LINUX_TO_IOP(arg->ioctl_code),
+			&req->ioctl_code);
+	writel(arg->inbuf_size, &req->inbuf_size);
+	writel(arg->outbuf_size, &req->outbuf_size);
+
+	/*
+	 * use the buffer on the IOP local memory first, then copy it
+	 * back to host.
+	 * the caller's request buffer shoudl be little-endian.
+	 */
+	if (arg->inbuf_size)
+		memcpy_toio(req->buf, arg->inbuf, arg->inbuf_size);
+
+	/* correct the controller ID for IOP */
+	if ((arg->ioctl_code == HPT_IOCTL_GET_CHANNEL_INFO ||
+		arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO_V2 ||
+		arg->ioctl_code == HPT_IOCTL_GET_CONTROLLER_INFO)
+		&& arg->inbuf_size >= sizeof(u32))
+		writel(0, req->buf);
+
+	writel(IOP_REQUEST_TYPE_IOCTL_COMMAND, &req->header.type);
+	writel(0, &req->header.flags);
+	writel(offsetof(struct hpt_iop_request_ioctl_command, buf)
+			+ arg->inbuf_size, &req->header.size);
+	writel((u32)(unsigned long)arg, &req->header.context);
+	writel(BITS_PER_LONG > 32 ? (u32)((unsigned long)arg>>32) : 0,
+			&req->header.context_hi32);
+	writel(IOP_RESULT_PENDING, &req->header.result);
+
+	arg->result = HPT_IOCTL_RESULT_FAILED;
+	arg->done = hptiop_ioctl_done;
+
+	writel(val, &hba->iop->inbound_queue);
+	hptiop_pci_posting_flush(hba->iop);
+
+	spin_unlock_irq(hba->host->host_lock);
+
+	wait_event_timeout(hba->ioctl_wq, arg->done == NULL, 60 * HZ);
+
+	if (arg->done != NULL) {
+		hptiop_reset_hba(hba);
+		if (ioctl_retry++ < 3)
+			goto retry;
+	}
+
+	dprintk("hpt_iop_ioctl %x result %d\n",
+			arg->ioctl_code, arg->result);
+}
+
+static int __hpt_do_ioctl(struct hptiop_hba *hba, u32 code, void *inbuf,
+			u32 insize, void *outbuf, u32 outsize)
+{
+	struct hpt_ioctl_k arg;
+	arg.hba = hba;
+	arg.ioctl_code = code;
+	arg.inbuf = inbuf;
+	arg.outbuf = outbuf;
+	arg.inbuf_size = insize;
+	arg.outbuf_size = outsize;
+	arg.bytes_returned = NULL;
+	hptiop_do_ioctl(&arg);
+	return arg.result;
+}
+
+static inline int hpt_id_valid(__le32 id)
+{
+	return id != 0 && id != cpu_to_le32(0xffffffff);
+}
+
+static int hptiop_get_controller_info(struct hptiop_hba *hba,
+					struct hpt_controller_info *pinfo)
+{
+	int id = 0;
+
+	return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CONTROLLER_INFO,
+		&id, sizeof(int), pinfo, sizeof(*pinfo));
+}
+
+
+static int hptiop_get_channel_info(struct hptiop_hba *hba, int bus,
+					struct hpt_channel_info *pinfo)
+{
+	u32 ids[2];
+
+	ids[0] = 0;
+	ids[1] = bus;
+	return __hpt_do_ioctl(hba, HPT_IOCTL_GET_CHANNEL_INFO,
+				ids, sizeof(ids), pinfo, sizeof(*pinfo));
+
+}
+
+static int hptiop_get_logical_devices(struct hptiop_hba *hba,
+					__le32 *pids, int maxcount)
+{
+	int i;
+	u32 count = maxcount - 1;
+
+	if (__hpt_do_ioctl(hba, HPT_IOCTL_GET_LOGICAL_DEVICES,
+			&count, sizeof(u32),
+			pids, sizeof(u32) * maxcount))
+		return -1;
+
+	maxcount = le32_to_cpu(pids[0]);
+	for (i = 0; i < maxcount; i++)
+		pids[i] = pids[i+1];
+
+	return maxcount;
+}
+
+static int hptiop_get_device_info_v3(struct hptiop_hba *hba, __le32 id,
+				struct hpt_logical_device_info_v3 *pinfo)
+{
+	return __hpt_do_ioctl(hba, HPT_IOCTL_GET_DEVICE_INFO_V3,
+				&id, sizeof(u32),
+				pinfo, sizeof(*pinfo));
+}
+
+static const char *get_array_status(struct hpt_logical_device_info_v3 *devinfo)
+{
+	static char s[64];
+	u32 flags = le32_to_cpu(devinfo->u.array.flags);
+	u32 trans_prog = le32_to_cpu(devinfo->u.array.transforming_progress);
+	u32 reb_prog = le32_to_cpu(devinfo->u.array.rebuilding_progress);
+
+	if (flags & ARRAY_FLAG_DISABLED)
+		return "Disabled";
+	else if (flags & ARRAY_FLAG_TRANSFORMING)
+		sprintf(s, "Expanding/Migrating %d.%d%%%s%s",
+			trans_prog / 100,
+			trans_prog % 100,
+			(flags & (ARRAY_FLAG_NEEDBUILDING|ARRAY_FLAG_BROKEN))?
+					", Critical" : "",
+			((flags & ARRAY_FLAG_NEEDINITIALIZING) &&
+			 !(flags & ARRAY_FLAG_REBUILDING) &&
+			 !(flags & ARRAY_FLAG_INITIALIZING))?
+					", Unintialized" : "");
+	else if ((flags & ARRAY_FLAG_BROKEN) &&
+				devinfo->u.array.array_type != AT_RAID6)
+		return "Critical";
+	else if (flags & ARRAY_FLAG_REBUILDING)
+		sprintf(s,
+			(flags & ARRAY_FLAG_NEEDINITIALIZING)?
+				"%sBackground initializing %d.%d%%" :
+					"%sRebuilding %d.%d%%",
+			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
+			reb_prog / 100,
+			reb_prog % 100);
+	else if (flags & ARRAY_FLAG_VERIFYING)
+		sprintf(s, "%sVerifying %d.%d%%",
+			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
+			reb_prog / 100,
+			reb_prog % 100);
+	else if (flags & ARRAY_FLAG_INITIALIZING)
+		sprintf(s, "%sForground initializing %d.%d%%",
+			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
+			reb_prog / 100,
+			reb_prog % 100);
+	else if (flags & ARRAY_FLAG_NEEDTRANSFORM)
+		sprintf(s,"%s%s%s", "Need Expanding/Migrating",
+			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "",
+			((flags & ARRAY_FLAG_NEEDINITIALIZING) &&
+			 !(flags & ARRAY_FLAG_REBUILDING) &&
+			 !(flags & ARRAY_FLAG_INITIALIZING))?
+				", Unintialized" : "");
+	else if (flags & ARRAY_FLAG_NEEDINITIALIZING &&
+		!(flags & ARRAY_FLAG_REBUILDING) &&
+		!(flags & ARRAY_FLAG_INITIALIZING))
+		sprintf(s,"%sUninitialized",
+			(flags & ARRAY_FLAG_BROKEN)? "Critical, " : "");
+	else if ((flags & ARRAY_FLAG_NEEDBUILDING) ||
+			(flags & ARRAY_FLAG_BROKEN))
+		return "Critical";
+	else
+		return "Normal";
+	return s;
+}
+
+static void hptiop_dump_devinfo(struct hptiop_hba *hba,
+			struct hptiop_getinfo *pinfo, __le32 id, int indent)
+{
+	struct hpt_logical_device_info_v3 devinfo;
+	int i;
+	u64 capacity;
+
+	for (i = 0; i < indent; i++)
+		hptiop_copy_info(pinfo, "\t");
+
+	if (hptiop_get_device_info_v3(hba, id, &devinfo)) {
+		hptiop_copy_info(pinfo, "unknown\n");
+		return;
+	}
+
+	switch (devinfo.type) {
+
+	case LDT_DEVICE: {
+		struct hd_driveid *driveid;
+		u32 flags = le32_to_cpu(devinfo.u.device.flags);
+
+		driveid = (struct hd_driveid *)devinfo.u.device.ident;
+		/* model[] is 40 chars long, but we just want 20 chars here */
+		driveid->model[20] = 0;
+
+		if (indent)
+			if (flags & DEVICE_FLAG_DISABLED)
+				hptiop_copy_info(pinfo,"Missing\n");
+			else
+				hptiop_copy_info(pinfo, "CH%d %s\n",
+					devinfo.u.device.path_id + 1,
+					driveid->model);
+		else {
+			capacity = le64_to_cpu(devinfo.capacity) * 512;
+			do_div(capacity, 1000000);
+			hptiop_copy_info(pinfo,
+				"CH%d %s, %lluMB, %s %s%s%s%s\n",
+				devinfo.u.device.path_id + 1,
+				driveid->model,
+				capacity,
+				(flags & DEVICE_FLAG_DISABLED)?
+					"Disabled" : "Normal",
+				devinfo.u.device.read_ahead_enabled?
+						"[RA]" : "",
+				devinfo.u.device.write_cache_enabled?
+						"[WC]" : "",
+				devinfo.u.device.TCQ_enabled?
+						"[TCQ]" : "",
+				devinfo.u.device.NCQ_enabled?
+						"[NCQ]" : ""
+			);
+		}
+		break;
+	}
+
+	case LDT_ARRAY:
+		if (devinfo.target_id != INVALID_TARGET_ID)
+			hptiop_copy_info(pinfo, "[DISK %d_%d] ",
+					devinfo.vbus_id, devinfo.target_id);
+
+		capacity = le64_to_cpu(devinfo.capacity) * 512;
+		do_div(capacity, 1000000);
+		hptiop_copy_info(pinfo, "%s (%s), %lluMB, %s\n",
+			devinfo.u.array.name,
+			devinfo.u.array.array_type==AT_RAID0? "RAID0" :
+				devinfo.u.array.array_type==AT_RAID1? "RAID1" :
+				devinfo.u.array.array_type==AT_RAID5? "RAID5" :
+				devinfo.u.array.array_type==AT_RAID6? "RAID6" :
+				devinfo.u.array.array_type==AT_JBOD? "JBOD" :
+					"unknown",
+			capacity,
+			get_array_status(&devinfo));
+		for (i = 0; i < devinfo.u.array.ndisk; i++) {
+			if (hpt_id_valid(devinfo.u.array.members[i])) {
+				if (cpu_to_le16(1<<i) &
+					devinfo.u.array.critical_members)
+					hptiop_copy_info(pinfo, "\t*");
+				hptiop_dump_devinfo(hba, pinfo,
+					devinfo.u.array.members[i], indent+1);
+			}
+			else
+				hptiop_copy_info(pinfo, "\tMissing\n");
+		}
+		if (id == devinfo.u.array.transform_source) {
+			hptiop_copy_info(pinfo, "\tExpanding/Migrating to:\n");
+			hptiop_dump_devinfo(hba, pinfo,
+				devinfo.u.array.transform_target, indent+1);
+		}
+		break;
+	}
+}
+
+static ssize_t hptiop_show_version(struct class_device *class_dev, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver);
+}
+
+static ssize_t hptiop_cdev_read(struct file *filp, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	struct hptiop_hba *hba = filp->private_data;
+	struct hptiop_getinfo info;
+	int i, j, ndev;
+	struct hpt_controller_info con_info;
+	struct hpt_channel_info chan_info;
+	__le32 ids[32];
+
+	info.buffer     = buf;
+	info.buflength  = count;
+	info.bufoffset  = ppos ? *ppos : 0;
+	info.filpos     = 0;
+	info.buffillen  = 0;
+
+	if (hptiop_get_controller_info(hba, &con_info))
+		return -EIO;
+
+	for (i = 0; i < con_info.num_buses; i++) {
+		if (hptiop_get_channel_info(hba, i, &chan_info) == 0) {
+			if (hpt_id_valid(chan_info.devices[0]))
+				hptiop_dump_devinfo(hba, &info,
+						chan_info.devices[0], 0);
+			if (hpt_id_valid(chan_info.devices[1]))
+				hptiop_dump_devinfo(hba, &info,
+						chan_info.devices[1], 0);
+		}
+	}
+
+	ndev = hptiop_get_logical_devices(hba, ids,
+					sizeof(ids) / sizeof(ids[0]));
+
+	/*
+	 * if hptiop_get_logical_devices fails, ndev==-1 and it just
+	 * output nothing here
+	 */
+	for (j = 0; j < ndev; j++)
+		hptiop_dump_devinfo(hba, &info, ids[j], 0);
+
+	if (ppos)
+		*ppos += info.buffillen;
+
+	return info.buffillen;
+}
+
+static int hptiop_cdev_ioctl(struct inode *inode,  struct file *file,
+					unsigned int cmd, unsigned long arg)
+{
+	struct hptiop_hba *hba = file->private_data;
+	struct hpt_ioctl_u ioctl_u;
+	struct hpt_ioctl_k ioctl_k;
+	u32 bytes_returned;
+	int err = -EINVAL;
+
+	if (copy_from_user(&ioctl_u,
+		(void __user *)arg, sizeof(struct hpt_ioctl_u)))
+		return -EINVAL;
+
+	if (ioctl_u.magic != HPT_IOCTL_MAGIC)
+		return -EINVAL;
+
+	ioctl_k.ioctl_code = ioctl_u.ioctl_code;
+	ioctl_k.inbuf = NULL;
+	ioctl_k.inbuf_size = ioctl_u.inbuf_size;
+	ioctl_k.outbuf = NULL;
+	ioctl_k.outbuf_size = ioctl_u.outbuf_size;
+	ioctl_k.hba = hba;
+	ioctl_k.bytes_returned = &bytes_returned;
+
+	/* verify user buffer */
+	if ((ioctl_k.inbuf_size && !access_ok(VERIFY_READ,
+			ioctl_u.inbuf, ioctl_k.inbuf_size)) ||
+		(ioctl_k.outbuf_size && !access_ok(VERIFY_WRITE,
+			ioctl_u.outbuf, ioctl_k.outbuf_size)) ||
+		(ioctl_u.bytes_returned && !access_ok(VERIFY_WRITE,
+			ioctl_u.bytes_returned, sizeof(u32))) ||
+		ioctl_k.inbuf_size + ioctl_k.outbuf_size > 0x10000) {
+
+		dprintk("scsi%d: got bad user address\n", hba->host->host_no);
+		return -EINVAL;
+	}
+
+	/* map buffer to kernel. */
+	if (ioctl_k.inbuf_size) {
+		ioctl_k.inbuf = kmalloc(ioctl_k.inbuf_size, GFP_KERNEL);
+		if (!ioctl_k.inbuf) {
+			dprintk("scsi%d: fail to alloc inbuf\n",
+					hba->host->host_no);
+			err = -ENOMEM;
+			goto err_exit;
+		}
+
+		if (copy_from_user(ioctl_k.inbuf,
+				ioctl_u.inbuf, ioctl_k.inbuf_size)) {
+			goto err_exit;
+		}
+	}
+
+	if (ioctl_k.outbuf_size) {
+		ioctl_k.outbuf = kmalloc(ioctl_k.outbuf_size, GFP_KERNEL);
+		if (!ioctl_k.outbuf) {
+			dprintk("scsi%d: fail to alloc outbuf\n",
+					hba->host->host_no);
+			err = -ENOMEM;
+			goto err_exit;
+		}
+	}
+
+	hptiop_do_ioctl(&ioctl_k);
+
+	if (ioctl_k.result == HPT_IOCTL_RESULT_OK) {
+		if (ioctl_k.outbuf_size &&
+			copy_to_user(ioctl_u.outbuf,
+				ioctl_k.outbuf, ioctl_k.outbuf_size))
+			goto err_exit;
+
+		if (ioctl_u.bytes_returned &&
+			copy_to_user(ioctl_u.bytes_returned,
+				&bytes_returned, sizeof(u32)))
+			goto err_exit;
+
+		err = 0;
+	}
+
+err_exit:
+	kfree(ioctl_k.inbuf);
+	kfree(ioctl_k.outbuf);
+
+	return err;
+}
+
+static int hptiop_cdev_open(struct inode *inode, struct file *file)
+{
+	struct hptiop_hba *hba;
+	unsigned i = 0, minor = iminor(inode);
+	int ret = -ENODEV;
+
+	spin_lock(&hptiop_hba_list_lock);
+	list_for_each_entry(hba, &hptiop_hba_list, link) {
+		if (i == minor) {
+			file->private_data = hba;
+			ret = 0;
+			goto out;
+		}
+		i++;
+	}
+
+out:
+	spin_unlock(&hptiop_hba_list_lock);
+	return ret;
+}
+
+static struct file_operations hptiop_cdev_fops = {
+	.owner = THIS_MODULE,
+	.read  = hptiop_cdev_read,
+	.ioctl = hptiop_cdev_ioctl,
+	.open  = hptiop_cdev_open,
+};
+
+static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *host = class_to_shost(class_dev);
+	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+
+	return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n",
+				hba->firmware_version >> 24,
+				(hba->firmware_version >> 16) & 0xff,
+				(hba->firmware_version >> 8) & 0xff,
+				hba->firmware_version & 0xff);
+}
+
+static struct class_device_attribute hptiop_attr_version = {
+	.attr = {
+		.name = "driver-version",
+		.mode = S_IRUGO,
+	},
+	.show = hptiop_show_version,
+};
+
+static struct class_device_attribute hptiop_attr_fw_version = {
+	.attr = {
+		.name = "firmware-version",
+		.mode = S_IRUGO,
+	},
+	.show = hptiop_show_fw_version,
+};
+
+static struct class_device_attribute *hptiop_attrs[] = {
+	&hptiop_attr_version,
+	&hptiop_attr_fw_version,
+	NULL
+};
+
+static struct scsi_host_template driver_template = {
+	.module                     = THIS_MODULE,
+	.name                       = driver_name,
+	.queuecommand               = hptiop_queuecommand,
+	.eh_device_reset_handler    = hptiop_reset,
+	.eh_bus_reset_handler       = hptiop_reset,
+	.info                       = hptiop_info,
+	.unchecked_isa_dma          = 0,
+	.emulated                   = 0,
+	.use_clustering             = ENABLE_CLUSTERING,
+	.proc_name                  = driver_name,
+	.shost_attrs                = hptiop_attrs,
+	.this_id                    = -1,
+	.change_queue_depth         = hptiop_adjust_disk_queue_depth,
+};
+
+static int __devinit hptiop_probe(struct pci_dev *pcidev,
+					const struct pci_device_id *id)
+{
+	struct Scsi_Host *host = NULL;
+	struct hptiop_hba *hba;
+	struct hpt_iop_request_get_config iop_config;
+	struct hpt_iop_request_set_config set_config;
+	dma_addr_t start_phy;
+	void *start_virt;
+	u32 offset, i, req_size;
+
+	dprintk("hptiop_probe(%p)\n", pcidev);
+
+	if (pci_enable_device(pcidev)) {
+		printk(KERN_ERR "hptiop: fail to enable pci device\n");
+		return -ENODEV;
+	}
+
+	printk(KERN_INFO "adapter at PCI %d:%d:%d, IRQ %d\n",
+		pcidev->bus->number, pcidev->devfn >> 3, pcidev->devfn & 7,
+		pcidev->irq);
+
+	pci_set_master(pcidev);
+
+	/* Enable 64bit DMA if possible */
+	if (pci_set_dma_mask(pcidev, DMA_64BIT_MASK)) {
+		if (pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
+			printk(KERN_ERR "hptiop: fail to set dma_mask\n");
+			goto disable_pci_device;
+		}
+	}
+
+	if (pci_request_regions(pcidev, driver_name)) {
+		printk(KERN_ERR "hptiop: pci_request_regions failed\n");
+		goto disable_pci_device;
+	}
+
+	host = scsi_host_alloc(&driver_template, sizeof(struct hptiop_hba));
+	if (!host) {
+		printk(KERN_ERR "hptiop: fail to alloc scsi host\n");
+		goto free_pci_regions;
+	}
+
+	hba = (struct hptiop_hba *)host->hostdata;
+
+	hba->pcidev = pcidev;
+	hba->host = host;
+	hba->initialized = 0;
+
+	atomic_set(&hba->resetting, 0);
+	atomic_set(&hba->reset_count, 0);
+
+	init_waitqueue_head(&hba->reset_wq);
+	init_waitqueue_head(&hba->ioctl_wq);
+
+	host->max_lun = 1;
+	host->max_channel = 0;
+	host->io_port = 0;
+	host->n_io_port = 0;
+	host->irq = pcidev->irq;
+
+	if (hptiop_map_pci_bar(hba))
+		goto free_scsi_host;
+
+	if (iop_wait_ready(hba->iop, 20000)) {
+		printk(KERN_ERR "scsi%d: firmware not ready\n",
+				hba->host->host_no);
+		goto unmap_pci_bar;
+	}
+
+	if (iop_get_config(hba, &iop_config)) {
+		printk(KERN_ERR "scsi%d: get config failed\n",
+				hba->host->host_no);
+		goto unmap_pci_bar;
+	}
+
+	hba->max_requests = min(le32_to_cpu(iop_config.max_requests),
+				HPTIOP_MAX_REQUESTS);
+	hba->max_devices = le32_to_cpu(iop_config.max_devices);
+	hba->max_request_size = le32_to_cpu(iop_config.request_size);
+	hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count);
+	hba->firmware_version = le32_to_cpu(iop_config.firmware_version);
+	hba->sdram_size = le32_to_cpu(iop_config.sdram_size);
+
+	host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9;
+	host->max_id = le32_to_cpu(iop_config.max_devices);
+	host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count);
+	host->can_queue = le32_to_cpu(iop_config.max_requests);
+	host->cmd_per_lun = le32_to_cpu(iop_config.max_requests);
+	host->max_cmd_len = 16;
+
+	set_config.vbus_id = cpu_to_le32(host->host_no);
+	set_config.iop_id = cpu_to_le32(host->host_no);
+
+	if (iop_set_config(hba, &set_config)) {
+		printk(KERN_ERR "scsi%d: set config failed\n",
+				hba->host->host_no);
+		goto unmap_pci_bar;
+	}
+
+	if (scsi_add_host(host, &pcidev->dev)) {
+		printk(KERN_ERR "scsi%d: scsi_add_host failed\n",
+					hba->host->host_no);
+		goto unmap_pci_bar;
+	}
+
+	pci_set_drvdata(pcidev, host);
+
+	if (request_irq(pcidev->irq, hptiop_intr, SA_SHIRQ,
+					driver_name, hba)) {
+		printk(KERN_ERR "scsi%d: request irq %d failed\n",
+					hba->host->host_no, pcidev->irq);
+		goto remove_scsi_host;
+	}
+
+	/* Allocate request mem */
+	req_size = sizeof(struct hpt_iop_request_scsi_command)
+		+ sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1);
+	if ((req_size& 0x1f) != 0)
+		req_size = (req_size + 0x1f) & ~0x1f;
+
+	dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests);
+
+	hba->req_size = req_size;
+	start_virt = dma_alloc_coherent(&pcidev->dev,
+				hba->req_size*hba->max_requests + 0x20,
+				&start_phy, GFP_KERNEL);
+
+	if (!start_virt) {
+		printk(KERN_ERR "scsi%d: fail to alloc request mem\n",
+					hba->host->host_no);
+		goto free_request_irq;
+	}
+
+	hba->dma_coherent = start_virt;
+	hba->dma_coherent_handle = start_phy;
+
+	if ((start_phy & 0x1f) != 0)
+	{
+		offset = ((start_phy + 0x1f) & ~0x1f) - start_phy;
+		start_phy += offset;
+		start_virt += offset;
+	}
+
+	hba->req_list = start_virt;
+	for (i = 0; i < hba->max_requests; i++) {
+		hba->reqs[i].next = NULL;
+		hba->reqs[i].req_virt = start_virt;
+		hba->reqs[i].req_shifted_phy = start_phy >> 5;
+		hba->reqs[i].index = i;
+		free_req(hba, &hba->reqs[i]);
+		start_virt = (char *)start_virt + hba->req_size;
+		start_phy = start_phy + hba->req_size;
+	}
+
+	/* Enable Interrupt and start background task */
+	if (hptiop_initialize_iop(hba))
+		goto free_request_mem;
+
+	spin_lock(&hptiop_hba_list_lock);
+	list_add_tail(&hba->link, &hptiop_hba_list);
+	spin_unlock(&hptiop_hba_list_lock);
+
+	scsi_scan_host(host);
+
+	dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no);
+	return 0;
+
+free_request_mem:
+	dma_free_coherent(&hba->pcidev->dev,
+			hba->req_size*hba->max_requests + 0x20,
+			hba->dma_coherent, hba->dma_coherent_handle);
+
+free_request_irq:
+	free_irq(hba->pcidev->irq, hba);
+
+remove_scsi_host:
+	scsi_remove_host(host);
+
+unmap_pci_bar:
+	iounmap(hba->iop);
+
+free_pci_regions:
+	pci_release_regions(pcidev) ;
+
+free_scsi_host:
+	scsi_host_put(host);
+
+disable_pci_device:
+	pci_disable_device(pcidev);
+
+	dprintk("scsi%d: hptiop_probe fail\n", host->host_no);
+	return -ENODEV;
+}
+
+static void hptiop_shutdown(struct pci_dev *pcidev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pcidev);
+	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+	struct hpt_iopmu __iomem *iop = hba->iop;
+	u32    int_mask;
+
+	dprintk("hptiop_shutdown(%p)\n", hba);
+
+	/* stop the iop */
+	if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
+		printk(KERN_ERR "scsi%d: shutdown the iop timeout\n",
+					hba->host->host_no);
+
+	/* disable all outbound interrupts */
+	int_mask = readl(&iop->outbound_intmask);
+	writel(int_mask |
+		IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE,
+		&iop->outbound_intmask);
+	hptiop_pci_posting_flush(iop);
+}
+
+static void hptiop_remove(struct pci_dev *pcidev)
+{
+	struct Scsi_Host *host = pci_get_drvdata(pcidev);
+	struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata;
+
+	dprintk("scsi%d: hptiop_remove\n", hba->host->host_no);
+
+	scsi_remove_host(host);
+
+	spin_lock(&hptiop_hba_list_lock);
+	list_del_init(&hba->link);
+	spin_unlock(&hptiop_hba_list_lock);
+
+	hptiop_shutdown(pcidev);
+
+	free_irq(hba->pcidev->irq, hba);
+
+	dma_free_coherent(&hba->pcidev->dev,
+			hba->req_size * hba->max_requests + 0x20,
+			hba->dma_coherent,
+			hba->dma_coherent_handle);
+
+	iounmap(hba->iop);
+
+	pci_release_regions(hba->pcidev);
+	pci_set_drvdata(hba->pcidev, NULL);
+	pci_disable_device(hba->pcidev);
+
+	scsi_host_put(host);
+}
+
+static struct pci_device_id hptiop_id_table[] = {
+	{ PCI_DEVICE(0x1103, 0x3220) },
+	{ PCI_DEVICE(0x1103, 0x3320) },
+	{},
+};
+
+MODULE_DEVICE_TABLE(pci, hptiop_id_table);
+
+static struct pci_driver hptiop_pci_driver = {
+	.name       = driver_name,
+	.id_table   = hptiop_id_table,
+	.probe      = hptiop_probe,
+	.remove     = hptiop_remove,
+	.shutdown   = hptiop_shutdown,
+};
+
+static int __init hptiop_module_init(void)
+{
+	int error;
+
+	printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver);
+
+	error = pci_register_driver(&hptiop_pci_driver);
+	if (error < 0)
+		return error;
+
+	hptiop_cdev_major = register_chrdev(0, "hptiop", &hptiop_cdev_fops);
+	if (hptiop_cdev_major < 0) {
+		printk(KERN_WARNING "unable to register hptiop device.\n");
+		return hptiop_cdev_major;
+	}
+
+	return 0;
+}
+
+static void __exit hptiop_module_exit(void)
+{
+	dprintk("hptiop_module_exit\n");
+	unregister_chrdev(hptiop_cdev_major, "hptiop");
+	pci_unregister_driver(&hptiop_pci_driver);
+}
+
+
+module_init(hptiop_module_init);
+module_exit(hptiop_module_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h
new file mode 100644
index 0000000..f04f7e8
--- /dev/null
+++ b/drivers/scsi/hptiop.h
@@ -0,0 +1,465 @@
+/*
+ * HighPoint RR3xxx controller driver for Linux
+ * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Please report bugs/comments/suggestions to linux@highpoint-tech.com
+ *
+ * For more information, visit http://www.highpoint-tech.com
+ */
+#ifndef _HPTIOP_H_
+#define _HPTIOP_H_
+
+/*
+ * logical device type.
+ * Identify array (logical device) and physical device.
+ */
+#define LDT_ARRAY   1
+#define LDT_DEVICE  2
+
+/*
+ * Array types
+ */
+#define AT_UNKNOWN  0
+#define AT_RAID0    1
+#define AT_RAID1    2
+#define AT_RAID5    3
+#define AT_RAID6    4
+#define AT_JBOD     7
+
+#define MAX_NAME_LENGTH     36
+#define MAX_ARRAYNAME_LEN   16
+
+#define MAX_ARRAY_MEMBERS_V1 8
+#define MAX_ARRAY_MEMBERS_V2 16
+
+/* keep definition for source code compatiblity */
+#define MAX_ARRAY_MEMBERS MAX_ARRAY_MEMBERS_V1
+
+/*
+ * array flags
+ */
+#define ARRAY_FLAG_DISABLED         0x00000001 /* The array is disabled */
+#define ARRAY_FLAG_NEEDBUILDING     0x00000002 /* need to be rebuilt */
+#define ARRAY_FLAG_REBUILDING       0x00000004 /* in rebuilding process */
+#define ARRAY_FLAG_BROKEN           0x00000008 /* broken but still working */
+#define ARRAY_FLAG_BOOTDISK         0x00000010 /* has a active partition */
+#define ARRAY_FLAG_BOOTMARK         0x00000040 /* array has boot mark set */
+#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */
+#define ARRAY_FLAG_VERIFYING        0x00000100 /* is being verified */
+#define ARRAY_FLAG_INITIALIZING     0x00000200 /* is being initialized */
+#define ARRAY_FLAG_TRANSFORMING     0x00000400 /* tranform in progress */
+#define ARRAY_FLAG_NEEDTRANSFORM    0x00000800 /* array need tranform */
+#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* initialization not done */
+#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant */
+
+/*
+ * device flags
+ */
+#define DEVICE_FLAG_DISABLED        0x00000001 /* device is disabled */
+#define DEVICE_FLAG_UNINITIALIZED   0x00010000 /* device is not initialized */
+#define DEVICE_FLAG_LEGACY          0x00020000 /* lagacy drive */
+#define DEVICE_FLAG_IS_SPARE        0x80000000 /* is a spare disk */
+
+/*
+ * ioctl codes
+ */
+#define HPT_CTL_CODE(x) (x+0xFF00)
+#define HPT_CTL_CODE_LINUX_TO_IOP(x) ((x)-0xff00)
+
+#define HPT_IOCTL_GET_CONTROLLER_INFO       HPT_CTL_CODE(2)
+#define HPT_IOCTL_GET_CHANNEL_INFO          HPT_CTL_CODE(3)
+#define HPT_IOCTL_GET_LOGICAL_DEVICES       HPT_CTL_CODE(4)
+#define HPT_IOCTL_GET_DRIVER_CAPABILITIES   HPT_CTL_CODE(19)
+#define HPT_IOCTL_GET_DEVICE_INFO_V3        HPT_CTL_CODE(46)
+#define HPT_IOCTL_GET_CONTROLLER_INFO_V2    HPT_CTL_CODE(47)
+
+/*
+ * Controller information.
+ */
+struct hpt_controller_info {
+	u8      chip_type;                    /* chip type */
+	u8      interrupt_level;              /* IRQ level */
+	u8      num_buses;                    /* bus count */
+	u8      chip_flags;
+
+	u8      product_id[MAX_NAME_LENGTH];/* product name */
+	u8      vendor_id[MAX_NAME_LENGTH]; /* vendor name */
+}
+__attribute__((packed));
+
+/*
+ * Channel information.
+ */
+struct hpt_channel_info {
+	__le32  io_port;         /* IDE Base Port Address */
+	__le32  control_port;    /* IDE Control Port Address */
+	__le32  devices[2];      /* device connected to this channel */
+}
+__attribute__((packed));
+
+/*
+ * Array information.
+ */
+struct hpt_array_info_v3 {
+	u8      name[MAX_ARRAYNAME_LEN]; /* array name */
+	u8      description[64];         /* array description */
+	u8      create_manager[16];      /* who created it */
+	__le32  create_time;             /* when created it */
+
+	u8      array_type;              /* array type */
+	u8      block_size_shift;        /* stripe size */
+	u8      ndisk;                   /* Number of ID in Members[] */
+	u8      reserved;
+
+	__le32  flags;                   /* working flags, see ARRAY_FLAG_XXX */
+	__le32  members[MAX_ARRAY_MEMBERS_V2];  /* member array/disks */
+
+	__le32  rebuilding_progress;
+	__le64  rebuilt_sectors; /* rebuilding point (LBA) for single member */
+
+	__le32  transform_source;
+	__le32  transform_target;    /* destination device ID */
+	__le32  transforming_progress;
+	__le32  signature;              /* persistent identification*/
+	__le16  critical_members;       /* bit mask of critical members */
+	__le16  reserve2;
+	__le32  reserve;
+}
+__attribute__((packed));
+
+/*
+ * physical device information.
+ */
+#define MAX_PARENTS_PER_DISK    8
+
+struct hpt_device_info_v2 {
+	u8   ctlr_id;             /* controller id */
+	u8   path_id;             /* bus */
+	u8   target_id;           /* id */
+	u8   device_mode_setting; /* Current Data Transfer mode: 0-4 PIO0-4 */
+				  /* 5-7 MW DMA0-2, 8-13 UDMA0-5 */
+	u8   device_type;         /* device type */
+	u8   usable_mode;         /* highest usable mode */
+
+#ifdef __BIG_ENDIAN_BITFIELD
+	u8   NCQ_enabled: 1;
+	u8   NCQ_supported: 1;
+	u8   TCQ_enabled: 1;
+	u8   TCQ_supported: 1;
+	u8   write_cache_enabled: 1;
+	u8   write_cache_supported: 1;
+	u8   read_ahead_enabled: 1;
+	u8   read_ahead_supported: 1;
+	u8   reserved6: 6;
+	u8   spin_up_mode: 2;
+#else
+	u8   read_ahead_supported: 1;
+	u8   read_ahead_enabled: 1;
+	u8   write_cache_supported: 1;
+	u8   write_cache_enabled: 1;
+	u8   TCQ_supported: 1;
+	u8   TCQ_enabled: 1;
+	u8   NCQ_supported: 1;
+	u8   NCQ_enabled: 1;
+	u8   spin_up_mode: 2;
+	u8   reserved6: 6;
+#endif
+
+	__le32  flags;         /* working flags, see DEVICE_FLAG_XXX */
+	u8      ident[150];    /* (partitial) Identify Data of this device */
+
+	__le64  total_free;
+	__le64  max_free;
+	__le64  bad_sectors;
+	__le32  parent_arrays[MAX_PARENTS_PER_DISK];
+}
+__attribute__((packed));
+
+/*
+ * Logical device information.
+ */
+#define INVALID_TARGET_ID   0xFF
+#define INVALID_BUS_ID      0xFF
+
+struct hpt_logical_device_info_v3 {
+	u8       type;                   /* LDT_ARRAY or LDT_DEVICE */
+	u8       cache_policy;           /* refer to CACHE_POLICY_xxx */
+	u8       vbus_id;                /* vbus sequence in vbus_list */
+	u8       target_id;              /* OS target id. 0xFF is invalid */
+					 /* OS name: DISK $VBusId_$TargetId */
+	__le64   capacity;               /* array capacity */
+	__le32   parent_array;           /* don't use this field for physical
+					    device. use ParentArrays field in
+					    hpt_device_info_v2 */
+	/* reserved statistic fields */
+	__le32   stat1;
+	__le32   stat2;
+	__le32   stat3;
+	__le32   stat4;
+
+	union {
+		struct hpt_array_info_v3 array;
+		struct hpt_device_info_v2 device;
+	} __attribute__((packed)) u;
+
+}
+__attribute__((packed));
+
+/*
+ * ioctl structure
+ */
+#define HPT_IOCTL_MAGIC   0xA1B2C3D4
+
+struct hpt_ioctl_u {
+	u32   magic;            /* used to check if it's a valid ioctl packet */
+	u32   ioctl_code;       /* operation control code */
+	void __user *inbuf;     /* input data buffer */
+	u32   inbuf_size;       /* size of input data buffer */
+	void __user *outbuf;    /* output data buffer */
+	u32   outbuf_size;      /* size of output data buffer */
+	void __user *bytes_returned;   /* count of bytes returned */
+}
+__attribute__((packed));
+
+
+struct hpt_iopmu
+{
+	__le32 resrved0[4];
+	__le32 inbound_msgaddr0;
+	__le32 inbound_msgaddr1;
+	__le32 outbound_msgaddr0;
+	__le32 outbound_msgaddr1;
+	__le32 inbound_doorbell;
+	__le32 inbound_intstatus;
+	__le32 inbound_intmask;
+	__le32 outbound_doorbell;
+	__le32 outbound_intstatus;
+	__le32 outbound_intmask;
+	__le32 reserved1[2];
+	__le32 inbound_queue;
+	__le32 outbound_queue;
+};
+
+#define IOPMU_QUEUE_EMPTY            0xffffffff
+#define IOPMU_QUEUE_MASK_HOST_BITS   0xf0000000
+#define IOPMU_QUEUE_ADDR_HOST_BIT    0x80000000
+
+#define IOPMU_OUTBOUND_INT_MSG0      1
+#define IOPMU_OUTBOUND_INT_MSG1      2
+#define IOPMU_OUTBOUND_INT_DOORBELL  4
+#define IOPMU_OUTBOUND_INT_POSTQUEUE 8
+#define IOPMU_OUTBOUND_INT_PCI       0x10
+
+#define IOPMU_INBOUND_INT_MSG0       1
+#define IOPMU_INBOUND_INT_MSG1       2
+#define IOPMU_INBOUND_INT_DOORBELL   4
+#define IOPMU_INBOUND_INT_ERROR      8
+#define IOPMU_INBOUND_INT_POSTQUEUE  0x10
+
+enum hpt_iopmu_message {
+	/* host-to-iop messages */
+	IOPMU_INBOUND_MSG0_NOP = 0,
+	IOPMU_INBOUND_MSG0_RESET,
+	IOPMU_INBOUND_MSG0_FLUSH,
+	IOPMU_INBOUND_MSG0_SHUTDOWN,
+	IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
+	IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
+	IOPMU_INBOUND_MSG0_MAX = 0xff,
+	/* iop-to-host messages */
+	IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100,
+	IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff,
+	IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200,
+	IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff,
+	IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300,
+	IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff,
+};
+
+struct hpt_iop_request_header
+{
+	__le32 size;
+	__le32 type;
+	__le32 flags;
+	__le32 result;
+	__le32 context; /* host context */
+	__le32 context_hi32;
+};
+
+#define IOP_REQUEST_FLAG_SYNC_REQUEST 1
+#define IOP_REQUEST_FLAG_BIST_REQUEST 2
+#define IOP_REQUEST_FLAG_REMAPPED     4
+#define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8
+
+enum hpt_iop_request_type {
+	IOP_REQUEST_TYPE_GET_CONFIG = 0,
+	IOP_REQUEST_TYPE_SET_CONFIG,
+	IOP_REQUEST_TYPE_BLOCK_COMMAND,
+	IOP_REQUEST_TYPE_SCSI_COMMAND,
+	IOP_REQUEST_TYPE_IOCTL_COMMAND,
+	IOP_REQUEST_TYPE_MAX
+};
+
+enum hpt_iop_result_type {
+	IOP_RESULT_PENDING = 0,
+	IOP_RESULT_SUCCESS,
+	IOP_RESULT_FAIL,
+	IOP_RESULT_BUSY,
+	IOP_RESULT_RESET,
+	IOP_RESULT_INVALID_REQUEST,
+	IOP_RESULT_BAD_TARGET,
+	IOP_RESULT_MODE_SENSE_CHECK_CONDITION,
+};
+
+struct hpt_iop_request_get_config
+{
+	struct hpt_iop_request_header header;
+	__le32 interface_version;
+	__le32 firmware_version;
+	__le32 max_requests;
+	__le32 request_size;
+	__le32 max_sg_count;
+	__le32 data_transfer_length;
+	__le32 alignment_mask;
+	__le32 max_devices;
+	__le32 sdram_size;
+};
+
+struct hpt_iop_request_set_config
+{
+	struct hpt_iop_request_header header;
+	__le32 iop_id;
+	__le32 vbus_id;
+	__le32 reserve[6];
+};
+
+struct hpt_iopsg
+{
+	__le32 size;
+	__le32 eot; /* non-zero: end of table */
+	__le64 pci_address;
+};
+
+struct hpt_iop_request_block_command
+{
+	struct hpt_iop_request_header header;
+	u8     channel;
+	u8     target;
+	u8     lun;
+	u8     pad1;
+	__le16 command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */
+	__le16 sectors;
+	__le64 lba;
+	struct hpt_iopsg sg_list[1];
+};
+
+#define IOP_BLOCK_COMMAND_READ     1
+#define IOP_BLOCK_COMMAND_WRITE    2
+#define IOP_BLOCK_COMMAND_VERIFY   3
+#define IOP_BLOCK_COMMAND_FLUSH    4
+#define IOP_BLOCK_COMMAND_SHUTDOWN 5
+
+struct hpt_iop_request_scsi_command
+{
+	struct hpt_iop_request_header header;
+	u8     channel;
+	u8     target;
+	u8     lun;
+	u8     pad1;
+	u8     cdb[16];
+	__le32 dataxfer_length;
+	struct hpt_iopsg sg_list[1];
+};
+
+struct hpt_iop_request_ioctl_command
+{
+	struct hpt_iop_request_header header;
+	__le32 ioctl_code;
+	__le32 inbuf_size;
+	__le32 outbuf_size;
+	__le32 bytes_returned;
+	u8     buf[1];
+	/* out data should be put at buf[(inbuf_size+3)&~3] */
+};
+
+#define HPTIOP_MAX_REQUESTS  256u
+
+struct hptiop_request {
+	struct hptiop_request * next;
+	void *                  req_virt;
+	u32                     req_shifted_phy;
+	struct scsi_cmnd *      scp;
+	int                     index;
+};
+
+struct hpt_scsi_pointer {
+	int mapped;
+	int sgcnt;
+	dma_addr_t dma_handle;
+};
+
+#define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp)
+
+struct hptiop_hba {
+	struct hpt_iopmu __iomem * iop;
+	struct Scsi_Host * host;
+	struct pci_dev * pcidev;
+
+	struct list_head link;
+
+	/* IOP config info */
+	u32     firmware_version;
+	u32     sdram_size;
+	u32     max_devices;
+	u32     max_requests;
+	u32     max_request_size;
+	u32     max_sg_descriptors;
+
+	u32     req_size; /* host-allocated request buffer size */
+	int     initialized;
+	int     msg_done;
+
+	struct hptiop_request * req_list;
+	struct hptiop_request reqs[HPTIOP_MAX_REQUESTS];
+
+	/* used to free allocated dma area */
+	void *      dma_coherent;
+	dma_addr_t  dma_coherent_handle;
+
+	atomic_t    reset_count;
+	atomic_t    resetting;
+
+	wait_queue_head_t reset_wq;
+	wait_queue_head_t ioctl_wq;
+};
+
+struct hpt_ioctl_k
+{
+	struct hptiop_hba * hba;
+	u32    ioctl_code;
+	u32    inbuf_size;
+	u32    outbuf_size;
+	void * inbuf;
+	void * outbuf;
+	u32  * bytes_returned;
+	void (*done)(struct hpt_ioctl_k *);
+	int    result; /* HPT_IOCTL_RESULT_ */
+};
+
+#define HPT_IOCTL_RESULT_OK         0
+#define HPT_IOCTL_RESULT_FAILED     (-1)
+
+#if 0
+#define dprintk(fmt, args...) do { printk(fmt, ##args); } while(0)
+#else
+#define dprintk(fmt, args...)
+#endif
+
+#endif
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index 24eb59e..497f664 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -760,7 +760,7 @@
 		while (!got_interrupt(host_index))
 			barrier();
 
-		/*if command succesful, break */
+		/*if command successful, break */
 		if ((stat_result(host_index) == IM_SCB_CMD_COMPLETED) || (stat_result(host_index) == IM_SCB_CMD_COMPLETED_WITH_RETRIES))
 			return 1;
 	}
@@ -885,7 +885,7 @@
 		while (!got_interrupt(host_index))
 			barrier();
 
-		/*if command succesful, break */
+		/*if command successful, break */
 		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
@@ -921,7 +921,7 @@
 			return 2;
 		} else
 			global_command_error_excuse = 0;
-		/*if command succesful, break */
+		/*if command successful, break */
 		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
@@ -959,7 +959,7 @@
 			/* did not work, finish */
 			return 1;
 		}
-		/*if command succesful, break */
+		/*if command successful, break */
 		if (stat_result(host_index) == IM_IMMEDIATE_CMD_COMPLETED)
 			return 1;
 	}
@@ -1441,7 +1441,7 @@
 	struct Scsi_Host *dev = dev_id;
 
 	spin_lock_irqsave(dev->host_lock, flags);
-	
+
 	shpnt = dev;		/* assign host-structure to local pointer */
 	len = 0;		/* set filled text-buffer index to 0 */
 	/* get the _special contents of the hostdata structure */
@@ -1456,7 +1456,7 @@
 		/* if the integrated subsystem has been found automatically: */
 		len += sprintf(buf + len,
 			       "Adapter category: integrated\n" "Chip revision level: %d\n" "Chip status: %s\n" "8 kByte NVRAM status: %s\n", ((pos[2] & 0xf0) >> 4), (pos[2] & 1) ? "enabled" : "disabled", (pos[2] & 2) ? "locked" : "accessible");
-	} else if ((speciale >= 0) && (speciale < (sizeof(subsys_list) / sizeof(struct subsys_list_struct)))) {
+	} else if ((speciale >= 0) && (speciale < ARRAY_SIZE(subsys_list))) {
 		/* if the subsystem is a slot adapter */
 		len += sprintf(buf + len, "Adapter category: slot-card\n" "ROM Segment Address: ");
 		if ((pos[2] & 0xf0) == 0xf0)
@@ -1477,16 +1477,16 @@
 	while (len % sizeof(int) != (sizeof(int) - 1))
 		len += sprintf(buf + len, " ");
 	len += sprintf(buf + len, "\n");
-	
+
 	spin_unlock_irqrestore(shpnt->host_lock, flags);
-	
+
 	return len;
 }
 
 int ibmmca_detect(struct scsi_host_template * scsi_template)
 {
 	struct Scsi_Host *shpnt;
-	int port, id, i, j, k, list_size, slot;
+	int port, id, i, j, k, slot;
 	int devices_on_irq_11 = 0;
 	int devices_on_irq_14 = 0;
 	int IRQ14_registered = 0;
@@ -1603,8 +1603,7 @@
 	/* now look for other adapters in MCA slots, */
 	/* determine the number of known IBM-SCSI-subsystem types */
 	/* see the pos[2] dependence to get the adapter port-offset. */
-	list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
-	for (i = 0; i < list_size; i++) {
+	for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
 		/* scan each slot for a fitting adapter id */
 		slot = 0;	/* start at slot 0 */
 		while ((slot = mca_find_adapter(subsys_list[i].mca_id, slot))
@@ -1669,8 +1668,7 @@
 	/* now check for SCSI-adapters, mapped to the integrated SCSI
 	 * area. E.g. a W/Cache in MCA-slot 9(!). Do the check correct here,
 	 * as this is a known effect on some models 95xx. */
-	list_size = sizeof(subsys_list) / sizeof(struct subsys_list_struct);
-	for (i = 0; i < list_size; i++) {
+	for (i = 0; i < ARRAY_SIZE(subsys_list); i++) {
 		/* scan each slot for a fitting adapter id */
 		slot = mca_find_adapter(subsys_list[i].mca_id, MCA_INTEGSCSI);
 		if (slot != MCA_NOTFOUND) {	/* scan through all slots */
@@ -2243,8 +2241,7 @@
 	int host_index;
 	unsigned long imm_command;
 
-	if (cmd == NULL)
-		BUG();
+	BUG_ON(cmd == NULL);
 
 	ticks = IM_RESET_DELAY * HZ;
 	shpnt = cmd->device->host;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 2e9be83..944fc12 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -121,10 +121,9 @@
 
 	pool->size = size;
 	pool->next = 0;
-	pool->events = kmalloc(pool->size * sizeof(*pool->events), GFP_KERNEL);
+	pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL);
 	if (!pool->events)
 		return -ENOMEM;
-	memset(pool->events, 0x00, pool->size * sizeof(*pool->events));
 
 	pool->iu_storage =
 	    dma_alloc_coherent(hostdata->dev,
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 39b760a..988e6f7a 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -600,8 +600,7 @@
 				"issuing a packet command\n");
 		return ide_do_reset (drive);
 	}
-	if (HWGROUP(drive)->handler != NULL)
-		BUG();
+	BUG_ON(HWGROUP(drive)->handler != NULL);
 	/* Set the interrupt routine */
 	ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
 	/* Send the actual packet */
@@ -691,8 +690,7 @@
 		set_bit(PC_DMA_OK, &pc->flags);
 
 	if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
-		if (HWGROUP(drive)->handler != NULL)
-			BUG();
+		BUG_ON(HWGROUP(drive)->handler != NULL);
 		ide_set_handler(drive, &idescsi_transfer_pc,
 				get_timeout(pc), idescsi_expiry);
 		/* Issue the packet command */
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index fc0f30a..681bd18 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -3,9 +3,6 @@
  * 
  * (The IMM is the embedded controller in the ZIP Plus drive.)
  * 
- * Current Maintainer: David Campbell (Perth, Western Australia)
- *                     campbell@torque.net
- *
  * My unoffical company acronym list is 21 pages long:
  *      FLA:    Four letter acronym with built in facility for
  *              future expansion to five letters.
@@ -1119,6 +1116,10 @@
 	return -ENODEV;
 }
 
+/*
+ * imm cannot deal with highmem, so this causes all IO pages for this host
+ * to reside in low memory (hence mapped)
+ */
 static int imm_adjust_queue(struct scsi_device *device)
 {
 	blk_queue_bounce_limit(device->request_queue, BLK_BOUNCE_HIGH);
@@ -1141,10 +1142,6 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 	.can_queue		= 1,
 	.slave_alloc		= imm_adjust_queue,
-	.unchecked_isa_dma	= 1, /* imm cannot deal with highmem, so
-				      * this is an easy trick to ensure
-				      * all io pages for this host reside
-				      * in low memory */
 };
 
 /***************************************************************************
diff --git a/drivers/scsi/imm.h b/drivers/scsi/imm.h
index dc3aebf..ece936a 100644
--- a/drivers/scsi/imm.h
+++ b/drivers/scsi/imm.h
@@ -2,7 +2,7 @@
 /*  Driver for the Iomega MatchMaker parallel port SCSI HBA embedded in 
  * the Iomega ZIP Plus drive
  * 
- * (c) 1998     David Campbell     campbell@torque.net
+ * (c) 1998     David Campbell
  *
  * Please note that I live in Perth, Western Australia. GMT+0800
  */
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 9c51987..883bc92 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -370,7 +370,7 @@
  */
 
 	if (cmd->use_sg) {
-		cmd->SCp.buffer = (struct scatterlist *) cmd->buffer;
+		cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
 		cmd->SCp.buffers_residual = cmd->use_sg - 1;
 		cmd->SCp.ptr = (char *) page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
 		cmd->SCp.this_residual = cmd->SCp.buffer->length;
@@ -1809,7 +1809,7 @@
 
 
 #define MAX_IN2000_HOSTS 3
-#define MAX_SETUP_ARGS (sizeof(setup_args) / sizeof(char *))
+#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args)
 #define SETUP_BUFFER_SIZE 200
 static char setup_buffer[SETUP_BUFFER_SIZE];
 static char setup_used[MAX_SETUP_ARGS];
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index 0cc7f65..913ba95 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -154,7 +154,6 @@
 static unsigned int i91u_debug = DEBUG_DEFAULT;
 #endif
 
-#define TULSZ(sz)     (sizeof(sz) / sizeof(sz[0]))
 #define TUL_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
 
 typedef struct PCI_ID_Struc {
@@ -2771,7 +2770,7 @@
 
 	init_i91uAdapter_table();
 
-	for (i = 0; i < TULSZ(i91u_pci_devices); i++)
+	for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++)
 	{
 		while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) {
 			if (pci_enable_device(pDev))
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 8b80e59..96b65b3 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -79,7 +79,6 @@
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_request.h>
 #include "ipr.h"
 
 /*
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index a4c0b04..78f2ff7 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -556,7 +556,7 @@
 		 * We now have key/value pairs.
 		 * Update the variables
 		 */
-		for (i = 0; i < (sizeof (options) / sizeof (options[0])); i++) {
+		for (i = 0; i < ARRAY_SIZE(options); i++) {
 			if (strnicmp
 			    (key, options[i].option_name,
 			     strlen(options[i].option_name)) == 0) {
@@ -4364,7 +4364,7 @@
 
 	METHOD_TRACE("ips_rdcap", 1);
 
-	if (scb->scsi_cmd->bufflen < 8)
+	if (scb->scsi_cmd->request_bufflen < 8)
 		return (0);
 
 	cap.lba =
@@ -6438,7 +6438,7 @@
 		/* VPP failure */
 		return (1);
 
-	/* check for succesful flash */
+	/* check for successful flash */
 	if (status & 0x30)
 		/* sequence error */
 		return (1);
@@ -6550,7 +6550,7 @@
 		/* VPP failure */
 		return (1);
 
-	/* check for succesful flash */
+	/* check for successful flash */
 	if (status & 0x30)
 		/* sequence error */
 		return (1);
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 2068b66..b4743a9 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -3,7 +3,8 @@
  *
  * Copyright (C) 2004 Dmitry Yusupov
  * Copyright (C) 2004 Alex Aizman
- * Copyright (C) 2005 Mike Christie
+ * Copyright (C) 2005 - 2006 Mike Christie
+ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
  * maintained by open-iscsi@googlegroups.com
  *
  * This program is free software; you can redistribute it and/or modify
@@ -36,37 +37,28 @@
 #include <linux/mutex.h>
 #include <net/tcp.h>
 #include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_request.h>
-#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_transport_iscsi.h>
 
 #include "iscsi_tcp.h"
 
+#define ISCSI_TCP_VERSION "1.0-595"
+
 MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
 	      "Alex Aizman <itn780@yahoo.com>");
 MODULE_DESCRIPTION("iSCSI/TCP data-path");
 MODULE_LICENSE("GPL");
-MODULE_VERSION("0:4.445");
+MODULE_VERSION(ISCSI_TCP_VERSION);
 /* #define DEBUG_TCP */
-/* #define DEBUG_SCSI */
 #define DEBUG_ASSERT
 
 #ifdef DEBUG_TCP
-#define debug_tcp(fmt...) printk(KERN_DEBUG "tcp: " fmt)
+#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
 #else
 #define debug_tcp(fmt...)
 #endif
 
-#ifdef DEBUG_SCSI
-#define debug_scsi(fmt...) printk(KERN_DEBUG "scsi: " fmt)
-#else
-#define debug_scsi(fmt...)
-#endif
-
 #ifndef DEBUG_ASSERT
 #ifdef BUG_ON
 #undef BUG_ON
@@ -74,22 +66,9 @@
 #define BUG_ON(expr)
 #endif
 
-#define INVALID_SN_DELTA	0xffff
-
 static unsigned int iscsi_max_lun = 512;
 module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
 
-/* global data */
-static kmem_cache_t *taskcache;
-
-static inline void
-iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size)
-{
-	sg_init_one(&ibuf->sg, (u8 *)vbuf, size);
-	ibuf->sent = 0;
-	ibuf->use_sendmsg = 0;
-}
-
 static inline void
 iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size)
 {
@@ -130,68 +109,39 @@
 iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,
 		 u8* crc)
 {
-	crypto_digest_digest(conn->tx_tfm, &buf->sg, 1, crc);
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+
+	crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc);
 	buf->sg.length += sizeof(uint32_t);
 }
 
-static void
-iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
-{
-	struct iscsi_session *session = conn->session;
-	unsigned long flags;
-
-	spin_lock_irqsave(&session->lock, flags);
-	if (session->conn_cnt == 1 || session->leadconn == conn)
-		session->state = ISCSI_STATE_FAILED;
-	spin_unlock_irqrestore(&session->lock, flags);
-	set_bit(SUSPEND_BIT, &conn->suspend_tx);
-	set_bit(SUSPEND_BIT, &conn->suspend_rx);
-	iscsi_conn_error(conn->cls_conn, err);
-}
-
 static inline int
-iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+iscsi_hdr_extract(struct iscsi_tcp_conn *tcp_conn)
 {
-	uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
-	uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
+	struct sk_buff *skb = tcp_conn->in.skb;
 
-	if (max_cmdsn < exp_cmdsn -1 &&
-	    max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
-		return ISCSI_ERR_MAX_CMDSN;
-	if (max_cmdsn > session->max_cmdsn ||
-	    max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
-		session->max_cmdsn = max_cmdsn;
-	if (exp_cmdsn > session->exp_cmdsn ||
-	    exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
-		session->exp_cmdsn = exp_cmdsn;
+	tcp_conn->in.zero_copy_hdr = 0;
 
-	return 0;
-}
-
-static inline int
-iscsi_hdr_extract(struct iscsi_conn *conn)
-{
-	struct sk_buff *skb = conn->in.skb;
-
-	if (conn->in.copy >= conn->hdr_size &&
-	    conn->in_progress == IN_PROGRESS_WAIT_HEADER) {
+	if (tcp_conn->in.copy >= tcp_conn->hdr_size &&
+	    tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER) {
 		/*
 		 * Zero-copy PDU Header: using connection context
 		 * to store header pointer.
 		 */
 		if (skb_shinfo(skb)->frag_list == NULL &&
-		    !skb_shinfo(skb)->nr_frags)
-			conn->in.hdr = (struct iscsi_hdr *)
-				((char*)skb->data + conn->in.offset);
-		else {
+		    !skb_shinfo(skb)->nr_frags) {
+			tcp_conn->in.hdr = (struct iscsi_hdr *)
+				((char*)skb->data + tcp_conn->in.offset);
+			tcp_conn->in.zero_copy_hdr = 1;
+		} else {
 			/* ignoring return code since we checked
 			 * in.copy before */
-			skb_copy_bits(skb, conn->in.offset,
-				&conn->hdr, conn->hdr_size);
-			conn->in.hdr = &conn->hdr;
+			skb_copy_bits(skb, tcp_conn->in.offset,
+				&tcp_conn->hdr, tcp_conn->hdr_size);
+			tcp_conn->in.hdr = &tcp_conn->hdr;
 		}
-		conn->in.offset += conn->hdr_size;
-		conn->in.copy -= conn->hdr_size;
+		tcp_conn->in.offset += tcp_conn->hdr_size;
+		tcp_conn->in.copy -= tcp_conn->hdr_size;
 	} else {
 		int hdr_remains;
 		int copylen;
@@ -201,118 +151,51 @@
 		 * copying it... This'll happen quite rarely.
 		 */
 
-		if (conn->in_progress == IN_PROGRESS_WAIT_HEADER)
-			conn->in.hdr_offset = 0;
+		if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER)
+			tcp_conn->in.hdr_offset = 0;
 
-		hdr_remains = conn->hdr_size - conn->in.hdr_offset;
+		hdr_remains = tcp_conn->hdr_size - tcp_conn->in.hdr_offset;
 		BUG_ON(hdr_remains <= 0);
 
-		copylen = min(conn->in.copy, hdr_remains);
-		skb_copy_bits(skb, conn->in.offset,
-			(char*)&conn->hdr + conn->in.hdr_offset, copylen);
+		copylen = min(tcp_conn->in.copy, hdr_remains);
+		skb_copy_bits(skb, tcp_conn->in.offset,
+			(char*)&tcp_conn->hdr + tcp_conn->in.hdr_offset,
+			copylen);
 
 		debug_tcp("PDU gather offset %d bytes %d in.offset %d "
-		       "in.copy %d\n", conn->in.hdr_offset, copylen,
-		       conn->in.offset, conn->in.copy);
+		       "in.copy %d\n", tcp_conn->in.hdr_offset, copylen,
+		       tcp_conn->in.offset, tcp_conn->in.copy);
 
-		conn->in.offset += copylen;
-		conn->in.copy -= copylen;
+		tcp_conn->in.offset += copylen;
+		tcp_conn->in.copy -= copylen;
 		if (copylen < hdr_remains)  {
-			conn->in_progress = IN_PROGRESS_HEADER_GATHER;
-			conn->in.hdr_offset += copylen;
+			tcp_conn->in_progress = IN_PROGRESS_HEADER_GATHER;
+			tcp_conn->in.hdr_offset += copylen;
 		        return -EAGAIN;
 		}
-		conn->in.hdr = &conn->hdr;
-		conn->discontiguous_hdr_cnt++;
-	        conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+		tcp_conn->in.hdr = &tcp_conn->hdr;
+		tcp_conn->discontiguous_hdr_cnt++;
+	        tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 	}
 
 	return 0;
 }
 
-static inline void
-iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+/*
+ * must be called with session lock
+ */
+static void
+__iscsi_ctask_cleanup(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
-	struct scsi_cmnd *sc = ctask->sc;
-	struct iscsi_session *session = conn->session;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct scsi_cmnd *sc;
 
-	spin_lock(&session->lock);
-	if (unlikely(!sc)) {
-		spin_unlock(&session->lock);
+	sc = ctask->sc;
+	if (unlikely(!sc))
 		return;
-	}
-	if (sc->sc_data_direction == DMA_TO_DEVICE) {
-		struct iscsi_data_task *dtask, *n;
-		/* WRITE: cleanup Data-Out's if any */
-		list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
-			list_del(&dtask->item);
-			mempool_free(dtask, ctask->datapool);
-		}
-	}
-	ctask->xmstate = XMSTATE_IDLE;
-	ctask->r2t = NULL;
-	ctask->sc = NULL;
-	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
-	spin_unlock(&session->lock);
-}
 
-/**
- * iscsi_cmd_rsp - SCSI Command Response processing
- * @conn: iscsi connection
- * @ctask: scsi command task
- **/
-static int
-iscsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
-{
-	int rc;
-	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)conn->in.hdr;
-	struct iscsi_session *session = conn->session;
-	struct scsi_cmnd *sc = ctask->sc;
-
-	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
-	if (rc) {
-		sc->result = (DID_ERROR << 16);
-		goto out;
-	}
-
-	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
-
-	sc->result = (DID_OK << 16) | rhdr->cmd_status;
-
-	if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) {
-		sc->result = (DID_ERROR << 16);
-		goto out;
-	}
-
-	if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION && conn->senselen) {
-		int sensecopy = min(conn->senselen, SCSI_SENSE_BUFFERSIZE);
-
-		memcpy(sc->sense_buffer, conn->data + 2, sensecopy);
-		debug_scsi("copied %d bytes of sense\n", sensecopy);
-	}
-
-	if (sc->sc_data_direction == DMA_TO_DEVICE)
-		goto out;
-
-	if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
-		int res_count = be32_to_cpu(rhdr->residual_count);
-
-		if (res_count > 0 && res_count <= sc->request_bufflen)
-			sc->resid = res_count;
-		else
-			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-	} else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
-		sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
-	else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
-		sc->resid = be32_to_cpu(rhdr->residual_count);
-
-out:
-	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
-		   (long)sc, sc->result, ctask->itt);
-	conn->scsirsp_pdus_cnt++;
-	iscsi_ctask_cleanup(conn, ctask);
-	sc->scsi_done(sc);
-	return rc;
+	tcp_ctask->xmstate = XMSTATE_IDLE;
+	tcp_ctask->r2t = NULL;
 }
 
 /**
@@ -324,7 +207,9 @@
 iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
 	int rc;
-	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)conn->in.hdr;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr;
 	struct iscsi_session *session = conn->session;
 	int datasn = be32_to_cpu(rhdr->datasn);
 
@@ -334,9 +219,9 @@
 	/*
 	 * setup Data-In byte counter (gets decremented..)
 	 */
-	ctask->data_count = conn->in.datalen;
+	ctask->data_count = tcp_conn->in.datalen;
 
-	if (conn->in.datalen == 0)
+	if (tcp_conn->in.datalen == 0)
 		return 0;
 
 	if (ctask->datasn != datasn)
@@ -344,8 +229,8 @@
 
 	ctask->datasn++;
 
-	ctask->data_offset = be32_to_cpu(rhdr->offset);
-	if (ctask->data_offset + conn->in.datalen > ctask->total_length)
+	tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
+	if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
 		return ISCSI_ERR_DATA_OFFSET;
 
 	if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) {
@@ -390,19 +275,17 @@
 			struct iscsi_r2t_info *r2t)
 {
 	struct iscsi_data *hdr;
-	struct iscsi_data_task *dtask;
 	struct scsi_cmnd *sc = ctask->sc;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
-	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
-	BUG_ON(!dtask);
-	hdr = &dtask->hdr;
+	hdr = &r2t->dtask.hdr;
 	memset(hdr, 0, sizeof(struct iscsi_data));
 	hdr->ttt = r2t->ttt;
 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
 	r2t->solicit_datasn++;
 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
-	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
-	hdr->itt = ctask->hdr.itt;
+	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+	hdr->itt = ctask->hdr->itt;
 	hdr->exp_statsn = r2t->exp_statsn;
 	hdr->offset = cpu_to_be32(r2t->data_offset);
 	if (r2t->data_length > conn->max_xmit_dlength) {
@@ -418,11 +301,9 @@
 
 	r2t->sent = 0;
 
-	iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
+	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
 			   sizeof(struct iscsi_hdr));
 
-	r2t->dtask = dtask;
-
 	if (sc->use_sg) {
 		int i, sg_count = 0;
 		struct scatterlist *sg = sc->request_buffer;
@@ -451,11 +332,9 @@
 		}
 		BUG_ON(r2t->sg == NULL);
 	} else
-		iscsi_buf_init_iov(&ctask->sendbuf,
+		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
 			    (char*)sc->request_buffer + r2t->data_offset,
 			    r2t->data_count);
-
-	list_add(&dtask->item, &ctask->dataqueue);
 }
 
 /**
@@ -468,17 +347,16 @@
 {
 	struct iscsi_r2t_info *r2t;
 	struct iscsi_session *session = conn->session;
-	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)conn->in.hdr;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_r2t_rsp *rhdr = (struct iscsi_r2t_rsp *)tcp_conn->in.hdr;
 	int r2tsn = be32_to_cpu(rhdr->r2tsn);
 	int rc;
 
-	if (conn->in.ahslen)
-		return ISCSI_ERR_AHSLEN;
-
-	if (conn->in.datalen)
+	if (tcp_conn->in.datalen)
 		return ISCSI_ERR_DATALEN;
 
-	if (ctask->exp_r2tsn && ctask->exp_r2tsn != r2tsn)
+	if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn)
 		return ISCSI_ERR_R2TSN;
 
 	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
@@ -496,7 +374,7 @@
 		spin_unlock(&session->lock);
 		return 0;
 	}
-	rc = __kfifo_get(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+	rc = __kfifo_get(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
 	BUG_ON(!rc);
 
 	r2t->exp_statsn = rhdr->statsn;
@@ -518,10 +396,10 @@
 
 	iscsi_solicit_data_init(conn, ctask, r2t);
 
-	ctask->exp_r2tsn = r2tsn + 1;
-	ctask->xmstate |= XMSTATE_SOL_HDR;
-	__kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*));
-	__kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*));
+	tcp_ctask->exp_r2tsn = r2tsn + 1;
+	tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+	__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
+	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
 
 	scsi_queue_work(session->host, &conn->xmitwork);
 	conn->r2t_pdus_cnt++;
@@ -531,258 +409,136 @@
 }
 
 static int
-iscsi_hdr_recv(struct iscsi_conn *conn)
+iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
 {
-	int rc = 0;
+	int rc = 0, opcode, ahslen;
 	struct iscsi_hdr *hdr;
-	struct iscsi_cmd_task *ctask;
 	struct iscsi_session *session = conn->session;
-	uint32_t cdgst, rdgst = 0;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	uint32_t cdgst, rdgst = 0, itt;
 
-	hdr = conn->in.hdr;
+	hdr = tcp_conn->in.hdr;
 
 	/* verify PDU length */
-	conn->in.datalen = ntoh24(hdr->dlength);
-	if (conn->in.datalen > conn->max_recv_dlength) {
+	tcp_conn->in.datalen = ntoh24(hdr->dlength);
+	if (tcp_conn->in.datalen > conn->max_recv_dlength) {
 		printk(KERN_ERR "iscsi_tcp: datalen %d > %d\n",
-		       conn->in.datalen, conn->max_recv_dlength);
+		       tcp_conn->in.datalen, conn->max_recv_dlength);
 		return ISCSI_ERR_DATALEN;
 	}
-	conn->data_copied = 0;
+	tcp_conn->data_copied = 0;
 
 	/* read AHS */
-	conn->in.ahslen = hdr->hlength * 4;
-	conn->in.offset += conn->in.ahslen;
-	conn->in.copy -= conn->in.ahslen;
-	if (conn->in.copy < 0) {
+	ahslen = hdr->hlength << 2;
+	tcp_conn->in.offset += ahslen;
+	tcp_conn->in.copy -= ahslen;
+	if (tcp_conn->in.copy < 0) {
 		printk(KERN_ERR "iscsi_tcp: can't handle AHS with length "
-		       "%d bytes\n", conn->in.ahslen);
+		       "%d bytes\n", ahslen);
 		return ISCSI_ERR_AHSLEN;
 	}
 
 	/* calculate read padding */
-	conn->in.padding = conn->in.datalen & (ISCSI_PAD_LEN-1);
-	if (conn->in.padding) {
-		conn->in.padding = ISCSI_PAD_LEN - conn->in.padding;
-		debug_scsi("read padding %d bytes\n", conn->in.padding);
+	tcp_conn->in.padding = tcp_conn->in.datalen & (ISCSI_PAD_LEN-1);
+	if (tcp_conn->in.padding) {
+		tcp_conn->in.padding = ISCSI_PAD_LEN - tcp_conn->in.padding;
+		debug_scsi("read padding %d bytes\n", tcp_conn->in.padding);
 	}
 
 	if (conn->hdrdgst_en) {
 		struct scatterlist sg;
 
 		sg_init_one(&sg, (u8 *)hdr,
-			    sizeof(struct iscsi_hdr) + conn->in.ahslen);
-		crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
+			    sizeof(struct iscsi_hdr) + ahslen);
+		crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
 		rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
-				     conn->in.ahslen);
+				     ahslen);
 		if (cdgst != rdgst) {
-			printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
-			       "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
-			       cdgst);
+			printk(KERN_ERR "iscsi_tcp: hdrdgst error "
+			       "recv 0x%x calc 0x%x\n", rdgst, cdgst);
 			return ISCSI_ERR_HDR_DGST;
 		}
 	}
 
-	/* save opcode for later */
-	conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK;
-
+	opcode = hdr->opcode & ISCSI_OPCODE_MASK;
 	/* verify itt (itt encoding: age+cid+itt) */
-	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
-		if ((hdr->itt & AGE_MASK) !=
-				(session->age << AGE_SHIFT)) {
-			printk(KERN_ERR "iscsi_tcp: received itt %x expected "
-				"session age (%x)\n", hdr->itt,
-				session->age & AGE_MASK);
-			return ISCSI_ERR_BAD_ITT;
-		}
-
-		if ((hdr->itt & CID_MASK) != (conn->id << CID_SHIFT)) {
-			printk(KERN_ERR "iscsi_tcp: received itt %x, expected "
-				"CID (%x)\n", hdr->itt, conn->id);
-			return ISCSI_ERR_BAD_ITT;
-		}
-		conn->in.itt = hdr->itt & ITT_MASK;
-	} else
-		conn->in.itt = hdr->itt;
+	rc = iscsi_verify_itt(conn, hdr, &itt);
+	if (rc == ISCSI_ERR_NO_SCSI_CMD) {
+		tcp_conn->in.datalen = 0; /* force drop */
+		return 0;
+	} else if (rc)
+		return rc;
 
 	debug_tcp("opcode 0x%x offset %d copy %d ahslen %d datalen %d\n",
-		  hdr->opcode, conn->in.offset, conn->in.copy,
-		  conn->in.ahslen, conn->in.datalen);
+		  opcode, tcp_conn->in.offset, tcp_conn->in.copy,
+		  ahslen, tcp_conn->in.datalen);
 
-	if (conn->in.itt < session->cmds_max) {
-		ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt];
+	switch(opcode) {
+	case ISCSI_OP_SCSI_DATA_IN:
+		tcp_conn->in.ctask = session->cmds[itt];
+		rc = iscsi_data_rsp(conn, tcp_conn->in.ctask);
+		/* fall through */
+	case ISCSI_OP_SCSI_CMD_RSP:
+		tcp_conn->in.ctask = session->cmds[itt];
+		if (tcp_conn->in.datalen)
+			goto copy_hdr;
 
-		if (!ctask->sc) {
-			printk(KERN_INFO "iscsi_tcp: dropping ctask with "
-			       "itt 0x%x\n", ctask->itt);
-			conn->in.datalen = 0; /* force drop */
-			return 0;
-		}
-
-		if (ctask->sc->SCp.phase != session->age) {
-			printk(KERN_ERR "iscsi_tcp: ctask's session age %d, "
-				"expected %d\n", ctask->sc->SCp.phase,
-				session->age);
-			return ISCSI_ERR_SESSION_FAILED;
-		}
-
-		conn->in.ctask = ctask;
-
-		debug_scsi("rsp [op 0x%x cid %d sc %lx itt 0x%x len %d]\n",
-			   hdr->opcode, conn->id, (long)ctask->sc,
-			   ctask->itt, conn->in.datalen);
-
-		switch(conn->in.opcode) {
-		case ISCSI_OP_SCSI_CMD_RSP:
-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
-			if (!conn->in.datalen)
-				rc = iscsi_cmd_rsp(conn, ctask);
-			else
-				/*
-				 * got sense or response data; copying PDU
-				 * Header to the connection's header
-				 * placeholder
-				 */
-				memcpy(&conn->hdr, hdr,
-				       sizeof(struct iscsi_hdr));
-			break;
-		case ISCSI_OP_SCSI_DATA_IN:
-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
-			/* save flags for non-exceptional status */
-			conn->in.flags = hdr->flags;
-			/* save cmd_status for sense data */
-			conn->in.cmd_status =
-				((struct iscsi_data_rsp*)hdr)->cmd_status;
-			rc = iscsi_data_rsp(conn, ctask);
-			break;
-		case ISCSI_OP_R2T:
-			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
-			if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
-				rc = iscsi_r2t_rsp(conn, ctask);
-			else
-				rc = ISCSI_ERR_PROTO;
-			break;
-		default:
-			rc = ISCSI_ERR_BAD_OPCODE;
-			break;
-		}
-	} else if (conn->in.itt >= ISCSI_MGMT_ITT_OFFSET &&
-		   conn->in.itt < ISCSI_MGMT_ITT_OFFSET +
-					session->mgmtpool_max) {
-		struct iscsi_mgmt_task *mtask = (struct iscsi_mgmt_task *)
-					session->mgmt_cmds[conn->in.itt -
-						ISCSI_MGMT_ITT_OFFSET];
-
-		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
-			   conn->in.opcode, conn->id, mtask->itt,
-			   conn->in.datalen);
-
-		switch(conn->in.opcode) {
-		case ISCSI_OP_LOGIN_RSP:
-		case ISCSI_OP_TEXT_RSP:
-		case ISCSI_OP_LOGOUT_RSP:
-			rc = iscsi_check_assign_cmdsn(session,
-						 (struct iscsi_nopin*)hdr);
-			if (rc)
-				break;
-
-			if (!conn->in.datalen) {
-				rc = iscsi_recv_pdu(conn->cls_conn, hdr,
-						    NULL, 0);
-				if (conn->login_mtask != mtask) {
-					spin_lock(&session->lock);
-					__kfifo_put(session->mgmtpool.queue,
-					    (void*)&mtask, sizeof(void*));
-					spin_unlock(&session->lock);
-				}
-			}
-			break;
-		case ISCSI_OP_SCSI_TMFUNC_RSP:
-			rc = iscsi_check_assign_cmdsn(session,
-						 (struct iscsi_nopin*)hdr);
-			if (rc)
-				break;
-
-			if (conn->in.datalen || conn->in.ahslen) {
-				rc = ISCSI_ERR_PROTO;
-				break;
-			}
-			conn->tmfrsp_pdus_cnt++;
-			spin_lock(&session->lock);
-			if (conn->tmabort_state == TMABORT_INITIAL) {
-				__kfifo_put(session->mgmtpool.queue,
-						(void*)&mtask, sizeof(void*));
-				conn->tmabort_state =
-					((struct iscsi_tm_rsp *)hdr)->
-					response == ISCSI_TMF_RSP_COMPLETE ?
-						TMABORT_SUCCESS:TMABORT_FAILED;
-				/* unblock eh_abort() */
-				wake_up(&conn->ehwait);
-			}
-			spin_unlock(&session->lock);
-			break;
-		case ISCSI_OP_NOOP_IN:
-			if (hdr->ttt != ISCSI_RESERVED_TAG) {
-				rc = ISCSI_ERR_PROTO;
-				break;
-			}
-			rc = iscsi_check_assign_cmdsn(session,
-						(struct iscsi_nopin*)hdr);
-			if (rc)
-				break;
-			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
-
-			if (!conn->in.datalen) {
-				struct iscsi_mgmt_task *mtask;
-
-				rc = iscsi_recv_pdu(conn->cls_conn, hdr,
-						    NULL, 0);
-				mtask = (struct iscsi_mgmt_task *)
-					session->mgmt_cmds[conn->in.itt -
-							ISCSI_MGMT_ITT_OFFSET];
-				if (conn->login_mtask != mtask) {
-					spin_lock(&session->lock);
-					__kfifo_put(session->mgmtpool.queue,
-						  (void*)&mtask, sizeof(void*));
-					spin_unlock(&session->lock);
-				}
-			}
-			break;
-		default:
-			rc = ISCSI_ERR_BAD_OPCODE;
-			break;
-		}
-	} else if (conn->in.itt == ISCSI_RESERVED_TAG) {
-		switch(conn->in.opcode) {
-		case ISCSI_OP_NOOP_IN:
-			if (!conn->in.datalen) {
-				rc = iscsi_check_assign_cmdsn(session,
-						 (struct iscsi_nopin*)hdr);
-				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
-					rc = iscsi_recv_pdu(conn->cls_conn,
-							    hdr, NULL, 0);
-			} else
-				rc = ISCSI_ERR_PROTO;
-			break;
-		case ISCSI_OP_REJECT:
-			/* we need sth like iscsi_reject_rsp()*/
-		case ISCSI_OP_ASYNC_EVENT:
-			/* we need sth like iscsi_async_event_rsp() */
-			rc = ISCSI_ERR_BAD_OPCODE;
-			break;
-		default:
-			rc = ISCSI_ERR_BAD_OPCODE;
-			break;
-		}
-	} else
-		rc = ISCSI_ERR_BAD_ITT;
+		spin_lock(&session->lock);
+		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
+		rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
+		spin_unlock(&session->lock);
+		break;
+	case ISCSI_OP_R2T:
+		tcp_conn->in.ctask = session->cmds[itt];
+		if (ahslen)
+			rc = ISCSI_ERR_AHSLEN;
+		else if (tcp_conn->in.ctask->sc->sc_data_direction ==
+								DMA_TO_DEVICE)
+			rc = iscsi_r2t_rsp(conn, tcp_conn->in.ctask);
+		else
+			rc = ISCSI_ERR_PROTO;
+		break;
+	case ISCSI_OP_LOGIN_RSP:
+	case ISCSI_OP_TEXT_RSP:
+	case ISCSI_OP_LOGOUT_RSP:
+	case ISCSI_OP_NOOP_IN:
+	case ISCSI_OP_REJECT:
+	case ISCSI_OP_ASYNC_EVENT:
+		if (tcp_conn->in.datalen)
+			goto copy_hdr;
+	/* fall through */
+	case ISCSI_OP_SCSI_TMFUNC_RSP:
+		rc = iscsi_complete_pdu(conn, hdr, NULL, 0);
+		break;
+	default:
+		rc = ISCSI_ERR_BAD_OPCODE;
+		break;
+	}
 
 	return rc;
+
+copy_hdr:
+	/*
+	 * if we did zero copy for the header but we will need multiple
+	 * skbs to complete the command then we have to copy the header
+	 * for later use
+	 */
+	if (tcp_conn->in.zero_copy_hdr && tcp_conn->in.copy <
+	   (tcp_conn->in.datalen + tcp_conn->in.padding +
+	    (conn->datadgst_en ? 4 : 0))) {
+		debug_tcp("Copying header for later use. in.copy %d in.datalen"
+			  " %d\n", tcp_conn->in.copy, tcp_conn->in.datalen);
+		memcpy(&tcp_conn->hdr, tcp_conn->in.hdr,
+		       sizeof(struct iscsi_hdr));
+		tcp_conn->in.hdr = &tcp_conn->hdr;
+		tcp_conn->in.zero_copy_hdr = 0;
+	}
+	return 0;
 }
 
 /**
  * iscsi_ctask_copy - copy skb bits to the destanation cmd task
- * @conn: iscsi connection
+ * @conn: iscsi tcp connection
  * @ctask: scsi command task
  * @buf: buffer to copy to
  * @buf_size: size of buffer
@@ -804,110 +560,113 @@
  *	buf_left		left to copy from in progress buffer
  **/
 static inline int
-iscsi_ctask_copy(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
 		void *buf, int buf_size, int offset)
 {
-	int buf_left = buf_size - (conn->data_copied + offset);
-	int size = min(conn->in.copy, buf_left);
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	int buf_left = buf_size - (tcp_conn->data_copied + offset);
+	int size = min(tcp_conn->in.copy, buf_left);
 	int rc;
 
 	size = min(size, ctask->data_count);
 
 	debug_tcp("ctask_copy %d bytes at offset %d copied %d\n",
-	       size, conn->in.offset, conn->in.copied);
+	       size, tcp_conn->in.offset, tcp_conn->in.copied);
 
 	BUG_ON(size <= 0);
-	BUG_ON(ctask->sent + size > ctask->total_length);
+	BUG_ON(tcp_ctask->sent + size > ctask->total_length);
 
-	rc = skb_copy_bits(conn->in.skb, conn->in.offset,
-			   (char*)buf + (offset + conn->data_copied), size);
+	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
+			   (char*)buf + (offset + tcp_conn->data_copied), size);
 	/* must fit into skb->len */
 	BUG_ON(rc);
 
-	conn->in.offset += size;
-	conn->in.copy -= size;
-	conn->in.copied += size;
-	conn->data_copied += size;
-	ctask->sent += size;
+	tcp_conn->in.offset += size;
+	tcp_conn->in.copy -= size;
+	tcp_conn->in.copied += size;
+	tcp_conn->data_copied += size;
+	tcp_ctask->sent += size;
 	ctask->data_count -= size;
 
-	BUG_ON(conn->in.copy < 0);
+	BUG_ON(tcp_conn->in.copy < 0);
 	BUG_ON(ctask->data_count < 0);
 
-	if (buf_size != (conn->data_copied + offset)) {
+	if (buf_size != (tcp_conn->data_copied + offset)) {
 		if (!ctask->data_count) {
-			BUG_ON(buf_size - conn->data_copied < 0);
+			BUG_ON(buf_size - tcp_conn->data_copied < 0);
 			/* done with this PDU */
-			return buf_size - conn->data_copied;
+			return buf_size - tcp_conn->data_copied;
 		}
 		return -EAGAIN;
 	}
 
 	/* done with this buffer or with both - PDU and buffer */
-	conn->data_copied = 0;
+	tcp_conn->data_copied = 0;
 	return 0;
 }
 
 /**
  * iscsi_tcp_copy - copy skb bits to the destanation buffer
- * @conn: iscsi connection
- * @buf: buffer to copy to
- * @buf_size: number of bytes to copy
+ * @conn: iscsi tcp connection
  *
  * Notes:
  *	The function calls skb_copy_bits() and updates per-connection
  *	byte counters.
  **/
 static inline int
-iscsi_tcp_copy(struct iscsi_conn *conn, void *buf, int buf_size)
+iscsi_tcp_copy(struct iscsi_tcp_conn *tcp_conn)
 {
-	int buf_left = buf_size - conn->data_copied;
-	int size = min(conn->in.copy, buf_left);
+	void *buf = tcp_conn->data;
+	int buf_size = tcp_conn->in.datalen;
+	int buf_left = buf_size - tcp_conn->data_copied;
+	int size = min(tcp_conn->in.copy, buf_left);
 	int rc;
 
 	debug_tcp("tcp_copy %d bytes at offset %d copied %d\n",
-	       size, conn->in.offset, conn->data_copied);
+	       size, tcp_conn->in.offset, tcp_conn->data_copied);
 	BUG_ON(size <= 0);
 
-	rc = skb_copy_bits(conn->in.skb, conn->in.offset,
-			   (char*)buf + conn->data_copied, size);
+	rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
+			   (char*)buf + tcp_conn->data_copied, size);
 	BUG_ON(rc);
 
-	conn->in.offset += size;
-	conn->in.copy -= size;
-	conn->in.copied += size;
-	conn->data_copied += size;
+	tcp_conn->in.offset += size;
+	tcp_conn->in.copy -= size;
+	tcp_conn->in.copied += size;
+	tcp_conn->data_copied += size;
 
-	if (buf_size != conn->data_copied)
+	if (buf_size != tcp_conn->data_copied)
 		return -EAGAIN;
 
 	return 0;
 }
 
 static inline void
-partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
-			 int offset, int length)
+partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn,
+			 struct scatterlist *sg, int offset, int length)
 {
 	struct scatterlist temp;
 
 	memcpy(&temp, sg, sizeof(struct scatterlist));
 	temp.offset = offset;
 	temp.length = length;
-	crypto_digest_update(conn->data_rx_tfm, &temp, 1);
+	crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1);
 }
 
 static void
-iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
+iscsi_recv_digest_update(struct iscsi_tcp_conn *tcp_conn, char* buf, int len)
 {
 	struct scatterlist tmp;
 
 	sg_init_one(&tmp, buf, len);
-	crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
+	crypto_digest_update(tcp_conn->data_rx_tfm, &tmp, 1);
 }
 
 static int iscsi_scsi_data_in(struct iscsi_conn *conn)
 {
-	struct iscsi_cmd_task *ctask = conn->in.ctask;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_cmd_task *ctask = tcp_conn->in.ctask;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	struct scsi_cmnd *sc = ctask->sc;
 	struct scatterlist *sg;
 	int i, offset, rc = 0;
@@ -919,31 +678,33 @@
 	 */
 	if (!sc->use_sg) {
 		i = ctask->data_count;
-		rc = iscsi_ctask_copy(conn, ctask, sc->request_buffer,
-				      sc->request_bufflen, ctask->data_offset);
+		rc = iscsi_ctask_copy(tcp_conn, ctask, sc->request_buffer,
+				      sc->request_bufflen,
+				      tcp_ctask->data_offset);
 		if (rc == -EAGAIN)
 			return rc;
 		if (conn->datadgst_en)
-			iscsi_recv_digest_update(conn, sc->request_buffer, i);
+			iscsi_recv_digest_update(tcp_conn, sc->request_buffer,
+						 i);
 		rc = 0;
 		goto done;
 	}
 
-	offset = ctask->data_offset;
+	offset = tcp_ctask->data_offset;
 	sg = sc->request_buffer;
 
-	if (ctask->data_offset)
-		for (i = 0; i < ctask->sg_count; i++)
+	if (tcp_ctask->data_offset)
+		for (i = 0; i < tcp_ctask->sg_count; i++)
 			offset -= sg[i].length;
 	/* we've passed through partial sg*/
 	if (offset < 0)
 		offset = 0;
 
-	for (i = ctask->sg_count; i < sc->use_sg; i++) {
+	for (i = tcp_ctask->sg_count; i < sc->use_sg; i++) {
 		char *dest;
 
 		dest = kmap_atomic(sg[i].page, KM_SOFTIRQ0);
-		rc = iscsi_ctask_copy(conn, ctask, dest + sg[i].offset,
+		rc = iscsi_ctask_copy(tcp_conn, ctask, dest + sg[i].offset,
 				      sg[i].length, offset);
 		kunmap_atomic(dest, KM_SOFTIRQ0);
 		if (rc == -EAGAIN)
@@ -952,15 +713,17 @@
 		if (!rc) {
 			if (conn->datadgst_en) {
 				if (!offset)
-					crypto_digest_update(conn->data_rx_tfm,
-							     &sg[i], 1);
+					crypto_digest_update(
+							tcp_conn->data_rx_tfm,
+							&sg[i], 1);
 				else
-					partial_sg_digest_update(conn, &sg[i],
+					partial_sg_digest_update(tcp_conn,
+							&sg[i],
 							sg[i].offset + offset,
 							sg[i].length - offset);
 			}
 			offset = 0;
-			ctask->sg_count++;
+			tcp_ctask->sg_count++;
 		}
 
 		if (!ctask->data_count) {
@@ -968,25 +731,26 @@
 				/*
 				 * data-in is complete, but buffer not...
 				 */
-				partial_sg_digest_update(conn, &sg[i],
+				partial_sg_digest_update(tcp_conn, &sg[i],
 						sg[i].offset, sg[i].length-rc);
 			rc = 0;
 			break;
 		}
 
-		if (!conn->in.copy)
+		if (!tcp_conn->in.copy)
 			return -EAGAIN;
 	}
 	BUG_ON(ctask->data_count);
 
 done:
 	/* check for non-exceptional status */
-	if (conn->in.flags & ISCSI_FLAG_DATA_STATUS) {
+	if (tcp_conn->in.hdr->flags & ISCSI_FLAG_DATA_STATUS) {
 		debug_scsi("done [sc %lx res %d itt 0x%x]\n",
 			   (long)sc, sc->result, ctask->itt);
-		conn->scsirsp_pdus_cnt++;
-		iscsi_ctask_cleanup(conn, ctask);
-		sc->scsi_done(sc);
+		spin_lock(&conn->session->lock);
+		__iscsi_ctask_cleanup(conn, ctask);
+		__iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
+		spin_unlock(&conn->session->lock);
 	}
 
 	return rc;
@@ -995,71 +759,38 @@
 static int
 iscsi_data_recv(struct iscsi_conn *conn)
 {
-	struct iscsi_session *session = conn->session;
-	int rc = 0;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	int rc = 0, opcode;
 
-	switch(conn->in.opcode) {
+	opcode = tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK;
+	switch (opcode) {
 	case ISCSI_OP_SCSI_DATA_IN:
 		rc = iscsi_scsi_data_in(conn);
 		break;
-	case ISCSI_OP_SCSI_CMD_RSP: {
-		/*
-		 * SCSI Sense Data:
-		 * copying the entire Data Segment.
-		 */
-		if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) {
-			rc = -EAGAIN;
-			goto exit;
-		}
-
-		/*
-		 * check for sense
-		 */
-		conn->in.hdr = &conn->hdr;
-		conn->senselen = (conn->data[0] << 8) | conn->data[1];
-		rc = iscsi_cmd_rsp(conn, conn->in.ctask);
-		if (!rc && conn->datadgst_en)
-			iscsi_recv_digest_update(conn, conn->data,
-						 conn->in.datalen);
-	}
-	break;
+	case ISCSI_OP_SCSI_CMD_RSP:
+		spin_lock(&conn->session->lock);
+		__iscsi_ctask_cleanup(conn, tcp_conn->in.ctask);
+		spin_unlock(&conn->session->lock);
 	case ISCSI_OP_TEXT_RSP:
 	case ISCSI_OP_LOGIN_RSP:
-	case ISCSI_OP_NOOP_IN: {
-		struct iscsi_mgmt_task *mtask = NULL;
-
-		if (conn->in.itt != ISCSI_RESERVED_TAG)
-			mtask = (struct iscsi_mgmt_task *)
-				session->mgmt_cmds[conn->in.itt -
-					ISCSI_MGMT_ITT_OFFSET];
-
+	case ISCSI_OP_NOOP_IN:
+	case ISCSI_OP_ASYNC_EVENT:
+	case ISCSI_OP_REJECT:
 		/*
 		 * Collect data segment to the connection's data
 		 * placeholder
 		 */
-		if (iscsi_tcp_copy(conn, conn->data, conn->in.datalen)) {
+		if (iscsi_tcp_copy(tcp_conn)) {
 			rc = -EAGAIN;
 			goto exit;
 		}
 
-		rc = iscsi_recv_pdu(conn->cls_conn, conn->in.hdr,
-				    conn->data, conn->in.datalen);
-
-		if (!rc && conn->datadgst_en &&
-			conn->in.opcode != ISCSI_OP_LOGIN_RSP)
-			iscsi_recv_digest_update(conn, conn->data,
-			  			conn->in.datalen);
-
-		if (mtask && conn->login_mtask != mtask) {
-			spin_lock(&session->lock);
-			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
-				    sizeof(void*));
-			spin_unlock(&session->lock);
-		}
-	}
-	break;
-	case ISCSI_OP_ASYNC_EVENT:
-	case ISCSI_OP_REJECT:
+		rc = iscsi_complete_pdu(conn, tcp_conn->in.hdr, tcp_conn->data,
+					tcp_conn->in.datalen);
+		if (!rc && conn->datadgst_en && opcode != ISCSI_OP_LOGIN_RSP)
+			iscsi_recv_digest_update(tcp_conn, tcp_conn->data,
+			  			tcp_conn->in.datalen);
+		break;
 	default:
 		BUG_ON(1);
 	}
@@ -1080,6 +811,7 @@
 {
 	int rc;
 	struct iscsi_conn *conn = rd_desc->arg.data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	int processed;
 	char pad[ISCSI_PAD_LEN];
 	struct scatterlist sg;
@@ -1088,15 +820,15 @@
 	 * Save current SKB and its offset in the corresponding
 	 * connection context.
 	 */
-	conn->in.copy = skb->len - offset;
-	conn->in.offset = offset;
-	conn->in.skb = skb;
-	conn->in.len = conn->in.copy;
-	BUG_ON(conn->in.copy <= 0);
-	debug_tcp("in %d bytes\n", conn->in.copy);
+	tcp_conn->in.copy = skb->len - offset;
+	tcp_conn->in.offset = offset;
+	tcp_conn->in.skb = skb;
+	tcp_conn->in.len = tcp_conn->in.copy;
+	BUG_ON(tcp_conn->in.copy <= 0);
+	debug_tcp("in %d bytes\n", tcp_conn->in.copy);
 
 more:
-	conn->in.copied = 0;
+	tcp_conn->in.copied = 0;
 	rc = 0;
 
 	if (unlikely(conn->suspend_rx)) {
@@ -1104,9 +836,9 @@
 		return 0;
 	}
 
-	if (conn->in_progress == IN_PROGRESS_WAIT_HEADER ||
-	    conn->in_progress == IN_PROGRESS_HEADER_GATHER) {
-		rc = iscsi_hdr_extract(conn);
+	if (tcp_conn->in_progress == IN_PROGRESS_WAIT_HEADER ||
+	    tcp_conn->in_progress == IN_PROGRESS_HEADER_GATHER) {
+		rc = iscsi_hdr_extract(tcp_conn);
 		if (rc) {
 		       if (rc == -EAGAIN)
 				goto nomore;
@@ -1119,90 +851,91 @@
 		/*
 		 * Verify and process incoming PDU header.
 		 */
-		rc = iscsi_hdr_recv(conn);
-		if (!rc && conn->in.datalen) {
+		rc = iscsi_tcp_hdr_recv(conn);
+		if (!rc && tcp_conn->in.datalen) {
 			if (conn->datadgst_en) {
-				BUG_ON(!conn->data_rx_tfm);
-				crypto_digest_init(conn->data_rx_tfm);
+				BUG_ON(!tcp_conn->data_rx_tfm);
+				crypto_digest_init(tcp_conn->data_rx_tfm);
 			}
-			conn->in_progress = IN_PROGRESS_DATA_RECV;
+			tcp_conn->in_progress = IN_PROGRESS_DATA_RECV;
 		} else if (rc) {
 			iscsi_conn_failure(conn, rc);
 			return 0;
 		}
 	}
 
-	if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
+	if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
 		uint32_t recv_digest;
+
 		debug_tcp("extra data_recv offset %d copy %d\n",
-			  conn->in.offset, conn->in.copy);
-		skb_copy_bits(conn->in.skb, conn->in.offset,
+			  tcp_conn->in.offset, tcp_conn->in.copy);
+		skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset,
 				&recv_digest, 4);
-		conn->in.offset += 4;
-		conn->in.copy -= 4;
-		if (recv_digest != conn->in.datadgst) {
+		tcp_conn->in.offset += 4;
+		tcp_conn->in.copy -= 4;
+		if (recv_digest != tcp_conn->in.datadgst) {
 			debug_tcp("iscsi_tcp: data digest error!"
 				  "0x%x != 0x%x\n", recv_digest,
-				  conn->in.datadgst);
+				  tcp_conn->in.datadgst);
 			iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
 			return 0;
 		} else {
 			debug_tcp("iscsi_tcp: data digest match!"
 				  "0x%x == 0x%x\n", recv_digest,
-				  conn->in.datadgst);
-			conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+				  tcp_conn->in.datadgst);
+			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 		}
 	}
 
-	if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) {
+	if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV &&
+	   tcp_conn->in.copy) {
 
 		debug_tcp("data_recv offset %d copy %d\n",
-		       conn->in.offset, conn->in.copy);
+		       tcp_conn->in.offset, tcp_conn->in.copy);
 
 		rc = iscsi_data_recv(conn);
 		if (rc) {
-			if (rc == -EAGAIN) {
-				rd_desc->count = conn->in.datalen -
-						conn->in.ctask->data_count;
+			if (rc == -EAGAIN)
 				goto again;
-			}
 			iscsi_conn_failure(conn, rc);
 			return 0;
 		}
-		conn->in.copy -= conn->in.padding;
-		conn->in.offset += conn->in.padding;
+		tcp_conn->in.copy -= tcp_conn->in.padding;
+		tcp_conn->in.offset += tcp_conn->in.padding;
 		if (conn->datadgst_en) {
-			if (conn->in.padding) {
-				debug_tcp("padding -> %d\n", conn->in.padding);
-				memset(pad, 0, conn->in.padding);
-				sg_init_one(&sg, pad, conn->in.padding);
-				crypto_digest_update(conn->data_rx_tfm, &sg, 1);
+			if (tcp_conn->in.padding) {
+				debug_tcp("padding -> %d\n",
+					  tcp_conn->in.padding);
+				memset(pad, 0, tcp_conn->in.padding);
+				sg_init_one(&sg, pad, tcp_conn->in.padding);
+				crypto_digest_update(tcp_conn->data_rx_tfm,
+						     &sg, 1);
 			}
-			crypto_digest_final(conn->data_rx_tfm,
-					    (u8 *) & conn->in.datadgst);
-			debug_tcp("rx digest 0x%x\n", conn->in.datadgst);
-			conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+			crypto_digest_final(tcp_conn->data_rx_tfm,
+					    (u8 *) & tcp_conn->in.datadgst);
+			debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
+			tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
 		} else
-			conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+			tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 	}
 
 	debug_tcp("f, processed %d from out of %d padding %d\n",
-	       conn->in.offset - offset, (int)len, conn->in.padding);
-	BUG_ON(conn->in.offset - offset > len);
+	       tcp_conn->in.offset - offset, (int)len, tcp_conn->in.padding);
+	BUG_ON(tcp_conn->in.offset - offset > len);
 
-	if (conn->in.offset - offset != len) {
+	if (tcp_conn->in.offset - offset != len) {
 		debug_tcp("continue to process %d bytes\n",
-		       (int)len - (conn->in.offset - offset));
+		       (int)len - (tcp_conn->in.offset - offset));
 		goto more;
 	}
 
 nomore:
-	processed = conn->in.offset - offset;
+	processed = tcp_conn->in.offset - offset;
 	BUG_ON(processed == 0);
 	return processed;
 
 again:
-	processed = conn->in.offset - offset;
+	processed = tcp_conn->in.offset - offset;
 	debug_tcp("c, processed %d from out of %d rd_desc_cnt %d\n",
 	          processed, (int)len, (int)rd_desc->count);
 	BUG_ON(processed == 0);
@@ -1220,9 +953,14 @@
 
 	read_lock(&sk->sk_callback_lock);
 
-	/* use rd_desc to pass 'conn' to iscsi_tcp_data_recv */
+	/*
+	 * Use rd_desc to pass 'conn' to iscsi_tcp_data_recv.
+	 * We set count to 1 because we want the network layer to
+	 * hand us all the skbs that are available. iscsi_tcp_data_recv
+	 * handled pdus that cross buffers or pdus that still need data.
+	 */
 	rd_desc.arg.data = conn;
-	rd_desc.count = 0;
+	rd_desc.count = 1;
 	tcp_read_sock(sk, &rd_desc, iscsi_tcp_data_recv);
 
 	read_unlock(&sk->sk_callback_lock);
@@ -1231,6 +969,7 @@
 static void
 iscsi_tcp_state_change(struct sock *sk)
 {
+	struct iscsi_tcp_conn *tcp_conn;
 	struct iscsi_conn *conn;
 	struct iscsi_session *session;
 	void (*old_state_change)(struct sock *);
@@ -1247,7 +986,8 @@
 		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
 	}
 
-	old_state_change = conn->old_state_change;
+	tcp_conn = conn->dd_data;
+	old_state_change = tcp_conn->old_state_change;
 
 	read_unlock(&sk->sk_callback_lock);
 
@@ -1262,23 +1002,25 @@
 iscsi_write_space(struct sock *sk)
 {
 	struct iscsi_conn *conn = (struct iscsi_conn*)sk->sk_user_data;
-	conn->old_write_space(sk);
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+
+	tcp_conn->old_write_space(sk);
 	debug_tcp("iscsi_write_space: cid %d\n", conn->id);
-	clear_bit(SUSPEND_BIT, &conn->suspend_tx);
 	scsi_queue_work(conn->session->host, &conn->xmitwork);
 }
 
 static void
 iscsi_conn_set_callbacks(struct iscsi_conn *conn)
 {
-	struct sock *sk = conn->sock->sk;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct sock *sk = tcp_conn->sock->sk;
 
 	/* assign new callbacks */
 	write_lock_bh(&sk->sk_callback_lock);
 	sk->sk_user_data = conn;
-	conn->old_data_ready = sk->sk_data_ready;
-	conn->old_state_change = sk->sk_state_change;
-	conn->old_write_space = sk->sk_write_space;
+	tcp_conn->old_data_ready = sk->sk_data_ready;
+	tcp_conn->old_state_change = sk->sk_state_change;
+	tcp_conn->old_write_space = sk->sk_write_space;
 	sk->sk_data_ready = iscsi_tcp_data_ready;
 	sk->sk_state_change = iscsi_tcp_state_change;
 	sk->sk_write_space = iscsi_write_space;
@@ -1288,14 +1030,15 @@
 static void
 iscsi_conn_restore_callbacks(struct iscsi_conn *conn)
 {
-	struct sock *sk = conn->sock->sk;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct sock *sk = tcp_conn->sock->sk;
 
 	/* restore socket callbacks, see also: iscsi_conn_set_callbacks() */
 	write_lock_bh(&sk->sk_callback_lock);
 	sk->sk_user_data    = NULL;
-	sk->sk_data_ready   = conn->old_data_ready;
-	sk->sk_state_change = conn->old_state_change;
-	sk->sk_write_space  = conn->old_write_space;
+	sk->sk_data_ready   = tcp_conn->old_data_ready;
+	sk->sk_state_change = tcp_conn->old_state_change;
+	sk->sk_write_space  = tcp_conn->old_write_space;
 	sk->sk_no_check	 = 0;
 	write_unlock_bh(&sk->sk_callback_lock);
 }
@@ -1310,8 +1053,9 @@
 static inline int
 iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
 {
-	struct socket *sk = conn->sock;
-	int offset = buf->sg.offset + buf->sent;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct socket *sk = tcp_conn->sock;
+	int offset = buf->sg.offset + buf->sent, res;
 
 	/*
 	 * if we got use_sg=0 or are sending something we kmallocd
@@ -1322,9 +1066,22 @@
 	 * slab case.
 	 */
 	if (buf->use_sendmsg)
-		return sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
+		res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
 	else
-		return conn->sendpage(sk, buf->sg.page, offset, size, flags);
+		res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags);
+
+	if (res >= 0) {
+		conn->txdata_octets += res;
+		buf->sent += res;
+		return res;
+	}
+
+	tcp_conn->sendpage_failures_cnt++;
+	if (res == -EAGAIN)
+		res = -ENOBUFS;
+	else
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	return res;
 }
 
 /**
@@ -1350,16 +1107,10 @@
 	res = iscsi_send(conn, buf, size, flags);
 	debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
 	if (res >= 0) {
-		conn->txdata_octets += res;
-		buf->sent += res;
 		if (size != res)
 			return -EAGAIN;
 		return 0;
-	} else if (res == -EAGAIN) {
-		conn->sendpage_failures_cnt++;
-		set_bit(SUSPEND_BIT, &conn->suspend_tx);
-	} else if (res == -EPIPE)
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	}
 
 	return res;
 }
@@ -1392,47 +1143,46 @@
 	debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
 		  size, buf->sent, *count, *sent, res);
 	if (res >= 0) {
-		conn->txdata_octets += res;
-		buf->sent += res;
 		*count -= res;
 		*sent += res;
 		if (size != res)
 			return -EAGAIN;
 		return 0;
-	} else if (res == -EAGAIN) {
-		conn->sendpage_failures_cnt++;
-		set_bit(SUSPEND_BIT, &conn->suspend_tx);
-	} else if (res == -EPIPE)
-		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+	}
 
 	return res;
 }
 
 static inline void
-iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn,
+		      struct iscsi_cmd_task *ctask)
 {
-	BUG_ON(!conn->data_tx_tfm);
-	crypto_digest_init(conn->data_tx_tfm);
-	ctask->digest_count = 4;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+
+	BUG_ON(!tcp_conn->data_tx_tfm);
+	crypto_digest_init(tcp_conn->data_tx_tfm);
+	tcp_ctask->digest_count = 4;
 }
 
 static int
 iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
 			struct iscsi_buf *buf, uint32_t *digest, int final)
 {
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	int rc = 0;
 	int sent = 0;
 
 	if (final)
-		crypto_digest_final(conn->data_tx_tfm, (u8*)digest);
+		crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
 
-	iscsi_buf_init_virt(buf, (char*)digest, 4);
-	rc = iscsi_sendpage(conn, buf, &ctask->digest_count, &sent);
+	iscsi_buf_init_iov(buf, (char*)digest, 4);
+	rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
 	if (rc) {
-		ctask->datadigest = *digest;
-		ctask->xmstate |= XMSTATE_DATA_DIGEST;
+		tcp_ctask->datadigest = *digest;
+		tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
 	} else
-		ctask->digest_count = 4;
+		tcp_ctask->digest_count = 4;
 	return rc;
 }
 
@@ -1453,21 +1203,19 @@
 iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
 			struct iscsi_r2t_info *r2t, int left)
 {
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	struct iscsi_data *hdr;
-	struct iscsi_data_task *dtask;
 	struct scsi_cmnd *sc = ctask->sc;
 	int new_offset;
 
-	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
-	BUG_ON(!dtask);
-	hdr = &dtask->hdr;
+	hdr = &r2t->dtask.hdr;
 	memset(hdr, 0, sizeof(struct iscsi_data));
 	hdr->ttt = r2t->ttt;
 	hdr->datasn = cpu_to_be32(r2t->solicit_datasn);
 	r2t->solicit_datasn++;
 	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
-	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
-	hdr->itt = ctask->hdr.itt;
+	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+	hdr->itt = ctask->hdr->itt;
 	hdr->exp_statsn = r2t->exp_statsn;
 	new_offset = r2t->data_offset + r2t->sent;
 	hdr->offset = cpu_to_be32(new_offset);
@@ -1481,181 +1229,98 @@
 	}
 	conn->dataout_pdus_cnt++;
 
-	iscsi_buf_init_virt(&r2t->headbuf, (char*)hdr,
+	iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
 			   sizeof(struct iscsi_hdr));
 
-	r2t->dtask = dtask;
-
 	if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) {
-		BUG_ON(ctask->bad_sg == r2t->sg);
+		BUG_ON(tcp_ctask->bad_sg == r2t->sg);
 		iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
 		r2t->sg += 1;
 	} else
-		iscsi_buf_init_iov(&ctask->sendbuf,
+		iscsi_buf_init_iov(&tcp_ctask->sendbuf,
 			    (char*)sc->request_buffer + new_offset,
 			    r2t->data_count);
-
-	list_add(&dtask->item, &ctask->dataqueue);
 }
 
 static void
 iscsi_unsolicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
-	struct iscsi_data *hdr;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	struct iscsi_data_task *dtask;
 
-	dtask = mempool_alloc(ctask->datapool, GFP_ATOMIC);
-	BUG_ON(!dtask);
-	hdr = &dtask->hdr;
-	memset(hdr, 0, sizeof(struct iscsi_data));
-	hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
-	hdr->datasn = cpu_to_be32(ctask->unsol_datasn);
-	ctask->unsol_datasn++;
-	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
-	memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
-	hdr->itt = ctask->hdr.itt;
-	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
-	hdr->offset = cpu_to_be32(ctask->total_length -
-				  ctask->r2t_data_count -
-				  ctask->unsol_count);
-	if (ctask->unsol_count > conn->max_xmit_dlength) {
-		hton24(hdr->dlength, conn->max_xmit_dlength);
-		ctask->data_count = conn->max_xmit_dlength;
-		hdr->flags = 0;
-	} else {
-		hton24(hdr->dlength, ctask->unsol_count);
-		ctask->data_count = ctask->unsol_count;
-		hdr->flags = ISCSI_FLAG_CMD_FINAL;
-	}
-
-	iscsi_buf_init_virt(&ctask->headbuf, (char*)hdr,
+	dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask;
+	iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr,
+				      tcp_ctask->r2t_data_count);
+	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
 			   sizeof(struct iscsi_hdr));
-
-	list_add(&dtask->item, &ctask->dataqueue);
-
-	ctask->dtask = dtask;
 }
 
 /**
- * iscsi_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
+ * iscsi_tcp_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
  * @conn: iscsi connection
  * @ctask: scsi command task
  * @sc: scsi command
  **/
 static void
-iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
-		struct scsi_cmnd *sc)
+iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
 {
-	struct iscsi_session *session = conn->session;
+	struct scsi_cmnd *sc = ctask->sc;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
-	BUG_ON(__kfifo_len(ctask->r2tqueue));
+	BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
 
-	ctask->sc = sc;
-	ctask->conn = conn;
-	ctask->hdr.opcode = ISCSI_OP_SCSI_CMD;
-	ctask->hdr.flags = ISCSI_ATTR_SIMPLE;
-	int_to_scsilun(sc->device->lun, (struct scsi_lun *)ctask->hdr.lun);
-	ctask->hdr.itt = ctask->itt | (conn->id << CID_SHIFT) |
-			 (session->age << AGE_SHIFT);
-	ctask->hdr.data_length = cpu_to_be32(sc->request_bufflen);
-	ctask->hdr.cmdsn = cpu_to_be32(session->cmdsn); session->cmdsn++;
-	ctask->hdr.exp_statsn = cpu_to_be32(conn->exp_statsn);
-	memcpy(ctask->hdr.cdb, sc->cmnd, sc->cmd_len);
-	memset(&ctask->hdr.cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
-
-	ctask->mtask = NULL;
-	ctask->sent = 0;
-	ctask->sg_count = 0;
-
-	ctask->total_length = sc->request_bufflen;
+	tcp_ctask->sent = 0;
+	tcp_ctask->sg_count = 0;
 
 	if (sc->sc_data_direction == DMA_TO_DEVICE) {
-		ctask->exp_r2tsn = 0;
-		ctask->hdr.flags |= ISCSI_FLAG_CMD_WRITE;
+		tcp_ctask->xmstate = XMSTATE_W_HDR;
+		tcp_ctask->exp_r2tsn = 0;
 		BUG_ON(ctask->total_length == 0);
+
 		if (sc->use_sg) {
 			struct scatterlist *sg = sc->request_buffer;
 
-			iscsi_buf_init_sg(&ctask->sendbuf,
-					  &sg[ctask->sg_count++]);
-			ctask->sg = sg;
-			ctask->bad_sg = sg + sc->use_sg;
-		} else {
-			iscsi_buf_init_iov(&ctask->sendbuf, sc->request_buffer,
-					sc->request_bufflen);
-		}
-
-		/*
-		 * Write counters:
-		 *
-		 *	imm_count	bytes to be sent right after
-		 *			SCSI PDU Header
-		 *
-		 *	unsol_count	bytes(as Data-Out) to be sent
-		 *			without	R2T ack right after
-		 *			immediate data
-		 *
-		 *	r2t_data_count	bytes to be sent via R2T ack's
-		 *
-		 *      pad_count       bytes to be sent as zero-padding
-		 */
-		ctask->imm_count = 0;
-		ctask->unsol_count = 0;
-		ctask->unsol_datasn = 0;
-		ctask->xmstate = XMSTATE_W_HDR;
-		/* calculate write padding */
-		ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1);
-		if (ctask->pad_count) {
-			ctask->pad_count = ISCSI_PAD_LEN - ctask->pad_count;
-			debug_scsi("write padding %d bytes\n",
-				ctask->pad_count);
-			ctask->xmstate |= XMSTATE_W_PAD;
-		}
-		if (session->imm_data_en) {
-			if (ctask->total_length >= session->first_burst)
-				ctask->imm_count = min(session->first_burst,
-							conn->max_xmit_dlength);
-			else
-				ctask->imm_count = min(ctask->total_length,
-							conn->max_xmit_dlength);
-			hton24(ctask->hdr.dlength, ctask->imm_count);
-			ctask->xmstate |= XMSTATE_IMM_DATA;
+			iscsi_buf_init_sg(&tcp_ctask->sendbuf,
+					  &sg[tcp_ctask->sg_count++]);
+			tcp_ctask->sg = sg;
+			tcp_ctask->bad_sg = sg + sc->use_sg;
 		} else
-			zero_data(ctask->hdr.dlength);
+			iscsi_buf_init_iov(&tcp_ctask->sendbuf,
+					   sc->request_buffer,
+					   sc->request_bufflen);
 
-		if (!session->initial_r2t_en)
-			ctask->unsol_count = min(session->first_burst,
-				ctask->total_length) - ctask->imm_count;
-		if (!ctask->unsol_count)
-			/* No unsolicit Data-Out's */
-			ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL;
-		else
-			ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
+		if (ctask->imm_count)
+			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
 
-		ctask->r2t_data_count = ctask->total_length -
+		tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1);
+		if (tcp_ctask->pad_count) {
+			tcp_ctask->pad_count = ISCSI_PAD_LEN -
+							tcp_ctask->pad_count;
+			debug_scsi("write padding %d bytes\n",
+				   tcp_ctask->pad_count);
+			tcp_ctask->xmstate |= XMSTATE_W_PAD;
+		}
+
+		if (ctask->unsol_count)
+			tcp_ctask->xmstate |= XMSTATE_UNS_HDR |
+						XMSTATE_UNS_INIT;
+		tcp_ctask->r2t_data_count = ctask->total_length -
 				    ctask->imm_count -
 				    ctask->unsol_count;
 
 		debug_scsi("cmd [itt %x total %d imm %d imm_data %d "
 			   "r2t_data %d]\n",
 			   ctask->itt, ctask->total_length, ctask->imm_count,
-			   ctask->unsol_count, ctask->r2t_data_count);
-	} else {
-		ctask->hdr.flags |= ISCSI_FLAG_CMD_FINAL;
-		if (sc->sc_data_direction == DMA_FROM_DEVICE)
-			ctask->hdr.flags |= ISCSI_FLAG_CMD_READ;
-		ctask->datasn = 0;
-		ctask->xmstate = XMSTATE_R_HDR;
-		zero_data(ctask->hdr.dlength);
-	}
+			   ctask->unsol_count, tcp_ctask->r2t_data_count);
+	} else
+		tcp_ctask->xmstate = XMSTATE_R_HDR;
 
-	iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr,
+	iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
 			    sizeof(struct iscsi_hdr));
-	conn->scsicmd_pdus_cnt++;
 }
 
 /**
- * iscsi_mtask_xmit - xmit management(immediate) task
+ * iscsi_tcp_mtask_xmit - xmit management(immediate) task
  * @conn: iscsi connection
  * @mtask: task management task
  *
@@ -1669,132 +1334,167 @@
  *		IN_PROGRESS_IMM_DATA - PDU Data xmit in progress
  **/
 static int
-iscsi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
+iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
 {
+	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+	int rc;
 
 	debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
-		conn->id, mtask->xmstate, mtask->itt);
+		conn->id, tcp_mtask->xmstate, mtask->itt);
 
-	if (mtask->xmstate & XMSTATE_IMM_HDR) {
-		mtask->xmstate &= ~XMSTATE_IMM_HDR;
+	if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
+		tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
 		if (mtask->data_count)
-			mtask->xmstate |= XMSTATE_IMM_DATA;
+			tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
 		if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
-	    	    conn->stop_stage != STOP_CONN_RECOVER &&
+		    conn->stop_stage != STOP_CONN_RECOVER &&
 		    conn->hdrdgst_en)
-			iscsi_hdr_digest(conn, &mtask->headbuf,
-					(u8*)mtask->hdrext);
-		if (iscsi_sendhdr(conn, &mtask->headbuf, mtask->data_count)) {
-			mtask->xmstate |= XMSTATE_IMM_HDR;
+			iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
+					(u8*)tcp_mtask->hdrext);
+		rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
+				   mtask->data_count);
+		if (rc) {
+			tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
 			if (mtask->data_count)
-				mtask->xmstate &= ~XMSTATE_IMM_DATA;
-			return -EAGAIN;
+				tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
+			return rc;
 		}
 	}
 
-	if (mtask->xmstate & XMSTATE_IMM_DATA) {
+	if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
 		BUG_ON(!mtask->data_count);
-		mtask->xmstate &= ~XMSTATE_IMM_DATA;
+		tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
 		/* FIXME: implement.
 		 * Virtual buffer could be spreaded across multiple pages...
 		 */
 		do {
-			if (iscsi_sendpage(conn, &mtask->sendbuf,
-				   &mtask->data_count, &mtask->sent)) {
-				mtask->xmstate |= XMSTATE_IMM_DATA;
-				return -EAGAIN;
+			int rc;
+
+			rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf,
+					&mtask->data_count, &tcp_mtask->sent);
+			if (rc) {
+				tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
+				return rc;
 			}
 		} while (mtask->data_count);
 	}
 
-	BUG_ON(mtask->xmstate != XMSTATE_IDLE);
+	BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE);
+	if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		struct iscsi_session *session = conn->session;
+
+		spin_lock_bh(&session->lock);
+		list_del(&conn->mtask->running);
+		__kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
+			    sizeof(void*));
+		spin_unlock_bh(&session->lock);
+	}
 	return 0;
 }
 
 static inline int
-handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+handle_xmstate_r_hdr(struct iscsi_conn *conn,
+		     struct iscsi_tcp_cmd_task *tcp_ctask)
 {
-	ctask->xmstate &= ~XMSTATE_R_HDR;
+	int rc;
+
+	tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
 	if (conn->hdrdgst_en)
-		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
-	if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) {
-		BUG_ON(ctask->xmstate != XMSTATE_IDLE);
+		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+				 (u8*)tcp_ctask->hdrext);
+	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0);
+	if (!rc) {
+		BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
 		return 0; /* wait for Data-In */
 	}
-	ctask->xmstate |= XMSTATE_R_HDR;
-	return -EAGAIN;
+	tcp_ctask->xmstate |= XMSTATE_R_HDR;
+	return rc;
 }
 
 static inline int
-handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+handle_xmstate_w_hdr(struct iscsi_conn *conn,
+		     struct iscsi_cmd_task *ctask)
 {
-	ctask->xmstate &= ~XMSTATE_W_HDR;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	int rc;
+
+	tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
 	if (conn->hdrdgst_en)
-		iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext);
-	if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) {
-		ctask->xmstate |= XMSTATE_W_HDR;
-		return -EAGAIN;
-	}
-	return 0;
+		iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
+				 (u8*)tcp_ctask->hdrext);
+	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
+	if (rc)
+		tcp_ctask->xmstate |= XMSTATE_W_HDR;
+	return rc;
 }
 
 static inline int
 handle_xmstate_data_digest(struct iscsi_conn *conn,
 			   struct iscsi_cmd_task *ctask)
 {
-	ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
-	debug_tcp("resent data digest 0x%x\n", ctask->datadigest);
-	if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
-				    &ctask->datadigest, 0)) {
-		ctask->xmstate |= XMSTATE_DATA_DIGEST;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	int rc;
+
+	tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
+	debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest);
+	rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
+				    &tcp_ctask->datadigest, 0);
+	if (rc) {
+		tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
 		debug_tcp("resent data digest 0x%x fail!\n",
-			  ctask->datadigest);
-		return -EAGAIN;
+			  tcp_ctask->datadigest);
 	}
-	return 0;
+
+	return rc;
 }
 
 static inline int
 handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	int rc;
+
 	BUG_ON(!ctask->imm_count);
-	ctask->xmstate &= ~XMSTATE_IMM_DATA;
+	tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
 
 	if (conn->datadgst_en) {
-		iscsi_data_digest_init(conn, ctask);
-		ctask->immdigest = 0;
+		iscsi_data_digest_init(tcp_conn, ctask);
+		tcp_ctask->immdigest = 0;
 	}
 
 	for (;;) {
-		if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->imm_count,
-				   &ctask->sent)) {
-			ctask->xmstate |= XMSTATE_IMM_DATA;
+		rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
+				   &ctask->imm_count, &tcp_ctask->sent);
+		if (rc) {
+			tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
 			if (conn->datadgst_en) {
-				crypto_digest_final(conn->data_tx_tfm,
-						(u8*)&ctask->immdigest);
+				crypto_digest_final(tcp_conn->data_tx_tfm,
+						(u8*)&tcp_ctask->immdigest);
 				debug_tcp("tx imm sendpage fail 0x%x\n",
-					  ctask->datadigest);
+					  tcp_ctask->datadigest);
 			}
-			return -EAGAIN;
+			return rc;
 		}
 		if (conn->datadgst_en)
-			crypto_digest_update(conn->data_tx_tfm,
-					     &ctask->sendbuf.sg, 1);
+			crypto_digest_update(tcp_conn->data_tx_tfm,
+					     &tcp_ctask->sendbuf.sg, 1);
 
 		if (!ctask->imm_count)
 			break;
-		iscsi_buf_init_sg(&ctask->sendbuf,
-				  &ctask->sg[ctask->sg_count++]);
+		iscsi_buf_init_sg(&tcp_ctask->sendbuf,
+				  &tcp_ctask->sg[tcp_ctask->sg_count++]);
 	}
 
-	if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) {
-		if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
-				            &ctask->immdigest, 1)) {
+	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
+		rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
+				            &tcp_ctask->immdigest, 1);
+		if (rc) {
 			debug_tcp("sending imm digest 0x%x fail!\n",
-				  ctask->immdigest);
-			return -EAGAIN;
+				  tcp_ctask->immdigest);
+			return rc;
 		}
-		debug_tcp("sending imm digest 0x%x\n", ctask->immdigest);
+		debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest);
 	}
 
 	return 0;
@@ -1803,74 +1503,81 @@
 static inline int
 handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	struct iscsi_data_task *dtask;
+	int rc;
 
-	ctask->xmstate |= XMSTATE_UNS_DATA;
-	if (ctask->xmstate & XMSTATE_UNS_INIT) {
+	tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
+	if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
 		iscsi_unsolicit_data_init(conn, ctask);
-		BUG_ON(!ctask->dtask);
-		dtask = ctask->dtask;
+		dtask = tcp_ctask->dtask;
 		if (conn->hdrdgst_en)
-			iscsi_hdr_digest(conn, &ctask->headbuf,
+			iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
 					(u8*)dtask->hdrext);
-		ctask->xmstate &= ~XMSTATE_UNS_INIT;
+		tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
 	}
-	if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->data_count)) {
-		ctask->xmstate &= ~XMSTATE_UNS_DATA;
-		ctask->xmstate |= XMSTATE_UNS_HDR;
-		return -EAGAIN;
+
+	rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count);
+	if (rc) {
+		tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
+		tcp_ctask->xmstate |= XMSTATE_UNS_HDR;
+		return rc;
 	}
 
 	debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n",
-		   ctask->itt, ctask->unsol_count, ctask->sent);
+		   ctask->itt, ctask->unsol_count, tcp_ctask->sent);
 	return 0;
 }
 
 static inline int
 handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
-	struct iscsi_data_task *dtask = ctask->dtask;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	int rc;
 
 	BUG_ON(!ctask->data_count);
-	ctask->xmstate &= ~XMSTATE_UNS_DATA;
+	tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
 
 	if (conn->datadgst_en) {
-		iscsi_data_digest_init(conn, ctask);
+		iscsi_data_digest_init(tcp_conn, ctask);
 		dtask->digest = 0;
 	}
 
 	for (;;) {
-		int start = ctask->sent;
+		int start = tcp_ctask->sent;
 
-		if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->data_count,
-				   &ctask->sent)) {
-			ctask->unsol_count -= ctask->sent - start;
-			ctask->xmstate |= XMSTATE_UNS_DATA;
+		rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
+				   &ctask->data_count, &tcp_ctask->sent);
+		if (rc) {
+			ctask->unsol_count -= tcp_ctask->sent - start;
+			tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
 			/* will continue with this ctask later.. */
 			if (conn->datadgst_en) {
-				crypto_digest_final(conn->data_tx_tfm,
+				crypto_digest_final(tcp_conn->data_tx_tfm,
 						(u8 *)&dtask->digest);
 				debug_tcp("tx uns data fail 0x%x\n",
 					  dtask->digest);
 			}
-			return -EAGAIN;
+			return rc;
 		}
 
-		BUG_ON(ctask->sent > ctask->total_length);
-		ctask->unsol_count -= ctask->sent - start;
+		BUG_ON(tcp_ctask->sent > ctask->total_length);
+		ctask->unsol_count -= tcp_ctask->sent - start;
 
 		/*
 		 * XXX:we may run here with un-initial sendbuf.
 		 * so pass it
 		 */
-		if (conn->datadgst_en && ctask->sent - start > 0)
-			crypto_digest_update(conn->data_tx_tfm,
-					     &ctask->sendbuf.sg, 1);
+		if (conn->datadgst_en && tcp_ctask->sent - start > 0)
+			crypto_digest_update(tcp_conn->data_tx_tfm,
+					     &tcp_ctask->sendbuf.sg, 1);
 
 		if (!ctask->data_count)
 			break;
-		iscsi_buf_init_sg(&ctask->sendbuf,
-				  &ctask->sg[ctask->sg_count++]);
+		iscsi_buf_init_sg(&tcp_ctask->sendbuf,
+				  &tcp_ctask->sg[tcp_ctask->sg_count++]);
 	}
 	BUG_ON(ctask->unsol_count < 0);
 
@@ -1880,27 +1587,29 @@
 	 */
 	if (ctask->unsol_count) {
 		if (conn->datadgst_en) {
-			if (iscsi_digest_final_send(conn, ctask,
+			rc = iscsi_digest_final_send(conn, ctask,
 						    &dtask->digestbuf,
-						    &dtask->digest, 1)) {
+						    &dtask->digest, 1);
+			if (rc) {
 				debug_tcp("send uns digest 0x%x fail\n",
 					  dtask->digest);
-				return -EAGAIN;
+				return rc;
 			}
 			debug_tcp("sending uns digest 0x%x, more uns\n",
 				  dtask->digest);
 		}
-		ctask->xmstate |= XMSTATE_UNS_INIT;
+		tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
 		return 1;
 	}
 
-	if (conn->datadgst_en && !(ctask->xmstate & XMSTATE_W_PAD)) {
-		if (iscsi_digest_final_send(conn, ctask,
+	if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
+		rc = iscsi_digest_final_send(conn, ctask,
 					    &dtask->digestbuf,
-					    &dtask->digest, 1)) {
+					    &dtask->digest, 1);
+		if (rc) {
 			debug_tcp("send last uns digest 0x%x fail\n",
 				   dtask->digest);
-			return -EAGAIN;
+			return rc;
 		}
 		debug_tcp("sending uns digest 0x%x\n",dtask->digest);
 	}
@@ -1912,15 +1621,17 @@
 handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
 	struct iscsi_session *session = conn->session;
-	struct iscsi_r2t_info *r2t = ctask->r2t;
-	struct iscsi_data_task *dtask = r2t->dtask;
-	int left;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_r2t_info *r2t = tcp_ctask->r2t;
+	struct iscsi_data_task *dtask = &r2t->dtask;
+	int left, rc;
 
-	ctask->xmstate &= ~XMSTATE_SOL_DATA;
-	ctask->dtask = dtask;
+	tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+	tcp_ctask->dtask = dtask;
 
 	if (conn->datadgst_en) {
-		iscsi_data_digest_init(conn, ctask);
+		iscsi_data_digest_init(tcp_conn, ctask);
 		dtask->digest = 0;
 	}
 solicit_again:
@@ -1930,25 +1641,27 @@
 	if (!r2t->data_count)
 		goto data_out_done;
 
-	if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) {
-		ctask->xmstate |= XMSTATE_SOL_DATA;
+	rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent);
+	if (rc) {
+		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
 		/* will continue with this ctask later.. */
 		if (conn->datadgst_en) {
-			crypto_digest_final(conn->data_tx_tfm,
+			crypto_digest_final(tcp_conn->data_tx_tfm,
 					  (u8 *)&dtask->digest);
 			debug_tcp("r2t data send fail 0x%x\n", dtask->digest);
 		}
-		return -EAGAIN;
+		return rc;
 	}
 
 	BUG_ON(r2t->data_count < 0);
 	if (conn->datadgst_en)
-		crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1);
+		crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg,
+				     1);
 
 	if (r2t->data_count) {
 		BUG_ON(ctask->sc->use_sg == 0);
 		if (!iscsi_buf_left(&r2t->sendbuf)) {
-			BUG_ON(ctask->bad_sg == r2t->sg);
+			BUG_ON(tcp_ctask->bad_sg == r2t->sg);
 			iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
 			r2t->sg += 1;
 		}
@@ -1964,19 +1677,20 @@
 	left = r2t->data_length - r2t->sent;
 	if (left) {
 		if (conn->datadgst_en) {
-			if (iscsi_digest_final_send(conn, ctask,
+			rc = iscsi_digest_final_send(conn, ctask,
 						    &dtask->digestbuf,
-						    &dtask->digest, 1)) {
+						    &dtask->digest, 1);
+			if (rc) {
 				debug_tcp("send r2t data digest 0x%x"
 					  "fail\n", dtask->digest);
-				return -EAGAIN;
+				return rc;
 			}
 			debug_tcp("r2t data send digest 0x%x\n",
 				  dtask->digest);
 		}
 		iscsi_solicit_data_cont(conn, ctask, r2t, left);
-		ctask->xmstate |= XMSTATE_SOL_DATA;
-		ctask->xmstate &= ~XMSTATE_SOL_HDR;
+		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
 		return 1;
 	}
 
@@ -1984,26 +1698,27 @@
 	 * Done with this R2T. Check if there are more
 	 * outstanding R2Ts ready to be processed.
 	 */
-	BUG_ON(ctask->r2t_data_count - r2t->data_length < 0);
+	BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0);
 	if (conn->datadgst_en) {
-		if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
-					    &dtask->digest, 1)) {
+		rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
+					    &dtask->digest, 1);
+		if (rc) {
 			debug_tcp("send last r2t data digest 0x%x"
 				  "fail\n", dtask->digest);
-			return -EAGAIN;
+			return rc;
 		}
 		debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
 	}
 
-	ctask->r2t_data_count -= r2t->data_length;
-	ctask->r2t = NULL;
+	tcp_ctask->r2t_data_count -= r2t->data_length;
+	tcp_ctask->r2t = NULL;
 	spin_lock_bh(&session->lock);
-	__kfifo_put(ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
+	__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*));
 	spin_unlock_bh(&session->lock);
-	if (__kfifo_get(ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
-		ctask->r2t = r2t;
-		ctask->xmstate |= XMSTATE_SOL_DATA;
-		ctask->xmstate &= ~XMSTATE_SOL_HDR;
+	if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
+		tcp_ctask->r2t = r2t;
+		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
 		return 1;
 	}
 
@@ -2013,36 +1728,44 @@
 static inline int
 handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
-	struct iscsi_data_task *dtask = ctask->dtask;
-	int sent;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_data_task *dtask = tcp_ctask->dtask;
+	int sent, rc;
 
-	ctask->xmstate &= ~XMSTATE_W_PAD;
-	iscsi_buf_init_virt(&ctask->sendbuf, (char*)&ctask->pad,
-			    ctask->pad_count);
-	if (iscsi_sendpage(conn, &ctask->sendbuf, &ctask->pad_count, &sent)) {
-		ctask->xmstate |= XMSTATE_W_PAD;
-		return -EAGAIN;
+	tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
+	iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+			    tcp_ctask->pad_count);
+	rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
+			   &sent);
+	if (rc) {
+		tcp_ctask->xmstate |= XMSTATE_W_PAD;
+		return rc;
 	}
 
 	if (conn->datadgst_en) {
-		crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1);
+		crypto_digest_update(tcp_conn->data_tx_tfm,
+				     &tcp_ctask->sendbuf.sg, 1);
 		/* imm data? */
 		if (!dtask) {
-			if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf,
-						    &ctask->immdigest, 1)) {
+			rc = iscsi_digest_final_send(conn, ctask,
+						    &tcp_ctask->immbuf,
+						    &tcp_ctask->immdigest, 1);
+			if (rc) {
 				debug_tcp("send padding digest 0x%x"
-					  "fail!\n", ctask->immdigest);
-				return -EAGAIN;
+					  "fail!\n", tcp_ctask->immdigest);
+				return rc;
 			}
 			debug_tcp("done with padding, digest 0x%x\n",
-				  ctask->datadigest);
+				  tcp_ctask->datadigest);
 		} else {
-			if (iscsi_digest_final_send(conn, ctask,
+			rc = iscsi_digest_final_send(conn, ctask,
 						    &dtask->digestbuf,
-						    &dtask->digest, 1)) {
+						    &dtask->digest, 1);
+			if (rc) {
 				debug_tcp("send padding digest 0x%x"
 				          "fail\n", dtask->digest);
-				return -EAGAIN;
+				return rc;
 			}
 			debug_tcp("done with padding, digest 0x%x\n",
 				  dtask->digest);
@@ -2053,12 +1776,13 @@
 }
 
 static int
-iscsi_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 	int rc = 0;
 
 	debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n",
-		conn->id, ctask->xmstate, ctask->itt);
+		conn->id, tcp_ctask->xmstate, ctask->itt);
 
 	/*
 	 * serialize with TMF AbortTask
@@ -2066,40 +1790,38 @@
 	if (ctask->mtask)
 		return rc;
 
-	if (ctask->xmstate & XMSTATE_R_HDR) {
-		rc = handle_xmstate_r_hdr(conn, ctask);
-		return rc;
-	}
+	if (tcp_ctask->xmstate & XMSTATE_R_HDR)
+		return handle_xmstate_r_hdr(conn, tcp_ctask);
 
-	if (ctask->xmstate & XMSTATE_W_HDR) {
+	if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
 		rc = handle_xmstate_w_hdr(conn, ctask);
 		if (rc)
 			return rc;
 	}
 
 	/* XXX: for data digest xmit recover */
-	if (ctask->xmstate & XMSTATE_DATA_DIGEST) {
+	if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) {
 		rc = handle_xmstate_data_digest(conn, ctask);
 		if (rc)
 			return rc;
 	}
 
-	if (ctask->xmstate & XMSTATE_IMM_DATA) {
+	if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
 		rc = handle_xmstate_imm_data(conn, ctask);
 		if (rc)
 			return rc;
 	}
 
-	if (ctask->xmstate & XMSTATE_UNS_HDR) {
+	if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) {
 		BUG_ON(!ctask->unsol_count);
-		ctask->xmstate &= ~XMSTATE_UNS_HDR;
+		tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR;
 unsolicit_head_again:
 		rc = handle_xmstate_uns_hdr(conn, ctask);
 		if (rc)
 			return rc;
 	}
 
-	if (ctask->xmstate & XMSTATE_UNS_DATA) {
+	if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) {
 		rc = handle_xmstate_uns_data(conn, ctask);
 		if (rc == 1)
 			goto unsolicit_head_again;
@@ -2108,23 +1830,24 @@
 		goto done;
 	}
 
-	if (ctask->xmstate & XMSTATE_SOL_HDR) {
+	if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
 		struct iscsi_r2t_info *r2t;
 
-		ctask->xmstate &= ~XMSTATE_SOL_HDR;
-		ctask->xmstate |= XMSTATE_SOL_DATA;
-		if (!ctask->r2t)
-			__kfifo_get(ctask->r2tqueue, (void*)&ctask->r2t,
+		tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
+		tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
+		if (!tcp_ctask->r2t)
+			__kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
 				    sizeof(void*));
 solicit_head_again:
-		r2t = ctask->r2t;
+		r2t = tcp_ctask->r2t;
 		if (conn->hdrdgst_en)
 			iscsi_hdr_digest(conn, &r2t->headbuf,
-					(u8*)r2t->dtask->hdrext);
-		if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) {
-			ctask->xmstate &= ~XMSTATE_SOL_DATA;
-			ctask->xmstate |= XMSTATE_SOL_HDR;
-			return -EAGAIN;
+					(u8*)r2t->dtask.hdrext);
+		rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
+		if (rc) {
+			tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
+			tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
+			return rc;
 		}
 
 		debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
@@ -2132,7 +1855,7 @@
 			r2t->sent);
 	}
 
-	if (ctask->xmstate & XMSTATE_SOL_DATA) {
+	if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) {
 		rc = handle_xmstate_sol_data(conn, ctask);
 		if (rc == 1)
 			goto solicit_head_again;
@@ -2145,1022 +1868,199 @@
 	 * Last thing to check is whether we need to send write
 	 * padding. Note that we check for xmstate equality, not just the bit.
 	 */
-	if (ctask->xmstate == XMSTATE_W_PAD)
+	if (tcp_ctask->xmstate == XMSTATE_W_PAD)
 		rc = handle_xmstate_w_pad(conn, ctask);
 
 	return rc;
 }
 
-/**
- * iscsi_data_xmit - xmit any command into the scheduled connection
- * @conn: iscsi connection
- *
- * Notes:
- *	The function can return -EAGAIN in which case the caller must
- *	re-schedule it again later or recover. '0' return code means
- *	successful xmit.
- **/
-static int
-iscsi_data_xmit(struct iscsi_conn *conn)
-{
-	if (unlikely(conn->suspend_tx)) {
-		debug_tcp("conn %d Tx suspended!\n", conn->id);
-		return 0;
-	}
-
-	/*
-	 * Transmit in the following order:
-	 *
-	 * 1) un-finished xmit (ctask or mtask)
-	 * 2) immediate control PDUs
-	 * 3) write data
-	 * 4) SCSI commands
-	 * 5) non-immediate control PDUs
-	 *
-	 * No need to lock around __kfifo_get as long as
-	 * there's one producer and one consumer.
-	 */
-
-	BUG_ON(conn->ctask && conn->mtask);
-
-	if (conn->ctask) {
-		if (iscsi_ctask_xmit(conn, conn->ctask))
-			goto again;
-		/* done with this in-progress ctask */
-		conn->ctask = NULL;
-	}
-	if (conn->mtask) {
-	        if (iscsi_mtask_xmit(conn, conn->mtask))
-		        goto again;
-		/* done with this in-progress mtask */
-		conn->mtask = NULL;
-	}
-
-	/* process immediate first */
-        if (unlikely(__kfifo_len(conn->immqueue))) {
-		struct iscsi_session *session = conn->session;
-	        while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
-			           sizeof(void*))) {
-		        if (iscsi_mtask_xmit(conn, conn->mtask))
-			        goto again;
-
-		        if (conn->mtask->hdr.itt ==
-					cpu_to_be32(ISCSI_RESERVED_TAG)) {
-			        spin_lock_bh(&session->lock);
-			        __kfifo_put(session->mgmtpool.queue,
-					    (void*)&conn->mtask, sizeof(void*));
-			        spin_unlock_bh(&session->lock);
-		        }
-	        }
-		/* done with this mtask */
-		conn->mtask = NULL;
-	}
-
-	/* process write queue */
-	while (__kfifo_get(conn->writequeue, (void*)&conn->ctask,
-			   sizeof(void*))) {
-		if (iscsi_ctask_xmit(conn, conn->ctask))
-			goto again;
-	}
-
-	/* process command queue */
-	while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
-			   sizeof(void*))) {
-		if (iscsi_ctask_xmit(conn, conn->ctask))
-			goto again;
-	}
-	/* done with this ctask */
-	conn->ctask = NULL;
-
-	/* process the rest control plane PDUs, if any */
-        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
-		struct iscsi_session *session = conn->session;
-
-	        while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
-			           sizeof(void*))) {
-		        if (iscsi_mtask_xmit(conn, conn->mtask))
-			        goto again;
-
-		        if (conn->mtask->hdr.itt ==
-					cpu_to_be32(ISCSI_RESERVED_TAG)) {
-			        spin_lock_bh(&session->lock);
-			        __kfifo_put(session->mgmtpool.queue,
-					    (void*)&conn->mtask,
-				            sizeof(void*));
-			        spin_unlock_bh(&session->lock);
-		        }
-	        }
-		/* done with this mtask */
-		conn->mtask = NULL;
-	}
-
-	return 0;
-
-again:
-	if (unlikely(conn->suspend_tx))
-		return 0;
-
-	return -EAGAIN;
-}
-
-static void
-iscsi_xmitworker(void *data)
-{
-	struct iscsi_conn *conn = data;
-
-	/*
-	 * serialize Xmit worker on a per-connection basis.
-	 */
-	mutex_lock(&conn->xmitmutex);
-	if (iscsi_data_xmit(conn))
-		scsi_queue_work(conn->session->host, &conn->xmitwork);
-	mutex_unlock(&conn->xmitmutex);
-}
-
-#define FAILURE_BAD_HOST		1
-#define FAILURE_SESSION_FAILED		2
-#define FAILURE_SESSION_FREED		3
-#define FAILURE_WINDOW_CLOSED		4
-#define FAILURE_SESSION_TERMINATE	5
-
-static int
-iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
-{
-	struct Scsi_Host *host;
-	int reason = 0;
-	struct iscsi_session *session;
-	struct iscsi_conn *conn = NULL;
-	struct iscsi_cmd_task *ctask = NULL;
-
-	sc->scsi_done = done;
-	sc->result = 0;
-
-	host = sc->device->host;
-	session = iscsi_hostdata(host->hostdata);
-	BUG_ON(host != session->host);
-
-	spin_lock(&session->lock);
-
-	if (session->state != ISCSI_STATE_LOGGED_IN) {
-		if (session->state == ISCSI_STATE_FAILED) {
-			reason = FAILURE_SESSION_FAILED;
-			goto reject;
-		} else if (session->state == ISCSI_STATE_TERMINATE) {
-			reason = FAILURE_SESSION_TERMINATE;
-			goto fault;
-		}
-		reason = FAILURE_SESSION_FREED;
-		goto fault;
-	}
-
-	/*
-	 * Check for iSCSI window and take care of CmdSN wrap-around
-	 */
-	if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
-		reason = FAILURE_WINDOW_CLOSED;
-		goto reject;
-	}
-
-	conn = session->leadconn;
-
-	__kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
-	BUG_ON(ctask->sc);
-
-	sc->SCp.phase = session->age;
-	sc->SCp.ptr = (char*)ctask;
-	iscsi_cmd_init(conn, ctask, sc);
-
-	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
-	debug_scsi(
-	       "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
-		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
-		conn->id, (long)sc, ctask->itt, sc->request_bufflen,
-		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
-	spin_unlock(&session->lock);
-
-	scsi_queue_work(host, &conn->xmitwork);
-	return 0;
-
-reject:
-	spin_unlock(&session->lock);
-	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
-	return SCSI_MLQUEUE_HOST_BUSY;
-
-fault:
-	spin_unlock(&session->lock);
-	printk(KERN_ERR "iscsi_tcp: cmd 0x%x is not queued (%d)\n",
-	       sc->cmnd[0], reason);
-	sc->sense_buffer[0] = 0x70;
-	sc->sense_buffer[2] = NOT_READY;
-	sc->sense_buffer[7] = 0x6;
-	sc->sense_buffer[12] = 0x08;
-	sc->sense_buffer[13] = 0x00;
-	sc->result = (DID_NO_CONNECT << 16);
-	sc->resid = sc->request_bufflen;
-	sc->scsi_done(sc);
-	return 0;
-}
-
-static int
-iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
-{
-	if (depth > ISCSI_MAX_CMD_PER_LUN)
-		depth = ISCSI_MAX_CMD_PER_LUN;
-	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
-	return sdev->queue_depth;
-}
-
-static int
-iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
-{
-	int i;
-
-	*items = kmalloc(max * sizeof(void*), GFP_KERNEL);
-	if (*items == NULL)
-		return -ENOMEM;
-
-	q->max = max;
-	q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL);
-	if (q->pool == NULL) {
-		kfree(*items);
-		return -ENOMEM;
-	}
-
-	q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
-			      GFP_KERNEL, NULL);
-	if (q->queue == ERR_PTR(-ENOMEM)) {
-		kfree(q->pool);
-		kfree(*items);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < max; i++) {
-		q->pool[i] = kmalloc(item_size, GFP_KERNEL);
-		if (q->pool[i] == NULL) {
-			int j;
-
-			for (j = 0; j < i; j++)
-				kfree(q->pool[j]);
-
-			kfifo_free(q->queue);
-			kfree(q->pool);
-			kfree(*items);
-			return -ENOMEM;
-		}
-		memset(q->pool[i], 0, item_size);
-		(*items)[i] = q->pool[i];
-		__kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*));
-	}
-	return 0;
-}
-
-static void
-iscsi_pool_free(struct iscsi_queue *q, void **items)
-{
-	int i;
-
-	for (i = 0; i < q->max; i++)
-		kfree(items[i]);
-	kfree(q->pool);
-	kfree(items);
-}
-
 static struct iscsi_cls_conn *
-iscsi_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+iscsi_tcp_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
 {
-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
 	struct iscsi_conn *conn;
 	struct iscsi_cls_conn *cls_conn;
+	struct iscsi_tcp_conn *tcp_conn;
 
-	cls_conn = iscsi_create_conn(cls_session, conn_idx);
+	cls_conn = iscsi_conn_setup(cls_session, conn_idx);
 	if (!cls_conn)
 		return NULL;
 	conn = cls_conn->dd_data;
-	memset(conn, 0, sizeof(*conn));
-
-	conn->cls_conn = cls_conn;
-	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
-	conn->in_progress = IN_PROGRESS_WAIT_HEADER;
-	conn->id = conn_idx;
-	conn->exp_statsn = 0;
-	conn->tmabort_state = TMABORT_INITIAL;
-
-	/* initial operational parameters */
-	conn->hdr_size = sizeof(struct iscsi_hdr);
-	conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
+	/*
+	 * due to strange issues with iser these are not set
+	 * in iscsi_conn_setup
+	 */
 	conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
 
-	/* initialize general xmit PDU commands queue */
-	conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
-					GFP_KERNEL, NULL);
-	if (conn->xmitqueue == ERR_PTR(-ENOMEM))
-		goto xmitqueue_alloc_fail;
+	tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL);
+	if (!tcp_conn)
+		goto tcp_conn_alloc_fail;
 
-	/* initialize write response PDU commands queue */
-	conn->writequeue = kfifo_alloc(session->cmds_max * sizeof(void*),
-					GFP_KERNEL, NULL);
-	if (conn->writequeue == ERR_PTR(-ENOMEM))
-		goto writequeue_alloc_fail;
-
-	/* initialize general immediate & non-immediate PDU commands queue */
-	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
-			                GFP_KERNEL, NULL);
-	if (conn->immqueue == ERR_PTR(-ENOMEM))
-		goto immqueue_alloc_fail;
-
-	conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
-			                GFP_KERNEL, NULL);
-	if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
-		goto mgmtqueue_alloc_fail;
-
-	INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn);
-
-	/* allocate login_mtask used for the login/text sequences */
-	spin_lock_bh(&session->lock);
-	if (!__kfifo_get(session->mgmtpool.queue,
-                         (void*)&conn->login_mtask,
-			 sizeof(void*))) {
-		spin_unlock_bh(&session->lock);
-		goto login_mtask_alloc_fail;
-	}
-	spin_unlock_bh(&session->lock);
+	conn->dd_data = tcp_conn;
+	tcp_conn->iscsi_conn = conn;
+	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
+	/* initial operational parameters */
+	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+	tcp_conn->data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH;
 
 	/* allocate initial PDU receive place holder */
-	if (conn->data_size <= PAGE_SIZE)
-		conn->data = kmalloc(conn->data_size, GFP_KERNEL);
+	if (tcp_conn->data_size <= PAGE_SIZE)
+		tcp_conn->data = kmalloc(tcp_conn->data_size, GFP_KERNEL);
 	else
-		conn->data = (void*)__get_free_pages(GFP_KERNEL,
-					get_order(conn->data_size));
-	if (!conn->data)
+		tcp_conn->data = (void*)__get_free_pages(GFP_KERNEL,
+					get_order(tcp_conn->data_size));
+	if (!tcp_conn->data)
 		goto max_recv_dlenght_alloc_fail;
 
-	init_timer(&conn->tmabort_timer);
-	mutex_init(&conn->xmitmutex);
-	init_waitqueue_head(&conn->ehwait);
-
 	return cls_conn;
 
 max_recv_dlenght_alloc_fail:
-	spin_lock_bh(&session->lock);
-	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
-		    sizeof(void*));
-	spin_unlock_bh(&session->lock);
-login_mtask_alloc_fail:
-	kfifo_free(conn->mgmtqueue);
-mgmtqueue_alloc_fail:
-	kfifo_free(conn->immqueue);
-immqueue_alloc_fail:
-	kfifo_free(conn->writequeue);
-writequeue_alloc_fail:
-	kfifo_free(conn->xmitqueue);
-xmitqueue_alloc_fail:
-	iscsi_destroy_conn(cls_conn);
+	kfree(tcp_conn);
+tcp_conn_alloc_fail:
+	iscsi_conn_teardown(cls_conn);
 	return NULL;
 }
 
 static void
-iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn)
+iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_session *session = conn->session;
-	unsigned long flags;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	int digest = 0;
 
-	mutex_lock(&conn->xmitmutex);
-	set_bit(SUSPEND_BIT, &conn->suspend_tx);
-	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) {
-		struct sock *sk = conn->sock->sk;
+	if (conn->hdrdgst_en || conn->datadgst_en)
+		digest = 1;
 
-		/*
-		 * conn_start() has never been called!
-		 * need to cleanup the socket.
-		 */
-		write_lock_bh(&sk->sk_callback_lock);
-		set_bit(SUSPEND_BIT, &conn->suspend_rx);
-		write_unlock_bh(&sk->sk_callback_lock);
+	iscsi_conn_teardown(cls_conn);
 
-		sock_hold(conn->sock->sk);
-		iscsi_conn_restore_callbacks(conn);
-		sock_put(conn->sock->sk);
-		sock_release(conn->sock);
-		conn->sock = NULL;
-	}
-
-	spin_lock_bh(&session->lock);
-	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
-	if (session->leadconn == conn) {
-		/*
-		 * leading connection? then give up on recovery.
-		 */
-		session->state = ISCSI_STATE_TERMINATE;
-		wake_up(&conn->ehwait);
-	}
-	spin_unlock_bh(&session->lock);
-
-	mutex_unlock(&conn->xmitmutex);
-
-	/*
-	 * Block until all in-progress commands for this connection
-	 * time out or fail.
-	 */
-	for (;;) {
-		spin_lock_irqsave(session->host->host_lock, flags);
-		if (!session->host->host_busy) { /* OK for ERL == 0 */
-			spin_unlock_irqrestore(session->host->host_lock, flags);
-			break;
-		}
-		spin_unlock_irqrestore(session->host->host_lock, flags);
-		msleep_interruptible(500);
-		printk("conn_destroy(): host_busy %d host_failed %d\n",
-			session->host->host_busy, session->host->host_failed);
-		/*
-		 * force eh_abort() to unblock
-		 */
-		wake_up(&conn->ehwait);
-	}
-
-	/* now free crypto */
-	if (conn->hdrdgst_en || conn->datadgst_en) {
-		if (conn->tx_tfm)
-			crypto_free_tfm(conn->tx_tfm);
-		if (conn->rx_tfm)
-			crypto_free_tfm(conn->rx_tfm);
-		if (conn->data_tx_tfm)
-			crypto_free_tfm(conn->data_tx_tfm);
-		if (conn->data_rx_tfm)
-			crypto_free_tfm(conn->data_rx_tfm);
+	/* now free tcp_conn */
+	if (digest) {
+		if (tcp_conn->tx_tfm)
+			crypto_free_tfm(tcp_conn->tx_tfm);
+		if (tcp_conn->rx_tfm)
+			crypto_free_tfm(tcp_conn->rx_tfm);
+		if (tcp_conn->data_tx_tfm)
+			crypto_free_tfm(tcp_conn->data_tx_tfm);
+		if (tcp_conn->data_rx_tfm)
+			crypto_free_tfm(tcp_conn->data_rx_tfm);
 	}
 
 	/* free conn->data, size = MaxRecvDataSegmentLength */
-	if (conn->data_size <= PAGE_SIZE)
-		kfree(conn->data);
+	if (tcp_conn->data_size <= PAGE_SIZE)
+		kfree(tcp_conn->data);
 	else
-		free_pages((unsigned long)conn->data,
-					get_order(conn->data_size));
-
-	spin_lock_bh(&session->lock);
-	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
-		    sizeof(void*));
-	list_del(&conn->item);
-	if (list_empty(&session->connections))
-		session->leadconn = NULL;
-	if (session->leadconn && session->leadconn == conn)
-		session->leadconn = container_of(session->connections.next,
-			struct iscsi_conn, item);
-
-	if (session->leadconn == NULL)
-		/* none connections exits.. reset sequencing */
-		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
-	spin_unlock_bh(&session->lock);
-
-	kfifo_free(conn->xmitqueue);
-	kfifo_free(conn->writequeue);
-	kfifo_free(conn->immqueue);
-	kfifo_free(conn->mgmtqueue);
-
-	iscsi_destroy_conn(cls_conn);
+		free_pages((unsigned long)tcp_conn->data,
+			   get_order(tcp_conn->data_size));
+	kfree(tcp_conn);
 }
 
 static int
-iscsi_conn_bind(struct iscsi_cls_session *cls_session,
-		struct iscsi_cls_conn *cls_conn, uint32_t transport_fd,
-		int is_leading)
+iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
+		    struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
+		    int is_leading)
 {
-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
-	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	struct sock *sk;
 	struct socket *sock;
 	int err;
 
 	/* lookup for existing socket */
-	sock = sockfd_lookup(transport_fd, &err);
+	sock = sockfd_lookup((int)transport_eph, &err);
 	if (!sock) {
 		printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err);
 		return -EEXIST;
 	}
 
-	/* lookup for existing connection */
-	spin_lock_bh(&session->lock);
-	list_for_each_entry(tmp, &session->connections, item) {
-		if (tmp == conn) {
-			if (conn->c_stage != ISCSI_CONN_STOPPED ||
-			    conn->stop_stage == STOP_CONN_TERM) {
-				printk(KERN_ERR "iscsi_tcp: can't bind "
-				       "non-stopped connection (%d:%d)\n",
-				       conn->c_stage, conn->stop_stage);
-				spin_unlock_bh(&session->lock);
-				return -EIO;
-			}
-			break;
-		}
-	}
-	if (tmp != conn) {
-		/* bind new iSCSI connection to session */
-		conn->session = session;
+	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
+	if (err)
+		return err;
 
-		list_add(&conn->item, &session->connections);
-	}
-	spin_unlock_bh(&session->lock);
+	/* bind iSCSI connection and socket */
+	tcp_conn->sock = sock;
 
-	if (conn->stop_stage != STOP_CONN_SUSPEND) {
-		/* bind iSCSI connection and socket */
-		conn->sock = sock;
+	/* setup Socket parameters */
+	sk = sock->sk;
+	sk->sk_reuse = 1;
+	sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
+	sk->sk_allocation = GFP_ATOMIC;
 
-		/* setup Socket parameters */
-		sk = sock->sk;
-		sk->sk_reuse = 1;
-		sk->sk_sndtimeo = 15 * HZ; /* FIXME: make it configurable */
-		sk->sk_allocation = GFP_ATOMIC;
-
-		/* FIXME: disable Nagle's algorithm */
-
-		/*
-		 * Intercept TCP callbacks for sendfile like receive
-		 * processing.
-		 */
-		iscsi_conn_set_callbacks(conn);
-
-		conn->sendpage = conn->sock->ops->sendpage;
-
-		/*
-		 * set receive state machine into initial state
-		 */
-		conn->in_progress = IN_PROGRESS_WAIT_HEADER;
-	}
-
-	if (is_leading)
-		session->leadconn = conn;
+	/* FIXME: disable Nagle's algorithm */
 
 	/*
-	 * Unblock xmitworker(), Login Phase will pass through.
+	 * Intercept TCP callbacks for sendfile like receive
+	 * processing.
 	 */
-	clear_bit(SUSPEND_BIT, &conn->suspend_rx);
-	clear_bit(SUSPEND_BIT, &conn->suspend_tx);
-
-	return 0;
-}
-
-static int
-iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
-{
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_session *session = conn->session;
-	struct sock *sk;
-
-	/* FF phase warming up... */
-
-	if (session == NULL) {
-		printk(KERN_ERR "iscsi_tcp: can't start unbound connection\n");
-		return -EPERM;
-	}
-
-	sk = conn->sock->sk;
-
-	write_lock_bh(&sk->sk_callback_lock);
-	spin_lock_bh(&session->lock);
-	conn->c_stage = ISCSI_CONN_STARTED;
-	session->state = ISCSI_STATE_LOGGED_IN;
-
-	switch(conn->stop_stage) {
-	case STOP_CONN_RECOVER:
-		/*
-		 * unblock eh_abort() if it is blocked. re-try all
-		 * commands after successful recovery
-		 */
-		session->conn_cnt++;
-		conn->stop_stage = 0;
-		conn->tmabort_state = TMABORT_INITIAL;
-		session->age++;
-		wake_up(&conn->ehwait);
-		break;
-	case STOP_CONN_TERM:
-		session->conn_cnt++;
-		conn->stop_stage = 0;
-		break;
-	case STOP_CONN_SUSPEND:
-		conn->stop_stage = 0;
-		clear_bit(SUSPEND_BIT, &conn->suspend_rx);
-		clear_bit(SUSPEND_BIT, &conn->suspend_tx);
-		break;
-	default:
-		break;
-	}
-	spin_unlock_bh(&session->lock);
-	write_unlock_bh(&sk->sk_callback_lock);
+	conn->recv_lock = &sk->sk_callback_lock;
+	iscsi_conn_set_callbacks(conn);
+	tcp_conn->sendpage = tcp_conn->sock->ops->sendpage;
+	/*
+	 * set receive state machine into initial state
+	 */
+	tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
 
 	return 0;
 }
 
 static void
-iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
 {
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct iscsi_session *session = conn->session;
-	struct sock *sk;
-	unsigned long flags;
+	struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+	struct iscsi_r2t_info *r2t;
 
-	BUG_ON(!conn->sock);
-	sk = conn->sock->sk;
-	write_lock_bh(&sk->sk_callback_lock);
-	set_bit(SUSPEND_BIT, &conn->suspend_rx);
-	write_unlock_bh(&sk->sk_callback_lock);
+	/* flush ctask's r2t queues */
+	while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)))
+		__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
+			    sizeof(void*));
 
-	mutex_lock(&conn->xmitmutex);
-
-	spin_lock_irqsave(session->host->host_lock, flags);
-	spin_lock(&session->lock);
-	conn->stop_stage = flag;
-	conn->c_stage = ISCSI_CONN_STOPPED;
-	set_bit(SUSPEND_BIT, &conn->suspend_tx);
-
-	if (flag != STOP_CONN_SUSPEND)
-		session->conn_cnt--;
-
-	if (session->conn_cnt == 0 || session->leadconn == conn)
-		session->state = ISCSI_STATE_FAILED;
-
-	spin_unlock(&session->lock);
-	spin_unlock_irqrestore(session->host->host_lock, flags);
-
-	if (flag == STOP_CONN_TERM || flag == STOP_CONN_RECOVER) {
-		struct iscsi_cmd_task *ctask;
-		struct iscsi_mgmt_task *mtask;
-
-		/*
-		 * Socket must go now.
-		 */
-		sock_hold(conn->sock->sk);
-		iscsi_conn_restore_callbacks(conn);
-		sock_put(conn->sock->sk);
-
-		/*
-		 * flush xmit queues.
-		 */
-		spin_lock_bh(&session->lock);
-		while (__kfifo_get(conn->writequeue, (void*)&ctask,
-			    sizeof(void*)) ||
-			__kfifo_get(conn->xmitqueue, (void*)&ctask,
-			    sizeof(void*))) {
-			struct iscsi_r2t_info *r2t;
-
-			/*
-			 * flush ctask's r2t queues
-			 */
-			while (__kfifo_get(ctask->r2tqueue, (void*)&r2t,
-				sizeof(void*)))
-				__kfifo_put(ctask->r2tpool.queue, (void*)&r2t,
-					    sizeof(void*));
-
-			spin_unlock_bh(&session->lock);
-			local_bh_disable();
-			iscsi_ctask_cleanup(conn, ctask);
-			local_bh_enable();
-			spin_lock_bh(&session->lock);
-		}
-		conn->ctask = NULL;
-		while (__kfifo_get(conn->immqueue, (void*)&mtask,
-			   sizeof(void*)) ||
-			__kfifo_get(conn->mgmtqueue, (void*)&mtask,
-			   sizeof(void*))) {
-			__kfifo_put(session->mgmtpool.queue,
-				    (void*)&mtask, sizeof(void*));
-		}
-		conn->mtask = NULL;
-		spin_unlock_bh(&session->lock);
-
-		/*
-		 * release socket only after we stopped data_xmit()
-		 * activity and flushed all outstandings
-		 */
-		sock_release(conn->sock);
-		conn->sock = NULL;
-
-		/*
-		 * for connection level recovery we should not calculate
-		 * header digest. conn->hdr_size used for optimization
-		 * in hdr_extract() and will be re-negotiated at
-		 * set_param() time.
-		 */
-		if (flag == STOP_CONN_RECOVER) {
-			conn->hdr_size = sizeof(struct iscsi_hdr);
-			conn->hdrdgst_en = 0;
-			conn->datadgst_en = 0;
-		}
-	}
-	mutex_unlock(&conn->xmitmutex);
+	__iscsi_ctask_cleanup(conn, ctask);
 }
 
-static int
-iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
-			char *data, uint32_t data_size)
+static void
+iscsi_tcp_suspend_conn_rx(struct iscsi_conn *conn)
 {
-	struct iscsi_session *session = conn->session;
-	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
-	struct iscsi_mgmt_task *mtask;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct sock *sk;
 
-	spin_lock_bh(&session->lock);
-	if (session->state == ISCSI_STATE_TERMINATE) {
-		spin_unlock_bh(&session->lock);
-		return -EPERM;
-	}
-	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
-	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
-		/*
-		 * Login and Text are sent serially, in
-		 * request-followed-by-response sequence.
-		 * Same mtask can be used. Same ITT must be used.
-		 * Note that login_mtask is preallocated at conn_create().
-		 */
-		mtask = conn->login_mtask;
-	else {
-	        BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
-	        BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+	if (!tcp_conn->sock)
+		return;
 
-		if (!__kfifo_get(session->mgmtpool.queue,
-				 (void*)&mtask, sizeof(void*))) {
-			spin_unlock_bh(&session->lock);
-			return -ENOSPC;
-		}
-	}
+	sk = tcp_conn->sock->sk;
+	write_lock_bh(&sk->sk_callback_lock);
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+	write_unlock_bh(&sk->sk_callback_lock);
+}
 
-	/*
-	 * pre-format CmdSN and ExpStatSN for outgoing PDU.
-	 */
-	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
-		hdr->itt = mtask->itt | (conn->id << CID_SHIFT) |
-			   (session->age << AGE_SHIFT);
-		nop->cmdsn = cpu_to_be32(session->cmdsn);
-		if (conn->c_stage == ISCSI_CONN_STARTED &&
-		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
-			session->cmdsn++;
-	} else
-		/* do not advance CmdSN */
-		nop->cmdsn = cpu_to_be32(session->cmdsn);
+static void
+iscsi_tcp_terminate_conn(struct iscsi_conn *conn)
+{
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 
-	nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+	if (!tcp_conn->sock)
+		return;
 
-	memcpy(&mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+	sock_hold(tcp_conn->sock->sk);
+	iscsi_conn_restore_callbacks(conn);
+	sock_put(tcp_conn->sock->sk);
 
-	iscsi_buf_init_virt(&mtask->headbuf, (char*)&mtask->hdr,
-				    sizeof(struct iscsi_hdr));
+	sock_release(tcp_conn->sock);
+	tcp_conn->sock = NULL;
+	conn->recv_lock = NULL;
+}
 
-	spin_unlock_bh(&session->lock);
+/* called with host lock */
+static void
+iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
+		    char *data, uint32_t data_size)
+{
+	struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
 
-	if (data_size) {
-		memcpy(mtask->data, data, data_size);
-		mtask->data_count = data_size;
-	} else
-		mtask->data_count = 0;
+	iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
+			   sizeof(struct iscsi_hdr));
+	tcp_mtask->xmstate = XMSTATE_IMM_HDR;
 
-	mtask->xmstate = XMSTATE_IMM_HDR;
-
-	if (mtask->data_count) {
-		iscsi_buf_init_iov(&mtask->sendbuf, (char*)mtask->data,
+	if (mtask->data_count)
+		iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
 				    mtask->data_count);
-	}
-
-	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
-		   hdr->opcode, hdr->itt, data_size);
-
-	/*
-	 * since send_pdu() could be called at least from two contexts,
-	 * we need to serialize __kfifo_put, so we don't have to take
-	 * additional lock on fast data-path
-	 */
-        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
-	        __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
-	else
-	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
-
-	scsi_queue_work(session->host, &conn->xmitwork);
-	return 0;
-}
-
-static int
-iscsi_eh_host_reset(struct scsi_cmnd *sc)
-{
-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
-	struct iscsi_conn *conn = ctask->conn;
-	struct iscsi_session *session = conn->session;
-
-	spin_lock_bh(&session->lock);
-	if (session->state == ISCSI_STATE_TERMINATE) {
-		debug_scsi("failing host reset: session terminated "
-			   "[CID %d age %d]", conn->id, session->age);
-		spin_unlock_bh(&session->lock);
-		return FAILED;
-	}
-	spin_unlock_bh(&session->lock);
-
-	debug_scsi("failing connection CID %d due to SCSI host reset "
-		   "[itt 0x%x age %d]", conn->id, ctask->itt,
-		   session->age);
-	iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-
-	return SUCCESS;
-}
-
-static void
-iscsi_tmabort_timedout(unsigned long data)
-{
-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data;
-	struct iscsi_conn *conn = ctask->conn;
-	struct iscsi_session *session = conn->session;
-
-	spin_lock(&session->lock);
-	if (conn->tmabort_state == TMABORT_INITIAL) {
-		__kfifo_put(session->mgmtpool.queue,
-				(void*)&ctask->mtask, sizeof(void*));
-		conn->tmabort_state = TMABORT_TIMEDOUT;
-		debug_scsi("tmabort timedout [sc %lx itt 0x%x]\n",
-			(long)ctask->sc, ctask->itt);
-		/* unblock eh_abort() */
-		wake_up(&conn->ehwait);
-	}
-	spin_unlock(&session->lock);
-}
-
-static int
-iscsi_eh_abort(struct scsi_cmnd *sc)
-{
-	int rc;
-	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
-	struct iscsi_conn *conn = ctask->conn;
-	struct iscsi_session *session = conn->session;
-
-	conn->eh_abort_cnt++;
-	debug_scsi("aborting [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
-
-	/*
-	 * two cases for ERL=0 here:
-	 *
-	 * 1) connection-level failure;
-	 * 2) recovery due protocol error;
-	 */
-	mutex_lock(&conn->xmitmutex);
-	spin_lock_bh(&session->lock);
-	if (session->state != ISCSI_STATE_LOGGED_IN) {
-		if (session->state == ISCSI_STATE_TERMINATE) {
-			spin_unlock_bh(&session->lock);
-			mutex_unlock(&conn->xmitmutex);
-			goto failed;
-		}
-		spin_unlock_bh(&session->lock);
-	} else {
-		struct iscsi_tm *hdr = &conn->tmhdr;
-
-		/*
-		 * Still LOGGED_IN...
-		 */
-
-		if (!ctask->sc || sc->SCp.phase != session->age) {
-			/*
-			 * 1) ctask completed before time out. But session
-			 *    is still ok => Happy Retry.
-			 * 2) session was re-open during time out of ctask.
-			 */
-			spin_unlock_bh(&session->lock);
-			mutex_unlock(&conn->xmitmutex);
-			goto success;
-		}
-		conn->tmabort_state = TMABORT_INITIAL;
-		spin_unlock_bh(&session->lock);
-
-		/*
-		 * ctask timed out but session is OK
-		 * ERL=0 requires task mgmt abort to be issued on each
-		 * failed command. requests must be serialized.
-		 */
-		memset(hdr, 0, sizeof(struct iscsi_tm));
-		hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
-		hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
-		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
-		memcpy(hdr->lun, ctask->hdr.lun, sizeof(hdr->lun));
-		hdr->rtt = ctask->hdr.itt;
-		hdr->refcmdsn = ctask->hdr.cmdsn;
-
-		rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
-					     NULL, 0);
-		if (rc) {
-			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-			debug_scsi("abort sent failure [itt 0x%x]", ctask->itt);
-		} else {
-			struct iscsi_r2t_info *r2t;
-
-			/*
-			 * TMF abort vs. TMF response race logic
-			 */
-			spin_lock_bh(&session->lock);
-			ctask->mtask = (struct iscsi_mgmt_task *)
-				session->mgmt_cmds[(hdr->itt & ITT_MASK) -
-							ISCSI_MGMT_ITT_OFFSET];
-			/*
-			 * have to flush r2tqueue to avoid r2t leaks
-			 */
-			while (__kfifo_get(ctask->r2tqueue, (void*)&r2t,
-				sizeof(void*))) {
-				__kfifo_put(ctask->r2tpool.queue, (void*)&r2t,
-					sizeof(void*));
-			}
-			if (conn->tmabort_state == TMABORT_INITIAL) {
-				conn->tmfcmd_pdus_cnt++;
-				conn->tmabort_timer.expires = 3*HZ + jiffies;
-				conn->tmabort_timer.function =
-						iscsi_tmabort_timedout;
-				conn->tmabort_timer.data = (unsigned long)ctask;
-				add_timer(&conn->tmabort_timer);
-				debug_scsi("abort sent [itt 0x%x]", ctask->itt);
-			} else {
-				if (!ctask->sc ||
-				    conn->tmabort_state == TMABORT_SUCCESS) {
-					conn->tmabort_state = TMABORT_INITIAL;
-					spin_unlock_bh(&session->lock);
-					mutex_unlock(&conn->xmitmutex);
-					goto success;
-				}
-				conn->tmabort_state = TMABORT_INITIAL;
-				iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-			}
-			spin_unlock_bh(&session->lock);
-		}
-	}
-	mutex_unlock(&conn->xmitmutex);
-
-
-	/*
-	 * block eh thread until:
-	 *
-	 * 1) abort response;
-	 * 2) abort timeout;
-	 * 3) session re-opened;
-	 * 4) session terminated;
-	 */
-	for (;;) {
-		int p_state = session->state;
-
-		rc = wait_event_interruptible(conn->ehwait,
-			(p_state == ISCSI_STATE_LOGGED_IN ?
-			 (session->state == ISCSI_STATE_TERMINATE ||
-			  conn->tmabort_state != TMABORT_INITIAL) :
-			 (session->state == ISCSI_STATE_TERMINATE ||
-			  session->state == ISCSI_STATE_LOGGED_IN)));
-		if (rc) {
-			/* shutdown.. */
-			session->state = ISCSI_STATE_TERMINATE;
-			goto failed;
-		}
-
-		if (signal_pending(current))
-			flush_signals(current);
-
-		if (session->state == ISCSI_STATE_TERMINATE)
-			goto failed;
-
-		spin_lock_bh(&session->lock);
-		if (sc->SCp.phase == session->age &&
-		   (conn->tmabort_state == TMABORT_TIMEDOUT ||
-		    conn->tmabort_state == TMABORT_FAILED)) {
-			conn->tmabort_state = TMABORT_INITIAL;
-			if (!ctask->sc) {
-				/*
-				 * ctask completed before tmf abort response or
-				 * time out.
-				 * But session is still ok => Happy Retry.
-				 */
-				spin_unlock_bh(&session->lock);
-				break;
-			}
-			spin_unlock_bh(&session->lock);
-			iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
-			continue;
-		}
-		spin_unlock_bh(&session->lock);
-		break;
-	}
-
-success:
-	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
-	rc = SUCCESS;
-	goto exit;
-
-failed:
-	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
-	rc = FAILED;
-
-exit:
-	del_timer_sync(&conn->tmabort_timer);
-
-	mutex_lock(&conn->xmitmutex);
-	if (conn->sock) {
-		struct sock *sk = conn->sock->sk;
-
-		write_lock_bh(&sk->sk_callback_lock);
-		iscsi_ctask_cleanup(conn, ctask);
-		write_unlock_bh(&sk->sk_callback_lock);
-	}
-	mutex_unlock(&conn->xmitmutex);
-	return rc;
 }
 
 static int
@@ -3174,6 +2074,7 @@
 	 */
 	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
 	        struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
 
 		/*
 		 * pre-allocated x4 as much r2ts to handle race when
@@ -3182,42 +2083,32 @@
 		 */
 
 		/* R2T pool */
-		if (iscsi_pool_init(&ctask->r2tpool, session->max_r2t * 4,
-			(void***)&ctask->r2ts, sizeof(struct iscsi_r2t_info))) {
+		if (iscsi_pool_init(&tcp_ctask->r2tpool, session->max_r2t * 4,
+				    (void***)&tcp_ctask->r2ts,
+				    sizeof(struct iscsi_r2t_info))) {
 			goto r2t_alloc_fail;
 		}
 
 		/* R2T xmit queue */
-		ctask->r2tqueue = kfifo_alloc(
+		tcp_ctask->r2tqueue = kfifo_alloc(
 		      session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL);
-		if (ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
-			iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts);
+		if (tcp_ctask->r2tqueue == ERR_PTR(-ENOMEM)) {
+			iscsi_pool_free(&tcp_ctask->r2tpool,
+					(void**)tcp_ctask->r2ts);
 			goto r2t_alloc_fail;
 		}
-
-		/*
-		 * number of
-		 * Data-Out PDU's within R2T-sequence can be quite big;
-		 * using mempool
-		 */
-		ctask->datapool = mempool_create_slab_pool(ISCSI_DTASK_DEFAULT_MAX,
-							   taskcache);
-		if (ctask->datapool == NULL) {
-			kfifo_free(ctask->r2tqueue);
-			iscsi_pool_free(&ctask->r2tpool, (void**)ctask->r2ts);
-			goto r2t_alloc_fail;
-		}
-		INIT_LIST_HEAD(&ctask->dataqueue);
 	}
 
 	return 0;
 
 r2t_alloc_fail:
 	for (i = 0; i < cmd_i; i++) {
-		mempool_destroy(session->cmds[i]->datapool);
-		kfifo_free(session->cmds[i]->r2tqueue);
-		iscsi_pool_free(&session->cmds[i]->r2tpool,
-				(void**)session->cmds[i]->r2ts);
+		struct iscsi_cmd_task *ctask = session->cmds[i];
+		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+
+		kfifo_free(tcp_ctask->r2tqueue);
+		iscsi_pool_free(&tcp_ctask->r2tpool,
+				(void**)tcp_ctask->r2ts);
 	}
 	return -ENOMEM;
 }
@@ -3228,152 +2119,29 @@
 	int i;
 
 	for (i = 0; i < session->cmds_max; i++) {
-		mempool_destroy(session->cmds[i]->datapool);
-		kfifo_free(session->cmds[i]->r2tqueue);
-		iscsi_pool_free(&session->cmds[i]->r2tpool,
-				(void**)session->cmds[i]->r2ts);
+		struct iscsi_cmd_task *ctask = session->cmds[i];
+		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+
+		kfifo_free(tcp_ctask->r2tqueue);
+		iscsi_pool_free(&tcp_ctask->r2tpool,
+				(void**)tcp_ctask->r2ts);
 	}
 }
 
-static struct scsi_host_template iscsi_sht = {
-	.name			= "iSCSI Initiator over TCP/IP, v."
-				  ISCSI_VERSION_STR,
-	.queuecommand           = iscsi_queuecommand,
-	.change_queue_depth	= iscsi_change_queue_depth,
-	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
-	.sg_tablesize		= ISCSI_SG_TABLESIZE,
-	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
-	.eh_abort_handler       = iscsi_eh_abort,
-	.eh_host_reset_handler	= iscsi_eh_host_reset,
-	.use_clustering         = DISABLE_CLUSTERING,
-	.proc_name		= "iscsi_tcp",
-	.this_id		= -1,
-};
-
-static struct iscsi_transport iscsi_tcp_transport;
-
-static struct iscsi_cls_session *
-iscsi_session_create(struct scsi_transport_template *scsit,
-		     uint32_t initial_cmdsn, uint32_t *sid)
-{
-	struct Scsi_Host *shost;
-	struct iscsi_session *session;
-	int cmd_i;
-
-	shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport);
-	if (!shost)
-		return NULL; 
-
-	session = iscsi_hostdata(shost->hostdata);
-	memset(session, 0, sizeof(struct iscsi_session));
-	session->host = shost;
-	session->state = ISCSI_STATE_FREE;
-	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
-	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
-	session->cmdsn = initial_cmdsn;
-	session->exp_cmdsn = initial_cmdsn + 1;
-	session->max_cmdsn = initial_cmdsn + 1;
-	session->max_r2t = 1;
-	*sid = shost->host_no;
-
-	/* initialize SCSI PDU commands pool */
-	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
-		(void***)&session->cmds, sizeof(struct iscsi_cmd_task)))
-		goto cmdpool_alloc_fail;
-
-	/* pre-format cmds pool with ITT */
-	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++)
-		session->cmds[cmd_i]->itt = cmd_i;
-
-	spin_lock_init(&session->lock);
-	INIT_LIST_HEAD(&session->connections);
-
-	/* initialize immediate command pool */
-	if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
-		(void***)&session->mgmt_cmds, sizeof(struct iscsi_mgmt_task)))
-		goto mgmtpool_alloc_fail;
-
-
-	/* pre-format immediate cmds pool with ITT */
-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
-		session->mgmt_cmds[cmd_i]->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
-		session->mgmt_cmds[cmd_i]->data = kmalloc(
-			DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
-		if (!session->mgmt_cmds[cmd_i]->data) {
-			int j;
-
-			for (j = 0; j < cmd_i; j++)
-				kfree(session->mgmt_cmds[j]->data);
-			goto immdata_alloc_fail;
-		}
-	}
-
-	if (iscsi_r2tpool_alloc(session))
-		goto r2tpool_alloc_fail;
-
-	return hostdata_session(shost->hostdata);
-
-r2tpool_alloc_fail:
-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
-		kfree(session->mgmt_cmds[cmd_i]->data);
-immdata_alloc_fail:
-	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
-mgmtpool_alloc_fail:
-	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
-cmdpool_alloc_fail:
-	iscsi_transport_destroy_session(shost);
-	return NULL;
-}
-
-static void
-iscsi_session_destroy(struct iscsi_cls_session *cls_session)
-{
-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
-	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
-	int cmd_i;
-	struct iscsi_data_task *dtask, *n;
-
-	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
-		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
-		list_for_each_entry_safe(dtask, n, &ctask->dataqueue, item) {
-			list_del(&dtask->item);
-			mempool_free(dtask, ctask->datapool);
-		}
-	}
-
-	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++)
-		kfree(session->mgmt_cmds[cmd_i]->data);
-
-	iscsi_r2tpool_free(session);
-	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
-	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
-
-	iscsi_transport_destroy_session(shost);
-}
-
 static int
 iscsi_conn_set_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param,
 		     uint32_t value)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
 	struct iscsi_session *session = conn->session;
-
-	spin_lock_bh(&session->lock);
-	if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
-	    conn->stop_stage != STOP_CONN_RECOVER) {
-		printk(KERN_ERR "iscsi_tcp: can not change parameter [%d]\n",
-		       param);
-		spin_unlock_bh(&session->lock);
-		return 0;
-	}
-	spin_unlock_bh(&session->lock);
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 
 	switch(param) {
 	case ISCSI_PARAM_MAX_RECV_DLENGTH: {
-		char *saveptr = conn->data;
+		char *saveptr = tcp_conn->data;
 		gfp_t flags = GFP_KERNEL;
 
-		if (conn->data_size >= value) {
+		if (tcp_conn->data_size >= value) {
 			conn->max_recv_dlength = value;
 			break;
 		}
@@ -3384,21 +2152,21 @@
 		spin_unlock_bh(&session->lock);
 
 		if (value <= PAGE_SIZE)
-			conn->data = kmalloc(value, flags);
+			tcp_conn->data = kmalloc(value, flags);
 		else
-			conn->data = (void*)__get_free_pages(flags,
+			tcp_conn->data = (void*)__get_free_pages(flags,
 							     get_order(value));
-		if (conn->data == NULL) {
-			conn->data = saveptr;
+		if (tcp_conn->data == NULL) {
+			tcp_conn->data = saveptr;
 			return -ENOMEM;
 		}
-		if (conn->data_size <= PAGE_SIZE)
+		if (tcp_conn->data_size <= PAGE_SIZE)
 			kfree(saveptr);
 		else
 			free_pages((unsigned long)saveptr,
-				   get_order(conn->data_size));
+				   get_order(tcp_conn->data_size));
 		conn->max_recv_dlength = value;
-		conn->data_size = value;
+		tcp_conn->data_size = value;
 		}
 		break;
 	case ISCSI_PARAM_MAX_XMIT_DLENGTH:
@@ -3406,49 +2174,51 @@
 		break;
 	case ISCSI_PARAM_HDRDGST_EN:
 		conn->hdrdgst_en = value;
-		conn->hdr_size = sizeof(struct iscsi_hdr);
+		tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
 		if (conn->hdrdgst_en) {
-			conn->hdr_size += sizeof(__u32);
-			if (!conn->tx_tfm)
-				conn->tx_tfm = crypto_alloc_tfm("crc32c", 0);
-			if (!conn->tx_tfm)
+			tcp_conn->hdr_size += sizeof(__u32);
+			if (!tcp_conn->tx_tfm)
+				tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c",
+								    0);
+			if (!tcp_conn->tx_tfm)
 				return -ENOMEM;
-			if (!conn->rx_tfm)
-				conn->rx_tfm = crypto_alloc_tfm("crc32c", 0);
-			if (!conn->rx_tfm) {
-				crypto_free_tfm(conn->tx_tfm);
+			if (!tcp_conn->rx_tfm)
+				tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c",
+								    0);
+			if (!tcp_conn->rx_tfm) {
+				crypto_free_tfm(tcp_conn->tx_tfm);
 				return -ENOMEM;
 			}
 		} else {
-			if (conn->tx_tfm)
-				crypto_free_tfm(conn->tx_tfm);
-			if (conn->rx_tfm)
-				crypto_free_tfm(conn->rx_tfm);
+			if (tcp_conn->tx_tfm)
+				crypto_free_tfm(tcp_conn->tx_tfm);
+			if (tcp_conn->rx_tfm)
+				crypto_free_tfm(tcp_conn->rx_tfm);
 		}
 		break;
 	case ISCSI_PARAM_DATADGST_EN:
 		conn->datadgst_en = value;
 		if (conn->datadgst_en) {
-			if (!conn->data_tx_tfm)
-				conn->data_tx_tfm =
+			if (!tcp_conn->data_tx_tfm)
+				tcp_conn->data_tx_tfm =
 				    crypto_alloc_tfm("crc32c", 0);
-			if (!conn->data_tx_tfm)
+			if (!tcp_conn->data_tx_tfm)
 				return -ENOMEM;
-			if (!conn->data_rx_tfm)
-				conn->data_rx_tfm =
+			if (!tcp_conn->data_rx_tfm)
+				tcp_conn->data_rx_tfm =
 				    crypto_alloc_tfm("crc32c", 0);
-			if (!conn->data_rx_tfm) {
-				crypto_free_tfm(conn->data_tx_tfm);
+			if (!tcp_conn->data_rx_tfm) {
+				crypto_free_tfm(tcp_conn->data_tx_tfm);
 				return -ENOMEM;
 			}
 		} else {
-			if (conn->data_tx_tfm)
-				crypto_free_tfm(conn->data_tx_tfm);
-			if (conn->data_rx_tfm)
-				crypto_free_tfm(conn->data_rx_tfm);
+			if (tcp_conn->data_tx_tfm)
+				crypto_free_tfm(tcp_conn->data_tx_tfm);
+			if (tcp_conn->data_rx_tfm)
+				crypto_free_tfm(tcp_conn->data_rx_tfm);
 		}
-		conn->sendpage = conn->datadgst_en ?
-			sock_no_sendpage : conn->sock->ops->sendpage;
+		tcp_conn->sendpage = conn->datadgst_en ?
+			sock_no_sendpage : tcp_conn->sock->ops->sendpage;
 		break;
 	case ISCSI_PARAM_INITIAL_R2T_EN:
 		session->initial_r2t_en = value;
@@ -3489,6 +2259,9 @@
 		BUG_ON(value);
 		session->ofmarker_en = value;
 		break;
+	case ISCSI_PARAM_EXP_STATSN:
+		conn->exp_statsn = value;
+		break;
 	default:
 		break;
 	}
@@ -3535,7 +2308,7 @@
 		*value = session->ofmarker_en;
 		break;
 	default:
-		return ISCSI_ERR_PARAM_NOT_FOUND;
+		return -EINVAL;
 	}
 
 	return 0;
@@ -3546,6 +2319,8 @@
 		     enum iscsi_param param, uint32_t *value)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct inet_sock *inet;
 
 	switch(param) {
 	case ISCSI_PARAM_MAX_RECV_DLENGTH:
@@ -3560,17 +2335,70 @@
 	case ISCSI_PARAM_DATADGST_EN:
 		*value = conn->datadgst_en;
 		break;
+	case ISCSI_PARAM_CONN_PORT:
+		mutex_lock(&conn->xmitmutex);
+		if (!tcp_conn->sock) {
+			mutex_unlock(&conn->xmitmutex);
+			return -EINVAL;
+		}
+
+		inet = inet_sk(tcp_conn->sock->sk);
+		*value = be16_to_cpu(inet->dport);
+		mutex_unlock(&conn->xmitmutex);
+	case ISCSI_PARAM_EXP_STATSN:
+		*value = conn->exp_statsn;
+		break;
 	default:
-		return ISCSI_ERR_PARAM_NOT_FOUND;
+		return -EINVAL;
 	}
 
 	return 0;
 }
 
+static int
+iscsi_conn_get_str_param(struct iscsi_cls_conn *cls_conn,
+			 enum iscsi_param param, char *buf)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct sock *sk;
+	struct inet_sock *inet;
+	struct ipv6_pinfo *np;
+	int len = 0;
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_ADDRESS:
+		mutex_lock(&conn->xmitmutex);
+		if (!tcp_conn->sock) {
+			mutex_unlock(&conn->xmitmutex);
+			return -EINVAL;
+		}
+
+		sk = tcp_conn->sock->sk;
+		if (sk->sk_family == PF_INET) {
+			inet = inet_sk(sk);
+			len = sprintf(buf, "%u.%u.%u.%u\n",
+				      NIPQUAD(inet->daddr));
+		} else {
+			np = inet6_sk(sk);
+			len = sprintf(buf,
+				"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+				NIP6(np->daddr));
+		}
+		mutex_unlock(&conn->xmitmutex);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return len;
+}
+
 static void
 iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 
 	stats->txdata_octets = conn->txdata_octets;
 	stats->rxdata_octets = conn->rxdata_octets;
@@ -3583,68 +2411,141 @@
 	stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
 	stats->custom_length = 3;
 	strcpy(stats->custom[0].desc, "tx_sendpage_failures");
-	stats->custom[0].value = conn->sendpage_failures_cnt;
+	stats->custom[0].value = tcp_conn->sendpage_failures_cnt;
 	strcpy(stats->custom[1].desc, "rx_discontiguous_hdr");
-	stats->custom[1].value = conn->discontiguous_hdr_cnt;
+	stats->custom[1].value = tcp_conn->discontiguous_hdr_cnt;
 	strcpy(stats->custom[2].desc, "eh_abort_cnt");
 	stats->custom[2].value = conn->eh_abort_cnt;
 }
 
-static int
-iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
-		    char *data, uint32_t data_size)
+static struct iscsi_cls_session *
+iscsi_tcp_session_create(struct iscsi_transport *iscsit,
+			 struct scsi_transport_template *scsit,
+			 uint32_t initial_cmdsn, uint32_t *hostno)
 {
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	int rc;
+	struct iscsi_cls_session *cls_session;
+	struct iscsi_session *session;
+	uint32_t hn;
+	int cmd_i;
 
-	mutex_lock(&conn->xmitmutex);
-	rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
-	mutex_unlock(&conn->xmitmutex);
+	cls_session = iscsi_session_setup(iscsit, scsit,
+					 sizeof(struct iscsi_tcp_cmd_task),
+					 sizeof(struct iscsi_tcp_mgmt_task),
+					 initial_cmdsn, &hn);
+	if (!cls_session)
+		return NULL;
+	*hostno = hn;
 
-	return rc;
+	session = class_to_transport_session(cls_session);
+	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+		struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+
+		ctask->hdr = &tcp_ctask->hdr;
+	}
+
+	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
+		struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];
+		struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
+
+		mtask->hdr = &tcp_mtask->hdr;
+	}
+
+	if (iscsi_r2tpool_alloc(class_to_transport_session(cls_session)))
+		goto r2tpool_alloc_fail;
+
+	return cls_session;
+
+r2tpool_alloc_fail:
+	iscsi_session_teardown(cls_session);
+	return NULL;
 }
 
+static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
+{
+	iscsi_r2tpool_free(class_to_transport_session(cls_session));
+	iscsi_session_teardown(cls_session);
+}
+
+static struct scsi_host_template iscsi_sht = {
+	.name			= "iSCSI Initiator over TCP/IP, v"
+				  ISCSI_TCP_VERSION,
+	.queuecommand           = iscsi_queuecommand,
+	.change_queue_depth	= iscsi_change_queue_depth,
+	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+	.eh_abort_handler       = iscsi_eh_abort,
+	.eh_host_reset_handler	= iscsi_eh_host_reset,
+	.use_clustering         = DISABLE_CLUSTERING,
+	.proc_name		= "iscsi_tcp",
+	.this_id		= -1,
+};
+
 static struct iscsi_transport iscsi_tcp_transport = {
 	.owner			= THIS_MODULE,
 	.name			= "tcp",
 	.caps			= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
 				  | CAP_DATADGST,
+	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
+				  ISCSI_MAX_XMIT_DLENGTH |
+				  ISCSI_HDRDGST_EN |
+				  ISCSI_DATADGST_EN |
+				  ISCSI_INITIAL_R2T_EN |
+				  ISCSI_MAX_R2T |
+				  ISCSI_IMM_DATA_EN |
+				  ISCSI_FIRST_BURST |
+				  ISCSI_MAX_BURST |
+				  ISCSI_PDU_INORDER_EN |
+				  ISCSI_DATASEQ_INORDER_EN |
+				  ISCSI_ERL |
+				  ISCSI_CONN_PORT |
+				  ISCSI_CONN_ADDRESS |
+				  ISCSI_EXP_STATSN,
 	.host_template		= &iscsi_sht,
-	.hostdata_size		= sizeof(struct iscsi_session),
 	.conndata_size		= sizeof(struct iscsi_conn),
 	.max_conn		= 1,
 	.max_cmd_len		= ISCSI_TCP_MAX_CMD_LEN,
-	.create_session		= iscsi_session_create,
-	.destroy_session	= iscsi_session_destroy,
-	.create_conn		= iscsi_conn_create,
-	.bind_conn		= iscsi_conn_bind,
-	.destroy_conn		= iscsi_conn_destroy,
+	/* session management */
+	.create_session		= iscsi_tcp_session_create,
+	.destroy_session	= iscsi_tcp_session_destroy,
+	/* connection management */
+	.create_conn		= iscsi_tcp_conn_create,
+	.bind_conn		= iscsi_tcp_conn_bind,
+	.destroy_conn		= iscsi_tcp_conn_destroy,
 	.set_param		= iscsi_conn_set_param,
 	.get_conn_param		= iscsi_conn_get_param,
+	.get_conn_str_param	= iscsi_conn_get_str_param,
 	.get_session_param	= iscsi_session_get_param,
 	.start_conn		= iscsi_conn_start,
 	.stop_conn		= iscsi_conn_stop,
+	/* these are called as part of conn recovery */
+	.suspend_conn_recv	= iscsi_tcp_suspend_conn_rx,
+	.terminate_conn		= iscsi_tcp_terminate_conn,
+	/* IO */
 	.send_pdu		= iscsi_conn_send_pdu,
 	.get_stats		= iscsi_conn_get_stats,
+	.init_cmd_task		= iscsi_tcp_cmd_init,
+	.init_mgmt_task		= iscsi_tcp_mgmt_init,
+	.xmit_cmd_task		= iscsi_tcp_ctask_xmit,
+	.xmit_mgmt_task		= iscsi_tcp_mtask_xmit,
+	.cleanup_cmd_task	= iscsi_tcp_cleanup_ctask,
+	/* recovery */
+	.session_recovery_timedout = iscsi_session_recovery_timedout,
 };
 
 static int __init
 iscsi_tcp_init(void)
 {
 	if (iscsi_max_lun < 1) {
-		printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun);
+		printk(KERN_ERR "iscsi_tcp: Invalid max_lun value of %u\n",
+		       iscsi_max_lun);
 		return -EINVAL;
 	}
 	iscsi_tcp_transport.max_lun = iscsi_max_lun;
 
-	taskcache = kmem_cache_create("iscsi_taskcache",
-			sizeof(struct iscsi_data_task), 0,
-			SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (!taskcache)
-		return -ENOMEM;
-
 	if (!iscsi_register_transport(&iscsi_tcp_transport))
-		kmem_cache_destroy(taskcache);
+		return -ENODEV;
 
 	return 0;
 }
@@ -3653,7 +2554,6 @@
 iscsi_tcp_exit(void)
 {
 	iscsi_unregister_transport(&iscsi_tcp_transport);
-	kmem_cache_destroy(taskcache);
 }
 
 module_init(iscsi_tcp_init);
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h
index ba26741..8083028 100644
--- a/drivers/scsi/iscsi_tcp.h
+++ b/drivers/scsi/iscsi_tcp.h
@@ -2,7 +2,8 @@
  * iSCSI Initiator TCP Transport
  * Copyright (C) 2004 Dmitry Yusupov
  * Copyright (C) 2004 Alex Aizman
- * Copyright (C) 2005 Mike Christie
+ * Copyright (C) 2005 - 2006 Mike Christie
+ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
  * maintained by open-iscsi@googlegroups.com
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,20 +22,7 @@
 #ifndef ISCSI_TCP_H
 #define ISCSI_TCP_H
 
-/* Session's states */
-#define ISCSI_STATE_FREE		1
-#define ISCSI_STATE_LOGGED_IN		2
-#define ISCSI_STATE_FAILED		3
-#define ISCSI_STATE_TERMINATE		4
-
-/* Connection's states */
-#define ISCSI_CONN_INITIAL_STAGE	0
-#define ISCSI_CONN_STARTED		1
-#define ISCSI_CONN_STOPPED		2
-#define ISCSI_CONN_CLEANUP_WAIT		3
-
-/* Connection suspend "bit" */
-#define SUSPEND_BIT			1
+#include <scsi/libiscsi.h>
 
 /* Socket's Receive state machine */
 #define IN_PROGRESS_WAIT_HEADER		0x0
@@ -42,12 +30,6 @@
 #define IN_PROGRESS_DATA_RECV		0x2
 #define IN_PROGRESS_DDIGEST_RECV	0x3
 
-/* Task Mgmt states */
-#define	TMABORT_INITIAL			0x0
-#define	TMABORT_SUCCESS			0x1
-#define	TMABORT_FAILED			0x2
-#define	TMABORT_TIMEDOUT		0x3
-
 /* xmit state machine */
 #define	XMSTATE_IDLE			0x0
 #define	XMSTATE_R_HDR			0x1
@@ -62,34 +44,14 @@
 #define	XMSTATE_W_PAD			0x200
 #define XMSTATE_DATA_DIGEST		0x400
 
-#define ISCSI_CONN_MAX			1
 #define ISCSI_CONN_RCVBUF_MIN		262144
 #define ISCSI_CONN_SNDBUF_MIN		262144
 #define ISCSI_PAD_LEN			4
 #define ISCSI_R2T_MAX			16
-#define ISCSI_XMIT_CMDS_MAX		128	/* must be power of 2 */
-#define ISCSI_MGMT_CMDS_MAX		32	/* must be power of 2 */
-#define ISCSI_MGMT_ITT_OFFSET		0xa00
 #define ISCSI_SG_TABLESIZE		SG_ALL
-#define ISCSI_DEF_CMD_PER_LUN		32
-#define ISCSI_MAX_CMD_PER_LUN		128
 #define ISCSI_TCP_MAX_CMD_LEN		16
 
-#define ITT_MASK			(0xfff)
-#define CID_SHIFT			12
-#define CID_MASK			(0xffff<<CID_SHIFT)
-#define AGE_SHIFT			28
-#define AGE_MASK			(0xf<<AGE_SHIFT)
-
-struct iscsi_queue {
-	struct kfifo		*queue;		/* FIFO Queue */
-	void			**pool;		/* Pool of elements */
-	int			max;		/* Max number of elements */
-};
-
-struct iscsi_session;
-struct iscsi_cmd_task;
-struct iscsi_mgmt_task;
+struct socket;
 
 /* Socket connection recieve helper */
 struct iscsi_tcp_recv {
@@ -104,48 +66,32 @@
 	struct iscsi_cmd_task	*ctask;		/* current cmd in progress */
 
 	/* copied and flipped values */
-	int			opcode;
-	int			flags;
-	int			cmd_status;
-	int			ahslen;
 	int			datalen;
-	uint32_t		itt;
 	int			datadgst;
+	char			zero_copy_hdr;
 };
 
-struct iscsi_cls_conn;
-
-struct iscsi_conn {
-	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
+struct iscsi_tcp_conn {
+	struct iscsi_conn	*iscsi_conn;
+	struct socket		*sock;
 	struct iscsi_hdr	hdr;		/* header placeholder */
 	char			hdrext[4*sizeof(__u16) +
 				    sizeof(__u32)];
 	int			data_copied;
 	char			*data;		/* data placeholder */
-	struct socket           *sock;          /* TCP socket */
 	int			data_size;	/* actual recv_dlength */
 	int			stop_stage;	/* conn_stop() flag: *
 						 * stop to recover,  *
 						 * stop to terminate */
 	/* iSCSI connection-wide sequencing */
-	uint32_t		exp_statsn;
 	int			hdr_size;	/* PDU header size */
-	unsigned long		suspend_rx;	/* suspend Rx */
 
 	struct crypto_tfm	*rx_tfm;	/* CRC32C (Rx) */
 	struct crypto_tfm	*data_rx_tfm;	/* CRC32C (Rx) for data */
 
 	/* control data */
-	int			senselen;	/* scsi sense length */
-	int			id;		/* CID */
 	struct iscsi_tcp_recv	in;		/* TCP receive context */
-	struct iscsi_session	*session;	/* parent session */
-	struct list_head	item;		/* maintains list of conns */
 	int			in_progress;	/* connection state machine */
-	int			c_stage;	/* connection state */
-	struct iscsi_mgmt_task	*login_mtask;	/* mtask used for login/text */
-	struct iscsi_mgmt_task	*mtask;		/* xmit mtask in progress */
-	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
 
 	/* old values for socket callbacks */
 	void			(*old_data_ready)(struct sock *, int);
@@ -155,93 +101,14 @@
 	/* xmit */
 	struct crypto_tfm	*tx_tfm;	/* CRC32C (Tx) */
 	struct crypto_tfm	*data_tx_tfm;	/* CRC32C (Tx) for data */
-	struct kfifo		*writequeue;	/* write cmds for Data-Outs */
-	struct kfifo		*immqueue;	/* immediate xmit queue */
-	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
-	struct kfifo		*xmitqueue;	/* data-path cmd queue */
-	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
-	struct mutex		xmitmutex;	/* serializes connection xmit,
-						 * access to kfifos:	  *
-						 * xmitqueue, writequeue, *
-						 * immqueue, mgmtqueue    */
-	unsigned long		suspend_tx;	/* suspend Tx */
 
-	/* abort */
-	wait_queue_head_t	ehwait;		/* used in eh_abort()     */
-	struct iscsi_tm		tmhdr;
-	struct timer_list	tmabort_timer;  /* abort timer */
-	int			tmabort_state;  /* see TMABORT_INITIAL, etc.*/
-
-	/* negotiated params */
-	int			max_recv_dlength;
-	int			max_xmit_dlength;
-	int			hdrdgst_en;
-	int			datadgst_en;
-
-	/* MIB-statistics */
-	uint64_t		txdata_octets;
-	uint64_t		rxdata_octets;
-	uint32_t		scsicmd_pdus_cnt;
-	uint32_t		dataout_pdus_cnt;
-	uint32_t		scsirsp_pdus_cnt;
-	uint32_t		datain_pdus_cnt;
-	uint32_t		r2t_pdus_cnt;
-	uint32_t		tmfcmd_pdus_cnt;
-	int32_t			tmfrsp_pdus_cnt;
-
-	/* custom statistics */
+	/* MIB custom statistics */
 	uint32_t		sendpage_failures_cnt;
 	uint32_t		discontiguous_hdr_cnt;
-	uint32_t		eh_abort_cnt;
 
 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
 };
 
-struct iscsi_session {
-	/* iSCSI session-wide sequencing */
-	uint32_t		cmdsn;
-	uint32_t		exp_cmdsn;
-	uint32_t		max_cmdsn;
-
-	/* configuration */
-	int			initial_r2t_en;
-	int			max_r2t;
-	int			imm_data_en;
-	int			first_burst;
-	int			max_burst;
-	int			time2wait;
-	int			time2retain;
-	int			pdu_inorder_en;
-	int			dataseq_inorder_en;
-	int			erl;
-	int			ifmarker_en;
-	int			ofmarker_en;
-
-	/* control data */
-	struct Scsi_Host	*host;
-	int			id;
-	struct iscsi_conn	*leadconn;	/* leading connection */
-	spinlock_t		lock;		/* protects session state, *
-						 * sequence numbers,       *
-						 * session resources:      *
-						 * - cmdpool,		   *
-						 * - mgmtpool,		   *
-						 * - r2tpool		   */
-	int			state;		/* session state           */
-	struct list_head	item;
-	void			*auth_client;
-	int			conn_cnt;
-	int			age;		/* counts session re-opens */
-
-	struct list_head	connections;	/* list of connections */
-	int			cmds_max;	/* size of cmds array */
-	struct iscsi_cmd_task	**cmds;		/* Original Cmds arr */
-	struct iscsi_queue	cmdpool;	/* PDU's pool */
-	int			mgmtpool_max;	/* size of mgmt array */
-	struct iscsi_mgmt_task	**mgmt_cmds;	/* Original mgmt arr */
-	struct iscsi_queue	mgmtpool;	/* Mgmt PDU's pool */
-};
-
 struct iscsi_buf {
 	struct scatterlist	sg;
 	unsigned int		sent;
@@ -251,22 +118,17 @@
 struct iscsi_data_task {
 	struct iscsi_data	hdr;			/* PDU */
 	char			hdrext[sizeof(__u32)];	/* Header-Digest */
-	struct list_head	item;			/* data queue item */
 	struct iscsi_buf	digestbuf;		/* digest buffer */
 	uint32_t		digest;			/* data digest */
 };
-#define ISCSI_DTASK_DEFAULT_MAX	ISCSI_SG_TABLESIZE * PAGE_SIZE / 512
 
-struct iscsi_mgmt_task {
-	struct iscsi_hdr	hdr;		/* mgmt. PDU */
-	char			hdrext[sizeof(__u32)];	/* Header-Digest */
-	char			*data;		/* mgmt payload */
+struct iscsi_tcp_mgmt_task {
+	struct iscsi_hdr	hdr;
+	char			hdrext[sizeof(__u32)]; /* Header-Digest */
 	int			xmstate;	/* mgmt xmit progress */
-	int			data_count;	/* counts data to be sent */
 	struct iscsi_buf	headbuf;	/* header buffer */
 	struct iscsi_buf	sendbuf;	/* in progress buffer */
 	int			sent;
-	uint32_t		itt;		/* this ITT */
 };
 
 struct iscsi_r2t_info {
@@ -280,48 +142,36 @@
 	int			data_count;	/* DATA-Out payload progress */
 	struct scatterlist	*sg;		/* per-R2T SG list */
 	int			solicit_datasn;
-	struct iscsi_data_task   *dtask;        /* which data task */
+	struct iscsi_data_task   dtask;        /* which data task */
 };
 
-struct iscsi_cmd_task {
-	struct iscsi_cmd	hdr;			/* iSCSI PDU header */
+struct iscsi_tcp_cmd_task {
+	struct iscsi_cmd	hdr;
 	char			hdrext[4*sizeof(__u16)+	/* AHS */
 				    sizeof(__u32)];	/* HeaderDigest */
 	char			pad[ISCSI_PAD_LEN];
-	int			itt;			/* this ITT */
-	int			datasn;			/* DataSN */
+	int			pad_count;		/* padded bytes */
 	struct iscsi_buf	headbuf;		/* header buf (xmit) */
 	struct iscsi_buf	sendbuf;		/* in progress buffer*/
+	int			xmstate;		/* xmit xtate machine */
 	int			sent;
 	struct scatterlist	*sg;			/* per-cmd SG list  */
 	struct scatterlist	*bad_sg;		/* assert statement */
 	int			sg_count;		/* SG's to process  */
-	uint32_t		unsol_datasn;
 	uint32_t		exp_r2tsn;
-	int			xmstate;		/* xmit xtate machine */
-	int			imm_count;		/* imm-data (bytes)   */
-	int			unsol_count;		/* unsolicited (bytes)*/
 	int			r2t_data_count;		/* R2T Data-Out bytes */
-	int			data_count;		/* remaining Data-Out */
-	int			pad_count;		/* padded bytes */
-	struct scsi_cmnd	*sc;			/* associated SCSI cmd*/
-	int			total_length;
 	int			data_offset;
-	struct iscsi_conn	*conn;			/* used connection    */
-	struct iscsi_mgmt_task	*mtask;			/* tmf mtask in progr */
-
 	struct iscsi_r2t_info	*r2t;			/* in progress R2T    */
 	struct iscsi_queue	r2tpool;
 	struct kfifo		*r2tqueue;
 	struct iscsi_r2t_info	**r2ts;
-	struct list_head	dataqueue;		/* Data-Out dataqueue */
-	mempool_t		*datapool;
 	uint32_t		datadigest;		/* for recover digest */
 	int			digest_count;
 	uint32_t		immdigest;		/* for imm data */
 	struct iscsi_buf	immbuf;			/* for imm data digest */
-	struct iscsi_data_task   *dtask;		/* data task in progress*/
-	int			digest_offset;		/* for partial buff digest */
+	struct iscsi_data_task	*dtask;		/* data task in progress*/
+	struct iscsi_data_task	unsol_dtask;	/* unsol data task */
+	int			digest_offset;	/* for partial buff digest */
 };
 
 #endif /* ISCSI_H */
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index 835dff0..004e1a0 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -652,6 +652,151 @@
 	ata_altstatus(ap);        /* dummy read */
 }
 
+/**
+ *	ata_bmdma_freeze - Freeze BMDMA controller port
+ *	@ap: port to freeze
+ *
+ *	Freeze BMDMA controller port.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+void ata_bmdma_freeze(struct ata_port *ap)
+{
+	struct ata_ioports *ioaddr = &ap->ioaddr;
+
+	ap->ctl |= ATA_NIEN;
+	ap->last_ctl = ap->ctl;
+
+	if (ap->flags & ATA_FLAG_MMIO)
+		writeb(ap->ctl, (void __iomem *)ioaddr->ctl_addr);
+	else
+		outb(ap->ctl, ioaddr->ctl_addr);
+}
+
+/**
+ *	ata_bmdma_thaw - Thaw BMDMA controller port
+ *	@ap: port to thaw
+ *
+ *	Thaw BMDMA controller port.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+void ata_bmdma_thaw(struct ata_port *ap)
+{
+	/* clear & re-enable interrupts */
+	ata_chk_status(ap);
+	ap->ops->irq_clear(ap);
+	if (ap->ioaddr.ctl_addr)	/* FIXME: hack. create a hook instead */
+		ata_irq_on(ap);
+}
+
+/**
+ *	ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
+ *	@ap: port to handle error for
+ *	@prereset: prereset method (can be NULL)
+ *	@softreset: softreset method (can be NULL)
+ *	@hardreset: hardreset method (can be NULL)
+ *	@postreset: postreset method (can be NULL)
+ *
+ *	Handle error for ATA BMDMA controller.  It can handle both
+ *	PATA and SATA controllers.  Many controllers should be able to
+ *	use this EH as-is or with some added handling before and
+ *	after.
+ *
+ *	This function is intended to be used for constructing
+ *	->error_handler callback by low level drivers.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ */
+void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+			ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+			ata_postreset_fn_t postreset)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
+	int thaw = 0;
+
+	qc = __ata_qc_from_tag(ap, ap->active_tag);
+	if (qc && !(qc->flags & ATA_QCFLAG_FAILED))
+		qc = NULL;
+
+	/* reset PIO HSM and stop DMA engine */
+	spin_lock_irqsave(ap->lock, flags);
+
+	ap->hsm_task_state = HSM_ST_IDLE;
+
+	if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
+		   qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
+		u8 host_stat;
+
+		host_stat = ata_bmdma_status(ap);
+
+		ata_ehi_push_desc(&ehc->i, "BMDMA stat 0x%x", host_stat);
+
+		/* BMDMA controllers indicate host bus error by
+		 * setting DMA_ERR bit and timing out.  As it wasn't
+		 * really a timeout event, adjust error mask and
+		 * cancel frozen state.
+		 */
+		if (qc->err_mask == AC_ERR_TIMEOUT && host_stat & ATA_DMA_ERR) {
+			qc->err_mask = AC_ERR_HOST_BUS;
+			thaw = 1;
+		}
+
+		ap->ops->bmdma_stop(qc);
+	}
+
+	ata_altstatus(ap);
+	ata_chk_status(ap);
+	ap->ops->irq_clear(ap);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	if (thaw)
+		ata_eh_thaw_port(ap);
+
+	/* PIO and DMA engines have been stopped, perform recovery */
+	ata_do_eh(ap, prereset, softreset, hardreset, postreset);
+}
+
+/**
+ *	ata_bmdma_error_handler - Stock error handler for BMDMA controller
+ *	@ap: port to handle error for
+ *
+ *	Stock error handler for BMDMA controller.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ */
+void ata_bmdma_error_handler(struct ata_port *ap)
+{
+	ata_reset_fn_t hardreset;
+
+	hardreset = NULL;
+	if (sata_scr_valid(ap))
+		hardreset = sata_std_hardreset;
+
+	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
+			   ata_std_postreset);
+}
+
+/**
+ *	ata_bmdma_post_internal_cmd - Stock post_internal_cmd for
+ *				      BMDMA controller
+ *	@qc: internal command to clean up
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ */
+void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+	ata_bmdma_stop(qc);
+}
+
 #ifdef CONFIG_PCI
 static struct ata_probe_ent *
 ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port)
@@ -930,10 +1075,21 @@
 
 	/* FIXME: check ata_device_add return */
 	if (legacy_mode) {
-		if (legacy_mode & (1 << 0))
+		struct device *dev = &pdev->dev;
+		struct ata_host_set *host_set = NULL;
+
+		if (legacy_mode & (1 << 0)) {
 			ata_device_add(probe_ent);
-		if (legacy_mode & (1 << 1))
+			host_set = dev_get_drvdata(dev);
+		}
+
+		if (legacy_mode & (1 << 1)) {
 			ata_device_add(probe_ent2);
+			if (host_set) {
+				host_set->next = dev_get_drvdata(dev);
+				dev_set_drvdata(dev, host_set);
+			}
+		}
 	} else
 		ata_device_add(probe_ent);
 
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index b046ffa..d1c1c30 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -61,26 +61,37 @@
 
 #include "libata.h"
 
-static unsigned int ata_dev_init_params(struct ata_port *ap,
-					struct ata_device *dev,
-					u16 heads,
-					u16 sectors);
-static void ata_set_mode(struct ata_port *ap);
-static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
-					 struct ata_device *dev);
-static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev);
+/* debounce timing parameters in msecs { interval, duration, timeout } */
+const unsigned long sata_deb_timing_boot[]		= {   5,  100, 2000 };
+const unsigned long sata_deb_timing_eh[]		= {  25,  500, 2000 };
+const unsigned long sata_deb_timing_before_fsrst[]	= { 100, 2000, 5000 };
+
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+					u16 heads, u16 sectors);
+static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
+static void ata_dev_xfermask(struct ata_device *dev);
 
 static unsigned int ata_unique_id = 1;
 static struct workqueue_struct *ata_wq;
 
+struct workqueue_struct *ata_aux_wq;
+
 int atapi_enabled = 1;
 module_param(atapi_enabled, int, 0444);
 MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
 
+int atapi_dmadir = 0;
+module_param(atapi_dmadir, int, 0444);
+MODULE_PARM_DESC(atapi_dmadir, "Enable ATAPI DMADIR bridge support (0=off, 1=on)");
+
 int libata_fua = 0;
 module_param_named(fua, libata_fua, int, 0444);
 MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
 
+static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
+module_param(ata_probe_timeout, int, 0444);
+MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -397,11 +408,22 @@
 	return "<n/a>";
 }
 
-static void ata_dev_disable(struct ata_port *ap, struct ata_device *dev)
+static const char *sata_spd_string(unsigned int spd)
 {
-	if (ata_dev_present(dev)) {
-		printk(KERN_WARNING "ata%u: dev %u disabled\n",
-		       ap->id, dev->devno);
+	static const char * const spd_str[] = {
+		"1.5 Gbps",
+		"3.0 Gbps",
+	};
+
+	if (spd == 0 || (spd - 1) >= ARRAY_SIZE(spd_str))
+		return "<unknown>";
+	return spd_str[spd - 1];
+}
+
+void ata_dev_disable(struct ata_device *dev)
+{
+	if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) {
+		ata_dev_printk(dev, KERN_WARNING, "disabled\n");
 		dev->class++;
 	}
 }
@@ -759,8 +781,9 @@
 void ata_dev_select(struct ata_port *ap, unsigned int device,
 			   unsigned int wait, unsigned int can_sleep)
 {
-	VPRINTK("ENTER, ata%u: device %u, wait %u\n",
-		ap->id, device, wait);
+	if (ata_msg_probe(ap))
+		ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, ata%u: "
+				"device %u, wait %u\n", ap->id, device, wait);
 
 	if (wait)
 		ata_wait_idle(ap);
@@ -915,9 +938,9 @@
 
 	DPRINTK("ENTER\n");
 
-	spin_lock_irqsave(&ap->host_set->lock, flags);
+	spin_lock_irqsave(ap->lock, flags);
 	ap->flags |= ATA_FLAG_FLUSH_PORT_TASK;
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	spin_unlock_irqrestore(ap->lock, flags);
 
 	DPRINTK("flush #1\n");
 	flush_workqueue(ata_wq);
@@ -928,30 +951,32 @@
 	 * Cancel and flush.
 	 */
 	if (!cancel_delayed_work(&ap->port_task)) {
-		DPRINTK("flush #2\n");
+		if (ata_msg_ctl(ap))
+			ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
+					__FUNCTION__);
 		flush_workqueue(ata_wq);
 	}
 
-	spin_lock_irqsave(&ap->host_set->lock, flags);
+	spin_lock_irqsave(ap->lock, flags);
 	ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK;
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	spin_unlock_irqrestore(ap->lock, flags);
 
-	DPRINTK("EXIT\n");
+	if (ata_msg_ctl(ap))
+		ata_port_printk(ap, KERN_DEBUG, "%s: EXIT\n", __FUNCTION__);
 }
 
 void ata_qc_complete_internal(struct ata_queued_cmd *qc)
 {
 	struct completion *waiting = qc->private_data;
 
-	qc->ap->ops->tf_read(qc->ap, &qc->tf);
 	complete(waiting);
 }
 
 /**
  *	ata_exec_internal - execute libata internal command
- *	@ap: Port to which the command is sent
  *	@dev: Device to which the command is sent
  *	@tf: Taskfile registers for the command and the result
+ *	@cdb: CDB for packet command
  *	@dma_dir: Data tranfer direction of the command
  *	@buf: Data buffer of the command
  *	@buflen: Length of data buffer
@@ -964,25 +989,66 @@
  *
  *	LOCKING:
  *	None.  Should be called with kernel context, might sleep.
+ *
+ *	RETURNS:
+ *	Zero on success, AC_ERR_* mask on failure
  */
-
-static unsigned
-ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
-		  struct ata_taskfile *tf,
-		  int dma_dir, void *buf, unsigned int buflen)
+unsigned ata_exec_internal(struct ata_device *dev,
+			   struct ata_taskfile *tf, const u8 *cdb,
+			   int dma_dir, void *buf, unsigned int buflen)
 {
+	struct ata_port *ap = dev->ap;
 	u8 command = tf->command;
 	struct ata_queued_cmd *qc;
+	unsigned int tag, preempted_tag;
+	u32 preempted_sactive, preempted_qc_active;
 	DECLARE_COMPLETION(wait);
 	unsigned long flags;
 	unsigned int err_mask;
+	int rc;
 
-	spin_lock_irqsave(&ap->host_set->lock, flags);
+	spin_lock_irqsave(ap->lock, flags);
 
-	qc = ata_qc_new_init(ap, dev);
-	BUG_ON(qc == NULL);
+	/* no internal command while frozen */
+	if (ap->flags & ATA_FLAG_FROZEN) {
+		spin_unlock_irqrestore(ap->lock, flags);
+		return AC_ERR_SYSTEM;
+	}
 
+	/* initialize internal qc */
+
+	/* XXX: Tag 0 is used for drivers with legacy EH as some
+	 * drivers choke if any other tag is given.  This breaks
+	 * ata_tag_internal() test for those drivers.  Don't use new
+	 * EH stuff without converting to it.
+	 */
+	if (ap->ops->error_handler)
+		tag = ATA_TAG_INTERNAL;
+	else
+		tag = 0;
+
+	if (test_and_set_bit(tag, &ap->qc_allocated))
+		BUG();
+	qc = __ata_qc_from_tag(ap, tag);
+
+	qc->tag = tag;
+	qc->scsicmd = NULL;
+	qc->ap = ap;
+	qc->dev = dev;
+	ata_qc_reinit(qc);
+
+	preempted_tag = ap->active_tag;
+	preempted_sactive = ap->sactive;
+	preempted_qc_active = ap->qc_active;
+	ap->active_tag = ATA_TAG_POISON;
+	ap->sactive = 0;
+	ap->qc_active = 0;
+
+	/* prepare & issue qc */
 	qc->tf = *tf;
+	if (cdb)
+		memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
 	qc->dma_dir = dma_dir;
 	if (dma_dir != DMA_NONE) {
 		ata_sg_init_one(qc, buf, buflen);
@@ -994,33 +1060,58 @@
 
 	ata_qc_issue(qc);
 
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	spin_unlock_irqrestore(ap->lock, flags);
 
-	if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
-		ata_port_flush_task(ap);
+	rc = wait_for_completion_timeout(&wait, ata_probe_timeout);
 
-		spin_lock_irqsave(&ap->host_set->lock, flags);
+	ata_port_flush_task(ap);
+
+	if (!rc) {
+		spin_lock_irqsave(ap->lock, flags);
 
 		/* We're racing with irq here.  If we lose, the
 		 * following test prevents us from completing the qc
-		 * again.  If completion irq occurs after here but
-		 * before the caller cleans up, it will result in a
-		 * spurious interrupt.  We can live with that.
+		 * twice.  If we win, the port is frozen and will be
+		 * cleaned up by ->post_internal_cmd().
 		 */
 		if (qc->flags & ATA_QCFLAG_ACTIVE) {
-			qc->err_mask = AC_ERR_TIMEOUT;
-			ata_qc_complete(qc);
-			printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
-			       ap->id, command);
+			qc->err_mask |= AC_ERR_TIMEOUT;
+
+			if (ap->ops->error_handler)
+				ata_port_freeze(ap);
+			else
+				ata_qc_complete(qc);
+
+			if (ata_msg_warn(ap))
+				ata_dev_printk(dev, KERN_WARNING,
+					"qc timeout (cmd 0x%x)\n", command);
 		}
 
-		spin_unlock_irqrestore(&ap->host_set->lock, flags);
+		spin_unlock_irqrestore(ap->lock, flags);
 	}
 
-	*tf = qc->tf;
+	/* do post_internal_cmd */
+	if (ap->ops->post_internal_cmd)
+		ap->ops->post_internal_cmd(qc);
+
+	if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) {
+		if (ata_msg_warn(ap))
+			ata_dev_printk(dev, KERN_WARNING,
+				"zero err_mask for failed "
+				"internal command, assuming AC_ERR_OTHER\n");
+		qc->err_mask |= AC_ERR_OTHER;
+	}
+
+	/* finish up */
+	spin_lock_irqsave(ap->lock, flags);
+
+	*tf = qc->result_tf;
 	err_mask = qc->err_mask;
 
 	ata_qc_free(qc);
+	ap->active_tag = preempted_tag;
+	ap->sactive = preempted_sactive;
+	ap->qc_active = preempted_qc_active;
 
 	/* XXX - Some LLDDs (sata_mv) disable port on command failure.
 	 * Until those drivers are fixed, we detect the condition
@@ -1033,15 +1124,44 @@
 	 *
 	 * Kill the following code as soon as those drivers are fixed.
 	 */
-	if (ap->flags & ATA_FLAG_PORT_DISABLED) {
+	if (ap->flags & ATA_FLAG_DISABLED) {
 		err_mask |= AC_ERR_SYSTEM;
 		ata_port_probe(ap);
 	}
 
+	spin_unlock_irqrestore(ap->lock, flags);
+
 	return err_mask;
 }
 
 /**
+ *	ata_do_simple_cmd - execute simple internal command
+ *	@dev: Device to which the command is sent
+ *	@cmd: Opcode to execute
+ *
+ *	Execute a 'simple' command, that only consists of the opcode
+ *	'cmd' itself, without filling any other registers
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	Zero on success, AC_ERR_* mask on failure
+ */
+unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd)
+{
+	struct ata_taskfile tf;
+
+	ata_tf_init(dev, &tf);
+
+	tf.command = cmd;
+	tf.flags |= ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+
+	return ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
+}
+
+/**
  *	ata_pio_need_iordy	-	check if iordy needed
  *	@adev: ATA device
  *
@@ -1076,11 +1196,10 @@
 
 /**
  *	ata_dev_read_id - Read ID data from the specified device
- *	@ap: port on which target device resides
  *	@dev: target device
  *	@p_class: pointer to class of the target device (may be changed)
  *	@post_reset: is this read ID post-reset?
- *	@p_id: read IDENTIFY page (newly allocated)
+ *	@id: buffer to read IDENTIFY data into
  *
  *	Read ID data from the specified device.  ATA_CMD_ID_ATA is
  *	performed on ATA devices and ATA_CMD_ID_ATAPI on ATAPI
@@ -1093,29 +1212,24 @@
  *	RETURNS:
  *	0 on success, -errno otherwise.
  */
-static int ata_dev_read_id(struct ata_port *ap, struct ata_device *dev,
-			   unsigned int *p_class, int post_reset, u16 **p_id)
+int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+		    int post_reset, u16 *id)
 {
+	struct ata_port *ap = dev->ap;
 	unsigned int class = *p_class;
 	struct ata_taskfile tf;
 	unsigned int err_mask = 0;
-	u16 *id;
 	const char *reason;
 	int rc;
 
-	DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
+	if (ata_msg_ctl(ap))
+		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
+			       __FUNCTION__, ap->id, dev->devno);
 
 	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
 
-	id = kmalloc(sizeof(id[0]) * ATA_ID_WORDS, GFP_KERNEL);
-	if (id == NULL) {
-		rc = -ENOMEM;
-		reason = "out of memory";
-		goto err_out;
-	}
-
  retry:
-	ata_tf_init(ap, &tf, dev->devno);
+	ata_tf_init(dev, &tf);
 
 	switch (class) {
 	case ATA_DEV_ATA:
@@ -1132,7 +1246,7 @@
 
 	tf.protocol = ATA_PROT_PIO;
 
-	err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
 				     id, sizeof(id[0]) * ATA_ID_WORDS);
 	if (err_mask) {
 		rc = -EIO;
@@ -1159,7 +1273,7 @@
 		 * Some drives were very specific about that exact sequence.
 		 */
 		if (ata_id_major_version(id) < 4 || !ata_id_has_lba(id)) {
-			err_mask = ata_dev_init_params(ap, dev, id[3], id[6]);
+			err_mask = ata_dev_init_params(dev, id[3], id[6]);
 			if (err_mask) {
 				rc = -EIO;
 				reason = "INIT_DEV_PARAMS failed";
@@ -1175,25 +1289,45 @@
 	}
 
 	*p_class = class;
-	*p_id = id;
+
 	return 0;
 
  err_out:
-	printk(KERN_WARNING "ata%u: dev %u failed to IDENTIFY (%s)\n",
-	       ap->id, dev->devno, reason);
-	kfree(id);
+	if (ata_msg_warn(ap))
+		ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY "
+			       "(%s, err_mask=0x%x)\n", reason, err_mask);
 	return rc;
 }
 
-static inline u8 ata_dev_knobble(const struct ata_port *ap,
-				 struct ata_device *dev)
+static inline u8 ata_dev_knobble(struct ata_device *dev)
 {
-	return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+	return ((dev->ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
+}
+
+static void ata_dev_config_ncq(struct ata_device *dev,
+			       char *desc, size_t desc_sz)
+{
+	struct ata_port *ap = dev->ap;
+	int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
+
+	if (!ata_id_has_ncq(dev->id)) {
+		desc[0] = '\0';
+		return;
+	}
+
+	if (ap->flags & ATA_FLAG_NCQ) {
+		hdepth = min(ap->host->can_queue, ATA_MAX_QUEUE - 1);
+		dev->flags |= ATA_DFLAG_NCQ;
+	}
+
+	if (hdepth >= ddepth)
+		snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth);
+	else
+		snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
 }
 
 /**
  *	ata_dev_configure - Configure the specified ATA/ATAPI device
- *	@ap: Port on which target device resides
  *	@dev: Target device to configure
  *	@print_info: Enable device info printout
  *
@@ -1206,30 +1340,35 @@
  *	RETURNS:
  *	0 on success, -errno otherwise
  */
-static int ata_dev_configure(struct ata_port *ap, struct ata_device *dev,
-			     int print_info)
+int ata_dev_configure(struct ata_device *dev, int print_info)
 {
+	struct ata_port *ap = dev->ap;
 	const u16 *id = dev->id;
 	unsigned int xfer_mask;
 	int i, rc;
 
-	if (!ata_dev_present(dev)) {
-		DPRINTK("ENTER/EXIT (host %u, dev %u) -- nodev\n",
-			ap->id, dev->devno);
+	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
+		ata_dev_printk(dev, KERN_INFO,
+			       "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n",
+			       __FUNCTION__, ap->id, dev->devno);
 		return 0;
 	}
 
-	DPRINTK("ENTER, host %u, dev %u\n", ap->id, dev->devno);
+	if (ata_msg_probe(ap))
+		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
+			       __FUNCTION__, ap->id, dev->devno);
 
 	/* print device capabilities */
-	if (print_info)
-		printk(KERN_DEBUG "ata%u: dev %u cfg 49:%04x 82:%04x 83:%04x "
-		       "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
-		       ap->id, dev->devno, id[49], id[82], id[83],
-		       id[84], id[85], id[86], id[87], id[88]);
+	if (ata_msg_probe(ap))
+		ata_dev_printk(dev, KERN_DEBUG,
+			       "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
+			       "85:%04x 86:%04x 87:%04x 88:%04x\n",
+			       __FUNCTION__,
+			       id[49], id[82], id[83], id[84],
+			       id[85], id[86], id[87], id[88]);
 
 	/* initialize to-be-configured parameters */
-	dev->flags = 0;
+	dev->flags &= ~ATA_DFLAG_CFG_MASK;
 	dev->max_sectors = 0;
 	dev->cdb_len = 0;
 	dev->n_sectors = 0;
@@ -1244,7 +1383,8 @@
 	/* find max transfer mode; for printk only */
 	xfer_mask = ata_id_xfermask(id);
 
-	ata_dump_id(id);
+	if (ata_msg_probe(ap))
+		ata_dump_id(id);
 
 	/* ATA-specific feature tests */
 	if (dev->class == ATA_DEV_ATA) {
@@ -1252,6 +1392,7 @@
 
 		if (ata_id_has_lba(id)) {
 			const char *lba_desc;
+			char ncq_desc[20];
 
 			lba_desc = "LBA";
 			dev->flags |= ATA_DFLAG_LBA;
@@ -1260,15 +1401,17 @@
 				lba_desc = "LBA48";
 			}
 
+			/* config NCQ */
+			ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
+
 			/* print device info to dmesg */
-			if (print_info)
-				printk(KERN_INFO "ata%u: dev %u ATA-%d, "
-				       "max %s, %Lu sectors: %s\n",
-				       ap->id, dev->devno,
-				       ata_id_major_version(id),
-				       ata_mode_string(xfer_mask),
-				       (unsigned long long)dev->n_sectors,
-				       lba_desc);
+			if (ata_msg_info(ap))
+				ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
+					"max %s, %Lu sectors: %s %s\n",
+					ata_id_major_version(id),
+					ata_mode_string(xfer_mask),
+					(unsigned long long)dev->n_sectors,
+					lba_desc, ncq_desc);
 		} else {
 			/* CHS */
 
@@ -1285,14 +1428,22 @@
 			}
 
 			/* print device info to dmesg */
-			if (print_info)
-				printk(KERN_INFO "ata%u: dev %u ATA-%d, "
-				       "max %s, %Lu sectors: CHS %u/%u/%u\n",
-				       ap->id, dev->devno,
-				       ata_id_major_version(id),
-				       ata_mode_string(xfer_mask),
-				       (unsigned long long)dev->n_sectors,
-				       dev->cylinders, dev->heads, dev->sectors);
+			if (ata_msg_info(ap))
+				ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
+					"max %s, %Lu sectors: CHS %u/%u/%u\n",
+					ata_id_major_version(id),
+					ata_mode_string(xfer_mask),
+					(unsigned long long)dev->n_sectors,
+					dev->cylinders, dev->heads,
+					dev->sectors);
+		}
+
+		if (dev->id[59] & 0x100) {
+			dev->multi_count = dev->id[59] & 0xff;
+			if (ata_msg_info(ap))
+				ata_dev_printk(dev, KERN_INFO,
+					"ata%u: dev %u multi count %u\n",
+					ap->id, dev->devno, dev->multi_count);
 		}
 
 		dev->cdb_len = 16;
@@ -1300,18 +1451,28 @@
 
 	/* ATAPI-specific feature tests */
 	else if (dev->class == ATA_DEV_ATAPI) {
+		char *cdb_intr_string = "";
+
 		rc = atapi_cdb_len(id);
 		if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
-			printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id);
+			if (ata_msg_warn(ap))
+				ata_dev_printk(dev, KERN_WARNING,
+					       "unsupported CDB len\n");
 			rc = -EINVAL;
 			goto err_out_nosup;
 		}
 		dev->cdb_len = (unsigned int) rc;
 
+		if (ata_id_cdb_intr(dev->id)) {
+			dev->flags |= ATA_DFLAG_CDB_INTR;
+			cdb_intr_string = ", CDB intr";
+		}
+
 		/* print device info to dmesg */
-		if (print_info)
-			printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
-			       ap->id, dev->devno, ata_mode_string(xfer_mask));
+		if (ata_msg_info(ap))
+			ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
+				       ata_mode_string(xfer_mask),
+				       cdb_intr_string);
 	}
 
 	ap->host->max_cmd_len = 0;
@@ -1321,10 +1482,10 @@
 					      ap->device[i].cdb_len);
 
 	/* limit bridge transfers to udma5, 200 sectors */
-	if (ata_dev_knobble(ap, dev)) {
-		if (print_info)
-			printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
-			       ap->id, dev->devno);
+	if (ata_dev_knobble(dev)) {
+		if (ata_msg_info(ap))
+			ata_dev_printk(dev, KERN_INFO,
+				       "applying bridge limits\n");
 		dev->udma_mask &= ATA_UDMA5;
 		dev->max_sectors = ATA_MAX_SECTORS;
 	}
@@ -1332,11 +1493,15 @@
 	if (ap->ops->dev_config)
 		ap->ops->dev_config(ap, dev);
 
-	DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
+	if (ata_msg_probe(ap))
+		ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
+			__FUNCTION__, ata_chk_status(ap));
 	return 0;
 
 err_out_nosup:
-	DPRINTK("EXIT, err\n");
+	if (ata_msg_probe(ap))
+		ata_dev_printk(dev, KERN_DEBUG,
+			       "%s: EXIT, err\n", __FUNCTION__);
 	return rc;
 }
 
@@ -1352,79 +1517,104 @@
  *	PCI/etc. bus probe sem.
  *
  *	RETURNS:
- *	Zero on success, non-zero on error.
+ *	Zero on success, negative errno otherwise.
  */
 
 static int ata_bus_probe(struct ata_port *ap)
 {
 	unsigned int classes[ATA_MAX_DEVICES];
-	unsigned int i, rc, found = 0;
+	int tries[ATA_MAX_DEVICES];
+	int i, rc, down_xfermask;
+	struct ata_device *dev;
 
 	ata_port_probe(ap);
 
-	/* reset and determine device classes */
 	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		classes[i] = ATA_DEV_UNKNOWN;
+		tries[i] = ATA_PROBE_MAX_TRIES;
 
-	if (ap->ops->probe_reset) {
-		rc = ap->ops->probe_reset(ap, classes);
-		if (rc) {
-			printk("ata%u: reset failed (errno=%d)\n", ap->id, rc);
-			return rc;
-		}
-	} else {
-		ap->ops->phy_reset(ap);
+ retry:
+	down_xfermask = 0;
 
-		if (!(ap->flags & ATA_FLAG_PORT_DISABLED))
-			for (i = 0; i < ATA_MAX_DEVICES; i++)
-				classes[i] = ap->device[i].class;
+	/* reset and determine device classes */
+	ap->ops->phy_reset(ap);
 
-		ata_port_probe(ap);
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		dev = &ap->device[i];
+
+		if (!(ap->flags & ATA_FLAG_DISABLED) &&
+		    dev->class != ATA_DEV_UNKNOWN)
+			classes[dev->devno] = dev->class;
+		else
+			classes[dev->devno] = ATA_DEV_NONE;
+
+		dev->class = ATA_DEV_UNKNOWN;
 	}
 
+	ata_port_probe(ap);
+
+	/* after the reset the device state is PIO 0 and the controller
+	   state is undefined. Record the mode */
+
 	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (classes[i] == ATA_DEV_UNKNOWN)
-			classes[i] = ATA_DEV_NONE;
+		ap->device[i].pio_mode = XFER_PIO_0;
 
 	/* read IDENTIFY page and configure devices */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
-		struct ata_device *dev = &ap->device[i];
+		dev = &ap->device[i];
 
-		dev->class = classes[i];
+		if (tries[i])
+			dev->class = classes[i];
 
-		if (!ata_dev_present(dev))
+		if (!ata_dev_enabled(dev))
 			continue;
 
-		WARN_ON(dev->id != NULL);
-		if (ata_dev_read_id(ap, dev, &dev->class, 1, &dev->id)) {
-			dev->class = ATA_DEV_NONE;
-			continue;
-		}
+		rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+		if (rc)
+			goto fail;
 
-		if (ata_dev_configure(ap, dev, 1)) {
-			ata_dev_disable(ap, dev);
-			continue;
-		}
-
-		found = 1;
+		rc = ata_dev_configure(dev, 1);
+		if (rc)
+			goto fail;
 	}
 
-	if (!found)
-		goto err_out_disable;
+	/* configure transfer mode */
+	rc = ata_set_mode(ap, &dev);
+	if (rc) {
+		down_xfermask = 1;
+		goto fail;
+	}
 
-	if (ap->ops->set_mode)
-		ap->ops->set_mode(ap);
-	else
-		ata_set_mode(ap);
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		if (ata_dev_enabled(&ap->device[i]))
+			return 0;
 
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
-		goto err_out_disable;
-
-	return 0;
-
-err_out_disable:
+	/* no device present, disable port */
+	ata_port_disable(ap);
 	ap->ops->port_disable(ap);
-	return -1;
+	return -ENODEV;
+
+ fail:
+	switch (rc) {
+	case -EINVAL:
+	case -ENODEV:
+		tries[dev->devno] = 0;
+		break;
+	case -EIO:
+		sata_down_spd_limit(ap);
+		/* fall through */
+	default:
+		tries[dev->devno]--;
+		if (down_xfermask &&
+		    ata_down_xfermask_limit(dev, tries[dev->devno] == 1))
+			tries[dev->devno] = 0;
+	}
+
+	if (!tries[dev->devno]) {
+		ata_down_xfermask_limit(dev, 1);
+		ata_dev_disable(dev);
+	}
+
+	goto retry;
 }
 
 /**
@@ -1440,7 +1630,7 @@
 
 void ata_port_probe(struct ata_port *ap)
 {
-	ap->flags &= ~ATA_FLAG_PORT_DISABLED;
+	ap->flags &= ~ATA_FLAG_DISABLED;
 }
 
 /**
@@ -1454,27 +1644,21 @@
  */
 static void sata_print_link_status(struct ata_port *ap)
 {
-	u32 sstatus, tmp;
-	const char *speed;
+	u32 sstatus, scontrol, tmp;
 
-	if (!ap->ops->scr_read)
+	if (sata_scr_read(ap, SCR_STATUS, &sstatus))
 		return;
+	sata_scr_read(ap, SCR_CONTROL, &scontrol);
 
-	sstatus = scr_read(ap, SCR_STATUS);
-
-	if (sata_dev_present(ap)) {
+	if (ata_port_online(ap)) {
 		tmp = (sstatus >> 4) & 0xf;
-		if (tmp & (1 << 0))
-			speed = "1.5";
-		else if (tmp & (1 << 1))
-			speed = "3.0";
-		else
-			speed = "<unknown>";
-		printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
-		       ap->id, speed, sstatus);
+		ata_port_printk(ap, KERN_INFO,
+				"SATA link up %s (SStatus %X SControl %X)\n",
+				sata_spd_string(tmp), sstatus, scontrol);
 	} else {
-		printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
-		       ap->id, sstatus);
+		ata_port_printk(ap, KERN_INFO,
+				"SATA link down (SStatus %X SControl %X)\n",
+				sstatus, scontrol);
 	}
 }
 
@@ -1497,17 +1681,18 @@
 
 	if (ap->flags & ATA_FLAG_SATA_RESET) {
 		/* issue phy wake/reset */
-		scr_write_flush(ap, SCR_CONTROL, 0x301);
+		sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
 		/* Couldn't find anything in SATA I/II specs, but
 		 * AHCI-1.1 10.4.2 says at least 1 ms. */
 		mdelay(1);
 	}
-	scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
+	/* phy wake/clear reset */
+	sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
 
 	/* wait for phy to become ready, if necessary */
 	do {
 		msleep(200);
-		sstatus = scr_read(ap, SCR_STATUS);
+		sata_scr_read(ap, SCR_STATUS, &sstatus);
 		if ((sstatus & 0xf) != 1)
 			break;
 	} while (time_before(jiffies, timeout));
@@ -1516,12 +1701,12 @@
 	sata_print_link_status(ap);
 
 	/* TODO: phy layer with polling, timeouts, etc. */
-	if (sata_dev_present(ap))
+	if (!ata_port_offline(ap))
 		ata_port_probe(ap);
 	else
 		ata_port_disable(ap);
 
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+	if (ap->flags & ATA_FLAG_DISABLED)
 		return;
 
 	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
@@ -1546,24 +1731,24 @@
 void sata_phy_reset(struct ata_port *ap)
 {
 	__sata_phy_reset(ap);
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+	if (ap->flags & ATA_FLAG_DISABLED)
 		return;
 	ata_bus_reset(ap);
 }
 
 /**
  *	ata_dev_pair		-	return other device on cable
- *	@ap: port
  *	@adev: device
  *
  *	Obtain the other device on the same cable, or if none is
  *	present NULL is returned
  */
 
-struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev)
+struct ata_device *ata_dev_pair(struct ata_device *adev)
 {
+	struct ata_port *ap = adev->ap;
 	struct ata_device *pair = &ap->device[1 - adev->devno];
-	if (!ata_dev_present(pair))
+	if (!ata_dev_enabled(pair))
 		return NULL;
 	return pair;
 }
@@ -1585,7 +1770,122 @@
 {
 	ap->device[0].class = ATA_DEV_NONE;
 	ap->device[1].class = ATA_DEV_NONE;
-	ap->flags |= ATA_FLAG_PORT_DISABLED;
+	ap->flags |= ATA_FLAG_DISABLED;
+}
+
+/**
+ *	sata_down_spd_limit - adjust SATA spd limit downward
+ *	@ap: Port to adjust SATA spd limit for
+ *
+ *	Adjust SATA spd limit of @ap downward.  Note that this
+ *	function only adjusts the limit.  The change must be applied
+ *	using sata_set_spd().
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ *	RETURNS:
+ *	0 on success, negative errno on failure
+ */
+int sata_down_spd_limit(struct ata_port *ap)
+{
+	u32 sstatus, spd, mask;
+	int rc, highbit;
+
+	rc = sata_scr_read(ap, SCR_STATUS, &sstatus);
+	if (rc)
+		return rc;
+
+	mask = ap->sata_spd_limit;
+	if (mask <= 1)
+		return -EINVAL;
+	highbit = fls(mask) - 1;
+	mask &= ~(1 << highbit);
+
+	spd = (sstatus >> 4) & 0xf;
+	if (spd <= 1)
+		return -EINVAL;
+	spd--;
+	mask &= (1 << spd) - 1;
+	if (!mask)
+		return -EINVAL;
+
+	ap->sata_spd_limit = mask;
+
+	ata_port_printk(ap, KERN_WARNING, "limiting SATA link speed to %s\n",
+			sata_spd_string(fls(mask)));
+
+	return 0;
+}
+
+static int __sata_set_spd_needed(struct ata_port *ap, u32 *scontrol)
+{
+	u32 spd, limit;
+
+	if (ap->sata_spd_limit == UINT_MAX)
+		limit = 0;
+	else
+		limit = fls(ap->sata_spd_limit);
+
+	spd = (*scontrol >> 4) & 0xf;
+	*scontrol = (*scontrol & ~0xf0) | ((limit & 0xf) << 4);
+
+	return spd != limit;
+}
+
+/**
+ *	sata_set_spd_needed - is SATA spd configuration needed
+ *	@ap: Port in question
+ *
+ *	Test whether the spd limit in SControl matches
+ *	@ap->sata_spd_limit.  This function is used to determine
+ *	whether hardreset is necessary to apply SATA spd
+ *	configuration.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ *	RETURNS:
+ *	1 if SATA spd configuration is needed, 0 otherwise.
+ */
+int sata_set_spd_needed(struct ata_port *ap)
+{
+	u32 scontrol;
+
+	if (sata_scr_read(ap, SCR_CONTROL, &scontrol))
+		return 0;
+
+	return __sata_set_spd_needed(ap, &scontrol);
+}
+
+/**
+ *	sata_set_spd - set SATA spd according to spd limit
+ *	@ap: Port to set SATA spd for
+ *
+ *	Set SATA spd of @ap according to sata_spd_limit.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ *	RETURNS:
+ *	0 if spd doesn't need to be changed, 1 if spd has been
+ *	changed.  Negative errno if SCR registers are inaccessible.
+ */
+int sata_set_spd(struct ata_port *ap)
+{
+	u32 scontrol;
+	int rc;
+
+	if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+		return rc;
+
+	if (!__sata_set_spd_needed(ap, &scontrol))
+		return 0;
+
+	if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+		return rc;
+
+	return 1;
 }
 
 /*
@@ -1736,52 +2036,149 @@
 	return 0;
 }
 
-static int ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
+/**
+ *	ata_down_xfermask_limit - adjust dev xfer masks downward
+ *	@dev: Device to adjust xfer masks
+ *	@force_pio0: Force PIO0
+ *
+ *	Adjust xfer masks of @dev downward.  Note that this function
+ *	does not apply the change.  Invoking ata_set_mode() afterwards
+ *	will apply the limit.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ *	RETURNS:
+ *	0 on success, negative errno on failure
+ */
+int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0)
+{
+	unsigned long xfer_mask;
+	int highbit;
+
+	xfer_mask = ata_pack_xfermask(dev->pio_mask, dev->mwdma_mask,
+				      dev->udma_mask);
+
+	if (!xfer_mask)
+		goto fail;
+	/* don't gear down to MWDMA from UDMA, go directly to PIO */
+	if (xfer_mask & ATA_MASK_UDMA)
+		xfer_mask &= ~ATA_MASK_MWDMA;
+
+	highbit = fls(xfer_mask) - 1;
+	xfer_mask &= ~(1 << highbit);
+	if (force_pio0)
+		xfer_mask &= 1 << ATA_SHIFT_PIO;
+	if (!xfer_mask)
+		goto fail;
+
+	ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
+			    &dev->udma_mask);
+
+	ata_dev_printk(dev, KERN_WARNING, "limiting speed to %s\n",
+		       ata_mode_string(xfer_mask));
+
+	return 0;
+
+ fail:
+	return -EINVAL;
+}
+
+static int ata_dev_set_mode(struct ata_device *dev)
 {
 	unsigned int err_mask;
 	int rc;
 
+	dev->flags &= ~ATA_DFLAG_PIO;
 	if (dev->xfer_shift == ATA_SHIFT_PIO)
 		dev->flags |= ATA_DFLAG_PIO;
 
-	err_mask = ata_dev_set_xfermode(ap, dev);
+	err_mask = ata_dev_set_xfermode(dev);
 	if (err_mask) {
-		printk(KERN_ERR
-		       "ata%u: failed to set xfermode (err_mask=0x%x)\n",
-		       ap->id, err_mask);
+		ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
+			       "(err_mask=0x%x)\n", err_mask);
 		return -EIO;
 	}
 
-	rc = ata_dev_revalidate(ap, dev, 0);
-	if (rc) {
-		printk(KERN_ERR
-		       "ata%u: failed to revalidate after set xfermode\n",
-		       ap->id);
+	rc = ata_dev_revalidate(dev, 0);
+	if (rc)
 		return rc;
-	}
 
 	DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
 		dev->xfer_shift, (int)dev->xfer_mode);
 
-	printk(KERN_INFO "ata%u: dev %u configured for %s\n",
-	       ap->id, dev->devno,
-	       ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
+	ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
+		       ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)));
 	return 0;
 }
 
-static int ata_host_set_pio(struct ata_port *ap)
+/**
+ *	ata_set_mode - Program timings and issue SET FEATURES - XFER
+ *	@ap: port on which timings will be programmed
+ *	@r_failed_dev: out paramter for failed device
+ *
+ *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
+ *	ata_set_mode() fails, pointer to the failing device is
+ *	returned in @r_failed_dev.
+ *
+ *	LOCKING:
+ *	PCI/etc. bus probe sem.
+ *
+ *	RETURNS:
+ *	0 on success, negative errno otherwise
+ */
+int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev)
 {
-	int i;
+	struct ata_device *dev;
+	int i, rc = 0, used_dma = 0, found = 0;
 
+	/* has private set_mode? */
+	if (ap->ops->set_mode) {
+		/* FIXME: make ->set_mode handle no device case and
+		 * return error code and failing device on failure.
+		 */
+		for (i = 0; i < ATA_MAX_DEVICES; i++) {
+			if (ata_dev_enabled(&ap->device[i])) {
+				ap->ops->set_mode(ap);
+				break;
+			}
+		}
+		return 0;
+	}
+
+	/* step 1: calculate xfer_mask */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
-		struct ata_device *dev = &ap->device[i];
+		unsigned int pio_mask, dma_mask;
 
-		if (!ata_dev_present(dev))
+		dev = &ap->device[i];
+
+		if (!ata_dev_enabled(dev))
+			continue;
+
+		ata_dev_xfermask(dev);
+
+		pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
+		dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
+		dev->pio_mode = ata_xfer_mask2mode(pio_mask);
+		dev->dma_mode = ata_xfer_mask2mode(dma_mask);
+
+		found = 1;
+		if (dev->dma_mode)
+			used_dma = 1;
+	}
+	if (!found)
+		goto out;
+
+	/* step 2: always set host PIO timings */
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		dev = &ap->device[i];
+		if (!ata_dev_enabled(dev))
 			continue;
 
 		if (!dev->pio_mode) {
-			printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, i);
-			return -1;
+			ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
+			rc = -EINVAL;
+			goto out;
 		}
 
 		dev->xfer_mode = dev->pio_mode;
@@ -1790,17 +2187,11 @@
 			ap->ops->set_piomode(ap, dev);
 	}
 
-	return 0;
-}
-
-static void ata_host_set_dma(struct ata_port *ap)
-{
-	int i;
-
+	/* step 3: set host DMA timings */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
-		struct ata_device *dev = &ap->device[i];
+		dev = &ap->device[i];
 
-		if (!ata_dev_present(dev) || !dev->dma_mode)
+		if (!ata_dev_enabled(dev) || !dev->dma_mode)
 			continue;
 
 		dev->xfer_mode = dev->dma_mode;
@@ -1808,79 +2199,33 @@
 		if (ap->ops->set_dmamode)
 			ap->ops->set_dmamode(ap, dev);
 	}
-}
-
-/**
- *	ata_set_mode - Program timings and issue SET FEATURES - XFER
- *	@ap: port on which timings will be programmed
- *
- *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).
- *
- *	LOCKING:
- *	PCI/etc. bus probe sem.
- */
-static void ata_set_mode(struct ata_port *ap)
-{
-	int i, rc, used_dma = 0;
-
-	/* step 1: calculate xfer_mask */
-	for (i = 0; i < ATA_MAX_DEVICES; i++) {
-		struct ata_device *dev = &ap->device[i];
-		unsigned int pio_mask, dma_mask;
-
-		if (!ata_dev_present(dev))
-			continue;
-
-		ata_dev_xfermask(ap, dev);
-
-		/* TODO: let LLDD filter dev->*_mask here */
-
-		pio_mask = ata_pack_xfermask(dev->pio_mask, 0, 0);
-		dma_mask = ata_pack_xfermask(0, dev->mwdma_mask, dev->udma_mask);
-		dev->pio_mode = ata_xfer_mask2mode(pio_mask);
-		dev->dma_mode = ata_xfer_mask2mode(dma_mask);
-
-		if (dev->dma_mode)
-			used_dma = 1;
-	}
-
-	/* step 2: always set host PIO timings */
-	rc = ata_host_set_pio(ap);
-	if (rc)
-		goto err_out;
-
-	/* step 3: set host DMA timings */
-	ata_host_set_dma(ap);
 
 	/* step 4: update devices' xfer mode */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
-		struct ata_device *dev = &ap->device[i];
+		dev = &ap->device[i];
 
-		if (!ata_dev_present(dev))
+		if (!ata_dev_enabled(dev))
 			continue;
 
-		if (ata_dev_set_mode(ap, dev))
-			goto err_out;
+		rc = ata_dev_set_mode(dev);
+		if (rc)
+			goto out;
 	}
 
-	/*
-	 *	Record simplex status. If we selected DMA then the other
-	 *	host channels are not permitted to do so.
+	/* Record simplex status. If we selected DMA then the other
+	 * host channels are not permitted to do so.
 	 */
-
 	if (used_dma && (ap->host_set->flags & ATA_HOST_SIMPLEX))
 		ap->host_set->simplex_claimed = 1;
 
-	/*
-	 *	Chip specific finalisation
-	 */
+	/* step5: chip specific finalisation */
 	if (ap->ops->post_set_mode)
 		ap->ops->post_set_mode(ap);
 
-	return;
-
-err_out:
-	ata_port_disable(ap);
+ out:
+	if (rc)
+		*r_failed_dev = dev;
+	return rc;
 }
 
 /**
@@ -1930,8 +2275,8 @@
 	}
 
 	if (status & ATA_BUSY)
-		printk(KERN_WARNING "ata%u is slow to respond, "
-		       "please be patient\n", ap->id);
+		ata_port_printk(ap, KERN_WARNING,
+				"port is slow to respond, please be patient\n");
 
 	timeout = timer_start + tmout;
 	while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
@@ -1940,8 +2285,8 @@
 	}
 
 	if (status & ATA_BUSY) {
-		printk(KERN_ERR "ata%u failed to respond (%lu secs)\n",
-		       ap->id, tmout / HZ);
+		ata_port_printk(ap, KERN_ERR, "port failed to respond "
+				"(%lu secs)\n", tmout / HZ);
 		return 1;
 	}
 
@@ -2033,8 +2378,10 @@
 	 * the bus shows 0xFF because the odd clown forgets the D7
 	 * pulldown resistor.
 	 */
-	if (ata_check_status(ap) == 0xFF)
+	if (ata_check_status(ap) == 0xFF) {
+		ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
 		return AC_ERR_OTHER;
+	}
 
 	ata_bus_post_reset(ap, devmask);
 
@@ -2058,7 +2405,7 @@
  *	Obtains host_set lock.
  *
  *	SIDE EFFECTS:
- *	Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
+ *	Sets ATA_FLAG_DISABLED if bus reset fails.
  */
 
 void ata_bus_reset(struct ata_port *ap)
@@ -2126,60 +2473,139 @@
 	return;
 
 err_out:
-	printk(KERN_ERR "ata%u: disabling port\n", ap->id);
+	ata_port_printk(ap, KERN_ERR, "disabling port\n");
 	ap->ops->port_disable(ap);
 
 	DPRINTK("EXIT\n");
 }
 
-static int sata_phy_resume(struct ata_port *ap)
-{
-	unsigned long timeout = jiffies + (HZ * 5);
-	u32 sstatus;
-
-	scr_write_flush(ap, SCR_CONTROL, 0x300);
-
-	/* Wait for phy to become ready, if necessary. */
-	do {
-		msleep(200);
-		sstatus = scr_read(ap, SCR_STATUS);
-		if ((sstatus & 0xf) != 1)
-			return 0;
-	} while (time_before(jiffies, timeout));
-
-	return -1;
-}
-
 /**
- *	ata_std_probeinit - initialize probing
- *	@ap: port to be probed
+ *	sata_phy_debounce - debounce SATA phy status
+ *	@ap: ATA port to debounce SATA phy status for
+ *	@params: timing parameters { interval, duratinon, timeout } in msec
  *
- *	@ap is about to be probed.  Initialize it.  This function is
- *	to be used as standard callback for ata_drive_probe_reset().
+ *	Make sure SStatus of @ap reaches stable state, determined by
+ *	holding the same value where DET is not 1 for @duration polled
+ *	every @interval, before @timeout.  Timeout constraints the
+ *	beginning of the stable state.  Because, after hot unplugging,
+ *	DET gets stuck at 1 on some controllers, this functions waits
+ *	until timeout then returns 0 if DET is stable at 1.
  *
- *	NOTE!!! Do not use this function as probeinit if a low level
- *	driver implements only hardreset.  Just pass NULL as probeinit
- *	in that case.  Using this function is probably okay but doing
- *	so makes reset sequence different from the original
- *	->phy_reset implementation and Jeff nervous.  :-P
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	0 on success, -errno on failure.
  */
-void ata_std_probeinit(struct ata_port *ap)
+int sata_phy_debounce(struct ata_port *ap, const unsigned long *params)
 {
-	if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) {
-		sata_phy_resume(ap);
-		if (sata_dev_present(ap))
-			ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+	unsigned long interval_msec = params[0];
+	unsigned long duration = params[1] * HZ / 1000;
+	unsigned long timeout = jiffies + params[2] * HZ / 1000;
+	unsigned long last_jiffies;
+	u32 last, cur;
+	int rc;
+
+	if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
+		return rc;
+	cur &= 0xf;
+
+	last = cur;
+	last_jiffies = jiffies;
+
+	while (1) {
+		msleep(interval_msec);
+		if ((rc = sata_scr_read(ap, SCR_STATUS, &cur)))
+			return rc;
+		cur &= 0xf;
+
+		/* DET stable? */
+		if (cur == last) {
+			if (cur == 1 && time_before(jiffies, timeout))
+				continue;
+			if (time_after(jiffies, last_jiffies + duration))
+				return 0;
+			continue;
+		}
+
+		/* unstable, start over */
+		last = cur;
+		last_jiffies = jiffies;
+
+		/* check timeout */
+		if (time_after(jiffies, timeout))
+			return -EBUSY;
 	}
 }
 
 /**
- *	ata_std_softreset - reset host port via ATA SRST
- *	@ap: port to reset
- *	@verbose: fail verbosely
- *	@classes: resulting classes of attached devices
+ *	sata_phy_resume - resume SATA phy
+ *	@ap: ATA port to resume SATA phy for
+ *	@params: timing parameters { interval, duratinon, timeout } in msec
  *
- *	Reset host port using ATA SRST.  This function is to be used
- *	as standard callback for ata_drive_*_reset() functions.
+ *	Resume SATA phy of @ap and debounce it.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	0 on success, -errno on failure.
+ */
+int sata_phy_resume(struct ata_port *ap, const unsigned long *params)
+{
+	u32 scontrol;
+	int rc;
+
+	if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+		return rc;
+
+	scontrol = (scontrol & 0x0f0) | 0x300;
+
+	if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+		return rc;
+
+	/* Some PHYs react badly if SStatus is pounded immediately
+	 * after resuming.  Delay 200ms before debouncing.
+	 */
+	msleep(200);
+
+	return sata_phy_debounce(ap, params);
+}
+
+static void ata_wait_spinup(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	unsigned long end, secs;
+	int rc;
+
+	/* first, debounce phy if SATA */
+	if (ap->cbl == ATA_CBL_SATA) {
+		rc = sata_phy_debounce(ap, sata_deb_timing_eh);
+
+		/* if debounced successfully and offline, no need to wait */
+		if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
+			return;
+	}
+
+	/* okay, let's give the drive time to spin up */
+	end = ehc->i.hotplug_timestamp + ATA_SPINUP_WAIT * HZ / 1000;
+	secs = ((end - jiffies) + HZ - 1) / HZ;
+
+	if (time_after(jiffies, end))
+		return;
+
+	if (secs > 5)
+		ata_port_printk(ap, KERN_INFO, "waiting for device to spin up "
+				"(%lu secs)\n", secs);
+
+	schedule_timeout_uninterruptible(end - jiffies);
+}
+
+/**
+ *	ata_std_prereset - prepare for reset
+ *	@ap: ATA port to be reset
+ *
+ *	@ap is about to be reset.  Initialize it.
  *
  *	LOCKING:
  *	Kernel thread context (may sleep)
@@ -2187,7 +2613,63 @@
  *	RETURNS:
  *	0 on success, -errno otherwise.
  */
-int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes)
+int ata_std_prereset(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	const unsigned long *timing;
+	int rc;
+
+	/* hotplug? */
+	if (ehc->i.flags & ATA_EHI_HOTPLUGGED) {
+		if (ap->flags & ATA_FLAG_HRST_TO_RESUME)
+			ehc->i.action |= ATA_EH_HARDRESET;
+		if (ap->flags & ATA_FLAG_SKIP_D2H_BSY)
+			ata_wait_spinup(ap);
+	}
+
+	/* if we're about to do hardreset, nothing more to do */
+	if (ehc->i.action & ATA_EH_HARDRESET)
+		return 0;
+
+	/* if SATA, resume phy */
+	if (ap->cbl == ATA_CBL_SATA) {
+		if (ap->flags & ATA_FLAG_LOADING)
+			timing = sata_deb_timing_boot;
+		else
+			timing = sata_deb_timing_eh;
+
+		rc = sata_phy_resume(ap, timing);
+		if (rc && rc != -EOPNOTSUPP) {
+			/* phy resume failed */
+			ata_port_printk(ap, KERN_WARNING, "failed to resume "
+					"link for reset (errno=%d)\n", rc);
+			return rc;
+		}
+	}
+
+	/* Wait for !BSY if the controller can wait for the first D2H
+	 * Reg FIS and we don't know that no device is attached.
+	 */
+	if (!(ap->flags & ATA_FLAG_SKIP_D2H_BSY) && !ata_port_offline(ap))
+		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
+
+	return 0;
+}
+
+/**
+ *	ata_std_softreset - reset host port via ATA SRST
+ *	@ap: port to reset
+ *	@classes: resulting classes of attached devices
+ *
+ *	Reset host port using ATA SRST.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise.
+ */
+int ata_std_softreset(struct ata_port *ap, unsigned int *classes)
 {
 	unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
 	unsigned int devmask = 0, err_mask;
@@ -2195,7 +2677,7 @@
 
 	DPRINTK("ENTER\n");
 
-	if (ap->ops->scr_read && !sata_dev_present(ap)) {
+	if (ata_port_offline(ap)) {
 		classes[0] = ATA_DEV_NONE;
 		goto out;
 	}
@@ -2213,11 +2695,7 @@
 	DPRINTK("about to softreset, devmask=%x\n", devmask);
 	err_mask = ata_bus_softreset(ap, devmask);
 	if (err_mask) {
-		if (verbose)
-			printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n",
-			       ap->id, err_mask);
-		else
-			DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n",
+		ata_port_printk(ap, KERN_ERR, "SRST failed (err_mask=0x%x)\n",
 				err_mask);
 		return -EIO;
 	}
@@ -2235,12 +2713,9 @@
 /**
  *	sata_std_hardreset - reset host port via SATA phy reset
  *	@ap: port to reset
- *	@verbose: fail verbosely
  *	@class: resulting class of attached device
  *
  *	SATA phy-reset host port using DET bits of SControl register.
- *	This function is to be used as standard callback for
- *	ata_drive_*_reset().
  *
  *	LOCKING:
  *	Kernel thread context (may sleep)
@@ -2248,35 +2723,57 @@
  *	RETURNS:
  *	0 on success, -errno otherwise.
  */
-int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class)
+int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
 {
+	u32 scontrol;
+	int rc;
+
 	DPRINTK("ENTER\n");
 
-	/* Issue phy wake/reset */
-	scr_write_flush(ap, SCR_CONTROL, 0x301);
+	if (sata_set_spd_needed(ap)) {
+		/* SATA spec says nothing about how to reconfigure
+		 * spd.  To be on the safe side, turn off phy during
+		 * reconfiguration.  This works for at least ICH7 AHCI
+		 * and Sil3124.
+		 */
+		if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+			return rc;
 
-	/*
-	 * Couldn't find anything in SATA I/II specs, but AHCI-1.1
+		scontrol = (scontrol & 0x0f0) | 0x302;
+
+		if ((rc = sata_scr_write(ap, SCR_CONTROL, scontrol)))
+			return rc;
+
+		sata_set_spd(ap);
+	}
+
+	/* issue phy wake/reset */
+	if ((rc = sata_scr_read(ap, SCR_CONTROL, &scontrol)))
+		return rc;
+
+	scontrol = (scontrol & 0x0f0) | 0x301;
+
+	if ((rc = sata_scr_write_flush(ap, SCR_CONTROL, scontrol)))
+		return rc;
+
+	/* Couldn't find anything in SATA I/II specs, but AHCI-1.1
 	 * 10.4.2 says at least 1 ms.
 	 */
 	msleep(1);
 
-	/* Bring phy back */
-	sata_phy_resume(ap);
+	/* bring phy back */
+	sata_phy_resume(ap, sata_deb_timing_eh);
 
 	/* TODO: phy layer with polling, timeouts, etc. */
-	if (!sata_dev_present(ap)) {
+	if (ata_port_offline(ap)) {
 		*class = ATA_DEV_NONE;
 		DPRINTK("EXIT, link offline\n");
 		return 0;
 	}
 
 	if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) {
-		if (verbose)
-			printk(KERN_ERR "ata%u: COMRESET failed "
-			       "(device not ready)\n", ap->id);
-		else
-			DPRINTK("EXIT, device not ready\n");
+		ata_port_printk(ap, KERN_ERR,
+				"COMRESET failed (device not ready)\n");
 		return -EIO;
 	}
 
@@ -2297,27 +2794,28 @@
  *	the device might have been reset more than once using
  *	different reset methods before postreset is invoked.
  *
- *	This function is to be used as standard callback for
- *	ata_drive_*_reset().
- *
  *	LOCKING:
  *	Kernel thread context (may sleep)
  */
 void ata_std_postreset(struct ata_port *ap, unsigned int *classes)
 {
+	u32 serror;
+
 	DPRINTK("ENTER\n");
 
-	/* set cable type if it isn't already set */
-	if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA)
-		ap->cbl = ATA_CBL_SATA;
-
 	/* print link status */
-	if (ap->cbl == ATA_CBL_SATA)
-		sata_print_link_status(ap);
+	sata_print_link_status(ap);
+
+	/* clear SError */
+	if (sata_scr_read(ap, SCR_ERROR, &serror) == 0)
+		sata_scr_write(ap, SCR_ERROR, serror);
 
 	/* re-enable interrupts */
-	if (ap->ioaddr.ctl_addr)	/* FIXME: hack. create a hook instead */
-		ata_irq_on(ap);
+	if (!ap->ops->error_handler) {
+		/* FIXME: hack. create a hook instead */
+		if (ap->ioaddr.ctl_addr)
+			ata_irq_on(ap);
+	}
 
 	/* is double-select really necessary? */
 	if (classes[0] != ATA_DEV_NONE)
@@ -2343,126 +2841,7 @@
 }
 
 /**
- *	ata_std_probe_reset - standard probe reset method
- *	@ap: prot to perform probe-reset
- *	@classes: resulting classes of attached devices
- *
- *	The stock off-the-shelf ->probe_reset method.
- *
- *	LOCKING:
- *	Kernel thread context (may sleep)
- *
- *	RETURNS:
- *	0 on success, -errno otherwise.
- */
-int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes)
-{
-	ata_reset_fn_t hardreset;
-
-	hardreset = NULL;
-	if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read)
-		hardreset = sata_std_hardreset;
-
-	return ata_drive_probe_reset(ap, ata_std_probeinit,
-				     ata_std_softreset, hardreset,
-				     ata_std_postreset, classes);
-}
-
-static int do_probe_reset(struct ata_port *ap, ata_reset_fn_t reset,
-			  ata_postreset_fn_t postreset,
-			  unsigned int *classes)
-{
-	int i, rc;
-
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		classes[i] = ATA_DEV_UNKNOWN;
-
-	rc = reset(ap, 0, classes);
-	if (rc)
-		return rc;
-
-	/* If any class isn't ATA_DEV_UNKNOWN, consider classification
-	 * is complete and convert all ATA_DEV_UNKNOWN to
-	 * ATA_DEV_NONE.
-	 */
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		if (classes[i] != ATA_DEV_UNKNOWN)
-			break;
-
-	if (i < ATA_MAX_DEVICES)
-		for (i = 0; i < ATA_MAX_DEVICES; i++)
-			if (classes[i] == ATA_DEV_UNKNOWN)
-				classes[i] = ATA_DEV_NONE;
-
-	if (postreset)
-		postreset(ap, classes);
-
-	return classes[0] != ATA_DEV_UNKNOWN ? 0 : -ENODEV;
-}
-
-/**
- *	ata_drive_probe_reset - Perform probe reset with given methods
- *	@ap: port to reset
- *	@probeinit: probeinit method (can be NULL)
- *	@softreset: softreset method (can be NULL)
- *	@hardreset: hardreset method (can be NULL)
- *	@postreset: postreset method (can be NULL)
- *	@classes: resulting classes of attached devices
- *
- *	Reset the specified port and classify attached devices using
- *	given methods.  This function prefers softreset but tries all
- *	possible reset sequences to reset and classify devices.  This
- *	function is intended to be used for constructing ->probe_reset
- *	callback by low level drivers.
- *
- *	Reset methods should follow the following rules.
- *
- *	- Return 0 on sucess, -errno on failure.
- *	- If classification is supported, fill classes[] with
- *	  recognized class codes.
- *	- If classification is not supported, leave classes[] alone.
- *	- If verbose is non-zero, print error message on failure;
- *	  otherwise, shut up.
- *
- *	LOCKING:
- *	Kernel thread context (may sleep)
- *
- *	RETURNS:
- *	0 on success, -EINVAL if no reset method is avaliable, -ENODEV
- *	if classification fails, and any error code from reset
- *	methods.
- */
-int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit,
-			  ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-			  ata_postreset_fn_t postreset, unsigned int *classes)
-{
-	int rc = -EINVAL;
-
-	if (probeinit)
-		probeinit(ap);
-
-	if (softreset) {
-		rc = do_probe_reset(ap, softreset, postreset, classes);
-		if (rc == 0)
-			return 0;
-	}
-
-	if (!hardreset)
-		return rc;
-
-	rc = do_probe_reset(ap, hardreset, postreset, classes);
-	if (rc == 0 || rc != -ENODEV)
-		return rc;
-
-	if (softreset)
-		rc = do_probe_reset(ap, softreset, postreset, classes);
-
-	return rc;
-}
-
-/**
  *	ata_dev_same_device - Determine whether new ID matches configured device
- *	@ap: port on which the device to compare against resides
  *	@dev: device to compare against
  *	@new_class: class of the new device
  *	@new_id: IDENTIFY page of the new device
@@ -2477,17 +2856,16 @@
  *	RETURNS:
  *	1 if @dev matches @new_class and @new_id, 0 otherwise.
  */
-static int ata_dev_same_device(struct ata_port *ap, struct ata_device *dev,
-			       unsigned int new_class, const u16 *new_id)
+static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
+			       const u16 *new_id)
 {
 	const u16 *old_id = dev->id;
 	unsigned char model[2][41], serial[2][21];
 	u64 new_n_sectors;
 
 	if (dev->class != new_class) {
-		printk(KERN_INFO
-		       "ata%u: dev %u class mismatch %d != %d\n",
-		       ap->id, dev->devno, dev->class, new_class);
+		ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
+			       dev->class, new_class);
 		return 0;
 	}
 
@@ -2498,24 +2876,22 @@
 	new_n_sectors = ata_id_n_sectors(new_id);
 
 	if (strcmp(model[0], model[1])) {
-		printk(KERN_INFO
-		       "ata%u: dev %u model number mismatch '%s' != '%s'\n",
-		       ap->id, dev->devno, model[0], model[1]);
+		ata_dev_printk(dev, KERN_INFO, "model number mismatch "
+			       "'%s' != '%s'\n", model[0], model[1]);
 		return 0;
 	}
 
 	if (strcmp(serial[0], serial[1])) {
-		printk(KERN_INFO
-		       "ata%u: dev %u serial number mismatch '%s' != '%s'\n",
-		       ap->id, dev->devno, serial[0], serial[1]);
+		ata_dev_printk(dev, KERN_INFO, "serial number mismatch "
+			       "'%s' != '%s'\n", serial[0], serial[1]);
 		return 0;
 	}
 
 	if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
-		printk(KERN_INFO
-		       "ata%u: dev %u n_sectors mismatch %llu != %llu\n",
-		       ap->id, dev->devno, (unsigned long long)dev->n_sectors,
-		       (unsigned long long)new_n_sectors);
+		ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
+			       "%llu != %llu\n",
+			       (unsigned long long)dev->n_sectors,
+			       (unsigned long long)new_n_sectors);
 		return 0;
 	}
 
@@ -2524,7 +2900,6 @@
 
 /**
  *	ata_dev_revalidate - Revalidate ATA device
- *	@ap: port on which the device to revalidate resides
  *	@dev: device to revalidate
  *	@post_reset: is this revalidation after reset?
  *
@@ -2537,40 +2912,37 @@
  *	RETURNS:
  *	0 on success, negative errno otherwise
  */
-int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
-		       int post_reset)
+int ata_dev_revalidate(struct ata_device *dev, int post_reset)
 {
-	unsigned int class;
-	u16 *id;
+	unsigned int class = dev->class;
+	u16 *id = (void *)dev->ap->sector_buf;
 	int rc;
 
-	if (!ata_dev_present(dev))
-		return -ENODEV;
-
-	class = dev->class;
-	id = NULL;
-
-	/* allocate & read ID data */
-	rc = ata_dev_read_id(ap, dev, &class, post_reset, &id);
-	if (rc)
-		goto fail;
-
-	/* is the device still there? */
-	if (!ata_dev_same_device(ap, dev, class, id)) {
+	if (!ata_dev_enabled(dev)) {
 		rc = -ENODEV;
 		goto fail;
 	}
 
-	kfree(dev->id);
-	dev->id = id;
+	/* read ID data */
+	rc = ata_dev_read_id(dev, &class, post_reset, id);
+	if (rc)
+		goto fail;
+
+	/* is the device still there? */
+	if (!ata_dev_same_device(dev, class, id)) {
+		rc = -ENODEV;
+		goto fail;
+	}
+
+	memcpy(dev->id, id, sizeof(id[0]) * ATA_ID_WORDS);
 
 	/* configure device according to the new ID */
-	return ata_dev_configure(ap, dev, 0);
+	rc = ata_dev_configure(dev, 0);
+	if (rc == 0)
+		return 0;
 
  fail:
-	printk(KERN_ERR "ata%u: dev %u revalidation failed (errno=%d)\n",
-	       ap->id, dev->devno, rc);
-	kfree(id);
+	ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
 	return rc;
 }
 
@@ -2626,6 +2998,14 @@
 	unsigned int nlen, rlen;
 	int i;
 
+	/* We don't support polling DMA.
+	 * DMA blacklist those ATAPI devices with CDB-intr (and use PIO)
+	 * if the LLDD handles only interrupts in the HSM_ST_LAST state.
+	 */
+	if ((dev->ap->flags & ATA_FLAG_PIO_POLLING) &&
+	    (dev->flags & ATA_DFLAG_CDB_INTR))
+		return 1;
+
 	ata_id_string(dev->id, model_num, ATA_ID_PROD_OFS,
 			  sizeof(model_num));
 	ata_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS,
@@ -2646,7 +3026,6 @@
 
 /**
  *	ata_dev_xfermask - Compute supported xfermask of the given device
- *	@ap: Port on which the device to compute xfermask for resides
  *	@dev: Device to compute xfermask for
  *
  *	Compute supported xfermask of @dev and store it in
@@ -2661,49 +3040,61 @@
  *	LOCKING:
  *	None.
  */
-static void ata_dev_xfermask(struct ata_port *ap, struct ata_device *dev)
+static void ata_dev_xfermask(struct ata_device *dev)
 {
+	struct ata_port *ap = dev->ap;
 	struct ata_host_set *hs = ap->host_set;
 	unsigned long xfer_mask;
 	int i;
 
-	xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
-				      ap->udma_mask);
+	xfer_mask = ata_pack_xfermask(ap->pio_mask,
+				      ap->mwdma_mask, ap->udma_mask);
+
+	/* Apply cable rule here.  Don't apply it early because when
+	 * we handle hot plug the cable type can itself change.
+	 */
+	if (ap->cbl == ATA_CBL_PATA40)
+		xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
 
 	/* FIXME: Use port-wide xfermask for now */
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *d = &ap->device[i];
-		if (!ata_dev_present(d))
+
+		if (ata_dev_absent(d))
 			continue;
-		xfer_mask &= ata_pack_xfermask(d->pio_mask, d->mwdma_mask,
-					       d->udma_mask);
+
+		if (ata_dev_disabled(d)) {
+			/* to avoid violating device selection timing */
+			xfer_mask &= ata_pack_xfermask(d->pio_mask,
+						       UINT_MAX, UINT_MAX);
+			continue;
+		}
+
+		xfer_mask &= ata_pack_xfermask(d->pio_mask,
+					       d->mwdma_mask, d->udma_mask);
 		xfer_mask &= ata_id_xfermask(d->id);
 		if (ata_dma_blacklisted(d))
 			xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
-		/* Apply cable rule here. Don't apply it early because when
-		   we handle hot plug the cable type can itself change */
-		if (ap->cbl == ATA_CBL_PATA40)
-			xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA);
 	}
 
 	if (ata_dma_blacklisted(dev))
-		printk(KERN_WARNING "ata%u: dev %u is on DMA blacklist, "
-		       "disabling DMA\n", ap->id, dev->devno);
+		ata_dev_printk(dev, KERN_WARNING,
+			       "device is on DMA blacklist, disabling DMA\n");
 
 	if (hs->flags & ATA_HOST_SIMPLEX) {
 		if (hs->simplex_claimed)
 			xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
 	}
+
 	if (ap->ops->mode_filter)
 		xfer_mask = ap->ops->mode_filter(ap, dev, xfer_mask);
 
-	ata_unpack_xfermask(xfer_mask, &dev->pio_mask, &dev->mwdma_mask,
-			    &dev->udma_mask);
+	ata_unpack_xfermask(xfer_mask, &dev->pio_mask,
+			    &dev->mwdma_mask, &dev->udma_mask);
 }
 
 /**
  *	ata_dev_set_xfermode - Issue SET FEATURES - XFER MODE command
- *	@ap: Port associated with device @dev
  *	@dev: Device to which command will be sent
  *
  *	Issue SET FEATURES - XFER MODE command to device @dev
@@ -2716,8 +3107,7 @@
  *	0 on success, AC_ERR_* mask otherwise.
  */
 
-static unsigned int ata_dev_set_xfermode(struct ata_port *ap,
-					 struct ata_device *dev)
+static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
 {
 	struct ata_taskfile tf;
 	unsigned int err_mask;
@@ -2725,14 +3115,14 @@
 	/* set up set-features taskfile */
 	DPRINTK("set features - xfer mode\n");
 
-	ata_tf_init(ap, &tf, dev->devno);
+	ata_tf_init(dev, &tf);
 	tf.command = ATA_CMD_SET_FEATURES;
 	tf.feature = SETFEATURES_XFER;
 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	tf.protocol = ATA_PROT_NODATA;
 	tf.nsect = dev->xfer_mode;
 
-	err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
 
 	DPRINTK("EXIT, err_mask=%x\n", err_mask);
 	return err_mask;
@@ -2740,7 +3130,6 @@
 
 /**
  *	ata_dev_init_params - Issue INIT DEV PARAMS command
- *	@ap: Port associated with device @dev
  *	@dev: Device to which command will be sent
  *	@heads: Number of heads (taskfile parameter)
  *	@sectors: Number of sectors (taskfile parameter)
@@ -2751,11 +3140,8 @@
  *	RETURNS:
  *	0 on success, AC_ERR_* mask otherwise.
  */
-
-static unsigned int ata_dev_init_params(struct ata_port *ap,
-					struct ata_device *dev,
-					u16 heads,
-					u16 sectors)
+static unsigned int ata_dev_init_params(struct ata_device *dev,
+					u16 heads, u16 sectors)
 {
 	struct ata_taskfile tf;
 	unsigned int err_mask;
@@ -2767,14 +3153,14 @@
 	/* set up init dev params taskfile */
 	DPRINTK("init dev params \n");
 
-	ata_tf_init(ap, &tf, dev->devno);
+	ata_tf_init(dev, &tf);
 	tf.command = ATA_CMD_INIT_DEV_PARAMS;
 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 	tf.protocol = ATA_PROT_NODATA;
 	tf.nsect = sectors;
 	tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
 
-	err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
 
 	DPRINTK("EXIT, err_mask=%x\n", err_mask);
 	return err_mask;
@@ -2957,6 +3343,7 @@
 	qc->n_elem = 1;
 	qc->orig_n_elem = 1;
 	qc->buf_virt = buf;
+	qc->nbytes = buflen;
 
 	sg = qc->__sg;
 	sg_init_one(sg, buf, buflen);
@@ -3140,134 +3527,6 @@
 }
 
 /**
- *	ata_poll_qc_complete - turn irq back on and finish qc
- *	@qc: Command to complete
- *	@err_mask: ATA status register content
- *
- *	LOCKING:
- *	None.  (grabs host lock)
- */
-
-void ata_poll_qc_complete(struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	ap->flags &= ~ATA_FLAG_NOINTR;
-	ata_irq_on(ap);
-	ata_qc_complete(qc);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-}
-
-/**
- *	ata_pio_poll - poll using PIO, depending on current state
- *	@ap: the target ata_port
- *
- *	LOCKING:
- *	None.  (executing in kernel thread context)
- *
- *	RETURNS:
- *	timeout value to use
- */
-
-static unsigned long ata_pio_poll(struct ata_port *ap)
-{
-	struct ata_queued_cmd *qc;
-	u8 status;
-	unsigned int poll_state = HSM_ST_UNKNOWN;
-	unsigned int reg_state = HSM_ST_UNKNOWN;
-
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	WARN_ON(qc == NULL);
-
-	switch (ap->hsm_task_state) {
-	case HSM_ST:
-	case HSM_ST_POLL:
-		poll_state = HSM_ST_POLL;
-		reg_state = HSM_ST;
-		break;
-	case HSM_ST_LAST:
-	case HSM_ST_LAST_POLL:
-		poll_state = HSM_ST_LAST_POLL;
-		reg_state = HSM_ST_LAST;
-		break;
-	default:
-		BUG();
-		break;
-	}
-
-	status = ata_chk_status(ap);
-	if (status & ATA_BUSY) {
-		if (time_after(jiffies, ap->pio_task_timeout)) {
-			qc->err_mask |= AC_ERR_TIMEOUT;
-			ap->hsm_task_state = HSM_ST_TMOUT;
-			return 0;
-		}
-		ap->hsm_task_state = poll_state;
-		return ATA_SHORT_PAUSE;
-	}
-
-	ap->hsm_task_state = reg_state;
-	return 0;
-}
-
-/**
- *	ata_pio_complete - check if drive is busy or idle
- *	@ap: the target ata_port
- *
- *	LOCKING:
- *	None.  (executing in kernel thread context)
- *
- *	RETURNS:
- *	Non-zero if qc completed, zero otherwise.
- */
-
-static int ata_pio_complete (struct ata_port *ap)
-{
-	struct ata_queued_cmd *qc;
-	u8 drv_stat;
-
-	/*
-	 * This is purely heuristic.  This is a fast path.  Sometimes when
-	 * we enter, BSY will be cleared in a chk-status or two.  If not,
-	 * the drive is probably seeking or something.  Snooze for a couple
-	 * msecs, then chk-status again.  If still busy, fall back to
-	 * HSM_ST_POLL state.
-	 */
-	drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
-	if (drv_stat & ATA_BUSY) {
-		msleep(2);
-		drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
-		if (drv_stat & ATA_BUSY) {
-			ap->hsm_task_state = HSM_ST_LAST_POLL;
-			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
-			return 0;
-		}
-	}
-
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	WARN_ON(qc == NULL);
-
-	drv_stat = ata_wait_idle(ap);
-	if (!ata_ok(drv_stat)) {
-		qc->err_mask |= __ac_err_mask(drv_stat);
-		ap->hsm_task_state = HSM_ST_ERR;
-		return 0;
-	}
-
-	ap->hsm_task_state = HSM_ST_IDLE;
-
-	WARN_ON(qc->err_mask);
-	ata_poll_qc_complete(qc);
-
-	/* another command may start at this point */
-
-	return 1;
-}
-
-
-/**
  *	swap_buf_le16 - swap halves of 16-bit words in place
  *	@buf:  Buffer to swap
  *	@buf_words:  Number of 16-bit words in buffer.
@@ -3291,7 +3550,7 @@
 
 /**
  *	ata_mmio_data_xfer - Transfer data by MMIO
- *	@ap: port to read/write
+ *	@adev: device for this I/O
  *	@buf: data buffer
  *	@buflen: buffer length
  *	@write_data: read/write
@@ -3302,9 +3561,10 @@
  *	Inherited from caller.
  */
 
-static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf,
-			       unsigned int buflen, int write_data)
+void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
+			unsigned int buflen, int write_data)
 {
+	struct ata_port *ap = adev->ap;
 	unsigned int i;
 	unsigned int words = buflen >> 1;
 	u16 *buf16 = (u16 *) buf;
@@ -3336,7 +3596,7 @@
 
 /**
  *	ata_pio_data_xfer - Transfer data by PIO
- *	@ap: port to read/write
+ *	@adev: device to target
  *	@buf: data buffer
  *	@buflen: buffer length
  *	@write_data: read/write
@@ -3347,9 +3607,10 @@
  *	Inherited from caller.
  */
 
-static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf,
-			      unsigned int buflen, int write_data)
+void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
+		       unsigned int buflen, int write_data)
 {
+	struct ata_port *ap = adev->ap;
 	unsigned int words = buflen >> 1;
 
 	/* Transfer multiple of 2 bytes */
@@ -3374,38 +3635,29 @@
 }
 
 /**
- *	ata_data_xfer - Transfer data from/to the data register.
- *	@ap: port to read/write
+ *	ata_pio_data_xfer_noirq - Transfer data by PIO
+ *	@adev: device to target
  *	@buf: data buffer
  *	@buflen: buffer length
- *	@do_write: read/write
+ *	@write_data: read/write
  *
- *	Transfer data from/to the device data register.
+ *	Transfer data from/to the device data register by PIO. Do the
+ *	transfer with interrupts disabled.
  *
  *	LOCKING:
  *	Inherited from caller.
  */
 
-static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
-			  unsigned int buflen, int do_write)
+void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
+				    unsigned int buflen, int write_data)
 {
-	/* Make the crap hardware pay the costs not the good stuff */
-	if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) {
-		unsigned long flags;
-		local_irq_save(flags);
-		if (ap->flags & ATA_FLAG_MMIO)
-			ata_mmio_data_xfer(ap, buf, buflen, do_write);
-		else
-			ata_pio_data_xfer(ap, buf, buflen, do_write);
-		local_irq_restore(flags);
-	} else {
-		if (ap->flags & ATA_FLAG_MMIO)
-			ata_mmio_data_xfer(ap, buf, buflen, do_write);
-		else
-			ata_pio_data_xfer(ap, buf, buflen, do_write);
-	}
+	unsigned long flags;
+	local_irq_save(flags);
+	ata_pio_data_xfer(adev, buf, buflen, write_data);
+	local_irq_restore(flags);
 }
 
+
 /**
  *	ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data.
  *	@qc: Command on going
@@ -3435,7 +3687,24 @@
 	page = nth_page(page, (offset >> PAGE_SHIFT));
 	offset %= PAGE_SIZE;
 
-	buf = kmap(page) + offset;
+	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+	if (PageHighMem(page)) {
+		unsigned long flags;
+
+		/* FIXME: use a bounce buffer */
+		local_irq_save(flags);
+		buf = kmap_atomic(page, KM_IRQ0);
+
+		/* do the actual data transfer */
+		ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
+
+		kunmap_atomic(buf, KM_IRQ0);
+		local_irq_restore(flags);
+	} else {
+		buf = page_address(page);
+		ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write);
+	}
 
 	qc->cursect++;
 	qc->cursg_ofs++;
@@ -3444,14 +3713,68 @@
 		qc->cursg++;
 		qc->cursg_ofs = 0;
 	}
+}
 
-	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+/**
+ *	ata_pio_sectors - Transfer one or many 512-byte sectors.
+ *	@qc: Command on going
+ *
+ *	Transfer one or many ATA_SECT_SIZE of data from/to the
+ *	ATA device for the DRQ request.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
 
-	/* do the actual data transfer */
-	do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
-	ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write);
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+	if (is_multi_taskfile(&qc->tf)) {
+		/* READ/WRITE MULTIPLE */
+		unsigned int nsect;
 
-	kunmap(page);
+		WARN_ON(qc->dev->multi_count == 0);
+
+		nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+		while (nsect--)
+			ata_pio_sector(qc);
+	} else
+		ata_pio_sector(qc);
+}
+
+/**
+ *	atapi_send_cdb - Write CDB bytes to hardware
+ *	@ap: Port to which ATAPI device is attached.
+ *	@qc: Taskfile currently active
+ *
+ *	When device has indicated its readiness to accept
+ *	a CDB, this function is called.  Send the CDB.
+ *
+ *	LOCKING:
+ *	caller.
+ */
+
+static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+{
+	/* send SCSI cdb */
+	DPRINTK("send cdb\n");
+	WARN_ON(qc->dev->cdb_len < 12);
+
+	ap->ops->data_xfer(qc->dev, qc->cdb, qc->dev->cdb_len, 1);
+	ata_altstatus(ap); /* flush */
+
+	switch (qc->tf.protocol) {
+	case ATA_PROT_ATAPI:
+		ap->hsm_task_state = HSM_ST;
+		break;
+	case ATA_PROT_ATAPI_NODATA:
+		ap->hsm_task_state = HSM_ST_LAST;
+		break;
+	case ATA_PROT_ATAPI_DMA:
+		ap->hsm_task_state = HSM_ST_LAST;
+		/* initiate bmdma */
+		ap->ops->bmdma_start(qc);
+		break;
+	}
 }
 
 /**
@@ -3492,11 +3815,11 @@
 		unsigned int i;
 
 		if (words) /* warning if bytes > 1 */
-			printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
-			       ap->id, bytes);
+			ata_dev_printk(qc->dev, KERN_WARNING,
+				       "%u bytes trailing data\n", bytes);
 
 		for (i = 0; i < words; i++)
-			ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write);
+			ap->ops->data_xfer(qc->dev, (unsigned char*)pad_buf, 2, do_write);
 
 		ap->hsm_task_state = HSM_ST_LAST;
 		return;
@@ -3517,7 +3840,24 @@
 	/* don't cross page boundaries */
 	count = min(count, (unsigned int)PAGE_SIZE - offset);
 
-	buf = kmap(page) + offset;
+	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
+
+	if (PageHighMem(page)) {
+		unsigned long flags;
+
+		/* FIXME: use bounce buffer */
+		local_irq_save(flags);
+		buf = kmap_atomic(page, KM_IRQ0);
+
+		/* do the actual data transfer */
+		ap->ops->data_xfer(qc->dev,  buf + offset, count, do_write);
+
+		kunmap_atomic(buf, KM_IRQ0);
+		local_irq_restore(flags);
+	} else {
+		buf = page_address(page);
+		ap->ops->data_xfer(qc->dev,  buf + offset, count, do_write);
+	}
 
 	bytes -= count;
 	qc->curbytes += count;
@@ -3528,13 +3868,6 @@
 		qc->cursg_ofs = 0;
 	}
 
-	DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-
-	/* do the actual data transfer */
-	ata_data_xfer(ap, buf, count, do_write);
-
-	kunmap(page);
-
 	if (bytes)
 		goto next_sg;
 }
@@ -3556,10 +3889,16 @@
 	unsigned int ireason, bc_lo, bc_hi, bytes;
 	int i_write, do_write = (qc->tf.flags & ATA_TFLAG_WRITE) ? 1 : 0;
 
-	ap->ops->tf_read(ap, &qc->tf);
-	ireason = qc->tf.nsect;
-	bc_lo = qc->tf.lbam;
-	bc_hi = qc->tf.lbah;
+	/* Abuse qc->result_tf for temp storage of intermediate TF
+	 * here to save some kernel stack usage.
+	 * For normal completion, qc->result_tf is not relevant. For
+	 * error, qc->result_tf is later overwritten by ata_qc_complete().
+	 * So, the correctness of qc->result_tf is not affected.
+	 */
+	ap->ops->tf_read(ap, &qc->result_tf);
+	ireason = qc->result_tf.nsect;
+	bc_lo = qc->result_tf.lbam;
+	bc_hi = qc->result_tf.lbah;
 	bytes = (bc_hi << 8) | bc_lo;
 
 	/* shall be cleared to zero, indicating xfer of data */
@@ -3571,310 +3910,368 @@
 	if (do_write != i_write)
 		goto err_out;
 
+	VPRINTK("ata%u: xfering %d bytes\n", ap->id, bytes);
+
 	__atapi_pio_bytes(qc, bytes);
 
 	return;
 
 err_out:
-	printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
-	      ap->id, dev->devno);
+	ata_dev_printk(dev, KERN_INFO, "ATAPI check failed\n");
 	qc->err_mask |= AC_ERR_HSM;
 	ap->hsm_task_state = HSM_ST_ERR;
 }
 
 /**
- *	ata_pio_block - start PIO on a block
+ *	ata_hsm_ok_in_wq - Check if the qc can be handled in the workqueue.
  *	@ap: the target ata_port
+ *	@qc: qc on going
  *
- *	LOCKING:
- *	None.  (executing in kernel thread context)
+ *	RETURNS:
+ *	1 if ok in workqueue, 0 otherwise.
  */
 
-static void ata_pio_block(struct ata_port *ap)
+static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *qc)
 {
-	struct ata_queued_cmd *qc;
+	if (qc->tf.flags & ATA_TFLAG_POLLING)
+		return 1;
+
+	if (ap->hsm_task_state == HSM_ST_FIRST) {
+		if (qc->tf.protocol == ATA_PROT_PIO &&
+		    (qc->tf.flags & ATA_TFLAG_WRITE))
+		    return 1;
+
+		if (is_atapi_taskfile(&qc->tf) &&
+		    !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+			return 1;
+	}
+
+	return 0;
+}
+
+/**
+ *	ata_hsm_qc_complete - finish a qc running on standard HSM
+ *	@qc: Command to complete
+ *	@in_wq: 1 if called from workqueue, 0 otherwise
+ *
+ *	Finish @qc which is running on standard HSM.
+ *
+ *	LOCKING:
+ *	If @in_wq is zero, spin_lock_irqsave(host_set lock).
+ *	Otherwise, none on entry and grabs host lock.
+ */
+static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned long flags;
+
+	if (ap->ops->error_handler) {
+		if (in_wq) {
+			spin_lock_irqsave(ap->lock, flags);
+
+			/* EH might have kicked in while host_set lock
+			 * is released.
+			 */
+			qc = ata_qc_from_tag(ap, qc->tag);
+			if (qc) {
+				if (likely(!(qc->err_mask & AC_ERR_HSM))) {
+					ata_irq_on(ap);
+					ata_qc_complete(qc);
+				} else
+					ata_port_freeze(ap);
+			}
+
+			spin_unlock_irqrestore(ap->lock, flags);
+		} else {
+			if (likely(!(qc->err_mask & AC_ERR_HSM)))
+				ata_qc_complete(qc);
+			else
+				ata_port_freeze(ap);
+		}
+	} else {
+		if (in_wq) {
+			spin_lock_irqsave(ap->lock, flags);
+			ata_irq_on(ap);
+			ata_qc_complete(qc);
+			spin_unlock_irqrestore(ap->lock, flags);
+		} else
+			ata_qc_complete(qc);
+	}
+
+	ata_altstatus(ap); /* flush */
+}
+
+/**
+ *	ata_hsm_move - move the HSM to the next state.
+ *	@ap: the target ata_port
+ *	@qc: qc on going
+ *	@status: current device status
+ *	@in_wq: 1 if called from workqueue, 0 otherwise
+ *
+ *	RETURNS:
+ *	1 when poll next status needed, 0 otherwise.
+ */
+int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+		 u8 status, int in_wq)
+{
+	unsigned long flags = 0;
+	int poll_next;
+
+	WARN_ON((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
+
+	/* Make sure ata_qc_issue_prot() does not throw things
+	 * like DMA polling into the workqueue. Notice that
+	 * in_wq is not equivalent to (qc->tf.flags & ATA_TFLAG_POLLING).
+	 */
+	WARN_ON(in_wq != ata_hsm_ok_in_wq(ap, qc));
+
+fsm_start:
+	DPRINTK("ata%u: protocol %d task_state %d (dev_stat 0x%X)\n",
+		ap->id, qc->tf.protocol, ap->hsm_task_state, status);
+
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		/* Send first data block or PACKET CDB */
+
+		/* If polling, we will stay in the work queue after
+		 * sending the data. Otherwise, interrupt handler
+		 * takes over after sending the data.
+		 */
+		poll_next = (qc->tf.flags & ATA_TFLAG_POLLING);
+
+		/* check device status */
+		if (unlikely((status & ATA_DRQ) == 0)) {
+			/* handle BSY=0, DRQ=0 as error */
+			if (likely(status & (ATA_ERR | ATA_DF)))
+				/* device stops HSM for abort/error */
+				qc->err_mask |= AC_ERR_DEV;
+			else
+				/* HSM violation. Let EH handle this */
+				qc->err_mask |= AC_ERR_HSM;
+
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* Device should not ask for data transfer (DRQ=1)
+		 * when it finds something wrong.
+		 * We ignore DRQ here and stop the HSM by
+		 * changing hsm_task_state to HSM_ST_ERR and
+		 * let the EH abort the command or reset the device.
+		 */
+		if (unlikely(status & (ATA_ERR | ATA_DF))) {
+			printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
+			       ap->id, status);
+			qc->err_mask |= AC_ERR_HSM;
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* Send the CDB (atapi) or the first data block (ata pio out).
+		 * During the state transition, interrupt handler shouldn't
+		 * be invoked before the data transfer is complete and
+		 * hsm_task_state is changed. Hence, the following locking.
+		 */
+		if (in_wq)
+			spin_lock_irqsave(ap->lock, flags);
+
+		if (qc->tf.protocol == ATA_PROT_PIO) {
+			/* PIO data out protocol.
+			 * send first data block.
+			 */
+
+			/* ata_pio_sectors() might change the state
+			 * to HSM_ST_LAST. so, the state is changed here
+			 * before ata_pio_sectors().
+			 */
+			ap->hsm_task_state = HSM_ST;
+			ata_pio_sectors(qc);
+			ata_altstatus(ap); /* flush */
+		} else
+			/* send CDB */
+			atapi_send_cdb(ap, qc);
+
+		if (in_wq)
+			spin_unlock_irqrestore(ap->lock, flags);
+
+		/* if polling, ata_pio_task() handles the rest.
+		 * otherwise, interrupt handler takes over from here.
+		 */
+		break;
+
+	case HSM_ST:
+		/* complete command or read/write the data register */
+		if (qc->tf.protocol == ATA_PROT_ATAPI) {
+			/* ATAPI PIO protocol */
+			if ((status & ATA_DRQ) == 0) {
+				/* No more data to transfer or device error.
+				 * Device error will be tagged in HSM_ST_LAST.
+				 */
+				ap->hsm_task_state = HSM_ST_LAST;
+				goto fsm_start;
+			}
+
+			/* Device should not ask for data transfer (DRQ=1)
+			 * when it finds something wrong.
+			 * We ignore DRQ here and stop the HSM by
+			 * changing hsm_task_state to HSM_ST_ERR and
+			 * let the EH abort the command or reset the device.
+			 */
+			if (unlikely(status & (ATA_ERR | ATA_DF))) {
+				printk(KERN_WARNING "ata%d: DRQ=1 with device error, dev_stat 0x%X\n",
+				       ap->id, status);
+				qc->err_mask |= AC_ERR_HSM;
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+
+			atapi_pio_bytes(qc);
+
+			if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
+				/* bad ireason reported by device */
+				goto fsm_start;
+
+		} else {
+			/* ATA PIO protocol */
+			if (unlikely((status & ATA_DRQ) == 0)) {
+				/* handle BSY=0, DRQ=0 as error */
+				if (likely(status & (ATA_ERR | ATA_DF)))
+					/* device stops HSM for abort/error */
+					qc->err_mask |= AC_ERR_DEV;
+				else
+					/* HSM violation. Let EH handle this */
+					qc->err_mask |= AC_ERR_HSM;
+
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+
+			/* For PIO reads, some devices may ask for
+			 * data transfer (DRQ=1) alone with ERR=1.
+			 * We respect DRQ here and transfer one
+			 * block of junk data before changing the
+			 * hsm_task_state to HSM_ST_ERR.
+			 *
+			 * For PIO writes, ERR=1 DRQ=1 doesn't make
+			 * sense since the data block has been
+			 * transferred to the device.
+			 */
+			if (unlikely(status & (ATA_ERR | ATA_DF))) {
+				/* data might be corrputed */
+				qc->err_mask |= AC_ERR_DEV;
+
+				if (!(qc->tf.flags & ATA_TFLAG_WRITE)) {
+					ata_pio_sectors(qc);
+					ata_altstatus(ap);
+					status = ata_wait_idle(ap);
+				}
+
+				if (status & (ATA_BUSY | ATA_DRQ))
+					qc->err_mask |= AC_ERR_HSM;
+
+				/* ata_pio_sectors() might change the
+				 * state to HSM_ST_LAST. so, the state
+				 * is changed after ata_pio_sectors().
+				 */
+				ap->hsm_task_state = HSM_ST_ERR;
+				goto fsm_start;
+			}
+
+			ata_pio_sectors(qc);
+
+			if (ap->hsm_task_state == HSM_ST_LAST &&
+			    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+				/* all data read */
+				ata_altstatus(ap);
+				status = ata_wait_idle(ap);
+				goto fsm_start;
+			}
+		}
+
+		ata_altstatus(ap); /* flush */
+		poll_next = 1;
+		break;
+
+	case HSM_ST_LAST:
+		if (unlikely(!ata_ok(status))) {
+			qc->err_mask |= __ac_err_mask(status);
+			ap->hsm_task_state = HSM_ST_ERR;
+			goto fsm_start;
+		}
+
+		/* no more data to transfer */
+		DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
+			ap->id, qc->dev->devno, status);
+
+		WARN_ON(qc->err_mask);
+
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		/* complete taskfile transaction */
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+
+	case HSM_ST_ERR:
+		/* make sure qc->err_mask is available to
+		 * know what's wrong and recover
+		 */
+		WARN_ON(qc->err_mask == 0);
+
+		ap->hsm_task_state = HSM_ST_IDLE;
+
+		/* complete taskfile transaction */
+		ata_hsm_qc_complete(qc, in_wq);
+
+		poll_next = 0;
+		break;
+	default:
+		poll_next = 0;
+		BUG();
+	}
+
+	return poll_next;
+}
+
+static void ata_pio_task(void *_data)
+{
+	struct ata_queued_cmd *qc = _data;
+	struct ata_port *ap = qc->ap;
 	u8 status;
+	int poll_next;
+
+fsm_start:
+	WARN_ON(ap->hsm_task_state == HSM_ST_IDLE);
 
 	/*
 	 * This is purely heuristic.  This is a fast path.
 	 * Sometimes when we enter, BSY will be cleared in
 	 * a chk-status or two.  If not, the drive is probably seeking
 	 * or something.  Snooze for a couple msecs, then
-	 * chk-status again.  If still busy, fall back to
-	 * HSM_ST_POLL state.
+	 * chk-status again.  If still busy, queue delayed work.
 	 */
 	status = ata_busy_wait(ap, ATA_BUSY, 5);
 	if (status & ATA_BUSY) {
 		msleep(2);
 		status = ata_busy_wait(ap, ATA_BUSY, 10);
 		if (status & ATA_BUSY) {
-			ap->hsm_task_state = HSM_ST_POLL;
-			ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
+			ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE);
 			return;
 		}
 	}
 
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	WARN_ON(qc == NULL);
+	/* move the HSM */
+	poll_next = ata_hsm_move(ap, qc, status, 1);
 
-	/* check error */
-	if (status & (ATA_ERR | ATA_DF)) {
-		qc->err_mask |= AC_ERR_DEV;
-		ap->hsm_task_state = HSM_ST_ERR;
-		return;
-	}
-
-	/* transfer data if any */
-	if (is_atapi_taskfile(&qc->tf)) {
-		/* DRQ=0 means no more data to transfer */
-		if ((status & ATA_DRQ) == 0) {
-			ap->hsm_task_state = HSM_ST_LAST;
-			return;
-		}
-
-		atapi_pio_bytes(qc);
-	} else {
-		/* handle BSY=0, DRQ=0 as error */
-		if ((status & ATA_DRQ) == 0) {
-			qc->err_mask |= AC_ERR_HSM;
-			ap->hsm_task_state = HSM_ST_ERR;
-			return;
-		}
-
-		ata_pio_sector(qc);
-	}
-
-	ata_altstatus(ap); /* flush */
-}
-
-static void ata_pio_error(struct ata_port *ap)
-{
-	struct ata_queued_cmd *qc;
-
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	WARN_ON(qc == NULL);
-
-	if (qc->tf.command != ATA_CMD_PACKET)
-		printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
-
-	/* make sure qc->err_mask is available to
-	 * know what's wrong and recover
+	/* another command or interrupt handler
+	 * may be running at this point.
 	 */
-	WARN_ON(qc->err_mask == 0);
-
-	ap->hsm_task_state = HSM_ST_IDLE;
-
-	ata_poll_qc_complete(qc);
-}
-
-static void ata_pio_task(void *_data)
-{
-	struct ata_port *ap = _data;
-	unsigned long timeout;
-	int qc_completed;
-
-fsm_start:
-	timeout = 0;
-	qc_completed = 0;
-
-	switch (ap->hsm_task_state) {
-	case HSM_ST_IDLE:
-		return;
-
-	case HSM_ST:
-		ata_pio_block(ap);
-		break;
-
-	case HSM_ST_LAST:
-		qc_completed = ata_pio_complete(ap);
-		break;
-
-	case HSM_ST_POLL:
-	case HSM_ST_LAST_POLL:
-		timeout = ata_pio_poll(ap);
-		break;
-
-	case HSM_ST_TMOUT:
-	case HSM_ST_ERR:
-		ata_pio_error(ap);
-		return;
-	}
-
-	if (timeout)
-		ata_port_queue_task(ap, ata_pio_task, ap, timeout);
-	else if (!qc_completed)
+	if (poll_next)
 		goto fsm_start;
 }
 
 /**
- *	atapi_packet_task - Write CDB bytes to hardware
- *	@_data: Port to which ATAPI device is attached.
- *
- *	When device has indicated its readiness to accept
- *	a CDB, this function is called.  Send the CDB.
- *	If DMA is to be performed, exit immediately.
- *	Otherwise, we are in polling mode, so poll
- *	status under operation succeeds or fails.
- *
- *	LOCKING:
- *	Kernel thread context (may sleep)
- */
-
-static void atapi_packet_task(void *_data)
-{
-	struct ata_port *ap = _data;
-	struct ata_queued_cmd *qc;
-	u8 status;
-
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	WARN_ON(qc == NULL);
-	WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
-
-	/* sleep-wait for BSY to clear */
-	DPRINTK("busy wait\n");
-	if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
-		qc->err_mask |= AC_ERR_TIMEOUT;
-		goto err_out;
-	}
-
-	/* make sure DRQ is set */
-	status = ata_chk_status(ap);
-	if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
-		qc->err_mask |= AC_ERR_HSM;
-		goto err_out;
-	}
-
-	/* send SCSI cdb */
-	DPRINTK("send cdb\n");
-	WARN_ON(qc->dev->cdb_len < 12);
-
-	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA ||
-	    qc->tf.protocol == ATA_PROT_ATAPI_NODATA) {
-		unsigned long flags;
-
-		/* Once we're done issuing command and kicking bmdma,
-		 * irq handler takes over.  To not lose irq, we need
-		 * to clear NOINTR flag before sending cdb, but
-		 * interrupt handler shouldn't be invoked before we're
-		 * finished.  Hence, the following locking.
-		 */
-		spin_lock_irqsave(&ap->host_set->lock, flags);
-		ap->flags &= ~ATA_FLAG_NOINTR;
-		ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
-		ata_altstatus(ap); /* flush */
-
-		if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
-			ap->ops->bmdma_start(qc);	/* initiate bmdma */
-		spin_unlock_irqrestore(&ap->host_set->lock, flags);
-	} else {
-		ata_data_xfer(ap, qc->cdb, qc->dev->cdb_len, 1);
-		ata_altstatus(ap); /* flush */
-
-		/* PIO commands are handled by polling */
-		ap->hsm_task_state = HSM_ST;
-		ata_port_queue_task(ap, ata_pio_task, ap, 0);
-	}
-
-	return;
-
-err_out:
-	ata_poll_qc_complete(qc);
-}
-
-/**
- *	ata_qc_timeout - Handle timeout of queued command
- *	@qc: Command that timed out
- *
- *	Some part of the kernel (currently, only the SCSI layer)
- *	has noticed that the active command on port @ap has not
- *	completed after a specified length of time.  Handle this
- *	condition by disabling DMA (if necessary) and completing
- *	transactions, with error if necessary.
- *
- *	This also handles the case of the "lost interrupt", where
- *	for some reason (possibly hardware bug, possibly driver bug)
- *	an interrupt was not delivered to the driver, even though the
- *	transaction completed successfully.
- *
- *	LOCKING:
- *	Inherited from SCSI layer (none, can sleep)
- */
-
-static void ata_qc_timeout(struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	struct ata_host_set *host_set = ap->host_set;
-	u8 host_stat = 0, drv_stat;
-	unsigned long flags;
-
-	DPRINTK("ENTER\n");
-
-	ap->hsm_task_state = HSM_ST_IDLE;
-
-	spin_lock_irqsave(&host_set->lock, flags);
-
-	switch (qc->tf.protocol) {
-
-	case ATA_PROT_DMA:
-	case ATA_PROT_ATAPI_DMA:
-		host_stat = ap->ops->bmdma_status(ap);
-
-		/* before we do anything else, clear DMA-Start bit */
-		ap->ops->bmdma_stop(qc);
-
-		/* fall through */
-
-	default:
-		ata_altstatus(ap);
-		drv_stat = ata_chk_status(ap);
-
-		/* ack bmdma irq events */
-		ap->ops->irq_clear(ap);
-
-		printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat, host_stat);
-
-		/* complete taskfile transaction */
-		qc->err_mask |= ac_err_mask(drv_stat);
-		break;
-	}
-
-	spin_unlock_irqrestore(&host_set->lock, flags);
-
-	ata_eh_qc_complete(qc);
-
-	DPRINTK("EXIT\n");
-}
-
-/**
- *	ata_eng_timeout - Handle timeout of queued command
- *	@ap: Port on which timed-out command is active
- *
- *	Some part of the kernel (currently, only the SCSI layer)
- *	has noticed that the active command on port @ap has not
- *	completed after a specified length of time.  Handle this
- *	condition by disabling DMA (if necessary) and completing
- *	transactions, with error if necessary.
- *
- *	This also handles the case of the "lost interrupt", where
- *	for some reason (possibly hardware bug, possibly driver bug)
- *	an interrupt was not delivered to the driver, even though the
- *	transaction completed successfully.
- *
- *	LOCKING:
- *	Inherited from SCSI layer (none, can sleep)
- */
-
-void ata_eng_timeout(struct ata_port *ap)
-{
-	DPRINTK("ENTER\n");
-
-	ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
-
-	DPRINTK("EXIT\n");
-}
-
-/**
  *	ata_qc_new - Request an available ATA command, for queueing
  *	@ap: Port associated with device @dev
  *	@dev: Device from whom we request an available command structure
@@ -3888,9 +4285,14 @@
 	struct ata_queued_cmd *qc = NULL;
 	unsigned int i;
 
-	for (i = 0; i < ATA_MAX_QUEUE; i++)
-		if (!test_and_set_bit(i, &ap->qactive)) {
-			qc = ata_qc_from_tag(ap, i);
+	/* no command while frozen */
+	if (unlikely(ap->flags & ATA_FLAG_FROZEN))
+		return NULL;
+
+	/* the last tag is reserved for internal command. */
+	for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
+		if (!test_and_set_bit(i, &ap->qc_allocated)) {
+			qc = __ata_qc_from_tag(ap, i);
 			break;
 		}
 
@@ -3902,16 +4304,15 @@
 
 /**
  *	ata_qc_new_init - Request an available ATA command, and initialize it
- *	@ap: Port associated with device @dev
  *	@dev: Device from whom we request an available command structure
  *
  *	LOCKING:
  *	None.
  */
 
-struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
-				      struct ata_device *dev)
+struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
 {
+	struct ata_port *ap = dev->ap;
 	struct ata_queued_cmd *qc;
 
 	qc = ata_qc_new(ap);
@@ -3946,36 +4347,153 @@
 	qc->flags = 0;
 	tag = qc->tag;
 	if (likely(ata_tag_valid(tag))) {
-		if (tag == ap->active_tag)
-			ap->active_tag = ATA_TAG_POISON;
 		qc->tag = ATA_TAG_POISON;
-		clear_bit(tag, &ap->qactive);
+		clear_bit(tag, &ap->qc_allocated);
 	}
 }
 
 void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
+	struct ata_port *ap = qc->ap;
+
 	WARN_ON(qc == NULL);	/* ata_qc_from_tag _might_ return NULL */
 	WARN_ON(!(qc->flags & ATA_QCFLAG_ACTIVE));
 
 	if (likely(qc->flags & ATA_QCFLAG_DMAMAP))
 		ata_sg_clean(qc);
 
+	/* command should be marked inactive atomically with qc completion */
+	if (qc->tf.protocol == ATA_PROT_NCQ)
+		ap->sactive &= ~(1 << qc->tag);
+	else
+		ap->active_tag = ATA_TAG_POISON;
+
 	/* atapi: mark qc as inactive to prevent the interrupt handler
 	 * from completing the command twice later, before the error handler
 	 * is called. (when rc != 0 and atapi request sense is needed)
 	 */
 	qc->flags &= ~ATA_QCFLAG_ACTIVE;
+	ap->qc_active &= ~(1 << qc->tag);
 
 	/* call completion callback */
 	qc->complete_fn(qc);
 }
 
+/**
+ *	ata_qc_complete - Complete an active ATA command
+ *	@qc: Command to complete
+ *	@err_mask: ATA Status register contents
+ *
+ *	Indicate to the mid and upper layers that an ATA
+ *	command has completed, with either an ok or not-ok status.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	/* XXX: New EH and old EH use different mechanisms to
+	 * synchronize EH with regular execution path.
+	 *
+	 * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED.
+	 * Normal execution path is responsible for not accessing a
+	 * failed qc.  libata core enforces the rule by returning NULL
+	 * from ata_qc_from_tag() for failed qcs.
+	 *
+	 * Old EH depends on ata_qc_complete() nullifying completion
+	 * requests if ATA_QCFLAG_EH_SCHEDULED is set.  Old EH does
+	 * not synchronize with interrupt handler.  Only PIO task is
+	 * taken care of.
+	 */
+	if (ap->ops->error_handler) {
+		WARN_ON(ap->flags & ATA_FLAG_FROZEN);
+
+		if (unlikely(qc->err_mask))
+			qc->flags |= ATA_QCFLAG_FAILED;
+
+		if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
+			if (!ata_tag_internal(qc->tag)) {
+				/* always fill result TF for failed qc */
+				ap->ops->tf_read(ap, &qc->result_tf);
+				ata_qc_schedule_eh(qc);
+				return;
+			}
+		}
+
+		/* read result TF if requested */
+		if (qc->flags & ATA_QCFLAG_RESULT_TF)
+			ap->ops->tf_read(ap, &qc->result_tf);
+
+		__ata_qc_complete(qc);
+	} else {
+		if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
+			return;
+
+		/* read result TF if failed or requested */
+		if (qc->err_mask || qc->flags & ATA_QCFLAG_RESULT_TF)
+			ap->ops->tf_read(ap, &qc->result_tf);
+
+		__ata_qc_complete(qc);
+	}
+}
+
+/**
+ *	ata_qc_complete_multiple - Complete multiple qcs successfully
+ *	@ap: port in question
+ *	@qc_active: new qc_active mask
+ *	@finish_qc: LLDD callback invoked before completing a qc
+ *
+ *	Complete in-flight commands.  This functions is meant to be
+ *	called from low-level driver's interrupt routine to complete
+ *	requests normally.  ap->qc_active and @qc_active is compared
+ *	and commands are completed accordingly.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Number of completed commands on success, -errno otherwise.
+ */
+int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+			     void (*finish_qc)(struct ata_queued_cmd *))
+{
+	int nr_done = 0;
+	u32 done_mask;
+	int i;
+
+	done_mask = ap->qc_active ^ qc_active;
+
+	if (unlikely(done_mask & qc_active)) {
+		ata_port_printk(ap, KERN_ERR, "illegal qc_active transition "
+				"(%08x->%08x)\n", ap->qc_active, qc_active);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ATA_MAX_QUEUE; i++) {
+		struct ata_queued_cmd *qc;
+
+		if (!(done_mask & (1 << i)))
+			continue;
+
+		if ((qc = ata_qc_from_tag(ap, i))) {
+			if (finish_qc)
+				finish_qc(qc);
+			ata_qc_complete(qc);
+			nr_done++;
+		}
+	}
+
+	return nr_done;
+}
+
 static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 
 	switch (qc->tf.protocol) {
+	case ATA_PROT_NCQ:
 	case ATA_PROT_DMA:
 	case ATA_PROT_ATAPI_DMA:
 		return 1;
@@ -4010,8 +4528,22 @@
 {
 	struct ata_port *ap = qc->ap;
 
-	qc->ap->active_tag = qc->tag;
+	/* Make sure only one non-NCQ command is outstanding.  The
+	 * check is skipped for old EH because it reuses active qc to
+	 * request ATAPI sense.
+	 */
+	WARN_ON(ap->ops->error_handler && ata_tag_valid(ap->active_tag));
+
+	if (qc->tf.protocol == ATA_PROT_NCQ) {
+		WARN_ON(ap->sactive & (1 << qc->tag));
+		ap->sactive |= 1 << qc->tag;
+	} else {
+		WARN_ON(ap->sactive);
+		ap->active_tag = qc->tag;
+	}
+
 	qc->flags |= ATA_QCFLAG_ACTIVE;
+	ap->qc_active |= 1 << qc->tag;
 
 	if (ata_should_dma_map(qc)) {
 		if (qc->flags & ATA_QCFLAG_SG) {
@@ -4061,43 +4593,105 @@
 {
 	struct ata_port *ap = qc->ap;
 
+	/* Use polling pio if the LLD doesn't handle
+	 * interrupt driven pio and atapi CDB interrupt.
+	 */
+	if (ap->flags & ATA_FLAG_PIO_POLLING) {
+		switch (qc->tf.protocol) {
+		case ATA_PROT_PIO:
+		case ATA_PROT_ATAPI:
+		case ATA_PROT_ATAPI_NODATA:
+			qc->tf.flags |= ATA_TFLAG_POLLING;
+			break;
+		case ATA_PROT_ATAPI_DMA:
+			if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+				/* see ata_dma_blacklisted() */
+				BUG();
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* select the device */
 	ata_dev_select(ap, qc->dev->devno, 1, 0);
 
+	/* start the command */
 	switch (qc->tf.protocol) {
 	case ATA_PROT_NODATA:
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_qc_set_polling(qc);
+
 		ata_tf_to_host(ap, &qc->tf);
+		ap->hsm_task_state = HSM_ST_LAST;
+
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_port_queue_task(ap, ata_pio_task, qc, 0);
+
 		break;
 
 	case ATA_PROT_DMA:
+		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+
 		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
 		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
 		ap->ops->bmdma_start(qc);	    /* initiate bmdma */
+		ap->hsm_task_state = HSM_ST_LAST;
 		break;
 
-	case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
-		ata_qc_set_polling(qc);
+	case ATA_PROT_PIO:
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_qc_set_polling(qc);
+
 		ata_tf_to_host(ap, &qc->tf);
-		ap->hsm_task_state = HSM_ST;
-		ata_port_queue_task(ap, ata_pio_task, ap, 0);
+
+		if (qc->tf.flags & ATA_TFLAG_WRITE) {
+			/* PIO data out protocol */
+			ap->hsm_task_state = HSM_ST_FIRST;
+			ata_port_queue_task(ap, ata_pio_task, qc, 0);
+
+			/* always send first data block using
+			 * the ata_pio_task() codepath.
+			 */
+		} else {
+			/* PIO data in protocol */
+			ap->hsm_task_state = HSM_ST;
+
+			if (qc->tf.flags & ATA_TFLAG_POLLING)
+				ata_port_queue_task(ap, ata_pio_task, qc, 0);
+
+			/* if polling, ata_pio_task() handles the rest.
+			 * otherwise, interrupt handler takes over from here.
+			 */
+		}
+
 		break;
 
 	case ATA_PROT_ATAPI:
-		ata_qc_set_polling(qc);
-		ata_tf_to_host(ap, &qc->tf);
-		ata_port_queue_task(ap, atapi_packet_task, ap, 0);
-		break;
-
 	case ATA_PROT_ATAPI_NODATA:
-		ap->flags |= ATA_FLAG_NOINTR;
+		if (qc->tf.flags & ATA_TFLAG_POLLING)
+			ata_qc_set_polling(qc);
+
 		ata_tf_to_host(ap, &qc->tf);
-		ata_port_queue_task(ap, atapi_packet_task, ap, 0);
+
+		ap->hsm_task_state = HSM_ST_FIRST;
+
+		/* send cdb by polling if no cdb interrupt */
+		if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
+		    (qc->tf.flags & ATA_TFLAG_POLLING))
+			ata_port_queue_task(ap, ata_pio_task, qc, 0);
 		break;
 
 	case ATA_PROT_ATAPI_DMA:
-		ap->flags |= ATA_FLAG_NOINTR;
+		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+
 		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
 		ap->ops->bmdma_setup(qc);	    /* set up bmdma */
-		ata_port_queue_task(ap, atapi_packet_task, ap, 0);
+		ap->hsm_task_state = HSM_ST_FIRST;
+
+		/* send cdb by polling if no cdb interrupt */
+		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+			ata_port_queue_task(ap, ata_pio_task, qc, 0);
 		break;
 
 	default:
@@ -4127,52 +4721,66 @@
 inline unsigned int ata_host_intr (struct ata_port *ap,
 				   struct ata_queued_cmd *qc)
 {
-	u8 status, host_stat;
+	u8 status, host_stat = 0;
 
-	switch (qc->tf.protocol) {
+	VPRINTK("ata%u: protocol %d task_state %d\n",
+		ap->id, qc->tf.protocol, ap->hsm_task_state);
 
-	case ATA_PROT_DMA:
-	case ATA_PROT_ATAPI_DMA:
-	case ATA_PROT_ATAPI:
-		/* check status of DMA engine */
-		host_stat = ap->ops->bmdma_status(ap);
-		VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
+	/* Check whether we are expecting interrupt in this state */
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		/* Some pre-ATAPI-4 devices assert INTRQ
+		 * at this state when ready to receive CDB.
+		 */
 
-		/* if it's not our irq... */
-		if (!(host_stat & ATA_DMA_INTR))
+		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+		 * The flag was turned on only for atapi devices.
+		 * No need to check is_atapi_taskfile(&qc->tf) again.
+		 */
+		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
 			goto idle_irq;
-
-		/* before we do anything else, clear DMA-Start bit */
-		ap->ops->bmdma_stop(qc);
-
-		/* fall through */
-
-	case ATA_PROT_ATAPI_NODATA:
-	case ATA_PROT_NODATA:
-		/* check altstatus */
-		status = ata_altstatus(ap);
-		if (status & ATA_BUSY)
-			goto idle_irq;
-
-		/* check main status, clearing INTRQ */
-		status = ata_chk_status(ap);
-		if (unlikely(status & ATA_BUSY))
-			goto idle_irq;
-		DPRINTK("ata%u: protocol %d (dev_stat 0x%X)\n",
-			ap->id, qc->tf.protocol, status);
-
-		/* ack bmdma irq events */
-		ap->ops->irq_clear(ap);
-
-		/* complete taskfile transaction */
-		qc->err_mask |= ac_err_mask(status);
-		ata_qc_complete(qc);
 		break;
+	case HSM_ST_LAST:
+		if (qc->tf.protocol == ATA_PROT_DMA ||
+		    qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+			/* check status of DMA engine */
+			host_stat = ap->ops->bmdma_status(ap);
+			VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
 
+			/* if it's not our irq... */
+			if (!(host_stat & ATA_DMA_INTR))
+				goto idle_irq;
+
+			/* before we do anything else, clear DMA-Start bit */
+			ap->ops->bmdma_stop(qc);
+
+			if (unlikely(host_stat & ATA_DMA_ERR)) {
+				/* error when transfering data to/from memory */
+				qc->err_mask |= AC_ERR_HOST_BUS;
+				ap->hsm_task_state = HSM_ST_ERR;
+			}
+		}
+		break;
+	case HSM_ST:
+		break;
 	default:
 		goto idle_irq;
 	}
 
+	/* check altstatus */
+	status = ata_altstatus(ap);
+	if (status & ATA_BUSY)
+		goto idle_irq;
+
+	/* check main status, clearing INTRQ */
+	status = ata_chk_status(ap);
+	if (unlikely(status & ATA_BUSY))
+		goto idle_irq;
+
+	/* ack bmdma irq events */
+	ap->ops->irq_clear(ap);
+
+	ata_hsm_move(ap, qc, status, 0);
 	return 1;	/* irq handled */
 
 idle_irq:
@@ -4181,7 +4789,7 @@
 #ifdef ATA_IRQ_TRAP
 	if ((ap->stats.idle_irq % 1000) == 0) {
 		ata_irq_ack(ap, 0); /* debug trap */
-		printk(KERN_WARNING "ata%d: irq trap\n", ap->id);
+		ata_port_printk(ap, KERN_WARNING, "irq trap\n");
 		return 1;
 	}
 #endif
@@ -4219,11 +4827,11 @@
 
 		ap = host_set->ports[i];
 		if (ap &&
-		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
+		    !(ap->flags & ATA_FLAG_DISABLED)) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (!(qc->tf.ctl & ATA_NIEN)) &&
+			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
 			    (qc->flags & ATA_QCFLAG_ACTIVE))
 				handled |= ata_host_intr(ap, qc);
 		}
@@ -4234,33 +4842,147 @@
 	return IRQ_RETVAL(handled);
 }
 
-
-/*
- * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
- * without filling any other registers
+/**
+ *	sata_scr_valid - test whether SCRs are accessible
+ *	@ap: ATA port to test SCR accessibility for
+ *
+ *	Test whether SCRs are accessible for @ap.
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	1 if SCRs are accessible, 0 otherwise.
  */
-static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
-			     u8 cmd)
+int sata_scr_valid(struct ata_port *ap)
 {
-	struct ata_taskfile tf;
-	int err;
-
-	ata_tf_init(ap, &tf, dev->devno);
-
-	tf.command = cmd;
-	tf.flags |= ATA_TFLAG_DEVICE;
-	tf.protocol = ATA_PROT_NODATA;
-
-	err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
-	if (err)
-		printk(KERN_ERR "%s: ata command failed: %d\n",
-				__FUNCTION__, err);
-
-	return err;
+	return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read;
 }
 
-static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
+/**
+ *	sata_scr_read - read SCR register of the specified port
+ *	@ap: ATA port to read SCR for
+ *	@reg: SCR to read
+ *	@val: Place to store read value
+ *
+ *	Read SCR register @reg of @ap into *@val.  This function is
+ *	guaranteed to succeed if the cable type of the port is SATA
+ *	and the port implements ->scr_read.
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	0 on success, negative errno on failure.
+ */
+int sata_scr_read(struct ata_port *ap, int reg, u32 *val)
 {
+	if (sata_scr_valid(ap)) {
+		*val = ap->ops->scr_read(ap, reg);
+		return 0;
+	}
+	return -EOPNOTSUPP;
+}
+
+/**
+ *	sata_scr_write - write SCR register of the specified port
+ *	@ap: ATA port to write SCR for
+ *	@reg: SCR to write
+ *	@val: value to write
+ *
+ *	Write @val to SCR register @reg of @ap.  This function is
+ *	guaranteed to succeed if the cable type of the port is SATA
+ *	and the port implements ->scr_read.
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	0 on success, negative errno on failure.
+ */
+int sata_scr_write(struct ata_port *ap, int reg, u32 val)
+{
+	if (sata_scr_valid(ap)) {
+		ap->ops->scr_write(ap, reg, val);
+		return 0;
+	}
+	return -EOPNOTSUPP;
+}
+
+/**
+ *	sata_scr_write_flush - write SCR register of the specified port and flush
+ *	@ap: ATA port to write SCR for
+ *	@reg: SCR to write
+ *	@val: value to write
+ *
+ *	This function is identical to sata_scr_write() except that this
+ *	function performs flush after writing to the register.
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	0 on success, negative errno on failure.
+ */
+int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val)
+{
+	if (sata_scr_valid(ap)) {
+		ap->ops->scr_write(ap, reg, val);
+		ap->ops->scr_read(ap, reg);
+		return 0;
+	}
+	return -EOPNOTSUPP;
+}
+
+/**
+ *	ata_port_online - test whether the given port is online
+ *	@ap: ATA port to test
+ *
+ *	Test whether @ap is online.  Note that this function returns 0
+ *	if online status of @ap cannot be obtained, so
+ *	ata_port_online(ap) != !ata_port_offline(ap).
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	1 if the port online status is available and online.
+ */
+int ata_port_online(struct ata_port *ap)
+{
+	u32 sstatus;
+
+	if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) == 0x3)
+		return 1;
+	return 0;
+}
+
+/**
+ *	ata_port_offline - test whether the given port is offline
+ *	@ap: ATA port to test
+ *
+ *	Test whether @ap is offline.  Note that this function returns
+ *	0 if offline status of @ap cannot be obtained, so
+ *	ata_port_online(ap) != !ata_port_offline(ap).
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	1 if the port offline status is available and offline.
+ */
+int ata_port_offline(struct ata_port *ap)
+{
+	u32 sstatus;
+
+	if (!sata_scr_read(ap, SCR_STATUS, &sstatus) && (sstatus & 0xf) != 0x3)
+		return 1;
+	return 0;
+}
+
+int ata_flush_cache(struct ata_device *dev)
+{
+	unsigned int err_mask;
 	u8 cmd;
 
 	if (!ata_try_flush_cache(dev))
@@ -4271,22 +4993,45 @@
 	else
 		cmd = ATA_CMD_FLUSH;
 
-	return ata_do_simple_cmd(ap, dev, cmd);
+	err_mask = ata_do_simple_cmd(dev, cmd);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR, "failed to flush cache\n");
+		return -EIO;
+	}
+
+	return 0;
 }
 
-static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
+static int ata_standby_drive(struct ata_device *dev)
 {
-	return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
+	unsigned int err_mask;
+
+	err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR, "failed to standby drive "
+			       "(err_mask=0x%x)\n", err_mask);
+		return -EIO;
+	}
+
+	return 0;
 }
 
-static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
+static int ata_start_drive(struct ata_device *dev)
 {
-	return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
+	unsigned int err_mask;
+
+	err_mask = ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR, "failed to start drive "
+			       "(err_mask=0x%x)\n", err_mask);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 /**
  *	ata_device_resume - wakeup a previously suspended devices
- *	@ap: port the device is connected to
  *	@dev: the device to resume
  *
  *	Kick the drive back into action, by sending it an idle immediate
@@ -4294,39 +5039,47 @@
  *	and host.
  *
  */
-int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
+int ata_device_resume(struct ata_device *dev)
 {
+	struct ata_port *ap = dev->ap;
+
 	if (ap->flags & ATA_FLAG_SUSPENDED) {
+		struct ata_device *failed_dev;
+
+		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
 		ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 200000);
+
 		ap->flags &= ~ATA_FLAG_SUSPENDED;
-		ata_set_mode(ap);
+		while (ata_set_mode(ap, &failed_dev))
+			ata_dev_disable(failed_dev);
 	}
-	if (!ata_dev_present(dev))
+	if (!ata_dev_enabled(dev))
 		return 0;
 	if (dev->class == ATA_DEV_ATA)
-		ata_start_drive(ap, dev);
+		ata_start_drive(dev);
 
 	return 0;
 }
 
 /**
  *	ata_device_suspend - prepare a device for suspend
- *	@ap: port the device is connected to
  *	@dev: the device to suspend
  *	@state: target power management state
  *
  *	Flush the cache on the drive, if appropriate, then issue a
  *	standbynow command.
  */
-int ata_device_suspend(struct ata_port *ap, struct ata_device *dev, pm_message_t state)
+int ata_device_suspend(struct ata_device *dev, pm_message_t state)
 {
-	if (!ata_dev_present(dev))
+	struct ata_port *ap = dev->ap;
+
+	if (!ata_dev_enabled(dev))
 		return 0;
 	if (dev->class == ATA_DEV_ATA)
-		ata_flush_cache(ap, dev);
+		ata_flush_cache(dev);
 
 	if (state.event != PM_EVENT_FREEZE)
-		ata_standby_drive(ap, dev);
+		ata_standby_drive(dev);
 	ap->flags |= ATA_FLAG_SUSPENDED;
 	return 0;
 }
@@ -4414,6 +5167,38 @@
 }
 
 /**
+ *	ata_dev_init - Initialize an ata_device structure
+ *	@dev: Device structure to initialize
+ *
+ *	Initialize @dev in preparation for probing.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ */
+void ata_dev_init(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->ap;
+	unsigned long flags;
+
+	/* SATA spd limit is bound to the first device */
+	ap->sata_spd_limit = ap->hw_sata_spd_limit;
+
+	/* High bits of dev->flags are used to record warm plug
+	 * requests which occur asynchronously.  Synchronize using
+	 * host_set lock.
+	 */
+	spin_lock_irqsave(ap->lock, flags);
+	dev->flags &= ~ATA_DFLAG_INIT_MASK;
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
+	       sizeof(*dev) - ATA_DEVICE_CLEAR_OFFSET);
+	dev->pio_mask = UINT_MAX;
+	dev->mwdma_mask = UINT_MAX;
+	dev->udma_mask = UINT_MAX;
+}
+
+/**
  *	ata_host_init - Initialize an ata_port structure
  *	@ap: Structure to initialize
  *	@host: associated SCSI mid-layer structure
@@ -4427,7 +5212,6 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-
 static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
 			  struct ata_host_set *host_set,
 			  const struct ata_probe_ent *ent, unsigned int port_no)
@@ -4440,7 +5224,8 @@
 	host->unique_id = ata_unique_id++;
 	host->max_cmd_len = 12;
 
-	ap->flags = ATA_FLAG_PORT_DISABLED;
+	ap->lock = &host_set->lock;
+	ap->flags = ATA_FLAG_DISABLED;
 	ap->id = host->unique_id;
 	ap->host = host;
 	ap->ctl = ATA_DEVCTL_OBS;
@@ -4454,19 +5239,35 @@
 	ap->udma_mask = ent->udma_mask;
 	ap->flags |= ent->host_flags;
 	ap->ops = ent->port_ops;
-	ap->cbl = ATA_CBL_NONE;
+	ap->hw_sata_spd_limit = UINT_MAX;
 	ap->active_tag = ATA_TAG_POISON;
 	ap->last_ctl = 0xFF;
 
+#if defined(ATA_VERBOSE_DEBUG)
+	/* turn on all debugging levels */
+	ap->msg_enable = 0x00FF;
+#elif defined(ATA_DEBUG)
+	ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR;
+#else
+	ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
+#endif
+
 	INIT_WORK(&ap->port_task, NULL, NULL);
+	INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap);
+	INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap);
 	INIT_LIST_HEAD(&ap->eh_done_q);
+	init_waitqueue_head(&ap->eh_wait_q);
+
+	/* set cable type */
+	ap->cbl = ATA_CBL_NONE;
+	if (ap->flags & ATA_FLAG_SATA)
+		ap->cbl = ATA_CBL_SATA;
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		struct ata_device *dev = &ap->device[i];
+		dev->ap = ap;
 		dev->devno = i;
-		dev->pio_mask = UINT_MAX;
-		dev->mwdma_mask = UINT_MAX;
-		dev->udma_mask = UINT_MAX;
+		ata_dev_init(dev);
 	}
 
 #ifdef ATA_IRQ_TRAP
@@ -4502,7 +5303,7 @@
 
 	DPRINTK("ENTER\n");
 
-	if (!ent->port_ops->probe_reset &&
+	if (!ent->port_ops->error_handler &&
 	    !(ent->host_flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST))) {
 		printk(KERN_ERR "ata%u: no reset mechanism available\n",
 		       port_no);
@@ -4515,7 +5316,7 @@
 
 	host->transportt = &ata_scsi_transport_template;
 
-	ap = (struct ata_port *) &host->hostdata[0];
+	ap = ata_shost_to_port(host);
 
 	ata_host_init(ap, host, host_set, ent, port_no);
 
@@ -4548,12 +5349,12 @@
  *	RETURNS:
  *	Number of ports registered.  Zero on error (no ports registered).
  */
-
 int ata_device_add(const struct ata_probe_ent *ent)
 {
 	unsigned int count = 0, i;
 	struct device *dev = ent->dev;
 	struct ata_host_set *host_set;
+	int rc;
 
 	DPRINTK("ENTER\n");
 	/* alloc a container for our list of ATA ports (buses) */
@@ -4586,18 +5387,18 @@
 				(ap->pio_mask << ATA_SHIFT_PIO);
 
 		/* print per-port info to dmesg */
-		printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX "
-				 "bmdma 0x%lX irq %lu\n",
-			ap->id,
-			ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
-			ata_mode_string(xfer_mode_mask),
-	       		ap->ioaddr.cmd_addr,
-	       		ap->ioaddr.ctl_addr,
-	       		ap->ioaddr.bmdma_addr,
-	       		ent->irq);
+		ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX "
+				"ctl 0x%lX bmdma 0x%lX irq %lu\n",
+				ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
+				ata_mode_string(xfer_mode_mask),
+				ap->ioaddr.cmd_addr,
+				ap->ioaddr.ctl_addr,
+				ap->ioaddr.bmdma_addr,
+				ent->irq);
 
 		ata_chk_status(ap);
 		host_set->ops->irq_clear(ap);
+		ata_eh_freeze_port(ap);	/* freeze port before requesting IRQ */
 		count++;
 	}
 
@@ -4605,41 +5406,72 @@
 		goto err_free_ret;
 
 	/* obtain irq, that is shared between channels */
-	if (request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
-			DRV_NAME, host_set))
+	rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags,
+			 DRV_NAME, host_set);
+	if (rc) {
+		dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n",
+			   ent->irq, rc);
 		goto err_out;
+	}
 
 	/* perform each probe synchronously */
 	DPRINTK("probe begin\n");
 	for (i = 0; i < count; i++) {
 		struct ata_port *ap;
+		u32 scontrol;
 		int rc;
 
 		ap = host_set->ports[i];
 
-		DPRINTK("ata%u: bus probe begin\n", ap->id);
-		rc = ata_bus_probe(ap);
-		DPRINTK("ata%u: bus probe end\n", ap->id);
-
-		if (rc) {
-			/* FIXME: do something useful here?
-			 * Current libata behavior will
-			 * tear down everything when
-			 * the module is removed
-			 * or the h/w is unplugged.
-			 */
+		/* init sata_spd_limit to the current value */
+		if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
+			int spd = (scontrol >> 4) & 0xf;
+			ap->hw_sata_spd_limit &= (1 << spd) - 1;
 		}
+		ap->sata_spd_limit = ap->hw_sata_spd_limit;
 
 		rc = scsi_add_host(ap->host, dev);
 		if (rc) {
-			printk(KERN_ERR "ata%u: scsi_add_host failed\n",
-			       ap->id);
+			ata_port_printk(ap, KERN_ERR, "scsi_add_host failed\n");
 			/* FIXME: do something useful here */
 			/* FIXME: handle unconditional calls to
 			 * scsi_scan_host and ata_host_remove, below,
 			 * at the very least
 			 */
 		}
+
+		if (ap->ops->error_handler) {
+			unsigned long flags;
+
+			ata_port_probe(ap);
+
+			/* kick EH for boot probing */
+			spin_lock_irqsave(ap->lock, flags);
+
+			ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1;
+			ap->eh_info.action |= ATA_EH_SOFTRESET;
+
+			ap->flags |= ATA_FLAG_LOADING;
+			ata_port_schedule_eh(ap);
+
+			spin_unlock_irqrestore(ap->lock, flags);
+
+			/* wait for EH to finish */
+			ata_port_wait_eh(ap);
+		} else {
+			DPRINTK("ata%u: bus probe begin\n", ap->id);
+			rc = ata_bus_probe(ap);
+			DPRINTK("ata%u: bus probe end\n", ap->id);
+
+			if (rc) {
+				/* FIXME: do something useful here?
+				 * Current libata behavior will
+				 * tear down everything when
+				 * the module is removed
+				 * or the h/w is unplugged.
+				 */
+			}
+		}
 	}
 
 	/* probes are done, now scan each port's disk(s) */
@@ -4667,6 +5499,63 @@
 }
 
 /**
+ *	ata_port_detach - Detach ATA port in prepration of device removal
+ *	@ap: ATA port to be detached
+ *
+ *	Detach all ATA devices and the associated SCSI devices of @ap;
+ *	then, remove the associated SCSI host.  @ap is guaranteed to
+ *	be quiescent on return from this function.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+void ata_port_detach(struct ata_port *ap)
+{
+	unsigned long flags;
+	int i;
+
+	if (!ap->ops->error_handler)
+		return;
+
+	/* tell EH we're leaving & flush EH */
+	spin_lock_irqsave(ap->lock, flags);
+	ap->flags |= ATA_FLAG_UNLOADING;
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	ata_port_wait_eh(ap);
+
+	/* EH is now guaranteed to see UNLOADING, so no new device
+	 * will be attached.  Disable all existing devices.
+	 */
+	spin_lock_irqsave(ap->lock, flags);
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		ata_dev_disable(&ap->device[i]);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	/* Final freeze & EH.  All in-flight commands are aborted.  EH
+	 * will be skipped and retrials will be terminated with bad
+	 * target.
+	 */
+	spin_lock_irqsave(ap->lock, flags);
+	ata_port_freeze(ap);	/* won't be thawed */
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	ata_port_wait_eh(ap);
+
+	/* Flush hotplug task.  The sequence is similar to
+	 * ata_port_flush_task().
+	 */
+	flush_workqueue(ata_aux_wq);
+	cancel_delayed_work(&ap->hotplug_task);
+	flush_workqueue(ata_aux_wq);
+
+	/* remove the associated SCSI host */
+	scsi_remove_host(ap->host);
+}
+
+/**
  *	ata_host_set_remove - PCI layer callback for device removal
  *	@host_set: ATA host set that was removed
  *
@@ -4679,18 +5568,15 @@
 
 void ata_host_set_remove(struct ata_host_set *host_set)
 {
-	struct ata_port *ap;
 	unsigned int i;
 
-	for (i = 0; i < host_set->n_ports; i++) {
-		ap = host_set->ports[i];
-		scsi_remove_host(ap->host);
-	}
+	for (i = 0; i < host_set->n_ports; i++)
+		ata_port_detach(host_set->ports[i]);
 
 	free_irq(host_set->irq, host_set);
 
 	for (i = 0; i < host_set->n_ports; i++) {
-		ap = host_set->ports[i];
+		struct ata_port *ap = host_set->ports[i];
 
 		ata_scsi_release(ap->host);
 
@@ -4728,15 +5614,12 @@
 
 int ata_scsi_release(struct Scsi_Host *host)
 {
-	struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
-	int i;
+	struct ata_port *ap = ata_shost_to_port(host);
 
 	DPRINTK("ENTER\n");
 
 	ap->ops->port_disable(ap);
 	ata_host_remove(ap, 0);
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		kfree(ap->device[i].id);
 
 	DPRINTK("EXIT\n");
 	return 1;
@@ -4796,8 +5679,12 @@
 {
 	struct device *dev = pci_dev_to_dev(pdev);
 	struct ata_host_set *host_set = dev_get_drvdata(dev);
+	struct ata_host_set *host_set2 = host_set->next;
 
 	ata_host_set_remove(host_set);
+	if (host_set2)
+		ata_host_set_remove(host_set2);
+
 	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	dev_set_drvdata(dev, NULL);
@@ -4858,10 +5745,17 @@
 
 static int __init ata_init(void)
 {
+	ata_probe_timeout *= HZ;
 	ata_wq = create_workqueue("ata");
 	if (!ata_wq)
 		return -ENOMEM;
 
+	ata_aux_wq = create_singlethread_workqueue("ata_aux");
+	if (!ata_aux_wq) {
+		destroy_workqueue(ata_wq);
+		return -ENOMEM;
+	}
+
 	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
 	return 0;
 }
@@ -4869,13 +5763,14 @@
 static void __exit ata_exit(void)
 {
 	destroy_workqueue(ata_wq);
+	destroy_workqueue(ata_aux_wq);
 }
 
 module_init(ata_init);
 module_exit(ata_exit);
 
 static unsigned long ratelimit_time;
-static spinlock_t ata_ratelimit_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ata_ratelimit_lock);
 
 int ata_ratelimit(void)
 {
@@ -4895,6 +5790,52 @@
 	return rc;
 }
 
+/**
+ *	ata_wait_register - wait until register value changes
+ *	@reg: IO-mapped register
+ *	@mask: Mask to apply to read register value
+ *	@val: Wait condition
+ *	@interval_msec: polling interval in milliseconds
+ *	@timeout_msec: timeout in milliseconds
+ *
+ *	Waiting for some bits of register to change is a common
+ *	operation for ATA controllers.  This function reads 32bit LE
+ *	IO-mapped register @reg and tests for the following condition.
+ *
+ *	(*@reg & mask) != val
+ *
+ *	If the condition is met, it returns; otherwise, the process is
+ *	repeated after @interval_msec until timeout.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep)
+ *
+ *	RETURNS:
+ *	The final register value.
+ */
+u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+		      unsigned long interval_msec,
+		      unsigned long timeout_msec)
+{
+	unsigned long timeout;
+	u32 tmp;
+
+	tmp = ioread32(reg);
+
+	/* Calculate timeout _after_ the first read to make sure
+	 * preceding writes reach the controller before starting to
+	 * eat away the timeout.
+	 */
+	timeout = jiffies + (timeout_msec * HZ) / 1000;
+
+	while ((tmp & mask) == val && time_before(jiffies, timeout)) {
+		msleep(interval_msec);
+		tmp = ioread32(reg);
+	}
+
+	return tmp;
+}
+
 /*
  * libata is essentially a library of internal helper functions for
  * low-level ATA host controller drivers.  As such, the API/ABI is
@@ -4902,15 +5843,20 @@
  * Do not depend on ABI/API stability.
  */
 
+EXPORT_SYMBOL_GPL(sata_deb_timing_boot);
+EXPORT_SYMBOL_GPL(sata_deb_timing_eh);
+EXPORT_SYMBOL_GPL(sata_deb_timing_before_fsrst);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_device_add);
+EXPORT_SYMBOL_GPL(ata_port_detach);
 EXPORT_SYMBOL_GPL(ata_host_set_remove);
 EXPORT_SYMBOL_GPL(ata_sg_init);
 EXPORT_SYMBOL_GPL(ata_sg_init_one);
-EXPORT_SYMBOL_GPL(__ata_qc_complete);
+EXPORT_SYMBOL_GPL(ata_hsm_move);
+EXPORT_SYMBOL_GPL(ata_qc_complete);
+EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
 EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
-EXPORT_SYMBOL_GPL(ata_eng_timeout);
 EXPORT_SYMBOL_GPL(ata_tf_load);
 EXPORT_SYMBOL_GPL(ata_tf_read);
 EXPORT_SYMBOL_GPL(ata_noop_dev_select);
@@ -4924,6 +5870,9 @@
 EXPORT_SYMBOL_GPL(ata_port_stop);
 EXPORT_SYMBOL_GPL(ata_host_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
+EXPORT_SYMBOL_GPL(ata_mmio_data_xfer);
+EXPORT_SYMBOL_GPL(ata_pio_data_xfer);
+EXPORT_SYMBOL_GPL(ata_pio_data_xfer_noirq);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
 EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
 EXPORT_SYMBOL_GPL(ata_bmdma_setup);
@@ -4931,33 +5880,46 @@
 EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
 EXPORT_SYMBOL_GPL(ata_bmdma_status);
 EXPORT_SYMBOL_GPL(ata_bmdma_stop);
+EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
+EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
+EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
+EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
+EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
 EXPORT_SYMBOL_GPL(ata_port_probe);
+EXPORT_SYMBOL_GPL(sata_set_spd);
+EXPORT_SYMBOL_GPL(sata_phy_debounce);
+EXPORT_SYMBOL_GPL(sata_phy_resume);
 EXPORT_SYMBOL_GPL(sata_phy_reset);
 EXPORT_SYMBOL_GPL(__sata_phy_reset);
 EXPORT_SYMBOL_GPL(ata_bus_reset);
-EXPORT_SYMBOL_GPL(ata_std_probeinit);
+EXPORT_SYMBOL_GPL(ata_std_prereset);
 EXPORT_SYMBOL_GPL(ata_std_softreset);
 EXPORT_SYMBOL_GPL(sata_std_hardreset);
 EXPORT_SYMBOL_GPL(ata_std_postreset);
-EXPORT_SYMBOL_GPL(ata_std_probe_reset);
-EXPORT_SYMBOL_GPL(ata_drive_probe_reset);
 EXPORT_SYMBOL_GPL(ata_dev_revalidate);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_pair);
 EXPORT_SYMBOL_GPL(ata_port_disable);
 EXPORT_SYMBOL_GPL(ata_ratelimit);
+EXPORT_SYMBOL_GPL(ata_wait_register);
 EXPORT_SYMBOL_GPL(ata_busy_sleep);
 EXPORT_SYMBOL_GPL(ata_port_queue_task);
 EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
 EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
 EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
+EXPORT_SYMBOL_GPL(ata_scsi_slave_destroy);
+EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
 EXPORT_SYMBOL_GPL(ata_scsi_release);
 EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(sata_scr_valid);
+EXPORT_SYMBOL_GPL(sata_scr_read);
+EXPORT_SYMBOL_GPL(sata_scr_write);
+EXPORT_SYMBOL_GPL(sata_scr_write_flush);
+EXPORT_SYMBOL_GPL(ata_port_online);
+EXPORT_SYMBOL_GPL(ata_port_offline);
 EXPORT_SYMBOL_GPL(ata_id_string);
 EXPORT_SYMBOL_GPL(ata_id_c_string);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
-EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
-EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 
 EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
 EXPORT_SYMBOL_GPL(ata_timing_compute);
@@ -4979,3 +5941,13 @@
 EXPORT_SYMBOL_GPL(ata_device_resume);
 EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
 EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
+
+EXPORT_SYMBOL_GPL(ata_eng_timeout);
+EXPORT_SYMBOL_GPL(ata_port_schedule_eh);
+EXPORT_SYMBOL_GPL(ata_port_abort);
+EXPORT_SYMBOL_GPL(ata_port_freeze);
+EXPORT_SYMBOL_GPL(ata_eh_freeze_port);
+EXPORT_SYMBOL_GPL(ata_eh_thaw_port);
+EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
+EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
+EXPORT_SYMBOL_GPL(ata_do_eh);
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
new file mode 100644
index 0000000..bf5a72a
--- /dev/null
+++ b/drivers/scsi/libata-eh.c
@@ -0,0 +1,1918 @@
+/*
+ *  libata-eh.c - libata error handling
+ *
+ *  Maintained by:  Jeff Garzik <jgarzik@pobox.com>
+ *    		    Please ALWAYS copy linux-ide@vger.kernel.org
+ *		    on emails.
+ *
+ *  Copyright 2006 Tejun Heo <htejun@gmail.com>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License as
+ *  published by the Free Software Foundation; either version 2, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; see the file COPYING.  If not, write to
+ *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
+ *  USA.
+ *
+ *
+ *  libata documentation is available via 'make {ps|pdf}docs',
+ *  as Documentation/DocBook/libata.*
+ *
+ *  Hardware documentation available from http://www.t13.org/ and
+ *  http://www.sata-io.org/
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include "scsi_transport_api.h"
+
+#include <linux/libata.h>
+
+#include "libata.h"
+
+static void __ata_port_freeze(struct ata_port *ap);
+static void ata_eh_finish(struct ata_port *ap);
+
+static void ata_ering_record(struct ata_ering *ering, int is_io,
+			     unsigned int err_mask)
+{
+	struct ata_ering_entry *ent;
+
+	WARN_ON(!err_mask);
+
+	ering->cursor++;
+	ering->cursor %= ATA_ERING_SIZE;
+
+	ent = &ering->ring[ering->cursor];
+	ent->is_io = is_io;
+	ent->err_mask = err_mask;
+	ent->timestamp = get_jiffies_64();
+}
+
+static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering)
+{
+	struct ata_ering_entry *ent = &ering->ring[ering->cursor];
+	if (!ent->err_mask)
+		return NULL;
+	return ent;
+}
+
+static int ata_ering_map(struct ata_ering *ering,
+			 int (*map_fn)(struct ata_ering_entry *, void *),
+			 void *arg)
+{
+	int idx, rc = 0;
+	struct ata_ering_entry *ent;
+
+	idx = ering->cursor;
+	do {
+		ent = &ering->ring[idx];
+		if (!ent->err_mask)
+			break;
+		rc = map_fn(ent, arg);
+		if (rc)
+			break;
+		idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE;
+	} while (idx != ering->cursor);
+
+	return rc;
+}
+
+static unsigned int ata_eh_dev_action(struct ata_device *dev)
+{
+	struct ata_eh_context *ehc = &dev->ap->eh_context;
+
+	return ehc->i.action | ehc->i.dev_action[dev->devno];
+}
+
+static void ata_eh_clear_action(struct ata_device *dev,
+				struct ata_eh_info *ehi, unsigned int action)
+{
+	int i;
+
+	if (!dev) {
+		ehi->action &= ~action;
+		for (i = 0; i < ATA_MAX_DEVICES; i++)
+			ehi->dev_action[i] &= ~action;
+	} else {
+		/* doesn't make sense for port-wide EH actions */
+		WARN_ON(!(action & ATA_EH_PERDEV_MASK));
+
+		/* break ehi->action into ehi->dev_action */
+		if (ehi->action & action) {
+			for (i = 0; i < ATA_MAX_DEVICES; i++)
+				ehi->dev_action[i] |= ehi->action & action;
+			ehi->action &= ~action;
+		}
+
+		/* turn off the specified per-dev action */
+		ehi->dev_action[dev->devno] &= ~action;
+	}
+}
+
+/**
+ *	ata_scsi_timed_out - SCSI layer time out callback
+ *	@cmd: timed out SCSI command
+ *
+ *	Handles SCSI layer timeout.  We race with normal completion of
+ *	the qc for @cmd.  If the qc is already gone, we lose and let
+ *	the scsi command finish (EH_HANDLED).  Otherwise, the qc has
+ *	timed out and EH should be invoked.  Prevent ata_qc_complete()
+ *	from finishing it by setting EH_SCHEDULED and return
+ *	EH_NOT_HANDLED.
+ *
+ *	TODO: kill this function once old EH is gone.
+ *
+ *	LOCKING:
+ *	Called from timer context
+ *
+ *	RETURNS:
+ *	EH_HANDLED or EH_NOT_HANDLED
+ */
+enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
+{
+	struct Scsi_Host *host = cmd->device->host;
+	struct ata_port *ap = ata_shost_to_port(host);
+	unsigned long flags;
+	struct ata_queued_cmd *qc;
+	enum scsi_eh_timer_return ret;
+
+	DPRINTK("ENTER\n");
+
+	if (ap->ops->error_handler) {
+		ret = EH_NOT_HANDLED;
+		goto out;
+	}
+
+	ret = EH_HANDLED;
+	spin_lock_irqsave(ap->lock, flags);
+	qc = ata_qc_from_tag(ap, ap->active_tag);
+	if (qc) {
+		WARN_ON(qc->scsicmd != cmd);
+		qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
+		qc->err_mask |= AC_ERR_TIMEOUT;
+		ret = EH_NOT_HANDLED;
+	}
+	spin_unlock_irqrestore(ap->lock, flags);
+
+ out:
+	DPRINTK("EXIT, ret=%d\n", ret);
+	return ret;
+}
+
+/**
+ *	ata_scsi_error - SCSI layer error handler callback
+ *	@host: SCSI host on which error occurred
+ *
+ *	Handles SCSI-layer-thrown error events.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
+ *
+ *	RETURNS:
+ *	Zero.
+ */
+void ata_scsi_error(struct Scsi_Host *host)
+{
+	struct ata_port *ap = ata_shost_to_port(host);
+	spinlock_t *ap_lock = ap->lock;
+	int i, repeat_cnt = ATA_EH_MAX_REPEAT;
+	unsigned long flags;
+
+	DPRINTK("ENTER\n");
+
+	/* synchronize with port task */
+	ata_port_flush_task(ap);
+
+	/* synchronize with host_set lock and sort out timeouts */
+
+	/* For new EH, all qcs are finished in one of three ways -
+	 * normal completion, error completion, and SCSI timeout.
+	 * Both cmpletions can race against SCSI timeout.  When normal
+	 * completion wins, the qc never reaches EH.  When error
+	 * completion wins, the qc has ATA_QCFLAG_FAILED set.
+	 *
+	 * When SCSI timeout wins, things are a bit more complex.
+	 * Normal or error completion can occur after the timeout but
+	 * before this point.  In such cases, both types of
+	 * completions are honored.  A scmd is determined to have
+	 * timed out iff its associated qc is active and not failed.
+	 */
+	if (ap->ops->error_handler) {
+		struct scsi_cmnd *scmd, *tmp;
+		int nr_timedout = 0;
+
+		spin_lock_irqsave(ap_lock, flags);
+
+		list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
+			struct ata_queued_cmd *qc;
+
+			for (i = 0; i < ATA_MAX_QUEUE; i++) {
+				qc = __ata_qc_from_tag(ap, i);
+				if (qc->flags & ATA_QCFLAG_ACTIVE &&
+				    qc->scsicmd == scmd)
+					break;
+			}
+
+			if (i < ATA_MAX_QUEUE) {
+				/* the scmd has an associated qc */
+				if (!(qc->flags & ATA_QCFLAG_FAILED)) {
+					/* which hasn't failed yet, timeout */
+					qc->err_mask |= AC_ERR_TIMEOUT;
+					qc->flags |= ATA_QCFLAG_FAILED;
+					nr_timedout++;
+				}
+			} else {
+				/* Normal completion occurred after
+				 * SCSI timeout but before this point.
+				 * Successfully complete it.
+				 */
+				scmd->retries = scmd->allowed;
+				scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+			}
+		}
+
+		/* If we have timed out qcs.  They belong to EH from
+		 * this point but the state of the controller is
+		 * unknown.  Freeze the port to make sure the IRQ
+		 * handler doesn't diddle with those qcs.  This must
+		 * be done atomically w.r.t. setting QCFLAG_FAILED.
+		 */
+		if (nr_timedout)
+			__ata_port_freeze(ap);
+
+		spin_unlock_irqrestore(ap_lock, flags);
+	} else
+		spin_unlock_wait(ap_lock);
+
+ repeat:
+	/* invoke error handler */
+	if (ap->ops->error_handler) {
+		/* fetch & clear EH info */
+		spin_lock_irqsave(ap_lock, flags);
+
+		memset(&ap->eh_context, 0, sizeof(ap->eh_context));
+		ap->eh_context.i = ap->eh_info;
+		memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+
+		ap->flags |= ATA_FLAG_EH_IN_PROGRESS;
+		ap->flags &= ~ATA_FLAG_EH_PENDING;
+
+		spin_unlock_irqrestore(ap_lock, flags);
+
+		/* invoke EH.  if unloading, just finish failed qcs */
+		if (!(ap->flags & ATA_FLAG_UNLOADING))
+			ap->ops->error_handler(ap);
+		else
+			ata_eh_finish(ap);
+
+		/* Exception might have happend after ->error_handler
+		 * recovered the port but before this point.  Repeat
+		 * EH in such case.
+		 */
+		spin_lock_irqsave(ap_lock, flags);
+
+		if (ap->flags & ATA_FLAG_EH_PENDING) {
+			if (--repeat_cnt) {
+				ata_port_printk(ap, KERN_INFO,
+					"EH pending after completion, "
+					"repeating EH (cnt=%d)\n", repeat_cnt);
+				spin_unlock_irqrestore(ap_lock, flags);
+				goto repeat;
+			}
+			ata_port_printk(ap, KERN_ERR, "EH pending after %d "
+					"tries, giving up\n", ATA_EH_MAX_REPEAT);
+		}
+
+		/* this run is complete, make sure EH info is clear */
+		memset(&ap->eh_info, 0, sizeof(ap->eh_info));
+
+		/* Clear host_eh_scheduled while holding ap_lock such
+		 * that if exception occurs after this point but
+		 * before EH completion, SCSI midlayer will
+		 * re-initiate EH.
+		 */
+		host->host_eh_scheduled = 0;
+
+		spin_unlock_irqrestore(ap_lock, flags);
+	} else {
+		WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
+		ap->ops->eng_timeout(ap);
+	}
+
+	/* finish or retry handled scmd's and clean up */
+	WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
+
+	scsi_eh_flush_done_q(&ap->eh_done_q);
+
+	/* clean up */
+	spin_lock_irqsave(ap_lock, flags);
+
+	if (ap->flags & ATA_FLAG_LOADING) {
+		ap->flags &= ~ATA_FLAG_LOADING;
+	} else {
+		if (ap->flags & ATA_FLAG_SCSI_HOTPLUG)
+			queue_work(ata_aux_wq, &ap->hotplug_task);
+		if (ap->flags & ATA_FLAG_RECOVERED)
+			ata_port_printk(ap, KERN_INFO, "EH complete\n");
+	}
+
+	ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED);
+
+	/* tell wait_eh that we're done */
+	ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS;
+	wake_up_all(&ap->eh_wait_q);
+
+	spin_unlock_irqrestore(ap_lock, flags);
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_port_wait_eh - Wait for the currently pending EH to complete
+ *	@ap: Port to wait EH for
+ *
+ *	Wait until the currently pending EH is complete.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+void ata_port_wait_eh(struct ata_port *ap)
+{
+	unsigned long flags;
+	DEFINE_WAIT(wait);
+
+ retry:
+	spin_lock_irqsave(ap->lock, flags);
+
+	while (ap->flags & (ATA_FLAG_EH_PENDING | ATA_FLAG_EH_IN_PROGRESS)) {
+		prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
+		spin_unlock_irqrestore(ap->lock, flags);
+		schedule();
+		spin_lock_irqsave(ap->lock, flags);
+	}
+	finish_wait(&ap->eh_wait_q, &wait);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	/* make sure SCSI EH is complete */
+	if (scsi_host_in_recovery(ap->host)) {
+		msleep(10);
+		goto retry;
+	}
+}
+
+/**
+ *	ata_qc_timeout - Handle timeout of queued command
+ *	@qc: Command that timed out
+ *
+ *	Some part of the kernel (currently, only the SCSI layer)
+ *	has noticed that the active command on port @ap has not
+ *	completed after a specified length of time.  Handle this
+ *	condition by disabling DMA (if necessary) and completing
+ *	transactions, with error if necessary.
+ *
+ *	This also handles the case of the "lost interrupt", where
+ *	for some reason (possibly hardware bug, possibly driver bug)
+ *	an interrupt was not delivered to the driver, even though the
+ *	transaction completed successfully.
+ *
+ *	TODO: kill this function once old EH is gone.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
+ */
+static void ata_qc_timeout(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	u8 host_stat = 0, drv_stat;
+	unsigned long flags;
+
+	DPRINTK("ENTER\n");
+
+	ap->hsm_task_state = HSM_ST_IDLE;
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	switch (qc->tf.protocol) {
+
+	case ATA_PROT_DMA:
+	case ATA_PROT_ATAPI_DMA:
+		host_stat = ap->ops->bmdma_status(ap);
+
+		/* before we do anything else, clear DMA-Start bit */
+		ap->ops->bmdma_stop(qc);
+
+		/* fall through */
+
+	default:
+		ata_altstatus(ap);
+		drv_stat = ata_chk_status(ap);
+
+		/* ack bmdma irq events */
+		ap->ops->irq_clear(ap);
+
+		ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, "
+			       "stat 0x%x host_stat 0x%x\n",
+			       qc->tf.command, drv_stat, host_stat);
+
+		/* complete taskfile transaction */
+		qc->err_mask |= AC_ERR_TIMEOUT;
+		break;
+	}
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	ata_eh_qc_complete(qc);
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_eng_timeout - Handle timeout of queued command
+ *	@ap: Port on which timed-out command is active
+ *
+ *	Some part of the kernel (currently, only the SCSI layer)
+ *	has noticed that the active command on port @ap has not
+ *	completed after a specified length of time.  Handle this
+ *	condition by disabling DMA (if necessary) and completing
+ *	transactions, with error if necessary.
+ *
+ *	This also handles the case of the "lost interrupt", where
+ *	for some reason (possibly hardware bug, possibly driver bug)
+ *	an interrupt was not delivered to the driver, even though the
+ *	transaction completed successfully.
+ *
+ *	TODO: kill this function once old EH is gone.
+ *
+ *	LOCKING:
+ *	Inherited from SCSI layer (none, can sleep)
+ */
+void ata_eng_timeout(struct ata_port *ap)
+{
+	DPRINTK("ENTER\n");
+
+	ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag));
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_qc_schedule_eh - schedule qc for error handling
+ *	@qc: command to schedule error handling for
+ *
+ *	Schedule error handling for @qc.  EH will kick in as soon as
+ *	other commands are drained.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+void ata_qc_schedule_eh(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	WARN_ON(!ap->ops->error_handler);
+
+	qc->flags |= ATA_QCFLAG_FAILED;
+	qc->ap->flags |= ATA_FLAG_EH_PENDING;
+
+	/* The following will fail if timeout has already expired.
+	 * ata_scsi_error() takes care of such scmds on EH entry.
+	 * Note that ATA_QCFLAG_FAILED is unconditionally set after
+	 * this function completes.
+	 */
+	scsi_req_abort_cmd(qc->scsicmd);
+}
+
+/**
+ *	ata_port_schedule_eh - schedule error handling without a qc
+ *	@ap: ATA port to schedule EH for
+ *
+ *	Schedule error handling for @ap.  EH will kick in as soon as
+ *	all commands are drained.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+void ata_port_schedule_eh(struct ata_port *ap)
+{
+	WARN_ON(!ap->ops->error_handler);
+
+	ap->flags |= ATA_FLAG_EH_PENDING;
+	scsi_schedule_eh(ap->host);
+
+	DPRINTK("port EH scheduled\n");
+}
+
+/**
+ *	ata_port_abort - abort all qc's on the port
+ *	@ap: ATA port to abort qc's for
+ *
+ *	Abort all active qc's of @ap and schedule EH.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Number of aborted qc's.
+ */
+int ata_port_abort(struct ata_port *ap)
+{
+	int tag, nr_aborted = 0;
+
+	WARN_ON(!ap->ops->error_handler);
+
+	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+		struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag);
+
+		if (qc) {
+			qc->flags |= ATA_QCFLAG_FAILED;
+			ata_qc_complete(qc);
+			nr_aborted++;
+		}
+	}
+
+	if (!nr_aborted)
+		ata_port_schedule_eh(ap);
+
+	return nr_aborted;
+}
+
+/**
+ *	__ata_port_freeze - freeze port
+ *	@ap: ATA port to freeze
+ *
+ *	This function is called when HSM violation or some other
+ *	condition disrupts normal operation of the port.  Frozen port
+ *	is not allowed to perform any operation until the port is
+ *	thawed, which usually follows a successful reset.
+ *
+ *	ap->ops->freeze() callback can be used for freezing the port
+ *	hardware-wise (e.g. mask interrupt and stop DMA engine).  If a
+ *	port cannot be frozen hardware-wise, the interrupt handler
+ *	must ack and clear interrupts unconditionally while the port
+ *	is frozen.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+static void __ata_port_freeze(struct ata_port *ap)
+{
+	WARN_ON(!ap->ops->error_handler);
+
+	if (ap->ops->freeze)
+		ap->ops->freeze(ap);
+
+	ap->flags |= ATA_FLAG_FROZEN;
+
+	DPRINTK("ata%u port frozen\n", ap->id);
+}
+
+/**
+ *	ata_port_freeze - abort & freeze port
+ *	@ap: ATA port to freeze
+ *
+ *	Abort and freeze @ap.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	Number of aborted commands.
+ */
+int ata_port_freeze(struct ata_port *ap)
+{
+	int nr_aborted;
+
+	WARN_ON(!ap->ops->error_handler);
+
+	nr_aborted = ata_port_abort(ap);
+	__ata_port_freeze(ap);
+
+	return nr_aborted;
+}
+
+/**
+ *	ata_eh_freeze_port - EH helper to freeze port
+ *	@ap: ATA port to freeze
+ *
+ *	Freeze @ap.
+ *
+ *	LOCKING:
+ *	None.
+ */
+void ata_eh_freeze_port(struct ata_port *ap)
+{
+	unsigned long flags;
+
+	if (!ap->ops->error_handler)
+		return;
+
+	spin_lock_irqsave(ap->lock, flags);
+	__ata_port_freeze(ap);
+	spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *	ata_port_thaw_port - EH helper to thaw port
+ *	@ap: ATA port to thaw
+ *
+ *	Thaw frozen port @ap.
+ *
+ *	LOCKING:
+ *	None.
+ */
+void ata_eh_thaw_port(struct ata_port *ap)
+{
+	unsigned long flags;
+
+	if (!ap->ops->error_handler)
+		return;
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	ap->flags &= ~ATA_FLAG_FROZEN;
+
+	if (ap->ops->thaw)
+		ap->ops->thaw(ap);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	DPRINTK("ata%u port thawed\n", ap->id);
+}
+
+static void ata_eh_scsidone(struct scsi_cmnd *scmd)
+{
+	/* nada */
+}
+
+static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	unsigned long flags;
+
+	spin_lock_irqsave(ap->lock, flags);
+	qc->scsidone = ata_eh_scsidone;
+	__ata_qc_complete(qc);
+	WARN_ON(ata_tag_valid(qc->tag));
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
+}
+
+/**
+ *	ata_eh_qc_complete - Complete an active ATA command from EH
+ *	@qc: Command to complete
+ *
+ *	Indicate to the mid and upper layers that an ATA command has
+ *	completed.  To be used from EH.
+ */
+void ata_eh_qc_complete(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	scmd->retries = scmd->allowed;
+	__ata_eh_qc_complete(qc);
+}
+
+/**
+ *	ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
+ *	@qc: Command to retry
+ *
+ *	Indicate to the mid and upper layers that an ATA command
+ *	should be retried.  To be used from EH.
+ *
+ *	SCSI midlayer limits the number of retries to scmd->allowed.
+ *	scmd->retries is decremented for commands which get retried
+ *	due to unrelated failures (qc->err_mask is zero).
+ */
+void ata_eh_qc_retry(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *scmd = qc->scsicmd;
+	if (!qc->err_mask && scmd->retries)
+		scmd->retries--;
+	__ata_eh_qc_complete(qc);
+}
+
+/**
+ *	ata_eh_detach_dev - detach ATA device
+ *	@dev: ATA device to detach
+ *
+ *	Detach @dev.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static void ata_eh_detach_dev(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->ap;
+	unsigned long flags;
+
+	ata_dev_disable(dev);
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	dev->flags &= ~ATA_DFLAG_DETACH;
+
+	if (ata_scsi_offline_dev(dev)) {
+		dev->flags |= ATA_DFLAG_DETACHED;
+		ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
+	}
+
+	/* clear per-dev EH actions */
+	ata_eh_clear_action(dev, &ap->eh_info, ATA_EH_PERDEV_MASK);
+	ata_eh_clear_action(dev, &ap->eh_context.i, ATA_EH_PERDEV_MASK);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *	ata_eh_about_to_do - about to perform eh_action
+ *	@ap: target ATA port
+ *	@dev: target ATA dev for per-dev action (can be NULL)
+ *	@action: action about to be performed
+ *
+ *	Called just before performing EH actions to clear related bits
+ *	in @ap->eh_info such that eh actions are not unnecessarily
+ *	repeated.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev,
+			       unsigned int action)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(ap->lock, flags);
+	ata_eh_clear_action(dev, &ap->eh_info, action);
+	ap->flags |= ATA_FLAG_RECOVERED;
+	spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *	ata_eh_done - EH action complete
+ *	@ap: target ATA port
+ *	@dev: target ATA dev for per-dev action (can be NULL)
+ *	@action: action just completed
+ *
+ *	Called right after performing EH actions to clear related bits
+ *	in @ap->eh_context.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static void ata_eh_done(struct ata_port *ap, struct ata_device *dev,
+			unsigned int action)
+{
+	ata_eh_clear_action(dev, &ap->eh_context.i, action);
+}
+
+/**
+ *	ata_err_string - convert err_mask to descriptive string
+ *	@err_mask: error mask to convert to string
+ *
+ *	Convert @err_mask to descriptive string.  Errors are
+ *	prioritized according to severity and only the most severe
+ *	error is reported.
+ *
+ *	LOCKING:
+ *	None.
+ *
+ *	RETURNS:
+ *	Descriptive string for @err_mask
+ */
+static const char * ata_err_string(unsigned int err_mask)
+{
+	if (err_mask & AC_ERR_HOST_BUS)
+		return "host bus error";
+	if (err_mask & AC_ERR_ATA_BUS)
+		return "ATA bus error";
+	if (err_mask & AC_ERR_TIMEOUT)
+		return "timeout";
+	if (err_mask & AC_ERR_HSM)
+		return "HSM violation";
+	if (err_mask & AC_ERR_SYSTEM)
+		return "internal error";
+	if (err_mask & AC_ERR_MEDIA)
+		return "media error";
+	if (err_mask & AC_ERR_INVALID)
+		return "invalid argument";
+	if (err_mask & AC_ERR_DEV)
+		return "device error";
+	return "unknown error";
+}
+
+/**
+ *	ata_read_log_page - read a specific log page
+ *	@dev: target device
+ *	@page: page to read
+ *	@buf: buffer to store read page
+ *	@sectors: number of sectors to read
+ *
+ *	Read log page using READ_LOG_EXT command.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, AC_ERR_* mask otherwise.
+ */
+static unsigned int ata_read_log_page(struct ata_device *dev,
+				      u8 page, void *buf, unsigned int sectors)
+{
+	struct ata_taskfile tf;
+	unsigned int err_mask;
+
+	DPRINTK("read log page - page %d\n", page);
+
+	ata_tf_init(dev, &tf);
+	tf.command = ATA_CMD_READ_LOG_EXT;
+	tf.lbal = page;
+	tf.nsect = sectors;
+	tf.hob_nsect = sectors >> 8;
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_PIO;
+
+	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
+				     buf, sectors * ATA_SECT_SIZE);
+
+	DPRINTK("EXIT, err_mask=%x\n", err_mask);
+	return err_mask;
+}
+
+/**
+ *	ata_eh_read_log_10h - Read log page 10h for NCQ error details
+ *	@dev: Device to read log page 10h from
+ *	@tag: Resulting tag of the failed command
+ *	@tf: Resulting taskfile registers of the failed command
+ *
+ *	Read log page 10h to obtain NCQ error details and clear error
+ *	condition.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise.
+ */
+static int ata_eh_read_log_10h(struct ata_device *dev,
+			       int *tag, struct ata_taskfile *tf)
+{
+	u8 *buf = dev->ap->sector_buf;
+	unsigned int err_mask;
+	u8 csum;
+	int i;
+
+	err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1);
+	if (err_mask)
+		return -EIO;
+
+	csum = 0;
+	for (i = 0; i < ATA_SECT_SIZE; i++)
+		csum += buf[i];
+	if (csum)
+		ata_dev_printk(dev, KERN_WARNING,
+			       "invalid checksum 0x%x on log page 10h\n", csum);
+
+	if (buf[0] & 0x80)
+		return -ENOENT;
+
+	*tag = buf[0] & 0x1f;
+
+	tf->command = buf[2];
+	tf->feature = buf[3];
+	tf->lbal = buf[4];
+	tf->lbam = buf[5];
+	tf->lbah = buf[6];
+	tf->device = buf[7];
+	tf->hob_lbal = buf[8];
+	tf->hob_lbam = buf[9];
+	tf->hob_lbah = buf[10];
+	tf->nsect = buf[12];
+	tf->hob_nsect = buf[13];
+
+	return 0;
+}
+
+/**
+ *	atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
+ *	@dev: device to perform REQUEST_SENSE to
+ *	@sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
+ *
+ *	Perform ATAPI REQUEST_SENSE after the device reported CHECK
+ *	SENSE.  This function is EH helper.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, AC_ERR_* mask on failure
+ */
+static unsigned int atapi_eh_request_sense(struct ata_device *dev,
+					   unsigned char *sense_buf)
+{
+	struct ata_port *ap = dev->ap;
+	struct ata_taskfile tf;
+	u8 cdb[ATAPI_CDB_LEN];
+
+	DPRINTK("ATAPI request sense\n");
+
+	ata_tf_init(dev, &tf);
+
+	/* FIXME: is this needed? */
+	memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
+
+	/* XXX: why tf_read here? */
+	ap->ops->tf_read(ap, &tf);
+
+	/* fill these in, for the case where they are -not- overwritten */
+	sense_buf[0] = 0x70;
+	sense_buf[2] = tf.feature >> 4;
+
+	memset(cdb, 0, ATAPI_CDB_LEN);
+	cdb[0] = REQUEST_SENSE;
+	cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf.command = ATA_CMD_PACKET;
+
+	/* is it pointless to prefer PIO for "safety reasons"? */
+	if (ap->flags & ATA_FLAG_PIO_DMA) {
+		tf.protocol = ATA_PROT_ATAPI_DMA;
+		tf.feature |= ATAPI_PKT_DMA;
+	} else {
+		tf.protocol = ATA_PROT_ATAPI;
+		tf.lbam = (8 * 1024) & 0xff;
+		tf.lbah = (8 * 1024) >> 8;
+	}
+
+	return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
+				 sense_buf, SCSI_SENSE_BUFFERSIZE);
+}
+
+/**
+ *	ata_eh_analyze_serror - analyze SError for a failed port
+ *	@ap: ATA port to analyze SError for
+ *
+ *	Analyze SError if available and further determine cause of
+ *	failure.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static void ata_eh_analyze_serror(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	u32 serror = ehc->i.serror;
+	unsigned int err_mask = 0, action = 0;
+
+	if (serror & SERR_PERSISTENT) {
+		err_mask |= AC_ERR_ATA_BUS;
+		action |= ATA_EH_HARDRESET;
+	}
+	if (serror &
+	    (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
+		err_mask |= AC_ERR_ATA_BUS;
+		action |= ATA_EH_SOFTRESET;
+	}
+	if (serror & SERR_PROTOCOL) {
+		err_mask |= AC_ERR_HSM;
+		action |= ATA_EH_SOFTRESET;
+	}
+	if (serror & SERR_INTERNAL) {
+		err_mask |= AC_ERR_SYSTEM;
+		action |= ATA_EH_SOFTRESET;
+	}
+	if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG))
+		ata_ehi_hotplugged(&ehc->i);
+
+	ehc->i.err_mask |= err_mask;
+	ehc->i.action |= action;
+}
+
+/**
+ *	ata_eh_analyze_ncq_error - analyze NCQ error
+ *	@ap: ATA port to analyze NCQ error for
+ *
+ *	Read log page 10h, determine the offending qc and acquire
+ *	error status TF.  For NCQ device errors, all LLDDs have to do
+ *	is setting AC_ERR_DEV in ehi->err_mask.  This function takes
+ *	care of the rest.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+static void ata_eh_analyze_ncq_error(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	struct ata_device *dev = ap->device;
+	struct ata_queued_cmd *qc;
+	struct ata_taskfile tf;
+	int tag, rc;
+
+	/* if frozen, we can't do much */
+	if (ap->flags & ATA_FLAG_FROZEN)
+		return;
+
+	/* is it NCQ device error? */
+	if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV))
+		return;
+
+	/* has LLDD analyzed already? */
+	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+		qc = __ata_qc_from_tag(ap, tag);
+
+		if (!(qc->flags & ATA_QCFLAG_FAILED))
+			continue;
+
+		if (qc->err_mask)
+			return;
+	}
+
+	/* okay, this error is ours */
+	rc = ata_eh_read_log_10h(dev, &tag, &tf);
+	if (rc) {
+		ata_port_printk(ap, KERN_ERR, "failed to read log page 10h "
+				"(errno=%d)\n", rc);
+		return;
+	}
+
+	if (!(ap->sactive & (1 << tag))) {
+		ata_port_printk(ap, KERN_ERR, "log page 10h reported "
+				"inactive tag %d\n", tag);
+		return;
+	}
+
+	/* we've got the perpetrator, condemn it */
+	qc = __ata_qc_from_tag(ap, tag);
+	memcpy(&qc->result_tf, &tf, sizeof(tf));
+	qc->err_mask |= AC_ERR_DEV;
+	ehc->i.err_mask &= ~AC_ERR_DEV;
+}
+
+/**
+ *	ata_eh_analyze_tf - analyze taskfile of a failed qc
+ *	@qc: qc to analyze
+ *	@tf: Taskfile registers to analyze
+ *
+ *	Analyze taskfile of @qc and further determine cause of
+ *	failure.  This function also requests ATAPI sense data if
+ *	avaliable.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	Determined recovery action
+ */
+static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+				      const struct ata_taskfile *tf)
+{
+	unsigned int tmp, action = 0;
+	u8 stat = tf->command, err = tf->feature;
+
+	if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) {
+		qc->err_mask |= AC_ERR_HSM;
+		return ATA_EH_SOFTRESET;
+	}
+
+	if (!(qc->err_mask & AC_ERR_DEV))
+		return 0;
+
+	switch (qc->dev->class) {
+	case ATA_DEV_ATA:
+		if (err & ATA_ICRC)
+			qc->err_mask |= AC_ERR_ATA_BUS;
+		if (err & ATA_UNC)
+			qc->err_mask |= AC_ERR_MEDIA;
+		if (err & ATA_IDNF)
+			qc->err_mask |= AC_ERR_INVALID;
+		break;
+
+	case ATA_DEV_ATAPI:
+		tmp = atapi_eh_request_sense(qc->dev,
+					     qc->scsicmd->sense_buffer);
+		if (!tmp) {
+			/* ATA_QCFLAG_SENSE_VALID is used to tell
+			 * atapi_qc_complete() that sense data is
+			 * already valid.
+			 *
+			 * TODO: interpret sense data and set
+			 * appropriate err_mask.
+			 */
+			qc->flags |= ATA_QCFLAG_SENSE_VALID;
+		} else
+			qc->err_mask |= tmp;
+	}
+
+	if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS))
+		action |= ATA_EH_SOFTRESET;
+
+	return action;
+}
+
+static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent)
+{
+	if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT))
+		return 1;
+
+	if (ent->is_io) {
+		if (ent->err_mask & AC_ERR_HSM)
+			return 1;
+		if ((ent->err_mask &
+		     (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
+			return 2;
+	}
+
+	return 0;
+}
+
+struct speed_down_needed_arg {
+	u64 since;
+	int nr_errors[3];
+};
+
+static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg)
+{
+	struct speed_down_needed_arg *arg = void_arg;
+
+	if (ent->timestamp < arg->since)
+		return -1;
+
+	arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++;
+	return 0;
+}
+
+/**
+ *	ata_eh_speed_down_needed - Determine wheter speed down is necessary
+ *	@dev: Device of interest
+ *
+ *	This function examines error ring of @dev and determines
+ *	whether speed down is necessary.  Speed down is necessary if
+ *	there have been more than 3 of Cat-1 errors or 10 of Cat-2
+ *	errors during last 15 minutes.
+ *
+ *	Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM
+ *	violation for known supported commands.
+ *
+ *	Cat-2 errors are unclassified DEV error for known supported
+ *	command.
+ *
+ *	LOCKING:
+ *	Inherited from caller.
+ *
+ *	RETURNS:
+ *	1 if speed down is necessary, 0 otherwise
+ */
+static int ata_eh_speed_down_needed(struct ata_device *dev)
+{
+	const u64 interval = 15LLU * 60 * HZ;
+	static const int err_limits[3] = { -1, 3, 10 };
+	struct speed_down_needed_arg arg;
+	struct ata_ering_entry *ent;
+	int err_cat;
+	u64 j64;
+
+	ent = ata_ering_top(&dev->ering);
+	if (!ent)
+		return 0;
+
+	err_cat = ata_eh_categorize_ering_entry(ent);
+	if (err_cat == 0)
+		return 0;
+
+	memset(&arg, 0, sizeof(arg));
+
+	j64 = get_jiffies_64();
+	if (j64 >= interval)
+		arg.since = j64 - interval;
+	else
+		arg.since = 0;
+
+	ata_ering_map(&dev->ering, speed_down_needed_cb, &arg);
+
+	return arg.nr_errors[err_cat] > err_limits[err_cat];
+}
+
+/**
+ *	ata_eh_speed_down - record error and speed down if necessary
+ *	@dev: Failed device
+ *	@is_io: Did the device fail during normal IO?
+ *	@err_mask: err_mask of the error
+ *
+ *	Record error and examine error history to determine whether
+ *	adjusting transmission speed is necessary.  It also sets
+ *	transmission limits appropriately if such adjustment is
+ *	necessary.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise
+ */
+static int ata_eh_speed_down(struct ata_device *dev, int is_io,
+			     unsigned int err_mask)
+{
+	if (!err_mask)
+		return 0;
+
+	/* record error and determine whether speed down is necessary */
+	ata_ering_record(&dev->ering, is_io, err_mask);
+
+	if (!ata_eh_speed_down_needed(dev))
+		return 0;
+
+	/* speed down SATA link speed if possible */
+	if (sata_down_spd_limit(dev->ap) == 0)
+		return ATA_EH_HARDRESET;
+
+	/* lower transfer mode */
+	if (ata_down_xfermask_limit(dev, 0) == 0)
+		return ATA_EH_SOFTRESET;
+
+	ata_dev_printk(dev, KERN_ERR,
+		       "speed down requested but no transfer mode left\n");
+	return 0;
+}
+
+/**
+ *	ata_eh_autopsy - analyze error and determine recovery action
+ *	@ap: ATA port to perform autopsy on
+ *
+ *	Analyze why @ap failed and determine which recovery action is
+ *	needed.  This function also sets more detailed AC_ERR_* values
+ *	and fills sense data for ATAPI CHECK SENSE.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+static void ata_eh_autopsy(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	unsigned int action = ehc->i.action;
+	struct ata_device *failed_dev = NULL;
+	unsigned int all_err_mask = 0;
+	int tag, is_io = 0;
+	u32 serror;
+	int rc;
+
+	DPRINTK("ENTER\n");
+
+	/* obtain and analyze SError */
+	rc = sata_scr_read(ap, SCR_ERROR, &serror);
+	if (rc == 0) {
+		ehc->i.serror |= serror;
+		ata_eh_analyze_serror(ap);
+	} else if (rc != -EOPNOTSUPP)
+		action |= ATA_EH_HARDRESET;
+
+	/* analyze NCQ failure */
+	ata_eh_analyze_ncq_error(ap);
+
+	/* any real error trumps AC_ERR_OTHER */
+	if (ehc->i.err_mask & ~AC_ERR_OTHER)
+		ehc->i.err_mask &= ~AC_ERR_OTHER;
+
+	all_err_mask |= ehc->i.err_mask;
+
+	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+		struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+		if (!(qc->flags & ATA_QCFLAG_FAILED))
+			continue;
+
+		/* inherit upper level err_mask */
+		qc->err_mask |= ehc->i.err_mask;
+
+		/* analyze TF */
+		action |= ata_eh_analyze_tf(qc, &qc->result_tf);
+
+		/* DEV errors are probably spurious in case of ATA_BUS error */
+		if (qc->err_mask & AC_ERR_ATA_BUS)
+			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA |
+					  AC_ERR_INVALID);
+
+		/* any real error trumps unknown error */
+		if (qc->err_mask & ~AC_ERR_OTHER)
+			qc->err_mask &= ~AC_ERR_OTHER;
+
+		/* SENSE_VALID trumps dev/unknown error and revalidation */
+		if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+			qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
+			action &= ~ATA_EH_REVALIDATE;
+		}
+
+		/* accumulate error info */
+		failed_dev = qc->dev;
+		all_err_mask |= qc->err_mask;
+		if (qc->flags & ATA_QCFLAG_IO)
+			is_io = 1;
+	}
+
+	/* enforce default EH actions */
+	if (ap->flags & ATA_FLAG_FROZEN ||
+	    all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+		action |= ATA_EH_SOFTRESET;
+	else if (all_err_mask)
+		action |= ATA_EH_REVALIDATE;
+
+	/* if we have offending qcs and the associated failed device */
+	if (failed_dev) {
+		/* speed down */
+		action |= ata_eh_speed_down(failed_dev, is_io, all_err_mask);
+
+		/* perform per-dev EH action only on the offending device */
+		ehc->i.dev_action[failed_dev->devno] |=
+			action & ATA_EH_PERDEV_MASK;
+		action &= ~ATA_EH_PERDEV_MASK;
+	}
+
+	/* record autopsy result */
+	ehc->i.dev = failed_dev;
+	ehc->i.action = action;
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_eh_report - report error handling to user
+ *	@ap: ATA port EH is going on
+ *
+ *	Report EH to user.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static void ata_eh_report(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	const char *frozen, *desc;
+	int tag, nr_failed = 0;
+
+	desc = NULL;
+	if (ehc->i.desc[0] != '\0')
+		desc = ehc->i.desc;
+
+	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+		struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+		if (!(qc->flags & ATA_QCFLAG_FAILED))
+			continue;
+		if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
+			continue;
+
+		nr_failed++;
+	}
+
+	if (!nr_failed && !ehc->i.err_mask)
+		return;
+
+	frozen = "";
+	if (ap->flags & ATA_FLAG_FROZEN)
+		frozen = " frozen";
+
+	if (ehc->i.dev) {
+		ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x "
+			       "SAct 0x%x SErr 0x%x action 0x%x%s\n",
+			       ehc->i.err_mask, ap->sactive, ehc->i.serror,
+			       ehc->i.action, frozen);
+		if (desc)
+			ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc);
+	} else {
+		ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x "
+				"SAct 0x%x SErr 0x%x action 0x%x%s\n",
+				ehc->i.err_mask, ap->sactive, ehc->i.serror,
+				ehc->i.action, frozen);
+		if (desc)
+			ata_port_printk(ap, KERN_ERR, "(%s)\n", desc);
+	}
+
+	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+		struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+		if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask)
+			continue;
+
+		ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x "
+			       "Emask 0x%x stat 0x%x err 0x%x (%s)\n",
+			       qc->tag, qc->tf.command, qc->err_mask,
+			       qc->result_tf.command, qc->result_tf.feature,
+			       ata_err_string(qc->err_mask));
+	}
+}
+
+static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
+			unsigned int *classes)
+{
+	int i, rc;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		classes[i] = ATA_DEV_UNKNOWN;
+
+	rc = reset(ap, classes);
+	if (rc)
+		return rc;
+
+	/* If any class isn't ATA_DEV_UNKNOWN, consider classification
+	 * is complete and convert all ATA_DEV_UNKNOWN to
+	 * ATA_DEV_NONE.
+	 */
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		if (classes[i] != ATA_DEV_UNKNOWN)
+			break;
+
+	if (i < ATA_MAX_DEVICES)
+		for (i = 0; i < ATA_MAX_DEVICES; i++)
+			if (classes[i] == ATA_DEV_UNKNOWN)
+				classes[i] = ATA_DEV_NONE;
+
+	return 0;
+}
+
+static int ata_eh_followup_srst_needed(int rc, int classify,
+				       const unsigned int *classes)
+{
+	if (rc == -EAGAIN)
+		return 1;
+	if (rc != 0)
+		return 0;
+	if (classify && classes[0] == ATA_DEV_UNKNOWN)
+		return 1;
+	return 0;
+}
+
+static int ata_eh_reset(struct ata_port *ap, int classify,
+			ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+			ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	unsigned int *classes = ehc->classes;
+	int tries = ATA_EH_RESET_TRIES;
+	int verbose = !(ap->flags & ATA_FLAG_LOADING);
+	unsigned int action;
+	ata_reset_fn_t reset;
+	int i, did_followup_srst, rc;
+
+	/* Determine which reset to use and record in ehc->i.action.
+	 * prereset() may examine and modify it.
+	 */
+	action = ehc->i.action;
+	ehc->i.action &= ~ATA_EH_RESET_MASK;
+	if (softreset && (!hardreset || (!sata_set_spd_needed(ap) &&
+					 !(action & ATA_EH_HARDRESET))))
+		ehc->i.action |= ATA_EH_SOFTRESET;
+	else
+		ehc->i.action |= ATA_EH_HARDRESET;
+
+	if (prereset) {
+		rc = prereset(ap);
+		if (rc) {
+			ata_port_printk(ap, KERN_ERR,
+					"prereset failed (errno=%d)\n", rc);
+			return rc;
+		}
+	}
+
+	/* prereset() might have modified ehc->i.action */
+	if (ehc->i.action & ATA_EH_HARDRESET)
+		reset = hardreset;
+	else if (ehc->i.action & ATA_EH_SOFTRESET)
+		reset = softreset;
+	else {
+		/* prereset told us not to reset, bang classes and return */
+		for (i = 0; i < ATA_MAX_DEVICES; i++)
+			classes[i] = ATA_DEV_NONE;
+		return 0;
+	}
+
+	/* did prereset() screw up?  if so, fix up to avoid oopsing */
+	if (!reset) {
+		ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested "
+				"invalid reset type\n");
+		if (softreset)
+			reset = softreset;
+		else
+			reset = hardreset;
+	}
+
+ retry:
+	/* shut up during boot probing */
+	if (verbose)
+		ata_port_printk(ap, KERN_INFO, "%s resetting port\n",
+				reset == softreset ? "soft" : "hard");
+
+	/* reset */
+	ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
+	ehc->i.flags |= ATA_EHI_DID_RESET;
+
+	rc = ata_do_reset(ap, reset, classes);
+
+	did_followup_srst = 0;
+	if (reset == hardreset &&
+	    ata_eh_followup_srst_needed(rc, classify, classes)) {
+		/* okay, let's do follow-up softreset */
+		did_followup_srst = 1;
+		reset = softreset;
+
+		if (!reset) {
+			ata_port_printk(ap, KERN_ERR,
+					"follow-up softreset required "
+					"but no softreset avaliable\n");
+			return -EINVAL;
+		}
+
+		ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
+		rc = ata_do_reset(ap, reset, classes);
+
+		if (rc == 0 && classify &&
+		    classes[0] == ATA_DEV_UNKNOWN) {
+			ata_port_printk(ap, KERN_ERR,
+					"classification failed\n");
+			return -EINVAL;
+		}
+	}
+
+	if (rc && --tries) {
+		const char *type;
+
+		if (reset == softreset) {
+			if (did_followup_srst)
+				type = "follow-up soft";
+			else
+				type = "soft";
+		} else
+			type = "hard";
+
+		ata_port_printk(ap, KERN_WARNING,
+				"%sreset failed, retrying in 5 secs\n", type);
+		ssleep(5);
+
+		if (reset == hardreset)
+			sata_down_spd_limit(ap);
+		if (hardreset)
+			reset = hardreset;
+		goto retry;
+	}
+
+	if (rc == 0) {
+		/* After the reset, the device state is PIO 0 and the
+		 * controller state is undefined.  Record the mode.
+		 */
+		for (i = 0; i < ATA_MAX_DEVICES; i++)
+			ap->device[i].pio_mode = XFER_PIO_0;
+
+		if (postreset)
+			postreset(ap, classes);
+
+		/* reset successful, schedule revalidation */
+		ata_eh_done(ap, NULL, ATA_EH_RESET_MASK);
+		ehc->i.action |= ATA_EH_REVALIDATE;
+	}
+
+	return rc;
+}
+
+static int ata_eh_revalidate_and_attach(struct ata_port *ap,
+					struct ata_device **r_failed_dev)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	struct ata_device *dev;
+	unsigned long flags;
+	int i, rc = 0;
+
+	DPRINTK("ENTER\n");
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		unsigned int action;
+
+		dev = &ap->device[i];
+		action = ata_eh_dev_action(dev);
+
+		if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) {
+			if (ata_port_offline(ap)) {
+				rc = -EIO;
+				break;
+			}
+
+			ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
+			rc = ata_dev_revalidate(dev,
+					ehc->i.flags & ATA_EHI_DID_RESET);
+			if (rc)
+				break;
+
+			ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
+
+			/* schedule the scsi_rescan_device() here */
+			queue_work(ata_aux_wq, &(ap->scsi_rescan_task));
+		} else if (dev->class == ATA_DEV_UNKNOWN &&
+			   ehc->tries[dev->devno] &&
+			   ata_class_enabled(ehc->classes[dev->devno])) {
+			dev->class = ehc->classes[dev->devno];
+
+			rc = ata_dev_read_id(dev, &dev->class, 1, dev->id);
+			if (rc == 0)
+				rc = ata_dev_configure(dev, 1);
+
+			if (rc) {
+				dev->class = ATA_DEV_UNKNOWN;
+				break;
+			}
+
+			spin_lock_irqsave(ap->lock, flags);
+			ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
+			spin_unlock_irqrestore(ap->lock, flags);
+		}
+	}
+
+	if (rc)
+		*r_failed_dev = dev;
+
+	DPRINTK("EXIT\n");
+	return rc;
+}
+
+static int ata_port_nr_enabled(struct ata_port *ap)
+{
+	int i, cnt = 0;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		if (ata_dev_enabled(&ap->device[i]))
+			cnt++;
+	return cnt;
+}
+
+static int ata_port_nr_vacant(struct ata_port *ap)
+{
+	int i, cnt = 0;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		if (ap->device[i].class == ATA_DEV_UNKNOWN)
+			cnt++;
+	return cnt;
+}
+
+static int ata_eh_skip_recovery(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	int i;
+
+	if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap))
+		return 0;
+
+	/* skip if class codes for all vacant slots are ATA_DEV_NONE */
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+
+		if (dev->class == ATA_DEV_UNKNOWN &&
+		    ehc->classes[dev->devno] != ATA_DEV_NONE)
+			return 0;
+	}
+
+	return 1;
+}
+
+/**
+ *	ata_eh_recover - recover host port after error
+ *	@ap: host port to recover
+ *	@prereset: prereset method (can be NULL)
+ *	@softreset: softreset method (can be NULL)
+ *	@hardreset: hardreset method (can be NULL)
+ *	@postreset: postreset method (can be NULL)
+ *
+ *	This is the alpha and omega, eum and yang, heart and soul of
+ *	libata exception handling.  On entry, actions required to
+ *	recover the port and hotplug requests are recorded in
+ *	eh_context.  This function executes all the operations with
+ *	appropriate retrials and fallbacks to resurrect failed
+ *	devices, detach goners and greet newcomers.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, -errno on failure.
+ */
+static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+			  ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+			  ata_postreset_fn_t postreset)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+	struct ata_device *dev;
+	int down_xfermask, i, rc;
+
+	DPRINTK("ENTER\n");
+
+	/* prep for recovery */
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		dev = &ap->device[i];
+
+		ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+
+		/* process hotplug request */
+		if (dev->flags & ATA_DFLAG_DETACH)
+			ata_eh_detach_dev(dev);
+
+		if (!ata_dev_enabled(dev) &&
+		    ((ehc->i.probe_mask & (1 << dev->devno)) &&
+		     !(ehc->did_probe_mask & (1 << dev->devno)))) {
+			ata_eh_detach_dev(dev);
+			ata_dev_init(dev);
+			ehc->did_probe_mask |= (1 << dev->devno);
+			ehc->i.action |= ATA_EH_SOFTRESET;
+		}
+	}
+
+ retry:
+	down_xfermask = 0;
+	rc = 0;
+
+	/* if UNLOADING, finish immediately */
+	if (ap->flags & ATA_FLAG_UNLOADING)
+		goto out;
+
+	/* skip EH if possible. */
+	if (ata_eh_skip_recovery(ap))
+		ehc->i.action = 0;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++)
+		ehc->classes[i] = ATA_DEV_UNKNOWN;
+
+	/* reset */
+	if (ehc->i.action & ATA_EH_RESET_MASK) {
+		ata_eh_freeze_port(ap);
+
+		rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset,
+				  softreset, hardreset, postreset);
+		if (rc) {
+			ata_port_printk(ap, KERN_ERR,
+					"reset failed, giving up\n");
+			goto out;
+		}
+
+		ata_eh_thaw_port(ap);
+	}
+
+	/* revalidate existing devices and attach new ones */
+	rc = ata_eh_revalidate_and_attach(ap, &dev);
+	if (rc)
+		goto dev_fail;
+
+	/* configure transfer mode if the port has been reset */
+	if (ehc->i.flags & ATA_EHI_DID_RESET) {
+		rc = ata_set_mode(ap, &dev);
+		if (rc) {
+			down_xfermask = 1;
+			goto dev_fail;
+		}
+	}
+
+	goto out;
+
+ dev_fail:
+	switch (rc) {
+	case -ENODEV:
+		/* device missing, schedule probing */
+		ehc->i.probe_mask |= (1 << dev->devno);
+	case -EINVAL:
+		ehc->tries[dev->devno] = 0;
+		break;
+	case -EIO:
+		sata_down_spd_limit(ap);
+	default:
+		ehc->tries[dev->devno]--;
+		if (down_xfermask &&
+		    ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1))
+			ehc->tries[dev->devno] = 0;
+	}
+
+	if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {
+		/* disable device if it has used up all its chances */
+		ata_dev_disable(dev);
+
+		/* detach if offline */
+		if (ata_port_offline(ap))
+			ata_eh_detach_dev(dev);
+
+		/* probe if requested */
+		if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+		    !(ehc->did_probe_mask & (1 << dev->devno))) {
+			ata_eh_detach_dev(dev);
+			ata_dev_init(dev);
+
+			ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+			ehc->did_probe_mask |= (1 << dev->devno);
+			ehc->i.action |= ATA_EH_SOFTRESET;
+		}
+	} else {
+		/* soft didn't work?  be haaaaard */
+		if (ehc->i.flags & ATA_EHI_DID_RESET)
+			ehc->i.action |= ATA_EH_HARDRESET;
+		else
+			ehc->i.action |= ATA_EH_SOFTRESET;
+	}
+
+	if (ata_port_nr_enabled(ap)) {
+		ata_port_printk(ap, KERN_WARNING, "failed to recover some "
+				"devices, retrying in 5 secs\n");
+		ssleep(5);
+	} else {
+		/* no device left, repeat fast */
+		msleep(500);
+	}
+
+	goto retry;
+
+ out:
+	if (rc) {
+		for (i = 0; i < ATA_MAX_DEVICES; i++)
+			ata_dev_disable(&ap->device[i]);
+	}
+
+	DPRINTK("EXIT, rc=%d\n", rc);
+	return rc;
+}
+
+/**
+ *	ata_eh_finish - finish up EH
+ *	@ap: host port to finish EH for
+ *
+ *	Recovery is complete.  Clean up EH states and retry or finish
+ *	failed qcs.
+ *
+ *	LOCKING:
+ *	None.
+ */
+static void ata_eh_finish(struct ata_port *ap)
+{
+	int tag;
+
+	/* retry or finish qcs */
+	for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
+		struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+		if (!(qc->flags & ATA_QCFLAG_FAILED))
+			continue;
+
+		if (qc->err_mask) {
+			/* FIXME: Once EH migration is complete,
+			 * generate sense data in this function,
+			 * considering both err_mask and tf.
+			 */
+			if (qc->err_mask & AC_ERR_INVALID)
+				ata_eh_qc_complete(qc);
+			else
+				ata_eh_qc_retry(qc);
+		} else {
+			if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+				ata_eh_qc_complete(qc);
+			} else {
+				/* feed zero TF to sense generation */
+				memset(&qc->result_tf, 0, sizeof(qc->result_tf));
+				ata_eh_qc_retry(qc);
+			}
+		}
+	}
+}
+
+/**
+ *	ata_do_eh - do standard error handling
+ *	@ap: host port to handle error for
+ *	@prereset: prereset method (can be NULL)
+ *	@softreset: softreset method (can be NULL)
+ *	@hardreset: hardreset method (can be NULL)
+ *	@postreset: postreset method (can be NULL)
+ *
+ *	Perform standard error handling sequence.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+	       ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+	       ata_postreset_fn_t postreset)
+{
+	if (!(ap->flags & ATA_FLAG_LOADING)) {
+		ata_eh_autopsy(ap);
+		ata_eh_report(ap);
+	}
+
+	ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
+	ata_eh_finish(ap);
+}
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index a0289ec..2915bca 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -38,9 +38,10 @@
 #include <linux/spinlock.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_device.h>
-#include <scsi/scsi_request.h>
+#include <scsi/scsi_tcq.h>
 #include <scsi/scsi_transport.h>
 #include <linux/libata.h>
 #include <linux/hdreg.h>
@@ -51,10 +52,14 @@
 #define SECTOR_SIZE	512
 
 typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd);
-static struct ata_device *
-ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev);
-static void ata_scsi_error(struct Scsi_Host *host);
-enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
+
+static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
+					const struct scsi_device *scsidev);
+static struct ata_device * ata_scsi_find_dev(struct ata_port *ap,
+					    const struct scsi_device *scsidev);
+static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+			      unsigned int id, unsigned int lun);
+
 
 #define RW_RECOVERY_MPAGE 0x1
 #define RW_RECOVERY_MPAGE_LEN 12
@@ -102,6 +107,7 @@
 struct scsi_transport_template ata_scsi_transport_template = {
 	.eh_strategy_handler	= ata_scsi_error,
 	.eh_timed_out		= ata_scsi_timed_out,
+	.user_scan		= ata_scsi_user_scan,
 };
 
 
@@ -216,9 +222,7 @@
 	 && copy_to_user(arg + sizeof(args), argbuf, argsize))
 		rc = -EFAULT;
 error:
-	if (argbuf)
-		kfree(argbuf);
-
+	kfree(argbuf);
 	return rc;
 }
 
@@ -304,7 +308,6 @@
 
 /**
  *	ata_scsi_qc_new - acquire new ata_queued_cmd reference
- *	@ap: ATA port to which the new command is attached
  *	@dev: ATA device to which the new command is attached
  *	@cmd: SCSI command that originated this ATA command
  *	@done: SCSI command completion function
@@ -323,14 +326,13 @@
  *	RETURNS:
  *	Command allocated, or %NULL if none available.
  */
-struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap,
-				       struct ata_device *dev,
+struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
 				       struct scsi_cmnd *cmd,
 				       void (*done)(struct scsi_cmnd *))
 {
 	struct ata_queued_cmd *qc;
 
-	qc = ata_qc_new_init(ap, dev);
+	qc = ata_qc_new_init(dev);
 	if (qc) {
 		qc->scsicmd = cmd;
 		qc->scsidone = done;
@@ -397,18 +399,18 @@
 
 int ata_scsi_device_resume(struct scsi_device *sdev)
 {
-	struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
-	struct ata_device *dev = &ap->device[sdev->id];
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
 
-	return ata_device_resume(ap, dev);
+	return ata_device_resume(dev);
 }
 
 int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
 {
-	struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
-	struct ata_device *dev = &ap->device[sdev->id];
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
 
-	return ata_device_suspend(ap, dev, state);
+	return ata_device_suspend(dev, state);
 }
 
 /**
@@ -419,6 +421,7 @@
  *	@sk: the sense key we'll fill out
  *	@asc: the additional sense code we'll fill out
  *	@ascq: the additional sense code qualifier we'll fill out
+ *	@verbose: be verbose
  *
  *	Converts an ATA error into a SCSI error.  Fill out pointers to
  *	SK, ASC, and ASCQ bytes for later use in fixed or descriptor
@@ -428,7 +431,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc,
-			u8 *ascq)
+			u8 *ascq, int verbose)
 {
 	int i;
 
@@ -493,8 +496,9 @@
 			}
 		}
 		/* No immediate match */
-		printk(KERN_WARNING "ata%u: no sense translation for "
-		       "error 0x%02x\n", id, drv_err);
+		if (verbose)
+			printk(KERN_WARNING "ata%u: no sense translation for "
+			       "error 0x%02x\n", id, drv_err);
 	}
 
 	/* Fall back to interpreting status bits */
@@ -507,8 +511,9 @@
 		}
 	}
 	/* No error?  Undecoded? */
-	printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n",
-	       id, drv_stat);
+	if (verbose)
+		printk(KERN_WARNING "ata%u: no sense translation for "
+		       "status: 0x%02x\n", id, drv_stat);
 
 	/* We need a sensible error return here, which is tricky, and one
 	   that won't cause people to do things like return a disk wrongly */
@@ -517,9 +522,10 @@
 	*ascq = 0x00;
 
  translate_done:
-	printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to "
-	       "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err,
-	       *sk, *asc, *ascq);
+	if (verbose)
+		printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x "
+		       "to SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n",
+		       id, drv_stat, drv_err, *sk, *asc, *ascq);
 	return;
 }
 
@@ -539,27 +545,23 @@
 void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
-	struct ata_taskfile *tf = &qc->tf;
+	struct ata_taskfile *tf = &qc->result_tf;
 	unsigned char *sb = cmd->sense_buffer;
 	unsigned char *desc = sb + 8;
+	int verbose = qc->ap->ops->error_handler == NULL;
 
 	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
 	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
 	/*
-	 * Read the controller registers.
-	 */
-	WARN_ON(qc->ap->ops->tf_read == NULL);
-	qc->ap->ops->tf_read(qc->ap, tf);
-
-	/*
 	 * Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 */
-	if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+	if (qc->err_mask ||
+	    tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
 		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-				   &sb[1], &sb[2], &sb[3]);
+				   &sb[1], &sb[2], &sb[3], verbose);
 		sb[1] &= 0x0f;
 	}
 
@@ -615,26 +617,22 @@
 void ata_gen_fixed_sense(struct ata_queued_cmd *qc)
 {
 	struct scsi_cmnd *cmd = qc->scsicmd;
-	struct ata_taskfile *tf = &qc->tf;
+	struct ata_taskfile *tf = &qc->result_tf;
 	unsigned char *sb = cmd->sense_buffer;
+	int verbose = qc->ap->ops->error_handler == NULL;
 
 	memset(sb, 0, SCSI_SENSE_BUFFERSIZE);
 
 	cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
 	/*
-	 * Read the controller registers.
-	 */
-	WARN_ON(qc->ap->ops->tf_read == NULL);
-	qc->ap->ops->tf_read(qc->ap, tf);
-
-	/*
 	 * Use ata_to_sense_error() to map status register bits
 	 * onto sense key, asc & ascq.
 	 */
-	if (tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
+	if (qc->err_mask ||
+	    tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ)) {
 		ata_to_sense_error(qc->ap->id, tf->command, tf->feature,
-				   &sb[2], &sb[12], &sb[13]);
+				   &sb[2], &sb[12], &sb[13], verbose);
 		sb[2] &= 0x0f;
 	}
 
@@ -677,7 +675,7 @@
 	 */
 	max_sectors = ATA_MAX_SECTORS;
 	if (dev->flags & ATA_DFLAG_LBA48)
-		max_sectors = 2048;
+		max_sectors = ATA_MAX_SECTORS_LBA48;
 	if (dev->max_sectors)
 		max_sectors = dev->max_sectors;
 
@@ -692,6 +690,14 @@
 		request_queue_t *q = sdev->request_queue;
 		blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
 	}
+
+	if (dev->flags & ATA_DFLAG_NCQ) {
+		int depth;
+
+		depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
+		depth = min(ATA_MAX_QUEUE - 1, depth);
+		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
+	}
 }
 
 /**
@@ -708,152 +714,88 @@
 
 int ata_scsi_slave_config(struct scsi_device *sdev)
 {
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
+
 	ata_scsi_sdev_config(sdev);
 
 	blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD);
 
-	if (sdev->id < ATA_MAX_DEVICES) {
-		struct ata_port *ap;
-		struct ata_device *dev;
-
-		ap = (struct ata_port *) &sdev->host->hostdata[0];
-		dev = &ap->device[sdev->id];
-
+	if (dev)
 		ata_scsi_dev_config(sdev, dev);
-	}
 
 	return 0;	/* scsi layer doesn't check return value, sigh */
 }
 
 /**
- *	ata_scsi_timed_out - SCSI layer time out callback
- *	@cmd: timed out SCSI command
+ *	ata_scsi_slave_destroy - SCSI device is about to be destroyed
+ *	@sdev: SCSI device to be destroyed
  *
- *	Handles SCSI layer timeout.  We race with normal completion of
- *	the qc for @cmd.  If the qc is already gone, we lose and let
- *	the scsi command finish (EH_HANDLED).  Otherwise, the qc has
- *	timed out and EH should be invoked.  Prevent ata_qc_complete()
- *	from finishing it by setting EH_SCHEDULED and return
- *	EH_NOT_HANDLED.
+ *	@sdev is about to be destroyed for hot/warm unplugging.  If
+ *	this unplugging was initiated by libata as indicated by NULL
+ *	dev->sdev, this function doesn't have to do anything.
+ *	Otherwise, SCSI layer initiated warm-unplug is in progress.
+ *	Clear dev->sdev, schedule the device for ATA detach and invoke
+ *	EH.
  *
  *	LOCKING:
- *	Called from timer context
+ *	Defined by SCSI layer.  We don't really care.
+ */
+void ata_scsi_slave_destroy(struct scsi_device *sdev)
+{
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	unsigned long flags;
+	struct ata_device *dev;
+
+	if (!ap->ops->error_handler)
+		return;
+
+	spin_lock_irqsave(ap->lock, flags);
+	dev = __ata_scsi_find_dev(ap, sdev);
+	if (dev && dev->sdev) {
+		/* SCSI device already in CANCEL state, no need to offline it */
+		dev->sdev = NULL;
+		dev->flags |= ATA_DFLAG_DETACH;
+		ata_port_schedule_eh(ap);
+	}
+	spin_unlock_irqrestore(ap->lock, flags);
+}
+
+/**
+ *	ata_scsi_change_queue_depth - SCSI callback for queue depth config
+ *	@sdev: SCSI device to configure queue depth for
+ *	@queue_depth: new queue depth
+ *
+ *	This is libata standard hostt->change_queue_depth callback.
+ *	SCSI will call into this callback when user tries to set queue
+ *	depth via sysfs.
+ *
+ *	LOCKING:
+ *	SCSI layer (we don't care)
  *
  *	RETURNS:
- *	EH_HANDLED or EH_NOT_HANDLED
+ *	Newly configured queue depth.
  */
-enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd)
+int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
 {
-	struct Scsi_Host *host = cmd->device->host;
-	struct ata_port *ap = (struct ata_port *) &host->hostdata[0];
-	unsigned long flags;
-	struct ata_queued_cmd *qc;
-	enum scsi_eh_timer_return ret = EH_HANDLED;
+	struct ata_port *ap = ata_shost_to_port(sdev->host);
+	struct ata_device *dev;
+	int max_depth;
 
-	DPRINTK("ENTER\n");
+	if (queue_depth < 1)
+		return sdev->queue_depth;
 
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-	if (qc) {
-		WARN_ON(qc->scsicmd != cmd);
-		qc->flags |= ATA_QCFLAG_EH_SCHEDULED;
-		qc->err_mask |= AC_ERR_TIMEOUT;
-		ret = EH_NOT_HANDLED;
-	}
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+	dev = ata_scsi_find_dev(ap, sdev);
+	if (!dev || !ata_dev_enabled(dev))
+		return sdev->queue_depth;
 
-	DPRINTK("EXIT, ret=%d\n", ret);
-	return ret;
-}
+	max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
+	max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
+	if (queue_depth > max_depth)
+		queue_depth = max_depth;
 
-/**
- *	ata_scsi_error - SCSI layer error handler callback
- *	@host: SCSI host on which error occurred
- *
- *	Handles SCSI-layer-thrown error events.
- *
- *	LOCKING:
- *	Inherited from SCSI layer (none, can sleep)
- */
-
-static void ata_scsi_error(struct Scsi_Host *host)
-{
-	struct ata_port *ap;
-	unsigned long flags;
-
-	DPRINTK("ENTER\n");
-
-	ap = (struct ata_port *) &host->hostdata[0];
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	WARN_ON(ap->flags & ATA_FLAG_IN_EH);
-	ap->flags |= ATA_FLAG_IN_EH;
-	WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-	ata_port_flush_task(ap);
-
-	ap->ops->eng_timeout(ap);
-
-	WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
-
-	scsi_eh_flush_done_q(&ap->eh_done_q);
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	ap->flags &= ~ATA_FLAG_IN_EH;
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-	DPRINTK("EXIT\n");
-}
-
-static void ata_eh_scsidone(struct scsi_cmnd *scmd)
-{
-	/* nada */
-}
-
-static void __ata_eh_qc_complete(struct ata_queued_cmd *qc)
-{
-	struct ata_port *ap = qc->ap;
-	struct scsi_cmnd *scmd = qc->scsicmd;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ap->host_set->lock, flags);
-	qc->scsidone = ata_eh_scsidone;
-	__ata_qc_complete(qc);
-	WARN_ON(ata_tag_valid(qc->tag));
-	spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-	scsi_eh_finish_cmd(scmd, &ap->eh_done_q);
-}
-
-/**
- *	ata_eh_qc_complete - Complete an active ATA command from EH
- *	@qc: Command to complete
- *
- *	Indicate to the mid and upper layers that an ATA command has
- *	completed.  To be used from EH.
- */
-void ata_eh_qc_complete(struct ata_queued_cmd *qc)
-{
-	struct scsi_cmnd *scmd = qc->scsicmd;
-	scmd->retries = scmd->allowed;
-	__ata_eh_qc_complete(qc);
-}
-
-/**
- *	ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH
- *	@qc: Command to retry
- *
- *	Indicate to the mid and upper layers that an ATA command
- *	should be retried.  To be used from EH.
- *
- *	SCSI midlayer limits the number of retries to scmd->allowed.
- *	This function might need to adjust scmd->retries for commands
- *	which get retried due to unrelated NCQ failures.
- */
-void ata_eh_qc_retry(struct ata_queued_cmd *qc)
-{
-	__ata_eh_qc_complete(qc);
+	scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
+	return queue_depth;
 }
 
 /**
@@ -891,7 +833,7 @@
 		tf->nsect = 1;	/* 1 sector, lba=0 */
 
 		if (qc->dev->flags & ATA_DFLAG_LBA) {
-			qc->tf.flags |= ATA_TFLAG_LBA;
+			tf->flags |= ATA_TFLAG_LBA;
 
 			tf->lbah = 0x0;
 			tf->lbam = 0x0;
@@ -1195,6 +1137,7 @@
 	u64 block;
 	u32 n_block;
 
+	qc->flags |= ATA_QCFLAG_IO;
 	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
 
 	if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
@@ -1241,7 +1184,36 @@
 		 */
 		goto nothing_to_do;
 
-	if (dev->flags & ATA_DFLAG_LBA) {
+	if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
+		/* yay, NCQ */
+		if (!lba_48_ok(block, n_block))
+			goto out_of_range;
+
+		tf->protocol = ATA_PROT_NCQ;
+		tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
+
+		if (tf->flags & ATA_TFLAG_WRITE)
+			tf->command = ATA_CMD_FPDMA_WRITE;
+		else
+			tf->command = ATA_CMD_FPDMA_READ;
+
+		qc->nsect = n_block;
+
+		tf->nsect = qc->tag << 3;
+		tf->hob_feature = (n_block >> 8) & 0xff;
+		tf->feature = n_block & 0xff;
+
+		tf->hob_lbah = (block >> 40) & 0xff;
+		tf->hob_lbam = (block >> 32) & 0xff;
+		tf->hob_lbal = (block >> 24) & 0xff;
+		tf->lbah = (block >> 16) & 0xff;
+		tf->lbam = (block >> 8) & 0xff;
+		tf->lbal = block & 0xff;
+
+		tf->device = 1 << 6;
+		if (tf->flags & ATA_TFLAG_FUA)
+			tf->device |= 1 << 7;
+	} else if (dev->flags & ATA_DFLAG_LBA) {
 		tf->flags |= ATA_TFLAG_LBA;
 
 		if (lba_28_ok(block, n_block)) {
@@ -1332,6 +1304,17 @@
 	u8 *cdb = cmd->cmnd;
  	int need_sense = (qc->err_mask != 0);
 
+	/* We snoop the SET_FEATURES - Write Cache ON/OFF command, and
+	 * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
+	 * cache
+	 */
+	if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) &&
+	    ((qc->tf.feature == SETFEATURES_WC_ON) ||
+	     (qc->tf.feature == SETFEATURES_WC_OFF))) {
+		qc->ap->eh_info.action |= ATA_EH_REVALIDATE;
+		ata_port_schedule_eh(qc->ap);
+	}
+
 	/* For ATA pass thru (SAT) commands, generate a sense block if
 	 * user mandated it or if there's an error.  Note that if we
 	 * generate because the user forced us to, a check condition
@@ -1356,10 +1339,8 @@
 		}
 	}
 
-	if (need_sense) {
-		/* The ata_gen_..._sense routines fill in tf */
-		ata_dump_status(qc->ap->id, &qc->tf);
-	}
+	if (need_sense && !qc->ap->ops->error_handler)
+		ata_dump_status(qc->ap->id, &qc->result_tf);
 
 	qc->scsidone(cmd);
 
@@ -1367,8 +1348,40 @@
 }
 
 /**
+ *	ata_scmd_need_defer - Check whether we need to defer scmd
+ *	@dev: ATA device to which the command is addressed
+ *	@is_io: Is the command IO (and thus possibly NCQ)?
+ *
+ *	NCQ and non-NCQ commands cannot run together.  As upper layer
+ *	only knows the queue depth, we are responsible for maintaining
+ *	exclusion.  This function checks whether a new command can be
+ *	issued to @dev.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	1 if deferring is needed, 0 otherwise.
+ */
+static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
+{
+	struct ata_port *ap = dev->ap;
+
+	if (!(dev->flags & ATA_DFLAG_NCQ))
+		return 0;
+
+	if (is_io) {
+		if (!ata_tag_valid(ap->active_tag))
+			return 0;
+	} else {
+		if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
+			return 0;
+	}
+	return 1;
+}
+
+/**
  *	ata_scsi_translate - Translate then issue SCSI command to ATA device
- *	@ap: ATA port to which the command is addressed
  *	@dev: ATA device to which the command is addressed
  *	@cmd: SCSI command to execute
  *	@done: SCSI command completion function
@@ -1389,19 +1402,25 @@
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command
+ *	needs to be deferred.
  */
-
-static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
-			      struct scsi_cmnd *cmd,
+static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *),
 			      ata_xlat_func_t xlat_func)
 {
 	struct ata_queued_cmd *qc;
 	u8 *scsicmd = cmd->cmnd;
+	int is_io = xlat_func == ata_scsi_rw_xlat;
 
 	VPRINTK("ENTER\n");
 
-	qc = ata_scsi_qc_new(ap, dev, cmd, done);
+	if (unlikely(ata_scmd_need_defer(dev, is_io)))
+		goto defer;
+
+	qc = ata_scsi_qc_new(dev, cmd, done);
 	if (!qc)
 		goto err_mem;
 
@@ -1409,8 +1428,8 @@
 	if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
 	    cmd->sc_data_direction == DMA_TO_DEVICE) {
 		if (unlikely(cmd->request_bufflen < 1)) {
-			printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n",
-			       ap->id, dev->devno);
+			ata_dev_printk(dev, KERN_WARNING,
+				       "WARNING: zero len r/w req\n");
 			goto err_did;
 		}
 
@@ -1432,13 +1451,13 @@
 	ata_qc_issue(qc);
 
 	VPRINTK("EXIT\n");
-	return;
+	return 0;
 
 early_finish:
         ata_qc_free(qc);
 	done(cmd);
 	DPRINTK("EXIT - early finish (good or error)\n");
-	return;
+	return 0;
 
 err_did:
 	ata_qc_free(qc);
@@ -1446,7 +1465,11 @@
 	cmd->result = (DID_ERROR << 16);
 	done(cmd);
 	DPRINTK("EXIT - internal\n");
-	return;
+	return 0;
+
+defer:
+	DPRINTK("EXIT - defer\n");
+	return SCSI_MLQUEUE_DEVICE_BUSY;
 }
 
 /**
@@ -1944,7 +1967,7 @@
 		return 0;
 
 	dpofua = 0;
-	if (ata_dev_supports_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 &&
+	if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
 	    (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
 		dpofua = 1 << 4;
 
@@ -2137,13 +2160,14 @@
 
 static void atapi_sense_complete(struct ata_queued_cmd *qc)
 {
-	if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0))
+	if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
 		/* FIXME: not quite right; we don't want the
 		 * translation of taskfile registers into
 		 * a sense descriptors, since that's only
 		 * correct for ATA, not ATAPI
 		 */
 		ata_gen_ata_desc_sense(qc);
+	}
 
 	qc->scsidone(qc->scsicmd);
 	ata_qc_free(qc);
@@ -2207,21 +2231,38 @@
 
 	VPRINTK("ENTER, err_mask 0x%X\n", err_mask);
 
+	/* handle completion from new EH */
+	if (unlikely(qc->ap->ops->error_handler &&
+		     (err_mask || qc->flags & ATA_QCFLAG_SENSE_VALID))) {
+
+		if (!(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
+			/* FIXME: not quite right; we don't want the
+			 * translation of taskfile registers into a
+			 * sense descriptors, since that's only
+			 * correct for ATA, not ATAPI
+			 */
+			ata_gen_ata_desc_sense(qc);
+		}
+
+		qc->scsicmd->result = SAM_STAT_CHECK_CONDITION;
+		qc->scsidone(cmd);
+		ata_qc_free(qc);
+		return;
+	}
+
+	/* successful completion or old EH failure path */
 	if (unlikely(err_mask & AC_ERR_DEV)) {
 		cmd->result = SAM_STAT_CHECK_CONDITION;
 		atapi_request_sense(qc);
 		return;
-	}
-
-	else if (unlikely(err_mask))
+	} else if (unlikely(err_mask)) {
 		/* FIXME: not quite right; we don't want the
 		 * translation of taskfile registers into
 		 * a sense descriptors, since that's only
 		 * correct for ATA, not ATAPI
 		 */
 		ata_gen_ata_desc_sense(qc);
-
-	else {
+	} else {
 		u8 *scsicmd = cmd->cmnd;
 
 		if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
@@ -2303,18 +2344,63 @@
 		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
 		qc->tf.feature |= ATAPI_PKT_DMA;
 
-#ifdef ATAPI_ENABLE_DMADIR
-		/* some SATA bridges need us to indicate data xfer direction */
-		if (cmd->sc_data_direction != DMA_TO_DEVICE)
+		if (atapi_dmadir && (cmd->sc_data_direction != DMA_TO_DEVICE))
+			/* some SATA bridges need us to indicate data xfer direction */
 			qc->tf.feature |= ATAPI_DMADIR;
-#endif
 	}
 
-	qc->nbytes = cmd->bufflen;
+	qc->nbytes = cmd->request_bufflen;
 
 	return 0;
 }
 
+static struct ata_device * ata_find_dev(struct ata_port *ap, int id)
+{
+	if (likely(id < ATA_MAX_DEVICES))
+		return &ap->device[id];
+	return NULL;
+}
+
+static struct ata_device * __ata_scsi_find_dev(struct ata_port *ap,
+					const struct scsi_device *scsidev)
+{
+	/* skip commands not addressed to targets we simulate */
+	if (unlikely(scsidev->channel || scsidev->lun))
+		return NULL;
+
+	return ata_find_dev(ap, scsidev->id);
+}
+
+/**
+ *	ata_scsi_dev_enabled - determine if device is enabled
+ *	@dev: ATA device
+ *
+ *	Determine if commands should be sent to the specified device.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	0 if commands are not allowed / 1 if commands are allowed
+ */
+
+static int ata_scsi_dev_enabled(struct ata_device *dev)
+{
+	if (unlikely(!ata_dev_enabled(dev)))
+		return 0;
+
+	if (!atapi_enabled || (dev->ap->flags & ATA_FLAG_NO_ATAPI)) {
+		if (unlikely(dev->class == ATA_DEV_ATAPI)) {
+			ata_dev_printk(dev, KERN_WARNING,
+				       "WARNING: ATAPI is %s, device ignored.\n",
+				       atapi_enabled ? "not supported with this driver" : "disabled");
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
 /**
  *	ata_scsi_find_dev - lookup ata_device from scsi_cmnd
  *	@ap: ATA port to which the device is attached
@@ -2331,33 +2417,14 @@
  *	RETURNS:
  *	Associated ATA device, or %NULL if not found.
  */
-
 static struct ata_device *
 ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev)
 {
-	struct ata_device *dev;
+	struct ata_device *dev = __ata_scsi_find_dev(ap, scsidev);
 
-	/* skip commands not addressed to targets we simulate */
-	if (likely(scsidev->id < ATA_MAX_DEVICES))
-		dev = &ap->device[scsidev->id];
-	else
+	if (unlikely(!dev || !ata_scsi_dev_enabled(dev)))
 		return NULL;
 
-	if (unlikely((scsidev->channel != 0) ||
-		     (scsidev->lun != 0)))
-		return NULL;
-
-	if (unlikely(!ata_dev_present(dev)))
-		return NULL;
-
-	if (!atapi_enabled || (ap->flags & ATA_FLAG_NO_ATAPI)) {
-		if (unlikely(dev->class == ATA_DEV_ATAPI)) {
-			printk(KERN_WARNING "ata%u(%u): WARNING: ATAPI is %s, device ignored.\n",
-			       ap->id, dev->devno, atapi_enabled ? "not supported with this driver" : "disabled");
-			return NULL;
-		}
-	}
-
 	return dev;
 }
 
@@ -2414,10 +2481,15 @@
 {
 	struct ata_taskfile *tf = &(qc->tf);
 	struct scsi_cmnd *cmd = qc->scsicmd;
+	struct ata_device *dev = qc->dev;
 
 	if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN)
 		goto invalid_fld;
 
+	/* We may not issue DMA commands if no DMA mode is set */
+	if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
+		goto invalid_fld;
+
 	if (scsicmd[1] & 0xe0)
 		/* PIO multi not supported yet */
 		goto invalid_fld;
@@ -2500,7 +2572,10 @@
 	 * TODO: find out if we need to do more here to
 	 *       cover scatter/gather case.
 	 */
-	qc->nsect = cmd->bufflen / ATA_SECT_SIZE;
+	qc->nsect = cmd->request_bufflen / ATA_SECT_SIZE;
+
+	/* request result TF */
+	qc->flags |= ATA_QCFLAG_RESULT_TF;
 
 	return 0;
 
@@ -2578,19 +2653,24 @@
 #endif
 }
 
-static inline void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
-				       struct ata_port *ap, struct ata_device *dev)
+static inline int __ata_scsi_queuecmd(struct scsi_cmnd *cmd,
+				      void (*done)(struct scsi_cmnd *),
+				      struct ata_device *dev)
 {
+	int rc = 0;
+
 	if (dev->class == ATA_DEV_ATA) {
 		ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
 							      cmd->cmnd[0]);
 
 		if (xlat_func)
-			ata_scsi_translate(ap, dev, cmd, done, xlat_func);
+			rc = ata_scsi_translate(dev, cmd, done, xlat_func);
 		else
-			ata_scsi_simulate(ap, dev, cmd, done);
+			ata_scsi_simulate(dev, cmd, done);
 	} else
-		ata_scsi_translate(ap, dev, cmd, done, atapi_xlat);
+		rc = ata_scsi_translate(dev, cmd, done, atapi_xlat);
+
+	return rc;
 }
 
 /**
@@ -2609,39 +2689,39 @@
  *	Releases scsi-layer-held lock, and obtains host_set lock.
  *
  *	RETURNS:
- *	Zero.
+ *	Return value from __ata_scsi_queuecmd() if @cmd can be queued,
+ *	0 otherwise.
  */
-
 int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
 	struct ata_port *ap;
 	struct ata_device *dev;
 	struct scsi_device *scsidev = cmd->device;
 	struct Scsi_Host *shost = scsidev->host;
+	int rc = 0;
 
-	ap = (struct ata_port *) &shost->hostdata[0];
+	ap = ata_shost_to_port(shost);
 
 	spin_unlock(shost->host_lock);
-	spin_lock(&ap->host_set->lock);
+	spin_lock(ap->lock);
 
 	ata_scsi_dump_cdb(ap, cmd);
 
 	dev = ata_scsi_find_dev(ap, scsidev);
 	if (likely(dev))
-		__ata_scsi_queuecmd(cmd, done, ap, dev);
+		rc = __ata_scsi_queuecmd(cmd, done, dev);
 	else {
 		cmd->result = (DID_BAD_TARGET << 16);
 		done(cmd);
 	}
 
-	spin_unlock(&ap->host_set->lock);
+	spin_unlock(ap->lock);
 	spin_lock(shost->host_lock);
-	return 0;
+	return rc;
 }
 
 /**
  *	ata_scsi_simulate - simulate SCSI command on ATA device
- *	@ap: port the device is connected to
  *	@dev: the target device
  *	@cmd: SCSI command being sent to device.
  *	@done: SCSI command completion function.
@@ -2653,14 +2733,12 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
-		      struct scsi_cmnd *cmd,
+void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
 		      void (*done)(struct scsi_cmnd *))
 {
 	struct ata_scsi_args args;
 	const u8 *scsicmd = cmd->cmnd;
 
-	args.ap = ap;
 	args.dev = dev;
 	args.id = dev->id;
 	args.cmd = cmd;
@@ -2732,17 +2810,241 @@
 
 void ata_scsi_scan_host(struct ata_port *ap)
 {
-	struct ata_device *dev;
 	unsigned int i;
 
-	if (ap->flags & ATA_FLAG_PORT_DISABLED)
+	if (ap->flags & ATA_FLAG_DISABLED)
 		return;
 
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		struct scsi_device *sdev;
+
+		if (!ata_dev_enabled(dev) || dev->sdev)
+			continue;
+
+		sdev = __scsi_add_device(ap->host, 0, i, 0, NULL);
+		if (!IS_ERR(sdev)) {
+			dev->sdev = sdev;
+			scsi_device_put(sdev);
+		}
+	}
+}
+
+/**
+ *	ata_scsi_offline_dev - offline attached SCSI device
+ *	@dev: ATA device to offline attached SCSI device for
+ *
+ *	This function is called from ata_eh_hotplug() and responsible
+ *	for taking the SCSI device attached to @dev offline.  This
+ *	function is called with host_set lock which protects dev->sdev
+ *	against clearing.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ *
+ *	RETURNS:
+ *	1 if attached SCSI device exists, 0 otherwise.
+ */
+int ata_scsi_offline_dev(struct ata_device *dev)
+{
+	if (dev->sdev) {
+		scsi_device_set_state(dev->sdev, SDEV_OFFLINE);
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ *	ata_scsi_remove_dev - remove attached SCSI device
+ *	@dev: ATA device to remove attached SCSI device for
+ *
+ *	This function is called from ata_eh_scsi_hotplug() and
+ *	responsible for removing the SCSI device attached to @dev.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+static void ata_scsi_remove_dev(struct ata_device *dev)
+{
+	struct ata_port *ap = dev->ap;
+	struct scsi_device *sdev;
+	unsigned long flags;
+
+	/* Alas, we need to grab scan_mutex to ensure SCSI device
+	 * state doesn't change underneath us and thus
+	 * scsi_device_get() always succeeds.  The mutex locking can
+	 * be removed if there is __scsi_device_get() interface which
+	 * increments reference counts regardless of device state.
+	 */
+	mutex_lock(&ap->host->scan_mutex);
+	spin_lock_irqsave(ap->lock, flags);
+
+	/* clearing dev->sdev is protected by host_set lock */
+	sdev = dev->sdev;
+	dev->sdev = NULL;
+
+	if (sdev) {
+		/* If user initiated unplug races with us, sdev can go
+		 * away underneath us after the host_set lock and
+		 * scan_mutex are released.  Hold onto it.
+		 */
+		if (scsi_device_get(sdev) == 0) {
+			/* The following ensures the attached sdev is
+			 * offline on return from ata_scsi_offline_dev()
+			 * regardless it wins or loses the race
+			 * against this function.
+			 */
+			scsi_device_set_state(sdev, SDEV_OFFLINE);
+		} else {
+			WARN_ON(1);
+			sdev = NULL;
+		}
+	}
+
+	spin_unlock_irqrestore(ap->lock, flags);
+	mutex_unlock(&ap->host->scan_mutex);
+
+	if (sdev) {
+		ata_dev_printk(dev, KERN_INFO, "detaching (SCSI %s)\n",
+			       sdev->sdev_gendev.bus_id);
+
+		scsi_remove_device(sdev);
+		scsi_device_put(sdev);
+	}
+}
+
+/**
+ *	ata_scsi_hotplug - SCSI part of hotplug
+ *	@data: Pointer to ATA port to perform SCSI hotplug on
+ *
+ *	Perform SCSI part of hotplug.  It's executed from a separate
+ *	workqueue after EH completes.  This is necessary because SCSI
+ *	hot plugging requires working EH and hot unplugging is
+ *	synchronized with hot plugging with a mutex.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+void ata_scsi_hotplug(void *data)
+{
+	struct ata_port *ap = data;
+	int i;
+
+	if (ap->flags & ATA_FLAG_UNLOADING) {
+		DPRINTK("ENTER/EXIT - unloading\n");
+		return;
+	}
+
+	DPRINTK("ENTER\n");
+
+	/* unplug detached devices */
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		unsigned long flags;
+
+		if (!(dev->flags & ATA_DFLAG_DETACHED))
+			continue;
+
+		spin_lock_irqsave(ap->lock, flags);
+		dev->flags &= ~ATA_DFLAG_DETACHED;
+		spin_unlock_irqrestore(ap->lock, flags);
+
+		ata_scsi_remove_dev(dev);
+	}
+
+	/* scan for new ones */
+	ata_scsi_scan_host(ap);
+
+	/* If we scanned while EH was in progress, scan would have
+	 * failed silently.  Requeue if there are enabled but
+	 * unattached devices.
+	 */
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+		if (ata_dev_enabled(dev) && !dev->sdev) {
+			queue_delayed_work(ata_aux_wq, &ap->hotplug_task, HZ);
+			break;
+		}
+	}
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_scsi_user_scan - indication for user-initiated bus scan
+ *	@shost: SCSI host to scan
+ *	@channel: Channel to scan
+ *	@id: ID to scan
+ *	@lun: LUN to scan
+ *
+ *	This function is called when user explicitly requests bus
+ *	scan.  Set probe pending flag and invoke EH.
+ *
+ *	LOCKING:
+ *	SCSI layer (we don't care)
+ *
+ *	RETURNS:
+ *	Zero.
+ */
+static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+			      unsigned int id, unsigned int lun)
+{
+	struct ata_port *ap = ata_shost_to_port(shost);
+	unsigned long flags;
+	int rc = 0;
+
+	if (!ap->ops->error_handler)
+		return -EOPNOTSUPP;
+
+	if ((channel != SCAN_WILD_CARD && channel != 0) ||
+	    (lun != SCAN_WILD_CARD && lun != 0))
+		return -EINVAL;
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	if (id == SCAN_WILD_CARD) {
+		ap->eh_info.probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+		ap->eh_info.action |= ATA_EH_SOFTRESET;
+	} else {
+		struct ata_device *dev = ata_find_dev(ap, id);
+
+		if (dev) {
+			ap->eh_info.probe_mask |= 1 << dev->devno;
+			ap->eh_info.action |= ATA_EH_SOFTRESET;
+		} else
+			rc = -EINVAL;
+	}
+
+	if (rc == 0)
+		ata_port_schedule_eh(ap);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	return rc;
+}
+
+/**
+ *	ata_scsi_dev_rescan - initiate scsi_rescan_device()
+ *	@data: Pointer to ATA port to perform scsi_rescan_device()
+ *
+ *	After ATA pass thru (SAT) commands are executed successfully,
+ *	libata need to propagate the changes to SCSI layer.  This
+ *	function must be executed from ata_aux_wq such that sdev
+ *	attach/detach don't race with rescan.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+void ata_scsi_dev_rescan(void *data)
+{
+	struct ata_port *ap = data;
+	struct ata_device *dev;
+	unsigned int i;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		dev = &ap->device[i];
 
-		if (ata_dev_present(dev))
-			scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0);
+		if (ata_dev_enabled(dev) && dev->sdev)
+			scsi_rescan_device(&(dev->sdev->sdev_gendev));
 	}
 }
-
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index bac8cba..c325679 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -29,10 +29,9 @@
 #define __LIBATA_H__
 
 #define DRV_NAME	"libata"
-#define DRV_VERSION	"1.20"	/* must be exactly four chars */
+#define DRV_VERSION	"2.00"	/* must be exactly four chars */
 
 struct ata_scsi_args {
-	struct ata_port		*ap;
 	struct ata_device	*dev;
 	u16			*id;
 	struct scsi_cmnd	*cmd;
@@ -40,18 +39,34 @@
 };
 
 /* libata-core.c */
+extern struct workqueue_struct *ata_aux_wq;
 extern int atapi_enabled;
+extern int atapi_dmadir;
 extern int libata_fua;
-extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
-				      struct ata_device *dev);
+extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
 extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
+extern void ata_dev_disable(struct ata_device *dev);
 extern void ata_port_flush_task(struct ata_port *ap);
+extern unsigned ata_exec_internal(struct ata_device *dev,
+				  struct ata_taskfile *tf, const u8 *cdb,
+				  int dma_dir, void *buf, unsigned int buflen);
+extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
+extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
+			   int post_reset, u16 *id);
+extern int ata_dev_configure(struct ata_device *dev, int print_info);
+extern int sata_down_spd_limit(struct ata_port *ap);
+extern int sata_set_spd_needed(struct ata_port *ap);
+extern int ata_down_xfermask_limit(struct ata_device *dev, int force_pio0);
+extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
 extern void ata_qc_issue(struct ata_queued_cmd *qc);
+extern void __ata_qc_complete(struct ata_queued_cmd *qc);
 extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+extern int ata_flush_cache(struct ata_device *dev);
+extern void ata_dev_init(struct ata_device *dev);
 extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
 
@@ -60,6 +75,8 @@
 extern struct scsi_transport_template ata_scsi_transport_template;
 
 extern void ata_scsi_scan_host(struct ata_port *ap);
+extern int ata_scsi_offline_dev(struct ata_device *dev);
+extern void ata_scsi_hotplug(void *data);
 extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
 			       unsigned int buflen);
 
@@ -88,5 +105,13 @@
 extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
                         unsigned int (*actor) (struct ata_scsi_args *args,
                                            u8 *rbuf, unsigned int buflen));
+extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
+extern void ata_scsi_dev_rescan(void *data);
+
+/* libata-eh.c */
+extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
+extern void ata_scsi_error(struct Scsi_Host *host);
+extern void ata_port_wait_eh(struct ata_port *ap);
+extern void ata_qc_schedule_eh(struct ata_queued_cmd *qc);
 
 #endif /* __LIBATA_H__ */
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
new file mode 100644
index 0000000..2673a11
--- /dev/null
+++ b/drivers/scsi/libiscsi.c
@@ -0,0 +1,1702 @@
+/*
+ * iSCSI lib functions
+ *
+ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004 - 2006 Mike Christie
+ * Copyright (C) 2004 - 2005 Dmitry Yusupov
+ * Copyright (C) 2004 - 2005 Alex Aizman
+ * maintained by open-iscsi@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/kfifo.h>
+#include <linux/delay.h>
+#include <net/tcp.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi.h>
+#include <scsi/iscsi_proto.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_iscsi.h>
+#include <scsi/libiscsi.h>
+
+struct iscsi_session *
+class_to_transport_session(struct iscsi_cls_session *cls_session)
+{
+	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+	return iscsi_hostdata(shost->hostdata);
+}
+EXPORT_SYMBOL_GPL(class_to_transport_session);
+
+#define INVALID_SN_DELTA	0xffff
+
+int
+iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
+{
+	uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn);
+	uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn);
+
+	if (max_cmdsn < exp_cmdsn -1 &&
+	    max_cmdsn > exp_cmdsn - INVALID_SN_DELTA)
+		return ISCSI_ERR_MAX_CMDSN;
+	if (max_cmdsn > session->max_cmdsn ||
+	    max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA)
+		session->max_cmdsn = max_cmdsn;
+	if (exp_cmdsn > session->exp_cmdsn ||
+	    exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA)
+		session->exp_cmdsn = exp_cmdsn;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn);
+
+void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask,
+				   struct iscsi_data *hdr,
+				   int transport_data_cnt)
+{
+	struct iscsi_conn *conn = ctask->conn;
+
+	memset(hdr, 0, sizeof(struct iscsi_data));
+	hdr->ttt = cpu_to_be32(ISCSI_RESERVED_TAG);
+	hdr->datasn = cpu_to_be32(ctask->unsol_datasn);
+	ctask->unsol_datasn++;
+	hdr->opcode = ISCSI_OP_SCSI_DATA_OUT;
+	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+
+	hdr->itt = ctask->hdr->itt;
+	hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+
+	hdr->offset = cpu_to_be32(ctask->total_length -
+				  transport_data_cnt -
+				  ctask->unsol_count);
+
+	if (ctask->unsol_count > conn->max_xmit_dlength) {
+		hton24(hdr->dlength, conn->max_xmit_dlength);
+		ctask->data_count = conn->max_xmit_dlength;
+		hdr->flags = 0;
+	} else {
+		hton24(hdr->dlength, ctask->unsol_count);
+		ctask->data_count = ctask->unsol_count;
+		hdr->flags = ISCSI_FLAG_CMD_FINAL;
+	}
+}
+EXPORT_SYMBOL_GPL(iscsi_prep_unsolicit_data_pdu);
+
+/**
+ * iscsi_prep_scsi_cmd_pdu - prep iscsi scsi cmd pdu
+ * @ctask: iscsi cmd task
+ *
+ * Prep basic iSCSI PDU fields for a scsi cmd pdu. The LLD should set
+ * fields like dlength or final based on how much data it sends
+ */
+static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_conn *conn = ctask->conn;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_cmd *hdr = ctask->hdr;
+	struct scsi_cmnd *sc = ctask->sc;
+
+        hdr->opcode = ISCSI_OP_SCSI_CMD;
+        hdr->flags = ISCSI_ATTR_SIMPLE;
+        int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun);
+        hdr->itt = ctask->itt | (conn->id << ISCSI_CID_SHIFT) |
+                         (session->age << ISCSI_AGE_SHIFT);
+        hdr->data_length = cpu_to_be32(sc->request_bufflen);
+        hdr->cmdsn = cpu_to_be32(session->cmdsn);
+        session->cmdsn++;
+        hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
+        memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
+        memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len);
+
+	if (sc->sc_data_direction == DMA_TO_DEVICE) {
+		hdr->flags |= ISCSI_FLAG_CMD_WRITE;
+		/*
+		 * Write counters:
+		 *
+		 *	imm_count	bytes to be sent right after
+		 *			SCSI PDU Header
+		 *
+		 *	unsol_count	bytes(as Data-Out) to be sent
+		 *			without	R2T ack right after
+		 *			immediate data
+		 *
+		 *	r2t_data_count	bytes to be sent via R2T ack's
+		 *
+		 *      pad_count       bytes to be sent as zero-padding
+		 */
+		ctask->imm_count = 0;
+		ctask->unsol_count = 0;
+		ctask->unsol_datasn = 0;
+
+		if (session->imm_data_en) {
+			if (ctask->total_length >= session->first_burst)
+				ctask->imm_count = min(session->first_burst,
+							conn->max_xmit_dlength);
+			else
+				ctask->imm_count = min(ctask->total_length,
+							conn->max_xmit_dlength);
+			hton24(ctask->hdr->dlength, ctask->imm_count);
+		} else
+			zero_data(ctask->hdr->dlength);
+
+		if (!session->initial_r2t_en)
+			ctask->unsol_count = min(session->first_burst,
+				ctask->total_length) - ctask->imm_count;
+		if (!ctask->unsol_count)
+			/* No unsolicit Data-Out's */
+			ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+	} else {
+		ctask->datasn = 0;
+		hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+		zero_data(hdr->dlength);
+
+		if (sc->sc_data_direction == DMA_FROM_DEVICE)
+			hdr->flags |= ISCSI_FLAG_CMD_READ;
+	}
+
+	conn->scsicmd_pdus_cnt++;
+}
+EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
+
+/**
+ * iscsi_complete_command - return command back to scsi-ml
+ * @session: iscsi session
+ * @ctask: iscsi cmd task
+ *
+ * Must be called with session lock.
+ * This function returns the scsi command to scsi-ml and returns
+ * the cmd task to the pool of available cmd tasks.
+ */
+static void iscsi_complete_command(struct iscsi_session *session,
+				   struct iscsi_cmd_task *ctask)
+{
+	struct scsi_cmnd *sc = ctask->sc;
+
+	ctask->sc = NULL;
+	list_del_init(&ctask->running);
+	__kfifo_put(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+	sc->scsi_done(sc);
+}
+
+/**
+ * iscsi_cmd_rsp - SCSI Command Response processing
+ * @conn: iscsi connection
+ * @hdr: iscsi header
+ * @ctask: scsi command task
+ * @data: cmd data buffer
+ * @datalen: len of buffer
+ *
+ * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and
+ * then completes the command and task.
+ **/
+static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+			      struct iscsi_cmd_task *ctask, char *data,
+			      int datalen)
+{
+	int rc;
+	struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr;
+	struct iscsi_session *session = conn->session;
+	struct scsi_cmnd *sc = ctask->sc;
+
+	rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
+	if (rc) {
+		sc->result = DID_ERROR << 16;
+		goto out;
+	}
+
+	conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1;
+
+	sc->result = (DID_OK << 16) | rhdr->cmd_status;
+
+	if (rhdr->response != ISCSI_STATUS_CMD_COMPLETED) {
+		sc->result = DID_ERROR << 16;
+		goto out;
+	}
+
+	if (rhdr->cmd_status == SAM_STAT_CHECK_CONDITION) {
+		int senselen;
+
+		if (datalen < 2) {
+invalid_datalen:
+			printk(KERN_ERR "iscsi: Got CHECK_CONDITION but "
+			       "invalid data buffer size of %d\n", datalen);
+			sc->result = DID_BAD_TARGET << 16;
+			goto out;
+		}
+
+		senselen = (data[0] << 8) | data[1];
+		if (datalen < senselen)
+			goto invalid_datalen;
+
+		memcpy(sc->sense_buffer, data + 2,
+		       min(senselen, SCSI_SENSE_BUFFERSIZE));
+		debug_scsi("copied %d bytes of sense\n",
+			   min(senselen, SCSI_SENSE_BUFFERSIZE));
+	}
+
+	if (sc->sc_data_direction == DMA_TO_DEVICE)
+		goto out;
+
+	if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) {
+		int res_count = be32_to_cpu(rhdr->residual_count);
+
+		if (res_count > 0 && res_count <= sc->request_bufflen)
+			sc->resid = res_count;
+		else
+			sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+	} else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW)
+		sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
+	else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW)
+		sc->resid = be32_to_cpu(rhdr->residual_count);
+
+out:
+	debug_scsi("done [sc %lx res %d itt 0x%x]\n",
+		   (long)sc, sc->result, ctask->itt);
+	conn->scsirsp_pdus_cnt++;
+
+	iscsi_complete_command(conn->session, ctask);
+	return rc;
+}
+
+/**
+ * __iscsi_complete_pdu - complete pdu
+ * @conn: iscsi conn
+ * @hdr: iscsi header
+ * @data: data buffer
+ * @datalen: len of data buffer
+ *
+ * Completes pdu processing by freeing any resources allocated at
+ * queuecommand or send generic. session lock must be held and verify
+ * itt must have been called.
+ */
+int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+			 char *data, int datalen)
+{
+	struct iscsi_session *session = conn->session;
+	int opcode = hdr->opcode & ISCSI_OPCODE_MASK, rc = 0;
+	struct iscsi_cmd_task *ctask;
+	struct iscsi_mgmt_task *mtask;
+	uint32_t itt;
+
+	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG))
+		itt = hdr->itt & ISCSI_ITT_MASK;
+	else
+		itt = hdr->itt;
+
+	if (itt < session->cmds_max) {
+		ctask = session->cmds[itt];
+
+		debug_scsi("cmdrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+			   opcode, conn->id, ctask->itt, datalen);
+
+		switch(opcode) {
+		case ISCSI_OP_SCSI_CMD_RSP:
+			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+			rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data,
+						datalen);
+			break;
+		case ISCSI_OP_SCSI_DATA_IN:
+			BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
+			if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
+				conn->scsirsp_pdus_cnt++;
+				iscsi_complete_command(session, ctask);
+			}
+			break;
+		case ISCSI_OP_R2T:
+			/* LLD handles this for now */
+			break;
+		default:
+			rc = ISCSI_ERR_BAD_OPCODE;
+			break;
+		}
+	} else if (itt >= ISCSI_MGMT_ITT_OFFSET &&
+		   itt < ISCSI_MGMT_ITT_OFFSET + session->mgmtpool_max) {
+		mtask = session->mgmt_cmds[itt - ISCSI_MGMT_ITT_OFFSET];
+
+		debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n",
+			   opcode, conn->id, mtask->itt, datalen);
+
+		rc = iscsi_check_assign_cmdsn(session,
+					      (struct iscsi_nopin*)hdr);
+		if (rc)
+			goto done;
+
+		switch(opcode) {
+		case ISCSI_OP_LOGOUT_RSP:
+			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+			/* fall through */
+		case ISCSI_OP_LOGIN_RSP:
+		case ISCSI_OP_TEXT_RSP:
+			/*
+			 * login related PDU's exp_statsn is handled in
+			 * userspace
+			 */
+			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
+			list_del(&mtask->running);
+			if (conn->login_mtask != mtask)
+				__kfifo_put(session->mgmtpool.queue,
+					    (void*)&mtask, sizeof(void*));
+			break;
+		case ISCSI_OP_SCSI_TMFUNC_RSP:
+			if (datalen) {
+				rc = ISCSI_ERR_PROTO;
+				break;
+			}
+
+			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+			conn->tmfrsp_pdus_cnt++;
+			if (conn->tmabort_state == TMABORT_INITIAL) {
+				conn->tmabort_state =
+					((struct iscsi_tm_rsp *)hdr)->
+					response == ISCSI_TMF_RSP_COMPLETE ?
+						TMABORT_SUCCESS:TMABORT_FAILED;
+				/* unblock eh_abort() */
+				wake_up(&conn->ehwait);
+			}
+			break;
+		case ISCSI_OP_NOOP_IN:
+			if (hdr->ttt != ISCSI_RESERVED_TAG) {
+				rc = ISCSI_ERR_PROTO;
+				break;
+			}
+			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+
+			rc = iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen);
+			list_del(&mtask->running);
+			if (conn->login_mtask != mtask)
+				__kfifo_put(session->mgmtpool.queue,
+					    (void*)&mtask, sizeof(void*));
+			break;
+		default:
+			rc = ISCSI_ERR_BAD_OPCODE;
+			break;
+		}
+	} else if (itt == ISCSI_RESERVED_TAG) {
+		switch(opcode) {
+		case ISCSI_OP_NOOP_IN:
+			if (!datalen) {
+				rc = iscsi_check_assign_cmdsn(session,
+						 (struct iscsi_nopin*)hdr);
+				if (!rc && hdr->ttt != ISCSI_RESERVED_TAG)
+					rc = iscsi_recv_pdu(conn->cls_conn,
+							    hdr, NULL, 0);
+			} else
+				rc = ISCSI_ERR_PROTO;
+			break;
+		case ISCSI_OP_REJECT:
+			/* we need sth like iscsi_reject_rsp()*/
+		case ISCSI_OP_ASYNC_EVENT:
+			conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1;
+			/* we need sth like iscsi_async_event_rsp() */
+			rc = ISCSI_ERR_BAD_OPCODE;
+			break;
+		default:
+			rc = ISCSI_ERR_BAD_OPCODE;
+			break;
+		}
+	} else
+		rc = ISCSI_ERR_BAD_ITT;
+
+done:
+	return rc;
+}
+EXPORT_SYMBOL_GPL(__iscsi_complete_pdu);
+
+int iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+		       char *data, int datalen)
+{
+	int rc;
+
+	spin_lock(&conn->session->lock);
+	rc = __iscsi_complete_pdu(conn, hdr, data, datalen);
+	spin_unlock(&conn->session->lock);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(iscsi_complete_pdu);
+
+/* verify itt (itt encoding: age+cid+itt) */
+int iscsi_verify_itt(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+		     uint32_t *ret_itt)
+{
+	struct iscsi_session *session = conn->session;
+	struct iscsi_cmd_task *ctask;
+	uint32_t itt;
+
+	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		if ((hdr->itt & ISCSI_AGE_MASK) !=
+		    (session->age << ISCSI_AGE_SHIFT)) {
+			printk(KERN_ERR "iscsi: received itt %x expected "
+				"session age (%x)\n", hdr->itt,
+				session->age & ISCSI_AGE_MASK);
+			return ISCSI_ERR_BAD_ITT;
+		}
+
+		if ((hdr->itt & ISCSI_CID_MASK) !=
+		    (conn->id << ISCSI_CID_SHIFT)) {
+			printk(KERN_ERR "iscsi: received itt %x, expected "
+				"CID (%x)\n", hdr->itt, conn->id);
+			return ISCSI_ERR_BAD_ITT;
+		}
+		itt = hdr->itt & ISCSI_ITT_MASK;
+	} else
+		itt = hdr->itt;
+
+	if (itt < session->cmds_max) {
+		ctask = session->cmds[itt];
+
+		if (!ctask->sc) {
+			printk(KERN_INFO "iscsi: dropping ctask with "
+			       "itt 0x%x\n", ctask->itt);
+			/* force drop */
+			return ISCSI_ERR_NO_SCSI_CMD;
+		}
+
+		if (ctask->sc->SCp.phase != session->age) {
+			printk(KERN_ERR "iscsi: ctask's session age %d, "
+				"expected %d\n", ctask->sc->SCp.phase,
+				session->age);
+			return ISCSI_ERR_SESSION_FAILED;
+		}
+	}
+
+	*ret_itt = itt;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_verify_itt);
+
+void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err)
+{
+	struct iscsi_session *session = conn->session;
+	unsigned long flags;
+
+	spin_lock_irqsave(&session->lock, flags);
+	if (session->state == ISCSI_STATE_FAILED) {
+		spin_unlock_irqrestore(&session->lock, flags);
+		return;
+	}
+
+	if (conn->stop_stage == 0)
+		session->state = ISCSI_STATE_FAILED;
+	spin_unlock_irqrestore(&session->lock, flags);
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+	iscsi_conn_error(conn->cls_conn, err);
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_failure);
+
+/**
+ * iscsi_data_xmit - xmit any command into the scheduled connection
+ * @conn: iscsi connection
+ *
+ * Notes:
+ *	The function can return -EAGAIN in which case the caller must
+ *	re-schedule it again later or recover. '0' return code means
+ *	successful xmit.
+ **/
+static int iscsi_data_xmit(struct iscsi_conn *conn)
+{
+	struct iscsi_transport *tt;
+	int rc = 0;
+
+	if (unlikely(conn->suspend_tx)) {
+		debug_scsi("conn %d Tx suspended!\n", conn->id);
+		return -ENODATA;
+	}
+	tt = conn->session->tt;
+
+	/*
+	 * Transmit in the following order:
+	 *
+	 * 1) un-finished xmit (ctask or mtask)
+	 * 2) immediate control PDUs
+	 * 3) write data
+	 * 4) SCSI commands
+	 * 5) non-immediate control PDUs
+	 *
+	 * No need to lock around __kfifo_get as long as
+	 * there's one producer and one consumer.
+	 */
+
+	BUG_ON(conn->ctask && conn->mtask);
+
+	if (conn->ctask) {
+		rc = tt->xmit_cmd_task(conn, conn->ctask);
+		if (rc)
+			goto again;
+		/* done with this in-progress ctask */
+		conn->ctask = NULL;
+	}
+	if (conn->mtask) {
+		rc = tt->xmit_mgmt_task(conn, conn->mtask);
+	        if (rc)
+		        goto again;
+		/* done with this in-progress mtask */
+		conn->mtask = NULL;
+	}
+
+	/* process immediate first */
+        if (unlikely(__kfifo_len(conn->immqueue))) {
+	        while (__kfifo_get(conn->immqueue, (void*)&conn->mtask,
+			           sizeof(void*))) {
+			spin_lock_bh(&conn->session->lock);
+			list_add_tail(&conn->mtask->running,
+				      &conn->mgmt_run_list);
+			spin_unlock_bh(&conn->session->lock);
+			rc = tt->xmit_mgmt_task(conn, conn->mtask);
+		        if (rc)
+			        goto again;
+	        }
+		/* done with this mtask */
+		conn->mtask = NULL;
+	}
+
+	/* process command queue */
+	while (__kfifo_get(conn->xmitqueue, (void*)&conn->ctask,
+			   sizeof(void*))) {
+		/*
+		 * iscsi tcp may readd the task to the xmitqueue to send
+		 * write data
+		 */
+		spin_lock_bh(&conn->session->lock);
+		if (list_empty(&conn->ctask->running))
+			list_add_tail(&conn->ctask->running, &conn->run_list);
+		spin_unlock_bh(&conn->session->lock);
+		rc = tt->xmit_cmd_task(conn, conn->ctask);
+		if (rc)
+			goto again;
+	}
+	/* done with this ctask */
+	conn->ctask = NULL;
+
+	/* process the rest control plane PDUs, if any */
+        if (unlikely(__kfifo_len(conn->mgmtqueue))) {
+	        while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask,
+			           sizeof(void*))) {
+			spin_lock_bh(&conn->session->lock);
+			list_add_tail(&conn->mtask->running,
+				      &conn->mgmt_run_list);
+			spin_unlock_bh(&conn->session->lock);
+		        rc = tt->xmit_mgmt_task(conn, conn->mtask);
+			if (rc)
+			        goto again;
+	        }
+		/* done with this mtask */
+		conn->mtask = NULL;
+	}
+
+	return -ENODATA;
+
+again:
+	if (unlikely(conn->suspend_tx))
+		return -ENODATA;
+
+	return rc;
+}
+
+static void iscsi_xmitworker(void *data)
+{
+	struct iscsi_conn *conn = data;
+	int rc;
+	/*
+	 * serialize Xmit worker on a per-connection basis.
+	 */
+	mutex_lock(&conn->xmitmutex);
+	do {
+		rc = iscsi_data_xmit(conn);
+	} while (rc >= 0 || rc == -EAGAIN);
+	mutex_unlock(&conn->xmitmutex);
+}
+
+enum {
+	FAILURE_BAD_HOST = 1,
+	FAILURE_SESSION_FAILED,
+	FAILURE_SESSION_FREED,
+	FAILURE_WINDOW_CLOSED,
+	FAILURE_SESSION_TERMINATE,
+	FAILURE_SESSION_IN_RECOVERY,
+	FAILURE_SESSION_RECOVERY_TIMEOUT,
+};
+
+int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
+{
+	struct Scsi_Host *host;
+	int reason = 0;
+	struct iscsi_session *session;
+	struct iscsi_conn *conn;
+	struct iscsi_cmd_task *ctask = NULL;
+
+	sc->scsi_done = done;
+	sc->result = 0;
+
+	host = sc->device->host;
+	session = iscsi_hostdata(host->hostdata);
+
+	spin_lock(&session->lock);
+
+	/*
+	 * ISCSI_STATE_FAILED is a temp. state. The recovery
+	 * code will decide what is best to do with command queued
+	 * during this time
+	 */
+	if (session->state != ISCSI_STATE_LOGGED_IN &&
+	    session->state != ISCSI_STATE_FAILED) {
+		/*
+		 * to handle the race between when we set the recovery state
+		 * and block the session we requeue here (commands could
+		 * be entering our queuecommand while a block is starting
+		 * up because the block code is not locked)
+		 */
+		if (session->state == ISCSI_STATE_IN_RECOVERY) {
+			reason = FAILURE_SESSION_IN_RECOVERY;
+			goto reject;
+		}
+
+		if (session->state == ISCSI_STATE_RECOVERY_FAILED)
+			reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
+		else if (session->state == ISCSI_STATE_TERMINATE)
+			reason = FAILURE_SESSION_TERMINATE;
+		else
+			reason = FAILURE_SESSION_FREED;
+		goto fault;
+	}
+
+	/*
+	 * Check for iSCSI window and take care of CmdSN wrap-around
+	 */
+	if ((int)(session->max_cmdsn - session->cmdsn) < 0) {
+		reason = FAILURE_WINDOW_CLOSED;
+		goto reject;
+	}
+
+	conn = session->leadconn;
+
+	__kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*));
+	sc->SCp.phase = session->age;
+	sc->SCp.ptr = (char *)ctask;
+
+	ctask->mtask = NULL;
+	ctask->conn = conn;
+	ctask->sc = sc;
+	INIT_LIST_HEAD(&ctask->running);
+	ctask->total_length = sc->request_bufflen;
+	iscsi_prep_scsi_cmd_pdu(ctask);
+
+	session->tt->init_cmd_task(ctask);
+
+	__kfifo_put(conn->xmitqueue, (void*)&ctask, sizeof(void*));
+	debug_scsi(
+	       "ctask enq [%s cid %d sc %lx itt 0x%x len %d cmdsn %d win %d]\n",
+		sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read",
+		conn->id, (long)sc, ctask->itt, sc->request_bufflen,
+		session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+	spin_unlock(&session->lock);
+
+	scsi_queue_work(host, &conn->xmitwork);
+	return 0;
+
+reject:
+	spin_unlock(&session->lock);
+	debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
+	return SCSI_MLQUEUE_HOST_BUSY;
+
+fault:
+	spin_unlock(&session->lock);
+	printk(KERN_ERR "iscsi: cmd 0x%x is not queued (%d)\n",
+	       sc->cmnd[0], reason);
+	sc->result = (DID_NO_CONNECT << 16);
+	sc->resid = sc->request_bufflen;
+	sc->scsi_done(sc);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_queuecommand);
+
+int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
+{
+	if (depth > ISCSI_MAX_CMD_PER_LUN)
+		depth = ISCSI_MAX_CMD_PER_LUN;
+	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+	return sdev->queue_depth;
+}
+EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+
+static int
+iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
+			char *data, uint32_t data_size)
+{
+	struct iscsi_session *session = conn->session;
+	struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr;
+	struct iscsi_mgmt_task *mtask;
+
+	spin_lock_bh(&session->lock);
+	if (session->state == ISCSI_STATE_TERMINATE) {
+		spin_unlock_bh(&session->lock);
+		return -EPERM;
+	}
+	if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) ||
+	    hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE))
+		/*
+		 * Login and Text are sent serially, in
+		 * request-followed-by-response sequence.
+		 * Same mtask can be used. Same ITT must be used.
+		 * Note that login_mtask is preallocated at conn_create().
+		 */
+		mtask = conn->login_mtask;
+	else {
+		BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+		BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+
+		nop->exp_statsn = cpu_to_be32(conn->exp_statsn);
+		if (!__kfifo_get(session->mgmtpool.queue,
+				 (void*)&mtask, sizeof(void*))) {
+			spin_unlock_bh(&session->lock);
+			return -ENOSPC;
+		}
+	}
+
+	/*
+	 * pre-format CmdSN for outgoing PDU.
+	 */
+	if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
+		hdr->itt = mtask->itt | (conn->id << ISCSI_CID_SHIFT) |
+			   (session->age << ISCSI_AGE_SHIFT);
+		nop->cmdsn = cpu_to_be32(session->cmdsn);
+		if (conn->c_stage == ISCSI_CONN_STARTED &&
+		    !(hdr->opcode & ISCSI_OP_IMMEDIATE))
+			session->cmdsn++;
+	} else
+		/* do not advance CmdSN */
+		nop->cmdsn = cpu_to_be32(session->cmdsn);
+
+	if (data_size) {
+		memcpy(mtask->data, data, data_size);
+		mtask->data_count = data_size;
+	} else
+		mtask->data_count = 0;
+
+	INIT_LIST_HEAD(&mtask->running);
+	memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr));
+	if (session->tt->init_mgmt_task)
+		session->tt->init_mgmt_task(conn, mtask, data, data_size);
+	spin_unlock_bh(&session->lock);
+
+	debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
+		   hdr->opcode, hdr->itt, data_size);
+
+	/*
+	 * since send_pdu() could be called at least from two contexts,
+	 * we need to serialize __kfifo_put, so we don't have to take
+	 * additional lock on fast data-path
+	 */
+        if (hdr->opcode & ISCSI_OP_IMMEDIATE)
+	        __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*));
+	else
+	        __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*));
+
+	scsi_queue_work(session->host, &conn->xmitwork);
+	return 0;
+}
+
+int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr,
+			char *data, uint32_t data_size)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	int rc;
+
+	mutex_lock(&conn->xmitmutex);
+	rc = iscsi_conn_send_generic(conn, hdr, data, data_size);
+	mutex_unlock(&conn->xmitmutex);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu);
+
+void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
+{
+	struct iscsi_session *session = class_to_transport_session(cls_session);
+	struct iscsi_conn *conn = session->leadconn;
+
+	spin_lock_bh(&session->lock);
+	if (session->state != ISCSI_STATE_LOGGED_IN) {
+		session->state = ISCSI_STATE_RECOVERY_FAILED;
+		if (conn)
+			wake_up(&conn->ehwait);
+	}
+	spin_unlock_bh(&session->lock);
+}
+EXPORT_SYMBOL_GPL(iscsi_session_recovery_timedout);
+
+int iscsi_eh_host_reset(struct scsi_cmnd *sc)
+{
+	struct Scsi_Host *host = sc->device->host;
+	struct iscsi_session *session = iscsi_hostdata(host->hostdata);
+	struct iscsi_conn *conn = session->leadconn;
+	int fail_session = 0;
+
+	spin_lock_bh(&session->lock);
+	if (session->state == ISCSI_STATE_TERMINATE) {
+failed:
+		debug_scsi("failing host reset: session terminated "
+			   "[CID %d age %d]", conn->id, session->age);
+		spin_unlock_bh(&session->lock);
+		return FAILED;
+	}
+
+	if (sc->SCp.phase == session->age) {
+		debug_scsi("failing connection CID %d due to SCSI host reset",
+			   conn->id);
+		fail_session = 1;
+	}
+	spin_unlock_bh(&session->lock);
+
+	/*
+	 * we drop the lock here but the leadconn cannot be destoyed while
+	 * we are in the scsi eh
+	 */
+	if (fail_session)
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+
+	debug_scsi("iscsi_eh_host_reset wait for relogin\n");
+	wait_event_interruptible(conn->ehwait,
+				 session->state == ISCSI_STATE_TERMINATE ||
+				 session->state == ISCSI_STATE_LOGGED_IN ||
+				 session->state == ISCSI_STATE_RECOVERY_FAILED);
+	if (signal_pending(current))
+		flush_signals(current);
+
+	spin_lock_bh(&session->lock);
+	if (session->state == ISCSI_STATE_LOGGED_IN)
+		printk(KERN_INFO "iscsi: host reset succeeded\n");
+	else
+		goto failed;
+	spin_unlock_bh(&session->lock);
+
+	return SUCCESS;
+}
+EXPORT_SYMBOL_GPL(iscsi_eh_host_reset);
+
+static void iscsi_tmabort_timedout(unsigned long data)
+{
+	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data;
+	struct iscsi_conn *conn = ctask->conn;
+	struct iscsi_session *session = conn->session;
+
+	spin_lock(&session->lock);
+	if (conn->tmabort_state == TMABORT_INITIAL) {
+		conn->tmabort_state = TMABORT_TIMEDOUT;
+		debug_scsi("tmabort timedout [sc %p itt 0x%x]\n",
+			ctask->sc, ctask->itt);
+		/* unblock eh_abort() */
+		wake_up(&conn->ehwait);
+	}
+	spin_unlock(&session->lock);
+}
+
+/* must be called with the mutex lock */
+static int iscsi_exec_abort_task(struct scsi_cmnd *sc,
+				 struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_conn *conn = ctask->conn;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_tm *hdr = &conn->tmhdr;
+	int rc;
+
+	/*
+	 * ctask timed out but session is OK requests must be serialized.
+	 */
+	memset(hdr, 0, sizeof(struct iscsi_tm));
+	hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE;
+	hdr->flags = ISCSI_TM_FUNC_ABORT_TASK;
+	hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+	memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun));
+	hdr->rtt = ctask->hdr->itt;
+	hdr->refcmdsn = ctask->hdr->cmdsn;
+
+	rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr,
+				     NULL, 0);
+	if (rc) {
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+		debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc);
+		return rc;
+	}
+
+	debug_scsi("abort sent [itt 0x%x]\n", ctask->itt);
+
+	spin_lock_bh(&session->lock);
+	ctask->mtask = (struct iscsi_mgmt_task *)
+			session->mgmt_cmds[(hdr->itt & ISCSI_ITT_MASK) -
+					ISCSI_MGMT_ITT_OFFSET];
+
+	if (conn->tmabort_state == TMABORT_INITIAL) {
+		conn->tmfcmd_pdus_cnt++;
+		conn->tmabort_timer.expires = 10*HZ + jiffies;
+		conn->tmabort_timer.function = iscsi_tmabort_timedout;
+		conn->tmabort_timer.data = (unsigned long)ctask;
+		add_timer(&conn->tmabort_timer);
+		debug_scsi("abort set timeout [itt 0x%x]", ctask->itt);
+	}
+	spin_unlock_bh(&session->lock);
+	mutex_unlock(&conn->xmitmutex);
+
+	/*
+	 * block eh thread until:
+	 *
+	 * 1) abort response
+	 * 2) abort timeout
+	 * 3) session is terminated or restarted or userspace has
+	 * given up on recovery
+	 */
+	wait_event_interruptible(conn->ehwait,
+				 sc->SCp.phase != session->age ||
+				 session->state != ISCSI_STATE_LOGGED_IN ||
+				 conn->tmabort_state != TMABORT_INITIAL);
+	if (signal_pending(current))
+		flush_signals(current);
+	del_timer_sync(&conn->tmabort_timer);
+
+	mutex_lock(&conn->xmitmutex);
+	return 0;
+}
+
+/*
+ * xmit mutex and session lock must be held
+ */
+#define iscsi_remove_task(tasktype)					\
+static struct iscsi_##tasktype *					\
+iscsi_remove_##tasktype(struct kfifo *fifo, uint32_t itt)		\
+{									\
+	int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*);		\
+	struct iscsi_##tasktype *task;					\
+									\
+	debug_scsi("searching %d tasks\n", nr_tasks);			\
+									\
+	for (i = 0; i < nr_tasks; i++) {				\
+		__kfifo_get(fifo, (void*)&task, sizeof(void*));		\
+		debug_scsi("check task %u\n", task->itt);		\
+									\
+		if (task->itt == itt) {					\
+			debug_scsi("matched task\n");			\
+			return task;					\
+		}							\
+									\
+		__kfifo_put(fifo, (void*)&task, sizeof(void*));		\
+	}								\
+	return NULL;							\
+}
+
+iscsi_remove_task(mgmt_task);
+iscsi_remove_task(cmd_task);
+
+static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask)
+{
+	struct iscsi_conn *conn = ctask->conn;
+	struct iscsi_session *session = conn->session;
+
+	if (!ctask->mtask)
+		return -EINVAL;
+
+	if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt))
+		list_del(&ctask->mtask->running);
+	__kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask,
+		    sizeof(void*));
+	ctask->mtask = NULL;
+	return 0;
+}
+
+/*
+ * session lock and xmitmutex must be held
+ */
+static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+			 int err)
+{
+	struct scsi_cmnd *sc;
+
+	conn->session->tt->cleanup_cmd_task(conn, ctask);
+	iscsi_ctask_mtask_cleanup(ctask);
+
+	sc = ctask->sc;
+	if (!sc)
+		return;
+	sc->result = err;
+	sc->resid = sc->request_bufflen;
+	iscsi_complete_command(conn->session, ctask);
+}
+
+int iscsi_eh_abort(struct scsi_cmnd *sc)
+{
+	struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)sc->SCp.ptr;
+	struct iscsi_conn *conn = ctask->conn;
+	struct iscsi_session *session = conn->session;
+	struct iscsi_cmd_task *pending_ctask;
+	int rc;
+
+	conn->eh_abort_cnt++;
+	debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt);
+
+	mutex_lock(&conn->xmitmutex);
+	spin_lock_bh(&session->lock);
+
+	/*
+	 * If we are not logged in or we have started a new session
+	 * then let the host reset code handle this
+	 */
+	if (session->state != ISCSI_STATE_LOGGED_IN ||
+	    sc->SCp.phase != session->age)
+		goto failed;
+
+	/* ctask completed before time out */
+	if (!ctask->sc)
+		goto success;
+
+	/* what should we do here ? */
+	if (conn->ctask == ctask) {
+		printk(KERN_INFO "iscsi: sc %p itt 0x%x partially sent. "
+		       "Failing abort\n", sc, ctask->itt);
+		goto failed;
+	}
+
+	/* check for the easy pending cmd abort */
+	pending_ctask = iscsi_remove_cmd_task(conn->xmitqueue, ctask->itt);
+	if (pending_ctask) {
+		/* iscsi_tcp queues write transfers on the xmitqueue */
+		if (list_empty(&pending_ctask->running)) {
+			debug_scsi("found pending task\n");
+			goto success;
+		} else
+			__kfifo_put(conn->xmitqueue, (void*)&pending_ctask,
+				    sizeof(void*));
+	}
+
+	conn->tmabort_state = TMABORT_INITIAL;
+
+	spin_unlock_bh(&session->lock);
+	rc = iscsi_exec_abort_task(sc, ctask);
+	spin_lock_bh(&session->lock);
+
+	iscsi_ctask_mtask_cleanup(ctask);
+	if (rc || sc->SCp.phase != session->age ||
+	    session->state != ISCSI_STATE_LOGGED_IN)
+		goto failed;
+
+	/* ctask completed before tmf abort response */
+	if (!ctask->sc) {
+		debug_scsi("sc completed while abort in progress\n");
+		goto success;
+	}
+
+	if (conn->tmabort_state != TMABORT_SUCCESS) {
+		spin_unlock_bh(&session->lock);
+		iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+		spin_lock_bh(&session->lock);
+		goto failed;
+	}
+
+success:
+	debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+	spin_unlock_bh(&session->lock);
+
+	/*
+	 * clean up task if aborted. we have the xmitmutex so grab
+	 * the recv lock as a writer
+	 */
+	write_lock_bh(conn->recv_lock);
+	spin_lock(&session->lock);
+	fail_command(conn, ctask, DID_ABORT << 16);
+	spin_unlock(&session->lock);
+	write_unlock_bh(conn->recv_lock);
+
+	mutex_unlock(&conn->xmitmutex);
+	return SUCCESS;
+
+failed:
+	spin_unlock_bh(&session->lock);
+	mutex_unlock(&conn->xmitmutex);
+
+	debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt);
+	return FAILED;
+}
+EXPORT_SYMBOL_GPL(iscsi_eh_abort);
+
+int
+iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
+{
+	int i;
+
+	*items = kmalloc(max * sizeof(void*), GFP_KERNEL);
+	if (*items == NULL)
+		return -ENOMEM;
+
+	q->max = max;
+	q->pool = kmalloc(max * sizeof(void*), GFP_KERNEL);
+	if (q->pool == NULL) {
+		kfree(*items);
+		return -ENOMEM;
+	}
+
+	q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
+			      GFP_KERNEL, NULL);
+	if (q->queue == ERR_PTR(-ENOMEM)) {
+		kfree(q->pool);
+		kfree(*items);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < max; i++) {
+		q->pool[i] = kmalloc(item_size, GFP_KERNEL);
+		if (q->pool[i] == NULL) {
+			int j;
+
+			for (j = 0; j < i; j++)
+				kfree(q->pool[j]);
+
+			kfifo_free(q->queue);
+			kfree(q->pool);
+			kfree(*items);
+			return -ENOMEM;
+		}
+		memset(q->pool[i], 0, item_size);
+		(*items)[i] = q->pool[i];
+		__kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*));
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_pool_init);
+
+void iscsi_pool_free(struct iscsi_queue *q, void **items)
+{
+	int i;
+
+	for (i = 0; i < q->max; i++)
+		kfree(items[i]);
+	kfree(q->pool);
+	kfree(items);
+}
+EXPORT_SYMBOL_GPL(iscsi_pool_free);
+
+/*
+ * iSCSI Session's hostdata organization:
+ *
+ *    *------------------* <== hostdata_session(host->hostdata)
+ *    | ptr to class sess|
+ *    |------------------| <== iscsi_hostdata(host->hostdata)
+ *    | iscsi_session    |
+ *    *------------------*
+ */
+
+#define hostdata_privsize(_sz)	(sizeof(unsigned long) + _sz + \
+				 _sz % sizeof(unsigned long))
+
+#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
+
+/**
+ * iscsi_session_setup - create iscsi cls session and host and session
+ * @scsit: scsi transport template
+ * @iscsit: iscsi transport template
+ * @initial_cmdsn: initial CmdSN
+ * @hostno: host no allocated
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+struct iscsi_cls_session *
+iscsi_session_setup(struct iscsi_transport *iscsit,
+		    struct scsi_transport_template *scsit,
+		    int cmd_task_size, int mgmt_task_size,
+		    uint32_t initial_cmdsn, uint32_t *hostno)
+{
+	struct Scsi_Host *shost;
+	struct iscsi_session *session;
+	struct iscsi_cls_session *cls_session;
+	int cmd_i;
+
+	shost = scsi_host_alloc(iscsit->host_template,
+				hostdata_privsize(sizeof(*session)));
+	if (!shost)
+		return NULL;
+
+	shost->max_id = 1;
+	shost->max_channel = 0;
+	shost->max_lun = iscsit->max_lun;
+	shost->max_cmd_len = iscsit->max_cmd_len;
+	shost->transportt = scsit;
+	shost->transportt->create_work_queue = 1;
+	*hostno = shost->host_no;
+
+	session = iscsi_hostdata(shost->hostdata);
+	memset(session, 0, sizeof(struct iscsi_session));
+	session->host = shost;
+	session->state = ISCSI_STATE_FREE;
+	session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX;
+	session->cmds_max = ISCSI_XMIT_CMDS_MAX;
+	session->cmdsn = initial_cmdsn;
+	session->exp_cmdsn = initial_cmdsn + 1;
+	session->max_cmdsn = initial_cmdsn + 1;
+	session->max_r2t = 1;
+	session->tt = iscsit;
+
+	/* initialize SCSI PDU commands pool */
+	if (iscsi_pool_init(&session->cmdpool, session->cmds_max,
+			    (void***)&session->cmds,
+			    cmd_task_size + sizeof(struct iscsi_cmd_task)))
+		goto cmdpool_alloc_fail;
+
+	/* pre-format cmds pool with ITT */
+	for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
+		struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
+
+		if (cmd_task_size)
+			ctask->dd_data = &ctask[1];
+		ctask->itt = cmd_i;
+	}
+
+	spin_lock_init(&session->lock);
+	INIT_LIST_HEAD(&session->connections);
+
+	/* initialize immediate command pool */
+	if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max,
+			   (void***)&session->mgmt_cmds,
+			   mgmt_task_size + sizeof(struct iscsi_mgmt_task)))
+		goto mgmtpool_alloc_fail;
+
+
+	/* pre-format immediate cmds pool with ITT */
+	for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
+		struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];
+
+		if (mgmt_task_size)
+			mtask->dd_data = &mtask[1];
+		mtask->itt = ISCSI_MGMT_ITT_OFFSET + cmd_i;
+	}
+
+	if (scsi_add_host(shost, NULL))
+		goto add_host_fail;
+
+	cls_session = iscsi_create_session(shost, iscsit, 0);
+	if (!cls_session)
+		goto cls_session_fail;
+	*(unsigned long*)shost->hostdata = (unsigned long)cls_session;
+
+	return cls_session;
+
+cls_session_fail:
+	scsi_remove_host(shost);
+add_host_fail:
+	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+mgmtpool_alloc_fail:
+	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+cmdpool_alloc_fail:
+	scsi_host_put(shost);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(iscsi_session_setup);
+
+/**
+ * iscsi_session_teardown - destroy session, host, and cls_session
+ * shost: scsi host
+ *
+ * This can be used by software iscsi_transports that allocate
+ * a session per scsi host.
+ **/
+void iscsi_session_teardown(struct iscsi_cls_session *cls_session)
+{
+	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
+	struct iscsi_session *session = iscsi_hostdata(shost->hostdata);
+
+	scsi_remove_host(shost);
+
+	iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds);
+	iscsi_pool_free(&session->cmdpool, (void**)session->cmds);
+
+	iscsi_destroy_session(cls_session);
+	scsi_host_put(shost);
+}
+EXPORT_SYMBOL_GPL(iscsi_session_teardown);
+
+/**
+ * iscsi_conn_setup - create iscsi_cls_conn and iscsi_conn
+ * @cls_session: iscsi_cls_session
+ * @conn_idx: cid
+ **/
+struct iscsi_cls_conn *
+iscsi_conn_setup(struct iscsi_cls_session *cls_session, uint32_t conn_idx)
+{
+	struct iscsi_session *session = class_to_transport_session(cls_session);
+	struct iscsi_conn *conn;
+	struct iscsi_cls_conn *cls_conn;
+	char *data;
+
+	cls_conn = iscsi_create_conn(cls_session, conn_idx);
+	if (!cls_conn)
+		return NULL;
+	conn = cls_conn->dd_data;
+	memset(conn, 0, sizeof(*conn));
+
+	conn->session = session;
+	conn->cls_conn = cls_conn;
+	conn->c_stage = ISCSI_CONN_INITIAL_STAGE;
+	conn->id = conn_idx;
+	conn->exp_statsn = 0;
+	conn->tmabort_state = TMABORT_INITIAL;
+	INIT_LIST_HEAD(&conn->run_list);
+	INIT_LIST_HEAD(&conn->mgmt_run_list);
+
+	/* initialize general xmit PDU commands queue */
+	conn->xmitqueue = kfifo_alloc(session->cmds_max * sizeof(void*),
+					GFP_KERNEL, NULL);
+	if (conn->xmitqueue == ERR_PTR(-ENOMEM))
+		goto xmitqueue_alloc_fail;
+
+	/* initialize general immediate & non-immediate PDU commands queue */
+	conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+			                GFP_KERNEL, NULL);
+	if (conn->immqueue == ERR_PTR(-ENOMEM))
+		goto immqueue_alloc_fail;
+
+	conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*),
+			                GFP_KERNEL, NULL);
+	if (conn->mgmtqueue == ERR_PTR(-ENOMEM))
+		goto mgmtqueue_alloc_fail;
+
+	INIT_WORK(&conn->xmitwork, iscsi_xmitworker, conn);
+
+	/* allocate login_mtask used for the login/text sequences */
+	spin_lock_bh(&session->lock);
+	if (!__kfifo_get(session->mgmtpool.queue,
+                         (void*)&conn->login_mtask,
+			 sizeof(void*))) {
+		spin_unlock_bh(&session->lock);
+		goto login_mtask_alloc_fail;
+	}
+	spin_unlock_bh(&session->lock);
+
+	data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL);
+	if (!data)
+		goto login_mtask_data_alloc_fail;
+	conn->login_mtask->data = data;
+
+	init_timer(&conn->tmabort_timer);
+	mutex_init(&conn->xmitmutex);
+	init_waitqueue_head(&conn->ehwait);
+
+	return cls_conn;
+
+login_mtask_data_alloc_fail:
+	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+		    sizeof(void*));
+login_mtask_alloc_fail:
+	kfifo_free(conn->mgmtqueue);
+mgmtqueue_alloc_fail:
+	kfifo_free(conn->immqueue);
+immqueue_alloc_fail:
+	kfifo_free(conn->xmitqueue);
+xmitqueue_alloc_fail:
+	iscsi_destroy_conn(cls_conn);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_setup);
+
+/**
+ * iscsi_conn_teardown - teardown iscsi connection
+ * cls_conn: iscsi class connection
+ *
+ * TODO: we may need to make this into a two step process
+ * like scsi-mls remove + put host
+ */
+void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+	unsigned long flags;
+
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+	mutex_lock(&conn->xmitmutex);
+	if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE) {
+		if (session->tt->suspend_conn_recv)
+			session->tt->suspend_conn_recv(conn);
+
+		session->tt->terminate_conn(conn);
+	}
+
+	spin_lock_bh(&session->lock);
+	conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
+	if (session->leadconn == conn) {
+		/*
+		 * leading connection? then give up on recovery.
+		 */
+		session->state = ISCSI_STATE_TERMINATE;
+		wake_up(&conn->ehwait);
+	}
+	spin_unlock_bh(&session->lock);
+
+	mutex_unlock(&conn->xmitmutex);
+
+	/*
+	 * Block until all in-progress commands for this connection
+	 * time out or fail.
+	 */
+	for (;;) {
+		spin_lock_irqsave(session->host->host_lock, flags);
+		if (!session->host->host_busy) { /* OK for ERL == 0 */
+			spin_unlock_irqrestore(session->host->host_lock, flags);
+			break;
+		}
+		spin_unlock_irqrestore(session->host->host_lock, flags);
+		msleep_interruptible(500);
+		printk(KERN_INFO "iscsi: scsi conn_destroy(): host_busy %d "
+		       "host_failed %d\n", session->host->host_busy,
+		       session->host->host_failed);
+		/*
+		 * force eh_abort() to unblock
+		 */
+		wake_up(&conn->ehwait);
+	}
+
+	spin_lock_bh(&session->lock);
+	kfree(conn->login_mtask->data);
+	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
+		    sizeof(void*));
+	list_del(&conn->item);
+	if (list_empty(&session->connections))
+		session->leadconn = NULL;
+	if (session->leadconn && session->leadconn == conn)
+		session->leadconn = container_of(session->connections.next,
+			struct iscsi_conn, item);
+
+	if (session->leadconn == NULL)
+		/* no connections exits.. reset sequencing */
+		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
+	spin_unlock_bh(&session->lock);
+
+	kfifo_free(conn->xmitqueue);
+	kfifo_free(conn->immqueue);
+	kfifo_free(conn->mgmtqueue);
+
+	iscsi_destroy_conn(cls_conn);
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_teardown);
+
+int iscsi_conn_start(struct iscsi_cls_conn *cls_conn)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+
+	if (session == NULL) {
+		printk(KERN_ERR "iscsi: can't start unbound connection\n");
+		return -EPERM;
+	}
+
+	spin_lock_bh(&session->lock);
+	conn->c_stage = ISCSI_CONN_STARTED;
+	session->state = ISCSI_STATE_LOGGED_IN;
+
+	switch(conn->stop_stage) {
+	case STOP_CONN_RECOVER:
+		/*
+		 * unblock eh_abort() if it is blocked. re-try all
+		 * commands after successful recovery
+		 */
+		conn->stop_stage = 0;
+		conn->tmabort_state = TMABORT_INITIAL;
+		session->age++;
+		spin_unlock_bh(&session->lock);
+
+		iscsi_unblock_session(session_to_cls(session));
+		wake_up(&conn->ehwait);
+		return 0;
+	case STOP_CONN_TERM:
+		conn->stop_stage = 0;
+		break;
+	default:
+		break;
+	}
+	spin_unlock_bh(&session->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_start);
+
+static void
+flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
+{
+	struct iscsi_mgmt_task *mtask, *tmp;
+
+	/* handle pending */
+	while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) ||
+	       __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) {
+		if (mtask == conn->login_mtask)
+			continue;
+		debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
+		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+			    sizeof(void*));
+	}
+
+	/* handle running */
+	list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
+		debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
+		list_del(&mtask->running);
+
+		if (mtask == conn->login_mtask)
+			continue;
+		__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
+			   sizeof(void*));
+	}
+
+	conn->mtask = NULL;
+}
+
+/* Fail commands. Mutex and session lock held and recv side suspended */
+static void fail_all_commands(struct iscsi_conn *conn)
+{
+	struct iscsi_cmd_task *ctask, *tmp;
+
+	/* flush pending */
+	while (__kfifo_get(conn->xmitqueue, (void*)&ctask, sizeof(void*))) {
+		debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc,
+			   ctask->itt);
+		fail_command(conn, ctask, DID_BUS_BUSY << 16);
+	}
+
+	/* fail all other running */
+	list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) {
+		debug_scsi("failing in progress sc %p itt 0x%x\n",
+			   ctask->sc, ctask->itt);
+		fail_command(conn, ctask, DID_BUS_BUSY << 16);
+	}
+
+	conn->ctask = NULL;
+}
+
+static void iscsi_start_session_recovery(struct iscsi_session *session,
+					 struct iscsi_conn *conn, int flag)
+{
+	int old_stop_stage;
+
+	spin_lock_bh(&session->lock);
+	if (conn->stop_stage == STOP_CONN_TERM) {
+		spin_unlock_bh(&session->lock);
+		return;
+	}
+
+	/*
+	 * When this is called for the in_login state, we only want to clean
+	 * up the login task and connection. We do not need to block and set
+	 * the recovery state again
+	 */
+	if (flag == STOP_CONN_TERM)
+		session->state = ISCSI_STATE_TERMINATE;
+	else if (conn->stop_stage != STOP_CONN_RECOVER)
+		session->state = ISCSI_STATE_IN_RECOVERY;
+
+	old_stop_stage = conn->stop_stage;
+	conn->stop_stage = flag;
+	conn->c_stage = ISCSI_CONN_STOPPED;
+	set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+	spin_unlock_bh(&session->lock);
+
+	if (session->tt->suspend_conn_recv)
+		session->tt->suspend_conn_recv(conn);
+
+	mutex_lock(&conn->xmitmutex);
+	/*
+	 * for connection level recovery we should not calculate
+	 * header digest. conn->hdr_size used for optimization
+	 * in hdr_extract() and will be re-negotiated at
+	 * set_param() time.
+	 */
+	if (flag == STOP_CONN_RECOVER) {
+		conn->hdrdgst_en = 0;
+		conn->datadgst_en = 0;
+		if (session->state == ISCSI_STATE_IN_RECOVERY &&
+		    old_stop_stage != STOP_CONN_RECOVER) {
+			debug_scsi("blocking session\n");
+			iscsi_block_session(session_to_cls(session));
+		}
+	}
+
+	session->tt->terminate_conn(conn);
+	/*
+	 * flush queues.
+	 */
+	spin_lock_bh(&session->lock);
+	fail_all_commands(conn);
+	flush_control_queues(session, conn);
+	spin_unlock_bh(&session->lock);
+
+	mutex_unlock(&conn->xmitmutex);
+}
+
+void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
+{
+	struct iscsi_conn *conn = cls_conn->dd_data;
+	struct iscsi_session *session = conn->session;
+
+	switch (flag) {
+	case STOP_CONN_RECOVER:
+	case STOP_CONN_TERM:
+		iscsi_start_session_recovery(session, conn, flag);
+		break;
+	default:
+		printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag);
+	}
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_stop);
+
+int iscsi_conn_bind(struct iscsi_cls_session *cls_session,
+		    struct iscsi_cls_conn *cls_conn, int is_leading)
+{
+	struct iscsi_session *session = class_to_transport_session(cls_session);
+	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
+
+	/* lookup for existing connection */
+	spin_lock_bh(&session->lock);
+	list_for_each_entry(tmp, &session->connections, item) {
+		if (tmp == conn) {
+			if (conn->c_stage != ISCSI_CONN_STOPPED ||
+			    conn->stop_stage == STOP_CONN_TERM) {
+				printk(KERN_ERR "iscsi: can't bind "
+				       "non-stopped connection (%d:%d)\n",
+				       conn->c_stage, conn->stop_stage);
+				spin_unlock_bh(&session->lock);
+				return -EIO;
+			}
+			break;
+		}
+	}
+	if (tmp != conn) {
+		/* bind new iSCSI connection to session */
+		conn->session = session;
+		list_add(&conn->item, &session->connections);
+	}
+	spin_unlock_bh(&session->lock);
+
+	if (is_leading)
+		session->leadconn = conn;
+
+	/*
+	 * Unblock xmitworker(), Login Phase will pass through.
+	 */
+	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx);
+	clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_bind);
+
+MODULE_AUTHOR("Mike Christie");
+MODULE_DESCRIPTION("iSCSI library functions");
+MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index e31fadd6..118206d 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -43,9 +43,6 @@
 
 /* #define DEBUG_MAC_ESP */
 
-#define mac_turnon_irq(x)	mac_enable_irq(x)
-#define mac_turnoff_irq(x)	mac_disable_irq(x)
-
 extern void esp_handle(struct NCR_ESP *esp);
 extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
 
@@ -639,13 +636,13 @@
 
 static void dma_ints_off(struct NCR_ESP * esp)
 {
-	mac_turnoff_irq(esp->irq);
+	disable_irq(esp->irq);
 }
 
 
 static void dma_ints_on(struct NCR_ESP * esp)
 {
-	mac_turnon_irq(esp->irq);
+	enable_irq(esp->irq);
 }
 
 /*
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 777f9bc..a942a21 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -65,9 +65,6 @@
 #define RESET_BOOT
 #define DRIVER_SETUP
 
-#define	ENABLE_IRQ()	mac_enable_irq( IRQ_MAC_SCSI ); 
-#define	DISABLE_IRQ()	mac_disable_irq( IRQ_MAC_SCSI );
-
 extern void via_scsi_clear(void);
 
 #ifdef RESET_BOOT
@@ -351,7 +348,7 @@
 	printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
 
 	/* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
-	mac_disable_irq(IRQ_MAC_SCSI);
+	disable_irq(IRQ_MAC_SCSI);
 
 	/* get in phase */
 	NCR5380_write( TARGET_COMMAND_REG,
@@ -369,7 +366,7 @@
 		barrier();
 
 	/* switch on SCSI IRQ again */
-	mac_enable_irq(IRQ_MAC_SCSI);
+	enable_irq(IRQ_MAC_SCSI);
 
 	printk(KERN_INFO " done\n" );
 }
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index de35ffe..5d2cefb 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -524,7 +524,7 @@
 	 * filter the internal and ioctl commands
 	 */
 	if((cmd->cmnd[0] == MEGA_INTERNAL_CMD)) {
-		return cmd->buffer;
+		return cmd->request_buffer;
 	}
 
 
@@ -1828,7 +1828,7 @@
 
 	scb->dma_type = MEGA_SGLIST;
 
-	if( sgcnt > adapter->sglen ) BUG();
+	BUG_ON(sgcnt > adapter->sglen);
 
 	*len = 0;
 
@@ -4492,7 +4492,7 @@
 	scmd->device = sdev;
 
 	scmd->device->host = adapter->host;
-	scmd->buffer = (void *)scb;
+	scmd->request_buffer = (void *)scb;
 	scmd->cmnd[0] = MEGA_INTERNAL_CMD;
 
 	scb->state |= SCB_ACTIVE;
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index bec1424..b7caf60 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -714,7 +714,7 @@
  * . Allocate memory required for all the commands
  * . Use internal library of FW routines, build up complete soft state
  */
-static int __init
+static int __devinit
 megaraid_init_mbox(adapter_t *adapter)
 {
 	struct pci_dev		*pdev;
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index 3972946..0c9516f 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -741,7 +741,6 @@
 megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
 {
 	u32 frame_count;
-	unsigned long flags;
 	struct megasas_cmd *cmd;
 	struct megasas_instance *instance;
 
@@ -776,9 +775,7 @@
 	/*
 	 * Issue the command to the FW
 	 */
-	spin_lock_irqsave(&instance->instance_lock, flags);
-	instance->fw_outstanding++;
-	spin_unlock_irqrestore(&instance->instance_lock, flags);
+	atomic_inc(&instance->fw_outstanding);
 
 	instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
 
@@ -826,19 +823,20 @@
 
 	for (i = 0; i < wait_time; i++) {
 
-		if (!instance->fw_outstanding)
+		int outstanding = atomic_read(&instance->fw_outstanding);
+
+		if (!outstanding)
 			break;
 
 		if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
 			printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
-			       "commands to complete\n", i,
-			       instance->fw_outstanding);
+			       "commands to complete\n",i,outstanding);
 		}
 
 		msleep(1000);
 	}
 
-	if (instance->fw_outstanding) {
+	if (atomic_read(&instance->fw_outstanding)) {
 		instance->hw_crit_error = 1;
 		return FAILED;
 	}
@@ -1050,7 +1048,6 @@
 {
 	int exception = 0;
 	struct megasas_header *hdr = &cmd->frame->hdr;
-	unsigned long flags;
 
 	if (cmd->scmd) {
 		cmd->scmd->SCp.ptr = (char *)0;
@@ -1082,9 +1079,7 @@
 
 		if (exception) {
 
-			spin_lock_irqsave(&instance->instance_lock, flags);
-			instance->fw_outstanding--;
-			spin_unlock_irqrestore(&instance->instance_lock, flags);
+			atomic_dec(&instance->fw_outstanding);
 
 			megasas_unmap_sgbuf(instance, cmd);
 			cmd->scmd->scsi_done(cmd->scmd);
@@ -1132,9 +1127,7 @@
 			break;
 		}
 
-		spin_lock_irqsave(&instance->instance_lock, flags);
-		instance->fw_outstanding--;
-		spin_unlock_irqrestore(&instance->instance_lock, flags);
+		atomic_dec(&instance->fw_outstanding);
 
 		megasas_unmap_sgbuf(instance, cmd);
 		cmd->scmd->scsi_done(cmd->scmd);
@@ -2171,11 +2164,12 @@
 	 */
 	INIT_LIST_HEAD(&instance->cmd_pool);
 
+	atomic_set(&instance->fw_outstanding,0);
+
 	init_waitqueue_head(&instance->int_cmd_wait_q);
 	init_waitqueue_head(&instance->abort_cmd_wait_q);
 
 	spin_lock_init(&instance->cmd_pool_lock);
-	spin_lock_init(&instance->instance_lock);
 
 	sema_init(&instance->aen_mutex, 1);
 	sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 89639f0..927d6ff 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1077,9 +1077,8 @@
 	struct pci_dev *pdev;
 	u32 unique_id;
 
-	u32 fw_outstanding;
+	atomic_t fw_outstanding;
 	u32 hw_crit_error;
-	spinlock_t instance_lock;
 
 	struct megasas_instance_template *instancet;
 };
diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c
index 22f9131..b28712d 100644
--- a/drivers/scsi/ncr53c8xx.c
+++ b/drivers/scsi/ncr53c8xx.c
@@ -529,7 +529,7 @@
 {
 	switch(cmd->__data_mapped) {
 	case 2:
-		dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
+		dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
 				cmd->sc_data_direction);
 		break;
 	case 1:
@@ -564,7 +564,7 @@
 	if (cmd->use_sg == 0)
 		return 0;
 
-	use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
+	use_sg = dma_map_sg(dev, cmd->request_buffer, cmd->use_sg,
 			cmd->sc_data_direction);
 	cmd->__data_mapped = 2;
 	cmd->__data_mapping = use_sg;
@@ -5118,8 +5118,7 @@
 		cp->host_status &= ~HS_SKIPMASK;
 		cp->start.schedule.l_paddr = 
 			cpu_to_scr(NCB_SCRIPT_PHYS (np, select));
-		list_del(&cp->link_ccbq);
-		list_add_tail(&cp->link_ccbq, &lp->skip_ccbq);
+		list_move_tail(&cp->link_ccbq, &lp->skip_ccbq);
 		if (cp->queued) {
 			--lp->queuedccbs;
 		}
@@ -7697,7 +7696,7 @@
 	if (!use_sg)
 		segment = ncr_scatter_no_sglist(np, cp, cmd);
 	else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
-		struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+		struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer;
 		struct scr_tblmove *data;
 
 		if (use_sg > MAX_SCATTER) {
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index 30ee0ef..5c55e15 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -1636,7 +1636,7 @@
 
 	if (SCpnt->use_sg) {
 		pci_unmap_sg(data->Pci,
-			     (struct scatterlist *)SCpnt->buffer,
+			     (struct scatterlist *)SCpnt->request_buffer,
 			     SCpnt->use_sg, SCpnt->sc_data_direction);
 	} else {
 		pci_unmap_single(data->Pci,
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index e3bd4bc..4a2fed3 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -4724,7 +4724,7 @@
 
 
 /* Flush the tape buffer before close */
-static int os_scsi_tape_flush(struct file * filp)
+static int os_scsi_tape_flush(struct file * filp, fl_owner_t id)
 {
 	int		      result = 0, result2;
 	struct osst_tape    * STp    = filp->private_data;
@@ -5492,7 +5492,7 @@
   char *stp;
 
   stp = get_options(str, ARRAY_SIZE(ints), ints);
-	
+
   if (ints[0] > 0) {
 	for (i = 0; i < ints[0] && i < ARRAY_SIZE(parms); i++)
 		  *parms[i].val = ints[i + 1];
@@ -5507,7 +5507,7 @@
 				break;
 			}
 		}
-		if (i >= sizeof(parms) / sizeof(struct osst_dev_parm))
+		if (i >= ARRAY_SIZE(parms))
 			printk(KERN_INFO "osst :I: Illegal parameter in '%s'\n",
 			       stp);
 		stp = strchr(stp, ',');
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index f09e94a..1bf96ed 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -156,7 +156,7 @@
 static struct override {
     unsigned short io_port;
     int  irq;
-} overrides 
+} overrides
 #ifdef PAS16_OVERRIDE
     [] __initdata = PAS16_OVERRIDE;
 #else
@@ -164,19 +164,19 @@
 	{0,IRQ_AUTO}};
 #endif
 
-#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
+#define NO_OVERRIDES ARRAY_SIZE(overrides)
 
 static struct base {
     unsigned short io_port;
     int noauto;
-} bases[] __initdata = 
+} bases[] __initdata =
 	{ {PAS16_DEFAULT_BASE_1, 0},
 	  {PAS16_DEFAULT_BASE_2, 0},
 	  {PAS16_DEFAULT_BASE_3, 0},
 	  {PAS16_DEFAULT_BASE_4, 0}
 	};
 
-#define NO_BASES (sizeof (bases) / sizeof (struct base))
+#define NO_BASES ARRAY_SIZE(bases)
 
 static const unsigned short  pas16_offset[ 8 ] =
     {
diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c
index 5cda16c..7ebe8e0 100644
--- a/drivers/scsi/pdc_adma.c
+++ b/drivers/scsi/pdc_adma.c
@@ -46,7 +46,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pdc_adma"
-#define DRV_VERSION	"0.03"
+#define DRV_VERSION	"0.04"
 
 /* macro to calculate base address for ATA regs */
 #define ADMA_ATA_REGS(base,port_no)	((base) + ((port_no) * 0x40))
@@ -152,6 +152,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ADMA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -167,6 +168,7 @@
 	.qc_prep		= adma_qc_prep,
 	.qc_issue		= adma_qc_issue,
 	.eng_timeout		= adma_eng_timeout,
+	.data_xfer		= ata_mmio_data_xfer,
 	.irq_handler		= adma_intr,
 	.irq_clear		= adma_irq_clear,
 	.port_start		= adma_port_start,
@@ -455,13 +457,13 @@
 			continue;
 		handled = 1;
 		adma_enter_reg_mode(ap);
-		if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
+		if (ap->flags & ATA_FLAG_DISABLED)
 			continue;
 		pp = ap->private_data;
 		if (!pp || pp->state != adma_state_pkt)
 			continue;
 		qc = ata_qc_from_tag(ap, ap->active_tag);
-		if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+		if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
 			if ((status & (aPERR | aPSD | aUIRQ)))
 				qc->err_mask |= AC_ERR_OTHER;
 			else if (pp->pkt[0] != cDONE)
@@ -480,13 +482,13 @@
 	for (port_no = 0; port_no < host_set->n_ports; ++port_no) {
 		struct ata_port *ap;
 		ap = host_set->ports[port_no];
-		if (ap && (!(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)))) {
+		if (ap && (!(ap->flags & ATA_FLAG_DISABLED))) {
 			struct ata_queued_cmd *qc;
 			struct adma_port_priv *pp = ap->private_data;
 			if (!pp || pp->state != adma_state_mmio)
 				continue;
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
 
 				/* check main status, clearing INTRQ */
 				u8 status = ata_check_status(ap);
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 46624ab..83a6717 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -27,6 +27,9 @@
 
 #include <linux/module.h>
 
+#define RQ_SCSI_BUSY		0xffff
+#define RQ_SCSI_DONE		0xfffe
+
 /* #define PLUTO_DEBUG */
 
 #define pluto_printk printk ("PLUTO %s: ", fc->name); printk
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 108910f..d58ac5a 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -6,8 +6,6 @@
  * (c) 1995,1996 Grant R. Guenther, grant@torque.net,
  * under the terms of the GNU General Public License.
  * 
- * Current Maintainer: David Campbell (Perth, Western Australia, GMT+0800)
- *                     campbell@torque.net
  */
 
 #include <linux/config.h>
diff --git a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h
index f6e1a15..7511df3 100644
--- a/drivers/scsi/ppa.h
+++ b/drivers/scsi/ppa.h
@@ -2,7 +2,7 @@
  * the Iomega ZIP drive
  * 
  * (c) 1996     Grant R. Guenther  grant@torque.net
- *              David Campbell     campbell@torque.net
+ *              David Campbell
  *
  *      All comments to David.
  */
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 5a48e55..680f606 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -397,30 +397,6 @@
 #include "ql1280_fw.h"
 #include "ql1040_fw.h"
 
-
-/*
- * Missing PCI ID's
- */
-#ifndef PCI_DEVICE_ID_QLOGIC_ISP1080
-#define PCI_DEVICE_ID_QLOGIC_ISP1080	0x1080
-#endif
-#ifndef PCI_DEVICE_ID_QLOGIC_ISP1240
-#define PCI_DEVICE_ID_QLOGIC_ISP1240	0x1240
-#endif
-#ifndef PCI_DEVICE_ID_QLOGIC_ISP1280
-#define PCI_DEVICE_ID_QLOGIC_ISP1280	0x1280
-#endif
-#ifndef PCI_DEVICE_ID_QLOGIC_ISP10160
-#define PCI_DEVICE_ID_QLOGIC_ISP10160	0x1016
-#endif
-#ifndef PCI_DEVICE_ID_QLOGIC_ISP12160
-#define PCI_DEVICE_ID_QLOGIC_ISP12160	0x1216
-#endif
-
-#ifndef PCI_VENDOR_ID_AMI
-#define PCI_VENDOR_ID_AMI               0x101e
-#endif
-
 #ifndef BITS_PER_LONG
 #error "BITS_PER_LONG not defined!"
 #endif
@@ -4239,15 +4215,12 @@
 {
 	char *sep;
 	long ret = -1;
-	int i, len;
-
-	len = sizeof(setup_token)/sizeof(struct setup_tokens);
+	int i;
 
 	sep = strchr(str, ':');
 
 	if (sep) {
-		for (i = 0; i < len; i++){
-
+		for (i = 0; i < ARRAY_SIZE(setup_token); i++) {
 			if (!strncmp(setup_token[i].token, str, (sep - str))) {
 				ret =  setup_token[i].val;
 				break;
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index ff40906..8c865b9 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -24,48 +24,3 @@
 	Firmware images can be retrieved from:
 
 		ftp://ftp.qlogic.com/outgoing/linux/firmware/
-
-	NOTE: The original method of building firmware-loader
-	modules has been deprecated as the firmware-images will
-	be removed from the kernel sources.
-
-config SCSI_QLA2XXX_EMBEDDED_FIRMWARE
-	bool "  Use firmware-loader modules (DEPRECATED)"
-	depends on SCSI_QLA_FC
-	help
-	  This option offers you the deprecated firmware-loader
-	  modules that have been obsoleted by the usage of the
-	  Firmware Loader interface in the qla2xxx driver.
-
-config SCSI_QLA21XX
-	tristate "  Build QLogic ISP2100 firmware-module"
-	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
-	---help---
-	This driver supports the QLogic 21xx (ISP2100) host adapter family.
-
-config SCSI_QLA22XX
-	tristate "  Build QLogic ISP2200 firmware-module"
-	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
-	---help---
-	This driver supports the QLogic 22xx (ISP2200) host adapter family.
-
-config SCSI_QLA2300
-	tristate "  Build QLogic ISP2300/ISP6312 firmware-module"
-	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
-	---help---
-	This driver supports the QLogic 2300 (ISP2300, ISP2312 and
-	ISP6312) host adapter family.
-
-config SCSI_QLA2322
-	tristate "  Build QLogic ISP2322/ISP6322 firmware-module"
-	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
-	---help---
-	This driver supports the QLogic 2322 (ISP2322 and ISP6322) host
-	adapter family.
-
-config SCSI_QLA24XX
-	tristate "  Build QLogic ISP24xx firmware-module"
-	depends on SCSI_QLA_FC && SCSI_QLA2XXX_EMBEDDED_FIRMWARE
-	---help---
-	This driver supports the QLogic 24xx (ISP2422 and ISP2432) host
-	adapter family.
diff --git a/drivers/scsi/qla2xxx/Makefile b/drivers/scsi/qla2xxx/Makefile
index c8f670e..411663a 100644
--- a/drivers/scsi/qla2xxx/Makefile
+++ b/drivers/scsi/qla2xxx/Makefile
@@ -1,18 +1,4 @@
-EXTRA_CFLAGS += -DUNIQUE_FW_NAME
-
 qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \
-		qla_dbg.o qla_sup.o qla_rscn.o qla_attr.o
+		qla_dbg.o qla_sup.o qla_attr.o
 
 obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx.o
-
-qla2100-y := ql2100.o ql2100_fw.o
-qla2200-y := ql2200.o ql2200_fw.o
-qla2300-y := ql2300.o ql2300_fw.o
-qla2322-y := ql2322.o ql2322_fw.o
-qla2400-y := ql2400.o ql2400_fw.o
-
-obj-$(CONFIG_SCSI_QLA21XX) += qla2xxx.o qla2100.o
-obj-$(CONFIG_SCSI_QLA22XX) += qla2xxx.o qla2200.o
-obj-$(CONFIG_SCSI_QLA2300) += qla2xxx.o qla2300.o
-obj-$(CONFIG_SCSI_QLA2322) += qla2xxx.o qla2322.o
-obj-$(CONFIG_SCSI_QLA24XX) += qla2xxx.o qla2400.o
diff --git a/drivers/scsi/qla2xxx/ql2100.c b/drivers/scsi/qla2xxx/ql2100.c
deleted file mode 100644
index f5db223..0000000
--- a/drivers/scsi/qla2xxx/ql2100.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (C)  2003 Christoph Hellwig.
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "qla_def.h"
-
-static char qla_driver_name[] = "qla2100";
-
-extern unsigned char  fw2100tp_version[];
-extern unsigned char  fw2100tp_version_str[];
-extern unsigned short fw2100tp_addr01;
-extern unsigned short fw2100tp_code01[];
-extern unsigned short fw2100tp_length01;
-
-static struct qla_fw_info qla_fw_tbl[] = {
-	{
-		.addressing	= FW_INFO_ADDR_NORMAL,
-		.fwcode		= &fw2100tp_code01[0],
-		.fwlen		= &fw2100tp_length01,
-		.fwstart	= &fw2100tp_addr01,
-	},
-
-	{ FW_INFO_ADDR_NOMORE, },
-};
-
-static struct qla_board_info qla_board_tbl = {
-	.drv_name	= qla_driver_name,
-
-	.isp_name	= "ISP2100",
-	.fw_info	= qla_fw_tbl,
-};
-
-static struct pci_device_id qla2100_pci_tbl[] = {
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2100,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl,
-	},
-
-	{0, 0},
-};
-MODULE_DEVICE_TABLE(pci, qla2100_pci_tbl);
-
-static int __devinit
-qla2100_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	return qla2x00_probe_one(pdev,
-	    (struct qla_board_info *)id->driver_data);
-}
-
-static void __devexit
-qla2100_remove_one(struct pci_dev *pdev)
-{
-	qla2x00_remove_one(pdev);
-}
-
-static struct pci_driver qla2100_pci_driver = {
-	.name		= "qla2100",
-	.id_table	= qla2100_pci_tbl,
-	.probe		= qla2100_probe_one,
-	.remove		= __devexit_p(qla2100_remove_one),
-};
-
-static int __init
-qla2100_init(void)
-{
-	return pci_module_init(&qla2100_pci_driver);
-}
-
-static void __exit
-qla2100_exit(void)
-{
-	pci_unregister_driver(&qla2100_pci_driver);
-}
-
-module_init(qla2100_init);
-module_exit(qla2100_exit);
-
-MODULE_AUTHOR("QLogic Corporation");
-MODULE_DESCRIPTION("QLogic ISP21xx FC-SCSI Host Bus Adapter driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2100_fw.c b/drivers/scsi/qla2xxx/ql2100_fw.c
deleted file mode 100644
index 5600616..0000000
--- a/drivers/scsi/qla2xxx/ql2100_fw.c
+++ /dev/null
@@ -1,4848 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-
-/*
- *	Firmware Version 1.19.25 (13:12 Dec 10, 2003)
- */
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2100tp_version = 1*1024+19;
-#else
-unsigned short risc_code_version = 1*1024+19;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned char fw2100tp_version_str[] = {1,19,25};
-#else
-unsigned char firmware_version[] = {1,19,25};
-#endif
-
-#ifdef UNIQUE_FW_NAME
-#define fw2100tp_VERSION_STRING "1.19.25"
-#else
-#define FW_VERSION_STRING "1.19.25"
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2100tp_addr01 = 0x1000 ;
-#else
-unsigned short risc_code_addr01 = 0x1000 ;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2100tp_code01[] = { 
-#else
-unsigned short risc_code01[] = { 
-#endif
-	0x0078, 0x102d, 0x0000, 0x9601, 0x0000, 0x0001, 0x0013, 0x0019,
-	0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030,
-	0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
-	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3231, 0x3030, 0x2046, 0x6972,
-	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
-	0x312e, 0x3139, 0x2020, 0x2020, 0x2400, 0x2091, 0x2000, 0x20c1,
-	0x0021, 0x2039, 0xffff, 0x2019, 0xaaaa, 0x2760, 0x2069, 0x7fff,
-	0x20c1, 0x0020, 0x2c2c, 0x2d34, 0x2762, 0x236a, 0x2c24, 0x2d04,
-	0x266a, 0x2562, 0xa406, 0x00c0, 0x1052, 0x20c1, 0x0021, 0x2c2c,
-	0x2362, 0x2c04, 0x2562, 0xa306, 0x0040, 0x1052, 0x20c1, 0x0020,
-	0x2039, 0x8fff, 0x20a1, 0xae00, 0x2708, 0x810d, 0x810d, 0x810d,
-	0x810d, 0xa18c, 0x000f, 0x2001, 0x000a, 0xa112, 0xa00e, 0x21a8,
-	0x41a4, 0x3400, 0x8211, 0x00c0, 0x105f, 0x2708, 0x3400, 0xa102,
-	0x0040, 0x106f, 0x0048, 0x106f, 0x20a8, 0xa00e, 0x41a4, 0x20a1,
-	0xa601, 0x2009, 0x0000, 0x20a9, 0x07ff, 0x41a4, 0x3400, 0x20c9,
-	0xabff, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x25c7,
-	0x2051, 0xa700, 0x2a70, 0x7762, 0xa786, 0x8fff, 0x0040, 0x1092,
-	0x705f, 0xce00, 0x705b, 0xcdf1, 0x7067, 0x0200, 0x706b, 0x0200,
-	0x0078, 0x109a, 0x705b, 0xbe01, 0x7067, 0x0100, 0x706b, 0x0100,
-	0x705f, 0xbe00, 0x1078, 0x12df, 0x1078, 0x13ca, 0x1078, 0x1577,
-	0x1078, 0x1ce9, 0x1078, 0x42ec, 0x1078, 0x76bf, 0x1078, 0x1355,
-	0x1078, 0x2ac0, 0x1078, 0x4e93, 0x1078, 0x49a3, 0x1078, 0x594a,
-	0x1078, 0x2263, 0x1078, 0x5c43, 0x1078, 0x5485, 0x1078, 0x2162,
-	0x1078, 0x2240, 0x2091, 0x3009, 0x7823, 0x0000, 0x0090, 0x10cf,
-	0x7820, 0xa086, 0x0002, 0x00c0, 0x10cf, 0x7823, 0x4000, 0x0068,
-	0x10c7, 0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70,
-	0x7003, 0x0000, 0x2001, 0x017f, 0x2003, 0x0000, 0x2a70, 0x7000,
-	0xa08e, 0x0003, 0x00c0, 0x10ef, 0x1078, 0x365e, 0x1078, 0x2ae8,
-	0x1078, 0x4ee3, 0x1078, 0x4b66, 0x2009, 0x0100, 0x2104, 0xa082,
-	0x0002, 0x0048, 0x10f3, 0x1078, 0x5966, 0x0078, 0x10d6, 0x1079,
-	0x10f7, 0x0078, 0x10dc, 0x1078, 0x7197, 0x0078, 0x10eb, 0x1101,
-	0x1102, 0x11be, 0x10ff, 0x1246, 0x12dc, 0x12dd, 0x12de, 0x1078,
-	0x1332, 0x007c, 0x127e, 0x0f7e, 0x2091, 0x8000, 0x7000, 0xa086,
-	0x0001, 0x00c0, 0x1198, 0x1078, 0x3aec, 0x2079, 0x0100, 0x7844,
-	0xa005, 0x00c0, 0x1198, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x1078,
-	0x1adf, 0x780f, 0x00ff, 0x7840, 0xa084, 0xfffb, 0x7842, 0x2011,
-	0x8010, 0x73c4, 0x1078, 0x361b, 0x2001, 0xffff, 0x1078, 0x5ae6,
-	0x723c, 0xc284, 0x723e, 0x2001, 0xa70c, 0x2014, 0xc2ac, 0x2202,
-	0x1078, 0x6f9f, 0x2011, 0x0004, 0x1078, 0x8d2b, 0x1078, 0x489e,
-	0x1078, 0x42d4, 0x0040, 0x1144, 0x7087, 0x0001, 0x70bf, 0x0000,
-	0x1078, 0x3c9e, 0x0078, 0x1198, 0x1078, 0x4967, 0x0040, 0x114d,
-	0x7a0c, 0xc2b4, 0x7a0e, 0x0078, 0x1159, 0x1078, 0x90b6, 0x70cc,
-	0xd09c, 0x00c0, 0x1159, 0x7098, 0xa005, 0x0040, 0x1159, 0x1078,
-	0x42b8, 0x70d7, 0x0000, 0x70d3, 0x0000, 0x72cc, 0x2079, 0xa752,
-	0x7804, 0xd0ac, 0x0040, 0x1165, 0xc295, 0x72ce, 0xa296, 0x0004,
-	0x0040, 0x1186, 0x2011, 0x0001, 0x1078, 0x8d2b, 0x7093, 0x0000,
-	0x7097, 0xffff, 0x7003, 0x0002, 0x0f7f, 0x1078, 0x2677, 0x2011,
-	0x0005, 0x1078, 0x70e0, 0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100,
-	0x60e3, 0x0008, 0x0c7f, 0x127f, 0x0078, 0x119a, 0x7093, 0x0000,
-	0x7097, 0xffff, 0x7003, 0x0002, 0x2011, 0x0005, 0x1078, 0x70e0,
-	0x1078, 0x62d1, 0x0c7e, 0x2061, 0x0100, 0x60e3, 0x0008, 0x0c7f,
-	0x0f7f, 0x127f, 0x007c, 0x0c7e, 0x20a9, 0x0082, 0x2009, 0x007e,
-	0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019, 0x0029, 0x1078,
-	0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, 0x027f, 0x017f, 0x1078,
-	0x298e, 0x8108, 0x00f0, 0x11a0, 0x0c7f, 0x706f, 0x0000, 0x7070,
-	0xa084, 0x00ff, 0x7072, 0x709b, 0x0000, 0x007c, 0x127e, 0x2091,
-	0x8000, 0x7000, 0xa086, 0x0002, 0x00c0, 0x1244, 0x7094, 0xa086,
-	0xffff, 0x0040, 0x11d1, 0x1078, 0x2677, 0x1078, 0x62d1, 0x0078,
-	0x1244, 0x70cc, 0xd09c, 0x0040, 0x11fd, 0xd084, 0x0040, 0x11fd,
-	0x0f7e, 0x2079, 0x0100, 0x790c, 0xc1b5, 0x790e, 0x0f7f, 0xd08c,
-	0x0040, 0x11fd, 0x70d0, 0xa086, 0xffff, 0x0040, 0x11f9, 0x1078,
-	0x27f7, 0x1078, 0x62d1, 0x70cc, 0xd094, 0x00c0, 0x1244, 0x2011,
-	0x0001, 0x2019, 0x0000, 0x1078, 0x282f, 0x1078, 0x62d1, 0x0078,
-	0x1244, 0x70d4, 0xa005, 0x00c0, 0x1244, 0x7090, 0xa005, 0x00c0,
-	0x1244, 0x1078, 0x4967, 0x00c0, 0x1244, 0x2001, 0xa753, 0x2004,
-	0xd0ac, 0x0040, 0x1227, 0x157e, 0x0c7e, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0, 0x121a, 0x6000, 0xd0ec,
-	0x00c0, 0x1222, 0x017f, 0x8108, 0x00f0, 0x1211, 0x0c7f, 0x157f,
-	0x0078, 0x1227, 0x017f, 0x0c7f, 0x157f, 0x0078, 0x1244, 0x7003,
-	0x0003, 0x7097, 0xffff, 0x2001, 0x0000, 0x1078, 0x24e8, 0x1078,
-	0x3699, 0x2001, 0xa9b2, 0x2004, 0xa086, 0x0005, 0x00c0, 0x123c,
-	0x2011, 0x0000, 0x1078, 0x70e0, 0x2011, 0x0000, 0x1078, 0x70ea,
-	0x1078, 0x62d1, 0x1078, 0x639b, 0x127f, 0x007c, 0x017e, 0x0f7e,
-	0x127e, 0x2091, 0x8000, 0x2079, 0x0100, 0x2009, 0x00f7, 0x1078,
-	0x42a1, 0x7940, 0xa18c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0040,
-	0x125b, 0x7827, 0x0040, 0xd19c, 0x0040, 0x1260, 0x7827, 0x0008,
-	0x007e, 0x037e, 0x157e, 0xa006, 0x1078, 0x5ae6, 0x7900, 0xa18a,
-	0x0003, 0x0050, 0x1289, 0x7954, 0xd1ac, 0x00c0, 0x1289, 0x2009,
-	0x00f8, 0x1078, 0x42a1, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9,
-	0x09c4, 0x7820, 0xd09c, 0x00c0, 0x1281, 0x7824, 0xd0ac, 0x00c0,
-	0x12ca, 0x00f0, 0x1279, 0x2001, 0x0001, 0x1078, 0x24e8, 0x0078,
-	0x12d5, 0x7853, 0x0000, 0x782f, 0x0020, 0x20a9, 0x0050, 0x00e0,
-	0x128f, 0x2091, 0x6000, 0x00f0, 0x128f, 0x7853, 0x0400, 0x782f,
-	0x0000, 0x2009, 0x00f8, 0x1078, 0x42a1, 0x20a9, 0x000e, 0x0005,
-	0x00f0, 0x129f, 0x7853, 0x1400, 0x7843, 0x0090, 0x7843, 0x0010,
-	0x2019, 0x61a8, 0x7854, 0x0005, 0x0005, 0xd08c, 0x0040, 0x12b4,
-	0x7824, 0xd0ac, 0x00c0, 0x12ca, 0x8319, 0x00c0, 0x12aa, 0x2009,
-	0xa732, 0x2104, 0x8000, 0x200a, 0xa084, 0xfff0, 0x0040, 0x12c4,
-	0x200b, 0x0000, 0x1078, 0x2588, 0x2001, 0x0001, 0x1078, 0x24e8,
-	0x0078, 0x12d3, 0x2001, 0xa732, 0x2003, 0x0000, 0x7828, 0xc09d,
-	0x782a, 0x7827, 0x0048, 0x7853, 0x0400, 0x157f, 0x037f, 0x007f,
-	0x127f, 0x0f7f, 0x017f, 0x007c, 0x007c, 0x007c, 0x007c, 0x2a70,
-	0x2061, 0xa9ad, 0x2063, 0x0001, 0x6007, 0x0013, 0x600b, 0x0019,
-	0x600f, 0x0017, 0x2009, 0x0100, 0x2104, 0xa082, 0x0002, 0x0048,
-	0x12f5, 0x7053, 0xffff, 0x0078, 0x12f7, 0x7053, 0x0000, 0x7057,
-	0xffff, 0x706f, 0x0000, 0x7073, 0x0000, 0x1078, 0x90b6, 0x2061,
-	0xa98d, 0x6003, 0x0909, 0x6007, 0x0000, 0x600b, 0x8800, 0x600f,
-	0x0200, 0x6013, 0x00ff, 0x6017, 0x0003, 0x601b, 0x0000, 0x601f,
-	0x07d0, 0x2061, 0xa995, 0x6003, 0x8000, 0x6007, 0x0000, 0x600b,
-	0x0000, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x0000, 0x601b,
-	0x0001, 0x601f, 0x0000, 0x2061, 0xa9a5, 0x6003, 0x514c, 0x6007,
-	0x4f47, 0x600b, 0x4943, 0x600f, 0x2020, 0x2001, 0xa726, 0x2003,
-	0x0000, 0x007c, 0x2091, 0x8000, 0x0068, 0x1334, 0x007e, 0x017e,
-	0x2079, 0x0000, 0x7818, 0xd084, 0x00c0, 0x133a, 0x017f, 0x792e,
-	0x007f, 0x782a, 0x007f, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002,
-	0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2079, 0xa700,
-	0x7803, 0x0005, 0x0078, 0x1352, 0x007c, 0x2071, 0xa700, 0x715c,
-	0x712e, 0x2021, 0x0001, 0xa190, 0x002d, 0xa298, 0x002d, 0x0048,
-	0x136b, 0x7060, 0xa302, 0x00c8, 0x136b, 0x220a, 0x2208, 0x2310,
-	0x8420, 0x0078, 0x135d, 0x200b, 0x0000, 0x74aa, 0x74ae, 0x007c,
-	0x0e7e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa700, 0x70ac, 0xa0ea,
-	0x0010, 0x00c8, 0x137e, 0xa06e, 0x0078, 0x1388, 0x8001, 0x70ae,
-	0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000,
-	0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa700, 0x127e, 0x2091,
-	0x8000, 0x70ac, 0x8001, 0x00c8, 0x1398, 0xa06e, 0x0078, 0x13a1,
-	0x70ae, 0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807,
-	0x0000, 0x127f, 0x0e7f, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0xa700, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000,
-	0x70ae, 0x127f, 0x0e7f, 0x007c, 0x8dff, 0x0040, 0x13c0, 0x6804,
-	0x6807, 0x0000, 0x007e, 0x1078, 0x13a4, 0x0d7f, 0x0078, 0x13b4,
-	0x007c, 0x0e7e, 0x2071, 0xa700, 0x70ac, 0xa08a, 0x0010, 0xa00d,
-	0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa9d6, 0x7007, 0x0000, 0x701b,
-	0x0000, 0x701f, 0x0000, 0x2071, 0x0000, 0x7010, 0xa085, 0x8004,
-	0x7012, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x0e7e, 0x2270,
-	0x700b, 0x0000, 0x2071, 0xa9d6, 0x7018, 0xa088, 0xa9df, 0x220a,
-	0x8000, 0xa084, 0x0007, 0x701a, 0x7004, 0xa005, 0x00c0, 0x13f6,
-	0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x127f,
-	0x007c, 0x0e7e, 0x2071, 0xa9d6, 0x7004, 0xa005, 0x00c0, 0x1406,
-	0x0f7e, 0x2079, 0x0010, 0x1078, 0x1408, 0x0f7f, 0x0e7f, 0x007c,
-	0x7000, 0x0079, 0x140b, 0x140f, 0x1479, 0x1496, 0x1496, 0x7018,
-	0x711c, 0xa106, 0x00c0, 0x1417, 0x7007, 0x0000, 0x007c, 0x0d7e,
-	0xa180, 0xa9df, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007,
-	0x711e, 0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c,
-	0x783a, 0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804,
-	0x0d7f, 0xd084, 0x0040, 0x1439, 0x7007, 0x0001, 0x1078, 0x143e,
-	0x007c, 0x7007, 0x0002, 0x1078, 0x1454, 0x007c, 0x017e, 0x027e,
-	0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1449, 0x2110,
-	0xa006, 0x700e, 0x7212, 0x8203, 0x7822, 0x7803, 0x0020, 0x7803,
-	0x0041, 0x027f, 0x017f, 0x007c, 0x017e, 0x027e, 0x137e, 0x147e,
-	0x157e, 0x7014, 0x2098, 0x20a1, 0x0014, 0x7803, 0x0026, 0x710c,
-	0x2011, 0x0040, 0xa182, 0x0040, 0x00c8, 0x1468, 0x2110, 0xa006,
-	0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803, 0x0020, 0x3300,
-	0x7016, 0x7803, 0x0001, 0x157f, 0x147f, 0x137f, 0x027f, 0x017f,
-	0x007c, 0x137e, 0x147e, 0x157e, 0x2099, 0xa7fa, 0x20a1, 0x0018,
-	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
-	0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x700b,
-	0xa7f5, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x137e, 0x147e,
-	0x157e, 0x2001, 0xa829, 0x209c, 0x20a1, 0x0014, 0x7803, 0x0026,
-	0x2001, 0xa82a, 0x20ac, 0x53a6, 0x2099, 0xa82b, 0x20a1, 0x0018,
-	0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x127e, 0x2091, 0x8000,
-	0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c, 0x7002, 0x700b,
-	0xa826, 0x127f, 0x157f, 0x147f, 0x137f, 0x007c, 0x017e, 0x0e7e,
-	0x2071, 0xa9d6, 0x0f7e, 0x2079, 0x0010, 0x7904, 0x7803, 0x0002,
-	0xd1fc, 0x0040, 0x14d0, 0xa18c, 0x0700, 0x7004, 0x1079, 0x14d4,
-	0x0f7f, 0x0e7f, 0x017f, 0x007c, 0x1408, 0x14dc, 0x1509, 0x1531,
-	0x1564, 0x14da, 0x0078, 0x14da, 0xa18c, 0x0700, 0x00c0, 0x1502,
-	0x137e, 0x147e, 0x157e, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803,
-	0x0040, 0x7010, 0x20a8, 0x53a5, 0x3400, 0x7016, 0x157f, 0x147f,
-	0x137f, 0x700c, 0xa005, 0x0040, 0x151e, 0x1078, 0x143e, 0x007c,
-	0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078,
-	0x1408, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200, 0x0078,
-	0x14fd, 0xa18c, 0x0700, 0x00c0, 0x1514, 0x700c, 0xa005, 0x0040,
-	0x151e, 0x1078, 0x1454, 0x007c, 0x7008, 0xa080, 0x0002, 0x2003,
-	0x0200, 0x7007, 0x0000, 0x1078, 0x1408, 0x007c, 0x0d7e, 0x7008,
-	0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838, 0x682e, 0x783c,
-	0x6832, 0x680b, 0x0100, 0x0d7f, 0x7007, 0x0000, 0x1078, 0x1408,
-	0x007c, 0xa18c, 0x0700, 0x00c0, 0x155e, 0x137e, 0x147e, 0x157e,
-	0x2001, 0xa7f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099, 0x0014,
-	0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xa7fa, 0x2004,
-	0xd0bc, 0x0040, 0x1554, 0x2001, 0xa803, 0x2004, 0xa080, 0x000d,
-	0x20a0, 0x20a9, 0x0020, 0x53a5, 0x157f, 0x147f, 0x137f, 0x7007,
-	0x0000, 0x1078, 0x4f8c, 0x1078, 0x1408, 0x007c, 0x2011, 0x8003,
-	0x1078, 0x361b, 0x0078, 0x1562, 0xa18c, 0x0700, 0x00c0, 0x1571,
-	0x2001, 0xa828, 0x2003, 0x0100, 0x7007, 0x0000, 0x1078, 0x1408,
-	0x007c, 0x2011, 0x8004, 0x1078, 0x361b, 0x0078, 0x1575, 0x127e,
-	0x2091, 0x2100, 0x2079, 0x0030, 0x2071, 0xa9e7, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x700f, 0xa9ed, 0x7013, 0xa9ed, 0x780f, 0x0076,
-	0x7803, 0x0004, 0x127f, 0x007c, 0x6934, 0xa184, 0x0007, 0x0079,
-	0x1591, 0x1599, 0x15df, 0x1599, 0x1599, 0x1599, 0x15c4, 0x15a8,
-	0x159d, 0xa085, 0x0001, 0x0078, 0x15f9, 0x684c, 0xd0bc, 0x0040,
-	0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x0078, 0x15e7,
-	0xa18c, 0x00ff, 0xa186, 0x001e, 0x00c0, 0x1599, 0x684c, 0xd0bc,
-	0x0040, 0x1599, 0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004,
-	0x6832, 0x6858, 0x0078, 0x15ef, 0xa18c, 0x00ff, 0xa186, 0x0015,
-	0x00c0, 0x1599, 0x684c, 0xd0ac, 0x0040, 0x1599, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004,
-	0x6832, 0xa006, 0x682e, 0x682a, 0x6858, 0x0078, 0x15ef, 0x684c,
-	0xd0ac, 0x0040, 0x1599, 0xa006, 0x682e, 0x682a, 0x6858, 0xa18c,
-	0x000f, 0xa188, 0x206a, 0x210c, 0x6932, 0x2d08, 0x691a, 0x6826,
-	0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c, 0x6912, 0x6980,
-	0x6916, 0x007c, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a,
-	0x2004, 0x82ff, 0x0040, 0x161c, 0xa280, 0x0004, 0x0d7e, 0x206c,
-	0x684c, 0xd0dc, 0x00c0, 0x1618, 0x1078, 0x158c, 0x0040, 0x1618,
-	0x0d7f, 0xa280, 0x0000, 0x2003, 0x0002, 0xa016, 0x0078, 0x161c,
-	0x6808, 0x8000, 0x680a, 0x0d7f, 0x127e, 0x047e, 0x037e, 0x027e,
-	0x2091, 0x2100, 0x027f, 0x037f, 0x047f, 0x7000, 0xa005, 0x00c0,
-	0x1630, 0x7206, 0x2001, 0x1651, 0x007e, 0x2260, 0x0078, 0x17e0,
-	0x710c, 0x220a, 0x8108, 0x230a, 0x8108, 0x240a, 0x8108, 0xa182,
-	0xaa08, 0x0048, 0x163d, 0x2009, 0xa9ed, 0x710e, 0x7010, 0xa102,
-	0xa082, 0x0009, 0x0040, 0x1648, 0xa080, 0x001b, 0x00c0, 0x164b,
-	0x2009, 0x0138, 0x200a, 0x7000, 0xa005, 0x00c0, 0x1651, 0x1078,
-	0x17c1, 0x127f, 0x007c, 0x127e, 0x027e, 0x037e, 0x0c7e, 0x007e,
-	0x2091, 0x2100, 0x007f, 0x047f, 0x037f, 0x027f, 0x0d7e, 0x0c7e,
-	0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e, 0xa005, 0x0040, 0x16dd,
-	0x6808, 0xa005, 0x0040, 0x174a, 0x7000, 0xa005, 0x00c0, 0x1672,
-	0x0078, 0x16d2, 0x700c, 0x7110, 0xa106, 0x00c0, 0x1753, 0x7004,
-	0xa406, 0x00c0, 0x16d2, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0040,
-	0x168f, 0x047e, 0x1078, 0x1913, 0x047f, 0x2460, 0x6010, 0xa080,
-	0x0002, 0x2004, 0xa005, 0x0040, 0x174a, 0x0078, 0x166c, 0x2001,
-	0x0207, 0x2004, 0xd09c, 0x00c0, 0x167b, 0x7804, 0xa084, 0x6000,
-	0x0040, 0x16a0, 0xa086, 0x6000, 0x0040, 0x16a0, 0x0078, 0x167b,
-	0x7100, 0xa186, 0x0002, 0x00c0, 0x16c0, 0x0e7e, 0x2b68, 0x6818,
-	0x2060, 0x1078, 0x203f, 0x2804, 0xac70, 0x6034, 0xd09c, 0x00c0,
-	0x16b5, 0x7108, 0x720c, 0x0078, 0x16b7, 0x7110, 0x7214, 0x6810,
-	0xa100, 0x6812, 0x6814, 0xa201, 0x6816, 0x0e7f, 0x0078, 0x16c4,
-	0xa186, 0x0001, 0x00c0, 0x16cc, 0x7820, 0x6910, 0xa100, 0x6812,
-	0x7824, 0x6914, 0xa101, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000,
-	0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009,
-	0x0048, 0x1078, 0x775c, 0x0078, 0x1753, 0x6808, 0xa005, 0x0040,
-	0x174a, 0x7000, 0xa005, 0x00c0, 0x16e7, 0x0078, 0x174a, 0x700c,
-	0x7110, 0xa106, 0x00c0, 0x16f0, 0x7004, 0xa406, 0x00c0, 0x174a,
-	0x2001, 0x0005, 0x2004, 0xd08c, 0x0040, 0x1704, 0x047e, 0x1078,
-	0x1913, 0x047f, 0x2460, 0x6010, 0xa080, 0x0002, 0x2004, 0xa005,
-	0x0040, 0x174a, 0x0078, 0x16e1, 0x2001, 0x0207, 0x2004, 0xd09c,
-	0x00c0, 0x16f0, 0x2001, 0x0005, 0x2004, 0xd08c, 0x00c0, 0x16f6,
-	0x7804, 0xa084, 0x6000, 0x0040, 0x171b, 0xa086, 0x6000, 0x0040,
-	0x171b, 0x0078, 0x16f0, 0x7007, 0x0000, 0xa016, 0x2218, 0x7000,
-	0xa08e, 0x0001, 0x0040, 0x173c, 0xa08e, 0x0002, 0x00c0, 0x174a,
-	0x0c7e, 0x0e7e, 0x6818, 0x2060, 0x1078, 0x203f, 0x2804, 0xac70,
-	0x6034, 0xd09c, 0x00c0, 0x1738, 0x7308, 0x720c, 0x0078, 0x173a,
-	0x7310, 0x7214, 0x0e7f, 0x0c7f, 0x7820, 0xa318, 0x7824, 0xa211,
-	0x6810, 0xa300, 0x6812, 0x6814, 0xa201, 0x6816, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x6100, 0xa18e, 0x0004, 0x00c0, 0x1753, 0x2009,
-	0x0048, 0x1078, 0x775c, 0x0c7f, 0x0d7f, 0x127f, 0x007c, 0x0f7e,
-	0x0e7e, 0x027e, 0x037e, 0x047e, 0x057e, 0x2071, 0xa9e7, 0x7000,
-	0xa086, 0x0000, 0x0040, 0x17ba, 0x7004, 0xac06, 0x00c0, 0x17ab,
-	0x2079, 0x0030, 0x7000, 0xa086, 0x0003, 0x0040, 0x17ab, 0x7804,
-	0xd0fc, 0x00c0, 0x17a7, 0x20e1, 0x6000, 0x2011, 0x0032, 0x2001,
-	0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106, 0x00c0, 0x176f,
-	0x8211, 0x00c0, 0x1777, 0x7804, 0xd0fc, 0x00c0, 0x17a7, 0x1078,
-	0x1b22, 0x027e, 0x057e, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0,
-	0x178d, 0x7803, 0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007,
-	0x0000, 0x057f, 0x027f, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001,
-	0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0078, 0x17ab, 0x1078,
-	0x1913, 0x0078, 0x175f, 0x157e, 0x20a9, 0x0009, 0x2009, 0xa9ed,
-	0x2104, 0xac06, 0x00c0, 0x17b5, 0x200a, 0xa188, 0x0003, 0x00f0,
-	0x17b0, 0x157f, 0x057f, 0x047f, 0x037f, 0x027f, 0x0e7f, 0x0f7f,
-	0x007c, 0x700c, 0x7110, 0xa106, 0x00c0, 0x17c9, 0x7003, 0x0000,
-	0x007c, 0x2104, 0x7006, 0x2060, 0x8108, 0x211c, 0x8108, 0x2124,
-	0x8108, 0xa182, 0xaa08, 0x0048, 0x17d7, 0x2009, 0xa9ed, 0x7112,
-	0x700c, 0xa106, 0x00c0, 0x17e0, 0x2001, 0x0138, 0x2003, 0x0008,
-	0x8cff, 0x00c0, 0x17e7, 0x1078, 0x1b4d, 0x0078, 0x1854, 0x6010,
-	0x2068, 0x2d58, 0x6828, 0xa406, 0x00c0, 0x17f2, 0x682c, 0xa306,
-	0x0040, 0x182f, 0x601c, 0xa086, 0x0008, 0x0040, 0x182f, 0x6024,
-	0xd0f4, 0x00c0, 0x181c, 0xd0d4, 0x0040, 0x1818, 0x6038, 0xa402,
-	0x6034, 0xa303, 0x0040, 0x1806, 0x00c8, 0x1818, 0x643a, 0x6336,
-	0x6c2a, 0x6b2e, 0x047e, 0x037e, 0x2400, 0x6c7c, 0xa402, 0x6812,
-	0x2300, 0x6b80, 0xa303, 0x6816, 0x037f, 0x047f, 0x0078, 0x181c,
-	0x1078, 0x9063, 0x0040, 0x17e3, 0x2001, 0xa774, 0x2004, 0xd0b4,
-	0x00c0, 0x182b, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x182b, 0x6817,
-	0x7fff, 0x6813, 0xffff, 0x1078, 0x208a, 0x00c0, 0x17e3, 0x0c7e,
-	0x7004, 0x2060, 0x6024, 0xc0d4, 0x6026, 0x0c7f, 0x684c, 0xd0f4,
-	0x0040, 0x1840, 0x6817, 0xffff, 0x6813, 0xffff, 0x0078, 0x17e3,
-	0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc,
-	0x000f, 0x2009, 0x0011, 0x1078, 0x1855, 0x0040, 0x1853, 0x2009,
-	0x0001, 0x1078, 0x1855, 0x2d58, 0x007c, 0x8aff, 0x0040, 0x18ec,
-	0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1877, 0xd0f4, 0x00c0,
-	0x1887, 0x0d7e, 0x2804, 0xac68, 0x2900, 0x0079, 0x1867, 0x18ce,
-	0x188e, 0x188e, 0x18ce, 0x18ce, 0x18c6, 0x18ce, 0x188e, 0x18ce,
-	0x1894, 0x1894, 0x18ce, 0x18ce, 0x18ce, 0x18bd, 0x1894, 0xc0fc,
-	0x6852, 0x6b6c, 0x6a70, 0x6d1c, 0x6c20, 0x0d7e, 0xd99c, 0x0040,
-	0x18d1, 0x2804, 0xac68, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0xc0f4,
-	0x6852, 0x6b6c, 0x6a70, 0x0d7e, 0x0078, 0x18d8, 0x6b08, 0x6a0c,
-	0x6d00, 0x6c04, 0x0078, 0x18d1, 0x7b0c, 0xd3bc, 0x0040, 0x18b5,
-	0x7004, 0x0e7e, 0x2070, 0x701c, 0x0e7f, 0xa086, 0x0008, 0x00c0,
-	0x18b5, 0x7b08, 0xa39c, 0x0fff, 0x2d20, 0x0d7f, 0x0d7e, 0x6a14,
-	0x82ff, 0x00c0, 0x18b0, 0x6810, 0xa302, 0x0048, 0x18b0, 0x6b10,
-	0x2011, 0x0000, 0x2468, 0x0078, 0x18b7, 0x6b10, 0x6a14, 0x6d00,
-	0x6c04, 0x6f08, 0x6e0c, 0x0078, 0x18d1, 0x0d7f, 0x0d7e, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x18ce, 0x0d7f, 0x1078,
-	0x2026, 0x00c0, 0x1855, 0xa00e, 0x0078, 0x18ec, 0x0d7f, 0x1078,
-	0x1332, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902,
-	0x7000, 0x8000, 0x7002, 0x0d7f, 0x6828, 0xa300, 0x682a, 0x682c,
-	0xa201, 0x682e, 0x2300, 0x6b10, 0xa302, 0x6812, 0x2200, 0x6a14,
-	0xa203, 0x6816, 0x1078, 0x2026, 0x007c, 0x1078, 0x1332, 0x1078,
-	0x1c97, 0x7004, 0x2060, 0x0d7e, 0x6010, 0x2068, 0x7003, 0x0000,
-	0x1078, 0x1af4, 0x1078, 0x8d16, 0x0040, 0x190c, 0x6808, 0x8001,
-	0x680a, 0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f,
-	0xffff, 0x6850, 0xc0bd, 0x6852, 0x0d7f, 0x1078, 0x8a11, 0x0078,
-	0x1adb, 0x1078, 0x1332, 0x127e, 0x2091, 0x2100, 0x007e, 0x017e,
-	0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700,
-	0x00c0, 0x18ef, 0xa184, 0x0003, 0xa086, 0x0003, 0x0040, 0x1911,
-	0x7000, 0x0079, 0x192b, 0x1933, 0x1935, 0x1a34, 0x1ab2, 0x1ac9,
-	0x1933, 0x1933, 0x1933, 0x1078, 0x1332, 0x8001, 0x7002, 0xa184,
-	0x0880, 0x00c0, 0x194a, 0x8aff, 0x0040, 0x19d4, 0x2009, 0x0001,
-	0x1078, 0x1855, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078, 0x1855,
-	0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc, 0x00c0,
-	0x19b2, 0x027e, 0x037e, 0x017e, 0x7808, 0xd0ec, 0x00c0, 0x1962,
-	0x7c20, 0x7d24, 0x7e30, 0x7f34, 0x7803, 0x0009, 0x7003, 0x0004,
-	0x0078, 0x1964, 0x1078, 0x1bd7, 0x017f, 0xd194, 0x0040, 0x196b,
-	0x8aff, 0x0040, 0x19a1, 0x6b28, 0x6a2c, 0x2400, 0x686e, 0xa31a,
-	0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x0c7e, 0x7004, 0x2060,
-	0x6024, 0xd0f4, 0x00c0, 0x197e, 0x633a, 0x6236, 0x0c7f, 0x2400,
-	0x6910, 0xa100, 0x6812, 0x2500, 0x6914, 0xa101, 0x6816, 0x037f,
-	0x027f, 0x2600, 0x681e, 0x2700, 0x6822, 0x1078, 0x203f, 0x2a00,
-	0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x6850, 0xc0fd, 0x6852,
-	0x6808, 0x8001, 0x680a, 0x00c0, 0x19a7, 0x684c, 0xd0e4, 0x0040,
-	0x19a7, 0x7004, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x7000,
-	0xa086, 0x0004, 0x0040, 0x1adb, 0x7003, 0x0000, 0x1078, 0x17c1,
-	0x0078, 0x1adb, 0x057e, 0x7d0c, 0xd5bc, 0x00c0, 0x19b9, 0x1078,
-	0xa58e, 0x057f, 0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078,
-	0x4963, 0x0040, 0x19c6, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b,
-	0xffff, 0x682f, 0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912,
-	0x6980, 0x6916, 0x0078, 0x1adb, 0x7004, 0x0c7e, 0x2060, 0x6024,
-	0x0c7f, 0xd0f4, 0x0040, 0x19e1, 0x6808, 0x8001, 0x680a, 0x0078,
-	0x19f5, 0x684c, 0xc0f5, 0x684e, 0x7814, 0xa005, 0x00c0, 0x19f9,
-	0x7003, 0x0000, 0x6808, 0x8001, 0x680a, 0x00c0, 0x19f5, 0x7004,
-	0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078,
-	0x1adb, 0x7814, 0x6910, 0xa102, 0x6812, 0x6914, 0xa183, 0x0000,
-	0x6816, 0x7814, 0x7908, 0xa18c, 0x0fff, 0xa192, 0x0841, 0x00c8,
-	0x18ef, 0xa188, 0x0007, 0x8114, 0x8214, 0x8214, 0xa10a, 0x8104,
-	0x8004, 0x8004, 0xa20a, 0x810b, 0x810b, 0x810b, 0x1078, 0x1b5e,
-	0x7803, 0x0004, 0x780f, 0xffff, 0x7803, 0x0001, 0x7804, 0xd0fc,
-	0x0040, 0x1a1e, 0x7803, 0x0002, 0x7803, 0x0004, 0x780f, 0x0076,
-	0x7004, 0x7007, 0x0000, 0x2060, 0x2009, 0x0048, 0x1078, 0x775c,
-	0x1078, 0x1b92, 0x0040, 0x19f5, 0x8001, 0x7002, 0xd194, 0x0040,
-	0x1a46, 0x7804, 0xd0fc, 0x00c0, 0x191b, 0x8aff, 0x0040, 0x1adb,
-	0x2009, 0x0001, 0x1078, 0x1855, 0x0078, 0x1adb, 0xa184, 0x0880,
-	0x00c0, 0x1a53, 0x8aff, 0x0040, 0x1adb, 0x2009, 0x0001, 0x1078,
-	0x1855, 0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc,
-	0x00c0, 0x1a93, 0x027e, 0x037e, 0x7808, 0xd0ec, 0x00c0, 0x1a66,
-	0x7803, 0x0009, 0x7003, 0x0004, 0x0078, 0x1a68, 0x1078, 0x1bd7,
-	0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x0f7e, 0x2d78, 0x2804,
-	0xac68, 0x6034, 0xd09c, 0x00c0, 0x1a83, 0x6808, 0x2008, 0xa31a,
-	0x680c, 0xa213, 0x7810, 0xa100, 0x7812, 0x690c, 0x7814, 0xa101,
-	0x7816, 0x0078, 0x1a8f, 0x6810, 0x2008, 0xa31a, 0x6814, 0xa213,
-	0x7810, 0xa100, 0x7812, 0x6914, 0x7814, 0xa101, 0x7816, 0x0f7f,
-	0x0d7f, 0x0078, 0x196d, 0x057e, 0x7d0c, 0x1078, 0xa58e, 0x057f,
-	0x1078, 0x1af4, 0x0f7e, 0x7004, 0x2078, 0x1078, 0x4963, 0x0040,
-	0x1aa4, 0x7824, 0xc0f5, 0x7826, 0x0f7f, 0x682b, 0xffff, 0x682f,
-	0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x6912, 0x6980, 0x6916,
-	0x0078, 0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d,
-	0x0040, 0x1ac5, 0x6808, 0x8001, 0x680a, 0x00c0, 0x1ac5, 0x7004,
-	0x2060, 0x2009, 0x0048, 0x1078, 0x775c, 0x1078, 0x17c1, 0x0078,
-	0x1adb, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x6010,
-	0xa005, 0x0040, 0x1ac5, 0x2068, 0x6808, 0x8000, 0x680a, 0x6c28,
-	0x6b2c, 0x1078, 0x17e0, 0x017f, 0x007f, 0x127f, 0x007c, 0x127e,
-	0x2091, 0x2100, 0x7000, 0xa086, 0x0003, 0x00c0, 0x1af2, 0x700c,
-	0x7110, 0xa106, 0x0040, 0x1af2, 0x20e1, 0x9028, 0x700f, 0xa9ed,
-	0x7013, 0xa9ed, 0x127f, 0x007c, 0x0c7e, 0x1078, 0x1b22, 0x20e1,
-	0x9028, 0x700c, 0x7110, 0xa106, 0x0040, 0x1b19, 0x2104, 0xa005,
-	0x0040, 0x1b08, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a,
-	0xa188, 0x0003, 0xa182, 0xaa08, 0x0048, 0x1b10, 0x2009, 0xa9ed,
-	0x7112, 0x700c, 0xa106, 0x00c0, 0x1af9, 0x2011, 0x0008, 0x0078,
-	0x1af9, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001, 0x0138, 0x2202,
-	0x0c7f, 0x007c, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2021,
-	0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x00c0, 0x1b3f, 0x2001,
-	0x0109, 0x201c, 0xa39c, 0x0048, 0x00c0, 0x1b3f, 0x2001, 0x0111,
-	0x201c, 0x83ff, 0x00c0, 0x1b3f, 0x8421, 0x00c0, 0x1b29, 0x007c,
-	0x2011, 0x0201, 0x2009, 0x003c, 0x2204, 0xa005, 0x00c0, 0x1b4c,
-	0x8109, 0x00c0, 0x1b44, 0x007c, 0x007c, 0x1078, 0x1b40, 0x0040,
-	0x1b55, 0x780c, 0xd0a4, 0x0040, 0x1b5b, 0x1078, 0x1af4, 0xa085,
-	0x0001, 0x0078, 0x1b5d, 0x1078, 0x1b92, 0x007c, 0x0e7e, 0x2071,
-	0x0200, 0x7808, 0xa084, 0xf000, 0xa10d, 0x1078, 0x1b22, 0x2019,
-	0x5000, 0x8319, 0x0040, 0x1b7c, 0x2001, 0xaa08, 0x2004, 0xa086,
-	0x0000, 0x0040, 0x1b7c, 0x2001, 0x0021, 0xd0fc, 0x0040, 0x1b69,
-	0x1078, 0x1eaa, 0x0078, 0x1b67, 0x20e1, 0x7000, 0x7324, 0x7420,
-	0x7028, 0x7028, 0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f,
-	0x0100, 0x7037, 0x0008, 0x7326, 0x7422, 0x2001, 0x0138, 0x2202,
-	0x0e7f, 0x007c, 0x027e, 0x2001, 0x015d, 0x2001, 0x0000, 0x7908,
-	0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0048, 0x1ba0, 0x2009, 0x0000,
-	0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001,
-	0x020a, 0x82ff, 0x0040, 0x1bb5, 0x20e1, 0x6000, 0x200c, 0x200c,
-	0x200c, 0x200c, 0x8211, 0x00c0, 0x1bae, 0x20e1, 0x7000, 0x200c,
-	0x200c, 0x7003, 0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c,
-	0x2001, 0x0209, 0x2004, 0xa106, 0x0040, 0x1bd4, 0x1078, 0x1b40,
-	0x0040, 0x1bd2, 0x7908, 0xd1ec, 0x00c0, 0x1bd4, 0x790c, 0xd1a4,
-	0x0040, 0x1b97, 0x1078, 0x1af4, 0xa006, 0x027f, 0x007c, 0x7c20,
-	0x7d24, 0x7e30, 0x7f34, 0x700c, 0x7110, 0xa106, 0x0040, 0x1c69,
-	0x7004, 0x017e, 0x210c, 0xa106, 0x017f, 0x0040, 0x1c69, 0x0d7e,
-	0x0c7e, 0x216c, 0x2d00, 0xa005, 0x0040, 0x1c67, 0x681c, 0xa086,
-	0x0008, 0x0040, 0x1c67, 0x6824, 0xd0d4, 0x00c0, 0x1c67, 0x6810,
-	0x2068, 0x6850, 0xd0fc, 0x0040, 0x1c29, 0x8108, 0x2104, 0x6b2c,
-	0xa306, 0x00c0, 0x1c67, 0x8108, 0x2104, 0x6a28, 0xa206, 0x00c0,
-	0x1c67, 0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x6870,
-	0x7826, 0x681c, 0x7832, 0x6820, 0x7836, 0x6818, 0x2060, 0x6034,
-	0xd09c, 0x0040, 0x1c24, 0x6830, 0x2004, 0xac68, 0x6808, 0x783a,
-	0x680c, 0x783e, 0x0078, 0x1c65, 0xa006, 0x783a, 0x783e, 0x0078,
-	0x1c65, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6b2c, 0xa306,
-	0x00c0, 0x1c67, 0x8108, 0x2104, 0xa005, 0x00c0, 0x1c67, 0x6a28,
-	0xa206, 0x00c0, 0x1c67, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2004,
-	0x6918, 0xa160, 0xa180, 0x000d, 0x2004, 0xd09c, 0x00c0, 0x1c57,
-	0x6008, 0x7822, 0x686e, 0x600c, 0x7826, 0x6872, 0x6000, 0x7832,
-	0x6004, 0x7836, 0xa006, 0x783a, 0x783e, 0x0078, 0x1c65, 0x6010,
-	0x7822, 0x686e, 0x6014, 0x7826, 0x6872, 0x6000, 0x7832, 0x6004,
-	0x7836, 0x6008, 0x783a, 0x600c, 0x783e, 0x7803, 0x0011, 0x0c7f,
-	0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0x027e, 0x2071, 0xa9e7,
-	0x2079, 0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x0040,
-	0x1c92, 0x8211, 0x0040, 0x1c90, 0x2001, 0x0005, 0x2004, 0xd08c,
-	0x0040, 0x1c79, 0x7904, 0xa18c, 0x0780, 0x017e, 0x1078, 0x1913,
-	0x017f, 0x81ff, 0x00c0, 0x1c90, 0x2011, 0x0050, 0x0078, 0x1c74,
-	0xa085, 0x0001, 0x027f, 0x017f, 0x0e7f, 0x0f7f, 0x007c, 0x7803,
-	0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0040, 0x1ce8, 0x8109,
-	0x00c0, 0x1c9b, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003, 0x1048,
-	0x1332, 0x1078, 0x1fca, 0x0e7e, 0x0f7e, 0x2071, 0xa9d6, 0x2079,
-	0x0010, 0x7004, 0xa086, 0x0000, 0x0040, 0x1ce0, 0x7800, 0x007e,
-	0x7820, 0x007e, 0x7830, 0x007e, 0x7834, 0x007e, 0x7838, 0x007e,
-	0x783c, 0x007e, 0x7803, 0x0004, 0x7823, 0x0000, 0x0005, 0x0005,
-	0x2079, 0x0030, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x2079, 0x0010,
-	0x007f, 0x783e, 0x007f, 0x783a, 0x007f, 0x7836, 0x007f, 0x7832,
-	0x007f, 0x7822, 0x007f, 0x7802, 0x0f7f, 0x0e7f, 0x0078, 0x1ce6,
-	0x0f7f, 0x0e7f, 0x7804, 0xd0ac, 0x10c0, 0x1332, 0x1078, 0x639b,
-	0x007c, 0x0e7e, 0x2071, 0xaa08, 0x7003, 0x0000, 0x0e7f, 0x007c,
-	0x0d7e, 0xa280, 0x0004, 0x206c, 0x694c, 0xd1dc, 0x00c0, 0x1d6b,
-	0x6934, 0xa184, 0x0007, 0x0079, 0x1cfd, 0x1d05, 0x1d56, 0x1d05,
-	0x1d05, 0x1d05, 0x1d3b, 0x1d18, 0x1d07, 0x1078, 0x1332, 0x684c,
-	0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a,
-	0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6958, 0x0078, 0x1d5e,
-	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x00c0, 0x1d05, 0x684c,
-	0xd0b4, 0x0040, 0x1e79, 0x6860, 0x682e, 0x6816, 0x685c, 0x682a,
-	0x6812, 0x687c, 0x680a, 0x6880, 0x680e, 0x6804, 0x681a, 0xa080,
-	0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832,
-	0x6958, 0x0078, 0x1d67, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x00c0,
-	0x1d6b, 0x684c, 0xd0b4, 0x0040, 0x1e79, 0x6804, 0x681a, 0xa080,
-	0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832,
-	0x6958, 0xa006, 0x682e, 0x682a, 0x0078, 0x1d67, 0x684c, 0xd0b4,
-	0x0040, 0x18ed, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a,
-	0x6834, 0xa084, 0x000f, 0xa080, 0x206a, 0x2004, 0x6832, 0x6926,
-	0x684c, 0xc0dd, 0x684e, 0x0d7f, 0x007c, 0x0f7e, 0x2079, 0x0020,
-	0x7804, 0xd0fc, 0x10c0, 0x1eaa, 0x0e7e, 0x0d7e, 0x2071, 0xaa08,
-	0x7000, 0xa005, 0x00c0, 0x1df0, 0x0c7e, 0x7206, 0xa280, 0x0004,
-	0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x0d7e, 0x2068,
-	0x686c, 0x7812, 0x6890, 0x0f7e, 0x20e1, 0x9040, 0x2079, 0x0200,
-	0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x0f7f, 0x0d7f, 0x2b68,
-	0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc,
-	0x000f, 0x6908, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0007, 0x0040,
-	0x1db2, 0xa184, 0x0007, 0x0040, 0x1db2, 0x017e, 0x2009, 0x0008,
-	0xa102, 0x017f, 0xa108, 0x791a, 0x7116, 0x701e, 0x680c, 0xa081,
-	0x0000, 0x781e, 0x701a, 0xa006, 0x700e, 0x7012, 0x7004, 0x692c,
-	0x6814, 0xa106, 0x00c0, 0x1dc9, 0x6928, 0x6810, 0xa106, 0x0040,
-	0x1dd6, 0x037e, 0x047e, 0x6b14, 0x6c10, 0x1078, 0x208a, 0x047f,
-	0x037f, 0x0040, 0x1dd6, 0x0c7f, 0x0078, 0x1df0, 0x8aff, 0x00c0,
-	0x1dde, 0x0c7f, 0xa085, 0x0001, 0x0078, 0x1df0, 0x127e, 0x2091,
-	0x8000, 0x2079, 0x0020, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0040,
-	0x1ded, 0x2009, 0x0001, 0x1078, 0x1df4, 0x127f, 0x0c7f, 0xa006,
-	0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x077e, 0x067e, 0x057e, 0x047e,
-	0x037e, 0x027e, 0x8aff, 0x0040, 0x1e72, 0x700c, 0x7214, 0xa23a,
-	0x7010, 0x7218, 0xa203, 0x0048, 0x1e71, 0xa705, 0x0040, 0x1e71,
-	0xa03e, 0x2730, 0x6850, 0xd0fc, 0x00c0, 0x1e24, 0x0d7e, 0x2804,
-	0xac68, 0x2900, 0x0079, 0x1e14, 0x1e53, 0x1e34, 0x1e34, 0x1e53,
-	0x1e53, 0x1e4b, 0x1e53, 0x1e34, 0x1e53, 0x1e3a, 0x1e3a, 0x1e53,
-	0x1e53, 0x1e53, 0x1e42, 0x1e3a, 0xc0fc, 0x6852, 0x6b6c, 0x6a70,
-	0x6d1c, 0x6c20, 0xd99c, 0x0040, 0x1e57, 0x0d7e, 0x2804, 0xac68,
-	0x6f08, 0x6e0c, 0x0078, 0x1e56, 0x6b08, 0x6a0c, 0x6d00, 0x6c04,
-	0x0078, 0x1e56, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c,
-	0x0078, 0x1e56, 0x0d7f, 0x0d7e, 0x6834, 0xa084, 0x00ff, 0xa086,
-	0x001e, 0x00c0, 0x1e53, 0x0d7f, 0x1078, 0x2026, 0x00c0, 0x1dfa,
-	0xa00e, 0x0078, 0x1e72, 0x0d7f, 0x1078, 0x1332, 0x0d7f, 0x7b22,
-	0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902, 0x7000, 0x8000,
-	0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x700c,
-	0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x1078, 0x2026, 0x0078,
-	0x1e72, 0xa006, 0x027f, 0x037f, 0x047f, 0x057f, 0x067f, 0x077f,
-	0x007c, 0x1078, 0x1332, 0x027e, 0x2001, 0x0105, 0x2003, 0x0010,
-	0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060,
-	0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x1e92, 0x6850,
-	0xc0bd, 0x6852, 0x0d7f, 0x0c7e, 0x1078, 0x8a11, 0x0c7f, 0x2001,
-	0xa9c0, 0x2004, 0xac06, 0x00c0, 0x1ea7, 0x20e1, 0x9040, 0x1078,
-	0x738a, 0x2011, 0x0000, 0x1078, 0x70ea, 0x1078, 0x639b, 0x027f,
-	0x0078, 0x1f76, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x0f7e,
-	0x0e7e, 0x0d7e, 0x0c7e, 0x2079, 0x0020, 0x2071, 0xaa08, 0x2b68,
-	0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x00c0,
-	0x1e7b, 0x7000, 0x0079, 0x1ec4, 0x1f76, 0x1ec8, 0x1f43, 0x1f74,
-	0x8001, 0x7002, 0xd19c, 0x00c0, 0x1edc, 0x8aff, 0x0040, 0x1efb,
-	0x2009, 0x0001, 0x1078, 0x1df4, 0x0040, 0x1f76, 0x2009, 0x0001,
-	0x1078, 0x1df4, 0x0078, 0x1f76, 0x7803, 0x0004, 0xd194, 0x0040,
-	0x1eec, 0x6850, 0xc0fc, 0x6852, 0x8aff, 0x00c0, 0x1ef1, 0x684c,
-	0xc0f5, 0x684e, 0x0078, 0x1ef1, 0x1078, 0x203f, 0x6850, 0xc0fd,
-	0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003,
-	0x0000, 0x0078, 0x1f76, 0x711c, 0x81ff, 0x0040, 0x1f11, 0x7918,
-	0x7922, 0x7827, 0x0000, 0x7803, 0x0001, 0x7000, 0x8000, 0x7002,
-	0x700c, 0xa100, 0x700e, 0x7010, 0xa081, 0x0000, 0x7012, 0x0078,
-	0x1f76, 0x0f7e, 0x027e, 0x781c, 0x007e, 0x7818, 0x007e, 0x2079,
-	0x0100, 0x7a14, 0xa284, 0x0004, 0xa085, 0x0012, 0x7816, 0x037e,
-	0x2019, 0x1000, 0x8319, 0x1040, 0x1332, 0x7820, 0xd0bc, 0x00c0,
-	0x1f22, 0x037f, 0x79c8, 0x007f, 0xa102, 0x017f, 0x007e, 0x017e,
-	0x79c4, 0x007f, 0xa103, 0x78c6, 0x007f, 0x78ca, 0xa284, 0x0004,
-	0xa085, 0x0012, 0x7816, 0x027f, 0x0f7f, 0x7803, 0x0008, 0x7003,
-	0x0000, 0x0078, 0x1f76, 0x8001, 0x7002, 0xd194, 0x0040, 0x1f58,
-	0x7804, 0xd0fc, 0x00c0, 0x1eba, 0xd19c, 0x00c0, 0x1f72, 0x8aff,
-	0x0040, 0x1f76, 0x2009, 0x0001, 0x1078, 0x1df4, 0x0078, 0x1f76,
-	0x027e, 0x037e, 0x6b28, 0x6a2c, 0x1078, 0x203f, 0x0d7e, 0x2804,
-	0xac68, 0x6034, 0xd09c, 0x00c0, 0x1f6b, 0x6808, 0xa31a, 0x680c,
-	0xa213, 0x0078, 0x1f6f, 0x6810, 0xa31a, 0x6814, 0xa213, 0x0d7f,
-	0x0078, 0x1eec, 0x0078, 0x1eec, 0x1078, 0x1332, 0x0c7f, 0x0d7f,
-	0x0e7f, 0x0f7f, 0x017f, 0x007f, 0x127f, 0x007c, 0x0f7e, 0x0e7e,
-	0x2071, 0xaa08, 0x7000, 0xa086, 0x0000, 0x0040, 0x1fc7, 0x2079,
-	0x0020, 0x017e, 0x2009, 0x0207, 0x210c, 0xd194, 0x0040, 0x1fa4,
-	0x2009, 0x020c, 0x210c, 0xa184, 0x0003, 0x0040, 0x1fa4, 0x1078,
-	0xa5e2, 0x2001, 0x0133, 0x2004, 0xa005, 0x1040, 0x1332, 0x20e1,
-	0x9040, 0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009,
-	0x0203, 0x210c, 0xa106, 0x00c0, 0x1faf, 0x20e1, 0x9040, 0x7804,
-	0xd0fc, 0x0040, 0x1f8a, 0x1078, 0x1eaa, 0x7000, 0xa086, 0x0000,
-	0x00c0, 0x1f8a, 0x017f, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x00c0,
-	0x1fbd, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003, 0x0000, 0x0e7f,
-	0x0f7f, 0x007c, 0x027e, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071,
-	0xaa08, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000, 0x0040, 0x2003,
-	0x7004, 0x2060, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x1fed,
-	0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x00c0, 0x1fed,
-	0x6808, 0x7a18, 0xa206, 0x0040, 0x2009, 0x2001, 0x0105, 0x2003,
-	0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004,
-	0x2060, 0x1078, 0x8a11, 0x20e1, 0x9040, 0x1078, 0x738a, 0x2011,
-	0x0000, 0x1078, 0x70ea, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x027f,
-	0x007c, 0x6810, 0x6a14, 0xa205, 0x00c0, 0x1fed, 0x684c, 0xc0dc,
-	0x684e, 0x2c10, 0x1078, 0x1cf0, 0x2001, 0x0105, 0x2003, 0x0010,
-	0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x2069, 0xa9b1,
-	0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x2003, 0x8840, 0x2804,
-	0xa005, 0x00c0, 0x203a, 0x6004, 0xa005, 0x0040, 0x203c, 0x681a,
-	0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x206a, 0x2044, 0x88ff,
-	0x1040, 0x1332, 0x8a51, 0x007c, 0x2051, 0x0000, 0x007c, 0x8a50,
-	0x8841, 0x2804, 0xa005, 0x00c0, 0x2059, 0x2c00, 0xad06, 0x0040,
-	0x204e, 0x6000, 0xa005, 0x00c0, 0x204e, 0x2d00, 0x2060, 0x681a,
-	0x6034, 0xa084, 0x000f, 0xa080, 0x207a, 0x2044, 0x88ff, 0x1040,
-	0x1332, 0x007c, 0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021,
-	0x0025, 0x0029, 0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027,
-	0x0000, 0x0000, 0x0000, 0x205f, 0x205b, 0x0000, 0x0000, 0x2069,
-	0x0000, 0x205f, 0x0000, 0x2066, 0x2063, 0x0000, 0x0000, 0x0000,
-	0x2069, 0x2066, 0x0000, 0x2061, 0x2061, 0x0000, 0x0000, 0x2069,
-	0x0000, 0x2061, 0x0000, 0x2067, 0x2067, 0x0000, 0x0000, 0x0000,
-	0x2069, 0x2067, 0x0a7e, 0x097e, 0x087e, 0x6b2e, 0x6c2a, 0x6858,
-	0xa055, 0x0040, 0x212d, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0,
-	0x206a, 0xa986, 0x0007, 0x0040, 0x20a5, 0xa986, 0x000e, 0x0040,
-	0x20a5, 0xa986, 0x000f, 0x00c0, 0x20a9, 0x605c, 0xa422, 0x6060,
-	0xa31b, 0x2804, 0xa045, 0x00c0, 0x20b7, 0x0050, 0x20b1, 0x0078,
-	0x212d, 0x6004, 0xa065, 0x0040, 0x212d, 0x0078, 0x2094, 0x2804,
-	0xa005, 0x0040, 0x20d5, 0xac68, 0xd99c, 0x00c0, 0x20c5, 0x6808,
-	0xa422, 0x680c, 0xa31b, 0x0078, 0x20c9, 0x6810, 0xa422, 0x6814,
-	0xa31b, 0x0048, 0x20f4, 0x2300, 0xa405, 0x0040, 0x20db, 0x8a51,
-	0x0040, 0x212d, 0x8840, 0x0078, 0x20b7, 0x6004, 0xa065, 0x0040,
-	0x212d, 0x0078, 0x2094, 0x8a51, 0x0040, 0x212d, 0x8840, 0x2804,
-	0xa005, 0x00c0, 0x20ee, 0x6004, 0xa065, 0x0040, 0x212d, 0x6034,
-	0xa0cc, 0x000f, 0xa9c0, 0x206a, 0x2804, 0x2040, 0x2b68, 0x6850,
-	0xc0fc, 0x6852, 0x0078, 0x2121, 0x8422, 0x8420, 0x831a, 0xa399,
-	0x0000, 0x0d7e, 0x2b68, 0x6c6e, 0x6b72, 0x0d7f, 0xd99c, 0x00c0,
-	0x210f, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x1048,
-	0x1332, 0x6800, 0xa420, 0x6804, 0xa319, 0x0078, 0x211b, 0x6910,
-	0x2400, 0xa122, 0x6914, 0x2300, 0xa11b, 0x1048, 0x1332, 0x6800,
-	0xa420, 0x6804, 0xa319, 0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd,
-	0x6852, 0x2c00, 0x681a, 0x2800, 0x6832, 0x2a00, 0x6826, 0x007f,
-	0x007f, 0x007f, 0xa006, 0x0078, 0x2132, 0x087f, 0x097f, 0x0a7f,
-	0xa085, 0x0001, 0x007c, 0x2001, 0x0005, 0x2004, 0xa084, 0x0007,
-	0x0079, 0x213a, 0x2142, 0x2143, 0x2146, 0x2149, 0x214e, 0x2151,
-	0x2156, 0x215b, 0x007c, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x1913,
-	0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x007c, 0x1078, 0x14be,
-	0x007c, 0x1078, 0x1eaa, 0x1078, 0x14be, 0x007c, 0x1078, 0x1913,
-	0x1078, 0x14be, 0x007c, 0x1078, 0x1913, 0x1078, 0x1eaa, 0x1078,
-	0x14be, 0x007c, 0x127e, 0x2091, 0x2300, 0x2079, 0x0200, 0x2071,
-	0xac80, 0x2069, 0xa700, 0x2009, 0x0004, 0x7912, 0x7817, 0x0004,
-	0x1078, 0x251f, 0x781b, 0x0002, 0x20e1, 0x8700, 0x127f, 0x007c,
-	0x127e, 0x2091, 0x2300, 0x781c, 0xa084, 0x0007, 0x0079, 0x2180,
-	0x21a4, 0x2188, 0x218c, 0x2190, 0x2196, 0x219a, 0x219e, 0x21a2,
-	0x1078, 0x548e, 0x0078, 0x21a4, 0x1078, 0x54da, 0x0078, 0x21a4,
-	0x1078, 0x548e, 0x1078, 0x54da, 0x0078, 0x21a4, 0x1078, 0x21a6,
-	0x0078, 0x21a4, 0x1078, 0x21a6, 0x0078, 0x21a4, 0x1078, 0x21a6,
-	0x0078, 0x21a4, 0x1078, 0x21a6, 0x127f, 0x007c, 0x007e, 0x017e,
-	0x027e, 0x1078, 0xa5e2, 0x7930, 0xa184, 0x0003, 0x0040, 0x21c9,
-	0x2001, 0xa9c0, 0x2004, 0xa005, 0x0040, 0x21c5, 0x2001, 0x0133,
-	0x2004, 0xa005, 0x1040, 0x1332, 0x0c7e, 0x2001, 0xa9c0, 0x2064,
-	0x1078, 0x8a11, 0x0c7f, 0x0078, 0x21f2, 0x20e1, 0x9040, 0x0078,
-	0x21f2, 0xa184, 0x0030, 0x0040, 0x21da, 0x6a00, 0xa286, 0x0003,
-	0x00c0, 0x21d4, 0x0078, 0x21d6, 0x1078, 0x4224, 0x20e1, 0x9010,
-	0x0078, 0x21f2, 0xa184, 0x00c0, 0x0040, 0x21ec, 0x0e7e, 0x037e,
-	0x047e, 0x057e, 0x2071, 0xa9e7, 0x1078, 0x1af4, 0x057f, 0x047f,
-	0x037f, 0x0e7f, 0x0078, 0x21f2, 0xa184, 0x0300, 0x0040, 0x21f2,
-	0x20e1, 0x9020, 0x7932, 0x027f, 0x017f, 0x007f, 0x007c, 0x017e,
-	0x0e7e, 0x0f7e, 0x2071, 0xa700, 0x7128, 0x2001, 0xa990, 0x2102,
-	0x2001, 0xa998, 0x2102, 0xa182, 0x0211, 0x00c8, 0x220b, 0x2009,
-	0x0008, 0x0078, 0x2235, 0xa182, 0x0259, 0x00c8, 0x2213, 0x2009,
-	0x0007, 0x0078, 0x2235, 0xa182, 0x02c1, 0x00c8, 0x221b, 0x2009,
-	0x0006, 0x0078, 0x2235, 0xa182, 0x0349, 0x00c8, 0x2223, 0x2009,
-	0x0005, 0x0078, 0x2235, 0xa182, 0x0421, 0x00c8, 0x222b, 0x2009,
-	0x0004, 0x0078, 0x2235, 0xa182, 0x0581, 0x00c8, 0x2233, 0x2009,
-	0x0003, 0x0078, 0x2235, 0x2009, 0x0002, 0x2079, 0x0200, 0x7912,
-	0x7817, 0x0004, 0x1078, 0x251f, 0x0f7f, 0x0e7f, 0x017f, 0x007c,
-	0x127e, 0x2091, 0x2200, 0x2061, 0x0100, 0x2071, 0xa700, 0x6024,
-	0x6026, 0x6053, 0x0030, 0x6033, 0x00ef, 0x60e7, 0x0000, 0x60eb,
-	0x00ef, 0x60e3, 0x0008, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f,
-	0x0080, 0x602f, 0x0000, 0x6007, 0x0eaf, 0x600f, 0x00ff, 0x602b,
-	0x002f, 0x127f, 0x007c, 0x2001, 0xa730, 0x2003, 0x0000, 0x2001,
-	0xa72f, 0x2003, 0x0001, 0x007c, 0x127e, 0x2091, 0x2200, 0x007e,
-	0x017e, 0x027e, 0x6124, 0xa184, 0x002c, 0x00c0, 0x227b, 0xa184,
-	0x0007, 0x0079, 0x2281, 0xa195, 0x0004, 0xa284, 0x0007, 0x0079,
-	0x2281, 0x22ad, 0x2289, 0x228d, 0x2291, 0x2297, 0x229b, 0x22a1,
-	0x22a7, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078, 0x5d45, 0x0078,
-	0x22ad, 0x1078, 0x5d45, 0x1078, 0x5c56, 0x0078, 0x22ad, 0x1078,
-	0x22b2, 0x0078, 0x22ad, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x0078,
-	0x22ad, 0x1078, 0x5d45, 0x1078, 0x22b2, 0x0078, 0x22ad, 0x1078,
-	0x5d45, 0x1078, 0x5c56, 0x1078, 0x22b2, 0x027f, 0x017f, 0x007f,
-	0x127f, 0x007c, 0x6124, 0xd1ac, 0x0040, 0x23ac, 0x017e, 0x047e,
-	0x0c7e, 0x644c, 0xa486, 0xf0f0, 0x00c0, 0x22c5, 0x2061, 0x0100,
-	0x644a, 0x6043, 0x0090, 0x6043, 0x0010, 0x74c6, 0xa48c, 0xff00,
-	0x7034, 0xd084, 0x0040, 0x22dd, 0xa186, 0xf800, 0x00c0, 0x22dd,
-	0x703c, 0xd084, 0x00c0, 0x22dd, 0xc085, 0x703e, 0x037e, 0x2418,
-	0x2011, 0x8016, 0x1078, 0x361b, 0x037f, 0xa196, 0xff00, 0x0040,
-	0x231f, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa116, 0x0040, 0x231f,
-	0x7130, 0xd184, 0x00c0, 0x231f, 0x2011, 0xa753, 0x2214, 0xd2ec,
-	0x0040, 0x22fa, 0xc18d, 0x7132, 0x2011, 0xa753, 0x2214, 0xd2ac,
-	0x00c0, 0x231f, 0x6240, 0xa294, 0x0010, 0x0040, 0x2306, 0x6248,
-	0xa294, 0xff00, 0xa296, 0xff00, 0x0040, 0x231f, 0x7030, 0xd08c,
-	0x0040, 0x2371, 0x7034, 0xd08c, 0x00c0, 0x2316, 0x2001, 0xa70c,
-	0x200c, 0xd1ac, 0x00c0, 0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4,
-	0x2011, 0x8013, 0x1078, 0x361b, 0x037f, 0x0078, 0x2371, 0x7034,
-	0xd08c, 0x00c0, 0x232b, 0x2001, 0xa70c, 0x200c, 0xd1ac, 0x00c0,
-	0x2371, 0xc1ad, 0x2102, 0x037e, 0x73c4, 0x2011, 0x8013, 0x1078,
-	0x361b, 0x037f, 0x7130, 0xc185, 0x7132, 0x2011, 0xa753, 0x220c,
-	0xd1a4, 0x0040, 0x2355, 0x017e, 0x2009, 0x0001, 0x2011, 0x0100,
-	0x1078, 0x5bf1, 0x2019, 0x000e, 0x1078, 0xa1a5, 0xa484, 0x00ff,
-	0xa080, 0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x8127, 0xa006,
-	0x2009, 0x000e, 0x1078, 0xa22d, 0x017f, 0xd1ac, 0x00c0, 0x2362,
-	0x017e, 0x2009, 0x0000, 0x2019, 0x0004, 0x1078, 0x284f, 0x017f,
-	0x0078, 0x2371, 0x157e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x1078,
-	0x45c4, 0x00c0, 0x236d, 0x1078, 0x42f8, 0x8108, 0x00f0, 0x2367,
-	0x157f, 0x0c7f, 0x047f, 0x0f7e, 0x2079, 0xa9c4, 0x783c, 0xa086,
-	0x0000, 0x0040, 0x2383, 0x6027, 0x0004, 0x783f, 0x0000, 0x2079,
-	0x0140, 0x7803, 0x0000, 0x0f7f, 0x2011, 0x0003, 0x1078, 0x70e0,
-	0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019,
-	0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x017f, 0x2001,
-	0xa700, 0x2014, 0xa296, 0x0004, 0x00c0, 0x23a4, 0xd19c, 0x00c0,
-	0x23ac, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001, 0x2001, 0xa722,
-	0x2003, 0x0000, 0x6027, 0x0020, 0xd194, 0x0040, 0x2490, 0x0f7e,
-	0x2079, 0xa9c4, 0x783c, 0xa086, 0x0001, 0x00c0, 0x23d0, 0x017e,
-	0x6027, 0x0004, 0x783f, 0x0000, 0x2079, 0x0140, 0x7803, 0x1000,
-	0x7803, 0x0000, 0x2079, 0xa9b1, 0x7807, 0x0000, 0x7833, 0x0000,
-	0x1078, 0x62d1, 0x1078, 0x639b, 0x017f, 0x0f7f, 0x0078, 0x2490,
-	0x0f7f, 0x017e, 0x3900, 0xa082, 0xaae3, 0x00c8, 0x23db, 0x017e,
-	0x1078, 0x747a, 0x017f, 0x6220, 0xd2b4, 0x0040, 0x2446, 0x1078,
-	0x5acb, 0x1078, 0x6e0f, 0x6027, 0x0004, 0x0f7e, 0x2019, 0xa9ba,
-	0x2304, 0xa07d, 0x0040, 0x241c, 0x7804, 0xa086, 0x0032, 0x00c0,
-	0x241c, 0x0d7e, 0x0c7e, 0x0e7e, 0x2069, 0x0140, 0x618c, 0x6288,
-	0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002, 0x2001, 0x0003,
-	0x8001, 0x00c0, 0x2400, 0x6043, 0x0000, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x618e, 0x628a, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x7810,
-	0x2070, 0x7037, 0x0103, 0x2f60, 0x1078, 0x772d, 0x0e7f, 0x0c7f,
-	0x0d7f, 0x0f7f, 0x017f, 0x007c, 0x0f7f, 0x0d7e, 0x2069, 0x0140,
-	0x6804, 0xa084, 0x4000, 0x0040, 0x2429, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa9b1, 0x6028, 0xa09a, 0x00c8,
-	0x00c8, 0x2439, 0x8000, 0x602a, 0x0c7f, 0x1078, 0x6e01, 0x0078,
-	0x248f, 0x2019, 0xa9ba, 0x2304, 0xa065, 0x0040, 0x2443, 0x2009,
-	0x0027, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x248f, 0xd2bc, 0x0040,
-	0x248f, 0x1078, 0x5ad8, 0x6017, 0x0010, 0x6027, 0x0004, 0x0d7e,
-	0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0040, 0x245b, 0x6803,
-	0x1000, 0x6803, 0x0000, 0x0d7f, 0x0c7e, 0x2061, 0xa9b1, 0x6044,
-	0xa09a, 0x00c8, 0x00c8, 0x247e, 0x8000, 0x6046, 0x603c, 0x0c7f,
-	0xa005, 0x0040, 0x248f, 0x2009, 0x07d0, 0x1078, 0x5ad0, 0xa080,
-	0x0007, 0x2004, 0xa086, 0x0006, 0x00c0, 0x247a, 0x6017, 0x0012,
-	0x0078, 0x248f, 0x6017, 0x0016, 0x0078, 0x248f, 0x037e, 0x2019,
-	0x0001, 0x1078, 0x7058, 0x037f, 0x2019, 0xa9c0, 0x2304, 0xa065,
-	0x0040, 0x248e, 0x2009, 0x004f, 0x1078, 0x775c, 0x0c7f, 0x017f,
-	0xd19c, 0x0040, 0x24e4, 0x7034, 0xd0ac, 0x00c0, 0x24c1, 0x017e,
-	0x157e, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9, 0x000a, 0x00f0,
-	0x249f, 0x602f, 0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9,
-	0x0320, 0x00e0, 0x24a9, 0x2091, 0x6000, 0x6020, 0xd09c, 0x00c0,
-	0x24b8, 0x157f, 0x6152, 0x017f, 0x6027, 0x0008, 0x0078, 0x24e4,
-	0x1078, 0x2577, 0x00f0, 0x24a9, 0x157f, 0x6152, 0x017f, 0x6027,
-	0x0008, 0x017e, 0x6028, 0xc09c, 0x602a, 0x2011, 0x0003, 0x1078,
-	0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e,
-	0x2019, 0x0000, 0x1078, 0x7058, 0x037f, 0x60e3, 0x0000, 0x1078,
-	0xa5bd, 0x1078, 0xa5db, 0x2001, 0xa700, 0x2003, 0x0004, 0x6027,
-	0x0008, 0x1078, 0x1246, 0x017f, 0xa18c, 0xffd0, 0x6126, 0x007c,
-	0x007e, 0x017e, 0x027e, 0x0e7e, 0x0f7e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0xa700, 0x71bc, 0x70be, 0xa116, 0x0040, 0x2518, 0x81ff,
-	0x0040, 0x2500, 0x2011, 0x8011, 0x1078, 0x361b, 0x0078, 0x2518,
-	0x2011, 0x8012, 0x1078, 0x361b, 0x2001, 0xa772, 0x2004, 0xd0fc,
-	0x00c0, 0x2518, 0x037e, 0x0c7e, 0x1078, 0x6f9f, 0x2061, 0x0100,
-	0x2019, 0x0028, 0x2009, 0x0000, 0x1078, 0x284f, 0x0c7f, 0x037f,
-	0x127f, 0x0f7f, 0x0e7f, 0x027f, 0x017f, 0x007f, 0x007c, 0x0c7e,
-	0x0f7e, 0x007e, 0x027e, 0x2061, 0x0100, 0xa190, 0x253b, 0x2204,
-	0x60f2, 0x2011, 0x2548, 0x6000, 0xa082, 0x0003, 0x00c8, 0x2534,
-	0x2001, 0x00ff, 0x0078, 0x2535, 0x2204, 0x60ee, 0x027f, 0x007f,
-	0x0f7f, 0x0c7f, 0x007c, 0x0840, 0x0840, 0x0840, 0x0580, 0x0420,
-	0x0348, 0x02c0, 0x0258, 0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8,
-	0x0140, 0x00f8, 0x00d0, 0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff,
-	0x2130, 0xa094, 0xff00, 0x00c0, 0x2558, 0x81ff, 0x0040, 0x255c,
-	0x1078, 0x5761, 0x0078, 0x2563, 0xa080, 0x29c0, 0x200c, 0xa18c,
-	0xff00, 0x810f, 0xa006, 0x007c, 0xa080, 0x29c0, 0x200c, 0xa18c,
-	0x00ff, 0x007c, 0x0c7e, 0x2061, 0xa700, 0x6030, 0x0040, 0x2573,
-	0xc09d, 0x0078, 0x2574, 0xc09c, 0x6032, 0x0c7f, 0x007c, 0x007e,
-	0x157e, 0x0f7e, 0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c,
-	0x00c0, 0x2584, 0x00f0, 0x257e, 0x0f7f, 0x157f, 0x007f, 0x007c,
-	0x0c7e, 0x007e, 0x2061, 0x0100, 0x6030, 0x007e, 0x6048, 0x007e,
-	0x60e4, 0x007e, 0x60e8, 0x007e, 0x6050, 0x007e, 0x60f0, 0x007e,
-	0x60ec, 0x007e, 0x600c, 0x007e, 0x6004, 0x007e, 0x6028, 0x007e,
-	0x60e0, 0x007e, 0x602f, 0x0100, 0x602f, 0x0000, 0x0005, 0x0005,
-	0x0005, 0x0005, 0x602f, 0x0040, 0x602f, 0x0000, 0x007f, 0x60e2,
-	0x007f, 0x602a, 0x007f, 0x6006, 0x007f, 0x600e, 0x007f, 0x60ee,
-	0x007f, 0x60f2, 0x007f, 0x6052, 0x007f, 0x60ea, 0x007f, 0x60e6,
-	0x007f, 0x604a, 0x007f, 0x6032, 0x007f, 0x0c7f, 0x007c, 0x25e7,
-	0x25eb, 0x25ef, 0x25f5, 0x25fb, 0x2601, 0x2607, 0x260f, 0x2617,
-	0x261d, 0x2623, 0x262b, 0x2633, 0x263b, 0x2643, 0x264d, 0x2657,
-	0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657,
-	0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x2657, 0x107e,
-	0x007e, 0x0078, 0x2670, 0x107e, 0x007e, 0x0078, 0x2670, 0x107e,
-	0x007e, 0x1078, 0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078,
-	0x226c, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078,
-	0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e,
-	0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e,
-	0x007e, 0x1078, 0x226c, 0x1078, 0x2133, 0x0078, 0x2670, 0x107e,
-	0x007e, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078,
-	0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078,
-	0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078,
-	0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078,
-	0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x2133, 0x1078,
-	0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078, 0x226c, 0x1078,
-	0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x107e, 0x007e, 0x1078,
-	0x226c, 0x1078, 0x2133, 0x1078, 0x2178, 0x0078, 0x2670, 0x0005,
-	0x0078, 0x2657, 0xb084, 0x003c, 0x8004, 0x8004, 0x0079, 0x2660,
-	0x2670, 0x25ed, 0x25f1, 0x25f7, 0x25fd, 0x2603, 0x2609, 0x2611,
-	0x2619, 0x261f, 0x2625, 0x262d, 0x2635, 0x263d, 0x2645, 0x264f,
-	0x0008, 0x265a, 0x007f, 0x107f, 0x2091, 0x8001, 0x007c, 0x0c7e,
-	0x027e, 0x047e, 0x2021, 0x0000, 0x1078, 0x4967, 0x00c0, 0x2772,
-	0x70cc, 0xd09c, 0x0040, 0x268e, 0xd084, 0x00c0, 0x268e, 0xd0bc,
-	0x00c0, 0x2772, 0x1078, 0x2776, 0x0078, 0x2772, 0xd0cc, 0x00c0,
-	0x2772, 0xd094, 0x0040, 0x2698, 0x7097, 0xffff, 0x0078, 0x2772,
-	0x2001, 0x010c, 0x203c, 0x7284, 0xd284, 0x0040, 0x2701, 0xd28c,
-	0x00c0, 0x2701, 0x037e, 0x7394, 0xa38e, 0xffff, 0x0040, 0x26ab,
-	0x83ff, 0x00c0, 0x26ad, 0x2019, 0x0001, 0x8314, 0xa2e0, 0xadc0,
-	0x2c04, 0xa38c, 0x0001, 0x0040, 0x26ba, 0xa084, 0xff00, 0x8007,
-	0x0078, 0x26bc, 0xa084, 0x00ff, 0xa70e, 0x0040, 0x26f6, 0xa08e,
-	0x0000, 0x0040, 0x26f6, 0xa08e, 0x00ff, 0x00c0, 0x26d3, 0x7230,
-	0xd284, 0x00c0, 0x26fc, 0x7284, 0xc28d, 0x7286, 0x7097, 0xffff,
-	0x037f, 0x0078, 0x2701, 0x2009, 0x0000, 0x1078, 0x254d, 0x1078,
-	0x455c, 0x00c0, 0x26f9, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x00c0, 0x26f0, 0x7030, 0xd08c, 0x0040, 0x26ea, 0x6000, 0xd0bc,
-	0x0040, 0x26f0, 0x1078, 0x278c, 0x0040, 0x26f9, 0x0078, 0x26f6,
-	0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x26f9, 0x8318, 0x0078,
-	0x26ad, 0x7396, 0x0078, 0x26fe, 0x7097, 0xffff, 0x037f, 0x0078,
-	0x2772, 0xa780, 0x29c0, 0x203c, 0xa7bc, 0xff00, 0x873f, 0x2041,
-	0x007e, 0x7094, 0xa096, 0xffff, 0x00c0, 0x2713, 0x2009, 0x0000,
-	0x28a8, 0x0078, 0x271f, 0xa812, 0x0048, 0x271b, 0x2008, 0xa802,
-	0x20a8, 0x0078, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x2700,
-	0x157e, 0x017e, 0xa106, 0x0040, 0x2766, 0xc484, 0x1078, 0x45c4,
-	0x0040, 0x2730, 0x1078, 0x455c, 0x00c0, 0x276f, 0x0078, 0x2731,
-	0xc485, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2740,
-	0x7030, 0xd08c, 0x0040, 0x275e, 0x6000, 0xd0bc, 0x00c0, 0x275e,
-	0x7284, 0xd28c, 0x0040, 0x2756, 0x6004, 0xa084, 0x00ff, 0xa082,
-	0x0006, 0x0048, 0x2766, 0xd484, 0x00c0, 0x2752, 0x1078, 0x457f,
-	0x0078, 0x2754, 0x1078, 0x298e, 0x0078, 0x2766, 0x1078, 0x28c4,
-	0x1078, 0x27b9, 0x0040, 0x276f, 0x0078, 0x2766, 0x1078, 0x2959,
-	0x0040, 0x2766, 0x1078, 0x278c, 0x0040, 0x276f, 0x017f, 0x8108,
-	0x157f, 0x00f0, 0x271f, 0x7097, 0xffff, 0x0078, 0x2772, 0x017f,
-	0x157f, 0x7196, 0x047f, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x017e,
-	0x7097, 0x0001, 0x2009, 0x007e, 0x1078, 0x455c, 0x00c0, 0x2789,
-	0x1078, 0x28c4, 0x1078, 0x27b9, 0x0040, 0x2789, 0x70cc, 0xc0bd,
-	0x70ce, 0x017f, 0x0c7f, 0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e,
-	0x2c68, 0x2001, 0xa757, 0x2004, 0xa084, 0x00ff, 0x6842, 0x1078,
-	0x76c7, 0x0040, 0x27b4, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001,
-	0x0000, 0x1078, 0x44ee, 0x2001, 0x0000, 0x1078, 0x4502, 0x127e,
-	0x2091, 0x8000, 0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0004,
-	0x1078, 0x775c, 0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f,
-	0x007c, 0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x2001, 0xa757,
-	0x2004, 0xa084, 0x00ff, 0x6842, 0x1078, 0x9197, 0x0040, 0x27f2,
-	0x2d00, 0x601a, 0x6800, 0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e,
-	0x0040, 0x27db, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
-	0x27db, 0x1078, 0x2880, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078,
-	0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000,
-	0x7090, 0x8000, 0x7092, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c,
-	0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e,
-	0x027e, 0x2009, 0x0080, 0x1078, 0x455c, 0x00c0, 0x2805, 0x1078,
-	0x2808, 0x0040, 0x2805, 0x70d3, 0xffff, 0x027f, 0x0c7f, 0x007c,
-	0x017e, 0x077e, 0x0d7e, 0x0c7e, 0x2c68, 0x1078, 0x76c7, 0x0040,
-	0x282a, 0x2d00, 0x601a, 0x601f, 0x0001, 0x2001, 0x0000, 0x1078,
-	0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x127e, 0x2091, 0x8000,
-	0x70d4, 0x8000, 0x70d6, 0x127f, 0x2009, 0x0002, 0x1078, 0x775c,
-	0xa085, 0x0001, 0x0c7f, 0x0d7f, 0x077f, 0x017f, 0x007c, 0x0c7e,
-	0x0d7e, 0x127e, 0x2091, 0x8000, 0x2009, 0x007f, 0x1078, 0x455c,
-	0x00c0, 0x284b, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x284b, 0x2d00,
-	0x601a, 0x6312, 0x601f, 0x0001, 0x620a, 0x2009, 0x0022, 0x1078,
-	0x775c, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x0c7f, 0x007c, 0x0e7e,
-	0x0c7e, 0x067e, 0x037e, 0x027e, 0x1078, 0x5f0e, 0x1078, 0x5eae,
-	0x1078, 0x8068, 0x2130, 0x81ff, 0x0040, 0x2864, 0x20a9, 0x007e,
-	0x2009, 0x0000, 0x0078, 0x2868, 0x20a9, 0x007f, 0x2009, 0x0000,
-	0x017e, 0x1078, 0x45c4, 0x00c0, 0x2871, 0x1078, 0x47e9, 0x1078,
-	0x42f8, 0x017f, 0x8108, 0x00f0, 0x2868, 0x86ff, 0x00c0, 0x287a,
-	0x1078, 0x119b, 0x027f, 0x037f, 0x067f, 0x0c7f, 0x0e7f, 0x007c,
-	0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x6218, 0x2270, 0x72a0,
-	0x027e, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000,
-	0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, 0x017f, 0x2e60,
-	0x1078, 0x47e9, 0x6210, 0x6314, 0x1078, 0x42f8, 0x6212, 0x6316,
-	0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x007e,
-	0x6018, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x00c0, 0x28ba, 0x2071,
-	0xa700, 0x7090, 0xa005, 0x0040, 0x28b7, 0x8001, 0x7092, 0x007f,
-	0x0e7f, 0x007c, 0x2071, 0xa700, 0x70d4, 0xa005, 0x0040, 0x28b7,
-	0x8001, 0x70d6, 0x0078, 0x28b7, 0x6000, 0xc08c, 0x6002, 0x007c,
-	0x0f7e, 0x0e7e, 0x0c7e, 0x037e, 0x027e, 0x017e, 0x157e, 0x2178,
-	0x81ff, 0x00c0, 0x28d7, 0x20a9, 0x0001, 0x0078, 0x28f2, 0x2001,
-	0xa753, 0x2004, 0xd0c4, 0x0040, 0x28ee, 0xd0a4, 0x0040, 0x28ee,
-	0x047e, 0x6018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427,
-	0xa006, 0x2009, 0x002d, 0x1078, 0xa22d, 0x047f, 0x20a9, 0x00ff,
-	0x2011, 0x0000, 0x027e, 0xa28e, 0x007e, 0x0040, 0x2936, 0xa28e,
-	0x007f, 0x0040, 0x2936, 0xa28e, 0x0080, 0x0040, 0x2936, 0xa288,
-	0xa835, 0x210c, 0x81ff, 0x0040, 0x2936, 0x8fff, 0x1040, 0x2942,
-	0x0c7e, 0x2160, 0x2001, 0x0001, 0x1078, 0x4972, 0x0c7f, 0x2019,
-	0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a,
-	0x0c7e, 0x027e, 0x2160, 0x6204, 0xa294, 0x00ff, 0xa286, 0x0006,
-	0x00c0, 0x2926, 0x6007, 0x0404, 0x0078, 0x292b, 0x2001, 0x0004,
-	0x8007, 0xa215, 0x6206, 0x027f, 0x0c7f, 0x017e, 0x2c08, 0x1078,
-	0x9f9b, 0x017f, 0x077f, 0x2160, 0x1078, 0x47e9, 0x027f, 0x8210,
-	0x00f0, 0x28f2, 0x157f, 0x017f, 0x027f, 0x037f, 0x0c7f, 0x0e7f,
-	0x0f7f, 0x007c, 0x047e, 0x027e, 0x017e, 0x2001, 0xa753, 0x2004,
-	0xd0c4, 0x0040, 0x2955, 0xd0a4, 0x0040, 0x2955, 0xa006, 0x2220,
-	0x8427, 0x2009, 0x0029, 0x1078, 0xa22d, 0x017f, 0x027f, 0x047f,
-	0x007c, 0x017e, 0x027e, 0x037e, 0x0c7e, 0x7284, 0x82ff, 0x0040,
-	0x2987, 0xa290, 0xa753, 0x2214, 0xd2ac, 0x00c0, 0x2987, 0x2100,
-	0x1078, 0x2564, 0x81ff, 0x0040, 0x2989, 0x2019, 0x0001, 0x8314,
-	0xa2e0, 0xadc0, 0x2c04, 0xd384, 0x0040, 0x297b, 0xa084, 0xff00,
-	0x8007, 0x0078, 0x297d, 0xa084, 0x00ff, 0xa116, 0x0040, 0x2989,
-	0xa096, 0x00ff, 0x0040, 0x2987, 0x8318, 0x0078, 0x296f, 0xa085,
-	0x0001, 0x0c7f, 0x037f, 0x027f, 0x017f, 0x007c, 0x017e, 0x0c7e,
-	0x127e, 0x2091, 0x8000, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e,
-	0x2019, 0x0029, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f,
-	0x027f, 0x017f, 0xa180, 0xa835, 0x2004, 0xa065, 0x0040, 0x29b7,
-	0x017e, 0x0c7e, 0x1078, 0x9197, 0x017f, 0x1040, 0x1332, 0x611a,
-	0x1078, 0x2880, 0x1078, 0x772d, 0x017f, 0x1078, 0x457f, 0x127f,
-	0x0c7f, 0x017f, 0x007c, 0x2001, 0xa733, 0x2004, 0xd0cc, 0x007c,
-	0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da,
-	0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce,
-	0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5,
-	0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3,
-	0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9,
-	0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b,
-	0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081,
-	0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073,
-	0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69,
-	0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056,
-	0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c,
-	0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c,
-	0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831,
-	0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026,
-	0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017,
-	0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000,
-	0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000,
-	0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300,
-	0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100,
-	0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00,
-	0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800,
-	0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000,
-	0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000,
-	0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500,
-	0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000,
-	0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000,
-	0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000,
-	0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000,
-	0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x2071, 0xa782, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016, 0x703a,
-	0x703e, 0x7033, 0xa792, 0x7037, 0xa792, 0x7007, 0x0001, 0x2061,
-	0xa7d2, 0x6003, 0x0002, 0x007c, 0x0090, 0x2ae7, 0x0068, 0x2ae7,
-	0x2071, 0xa782, 0x2b78, 0x7818, 0xd084, 0x00c0, 0x2ae7, 0x2a60,
-	0x7820, 0xa08e, 0x0069, 0x00c0, 0x2bd7, 0x0079, 0x2b6b, 0x007c,
-	0x2071, 0xa782, 0x7004, 0x0079, 0x2aed, 0x2af1, 0x2af2, 0x2afc,
-	0x2b0e, 0x007c, 0x0090, 0x2afb, 0x0068, 0x2afb, 0x2b78, 0x7818,
-	0xd084, 0x0040, 0x2b1a, 0x007c, 0x2b78, 0x2061, 0xa7d2, 0x6008,
-	0xa08e, 0x0100, 0x0040, 0x2b09, 0xa086, 0x0200, 0x0040, 0x2bcf,
-	0x007c, 0x7014, 0x2068, 0x2a60, 0x7018, 0x007a, 0x7010, 0x2068,
-	0x6834, 0xa086, 0x0103, 0x0040, 0x2b16, 0x007c, 0x2a60, 0x2b78,
-	0x7018, 0x007a, 0x2a60, 0x7820, 0xa08a, 0x0040, 0x00c8, 0x2b23,
-	0x61bc, 0x0079, 0x2b2b, 0x2100, 0xa08a, 0x003f, 0x00c8, 0x2bcb,
-	0x61bc, 0x0079, 0x2b6b, 0x2bad, 0x2bdf, 0x2be7, 0x2beb, 0x2bf3,
-	0x2bf9, 0x2bfd, 0x2c09, 0x2c0d, 0x2c17, 0x2c1b, 0x2bcb, 0x2bcb,
-	0x2bcb, 0x2c1f, 0x2bcb, 0x2c2f, 0x2c46, 0x2c5d, 0x2cdd, 0x2ce2,
-	0x2d0f, 0x2d69, 0x2d7a, 0x2d98, 0x2dd9, 0x2de3, 0x2df0, 0x2e03,
-	0x2e22, 0x2e2b, 0x2e68, 0x2e6e, 0x2bcb, 0x2e8a, 0x2bcb, 0x2bcb,
-	0x2bcb, 0x2bcb, 0x2bcb, 0x2e91, 0x2e9b, 0x2bcb, 0x2bcb, 0x2bcb,
-	0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2ea3, 0x2bcb, 0x2bcb,
-	0x2bcb, 0x2bcb, 0x2bcb, 0x2eb5, 0x2ece, 0x2bcb, 0x2bcb, 0x2bcb,
-	0x2bcb, 0x2bcb, 0x2bcb, 0x2ee0, 0x2f37, 0x2f95, 0x2fa9, 0x2bcb,
-	0x2bcb, 0x2bcb, 0x398e, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb,
-	0x2bcb, 0x2bcb, 0x2bcb, 0x2c17, 0x2c1b, 0x2fc0, 0x2bcb, 0x2fcd,
-	0x3a26, 0x3a83, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb,
-	0x2bcb, 0x2bcb, 0x2bcb, 0x301a, 0x314f, 0x316b, 0x3177, 0x31da,
-	0x3233, 0x323e, 0x327d, 0x328c, 0x329b, 0x329e, 0x2fd1, 0x32c2,
-	0x331e, 0x332b, 0x343c, 0x356f, 0x3599, 0x36a6, 0x2bcb, 0x36b6,
-	0x36f0, 0x37bf, 0x2bcb, 0x2bcb, 0x2bcb, 0x2bcb, 0x3827, 0x3843,
-	0x38bd, 0x3977, 0x713c, 0x0078, 0x2bad, 0x2021, 0x4000, 0x1078,
-	0x35f5, 0x127e, 0x2091, 0x8000, 0x0068, 0x2bba, 0x7818, 0xd084,
-	0x0040, 0x2bbd, 0x127f, 0x0078, 0x2bb1, 0x7c22, 0x7926, 0x7a2a,
-	0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091,
-	0x5000, 0x127f, 0x007c, 0x2021, 0x4001, 0x0078, 0x2baf, 0x2021,
-	0x4002, 0x0078, 0x2baf, 0x2021, 0x4003, 0x0078, 0x2baf, 0x2021,
-	0x4005, 0x0078, 0x2baf, 0x2021, 0x4006, 0x0078, 0x2baf, 0xa02e,
-	0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0078, 0x3604, 0x7823,
-	0x0004, 0x7824, 0x007a, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824,
-	0x7930, 0x0078, 0x3608, 0x7924, 0x7828, 0x2114, 0x200a, 0x0078,
-	0x2bad, 0x7924, 0x2114, 0x0078, 0x2bad, 0x2099, 0x0009, 0x20a1,
-	0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924, 0x7a28, 0x7b2c, 0x0078,
-	0x2bad, 0x7824, 0x2060, 0x0078, 0x2c21, 0x2009, 0x0001, 0x2011,
-	0x0013, 0x2019, 0x0019, 0x783b, 0x0017, 0x0078, 0x2bad, 0x7d38,
-	0x7c3c, 0x0078, 0x2be1, 0x7d38, 0x7c3c, 0x0078, 0x2bed, 0x2061,
-	0x1000, 0x610c, 0xa006, 0x2c14, 0xa200, 0x8c60, 0x8109, 0x00c0,
-	0x2c23, 0x2010, 0xa005, 0x0040, 0x2bad, 0x0078, 0x2bd3, 0x2069,
-	0xa752, 0x7824, 0x7930, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040,
-	0x2bdb, 0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006,
-	0x685a, 0x685e, 0x1078, 0x4eae, 0x0078, 0x2bad, 0x2069, 0xa752,
-	0x7824, 0x7934, 0xa11a, 0x00c8, 0x2bdb, 0x8019, 0x0040, 0x2bdb,
-	0x684e, 0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a,
-	0x686e, 0x1078, 0x4a3e, 0x0078, 0x2bad, 0xa02e, 0x2520, 0x81ff,
-	0x00c0, 0x2bd7, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1,
-	0xa789, 0x41a1, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020,
-	0x1078, 0x3604, 0x701b, 0x2c75, 0x007c, 0x6834, 0x2008, 0xa084,
-	0x00ff, 0xa096, 0x0011, 0x0040, 0x2c85, 0xa096, 0x0019, 0x0040,
-	0x2c85, 0xa096, 0x0015, 0x00c0, 0x2bd7, 0x810f, 0xa18c, 0x00ff,
-	0x0040, 0x2bd7, 0x710e, 0x700c, 0x8001, 0x0040, 0x2cb6, 0x700e,
-	0x1078, 0x35ba, 0x0040, 0x2bd7, 0x2009, 0x0020, 0x2061, 0xa7d2,
-	0x6224, 0x6328, 0x642c, 0x6530, 0xa290, 0x0040, 0xa399, 0x0000,
-	0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x1078, 0x3604, 0x701b, 0x2ca9,
-	0x007c, 0x6834, 0xa084, 0x00ff, 0xa096, 0x0002, 0x0040, 0x2cb4,
-	0xa096, 0x000a, 0x00c0, 0x2bd7, 0x0078, 0x2c8b, 0x7010, 0x2068,
-	0x6838, 0xc0fd, 0x683a, 0x1078, 0x4431, 0x00c0, 0x2cc4, 0x7007,
-	0x0003, 0x701b, 0x2cc6, 0x007c, 0x1078, 0x4b51, 0x127e, 0x2091,
-	0x8000, 0x20a9, 0x0005, 0x2099, 0xa789, 0x530a, 0x2100, 0xa210,
-	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80, 0x000d,
-	0x2009, 0x0020, 0x127f, 0x0078, 0x3608, 0x61a4, 0x7824, 0x60a6,
-	0x0078, 0x2bad, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827, 0x4953,
-	0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104, 0x7832,
-	0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200, 0x603c,
-	0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e, 0x781b,
-	0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010, 0x20c1,
-	0x00f0, 0xa08a, 0x0003, 0x00c8, 0x0427, 0x0078, 0x0423, 0x81ff,
-	0x00c0, 0x2bd7, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4,
-	0x00c0, 0x2bdb, 0x7e38, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048,
-	0x2d23, 0x0078, 0x2bdb, 0x7c28, 0x7d2c, 0x1078, 0x47a4, 0xd28c,
-	0x00c0, 0x2d2e, 0x1078, 0x4736, 0x0078, 0x2d30, 0x1078, 0x4772,
-	0x00c0, 0x2d5a, 0x2061, 0xae00, 0x127e, 0x2091, 0x8000, 0x6000,
-	0xa086, 0x0000, 0x0040, 0x2d48, 0x6010, 0xa06d, 0x0040, 0x2d48,
-	0x683c, 0xa406, 0x00c0, 0x2d48, 0x6840, 0xa506, 0x0040, 0x2d53,
-	0x127f, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02, 0x00c8,
-	0x2bd7, 0x0078, 0x2d34, 0x1078, 0x8a11, 0x127f, 0x0040, 0x2bd7,
-	0x0078, 0x2bad, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x8f95, 0x1078, 0x4a73, 0x127f, 0x0078,
-	0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb,
-	0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078, 0x47b2, 0x0040, 0x2bd7,
-	0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040,
-	0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0005, 0x1078,
-	0x47d3, 0x0040, 0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb,
-	0x8003, 0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x0078, 0x2bad,
-	0x127e, 0x2091, 0x8000, 0x81ff, 0x0040, 0x2da2, 0x2009, 0x0001,
-	0x0078, 0x2dd3, 0x2029, 0x00ff, 0x6450, 0x2400, 0xa506, 0x0040,
-	0x2dcd, 0x2508, 0x1078, 0x45c4, 0x00c0, 0x2dcd, 0x1078, 0x482f,
-	0x00c0, 0x2db8, 0x2009, 0x0002, 0x62ac, 0x2518, 0x0078, 0x2dd3,
-	0x2019, 0x0004, 0x1078, 0x47d3, 0x00c0, 0x2dc2, 0x2009, 0x0006,
-	0x0078, 0x2dd3, 0x7824, 0xa08a, 0x1000, 0x00c8, 0x2dd6, 0x8003,
-	0x800b, 0x810b, 0xa108, 0x1078, 0x5a52, 0x8529, 0x00c8, 0x2da5,
-	0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bd7, 0x127f, 0x0078,
-	0x2bdb, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x46e7, 0x1078,
-	0x47a4, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2,
-	0x0040, 0x2bdb, 0x1078, 0x46d6, 0x1078, 0x47a4, 0x0078, 0x2bad,
-	0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078,
-	0x4775, 0x0040, 0x2bd7, 0x1078, 0x4484, 0x1078, 0x472f, 0x1078,
-	0x47a4, 0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078,
-	0x4673, 0x0040, 0x2bd7, 0x62a0, 0x2019, 0x0005, 0x0c7e, 0x1078,
-	0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078,
-	0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x1078, 0x47a4,
-	0x0078, 0x2bad, 0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x47a4,
-	0x2208, 0x0078, 0x2bad, 0x157e, 0x0d7e, 0x0e7e, 0x2069, 0xa814,
-	0x6810, 0x6914, 0xa10a, 0x00c8, 0x2e37, 0x2009, 0x0000, 0x6816,
-	0x2011, 0x0000, 0x2019, 0x0000, 0x20a9, 0x00ff, 0x2069, 0xa835,
-	0x2d04, 0xa075, 0x0040, 0x2e4c, 0x704c, 0x1078, 0x2e56, 0xa210,
-	0x7080, 0x1078, 0x2e56, 0xa318, 0x8d68, 0x00f0, 0x2e40, 0x2300,
-	0xa218, 0x0e7f, 0x0d7f, 0x157f, 0x0078, 0x2bad, 0x0f7e, 0x017e,
-	0xa07d, 0x0040, 0x2e65, 0x2001, 0x0000, 0x8000, 0x2f0c, 0x81ff,
-	0x0040, 0x2e65, 0x2178, 0x0078, 0x2e5d, 0x017f, 0x0f7f, 0x007c,
-	0x2069, 0xa814, 0x6910, 0x62a8, 0x0078, 0x2bad, 0x81ff, 0x00c0,
-	0x2bd7, 0x6150, 0xa190, 0x29c0, 0x2214, 0xa294, 0x00ff, 0x6070,
-	0xa084, 0xff00, 0xa215, 0x636c, 0x67cc, 0xd79c, 0x0040, 0x2e84,
-	0x2031, 0x0001, 0x0078, 0x2e86, 0x2031, 0x0000, 0x7e3a, 0x7f3e,
-	0x0078, 0x2bad, 0x6140, 0x6244, 0x2019, 0xa9a2, 0x231c, 0x0078,
-	0x2bad, 0x127e, 0x2091, 0x8000, 0x6134, 0x6338, 0xa006, 0x2010,
-	0x127f, 0x0078, 0x2bad, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6244,
-	0x6338, 0x0078, 0x2bad, 0x6140, 0x6244, 0x7824, 0x6042, 0x7b28,
-	0x6346, 0x2069, 0xa752, 0x831f, 0xa305, 0x6816, 0x782c, 0x2069,
-	0xa9a2, 0x2d1c, 0x206a, 0x0078, 0x2bad, 0x017e, 0x127e, 0x2091,
-	0x8000, 0x7824, 0x6036, 0xd094, 0x0040, 0x2ec8, 0x7828, 0xa085,
-	0x0001, 0x2009, 0xa9ab, 0x200a, 0x2001, 0xffff, 0x1078, 0x5ae6,
-	0x782c, 0x603a, 0x127f, 0x017f, 0x0078, 0x2bad, 0x1078, 0x35e4,
-	0x0040, 0x2bdb, 0x7828, 0xa00d, 0x0040, 0x2bdb, 0x782c, 0xa005,
-	0x0040, 0x2bdb, 0x6244, 0x6146, 0x6338, 0x603a, 0x0078, 0x2bad,
-	0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e,
-	0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff,
-	0x00c0, 0x2ef7, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f06, 0xa182,
-	0x007f, 0x00c8, 0x2f30, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff,
-	0x6030, 0xa116, 0x0040, 0x2f30, 0x810f, 0xa105, 0x127e, 0x2091,
-	0x8000, 0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f2c, 0x601a,
-	0x600b, 0xbc09, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f33,
-	0x6837, 0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078,
-	0x775c, 0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7,
-	0x0c7f, 0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f2c, 0x2001,
-	0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x0c7e, 0x2061,
-	0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x00c0,
-	0x2f4e, 0x6030, 0xa085, 0xff00, 0x0078, 0x2f5d, 0xa182, 0x007f,
-	0x00c8, 0x2f87, 0xa188, 0x29c0, 0x210c, 0xa18c, 0x00ff, 0x6030,
-	0xa116, 0x0040, 0x2f87, 0x810f, 0xa105, 0x127e, 0x2091, 0x8000,
-	0x007e, 0x1078, 0x76c7, 0x007f, 0x0040, 0x2f83, 0x601a, 0x600b,
-	0xbc05, 0x601f, 0x0001, 0x1078, 0x35ba, 0x0040, 0x2f8a, 0x6837,
-	0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x701b, 0x2f8e, 0x2d00, 0x6012, 0x2009, 0x0032, 0x1078, 0x775c,
-	0x127f, 0x0c7f, 0x007c, 0x127f, 0x0c7f, 0x0078, 0x2bd7, 0x0c7f,
-	0x0078, 0x2bdb, 0x1078, 0x772d, 0x0078, 0x2f83, 0x6830, 0xa086,
-	0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad, 0x2061, 0xaa33, 0x127e,
-	0x2091, 0x8000, 0x6000, 0xd084, 0x0040, 0x2fa6, 0x6104, 0x6208,
-	0x2019, 0xa712, 0x231c, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078,
-	0x2bdb, 0x81ff, 0x00c0, 0x2bd7, 0x127e, 0x2091, 0x8000, 0x6248,
-	0x6064, 0xa202, 0x0048, 0x2fbd, 0xa085, 0x0001, 0x1078, 0x256a,
-	0x1078, 0x3c9e, 0x127f, 0x0078, 0x2bad, 0x127f, 0x0078, 0x2bdb,
-	0x127e, 0x2091, 0x8000, 0x20a9, 0x0012, 0x2001, 0xa740, 0x20a0,
-	0xa006, 0x40a4, 0x127f, 0x0078, 0x2bad, 0x7d38, 0x7c3c, 0x0078,
-	0x2c5f, 0x7824, 0xa09c, 0x00ff, 0xa39a, 0x0003, 0x00c8, 0x2bd7,
-	0x6250, 0xa084, 0xff00, 0x8007, 0xa206, 0x00c0, 0x2fe9, 0x2001,
-	0xa740, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0078,
-	0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x2bd7, 0x0c7e,
-	0x1078, 0x35ba, 0x0c7f, 0x0040, 0x2bd7, 0x6837, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x1078, 0x8e5a, 0x0040, 0x2bd7, 0x7007, 0x0003,
-	0x701b, 0x300b, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7,
-	0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x0078, 0x3608, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x1078, 0x42dd,
-	0x2009, 0x001c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604,
-	0x701b, 0x302b, 0x007c, 0xade8, 0x000d, 0x6800, 0xa005, 0x0040,
-	0x2bdb, 0x6804, 0xd0ac, 0x0040, 0x3038, 0xd0a4, 0x0040, 0x2bdb,
-	0xd094, 0x0040, 0x3043, 0x0c7e, 0x2061, 0x0100, 0x6104, 0xa18c,
-	0xffdf, 0x6106, 0x0c7f, 0xd08c, 0x0040, 0x304e, 0x0c7e, 0x2061,
-	0x0100, 0x6104, 0xa18d, 0x0010, 0x6106, 0x0c7f, 0x2009, 0x0100,
-	0x210c, 0xa18a, 0x0002, 0x0048, 0x3063, 0xd084, 0x0040, 0x3063,
-	0x6a28, 0xa28a, 0x007f, 0x00c8, 0x2bdb, 0xa288, 0x29c0, 0x210c,
-	0xa18c, 0x00ff, 0x6156, 0xd0dc, 0x0040, 0x306c, 0x6828, 0xa08a,
-	0x007f, 0x00c8, 0x2bdb, 0x6052, 0x6808, 0xa08a, 0x0100, 0x0048,
-	0x2bdb, 0xa08a, 0x0841, 0x00c8, 0x2bdb, 0xa084, 0x0007, 0x00c0,
-	0x2bdb, 0x680c, 0xa005, 0x0040, 0x2bdb, 0x6810, 0xa005, 0x0040,
-	0x2bdb, 0x6848, 0x6940, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040,
-	0x2bdb, 0x684c, 0x6944, 0xa10a, 0x00c8, 0x2bdb, 0x8001, 0x0040,
-	0x2bdb, 0x6804, 0xd0fc, 0x0040, 0x30c2, 0x1078, 0x35ba, 0x0040,
-	0x2bd7, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0xa290,
-	0x0038, 0xa399, 0x0000, 0x1078, 0x3604, 0x701b, 0x30a8, 0x007c,
-	0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xa76e, 0x2da0,
-	0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xa772, 0x200c, 0xd1e4,
-	0x0040, 0x30c2, 0x0c7e, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00,
-	0x6006, 0x0c7f, 0x20a9, 0x001c, 0x2d98, 0x2069, 0xa752, 0x2da0,
-	0x53a3, 0x6814, 0xa08c, 0x00ff, 0x6142, 0x8007, 0xa084, 0x00ff,
-	0x6046, 0x1078, 0x4eae, 0x1078, 0x49ce, 0x1078, 0x4a3e, 0x6000,
-	0xa086, 0x0000, 0x00c0, 0x314d, 0x6808, 0x602a, 0x1078, 0x21f7,
-	0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f,
-	0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0040, 0x30fa,
-	0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f,
-	0x0078, 0x30fc, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312,
-	0x1078, 0x5b19, 0x6904, 0xd1fc, 0x0040, 0x312f, 0x0c7e, 0x2009,
-	0x0000, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0040, 0x312c, 0x0078,
-	0x3116, 0x839d, 0x00c8, 0x312c, 0x3508, 0x8109, 0x1078, 0x5480,
-	0x6878, 0x6016, 0x6874, 0x2008, 0xa084, 0xff00, 0x8007, 0x600a,
-	0xa184, 0x00ff, 0x6006, 0x8108, 0x00c0, 0x312a, 0x6003, 0x0003,
-	0x0078, 0x312c, 0x6003, 0x0001, 0x00f0, 0x3111, 0x0c7f, 0x0c7e,
-	0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x0c7f, 0x1078,
-	0x3819, 0x0040, 0x313d, 0x1078, 0x256a, 0x60c0, 0xa005, 0x0040,
-	0x3149, 0x6003, 0x0001, 0x2091, 0x301d, 0x1078, 0x4224, 0x0078,
-	0x314d, 0x6003, 0x0004, 0x2091, 0x301d, 0x0078, 0x2bad, 0x6000,
-	0xa086, 0x0000, 0x0040, 0x2bd7, 0x2069, 0xa752, 0x7830, 0x6842,
-	0x7834, 0x6846, 0x6804, 0xd0fc, 0x0040, 0x3162, 0x2009, 0x0030,
-	0x0078, 0x3164, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28, 0x7c3c,
-	0x7d38, 0x0078, 0x3608, 0xa006, 0x1078, 0x256a, 0x81ff, 0x00c0,
-	0x2bd7, 0x1078, 0x42dd, 0x1078, 0x4224, 0x0078, 0x2bad, 0x81ff,
-	0x00c0, 0x2bd7, 0x6184, 0x81ff, 0x0040, 0x3191, 0x703f, 0x0000,
-	0x2001, 0xadc0, 0x2009, 0x0040, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x3608, 0x701b, 0x2baa, 0x127f,
-	0x007c, 0x703f, 0x0001, 0x0d7e, 0x2069, 0xadc0, 0x20a9, 0x0040,
-	0x20a1, 0xadc0, 0x2019, 0xffff, 0x43a4, 0x6550, 0xa588, 0x29c0,
-	0x210c, 0xa18c, 0x00ff, 0x216a, 0xa00e, 0x2011, 0x0002, 0x2100,
-	0xa506, 0x0040, 0x31c3, 0x1078, 0x45c4, 0x00c0, 0x31c3, 0x6014,
-	0x821c, 0x0048, 0x31bb, 0xa398, 0xadc0, 0xa085, 0xff00, 0x8007,
-	0x201a, 0x0078, 0x31c2, 0xa398, 0xadc0, 0x2324, 0xa4a4, 0xff00,
-	0xa405, 0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x00c8, 0x31ca,
-	0x0078, 0x31a7, 0x8201, 0x8007, 0x2d0c, 0xa105, 0x206a, 0x0d7f,
-	0x20a9, 0x0040, 0x20a1, 0xadc0, 0x2099, 0xadc0, 0x1078, 0x4281,
-	0x0078, 0x3180, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0c7e, 0x1078,
-	0x35ba, 0x0c7f, 0x00c0, 0x31e8, 0x2009, 0x0002, 0x0078, 0x2bd7,
-	0x2001, 0xa753, 0x2004, 0xd0b4, 0x0040, 0x320f, 0x6000, 0xd08c,
-	0x00c0, 0x320f, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
-	0x320f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x1078, 0x8eae,
-	0x00c0, 0x3206, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003,
-	0x701b, 0x320b, 0x007c, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x20a9,
-	0x002b, 0x2c98, 0xade8, 0x0002, 0x2da0, 0x53a3, 0x20a9, 0x0004,
-	0xac80, 0x0006, 0x2098, 0xad80, 0x0006, 0x20a0, 0x1078, 0x4281,
-	0x20a9, 0x0004, 0xac80, 0x000a, 0x2098, 0xad80, 0x000a, 0x20a0,
-	0x1078, 0x4281, 0x2d00, 0x2009, 0x002b, 0x7a2c, 0x7b28, 0x7c3c,
-	0x7d38, 0x0078, 0x3608, 0x81ff, 0x00c0, 0x2bd7, 0x1078, 0x35d2,
-	0x0040, 0x2bdb, 0x1078, 0x47bd, 0x0078, 0x2bad, 0x81ff, 0x00c0,
-	0x2bd7, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x1078, 0x35e4,
-	0x0040, 0x2bdb, 0x1078, 0x482f, 0x0040, 0x2bd7, 0x2019, 0x0004,
-	0x1078, 0x47d3, 0x7924, 0x810f, 0x7a28, 0x1078, 0x3259, 0x0078,
-	0x2bad, 0xa186, 0x00ff, 0x0040, 0x3261, 0x1078, 0x3271, 0x0078,
-	0x3270, 0x2029, 0x007e, 0x2061, 0xa700, 0x6450, 0x2400, 0xa506,
-	0x0040, 0x326d, 0x2508, 0x1078, 0x3271, 0x8529, 0x00c8, 0x3266,
-	0x007c, 0x1078, 0x45c4, 0x00c0, 0x327c, 0x2200, 0x8003, 0x800b,
-	0x810b, 0xa108, 0x1078, 0x5a52, 0x007c, 0x81ff, 0x00c0, 0x2bd7,
-	0x1078, 0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7,
-	0x1078, 0x47c8, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7, 0x1078,
-	0x35d2, 0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x1078,
-	0x47b2, 0x0078, 0x2bad, 0x6100, 0x0078, 0x2bad, 0x1078, 0x35e4,
-	0x0040, 0x2bdb, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0,
-	0x2bd7, 0x0d7e, 0xace8, 0x000a, 0x7924, 0xd184, 0x0040, 0x32b2,
-	0xace8, 0x0006, 0x680c, 0x8007, 0x783e, 0x6808, 0x8007, 0x783a,
-	0x6b04, 0x831f, 0x6a00, 0x8217, 0x0d7f, 0x6100, 0xa18c, 0x0200,
-	0x0078, 0x2bad, 0xa006, 0x1078, 0x256a, 0x7824, 0xa084, 0x00ff,
-	0xa086, 0x00ff, 0x0040, 0x32cf, 0x81ff, 0x00c0, 0x2bd7, 0x1078,
-	0x42dd, 0x7828, 0xa08a, 0x1000, 0x00c8, 0x2bdb, 0x7924, 0xa18c,
-	0xff00, 0x810f, 0xa186, 0x00ff, 0x0040, 0x32e5, 0xa182, 0x007f,
-	0x00c8, 0x2bdb, 0x2100, 0x1078, 0x2564, 0x027e, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x2061, 0xa9c4, 0x601b, 0x0000, 0x601f, 0x0000,
-	0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002, 0x1078, 0x70ea,
-	0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078, 0x7058, 0x037f,
-	0x2061, 0x0100, 0x6030, 0xa084, 0x00ff, 0x810f, 0xa105, 0x604a,
-	0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d, 0x2011, 0x4259,
-	0x1078, 0x5add, 0x7924, 0xa18c, 0xff00, 0x810f, 0x7a28, 0x1078,
-	0x3259, 0x127f, 0x0c7f, 0x027f, 0x0078, 0x2bad, 0x7924, 0xa18c,
-	0xff00, 0x810f, 0x0c7e, 0x1078, 0x455c, 0x2c08, 0x0c7f, 0x00c0,
-	0x2bdb, 0x0078, 0x2bad, 0x81ff, 0x0040, 0x3332, 0x2009, 0x0001,
-	0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x333a, 0x2009, 0x0005,
-	0x0078, 0x2bd7, 0x1078, 0x35ba, 0x00c0, 0x3342, 0x2009, 0x0002,
-	0x0078, 0x2bd7, 0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078,
-	0x3604, 0x701b, 0x334c, 0x007c, 0x2009, 0x0080, 0x1078, 0x45c4,
-	0x00c0, 0x3359, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x0040,
-	0x335d, 0x2021, 0x400a, 0x0078, 0x2baf, 0x0d7e, 0xade8, 0x000d,
-	0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x6e18, 0x6820, 0xa0be,
-	0x0100, 0x0040, 0x33d0, 0xa0be, 0x0112, 0x0040, 0x33d0, 0xa0be,
-	0x0113, 0x0040, 0x33d0, 0xa0be, 0x0114, 0x0040, 0x33d0, 0xa0be,
-	0x0117, 0x0040, 0x33d0, 0xa0be, 0x011a, 0x0040, 0x33d0, 0xa0be,
-	0x0121, 0x0040, 0x33c6, 0xa0be, 0x0131, 0x0040, 0x33c6, 0xa0be,
-	0x0171, 0x0040, 0x33d0, 0xa0be, 0x0173, 0x0040, 0x33d0, 0xa0be,
-	0x01a1, 0x00c0, 0x3398, 0x6830, 0x8007, 0x6832, 0x0078, 0x33d6,
-	0xa0be, 0x0212, 0x0040, 0x33cc, 0xa0be, 0x0213, 0x0040, 0x33cc,
-	0xa0be, 0x0214, 0x0040, 0x33be, 0xa0be, 0x0217, 0x0040, 0x33b8,
-	0xa0be, 0x021a, 0x00c0, 0x33b1, 0x6838, 0x8007, 0x683a, 0x0078,
-	0x33d0, 0xa0be, 0x0300, 0x0040, 0x33d0, 0x0d7f, 0x0078, 0x2bdb,
-	0xad80, 0x0010, 0x20a9, 0x0007, 0x1078, 0x3418, 0xad80, 0x000e,
-	0x20a9, 0x0001, 0x1078, 0x3418, 0x0078, 0x33d0, 0xad80, 0x000c,
-	0x1078, 0x3426, 0x0078, 0x33d6, 0xad80, 0x000e, 0x1078, 0x3426,
-	0xad80, 0x000c, 0x20a9, 0x0001, 0x1078, 0x3418, 0x0c7e, 0x1078,
-	0x35ba, 0x0040, 0x3409, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119,
-	0x6853, 0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e,
-	0x6883, 0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b,
-	0x0000, 0x0c7f, 0x0d7f, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x6823, 0x0000, 0x6804, 0x2068, 0x1078, 0x8e76, 0x00c0, 0x3404,
-	0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x340f,
-	0x007c, 0x0c7f, 0x0d7f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6820,
-	0xa086, 0x8001, 0x00c0, 0x2bad, 0x2009, 0x0004, 0x0078, 0x2bd7,
-	0x017e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108,
-	0x280a, 0x8108, 0x00f0, 0x341a, 0x017f, 0x007c, 0x017e, 0x0a7e,
-	0x0b7e, 0x2008, 0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000,
-	0x205c, 0x2b0a, 0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a,
-	0x0b7f, 0x0a7f, 0x017f, 0x007c, 0x81ff, 0x0040, 0x3443, 0x2009,
-	0x0001, 0x0078, 0x2bd7, 0x60cc, 0xd09c, 0x00c0, 0x344b, 0x2009,
-	0x0005, 0x0078, 0x2bd7, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f,
-	0xa182, 0x0080, 0x0048, 0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb,
-	0x7a2c, 0x7b28, 0x606c, 0xa306, 0x00c0, 0x3466, 0x6070, 0xa24e,
-	0x0040, 0x2bdb, 0xa9cc, 0xff00, 0x0040, 0x2bdb, 0x0c7e, 0x1078,
-	0x350f, 0x2c68, 0x0c7f, 0x0040, 0x349e, 0xa0c6, 0x4000, 0x00c0,
-	0x3484, 0x0c7e, 0x007e, 0x2d60, 0x2009, 0x0000, 0x1078, 0x489b,
-	0x00c0, 0x347b, 0xc185, 0x6000, 0xd0bc, 0x0040, 0x3480, 0xc18d,
-	0x007f, 0x0c7f, 0x0078, 0x349b, 0xa0c6, 0x4007, 0x00c0, 0x348b,
-	0x2408, 0x0078, 0x349b, 0xa0c6, 0x4008, 0x00c0, 0x3493, 0x2708,
-	0x2610, 0x0078, 0x349b, 0xa0c6, 0x4009, 0x00c0, 0x3499, 0x0078,
-	0x349b, 0x2001, 0x4006, 0x2020, 0x0078, 0x2baf, 0x2d00, 0x7022,
-	0x017e, 0x0b7e, 0x0c7e, 0x0e7e, 0x2c70, 0x1078, 0x76c7, 0x0040,
-	0x34e4, 0x2d00, 0x601a, 0x2001, 0xa757, 0x2004, 0xa084, 0x00ff,
-	0x6842, 0x2e58, 0x0e7f, 0x0e7e, 0x0c7e, 0x1078, 0x35ba, 0x0c7f,
-	0x2b70, 0x00c0, 0x34c5, 0x1078, 0x772d, 0x0e7f, 0x0c7f, 0x0b7f,
-	0x017f, 0x2009, 0x0002, 0x0078, 0x2bd7, 0x6837, 0x0000, 0x2d00,
-	0x6012, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x2880, 0x127f, 0x601f, 0x0001, 0x2001, 0x0000,
-	0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x2009, 0x0002,
-	0x1078, 0x775c, 0xa085, 0x0001, 0x0e7f, 0x0c7f, 0x0b7f, 0x017f,
-	0x00c0, 0x34ee, 0x2009, 0x0003, 0x0078, 0x2bd7, 0x7007, 0x0003,
-	0x701b, 0x34f3, 0x007c, 0x6830, 0xa086, 0x0100, 0x7020, 0x2060,
-	0x00c0, 0x3501, 0x2009, 0x0004, 0x6204, 0xa294, 0x00ff, 0x0078,
-	0x2bd7, 0x2009, 0x0000, 0x1078, 0x489b, 0x00c0, 0x3508, 0xc185,
-	0x6000, 0xd0bc, 0x0040, 0x350d, 0xc18d, 0x0078, 0x2bad, 0x0e7e,
-	0x0d7e, 0x2029, 0x0000, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071,
-	0xa8b5, 0x2e04, 0xa005, 0x00c0, 0x3524, 0x2100, 0xa406, 0x00c0,
-	0x3555, 0x2428, 0x0078, 0x3555, 0x2068, 0x6f10, 0x2700, 0xa306,
-	0x00c0, 0x3546, 0x6e14, 0x2600, 0xa206, 0x00c0, 0x3546, 0x2400,
-	0xa106, 0x00c0, 0x3542, 0x2d60, 0xd884, 0x0040, 0x356a, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x356a, 0x2001, 0x4000,
-	0x0078, 0x356b, 0x2001, 0x4007, 0x0078, 0x356b, 0x2400, 0xa106,
-	0x00c0, 0x3555, 0x6e14, 0x87ff, 0x00c0, 0x3551, 0x86ff, 0x0040,
-	0x3521, 0x2001, 0x4008, 0x0078, 0x356b, 0x8420, 0x8e70, 0x00f0,
-	0x3519, 0x85ff, 0x00c0, 0x3564, 0x2001, 0x4009, 0x0078, 0x356b,
-	0x2001, 0x0001, 0x0078, 0x356b, 0x1078, 0x455c, 0x00c0, 0x3560,
-	0x6312, 0x6216, 0xa006, 0xa005, 0x0d7f, 0x0e7f, 0x007c, 0x81ff,
-	0x00c0, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7, 0x6837, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005, 0x0040, 0x2bdb, 0xa096,
-	0x00ff, 0x0040, 0x3587, 0xa092, 0x0004, 0x00c8, 0x2bdb, 0x2010,
-	0x2d18, 0x1078, 0x282f, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b,
-	0x3592, 0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078,
-	0x2bad, 0x7924, 0xa18c, 0xff00, 0x810f, 0xa182, 0x0080, 0x0048,
-	0x2bdb, 0xa182, 0x00ff, 0x00c8, 0x2bdb, 0x127e, 0x2091, 0x8000,
-	0x1078, 0x8d5b, 0x00c0, 0x35b7, 0xa190, 0xa835, 0x2204, 0xa065,
-	0x0040, 0x35b7, 0x1078, 0x42f8, 0x127f, 0x0078, 0x2bad, 0x127f,
-	0x0078, 0x2bd7, 0x1078, 0x138b, 0x0040, 0x35d1, 0xa006, 0x6802,
-	0x7010, 0xa005, 0x00c0, 0x35c9, 0x2d00, 0x7012, 0x7016, 0x0078,
-	0x35cf, 0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80,
-	0x000d, 0x007c, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x1078, 0x45c4,
-	0x00c0, 0x35e1, 0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0048,
-	0x35e2, 0xa066, 0x8cff, 0x007c, 0x7e24, 0x860f, 0xa18c, 0x00ff,
-	0x1078, 0x45c4, 0x00c0, 0x35f2, 0xa6b4, 0x00ff, 0xa682, 0x4000,
-	0x0048, 0x35f3, 0xa066, 0x8cff, 0x007c, 0x017e, 0x7110, 0x81ff,
-	0x0040, 0x3600, 0x2168, 0x6904, 0x1078, 0x13a4, 0x0078, 0x35f7,
-	0x7112, 0x7116, 0x017f, 0x007c, 0x2031, 0x0001, 0x0078, 0x360a,
-	0x2031, 0x0000, 0x2061, 0xa7d2, 0x6606, 0x6112, 0x600e, 0x6226,
-	0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002,
-	0x701b, 0x2bad, 0x007c, 0x0f7e, 0x127e, 0x2091, 0x8000, 0x2079,
-	0x0000, 0x2001, 0xa790, 0x2004, 0xa005, 0x00c0, 0x3636, 0x0068,
-	0x3636, 0x7818, 0xd084, 0x00c0, 0x3636, 0x7a22, 0x7b26, 0x7c2a,
-	0x781b, 0x0001, 0x2091, 0x4080, 0x0078, 0x365b, 0x017e, 0x0c7e,
-	0x0e7e, 0x2071, 0xa782, 0x7138, 0xa182, 0x0008, 0x0048, 0x3644,
-	0x7030, 0x2060, 0x0078, 0x3655, 0x7030, 0xa0e0, 0x0008, 0xac82,
-	0xa7d2, 0x0048, 0x364d, 0x2061, 0xa792, 0x2c00, 0x7032, 0x81ff,
-	0x00c0, 0x3653, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306, 0x640a,
-	0x0e7f, 0x0c7f, 0x017f, 0x127f, 0x0f7f, 0x007c, 0x0e7e, 0x2071,
-	0xa782, 0x7038, 0xa005, 0x0040, 0x3697, 0x127e, 0x2091, 0x8000,
-	0x0068, 0x3696, 0x0f7e, 0x2079, 0x0000, 0x7818, 0xd084, 0x00c0,
-	0x3695, 0x0c7e, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826,
-	0x6008, 0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001,
-	0x703a, 0xa005, 0x00c0, 0x368b, 0x7033, 0xa792, 0x7037, 0xa792,
-	0x0c7f, 0x0078, 0x3695, 0xac80, 0x0008, 0xa0fa, 0xa7d2, 0x0048,
-	0x3693, 0x2001, 0xa792, 0x7036, 0x0c7f, 0x0f7f, 0x127f, 0x0e7f,
-	0x007c, 0x027e, 0x2001, 0xa753, 0x2004, 0xd0c4, 0x0040, 0x36a4,
-	0x2011, 0x8014, 0x1078, 0x361b, 0x027f, 0x007c, 0x81ff, 0x00c0,
-	0x2bd7, 0x127e, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac,
-	0x6032, 0x1078, 0x4224, 0x127f, 0x0078, 0x2bad, 0x81ff, 0x00c0,
-	0x2bd7, 0x6000, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x2001, 0xa753,
-	0x2004, 0xd0ac, 0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x36d3, 0x7828,
-	0xa005, 0x0040, 0x2bad, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x0040,
-	0x2bd7, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x1078, 0x8f22, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x36e9,
-	0x007c, 0x6830, 0xa086, 0x0100, 0x0040, 0x2bd7, 0x0078, 0x2bad,
-	0x2001, 0xa700, 0x2004, 0xa086, 0x0003, 0x00c0, 0x2bd7, 0x7f24,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x35ba, 0x0040, 0x2bd7,
-	0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000,
-	0xad80, 0x0005, 0x7026, 0x20a0, 0x1078, 0x45c4, 0x00c0, 0x376d,
-	0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0040, 0x371d, 0xa0c4,
-	0xff00, 0xa8c6, 0x0600, 0x00c0, 0x376d, 0x2001, 0xa753, 0x2004,
-	0xd0ac, 0x00c0, 0x372a, 0x1078, 0x489b, 0x00c0, 0x372a, 0xd79c,
-	0x0040, 0x376d, 0xd794, 0x00c0, 0x3730, 0xd784, 0x0040, 0x373c,
-	0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004, 0x53a3, 0x1078,
-	0x3426, 0xd794, 0x0040, 0x3745, 0xac80, 0x000a, 0x2098, 0x3400,
-	0x20a9, 0x0004, 0x53a3, 0x1078, 0x3426, 0x21a2, 0xd794, 0x0040,
-	0x3765, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3,
-	0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400,
-	0x20a9, 0x0002, 0x53a3, 0x1078, 0x3418, 0xac80, 0x0026, 0x2098,
-	0x20a9, 0x0002, 0x53a3, 0x0078, 0x3766, 0x94a0, 0xd794, 0x0040,
-	0x376b, 0xa6b0, 0x000b, 0xa6b0, 0x0005, 0x8108, 0xd78c, 0x0040,
-	0x3777, 0xa186, 0x0100, 0x0040, 0x3788, 0x0078, 0x377b, 0xa186,
-	0x007e, 0x0040, 0x3788, 0xd794, 0x0040, 0x3782, 0xa686, 0x0020,
-	0x0078, 0x3784, 0xa686, 0x0028, 0x0040, 0x3791, 0x0078, 0x370c,
-	0x86ff, 0x00c0, 0x378f, 0x7120, 0x810b, 0x0078, 0x2bad, 0x702f,
-	0x0001, 0x711e, 0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xa7d2,
-	0x6007, 0x0000, 0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e,
-	0x6532, 0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x37a9,
-	0x007c, 0x702c, 0xa005, 0x00c0, 0x37bb, 0x711c, 0x7024, 0x20a0,
-	0x7728, 0x2031, 0x0000, 0x2061, 0xa7d2, 0x6224, 0x6328, 0x642c,
-	0x6530, 0x0078, 0x370c, 0x7120, 0x810b, 0x0078, 0x2bad, 0x2029,
-	0x007e, 0x7924, 0x7a28, 0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007,
-	0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa184,
-	0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb,
-	0xa284, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502,
-	0x0048, 0x2bdb, 0xa284, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb,
-	0xa502, 0x0048, 0x2bdb, 0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020,
-	0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa384, 0x00ff, 0xa0e2,
-	0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb, 0xa484, 0xff00,
-	0x8007, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048, 0x2bdb,
-	0xa484, 0x00ff, 0xa0e2, 0x0020, 0x0048, 0x2bdb, 0xa502, 0x0048,
-	0x2bdb, 0x2061, 0xa9a5, 0x6102, 0x6206, 0x630a, 0x640e, 0x0078,
-	0x2bad, 0x007e, 0x2001, 0xa753, 0x2004, 0xd0cc, 0x007f, 0x007c,
-	0x007e, 0x2001, 0xa772, 0x2004, 0xd0bc, 0x007f, 0x007c, 0x6164,
-	0x7a24, 0x6300, 0x82ff, 0x00c0, 0x3830, 0x7926, 0x0078, 0x2bad,
-	0x83ff, 0x00c0, 0x2bdb, 0x2001, 0xfff0, 0xa200, 0x00c8, 0x2bdb,
-	0x2019, 0xffff, 0x6068, 0xa302, 0xa200, 0x0048, 0x2bdb, 0x7926,
-	0x6266, 0x0078, 0x2bad, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003,
-	0x00c0, 0x2bd7, 0x7c28, 0x7d24, 0x7e38, 0x7f2c, 0x1078, 0x35ba,
-	0x0040, 0x2bd7, 0x2009, 0x0000, 0x2019, 0x0000, 0x7023, 0x0000,
-	0x702f, 0x0000, 0xad80, 0x0003, 0x7026, 0x20a0, 0xa1e0, 0xa835,
-	0x2c64, 0x8cff, 0x0040, 0x387d, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0006, 0x0040, 0x3872, 0x6004, 0xa084, 0xff00, 0xa086, 0x0600,
-	0x00c0, 0x387d, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007, 0xa105,
-	0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182, 0x00ff,
-	0x0040, 0x3888, 0xa386, 0x002a, 0x0040, 0x3891, 0x0078, 0x385e,
-	0x83ff, 0x00c0, 0x388f, 0x7120, 0x810c, 0x0078, 0x2bad, 0x702f,
-	0x0001, 0x711e, 0x7020, 0xa300, 0x7022, 0x2061, 0xa7d2, 0x6007,
-	0x0000, 0x6312, 0x7024, 0x600e, 0x6426, 0x652a, 0x662e, 0x6732,
-	0x2c10, 0x1078, 0x13db, 0x7007, 0x0002, 0x701b, 0x38a8, 0x007c,
-	0x702c, 0xa005, 0x00c0, 0x38b9, 0x711c, 0x7024, 0x20a0, 0x2019,
-	0x0000, 0x2061, 0xa7d2, 0x6424, 0x6528, 0x662c, 0x6730, 0x0078,
-	0x385e, 0x7120, 0x810c, 0x0078, 0x2bad, 0x81ff, 0x00c0, 0x2bd7,
-	0x60cc, 0xd09c, 0x0040, 0x2bd7, 0x1078, 0x35ba, 0x0040, 0x2bd7,
-	0x7924, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b,
-	0x38d2, 0x007c, 0x0d7e, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000,
-	0x0040, 0x38e5, 0xa0be, 0x7100, 0x0040, 0x38e5, 0xa0be, 0x7200,
-	0x0040, 0x38e5, 0x0d7f, 0x0078, 0x2bdb, 0x6820, 0x6924, 0x1078,
-	0x254d, 0x00c0, 0x3910, 0x1078, 0x455c, 0x00c0, 0x3910, 0x7122,
-	0x6612, 0x6516, 0x6e18, 0x0c7e, 0x1078, 0x35ba, 0x0040, 0x3910,
-	0x1078, 0x35ba, 0x0040, 0x3910, 0x0c7f, 0x0d7f, 0x6837, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x1078,
-	0x8e92, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3913, 0x007c,
-	0x0d7f, 0x0078, 0x2bd7, 0x7120, 0x1078, 0x298e, 0x6820, 0xa086,
-	0x8001, 0x0040, 0x2bd7, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002,
-	0x007e, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x1078, 0x4281, 0x007f,
-	0xade8, 0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xa7d2,
-	0x6007, 0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x00c0, 0x393a,
-	0x0078, 0x393e, 0xa7c6, 0x7100, 0x00c0, 0x3946, 0xa6c2, 0x0004,
-	0x0048, 0x2bdb, 0x2009, 0x0004, 0x0078, 0x3608, 0xa7c6, 0x7200,
-	0x00c0, 0x2bdb, 0xa6c2, 0x0054, 0x0048, 0x2bdb, 0x600e, 0x6013,
-	0x002a, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10, 0x1078, 0x13db,
-	0x7007, 0x0002, 0x701b, 0x395d, 0x007c, 0x701c, 0x2068, 0x6804,
-	0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x007e, 0x20a9, 0x002a,
-	0x2098, 0x20a0, 0x1078, 0x4281, 0x007f, 0x2009, 0x002a, 0x2061,
-	0xa7d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0078, 0x3608, 0x81ff,
-	0x00c0, 0x2bd7, 0x792c, 0x2001, 0xa99d, 0x2102, 0x1078, 0x35d2,
-	0x0040, 0x2bdb, 0x1078, 0x4673, 0x0040, 0x2bd7, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x47de, 0x127f, 0x0078, 0x2bad, 0x7824, 0xd08c,
-	0x00c0, 0x3995, 0xd084, 0x0040, 0x31da, 0x1078, 0x35e4, 0x0040,
-	0x2bdb, 0x0c7e, 0x1078, 0x35ba, 0x0c7f, 0x00c0, 0x39a3, 0x2009,
-	0x0002, 0x0078, 0x2bd7, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x0040, 0x39b0, 0xa08e, 0x0004, 0x0040, 0x39b0, 0xa08e, 0x0005,
-	0x00c0, 0x39dd, 0x7824, 0xd08c, 0x0040, 0x39bb, 0x6000, 0xc08c,
-	0x6002, 0x0078, 0x39c5, 0x2001, 0xa753, 0x2004, 0xd0b4, 0x0040,
-	0x320f, 0x6000, 0xd08c, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x1078, 0x8eae, 0x00c0, 0x39d2, 0x2009, 0x0003,
-	0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x39d7, 0x007c, 0x1078,
-	0x35e4, 0x0040, 0x2bdb, 0x0078, 0x320f, 0x2009, 0xa72f, 0x210c,
-	0x81ff, 0x0040, 0x39e7, 0x2009, 0x0001, 0x0078, 0x2bd7, 0x2001,
-	0xa700, 0x2004, 0xa086, 0x0003, 0x0040, 0x39f2, 0x2009, 0x0007,
-	0x0078, 0x2bd7, 0x2001, 0xa753, 0x2004, 0xd0ac, 0x0040, 0x39fc,
-	0x2009, 0x0008, 0x0078, 0x2bd7, 0x609c, 0xd0a4, 0x00c0, 0x3a03,
-	0xd0ac, 0x00c0, 0x320f, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x1078, 0x8f22, 0x00c0, 0x3a12, 0x2009, 0x0003,
-	0x0078, 0x2bd7, 0x7007, 0x0003, 0x701b, 0x3a17, 0x007c, 0x6830,
-	0xa086, 0x0100, 0x00c0, 0x3a20, 0x2009, 0x0004, 0x0078, 0x2bd7,
-	0x1078, 0x35e4, 0x0040, 0x2bdb, 0x0078, 0x39b2, 0x81ff, 0x2009,
-	0x0001, 0x00c0, 0x2bd7, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007,
-	0x00c0, 0x2bd7, 0x2001, 0xa753, 0x2004, 0xd0ac, 0x2009, 0x0008,
-	0x00c0, 0x2bd7, 0x1078, 0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e,
-	0x1078, 0x35ba, 0x0c7f, 0x2009, 0x0002, 0x0040, 0x2bd7, 0x6837,
-	0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194,
-	0xff00, 0xa18c, 0x00ff, 0xa006, 0x82ff, 0x00c0, 0x3a65, 0xc0ed,
-	0x6952, 0x792c, 0x6956, 0x0078, 0x3a6e, 0xa28e, 0x0100, 0x00c0,
-	0x2bdb, 0xc0e5, 0x6853, 0x0000, 0x6857, 0x0000, 0x683e, 0x1078,
-	0x90cd, 0x2009, 0x0003, 0x0040, 0x2bd7, 0x7007, 0x0003, 0x701b,
-	0x3a7a, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0040,
-	0x2bd7, 0x0078, 0x2bad, 0x81ff, 0x2009, 0x0001, 0x00c0, 0x2bd7,
-	0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x00c0, 0x2bd7, 0x1078,
-	0x35e4, 0x0040, 0x2bdb, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x2009, 0x0009, 0x00c0, 0x2bd7, 0x0c7e, 0x1078, 0x35ba, 0x0c7f,
-	0x2009, 0x0002, 0x0040, 0x2bd7, 0xad80, 0x000f, 0x2009, 0x0008,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x1078, 0x3604, 0x701b, 0x3ab1,
-	0x007c, 0x0d7e, 0xade8, 0x000f, 0x6800, 0xa086, 0x0500, 0x00c0,
-	0x3ac4, 0x6804, 0xa005, 0x00c0, 0x3ac4, 0x6808, 0xa084, 0xff00,
-	0x00c0, 0x3ac4, 0x0078, 0x3ac7, 0x0d7f, 0x00c0, 0x2bdb, 0x0d7f,
-	0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x0c7e,
-	0x1078, 0x35e4, 0x00c0, 0x3ad7, 0x0c7f, 0x0078, 0x2bdb, 0x1078,
-	0x9129, 0x2009, 0x0003, 0x0c7f, 0x0040, 0x2bd7, 0x7007, 0x0003,
-	0x701b, 0x3ae3, 0x007c, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004,
-	0x0040, 0x2bd7, 0x0078, 0x2bad, 0x127e, 0x0c7e, 0x0e7e, 0x2061,
-	0x0100, 0x2071, 0xa700, 0x6044, 0xd0a4, 0x00c0, 0x3b15, 0xd084,
-	0x0040, 0x3afe, 0x1078, 0x3c75, 0x0078, 0x3b11, 0xd08c, 0x0040,
-	0x3b05, 0x1078, 0x3b8c, 0x0078, 0x3b11, 0xd094, 0x0040, 0x3b0c,
-	0x1078, 0x3b60, 0x0078, 0x3b11, 0xd09c, 0x0040, 0x3b11, 0x1078,
-	0x3b1f, 0x0e7f, 0x0c7f, 0x127f, 0x007c, 0x017e, 0x6128, 0xd19c,
-	0x00c0, 0x3b1c, 0xc19d, 0x612a, 0x017f, 0x0078, 0x3b11, 0x624c,
-	0xa286, 0xf0f0, 0x00c0, 0x3b30, 0x6048, 0xa086, 0xf0f0, 0x0040,
-	0x3b30, 0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0078, 0x3b5f,
-	0xa294, 0xff00, 0xa296, 0xf700, 0x0040, 0x3b45, 0x7134, 0xd1a4,
-	0x00c0, 0x3b45, 0x6240, 0xa294, 0x0010, 0x0040, 0x3b45, 0x2009,
-	0x00f7, 0x1078, 0x42a1, 0x0078, 0x3b5f, 0x6043, 0x0040, 0x6043,
-	0x0000, 0x7077, 0x0000, 0x708f, 0x0001, 0x70b3, 0x0000, 0x70cf,
-	0x0000, 0x2009, 0xadc0, 0x200b, 0x0000, 0x7087, 0x0000, 0x707b,
-	0x000f, 0x2009, 0x000f, 0x2011, 0x41d5, 0x1078, 0x5add, 0x007c,
-	0x157e, 0x7078, 0xa005, 0x00c0, 0x3b8a, 0x2011, 0x41d5, 0x1078,
-	0x5a45, 0x6040, 0xa094, 0x0010, 0xa285, 0x0020, 0x6042, 0x20a9,
-	0x00c8, 0x6044, 0xd08c, 0x00c0, 0x3b83, 0x00f0, 0x3b71, 0x6242,
-	0x708b, 0x0000, 0x6040, 0xa094, 0x0010, 0xa285, 0x0080, 0x6042,
-	0x6242, 0x0078, 0x3b8a, 0x6242, 0x708b, 0x0000, 0x707f, 0x0000,
-	0x0078, 0x3b8a, 0x157f, 0x007c, 0x707c, 0xa08a, 0x0003, 0x00c8,
-	0x3b95, 0x1079, 0x3b98, 0x0078, 0x3b97, 0x1078, 0x1332, 0x007c,
-	0x3b9b, 0x3bea, 0x3c74, 0x0f7e, 0x707f, 0x0001, 0x20e1, 0xa000,
-	0x20e1, 0x8700, 0x1078, 0x21f7, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x2079, 0xac00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000,
-	0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000,
-	0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000,
-	0x782f, 0x0000, 0x2079, 0xac0c, 0x207b, 0x1101, 0x7807, 0x0000,
-	0x2099, 0xa705, 0x20a1, 0xac0e, 0x20a9, 0x0004, 0x53a3, 0x2079,
-	0xac12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xac00, 0x20a1,
-	0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000,
-	0x1078, 0x420b, 0x0f7f, 0x7083, 0x0000, 0x6043, 0x0008, 0x6043,
-	0x0000, 0x007c, 0x0d7e, 0x7080, 0x7083, 0x0000, 0xa025, 0x0040,
-	0x3c5e, 0x6020, 0xd0b4, 0x00c0, 0x3c5c, 0x718c, 0x81ff, 0x0040,
-	0x3c4b, 0xa486, 0x000c, 0x00c0, 0x3c56, 0xa480, 0x0018, 0x8004,
-	0x20a8, 0x2011, 0xac80, 0x2019, 0xac00, 0x220c, 0x2304, 0xa106,
-	0x00c0, 0x3c22, 0x8210, 0x8318, 0x00f0, 0x3c05, 0x6043, 0x0004,
-	0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x707f, 0x0002,
-	0x708b, 0x0002, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078, 0x5add,
-	0x0078, 0x3c5c, 0x2069, 0xac80, 0x6930, 0xa18e, 0x1101, 0x00c0,
-	0x3c56, 0x6834, 0xa005, 0x00c0, 0x3c56, 0x6900, 0xa18c, 0x00ff,
-	0x00c0, 0x3c36, 0x6804, 0xa005, 0x0040, 0x3c4b, 0x2011, 0xac8e,
-	0x2019, 0xa705, 0x20a9, 0x0004, 0x220c, 0x2304, 0xa102, 0x0048,
-	0x3c49, 0x00c0, 0x3c56, 0x8210, 0x8318, 0x00f0, 0x3c3c, 0x0078,
-	0x3c56, 0x708f, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
-	0xac80, 0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008,
-	0x6043, 0x0000, 0x0078, 0x3c5e, 0x0d7f, 0x007c, 0x6020, 0xd0b4,
-	0x00c0, 0x3c5c, 0x60c3, 0x000c, 0x2011, 0xa9bb, 0x2013, 0x0000,
-	0x7083, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575,
-	0x1078, 0x6e06, 0x0078, 0x3c5c, 0x007c, 0x7088, 0xa08a, 0x001d,
-	0x00c8, 0x3c7e, 0x1079, 0x3c81, 0x0078, 0x3c80, 0x1078, 0x1332,
-	0x007c, 0x3cab, 0x3cba, 0x3ce9, 0x3d02, 0x3d2e, 0x3d5a, 0x3d86,
-	0x3dbc, 0x3de8, 0x3e10, 0x3e53, 0x3e7d, 0x3e9f, 0x3eb5, 0x3edb,
-	0x3eee, 0x3ef7, 0x3f2b, 0x3f57, 0x3f83, 0x3faf, 0x3fe5, 0x4030,
-	0x405f, 0x4081, 0x40c3, 0x40e9, 0x4102, 0x4103, 0x0c7e, 0x2061,
-	0xa700, 0x6003, 0x0007, 0x2061, 0x0100, 0x6004, 0xa084, 0xfff9,
-	0x6006, 0x0c7f, 0x007c, 0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043,
-	0x0002, 0x708b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x41dc, 0x1078,
-	0x5add, 0x007c, 0x0f7e, 0x7080, 0xa086, 0x0014, 0x00c0, 0x3ce7,
-	0x6043, 0x0000, 0x6020, 0xd0b4, 0x00c0, 0x3ce7, 0x2079, 0xac80,
-	0x7a30, 0xa296, 0x1102, 0x00c0, 0x3ce5, 0x7834, 0xa005, 0x00c0,
-	0x3ce5, 0x7a38, 0xd2fc, 0x0040, 0x3cdb, 0x70b0, 0xa005, 0x00c0,
-	0x3cdb, 0x70b3, 0x0001, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x708b,
-	0x0010, 0x1078, 0x3ef7, 0x0078, 0x3ce7, 0x1078, 0x4224, 0x0f7f,
-	0x007c, 0x708b, 0x0003, 0x6043, 0x0004, 0x2011, 0x41dc, 0x1078,
-	0x5a45, 0x1078, 0x4289, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9,
-	0x000a, 0x20a3, 0x0000, 0x00f0, 0x3cf9, 0x60c3, 0x0014, 0x1078,
-	0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d2c, 0x2011,
-	0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d2a, 0x2079,
-	0xac80, 0x7a30, 0xa296, 0x1102, 0x00c0, 0x3d2a, 0x7834, 0xa005,
-	0x00c0, 0x3d2a, 0x7a38, 0xd2fc, 0x0040, 0x3d24, 0x70b0, 0xa005,
-	0x00c0, 0x3d24, 0x70b3, 0x0001, 0x708b, 0x0004, 0x1078, 0x3d2e,
-	0x0078, 0x3d2c, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0005,
-	0x1078, 0x4289, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011,
-	0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3d4c, 0x7074, 0xa005, 0x00c0,
-	0x3d4c, 0x7150, 0xa186, 0xffff, 0x0040, 0x3d4c, 0x1078, 0x419d,
-	0x0040, 0x3d4c, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298, 0x26a0,
-	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
-	0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3d84, 0x2011,
-	0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3d82, 0x2079,
-	0xac80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3d82, 0x7834, 0xa005,
-	0x00c0, 0x3d82, 0x7a38, 0xd2fc, 0x0040, 0x3d7c, 0x70b0, 0xa005,
-	0x00c0, 0x3d7c, 0x70b3, 0x0001, 0x708b, 0x0006, 0x1078, 0x3d86,
-	0x0078, 0x3d84, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b, 0x0007,
-	0x1078, 0x4289, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430, 0x2011,
-	0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3dae, 0x7074, 0xa005, 0x00c0,
-	0x3dae, 0x7154, 0xa186, 0xffff, 0x0040, 0x3dae, 0xa180, 0x29c0,
-	0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040, 0x3dae,
-	0x1078, 0x3820, 0x0040, 0x3dae, 0x1078, 0x256a, 0x20a9, 0x0008,
-	0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040,
-	0x3de6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0,
-	0x3de4, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3de4,
-	0x7834, 0xa005, 0x00c0, 0x3de4, 0x7a38, 0xd2fc, 0x0040, 0x3dde,
-	0x70b0, 0xa005, 0x00c0, 0x3dde, 0x70b3, 0x0001, 0x708b, 0x0008,
-	0x1078, 0x3de8, 0x0078, 0x3de6, 0x1078, 0x4224, 0x0f7f, 0x007c,
-	0x708b, 0x0009, 0x1078, 0x4289, 0x20a3, 0x1105, 0x20a3, 0x0100,
-	0x3430, 0x1078, 0x42d4, 0x00c0, 0x3e01, 0x7074, 0xa005, 0x00c0,
-	0x3e01, 0x1078, 0x4104, 0x00c0, 0x3e0b, 0xa085, 0x0001, 0x1078,
-	0x256a, 0x20a9, 0x0008, 0x2099, 0xac8e, 0x26a0, 0x53a6, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c,
-	0x0f7e, 0x7080, 0xa005, 0x0040, 0x3e51, 0x2011, 0x41dc, 0x1078,
-	0x5a45, 0xa086, 0x0014, 0x00c0, 0x3e4f, 0x2079, 0xac80, 0x7a30,
-	0xa296, 0x1105, 0x00c0, 0x3e4f, 0x7834, 0x2011, 0x0100, 0xa21e,
-	0x00c0, 0x3e3a, 0x7a38, 0xd2fc, 0x0040, 0x3e34, 0x70b0, 0xa005,
-	0x00c0, 0x3e34, 0x70b3, 0x0001, 0x708b, 0x000a, 0x1078, 0x3e53,
-	0x0078, 0x3e51, 0xa005, 0x00c0, 0x3e4f, 0x7a38, 0xd2fc, 0x0040,
-	0x3e47, 0x70b0, 0xa005, 0x00c0, 0x3e47, 0x70b3, 0x0001, 0x7087,
-	0x0000, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3e51, 0x1078,
-	0x4224, 0x0f7f, 0x007c, 0x708b, 0x000b, 0x2011, 0xac0e, 0x22a0,
-	0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002, 0x2009,
-	0x0000, 0x41a4, 0x1078, 0x4289, 0x20a3, 0x1106, 0x20a3, 0x0000,
-	0x1078, 0x42d4, 0x0040, 0x3e70, 0x2013, 0x0000, 0x0078, 0x3e74,
-	0x6030, 0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6,
-	0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005,
-	0x0040, 0x3e9d, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084,
-	0x00c0, 0x3e9b, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1106, 0x00c0,
-	0x3e9b, 0x7834, 0xa005, 0x00c0, 0x3e9b, 0x708b, 0x000c, 0x1078,
-	0x3e9f, 0x0078, 0x3e9d, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b,
-	0x000d, 0x1078, 0x4289, 0x20a3, 0x1107, 0x20a3, 0x0000, 0x2099,
-	0xac8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0084, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005,
-	0x0040, 0x3ed9, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084,
-	0x00c0, 0x3ed7, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1107, 0x00c0,
-	0x3ed7, 0x7834, 0xa005, 0x00c0, 0x3ed7, 0x7087, 0x0001, 0x1078,
-	0x427b, 0x708b, 0x000e, 0x1078, 0x3edb, 0x0078, 0x3ed9, 0x1078,
-	0x4224, 0x0f7f, 0x007c, 0x708b, 0x000f, 0x7083, 0x0000, 0x608b,
-	0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009,
-	0x07d0, 0x2011, 0x41dc, 0x1078, 0x5a38, 0x007c, 0x7080, 0xa005,
-	0x0040, 0x3ef6, 0x2011, 0x41dc, 0x1078, 0x5a45, 0x007c, 0x708b,
-	0x0011, 0x1078, 0x42d4, 0x00c0, 0x3f14, 0x716c, 0x81ff, 0x0040,
-	0x3f14, 0x2009, 0x0000, 0x7070, 0xa084, 0x00ff, 0x1078, 0x254d,
-	0xa186, 0x007e, 0x0040, 0x3f14, 0xa186, 0x0080, 0x0040, 0x3f14,
-	0x2011, 0xac8e, 0x1078, 0x419d, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x2099, 0xac80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080,
-	0x0007, 0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014,
-	0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3f55,
-	0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3f53,
-	0x2079, 0xac80, 0x7a30, 0xa296, 0x1103, 0x00c0, 0x3f53, 0x7834,
-	0xa005, 0x00c0, 0x3f53, 0x7a38, 0xd2fc, 0x0040, 0x3f4d, 0x70b0,
-	0xa005, 0x00c0, 0x3f4d, 0x70b3, 0x0001, 0x708b, 0x0012, 0x1078,
-	0x3f57, 0x0078, 0x3f55, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b,
-	0x0013, 0x1078, 0x4295, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430,
-	0x2011, 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3f75, 0x7074, 0xa005,
-	0x00c0, 0x3f75, 0x7150, 0xa186, 0xffff, 0x0040, 0x3f75, 0x1078,
-	0x419d, 0x0040, 0x3f75, 0x1078, 0x42b8, 0x20a9, 0x0008, 0x2298,
-	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
-	0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x3fad,
-	0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014, 0x00c0, 0x3fab,
-	0x2079, 0xac80, 0x7a30, 0xa296, 0x1104, 0x00c0, 0x3fab, 0x7834,
-	0xa005, 0x00c0, 0x3fab, 0x7a38, 0xd2fc, 0x0040, 0x3fa5, 0x70b0,
-	0xa005, 0x00c0, 0x3fa5, 0x70b3, 0x0001, 0x708b, 0x0014, 0x1078,
-	0x3faf, 0x0078, 0x3fad, 0x1078, 0x4224, 0x0f7f, 0x007c, 0x708b,
-	0x0015, 0x1078, 0x4295, 0x20a3, 0x1104, 0x20a3, 0x0000, 0x3430,
-	0x2011, 0xac8e, 0x1078, 0x42d4, 0x00c0, 0x3fd7, 0x7074, 0xa005,
-	0x00c0, 0x3fd7, 0x7154, 0xa186, 0xffff, 0x0040, 0x3fd7, 0xa180,
-	0x29c0, 0x200c, 0xa18c, 0xff00, 0x810f, 0x1078, 0x419d, 0x0040,
-	0x3fd7, 0x1078, 0x3820, 0x0040, 0x3fd7, 0x1078, 0x256a, 0x20a9,
-	0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005,
-	0x0040, 0x402e, 0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0014,
-	0x00c0, 0x402c, 0x2079, 0xac80, 0x7a30, 0xa296, 0x1105, 0x00c0,
-	0x402c, 0x7834, 0x2011, 0x0100, 0xa21e, 0x00c0, 0x400b, 0x7a38,
-	0xd2fc, 0x0040, 0x4009, 0x70b0, 0xa005, 0x00c0, 0x4009, 0x70b3,
-	0x0001, 0x0078, 0x401a, 0xa005, 0x00c0, 0x402c, 0x7a38, 0xd2fc,
-	0x0040, 0x4018, 0x70b0, 0xa005, 0x00c0, 0x4018, 0x70b3, 0x0001,
-	0x7087, 0x0000, 0x7a38, 0xd2f4, 0x0040, 0x4026, 0x2001, 0xa774,
-	0x2004, 0xd0a4, 0x00c0, 0x4026, 0x70cf, 0x0008, 0x708b, 0x0016,
-	0x1078, 0x4030, 0x0078, 0x402e, 0x1078, 0x4224, 0x0f7f, 0x007c,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xac80, 0x20a1, 0x020b,
-	0x20a9, 0x000e, 0x53a6, 0x3430, 0x2011, 0xac8e, 0x708b, 0x0017,
-	0x1078, 0x42d4, 0x00c0, 0x4050, 0x7074, 0xa005, 0x00c0, 0x4050,
-	0x1078, 0x4104, 0x00c0, 0x405a, 0xa085, 0x0001, 0x1078, 0x256a,
-	0x20a9, 0x0008, 0x2099, 0xac8e, 0x26a0, 0x53a6, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078, 0x420b, 0x007c, 0x0f7e,
-	0x7080, 0xa005, 0x0040, 0x407f, 0x2011, 0x41dc, 0x1078, 0x5a45,
-	0xa086, 0x0084, 0x00c0, 0x407d, 0x2079, 0xac80, 0x7a30, 0xa296,
-	0x1106, 0x00c0, 0x407d, 0x7834, 0xa005, 0x00c0, 0x407d, 0x708b,
-	0x0018, 0x1078, 0x4081, 0x0078, 0x407f, 0x1078, 0x4224, 0x0f7f,
-	0x007c, 0x708b, 0x0019, 0x1078, 0x4295, 0x20a3, 0x1106, 0x20a3,
-	0x0000, 0x3430, 0x2099, 0xac8e, 0x2039, 0xac0e, 0x27a0, 0x20a9,
-	0x0040, 0x53a3, 0x1078, 0x42d4, 0x00c0, 0x40b5, 0x2728, 0x2514,
-	0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007,
-	0xa205, 0x202a, 0x6030, 0x2310, 0x8214, 0xa2a0, 0xac0e, 0x2414,
-	0xa38c, 0x0001, 0x0040, 0x40b0, 0xa294, 0xff00, 0x0078, 0x40b3,
-	0xa294, 0x00ff, 0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9,
-	0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084,
-	0x1078, 0x420b, 0x007c, 0x0f7e, 0x7080, 0xa005, 0x0040, 0x40e7,
-	0x2011, 0x41dc, 0x1078, 0x5a45, 0xa086, 0x0084, 0x00c0, 0x40e5,
-	0x2079, 0xac80, 0x7a30, 0xa296, 0x1107, 0x00c0, 0x40e5, 0x7834,
-	0xa005, 0x00c0, 0x40e5, 0x7087, 0x0001, 0x1078, 0x427b, 0x708b,
-	0x001a, 0x1078, 0x40e9, 0x0078, 0x40e7, 0x1078, 0x4224, 0x0f7f,
-	0x007c, 0x708b, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
-	0xac80, 0x20a1, 0x020b, 0x7480, 0xa480, 0x0018, 0xa080, 0x0007,
-	0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x1078,
-	0x420b, 0x007c, 0x007c, 0x007c, 0x087e, 0x097e, 0x2029, 0xa753,
-	0x252c, 0x20a9, 0x0008, 0x2041, 0xac0e, 0x28a0, 0x2099, 0xac8e,
-	0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0040, 0x411a,
-	0x2011, 0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x00c0,
-	0x412c, 0xd5d4, 0x0040, 0x4127, 0x8210, 0x0078, 0x4128, 0x8211,
-	0x00f0, 0x411a, 0x0078, 0x4194, 0x82ff, 0x00c0, 0x413e, 0xd5d4,
-	0x0040, 0x4138, 0xa1a6, 0x3fff, 0x0040, 0x4124, 0x0078, 0x413c,
-	0xa1a6, 0x3fff, 0x0040, 0x4194, 0xa18d, 0xc000, 0x20a9, 0x0010,
-	0x2019, 0x0001, 0xd5d4, 0x0040, 0x4147, 0x2019, 0x0010, 0x2120,
-	0xd5d4, 0x0040, 0x414e, 0x8423, 0x0078, 0x414f, 0x8424, 0x00c8,
-	0x415c, 0xd5d4, 0x0040, 0x4157, 0x8319, 0x0078, 0x4158, 0x8318,
-	0x00f0, 0x4148, 0x0078, 0x4194, 0x23a8, 0x2021, 0x0001, 0x8426,
-	0x8425, 0x00f0, 0x4160, 0x2328, 0x8529, 0xa2be, 0x0007, 0x0040,
-	0x4174, 0x007e, 0x2039, 0x0007, 0x2200, 0xa73a, 0x007f, 0x27a8,
-	0xa5a8, 0x0010, 0x00f0, 0x4170, 0x7552, 0xa5c8, 0x29c0, 0x292c,
-	0xa5ac, 0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000,
-	0x7572, 0x2018, 0x2304, 0xa405, 0x201a, 0x7077, 0x0001, 0x26a0,
-	0x2898, 0x20a9, 0x0008, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0xa085, 0x0001, 0x0078, 0x419a, 0xa006, 0x0078, 0x419a, 0xa006,
-	0x1078, 0x1332, 0x097f, 0x087f, 0x007c, 0x2118, 0x2021, 0x0000,
-	0x2001, 0x0007, 0xa39a, 0x0010, 0x0048, 0x41aa, 0x8420, 0x8001,
-	0x0078, 0x41a2, 0x2118, 0x84ff, 0x0040, 0x41b3, 0xa39a, 0x0010,
-	0x8421, 0x00c0, 0x41ae, 0x2021, 0x0001, 0x83ff, 0x0040, 0x41bc,
-	0x8423, 0x8319, 0x00c0, 0x41b8, 0xa238, 0x2704, 0xa42c, 0x00c0,
-	0x41d4, 0xa405, 0x203a, 0x7152, 0xa1a0, 0x29c0, 0x242c, 0xa5ac,
-	0x00ff, 0x6532, 0x60e7, 0x0000, 0x65ea, 0x706f, 0x0000, 0x7572,
-	0x7077, 0x0001, 0xa084, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa700,
-	0x707b, 0x0000, 0x0e7f, 0x007c, 0x0e7e, 0x0f7e, 0x2001, 0x0002,
-	0x1078, 0x5ae6, 0x2079, 0x0100, 0x2071, 0x0140, 0x1078, 0x6e0f,
-	0x7004, 0xa084, 0x4000, 0x0040, 0x41f1, 0x7003, 0x1000, 0x7003,
-	0x0000, 0x127e, 0x2091, 0x8000, 0x2071, 0xa722, 0x2073, 0x0000,
-	0x7840, 0x027e, 0x017e, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x017f,
-	0xa094, 0x0010, 0xa285, 0x0080, 0x7842, 0x7a42, 0x027f, 0x127f,
-	0x0f7f, 0x0e7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x2011, 0xa9bb,
-	0x2013, 0x0000, 0x7083, 0x0000, 0x127f, 0x20e1, 0x9080, 0x60a3,
-	0x0056, 0x60a7, 0x9575, 0x1078, 0x6e06, 0x2009, 0x07d0, 0x2011,
-	0x41dc, 0x1078, 0x5add, 0x007c, 0x017e, 0x027e, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x2011, 0x0003, 0x1078, 0x70e0, 0x2011, 0x0002,
-	0x1078, 0x70ea, 0x1078, 0x6fc4, 0x037e, 0x2019, 0x0000, 0x1078,
-	0x7058, 0x037f, 0x2009, 0x00f7, 0x1078, 0x42a1, 0x2061, 0xa9c4,
-	0x601b, 0x0000, 0x601f, 0x0000, 0x2061, 0xa700, 0x6003, 0x0001,
-	0x2061, 0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x002d,
-	0x2011, 0x4259, 0x1078, 0x5a38, 0x127f, 0x0c7f, 0x027f, 0x017f,
-	0x007c, 0x0e7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2001, 0x0001,
-	0x1078, 0x5ae6, 0x2071, 0x0100, 0x1078, 0x6e0f, 0x2071, 0x0140,
-	0x7004, 0xa084, 0x4000, 0x0040, 0x4271, 0x7003, 0x1000, 0x7003,
-	0x0000, 0x2001, 0x0001, 0x1078, 0x24e8, 0x1078, 0x4224, 0x127f,
-	0x007f, 0x0e7f, 0x007c, 0x20a9, 0x0040, 0x20a1, 0xadc0, 0x2099,
-	0xac8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x00f0, 0x4281,
-	0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xac00, 0x20a1,
-	0x020b, 0x20a9, 0x000c, 0x53a6, 0x007c, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x2099, 0xac80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6,
-	0x007c, 0x0c7e, 0x007e, 0x2061, 0x0100, 0x810f, 0x2001, 0xa72f,
-	0x2004, 0xa005, 0x00c0, 0x42b2, 0x6030, 0xa084, 0x00ff, 0xa105,
-	0x0078, 0x42b4, 0xa185, 0x00f7, 0x604a, 0x007f, 0x0c7f, 0x007c,
-	0x017e, 0x047e, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x42cb,
-	0xa006, 0x2020, 0x2009, 0x002a, 0x1078, 0xa22d, 0x2001, 0xa70c,
-	0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x1078,
-	0x284f, 0x047f, 0x017f, 0x007c, 0x007e, 0x2001, 0xa70c, 0x2004,
-	0xd09c, 0x0040, 0x42db, 0x007f, 0x007c, 0x007e, 0x017e, 0x127e,
-	0x2091, 0x8000, 0x2001, 0x0101, 0x200c, 0xa18d, 0x0006, 0x2102,
-	0x127f, 0x017f, 0x007f, 0x007c, 0x157e, 0x20a9, 0x00ff, 0x2009,
-	0xa835, 0xa006, 0x200a, 0x8108, 0x00f0, 0x42f2, 0x157f, 0x007c,
-	0x0d7e, 0x037e, 0x157e, 0x137e, 0x147e, 0x2069, 0xa752, 0xa006,
-	0x6002, 0x6007, 0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x29c0,
-	0x231c, 0xa39c, 0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006,
-	0x23a0, 0x40a4, 0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4,
-	0x603e, 0x6042, 0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062,
-	0x6066, 0x606a, 0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082,
-	0x6086, 0x608a, 0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae,
-	0x61a2, 0x0d7e, 0x60a4, 0xa06d, 0x0040, 0x4338, 0x1078, 0x13a4,
-	0x60a7, 0x0000, 0x60a8, 0xa06d, 0x0040, 0x4340, 0x1078, 0x13a4,
-	0x60ab, 0x0000, 0x0d7f, 0xa006, 0x604a, 0x6810, 0x603a, 0x680c,
-	0x6046, 0x6814, 0xa084, 0x00ff, 0x6042, 0x147f, 0x137f, 0x157f,
-	0x037f, 0x0d7f, 0x007c, 0x127e, 0x2091, 0x8000, 0x6944, 0x6e48,
-	0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8, 0x4424, 0xa18c, 0xff00,
-	0x810f, 0xa182, 0x00ff, 0x00c8, 0x442a, 0x2001, 0xa70c, 0x2004,
-	0xa084, 0x0003, 0x0040, 0x4385, 0x2001, 0xa70c, 0x2004, 0xd084,
-	0x00c0, 0x4405, 0xa188, 0xa835, 0x2104, 0xa065, 0x0040, 0x4405,
-	0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x00c0, 0x4405, 0x6000,
-	0xd0c4, 0x0040, 0x4405, 0x0078, 0x4392, 0xa188, 0xa835, 0x2104,
-	0xa065, 0x0040, 0x43e9, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006,
-	0x00c0, 0x43ef, 0x60a4, 0xa00d, 0x0040, 0x439a, 0x1078, 0x4817,
-	0x0040, 0x43e3, 0x60a8, 0xa00d, 0x0040, 0x43b4, 0x1078, 0x486a,
-	0x00c0, 0x43b4, 0x694c, 0xd1fc, 0x00c0, 0x43aa, 0x1078, 0x44df,
-	0x0078, 0x43de, 0x1078, 0x4484, 0x694c, 0xd1ec, 0x00c0, 0x43de,
-	0x1078, 0x46d6, 0x0078, 0x43de, 0x694c, 0xa184, 0xa000, 0x0040,
-	0x43ce, 0xd1ec, 0x0040, 0x43c7, 0xd1fc, 0x0040, 0x43c3, 0x1078,
-	0x46e7, 0x0078, 0x43ca, 0x1078, 0x46e7, 0x0078, 0x43ce, 0xd1fc,
-	0x0040, 0x43ce, 0x1078, 0x4484, 0x0078, 0x43de, 0x6050, 0xa00d,
-	0x0040, 0x43d9, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052, 0x0078,
-	0x43de, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x1078, 0x5da9,
-	0xa006, 0x127f, 0x007c, 0x2001, 0x0005, 0x2009, 0x0000, 0x0078,
-	0x442e, 0x2001, 0x0028, 0x2009, 0x0000, 0x0078, 0x442e, 0xa082,
-	0x0006, 0x00c8, 0x4405, 0x60a0, 0xd0bc, 0x00c0, 0x4401, 0x6100,
-	0xd1fc, 0x0040, 0x4392, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078,
-	0x442e, 0x2001, 0x0028, 0x0078, 0x4420, 0x2009, 0xa70c, 0x210c,
-	0xd18c, 0x0040, 0x440f, 0x2001, 0x0004, 0x0078, 0x4420, 0xd184,
-	0x0040, 0x4416, 0x2001, 0x0004, 0x0078, 0x4420, 0x2001, 0x0029,
-	0x6100, 0xd1fc, 0x0040, 0x4420, 0x2009, 0x1000, 0x0078, 0x442e,
-	0x2009, 0x0000, 0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000,
-	0x0078, 0x442e, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x127f,
-	0x007c, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000, 0x00c8,
-	0x447e, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x00c8, 0x4464,
-	0xa188, 0xa835, 0x2104, 0xa065, 0x0040, 0x4464, 0x6004, 0xa084,
-	0x00ff, 0xa08e, 0x0006, 0x00c0, 0x446a, 0x684c, 0xd0ec, 0x0040,
-	0x4457, 0x1078, 0x46e7, 0x1078, 0x4484, 0x0078, 0x445f, 0x1078,
-	0x4484, 0x684c, 0xd0fc, 0x0040, 0x445f, 0x1078, 0x46d6, 0x1078,
-	0x472f, 0xa006, 0x0078, 0x4482, 0x2001, 0x0028, 0x2009, 0x0000,
-	0x0078, 0x4482, 0xa082, 0x0006, 0x00c8, 0x4478, 0x6100, 0xd1fc,
-	0x0040, 0x444d, 0x2001, 0x0029, 0x2009, 0x1000, 0x0078, 0x4482,
-	0x2001, 0x0029, 0x2009, 0x0000, 0x0078, 0x4482, 0x2001, 0x0029,
-	0x2009, 0x0000, 0xa005, 0x007c, 0x127e, 0x2091, 0x8000, 0x6050,
-	0xa00d, 0x0040, 0x4492, 0x2d00, 0x200a, 0x6803, 0x0000, 0x6052,
-	0x127f, 0x007c, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x0078,
-	0x4490, 0x127e, 0x2091, 0x8000, 0x604c, 0xa005, 0x0040, 0x44af,
-	0x0e7e, 0x2071, 0xa9b1, 0x7004, 0xa086, 0x0002, 0x0040, 0x44b6,
-	0x0e7f, 0x604c, 0x6802, 0x2d00, 0x604e, 0x127f, 0x007c, 0x2d00,
-	0x6052, 0x604e, 0x6803, 0x0000, 0x0078, 0x44ad, 0x701c, 0xac06,
-	0x00c0, 0x44a8, 0x604c, 0x2070, 0x7000, 0x6802, 0x2d00, 0x7002,
-	0x0e7f, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x604c, 0xa06d,
-	0x0040, 0x44d1, 0x6800, 0xa005, 0x00c0, 0x44cf, 0x6052, 0x604e,
-	0xad05, 0x127f, 0x007c, 0x604c, 0xa06d, 0x0040, 0x44de, 0x6800,
-	0xa005, 0x00c0, 0x44dc, 0x6052, 0x604e, 0xad05, 0x007c, 0x6803,
-	0x0000, 0x6084, 0xa00d, 0x0040, 0x44e9, 0x2d00, 0x200a, 0x6086,
-	0x007c, 0x2d00, 0x6086, 0x6082, 0x0078, 0x44e8, 0x127e, 0x0c7e,
-	0x027e, 0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0040,
-	0x44fc, 0xc285, 0x0078, 0x44fd, 0xc284, 0x6202, 0x027f, 0x0c7f,
-	0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091, 0x8000, 0x6218, 0x2260,
-	0x6204, 0x007e, 0xa086, 0x0006, 0x00c0, 0x4521, 0x609c, 0xd0ac,
-	0x0040, 0x4521, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x4521,
-	0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x00c0, 0x4521, 0x2011,
-	0x0600, 0x007f, 0xa294, 0xff00, 0xa215, 0x6206, 0x007e, 0xa086,
-	0x0006, 0x00c0, 0x4531, 0x6290, 0x82ff, 0x00c0, 0x4531, 0x1078,
-	0x1332, 0x007f, 0x0c7f, 0x127f, 0x007c, 0x127e, 0x0c7e, 0x2091,
-	0x8000, 0x6218, 0x2260, 0x6204, 0x007e, 0xa086, 0x0006, 0x00c0,
-	0x4553, 0x609c, 0xd0a4, 0x0040, 0x4553, 0x2001, 0xa753, 0x2004,
-	0xd0ac, 0x00c0, 0x4553, 0xa284, 0x00ff, 0xa086, 0x0007, 0x00c0,
-	0x4553, 0x2011, 0x0006, 0x007f, 0xa294, 0x00ff, 0x8007, 0xa215,
-	0x6206, 0x0c7f, 0x127f, 0x007c, 0x027e, 0xa182, 0x00ff, 0x0048,
-	0x4565, 0xa085, 0x0001, 0x0078, 0x457d, 0xa190, 0xa835, 0x2204,
-	0xa065, 0x00c0, 0x457c, 0x017e, 0x0d7e, 0x1078, 0x1370, 0x2d60,
-	0x0d7f, 0x017f, 0x0040, 0x4561, 0x2c00, 0x2012, 0x60a7, 0x0000,
-	0x60ab, 0x0000, 0x1078, 0x42f8, 0xa006, 0x027f, 0x007c, 0x127e,
-	0x2091, 0x8000, 0x027e, 0xa182, 0x00ff, 0x0048, 0x458b, 0xa085,
-	0x0001, 0x0078, 0x45c1, 0x0d7e, 0xa190, 0xa835, 0x2204, 0xa06d,
-	0x0040, 0x45bf, 0x2013, 0x0000, 0x0d7e, 0x0c7e, 0x2d60, 0x60a4,
-	0xa06d, 0x0040, 0x459d, 0x1078, 0x13a4, 0x60a8, 0xa06d, 0x0040,
-	0x45a3, 0x1078, 0x13a4, 0x0c7f, 0x0d7f, 0x0d7e, 0x0c7e, 0x68ac,
-	0x2060, 0x8cff, 0x0040, 0x45bb, 0x600c, 0x007e, 0x6010, 0x2068,
-	0x1078, 0x8d16, 0x0040, 0x45b6, 0x1078, 0x13b4, 0x1078, 0x772d,
-	0x0c7f, 0x0078, 0x45a9, 0x0c7f, 0x0d7f, 0x1078, 0x13a4, 0x0d7f,
-	0xa006, 0x027f, 0x127f, 0x007c, 0x017e, 0xa182, 0x00ff, 0x0048,
-	0x45cd, 0xa085, 0x0001, 0x0078, 0x45d4, 0xa188, 0xa835, 0x2104,
-	0xa065, 0x0040, 0x45c9, 0xa006, 0x017f, 0x007c, 0x0d7e, 0x157e,
-	0x137e, 0x147e, 0x600b, 0x0000, 0x600f, 0x0000, 0x6000, 0xc08c,
-	0x6002, 0x2069, 0xac8e, 0x6808, 0x605e, 0x6810, 0x6062, 0x6138,
-	0xa10a, 0x0048, 0x45ec, 0x603a, 0x6814, 0x6066, 0x2099, 0xac96,
-	0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099, 0xac9a,
-	0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069, 0xacae,
-	0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818, 0x6076,
-	0x60a0, 0xa086, 0x007e, 0x00c0, 0x4611, 0x2069, 0xac8e, 0x690c,
-	0x616e, 0xa182, 0x0211, 0x00c8, 0x4619, 0x2009, 0x0008, 0x0078,
-	0x4643, 0xa182, 0x0259, 0x00c8, 0x4621, 0x2009, 0x0007, 0x0078,
-	0x4643, 0xa182, 0x02c1, 0x00c8, 0x4629, 0x2009, 0x0006, 0x0078,
-	0x4643, 0xa182, 0x0349, 0x00c8, 0x4631, 0x2009, 0x0005, 0x0078,
-	0x4643, 0xa182, 0x0421, 0x00c8, 0x4639, 0x2009, 0x0004, 0x0078,
-	0x4643, 0xa182, 0x0581, 0x00c8, 0x4641, 0x2009, 0x0003, 0x0078,
-	0x4643, 0x2009, 0x0002, 0x6192, 0x147f, 0x137f, 0x157f, 0x0d7f,
-	0x007c, 0x017e, 0x027e, 0x0e7e, 0x2071, 0xac8d, 0x2e04, 0x6896,
-	0x2071, 0xac8e, 0x7004, 0x689a, 0x701c, 0x689e, 0x6a00, 0x2009,
-	0xa772, 0x210c, 0xd0bc, 0x0040, 0x4663, 0xd1ec, 0x0040, 0x4663,
-	0xc2ad, 0x0078, 0x4664, 0xc2ac, 0xd0c4, 0x0040, 0x466d, 0xd1e4,
-	0x0040, 0x466d, 0xc2bd, 0x0078, 0x466e, 0xc2bc, 0x6a02, 0x0e7f,
-	0x027f, 0x017f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4,
-	0xa06d, 0x0040, 0x4697, 0x6900, 0x81ff, 0x00c0, 0x46ab, 0x6a04,
-	0xa282, 0x0010, 0x00c8, 0x46b0, 0xad88, 0x0004, 0x20a9, 0x0010,
-	0x2104, 0xa086, 0xffff, 0x0040, 0x4692, 0x8108, 0x00f0, 0x4688,
-	0x1078, 0x1332, 0x260a, 0x8210, 0x6a06, 0x0078, 0x46ab, 0x1078,
-	0x138b, 0x0040, 0x46b0, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88,
-	0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x00f0, 0x46a3,
-	0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c,
-	0xa006, 0x0078, 0x46ad, 0x127e, 0x2091, 0x8000, 0x0d7e, 0x60a4,
-	0xa00d, 0x0040, 0x46d3, 0x2168, 0x6800, 0xa005, 0x00c0, 0x46cf,
-	0x1078, 0x4817, 0x00c0, 0x46d3, 0x200b, 0xffff, 0x6804, 0xa08a,
-	0x0002, 0x0048, 0x46cf, 0x8001, 0x6806, 0x0078, 0x46d3, 0x1078,
-	0x13a4, 0x60a7, 0x0000, 0x0d7f, 0x127f, 0x007c, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x487f, 0x0078, 0x46df, 0x1078, 0x4484, 0x1078,
-	0x4775, 0x00c0, 0x46dd, 0x1078, 0x472f, 0x127f, 0x007c, 0x0d7e,
-	0x127e, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x0040, 0x470b, 0x6950,
-	0x81ff, 0x00c0, 0x471f, 0x6a54, 0xa282, 0x0010, 0x00c8, 0x472c,
-	0xad88, 0x0018, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0040,
-	0x4706, 0x8108, 0x00f0, 0x46fc, 0x1078, 0x1332, 0x260a, 0x8210,
-	0x6a56, 0x0078, 0x471f, 0x1078, 0x138b, 0x0040, 0x472c, 0x2d00,
-	0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9, 0x0010, 0x200b,
-	0xffff, 0x8108, 0x00f0, 0x4717, 0x6857, 0x0001, 0x6e62, 0x0078,
-	0x4723, 0x1078, 0x44df, 0x1078, 0x4739, 0x00c0, 0x4721, 0xa085,
-	0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x4729, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x5da9, 0x127f, 0x007c, 0xa01e, 0x0078,
-	0x473b, 0x2019, 0x0001, 0xa00e, 0x127e, 0x2091, 0x8000, 0x604c,
-	0x2068, 0x6000, 0xd0dc, 0x00c0, 0x4759, 0x8dff, 0x0040, 0x4770,
-	0x83ff, 0x0040, 0x4751, 0x6848, 0xa606, 0x0040, 0x475e, 0x0078,
-	0x4759, 0x683c, 0xa406, 0x00c0, 0x4759, 0x6840, 0xa506, 0x0040,
-	0x475e, 0x2d08, 0x6800, 0x2068, 0x0078, 0x4745, 0x1078, 0x7233,
-	0x6a00, 0x604c, 0xad06, 0x00c0, 0x4768, 0x624e, 0x0078, 0x476b,
-	0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0, 0x4770, 0x6152, 0x8dff,
-	0x127f, 0x007c, 0xa01e, 0x0078, 0x4777, 0x2019, 0x0001, 0xa00e,
-	0x6080, 0x2068, 0x8dff, 0x0040, 0x47a3, 0x83ff, 0x0040, 0x4786,
-	0x6848, 0xa606, 0x0040, 0x4793, 0x0078, 0x478e, 0x683c, 0xa406,
-	0x00c0, 0x478e, 0x6840, 0xa506, 0x0040, 0x4793, 0x2d08, 0x6800,
-	0x2068, 0x0078, 0x477a, 0x6a00, 0x6080, 0xad06, 0x00c0, 0x479b,
-	0x6282, 0x0078, 0x479e, 0xa180, 0x0000, 0x2202, 0x82ff, 0x00c0,
-	0x47a3, 0x6186, 0x8dff, 0x007c, 0xa016, 0x1078, 0x4810, 0x00c0,
-	0x47ab, 0x2011, 0x0001, 0x1078, 0x4863, 0x00c0, 0x47b1, 0xa295,
-	0x0002, 0x007c, 0x1078, 0x489b, 0x0040, 0x47ba, 0x1078, 0x8dda,
-	0x0078, 0x47bc, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040,
-	0x47c5, 0x1078, 0x8d72, 0x0078, 0x47c7, 0xa085, 0x0001, 0x007c,
-	0x1078, 0x489b, 0x0040, 0x47d0, 0x1078, 0x8dbc, 0x0078, 0x47d2,
-	0xa085, 0x0001, 0x007c, 0x1078, 0x489b, 0x0040, 0x47db, 0x1078,
-	0x8d8e, 0x0078, 0x47dd, 0xa085, 0x0001, 0x007c, 0x1078, 0x489b,
-	0x0040, 0x47e6, 0x1078, 0x8df8, 0x0078, 0x47e8, 0xa085, 0x0001,
-	0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x8000, 0x6080, 0xa06d,
-	0x0040, 0x4808, 0x6800, 0x007e, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x8f8d, 0x007e, 0x6000, 0xd0fc, 0x0040, 0x4802,
-	0x1078, 0xa4fd, 0x007f, 0x1078, 0x4a73, 0x007f, 0x0078, 0x47ef,
-	0x6083, 0x0000, 0x6087, 0x0000, 0x0d7f, 0x007f, 0x127f, 0x007c,
-	0x60a4, 0xa00d, 0x00c0, 0x4817, 0xa085, 0x0001, 0x007c, 0x0e7e,
-	0x2170, 0x7000, 0xa005, 0x00c0, 0x482c, 0x20a9, 0x0010, 0xae88,
-	0x0004, 0x2104, 0xa606, 0x0040, 0x482c, 0x8108, 0x00f0, 0x4821,
-	0xa085, 0x0001, 0x0078, 0x482d, 0xa006, 0x0e7f, 0x007c, 0x0d7e,
-	0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x00c0, 0x483d, 0x1078,
-	0x138b, 0x0040, 0x484f, 0x2d00, 0x60a6, 0x6803, 0x0001, 0x6807,
-	0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108,
-	0x00f0, 0x4845, 0xa085, 0x0001, 0x127f, 0x0d7f, 0x007c, 0xa006,
-	0x0078, 0x484c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x60a4, 0xa06d,
-	0x0040, 0x4860, 0x60a7, 0x0000, 0x1078, 0x13a4, 0xa085, 0x0001,
-	0x127f, 0x0d7f, 0x007c, 0x60a8, 0xa00d, 0x00c0, 0x486a, 0xa085,
-	0x0001, 0x007c, 0x0e7e, 0x2170, 0x7050, 0xa005, 0x00c0, 0x487d,
-	0x20a9, 0x0010, 0xae88, 0x0018, 0x2104, 0xa606, 0x0040, 0x487d,
-	0x8108, 0x00f0, 0x4874, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x127e,
-	0x2091, 0x8000, 0x1078, 0x4863, 0x00c0, 0x4899, 0x200b, 0xffff,
-	0x0d7e, 0x60a8, 0x2068, 0x6854, 0xa08a, 0x0002, 0x0048, 0x4894,
-	0x8001, 0x6856, 0x0078, 0x4898, 0x1078, 0x13a4, 0x60ab, 0x0000,
-	0x0d7f, 0x127f, 0x007c, 0x609c, 0xd0a4, 0x007c, 0x0f7e, 0x71b0,
-	0x81ff, 0x00c0, 0x48b9, 0x71cc, 0xd19c, 0x0040, 0x48b9, 0x2001,
-	0x007e, 0xa080, 0xa835, 0x2004, 0xa07d, 0x0040, 0x48b9, 0x7804,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x48b9, 0x7800, 0xc0ed,
-	0x7802, 0x2079, 0xa752, 0x7804, 0xd0a4, 0x0040, 0x48df, 0x157e,
-	0x0c7e, 0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4,
-	0x00c0, 0x48d9, 0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004,
-	0x0040, 0x48d6, 0xa086, 0x0006, 0x00c0, 0x48d9, 0x6000, 0xc0ed,
-	0x6002, 0x017f, 0x8108, 0x00f0, 0x48c5, 0x0c7f, 0x157f, 0x1078,
-	0x4967, 0x0040, 0x48e8, 0x2001, 0xa9a1, 0x200c, 0x0078, 0x48f0,
-	0x2079, 0xa752, 0x7804, 0xd0a4, 0x0040, 0x48f4, 0x2009, 0x07d0,
-	0x2011, 0x48f6, 0x1078, 0x5add, 0x0f7f, 0x007c, 0x2011, 0x48f6,
-	0x1078, 0x5a45, 0x1078, 0x4967, 0x0040, 0x491e, 0x2001, 0xa8b3,
-	0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xa753,
-	0x2004, 0xd0a4, 0x0040, 0x4912, 0x2009, 0x07d0, 0x2011, 0x48f6,
-	0x1078, 0x5add, 0x0e7e, 0x2071, 0xa700, 0x706f, 0x0000, 0x7073,
-	0x0000, 0x1078, 0x2677, 0x0e7f, 0x0078, 0x4956, 0x157e, 0x0c7e,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x017e, 0x1078, 0x45c4, 0x00c0,
-	0x4950, 0x6000, 0xd0ec, 0x0040, 0x4950, 0x047e, 0x62a0, 0xa294,
-	0x00ff, 0x8227, 0xa006, 0x2009, 0x0029, 0x1078, 0xa22d, 0x6000,
-	0xc0e5, 0xc0ec, 0x6002, 0x6004, 0xa084, 0x00ff, 0xa085, 0x0700,
-	0x6006, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e, 0x2039, 0x0000,
-	0x1078, 0x5e0a, 0x2009, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x047f,
-	0x017f, 0x8108, 0x00f0, 0x4924, 0x0c7f, 0x157f, 0x007c, 0x0c7e,
-	0x6018, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x0c7f, 0x007c, 0x7818,
-	0x2004, 0xd0ac, 0x007c, 0x7818, 0x2004, 0xd0bc, 0x007c, 0x0f7e,
-	0x2001, 0xa8b3, 0x2004, 0xa07d, 0x0040, 0x4970, 0x7800, 0xd0ec,
-	0x0f7f, 0x007c, 0x127e, 0x027e, 0x2091, 0x8000, 0x007e, 0x62a0,
-	0xa290, 0xa835, 0x2204, 0xac06, 0x10c0, 0x1332, 0x007f, 0x6200,
-	0xa005, 0x0040, 0x4986, 0xc2fd, 0x0078, 0x4987, 0xc2fc, 0x6202,
-	0x027f, 0x127f, 0x007c, 0x2011, 0xa733, 0x2204, 0xd0cc, 0x0040,
-	0x4998, 0x2001, 0xa99f, 0x200c, 0x2011, 0x4999, 0x1078, 0x5add,
-	0x007c, 0x2011, 0x4999, 0x1078, 0x5a45, 0x2011, 0xa733, 0x2204,
-	0xc0cc, 0x2012, 0x007c, 0x2071, 0xa814, 0x7003, 0x0001, 0x7007,
-	0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f,
-	0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b,
-	0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xa97d, 0x7003,
-	0xa814, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xa95d, 0x7013,
-	0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x007c, 0x017e, 0x0e7e,
-	0x2071, 0xa935, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001,
-	0xa753, 0x2004, 0xd0fc, 0x00c0, 0x49e8, 0x2001, 0xa753, 0x2004,
-	0xa00e, 0xd09c, 0x0040, 0x49e5, 0x8108, 0x7102, 0x0078, 0x4a3b,
-	0x2001, 0xa772, 0x200c, 0xa184, 0x000f, 0x2009, 0xa773, 0x210c,
-	0x0079, 0x49f2, 0x49dd, 0x4a13, 0x4a1b, 0x4a26, 0x4a2c, 0x49dd,
-	0x49dd, 0x49dd, 0x4a02, 0x49dd, 0x49dd, 0x49dd, 0x49dd, 0x49dd,
-	0x49dd, 0x49dd, 0x7003, 0x0004, 0x137e, 0x147e, 0x157e, 0x2099,
-	0xa776, 0x20a1, 0xa986, 0x20a9, 0x0004, 0x53a3, 0x157f, 0x147f,
-	0x137f, 0x0078, 0x4a3b, 0x708f, 0x0005, 0x7007, 0x0122, 0x2001,
-	0x0002, 0x0078, 0x4a21, 0x708f, 0x0002, 0x7007, 0x0121, 0x2001,
-	0x0003, 0x7002, 0x7097, 0x0001, 0x0078, 0x4a38, 0x7007, 0x0122,
-	0x2001, 0x0002, 0x0078, 0x4a30, 0x7007, 0x0121, 0x2001, 0x0003,
-	0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007, 0x709a,
-	0xa184, 0x00ff, 0x7092, 0x0e7f, 0x017f, 0x007c, 0x0e7e, 0x2071,
-	0xa814, 0x684c, 0xa005, 0x00c0, 0x4a4c, 0x7028, 0xc085, 0x702a,
-	0xa085, 0x0001, 0x0078, 0x4a71, 0x6a60, 0x7236, 0x6b64, 0x733a,
-	0x6868, 0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e,
-	0x6844, 0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007,
-	0x8006, 0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100,
-	0xa319, 0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001,
-	0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x027e, 0x6838, 0xd0fc, 0x00c0,
-	0x4ac9, 0x6804, 0xa00d, 0x0040, 0x4a8f, 0x0d7e, 0x2071, 0xa700,
-	0xa016, 0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff,
-	0x00c0, 0x4a82, 0x702e, 0x70ac, 0xa200, 0x70ae, 0x0d7f, 0x2071,
-	0xa814, 0x701c, 0xa005, 0x00c0, 0x4adb, 0x0068, 0x4ad9, 0x2071,
-	0xa935, 0x7200, 0x82ff, 0x0040, 0x4ad9, 0x6934, 0xa186, 0x0103,
-	0x00c0, 0x4aec, 0x6948, 0x6844, 0xa105, 0x00c0, 0x4acc, 0x2009,
-	0x8020, 0x2200, 0x0079, 0x4aac, 0x4ad9, 0x4ab1, 0x4b09, 0x4b17,
-	0x4ad9, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ad9, 0x7122,
-	0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x2071, 0xa700, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70ac, 0x8000,
-	0x70ae, 0x027f, 0x0e7f, 0x007c, 0x6844, 0xa086, 0x0100, 0x00c0,
-	0x4ad9, 0x6868, 0xa005, 0x00c0, 0x4ad9, 0x2009, 0x8020, 0x0078,
-	0x4aa9, 0x2071, 0xa814, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000,
-	0x7012, 0x7018, 0xa06d, 0x711a, 0x0040, 0x4ae9, 0x6902, 0x0078,
-	0x4aea, 0x711e, 0x0078, 0x4ac9, 0xa18c, 0x00ff, 0xa186, 0x0017,
-	0x0040, 0x4afa, 0xa186, 0x001e, 0x0040, 0x4afa, 0xa18e, 0x001f,
-	0x00c0, 0x4ad9, 0x684c, 0xd0cc, 0x0040, 0x4ad9, 0x6850, 0xa084,
-	0x00ff, 0xa086, 0x0001, 0x00c0, 0x4ad9, 0x2009, 0x8021, 0x0078,
-	0x4aa9, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4ad9, 0x7186,
-	0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x4b27, 0x7084,
-	0x8008, 0xa092, 0x000f, 0x00c8, 0x4ad9, 0x7186, 0xae90, 0x0003,
-	0x8003, 0xa210, 0x683c, 0x2012, 0x8210, 0x6840, 0x2012, 0x7088,
-	0xa10a, 0x0048, 0x4ac0, 0x718c, 0x7084, 0xa10a, 0x0048, 0x4ac0,
-	0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4ac0, 0x2071, 0xa935,
-	0x7000, 0xa086, 0x0002, 0x00c0, 0x4b47, 0x1078, 0x4dc3, 0x2071,
-	0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4ac0, 0x1078,
-	0x4dee, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078,
-	0x4ac0, 0x007e, 0x684c, 0x007e, 0x6837, 0x0103, 0x20a9, 0x001c,
-	0xad80, 0x0011, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x007f, 0xa084,
-	0x00ff, 0x684e, 0x007f, 0x684a, 0x6952, 0x007c, 0x2071, 0xa814,
-	0x7004, 0x0079, 0x4b6b, 0x4b75, 0x4b86, 0x4d94, 0x4d95, 0x4dbc,
-	0x4dc2, 0x4b76, 0x4d82, 0x4d23, 0x4da5, 0x007c, 0x127e, 0x2091,
-	0x8000, 0x0068, 0x4b85, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091,
-	0x4080, 0x7007, 0x0001, 0x700b, 0x0000, 0x127f, 0x2069, 0xa9c4,
-	0x6844, 0xa005, 0x0050, 0x4bae, 0x00c0, 0x4bae, 0x127e, 0x2091,
-	0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xa820, 0x2004, 0xa10a,
-	0x0040, 0x4ba9, 0x0068, 0x4bad, 0x2069, 0x0000, 0x6818, 0xd084,
-	0x00c0, 0x4bad, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091,
-	0x4080, 0x2069, 0xa9c4, 0x6847, 0xffff, 0x127f, 0x2069, 0xa700,
-	0x6848, 0x6964, 0xa102, 0x2069, 0xa935, 0x688a, 0x6984, 0x701c,
-	0xa06d, 0x0040, 0x4bc0, 0x81ff, 0x0040, 0x4c08, 0x0078, 0x4bd6,
-	0x81ff, 0x0040, 0x4cda, 0x2071, 0xa935, 0x7184, 0x7088, 0xa10a,
-	0x00c8, 0x4bd6, 0x7190, 0x2071, 0xa9c4, 0x7040, 0xa005, 0x0040,
-	0x4bd6, 0x00d0, 0x4cda, 0x7142, 0x0078, 0x4cda, 0x2071, 0xa935,
-	0x718c, 0x127e, 0x2091, 0x8000, 0x7084, 0xa10a, 0x0048, 0x4cf7,
-	0x0068, 0x4c8c, 0x2071, 0x0000, 0x7018, 0xd084, 0x00c0, 0x4c8c,
-	0x2001, 0xffff, 0x2071, 0xa9c4, 0x7042, 0x2071, 0xa935, 0x7000,
-	0xa086, 0x0002, 0x00c0, 0x4bfe, 0x1078, 0x4dc3, 0x2071, 0x0000,
-	0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c, 0x1078, 0x4dee,
-	0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078, 0x4c8c,
-	0x2071, 0xa935, 0x7000, 0xa005, 0x0040, 0x4cb9, 0x6934, 0xa186,
-	0x0103, 0x00c0, 0x4c8f, 0x684c, 0xd0bc, 0x00c0, 0x4cb9, 0x6948,
-	0x6844, 0xa105, 0x00c0, 0x4cac, 0x2009, 0x8020, 0x2071, 0xa935,
-	0x7000, 0x0079, 0x4c23, 0x4cb9, 0x4c71, 0x4c49, 0x4c5b, 0x4c28,
-	0x137e, 0x147e, 0x157e, 0x2099, 0xa776, 0x20a1, 0xa986, 0x20a9,
-	0x0004, 0x53a3, 0x157f, 0x147f, 0x137f, 0x2071, 0xa97d, 0xad80,
-	0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b, 0x0000,
-	0x2e10, 0x1078, 0x13db, 0x2071, 0xa814, 0x7007, 0x0009, 0x0078,
-	0x4cda, 0x7084, 0x8008, 0xa092, 0x001e, 0x00c8, 0x4cda, 0xae90,
-	0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xa814, 0x1078,
-	0x4e4c, 0x0078, 0x4cda, 0x7084, 0x8008, 0xa092, 0x000f, 0x00c8,
-	0x4cda, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012, 0x8210,
-	0x6840, 0x2012, 0x7186, 0x2071, 0xa814, 0x1078, 0x4e4c, 0x0078,
-	0x4cda, 0x127e, 0x2091, 0x8000, 0x0068, 0x4c8c, 0x2071, 0x0000,
-	0x7018, 0xd084, 0x00c0, 0x4c8c, 0x7122, 0x683c, 0x7026, 0x6840,
-	0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x127f, 0x2071, 0xa814,
-	0x1078, 0x4e4c, 0x0078, 0x4cda, 0x127f, 0x0078, 0x4cda, 0xa18c,
-	0x00ff, 0xa186, 0x0017, 0x0040, 0x4c9d, 0xa186, 0x001e, 0x0040,
-	0x4c9d, 0xa18e, 0x001f, 0x00c0, 0x4cb9, 0x684c, 0xd0cc, 0x0040,
-	0x4cb9, 0x6850, 0xa084, 0x00ff, 0xa086, 0x0001, 0x00c0, 0x4cb9,
-	0x2009, 0x8021, 0x0078, 0x4c1e, 0x6844, 0xa086, 0x0100, 0x00c0,
-	0x4cb9, 0x6868, 0xa005, 0x00c0, 0x4cb9, 0x2009, 0x8020, 0x0078,
-	0x4c1e, 0x2071, 0xa814, 0x1078, 0x4e60, 0x0040, 0x4cda, 0x2071,
-	0xa814, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003,
-	0x00c0, 0x4cd1, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0040, 0x4cd1,
-	0x710e, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086, 0x0100,
-	0x0040, 0x4d95, 0x127e, 0x2091, 0x8000, 0x2071, 0xa814, 0x7008,
-	0xa086, 0x0001, 0x00c0, 0x4cf5, 0x0068, 0x4cf5, 0x2009, 0x000d,
-	0x7030, 0x200a, 0x2091, 0x4080, 0x700b, 0x0000, 0x7004, 0xa086,
-	0x0006, 0x00c0, 0x4cf5, 0x7007, 0x0001, 0x127f, 0x007c, 0x2071,
-	0xa814, 0x1078, 0x4e60, 0x0040, 0x4d20, 0x2071, 0xa935, 0x7084,
-	0x700a, 0x20a9, 0x0020, 0x2099, 0xa936, 0x20a1, 0xa95d, 0x53a3,
-	0x7087, 0x0000, 0x2071, 0xa814, 0x2069, 0xa97d, 0x706c, 0x6826,
-	0x7070, 0x682a, 0x7074, 0x682e, 0x7078, 0x6832, 0x2d10, 0x1078,
-	0x13db, 0x7007, 0x0008, 0x2001, 0xffff, 0x2071, 0xa9c4, 0x7042,
-	0x127f, 0x0078, 0x4cda, 0x2069, 0xa97d, 0x6808, 0xa08e, 0x0000,
-	0x0040, 0x4d81, 0xa08e, 0x0200, 0x0040, 0x4d7f, 0xa08e, 0x0100,
-	0x00c0, 0x4d81, 0x127e, 0x2091, 0x8000, 0x0068, 0x4d7c, 0x2069,
-	0x0000, 0x6818, 0xd084, 0x00c0, 0x4d7c, 0x702c, 0x7130, 0x8108,
-	0xa102, 0x0048, 0x4d4a, 0xa00e, 0x7034, 0x706e, 0x7038, 0x7072,
-	0x0078, 0x4d54, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8, 0x4d54,
-	0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000,
-	0x2001, 0xa95a, 0x2004, 0xa005, 0x00c0, 0x4d73, 0x6934, 0x2069,
-	0xa935, 0x689c, 0x699e, 0x2069, 0xa9c4, 0xa102, 0x00c0, 0x4d6c,
-	0x6844, 0xa005, 0x00d0, 0x4d7a, 0x2001, 0xa95b, 0x200c, 0x810d,
-	0x6946, 0x0078, 0x4d7a, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001,
-	0x2091, 0x4080, 0x7007, 0x0001, 0x127f, 0x0078, 0x4d81, 0x7007,
-	0x0005, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4d93, 0x1078, 0x4e60,
-	0x0040, 0x4d93, 0x7007, 0x0003, 0x1078, 0x4e80, 0x7050, 0xa086,
-	0x0100, 0x0040, 0x4d95, 0x007c, 0x007c, 0x7050, 0xa09e, 0x0100,
-	0x00c0, 0x4d9e, 0x7007, 0x0004, 0x0078, 0x4dbc, 0xa086, 0x0200,
-	0x00c0, 0x4da4, 0x7007, 0x0005, 0x007c, 0x2001, 0xa97f, 0x2004,
-	0xa08e, 0x0100, 0x00c0, 0x4db1, 0x7007, 0x0001, 0x1078, 0x4e4c,
-	0x007c, 0xa08e, 0x0000, 0x0040, 0x4db0, 0xa08e, 0x0200, 0x00c0,
-	0x4db0, 0x7007, 0x0005, 0x007c, 0x1078, 0x4e16, 0x7006, 0x1078,
-	0x4e4c, 0x007c, 0x007c, 0x0e7e, 0x157e, 0x2071, 0xa935, 0x7184,
-	0x81ff, 0x0040, 0x4deb, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071,
-	0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0070, 0x4de8, 0x2014,
-	0x722a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x722e, 0x8000, 0x0070,
-	0x4de8, 0x2014, 0x723a, 0x8000, 0x0070, 0x4de8, 0x2014, 0x723e,
-	0xa180, 0x8030, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x0e7e, 0x157e,
-	0x2071, 0xa935, 0x7184, 0x81ff, 0x0040, 0x4e13, 0xa006, 0x7086,
-	0xae80, 0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000,
-	0x2014, 0x722a, 0x8000, 0x0070, 0x4e0c, 0x2014, 0x723a, 0x8000,
-	0x2014, 0x723e, 0x0078, 0x4e10, 0x2001, 0x8020, 0x0078, 0x4e12,
-	0x2001, 0x8042, 0x7022, 0x157f, 0x0e7f, 0x007c, 0x702c, 0x7130,
-	0x8108, 0xa102, 0x0048, 0x4e23, 0xa00e, 0x7034, 0x706e, 0x7038,
-	0x7072, 0x0078, 0x4e2d, 0x706c, 0xa080, 0x0040, 0x706e, 0x00c8,
-	0x4e2d, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132, 0x700c, 0x8001,
-	0x700e, 0x00c0, 0x4e43, 0x127e, 0x2091, 0x8000, 0x0068, 0x4e46,
-	0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001, 0x700b,
-	0x0000, 0x127f, 0x007c, 0x2001, 0x0007, 0x007c, 0x2001, 0x0006,
-	0x700b, 0x0001, 0x127f, 0x007c, 0x701c, 0xa06d, 0x0040, 0x4e5f,
-	0x127e, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e,
-	0xa005, 0x00c0, 0x4e5c, 0x701a, 0x127f, 0x1078, 0x13a4, 0x007c,
-	0x2019, 0x000d, 0x2304, 0x230c, 0xa10e, 0x0040, 0x4e6f, 0x2304,
-	0x230c, 0xa10e, 0x0040, 0x4e6f, 0xa006, 0x0078, 0x4e7f, 0x732c,
-	0x8319, 0x7130, 0xa102, 0x00c0, 0x4e79, 0x2300, 0xa005, 0x0078,
-	0x4e7f, 0x0048, 0x4e7e, 0xa302, 0x0078, 0x4e7f, 0x8002, 0x007c,
-	0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x127e,
-	0x2091, 0x8000, 0x2009, 0xa9d6, 0x2104, 0xc08d, 0x200a, 0x127f,
-	0x1078, 0x13f9, 0x007c, 0x2071, 0xa7e2, 0x7003, 0x0000, 0x7007,
-	0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000, 0x7053,
-	0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000, 0x708b,
-	0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x007c, 0x0e7e, 0x2071,
-	0xa7e2, 0x6848, 0xa005, 0x00c0, 0x4ebc, 0x7028, 0xc085, 0x702a,
-	0xa085, 0x0001, 0x0078, 0x4ee1, 0x6a50, 0x7236, 0x6b54, 0x733a,
-	0x6858, 0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e,
-	0x6840, 0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006,
-	0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272,
-	0x7376, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000,
-	0xa006, 0x0e7f, 0x007c, 0x2b78, 0x2071, 0xa7e2, 0x7004, 0x1079,
-	0x4f41, 0x700c, 0x0079, 0x4eec, 0x4ef1, 0x4ee6, 0x4ee6, 0x4ee6,
-	0x4ee6, 0x007c, 0x700c, 0x0079, 0x4ef5, 0x4efa, 0x4f3f, 0x4f3f,
-	0x4f40, 0x4f40, 0x7830, 0x7930, 0xa106, 0x0040, 0x4f04, 0x7830,
-	0x7930, 0xa106, 0x00c0, 0x4f2a, 0x7030, 0xa10a, 0x0040, 0x4f2a,
-	0x00c8, 0x4f0c, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x00c8, 0x4f2b,
-	0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00, 0x705a, 0x7063, 0x0040,
-	0x2001, 0x0003, 0x7057, 0x0000, 0x127e, 0x007e, 0x2091, 0x8000,
-	0x2009, 0xa9d6, 0x2104, 0xc085, 0x200a, 0x007f, 0x700e, 0x127f,
-	0x1078, 0x13f9, 0x007c, 0x1078, 0x1370, 0x0040, 0x4f2a, 0x2d00,
-	0x705a, 0x1078, 0x1370, 0x00c0, 0x4f37, 0x0078, 0x4f16, 0x2d00,
-	0x7086, 0x7063, 0x0080, 0x2001, 0x0004, 0x0078, 0x4f1a, 0x007c,
-	0x007c, 0x4f52, 0x4f53, 0x4f8a, 0x4f8b, 0x4f3f, 0x4fc1, 0x4fc6,
-	0x4ffd, 0x4ffe, 0x5019, 0x501a, 0x501b, 0x501c, 0x501d, 0x501e,
-	0x509e, 0x50c8, 0x007c, 0x700c, 0x0079, 0x4f56, 0x4f5b, 0x4f5e,
-	0x4f6e, 0x4f89, 0x4f89, 0x1078, 0x4ef2, 0x007c, 0x127e, 0x8001,
-	0x700e, 0x7058, 0x007e, 0x1078, 0x5464, 0x0040, 0x4f6b, 0x2091,
-	0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078, 0x4f77, 0x127e, 0x8001,
-	0x700e, 0x1078, 0x5464, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803,
-	0x0000, 0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x0020,
-	0x00c8, 0x4f86, 0x1079, 0x4fa1, 0x127f, 0x007c, 0x127f, 0x1078,
-	0x501f, 0x007c, 0x007c, 0x007c, 0x0e7e, 0x2071, 0xa7e2, 0x700c,
-	0x0079, 0x4f92, 0x4f97, 0x4f97, 0x4f97, 0x4f99, 0x4f9d, 0x0e7f,
-	0x007c, 0x700f, 0x0001, 0x0078, 0x4f9f, 0x700f, 0x0002, 0x0e7f,
-	0x007c, 0x501f, 0x501f, 0x503b, 0x501f, 0x5171, 0x501f, 0x501f,
-	0x501f, 0x501f, 0x501f, 0x503b, 0x51bb, 0x5208, 0x5261, 0x5277,
-	0x501f, 0x501f, 0x5057, 0x503b, 0x501f, 0x501f, 0x5078, 0x5338,
-	0x5356, 0x501f, 0x5057, 0x501f, 0x501f, 0x501f, 0x501f, 0x506d,
-	0x5356, 0x7020, 0x2068, 0x1078, 0x13a4, 0x007c, 0x700c, 0x0079,
-	0x4fc9, 0x4fce, 0x4fd1, 0x4fe1, 0x4ffc, 0x4ffc, 0x1078, 0x4ef2,
-	0x007c, 0x127e, 0x8001, 0x700e, 0x7058, 0x007e, 0x1078, 0x5464,
-	0x0040, 0x4fde, 0x2091, 0x8000, 0x1078, 0x4ef2, 0x0d7f, 0x0078,
-	0x4fea, 0x127e, 0x8001, 0x700e, 0x1078, 0x5464, 0x7058, 0x2068,
-	0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000, 0x6834, 0xa084,
-	0x00ff, 0xa08a, 0x001a, 0x00c8, 0x4ff9, 0x1079, 0x4fff, 0x127f,
-	0x007c, 0x127f, 0x1078, 0x501f, 0x007c, 0x007c, 0x007c, 0x501f,
-	0x503b, 0x515b, 0x501f, 0x503b, 0x501f, 0x503b, 0x503b, 0x501f,
-	0x503b, 0x515b, 0x503b, 0x503b, 0x503b, 0x503b, 0x503b, 0x501f,
-	0x503b, 0x515b, 0x501f, 0x501f, 0x503b, 0x501f, 0x501f, 0x501f,
-	0x503b, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x007c, 0x7007,
-	0x0001, 0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838,
-	0xa084, 0x00ff, 0xc0e5, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x4a73, 0x127f, 0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff,
-	0xc0ed, 0x683a, 0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f,
-	0x007c, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x4a73, 0x127f, 0x007c, 0x6834,
-	0x8007, 0xa084, 0x00ff, 0x0040, 0x502d, 0x8001, 0x00c0, 0x5064,
-	0x7007, 0x0001, 0x0078, 0x513a, 0x7007, 0x0006, 0x7012, 0x2d00,
-	0x7016, 0x701a, 0x704b, 0x513a, 0x007c, 0x684c, 0xa084, 0x00c0,
-	0xa086, 0x00c0, 0x00c0, 0x5078, 0x7007, 0x0001, 0x0078, 0x5373,
-	0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098,
-	0x20a1, 0xa80d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x00c8,
-	0x5049, 0x6884, 0xa08a, 0x0002, 0x00c8, 0x5049, 0x82ff, 0x00c0,
-	0x509a, 0x6888, 0x698c, 0xa105, 0x0040, 0x509a, 0x2001, 0x510a,
-	0x0078, 0x509d, 0xa280, 0x5100, 0x2004, 0x70c6, 0x7010, 0xa015,
-	0x0040, 0x50e8, 0x1078, 0x1370, 0x00c0, 0x50a9, 0x7007, 0x000f,
-	0x007c, 0x2d00, 0x7022, 0x70c4, 0x2060, 0x6000, 0x6836, 0x6004,
-	0xad00, 0x7096, 0x6008, 0xa20a, 0x00c8, 0x50b8, 0xa00e, 0x2200,
-	0x7112, 0x620c, 0x8003, 0x800b, 0xa296, 0x0004, 0x0040, 0x50c1,
-	0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022, 0x1078, 0x13db,
-	0x7090, 0xa08e, 0x0100, 0x0040, 0x50dc, 0xa086, 0x0200, 0x0040,
-	0x50d4, 0x7007, 0x0010, 0x007c, 0x7020, 0x2068, 0x1078, 0x13a4,
-	0x7014, 0x2068, 0x0078, 0x5049, 0x7020, 0x2068, 0x7018, 0x6802,
-	0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0078, 0x509e,
-	0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x00c0, 0x50f7,
-	0x6888, 0x698c, 0xa105, 0x0040, 0x50f7, 0x1078, 0x510e, 0x6834,
-	0xa084, 0x00ff, 0xa086, 0x001e, 0x0040, 0x5373, 0x0078, 0x513a,
-	0x5102, 0x5106, 0x0002, 0x0011, 0x0007, 0x0004, 0x000a, 0x000f,
-	0x0005, 0x0006, 0x000a, 0x0011, 0x0005, 0x0004, 0x0f7e, 0x0e7e,
-	0x0c7e, 0x077e, 0x067e, 0x6f88, 0x6e8c, 0x6804, 0x2060, 0xacf0,
-	0x0021, 0xacf8, 0x0027, 0x2009, 0x0005, 0x700c, 0x7816, 0x7008,
-	0x7812, 0x7004, 0x7806, 0x7000, 0x7802, 0x7e0e, 0x7f0a, 0x8109,
-	0x0040, 0x5130, 0xaef2, 0x0004, 0xaffa, 0x0006, 0x0078, 0x511d,
-	0x6004, 0xa065, 0x00c0, 0x5117, 0x067f, 0x077f, 0x0c7f, 0x0e7f,
-	0x0f7f, 0x007c, 0x2009, 0xa72f, 0x210c, 0x81ff, 0x00c0, 0x5155,
-	0x6838, 0xa084, 0x00ff, 0x683a, 0x1078, 0x4353, 0x00c0, 0x5149,
-	0x007c, 0x1078, 0x4b51, 0x127e, 0x2091, 0x8000, 0x1078, 0x8f8d,
-	0x1078, 0x4a73, 0x127f, 0x0078, 0x5148, 0x2001, 0x0028, 0x2009,
-	0x0000, 0x0078, 0x5149, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906,
-	0x711a, 0x7010, 0x8001, 0x7012, 0x0040, 0x516a, 0x7007, 0x0006,
-	0x0078, 0x5170, 0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x107a,
-	0x007c, 0x7007, 0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848,
-	0xa084, 0x00ff, 0x20a9, 0x0001, 0xa096, 0x0001, 0x0040, 0x519a,
-	0x2009, 0x0000, 0x20a9, 0x00ff, 0xa096, 0x0002, 0x0040, 0x519a,
-	0xa005, 0x00c0, 0x51ad, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x1078,
-	0x45c4, 0x00c0, 0x51ad, 0x067e, 0x6e50, 0x1078, 0x46b3, 0x067f,
-	0x0078, 0x51ad, 0x047e, 0x2011, 0xa70c, 0x2224, 0xc484, 0xc48c,
-	0x2412, 0x047f, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x51a9, 0x1078,
-	0x4852, 0x8108, 0x00f0, 0x51a3, 0x0c7f, 0x684c, 0xd084, 0x00c0,
-	0x51b4, 0x1078, 0x13a4, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x4a73, 0x127f, 0x007c, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001,
-	0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x51ff, 0x2061, 0xaa33,
-	0x6100, 0xd184, 0x0040, 0x51df, 0x6858, 0xa084, 0x00ff, 0x00c0,
-	0x5202, 0x6000, 0xd084, 0x0040, 0x51ff, 0x6004, 0xa005, 0x00c0,
-	0x5205, 0x6003, 0x0000, 0x600b, 0x0000, 0x0078, 0x51fc, 0x2011,
-	0x0001, 0x6860, 0xa005, 0x00c0, 0x51e7, 0x2001, 0x001e, 0x8000,
-	0x6016, 0x6858, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x6006, 0x6858,
-	0x8007, 0xa084, 0x00ff, 0x0040, 0x51ff, 0x600a, 0x6858, 0x8000,
-	0x00c0, 0x51fb, 0xc28d, 0x6202, 0x127f, 0x0078, 0x5453, 0x127f,
-	0x0078, 0x544b, 0x127f, 0x0078, 0x5443, 0x127f, 0x0078, 0x5447,
-	0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xa753, 0x2004,
-	0xd0a4, 0x0040, 0x525e, 0x2061, 0xaa33, 0x6000, 0xd084, 0x0040,
-	0x525e, 0x6204, 0x6308, 0xd08c, 0x00c0, 0x5250, 0x6c48, 0xa484,
-	0x0003, 0x0040, 0x5236, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x00c0,
-	0x522f, 0x2100, 0xa210, 0x0048, 0x525b, 0x0078, 0x5236, 0x8001,
-	0x00c0, 0x525b, 0x2100, 0xa212, 0x0048, 0x525b, 0xa484, 0x000c,
-	0x0040, 0x5250, 0x6958, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004,
-	0x00c0, 0x5248, 0x2100, 0xa318, 0x0048, 0x525b, 0x0078, 0x5250,
-	0xa082, 0x0004, 0x00c0, 0x525b, 0x2100, 0xa31a, 0x0048, 0x525b,
-	0x6860, 0xa005, 0x0040, 0x5256, 0x8000, 0x6016, 0x6206, 0x630a,
-	0x127f, 0x0078, 0x5453, 0x127f, 0x0078, 0x544f, 0x127f, 0x0078,
-	0x544b, 0x127e, 0x2091, 0x8000, 0x7007, 0x0001, 0x2061, 0xaa33,
-	0x6300, 0xd38c, 0x00c0, 0x5271, 0x6308, 0x8318, 0x0048, 0x5274,
-	0x630a, 0x127f, 0x0078, 0x5461, 0x127f, 0x0078, 0x544f, 0x127e,
-	0x0c7e, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c, 0xd0ac, 0x0040,
-	0x528b, 0x0c7e, 0x2061, 0xaa33, 0x6000, 0xa084, 0xfcff, 0x6002,
-	0x0c7f, 0x0078, 0x52ba, 0x6858, 0xa005, 0x0040, 0x52d1, 0x685c,
-	0xa065, 0x0040, 0x52cd, 0x2001, 0xa72f, 0x2004, 0xa005, 0x0040,
-	0x529d, 0x1078, 0x8ed6, 0x0078, 0x52ab, 0x6013, 0x0400, 0x6037,
-	0x0000, 0x694c, 0xd1a4, 0x0040, 0x52a7, 0x6950, 0x6136, 0x2009,
-	0x0041, 0x1078, 0x775c, 0x6958, 0xa18c, 0xff00, 0xa186, 0x2000,
-	0x00c0, 0x52ba, 0x027e, 0x2009, 0x0000, 0x2011, 0xfdff, 0x1078,
-	0x5bf1, 0x027f, 0x684c, 0xd0c4, 0x0040, 0x52c9, 0x2061, 0xaa33,
-	0x6000, 0xd08c, 0x00c0, 0x52c9, 0x6008, 0x8000, 0x0048, 0x52cd,
-	0x600a, 0x0c7f, 0x127f, 0x0078, 0x5453, 0x0c7f, 0x127f, 0x0078,
-	0x544b, 0x6954, 0xa186, 0x0045, 0x0040, 0x5306, 0xa186, 0x002a,
-	0x00c0, 0x52e1, 0x2001, 0xa70c, 0x200c, 0xc194, 0x2102, 0x0078,
-	0x52ba, 0xa186, 0x0020, 0x0040, 0x52fa, 0xa186, 0x0029, 0x0040,
-	0x52ed, 0xa186, 0x002d, 0x00c0, 0x52cd, 0x6944, 0xa18c, 0xff00,
-	0x810f, 0x1078, 0x45c4, 0x00c0, 0x52ba, 0x6000, 0xc0e4, 0x6002,
-	0x0078, 0x52ba, 0x685c, 0xa065, 0x0040, 0x52cd, 0x6007, 0x0024,
-	0x2001, 0xa9a3, 0x2004, 0x6016, 0x0078, 0x52ba, 0x685c, 0xa065,
-	0x0040, 0x52cd, 0x0e7e, 0x6860, 0xa075, 0x2001, 0xa72f, 0x2004,
-	0xa005, 0x0040, 0x531e, 0x1078, 0x8ed6, 0x8eff, 0x0040, 0x531b,
-	0x2e60, 0x1078, 0x8ed6, 0x0e7f, 0x0078, 0x52ba, 0x6024, 0xc0dc,
-	0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0040,
-	0x532f, 0x6007, 0x003b, 0x6874, 0x602a, 0x6878, 0x6012, 0x6003,
-	0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x0078, 0x52ba,
-	0x2061, 0xaa33, 0x6000, 0xd084, 0x0040, 0x5352, 0xd08c, 0x00c0,
-	0x5461, 0x2091, 0x8000, 0x6204, 0x8210, 0x0048, 0x534c, 0x6206,
-	0x2091, 0x8001, 0x0078, 0x5461, 0x2091, 0x8001, 0x6853, 0x0016,
-	0x0078, 0x545a, 0x6853, 0x0007, 0x0078, 0x545a, 0x6834, 0x8007,
-	0xa084, 0x00ff, 0x00c0, 0x5360, 0x1078, 0x502d, 0x0078, 0x5372,
-	0x2030, 0x8001, 0x00c0, 0x536a, 0x7007, 0x0001, 0x1078, 0x5373,
-	0x0078, 0x5372, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a,
-	0x704b, 0x5373, 0x007c, 0x0e7e, 0x127e, 0x2091, 0x8000, 0xa03e,
-	0x2009, 0xa72f, 0x210c, 0x81ff, 0x00c0, 0x53ff, 0x2009, 0xa70c,
-	0x210c, 0xd194, 0x00c0, 0x5431, 0x6848, 0x2070, 0xae82, 0xae00,
-	0x0048, 0x53ef, 0x2001, 0xa716, 0x2004, 0xae02, 0x00c8, 0x53ef,
-	0x2061, 0xaa33, 0x6100, 0xa184, 0x0301, 0xa086, 0x0001, 0x00c0,
-	0x53d2, 0x711c, 0xa186, 0x0006, 0x00c0, 0x53da, 0x7018, 0xa005,
-	0x0040, 0x53ff, 0x2004, 0xd0e4, 0x00c0, 0x542b, 0x7024, 0xd0dc,
-	0x00c0, 0x5435, 0x6853, 0x0000, 0x6803, 0x0000, 0x2d08, 0x7010,
-	0xa005, 0x00c0, 0x53be, 0x7112, 0x684c, 0xd0f4, 0x00c0, 0x5439,
-	0x2e60, 0x1078, 0x5b27, 0x127f, 0x0e7f, 0x007c, 0x2068, 0x6800,
-	0xa005, 0x00c0, 0x53be, 0x6902, 0x2168, 0x684c, 0xd0f4, 0x00c0,
-	0x5439, 0x127f, 0x0e7f, 0x007c, 0x127f, 0x0e7f, 0x6853, 0x0006,
-	0x0078, 0x545a, 0xd184, 0x0040, 0x53cc, 0xd1c4, 0x00c0, 0x53f3,
-	0x0078, 0x53f7, 0x6944, 0xa18c, 0xff00, 0x810f, 0x1078, 0x45c4,
-	0x00c0, 0x542b, 0x6000, 0xd0e4, 0x00c0, 0x542b, 0x711c, 0xa186,
-	0x0007, 0x00c0, 0x53ef, 0x6853, 0x0002, 0x0078, 0x542d, 0x6853,
-	0x0008, 0x0078, 0x542d, 0x6853, 0x000e, 0x0078, 0x542d, 0x6853,
-	0x0017, 0x0078, 0x542d, 0x6853, 0x0035, 0x0078, 0x542d, 0x2001,
-	0xa772, 0x2004, 0xd0fc, 0x0040, 0x5427, 0x6848, 0x2070, 0xae82,
-	0xae00, 0x0048, 0x5427, 0x6058, 0xae02, 0x00c8, 0x5427, 0x711c,
-	0xa186, 0x0006, 0x00c0, 0x5427, 0x7018, 0xa005, 0x0040, 0x5427,
-	0x2004, 0xd0bc, 0x0040, 0x5427, 0x2039, 0x0001, 0x7000, 0xa086,
-	0x0007, 0x00c0, 0x537e, 0x7003, 0x0002, 0x0078, 0x537e, 0x6853,
-	0x0028, 0x0078, 0x542d, 0x6853, 0x0029, 0x127f, 0x0e7f, 0x0078,
-	0x545a, 0x6853, 0x002a, 0x0078, 0x542d, 0x6853, 0x0045, 0x0078,
-	0x542d, 0x2e60, 0x2019, 0x0002, 0x6017, 0x0014, 0x1078, 0x9dd7,
-	0x127f, 0x0e7f, 0x007c, 0x2009, 0x003e, 0x0078, 0x5455, 0x2009,
-	0x0004, 0x0078, 0x5455, 0x2009, 0x0006, 0x0078, 0x5455, 0x2009,
-	0x0016, 0x0078, 0x5455, 0x2009, 0x0001, 0x6854, 0xa084, 0xff00,
-	0xa105, 0x6856, 0x2091, 0x8000, 0x1078, 0x4a73, 0x2091, 0x8001,
-	0x007c, 0x1078, 0x13a4, 0x007c, 0x702c, 0x7130, 0x8108, 0xa102,
-	0x0048, 0x5471, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0078,
-	0x547d, 0x7070, 0xa080, 0x0040, 0x7072, 0x00c8, 0x547d, 0x7074,
-	0xa081, 0x0000, 0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x007c,
-	0x0d7e, 0x1078, 0x5b1e, 0x0d7f, 0x007c, 0x0d7e, 0x2011, 0x0004,
-	0x2204, 0xa085, 0x8002, 0x2012, 0x0d7f, 0x007c, 0x20e1, 0x0002,
-	0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0040, 0x549c,
-	0xa086, 0x1000, 0x00c0, 0x54d3, 0x20e1, 0x0000, 0x3d00, 0xa094,
-	0xff00, 0x8217, 0xa084, 0xf000, 0xa086, 0x3000, 0x00c0, 0x54b7,
-	0xa184, 0xff00, 0x8007, 0xa086, 0x0008, 0x00c0, 0x54d3, 0x1078,
-	0x29bb, 0x00c0, 0x54d3, 0x1078, 0x56b2, 0x0078, 0x54ce, 0x20e1,
-	0x0004, 0x3d60, 0xd1bc, 0x00c0, 0x54be, 0x3e60, 0xac84, 0x000f,
-	0x00c0, 0x54d3, 0xac82, 0xae00, 0x0048, 0x54d3, 0x6858, 0xac02,
-	0x00c8, 0x54d3, 0x2009, 0x0047, 0x1078, 0x775c, 0x7a1c, 0xd284,
-	0x00c0, 0x548e, 0x007c, 0xa016, 0x1078, 0x15fa, 0x0078, 0x54ce,
-	0x0078, 0x54d3, 0x781c, 0xd08c, 0x0040, 0x5502, 0x157e, 0x137e,
-	0x147e, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584, 0x0076, 0x00c0,
-	0x5518, 0xa484, 0x7000, 0xa086, 0x1000, 0x00c0, 0x5507, 0x1078,
-	0x554e, 0x0040, 0x5518, 0x20e1, 0x3000, 0x7828, 0x7828, 0x1078,
-	0x556c, 0x147f, 0x137f, 0x157f, 0x2009, 0xa9b9, 0x2104, 0xa005,
-	0x00c0, 0x5503, 0x007c, 0x1078, 0x62d1, 0x0078, 0x5502, 0xa484,
-	0x7000, 0x00c0, 0x5518, 0x1078, 0x554e, 0x0040, 0x552c, 0x7000,
-	0xa084, 0xff00, 0xa086, 0x8100, 0x0040, 0x54f3, 0x0078, 0x552c,
-	0x1078, 0xa55f, 0xd5a4, 0x0040, 0x5528, 0x047e, 0x1078, 0x1b22,
-	0x047f, 0x20e1, 0x9010, 0x2001, 0x0138, 0x2202, 0x0078, 0x5530,
-	0x1078, 0x554e, 0x6883, 0x0000, 0x20e1, 0x3000, 0x7828, 0x7828,
-	0x1078, 0x5537, 0x147f, 0x137f, 0x157f, 0x0078, 0x5502, 0x2001,
-	0xa70e, 0x2004, 0xd08c, 0x0040, 0x554d, 0x2001, 0xa700, 0x2004,
-	0xa086, 0x0003, 0x00c0, 0x554d, 0x027e, 0x037e, 0x2011, 0x8048,
-	0x2518, 0x1078, 0x361b, 0x037f, 0x027f, 0x007c, 0xa484, 0x01ff,
-	0x6882, 0xa005, 0x0040, 0x5560, 0xa080, 0x001f, 0xa084, 0x03f8,
-	0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5, 0x007c,
-	0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
-	0xa085, 0x0001, 0x0078, 0x555f, 0x7000, 0xa084, 0xff00, 0xa08c,
-	0xf000, 0x8007, 0xa196, 0x0000, 0x00c0, 0x5579, 0x0078, 0x57ba,
-	0x007c, 0xa196, 0x2000, 0x00c0, 0x558a, 0x6900, 0xa18e, 0x0001,
-	0x00c0, 0x5586, 0x1078, 0x3aec, 0x0078, 0x5578, 0x1078, 0x5592,
-	0x0078, 0x5578, 0xa196, 0x8000, 0x00c0, 0x5578, 0x1078, 0x5871,
-	0x0078, 0x5578, 0x0c7e, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa196,
-	0x0001, 0x0040, 0x559f, 0xa196, 0x0023, 0x00c0, 0x56aa, 0xa08e,
-	0x0023, 0x00c0, 0x55d4, 0x1078, 0x591d, 0x0040, 0x56aa, 0x7124,
-	0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x55b8, 0x7034, 0xa005,
-	0x00c0, 0x56aa, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa,
-	0xa08e, 0x0214, 0x0040, 0x55c0, 0xa08e, 0x0210, 0x00c0, 0x55c6,
-	0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0100,
-	0x00c0, 0x56aa, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0016,
-	0x1078, 0x775c, 0x0078, 0x56aa, 0xa08e, 0x0022, 0x00c0, 0x56aa,
-	0x7030, 0xa08e, 0x0300, 0x00c0, 0x55e5, 0x7034, 0xa005, 0x00c0,
-	0x56aa, 0x2009, 0x0017, 0x0078, 0x5676, 0xa08e, 0x0500, 0x00c0,
-	0x55f1, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x0018, 0x0078,
-	0x5676, 0xa08e, 0x2010, 0x00c0, 0x55f9, 0x2009, 0x0019, 0x0078,
-	0x5676, 0xa08e, 0x2110, 0x00c0, 0x5601, 0x2009, 0x001a, 0x0078,
-	0x5676, 0xa08e, 0x5200, 0x00c0, 0x560d, 0x7034, 0xa005, 0x00c0,
-	0x56aa, 0x2009, 0x001b, 0x0078, 0x5676, 0xa08e, 0x5000, 0x00c0,
-	0x5619, 0x7034, 0xa005, 0x00c0, 0x56aa, 0x2009, 0x001c, 0x0078,
-	0x5676, 0xa08e, 0x1300, 0x00c0, 0x5621, 0x2009, 0x0034, 0x0078,
-	0x5676, 0xa08e, 0x1200, 0x00c0, 0x562d, 0x7034, 0xa005, 0x00c0,
-	0x56aa, 0x2009, 0x0024, 0x0078, 0x5676, 0xa08c, 0xff00, 0xa18e,
-	0x2400, 0x00c0, 0x5637, 0x2009, 0x002d, 0x0078, 0x5676, 0xa08c,
-	0xff00, 0xa18e, 0x5300, 0x00c0, 0x5641, 0x2009, 0x002a, 0x0078,
-	0x5676, 0xa08e, 0x0f00, 0x00c0, 0x5649, 0x2009, 0x0020, 0x0078,
-	0x5676, 0xa08e, 0x5300, 0x00c0, 0x564f, 0x0078, 0x566c, 0xa08e,
-	0x6104, 0x00c0, 0x566c, 0x2011, 0xac8d, 0x8208, 0x2204, 0xa082,
-	0x0004, 0x20a8, 0x95ac, 0x95ac, 0x2011, 0x8015, 0x211c, 0x8108,
-	0x047e, 0x2124, 0x1078, 0x361b, 0x047f, 0x8108, 0x00f0, 0x565c,
-	0x2009, 0x0023, 0x0078, 0x5676, 0xa08e, 0x6000, 0x00c0, 0x5674,
-	0x2009, 0x003f, 0x0078, 0x5676, 0x2009, 0x001d, 0x017e, 0x2011,
-	0xac83, 0x2204, 0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x56ac,
-	0x1078, 0x455c, 0x00c0, 0x56ac, 0x6612, 0x6516, 0x86ff, 0x0040,
-	0x569c, 0x017f, 0x017e, 0xa186, 0x0017, 0x00c0, 0x569c, 0x686c,
-	0xa606, 0x00c0, 0x569c, 0x6870, 0xa506, 0xa084, 0xff00, 0x00c0,
-	0x569c, 0x6000, 0xc0f5, 0x6002, 0x0c7e, 0x1078, 0x76c7, 0x0040,
-	0x56af, 0x017f, 0x611a, 0x601f, 0x0004, 0x7120, 0x610a, 0x017f,
-	0x1078, 0x775c, 0x0c7f, 0x007c, 0x017f, 0x0078, 0x56aa, 0x0c7f,
-	0x0078, 0x56ac, 0x0c7e, 0x1078, 0x570f, 0x00c0, 0x570d, 0xa28e,
-	0x0033, 0x00c0, 0x56de, 0x1078, 0x591d, 0x0040, 0x570d, 0x7124,
-	0x610a, 0x7030, 0xa08e, 0x0200, 0x00c0, 0x56d0, 0x7034, 0xa005,
-	0x00c0, 0x570d, 0x2009, 0x0015, 0x1078, 0x775c, 0x0078, 0x570d,
-	0xa08e, 0x0100, 0x00c0, 0x570d, 0x7034, 0xa005, 0x00c0, 0x570d,
-	0x2009, 0x0016, 0x1078, 0x775c, 0x0078, 0x570d, 0xa28e, 0x0032,
-	0x00c0, 0x570d, 0x7030, 0xa08e, 0x1400, 0x00c0, 0x570d, 0x2009,
-	0x0038, 0x017e, 0x2011, 0xac83, 0x2204, 0x8211, 0x220c, 0x1078,
-	0x254d, 0x00c0, 0x570c, 0x1078, 0x455c, 0x00c0, 0x570c, 0x6612,
-	0x6516, 0x0c7e, 0x1078, 0x76c7, 0x0040, 0x570b, 0x017f, 0x611a,
-	0x601f, 0x0004, 0x7120, 0x610a, 0x017f, 0x1078, 0x775c, 0x1078,
-	0x62d1, 0x0078, 0x570d, 0x0c7f, 0x017f, 0x0c7f, 0x007c, 0x0f7e,
-	0x0d7e, 0x027e, 0x017e, 0x137e, 0x147e, 0x157e, 0x3c00, 0x007e,
-	0x2079, 0x0030, 0x2069, 0x0200, 0x1078, 0x1c6a, 0x00c0, 0x5750,
-	0x1078, 0x1b40, 0x0040, 0x575d, 0x7908, 0xa18c, 0x1fff, 0xa182,
-	0x0011, 0x00c8, 0x575a, 0x20a9, 0x000c, 0x20e1, 0x0000, 0x2ea0,
-	0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004,
-	0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0xa08a, 0x0140,
-	0x10c8, 0x1332, 0x80ac, 0x20e1, 0x6000, 0x2099, 0x020a, 0x53a5,
-	0x20e1, 0x7000, 0x6828, 0x6828, 0x7803, 0x0004, 0xa294, 0x0070,
-	0x007f, 0x20e0, 0x157f, 0x147f, 0x137f, 0x017f, 0x027f, 0x0d7f,
-	0x0f7f, 0x007c, 0xa016, 0x1078, 0x15fa, 0xa085, 0x0001, 0x0078,
-	0x5750, 0x047e, 0x0e7e, 0x0d7e, 0x2028, 0x2130, 0xa696, 0x00ff,
-	0x00c0, 0x5782, 0xa596, 0xfffd, 0x00c0, 0x5772, 0x2009, 0x007f,
-	0x0078, 0x57b5, 0xa596, 0xfffe, 0x00c0, 0x577a, 0x2009, 0x007e,
-	0x0078, 0x57b5, 0xa596, 0xfffc, 0x00c0, 0x5782, 0x2009, 0x0080,
-	0x0078, 0x57b5, 0x2011, 0x0000, 0x2021, 0x0081, 0x20a9, 0x007e,
-	0x2071, 0xa8b6, 0x2e1c, 0x83ff, 0x00c0, 0x5794, 0x82ff, 0x00c0,
-	0x57a9, 0x2410, 0x0078, 0x57a9, 0x2368, 0x6f10, 0x007e, 0x2100,
-	0xa706, 0x007f, 0x6b14, 0x00c0, 0x57a3, 0xa346, 0x00c0, 0x57a3,
-	0x2408, 0x0078, 0x57b5, 0x87ff, 0x00c0, 0x57a9, 0x83ff, 0x0040,
-	0x578e, 0x8420, 0x8e70, 0x00f0, 0x578a, 0x82ff, 0x00c0, 0x57b4,
-	0xa085, 0x0001, 0x0078, 0x57b6, 0x2208, 0xa006, 0x0d7f, 0x0e7f,
-	0x047f, 0x007c, 0xa084, 0x0007, 0x0079, 0x57bf, 0x007c, 0x57c7,
-	0x57c7, 0x57c7, 0x5933, 0x57c7, 0x57c8, 0x57e1, 0x5858, 0x007c,
-	0x7110, 0xd1bc, 0x0040, 0x57e0, 0x7120, 0x2160, 0xac8c, 0x000f,
-	0x00c0, 0x57e0, 0xac8a, 0xae00, 0x0048, 0x57e0, 0x6858, 0xac02,
-	0x00c8, 0x57e0, 0x7124, 0x610a, 0x2009, 0x0046, 0x1078, 0x775c,
-	0x007c, 0x0c7e, 0xa484, 0x01ff, 0x0040, 0x5833, 0x7110, 0xd1bc,
-	0x00c0, 0x5833, 0x2011, 0xac83, 0x2204, 0x8211, 0x220c, 0x1078,
-	0x254d, 0x00c0, 0x5833, 0x1078, 0x455c, 0x00c0, 0x5833, 0x6612,
-	0x6516, 0x6000, 0xd0ec, 0x00c0, 0x5833, 0x6204, 0xa294, 0xff00,
-	0x8217, 0xa286, 0x0006, 0x00c0, 0x5818, 0x0c7e, 0x1078, 0x76c7,
-	0x017f, 0x0040, 0x5835, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a,
-	0x7130, 0x6122, 0x2009, 0x0044, 0x1078, 0x775c, 0x0078, 0x5833,
-	0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f,
-	0x0004, 0x7120, 0x610a, 0xa286, 0x0004, 0x00c0, 0x582b, 0x6007,
-	0x0005, 0x0078, 0x582d, 0x6007, 0x0001, 0x6003, 0x0001, 0x1078,
-	0x5dd7, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x2001, 0xa70d, 0x2004,
-	0xd0ec, 0x0040, 0x583f, 0x2011, 0x8049, 0x1078, 0x361b, 0x0c7e,
-	0x1078, 0x9197, 0x017f, 0x0040, 0x5833, 0x611a, 0x601f, 0x0006,
-	0x7120, 0x610a, 0x7130, 0x6122, 0x6013, 0x0300, 0x6003, 0x0001,
-	0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x5833,
-	0x7110, 0xd1bc, 0x0040, 0x5870, 0x7020, 0x2060, 0xac84, 0x000f,
-	0x00c0, 0x5870, 0xac82, 0xae00, 0x0048, 0x5870, 0x6858, 0xac02,
-	0x00c8, 0x5870, 0x7124, 0x610a, 0x2009, 0x0045, 0x1078, 0x775c,
-	0x007c, 0x007e, 0x1078, 0x29bb, 0x007f, 0x00c0, 0x5887, 0x7110,
-	0xa18c, 0xff00, 0x810f, 0xa18e, 0x0000, 0x00c0, 0x5887, 0xa084,
-	0x000f, 0xa08a, 0x0006, 0x00c8, 0x5887, 0x1079, 0x5888, 0x007c,
-	0x588e, 0x588f, 0x588e, 0x588e, 0x58ff, 0x590e, 0x007c, 0x7110,
-	0xd1bc, 0x0040, 0x5897, 0x702c, 0xd084, 0x0040, 0x58fe, 0x700c,
-	0x7108, 0x1078, 0x254d, 0x00c0, 0x58fe, 0x1078, 0x455c, 0x00c0,
-	0x58fe, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x0040, 0x58c9,
-	0xa28c, 0x00ff, 0xa186, 0x0004, 0x0040, 0x58b2, 0xa186, 0x0006,
-	0x00c0, 0x58ef, 0x0c7e, 0x1078, 0x591d, 0x0c7f, 0x0040, 0x58fe,
-	0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f,
-	0x0002, 0x7120, 0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078,
-	0x58fe, 0xa28c, 0x00ff, 0xa186, 0x0006, 0x0040, 0x58de, 0xa186,
-	0x0004, 0x0040, 0x58de, 0xa294, 0xff00, 0x8217, 0xa286, 0x0004,
-	0x0040, 0x58de, 0xa286, 0x0006, 0x00c0, 0x58ef, 0x0c7e, 0x1078,
-	0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0005, 0x7120,
-	0x610a, 0x2009, 0x0088, 0x1078, 0x775c, 0x0078, 0x58fe, 0x0c7e,
-	0x1078, 0x76c7, 0x017f, 0x0040, 0x58fe, 0x611a, 0x601f, 0x0004,
-	0x7120, 0x610a, 0x2009, 0x0001, 0x1078, 0x775c, 0x007c, 0x7110,
-	0xd1bc, 0x0040, 0x590d, 0x1078, 0x591d, 0x0040, 0x590d, 0x7124,
-	0x610a, 0x2009, 0x0089, 0x1078, 0x775c, 0x007c, 0x7110, 0xd1bc,
-	0x0040, 0x591c, 0x1078, 0x591d, 0x0040, 0x591c, 0x7124, 0x610a,
-	0x2009, 0x008a, 0x1078, 0x775c, 0x007c, 0x7020, 0x2060, 0xac84,
-	0x000f, 0x00c0, 0x5930, 0xac82, 0xae00, 0x0048, 0x5930, 0x2001,
-	0xa716, 0x2004, 0xac02, 0x00c8, 0x5930, 0xa085, 0x0001, 0x007c,
-	0xa006, 0x0078, 0x592f, 0x7110, 0xd1bc, 0x00c0, 0x5949, 0x7024,
-	0x2060, 0xac84, 0x000f, 0x00c0, 0x5949, 0xac82, 0xae00, 0x0048,
-	0x5949, 0x6858, 0xac02, 0x00c8, 0x5949, 0x2009, 0x0051, 0x1078,
-	0x775c, 0x007c, 0x2071, 0xa9c4, 0x7003, 0x0003, 0x700f, 0x0361,
-	0xa006, 0x701a, 0x7012, 0x7017, 0xae00, 0x7007, 0x0000, 0x7026,
-	0x702b, 0x6e1c, 0x7032, 0x7037, 0x6e70, 0x703b, 0x0002, 0x703f,
-	0x0000, 0x7043, 0xffff, 0x7047, 0xffff, 0x007c, 0x2071, 0xa9c4,
-	0x00e0, 0x5a32, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x00c0,
-	0x59de, 0x700f, 0x0361, 0x7007, 0x0001, 0x127e, 0x2091, 0x8000,
-	0x7138, 0x8109, 0x713a, 0x00c0, 0x59dc, 0x703b, 0x0002, 0x2009,
-	0x0100, 0x2104, 0xa082, 0x0003, 0x00c8, 0x59dc, 0x703c, 0xa086,
-	0x0001, 0x00c0, 0x59b9, 0x0d7e, 0x2069, 0x0140, 0x6804, 0xa084,
-	0x4000, 0x0040, 0x5997, 0x6803, 0x1000, 0x0078, 0x599e, 0x6804,
-	0xa084, 0x1000, 0x0040, 0x599e, 0x6803, 0x0100, 0x6803, 0x0000,
-	0x703f, 0x0000, 0x2069, 0xa9b1, 0x6804, 0xa082, 0x0006, 0x00c0,
-	0x59ab, 0x6807, 0x0000, 0x6830, 0xa082, 0x0003, 0x00c0, 0x59b2,
-	0x6833, 0x0000, 0x1078, 0x62d1, 0x1078, 0x639b, 0x0d7f, 0x0078,
-	0x59dc, 0x0d7e, 0x2069, 0xa700, 0x6948, 0x6864, 0xa102, 0x00c8,
-	0x59db, 0x2069, 0xa9b1, 0x6804, 0xa086, 0x0000, 0x00c0, 0x59db,
-	0x6830, 0xa086, 0x0000, 0x00c0, 0x59db, 0x703f, 0x0001, 0x6807,
-	0x0006, 0x6833, 0x0003, 0x2069, 0x0100, 0x6830, 0x689e, 0x2069,
-	0x0140, 0x6803, 0x0600, 0x0d7f, 0x0078, 0x59e1, 0x127e, 0x2091,
-	0x8000, 0x7024, 0xa00d, 0x0040, 0x59f9, 0x7020, 0x8001, 0x7022,
-	0x00c0, 0x59f9, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8,
-	0x00c0, 0x59f4, 0x7028, 0x107a, 0x81ff, 0x00c0, 0x59f9, 0x7028,
-	0x107a, 0x7030, 0xa00d, 0x0040, 0x5a10, 0x702c, 0x8001, 0x702e,
-	0x00c0, 0x5a10, 0x702f, 0x0009, 0x8109, 0x7132, 0x0040, 0x5a0e,
-	0xa184, 0x007f, 0x1040, 0x6ea2, 0x0078, 0x5a10, 0x7034, 0x107a,
-	0x7040, 0xa005, 0x0040, 0x5a18, 0x0050, 0x5a18, 0x8001, 0x7042,
-	0x7044, 0xa005, 0x0040, 0x5a20, 0x0050, 0x5a20, 0x8001, 0x7046,
-	0x7018, 0xa00d, 0x0040, 0x5a31, 0x7008, 0x8001, 0x700a, 0x00c0,
-	0x5a31, 0x700b, 0x0009, 0x8109, 0x711a, 0x00c0, 0x5a31, 0x701c,
-	0x107a, 0x127f, 0x7004, 0x0079, 0x5a35, 0x5a5c, 0x5a5d, 0x5a79,
-	0x0e7e, 0x2071, 0xa9c4, 0x7018, 0xa005, 0x00c0, 0x5a43, 0x711a,
-	0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x0e7e, 0x007e, 0x2071,
-	0xa9c4, 0x701c, 0xa206, 0x00c0, 0x5a4f, 0x701a, 0x701e, 0x007f,
-	0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa9c4, 0x6088, 0xa102, 0x0048,
-	0x5a5a, 0x618a, 0x0e7f, 0x007c, 0x007c, 0x7110, 0x1078, 0x45c4,
-	0x00c0, 0x5a6f, 0x6088, 0x8001, 0x0048, 0x5a6f, 0x608a, 0x00c0,
-	0x5a6f, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x8108,
-	0xa182, 0x00ff, 0x0048, 0x5a77, 0xa00e, 0x7007, 0x0002, 0x7112,
-	0x007c, 0x7014, 0x2060, 0x127e, 0x2091, 0x8000, 0x603c, 0xa005,
-	0x0040, 0x5a88, 0x8001, 0x603e, 0x00c0, 0x5a88, 0x1078, 0x8fac,
-	0x6014, 0xa005, 0x0040, 0x5ab2, 0x8001, 0x6016, 0x00c0, 0x5ab2,
-	0x611c, 0xa186, 0x0003, 0x0040, 0x5a99, 0xa186, 0x0006, 0x00c0,
-	0x5ab0, 0x6010, 0x2068, 0x6854, 0xa08a, 0x199a, 0x0048, 0x5ab0,
-	0xa082, 0x1999, 0x6856, 0xa08a, 0x199a, 0x0048, 0x5aa9, 0x2001,
-	0x1999, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x0078, 0x5ab2,
-	0x1078, 0x8ace, 0x127f, 0xac88, 0x0010, 0x7116, 0x2001, 0xce00,
-	0xa102, 0x0048, 0x5abf, 0x7017, 0xae00, 0x7007, 0x0000, 0x007c,
-	0x0e7e, 0x2071, 0xa9c4, 0x7027, 0x07d0, 0x7023, 0x0009, 0x703b,
-	0x0002, 0x0e7f, 0x007c, 0x2001, 0xa9cd, 0x2003, 0x0000, 0x007c,
-	0x0e7e, 0x2071, 0xa9c4, 0x7132, 0x702f, 0x0009, 0x0e7f, 0x007c,
-	0x2011, 0xa9d0, 0x2013, 0x0000, 0x007c, 0x0e7e, 0x2071, 0xa9c4,
-	0x711a, 0x721e, 0x700b, 0x0009, 0x0e7f, 0x007c, 0x027e, 0x0e7e,
-	0x0f7e, 0x2079, 0xa700, 0x7a34, 0xd294, 0x0040, 0x5b15, 0x2071,
-	0xa9ac, 0x2e14, 0xa0fe, 0x0000, 0x0040, 0x5b02, 0xa0fe, 0x0001,
-	0x0040, 0x5b06, 0xa0fe, 0x0002, 0x00c0, 0x5b11, 0xa292, 0x0085,
-	0x0078, 0x5b08, 0xa292, 0x0005, 0x0078, 0x5b08, 0xa292, 0x0002,
-	0x2272, 0x0040, 0x5b0d, 0x00c8, 0x5b15, 0x2011, 0x8037, 0x1078,
-	0x361b, 0x2011, 0xa9ab, 0x2204, 0x2072, 0x0f7f, 0x0e7f, 0x027f,
-	0x007c, 0x0c7e, 0x2061, 0xaa33, 0x0c7f, 0x007c, 0xa184, 0x000f,
-	0x8003, 0x8003, 0x8003, 0xa080, 0xaa33, 0x2060, 0x007c, 0x6854,
-	0xa08a, 0x199a, 0x0048, 0x5b2e, 0x2001, 0x1999, 0xa005, 0x00c0,
-	0x5b3d, 0x0c7e, 0x2061, 0xaa33, 0x6014, 0x0c7f, 0xa005, 0x00c0,
-	0x5b42, 0x2001, 0x001e, 0x0078, 0x5b42, 0xa08e, 0xffff, 0x00c0,
-	0x5b42, 0xa006, 0x8003, 0x800b, 0x810b, 0xa108, 0x6116, 0x684c,
-	0xa08c, 0x00c0, 0xa18e, 0x00c0, 0x0040, 0x5b9e, 0xd0b4, 0x00c0,
-	0x5b59, 0xd0bc, 0x00c0, 0x5b8b, 0x2009, 0x0006, 0x1078, 0x5bc3,
-	0x007c, 0xd0fc, 0x0040, 0x5b64, 0xa084, 0x0003, 0x0040, 0x5b64,
-	0xa086, 0x0003, 0x00c0, 0x5bbc, 0x6024, 0xd0d4, 0x0040, 0x5b6e,
-	0xc0d4, 0x6026, 0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xa774,
-	0x2104, 0xd084, 0x0040, 0x5b83, 0x6118, 0xa188, 0x0027, 0x2104,
-	0xd08c, 0x00c0, 0x5b83, 0x87ff, 0x00c0, 0x5b82, 0x2009, 0x0042,
-	0x1078, 0x775c, 0x007c, 0x87ff, 0x00c0, 0x5b8a, 0x2009, 0x0043,
-	0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040, 0x5b96, 0xa084, 0x0003,
-	0x0040, 0x5b96, 0xa086, 0x0003, 0x00c0, 0x5bbc, 0x87ff, 0x00c0,
-	0x5b9d, 0x2009, 0x0042, 0x1078, 0x775c, 0x007c, 0xd0fc, 0x0040,
-	0x5baf, 0xa084, 0x0003, 0xa08e, 0x0002, 0x0040, 0x5bb3, 0x87ff,
-	0x00c0, 0x5bae, 0x2009, 0x0041, 0x1078, 0x775c, 0x007c, 0x1078,
-	0x5bc1, 0x0078, 0x5bae, 0x87ff, 0x00c0, 0x5bae, 0x2009, 0x0043,
-	0x1078, 0x775c, 0x0078, 0x5bae, 0x2009, 0x0004, 0x1078, 0x5bc3,
-	0x007c, 0x2009, 0x0001, 0x0d7e, 0x6010, 0xa0ec, 0xf000, 0x0040,
-	0x5bef, 0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x00c0,
-	0x5be5, 0x694c, 0xa18c, 0x8100, 0xa18e, 0x8100, 0x00c0, 0x5be5,
-	0x0c7e, 0x2061, 0xaa33, 0x6200, 0xd28c, 0x00c0, 0x5be4, 0x6204,
-	0x8210, 0x0048, 0x5be4, 0x6206, 0x0c7f, 0x1078, 0x4a73, 0x6010,
-	0xa06d, 0x077e, 0x2039, 0x0000, 0x10c0, 0x5b27, 0x077f, 0x0d7f,
-	0x007c, 0x157e, 0x0c7e, 0x2061, 0xaa33, 0x6000, 0x81ff, 0x0040,
-	0x5bfc, 0xa205, 0x0078, 0x5bfd, 0xa204, 0x6002, 0x0c7f, 0x157f,
-	0x007c, 0x6800, 0xd08c, 0x00c0, 0x5c0d, 0x6808, 0xa005, 0x0040,
-	0x5c0d, 0x8001, 0x680a, 0xa085, 0x0001, 0x007c, 0x20a9, 0x0010,
-	0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x5c17, 0xa200, 0x00f0,
-	0x5c12, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005,
-	0x0040, 0x5c3d, 0xa11a, 0x00c8, 0x5c3d, 0x8213, 0x818d, 0x0048,
-	0x5c30, 0xa11a, 0x00c8, 0x5c31, 0x00f0, 0x5c25, 0x0078, 0x5c35,
-	0xa11a, 0x2308, 0x8210, 0x00f0, 0x5c25, 0x007e, 0x3200, 0xa084,
-	0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085,
-	0x0800, 0x0078, 0x5c39, 0x127e, 0x2091, 0x2200, 0x2079, 0xa9b1,
-	0x127f, 0x0d7e, 0x2069, 0xa9b1, 0x6803, 0x0005, 0x2069, 0x0004,
-	0x2d04, 0xa085, 0x8001, 0x206a, 0x0d7f, 0x007c, 0x0c7e, 0x6027,
-	0x0001, 0x7804, 0xa084, 0x0007, 0x0079, 0x5c5e, 0x5c68, 0x5c8d,
-	0x5ce8, 0x5c6e, 0x5c8d, 0x5c68, 0x5c66, 0x5c66, 0x1078, 0x1332,
-	0x1078, 0x5acb, 0x1078, 0x62d1, 0x0c7f, 0x007c, 0x62c0, 0x82ff,
-	0x00c0, 0x5c74, 0x0c7f, 0x007c, 0x2011, 0x41dc, 0x1078, 0x5a45,
-	0x7828, 0xa092, 0x00c8, 0x00c8, 0x5c83, 0x8000, 0x782a, 0x1078,
-	0x421b, 0x0078, 0x5c72, 0x1078, 0x41dc, 0x7807, 0x0003, 0x7827,
-	0x0000, 0x782b, 0x0000, 0x0078, 0x5c72, 0x1078, 0x5acb, 0x3c00,
-	0x007e, 0x2011, 0x0209, 0x20e1, 0x4000, 0x2214, 0x007f, 0x20e0,
-	0x82ff, 0x0040, 0x5cab, 0x62c0, 0x82ff, 0x00c0, 0x5cab, 0x782b,
-	0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013, 0x1078,
-	0x775c, 0x0c7f, 0x007c, 0x3900, 0xa082, 0xaae3, 0x00c8, 0x5cb2,
-	0x1078, 0x747a, 0x0c7e, 0x7824, 0xa065, 0x1040, 0x1332, 0x7804,
-	0xa086, 0x0004, 0x0040, 0x5d2d, 0x7828, 0xa092, 0x2710, 0x00c8,
-	0x5cc8, 0x8000, 0x782a, 0x0c7f, 0x1078, 0x6e01, 0x0078, 0x5ca9,
-	0x6104, 0xa186, 0x0003, 0x00c0, 0x5cdf, 0x0e7e, 0x2071, 0xa700,
-	0x70d8, 0x0e7f, 0xd08c, 0x0040, 0x5cdf, 0x0c7e, 0x0e7e, 0x2061,
-	0x0100, 0x2071, 0xa700, 0x1078, 0x4224, 0x0e7f, 0x0c7f, 0x1078,
-	0xa5d4, 0x2009, 0x0014, 0x1078, 0x775c, 0x0c7f, 0x0078, 0x5ca9,
-	0x2001, 0xa9cd, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x00c0, 0x5cfc,
-	0x782b, 0x0000, 0x7824, 0xa065, 0x1040, 0x1332, 0x2009, 0x0013,
-	0x1078, 0x77b3, 0x0c7f, 0x007c, 0x0c7e, 0x0d7e, 0x3900, 0xa082,
-	0xaae3, 0x00c8, 0x5d05, 0x1078, 0x747a, 0x7824, 0xa005, 0x1040,
-	0x1332, 0x781c, 0xa06d, 0x1040, 0x1332, 0x6800, 0xc0dc, 0x6802,
-	0x7924, 0x2160, 0x1078, 0x772d, 0x693c, 0x81ff, 0x1040, 0x1332,
-	0x8109, 0x693e, 0x6854, 0xa015, 0x0040, 0x5d21, 0x7a1e, 0x0078,
-	0x5d23, 0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x0d7f,
-	0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5cfa, 0x6104, 0xa186, 0x0002,
-	0x0040, 0x5d38, 0xa186, 0x0004, 0x0040, 0x5d38, 0x0078, 0x5cbc,
-	0x7808, 0xac06, 0x0040, 0x5cbc, 0x1078, 0x61cd, 0x1078, 0x5dd7,
-	0x0c7f, 0x1078, 0x62d1, 0x0078, 0x5ca9, 0x0c7e, 0x6027, 0x0002,
-	0x62c8, 0x82ff, 0x00c0, 0x5d61, 0x62c4, 0x82ff, 0x00c0, 0x5d61,
-	0x793c, 0xa1e5, 0x0000, 0x0040, 0x5d5b, 0x2009, 0x0049, 0x1078,
-	0x775c, 0x0c7f, 0x007c, 0x2011, 0xa9d0, 0x2013, 0x0000, 0x0078,
-	0x5d59, 0x3908, 0xa192, 0xaae3, 0x00c8, 0x5d68, 0x1078, 0x747a,
-	0x6017, 0x0010, 0x793c, 0x81ff, 0x0040, 0x5d5b, 0x7944, 0xa192,
-	0x7530, 0x00c8, 0x5d85, 0x8108, 0x7946, 0x793c, 0xa188, 0x0007,
-	0x210c, 0xa18e, 0x0006, 0x00c0, 0x5d81, 0x6017, 0x0012, 0x0078,
-	0x5d59, 0x6017, 0x0016, 0x0078, 0x5d59, 0x7848, 0xc085, 0x784a,
-	0x0078, 0x5d59, 0x007e, 0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000,
-	0x600f, 0x0000, 0x2c08, 0x2061, 0xa9b1, 0x6020, 0x8000, 0x6022,
-	0x6010, 0xa005, 0x0040, 0x5da5, 0xa080, 0x0003, 0x2102, 0x6112,
-	0x127f, 0x0c7f, 0x017f, 0x007f, 0x007c, 0x6116, 0x6112, 0x0078,
-	0x5da0, 0x0d7e, 0x2069, 0xa9b1, 0x6000, 0xd0d4, 0x0040, 0x5dbe,
-	0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x00c0, 0x5db9, 0x2c00,
-	0x681e, 0x6804, 0xa084, 0x0007, 0x0079, 0x62d9, 0xc0d5, 0x6002,
-	0x6818, 0xa005, 0x0040, 0x5dd0, 0x6056, 0x605b, 0x0000, 0x007e,
-	0x2c00, 0x681a, 0x0d7f, 0x685a, 0x2069, 0xa9b1, 0x0078, 0x5db0,
-	0x6056, 0x605a, 0x2c00, 0x681a, 0x681e, 0x0078, 0x5db0, 0x007e,
-	0x017e, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08,
-	0x2061, 0xa9b1, 0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0040,
-	0x5df2, 0xa080, 0x0003, 0x2102, 0x610a, 0x127f, 0x0c7f, 0x017f,
-	0x007f, 0x007c, 0x610e, 0x610a, 0x0078, 0x5ded, 0x0c7e, 0x600f,
-	0x0000, 0x2c08, 0x2061, 0xa9b1, 0x6034, 0xa005, 0x0040, 0x5e06,
-	0xa080, 0x0003, 0x2102, 0x6136, 0x0c7f, 0x007c, 0x613a, 0x6136,
-	0x0078, 0x5e04, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x057e,
-	0x037e, 0x027e, 0x017e, 0x007e, 0x127e, 0xa02e, 0x2071, 0xa9b1,
-	0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0040, 0x5e8c,
-	0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x5e87, 0x87ff,
-	0x0040, 0x5e2e, 0x6020, 0xa106, 0x00c0, 0x5e87, 0x703c, 0xac06,
-	0x00c0, 0x5e44, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033,
-	0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b,
-	0x0000, 0x037f, 0x2029, 0x0001, 0x7038, 0xac36, 0x00c0, 0x5e4a,
-	0x660c, 0x763a, 0x7034, 0xac36, 0x00c0, 0x5e58, 0x2c00, 0xaf36,
-	0x0040, 0x5e56, 0x2f00, 0x7036, 0x0078, 0x5e58, 0x7037, 0x0000,
-	0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040, 0x5e61, 0x7e0e, 0x0078,
-	0x5e62, 0x2678, 0x600f, 0x0000, 0x1078, 0x8d16, 0x0040, 0x5e82,
-	0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5e9d, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x077e, 0x1078,
-	0x8f8d, 0x1078, 0xa4f2, 0x1078, 0x4a73, 0x077f, 0x037f, 0x017f,
-	0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x5e1d, 0x2c78,
-	0x600c, 0x2060, 0x0078, 0x5e1d, 0x85ff, 0x0040, 0x5e91, 0x1078,
-	0x639b, 0x127f, 0x007f, 0x017f, 0x027f, 0x037f, 0x057f, 0x067f,
-	0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086, 0x0006,
-	0x00c0, 0x5e6f, 0x017e, 0x037e, 0x077e, 0x1078, 0xa4f2, 0x1078,
-	0xa1da, 0x077f, 0x037f, 0x017f, 0x0078, 0x5e82, 0x007e, 0x067e,
-	0x0c7e, 0x0d7e, 0x0f7e, 0x2031, 0x0000, 0x127e, 0x2091, 0x8000,
-	0x2079, 0xa9b1, 0x7838, 0xa065, 0x0040, 0x5eef, 0x600c, 0x007e,
-	0x600f, 0x0000, 0x783c, 0xac06, 0x00c0, 0x5ed6, 0x037e, 0x2019,
-	0x0001, 0x1078, 0x7058, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843,
-	0x0000, 0x7847, 0x0000, 0x784b, 0x0000, 0x037f, 0x1078, 0x8d16,
-	0x0040, 0x5eea, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x00c0,
-	0x5ef8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73,
-	0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x007f, 0x0078, 0x5ebb, 0x7e3a,
-	0x7e36, 0x127f, 0x0f7f, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c,
-	0x601c, 0xa086, 0x0006, 0x00c0, 0x5ee1, 0x1078, 0xa1da, 0x0078,
-	0x5eea, 0x017e, 0x027e, 0x087e, 0x2041, 0x0000, 0x1078, 0x5f1b,
-	0x1078, 0x5fdb, 0x087f, 0x027f, 0x017f, 0x007c, 0x0f7e, 0x127e,
-	0x2079, 0xa9b1, 0x2091, 0x8000, 0x1078, 0x6076, 0x1078, 0x60ec,
-	0x127f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e,
-	0x017e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x7614,
-	0x2660, 0x2678, 0x8cff, 0x0040, 0x5fb5, 0x6018, 0xa080, 0x0028,
-	0x2004, 0xa206, 0x00c0, 0x5fb0, 0x88ff, 0x0040, 0x5f3b, 0x6020,
-	0xa106, 0x00c0, 0x5fb0, 0x7024, 0xac06, 0x00c0, 0x5f6b, 0x2069,
-	0x0100, 0x68c0, 0xa005, 0x0040, 0x5f66, 0x1078, 0x5acb, 0x1078,
-	0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000, 0x037e,
-	0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x5f5b, 0x6803,
-	0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040,
-	0x5f63, 0x6827, 0x0001, 0x037f, 0x0078, 0x5f6b, 0x6003, 0x0009,
-	0x630a, 0x0078, 0x5fb0, 0x7014, 0xac36, 0x00c0, 0x5f71, 0x660c,
-	0x7616, 0x7010, 0xac36, 0x00c0, 0x5f7f, 0x2c00, 0xaf36, 0x0040,
-	0x5f7d, 0x2f00, 0x7012, 0x0078, 0x5f7f, 0x7013, 0x0000, 0x660c,
-	0x067e, 0x2c00, 0xaf06, 0x0040, 0x5f88, 0x7e0e, 0x0078, 0x5f89,
-	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040,
-	0x5fa9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x5fbe, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x017e, 0x037e, 0x087e, 0x1078, 0x8f8d,
-	0x1078, 0xa4f2, 0x1078, 0x4a73, 0x087f, 0x037f, 0x017f, 0x1078,
-	0x8ec9, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x5f2a,
-	0x2c78, 0x600c, 0x2060, 0x0078, 0x5f2a, 0x127f, 0x007f, 0x017f,
-	0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x601c, 0xa086,
-	0x0006, 0x00c0, 0x5fcf, 0x017e, 0x037e, 0x087e, 0x1078, 0xa4f2,
-	0x1078, 0xa1da, 0x087f, 0x037f, 0x017f, 0x0078, 0x5fa9, 0x601c,
-	0xa086, 0x0002, 0x00c0, 0x5fa9, 0x6004, 0xa086, 0x0085, 0x0040,
-	0x5f96, 0x0078, 0x5fa9, 0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000,
-	0xa280, 0xa835, 0x2004, 0xa065, 0x0040, 0x6072, 0x0f7e, 0x0e7e,
-	0x0d7e, 0x067e, 0x2071, 0xa9b1, 0x6654, 0x7018, 0xac06, 0x00c0,
-	0x5ff2, 0x761a, 0x701c, 0xac06, 0x00c0, 0x5ffe, 0x86ff, 0x00c0,
-	0x5ffd, 0x7018, 0x701e, 0x0078, 0x5ffe, 0x761e, 0x6058, 0xa07d,
-	0x0040, 0x6003, 0x7e56, 0xa6ed, 0x0000, 0x0040, 0x6009, 0x2f00,
-	0x685a, 0x6057, 0x0000, 0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc,
-	0x6002, 0x1078, 0x44d3, 0x0040, 0x606e, 0x7624, 0x86ff, 0x0040,
-	0x605c, 0xa680, 0x0004, 0x2004, 0xad06, 0x00c0, 0x605c, 0x0d7e,
-	0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x6053, 0x1078, 0x5acb,
-	0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7027, 0x0000,
-	0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x603c,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0040, 0x6044, 0x6827, 0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c,
-	0xa005, 0x0040, 0x604d, 0x8001, 0x603e, 0x2660, 0x1078, 0x8ed6,
-	0x0c7f, 0x0078, 0x605c, 0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009,
-	0x630a, 0x0c7f, 0x0078, 0x6011, 0x8dff, 0x0040, 0x606a, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f8d, 0x1078, 0xa4f2,
-	0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x6011, 0x067f, 0x0d7f,
-	0x0e7f, 0x0f7f, 0x127f, 0x007f, 0x0c7f, 0x007c, 0x007e, 0x067e,
-	0x0c7e, 0x0d7e, 0x2031, 0x0000, 0x7814, 0xa065, 0x0040, 0x60d0,
-	0x600c, 0x007e, 0x600f, 0x0000, 0x7824, 0xac06, 0x00c0, 0x60b5,
-	0x2069, 0x0100, 0x68c0, 0xa005, 0x0040, 0x60af, 0x1078, 0x5acb,
-	0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378, 0x7827, 0x0000,
-	0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0040, 0x60a4,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0040, 0x60ac, 0x6827, 0x0001, 0x037f, 0x0078, 0x60b5, 0x6003,
-	0x0009, 0x630a, 0x2c30, 0x0078, 0x60cd, 0x6010, 0x2068, 0x1078,
-	0x8d16, 0x0040, 0x60c9, 0x601c, 0xa086, 0x0003, 0x00c0, 0x60d7,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078,
-	0x8ec9, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x007f, 0x0078, 0x607d,
-	0x7e16, 0x7e12, 0x0d7f, 0x0c7f, 0x067f, 0x007f, 0x007c, 0x601c,
-	0xa086, 0x0006, 0x00c0, 0x60e0, 0x1078, 0xa1da, 0x0078, 0x60c9,
-	0x601c, 0xa086, 0x0002, 0x00c0, 0x60c9, 0x6004, 0xa086, 0x0085,
-	0x0040, 0x60c0, 0x0078, 0x60c9, 0x007e, 0x067e, 0x0c7e, 0x0d7e,
-	0x7818, 0xa065, 0x0040, 0x615a, 0x6054, 0x007e, 0x6057, 0x0000,
-	0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x1078, 0x44d3,
-	0x0040, 0x6157, 0x7e24, 0x86ff, 0x0040, 0x6149, 0xa680, 0x0004,
-	0x2004, 0xad06, 0x00c0, 0x6149, 0x0d7e, 0x2069, 0x0100, 0x68c0,
-	0xa005, 0x0040, 0x6140, 0x1078, 0x5acb, 0x1078, 0x6e0f, 0x68c3,
-	0x0000, 0x1078, 0x7378, 0x7827, 0x0000, 0x037e, 0x2069, 0x0140,
-	0x6b04, 0xa384, 0x1000, 0x0040, 0x6129, 0x6803, 0x0100, 0x6803,
-	0x0000, 0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x6131, 0x6827,
-	0x0001, 0x037f, 0x0d7f, 0x0c7e, 0x603c, 0xa005, 0x0040, 0x613a,
-	0x8001, 0x603e, 0x2660, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x6149,
-	0x0d7f, 0x0c7e, 0x2660, 0x6003, 0x0009, 0x630a, 0x0c7f, 0x0078,
-	0x60fe, 0x8dff, 0x0040, 0x6153, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x4a73, 0x1078, 0x7233, 0x0078, 0x60fe, 0x007f,
-	0x0078, 0x60f1, 0x781e, 0x781a, 0x0d7f, 0x0c7f, 0x067f, 0x007f,
-	0x007c, 0x0e7e, 0x0d7e, 0x067e, 0x6000, 0xd0dc, 0x0040, 0x6181,
-	0x604c, 0xa06d, 0x0040, 0x6181, 0x6848, 0xa606, 0x00c0, 0x6181,
-	0x2071, 0xa9b1, 0x7024, 0xa035, 0x0040, 0x6181, 0xa080, 0x0004,
-	0x2004, 0xad06, 0x00c0, 0x6181, 0x6000, 0xc0dc, 0x6002, 0x1078,
-	0x6185, 0x067f, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x2079, 0x0100,
-	0x78c0, 0xa005, 0x00c0, 0x6194, 0x0c7e, 0x2660, 0x6003, 0x0009,
-	0x630a, 0x0c7f, 0x0078, 0x61cb, 0x1078, 0x6e0f, 0x78c3, 0x0000,
-	0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2079, 0x0140, 0x7b04,
-	0xa384, 0x1000, 0x0040, 0x61a8, 0x7803, 0x0100, 0x7803, 0x0000,
-	0x2079, 0x0100, 0x7824, 0xd084, 0x0040, 0x61b0, 0x7827, 0x0001,
-	0x1078, 0x7378, 0x037f, 0x1078, 0x44d3, 0x0c7e, 0x603c, 0xa005,
-	0x0040, 0x61bc, 0x8001, 0x603e, 0x2660, 0x1078, 0x772d, 0x0c7f,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x8f8d, 0x1078,
-	0x4a73, 0x1078, 0x7233, 0x0f7f, 0x007c, 0x0e7e, 0x0c7e, 0x2071,
-	0xa9b1, 0x7004, 0xa084, 0x0007, 0x0079, 0x61d6, 0x61e0, 0x61e3,
-	0x61fc, 0x6218, 0x6262, 0x61e0, 0x61e0, 0x61de, 0x1078, 0x1332,
-	0x0c7f, 0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x61f1, 0x7020,
-	0x8001, 0x7022, 0x600c, 0xa015, 0x0040, 0x61f8, 0x7216, 0x600f,
-	0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c,
-	0x7216, 0x7212, 0x0078, 0x61f1, 0x6018, 0x2060, 0x1078, 0x44d3,
-	0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0040, 0x620d,
-	0x6054, 0xa015, 0x0040, 0x6214, 0x721e, 0x7007, 0x0000, 0x7027,
-	0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x7218, 0x721e, 0x0078, 0x620d,
-	0x7024, 0xa065, 0x0040, 0x625f, 0x700c, 0xac06, 0x00c0, 0x622f,
-	0x1078, 0x7233, 0x600c, 0xa015, 0x0040, 0x622b, 0x720e, 0x600f,
-	0x0000, 0x0078, 0x625d, 0x720e, 0x720a, 0x0078, 0x625d, 0x7014,
-	0xac06, 0x00c0, 0x6242, 0x1078, 0x7233, 0x600c, 0xa015, 0x0040,
-	0x623e, 0x7216, 0x600f, 0x0000, 0x0078, 0x625d, 0x7216, 0x7212,
-	0x0078, 0x625d, 0x601c, 0xa086, 0x0003, 0x00c0, 0x625d, 0x6018,
-	0x2060, 0x1078, 0x44d3, 0x6000, 0xc0dc, 0x6002, 0x1078, 0x7233,
-	0x701c, 0xa065, 0x0040, 0x625d, 0x6054, 0xa015, 0x0040, 0x625b,
-	0x721e, 0x0078, 0x625d, 0x7218, 0x721e, 0x7027, 0x0000, 0x0c7f,
-	0x0e7f, 0x007c, 0x7024, 0xa065, 0x0040, 0x626f, 0x1078, 0x7233,
-	0x600c, 0xa015, 0x0040, 0x6276, 0x720e, 0x600f, 0x0000, 0x1078,
-	0x7378, 0x7027, 0x0000, 0x0c7f, 0x0e7f, 0x007c, 0x720e, 0x720a,
-	0x0078, 0x626f, 0x0d7e, 0x2069, 0xa9b1, 0x6830, 0xa084, 0x0003,
-	0x0079, 0x6282, 0x6288, 0x628a, 0x62b4, 0x6288, 0x1078, 0x1332,
-	0x0d7f, 0x007c, 0x0c7e, 0x6840, 0xa086, 0x0001, 0x0040, 0x62aa,
-	0x683c, 0xa065, 0x0040, 0x629b, 0x600c, 0xa015, 0x0040, 0x62a6,
-	0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x2011,
-	0xa9d0, 0x2013, 0x0000, 0x0c7f, 0x0d7f, 0x007c, 0x683a, 0x6836,
-	0x0078, 0x629b, 0x6843, 0x0000, 0x6838, 0xa065, 0x0040, 0x629b,
-	0x6003, 0x0003, 0x0078, 0x629b, 0x0c7e, 0x6843, 0x0000, 0x6847,
-	0x0000, 0x684b, 0x0000, 0x683c, 0xa065, 0x0040, 0x62ce, 0x600c,
-	0xa015, 0x0040, 0x62ca, 0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000,
-	0x0078, 0x62ce, 0x683f, 0x0000, 0x683a, 0x6836, 0x0c7f, 0x0d7f,
-	0x007c, 0x0d7e, 0x2069, 0xa9b1, 0x6804, 0xa084, 0x0007, 0x0079,
-	0x62d9, 0x62e3, 0x638a, 0x638a, 0x638a, 0x638a, 0x638c, 0x638a,
-	0x62e1, 0x1078, 0x1332, 0x6820, 0xa005, 0x00c0, 0x62e9, 0x0d7f,
-	0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040, 0x62f8, 0x6807, 0x0004,
-	0x6826, 0x682b, 0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c,
-	0x6814, 0xa065, 0x0040, 0x6306, 0x6807, 0x0001, 0x6826, 0x682b,
-	0x0000, 0x1078, 0x63d4, 0x0c7f, 0x0d7f, 0x007c, 0x0e7e, 0x037e,
-	0x6a1c, 0xa2f5, 0x0000, 0x0040, 0x6385, 0x704c, 0xa00d, 0x0040,
-	0x6315, 0x7088, 0xa005, 0x0040, 0x632d, 0x7054, 0xa075, 0x0040,
-	0x631e, 0xa20e, 0x0040, 0x6385, 0x0078, 0x6323, 0x6818, 0xa20e,
-	0x0040, 0x6385, 0x2070, 0x704c, 0xa00d, 0x0040, 0x6315, 0x7088,
-	0xa005, 0x00c0, 0x6315, 0x2e00, 0x681e, 0x733c, 0x7038, 0xa302,
-	0x00c8, 0x6315, 0x1078, 0x76fc, 0x0040, 0x6385, 0x8318, 0x733e,
-	0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084, 0x00ff,
-	0x6032, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015, 0x2004,
-	0xa08a, 0x199a, 0x0048, 0x634e, 0x2001, 0x1999, 0x8003, 0x801b,
-	0x831b, 0xa318, 0x6316, 0x037f, 0x0f7e, 0x2c78, 0x71a0, 0xd1bc,
-	0x0040, 0x6367, 0x7100, 0xd1f4, 0x0040, 0x6363, 0x7114, 0xa18c,
-	0x00ff, 0x0078, 0x636c, 0x2009, 0x0000, 0x0078, 0x636c, 0xa1e0,
-	0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a, 0x1078,
-	0x6965, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18, 0x6b26,
-	0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807, 0x0040,
-	0x0f7f, 0x0e7f, 0x0c7f, 0x0d7f, 0x007c, 0x037f, 0x0e7f, 0x0c7f,
-	0x0078, 0x6383, 0x0d7f, 0x007c, 0x0c7e, 0x680c, 0xa065, 0x0040,
-	0x6398, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x1078, 0x63d4,
-	0x0c7f, 0x0d7f, 0x007c, 0x0f7e, 0x0d7e, 0x2069, 0xa9b1, 0x6830,
-	0xa086, 0x0000, 0x00c0, 0x63bb, 0x6838, 0xa07d, 0x0040, 0x63bb,
-	0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x127e,
-	0x0f7e, 0x2091, 0x2200, 0x027f, 0x1078, 0x1d6d, 0x00c0, 0x63be,
-	0x127f, 0x1078, 0x6cb3, 0x0d7f, 0x0f7f, 0x007c, 0x127f, 0x6843,
-	0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0040, 0x63d0, 0x6a3a,
-	0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0078, 0x63bb,
-	0x683a, 0x6836, 0x0078, 0x63ca, 0x601c, 0xa084, 0x000f, 0x1079,
-	0x63da, 0x007c, 0x63e3, 0x63e8, 0x6809, 0x6922, 0x63e8, 0x6809,
-	0x6922, 0x63e3, 0x63e8, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c,
-	0x157e, 0x137e, 0x147e, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0044,
-	0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc, 0x0040, 0x6405,
-	0x7900, 0xd1f4, 0x0040, 0x6401, 0x7914, 0xa18c, 0x00ff, 0x0078,
-	0x640a, 0x2009, 0x0000, 0x0078, 0x640a, 0xa1f8, 0x29c0, 0x2f0c,
-	0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040,
-	0x00c8, 0x645c, 0x1079, 0x641a, 0x0f7f, 0x0c7f, 0x147f, 0x137f,
-	0x157f, 0x007c, 0x64c2, 0x650a, 0x6532, 0x65cd, 0x65fd, 0x6605,
-	0x662c, 0x663d, 0x664e, 0x6656, 0x666e, 0x6656, 0x66d9, 0x663d,
-	0x66fa, 0x6702, 0x664e, 0x6702, 0x6713, 0x645a, 0x645a, 0x645a,
-	0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a, 0x645a,
-	0x6eef, 0x6f14, 0x6f29, 0x6f4c, 0x6f6d, 0x662c, 0x645a, 0x662c,
-	0x6656, 0x645a, 0x6532, 0x65cd, 0x645a, 0x749c, 0x6656, 0x645a,
-	0x74bc, 0x6656, 0x645a, 0x645a, 0x64bd, 0x646b, 0x645a, 0x74e1,
-	0x7558, 0x7640, 0x645a, 0x7651, 0x6626, 0x766d, 0x645a, 0x6f82,
-	0x645a, 0x645a, 0x1078, 0x1332, 0x2100, 0x1079, 0x6465, 0x0f7f,
-	0x0c7f, 0x147f, 0x137f, 0x157f, 0x007c, 0x6469, 0x6469, 0x6469,
-	0x649f, 0x1078, 0x1332, 0x0d7e, 0x20a1, 0x020b, 0x1078, 0x6731,
-	0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3, 0x0018, 0x20a3, 0x0800,
-	0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb, 0x0d7f, 0x007c,
-	0x0d7e, 0x7818, 0x2068, 0x68a0, 0xa082, 0x007e, 0x0048, 0x649c,
-	0xa085, 0x0001, 0x0d7f, 0x007c, 0xa006, 0x0078, 0x649a, 0x0d7e,
-	0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500, 0x20a3, 0x0000,
-	0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2, 0x680c, 0x20a2, 0x6810,
-	0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2, 0x681c, 0x20a2, 0x60c3,
-	0x0010, 0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x6030, 0x609a, 0x1078,
-	0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x5200,
-	0x20a3, 0x0000, 0x0d7e, 0x2069, 0xa752, 0x6804, 0xd084, 0x0040,
-	0x64dc, 0x6828, 0x20a3, 0x0000, 0x017e, 0x1078, 0x2564, 0x21a2,
-	0x017f, 0x0d7f, 0x0078, 0x64e1, 0x0d7f, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x20a9, 0x0004,
-	0x2099, 0xa701, 0x53a6, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082,
-	0x007f, 0x0048, 0x64fb, 0x2001, 0xa71b, 0x20a6, 0x2001, 0xa71c,
-	0x20a6, 0x0078, 0x6501, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff,
-	0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078,
-	0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x0500,
-	0x20a3, 0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f,
-	0x0048, 0x6522, 0x2001, 0xa71b, 0x20a6, 0x2001, 0xa71c, 0x20a6,
-	0x0078, 0x6528, 0x20a3, 0x0000, 0x6030, 0xa084, 0x00ff, 0x20a2,
-	0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x60c3, 0x0010, 0x1078,
-	0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x6731, 0x0c7e, 0x7818,
-	0x2060, 0x2001, 0x0000, 0x1078, 0x4972, 0x0c7f, 0x7818, 0xa080,
-	0x0028, 0x2004, 0xa086, 0x007e, 0x00c0, 0x654d, 0x20a3, 0x0400,
-	0x620c, 0xc2b4, 0x620e, 0x0078, 0x654f, 0x20a3, 0x0300, 0x20a3,
-	0x0000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x00c0,
-	0x659c, 0x2099, 0xa98d, 0x33a6, 0x9398, 0x33a6, 0x9398, 0x3304,
-	0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9, 0x0004, 0x2099,
-	0xa705, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xa701, 0x53a6, 0x20a9,
-	0x0010, 0x20a3, 0x0000, 0x00f0, 0x6579, 0x2099, 0xa995, 0x3304,
-	0xc0dd, 0x20a2, 0x2001, 0xa772, 0x2004, 0xd0e4, 0x0040, 0x6594,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6,
-	0x20a9, 0x0004, 0x0078, 0x6596, 0x20a9, 0x0007, 0x20a3, 0x0000,
-	0x00f0, 0x6596, 0x0078, 0x65bc, 0x2099, 0xa98d, 0x20a9, 0x0008,
-	0x53a6, 0x20a9, 0x0004, 0x2099, 0xa705, 0x53a6, 0x20a9, 0x0004,
-	0x2099, 0xa701, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0,
-	0x65ad, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x00f0, 0x65b3, 0x2099,
-	0xa995, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000,
-	0x00f0, 0x65be, 0x20a9, 0x000a, 0x20a3, 0x0000, 0x00f0, 0x65c4,
-	0x60c3, 0x0074, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x6731, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x20a3,
-	0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e,
-	0x2079, 0xa752, 0x7904, 0x0f7f, 0xd1ac, 0x00c0, 0x65e9, 0xa085,
-	0x0020, 0xd1a4, 0x0040, 0x65ee, 0xa085, 0x0010, 0xa085, 0x0002,
-	0x0d7e, 0x0078, 0x66b7, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x6731, 0x20a3, 0x5000, 0x0078, 0x654f, 0x20a1, 0x020b, 0x1078,
-	0x6731, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b,
-	0x1078, 0x67b9, 0x0078, 0x6630, 0x20a1, 0x020b, 0x1078, 0x67c2,
-	0x20a3, 0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0004, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3,
-	0x2a00, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b,
-	0x1078, 0x67c2, 0x20a3, 0x0200, 0x0078, 0x654f, 0x20a1, 0x020b,
-	0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005,
-	0x0040, 0x6665, 0x20a2, 0x0078, 0x6667, 0x20a3, 0x0003, 0x7810,
-	0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x0d7e, 0x20a1,
-	0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3,
-	0x0800, 0x7818, 0x2068, 0x6894, 0xa086, 0x0014, 0x00c0, 0x6694,
-	0x6998, 0xa184, 0xc000, 0x00c0, 0x6690, 0xd1ec, 0x0040, 0x668c,
-	0x20a3, 0x2100, 0x0078, 0x6696, 0x20a3, 0x0100, 0x0078, 0x6696,
-	0x20a3, 0x0400, 0x0078, 0x6696, 0x20a3, 0x0700, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x0f7e, 0x2079, 0xa752, 0x7904,
-	0x0f7f, 0xd1ac, 0x00c0, 0x66a6, 0xa085, 0x0020, 0xd1a4, 0x0040,
-	0x66ab, 0xa085, 0x0010, 0x2009, 0xa774, 0x210c, 0xd184, 0x0040,
-	0x66b5, 0x699c, 0xd18c, 0x0040, 0x66b7, 0xa085, 0x0002, 0x027e,
-	0x2009, 0xa772, 0x210c, 0xd1e4, 0x0040, 0x66c5, 0xc0c5, 0xa094,
-	0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xd1ec, 0x0040, 0x66cf,
-	0xa094, 0x0030, 0xa296, 0x0010, 0x0040, 0x66cf, 0xc0bd, 0x027f,
-	0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014, 0x1078, 0x6dfb, 0x0d7f,
-	0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0210, 0x20a3,
-	0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x1078,
-	0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0200,
-	0x0078, 0x64c8, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100,
-	0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00, 0x60c3, 0x0008,
-	0x1078, 0x6dfb, 0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a1,
-	0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c,
-	0x027e, 0x037e, 0x047e, 0x2019, 0x3200, 0x2021, 0x0800, 0x0078,
-	0x6738, 0x027e, 0x037e, 0x047e, 0x2019, 0x2200, 0x2021, 0x0100,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2014,
-	0xa286, 0x007e, 0x00c0, 0x674b, 0xa385, 0x00ff, 0x20a2, 0x20a3,
-	0xfffe, 0x0078, 0x6780, 0xa286, 0x007f, 0x00c0, 0x6757, 0x0d7e,
-	0xa385, 0x00ff, 0x20a2, 0x20a3, 0xfffd, 0x0078, 0x676e, 0xd2bc,
-	0x0040, 0x6776, 0xa286, 0x0080, 0x0d7e, 0x00c0, 0x6766, 0xa385,
-	0x00ff, 0x20a2, 0x20a3, 0xfffc, 0x0078, 0x676e, 0xa2e8, 0xa835,
-	0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6784, 0x0d7e, 0xa2e8,
-	0xa835, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f,
-	0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x047f,
-	0x037f, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000,
-	0x2fa2, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
-	0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff,
-	0x2011, 0xfffc, 0x22a2, 0x0d7e, 0x2069, 0xa71b, 0x2da6, 0x8d68,
-	0x2da6, 0x0d7f, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x0078, 0x678b,
-	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000,
-	0x007c, 0x027e, 0x037e, 0x047e, 0x2019, 0x3300, 0x2021, 0x0800,
-	0x0078, 0x67c9, 0x027e, 0x037e, 0x047e, 0x2019, 0x2300, 0x2021,
-	0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xa092, 0x007e, 0x0048, 0x67e6, 0x0d7e, 0xa0e8, 0xa835,
-	0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x67f4, 0x0d7e, 0xa0e8,
-	0xa835, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x0d7f,
-	0x20a3, 0x0000, 0x6230, 0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3,
-	0x0000, 0x047f, 0x037f, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000,
-	0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f,
-	0x007c, 0x0c7e, 0x0f7e, 0x6004, 0xa08a, 0x0085, 0x1048, 0x1332,
-	0xa08a, 0x008c, 0x10c8, 0x1332, 0x6118, 0x2178, 0x79a0, 0xd1bc,
-	0x0040, 0x6827, 0x7900, 0xd1f4, 0x0040, 0x6823, 0x7914, 0xa18c,
-	0x00ff, 0x0078, 0x682c, 0x2009, 0x0000, 0x0078, 0x682c, 0xa1f8,
-	0x29c0, 0x2f0c, 0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a,
-	0xa082, 0x0085, 0x1079, 0x6837, 0x0f7f, 0x0c7f, 0x007c, 0x6840,
-	0x684b, 0x6866, 0x683e, 0x683e, 0x683e, 0x6840, 0x1078, 0x1332,
-	0x147e, 0x20a1, 0x020b, 0x1078, 0x6879, 0x60c3, 0x0000, 0x1078,
-	0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1, 0x020b, 0x1078, 0x68ad,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2, 0x7810, 0x20a2,
-	0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f, 0x007c, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x68ee, 0x20a3, 0x0003, 0x20a3, 0x0300, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004, 0x1078, 0x6dfb, 0x147f,
-	0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
-	0x0028, 0x2004, 0xa092, 0x007e, 0x0048, 0x6898, 0x0d7e, 0xa0e8,
-	0xa835, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x68a7,
-	0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2,
-	0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3,
-	0x0009, 0x20a3, 0x0000, 0x0078, 0x678b, 0x027e, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092, 0x007e,
-	0x0048, 0x68cc, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085,
-	0x8400, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68,
-	0x2da6, 0x0d7f, 0x0078, 0x68db, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c,
-	0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3,
-	0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000, 0x1078,
-	0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7a10, 0x22a2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x027e, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xa092,
-	0x007e, 0x0048, 0x690d, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810,
-	0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6,
-	0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x691c, 0x0d7e, 0xa0e8, 0xa835,
-	0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2, 0x6814, 0x20a2, 0x0d7f,
-	0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0099, 0x20a3, 0x0000,
-	0x0078, 0x68df, 0x0c7e, 0x0f7e, 0x2c78, 0x7804, 0xa08a, 0x0040,
-	0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332, 0x7918, 0x2160,
-	0x61a0, 0xd1bc, 0x0040, 0x6941, 0x6100, 0xd1f4, 0x0040, 0x693d,
-	0x6114, 0xa18c, 0x00ff, 0x0078, 0x6946, 0x2009, 0x0000, 0x0078,
-	0x6946, 0xa1e0, 0x29c0, 0x2c0c, 0xa18c, 0x00ff, 0x2061, 0x0100,
-	0x619a, 0xa082, 0x0040, 0x1079, 0x6950, 0x0f7f, 0x0c7f, 0x007c,
-	0x6965, 0x6a73, 0x6a14, 0x6c27, 0x6963, 0x6963, 0x6963, 0x6963,
-	0x6963, 0x6963, 0x6963, 0x714c, 0x715d, 0x716e, 0x717f, 0x6963,
-	0x767e, 0x6963, 0x713b, 0x1078, 0x1332, 0x0d7e, 0x157e, 0x147e,
-	0x780b, 0xffff, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7910, 0x2168,
-	0x6948, 0x7922, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c,
-	0xa184, 0x000f, 0x00c0, 0x6980, 0x2001, 0x0005, 0x0078, 0x698a,
-	0xd184, 0x0040, 0x6987, 0x2001, 0x0004, 0x0078, 0x698a, 0xa084,
-	0x0006, 0x8004, 0x017e, 0x2008, 0x7830, 0xa084, 0x00ff, 0x8007,
-	0xa105, 0x017f, 0x20a2, 0xd1ac, 0x0040, 0x699a, 0x20a3, 0x0002,
-	0x0078, 0x69a6, 0xd1b4, 0x0040, 0x69a1, 0x20a3, 0x0001, 0x0078,
-	0x69a6, 0x20a3, 0x0000, 0x2230, 0x0078, 0x69a8, 0x6a80, 0x6e7c,
-	0x20a9, 0x0008, 0xad80, 0x0017, 0x200c, 0x810f, 0x21a2, 0x8000,
-	0x00f0, 0x69ac, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080,
-	0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xa9cd,
-	0x2003, 0x07d0, 0x2001, 0xa9cc, 0x2003, 0x0009, 0x2001, 0xa9d2,
-	0x2003, 0x0002, 0x1078, 0x158c, 0x147f, 0x157f, 0x0d7f, 0x007c,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7a18, 0xa280, 0x0023, 0x2014,
-	0x8210, 0xa294, 0x00ff, 0x2202, 0x8217, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xd0bc, 0x0040, 0x69f6, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c,
-	0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6a05, 0x0d7e, 0xa0e8,
-	0xa835, 0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2,
-	0x0d7f, 0x20a3, 0x0000, 0x6130, 0x21a2, 0x20a3, 0x0829, 0x20a3,
-	0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x6a34, 0x7810, 0x2068, 0x6860, 0x20a2,
-	0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x147f,
-	0x137f, 0x157f, 0x0d7f, 0x007c, 0x027e, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6a52,
-	0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f,
-	0x0078, 0x6a61, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085,
-	0x0500, 0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230,
-	0x22a2, 0x20a3, 0x0889, 0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2,
-	0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x027f, 0x007c, 0x0d7e, 0x157e, 0x137e, 0x147e, 0x7810,
-	0xa0ec, 0xf000, 0x0040, 0x6a8b, 0xa06d, 0x1078, 0x495f, 0x0040,
-	0x6a8b, 0x684c, 0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6a8b,
-	0x7824, 0xc0cd, 0x7826, 0x20a1, 0x020b, 0x1078, 0x6be0, 0xa016,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810, 0xa084, 0xf000,
-	0x00c0, 0x6aa2, 0x7810, 0xa084, 0x0700, 0x8007, 0x1079, 0x6aaa,
-	0x0078, 0x6aa5, 0xa006, 0x1079, 0x6aaa, 0x147f, 0x137f, 0x157f,
-	0x0d7f, 0x007c, 0x6ab4, 0x6b4c, 0x6b57, 0x6b81, 0x6b95, 0x6bb1,
-	0x6bbc, 0x6ab2, 0x1078, 0x1332, 0x017e, 0x037e, 0x694c, 0xa18c,
-	0x0003, 0x0040, 0x6abf, 0xa186, 0x0003, 0x00c0, 0x6ace, 0x6b78,
-	0x7824, 0xd0cc, 0x0040, 0x6ac5, 0xc3e5, 0x23a2, 0x6868, 0x20a2,
-	0x6864, 0x20a2, 0x037f, 0x017f, 0x0078, 0x6b8c, 0xa186, 0x0001,
-	0x10c0, 0x1332, 0x6b78, 0x7824, 0xd0cc, 0x0040, 0x6ad8, 0xc3e5,
-	0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2, 0x6874, 0x20a2,
-	0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384, 0x0300, 0x0040,
-	0x6b46, 0xd3c4, 0x0040, 0x6aee, 0x687c, 0xa108, 0xd3cc, 0x0040,
-	0x6af3, 0x6874, 0xa108, 0x157e, 0x20a9, 0x000d, 0xad80, 0x0020,
-	0x201c, 0x831f, 0x23a2, 0x8000, 0x00f0, 0x6af8, 0x157f, 0x22a2,
-	0x22a2, 0x22a2, 0xa184, 0x0003, 0x0040, 0x6b46, 0x20a1, 0x020b,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x007e, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xd0bc, 0x0040, 0x6b26, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c,
-	0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6b35, 0x0d7e, 0xa0e8,
-	0xa835, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
-	0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x007f, 0x7b24, 0xd3cc,
-	0x0040, 0x6b3e, 0x20a3, 0x0889, 0x0078, 0x6b40, 0x20a3, 0x0898,
-	0x20a2, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x61c2, 0x037f,
-	0x017f, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc,
-	0x0040, 0x6b53, 0xc2e5, 0x22a2, 0xa016, 0x0078, 0x6b8a, 0x2011,
-	0x0302, 0x7824, 0xd0cc, 0x0040, 0x6b5e, 0xc2e5, 0x22a2, 0xa016,
-	0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500,
-	0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x1078, 0x6dfb,
-	0x007c, 0x2011, 0x0028, 0x7824, 0xd0cc, 0x0040, 0x6b88, 0xc2e5,
-	0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
-	0x60c3, 0x0018, 0x1078, 0x6dfb, 0x007c, 0x2011, 0x0100, 0x7824,
-	0xd0cc, 0x0040, 0x6b9c, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2,
-	0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7834, 0xa084,
-	0x00ff, 0x20a2, 0x22a2, 0x22a2, 0x60c3, 0x0020, 0x1078, 0x6dfb,
-	0x007c, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0040, 0x6bb8, 0xc2e5,
-	0x22a2, 0xa016, 0x0078, 0x6b8a, 0x037e, 0x7b10, 0xa384, 0xff00,
-	0x7812, 0xa384, 0x00ff, 0x8001, 0x00c0, 0x6bcf, 0x7824, 0xd0cc,
-	0x0040, 0x6bcb, 0xc2e5, 0x22a2, 0x037f, 0x0078, 0x6b8a, 0x047e,
-	0x2021, 0x0800, 0x007e, 0x7824, 0xd0cc, 0x007f, 0x0040, 0x6bd9,
-	0xc4e5, 0x24a2, 0x047f, 0x22a2, 0x20a2, 0x037f, 0x0078, 0x6b8c,
-	0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xd0bc, 0x0040, 0x6bfe, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c,
-	0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x6c0d, 0x0d7e, 0xa0e8,
-	0xa835, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2, 0x6814, 0x20a2,
-	0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x7824, 0xd0cc, 0x0040,
-	0x6c15, 0x20a3, 0x0889, 0x0078, 0x6c17, 0x20a3, 0x0898, 0x20a3,
-	0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2,
-	0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x027f, 0x007c, 0x0d7e,
-	0x157e, 0x137e, 0x147e, 0x017e, 0x037e, 0x7810, 0xa084, 0x0700,
-	0x8007, 0x1079, 0x6c3a, 0x037f, 0x017f, 0x147f, 0x137f, 0x157f,
-	0x0d7f, 0x007c, 0x6c42, 0x6c42, 0x6c44, 0x6c42, 0x6c42, 0x6c42,
-	0x6c69, 0x6c42, 0x1078, 0x1332, 0x7910, 0xa18c, 0xf8ff, 0xa18d,
-	0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73,
-	0x0d7e, 0x2069, 0xa752, 0x6804, 0xd0bc, 0x0040, 0x6c5e, 0x682c,
-	0xa084, 0x00ff, 0x8007, 0x20a2, 0x0078, 0x6c60, 0x20a3, 0x3f00,
-	0x0d7f, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x1078, 0x6dfb,
-	0x007c, 0x20a1, 0x020b, 0x2009, 0x0003, 0x1078, 0x6c73, 0x20a3,
-	0x7f00, 0x0078, 0x6c61, 0x027e, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x7818, 0xa080, 0x0028, 0x2004, 0xd0bc, 0x0040, 0x6c91, 0x0d7e,
-	0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2, 0x6814,
-	0x20a2, 0x2069, 0xa71b, 0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078,
-	0x6ca0, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c, 0x6810, 0xa085, 0x0100,
-	0x20a2, 0x6814, 0x20a2, 0x0d7f, 0x20a3, 0x0000, 0x6230, 0x22a2,
-	0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x1078, 0x6dea, 0x22a2,
-	0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x0c7e, 0x057e, 0x047e,
-	0x037e, 0x2061, 0x0100, 0x2071, 0xa700, 0x6130, 0x7818, 0x2068,
-	0x68a0, 0x2028, 0xd0bc, 0x00c0, 0x6cca, 0x6910, 0x6a14, 0x6430,
-	0x0078, 0x6cce, 0x6910, 0x6a14, 0x736c, 0x7470, 0x781c, 0xa086,
-	0x0006, 0x0040, 0x6d2d, 0xd5bc, 0x0040, 0x6cde, 0xa185, 0x0100,
-	0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6ce5, 0xa185, 0x0100,
-	0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x6073, 0x0809, 0x6077,
-	0x0008, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a,
-	0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7810, 0x2070,
-	0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca,
-	0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0xa582, 0x0080, 0x0048, 0x6d17, 0x6a00, 0xd2f4, 0x0040, 0x6d15,
-	0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d17, 0x2011, 0x0000, 0x629e,
-	0x6017, 0x0016, 0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005,
-	0x0040, 0x6d24, 0x2009, 0x1b58, 0x1078, 0x5ad0, 0x037f, 0x047f,
-	0x057f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x7810, 0x2070, 0x704c,
-	0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x6d85, 0xd5bc, 0x0040,
-	0x6d41, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078,
-	0x6d48, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e,
-	0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff,
-	0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808,
-	0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c,
-	0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109,
-	0x792a, 0x686c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7,
-	0x0000, 0xa582, 0x0080, 0x0048, 0x6d80, 0x6a00, 0xd2f4, 0x0040,
-	0x6d7e, 0x6a14, 0xa294, 0x00ff, 0x0078, 0x6d80, 0x2011, 0x0000,
-	0x629e, 0x6017, 0x0012, 0x0078, 0x6d1a, 0xd5bc, 0x0040, 0x6d90,
-	0xa185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0078, 0x6d97,
-	0xa185, 0x0700, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x1078,
-	0x495f, 0x0040, 0x6dad, 0x0d7e, 0x7810, 0xa06d, 0x684c, 0x0d7f,
-	0xa084, 0x2020, 0xa086, 0x2020, 0x00c0, 0x6dad, 0x7824, 0xc0cd,
-	0x7826, 0x6073, 0x0889, 0x0078, 0x6daf, 0x6073, 0x0898, 0x6077,
-	0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e, 0x8007, 0x607a,
-	0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082, 0x7014, 0x608a,
-	0x7010, 0x608e, 0x700c, 0x60c6, 0x7008, 0x60ca, 0x686c, 0x60ce,
-	0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582, 0x0080,
-	0x0048, 0x6ddd, 0x6a00, 0xd2f4, 0x0040, 0x6ddb, 0x6a14, 0xa294,
-	0x00ff, 0x0078, 0x6ddd, 0x2011, 0x0000, 0x629e, 0x7824, 0xd0cc,
-	0x0040, 0x6de6, 0x6017, 0x0016, 0x0078, 0x6d1a, 0x6017, 0x0012,
-	0x0078, 0x6d1a, 0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294,
-	0x00ff, 0x2202, 0x8217, 0x007c, 0x0d7e, 0x2069, 0xa9b1, 0x6843,
-	0x0001, 0x0d7f, 0x007c, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7,
-	0x9575, 0x1078, 0x6e06, 0x1078, 0x5ac0, 0x007c, 0x007e, 0x6014,
-	0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x007f, 0x007c, 0x007e,
-	0x0c7e, 0x2061, 0x0100, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008,
-	0x6016, 0x0c7f, 0x007f, 0x007c, 0x0c7e, 0x0d7e, 0x017e, 0x027e,
-	0x2061, 0x0100, 0x2069, 0x0140, 0x6904, 0xa194, 0x4000, 0x0040,
-	0x6e59, 0x1078, 0x6e0f, 0x6803, 0x1000, 0x6803, 0x0000, 0x0c7e,
-	0x2061, 0xa9b1, 0x6128, 0xa192, 0x00c8, 0x00c8, 0x6e44, 0x8108,
-	0x612a, 0x6124, 0x0c7f, 0x81ff, 0x0040, 0x6e54, 0x1078, 0x5ac0,
-	0x1078, 0x6e06, 0x0078, 0x6e54, 0x6124, 0xa1e5, 0x0000, 0x0040,
-	0x6e51, 0x1078, 0xa5d4, 0x1078, 0x5acb, 0x2009, 0x0014, 0x1078,
-	0x775c, 0x0c7f, 0x0078, 0x6e54, 0x027f, 0x017f, 0x0d7f, 0x0c7f,
-	0x007c, 0x2001, 0xa9cd, 0x2004, 0xa005, 0x00c0, 0x6e54, 0x0c7e,
-	0x2061, 0xa9b1, 0x6128, 0xa192, 0x0003, 0x00c8, 0x6e44, 0x8108,
-	0x612a, 0x0c7f, 0x1078, 0x5ac0, 0x1078, 0x4224, 0x0078, 0x6e54,
-	0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x027e, 0x1078, 0x5ad8, 0x2071,
-	0xa9b1, 0x713c, 0x81ff, 0x0040, 0x6e9a, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x6904, 0xa194, 0x4000, 0x0040, 0x6ea0, 0x6803, 0x1000,
-	0x6803, 0x0000, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x037f,
-	0x713c, 0x2160, 0x1078, 0xa5d4, 0x2009, 0x004a, 0x1078, 0x775c,
-	0x0078, 0x6e9a, 0x027f, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c,
-	0x0078, 0x6e8a, 0x0e7e, 0x2071, 0xa9b1, 0x7048, 0xd084, 0x0040,
-	0x6ebc, 0x713c, 0x81ff, 0x0040, 0x6ebc, 0x2071, 0x0100, 0xa188,
-	0x0007, 0x210c, 0xa18e, 0x0006, 0x00c0, 0x6eba, 0x7017, 0x0012,
-	0x0078, 0x6ebc, 0x7017, 0x0016, 0x0e7f, 0x007c, 0x0e7e, 0x0d7e,
-	0x0c7e, 0x067e, 0x057e, 0x047e, 0x007e, 0x127e, 0x2091, 0x8000,
-	0x6018, 0x2068, 0x6ca0, 0x2071, 0xa9b1, 0x7018, 0x2068, 0x8dff,
-	0x0040, 0x6ee6, 0x68a0, 0xa406, 0x0040, 0x6eda, 0x6854, 0x2068,
-	0x0078, 0x6ecf, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60,
-	0x1078, 0x4736, 0x0040, 0x6ee6, 0xa085, 0x0001, 0x127f, 0x007f,
-	0x047f, 0x057f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0x20a1,
-	0x020b, 0x1078, 0x6731, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x781c, 0xa086, 0x0004, 0x00c0, 0x6f01, 0x6098, 0x0078,
-	0x6f02, 0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9,
-	0x0010, 0xa006, 0x20a2, 0x00f0, 0x6f0a, 0x20a2, 0x20a2, 0x60c3,
-	0x002c, 0x1078, 0x6dfb, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x6731, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f, 0x157f,
-	0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3,
-	0x0200, 0x20a3, 0x0000, 0x20a9, 0x0006, 0x2011, 0xa740, 0x2019,
-	0xa741, 0x23a6, 0x22a6, 0xa398, 0x0002, 0xa290, 0x0002, 0x00f0,
-	0x6f39, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x001c, 0x1078,
-	0x6dfb, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e,
-	0x20a1, 0x020b, 0x1078, 0x6799, 0x1078, 0x67b0, 0x7810, 0xa080,
-	0x0000, 0x2004, 0xa080, 0x0015, 0x2098, 0x7808, 0xa088, 0x0002,
-	0x21a8, 0x53a6, 0xa080, 0x0004, 0x8003, 0x60c2, 0x1078, 0x6dfb,
-	0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x157e, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x6731, 0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x7808, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x147f,
-	0x157f, 0x007c, 0x157e, 0x147e, 0x017e, 0x027e, 0x20a1, 0x020b,
-	0x1078, 0x6731, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080, 0x0017,
-	0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2,
-	0x1078, 0x6dfb, 0x027f, 0x017f, 0x147f, 0x157f, 0x007c, 0x0e7e,
-	0x0c7e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x700c,
-	0x2060, 0x8cff, 0x0040, 0x6fbb, 0x1078, 0x8f10, 0x00c0, 0x6fb2,
-	0x1078, 0x7c83, 0x600c, 0x007e, 0x1078, 0x772d, 0x1078, 0x7233,
-	0x0c7f, 0x0078, 0x6fa9, 0x700f, 0x0000, 0x700b, 0x0000, 0x127f,
-	0x007f, 0x0c7f, 0x0e7f, 0x007c, 0x127e, 0x157e, 0x0f7e, 0x0e7e,
-	0x0d7e, 0x0c7e, 0x027e, 0x017e, 0x007e, 0x2091, 0x8000, 0x2069,
-	0x0100, 0x2079, 0x0140, 0x2071, 0xa9b1, 0x7024, 0x2060, 0x8cff,
-	0x0040, 0x7014, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x5acb,
-	0x2009, 0x0013, 0x1078, 0x775c, 0x20a9, 0x01f4, 0x6824, 0xd094,
-	0x0040, 0x6ff7, 0x6827, 0x0004, 0x7804, 0xa084, 0x4000, 0x0040,
-	0x7009, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0x7009, 0xd084,
-	0x0040, 0x6ffe, 0x6827, 0x0001, 0x0078, 0x7000, 0x00f0, 0x6fe6,
-	0x7804, 0xa084, 0x1000, 0x0040, 0x7009, 0x7803, 0x0100, 0x7803,
-	0x0000, 0x6824, 0x007f, 0x017f, 0x027f, 0x0c7f, 0x0d7f, 0x0e7f,
-	0x0f7f, 0x157f, 0x127f, 0x007c, 0x2001, 0xa700, 0x2004, 0xa096,
-	0x0001, 0x0040, 0x704e, 0xa096, 0x0004, 0x0040, 0x704e, 0x1078,
-	0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x41dc, 0x1078,
-	0x5a45, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0040, 0x703c, 0x6827,
-	0x0004, 0x7804, 0xa084, 0x4000, 0x0040, 0x704e, 0x7803, 0x1000,
-	0x7803, 0x0000, 0x0078, 0x704e, 0xd084, 0x0040, 0x7043, 0x6827,
-	0x0001, 0x0078, 0x7045, 0x00f0, 0x702b, 0x7804, 0xa084, 0x1000,
-	0x0040, 0x704e, 0x7803, 0x0100, 0x7803, 0x0000, 0x007f, 0x017f,
-	0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
-	0x127e, 0x157e, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x027e, 0x017e,
-	0x007e, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
-	0xa9b1, 0x703c, 0x2060, 0x8cff, 0x0040, 0x70d6, 0x68af, 0x95f5,
-	0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x00c0, 0x7074, 0x68c7,
-	0x0000, 0x68cb, 0x0008, 0x1078, 0x5ad8, 0x1078, 0x1f7e, 0x047e,
-	0x057e, 0x2009, 0x017f, 0x212c, 0x200b, 0x00a5, 0x2021, 0x0169,
-	0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x70a5, 0x68c7,
-	0x0000, 0x68cb, 0x0008, 0x0e7e, 0x0f7e, 0x2079, 0x0020, 0x2071,
-	0xaa08, 0x6814, 0xa084, 0x0004, 0xa085, 0x0012, 0x6816, 0x7803,
-	0x0008, 0x7003, 0x0000, 0x0f7f, 0x0e7f, 0x250a, 0x057f, 0x047f,
-	0xa39d, 0x0000, 0x00c0, 0x70b0, 0x2009, 0x0049, 0x1078, 0x775c,
-	0x20a9, 0x03e8, 0x6824, 0xd094, 0x0040, 0x70c3, 0x6827, 0x0004,
-	0x7804, 0xa084, 0x4000, 0x0040, 0x70d5, 0x7803, 0x1000, 0x7803,
-	0x0000, 0x0078, 0x70d5, 0xd08c, 0x0040, 0x70ca, 0x6827, 0x0002,
-	0x0078, 0x70cc, 0x00f0, 0x70b2, 0x7804, 0xa084, 0x1000, 0x0040,
-	0x70d5, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x007f, 0x017f,
-	0x027f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f, 0x157f, 0x127f, 0x007c,
-	0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa9b1, 0x6a06, 0x127f,
-	0x0d7f, 0x007c, 0x0d7e, 0x127e, 0x2091, 0x8000, 0x2069, 0xa9b1,
-	0x6a32, 0x127f, 0x0d7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e,
-	0x007e, 0x127e, 0x2071, 0xa9b1, 0x7614, 0x2660, 0x2678, 0x2091,
-	0x8000, 0x8cff, 0x0040, 0x7134, 0x601c, 0xa206, 0x00c0, 0x712f,
-	0x7014, 0xac36, 0x00c0, 0x710e, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x00c0, 0x711c, 0x2c00, 0xaf36, 0x0040, 0x711a, 0x2f00, 0x7012,
-	0x0078, 0x711c, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
-	0x0040, 0x7125, 0x7e0e, 0x0078, 0x7126, 0x2678, 0x600f, 0x0000,
-	0x1078, 0x8ed6, 0x1078, 0x7233, 0x0c7f, 0x0078, 0x7101, 0x2c78,
-	0x600c, 0x2060, 0x0078, 0x7101, 0x127f, 0x007f, 0x067f, 0x0c7f,
-	0x0e7f, 0x0f7f, 0x007c, 0x157e, 0x147e, 0x20a1, 0x020b, 0x1078,
-	0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
-	0x20a3, 0x1000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1, 0x020b,
-	0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x20a3, 0x4000, 0x0078, 0x718e, 0x157e, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x20a3, 0x2000, 0x0078, 0x718e, 0x157e, 0x147e,
-	0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x718e, 0x157e,
-	0x147e, 0x20a1, 0x020b, 0x1078, 0x69d0, 0x7810, 0x20a2, 0xa006,
-	0x20a2, 0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x1078, 0x723e,
-	0x60c3, 0x0020, 0x1078, 0x6dfb, 0x147f, 0x157f, 0x007c, 0x127e,
-	0x0c7e, 0x2091, 0x8000, 0x2061, 0x0100, 0x6120, 0xd1b4, 0x00c0,
-	0x71a6, 0xd1bc, 0x00c0, 0x71f0, 0x0078, 0x7230, 0x2009, 0x017f,
-	0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069, 0x0140, 0x20a9,
-	0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000, 0x0040, 0x71e7,
-	0x6020, 0xd0b4, 0x0040, 0x71e7, 0x6024, 0xd094, 0x00c0, 0x71e7,
-	0x2104, 0xa084, 0x000f, 0xa086, 0x0004, 0x00c0, 0x71e7, 0x00f0,
-	0x71b3, 0x027e, 0x6198, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c,
-	0x00ff, 0xa10d, 0x6088, 0x628c, 0x618e, 0x608b, 0xbc91, 0x6043,
-	0x0001, 0x6043, 0x0000, 0x608a, 0x628e, 0x6024, 0xd094, 0x00c0,
-	0x71e6, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x71dd, 0x027f, 0x0d7f,
-	0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000, 0x0078, 0x7230,
-	0x2009, 0x017f, 0x200b, 0x00a1, 0x157e, 0x007e, 0x0d7e, 0x2069,
-	0x0140, 0x20a9, 0x001e, 0x2009, 0x0169, 0x6804, 0xa084, 0x4000,
-	0x0040, 0x7229, 0x6020, 0xd0bc, 0x0040, 0x7229, 0x2104, 0xa084,
-	0x000f, 0xa086, 0x0004, 0x00c0, 0x7229, 0x00f0, 0x71fd, 0x027e,
-	0x6164, 0xa18c, 0x00ff, 0x8107, 0x6130, 0xa18c, 0x00ff, 0xa10d,
-	0x6088, 0x628c, 0x608b, 0xbc91, 0x618e, 0x6043, 0x0001, 0x6043,
-	0x0000, 0x608a, 0x628e, 0x6a04, 0xa294, 0x4000, 0x00c0, 0x7223,
-	0x027f, 0x0d7f, 0x007f, 0x157f, 0x2009, 0x017f, 0x200b, 0x0000,
-	0x0c7f, 0x127f, 0x007c, 0x0e7e, 0x2071, 0xa9b1, 0x7020, 0xa005,
-	0x0040, 0x723c, 0x8001, 0x7022, 0x0e7f, 0x007c, 0x20a9, 0x0008,
-	0x20a2, 0x00f0, 0x7240, 0x20a2, 0x20a2, 0x007c, 0x0f7e, 0x0e7e,
-	0x0d7e, 0x0c7e, 0x077e, 0x067e, 0x007e, 0x127e, 0x2091, 0x8000,
-	0x2071, 0xa9b1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001, 0x87ff,
-	0x0040, 0x72e2, 0x8cff, 0x0040, 0x72e2, 0x601c, 0xa086, 0x0006,
-	0x00c0, 0x72dd, 0x88ff, 0x0040, 0x726d, 0x2800, 0xac06, 0x00c0,
-	0x72dd, 0x2039, 0x0000, 0x0078, 0x7278, 0x6018, 0xa206, 0x00c0,
-	0x72dd, 0x85ff, 0x0040, 0x7278, 0x6020, 0xa106, 0x00c0, 0x72dd,
-	0x7024, 0xac06, 0x00c0, 0x72a8, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x0040, 0x72a3, 0x1078, 0x5acb, 0x6817, 0x0008, 0x68c3, 0x0000,
-	0x1078, 0x7378, 0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04,
-	0xa384, 0x1000, 0x0040, 0x7298, 0x6803, 0x0100, 0x6803, 0x0000,
-	0x2069, 0x0100, 0x6824, 0xd084, 0x0040, 0x72a0, 0x6827, 0x0001,
-	0x037f, 0x0078, 0x72a8, 0x6003, 0x0009, 0x630a, 0x0078, 0x72dd,
-	0x7014, 0xac36, 0x00c0, 0x72ae, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x00c0, 0x72bc, 0x2c00, 0xaf36, 0x0040, 0x72ba, 0x2f00, 0x7012,
-	0x0078, 0x72bc, 0x7013, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06,
-	0x0040, 0x72c5, 0x7e0e, 0x0078, 0x72c6, 0x2678, 0x89ff, 0x00c0,
-	0x72d5, 0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040,
-	0x72d3, 0x1078, 0xa1da, 0x1078, 0x8ed6, 0x1078, 0x7233, 0x88ff,
-	0x00c0, 0x72ec, 0x0c7f, 0x0078, 0x7257, 0x2c78, 0x600c, 0x2060,
-	0x0078, 0x7257, 0xa006, 0x127f, 0x007f, 0x067f, 0x077f, 0x0c7f,
-	0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x6017, 0x0000, 0x0c7f, 0xa8c5,
-	0x0001, 0x0078, 0x72e3, 0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e,
-	0x027e, 0x007e, 0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x7638,
-	0x2660, 0x2678, 0x8cff, 0x0040, 0x7367, 0x601c, 0xa086, 0x0006,
-	0x00c0, 0x7362, 0x87ff, 0x0040, 0x7313, 0x2700, 0xac06, 0x00c0,
-	0x7362, 0x0078, 0x731e, 0x6018, 0xa206, 0x00c0, 0x7362, 0x85ff,
-	0x0040, 0x731e, 0x6020, 0xa106, 0x00c0, 0x7362, 0x703c, 0xac06,
-	0x00c0, 0x7332, 0x037e, 0x2019, 0x0001, 0x1078, 0x7058, 0x7033,
-	0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000, 0x704b,
-	0x0000, 0x037f, 0x7038, 0xac36, 0x00c0, 0x7338, 0x660c, 0x763a,
-	0x7034, 0xac36, 0x00c0, 0x7346, 0x2c00, 0xaf36, 0x0040, 0x7344,
-	0x2f00, 0x7036, 0x0078, 0x7346, 0x7037, 0x0000, 0x660c, 0x067e,
-	0x2c00, 0xaf06, 0x0040, 0x734f, 0x7e0e, 0x0078, 0x7350, 0x2678,
-	0x600f, 0x0000, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x735a,
-	0x1078, 0xa1da, 0x1078, 0x8ed6, 0x87ff, 0x00c0, 0x7371, 0x0c7f,
-	0x0078, 0x7302, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7302, 0xa006,
-	0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
-	0x007c, 0x6017, 0x0000, 0x0c7f, 0xa7bd, 0x0001, 0x0078, 0x7368,
-	0x0e7e, 0x2071, 0xa9b1, 0x2001, 0xa700, 0x2004, 0xa086, 0x0002,
-	0x00c0, 0x7386, 0x7007, 0x0005, 0x0078, 0x7388, 0x7007, 0x0000,
-	0x0e7f, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e, 0x067e, 0x027e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2071, 0xa9b1, 0x2c10, 0x7638, 0x2660,
-	0x2678, 0x8cff, 0x0040, 0x73c8, 0x2200, 0xac06, 0x00c0, 0x73c3,
-	0x7038, 0xac36, 0x00c0, 0x73a6, 0x660c, 0x763a, 0x7034, 0xac36,
-	0x00c0, 0x73b4, 0x2c00, 0xaf36, 0x0040, 0x73b2, 0x2f00, 0x7036,
-	0x0078, 0x73b4, 0x7037, 0x0000, 0x660c, 0x2c00, 0xaf06, 0x0040,
-	0x73bc, 0x7e0e, 0x0078, 0x73bd, 0x2678, 0x600f, 0x0000, 0xa085,
-	0x0001, 0x0078, 0x73c8, 0x2c78, 0x600c, 0x2060, 0x0078, 0x7399,
-	0x127f, 0x007f, 0x027f, 0x067f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c,
-	0x0f7e, 0x0e7e, 0x0d7e, 0x0c7e, 0x067e, 0x007e, 0x127e, 0x2091,
-	0x8000, 0x2071, 0xa9b1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0040,
-	0x7469, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x00c0, 0x7464,
-	0x7024, 0xac06, 0x00c0, 0x740f, 0x2069, 0x0100, 0x68c0, 0xa005,
-	0x0040, 0x743d, 0x1078, 0x6e0f, 0x68c3, 0x0000, 0x1078, 0x7378,
-	0x7027, 0x0000, 0x037e, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0040, 0x7406, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0040, 0x740e, 0x6827, 0x0001, 0x037f, 0x700c,
-	0xac36, 0x00c0, 0x7415, 0x660c, 0x760e, 0x7008, 0xac36, 0x00c0,
-	0x7423, 0x2c00, 0xaf36, 0x0040, 0x7421, 0x2f00, 0x700a, 0x0078,
-	0x7423, 0x700b, 0x0000, 0x660c, 0x067e, 0x2c00, 0xaf06, 0x0040,
-	0x742c, 0x7e0e, 0x0078, 0x742d, 0x2678, 0x600f, 0x0000, 0x1078,
-	0x8efc, 0x00c0, 0x7441, 0x1078, 0x28a6, 0x1078, 0x8f10, 0x00c0,
-	0x745d, 0x1078, 0x7c83, 0x0078, 0x745d, 0x1078, 0x7378, 0x0078,
-	0x740f, 0x1078, 0x8f10, 0x00c0, 0x7449, 0x1078, 0x7c83, 0x0078,
-	0x745d, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x745d, 0x601c,
-	0xa086, 0x0003, 0x00c0, 0x7471, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x1078, 0x8ed6, 0x1078,
-	0x7233, 0x0c7f, 0x0078, 0x73de, 0x2c78, 0x600c, 0x2060, 0x0078,
-	0x73de, 0x127f, 0x007f, 0x067f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0f7f,
-	0x007c, 0x601c, 0xa086, 0x0006, 0x00c0, 0x745d, 0x1078, 0xa1da,
-	0x0078, 0x745d, 0x037e, 0x157e, 0x137e, 0x147e, 0x3908, 0xa006,
-	0xa190, 0x0020, 0x221c, 0xa39e, 0x2676, 0x00c0, 0x748b, 0x8210,
-	0x8000, 0x0078, 0x7482, 0xa005, 0x0040, 0x7497, 0x20a9, 0x0020,
-	0x2198, 0x8211, 0xa282, 0x0020, 0x20c8, 0x20a0, 0x53a3, 0x147f,
-	0x137f, 0x157f, 0x037f, 0x007c, 0x0d7e, 0x20a1, 0x020b, 0x1078,
-	0x67c2, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3, 0x0014, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x2099, 0xa9a5, 0x20a9, 0x0004, 0x53a6,
-	0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x1078, 0x6dfb, 0x0d7f, 0x007c, 0x20a1, 0x020b, 0x1078, 0x67c2,
-	0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800, 0x7810, 0xa084,
-	0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2, 0x7828, 0x20a2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x1078, 0x6dfb,
-	0x007c, 0x0d7e, 0x017e, 0x2f68, 0x2009, 0x0035, 0x1078, 0x91cc,
-	0x00c0, 0x7551, 0x20a1, 0x020b, 0x1078, 0x6731, 0x20a3, 0x1300,
-	0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086, 0x0003, 0x0040,
-	0x752d, 0x7818, 0xa080, 0x0028, 0x2014, 0xa286, 0x007e, 0x00c0,
-	0x7507, 0x20a3, 0x00ff, 0x20a3, 0xfffe, 0x0078, 0x7542, 0xa286,
-	0x007f, 0x00c0, 0x7511, 0x20a3, 0x00ff, 0x20a3, 0xfffd, 0x0078,
-	0x7542, 0xd2bc, 0x0040, 0x7527, 0xa286, 0x0080, 0x00c0, 0x751e,
-	0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0078, 0x7542, 0xa2e8, 0xa835,
-	0x2d6c, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x0078, 0x7542, 0x20a3,
-	0x0000, 0x6098, 0x20a2, 0x0078, 0x7542, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xa082, 0x007e, 0x0048, 0x753e, 0x0d7e, 0x2069, 0xa71b,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x7542, 0x20a3, 0x0000,
-	0x6030, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x000c, 0x1078, 0x6dfb, 0x017f, 0x0d7f,
-	0x007c, 0x7817, 0x0001, 0x7803, 0x0006, 0x017f, 0x0d7f, 0x007c,
-	0x0d7e, 0x027e, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x0040,
-	0x757a, 0xa186, 0x0003, 0x0040, 0x75d5, 0xa186, 0x0005, 0x0040,
-	0x75b8, 0xa186, 0x0004, 0x0040, 0x75a8, 0xa186, 0x0008, 0x0040,
-	0x75c2, 0x7807, 0x0037, 0x7813, 0x1700, 0x1078, 0x7640, 0x027f,
-	0x0d7f, 0x007c, 0x1078, 0x75fd, 0x2009, 0x4000, 0x6800, 0x0079,
-	0x7581, 0x7594, 0x75a2, 0x7596, 0x75a2, 0x759d, 0x7594, 0x7594,
-	0x75a2, 0x75a2, 0x75a2, 0x75a2, 0x7594, 0x7594, 0x7594, 0x7594,
-	0x7594, 0x75a2, 0x7594, 0x75a2, 0x1078, 0x1332, 0x6824, 0xd0e4,
-	0x0040, 0x759d, 0xd0cc, 0x0040, 0x75a0, 0xa00e, 0x0078, 0x75a2,
-	0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2, 0x0078, 0x75f3,
-	0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
-	0x6a00, 0xa286, 0x0002, 0x00c0, 0x75b6, 0xa00e, 0x0078, 0x75f3,
-	0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000,
-	0x0078, 0x75f3, 0x1078, 0x75fd, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x2009, 0x4000, 0xa286, 0x0005, 0x0040, 0x75d2, 0xa286, 0x0002,
-	0x00c0, 0x75d3, 0xa00e, 0x0078, 0x75f3, 0x1078, 0x75fd, 0x6810,
-	0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103, 0x20a2,
-	0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002, 0x0040,
-	0x75f1, 0xa08e, 0x0004, 0x0040, 0x75f1, 0x2009, 0x4000, 0x0078,
-	0x75f3, 0x2009, 0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018,
-	0x1078, 0x6dfb, 0x027f, 0x0d7f, 0x007c, 0x037e, 0x047e, 0x057e,
-	0x067e, 0x20a1, 0x020b, 0x1078, 0x67c2, 0xa006, 0x20a3, 0x0200,
-	0x20a2, 0x7934, 0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xa092, 0x007e, 0x0048, 0x7623, 0x0d7e, 0x2069, 0xa71b,
-	0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xa835, 0x2d6c, 0x6b10, 0x6c14,
-	0x0d7f, 0x0078, 0x7629, 0x2019, 0x0000, 0x6498, 0x2029, 0x0000,
-	0x6630, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003, 0x00c0,
-	0x7637, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0078, 0x763b, 0x23a2,
-	0x24a2, 0x25a2, 0x26a2, 0x067f, 0x057f, 0x047f, 0x037f, 0x007c,
-	0x20a1, 0x020b, 0x1078, 0x67c2, 0x20a3, 0x0100, 0x20a3, 0x0000,
-	0x20a3, 0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb,
-	0x007c, 0x20a1, 0x020b, 0x1078, 0x6728, 0x20a3, 0x1400, 0x20a3,
-	0x0000, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c,
-	0x20a2, 0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000,
-	0x60c3, 0x0010, 0x1078, 0x6dfb, 0x007c, 0x20a1, 0x020b, 0x1078,
-	0x67b9, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810,
-	0x20a2, 0x60c3, 0x0008, 0x1078, 0x6dfb, 0x007c, 0x147e, 0x20a1,
-	0x020b, 0x1078, 0x7689, 0x60c3, 0x0000, 0x1078, 0x6dfb, 0x147f,
-	0x007c, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0xd0bc, 0x0040, 0x76a6, 0x0d7e, 0xa0e8, 0xa835, 0x2d6c,
-	0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xa71b,
-	0x2da6, 0x8d68, 0x2da6, 0x0d7f, 0x0078, 0x76ae, 0x20a3, 0x0300,
-	0x6298, 0x22a2, 0x20a3, 0x0000, 0x6230, 0x22a2, 0x20a3, 0x0819,
-	0x20a3, 0x0000, 0x1078, 0x6dea, 0x22a2, 0x20a3, 0x0000, 0x2fa2,
-	0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x007c, 0x2061,
-	0xae00, 0x2a70, 0x7064, 0x704a, 0x704f, 0xae00, 0x007c, 0x0e7e,
-	0x127e, 0x2071, 0xa700, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010,
-	0x0048, 0x76f9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040,
-	0x76e5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x76e1, 0x0078,
-	0x76d4, 0x2061, 0xae00, 0x0078, 0x76d4, 0x6003, 0x0008, 0x8529,
-	0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x76f5, 0x754e,
-	0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xae00, 0x0078,
-	0x76f0, 0xa006, 0x0078, 0x76f2, 0x0e7e, 0x2071, 0xa700, 0x7548,
-	0xa582, 0x0010, 0x0048, 0x772a, 0x704c, 0x2060, 0x6000, 0xa086,
-	0x0000, 0x0040, 0x7717, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8,
-	0x7713, 0x0078, 0x7706, 0x2061, 0xae00, 0x0078, 0x7706, 0x6003,
-	0x0008, 0x8529, 0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8,
-	0x7726, 0x754e, 0xa085, 0x0001, 0x0e7f, 0x007c, 0x704f, 0xae00,
-	0x0078, 0x7722, 0xa006, 0x0078, 0x7724, 0xac82, 0xae00, 0x1048,
-	0x1332, 0x2001, 0xa716, 0x2004, 0xac02, 0x10c8, 0x1332, 0xa006,
-	0x6006, 0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000,
-	0x6003, 0x0000, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036,
-	0x603a, 0x603e, 0x2061, 0xa700, 0x6048, 0x8000, 0x604a, 0xa086,
-	0x0001, 0x0040, 0x7754, 0x007c, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x62d1, 0x127f, 0x0078, 0x7753, 0x601c, 0xa084, 0x000f, 0x0079,
-	0x7761, 0x776a, 0x777b, 0x7797, 0x77b3, 0x921e, 0x923a, 0x9256,
-	0x776a, 0x777b, 0xa186, 0x0013, 0x00c0, 0x7773, 0x1078, 0x61cd,
-	0x1078, 0x62d1, 0x007c, 0xa18e, 0x0047, 0x00c0, 0x777a, 0xa016,
-	0x1078, 0x15fa, 0x007c, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x1332, 0x1079, 0x7785, 0x067f, 0x007c, 0x7795, 0x7b00, 0x7cb2,
-	0x7795, 0x7d36, 0x77cf, 0x7795, 0x7795, 0x7a92, 0x80f6, 0x7795,
-	0x7795, 0x7795, 0x7795, 0x7795, 0x7795, 0x1078, 0x1332, 0x067e,
-	0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x77a1, 0x067f,
-	0x007c, 0x77b1, 0x87d3, 0x77b1, 0x77b1, 0x77b1, 0x77b1, 0x77b1,
-	0x77b1, 0x8776, 0x8961, 0x77b1, 0x8803, 0x8889, 0x8803, 0x8889,
-	0x77b1, 0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8,
-	0x1332, 0x1079, 0x77bd, 0x067f, 0x007c, 0x77cd, 0x813d, 0x820e,
-	0x8372, 0x84f1, 0x77cd, 0x77cd, 0x77cd, 0x8116, 0x871e, 0x8722,
-	0x77cd, 0x77cd, 0x77cd, 0x77cd, 0x8752, 0x1078, 0x1332, 0xa1b6,
-	0x0015, 0x00c0, 0x77d7, 0x1078, 0x772d, 0x0078, 0x77dd, 0xa1b6,
-	0x0016, 0x10c0, 0x1332, 0x1078, 0x772d, 0x007c, 0x20a9, 0x000e,
-	0x2e98, 0x6010, 0x20a0, 0x53a3, 0x20a9, 0x0006, 0x3310, 0x3420,
-	0x9398, 0x94a0, 0x3318, 0x3428, 0x222e, 0x2326, 0xa290, 0x0002,
-	0xa5a8, 0x0002, 0xa398, 0x0002, 0xa4a0, 0x0002, 0x00f0, 0x77ec,
-	0x0e7e, 0x1078, 0x8d16, 0x0040, 0x7803, 0x6010, 0x2070, 0x7007,
-	0x0000, 0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0d7e,
-	0x037e, 0x7330, 0xa386, 0x0200, 0x00c0, 0x7814, 0x6018, 0x2068,
-	0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005, 0x0040, 0x781e,
-	0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x1078, 0x772d,
-	0x037f, 0x0d7f, 0x007c, 0x017e, 0x20a9, 0x002a, 0xae80, 0x000c,
-	0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9, 0x002a,
-	0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0, 0x53a3,
-	0x0e7e, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x0e7f, 0x1078,
-	0x772d, 0x017f, 0x007c, 0x0e7e, 0x0d7e, 0x603f, 0x0000, 0x2c68,
-	0x017e, 0x2009, 0x0035, 0x1078, 0x91cc, 0x017f, 0x00c0, 0x785f,
-	0x027e, 0x6228, 0x2268, 0x027f, 0x2071, 0xac8c, 0x6b1c, 0xa386,
-	0x0003, 0x0040, 0x7863, 0xa386, 0x0006, 0x0040, 0x7867, 0x1078,
-	0x772d, 0x0078, 0x7869, 0x1078, 0x786c, 0x0078, 0x7869, 0x1078,
-	0x7938, 0x0d7f, 0x0e7f, 0x007c, 0x0f7e, 0x6810, 0x2078, 0xa186,
-	0x0015, 0x0040, 0x791d, 0xa18e, 0x0016, 0x00c0, 0x7936, 0x700c,
-	0xa08c, 0xff00, 0xa186, 0x1700, 0x0040, 0x7882, 0xa186, 0x0300,
-	0x00c0, 0x78f8, 0x8fff, 0x00c0, 0x788c, 0x6800, 0xa086, 0x000f,
-	0x0040, 0x78db, 0x0078, 0x7934, 0x6808, 0xa086, 0xffff, 0x00c0,
-	0x7921, 0x784c, 0xa084, 0x0060, 0xa086, 0x0020, 0x00c0, 0x78a2,
-	0x797c, 0x7810, 0xa106, 0x00c0, 0x7921, 0x7980, 0x7814, 0xa106,
-	0x00c0, 0x7921, 0x1078, 0x8ec9, 0x6830, 0x7852, 0x784c, 0xc0dc,
-	0xc0f4, 0xc0d4, 0x784e, 0x027e, 0xa00e, 0x6a14, 0x2001, 0x000a,
-	0x1078, 0x5c1c, 0x7854, 0xa20a, 0x0048, 0x78b7, 0x8011, 0x7a56,
-	0x82ff, 0x027f, 0x00c0, 0x78c3, 0x0c7e, 0x2d60, 0x1078, 0x8af0,
-	0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x0d7e, 0x2f68, 0x6838, 0xd0fc,
-	0x00c0, 0x78ce, 0x1078, 0x4353, 0x0078, 0x78d0, 0x1078, 0x4431,
-	0x0d7f, 0x0c7f, 0x00c0, 0x7921, 0x0c7e, 0x2d60, 0x1078, 0x772d,
-	0x0c7f, 0x0078, 0x7934, 0x0c7e, 0x1078, 0x9197, 0x0040, 0x78f1,
-	0x6013, 0x0000, 0x6818, 0x601a, 0x601f, 0x0003, 0x6904, 0x0c7e,
-	0x2d60, 0x1078, 0x772d, 0x0c7f, 0x1078, 0x775c, 0x0c7f, 0x0078,
-	0x7934, 0x2001, 0xa9a4, 0x2004, 0x683e, 0x0c7f, 0x0078, 0x7934,
-	0x7008, 0xa086, 0x000b, 0x00c0, 0x7912, 0x6018, 0x200c, 0xc1bc,
-	0x2102, 0x0c7e, 0x2d60, 0x7853, 0x0003, 0x6007, 0x0085, 0x6003,
-	0x000b, 0x601f, 0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f,
-	0x0078, 0x7934, 0x700c, 0xa086, 0x2a00, 0x00c0, 0x7921, 0x2001,
-	0xa9a4, 0x2004, 0x683e, 0x0078, 0x7934, 0x1078, 0x7953, 0x0078,
-	0x7936, 0x8fff, 0x1040, 0x1332, 0x0c7e, 0x0d7e, 0x2d60, 0x2f68,
-	0x6837, 0x0103, 0x684b, 0x0003, 0x1078, 0x89df, 0x1078, 0x8ec9,
-	0x1078, 0x8ed6, 0x0d7f, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c,
-	0xa186, 0x0015, 0x00c0, 0x7942, 0x2001, 0xa9a4, 0x2004, 0x683e,
-	0x0078, 0x7950, 0xa18e, 0x0016, 0x00c0, 0x7952, 0x0c7e, 0x2d00,
-	0x2060, 0x1078, 0xa4a5, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x0c7f,
-	0x1078, 0x772d, 0x007c, 0x027e, 0x037e, 0x047e, 0x7228, 0x7c80,
-	0x7b7c, 0xd2f4, 0x0040, 0x7962, 0x2001, 0xa9a4, 0x2004, 0x683e,
-	0x0078, 0x79c6, 0x0c7e, 0x2d60, 0x1078, 0x8a03, 0x0c7f, 0x6804,
-	0xa086, 0x0050, 0x00c0, 0x797a, 0x0c7e, 0x2d00, 0x2060, 0x6003,
-	0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f,
-	0x0078, 0x79c6, 0x6800, 0xa086, 0x000f, 0x0040, 0x799c, 0x8fff,
-	0x1040, 0x1332, 0x6824, 0xd0dc, 0x00c0, 0x799c, 0x6800, 0xa086,
-	0x0004, 0x00c0, 0x79a1, 0x784c, 0xd0ac, 0x0040, 0x79a1, 0x784c,
-	0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001,
-	0x0001, 0x682e, 0x0078, 0x79c0, 0x2001, 0x0007, 0x682e, 0x0078,
-	0x79c0, 0x784c, 0xd0b4, 0x00c0, 0x79ae, 0xd0ac, 0x0040, 0x799c,
-	0x784c, 0xd0f4, 0x00c0, 0x799c, 0x0078, 0x798f, 0xd2ec, 0x00c0,
-	0x799c, 0x7024, 0xa306, 0x00c0, 0x79b9, 0x7020, 0xa406, 0x0040,
-	0x799c, 0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e,
-	0x1078, 0x9000, 0x1078, 0x62d1, 0x0078, 0x79c8, 0x1078, 0x772d,
-	0x047f, 0x037f, 0x027f, 0x007c, 0x0e7e, 0x0d7e, 0x027e, 0x6034,
-	0x2068, 0x6a1c, 0xa286, 0x0007, 0x0040, 0x7a35, 0xa286, 0x0002,
-	0x0040, 0x7a35, 0xa286, 0x0000, 0x0040, 0x7a35, 0x6808, 0x6338,
-	0xa306, 0x00c0, 0x7a35, 0x2071, 0xac8c, 0xa186, 0x0015, 0x0040,
-	0x7a2f, 0xa18e, 0x0016, 0x00c0, 0x7a02, 0x6030, 0xa084, 0x00ff,
-	0xa086, 0x0001, 0x00c0, 0x7a02, 0x700c, 0xa086, 0x2a00, 0x00c0,
-	0x7a02, 0x6034, 0xa080, 0x0009, 0x200c, 0xc1dd, 0xc1f5, 0x2102,
-	0x0078, 0x7a2f, 0x0c7e, 0x6034, 0x2060, 0x6104, 0xa186, 0x004b,
-	0x0040, 0x7a22, 0xa186, 0x004c, 0x0040, 0x7a22, 0xa186, 0x004d,
-	0x0040, 0x7a22, 0xa186, 0x004e, 0x0040, 0x7a22, 0xa186, 0x0052,
-	0x0040, 0x7a22, 0x6010, 0x2068, 0x1078, 0x8d16, 0x1040, 0x1332,
-	0x6853, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002,
-	0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7f, 0x0078, 0x7a35, 0x6034,
-	0x2068, 0x2001, 0xa9a4, 0x2004, 0x683e, 0x1078, 0x772d, 0x027f,
-	0x0d7f, 0x0e7f, 0x007c, 0x0d7e, 0x20a9, 0x000e, 0x2e98, 0x6010,
-	0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x00c0, 0x7a73, 0x6018, 0x2068,
-	0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290, 0x0004, 0x20a9,
-	0x0004, 0xad98, 0x000a, 0x1078, 0x80de, 0x027f, 0x037f, 0x157f,
-	0x00c0, 0x7a76, 0x157e, 0x037e, 0x027e, 0xae90, 0x000c, 0xa290,
-	0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x1078, 0x80de, 0x027f,
-	0x037f, 0x157f, 0x00c0, 0x7a76, 0x7038, 0x680a, 0x703c, 0x680e,
-	0x6800, 0xc08d, 0x6802, 0x0d7f, 0x0078, 0x77f8, 0x1078, 0x2880,
-	0x0c7e, 0x1078, 0x76c7, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f,
-	0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x1078,
-	0x4502, 0x1078, 0x4535, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7f,
-	0x0078, 0x7a73, 0x2100, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0xa1b2,
-	0x0040, 0x00c8, 0x7af7, 0x0079, 0x7a9d, 0x7aeb, 0x7adf, 0x7aeb,
-	0x7aeb, 0x7aeb, 0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add,
-	0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add,
-	0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add,
-	0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7aeb, 0x7aeb,
-	0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add,
-	0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7aeb,
-	0x7aeb, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add, 0x7add,
-	0x7add, 0x7add, 0x7aeb, 0x7add, 0x7add, 0x1078, 0x1332, 0x6003,
-	0x0001, 0x6106, 0x1078, 0x5dd7, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x62d1, 0x127f, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5dd7,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x2600,
-	0x0079, 0x7afa, 0x7afe, 0x7afe, 0x7afe, 0x7aeb, 0x1078, 0x1332,
-	0x6004, 0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0,
-	0x7b10, 0xa0b2, 0x0040, 0x00c8, 0x7c79, 0x2008, 0x0079, 0x7bbf,
-	0xa1b6, 0x0027, 0x00c0, 0x7b7c, 0x1078, 0x61cd, 0x6004, 0x1078,
-	0x8efc, 0x0040, 0x7b2d, 0x1078, 0x8f10, 0x0040, 0x7b74, 0xa08e,
-	0x0021, 0x0040, 0x7b78, 0xa08e, 0x0022, 0x0040, 0x7b74, 0xa08e,
-	0x003d, 0x0040, 0x7b78, 0x0078, 0x7b6f, 0x1078, 0x28a6, 0x2001,
-	0x0007, 0x1078, 0x4502, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078,
-	0x7c83, 0xa186, 0x007e, 0x00c0, 0x7b42, 0x2001, 0xa733, 0x2014,
-	0xc285, 0x2202, 0x017e, 0x027e, 0x037e, 0x2110, 0x027e, 0x2019,
-	0x0028, 0x1078, 0x73d0, 0x027f, 0x1078, 0xa501, 0x037f, 0x027f,
-	0x017f, 0x017e, 0x027e, 0x037e, 0x2110, 0x2019, 0x0028, 0x1078,
-	0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x0c7e, 0x6018,
-	0xa065, 0x0040, 0x7b65, 0x1078, 0x47e9, 0x0c7f, 0x2c08, 0x1078,
-	0x9f9b, 0x077f, 0x037f, 0x027f, 0x017f, 0x1078, 0x457f, 0x1078,
-	0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x7b6f,
-	0x1078, 0x7ca6, 0x0078, 0x7b6f, 0xa186, 0x0014, 0x00c0, 0x7b73,
-	0x1078, 0x61cd, 0x1078, 0x2880, 0x1078, 0x8efc, 0x00c0, 0x7b9b,
-	0x1078, 0x28a6, 0x6018, 0xa080, 0x0028, 0x200c, 0x1078, 0x7c83,
-	0xa186, 0x007e, 0x00c0, 0x7b99, 0x2001, 0xa733, 0x200c, 0xc185,
-	0x2102, 0x0078, 0x7b6f, 0x1078, 0x8f10, 0x00c0, 0x7ba3, 0x1078,
-	0x7c83, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0032, 0x00c0, 0x7bb4,
-	0x0e7e, 0x0f7e, 0x2071, 0xa782, 0x2079, 0x0000, 0x1078, 0x2bd7,
-	0x0f7f, 0x0e7f, 0x0078, 0x7b6f, 0x6004, 0xa08e, 0x0021, 0x0040,
-	0x7b9f, 0xa08e, 0x0022, 0x1040, 0x7c83, 0x0078, 0x7b6f, 0x7c01,
-	0x7c03, 0x7c07, 0x7c0b, 0x7c0f, 0x7c13, 0x7bff, 0x7bff, 0x7bff,
-	0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
-	0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
-	0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c17, 0x7c29, 0x7bff,
-	0x7c2b, 0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7c29,
-	0x7c29, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
-	0x7bff, 0x7c5c, 0x7c29, 0x7bff, 0x7c23, 0x7bff, 0x7bff, 0x7bff,
-	0x7c25, 0x7bff, 0x7bff, 0x7bff, 0x7c29, 0x7bff, 0x7bff, 0x1078,
-	0x1332, 0x0078, 0x7c29, 0x2001, 0x000b, 0x0078, 0x7c36, 0x2001,
-	0x0003, 0x0078, 0x7c36, 0x2001, 0x0005, 0x0078, 0x7c36, 0x2001,
-	0x0001, 0x0078, 0x7c36, 0x2001, 0x0009, 0x0078, 0x7c36, 0x1078,
-	0x61cd, 0x6003, 0x0005, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x1078,
-	0x62d1, 0x0078, 0x7c35, 0x0078, 0x7c29, 0x0078, 0x7c29, 0x1078,
-	0x4502, 0x0078, 0x7c6e, 0x1078, 0x61cd, 0x6003, 0x0004, 0x2001,
-	0xa9a2, 0x2004, 0x6016, 0x1078, 0x62d1, 0x007c, 0x1078, 0x4502,
-	0x1078, 0x61cd, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002,
-	0x037e, 0x2019, 0xa75d, 0x2304, 0xa084, 0xff00, 0x00c0, 0x7c4d,
-	0x2019, 0xa9a2, 0x231c, 0x0078, 0x7c56, 0x8007, 0xa09a, 0x0004,
-	0x0048, 0x7c48, 0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x037f,
-	0x1078, 0x62d1, 0x0078, 0x7c35, 0x0e7e, 0x0f7e, 0x2071, 0xa782,
-	0x2079, 0x0000, 0x1078, 0x2bd7, 0x0f7f, 0x0e7f, 0x1078, 0x61cd,
-	0x1078, 0x772d, 0x1078, 0x62d1, 0x0078, 0x7c35, 0x1078, 0x61cd,
-	0x6003, 0x0002, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x1078, 0x62d1,
-	0x007c, 0x2600, 0x2008, 0x0079, 0x7c7d, 0x7c81, 0x7c81, 0x7c81,
-	0x7c6e, 0x1078, 0x1332, 0x0e7e, 0x1078, 0x8d16, 0x0040, 0x7c9f,
-	0x6010, 0x2070, 0x7038, 0xd0fc, 0x0040, 0x7c9f, 0x7007, 0x0000,
-	0x017e, 0x6004, 0xa08e, 0x0021, 0x0040, 0x7ca1, 0xa08e, 0x003d,
-	0x0040, 0x7ca1, 0x017f, 0x7037, 0x0103, 0x7033, 0x0100, 0x0e7f,
-	0x007c, 0x017f, 0x1078, 0x7ca6, 0x0078, 0x7c9f, 0x0e7e, 0xacf0,
-	0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x7023, 0x8001,
-	0x0e7f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084, 0x00ff,
-	0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0x6604, 0xa6b6, 0x0043,
-	0x00c0, 0x7cc6, 0x1078, 0x9144, 0x0078, 0x7d25, 0x6604, 0xa6b6,
-	0x0033, 0x00c0, 0x7ccf, 0x1078, 0x90e8, 0x0078, 0x7d25, 0x6604,
-	0xa6b6, 0x0028, 0x00c0, 0x7cd8, 0x1078, 0x8f3f, 0x0078, 0x7d25,
-	0x6604, 0xa6b6, 0x0029, 0x00c0, 0x7ce1, 0x1078, 0x8f59, 0x0078,
-	0x7d25, 0x6604, 0xa6b6, 0x001f, 0x00c0, 0x7cea, 0x1078, 0x77de,
-	0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0000, 0x00c0, 0x7cf3, 0x1078,
-	0x7a3b, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0022, 0x00c0, 0x7cfc,
-	0x1078, 0x7807, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0035, 0x00c0,
-	0x7d05, 0x1078, 0x7843, 0x0078, 0x7d25, 0x6604, 0xa6b6, 0x0039,
-	0x00c0, 0x7d0e, 0x1078, 0x79cc, 0x0078, 0x7d25, 0x6604, 0xa6b6,
-	0x003d, 0x00c0, 0x7d17, 0x1078, 0x7823, 0x0078, 0x7d25, 0xa1b6,
-	0x0015, 0x00c0, 0x7d1f, 0x1079, 0x7d2a, 0x0078, 0x7d25, 0xa1b6,
-	0x0016, 0x00c0, 0x7d26, 0x1079, 0x7e7f, 0x007c, 0x1078, 0x7773,
-	0x0078, 0x7d25, 0x7d4e, 0x7d51, 0x7d4e, 0x7d9c, 0x7d4e, 0x7e13,
-	0x7e8b, 0x7d4e, 0x7d4e, 0x7e57, 0x7d4e, 0x7e6d, 0xa1b6, 0x0048,
-	0x0040, 0x7d42, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078,
-	0x15fa, 0x007c, 0x0e7e, 0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070,
-	0x7037, 0x0103, 0x0e7f, 0x1078, 0x772d, 0x007c, 0x0005, 0x0005,
-	0x007c, 0x0e7e, 0x2071, 0xa700, 0x7080, 0xa086, 0x0074, 0x00c0,
-	0x7d85, 0x1078, 0x9f6f, 0x00c0, 0x7d77, 0x0d7e, 0x6018, 0x2068,
-	0x7030, 0xd08c, 0x0040, 0x7d6a, 0x6800, 0xd0bc, 0x0040, 0x7d6a,
-	0xc0c5, 0x6802, 0x1078, 0x7d89, 0x0d7f, 0x2001, 0x0006, 0x1078,
-	0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078, 0x7d87, 0x2001,
-	0x000a, 0x1078, 0x4502, 0x1078, 0x28a6, 0x6003, 0x0001, 0x6007,
-	0x0001, 0x1078, 0x5dd7, 0x0078, 0x7d87, 0x1078, 0x7dff, 0x0e7f,
-	0x007c, 0x6800, 0xd084, 0x0040, 0x7d9b, 0x2001, 0x0000, 0x1078,
-	0x44ee, 0x2069, 0xa752, 0x6804, 0xd0a4, 0x0040, 0x7d9b, 0x2001,
-	0x0006, 0x1078, 0x4535, 0x007c, 0x0d7e, 0x2011, 0xa720, 0x2204,
-	0xa086, 0x0074, 0x00c0, 0x7dfb, 0x6018, 0x2068, 0x6aa0, 0xa286,
-	0x007e, 0x00c0, 0x7daf, 0x1078, 0x7f9b, 0x0078, 0x7dfd, 0x1078,
-	0x7f91, 0x6018, 0x2068, 0xa080, 0x0028, 0x2014, 0xa286, 0x0080,
-	0x00c0, 0x7dd3, 0x6813, 0x00ff, 0x6817, 0xfffc, 0x6010, 0xa005,
-	0x0040, 0x7dc9, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6833,
-	0x0200, 0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x28a6, 0x1078,
-	0x772d, 0x0078, 0x7dfd, 0x0e7e, 0x2071, 0xa733, 0x2e04, 0xd09c,
-	0x0040, 0x7dee, 0x2071, 0xac80, 0x7108, 0x720c, 0xa18c, 0x00ff,
-	0x00c0, 0x7de6, 0xa284, 0xff00, 0x0040, 0x7dee, 0x6018, 0x2070,
-	0x70a0, 0xd0bc, 0x00c0, 0x7dee, 0x7112, 0x7216, 0x0e7f, 0x2001,
-	0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003, 0x1078,
-	0x5dd7, 0x0078, 0x7dfd, 0x1078, 0x7dff, 0x0d7f, 0x007c, 0x2001,
-	0x0007, 0x1078, 0x4502, 0x2001, 0xa700, 0x2004, 0xa086, 0x0003,
-	0x00c0, 0x7e0e, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x28a6,
-	0x1078, 0x772d, 0x007c, 0x0e7e, 0x2071, 0xa700, 0x7080, 0xa086,
-	0x0014, 0x00c0, 0x7e51, 0x7000, 0xa086, 0x0003, 0x00c0, 0x7e26,
-	0x6010, 0xa005, 0x00c0, 0x7e26, 0x1078, 0x3699, 0x0d7e, 0x6018,
-	0x2068, 0x1078, 0x4649, 0x1078, 0x7d89, 0x0d7f, 0x1078, 0x8043,
-	0x00c0, 0x7e51, 0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005,
-	0x0040, 0x7e51, 0x2001, 0x0006, 0x1078, 0x4502, 0x0e7e, 0x6010,
-	0xa005, 0x0040, 0x7e4a, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103,
-	0x7033, 0x0200, 0x0e7f, 0x1078, 0x28a6, 0x1078, 0x772d, 0x0078,
-	0x7e55, 0x1078, 0x7c83, 0x1078, 0x7dff, 0x0e7f, 0x007c, 0x2011,
-	0xa720, 0x2204, 0xa086, 0x0014, 0x00c0, 0x7e6a, 0x2001, 0x0002,
-	0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078, 0x5dd7,
-	0x0078, 0x7e6c, 0x1078, 0x7dff, 0x007c, 0x2011, 0xa720, 0x2204,
-	0xa086, 0x0004, 0x00c0, 0x7e7c, 0x2001, 0x0007, 0x1078, 0x4502,
-	0x1078, 0x772d, 0x0078, 0x7e7e, 0x1078, 0x7dff, 0x007c, 0x7d4e,
-	0x7e97, 0x7d4e, 0x7ed2, 0x7d4e, 0x7f44, 0x7e8b, 0x7d4e, 0x7d4e,
-	0x7f59, 0x7d4e, 0x7f6c, 0x6604, 0xa686, 0x0003, 0x0040, 0x7e13,
-	0xa6b6, 0x001e, 0x00c0, 0x7e96, 0x1078, 0x772d, 0x007c, 0x0d7e,
-	0x0c7e, 0x1078, 0x7f7f, 0x00c0, 0x7ead, 0x2001, 0x0000, 0x1078,
-	0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x1078, 0x5dd7, 0x0078, 0x7ecf, 0x2009, 0xac8e, 0x2104,
-	0xa086, 0x0009, 0x00c0, 0x7ec2, 0x6018, 0x2068, 0x6840, 0xa084,
-	0x00ff, 0xa005, 0x0040, 0x7ecd, 0x8001, 0x6842, 0x6017, 0x000a,
-	0x0078, 0x7ecf, 0x2009, 0xac8f, 0x2104, 0xa084, 0xff00, 0xa086,
-	0x1900, 0x00c0, 0x7ecd, 0x0078, 0x7ea1, 0x1078, 0x7dff, 0x0c7f,
-	0x0d7f, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7ee6, 0x2001, 0x0000,
-	0x1078, 0x44ee, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003, 0x0001,
-	0x6007, 0x0002, 0x1078, 0x5dd7, 0x0078, 0x7f12, 0x1078, 0x7c83,
-	0x2009, 0xac8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0040,
-	0x7f13, 0xa686, 0x000b, 0x0040, 0x7f10, 0x2009, 0xac8f, 0x2104,
-	0xa084, 0xff00, 0x00c0, 0x7f00, 0xa686, 0x0009, 0x0040, 0x7f13,
-	0xa086, 0x1900, 0x00c0, 0x7f10, 0xa686, 0x0009, 0x0040, 0x7f13,
-	0x2001, 0x0004, 0x1078, 0x4502, 0x1078, 0x772d, 0x0078, 0x7f12,
-	0x1078, 0x7dff, 0x007c, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16,
-	0x0040, 0x7f21, 0x6838, 0xd0fc, 0x0040, 0x7f21, 0x0d7f, 0x0078,
-	0x7f10, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0040,
-	0x7f32, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x0d7f,
-	0x0078, 0x7f12, 0x68a0, 0xa086, 0x007e, 0x00c0, 0x7f3f, 0x0e7e,
-	0x2071, 0xa700, 0x1078, 0x42b8, 0x0e7f, 0x0078, 0x7f41, 0x1078,
-	0x2880, 0x0d7f, 0x0078, 0x7f10, 0x1078, 0x7f8e, 0x00c0, 0x7f54,
-	0x2001, 0x0004, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0003,
-	0x1078, 0x5dd7, 0x0078, 0x7f58, 0x1078, 0x7c83, 0x1078, 0x7dff,
-	0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f69, 0x2001, 0x0008, 0x1078,
-	0x4502, 0x6003, 0x0001, 0x6007, 0x0005, 0x1078, 0x5dd7, 0x0078,
-	0x7f6b, 0x1078, 0x7dff, 0x007c, 0x1078, 0x7f8e, 0x00c0, 0x7f7c,
-	0x2001, 0x000a, 0x1078, 0x4502, 0x6003, 0x0001, 0x6007, 0x0001,
-	0x1078, 0x5dd7, 0x0078, 0x7f7e, 0x1078, 0x7dff, 0x007c, 0x2009,
-	0xac8e, 0x2104, 0xa086, 0x0003, 0x00c0, 0x7f8d, 0x2009, 0xac8f,
-	0x2104, 0xa084, 0xff00, 0xa086, 0x2a00, 0x007c, 0xa085, 0x0001,
-	0x007c, 0x0c7e, 0x017e, 0xac88, 0x0006, 0x2164, 0x1078, 0x45d6,
-	0x017f, 0x0c7f, 0x007c, 0x0f7e, 0x0e7e, 0x0d7e, 0x037e, 0x017e,
-	0x6018, 0x2068, 0x2071, 0xa733, 0x2e04, 0xa085, 0x0003, 0x2072,
-	0x1078, 0x8014, 0x0040, 0x7fd9, 0x2009, 0xa733, 0x2104, 0xc0cd,
-	0x200a, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040, 0x7fc2, 0xa006,
-	0x2020, 0x2009, 0x002a, 0x1078, 0xa22d, 0x2001, 0xa70c, 0x200c,
-	0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x1078, 0x284f,
-	0x2071, 0xa700, 0x1078, 0x2677, 0x0c7e, 0x157e, 0x20a9, 0x0081,
-	0x2009, 0x007f, 0x1078, 0x298e, 0x8108, 0x00f0, 0x7fd2, 0x157f,
-	0x0c7f, 0x1078, 0x7f91, 0x6813, 0x00ff, 0x6817, 0xfffe, 0x2071,
-	0xac80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069, 0xa71b,
-	0x206a, 0x78e6, 0x007e, 0x8e70, 0x2e04, 0x2069, 0xa71c, 0x206a,
-	0x78ea, 0xa084, 0xff00, 0x017f, 0xa105, 0x2009, 0xa726, 0x200a,
-	0x2069, 0xac8e, 0x2071, 0xa99e, 0x6810, 0x2072, 0x6814, 0x7006,
-	0x6818, 0x700a, 0x681c, 0x700e, 0x1078, 0x907e, 0x2001, 0x0006,
-	0x1078, 0x4502, 0x1078, 0x28a6, 0x1078, 0x772d, 0x017f, 0x037f,
-	0x0d7f, 0x0e7f, 0x0f7f, 0x007c, 0x027e, 0x037e, 0x0e7e, 0x157e,
-	0x2019, 0xa726, 0x231c, 0x83ff, 0x0040, 0x803e, 0x2071, 0xac80,
-	0x2e14, 0xa294, 0x00ff, 0x7004, 0xa084, 0xff00, 0xa205, 0xa306,
-	0x00c0, 0x803e, 0x2011, 0xac96, 0xad98, 0x000a, 0x20a9, 0x0004,
-	0x1078, 0x80de, 0x00c0, 0x803e, 0x2011, 0xac9a, 0xad98, 0x0006,
-	0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x803e, 0x157f, 0x0e7f,
-	0x037f, 0x027f, 0x007c, 0x0e7e, 0x2071, 0xac8c, 0x7004, 0xa086,
-	0x0014, 0x00c0, 0x8066, 0x7008, 0xa086, 0x0800, 0x00c0, 0x8066,
-	0x700c, 0xd0ec, 0x0040, 0x8064, 0xa084, 0x0f00, 0xa086, 0x0100,
-	0x00c0, 0x8064, 0x7024, 0xd0a4, 0x00c0, 0x8061, 0xd0ac, 0x0040,
-	0x8064, 0xa006, 0x0078, 0x8066, 0xa085, 0x0001, 0x0e7f, 0x007c,
-	0x0e7e, 0x0d7e, 0x0c7e, 0x077e, 0x057e, 0x047e, 0x027e, 0x007e,
-	0x127e, 0x2091, 0x8000, 0x2029, 0xa9ba, 0x252c, 0x2021, 0xa9c0,
-	0x2424, 0x2061, 0xae00, 0x2071, 0xa700, 0x7248, 0x7064, 0xa202,
-	0x00c8, 0x80cc, 0x1078, 0xa252, 0x0040, 0x80c4, 0x671c, 0xa786,
-	0x0001, 0x0040, 0x80c4, 0xa786, 0x0007, 0x0040, 0x80c4, 0x2500,
-	0xac06, 0x0040, 0x80c4, 0x2400, 0xac06, 0x0040, 0x80c4, 0x0c7e,
-	0x6000, 0xa086, 0x0004, 0x00c0, 0x809f, 0x1078, 0x1757, 0xa786,
-	0x0008, 0x00c0, 0x80ae, 0x1078, 0x8f10, 0x00c0, 0x80ae, 0x0c7f,
-	0x1078, 0x7c83, 0x1078, 0x8ed6, 0x0078, 0x80c4, 0x6010, 0x2068,
-	0x1078, 0x8d16, 0x0040, 0x80c1, 0xa786, 0x0003, 0x00c0, 0x80d6,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0x4a73, 0x1078,
-	0x8ec9, 0x1078, 0x8ed6, 0x0c7f, 0xace0, 0x0010, 0x7058, 0xac02,
-	0x00c8, 0x80cc, 0x0078, 0x807d, 0x127f, 0x007f, 0x027f, 0x047f,
-	0x057f, 0x077f, 0x0c7f, 0x0d7f, 0x0e7f, 0x007c, 0xa786, 0x0006,
-	0x00c0, 0x80b8, 0x1078, 0xa1da, 0x0078, 0x80c1, 0x220c, 0x2304,
-	0xa106, 0x00c0, 0x80e9, 0x8210, 0x8318, 0x00f0, 0x80de, 0xa006,
-	0x007c, 0x2304, 0xa102, 0x0048, 0x80f1, 0x2001, 0x0001, 0x0078,
-	0x80f3, 0x2001, 0x0000, 0xa18d, 0x0001, 0x007c, 0x6004, 0xa08a,
-	0x0044, 0x10c8, 0x1332, 0x1078, 0x8efc, 0x0040, 0x8105, 0x1078,
-	0x8f10, 0x0040, 0x8112, 0x0078, 0x810b, 0x1078, 0x28a6, 0x1078,
-	0x8f10, 0x0040, 0x8112, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078,
-	0x62d1, 0x007c, 0x1078, 0x7c83, 0x0078, 0x810b, 0xa182, 0x0040,
-	0x0079, 0x811a, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812d,
-	0x812d, 0x812d, 0x812d, 0x812d, 0x812d, 0x812f, 0x812f, 0x812f,
-	0x812f, 0x812d, 0x812d, 0x812d, 0x812f, 0x1078, 0x1332, 0x600b,
-	0xffff, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091,
-	0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0xa186, 0x0013, 0x00c0,
-	0x8146, 0x6004, 0xa082, 0x0040, 0x0079, 0x81d1, 0xa186, 0x0027,
-	0x00c0, 0x8168, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6110,
-	0x2168, 0x1078, 0x8d16, 0x0040, 0x8162, 0x6837, 0x0103, 0x684b,
-	0x0029, 0x6847, 0x0000, 0x694c, 0xc1c5, 0x694e, 0x1078, 0x4a73,
-	0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c,
-	0xa186, 0x0014, 0x00c0, 0x8171, 0x6004, 0xa082, 0x0040, 0x0079,
-	0x8199, 0xa186, 0x0046, 0x0040, 0x817d, 0xa186, 0x0045, 0x0040,
-	0x817d, 0xa186, 0x0047, 0x10c0, 0x1332, 0x2001, 0x0109, 0x2004,
-	0xd084, 0x0040, 0x8196, 0x127e, 0x2091, 0x2200, 0x007e, 0x017e,
-	0x027e, 0x1078, 0x5c56, 0x027f, 0x017f, 0x007f, 0x127f, 0x6000,
-	0xa086, 0x0002, 0x00c0, 0x8196, 0x0078, 0x820e, 0x1078, 0x7773,
-	0x007c, 0x81ae, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ac,
-	0x81ac, 0x81ac, 0x81ac, 0x81ac, 0x81ca, 0x81ca, 0x81ca, 0x81ca,
-	0x81ac, 0x81ca, 0x81ac, 0x81ca, 0x1078, 0x1332, 0x1078, 0x61cd,
-	0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d16, 0x0040, 0x81c4, 0x6837,
-	0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852,
-	0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078,
-	0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1,
-	0x007c, 0x81e6, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81e4,
-	0x81e4, 0x81e4, 0x81e4, 0x81e4, 0x81f8, 0x81f8, 0x81f8, 0x81f8,
-	0x81e4, 0x8207, 0x81e4, 0x81f8, 0x1078, 0x1332, 0x1078, 0x61cd,
-	0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x62d1,
-	0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x007c,
-	0x1078, 0x61cd, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x2001, 0xa9a4,
-	0x2004, 0x603e, 0x6003, 0x000f, 0x1078, 0x62d1, 0x007c, 0x1078,
-	0x61cd, 0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x8212, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8227,
-	0x8331, 0x8363, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x8225,
-	0x8225, 0x8225, 0x8225, 0x8225, 0x8225, 0x1078, 0x1332, 0x0e7e,
-	0x0d7e, 0x603f, 0x0000, 0x2071, 0xac80, 0x7124, 0x610a, 0x2071,
-	0xac8c, 0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0040,
-	0x82f0, 0xa68c, 0x0c00, 0x0040, 0x8265, 0x0f7e, 0x2c78, 0x1078,
-	0x4963, 0x0f7f, 0x0040, 0x8261, 0x684c, 0xd0ac, 0x0040, 0x8261,
-	0x6024, 0xd0dc, 0x00c0, 0x8261, 0x6850, 0xd0bc, 0x00c0, 0x8261,
-	0x7318, 0x6814, 0xa306, 0x00c0, 0x8308, 0x731c, 0x6810, 0xa31e,
-	0x0040, 0x8261, 0xd6d4, 0x0040, 0x8308, 0x6b14, 0xa305, 0x00c0,
-	0x8308, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
-	0x0002, 0x0040, 0x8298, 0xa186, 0x0028, 0x00c0, 0x8275, 0x1078,
-	0x8eea, 0x684b, 0x001c, 0x0078, 0x829a, 0xd6dc, 0x0040, 0x8291,
-	0x684b, 0x0015, 0x684c, 0xd0ac, 0x0040, 0x828f, 0x6914, 0x6a10,
-	0x2100, 0xa205, 0x0040, 0x828f, 0x7018, 0xa106, 0x00c0, 0x828c,
-	0x701c, 0xa206, 0x0040, 0x828f, 0x6962, 0x6a5e, 0xc6dc, 0x0078,
-	0x829a, 0xd6d4, 0x0040, 0x8298, 0x684b, 0x0007, 0x0078, 0x829a,
-	0x684b, 0x0000, 0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x0040,
-	0x82c3, 0xa686, 0x0100, 0x00c0, 0x82ae, 0x2001, 0xac99, 0x2004,
-	0xa005, 0x00c0, 0x82ae, 0xc6c4, 0x0078, 0x8236, 0x7328, 0x732c,
-	0x6b56, 0x83ff, 0x0040, 0x82c3, 0xa38a, 0x0009, 0x0048, 0x82ba,
-	0x2019, 0x0008, 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019,
-	0x1078, 0x89f2, 0x037f, 0xd6cc, 0x0040, 0x831e, 0x7124, 0x695a,
-	0x81ff, 0x0040, 0x831e, 0xa192, 0x0021, 0x00c8, 0x82dc, 0x2071,
-	0xac98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2,
-	0x1078, 0x9204, 0x0078, 0x831e, 0x6838, 0xd0fc, 0x0040, 0x82e5,
-	0x2009, 0x0020, 0x695a, 0x0078, 0x82cf, 0x0f7e, 0x2d78, 0x1078,
-	0x898a, 0x0f7f, 0x1078, 0x9204, 0x1078, 0x89df, 0x0078, 0x8320,
-	0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x830e, 0x684c,
-	0xd0ac, 0x0040, 0x830e, 0x6024, 0xd0dc, 0x00c0, 0x830e, 0x6850,
-	0xd0bc, 0x00c0, 0x830e, 0x6810, 0x6914, 0xa105, 0x0040, 0x830e,
-	0x1078, 0x8fcf, 0x0d7f, 0x0e7f, 0x0078, 0x8330, 0x684b, 0x0000,
-	0x6837, 0x0103, 0x6e46, 0x684c, 0xd0ac, 0x0040, 0x831e, 0x6810,
-	0x6914, 0xa115, 0x0040, 0x831e, 0x1078, 0x84e2, 0x1078, 0x4a73,
-	0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x8328, 0x8211, 0x6a3e,
-	0x1078, 0x8f99, 0x0d7f, 0x0e7f, 0x00c0, 0x8330, 0x1078, 0x772d,
-	0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xac8c, 0x7c04, 0x7b00,
-	0x7e0c, 0x7d08, 0x6010, 0x2078, 0x784c, 0xd0ac, 0x0040, 0x8348,
-	0x6003, 0x0002, 0x0f7f, 0x007c, 0x2130, 0x2228, 0x0078, 0x8354,
-	0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80, 0xa213, 0x2600, 0xa102,
-	0x2500, 0xa203, 0x0048, 0x8344, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e,
-	0x0f7f, 0x603f, 0x0000, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6,
-	0x1078, 0x639b, 0x007c, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x6003,
-	0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078,
-	0x15fa, 0x007c, 0xa182, 0x0040, 0x0079, 0x8376, 0x8389, 0x8389,
-	0x8389, 0x8389, 0x8389, 0x838b, 0x8431, 0x8389, 0x8389, 0x8447,
-	0x84b8, 0x8389, 0x8389, 0x8389, 0x8389, 0x84c7, 0x8389, 0x8389,
-	0x8389, 0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071,
-	0xac8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46, 0x7f4c,
-	0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040, 0x83a2,
-	0x8211, 0x6a3e, 0x86ff, 0x0040, 0x842c, 0xa694, 0xff00, 0xa284,
-	0x0c00, 0x0040, 0x83af, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284,
-	0x0300, 0x0040, 0x842c, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00,
-	0x784a, 0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a,
-	0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0040,
-	0x83cd, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186,
-	0x0002, 0x0040, 0x83e9, 0xa186, 0x0028, 0x00c0, 0x83db, 0x684b,
-	0x001c, 0x0078, 0x83eb, 0xd6dc, 0x0040, 0x83e2, 0x684b, 0x0015,
-	0x0078, 0x83eb, 0xd6d4, 0x0040, 0x83e9, 0x684b, 0x0007, 0x0078,
-	0x83eb, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856,
-	0xa01e, 0xd6c4, 0x0040, 0x8409, 0x7328, 0x732c, 0x6b56, 0x83ff,
-	0x0040, 0x8409, 0xa38a, 0x0009, 0x0048, 0x8400, 0x2019, 0x0008,
-	0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, 0x1078, 0x89f2,
-	0x037f, 0xd6cc, 0x0040, 0x842c, 0x7124, 0x695a, 0x81ff, 0x0040,
-	0x842c, 0xa192, 0x0021, 0x00c8, 0x8420, 0x2071, 0xac98, 0x831c,
-	0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, 0x0078, 0x842c,
-	0x7838, 0xd0fc, 0x0040, 0x8429, 0x2009, 0x0020, 0x695a, 0x0078,
-	0x8415, 0x2d78, 0x1078, 0x898a, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f,
-	0x007c, 0x0f7e, 0x6003, 0x0003, 0x2079, 0xac8c, 0x7c04, 0x7b00,
-	0x7e0c, 0x7d08, 0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e,
-	0x0f7f, 0x2c10, 0x1078, 0x1cf0, 0x1078, 0x6df4, 0x007c, 0x0d7e,
-	0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x8453, 0x2001,
-	0xa9a4, 0x2004, 0x603e, 0x6003, 0x0002, 0x1078, 0x627a, 0x1078,
-	0x639b, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040, 0x84b6, 0xd1cc,
-	0x0040, 0x848d, 0x6948, 0x6838, 0xd0fc, 0x0040, 0x8485, 0x017e,
-	0x684c, 0x007e, 0x6850, 0x007e, 0xad90, 0x000d, 0xa198, 0x000d,
-	0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318, 0x8210,
-	0x00f0, 0x8474, 0x157f, 0x007f, 0x6852, 0x007f, 0x684e, 0x017f,
-	0x2168, 0x1078, 0x13b4, 0x0078, 0x84b0, 0x017e, 0x1078, 0x13b4,
-	0x0d7f, 0x1078, 0x89df, 0x0078, 0x84b0, 0x6837, 0x0103, 0x6944,
-	0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040, 0x84ac, 0xa086, 0x0028,
-	0x00c0, 0x849e, 0x684b, 0x001c, 0x0078, 0x84ae, 0xd1dc, 0x0040,
-	0x84a5, 0x684b, 0x0015, 0x0078, 0x84ae, 0xd1d4, 0x0040, 0x84ac,
-	0x684b, 0x0007, 0x0078, 0x84ae, 0x684b, 0x0000, 0x1078, 0x4a73,
-	0x1078, 0x8f99, 0x00c0, 0x84b6, 0x1078, 0x772d, 0x0d7f, 0x007c,
-	0x2019, 0x0001, 0x1078, 0x7058, 0x6003, 0x0002, 0x2001, 0xa9a4,
-	0x2004, 0x603e, 0x1078, 0x627a, 0x1078, 0x639b, 0x007c, 0x1078,
-	0x627a, 0x1078, 0x2880, 0x0d7e, 0x6110, 0x2168, 0x1078, 0x8d16,
-	0x0040, 0x84dc, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000,
-	0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d, 0x1078,
-	0x639b, 0x007c, 0x684b, 0x0015, 0xd1fc, 0x0040, 0x84ee, 0x684b,
-	0x0007, 0x8002, 0x8000, 0x810a, 0xa189, 0x0000, 0x6962, 0x685e,
-	0x007c, 0xa182, 0x0040, 0x0079, 0x84f5, 0x8508, 0x8508, 0x8508,
-	0x8508, 0x8508, 0x850a, 0x8508, 0x85e0, 0x85ec, 0x8508, 0x8508,
-	0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508, 0x8508,
-	0x1078, 0x1332, 0x077e, 0x0f7e, 0x0e7e, 0x0d7e, 0x2071, 0xac8c,
-	0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x0f7e, 0x2c78, 0x1078,
-	0x4963, 0x0f7f, 0x0040, 0x8528, 0xa684, 0x00ff, 0x00c0, 0x8528,
-	0x6024, 0xd0f4, 0x0040, 0x8528, 0x1078, 0x8fcf, 0x0078, 0x85db,
-	0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff,
-	0x0040, 0x8534, 0x8211, 0x6a3e, 0x86ff, 0x0040, 0x85d0, 0xa694,
-	0xff00, 0xa284, 0x0c00, 0x0040, 0x8541, 0x7018, 0x7862, 0x701c,
-	0x785e, 0xa284, 0x0300, 0x0040, 0x85cd, 0xa686, 0x0100, 0x00c0,
-	0x8553, 0x2001, 0xac99, 0x2004, 0xa005, 0x00c0, 0x8553, 0xc6c4,
-	0x7e46, 0x0078, 0x8534, 0x1078, 0x138b, 0x1040, 0x1332, 0x2d00,
-	0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e, 0x6837, 0x0103, 0x7838,
-	0x683a, 0x783c, 0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00,
-	0x0040, 0x856e, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff,
-	0xa186, 0x0002, 0x0040, 0x858a, 0xa186, 0x0028, 0x00c0, 0x857c,
-	0x684b, 0x001c, 0x0078, 0x858c, 0xd6dc, 0x0040, 0x8583, 0x684b,
-	0x0015, 0x0078, 0x858c, 0xd6d4, 0x0040, 0x858a, 0x684b, 0x0007,
-	0x0078, 0x858c, 0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854,
-	0x6856, 0xa01e, 0xd6c4, 0x0040, 0x85aa, 0x7328, 0x732c, 0x6b56,
-	0x83ff, 0x0040, 0x85aa, 0xa38a, 0x0009, 0x0048, 0x85a1, 0x2019,
-	0x0008, 0x037e, 0x2308, 0x2019, 0xac98, 0xad90, 0x0019, 0x1078,
-	0x89f2, 0x037f, 0xd6cc, 0x0040, 0x85cd, 0x7124, 0x695a, 0x81ff,
-	0x0040, 0x85cd, 0xa192, 0x0021, 0x00c8, 0x85c1, 0x2071, 0xac98,
-	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x1078, 0x89f2, 0x0078,
-	0x85cd, 0x7838, 0xd0fc, 0x0040, 0x85ca, 0x2009, 0x0020, 0x695a,
-	0x0078, 0x85b6, 0x2d78, 0x1078, 0x898a, 0xd6dc, 0x00c0, 0x85d3,
-	0xa006, 0x0078, 0x85d9, 0x2001, 0x0001, 0x2071, 0xac8c, 0x7218,
-	0x731c, 0x1078, 0x1653, 0x0d7f, 0x0e7f, 0x0f7f, 0x077f, 0x007c,
-	0x2001, 0xa9a4, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x1078, 0x15fa, 0x007c, 0x2001, 0xa9a4, 0x2004, 0x603e,
-	0x0d7e, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0040,
-	0x871c, 0x603f, 0x0000, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x0f7f,
-	0x0040, 0x8632, 0x6814, 0x6910, 0xa115, 0x0040, 0x8632, 0x6a60,
-	0xa206, 0x00c0, 0x860f, 0x685c, 0xa106, 0x0040, 0x8632, 0x684c,
-	0xc0e4, 0x684e, 0x6847, 0x0000, 0x6863, 0x0000, 0x685f, 0x0000,
-	0x6024, 0xd0f4, 0x00c0, 0x8627, 0x697c, 0x6810, 0xa102, 0x603a,
-	0x6980, 0x6814, 0xa103, 0x6036, 0x6024, 0xc0f5, 0x6026, 0x0d7e,
-	0x6018, 0x2068, 0x683c, 0x8000, 0x683e, 0x0d7f, 0x1078, 0x8fcf,
-	0x0078, 0x871c, 0x694c, 0xd1cc, 0x0040, 0x86e1, 0x6948, 0x6838,
-	0xd0fc, 0x0040, 0x8699, 0x017e, 0x684c, 0x007e, 0x6850, 0x007e,
-	0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0040,
-	0x866c, 0xa086, 0x0028, 0x00c0, 0x8653, 0x684b, 0x001c, 0x784b,
-	0x001c, 0x0078, 0x8677, 0xd1dc, 0x0040, 0x8663, 0x684b, 0x0015,
-	0x784b, 0x0015, 0x1078, 0x917c, 0x0040, 0x8661, 0x7944, 0xc1dc,
-	0x7946, 0x0078, 0x8677, 0xd1d4, 0x0040, 0x866c, 0x684b, 0x0007,
-	0x784b, 0x0007, 0x0078, 0x8677, 0x684c, 0xd0ac, 0x0040, 0x8677,
-	0x6810, 0x6914, 0xa115, 0x0040, 0x8677, 0x1078, 0x84e2, 0x6848,
-	0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d, 0xaf98,
-	0x000d, 0x2009, 0x0020, 0x157e, 0x21a8, 0x2304, 0x2012, 0x8318,
-	0x8210, 0x00f0, 0x8685, 0x157f, 0x0f7f, 0x007f, 0x6852, 0x007f,
-	0x684e, 0x1078, 0x9204, 0x017f, 0x2168, 0x1078, 0x13b4, 0x0078,
-	0x8716, 0x017e, 0x0f7e, 0x2178, 0x7944, 0xa184, 0x00ff, 0xa0b6,
-	0x0002, 0x0040, 0x86c6, 0xa086, 0x0028, 0x00c0, 0x86ad, 0x684b,
-	0x001c, 0x784b, 0x001c, 0x0078, 0x86d1, 0xd1dc, 0x0040, 0x86bd,
-	0x684b, 0x0015, 0x784b, 0x0015, 0x1078, 0x917c, 0x0040, 0x86bb,
-	0x7944, 0xc1dc, 0x7946, 0x0078, 0x86d1, 0xd1d4, 0x0040, 0x86c6,
-	0x684b, 0x0007, 0x784b, 0x0007, 0x0078, 0x86d1, 0x684c, 0xd0ac,
-	0x0040, 0x86d1, 0x6810, 0x6914, 0xa115, 0x0040, 0x86d1, 0x1078,
-	0x84e2, 0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x0f7f,
-	0x1078, 0x13b4, 0x0d7f, 0x1078, 0x9204, 0x1078, 0x89df, 0x0078,
-	0x8716, 0x6837, 0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002,
-	0x0040, 0x8707, 0xa086, 0x0028, 0x00c0, 0x86f2, 0x684b, 0x001c,
-	0x0078, 0x8714, 0xd1dc, 0x0040, 0x8700, 0x684b, 0x0015, 0x1078,
-	0x917c, 0x0040, 0x86fe, 0x6944, 0xc1dc, 0x6946, 0x0078, 0x8714,
-	0xd1d4, 0x0040, 0x8707, 0x684b, 0x0007, 0x0078, 0x8714, 0x684b,
-	0x0000, 0x684c, 0xd0ac, 0x0040, 0x8714, 0x6810, 0x6914, 0xa115,
-	0x0040, 0x8714, 0x1078, 0x84e2, 0x1078, 0x4a73, 0x1078, 0x8f99,
-	0x00c0, 0x871c, 0x1078, 0x772d, 0x0d7f, 0x007c, 0x1078, 0x61cd,
-	0x0078, 0x8724, 0x1078, 0x627a, 0x1078, 0x8d16, 0x0040, 0x8743,
-	0x0d7e, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xa70c, 0x210c,
-	0xd18c, 0x00c0, 0x874e, 0xd184, 0x00c0, 0x874a, 0x6108, 0x694a,
-	0xa18e, 0x0029, 0x00c0, 0x873e, 0x1078, 0xa4f2, 0x6847, 0x0000,
-	0x1078, 0x4a73, 0x0d7f, 0x1078, 0x772d, 0x1078, 0x62d1, 0x1078,
-	0x639b, 0x007c, 0x684b, 0x0004, 0x0078, 0x873e, 0x684b, 0x0004,
-	0x0078, 0x873e, 0xa182, 0x0040, 0x0079, 0x8756, 0x8769, 0x8769,
-	0x8769, 0x8769, 0x8769, 0x876b, 0x8769, 0x876e, 0x8769, 0x8769,
-	0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769, 0x8769,
-	0x8769, 0x1078, 0x1332, 0x1078, 0x772d, 0x007c, 0x007e, 0x027e,
-	0xa016, 0x1078, 0x15fa, 0x027f, 0x007f, 0x007c, 0xa182, 0x0085,
-	0x0079, 0x877a, 0x8783, 0x8781, 0x8781, 0x878f, 0x8781, 0x8781,
-	0x8781, 0x1078, 0x1332, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x027e,
-	0x057e, 0x0d7e, 0x0e7e, 0x2071, 0xac80, 0x7224, 0x6212, 0x7220,
-	0x1078, 0x8d02, 0x0040, 0x87b4, 0x2268, 0x6800, 0xa086, 0x0000,
-	0x0040, 0x87b4, 0x6018, 0x6d18, 0xa52e, 0x00c0, 0x87b4, 0x0c7e,
-	0x2d60, 0x1078, 0x8a03, 0x0c7f, 0x0040, 0x87b4, 0x6803, 0x0002,
-	0x6007, 0x0086, 0x0078, 0x87b6, 0x6007, 0x0087, 0x6003, 0x0001,
-	0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0f7e, 0x2278, 0x1078, 0x4963,
-	0x0f7f, 0x0040, 0x87ce, 0x6824, 0xd0ec, 0x0040, 0x87ce, 0x0c7e,
-	0x2260, 0x603f, 0x0000, 0x1078, 0x8fcf, 0x0c7f, 0x0e7f, 0x0d7f,
-	0x057f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x87e4, 0x6004,
-	0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332,
-	0xa082, 0x0085, 0x0079, 0x87f3, 0xa186, 0x0027, 0x0040, 0x87ec,
-	0xa186, 0x0014, 0x10c0, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6,
-	0x1078, 0x62d1, 0x007c, 0x87fa, 0x87fc, 0x87fc, 0x87fa, 0x87fa,
-	0x87fa, 0x87fa, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6,
-	0x1078, 0x62d1, 0x007c, 0xa186, 0x0013, 0x00c0, 0x880d, 0x6004,
-	0xa082, 0x0085, 0x2008, 0x0078, 0x8848, 0xa186, 0x0027, 0x00c0,
-	0x8830, 0x1078, 0x61cd, 0x1078, 0x2880, 0x0d7e, 0x6010, 0x2068,
-	0x1078, 0x8d16, 0x0040, 0x8826, 0x6837, 0x0103, 0x6847, 0x0000,
-	0x684b, 0x0029, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078,
-	0x772d, 0x1078, 0x62d1, 0x007c, 0x1078, 0x7773, 0x0078, 0x882b,
-	0xa186, 0x0014, 0x00c0, 0x882c, 0x1078, 0x61cd, 0x0d7e, 0x6010,
-	0x2068, 0x1078, 0x8d16, 0x0040, 0x8826, 0x6837, 0x0103, 0x6847,
-	0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x0078, 0x8822,
-	0x0079, 0x884a, 0x8853, 0x8851, 0x8851, 0x8851, 0x8851, 0x8851,
-	0x886e, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6030, 0xa08c, 0xff00,
-	0x810f, 0xa186, 0x0039, 0x0040, 0x8861, 0xa186, 0x0035, 0x00c0,
-	0x8865, 0x2001, 0xa9a2, 0x0078, 0x8867, 0x2001, 0xa9a3, 0x2004,
-	0x6016, 0x6003, 0x000c, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd,
-	0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x887c,
-	0xa186, 0x0035, 0x00c0, 0x8880, 0x2001, 0xa9a2, 0x0078, 0x8882,
-	0x2001, 0xa9a3, 0x2004, 0x6016, 0x6003, 0x000e, 0x1078, 0x62d1,
-	0x007c, 0xa182, 0x008c, 0x00c8, 0x8893, 0xa182, 0x0085, 0x0048,
-	0x8893, 0x0079, 0x8896, 0x1078, 0x7773, 0x007c, 0x889d, 0x889d,
-	0x889d, 0x889d, 0x889f, 0x88fc, 0x889d, 0x1078, 0x1332, 0x0f7e,
-	0x2c78, 0x1078, 0x4963, 0x0f7f, 0x0040, 0x88b2, 0x6030, 0xa08c,
-	0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8913, 0xa186, 0x0035,
-	0x0040, 0x8913, 0x0d7e, 0x1078, 0x8d16, 0x00c0, 0x88bb, 0x1078,
-	0x8ec9, 0x0078, 0x88de, 0x6010, 0x2068, 0x684c, 0xd0e4, 0x00c0,
-	0x88c3, 0x1078, 0x8ec9, 0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040,
-	0x88cf, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0078, 0x88da, 0xd0bc,
-	0x0040, 0x88d6, 0x684b, 0x0002, 0x0078, 0x88da, 0x684b, 0x0005,
-	0x1078, 0x8f95, 0x6847, 0x0000, 0x1078, 0x4a73, 0x2c68, 0x1078,
-	0x76c7, 0x0040, 0x88f7, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009,
-	0xac8e, 0x210c, 0x6136, 0x2009, 0xac8f, 0x210c, 0x613a, 0x6918,
-	0x611a, 0x6920, 0x6122, 0x601f, 0x0001, 0x1078, 0x5d8a, 0x2d60,
-	0x1078, 0x772d, 0x0d7f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963,
-	0x0f7f, 0x0040, 0x8939, 0x6030, 0xa08c, 0xff00, 0x810f, 0xa186,
-	0x0035, 0x0040, 0x8913, 0xa186, 0x001e, 0x0040, 0x8913, 0xa186,
-	0x0039, 0x00c0, 0x8939, 0x0d7e, 0x2c68, 0x1078, 0x91cc, 0x00c0,
-	0x895d, 0x1078, 0x76c7, 0x0040, 0x8936, 0x6106, 0x6003, 0x0001,
-	0x601f, 0x0001, 0x6918, 0x611a, 0x6928, 0x612a, 0x692c, 0x612e,
-	0x6930, 0xa18c, 0x00ff, 0x6132, 0x6934, 0x6136, 0x6938, 0x613a,
-	0x6920, 0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2d60, 0x0078,
-	0x895d, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x895d,
-	0x6837, 0x0103, 0x6850, 0xd0b4, 0x0040, 0x894c, 0xc0ec, 0x6852,
-	0x684b, 0x0006, 0x0078, 0x8957, 0xd0bc, 0x0040, 0x8953, 0x684b,
-	0x0002, 0x0078, 0x8957, 0x684b, 0x0005, 0x1078, 0x8f95, 0x6847,
-	0x0000, 0x1078, 0x4a73, 0x1078, 0x8ec9, 0x0d7f, 0x1078, 0x772d,
-	0x007c, 0x017e, 0x0d7e, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040,
-	0x8971, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x1078,
-	0x4a73, 0x0d7f, 0x017f, 0xa186, 0x0013, 0x0040, 0x8983, 0xa186,
-	0x0014, 0x0040, 0x8983, 0xa186, 0x0027, 0x0040, 0x8983, 0x1078,
-	0x7773, 0x0078, 0x8989, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078,
-	0x62d1, 0x007c, 0x057e, 0x067e, 0x0d7e, 0x0f7e, 0x2029, 0x0001,
-	0xa182, 0x0101, 0x00c8, 0x8996, 0x0078, 0x8998, 0x2009, 0x0100,
-	0x2130, 0x2069, 0xac98, 0x831c, 0x2300, 0xad18, 0x2009, 0x0020,
-	0xaf90, 0x001d, 0x1078, 0x89f2, 0xa6b2, 0x0020, 0x7804, 0xa06d,
-	0x0040, 0x89ac, 0x1078, 0x13b4, 0x1078, 0x138b, 0x0040, 0x89d6,
-	0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a,
-	0x003d, 0x00c8, 0x89c2, 0x2608, 0xad90, 0x000f, 0x1078, 0x89f2,
-	0x0078, 0x89d6, 0xa6b2, 0x003c, 0x2009, 0x003c, 0x2d78, 0xad90,
-	0x000f, 0x1078, 0x89f2, 0x0078, 0x89ac, 0x0f7f, 0x852f, 0xa5ad,
-	0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0078, 0x89db, 0x0f7f, 0x852f,
-	0xa5ad, 0x0003, 0x7d36, 0x0d7f, 0x067f, 0x057f, 0x007c, 0x0f7e,
-	0x8dff, 0x0040, 0x89f0, 0x6804, 0xa07d, 0x0040, 0x89ee, 0x6807,
-	0x0000, 0x1078, 0x4a73, 0x2f68, 0x0078, 0x89e3, 0x1078, 0x4a73,
-	0x0f7f, 0x007c, 0x157e, 0xa184, 0x0001, 0x0040, 0x89f8, 0x8108,
-	0x810c, 0x21a8, 0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x00f0,
-	0x89fa, 0x157f, 0x007c, 0x067e, 0x127e, 0x2091, 0x8000, 0x2031,
-	0x0001, 0x601c, 0xa084, 0x000f, 0x1079, 0x8a1f, 0x127f, 0x067f,
-	0x007c, 0x127e, 0x2091, 0x8000, 0x067e, 0x2031, 0x0000, 0x601c,
-	0xa084, 0x000f, 0x1079, 0x8a1f, 0x067f, 0x127f, 0x007c, 0x8a39,
-	0x8a27, 0x8a34, 0x8a55, 0x8a27, 0x8a34, 0x8a55, 0x8a34, 0x1078,
-	0x1332, 0x037e, 0x2019, 0x0010, 0x1078, 0x9dd7, 0x601f, 0x0006,
-	0x6003, 0x0007, 0x037f, 0x007c, 0xa006, 0x007c, 0xa085, 0x0001,
-	0x007c, 0x0d7e, 0x86ff, 0x00c0, 0x8a50, 0x6010, 0x2068, 0x1078,
-	0x8d16, 0x0040, 0x8a52, 0xa00e, 0x2001, 0x0005, 0x1078, 0x4b51,
-	0x1078, 0x8f95, 0x1078, 0x4a73, 0x1078, 0x772d, 0xa085, 0x0001,
-	0x0d7f, 0x007c, 0xa006, 0x0078, 0x8a50, 0x6000, 0xa08a, 0x0010,
-	0x10c8, 0x1332, 0x1079, 0x8a5d, 0x007c, 0x8a6d, 0x8a92, 0x8a6f,
-	0x8ab5, 0x8a8e, 0x8a6d, 0x8a34, 0x8a39, 0x8a39, 0x8a34, 0x8a34,
-	0x8a34, 0x8a34, 0x8a34, 0x8a34, 0x8a34, 0x1078, 0x1332, 0x86ff,
-	0x00c0, 0x8a8b, 0x601c, 0xa086, 0x0006, 0x0040, 0x8a8b, 0x0d7e,
-	0x6010, 0x2068, 0x1078, 0x8d16, 0x0040, 0x8a80, 0x1078, 0x8f95,
-	0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x1078,
-	0x5d8a, 0x1078, 0x62d1, 0xa085, 0x0001, 0x007c, 0x1078, 0x1757,
-	0x0078, 0x8a6f, 0x0e7e, 0x2071, 0xa9b1, 0x7024, 0xac06, 0x00c0,
-	0x8a9b, 0x1078, 0x6fc4, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006,
-	0x00c0, 0x8aad, 0x087e, 0x097e, 0x2049, 0x0001, 0x2c40, 0x1078,
-	0x7246, 0x097f, 0x087f, 0x0078, 0x8aaf, 0x1078, 0x6ebe, 0x0e7f,
-	0x00c0, 0x8a6f, 0x1078, 0x8a34, 0x007c, 0x037e, 0x0e7e, 0x2071,
-	0xa9b1, 0x703c, 0xac06, 0x00c0, 0x8ac5, 0x2019, 0x0000, 0x1078,
-	0x7058, 0x0e7f, 0x037f, 0x0078, 0x8a6f, 0x1078, 0x738a, 0x0e7f,
-	0x037f, 0x00c0, 0x8a6f, 0x1078, 0x8a34, 0x007c, 0x0c7e, 0x601c,
-	0xa084, 0x000f, 0x1079, 0x8ad6, 0x0c7f, 0x007c, 0x8ae5, 0x8b57,
-	0x8c8f, 0x8af0, 0x8ed6, 0x8ae5, 0x9dc8, 0x772d, 0x8b57, 0x1078,
-	0x8f10, 0x00c0, 0x8ae5, 0x1078, 0x7c83, 0x007c, 0x1078, 0x61cd,
-	0x1078, 0x62d1, 0x1078, 0x772d, 0x007c, 0x6017, 0x0001, 0x007c,
-	0x1078, 0x8d16, 0x0040, 0x8af8, 0x6010, 0xa080, 0x0019, 0x2c02,
-	0x6000, 0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b00, 0x007c,
-	0x8b10, 0x8b12, 0x8b34, 0x8b46, 0x8b53, 0x8b10, 0x8ae5, 0x8ae5,
-	0x8ae5, 0x8b46, 0x8b46, 0x8b10, 0x8b10, 0x8b10, 0x8b10, 0x8b50,
-	0x1078, 0x1332, 0x0e7e, 0x6010, 0x2070, 0x7050, 0xc0b5, 0x7052,
-	0x2071, 0xa9b1, 0x7024, 0xac06, 0x0040, 0x8b30, 0x1078, 0x6ebe,
-	0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x2001, 0xa9a3,
-	0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0e7f, 0x007c,
-	0x6017, 0x0001, 0x0078, 0x8b2e, 0x0d7e, 0x6010, 0x2068, 0x6850,
-	0xc0b5, 0x6852, 0x0d7f, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f,
-	0x0002, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x0d7e, 0x6017,
-	0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x0d7f, 0x007c,
-	0x1078, 0x772d, 0x007c, 0x1078, 0x1757, 0x0078, 0x8b34, 0x6000,
-	0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8b5f, 0x007c, 0x8b6f,
-	0x8aed, 0x8b71, 0x8b6f, 0x8b71, 0x8b71, 0x8ae6, 0x8b6f, 0x8adf,
-	0x8adf, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x8b6f, 0x1078,
-	0x1332, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x0d7f,
-	0xa08a, 0x000c, 0x10c8, 0x1332, 0x1079, 0x8b7f, 0x007c, 0x8b8b,
-	0x8c33, 0x8b8d, 0x8bcd, 0x8b8d, 0x8bcd, 0x8b8d, 0x8b9a, 0x8b8b,
-	0x8bcd, 0x8b8b, 0x8bb7, 0x1078, 0x1332, 0x6004, 0xa08e, 0x0016,
-	0x0040, 0x8bc8, 0xa08e, 0x0004, 0x0040, 0x8bc8, 0xa08e, 0x0002,
-	0x0040, 0x8bc8, 0x6004, 0x1078, 0x8f10, 0x0040, 0x8c4e, 0xa08e,
-	0x0021, 0x0040, 0x8c52, 0xa08e, 0x0022, 0x0040, 0x8c4e, 0xa08e,
-	0x003d, 0x0040, 0x8c52, 0xa08e, 0x0039, 0x0040, 0x8c56, 0xa08e,
-	0x0035, 0x0040, 0x8c56, 0xa08e, 0x001e, 0x0040, 0x8bca, 0xa08e,
-	0x0001, 0x00c0, 0x8bc6, 0x0d7e, 0x6018, 0x2068, 0x6804, 0xa084,
-	0x00ff, 0x0d7f, 0xa086, 0x0006, 0x0040, 0x8bc8, 0x1078, 0x2880,
-	0x1078, 0x7c83, 0x1078, 0x8ed6, 0x007c, 0x0c7e, 0x0d7e, 0x6104,
-	0xa186, 0x0016, 0x0040, 0x8c23, 0xa186, 0x0002, 0x00c0, 0x8bf6,
-	0x6018, 0x2068, 0x68a0, 0xd0bc, 0x00c0, 0x8c7a, 0x6840, 0xa084,
-	0x00ff, 0xa005, 0x0040, 0x8bf6, 0x8001, 0x6842, 0x6013, 0x0000,
-	0x601f, 0x0007, 0x6017, 0x0398, 0x1078, 0x76c7, 0x0040, 0x8bf6,
-	0x2d00, 0x601a, 0x601f, 0x0001, 0x0078, 0x8c23, 0x0d7f, 0x0c7f,
-	0x6004, 0xa08e, 0x0002, 0x00c0, 0x8c14, 0x6018, 0xa080, 0x0028,
-	0x2004, 0xa086, 0x007e, 0x00c0, 0x8c14, 0x2009, 0xa733, 0x2104,
-	0xc085, 0x200a, 0x0e7e, 0x2071, 0xa700, 0x1078, 0x42b8, 0x0e7f,
-	0x1078, 0x7c83, 0x0078, 0x8c18, 0x1078, 0x7c83, 0x1078, 0x2880,
-	0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x127f, 0x0e7f,
-	0x1078, 0x8ed6, 0x007c, 0x2001, 0x0002, 0x1078, 0x4502, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0d7f,
-	0x0c7f, 0x0078, 0x8c22, 0x0c7e, 0x0d7e, 0x6104, 0xa186, 0x0016,
-	0x0040, 0x8c23, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005,
-	0x0040, 0x8bf6, 0x8001, 0x6842, 0x6003, 0x0001, 0x1078, 0x5dd7,
-	0x1078, 0x62d1, 0x0d7f, 0x0c7f, 0x0078, 0x8c22, 0x1078, 0x7c83,
-	0x0078, 0x8bca, 0x1078, 0x7ca6, 0x0078, 0x8bca, 0x0d7e, 0x2c68,
-	0x6104, 0x1078, 0x91cc, 0x0d7f, 0x0040, 0x8c62, 0x1078, 0x772d,
-	0x0078, 0x8c79, 0x6004, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105,
-	0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002, 0x6038,
-	0x600a, 0x2001, 0xa9a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078,
-	0x62d1, 0x007c, 0x0d7f, 0x0c7f, 0x1078, 0x7c83, 0x1078, 0x2880,
-	0x0e7e, 0x127e, 0x2091, 0x8000, 0x1078, 0x28a6, 0x6013, 0x0000,
-	0x601f, 0x0007, 0x6017, 0x0398, 0x127f, 0x0e7f, 0x007c, 0x6000,
-	0xa08a, 0x0010, 0x10c8, 0x1332, 0x1079, 0x8c97, 0x007c, 0x8ca7,
-	0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7, 0x8ca7,
-	0x8ae5, 0x8ca7, 0x8aed, 0x8ca9, 0x8aed, 0x8cb7, 0x8ca7, 0x1078,
-	0x1332, 0x6004, 0xa086, 0x008b, 0x0040, 0x8cb7, 0x6007, 0x008b,
-	0x6003, 0x000d, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x007c, 0x1078,
-	0x8ec9, 0x1078, 0x8d16, 0x0040, 0x8cef, 0x1078, 0x2880, 0x0d7e,
-	0x1078, 0x8d16, 0x0040, 0x8cd1, 0x6010, 0x2068, 0x6837, 0x0103,
-	0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed, 0x6852, 0x1078,
-	0x4a73, 0x2c68, 0x1078, 0x76c7, 0x0040, 0x8cdf, 0x6818, 0x601a,
-	0x0c7e, 0x2d60, 0x1078, 0x8ed6, 0x0c7f, 0x0078, 0x8ce0, 0x2d60,
-	0x0d7f, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007, 0x0001, 0x6003,
-	0x0001, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0078, 0x8d01, 0x6030,
-	0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0040, 0x8cfb, 0xa186,
-	0x0035, 0x00c0, 0x8cff, 0x1078, 0x2880, 0x0078, 0x8cd1, 0x1078,
-	0x8ed6, 0x007c, 0xa284, 0x000f, 0x00c0, 0x8d13, 0xa282, 0xae00,
-	0x0048, 0x8d13, 0x2001, 0xa716, 0x2004, 0xa202, 0x00c8, 0x8d13,
-	0xa085, 0x0001, 0x007c, 0xa006, 0x0078, 0x8d12, 0x027e, 0x0e7e,
-	0x2071, 0xa700, 0x6210, 0x705c, 0xa202, 0x0048, 0x8d28, 0x7060,
-	0xa202, 0x00c8, 0x8d28, 0xa085, 0x0001, 0x0e7f, 0x027f, 0x007c,
-	0xa006, 0x0078, 0x8d25, 0x0e7e, 0x0c7e, 0x037e, 0x007e, 0x127e,
-	0x2091, 0x8000, 0x2061, 0xae00, 0x2071, 0xa700, 0x7348, 0x7064,
-	0xa302, 0x00c8, 0x8d55, 0x601c, 0xa206, 0x00c0, 0x8d4d, 0x1078,
-	0x903b, 0x0040, 0x8d4d, 0x1078, 0x8f10, 0x00c0, 0x8d49, 0x1078,
-	0x7c83, 0x0c7e, 0x1078, 0x772d, 0x0c7f, 0xace0, 0x0010, 0x7058,
-	0xac02, 0x00c8, 0x8d55, 0x0078, 0x8d36, 0x127f, 0x007f, 0x037f,
-	0x0c7f, 0x0e7f, 0x007c, 0x0e7e, 0x0c7e, 0x017e, 0xa188, 0xa835,
-	0x210c, 0x81ff, 0x0040, 0x8d69, 0x2061, 0xaab3, 0x611a, 0x1078,
-	0x2880, 0xa006, 0x0078, 0x8d6e, 0xa085, 0x0001, 0x017f, 0x0c7f,
-	0x0e7f, 0x007c, 0x0c7e, 0x057e, 0x127e, 0x2091, 0x8000, 0x0c7e,
-	0x1078, 0x76c7, 0x057f, 0x0040, 0x8d8b, 0x6612, 0x651a, 0x601f,
-	0x0003, 0x2009, 0x004b, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f,
-	0x057f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8d87, 0x0c7e, 0x057e,
-	0x127e, 0x2091, 0x8000, 0x62a0, 0x0c7e, 0x1078, 0x76c7, 0x057f,
-	0x0040, 0x8db9, 0x6013, 0x0000, 0x651a, 0x601f, 0x0003, 0x0c7e,
-	0x2560, 0x1078, 0x47e9, 0x0c7f, 0x1078, 0x5f01, 0x077e, 0x2039,
-	0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f, 0x2009,
-	0x004c, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x057f, 0x0c7f,
-	0x007c, 0xa006, 0x0078, 0x8db5, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e,
-	0x1078, 0x76c7, 0x2c78, 0x0c7f, 0x0040, 0x8dd6, 0x7e12, 0x2c00,
-	0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x1078, 0x8e21, 0x2f60,
-	0x2009, 0x004d, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f,
-	0x0f7f, 0x007c, 0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7,
-	0x2c78, 0x0c7f, 0x0040, 0x8df4, 0x7e12, 0x2c00, 0x781a, 0x781f,
-	0x0003, 0x2021, 0x0005, 0x1078, 0x8e21, 0x2f60, 0x2009, 0x004e,
-	0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f, 0x007c,
-	0x0f7e, 0x0c7e, 0x047e, 0x0c7e, 0x1078, 0x76c7, 0x2c78, 0x0c7f,
-	0x0040, 0x8e1d, 0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021,
-	0x0004, 0x1078, 0x8e21, 0x2001, 0xa99d, 0x2004, 0xd0fc, 0x0040,
-	0x8e16, 0x2f60, 0x1078, 0x772d, 0x0078, 0x8e1b, 0x2f60, 0x2009,
-	0x0052, 0x1078, 0x775c, 0xa085, 0x0001, 0x047f, 0x0c7f, 0x0f7f,
-	0x007c, 0x097e, 0x077e, 0x127e, 0x2091, 0x8000, 0x1078, 0x4775,
-	0x0040, 0x8e2e, 0x2001, 0x8e26, 0x0078, 0x8e34, 0x1078, 0x4739,
-	0x0040, 0x8e3d, 0x2001, 0x8e2e, 0x007e, 0xa00e, 0x2400, 0x1078,
-	0x4b51, 0x1078, 0x4a73, 0x007f, 0x007a, 0x2418, 0x1078, 0x6161,
-	0x62a0, 0x087e, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x1078,
-	0x5f1b, 0x087f, 0x1078, 0x5e0a, 0x2f08, 0x2648, 0x1078, 0x9f9b,
-	0x613c, 0x81ff, 0x1040, 0x5fdb, 0x1078, 0x62d1, 0x127f, 0x077f,
-	0x097f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
-	0x76c7, 0x017f, 0x0040, 0x8e73, 0x660a, 0x611a, 0x601f, 0x0001,
-	0x2d00, 0x6012, 0x2009, 0x001f, 0x1078, 0x775c, 0xa085, 0x0001,
-	0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8e70, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8e8f,
-	0x660a, 0x611a, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009, 0x0021,
-	0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006,
-	0x0078, 0x8e8c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
-	0x76c7, 0x017f, 0x0040, 0x8eab, 0x660a, 0x611a, 0x601f, 0x0001,
-	0x2d00, 0x6012, 0x2009, 0x003d, 0x1078, 0x775c, 0xa085, 0x0001,
-	0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8ea8, 0x0c7e, 0x127e,
-	0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x8ec6,
-	0x611a, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000, 0x1078,
-	0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078,
-	0x8ec3, 0x027e, 0x0d7e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0040,
-	0x8ed3, 0x8211, 0x6a3e, 0x0d7f, 0x027f, 0x007c, 0x007e, 0x6000,
-	0xa086, 0x0000, 0x0040, 0x8ee8, 0x6013, 0x0000, 0x601f, 0x0007,
-	0x2001, 0xa9a3, 0x2004, 0x6016, 0x1078, 0xa4a5, 0x603f, 0x0000,
-	0x007f, 0x007c, 0x067e, 0x0c7e, 0x0d7e, 0x2031, 0xa753, 0x2634,
-	0xd6e4, 0x0040, 0x8ef8, 0x6618, 0x2660, 0x6e48, 0x1078, 0x46e7,
-	0x0d7f, 0x0c7f, 0x067f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e,
-	0x0002, 0x0040, 0x8f0d, 0xa08e, 0x0003, 0x0040, 0x8f0d, 0xa08e,
-	0x0004, 0x0040, 0x8f0d, 0xa085, 0x0001, 0x017f, 0x007f, 0x007c,
-	0x007e, 0x0d7e, 0x6010, 0xa06d, 0x0040, 0x8f1d, 0x6838, 0xd0fc,
-	0x0040, 0x8f1d, 0xa006, 0x0078, 0x8f1f, 0xa085, 0x0001, 0x0d7f,
-	0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078,
-	0x76c7, 0x017f, 0x0040, 0x8f3c, 0x611a, 0x601f, 0x0001, 0x2d00,
-	0x6012, 0x1078, 0x2880, 0x2009, 0x0028, 0x1078, 0x775c, 0xa085,
-	0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x8f39, 0xa186,
-	0x0015, 0x00c0, 0x8f54, 0x2011, 0xa720, 0x2204, 0xa086, 0x0074,
-	0x00c0, 0x8f54, 0x1078, 0x7f91, 0x6003, 0x0001, 0x6007, 0x0029,
-	0x1078, 0x5dd7, 0x0078, 0x8f58, 0x1078, 0x7c83, 0x1078, 0x772d,
-	0x007c, 0xa186, 0x0016, 0x00c0, 0x8f63, 0x2001, 0x0004, 0x1078,
-	0x4502, 0x0078, 0x8f84, 0xa186, 0x0015, 0x00c0, 0x8f88, 0x2011,
-	0xa720, 0x2204, 0xa086, 0x0014, 0x00c0, 0x8f88, 0x0d7e, 0x6018,
-	0x2068, 0x1078, 0x4649, 0x0d7f, 0x1078, 0x8043, 0x00c0, 0x8f88,
-	0x0d7e, 0x6018, 0x2068, 0x6890, 0x0d7f, 0xa005, 0x0040, 0x8f88,
-	0x2001, 0x0006, 0x1078, 0x4502, 0x1078, 0x77f8, 0x0078, 0x8f8c,
-	0x1078, 0x7c83, 0x1078, 0x772d, 0x007c, 0x6848, 0xa086, 0x0005,
-	0x00c0, 0x8f94, 0x1078, 0x8f95, 0x007c, 0x6850, 0xc0ad, 0x6852,
-	0x007c, 0x0e7e, 0x2071, 0xac8c, 0x7014, 0xd0e4, 0x0040, 0x8faa,
-	0x6013, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050, 0x1078, 0x5d8a,
-	0x1078, 0x62d1, 0x0e7f, 0x007c, 0x0c7e, 0x0f7e, 0x2c78, 0x1078,
-	0x4963, 0x0f7f, 0x0040, 0x8fb9, 0x601c, 0xa084, 0x000f, 0x1079,
-	0x8fbb, 0x0c7f, 0x007c, 0x8ae5, 0x8fc6, 0x8fc9, 0x8fcc, 0xa26d,
-	0xa289, 0xa28c, 0x8ae5, 0x8ae5, 0x1078, 0x1332, 0x0005, 0x0005,
-	0x007c, 0x0005, 0x0005, 0x007c, 0x1078, 0x8fcf, 0x007c, 0x0f7e,
-	0x2c78, 0x1078, 0x4963, 0x0040, 0x8ffe, 0x1078, 0x76c7, 0x00c0,
-	0x8fdf, 0x2001, 0xa9a4, 0x2004, 0x783e, 0x0078, 0x8ffe, 0x7818,
-	0x601a, 0x781c, 0xa086, 0x0003, 0x0040, 0x8fec, 0x7808, 0x6036,
-	0x2f00, 0x603a, 0x0078, 0x8ff0, 0x7808, 0x603a, 0x2f00, 0x6036,
-	0x602a, 0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7920,
-	0x6122, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x2f60, 0x0f7f, 0x007c,
-	0x017e, 0x0f7e, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0040, 0x9011,
-	0xa086, 0x0005, 0x0040, 0x9015, 0xa006, 0x602a, 0x602e, 0x0078,
-	0x9026, 0x6824, 0xc0f4, 0xc0d5, 0x6826, 0x6810, 0x2078, 0x787c,
-	0x6938, 0xa102, 0x7880, 0x6934, 0xa103, 0x00c8, 0x900c, 0x6834,
-	0x602a, 0x6838, 0xa084, 0xfffc, 0x683a, 0x602e, 0x2d00, 0x6036,
-	0x6808, 0x603a, 0x6918, 0x611a, 0x6920, 0x6122, 0x601f, 0x0001,
-	0x6007, 0x0039, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x6803, 0x0002,
-	0x0f7f, 0x017f, 0x007c, 0x007e, 0x017e, 0x6004, 0xa08e, 0x0034,
-	0x0040, 0x9060, 0xa08e, 0x0035, 0x0040, 0x9060, 0xa08e, 0x0036,
-	0x0040, 0x9060, 0xa08e, 0x0037, 0x0040, 0x9060, 0xa08e, 0x0038,
-	0x0040, 0x9060, 0xa08e, 0x0039, 0x0040, 0x9060, 0xa08e, 0x003a,
-	0x0040, 0x9060, 0xa08e, 0x003b, 0x0040, 0x9060, 0xa085, 0x0001,
-	0x017f, 0x007f, 0x007c, 0x0f7e, 0x2c78, 0x1078, 0x4963, 0x00c0,
-	0x906d, 0xa085, 0x0001, 0x0078, 0x907c, 0x6024, 0xd0f4, 0x00c0,
-	0x907b, 0xc0f5, 0x6026, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c,
-	0x6036, 0x1078, 0x1757, 0xa006, 0x0f7f, 0x007c, 0x007e, 0x017e,
-	0x027e, 0x037e, 0x0e7e, 0x2001, 0xa99e, 0x200c, 0x8000, 0x2014,
-	0x2001, 0x0032, 0x1078, 0x5c1c, 0x2001, 0xa9a2, 0x82ff, 0x00c0,
-	0x9093, 0x2011, 0x0014, 0x2202, 0x2001, 0xa9a0, 0x200c, 0x8000,
-	0x2014, 0x2071, 0xa98d, 0x711a, 0x721e, 0x2001, 0x0064, 0x1078,
-	0x5c1c, 0x2001, 0xa9a3, 0x82ff, 0x00c0, 0x90a8, 0x2011, 0x0014,
-	0x2202, 0x2009, 0xa9a4, 0xa280, 0x000a, 0x200a, 0x1078, 0x498b,
-	0x0e7f, 0x037f, 0x027f, 0x017f, 0x007f, 0x007c, 0x007e, 0x0e7e,
-	0x2001, 0xa9a2, 0x2003, 0x0028, 0x2001, 0xa9a3, 0x2003, 0x0014,
-	0x2071, 0xa98d, 0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xa9a4,
-	0x2003, 0x001e, 0x0e7f, 0x007f, 0x007c, 0x0c7e, 0x127e, 0x2091,
-	0x8000, 0x0c7e, 0x1078, 0x76c7, 0x017f, 0x0040, 0x90e5, 0x611a,
-	0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x1078, 0x775c,
-	0xa085, 0x0001, 0x127f, 0x0c7f, 0x007c, 0xa006, 0x0078, 0x90e2,
-	0x0d7e, 0x0e7e, 0x0f7e, 0x2071, 0xa700, 0xa186, 0x0015, 0x00c0,
-	0x9117, 0x7080, 0xa086, 0x0018, 0x00c0, 0x9117, 0x6010, 0x2068,
-	0x6a3c, 0xd2e4, 0x00c0, 0x910b, 0x2c78, 0x1078, 0x6490, 0x0040,
-	0x911f, 0x706c, 0x6a50, 0xa206, 0x00c0, 0x9113, 0x7070, 0x6a54,
-	0xa206, 0x00c0, 0x9113, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
-	0x0000, 0x1078, 0x28c8, 0x1078, 0x77f8, 0x0078, 0x911b, 0x1078,
-	0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x7050,
-	0xa080, 0x29c0, 0x2004, 0x6a54, 0xa206, 0x0040, 0x910b, 0x0078,
-	0x9113, 0x0c7e, 0x127e, 0x2091, 0x8000, 0x0c7e, 0x1078, 0x76c7,
-	0x017f, 0x0040, 0x9141, 0x611a, 0x601f, 0x0001, 0x2d00, 0x6012,
-	0x2009, 0x0043, 0x1078, 0x775c, 0xa085, 0x0001, 0x127f, 0x0c7f,
-	0x007c, 0xa006, 0x0078, 0x913e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2071,
-	0xa700, 0xa186, 0x0015, 0x00c0, 0x916a, 0x7080, 0xa086, 0x0004,
-	0x00c0, 0x916a, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x1078, 0x6490,
-	0x0040, 0x9172, 0x706c, 0x6a08, 0xa206, 0x00c0, 0x9166, 0x7070,
-	0x6a0c, 0xa206, 0x00c0, 0x9166, 0x1078, 0x2880, 0x1078, 0x77f8,
-	0x0078, 0x916e, 0x1078, 0x7c83, 0x1078, 0x772d, 0x0f7f, 0x0e7f,
-	0x0d7f, 0x007c, 0x7050, 0xa080, 0x29c0, 0x2004, 0x6a0c, 0xa206,
-	0x0040, 0x9164, 0x0078, 0x9166, 0x017e, 0x027e, 0x684c, 0xd0ac,
-	0x0040, 0x9194, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0040, 0x9194,
-	0x6860, 0xa106, 0x00c0, 0x9190, 0x685c, 0xa206, 0x0040, 0x9194,
-	0x6962, 0x6a5e, 0xa085, 0x0001, 0x027f, 0x017f, 0x007c, 0x0e7e,
-	0x127e, 0x2071, 0xa700, 0x2091, 0x8000, 0x7548, 0xa582, 0x0001,
-	0x0048, 0x91c9, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0040,
-	0x91b5, 0xace0, 0x0010, 0x7058, 0xac02, 0x00c8, 0x91b1, 0x0078,
-	0x91a4, 0x2061, 0xae00, 0x0078, 0x91a4, 0x6003, 0x0008, 0x8529,
-	0x754a, 0xaca8, 0x0010, 0x7058, 0xa502, 0x00c8, 0x91c5, 0x754e,
-	0xa085, 0x0001, 0x127f, 0x0e7f, 0x007c, 0x704f, 0xae00, 0x0078,
-	0x91c0, 0xa006, 0x0078, 0x91c2, 0x0c7e, 0x027e, 0x017e, 0xa186,
-	0x0035, 0x0040, 0x91d6, 0x6a34, 0x0078, 0x91d7, 0x6a28, 0x1078,
-	0x8d02, 0x0040, 0x9200, 0x2260, 0x611c, 0xa186, 0x0003, 0x0040,
-	0x91e5, 0xa186, 0x0006, 0x00c0, 0x91fc, 0x6834, 0xa206, 0x0040,
-	0x91f4, 0x6838, 0xa206, 0x00c0, 0x91fc, 0x6108, 0x6834, 0xa106,
-	0x00c0, 0x91fc, 0x0078, 0x91f9, 0x6008, 0x6938, 0xa106, 0x00c0,
-	0x91fc, 0x6018, 0x6918, 0xa106, 0x017f, 0x027f, 0x0c7f, 0x007c,
-	0xa085, 0x0001, 0x0078, 0x91fc, 0x6944, 0xd1cc, 0x0040, 0x921d,
-	0xa18c, 0x00ff, 0xa18e, 0x0002, 0x00c0, 0x921d, 0xad88, 0x001e,
-	0x210c, 0xa18c, 0x0f00, 0x810f, 0xa18e, 0x0001, 0x00c0, 0x921d,
-	0x6810, 0x6914, 0xa115, 0x10c0, 0x84e2, 0x007c, 0x067e, 0x6000,
-	0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9228, 0x067f, 0x007c,
-	0x9238, 0x96ef, 0x980b, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238,
-	0x9272, 0x989e, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238, 0x9238,
-	0x1078, 0x1332, 0x067e, 0x6000, 0xa0b2, 0x0010, 0x10c8, 0x1332,
-	0x1079, 0x9244, 0x067f, 0x007c, 0x9254, 0x9d63, 0x9254, 0x9254,
-	0x9254, 0x9254, 0x9254, 0x9254, 0x9d21, 0x9db1, 0x9254, 0xa3c0,
-	0xa3f4, 0xa3c0, 0xa3f4, 0x9254, 0x1078, 0x1332, 0x067e, 0x6000,
-	0xa0b2, 0x0010, 0x10c8, 0x1332, 0x1079, 0x9260, 0x067f, 0x007c,
-	0x9270, 0x99fb, 0x9ad7, 0x9b05, 0x9b80, 0x9270, 0x9c86, 0x9c2e,
-	0x98aa, 0x9cf5, 0x9d0b, 0x9270, 0x9270, 0x9270, 0x9270, 0x9270,
-	0x1078, 0x1332, 0xa1b2, 0x0044, 0x10c8, 0x1332, 0x2100, 0x0079,
-	0x9279, 0x92b9, 0x94a8, 0x92b9, 0x92b9, 0x92b9, 0x94b0, 0x92b9,
-	0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9,
-	0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9,
-	0x92bb, 0x9321, 0x9330, 0x9387, 0x93a6, 0x9425, 0x9495, 0x92b9,
-	0x92b9, 0x94b4, 0x92b9, 0x92b9, 0x94c7, 0x94d2, 0x92b9, 0x92b9,
-	0x92b9, 0x92b9, 0x92b9, 0x950a, 0x92b9, 0x92b9, 0x9519, 0x92b9,
-	0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x9532, 0x92b9, 0x92b9,
-	0x92b9, 0x95bf, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9, 0x92b9,
-	0x9639, 0x1078, 0x1332, 0x1078, 0x4967, 0x00c0, 0x92cb, 0x2001,
-	0xa733, 0x2004, 0xd0cc, 0x00c0, 0x92cb, 0xa084, 0x0009, 0xa086,
-	0x0008, 0x00c0, 0x92d3, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013,
-	0x0000, 0x0078, 0x94a3, 0x1078, 0x4957, 0x0e7e, 0x0c7e, 0x037e,
-	0x027e, 0x017e, 0x6218, 0x2270, 0x72a0, 0x027e, 0x2019, 0x0029,
-	0x1078, 0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08,
-	0x1078, 0x9f9b, 0x077f, 0x017f, 0x2e60, 0x1078, 0x47e9, 0x017f,
-	0x027f, 0x037f, 0x0c7f, 0x0e7f, 0x6618, 0x0c7e, 0x2660, 0x1078,
-	0x45d6, 0x0c7f, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082,
-	0x0006, 0x0048, 0x9313, 0x1078, 0x9ecf, 0x00c0, 0x9381, 0x1078,
-	0x9e60, 0x00c0, 0x930f, 0x6007, 0x0008, 0x0078, 0x94a3, 0x6007,
-	0x0009, 0x0078, 0x94a3, 0x1078, 0xa0af, 0x0040, 0x931d, 0x1078,
-	0x9ecf, 0x0040, 0x9307, 0x0078, 0x9381, 0x6013, 0x1900, 0x0078,
-	0x930f, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6106, 0x1078, 0x9e15,
-	0x6007, 0x0006, 0x0078, 0x94a3, 0x6007, 0x0007, 0x0078, 0x94a3,
-	0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, 0x9674,
-	0x0d7e, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006,
-	0x00c8, 0x9346, 0x2001, 0x0001, 0x1078, 0x44ee, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0040, 0x9363, 0xa686, 0x0004, 0x0040,
-	0x9363, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9363,
-	0xa686, 0x0004, 0x0040, 0x9363, 0xa686, 0x0005, 0x0040, 0x9363,
-	0x0d7f, 0x0078, 0x9381, 0x1078, 0x9f35, 0x00c0, 0x937c, 0xa686,
-	0x0006, 0x00c0, 0x9375, 0x027e, 0x6218, 0xa290, 0x0028, 0x2214,
-	0x2009, 0x0000, 0x1078, 0x28c8, 0x027f, 0x1078, 0x4649, 0x6007,
-	0x000a, 0x0d7f, 0x0078, 0x94a3, 0x6007, 0x000b, 0x0d7f, 0x0078,
-	0x94a3, 0x1078, 0x2880, 0x6007, 0x0001, 0x0078, 0x94a3, 0x1078,
-	0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6618,
-	0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa686, 0x0707, 0x0040, 0x9381,
-	0x027e, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x1078,
-	0x28c8, 0x027f, 0x6007, 0x000c, 0x0078, 0x94a3, 0x1078, 0x4967,
-	0x00c0, 0x93b3, 0x2001, 0xa733, 0x2004, 0xa084, 0x0009, 0xa086,
-	0x0008, 0x00c0, 0x93bb, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013,
-	0x0000, 0x0078, 0x94a3, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001,
-	0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x93ff, 0xa6b4,
-	0xff00, 0x8637, 0xa686, 0x0004, 0x0040, 0x93d2, 0xa686, 0x0006,
-	0x00c0, 0x9381, 0x1078, 0x9f44, 0x00c0, 0x93da, 0x6007, 0x000e,
-	0x0078, 0x94a3, 0x047e, 0x6418, 0xa4a0, 0x0028, 0x2424, 0xa4a4,
-	0x00ff, 0x8427, 0x047e, 0x1078, 0x2880, 0x047f, 0x017e, 0xa006,
-	0x2009, 0xa753, 0x210c, 0xd1a4, 0x0040, 0x93f9, 0x2009, 0x0029,
-	0x1078, 0xa22d, 0x6018, 0x0d7e, 0x2068, 0x6800, 0xc0e5, 0x6802,
-	0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001, 0x0078, 0x94a3, 0x2001,
-	0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9,
-	0x0004, 0x2019, 0xa705, 0x2011, 0xac90, 0x1078, 0x80de, 0x037f,
-	0x027f, 0x017f, 0x157f, 0xa005, 0x0040, 0x941f, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0040, 0x93d2, 0x0078, 0x9381, 0x6013,
-	0x1900, 0x6007, 0x0009, 0x0078, 0x94a3, 0x1078, 0x4967, 0x00c0,
-	0x9432, 0x2001, 0xa733, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008,
-	0x00c0, 0x943a, 0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000,
-	0x0078, 0x94a3, 0x1078, 0x4957, 0x6618, 0xa6b0, 0x0001, 0x2634,
-	0xa684, 0x00ff, 0xa082, 0x0006, 0x0048, 0x9482, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0004, 0x0040, 0x9451, 0xa686, 0x0006, 0x00c0,
-	0x9381, 0x1078, 0x9f6f, 0x00c0, 0x945d, 0x1078, 0x9e60, 0x00c0,
-	0x945d, 0x6007, 0x0010, 0x0078, 0x94a3, 0x047e, 0x6418, 0xa4a0,
-	0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x047e, 0x1078, 0x2880,
-	0x047f, 0x017e, 0xa006, 0x2009, 0xa753, 0x210c, 0xd1a4, 0x0040,
-	0x947c, 0x2009, 0x0029, 0x1078, 0xa22d, 0x6018, 0x0d7e, 0x2068,
-	0x6800, 0xc0e5, 0x6802, 0x0d7f, 0x017f, 0x047f, 0x6007, 0x0001,
-	0x0078, 0x94a3, 0x1078, 0xa0af, 0x0040, 0x948f, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0040, 0x9451, 0x0078, 0x9381, 0x6013,
-	0x1900, 0x6007, 0x0009, 0x0078, 0x94a3, 0x1078, 0x29bb, 0x00c0,
-	0x9674, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0,
-	0x9381, 0x6007, 0x0012, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c,
-	0x6007, 0x0001, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x0078, 0x94a7,
-	0x6007, 0x0005, 0x0078, 0x94aa, 0x1078, 0xa42c, 0x00c0, 0x9674,
-	0x1078, 0x29bb, 0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381,
-	0x6007, 0x0020, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x007c, 0x1078,
-	0x29bb, 0x00c0, 0x9674, 0x6007, 0x0023, 0x6003, 0x0001, 0x1078,
-	0x5dd7, 0x007c, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb,
-	0x00c0, 0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, 0x017e, 0x027e,
-	0x2011, 0xac90, 0x2214, 0x2c08, 0xa006, 0x1078, 0xa1f6, 0x00c0,
-	0x94f9, 0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xac89,
-	0x2214, 0xa296, 0xffff, 0x00c0, 0x9503, 0x6007, 0x0025, 0x0078,
-	0x9503, 0x6004, 0xa086, 0x0024, 0x00c0, 0x9500, 0x1078, 0x772d,
-	0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x1078, 0x5dd7, 0x027f,
-	0x017f, 0x007c, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x6106, 0x1078,
-	0x9697, 0x6007, 0x002b, 0x0078, 0x94a3, 0x6007, 0x002c, 0x0078,
-	0x94a3, 0x1078, 0xa42c, 0x00c0, 0x9674, 0x1078, 0x29bb, 0x00c0,
-	0x9674, 0x1078, 0x9677, 0x00c0, 0x9381, 0x6106, 0x1078, 0x969c,
-	0x00c0, 0x952e, 0x6007, 0x002e, 0x0078, 0x94a3, 0x6007, 0x002f,
-	0x0078, 0x94a3, 0x1078, 0x29bb, 0x00c0, 0x9674, 0x0e7e, 0x0d7e,
-	0x0c7e, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086,
-	0x0006, 0x0040, 0x954f, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006,
-	0x0040, 0x954f, 0x0c7f, 0x0d7f, 0x0e7f, 0x0078, 0x94a8, 0x2001,
-	0xa772, 0x2004, 0xd0e4, 0x0040, 0x95bb, 0x2071, 0xac8c, 0x7010,
-	0x6036, 0x7014, 0x603a, 0x7108, 0x720c, 0x2001, 0xa753, 0x2004,
-	0xd0a4, 0x0040, 0x956d, 0x6018, 0x2068, 0x6810, 0xa106, 0x00c0,
-	0x956d, 0x6814, 0xa206, 0x0040, 0x9591, 0x2001, 0xa753, 0x2004,
-	0xd0ac, 0x00c0, 0x95af, 0x2069, 0xa700, 0x6870, 0xa206, 0x00c0,
-	0x95af, 0x686c, 0xa106, 0x00c0, 0x95af, 0x7210, 0x1078, 0x8d02,
-	0x0040, 0x95b5, 0x1078, 0xa29e, 0x0040, 0x95b5, 0x622a, 0x6007,
-	0x0036, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0c7f, 0x0d7f, 0x0e7f,
-	0x007c, 0x7214, 0xa286, 0xffff, 0x0040, 0x95a3, 0x1078, 0x8d02,
-	0x0040, 0x95b5, 0xa280, 0x0002, 0x2004, 0x7110, 0xa106, 0x00c0,
-	0x95b5, 0x0078, 0x957e, 0x7210, 0x2c08, 0xa085, 0x0001, 0x1078,
-	0xa1f6, 0x2c10, 0x2160, 0x0040, 0x95b5, 0x0078, 0x957e, 0x6007,
-	0x0037, 0x6013, 0x1500, 0x0078, 0x9589, 0x6007, 0x0037, 0x6013,
-	0x1700, 0x0078, 0x9589, 0x6007, 0x0012, 0x0078, 0x9589, 0x1078,
-	0x29bb, 0x00c0, 0x9674, 0x6018, 0xa080, 0x0001, 0x2004, 0xa084,
-	0xff00, 0x8007, 0xa086, 0x0006, 0x00c0, 0x94a8, 0x0e7e, 0x0d7e,
-	0x0c7e, 0x2001, 0xa772, 0x2004, 0xd0e4, 0x0040, 0x9631, 0x2069,
-	0xa700, 0x2071, 0xac8c, 0x7008, 0x6036, 0x720c, 0x623a, 0xa286,
-	0xffff, 0x00c0, 0x95ee, 0x7208, 0x0c7e, 0x2c08, 0xa085, 0x0001,
-	0x1078, 0xa1f6, 0x2c10, 0x0c7f, 0x0040, 0x9625, 0x1078, 0x8d02,
-	0x0040, 0x9625, 0x0c7e, 0x027e, 0x2260, 0x1078, 0x8a03, 0x027f,
-	0x0c7f, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186, 0x0001, 0x0040,
-	0x960f, 0xa186, 0x0005, 0x0040, 0x9609, 0xa186, 0x0007, 0x00c0,
-	0x9619, 0xa280, 0x0004, 0x2004, 0xa005, 0x0040, 0x9619, 0x057e,
-	0x7510, 0x7614, 0x1078, 0xa2b3, 0x057f, 0x0c7f, 0x0d7f, 0x0e7f,
-	0x007c, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003,
-	0x0001, 0x1078, 0x5d8a, 0x0078, 0x9615, 0x6007, 0x003b, 0x602b,
-	0x0009, 0x6013, 0x1700, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x0078,
-	0x9615, 0x6007, 0x003b, 0x602b, 0x000b, 0x6013, 0x0000, 0x0078,
-	0x9589, 0x0e7e, 0x027e, 0x1078, 0x4967, 0x0040, 0x966e, 0x1078,
-	0x4957, 0x1078, 0xa4b9, 0x00c0, 0x966c, 0x2071, 0xa700, 0x70cc,
-	0xc085, 0x70ce, 0x0f7e, 0x2079, 0x0100, 0x7298, 0xa284, 0x00ff,
-	0x706e, 0x78e6, 0xa284, 0xff00, 0x7270, 0xa205, 0x7072, 0x78ea,
-	0x0f7f, 0x70d7, 0x0000, 0x2001, 0xa753, 0x2004, 0xd0a4, 0x0040,
-	0x9665, 0x2011, 0xa9ca, 0x2013, 0x07d0, 0xd0ac, 0x00c0, 0x966e,
-	0x1078, 0x2677, 0x0078, 0x966e, 0x1078, 0xa4e9, 0x027f, 0x0e7f,
-	0x1078, 0x772d, 0x0078, 0x94a7, 0x1078, 0x772d, 0x007c, 0x0d7e,
-	0x067e, 0x6618, 0x2668, 0x6e04, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0006, 0x0040, 0x9694, 0xa686, 0x0004, 0x0040, 0x9694, 0x6e04,
-	0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0040, 0x9694, 0xa686, 0x0004,
-	0x0040, 0x9694, 0xa085, 0x0001, 0x067f, 0x0d7f, 0x007c, 0x0d7e,
-	0x1078, 0x96cb, 0x0d7f, 0x007c, 0x0d7e, 0x1078, 0x96da, 0x00c0,
-	0x96c4, 0x680c, 0xa08c, 0xff00, 0x6820, 0xa084, 0x00ff, 0xa115,
-	0x6212, 0x6824, 0x602a, 0xd1e4, 0x0040, 0x96b2, 0x2009, 0x0001,
-	0x0078, 0x96c0, 0xd1ec, 0x0040, 0x96c4, 0x6920, 0xa18c, 0x00ff,
-	0x6824, 0x1078, 0x254d, 0x00c0, 0x96c4, 0x2110, 0x2009, 0x0000,
-	0x1078, 0x28c8, 0x0078, 0x96c8, 0xa085, 0x0001, 0x0078, 0x96c9,
-	0xa006, 0x0d7f, 0x007c, 0x2069, 0xac8d, 0x6800, 0xa082, 0x0010,
-	0x00c8, 0x96d8, 0x6013, 0x0000, 0xa085, 0x0001, 0x0078, 0x96d9,
-	0xa006, 0x007c, 0x6013, 0x0000, 0x2069, 0xac8c, 0x6808, 0xa084,
-	0xff00, 0xa086, 0x0800, 0x00c0, 0x96ee, 0x6800, 0xa084, 0x00ff,
-	0xa08e, 0x0014, 0x0040, 0x96ee, 0xa08e, 0x0010, 0x007c, 0x6004,
-	0xa0b2, 0x0044, 0x10c8, 0x1332, 0xa1b6, 0x0013, 0x00c0, 0x96fb,
-	0x2008, 0x0079, 0x970e, 0xa1b6, 0x0027, 0x0040, 0x9703, 0xa1b6,
-	0x0014, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078,
-	0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, 0x974e, 0x9750,
-	0x974e, 0x974e, 0x974e, 0x9750, 0x975c, 0x97e6, 0x97a9, 0x97e6,
-	0x97bd, 0x97e6, 0x975c, 0x97e6, 0x97de, 0x97e6, 0x97de, 0x97e6,
-	0x97e6, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e, 0x974e,
-	0x974e, 0x974e, 0x974e, 0x974e, 0x9750, 0x974e, 0x97e6, 0x974e,
-	0x974e, 0x97e6, 0x974e, 0x97e6, 0x97e6, 0x974e, 0x974e, 0x974e,
-	0x974e, 0x97e6, 0x97e6, 0x974e, 0x97e6, 0x97e6, 0x974e, 0x974e,
-	0x974e, 0x974e, 0x974e, 0x9750, 0x97e6, 0x97e6, 0x974e, 0x974e,
-	0x97e6, 0x97e6, 0x974e, 0x974e, 0x974e, 0x974e, 0x1078, 0x1332,
-	0x1078, 0x61cd, 0x2001, 0xa9a2, 0x2004, 0x6016, 0x6003, 0x0002,
-	0x1078, 0x62d1, 0x0078, 0x97ec, 0x0f7e, 0x2079, 0xa752, 0x7804,
-	0x0f7f, 0xd0ac, 0x00c0, 0x97e6, 0x2001, 0x0000, 0x1078, 0x44ee,
-	0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff, 0x0040, 0x97e6,
-	0x0c7e, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x00c0, 0x9780, 0x6010,
-	0xa005, 0x0040, 0x9780, 0x0c7f, 0x1078, 0x3699, 0x0078, 0x97e6,
-	0x0c7f, 0x2001, 0xa700, 0x2004, 0xa086, 0x0002, 0x00c0, 0x978f,
-	0x0f7e, 0x2079, 0xa700, 0x7890, 0x8000, 0x7892, 0x0f7f, 0x2001,
-	0x0002, 0x1078, 0x4502, 0x1078, 0x61cd, 0x601f, 0x0001, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x1078, 0x5dd7, 0x1078, 0x62d1, 0x0c7e,
-	0x6118, 0x2160, 0x2009, 0x0001, 0x1078, 0x5a52, 0x0c7f, 0x0078,
-	0x97ec, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4, 0xff00,
-	0x8637, 0xa686, 0x0006, 0x0040, 0x97e6, 0xa686, 0x0004, 0x0040,
-	0x97e6, 0x2001, 0x0004, 0x0078, 0x97e4, 0x2001, 0xa700, 0x2004,
-	0xa086, 0x0003, 0x00c0, 0x97c6, 0x1078, 0x3699, 0x2001, 0x0006,
-	0x1078, 0x97ed, 0x6618, 0x0d7e, 0x2668, 0x6e04, 0x0d7f, 0xa6b4,
-	0xff00, 0x8637, 0xa686, 0x0006, 0x0040, 0x97e6, 0x2001, 0x0006,
-	0x0078, 0x97e4, 0x2001, 0x0004, 0x0078, 0x97e4, 0x2001, 0x0006,
-	0x1078, 0x97ed, 0x0078, 0x97e6, 0x1078, 0x4535, 0x1078, 0x61cd,
-	0x1078, 0x772d, 0x1078, 0x62d1, 0x007c, 0x017e, 0x0d7e, 0x6118,
-	0x2168, 0x6900, 0xd184, 0x0040, 0x9808, 0x6104, 0xa18e, 0x000a,
-	0x00c0, 0x9800, 0x699c, 0xd1a4, 0x00c0, 0x9800, 0x2001, 0x0007,
-	0x1078, 0x4502, 0x2001, 0x0000, 0x1078, 0x44ee, 0x1078, 0x28a6,
-	0x0d7f, 0x017f, 0x007c, 0x0d7e, 0x6618, 0x2668, 0x6804, 0xa084,
-	0xff00, 0x8007, 0x0d7f, 0xa0b2, 0x000c, 0x10c8, 0x1332, 0xa1b6,
-	0x0015, 0x00c0, 0x981f, 0x1079, 0x9826, 0x0078, 0x9825, 0xa1b6,
-	0x0016, 0x10c0, 0x1332, 0x1079, 0x9832, 0x007c, 0x7d4e, 0x7d4e,
-	0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x9887, 0x983e, 0x7d4e, 0x7d4e,
-	0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e,
-	0x9887, 0x988f, 0x7d4e, 0x7d4e, 0x7d4e, 0x7d4e, 0x0f7e, 0x2079,
-	0xa752, 0x7804, 0xd0ac, 0x00c0, 0x9865, 0x6018, 0xa07d, 0x0040,
-	0x9865, 0x7800, 0xd0f4, 0x00c0, 0x9851, 0x7810, 0xa005, 0x00c0,
-	0x9865, 0x2001, 0x0000, 0x1078, 0x44ee, 0x2001, 0x0002, 0x1078,
-	0x4502, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x1078,
-	0x5dd7, 0x1078, 0x62d1, 0x0078, 0x9885, 0x2011, 0xac83, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9885, 0x0c7e, 0x1078,
-	0x45c4, 0x0040, 0x9878, 0x0c7f, 0x1078, 0x772d, 0x0078, 0x9885,
-	0x6010, 0x007e, 0x6014, 0x007e, 0x1078, 0x42f8, 0x007f, 0x6016,
-	0x007f, 0x6012, 0x0c7f, 0x1078, 0x772d, 0x0f7f, 0x007c, 0x6604,
-	0xa6b6, 0x001e, 0x00c0, 0x988e, 0x1078, 0x772d, 0x007c, 0x1078,
-	0x7f8e, 0x00c0, 0x989b, 0x6003, 0x0001, 0x6007, 0x0001, 0x1078,
-	0x5dd7, 0x0078, 0x989d, 0x1078, 0x772d, 0x007c, 0x6004, 0xa08a,
-	0x0044, 0x10c8, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078,
-	0x62d1, 0x007c, 0xa182, 0x0040, 0x0079, 0x98ae, 0x98c1, 0x98c1,
-	0x98c1, 0x98c1, 0x98c3, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1,
-	0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1, 0x98c1,
-	0x98c1, 0x1078, 0x1332, 0x0d7e, 0x0e7e, 0x0f7e, 0x157e, 0x047e,
-	0x027e, 0x6218, 0xa280, 0x002b, 0x2004, 0xa005, 0x0040, 0x98d4,
-	0x2021, 0x0000, 0x1078, 0xa482, 0x6106, 0x2071, 0xac80, 0x7444,
-	0xa4a4, 0xff00, 0x0040, 0x992b, 0xa486, 0x2000, 0x00c0, 0x98e6,
-	0x2009, 0x0001, 0x2011, 0x0200, 0x1078, 0x5bf1, 0x1078, 0x138b,
-	0x1040, 0x1332, 0x6003, 0x0007, 0x2d00, 0x6837, 0x010d, 0x6803,
-	0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00, 0x685e, 0x6008, 0x68b2,
-	0x6018, 0x2078, 0x78a0, 0x8007, 0x7130, 0x694a, 0x017e, 0xa084,
-	0xff00, 0x6846, 0x684f, 0x0000, 0x6857, 0x0036, 0x1078, 0x4a73,
-	0x017f, 0xa486, 0x2000, 0x00c0, 0x9913, 0x2019, 0x0017, 0x1078,
-	0xa1a5, 0x0078, 0x998d, 0xa486, 0x0400, 0x00c0, 0x991d, 0x2019,
-	0x0002, 0x1078, 0xa156, 0x0078, 0x998d, 0xa486, 0x0200, 0x00c0,
-	0x9923, 0x1078, 0xa13b, 0xa486, 0x1000, 0x00c0, 0x9929, 0x1078,
-	0xa18a, 0x0078, 0x998d, 0x2069, 0xaa33, 0x6a00, 0xd284, 0x0040,
-	0x99f7, 0xa284, 0x0300, 0x00c0, 0x99ef, 0x6804, 0xa005, 0x0040,
-	0x99d5, 0x2d78, 0x6003, 0x0007, 0x1078, 0x1370, 0x0040, 0x9994,
-	0x7800, 0xd08c, 0x00c0, 0x9947, 0x7804, 0x8001, 0x7806, 0x6013,
-	0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008,
-	0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
-	0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992,
-	0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286,
-	0x0002, 0x00c0, 0x996f, 0x684f, 0x0040, 0x0078, 0x9979, 0xa286,
-	0x0001, 0x00c0, 0x9977, 0x684f, 0x0080, 0x0078, 0x9979, 0x684f,
-	0x0000, 0x20a9, 0x000a, 0x2001, 0xac90, 0xad90, 0x0015, 0x200c,
-	0x810f, 0x2112, 0x8000, 0x8210, 0x00f0, 0x997f, 0x200c, 0x6982,
-	0x8000, 0x200c, 0x697e, 0x1078, 0x4a73, 0x027f, 0x047f, 0x157f,
-	0x0f7f, 0x0e7f, 0x0d7f, 0x007c, 0x2001, 0xa70e, 0x2004, 0xd084,
-	0x0040, 0x999e, 0x1078, 0x138b, 0x00c0, 0x9940, 0x6013, 0x0100,
-	0x6003, 0x0001, 0x6007, 0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1,
-	0x0078, 0x998d, 0x2069, 0xac92, 0x2d04, 0xa084, 0xff00, 0xa086,
-	0x1200, 0x00c0, 0x99c9, 0x2069, 0xac80, 0x686c, 0xa084, 0x00ff,
-	0x017e, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x017f, 0x6003,
-	0x0001, 0x6007, 0x0043, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078,
-	0x998d, 0x6013, 0x0200, 0x6003, 0x0001, 0x6007, 0x0041, 0x1078,
-	0x5d8a, 0x1078, 0x62d1, 0x0078, 0x998d, 0x2001, 0xa70d, 0x2004,
-	0xd0ec, 0x0040, 0x99df, 0x2011, 0x8049, 0x1078, 0x361b, 0x6013,
-	0x0300, 0x0078, 0x99e5, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007,
-	0x0041, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x998d, 0x6013,
-	0x0500, 0x0078, 0x99e5, 0x6013, 0x0600, 0x0078, 0x99aa, 0x6013,
-	0x0200, 0x0078, 0x99aa, 0xa186, 0x0013, 0x00c0, 0x9a0d, 0x6004,
-	0xa08a, 0x0040, 0x1048, 0x1332, 0xa08a, 0x0053, 0x10c8, 0x1332,
-	0xa082, 0x0040, 0x2008, 0x0079, 0x9a92, 0xa186, 0x0051, 0x0040,
-	0x9a1a, 0xa186, 0x0047, 0x00c0, 0x9a33, 0x6004, 0xa086, 0x0041,
-	0x0040, 0x9a41, 0x2001, 0x0109, 0x2004, 0xd084, 0x0040, 0x9a41,
-	0x127e, 0x2091, 0x2200, 0x007e, 0x017e, 0x027e, 0x1078, 0x5c56,
-	0x027f, 0x017f, 0x007f, 0x127f, 0x6000, 0xa086, 0x0002, 0x00c0,
-	0x9a41, 0x0078, 0x9ad7, 0xa186, 0x0027, 0x0040, 0x9a3b, 0xa186,
-	0x0014, 0x10c0, 0x1332, 0x6004, 0xa082, 0x0040, 0x2008, 0x0079,
-	0x9a44, 0x1078, 0x7773, 0x007c, 0x9a57, 0x9a59, 0x9a59, 0x9a81,
-	0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57,
-	0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x9a57, 0x1078,
-	0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x037e, 0x0d7e, 0x6010,
-	0xa06d, 0x0040, 0x9a7e, 0xad84, 0xf000, 0x0040, 0x9a7e, 0x6003,
-	0x0002, 0x6018, 0x2004, 0xd0bc, 0x00c0, 0x9a7e, 0x2019, 0x0004,
-	0x1078, 0xa1da, 0x6013, 0x0000, 0x6014, 0xa005, 0x00c0, 0x9a7c,
-	0x2001, 0xa9a3, 0x2004, 0x6016, 0x6003, 0x0007, 0x0d7f, 0x037f,
-	0x007c, 0x0d7e, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x1078, 0x8d16,
-	0x0040, 0x9a8e, 0x6010, 0x2068, 0x1078, 0x13a4, 0x1078, 0x8ed6,
-	0x0d7f, 0x007c, 0x9aa5, 0x9ac4, 0x9aae, 0x9ad1, 0x9aa5, 0x9aa5,
-	0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5,
-	0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x9aa5, 0x1078, 0x1332, 0x6010,
-	0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x1078, 0x61cd,
-	0x6010, 0xa080, 0x0013, 0x2004, 0xd0b4, 0x0040, 0x9abf, 0x6003,
-	0x0007, 0x2009, 0x0043, 0x1078, 0x775c, 0x0078, 0x9ac1, 0x6003,
-	0x0002, 0x1078, 0x62d1, 0x007c, 0x1078, 0x61cd, 0x1078, 0xa433,
-	0x00c0, 0x9ace, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x1078, 0x62d1,
-	0x007c, 0x1078, 0x61cd, 0x2009, 0x0041, 0x0078, 0x9c2e, 0xa182,
-	0x0040, 0x0079, 0x9adb, 0x9aee, 0x9af0, 0x9aee, 0x9aee, 0x9aee,
-	0x9aee, 0x9aee, 0x9af1, 0x9aee, 0x9aee, 0x9aee, 0x9aee, 0x9aee,
-	0x9aee, 0x9aee, 0x9aee, 0x9aee, 0x9afc, 0x9aee, 0x1078, 0x1332,
-	0x007c, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x1078, 0x15fa, 0x007c, 0x0d7e, 0x1078, 0x5bc1, 0x0d7f,
-	0x1078, 0xa4a5, 0x1078, 0x772d, 0x007c, 0xa182, 0x0040, 0x0079,
-	0x9b09, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c,
-	0x9b1e, 0x9b1c, 0x9b21, 0x9b4c, 0x9b1c, 0x9b1c, 0x9b1c, 0x9b1c,
-	0x9b4c, 0x9b1c, 0x9b1c, 0x9b1c, 0x1078, 0x1332, 0x1078, 0x7773,
-	0x007c, 0x1078, 0x627a, 0x1078, 0x639b, 0x6010, 0x0d7e, 0x2068,
-	0x684c, 0xd0fc, 0x0040, 0x9b37, 0xa08c, 0x0003, 0xa18e, 0x0002,
-	0x0040, 0x9b3f, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c2e, 0x6003,
-	0x0007, 0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x1078,
-	0xa433, 0x0040, 0x9b45, 0x0d7f, 0x007c, 0x1078, 0x5bc1, 0x1078,
-	0x772d, 0x0d7f, 0x0078, 0x9b3e, 0x037e, 0x1078, 0x627a, 0x1078,
-	0x639b, 0x6010, 0x0d7e, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0040,
-	0x9b6c, 0x684c, 0xa084, 0x0003, 0xa086, 0x0002, 0x0040, 0x9b68,
-	0x687c, 0x632c, 0xa31a, 0x632e, 0x6880, 0x6328, 0xa31b, 0x632a,
-	0x6003, 0x0002, 0x0078, 0x9b7d, 0x2019, 0x0004, 0x1078, 0xa1da,
-	0x6014, 0xa005, 0x00c0, 0x9b79, 0x2001, 0xa9a3, 0x2004, 0x8003,
-	0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x0d7f, 0x037f, 0x007c,
-	0xa186, 0x0013, 0x00c0, 0x9b8e, 0x6004, 0xa086, 0x0042, 0x10c0,
-	0x1332, 0x1078, 0x61cd, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0027,
-	0x0040, 0x9b96, 0xa186, 0x0014, 0x00c0, 0x9ba6, 0x6004, 0xa086,
-	0x0042, 0x10c0, 0x1332, 0x2001, 0x0007, 0x1078, 0x4535, 0x1078,
-	0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c, 0xa182, 0x0040,
-	0x0079, 0x9baa, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd,
-	0x9bbd, 0x9bbf, 0x9bcb, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd,
-	0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x9bbd, 0x1078, 0x1332, 0x037e,
-	0x047e, 0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x1078, 0x15fa,
-	0x047f, 0x037f, 0x007c, 0x6010, 0x0d7e, 0x2068, 0x6810, 0x6a14,
-	0x6118, 0x210c, 0xd1bc, 0x0040, 0x9bea, 0x6124, 0xd1f4, 0x00c0,
-	0x9bea, 0x007e, 0x047e, 0x057e, 0x6c7c, 0xa422, 0x6d80, 0x2200,
-	0xa52b, 0x602c, 0xa420, 0x642e, 0x6028, 0xa529, 0x652a, 0x057f,
-	0x047f, 0x007f, 0xa20d, 0x00c0, 0x9bfe, 0x684c, 0xd0fc, 0x0040,
-	0x9bf6, 0x2009, 0x0041, 0x0d7f, 0x0078, 0x9c2e, 0x6003, 0x0007,
-	0x6017, 0x0000, 0x1078, 0x5bc1, 0x0d7f, 0x007c, 0x007e, 0x0f7e,
-	0x2c78, 0x1078, 0x4963, 0x0f7f, 0x007f, 0x0040, 0x9c0b, 0x6003,
-	0x0002, 0x0d7f, 0x007c, 0x2009, 0xa70d, 0x210c, 0xd19c, 0x0040,
-	0x9c15, 0x6003, 0x0007, 0x0078, 0x9c17, 0x6003, 0x0006, 0x1078,
-	0x9c1d, 0x1078, 0x5bc3, 0x0d7f, 0x007c, 0xd2fc, 0x0040, 0x9c29,
-	0x8002, 0x8000, 0x8212, 0xa291, 0x0000, 0x2009, 0x0009, 0x0078,
-	0x9c2b, 0x2009, 0x0015, 0x6a6a, 0x6866, 0x007c, 0xa182, 0x0040,
-	0x0048, 0x9c34, 0x0079, 0x9c41, 0xa186, 0x0013, 0x0040, 0x9c3c,
-	0xa186, 0x0014, 0x10c0, 0x1332, 0x6024, 0xd0dc, 0x1040, 0x1332,
-	0x007c, 0x9c54, 0x9c5b, 0x9c67, 0x9c73, 0x9c54, 0x9c54, 0x9c54,
-	0x9c82, 0x9c54, 0x9c56, 0x9c56, 0x9c54, 0x9c54, 0x9c54, 0x9c54,
-	0x9c54, 0x9c54, 0x9c54, 0x9c54, 0x1078, 0x1332, 0x6024, 0xd0dc,
-	0x1040, 0x1332, 0x007c, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a,
-	0x127e, 0x2091, 0x8000, 0x1078, 0x62d1, 0x127f, 0x007c, 0x6003,
-	0x0001, 0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078,
-	0x62d1, 0x127f, 0x007c, 0x6003, 0x0003, 0x6106, 0x2c10, 0x1078,
-	0x1cf0, 0x127e, 0x2091, 0x8000, 0x1078, 0x5df6, 0x1078, 0x639b,
-	0x127f, 0x007c, 0xa016, 0x1078, 0x15fa, 0x007c, 0x127e, 0x2091,
-	0x8000, 0x037e, 0x0d7e, 0xa182, 0x0040, 0x1079, 0x9c93, 0x0d7f,
-	0x037f, 0x127f, 0x007c, 0x9ca3, 0x9ca5, 0x9cba, 0x9cd9, 0x9ca3,
-	0x9ca3, 0x9ca3, 0x9cf1, 0x9ca3, 0x9ca3, 0x9ca3, 0x9ca3, 0x9ca3,
-	0x9ca3, 0x9ca3, 0x9ca3, 0x1078, 0x1332, 0x6010, 0x2068, 0x684c,
-	0xd0fc, 0x0040, 0x9ccf, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040,
-	0x9ccf, 0x6003, 0x0001, 0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1,
-	0x0078, 0x9cf4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9ccf,
-	0xa09c, 0x0003, 0xa39e, 0x0003, 0x0040, 0x9ccf, 0x6003, 0x0001,
-	0x6106, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0078, 0x9cf4, 0x6013,
-	0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x1078, 0xa1da, 0x0078,
-	0x9cf4, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0040, 0x9ccf, 0xa09c,
-	0x0003, 0xa39e, 0x0003, 0x0040, 0x9ccf, 0x6003, 0x0003, 0x6106,
-	0x2c10, 0x1078, 0x1cf0, 0x1078, 0x5df6, 0x1078, 0x639b, 0x0078,
-	0x9cf4, 0xa016, 0x1078, 0x15fa, 0x007c, 0x1078, 0x61cd, 0x6110,
-	0x81ff, 0x0040, 0x9d06, 0x0d7e, 0x2168, 0x1078, 0xa4f2, 0x037e,
-	0x2019, 0x0029, 0x1078, 0xa1da, 0x037f, 0x0d7f, 0x1078, 0x8ed6,
-	0x1078, 0x62d1, 0x007c, 0x1078, 0x627a, 0x6110, 0x81ff, 0x0040,
-	0x9d1c, 0x0d7e, 0x2168, 0x1078, 0xa4f2, 0x037e, 0x2019, 0x0029,
-	0x1078, 0xa1da, 0x037f, 0x0d7f, 0x1078, 0x8ed6, 0x1078, 0x639b,
-	0x007c, 0xa182, 0x0085, 0x0079, 0x9d25, 0x9d2e, 0x9d2c, 0x9d2c,
-	0x9d3a, 0x9d2c, 0x9d2c, 0x9d2c, 0x1078, 0x1332, 0x6003, 0x000b,
-	0x6106, 0x1078, 0x5d8a, 0x127e, 0x2091, 0x8000, 0x1078, 0x62d1,
-	0x127f, 0x007c, 0x027e, 0x0e7e, 0x1078, 0xa42c, 0x0040, 0x9d44,
-	0x1078, 0x772d, 0x0078, 0x9d60, 0x2071, 0xac80, 0x7224, 0x6212,
-	0x7220, 0x1078, 0xa079, 0x0040, 0x9d51, 0x6007, 0x0086, 0x0078,
-	0x9d5a, 0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x00c0, 0x9d5a,
-	0x6007, 0x0086, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1,
-	0x0e7f, 0x027f, 0x007c, 0xa186, 0x0013, 0x00c0, 0x9d74, 0x6004,
-	0xa08a, 0x0085, 0x1048, 0x1332, 0xa08a, 0x008c, 0x10c8, 0x1332,
-	0xa082, 0x0085, 0x0079, 0x9d8b, 0xa186, 0x0027, 0x0040, 0x9d80,
-	0xa186, 0x0014, 0x0040, 0x9d80, 0x1078, 0x7773, 0x0078, 0x9d8a,
-	0x2001, 0x0007, 0x1078, 0x4535, 0x1078, 0x61cd, 0x1078, 0x8ed6,
-	0x1078, 0x62d1, 0x007c, 0x9d92, 0x9d94, 0x9d94, 0x9d92, 0x9d92,
-	0x9d92, 0x9d92, 0x1078, 0x1332, 0x1078, 0x61cd, 0x1078, 0x8ed6,
-	0x1078, 0x62d1, 0x007c, 0xa182, 0x0085, 0x1048, 0x1332, 0xa182,
-	0x008c, 0x10c8, 0x1332, 0xa182, 0x0085, 0x0079, 0x9da7, 0x9dae,
-	0x9dae, 0x9dae, 0x9db0, 0x9dae, 0x9dae, 0x9dae, 0x1078, 0x1332,
-	0x007c, 0xa186, 0x0013, 0x0040, 0x9dc1, 0xa186, 0x0014, 0x0040,
-	0x9dc1, 0xa186, 0x0027, 0x0040, 0x9dc1, 0x1078, 0x7773, 0x0078,
-	0x9dc7, 0x1078, 0x61cd, 0x1078, 0x8ed6, 0x1078, 0x62d1, 0x007c,
-	0x037e, 0x1078, 0xa4a5, 0x603f, 0x0000, 0x2019, 0x000b, 0x1078,
-	0x9dd7, 0x601f, 0x0006, 0x6003, 0x0007, 0x037f, 0x007c, 0x127e,
-	0x037e, 0x2091, 0x8000, 0x087e, 0x2c40, 0x097e, 0x2049, 0x0000,
-	0x1078, 0x7246, 0x097f, 0x087f, 0x00c0, 0x9e12, 0x077e, 0x2c38,
-	0x1078, 0x72f3, 0x077f, 0x00c0, 0x9e12, 0x6000, 0xa086, 0x0000,
-	0x0040, 0x9e12, 0x601c, 0xa086, 0x0007, 0x0040, 0x9e12, 0x0d7e,
-	0x6000, 0xa086, 0x0004, 0x00c0, 0x9e03, 0x1078, 0xa4a5, 0x601f,
-	0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040,
-	0x9e0b, 0x1078, 0xa1da, 0x0d7f, 0x6013, 0x0000, 0x1078, 0xa4a5,
-	0x601f, 0x0007, 0x037f, 0x127f, 0x007c, 0x0f7e, 0x0c7e, 0x037e,
-	0x157e, 0x2079, 0xac80, 0x7938, 0x783c, 0x1078, 0x254d, 0x00c0,
-	0x9e59, 0x017e, 0x0c7e, 0x1078, 0x45c4, 0x00c0, 0x9e59, 0x017f,
-	0x027f, 0x027e, 0x017e, 0x2019, 0x0029, 0x1078, 0x73d0, 0x1078,
-	0x5f01, 0x077e, 0x2039, 0x0000, 0x1078, 0x5e0a, 0x077f, 0x017f,
-	0x077e, 0x2039, 0x0000, 0x1078, 0x9f9b, 0x077f, 0x1078, 0x47e9,
-	0x027e, 0x6204, 0xa294, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040,
-	0x9e4d, 0xa286, 0x0004, 0x00c0, 0x9e50, 0x62a0, 0x1078, 0x2942,
-	0x027f, 0x017f, 0x1078, 0x42f8, 0x6612, 0x6516, 0xa006, 0x0078,
-	0x9e5b, 0x0c7f, 0x017f, 0x157f, 0x037f, 0x0c7f, 0x0f7f, 0x007c,
-	0x0c7e, 0x0d7e, 0x0e7e, 0x017e, 0x2009, 0xa720, 0x2104, 0xa086,
-	0x0074, 0x00c0, 0x9ec3, 0x2069, 0xac8e, 0x690c, 0xa182, 0x0100,
-	0x0048, 0x9eb3, 0x6908, 0xa184, 0x8000, 0x0040, 0x9ebf, 0x6018,
-	0x2070, 0x7010, 0xa084, 0x00ff, 0x0040, 0x9e82, 0x7000, 0xd0f4,
-	0x0040, 0x9e86, 0xa184, 0x0800, 0x0040, 0x9ebf, 0x6910, 0xa18a,
-	0x0001, 0x0048, 0x9eb7, 0x6914, 0x2069, 0xacae, 0x6904, 0x81ff,
-	0x00c0, 0x9eab, 0x690c, 0xa182, 0x0100, 0x0048, 0x9eb3, 0x6908,
-	0x81ff, 0x00c0, 0x9eaf, 0x6910, 0xa18a, 0x0001, 0x0048, 0x9eb7,
-	0x6918, 0xa18a, 0x0001, 0x0048, 0x9ebf, 0x0078, 0x9ec9, 0x6013,
-	0x0100, 0x0078, 0x9ec5, 0x6013, 0x0300, 0x0078, 0x9ec5, 0x6013,
-	0x0500, 0x0078, 0x9ec5, 0x6013, 0x0700, 0x0078, 0x9ec5, 0x6013,
-	0x0900, 0x0078, 0x9ec5, 0x6013, 0x0b00, 0x0078, 0x9ec5, 0x6013,
-	0x0f00, 0x0078, 0x9ec5, 0x6013, 0x2d00, 0xa085, 0x0001, 0x0078,
-	0x9eca, 0xa006, 0x017f, 0x0e7f, 0x0d7f, 0x0c7f, 0x007c, 0x0c7e,
-	0x0d7e, 0x027e, 0x037e, 0x157e, 0x6218, 0x2268, 0x6b04, 0xa394,
-	0x00ff, 0xa286, 0x0006, 0x0040, 0x9ef3, 0xa286, 0x0004, 0x0040,
-	0x9ef3, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0040, 0x9ef3,
-	0xa286, 0x0004, 0x0040, 0x9ef3, 0x0c7e, 0x2d60, 0x1078, 0x45d6,
-	0x0c7f, 0x0078, 0x9f2e, 0x2011, 0xac96, 0xad98, 0x000a, 0x20a9,
-	0x0004, 0x1078, 0x80de, 0x00c0, 0x9f2f, 0x2011, 0xac9a, 0xad98,
-	0x0006, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f2f, 0x047e,
-	0x017e, 0x6aa0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009, 0xa753,
-	0x210c, 0xd1a4, 0x0040, 0x9f1b, 0x2009, 0x0029, 0x1078, 0xa22d,
-	0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029, 0x1078, 0x5f01, 0x077e,
-	0x2039, 0x0000, 0x1078, 0x5e0a, 0x2c08, 0x1078, 0x9f9b, 0x077f,
-	0x2001, 0x0007, 0x1078, 0x4535, 0x017f, 0x047f, 0xa006, 0x157f,
-	0x037f, 0x027f, 0x0d7f, 0x0c7f, 0x007c, 0x0d7e, 0x2069, 0xac8e,
-	0x6800, 0xa086, 0x0800, 0x0040, 0x9f41, 0x6013, 0x0000, 0x0078,
-	0x9f42, 0xa006, 0x0d7f, 0x007c, 0x0c7e, 0x0f7e, 0x017e, 0x027e,
-	0x037e, 0x157e, 0x2079, 0xac8c, 0x7930, 0x7834, 0x1078, 0x254d,
-	0x00c0, 0x9f68, 0x1078, 0x45c4, 0x00c0, 0x9f68, 0x2011, 0xac90,
-	0xac98, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de, 0x00c0, 0x9f68,
-	0x2011, 0xac94, 0xac98, 0x0006, 0x20a9, 0x0004, 0x1078, 0x80de,
-	0x157f, 0x037f, 0x027f, 0x017f, 0x0f7f, 0x0c7f, 0x007c, 0x0c7e,
-	0x007e, 0x017e, 0x027e, 0x037e, 0x157e, 0x2011, 0xac83, 0x2204,
-	0x8211, 0x220c, 0x1078, 0x254d, 0x00c0, 0x9f94, 0x1078, 0x45c4,
-	0x00c0, 0x9f94, 0x2011, 0xac96, 0xac98, 0x000a, 0x20a9, 0x0004,
-	0x1078, 0x80de, 0x00c0, 0x9f94, 0x2011, 0xac9a, 0xac98, 0x0006,
-	0x20a9, 0x0004, 0x1078, 0x80de, 0x157f, 0x037f, 0x027f, 0x017f,
-	0x007f, 0x0c7f, 0x007c, 0x0e7e, 0x0c7e, 0x087e, 0x077e, 0x067e,
-	0x057e, 0x047e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740, 0x2029,
-	0xa9ba, 0x252c, 0x2021, 0xa9c0, 0x2424, 0x2061, 0xae00, 0x2071,
-	0xa700, 0x7648, 0x7064, 0x81ff, 0x0040, 0x9fc2, 0x007e, 0xa186,
-	0xaab3, 0x007f, 0x0040, 0x9fc2, 0x8001, 0xa602, 0x00c8, 0xa02c,
-	0x0078, 0x9fc5, 0xa606, 0x0040, 0xa02c, 0x2100, 0xac06, 0x0040,
-	0xa022, 0x1078, 0xa252, 0x0040, 0xa022, 0x671c, 0xa786, 0x0001,
-	0x0040, 0xa047, 0xa786, 0x0004, 0x0040, 0xa047, 0xa786, 0x0007,
-	0x0040, 0xa022, 0x2500, 0xac06, 0x0040, 0xa022, 0x2400, 0xac06,
-	0x0040, 0xa022, 0x1078, 0xa266, 0x00c0, 0xa022, 0x88ff, 0x0040,
-	0x9fed, 0x6020, 0xa906, 0x00c0, 0xa022, 0x0d7e, 0x6000, 0xa086,
-	0x0004, 0x00c0, 0x9ff7, 0x017e, 0x1078, 0x1757, 0x017f, 0xa786,
-	0x0008, 0x00c0, 0xa006, 0x1078, 0x8f10, 0x00c0, 0xa006, 0x1078,
-	0x7c83, 0x0d7f, 0x1078, 0x8ed6, 0x0078, 0xa022, 0x6010, 0x2068,
-	0x1078, 0x8d16, 0x0040, 0xa01f, 0xa786, 0x0003, 0x00c0, 0xa036,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x1078, 0xa4f2, 0x017e,
-	0x1078, 0x8f8d, 0x1078, 0x4a73, 0x017f, 0x1078, 0x8ec9, 0x0d7f,
-	0x1078, 0x8ed6, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02,
-	0x00c8, 0xa02c, 0x0078, 0x9faf, 0x127f, 0x027f, 0x047f, 0x057f,
-	0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x007c, 0xa786, 0x0006,
-	0x00c0, 0xa010, 0xa386, 0x0005, 0x0040, 0xa044, 0x1078, 0xa4f2,
-	0x1078, 0xa1da, 0x0078, 0xa01f, 0x0d7f, 0x0078, 0xa022, 0x1078,
-	0xa266, 0x00c0, 0xa022, 0x81ff, 0x0040, 0xa022, 0xa180, 0x0001,
-	0x2004, 0xa086, 0x0018, 0x0040, 0xa05c, 0xa180, 0x0001, 0x2004,
-	0xa086, 0x002d, 0x00c0, 0xa022, 0x6000, 0xa086, 0x0002, 0x00c0,
-	0xa022, 0x1078, 0x8efc, 0x0040, 0xa06d, 0x1078, 0x8f10, 0x00c0,
-	0xa022, 0x1078, 0x7c83, 0x0078, 0xa075, 0x1078, 0x28a6, 0x1078,
-	0x8f10, 0x00c0, 0xa075, 0x1078, 0x7c83, 0x1078, 0x8ed6, 0x0078,
-	0xa022, 0x0c7e, 0x0e7e, 0x017e, 0x2c08, 0x2170, 0xa006, 0x1078,
-	0xa1f6, 0x017f, 0x0040, 0xa089, 0x601c, 0xa084, 0x000f, 0x1079,
-	0xa08c, 0x0e7f, 0x0c7f, 0x007c, 0xa094, 0xa094, 0xa094, 0xa094,
-	0xa094, 0xa094, 0xa096, 0xa094, 0xa006, 0x007c, 0x047e, 0x017e,
-	0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00,
-	0x2009, 0x0020, 0x1078, 0xa22d, 0x017f, 0x047f, 0x037e, 0x2019,
-	0x0002, 0x1078, 0x9dd7, 0x037f, 0xa085, 0x0001, 0x007c, 0x2001,
-	0x0001, 0x1078, 0x44ee, 0x157e, 0x017e, 0x027e, 0x037e, 0x20a9,
-	0x0004, 0x2019, 0xa705, 0x2011, 0xac96, 0x1078, 0x80de, 0x037f,
-	0x027f, 0x017f, 0x157f, 0xa005, 0x007c, 0x0f7e, 0x0e7e, 0x0c7e,
-	0x087e, 0x077e, 0x067e, 0x027e, 0x127e, 0x2091, 0x8000, 0x2740,
-	0x2061, 0xae00, 0x2079, 0x0001, 0x8fff, 0x0040, 0xa12d, 0x2071,
-	0xa700, 0x7648, 0x7064, 0x8001, 0xa602, 0x00c8, 0xa12d, 0x88ff,
-	0x0040, 0xa0e8, 0x2800, 0xac06, 0x00c0, 0xa123, 0x2079, 0x0000,
-	0x1078, 0xa252, 0x0040, 0xa123, 0x2400, 0xac06, 0x0040, 0xa123,
-	0x671c, 0xa786, 0x0006, 0x00c0, 0xa123, 0xa786, 0x0007, 0x0040,
-	0xa123, 0x88ff, 0x00c0, 0xa107, 0x6018, 0xa206, 0x00c0, 0xa123,
-	0x85ff, 0x0040, 0xa107, 0x6020, 0xa106, 0x00c0, 0xa123, 0x0d7e,
-	0x6000, 0xa086, 0x0004, 0x00c0, 0xa113, 0x1078, 0xa4a5, 0x601f,
-	0x0007, 0x1078, 0x1757, 0x6010, 0x2068, 0x1078, 0x8d16, 0x0040,
-	0xa11d, 0x047e, 0x1078, 0xa1da, 0x047f, 0x0d7f, 0x1078, 0x8ed6,
-	0x88ff, 0x00c0, 0xa137, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004,
-	0xac02, 0x00c8, 0xa12d, 0x0078, 0xa0d4, 0xa006, 0x127f, 0x027f,
-	0x067f, 0x077f, 0x087f, 0x0c7f, 0x0e7f, 0x0f7f, 0x007c, 0xa8c5,
-	0x0001, 0x0078, 0xa12e, 0x077e, 0x057e, 0x087e, 0x2041, 0x0000,
-	0x2029, 0x0001, 0x2c20, 0x2019, 0x0002, 0x6218, 0x097e, 0x2049,
-	0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078,
-	0x72f3, 0x1078, 0xa0c5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e,
-	0x057e, 0x077e, 0x0c7e, 0x157e, 0x2c20, 0x2128, 0x20a9, 0x007f,
-	0x2009, 0x0000, 0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa17e,
-	0x2c10, 0x057e, 0x087e, 0x2041, 0x0000, 0x2508, 0x2029, 0x0001,
-	0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f, 0x2039,
-	0x0000, 0x1078, 0x72f3, 0x1078, 0xa0c5, 0x057f, 0x037f, 0x017f,
-	0x8108, 0x00f0, 0xa162, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f,
-	0x027f, 0x007c, 0x077e, 0x057e, 0x6218, 0x087e, 0x2041, 0x0000,
-	0x2029, 0x0001, 0x2019, 0x0048, 0x097e, 0x2049, 0x0000, 0x1078,
-	0x7246, 0x097f, 0x087f, 0x2039, 0x0000, 0x1078, 0x72f3, 0x2c20,
-	0x1078, 0xa0c5, 0x057f, 0x077f, 0x007c, 0x027e, 0x047e, 0x057e,
-	0x077e, 0x0c7e, 0x157e, 0x2c20, 0x20a9, 0x007f, 0x2009, 0x0000,
-	0x017e, 0x037e, 0x1078, 0x45c4, 0x00c0, 0xa1ce, 0x2c10, 0x087e,
-	0x2041, 0x0000, 0x2828, 0x047e, 0x2021, 0x0001, 0x1078, 0xa482,
-	0x047f, 0x097e, 0x2049, 0x0000, 0x1078, 0x7246, 0x097f, 0x087f,
-	0x2039, 0x0000, 0x1078, 0x72f3, 0x1078, 0xa0c5, 0x037f, 0x017f,
-	0x8108, 0x00f0, 0xa1b0, 0x157f, 0x0c7f, 0x077f, 0x057f, 0x047f,
-	0x027f, 0x007c, 0x017e, 0x0f7e, 0xad82, 0xce00, 0x0048, 0xa1f3,
-	0xad82, 0xffff, 0x00c8, 0xa1f3, 0x6800, 0xa07d, 0x0040, 0xa1f0,
-	0x6803, 0x0000, 0x6b52, 0x1078, 0x4a73, 0x2f68, 0x0078, 0xa1e4,
-	0x6b52, 0x1078, 0x4a73, 0x0f7f, 0x017f, 0x007c, 0x0e7e, 0x047e,
-	0x037e, 0x2061, 0xae00, 0xa005, 0x00c0, 0xa206, 0x2071, 0xa700,
-	0x7448, 0x7064, 0x8001, 0xa402, 0x00c8, 0xa228, 0x2100, 0xac06,
-	0x0040, 0xa21a, 0x6000, 0xa086, 0x0000, 0x0040, 0xa21a, 0x6008,
-	0xa206, 0x00c0, 0xa21a, 0x6018, 0xa1a0, 0x0006, 0x2424, 0xa406,
-	0x0040, 0xa224, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004, 0xac02,
-	0x00c8, 0xa228, 0x0078, 0xa206, 0xa085, 0x0001, 0x0078, 0xa229,
-	0xa006, 0x037f, 0x047f, 0x0e7f, 0x007c, 0x0d7e, 0x007e, 0x1078,
-	0x138b, 0x007f, 0x1040, 0x1332, 0x6837, 0x010d, 0x685e, 0x027e,
-	0x2010, 0x1078, 0x8d02, 0x2001, 0x0000, 0x0040, 0xa243, 0x2200,
-	0xa080, 0x0008, 0x2004, 0x027f, 0x684a, 0x6956, 0x6c46, 0x684f,
-	0x0000, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a, 0x1078, 0x4a73,
-	0x0d7f, 0x007c, 0x6700, 0xa786, 0x0000, 0x0040, 0xa265, 0xa786,
-	0x0001, 0x0040, 0xa265, 0xa786, 0x000a, 0x0040, 0xa265, 0xa786,
-	0x0009, 0x0040, 0xa265, 0xa085, 0x0001, 0x007c, 0x0e7e, 0x6018,
-	0x2070, 0x70a0, 0xa206, 0x0e7f, 0x007c, 0x017e, 0x6004, 0xa08e,
-	0x001e, 0x00c0, 0xa287, 0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105,
-	0x6032, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0005, 0x2001,
-	0xa9a3, 0x2004, 0x6016, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x017f,
-	0x007c, 0x0005, 0x0005, 0x007c, 0x6024, 0xd0e4, 0x0040, 0xa29d,
-	0xd0cc, 0x0040, 0xa297, 0x1078, 0x8fcf, 0x0078, 0xa29d, 0x1078,
-	0xa4a5, 0x1078, 0x5bc1, 0x1078, 0x772d, 0x007c, 0xa280, 0x0007,
-	0x2004, 0xa084, 0x000f, 0x0079, 0xa2a5, 0xa2ae, 0xa2ae, 0xa2ae,
-	0xa2b0, 0xa2ae, 0xa2b0, 0xa2b0, 0xa2ae, 0xa2b0, 0xa006, 0x007c,
-	0xa085, 0x0001, 0x007c, 0xa280, 0x0007, 0x2004, 0xa084, 0x000f,
-	0x0079, 0xa2ba, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3, 0xa2c3,
-	0xa2ce, 0xa2c3, 0xa2c3, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013,
-	0x2a00, 0x6003, 0x0001, 0x1078, 0x5d8a, 0x007c, 0x0c7e, 0x2260,
-	0x1078, 0xa4a5, 0x603f, 0x0000, 0x6024, 0xc0f4, 0xc0cc, 0x6026,
-	0x0c7f, 0x0d7e, 0x2268, 0xa186, 0x0007, 0x00c0, 0xa32f, 0x6810,
-	0xa005, 0x0040, 0xa2ec, 0xa080, 0x0013, 0x2004, 0xd0fc, 0x00c0,
-	0xa2ec, 0x0d7f, 0x0078, 0xa2c3, 0x6007, 0x003a, 0x6003, 0x0001,
-	0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100, 0xa186,
-	0x0002, 0x00c0, 0xa3bd, 0x6010, 0xa005, 0x00c0, 0xa306, 0x6000,
-	0xa086, 0x0007, 0x10c0, 0x1332, 0x0078, 0xa3bd, 0xa08c, 0xf000,
-	0x00c0, 0xa312, 0x0078, 0xa312, 0x2068, 0x6800, 0xa005, 0x00c0,
-	0xa30c, 0x2d00, 0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086,
-	0x0002, 0x00c0, 0xa32b, 0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4,
-	0x684e, 0x6850, 0xc0f4, 0xc0fc, 0x6852, 0x2009, 0x0043, 0x1078,
-	0x9c2e, 0x0078, 0xa3bd, 0x2009, 0x0041, 0x0078, 0xa3b7, 0xa186,
-	0x0005, 0x00c0, 0xa376, 0x6810, 0xa080, 0x0013, 0x2004, 0xd0bc,
-	0x00c0, 0xa33d, 0x0d7f, 0x0078, 0xa2c3, 0xd0b4, 0x0040, 0xa345,
-	0xd0fc, 0x1040, 0x1332, 0x0078, 0xa2df, 0x6007, 0x003a, 0x6003,
-	0x0001, 0x1078, 0x5d8a, 0x1078, 0x62d1, 0x0c7e, 0x2d60, 0x6100,
-	0xa186, 0x0002, 0x0040, 0xa358, 0xa186, 0x0004, 0x00c0, 0xa3bd,
-	0x2071, 0xa9e7, 0x7000, 0xa086, 0x0003, 0x00c0, 0xa365, 0x7004,
-	0xac06, 0x00c0, 0xa365, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013,
-	0x200c, 0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc,
-	0xc1bc, 0x2102, 0x2009, 0x0042, 0x0078, 0xa3b7, 0x037e, 0x0d7e,
-	0x0d7e, 0x1078, 0x138b, 0x037f, 0x1040, 0x1332, 0x6837, 0x010d,
-	0x6803, 0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857,
-	0x0045, 0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6024, 0xc0dd,
-	0x6026, 0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007,
-	0x6320, 0x6b4a, 0x6846, 0x684f, 0x0000, 0x6d6a, 0x6e66, 0x686f,
-	0x0001, 0x1078, 0x4a73, 0x2019, 0x0045, 0x6008, 0x2068, 0x1078,
-	0x9dd7, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007, 0x6017,
-	0x0000, 0x603f, 0x0000, 0x0d7f, 0x037f, 0x0078, 0xa3be, 0x603f,
-	0x0000, 0x6003, 0x0007, 0x1078, 0x9c2e, 0x0c7f, 0x0d7f, 0x007c,
-	0xa186, 0x0013, 0x00c0, 0xa3ca, 0x6004, 0xa082, 0x0085, 0x2008,
-	0x0079, 0xa3e4, 0xa186, 0x0027, 0x00c0, 0xa3dd, 0x1078, 0x61cd,
-	0x037e, 0x0d7e, 0x6010, 0x2068, 0x2019, 0x0004, 0x1078, 0xa1da,
-	0x0d7f, 0x037f, 0x1078, 0x62d1, 0x007c, 0xa186, 0x0014, 0x0040,
-	0xa3ce, 0x1078, 0x7773, 0x007c, 0xa3ed, 0xa3eb, 0xa3eb, 0xa3eb,
-	0xa3eb, 0xa3eb, 0xa3ed, 0x1078, 0x1332, 0x1078, 0x61cd, 0x6003,
-	0x000c, 0x1078, 0x62d1, 0x007c, 0xa182, 0x008c, 0x00c8, 0xa3fe,
-	0xa182, 0x0085, 0x0048, 0xa3fe, 0x0079, 0xa401, 0x1078, 0x7773,
-	0x007c, 0xa408, 0xa408, 0xa408, 0xa408, 0xa40a, 0xa429, 0xa408,
-	0x1078, 0x1332, 0x0d7e, 0x2c68, 0x1078, 0x76c7, 0x0040, 0xa424,
-	0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xac8e, 0x210c, 0x6136,
-	0x2009, 0xac8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a,
-	0x601f, 0x0004, 0x1078, 0x5d8a, 0x2d60, 0x1078, 0x772d, 0x0d7f,
-	0x007c, 0x1078, 0x772d, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000,
-	0xd0ec, 0x0e7f, 0x007c, 0x6010, 0xa08c, 0xf000, 0x0040, 0xa481,
-	0xa080, 0x0013, 0x200c, 0xd1ec, 0x0040, 0xa481, 0x2001, 0xa772,
-	0x2004, 0xd0ec, 0x0040, 0xa481, 0x6003, 0x0002, 0x6024, 0xc0e5,
-	0x6026, 0xd1ac, 0x0040, 0xa45f, 0x0f7e, 0x2c78, 0x1078, 0x495f,
-	0x0f7f, 0x0040, 0xa45f, 0x2001, 0xa9a4, 0x2004, 0x603e, 0x2009,
-	0xa772, 0x210c, 0xd1f4, 0x00c0, 0xa47f, 0x0078, 0xa471, 0x2009,
-	0xa772, 0x210c, 0xd1f4, 0x0040, 0xa46b, 0x6024, 0xc0e4, 0x6026,
-	0xa006, 0x0078, 0xa481, 0x2001, 0xa9a4, 0x200c, 0x8103, 0xa100,
-	0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0040, 0xa47c,
-	0xa088, 0x0003, 0x0078, 0xa474, 0x2c0a, 0x600f, 0x0000, 0xa085,
-	0x0001, 0x007c, 0x017e, 0x0c7e, 0x0e7e, 0x6120, 0xa2f0, 0x002b,
-	0x2e04, 0x2060, 0x8cff, 0x0040, 0xa4a1, 0x84ff, 0x00c0, 0xa494,
-	0x6020, 0xa106, 0x00c0, 0xa49c, 0x600c, 0x2072, 0x1078, 0x5bc1,
-	0x1078, 0x772d, 0x0078, 0xa49e, 0xacf0, 0x0003, 0x2e64, 0x0078,
-	0xa48a, 0x0e7f, 0x0c7f, 0x017f, 0x007c, 0x0d7e, 0x6018, 0xa0e8,
-	0x002b, 0x2d04, 0xa005, 0x0040, 0xa4b7, 0xac06, 0x0040, 0xa4b5,
-	0x2d04, 0xa0e8, 0x0003, 0x0078, 0xa4a9, 0x600c, 0x206a, 0x0d7f,
-	0x007c, 0x027e, 0x037e, 0x157e, 0x2011, 0xa726, 0x2204, 0xa084,
-	0x00ff, 0x2019, 0xac8e, 0x2334, 0xa636, 0x00c0, 0xa4e5, 0x8318,
-	0x2334, 0x2204, 0xa084, 0xff00, 0xa636, 0x00c0, 0xa4e5, 0x2011,
-	0xac90, 0x6018, 0xa098, 0x000a, 0x20a9, 0x0004, 0x1078, 0x80de,
-	0x00c0, 0xa4e5, 0x2011, 0xac94, 0x6018, 0xa098, 0x0006, 0x20a9,
-	0x0004, 0x1078, 0x80de, 0x00c0, 0xa4e5, 0x157f, 0x037f, 0x027f,
-	0x007c, 0x0e7e, 0x2071, 0xa700, 0x1078, 0x42b8, 0x1078, 0x2677,
-	0x0e7f, 0x007c, 0x0e7e, 0x6018, 0x2070, 0x7000, 0xd0fc, 0x0040,
-	0xa4fb, 0x1078, 0xa4fd, 0x0e7f, 0x007c, 0x6850, 0xc0e5, 0x6852,
-	0x007c, 0x0e7e, 0x0c7e, 0x077e, 0x067e, 0x057e, 0x047e, 0x027e,
-	0x017e, 0x127e, 0x2091, 0x8000, 0x2029, 0xa9ba, 0x252c, 0x2021,
-	0xa9c0, 0x2424, 0x2061, 0xae00, 0x2071, 0xa700, 0x7648, 0x7064,
-	0xa606, 0x0040, 0xa555, 0x671c, 0xa786, 0x0001, 0x0040, 0xa524,
-	0xa786, 0x0008, 0x00c0, 0xa54b, 0x2500, 0xac06, 0x0040, 0xa54b,
-	0x2400, 0xac06, 0x0040, 0xa54b, 0x1078, 0xa252, 0x0040, 0xa54b,
-	0x1078, 0xa266, 0x00c0, 0xa54b, 0x6000, 0xa086, 0x0004, 0x00c0,
-	0xa53d, 0x017e, 0x1078, 0x1757, 0x017f, 0x1078, 0x8efc, 0x00c0,
-	0xa543, 0x1078, 0x28a6, 0x1078, 0x8f10, 0x00c0, 0xa549, 0x1078,
-	0x7c83, 0x1078, 0x8ed6, 0xace0, 0x0010, 0x2001, 0xa716, 0x2004,
-	0xac02, 0x00c8, 0xa555, 0x0078, 0xa514, 0x127f, 0x017f, 0x027f,
-	0x047f, 0x057f, 0x067f, 0x077f, 0x0c7f, 0x0e7f, 0x007c, 0x127e,
-	0x007e, 0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa740, 0xd5a4,
-	0x0040, 0xa56d, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa573,
-	0x7030, 0x8000, 0x7032, 0xd5ac, 0x0040, 0xa589, 0x2500, 0xa084,
-	0x0007, 0xa08e, 0x0003, 0x0040, 0xa589, 0xa08e, 0x0004, 0x0040,
-	0xa589, 0xa08e, 0x0005, 0x0040, 0xa589, 0x2071, 0xa74a, 0x1078,
-	0xa5ca, 0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e,
-	0x0e7e, 0x017e, 0x2091, 0x8000, 0x2071, 0xa740, 0xd5a4, 0x0040,
-	0xa59c, 0x7034, 0x8000, 0x7036, 0xd5b4, 0x0040, 0xa5a2, 0x7030,
-	0x8000, 0x7032, 0xd5ac, 0x0040, 0xa5b8, 0x2500, 0xa084, 0x0007,
-	0xa08e, 0x0003, 0x0040, 0xa5b8, 0xa08e, 0x0004, 0x0040, 0xa5b8,
-	0xa08e, 0x0005, 0x0040, 0xa5b8, 0x2071, 0xa74a, 0x1078, 0xa5ca,
-	0x017f, 0x0e7f, 0x007f, 0x127f, 0x007c, 0x127e, 0x007e, 0x0e7e,
-	0x2091, 0x8000, 0x2071, 0xa742, 0x1078, 0xa5ca, 0x0e7f, 0x007f,
-	0x127f, 0x007c, 0x2e04, 0x8000, 0x2072, 0x00c8, 0xa5d3, 0x8e70,
-	0x2e04, 0x8000, 0x2072, 0x007c, 0x0e7e, 0x2071, 0xa740, 0x1078,
-	0xa5ca, 0x0e7f, 0x007c, 0x0e7e, 0x2071, 0xa744, 0x1078, 0xa5ca,
-	0x0e7f, 0x007c, 0x127e, 0x007e, 0x0e7e, 0x2091, 0x8000, 0x2071,
-	0xa740, 0x7044, 0x8000, 0x7046, 0x0e7f, 0x007f, 0x127f, 0x007c,
-	0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
-	0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
-	0x4811
-};
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2100tp_length01 = 0x9601;
-#else
-unsigned short risc_code_length01 = 0x9601;
-#endif
-
diff --git a/drivers/scsi/qla2xxx/ql2200.c b/drivers/scsi/qla2xxx/ql2200.c
deleted file mode 100644
index 0eef72d..0000000
--- a/drivers/scsi/qla2xxx/ql2200.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (C)  2003 Christoph Hellwig.
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "qla_def.h"
-
-static char qla_driver_name[] = "qla2200";
-
-extern unsigned char  fw2200tp_version[];
-extern unsigned char  fw2200tp_version_str[];
-extern unsigned short fw2200tp_addr01;
-extern unsigned short fw2200tp_code01[];
-extern unsigned short fw2200tp_length01;
-
-static struct qla_fw_info qla_fw_tbl[] = {
-	{
-		.addressing	= FW_INFO_ADDR_NORMAL,
-		.fwcode		= &fw2200tp_code01[0],
-		.fwlen		= &fw2200tp_length01,
-		.fwstart	= &fw2200tp_addr01,
-	},
-
-	{ FW_INFO_ADDR_NOMORE, },
-};
-
-static struct qla_board_info qla_board_tbl = {
-	.drv_name	= qla_driver_name,
-
-	.isp_name	= "ISP2200",
-	.fw_info	= qla_fw_tbl,
-};
-
-static struct pci_device_id qla2200_pci_tbl[] = {
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2200,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl,
-	},
-
-	{0, 0},
-};
-MODULE_DEVICE_TABLE(pci, qla2200_pci_tbl);
-
-static int __devinit
-qla2200_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	return qla2x00_probe_one(pdev,
-	    (struct qla_board_info *)id->driver_data);
-}
-
-static void __devexit
-qla2200_remove_one(struct pci_dev *pdev)
-{
-	qla2x00_remove_one(pdev);
-}
-
-static struct pci_driver qla2200_pci_driver = {
-	.name		= "qla2200",
-	.id_table	= qla2200_pci_tbl,
-	.probe		= qla2200_probe_one,
-	.remove		= __devexit_p(qla2200_remove_one),
-};
-
-static int __init
-qla2200_init(void)
-{
-	return pci_module_init(&qla2200_pci_driver);
-}
-
-static void __exit
-qla2200_exit(void)
-{
-	pci_unregister_driver(&qla2200_pci_driver);
-}
-
-module_init(qla2200_init);
-module_exit(qla2200_exit);
-
-MODULE_AUTHOR("QLogic Corporation");
-MODULE_DESCRIPTION("QLogic ISP22xx FC-SCSI Host Bus Adapter driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2200_fw.c b/drivers/scsi/qla2xxx/ql2200_fw.c
deleted file mode 100644
index ac07e18..0000000
--- a/drivers/scsi/qla2xxx/ql2200_fw.c
+++ /dev/null
@@ -1,5333 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-
-/*
- *	Firmware Version 2.02.08 (17:06 Mar 22, 2005)
- */
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2200tp_version = 2*1024+2;
-#else
-unsigned short risc_code_version = 2*1024+2;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned char fw2200tp_version_str[] = {2,2,8};
-#else
-unsigned char firmware_version[] = {2,2,8};
-#endif
-
-#ifdef UNIQUE_FW_NAME
-#define fw2200tp_VERSION_STRING "2.02.08"
-#else
-#define FW_VERSION_STRING "2.02.08"
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2200tp_addr01 = 0x1000 ;
-#else
-unsigned short risc_code_addr01 = 0x1000 ;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2200tp_code01[] = { 
-#else
-unsigned short risc_code01[] = { 
-#endif
-	0x0470, 0x0000, 0x0000, 0xa52b, 0x0000, 0x0002, 0x0002, 0x0008,
-	0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030,
-	0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
-	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3232, 0x3030, 0x2046, 0x6972,
-	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
-	0x322e, 0x3032, 0x2e30, 0x3820, 0x2020, 0x2020, 0x2400, 0x20c1,
-	0x0005, 0x2001, 0x017f, 0x2003, 0x0000, 0x20c9, 0xbbff, 0x2091,
-	0x2000, 0x2059, 0x0000, 0x2b78, 0x7823, 0x0004, 0x2089, 0x299f,
-	0x2051, 0xb600, 0x2a70, 0x2029, 0xee00, 0x2031, 0xffff, 0x2039,
-	0xede9, 0x2021, 0x0200, 0x0804, 0x146d, 0x20a1, 0xb52b, 0xa00e,
-	0x20a9, 0x08d5, 0x41a4, 0x3400, 0x7562, 0x7666, 0x775e, 0x746a,
-	0x746e, 0x20a1, 0xbe00, 0x7164, 0x810d, 0x810d, 0x810d, 0x810d,
-	0xa18c, 0x000f, 0x2001, 0x000b, 0xa112, 0xa00e, 0x21a8, 0x41a4,
-	0x3400, 0x8211, 0x1dd8, 0x7164, 0x3400, 0xa102, 0x0120, 0x0218,
-	0x20a8, 0xa00e, 0x41a4, 0x3800, 0xd08c, 0x01d8, 0x2009, 0xb600,
-	0x810d, 0x810d, 0x810d, 0x810d, 0xa18c, 0x000f, 0x2001, 0x0001,
-	0xa112, 0x20a1, 0x1000, 0xa00e, 0x21a8, 0x41a4, 0x8211, 0x1de0,
-	0x2009, 0xb600, 0x3400, 0xa102, 0x0120, 0x0218, 0x20a8, 0xa00e,
-	0x41a4, 0x080c, 0x1416, 0x080c, 0x1637, 0x080c, 0x17d4, 0x080c,
-	0x1fbe, 0x080c, 0x4c72, 0x080c, 0x8646, 0x080c, 0x15c0, 0x080c,
-	0x2ef9, 0x080c, 0x5dfc, 0x080c, 0x53b3, 0x080c, 0x6940, 0x080c,
-	0x2545, 0x080c, 0x6bd3, 0x080c, 0x642d, 0x080c, 0x23ff, 0x080c,
-	0x2513, 0x2091, 0x3009, 0x7823, 0x0000, 0x1004, 0x10c5, 0x7820,
-	0xa086, 0x0002, 0x1150, 0x7823, 0x4000, 0x0e04, 0x10bd, 0x781b,
-	0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2a70, 0x7003, 0x0000,
-	0x2a70, 0x7000, 0xa08e, 0x0003, 0x1158, 0x080c, 0x3f4f, 0x080c,
-	0x2f20, 0x080c, 0x5e4a, 0x080c, 0x5562, 0x080c, 0x696b, 0x0c80,
-	0x000b, 0x0c98, 0x10e4, 0x10e5, 0x1215, 0x10e2, 0x12e2, 0x1413,
-	0x1414, 0x1415, 0x080c, 0x151a, 0x0005, 0x0126, 0x00f6, 0x2091,
-	0x8000, 0x7000, 0xa086, 0x0001, 0x1904, 0x11f2, 0x080c, 0x158d,
-	0x080c, 0x5b41, 0x0150, 0x080c, 0x5b67, 0x15c0, 0x2079, 0x0100,
-	0x7828, 0xa085, 0x1800, 0x782a, 0x0488, 0x080c, 0x5a79, 0x7000,
-	0xa086, 0x0001, 0x1904, 0x11f2, 0x708c, 0xa086, 0x0028, 0x1904,
-	0x11f2, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100, 0x7827,
-	0xffff, 0x7a28, 0xa295, 0x1e2f, 0x7a2a, 0x2011, 0x5a14, 0x080c,
-	0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x2011, 0x5a56, 0x080c,
-	0x6a0e, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x2011, 0x8030, 0x2019,
-	0x0000, 0x708b, 0x0000, 0x080c, 0x1e05, 0x00e8, 0x080c, 0x44d6,
-	0x2079, 0x0100, 0x7844, 0xa005, 0x1904, 0x11f2, 0x2011, 0x4b23,
-	0x080c, 0x6a0e, 0x2011, 0x5a56, 0x080c, 0x6a0e, 0x080c, 0x1e05,
-	0x2001, 0xb88d, 0x2004, 0x780e, 0x7840, 0xa084, 0xfffb, 0x7842,
-	0x2011, 0x8010, 0x73cc, 0x080c, 0x3f13, 0x723c, 0xc284, 0x723e,
-	0x2001, 0xb60c, 0x200c, 0xc1ac, 0x2102, 0x080c, 0x7fbc, 0x2011,
-	0x0004, 0x080c, 0x9d1c, 0x080c, 0x52bf, 0x080c, 0x5b41, 0x0158,
-	0x080c, 0x4c4a, 0x0140, 0x708b, 0x0001, 0x70c7, 0x0000, 0x080c,
-	0x4673, 0x0804, 0x11f2, 0x080c, 0x537b, 0x0120, 0x7a0c, 0xc2b4,
-	0x7a0e, 0x0060, 0x7073, 0x0000, 0x080c, 0xa0c4, 0x70d4, 0xd09c,
-	0x1128, 0x70a0, 0xa005, 0x0110, 0x080c, 0x4c28, 0x70df, 0x0000,
-	0x70db, 0x0000, 0x72d4, 0x080c, 0x5b41, 0x1180, 0x2011, 0x0000,
-	0x0016, 0x080c, 0x2920, 0x2019, 0xb88f, 0x211a, 0x001e, 0x7053,
-	0xffff, 0x7057, 0x00ef, 0x7077, 0x0000, 0x0020, 0x2019, 0xb88f,
-	0x201b, 0x0000, 0x2079, 0xb652, 0x7804, 0xd0ac, 0x0108, 0xc295,
-	0x72d6, 0x080c, 0x5b41, 0x0118, 0xa296, 0x0004, 0x0548, 0x2011,
-	0x0001, 0x080c, 0x9d1c, 0x709b, 0x0000, 0x709f, 0xffff, 0x7003,
-	0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003,
-	0x782a, 0x00fe, 0x080c, 0x2aed, 0x2011, 0x0005, 0x080c, 0x80fc,
-	0x080c, 0x71e5, 0x080c, 0x5b41, 0x0148, 0x00c6, 0x2061, 0x0100,
-	0x0016, 0x080c, 0x2920, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x0420,
-	0x709b, 0x0000, 0x709f, 0xffff, 0x7003, 0x0002, 0x00f6, 0x2079,
-	0x0100, 0x7827, 0x0003, 0x7828, 0xa085, 0x0003, 0x782a, 0x00fe,
-	0x2011, 0x0005, 0x080c, 0x80fc, 0x080c, 0x71e5, 0x080c, 0x5b41,
-	0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x2920, 0x61e2,
-	0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x080c, 0x5b41,
-	0x1118, 0x20a9, 0x0100, 0x0010, 0x20a9, 0x0082, 0x080c, 0x5b41,
-	0x1118, 0x2009, 0x0000, 0x0010, 0x2009, 0x007e, 0x080c, 0x2dcc,
-	0x8108, 0x1f04, 0x1206, 0x00ce, 0x7073, 0x0000, 0x7074, 0xa084,
-	0x00ff, 0x7076, 0x70a3, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x7000, 0xa086, 0x0002, 0x1904, 0x12e0, 0x709c, 0xa086, 0xffff,
-	0x0130, 0x080c, 0x2aed, 0x080c, 0x71e5, 0x0804, 0x12e0, 0x70d4,
-	0xd0ac, 0x1110, 0xd09c, 0x0540, 0xd084, 0x0530, 0x0006, 0x0016,
-	0x2001, 0x0103, 0x2009, 0xb88d, 0x210c, 0x2102, 0x001e, 0x000e,
-	0xd08c, 0x01d0, 0x70d8, 0xa086, 0xffff, 0x0190, 0x080c, 0x2c4c,
-	0x080c, 0x71e5, 0x70d4, 0xd094, 0x1904, 0x12e0, 0x2011, 0x0001,
-	0x2019, 0x0000, 0x080c, 0x2c84, 0x080c, 0x71e5, 0x0804, 0x12e0,
-	0x70dc, 0xa005, 0x1904, 0x12e0, 0x7098, 0xa005, 0x1904, 0x12e0,
-	0x70d4, 0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x12e0, 0x080c, 0x537b,
-	0x1904, 0x12e0, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x01c8, 0x0156,
-	0x00c6, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b,
-	0x1118, 0x6000, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x126d,
-	0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x12e0,
-	0x0006, 0x0016, 0x2001, 0x0103, 0x2009, 0xb88d, 0x210c, 0x2102,
-	0x001e, 0x000e, 0x71a8, 0x81ff, 0x11b0, 0xa006, 0x2009, 0x0200,
-	0x20a9, 0x0002, 0x20a1, 0xb8df, 0x40a1, 0x2009, 0x0700, 0x20a9,
-	0x0002, 0x20a1, 0xb8cf, 0x40a1, 0x7070, 0x8007, 0x7174, 0x810f,
-	0x20a9, 0x0002, 0x40a1, 0x20a1, 0xb8d3, 0x2009, 0x0000, 0x080c,
-	0x1500, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x40a1, 0x7030,
-	0xc08c, 0x7032, 0x7003, 0x0003, 0x709f, 0xffff, 0x080c, 0x1586,
-	0xa006, 0x080c, 0x27f8, 0x080c, 0x3f85, 0x00f6, 0x2079, 0x0100,
-	0x080c, 0x5b67, 0x0150, 0x080c, 0x5b41, 0x7828, 0x0118, 0xa084,
-	0xe1ff, 0x0010, 0xa084, 0xffdf, 0x782a, 0x00fe, 0x2001, 0xb8e2,
-	0x2004, 0xa086, 0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0x80fc,
-	0x2011, 0x0000, 0x080c, 0x8106, 0x080c, 0x71e5, 0x080c, 0x72a2,
-	0x012e, 0x0005, 0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000,
-	0x2079, 0x0100, 0x2009, 0xb634, 0x2104, 0xa005, 0x1110, 0x080c,
-	0x294c, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x7940, 0xa18c, 0x0010,
-	0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827, 0x0040, 0xd19c, 0x0110,
-	0x7827, 0x0008, 0x0006, 0x0036, 0x0156, 0x7954, 0xd1ac, 0x1904,
-	0x1350, 0x080c, 0x5b53, 0x0158, 0x080c, 0x5b67, 0x1128, 0x2001,
-	0xb89e, 0x2003, 0x0000, 0x0070, 0x080c, 0x5b49, 0x0dc0, 0x2001,
-	0xb89e, 0x2003, 0xaaaa, 0x2001, 0xb89f, 0x2003, 0x0001, 0x080c,
-	0x5a79, 0x0058, 0x080c, 0x5b41, 0x0140, 0x2009, 0x00f8, 0x080c,
-	0x4c11, 0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820,
-	0xd09c, 0x1138, 0x080c, 0x5b41, 0x0138, 0x7824, 0xd0ac, 0x1904,
-	0x13fa, 0x1f04, 0x132f, 0x0070, 0x7824, 0x080c, 0x5b5d, 0x0118,
-	0xd0ac, 0x1904, 0x13fa, 0xa084, 0x1800, 0x0d98, 0x7003, 0x0001,
-	0x0804, 0x13fa, 0x2001, 0x0001, 0x080c, 0x27f8, 0x0804, 0x1409,
-	0x7850, 0xa084, 0x0180, 0x7852, 0x782f, 0x0020, 0x20a9, 0x0046,
-	0x1d04, 0x1358, 0x080c, 0x6ab6, 0x1f04, 0x1358, 0x7850, 0xa084,
-	0x0180, 0xa085, 0x0400, 0x7852, 0x782f, 0x0000, 0x080c, 0x5b53,
-	0x0158, 0x080c, 0x5b67, 0x1128, 0x2001, 0xb89e, 0x2003, 0x0000,
-	0x0070, 0x080c, 0x5b49, 0x0dc0, 0x2001, 0xb89e, 0x2003, 0xaaaa,
-	0x2001, 0xb89f, 0x2003, 0x0001, 0x080c, 0x5a79, 0x0020, 0x2009,
-	0x00f8, 0x080c, 0x4c11, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x1385,
-	0x7850, 0xa084, 0x0180, 0xa085, 0x1400, 0x7852, 0x080c, 0x5b41,
-	0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678, 0x2019,
-	0xea60, 0x7820, 0xd09c, 0x1558, 0x080c, 0x5b41, 0x05d8, 0x7824,
-	0xd0ac, 0x1904, 0x13fa, 0x080c, 0x5b67, 0x1508, 0x0046, 0x2021,
-	0x0190, 0x8421, 0x1df0, 0x004e, 0x8421, 0x11c8, 0x7827, 0x0048,
-	0x20a9, 0x01f4, 0x1d04, 0x13b2, 0x080c, 0x6ab6, 0x1f04, 0x13b2,
-	0x7824, 0xa084, 0x0068, 0x15c8, 0x2001, 0xb89e, 0x2003, 0xaaaa,
-	0x2001, 0xb89f, 0x2003, 0x0001, 0x7003, 0x0001, 0x0498, 0x1d04,
-	0x13cb, 0x080c, 0x6ab6, 0x8319, 0x1960, 0x2009, 0xb634, 0x2104,
-	0x8000, 0x200a, 0xa084, 0xfff0, 0x0120, 0x200b, 0x0000, 0x080c,
-	0x294c, 0x00d8, 0x080c, 0x5b53, 0x1140, 0xa4a2, 0x0064, 0x1128,
-	0x080c, 0x5b18, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0xe000,
-	0xe000, 0x7824, 0x080c, 0x5b5d, 0x0110, 0xd0ac, 0x1158, 0xa084,
-	0x1800, 0x09a8, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c,
-	0x27f8, 0x0048, 0x2001, 0xb634, 0x2003, 0x0000, 0x7827, 0x0048,
-	0x7828, 0xc09d, 0x782a, 0x7850, 0xa084, 0x0180, 0xa085, 0x0400,
-	0x7852, 0x015e, 0x003e, 0x000e, 0x080c, 0x155d, 0x012e, 0x00fe,
-	0x004e, 0x001e, 0x0005, 0x0005, 0x0005, 0x0005, 0x2a70, 0x2061,
-	0xb8c2, 0x2063, 0x0002, 0x6007, 0x0002, 0x600b, 0x0008, 0x600f,
-	0x0017, 0x2001, 0xb89e, 0x2003, 0x0000, 0x708b, 0x0000, 0x2009,
-	0x0100, 0x2104, 0xa082, 0x0002, 0x0218, 0x7053, 0xffff, 0x0010,
-	0x7053, 0x0000, 0x705b, 0xffff, 0x7073, 0x0000, 0x7077, 0x0000,
-	0x080c, 0xa0c4, 0x2061, 0xb88e, 0x6003, 0x0909, 0x6007, 0x0000,
-	0x600b, 0x8800, 0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x000f,
-	0x601b, 0x0000, 0x601f, 0x07d0, 0x2061, 0xb896, 0x6003, 0x8000,
-	0x6007, 0x0000, 0x600b, 0x0000, 0x600f, 0x0200, 0x6013, 0x00ff,
-	0x6017, 0x0000, 0x601b, 0x0001, 0x601f, 0x0000, 0x2061, 0xb8b9,
-	0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f, 0x2020,
-	0x2001, 0xb628, 0x2003, 0x0000, 0x0005, 0x04a0, 0x2011, 0x0000,
-	0x81ff, 0x0570, 0xa186, 0x0001, 0x1148, 0x2031, 0x8fff, 0x2039,
-	0xd601, 0x2021, 0x0100, 0x2029, 0xd600, 0x00e8, 0xa186, 0x0002,
-	0x1118, 0x2011, 0x0000, 0x00b8, 0xa186, 0x0005, 0x1118, 0x2011,
-	0x0001, 0x0088, 0xa186, 0x0009, 0x1118, 0x2011, 0x0002, 0x0058,
-	0xa186, 0x000a, 0x1118, 0x2011, 0x0002, 0x0028, 0xa186, 0x0055,
-	0x1110, 0x2011, 0x0003, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0,
-	0x0804, 0x104d, 0xa00e, 0x2011, 0x0003, 0x2019, 0x14a9, 0x0804,
-	0x14fa, 0x2019, 0xaaaa, 0x2061, 0xffff, 0x2c14, 0x2362, 0xe000,
-	0xe000, 0x2c04, 0xa306, 0x2262, 0x1110, 0xc1b5, 0xc1a5, 0x2011,
-	0x0000, 0x2019, 0x14bc, 0x04f0, 0x2019, 0xaaaa, 0x2061, 0xffff,
-	0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c, 0x2061, 0x7fff, 0xe000,
-	0xe000, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x0110, 0xc18d,
-	0x0008, 0xc185, 0x2011, 0x0002, 0x2019, 0x14d7, 0x0418, 0x2061,
-	0xffff, 0x2019, 0xaaaa, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c04,
-	0x2262, 0xa306, 0x1180, 0x2c14, 0x2362, 0xe000, 0xe000, 0x2c1c,
-	0x2061, 0x7fff, 0x2c04, 0x2061, 0xffff, 0x2262, 0xa306, 0x1110,
-	0xc195, 0x0008, 0xc19d, 0x2011, 0x0001, 0x2019, 0x14f8, 0x0010,
-	0x0804, 0x146e, 0x3800, 0xa084, 0xfffc, 0xa205, 0x20c0, 0x0837,
-	0x2011, 0x0000, 0x080c, 0x501b, 0x1178, 0x6004, 0xa0c4, 0x00ff,
-	0xa8c6, 0x0006, 0x0128, 0xa0c4, 0xff00, 0xa8c6, 0x0600, 0x1120,
-	0xa186, 0x0080, 0x0108, 0x8210, 0x8108, 0xa186, 0x0100, 0x1d50,
-	0x2208, 0x0005, 0x2091, 0x8000, 0x0e04, 0x151c, 0x0006, 0x0016,
-	0x2079, 0x0000, 0x7818, 0xd084, 0x1de8, 0x001e, 0x792e, 0x000e,
-	0x782a, 0x000e, 0x7826, 0x3900, 0x783a, 0x7823, 0x8002, 0x781b,
-	0x0001, 0x2091, 0x5000, 0x0126, 0x0156, 0x0146, 0x20a9, 0x0010,
-	0x20a1, 0xba0d, 0x2091, 0x2000, 0x40a1, 0x20a9, 0x0010, 0x2091,
-	0x2200, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2400, 0x40a1, 0x20a9,
-	0x0010, 0x2091, 0x2600, 0x40a1, 0x20a9, 0x0010, 0x2091, 0x2800,
-	0x40a1, 0x014e, 0x015e, 0x012e, 0x2079, 0xb600, 0x7803, 0x0005,
-	0x2091, 0x4080, 0x04c9, 0x0cf8, 0x0005, 0x0006, 0x080c, 0x15a8,
-	0x1518, 0x00f6, 0x2079, 0xb624, 0x2f04, 0x8000, 0x207a, 0xa082,
-	0x000f, 0x0258, 0xa006, 0x207a, 0x2079, 0xb626, 0x2f04, 0xa084,
-	0x0001, 0xa086, 0x0001, 0x207a, 0x0070, 0x2079, 0xb626, 0x2f7c,
-	0x8fff, 0x1128, 0x2001, 0x0c03, 0x2003, 0x0040, 0x0020, 0x2001,
-	0x0c03, 0x2003, 0x00c0, 0x00fe, 0x000e, 0x0005, 0x0409, 0x1120,
-	0x2001, 0x0c03, 0x2003, 0x0080, 0x0005, 0x00d1, 0x1120, 0x2001,
-	0x0c03, 0x2003, 0x0040, 0x0005, 0x0006, 0x0091, 0x1178, 0x2001,
-	0x0c03, 0x2003, 0x0040, 0x2009, 0x0fff, 0x00a1, 0x2001, 0x0c03,
-	0x2003, 0x0080, 0x2009, 0x0fff, 0x0069, 0x0c88, 0x000e, 0x0005,
-	0x00c6, 0x2061, 0x0c00, 0x2c04, 0xa084, 0x00ff, 0xa086, 0x00aa,
-	0x00ce, 0x0005, 0x0156, 0x0126, 0xa18c, 0x0fff, 0x21a8, 0x1d04,
-	0x15b7, 0x2091, 0x6000, 0x1f04, 0x15b7, 0x012e, 0x015e, 0x0005,
-	0x2071, 0xb600, 0x7160, 0x712e, 0x2021, 0x0001, 0xa190, 0x0030,
-	0xa298, 0x0030, 0x0240, 0x7064, 0xa302, 0x1228, 0x220a, 0x2208,
-	0x2310, 0x8420, 0x0ca8, 0x3800, 0xd08c, 0x0148, 0x7064, 0xa086,
-	0xb600, 0x0128, 0x7067, 0xb600, 0x2011, 0x1000, 0x0c48, 0x200b,
-	0x0000, 0x74b2, 0x74b6, 0x0005, 0x00e6, 0x0126, 0x2091, 0x8000,
-	0x2071, 0xb600, 0x70b4, 0xa0ea, 0x0010, 0x0268, 0x8001, 0x70b6,
-	0x702c, 0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000,
-	0x012e, 0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x2071, 0xb600,
-	0x0126, 0x2091, 0x8000, 0x70b4, 0x8001, 0x0260, 0x70b6, 0x702c,
-	0x2068, 0x2d04, 0x702e, 0x206b, 0x0000, 0x6807, 0x0000, 0x012e,
-	0x00ee, 0x0005, 0xa06e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000,
-	0x2071, 0xb600, 0x702c, 0x206a, 0x2d00, 0x702e, 0x70b4, 0x8000,
-	0x70b6, 0x012e, 0x00ee, 0x0005, 0x8dff, 0x0138, 0x6804, 0x6807,
-	0x0000, 0x0006, 0x0c49, 0x00de, 0x0cb8, 0x0005, 0x00e6, 0x2071,
-	0xb600, 0x70b4, 0xa08a, 0x0010, 0xa00d, 0x00ee, 0x0005, 0x00e6,
-	0x2071, 0xb913, 0x7007, 0x0000, 0x701b, 0x0000, 0x701f, 0x0000,
-	0x2071, 0x0000, 0x7010, 0xa085, 0x8004, 0x7012, 0x00ee, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x00e6, 0x2270, 0x700b, 0x0000, 0x2071,
-	0xb913, 0x7018, 0xa088, 0xb91c, 0x220a, 0x8000, 0xa084, 0x0007,
-	0x701a, 0x7004, 0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0089,
-	0x00fe, 0x00ee, 0x012e, 0x0005, 0x00e6, 0x2071, 0xb913, 0x7004,
-	0xa005, 0x1128, 0x00f6, 0x2079, 0x0010, 0x0019, 0x00fe, 0x00ee,
-	0x0005, 0x7000, 0x0002, 0x1677, 0x16db, 0x16f8, 0x16f8, 0x7018,
-	0x711c, 0xa106, 0x1118, 0x7007, 0x0000, 0x0005, 0x00d6, 0xa180,
-	0xb91c, 0x2004, 0x700a, 0x2068, 0x8108, 0xa18c, 0x0007, 0x711e,
-	0x7803, 0x0026, 0x6824, 0x7832, 0x6828, 0x7836, 0x682c, 0x783a,
-	0x6830, 0x783e, 0x6810, 0x700e, 0x680c, 0x7016, 0x6804, 0x00de,
-	0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007, 0x0002,
-	0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182,
-	0x0040, 0x1210, 0x2110, 0xa006, 0x700e, 0x7212, 0x8203, 0x7822,
-	0x7803, 0x0020, 0x7803, 0x0041, 0x002e, 0x001e, 0x0005, 0x0016,
-	0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x2098, 0x20a1, 0x0014,
-	0x7803, 0x0026, 0x710c, 0x2011, 0x0040, 0xa182, 0x0040, 0x1210,
-	0x2110, 0xa006, 0x700e, 0x22a8, 0x53a6, 0x8203, 0x7822, 0x7803,
-	0x0020, 0x3300, 0x7016, 0x7803, 0x0001, 0x015e, 0x014e, 0x013e,
-	0x002e, 0x001e, 0x0005, 0x0136, 0x0146, 0x0156, 0x2099, 0xb6fa,
-	0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
-	0x2091, 0x8000, 0x7803, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084,
-	0x7002, 0x700b, 0xb6f5, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
-	0x0136, 0x0146, 0x0156, 0x2001, 0xb729, 0x209c, 0x20a1, 0x0014,
-	0x7803, 0x0026, 0x2001, 0xb72a, 0x20ac, 0x53a6, 0x2099, 0xb72b,
-	0x20a1, 0x0018, 0x20a9, 0x0008, 0x53a3, 0x7803, 0x0020, 0x0126,
-	0x2091, 0x8000, 0x7803, 0x0001, 0x7007, 0x0004, 0x7000, 0xc08c,
-	0x7002, 0x700b, 0xb726, 0x012e, 0x015e, 0x014e, 0x013e, 0x0005,
-	0x0016, 0x00e6, 0x2071, 0xb913, 0x00f6, 0x2079, 0x0010, 0x7904,
-	0x7803, 0x0002, 0xd1fc, 0x0120, 0xa18c, 0x0700, 0x7004, 0x0023,
-	0x00fe, 0x00ee, 0x001e, 0x0005, 0x1671, 0x173b, 0x1769, 0x1793,
-	0x17c3, 0x173a, 0x0cf8, 0xa18c, 0x0700, 0x1528, 0x0136, 0x0146,
-	0x0156, 0x7014, 0x20a0, 0x2099, 0x0014, 0x7803, 0x0040, 0x7010,
-	0x20a8, 0x53a5, 0x3400, 0x7016, 0x015e, 0x014e, 0x013e, 0x700c,
-	0xa005, 0x0570, 0x7830, 0x7832, 0x7834, 0x7836, 0x080c, 0x16a2,
-	0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0100, 0x7007, 0x0000,
-	0x080c, 0x1671, 0x0005, 0x7008, 0xa080, 0x0002, 0x2003, 0x0200,
-	0x0ca8, 0xa18c, 0x0700, 0x1150, 0x700c, 0xa005, 0x0188, 0x7830,
-	0x7832, 0x7834, 0x7836, 0x080c, 0x16b7, 0x0005, 0x7008, 0xa080,
-	0x0002, 0x2003, 0x0200, 0x7007, 0x0000, 0x080c, 0x1671, 0x0005,
-	0x00d6, 0x7008, 0x2068, 0x7830, 0x6826, 0x7834, 0x682a, 0x7838,
-	0x682e, 0x783c, 0x6832, 0x680b, 0x0100, 0x00de, 0x7007, 0x0000,
-	0x080c, 0x1671, 0x0005, 0xa18c, 0x0700, 0x1540, 0x0136, 0x0146,
-	0x0156, 0x2001, 0xb6f8, 0x2004, 0xa080, 0x000d, 0x20a0, 0x2099,
-	0x0014, 0x7803, 0x0040, 0x20a9, 0x0020, 0x53a5, 0x2001, 0xb6fa,
-	0x2004, 0xd0bc, 0x0148, 0x2001, 0xb703, 0x2004, 0xa080, 0x000d,
-	0x20a0, 0x20a9, 0x0020, 0x53a5, 0x015e, 0x014e, 0x013e, 0x7007,
-	0x0000, 0x080c, 0x5ee1, 0x080c, 0x1671, 0x0005, 0x2011, 0x8003,
-	0x080c, 0x3f13, 0x0cf8, 0xa18c, 0x0700, 0x1148, 0x2001, 0xb728,
-	0x2003, 0x0100, 0x7007, 0x0000, 0x080c, 0x1671, 0x0005, 0x2011,
-	0x8004, 0x080c, 0x3f13, 0x0cf8, 0x0126, 0x2091, 0x2200, 0x2079,
-	0x0030, 0x2071, 0xb924, 0x7003, 0x0000, 0x700f, 0xb930, 0x7013,
-	0xb930, 0x780f, 0x00f6, 0x7803, 0x0004, 0x012e, 0x0005, 0x6934,
-	0xa184, 0x0007, 0x0002, 0x17f3, 0x1831, 0x17f3, 0x17f3, 0x17f3,
-	0x1819, 0x1800, 0x17f7, 0xa085, 0x0001, 0x0804, 0x184b, 0x684c,
-	0xd0bc, 0x0dc8, 0x6860, 0x682e, 0x685c, 0x682a, 0x6858, 0x04c8,
-	0xa18c, 0x00ff, 0xa186, 0x001e, 0x1d70, 0x684c, 0xd0bc, 0x0d58,
-	0x6860, 0x682e, 0x685c, 0x682a, 0x6804, 0x681a, 0xa080, 0x000d,
-	0x2004, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, 0x6832, 0x6858,
-	0x0440, 0xa18c, 0x00ff, 0xa186, 0x0015, 0x19a8, 0x684c, 0xd0ac,
-	0x0990, 0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f,
-	0xa080, 0x2308, 0x2005, 0x6832, 0xa006, 0x682e, 0x682a, 0x6858,
-	0x0080, 0x684c, 0xd0ac, 0x0904, 0x17f3, 0xa006, 0x682e, 0x682a,
-	0x6858, 0xa18c, 0x000f, 0xa188, 0x2308, 0x210d, 0x6932, 0x2d08,
-	0x691a, 0x6826, 0x684c, 0xc0dd, 0x684e, 0xa006, 0x680a, 0x697c,
-	0x6912, 0x6980, 0x6916, 0x0005, 0x684c, 0xd0ac, 0x090c, 0x151a,
-	0x6833, 0x2305, 0x2d08, 0x691a, 0x6858, 0x8001, 0x6826, 0x684c,
-	0xc0dd, 0x684e, 0xa006, 0x680a, 0x682e, 0x682a, 0x697c, 0x6912,
-	0x6980, 0x6916, 0x0005, 0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001,
-	0x020a, 0x2004, 0x82ff, 0x01e8, 0xa280, 0x0004, 0x00d6, 0x206c,
-	0x684c, 0xd0dc, 0x1190, 0xa280, 0x0007, 0x2004, 0xa086, 0x000a,
-	0x1110, 0x0891, 0x0010, 0x080c, 0x17e7, 0x0138, 0x00de, 0xa280,
-	0x0000, 0x2003, 0x0002, 0xa016, 0x0020, 0x6808, 0x8000, 0x680a,
-	0x00de, 0x0126, 0x0046, 0x0036, 0x0026, 0x2091, 0x2200, 0x002e,
-	0x003e, 0x004e, 0x7000, 0xa005, 0x01d0, 0x710c, 0x220a, 0x8108,
-	0x230a, 0x8108, 0x240a, 0x8108, 0xa182, 0xb94b, 0x0210, 0x2009,
-	0xb930, 0x710e, 0x7010, 0xa102, 0xa082, 0x0009, 0x0118, 0xa080,
-	0x001b, 0x1118, 0x2009, 0x0138, 0x200a, 0x012e, 0x0005, 0x7206,
-	0x2001, 0x18ad, 0x0006, 0x2260, 0x0804, 0x19da, 0x0126, 0x0026,
-	0x0036, 0x00c6, 0x0006, 0x2091, 0x2200, 0x000e, 0x004e, 0x003e,
-	0x002e, 0x00d6, 0x00c6, 0x2460, 0x6110, 0x2168, 0x6a62, 0x6b5e,
-	0xa005, 0x0904, 0x190f, 0x6808, 0xa005, 0x0904, 0x1946, 0x7000,
-	0xa005, 0x1108, 0x0488, 0x700c, 0x7110, 0xa106, 0x1904, 0x194e,
-	0x7004, 0xa406, 0x1548, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0168,
-	0x0046, 0x080c, 0x1b22, 0x004e, 0x2460, 0x6010, 0xa080, 0x0002,
-	0x2004, 0xa005, 0x0904, 0x1946, 0x0c10, 0x2001, 0x0207, 0x2004,
-	0xd09c, 0x1d48, 0x7804, 0xa084, 0x6000, 0x0120, 0xa086, 0x6000,
-	0x0108, 0x0c08, 0x7818, 0x6812, 0x781c, 0x6816, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x7004, 0x2060, 0x6100, 0xa18e, 0x0004, 0x1904,
-	0x194e, 0x2009, 0x0048, 0x080c, 0x86d3, 0x0804, 0x194e, 0x6808,
-	0xa005, 0x05a0, 0x7000, 0xa005, 0x0588, 0x700c, 0x7110, 0xa106,
-	0x1118, 0x7004, 0xa406, 0x1550, 0x2001, 0x0005, 0x2004, 0xd08c,
-	0x0160, 0x0046, 0x080c, 0x1b22, 0x004e, 0x2460, 0x6010, 0xa080,
-	0x0002, 0x2004, 0xa005, 0x01d0, 0x0c28, 0x2001, 0x0207, 0x2004,
-	0xd09c, 0x1d50, 0x2001, 0x0005, 0x2004, 0xd08c, 0x1d50, 0x7804,
-	0xa084, 0x6000, 0x0118, 0xa086, 0x6000, 0x19f0, 0x7818, 0x6812,
-	0x781c, 0x6816, 0x7803, 0x0004, 0x7003, 0x0000, 0x6100, 0xa18e,
-	0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0x86d3, 0x00ce, 0x00de,
-	0x012e, 0x0005, 0x00f6, 0x00e6, 0x0026, 0x0036, 0x0046, 0x0056,
-	0x2071, 0xb924, 0x7000, 0xa086, 0x0000, 0x0904, 0x19b8, 0x7004,
-	0xac06, 0x1904, 0x19aa, 0x2079, 0x0030, 0x7000, 0xa086, 0x0003,
-	0x0904, 0x19aa, 0x7804, 0xd0fc, 0x15c8, 0x20e1, 0x6000, 0x2011,
-	0x0032, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209, 0x2004, 0xa106,
-	0x1d88, 0x8211, 0x1db0, 0x7804, 0xd0fc, 0x1540, 0x080c, 0x1e8a,
-	0x0026, 0x0056, 0x7803, 0x0004, 0x7804, 0xd0ac, 0x1de8, 0x7803,
-	0x0002, 0x7803, 0x0009, 0x7003, 0x0003, 0x7007, 0x0000, 0x005e,
-	0x002e, 0x2001, 0x015d, 0x2003, 0x0000, 0x080c, 0x5b41, 0x1138,
-	0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, 0x006e, 0x0058, 0x2001,
-	0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0020, 0x080c, 0x1b22,
-	0x0804, 0x195a, 0x0156, 0x20a9, 0x0009, 0x2009, 0xb930, 0x2104,
-	0xac06, 0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x19af, 0x015e,
-	0x005e, 0x004e, 0x003e, 0x002e, 0x00ee, 0x00fe, 0x0005, 0x700c,
-	0x7110, 0xa106, 0x0904, 0x1a4e, 0x2104, 0x7006, 0x2060, 0x8108,
-	0x211c, 0x8108, 0x2124, 0x8108, 0xa182, 0xb94b, 0x0210, 0x2009,
-	0xb930, 0x7112, 0x700c, 0xa106, 0x1128, 0x080c, 0x2920, 0x2001,
-	0x0138, 0x2102, 0x8cff, 0x0598, 0x6010, 0x2068, 0x2d58, 0x6828,
-	0xa406, 0x1590, 0x682c, 0xa306, 0x1578, 0x7004, 0x2060, 0x6020,
-	0xc0d4, 0x6022, 0x684c, 0xd0f4, 0x0128, 0x6817, 0xffff, 0x6813,
-	0xffff, 0x00e8, 0x6850, 0xd0f4, 0x1130, 0x7803, 0x0004, 0x6810,
-	0x781a, 0x6814, 0x781e, 0x6824, 0x2050, 0x6818, 0x2060, 0x6830,
-	0x2040, 0x6034, 0xa0cc, 0x000f, 0x2009, 0x0011, 0x080c, 0x1a51,
-	0x0120, 0x2009, 0x0001, 0x080c, 0x1a51, 0x2d58, 0x0005, 0x080c,
-	0x1df9, 0x0904, 0x19bf, 0x0cd0, 0x6020, 0xd0f4, 0x11e0, 0xd0d4,
-	0x01b8, 0x6038, 0xa402, 0x6034, 0xa303, 0x0108, 0x1288, 0x643a,
-	0x6336, 0x6c2a, 0x6b2e, 0x0046, 0x0036, 0x2400, 0x6c7c, 0xa402,
-	0x6812, 0x2300, 0x6b80, 0xa303, 0x6816, 0x003e, 0x004e, 0x0018,
-	0x080c, 0xa056, 0x09e0, 0x601c, 0xa08e, 0x0008, 0x0904, 0x19e5,
-	0xa08e, 0x000a, 0x0904, 0x19e5, 0x2001, 0xb674, 0x2004, 0xd0b4,
-	0x1140, 0x6018, 0x2004, 0xd0bc, 0x1120, 0x6817, 0x7fff, 0x6813,
-	0xffff, 0x080c, 0x2328, 0x1918, 0x0804, 0x19e5, 0x7003, 0x0000,
-	0x0005, 0x8aff, 0x0904, 0x1afc, 0xa03e, 0x2730, 0xc9fc, 0x6850,
-	0xd0fc, 0x11b8, 0xd0f4, 0x1588, 0x00d6, 0x2805, 0xac68, 0x2900,
-	0x0002, 0x1aba, 0x1a93, 0x1a93, 0x1aba, 0x1aba, 0x1ab2, 0x1aba,
-	0x1a93, 0x1aba, 0x1a9b, 0x1a9b, 0x1aba, 0x1aba, 0x1aba, 0x1aaa,
-	0x1a9b, 0x7803, 0x0004, 0xc0fc, 0x6852, 0x6b6c, 0x6a70, 0x6d1c,
-	0x6c20, 0x00d6, 0xd99c, 0x0140, 0x2805, 0xac68, 0x6f08, 0x6e0c,
-	0x080c, 0x23ed, 0x0120, 0x04d0, 0x080c, 0x23ed, 0x15b0, 0x6850,
-	0xc0fd, 0x6852, 0x00de, 0xa006, 0x0005, 0xc0f4, 0x6852, 0x6b6c,
-	0x6a70, 0x00d6, 0x04c0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x080c,
-	0x23ed, 0x0d80, 0x0410, 0x6b10, 0x6a14, 0x6d00, 0x6c04, 0x6f08,
-	0x6e0c, 0x080c, 0x23ed, 0x0d30, 0x00c8, 0x6d00, 0x6c04, 0x6f08,
-	0x6e0c, 0x00a0, 0x00de, 0x00d6, 0x6834, 0xa084, 0x00ff, 0xa086,
-	0x001e, 0x1140, 0x00de, 0x080c, 0x22ca, 0x1904, 0x1a51, 0xa00e,
-	0x0804, 0x1afc, 0x00de, 0x080c, 0x151a, 0xc9fd, 0x7b22, 0x7a26,
-	0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7316, 0x721a, 0x751e, 0x7422,
-	0x7726, 0x762a, 0x7902, 0x7100, 0x8108, 0x7102, 0x00de, 0x6828,
-	0xa300, 0x682a, 0x682c, 0xa201, 0x682e, 0x8109, 0x2d08, 0x1500,
-	0xd9fc, 0x0160, 0xc9fc, 0x080c, 0x22ca, 0x01e8, 0x2805, 0xac68,
-	0x6800, 0xa506, 0x11c0, 0x6804, 0xa406, 0x00a8, 0xc9fc, 0x080c,
-	0x22ca, 0x0188, 0x2805, 0xac68, 0x6800, 0xa506, 0x1160, 0x6804,
-	0xa406, 0x1148, 0x6808, 0xa706, 0x1130, 0x680c, 0xa606, 0x0018,
-	0xc9fc, 0x080c, 0x22ca, 0x2168, 0x0005, 0x080c, 0x151a, 0x080c,
-	0x1f71, 0x7004, 0x2060, 0x00d6, 0x6010, 0x2068, 0x7003, 0x0000,
-	0x080c, 0x1e1a, 0x080c, 0x9d16, 0x0170, 0x6808, 0x8001, 0x680a,
-	0x697c, 0x6912, 0x6980, 0x6916, 0x682b, 0xffff, 0x682f, 0xffff,
-	0x6850, 0xc0bd, 0x6852, 0x00de, 0x080c, 0x99e6, 0x0804, 0x1d47,
-	0x080c, 0x151a, 0x0126, 0x2091, 0x2200, 0x0006, 0x0016, 0x2b68,
-	0x6818, 0x2060, 0x7904, 0x7803, 0x0002, 0xa184, 0x0700, 0x1978,
-	0xa184, 0x0003, 0xa086, 0x0003, 0x0d58, 0x7000, 0x0002, 0x1b3f,
-	0x1b45, 0x1c56, 0x1d22, 0x1d36, 0x1b3f, 0x1b3f, 0x1b3f, 0x7804,
-	0xd09c, 0x1904, 0x1d47, 0x080c, 0x151a, 0x8001, 0x7002, 0xd1bc,
-	0x11a0, 0xd19c, 0x1904, 0x1bda, 0xd1dc, 0x1178, 0x8aff, 0x0904,
-	0x1bda, 0x2009, 0x0001, 0x080c, 0x1a51, 0x0904, 0x1d47, 0x2009,
-	0x0001, 0x080c, 0x1a51, 0x0804, 0x1d47, 0x7803, 0x0004, 0x7003,
-	0x0000, 0xd1bc, 0x1904, 0x1bba, 0x0026, 0x0036, 0x7c20, 0x7d24,
-	0x7e30, 0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201,
-	0x2004, 0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009,
-	0x7003, 0x0004, 0x0010, 0x080c, 0x1d4b, 0x6b28, 0x6a2c, 0x2400,
-	0x686e, 0xa31a, 0x2500, 0x6872, 0xa213, 0x6b2a, 0x6a2e, 0x00c6,
-	0x7004, 0x2060, 0x6020, 0xd0f4, 0x1110, 0x633a, 0x6236, 0x00ce,
-	0x003e, 0x002e, 0x6e1e, 0x6f22, 0x2500, 0xa405, 0x0128, 0x080c,
-	0x22e0, 0x6850, 0xc0fd, 0x6852, 0x2a00, 0x6826, 0x2c00, 0x681a,
-	0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x1148, 0x684c, 0xd0e4,
-	0x0130, 0x7004, 0x2060, 0x2009, 0x0048, 0x080c, 0x86d3, 0x7000,
-	0xa086, 0x0004, 0x0904, 0x1d47, 0x7003, 0x0000, 0x080c, 0x19bf,
-	0x0804, 0x1d47, 0x0056, 0x7d0c, 0xd5bc, 0x1110, 0x080c, 0xb4c3,
-	0x005e, 0x080c, 0x1e1a, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5377,
-	0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f,
-	0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e,
-	0x0804, 0x1d47, 0x7004, 0x00c6, 0x2060, 0x6020, 0x00ce, 0xd0f4,
-	0x0120, 0x6808, 0x8001, 0x680a, 0x04c0, 0x7818, 0x6812, 0x7a1c,
-	0x6a16, 0xd19c, 0x0160, 0xa205, 0x0150, 0x7004, 0xa080, 0x0007,
-	0x2004, 0xa084, 0xfffd, 0xa086, 0x0008, 0x1904, 0x1b5d, 0x684c,
-	0xc0f5, 0x684e, 0x7814, 0xa005, 0x1520, 0x7003, 0x0000, 0x6808,
-	0x8001, 0x680a, 0x01a0, 0x7004, 0x2060, 0x601c, 0xa086, 0x000a,
-	0x11a0, 0x0156, 0x20a9, 0x0009, 0x2009, 0xb930, 0x2104, 0xac06,
-	0x1108, 0x200a, 0xa188, 0x0003, 0x1f04, 0x1c0e, 0x015e, 0x7004,
-	0x2060, 0x2009, 0x0048, 0x080c, 0x86d3, 0x080c, 0x19bf, 0x0804,
-	0x1d47, 0x7818, 0x6812, 0x781c, 0x6816, 0x7814, 0x7908, 0xa18c,
-	0x0fff, 0xa192, 0x0841, 0x1a04, 0x1aff, 0xa188, 0x0007, 0x8114,
-	0x8214, 0x8214, 0xa10a, 0x8104, 0x8004, 0x8004, 0xa20a, 0x810b,
-	0x810b, 0x810b, 0x080c, 0x1eb5, 0x7803, 0x0004, 0x780f, 0xffff,
-	0x7803, 0x0001, 0x7804, 0xd0fc, 0x0de8, 0x7803, 0x0002, 0x7803,
-	0x0004, 0x780f, 0x00f6, 0x7004, 0x7007, 0x0000, 0x2060, 0x2009,
-	0x0048, 0x080c, 0x86d3, 0x080c, 0x1f0b, 0x0838, 0x8001, 0x7002,
-	0xd194, 0x01b0, 0x7804, 0xd0fc, 0x1904, 0x1cf2, 0xd09c, 0x0138,
-	0x7804, 0xd0fc, 0x1904, 0x1cf2, 0xd09c, 0x1904, 0x1cf6, 0x8aff,
-	0x0904, 0x1d47, 0x2009, 0x0001, 0x080c, 0x1a51, 0x0804, 0x1d47,
-	0xa184, 0x0888, 0x1148, 0x8aff, 0x0904, 0x1d47, 0x2009, 0x0001,
-	0x080c, 0x1a51, 0x0804, 0x1d47, 0x7818, 0x6812, 0x7a1c, 0x6a16,
-	0xa205, 0x0904, 0x1bf7, 0x7803, 0x0004, 0x7003, 0x0000, 0xd1bc,
-	0x1904, 0x1cd4, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0029, 0x1118,
-	0xd19c, 0x1904, 0x1bf7, 0x0026, 0x0036, 0x7c20, 0x7d24, 0x7e30,
-	0x7f34, 0x7818, 0x6812, 0x781c, 0x6816, 0x2001, 0x0201, 0x2004,
-	0xa005, 0x0140, 0x7808, 0xd0ec, 0x1128, 0x7803, 0x0009, 0x7003,
-	0x0004, 0x0020, 0x0016, 0x080c, 0x1d4b, 0x001e, 0x6b28, 0x6a2c,
-	0x080c, 0x22e0, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128,
-	0x6808, 0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814,
-	0xa213, 0x00de, 0xd194, 0x0904, 0x1b7f, 0x2a00, 0x6826, 0x2c00,
-	0x681a, 0x2800, 0x6832, 0x6808, 0x8001, 0x680a, 0x6b2a, 0x6a2e,
-	0x003e, 0x002e, 0x0804, 0x1c1d, 0x0056, 0x7d0c, 0x080c, 0xb4c3,
-	0x005e, 0x080c, 0x1e1a, 0x00f6, 0x7004, 0x2078, 0x080c, 0x5377,
-	0x0118, 0x7820, 0xc0f5, 0x7822, 0x00fe, 0x682b, 0xffff, 0x682f,
-	0xffff, 0x6808, 0x8001, 0x680a, 0x697c, 0x791a, 0x6980, 0x791e,
-	0x0804, 0x1d47, 0x7804, 0xd09c, 0x0904, 0x1b2a, 0x7c20, 0x7824,
-	0xa405, 0x1904, 0x1b2a, 0x7818, 0x6812, 0x7c1c, 0x6c16, 0xa405,
-	0x1120, 0x7803, 0x0002, 0x0804, 0x1bf7, 0x751c, 0x7420, 0x7724,
-	0x7628, 0x7014, 0xa528, 0x7018, 0xa421, 0xa7b9, 0x0000, 0xa6b1,
-	0x0000, 0x7830, 0xa506, 0x1150, 0x7834, 0xa406, 0x1138, 0x7838,
-	0xa706, 0x1120, 0x783c, 0xa606, 0x0904, 0x1b2a, 0x7803, 0x0002,
-	0x0804, 0x1c83, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0xa00d,
-	0x0150, 0x6808, 0x8001, 0x680a, 0x1130, 0x7004, 0x2060, 0x2009,
-	0x0048, 0x080c, 0x86d3, 0x080c, 0x19bf, 0x0088, 0x7803, 0x0004,
-	0x7003, 0x0000, 0x7004, 0x2060, 0x6010, 0xa005, 0x0da0, 0x2068,
-	0x6808, 0x8000, 0x680a, 0x6c28, 0x6b2c, 0x080c, 0x19da, 0x001e,
-	0x000e, 0x012e, 0x0005, 0x700c, 0x7110, 0xa106, 0x0904, 0x1ded,
-	0x7004, 0x0016, 0x210c, 0xa106, 0x001e, 0x0904, 0x1ded, 0x00d6,
-	0x00c6, 0x216c, 0x2d00, 0xa005, 0x0904, 0x1deb, 0x681c, 0xa086,
-	0x0008, 0x0904, 0x1deb, 0x6820, 0xd0d4, 0x1904, 0x1deb, 0x6810,
-	0x2068, 0x6850, 0xd0fc, 0x05a8, 0x8108, 0x2104, 0x6b2c, 0xa306,
-	0x1904, 0x1deb, 0x8108, 0x2104, 0x6a28, 0xa206, 0x1904, 0x1deb,
-	0x6850, 0xc0fc, 0xc0f5, 0x6852, 0x686c, 0x7822, 0x7016, 0x6870,
-	0x7826, 0x701a, 0x681c, 0x7832, 0x701e, 0x6820, 0x7836, 0x7022,
-	0x6818, 0x2060, 0x6034, 0xd09c, 0x0168, 0x6830, 0x2005, 0x00d6,
-	0xac68, 0x6808, 0x783a, 0x7026, 0x680c, 0x783e, 0x702a, 0x00de,
-	0x0804, 0x1de5, 0xa006, 0x783a, 0x783e, 0x7026, 0x702a, 0x0804,
-	0x1de5, 0x8108, 0x2104, 0xa005, 0x1904, 0x1deb, 0x6b2c, 0xa306,
-	0x1904, 0x1deb, 0x8108, 0x2104, 0xa005, 0x15e8, 0x6a28, 0xa206,
-	0x15d0, 0x6850, 0xc0f5, 0x6852, 0x6830, 0x2005, 0x6918, 0xa160,
-	0xa180, 0x000d, 0x2004, 0xd09c, 0x11a0, 0x6008, 0x7822, 0x7016,
-	0x686e, 0x600c, 0x7826, 0x701a, 0x6872, 0x6000, 0x7832, 0x701e,
-	0x6004, 0x7836, 0x7022, 0xa006, 0x783a, 0x783e, 0x7026, 0x702a,
-	0x00a0, 0x6010, 0x7822, 0x7016, 0x686e, 0x6014, 0x7826, 0x701a,
-	0x6872, 0x6000, 0x7832, 0x701e, 0x6004, 0x7836, 0x7022, 0x6008,
-	0x783a, 0x7026, 0x600c, 0x783e, 0x702a, 0x6810, 0x781a, 0x6814,
-	0x781e, 0x7803, 0x0011, 0x00ce, 0x00de, 0x0005, 0x2011, 0x0201,
-	0x2009, 0x003c, 0x2204, 0xa005, 0x1118, 0x8109, 0x1dd8, 0x0005,
-	0x0005, 0x0ca1, 0x0118, 0x780c, 0xd0a4, 0x0120, 0x00d9, 0xa085,
-	0x0001, 0x0010, 0x080c, 0x1f0b, 0x0005, 0x0126, 0x2091, 0x2200,
-	0x7000, 0xa086, 0x0003, 0x1160, 0x700c, 0x7110, 0xa106, 0x0140,
-	0x080c, 0x2991, 0x20e1, 0x9028, 0x700f, 0xb930, 0x7013, 0xb930,
-	0x012e, 0x0005, 0x00c6, 0x080c, 0x5b41, 0x11b8, 0x2001, 0x0160,
-	0x2003, 0x0000, 0x2001, 0x0138, 0x2003, 0x0000, 0x2011, 0x00c8,
-	0xe000, 0xe000, 0x8211, 0x1de0, 0x04b1, 0x0066, 0x2031, 0x0000,
-	0x080c, 0x5bc3, 0x006e, 0x00ce, 0x0005, 0x080c, 0x1e8a, 0x080c,
-	0x2991, 0x20e1, 0x9028, 0x700c, 0x7110, 0xa106, 0x01c0, 0x2104,
-	0xa005, 0x0130, 0x2060, 0x6010, 0x2060, 0x6008, 0x8001, 0x600a,
-	0xa188, 0x0003, 0xa182, 0xb94b, 0x0210, 0x2009, 0xb930, 0x7112,
-	0x700c, 0xa106, 0x1d40, 0x080c, 0x2920, 0x2110, 0x0c20, 0x2001,
-	0x015d, 0x2003, 0x0000, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138,
-	0x2202, 0x00ce, 0x0005, 0x080c, 0x2991, 0x20e1, 0x9028, 0x2001,
-	0x015d, 0x2003, 0x0000, 0x00e6, 0x00c6, 0x0016, 0x2071, 0xb924,
-	0x700c, 0x7110, 0xa106, 0x0190, 0x2104, 0xa005, 0x0130, 0x2060,
-	0x6010, 0x2060, 0x6008, 0x8001, 0x600a, 0xa188, 0x0003, 0xa182,
-	0xb94b, 0x0210, 0x2009, 0xb930, 0x7112, 0x0c50, 0x001e, 0x00ce,
-	0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001,
-	0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x5b41, 0x1148, 0x2021,
-	0x0002, 0x1d04, 0x1e99, 0x2091, 0x6000, 0x8421, 0x1dd0, 0x0005,
-	0x2021, 0xb015, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001,
-	0x0109, 0x201c, 0xa39c, 0x0048, 0x1138, 0x2001, 0x0111, 0x201c,
-	0x83ff, 0x1110, 0x8421, 0x1d70, 0x0005, 0x00e6, 0x2071, 0x0200,
-	0x7808, 0xa084, 0xf000, 0xa10d, 0x0869, 0x2001, 0x0105, 0x2004,
-	0xa084, 0x0003, 0x1130, 0x2001, 0xb94b, 0x2004, 0xa086, 0x0000,
-	0x0548, 0xa026, 0x2019, 0xf000, 0x8319, 0x1148, 0x2001, 0x012b,
-	0x2003, 0x95f5, 0x2001, 0x0129, 0x2003, 0x95f5, 0x00d8, 0x2001,
-	0x0105, 0x2004, 0xa084, 0x0003, 0x1130, 0x2001, 0xb94b, 0x2004,
-	0xa086, 0x0000, 0x0178, 0x2001, 0x0132, 0x2004, 0xa436, 0x0110,
-	0x2020, 0x0c00, 0x2001, 0x0021, 0x2004, 0xd0fc, 0x09e8, 0x080c,
-	0x216d, 0x08c0, 0x20e1, 0x7000, 0x7324, 0x7420, 0x7028, 0x7028,
-	0x7426, 0x7037, 0x0001, 0x810f, 0x712e, 0x702f, 0x0100, 0x7037,
-	0x0008, 0x7326, 0x7422, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138,
-	0x2202, 0x00ee, 0x0005, 0x0026, 0x2001, 0x015d, 0x2003, 0x0000,
-	0x7908, 0xa18c, 0x0fff, 0xa182, 0x0ffd, 0x0210, 0x2009, 0x0000,
-	0xa190, 0x0007, 0xa294, 0x1ff8, 0x8214, 0x8214, 0x8214, 0x2001,
-	0x020a, 0x82ff, 0x0140, 0x20e1, 0x6000, 0x200c, 0x200c, 0x200c,
-	0x200c, 0x8211, 0x1dd0, 0x20e1, 0x7000, 0x200c, 0x200c, 0x7003,
-	0x0000, 0x20e1, 0x6000, 0x2001, 0x0208, 0x200c, 0x2001, 0x0209,
-	0x2004, 0xa106, 0x0158, 0x080c, 0x1dee, 0x0130, 0x7908, 0xd1ec,
-	0x1128, 0x790c, 0xd1a4, 0x0960, 0x080c, 0x1e1a, 0xa006, 0x002e,
-	0x0005, 0x00f6, 0x00e6, 0x0016, 0x0026, 0x2071, 0xb924, 0x2079,
-	0x0030, 0x2011, 0x0050, 0x7000, 0xa086, 0x0000, 0x01a8, 0x8211,
-	0x0188, 0x2001, 0x0005, 0x2004, 0xd08c, 0x0dc8, 0x7904, 0xa18c,
-	0x0780, 0x0016, 0x080c, 0x1b22, 0x001e, 0x81ff, 0x1118, 0x2011,
-	0x0050, 0x0c48, 0xa085, 0x0001, 0x002e, 0x001e, 0x00ee, 0x00fe,
-	0x0005, 0x7803, 0x0004, 0x2009, 0x0064, 0x7804, 0xd0ac, 0x0904,
-	0x1fbd, 0x8109, 0x1dd0, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0003,
-	0x0a0c, 0x151a, 0x080c, 0x2274, 0x00e6, 0x00f6, 0x2071, 0xb913,
-	0x2079, 0x0010, 0x7004, 0xa086, 0x0000, 0x0538, 0x7800, 0x0006,
-	0x7820, 0x0006, 0x7830, 0x0006, 0x7834, 0x0006, 0x7838, 0x0006,
-	0x783c, 0x0006, 0x7803, 0x0004, 0xe000, 0xe000, 0x2079, 0x0030,
-	0x7804, 0xd0ac, 0x190c, 0x151a, 0x2079, 0x0010, 0x000e, 0x783e,
-	0x000e, 0x783a, 0x000e, 0x7836, 0x000e, 0x7832, 0x000e, 0x7822,
-	0x000e, 0x7802, 0x00fe, 0x00ee, 0x0030, 0x00fe, 0x00ee, 0x7804,
-	0xd0ac, 0x190c, 0x151a, 0x080c, 0x72a2, 0x0005, 0x00e6, 0x2071,
-	0xb94b, 0x7003, 0x0000, 0x00ee, 0x0005, 0x00d6, 0xa280, 0x0004,
-	0x206c, 0x694c, 0xd1dc, 0x1904, 0x203b, 0x6934, 0xa184, 0x0007,
-	0x0002, 0x1fd9, 0x2026, 0x1fd9, 0x1fd9, 0x1fd9, 0x200d, 0x1fec,
-	0x1fdb, 0x080c, 0x151a, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6860,
-	0x682e, 0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880,
-	0x680e, 0x6958, 0x0804, 0x202e, 0x6834, 0xa084, 0x00ff, 0xa086,
-	0x001e, 0x1d38, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6860, 0x682e,
-	0x6816, 0x685c, 0x682a, 0x6812, 0x687c, 0x680a, 0x6880, 0x680e,
-	0x6804, 0x681a, 0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080,
-	0x2308, 0x2005, 0x6832, 0x6958, 0x0450, 0xa18c, 0x00ff, 0xa186,
-	0x0015, 0x1548, 0x684c, 0xd0b4, 0x0904, 0x212a, 0x6804, 0x681a,
-	0xa080, 0x000d, 0x2004, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005,
-	0x6832, 0x6958, 0xa006, 0x682e, 0x682a, 0x0088, 0x684c, 0xd0b4,
-	0x0904, 0x1afd, 0x6958, 0xa006, 0x682e, 0x682a, 0x2d00, 0x681a,
-	0x6834, 0xa084, 0x000f, 0xa080, 0x2308, 0x2005, 0x6832, 0x6926,
-	0x684c, 0xc0dd, 0x684e, 0x00de, 0x0005, 0x00f6, 0x2079, 0x0020,
-	0x7804, 0xd0fc, 0x190c, 0x216d, 0x00e6, 0x00d6, 0x2071, 0xb94b,
-	0x7000, 0xa005, 0x1904, 0x20aa, 0x00c6, 0x7206, 0xa280, 0x0004,
-	0x205c, 0x7004, 0x2068, 0x7803, 0x0004, 0x6818, 0x00d6, 0x2068,
-	0x686c, 0x7812, 0x6890, 0x00f6, 0x20e1, 0x9040, 0x2079, 0x0200,
-	0x781a, 0x2079, 0x0100, 0x8004, 0x78d6, 0x00fe, 0x00de, 0x2b68,
-	0x6824, 0x2050, 0x6818, 0x2060, 0x6830, 0x2040, 0x6034, 0xa0cc,
-	0x000f, 0x6908, 0x791a, 0x7116, 0x680c, 0x781e, 0x701a, 0xa006,
-	0x700e, 0x7012, 0x7004, 0x692c, 0x6814, 0xa106, 0x1120, 0x6928,
-	0x6810, 0xa106, 0x0190, 0x2001, 0xb674, 0x2004, 0xd0cc, 0x0110,
-	0x00ce, 0x0400, 0x0036, 0x0046, 0x6b14, 0x6c10, 0x080c, 0x2328,
-	0x004e, 0x003e, 0x0110, 0x00ce, 0x00a8, 0x8aff, 0x1120, 0x00ce,
-	0xa085, 0x0001, 0x0078, 0x0126, 0x2091, 0x8000, 0x2079, 0x0020,
-	0x2009, 0x0001, 0x0059, 0x0118, 0x2009, 0x0001, 0x0039, 0x012e,
-	0x00ce, 0xa006, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x0076, 0x0066,
-	0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x2123, 0x700c,
-	0x7214, 0xa23a, 0x7010, 0x7218, 0xa203, 0x0a04, 0x2122, 0xa705,
-	0x0904, 0x2122, 0xa03e, 0x2730, 0x6850, 0xd0fc, 0x11a8, 0x00d6,
-	0x2805, 0xac68, 0x2900, 0x0002, 0x2105, 0x20ea, 0x20ea, 0x2105,
-	0x2105, 0x20fe, 0x2105, 0x20ea, 0x2105, 0x20ef, 0x20ef, 0x2105,
-	0x2105, 0x2105, 0x20f6, 0x20ef, 0xc0fc, 0x6852, 0x6b6c, 0x6a70,
-	0x6d1c, 0x6c20, 0xd99c, 0x0528, 0x00d6, 0x2805, 0xac68, 0x6f08,
-	0x6e0c, 0x00f0, 0x6b08, 0x6a0c, 0x6d00, 0x6c04, 0x00c8, 0x6b10,
-	0x6a14, 0x6d00, 0x6c04, 0x6f08, 0x6e0c, 0x0090, 0x00de, 0x00d6,
-	0x6834, 0xa084, 0x00ff, 0xa086, 0x001e, 0x1138, 0x00de, 0x080c,
-	0x22ca, 0x1904, 0x20b4, 0xa00e, 0x00f0, 0x00de, 0x080c, 0x151a,
-	0x00de, 0x7b22, 0x7a26, 0x7d32, 0x7c36, 0x7f3a, 0x7e3e, 0x7902,
-	0x7000, 0x8000, 0x7002, 0x6828, 0xa300, 0x682a, 0x682c, 0xa201,
-	0x682e, 0x700c, 0xa300, 0x700e, 0x7010, 0xa201, 0x7012, 0x080c,
-	0x22ca, 0x0008, 0xa006, 0x002e, 0x003e, 0x004e, 0x005e, 0x006e,
-	0x007e, 0x0005, 0x080c, 0x151a, 0x0026, 0x2001, 0x0105, 0x2003,
-	0x0010, 0x20e1, 0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004,
-	0x2060, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0118, 0x6850,
-	0xc0bd, 0x6852, 0x601c, 0xa086, 0x0006, 0x1180, 0x2061, 0x0100,
-	0x62c8, 0x2001, 0x00fa, 0x8001, 0x1df0, 0x60c8, 0xa206, 0x1dc0,
-	0x60c4, 0x686a, 0x60c8, 0x6866, 0x7004, 0x2060, 0x00de, 0x00c6,
-	0x080c, 0x99e6, 0x00ce, 0x2001, 0xb8f0, 0x2004, 0xac06, 0x1150,
-	0x20e1, 0x9040, 0x080c, 0x82e4, 0x2011, 0x0000, 0x080c, 0x8106,
-	0x080c, 0x72a2, 0x002e, 0x0804, 0x2227, 0x0126, 0x2091, 0x2400,
-	0x0006, 0x0016, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x2079, 0x0020,
-	0x2071, 0xb94b, 0x2b68, 0x6818, 0x2060, 0x7904, 0x7803, 0x0002,
-	0xa184, 0x0700, 0x1904, 0x212c, 0x7000, 0x0002, 0x2227, 0x218a,
-	0x21fa, 0x2225, 0x8001, 0x7002, 0xd19c, 0x1170, 0x8aff, 0x05d0,
-	0x2009, 0x0001, 0x080c, 0x20ae, 0x0904, 0x2227, 0x2009, 0x0001,
-	0x080c, 0x20ae, 0x0804, 0x2227, 0x7803, 0x0004, 0xd194, 0x0148,
-	0x6850, 0xc0fc, 0x6852, 0x8aff, 0x11d8, 0x684c, 0xc0f5, 0x684e,
-	0x00b8, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x7820, 0x686e, 0xa31a,
-	0x7824, 0x6872, 0xa213, 0x7830, 0x681e, 0x7834, 0x6822, 0x6b2a,
-	0x6a2e, 0x003e, 0x002e, 0x080c, 0x22e0, 0x6850, 0xc0fd, 0x6852,
-	0x2a00, 0x6826, 0x2c00, 0x681a, 0x2800, 0x6832, 0x7003, 0x0000,
-	0x0804, 0x2227, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006,
-	0x2079, 0x0100, 0x7a14, 0xa284, 0x0184, 0xa085, 0x0012, 0x7816,
-	0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x151a, 0x7820, 0xd0bc,
-	0x1dd0, 0x003e, 0x79c8, 0x000e, 0xa102, 0x001e, 0x0006, 0x0016,
-	0x79c4, 0x000e, 0xa103, 0x78c6, 0x000e, 0x78ca, 0xa284, 0x0184,
-	0xa085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x7803, 0x0008, 0x7003,
-	0x0000, 0x0468, 0x8001, 0x7002, 0xd194, 0x0168, 0x7804, 0xd0fc,
-	0x1904, 0x217d, 0xd19c, 0x11f8, 0x8aff, 0x0508, 0x2009, 0x0001,
-	0x080c, 0x20ae, 0x00e0, 0x0026, 0x0036, 0x6b28, 0x6a2c, 0x080c,
-	0x22e0, 0x00d6, 0x2805, 0xac68, 0x6034, 0xd09c, 0x1128, 0x6808,
-	0xa31a, 0x680c, 0xa213, 0x0020, 0x6810, 0xa31a, 0x6814, 0xa213,
-	0x00de, 0x0804, 0x21ad, 0x0804, 0x21a9, 0x080c, 0x151a, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x001e, 0x000e, 0x012e, 0x0005, 0x00f6,
-	0x00e6, 0x2071, 0xb94b, 0x7000, 0xa086, 0x0000, 0x05d0, 0x2079,
-	0x0020, 0x0016, 0x2009, 0x0207, 0x210c, 0xd194, 0x0198, 0x2009,
-	0x020c, 0x210c, 0xa184, 0x0003, 0x0168, 0x080c, 0xb50c, 0x2001,
-	0x0133, 0x2004, 0xa005, 0x090c, 0x151a, 0x20e1, 0x9040, 0x2001,
-	0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c,
-	0xa106, 0x1110, 0x20e1, 0x9040, 0x7804, 0xd0fc, 0x09d8, 0x080c,
-	0x216d, 0x7000, 0xa086, 0x0000, 0x19a8, 0x001e, 0x7803, 0x0004,
-	0x7804, 0xd0ac, 0x1de8, 0x20e1, 0x9040, 0x7803, 0x0002, 0x7003,
-	0x0000, 0x00ee, 0x00fe, 0x0005, 0x0026, 0x00c6, 0x00d6, 0x00e6,
-	0x00f6, 0x2071, 0xb94b, 0x2079, 0x0020, 0x7000, 0xa086, 0x0000,
-	0x0540, 0x7004, 0x2060, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0158,
-	0x6850, 0xc0b5, 0x6852, 0x680c, 0x7a1c, 0xa206, 0x1120, 0x6808,
-	0x7a18, 0xa206, 0x01e0, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1,
-	0x9040, 0x7803, 0x0004, 0x7003, 0x0000, 0x7004, 0x2060, 0x080c,
-	0x99e6, 0x20e1, 0x9040, 0x080c, 0x82e4, 0x2011, 0x0000, 0x080c,
-	0x8106, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x0005, 0x6810,
-	0x6a14, 0xa205, 0x1d00, 0x684c, 0xc0dc, 0x684e, 0x2c10, 0x080c,
-	0x1fc5, 0x2001, 0x0105, 0x2003, 0x0010, 0x20e1, 0x9040, 0x7803,
-	0x0004, 0x7003, 0x0000, 0x2069, 0xb8e1, 0x6833, 0x0000, 0x683f,
-	0x0000, 0x08f8, 0x8840, 0x2805, 0xa005, 0x1170, 0x6004, 0xa005,
-	0x0168, 0x681a, 0x2060, 0x6034, 0xa084, 0x000f, 0xa080, 0x2308,
-	0x2045, 0x88ff, 0x090c, 0x151a, 0x8a51, 0x0005, 0x2050, 0x0005,
-	0x8a50, 0x8841, 0x2805, 0xa005, 0x1190, 0x2c00, 0xad06, 0x0120,
-	0x6000, 0xa005, 0x1108, 0x2d00, 0x2060, 0x681a, 0x6034, 0xa084,
-	0x000f, 0xa080, 0x2318, 0x2045, 0x88ff, 0x090c, 0x151a, 0x0005,
-	0x0000, 0x0011, 0x0015, 0x0019, 0x001d, 0x0021, 0x0025, 0x0029,
-	0x0000, 0x000f, 0x0015, 0x001b, 0x0021, 0x0027, 0x0000, 0x0000,
-	0x0000, 0x22fd, 0x22f9, 0x0000, 0x0000, 0x2307, 0x0000, 0x22fd,
-	0x0000, 0x2304, 0x2301, 0x0000, 0x0000, 0x0000, 0x2307, 0x2304,
-	0x0000, 0x22ff, 0x22ff, 0x0000, 0x0000, 0x2307, 0x0000, 0x22ff,
-	0x0000, 0x2305, 0x2305, 0x0000, 0x0000, 0x0000, 0x2307, 0x2305,
-	0x00a6, 0x0096, 0x0086, 0x6b2e, 0x6c2a, 0x6858, 0xa055, 0x0904,
-	0x23b9, 0x2d60, 0x6034, 0xa0cc, 0x000f, 0xa9c0, 0x2308, 0xa986,
-	0x0007, 0x0130, 0xa986, 0x000e, 0x0118, 0xa986, 0x000f, 0x1120,
-	0x605c, 0xa422, 0x6060, 0xa31b, 0x2805, 0xa045, 0x1140, 0x0310,
-	0x0804, 0x23b9, 0x6004, 0xa065, 0x0904, 0x23b9, 0x0c18, 0x2805,
-	0xa005, 0x01a8, 0xac68, 0xd99c, 0x1128, 0x6808, 0xa422, 0x680c,
-	0xa31b, 0x0020, 0x6810, 0xa422, 0x6814, 0xa31b, 0x0620, 0x2300,
-	0xa405, 0x0150, 0x8a51, 0x0904, 0x23b9, 0x8840, 0x0c40, 0x6004,
-	0xa065, 0x0904, 0x23b9, 0x0830, 0x8a51, 0x0904, 0x23b9, 0x8840,
-	0x2805, 0xa005, 0x1158, 0x6004, 0xa065, 0x0904, 0x23b9, 0x6034,
-	0xa0cc, 0x000f, 0xa9c0, 0x2308, 0x2805, 0x2040, 0x2b68, 0x6850,
-	0xc0fc, 0x6852, 0x0458, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000,
-	0x00d6, 0x2b68, 0x6c6e, 0x6b72, 0x00de, 0xd99c, 0x1168, 0x6908,
-	0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x0a0c, 0x151a, 0x6800,
-	0xa420, 0x6804, 0xa319, 0x0060, 0x6910, 0x2400, 0xa122, 0x6914,
-	0x2300, 0xa11b, 0x0a0c, 0x151a, 0x6800, 0xa420, 0x6804, 0xa319,
-	0x2b68, 0x6c1e, 0x6b22, 0x6850, 0xc0fd, 0x6852, 0x2c00, 0x681a,
-	0x2800, 0x6832, 0x2a00, 0x6826, 0x000e, 0x000e, 0x000e, 0xa006,
-	0x0028, 0x008e, 0x009e, 0x00ae, 0xa085, 0x0001, 0x0005, 0x2001,
-	0x0005, 0x2004, 0xa084, 0x0007, 0x0002, 0x23cd, 0x23ce, 0x23d1,
-	0x23d4, 0x23d9, 0x23dc, 0x23e1, 0x23e6, 0x0005, 0x080c, 0x216d,
-	0x0005, 0x080c, 0x1b22, 0x0005, 0x080c, 0x1b22, 0x080c, 0x216d,
-	0x0005, 0x080c, 0x1720, 0x0005, 0x080c, 0x216d, 0x080c, 0x1720,
-	0x0005, 0x080c, 0x1b22, 0x080c, 0x1720, 0x0005, 0x080c, 0x1b22,
-	0x080c, 0x216d, 0x080c, 0x1720, 0x0005, 0x0006, 0x7000, 0xa086,
-	0x0001, 0x1158, 0x701c, 0xa506, 0x1140, 0x7020, 0xa406, 0x1128,
-	0x7024, 0xa706, 0x1110, 0x7028, 0xa606, 0x000e, 0x0005, 0x0126,
-	0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0xbc80, 0x2069, 0xb600,
-	0x080c, 0x24f5, 0x080c, 0x24e5, 0x2009, 0x0004, 0x7912, 0x7817,
-	0x0004, 0x080c, 0x282d, 0x781b, 0x0002, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x20a9, 0x0080, 0x782f, 0x0000, 0x1f04, 0x241b, 0x20e1,
-	0x9080, 0x783b, 0x001f, 0x20e1, 0x8700, 0x012e, 0x0005, 0x0126,
-	0x2091, 0x2600, 0x781c, 0xd0a4, 0x190c, 0x24e2, 0xa084, 0x0007,
-	0x0002, 0x244b, 0x2439, 0x243c, 0x243f, 0x2444, 0x2446, 0x2448,
-	0x244a, 0x080c, 0x6436, 0x0078, 0x080c, 0x6475, 0x0060, 0x080c,
-	0x6436, 0x080c, 0x6475, 0x0038, 0x0041, 0x0028, 0x0031, 0x0018,
-	0x0021, 0x0008, 0x0011, 0x012e, 0x0005, 0x0006, 0x0016, 0x0026,
-	0x080c, 0xb50c, 0x7930, 0xa184, 0x0003, 0x01b0, 0x2001, 0xb8f0,
-	0x2004, 0xa005, 0x0170, 0x2001, 0x0133, 0x2004, 0xa005, 0x090c,
-	0x151a, 0x00c6, 0x2001, 0xb8f0, 0x2064, 0x080c, 0x99e6, 0x00ce,
-	0x04b8, 0x20e1, 0x9040, 0x04a0, 0xa184, 0x0030, 0x01e0, 0x6a00,
-	0xa286, 0x0003, 0x1108, 0x00a0, 0x080c, 0x5b41, 0x1178, 0x2001,
-	0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085,
-	0x0001, 0x080c, 0x5b85, 0x080c, 0x5a79, 0x0010, 0x080c, 0x4b7b,
-	0x080c, 0x24e5, 0x00a8, 0xa184, 0x00c0, 0x0168, 0x00e6, 0x0036,
-	0x0046, 0x0056, 0x2071, 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e,
-	0x003e, 0x00ee, 0x0028, 0xa184, 0x0300, 0x0110, 0x20e1, 0x9020,
-	0x7932, 0x002e, 0x001e, 0x000e, 0x0005, 0x0016, 0x00e6, 0x00f6,
-	0x2071, 0xb600, 0x7128, 0x2001, 0xb891, 0x2102, 0x2001, 0xb899,
-	0x2102, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182,
-	0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218,
-	0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005,
-	0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182,
-	0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x2079,
-	0x0200, 0x7912, 0x7817, 0x0004, 0x080c, 0x282d, 0x00fe, 0x00ee,
-	0x001e, 0x0005, 0x7938, 0x080c, 0x151a, 0x00e6, 0x0026, 0x2071,
-	0x0200, 0x20e1, 0x1000, 0x7220, 0x7028, 0x7020, 0xa206, 0x0de0,
-	0x20e1, 0x9010, 0x002e, 0x00ee, 0x0005, 0x20e1, 0xa000, 0x7837,
-	0x0001, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f, 0x0000, 0x782f,
-	0x0000, 0x7837, 0x0005, 0x20a9, 0x0210, 0x7830, 0xd0bc, 0x1110,
-	0x1f04, 0x2505, 0x7837, 0x0001, 0x7837, 0x0000, 0xe000, 0xe000,
-	0x20e1, 0xa000, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100,
-	0x2071, 0xb600, 0x6024, 0x6026, 0x6053, 0x0030, 0x080c, 0x286c,
-	0x6050, 0xa084, 0xfe7f, 0x6052, 0x2009, 0x00ef, 0x6132, 0x6136,
-	0x080c, 0x287c, 0x60e7, 0x0000, 0x61ea, 0x60e3, 0x0008, 0x604b,
-	0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080, 0x602f, 0x0000, 0x6007,
-	0x0e9f, 0x601b, 0x001e, 0x600f, 0x00ff, 0x2001, 0xb88d, 0x2003,
-	0x00ff, 0x602b, 0x002f, 0x012e, 0x0005, 0x2001, 0xb632, 0x2003,
-	0x0000, 0x2001, 0xb631, 0x2003, 0x0001, 0x0005, 0x0126, 0x2091,
-	0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0xa184, 0x1e2c, 0x1118,
-	0xa184, 0x0007, 0x002a, 0xa195, 0x0004, 0xa284, 0x0007, 0x0002,
-	0x2582, 0x2568, 0x256b, 0x256e, 0x2573, 0x2575, 0x2579, 0x257d,
-	0x080c, 0x6be6, 0x00b8, 0x080c, 0x6cc1, 0x00a0, 0x080c, 0x6cc1,
-	0x080c, 0x6be6, 0x0078, 0x0099, 0x0068, 0x080c, 0x6be6, 0x0079,
-	0x0048, 0x080c, 0x6cc1, 0x0059, 0x0028, 0x080c, 0x6cc1, 0x080c,
-	0x6be6, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005, 0x6124,
-	0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x279b, 0x080c, 0x5b41,
-	0x0578, 0x7000, 0xa086, 0x0003, 0x0198, 0x6024, 0xa084, 0x1800,
-	0x0178, 0x080c, 0x5b67, 0x0118, 0x080c, 0x5b53, 0x1148, 0x6027,
-	0x0020, 0x6043, 0x0000, 0x2001, 0xb89e, 0x2003, 0xaaaa, 0x0458,
-	0x080c, 0x5b67, 0x15d0, 0x6024, 0xa084, 0x1800, 0x1108, 0x04a8,
-	0x2001, 0xb89e, 0x2003, 0xaaaa, 0x2001, 0xb89f, 0x2003, 0x0001,
-	0x2001, 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, 0x0804, 0x279b,
-	0xd1ac, 0x1518, 0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1188, 0xd0d4,
-	0x11a0, 0xd0cc, 0x0130, 0x708c, 0xa086, 0x0028, 0x1110, 0x080c,
-	0x5cd0, 0x0804, 0x279b, 0x2001, 0xb89f, 0x2003, 0x0000, 0x0048,
-	0x2001, 0xb89f, 0x2003, 0x0002, 0x0020, 0x080c, 0x5c43, 0x0804,
-	0x279b, 0x080c, 0x5d75, 0x0804, 0x279b, 0xd1ac, 0x0904, 0x26e3,
-	0x080c, 0x5b41, 0x11d8, 0x6027, 0x0020, 0x0006, 0x0026, 0x0036,
-	0x080c, 0x5b5d, 0x1170, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001,
-	0xb600, 0x2003, 0x0001, 0x080c, 0x5a79, 0x003e, 0x002e, 0x000e,
-	0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x5b18, 0x0016, 0x0046,
-	0x00c6, 0x644c, 0xa486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a,
-	0x6043, 0x0090, 0x6043, 0x0010, 0x74ce, 0xa48c, 0xff00, 0x7034,
-	0xd084, 0x0178, 0xa186, 0xf800, 0x1160, 0x703c, 0xd084, 0x1148,
-	0xc085, 0x703e, 0x0036, 0x2418, 0x2011, 0x8016, 0x080c, 0x3f13,
-	0x003e, 0xa196, 0xff00, 0x05b8, 0x7054, 0xa084, 0x00ff, 0x810f,
-	0xa116, 0x0588, 0x7130, 0xd184, 0x1570, 0x2011, 0xb653, 0x2214,
-	0xd2ec, 0x0138, 0xc18d, 0x7132, 0x2011, 0xb653, 0x2214, 0xd2ac,
-	0x1510, 0x6240, 0xa294, 0x0010, 0x0130, 0x6248, 0xa294, 0xff00,
-	0xa296, 0xff00, 0x01c0, 0x7030, 0xd08c, 0x0904, 0x26b0, 0x7034,
-	0xd08c, 0x1140, 0x2001, 0xb60c, 0x200c, 0xd1ac, 0x1904, 0x26b0,
-	0xc1ad, 0x2102, 0x0036, 0x73cc, 0x2011, 0x8013, 0x080c, 0x3f13,
-	0x003e, 0x0804, 0x26b0, 0x7034, 0xd08c, 0x1140, 0x2001, 0xb60c,
-	0x200c, 0xd1ac, 0x1904, 0x26b0, 0xc1ad, 0x2102, 0x0036, 0x73cc,
-	0x2011, 0x8013, 0x080c, 0x3f13, 0x003e, 0x7130, 0xc185, 0x7132,
-	0x2011, 0xb653, 0x220c, 0xd1a4, 0x01d0, 0x0016, 0x2009, 0x0001,
-	0x2011, 0x0100, 0x080c, 0x6b8c, 0x2019, 0x000e, 0x080c, 0xb121,
-	0xa484, 0x00ff, 0xa080, 0x2df9, 0x200d, 0xa18c, 0xff00, 0x810f,
-	0x8127, 0xa006, 0x2009, 0x000e, 0x080c, 0xb1a4, 0x001e, 0xd1ac,
-	0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004, 0x080c, 0x2ca4,
-	0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0x080c,
-	0x501b, 0x1110, 0x080c, 0x4c7e, 0x8108, 0x1f04, 0x26a7, 0x015e,
-	0x00ce, 0x004e, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002,
-	0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c,
-	0x806b, 0x003e, 0x60e3, 0x0000, 0x001e, 0x2001, 0xb600, 0x2014,
-	0xa296, 0x0004, 0x1128, 0xd19c, 0x11b0, 0x6228, 0xc29d, 0x622a,
-	0x2003, 0x0001, 0x2001, 0xb623, 0x2003, 0x0000, 0x6027, 0x0020,
-	0x080c, 0x5b67, 0x1140, 0x0016, 0x2009, 0x07d0, 0x2011, 0x5a56,
-	0x080c, 0x6a94, 0x001e, 0xd194, 0x0904, 0x279b, 0x0016, 0x6220,
-	0xd2b4, 0x0904, 0x274c, 0x080c, 0x6a82, 0x080c, 0x7df3, 0x6027,
-	0x0004, 0x00f6, 0x2019, 0xb8ea, 0x2304, 0xa07d, 0x0570, 0x7804,
-	0xa086, 0x0032, 0x1550, 0x00d6, 0x00c6, 0x00e6, 0x2069, 0x0140,
-	0x618c, 0x6288, 0x7818, 0x608e, 0x7808, 0x608a, 0x6043, 0x0002,
-	0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x6803, 0x1000,
-	0x6803, 0x0000, 0x618e, 0x628a, 0x080c, 0x7102, 0x080c, 0x71e5,
-	0x7810, 0x2070, 0x7037, 0x0103, 0x2f60, 0x080c, 0x86a4, 0x00ee,
-	0x00ce, 0x00de, 0x00fe, 0x001e, 0x0005, 0x00fe, 0x00d6, 0x2069,
-	0x0140, 0x6804, 0xa084, 0x4000, 0x0120, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x00de, 0x00c6, 0x2061, 0xb8e1, 0x6028, 0xa09a, 0x00c8,
-	0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0x7de6, 0x0804, 0x279a,
-	0x2019, 0xb8ea, 0x2304, 0xa065, 0x0120, 0x2009, 0x0027, 0x080c,
-	0x86d3, 0x00ce, 0x0804, 0x279a, 0xd2bc, 0x0904, 0x279a, 0x080c,
-	0x6a8f, 0x6014, 0xa084, 0x0184, 0xa085, 0x0010, 0x6016, 0x6027,
-	0x0004, 0x00d6, 0x2069, 0x0140, 0x6804, 0xa084, 0x4000, 0x0120,
-	0x6803, 0x1000, 0x6803, 0x0000, 0x00de, 0x00c6, 0x2061, 0xb8e1,
-	0x6044, 0xa09a, 0x00c8, 0x12f0, 0x8000, 0x6046, 0x603c, 0x00ce,
-	0xa005, 0x0540, 0x2009, 0x07d0, 0x080c, 0x6a87, 0xa080, 0x0007,
-	0x2004, 0xa086, 0x0006, 0x1138, 0x6114, 0xa18c, 0x0184, 0xa18d,
-	0x0012, 0x6116, 0x00b8, 0x6114, 0xa18c, 0x0184, 0xa18d, 0x0016,
-	0x6116, 0x0080, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, 0x003e,
-	0x2019, 0xb8f0, 0x2304, 0xa065, 0x0120, 0x2009, 0x004f, 0x080c,
-	0x86d3, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x27f4, 0x7034, 0xd0ac,
-	0x1560, 0x0016, 0x0156, 0x6027, 0x0008, 0x602f, 0x0020, 0x20a9,
-	0x0006, 0x1d04, 0x27a9, 0x2091, 0x6000, 0x1f04, 0x27a9, 0x602f,
-	0x0000, 0x6150, 0xa185, 0x1400, 0x6052, 0x20a9, 0x0366, 0x1d04,
-	0x27b7, 0x2091, 0x6000, 0x6020, 0xd09c, 0x1130, 0x015e, 0x6152,
-	0x001e, 0x6027, 0x0008, 0x0480, 0x080c, 0x293c, 0x1f04, 0x27b7,
-	0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x0016, 0x6028, 0xc09c,
-	0x602a, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c,
-	0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b,
-	0x003e, 0x60e3, 0x0000, 0x080c, 0xb4eb, 0x080c, 0xb506, 0xa085,
-	0x0001, 0x080c, 0x5b85, 0x2001, 0xb600, 0x2003, 0x0004, 0x6027,
-	0x0008, 0x080c, 0x12e2, 0x001e, 0xa18c, 0xffd0, 0x6126, 0x0005,
-	0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000,
-	0x2071, 0xb600, 0x71c4, 0x70c6, 0xa116, 0x0500, 0x81ff, 0x0128,
-	0x2011, 0x8011, 0x080c, 0x3f13, 0x00c8, 0x2011, 0x8012, 0x080c,
-	0x3f13, 0x2001, 0xb672, 0x2004, 0xd0fc, 0x1180, 0x0036, 0x00c6,
-	0x080c, 0x28c7, 0x080c, 0x7fbc, 0x2061, 0x0100, 0x2019, 0x0028,
-	0x2009, 0x0000, 0x080c, 0x2ca4, 0x00ce, 0x003e, 0x012e, 0x00fe,
-	0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x00c6, 0x00f6, 0x0006,
-	0x0026, 0x2061, 0x0100, 0xa190, 0x2840, 0x2205, 0x60f2, 0x2011,
-	0x284d, 0x2205, 0x60ee, 0x002e, 0x000e, 0x00fe, 0x00ce, 0x0005,
-	0x0840, 0x0840, 0x0840, 0x0580, 0x0420, 0x0348, 0x02c0, 0x0258,
-	0x0210, 0x01a8, 0x01a8, 0x01a8, 0x01a8, 0x0140, 0x00f8, 0x00d0,
-	0x00b0, 0x00a0, 0x2028, 0xa18c, 0x00ff, 0x2130, 0xa094, 0xff00,
-	0x1110, 0x81ff, 0x0118, 0x080c, 0x6723, 0x0038, 0xa080, 0x2df9,
-	0x200d, 0xa18c, 0xff00, 0x810f, 0xa006, 0x0005, 0xa080, 0x2df9,
-	0x200d, 0xa18c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001,
-	0xb615, 0x2003, 0x00ef, 0x20a9, 0x0010, 0xa006, 0x6852, 0x6856,
-	0x1f04, 0x2877, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069,
-	0x0140, 0x2001, 0xb615, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214,
-	0x20a9, 0x0010, 0x6853, 0x0000, 0xa006, 0x82ff, 0x1128, 0xa184,
-	0x000f, 0xa080, 0xb51a, 0x2005, 0x6856, 0x8211, 0x1f04, 0x288c,
-	0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0xb600, 0x6030,
-	0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156,
-	0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0xa116,
-	0x0180, 0xa112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402,
-	0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x28bc, 0x680f,
-	0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x2001,
-	0xb653, 0x2004, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0xa006, 0x0046,
-	0x2020, 0x2009, 0x002e, 0x080c, 0xb1a4, 0x004e, 0x0005, 0x00f6,
-	0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0548, 0xa084,
-	0x0700, 0xa08e, 0x0300, 0x1520, 0x2011, 0x0000, 0x2009, 0x0002,
-	0x2300, 0xa080, 0x0020, 0x2018, 0x2300, 0x080c, 0x6bb2, 0x2011,
-	0x0030, 0x2200, 0x8007, 0xa085, 0x004c, 0x78c2, 0x2009, 0x0204,
-	0x210c, 0x2200, 0xa100, 0x2009, 0x0138, 0x200a, 0x080c, 0x5b41,
-	0x1118, 0x2009, 0xb88f, 0x200a, 0x002e, 0x001e, 0x00fe, 0x0005,
-	0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016,
-	0x0026, 0x2001, 0x0170, 0x200c, 0x8000, 0x2014, 0xa184, 0x0003,
-	0x0110, 0x0804, 0x1b20, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005,
-	0x0006, 0x2001, 0x0100, 0x2004, 0xa082, 0x0005, 0x000e, 0x0268,
-	0x2001, 0x0170, 0x200c, 0xa18c, 0x00ff, 0xa18e, 0x004c, 0x1128,
-	0x200c, 0xa18c, 0xff00, 0x810f, 0x0010, 0x2009, 0x0000, 0x2001,
-	0x0204, 0x2004, 0xa108, 0x0005, 0x0006, 0x0156, 0x00f6, 0x2079,
-	0x0100, 0x20a9, 0x000a, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2943,
-	0x00fe, 0x015e, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061,
-	0x0100, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4, 0x0006, 0x60e8,
-	0x0006, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006, 0x600c,
-	0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x60e0, 0x0006, 0x602f,
-	0x0100, 0x602f, 0x0000, 0xe000, 0xe000, 0xe000, 0xe000, 0x602f,
-	0x0040, 0x602f, 0x0000, 0x000e, 0x60e2, 0x000e, 0x602a, 0x000e,
-	0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2, 0x000e,
-	0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e,
-	0x6032, 0x6036, 0x2008, 0x080c, 0x287c, 0x000e, 0x00ce, 0x001e,
-	0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140, 0x2009, 0x0170,
-	0x2104, 0x200b, 0x0080, 0xe000, 0xe000, 0x200a, 0x0005, 0x2a2f,
-	0x2a33, 0x2a37, 0x2a3d, 0x2a43, 0x2a49, 0x2a4f, 0x2a57, 0x2a5f,
-	0x2a65, 0x2a6b, 0x2a73, 0x2a7b, 0x2a83, 0x2a8b, 0x2a95, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f,
-	0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f,
-	0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2aa1,
-	0x2aa1, 0x2aa7, 0x2aa7, 0x2aae, 0x2aae, 0x2ab5, 0x2ab5, 0x2abe,
-	0x2abe, 0x2ac5, 0x2ac5, 0x2ace, 0x2ace, 0x2ad7, 0x2ad7, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f,
-	0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f,
-	0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2,
-	0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2ae2, 0x2a9f,
-	0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f,
-	0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x2a9f, 0x0106,
-	0x0006, 0x0804, 0x2aea, 0x0106, 0x0006, 0x0804, 0x2aea, 0x0106,
-	0x0006, 0x080c, 0x254e, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c,
-	0x254e, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x0804,
-	0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106,
-	0x0006, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106,
-	0x0006, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0804, 0x2aea, 0x0106,
-	0x0006, 0x080c, 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c,
-	0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c,
-	0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c,
-	0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x080c,
-	0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x23bf, 0x080c,
-	0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c, 0x254e, 0x080c,
-	0x23bf, 0x080c, 0x2427, 0x0804, 0x2aea, 0x0106, 0x0006, 0x080c,
-	0x254e, 0x080c, 0x23bf, 0x080c, 0x2427, 0x0804, 0x2aea, 0xe000,
-	0x0cf0, 0x0106, 0x0006, 0x080c, 0x290b, 0x0804, 0x2aea, 0x0106,
-	0x0006, 0x080c, 0x290b, 0x080c, 0x254e, 0x04e0, 0x0106, 0x0006,
-	0x080c, 0x290b, 0x080c, 0x23bf, 0x04a8, 0x0106, 0x0006, 0x080c,
-	0x290b, 0x080c, 0x254e, 0x080c, 0x23bf, 0x0460, 0x0106, 0x0006,
-	0x080c, 0x290b, 0x080c, 0x2427, 0x0428, 0x0106, 0x0006, 0x080c,
-	0x290b, 0x080c, 0x254e, 0x080c, 0x2427, 0x00e0, 0x0106, 0x0006,
-	0x080c, 0x290b, 0x080c, 0x23bf, 0x080c, 0x2427, 0x0098, 0x0106,
-	0x0006, 0x080c, 0x290b, 0x080c, 0x254e, 0x080c, 0x23bf, 0x080c,
-	0x2427, 0x0040, 0x20d1, 0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000,
-	0x080c, 0x151a, 0x000e, 0x010e, 0x000d, 0x00c6, 0x0026, 0x0046,
-	0x2021, 0x0000, 0x080c, 0x537b, 0x1904, 0x2bca, 0x72d4, 0x2001,
-	0xb89e, 0x2004, 0xa005, 0x1110, 0xd29c, 0x0148, 0xd284, 0x1138,
-	0xd2bc, 0x1904, 0x2bca, 0x080c, 0x2bce, 0x0804, 0x2bca, 0xd2cc,
-	0x1904, 0x2bca, 0x080c, 0x5b41, 0x1120, 0x709f, 0xffff, 0x0804,
-	0x2bca, 0xd294, 0x0120, 0x709f, 0xffff, 0x0804, 0x2bca, 0x2001,
-	0xb615, 0x203c, 0x7288, 0xd284, 0x0904, 0x2b6c, 0xd28c, 0x1904,
-	0x2b6c, 0x0036, 0x739c, 0xa38e, 0xffff, 0x1110, 0x2019, 0x0001,
-	0x8314, 0xa2e0, 0xbdc0, 0x2c04, 0xa38c, 0x0001, 0x0120, 0xa084,
-	0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa70e, 0x0560, 0xa08e,
-	0x0000, 0x0548, 0xa08e, 0x00ff, 0x1150, 0x7230, 0xd284, 0x1538,
-	0x7288, 0xc28d, 0x728a, 0x709f, 0xffff, 0x003e, 0x0428, 0x2009,
-	0x0000, 0x080c, 0x2852, 0x080c, 0x4fbf, 0x11b8, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x1150, 0x7030, 0xd08c, 0x0118, 0x6000,
-	0xd0bc, 0x0120, 0x080c, 0x2be1, 0x0140, 0x0028, 0x080c, 0x2d12,
-	0x080c, 0x2c0f, 0x0110, 0x8318, 0x0818, 0x739e, 0x0010, 0x709f,
-	0xffff, 0x003e, 0x0804, 0x2bca, 0xa780, 0x2df9, 0x203d, 0xa7bc,
-	0xff00, 0x873f, 0x2041, 0x007e, 0x709c, 0xa096, 0xffff, 0x1120,
-	0x2009, 0x0000, 0x28a8, 0x0050, 0xa812, 0x0220, 0x2008, 0xa802,
-	0x20a8, 0x0020, 0x709f, 0xffff, 0x0804, 0x2bca, 0x2700, 0x0156,
-	0x0016, 0xa106, 0x05a0, 0xc484, 0x080c, 0x501b, 0x0120, 0x080c,
-	0x4fbf, 0x15a8, 0x0008, 0xc485, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0006, 0x1130, 0x7030, 0xd08c, 0x01e8, 0x6000, 0xd0bc, 0x11d0,
-	0x7288, 0xd28c, 0x0188, 0x6004, 0xa084, 0x00ff, 0xa082, 0x0006,
-	0x02b0, 0xd484, 0x1118, 0x080c, 0x4fde, 0x0028, 0x080c, 0x2d9f,
-	0x0170, 0x080c, 0x2dcc, 0x0058, 0x080c, 0x2d12, 0x080c, 0x2c0f,
-	0x0170, 0x0028, 0x080c, 0x2d9f, 0x0110, 0x0419, 0x0140, 0x001e,
-	0x8108, 0x015e, 0x1f04, 0x2b86, 0x709f, 0xffff, 0x0018, 0x001e,
-	0x015e, 0x719e, 0x004e, 0x002e, 0x00ce, 0x0005, 0x00c6, 0x0016,
-	0x709f, 0x0001, 0x2009, 0x007e, 0x080c, 0x4fbf, 0x1138, 0x080c,
-	0x2d12, 0x04a9, 0x0118, 0x70d4, 0xc0bd, 0x70d6, 0x001e, 0x00ce,
-	0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb657,
-	0x2004, 0xa084, 0x00ff, 0x6842, 0x080c, 0x9f92, 0x01d8, 0x2d00,
-	0x601a, 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2001, 0x0000, 0x080c,
-	0x4f5d, 0x2001, 0x0000, 0x080c, 0x4f6f, 0x0126, 0x2091, 0x8000,
-	0x7098, 0x8000, 0x709a, 0x012e, 0x2009, 0x0004, 0x080c, 0x86d3,
-	0xa085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x0016,
-	0x0076, 0x00d6, 0x00c6, 0x2c68, 0x2001, 0xb657, 0x2004, 0xa084,
-	0x00ff, 0x6842, 0x080c, 0x9f92, 0x0550, 0x2d00, 0x601a, 0x6800,
-	0xc0c4, 0x6802, 0x68a0, 0xa086, 0x007e, 0x0140, 0x6804, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x1110, 0x080c, 0x2cd1, 0x080c, 0xa0e3,
-	0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002,
-	0x080c, 0x4f6f, 0x0126, 0x2091, 0x8000, 0x7098, 0x8000, 0x709a,
-	0x012e, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, 0x00ce,
-	0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x0026, 0x2009, 0x0080,
-	0x080c, 0x4fbf, 0x1120, 0x0031, 0x0110, 0x70db, 0xffff, 0x002e,
-	0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2c68, 0x080c,
-	0x864e, 0x01e8, 0x2d00, 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0001,
-	0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x2cd1, 0x70dc, 0x8000, 0x70de,
-	0x012e, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001, 0x00ce,
-	0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126, 0x2091,
-	0x8000, 0x2009, 0x007f, 0x080c, 0x4fbf, 0x1190, 0x2c68, 0x080c,
-	0x864e, 0x0170, 0x2d00, 0x601a, 0x6312, 0x601f, 0x0001, 0x620a,
-	0x080c, 0xa0e3, 0x2009, 0x0022, 0x080c, 0x86d3, 0xa085, 0x0001,
-	0x012e, 0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036,
-	0x0026, 0x080c, 0x6e73, 0x080c, 0x6e16, 0x080c, 0x90fb, 0x2130,
-	0x81ff, 0x0128, 0x20a9, 0x007e, 0x2009, 0x0000, 0x0020, 0x20a9,
-	0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1120, 0x080c,
-	0x521c, 0x080c, 0x4c7e, 0x001e, 0x8108, 0x1f04, 0x2cbb, 0x86ff,
-	0x1110, 0x080c, 0x11f5, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee,
-	0x0005, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218, 0x2270,
-	0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, 0x2039,
-	0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, 0xaf3e, 0x007e, 0x001e,
-	0x2e60, 0x080c, 0x521c, 0x6210, 0x6314, 0x080c, 0x4c7e, 0x6212,
-	0x6316, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6,
-	0x0006, 0x6018, 0xa080, 0x0028, 0x2004, 0xa086, 0x0080, 0x0150,
-	0x2071, 0xb600, 0x7098, 0xa005, 0x0110, 0x8001, 0x709a, 0x000e,
-	0x00ee, 0x0005, 0x2071, 0xb600, 0x70dc, 0xa005, 0x0dc0, 0x8001,
-	0x70de, 0x0ca8, 0x6000, 0xc08c, 0x6002, 0x0005, 0x00f6, 0x00e6,
-	0x00c6, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x81ff, 0x1118,
-	0x20a9, 0x0001, 0x0098, 0x2001, 0xb653, 0x2004, 0xd0c4, 0x0150,
-	0xd0a4, 0x0140, 0xa006, 0x0046, 0x2020, 0x2009, 0x002d, 0x080c,
-	0xb1a4, 0x004e, 0x20a9, 0x00ff, 0x2011, 0x0000, 0x0026, 0xa28e,
-	0x007e, 0x0904, 0x2d7e, 0xa28e, 0x007f, 0x0904, 0x2d7e, 0xa28e,
-	0x0080, 0x05e0, 0xa288, 0xb735, 0x210c, 0x81ff, 0x05b8, 0x8fff,
-	0x1148, 0x2001, 0xb8be, 0x0006, 0x2003, 0x0001, 0x04d9, 0x000e,
-	0x2003, 0x0000, 0x00c6, 0x2160, 0x2001, 0x0001, 0x080c, 0x5385,
-	0x00ce, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000,
-	0x080c, 0x6d74, 0x00c6, 0x0026, 0x2160, 0x6204, 0xa294, 0x00ff,
-	0xa286, 0x0006, 0x1118, 0x6007, 0x0404, 0x0028, 0x2001, 0x0004,
-	0x8007, 0xa215, 0x6206, 0x002e, 0x00ce, 0x0016, 0x2c08, 0x080c,
-	0xaf3e, 0x001e, 0x007e, 0x2160, 0x080c, 0x521c, 0x002e, 0x8210,
-	0x1f04, 0x2d36, 0x015e, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee,
-	0x00fe, 0x0005, 0x0046, 0x0026, 0x0016, 0x2001, 0xb653, 0x2004,
-	0xd0c4, 0x0148, 0xd0a4, 0x0138, 0xa006, 0x2220, 0x8427, 0x2009,
-	0x0029, 0x080c, 0xb1a4, 0x001e, 0x002e, 0x004e, 0x0005, 0x0016,
-	0x0026, 0x0036, 0x00c6, 0x7288, 0x82ff, 0x01f8, 0x2011, 0xb653,
-	0x2214, 0xd2ac, 0x11d0, 0x2100, 0x080c, 0x2866, 0x81ff, 0x01b8,
-	0x2019, 0x0001, 0x8314, 0xa2e0, 0xbdc0, 0x2c04, 0xd384, 0x0120,
-	0xa084, 0xff00, 0x8007, 0x0010, 0xa084, 0x00ff, 0xa116, 0x0138,
-	0xa096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0xa085, 0x0001, 0x00ce,
-	0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x0016, 0x0026, 0x0036, 0x2110, 0x0026, 0x2019, 0x0029,
-	0x080c, 0x8320, 0x002e, 0x080c, 0xb449, 0x003e, 0x002e, 0x001e,
-	0xa180, 0xb735, 0x2004, 0xa065, 0x0158, 0x0016, 0x00c6, 0x2061,
-	0xb9f5, 0x001e, 0x611a, 0x080c, 0x2cd1, 0x001e, 0x080c, 0x4fde,
-	0x012e, 0x00ce, 0x001e, 0x0005, 0x2001, 0xb635, 0x2004, 0xd0cc,
-	0x0005, 0x7eef, 0x7de8, 0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc,
-	0x80da, 0x7ad9, 0x80d6, 0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1,
-	0x79ce, 0x78cd, 0x80cc, 0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6,
-	0x77c5, 0x76c3, 0x80bc, 0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4,
-	0x72b3, 0x80b2, 0x80b1, 0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa,
-	0x6ea9, 0x80a7, 0x6da6, 0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d,
-	0x809b, 0x8098, 0x6797, 0x6690, 0x658f, 0x6488, 0x6384, 0x6282,
-	0x8081, 0x8080, 0x617c, 0x607a, 0x8079, 0x5f76, 0x8075, 0x8074,
-	0x8073, 0x8072, 0x8071, 0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a,
-	0x5b69, 0x8067, 0x5a66, 0x5965, 0x5863, 0x575c, 0x565a, 0x5559,
-	0x8056, 0x8055, 0x5454, 0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d,
-	0x804c, 0x804b, 0x4e4a, 0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043,
-	0x803c, 0x803a, 0x8039, 0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932,
-	0x4831, 0x802e, 0x472d, 0x462c, 0x452b, 0x442a, 0x4329, 0x4227,
-	0x8026, 0x8025, 0x4123, 0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18,
-	0x8017, 0x8010, 0x3b0f, 0x3a08, 0x8004, 0x3902, 0x8001, 0x8000,
-	0x8000, 0x3800, 0x3700, 0x3600, 0x8000, 0x3500, 0x8000, 0x8000,
-	0x8000, 0x3400, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x3300, 0x3200, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x3100, 0x3000, 0x8000, 0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00,
-	0x2c00, 0x8000, 0x8000, 0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900,
-	0x2800, 0x8000, 0x2700, 0x2600, 0x2500, 0x2400, 0x2300, 0x2200,
-	0x8000, 0x8000, 0x2100, 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00,
-	0x8000, 0x8000, 0x1b00, 0x1a00, 0x8000, 0x1900, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x1800, 0x8000, 0x1700, 0x1600,
-	0x1500, 0x8000, 0x1400, 0x1300, 0x1200, 0x1100, 0x1000, 0x0f00,
-	0x8000, 0x8000, 0x0e00, 0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900,
-	0x8000, 0x8000, 0x0800, 0x0700, 0x8000, 0x0600, 0x8000, 0x8000,
-	0x8000, 0x0500, 0x0400, 0x0300, 0x8000, 0x0200, 0x8000, 0x8000,
-	0x8000, 0x0100, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x0000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x2071, 0xb682, 0x7003, 0x0002, 0xa006, 0x7012, 0x7016,
-	0x703a, 0x703e, 0x7033, 0xb692, 0x7037, 0xb692, 0x7007, 0x0001,
-	0x2061, 0xb6d2, 0x6003, 0x0002, 0x0005, 0x1004, 0x2f1f, 0x0e04,
-	0x2f1f, 0x2071, 0xb682, 0x2b78, 0x7818, 0xd084, 0x1140, 0x2a60,
-	0x7820, 0xa08e, 0x0069, 0x1904, 0x3004, 0x0804, 0x2f9d, 0x0005,
-	0x2071, 0xb682, 0x7004, 0x0002, 0x2f28, 0x2f29, 0x2f32, 0x2f43,
-	0x0005, 0x1004, 0x2f31, 0x0e04, 0x2f31, 0x2b78, 0x7818, 0xd084,
-	0x01e8, 0x0005, 0x2b78, 0x2061, 0xb6d2, 0x6008, 0xa08e, 0x0100,
-	0x0128, 0xa086, 0x0200, 0x0904, 0x2ffe, 0x0005, 0x7014, 0x2068,
-	0x2a60, 0x7018, 0x0807, 0x7010, 0x2068, 0x6834, 0xa086, 0x0103,
-	0x0108, 0x0005, 0x2a60, 0x2b78, 0x7018, 0x0807, 0x2a60, 0x7820,
-	0xa08a, 0x0040, 0x1210, 0x61c4, 0x0042, 0x2100, 0xa08a, 0x003f,
-	0x1a04, 0x2ffb, 0x61c4, 0x0804, 0x2f9d, 0x2fdf, 0x300a, 0x3012,
-	0x3016, 0x301e, 0x3024, 0x3028, 0x3034, 0x3037, 0x3041, 0x3044,
-	0x2ffb, 0x2ffb, 0x2ffb, 0x3047, 0x2ffb, 0x3056, 0x306d, 0x3084,
-	0x30fe, 0x3103, 0x312c, 0x317d, 0x318e, 0x31ad, 0x31e5, 0x31ef,
-	0x31fc, 0x320f, 0x3230, 0x3239, 0x326f, 0x3275, 0x2ffb, 0x329e,
-	0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32a5, 0x32af, 0x2ffb,
-	0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32b7,
-	0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x32c9, 0x32d3, 0x2ffb,
-	0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x0002, 0x32fd, 0x3351,
-	0x33ac, 0x33c6, 0x2ffb, 0x33f7, 0x382a, 0x427a, 0x2ffb, 0x2ffb,
-	0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x2ffb, 0x3041, 0x3044,
-	0x382c, 0x2ffb, 0x3839, 0x4313, 0x436e, 0x43d2, 0x2ffb, 0x4435,
-	0x445f, 0x447e, 0x44b0, 0x2ffb, 0x2ffb, 0x2ffb, 0x383d, 0x39e2,
-	0x39fc, 0x3a26, 0x3a87, 0x3ae7, 0x3af2, 0x3b2a, 0x3b39, 0x3b48,
-	0x3b4b, 0x3b6e, 0x3bba, 0x3c34, 0x3c41, 0x3d42, 0x3e6a, 0x3e93,
-	0x3f91, 0x3fb3, 0x3fbf, 0x3ff8, 0x40bc, 0x2ffb, 0x2ffb, 0x2ffb,
-	0x2ffb, 0x4124, 0x413f, 0x41b1, 0x4263, 0x713c, 0x0000, 0x2021,
-	0x4000, 0x080c, 0x3ef0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x2feb,
-	0x7818, 0xd084, 0x0110, 0x012e, 0x0cb0, 0x7c22, 0x7926, 0x7a2a,
-	0x7b2e, 0x781b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x2091,
-	0x5000, 0x012e, 0x0005, 0x2021, 0x4001, 0x0c18, 0x2021, 0x4002,
-	0x0c00, 0x2021, 0x4003, 0x08e8, 0x2021, 0x4005, 0x08d0, 0x2021,
-	0x4006, 0x08b8, 0xa02e, 0x2520, 0x7b28, 0x7a2c, 0x7824, 0x7930,
-	0x0804, 0x3efd, 0x7823, 0x0004, 0x7824, 0x0807, 0xa02e, 0x2520,
-	0x7b28, 0x7a2c, 0x7824, 0x7930, 0x0804, 0x3f00, 0x7924, 0x7828,
-	0x2114, 0x200a, 0x0804, 0x2fdf, 0x7924, 0x2114, 0x0804, 0x2fdf,
-	0x2099, 0x0009, 0x20a1, 0x0009, 0x20a9, 0x0007, 0x53a3, 0x7924,
-	0x7a28, 0x7b2c, 0x0804, 0x2fdf, 0x7824, 0x2060, 0x0090, 0x2009,
-	0x0002, 0x2011, 0x0002, 0x2019, 0x0008, 0x783b, 0x0017, 0x0804,
-	0x2fdf, 0x7d38, 0x7c3c, 0x0840, 0x7d38, 0x7c3c, 0x0888, 0x2061,
-	0x1000, 0xe10c, 0xa006, 0x2c15, 0xa200, 0x8c60, 0x8109, 0x1dd8,
-	0x2010, 0xa005, 0x0904, 0x2fdf, 0x0804, 0x3001, 0x2069, 0xb652,
-	0x7824, 0x7930, 0xa11a, 0x1a04, 0x3007, 0x8019, 0x0904, 0x3007,
-	0x684a, 0x6942, 0x782c, 0x6852, 0x7828, 0x6856, 0xa006, 0x685a,
-	0x685e, 0x080c, 0x5e17, 0x0804, 0x2fdf, 0x2069, 0xb652, 0x7824,
-	0x7934, 0xa11a, 0x1a04, 0x3007, 0x8019, 0x0904, 0x3007, 0x684e,
-	0x6946, 0x782c, 0x6862, 0x7828, 0x6866, 0xa006, 0x686a, 0x686e,
-	0x080c, 0x5447, 0x0804, 0x2fdf, 0xa02e, 0x2520, 0x81ff, 0x1904,
-	0x3004, 0x7924, 0x7b28, 0x7a2c, 0x20a9, 0x0005, 0x20a1, 0xb689,
-	0x41a1, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x2009, 0x0020, 0x080c,
-	0x3efd, 0x701b, 0x309c, 0x0005, 0x6834, 0x2008, 0xa084, 0x00ff,
-	0xa096, 0x0011, 0x0138, 0xa096, 0x0019, 0x0120, 0xa096, 0x0015,
-	0x1904, 0x3004, 0x810f, 0xa18c, 0x00ff, 0x0904, 0x3004, 0x710e,
-	0x700c, 0x8001, 0x0528, 0x700e, 0x080c, 0x3ebc, 0x0904, 0x3004,
-	0x2009, 0x0020, 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, 0x6530,
-	0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
-	0x080c, 0x3efd, 0x701b, 0x30cd, 0x0005, 0x6834, 0xa084, 0x00ff,
-	0xa096, 0x0002, 0x0120, 0xa096, 0x000a, 0x1904, 0x3004, 0x08c0,
-	0x7010, 0x2068, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x4ebb, 0x1128,
-	0x7007, 0x0003, 0x701b, 0x30e7, 0x0005, 0x080c, 0x554d, 0x0126,
-	0x2091, 0x8000, 0x20a9, 0x0005, 0x2099, 0xb689, 0x530a, 0x2100,
-	0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0xad80,
-	0x000d, 0x2009, 0x0020, 0x012e, 0x0804, 0x3f00, 0x61ac, 0x7824,
-	0x60ae, 0x0804, 0x2fdf, 0x2091, 0x8000, 0x7823, 0x4000, 0x7827,
-	0x4953, 0x782b, 0x5020, 0x782f, 0x2020, 0x2009, 0x017f, 0x2104,
-	0x7832, 0x3f00, 0x7836, 0x2061, 0x0100, 0x6200, 0x2061, 0x0200,
-	0x603c, 0x8007, 0xa205, 0x783a, 0x2009, 0x04fd, 0x2104, 0x783e,
-	0x781b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x2071, 0x0010,
-	0x20c1, 0x00f0, 0x0804, 0x0427, 0x81ff, 0x1904, 0x3004, 0x7924,
-	0x810f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1904, 0x3007, 0x7e38,
-	0xa684, 0x3fff, 0xa082, 0x4000, 0x0210, 0x0804, 0x3007, 0x7c28,
-	0x7d2c, 0x080c, 0x51e3, 0xd28c, 0x1118, 0x080c, 0x518c, 0x0010,
-	0x080c, 0x51bc, 0x1518, 0x2061, 0xbe00, 0x0126, 0x2091, 0x8000,
-	0x6000, 0xa086, 0x0000, 0x0148, 0x6010, 0xa06d, 0x0130, 0x683c,
-	0xa406, 0x1118, 0x6840, 0xa506, 0x0150, 0x012e, 0xace0, 0x0018,
-	0x2001, 0xb617, 0x2004, 0xac02, 0x1a04, 0x3004, 0x0c30, 0x080c,
-	0x99e6, 0x012e, 0x0904, 0x3004, 0x0804, 0x2fdf, 0xa00e, 0x2001,
-	0x0005, 0x080c, 0x554d, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f8e,
-	0x080c, 0x547a, 0x012e, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004,
-	0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004,
-	0x080c, 0x51ef, 0x0904, 0x3004, 0x0804, 0x2fdf, 0x81ff, 0x1904,
-	0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x080c, 0x525b, 0x0904,
-	0x3004, 0x2019, 0x0005, 0x7924, 0x080c, 0x520a, 0x0904, 0x3004,
-	0x7828, 0xa08a, 0x1000, 0x1a04, 0x3007, 0x8003, 0x800b, 0x810b,
-	0xa108, 0x080c, 0x6a1a, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000,
-	0x81ff, 0x0118, 0x2009, 0x0001, 0x0450, 0x2029, 0x00ff, 0x6450,
-	0x2400, 0xa506, 0x01f8, 0x2508, 0x080c, 0x501b, 0x11d8, 0x080c,
-	0x525b, 0x1128, 0x2009, 0x0002, 0x62b4, 0x2518, 0x00c0, 0x2019,
-	0x0004, 0xa00e, 0x080c, 0x520a, 0x1118, 0x2009, 0x0006, 0x0078,
-	0x7824, 0xa08a, 0x1000, 0x1270, 0x8003, 0x800b, 0x810b, 0xa108,
-	0x080c, 0x6a1a, 0x8529, 0x1ae0, 0x012e, 0x0804, 0x2fdf, 0x012e,
-	0x0804, 0x3004, 0x012e, 0x0804, 0x3007, 0x080c, 0x3ed1, 0x0904,
-	0x3007, 0x080c, 0x5147, 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x81ff,
-	0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x5138,
-	0x080c, 0x51e3, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x080c,
-	0x3ed1, 0x0904, 0x3007, 0x080c, 0x51be, 0x0904, 0x3004, 0x080c,
-	0x4eff, 0x080c, 0x5185, 0x080c, 0x51e3, 0x0804, 0x2fdf, 0x080c,
-	0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, 0x62a0,
-	0x2019, 0x0005, 0x00c6, 0x080c, 0x521c, 0x2061, 0x0000, 0x080c,
-	0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2009, 0x0000,
-	0x080c, 0xaf3e, 0x007e, 0x00ce, 0x080c, 0x51e3, 0x0804, 0x2fdf,
-	0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51e3, 0x2208, 0x0804,
-	0x2fdf, 0x0156, 0x00d6, 0x00e6, 0x2069, 0xb714, 0x6810, 0x6914,
-	0xa10a, 0x1210, 0x2009, 0x0000, 0x6816, 0x2011, 0x0000, 0x2019,
-	0x0000, 0x20a9, 0x007e, 0x2069, 0xb735, 0x2d04, 0xa075, 0x0130,
-	0x704c, 0x0071, 0xa210, 0x7080, 0x0059, 0xa318, 0x8d68, 0x1f04,
-	0x324d, 0x2300, 0xa218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x2fdf,
-	0x00f6, 0x0016, 0xa07d, 0x0140, 0x2001, 0x0000, 0x8000, 0x2f0c,
-	0x81ff, 0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069,
-	0xb714, 0x6910, 0x62b0, 0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004,
-	0x6150, 0xa190, 0x2df9, 0x2215, 0xa294, 0x00ff, 0x6370, 0x83ff,
-	0x0108, 0x6274, 0x67d4, 0xd79c, 0x0118, 0x2031, 0x0001, 0x0090,
-	0xd7ac, 0x0118, 0x2031, 0x0003, 0x0068, 0xd7a4, 0x0118, 0x2031,
-	0x0002, 0x0040, 0x080c, 0x5b41, 0x1118, 0x2031, 0x0004, 0x0010,
-	0x2031, 0x0000, 0x7e3a, 0x7f3e, 0x0804, 0x2fdf, 0x6140, 0x6244,
-	0x2019, 0xb8b6, 0x231c, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000,
-	0x6134, 0xa006, 0x2010, 0x6338, 0x012e, 0x0804, 0x2fdf, 0x080c,
-	0x3ee1, 0x0904, 0x3007, 0x6244, 0x6338, 0x0804, 0x2fdf, 0x6140,
-	0x6244, 0x7824, 0x6042, 0x7b28, 0x6346, 0x2069, 0xb652, 0x831f,
-	0xa305, 0x6816, 0x782c, 0x2069, 0xb8b6, 0x2d1c, 0x206a, 0x0804,
-	0x2fdf, 0x0126, 0x2091, 0x8000, 0x7824, 0x6036, 0x782c, 0x603a,
-	0x012e, 0x0804, 0x2fdf, 0x7838, 0xa005, 0x01a8, 0x7828, 0xa025,
-	0x0904, 0x3007, 0x782c, 0xa02d, 0x0904, 0x3007, 0xa00e, 0x080c,
-	0x501b, 0x1120, 0x6244, 0x6338, 0x6446, 0x653a, 0xa186, 0x00ff,
-	0x0190, 0x8108, 0x0ca0, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x7828,
-	0xa00d, 0x0904, 0x3007, 0x782c, 0xa005, 0x0904, 0x3007, 0x6244,
-	0x6146, 0x6338, 0x603a, 0x0804, 0x2fdf, 0x2001, 0xb600, 0x2004,
-	0xa086, 0x0003, 0x1904, 0x3004, 0x00c6, 0x2061, 0x0100, 0x7924,
-	0x810f, 0xa18c, 0x00ff, 0xa196, 0x00ff, 0x1130, 0x2001, 0xb615,
-	0x2004, 0xa085, 0xff00, 0x0078, 0xa182, 0x007f, 0x16a0, 0xa188,
-	0x2df9, 0x210d, 0xa18c, 0x00ff, 0x2001, 0xb615, 0x2004, 0xa116,
-	0x0550, 0x810f, 0xa105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c,
-	0x864e, 0x000e, 0x01e0, 0x601a, 0x600b, 0xbc09, 0x601f, 0x0001,
-	0x080c, 0x3ebc, 0x01d8, 0x6837, 0x0000, 0x7007, 0x0003, 0x6833,
-	0x0000, 0x6838, 0xc0fd, 0x683a, 0x701b, 0x33a5, 0x2d00, 0x6012,
-	0x2009, 0x0032, 0x080c, 0x86d3, 0x012e, 0x00ce, 0x0005, 0x012e,
-	0x00ce, 0x0804, 0x3004, 0x00ce, 0x0804, 0x3007, 0x080c, 0x86a4,
-	0x0cb0, 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004,
-	0x00c6, 0x2061, 0x0100, 0x7924, 0x810f, 0xa18c, 0x00ff, 0xa196,
-	0x00ff, 0x1130, 0x2001, 0xb615, 0x2004, 0xa085, 0xff00, 0x0078,
-	0xa182, 0x007f, 0x16a0, 0xa188, 0x2df9, 0x210d, 0xa18c, 0x00ff,
-	0x2001, 0xb615, 0x2004, 0xa116, 0x0550, 0x810f, 0xa105, 0x0126,
-	0x2091, 0x8000, 0x0006, 0x080c, 0x864e, 0x000e, 0x01e0, 0x601a,
-	0x600b, 0xbc05, 0x601f, 0x0001, 0x080c, 0x3ebc, 0x01d8, 0x6837,
-	0x0000, 0x7007, 0x0003, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x701b, 0x33a5, 0x2d00, 0x6012, 0x2009, 0x0032, 0x080c, 0x86d3,
-	0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x3004, 0x00ce,
-	0x0804, 0x3007, 0x080c, 0x86a4, 0x0cb0, 0x6830, 0xa086, 0x0100,
-	0x0904, 0x3004, 0x0804, 0x2fdf, 0x2061, 0xb975, 0x0126, 0x2091,
-	0x8000, 0x6000, 0xd084, 0x0178, 0x6104, 0x6208, 0x2a60, 0x6068,
-	0x783a, 0x60b4, 0x783e, 0x60b0, 0x2019, 0x0072, 0x201a, 0x6348,
-	0x012e, 0x0804, 0x2fdf, 0xa00e, 0x2110, 0x0c80, 0x81ff, 0x1904,
-	0x3004, 0x080c, 0x5b41, 0x0904, 0x3004, 0x0126, 0x2091, 0x8000,
-	0x6248, 0x6068, 0xa202, 0x0248, 0xa085, 0x0001, 0x080c, 0x289c,
-	0x080c, 0x4673, 0x012e, 0x0804, 0x2fdf, 0x012e, 0x0804, 0x3007,
-	0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0xb8c0, 0x2070, 0x2061,
-	0xb652, 0x6008, 0x2072, 0x2009, 0x0000, 0x2011, 0x1000, 0x080c,
-	0x6bb2, 0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x7824, 0xa084, 0x0007, 0x0002, 0x3409, 0x3412,
-	0x3419, 0x3406, 0x3406, 0x3406, 0x3406, 0x3406, 0x012e, 0x0804,
-	0x3007, 0x2009, 0x0114, 0x2104, 0xa085, 0x0800, 0x200a, 0x080c,
-	0x3584, 0x0070, 0x2009, 0x010b, 0x200b, 0x0010, 0x080c, 0x3584,
-	0x0038, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x2fe1,
-	0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6,
-	0x080c, 0x33e0, 0x2009, 0x0101, 0x210c, 0x0016, 0x2001, 0x0138,
-	0x200c, 0x2003, 0x0001, 0x0016, 0x2001, 0x007a, 0x2034, 0x2001,
-	0x007b, 0x202c, 0xa006, 0x2048, 0x2050, 0x2058, 0x080c, 0x37cf,
-	0x080c, 0x3733, 0xa03e, 0x2720, 0x00f6, 0x00e6, 0x00c6, 0x2d60,
-	0x2071, 0xb94b, 0x2079, 0x0020, 0x00d6, 0x2069, 0x0000, 0x6824,
-	0xd0b4, 0x0140, 0x2001, 0x007d, 0x2004, 0x783e, 0x2001, 0x007c,
-	0x2004, 0x783a, 0x00de, 0x2011, 0x0001, 0x080c, 0x36df, 0x080c,
-	0x36df, 0x00ce, 0x00ee, 0x00fe, 0x080c, 0x362a, 0x080c, 0x3707,
-	0x080c, 0x3684, 0x080c, 0x35e9, 0x080c, 0x361a, 0x00f6, 0x2079,
-	0x0100, 0x7824, 0xd094, 0x0530, 0x7814, 0xa084, 0x0184, 0xa085,
-	0x0010, 0x7816, 0x2079, 0x0140, 0x080c, 0x3562, 0x1110, 0x00fe,
-	0x0430, 0x7804, 0xd0dc, 0x0dc0, 0x2079, 0x0100, 0x7827, 0x0086,
-	0x7814, 0xa084, 0x0184, 0xa085, 0x0032, 0x7816, 0x080c, 0x3562,
-	0x1110, 0x00fe, 0x00a0, 0x7824, 0xd0bc, 0x0dc0, 0x7827, 0x0080,
-	0xa026, 0x7c16, 0x7824, 0xd0ac, 0x0130, 0x8b58, 0x080c, 0x356c,
-	0x00fe, 0x0804, 0x352c, 0x00fe, 0x080c, 0x3562, 0x1150, 0x8948,
-	0x2001, 0x007a, 0x2602, 0x2001, 0x007b, 0x2502, 0x080c, 0x356c,
-	0x0088, 0x87ff, 0x0140, 0x2001, 0x0201, 0x2004, 0xa005, 0x1904,
-	0x3466, 0x8739, 0x0038, 0x2001, 0xb924, 0x2004, 0xa086, 0x0000,
-	0x1904, 0x3466, 0x2001, 0x0033, 0x2003, 0x00f6, 0x8631, 0x1208,
-	0x8529, 0x2500, 0xa605, 0x0904, 0x352c, 0x7824, 0xd0bc, 0x0128,
-	0x2900, 0xaa05, 0xab05, 0x1904, 0x352c, 0x6033, 0x000d, 0x2001,
-	0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac, 0x1148, 0x2001, 0xb924,
-	0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009, 0x0040, 0x6027,
-	0x0001, 0x2001, 0x0075, 0x2004, 0xa005, 0x0108, 0x6026, 0x2c00,
-	0x601a, 0x20e1, 0x9040, 0x2d00, 0x681a, 0x6833, 0x000d, 0x7824,
-	0xd0a4, 0x1180, 0x6827, 0x0000, 0x00c6, 0x20a9, 0x0004, 0x2061,
-	0x0020, 0x6003, 0x0008, 0x2001, 0x0203, 0x2004, 0x1f04, 0x3501,
-	0x00ce, 0x0040, 0x6827, 0x0001, 0x2001, 0x0074, 0x2004, 0xa005,
-	0x0108, 0x6826, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061, 0x0020,
-	0x7827, 0x0002, 0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x601a,
-	0x0006, 0x2001, 0x0073, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca,
-	0x00ce, 0x00fe, 0x0804, 0x3444, 0x2061, 0x0100, 0x6027, 0x0002,
-	0x001e, 0x61e2, 0x001e, 0x6106, 0x7824, 0xa084, 0x0003, 0xa086,
-	0x0002, 0x0188, 0x20e1, 0x9028, 0x6050, 0xa084, 0xf7ef, 0x6052,
-	0x602f, 0x0000, 0x602c, 0xc0ac, 0x602e, 0x604b, 0xf7f7, 0x6043,
-	0x0090, 0x6043, 0x0010, 0x2908, 0x2a10, 0x2b18, 0x2b00, 0xaa05,
-	0xa905, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e,
-	0x008e, 0x1118, 0x012e, 0x0804, 0x2fdf, 0x012e, 0x2021, 0x400c,
-	0x0804, 0x2fe1, 0xa085, 0x0001, 0x1d04, 0x356b, 0x2091, 0x6000,
-	0x8420, 0xa486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010,
-	0x2001, 0x0030, 0x2003, 0x0004, 0x2001, 0x0020, 0x2003, 0x0004,
-	0x2001, 0xb924, 0x2003, 0x0000, 0x2001, 0xb94b, 0x2003, 0x0000,
-	0x20e1, 0xf000, 0xa026, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001,
-	0xb615, 0x200c, 0x7932, 0x7936, 0x080c, 0x287c, 0x7850, 0xa084,
-	0x0980, 0xa085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0,
-	0xa084, 0x0980, 0x7852, 0x782c, 0xc0ad, 0x782e, 0x20a9, 0x0046,
-	0x1d04, 0x35a0, 0x2091, 0x6000, 0x1f04, 0x35a0, 0x7850, 0xa085,
-	0x0400, 0x7852, 0x2001, 0x0009, 0x2004, 0xa084, 0x0003, 0xa086,
-	0x0001, 0x1118, 0x782c, 0xc0ac, 0x782e, 0x784b, 0xf7f7, 0x7843,
-	0x0090, 0x7843, 0x0010, 0x20a9, 0x000e, 0xe000, 0x1f04, 0x35bd,
-	0x7850, 0xa085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854, 0xe000,
-	0xe000, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048, 0x7850,
-	0xa085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4, 0xe000,
-	0xe000, 0x8319, 0x1de0, 0x2001, 0x0140, 0x2003, 0x0100, 0x7827,
-	0x0020, 0x7843, 0x0000, 0x2003, 0x0000, 0x7827, 0x0048, 0x00fe,
-	0x0005, 0x7824, 0xd0ac, 0x11c8, 0x00f6, 0x00e6, 0x2071, 0xb924,
-	0x2079, 0x0030, 0x2001, 0x0201, 0x2004, 0xa005, 0x0160, 0x7000,
-	0xa086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003,
-	0x0003, 0x7803, 0x0019, 0x00ee, 0x00fe, 0x0005, 0x780c, 0xa08c,
-	0x0070, 0x0178, 0x2009, 0x007a, 0x260a, 0x2009, 0x007b, 0x250a,
-	0xd0b4, 0x0108, 0x8a50, 0xd0ac, 0x0108, 0x8948, 0xd0a4, 0x0108,
-	0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0140,
-	0x20e1, 0x0007, 0x20e1, 0x2000, 0x2001, 0x020a, 0x2004, 0x0ca8,
-	0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0xb8c1, 0x2004,
-	0x70e2, 0x2009, 0xb615, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166,
-	0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078,
-	0xa080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa,
-	0xa006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af,
-	0x95d5, 0x7027, 0x0080, 0x7014, 0xa084, 0x0184, 0xa085, 0x0032,
-	0x7016, 0x080c, 0x3707, 0x080c, 0x3562, 0x1110, 0x8421, 0x0028,
-	0x7024, 0xd0bc, 0x0db0, 0x7027, 0x0080, 0x00f6, 0x00e6, 0x2071,
-	0xb924, 0x2079, 0x0030, 0x00d6, 0x2069, 0x0000, 0x6824, 0xd0b4,
-	0x0120, 0x683c, 0x783e, 0x6838, 0x783a, 0x00de, 0x2011, 0x0011,
-	0x080c, 0x36df, 0x2011, 0x0001, 0x080c, 0x36df, 0x00ee, 0x00fe,
-	0x7017, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0xb924,
-	0x2079, 0x0030, 0x7904, 0xd1fc, 0x0904, 0x36dc, 0x7803, 0x0002,
-	0xa026, 0xd19c, 0x1904, 0x36d8, 0x7000, 0x0002, 0x36dc, 0x369a,
-	0x36be, 0x36d8, 0xd1bc, 0x1150, 0xd1dc, 0x1150, 0x8001, 0x7002,
-	0x2011, 0x0001, 0x04e1, 0x05c0, 0x04d1, 0x04b0, 0x780f, 0x0000,
-	0x7820, 0x7924, 0x7803, 0x0004, 0x7822, 0x7926, 0x2001, 0x0201,
-	0x200c, 0x81ff, 0x0de8, 0x080c, 0x3606, 0x2009, 0x0001, 0x7808,
-	0xd0ec, 0x0110, 0x2009, 0x0011, 0x7902, 0x00f0, 0x8001, 0x7002,
-	0xa184, 0x0880, 0x1138, 0x7804, 0xd0fc, 0x1940, 0x2011, 0x0001,
-	0x00b1, 0x0090, 0x6030, 0xa092, 0x0004, 0xa086, 0x0009, 0x1120,
-	0x6000, 0x601a, 0x2011, 0x0025, 0x6232, 0xd1dc, 0x1988, 0x0870,
-	0x7803, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x6024,
-	0xa005, 0x0520, 0x8001, 0x6026, 0x6018, 0x6130, 0xa140, 0x2804,
-	0x7832, 0x8840, 0x2804, 0x7836, 0x8840, 0x2804, 0x7822, 0x8840,
-	0x2804, 0x7826, 0x8840, 0x7a02, 0x7000, 0x8000, 0x7002, 0x6018,
-	0xa802, 0xa08a, 0x0029, 0x1138, 0x6018, 0xa080, 0x0001, 0x2004,
-	0x601a, 0x2001, 0x000d, 0x6032, 0xa085, 0x0001, 0x0005, 0x00f6,
-	0x00e6, 0x00c6, 0x2071, 0xb94b, 0x2079, 0x0020, 0x7904, 0xd1fc,
-	0x01f0, 0x7803, 0x0002, 0x2d60, 0xa026, 0x7000, 0x0002, 0x372f,
-	0x371a, 0x3726, 0x8001, 0x7002, 0xd19c, 0x1188, 0x2011, 0x0001,
-	0x080c, 0x36df, 0x0160, 0x080c, 0x36df, 0x0048, 0x8001, 0x7002,
-	0x7804, 0xd0fc, 0x1d30, 0x2011, 0x0001, 0x080c, 0x36df, 0x00ce,
-	0x00ee, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200,
-	0x2001, 0xb8c1, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0xb8c0,
-	0x2004, 0x60ce, 0x6004, 0xc0ac, 0xa085, 0x0200, 0x6006, 0x2001,
-	0x0074, 0x2004, 0xa005, 0x01f8, 0x2038, 0x2001, 0x0076, 0x2024,
-	0x2001, 0x0077, 0x201c, 0x080c, 0x3ebc, 0x6833, 0x000d, 0x6f26,
-	0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007,
-	0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d, 0x04b1, 0x1d90,
-	0x2d00, 0x681a, 0x0088, 0x080c, 0x3ebc, 0x6833, 0x000d, 0x2070,
-	0x6827, 0x0001, 0x2d00, 0x681a, 0x2001, 0x0076, 0x2004, 0x2072,
-	0x2001, 0x0077, 0x2004, 0x7006, 0x2061, 0x0020, 0x2079, 0x0100,
-	0x2001, 0xb8c0, 0x2004, 0x6012, 0x20e1, 0x9040, 0x2001, 0x0072,
-	0x2004, 0xa084, 0xfff8, 0x700a, 0x601a, 0x0006, 0x2001, 0x0073,
-	0x2004, 0x700e, 0x601e, 0x78c6, 0x000e, 0x78ca, 0xa006, 0x603a,
-	0x603e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0010,
-	0x20a0, 0x2099, 0x0014, 0x7003, 0x0026, 0x7432, 0x7336, 0xa006,
-	0x703a, 0x703e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7122, 0x7003,
-	0x0041, 0x7004, 0xd0fc, 0x0de8, 0x7003, 0x0002, 0x7003, 0x0040,
-	0x53a5, 0x7430, 0x7334, 0x87ff, 0x0180, 0x00c6, 0x00d6, 0x2d60,
-	0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x6018, 0x2070, 0x2d00, 0x7006,
-	0x601a, 0x00de, 0x00ce, 0xa085, 0x0001, 0x00ee, 0x0005, 0x00e6,
-	0x2001, 0x0075, 0x2004, 0xa005, 0x0508, 0x2038, 0x2001, 0x0078,
-	0x2024, 0x2001, 0x0079, 0x201c, 0x080c, 0x3ebc, 0x2d60, 0x6833,
-	0x000d, 0x6f26, 0x2d00, 0x681a, 0xa78a, 0x0007, 0x0220, 0x2138,
-	0x2009, 0x0007, 0x0010, 0x2708, 0xa03e, 0x6818, 0xa080, 0x000d,
-	0x080c, 0x379d, 0x1d88, 0x2d00, 0x681a, 0x00e0, 0x080c, 0x3ebc,
-	0x2d60, 0x6033, 0x000d, 0x2070, 0x6027, 0x0001, 0x2c00, 0x601a,
-	0x2001, 0x0078, 0x2004, 0x2072, 0x2001, 0x0079, 0x2004, 0x7006,
-	0x2001, 0x0072, 0x2004, 0xa084, 0xfff8, 0x700a, 0x2001, 0x0073,
-	0x2004, 0x700e, 0x2001, 0x0030, 0x2003, 0x0004, 0x7824, 0xd0ac,
-	0x1178, 0x2001, 0x0101, 0x200c, 0xc1ed, 0x2102, 0x6027, 0x0000,
-	0x2001, 0xb924, 0x2003, 0x0003, 0x2001, 0x0030, 0x2003, 0x0009,
-	0x00ee, 0x0005, 0x0804, 0x2fdf, 0x0126, 0x2091, 0x8000, 0x20a9,
-	0x0012, 0x2001, 0xb640, 0x20a0, 0xa006, 0x40a4, 0x012e, 0x0804,
-	0x2fdf, 0x7d38, 0x7c3c, 0x0804, 0x3086, 0x080c, 0x3ebc, 0x0904,
-	0x3004, 0x080c, 0x5b41, 0x0110, 0x080c, 0x4c52, 0x2009, 0x001c,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x3851,
-	0x0005, 0xade8, 0x000d, 0x6800, 0xa005, 0x0904, 0x3007, 0x6804,
-	0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x3007, 0xd094, 0x00c6, 0x2061,
-	0x0100, 0x6104, 0x0138, 0x6200, 0xa292, 0x0005, 0x0218, 0xa18c,
-	0xffdf, 0x0010, 0xa18d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6,
-	0x2061, 0x0100, 0x6104, 0x0118, 0xa18d, 0x0010, 0x0010, 0xa18c,
-	0xffef, 0x6106, 0x00ce, 0x2009, 0x0100, 0x210c, 0xa18a, 0x0002,
-	0x0268, 0xd084, 0x0158, 0x6a28, 0xa28a, 0x007f, 0x1a04, 0x3007,
-	0xa288, 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x615a, 0xd0dc, 0x0130,
-	0x6828, 0xa08a, 0x007f, 0x1a04, 0x3007, 0x6052, 0x6808, 0xa08a,
-	0x0100, 0x0a04, 0x3007, 0xa08a, 0x0841, 0x1a04, 0x3007, 0xa084,
-	0x0007, 0x1904, 0x3007, 0x680c, 0xa005, 0x0904, 0x3007, 0x6810,
-	0xa005, 0x0904, 0x3007, 0x6848, 0x6940, 0xa10a, 0x1a04, 0x3007,
-	0x8001, 0x0904, 0x3007, 0x684c, 0x6944, 0xa10a, 0x1a04, 0x3007,
-	0x8001, 0x0904, 0x3007, 0x6804, 0xd0fc, 0x0560, 0x080c, 0x3ebc,
-	0x0904, 0x3004, 0x2009, 0x0014, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0xa290, 0x0038, 0xa399, 0x0000, 0x080c, 0x3efd, 0x701b, 0x38d1,
-	0x0005, 0xade8, 0x000d, 0x20a9, 0x0014, 0x2d98, 0x2069, 0xb66e,
-	0x2da0, 0x53a3, 0x7010, 0xa0e8, 0x000d, 0x2001, 0xb672, 0x200c,
-	0xd1e4, 0x0140, 0x00c6, 0x2061, 0x0100, 0x6004, 0xa085, 0x0b00,
-	0x6006, 0x00ce, 0x2009, 0xb8b1, 0x200b, 0x0000, 0x2001, 0xb674,
-	0x2004, 0xd0ac, 0x0158, 0x7824, 0x200a, 0x2009, 0x017f, 0x200a,
-	0x3200, 0xa084, 0x003f, 0xa085, 0x3020, 0x2090, 0x20a9, 0x001c,
-	0x2d98, 0x2069, 0xb652, 0x2da0, 0x53a3, 0x6814, 0xa08c, 0x00ff,
-	0x6142, 0x8007, 0xa084, 0x00ff, 0x6046, 0x080c, 0x5e17, 0x080c,
-	0x53de, 0x080c, 0x5447, 0x6000, 0xa086, 0x0000, 0x1904, 0x39cc,
-	0x6808, 0x602a, 0x080c, 0x24a5, 0x0006, 0x2001, 0x0100, 0x2004,
-	0xa082, 0x0005, 0x000e, 0x0268, 0x2009, 0x0170, 0x200b, 0x0080,
-	0xe000, 0xe000, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x28d7,
-	0x003e, 0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217,
-	0x831f, 0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148,
-	0x6830, 0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f,
-	0x0010, 0xa084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007,
-	0x810f, 0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0xb8c7, 0x40a1,
-	0x080c, 0x6ada, 0x6904, 0xd1fc, 0x0520, 0x00c6, 0x2009, 0x0000,
-	0x20a9, 0x0001, 0x6b70, 0xd384, 0x01c8, 0x0020, 0x839d, 0x12b0,
-	0x3508, 0x8109, 0x080c, 0x63ce, 0x6878, 0x6016, 0x6874, 0x2008,
-	0xa084, 0xff00, 0x8007, 0x600a, 0xa184, 0x00ff, 0x6006, 0x8108,
-	0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001, 0x1f04, 0x3966,
-	0x00ce, 0x2069, 0xb652, 0x2001, 0xb89e, 0x6a80, 0xa294, 0x0030,
-	0xa28e, 0x0000, 0x0170, 0xa28e, 0x0010, 0x0118, 0xa28e, 0x0020,
-	0x0140, 0x2003, 0xaaaa, 0x080c, 0x2920, 0x2001, 0xb88f, 0x2102,
-	0x0008, 0x2102, 0x00c6, 0x2061, 0x0100, 0x602f, 0x0040, 0x602f,
-	0x0000, 0x00ce, 0x080c, 0x5b41, 0x0128, 0x080c, 0x4116, 0x0110,
-	0x080c, 0x289c, 0x60c8, 0xa005, 0x01d0, 0x6003, 0x0001, 0x2009,
-	0x39b2, 0x00e0, 0x080c, 0x5b41, 0x1178, 0x2011, 0x5a14, 0x080c,
-	0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x2001, 0xb89f, 0x2003,
-	0x0000, 0x080c, 0x5a79, 0x0040, 0x080c, 0x4b7b, 0x0028, 0x6003,
-	0x0004, 0x2009, 0x39cc, 0x0010, 0x0804, 0x2fdf, 0x2001, 0x0100,
-	0x2004, 0xa082, 0x0005, 0x0258, 0x2001, 0x0170, 0x2004, 0xa084,
-	0x00ff, 0xa086, 0x004c, 0x1118, 0x2091, 0x309d, 0x0817, 0x2091,
-	0x301d, 0x0817, 0x6000, 0xa086, 0x0000, 0x0904, 0x3004, 0x2069,
-	0xb652, 0x7830, 0x6842, 0x7834, 0x6846, 0x6804, 0xd0fc, 0x0118,
-	0x2009, 0x0030, 0x0010, 0x2009, 0x001c, 0x2d00, 0x7a2c, 0x7b28,
-	0x7c3c, 0x7d38, 0x0804, 0x3f00, 0xa006, 0x080c, 0x289c, 0x81ff,
-	0x1904, 0x3004, 0x080c, 0x5b41, 0x1178, 0x2001, 0xb89f, 0x2003,
-	0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c,
-	0x5b85, 0x080c, 0x5a79, 0x0080, 0x0016, 0x2009, 0xffff, 0x8109,
-	0x0130, 0x2001, 0xb8e2, 0x2004, 0xa086, 0x0000, 0x1dc0, 0x001e,
-	0x080c, 0x4c52, 0x080c, 0x4b7b, 0x0804, 0x2fdf, 0x81ff, 0x1904,
-	0x3004, 0x080c, 0x5b41, 0x1110, 0x0804, 0x3004, 0x6188, 0x81ff,
-	0x0198, 0x703f, 0x0000, 0x2001, 0xbdc0, 0x2009, 0x0040, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x0126, 0x2091, 0x8000, 0x080c, 0x3f00,
-	0x701b, 0x2fdd, 0x012e, 0x0005, 0x703f, 0x0001, 0x00d6, 0x2069,
-	0xbdc0, 0x20a9, 0x0040, 0x20a1, 0xbdc0, 0x2019, 0xffff, 0x43a4,
-	0x6550, 0xa588, 0x2df9, 0x210d, 0xa18c, 0x00ff, 0x216a, 0xa00e,
-	0x2011, 0x0002, 0x2100, 0xa506, 0x01a8, 0x080c, 0x501b, 0x1190,
-	0x6014, 0x821c, 0x0238, 0xa398, 0xbdc0, 0xa085, 0xff00, 0x8007,
-	0x201a, 0x0038, 0xa398, 0xbdc0, 0x2324, 0xa4a4, 0xff00, 0xa405,
-	0x201a, 0x8210, 0x8108, 0xa182, 0x0080, 0x1208, 0x0c18, 0x8201,
-	0x8007, 0x2d0c, 0xa105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1,
-	0xbdc0, 0x2099, 0xbdc0, 0x080c, 0x4bf1, 0x0804, 0x3a33, 0x080c,
-	0x3ee1, 0x0904, 0x3007, 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x1120,
-	0x2009, 0x0002, 0x0804, 0x3004, 0x2001, 0xb653, 0x2004, 0xd0b4,
-	0x0550, 0x7824, 0xa084, 0xff00, 0xa08e, 0x7e00, 0x0520, 0xa08e,
-	0x7f00, 0x0508, 0xa08e, 0x8000, 0x01f0, 0x6000, 0xd08c, 0x11d8,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x11a8, 0x6837, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e96, 0x1120, 0x2009, 0x0003,
-	0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3abf, 0x0005, 0x080c,
-	0x3ee1, 0x0904, 0x3007, 0x20a9, 0x002b, 0x2c98, 0xade8, 0x0002,
-	0x2da0, 0x53a3, 0x20a9, 0x0004, 0xac80, 0x0006, 0x2098, 0xad80,
-	0x0006, 0x20a0, 0x080c, 0x4bf1, 0x20a9, 0x0004, 0xac80, 0x000a,
-	0x2098, 0xad80, 0x000a, 0x20a0, 0x080c, 0x4bf1, 0x2d00, 0x2009,
-	0x002b, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x81ff,
-	0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x51f8,
-	0x0804, 0x2fdf, 0x81ff, 0x1904, 0x3004, 0x7828, 0xa08a, 0x1000,
-	0x1a04, 0x3007, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x080c, 0x525b,
-	0x0904, 0x3004, 0x2019, 0x0004, 0xa00e, 0x080c, 0x520a, 0x7924,
-	0x810f, 0x7a28, 0x0011, 0x0804, 0x2fdf, 0xa186, 0x00ff, 0x0110,
-	0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0xb600, 0x6450, 0x2400,
-	0xa506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c,
-	0x501b, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0xa108, 0x080c,
-	0x6a1a, 0x0005, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904,
-	0x3007, 0x080c, 0x50e1, 0x0904, 0x3004, 0x080c, 0x5201, 0x0804,
-	0x2fdf, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ed1, 0x0904, 0x3007,
-	0x080c, 0x50e1, 0x0904, 0x3004, 0x080c, 0x51ef, 0x0804, 0x2fdf,
-	0x6100, 0x0804, 0x2fdf, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x2001,
-	0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x00d6, 0xace8,
-	0x000a, 0x7924, 0xd184, 0x0110, 0xace8, 0x0006, 0x680c, 0x8007,
-	0x783e, 0x6808, 0x8007, 0x783a, 0x6b04, 0x831f, 0x6a00, 0x8217,
-	0x00de, 0x6100, 0xa18c, 0x0200, 0x0804, 0x2fdf, 0x7824, 0xa09c,
-	0x0003, 0xd0b4, 0x1160, 0xa39a, 0x0003, 0x1a04, 0x3004, 0x6250,
-	0xa294, 0x00ff, 0xa084, 0xff00, 0x8007, 0xa206, 0x1150, 0x2001,
-	0xb640, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804,
-	0x3f00, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1904, 0x3004, 0x00c6,
-	0x080c, 0x3ebc, 0x00ce, 0x0904, 0x3004, 0x6837, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x080c, 0x9e42, 0x0904, 0x3004, 0x7007, 0x0003,
-	0x701b, 0x3bab, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3004,
-	0xad80, 0x000e, 0x2009, 0x000c, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38,
-	0x0804, 0x3f00, 0xa006, 0x080c, 0x289c, 0x7824, 0xa084, 0x00ff,
-	0xa086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x3004, 0x080c, 0x5b41,
-	0x0110, 0x080c, 0x4c52, 0x7828, 0xa08a, 0x1000, 0x1a04, 0x3007,
-	0x7924, 0xa18c, 0xff00, 0x810f, 0xa186, 0x00ff, 0x0138, 0xa182,
-	0x007f, 0x1a04, 0x3007, 0x2100, 0x080c, 0x2866, 0x0026, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x2061, 0xb8f4, 0x601b, 0x0000, 0x601f,
-	0x0000, 0x080c, 0x5b41, 0x1178, 0x2001, 0xb89f, 0x2003, 0x0001,
-	0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b85,
-	0x080c, 0x5a79, 0x0440, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011,
-	0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000,
-	0x080c, 0x806b, 0x003e, 0x2061, 0x0100, 0x2001, 0xb615, 0x2004,
-	0xa084, 0x00ff, 0x810f, 0xa105, 0x604a, 0x6043, 0x0090, 0x6043,
-	0x0010, 0x2009, 0xb8bf, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011,
-	0x4bb4, 0x080c, 0x6a94, 0x7924, 0xa18c, 0xff00, 0x810f, 0x080c,
-	0x5b41, 0x1110, 0x2009, 0x00ff, 0x7a28, 0x080c, 0x3b0d, 0x012e,
-	0x00ce, 0x002e, 0x0804, 0x2fdf, 0x7924, 0xa18c, 0xff00, 0x810f,
-	0x00c6, 0x080c, 0x4fbf, 0x2c08, 0x00ce, 0x1904, 0x3007, 0x0804,
-	0x2fdf, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004, 0x60d4,
-	0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x3004,
-	0x080c, 0x3ebc, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x7924,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x3c61,
-	0x0005, 0x2009, 0x0080, 0x080c, 0x501b, 0x1130, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x0120, 0x2021, 0x400a, 0x0804, 0x2fe1,
-	0x00d6, 0xade8, 0x000d, 0x6900, 0x6a08, 0x6b0c, 0x6c10, 0x6d14,
-	0x6e18, 0x6820, 0xa0be, 0x0100, 0x0904, 0x3cd8, 0xa0be, 0x0112,
-	0x0904, 0x3cd8, 0xa0be, 0x0113, 0x0904, 0x3cd8, 0xa0be, 0x0114,
-	0x0904, 0x3cd8, 0xa0be, 0x0117, 0x0904, 0x3cd8, 0xa0be, 0x011a,
-	0x0904, 0x3cd8, 0xa0be, 0x011c, 0x0904, 0x3cd8, 0xa0be, 0x0121,
-	0x05b0, 0xa0be, 0x0131, 0x0598, 0xa0be, 0x0171, 0x05c8, 0xa0be,
-	0x0173, 0x05b0, 0xa0be, 0x01a1, 0x1120, 0x6830, 0x8007, 0x6832,
-	0x04a8, 0xa0be, 0x0212, 0x0540, 0xa0be, 0x0213, 0x0528, 0xa0be,
-	0x0214, 0x01b0, 0xa0be, 0x0217, 0x0168, 0xa0be, 0x021a, 0x1120,
-	0x6838, 0x8007, 0x683a, 0x00e0, 0xa0be, 0x0300, 0x01c8, 0x00de,
-	0x0804, 0x3007, 0xad80, 0x0010, 0x20a9, 0x0007, 0x080c, 0x3d1e,
-	0xad80, 0x000e, 0x20a9, 0x0001, 0x080c, 0x3d1e, 0x0048, 0xad80,
-	0x000c, 0x080c, 0x3d2c, 0x0050, 0xad80, 0x000e, 0x080c, 0x3d2c,
-	0xad80, 0x000c, 0x20a9, 0x0001, 0x080c, 0x3d1e, 0x00c6, 0x080c,
-	0x3ebc, 0x0568, 0x6838, 0xc0fd, 0x683a, 0x6837, 0x0119, 0x6853,
-	0x0000, 0x684f, 0x0020, 0x685b, 0x0001, 0x810b, 0x697e, 0x6883,
-	0x0000, 0x6a86, 0x6b8a, 0x6c8e, 0x6d92, 0x6996, 0x689b, 0x0000,
-	0x00ce, 0x00de, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x6823,
-	0x0000, 0x6804, 0x2068, 0x080c, 0x9e5e, 0x1120, 0x2009, 0x0003,
-	0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3d15, 0x0005, 0x00ce,
-	0x00de, 0x2009, 0x0002, 0x0804, 0x3004, 0x6820, 0xa086, 0x8001,
-	0x1904, 0x2fdf, 0x2009, 0x0004, 0x0804, 0x3004, 0x0016, 0x2008,
-	0x2044, 0x8000, 0x204c, 0x8000, 0x290a, 0x8108, 0x280a, 0x8108,
-	0x1f04, 0x3d20, 0x001e, 0x0005, 0x0016, 0x00a6, 0x00b6, 0x2008,
-	0x2044, 0x8000, 0x204c, 0x8000, 0x2054, 0x8000, 0x205c, 0x2b0a,
-	0x8108, 0x2a0a, 0x8108, 0x290a, 0x8108, 0x280a, 0x00be, 0x00ae,
-	0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004,
-	0x60d4, 0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804,
-	0x3004, 0x7924, 0x2140, 0xa18c, 0xff00, 0x810f, 0x60d4, 0xd0ac,
-	0x1120, 0xa182, 0x0080, 0x0a04, 0x3007, 0xa182, 0x00ff, 0x1a04,
-	0x3007, 0x7a2c, 0x7b28, 0x6070, 0xa306, 0x1140, 0x6074, 0xa24e,
-	0x0904, 0x3007, 0xa9cc, 0xff00, 0x0904, 0x3007, 0x0126, 0x2091,
-	0x8000, 0x00c6, 0x080c, 0x3e0c, 0x2c68, 0x00ce, 0x0538, 0xa0c6,
-	0x4000, 0x1178, 0x00c6, 0x0006, 0x2d60, 0xa00e, 0x080c, 0x52bc,
-	0x1108, 0xc185, 0x6000, 0xd0bc, 0x0108, 0xc18d, 0x000e, 0x00ce,
-	0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008,
-	0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010,
-	0x2001, 0x4006, 0x2020, 0x012e, 0x0804, 0x2fe1, 0x2d00, 0x7022,
-	0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0x864e, 0x05c0,
-	0x2d00, 0x601a, 0x080c, 0xa0e3, 0x2e58, 0x00ee, 0x00e6, 0x00c6,
-	0x080c, 0x3ebc, 0x00ce, 0x2b70, 0x1158, 0x080c, 0x86a4, 0x00ee,
-	0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002, 0x0804, 0x3004,
-	0x6837, 0x0000, 0x683b, 0x0000, 0x2d00, 0x6012, 0x6833, 0x0000,
-	0x6838, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x080c, 0x2cd1,
-	0x601f, 0x0001, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002,
-	0x080c, 0x4f6f, 0x2009, 0x0002, 0x080c, 0x86d3, 0xa085, 0x0001,
-	0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003,
-	0x0804, 0x3004, 0x7007, 0x0003, 0x701b, 0x3def, 0x0005, 0x6830,
-	0xa086, 0x0100, 0x7020, 0x2060, 0x1138, 0x2009, 0x0004, 0x6204,
-	0xa294, 0x00ff, 0x0804, 0x3004, 0x2009, 0x0000, 0x6838, 0xd0f4,
-	0x1904, 0x2fdf, 0x080c, 0x52bc, 0x1108, 0xc185, 0x6000, 0xd0bc,
-	0x0108, 0xc18d, 0x0804, 0x2fdf, 0x00e6, 0x00d6, 0xa02e, 0x2001,
-	0xb635, 0x2004, 0xd0ac, 0x0130, 0xa026, 0x20a9, 0x00ff, 0x2071,
-	0xb735, 0x0030, 0x2021, 0x0080, 0x20a9, 0x007f, 0x2071, 0xb7b5,
-	0x2e04, 0xa005, 0x1130, 0x2100, 0xa406, 0x1570, 0x2428, 0xc5fd,
-	0x0458, 0x2068, 0x6f10, 0x2700, 0xa306, 0x11b0, 0x6e14, 0x2600,
-	0xa206, 0x1190, 0x2400, 0xa106, 0x1160, 0x2d60, 0xd884, 0x0568,
-	0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1538, 0x2001, 0x4000,
-	0x0428, 0x2001, 0x4007, 0x0410, 0x2400, 0xa106, 0x1168, 0x6e14,
-	0x87ff, 0x1138, 0x86ff, 0x09d0, 0x2001, 0xb635, 0x2004, 0xd0ac,
-	0x19a8, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x3e20,
-	0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030,
-	0x080c, 0x4fbf, 0x1dd0, 0x6312, 0x6216, 0xa006, 0xa005, 0x00de,
-	0x00ee, 0x0005, 0x81ff, 0x1904, 0x3004, 0x080c, 0x3ebc, 0x0904,
-	0x3004, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x7824, 0xa005,
-	0x0904, 0x3007, 0xa096, 0x00ff, 0x0120, 0xa092, 0x0004, 0x1a04,
-	0x3007, 0x2010, 0x2d18, 0x080c, 0x2c84, 0x0904, 0x3004, 0x7007,
-	0x0003, 0x701b, 0x3e8c, 0x0005, 0x6830, 0xa086, 0x0100, 0x0904,
-	0x3004, 0x0804, 0x2fdf, 0x7924, 0xa18c, 0xff00, 0x810f, 0x60d4,
-	0xd0ac, 0x1120, 0xa182, 0x0080, 0x0a04, 0x3007, 0xa182, 0x00ff,
-	0x1a04, 0x3007, 0x0126, 0x2091, 0x8000, 0x080c, 0x9d46, 0x1188,
-	0xa190, 0xb735, 0x2204, 0xa065, 0x0160, 0x080c, 0x4c7e, 0x2001,
-	0xb635, 0x2004, 0xd0ac, 0x0110, 0x6017, 0x0000, 0x012e, 0x0804,
-	0x2fdf, 0x012e, 0x0804, 0x3004, 0x080c, 0x15fd, 0x0188, 0xa006,
-	0x6802, 0x7010, 0xa005, 0x1120, 0x2d00, 0x7012, 0x7016, 0x0030,
-	0x7014, 0x6802, 0x2060, 0x2d00, 0x6006, 0x7016, 0xad80, 0x000d,
-	0x0005, 0x7924, 0x810f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1130,
-	0x7e28, 0xa684, 0x3fff, 0xa082, 0x4000, 0x0208, 0xa066, 0x8cff,
-	0x0005, 0x7e24, 0x860f, 0xa18c, 0x00ff, 0x080c, 0x501b, 0x1128,
-	0xa6b4, 0x00ff, 0xa682, 0x4000, 0x0208, 0xa066, 0x8cff, 0x0005,
-	0x0016, 0x7110, 0x81ff, 0x0128, 0x2168, 0x6904, 0x080c, 0x1614,
-	0x0cc8, 0x7112, 0x7116, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010,
-	0x2031, 0x0000, 0x2061, 0xb6d2, 0x6606, 0x6112, 0x600e, 0x6226,
-	0x632a, 0x642e, 0x6532, 0x2c10, 0x080c, 0x1648, 0x7007, 0x0002,
-	0x701b, 0x2fdf, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079,
-	0x0000, 0x2001, 0xb690, 0x2004, 0xa005, 0x1168, 0x0e04, 0x3f2b,
-	0x7818, 0xd084, 0x1140, 0x7a22, 0x7b26, 0x7c2a, 0x781b, 0x0001,
-	0x2091, 0x4080, 0x0408, 0x0016, 0x00c6, 0x00e6, 0x2071, 0xb682,
-	0x7138, 0xa182, 0x0010, 0x0218, 0x7030, 0x2060, 0x0078, 0x7030,
-	0xa0e0, 0x0004, 0xac82, 0xb6d2, 0x0210, 0x2061, 0xb692, 0x2c00,
-	0x7032, 0x81ff, 0x1108, 0x7036, 0x8108, 0x713a, 0x2262, 0x6306,
-	0x640a, 0x00ee, 0x00ce, 0x001e, 0x012e, 0x00fe, 0x0005, 0x00e6,
-	0x2071, 0xb682, 0x7038, 0xa005, 0x0570, 0x0126, 0x2091, 0x8000,
-	0x0e04, 0x3f82, 0x00f6, 0x2079, 0x0000, 0x7818, 0xd084, 0x1508,
-	0x00c6, 0x7034, 0x2060, 0x2c04, 0x7822, 0x6004, 0x7826, 0x6008,
-	0x782a, 0x781b, 0x0001, 0x2091, 0x4080, 0x7038, 0x8001, 0x703a,
-	0xa005, 0x1130, 0x7033, 0xb692, 0x7037, 0xb692, 0x00ce, 0x0048,
-	0xac80, 0x0004, 0xa0fa, 0xb6d2, 0x0210, 0x2001, 0xb692, 0x7036,
-	0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x0026, 0x2001, 0xb653,
-	0x2004, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c, 0x3f13, 0x002e,
-	0x0005, 0x81ff, 0x1904, 0x3004, 0x0126, 0x2091, 0x8000, 0x6030,
-	0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x5b41, 0x1178, 0x2001,
-	0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085,
-	0x0001, 0x080c, 0x5b85, 0x080c, 0x5a79, 0x0010, 0x080c, 0x4b7b,
-	0x012e, 0x0804, 0x2fdf, 0x7824, 0x2008, 0xa18c, 0xfffd, 0x1128,
-	0x61e0, 0xa10d, 0x61e2, 0x0804, 0x2fdf, 0x0804, 0x3007, 0x81ff,
-	0x1904, 0x3004, 0x6000, 0xa086, 0x0003, 0x1904, 0x3004, 0x2001,
-	0xb653, 0x2004, 0xd0ac, 0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904,
-	0x3007, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1120, 0x7828,
-	0xa005, 0x0904, 0x2fdf, 0x00c6, 0x080c, 0x3ebc, 0x00ce, 0x0904,
-	0x3004, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a,
-	0x080c, 0x9f27, 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x3ff1,
-	0x0005, 0x6830, 0xa086, 0x0100, 0x0904, 0x3004, 0x0804, 0x2fdf,
-	0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x7f24,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3ebc, 0x0904, 0x3004,
-	0x2009, 0x0000, 0x2031, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000,
-	0xad80, 0x0005, 0x7026, 0x20a0, 0x080c, 0x501b, 0x1904, 0x406b,
-	0x6004, 0xa0c4, 0x00ff, 0xa8c6, 0x0006, 0x0130, 0xa0c4, 0xff00,
-	0xa8c6, 0x0600, 0x1904, 0x406b, 0x2001, 0xb653, 0x2004, 0xd0ac,
-	0x1128, 0x080c, 0x52bc, 0x1110, 0xd79c, 0x05e8, 0xd794, 0x1110,
-	0xd784, 0x0158, 0xac80, 0x0006, 0x2098, 0x3400, 0x20a9, 0x0004,
-	0x53a3, 0x080c, 0x3d2c, 0xd794, 0x0148, 0xac80, 0x000a, 0x2098,
-	0x3400, 0x20a9, 0x0004, 0x53a3, 0x080c, 0x3d2c, 0x21a2, 0xd794,
-	0x01d8, 0xac80, 0x0000, 0x2098, 0x94a0, 0x20a9, 0x0002, 0x53a3,
-	0xac80, 0x0003, 0x20a6, 0x94a0, 0xac80, 0x0004, 0x2098, 0x3400,
-	0x20a9, 0x0002, 0x53a3, 0x080c, 0x3d1e, 0xac80, 0x0026, 0x2098,
-	0x20a9, 0x0002, 0x53a3, 0x0008, 0x94a0, 0xd794, 0x0110, 0xa6b0,
-	0x000b, 0xa6b0, 0x0005, 0x8108, 0x2001, 0xb635, 0x2004, 0xd0ac,
-	0x0118, 0xa186, 0x0100, 0x0040, 0xd78c, 0x0120, 0xa186, 0x0100,
-	0x0170, 0x0018, 0xa186, 0x007e, 0x0150, 0xd794, 0x0118, 0xa686,
-	0x0020, 0x0010, 0xa686, 0x0028, 0x0150, 0x0804, 0x4014, 0x86ff,
-	0x1120, 0x7120, 0x810b, 0x0804, 0x2fdf, 0x702f, 0x0001, 0x711e,
-	0x7020, 0xa600, 0x7022, 0x772a, 0x2061, 0xb6d2, 0x6007, 0x0000,
-	0x6612, 0x7024, 0x600e, 0x6226, 0x632a, 0x642e, 0x6532, 0x2c10,
-	0x080c, 0x1648, 0x7007, 0x0002, 0x701b, 0x40a7, 0x0005, 0x702c,
-	0xa005, 0x1170, 0x711c, 0x7024, 0x20a0, 0x7728, 0x2031, 0x0000,
-	0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c, 0x6530, 0x0804, 0x4014,
-	0x7120, 0x810b, 0x0804, 0x2fdf, 0x2029, 0x007e, 0x7924, 0x7a28,
-	0x7b2c, 0x7c38, 0xa184, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04,
-	0x3007, 0xa502, 0x0a04, 0x3007, 0xa184, 0x00ff, 0xa0e2, 0x0020,
-	0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa284, 0xff00, 0x8007,
-	0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa284,
-	0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007,
-	0xa384, 0xff00, 0x8007, 0xa0e2, 0x0020, 0x0a04, 0x3007, 0xa502,
-	0x0a04, 0x3007, 0xa384, 0x00ff, 0xa0e2, 0x0020, 0x0a04, 0x3007,
-	0xa502, 0x0a04, 0x3007, 0xa484, 0xff00, 0x8007, 0xa0e2, 0x0020,
-	0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0xa484, 0x00ff, 0xa0e2,
-	0x0020, 0x0a04, 0x3007, 0xa502, 0x0a04, 0x3007, 0x2061, 0xb8b9,
-	0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x2fdf, 0x0006, 0x2001,
-	0xb653, 0x2004, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672,
-	0x2004, 0xd0bc, 0x000e, 0x0005, 0x6168, 0x7a24, 0x6300, 0x82ff,
-	0x1118, 0x7926, 0x0804, 0x2fdf, 0x83ff, 0x1904, 0x3007, 0x2001,
-	0xfff0, 0xa200, 0x1a04, 0x3007, 0x2019, 0xffff, 0x606c, 0xa302,
-	0xa200, 0x0a04, 0x3007, 0x7926, 0x626a, 0x0804, 0x2fdf, 0x2001,
-	0xb600, 0x2004, 0xa086, 0x0003, 0x1904, 0x3004, 0x7c28, 0x7d24,
-	0x7e38, 0x7f2c, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x2009, 0x0000,
-	0x2019, 0x0000, 0x7023, 0x0000, 0x702f, 0x0000, 0xad80, 0x0003,
-	0x7026, 0x20a0, 0xa1e0, 0xb735, 0x2c64, 0x8cff, 0x01b8, 0x6004,
-	0xa084, 0x00ff, 0xa086, 0x0006, 0x0130, 0x6004, 0xa084, 0xff00,
-	0xa086, 0x0600, 0x1158, 0x6014, 0x20a2, 0x94a0, 0x6010, 0x8007,
-	0xa105, 0x8007, 0x20a2, 0x94a0, 0xa398, 0x0002, 0x8108, 0xa182,
-	0x00ff, 0x0120, 0xa386, 0x002a, 0x0148, 0x08e0, 0x83ff, 0x1120,
-	0x7120, 0x810c, 0x0804, 0x2fdf, 0x702f, 0x0001, 0x711e, 0x7020,
-	0xa300, 0x7022, 0x2061, 0xb6d2, 0x6007, 0x0000, 0x6312, 0x7024,
-	0x600e, 0x6426, 0x652a, 0x662e, 0x6732, 0x2c10, 0x080c, 0x1648,
-	0x7007, 0x0002, 0x701b, 0x419d, 0x0005, 0x702c, 0xa005, 0x1168,
-	0x711c, 0x7024, 0x20a0, 0x2019, 0x0000, 0x2061, 0xb6d2, 0x6424,
-	0x6528, 0x662c, 0x6730, 0x0804, 0x415a, 0x7120, 0x810c, 0x0804,
-	0x2fdf, 0x81ff, 0x1904, 0x3004, 0x60d4, 0xd0ac, 0x1118, 0xd09c,
-	0x0904, 0x3004, 0x080c, 0x3ebc, 0x0904, 0x3004, 0x7924, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x41c8, 0x0005,
-	0x00d6, 0xade8, 0x000d, 0x6828, 0xa0be, 0x7000, 0x0148, 0xa0be,
-	0x7100, 0x0130, 0xa0be, 0x7200, 0x0118, 0x00de, 0x0804, 0x3007,
-	0x6820, 0x6924, 0x080c, 0x2852, 0x1510, 0x080c, 0x4fbf, 0x11f8,
-	0x7122, 0x6612, 0x6516, 0x6e18, 0x00c6, 0x080c, 0x3ebc, 0x01b8,
-	0x080c, 0x3ebc, 0x01a0, 0x00ce, 0x00de, 0x6837, 0x0000, 0x6838,
-	0xc0fd, 0x683a, 0x6823, 0x0000, 0x6804, 0x2068, 0x080c, 0x9e7a,
-	0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x4202, 0x0005, 0x00de,
-	0x0804, 0x3004, 0x7120, 0x080c, 0x2dcc, 0x6820, 0xa086, 0x8001,
-	0x0904, 0x3004, 0x2d00, 0x701e, 0x6804, 0xa080, 0x0002, 0x0006,
-	0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4bf1, 0x000e, 0xade8,
-	0x000d, 0x6a08, 0x6b0c, 0x6c10, 0x6d14, 0x2061, 0xb6d2, 0x6007,
-	0x0000, 0x6e00, 0x6f28, 0xa7c6, 0x7000, 0x1108, 0x0018, 0xa7c6,
-	0x7100, 0x1140, 0xa6c2, 0x0004, 0x0a04, 0x3007, 0x2009, 0x0004,
-	0x0804, 0x3f00, 0xa7c6, 0x7200, 0x1904, 0x3007, 0xa6c2, 0x0054,
-	0x0a04, 0x3007, 0x600e, 0x6013, 0x002a, 0x6226, 0x632a, 0x642e,
-	0x6532, 0x2c10, 0x080c, 0x1648, 0x7007, 0x0002, 0x701b, 0x4249,
-	0x0005, 0x701c, 0x2068, 0x6804, 0xa080, 0x0001, 0x2004, 0xa080,
-	0x0002, 0x0006, 0x20a9, 0x002a, 0x2098, 0x20a0, 0x080c, 0x4bf1,
-	0x000e, 0x2009, 0x002a, 0x2061, 0xb6d2, 0x6224, 0x6328, 0x642c,
-	0x6530, 0x0804, 0x3f00, 0x81ff, 0x1904, 0x3004, 0x792c, 0x2001,
-	0xb8a0, 0x2102, 0x080c, 0x3ed1, 0x0904, 0x3007, 0x080c, 0x50e1,
-	0x0904, 0x3004, 0x0126, 0x2091, 0x8000, 0x080c, 0x5213, 0x012e,
-	0x0804, 0x2fdf, 0x7824, 0xd08c, 0x1118, 0xd084, 0x0904, 0x3a87,
-	0x080c, 0x3ee1, 0x0904, 0x3007, 0x00c6, 0x080c, 0x3ebc, 0x00ce,
-	0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa08e, 0x0005,
-	0x15b8, 0x7824, 0xd08c, 0x0120, 0x6000, 0xc08c, 0x6002, 0x0030,
-	0x2001, 0xb653, 0x2004, 0xd0b4, 0x0904, 0x3ac3, 0x7824, 0xa084,
-	0xff00, 0xa08e, 0x7e00, 0x0904, 0x3ac3, 0xa08e, 0x7f00, 0x0904,
-	0x3ac3, 0xa08e, 0x8000, 0x0904, 0x3ac3, 0x6000, 0xd08c, 0x1904,
-	0x3ac3, 0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x080c, 0x9e96,
-	0x1120, 0x2009, 0x0003, 0x0804, 0x3004, 0x7007, 0x0003, 0x701b,
-	0x42ca, 0x0005, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x0804, 0x3ac3,
-	0x2009, 0xb631, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
-	0x3004, 0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x0120, 0x2009,
-	0x0007, 0x0804, 0x3004, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x0120,
-	0x2009, 0x0008, 0x0804, 0x3004, 0x609c, 0xd0a4, 0x1118, 0xd0ac,
-	0x1904, 0x3ac3, 0x6837, 0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd,
-	0x683a, 0x080c, 0x9f27, 0x1120, 0x2009, 0x0003, 0x0804, 0x3004,
-	0x7007, 0x0003, 0x701b, 0x4305, 0x0005, 0x6830, 0xa086, 0x0100,
-	0x1120, 0x2009, 0x0004, 0x0804, 0x3004, 0x080c, 0x3ee1, 0x0904,
-	0x3007, 0x0804, 0x4299, 0x81ff, 0x2009, 0x0001, 0x1904, 0x3004,
-	0x6000, 0xa086, 0x0003, 0x2009, 0x0007, 0x1904, 0x3004, 0x2001,
-	0xb653, 0x2004, 0xd0ac, 0x2009, 0x0008, 0x1904, 0x3004, 0x080c,
-	0x3ee1, 0x0904, 0x3007, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0006,
-	0x2009, 0x0009, 0x1904, 0x3004, 0x00c6, 0x080c, 0x3ebc, 0x00ce,
-	0x2009, 0x0002, 0x0904, 0x3004, 0x6837, 0x0000, 0x6833, 0x0000,
-	0x6838, 0xc0fd, 0x683a, 0x7928, 0xa194, 0xff00, 0xa18c, 0x00ff,
-	0xa006, 0x82ff, 0x1128, 0xc0ed, 0x6952, 0x792c, 0x6956, 0x0048,
-	0xa28e, 0x0100, 0x1904, 0x3007, 0xc0e5, 0x6853, 0x0000, 0x6857,
-	0x0000, 0x683e, 0x080c, 0xa0e4, 0x2009, 0x0003, 0x0904, 0x3004,
-	0x7007, 0x0003, 0x701b, 0x4365, 0x0005, 0x6830, 0xa086, 0x0100,
-	0x2009, 0x0004, 0x0904, 0x3004, 0x0804, 0x2fdf, 0x81ff, 0x2009,
-	0x0001, 0x1904, 0x3004, 0x6000, 0xa086, 0x0003, 0x2009, 0x0007,
-	0x1904, 0x3004, 0x080c, 0x3ee1, 0x0904, 0x3007, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x2009, 0x0009, 0x1904, 0x3004, 0x00c6,
-	0x080c, 0x3ebc, 0x00ce, 0x2009, 0x0002, 0x0904, 0x3004, 0xad80,
-	0x000f, 0x2009, 0x0008, 0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c,
-	0x3efd, 0x701b, 0x439c, 0x0005, 0x00d6, 0xade8, 0x000f, 0x6800,
-	0xa086, 0x0500, 0x1140, 0x6804, 0xa005, 0x1128, 0x6808, 0xa084,
-	0xff00, 0x1108, 0x0018, 0x00de, 0x1904, 0x3007, 0x00de, 0x6837,
-	0x0000, 0x6833, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x00c6, 0x080c,
-	0x3ee1, 0x1118, 0x00ce, 0x0804, 0x3007, 0x080c, 0xa133, 0x2009,
-	0x0003, 0x00ce, 0x0904, 0x3004, 0x7007, 0x0003, 0x701b, 0x43c9,
-	0x0005, 0x6830, 0xa086, 0x0100, 0x2009, 0x0004, 0x0904, 0x3004,
-	0x0804, 0x2fdf, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x3004,
-	0x6000, 0xa086, 0x0003, 0x0120, 0x2009, 0x0007, 0x0804, 0x3004,
-	0x7e24, 0x860f, 0xa18c, 0x00ff, 0xa6b4, 0x00ff, 0x080c, 0x501b,
-	0x1904, 0x3007, 0xa186, 0x007f, 0x0150, 0x6004, 0xa084, 0x00ff,
-	0xa086, 0x0006, 0x0120, 0x2009, 0x0009, 0x0804, 0x3004, 0x00c6,
-	0x080c, 0x3ebc, 0x00ce, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004,
-	0x6837, 0x0000, 0x6838, 0xc0fd, 0x683a, 0x2001, 0x0100, 0x8007,
-	0x680a, 0x080c, 0x9eb1, 0x1120, 0x2009, 0x0003, 0x0804, 0x3004,
-	0x7007, 0x0003, 0x701b, 0x4415, 0x0005, 0x6808, 0x8007, 0xa086,
-	0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x3004, 0x68b0, 0x6836,
-	0x6810, 0x8007, 0xa084, 0x00ff, 0x800c, 0x6814, 0x8007, 0xa084,
-	0x00ff, 0x8004, 0xa080, 0x0002, 0xa108, 0xad80, 0x0004, 0x7a2c,
-	0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x080c, 0x3ebc, 0x1120,
-	0x2009, 0x0002, 0x0804, 0x3004, 0x7924, 0xa194, 0xff00, 0xa18c,
-	0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3007, 0x2009, 0x001a,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x080c, 0x3efd, 0x701b, 0x4451,
-	0x0005, 0x2001, 0xb62a, 0x2003, 0x0001, 0xad80, 0x000d, 0x2098,
-	0x20a9, 0x001a, 0x20a1, 0xb8c7, 0x53a3, 0x0804, 0x2fdf, 0x080c,
-	0x3ebc, 0x1120, 0x2009, 0x0002, 0x0804, 0x3004, 0x7924, 0xa194,
-	0xff00, 0xa18c, 0x00ff, 0x8217, 0x82ff, 0x0110, 0x0804, 0x3007,
-	0x2099, 0xb8c7, 0x20a0, 0x20a9, 0x001a, 0x53a3, 0x2009, 0x001a,
-	0x7a2c, 0x7b28, 0x7c3c, 0x7d38, 0x0804, 0x3f00, 0x7824, 0xa08a,
-	0x1000, 0x1a04, 0x3007, 0x0126, 0x2091, 0x8000, 0x8003, 0x800b,
-	0x810b, 0xa108, 0x00c6, 0x2061, 0xb8f4, 0x6142, 0x00ce, 0x012e,
-	0x0804, 0x2fdf, 0x00c6, 0x080c, 0x5b41, 0x1188, 0x2001, 0xb89f,
-	0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085, 0x0001,
-	0x080c, 0x5b85, 0x080c, 0x5a79, 0x080c, 0x151a, 0x0038, 0x2061,
-	0xb600, 0x6030, 0xc09d, 0x6032, 0x080c, 0x4b7b, 0x00ce, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0xb8f4, 0x7924, 0x6152,
-	0x614e, 0x6057, 0x0000, 0x604b, 0x0009, 0x7838, 0x606a, 0x783c,
-	0x6066, 0x7828, 0x6062, 0x782c, 0x605e, 0x2061, 0xb8a1, 0x2001,
-	0xb909, 0x600e, 0x6013, 0x0001, 0x6017, 0x0002, 0x6007, 0x0000,
-	0x6037, 0x0000, 0x00ce, 0x012e, 0x0804, 0x2fdf, 0x0126, 0x00c6,
-	0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x6044, 0xd0a4, 0x11b0,
-	0xd084, 0x0118, 0x080c, 0x464d, 0x0068, 0xd08c, 0x0118, 0x080c,
-	0x456e, 0x0040, 0xd094, 0x0118, 0x080c, 0x453f, 0x0018, 0xd09c,
-	0x0108, 0x0061, 0x00ee, 0x00ce, 0x012e, 0x0005, 0x0016, 0x6128,
-	0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0ca0, 0x624c, 0xa286,
-	0xf0f0, 0x1150, 0x6048, 0xa086, 0xf0f0, 0x0130, 0x624a, 0x6043,
-	0x0090, 0x6043, 0x0010, 0x0490, 0xa294, 0xff00, 0xa296, 0xf700,
-	0x0178, 0x7134, 0xd1a4, 0x1160, 0x6240, 0xa295, 0x0100, 0x6242,
-	0xa294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x00f0,
-	0x6040, 0xa084, 0x0010, 0xa085, 0x0140, 0x6042, 0x6043, 0x0000,
-	0x707b, 0x0000, 0x7097, 0x0001, 0x70bb, 0x0000, 0x70d7, 0x0000,
-	0x2009, 0xbdc0, 0x200b, 0x0000, 0x708b, 0x0000, 0x707f, 0x000a,
-	0x2009, 0x000a, 0x2011, 0x4b1c, 0x080c, 0x6a94, 0x0005, 0x0156,
-	0x2001, 0xb674, 0x2004, 0xd08c, 0x0110, 0x7053, 0xffff, 0x707c,
-	0xa005, 0x1510, 0x2011, 0x4b1c, 0x080c, 0x6a0e, 0x6040, 0xa094,
-	0x0010, 0xa285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c,
-	0x1168, 0x1f04, 0x4556, 0x6242, 0x708f, 0x0000, 0x6040, 0xa094,
-	0x0010, 0xa285, 0x0080, 0x6042, 0x6242, 0x0030, 0x6242, 0x708f,
-	0x0000, 0x7083, 0x0000, 0x0000, 0x015e, 0x0005, 0x7080, 0xa08a,
-	0x0003, 0x1210, 0x0023, 0x0010, 0x080c, 0x151a, 0x0005, 0x457a,
-	0x45ca, 0x464c, 0x00f6, 0x7083, 0x0001, 0x20e1, 0xa000, 0xe000,
-	0x20e1, 0x8700, 0x080c, 0x24a5, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x2079, 0xbc00, 0x207b, 0x2200, 0x7807, 0x00ef, 0x780b, 0x0000,
-	0x780f, 0x00ef, 0x7813, 0x0138, 0x7817, 0x0000, 0x781b, 0x0000,
-	0x781f, 0x0000, 0x7823, 0xffff, 0x7827, 0xffff, 0x782b, 0x0000,
-	0x782f, 0x0000, 0x2079, 0xbc0c, 0x207b, 0x1101, 0x7807, 0x0000,
-	0x2099, 0xb605, 0x20a1, 0xbc0e, 0x20a9, 0x0004, 0x53a3, 0x2079,
-	0xbc12, 0x207b, 0x0000, 0x7807, 0x0000, 0x2099, 0xbc00, 0x20a1,
-	0x020b, 0x20a9, 0x0014, 0x53a6, 0x60c3, 0x000c, 0x600f, 0x0000,
-	0x080c, 0x4b55, 0x00fe, 0x7087, 0x0000, 0x6043, 0x0008, 0x6043,
-	0x0000, 0x0005, 0x00d6, 0x7084, 0x7087, 0x0000, 0xa025, 0x0904,
-	0x4634, 0x6020, 0xd0b4, 0x1904, 0x4632, 0x7194, 0x81ff, 0x0904,
-	0x4622, 0xa486, 0x000c, 0x1904, 0x462d, 0xa480, 0x0018, 0x8004,
-	0x20a8, 0x2011, 0xbc80, 0x2019, 0xbc00, 0x220c, 0x2304, 0xa106,
-	0x11b8, 0x8210, 0x8318, 0x1f04, 0x45e5, 0x6043, 0x0004, 0x608b,
-	0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0006, 0x7083, 0x0002, 0x708f,
-	0x0002, 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a94, 0x0490,
-	0x2069, 0xbc80, 0x6930, 0xa18e, 0x1101, 0x1538, 0x6834, 0xa005,
-	0x1520, 0x6900, 0xa18c, 0x00ff, 0x1118, 0x6804, 0xa005, 0x0190,
-	0x2011, 0xbc8e, 0x2019, 0xb605, 0x20a9, 0x0004, 0x220c, 0x2304,
-	0xa102, 0x0230, 0x1190, 0x8210, 0x8318, 0x1f04, 0x4616, 0x0068,
-	0x7097, 0x0000, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80,
-	0x20a1, 0x020b, 0x20a9, 0x0014, 0x53a6, 0x6043, 0x0008, 0x6043,
-	0x0000, 0x0010, 0x00de, 0x0005, 0x6040, 0xa085, 0x0100, 0x6042,
-	0x6020, 0xd0b4, 0x1db8, 0x60c3, 0x000c, 0x2011, 0xb8eb, 0x2013,
-	0x0000, 0x7087, 0x0000, 0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7,
-	0x9575, 0x080c, 0x7dea, 0x0c30, 0x0005, 0x708c, 0xa08a, 0x001d,
-	0x1210, 0x0023, 0x0010, 0x080c, 0x151a, 0x0005, 0x4680, 0x468f,
-	0x46b7, 0x46d0, 0x46f4, 0x471c, 0x4740, 0x4771, 0x4795, 0x47bd,
-	0x47f4, 0x481c, 0x4838, 0x484e, 0x486e, 0x4881, 0x4889, 0x48b9,
-	0x48dd, 0x4905, 0x4929, 0x495a, 0x4997, 0x49c6, 0x49e2, 0x4a21,
-	0x4a41, 0x4a5a, 0x4a5b, 0x00c6, 0x2061, 0xb600, 0x6003, 0x0007,
-	0x2061, 0x0100, 0x6004, 0xa084, 0xfff9, 0x6006, 0x00ce, 0x0005,
-	0x608b, 0xbc94, 0x608f, 0xf0f0, 0x6043, 0x0002, 0x708f, 0x0001,
-	0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a94, 0x0005, 0x00f6,
-	0x7084, 0xa086, 0x0014, 0x1508, 0x6043, 0x0000, 0x6020, 0xd0b4,
-	0x11e0, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1102, 0x11a0, 0x7834,
-	0xa005, 0x1188, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110,
-	0x70bb, 0x0001, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x708f, 0x0010,
-	0x080c, 0x4889, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f,
-	0x0003, 0x6043, 0x0004, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x080c,
-	0x4bf9, 0x20a3, 0x1102, 0x20a3, 0x0000, 0x20a9, 0x000a, 0x20a3,
-	0x0000, 0x1f04, 0x46c7, 0x60c3, 0x0014, 0x080c, 0x4b55, 0x0005,
-	0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c, 0x6a0e,
-	0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1102,
-	0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8,
-	0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0004, 0x0029, 0x0010,
-	0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0005, 0x080c, 0x4bf9,
-	0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbc8e, 0x080c,
-	0x4c4a, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186, 0xffff,
-	0x0128, 0x080c, 0x4ae7, 0x0110, 0x080c, 0x4c28, 0x20a9, 0x0008,
-	0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0014, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0,
-	0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079,
-	0xbc80, 0x7a30, 0xa296, 0x1103, 0x1178, 0x7834, 0xa005, 0x1160,
-	0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001,
-	0x708f, 0x0006, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005,
-	0x708f, 0x0007, 0x080c, 0x4bf9, 0x20a3, 0x1104, 0x20a3, 0x0000,
-	0x3430, 0x2011, 0xbc8e, 0x080c, 0x4c4a, 0x11a8, 0x7078, 0xa005,
-	0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2df9, 0x200d,
-	0xa18c, 0xff00, 0x810f, 0x080c, 0x4ae7, 0x0128, 0x080c, 0x411d,
-	0x0110, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2298, 0x26a0, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c, 0x4b55,
-	0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c,
-	0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296,
-	0x1104, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128,
-	0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0008, 0x0029,
-	0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0009, 0x080c,
-	0x4bf9, 0x20a3, 0x1105, 0x20a3, 0x0100, 0x3430, 0x080c, 0x4c4a,
-	0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a5c, 0x1170, 0xa085,
-	0x0001, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2099, 0xbc8e, 0x26a0,
-	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c,
-	0x4b55, 0x0010, 0x080c, 0x4673, 0x0005, 0x00f6, 0x7084, 0xa005,
-	0x0588, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x1540,
-	0x2079, 0xbc80, 0x7a30, 0xa296, 0x1105, 0x1510, 0x7834, 0x2011,
-	0x0100, 0xa21e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005,
-	0x1110, 0x70bb, 0x0001, 0x708f, 0x000a, 0x00b1, 0x0098, 0xa005,
-	0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb,
-	0x0001, 0x708b, 0x0000, 0x708f, 0x000e, 0x080c, 0x486e, 0x0010,
-	0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x000b, 0x2011, 0xbc0e,
-	0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff, 0x43a4, 0x20a9, 0x0002,
-	0x2009, 0x0000, 0x41a4, 0x080c, 0x4bf9, 0x20a3, 0x1106, 0x20a3,
-	0x0000, 0x080c, 0x4c4a, 0x0118, 0x2013, 0x0000, 0x0020, 0x7054,
-	0xa085, 0x0100, 0x2012, 0x2298, 0x20a9, 0x0042, 0x53a6, 0x60c3,
-	0x0084, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x01b0,
-	0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084, 0x1168, 0x2079,
-	0xbc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834, 0xa005, 0x1120,
-	0x708f, 0x000c, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005,
-	0x708f, 0x000d, 0x080c, 0x4bf9, 0x20a3, 0x1107, 0x20a3, 0x0000,
-	0x2099, 0xbc8e, 0x20a9, 0x0040, 0x53a6, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0084, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084,
-	0xa005, 0x01d0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084,
-	0x1188, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1107, 0x1158, 0x7834,
-	0xa005, 0x1140, 0x708b, 0x0001, 0x080c, 0x4beb, 0x708f, 0x000e,
-	0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x000f,
-	0x7087, 0x0000, 0x608b, 0xbc85, 0x608f, 0xb5b5, 0x6043, 0x0005,
-	0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x4b23, 0x080c, 0x6a02,
-	0x0005, 0x7084, 0xa005, 0x0120, 0x2011, 0x4b23, 0x080c, 0x6a0e,
-	0x0005, 0x708f, 0x0011, 0x080c, 0x4c4a, 0x11a0, 0x7170, 0x81ff,
-	0x0188, 0x2009, 0x0000, 0x7074, 0xa084, 0x00ff, 0x080c, 0x2852,
-	0xa186, 0x007e, 0x0138, 0xa186, 0x0080, 0x0120, 0x2011, 0xbc8e,
-	0x080c, 0x4ae7, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80,
-	0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007, 0xa084,
-	0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0014, 0x080c, 0x4b55,
-	0x0005, 0x00f6, 0x7084, 0xa005, 0x01f0, 0x2011, 0x4b23, 0x080c,
-	0x6a0e, 0xa086, 0x0014, 0x11a8, 0x2079, 0xbc80, 0x7a30, 0xa296,
-	0x1103, 0x1178, 0x7834, 0xa005, 0x1160, 0x7a38, 0xd2fc, 0x0128,
-	0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001, 0x708f, 0x0012, 0x0029,
-	0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x708f, 0x0013, 0x080c,
-	0x4c05, 0x20a3, 0x1103, 0x20a3, 0x0000, 0x3430, 0x2011, 0xbc8e,
-	0x080c, 0x4c4a, 0x1160, 0x7078, 0xa005, 0x1148, 0x7150, 0xa186,
-	0xffff, 0x0128, 0x080c, 0x4ae7, 0x0110, 0x080c, 0x4c28, 0x20a9,
-	0x0008, 0x2298, 0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x080c, 0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005,
-	0x01f0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0014, 0x11a8,
-	0x2079, 0xbc80, 0x7a30, 0xa296, 0x1104, 0x1178, 0x7834, 0xa005,
-	0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb,
-	0x0001, 0x708f, 0x0014, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe,
-	0x0005, 0x708f, 0x0015, 0x080c, 0x4c05, 0x20a3, 0x1104, 0x20a3,
-	0x0000, 0x3430, 0x2011, 0xbc8e, 0x080c, 0x4c4a, 0x11a8, 0x7078,
-	0xa005, 0x1190, 0x7158, 0xa186, 0xffff, 0x0170, 0xa180, 0x2df9,
-	0x200d, 0xa18c, 0xff00, 0x810f, 0x080c, 0x4ae7, 0x0128, 0x080c,
-	0x411d, 0x0110, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2298, 0x26a0,
-	0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014, 0x080c,
-	0x4b55, 0x0005, 0x00f6, 0x7084, 0xa005, 0x05b8, 0x2011, 0x4b23,
-	0x080c, 0x6a0e, 0xa086, 0x0014, 0x1570, 0x2079, 0xbc80, 0x7a30,
-	0xa296, 0x1105, 0x1540, 0x7834, 0x2011, 0x0100, 0xa21e, 0x1148,
-	0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005, 0x1110, 0x70bb, 0x0001,
-	0x0060, 0xa005, 0x11c0, 0x7a38, 0xd2fc, 0x0128, 0x70b8, 0xa005,
-	0x1110, 0x70bb, 0x0001, 0x708b, 0x0000, 0x7a38, 0xd2f4, 0x0138,
-	0x2001, 0xb674, 0x2004, 0xd0a4, 0x1110, 0x70d7, 0x0008, 0x708f,
-	0x0016, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe, 0x0005, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x2099, 0xbc80, 0x20a1, 0x020b, 0x20a9,
-	0x000e, 0x53a6, 0x3430, 0x2011, 0xbc8e, 0x708f, 0x0017, 0x080c,
-	0x4c4a, 0x1150, 0x7078, 0xa005, 0x1138, 0x080c, 0x4a5c, 0x1170,
-	0xa085, 0x0001, 0x080c, 0x289c, 0x20a9, 0x0008, 0x2099, 0xbc8e,
-	0x26a0, 0x53a6, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0014,
-	0x080c, 0x4b55, 0x0010, 0x080c, 0x4673, 0x0005, 0x00f6, 0x7084,
-	0xa005, 0x01b0, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0xa086, 0x0084,
-	0x1168, 0x2079, 0xbc80, 0x7a30, 0xa296, 0x1106, 0x1138, 0x7834,
-	0xa005, 0x1120, 0x708f, 0x0018, 0x0029, 0x0010, 0x080c, 0x4b7b,
-	0x00fe, 0x0005, 0x708f, 0x0019, 0x080c, 0x4c05, 0x20a3, 0x1106,
-	0x20a3, 0x0000, 0x3430, 0x2099, 0xbc8e, 0x2039, 0xbc0e, 0x27a0,
-	0x20a9, 0x0040, 0x53a3, 0x080c, 0x4c4a, 0x11e8, 0x2728, 0x2514,
-	0x8207, 0xa084, 0x00ff, 0x8000, 0x2018, 0xa294, 0x00ff, 0x8007,
-	0xa205, 0x202a, 0x7054, 0x2310, 0x8214, 0xa2a0, 0xbc0e, 0x2414,
-	0xa38c, 0x0001, 0x0118, 0xa294, 0xff00, 0x0018, 0xa294, 0x00ff,
-	0x8007, 0xa215, 0x2222, 0x2798, 0x26a0, 0x20a9, 0x0040, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0084, 0x080c, 0x4b55,
-	0x0005, 0x00f6, 0x7084, 0xa005, 0x01d0, 0x2011, 0x4b23, 0x080c,
-	0x6a0e, 0xa086, 0x0084, 0x1188, 0x2079, 0xbc80, 0x7a30, 0xa296,
-	0x1107, 0x1158, 0x7834, 0xa005, 0x1140, 0x708b, 0x0001, 0x080c,
-	0x4beb, 0x708f, 0x001a, 0x0029, 0x0010, 0x080c, 0x4b7b, 0x00fe,
-	0x0005, 0x708f, 0x001b, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099,
-	0xbc80, 0x20a1, 0x020b, 0x7484, 0xa480, 0x0018, 0xa080, 0x0007,
-	0xa084, 0x03f8, 0x8004, 0x20a8, 0x53a6, 0x60c3, 0x0084, 0x080c,
-	0x4b55, 0x0005, 0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0xb653,
-	0x252c, 0x20a9, 0x0008, 0x2041, 0xbc0e, 0x28a0, 0x2099, 0xbc8e,
-	0x53a3, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0110, 0x2011,
-	0x0000, 0x2800, 0xa200, 0x200c, 0xa1a6, 0xffff, 0x1148, 0xd5d4,
-	0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x4a71, 0x0804, 0x4adf,
-	0x82ff, 0x1160, 0xd5d4, 0x0120, 0xa1a6, 0x3fff, 0x0d90, 0x0020,
-	0xa1a6, 0x3fff, 0x0904, 0x4adf, 0xa18d, 0xc000, 0x20a9, 0x0010,
-	0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4,
-	0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319,
-	0x0008, 0x8318, 0x1f04, 0x4a97, 0x04d0, 0x23a8, 0x2021, 0x0001,
-	0x8426, 0x8425, 0x1f04, 0x4aa9, 0x2328, 0x8529, 0xa2be, 0x0007,
-	0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0xa73a, 0x000e, 0x27a8,
-	0xa5a8, 0x0010, 0x1f04, 0x4ab8, 0x7552, 0xa5c8, 0x2df9, 0x292d,
-	0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c,
-	0x287c, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0xa405,
-	0x201a, 0x707b, 0x0001, 0x26a0, 0x2898, 0x20a9, 0x0008, 0x53a6,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0xa085, 0x0001, 0x0028, 0xa006,
-	0x0018, 0xa006, 0x080c, 0x151a, 0x009e, 0x008e, 0x0005, 0x2118,
-	0x2021, 0x0000, 0x2001, 0x0007, 0xa39a, 0x0010, 0x0218, 0x8420,
-	0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0xa39a, 0x0010, 0x8421,
-	0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319, 0x1de8,
-	0xa238, 0x2704, 0xa42c, 0x11b8, 0xa405, 0x203a, 0x7152, 0xa1a0,
-	0x2df9, 0x242d, 0xa5ac, 0x00ff, 0x7576, 0x6532, 0x6536, 0x0016,
-	0x2508, 0x080c, 0x287c, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x707b,
-	0x0001, 0xa084, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb600, 0x707f,
-	0x0000, 0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071,
-	0x0140, 0x080c, 0x4c61, 0x080c, 0x7df3, 0x7004, 0xa084, 0x4000,
-	0x0120, 0x7003, 0x1000, 0x7003, 0x0000, 0x0126, 0x2091, 0x8000,
-	0x2071, 0xb623, 0x2073, 0x0000, 0x7840, 0x0026, 0x0016, 0x2009,
-	0x00f7, 0x080c, 0x4c11, 0x001e, 0xa094, 0x0010, 0xa285, 0x0080,
-	0x7842, 0x7a42, 0x2009, 0x1388, 0x2011, 0x5a14, 0x080c, 0x6a94,
-	0x002e, 0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x2011, 0xb8eb, 0x2013, 0x0000, 0x7087, 0x0000, 0x012e, 0x20e1,
-	0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0x7dea, 0x6144,
-	0xd184, 0x0120, 0x718c, 0xa18d, 0x2000, 0x0018, 0x7180, 0xa18d,
-	0x1000, 0x2011, 0xb8bf, 0x2112, 0x2009, 0x07d0, 0x2011, 0x4b23,
-	0x080c, 0x6a94, 0x0005, 0x0016, 0x0026, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c,
-	0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b,
-	0x003e, 0x2009, 0x00f7, 0x080c, 0x4c11, 0x2061, 0xb8f4, 0x601b,
-	0x0000, 0x601f, 0x0000, 0x2061, 0xb600, 0x6003, 0x0001, 0x2061,
-	0x0100, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0xb8bf, 0x200b,
-	0x0000, 0x2009, 0x002d, 0x2011, 0x4bb4, 0x080c, 0x6a02, 0x012e,
-	0x00ce, 0x002e, 0x001e, 0x0005, 0x00e6, 0x0006, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x4c61, 0x2071, 0x0100, 0x080c, 0x7df3, 0x2071,
-	0x0140, 0x7004, 0xa084, 0x4000, 0x0120, 0x7003, 0x1000, 0x7003,
-	0x0000, 0x080c, 0x5b49, 0x01a8, 0x080c, 0x5b67, 0x1190, 0x2001,
-	0xb89e, 0x2003, 0xaaaa, 0x0016, 0x080c, 0x2920, 0x2001, 0xb88f,
-	0x2102, 0x001e, 0x2001, 0xb89f, 0x2003, 0x0000, 0x080c, 0x5a79,
-	0x0030, 0x2001, 0x0001, 0x080c, 0x27f8, 0x080c, 0x4b7b, 0x012e,
-	0x000e, 0x00ee, 0x0005, 0x20a9, 0x0040, 0x20a1, 0xbdc0, 0x2099,
-	0xbc8e, 0x3304, 0x8007, 0x20a2, 0x9398, 0x94a0, 0x1f04, 0x4bf1,
-	0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x2099, 0xbc00, 0x20a1,
-	0x020b, 0x20a9, 0x000c, 0x53a6, 0x0005, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x2099, 0xbc80, 0x20a1, 0x020b, 0x20a9, 0x000c, 0x53a6,
-	0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0xb631,
-	0x2004, 0xa005, 0x1138, 0x2001, 0xb615, 0x2004, 0xa084, 0x00ff,
-	0xa105, 0x0010, 0xa185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005,
-	0x0016, 0x0046, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0158, 0xa006,
-	0x2020, 0x2009, 0x002a, 0x080c, 0xb1a4, 0x2001, 0xb60c, 0x200c,
-	0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0000, 0x080c, 0x2ca4,
-	0x004e, 0x001e, 0x0005, 0x080c, 0x4b7b, 0x708f, 0x0000, 0x7087,
-	0x0000, 0x0005, 0x0006, 0x2001, 0xb60c, 0x2004, 0xd09c, 0x0100,
-	0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001,
-	0x0101, 0x200c, 0xa18d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e,
-	0x0005, 0x2001, 0xb60d, 0x2004, 0xd0bc, 0x0158, 0x0026, 0x0036,
-	0x2011, 0x8017, 0x2001, 0xb8bf, 0x201c, 0x080c, 0x3f13, 0x003e,
-	0x002e, 0x0005, 0x0156, 0x20a9, 0x00ff, 0x2009, 0xb735, 0xa006,
-	0x200a, 0x8108, 0x1f04, 0x4c78, 0x015e, 0x0005, 0x00d6, 0x0036,
-	0x0156, 0x0136, 0x0146, 0x2069, 0xb652, 0xa006, 0x6002, 0x6007,
-	0x0707, 0x600a, 0x600e, 0x6012, 0xa198, 0x2df9, 0x231d, 0xa39c,
-	0x00ff, 0x6316, 0x20a9, 0x0004, 0xac98, 0x0006, 0x23a0, 0x40a4,
-	0x20a9, 0x0004, 0xac98, 0x000a, 0x23a0, 0x40a4, 0x603e, 0x6042,
-	0x604e, 0x6052, 0x6056, 0x605a, 0x605e, 0x6062, 0x6066, 0x606a,
-	0x606e, 0x6072, 0x6076, 0x607a, 0x607e, 0x6082, 0x6086, 0x608a,
-	0x608e, 0x6092, 0x6096, 0x609a, 0x609e, 0x60ae, 0x61a2, 0x00d6,
-	0x60a4, 0xa06d, 0x0110, 0x080c, 0x1614, 0x60a7, 0x0000, 0x60a8,
-	0xa06d, 0x0110, 0x080c, 0x1614, 0x60ab, 0x0000, 0x00de, 0xa006,
-	0x604a, 0x6810, 0x603a, 0x680c, 0x6046, 0x6814, 0xa084, 0x00ff,
-	0x6042, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082, 0x4000,
-	0x1a04, 0x4d8c, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x1a04,
-	0x4d91, 0x2001, 0xb60c, 0x2004, 0xa084, 0x0003, 0x01c0, 0x2001,
-	0xb60c, 0x2004, 0xd084, 0x1904, 0x4d74, 0xa188, 0xb735, 0x2104,
-	0xa065, 0x0904, 0x4d74, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006,
-	0x1904, 0x4d74, 0x6000, 0xd0c4, 0x0904, 0x4d74, 0x0068, 0xa188,
-	0xb735, 0x2104, 0xa065, 0x0904, 0x4d59, 0x6004, 0xa084, 0x00ff,
-	0xa08e, 0x0006, 0x1904, 0x4d5e, 0x60a4, 0xa00d, 0x0118, 0x080c,
-	0x5246, 0x05d0, 0x60a8, 0xa00d, 0x0188, 0x080c, 0x5291, 0x1170,
-	0x694c, 0xd1fc, 0x1118, 0x080c, 0x4f50, 0x0448, 0x080c, 0x4eff,
-	0x694c, 0xd1ec, 0x1520, 0x080c, 0x5138, 0x0408, 0x694c, 0xa184,
-	0xa000, 0x0178, 0xd1ec, 0x0140, 0xd1fc, 0x0118, 0x080c, 0x5147,
-	0x0028, 0x080c, 0x5147, 0x0028, 0xd1fc, 0x0118, 0x080c, 0x4eff,
-	0x0070, 0x6050, 0xa00d, 0x0130, 0x2d00, 0x200a, 0x6803, 0x0000,
-	0x6052, 0x0028, 0x2d00, 0x6052, 0x604e, 0x6803, 0x0000, 0x080c,
-	0x6d1c, 0xa006, 0x012e, 0x0005, 0x2001, 0x0005, 0x2009, 0x0000,
-	0x04e0, 0x2001, 0x0028, 0x2009, 0x0000, 0x04b8, 0xa082, 0x0006,
-	0x1298, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc,
-	0x1140, 0x6100, 0xd1fc, 0x0128, 0x2001, 0x0029, 0x2009, 0x1000,
-	0x0420, 0x2001, 0x0028, 0x00a8, 0x2009, 0xb60c, 0x210c, 0xd18c,
-	0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118, 0x2001, 0x0004,
-	0x0040, 0x2001, 0x0029, 0x6100, 0xd1fc, 0x0118, 0x2009, 0x1000,
-	0x0060, 0x2009, 0x0000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000,
-	0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x012e, 0x0005,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x6844, 0x8007, 0xa084, 0x00ff,
-	0x2008, 0xa182, 0x00ff, 0x1a04, 0x4deb, 0xa188, 0xb735, 0x2104,
-	0xa065, 0x01c0, 0x6004, 0xa084, 0x00ff, 0xa08e, 0x0006, 0x11a8,
-	0x2c70, 0x080c, 0x864e, 0x05e8, 0x2e00, 0x601a, 0x2d00, 0x6012,
-	0x600b, 0xffff, 0x601f, 0x000a, 0x2009, 0x0003, 0x080c, 0x86d3,
-	0xa006, 0x0460, 0x2001, 0x0028, 0x0440, 0xa082, 0x0006, 0x1298,
-	0x2001, 0xb635, 0x2004, 0xd0ac, 0x1158, 0x60a0, 0xd0bc, 0x1140,
-	0x6100, 0xd1fc, 0x09e8, 0x2001, 0x0029, 0x2009, 0x1000, 0x00a8,
-	0x2001, 0x0028, 0x0090, 0x2009, 0xb60c, 0x210c, 0xd18c, 0x0118,
-	0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001, 0x0004, 0x0028,
-	0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0xa005, 0x012e, 0x00ee,
-	0x0005, 0x2001, 0x002c, 0x0cc8, 0x00f6, 0x00e6, 0x0126, 0x2091,
-	0x8000, 0x2011, 0x0000, 0x2079, 0xb600, 0x6944, 0xa18c, 0xff00,
-	0x810f, 0xa182, 0x00ff, 0x1a04, 0x4eb6, 0x080c, 0x501b, 0x11a0,
-	0x6004, 0xa084, 0x00ff, 0xa082, 0x0006, 0x1270, 0x6864, 0xa0c6,
-	0x006f, 0x0150, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1904, 0x4e9f,
-	0x60a0, 0xd0bc, 0x1904, 0x4e9f, 0x6864, 0xa0c6, 0x006f, 0x0118,
-	0x2008, 0x0804, 0x4e68, 0x6968, 0x2140, 0xa18c, 0xff00, 0x810f,
-	0x78d4, 0xd0ac, 0x1118, 0xa182, 0x0080, 0x06d0, 0xa182, 0x00ff,
-	0x16b8, 0x6a70, 0x6b6c, 0x7870, 0xa306, 0x1160, 0x7874, 0xa24e,
-	0x1118, 0x2208, 0x2310, 0x0460, 0xa9cc, 0xff00, 0x1118, 0x2208,
-	0x2310, 0x0430, 0x080c, 0x3e0c, 0x2c70, 0x0550, 0x2009, 0x0000,
-	0x2011, 0x0000, 0xa0c6, 0x4000, 0x1160, 0x0006, 0x2e60, 0x080c,
-	0x52bc, 0x1108, 0xc185, 0x7000, 0xd0bc, 0x0108, 0xc18d, 0x000e,
-	0x0088, 0xa0c6, 0x4007, 0x1110, 0x2408, 0x0060, 0xa0c6, 0x4008,
-	0x1118, 0x2708, 0x2610, 0x0030, 0xa0c6, 0x4009, 0x1108, 0x0010,
-	0x2001, 0x4006, 0x6866, 0x696a, 0x6a6e, 0x2001, 0x0030, 0x0450,
-	0x080c, 0x864e, 0x1138, 0x2001, 0x4005, 0x2009, 0x0003, 0x2011,
-	0x0000, 0x0c80, 0x2e00, 0x601a, 0x080c, 0xa0e3, 0x2d00, 0x6012,
-	0x601f, 0x0001, 0x6838, 0xd88c, 0x0108, 0xc0f5, 0x683a, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x2cd1, 0x012e, 0x2001, 0x0000, 0x080c,
-	0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x2009, 0x0002, 0x080c,
-	0x86d3, 0xa006, 0xa005, 0x012e, 0x00ee, 0x00fe, 0x0005, 0x2001,
-	0x0028, 0x2009, 0x0000, 0x0cb0, 0x2009, 0xb60c, 0x210c, 0xd18c,
-	0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004,
-	0x0010, 0x2001, 0x0029, 0x2009, 0x0000, 0x0c20, 0x2001, 0x0029,
-	0x2009, 0x0000, 0x08f8, 0x6944, 0x6e48, 0xa684, 0x3fff, 0xa082,
-	0x4000, 0x16b8, 0xa18c, 0xff00, 0x810f, 0xa182, 0x00ff, 0x12e0,
-	0xa188, 0xb735, 0x2104, 0xa065, 0x01b8, 0x6004, 0xa084, 0x00ff,
-	0xa08e, 0x0006, 0x11b0, 0x684c, 0xd0ec, 0x0120, 0x080c, 0x5147,
-	0x0431, 0x0030, 0x0421, 0x684c, 0xd0fc, 0x0110, 0x080c, 0x5138,
-	0x080c, 0x5185, 0xa006, 0x00c8, 0x2001, 0x0028, 0x2009, 0x0000,
-	0x00a0, 0xa082, 0x0006, 0x1240, 0x6100, 0xd1fc, 0x0d20, 0x2001,
-	0x0029, 0x2009, 0x1000, 0x0048, 0x2001, 0x0029, 0x2009, 0x0000,
-	0x0020, 0x2001, 0x0029, 0x2009, 0x0000, 0xa005, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x6050, 0xa00d, 0x0138, 0x2d00, 0x200a, 0x6803,
-	0x0000, 0x6052, 0x012e, 0x0005, 0x2d00, 0x6052, 0x604e, 0x6803,
-	0x0000, 0x0cc0, 0x0126, 0x2091, 0x8000, 0x604c, 0xa005, 0x0170,
-	0x00e6, 0x2071, 0xb8e1, 0x7004, 0xa086, 0x0002, 0x0168, 0x00ee,
-	0x604c, 0x6802, 0x2d00, 0x604e, 0x012e, 0x0005, 0x2d00, 0x6052,
-	0x604e, 0x6803, 0x0000, 0x0cc0, 0x701c, 0xac06, 0x1d80, 0x604c,
-	0x2070, 0x7000, 0x6802, 0x2d00, 0x7002, 0x00ee, 0x012e, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x604c, 0xa06d, 0x0130, 0x6800, 0xa005,
-	0x1108, 0x6052, 0x604e, 0xad05, 0x012e, 0x0005, 0x604c, 0xa06d,
-	0x0130, 0x6800, 0xa005, 0x1108, 0x6052, 0x604e, 0xad05, 0x0005,
-	0x6803, 0x0000, 0x6084, 0xa00d, 0x0120, 0x2d00, 0x200a, 0x6086,
-	0x0005, 0x2d00, 0x6086, 0x6082, 0x0cd8, 0x0126, 0x00c6, 0x0026,
-	0x2091, 0x8000, 0x6218, 0x2260, 0x6200, 0xa005, 0x0110, 0xc285,
-	0x0008, 0xc284, 0x6202, 0x002e, 0x00ce, 0x012e, 0x0005, 0x0126,
-	0x00c6, 0x2091, 0x8000, 0x6218, 0x2260, 0x6204, 0x0006, 0xa086,
-	0x0006, 0x1180, 0x609c, 0xd0ac, 0x0168, 0x2001, 0xb653, 0x2004,
-	0xd0a4, 0x0140, 0xa284, 0xff00, 0x8007, 0xa086, 0x0007, 0x1110,
-	0x2011, 0x0600, 0x000e, 0xa294, 0xff00, 0xa215, 0x6206, 0x0006,
-	0xa086, 0x0006, 0x1128, 0x6290, 0x82ff, 0x1110, 0x080c, 0x151a,
-	0x000e, 0x00ce, 0x012e, 0x0005, 0x0126, 0x00c6, 0x2091, 0x8000,
-	0x6218, 0x2260, 0x6204, 0x0006, 0xa086, 0x0006, 0x1178, 0x609c,
-	0xd0a4, 0x0160, 0x2001, 0xb653, 0x2004, 0xd0ac, 0x1138, 0xa284,
-	0x00ff, 0xa086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e, 0xa294,
-	0x00ff, 0x8007, 0xa215, 0x6206, 0x00ce, 0x012e, 0x0005, 0x0026,
-	0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x00b0, 0xa190, 0xb735,
-	0x2204, 0xa065, 0x1180, 0x0016, 0x00d6, 0x080c, 0x15e4, 0x2d60,
-	0x00de, 0x001e, 0x0d80, 0x2c00, 0x2012, 0x60a7, 0x0000, 0x60ab,
-	0x0000, 0x080c, 0x4c7e, 0xa006, 0x002e, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x0026, 0xa182, 0x00ff, 0x0218, 0xa085, 0x0001, 0x0480,
-	0x00d6, 0xa190, 0xb735, 0x2204, 0xa06d, 0x0540, 0x2013, 0x0000,
-	0x00d6, 0x00c6, 0x2d60, 0x60a4, 0xa06d, 0x0110, 0x080c, 0x1614,
-	0x60a8, 0xa06d, 0x0110, 0x080c, 0x1614, 0x00ce, 0x00de, 0x00d6,
-	0x00c6, 0x68ac, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6010,
-	0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0x1624, 0x080c, 0x86a4,
-	0x00ce, 0x0c88, 0x00ce, 0x00de, 0x080c, 0x1614, 0x00de, 0xa006,
-	0x002e, 0x012e, 0x0005, 0x0016, 0xa182, 0x00ff, 0x0218, 0xa085,
-	0x0001, 0x0030, 0xa188, 0xb735, 0x2104, 0xa065, 0x0dc0, 0xa006,
-	0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x600b, 0x0000,
-	0x600f, 0x0000, 0x6000, 0xc08c, 0x6002, 0x080c, 0x5b41, 0x1558,
-	0x60a0, 0xa086, 0x007e, 0x2069, 0xbc90, 0x0130, 0x2001, 0xb635,
-	0x2004, 0xd0ac, 0x1500, 0x0098, 0x2d04, 0xd0e4, 0x01e0, 0x00d6,
-	0x2069, 0xbc8e, 0x00c6, 0x2061, 0xb8b2, 0x6810, 0x2062, 0x6814,
-	0x6006, 0x6818, 0x600a, 0x681c, 0x600e, 0x00ce, 0x00de, 0x8d69,
-	0x2d04, 0x2069, 0x0140, 0xa005, 0x1110, 0x2001, 0x0001, 0x6886,
-	0x2069, 0xb600, 0x68a6, 0x2069, 0xbc8e, 0x6808, 0x605e, 0x6810,
-	0x6062, 0x6138, 0xa10a, 0x0208, 0x603a, 0x6814, 0x6066, 0x2099,
-	0xbc96, 0xac88, 0x000a, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2099,
-	0xbc9a, 0xac88, 0x0006, 0x21a0, 0x20a9, 0x0004, 0x53a3, 0x2069,
-	0xbcae, 0x6808, 0x606a, 0x690c, 0x616e, 0x6810, 0x6072, 0x6818,
-	0x6076, 0x60a0, 0xa086, 0x007e, 0x1120, 0x2069, 0xbc8e, 0x690c,
-	0x616e, 0xa182, 0x0211, 0x1218, 0x2009, 0x0008, 0x0400, 0xa182,
-	0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0xa182, 0x02c1, 0x1218,
-	0x2009, 0x0006, 0x00a0, 0xa182, 0x0349, 0x1218, 0x2009, 0x0005,
-	0x0070, 0xa182, 0x0421, 0x1218, 0x2009, 0x0004, 0x0040, 0xa182,
-	0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009, 0x0002, 0x6192,
-	0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016, 0x0026, 0x00e6,
-	0x2071, 0xbc8d, 0x2e04, 0x6896, 0x2071, 0xbc8e, 0x7004, 0x689a,
-	0x701c, 0x689e, 0x6a00, 0x2009, 0xb672, 0x210c, 0xd0bc, 0x0120,
-	0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac, 0xd0c4, 0x0120, 0xd1e4,
-	0x0110, 0xc2bd, 0x0008, 0xc2bc, 0x6a02, 0x00ee, 0x002e, 0x001e,
-	0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4, 0xa06d, 0x01c0,
-	0x6900, 0x81ff, 0x1540, 0x6a04, 0xa282, 0x0010, 0x1648, 0xad88,
-	0x0004, 0x20a9, 0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108,
-	0x1f04, 0x50f3, 0x080c, 0x151a, 0x260a, 0x8210, 0x6a06, 0x0098,
-	0x080c, 0x15fd, 0x01a8, 0x2d00, 0x60a6, 0x6803, 0x0000, 0xad88,
-	0x0004, 0x20a9, 0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x510b,
-	0x6807, 0x0001, 0x6e12, 0xa085, 0x0001, 0x012e, 0x00de, 0x0005,
-	0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x00d6, 0x60a4, 0xa00d,
-	0x01a0, 0x2168, 0x6800, 0xa005, 0x1160, 0x080c, 0x5246, 0x1168,
-	0x200b, 0xffff, 0x6804, 0xa08a, 0x0002, 0x0218, 0x8001, 0x6806,
-	0x0020, 0x080c, 0x1614, 0x60a7, 0x0000, 0x00de, 0x012e, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x52a4, 0x0010, 0x080c, 0x4eff,
-	0x080c, 0x51be, 0x1dd8, 0x080c, 0x5185, 0x012e, 0x0005, 0x00d6,
-	0x0126, 0x2091, 0x8000, 0x60a8, 0xa06d, 0x01c0, 0x6950, 0x81ff,
-	0x1540, 0x6a54, 0xa282, 0x0010, 0x1670, 0xad88, 0x0018, 0x20a9,
-	0x0010, 0x2104, 0xa086, 0xffff, 0x0128, 0x8108, 0x1f04, 0x5159,
-	0x080c, 0x151a, 0x260a, 0x8210, 0x6a56, 0x0098, 0x080c, 0x15fd,
-	0x01d0, 0x2d00, 0x60aa, 0x6853, 0x0000, 0xad88, 0x0018, 0x20a9,
-	0x0010, 0x200b, 0xffff, 0x8108, 0x1f04, 0x5171, 0x6857, 0x0001,
-	0x6e62, 0x0010, 0x080c, 0x4f50, 0x0089, 0x1de0, 0xa085, 0x0001,
-	0x012e, 0x00de, 0x0005, 0xa006, 0x0cd8, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6d1c, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001,
-	0xa00e, 0x0126, 0x2091, 0x8000, 0x604c, 0x2068, 0x6000, 0xd0dc,
-	0x1170, 0x8dff, 0x01f8, 0x83ff, 0x0120, 0x6848, 0xa606, 0x0158,
-	0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506, 0x0120, 0x2d08,
-	0x6800, 0x2068, 0x0c70, 0x080c, 0x81a5, 0x6a00, 0x604c, 0xad06,
-	0x1110, 0x624e, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110,
-	0x6152, 0x8dff, 0x012e, 0x0005, 0xa01e, 0x0010, 0x2019, 0x0001,
-	0xa00e, 0x6080, 0x2068, 0x8dff, 0x01e8, 0x83ff, 0x0120, 0x6848,
-	0xa606, 0x0158, 0x0030, 0x683c, 0xa406, 0x1118, 0x6840, 0xa506,
-	0x0120, 0x2d08, 0x6800, 0x2068, 0x0c70, 0x6a00, 0x6080, 0xad06,
-	0x1110, 0x6282, 0x0018, 0xa180, 0x0000, 0x2202, 0x82ff, 0x1110,
-	0x6186, 0x8dff, 0x0005, 0xa016, 0x080c, 0x5240, 0x1110, 0x2011,
-	0x0001, 0x080c, 0x528b, 0x1110, 0xa295, 0x0002, 0x0005, 0x080c,
-	0x52bc, 0x0118, 0x080c, 0x9dcb, 0x0010, 0xa085, 0x0001, 0x0005,
-	0x080c, 0x52bc, 0x0118, 0x080c, 0x9d5b, 0x0010, 0xa085, 0x0001,
-	0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9dae, 0x0010, 0xa085,
-	0x0001, 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9d77, 0x0010,
-	0xa085, 0x0001, 0x0005, 0x080c, 0x52bc, 0x0118, 0x080c, 0x9de7,
-	0x0010, 0xa085, 0x0001, 0x0005, 0x0126, 0x0006, 0x00d6, 0x2091,
-	0x8000, 0x6080, 0xa06d, 0x01a0, 0x6800, 0x0006, 0x6837, 0x0103,
-	0x6b4a, 0x6847, 0x0000, 0x080c, 0x9f88, 0x0006, 0x6000, 0xd0fc,
-	0x0110, 0x080c, 0xb445, 0x000e, 0x080c, 0x547a, 0x000e, 0x0c50,
-	0x6083, 0x0000, 0x6087, 0x0000, 0x00de, 0x000e, 0x012e, 0x0005,
-	0x60a4, 0xa00d, 0x1118, 0xa085, 0x0001, 0x0005, 0x00e6, 0x2170,
-	0x7000, 0xa005, 0x1168, 0x20a9, 0x0010, 0xae88, 0x0004, 0x2104,
-	0xa606, 0x0130, 0x8108, 0x1f04, 0x524f, 0xa085, 0x0001, 0x0008,
-	0xa006, 0x00ee, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4,
-	0xa06d, 0x1128, 0x080c, 0x15fd, 0x01a0, 0x2d00, 0x60a6, 0x6803,
-	0x0001, 0x6807, 0x0000, 0xad88, 0x0004, 0x20a9, 0x0010, 0x200b,
-	0xffff, 0x8108, 0x1f04, 0x526f, 0xa085, 0x0001, 0x012e, 0x00de,
-	0x0005, 0xa006, 0x0cd8, 0x00d6, 0x0126, 0x2091, 0x8000, 0x60a4,
-	0xa06d, 0x0130, 0x60a7, 0x0000, 0x080c, 0x1614, 0xa085, 0x0001,
-	0x012e, 0x00de, 0x0005, 0x60a8, 0xa00d, 0x1118, 0xa085, 0x0001,
-	0x0005, 0x00e6, 0x2170, 0x7050, 0xa005, 0x1160, 0x20a9, 0x0010,
-	0xae88, 0x0018, 0x2104, 0xa606, 0x0128, 0x8108, 0x1f04, 0x529a,
-	0xa085, 0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x0c19,
-	0x1188, 0x200b, 0xffff, 0x00d6, 0x60a8, 0x2068, 0x6854, 0xa08a,
-	0x0002, 0x0218, 0x8001, 0x6856, 0x0020, 0x080c, 0x1614, 0x60ab,
-	0x0000, 0x00de, 0x012e, 0x0005, 0x609c, 0xd0a4, 0x0005, 0x00f6,
-	0x080c, 0x5b41, 0x01b0, 0x71b8, 0x81ff, 0x1198, 0x71d4, 0xd19c,
-	0x0180, 0x2001, 0x007e, 0xa080, 0xb735, 0x2004, 0xa07d, 0x0148,
-	0x7804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x1118, 0x7800, 0xc0ed,
-	0x7802, 0x2079, 0xb652, 0x7804, 0xd0a4, 0x01e8, 0x0156, 0x00c6,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1168,
-	0x6004, 0xa084, 0xff00, 0x8007, 0xa096, 0x0004, 0x0118, 0xa086,
-	0x0006, 0x1118, 0x6000, 0xc0ed, 0x6002, 0x001e, 0x8108, 0x1f04,
-	0x52e4, 0x00ce, 0x015e, 0x080c, 0x537b, 0x0120, 0x2001, 0xb8b5,
-	0x200c, 0x0038, 0x2079, 0xb652, 0x7804, 0xd0a4, 0x0130, 0x2009,
-	0x07d0, 0x2011, 0x530f, 0x080c, 0x6a94, 0x00fe, 0x0005, 0x2011,
-	0x530f, 0x080c, 0x6a0e, 0x080c, 0x537b, 0x01f0, 0x2001, 0xb7b3,
-	0x2004, 0xa080, 0x0000, 0x200c, 0xc1ec, 0x2102, 0x2001, 0xb653,
-	0x2004, 0xd0a4, 0x0130, 0x2009, 0x07d0, 0x2011, 0x530f, 0x080c,
-	0x6a94, 0x00e6, 0x2071, 0xb600, 0x7073, 0x0000, 0x7077, 0x0000,
-	0x080c, 0x2aed, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9, 0x007f,
-	0x2009, 0x0000, 0x0016, 0x080c, 0x501b, 0x1530, 0x6000, 0xd0ec,
-	0x0518, 0x0046, 0x62a0, 0xa294, 0x00ff, 0x8227, 0xa006, 0x2009,
-	0x0029, 0x080c, 0xb1a4, 0x6000, 0xc0e5, 0xc0ec, 0x6002, 0x6004,
-	0xa084, 0x00ff, 0xa085, 0x0700, 0x6006, 0x2019, 0x0029, 0x080c,
-	0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2009, 0x0000,
-	0x080c, 0xaf3e, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04, 0x533a,
-	0x00ce, 0x015e, 0x0005, 0x00c6, 0x6018, 0x2060, 0x6000, 0xc0ec,
-	0x6002, 0x00ce, 0x0005, 0x7818, 0x2004, 0xd0ac, 0x0005, 0x7818,
-	0x2004, 0xd0bc, 0x0005, 0x00f6, 0x2001, 0xb7b3, 0x2004, 0xa07d,
-	0x0110, 0x7800, 0xd0ec, 0x00fe, 0x0005, 0x0126, 0x0026, 0x2091,
-	0x8000, 0x0006, 0x62a0, 0xa290, 0xb735, 0x2204, 0xac06, 0x190c,
-	0x151a, 0x000e, 0x6200, 0xa005, 0x0110, 0xc2fd, 0x0008, 0xc2fc,
-	0x6202, 0x002e, 0x012e, 0x0005, 0x2011, 0xb635, 0x2204, 0xd0cc,
-	0x0138, 0x2001, 0xb8b3, 0x200c, 0x2011, 0x53a9, 0x080c, 0x6a94,
-	0x0005, 0x2011, 0x53a9, 0x080c, 0x6a0e, 0x2011, 0xb635, 0x2204,
-	0xc0cc, 0x2012, 0x0005, 0x2071, 0xb714, 0x7003, 0x0001, 0x7007,
-	0x0000, 0x7013, 0x0000, 0x7017, 0x0000, 0x701b, 0x0000, 0x701f,
-	0x0000, 0x700b, 0x0000, 0x704b, 0x0001, 0x704f, 0x0000, 0x705b,
-	0x0020, 0x705f, 0x0040, 0x707f, 0x0000, 0x2071, 0xb87d, 0x7003,
-	0xb714, 0x7007, 0x0000, 0x700b, 0x0000, 0x700f, 0xb85d, 0x7013,
-	0x0020, 0x7017, 0x0040, 0x7037, 0x0000, 0x0005, 0x0016, 0x00e6,
-	0x2071, 0xb835, 0xa00e, 0x7186, 0x718a, 0x7097, 0x0001, 0x2001,
-	0xb653, 0x2004, 0xd0fc, 0x1150, 0x2001, 0xb653, 0x2004, 0xa00e,
-	0xd09c, 0x0108, 0x8108, 0x7102, 0x0804, 0x5444, 0x2001, 0xb672,
-	0x200c, 0xa184, 0x000f, 0x2009, 0xb673, 0x210c, 0x0002, 0x53ec,
-	0x541f, 0x5426, 0x5430, 0x5435, 0x53ec, 0x53ec, 0x53ec, 0x540f,
-	0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x7003,
-	0x0004, 0x0136, 0x0146, 0x0156, 0x2099, 0xb676, 0x20a1, 0xb886,
-	0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x0428, 0x708f,
-	0x0005, 0x7007, 0x0122, 0x2001, 0x0002, 0x0030, 0x708f, 0x0002,
-	0x7007, 0x0121, 0x2001, 0x0003, 0x7002, 0x7097, 0x0001, 0x0088,
-	0x7007, 0x0122, 0x2001, 0x0002, 0x0020, 0x7007, 0x0121, 0x2001,
-	0x0003, 0x7002, 0xa006, 0x7096, 0x708e, 0xa184, 0xff00, 0x8007,
-	0x709a, 0xa184, 0x00ff, 0x7092, 0x00ee, 0x001e, 0x0005, 0x00e6,
-	0x2071, 0xb714, 0x684c, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a,
-	0xa085, 0x0001, 0x0428, 0x6a60, 0x7236, 0x6b64, 0x733a, 0x6868,
-	0x703e, 0x7076, 0x686c, 0x7042, 0x707a, 0x684c, 0x702e, 0x6844,
-	0x7032, 0x2009, 0x000d, 0x200a, 0x700b, 0x0000, 0x8007, 0x8006,
-	0x8006, 0xa08c, 0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319,
-	0x726e, 0x7372, 0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0xa006,
-	0x00ee, 0x0005, 0x0156, 0x00e6, 0x0026, 0x6838, 0xd0fc, 0x1904,
-	0x54d3, 0x6804, 0xa00d, 0x0188, 0x00d6, 0x2071, 0xb600, 0xa016,
-	0x702c, 0x2168, 0x6904, 0x206a, 0x8210, 0x2d00, 0x81ff, 0x1dc8,
-	0x702e, 0x70b4, 0xa200, 0x70b6, 0x00de, 0x2071, 0xb714, 0x701c,
-	0xa005, 0x1904, 0x54e3, 0x20a9, 0x0032, 0x0f04, 0x54e1, 0x0e04,
-	0x549d, 0x2071, 0xb835, 0x7200, 0x82ff, 0x05d8, 0x6934, 0xa186,
-	0x0103, 0x1904, 0x54f1, 0x6948, 0x6844, 0xa105, 0x1540, 0x2009,
-	0x8020, 0x2200, 0x0002, 0x54e1, 0x54b8, 0x5509, 0x5515, 0x54e1,
-	0x2071, 0x0000, 0x20a9, 0x0032, 0x0f04, 0x54e1, 0x7018, 0xd084,
-	0x1dd8, 0x7122, 0x683c, 0x7026, 0x6840, 0x702a, 0x701b, 0x0001,
-	0x2091, 0x4080, 0x2071, 0xb600, 0x702c, 0x206a, 0x2d00, 0x702e,
-	0x70b4, 0x8000, 0x70b6, 0x002e, 0x00ee, 0x015e, 0x0005, 0x6844,
-	0xa086, 0x0100, 0x1130, 0x6868, 0xa005, 0x1118, 0x2009, 0x8020,
-	0x0880, 0x2071, 0xb714, 0x2d08, 0x206b, 0x0000, 0x7010, 0x8000,
-	0x7012, 0x7018, 0xa06d, 0x711a, 0x0110, 0x6902, 0x0008, 0x711e,
-	0x0c10, 0xa18c, 0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e,
-	0x0118, 0xa18e, 0x001f, 0x1d28, 0x684c, 0xd0cc, 0x0d10, 0x6850,
-	0xa084, 0x00ff, 0xa086, 0x0001, 0x19e0, 0x2009, 0x8021, 0x0804,
-	0x54b1, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a98, 0x7186, 0xae90,
-	0x0003, 0xa210, 0x683c, 0x2012, 0x0078, 0x7084, 0x8008, 0xa092,
-	0x000f, 0x1a38, 0x7186, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c,
-	0x2012, 0x8210, 0x6840, 0x2012, 0x7088, 0xa10a, 0x0a04, 0x54ca,
-	0x718c, 0x7084, 0xa10a, 0x0a04, 0x54ca, 0x2071, 0x0000, 0x7018,
-	0xd084, 0x1904, 0x54ca, 0x2071, 0xb835, 0x7000, 0xa086, 0x0002,
-	0x1150, 0x080c, 0x5794, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
-	0x4080, 0x0804, 0x54ca, 0x080c, 0x57be, 0x2071, 0x0000, 0x701b,
-	0x0001, 0x2091, 0x4080, 0x0804, 0x54ca, 0x0006, 0x684c, 0x0006,
-	0x6837, 0x0103, 0x20a9, 0x001c, 0xad80, 0x0011, 0x20a0, 0x2001,
-	0x0000, 0x40a4, 0x000e, 0xa084, 0x00ff, 0x684e, 0x000e, 0x684a,
-	0x6952, 0x0005, 0x2071, 0xb714, 0x7004, 0x0002, 0x5570, 0x5581,
-	0x577f, 0x5780, 0x578d, 0x5793, 0x5571, 0x5770, 0x5706, 0x575c,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x0e04, 0x5580, 0x2009, 0x000d,
-	0x7030, 0x200a, 0x2091, 0x4080, 0x7007, 0x0001, 0x700b, 0x0000,
-	0x012e, 0x2069, 0xb8f4, 0x683c, 0xa005, 0x03f8, 0x11f0, 0x0126,
-	0x2091, 0x8000, 0x2069, 0x0000, 0x6934, 0x2001, 0xb720, 0x2004,
-	0xa10a, 0x0170, 0x0e04, 0x55a4, 0x2069, 0x0000, 0x6818, 0xd084,
-	0x1158, 0x2009, 0x8040, 0x6922, 0x681b, 0x0001, 0x2091, 0x4080,
-	0x2069, 0xb8f4, 0x683f, 0xffff, 0x012e, 0x2069, 0xb600, 0x6848,
-	0x6968, 0xa102, 0x2069, 0xb835, 0x688a, 0x6984, 0x701c, 0xa06d,
-	0x0120, 0x81ff, 0x0904, 0x55fa, 0x00a0, 0x81ff, 0x0904, 0x56c0,
-	0x2071, 0xb835, 0x7184, 0x7088, 0xa10a, 0x1258, 0x7190, 0x2071,
-	0xb8f4, 0x7038, 0xa005, 0x0128, 0x1b04, 0x56c0, 0x713a, 0x0804,
-	0x56c0, 0x2071, 0xb835, 0x718c, 0x0126, 0x2091, 0x8000, 0x7084,
-	0xa10a, 0x0a04, 0x56db, 0x0e04, 0x567c, 0x2071, 0x0000, 0x7018,
-	0xd084, 0x1904, 0x567c, 0x2001, 0xffff, 0x2071, 0xb8f4, 0x703a,
-	0x2071, 0xb835, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x5794,
-	0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0804, 0x567c,
-	0x080c, 0x57be, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x0804, 0x567c, 0x2071, 0xb835, 0x7000, 0xa005, 0x0904, 0x56a2,
-	0x6934, 0xa186, 0x0103, 0x1904, 0x567f, 0x684c, 0xd0bc, 0x1904,
-	0x56a2, 0x6948, 0x6844, 0xa105, 0x1904, 0x5697, 0x2009, 0x8020,
-	0x2071, 0xb835, 0x7000, 0x0002, 0x56a2, 0x5662, 0x563a, 0x564c,
-	0x5619, 0x0136, 0x0146, 0x0156, 0x2099, 0xb676, 0x20a1, 0xb886,
-	0x20a9, 0x0004, 0x53a3, 0x015e, 0x014e, 0x013e, 0x2071, 0xb87d,
-	0xad80, 0x000f, 0x700e, 0x7013, 0x0002, 0x7007, 0x0002, 0x700b,
-	0x0000, 0x2e10, 0x080c, 0x1648, 0x2071, 0xb714, 0x7007, 0x0009,
-	0x0804, 0x56c0, 0x7084, 0x8008, 0xa092, 0x001e, 0x1a04, 0x56c0,
-	0xae90, 0x0003, 0xa210, 0x683c, 0x2012, 0x7186, 0x2071, 0xb714,
-	0x080c, 0x5815, 0x0804, 0x56c0, 0x7084, 0x8008, 0xa092, 0x000f,
-	0x1a04, 0x56c0, 0xae90, 0x0003, 0x8003, 0xa210, 0x683c, 0x2012,
-	0x8210, 0x6840, 0x2012, 0x7186, 0x2071, 0xb714, 0x080c, 0x5815,
-	0x0804, 0x56c0, 0x0126, 0x2091, 0x8000, 0x0e04, 0x567c, 0x2071,
-	0x0000, 0x7018, 0xd084, 0x1180, 0x7122, 0x683c, 0x7026, 0x6840,
-	0x702a, 0x701b, 0x0001, 0x2091, 0x4080, 0x012e, 0x2071, 0xb714,
-	0x080c, 0x5815, 0x0804, 0x56c0, 0x012e, 0x0804, 0x56c0, 0xa18c,
-	0x00ff, 0xa186, 0x0017, 0x0130, 0xa186, 0x001e, 0x0118, 0xa18e,
-	0x001f, 0x11c0, 0x684c, 0xd0cc, 0x01a8, 0x6850, 0xa084, 0x00ff,
-	0xa086, 0x0001, 0x1178, 0x2009, 0x8021, 0x0804, 0x5610, 0x6844,
-	0xa086, 0x0100, 0x1138, 0x6868, 0xa005, 0x1120, 0x2009, 0x8020,
-	0x0804, 0x5610, 0x2071, 0xb714, 0x080c, 0x5827, 0x01c8, 0x2071,
-	0xb714, 0x700f, 0x0001, 0x6934, 0xa184, 0x00ff, 0xa086, 0x0003,
-	0x1130, 0x810f, 0xa18c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x7007,
-	0x0003, 0x080c, 0x5840, 0x7050, 0xa086, 0x0100, 0x0904, 0x5780,
-	0x0126, 0x2091, 0x8000, 0x2071, 0xb714, 0x7008, 0xa086, 0x0001,
-	0x1180, 0x0e04, 0x56d9, 0x2009, 0x000d, 0x7030, 0x200a, 0x2091,
-	0x4080, 0x700b, 0x0000, 0x7004, 0xa086, 0x0006, 0x1110, 0x7007,
-	0x0001, 0x012e, 0x0005, 0x2071, 0xb714, 0x080c, 0x5827, 0x0518,
-	0x2071, 0xb835, 0x7084, 0x700a, 0x20a9, 0x0020, 0x2099, 0xb836,
-	0x20a1, 0xb85d, 0x53a3, 0x7087, 0x0000, 0x2071, 0xb714, 0x2069,
-	0xb87d, 0x706c, 0x6826, 0x7070, 0x682a, 0x7074, 0x682e, 0x7078,
-	0x6832, 0x2d10, 0x080c, 0x1648, 0x7007, 0x0008, 0x2001, 0xffff,
-	0x2071, 0xb8f4, 0x703a, 0x012e, 0x0804, 0x56c0, 0x2069, 0xb87d,
-	0x6808, 0xa08e, 0x0000, 0x0904, 0x575b, 0xa08e, 0x0200, 0x0904,
-	0x5759, 0xa08e, 0x0100, 0x1904, 0x575b, 0x0126, 0x2091, 0x8000,
-	0x0e04, 0x5757, 0x2069, 0x0000, 0x6818, 0xd084, 0x15c0, 0x702c,
-	0x7130, 0x8108, 0xa102, 0x0230, 0xa00e, 0x7034, 0x706e, 0x7038,
-	0x7072, 0x0048, 0x706c, 0xa080, 0x0040, 0x706e, 0x1220, 0x7070,
-	0xa081, 0x0000, 0x7072, 0x7132, 0x6936, 0x700b, 0x0000, 0x2001,
-	0xb85a, 0x2004, 0xa005, 0x1190, 0x6934, 0x2069, 0xb835, 0x689c,
-	0x699e, 0x2069, 0xb8f4, 0xa102, 0x1118, 0x683c, 0xa005, 0x1368,
-	0x2001, 0xb85b, 0x200c, 0x810d, 0x693e, 0x0038, 0x2009, 0x8040,
-	0x6922, 0x681b, 0x0001, 0x2091, 0x4080, 0x7007, 0x0001, 0x012e,
-	0x0010, 0x7007, 0x0005, 0x0005, 0x2001, 0xb87f, 0x2004, 0xa08e,
-	0x0100, 0x1128, 0x7007, 0x0001, 0x080c, 0x5815, 0x0005, 0xa08e,
-	0x0000, 0x0de0, 0xa08e, 0x0200, 0x1dc8, 0x7007, 0x0005, 0x0005,
-	0x701c, 0xa06d, 0x0158, 0x080c, 0x5827, 0x0140, 0x7007, 0x0003,
-	0x080c, 0x5840, 0x7050, 0xa086, 0x0100, 0x0110, 0x0005, 0x0005,
-	0x7050, 0xa09e, 0x0100, 0x1118, 0x7007, 0x0004, 0x0030, 0xa086,
-	0x0200, 0x1110, 0x7007, 0x0005, 0x0005, 0x080c, 0x57e3, 0x7006,
-	0x080c, 0x5815, 0x0005, 0x0005, 0x00e6, 0x0156, 0x2071, 0xb835,
-	0x7184, 0x81ff, 0x0500, 0xa006, 0x7086, 0xae80, 0x0003, 0x2071,
-	0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x0f04, 0x57b8, 0x2014,
-	0x722a, 0x8000, 0x0f04, 0x57b8, 0x2014, 0x722e, 0x8000, 0x0f04,
-	0x57b8, 0x2014, 0x723a, 0x8000, 0x0f04, 0x57b8, 0x2014, 0x723e,
-	0xa180, 0x8030, 0x7022, 0x015e, 0x00ee, 0x0005, 0x00e6, 0x0156,
-	0x2071, 0xb835, 0x7184, 0x81ff, 0x01d8, 0xa006, 0x7086, 0xae80,
-	0x0003, 0x2071, 0x0000, 0x21a8, 0x2014, 0x7226, 0x8000, 0x2014,
-	0x722a, 0x8000, 0x0f04, 0x57da, 0x2014, 0x723a, 0x8000, 0x2014,
-	0x723e, 0x0018, 0x2001, 0x8020, 0x0010, 0x2001, 0x8042, 0x7022,
-	0x015e, 0x00ee, 0x0005, 0x702c, 0x7130, 0x8108, 0xa102, 0x0230,
-	0xa00e, 0x7034, 0x706e, 0x7038, 0x7072, 0x0048, 0x706c, 0xa080,
-	0x0040, 0x706e, 0x1220, 0x7070, 0xa081, 0x0000, 0x7072, 0x7132,
-	0x700c, 0x8001, 0x700e, 0x1180, 0x0126, 0x2091, 0x8000, 0x0e04,
-	0x580f, 0x2001, 0x000d, 0x2102, 0x2091, 0x4080, 0x2001, 0x0001,
-	0x700b, 0x0000, 0x012e, 0x0005, 0x2001, 0x0007, 0x0005, 0x2001,
-	0x0006, 0x700b, 0x0001, 0x012e, 0x0005, 0x701c, 0xa06d, 0x0170,
-	0x0126, 0x2091, 0x8000, 0x7010, 0x8001, 0x7012, 0x2d04, 0x701e,
-	0xa005, 0x1108, 0x701a, 0x012e, 0x080c, 0x1614, 0x0005, 0x2019,
-	0x000d, 0x2304, 0x230c, 0xa10e, 0x0130, 0x2304, 0x230c, 0xa10e,
-	0x0110, 0xa006, 0x0060, 0x732c, 0x8319, 0x7130, 0xa102, 0x1118,
-	0x2300, 0xa005, 0x0020, 0x0210, 0xa302, 0x0008, 0x8002, 0x0005,
-	0x2d00, 0x7026, 0xa080, 0x000d, 0x7056, 0x7053, 0x0000, 0x0126,
-	0x2091, 0x8000, 0x2009, 0xb913, 0x2104, 0xc08d, 0x200a, 0x012e,
-	0x080c, 0x1664, 0x0005, 0x708c, 0xa08a, 0x0029, 0x1220, 0xa082,
-	0x001d, 0x0033, 0x0010, 0x080c, 0x151a, 0x6027, 0x1e00, 0x0005,
-	0x594e, 0x58c9, 0x58e1, 0x591e, 0x593f, 0x5979, 0x598b, 0x58e1,
-	0x5965, 0x586d, 0x589b, 0x586c, 0x0005, 0x00d6, 0x2069, 0x0200,
-	0x6804, 0xa005, 0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028,
-	0x2069, 0xb8c6, 0x2d04, 0x7002, 0x080c, 0x5c43, 0x6028, 0xa085,
-	0x0600, 0x602a, 0x00b0, 0x708f, 0x0028, 0x2069, 0xb8c6, 0x2d04,
-	0x7002, 0x6028, 0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046,
-	0x0056, 0x2071, 0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, 0x003e,
-	0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0xa005,
-	0x1180, 0x6808, 0xa005, 0x1518, 0x708f, 0x0028, 0x2069, 0xb8c6,
-	0x2d04, 0x7002, 0x080c, 0x5cd0, 0x6028, 0xa085, 0x0600, 0x602a,
-	0x00b0, 0x708f, 0x0028, 0x2069, 0xb8c6, 0x2d04, 0x7002, 0x6028,
-	0xa085, 0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071,
-	0xb924, 0x080c, 0x1e1a, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de,
-	0x0005, 0x6803, 0x0090, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x59f6,
-	0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x708f, 0x0020,
-	0x080c, 0x59f6, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f,
-	0x0005, 0x6803, 0x0088, 0x6124, 0xd1cc, 0x1590, 0xd1dc, 0x1568,
-	0xd1e4, 0x1540, 0xa184, 0x1e00, 0x1580, 0x60e3, 0x0001, 0x600c,
-	0xc0b4, 0x600e, 0x080c, 0x5b71, 0x080c, 0x24e5, 0x0156, 0x6803,
-	0x0100, 0x20a9, 0x0014, 0x6804, 0xd0dc, 0x1118, 0x1f04, 0x58fb,
-	0x0048, 0x20a9, 0x0014, 0x6803, 0x0080, 0x6804, 0xd0d4, 0x1130,
-	0x1f04, 0x5905, 0x080c, 0x5b92, 0x015e, 0x0078, 0x015e, 0x708f,
-	0x0028, 0x0058, 0x708f, 0x001e, 0x0040, 0x708f, 0x001d, 0x0028,
-	0x708f, 0x0020, 0x0010, 0x708f, 0x001f, 0x0005, 0x60e3, 0x0001,
-	0x600c, 0xc0b4, 0x600e, 0x080c, 0x5b71, 0x080c, 0x24e5, 0x6803,
-	0x0080, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130,
-	0xa184, 0x1e00, 0x1158, 0x708f, 0x0028, 0x0040, 0x708f, 0x001e,
-	0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x001f, 0x0005, 0x6803,
-	0x00a0, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1e63,
-	0x708f, 0x001e, 0x0010, 0x708f, 0x001d, 0x0005, 0x080c, 0x5a68,
-	0x6124, 0xd1dc, 0x1188, 0x080c, 0x59f6, 0x0016, 0x080c, 0x1e63,
-	0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x708f, 0x001e, 0x0020,
-	0x708f, 0x001f, 0x080c, 0x59f6, 0x0005, 0x6803, 0x00a0, 0x6124,
-	0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140,
-	0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010, 0x708f, 0x0021,
-	0x0005, 0x080c, 0x5a68, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128,
-	0xd1e4, 0x0140, 0x708f, 0x001e, 0x0028, 0x708f, 0x001d, 0x0010,
-	0x708f, 0x001f, 0x0005, 0x6803, 0x0090, 0x6124, 0xd1d4, 0x1178,
-	0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x708f, 0x001e,
-	0x0040, 0x708f, 0x001d, 0x0028, 0x708f, 0x0020, 0x0010, 0x708f,
-	0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061,
-	0x0100, 0x2069, 0x0140, 0x2071, 0xb600, 0x2091, 0x8000, 0x080c,
-	0x5b41, 0x11e8, 0x2001, 0xb60c, 0x200c, 0xd1b4, 0x01c0, 0xc1b4,
-	0x2102, 0x6027, 0x0200, 0xe000, 0xe000, 0x6024, 0xd0cc, 0x0158,
-	0x6803, 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600,
-	0x2003, 0x0001, 0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c,
-	0x5b5d, 0x0150, 0x080c, 0x5b53, 0x1138, 0x2001, 0x0001, 0x080c,
-	0x27f8, 0x080c, 0x5b18, 0x00a0, 0x080c, 0x5a65, 0x0178, 0x2001,
-	0x0001, 0x080c, 0x27f8, 0x708c, 0xa086, 0x001e, 0x0120, 0x708c,
-	0xa086, 0x0022, 0x1118, 0x708f, 0x0025, 0x0010, 0x708f, 0x0021,
-	0x012e, 0x00ee, 0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011,
-	0x5a07, 0x080c, 0x6ace, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064,
-	0x2011, 0x5a07, 0x080c, 0x6ac5, 0x002e, 0x001e, 0x0005, 0x00e6,
-	0x00f6, 0x0016, 0x080c, 0x7df3, 0x2071, 0xb600, 0x080c, 0x59a2,
-	0x001e, 0x00fe, 0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6,
-	0x00d6, 0x00e6, 0x00f6, 0x0126, 0x080c, 0x7df3, 0x2061, 0x0100,
-	0x2069, 0x0140, 0x2071, 0xb600, 0x2091, 0x8000, 0x6028, 0xc09c,
-	0x602a, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c,
-	0x8106, 0x080c, 0x7fe0, 0x080c, 0x6a82, 0x0036, 0x2019, 0x0000,
-	0x080c, 0x806b, 0x003e, 0x60e3, 0x0000, 0x080c, 0xb4eb, 0x080c,
-	0xb506, 0x2001, 0xb600, 0x2003, 0x0004, 0x6027, 0x0008, 0x080c,
-	0x12e2, 0x2001, 0x0001, 0x080c, 0x27f8, 0x012e, 0x00fe, 0x00ee,
-	0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x2001, 0xb600,
-	0x2004, 0xa086, 0x0004, 0x0140, 0x2001, 0xb89e, 0x2003, 0xaaaa,
-	0x2001, 0xb89f, 0x2003, 0x0000, 0x0005, 0x6020, 0xd09c, 0x0005,
-	0x6800, 0xa086, 0x00c0, 0x0160, 0x6803, 0x00c0, 0x0156, 0x20a9,
-	0x002d, 0x1d04, 0x5a71, 0x2091, 0x6000, 0x1f04, 0x5a71, 0x015e,
-	0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140,
-	0x2071, 0xb600, 0x2001, 0xb89f, 0x200c, 0xa186, 0x0000, 0x0158,
-	0xa186, 0x0001, 0x0158, 0xa186, 0x0002, 0x0158, 0xa186, 0x0003,
-	0x0158, 0x0804, 0x5b06, 0x708f, 0x0022, 0x0040, 0x708f, 0x0021,
-	0x0028, 0x708f, 0x0023, 0x0020, 0x708f, 0x0024, 0x6043, 0x0000,
-	0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28a7,
-	0x0026, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c,
-	0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019, 0x0000, 0x080c, 0x806b,
-	0x003e, 0x002e, 0x7000, 0xa08e, 0x0004, 0x0118, 0x602b, 0x0028,
-	0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091, 0x8000, 0x20a9,
-	0x0005, 0x6024, 0xd0ac, 0x0120, 0x012e, 0x015e, 0x0804, 0x5b14,
-	0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6904, 0xd1d4, 0x1130,
-	0x6803, 0x0100, 0x1f04, 0x5ac9, 0x080c, 0x5b92, 0x012e, 0x015e,
-	0x080c, 0x5b53, 0x01a8, 0x6044, 0xa005, 0x0168, 0x6050, 0x0006,
-	0xa085, 0x0020, 0x6052, 0x080c, 0x5b92, 0xa006, 0x8001, 0x1df0,
-	0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110, 0x080c, 0x5b92,
-	0x0016, 0x0026, 0x2009, 0x00c8, 0x2011, 0x5a14, 0x080c, 0x6a94,
-	0x002e, 0x001e, 0x2001, 0xb89f, 0x2003, 0x0004, 0x080c, 0x5853,
-	0x080c, 0x5b53, 0x0148, 0x6804, 0xd0d4, 0x1130, 0xd0dc, 0x1100,
-	0x2001, 0xb89f, 0x2003, 0x0000, 0x00ee, 0x00de, 0x00ce, 0x0005,
-	0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071,
-	0xb600, 0x2001, 0xb89e, 0x2003, 0x0000, 0x2001, 0xb88f, 0x2003,
-	0x0000, 0x708f, 0x0000, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001,
-	0x0000, 0x080c, 0x28a7, 0x6803, 0x0000, 0x6043, 0x0090, 0x6043,
-	0x0010, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce,
-	0x0005, 0x0006, 0x2001, 0xb89e, 0x2004, 0xa086, 0xaaaa, 0x000e,
-	0x0005, 0x0006, 0x2001, 0xb672, 0x2004, 0xa084, 0x0030, 0xa086,
-	0x0000, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672, 0x2004, 0xa084,
-	0x0030, 0xa086, 0x0030, 0x000e, 0x0005, 0x0006, 0x2001, 0xb672,
-	0x2004, 0xa084, 0x0030, 0xa086, 0x0010, 0x000e, 0x0005, 0x0006,
-	0x2001, 0xb672, 0x2004, 0xa084, 0x0030, 0xa086, 0x0020, 0x000e,
-	0x0005, 0x2001, 0xb60c, 0x2004, 0xd0a4, 0x0170, 0x080c, 0x28c7,
-	0x0036, 0x0016, 0x2009, 0x0000, 0x2019, 0x0028, 0x080c, 0x2ca4,
-	0x001e, 0x003e, 0xa006, 0x0009, 0x0005, 0x00e6, 0x2071, 0xb60c,
-	0x2e04, 0x0118, 0xa085, 0x0010, 0x0010, 0xa084, 0xffef, 0x2072,
-	0x00ee, 0x0005, 0x6050, 0x0006, 0x60f0, 0x0006, 0x60ec, 0x0006,
-	0x600c, 0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x602f, 0x0100,
-	0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a,
-	0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e, 0x60f2,
-	0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28a7,
-	0x6800, 0xa084, 0x00a0, 0xc0bd, 0x6802, 0x6803, 0x00a0, 0x000e,
-	0x6052, 0x6050, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6,
-	0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0xb600,
-	0x6020, 0xa084, 0x0080, 0x0138, 0x2001, 0xb60c, 0x200c, 0xc1bd,
-	0x2102, 0x0804, 0x5c3b, 0x2001, 0xb60c, 0x200c, 0xc1bc, 0x2102,
-	0x6028, 0xa084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x6803, 0x0090,
-	0x20a9, 0x0384, 0x6024, 0xd0cc, 0x1508, 0x1d04, 0x5bea, 0x2091,
-	0x6000, 0x1f04, 0x5bea, 0x2011, 0x0003, 0x080c, 0x80fc, 0x2011,
-	0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x2019, 0x0000, 0x080c,
-	0x806b, 0x6803, 0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001,
-	0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x0468, 0x86ff, 0x1120,
-	0x080c, 0x1e63, 0x080c, 0x24e5, 0x60e3, 0x0000, 0x2001, 0xb88f,
-	0x2004, 0x080c, 0x28a7, 0x60e2, 0x6803, 0x0080, 0x20a9, 0x0384,
-	0x6027, 0x1e00, 0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0138,
-	0x1d04, 0x5c20, 0x2091, 0x6000, 0x1f04, 0x5c20, 0x0820, 0x6028,
-	0xa085, 0x1e00, 0x602a, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001,
-	0x0008, 0x6886, 0xa006, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e,
-	0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x00c6,
-	0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x2069, 0x0140,
-	0x6020, 0xa084, 0x00c0, 0x0120, 0x6884, 0xa005, 0x1904, 0x5c97,
-	0x6803, 0x0088, 0x60e3, 0x0000, 0x6887, 0x0000, 0x2001, 0x0000,
-	0x080c, 0x28a7, 0x2069, 0x0200, 0x6804, 0xa005, 0x1118, 0x6808,
-	0xa005, 0x01c0, 0x6028, 0xa084, 0xfbff, 0x602a, 0x6027, 0x0400,
-	0x2069, 0xb8c6, 0x7000, 0x206a, 0x708f, 0x0026, 0x7003, 0x0001,
-	0x20a9, 0x0002, 0x1d04, 0x5c7a, 0x2091, 0x6000, 0x1f04, 0x5c7a,
-	0x0804, 0x5cc8, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027, 0x1e00,
-	0x2009, 0x1e00, 0xe000, 0x6024, 0xa10c, 0x0520, 0xa084, 0x1a00,
-	0x1508, 0x1d04, 0x5c86, 0x2091, 0x6000, 0x1f04, 0x5c86, 0x2011,
-	0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, 0x8106, 0x080c,
-	0x7fe0, 0x2019, 0x0000, 0x080c, 0x806b, 0x6803, 0x00a0, 0x2001,
-	0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0xa085,
-	0x0001, 0x00b0, 0x080c, 0x24e5, 0x6803, 0x0080, 0x2069, 0x0140,
-	0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001, 0x0008,
-	0x6886, 0x2001, 0xb88f, 0x2004, 0x080c, 0x28a7, 0x60e2, 0xa006,
-	0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005,
-	0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061,
-	0x0100, 0x2071, 0xb600, 0x6020, 0xa084, 0x00c0, 0x01e0, 0x2011,
-	0x0003, 0x080c, 0x80fc, 0x2011, 0x0002, 0x080c, 0x8106, 0x080c,
-	0x7fe0, 0x2019, 0x0000, 0x080c, 0x806b, 0x2069, 0x0140, 0x6803,
-	0x00a0, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001, 0xb600, 0x2003,
-	0x0001, 0x0804, 0x5d6d, 0x2001, 0xb60c, 0x200c, 0xd1b4, 0x1160,
-	0xc1b5, 0x2102, 0x080c, 0x59fc, 0x2069, 0x0140, 0x080c, 0x24e5,
-	0x6803, 0x0080, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804, 0xa005,
-	0x1118, 0x6808, 0xa005, 0x01c0, 0x6028, 0xa084, 0xfdff, 0x602a,
-	0x6027, 0x0200, 0x2069, 0xb8c6, 0x7000, 0x206a, 0x708f, 0x0027,
-	0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x5d24, 0x2091, 0x6000,
-	0x1f04, 0x5d24, 0x0804, 0x5d6d, 0x6027, 0x1e00, 0x2009, 0x1e00,
-	0xe000, 0x6024, 0xa10c, 0x01c8, 0xa084, 0x1c00, 0x11b0, 0x1d04,
-	0x5d2c, 0x0006, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x696b,
-	0x00ee, 0x00de, 0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0xb8f4,
-	0x7018, 0x00ee, 0xa005, 0x1d00, 0x0500, 0x0026, 0x2011, 0x5a14,
-	0x080c, 0x6a0e, 0x2011, 0x5a07, 0x080c, 0x6ace, 0x002e, 0x2069,
-	0x0140, 0x60e3, 0x0000, 0x70a4, 0xa005, 0x1118, 0x6887, 0x0001,
-	0x0008, 0x6886, 0x2001, 0xb88f, 0x2004, 0x080c, 0x28a7, 0x60e2,
-	0x2001, 0xb60c, 0x200c, 0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce,
-	0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026,
-	0x0036, 0x0046, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600,
-	0x7130, 0xd184, 0x1180, 0x2011, 0xb653, 0x2214, 0xd2ec, 0x0138,
-	0xc18d, 0x7132, 0x2011, 0xb653, 0x2214, 0xd2ac, 0x1120, 0x7030,
-	0xd08c, 0x0904, 0x5dda, 0x7130, 0xc185, 0x7132, 0x2011, 0xb653,
-	0x220c, 0xd1a4, 0x0530, 0x0016, 0x2019, 0x000e, 0x080c, 0xb121,
-	0x0156, 0x20a9, 0x007f, 0x2009, 0x0000, 0xa186, 0x007e, 0x01a0,
-	0xa186, 0x0080, 0x0188, 0x080c, 0x501b, 0x1170, 0x8127, 0xa006,
-	0x0016, 0x2009, 0x000e, 0x080c, 0xb1a4, 0x2009, 0x0001, 0x2011,
-	0x0100, 0x080c, 0x6b8c, 0x001e, 0x8108, 0x1f04, 0x5da5, 0x015e,
-	0x001e, 0xd1ac, 0x1148, 0x0016, 0x2009, 0x0000, 0x2019, 0x0004,
-	0x080c, 0x2ca4, 0x001e, 0x0070, 0x0156, 0x20a9, 0x007f, 0x2009,
-	0x0000, 0x080c, 0x501b, 0x1110, 0x080c, 0x4c7e, 0x8108, 0x1f04,
-	0x5dd1, 0x015e, 0x080c, 0x1e63, 0x2011, 0x0003, 0x080c, 0x80fc,
-	0x2011, 0x0002, 0x080c, 0x8106, 0x080c, 0x7fe0, 0x0036, 0x2019,
-	0x0000, 0x080c, 0x806b, 0x003e, 0x60e3, 0x0000, 0x2001, 0xb600,
-	0x2003, 0x0001, 0x080c, 0x5a79, 0x00ee, 0x00ce, 0x004e, 0x003e,
-	0x002e, 0x001e, 0x015e, 0x0005, 0x2071, 0xb6e2, 0x7003, 0x0000,
-	0x7007, 0x0000, 0x700f, 0x0000, 0x702b, 0x0001, 0x704f, 0x0000,
-	0x7053, 0x0001, 0x705f, 0x0020, 0x7063, 0x0040, 0x7083, 0x0000,
-	0x708b, 0x0000, 0x708f, 0x0001, 0x70bf, 0x0000, 0x0005, 0x00e6,
-	0x2071, 0xb6e2, 0x6848, 0xa005, 0x1130, 0x7028, 0xc085, 0x702a,
-	0xa085, 0x0001, 0x0428, 0x6a50, 0x7236, 0x6b54, 0x733a, 0x6858,
-	0x703e, 0x707a, 0x685c, 0x7042, 0x707e, 0x6848, 0x702e, 0x6840,
-	0x7032, 0x2009, 0x000c, 0x200a, 0x8007, 0x8006, 0x8006, 0xa08c,
-	0x003f, 0xa084, 0xffc0, 0xa210, 0x2100, 0xa319, 0x7272, 0x7376,
-	0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700f, 0x0000, 0xa006,
-	0x00ee, 0x0005, 0x2b78, 0x2071, 0xb6e2, 0x7004, 0x0043, 0x700c,
-	0x0002, 0x5e56, 0x5e4d, 0x5e4d, 0x5e4d, 0x5e4d, 0x0005, 0x5eac,
-	0x5ead, 0x5edf, 0x5ee0, 0x5eaa, 0x5f2e, 0x5f33, 0x5f64, 0x5f65,
-	0x5f80, 0x5f81, 0x5f82, 0x5f83, 0x5f84, 0x5f85, 0x603b, 0x6062,
-	0x700c, 0x0002, 0x5e6f, 0x5eaa, 0x5eaa, 0x5eab, 0x5eab, 0x7830,
-	0x7930, 0xa106, 0x0120, 0x7830, 0x7930, 0xa106, 0x1510, 0x7030,
-	0xa10a, 0x01f8, 0x1210, 0x712c, 0xa10a, 0xa18a, 0x0002, 0x12d0,
-	0x080c, 0x15e4, 0x01b0, 0x2d00, 0x705a, 0x7063, 0x0040, 0x2001,
-	0x0003, 0x7057, 0x0000, 0x0126, 0x0006, 0x2091, 0x8000, 0x2009,
-	0xb913, 0x2104, 0xc085, 0x200a, 0x000e, 0x700e, 0x012e, 0x080c,
-	0x1664, 0x0005, 0x080c, 0x15e4, 0x0de0, 0x2d00, 0x705a, 0x080c,
-	0x15e4, 0x1108, 0x0c10, 0x2d00, 0x7086, 0x7063, 0x0080, 0x2001,
-	0x0004, 0x08f8, 0x0005, 0x0005, 0x0005, 0x700c, 0x0002, 0x5eb4,
-	0x5eb7, 0x5ec5, 0x5ede, 0x5ede, 0x080c, 0x5e68, 0x0005, 0x0126,
-	0x8001, 0x700e, 0x7058, 0x0006, 0x080c, 0x63b5, 0x0120, 0x2091,
-	0x8000, 0x080c, 0x5e68, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e,
-	0x080c, 0x63b5, 0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000,
-	0x6807, 0x0000, 0x6834, 0xa084, 0x00ff, 0xa08a, 0x003a, 0x1218,
-	0x00db, 0x012e, 0x0005, 0x012e, 0x080c, 0x5f86, 0x0005, 0x0005,
-	0x0005, 0x00e6, 0x2071, 0xb6e2, 0x700c, 0x0002, 0x5eeb, 0x5eeb,
-	0x5eeb, 0x5eed, 0x5ef0, 0x00ee, 0x0005, 0x700f, 0x0001, 0x0010,
-	0x700f, 0x0002, 0x00ee, 0x0005, 0x5f86, 0x5f86, 0x5fa2, 0x5f86,
-	0x611f, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fa2, 0x6161,
-	0x61a4, 0x61ed, 0x6201, 0x5f86, 0x5f86, 0x5fbe, 0x5fa2, 0x5f86,
-	0x5f86, 0x6018, 0x62ad, 0x62c8, 0x5f86, 0x5fbe, 0x5f86, 0x5f86,
-	0x5f86, 0x5f86, 0x600e, 0x62c8, 0x5f86, 0x5f86, 0x5f86, 0x5f86,
-	0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fd2, 0x5f86, 0x5f86,
-	0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x63d3,
-	0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5f86, 0x5fe7, 0x7020, 0x2068,
-	0x080c, 0x1614, 0x0005, 0x700c, 0x0002, 0x5f3a, 0x5f3d, 0x5f4b,
-	0x5f63, 0x5f63, 0x080c, 0x5e68, 0x0005, 0x0126, 0x8001, 0x700e,
-	0x7058, 0x0006, 0x080c, 0x63b5, 0x0120, 0x2091, 0x8000, 0x080c,
-	0x5e68, 0x00de, 0x0048, 0x0126, 0x8001, 0x700e, 0x080c, 0x63b5,
-	0x7058, 0x2068, 0x7084, 0x705a, 0x6803, 0x0000, 0x6807, 0x0000,
-	0x6834, 0xa084, 0x00ff, 0xa08a, 0x001a, 0x1218, 0x003b, 0x012e,
-	0x0005, 0x012e, 0x0419, 0x0005, 0x0005, 0x0005, 0x5f86, 0x5fa2,
-	0x610b, 0x5f86, 0x5fa2, 0x5f86, 0x5fa2, 0x5fa2, 0x5f86, 0x5fa2,
-	0x610b, 0x5fa2, 0x5fa2, 0x5fa2, 0x5fa2, 0x5fa2, 0x5f86, 0x5fa2,
-	0x610b, 0x5f86, 0x5f86, 0x5fa2, 0x5f86, 0x5f86, 0x5f86, 0x5fa2,
-	0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x7007, 0x0001,
-	0x6838, 0xa084, 0x00ff, 0xc0d5, 0x683a, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x547a, 0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084,
-	0x00ff, 0xc0e5, 0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a,
-	0x012e, 0x0005, 0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0ed,
-	0x683a, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e, 0x0005,
-	0x7007, 0x0001, 0x6838, 0xa084, 0x00ff, 0xc0dd, 0x683a, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x547a, 0x012e, 0x0005, 0x6834, 0x8007,
-	0xa084, 0x00ff, 0x0988, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804,
-	0x60cb, 0x7007, 0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b,
-	0x60cb, 0x0005, 0x6834, 0x8007, 0xa084, 0x00ff, 0x0904, 0x5f94,
-	0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x60e8, 0x7007, 0x0006,
-	0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x60e8, 0x0005, 0x6834,
-	0x8007, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1904, 0x5f94, 0x7007,
-	0x0001, 0x2009, 0xb631, 0x210c, 0x81ff, 0x11a8, 0x6838, 0xa084,
-	0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4df4, 0x1108, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x6837, 0x0139, 0x684a, 0x6952, 0x080c,
-	0x547a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x0c90, 0x684c, 0xa084,
-	0x00c0, 0xa086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x62e0,
-	0x2d00, 0x7016, 0x701a, 0x20a9, 0x0004, 0xa080, 0x0024, 0x2098,
-	0x20a1, 0xb70d, 0x53a3, 0x6858, 0x7012, 0xa082, 0x0401, 0x1a04,
-	0x5fb0, 0x6a84, 0xa28a, 0x0002, 0x1a04, 0x5fb0, 0x82ff, 0x1138,
-	0x6888, 0x698c, 0xa105, 0x0118, 0x2001, 0x609e, 0x0018, 0xa280,
-	0x6094, 0x2005, 0x70c6, 0x7010, 0xa015, 0x0904, 0x6080, 0x080c,
-	0x15e4, 0x1118, 0x7007, 0x000f, 0x0005, 0x2d00, 0x7022, 0x70c4,
-	0x2060, 0x2c05, 0x6836, 0xe004, 0xad00, 0x7096, 0xe008, 0xa20a,
-	0x1210, 0xa00e, 0x2200, 0x7112, 0xe20c, 0x8003, 0x800b, 0xa296,
-	0x0004, 0x0108, 0xa108, 0x719a, 0x810b, 0x719e, 0xae90, 0x0022,
-	0x080c, 0x1648, 0x7090, 0xa08e, 0x0100, 0x0170, 0xa086, 0x0200,
-	0x0118, 0x7007, 0x0010, 0x0005, 0x7020, 0x2068, 0x080c, 0x1614,
-	0x7014, 0x2068, 0x0804, 0x5fb0, 0x7020, 0x2068, 0x7018, 0x6802,
-	0x6807, 0x0000, 0x2d08, 0x2068, 0x6906, 0x711a, 0x0804, 0x603b,
-	0x7014, 0x2068, 0x7007, 0x0001, 0x6884, 0xa005, 0x1128, 0x6888,
-	0x698c, 0xa105, 0x0108, 0x00b1, 0x6834, 0xa084, 0x00ff, 0xa086,
-	0x001e, 0x0904, 0x62e0, 0x04b8, 0x6096, 0x609a, 0x0002, 0x0011,
-	0x0007, 0x0004, 0x000a, 0x000f, 0x0005, 0x0006, 0x000a, 0x0011,
-	0x0005, 0x0004, 0x00f6, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x6f88,
-	0x6e8c, 0x6804, 0x2060, 0xacf0, 0x0021, 0xacf8, 0x0027, 0x2009,
-	0x0005, 0x700c, 0x7816, 0x7008, 0x7812, 0x7004, 0x7806, 0x7000,
-	0x7802, 0x7e0e, 0x7f0a, 0x8109, 0x0128, 0xaef2, 0x0004, 0xaffa,
-	0x0006, 0x0c78, 0x6004, 0xa065, 0x1d30, 0x006e, 0x007e, 0x00ce,
-	0x00ee, 0x00fe, 0x0005, 0x2009, 0xb631, 0x210c, 0x81ff, 0x1198,
-	0x6838, 0xa084, 0x00ff, 0x683a, 0x080c, 0x4cd7, 0x1108, 0x0005,
-	0x080c, 0x554d, 0x0126, 0x2091, 0x8000, 0x080c, 0x9f88, 0x080c,
-	0x547a, 0x012e, 0x0ca0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c80,
-	0x2009, 0xb631, 0x210c, 0x81ff, 0x11b0, 0x6858, 0xa005, 0x01c0,
-	0x6838, 0xa084, 0x00ff, 0x683a, 0x6853, 0x0000, 0x080c, 0x4d98,
-	0x1108, 0x0005, 0x0126, 0x2091, 0x8000, 0x684a, 0x6952, 0x080c,
-	0x547a, 0x012e, 0x0cb0, 0x2001, 0x0028, 0x2009, 0x0000, 0x0c90,
-	0x2001, 0x0000, 0x0c78, 0x7018, 0x6802, 0x2d08, 0x2068, 0x6906,
-	0x711a, 0x7010, 0x8001, 0x7012, 0x0118, 0x7007, 0x0006, 0x0030,
-	0x7014, 0x2068, 0x7007, 0x0001, 0x7048, 0x080f, 0x0005, 0x7007,
-	0x0001, 0x6944, 0x810f, 0xa18c, 0x00ff, 0x6848, 0xa084, 0x00ff,
-	0x20a9, 0x0001, 0xa096, 0x0001, 0x01b0, 0x2009, 0x0000, 0x20a9,
-	0x00ff, 0xa096, 0x0002, 0x0178, 0xa005, 0x11f0, 0x6944, 0x810f,
-	0xa18c, 0x00ff, 0x080c, 0x501b, 0x11b8, 0x0066, 0x6e50, 0x080c,
-	0x511a, 0x006e, 0x0088, 0x0046, 0x2011, 0xb60c, 0x2224, 0xc484,
-	0x2412, 0x004e, 0x00c6, 0x080c, 0x501b, 0x1110, 0x080c, 0x527b,
-	0x8108, 0x1f04, 0x614b, 0x00ce, 0x684c, 0xd084, 0x1118, 0x080c,
-	0x1614, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001, 0x2001, 0xb653,
-	0x2004, 0xd0a4, 0x0580, 0x2061, 0xb975, 0x6100, 0xd184, 0x0178,
-	0x6858, 0xa084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004,
-	0xa005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011,
-	0x0001, 0x6860, 0xa005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016,
-	0x6858, 0xa084, 0x00ff, 0x0178, 0x6006, 0x6858, 0x8007, 0xa084,
-	0x00ff, 0x0148, 0x600a, 0x6858, 0x8000, 0x1108, 0xc28d, 0x6202,
-	0x012e, 0x0804, 0x63a4, 0x012e, 0x0804, 0x639e, 0x012e, 0x0804,
-	0x6398, 0x012e, 0x0804, 0x639b, 0x0126, 0x2091, 0x8000, 0x7007,
-	0x0001, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x05e0, 0x2061, 0xb975,
-	0x6000, 0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0x6c48,
-	0xa484, 0x0003, 0x0170, 0x6958, 0xa18c, 0x00ff, 0x8001, 0x1120,
-	0x2100, 0xa210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0xa212,
-	0x02f0, 0xa484, 0x000c, 0x0188, 0x6958, 0x810f, 0xa18c, 0x00ff,
-	0xa082, 0x0004, 0x1120, 0x2100, 0xa318, 0x0288, 0x0030, 0xa082,
-	0x0004, 0x1168, 0x2100, 0xa31a, 0x0250, 0x6860, 0xa005, 0x0110,
-	0x8000, 0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x63a4, 0x012e,
-	0x0804, 0x63a1, 0x012e, 0x0804, 0x639e, 0x0126, 0x2091, 0x8000,
-	0x7007, 0x0001, 0x2061, 0xb975, 0x6300, 0xd38c, 0x1120, 0x6308,
-	0x8318, 0x0220, 0x630a, 0x012e, 0x0804, 0x63b2, 0x012e, 0x0804,
-	0x63a1, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0x684c,
-	0xd0ac, 0x0148, 0x00c6, 0x2061, 0xb975, 0x6000, 0xa084, 0xfcff,
-	0x6002, 0x00ce, 0x0448, 0x6858, 0xa005, 0x05d0, 0x685c, 0xa065,
-	0x0598, 0x2001, 0xb631, 0x2004, 0xa005, 0x0118, 0x080c, 0x9ed9,
-	0x0068, 0x6013, 0x0400, 0x6057, 0x0000, 0x694c, 0xd1a4, 0x0110,
-	0x6950, 0x6156, 0x2009, 0x0041, 0x080c, 0x86d3, 0x6958, 0xa18c,
-	0xff00, 0xa186, 0x2000, 0x1140, 0x0026, 0x2009, 0x0000, 0x2011,
-	0xfdff, 0x080c, 0x6b8c, 0x002e, 0x684c, 0xd0c4, 0x0148, 0x2061,
-	0xb975, 0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a,
-	0x00ce, 0x012e, 0x0804, 0x63a4, 0x00ce, 0x012e, 0x0804, 0x639e,
-	0x6954, 0xa186, 0x002e, 0x0d40, 0xa186, 0x002d, 0x0d28, 0xa186,
-	0x0045, 0x0528, 0xa186, 0x002a, 0x1130, 0x2001, 0xb60c, 0x200c,
-	0xc194, 0x2102, 0x08c8, 0xa186, 0x0020, 0x0170, 0xa186, 0x0029,
-	0x1d18, 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x501b, 0x1960,
-	0x6000, 0xc0e4, 0x6002, 0x0840, 0x685c, 0xa065, 0x09a8, 0x6007,
-	0x0024, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x0804, 0x623c, 0x685c,
-	0xa065, 0x0950, 0x00e6, 0x6860, 0xa075, 0x2001, 0xb631, 0x2004,
-	0xa005, 0x0150, 0x080c, 0x9ed9, 0x8eff, 0x0118, 0x2e60, 0x080c,
-	0x9ed9, 0x00ee, 0x0804, 0x623c, 0x6020, 0xc0dc, 0xc0d5, 0x6022,
-	0x2e60, 0x6007, 0x003a, 0x6870, 0xa005, 0x0130, 0x6007, 0x003b,
-	0x6874, 0x602a, 0x6878, 0x6012, 0x6003, 0x0001, 0x080c, 0x6cff,
-	0x080c, 0x71e5, 0x00ee, 0x0804, 0x623c, 0x2061, 0xb975, 0x6000,
-	0xd084, 0x0190, 0xd08c, 0x1904, 0x63b2, 0x0126, 0x2091, 0x8000,
-	0x6204, 0x8210, 0x0220, 0x6206, 0x012e, 0x0804, 0x63b2, 0x012e,
-	0x6853, 0x0016, 0x0804, 0x63ab, 0x6853, 0x0007, 0x0804, 0x63ab,
-	0x6834, 0x8007, 0xa084, 0x00ff, 0x1118, 0x080c, 0x5f94, 0x0078,
-	0x2030, 0x8001, 0x1120, 0x7007, 0x0001, 0x0051, 0x0040, 0x7007,
-	0x0006, 0x7012, 0x2d00, 0x7016, 0x701a, 0x704b, 0x62e0, 0x0005,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0xa03e, 0x2009, 0xb631, 0x210c,
-	0x81ff, 0x1904, 0x635e, 0x2009, 0xb60c, 0x210c, 0xd194, 0x1904,
-	0x6388, 0x6848, 0x2070, 0xae82, 0xbe00, 0x0a04, 0x6352, 0x2001,
-	0xb617, 0x2004, 0xae02, 0x1a04, 0x6352, 0x711c, 0xa186, 0x0006,
-	0x1904, 0x6341, 0x7018, 0xa005, 0x0904, 0x635e, 0x2004, 0xd0e4,
-	0x1904, 0x6383, 0x2061, 0xb975, 0x6100, 0xa184, 0x0301, 0xa086,
-	0x0001, 0x1550, 0x7020, 0xd0dc, 0x1904, 0x638b, 0x6853, 0x0000,
-	0x6803, 0x0000, 0x2d08, 0x7010, 0xa005, 0x1158, 0x7112, 0x684c,
-	0xd0f4, 0x1904, 0x638e, 0x2e60, 0x080c, 0x6ae8, 0x012e, 0x00ee,
-	0x0005, 0x2068, 0x6800, 0xa005, 0x1de0, 0x6902, 0x2168, 0x684c,
-	0xd0f4, 0x1904, 0x638e, 0x012e, 0x00ee, 0x0005, 0x012e, 0x00ee,
-	0x6853, 0x0006, 0x0804, 0x63ab, 0xd184, 0x0dc0, 0xd1c4, 0x11a8,
-	0x00b8, 0x6944, 0xa18c, 0xff00, 0x810f, 0x080c, 0x501b, 0x15d8,
-	0x6000, 0xd0e4, 0x15c0, 0x711c, 0xa186, 0x0007, 0x1118, 0x6853,
-	0x0002, 0x0498, 0x6853, 0x0008, 0x0480, 0x6853, 0x000e, 0x0468,
-	0x6853, 0x0017, 0x0450, 0x6853, 0x0035, 0x0438, 0x2001, 0xb672,
-	0x2004, 0xd0fc, 0x01e8, 0x6848, 0x2070, 0xae82, 0xbe00, 0x02c0,
-	0x605c, 0xae02, 0x12a8, 0x711c, 0xa186, 0x0006, 0x1188, 0x7018,
-	0xa005, 0x0170, 0x2004, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000,
-	0xa086, 0x0007, 0x1904, 0x62eb, 0x7003, 0x0002, 0x0804, 0x62eb,
-	0x6853, 0x0028, 0x0010, 0x6853, 0x0029, 0x012e, 0x00ee, 0x0418,
-	0x6853, 0x002a, 0x0cd0, 0x6853, 0x0045, 0x0cb8, 0x2e60, 0x2019,
-	0x0002, 0x6017, 0x0014, 0x080c, 0xad9c, 0x012e, 0x00ee, 0x0005,
-	0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009, 0x0006,
-	0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0x6854, 0xa084,
-	0xff00, 0xa105, 0x6856, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a,
-	0x012e, 0x0005, 0x080c, 0x1614, 0x0005, 0x702c, 0x7130, 0x8108,
-	0xa102, 0x0230, 0xa00e, 0x7034, 0x7072, 0x7038, 0x7076, 0x0058,
-	0x7070, 0xa080, 0x0040, 0x7072, 0x1230, 0x7074, 0xa081, 0x0000,
-	0x7076, 0xa085, 0x0001, 0x7932, 0x7132, 0x0005, 0x00d6, 0x080c,
-	0x6adf, 0x00de, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016,
-	0x7007, 0x0001, 0x6a44, 0xa282, 0x0004, 0x1a04, 0x641e, 0xd284,
-	0x0170, 0x6a4c, 0xa290, 0xb735, 0x2204, 0xa065, 0x6004, 0x05e0,
-	0x8007, 0xa084, 0x00ff, 0xa084, 0x0006, 0x1108, 0x04a8, 0x2c10,
-	0x080c, 0x864e, 0x1118, 0x080c, 0x9f92, 0x05a0, 0x621a, 0x6844,
-	0x0002, 0x63fd, 0x6402, 0x6405, 0x640b, 0x2019, 0x0002, 0x080c,
-	0xb121, 0x0060, 0x080c, 0xb0b8, 0x0048, 0x2019, 0x0002, 0x6950,
-	0x080c, 0xb0d3, 0x0018, 0x6950, 0x080c, 0xb0b8, 0x080c, 0x86a4,
-	0x6857, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x547a, 0x012e,
-	0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0x6857, 0x0006,
-	0x0c88, 0x6857, 0x0002, 0x0c70, 0x6857, 0x0005, 0x0c58, 0x6857,
-	0x0004, 0x0c40, 0x6857, 0x0007, 0x0c28, 0x00d6, 0x2011, 0x0004,
-	0x2204, 0xa085, 0x8002, 0x2012, 0x00de, 0x0005, 0x20e1, 0x0002,
-	0x3d08, 0x20e1, 0x2000, 0x3d00, 0xa084, 0x7000, 0x0118, 0xa086,
-	0x1000, 0x1570, 0x20e1, 0x0000, 0x3d00, 0xa094, 0xff00, 0x8217,
-	0xa084, 0xf000, 0xa086, 0x3000, 0x1160, 0xa184, 0xff00, 0x8007,
-	0xa086, 0x0008, 0x11e8, 0x080c, 0x2df4, 0x11d0, 0x080c, 0x6675,
-	0x0098, 0x20e1, 0x0004, 0x3d60, 0xd1bc, 0x1108, 0x3e60, 0xac84,
-	0x0007, 0x1170, 0xac82, 0xbe00, 0x0258, 0x685c, 0xac02, 0x1240,
-	0x2009, 0x0047, 0x080c, 0x86d3, 0x7a1c, 0xd284, 0x1938, 0x0005,
-	0xa016, 0x080c, 0x1863, 0x0cc0, 0x0cd8, 0x781c, 0xd08c, 0x0500,
-	0x0156, 0x0136, 0x0146, 0x20e1, 0x3000, 0x3d20, 0x3e28, 0xa584,
-	0x0076, 0x1538, 0xa484, 0x7000, 0xa086, 0x1000, 0x11a8, 0x080c,
-	0x64f0, 0x01f8, 0x20e1, 0x3000, 0x7828, 0x7828, 0x080c, 0x650c,
-	0x014e, 0x013e, 0x015e, 0x2009, 0xb8e9, 0x2104, 0xa005, 0x1108,
-	0x0005, 0x080c, 0x71e5, 0x0ce0, 0xa484, 0x7000, 0x1548, 0x080c,
-	0x64f0, 0x01d8, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x0d10,
-	0x00a0, 0xd5a4, 0x0178, 0x0056, 0x0046, 0x080c, 0x1e8a, 0x080c,
-	0x24e5, 0x2001, 0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x004e,
-	0x005e, 0x0048, 0x04a9, 0x6887, 0x0000, 0x080c, 0xb49b, 0x20e1,
-	0x3000, 0x7828, 0x7828, 0x00b9, 0x014e, 0x013e, 0x015e, 0x0880,
-	0x0439, 0x1130, 0x7000, 0xa084, 0xff00, 0xa086, 0x8100, 0x1d68,
-	0x080c, 0xb49b, 0x20e1, 0x3000, 0x7828, 0x7828, 0x0056, 0x080c,
-	0x68e6, 0x005e, 0x0c40, 0x2001, 0xb60e, 0x2004, 0xd08c, 0x0178,
-	0x2001, 0xb600, 0x2004, 0xa086, 0x0003, 0x1148, 0x0026, 0x0036,
-	0x2011, 0x8048, 0x2518, 0x080c, 0x3f13, 0x003e, 0x002e, 0x0005,
-	0xa484, 0x01ff, 0x6886, 0xa005, 0x0160, 0xa080, 0x001f, 0xa084,
-	0x03f8, 0x80ac, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a, 0x53a5,
-	0x0005, 0x20a9, 0x000c, 0x20e1, 0x1000, 0x2ea0, 0x2099, 0x020a,
-	0x53a5, 0xa085, 0x0001, 0x0ca0, 0x7000, 0xa084, 0xff00, 0xa08c,
-	0xf000, 0x8007, 0xa196, 0x0000, 0x1118, 0x0804, 0x677a, 0x0005,
-	0xa196, 0x2000, 0x1148, 0x6900, 0xa18e, 0x0001, 0x1118, 0x080c,
-	0x44d6, 0x0ca8, 0x0039, 0x0c98, 0xa196, 0x8000, 0x1d80, 0x080c,
-	0x6826, 0x0c68, 0x00c6, 0x6a84, 0x82ff, 0x0904, 0x666f, 0x7110,
-	0xa18c, 0xff00, 0x810f, 0xa196, 0x0001, 0x0120, 0xa196, 0x0023,
-	0x1904, 0x666f, 0xa08e, 0x0023, 0x1570, 0x080c, 0x68c1, 0x0904,
-	0x666f, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1150, 0x7034,
-	0xa005, 0x1904, 0x666f, 0x2009, 0x0015, 0x080c, 0x86d3, 0x0804,
-	0x666f, 0xa08e, 0x0214, 0x0118, 0xa08e, 0x0210, 0x1130, 0x2009,
-	0x0015, 0x080c, 0x86d3, 0x0804, 0x666f, 0xa08e, 0x0100, 0x1904,
-	0x666f, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x0016, 0x080c,
-	0x86d3, 0x0804, 0x666f, 0xa08e, 0x0022, 0x1904, 0x666f, 0x7030,
-	0xa08e, 0x0300, 0x1580, 0x68d4, 0xd0a4, 0x0528, 0xc0b5, 0x68d6,
-	0x7100, 0xa18c, 0x00ff, 0x6972, 0x7004, 0x6876, 0x00f6, 0x2079,
-	0x0100, 0x79e6, 0x78ea, 0x0006, 0xa084, 0x00ff, 0x0016, 0x2008,
-	0x080c, 0x287c, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c,
-	0x2852, 0x6952, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071,
-	0xb600, 0x70a6, 0x00ee, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009,
-	0x0017, 0x0804, 0x6635, 0xa08e, 0x0400, 0x1158, 0x7034, 0xa005,
-	0x1904, 0x666f, 0x68d4, 0xc0a5, 0x68d6, 0x2009, 0x0030, 0x0804,
-	0x6635, 0xa08e, 0x0500, 0x1140, 0x7034, 0xa005, 0x1904, 0x666f,
-	0x2009, 0x0018, 0x0804, 0x6635, 0xa08e, 0x2010, 0x1120, 0x2009,
-	0x0019, 0x0804, 0x6635, 0xa08e, 0x2110, 0x1120, 0x2009, 0x001a,
-	0x0804, 0x6635, 0xa08e, 0x5200, 0x1140, 0x7034, 0xa005, 0x1904,
-	0x666f, 0x2009, 0x001b, 0x0804, 0x6635, 0xa08e, 0x5000, 0x1140,
-	0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x001c, 0x0804, 0x6635,
-	0xa08e, 0x1300, 0x1120, 0x2009, 0x0034, 0x0804, 0x6635, 0xa08e,
-	0x1200, 0x1140, 0x7034, 0xa005, 0x1904, 0x666f, 0x2009, 0x0024,
-	0x0804, 0x6635, 0xa08c, 0xff00, 0xa18e, 0x2400, 0x1118, 0x2009,
-	0x002d, 0x04d8, 0xa08c, 0xff00, 0xa18e, 0x5300, 0x1118, 0x2009,
-	0x002a, 0x0498, 0xa08e, 0x0f00, 0x1118, 0x2009, 0x0020, 0x0468,
-	0xa08e, 0x5300, 0x1108, 0x00d8, 0xa08e, 0x6104, 0x11c0, 0x2011,
-	0xbc8d, 0x8208, 0x2204, 0xa082, 0x0004, 0x20a8, 0x95ac, 0x95ac,
-	0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x3f13,
-	0x004e, 0x8108, 0x1f04, 0x6618, 0x2009, 0x0023, 0x0070, 0xa08e,
-	0x6000, 0x1118, 0x2009, 0x003f, 0x0040, 0xa08e, 0x7800, 0x1118,
-	0x2009, 0x0045, 0x0010, 0x2009, 0x001d, 0x0016, 0x2011, 0xbc83,
-	0x2204, 0x8211, 0x220c, 0x080c, 0x2852, 0x1598, 0x080c, 0x4fbf,
-	0x1580, 0x6612, 0x6516, 0x86ff, 0x01e8, 0x001e, 0x0016, 0xa186,
-	0x0017, 0x1158, 0x6870, 0xa606, 0x11a8, 0x6874, 0xa506, 0xa084,
-	0xff00, 0x1180, 0x6000, 0xc0f5, 0x6002, 0xa186, 0x0046, 0x1150,
-	0x6870, 0xa606, 0x1138, 0x6874, 0xa506, 0xa084, 0xff00, 0x1110,
-	0x001e, 0x0068, 0x00c6, 0x080c, 0x864e, 0x0168, 0x001e, 0x611a,
-	0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c, 0x86d3, 0x00ce,
-	0x0005, 0x001e, 0x0ce0, 0x00ce, 0x0ce0, 0x00c6, 0x0046, 0x080c,
-	0x66c9, 0x1904, 0x66c6, 0xa28e, 0x0033, 0x11e8, 0x080c, 0x68c1,
-	0x0904, 0x66c6, 0x7124, 0x610a, 0x7030, 0xa08e, 0x0200, 0x1140,
-	0x7034, 0xa005, 0x15d8, 0x2009, 0x0015, 0x080c, 0x86d3, 0x04b0,
-	0xa08e, 0x0100, 0x1598, 0x7034, 0xa005, 0x1580, 0x2009, 0x0016,
-	0x080c, 0x86d3, 0x0458, 0xa28e, 0x0032, 0x1540, 0x7030, 0xa08e,
-	0x1400, 0x1520, 0x2009, 0x0038, 0x0016, 0x2011, 0xbc83, 0x2204,
-	0x8211, 0x220c, 0x080c, 0x2852, 0x11c0, 0x080c, 0x4fbf, 0x11a8,
-	0x6612, 0x6516, 0x00c6, 0x080c, 0x864e, 0x0170, 0x001e, 0x611a,
-	0x080c, 0xa0e3, 0x601f, 0x0004, 0x7120, 0x610a, 0x001e, 0x080c,
-	0x86d3, 0x080c, 0x71e5, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce,
-	0x0005, 0x00f6, 0x00d6, 0x0026, 0x0016, 0x0136, 0x0146, 0x0156,
-	0x3c00, 0x0006, 0x2079, 0x0030, 0x2069, 0x0200, 0x080c, 0x1f49,
-	0x1590, 0x080c, 0x1dee, 0x05e0, 0x04f1, 0x1130, 0x7908, 0xa18c,
-	0x1fff, 0xa182, 0x0011, 0x1688, 0x20a9, 0x000c, 0x20e1, 0x0000,
-	0x2ea0, 0x2099, 0x020a, 0x53a5, 0x20e1, 0x2000, 0x2001, 0x020a,
-	0x2004, 0x7a0c, 0x7808, 0xa080, 0x0007, 0xa084, 0x1ff8, 0x0419,
-	0x1120, 0xa08a, 0x0140, 0x1a0c, 0x151a, 0x80ac, 0x20e1, 0x6000,
-	0x2099, 0x020a, 0x53a5, 0x20e1, 0x7000, 0x6828, 0x6828, 0x7803,
-	0x0004, 0xa294, 0x0070, 0x000e, 0x20e0, 0x015e, 0x014e, 0x013e,
-	0x001e, 0x002e, 0x00de, 0x00fe, 0x0005, 0xa016, 0x080c, 0x1863,
-	0xa085, 0x0001, 0x0c80, 0x0006, 0x2001, 0x0111, 0x2004, 0xa084,
-	0x0003, 0x000e, 0x0005, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130,
-	0xa696, 0x00ff, 0x1198, 0xa596, 0xfffd, 0x1120, 0x2009, 0x007f,
-	0x0804, 0x6775, 0xa596, 0xfffe, 0x1118, 0x2009, 0x007e, 0x04e8,
-	0xa596, 0xfffc, 0x1118, 0x2009, 0x0080, 0x04b8, 0x2011, 0x0000,
-	0x2019, 0xb635, 0x231c, 0xd3ac, 0x0138, 0x2021, 0x0000, 0x20a9,
-	0x00ff, 0x2071, 0xb735, 0x0030, 0x2021, 0x0081, 0x20a9, 0x007e,
-	0x2071, 0xb7b6, 0x2e1c, 0x83ff, 0x1128, 0x82ff, 0x1198, 0x2410,
-	0xc2fd, 0x0080, 0x2368, 0x6f10, 0x0006, 0x2100, 0xa706, 0x000e,
-	0x6b14, 0x1120, 0xa346, 0x1110, 0x2408, 0x0078, 0x87ff, 0x1110,
-	0x83ff, 0x0d58, 0x8420, 0x8e70, 0x1f04, 0x6752, 0x82ff, 0x1118,
-	0xa085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0xa006, 0x00de, 0x00ee,
-	0x004e, 0x0005, 0xa084, 0x0007, 0x000a, 0x0005, 0x6786, 0x6786,
-	0x6786, 0x68d3, 0x6786, 0x6787, 0x679c, 0x6811, 0x0005, 0x7110,
-	0xd1bc, 0x0188, 0x7120, 0x2160, 0xac8c, 0x0007, 0x1160, 0xac8a,
-	0xbe00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124, 0x610a, 0x2009,
-	0x0046, 0x080c, 0x86d3, 0x0005, 0x00c6, 0xa484, 0x01ff, 0x0904,
-	0x67ef, 0x7110, 0xd1bc, 0x1904, 0x67ef, 0x2011, 0xbc83, 0x2204,
-	0x8211, 0x220c, 0x080c, 0x2852, 0x1904, 0x67ef, 0x080c, 0x4fbf,
-	0x15f0, 0x6612, 0x6516, 0x6000, 0xd0ec, 0x15c8, 0x6204, 0xa294,
-	0xff00, 0x8217, 0xa286, 0x0006, 0x0148, 0x6204, 0xa294, 0x00ff,
-	0xa286, 0x0006, 0x11a0, 0xa295, 0x0600, 0x6206, 0x00c6, 0x080c,
-	0x864e, 0x001e, 0x0530, 0x611a, 0x601f, 0x0006, 0x7120, 0x610a,
-	0x7130, 0x6152, 0x2009, 0x0044, 0x080c, 0x86d3, 0x00c0, 0x00c6,
-	0x080c, 0x864e, 0x001e, 0x0198, 0x611a, 0x601f, 0x0004, 0x7120,
-	0x610a, 0xa286, 0x0004, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007,
-	0x0001, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00ce,
-	0x0005, 0x2001, 0xb60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049,
-	0x080c, 0x3f13, 0x00c6, 0x080c, 0x9f92, 0x001e, 0x0d80, 0x611a,
-	0x601f, 0x0006, 0x7120, 0x610a, 0x7130, 0x6152, 0x6013, 0x0300,
-	0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5,
-	0x08f0, 0x7110, 0xd1bc, 0x0188, 0x7020, 0x2060, 0xac84, 0x0007,
-	0x1160, 0xac82, 0xbe00, 0x0248, 0x685c, 0xac02, 0x1230, 0x7124,
-	0x610a, 0x2009, 0x0045, 0x080c, 0x86d3, 0x0005, 0x0006, 0x080c,
-	0x2df4, 0x000e, 0x1168, 0x7110, 0xa18c, 0xff00, 0x810f, 0xa18e,
-	0x0000, 0x1130, 0xa084, 0x000f, 0xa08a, 0x0006, 0x1208, 0x000b,
-	0x0005, 0x683f, 0x6840, 0x683f, 0x683f, 0x68a9, 0x68b5, 0x0005,
-	0x7110, 0xd1bc, 0x0120, 0x702c, 0xd084, 0x0904, 0x68a8, 0x700c,
-	0x7108, 0x080c, 0x2852, 0x1904, 0x68a8, 0x080c, 0x4fbf, 0x1904,
-	0x68a8, 0x6612, 0x6516, 0x6204, 0x7110, 0xd1bc, 0x01f8, 0xa28c,
-	0x00ff, 0xa186, 0x0004, 0x0118, 0xa186, 0x0006, 0x15c8, 0x00c6,
-	0x080c, 0x68c1, 0x00ce, 0x0904, 0x68a8, 0x00c6, 0x080c, 0x864e,
-	0x001e, 0x05f0, 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0002, 0x7120,
-	0x610a, 0x2009, 0x0088, 0x080c, 0x86d3, 0x0490, 0xa28c, 0x00ff,
-	0xa186, 0x0006, 0x0160, 0xa186, 0x0004, 0x0148, 0xa294, 0xff00,
-	0x8217, 0xa286, 0x0004, 0x0118, 0xa286, 0x0006, 0x1188, 0x00c6,
-	0x080c, 0x864e, 0x001e, 0x01e0, 0x611a, 0x080c, 0xa0e3, 0x601f,
-	0x0005, 0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0x86d3, 0x0080,
-	0x00c6, 0x080c, 0x864e, 0x001e, 0x0158, 0x611a, 0x080c, 0xa0e3,
-	0x601f, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0x86d3,
-	0x0005, 0x7110, 0xd1bc, 0x0140, 0x00a1, 0x0130, 0x7124, 0x610a,
-	0x2009, 0x0089, 0x080c, 0x86d3, 0x0005, 0x7110, 0xd1bc, 0x0140,
-	0x0041, 0x0130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c, 0x86d3,
-	0x0005, 0x7020, 0x2060, 0xac84, 0x0007, 0x1158, 0xac82, 0xbe00,
-	0x0240, 0x2001, 0xb617, 0x2004, 0xac02, 0x1218, 0xa085, 0x0001,
-	0x0005, 0xa006, 0x0ce8, 0x7110, 0xd1bc, 0x1178, 0x7024, 0x2060,
-	0xac84, 0x0007, 0x1150, 0xac82, 0xbe00, 0x0238, 0x685c, 0xac02,
-	0x1220, 0x2009, 0x0051, 0x080c, 0x86d3, 0x0005, 0x2031, 0x0105,
-	0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031, 0x0207,
-	0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6, 0x00d6,
-	0x00f6, 0x7000, 0xa084, 0xf000, 0xa086, 0xc000, 0x05b0, 0x080c,
-	0x864e, 0x0598, 0x0066, 0x00c6, 0x0046, 0x2011, 0xbc83, 0x2204,
-	0x8211, 0x220c, 0x080c, 0x2852, 0x1580, 0x080c, 0x4fbf, 0x1568,
-	0x6612, 0x6516, 0x2c00, 0x004e, 0x00ce, 0x601a, 0x080c, 0xa0e3,
-	0x080c, 0x15fd, 0x01f0, 0x2d00, 0x6056, 0x6803, 0x0000, 0x6837,
-	0x0000, 0x6c3a, 0xadf8, 0x000f, 0x20a9, 0x000e, 0x2fa0, 0x2e98,
-	0x53a3, 0x006e, 0x6612, 0x6007, 0x003e, 0x601f, 0x0001, 0x6003,
-	0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00fe, 0x00de, 0x00ce,
-	0x0005, 0x080c, 0x86a4, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8,
-	0x2071, 0xb8f4, 0x7003, 0x0003, 0x700f, 0x0361, 0xa006, 0x701a,
-	0x7076, 0x7012, 0x7017, 0xbe00, 0x7007, 0x0000, 0x7026, 0x702b,
-	0x7e0a, 0x7032, 0x7037, 0x7e6a, 0x703b, 0xffff, 0x703f, 0xffff,
-	0x7042, 0x7047, 0x4492, 0x704a, 0x705b, 0x6a9d, 0x2001, 0xb8a1,
-	0x2003, 0x0003, 0x2001, 0xb8a3, 0x2003, 0x0100, 0x3a00, 0xa084,
-	0x0005, 0x706e, 0x0005, 0x2071, 0xb8f4, 0x1d04, 0x69fd, 0x2091,
-	0x6000, 0x700c, 0x8001, 0x700e, 0x1518, 0x700f, 0x0361, 0x7007,
-	0x0001, 0x0126, 0x2091, 0x8000, 0x7040, 0xa00d, 0x0128, 0x8109,
-	0x7142, 0x1110, 0x7044, 0x080f, 0x00c6, 0x2061, 0xb600, 0x6034,
-	0x00ce, 0xd0cc, 0x0180, 0x3a00, 0xa084, 0x0005, 0x726c, 0xa216,
-	0x0150, 0x706e, 0x2011, 0x8043, 0x2018, 0x080c, 0x3f13, 0x0018,
-	0x0126, 0x2091, 0x8000, 0x7024, 0xa00d, 0x0188, 0x7020, 0x8001,
-	0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0xa186, 0x03e8,
-	0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030,
-	0xa00d, 0x0180, 0x702c, 0x8001, 0x702e, 0x1160, 0x702f, 0x0009,
-	0x8109, 0x7132, 0x0128, 0xa184, 0x007f, 0x090c, 0x7eaf, 0x0010,
-	0x7034, 0x080f, 0x7038, 0xa005, 0x0118, 0x0310, 0x8001, 0x703a,
-	0x703c, 0xa005, 0x0118, 0x0310, 0x8001, 0x703e, 0x704c, 0xa00d,
-	0x0168, 0x7048, 0x8001, 0x704a, 0x1148, 0x704b, 0x0009, 0x8109,
-	0x714e, 0x1120, 0x7150, 0x714e, 0x7058, 0x080f, 0x7018, 0xa00d,
-	0x01d8, 0x0016, 0x7074, 0xa00d, 0x0158, 0x7070, 0x8001, 0x7072,
-	0x1138, 0x7073, 0x0009, 0x8109, 0x7176, 0x1110, 0x7078, 0x080f,
-	0x001e, 0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109,
-	0x711a, 0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x6a23,
-	0x6a24, 0x6a3c, 0x00e6, 0x2071, 0xb8f4, 0x7018, 0xa005, 0x1120,
-	0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006,
-	0x2071, 0xb8f4, 0x701c, 0xa206, 0x1110, 0x701a, 0x701e, 0x000e,
-	0x00ee, 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x6088, 0xa102, 0x0208,
-	0x618a, 0x00ee, 0x0005, 0x0005, 0x7110, 0x080c, 0x501b, 0x1158,
-	0x6088, 0x8001, 0x0240, 0x608a, 0x1130, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x71e5, 0x012e, 0x8108, 0xa182, 0x00ff, 0x0218, 0xa00e,
-	0x7007, 0x0002, 0x7112, 0x0005, 0x7014, 0x2060, 0x0126, 0x2091,
-	0x8000, 0x603c, 0xa005, 0x0128, 0x8001, 0x603e, 0x1110, 0x080c,
-	0x9fd1, 0x6014, 0xa005, 0x0500, 0x8001, 0x6016, 0x11e8, 0x611c,
-	0xa186, 0x0003, 0x0118, 0xa186, 0x0006, 0x11a0, 0x6010, 0x2068,
-	0x6854, 0xa08a, 0x199a, 0x0270, 0xa082, 0x1999, 0x6856, 0xa08a,
-	0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0xa108,
-	0x6116, 0x0010, 0x080c, 0x9aa1, 0x012e, 0xac88, 0x0018, 0x7116,
-	0x2001, 0xee00, 0xa102, 0x0220, 0x7017, 0xbe00, 0x7007, 0x0000,
-	0x0005, 0x00e6, 0x2071, 0xb8f4, 0x7027, 0x07d0, 0x7023, 0x0009,
-	0x00ee, 0x0005, 0x2001, 0xb8fd, 0x2003, 0x0000, 0x0005, 0x00e6,
-	0x2071, 0xb8f4, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005, 0x2011,
-	0xb900, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0xb8f4, 0x711a,
-	0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00c6, 0x0026, 0x7054,
-	0x8000, 0x7056, 0x2061, 0xb8a1, 0x6008, 0xa086, 0x0000, 0x0158,
-	0x7068, 0x6032, 0x7064, 0x602e, 0x7060, 0x602a, 0x705c, 0x6026,
-	0x2c10, 0x080c, 0x1648, 0x002e, 0x00ce, 0x0005, 0x0006, 0x0016,
-	0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x696b, 0x00fe, 0x00ee,
-	0x00de, 0x00ce, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0xb8f4,
-	0x7176, 0x727a, 0x7073, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006,
-	0x2071, 0xb8f4, 0x7078, 0xa206, 0x1110, 0x7076, 0x707a, 0x000e,
-	0x00ee, 0x0005, 0x00c6, 0x2061, 0xb975, 0x00ce, 0x0005, 0xa184,
-	0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0xb975, 0x2060, 0x0005,
-	0x6854, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0xa005, 0x1150,
-	0x00c6, 0x2061, 0xb975, 0x6014, 0x00ce, 0xa005, 0x1138, 0x2001,
-	0x001e, 0x0020, 0xa08e, 0xffff, 0x1108, 0xa006, 0x8003, 0x800b,
-	0x810b, 0xa108, 0x6116, 0x684c, 0xa08c, 0x00c0, 0xa18e, 0x00c0,
-	0x05e8, 0xd0b4, 0x1138, 0xd0bc, 0x1550, 0x2009, 0x0006, 0x080c,
-	0x6b63, 0x0005, 0xd0fc, 0x0138, 0xa084, 0x0003, 0x0120, 0xa086,
-	0x0003, 0x1904, 0x6b5d, 0x6020, 0xd0d4, 0x0130, 0xc0d4, 0x6022,
-	0x6860, 0x602a, 0x685c, 0x602e, 0x2009, 0xb674, 0x2104, 0xd084,
-	0x0138, 0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0x86d3, 0x0005,
-	0x87ff, 0x1120, 0x2009, 0x0043, 0x080c, 0x86d3, 0x0005, 0xd0fc,
-	0x0130, 0xa084, 0x0003, 0x0118, 0xa086, 0x0003, 0x11f0, 0x87ff,
-	0x1120, 0x2009, 0x0042, 0x080c, 0x86d3, 0x0005, 0xd0fc, 0x0160,
-	0xa084, 0x0003, 0xa08e, 0x0002, 0x0148, 0x87ff, 0x1120, 0x2009,
-	0x0041, 0x080c, 0x86d3, 0x0005, 0x0061, 0x0ce8, 0x87ff, 0x1dd8,
-	0x2009, 0x0043, 0x080c, 0x86d3, 0x0cb0, 0x2009, 0x0004, 0x0019,
-	0x0005, 0x2009, 0x0001, 0x00d6, 0x6010, 0xa0ec, 0xf000, 0x0510,
-	0x2068, 0x6952, 0x6800, 0x6012, 0xa186, 0x0001, 0x1188, 0x694c,
-	0xa18c, 0x8100, 0xa18e, 0x8100, 0x1158, 0x00c6, 0x2061, 0xb975,
-	0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce,
-	0x080c, 0x547a, 0x6010, 0xa06d, 0x0076, 0x2039, 0x0000, 0x190c,
-	0x6ae8, 0x007e, 0x00de, 0x0005, 0x0156, 0x00c6, 0x2061, 0xb975,
-	0x6000, 0x81ff, 0x0110, 0xa205, 0x0008, 0xa204, 0x6002, 0x00ce,
-	0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0xa005, 0x0120,
-	0x8001, 0x680a, 0xa085, 0x0001, 0x0005, 0x20a9, 0x0010, 0xa006,
-	0x8004, 0x8086, 0x818e, 0x1208, 0xa200, 0x1f04, 0x6ba9, 0x8086,
-	0x818e, 0x0005, 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a,
-	0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x6bb9,
-	0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04, 0x6bb9, 0x0006, 0x3200,
-	0xa084, 0xefff, 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200,
-	0xa085, 0x1000, 0x0cb8, 0x0126, 0x2091, 0x2800, 0x2079, 0xb8e1,
-	0x012e, 0x00d6, 0x2069, 0xb8e1, 0x6803, 0x0005, 0x2069, 0x0004,
-	0x2d04, 0xa085, 0x8001, 0x206a, 0x00de, 0x0005, 0x00c6, 0x6027,
-	0x0001, 0x7804, 0xa084, 0x0007, 0x0002, 0x6bf7, 0x6c18, 0x6c6b,
-	0x6bfd, 0x6c18, 0x6bf7, 0x6bf5, 0x6bf5, 0x080c, 0x151a, 0x080c,
-	0x6a82, 0x080c, 0x71e5, 0x00ce, 0x0005, 0x62c0, 0x82ff, 0x1110,
-	0x00ce, 0x0005, 0x2011, 0x4b23, 0x080c, 0x6a0e, 0x7828, 0xa092,
-	0x00c8, 0x1228, 0x8000, 0x782a, 0x080c, 0x4b65, 0x0c88, 0x080c,
-	0x4b23, 0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c40,
-	0x080c, 0x6a82, 0x3c00, 0x0006, 0x2011, 0x0209, 0x20e1, 0x4000,
-	0x2214, 0x000e, 0x20e0, 0x82ff, 0x0178, 0x62c0, 0x82ff, 0x1160,
-	0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x151a, 0x2009, 0x0013,
-	0x080c, 0x86d3, 0x00ce, 0x0005, 0x3900, 0xa082, 0xba2d, 0x1210,
-	0x080c, 0x83b9, 0x00c6, 0x7824, 0xa065, 0x090c, 0x151a, 0x7804,
-	0xa086, 0x0004, 0x0904, 0x6cab, 0x7828, 0xa092, 0x2710, 0x1230,
-	0x8000, 0x782a, 0x00ce, 0x080c, 0x7de6, 0x0c20, 0x6104, 0xa186,
-	0x0003, 0x1188, 0x00e6, 0x2071, 0xb600, 0x70e0, 0x00ee, 0xd08c,
-	0x0150, 0x00c6, 0x00e6, 0x2061, 0x0100, 0x2071, 0xb600, 0x080c,
-	0x4b7b, 0x00ee, 0x00ce, 0x080c, 0xb500, 0x2009, 0x0014, 0x080c,
-	0x86d3, 0x00ce, 0x0838, 0x2001, 0xb8fd, 0x2003, 0x0000, 0x62c0,
-	0x82ff, 0x1160, 0x782b, 0x0000, 0x7824, 0xa065, 0x090c, 0x151a,
-	0x2009, 0x0013, 0x080c, 0x872c, 0x00ce, 0x0005, 0x00c6, 0x00d6,
-	0x3900, 0xa082, 0xba2d, 0x1210, 0x080c, 0x83b9, 0x7824, 0xa005,
-	0x090c, 0x151a, 0x781c, 0xa06d, 0x090c, 0x151a, 0x6800, 0xc0dc,
-	0x6802, 0x7924, 0x2160, 0x080c, 0x86a4, 0x693c, 0x81ff, 0x090c,
-	0x151a, 0x8109, 0x693e, 0x6854, 0xa015, 0x0110, 0x7a1e, 0x0010,
-	0x7918, 0x791e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce,
-	0x080c, 0x71e5, 0x0888, 0x6104, 0xa186, 0x0002, 0x0128, 0xa186,
-	0x0004, 0x0110, 0x0804, 0x6c44, 0x7808, 0xac06, 0x0904, 0x6c44,
-	0x080c, 0x7102, 0x080c, 0x6d45, 0x00ce, 0x080c, 0x71e5, 0x0804,
-	0x6c32, 0x00c6, 0x6027, 0x0002, 0x62c8, 0x60c4, 0xa205, 0x1178,
-	0x793c, 0xa1e5, 0x0000, 0x0130, 0x2009, 0x0049, 0x080c, 0x86d3,
-	0x00ce, 0x0005, 0x2011, 0xb900, 0x2013, 0x0000, 0x0cc8, 0x3908,
-	0xa192, 0xba2d, 0x1210, 0x080c, 0x83b9, 0x793c, 0x81ff, 0x0d90,
-	0x7944, 0xa192, 0x7530, 0x12b8, 0x8108, 0x7946, 0x793c, 0xa188,
-	0x0007, 0x210c, 0xa18e, 0x0006, 0x1138, 0x6014, 0xa084, 0x0184,
-	0xa085, 0x0012, 0x6016, 0x08e0, 0x6014, 0xa084, 0x0184, 0xa085,
-	0x0016, 0x6016, 0x08a8, 0x7848, 0xc085, 0x784a, 0x0888, 0x0006,
-	0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08,
-	0x2061, 0xb8e1, 0x6020, 0x8000, 0x6022, 0x6010, 0xa005, 0x0148,
-	0xa080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e,
-	0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0xb8e1, 0x6000,
-	0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0xa086, 0x0001, 0x1110,
-	0x2c00, 0x681e, 0x6804, 0xa084, 0x0007, 0x0804, 0x71eb, 0xc0d5,
-	0x6002, 0x6818, 0xa005, 0x0158, 0x6056, 0x605b, 0x0000, 0x0006,
-	0x2c00, 0x681a, 0x00de, 0x685a, 0x2069, 0xb8e1, 0x0c18, 0x6056,
-	0x605a, 0x2c00, 0x681a, 0x681e, 0x08e8, 0x0006, 0x0016, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb8e1,
-	0x6020, 0x8000, 0x6022, 0x6008, 0xa005, 0x0148, 0xa080, 0x0003,
-	0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e, 0x0005, 0x610e,
-	0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08, 0x2061, 0xb8e1,
-	0x6034, 0xa005, 0x0130, 0xa080, 0x0003, 0x2102, 0x6136, 0x00ce,
-	0x0005, 0x613a, 0x6136, 0x0cd8, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
-	0x0076, 0x0066, 0x0056, 0x0036, 0x0026, 0x0016, 0x0006, 0x0126,
-	0xa02e, 0x2071, 0xb8e1, 0x7638, 0x2660, 0x2678, 0x2091, 0x8000,
-	0x8cff, 0x0904, 0x6ded, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206,
-	0x1904, 0x6de8, 0x87ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6de8,
-	0x703c, 0xac06, 0x1190, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b,
-	0x7033, 0x0000, 0x703f, 0x0000, 0x7043, 0x0000, 0x7047, 0x0000,
-	0x704b, 0x0000, 0x003e, 0x2029, 0x0001, 0x7038, 0xac36, 0x1110,
-	0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118,
-	0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00,
-	0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c,
-	0x9d16, 0x01c8, 0x6010, 0x2068, 0x601c, 0xa086, 0x0003, 0x1580,
-	0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000, 0x0016, 0x0036, 0x0076,
-	0x080c, 0x9f88, 0x080c, 0xb43c, 0x080c, 0x547a, 0x007e, 0x003e,
-	0x001e, 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x00ce, 0x0804, 0x6d88,
-	0x2c78, 0x600c, 0x2060, 0x0804, 0x6d88, 0x85ff, 0x0120, 0x0036,
-	0x080c, 0x72a2, 0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e,
-	0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005,
-	0x601c, 0xa086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c,
-	0xb43c, 0x080c, 0xb155, 0x007e, 0x003e, 0x001e, 0x08a0, 0x601c,
-	0xa086, 0x000a, 0x0904, 0x6dd2, 0x0804, 0x6dd0, 0x0006, 0x0066,
-	0x00c6, 0x00d6, 0x00f6, 0x2031, 0x0000, 0x0126, 0x2091, 0x8000,
-	0x2079, 0xb8e1, 0x7838, 0xa065, 0x0568, 0x600c, 0x0006, 0x600f,
-	0x0000, 0x783c, 0xac06, 0x1180, 0x0036, 0x2019, 0x0001, 0x080c,
-	0x806b, 0x7833, 0x0000, 0x783f, 0x0000, 0x7843, 0x0000, 0x7847,
-	0x0000, 0x784b, 0x0000, 0x003e, 0x080c, 0x9d16, 0x0178, 0x6010,
-	0x2068, 0x601c, 0xa086, 0x0003, 0x11b0, 0x6837, 0x0103, 0x6b4a,
-	0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0x9ed9,
-	0x000e, 0x0888, 0x7e3a, 0x7e36, 0x012e, 0x00fe, 0x00de, 0x00ce,
-	0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c,
-	0xb155, 0x0c60, 0x601c, 0xa086, 0x000a, 0x0d08, 0x08f0, 0x0016,
-	0x0026, 0x0086, 0x2041, 0x0000, 0x0099, 0x080c, 0x6f35, 0x008e,
-	0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0xb8e1, 0x2091,
-	0x8000, 0x080c, 0x6fc2, 0x080c, 0x7034, 0x012e, 0x00fe, 0x0005,
-	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126,
-	0x2091, 0x8000, 0x2071, 0xb8e1, 0x7614, 0x2660, 0x2678, 0x8cff,
-	0x0904, 0x6f0b, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904,
-	0x6f06, 0x88ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x6f06, 0x7024,
-	0xac06, 0x1538, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0, 0x080c,
-	0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x0020, 0x6003, 0x0009, 0x630a,
-	0x04e8, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010, 0xac36,
-	0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010, 0x7013,
-	0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008,
-	0x2678, 0x600f, 0x0000, 0x6010, 0x2068, 0x080c, 0x9d16, 0x01b8,
-	0x601c, 0xa086, 0x0003, 0x1540, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0x9f88, 0x080c, 0xb43c,
-	0x080c, 0x547a, 0x008e, 0x003e, 0x001e, 0x080c, 0x9ecd, 0x080c,
-	0x9ed9, 0x080c, 0x81a5, 0x00ce, 0x0804, 0x6e8f, 0x2c78, 0x600c,
-	0x2060, 0x0804, 0x6e8f, 0x012e, 0x000e, 0x001e, 0x006e, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1158,
-	0x0016, 0x0036, 0x0086, 0x080c, 0xb43c, 0x080c, 0xb155, 0x008e,
-	0x003e, 0x001e, 0x08e0, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004,
-	0xa086, 0x0085, 0x0908, 0x0898, 0x601c, 0xa086, 0x0005, 0x1978,
-	0x6004, 0xa086, 0x0085, 0x0d20, 0x0850, 0x00c6, 0x0006, 0x0126,
-	0x2091, 0x8000, 0xa280, 0xb735, 0x2004, 0xa065, 0x0904, 0x6fbe,
-	0x00f6, 0x00e6, 0x00d6, 0x0066, 0x2071, 0xb8e1, 0x6654, 0x7018,
-	0xac06, 0x1108, 0x761a, 0x701c, 0xac06, 0x1130, 0x86ff, 0x1118,
-	0x7018, 0x701e, 0x0008, 0x761e, 0x6058, 0xa07d, 0x0108, 0x7e56,
-	0xa6ed, 0x0000, 0x0110, 0x2f00, 0x685a, 0x6057, 0x0000, 0x605b,
-	0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4f46, 0x0904,
-	0x6fba, 0x7624, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004, 0xad06,
-	0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548, 0x080c,
-	0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c, 0xa005,
-	0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9ed9, 0x00ce, 0x0048,
-	0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce, 0x0804,
-	0x6f65, 0x8dff, 0x0158, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
-	0x080c, 0x9f88, 0x080c, 0xb43c, 0x080c, 0x547a, 0x080c, 0x81a5,
-	0x0804, 0x6f65, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e, 0x000e,
-	0x00ce, 0x0005, 0x0006, 0x0066, 0x00c6, 0x00d6, 0x2031, 0x0000,
-	0x7814, 0xa065, 0x0904, 0x7014, 0x600c, 0x0006, 0x600f, 0x0000,
-	0x7824, 0xac06, 0x1540, 0x2069, 0x0100, 0x68c0, 0xa005, 0x01f0,
-	0x080c, 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4,
-	0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
-	0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003, 0x0009,
-	0x630a, 0x2c30, 0x00b0, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0168,
-	0x601c, 0xa086, 0x0003, 0x11b8, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x080c,
-	0x81a5, 0x000e, 0x0804, 0x6fc9, 0x7e16, 0x7e12, 0x00de, 0x00ce,
-	0x006e, 0x000e, 0x0005, 0x601c, 0xa086, 0x0006, 0x1118, 0x080c,
-	0xb155, 0x0c58, 0x601c, 0xa086, 0x0002, 0x1128, 0x6004, 0xa086,
-	0x0085, 0x09d0, 0x0c10, 0x601c, 0xa086, 0x0005, 0x19f0, 0x6004,
-	0xa086, 0x0085, 0x0d60, 0x08c8, 0x0006, 0x0066, 0x00c6, 0x00d6,
-	0x7818, 0xa065, 0x0904, 0x709a, 0x6054, 0x0006, 0x6057, 0x0000,
-	0x605b, 0x0000, 0x6000, 0xc0d4, 0xc0dc, 0x6002, 0x080c, 0x4f46,
-	0x0904, 0x7097, 0x7e24, 0x86ff, 0x05e8, 0xa680, 0x0004, 0x2004,
-	0xad06, 0x15c0, 0x00d6, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0548,
-	0x080c, 0x6a82, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4,
-	0x7827, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000,
-	0x0120, 0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824,
-	0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0x603c,
-	0xa005, 0x0110, 0x8001, 0x603e, 0x2660, 0x080c, 0x9ed9, 0x00ce,
-	0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce,
-	0x0804, 0x7046, 0x8dff, 0x0138, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0x547a, 0x080c, 0x81a5, 0x0804, 0x7046, 0x000e,
-	0x0804, 0x7039, 0x781e, 0x781a, 0x00de, 0x00ce, 0x006e, 0x000e,
-	0x0005, 0x00e6, 0x00d6, 0x0066, 0x6000, 0xd0dc, 0x01a0, 0x604c,
-	0xa06d, 0x0188, 0x6848, 0xa606, 0x1170, 0x2071, 0xb8e1, 0x7024,
-	0xa035, 0x0148, 0xa080, 0x0004, 0x2004, 0xad06, 0x1120, 0x6000,
-	0xc0dc, 0x6002, 0x0021, 0x006e, 0x00de, 0x00ee, 0x0005, 0x00f6,
-	0x2079, 0x0100, 0x78c0, 0xa005, 0x1138, 0x00c6, 0x2660, 0x6003,
-	0x0009, 0x630a, 0x00ce, 0x04a0, 0x080c, 0x7df3, 0x78c3, 0x0000,
-	0x080c, 0x82d4, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04,
-	0xa384, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x2079,
-	0x0100, 0x7824, 0xd084, 0x0110, 0x7827, 0x0001, 0x080c, 0x82d4,
-	0x003e, 0x080c, 0x4f46, 0x00c6, 0x603c, 0xa005, 0x0110, 0x8001,
-	0x603e, 0x2660, 0x080c, 0x86a4, 0x00ce, 0x6837, 0x0103, 0x6b4a,
-	0x6847, 0x0000, 0x080c, 0x9f88, 0x080c, 0x547a, 0x080c, 0x81a5,
-	0x00fe, 0x0005, 0x00e6, 0x00c6, 0x2071, 0xb8e1, 0x7004, 0xa084,
-	0x0007, 0x0002, 0x7114, 0x7117, 0x712d, 0x7146, 0x7183, 0x7114,
-	0x7112, 0x7112, 0x080c, 0x151a, 0x00ce, 0x00ee, 0x0005, 0x7024,
-	0xa065, 0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0xa015, 0x0150,
-	0x7216, 0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce,
-	0x00ee, 0x0005, 0x7216, 0x7212, 0x0cb0, 0x6018, 0x2060, 0x080c,
-	0x4f46, 0x6000, 0xc0dc, 0x6002, 0x7020, 0x8001, 0x7022, 0x0120,
-	0x6054, 0xa015, 0x0140, 0x721e, 0x7007, 0x0000, 0x7027, 0x0000,
-	0x00ce, 0x00ee, 0x0005, 0x7218, 0x721e, 0x0cb0, 0x7024, 0xa065,
-	0x05b8, 0x700c, 0xac06, 0x1160, 0x080c, 0x81a5, 0x600c, 0xa015,
-	0x0120, 0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430,
-	0x7014, 0xac06, 0x1160, 0x080c, 0x81a5, 0x600c, 0xa015, 0x0120,
-	0x7216, 0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x601c,
-	0xa086, 0x0003, 0x1198, 0x6018, 0x2060, 0x080c, 0x4f46, 0x6000,
-	0xc0dc, 0x6002, 0x080c, 0x81a5, 0x701c, 0xa065, 0x0138, 0x6054,
-	0xa015, 0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000,
-	0x00ce, 0x00ee, 0x0005, 0x7024, 0xa065, 0x0140, 0x080c, 0x81a5,
-	0x600c, 0xa015, 0x0150, 0x720e, 0x600f, 0x0000, 0x080c, 0x82d4,
-	0x7027, 0x0000, 0x00ce, 0x00ee, 0x0005, 0x720e, 0x720a, 0x0cb0,
-	0x00d6, 0x2069, 0xb8e1, 0x6830, 0xa084, 0x0003, 0x0002, 0x71a5,
-	0x71a7, 0x71cb, 0x71a3, 0x080c, 0x151a, 0x00de, 0x0005, 0x00c6,
-	0x6840, 0xa086, 0x0001, 0x01b8, 0x683c, 0xa065, 0x0130, 0x600c,
-	0xa015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000, 0x683f,
-	0x0000, 0x2011, 0xb900, 0x2013, 0x0000, 0x00ce, 0x00de, 0x0005,
-	0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0xa065, 0x0d68,
-	0x6003, 0x0003, 0x0c50, 0x00c6, 0x6843, 0x0000, 0x6847, 0x0000,
-	0x684b, 0x0000, 0x683c, 0xa065, 0x0168, 0x600c, 0xa015, 0x0130,
-	0x6a3a, 0x600f, 0x0000, 0x683f, 0x0000, 0x0020, 0x683f, 0x0000,
-	0x683a, 0x6836, 0x00ce, 0x00de, 0x0005, 0x00d6, 0x2069, 0xb8e1,
-	0x6804, 0xa084, 0x0007, 0x0002, 0x71f6, 0x7292, 0x7292, 0x7292,
-	0x7292, 0x7294, 0x71f4, 0x71f4, 0x080c, 0x151a, 0x6820, 0xa005,
-	0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0150, 0x6807,
-	0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x72e4, 0x00ce, 0x00de,
-	0x0005, 0x6814, 0xa065, 0x0150, 0x6807, 0x0001, 0x6826, 0x682b,
-	0x0000, 0x080c, 0x72e4, 0x00ce, 0x00de, 0x0005, 0x00e6, 0x0036,
-	0x6a1c, 0xa2f5, 0x0000, 0x0904, 0x728e, 0x704c, 0xa00d, 0x0118,
-	0x7088, 0xa005, 0x01a0, 0x7054, 0xa075, 0x0120, 0xa20e, 0x0904,
-	0x728e, 0x0028, 0x6818, 0xa20e, 0x0904, 0x728e, 0x2070, 0x704c,
-	0xa00d, 0x0d88, 0x7088, 0xa005, 0x1d70, 0x2e00, 0x681e, 0x733c,
-	0x7038, 0xa302, 0x1e40, 0x080c, 0x867b, 0x0904, 0x728e, 0x8318,
-	0x733e, 0x6112, 0x2e10, 0x621a, 0xa180, 0x0014, 0x2004, 0xa084,
-	0x00ff, 0x605a, 0xa180, 0x0014, 0x2003, 0x0000, 0xa180, 0x0015,
-	0x2004, 0xa08a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x801b,
-	0x831b, 0xa318, 0x6316, 0x003e, 0x00f6, 0x2c78, 0x71a0, 0x2001,
-	0xb635, 0x2004, 0xd0ac, 0x1110, 0xd1bc, 0x0150, 0x7100, 0xd1f4,
-	0x0120, 0x7114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000, 0x0028,
-	0xa1e0, 0x2df9, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100, 0x619a,
-	0x080c, 0x7914, 0x7300, 0xc3dd, 0x7302, 0x6807, 0x0002, 0x2f18,
-	0x6b26, 0x682b, 0x0000, 0x781f, 0x0003, 0x7803, 0x0001, 0x7807,
-	0x0040, 0x00fe, 0x00ee, 0x00ce, 0x00de, 0x0005, 0x003e, 0x00ee,
-	0x00ce, 0x0cd0, 0x00de, 0x0005, 0x00c6, 0x680c, 0xa065, 0x0138,
-	0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x72e4, 0x00ce,
-	0x00de, 0x0005, 0x00f6, 0x00d6, 0x2069, 0xb8e1, 0x6830, 0xa086,
-	0x0000, 0x11d0, 0x2001, 0xb60c, 0x200c, 0xd1bc, 0x1560, 0x6838,
-	0xa07d, 0x0190, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b,
-	0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x203d,
-	0x1130, 0x012e, 0x080c, 0x7c5d, 0x00de, 0x00fe, 0x0005, 0x012e,
-	0xe000, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0xa015, 0x0140,
-	0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000, 0x0c60,
-	0x683a, 0x6836, 0x0cc0, 0xc1bc, 0x2102, 0x0066, 0x2031, 0x0001,
-	0x080c, 0x5bc3, 0x006e, 0x0858, 0x601c, 0xa084, 0x000f, 0x000b,
-	0x0005, 0x72f2, 0x72f7, 0x77b5, 0x78d1, 0x72f7, 0x77b5, 0x78d1,
-	0x72f2, 0x72f7, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0x0156,
-	0x0136, 0x0146, 0x00c6, 0x00f6, 0x6004, 0xa08a, 0x0080, 0x1a0c,
-	0x151a, 0x6118, 0x2178, 0x79a0, 0x2011, 0xb635, 0x2214, 0xd2ac,
-	0x1110, 0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c,
-	0x00ff, 0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2df9, 0x2f0d,
-	0xa18c, 0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa08a, 0x0040,
-	0x1a04, 0x736b, 0x0033, 0x00fe, 0x00ce, 0x014e, 0x013e, 0x015e,
-	0x0005, 0x741a, 0x7465, 0x7492, 0x755f, 0x758d, 0x7595, 0x75bb,
-	0x75cc, 0x75dd, 0x75e5, 0x75fb, 0x75e5, 0x765c, 0x75cc, 0x767d,
-	0x7685, 0x75dd, 0x7685, 0x7696, 0x7369, 0x7369, 0x7369, 0x7369,
-	0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7369, 0x7efe,
-	0x7f23, 0x7f46, 0x7f69, 0x7f8a, 0x75bb, 0x7369, 0x75bb, 0x75e5,
-	0x7369, 0x7492, 0x755f, 0x7369, 0x83d6, 0x75e5, 0x7369, 0x83f6,
-	0x75e5, 0x7369, 0x75dd, 0x7413, 0x737e, 0x7369, 0x841b, 0x8490,
-	0x8567, 0x7369, 0x8578, 0x75b6, 0x8594, 0x7369, 0x7f9f, 0x85ef,
-	0x7369, 0x080c, 0x151a, 0x2100, 0x0033, 0x00fe, 0x00ce, 0x014e,
-	0x013e, 0x015e, 0x0005, 0x737c, 0x737c, 0x737c, 0x73b2, 0x73d0,
-	0x73e6, 0x737c, 0x737c, 0x737c, 0x080c, 0x151a, 0x00d6, 0x20a1,
-	0x020b, 0x080c, 0x76b3, 0x7810, 0x2068, 0x20a3, 0x2414, 0x20a3,
-	0x0018, 0x20a3, 0x0800, 0x683c, 0x20a2, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x6850, 0x20a2, 0x6854,
-	0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c,
-	0x7de0, 0x00de, 0x0005, 0x00d6, 0x7818, 0x2068, 0x68a0, 0x2069,
-	0xb600, 0x6ad4, 0xd2ac, 0x1110, 0xd0bc, 0x0110, 0xa085, 0x0001,
-	0x00de, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3,
-	0x0500, 0x20a3, 0x0000, 0x7810, 0xa0e8, 0x000f, 0x6808, 0x20a2,
-	0x680c, 0x20a2, 0x6810, 0x20a2, 0x6814, 0x20a2, 0x6818, 0x20a2,
-	0x681c, 0x20a2, 0x60c3, 0x0010, 0x080c, 0x7de0, 0x00de, 0x0005,
-	0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, 0x7800,
-	0x20a3, 0x0000, 0x7808, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3,
-	0x0008, 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x0156, 0x0146,
-	0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0000,
-	0x20a3, 0xdf10, 0x20a3, 0x0034, 0x2099, 0xb605, 0x20a9, 0x0004,
-	0x53a6, 0x2099, 0xb601, 0x20a9, 0x0004, 0x53a6, 0x2099, 0xb8c7,
-	0x20a9, 0x001a, 0x3304, 0x8007, 0x20a2, 0x9398, 0x1f04, 0x7402,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x004c, 0x080c, 0x7de0,
-	0x014e, 0x015e, 0x0005, 0x2001, 0xb615, 0x2004, 0x609a, 0x080c,
-	0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x20a3, 0x5200,
-	0x20a3, 0x0000, 0x00d6, 0x2069, 0xb652, 0x6804, 0xd084, 0x0150,
-	0x6828, 0x20a3, 0x0000, 0x0016, 0x080c, 0x2866, 0x21a2, 0x001e,
-	0x00de, 0x0028, 0x00de, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9,
-	0x0004, 0x2099, 0xb605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb601,
-	0x53a6, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1138, 0x7818, 0xa080,
-	0x0028, 0x2004, 0xa082, 0x007f, 0x0238, 0x2001, 0xb61c, 0x20a6,
-	0x2001, 0xb61d, 0x20a6, 0x0040, 0x20a3, 0x0000, 0x2001, 0xb615,
-	0x2004, 0xa084, 0x00ff, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x001c, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x76b3, 0x20a3, 0x0500, 0x20a3, 0x0000, 0x2001, 0xb635, 0x2004,
-	0xd0ac, 0x1138, 0x7818, 0xa080, 0x0028, 0x2004, 0xa082, 0x007f,
-	0x0238, 0x2001, 0xb61c, 0x20a6, 0x2001, 0xb61d, 0x20a6, 0x0040,
-	0x20a3, 0x0000, 0x2001, 0xb615, 0x2004, 0xa084, 0x00ff, 0x20a2,
-	0x20a9, 0x0004, 0x2099, 0xb605, 0x53a6, 0x60c3, 0x0010, 0x080c,
-	0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x00c6, 0x7818,
-	0x2060, 0x2001, 0x0000, 0x080c, 0x5385, 0x00ce, 0x7818, 0xa080,
-	0x0028, 0x2004, 0xa086, 0x007e, 0x1130, 0x20a3, 0x0400, 0x620c,
-	0xc2b4, 0x620e, 0x0010, 0x20a3, 0x0300, 0x20a3, 0x0000, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xa086, 0x007e, 0x1904, 0x7521, 0x2001,
-	0xb635, 0x2004, 0xd0a4, 0x01c8, 0x2099, 0xb88e, 0x33a6, 0x9398,
-	0x20a3, 0x0000, 0x9398, 0x3304, 0xa084, 0x2000, 0x20a2, 0x9398,
-	0x33a6, 0x9398, 0x20a3, 0x0000, 0x9398, 0x2001, 0x2710, 0x20a2,
-	0x9398, 0x33a6, 0x9398, 0x33a6, 0x00d0, 0x2099, 0xb88e, 0x33a6,
-	0x9398, 0x33a6, 0x9398, 0x3304, 0x080c, 0x5b41, 0x1118, 0xa084,
-	0x37ff, 0x0010, 0xa084, 0x3fff, 0x20a2, 0x9398, 0x33a6, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a9,
-	0x0004, 0x2099, 0xb605, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb601,
-	0x53a6, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04, 0x74fb, 0x20a9,
-	0x0008, 0x20a3, 0x0000, 0x1f04, 0x7501, 0x2099, 0xb896, 0x3304,
-	0xc0dd, 0x20a2, 0x2001, 0xb672, 0x2004, 0xd0e4, 0x0158, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x9398, 0x9398, 0x9398, 0x33a6, 0x20a9,
-	0x0004, 0x0010, 0x20a9, 0x0007, 0x20a3, 0x0000, 0x1f04, 0x751c,
-	0x0468, 0x2001, 0xb635, 0x2004, 0xd0a4, 0x0140, 0x2001, 0xb88f,
-	0x2004, 0x60e3, 0x0000, 0x080c, 0x28a7, 0x60e2, 0x2099, 0xb88e,
-	0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0004, 0x2099, 0xb605, 0x53a6,
-	0x20a9, 0x0004, 0x2099, 0xb601, 0x53a6, 0x20a9, 0x0008, 0x20a3,
-	0x0000, 0x1f04, 0x753f, 0x20a9, 0x0008, 0x20a3, 0x0000, 0x1f04,
-	0x7545, 0x2099, 0xb896, 0x20a9, 0x0008, 0x53a6, 0x20a9, 0x0008,
-	0x20a3, 0x0000, 0x1f04, 0x7550, 0x20a9, 0x000a, 0x20a3, 0x0000,
-	0x1f04, 0x7556, 0x60c3, 0x0074, 0x080c, 0x7de0, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x76b3, 0x20a3, 0x2010, 0x20a3, 0x0014, 0x20a3,
-	0x0800, 0x20a3, 0x2000, 0xa006, 0x20a2, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x00f6, 0x2079, 0xb652, 0x7904, 0x00fe, 0xd1ac, 0x1110,
-	0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0xa085, 0x0002,
-	0x00d6, 0x0804, 0x763e, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x76b3, 0x20a3, 0x5000, 0x0804, 0x74ad, 0x20a1, 0x020b, 0x080c,
-	0x76b3, 0x20a3, 0x2110, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3,
-	0x0000, 0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b,
-	0x080c, 0x7747, 0x0020, 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3,
-	0x0200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3,
-	0x0004, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x774f,
-	0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3, 0x2a00,
-	0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x774f, 0x20a3, 0x0200, 0x0804, 0x74ad, 0x20a1, 0x020b, 0x080c,
-	0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0xa005, 0x0110,
-	0x20a2, 0x0010, 0x20a3, 0x0003, 0x7810, 0x20a2, 0x60c3, 0x0008,
-	0x080c, 0x7de0, 0x0005, 0x00d6, 0x20a1, 0x020b, 0x080c, 0x774f,
-	0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0800, 0x7818, 0x2068,
-	0x6894, 0xa086, 0x0014, 0x1198, 0x699c, 0xa184, 0x0030, 0x0190,
-	0x6998, 0xa184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x20a3, 0x2100,
-	0x0058, 0x20a3, 0x0100, 0x0040, 0x20a3, 0x0400, 0x0028, 0x20a3,
-	0x0700, 0x0010, 0x700f, 0x0800, 0xa006, 0x20a2, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x00f6, 0x2079, 0xb652, 0x7904, 0x00fe, 0xd1ac,
-	0x1110, 0xa085, 0x0020, 0xd1a4, 0x0110, 0xa085, 0x0010, 0x2009,
-	0xb674, 0x210c, 0xd184, 0x1110, 0xa085, 0x0002, 0x0026, 0x2009,
-	0xb672, 0x210c, 0xd1e4, 0x0130, 0xc0c5, 0xa094, 0x0030, 0xa296,
-	0x0010, 0x0140, 0xd1ec, 0x0130, 0xa094, 0x0030, 0xa296, 0x0010,
-	0x0108, 0xc0bd, 0x002e, 0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x0014,
-	0x080c, 0x7de0, 0x00de, 0x0005, 0x20a1, 0x020b, 0x080c, 0x774f,
-	0x20a3, 0x0210, 0x20a3, 0x0014, 0x20a3, 0x0000, 0x20a3, 0x0100,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x60c3, 0x0014, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c,
-	0x774f, 0x20a3, 0x0200, 0x0804, 0x7420, 0x20a1, 0x020b, 0x080c,
-	0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3, 0x0003, 0x20a3,
-	0x2a00, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0100,
-	0x20a3, 0x0000, 0x20a3, 0x000b, 0x20a3, 0x0000, 0x60c3, 0x0008,
-	0x080c, 0x7de0, 0x0005, 0x0026, 0x0036, 0x0046, 0x2019, 0x3200,
-	0x2021, 0x0800, 0x0038, 0x0026, 0x0036, 0x0046, 0x2019, 0x2200,
-	0x2021, 0x0100, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080,
-	0x0028, 0x2014, 0xa286, 0x007e, 0x11a0, 0xa385, 0x00ff, 0x20a2,
-	0x20a3, 0xfffe, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x2001,
-	0xb89e, 0x2004, 0xa005, 0x0118, 0x2011, 0xb61d, 0x2214, 0x22a2,
-	0x04d0, 0xa286, 0x007f, 0x1138, 0x00d6, 0xa385, 0x00ff, 0x20a2,
-	0x20a3, 0xfffd, 0x00c8, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110,
-	0xd2bc, 0x01c8, 0xa286, 0x0080, 0x00d6, 0x1130, 0xa385, 0x00ff,
-	0x20a2, 0x20a3, 0xfffc, 0x0040, 0xa2e8, 0xb735, 0x2d6c, 0x6810,
-	0xa305, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68,
-	0x2da6, 0x00de, 0x0080, 0x00d6, 0xa2e8, 0xb735, 0x2d6c, 0x6810,
-	0xa305, 0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011,
-	0xb615, 0x2214, 0x22a2, 0xa485, 0x0029, 0x20a2, 0x004e, 0x003e,
-	0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x2fa2,
-	0x20a3, 0xffff, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x20a3, 0x02ff, 0x2011,
-	0xfffc, 0x22a2, 0x00d6, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6,
-	0x00de, 0x20a3, 0x2029, 0x20a3, 0x0000, 0x08e0, 0x20a3, 0x0100,
-	0x20a3, 0x0000, 0x20a3, 0xfc02, 0x20a3, 0x0000, 0x0005, 0x0026,
-	0x0036, 0x0046, 0x2019, 0x3300, 0x2021, 0x0800, 0x0038, 0x0026,
-	0x0036, 0x0046, 0x2019, 0x2300, 0x2021, 0x0100, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635,
-	0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x02d8, 0x00d6, 0xa0e8,
-	0xb735, 0x2d6c, 0x6810, 0xa305, 0x20a2, 0x6814, 0x20a2, 0x6810,
-	0xa005, 0x1140, 0x6814, 0xa005, 0x1128, 0x20a3, 0x00ff, 0x20a3,
-	0xfffe, 0x0028, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0080, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa305, 0x20a2,
-	0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214,
-	0x22a2, 0xa485, 0x0098, 0x20a2, 0x20a3, 0x0000, 0x004e, 0x003e,
-	0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x080c, 0x7dcf,
-	0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x7810, 0x20a2, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00c6, 0x00f6, 0x6004,
-	0xa08a, 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, 0x1a0c, 0x151a,
-	0x6118, 0x2178, 0x79a0, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110,
-	0xd1bc, 0x0150, 0x7900, 0xd1f4, 0x0120, 0x7914, 0xa18c, 0x00ff,
-	0x0040, 0x2009, 0x0000, 0x0028, 0xa1f8, 0x2df9, 0x2f0d, 0xa18c,
-	0x00ff, 0x2c78, 0x2061, 0x0100, 0x619a, 0xa082, 0x0085, 0x001b,
-	0x00fe, 0x00ce, 0x0005, 0x77ec, 0x77f6, 0x7811, 0x77ea, 0x77ea,
-	0x77ea, 0x77ec, 0x080c, 0x151a, 0x0146, 0x20a1, 0x020b, 0x04a1,
-	0x60c3, 0x0000, 0x080c, 0x7de0, 0x014e, 0x0005, 0x0146, 0x20a1,
-	0x020b, 0x080c, 0x785d, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808,
-	0x20a2, 0x7810, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0xffff, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x014e,
-	0x0005, 0x0146, 0x20a1, 0x020b, 0x080c, 0x7897, 0x20a3, 0x0003,
-	0x20a3, 0x0300, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0004,
-	0x080c, 0x7de0, 0x014e, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, 0x2214,
-	0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8, 0xb735,
-	0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2, 0x2069,
-	0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8,
-	0xb735, 0x2d6c, 0x6810, 0xa085, 0x8100, 0x20a2, 0x6814, 0x20a2,
-	0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, 0x20a3,
-	0x0009, 0x20a3, 0x0000, 0x0804, 0x771a, 0x0026, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635,
-	0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288, 0x00d6, 0xa0e8,
-	0xb735, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6,
-	0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8400, 0x20a2, 0x6814,
-	0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2,
-	0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804, 0x77a6, 0x0026,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004,
-	0x2011, 0xb635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0288,
-	0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8500, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x8500,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615,
-	0x2214, 0x22a2, 0x2001, 0x0099, 0x20a2, 0x20a3, 0x0000, 0x0804,
-	0x77a6, 0x00c6, 0x00f6, 0x2c78, 0x7804, 0xa08a, 0x0040, 0x0a0c,
-	0x151a, 0xa08a, 0x0053, 0x1a0c, 0x151a, 0x7918, 0x2160, 0x61a0,
-	0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd1bc, 0x0150, 0x6100,
-	0xd1f4, 0x0120, 0x6114, 0xa18c, 0x00ff, 0x0040, 0x2009, 0x0000,
-	0x0028, 0xa1e0, 0x2df9, 0x2c0d, 0xa18c, 0x00ff, 0x2061, 0x0100,
-	0x619a, 0xa082, 0x0040, 0x001b, 0x00fe, 0x00ce, 0x0005, 0x7914,
-	0x7a20, 0x79bd, 0x7bd2, 0x7912, 0x7912, 0x7912, 0x7912, 0x7912,
-	0x7912, 0x7912, 0x815e, 0x816e, 0x817e, 0x818e, 0x7912, 0x85a5,
-	0x7912, 0x814d, 0x080c, 0x151a, 0x00d6, 0x0156, 0x0146, 0x780b,
-	0xffff, 0x20a1, 0x020b, 0x080c, 0x7974, 0x7910, 0x2168, 0x6948,
-	0x7952, 0x21a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x694c, 0xa184,
-	0x000f, 0x1118, 0x2001, 0x0005, 0x0040, 0xd184, 0x0118, 0x2001,
-	0x0004, 0x0018, 0xa084, 0x0006, 0x8004, 0x0016, 0x2008, 0x7858,
-	0xa084, 0x00ff, 0x8007, 0xa105, 0x001e, 0x20a2, 0xd1ac, 0x0118,
-	0x20a3, 0x0002, 0x0048, 0xd1b4, 0x0118, 0x20a3, 0x0001, 0x0020,
-	0x20a3, 0x0000, 0x2230, 0x0010, 0x6a80, 0x6e7c, 0x20a9, 0x0008,
-	0x0136, 0xad88, 0x0017, 0x2198, 0x20a1, 0x021b, 0x53a6, 0x013e,
-	0x20a1, 0x020b, 0x22a2, 0x26a2, 0x60c3, 0x0020, 0x20e1, 0x9080,
-	0x6014, 0xa084, 0x0004, 0xa085, 0x0009, 0x6016, 0x2001, 0xb8fd,
-	0x2003, 0x07d0, 0x2001, 0xb8fc, 0x2003, 0x0009, 0x080c, 0x17e7,
-	0x014e, 0x015e, 0x00de, 0x0005, 0x20e1, 0x9080, 0x20e1, 0x4000,
-	0x7a18, 0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202,
-	0x8217, 0x7818, 0xa080, 0x0028, 0x2004, 0x2019, 0xb635, 0x231c,
-	0xd3ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb735, 0x2d6c,
-	0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c,
-	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb735,
-	0x2d6c, 0x6810, 0xa085, 0x0600, 0x20a2, 0x6814, 0x20a2, 0x00de,
-	0x20a3, 0x0000, 0x2009, 0xb615, 0x210c, 0x21a2, 0x20a3, 0x0829,
-	0x20a3, 0x0000, 0x22a2, 0x20a3, 0x0000, 0x2fa2, 0x20a3, 0xffff,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x00d6, 0x0156, 0x0136,
-	0x0146, 0x20a1, 0x020b, 0x00c1, 0x7810, 0x2068, 0x6860, 0x20a2,
-	0x685c, 0x20a2, 0x6880, 0x20a2, 0x687c, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x014e,
-	0x013e, 0x015e, 0x00de, 0x0005, 0x0026, 0x20e1, 0x9080, 0x20e1,
-	0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011, 0xb635, 0x2214,
-	0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8, 0xb735, 0x2d6c,
-	0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x2069, 0xb61c,
-	0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0088, 0x00d6, 0xa0e8, 0xb735,
-	0x2d6c, 0x6810, 0xa085, 0x0500, 0x20a2, 0x6814, 0x20a2, 0x00de,
-	0x20a3, 0x0000, 0x2011, 0xb615, 0x2214, 0x22a2, 0x20a3, 0x0889,
-	0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08,
-	0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x002e, 0x0005,
-	0x00d6, 0x0156, 0x0136, 0x0146, 0x7810, 0xa0ec, 0xf000, 0x0168,
-	0xa06d, 0x080c, 0x5373, 0x0148, 0x684c, 0xa084, 0x2020, 0xa086,
-	0x2020, 0x1118, 0x7820, 0xc0cd, 0x7822, 0x20a1, 0x020b, 0x080c,
-	0x7b88, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x7810,
-	0xa084, 0xf000, 0x1130, 0x7810, 0xa084, 0x0700, 0x8007, 0x0043,
-	0x0010, 0xa006, 0x002b, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005,
-	0x7a5a, 0x7aef, 0x7aff, 0x7b31, 0x7b44, 0x7b5f, 0x7b68, 0x7a58,
-	0x080c, 0x151a, 0x0016, 0x0036, 0x694c, 0xa18c, 0x0003, 0x0118,
-	0xa186, 0x0003, 0x1170, 0x6b78, 0x7820, 0xd0cc, 0x0108, 0xc3e5,
-	0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x003e, 0x001e, 0x0804,
-	0x7b3b, 0xa186, 0x0001, 0x190c, 0x151a, 0x6b78, 0x7820, 0xd0cc,
-	0x0108, 0xc3e5, 0x23a2, 0x6868, 0x20a2, 0x6864, 0x20a2, 0x22a2,
-	0x6874, 0x20a2, 0x22a2, 0x687c, 0x20a2, 0x2009, 0x0018, 0xa384,
-	0x0300, 0x0904, 0x7ae9, 0xd3c4, 0x0110, 0x687c, 0xa108, 0xd3cc,
-	0x0110, 0x6874, 0xa108, 0x0156, 0x20a9, 0x000d, 0xad80, 0x0020,
-	0x201c, 0x831f, 0x23a2, 0x8000, 0x1f04, 0x7a98, 0x015e, 0x22a2,
-	0x22a2, 0x22a2, 0xa184, 0x0003, 0x0904, 0x7ae9, 0x20a1, 0x020b,
-	0x20e1, 0x9080, 0x20e1, 0x4000, 0x0006, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
-	0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615,
-	0x2214, 0x22a2, 0x000e, 0x7b20, 0xd3cc, 0x0118, 0x20a3, 0x0889,
-	0x0010, 0x20a3, 0x0898, 0x20a2, 0x080c, 0x7dcf, 0x22a2, 0x20a3,
-	0x0000, 0x61c2, 0x003e, 0x001e, 0x080c, 0x7de0, 0x0005, 0x2011,
-	0x0008, 0x2001, 0xb60d, 0x2004, 0xd0f4, 0x0110, 0x2011, 0x0028,
-	0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x04d0, 0x2011,
-	0x0302, 0x0016, 0x0036, 0x7828, 0x792c, 0xa11d, 0x0108, 0xc2dd,
-	0x7b20, 0xd3cc, 0x0108, 0xc2e5, 0x22a2, 0x20a2, 0x21a2, 0x003e,
-	0x001e, 0xa016, 0x22a2, 0x20a3, 0x0012, 0x22a2, 0x20a3, 0x0008,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x20a3, 0x7000, 0x20a3, 0x0500,
-	0x22a2, 0x20a3, 0x000a, 0x22a2, 0x22a2, 0x20a3, 0x2500, 0x22a2,
-	0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0032, 0x080c, 0x7de0,
-	0x0005, 0x2011, 0x0028, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2,
-	0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x22a2, 0x60c3,
-	0x0018, 0x080c, 0x7de0, 0x0005, 0x2011, 0x0100, 0x7820, 0xd0cc,
-	0x0108, 0xc2e5, 0x22a2, 0xa016, 0x22a2, 0x22a2, 0x22a2, 0x22a2,
-	0x22a2, 0x20a3, 0x0008, 0x22a2, 0x7854, 0xa084, 0x00ff, 0x20a2,
-	0x22a2, 0x22a2, 0x60c3, 0x0020, 0x080c, 0x7de0, 0x0005, 0x2011,
-	0x0008, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0xa016, 0x0888,
-	0x0036, 0x7b10, 0xa384, 0xff00, 0x7812, 0xa384, 0x00ff, 0x8001,
-	0x1138, 0x7820, 0xd0cc, 0x0108, 0xc2e5, 0x22a2, 0x003e, 0x0808,
-	0x0046, 0x2021, 0x0800, 0x0006, 0x7820, 0xd0cc, 0x000e, 0x0108,
-	0xc4e5, 0x24a2, 0x004e, 0x22a2, 0x20a2, 0x003e, 0x0804, 0x7b3b,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
-	0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0700,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615,
-	0x2214, 0x22a2, 0x7820, 0xd0cc, 0x0118, 0x20a3, 0x0889, 0x0010,
-	0x20a3, 0x0898, 0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3,
-	0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x002e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x0016, 0x0036,
-	0x7810, 0xa084, 0x0700, 0x8007, 0x003b, 0x003e, 0x001e, 0x014e,
-	0x013e, 0x015e, 0x00de, 0x0005, 0x7bec, 0x7bec, 0x7bee, 0x7bec,
-	0x7bec, 0x7bec, 0x7c10, 0x7bec, 0x080c, 0x151a, 0x7910, 0xa18c,
-	0xf8ff, 0xa18d, 0x0600, 0x7912, 0x20a1, 0x020b, 0x2009, 0x0003,
-	0x00f9, 0x00d6, 0x2069, 0xb652, 0x6804, 0xd0bc, 0x0130, 0x682c,
-	0xa084, 0x00ff, 0x8007, 0x20a2, 0x0010, 0x20a3, 0x3f00, 0x00de,
-	0x22a2, 0x22a2, 0x22a2, 0x60c3, 0x0001, 0x080c, 0x7de0, 0x0005,
-	0x20a1, 0x020b, 0x2009, 0x0003, 0x0019, 0x20a3, 0x7f00, 0x0c80,
-	0x0026, 0x20e1, 0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028,
-	0x2004, 0x2011, 0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188,
-	0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0100, 0x20a2,
-	0x6814, 0x20a2, 0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de,
-	0x0088, 0x00d6, 0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0100,
-	0x20a2, 0x6814, 0x20a2, 0x00de, 0x20a3, 0x0000, 0x2011, 0xb615,
-	0x2214, 0x22a2, 0x20a3, 0x0888, 0xa18d, 0x0008, 0x21a2, 0x080c,
-	0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x7a08, 0x22a2, 0x2fa2, 0x20a3,
-	0x0000, 0x20a3, 0x0000, 0x002e, 0x0005, 0x00e6, 0x00d6, 0x00c6,
-	0x0056, 0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0xb600, 0x7154,
-	0x7818, 0x2068, 0x68a0, 0x2028, 0x76d4, 0xd6ac, 0x1130, 0xd0bc,
-	0x1120, 0x6910, 0x6a14, 0x7454, 0x0020, 0x6910, 0x6a14, 0x7370,
-	0x7474, 0x781c, 0xa0be, 0x0006, 0x0904, 0x7d1a, 0xa0be, 0x000a,
-	0x15e8, 0xa185, 0x0200, 0x6062, 0x6266, 0x636a, 0x646e, 0x6073,
-	0x2029, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff, 0x688e,
-	0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086,
-	0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6,
-	0x7008, 0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0x609f, 0x0000, 0x080c, 0x8640, 0x2009, 0x07d0, 0x60c4, 0xa084,
-	0xfff0, 0xa005, 0x0110, 0x2009, 0x1b58, 0x080c, 0x6a87, 0x003e,
-	0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x70d4, 0xd0ac,
-	0x1110, 0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a,
-	0x646e, 0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000,
-	0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084,
-	0x00ff, 0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6082,
-	0x7808, 0x6086, 0x7810, 0x2070, 0x7014, 0x608a, 0x7010, 0x608e,
-	0x700c, 0x60c6, 0x7008, 0x60ca, 0x792c, 0xa108, 0x792e, 0x700c,
-	0x7928, 0xa109, 0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7,
-	0x0000, 0xa582, 0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14,
-	0xa294, 0x00ff, 0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x8640,
-	0x2009, 0x07d0, 0x60c4, 0xa084, 0xfff0, 0xa005, 0x0110, 0x2009,
-	0x1b58, 0x080c, 0x6a87, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de,
-	0x00ee, 0x0005, 0x7810, 0x2070, 0x704c, 0xa084, 0x0003, 0xa086,
-	0x0002, 0x0904, 0x7d70, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110,
-	0xd5bc, 0x0138, 0xa185, 0x0100, 0x6062, 0x6266, 0x636a, 0x646e,
-	0x0038, 0xa185, 0x0100, 0x6062, 0x6266, 0x606b, 0x0000, 0x646e,
-	0x6073, 0x0880, 0x6077, 0x0008, 0x688c, 0x8000, 0xa084, 0x00ff,
-	0x688e, 0x8007, 0x607a, 0x7834, 0x607e, 0x2f00, 0x6086, 0x7808,
-	0x6082, 0x7060, 0x608a, 0x705c, 0x608e, 0x7080, 0x60c6, 0x707c,
-	0x60ca, 0x707c, 0x792c, 0xa108, 0x792e, 0x7080, 0x7928, 0xa109,
-	0x792a, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582,
-	0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff,
-	0x0010, 0x2011, 0x0000, 0x629e, 0x080c, 0x863d, 0x0804, 0x7d08,
-	0x2001, 0xb635, 0x2004, 0xd0ac, 0x1110, 0xd5bc, 0x0138, 0xa185,
-	0x0700, 0x6062, 0x6266, 0x636a, 0x646e, 0x0038, 0xa185, 0x0700,
-	0x6062, 0x6266, 0x606b, 0x0000, 0x646e, 0x080c, 0x5373, 0x0180,
-	0x00d6, 0x7810, 0xa06d, 0x684c, 0x00de, 0xa084, 0x2020, 0xa086,
-	0x2020, 0x1130, 0x7820, 0xc0cd, 0x7822, 0x6073, 0x0889, 0x0010,
-	0x6073, 0x0898, 0x6077, 0x0000, 0x688c, 0x8000, 0xa084, 0x00ff,
-	0x688e, 0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808,
-	0x6082, 0x7014, 0x608a, 0x7010, 0x608e, 0x700c, 0x60c6, 0x7008,
-	0x60ca, 0x686c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xa582,
-	0x0080, 0x0248, 0x6a00, 0xd2f4, 0x0120, 0x6a14, 0xa294, 0x00ff,
-	0x0010, 0x2011, 0x0000, 0x629e, 0x7820, 0xd0cc, 0x0120, 0x080c,
-	0x8640, 0x0804, 0x7d08, 0x080c, 0x863d, 0x0804, 0x7d08, 0x7a18,
-	0xa280, 0x0023, 0x2014, 0x8210, 0xa294, 0x00ff, 0x2202, 0x8217,
-	0x0005, 0x00d6, 0x2069, 0xb8e1, 0x6843, 0x0001, 0x00de, 0x0005,
-	0x20e1, 0x9080, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x0019, 0x080c,
-	0x6a79, 0x0005, 0x0006, 0x6014, 0xa084, 0x0004, 0xa085, 0x0009,
-	0x6016, 0x000e, 0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100,
-	0x61a4, 0x60a7, 0x95f5, 0x6014, 0xa084, 0x0004, 0xa085, 0x0008,
-	0x6016, 0x000e, 0xe000, 0xe000, 0xe000, 0xe000, 0x61a6, 0x00ce,
-	0x001e, 0x0005, 0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100,
-	0x2069, 0x0140, 0x080c, 0x5b41, 0x1198, 0x2001, 0xb8fd, 0x2004,
-	0xa005, 0x15b8, 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3, 0x006e,
-	0x1118, 0x080c, 0x6a79, 0x0468, 0x00c6, 0x2061, 0xb8e1, 0x00d8,
-	0x6904, 0xa194, 0x4000, 0x0550, 0x0831, 0x6803, 0x1000, 0x6803,
-	0x0000, 0x00c6, 0x2061, 0xb8e1, 0x6128, 0xa192, 0x00c8, 0x1258,
-	0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x6a79,
-	0x080c, 0x7dea, 0x0070, 0x6124, 0xa1e5, 0x0000, 0x0140, 0x080c,
-	0xb500, 0x080c, 0x6a82, 0x2009, 0x0014, 0x080c, 0x86d3, 0x00ce,
-	0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0xb8fd,
-	0x2004, 0xa005, 0x1db0, 0x00c6, 0x2061, 0xb8e1, 0x6128, 0xa192,
-	0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x6a79, 0x080c,
-	0x4b7b, 0x0c38, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c,
-	0x6a8f, 0x2071, 0xb8e1, 0x713c, 0x81ff, 0x0590, 0x2061, 0x0100,
-	0x2069, 0x0140, 0x080c, 0x5b41, 0x11a8, 0x0036, 0x2019, 0x0002,
-	0x080c, 0x806b, 0x003e, 0x713c, 0x2160, 0x080c, 0xb500, 0x2009,
-	0x004a, 0x080c, 0x86d3, 0x0066, 0x2031, 0x0001, 0x080c, 0x5bc3,
-	0x006e, 0x00b0, 0x6904, 0xa194, 0x4000, 0x01c0, 0x6803, 0x1000,
-	0x6803, 0x0000, 0x0036, 0x2019, 0x0001, 0x080c, 0x806b, 0x003e,
-	0x713c, 0x2160, 0x080c, 0xb500, 0x2009, 0x004a, 0x080c, 0x86d3,
-	0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0c58, 0x0026,
-	0x00e6, 0x2071, 0xb8e1, 0x7048, 0xd084, 0x01c0, 0x713c, 0x81ff,
-	0x01a8, 0x2071, 0x0100, 0xa188, 0x0007, 0x2114, 0xa28e, 0x0006,
-	0x1138, 0x7014, 0xa084, 0x0184, 0xa085, 0x0012, 0x7016, 0x0030,
-	0x7014, 0xa084, 0x0184, 0xa085, 0x0016, 0x7016, 0x00ee, 0x002e,
-	0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006,
-	0x0126, 0x2091, 0x8000, 0x6018, 0x2068, 0x6ca0, 0x2071, 0xb8e1,
-	0x7018, 0x2068, 0x8dff, 0x0188, 0x68a0, 0xa406, 0x0118, 0x6854,
-	0x2068, 0x0cc0, 0x6010, 0x2060, 0x643c, 0x6540, 0x6648, 0x2d60,
-	0x080c, 0x518c, 0x0110, 0xa085, 0x0001, 0x012e, 0x000e, 0x004e,
-	0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x20a1, 0x020b,
-	0x080c, 0x76b3, 0x20a3, 0x1200, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x781c, 0xa086, 0x0004, 0x1110, 0x6098, 0x0018, 0x2001, 0xb615,
-	0x2004, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a9, 0x0010,
-	0xa006, 0x20a2, 0x1f04, 0x7f19, 0x20a2, 0x20a2, 0x60c3, 0x002c,
-	0x080c, 0x7de0, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c,
-	0x76b3, 0x20a3, 0x0f00, 0x20a3, 0x0000, 0x7808, 0xd09c, 0x1150,
-	0x20a3, 0x0000, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x014e,
-	0x015e, 0x0005, 0x00d6, 0x7818, 0xa06d, 0x090c, 0x151a, 0x6810,
-	0xa084, 0x00ff, 0x20a2, 0x6814, 0x00de, 0x0c60, 0x0156, 0x0146,
-	0x20a1, 0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0000,
-	0x20a9, 0x0006, 0x2011, 0xb640, 0x2019, 0xb641, 0x23a6, 0x22a6,
-	0xa398, 0x0002, 0xa290, 0x0002, 0x1f04, 0x7f56, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x001c, 0x080c, 0x7de0, 0x014e, 0x015e,
-	0x0005, 0x0156, 0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c,
-	0x7728, 0x080c, 0x773e, 0x7810, 0xa080, 0x0000, 0x2004, 0xa080,
-	0x0015, 0x2098, 0x7808, 0xa088, 0x0002, 0x21a8, 0x53a6, 0xa080,
-	0x0004, 0x8003, 0x60c2, 0x080c, 0x7de0, 0x002e, 0x001e, 0x014e,
-	0x015e, 0x0005, 0x0156, 0x0146, 0x20a1, 0x020b, 0x080c, 0x76b3,
-	0x20a3, 0x6200, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x7808, 0x20a2,
-	0x60c3, 0x0008, 0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x0156,
-	0x0146, 0x0016, 0x0026, 0x20a1, 0x020b, 0x080c, 0x76b3, 0x7810,
-	0xa080, 0x0000, 0x2004, 0xa080, 0x0017, 0x2098, 0x7808, 0xa088,
-	0x0002, 0x21a8, 0x53a6, 0x8003, 0x60c2, 0x080c, 0x7de0, 0x002e,
-	0x001e, 0x014e, 0x015e, 0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126,
-	0x2091, 0x8000, 0x2071, 0xb8e1, 0x700c, 0x2060, 0x8cff, 0x0178,
-	0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x600c, 0x0006, 0x080c,
-	0xa0db, 0x080c, 0x86a4, 0x080c, 0x81a5, 0x00ce, 0x0c78, 0x700f,
-	0x0000, 0x700b, 0x0000, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005,
-	0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0026, 0x0016,
-	0x0006, 0x2091, 0x8000, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
-	0xb8e1, 0x7024, 0x2060, 0x8cff, 0x05a0, 0x080c, 0x7df3, 0x68c3,
-	0x0000, 0x080c, 0x6a82, 0x2009, 0x0013, 0x080c, 0x86d3, 0x20a9,
-	0x01f4, 0x6824, 0xd094, 0x0158, 0x6827, 0x0004, 0x7804, 0xa084,
-	0x4000, 0x01a0, 0x7803, 0x1000, 0x7803, 0x0000, 0x0078, 0xd084,
-	0x0118, 0x6827, 0x0001, 0x0010, 0x1f04, 0x8001, 0x7804, 0xa084,
-	0x1000, 0x0120, 0x7803, 0x0100, 0x7803, 0x0000, 0x6824, 0x000e,
-	0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e,
-	0x0005, 0x2001, 0xb600, 0x2004, 0xa096, 0x0001, 0x0590, 0xa096,
-	0x0004, 0x0578, 0x080c, 0x6a82, 0x6814, 0xa084, 0x0001, 0x0110,
-	0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x2011, 0x4b23,
-	0x080c, 0x6a0e, 0x20a9, 0x01f4, 0x6824, 0xd094, 0x0158, 0x6827,
-	0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803,
-	0x0000, 0x0078, 0xd084, 0x0118, 0x6827, 0x0001, 0x0010, 0x1f04,
-	0x8044, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803,
-	0x0000, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee, 0x00fe,
-	0x015e, 0x012e, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2069, 0x0100,
-	0x2079, 0x0140, 0x2071, 0xb8e1, 0x703c, 0x2060, 0x8cff, 0x0904,
-	0x80f2, 0xa386, 0x0002, 0x1128, 0x6814, 0xa084, 0x0002, 0x0904,
-	0x80f2, 0x68af, 0x95f5, 0x6817, 0x0010, 0x2009, 0x00fa, 0x8109,
-	0x1df0, 0x68c7, 0x0000, 0x68cb, 0x0008, 0x080c, 0x6a8f, 0x080c,
-	0x222f, 0x0046, 0x2009, 0x017f, 0x200b, 0x00a5, 0x2021, 0x0169,
-	0x2404, 0xa084, 0x000f, 0xa086, 0x0004, 0x1500, 0x68af, 0x95f5,
-	0x68c7, 0x0000, 0x68cb, 0x0008, 0x00e6, 0x00f6, 0x2079, 0x0020,
-	0x2071, 0xb94b, 0x6814, 0xa084, 0x0184, 0xa085, 0x0012, 0x6816,
-	0x7803, 0x0008, 0x7003, 0x0000, 0x00fe, 0x00ee, 0xa386, 0x0002,
-	0x1128, 0x7884, 0xa005, 0x1110, 0x7887, 0x0001, 0x2001, 0xb8b1,
-	0x2004, 0x200a, 0x004e, 0xa39d, 0x0000, 0x1120, 0x2009, 0x0049,
-	0x080c, 0x86d3, 0x20a9, 0x03e8, 0x6824, 0xd094, 0x0158, 0x6827,
-	0x0004, 0x7804, 0xa084, 0x4000, 0x01a0, 0x7803, 0x1000, 0x7803,
-	0x0000, 0x0078, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04,
-	0x80d4, 0x7804, 0xa084, 0x1000, 0x0120, 0x7803, 0x0100, 0x7803,
-	0x0000, 0x6824, 0x000e, 0x001e, 0x002e, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000,
-	0x2069, 0xb8e1, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126,
-	0x2091, 0x8000, 0x2069, 0xb8e1, 0x6a32, 0x012e, 0x00de, 0x0005,
-	0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2071, 0xb8e1,
-	0x7614, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0538, 0x601c,
-	0xa206, 0x1500, 0x7014, 0xac36, 0x1110, 0x660c, 0x7616, 0x7010,
-	0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7012, 0x0010,
-	0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e,
-	0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9ed9, 0x080c, 0x81a5,
-	0x00ce, 0x08d8, 0x2c78, 0x600c, 0x2060, 0x08b8, 0x012e, 0x000e,
-	0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0156, 0x0146, 0x20a1,
-	0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2, 0x20a2,
-	0x20a2, 0x20a2, 0x20a3, 0x1000, 0x0804, 0x819d, 0x0156, 0x0146,
-	0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x4000, 0x0478, 0x0156, 0x0146,
-	0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x2000, 0x00f8, 0x0156, 0x0146,
-	0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0400, 0x0078, 0x0156, 0x0146,
-	0x20a1, 0x020b, 0x080c, 0x7974, 0x7810, 0x20a2, 0xa006, 0x20a2,
-	0x20a2, 0x20a2, 0x20a2, 0x20a3, 0x0200, 0x0089, 0x60c3, 0x0020,
-	0x080c, 0x7de0, 0x014e, 0x015e, 0x0005, 0x00e6, 0x2071, 0xb8e1,
-	0x7020, 0xa005, 0x0110, 0x8001, 0x7022, 0x00ee, 0x0005, 0x20a9,
-	0x0008, 0x20a2, 0x1f04, 0x81b1, 0x20a2, 0x20a2, 0x0005, 0x00f6,
-	0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091,
-	0x8000, 0x2071, 0xb8e1, 0x7614, 0x2660, 0x2678, 0x2039, 0x0001,
-	0x87ff, 0x0904, 0x824d, 0x8cff, 0x0904, 0x824d, 0x601c, 0xa086,
-	0x0006, 0x1904, 0x8248, 0x88ff, 0x0138, 0x2800, 0xac06, 0x1904,
-	0x8248, 0x2039, 0x0000, 0x0050, 0x6018, 0xa206, 0x1904, 0x8248,
-	0x85ff, 0x0120, 0x6050, 0xa106, 0x1904, 0x8248, 0x7024, 0xac06,
-	0x1598, 0x2069, 0x0100, 0x68c0, 0xa005, 0x1160, 0x6824, 0xd084,
-	0x0148, 0x6827, 0x0001, 0x080c, 0x6a82, 0x080c, 0x82d4, 0x7027,
-	0x0000, 0x0410, 0x080c, 0x6a82, 0x6820, 0xd0b4, 0x0110, 0x68a7,
-	0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x7014, 0xac36, 0x1110, 0x660c,
-	0x7616, 0x7010, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00,
-	0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06,
-	0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1158, 0x600f, 0x0000,
-	0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, 0x080c,
-	0x9ed9, 0x080c, 0x81a5, 0x88ff, 0x1190, 0x00ce, 0x0804, 0x81c8,
-	0x2c78, 0x600c, 0x2060, 0x0804, 0x81c8, 0xa006, 0x012e, 0x000e,
-	0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017,
-	0x0000, 0x00ce, 0xa8c5, 0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
-	0xb8e1, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904, 0x82c4, 0x601c,
-	0xa086, 0x0006, 0x1904, 0x82bf, 0x87ff, 0x0128, 0x2700, 0xac06,
-	0x1904, 0x82bf, 0x0048, 0x6018, 0xa206, 0x1904, 0x82bf, 0x85ff,
-	0x0118, 0x6050, 0xa106, 0x15d8, 0x703c, 0xac06, 0x1180, 0x0036,
-	0x2019, 0x0001, 0x080c, 0x806b, 0x7033, 0x0000, 0x703f, 0x0000,
-	0x7043, 0x0000, 0x7047, 0x0000, 0x704b, 0x0000, 0x003e, 0x7038,
-	0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140, 0x2c00,
-	0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c,
-	0x0066, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f,
-	0x0000, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155,
-	0x080c, 0x9ed9, 0x87ff, 0x1190, 0x00ce, 0x0804, 0x826c, 0x2c78,
-	0x600c, 0x2060, 0x0804, 0x826c, 0xa006, 0x012e, 0x000e, 0x002e,
-	0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6017, 0x0000,
-	0x00ce, 0xa7bd, 0x0001, 0x0c88, 0x00e6, 0x2071, 0xb8e1, 0x2001,
-	0xb600, 0x2004, 0xa086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010,
-	0x7007, 0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066,
-	0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0xb8e1, 0x2c10,
-	0x7638, 0x2660, 0x2678, 0x8cff, 0x0518, 0x2200, 0xac06, 0x11e0,
-	0x7038, 0xac36, 0x1110, 0x660c, 0x763a, 0x7034, 0xac36, 0x1140,
-	0x2c00, 0xaf36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000,
-	0x660c, 0x2c00, 0xaf06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f,
-	0x0000, 0xa085, 0x0001, 0x0020, 0x2c78, 0x600c, 0x2060, 0x08d8,
-	0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee, 0x00fe, 0x0005,
-	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0006, 0x0126, 0x2091,
-	0x8000, 0x2071, 0xb8e1, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904,
-	0x83aa, 0x6018, 0xa080, 0x0028, 0x2004, 0xa206, 0x1904, 0x83a5,
-	0x7024, 0xac06, 0x1508, 0x2069, 0x0100, 0x68c0, 0xa005, 0x0904,
-	0x8381, 0x080c, 0x7df3, 0x68c3, 0x0000, 0x080c, 0x82d4, 0x7027,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0xa384, 0x1000, 0x0120,
-	0x6803, 0x0100, 0x6803, 0x0000, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0xac36, 0x1110, 0x660c,
-	0x760e, 0x7008, 0xac36, 0x1140, 0x2c00, 0xaf36, 0x0118, 0x2f00,
-	0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0xaf06,
-	0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0x9f03,
-	0x1158, 0x080c, 0x2cf7, 0x080c, 0x9f14, 0x11f0, 0x080c, 0x8ca5,
-	0x00d8, 0x080c, 0x82d4, 0x08c0, 0x080c, 0x9f14, 0x1118, 0x080c,
-	0x8ca5, 0x0090, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0168, 0x601c,
-	0xa086, 0x0003, 0x11f8, 0x6837, 0x0103, 0x6b4a, 0x6847, 0x0000,
-	0x080c, 0x547a, 0x080c, 0x9ecd, 0x080c, 0xa0db, 0x080c, 0x9ed9,
-	0x080c, 0x81a5, 0x00ce, 0x0804, 0x832e, 0x2c78, 0x600c, 0x2060,
-	0x0804, 0x832e, 0x012e, 0x000e, 0x006e, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x0005, 0x601c, 0xa086, 0x0006, 0x1d30, 0x080c, 0xb155,
-	0x0c18, 0x0036, 0x0156, 0x0136, 0x0146, 0x3908, 0xa006, 0xa190,
-	0x0020, 0x221c, 0xa39e, 0x2aec, 0x1118, 0x8210, 0x8000, 0x0cc8,
-	0xa005, 0x0138, 0x20a9, 0x0020, 0x2198, 0xa110, 0x22a0, 0x22c8,
-	0x53a3, 0x014e, 0x013e, 0x015e, 0x003e, 0x0005, 0x00d6, 0x20a1,
-	0x020b, 0x080c, 0x774f, 0x20a3, 0x0200, 0x20a3, 0x0014, 0x60c3,
-	0x0014, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2099, 0xb8b9, 0x20a9,
-	0x0004, 0x53a6, 0x20a3, 0x0004, 0x20a3, 0x7878, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x080c, 0x7de0, 0x00de, 0x0005, 0x20a1, 0x020b,
-	0x080c, 0x774f, 0x20a3, 0x0214, 0x20a3, 0x0018, 0x20a3, 0x0800,
-	0x7810, 0xa084, 0xff00, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x20a3, 0x0000, 0x7810, 0xa084, 0x00ff, 0x20a2,
-	0x7828, 0x20a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x60c3, 0x0018,
-	0x080c, 0x7de0, 0x0005, 0x00d6, 0x0016, 0x2f68, 0x2009, 0x0035,
-	0x080c, 0xa1c6, 0x1904, 0x8489, 0x20a1, 0x020b, 0x080c, 0x76b3,
-	0x20a3, 0x1300, 0x20a3, 0x0000, 0x7828, 0x2068, 0x681c, 0xa086,
-	0x0003, 0x0580, 0x7818, 0xa080, 0x0028, 0x2014, 0x2001, 0xb635,
-	0x2004, 0xd0ac, 0x11d0, 0xa286, 0x007e, 0x1128, 0x20a3, 0x00ff,
-	0x20a3, 0xfffe, 0x04b8, 0xa286, 0x007f, 0x1128, 0x20a3, 0x00ff,
-	0x20a3, 0xfffd, 0x0478, 0xd2bc, 0x0180, 0xa286, 0x0080, 0x1128,
-	0x20a3, 0x00ff, 0x20a3, 0xfffc, 0x0428, 0xa2e8, 0xb735, 0x2d6c,
-	0x6810, 0x20a2, 0x6814, 0x20a2, 0x00e8, 0x20a3, 0x0000, 0x6098,
-	0x20a2, 0x00c0, 0x2001, 0xb635, 0x2004, 0xd0ac, 0x1138, 0x7818,
-	0xa080, 0x0028, 0x2004, 0xa082, 0x007e, 0x0240, 0x00d6, 0x2069,
-	0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0020, 0x20a3, 0x0000,
-	0x6034, 0x20a2, 0x7834, 0x20a2, 0x7838, 0x20a2, 0x20a3, 0x0000,
-	0x20a3, 0x0000, 0x60c3, 0x000c, 0x080c, 0x7de0, 0x001e, 0x00de,
-	0x0005, 0x7817, 0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x0005,
-	0x00d6, 0x0026, 0x7928, 0x2168, 0x691c, 0xa186, 0x0006, 0x01c0,
-	0xa186, 0x0003, 0x0904, 0x84ff, 0xa186, 0x0005, 0x0904, 0x84e8,
-	0xa186, 0x0004, 0x05b8, 0xa186, 0x0008, 0x0904, 0x84f0, 0x7807,
-	0x0037, 0x7813, 0x1700, 0x080c, 0x8567, 0x002e, 0x00de, 0x0005,
-	0x080c, 0x8523, 0x2009, 0x4000, 0x6800, 0x0002, 0x84c9, 0x84d4,
-	0x84cb, 0x84d4, 0x84d0, 0x84c9, 0x84c9, 0x84d4, 0x84d4, 0x84d4,
-	0x84d4, 0x84c9, 0x84c9, 0x84c9, 0x84c9, 0x84c9, 0x84d4, 0x84c9,
-	0x84d4, 0x080c, 0x151a, 0x6820, 0xd0e4, 0x0110, 0xd0cc, 0x0110,
-	0xa00e, 0x0010, 0x2009, 0x2000, 0x6828, 0x20a2, 0x682c, 0x20a2,
-	0x0804, 0x8519, 0x080c, 0x8523, 0x20a3, 0x0000, 0x20a3, 0x0000,
-	0x2009, 0x4000, 0x6a00, 0xa286, 0x0002, 0x1108, 0xa00e, 0x0488,
-	0x04d1, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0x0448,
-	0x0491, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x2009, 0x4000, 0xa286,
-	0x0005, 0x0118, 0xa286, 0x0002, 0x1108, 0xa00e, 0x00d0, 0x0419,
-	0x6810, 0x2068, 0x697c, 0x6810, 0xa112, 0x6980, 0x6814, 0xa103,
-	0x20a2, 0x22a2, 0x7928, 0xa180, 0x0000, 0x2004, 0xa08e, 0x0002,
-	0x0130, 0xa08e, 0x0004, 0x0118, 0x2009, 0x4000, 0x0010, 0x2009,
-	0x0000, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0018, 0x080c, 0x7de0,
-	0x002e, 0x00de, 0x0005, 0x0036, 0x0046, 0x0056, 0x0066, 0x20a1,
-	0x020b, 0x080c, 0x774f, 0xa006, 0x20a3, 0x0200, 0x20a2, 0x7934,
-	0x21a2, 0x7938, 0x21a2, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011,
-	0xb635, 0x2214, 0xd2ac, 0x1118, 0xa092, 0x007e, 0x0268, 0x00d6,
-	0x2069, 0xb61c, 0x2d2c, 0x8d68, 0x2d34, 0xa0e8, 0xb735, 0x2d6c,
-	0x6b10, 0x6c14, 0x00de, 0x0030, 0x2019, 0x0000, 0x6498, 0x2029,
-	0x0000, 0x6634, 0x7828, 0xa080, 0x0007, 0x2004, 0xa086, 0x0003,
-	0x1128, 0x25a2, 0x26a2, 0x23a2, 0x24a2, 0x0020, 0x23a2, 0x24a2,
-	0x25a2, 0x26a2, 0x006e, 0x005e, 0x004e, 0x003e, 0x0005, 0x20a1,
-	0x020b, 0x080c, 0x774f, 0x20a3, 0x0100, 0x20a3, 0x0000, 0x20a3,
-	0x0009, 0x7810, 0x20a2, 0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005,
-	0x20a1, 0x020b, 0x080c, 0x76ab, 0x20a3, 0x1400, 0x20a3, 0x0000,
-	0x7834, 0x20a2, 0x7838, 0x20a2, 0x7828, 0x20a2, 0x782c, 0x20a2,
-	0x7830, 0xa084, 0x00ff, 0x8007, 0x20a2, 0x20a3, 0x0000, 0x60c3,
-	0x0010, 0x080c, 0x7de0, 0x0005, 0x20a1, 0x020b, 0x080c, 0x7747,
-	0x20a3, 0x0100, 0x20a3, 0x0000, 0x7828, 0x20a2, 0x7810, 0x20a2,
-	0x60c3, 0x0008, 0x080c, 0x7de0, 0x0005, 0x0146, 0x20a1, 0x020b,
-	0x0031, 0x60c3, 0x0000, 0x080c, 0x7de0, 0x014e, 0x0005, 0x20e1,
-	0x9080, 0x20e1, 0x4000, 0x7818, 0xa080, 0x0028, 0x2004, 0x2011,
-	0xb635, 0x2214, 0xd2ac, 0x1110, 0xd0bc, 0x0188, 0x00d6, 0xa0e8,
-	0xb735, 0x2d6c, 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814, 0x20a2,
-	0x2069, 0xb61c, 0x2da6, 0x8d68, 0x2da6, 0x00de, 0x0078, 0x00d6,
-	0xa0e8, 0xb735, 0x2d6c, 0x6810, 0xa085, 0x0300, 0x20a2, 0x6814,
-	0x20a2, 0x00de, 0x20a3, 0x0000, 0x6234, 0x22a2, 0x20a3, 0x0819,
-	0x20a3, 0x0000, 0x080c, 0x7dcf, 0x22a2, 0x20a3, 0x0000, 0x2fa2,
-	0x7a08, 0x22a2, 0x20a3, 0x0000, 0x20a3, 0x0000, 0x0005, 0x20a1,
-	0x020b, 0x0079, 0x7910, 0x21a2, 0x20a3, 0x0000, 0x60c3, 0x0000,
-	0x20e1, 0x9080, 0x60a7, 0x9575, 0x080c, 0x7dea, 0x080c, 0x6a79,
-	0x0005, 0x0156, 0x0136, 0x0036, 0x00d6, 0x00e6, 0x20e1, 0x9080,
-	0x20e1, 0x4000, 0x7854, 0x2068, 0xadf0, 0x000f, 0x7210, 0xa296,
-	0x00c0, 0xa294, 0xfffd, 0x7212, 0x7214, 0xa294, 0x0300, 0x7216,
-	0x7100, 0xa194, 0x00ff, 0x7308, 0xa384, 0x00ff, 0xa08d, 0xc200,
-	0x7102, 0xa384, 0xff00, 0xa215, 0x720a, 0x7004, 0x720c, 0x700e,
-	0x7206, 0x20a9, 0x000a, 0x2e98, 0x53a6, 0x60a3, 0x0035, 0x6a38,
-	0xa294, 0x7000, 0xa286, 0x3000, 0x0110, 0x60a3, 0x0037, 0x00ee,
-	0x00de, 0x003e, 0x013e, 0x015e, 0x0005, 0x2009, 0x0092, 0x0010,
-	0x2009, 0x0096, 0x60ab, 0x0036, 0x6116, 0x0005, 0x2061, 0xbe00,
-	0x2a70, 0x7068, 0x704a, 0x704f, 0xbe00, 0x0005, 0x00e6, 0x0126,
-	0x2071, 0xb600, 0x2091, 0x8000, 0x7548, 0xa582, 0x0010, 0x0608,
-	0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148, 0xace0, 0x0018,
-	0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbe00, 0x0c98, 0x6003,
-	0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c, 0xa502, 0x1230,
-	0x754e, 0xa085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x704f, 0xbe00,
-	0x0cc0, 0xa006, 0x0cc0, 0x00e6, 0x2071, 0xb600, 0x7548, 0xa582,
-	0x0010, 0x0600, 0x704c, 0x2060, 0x6000, 0xa086, 0x0000, 0x0148,
-	0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0, 0x2061, 0xbe00,
-	0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8, 0x0018, 0x705c,
-	0xa502, 0x1228, 0x754e, 0xa085, 0x0001, 0x00ee, 0x0005, 0x704f,
-	0xbe00, 0x0cc8, 0xa006, 0x0cc8, 0xac82, 0xbe00, 0x0a0c, 0x151a,
-	0x2001, 0xb617, 0x2004, 0xac02, 0x1a0c, 0x151a, 0xa006, 0x6006,
-	0x600a, 0x600e, 0x6012, 0x6016, 0x601a, 0x601f, 0x0000, 0x6003,
-	0x0000, 0x6052, 0x6056, 0x6022, 0x6026, 0x602a, 0x602e, 0x6032,
-	0x6036, 0x603a, 0x603e, 0x2061, 0xb600, 0x6048, 0x8000, 0x604a,
-	0xa086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x71e5, 0x012e, 0x0cc0, 0x601c, 0xa084, 0x000f, 0x0002, 0x86e7,
-	0x86f6, 0x8711, 0x872c, 0xa20e, 0xa229, 0xa244, 0x86e7, 0x86f6,
-	0x86e7, 0x8747, 0x86e7, 0x86e7, 0x86e7, 0x86e7, 0x86e7, 0xa186,
-	0x0013, 0x1128, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0xa18e,
-	0x0047, 0x1118, 0xa016, 0x080c, 0x1863, 0x0005, 0x0066, 0x6000,
-	0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0x870f,
-	0x8b27, 0x8cdf, 0x870f, 0x8d54, 0x8805, 0x870f, 0x870f, 0x8ab9,
-	0x917b, 0x870f, 0x870f, 0x870f, 0x870f, 0x870f, 0x870f, 0x080c,
-	0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013,
-	0x006e, 0x0005, 0x872a, 0x97de, 0x872a, 0x872a, 0x872a, 0x872a,
-	0x872a, 0x872a, 0x9789, 0x994a, 0x872a, 0x980b, 0x9882, 0x980b,
-	0x9882, 0x872a, 0x080c, 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010,
-	0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0x8745, 0x91bc, 0x9286,
-	0x93c4, 0x954d, 0x8745, 0x8745, 0x8745, 0x9196, 0x9739, 0x973c,
-	0x8745, 0x8745, 0x8745, 0x8745, 0x9766, 0x080c, 0x151a, 0x0066,
-	0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005,
-	0x8760, 0x8760, 0x8760, 0x878e, 0x87db, 0x8760, 0x8760, 0x8760,
-	0x8762, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760, 0x8760,
-	0x080c, 0x151a, 0xa186, 0x0003, 0x190c, 0x151a, 0x00d6, 0x6003,
-	0x0003, 0x6106, 0x6010, 0x2068, 0x684f, 0x0040, 0x687c, 0x680a,
-	0x6880, 0x680e, 0x6813, 0x0000, 0x6817, 0x0000, 0x6854, 0xa092,
-	0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0xa210,
-	0x6216, 0x00de, 0x2c10, 0x080c, 0x1fc5, 0x080c, 0x6d62, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x72a2, 0x012e, 0x0005, 0xa182, 0x0047,
-	0x0002, 0x879a, 0x879a, 0x879c, 0x87b5, 0x879a, 0x879a, 0x879a,
-	0x879a, 0x87c7, 0x080c, 0x151a, 0x00d6, 0x0016, 0x080c, 0x7198,
-	0x080c, 0x72a2, 0x6003, 0x0004, 0x6110, 0x2168, 0x684f, 0x0020,
-	0x685c, 0x685a, 0x6874, 0x687e, 0x6878, 0x6882, 0x6897, 0x0000,
-	0x689b, 0x0000, 0x001e, 0x00de, 0x0005, 0x080c, 0x7198, 0x00d6,
-	0x6110, 0x2168, 0x080c, 0x9d16, 0x0120, 0x684b, 0x0006, 0x080c,
-	0x547a, 0x00de, 0x080c, 0x86a4, 0x080c, 0x72a2, 0x0005, 0x080c,
-	0x7198, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16,
-	0x0120, 0x684b, 0x0029, 0x080c, 0x547a, 0x00de, 0x080c, 0x86a4,
-	0x080c, 0x72a2, 0x0005, 0xa182, 0x0047, 0x0002, 0x87e9, 0x87f8,
-	0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x87e7, 0x080c,
-	0x151a, 0x00d6, 0x6010, 0x2068, 0x684c, 0xc0f4, 0x684e, 0x00de,
-	0x20e1, 0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005,
-	0x00d6, 0x6110, 0x2168, 0x684b, 0x0000, 0x6853, 0x0000, 0x080c,
-	0x547a, 0x00de, 0x080c, 0x86a4, 0x0005, 0xa1b6, 0x0015, 0x1118,
-	0x080c, 0x86a4, 0x0030, 0xa1b6, 0x0016, 0x190c, 0x151a, 0x080c,
-	0x86a4, 0x0005, 0x20a9, 0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3,
-	0x20a9, 0x0006, 0x3310, 0x3420, 0x9398, 0x94a0, 0x3318, 0x3428,
-	0x222e, 0x2326, 0xa290, 0x0002, 0xa5a8, 0x0002, 0xa398, 0x0002,
-	0xa4a0, 0x0002, 0x1f04, 0x8820, 0x00e6, 0x080c, 0x9d16, 0x0130,
-	0x6010, 0x2070, 0x7007, 0x0000, 0x7037, 0x0103, 0x00ee, 0x080c,
-	0x86a4, 0x0005, 0x00d6, 0x0036, 0x7330, 0xa386, 0x0200, 0x1130,
-	0x6018, 0x2068, 0x6813, 0x00ff, 0x6817, 0xfffd, 0x6010, 0xa005,
-	0x0130, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103, 0x6b32, 0x080c,
-	0x86a4, 0x003e, 0x00de, 0x0005, 0x0016, 0x20a9, 0x002a, 0xae80,
-	0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x53a3, 0x20a9,
-	0x002a, 0x6010, 0xa080, 0x0001, 0x2004, 0xa080, 0x0002, 0x20a0,
-	0x53a3, 0x00e6, 0x6010, 0x2004, 0x2070, 0x7037, 0x0103, 0x00ee,
-	0x080c, 0x86a4, 0x001e, 0x0005, 0x0016, 0x2009, 0x0000, 0x7030,
-	0xa086, 0x0100, 0x0140, 0x7038, 0xa084, 0x00ff, 0x800c, 0x703c,
-	0xa084, 0x00ff, 0x8004, 0xa080, 0x0004, 0xa108, 0x21a8, 0xae80,
-	0x000c, 0x2098, 0x6010, 0xa080, 0x0002, 0x20a0, 0x080c, 0x4bf1,
-	0x00e6, 0x080c, 0x9d16, 0x0140, 0x6010, 0x2070, 0x7007, 0x0000,
-	0x7034, 0x70b2, 0x7037, 0x0103, 0x00ee, 0x080c, 0x86a4, 0x001e,
-	0x0005, 0x00e6, 0x00d6, 0x603f, 0x0000, 0x2c68, 0x0016, 0x2009,
-	0x0035, 0x080c, 0xa1c6, 0x001e, 0x1168, 0x0026, 0x6228, 0x2268,
-	0x002e, 0x2071, 0xbc8c, 0x6b1c, 0xa386, 0x0003, 0x0130, 0xa386,
-	0x0006, 0x0128, 0x080c, 0x86a4, 0x0020, 0x0031, 0x0010, 0x080c,
-	0x8982, 0x00de, 0x00ee, 0x0005, 0x00f6, 0x6810, 0x2078, 0xa186,
-	0x0015, 0x0904, 0x8969, 0xa18e, 0x0016, 0x1904, 0x8980, 0x700c,
-	0xa08c, 0xff00, 0xa186, 0x1700, 0x0120, 0xa186, 0x0300, 0x1904,
-	0x8948, 0x8fff, 0x1138, 0x6800, 0xa086, 0x000f, 0x0904, 0x892c,
-	0x0804, 0x897e, 0x6808, 0xa086, 0xffff, 0x1904, 0x896b, 0x784c,
-	0xa084, 0x0060, 0xa086, 0x0020, 0x1150, 0x797c, 0x7810, 0xa106,
-	0x1904, 0x896b, 0x7980, 0x7814, 0xa106, 0x1904, 0x896b, 0x080c,
-	0x9ecd, 0x6858, 0x7852, 0x784c, 0xc0dc, 0xc0f4, 0xc0d4, 0x784e,
-	0x0026, 0xa00e, 0x6a14, 0x2001, 0x000a, 0x080c, 0x6bb2, 0x7854,
-	0xa20a, 0x0208, 0x8011, 0x7a56, 0x82ff, 0x002e, 0x1138, 0x00c6,
-	0x2d60, 0x080c, 0x9ac5, 0x00ce, 0x0804, 0x897e, 0x00c6, 0x00d6,
-	0x2f68, 0x6838, 0xd0fc, 0x1118, 0x080c, 0x4cd7, 0x0010, 0x080c,
-	0x4ebb, 0x00de, 0x00ce, 0x1904, 0x896b, 0x00c6, 0x2d60, 0x080c,
-	0x86a4, 0x00ce, 0x0804, 0x897e, 0x00c6, 0x080c, 0x9f92, 0x0190,
-	0x6013, 0x0000, 0x6818, 0x601a, 0x080c, 0xa0e3, 0x601f, 0x0003,
-	0x6904, 0x00c6, 0x2d60, 0x080c, 0x86a4, 0x00ce, 0x080c, 0x86d3,
-	0x00ce, 0x04e0, 0x2001, 0xb8b8, 0x2004, 0x683e, 0x00ce, 0x04b0,
-	0x7008, 0xa086, 0x000b, 0x11a0, 0x6018, 0x200c, 0xc1bc, 0x2102,
-	0x00c6, 0x2d60, 0x784b, 0x0003, 0x6007, 0x0085, 0x6003, 0x000b,
-	0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ce, 0x00f0,
-	0x700c, 0xa086, 0x2a00, 0x1138, 0x2001, 0xb8b8, 0x2004, 0x683e,
-	0x00a8, 0x0481, 0x00a8, 0x8fff, 0x090c, 0x151a, 0x00c6, 0x00d6,
-	0x2d60, 0x2f68, 0x6837, 0x0103, 0x684b, 0x0003, 0x080c, 0x99b9,
-	0x080c, 0x9ecd, 0x080c, 0x9ed9, 0x00de, 0x00ce, 0x080c, 0x86a4,
-	0x00fe, 0x0005, 0xa186, 0x0015, 0x1128, 0x2001, 0xb8b8, 0x2004,
-	0x683e, 0x0068, 0xa18e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060,
-	0x080c, 0xb3f6, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x00ce, 0x080c,
-	0x86a4, 0x0005, 0x0026, 0x0036, 0x0046, 0x7228, 0x7c80, 0x7b7c,
-	0xd2f4, 0x0130, 0x2001, 0xb8b8, 0x2004, 0x683e, 0x0804, 0x89fc,
-	0x00c6, 0x2d60, 0x080c, 0x99d9, 0x00ce, 0x6804, 0xa086, 0x0050,
-	0x1168, 0x00c6, 0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050,
-	0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ce, 0x04f0, 0x6800, 0xa086,
-	0x000f, 0x01c8, 0x8fff, 0x090c, 0x151a, 0x6820, 0xd0dc, 0x1198,
-	0x6800, 0xa086, 0x0004, 0x1198, 0x784c, 0xd0ac, 0x0180, 0x784c,
-	0xc0dc, 0xc0f4, 0x784e, 0x7850, 0xc0f4, 0xc0fc, 0x7852, 0x2001,
-	0x0001, 0x682e, 0x00e0, 0x2001, 0x0007, 0x682e, 0x00c0, 0x784c,
-	0xd0b4, 0x1130, 0xd0ac, 0x0db8, 0x784c, 0xd0f4, 0x1da0, 0x0c38,
-	0xd2ec, 0x1d88, 0x7024, 0xa306, 0x1118, 0x7020, 0xa406, 0x0d58,
-	0x7020, 0x6836, 0x7024, 0x683a, 0x2001, 0x0005, 0x682e, 0x080c,
-	0xa01f, 0x080c, 0x71e5, 0x0010, 0x080c, 0x86a4, 0x004e, 0x003e,
-	0x002e, 0x0005, 0x00e6, 0x00d6, 0x0026, 0x6034, 0x2068, 0x6a1c,
-	0xa286, 0x0007, 0x0904, 0x8a60, 0xa286, 0x0002, 0x0904, 0x8a60,
-	0xa286, 0x0000, 0x0904, 0x8a60, 0x6808, 0x6338, 0xa306, 0x1904,
-	0x8a60, 0x2071, 0xbc8c, 0xa186, 0x0015, 0x05e0, 0xa18e, 0x0016,
-	0x1190, 0x6030, 0xa084, 0x00ff, 0xa086, 0x0001, 0x1160, 0x700c,
-	0xa086, 0x2a00, 0x1140, 0x6034, 0xa080, 0x0008, 0x200c, 0xc1dd,
-	0xc1f5, 0x2102, 0x0438, 0x00c6, 0x6034, 0x2060, 0x6104, 0xa186,
-	0x004b, 0x01a0, 0xa186, 0x004c, 0x0188, 0xa186, 0x004d, 0x0170,
-	0xa186, 0x004e, 0x0158, 0xa186, 0x0052, 0x0140, 0x6010, 0x2068,
-	0x080c, 0x9d16, 0x090c, 0x151a, 0x684b, 0x0003, 0x6007, 0x0085,
-	0x6003, 0x000b, 0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5,
-	0x00ce, 0x0030, 0x6034, 0x2070, 0x2001, 0xb8b8, 0x2004, 0x703e,
-	0x080c, 0x86a4, 0x002e, 0x00de, 0x00ee, 0x0005, 0x00d6, 0x20a9,
-	0x000e, 0x2e98, 0x6010, 0x20a0, 0x53a3, 0xa1b6, 0x0015, 0x1558,
-	0x6018, 0x2068, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c, 0xa290,
-	0x0004, 0x20a9, 0x0004, 0xad98, 0x000a, 0x080c, 0x9166, 0x002e,
-	0x003e, 0x015e, 0x11d8, 0x0156, 0x0036, 0x0026, 0xae90, 0x000c,
-	0xa290, 0x0008, 0x20a9, 0x0004, 0xad98, 0x0006, 0x080c, 0x9166,
-	0x002e, 0x003e, 0x015e, 0x1150, 0x7038, 0x680a, 0x703c, 0x680e,
-	0x6800, 0xc08d, 0x6802, 0x00de, 0x0804, 0x882c, 0x080c, 0x2cd1,
-	0x00c6, 0x080c, 0x864e, 0x2f00, 0x601a, 0x6013, 0x0000, 0x601f,
-	0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x2001, 0x0007, 0x080c,
-	0x4f6f, 0x080c, 0x4f9c, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00ce,
-	0x0c10, 0x2100, 0xa1b2, 0x0080, 0x1a0c, 0x151a, 0xa1b2, 0x0040,
-	0x1a04, 0x8b1d, 0x0002, 0x8b11, 0x8b05, 0x8b11, 0x8b11, 0x8b11,
-	0x8b11, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03,
-	0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03,
-	0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03,
-	0x8b03, 0x8b03, 0x8b11, 0x8b03, 0x8b11, 0x8b11, 0x8b03, 0x8b03,
-	0x8b03, 0x8b03, 0x8b03, 0x8b11, 0x8b03, 0x8b03, 0x8b03, 0x8b03,
-	0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b11, 0x8b11, 0x8b03,
-	0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03, 0x8b03,
-	0x8b11, 0x8b03, 0x8b03, 0x080c, 0x151a, 0x6003, 0x0001, 0x6106,
-	0x080c, 0x6d45, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e,
-	0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x6d45, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, 0x2600, 0x0002, 0x8b11,
-	0x8b11, 0x8b25, 0x8b11, 0x8b11, 0x8b25, 0x080c, 0x151a, 0x6004,
-	0xa0b2, 0x0080, 0x1a0c, 0x151a, 0xa1b6, 0x0013, 0x0904, 0x8bd7,
-	0xa1b6, 0x0027, 0x1904, 0x8b9d, 0x080c, 0x7102, 0x6004, 0x080c,
-	0x9f03, 0x0190, 0x080c, 0x9f14, 0x0904, 0x8b97, 0xa08e, 0x0021,
-	0x0904, 0x8b9a, 0xa08e, 0x0022, 0x0904, 0x8b97, 0xa08e, 0x003d,
-	0x0904, 0x8b9a, 0x0804, 0x8b90, 0x080c, 0x2cf7, 0x2001, 0x0007,
-	0x080c, 0x4f6f, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8ca5,
-	0xa186, 0x007e, 0x1148, 0x2001, 0xb635, 0x2014, 0xc285, 0x080c,
-	0x5b41, 0x1108, 0xc2ad, 0x2202, 0x0016, 0x0026, 0x0036, 0x2110,
-	0x0026, 0x2019, 0x0028, 0x080c, 0x8320, 0x002e, 0x080c, 0xb449,
-	0x003e, 0x002e, 0x001e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019,
-	0x0028, 0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74,
-	0x00c6, 0x6018, 0xa065, 0x0110, 0x080c, 0x521c, 0x00ce, 0x2c08,
-	0x080c, 0xaf3e, 0x007e, 0x003e, 0x002e, 0x001e, 0x080c, 0x4fde,
-	0x080c, 0xa0db, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0x080c,
-	0x8ca5, 0x0cb0, 0x080c, 0x8cd3, 0x0c98, 0xa186, 0x0014, 0x1db0,
-	0x080c, 0x7102, 0x080c, 0x2cd1, 0x080c, 0x9f03, 0x1188, 0x080c,
-	0x2cf7, 0x6018, 0xa080, 0x0028, 0x200c, 0x080c, 0x8ca5, 0xa186,
-	0x007e, 0x1128, 0x2001, 0xb635, 0x200c, 0xc185, 0x2102, 0x08c0,
-	0x080c, 0x9f14, 0x1118, 0x080c, 0x8ca5, 0x0890, 0x6004, 0xa08e,
-	0x0032, 0x1158, 0x00e6, 0x00f6, 0x2071, 0xb682, 0x2079, 0x0000,
-	0x080c, 0x3004, 0x00fe, 0x00ee, 0x0818, 0x6004, 0xa08e, 0x0021,
-	0x0d50, 0xa08e, 0x0022, 0x090c, 0x8ca5, 0x0804, 0x8b90, 0xa0b2,
-	0x0040, 0x1a04, 0x8c9a, 0x2008, 0x0002, 0x8c1f, 0x8c20, 0x8c23,
-	0x8c26, 0x8c29, 0x8c2c, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d,
-	0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d,
-	0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d,
-	0x8c1d, 0x8c1d, 0x8c1d, 0x8c2f, 0x8c3e, 0x8c1d, 0x8c40, 0x8c3e,
-	0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c3e, 0x8c3e, 0x8c1d,
-	0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c7a,
-	0x8c3e, 0x8c1d, 0x8c3a, 0x8c1d, 0x8c1d, 0x8c1d, 0x8c3b, 0x8c1d,
-	0x8c1d, 0x8c1d, 0x8c3e, 0x8c71, 0x8c1d, 0x080c, 0x151a, 0x00f0,
-	0x2001, 0x000b, 0x0460, 0x2001, 0x0003, 0x0448, 0x2001, 0x0005,
-	0x0430, 0x2001, 0x0001, 0x0418, 0x2001, 0x0009, 0x0400, 0x080c,
-	0x7102, 0x6003, 0x0005, 0x2001, 0xb8b8, 0x2004, 0x603e, 0x080c,
-	0x71e5, 0x00a0, 0x0018, 0x0010, 0x080c, 0x4f6f, 0x0804, 0x8c8b,
-	0x080c, 0x7102, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x2001, 0xb8b8,
-	0x2004, 0x603e, 0x6003, 0x0004, 0x080c, 0x71e5, 0x0005, 0x080c,
-	0x4f6f, 0x080c, 0x7102, 0x6003, 0x0002, 0x2001, 0xb8b8, 0x2004,
-	0x603e, 0x0036, 0x2019, 0xb65d, 0x2304, 0xa084, 0xff00, 0x1120,
-	0x2001, 0xb8b6, 0x201c, 0x0040, 0x8007, 0xa09a, 0x0004, 0x0ec0,
-	0x8003, 0x801b, 0x831b, 0xa318, 0x6316, 0x003e, 0x080c, 0x71e5,
-	0x08e8, 0x080c, 0x7102, 0x080c, 0xa0db, 0x080c, 0x86a4, 0x080c,
-	0x71e5, 0x08a0, 0x00e6, 0x00f6, 0x2071, 0xb682, 0x2079, 0x0000,
-	0x080c, 0x3004, 0x00fe, 0x00ee, 0x080c, 0x7102, 0x080c, 0x86a4,
-	0x080c, 0x71e5, 0x0818, 0x080c, 0x7102, 0x2001, 0xb8b8, 0x2004,
-	0x603e, 0x6003, 0x0002, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x080c,
-	0x71e5, 0x0005, 0x2600, 0x2008, 0x0002, 0x8ca3, 0x8ca3, 0x8ca3,
-	0x8c8b, 0x8c8b, 0x8ca3, 0x080c, 0x151a, 0x00e6, 0x0026, 0x0016,
-	0x080c, 0x9d16, 0x0508, 0x6010, 0x2070, 0x7034, 0xa086, 0x0139,
-	0x1148, 0x2001, 0x0030, 0x2009, 0x0000, 0x2011, 0x4005, 0x080c,
-	0xa192, 0x0090, 0x7038, 0xd0fc, 0x0178, 0x7007, 0x0000, 0x0016,
-	0x6004, 0xa08e, 0x0021, 0x0160, 0xa08e, 0x003d, 0x0148, 0x001e,
-	0x7037, 0x0103, 0x7033, 0x0100, 0x001e, 0x002e, 0x00ee, 0x0005,
-	0x001e, 0x0009, 0x0cc8, 0x00e6, 0xacf0, 0x0004, 0x2e74, 0x7000,
-	0x2070, 0x7037, 0x0103, 0x7023, 0x8001, 0x00ee, 0x0005, 0x00d6,
-	0x6618, 0x2668, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa0b2, 0x000c,
-	0x1a0c, 0x151a, 0x6604, 0xa6b6, 0x0043, 0x1120, 0x080c, 0xa14e,
-	0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0033, 0x1120, 0x080c, 0xa0fe,
-	0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0028, 0x1120, 0x080c, 0x9f44,
-	0x0804, 0x8d44, 0x6604, 0xa6b6, 0x0029, 0x1118, 0x080c, 0x9f5b,
-	0x04d8, 0x6604, 0xa6b6, 0x001f, 0x1118, 0x080c, 0x8812, 0x04a0,
-	0x6604, 0xa6b6, 0x0000, 0x1118, 0x080c, 0x8a66, 0x0468, 0x6604,
-	0xa6b6, 0x0022, 0x1118, 0x080c, 0x883a, 0x0430, 0x6604, 0xa6b6,
-	0x0035, 0x1118, 0x080c, 0x88a1, 0x00f8, 0x6604, 0xa6b6, 0x0039,
-	0x1118, 0x080c, 0x8a02, 0x00c0, 0x6604, 0xa6b6, 0x003d, 0x1118,
-	0x080c, 0x8854, 0x0088, 0x6604, 0xa6b6, 0x0044, 0x1118, 0x080c,
-	0x8874, 0x0050, 0xa1b6, 0x0015, 0x1110, 0x0053, 0x0028, 0xa1b6,
-	0x0016, 0x1118, 0x0804, 0x8f08, 0x0005, 0x080c, 0x86ef, 0x0ce0,
-	0x8d6b, 0x8d6e, 0x8d6b, 0x8db0, 0x8d6b, 0x8e95, 0x8f16, 0x8d6b,
-	0x8d6b, 0x8ee4, 0x8d6b, 0x8ef8, 0xa1b6, 0x0048, 0x0140, 0x20e1,
-	0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, 0x00e6,
-	0xacf0, 0x0004, 0x2e74, 0x7000, 0x2070, 0x7037, 0x0103, 0x00ee,
-	0x080c, 0x86a4, 0x0005, 0xe000, 0xe000, 0x0005, 0x00e6, 0x2071,
-	0xb600, 0x7084, 0xa086, 0x0074, 0x1530, 0x080c, 0xaf15, 0x11b0,
-	0x00d6, 0x6018, 0x2068, 0x7030, 0xd08c, 0x0128, 0x6800, 0xd0bc,
-	0x0110, 0xc0c5, 0x6802, 0x00d9, 0x00de, 0x2001, 0x0006, 0x080c,
-	0x4f6f, 0x080c, 0x2cf7, 0x080c, 0x86a4, 0x0078, 0x2001, 0x000a,
-	0x080c, 0x4f6f, 0x080c, 0x2cf7, 0x6003, 0x0001, 0x6007, 0x0001,
-	0x080c, 0x6d45, 0x0010, 0x080c, 0x8e82, 0x00ee, 0x0005, 0x6800,
-	0xd084, 0x0168, 0x2001, 0x0000, 0x080c, 0x4f5d, 0x2069, 0xb652,
-	0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x4f9c, 0x0005,
-	0x00d6, 0x2011, 0xb621, 0x2204, 0xa086, 0x0074, 0x1904, 0x8e7f,
-	0x6018, 0x2068, 0x6aa0, 0xa286, 0x007e, 0x1120, 0x080c, 0x902e,
-	0x0804, 0x8e1e, 0x080c, 0x9024, 0x6018, 0x2068, 0xa080, 0x0028,
-	0x2014, 0xa286, 0x0080, 0x11c0, 0x6813, 0x00ff, 0x6817, 0xfffc,
-	0x6010, 0xa005, 0x0138, 0x2068, 0x6807, 0x0000, 0x6837, 0x0103,
-	0x6833, 0x0200, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x080c, 0x2cf7,
-	0x080c, 0x86a4, 0x0804, 0x8e80, 0x00e6, 0x2071, 0xb635, 0x2e04,
-	0xd09c, 0x0188, 0x2071, 0xbc80, 0x7108, 0x720c, 0xa18c, 0x00ff,
-	0x1118, 0xa284, 0xff00, 0x0138, 0x6018, 0x2070, 0x70a0, 0xd0bc,
-	0x1110, 0x7112, 0x7216, 0x00ee, 0x6010, 0xa005, 0x0198, 0x2068,
-	0x6838, 0xd0f4, 0x0178, 0x6834, 0xa084, 0x00ff, 0xa086, 0x0039,
-	0x1958, 0x2001, 0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c,
-	0xa192, 0x0840, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x6003, 0x0001,
-	0x6007, 0x0003, 0x080c, 0x6d45, 0x0804, 0x8e80, 0x685c, 0xd0e4,
-	0x01d8, 0x080c, 0xa08e, 0x080c, 0x5b41, 0x0118, 0xd0dc, 0x1904,
-	0x8dda, 0x2011, 0xb635, 0x2204, 0xc0ad, 0x2012, 0x2001, 0xb88f,
-	0x2004, 0x00f6, 0x2079, 0x0100, 0x78e3, 0x0000, 0x080c, 0x28a7,
-	0x78e2, 0x00fe, 0x0804, 0x8dda, 0x080c, 0xa0c4, 0x2011, 0xb635,
-	0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xb037, 0x000e, 0x1904,
-	0x8dda, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x2001,
-	0x0000, 0x080c, 0x4f5d, 0x00c6, 0x2009, 0x00ef, 0x00f6, 0x2079,
-	0x0100, 0x79ea, 0x7932, 0x7936, 0x00fe, 0x080c, 0x287c, 0x00f6,
-	0x2079, 0xb600, 0x7976, 0x2100, 0x2009, 0x0000, 0x080c, 0x2852,
-	0x7952, 0x00fe, 0x8108, 0x080c, 0x4fbf, 0x2c00, 0x00ce, 0x1904,
-	0x8dda, 0x601a, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x601f, 0x0001,
-	0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x0008, 0x0011,
-	0x00de, 0x0005, 0x2001, 0x0007, 0x080c, 0x4f6f, 0x2001, 0xb600,
-	0x2004, 0xa086, 0x0003, 0x1120, 0x2001, 0x0007, 0x080c, 0x4f9c,
-	0x080c, 0x2cf7, 0x080c, 0x86a4, 0x0005, 0x00e6, 0x0026, 0x0016,
-	0x2071, 0xb600, 0x7084, 0xa086, 0x0014, 0x15f0, 0x7000, 0xa086,
-	0x0003, 0x1128, 0x6010, 0xa005, 0x1110, 0x080c, 0x3f85, 0x00d6,
-	0x6018, 0x2068, 0x080c, 0x50bd, 0x080c, 0x8d9f, 0x00de, 0x080c,
-	0x90dd, 0x1550, 0x00d6, 0x6018, 0x2068, 0x6890, 0x00de, 0xa005,
-	0x0518, 0x2001, 0x0006, 0x080c, 0x4f6f, 0x00e6, 0x6010, 0xa075,
-	0x01a8, 0x7034, 0xa084, 0x00ff, 0xa086, 0x0039, 0x1148, 0x2001,
-	0x0000, 0x2009, 0x0000, 0x2011, 0x4000, 0x080c, 0xa192, 0x0030,
-	0x7007, 0x0000, 0x7037, 0x0103, 0x7033, 0x0200, 0x00ee, 0x080c,
-	0x2cf7, 0x080c, 0x86a4, 0x0020, 0x080c, 0x8ca5, 0x080c, 0x8e82,
-	0x001e, 0x002e, 0x00ee, 0x0005, 0x2011, 0xb621, 0x2204, 0xa086,
-	0x0014, 0x1158, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001,
-	0x6007, 0x0001, 0x080c, 0x6d45, 0x0010, 0x080c, 0x8e82, 0x0005,
-	0x2011, 0xb621, 0x2204, 0xa086, 0x0004, 0x1138, 0x2001, 0x0007,
-	0x080c, 0x4f6f, 0x080c, 0x86a4, 0x0010, 0x080c, 0x8e82, 0x0005,
-	0x000b, 0x0005, 0x8d6b, 0x8f21, 0x8d6b, 0x8f55, 0x8d6b, 0x8fe0,
-	0x8f16, 0x8d6b, 0x8d6b, 0x8ff3, 0x8d6b, 0x9003, 0x6604, 0xa686,
-	0x0003, 0x0904, 0x8e95, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x86a4,
-	0x0005, 0x00d6, 0x00c6, 0x080c, 0x9013, 0x1178, 0x2001, 0x0000,
-	0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001,
-	0x6007, 0x0002, 0x080c, 0x6d45, 0x00e8, 0x2009, 0xbc8e, 0x2104,
-	0xa086, 0x0009, 0x1160, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff,
-	0xa005, 0x0170, 0x8001, 0x6842, 0x6017, 0x000a, 0x0058, 0x2009,
-	0xbc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x1900, 0x1108, 0x08d0,
-	0x080c, 0x8e82, 0x00ce, 0x00de, 0x0005, 0x0026, 0x2011, 0x0000,
-	0x080c, 0x9021, 0x00d6, 0x2069, 0xb89e, 0x2d04, 0xa005, 0x0168,
-	0x6018, 0x2068, 0x68a0, 0xa086, 0x007e, 0x1138, 0x2069, 0xb61d,
-	0x2d04, 0x8000, 0x206a, 0x00de, 0x0010, 0x00de, 0x0078, 0x2001,
-	0x0000, 0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x0480, 0x00d6, 0x6010,
-	0x2068, 0x080c, 0x9d16, 0x00de, 0x0108, 0x6a34, 0x080c, 0x8ca5,
-	0x2009, 0xbc8e, 0x2134, 0xa6b4, 0x00ff, 0xa686, 0x0005, 0x0500,
-	0xa686, 0x000b, 0x01c8, 0x2009, 0xbc8f, 0x2104, 0xa084, 0xff00,
-	0x1118, 0xa686, 0x0009, 0x01a0, 0xa086, 0x1900, 0x1168, 0xa686,
-	0x0009, 0x0170, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x2001, 0x0028,
-	0x6016, 0x6007, 0x004b, 0x0010, 0x080c, 0x8e82, 0x002e, 0x0005,
-	0x00d6, 0xa286, 0x0139, 0x0160, 0x6010, 0x2068, 0x080c, 0x9d16,
-	0x0148, 0x6834, 0xa086, 0x0139, 0x0118, 0x6838, 0xd0fc, 0x0110,
-	0x00de, 0x0c50, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005,
-	0x0140, 0x8001, 0x6842, 0x6017, 0x000a, 0x6007, 0x0016, 0x00de,
-	0x08e8, 0x68a0, 0xa086, 0x007e, 0x1138, 0x00e6, 0x2071, 0xb600,
-	0x080c, 0x4c28, 0x00ee, 0x0010, 0x080c, 0x2cd1, 0x00de, 0x0860,
-	0x080c, 0x9021, 0x1158, 0x2001, 0x0004, 0x080c, 0x4f6f, 0x6003,
-	0x0001, 0x6007, 0x0003, 0x080c, 0x6d45, 0x0020, 0x080c, 0x8ca5,
-	0x080c, 0x8e82, 0x0005, 0x0469, 0x1158, 0x2001, 0x0008, 0x080c,
-	0x4f6f, 0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x6d45, 0x0010,
-	0x080c, 0x8e82, 0x0005, 0x00e9, 0x1158, 0x2001, 0x000a, 0x080c,
-	0x4f6f, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6d45, 0x0010,
-	0x080c, 0x8e82, 0x0005, 0x2009, 0xbc8e, 0x2104, 0xa086, 0x0003,
-	0x1138, 0x2009, 0xbc8f, 0x2104, 0xa084, 0xff00, 0xa086, 0x2a00,
-	0x0005, 0xa085, 0x0001, 0x0005, 0x00c6, 0x0016, 0xac88, 0x0006,
-	0x2164, 0x080c, 0x502a, 0x001e, 0x00ce, 0x0005, 0x00f6, 0x00e6,
-	0x00d6, 0x0036, 0x0016, 0x6018, 0x2068, 0x2071, 0xb635, 0x2e04,
-	0xa085, 0x0003, 0x2072, 0x080c, 0x90b2, 0x0560, 0x2009, 0xb635,
-	0x2104, 0xc0cd, 0x200a, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0158,
-	0xa006, 0x2020, 0x2009, 0x002a, 0x080c, 0xb1a4, 0x2001, 0xb60c,
-	0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001, 0x080c,
-	0x2ca4, 0x2071, 0xb600, 0x080c, 0x2aed, 0x00c6, 0x0156, 0x20a9,
-	0x0081, 0x2009, 0x007f, 0x080c, 0x2dcc, 0x8108, 0x1f04, 0x9063,
-	0x015e, 0x00ce, 0x080c, 0x9024, 0x6813, 0x00ff, 0x6817, 0xfffe,
-	0x2071, 0xbc80, 0x2079, 0x0100, 0x2e04, 0xa084, 0x00ff, 0x2069,
-	0xb61c, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04, 0x2069, 0xb61d,
-	0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0xa084, 0xff00, 0x001e,
-	0xa105, 0x2009, 0xb628, 0x200a, 0x2200, 0xa084, 0x00ff, 0x2008,
-	0x080c, 0x287c, 0x080c, 0x5b41, 0x0170, 0x2069, 0xbc8e, 0x2071,
-	0xb8b2, 0x6810, 0x2072, 0x6814, 0x7006, 0x6818, 0x700a, 0x681c,
-	0x700e, 0x080c, 0xa08e, 0x0040, 0x2001, 0x0006, 0x080c, 0x4f6f,
-	0x080c, 0x2cf7, 0x080c, 0x86a4, 0x001e, 0x003e, 0x00de, 0x00ee,
-	0x00fe, 0x0005, 0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0xb628,
-	0x231c, 0x83ff, 0x01e8, 0x2071, 0xbc80, 0x2e14, 0xa294, 0x00ff,
-	0x7004, 0xa084, 0xff00, 0xa205, 0xa306, 0x1190, 0x2011, 0xbc96,
-	0xad98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1148, 0x2011,
-	0xbc9a, 0xad98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1100,
-	0x015e, 0x00ee, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xbc8c,
-	0x7004, 0xa086, 0x0014, 0x11a8, 0x7008, 0xa086, 0x0800, 0x1188,
-	0x700c, 0xd0ec, 0x0160, 0xa084, 0x0f00, 0xa086, 0x0100, 0x1138,
-	0x7024, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0xa006, 0x0010, 0xa085,
-	0x0001, 0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0056,
-	0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0xb8ea,
-	0x252c, 0x2021, 0xb8f0, 0x2424, 0x2061, 0xbe00, 0x2071, 0xb600,
-	0x7248, 0x7068, 0xa202, 0x16f0, 0x080c, 0xb1cc, 0x05a0, 0x671c,
-	0xa786, 0x0001, 0x0580, 0xa786, 0x0007, 0x0568, 0x2500, 0xac06,
-	0x0550, 0x2400, 0xac06, 0x0538, 0x00c6, 0x6000, 0xa086, 0x0004,
-	0x1110, 0x080c, 0x1952, 0xa786, 0x0008, 0x1148, 0x080c, 0x9f14,
-	0x1130, 0x00ce, 0x080c, 0x8ca5, 0x080c, 0x9ed9, 0x00a0, 0x6010,
-	0x2068, 0x080c, 0x9d16, 0x0160, 0xa786, 0x0003, 0x11e8, 0x6837,
-	0x0103, 0x6b4a, 0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd,
-	0x080c, 0x9ed9, 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1210,
-	0x0804, 0x9110, 0x012e, 0x000e, 0x002e, 0x004e, 0x005e, 0x007e,
-	0x00ce, 0x00de, 0x00ee, 0x0005, 0xa786, 0x0006, 0x1118, 0x080c,
-	0xb155, 0x0c30, 0xa786, 0x000a, 0x09e0, 0x08c8, 0x220c, 0x2304,
-	0xa106, 0x1130, 0x8210, 0x8318, 0x1f04, 0x9166, 0xa006, 0x0005,
-	0x2304, 0xa102, 0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000,
-	0xa18d, 0x0001, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c, 0x151a,
-	0x080c, 0x9f03, 0x0120, 0x080c, 0x9f14, 0x0168, 0x0028, 0x080c,
-	0x2cf7, 0x080c, 0x9f14, 0x0138, 0x080c, 0x7102, 0x080c, 0x86a4,
-	0x080c, 0x71e5, 0x0005, 0x080c, 0x8ca5, 0x0cb0, 0xa182, 0x0040,
-	0x0002, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ac,
-	0x91ac, 0x91ac, 0x91ac, 0x91ac, 0x91ae, 0x91ae, 0x91ae, 0x91ae,
-	0x91ac, 0x91ac, 0x91ac, 0x91ae, 0x080c, 0x151a, 0x600b, 0xffff,
-	0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x71e5, 0x012e, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004,
-	0xa082, 0x0040, 0x0804, 0x9248, 0xa186, 0x0027, 0x11e8, 0x080c,
-	0x7102, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16,
-	0x0168, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847, 0x0000, 0x694c,
-	0xc1c5, 0x694e, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c,
-	0x86a4, 0x080c, 0x71e5, 0x0005, 0xa186, 0x0014, 0x1120, 0x6004,
-	0xa082, 0x0040, 0x0428, 0xa186, 0x0046, 0x0138, 0xa186, 0x0045,
-	0x0120, 0xa186, 0x0047, 0x190c, 0x151a, 0x2001, 0x0109, 0x2004,
-	0xd084, 0x0198, 0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026,
-	0x080c, 0x6be6, 0x002e, 0x001e, 0x000e, 0x012e, 0xe000, 0x6000,
-	0xa086, 0x0002, 0x1110, 0x0804, 0x9286, 0x080c, 0x86ef, 0x0005,
-	0x0002, 0x9226, 0x9224, 0x9224, 0x9224, 0x9224, 0x9224, 0x9224,
-	0x9224, 0x9224, 0x9224, 0x9224, 0x9241, 0x9241, 0x9241, 0x9241,
-	0x9224, 0x9241, 0x9224, 0x9241, 0x080c, 0x151a, 0x080c, 0x7102,
-	0x00d6, 0x6110, 0x2168, 0x080c, 0x9d16, 0x0168, 0x6837, 0x0103,
-	0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ec, 0x6852, 0x080c,
-	0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5,
-	0x0005, 0x080c, 0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005,
-	0x0002, 0x925e, 0x925c, 0x925c, 0x925c, 0x925c, 0x925c, 0x925c,
-	0x925c, 0x925c, 0x925c, 0x925c, 0x9270, 0x9270, 0x9270, 0x9270,
-	0x925c, 0x927f, 0x925c, 0x9270, 0x080c, 0x151a, 0x080c, 0x7102,
-	0x2001, 0xb8b8, 0x2004, 0x603e, 0x6003, 0x0002, 0x080c, 0x71e5,
-	0x6010, 0xa088, 0x0013, 0x2104, 0xa085, 0x0400, 0x200a, 0x0005,
-	0x080c, 0x7102, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x2001, 0xb8b8,
-	0x2004, 0x603e, 0x6003, 0x000f, 0x080c, 0x71e5, 0x0005, 0x080c,
-	0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0040,
-	0x0002, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929e, 0x9386,
-	0x93b5, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c, 0x929c,
-	0x929c, 0x929c, 0x929c, 0x929c, 0x080c, 0x151a, 0x00e6, 0x00d6,
-	0x603f, 0x0000, 0x2071, 0xbc80, 0x7124, 0x610a, 0x2071, 0xbc8c,
-	0x6110, 0x2168, 0x7614, 0xa6b4, 0x0fff, 0x86ff, 0x0904, 0x934c,
-	0xa68c, 0x0c00, 0x0518, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe,
-	0x01c8, 0x684c, 0xd0ac, 0x01b0, 0x6020, 0xd0dc, 0x1198, 0x6850,
-	0xd0bc, 0x1180, 0x7318, 0x6814, 0xa306, 0x1904, 0x935f, 0x731c,
-	0x6810, 0xa31e, 0x0138, 0xd6d4, 0x0904, 0x935f, 0x6b14, 0xa305,
-	0x1904, 0x935f, 0x7318, 0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff,
-	0xa186, 0x0002, 0x0518, 0xa186, 0x0028, 0x1128, 0x080c, 0x9ef2,
-	0x684b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0x684b, 0x0015, 0x684c,
-	0xd0ac, 0x0170, 0x6914, 0x6a10, 0x2100, 0xa205, 0x0148, 0x7018,
-	0xa106, 0x1118, 0x701c, 0xa206, 0x0118, 0x6962, 0x6a5e, 0xc6dc,
-	0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000,
-	0x6837, 0x0103, 0x6e46, 0xa01e, 0xd6c4, 0x01f0, 0xa686, 0x0100,
-	0x1140, 0x2001, 0xbc99, 0x2004, 0xa005, 0x1118, 0xc6c4, 0x0804,
-	0x92ad, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009,
-	0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, 0xad90,
-	0x0019, 0x080c, 0x99c9, 0x003e, 0xd6cc, 0x0904, 0x9375, 0x7124,
-	0x695a, 0x81ff, 0x0904, 0x9375, 0xa192, 0x0021, 0x1260, 0x2071,
-	0xbc98, 0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x99c9,
-	0x080c, 0xa1f3, 0x04d0, 0x6838, 0xd0fc, 0x0120, 0x2009, 0x0020,
-	0x695a, 0x0c68, 0x00f6, 0x2d78, 0x080c, 0x996e, 0x00fe, 0x080c,
-	0xa1f3, 0x080c, 0x99b9, 0x0458, 0x00f6, 0x2c78, 0x080c, 0x5377,
-	0x00fe, 0x0190, 0x684c, 0xd0ac, 0x0178, 0x6020, 0xd0dc, 0x1160,
-	0x6850, 0xd0bc, 0x1148, 0x6810, 0x6914, 0xa105, 0x0128, 0x080c,
-	0x9ff1, 0x00de, 0x00ee, 0x0408, 0x684b, 0x0000, 0x6837, 0x0103,
-	0x6e46, 0x080c, 0x9523, 0x1148, 0x684c, 0xd0ac, 0x0130, 0x6810,
-	0x6914, 0xa115, 0x0110, 0x080c, 0x953f, 0x080c, 0x547a, 0x6218,
-	0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x080c, 0x9fbf,
-	0x00de, 0x00ee, 0x1110, 0x080c, 0x86a4, 0x0005, 0x00f6, 0x6003,
-	0x0003, 0x2079, 0xbc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x6010,
-	0x2078, 0x784c, 0xd0ac, 0x0138, 0x6003, 0x0002, 0x00fe, 0x0005,
-	0x2130, 0x2228, 0x0058, 0x2400, 0x797c, 0xa10a, 0x2300, 0x7a80,
-	0xa213, 0x2600, 0xa102, 0x2500, 0xa203, 0x0e90, 0x7c12, 0x7b16,
-	0x7e0a, 0x7d0e, 0x00fe, 0x603f, 0x0000, 0x2c10, 0x080c, 0x1fc5,
-	0x080c, 0x6d62, 0x080c, 0x72a2, 0x0005, 0x2001, 0xb8b8, 0x2004,
-	0x603e, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x080c, 0x1863, 0x0005, 0xa182, 0x0040, 0x0002, 0x93da,
-	0x93da, 0x93da, 0x93da, 0x93da, 0x93dc, 0x946f, 0x93da, 0x93da,
-	0x9485, 0x94eb, 0x93da, 0x93da, 0x93da, 0x93da, 0x9509, 0x93da,
-	0x93da, 0x93da, 0x080c, 0x151a, 0x0076, 0x00f6, 0x00e6, 0x00d6,
-	0x2071, 0xbc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff, 0x7e46,
-	0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff, 0x0110,
-	0x8211, 0x6a3e, 0x86ff, 0x0904, 0x946a, 0xa694, 0xff00, 0xa284,
-	0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284, 0x0300,
-	0x0904, 0x946a, 0x080c, 0x15fd, 0x090c, 0x151a, 0x2d00, 0x784a,
-	0x7f4c, 0xc7cd, 0x7f4e, 0x6837, 0x0103, 0x7838, 0x683a, 0x783c,
-	0x683e, 0x7840, 0x6842, 0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318,
-	0x6b62, 0x731c, 0x6b5e, 0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180,
-	0xa186, 0x0028, 0x1118, 0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118,
-	0x684b, 0x0015, 0x0038, 0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010,
-	0x684b, 0x0000, 0x6f4e, 0x7850, 0x6852, 0x7854, 0x6856, 0xa01e,
-	0xd6c4, 0x0198, 0x7328, 0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a,
-	0x0009, 0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0xbc98,
-	0xad90, 0x0019, 0x080c, 0x99c9, 0x003e, 0xd6cc, 0x01d8, 0x7124,
-	0x695a, 0x81ff, 0x01b8, 0xa192, 0x0021, 0x1250, 0x2071, 0xbc98,
-	0x831c, 0x2300, 0xae18, 0xad90, 0x001d, 0x080c, 0x99c9, 0x0050,
-	0x7838, 0xd0fc, 0x0120, 0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78,
-	0x080c, 0x996e, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005, 0x00f6,
-	0x6003, 0x0003, 0x2079, 0xbc8c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08,
-	0x6010, 0x2078, 0x7c12, 0x7b16, 0x7e0a, 0x7d0e, 0x00fe, 0x2c10,
-	0x080c, 0x1fc5, 0x080c, 0x7dd9, 0x0005, 0x00d6, 0x00f6, 0x2c78,
-	0x080c, 0x5377, 0x00fe, 0x0120, 0x2001, 0xb8b8, 0x2004, 0x603e,
-	0x6003, 0x0002, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6110, 0x2168,
-	0x694c, 0xd1e4, 0x0904, 0x94e9, 0xd1cc, 0x0540, 0x6948, 0x6838,
-	0xd0fc, 0x01e8, 0x0016, 0x684c, 0x0006, 0x6850, 0x0006, 0xad90,
-	0x000d, 0xa198, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304,
-	0x2012, 0x8318, 0x8210, 0x1f04, 0x94af, 0x015e, 0x000e, 0x6852,
-	0x000e, 0x684e, 0x001e, 0x2168, 0x080c, 0x1624, 0x0428, 0x0016,
-	0x080c, 0x1624, 0x00de, 0x080c, 0x99b9, 0x00f0, 0x6837, 0x0103,
-	0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x0180, 0xa086, 0x0028,
-	0x1118, 0x684b, 0x001c, 0x0070, 0xd1dc, 0x0118, 0x684b, 0x0015,
-	0x0048, 0xd1d4, 0x0118, 0x684b, 0x0007, 0x0020, 0x684b, 0x0000,
-	0x080c, 0x9523, 0x080c, 0x547a, 0x080c, 0x9fbf, 0x1110, 0x080c,
-	0x86a4, 0x00de, 0x0005, 0x2019, 0x0001, 0x080c, 0x806b, 0x6003,
-	0x0002, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0140, 0x6808,
-	0x612c, 0xa10a, 0x612e, 0x680c, 0x6128, 0xa10b, 0x612a, 0x00de,
-	0x2001, 0xb8b8, 0x2004, 0x603e, 0x080c, 0x7198, 0x080c, 0x72a2,
-	0x0005, 0x080c, 0x7198, 0x080c, 0x2cd1, 0x00d6, 0x6110, 0x2168,
-	0x080c, 0x9d16, 0x0150, 0x6837, 0x0103, 0x684b, 0x0029, 0x6847,
-	0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4,
-	0x080c, 0x72a2, 0x0005, 0x684c, 0xd0b4, 0x01c0, 0x602c, 0x697c,
-	0xa112, 0x6028, 0x6980, 0xa10b, 0x2100, 0xa205, 0x0168, 0x684b,
-	0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8212, 0x8210, 0x810a,
-	0xa189, 0x0000, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x0005, 0x684b,
-	0x0015, 0xd1fc, 0x0138, 0x684b, 0x0007, 0x8002, 0x8000, 0x810a,
-	0xa189, 0x0000, 0x6962, 0x685e, 0x0005, 0xa182, 0x0040, 0x0002,
-	0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9565, 0x9563, 0x9620,
-	0x962c, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563, 0x9563,
-	0x9563, 0x9563, 0x9563, 0x080c, 0x151a, 0x0076, 0x00f6, 0x00e6,
-	0x00d6, 0x2071, 0xbc8c, 0x6110, 0x2178, 0x7614, 0xa6b4, 0x0fff,
-	0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x0150, 0xa684, 0x00ff,
-	0x1138, 0x6020, 0xd0f4, 0x0120, 0x080c, 0x9ff1, 0x0804, 0x961b,
-	0x7e46, 0x7f4c, 0xc7e5, 0x7f4e, 0x6218, 0x2268, 0x6a3c, 0x82ff,
-	0x0110, 0x8211, 0x6a3e, 0x86ff, 0x0904, 0x9611, 0xa694, 0xff00,
-	0xa284, 0x0c00, 0x0120, 0x7018, 0x7862, 0x701c, 0x785e, 0xa284,
-	0x0300, 0x0904, 0x960f, 0xa686, 0x0100, 0x1140, 0x2001, 0xbc99,
-	0x2004, 0xa005, 0x1118, 0xc6c4, 0x7e46, 0x0c28, 0x080c, 0x15fd,
-	0x090c, 0x151a, 0x2d00, 0x784a, 0x7f4c, 0xa7bd, 0x0200, 0x7f4e,
-	0x6837, 0x0103, 0x7838, 0x683a, 0x783c, 0x683e, 0x7840, 0x6842,
-	0x6e46, 0xa68c, 0x0c00, 0x0120, 0x7318, 0x6b62, 0x731c, 0x6b5e,
-	0xa68c, 0x00ff, 0xa186, 0x0002, 0x0180, 0xa186, 0x0028, 0x1118,
-	0x684b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0x684b, 0x0015, 0x0038,
-	0xd6d4, 0x0118, 0x684b, 0x0007, 0x0010, 0x684b, 0x0000, 0x6f4e,
-	0x7850, 0x6852, 0x7854, 0x6856, 0xa01e, 0xd6c4, 0x0198, 0x7328,
-	0x732c, 0x6b56, 0x83ff, 0x0170, 0xa38a, 0x0009, 0x0210, 0x2019,
-	0x0008, 0x0036, 0x2308, 0x2019, 0xbc98, 0xad90, 0x0019, 0x080c,
-	0x99c9, 0x003e, 0xd6cc, 0x01d8, 0x7124, 0x695a, 0x81ff, 0x01b8,
-	0xa192, 0x0021, 0x1250, 0x2071, 0xbc98, 0x831c, 0x2300, 0xae18,
-	0xad90, 0x001d, 0x080c, 0x99c9, 0x0050, 0x7838, 0xd0fc, 0x0120,
-	0x2009, 0x0020, 0x695a, 0x0c78, 0x2d78, 0x080c, 0x996e, 0xd6dc,
-	0x1110, 0xa006, 0x0030, 0x2001, 0x0001, 0x2071, 0xbc8c, 0x7218,
-	0x731c, 0x080c, 0x18b6, 0x00de, 0x00ee, 0x00fe, 0x007e, 0x0005,
-	0x2001, 0xb8b8, 0x2004, 0x603e, 0x20e1, 0x0005, 0x3d18, 0x3e20,
-	0x2c10, 0x080c, 0x1863, 0x0005, 0x2001, 0xb8b8, 0x2004, 0x603e,
-	0x00d6, 0x6003, 0x0002, 0x6110, 0x2168, 0x694c, 0xd1e4, 0x0904,
-	0x9737, 0x603f, 0x0000, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe,
-	0x0560, 0x6814, 0x6910, 0xa115, 0x0540, 0x6a60, 0xa206, 0x1118,
-	0x685c, 0xa106, 0x0510, 0x684c, 0xc0e4, 0x684e, 0x6847, 0x0000,
-	0x6863, 0x0000, 0x685f, 0x0000, 0x6020, 0xd0f4, 0x1158, 0x697c,
-	0x6810, 0xa102, 0x603a, 0x6980, 0x6814, 0xa103, 0x6036, 0x6020,
-	0xc0f5, 0x6022, 0x00d6, 0x6018, 0x2068, 0x683c, 0x8000, 0x683e,
-	0x00de, 0x080c, 0x9ff1, 0x0804, 0x9737, 0x694c, 0xd1cc, 0x0904,
-	0x9707, 0x6948, 0x6838, 0xd0fc, 0x0904, 0x96ca, 0x0016, 0x684c,
-	0x0006, 0x6850, 0x0006, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff,
-	0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c,
-	0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b,
-	0x0015, 0x080c, 0xa17b, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080,
-	0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c,
-	0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f,
-	0x6848, 0x784a, 0x6860, 0x7862, 0x685c, 0x785e, 0xad90, 0x000d,
-	0xaf98, 0x000d, 0x2009, 0x0020, 0x0156, 0x21a8, 0x2304, 0x2012,
-	0x8318, 0x8210, 0x1f04, 0x96b6, 0x015e, 0x00fe, 0x000e, 0x6852,
-	0x000e, 0x684e, 0x080c, 0xa1f3, 0x001e, 0x2168, 0x080c, 0x1624,
-	0x0804, 0x9732, 0x0016, 0x00f6, 0x2178, 0x7944, 0xa184, 0x00ff,
-	0xa0b6, 0x0002, 0x01e0, 0xa086, 0x0028, 0x1128, 0x684b, 0x001c,
-	0x784b, 0x001c, 0x00e8, 0xd1dc, 0x0158, 0x684b, 0x0015, 0x784b,
-	0x0015, 0x080c, 0xa17b, 0x0118, 0x7944, 0xc1dc, 0x7946, 0x0080,
-	0xd1d4, 0x0128, 0x684b, 0x0007, 0x784b, 0x0007, 0x0048, 0x684c,
-	0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f,
-	0x6860, 0x7862, 0x685c, 0x785e, 0x684c, 0x784e, 0x00fe, 0x080c,
-	0x1624, 0x00de, 0x080c, 0xa1f3, 0x080c, 0x99b9, 0x0458, 0x6837,
-	0x0103, 0x6944, 0xa184, 0x00ff, 0xa0b6, 0x0002, 0x01b0, 0xa086,
-	0x0028, 0x1118, 0x684b, 0x001c, 0x00d8, 0xd1dc, 0x0148, 0x684b,
-	0x0015, 0x080c, 0xa17b, 0x0118, 0x6944, 0xc1dc, 0x6946, 0x0080,
-	0xd1d4, 0x0118, 0x684b, 0x0007, 0x0058, 0x684b, 0x0000, 0x684c,
-	0xd0ac, 0x0130, 0x6810, 0x6914, 0xa115, 0x0110, 0x080c, 0x953f,
-	0x080c, 0x547a, 0x080c, 0x9fbf, 0x1110, 0x080c, 0x86a4, 0x00de,
-	0x0005, 0x080c, 0x7102, 0x0010, 0x080c, 0x7198, 0x080c, 0x9d16,
-	0x01c0, 0x00d6, 0x6110, 0x2168, 0x6837, 0x0103, 0x2009, 0xb60c,
-	0x210c, 0xd18c, 0x11c0, 0xd184, 0x1198, 0x6108, 0x694a, 0xa18e,
-	0x0029, 0x1110, 0x080c, 0xb43c, 0x6847, 0x0000, 0x080c, 0x547a,
-	0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x080c, 0x72a2, 0x0005,
-	0x684b, 0x0004, 0x0c88, 0x684b, 0x0004, 0x0c70, 0xa182, 0x0040,
-	0x0002, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977e, 0x977c,
-	0x9781, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c, 0x977c,
-	0x977c, 0x977c, 0x977c, 0x977c, 0x080c, 0x151a, 0x080c, 0x86a4,
-	0x0005, 0x0006, 0x0026, 0xa016, 0x080c, 0x1863, 0x002e, 0x000e,
-	0x0005, 0xa182, 0x0085, 0x0002, 0x9795, 0x9793, 0x9793, 0x97a1,
-	0x9793, 0x9793, 0x9793, 0x080c, 0x151a, 0x6003, 0x0001, 0x6106,
-	0x080c, 0x6cff, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e,
-	0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0xbc80, 0x7224,
-	0x6212, 0x7220, 0x080c, 0x9d06, 0x01a0, 0x2268, 0x6800, 0xa086,
-	0x0000, 0x0178, 0x6018, 0x6d18, 0xa52e, 0x1158, 0x00c6, 0x2d60,
-	0x080c, 0x99d9, 0x00ce, 0x0128, 0x6803, 0x0002, 0x6007, 0x0086,
-	0x0010, 0x6007, 0x0087, 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c,
-	0x71e5, 0x00f6, 0x2278, 0x080c, 0x5377, 0x00fe, 0x0150, 0x6820,
-	0xd0ec, 0x0138, 0x00c6, 0x2260, 0x603f, 0x0000, 0x080c, 0x9ff1,
-	0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0xa186, 0x0013,
-	0x1160, 0x6004, 0xa08a, 0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c,
-	0x1a0c, 0x151a, 0xa082, 0x0085, 0x0072, 0xa186, 0x0027, 0x0120,
-	0xa186, 0x0014, 0x190c, 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9,
-	0x080c, 0x71e5, 0x0005, 0x9802, 0x9804, 0x9804, 0x9802, 0x9802,
-	0x9802, 0x9802, 0x080c, 0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9,
-	0x080c, 0x71e5, 0x0005, 0xa186, 0x0013, 0x1128, 0x6004, 0xa082,
-	0x0085, 0x2008, 0x04a8, 0xa186, 0x0027, 0x11e8, 0x080c, 0x7102,
-	0x080c, 0x2cd1, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0150,
-	0x6837, 0x0103, 0x6847, 0x0000, 0x684b, 0x0029, 0x080c, 0x547a,
-	0x080c, 0x9ecd, 0x00de, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005,
-	0x080c, 0x86ef, 0x0ce0, 0xa186, 0x0014, 0x1dd0, 0x080c, 0x7102,
-	0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0d60, 0x6837, 0x0103,
-	0x6847, 0x0000, 0x684b, 0x0006, 0x6850, 0xc0ec, 0x6852, 0x08f0,
-	0x0002, 0x9852, 0x9850, 0x9850, 0x9850, 0x9850, 0x9850, 0x986a,
-	0x080c, 0x151a, 0x080c, 0x7102, 0x6030, 0xa08c, 0xff00, 0x810f,
-	0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb8b6,
-	0x0010, 0x2001, 0xb8b7, 0x2004, 0x6016, 0x6003, 0x000c, 0x080c,
-	0x71e5, 0x0005, 0x080c, 0x7102, 0x6030, 0xa08c, 0xff00, 0x810f,
-	0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x2001, 0xb8b6,
-	0x0010, 0x2001, 0xb8b7, 0x2004, 0x6016, 0x6003, 0x000e, 0x080c,
-	0x71e5, 0x0005, 0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208,
-	0x001a, 0x080c, 0x86ef, 0x0005, 0x9893, 0x9893, 0x9893, 0x9893,
-	0x9895, 0x98ee, 0x9893, 0x080c, 0x151a, 0x00d6, 0x00f6, 0x2c78,
-	0x080c, 0x5377, 0x00fe, 0x0168, 0x6030, 0xa08c, 0xff00, 0x810f,
-	0xa186, 0x0039, 0x0118, 0xa186, 0x0035, 0x1118, 0x00de, 0x0804,
-	0x9901, 0x080c, 0x9d16, 0x1118, 0x080c, 0x9ecd, 0x00f0, 0x6010,
-	0x2068, 0x684c, 0xd0e4, 0x1110, 0x080c, 0x9ecd, 0x6837, 0x0103,
-	0x6850, 0xd0b4, 0x0128, 0x684b, 0x0006, 0xc0ec, 0x6852, 0x0048,
-	0xd0bc, 0x0118, 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c,
-	0x9f8e, 0x6847, 0x0000, 0x080c, 0x547a, 0x2c68, 0x080c, 0x864e,
-	0x01c0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b, 0xffff, 0x2009,
-	0xbc8e, 0x210c, 0x6136, 0x2009, 0xbc8f, 0x210c, 0x613a, 0x6918,
-	0x611a, 0x080c, 0xa0e3, 0x6950, 0x6152, 0x601f, 0x0001, 0x080c,
-	0x6cff, 0x2d60, 0x080c, 0x86a4, 0x00de, 0x0005, 0x00f6, 0x2c78,
-	0x080c, 0x5377, 0x00fe, 0x0598, 0x6030, 0xa08c, 0xff00, 0x810f,
-	0xa186, 0x0035, 0x0130, 0xa186, 0x001e, 0x0118, 0xa186, 0x0039,
-	0x1530, 0x00d6, 0x2c68, 0x080c, 0xa1c6, 0x1904, 0x9946, 0x080c,
-	0x864e, 0x01d8, 0x6106, 0x6003, 0x0001, 0x601f, 0x0001, 0x6918,
-	0x611a, 0x6928, 0x612a, 0x692c, 0x612e, 0x6930, 0xa18c, 0x00ff,
-	0x6132, 0x6934, 0x6136, 0x6938, 0x613a, 0x6950, 0x6152, 0x080c,
-	0xa0e3, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x2d60, 0x00f8, 0x00d6,
-	0x6010, 0x2068, 0x080c, 0x9d16, 0x01c8, 0x6837, 0x0103, 0x6850,
-	0xd0b4, 0x0128, 0xc0ec, 0x6852, 0x684b, 0x0006, 0x0048, 0xd0bc,
-	0x0118, 0x684b, 0x0002, 0x0020, 0x684b, 0x0005, 0x080c, 0x9f8e,
-	0x6847, 0x0000, 0x080c, 0x547a, 0x080c, 0x9ecd, 0x00de, 0x080c,
-	0x86a4, 0x0005, 0x0016, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16,
-	0x0140, 0x6837, 0x0103, 0x684b, 0x0028, 0x6847, 0x0000, 0x080c,
-	0x547a, 0x00de, 0x001e, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014,
-	0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x86ef, 0x0030, 0x080c,
-	0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0x0056, 0x0066,
-	0x00d6, 0x00f6, 0x2029, 0x0001, 0xa182, 0x0101, 0x1208, 0x0010,
-	0x2009, 0x0100, 0x2130, 0x2069, 0xbc98, 0x831c, 0x2300, 0xad18,
-	0x2009, 0x0020, 0xaf90, 0x001d, 0x080c, 0x99c9, 0xa6b2, 0x0020,
-	0x7804, 0xa06d, 0x0110, 0x080c, 0x1624, 0x080c, 0x15fd, 0x0500,
-	0x8528, 0x6837, 0x0110, 0x683b, 0x0000, 0x2d20, 0x7c06, 0xa68a,
-	0x003d, 0x1228, 0x2608, 0xad90, 0x000f, 0x0459, 0x0088, 0xa6b2,
-	0x003c, 0x2009, 0x003c, 0x2d78, 0xad90, 0x000f, 0x0411, 0x0c28,
-	0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0xa5ac, 0x0000, 0x0028,
-	0x00fe, 0x852f, 0xa5ad, 0x0003, 0x7d36, 0x00de, 0x006e, 0x005e,
-	0x0005, 0x00f6, 0x8dff, 0x0158, 0x6804, 0xa07d, 0x0130, 0x6807,
-	0x0000, 0x080c, 0x547a, 0x2f68, 0x0cb8, 0x080c, 0x547a, 0x00fe,
-	0x0005, 0x0156, 0xa184, 0x0001, 0x0108, 0x8108, 0x810c, 0x21a8,
-	0x2304, 0x8007, 0x2012, 0x8318, 0x8210, 0x1f04, 0x99d0, 0x015e,
-	0x0005, 0x0066, 0x0126, 0x2091, 0x8000, 0x2031, 0x0001, 0x601c,
-	0xa084, 0x000f, 0x0083, 0x012e, 0x006e, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x0066, 0x2031, 0x0000, 0x601c, 0xa084, 0x000f, 0x001b,
-	0x006e, 0x012e, 0x0005, 0x9a10, 0x9a10, 0x9a0b, 0x9a32, 0x99fe,
-	0x9a0b, 0x9a32, 0x9a0b, 0x9a0b, 0x99fe, 0x9a0b, 0x080c, 0x151a,
-	0x0036, 0x2019, 0x0010, 0x080c, 0xad9c, 0x601f, 0x0006, 0x6003,
-	0x0007, 0x003e, 0x0005, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005,
-	0x00d6, 0x86ff, 0x11d8, 0x6010, 0x2068, 0x080c, 0x9d16, 0x01c0,
-	0x6834, 0xa086, 0x0139, 0x1128, 0x684b, 0x0005, 0x6853, 0x0000,
-	0x0028, 0xa00e, 0x2001, 0x0005, 0x080c, 0x554d, 0x080c, 0x9f8e,
-	0x080c, 0x547a, 0x080c, 0x86a4, 0xa085, 0x0001, 0x00de, 0x0005,
-	0xa006, 0x0ce0, 0x6000, 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b,
-	0x0005, 0x9a49, 0x9a6a, 0x9a4b, 0x9a89, 0x9a67, 0x9a49, 0x9a0b,
-	0x9a10, 0x9a10, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b, 0x9a0b,
-	0x9a0b, 0x080c, 0x151a, 0x86ff, 0x11b8, 0x601c, 0xa086, 0x0006,
-	0x0198, 0x00d6, 0x6010, 0x2068, 0x080c, 0x9d16, 0x0110, 0x080c,
-	0x9f8e, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002,
-	0x080c, 0x6cff, 0x080c, 0x71e5, 0xa085, 0x0001, 0x0005, 0x080c,
-	0x1952, 0x0c08, 0x00e6, 0x2071, 0xb8e1, 0x7024, 0xac06, 0x1110,
-	0x080c, 0x7fe0, 0x601c, 0xa084, 0x000f, 0xa086, 0x0006, 0x1150,
-	0x0086, 0x0096, 0x2049, 0x0001, 0x2c40, 0x080c, 0x81b7, 0x009e,
-	0x008e, 0x0010, 0x080c, 0x7ed1, 0x00ee, 0x1928, 0x080c, 0x9a0b,
-	0x0005, 0x0036, 0x00e6, 0x2071, 0xb8e1, 0x703c, 0xac06, 0x1140,
-	0x2019, 0x0000, 0x080c, 0x806b, 0x00ee, 0x003e, 0x0804, 0x9a4b,
-	0x080c, 0x82e4, 0x00ee, 0x003e, 0x1904, 0x9a4b, 0x080c, 0x9a0b,
-	0x0005, 0x00c6, 0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005,
-	0x9aba, 0x9b27, 0x9c75, 0x9ac5, 0x9ed9, 0x9aba, 0xad8e, 0xa20a,
-	0x9b27, 0x9ab3, 0x9ce0, 0x080c, 0x151a, 0x080c, 0x9f14, 0x1110,
-	0x080c, 0x8ca5, 0x0005, 0x080c, 0x7102, 0x080c, 0x71e5, 0x080c,
-	0x86a4, 0x0005, 0x6017, 0x0001, 0x0005, 0x080c, 0x9d16, 0x0120,
-	0x6010, 0xa080, 0x0019, 0x2c02, 0x6000, 0xa08a, 0x0010, 0x1a0c,
-	0x151a, 0x000b, 0x0005, 0x9ae3, 0x9ae5, 0x9b05, 0x9b17, 0x9b24,
-	0x9ae3, 0x9aba, 0x9aba, 0x9aba, 0x9b17, 0x9b17, 0x9ae3, 0x9ae3,
-	0x9ae3, 0x9ae3, 0x9b21, 0x080c, 0x151a, 0x00e6, 0x6010, 0x2070,
-	0x7050, 0xc0b5, 0x7052, 0x2071, 0xb8e1, 0x7024, 0xac06, 0x0190,
-	0x080c, 0x7ed1, 0x6007, 0x0085, 0x6003, 0x000b, 0x601f, 0x0002,
-	0x2001, 0xb8b7, 0x2004, 0x6016, 0x080c, 0x6cff, 0x080c, 0x71e5,
-	0x00ee, 0x0005, 0x6017, 0x0001, 0x0cd8, 0x00d6, 0x6010, 0x2068,
-	0x6850, 0xc0b5, 0x6852, 0x00de, 0x6007, 0x0085, 0x6003, 0x000b,
-	0x601f, 0x0002, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0005, 0x00d6,
-	0x6017, 0x0001, 0x6010, 0x2068, 0x6850, 0xc0b5, 0x6852, 0x00de,
-	0x0005, 0x080c, 0x86a4, 0x0005, 0x080c, 0x1952, 0x08f0, 0x6000,
-	0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9b3e, 0x9ac2,
-	0x9b40, 0x9b3e, 0x9b40, 0x9b40, 0x9abb, 0x9b3e, 0x9ab5, 0x9ab5,
-	0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x9b3e, 0x080c, 0x151a,
-	0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa08a,
-	0x000c, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9b59, 0x9c1b, 0x9b5b,
-	0x9b99, 0x9b5b, 0x9b99, 0x9b5b, 0x9b69, 0x9b59, 0x9b99, 0x9b59,
-	0x9b85, 0x080c, 0x151a, 0x6004, 0xa08e, 0x0016, 0x05a8, 0xa08e,
-	0x0004, 0x0590, 0xa08e, 0x0002, 0x0578, 0xa08e, 0x004b, 0x0904,
-	0x9c17, 0x6004, 0x080c, 0x9f14, 0x0904, 0x9c34, 0xa08e, 0x0021,
-	0x0904, 0x9c38, 0xa08e, 0x0022, 0x0904, 0x9c34, 0xa08e, 0x003d,
-	0x0904, 0x9c38, 0xa08e, 0x0039, 0x0904, 0x9c3c, 0xa08e, 0x0035,
-	0x0904, 0x9c3c, 0xa08e, 0x001e, 0x0188, 0xa08e, 0x0001, 0x1150,
-	0x00d6, 0x6018, 0x2068, 0x6804, 0xa084, 0x00ff, 0x00de, 0xa086,
-	0x0006, 0x0110, 0x080c, 0x2cd1, 0x080c, 0x8ca5, 0x080c, 0x9ed9,
-	0x0005, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016, 0x0904, 0x9c08,
-	0xa186, 0x0002, 0x15d8, 0x2001, 0xb635, 0x2004, 0xd08c, 0x1198,
-	0x080c, 0x5b41, 0x1180, 0x2001, 0xb89f, 0x2003, 0x0001, 0x2001,
-	0xb600, 0x2003, 0x0001, 0xa085, 0x0001, 0x080c, 0x5b85, 0x080c,
-	0x5a79, 0x0804, 0x9c5e, 0x6018, 0x2068, 0x2001, 0xb635, 0x2004,
-	0xd0ac, 0x1904, 0x9c5e, 0x68a0, 0xd0bc, 0x1904, 0x9c5e, 0x6840,
-	0xa084, 0x00ff, 0xa005, 0x0190, 0x8001, 0x6842, 0x6013, 0x0000,
-	0x601f, 0x0007, 0x6017, 0x0398, 0x603f, 0x0000, 0x080c, 0x864e,
-	0x0128, 0x2d00, 0x601a, 0x601f, 0x0001, 0x0450, 0x00de, 0x00ce,
-	0x6004, 0xa08e, 0x0002, 0x11a8, 0x6018, 0xa080, 0x0028, 0x2004,
-	0xa086, 0x007e, 0x1170, 0x2009, 0xb635, 0x2104, 0xc085, 0x200a,
-	0x00e6, 0x2071, 0xb600, 0x080c, 0x4c28, 0x00ee, 0x080c, 0x8ca5,
-	0x0020, 0x080c, 0x8ca5, 0x080c, 0x2cd1, 0x00e6, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x2cf7, 0x012e, 0x00ee, 0x080c, 0x9ed9, 0x0005,
-	0x2001, 0x0002, 0x080c, 0x4f6f, 0x6003, 0x0001, 0x6007, 0x0002,
-	0x080c, 0x6d45, 0x080c, 0x71e5, 0x00de, 0x00ce, 0x0c80, 0x080c,
-	0x2cf7, 0x0804, 0x9b94, 0x00c6, 0x00d6, 0x6104, 0xa186, 0x0016,
-	0x0d38, 0x6018, 0x2068, 0x6840, 0xa084, 0x00ff, 0xa005, 0x0904,
-	0x9bde, 0x8001, 0x6842, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c,
-	0x71e5, 0x00de, 0x00ce, 0x0898, 0x080c, 0x8ca5, 0x0804, 0x9b96,
-	0x080c, 0x8cd3, 0x0804, 0x9b96, 0x00d6, 0x2c68, 0x6104, 0x080c,
-	0xa1c6, 0x00de, 0x0118, 0x080c, 0x86a4, 0x00b8, 0x6004, 0x8007,
-	0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085, 0x6003,
-	0x000b, 0x601f, 0x0002, 0x6038, 0x600a, 0x2001, 0xb8b7, 0x2004,
-	0x6016, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0005, 0x00de, 0x00ce,
-	0x080c, 0x8ca5, 0x080c, 0x2cd1, 0x00e6, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x2cf7, 0x6013, 0x0000, 0x601f, 0x0007, 0x6017, 0x0398,
-	0x603f, 0x0000, 0x012e, 0x00ee, 0x0005, 0x6000, 0xa08a, 0x0010,
-	0x1a0c, 0x151a, 0x000b, 0x0005, 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c,
-	0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, 0x9c8c, 0x9aba, 0x9c8c, 0x9ac2,
-	0x9c8e, 0x9ac2, 0x9c9b, 0x9c8c, 0x080c, 0x151a, 0x6004, 0xa086,
-	0x008b, 0x0148, 0x6007, 0x008b, 0x6003, 0x000d, 0x080c, 0x6cff,
-	0x080c, 0x71e5, 0x0005, 0x080c, 0x9ecd, 0x080c, 0x9d16, 0x0580,
-	0x080c, 0x2cd1, 0x00d6, 0x080c, 0x9d16, 0x0168, 0x6010, 0x2068,
-	0x6837, 0x0103, 0x684b, 0x0006, 0x6847, 0x0000, 0x6850, 0xc0ed,
-	0x6852, 0x080c, 0x547a, 0x2c68, 0x080c, 0x864e, 0x0150, 0x6818,
-	0x601a, 0x080c, 0xa0e3, 0x00c6, 0x2d60, 0x080c, 0x9ed9, 0x00ce,
-	0x0008, 0x2d60, 0x00de, 0x6013, 0x0000, 0x601f, 0x0001, 0x6007,
-	0x0001, 0x6003, 0x0001, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x0078,
-	0x6030, 0xa08c, 0xff00, 0x810f, 0xa186, 0x0039, 0x0118, 0xa186,
-	0x0035, 0x1118, 0x080c, 0x2cd1, 0x08b0, 0x080c, 0x9ed9, 0x0005,
-	0x6000, 0xa08a, 0x0010, 0x1a0c, 0x151a, 0x000b, 0x0005, 0x9cf7,
-	0x9cf7, 0x9cf7, 0x9cf9, 0x9cf9, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7,
-	0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x9cf7, 0x080c,
-	0x151a, 0x080c, 0x82e4, 0x190c, 0x151a, 0x6110, 0x2168, 0x684b,
-	0x0006, 0x080c, 0x547a, 0x080c, 0x86a4, 0x0005, 0xa284, 0x0007,
-	0x1158, 0xa282, 0xbe00, 0x0240, 0x2001, 0xb617, 0x2004, 0xa202,
-	0x1218, 0xa085, 0x0001, 0x0005, 0xa006, 0x0ce8, 0x0026, 0x6210,
-	0xa294, 0xf000, 0x002e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006,
-	0x0126, 0x2091, 0x8000, 0x2061, 0xbe00, 0x2071, 0xb600, 0x7348,
-	0x7068, 0xa302, 0x12a8, 0x601c, 0xa206, 0x1160, 0x080c, 0xa06e,
-	0x0148, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x00c6, 0x080c,
-	0x86a4, 0x00ce, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0c38,
-	0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6,
-	0x0016, 0xa188, 0xb735, 0x210c, 0x81ff, 0x0128, 0x2061, 0xb9f5,
-	0x611a, 0x080c, 0x2cd1, 0xa006, 0x0010, 0xa085, 0x0001, 0x001e,
-	0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0056, 0x0126, 0x2091, 0x8000,
-	0x00c6, 0x080c, 0x864e, 0x005e, 0x0180, 0x6612, 0x651a, 0x080c,
-	0xa0e3, 0x601f, 0x0003, 0x2009, 0x004b, 0x080c, 0x86d3, 0xa085,
-	0x0001, 0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00c6,
-	0x0056, 0x0126, 0x2091, 0x8000, 0x62a0, 0x00c6, 0x080c, 0x9f92,
-	0x005e, 0x0550, 0x6013, 0x0000, 0x651a, 0x080c, 0xa0e3, 0x601f,
-	0x0003, 0x0016, 0x00c6, 0x2560, 0x080c, 0x521c, 0x00ce, 0x080c,
-	0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c,
-	0xaf3e, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c, 0x86a4, 0xa085,
-	0x0001, 0x0030, 0x2009, 0x004c, 0x080c, 0x86d3, 0xa085, 0x0001,
-	0x012e, 0x005e, 0x00ce, 0x0005, 0xa006, 0x0cd0, 0x00f6, 0x00c6,
-	0x0046, 0x00c6, 0x080c, 0x864e, 0x2c78, 0x00ce, 0x0180, 0x7e12,
-	0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0005, 0x080c, 0x9e0c,
-	0x2f60, 0x2009, 0x004d, 0x080c, 0x86d3, 0xa085, 0x0001, 0x004e,
-	0x00ce, 0x00fe, 0x0005, 0x00f6, 0x00c6, 0x0046, 0x00c6, 0x080c,
-	0x864e, 0x2c78, 0x00ce, 0x0178, 0x7e12, 0x2c00, 0x781a, 0x781f,
-	0x0003, 0x2021, 0x0005, 0x0481, 0x2f60, 0x2009, 0x004e, 0x080c,
-	0x86d3, 0xa085, 0x0001, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6,
-	0x00c6, 0x0046, 0x00c6, 0x080c, 0x864e, 0x2c78, 0x00ce, 0x01c0,
-	0x7e12, 0x2c00, 0x781a, 0x781f, 0x0003, 0x2021, 0x0004, 0x00a1,
-	0x2001, 0xb8a0, 0x2004, 0xd0fc, 0x0120, 0x2f60, 0x080c, 0x86a4,
-	0x0028, 0x2f60, 0x2009, 0x0052, 0x080c, 0x86d3, 0xa085, 0x0001,
-	0x004e, 0x00ce, 0x00fe, 0x0005, 0x0096, 0x0076, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x51be, 0x0118, 0x2001, 0x9e11, 0x0028, 0x080c,
-	0x518e, 0x0158, 0x2001, 0x9e17, 0x0006, 0xa00e, 0x2400, 0x080c,
-	0x554d, 0x080c, 0x547a, 0x000e, 0x0807, 0x2418, 0x080c, 0x70a1,
-	0x62a0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c,
-	0x6e80, 0x008e, 0x080c, 0x6d74, 0x2f08, 0x2648, 0x080c, 0xaf3e,
-	0x613c, 0x81ff, 0x090c, 0x6f35, 0x080c, 0x71e5, 0x012e, 0x007e,
-	0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c,
-	0x864e, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f,
-	0x0001, 0x2d00, 0x6012, 0x2009, 0x001f, 0x080c, 0x86d3, 0xa085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126,
-	0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, 0x001e, 0x0188, 0x660a,
-	0x611a, 0x080c, 0xa0e3, 0x601f, 0x0008, 0x2d00, 0x6012, 0x2009,
-	0x0021, 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005,
-	0xa006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c,
-	0x864e, 0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f,
-	0x0001, 0x2d00, 0x6012, 0x2009, 0x003d, 0x080c, 0x86d3, 0xa085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00c6, 0x0126,
-	0x2091, 0x8000, 0x00c6, 0x080c, 0x9f92, 0x001e, 0x0180, 0x611a,
-	0x080c, 0xa0e3, 0x601f, 0x0001, 0x2d00, 0x6012, 0x2009, 0x0000,
-	0x080c, 0x86d3, 0xa085, 0x0001, 0x012e, 0x00ce, 0x0005, 0xa006,
-	0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e,
-	0x001e, 0x0188, 0x660a, 0x611a, 0x080c, 0xa0e3, 0x601f, 0x0001,
-	0x2d00, 0x6012, 0x2009, 0x0044, 0x080c, 0x86d3, 0xa085, 0x0001,
-	0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x0026, 0x00d6, 0x6218,
-	0x2268, 0x6a3c, 0x82ff, 0x0110, 0x8211, 0x6a3e, 0x00de, 0x002e,
-	0x0005, 0x0006, 0x6000, 0xa086, 0x0000, 0x0190, 0x6013, 0x0000,
-	0x601f, 0x0007, 0x2001, 0xb8b6, 0x2004, 0x0006, 0xa082, 0x0051,
-	0x000e, 0x0208, 0x8004, 0x6016, 0x080c, 0xb3f6, 0x603f, 0x0000,
-	0x000e, 0x0005, 0x0066, 0x00c6, 0x00d6, 0x2031, 0xb653, 0x2634,
-	0xd6e4, 0x0128, 0x6618, 0x2660, 0x6e48, 0x080c, 0x5147, 0x00de,
-	0x00ce, 0x006e, 0x0005, 0x0006, 0x0016, 0x6004, 0xa08e, 0x0002,
-	0x0140, 0xa08e, 0x0003, 0x0128, 0xa08e, 0x0004, 0x0110, 0xa085,
-	0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x00d6, 0x6010, 0xa06d,
-	0x0148, 0x6834, 0xa086, 0x0139, 0x0138, 0x6838, 0xd0fc, 0x0110,
-	0xa006, 0x0010, 0xa085, 0x0001, 0x00de, 0x000e, 0x0005, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x00c6, 0x080c, 0x864e, 0x001e, 0x0190,
-	0x611a, 0x080c, 0xa0e3, 0x601f, 0x0001, 0x2d00, 0x6012, 0x080c,
-	0x2cd1, 0x2009, 0x0028, 0x080c, 0x86d3, 0xa085, 0x0001, 0x012e,
-	0x00ce, 0x0005, 0xa006, 0x0cd8, 0xa186, 0x0015, 0x1178, 0x2011,
-	0xb621, 0x2204, 0xa086, 0x0074, 0x1148, 0x080c, 0x9024, 0x6003,
-	0x0001, 0x6007, 0x0029, 0x080c, 0x6d45, 0x0020, 0x080c, 0x8ca5,
-	0x080c, 0x86a4, 0x0005, 0xa186, 0x0016, 0x1128, 0x2001, 0x0004,
-	0x080c, 0x4f6f, 0x00e8, 0xa186, 0x0015, 0x11e8, 0x2011, 0xb621,
-	0x2204, 0xa086, 0x0014, 0x11b8, 0x00d6, 0x6018, 0x2068, 0x080c,
-	0x50bd, 0x00de, 0x080c, 0x90dd, 0x1170, 0x00d6, 0x6018, 0x2068,
-	0x6890, 0x00de, 0xa005, 0x0138, 0x2001, 0x0006, 0x080c, 0x4f6f,
-	0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5, 0x080c, 0x86a4, 0x0005,
-	0x6848, 0xa086, 0x0005, 0x1108, 0x0009, 0x0005, 0x6850, 0xc0ad,
-	0x6852, 0x0005, 0x00e6, 0x0126, 0x2071, 0xb600, 0x2091, 0x8000,
-	0x7548, 0xa582, 0x0001, 0x0608, 0x704c, 0x2060, 0x6000, 0xa086,
-	0x0000, 0x0148, 0xace0, 0x0018, 0x705c, 0xac02, 0x1208, 0x0cb0,
-	0x2061, 0xbe00, 0x0c98, 0x6003, 0x0008, 0x8529, 0x754a, 0xaca8,
-	0x0018, 0x705c, 0xa502, 0x1230, 0x754e, 0xa085, 0x0001, 0x012e,
-	0x00ee, 0x0005, 0x704f, 0xbe00, 0x0cc0, 0xa006, 0x0cc0, 0x00e6,
-	0x2071, 0xbc8c, 0x7014, 0xd0e4, 0x0150, 0x6013, 0x0000, 0x6003,
-	0x0001, 0x6007, 0x0050, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00ee,
-	0x0005, 0x00c6, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x0120,
-	0x601c, 0xa084, 0x000f, 0x0013, 0x00ce, 0x0005, 0x9aba, 0x9fe9,
-	0x9fec, 0x9fef, 0xb1e3, 0xb1fe, 0xb201, 0x9aba, 0x9aba, 0x080c,
-	0x151a, 0xe000, 0xe000, 0x0005, 0xe000, 0xe000, 0x0005, 0x0009,
-	0x0005, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x0538, 0x080c, 0x864e,
-	0x1128, 0x2001, 0xb8b8, 0x2004, 0x783e, 0x00f8, 0x7818, 0x601a,
-	0x080c, 0xa0e3, 0x781c, 0xa086, 0x0003, 0x0128, 0x7808, 0x6036,
-	0x2f00, 0x603a, 0x0020, 0x7808, 0x603a, 0x2f00, 0x6036, 0x602a,
-	0x601f, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001, 0x7950, 0x6152,
-	0x080c, 0x6cff, 0x080c, 0x71e5, 0x2f60, 0x00fe, 0x0005, 0x0016,
-	0x00f6, 0x682c, 0x6032, 0xa08e, 0x0001, 0x0138, 0xa086, 0x0005,
-	0x0140, 0xa006, 0x602a, 0x602e, 0x00a0, 0x6820, 0xc0f4, 0xc0d5,
-	0x6822, 0x6810, 0x2078, 0x787c, 0x6938, 0xa102, 0x7880, 0x6934,
-	0xa103, 0x1e78, 0x6834, 0x602a, 0x6838, 0xa084, 0xfffc, 0x683a,
-	0x602e, 0x2d00, 0x6036, 0x6808, 0x603a, 0x6918, 0x611a, 0x6950,
-	0x6152, 0x601f, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001, 0x080c,
-	0x6cff, 0x6803, 0x0002, 0x00fe, 0x001e, 0x0005, 0x00f6, 0x2c78,
-	0x080c, 0x5377, 0x1118, 0xa085, 0x0001, 0x0070, 0x6020, 0xd0f4,
-	0x1150, 0xc0f5, 0x6022, 0x6010, 0x2078, 0x7828, 0x603a, 0x782c,
-	0x6036, 0x080c, 0x1952, 0xa006, 0x00fe, 0x0005, 0x0006, 0x0016,
-	0x6004, 0xa08e, 0x0034, 0x01b8, 0xa08e, 0x0035, 0x01a0, 0xa08e,
-	0x0036, 0x0188, 0xa08e, 0x0037, 0x0170, 0xa08e, 0x0038, 0x0158,
-	0xa08e, 0x0039, 0x0140, 0xa08e, 0x003a, 0x0128, 0xa08e, 0x003b,
-	0x0110, 0xa085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016,
-	0x0026, 0x0036, 0x00e6, 0x2001, 0xb8b2, 0x200c, 0x8000, 0x2014,
-	0x2001, 0x0032, 0x080c, 0x6bb2, 0x2001, 0xb8b6, 0x82ff, 0x1110,
-	0x2011, 0x0014, 0x2202, 0x2001, 0xb8b4, 0x200c, 0x8000, 0x2014,
-	0x2071, 0xb88e, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x6bb2,
-	0x2001, 0xb8b7, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2009,
-	0xb8b8, 0xa280, 0x000a, 0x200a, 0x080c, 0x539c, 0x00ee, 0x003e,
-	0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x00e6, 0x2001, 0xb8b6,
-	0x2003, 0x0028, 0x2001, 0xb8b7, 0x2003, 0x0014, 0x2071, 0xb88e,
-	0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0xb8b8, 0x2003, 0x001e,
-	0x00ee, 0x000e, 0x0005, 0x00d6, 0x6054, 0xa06d, 0x0110, 0x080c,
-	0x1614, 0x00de, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000,
-	0x00c6, 0x080c, 0x864e, 0x001e, 0x0178, 0x611a, 0x0ca1, 0x601f,
-	0x0001, 0x2d00, 0x6012, 0x2009, 0x0033, 0x080c, 0x86d3, 0xa085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6,
-	0x00f6, 0x2071, 0xb600, 0xa186, 0x0015, 0x1500, 0x7084, 0xa086,
-	0x0018, 0x11e0, 0x6010, 0x2068, 0x6a3c, 0xd2e4, 0x1160, 0x2c78,
-	0x080c, 0x73a3, 0x01d8, 0x7070, 0x6a50, 0xa206, 0x1160, 0x7074,
-	0x6a54, 0xa206, 0x1140, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
-	0x0000, 0x080c, 0x2d16, 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5,
-	0x080c, 0x86a4, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a54,
-	0xa206, 0x0d48, 0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x00c6,
-	0x080c, 0x864e, 0x001e, 0x0180, 0x611a, 0x080c, 0xa0e3, 0x601f,
-	0x0001, 0x2d00, 0x6012, 0x2009, 0x0043, 0x080c, 0x86d3, 0xa085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0xa006, 0x0cd8, 0x00d6, 0x00e6,
-	0x00f6, 0x2071, 0xb600, 0xa186, 0x0015, 0x11c0, 0x7084, 0xa086,
-	0x0004, 0x11a0, 0x6010, 0xa0e8, 0x000f, 0x2c78, 0x080c, 0x73a3,
-	0x01a8, 0x7070, 0x6a08, 0xa206, 0x1130, 0x7074, 0x6a0c, 0xa206,
-	0x1110, 0x080c, 0x2cd1, 0x080c, 0x882c, 0x0020, 0x080c, 0x8ca5,
-	0x080c, 0x86a4, 0x00fe, 0x00ee, 0x00de, 0x0005, 0x7054, 0x6a0c,
-	0xa206, 0x0d78, 0x0c80, 0x0016, 0x0026, 0x684c, 0xd0ac, 0x0178,
-	0x6914, 0x6a10, 0x2100, 0xa205, 0x0150, 0x6860, 0xa106, 0x1118,
-	0x685c, 0xa206, 0x0120, 0x6962, 0x6a5e, 0xa085, 0x0001, 0x002e,
-	0x001e, 0x0005, 0x00d6, 0x0036, 0x6310, 0x2368, 0x684a, 0x6952,
-	0xa29e, 0x4000, 0x11a0, 0x00c6, 0x6318, 0x2360, 0x2009, 0x0000,
-	0x6838, 0xd0f4, 0x1140, 0x080c, 0x52bc, 0x1108, 0xc185, 0x6000,
-	0xd0bc, 0x0108, 0xc18d, 0x6a66, 0x696a, 0x00ce, 0x0080, 0x6a66,
-	0x3918, 0xa398, 0x0006, 0x231c, 0x686b, 0x0004, 0x6b72, 0x00c6,
-	0x6318, 0x2360, 0x6004, 0xa084, 0x00ff, 0x686e, 0x00ce, 0x080c,
-	0x547a, 0x6013, 0x0000, 0x003e, 0x00de, 0x0005, 0x00c6, 0x0026,
-	0x0016, 0xa186, 0x0035, 0x0110, 0x6a34, 0x0008, 0x6a28, 0x080c,
-	0x9d06, 0x01f0, 0x2260, 0x611c, 0xa186, 0x0003, 0x0118, 0xa186,
-	0x0006, 0x1190, 0x6834, 0xa206, 0x0140, 0x6838, 0xa206, 0x1160,
-	0x6108, 0x6834, 0xa106, 0x1140, 0x0020, 0x6008, 0x6938, 0xa106,
-	0x1118, 0x6018, 0x6918, 0xa106, 0x001e, 0x002e, 0x00ce, 0x0005,
-	0xa085, 0x0001, 0x0cc8, 0x6944, 0xd1cc, 0x0198, 0xa18c, 0x00ff,
-	0xa18e, 0x0002, 0x1170, 0xad88, 0x001e, 0x210c, 0xa18c, 0x0f00,
-	0x810f, 0xa18e, 0x0001, 0x1128, 0x6810, 0x6914, 0xa115, 0x190c,
-	0x953f, 0x0005, 0x080c, 0x86a4, 0x0804, 0x71e5, 0x0066, 0x6000,
-	0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0xa227,
-	0xa702, 0xa828, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0xa25f,
-	0xa8ac, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0xa227, 0x080c,
-	0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010, 0x1a0c, 0x151a, 0x0013,
-	0x006e, 0x0005, 0xa242, 0xad33, 0xa242, 0xa242, 0xa242, 0xa242,
-	0xa242, 0xa242, 0xacf5, 0xad7b, 0xa242, 0xb328, 0xb358, 0xb328,
-	0xb358, 0xa242, 0x080c, 0x151a, 0x0066, 0x6000, 0xa0b2, 0x0010,
-	0x1a0c, 0x151a, 0x0013, 0x006e, 0x0005, 0xa25d, 0xa9fc, 0xaac9,
-	0xaaf6, 0xab7a, 0xa25d, 0xac67, 0xac12, 0xa8b8, 0xaccb, 0xace0,
-	0xa25d, 0xa25d, 0xa25d, 0xa25d, 0xa25d, 0x080c, 0x151a, 0xa1b2,
-	0x0080, 0x1a0c, 0x151a, 0x2100, 0xa1b2, 0x0040, 0x1a04, 0xa676,
-	0x0002, 0xa2a9, 0xa474, 0xa2a9, 0xa2a9, 0xa2a9, 0xa47b, 0xa2a9,
-	0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9,
-	0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9,
-	0xa2ab, 0xa309, 0xa318, 0xa366, 0xa384, 0xa402, 0xa461, 0xa2a9,
-	0xa2a9, 0xa47e, 0xa2a9, 0xa2a9, 0xa491, 0xa49c, 0xa2a9, 0xa2a9,
-	0xa2a9, 0xa2a9, 0xa2a9, 0xa527, 0xa2a9, 0xa2a9, 0xa53a, 0xa2a9,
-	0xa2a9, 0xa4f2, 0xa2a9, 0xa2a9, 0xa2a9, 0xa552, 0xa2a9, 0xa2a9,
-	0xa2a9, 0xa5cc, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9, 0xa2a9,
-	0xa63d, 0x080c, 0x151a, 0x080c, 0x537b, 0x1150, 0x2001, 0xb635,
-	0x2004, 0xd0cc, 0x1128, 0xa084, 0x0009, 0xa086, 0x0008, 0x1140,
-	0x6007, 0x0009, 0x602b, 0x0009, 0x6013, 0x0000, 0x0804, 0xa46f,
-	0x080c, 0x536b, 0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6218,
-	0x2270, 0x72a0, 0x0026, 0x2019, 0x0029, 0x080c, 0x6e67, 0x0076,
-	0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08, 0x080c, 0xaf3e, 0x007e,
-	0x001e, 0x2e60, 0x080c, 0x521c, 0x001e, 0x002e, 0x003e, 0x00ce,
-	0x00ee, 0x6618, 0x00c6, 0x2660, 0x080c, 0x502a, 0x00ce, 0xa6b0,
-	0x0001, 0x2634, 0xa684, 0x00ff, 0xa082, 0x0006, 0x0278, 0x080c,
-	0xae82, 0x1904, 0xa360, 0x080c, 0xae22, 0x1120, 0x6007, 0x0008,
-	0x0804, 0xa46f, 0x6007, 0x0009, 0x0804, 0xa46f, 0x080c, 0xb037,
-	0x0128, 0x080c, 0xae82, 0x0d78, 0x0804, 0xa360, 0x6013, 0x1900,
-	0x0c88, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6106, 0x080c, 0xaddc,
-	0x6007, 0x0006, 0x0804, 0xa46f, 0x6007, 0x0007, 0x0804, 0xa46f,
-	0x080c, 0xb38c, 0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673,
-	0x00d6, 0x6618, 0x2668, 0x6e04, 0xa684, 0x00ff, 0xa082, 0x0006,
-	0x1220, 0x2001, 0x0001, 0x080c, 0x4f5d, 0xa6b4, 0xff00, 0x8637,
-	0xa686, 0x0006, 0x0188, 0xa686, 0x0004, 0x0170, 0x6e04, 0xa6b4,
-	0x00ff, 0xa686, 0x0006, 0x0140, 0xa686, 0x0004, 0x0128, 0xa686,
-	0x0005, 0x0110, 0x00de, 0x00e0, 0x080c, 0xaee0, 0x11a0, 0xa686,
-	0x0006, 0x1150, 0x0026, 0x6218, 0xa290, 0x0028, 0x2214, 0x2009,
-	0x0000, 0x080c, 0x2d16, 0x002e, 0x080c, 0x50bd, 0x6007, 0x000a,
-	0x00de, 0x0804, 0xa46f, 0x6007, 0x000b, 0x00de, 0x0804, 0xa46f,
-	0x080c, 0x2cd1, 0x6007, 0x0001, 0x0804, 0xa46f, 0x080c, 0xb38c,
-	0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6618, 0x00d6,
-	0x2668, 0x6e04, 0x00de, 0xa686, 0x0707, 0x0d50, 0x0026, 0x6218,
-	0xa290, 0x0028, 0x2214, 0x2009, 0x0000, 0x080c, 0x2d16, 0x002e,
-	0x6007, 0x000c, 0x0804, 0xa46f, 0x080c, 0x537b, 0x1140, 0x2001,
-	0xb635, 0x2004, 0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804,
-	0xa2b8, 0x080c, 0x536b, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684,
-	0x00ff, 0xa082, 0x0006, 0x06e8, 0x1138, 0x0026, 0x2001, 0x0006,
-	0x080c, 0x4f9c, 0x002e, 0x0050, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0004, 0x0120, 0xa686, 0x0006, 0x1904, 0xa360, 0x080c, 0xaeed,
-	0x1120, 0x6007, 0x000e, 0x0804, 0xa46f, 0x0046, 0x6418, 0xa4a0,
-	0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c, 0x2cd1,
-	0x004e, 0x0016, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, 0x0158,
-	0x2009, 0x0029, 0x080c, 0xb1a4, 0x6018, 0x00d6, 0x2068, 0x6800,
-	0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001, 0x0804,
-	0xa46f, 0x2001, 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, 0x0026,
-	0x0036, 0x20a9, 0x0004, 0x2019, 0xb605, 0x2011, 0xbc90, 0x080c,
-	0x9166, 0x003e, 0x002e, 0x001e, 0x015e, 0xa005, 0x0168, 0xa6b4,
-	0xff00, 0x8637, 0xa682, 0x0004, 0x0a04, 0xa360, 0xa682, 0x0007,
-	0x0a04, 0xa3ae, 0x0804, 0xa360, 0x6013, 0x1900, 0x6007, 0x0009,
-	0x0804, 0xa46f, 0x080c, 0x537b, 0x1140, 0x2001, 0xb635, 0x2004,
-	0xa084, 0x0009, 0xa086, 0x0008, 0x1110, 0x0804, 0xa2b8, 0x080c,
-	0x536b, 0x6618, 0xa6b0, 0x0001, 0x2634, 0xa684, 0x00ff, 0xa082,
-	0x0006, 0x06b8, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0004, 0x0120,
-	0xa686, 0x0006, 0x1904, 0xa360, 0x080c, 0xaf15, 0x1138, 0x080c,
-	0xae22, 0x1120, 0x6007, 0x0010, 0x0804, 0xa46f, 0x0046, 0x6418,
-	0xa4a0, 0x0028, 0x2424, 0xa4a4, 0x00ff, 0x8427, 0x0046, 0x080c,
-	0x2cd1, 0x004e, 0x0016, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4,
-	0x0158, 0x2009, 0x0029, 0x080c, 0xb1a4, 0x6018, 0x00d6, 0x2068,
-	0x6800, 0xc0e5, 0x6802, 0x00de, 0x001e, 0x004e, 0x6007, 0x0001,
-	0x00f0, 0x080c, 0xb037, 0x0140, 0xa6b4, 0xff00, 0x8637, 0xa686,
-	0x0006, 0x0950, 0x0804, 0xa360, 0x6013, 0x1900, 0x6007, 0x0009,
-	0x0070, 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xb38c, 0x1904,
-	0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6007, 0x0012, 0x6003,
-	0x0001, 0x080c, 0x6d45, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001,
-	0x080c, 0x6d45, 0x0cc0, 0x6007, 0x0005, 0x0cc0, 0x080c, 0xb38c,
-	0x1904, 0xa673, 0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b,
-	0x1904, 0xa360, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c, 0x6d45,
-	0x0005, 0x080c, 0x2df4, 0x1904, 0xa673, 0x6007, 0x0023, 0x6003,
-	0x0001, 0x080c, 0x6d45, 0x0005, 0x080c, 0xb38c, 0x1904, 0xa673,
-	0x080c, 0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360,
-	0x0016, 0x0026, 0x2011, 0xbc91, 0x2214, 0xa286, 0xffff, 0x0190,
-	0x2c08, 0x080c, 0x9d06, 0x01e0, 0x2260, 0x2011, 0xbc90, 0x2214,
-	0x6008, 0xa206, 0x11a8, 0x6018, 0xa190, 0x0006, 0x2214, 0xa206,
-	0x01e8, 0x0070, 0x2011, 0xbc90, 0x2214, 0x2c08, 0xa006, 0x080c,
-	0xb176, 0x11a0, 0x2011, 0xbc91, 0x2214, 0xa286, 0xffff, 0x01c0,
-	0x2160, 0x6007, 0x0026, 0x6013, 0x1700, 0x2011, 0xbc89, 0x2214,
-	0xa296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x601c, 0xa086,
-	0x0007, 0x1d70, 0x6004, 0xa086, 0x0024, 0x1110, 0x080c, 0x86a4,
-	0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x6d45, 0x002e,
-	0x001e, 0x0005, 0x2001, 0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016,
-	0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0xb605, 0x2011, 0xbc96,
-	0x080c, 0x9166, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007,
-	0x0031, 0x0804, 0xa46f, 0x080c, 0x8e82, 0x080c, 0x5b41, 0x11b0,
-	0x0006, 0x0026, 0x0036, 0x080c, 0x5b5d, 0x1158, 0x2001, 0xb89f,
-	0x2003, 0x0001, 0x2001, 0xb600, 0x2003, 0x0001, 0x080c, 0x5a79,
-	0x0010, 0x080c, 0x5b18, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c,
-	0x2df4, 0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6106,
-	0x080c, 0xa6b7, 0x6007, 0x002b, 0x0804, 0xa46f, 0x6007, 0x002c,
-	0x0804, 0xa46f, 0x080c, 0xb38c, 0x1904, 0xa673, 0x080c, 0x2df4,
-	0x1904, 0xa673, 0x080c, 0xa69b, 0x1904, 0xa360, 0x6106, 0x080c,
-	0xa6bb, 0x1120, 0x6007, 0x002e, 0x0804, 0xa46f, 0x6007, 0x002f,
-	0x0804, 0xa46f, 0x080c, 0x2df4, 0x1904, 0xa673, 0x00e6, 0x00d6,
-	0x00c6, 0x6018, 0xa080, 0x0001, 0x200c, 0xa184, 0x00ff, 0xa086,
-	0x0006, 0x0158, 0xa184, 0xff00, 0x8007, 0xa086, 0x0006, 0x0128,
-	0x00ce, 0x00de, 0x00ee, 0x0804, 0xa474, 0x2001, 0xb672, 0x2004,
-	0xd0e4, 0x0904, 0xa5c9, 0x2071, 0xbc8c, 0x7010, 0x6036, 0x7014,
-	0x603a, 0x7108, 0x720c, 0x2001, 0xb653, 0x2004, 0xd0a4, 0x0140,
-	0x6018, 0x2068, 0x6810, 0xa106, 0x1118, 0x6814, 0xa206, 0x01f8,
-	0x2001, 0xb653, 0x2004, 0xd0ac, 0x1590, 0x2069, 0xb600, 0x6874,
-	0xa206, 0x1568, 0x6870, 0xa106, 0x1550, 0x7210, 0x080c, 0x9d06,
-	0x0558, 0x080c, 0xb210, 0x0540, 0x622a, 0x6007, 0x0036, 0x6003,
-	0x0001, 0x080c, 0x6cff, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214,
-	0xa286, 0xffff, 0x0150, 0x080c, 0x9d06, 0x01b0, 0xa280, 0x0002,
-	0x2004, 0x7110, 0xa106, 0x1180, 0x0c08, 0x7210, 0x2c08, 0xa085,
-	0x0001, 0x080c, 0xb176, 0x2c10, 0x2160, 0x0130, 0x08b8, 0x6007,
-	0x0037, 0x6013, 0x1500, 0x08d8, 0x6007, 0x0037, 0x6013, 0x1700,
-	0x08b0, 0x6007, 0x0012, 0x0898, 0x080c, 0x2df4, 0x1904, 0xa673,
-	0x6018, 0xa080, 0x0001, 0x2004, 0xa084, 0xff00, 0x8007, 0xa086,
-	0x0006, 0x1904, 0xa474, 0x00e6, 0x00d6, 0x00c6, 0x2001, 0xb672,
-	0x2004, 0xd0e4, 0x0904, 0xa635, 0x2069, 0xb600, 0x2071, 0xbc8c,
-	0x7008, 0x6036, 0x720c, 0x623a, 0xa286, 0xffff, 0x1150, 0x7208,
-	0x00c6, 0x2c08, 0xa085, 0x0001, 0x080c, 0xb176, 0x2c10, 0x00ce,
-	0x0588, 0x080c, 0x9d06, 0x0570, 0x00c6, 0x0026, 0x2260, 0x080c,
-	0x99d9, 0x002e, 0x00ce, 0x7118, 0xa18c, 0xff00, 0x810f, 0xa186,
-	0x0001, 0x0158, 0xa186, 0x0005, 0x0118, 0xa186, 0x0007, 0x1178,
-	0xa280, 0x0004, 0x2004, 0xa005, 0x0150, 0x0056, 0x7510, 0x7614,
-	0x080c, 0xb227, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007,
-	0x003b, 0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c,
-	0x6cff, 0x0c88, 0x6007, 0x003b, 0x602b, 0x0009, 0x6013, 0x1700,
-	0x6003, 0x0001, 0x080c, 0x6cff, 0x0c30, 0x6007, 0x003b, 0x602b,
-	0x000b, 0x6013, 0x0000, 0x0804, 0xa59f, 0x00e6, 0x0026, 0x080c,
-	0x537b, 0x0558, 0x080c, 0x536b, 0x080c, 0xb407, 0x1520, 0x2071,
-	0xb600, 0x70d4, 0xc085, 0x70d6, 0x00f6, 0x2079, 0x0100, 0x72a0,
-	0xa284, 0x00ff, 0x7072, 0x78e6, 0xa284, 0xff00, 0x7274, 0xa205,
-	0x7076, 0x78ea, 0x00fe, 0x70df, 0x0000, 0x2001, 0xb653, 0x2004,
-	0xd0a4, 0x0120, 0x2011, 0xb8fa, 0x2013, 0x07d0, 0xd0ac, 0x1128,
-	0x080c, 0x2aed, 0x0010, 0x080c, 0xb433, 0x002e, 0x00ee, 0x080c,
-	0x86a4, 0x0804, 0xa473, 0x080c, 0x86a4, 0x0005, 0x2600, 0x0002,
-	0xa681, 0xa681, 0xa681, 0xa681, 0xa681, 0xa683, 0xa681, 0xa681,
-	0xa681, 0x080c, 0x151a, 0x080c, 0xb38c, 0x1d68, 0x080c, 0x2df4,
-	0x1d50, 0x0089, 0x1138, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c,
-	0x6d45, 0x0005, 0x080c, 0x2cd1, 0x6007, 0x0001, 0x6003, 0x0001,
-	0x080c, 0x6d45, 0x0005, 0x00d6, 0x0066, 0x6618, 0x2668, 0x6e04,
-	0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0xa686, 0x0004,
-	0x0158, 0x6e04, 0xa6b4, 0x00ff, 0xa686, 0x0006, 0x0128, 0xa686,
-	0x0004, 0x0110, 0xa085, 0x0001, 0x006e, 0x00de, 0x0005, 0x00d6,
-	0x0449, 0x00de, 0x0005, 0x00d6, 0x0491, 0x11f0, 0x680c, 0xa08c,
-	0xff00, 0x6820, 0xa084, 0x00ff, 0xa115, 0x6212, 0x6824, 0x602a,
-	0xd1e4, 0x0118, 0x2009, 0x0001, 0x0060, 0xd1ec, 0x0168, 0x6920,
-	0xa18c, 0x00ff, 0x6824, 0x080c, 0x2852, 0x1130, 0x2110, 0x2009,
-	0x0000, 0x080c, 0x2d16, 0x0018, 0xa085, 0x0001, 0x0008, 0xa006,
-	0x00de, 0x0005, 0x2069, 0xbc8d, 0x6800, 0xa082, 0x0010, 0x1228,
-	0x6013, 0x0000, 0xa085, 0x0001, 0x0008, 0xa006, 0x0005, 0x6013,
-	0x0000, 0x2069, 0xbc8c, 0x6808, 0xa084, 0xff00, 0xa086, 0x0800,
-	0x1140, 0x6800, 0xa084, 0x00ff, 0xa08e, 0x0014, 0x0110, 0xa08e,
-	0x0010, 0x0005, 0x6004, 0xa0b2, 0x0080, 0x1a0c, 0x151a, 0xa1b6,
-	0x0013, 0x1130, 0x2008, 0xa1b2, 0x0040, 0x1a04, 0xa802, 0x0092,
-	0xa1b6, 0x0027, 0x0120, 0xa1b6, 0x0014, 0x190c, 0x151a, 0x2001,
-	0x0007, 0x080c, 0x4f9c, 0x080c, 0x7102, 0x080c, 0x9ed9, 0x080c,
-	0x71e5, 0x0005, 0xa762, 0xa764, 0xa762, 0xa762, 0xa762, 0xa764,
-	0xa776, 0xa7fb, 0xa7c6, 0xa7fb, 0xa7d7, 0xa7fb, 0xa776, 0xa7fb,
-	0xa7f3, 0xa7fb, 0xa7f3, 0xa7fb, 0xa7fb, 0xa762, 0xa762, 0xa762,
-	0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762, 0xa762,
-	0xa764, 0xa762, 0xa7fb, 0xa762, 0xa762, 0xa7fb, 0xa762, 0xa7f8,
-	0xa7fb, 0xa762, 0xa762, 0xa762, 0xa762, 0xa7fb, 0xa7fb, 0xa762,
-	0xa7fb, 0xa7fb, 0xa762, 0xa770, 0xa762, 0xa762, 0xa762, 0xa762,
-	0xa7f7, 0xa7fb, 0xa762, 0xa762, 0xa7fb, 0xa7fb, 0xa762, 0xa762,
-	0xa762, 0xa762, 0x080c, 0x151a, 0x080c, 0x7102, 0x2001, 0xb8b6,
-	0x2004, 0x6016, 0x6003, 0x0002, 0x080c, 0x71e5, 0x0804, 0xa801,
-	0x2001, 0x0000, 0x080c, 0x4f5d, 0x0804, 0xa7fb, 0x00f6, 0x2079,
-	0xb652, 0x7804, 0x00fe, 0xd0ac, 0x1904, 0xa7fb, 0x2001, 0x0000,
-	0x080c, 0x4f5d, 0x6018, 0xa080, 0x0004, 0x2004, 0xa086, 0x00ff,
-	0x1140, 0x00f6, 0x2079, 0xb600, 0x7898, 0x8000, 0x789a, 0x00fe,
-	0x00e0, 0x00c6, 0x6018, 0x2060, 0x6000, 0xd0f4, 0x1140, 0x6010,
-	0xa005, 0x0128, 0x00ce, 0x080c, 0x3f85, 0x0804, 0xa7fb, 0x00ce,
-	0x2001, 0xb600, 0x2004, 0xa086, 0x0002, 0x1138, 0x00f6, 0x2079,
-	0xb600, 0x7898, 0x8000, 0x789a, 0x00fe, 0x2001, 0x0002, 0x080c,
-	0x4f6f, 0x080c, 0x7102, 0x601f, 0x0001, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x080c, 0x6d45, 0x080c, 0x71e5, 0x00c6, 0x6118, 0x2160,
-	0x2009, 0x0001, 0x080c, 0x6a1a, 0x00ce, 0x04d8, 0x6618, 0x00d6,
-	0x2668, 0x6e04, 0x00de, 0xa6b4, 0xff00, 0x8637, 0xa686, 0x0006,
-	0x0550, 0xa686, 0x0004, 0x0538, 0x2001, 0x0004, 0x0410, 0x2001,
-	0xb600, 0x2004, 0xa086, 0x0003, 0x1110, 0x080c, 0x3f85, 0x2001,
-	0x0006, 0x04a1, 0x6618, 0x00d6, 0x2668, 0x6e04, 0x00de, 0xa6b4,
-	0xff00, 0x8637, 0xa686, 0x0006, 0x0170, 0x2001, 0x0006, 0x0048,
-	0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0401, 0x0020, 0x0018,
-	0x0010, 0x080c, 0x4f9c, 0x080c, 0x7102, 0x080c, 0x86a4, 0x080c,
-	0x71e5, 0x0005, 0x2600, 0x0002, 0xa80d, 0xa80d, 0xa80d, 0xa80d,
-	0xa80d, 0xa80f, 0xa80d, 0xa80d, 0xa80d, 0x080c, 0x151a, 0x080c,
-	0x7102, 0x080c, 0x86a4, 0x080c, 0x71e5, 0x0005, 0x0016, 0x00d6,
-	0x6118, 0x2168, 0x6900, 0xd184, 0x0140, 0x080c, 0x4f6f, 0x2001,
-	0x0000, 0x080c, 0x4f5d, 0x080c, 0x2cf7, 0x00de, 0x001e, 0x0005,
-	0x00d6, 0x6618, 0x2668, 0x6804, 0xa084, 0xff00, 0x8007, 0x00de,
-	0xa0b2, 0x000c, 0x1a0c, 0x151a, 0xa1b6, 0x0015, 0x1110, 0x003b,
-	0x0028, 0xa1b6, 0x0016, 0x190c, 0x151a, 0x006b, 0x0005, 0x8d6b,
-	0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0xa898, 0xa857, 0x8d6b,
-	0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b,
-	0x8d6b, 0xa898, 0xa89f, 0x8d6b, 0x8d6b, 0x8d6b, 0x8d6b, 0x00f6,
-	0x2079, 0xb652, 0x7804, 0xd0ac, 0x11e0, 0x6018, 0xa07d, 0x01c8,
-	0x7800, 0xd0f4, 0x1118, 0x7810, 0xa005, 0x1198, 0x2001, 0x0000,
-	0x080c, 0x4f5d, 0x2001, 0x0002, 0x080c, 0x4f6f, 0x601f, 0x0001,
-	0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x6d45, 0x080c, 0x71e5,
-	0x00e8, 0x2011, 0xbc83, 0x2204, 0x8211, 0x220c, 0x080c, 0x2852,
-	0x11a8, 0x00c6, 0x080c, 0x501b, 0x0120, 0x00ce, 0x080c, 0x86a4,
-	0x0068, 0x6010, 0x0006, 0x6014, 0x0006, 0x080c, 0x4c7e, 0x000e,
-	0x6016, 0x000e, 0x6012, 0x00ce, 0x080c, 0x86a4, 0x00fe, 0x0005,
-	0x6604, 0xa6b6, 0x001e, 0x1110, 0x080c, 0x86a4, 0x0005, 0x080c,
-	0x9021, 0x1138, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x6d45,
-	0x0010, 0x080c, 0x86a4, 0x0005, 0x6004, 0xa08a, 0x0080, 0x1a0c,
-	0x151a, 0x080c, 0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005,
-	0xa182, 0x0040, 0x0002, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8d0,
-	0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce,
-	0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0xa8ce, 0x080c, 0x151a,
-	0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0046, 0x0026, 0x6218, 0xa280,
-	0x002b, 0x2004, 0xa005, 0x0120, 0x2021, 0x0000, 0x080c, 0xb3d8,
-	0x6106, 0x2071, 0xbc80, 0x7444, 0xa4a4, 0xff00, 0x0904, 0xa934,
-	0xa486, 0x2000, 0x1130, 0x2009, 0x0001, 0x2011, 0x0200, 0x080c,
-	0x6b8c, 0x080c, 0x15fd, 0x090c, 0x151a, 0x6003, 0x0007, 0x2d00,
-	0x6837, 0x010d, 0x6803, 0x0000, 0x683b, 0x0000, 0x6c5a, 0x2c00,
-	0x685e, 0x6008, 0x68b2, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
-	0x694a, 0x0016, 0xa084, 0xff00, 0x6846, 0x684f, 0x0000, 0x6853,
-	0x0000, 0x6857, 0x0036, 0x080c, 0x547a, 0x001e, 0xa486, 0x2000,
-	0x1130, 0x2019, 0x0017, 0x080c, 0xb121, 0x0804, 0xa991, 0xa486,
-	0x0400, 0x1130, 0x2019, 0x0002, 0x080c, 0xb0d3, 0x0804, 0xa991,
-	0xa486, 0x0200, 0x1110, 0x080c, 0xb0b8, 0xa486, 0x1000, 0x1110,
-	0x080c, 0xb106, 0x0804, 0xa991, 0x2069, 0xb975, 0x6a00, 0xd284,
-	0x0904, 0xa9f8, 0xa284, 0x0300, 0x1904, 0xa9f1, 0x6804, 0xa005,
-	0x0904, 0xa9d9, 0x2d78, 0x6003, 0x0007, 0x080c, 0x15e4, 0x0904,
-	0xa998, 0x7800, 0xd08c, 0x1118, 0x7804, 0x8001, 0x7806, 0x6013,
-	0x0000, 0x6803, 0x0000, 0x6837, 0x0116, 0x683b, 0x0000, 0x6008,
-	0x68b2, 0x2c00, 0x684a, 0x6018, 0x2078, 0x78a0, 0x8007, 0x7130,
-	0x6986, 0x6846, 0x7928, 0x698a, 0x792c, 0x698e, 0x7930, 0x6992,
-	0x7934, 0x6996, 0x6853, 0x003d, 0x7244, 0xa294, 0x0003, 0xa286,
-	0x0002, 0x1118, 0x684f, 0x0040, 0x0040, 0xa286, 0x0001, 0x1118,
-	0x684f, 0x0080, 0x0010, 0x684f, 0x0000, 0x20a9, 0x000a, 0x2001,
-	0xbc90, 0xad90, 0x0015, 0x200c, 0x810f, 0x2112, 0x8000, 0x8210,
-	0x1f04, 0xa983, 0x200c, 0x6982, 0x8000, 0x200c, 0x697e, 0x080c,
-	0x547a, 0x002e, 0x004e, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x0005,
-	0x2001, 0xb60e, 0x2004, 0xd084, 0x0120, 0x080c, 0x15fd, 0x1904,
-	0xa949, 0x6013, 0x0100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c,
-	0x6cff, 0x080c, 0x71e5, 0x0c28, 0x2069, 0xbc92, 0x2d04, 0xa084,
-	0xff00, 0xa086, 0x1200, 0x11a8, 0x2069, 0xbc80, 0x686c, 0xa084,
-	0x00ff, 0x0016, 0x6110, 0xa18c, 0x0700, 0xa10d, 0x6112, 0x001e,
-	0x6003, 0x0001, 0x6007, 0x0043, 0x080c, 0x6cff, 0x080c, 0x71e5,
-	0x0840, 0x6868, 0x602a, 0x686c, 0x602e, 0x6013, 0x0200, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0804,
-	0xa991, 0x2001, 0xb60d, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049,
-	0x080c, 0x3f13, 0x6013, 0x0300, 0x0010, 0x6013, 0x0100, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0804,
-	0xa991, 0x6013, 0x0500, 0x0c98, 0x6013, 0x0600, 0x0804, 0xa9ac,
-	0x6013, 0x0200, 0x0804, 0xa9ac, 0xa186, 0x0013, 0x1170, 0x6004,
-	0xa08a, 0x0040, 0x0a0c, 0x151a, 0xa08a, 0x0053, 0x1a0c, 0x151a,
-	0xa082, 0x0040, 0x2008, 0x0804, 0xaa86, 0xa186, 0x0051, 0x0138,
-	0xa186, 0x0047, 0x11d8, 0x6004, 0xa086, 0x0041, 0x0518, 0x2001,
-	0x0109, 0x2004, 0xd084, 0x01f0, 0x0126, 0x2091, 0x2800, 0x0006,
-	0x0016, 0x0026, 0x080c, 0x6be6, 0x002e, 0x001e, 0x000e, 0x012e,
-	0x6000, 0xa086, 0x0002, 0x1170, 0x0804, 0xaac9, 0xa186, 0x0027,
-	0x0120, 0xa186, 0x0014, 0x190c, 0x151a, 0x6004, 0xa082, 0x0040,
-	0x2008, 0x001a, 0x080c, 0x86ef, 0x0005, 0xaa50, 0xaa52, 0xaa52,
-	0xaa76, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50,
-	0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50, 0xaa50,
-	0x080c, 0x151a, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0036, 0x00d6,
-	0x6010, 0xa06d, 0x01c0, 0xad84, 0xf000, 0x01a8, 0x6003, 0x0002,
-	0x6018, 0x2004, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xb155,
-	0x6013, 0x0000, 0x6014, 0xa005, 0x1120, 0x2001, 0xb8b7, 0x2004,
-	0x6016, 0x6003, 0x0007, 0x00de, 0x003e, 0x0005, 0x00d6, 0x080c,
-	0x7102, 0x080c, 0x71e5, 0x080c, 0x9d16, 0x0120, 0x6010, 0x2068,
-	0x080c, 0x1614, 0x080c, 0x9ed9, 0x00de, 0x0005, 0x0002, 0xaa9a,
-	0xaab7, 0xaaa3, 0xaac3, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a,
-	0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a, 0xaa9a,
-	0xaa9a, 0xaa9a, 0x080c, 0x151a, 0x6010, 0xa088, 0x0013, 0x2104,
-	0xa085, 0x0400, 0x200a, 0x080c, 0x7102, 0x6010, 0xa080, 0x0013,
-	0x2004, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c,
-	0x86d3, 0x0010, 0x6003, 0x0002, 0x080c, 0x71e5, 0x0005, 0x080c,
-	0x7102, 0x080c, 0xb393, 0x1120, 0x080c, 0x6b61, 0x080c, 0x86a4,
-	0x080c, 0x71e5, 0x0005, 0x080c, 0x7102, 0x2009, 0x0041, 0x0804,
-	0xac12, 0xa182, 0x0040, 0x0002, 0xaadf, 0xaae1, 0xaadf, 0xaadf,
-	0xaadf, 0xaadf, 0xaadf, 0xaae2, 0xaadf, 0xaadf, 0xaadf, 0xaadf,
-	0xaadf, 0xaadf, 0xaadf, 0xaadf, 0xaadf, 0xaaed, 0xaadf, 0x080c,
-	0x151a, 0x0005, 0x6003, 0x0004, 0x6110, 0x20e1, 0x0005, 0x3d18,
-	0x3e20, 0x2c10, 0x080c, 0x1863, 0x0005, 0x00d6, 0x080c, 0x6b61,
-	0x00de, 0x080c, 0xb3f6, 0x080c, 0x86a4, 0x0005, 0xa182, 0x0040,
-	0x0002, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c, 0xab0c,
-	0xab0e, 0xab0c, 0xab11, 0xab4a, 0xab0c, 0xab0c, 0xab0c, 0xab0c,
-	0xab4a, 0xab0c, 0xab0c, 0xab0c, 0x080c, 0x151a, 0x080c, 0x86ef,
-	0x0005, 0x2001, 0xb672, 0x2004, 0xd0e4, 0x0158, 0x2001, 0x0100,
-	0x2004, 0xa082, 0x0005, 0x0228, 0x2001, 0x011f, 0x2004, 0x6036,
-	0x0010, 0x6037, 0x0000, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6010,
-	0x00d6, 0x2068, 0x684c, 0xd0fc, 0x0150, 0xa08c, 0x0003, 0xa18e,
-	0x0002, 0x0168, 0x2009, 0x0041, 0x00de, 0x0804, 0xac12, 0x6003,
-	0x0007, 0x6017, 0x0000, 0x080c, 0x6b61, 0x00de, 0x0005, 0x080c,
-	0xb393, 0x0110, 0x00de, 0x0005, 0x080c, 0x6b61, 0x080c, 0x86a4,
-	0x00de, 0x0ca0, 0x0036, 0x080c, 0x7198, 0x080c, 0x72a2, 0x6010,
-	0x00d6, 0x2068, 0x6018, 0x2004, 0xd0bc, 0x0188, 0x684c, 0xa084,
-	0x0003, 0xa086, 0x0002, 0x0140, 0x687c, 0x632c, 0xa31a, 0x632e,
-	0x6880, 0x6328, 0xa31b, 0x632a, 0x6003, 0x0002, 0x0080, 0x2019,
-	0x0004, 0x080c, 0xb155, 0x6014, 0xa005, 0x1128, 0x2001, 0xb8b7,
-	0x2004, 0x8003, 0x6016, 0x6013, 0x0000, 0x6003, 0x0007, 0x00de,
-	0x003e, 0x0005, 0xa186, 0x0013, 0x1150, 0x6004, 0xa086, 0x0042,
-	0x190c, 0x151a, 0x080c, 0x7102, 0x080c, 0x71e5, 0x0005, 0xa186,
-	0x0027, 0x0118, 0xa186, 0x0014, 0x1180, 0x6004, 0xa086, 0x0042,
-	0x190c, 0x151a, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x080c, 0x7102,
-	0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0040, 0x0002,
-	0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb5,
-	0xabc1, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3, 0xabb3,
-	0xabb3, 0xabb3, 0xabb3, 0x080c, 0x151a, 0x0036, 0x0046, 0x20e1,
-	0x0005, 0x3d18, 0x3e20, 0x2c10, 0x080c, 0x1863, 0x004e, 0x003e,
-	0x0005, 0x6010, 0x00d6, 0x2068, 0x6810, 0x6a14, 0x0006, 0x0046,
-	0x0056, 0x6c7c, 0xa422, 0x6d80, 0x2200, 0xa52b, 0x602c, 0xa420,
-	0x642e, 0x6028, 0xa529, 0x652a, 0x005e, 0x004e, 0x000e, 0xa20d,
-	0x1178, 0x684c, 0xd0fc, 0x0120, 0x2009, 0x0041, 0x00de, 0x0490,
-	0x6003, 0x0007, 0x6017, 0x0000, 0x080c, 0x6b61, 0x00de, 0x0005,
-	0x0006, 0x00f6, 0x2c78, 0x080c, 0x5377, 0x00fe, 0x000e, 0x0120,
-	0x6003, 0x0002, 0x00de, 0x0005, 0x2009, 0xb60d, 0x210c, 0xd19c,
-	0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006, 0x0021, 0x080c,
-	0x6b63, 0x00de, 0x0005, 0xd2fc, 0x0140, 0x8002, 0x8000, 0x8212,
-	0xa291, 0x0000, 0x2009, 0x0009, 0x0010, 0x2009, 0x0015, 0x6a6a,
-	0x6866, 0x0005, 0xa182, 0x0040, 0x0208, 0x0062, 0xa186, 0x0013,
-	0x0120, 0xa186, 0x0014, 0x190c, 0x151a, 0x6020, 0xd0dc, 0x090c,
-	0x151a, 0x0005, 0xac35, 0xac3c, 0xac48, 0xac54, 0xac35, 0xac35,
-	0xac35, 0xac63, 0xac35, 0xac37, 0xac37, 0xac35, 0xac35, 0xac35,
-	0xac35, 0xac37, 0xac35, 0xac37, 0xac35, 0x080c, 0x151a, 0x6020,
-	0xd0dc, 0x090c, 0x151a, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c,
-	0x6cff, 0x0126, 0x2091, 0x8000, 0x080c, 0x71e5, 0x012e, 0x0005,
-	0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x71e5, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106, 0x2c10,
-	0x080c, 0x1fc5, 0x0126, 0x2091, 0x8000, 0x080c, 0x6d62, 0x080c,
-	0x72a2, 0x012e, 0x0005, 0xa016, 0x080c, 0x1863, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x0036, 0x00d6, 0xa182, 0x0040, 0x0023, 0x00de,
-	0x003e, 0x012e, 0x0005, 0xac83, 0xac85, 0xac97, 0xacb2, 0xac83,
-	0xac83, 0xac83, 0xacc7, 0xac83, 0xac83, 0xac83, 0xac83, 0xac83,
-	0xac83, 0xac83, 0xac83, 0x080c, 0x151a, 0x6010, 0x2068, 0x684c,
-	0xd0fc, 0x01f8, 0xa09c, 0x0003, 0xa39e, 0x0003, 0x01d0, 0x6003,
-	0x0001, 0x6106, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x0498, 0x6010,
-	0x2068, 0x684c, 0xd0fc, 0x0168, 0xa09c, 0x0003, 0xa39e, 0x0003,
-	0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x6cff, 0x080c, 0x71e5,
-	0x0408, 0x6013, 0x0000, 0x6017, 0x0000, 0x2019, 0x0004, 0x080c,
-	0xb155, 0x00c0, 0x6010, 0x2068, 0x684c, 0xd0fc, 0x0d90, 0xa09c,
-	0x0003, 0xa39e, 0x0003, 0x0d68, 0x6003, 0x0003, 0x6106, 0x2c10,
-	0x080c, 0x1fc5, 0x080c, 0x6d62, 0x080c, 0x72a2, 0x0018, 0xa016,
-	0x080c, 0x1863, 0x0005, 0x080c, 0x7102, 0x6110, 0x81ff, 0x0158,
-	0x00d6, 0x2168, 0x080c, 0xb43c, 0x0036, 0x2019, 0x0029, 0x080c,
-	0xb155, 0x003e, 0x00de, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005,
-	0x080c, 0x7198, 0x6110, 0x81ff, 0x0158, 0x00d6, 0x2168, 0x080c,
-	0xb43c, 0x0036, 0x2019, 0x0029, 0x080c, 0xb155, 0x003e, 0x00de,
-	0x080c, 0x9ed9, 0x080c, 0x72a2, 0x0005, 0xa182, 0x0085, 0x0002,
-	0xad01, 0xacff, 0xacff, 0xad0d, 0xacff, 0xacff, 0xacff, 0x080c,
-	0x151a, 0x6003, 0x000b, 0x6106, 0x080c, 0x6cff, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x71e5, 0x012e, 0x0005, 0x0026, 0x00e6, 0x080c,
-	0xb38c, 0x0118, 0x080c, 0x86a4, 0x00d8, 0x2071, 0xbc80, 0x7224,
-	0x6212, 0x7220, 0x080c, 0xb003, 0x0118, 0x6007, 0x0086, 0x0040,
-	0x6007, 0x0087, 0x7224, 0xa296, 0xffff, 0x1110, 0x6007, 0x0086,
-	0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x080c, 0x72a2,
-	0x00ee, 0x002e, 0x0005, 0xa186, 0x0013, 0x1160, 0x6004, 0xa08a,
-	0x0085, 0x0a0c, 0x151a, 0xa08a, 0x008c, 0x1a0c, 0x151a, 0xa082,
-	0x0085, 0x00a2, 0xa186, 0x0027, 0x0130, 0xa186, 0x0014, 0x0118,
-	0x080c, 0x86ef, 0x0050, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x080c,
-	0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xad5d, 0xad5f,
-	0xad5f, 0xad5d, 0xad5d, 0xad5d, 0xad5d, 0x080c, 0x151a, 0x080c,
-	0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0xa182, 0x0085,
-	0x0a0c, 0x151a, 0xa182, 0x008c, 0x1a0c, 0x151a, 0xa182, 0x0085,
-	0x0002, 0xad78, 0xad78, 0xad78, 0xad7a, 0xad78, 0xad78, 0xad78,
-	0x080c, 0x151a, 0x0005, 0xa186, 0x0013, 0x0148, 0xa186, 0x0014,
-	0x0130, 0xa186, 0x0027, 0x0118, 0x080c, 0x86ef, 0x0030, 0x080c,
-	0x7102, 0x080c, 0x9ed9, 0x080c, 0x71e5, 0x0005, 0x0036, 0x080c,
-	0xb3f6, 0x603f, 0x0000, 0x2019, 0x000b, 0x0031, 0x601f, 0x0006,
-	0x6003, 0x0007, 0x003e, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000,
-	0x0086, 0x2c40, 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, 0x009e,
-	0x008e, 0x1578, 0x0076, 0x2c38, 0x080c, 0x825d, 0x007e, 0x1548,
-	0x6000, 0xa086, 0x0000, 0x0528, 0x601c, 0xa086, 0x0007, 0x0508,
-	0x00d6, 0x6000, 0xa086, 0x0004, 0x1150, 0x080c, 0xb3f6, 0x601f,
-	0x0007, 0x2001, 0xb8b6, 0x2004, 0x6016, 0x080c, 0x1952, 0x6010,
-	0x2068, 0x080c, 0x9d16, 0x0110, 0x080c, 0xb155, 0x00de, 0x6013,
-	0x0000, 0x080c, 0xb3f6, 0x601f, 0x0007, 0x2001, 0xb8b6, 0x2004,
-	0x6016, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6, 0x0036, 0x0156,
-	0x2079, 0xbc80, 0x7938, 0x783c, 0x080c, 0x2852, 0x15b0, 0x0016,
-	0x00c6, 0x080c, 0x501b, 0x1578, 0x001e, 0x002e, 0x0026, 0x0016,
-	0x2019, 0x0029, 0x080c, 0x8320, 0x080c, 0x6e67, 0x0076, 0x2039,
-	0x0000, 0x080c, 0x6d74, 0x007e, 0x001e, 0x0076, 0x2039, 0x0000,
-	0x080c, 0xaf3e, 0x007e, 0x080c, 0x521c, 0x0026, 0x6204, 0xa294,
-	0xff00, 0x8217, 0xa286, 0x0006, 0x0118, 0xa286, 0x0004, 0x1118,
-	0x62a0, 0x080c, 0x2d8a, 0x002e, 0x001e, 0x080c, 0x4c7e, 0x6612,
-	0x6516, 0xa006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00ce,
-	0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x0016, 0x2009, 0xb621,
-	0x2104, 0xa086, 0x0074, 0x1904, 0xae77, 0x2069, 0xbc8e, 0x690c,
-	0xa182, 0x0100, 0x06c0, 0x6908, 0xa184, 0x8000, 0x05e8, 0x2001,
-	0xb89e, 0x2004, 0xa005, 0x1160, 0x6018, 0x2070, 0x7010, 0xa084,
-	0x00ff, 0x0118, 0x7000, 0xd0f4, 0x0118, 0xa184, 0x0800, 0x0560,
-	0x6910, 0xa18a, 0x0001, 0x0610, 0x6914, 0x2069, 0xbcae, 0x6904,
-	0x81ff, 0x1198, 0x690c, 0xa182, 0x0100, 0x02a8, 0x6908, 0x81ff,
-	0x1178, 0x6910, 0xa18a, 0x0001, 0x0288, 0x6918, 0xa18a, 0x0001,
-	0x0298, 0x00d0, 0x6013, 0x0100, 0x00a0, 0x6013, 0x0300, 0x0088,
-	0x6013, 0x0500, 0x0070, 0x6013, 0x0700, 0x0058, 0x6013, 0x0900,
-	0x0040, 0x6013, 0x0b00, 0x0028, 0x6013, 0x0f00, 0x0010, 0x6013,
-	0x2d00, 0xa085, 0x0001, 0x0008, 0xa006, 0x001e, 0x00ee, 0x00de,
-	0x00ce, 0x0005, 0x00c6, 0x00d6, 0x0026, 0x0036, 0x0156, 0x6218,
-	0x2268, 0x6b04, 0xa394, 0x00ff, 0xa286, 0x0006, 0x0190, 0xa286,
-	0x0004, 0x0178, 0xa394, 0xff00, 0x8217, 0xa286, 0x0006, 0x0148,
-	0xa286, 0x0004, 0x0130, 0x00c6, 0x2d60, 0x080c, 0x502a, 0x00ce,
-	0x04c0, 0x2011, 0xbc96, 0xad98, 0x000a, 0x20a9, 0x0004, 0x080c,
-	0x9166, 0x1580, 0x2011, 0xbc9a, 0xad98, 0x0006, 0x20a9, 0x0004,
-	0x080c, 0x9166, 0x1538, 0x0046, 0x0016, 0x6aa0, 0xa294, 0x00ff,
-	0x8227, 0xa006, 0x2009, 0xb653, 0x210c, 0xd1a4, 0x0138, 0x2009,
-	0x0029, 0x080c, 0xb1a4, 0x6800, 0xc0e5, 0x6802, 0x2019, 0x0029,
-	0x080c, 0x6e67, 0x0076, 0x2039, 0x0000, 0x080c, 0x6d74, 0x2c08,
-	0x080c, 0xaf3e, 0x007e, 0x2001, 0x0007, 0x080c, 0x4f9c, 0x001e,
-	0x004e, 0xa006, 0x015e, 0x003e, 0x002e, 0x00de, 0x00ce, 0x0005,
-	0x00d6, 0x2069, 0xbc8e, 0x6800, 0xa086, 0x0800, 0x0118, 0x6013,
-	0x0000, 0x0008, 0xa006, 0x00de, 0x0005, 0x00c6, 0x00f6, 0x0016,
-	0x0026, 0x0036, 0x0156, 0x2079, 0xbc8c, 0x7930, 0x7834, 0x080c,
-	0x2852, 0x11a0, 0x080c, 0x501b, 0x1188, 0x2011, 0xbc90, 0xac98,
-	0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1140, 0x2011, 0xbc94,
-	0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x015e, 0x003e,
-	0x002e, 0x001e, 0x00fe, 0x00ce, 0x0005, 0x00c6, 0x0006, 0x0016,
-	0x0026, 0x0036, 0x0156, 0x2011, 0xbc83, 0x2204, 0x8211, 0x220c,
-	0x080c, 0x2852, 0x11a0, 0x080c, 0x501b, 0x1188, 0x2011, 0xbc96,
-	0xac98, 0x000a, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1140, 0x2011,
-	0xbc9a, 0xac98, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x015e,
-	0x003e, 0x002e, 0x001e, 0x000e, 0x00ce, 0x0005, 0x00e6, 0x00c6,
-	0x0086, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091,
-	0x8000, 0x2740, 0x2029, 0xb8ea, 0x252c, 0x2021, 0xb8f0, 0x2424,
-	0x2061, 0xbe00, 0x2071, 0xb600, 0x7648, 0x7068, 0x81ff, 0x0150,
-	0x0006, 0xa186, 0xb9f5, 0x000e, 0x0128, 0x8001, 0xa602, 0x1a04,
-	0xafbf, 0x0018, 0xa606, 0x0904, 0xafbf, 0x2100, 0xac06, 0x0904,
-	0xafb6, 0x080c, 0xb1cc, 0x0904, 0xafb6, 0x671c, 0xa786, 0x0001,
-	0x0904, 0xafda, 0xa786, 0x0004, 0x0904, 0xafda, 0xa786, 0x0007,
-	0x05e8, 0x2500, 0xac06, 0x05d0, 0x2400, 0xac06, 0x05b8, 0x080c,
-	0xb1dc, 0x15a0, 0x88ff, 0x0118, 0x6050, 0xa906, 0x1578, 0x00d6,
-	0x6000, 0xa086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1952, 0x001e,
-	0xa786, 0x0008, 0x1148, 0x080c, 0x9f14, 0x1130, 0x080c, 0x8ca5,
-	0x00de, 0x080c, 0x9ed9, 0x00d0, 0x6010, 0x2068, 0x080c, 0x9d16,
-	0x0190, 0xa786, 0x0003, 0x1528, 0x6837, 0x0103, 0x6b4a, 0x6847,
-	0x0000, 0x080c, 0xb43c, 0x0016, 0x080c, 0x9f88, 0x080c, 0x547a,
-	0x001e, 0x080c, 0x9ecd, 0x00de, 0x080c, 0x9ed9, 0xace0, 0x0018,
-	0x2001, 0xb617, 0x2004, 0xac02, 0x1210, 0x0804, 0xaf52, 0x012e,
-	0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee,
-	0x0005, 0xa786, 0x0006, 0x1150, 0xa386, 0x0005, 0x0128, 0x080c,
-	0xb43c, 0x080c, 0xb155, 0x08f8, 0x00de, 0x0c00, 0xa786, 0x000a,
-	0x0968, 0x0850, 0x080c, 0xb1dc, 0x19c8, 0x81ff, 0x09b8, 0xa180,
-	0x0001, 0x2004, 0xa086, 0x0018, 0x0130, 0xa180, 0x0001, 0x2004,
-	0xa086, 0x002d, 0x1958, 0x6000, 0xa086, 0x0002, 0x1938, 0x080c,
-	0x9f03, 0x0130, 0x080c, 0x9f14, 0x1908, 0x080c, 0x8ca5, 0x0038,
-	0x080c, 0x2cf7, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x080c,
-	0x9ed9, 0x0804, 0xafb6, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170,
-	0xa006, 0x080c, 0xb176, 0x001e, 0x0120, 0x601c, 0xa084, 0x000f,
-	0x001b, 0x00ee, 0x00ce, 0x0005, 0xb01c, 0xb01c, 0xb01c, 0xb01c,
-	0xb01c, 0xb01c, 0xb01e, 0xb01c, 0xa006, 0x0005, 0x0046, 0x0016,
-	0x7018, 0xa080, 0x0028, 0x2024, 0xa4a4, 0x00ff, 0x8427, 0x2c00,
-	0x2009, 0x0020, 0x080c, 0xb1a4, 0x001e, 0x004e, 0x0036, 0x2019,
-	0x0002, 0x080c, 0xad9c, 0x003e, 0xa085, 0x0001, 0x0005, 0x2001,
-	0x0001, 0x080c, 0x4f5d, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9,
-	0x0004, 0x2019, 0xb605, 0x2011, 0xbc96, 0x080c, 0x9166, 0x003e,
-	0x002e, 0x001e, 0x015e, 0xa005, 0x0005, 0x00f6, 0x00e6, 0x00c6,
-	0x0086, 0x0076, 0x0066, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740,
-	0x2061, 0xbe00, 0x2079, 0x0001, 0x8fff, 0x0904, 0xb0ab, 0x2071,
-	0xb600, 0x7648, 0x7068, 0x8001, 0xa602, 0x1a04, 0xb0ab, 0x88ff,
-	0x0128, 0x2800, 0xac06, 0x15b0, 0x2079, 0x0000, 0x080c, 0xb1cc,
-	0x0588, 0x2400, 0xac06, 0x0570, 0x671c, 0xa786, 0x0006, 0x1550,
-	0xa786, 0x0007, 0x0538, 0x88ff, 0x1140, 0x6018, 0xa206, 0x1510,
-	0x85ff, 0x0118, 0x6050, 0xa106, 0x11e8, 0x00d6, 0x6000, 0xa086,
-	0x0004, 0x1150, 0x080c, 0xb3f6, 0x601f, 0x0007, 0x2001, 0xb8b6,
-	0x2004, 0x6016, 0x080c, 0x1952, 0x6010, 0x2068, 0x080c, 0x9d16,
-	0x0120, 0x0046, 0x080c, 0xb155, 0x004e, 0x00de, 0x080c, 0x9ed9,
-	0x88ff, 0x1198, 0xace0, 0x0018, 0x2001, 0xb617, 0x2004, 0xac02,
-	0x1210, 0x0804, 0xb05c, 0xa006, 0x012e, 0x002e, 0x006e, 0x007e,
-	0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0xa8c5, 0x0001, 0x0ca0,
-	0x0076, 0x0056, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2c20,
-	0x2019, 0x0002, 0x6218, 0x0096, 0x2049, 0x0000, 0x080c, 0x81b7,
-	0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c, 0xb04d,
-	0x005e, 0x007e, 0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6,
-	0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x2009, 0x0000, 0x0016,
-	0x0036, 0x080c, 0x501b, 0x11b0, 0x2c10, 0x0056, 0x0086, 0x2041,
-	0x0000, 0x2508, 0x2029, 0x0001, 0x0096, 0x2049, 0x0000, 0x080c,
-	0x81b7, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c,
-	0xb04d, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb0df, 0x015e,
-	0x00ce, 0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0076, 0x0056,
-	0x6218, 0x0086, 0x2041, 0x0000, 0x2029, 0x0001, 0x2019, 0x0048,
-	0x0096, 0x2049, 0x0000, 0x080c, 0x81b7, 0x009e, 0x008e, 0x2039,
-	0x0000, 0x080c, 0x825d, 0x2c20, 0x080c, 0xb04d, 0x005e, 0x007e,
-	0x0005, 0x0026, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20,
-	0x20a9, 0x007f, 0x2009, 0x0000, 0x0016, 0x0036, 0x080c, 0x501b,
-	0x11c0, 0x2c10, 0x0086, 0x2041, 0x0000, 0x2828, 0x0046, 0x2021,
-	0x0001, 0x080c, 0xb3d8, 0x004e, 0x0096, 0x2049, 0x0000, 0x080c,
-	0x81b7, 0x009e, 0x008e, 0x2039, 0x0000, 0x080c, 0x825d, 0x080c,
-	0xb04d, 0x003e, 0x001e, 0x8108, 0x1f04, 0xb12c, 0x015e, 0x00ce,
-	0x007e, 0x005e, 0x004e, 0x002e, 0x0005, 0x0016, 0x00f6, 0x3800,
-	0xd08c, 0x0130, 0xad82, 0x1000, 0x02b0, 0xad82, 0xb600, 0x0230,
-	0xad82, 0xee00, 0x0280, 0xad82, 0xffff, 0x1268, 0x6800, 0xa07d,
-	0x0138, 0x6803, 0x0000, 0x6b52, 0x080c, 0x547a, 0x2f68, 0x0cb0,
-	0x6b52, 0x080c, 0x547a, 0x00fe, 0x001e, 0x0005, 0x00e6, 0x0046,
-	0x0036, 0x2061, 0xbe00, 0xa005, 0x1138, 0x2071, 0xb600, 0x7448,
-	0x7068, 0x8001, 0xa402, 0x12d8, 0x2100, 0xac06, 0x0168, 0x6000,
-	0xa086, 0x0000, 0x0148, 0x6008, 0xa206, 0x1130, 0x6018, 0xa1a0,
-	0x0006, 0x2424, 0xa406, 0x0140, 0xace0, 0x0018, 0x2001, 0xb617,
-	0x2004, 0xac02, 0x1220, 0x0c40, 0xa085, 0x0001, 0x0008, 0xa006,
-	0x003e, 0x004e, 0x00ee, 0x0005, 0x00d6, 0x0006, 0x080c, 0x15fd,
-	0x000e, 0x090c, 0x151a, 0x6837, 0x010d, 0x685e, 0x0026, 0x2010,
-	0x080c, 0x9d06, 0x2001, 0x0000, 0x0120, 0x2200, 0xa080, 0x0014,
-	0x2004, 0x002e, 0x684a, 0x6956, 0x6c46, 0x684f, 0x0000, 0x2001,
-	0xb8be, 0x2004, 0x6852, 0xa006, 0x68b2, 0x6802, 0x683a, 0x685a,
-	0x080c, 0x547a, 0x00de, 0x0005, 0x6700, 0xa786, 0x0000, 0x0158,
-	0xa786, 0x0001, 0x0140, 0xa786, 0x000a, 0x0128, 0xa786, 0x0009,
-	0x0110, 0xa085, 0x0001, 0x0005, 0x00e6, 0x6018, 0x2070, 0x70a0,
-	0xa206, 0x00ee, 0x0005, 0x0016, 0x6004, 0xa08e, 0x001e, 0x11a0,
-	0x8007, 0x6130, 0xa18c, 0x00ff, 0xa105, 0x6032, 0x6007, 0x0085,
-	0x6003, 0x000b, 0x601f, 0x0005, 0x2001, 0xb8b7, 0x2004, 0x6016,
-	0x080c, 0x6cff, 0x080c, 0x71e5, 0x001e, 0x0005, 0xe000, 0xe000,
-	0x0005, 0x6020, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c, 0x9ff1,
-	0x0030, 0x080c, 0xb3f6, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x0005,
-	0xa280, 0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb21f, 0xb21f,
-	0xb21f, 0xb224, 0xb21f, 0xb221, 0xb221, 0xb21f, 0xb221, 0xa006,
-	0x0005, 0x00c6, 0x2260, 0x00ce, 0xa085, 0x0001, 0x0005, 0xa280,
-	0x0007, 0x2004, 0xa084, 0x000f, 0x0002, 0xb236, 0xb236, 0xb236,
-	0xb236, 0xb236, 0xb236, 0xb241, 0xb236, 0xb236, 0x6007, 0x003b,
-	0x602b, 0x0009, 0x6013, 0x2a00, 0x6003, 0x0001, 0x080c, 0x6cff,
-	0x0005, 0x00c6, 0x2260, 0x080c, 0xb3f6, 0x603f, 0x0000, 0x6020,
-	0xc0f4, 0xc0cc, 0x6022, 0x6037, 0x0000, 0x00ce, 0x00d6, 0x2268,
-	0xa186, 0x0007, 0x1904, 0xb29c, 0x6810, 0xa005, 0x0138, 0xa080,
-	0x0013, 0x2004, 0xd0fc, 0x1110, 0x00de, 0x08c0, 0x6007, 0x003a,
-	0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00c6, 0x2d60,
-	0x6100, 0xa186, 0x0002, 0x1904, 0xb325, 0x6010, 0xa005, 0x1138,
-	0x6000, 0xa086, 0x0007, 0x190c, 0x151a, 0x0804, 0xb325, 0xa08c,
-	0xf000, 0x1130, 0x0028, 0x2068, 0x6800, 0xa005, 0x1de0, 0x2d00,
-	0xa080, 0x0013, 0x2004, 0xa084, 0x0003, 0xa086, 0x0002, 0x1180,
-	0x6010, 0x2068, 0x684c, 0xc0dc, 0xc0f4, 0x684e, 0x6850, 0xc0f4,
-	0xc0fc, 0x6852, 0x2009, 0x0043, 0x080c, 0xac12, 0x0804, 0xb325,
-	0x2009, 0x0041, 0x0804, 0xb31f, 0xa186, 0x0005, 0x15f0, 0x6810,
-	0xa080, 0x0013, 0x2004, 0xd0bc, 0x1118, 0x00de, 0x0804, 0xb236,
-	0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x151a, 0x0804, 0xb254, 0x6007,
-	0x003a, 0x6003, 0x0001, 0x080c, 0x6cff, 0x080c, 0x71e5, 0x00c6,
-	0x2d60, 0x6100, 0xa186, 0x0002, 0x0120, 0xa186, 0x0004, 0x1904,
-	0xb325, 0x2071, 0xb924, 0x7000, 0xa086, 0x0003, 0x1128, 0x7004,
-	0xac06, 0x1110, 0x7003, 0x0000, 0x6810, 0xa080, 0x0013, 0x200c,
-	0xc1f4, 0xc1dc, 0x2102, 0x8000, 0x200c, 0xc1f4, 0xc1fc, 0xc1bc,
-	0x2102, 0x2009, 0x0042, 0x0804, 0xb31f, 0x0036, 0x00d6, 0x00d6,
-	0x080c, 0x15fd, 0x003e, 0x090c, 0x151a, 0x6837, 0x010d, 0x6803,
-	0x0000, 0x683b, 0x0000, 0x685b, 0x0000, 0x6b5e, 0x6857, 0x0045,
-	0x2c00, 0x6862, 0x6034, 0x6872, 0x2360, 0x6020, 0xc0dd, 0x6022,
-	0x6018, 0xa080, 0x0028, 0x2004, 0xa084, 0x00ff, 0x8007, 0x6350,
-	0x6b4a, 0x6846, 0x684f, 0x0000, 0x6853, 0x0000, 0x6d6a, 0x6e66,
-	0x686f, 0x0001, 0x080c, 0x547a, 0x2019, 0x0045, 0x6008, 0x2068,
-	0x080c, 0xad9c, 0x2d00, 0x600a, 0x601f, 0x0006, 0x6003, 0x0007,
-	0x6017, 0x0000, 0x603f, 0x0000, 0x00de, 0x003e, 0x0038, 0x603f,
-	0x0000, 0x6003, 0x0007, 0x080c, 0xac12, 0x00ce, 0x00de, 0x0005,
-	0xa186, 0x0013, 0x1128, 0x6004, 0xa082, 0x0085, 0x2008, 0x00c2,
-	0xa186, 0x0027, 0x1178, 0x080c, 0x7102, 0x0036, 0x00d6, 0x6010,
-	0x2068, 0x2019, 0x0004, 0x080c, 0xb155, 0x00de, 0x003e, 0x080c,
-	0x71e5, 0x0005, 0xa186, 0x0014, 0x0d70, 0x080c, 0x86ef, 0x0005,
-	0xb351, 0xb34f, 0xb34f, 0xb34f, 0xb34f, 0xb34f, 0xb351, 0x080c,
-	0x151a, 0x080c, 0x7102, 0x6003, 0x000c, 0x080c, 0x71e5, 0x0005,
-	0xa182, 0x008c, 0x1220, 0xa182, 0x0085, 0x0208, 0x001a, 0x080c,
-	0x86ef, 0x0005, 0xb369, 0xb369, 0xb369, 0xb369, 0xb36b, 0xb389,
-	0xb369, 0x080c, 0x151a, 0x00d6, 0x2c68, 0x080c, 0x864e, 0x01a0,
-	0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0xbc8e, 0x210c, 0x6136,
-	0x2009, 0xbc8f, 0x210c, 0x613a, 0x600b, 0xffff, 0x6918, 0x611a,
-	0x601f, 0x0004, 0x080c, 0x6cff, 0x2d60, 0x080c, 0x86a4, 0x00de,
-	0x0005, 0x080c, 0x86a4, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000,
-	0xd0ec, 0x00ee, 0x0005, 0x6010, 0xa08c, 0xf000, 0x0904, 0xb3d7,
-	0xa080, 0x0013, 0x200c, 0xd1ec, 0x05d0, 0x2001, 0xb672, 0x2004,
-	0xd0ec, 0x05a8, 0x6003, 0x0002, 0x6020, 0xc0e5, 0x6022, 0xd1ac,
-	0x0180, 0x00f6, 0x2c78, 0x080c, 0x5373, 0x00fe, 0x0150, 0x2001,
-	0xb8b8, 0x2004, 0x603e, 0x2009, 0xb672, 0x210c, 0xd1f4, 0x11e8,
-	0x0080, 0x2009, 0xb672, 0x210c, 0xd1f4, 0x0128, 0x6020, 0xc0e4,
-	0x6022, 0xa006, 0x00a0, 0x2001, 0xb8b8, 0x200c, 0x8103, 0xa100,
-	0x603e, 0x6018, 0xa088, 0x002b, 0x2104, 0xa005, 0x0118, 0xa088,
-	0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000, 0xa085, 0x0001, 0x0005,
-	0x0016, 0x00c6, 0x00e6, 0x6150, 0xa2f0, 0x002b, 0x2e04, 0x2060,
-	0x8cff, 0x0180, 0x84ff, 0x1118, 0x6050, 0xa106, 0x1138, 0x600c,
-	0x2072, 0x080c, 0x6b61, 0x080c, 0x86a4, 0x0010, 0xacf0, 0x0003,
-	0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6, 0x6018,
-	0xa0e8, 0x002b, 0x2d04, 0xa005, 0x0140, 0xac06, 0x0120, 0x2d04,
-	0xa0e8, 0x0003, 0x0cb8, 0x600c, 0x206a, 0x00de, 0x0005, 0x0026,
-	0x0036, 0x0156, 0x2011, 0xb628, 0x2204, 0xa084, 0x00ff, 0x2019,
-	0xbc8e, 0x2334, 0xa636, 0x11d8, 0x8318, 0x2334, 0x2204, 0xa084,
-	0xff00, 0xa636, 0x11a0, 0x2011, 0xbc90, 0x6018, 0xa098, 0x000a,
-	0x20a9, 0x0004, 0x080c, 0x9166, 0x1150, 0x2011, 0xbc94, 0x6018,
-	0xa098, 0x0006, 0x20a9, 0x0004, 0x080c, 0x9166, 0x1100, 0x015e,
-	0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0xb600, 0x080c, 0x4c28,
-	0x080c, 0x2aed, 0x00ee, 0x0005, 0x00e6, 0x6018, 0x2070, 0x7000,
-	0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005, 0x6850, 0xc0e5, 0x6852,
-	0x0005, 0x00e6, 0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026,
-	0x0016, 0x0126, 0x2091, 0x8000, 0x2029, 0xb8ea, 0x252c, 0x2021,
-	0xb8f0, 0x2424, 0x2061, 0xbe00, 0x2071, 0xb600, 0x7648, 0x7068,
-	0xa606, 0x0578, 0x671c, 0xa786, 0x0001, 0x0118, 0xa786, 0x0008,
-	0x1500, 0x2500, 0xac06, 0x01e8, 0x2400, 0xac06, 0x01d0, 0x080c,
-	0xb1cc, 0x01b8, 0x080c, 0xb1dc, 0x11a0, 0x6000, 0xa086, 0x0004,
-	0x1120, 0x0016, 0x080c, 0x1952, 0x001e, 0x080c, 0x9f03, 0x1110,
-	0x080c, 0x2cf7, 0x080c, 0x9f14, 0x1110, 0x080c, 0x8ca5, 0x080c,
-	0x9ed9, 0xace0, 0x0018, 0x2001, 0xb617, 0x2004, 0xac02, 0x1208,
-	0x0858, 0x012e, 0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e,
-	0x00ce, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091,
-	0x8000, 0x2071, 0xb640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036,
-	0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500,
-	0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130,
-	0xa08e, 0x0005, 0x0118, 0x2071, 0xb64a, 0x04c9, 0x001e, 0x00ee,
-	0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091,
-	0x8000, 0x2071, 0xb640, 0xd5a4, 0x0118, 0x7034, 0x8000, 0x7036,
-	0xd5b4, 0x0118, 0x7030, 0x8000, 0x7032, 0xd5ac, 0x0178, 0x2500,
-	0xa084, 0x0007, 0xa08e, 0x0003, 0x0148, 0xa08e, 0x0004, 0x0130,
-	0xa08e, 0x0005, 0x0118, 0x2071, 0xb64a, 0x0089, 0x001e, 0x00ee,
-	0x000e, 0x012e, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000,
-	0x2071, 0xb642, 0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e04,
-	0x8000, 0x2072, 0x1220, 0x8e70, 0x2e04, 0x8000, 0x2072, 0x0005,
-	0x00e6, 0x2071, 0xb640, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071,
-	0xb644, 0x0c69, 0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091,
-	0x8000, 0x2071, 0xb640, 0x7044, 0x8000, 0x7046, 0x00ee, 0x000e,
-	0x012e, 0x0005, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020,
-	0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000,
-	0x4000, 0x8000, 0xdb06
-};
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2200tp_length01 = 0xa52b;
-#else
-unsigned short risc_code_length01 = 0xa52b;
-#endif
-
diff --git a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c
deleted file mode 100644
index e7a93dd..0000000
--- a/drivers/scsi/qla2xxx/ql2300.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (C)  2003 Christoph Hellwig.
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "qla_def.h"
-
-static char qla_driver_name[] = "qla2300";
-
-extern unsigned char  fw2300ipx_version[];
-extern unsigned char  fw2300ipx_version_str[];
-extern unsigned short fw2300ipx_addr01;
-extern unsigned short fw2300ipx_code01[];
-extern unsigned short fw2300ipx_length01;
-
-static struct qla_fw_info qla_fw_tbl[] = {
-	{
-		.addressing	= FW_INFO_ADDR_NORMAL,
-		.fwcode		= &fw2300ipx_code01[0],
-		.fwlen		= &fw2300ipx_length01,
-		.fwstart	= &fw2300ipx_addr01,
-	},
-	{ FW_INFO_ADDR_NOMORE, },
-};
-
-static struct qla_board_info qla_board_tbl[] = {
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP2300",
-		.fw_info	= qla_fw_tbl,
-	},
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP2312",
-		.fw_info	= qla_fw_tbl,
-	},
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP6312",
-		.fw_info	= qla_fw_tbl,
-	},
-};
-
-static struct pci_device_id qla2300_pci_tbl[] = {
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2300,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[0],
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2312,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[1],
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP6312,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[2],
-	},
-	{0, 0},
-};
-MODULE_DEVICE_TABLE(pci, qla2300_pci_tbl);
-
-static int __devinit
-qla2300_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	return qla2x00_probe_one(pdev,
-	    (struct qla_board_info *)id->driver_data);
-}
-
-static void __devexit
-qla2300_remove_one(struct pci_dev *pdev)
-{
-	qla2x00_remove_one(pdev);
-}
-
-static struct pci_driver qla2300_pci_driver = {
-	.name		= "qla2300",
-	.id_table	= qla2300_pci_tbl,
-	.probe		= qla2300_probe_one,
-	.remove		= __devexit_p(qla2300_remove_one),
-};
-
-static int __init
-qla2300_init(void)
-{
-	return pci_module_init(&qla2300_pci_driver);
-}
-
-static void __exit
-qla2300_exit(void)
-{
-	pci_unregister_driver(&qla2300_pci_driver);
-}
-
-module_init(qla2300_init);
-module_exit(qla2300_exit);
-
-MODULE_AUTHOR("QLogic Corporation");
-MODULE_DESCRIPTION("QLogic ISP23xx FC-SCSI Host Bus Adapter driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2300_fw.c b/drivers/scsi/qla2xxx/ql2300_fw.c
deleted file mode 100644
index b8ce7fe..0000000
--- a/drivers/scsi/qla2xxx/ql2300_fw.c
+++ /dev/null
@@ -1,7746 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-
-/*
- *	Firmware Version 3.03.20 (15:39 Feb 01, 2006)
- */
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2300ipx_version = 3*1024+3;
-#else
-unsigned short risc_code_version = 3*1024+3;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned char fw2300ipx_version_str[] = {3, 3,20};
-#else
-unsigned char firmware_version[] = {3, 3,20};
-#endif
-
-#ifdef UNIQUE_FW_NAME
-#define fw2300ipx_VERSION_STRING "3.03.20"
-#else
-#define FW_VERSION_STRING "3.03.20"
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2300ipx_addr01 = 0x0800 ;
-#else
-unsigned short risc_code_addr01 = 0x0800 ;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2300ipx_code01[] = { 
-#else
-unsigned short risc_code01[] = { 
-#endif
-	0x0470, 0x0000, 0x0000, 0xf091, 0x0000, 0x0003, 0x0003, 0x0014,
-	0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030,
-	0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
-	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972,
-	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
-	0x332e, 0x3033, 0x2e32, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9,
-	0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f,
-	0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001,
-	0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000,
-	0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f,
-	0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091,
-	0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00,
-	0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001,
-	0x0000, 0x20c1, 0x0004, 0x20c9, 0x1bff, 0x2059, 0x0000, 0x2b78,
-	0x7883, 0x0004, 0x2089, 0x2d93, 0x2051, 0x1800, 0x2a70, 0x20e1,
-	0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e52, 0x2029,
-	0x4d00, 0x2031, 0xffff, 0x2039, 0x4cd0, 0x2021, 0x0200, 0x20e9,
-	0x0001, 0x20a1, 0x0000, 0x20a9, 0x0800, 0x900e, 0x4104, 0x20e9,
-	0x0001, 0x20a1, 0x1000, 0x900e, 0x2001, 0x0cc0, 0x9084, 0x0fff,
-	0x20a8, 0x4104, 0x2001, 0x0000, 0x9086, 0x0000, 0x0120, 0x21a8,
-	0x4104, 0x8001, 0x1de0, 0x756e, 0x7672, 0x776a, 0x7476, 0x747a,
-	0x00e6, 0x2071, 0x1ad1, 0x2472, 0x00ee, 0x20a1, 0x1cd0, 0x7170,
-	0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x000f, 0x2001, 0x0001,
-	0x9112, 0x900e, 0x21a8, 0x4104, 0x8211, 0x1de0, 0x7170, 0x3400,
-	0x8001, 0x9102, 0x0120, 0x0218, 0x20a8, 0x900e, 0x4104, 0x2009,
-	0x1800, 0x810d, 0x810d, 0x810d, 0x810d, 0x810d, 0x918c, 0x001f,
-	0x2001, 0x0001, 0x9112, 0x20e9, 0x0001, 0x20a1, 0x0800, 0x900e,
-	0x20a9, 0x0800, 0x4104, 0x8211, 0x1dd8, 0x080c, 0x0f26, 0x080c,
-	0x613c, 0x080c, 0xb269, 0x080c, 0x10dd, 0x080c, 0x12fc, 0x080c,
-	0x1bd7, 0x080c, 0x0d57, 0x080c, 0x1062, 0x080c, 0x34b6, 0x080c,
-	0x7946, 0x080c, 0x6b7c, 0x080c, 0x8a69, 0x080c, 0x874a, 0x080c,
-	0x24b7, 0x080c, 0x93a5, 0x080c, 0x8066, 0x080c, 0x22e8, 0x080c,
-	0x241c, 0x080c, 0x24ac, 0x2091, 0x3009, 0x7883, 0x0000, 0x1004,
-	0x091f, 0x7880, 0x9086, 0x0002, 0x1190, 0x7883, 0x4000, 0x7837,
-	0x4000, 0x7833, 0x0010, 0x0e04, 0x0913, 0x2091, 0x5000, 0x2091,
-	0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2071,
-	0x1800, 0x7003, 0x0000, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003,
-	0x1178, 0x080c, 0x4d09, 0x080c, 0x34dd, 0x080c, 0x79b7, 0x080c,
-	0x7122, 0x080c, 0x8b50, 0x080c, 0x8776, 0x080c, 0x2cdd, 0x0c58,
-	0x000b, 0x0c78, 0x0944, 0x0945, 0x0ae0, 0x0942, 0x0ba0, 0x0d56,
-	0x0d56, 0x0d56, 0x080c, 0x0dc5, 0x0005, 0x0126, 0x00f6, 0x2091,
-	0x8000, 0x7000, 0x9086, 0x0001, 0x1904, 0x0ab3, 0x080c, 0x0e94,
-	0x080c, 0x7637, 0x0150, 0x080c, 0x765a, 0x15a0, 0x2079, 0x0100,
-	0x7828, 0x9085, 0x1800, 0x782a, 0x0468, 0x080c, 0x7563, 0x7000,
-	0x9086, 0x0001, 0x1904, 0x0ab3, 0x7098, 0x9086, 0x0029, 0x1904,
-	0x0ab3, 0x080c, 0x8733, 0x080c, 0x8725, 0x2001, 0x0161, 0x2003,
-	0x0001, 0x2079, 0x0100, 0x7827, 0xffff, 0x7a28, 0x9295, 0x5e2f,
-	0x7a2a, 0x2011, 0x74b2, 0x080c, 0x883d, 0x2011, 0x74a5, 0x080c,
-	0x8917, 0x2011, 0x5f97, 0x080c, 0x883d, 0x2011, 0x8030, 0x901e,
-	0x7396, 0x04d0, 0x080c, 0x583f, 0x2079, 0x0100, 0x7844, 0x9005,
-	0x1904, 0x0ab3, 0x2011, 0x5f97, 0x080c, 0x883d, 0x2011, 0x74b2,
-	0x080c, 0x883d, 0x2011, 0x74a5, 0x080c, 0x8917, 0x2001, 0x0265,
-	0x2001, 0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842,
-	0x2001, 0x19a7, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100,
-	0x080c, 0x60e4, 0x00ce, 0x0804, 0x0ab3, 0x780f, 0x006b, 0x7a28,
-	0x080c, 0x763f, 0x0118, 0x9295, 0x5e2f, 0x0010, 0x9295, 0x402f,
-	0x7a2a, 0x2011, 0x8010, 0x73d8, 0x2001, 0x19a8, 0x2003, 0x0001,
-	0x080c, 0x2b82, 0x080c, 0x4c44, 0x7248, 0xc284, 0x724a, 0x2001,
-	0x180c, 0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x080c, 0xa9b0, 0x2011,
-	0x0004, 0x080c, 0xd0e8, 0x080c, 0x6947, 0x080c, 0x7637, 0x1120,
-	0x080c, 0x2bc6, 0x02e0, 0x0400, 0x080c, 0x60eb, 0x0140, 0x7097,
-	0x0001, 0x70d3, 0x0000, 0x080c, 0x5a11, 0x0804, 0x0ab3, 0x080c,
-	0x57d5, 0xd094, 0x0188, 0x2011, 0x180c, 0x2204, 0xc0cd, 0x2012,
-	0x080c, 0x57d9, 0xd0d4, 0x1118, 0x080c, 0x2bc6, 0x1270, 0x2011,
-	0x180c, 0x2204, 0xc0bc, 0x00a8, 0x080c, 0x57d9, 0xd0d4, 0x1db8,
-	0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060, 0x2011, 0x180c, 0x2204,
-	0xc0bd, 0x2012, 0x080c, 0x6a9b, 0x1128, 0xd0a4, 0x0118, 0x2204,
-	0xc0fd, 0x2012, 0x080c, 0x6a61, 0x0120, 0x7a0c, 0xc2b4, 0x7a0e,
-	0x00a8, 0x707f, 0x0000, 0x080c, 0x7637, 0x1130, 0x70b0, 0x9005,
-	0x1168, 0x080c, 0xd52b, 0x0050, 0x080c, 0xd52b, 0x70dc, 0xd09c,
-	0x1128, 0x70b0, 0x9005, 0x0110, 0x080c, 0x60c1, 0x70e7, 0x0000,
-	0x70e3, 0x0000, 0x70a7, 0x0000, 0x080c, 0x2bce, 0x0228, 0x2011,
-	0x0101, 0x2204, 0xc0c4, 0x2012, 0x72dc, 0x080c, 0x7637, 0x1178,
-	0x9016, 0x0016, 0x080c, 0x298b, 0x2019, 0x196d, 0x211a, 0x001e,
-	0x705f, 0xffff, 0x7063, 0x00ef, 0x7083, 0x0000, 0x0020, 0x2019,
-	0x196d, 0x201b, 0x0000, 0x2079, 0x1847, 0x7804, 0xd0ac, 0x0108,
-	0xc295, 0x72de, 0x080c, 0x7637, 0x0118, 0x9296, 0x0004, 0x0548,
-	0x2011, 0x0001, 0x080c, 0xd0e8, 0x70ab, 0x0000, 0x70af, 0xffff,
-	0x7003, 0x0002, 0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085,
-	0x0003, 0x782a, 0x00fe, 0x080c, 0x3000, 0x2011, 0x0005, 0x080c,
-	0xaabf, 0x080c, 0x9ab1, 0x080c, 0x7637, 0x0148, 0x00c6, 0x2061,
-	0x0100, 0x0016, 0x080c, 0x298b, 0x61e2, 0x001e, 0x00ce, 0x012e,
-	0x0420, 0x70ab, 0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x00f6,
-	0x2079, 0x0100, 0x7827, 0x0003, 0x7828, 0x9085, 0x0003, 0x782a,
-	0x00fe, 0x2011, 0x0005, 0x080c, 0xaabf, 0x080c, 0x9ab1, 0x080c,
-	0x7637, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c, 0x298b,
-	0x61e2, 0x001e, 0x00ce, 0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6,
-	0x080c, 0x7637, 0x1118, 0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782,
-	0x080c, 0x7637, 0x1110, 0x900e, 0x0010, 0x2009, 0x007e, 0x86ff,
-	0x0138, 0x9180, 0x1000, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc,
-	0x090c, 0x334c, 0x8108, 0x1f04, 0x0ac7, 0x707f, 0x0000, 0x7080,
-	0x9084, 0x00ff, 0x7082, 0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005,
-	0x00b6, 0x0126, 0x2091, 0x8000, 0x7000, 0x9086, 0x0002, 0x1904,
-	0x0b9d, 0x70ac, 0x9086, 0xffff, 0x0130, 0x080c, 0x3000, 0x080c,
-	0x9ab1, 0x0804, 0x0b9d, 0x70dc, 0xd0ac, 0x1110, 0xd09c, 0x0558,
-	0xd084, 0x0548, 0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e,
-	0xd08c, 0x0508, 0x080c, 0x33af, 0x11d0, 0x70e0, 0x9086, 0xffff,
-	0x01b0, 0x080c, 0x31bc, 0x080c, 0x9ab1, 0x70dc, 0xd094, 0x1904,
-	0x0b9d, 0x2011, 0x0001, 0x080c, 0xd7e3, 0x0110, 0x2011, 0x0003,
-	0x901e, 0x080c, 0x31f6, 0x080c, 0x9ab1, 0x0804, 0x0b9d, 0x70e4,
-	0x9005, 0x1904, 0x0b9d, 0x70a8, 0x9005, 0x1904, 0x0b9d, 0x70dc,
-	0xd0a4, 0x0118, 0xd0b4, 0x0904, 0x0b9d, 0x080c, 0x6a61, 0x1904,
-	0x0b9d, 0x080c, 0x6ab4, 0x1904, 0x0b9d, 0x080c, 0x6a9b, 0x01c0,
-	0x0156, 0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724,
-	0x1118, 0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b3d,
-	0x00ce, 0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0b9d,
-	0x0006, 0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x2011, 0x19b4,
-	0x080c, 0x0f96, 0x2011, 0x19ce, 0x080c, 0x0f96, 0x7030, 0xc08c,
-	0x7032, 0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x0e76, 0x9006,
-	0x080c, 0x281c, 0x080c, 0x33af, 0x0118, 0x080c, 0x4de1, 0x0050,
-	0x0036, 0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4dfb,
-	0x004e, 0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x765a, 0x0150,
-	0x080c, 0x7637, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084,
-	0xffdf, 0x782a, 0x00fe, 0x2001, 0x19e9, 0x2004, 0x9086, 0x0005,
-	0x1120, 0x2011, 0x0000, 0x080c, 0xaabf, 0x2011, 0x0000, 0x080c,
-	0xaac9, 0x080c, 0x9ab1, 0x080c, 0x9bd3, 0x012e, 0x00be, 0x0005,
-	0x0016, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100,
-	0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x60aa,
-	0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0110, 0x7827,
-	0x0040, 0xd19c, 0x0110, 0x7827, 0x0008, 0x0006, 0x0036, 0x0156,
-	0x7954, 0xd1ac, 0x1904, 0x0c2d, 0x2001, 0x19a8, 0x2004, 0x9005,
-	0x1518, 0x080c, 0x2c49, 0x1148, 0x2001, 0x0001, 0x080c, 0x2bb1,
-	0x2001, 0x0001, 0x080c, 0x2b94, 0x00b8, 0x080c, 0x2c51, 0x1138,
-	0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x0068, 0x080c,
-	0x2c59, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108, 0x0020,
-	0x080c, 0x29bf, 0x0804, 0x0d0d, 0x080c, 0x7648, 0x0148, 0x080c,
-	0x765a, 0x1118, 0x080c, 0x7941, 0x0050, 0x080c, 0x763f, 0x0dd0,
-	0x080c, 0x793c, 0x080c, 0x7932, 0x080c, 0x7563, 0x0058, 0x080c,
-	0x7637, 0x0140, 0x2009, 0x00f8, 0x080c, 0x60aa, 0x7843, 0x0090,
-	0x7843, 0x0010, 0x20a9, 0x09c4, 0x7820, 0xd09c, 0x1138, 0x080c,
-	0x7637, 0x0138, 0x7824, 0xd0ac, 0x1904, 0x0d12, 0x1f04, 0x0c0c,
-	0x0070, 0x7824, 0x080c, 0x7651, 0x0118, 0xd0ac, 0x1904, 0x0d12,
-	0x9084, 0x1800, 0x0d98, 0x7003, 0x0001, 0x0804, 0x0d12, 0x2001,
-	0x0001, 0x080c, 0x281c, 0x0804, 0x0d25, 0x2001, 0x19a8, 0x2004,
-	0x9005, 0x1518, 0x080c, 0x2c49, 0x1148, 0x2001, 0x0001, 0x080c,
-	0x2bb1, 0x2001, 0x0001, 0x080c, 0x2b94, 0x00b8, 0x080c, 0x2c51,
-	0x1138, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x0068,
-	0x080c, 0x2c59, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108,
-	0x0020, 0x080c, 0x29bf, 0x0804, 0x0d0d, 0x7850, 0x9085, 0x0040,
-	0x7852, 0x7938, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c, 0x2c61,
-	0x9085, 0x2000, 0x7852, 0x793a, 0x20a9, 0x0046, 0x1d04, 0x0c66,
-	0x080c, 0x88f7, 0x1f04, 0x0c66, 0x7850, 0x9085, 0x0400, 0x9084,
-	0xdfbf, 0x7852, 0x793a, 0x080c, 0x7648, 0x0148, 0x080c, 0x765a,
-	0x1118, 0x080c, 0x7941, 0x0050, 0x080c, 0x763f, 0x0dd0, 0x080c,
-	0x793c, 0x080c, 0x7932, 0x080c, 0x7563, 0x0020, 0x2009, 0x00f8,
-	0x080c, 0x60aa, 0x20a9, 0x0028, 0xa001, 0x1f04, 0x0c8c, 0x7850,
-	0x9085, 0x1400, 0x7852, 0x080c, 0x7637, 0x0120, 0x7843, 0x0090,
-	0x7843, 0x0010, 0x2021, 0xe678, 0x2019, 0xea60, 0x0d0c, 0x88f7,
-	0x7820, 0xd09c, 0x1588, 0x080c, 0x7637, 0x0904, 0x0cf2, 0x7824,
-	0xd0ac, 0x1904, 0x0d12, 0x080c, 0x765a, 0x1530, 0x0046, 0x2021,
-	0x0320, 0x8421, 0x1df0, 0x004e, 0x7827, 0x1800, 0x080c, 0x2c61,
-	0x7824, 0x9084, 0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001,
-	0x1810, 0x2004, 0x9084, 0x9000, 0x0110, 0x080c, 0x0d33, 0x8421,
-	0x1158, 0x1d04, 0x0ccd, 0x080c, 0x88f7, 0x080c, 0x793c, 0x080c,
-	0x7932, 0x7003, 0x0001, 0x04f0, 0x8319, 0x1940, 0x1d04, 0x0cda,
-	0x080c, 0x88f7, 0x2009, 0x199b, 0x2104, 0x9005, 0x0118, 0x8001,
-	0x200a, 0x1178, 0x200b, 0x000a, 0x7827, 0x0048, 0x20a9, 0x0002,
-	0x080c, 0x2c42, 0x7924, 0x080c, 0x2c61, 0xd19c, 0x0110, 0x080c,
-	0x2b82, 0x00d8, 0x080c, 0x7648, 0x1140, 0x94a2, 0x03e8, 0x1128,
-	0x080c, 0x760f, 0x7003, 0x0001, 0x00a8, 0x7827, 0x1800, 0x080c,
-	0x2c61, 0x7824, 0x080c, 0x7651, 0x0110, 0xd0ac, 0x1158, 0x9084,
-	0x1800, 0x0950, 0x7003, 0x0001, 0x0028, 0x2001, 0x0001, 0x080c,
-	0x281c, 0x0078, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904,
-	0x918d, 0x0002, 0x7906, 0x7827, 0x0048, 0x7828, 0x9085, 0x0028,
-	0x782a, 0x7850, 0x9085, 0x0400, 0x7852, 0x2001, 0x19a8, 0x2003,
-	0x0000, 0x9006, 0x78f2, 0x015e, 0x003e, 0x000e, 0x012e, 0x00fe,
-	0x004e, 0x001e, 0x0005, 0x0006, 0x0016, 0x0036, 0x0046, 0x00b6,
-	0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0069, 0x0d0c, 0x88f7,
-	0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e,
-	0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, 0x7004, 0x9086,
-	0x0001, 0x1110, 0x080c, 0x34dd, 0x00ee, 0x0005, 0x0005, 0x2a70,
-	0x2061, 0x19ac, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0014,
-	0x600f, 0x0137, 0x2001, 0x197c, 0x900e, 0x2102, 0x7196, 0x2001,
-	0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008,
-	0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xd52b, 0x70eb,
-	0x00c0, 0x2061, 0x196c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800,
-	0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f,
-	0x07d0, 0x2061, 0x1974, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f,
-	0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061,
-	0x1989, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f,
-	0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x6724,
-	0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4,
-	0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210,
-	0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000,
-	0x2079, 0x0000, 0x000e, 0x00f6, 0x0010, 0x2091, 0x8000, 0x0e04,
-	0x0dc7, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000,
-	0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e,
-	0x7886, 0x3900, 0x789a, 0x00d6, 0x2069, 0x0300, 0x6818, 0x78ae,
-	0x681c, 0x78b2, 0x2001, 0x1a09, 0x2004, 0x78b6, 0x2001, 0x1a86,
-	0x2004, 0x78ba, 0x6808, 0x78be, 0x00de, 0x7833, 0x0012, 0x2091,
-	0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069,
-	0x1aa9, 0x7a08, 0x226a, 0x2069, 0x1aaa, 0x7a18, 0x226a, 0x8d68,
-	0x7a1c, 0x226a, 0x782c, 0x2019, 0x1ab7, 0x201a, 0x2019, 0x1aba,
-	0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318,
-	0x9386, 0x1acf, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011,
-	0xdead, 0x2019, 0x1ab8, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803,
-	0x0000, 0x2069, 0x1a89, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28,
-	0x226a, 0x8d68, 0x8318, 0x1f04, 0x0e26, 0x002e, 0x003e, 0x00de,
-	0x015e, 0x2079, 0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001,
-	0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a1c, 0x2004, 0x9005,
-	0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a,
-	0x2003, 0x0002, 0x2003, 0x1001, 0x080c, 0x57e4, 0x1108, 0x0099,
-	0x0cd8, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003, 0x2004, 0x9084,
-	0x0600, 0x1118, 0x918d, 0x2800, 0x0010, 0x918d, 0x2000, 0x2001,
-	0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011, 0x0080, 0x080c,
-	0x0eee, 0x20a9, 0x0900, 0x080c, 0x0f0f, 0x2011, 0x0040, 0x080c,
-	0x0eee, 0x20a9, 0x0900, 0x080c, 0x0f0f, 0x0c78, 0x0026, 0x080c,
-	0x0efb, 0x1118, 0x2011, 0x0040, 0x0098, 0x2011, 0x010e, 0x2214,
-	0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010,
-	0x2011, 0x6840, 0xd0e4, 0x70ef, 0x0000, 0x1120, 0x70ef, 0x0fa0,
-	0x080c, 0x0f00, 0x002e, 0x0005, 0x0026, 0x080c, 0x0efb, 0x0128,
-	0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c,
-	0x0f00, 0x002e, 0x0005, 0x0026, 0x70ef, 0x0000, 0x080c, 0x0efb,
-	0x1148, 0x080c, 0x2c59, 0x1118, 0x2011, 0x8484, 0x0058, 0x2011,
-	0x8282, 0x0040, 0x080c, 0x2c59, 0x1118, 0x2011, 0xcdc5, 0x0010,
-	0x2011, 0xcac2, 0x080c, 0x0f00, 0x002e, 0x0005, 0x00e6, 0x0006,
-	0x2071, 0x1800, 0xd0b4, 0x70e8, 0x1110, 0xc0e4, 0x0048, 0x0006,
-	0x3b00, 0x9084, 0xff3f, 0x20d8, 0x000e, 0x70ef, 0x0000, 0xc0e5,
-	0x0079, 0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800, 0xd0e4,
-	0x70e8, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0011, 0x00ee, 0x0005,
-	0x70ea, 0x7000, 0x9084, 0x0007, 0x000b, 0x0005, 0x0ebd, 0x0e94,
-	0x0e94, 0x0e76, 0x0ea3, 0x0e94, 0x0e94, 0x0ea3, 0x0016, 0x3b08,
-	0x3a00, 0x9104, 0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205,
-	0x20d0, 0x001e, 0x0005, 0x2001, 0x183a, 0x2004, 0xd0dc, 0x0005,
-	0x9e86, 0x1800, 0x190c, 0x0dc5, 0x70e8, 0xd0e4, 0x0108, 0xc2e5,
-	0x72ea, 0xd0e4, 0x1118, 0x9294, 0x00c0, 0x0c01, 0x0005, 0x1d04,
-	0x0f0f, 0x2091, 0x6000, 0x1f04, 0x0f0f, 0x0005, 0x890e, 0x810e,
-	0x810f, 0x9194, 0x003f, 0x918c, 0xffc0, 0x0005, 0x0006, 0x2200,
-	0x914d, 0x894f, 0x894d, 0x894d, 0x000e, 0x0005, 0x01d6, 0x0146,
-	0x0036, 0x0096, 0x2061, 0x188d, 0x600b, 0x0000, 0x600f, 0x0000,
-	0x6003, 0x0000, 0x6007, 0x0000, 0x2009, 0xffc0, 0x2105, 0x0006,
-	0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555, 0x9016, 0x2049, 0x0bff,
-	0xab02, 0xa001, 0xa001, 0xa800, 0x9306, 0x1138, 0x2105, 0x9306,
-	0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98, 0x000e, 0x200f, 0x2001,
-	0x189d, 0x928a, 0x000e, 0x1638, 0x928a, 0x0006, 0x2011, 0x0006,
-	0x1210, 0x2011, 0x0000, 0x2202, 0x9006, 0x2008, 0x82ff, 0x01b0,
-	0x8200, 0x600a, 0x600f, 0xffff, 0x6003, 0x0002, 0x6007, 0x0000,
-	0x0026, 0x2019, 0x0010, 0x9280, 0x0001, 0x20e8, 0x21a0, 0x21a8,
-	0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0, 0x002e, 0x009e, 0x003e,
-	0x014e, 0x01de, 0x0005, 0x2011, 0x000e, 0x08e8, 0x0016, 0x0026,
-	0x0096, 0x3348, 0x080c, 0x0f16, 0x2100, 0x9300, 0x2098, 0x22e0,
-	0x009e, 0x002e, 0x001e, 0x0036, 0x3518, 0x20a9, 0x0001, 0x4002,
-	0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e, 0x0005, 0x20e9, 0x0001,
-	0x71b8, 0x81ff, 0x11c0, 0x9006, 0x2009, 0x0200, 0x20a9, 0x0002,
-	0x9298, 0x0018, 0x23a0, 0x4001, 0x2009, 0x0700, 0x20a9, 0x0002,
-	0x9298, 0x0008, 0x23a0, 0x4001, 0x707c, 0x8007, 0x7180, 0x810f,
-	0x20a9, 0x0002, 0x4001, 0x9298, 0x000c, 0x23a0, 0x900e, 0x080c,
-	0x0da5, 0x2001, 0x0000, 0x810f, 0x20a9, 0x0002, 0x4001, 0x0005,
-	0x89ff, 0x0140, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c, 0x1040,
-	0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x10b9,
-	0x090c, 0x0dc5, 0x00ee, 0x0005, 0x0086, 0x00e6, 0x0006, 0x0026,
-	0x0036, 0x0126, 0x2091, 0x8000, 0x00c9, 0x2071, 0x1800, 0x73c0,
-	0x702c, 0x9016, 0x9045, 0x0158, 0x8210, 0x9906, 0x090c, 0x0dc5,
-	0x2300, 0x9202, 0x0120, 0x1a0c, 0x0dc5, 0xa000, 0x0c98, 0x012e,
-	0x003e, 0x002e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x0086, 0x00e6,
-	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x1910, 0x7010, 0x9005,
-	0x0140, 0x7018, 0x9045, 0x0128, 0x9906, 0x090c, 0x0dc5, 0xa000,
-	0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e, 0x0005, 0x00e6, 0x2071,
-	0x1800, 0x0126, 0x2091, 0x8000, 0x70c0, 0x8001, 0x0270, 0x70c2,
-	0x702c, 0x2048, 0x9085, 0x0001, 0xa800, 0x702e, 0xa803, 0x0000,
-	0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8, 0x00e6,
-	0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x70c0, 0x90ca, 0x0020,
-	0x0268, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0xa803,
-	0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005, 0x904e, 0x0cd8,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x0016, 0x890e, 0x810e, 0x810f,
-	0x9184, 0x003f, 0xa862, 0x9184, 0xffc0, 0xa85e, 0x001e, 0x0020,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x702c, 0xa802,
-	0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x012e,
-	0x00ee, 0x0005, 0x2071, 0x1800, 0x9026, 0x2009, 0x0000, 0x2049,
-	0x0400, 0x2900, 0x702e, 0x8940, 0x2800, 0xa802, 0xa95e, 0xa863,
-	0x0001, 0x8420, 0x9886, 0x0440, 0x0120, 0x2848, 0x9188, 0x0040,
-	0x0c90, 0x2071, 0x188d, 0x7000, 0x9005, 0x11a0, 0x2001, 0x0534,
-	0xa802, 0x2048, 0x2009, 0x4d00, 0x8940, 0x2800, 0xa802, 0xa95e,
-	0xa863, 0x0001, 0x8420, 0x9886, 0x0800, 0x0120, 0x2848, 0x9188,
-	0x0040, 0x0c90, 0x2071, 0x188d, 0x7104, 0x7200, 0x82ff, 0x01d0,
-	0x7308, 0x8318, 0x831f, 0x831b, 0x831b, 0x7312, 0x8319, 0x2001,
-	0x0800, 0xa802, 0x2048, 0x8900, 0xa802, 0x2040, 0xa95e, 0xaa62,
-	0x8420, 0x2300, 0x9906, 0x0130, 0x2848, 0x9188, 0x0040, 0x9291,
-	0x0000, 0x0c88, 0xa803, 0x0000, 0x2071, 0x1800, 0x74be, 0x74c2,
-	0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00, 0x01e8, 0x908c, 0xf800,
-	0x1168, 0x9982, 0x0400, 0x02b8, 0x9982, 0x0440, 0x0278, 0x9982,
-	0x0534, 0x0288, 0x9982, 0x0800, 0x1270, 0x0040, 0x9982, 0x0800,
-	0x0250, 0x2071, 0x188d, 0x7010, 0x9902, 0x1228, 0x9085, 0x0001,
-	0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8, 0x00e6, 0x2071, 0x1a1b,
-	0x7007, 0x0000, 0x9006, 0x701e, 0x7022, 0x7002, 0x2071, 0x0000,
-	0x7010, 0x9085, 0x8044, 0x7012, 0x2071, 0x0080, 0x9006, 0x20a9,
-	0x0040, 0x7022, 0x1f04, 0x10f1, 0x702b, 0x0020, 0x00ee, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x1a1b,
-	0x701c, 0x9088, 0x1a25, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e,
-	0x7120, 0x9106, 0x090c, 0x0dc5, 0x7004, 0x9005, 0x1128, 0x00f6,
-	0x2079, 0x0080, 0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x00e6, 0x2071, 0x1a1b, 0x7004, 0x9005, 0x1128,
-	0x00f6, 0x2079, 0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005,
-	0x7004, 0x9086, 0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002,
-	0x113a, 0x12bd, 0x1138, 0x1138, 0x12b1, 0x12b1, 0x12b1, 0x12b1,
-	0x080c, 0x0dc5, 0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184,
-	0x0001, 0x1120, 0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096,
-	0x9180, 0x1a25, 0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f,
-	0x7122, 0x782b, 0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894,
-	0x780a, 0xa898, 0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874,
-	0x701a, 0xa868, 0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029,
-	0x0005, 0x7007, 0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c,
-	0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e,
-	0x7212, 0x8203, 0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e,
-	0x001e, 0x0005, 0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014,
-	0x20e0, 0x7018, 0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b,
-	0x0026, 0x710c, 0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110,
-	0x9006, 0x700e, 0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020,
-	0x3300, 0x701a, 0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e,
-	0x001e, 0x0005, 0x2009, 0x1a1b, 0x2104, 0xc095, 0x200a, 0x080c,
-	0x1117, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1a1b, 0x00f6, 0x2079,
-	0x0080, 0x792c, 0xd1bc, 0x190c, 0x0dbe, 0x782b, 0x0002, 0xd1fc,
-	0x0120, 0x918c, 0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e,
-	0x0005, 0x1128, 0x11d0, 0x1204, 0x12dc, 0x0dc5, 0x12f7, 0x0dc5,
-	0x918c, 0x0700, 0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8,
-	0x7018, 0x20a0, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040,
-	0x7010, 0x20a8, 0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e,
-	0x700c, 0x9005, 0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c,
-	0x116d, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e,
-	0x7007, 0x0000, 0x080c, 0x1128, 0x0005, 0x7008, 0x0096, 0x2048,
-	0xa86f, 0x0200, 0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c,
-	0x9005, 0x0180, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x1182,
-	0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007,
-	0x0000, 0x0080, 0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804,
-	0xa892, 0x7808, 0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e,
-	0x7007, 0x0000, 0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b9,
-	0x2004, 0x9906, 0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0,
-	0x00de, 0x009e, 0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150,
-	0xa89c, 0x0086, 0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c,
-	0x1117, 0x0005, 0x00de, 0x009e, 0x080c, 0x1117, 0x0005, 0xa8a8,
-	0xd08c, 0x0005, 0x0096, 0xa0a0, 0x904d, 0x090c, 0x0dc5, 0xa06c,
-	0x908e, 0x0100, 0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897,
-	0x4002, 0x080c, 0x6e92, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848,
-	0x080c, 0x1040, 0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c,
-	0x0dc5, 0xa06c, 0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883,
-	0x0000, 0x00c0, 0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e,
-	0x2050, 0x8006, 0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0,
-	0x9080, 0x0002, 0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c,
-	0x10f8, 0x00e8, 0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x6e92,
-	0x000e, 0x001e, 0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060,
-	0x080c, 0xb2d3, 0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3,
-	0x0000, 0x080c, 0x1040, 0x7007, 0x0000, 0x080c, 0x1117, 0x00ae,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005,
-	0x7000, 0xc094, 0x7002, 0x012e, 0x0005, 0x0096, 0x2001, 0x192f,
-	0x204c, 0xa87c, 0x7812, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894,
-	0x780a, 0xa898, 0x780e, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000,
-	0x782b, 0x0041, 0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900,
-	0x700a, 0x012e, 0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088,
-	0x782b, 0x0040, 0x0096, 0x2001, 0x192f, 0x204c, 0xaa7c, 0x009e,
-	0x080c, 0x8d91, 0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a,
-	0x080c, 0x8bf3, 0x7007, 0x0000, 0x080c, 0x1128, 0x0005, 0x7007,
-	0x0000, 0x080c, 0x1128, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079,
-	0x0300, 0x2071, 0x1a65, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x781b,
-	0x4800, 0x00c1, 0x7803, 0x0003, 0x780f, 0x0000, 0x20a9, 0x03ea,
-	0x2061, 0xf0ae, 0x2c0d, 0x7912, 0xe104, 0x9ce0, 0x0002, 0x7916,
-	0x1f04, 0x1312, 0x7807, 0x0007, 0x7803, 0x0000, 0x7803, 0x0001,
-	0x012e, 0x0005, 0x00c6, 0x7803, 0x0000, 0x7808, 0xd09c, 0x0120,
-	0x7820, 0x080c, 0x1376, 0x0cc8, 0x2001, 0x1a66, 0x2003, 0x0000,
-	0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807,
-	0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b,
-	0x1a89, 0x781f, 0xff00, 0x781b, 0xb700, 0x2001, 0x0200, 0x2004,
-	0xd0dc, 0x0110, 0x781f, 0x0303, 0x2061, 0x1a89, 0x602f, 0x1cd0,
-	0x2001, 0x181a, 0x2004, 0x9082, 0x1cd0, 0x6032, 0x603b, 0x20c7,
-	0x2001, 0x33b6, 0xd0fc, 0x190c, 0x0dc5, 0x2001, 0x1810, 0x2004,
-	0xd0c4, 0x1128, 0x2001, 0x0003, 0x2004, 0xd0d4, 0x1118, 0x783f,
-	0x33b6, 0x0020, 0x9084, 0xc000, 0x783f, 0xb3b6, 0x604f, 0x193d,
-	0x2001, 0x1928, 0x2004, 0x6042, 0x00ce, 0x0005, 0x9086, 0x000d,
-	0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c,
-	0xd0c6, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016,
-	0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c,
-	0xb352, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908,
-	0x9184, 0x0070, 0x190c, 0x0dbe, 0xd19c, 0x0158, 0x7820, 0x908c,
-	0xf000, 0x15e8, 0x908a, 0x0024, 0x1a0c, 0x0dc5, 0x0023, 0x012e,
-	0x0005, 0x012e, 0x0005, 0x13cf, 0x13cf, 0x13e6, 0x13eb, 0x13ef,
-	0x13f4, 0x141c, 0x1420, 0x142e, 0x1432, 0x13cf, 0x14ff, 0x1503,
-	0x1575, 0x157c, 0x13cf, 0x157d, 0x157e, 0x1589, 0x1590, 0x13cf,
-	0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13f6, 0x13cf,
-	0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13cf, 0x13d3, 0x13d1, 0x080c,
-	0x0dc5, 0x080c, 0x0dbe, 0x080c, 0x159b, 0x2009, 0x1a7e, 0x2104,
-	0x8000, 0x200a, 0x080c, 0x813a, 0x080c, 0x1ad9, 0x0005, 0x2009,
-	0x0048, 0x2060, 0x080c, 0xb352, 0x012e, 0x0005, 0x7004, 0xc085,
-	0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c,
-	0x159b, 0x080c, 0x16fb, 0x0005, 0x080c, 0x0dc5, 0x080c, 0x159b,
-	0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009,
-	0x0048, 0x080c, 0xb352, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009,
-	0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8,
-	0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x15a0, 0x2001,
-	0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005,
-	0x080c, 0x159b, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff,
-	0x009e, 0x2009, 0x0048, 0x080c, 0xb352, 0x0005, 0x080c, 0x159b,
-	0x080c, 0x0dc5, 0x080c, 0x159b, 0x080c, 0x14ea, 0x7827, 0x0018,
-	0x79ac, 0xd1dc, 0x0904, 0x149b, 0x7827, 0x0015, 0x7828, 0x782b,
-	0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003,
-	0x0020, 0x0804, 0x14a1, 0x7004, 0x9005, 0x01c8, 0x1188, 0x78ab,
-	0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0dc5,
-	0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x14cf,
-	0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1503, 0x0005, 0x7827,
-	0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106,
-	0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, 0x702c, 0xd0c4,
-	0x0140, 0x00ee, 0x080c, 0x1ad9, 0x080c, 0x1322, 0x7803, 0x0001,
-	0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00,
-	0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006,
-	0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x1503, 0x2001, 0x020d,
-	0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c,
-	0x0dc5, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8,
-	0x080c, 0x813a, 0x080c, 0x1ad9, 0x080c, 0xd0d8, 0x0158, 0xa9ac,
-	0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880,
-	0xc0bd, 0xa882, 0x080c, 0xccf3, 0x0005, 0x6020, 0x9086, 0x0009,
-	0x1128, 0x2009, 0x004c, 0x080c, 0xb352, 0x0048, 0x6010, 0x00b6,
-	0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xd4c4, 0x2029,
-	0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8,
-	0x7dbc, 0x080c, 0xf057, 0xd5a4, 0x1118, 0x080c, 0x15a0, 0x0005,
-	0x080c, 0x813a, 0x080c, 0x1ad9, 0x0005, 0x781f, 0x0300, 0x7803,
-	0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300,
-	0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016,
-	0x080c, 0x1611, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004,
-	0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0dc5,
-	0xd184, 0x11b1, 0xd19c, 0x0180, 0xc19c, 0x7106, 0x0016, 0x080c,
-	0x16de, 0x001e, 0x0148, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003,
-	0x0020, 0x080c, 0x15a0, 0x0005, 0x81ff, 0x190c, 0x0dc5, 0x0005,
-	0x2100, 0xc184, 0xc1b4, 0x7106, 0xd0b4, 0x0016, 0x00e6, 0x1904,
-	0x156a, 0x2071, 0x0200, 0x080c, 0x16cb, 0x05e0, 0x080c, 0x16de,
-	0x05b0, 0x6014, 0x9005, 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e,
-	0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1550,
-	0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe,
-	0x00b0, 0x00f6, 0x2c78, 0x080c, 0x18fd, 0x00fe, 0x2009, 0x01f4,
-	0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001,
-	0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x15a0, 0x0040, 0x2001,
-	0x020d, 0x2003, 0x0020, 0x080c, 0x1322, 0x7803, 0x0001, 0x00ee,
-	0x001e, 0x0005, 0x080c, 0x16de, 0x0dd0, 0x2001, 0x020d, 0x2003,
-	0x0050, 0x2003, 0x0020, 0x0461, 0x0c90, 0x0429, 0x2060, 0x2009,
-	0x0053, 0x080c, 0xb352, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008,
-	0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x90de,
-	0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8ce2, 0x0cd0, 0x0005,
-	0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, 0x181f, 0x2214,
-	0x080c, 0x1611, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005,
-	0x080c, 0x14ea, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109,
-	0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000,
-	0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182,
-	0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c,
-	0x810c, 0x080c, 0x1603, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9,
-	0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4,
-	0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0,
-	0x080c, 0x813a, 0x080c, 0x1ad9, 0x0090, 0x7827, 0x0015, 0x782b,
-	0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003,
-	0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de,
-	0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827,
-	0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800,
-	0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005,
-	0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041,
-	0x0005, 0x00f6, 0x2079, 0x0300, 0x0006, 0x7808, 0xd09c, 0x0140,
-	0x0016, 0x0026, 0x00c6, 0x080c, 0x1394, 0x00ce, 0x002e, 0x001e,
-	0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0059,
-	0x1118, 0x000e, 0x00fe, 0x0005, 0x000e, 0x792c, 0x3900, 0x8000,
-	0x2004, 0x080c, 0x0dc5, 0x2009, 0x180c, 0x2104, 0xc0f4, 0x200a,
-	0x2009, 0xff00, 0x8109, 0x0904, 0x168f, 0x7a18, 0x9284, 0x0030,
-	0x0904, 0x168a, 0x9284, 0x0048, 0x9086, 0x0008, 0x1904, 0x168a,
-	0x2001, 0x0109, 0x2004, 0xd08c, 0x01f0, 0x0006, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x0126, 0x2091, 0x2800, 0x00f6, 0x0026,
-	0x0016, 0x2009, 0x1a81, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c,
-	0x94b1, 0x001e, 0x002e, 0x00fe, 0x012e, 0x015e, 0x014e, 0x013e,
-	0x01de, 0x01ce, 0x000e, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x01d0,
-	0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x00f6,
-	0x0016, 0x2009, 0x1a82, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c,
-	0x1eeb, 0x001e, 0x00fe, 0x015e, 0x014e, 0x013e, 0x01de, 0x01ce,
-	0x012e, 0x000e, 0x7818, 0xd0bc, 0x1904, 0x163a, 0x0005, 0x2001,
-	0x180c, 0x2004, 0xd0f4, 0x1528, 0x7a18, 0x9284, 0x0030, 0x0508,
-	0x9284, 0x0048, 0x9086, 0x0008, 0x11e0, 0x2001, 0x19f7, 0x2004,
-	0x9005, 0x01b8, 0x2001, 0x1a69, 0x2004, 0x9086, 0x0000, 0x0188,
-	0x2009, 0x1a80, 0x2104, 0x8000, 0x0208, 0x200a, 0x080c, 0xa767,
-	0x2009, 0x180c, 0x2104, 0xc0f5, 0x200a, 0x2009, 0xff00, 0x0804,
-	0x163a, 0x9085, 0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b,
-	0x8080, 0x080c, 0x1633, 0x1108, 0x0005, 0x792c, 0x3900, 0x8000,
-	0x2004, 0x080c, 0x0dc5, 0x7037, 0x0001, 0x7150, 0x7037, 0x0002,
-	0x7050, 0x2060, 0xd1bc, 0x1110, 0x7054, 0x2060, 0x918c, 0xff00,
-	0x9186, 0x0500, 0x0110, 0x9085, 0x0001, 0x0005, 0x0006, 0x0046,
-	0x00e6, 0x2071, 0x0200, 0x7037, 0x0002, 0x7058, 0x9084, 0xff00,
-	0x8007, 0x9086, 0x00bc, 0x1158, 0x2021, 0x1a7f, 0x2404, 0x8000,
-	0x0208, 0x2022, 0x080c, 0x813a, 0x080c, 0x1ad9, 0x9006, 0x00ee,
-	0x004e, 0x000e, 0x0005, 0x0c11, 0x1108, 0x0005, 0x00e6, 0x0016,
-	0x2071, 0x0200, 0x0841, 0x6124, 0xd1dc, 0x01f8, 0x701c, 0xd08c,
-	0x0904, 0x175d, 0x7017, 0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc,
-	0x0904, 0x175d, 0x2001, 0x0268, 0x00c6, 0x2064, 0x6104, 0x6038,
-	0x00ce, 0x918e, 0x0039, 0x1904, 0x175d, 0x9c06, 0x15f0, 0x0126,
-	0x2091, 0x2600, 0x080c, 0x8081, 0x012e, 0x7358, 0x745c, 0x6014,
-	0x905d, 0x0598, 0x2b48, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be,
-	0xd0bc, 0x190c, 0xd49f, 0xab42, 0xac3e, 0x2001, 0x1869, 0x2004,
-	0xd0b4, 0x1170, 0x601c, 0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058,
-	0xb800, 0x00be, 0xd0bc, 0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff,
-	0x080c, 0x20e7, 0x1190, 0x080c, 0x195a, 0x2a00, 0xa816, 0x0130,
-	0x2800, 0xa80e, 0x2c05, 0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020,
-	0x781f, 0x0300, 0x001e, 0x00ee, 0x0005, 0x7037, 0x0050, 0x7037,
-	0x0020, 0x001e, 0x00ee, 0x080c, 0x15a0, 0x0005, 0x080c, 0x0dc5,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x190c, 0x6b5e, 0x2ff0, 0x0126,
-	0x2091, 0x2200, 0x0016, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940,
-	0x903e, 0x2730, 0xa864, 0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088,
-	0x20c7, 0x2165, 0x0002, 0x179a, 0x1808, 0x179a, 0x179a, 0x179e,
-	0x17e9, 0x179a, 0x17be, 0x1793, 0x17ff, 0x179a, 0x179a, 0x17a3,
-	0x18f5, 0x17d2, 0x17c8, 0xa964, 0x918c, 0x00ff, 0x918e, 0x0048,
-	0x0904, 0x17ff, 0x9085, 0x0001, 0x0804, 0x18eb, 0xa87c, 0xd0ac,
-	0x0dc8, 0x0804, 0x180f, 0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x187a,
-	0xa898, 0x901d, 0x1108, 0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42,
-	0x3e00, 0x9080, 0x0008, 0x2004, 0x9080, 0x933d, 0x2005, 0x9005,
-	0x090c, 0x0dc5, 0x2004, 0xa8ae, 0x0804, 0x18d3, 0xa87c, 0xd0bc,
-	0x09c8, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x180f,
-	0xa87c, 0xd0bc, 0x0978, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888,
-	0x0804, 0x187a, 0xa87c, 0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c,
-	0xa83e, 0xa804, 0x9045, 0x090c, 0x0dc5, 0xa164, 0xa91a, 0x91ec,
-	0x000f, 0x9d80, 0x20c7, 0x2065, 0xa888, 0xd19c, 0x1904, 0x187a,
-	0x0430, 0xa87c, 0xd0ac, 0x0904, 0x179a, 0xa804, 0x9045, 0x090c,
-	0x0dc5, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x20c7, 0x2065,
-	0x9006, 0xa842, 0xa83e, 0xd19c, 0x1904, 0x187a, 0x0080, 0xa87c,
-	0xd0ac, 0x0904, 0x179a, 0x9006, 0xa842, 0xa83e, 0x0804, 0x187a,
-	0xa87c, 0xd0ac, 0x0904, 0x179a, 0x9006, 0xa842, 0xa83e, 0x2c05,
-	0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002, 0x1832,
-	0x1832, 0x1834, 0x1832, 0x1832, 0x1832, 0x183e, 0x1832, 0x1832,
-	0x1832, 0x1848, 0x1832, 0x1832, 0x1832, 0x1852, 0x1832, 0x1832,
-	0x1832, 0x185c, 0x1832, 0x1832, 0x1832, 0x1866, 0x1832, 0x1832,
-	0x1832, 0x1870, 0x080c, 0x0dc5, 0xa574, 0xa478, 0x9d86, 0x0024,
-	0x0904, 0x17a8, 0xa37c, 0xa280, 0x0804, 0x18d3, 0xa584, 0xa488,
-	0x9d86, 0x0024, 0x0904, 0x17a8, 0xa38c, 0xa290, 0x0804, 0x18d3,
-	0xa594, 0xa498, 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa39c, 0xa2a0,
-	0x0804, 0x18d3, 0xa5a4, 0xa4a8, 0x9d86, 0x0024, 0x0904, 0x17a8,
-	0xa3ac, 0xa2b0, 0x0804, 0x18d3, 0xa5b4, 0xa4b8, 0x9d86, 0x0024,
-	0x0904, 0x17a8, 0xa3bc, 0xa2c0, 0x0804, 0x18d3, 0xa5c4, 0xa4c8,
-	0x9d86, 0x0024, 0x0904, 0x17a8, 0xa3cc, 0xa2d0, 0x0804, 0x18d3,
-	0xa5d4, 0xa4d8, 0x9d86, 0x0024, 0x0904, 0x17a8, 0xa3dc, 0xa2e0,
-	0x0804, 0x18d3, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082,
-	0x001b, 0x0002, 0x189d, 0x189b, 0x189b, 0x189b, 0x189b, 0x189b,
-	0x18a8, 0x189b, 0x189b, 0x189b, 0x189b, 0x189b, 0x18b3, 0x189b,
-	0x189b, 0x189b, 0x189b, 0x189b, 0x18be, 0x189b, 0x189b, 0x189b,
-	0x189b, 0x189b, 0x18c9, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774,
-	0xa678, 0x9d86, 0x002c, 0x0904, 0x17a8, 0xa37c, 0xa280, 0x0458,
-	0xa584, 0xa488, 0xa78c, 0xa690, 0x9d86, 0x002c, 0x0904, 0x17a8,
-	0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86,
-	0x002c, 0x0904, 0x17a8, 0xa3ac, 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8,
-	0xa7bc, 0xa6c0, 0x9d86, 0x002c, 0x0904, 0x17a8, 0xa3c4, 0xa2c8,
-	0x0050, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0x9d86, 0x002c, 0x0904,
-	0x17a8, 0xa3dc, 0xa2e0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26,
-	0xae2a, 0xa988, 0x8c60, 0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a,
-	0x8109, 0xa916, 0x1160, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c,
-	0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x001e, 0x012e, 0x0005, 0x2800,
-	0xa80e, 0xab0a, 0x2c00, 0xa812, 0x0c70, 0x0804, 0x179a, 0x2001,
-	0x180d, 0x2004, 0xd08c, 0x190c, 0x6b5e, 0x2ff0, 0x0126, 0x2091,
-	0x2200, 0x0016, 0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e,
-	0x2061, 0x20c2, 0xa813, 0x20c2, 0x2c05, 0xa80a, 0xa964, 0xa91a,
-	0xa87c, 0xd0ac, 0x090c, 0x0dc5, 0x9006, 0xa842, 0xa83e, 0x2c05,
-	0x908a, 0x0034, 0x1a0c, 0x0dc5, 0xadcc, 0xacd0, 0xafd4, 0xaed8,
-	0xabdc, 0xaae0, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a,
-	0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff,
-	0x9086, 0x0008, 0x1120, 0x8109, 0xa916, 0x0128, 0x0080, 0x918a,
-	0x0002, 0xa916, 0x1160, 0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c,
-	0xc0dd, 0xa87e, 0x9006, 0x00ce, 0x001e, 0x012e, 0x0005, 0xa804,
-	0x9045, 0x090c, 0x0dc5, 0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f,
-	0x9080, 0x20c7, 0x2015, 0x82ff, 0x090c, 0x0dc5, 0xaa12, 0x2205,
-	0xa80a, 0x0c08, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00,
-	0x0002, 0x1a4f, 0x19b1, 0x19b1, 0x1a4f, 0x1a4f, 0x1a49, 0x1a4f,
-	0x19b1, 0x1a00, 0x1a00, 0x1a00, 0x1a4f, 0x1a4f, 0x1a4f, 0x1a46,
-	0x1a00, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c,
-	0x0904, 0x1a51, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082,
-	0x001b, 0x0002, 0x199d, 0x199b, 0x199b, 0x199b, 0x199b, 0x199b,
-	0x19a1, 0x199b, 0x199b, 0x199b, 0x199b, 0x199b, 0x19a5, 0x199b,
-	0x199b, 0x199b, 0x199b, 0x199b, 0x19a9, 0x199b, 0x199b, 0x199b,
-	0x199b, 0x199b, 0x19ad, 0x080c, 0x0dc5, 0xa774, 0xa678, 0x0804,
-	0x1a51, 0xa78c, 0xa690, 0x0804, 0x1a51, 0xa7a4, 0xa6a8, 0x0804,
-	0x1a51, 0xa7bc, 0xa6c0, 0x0804, 0x1a51, 0xa7d4, 0xa6d8, 0x0804,
-	0x1a51, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b,
-	0x0002, 0x19d4, 0x19d4, 0x19d6, 0x19d4, 0x19d4, 0x19d4, 0x19dc,
-	0x19d4, 0x19d4, 0x19d4, 0x19e2, 0x19d4, 0x19d4, 0x19d4, 0x19e8,
-	0x19d4, 0x19d4, 0x19d4, 0x19ee, 0x19d4, 0x19d4, 0x19d4, 0x19f4,
-	0x19d4, 0x19d4, 0x19d4, 0x19fa, 0x080c, 0x0dc5, 0xa574, 0xa478,
-	0xa37c, 0xa280, 0x0804, 0x1a51, 0xa584, 0xa488, 0xa38c, 0xa290,
-	0x0804, 0x1a51, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1a51,
-	0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1a51, 0xa5b4, 0xa4b8,
-	0xa3bc, 0xa2c0, 0x0804, 0x1a51, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0,
-	0x0804, 0x1a51, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1a51,
-	0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002,
-	0x1a23, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a2a, 0x1a21,
-	0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a31, 0x1a21, 0x1a21, 0x1a21,
-	0x1a21, 0x1a21, 0x1a38, 0x1a21, 0x1a21, 0x1a21, 0x1a21, 0x1a21,
-	0x1a3f, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c,
-	0xa280, 0x0438, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394, 0xa298,
-	0x0400, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8,
-	0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc,
-	0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e,
-	0x1130, 0x080c, 0x207f, 0x1904, 0x195a, 0x900e, 0x0050, 0x080c,
-	0x0dc5, 0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c,
-	0x207f, 0x0005, 0x6014, 0x2048, 0x6118, 0x81ff, 0x0148, 0x810c,
-	0x810c, 0x810c, 0x81ff, 0x1118, 0xa887, 0x0001, 0x0008, 0xa986,
-	0x601b, 0x0002, 0xa874, 0x9084, 0x00ff, 0x9084, 0x0008, 0x0150,
-	0x00e9, 0x6000, 0x9086, 0x0004, 0x1120, 0x2009, 0x0048, 0x080c,
-	0xb352, 0x0005, 0xa974, 0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c,
-	0x9106, 0x1158, 0xa938, 0xa890, 0x9106, 0x1138, 0x601c, 0xc084,
-	0x601e, 0x2009, 0x0048, 0x0804, 0xb352, 0x0005, 0x0126, 0x00c6,
-	0x2091, 0x2200, 0x00ce, 0x7908, 0x918c, 0x0007, 0x9186, 0x0000,
-	0x05b0, 0x9186, 0x0003, 0x0598, 0x6020, 0x6023, 0x0000, 0x0006,
-	0x2031, 0x0008, 0x00c6, 0x781f, 0x0808, 0x7808, 0xd09c, 0x0120,
-	0x080c, 0x1394, 0x8631, 0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031,
-	0x0168, 0x00c6, 0x7808, 0xd09c, 0x190c, 0x1394, 0x00ce, 0x2001,
-	0x0038, 0x080c, 0x1b69, 0x7930, 0x9186, 0x0040, 0x0160, 0x9186,
-	0x0042, 0x190c, 0x0dc5, 0x2001, 0x001e, 0x8001, 0x1df0, 0x8631,
-	0x1d40, 0x080c, 0x1b78, 0x000e, 0x6022, 0x012e, 0x0005, 0x080c,
-	0x1b65, 0x7827, 0x0015, 0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000,
-	0x0ca0, 0x00f6, 0x2079, 0x0300, 0x7803, 0x0000, 0x78ab, 0x0004,
-	0x2001, 0xf000, 0x8001, 0x090c, 0x0dc5, 0x7aac, 0xd2ac, 0x1dd0,
-	0x00fe, 0x080c, 0x7637, 0x1188, 0x2001, 0x0138, 0x2003, 0x0000,
-	0x2001, 0x0160, 0x2003, 0x0000, 0x2011, 0x012c, 0xa001, 0xa001,
-	0x8211, 0x1de0, 0x0059, 0x0804, 0x76e4, 0x0479, 0x0039, 0x2001,
-	0x0160, 0x2502, 0x2001, 0x0138, 0x2202, 0x0005, 0x00e6, 0x2071,
-	0x0200, 0x080c, 0x2c6d, 0x2009, 0x003c, 0x080c, 0x2409, 0x2001,
-	0x015d, 0x2003, 0x0000, 0x7000, 0x9084, 0x003c, 0x1de0, 0x080c,
-	0x8725, 0x70a0, 0x70a2, 0x7098, 0x709a, 0x709c, 0x709e, 0x2001,
-	0x020d, 0x2003, 0x0020, 0x00f6, 0x2079, 0x0300, 0x080c, 0x1322,
-	0x7803, 0x0001, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x0138, 0x2014,
-	0x2003, 0x0000, 0x2001, 0x0160, 0x202c, 0x2003, 0x0000, 0x080c,
-	0x7637, 0x1108, 0x0005, 0x2021, 0x0260, 0x2001, 0x0141, 0x201c,
-	0xd3dc, 0x1168, 0x2001, 0x0109, 0x201c, 0x939c, 0x0048, 0x1160,
-	0x2001, 0x0111, 0x201c, 0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001,
-	0x015d, 0x2003, 0x0000, 0x0005, 0x0046, 0x2021, 0x0019, 0x2003,
-	0x0048, 0xa001, 0xa001, 0x201c, 0x939c, 0x0048, 0x0120, 0x8421,
-	0x1db0, 0x004e, 0x0c60, 0x004e, 0x0c40, 0x601c, 0xc084, 0x601e,
-	0x0005, 0x2c08, 0x621c, 0x080c, 0x1611, 0x7930, 0x0005, 0x2c08,
-	0x621c, 0x080c, 0x16bc, 0x7930, 0x0005, 0x8001, 0x1df0, 0x0005,
-	0x2031, 0x0064, 0x781c, 0x9084, 0x0007, 0x0170, 0x2001, 0x0038,
-	0x0c41, 0x9186, 0x0040, 0x0904, 0x1bd6, 0x2001, 0x001e, 0x0c69,
-	0x8631, 0x1d80, 0x080c, 0x0dc5, 0x781f, 0x0202, 0x2001, 0x015d,
-	0x2003, 0x0000, 0x2001, 0x0dac, 0x0c01, 0x781c, 0xd084, 0x0110,
-	0x0861, 0x04e0, 0x2001, 0x0030, 0x0891, 0x9186, 0x0040, 0x0568,
-	0x781c, 0xd084, 0x1da8, 0x781f, 0x0101, 0x2001, 0x0014, 0x0869,
-	0x2001, 0x0037, 0x0821, 0x9186, 0x0040, 0x0140, 0x2001, 0x0030,
-	0x080c, 0x1b6f, 0x9186, 0x0040, 0x190c, 0x0dc5, 0x00d6, 0x2069,
-	0x0200, 0x692c, 0xd1f4, 0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130,
-	0x6800, 0x9085, 0x1800, 0x6802, 0x00de, 0x0080, 0x6908, 0x9184,
-	0x0007, 0x1db0, 0x00de, 0x781f, 0x0100, 0x791c, 0x9184, 0x0007,
-	0x090c, 0x0dc5, 0xa001, 0xa001, 0x781f, 0x0200, 0x0005, 0x0126,
-	0x2091, 0x2400, 0x2071, 0x1a69, 0x2079, 0x0090, 0x012e, 0x0005,
-	0x9280, 0x0005, 0x2004, 0x2048, 0xa97c, 0xd1dc, 0x1904, 0x1c78,
-	0xa964, 0x9184, 0x0007, 0x0002, 0x1bf4, 0x1c63, 0x1c0b, 0x1c0d,
-	0x1c0b, 0x1c4b, 0x1c2b, 0x1c1a, 0x918c, 0x00ff, 0x9186, 0x0008,
-	0x1170, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0x9006, 0xa842, 0xa83e,
-	0xa988, 0x2900, 0xa85a, 0xa813, 0x20c2, 0x0804, 0x1c74, 0x9186,
-	0x0048, 0x0904, 0x1c63, 0x080c, 0x0dc5, 0x9184, 0x00ff, 0x9086,
-	0x0013, 0x0904, 0x1c63, 0x9184, 0x00ff, 0x9086, 0x001b, 0x0904,
-	0x1c63, 0x0c88, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa890, 0xa842,
-	0xa83a, 0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a,
-	0xa988, 0x0804, 0x1c6b, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e,
-	0x19d0, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa890, 0xa842, 0xa83a,
-	0xa88c, 0xa83e, 0xa836, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa804,
-	0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x20c7, 0x2005,
-	0xa812, 0xa988, 0x0448, 0x918c, 0x00ff, 0x9186, 0x0015, 0x1540,
-	0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa804, 0xa85a, 0x2040, 0xa064,
-	0x9084, 0x000f, 0x9080, 0x20c7, 0x2005, 0xa812, 0xa988, 0x9006,
-	0xa842, 0xa83e, 0x0088, 0xa87c, 0xd0b4, 0x0904, 0x1ea5, 0xa988,
-	0x9006, 0xa842, 0xa83e, 0x2900, 0xa85a, 0xa864, 0x9084, 0x000f,
-	0x9080, 0x20c7, 0x2005, 0xa812, 0xa916, 0xa87c, 0xc0dd, 0xa87e,
-	0x0005, 0x00f6, 0x2079, 0x0090, 0x782c, 0xd0fc, 0x190c, 0x1eeb,
-	0x00e6, 0x2071, 0x1a69, 0x7000, 0x9005, 0x1904, 0x1cdf, 0x7206,
-	0x9280, 0x0005, 0x204c, 0x9280, 0x0004, 0x2004, 0x782b, 0x0004,
-	0x00f6, 0x2079, 0x0200, 0x7803, 0x0040, 0x00fe, 0x00b6, 0x2058,
-	0xb86c, 0x7836, 0xb890, 0x00be, 0x00f6, 0x2079, 0x0200, 0x7803,
-	0x0040, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x781a,
-	0x78d7, 0x0000, 0x00fe, 0xa814, 0x2050, 0xa858, 0x2040, 0xa810,
-	0x2060, 0xa064, 0x90ec, 0x000f, 0xa944, 0x791a, 0x7116, 0xa848,
-	0x781e, 0x701a, 0x9006, 0x700e, 0x7012, 0x7004, 0xa940, 0xa838,
-	0x9106, 0x1500, 0xa93c, 0xa834, 0x9106, 0x11e0, 0x0006, 0x0016,
-	0xa938, 0xa834, 0x9105, 0x0118, 0x001e, 0x000e, 0x0098, 0x001e,
-	0x000e, 0x8aff, 0x01c8, 0x0126, 0x2091, 0x8000, 0x2009, 0x0306,
-	0x200b, 0x0808, 0x00d9, 0x0108, 0x00c9, 0x012e, 0x9006, 0x00ee,
-	0x00fe, 0x0005, 0x0036, 0x0046, 0xab38, 0xac34, 0x080c, 0x20e7,
-	0x004e, 0x003e, 0x0d30, 0x0c98, 0x9085, 0x0001, 0x0c80, 0x2009,
-	0x0306, 0x200b, 0x4800, 0x7027, 0x0000, 0x0005, 0x0076, 0x0066,
-	0x0056, 0x0046, 0x0036, 0x0026, 0x8aff, 0x0904, 0x1e9e, 0x700c,
-	0x7214, 0x923a, 0x7010, 0x7218, 0x9203, 0x0a04, 0x1e9d, 0x9705,
-	0x0904, 0x1e9d, 0x903e, 0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00,
-	0x0002, 0x1e22, 0x1d61, 0x1d61, 0x1e22, 0x1e22, 0x1dff, 0x1e22,
-	0x1d61, 0x1e06, 0x1db0, 0x1db0, 0x1e22, 0x1e22, 0x1e22, 0x1df9,
-	0x1db0, 0xc0fc, 0xa882, 0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c,
-	0x0904, 0x1e2f, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082,
-	0x001b, 0x0002, 0x1d4d, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b,
-	0x1d51, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d55, 0x1d4b,
-	0x1d4b, 0x1d4b, 0x1d4b, 0x1d4b, 0x1d59, 0x1d4b, 0x1d4b, 0x1d4b,
-	0x1d4b, 0x1d4b, 0x1d5d, 0x080c, 0x0dc5, 0xa774, 0xa678, 0x0804,
-	0x1e2f, 0xa78c, 0xa690, 0x0804, 0x1e2f, 0xa7a4, 0xa6a8, 0x0804,
-	0x1e2f, 0xa7bc, 0xa6c0, 0x0804, 0x1e2f, 0xa7d4, 0xa6d8, 0x0804,
-	0x1e2f, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b,
-	0x0002, 0x1d84, 0x1d84, 0x1d86, 0x1d84, 0x1d84, 0x1d84, 0x1d8c,
-	0x1d84, 0x1d84, 0x1d84, 0x1d92, 0x1d84, 0x1d84, 0x1d84, 0x1d98,
-	0x1d84, 0x1d84, 0x1d84, 0x1d9e, 0x1d84, 0x1d84, 0x1d84, 0x1da4,
-	0x1d84, 0x1d84, 0x1d84, 0x1daa, 0x080c, 0x0dc5, 0xa574, 0xa478,
-	0xa37c, 0xa280, 0x0804, 0x1e2f, 0xa584, 0xa488, 0xa38c, 0xa290,
-	0x0804, 0x1e2f, 0xa594, 0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1e2f,
-	0xa5a4, 0xa4a8, 0xa3ac, 0xa2b0, 0x0804, 0x1e2f, 0xa5b4, 0xa4b8,
-	0xa3bc, 0xa2c0, 0x0804, 0x1e2f, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0,
-	0x0804, 0x1e2f, 0xa5d4, 0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1e2f,
-	0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002,
-	0x1dd3, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1ddb, 0x1dd1,
-	0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1de3, 0x1dd1, 0x1dd1, 0x1dd1,
-	0x1dd1, 0x1dd1, 0x1deb, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1, 0x1dd1,
-	0x1df2, 0x080c, 0x0dc5, 0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c,
-	0xa280, 0x0804, 0x1e2f, 0xa584, 0xa488, 0xa78c, 0xa690, 0xa394,
-	0xa298, 0x0804, 0x1e2f, 0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0xa3ac,
-	0xa2b0, 0x0804, 0x1e2f, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0xa3c4,
-	0xa2c8, 0x04e8, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8, 0xa3dc, 0xa2e0,
-	0x04b0, 0xa864, 0x9084, 0x00ff, 0x9086, 0x001e, 0x1518, 0x080c,
-	0x207f, 0x1904, 0x1cfc, 0x900e, 0x0804, 0x1e9e, 0xab64, 0x939c,
-	0x00ff, 0x9386, 0x0048, 0x1180, 0x00c6, 0x7004, 0x2060, 0x6004,
-	0x9086, 0x0043, 0x00ce, 0x0904, 0x1db0, 0xab9c, 0x9016, 0xad8c,
-	0xac90, 0xaf94, 0xae98, 0x0098, 0x9386, 0x0008, 0x0904, 0x1db0,
-	0x080c, 0x0dc5, 0xa964, 0x918c, 0x00ff, 0x9186, 0x0013, 0x0904,
-	0x1d61, 0x9186, 0x001b, 0x0904, 0x1db0, 0x080c, 0x0dc5, 0x2009,
-	0x030f, 0x2104, 0xd0fc, 0x0538, 0x0066, 0x2009, 0x0306, 0x2134,
-	0x200b, 0x4000, 0x2104, 0x9084, 0x0030, 0x15b8, 0x2031, 0x1000,
-	0x2600, 0x9302, 0x928b, 0x0000, 0xa82e, 0xa932, 0x0278, 0x9105,
-	0x0168, 0x2011, 0x0000, 0x2618, 0x2600, 0x9500, 0xa81e, 0x9481,
-	0x0000, 0xa822, 0xa880, 0xc0fd, 0xa882, 0x0020, 0xa82f, 0x0000,
-	0xa833, 0x0000, 0x006e, 0x7b12, 0x7a16, 0x7d02, 0x7c06, 0x7f0a,
-	0x7e0e, 0x782b, 0x0001, 0x7000, 0x8000, 0x7002, 0xa83c, 0x9300,
-	0xa83e, 0xa840, 0x9201, 0xa842, 0x700c, 0x9300, 0x700e, 0x7010,
-	0x9201, 0x7012, 0x080c, 0x207f, 0x0448, 0xd6b4, 0x0110, 0x200b,
-	0x4040, 0x2031, 0x0080, 0x9584, 0x007f, 0x0108, 0x9632, 0x7124,
-	0x7000, 0x9086, 0x0000, 0x1198, 0xc185, 0x7126, 0x2009, 0x0306,
-	0x2104, 0xd0b4, 0x1904, 0x1e40, 0x200b, 0x4040, 0x2009, 0x1a83,
-	0x2104, 0x8000, 0x0a04, 0x1e40, 0x200a, 0x0804, 0x1e40, 0xc18d,
-	0x7126, 0xd184, 0x1d58, 0x0804, 0x1e40, 0x9006, 0x002e, 0x003e,
-	0x004e, 0x005e, 0x006e, 0x007e, 0x0005, 0x080c, 0x0dc5, 0x0026,
-	0x2001, 0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7003, 0x0000,
-	0x7004, 0x2060, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0118, 0xa880,
-	0xc0bd, 0xa882, 0x782c, 0xd0ac, 0x1de8, 0x080c, 0x1cef, 0x6020,
-	0x9086, 0x0006, 0x1180, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa,
-	0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8,
-	0xa896, 0x7004, 0x2060, 0x00c6, 0x080c, 0xccf3, 0x00ce, 0x2001,
-	0x19f7, 0x2004, 0x9c06, 0x1160, 0x2009, 0x0040, 0x080c, 0x2409,
-	0x080c, 0xac2b, 0x2011, 0x0000, 0x080c, 0xaac9, 0x080c, 0x9bd3,
-	0x002e, 0x0804, 0x202f, 0x0126, 0x2091, 0x2400, 0xa858, 0x2040,
-	0x792c, 0x782b, 0x0002, 0x9184, 0x0700, 0x1904, 0x1ea7, 0x7000,
-	0x0002, 0x202f, 0x1efd, 0x1f7d, 0x202d, 0x8001, 0x7002, 0x7027,
-	0x0000, 0xd19c, 0x1158, 0x8aff, 0x0904, 0x1f4a, 0x080c, 0x1cf6,
-	0x0904, 0x202f, 0x080c, 0x1cf6, 0x0804, 0x202f, 0x782b, 0x0004,
-	0xd194, 0x0148, 0xa880, 0xc0fc, 0xa882, 0x8aff, 0x1518, 0xa87c,
-	0xc0f5, 0xa87e, 0x00f8, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x0016,
-	0x7910, 0xa82c, 0x9100, 0xa82e, 0x7914, 0xa830, 0x9101, 0xa832,
-	0x001e, 0x7810, 0x931a, 0x7814, 0x9213, 0x7800, 0xa81e, 0x7804,
-	0xa822, 0xab3e, 0xaa42, 0x003e, 0x002e, 0x080c, 0x209a, 0xa880,
-	0xc0fd, 0xa882, 0x2a00, 0xa816, 0x2800, 0xa85a, 0x2c00, 0xa812,
-	0x7003, 0x0000, 0x2009, 0x0306, 0x200b, 0x4800, 0x7027, 0x0000,
-	0x0804, 0x202f, 0x00f6, 0x0026, 0x781c, 0x0006, 0x7818, 0x0006,
-	0x2079, 0x0100, 0x7a14, 0x9284, 0x1984, 0x9085, 0x0012, 0x7816,
-	0x0036, 0x2019, 0x1000, 0x8319, 0x090c, 0x0dc5, 0x7820, 0xd0bc,
-	0x1dd0, 0x003e, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006, 0x0016,
-	0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284, 0x1984,
-	0x9085, 0x0012, 0x7816, 0x002e, 0x00fe, 0x782b, 0x0008, 0x7003,
-	0x0000, 0x080c, 0x1cef, 0x0804, 0x202f, 0x8001, 0x7002, 0x7024,
-	0x8004, 0x7026, 0xd194, 0x0170, 0x782c, 0xd0fc, 0x1904, 0x1ef0,
-	0xd19c, 0x1904, 0x202b, 0x8aff, 0x0904, 0x202f, 0x080c, 0x1cf6,
-	0x0804, 0x202f, 0x0026, 0x0036, 0xab3c, 0xaa40, 0x080c, 0x209a,
-	0xdd9c, 0x1904, 0x1fea, 0x2c05, 0x908a, 0x0036, 0x1a0c, 0x0dc5,
-	0x9082, 0x001b, 0x0002, 0x1fbe, 0x1fbe, 0x1fc0, 0x1fbe, 0x1fbe,
-	0x1fbe, 0x1fc6, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fcc, 0x1fbe, 0x1fbe,
-	0x1fbe, 0x1fd2, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fd8, 0x1fbe, 0x1fbe,
-	0x1fbe, 0x1fde, 0x1fbe, 0x1fbe, 0x1fbe, 0x1fe4, 0x080c, 0x0dc5,
-	0xa07c, 0x931a, 0xa080, 0x9213, 0x0804, 0x1f1f, 0xa08c, 0x931a,
-	0xa090, 0x9213, 0x0804, 0x1f1f, 0xa09c, 0x931a, 0xa0a0, 0x9213,
-	0x0804, 0x1f1f, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1f1f,
-	0xa0bc, 0x931a, 0xa0c0, 0x9213, 0x0804, 0x1f1f, 0xa0cc, 0x931a,
-	0xa0d0, 0x9213, 0x0804, 0x1f1f, 0xa0dc, 0x931a, 0xa0e0, 0x9213,
-	0x0804, 0x1f1f, 0x2c05, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082,
-	0x001b, 0x0002, 0x200d, 0x200b, 0x200b, 0x200b, 0x200b, 0x200b,
-	0x2013, 0x200b, 0x200b, 0x200b, 0x200b, 0x200b, 0x2019, 0x200b,
-	0x200b, 0x200b, 0x200b, 0x200b, 0x201f, 0x200b, 0x200b, 0x200b,
-	0x200b, 0x200b, 0x2025, 0x080c, 0x0dc5, 0xa07c, 0x931a, 0xa080,
-	0x9213, 0x0804, 0x1f1f, 0xa094, 0x931a, 0xa098, 0x9213, 0x0804,
-	0x1f1f, 0xa0ac, 0x931a, 0xa0b0, 0x9213, 0x0804, 0x1f1f, 0xa0c4,
-	0x931a, 0xa0c8, 0x9213, 0x0804, 0x1f1f, 0xa0dc, 0x931a, 0xa0e0,
-	0x9213, 0x0804, 0x1f1f, 0x0804, 0x1f1b, 0x080c, 0x0dc5, 0x012e,
-	0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a69, 0x7000, 0x9086, 0x0000,
-	0x0904, 0x207a, 0x2079, 0x0090, 0x2009, 0x0207, 0x210c, 0xd194,
-	0x01b8, 0x2009, 0x020c, 0x210c, 0x9184, 0x0003, 0x0188, 0x080c,
-	0xf0a0, 0x2001, 0x0133, 0x2004, 0x9005, 0x090c, 0x0dc5, 0x0016,
-	0x2009, 0x0040, 0x080c, 0x2409, 0x001e, 0x2001, 0x020c, 0x2102,
-	0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120,
-	0x2009, 0x0040, 0x080c, 0x2409, 0x782c, 0xd0fc, 0x09a8, 0x080c,
-	0x1eeb, 0x7000, 0x9086, 0x0000, 0x1978, 0x782b, 0x0004, 0x782c,
-	0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2409, 0x782b, 0x0002,
-	0x7003, 0x0000, 0x080c, 0x1cef, 0x00ee, 0x00fe, 0x0005, 0xa880,
-	0xd0fc, 0x11a8, 0x8c60, 0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005,
-	0xa004, 0x9005, 0x0168, 0xa85a, 0x2040, 0xa064, 0x9084, 0x000f,
-	0x9080, 0x20c7, 0x2065, 0x8cff, 0x090c, 0x0dc5, 0x8a51, 0x0005,
-	0x2050, 0x0005, 0xa880, 0xd0fc, 0x11b8, 0x8a50, 0x8c61, 0x2c05,
-	0x9005, 0x1190, 0x2800, 0x9906, 0x0120, 0xa000, 0x9005, 0x1108,
-	0x2900, 0x2040, 0xa85a, 0xa064, 0x9084, 0x000f, 0x9080, 0x20d7,
-	0x2065, 0x8cff, 0x090c, 0x0dc5, 0x0005, 0x0000, 0x001d, 0x0021,
-	0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000, 0x001b, 0x0021,
-	0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023, 0x0000, 0x0000,
-	0x20ba, 0x20b6, 0x20ba, 0x20ba, 0x20c4, 0x0000, 0x20ba, 0x20c1,
-	0x20c1, 0x20be, 0x20c1, 0x20c1, 0x0000, 0x20c4, 0x20c1, 0x0000,
-	0x20bc, 0x20bc, 0x0000, 0x20bc, 0x20c4, 0x0000, 0x20bc, 0x20c2,
-	0x20c2, 0x20c2, 0x0000, 0x20c2, 0x0000, 0x20c4, 0x20c2, 0x00c6,
-	0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055, 0x0904, 0x22c6,
-	0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff, 0x9086, 0x0008,
-	0x1118, 0x2061, 0x20c2, 0x00d0, 0x9de0, 0x20c7, 0x9d86, 0x0007,
-	0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f, 0x1120, 0xa08c,
-	0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140, 0x0310, 0x0804,
-	0x22c6, 0xa004, 0x9045, 0x0904, 0x22c6, 0x08d8, 0x2c05, 0x9005,
-	0x0904, 0x21ae, 0xdd9c, 0x1904, 0x216a, 0x908a, 0x0036, 0x1a0c,
-	0x0dc5, 0x9082, 0x001b, 0x0002, 0x213f, 0x213f, 0x2141, 0x213f,
-	0x213f, 0x213f, 0x2147, 0x213f, 0x213f, 0x213f, 0x214d, 0x213f,
-	0x213f, 0x213f, 0x2153, 0x213f, 0x213f, 0x213f, 0x2159, 0x213f,
-	0x213f, 0x213f, 0x215f, 0x213f, 0x213f, 0x213f, 0x2165, 0x080c,
-	0x0dc5, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804, 0x21a4, 0xa08c,
-	0x9422, 0xa090, 0x931b, 0x0804, 0x21a4, 0xa09c, 0x9422, 0xa0a0,
-	0x931b, 0x0804, 0x21a4, 0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0804,
-	0x21a4, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804, 0x21a4, 0xa0cc,
-	0x9422, 0xa0d0, 0x931b, 0x0804, 0x21a4, 0xa0dc, 0x9422, 0xa0e0,
-	0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082, 0x001b,
-	0x0002, 0x218c, 0x218a, 0x218a, 0x218a, 0x218a, 0x218a, 0x2191,
-	0x218a, 0x218a, 0x218a, 0x218a, 0x218a, 0x2196, 0x218a, 0x218a,
-	0x218a, 0x218a, 0x218a, 0x219b, 0x218a, 0x218a, 0x218a, 0x218a,
-	0x218a, 0x21a0, 0x080c, 0x0dc5, 0xa07c, 0x9422, 0xa080, 0x931b,
-	0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070, 0xa0ac, 0x9422,
-	0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8, 0x931b, 0x0020,
-	0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, 0x2300, 0x9405, 0x0160,
-	0x8a51, 0x0904, 0x22c6, 0x8c60, 0x0804, 0x2116, 0xa004, 0x9045,
-	0x0904, 0x22c6, 0x0804, 0x20f1, 0x8a51, 0x0904, 0x22c6, 0x8c60,
-	0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904, 0x22c6, 0xa064,
-	0x90ec, 0x000f, 0x9de0, 0x20c7, 0x2c05, 0x2060, 0xa880, 0xc0fc,
-	0xa882, 0x0804, 0x22bb, 0x2c05, 0x8422, 0x8420, 0x831a, 0x9399,
-	0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x2258, 0x9082, 0x001b,
-	0x0002, 0x21f4, 0x21f4, 0x21f6, 0x21f4, 0x21f4, 0x21f4, 0x2204,
-	0x21f4, 0x21f4, 0x21f4, 0x2212, 0x21f4, 0x21f4, 0x21f4, 0x2220,
-	0x21f4, 0x21f4, 0x21f4, 0x222e, 0x21f4, 0x21f4, 0x21f4, 0x223c,
-	0x21f4, 0x21f4, 0x21f4, 0x224a, 0x080c, 0x0dc5, 0xa17c, 0x2400,
-	0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa074, 0x9420,
-	0xa078, 0x9319, 0x0804, 0x22b6, 0xa18c, 0x2400, 0x9122, 0xa190,
-	0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa084, 0x9420, 0xa088, 0x9319,
-	0x0804, 0x22b6, 0xa19c, 0x2400, 0x9122, 0xa1a0, 0x2300, 0x911b,
-	0x0a0c, 0x0dc5, 0xa094, 0x9420, 0xa098, 0x9319, 0x0804, 0x22b6,
-	0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dc5,
-	0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x22b6, 0xa1bc, 0x2400,
-	0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0b4, 0x9420,
-	0xa0b8, 0x9319, 0x0804, 0x22b6, 0xa1cc, 0x2400, 0x9122, 0xa1d0,
-	0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0c4, 0x9420, 0xa0c8, 0x9319,
-	0x0804, 0x22b6, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b,
-	0x0a0c, 0x0dc5, 0xa0d4, 0x9420, 0xa0d8, 0x9319, 0x0804, 0x22b6,
-	0x9082, 0x001b, 0x0002, 0x2276, 0x2274, 0x2274, 0x2274, 0x2274,
-	0x2274, 0x2283, 0x2274, 0x2274, 0x2274, 0x2274, 0x2274, 0x2290,
-	0x2274, 0x2274, 0x2274, 0x2274, 0x2274, 0x229d, 0x2274, 0x2274,
-	0x2274, 0x2274, 0x2274, 0x22aa, 0x080c, 0x0dc5, 0xa17c, 0x2400,
-	0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa06c, 0x9420,
-	0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122, 0xa198, 0x2300,
-	0x911b, 0x0a0c, 0x0dc5, 0xa084, 0x9420, 0xa088, 0x9319, 0x0430,
-	0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b, 0x0a0c, 0x0dc5,
-	0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4, 0x2400, 0x9122,
-	0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0dc5, 0xa0b4, 0x9420, 0xa0b8,
-	0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0, 0x2300, 0x911b,
-	0x0a0c, 0x0dc5, 0xa0cc, 0x9420, 0xa0d0, 0x9319, 0xac1e, 0xab22,
-	0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, 0x2c00, 0xa812, 0x2a00,
-	0xa816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028, 0x008e, 0x00de,
-	0x00ce, 0x9085, 0x0001, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc,
-	0x190c, 0x0dbe, 0x9084, 0x0007, 0x0002, 0x22e7, 0x1eeb, 0x22e7,
-	0x22dd, 0x22e0, 0x22e3, 0x22e0, 0x22e3, 0x080c, 0x1eeb, 0x0005,
-	0x080c, 0x11b2, 0x0005, 0x080c, 0x1eeb, 0x080c, 0x11b2, 0x0005,
-	0x0126, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x0260, 0x2069,
-	0x1800, 0x7817, 0x0000, 0x789b, 0x0814, 0x78a3, 0x0406, 0x789f,
-	0x0410, 0x2009, 0x013b, 0x200b, 0x0400, 0x781b, 0x0002, 0x783b,
-	0x001f, 0x7837, 0x0020, 0x7803, 0x1600, 0x012e, 0x0005, 0x2091,
-	0x2600, 0x781c, 0xd0a4, 0x190c, 0x2406, 0x7900, 0xd1dc, 0x1118,
-	0x9084, 0x0006, 0x001a, 0x9084, 0x000e, 0x0002, 0x232e, 0x2326,
-	0x8081, 0x2326, 0x2328, 0x2328, 0x2328, 0x2328, 0x8067, 0x2326,
-	0x232a, 0x2326, 0x2328, 0x2326, 0x2328, 0x2326, 0x080c, 0x0dc5,
-	0x0031, 0x0020, 0x080c, 0x8067, 0x080c, 0x8081, 0x0005, 0x0006,
-	0x0016, 0x0026, 0x080c, 0xf0a0, 0x7930, 0x9184, 0x0003, 0x01c0,
-	0x2001, 0x19f7, 0x2004, 0x9005, 0x0170, 0x2001, 0x0133, 0x2004,
-	0x9005, 0x090c, 0x0dc5, 0x00c6, 0x2001, 0x19f7, 0x2064, 0x080c,
-	0xccf3, 0x00ce, 0x00f8, 0x2009, 0x0040, 0x080c, 0x2409, 0x00d0,
-	0x9184, 0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c,
-	0x7637, 0x1138, 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x7563,
-	0x0010, 0x080c, 0x5fed, 0x080c, 0x8130, 0x0041, 0x0018, 0x9184,
-	0x9540, 0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036,
-	0x0046, 0x0056, 0x2071, 0x1a65, 0x080c, 0x1ad9, 0x005e, 0x004e,
-	0x003e, 0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800,
-	0x7128, 0x2001, 0x196f, 0x2102, 0x2001, 0x1977, 0x2102, 0x2001,
-	0x013b, 0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3,
-	0x0200, 0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005,
-	0x2320, 0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423,
-	0x8423, 0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403,
-	0x8003, 0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238,
-	0x2011, 0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182,
-	0x034c, 0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098,
-	0x9182, 0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058,
-	0x9182, 0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018,
-	0x2011, 0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301,
-	0x9402, 0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a,
-	0x012e, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084,
-	0xffc0, 0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069,
-	0x0200, 0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812,
-	0x00de, 0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084,
-	0xfff8, 0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c,
-	0x0dbe, 0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001,
-	0xa001, 0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001,
-	0xa001, 0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061,
-	0x0100, 0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2c67, 0x080c,
-	0x2b82, 0x6054, 0x8004, 0x8004, 0x8004, 0x8004, 0x9084, 0x000c,
-	0x6150, 0x918c, 0xfff3, 0x9105, 0x6052, 0x6050, 0x9084, 0xb17f,
-	0x9085, 0x2000, 0x6052, 0x2009, 0x199d, 0x2011, 0x199e, 0x6358,
-	0x939c, 0x38f0, 0x2320, 0x080c, 0x2bc6, 0x1238, 0x939d, 0x4003,
-	0x94a5, 0x8603, 0x230a, 0x2412, 0x0030, 0x939d, 0x0203, 0x94a5,
-	0x8603, 0x230a, 0x2412, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c,
-	0x2b94, 0x20a9, 0x0012, 0x1d04, 0x245b, 0x2091, 0x6000, 0x1f04,
-	0x245b, 0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400,
-	0x9084, 0xdfff, 0x6052, 0x6024, 0x6026, 0x080c, 0x28ac, 0x2009,
-	0x00ef, 0x6132, 0x6136, 0x080c, 0x28bc, 0x60e7, 0x0000, 0x61ea,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1110, 0x2001,
-	0x0008, 0x60e2, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080,
-	0x602f, 0x0000, 0x6007, 0x349f, 0x60bb, 0x0000, 0x20a9, 0x0018,
-	0x60bf, 0x0000, 0x1f04, 0x2490, 0x60bb, 0x0000, 0x60bf, 0x0108,
-	0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320,
-	0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b,
-	0x602b, 0x402f, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3,
-	0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001,
-	0x1835, 0x2003, 0x0000, 0x2001, 0x1834, 0x2003, 0x0001, 0x0005,
-	0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x0066,
-	0x2031, 0x1837, 0x2634, 0x96b4, 0x0028, 0x006e, 0x1138, 0x6020,
-	0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, 0x1198, 0x9184, 0x5e2c,
-	0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004, 0x9284, 0x0007,
-	0x0082, 0x0016, 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0d70,
-	0x0c98, 0x0016, 0x2001, 0x188b, 0x200c, 0xd194, 0x001e, 0x0d30,
-	0x0c58, 0x2513, 0x24f9, 0x24fc, 0x24ff, 0x2504, 0x2506, 0x250a,
-	0x250e, 0x080c, 0x93e2, 0x00b8, 0x080c, 0x94b1, 0x00a0, 0x080c,
-	0x94b1, 0x080c, 0x93e2, 0x0078, 0x0099, 0x0068, 0x080c, 0x93e2,
-	0x0079, 0x0048, 0x080c, 0x94b1, 0x0059, 0x0028, 0x080c, 0x94b1,
-	0x080c, 0x93e2, 0x0029, 0x002e, 0x001e, 0x000e, 0x012e, 0x0005,
-	0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118, 0xd19c, 0x1904, 0x2784,
-	0xd1f4, 0x190c, 0x0dbe, 0x080c, 0x7637, 0x0904, 0x256e, 0x080c,
-	0xd7e3, 0x1120, 0x7000, 0x9086, 0x0003, 0x0570, 0x6024, 0x9084,
-	0x1800, 0x0550, 0x080c, 0x765a, 0x0118, 0x080c, 0x7648, 0x1520,
-	0x6027, 0x0020, 0x6043, 0x0000, 0x080c, 0xd7e3, 0x0168, 0x080c,
-	0x765a, 0x1150, 0x2001, 0x19a8, 0x2003, 0x0001, 0x6027, 0x1800,
-	0x080c, 0x74b2, 0x0804, 0x2787, 0x70a4, 0x9005, 0x1150, 0x70a7,
-	0x0001, 0x00d6, 0x2069, 0x0140, 0x080c, 0x768b, 0x00de, 0x1904,
-	0x2787, 0x080c, 0x793c, 0x0428, 0x080c, 0x765a, 0x1590, 0x6024,
-	0x9084, 0x1800, 0x1108, 0x0468, 0x080c, 0x793c, 0x080c, 0x7932,
-	0x080c, 0x612e, 0x080c, 0x7563, 0x0804, 0x2784, 0xd1ac, 0x1508,
-	0x6024, 0xd0dc, 0x1170, 0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc,
-	0x0130, 0x7098, 0x9086, 0x0029, 0x1110, 0x080c, 0x7818, 0x0804,
-	0x2784, 0x080c, 0x7937, 0x0048, 0x2001, 0x197d, 0x2003, 0x0002,
-	0x0020, 0x080c, 0x7774, 0x0804, 0x2784, 0x080c, 0x78ba, 0x0804,
-	0x2784, 0x6220, 0xd1bc, 0x0138, 0xd2bc, 0x1904, 0x27e1, 0xd2b4,
-	0x1904, 0x27f4, 0x0000, 0xd1ac, 0x0904, 0x2699, 0x0036, 0x6328,
-	0xc3bc, 0x632a, 0x003e, 0x080c, 0x7637, 0x11c0, 0x6027, 0x0020,
-	0x0006, 0x0026, 0x0036, 0x080c, 0x7651, 0x1158, 0x080c, 0x7932,
-	0x080c, 0x612e, 0x080c, 0x7563, 0x003e, 0x002e, 0x000e, 0x00ae,
-	0x0005, 0x003e, 0x002e, 0x000e, 0x080c, 0x760f, 0x0016, 0x0046,
-	0x00c6, 0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a,
-	0x6043, 0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038,
-	0xd084, 0x0190, 0x080c, 0xd7e3, 0x1118, 0x9186, 0xf800, 0x1160,
-	0x7048, 0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, 0x2011,
-	0x8016, 0x080c, 0x4c44, 0x003e, 0x080c, 0xd7dc, 0x1904, 0x2676,
-	0x9196, 0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff,
-	0x0110, 0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x33aa,
-	0x0128, 0xc18d, 0x7132, 0x080c, 0x6a9b, 0x1510, 0x6240, 0x9294,
-	0x0010, 0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0,
-	0x7030, 0xd08c, 0x0904, 0x2676, 0x7038, 0xd08c, 0x1140, 0x2001,
-	0x180c, 0x200c, 0xd1ac, 0x1904, 0x2676, 0xc1ad, 0x2102, 0x0036,
-	0x73d8, 0x2011, 0x8013, 0x080c, 0x4c44, 0x003e, 0x0804, 0x2676,
-	0x7038, 0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904,
-	0x2676, 0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c,
-	0x4c44, 0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c,
-	0xd1a4, 0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c,
-	0x8a50, 0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xeba1,
-	0x00ce, 0x9484, 0x00ff, 0x9080, 0x33b6, 0x200d, 0x918c, 0xff00,
-	0x810f, 0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xec31, 0x001e,
-	0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x321b, 0x001e,
-	0x00a8, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6724,
-	0x1140, 0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c,
-	0x6148, 0x8108, 0x1f04, 0x2666, 0x00be, 0x015e, 0x00ce, 0x004e,
-	0x080c, 0xb244, 0x60e3, 0x0000, 0x001e, 0x2001, 0x1800, 0x2014,
-	0x9296, 0x0004, 0x1170, 0xd19c, 0x11a0, 0x2011, 0x180c, 0x2214,
-	0xd29c, 0x1120, 0x6204, 0x9295, 0x0002, 0x6206, 0x6228, 0xc29d,
-	0x622a, 0x2003, 0x0001, 0x2001, 0x1826, 0x2003, 0x0000, 0x6027,
-	0x0020, 0xd194, 0x0904, 0x2784, 0x0016, 0x6220, 0xd2b4, 0x0904,
-	0x2721, 0x080c, 0x88c3, 0x080c, 0xa6e9, 0x6027, 0x0004, 0x00f6,
-	0x2019, 0x19f1, 0x2304, 0x907d, 0x0904, 0x26f0, 0x7804, 0x9086,
-	0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6, 0x0096, 0x2069, 0x0140,
-	0x782c, 0x685e, 0x7808, 0x685a, 0x6043, 0x0002, 0x2001, 0x0003,
-	0x8001, 0x1df0, 0x6043, 0x0000, 0x2001, 0x003c, 0x8001, 0x1df0,
-	0x080c, 0x2d49, 0x2001, 0x001e, 0x8001, 0x0240, 0x20a9, 0x0009,
-	0x080c, 0x2c42, 0x6904, 0xd1dc, 0x1140, 0x0cb0, 0x2001, 0x0100,
-	0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x080c, 0x99a5, 0x080c,
-	0x9ab1, 0x7814, 0x2048, 0xa867, 0x0103, 0x2f60, 0x080c, 0xb2d3,
-	0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe, 0x001e, 0x00ae, 0x0005,
-	0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110,
-	0x080c, 0x2d49, 0x00de, 0x00c6, 0x2061, 0x19e8, 0x6028, 0x080c,
-	0xd7e3, 0x0120, 0x909a, 0x0003, 0x1258, 0x0018, 0x909a, 0x00c8,
-	0x1238, 0x8000, 0x602a, 0x00ce, 0x080c, 0xa6c5, 0x0804, 0x2783,
-	0x2061, 0x0100, 0x62c0, 0x080c, 0xb0ca, 0x2019, 0x19f1, 0x2304,
-	0x9065, 0x0120, 0x2009, 0x0027, 0x080c, 0xb352, 0x00ce, 0x0804,
-	0x2783, 0xd2bc, 0x0904, 0x276a, 0x080c, 0x88d0, 0x6014, 0x9084,
-	0x1984, 0x9085, 0x0010, 0x6016, 0x6027, 0x0004, 0x00d6, 0x2069,
-	0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d49, 0x00de,
-	0x00c6, 0x2061, 0x19e8, 0x6044, 0x080c, 0xd7e3, 0x0120, 0x909a,
-	0x0003, 0x1658, 0x0018, 0x909a, 0x00c8, 0x1638, 0x8000, 0x6046,
-	0x603c, 0x00ce, 0x9005, 0x05b8, 0x2009, 0x07d0, 0x080c, 0x88c8,
-	0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x6114, 0x918c,
-	0x1984, 0x918d, 0x0012, 0x6116, 0x0430, 0x9080, 0x0008, 0x2004,
-	0x9086, 0x0009, 0x0d98, 0x6114, 0x918c, 0x1984, 0x918d, 0x0016,
-	0x6116, 0x00c8, 0x6027, 0x0004, 0x00b0, 0x0036, 0x2019, 0x0001,
-	0x080c, 0xaa49, 0x003e, 0x2019, 0x19f7, 0x2304, 0x9065, 0x0150,
-	0x2009, 0x004f, 0x6020, 0x9086, 0x0009, 0x1110, 0x2009, 0x004f,
-	0x080c, 0xb352, 0x00ce, 0x001e, 0xd19c, 0x0904, 0x27dc, 0x7038,
-	0xd0ac, 0x1538, 0x0016, 0x0156, 0x6027, 0x0008, 0x080c, 0x2d73,
-	0x20a9, 0x0028, 0xa001, 0x1f04, 0x2792, 0x6150, 0x9185, 0x1400,
-	0x6052, 0x20a9, 0x0366, 0x1d04, 0x279b, 0x080c, 0x88f7, 0x6020,
-	0xd09c, 0x1130, 0x015e, 0x6152, 0x001e, 0x6027, 0x0008, 0x04a0,
-	0x080c, 0x2c29, 0x1f04, 0x279b, 0x015e, 0x6152, 0x001e, 0x6027,
-	0x0008, 0x0016, 0x6028, 0xc09c, 0x602a, 0x080c, 0xb244, 0x60e3,
-	0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x080c, 0x57d9, 0xd0fc,
-	0x1138, 0x080c, 0xd7dc, 0x1120, 0x9085, 0x0001, 0x080c, 0x767b,
-	0x9006, 0x080c, 0x2d39, 0x2009, 0x0002, 0x080c, 0x2c67, 0x00e6,
-	0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0ea3, 0x00ee, 0x6027,
-	0x0008, 0x080c, 0x0ba0, 0x001e, 0x918c, 0xffd0, 0x6126, 0x00ae,
-	0x0005, 0x0016, 0x2001, 0x188b, 0x200c, 0xd184, 0x001e, 0x0904,
-	0x259b, 0x0016, 0x2009, 0x27ed, 0x00d0, 0x2001, 0x188b, 0x200c,
-	0xc184, 0x2102, 0x001e, 0x0c40, 0x0016, 0x2001, 0x188b, 0x200c,
-	0xd194, 0x001e, 0x0904, 0x259b, 0x0016, 0x2009, 0x2800, 0x0038,
-	0x2001, 0x188b, 0x200c, 0xc194, 0x2102, 0x001e, 0x08a8, 0x6028,
-	0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003, 0xbc91, 0x8000, 0x2003,
-	0xffff, 0x6043, 0x0001, 0x080c, 0x2c61, 0x6027, 0x0080, 0x6017,
-	0x0000, 0x6043, 0x0000, 0x0817, 0x0006, 0x0016, 0x0026, 0x0036,
-	0x00e6, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800, 0x71d0,
-	0x70d2, 0x9116, 0x0904, 0x286b, 0x81ff, 0x01a0, 0x2009, 0x0000,
-	0x080c, 0x2c67, 0x2011, 0x8011, 0x2019, 0x010e, 0x231c, 0x939e,
-	0x0007, 0x1118, 0x2019, 0x0001, 0x0010, 0x2019, 0x0000, 0x080c,
-	0x4c44, 0x0448, 0x2001, 0x19a9, 0x200c, 0x81ff, 0x1140, 0x2001,
-	0x0109, 0x2004, 0xd0b4, 0x0118, 0x2019, 0x0003, 0x0008, 0x2118,
-	0x2011, 0x8012, 0x080c, 0x4c44, 0x080c, 0x0ea3, 0x080c, 0x57d9,
-	0xd0fc, 0x1188, 0x080c, 0xd7dc, 0x1170, 0x00c6, 0x080c, 0x2907,
-	0x080c, 0xa9b0, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009, 0x0002,
-	0x080c, 0x321b, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e, 0x002e,
-	0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094,
-	0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8, 0x81ff,
-	0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011, 0x1820,
-	0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148, 0x2011,
-	0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206, 0x1120,
-	0x2500, 0x080c, 0x83a5, 0x0048, 0x9584, 0x00ff, 0x9080, 0x33b6,
-	0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080, 0x33b6,
-	0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140, 0x2001,
-	0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852, 0x6856,
-	0x1f04, 0x28b7, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026, 0x2069,
-	0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214, 0x8214,
-	0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128, 0x9184,
-	0x000f, 0x9080, 0xf880, 0x2005, 0x6856, 0x8211, 0x1f04, 0x28cc,
-	0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800, 0x6030,
-	0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005, 0x0156,
-	0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980, 0x9116,
-	0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001, 0x0402,
-	0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x28fc, 0x680f,
-	0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005, 0x080c,
-	0x57d5, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046, 0x2020,
-	0x2009, 0x002e, 0x080c, 0xec31, 0x004e, 0x0005, 0x00f6, 0x0016,
-	0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x2973, 0x080c,
-	0x2bc6, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120, 0x2011,
-	0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011, 0x8000,
-	0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009, 0x0001,
-	0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002, 0x00b0,
-	0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078, 0x908e,
-	0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084, 0x0700,
-	0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300, 0x9080,
-	0x0020, 0x2018, 0x080c, 0x9375, 0x928c, 0xff00, 0x0110, 0x2011,
-	0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009, 0x0138,
-	0x220a, 0x080c, 0x7637, 0x1118, 0x2009, 0x196d, 0x220a, 0x002e,
-	0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126, 0x2091,
-	0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c, 0x8000,
-	0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0dbe, 0x002e, 0x001e,
-	0x000e, 0x012e, 0x0005, 0x2001, 0x180d, 0x2004, 0xd08c, 0x0118,
-	0x2009, 0x0002, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc, 0x0168,
-	0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c, 0x1128,
-	0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001, 0x0227,
-	0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001, 0x0226,
-	0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005, 0x0018,
-	0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800, 0x0156,
-	0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1990, 0x2004, 0x908a,
-	0x0007, 0x1a0c, 0x0dc5, 0x0033, 0x00ee, 0x002e, 0x001e, 0x000e,
-	0x015e, 0x0005, 0x29d9, 0x29f7, 0x2a1b, 0x2a1d, 0x2a46, 0x2a48,
-	0x2a4a, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c, 0x2c24, 0x2001,
-	0x1992, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a, 0x9006,
-	0x20a9, 0x0009, 0x080c, 0x2be2, 0x2001, 0x1990, 0x2003, 0x0006,
-	0x2009, 0x001e, 0x2011, 0x2a4b, 0x080c, 0x88d5, 0x0005, 0x2009,
-	0x1995, 0x200b, 0x0000, 0x2001, 0x199a, 0x2003, 0x0036, 0x2001,
-	0x1999, 0x2003, 0x002a, 0x2001, 0x1992, 0x2003, 0x0001, 0x9006,
-	0x080c, 0x2b94, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c, 0x2be2,
-	0x2001, 0x1990, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011, 0x2a4b,
-	0x080c, 0x88d5, 0x0005, 0x080c, 0x0dc5, 0x2001, 0x199a, 0x2003,
-	0x0036, 0x2001, 0x1992, 0x2003, 0x0003, 0x7a38, 0x9294, 0x0005,
-	0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c,
-	0x2b94, 0x2001, 0x1996, 0x2003, 0x0000, 0x2001, 0xffff, 0x20a9,
-	0x0009, 0x080c, 0x2be2, 0x2001, 0x1990, 0x2003, 0x0006, 0x2009,
-	0x001e, 0x2011, 0x2a4b, 0x080c, 0x88d5, 0x0005, 0x080c, 0x0dc5,
-	0x080c, 0x0dc5, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6, 0x00f6,
-	0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001, 0x1992,
-	0x2004, 0x908a, 0x0007, 0x1a0c, 0x0dc5, 0x0043, 0x012e, 0x015e,
-	0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2a6d, 0x2a89,
-	0x2ac5, 0x2af1, 0x2b11, 0x2b1d, 0x2b1f, 0x080c, 0x2bd6, 0x1190,
-	0x2009, 0x1998, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0004,
-	0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1990, 0x2003,
-	0x0001, 0x0030, 0x080c, 0x2b43, 0x2001, 0xffff, 0x080c, 0x29e8,
-	0x0005, 0x080c, 0x2b21, 0x05c0, 0x2009, 0x1999, 0x2104, 0x8001,
-	0x200a, 0x080c, 0x2bd6, 0x1158, 0x7a38, 0x9294, 0x0005, 0x9296,
-	0x0005, 0x0518, 0x2009, 0x1998, 0x2104, 0xc085, 0x200a, 0x2009,
-	0x1995, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118, 0x080c,
-	0x2b29, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006, 0x9296,
-	0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1,
-	0x2001, 0x1992, 0x2003, 0x0002, 0x0028, 0x2001, 0x1990, 0x2003,
-	0x0003, 0x0010, 0x080c, 0x2a0a, 0x0005, 0x080c, 0x2b21, 0x0540,
-	0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x080c, 0x2bd6, 0x1148,
-	0x2001, 0x1990, 0x2003, 0x0003, 0x2001, 0x1991, 0x2003, 0x0000,
-	0x00b8, 0x2009, 0x1999, 0x2104, 0x9005, 0x1118, 0x080c, 0x2b66,
-	0x0010, 0x080c, 0x2b36, 0x080c, 0x2b29, 0x2009, 0x1995, 0x200b,
-	0x0000, 0x2001, 0x1992, 0x2003, 0x0001, 0x080c, 0x2a0a, 0x0000,
-	0x0005, 0x0479, 0x01e8, 0x080c, 0x2bd6, 0x1198, 0x2009, 0x1996,
-	0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078, 0x2001,
-	0x199b, 0x2003, 0x000a, 0x2009, 0x1998, 0x2104, 0xc0fd, 0x200a,
-	0x0038, 0x00f9, 0x2001, 0x1992, 0x2003, 0x0004, 0x080c, 0x2a35,
-	0x0005, 0x0079, 0x0148, 0x080c, 0x2bd6, 0x1118, 0x080c, 0x2a21,
-	0x0018, 0x0079, 0x080c, 0x2a35, 0x0005, 0x080c, 0x0dc5, 0x080c,
-	0x0dc5, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x090c, 0x2b82,
-	0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006,
-	0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, 0x0005, 0x7a38, 0x9294,
-	0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001,
-	0x080c, 0x2b94, 0x0005, 0x2009, 0x1995, 0x2104, 0x8000, 0x200a,
-	0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38, 0x9294,
-	0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001,
-	0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110, 0x9006,
-	0x0010, 0x2001, 0x0001, 0x080c, 0x2bb1, 0x0005, 0x0086, 0x2001,
-	0x1998, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0dc5, 0x2009, 0x1997,
-	0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120, 0xd084,
-	0x1120, 0x080c, 0x0dc5, 0x9006, 0x0010, 0x2001, 0x0001, 0x00a1,
-	0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1990, 0x20a9, 0x0009,
-	0x2003, 0x0000, 0x8000, 0x1f04, 0x2b88, 0x2001, 0x1997, 0x2003,
-	0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085,
-	0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004, 0x783a,
-	0x2009, 0x199d, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084, 0xfffb,
-	0x9085, 0x0006, 0x783a, 0x2009, 0x199e, 0x210c, 0x795a, 0x00fe,
-	0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0138, 0x7838,
-	0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x0030, 0x7838, 0x9084,
-	0xfffb, 0x9085, 0x0005, 0x783a, 0x00fe, 0x0005, 0x0006, 0x2001,
-	0x0100, 0x2004, 0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001,
-	0x0100, 0x2004, 0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9,
-	0x0064, 0x7820, 0x080c, 0x2c61, 0xd09c, 0x1110, 0x1f04, 0x2bd9,
-	0x015e, 0x0005, 0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x7850,
-	0x9085, 0x0040, 0x7852, 0x7850, 0x9084, 0xfbcf, 0x7852, 0x080c,
-	0x2c61, 0x9085, 0x2000, 0x7852, 0x000e, 0x2008, 0x9186, 0x0000,
-	0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118, 0x783b,
-	0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005, 0x0030,
-	0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006, 0x1d04,
-	0x2c0f, 0x080c, 0x88f7, 0x1f04, 0x2c0f, 0x7850, 0x9085, 0x0400,
-	0x9084, 0xdfbf, 0x7852, 0x080c, 0x2c61, 0x9085, 0x1000, 0x7852,
-	0x000e, 0x001e, 0x012e, 0x0005, 0x7850, 0x9084, 0xffcf, 0x7852,
-	0x0005, 0x0006, 0x0156, 0x00f6, 0x2079, 0x0100, 0x20a9, 0x000a,
-	0x7854, 0xd0ac, 0x1130, 0x7820, 0xd0e4, 0x1140, 0x1f04, 0x2c33,
-	0x0028, 0x7854, 0xd08c, 0x1110, 0x1f04, 0x2c39, 0x00fe, 0x015e,
-	0x000e, 0x0005, 0x1d04, 0x2c42, 0x080c, 0x88f7, 0x1f04, 0x2c42,
-	0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0000, 0x000e,
-	0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0001, 0x000e,
-	0x0005, 0x0006, 0x2001, 0x199c, 0x2004, 0x9086, 0x0002, 0x000e,
-	0x0005, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006,
-	0x2001, 0x19a9, 0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104,
-	0xd0dc, 0x0140, 0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001,
-	0xa001, 0x200a, 0x0005, 0x0036, 0x0046, 0x2001, 0x0141, 0x200c,
-	0x918c, 0xff00, 0x9186, 0x2100, 0x0140, 0x9186, 0x2000, 0x0170,
-	0x9186, 0x0100, 0x1904, 0x2cda, 0x0048, 0x0016, 0x2009, 0x1a87,
-	0x2104, 0x8000, 0x0208, 0x200a, 0x001e, 0x04f0, 0x2009, 0x00a2,
-	0x080c, 0x0e52, 0x2019, 0x0160, 0x2324, 0x2011, 0x0003, 0x2009,
-	0x0169, 0x2104, 0x9084, 0x0007, 0x210c, 0x918c, 0x0007, 0x910e,
-	0x1db0, 0x9086, 0x0003, 0x1548, 0x2304, 0x0066, 0x0076, 0x2031,
-	0x0002, 0x233c, 0x973e, 0x0148, 0x8631, 0x1dd8, 0x2031, 0x1a88,
-	0x263c, 0x8738, 0x0208, 0x2732, 0x2304, 0x007e, 0x006e, 0x9402,
-	0x02a0, 0x19d0, 0x8211, 0x19d8, 0x84ff, 0x0170, 0x2001, 0x0141,
-	0x200c, 0x918c, 0xff00, 0x9186, 0x0100, 0x0130, 0x2009, 0x180c,
-	0x2104, 0xc0dd, 0x200a, 0x0008, 0x0421, 0x2001, 0x1981, 0x200c,
-	0x080c, 0x0e52, 0x004e, 0x003e, 0x0005, 0x2001, 0x180c, 0x2004,
-	0xd0dc, 0x01b0, 0x2001, 0x0160, 0x2004, 0x9005, 0x0140, 0x2001,
-	0x0141, 0x2004, 0x9084, 0xff00, 0x9086, 0x0100, 0x1148, 0x0126,
-	0x2091, 0x8000, 0x0016, 0x0026, 0x0021, 0x002e, 0x001e, 0x012e,
-	0x0005, 0x00c6, 0x2061, 0x0100, 0x6014, 0x0006, 0x2001, 0x0161,
-	0x2003, 0x0000, 0x6017, 0x0018, 0xa001, 0xa001, 0x602f, 0x0008,
-	0x6104, 0x918e, 0x0010, 0x6106, 0x918e, 0x0010, 0x6106, 0x6017,
-	0x0040, 0x04b9, 0x001e, 0x9184, 0x0003, 0x01e0, 0x0036, 0x0016,
-	0x2019, 0x0141, 0x6124, 0x918c, 0x0028, 0x1120, 0x2304, 0x9084,
-	0x2800, 0x0dc0, 0x001e, 0x919c, 0xffe4, 0x9184, 0x0001, 0x0118,
-	0x9385, 0x0009, 0x6016, 0x9184, 0x0002, 0x0118, 0x9385, 0x0012,
-	0x6016, 0x003e, 0x2001, 0x180c, 0x200c, 0xc1dc, 0x2102, 0x00ce,
-	0x0005, 0x0016, 0x0026, 0x080c, 0x7651, 0x0108, 0xc0bc, 0x2009,
-	0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e,
-	0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001,
-	0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016,
-	0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a,
-	0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104,
-	0x1128, 0x080c, 0x7651, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a,
-	0x001e, 0x000e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, 0x0040,
-	0x6052, 0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2c61, 0x9085,
-	0x2000, 0x6052, 0x20a9, 0x0012, 0x1d04, 0x2d84, 0x080c, 0x88f7,
-	0x1f04, 0x2d84, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052,
-	0x015e, 0x000e, 0x0005, 0x2fff, 0x2fff, 0x2e23, 0x2e23, 0x2e2f,
-	0x2e2f, 0x2e3b, 0x2e3b, 0x2e49, 0x2e49, 0x2e55, 0x2e55, 0x2e63,
-	0x2e63, 0x2e71, 0x2e71, 0x2e83, 0x2e83, 0x2e8f, 0x2e8f, 0x2e9d,
-	0x2e9d, 0x2ebb, 0x2ebb, 0x2edb, 0x2edb, 0x2eab, 0x2eab, 0x2ecb,
-	0x2ecb, 0x2ee9, 0x2ee9, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2efb, 0x2efb, 0x2f07, 0x2f07, 0x2f15,
-	0x2f15, 0x2f23, 0x2f23, 0x2f33, 0x2f33, 0x2f41, 0x2f41, 0x2f51,
-	0x2f51, 0x2f61, 0x2f61, 0x2f73, 0x2f73, 0x2f81, 0x2f81, 0x2f91,
-	0x2f91, 0x2fb3, 0x2fb3, 0x2fd5, 0x2fd5, 0x2fa1, 0x2fa1, 0x2fc4,
-	0x2fc4, 0x2fe4, 0x2fe4, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81, 0x2e81,
-	0x2e81, 0x2e81, 0x2e81, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x0804, 0x2ff7, 0x0106,
-	0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c,
-	0x22cc, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126,
-	0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x080c,
-	0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x2307, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, 0x2307, 0x0804,
-	0x2ff7, 0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x0804, 0x2ff7, 0x0106,
-	0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c,
-	0x24c0, 0x080c, 0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126,
-	0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c,
-	0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c,
-	0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c,
-	0x1394, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x22cc, 0x080c, 0x1394, 0x080c,
-	0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x1394, 0x080c, 0x2307, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c,
-	0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x0804, 0x2ff7, 0x0106,
-	0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c,
-	0x2976, 0x080c, 0x24c0, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126,
-	0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c,
-	0x22cc, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c,
-	0x24c0, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x2307, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x2307, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x2307, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x24c0, 0x080c,
-	0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x1394, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x1394, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c, 0x1394, 0x0804,
-	0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x2976, 0x080c, 0x24c0, 0x080c, 0x1394, 0x080c,
-	0x2307, 0x0804, 0x2ff7, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc, 0x080c,
-	0x24c0, 0x080c, 0x1394, 0x0498, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc,
-	0x080c, 0x1394, 0x080c, 0x2307, 0x0410, 0x0106, 0x0006, 0x0126,
-	0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c,
-	0x1394, 0x080c, 0x2307, 0x0098, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x2976, 0x080c, 0x22cc,
-	0x080c, 0x24c0, 0x080c, 0x1394, 0x080c, 0x2307, 0x0000, 0x015e,
-	0x014e, 0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d,
-	0x00b6, 0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6a61, 0x1904,
-	0x3137, 0x72dc, 0x2001, 0x197c, 0x2004, 0x9005, 0x1110, 0xd29c,
-	0x0148, 0xd284, 0x1138, 0xd2bc, 0x1904, 0x3137, 0x080c, 0x313c,
-	0x0804, 0x3137, 0xd2cc, 0x1904, 0x3137, 0x080c, 0x7637, 0x1120,
-	0x70af, 0xffff, 0x0804, 0x3137, 0xd294, 0x0120, 0x70af, 0xffff,
-	0x0804, 0x3137, 0x080c, 0x33a5, 0x0160, 0x080c, 0xd7e3, 0x0128,
-	0x2001, 0x1818, 0x203c, 0x0804, 0x30b0, 0x70af, 0xffff, 0x0804,
-	0x3137, 0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x30b0,
-	0xd28c, 0x1904, 0x30b0, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110,
-	0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0x938c, 0x0001,
-	0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e,
-	0x0904, 0x30a6, 0x908e, 0x0000, 0x0904, 0x30a6, 0x908e, 0x00ff,
-	0x1160, 0x7230, 0xd284, 0x1904, 0x30ab, 0x7294, 0xc28d, 0x7296,
-	0x70af, 0xffff, 0x003e, 0x0804, 0x30b0, 0x2009, 0x180d, 0x210c,
-	0xd18c, 0x0150, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e,
-	0x0118, 0x70af, 0xffff, 0x0488, 0x900e, 0x080c, 0x2873, 0x080c,
-	0x66b9, 0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148,
-	0x00c6, 0x2060, 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af,
-	0x0000, 0x080c, 0x6aa3, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800,
-	0xd0bc, 0x0138, 0x080c, 0x6944, 0x0120, 0x080c, 0x3155, 0x0148,
-	0x0028, 0x080c, 0x3295, 0x080c, 0x3181, 0x0118, 0x8318, 0x0804,
-	0x304a, 0x73ae, 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x3137,
-	0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e,
-	0x70ac, 0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812,
-	0x0220, 0x2008, 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804,
-	0x3137, 0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x312c, 0x2001,
-	0x180d, 0x2004, 0xd08c, 0x0158, 0x0026, 0x2011, 0x0010, 0x080c,
-	0x6ac7, 0x002e, 0x0120, 0x2009, 0xffff, 0x0804, 0x3134, 0xc484,
-	0x080c, 0x6724, 0x0168, 0x080c, 0xd7e3, 0x1904, 0x312c, 0x080c,
-	0x33a5, 0x1904, 0x312c, 0x080c, 0x66b9, 0x1904, 0x3134, 0x0008,
-	0xc485, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060,
-	0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, 0x0000, 0x080c,
-	0x6aa3, 0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0,
-	0x7294, 0xd28c, 0x0180, 0x080c, 0x6aa3, 0x9082, 0x0006, 0x02e0,
-	0xd484, 0x1118, 0x080c, 0x66de, 0x0028, 0x080c, 0x3321, 0x01a0,
-	0x080c, 0x334c, 0x0088, 0x080c, 0x3295, 0x080c, 0xd7e3, 0x1160,
-	0x080c, 0x3181, 0x0188, 0x0040, 0x080c, 0xd7e3, 0x1118, 0x080c,
-	0x3321, 0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04,
-	0x30c9, 0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e,
-	0x002e, 0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001,
-	0x2009, 0x007e, 0x080c, 0x66b9, 0x1168, 0xb813, 0x00ff, 0xb817,
-	0xfffe, 0x080c, 0x3295, 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de,
-	0x080c, 0xd52b, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6,
-	0x00c6, 0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c,
-	0xb325, 0x01d0, 0x2b00, 0x6012, 0x080c, 0xd554, 0x6023, 0x0001,
-	0x9006, 0x080c, 0x6656, 0x2001, 0x0000, 0x080c, 0x666a, 0x0126,
-	0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004,
-	0x080c, 0xb352, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e,
-	0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004,
-	0x9084, 0x00ff, 0xb842, 0x080c, 0xb325, 0x0548, 0x2b00, 0x6012,
-	0xb800, 0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804,
-	0x9084, 0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x3250, 0x080c,
-	0xd554, 0x6023, 0x0001, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002,
-	0x080c, 0x666a, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa,
-	0x012e, 0x2009, 0x0002, 0x080c, 0xb352, 0x9085, 0x0001, 0x00ce,
-	0x00de, 0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009,
-	0x0080, 0x080c, 0x66b9, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc,
-	0x0039, 0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005,
-	0x0016, 0x0076, 0x00d6, 0x00c6, 0x080c, 0xb27d, 0x01d0, 0x2b00,
-	0x6012, 0x080c, 0xd554, 0x6023, 0x0001, 0x9006, 0x080c, 0x6656,
-	0x2001, 0x0002, 0x080c, 0x666a, 0x0126, 0x2091, 0x8000, 0x70e4,
-	0x8000, 0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xb352, 0x9085,
-	0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6,
-	0x0126, 0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x66b9, 0x11b8,
-	0xb813, 0x00ff, 0xb817, 0xfffd, 0xb8cf, 0x0004, 0x080c, 0xb27d,
-	0x0170, 0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c,
-	0xd554, 0x2009, 0x0022, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e,
-	0x00de, 0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026,
-	0x00b6, 0x21f0, 0x080c, 0x96af, 0x080c, 0x962f, 0x080c, 0xb111,
-	0x080c, 0xc2d3, 0x3e08, 0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e,
-	0x900e, 0x0018, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724,
-	0x1140, 0x9686, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c,
-	0x6148, 0x001e, 0x8108, 0x1f04, 0x3235, 0x9686, 0x0001, 0x190c,
-	0x3379, 0x00be, 0x002e, 0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005,
-	0x00e6, 0x00c6, 0x0046, 0x0036, 0x0026, 0x0016, 0x00b6, 0x6210,
-	0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076,
-	0x2039, 0x0000, 0x080c, 0x9577, 0x2c08, 0x080c, 0xe91c, 0x007e,
-	0x001e, 0xba10, 0xbb14, 0xbcc0, 0x080c, 0x6148, 0xba12, 0xbb16,
-	0xbcc2, 0x00be, 0x001e, 0x002e, 0x003e, 0x004e, 0x00ce, 0x00ee,
-	0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010, 0x2058, 0xb8a0, 0x00be,
-	0x9086, 0x0080, 0x0150, 0x2071, 0x1800, 0x70a8, 0x9005, 0x0110,
-	0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x70e4,
-	0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8, 0xb800, 0xc08c, 0xb802,
-	0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6, 0x0046, 0x0036, 0x0026,
-	0x0016, 0x0156, 0x2178, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078,
-	0x080c, 0x57d5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020,
-	0x2009, 0x002d, 0x080c, 0xec31, 0x20a9, 0x0800, 0x9016, 0x0026,
-	0x928e, 0x007e, 0x0904, 0x3300, 0x928e, 0x007f, 0x0904, 0x3300,
-	0x928e, 0x0080, 0x05e8, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c0,
-	0x8fff, 0x1148, 0x2001, 0x198e, 0x0006, 0x2003, 0x0001, 0x04f1,
-	0x000e, 0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001,
-	0x080c, 0x6a6d, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x96a4,
-	0x0076, 0x2039, 0x0000, 0x080c, 0x9577, 0x00b6, 0x00c6, 0x0026,
-	0x2158, 0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807,
-	0x0404, 0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e,
-	0x00ce, 0x00be, 0x0016, 0x2c08, 0x080c, 0xe91c, 0x001e, 0x007e,
-	0x002e, 0x8210, 0x1f04, 0x32b7, 0x015e, 0x001e, 0x002e, 0x003e,
-	0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0046, 0x0026,
-	0x0016, 0x080c, 0x57d5, 0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006,
-	0x2220, 0x2009, 0x0029, 0x080c, 0xec31, 0x001e, 0x002e, 0x004e,
-	0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294, 0x82ff, 0x01e8,
-	0x080c, 0x6a9b, 0x11d0, 0x2100, 0x080c, 0x28a6, 0x81ff, 0x01b8,
-	0x2019, 0x0001, 0x8314, 0x92e0, 0x1c80, 0x2c04, 0xd384, 0x0120,
-	0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x9116, 0x0138,
-	0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085, 0x0001, 0x00ce,
-	0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x0036, 0x2019, 0x0029, 0x00a9, 0x003e, 0x9180, 0x1000,
-	0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1ab7, 0x001e,
-	0x6112, 0x080c, 0x3250, 0x001e, 0x080c, 0x66de, 0x012e, 0x00ce,
-	0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0xac6c, 0x080c,
-	0xef94, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc,
-	0x0005, 0x00c6, 0x00b6, 0x080c, 0x7637, 0x1118, 0x20a9, 0x0800,
-	0x0010, 0x20a9, 0x0782, 0x080c, 0x7637, 0x1110, 0x900e, 0x0010,
-	0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff,
-	0x0110, 0xb800, 0xd0bc, 0x090c, 0x66de, 0x8108, 0x1f04, 0x338a,
-	0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, 0x6082,
-	0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, 0x2004,
-	0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, 0x0026,
-	0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, 0x7de8,
-	0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6,
-	0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc,
-	0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc,
-	0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1,
-	0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6,
-	0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797,
-	0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c,
-	0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071,
-	0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66,
-	0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454,
-	0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a,
-	0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039,
-	0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d,
-	0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123,
-	0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f,
-	0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700,
-	0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000,
-	0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000,
-	0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700,
-	0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100,
-	0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00,
-	0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400,
-	0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00,
-	0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800,
-	0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400,
-	0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189e,
-	0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e,
-	0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, 0x0001,
-	0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x706a, 0xa867, 0x0002,
-	0xa8ab, 0xdcb0, 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x706e,
-	0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, 0x7004,
-	0x0002, 0x34e5, 0x34e6, 0x34f9, 0x350d, 0x0005, 0x1004, 0x34f6,
-	0x0e04, 0x34f6, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c,
-	0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e,
-	0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, 0xa86c, 0x908e,
-	0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x35e1, 0x0005, 0x7018,
-	0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864,
-	0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128,
-	0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061,
-	0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040,
-	0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x35de,
-	0x61d0, 0x0804, 0x3573, 0x35b5, 0x35ed, 0x35de, 0x35f9, 0x3603,
-	0x3609, 0x360d, 0x361d, 0x3621, 0x3637, 0x363d, 0x3643, 0x364e,
-	0x3659, 0x3668, 0x3677, 0x3685, 0x369c, 0x36b7, 0x35de, 0x3762,
-	0x37a0, 0x3846, 0x3857, 0x387a, 0x35de, 0x35de, 0x35de, 0x38b2,
-	0x38ce, 0x38d7, 0x3906, 0x390c, 0x35de, 0x3952, 0x35de, 0x35de,
-	0x35de, 0x35de, 0x35de, 0x395d, 0x3966, 0x396e, 0x3970, 0x35de,
-	0x35de, 0x35de, 0x35de, 0x35de, 0x35de, 0x399c, 0x35de, 0x35de,
-	0x35de, 0x35de, 0x35de, 0x39b9, 0x3a40, 0x35de, 0x35de, 0x35de,
-	0x35de, 0x35de, 0x35de, 0x0002, 0x3a6a, 0x3a6d, 0x3acc, 0x3ae5,
-	0x3b15, 0x3db7, 0x35de, 0x5398, 0x35de, 0x35de, 0x35de, 0x35de,
-	0x35de, 0x35de, 0x35de, 0x35de, 0x3637, 0x363d, 0x42ec, 0x57f9,
-	0x430a, 0x5427, 0x5479, 0x5584, 0x35de, 0x55e6, 0x5622, 0x5653,
-	0x575b, 0x5680, 0x56db, 0x35de, 0x430e, 0x44e1, 0x44f7, 0x451c,
-	0x4581, 0x45f5, 0x4615, 0x468c, 0x46e8, 0x4744, 0x4747, 0x476c,
-	0x4823, 0x4889, 0x4891, 0x49c6, 0x4b6e, 0x4ba2, 0x4e06, 0x35de,
-	0x4e24, 0x4eeb, 0x4fd4, 0x502e, 0x35de, 0x50c1, 0x35de, 0x50d7,
-	0x50f2, 0x4891, 0x5338, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c,
-	0x4c20, 0x0126, 0x2091, 0x8000, 0x0e04, 0x35bf, 0x0010, 0x012e,
-	0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010,
-	0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080,
-	0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x7007, 0x0001,
-	0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001,
-	0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021,
-	0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e,
-	0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x81ff, 0x0d98, 0x0804,
-	0x4c2d, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884,
-	0x7990, 0x0804, 0x4c30, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804,
-	0x35b5, 0x7984, 0x2114, 0x0804, 0x35b5, 0x20e1, 0x0000, 0x2099,
-	0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003,
-	0x7984, 0x7a88, 0x7b8c, 0x0804, 0x35b5, 0x7884, 0x2060, 0x0804,
-	0x366a, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0014, 0x789b,
-	0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118,
-	0x7896, 0x0804, 0x35b5, 0x7897, 0x0001, 0x0804, 0x35b5, 0x2039,
-	0x0001, 0x7d98, 0x7c9c, 0x0804, 0x35f1, 0x2039, 0x0001, 0x7d98,
-	0x7c9c, 0x0804, 0x35fd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804,
-	0x35ea, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x35f1, 0x79a0, 0x9182,
-	0x0040, 0x0210, 0x0804, 0x35ea, 0x2138, 0x7d98, 0x7c9c, 0x0804,
-	0x35fd, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x35ea, 0x21e8,
-	0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x35b5,
-	0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109,
-	0x1dd8, 0x2010, 0x9005, 0x0904, 0x35b5, 0x0804, 0x35e4, 0x79a0,
-	0x9182, 0x0040, 0x0210, 0x0804, 0x35ea, 0x21e0, 0x20a9, 0x0001,
-	0x7984, 0x2198, 0x4012, 0x0804, 0x35b5, 0x2069, 0x1847, 0x7884,
-	0x7990, 0x911a, 0x1a04, 0x35ea, 0x8019, 0x0904, 0x35ea, 0x684a,
-	0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e,
-	0x080c, 0x7963, 0x0804, 0x35b5, 0x2069, 0x1847, 0x7884, 0x7994,
-	0x911a, 0x1a04, 0x35ea, 0x8019, 0x0904, 0x35ea, 0x684e, 0x6946,
-	0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x6bf8, 0x012e, 0x0804, 0x35b5, 0x902e,
-	0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35e7, 0x7984,
-	0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6,
-	0x4101, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7,
-	0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d,
-	0x701f, 0x36db, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096,
-	0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138,
-	0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x35e7, 0x810f,
-	0x918c, 0x00ff, 0x0904, 0x35e7, 0x7112, 0x7010, 0x8001, 0x0560,
-	0x7012, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7,
-	0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598,
-	0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000,
-	0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x3719,
-	0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096,
-	0x000a, 0x1904, 0x35e7, 0x0888, 0x0126, 0x2091, 0x8000, 0x7014,
-	0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096,
-	0x0029, 0x1148, 0xc2fd, 0xaa7a, 0x080c, 0x629f, 0x0138, 0xa87a,
-	0xa982, 0x012e, 0x0060, 0x080c, 0x65cf, 0x1130, 0x7007, 0x0003,
-	0x701f, 0x3747, 0x012e, 0x0005, 0x080c, 0x710b, 0x012e, 0x0126,
-	0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6,
-	0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9,
-	0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60,
-	0x0804, 0x4c30, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010,
-	0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020,
-	0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100,
-	0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009,
-	0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001,
-	0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a1c, 0x2004, 0x9005,
-	0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a,
-	0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427,
-	0x81ff, 0x1904, 0x35e7, 0x7984, 0x080c, 0x6724, 0x1904, 0x35ea,
-	0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x35ea, 0x7c88,
-	0x7d8c, 0x080c, 0x6887, 0x080c, 0x6856, 0x0000, 0x1518, 0x2061,
-	0x1cd0, 0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148,
-	0x6014, 0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506,
-	0x0150, 0x012e, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02,
-	0x1a04, 0x35e7, 0x0c30, 0x080c, 0xccf3, 0x012e, 0x0904, 0x35e7,
-	0x0804, 0x35b5, 0x900e, 0x2001, 0x0005, 0x080c, 0x710b, 0x0126,
-	0x2091, 0x8000, 0x080c, 0xd3d4, 0x080c, 0x6e9f, 0x012e, 0x0804,
-	0x35b5, 0x00a6, 0x2950, 0xb198, 0x080c, 0x6724, 0x1904, 0x3833,
-	0xb6a4, 0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0,
-	0x080c, 0x6887, 0x080c, 0x6856, 0x1520, 0x2061, 0x1cd0, 0x0126,
-	0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d,
-	0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e,
-	0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d,
-	0x12b0, 0x0c28, 0x080c, 0xccf3, 0x012e, 0x2009, 0x0003, 0x0178,
-	0x00e0, 0x900e, 0x2001, 0x0005, 0x080c, 0x710b, 0x0126, 0x2091,
-	0x8000, 0x080c, 0xd3d4, 0x080c, 0x6e92, 0x012e, 0x0070, 0xb097,
-	0x4005, 0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001,
-	0x2001, 0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006,
-	0x918d, 0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904,
-	0x35e7, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x67eb, 0x0904,
-	0x35e7, 0x080c, 0x688d, 0x0904, 0x35e7, 0x0804, 0x460c, 0x81ff,
-	0x1904, 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x691b,
-	0x0904, 0x35e7, 0x2019, 0x0005, 0x79a8, 0x080c, 0x68a8, 0x0904,
-	0x35e7, 0x7888, 0x908a, 0x1000, 0x1a04, 0x35ea, 0x8003, 0x800b,
-	0x810b, 0x9108, 0x080c, 0x884b, 0x79a8, 0xd184, 0x1904, 0x35b5,
-	0x0804, 0x460c, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009,
-	0x0001, 0x0450, 0x2029, 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8,
-	0x2508, 0x080c, 0x6724, 0x11d8, 0x080c, 0x691b, 0x1128, 0x2009,
-	0x0002, 0x62c0, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c,
-	0x68a8, 0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000,
-	0x1270, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x884b, 0x8529,
-	0x1ae0, 0x012e, 0x0804, 0x35b5, 0x012e, 0x0804, 0x35e7, 0x012e,
-	0x0804, 0x35ea, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x67eb,
-	0x0904, 0x35e7, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066, 0x080c,
-	0x96a4, 0x0076, 0x903e, 0x080c, 0x9577, 0x900e, 0x080c, 0xe91c,
-	0x007e, 0x00ce, 0x080c, 0x6887, 0x0804, 0x35b5, 0x080c, 0x4bfb,
-	0x0904, 0x35ea, 0x080c, 0x6887, 0x2208, 0x0804, 0x35b5, 0x0156,
-	0x00d6, 0x00e6, 0x2069, 0x1910, 0x6810, 0x6914, 0x910a, 0x1208,
-	0x900e, 0x6816, 0x9016, 0x901e, 0x20a9, 0x007e, 0x2069, 0x1000,
-	0x2d04, 0x905d, 0x0118, 0xb84c, 0x0059, 0x9210, 0x8d68, 0x1f04,
-	0x38e8, 0x2300, 0x9218, 0x00ee, 0x00de, 0x015e, 0x0804, 0x35b5,
-	0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff,
-	0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910,
-	0x6910, 0x62bc, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001,
-	0x0804, 0x35e7, 0x0126, 0x2091, 0x8000, 0x080c, 0x57e9, 0x0128,
-	0x2009, 0x0007, 0x012e, 0x0804, 0x35e7, 0x012e, 0x615c, 0x9190,
-	0x33b6, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280,
-	0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001,
-	0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003,
-	0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002,
-	0x0068, 0x080c, 0x7637, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c,
-	0x0120, 0x2009, 0x0005, 0x0804, 0x35e7, 0x9036, 0x7e9a, 0x7f9e,
-	0x0804, 0x35b5, 0x614c, 0x6250, 0x2019, 0x1986, 0x231c, 0x2001,
-	0x1987, 0x2004, 0x789a, 0x0804, 0x35b5, 0x0126, 0x2091, 0x8000,
-	0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x35b5, 0x080c, 0x4c17,
-	0x0904, 0x35ea, 0xba44, 0xbb38, 0x0804, 0x35b5, 0x080c, 0x0dc5,
-	0x080c, 0x4c17, 0x2110, 0x0904, 0x35ea, 0xb804, 0x908c, 0x00ff,
-	0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009,
-	0x0009, 0x1904, 0x35e7, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005,
-	0x00c6, 0x9066, 0x080c, 0xac6c, 0x080c, 0x96a4, 0x0076, 0x903e,
-	0x080c, 0x9577, 0x900e, 0x080c, 0xe91c, 0x007e, 0x00ce, 0xb807,
-	0x0407, 0x012e, 0x0804, 0x35b5, 0x614c, 0x6250, 0x7884, 0x604e,
-	0x7b88, 0x6352, 0x2069, 0x1847, 0x831f, 0x9305, 0x6816, 0x788c,
-	0x2069, 0x1986, 0x2d1c, 0x206a, 0x7e98, 0x9682, 0x0014, 0x1210,
-	0x2031, 0x07d0, 0x2069, 0x1987, 0x2d04, 0x266a, 0x789a, 0x0804,
-	0x35b5, 0x0126, 0x2091, 0x8000, 0x6138, 0x7884, 0x603a, 0x910e,
-	0xd1b4, 0x190c, 0x0ebe, 0xd094, 0x0148, 0x00e6, 0x2071, 0x19fb,
-	0x79b4, 0x9192, 0x07d0, 0x1208, 0x713e, 0x00ee, 0xd0c4, 0x01a8,
-	0x00d6, 0x78a8, 0x2009, 0x199d, 0x200a, 0x78ac, 0x2011, 0x199e,
-	0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118, 0x2214,
-	0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0xd0ec, 0x0178,
-	0x6034, 0xc08d, 0x6036, 0x2001, 0x0050, 0x6076, 0x607a, 0x6056,
-	0x606b, 0x2450, 0x00c6, 0x2061, 0x1ad1, 0x2062, 0x00ce, 0x2011,
-	0x0114, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0080, 0x0010,
-	0x918c, 0xff7f, 0x2112, 0x603c, 0x7988, 0x613e, 0x6140, 0x910d,
-	0x788c, 0x6042, 0x7a88, 0x9294, 0x1000, 0x9205, 0x910e, 0xd1e4,
-	0x190c, 0x0ed4, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046, 0x9084,
-	0x0001, 0x090c, 0x42ec, 0x6040, 0xd0cc, 0x0120, 0x78b0, 0x2011,
-	0x0114, 0x2012, 0x012e, 0x0804, 0x35b5, 0x00f6, 0x2079, 0x1800,
-	0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084, 0xfebf,
-	0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a, 0xa897,
-	0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe, 0x0005,
-	0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x35ea, 0x788c,
-	0x902d, 0x0904, 0x35ea, 0x900e, 0x080c, 0x6724, 0x1120, 0xba44,
-	0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108, 0x0ca0,
-	0x080c, 0x4c17, 0x0904, 0x35ea, 0x7888, 0x900d, 0x0904, 0x35ea,
-	0x788c, 0x9005, 0x0904, 0x35ea, 0xba44, 0xb946, 0xbb38, 0xb83a,
-	0x0804, 0x35b5, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05, 0x080c,
-	0x57e9, 0x1904, 0x35e7, 0x00c6, 0x2061, 0x0100, 0x7984, 0x9186,
-	0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00, 0x0088,
-	0x9182, 0x007f, 0x16e0, 0x9188, 0x33b6, 0x210d, 0x918c, 0x00ff,
-	0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580, 0x810f,
-	0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xb27d, 0x000e,
-	0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x66bf, 0x2b08,
-	0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4be4, 0x01d0,
-	0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd, 0xa86a,
-	0x701f, 0x3ac5, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c, 0xb352,
-	0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x35e7, 0x00ce,
-	0x0804, 0x35ea, 0x080c, 0xb2d3, 0x0cb0, 0xa830, 0x9086, 0x0100,
-	0x0904, 0x35e7, 0x0804, 0x35b5, 0x2061, 0x1a74, 0x0126, 0x2091,
-	0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061, 0x1800,
-	0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa, 0x012e,
-	0x0804, 0x35b5, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904, 0x35e7,
-	0x080c, 0x7637, 0x0904, 0x35e7, 0x0126, 0x2091, 0x8000, 0x6254,
-	0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x28dc, 0x080c,
-	0x5a11, 0x012e, 0x0804, 0x35b5, 0x012e, 0x0804, 0x35ea, 0x0006,
-	0x0016, 0x00c6, 0x00e6, 0x2001, 0x19aa, 0x2070, 0x2061, 0x1847,
-	0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x9375, 0x7206,
-	0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x35b7, 0x7884,
-	0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, 0x0180, 0x9082,
-	0x00e1, 0x0298, 0x012e, 0x0804, 0x35ea, 0x2001, 0x002a, 0x2004,
-	0x9005, 0x0128, 0x2069, 0x1847, 0x6908, 0x9102, 0x1230, 0x012e,
-	0x0804, 0x35ea, 0x012e, 0x0804, 0x35e7, 0x080c, 0xb23d, 0x0dd0,
-	0x7884, 0xd0fc, 0x0904, 0x3b94, 0x00c6, 0x080c, 0x4be4, 0x00ce,
-	0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e, 0x789c,
-	0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f, 0x2004,
-	0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031, 0x2004,
-	0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035, 0x2004,
-	0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084, 0x00fc,
-	0x8004, 0xa816, 0x080c, 0x3d1a, 0x0928, 0x7014, 0x2048, 0xad2c,
-	0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029,
-	0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f,
-	0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c2d, 0x701f, 0x3c57,
-	0x7023, 0x0001, 0x012e, 0x0005, 0x0046, 0x0086, 0x0096, 0x00a6,
-	0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3aff, 0x2001,
-	0x19a0, 0x2003, 0x0000, 0x2021, 0x000a, 0x2061, 0x0100, 0x6104,
-	0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1, 0x60bf, 0x0012, 0x080c,
-	0x3d89, 0x080c, 0x3d48, 0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071,
-	0x1a69, 0x2079, 0x0090, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4,
-	0x0140, 0x2001, 0x0035, 0x2004, 0x780e, 0x2001, 0x0034, 0x2004,
-	0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4130, 0x008e, 0x00ee,
-	0x00fe, 0x080c, 0x4052, 0x080c, 0x3f57, 0x05b8, 0x2001, 0x020b,
-	0x2004, 0x9084, 0x0140, 0x1db8, 0x080c, 0x41a4, 0x00f6, 0x2079,
-	0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x1560, 0x2071, 0x0200,
-	0x7037, 0x0000, 0x7050, 0x9084, 0xff00, 0x9086, 0x3200, 0x1510,
-	0x7037, 0x0001, 0x7050, 0x9084, 0xff00, 0x9086, 0xe100, 0x11d0,
-	0x7037, 0x0000, 0x7054, 0x7037, 0x0000, 0x715c, 0x9106, 0x1190,
-	0x2001, 0x1820, 0x2004, 0x9106, 0x1168, 0x00c6, 0x2061, 0x0100,
-	0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138, 0x080c, 0x3f61, 0x080c,
-	0x3d43, 0x0058, 0x080c, 0x3d43, 0x080c, 0x40c8, 0x080c, 0x4048,
-	0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8, 0x2001, 0x032a, 0x2003,
-	0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x001e, 0x6106, 0x2011,
-	0x020d, 0x2013, 0x0020, 0x60bb, 0x0000, 0x60bf, 0x0108, 0x60bf,
-	0x0012, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd, 0x2102, 0x080c,
-	0x12fc, 0x2009, 0x0028, 0x080c, 0x2409, 0x2001, 0x0227, 0x200c,
-	0x2102, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e,
-	0x008e, 0x004e, 0x2001, 0x19a0, 0x2004, 0x9005, 0x1118, 0x012e,
-	0x0804, 0x35b5, 0x012e, 0x2021, 0x400c, 0x0804, 0x35b7, 0x0016,
-	0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6,
-	0x0156, 0x7014, 0x2048, 0x7020, 0x20a8, 0x8000, 0x7022, 0xa804,
-	0x9005, 0x0904, 0x3cb3, 0x2048, 0x1f04, 0x3c67, 0x7068, 0x2040,
-	0xa28c, 0xa390, 0xa494, 0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120,
-	0x2029, 0x0000, 0x2021, 0x0000, 0x0096, 0x7014, 0x2048, 0xa864,
-	0x009e, 0x9086, 0x0103, 0x0170, 0x8906, 0x8006, 0x8007, 0x90bc,
-	0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c2d, 0x701f,
-	0x3c57, 0x00b0, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084,
-	0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0,
-	0x0006, 0x080c, 0x0f8b, 0x000e, 0x080c, 0x4c30, 0x701f, 0x3c57,
-	0x015e, 0x00de, 0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e,
-	0x002e, 0x001e, 0x0005, 0x7014, 0x2048, 0xa864, 0x9086, 0x0103,
-	0x1118, 0x701f, 0x3d18, 0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd,
-	0xa86a, 0x2009, 0x007f, 0x080c, 0x66b9, 0x0110, 0x9006, 0x0030,
-	0xb813, 0x00ff, 0xb817, 0xfffd, 0x080c, 0xd5a7, 0x015e, 0x00de,
-	0x009e, 0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e,
-	0x0904, 0x35e7, 0x0016, 0x0026, 0x0036, 0x0046, 0x0056, 0x0076,
-	0x0086, 0x0096, 0x00d6, 0x0156, 0x701f, 0x3cea, 0x7007, 0x0003,
-	0x0804, 0x3ca8, 0xa830, 0x9086, 0x0100, 0x2021, 0x400c, 0x0904,
-	0x35b7, 0x0076, 0xad10, 0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808,
-	0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006,
-	0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8,
-	0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0f8b, 0x000e,
-	0x080c, 0x4c30, 0x007e, 0x701f, 0x3c57, 0x7023, 0x0001, 0x0005,
-	0x0804, 0x35b5, 0x0156, 0x00c6, 0xa814, 0x908a, 0x001e, 0x0218,
-	0xa833, 0x001e, 0x0010, 0xa832, 0x0078, 0x81ff, 0x0168, 0x0016,
-	0x080c, 0x4be4, 0x001e, 0x0130, 0xa800, 0x2040, 0xa008, 0xa80a,
-	0x2100, 0x0c58, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x015e,
-	0x0005, 0x0006, 0x00f6, 0x2079, 0x0000, 0x7880, 0x9086, 0x0044,
-	0x00fe, 0x000e, 0x0005, 0x2001, 0x19a0, 0x2003, 0x0001, 0x0005,
-	0x00f6, 0x00e6, 0x00c6, 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004,
-	0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104,
-	0xc1ac, 0x6106, 0x080c, 0x4be4, 0xa813, 0x0019, 0xa817, 0x0001,
-	0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001, 0x002f,
-	0x2004, 0xa86a, 0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa,
-	0x2004, 0x6036, 0x2009, 0x0040, 0x080c, 0x2409, 0x2001, 0x002a,
-	0x2004, 0x9084, 0xfff8, 0xa86e, 0x601a, 0xa873, 0x0000, 0x601f,
-	0x0000, 0x78ca, 0x9006, 0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe,
-	0x0005, 0x00e6, 0x080c, 0x4be4, 0x2940, 0xa013, 0x0019, 0xa017,
-	0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa866, 0x2001,
-	0x0031, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8,
-	0xa86e, 0xa873, 0x0000, 0x2001, 0x032a, 0x2003, 0x0004, 0x2001,
-	0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001,
-	0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x81ff, 0x0148, 0x080c, 0x2c59, 0x1130, 0x9006,
-	0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94, 0x2001, 0x199f, 0x2003,
-	0x0000, 0x7884, 0x9084, 0x0007, 0x0002, 0x3dd8, 0x3de1, 0x3dea,
-	0x3dd5, 0x3dd5, 0x3dd5, 0x3dd5, 0x3dd5, 0x012e, 0x0804, 0x35ea,
-	0x2009, 0x0114, 0x2104, 0x9085, 0x0800, 0x200a, 0x080c, 0x3fab,
-	0x00c0, 0x2009, 0x0114, 0x2104, 0x9085, 0x4000, 0x200a, 0x080c,
-	0x3fab, 0x0078, 0x080c, 0x7637, 0x1128, 0x012e, 0x2009, 0x0016,
-	0x0804, 0x35e7, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804,
-	0x35b7, 0x2001, 0x0141, 0x2004, 0xd0dc, 0x0db0, 0x0086, 0x0096,
-	0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3aff,
-	0x2009, 0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068,
-	0x2060, 0x2058, 0x080c, 0x427f, 0x080c, 0x41cf, 0x903e, 0x2720,
-	0x00f6, 0x00e6, 0x0086, 0x2940, 0x2071, 0x1a69, 0x2079, 0x0090,
-	0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e,
-	0x68d0, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x4130, 0x080c,
-	0x2c61, 0x080c, 0x2c61, 0x080c, 0x2c61, 0x080c, 0x2c61, 0x080c,
-	0x4130, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x4052, 0x2009, 0x9c40,
-	0x8109, 0x11b0, 0x080c, 0x3f61, 0x2001, 0x0004, 0x200c, 0x918c,
-	0xfffd, 0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be,
-	0x00ae, 0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x35e7, 0x0cf8,
-	0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079,
-	0x0000, 0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c,
-	0x81ff, 0x0150, 0x080c, 0x4030, 0x2d00, 0x9c05, 0x9b05, 0x0120,
-	0x080c, 0x3f61, 0x0804, 0x3f0e, 0x080c, 0x41a4, 0x080c, 0x40c8,
-	0x080c, 0x4013, 0x080c, 0x4048, 0x00f6, 0x2079, 0x0100, 0x7824,
-	0xd0ac, 0x0130, 0x8b58, 0x080c, 0x3f61, 0x00fe, 0x0804, 0x3f0e,
-	0x00fe, 0x080c, 0x3f57, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602,
-	0x2001, 0x0033, 0x2502, 0x080c, 0x3f61, 0x0080, 0x87ff, 0x0138,
-	0x2001, 0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001,
-	0x1a65, 0x2004, 0x9086, 0x0000, 0x1904, 0x3e5e, 0x2001, 0x032f,
-	0x2003, 0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904,
-	0x3f0e, 0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904,
-	0x3f0e, 0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884,
-	0xd0ac, 0x1148, 0x2001, 0x1a65, 0x2003, 0x0003, 0x2001, 0x032a,
-	0x2003, 0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108,
-	0xa016, 0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x2409, 0x2900,
-	0xa85a, 0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000,
-	0x00c6, 0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001,
-	0x0203, 0x2004, 0x1f04, 0x3ee5, 0x00ce, 0x0030, 0xa817, 0x0001,
-	0x78b0, 0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100,
-	0x2061, 0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084,
-	0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6,
-	0x000e, 0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3e18, 0x001e, 0x00c6,
-	0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002,
-	0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c,
-	0x918c, 0xfffd, 0x2102, 0x080c, 0x12fc, 0x7884, 0x9084, 0x0003,
-	0x9086, 0x0002, 0x01a0, 0x2009, 0x0028, 0x080c, 0x2409, 0x2001,
-	0x0227, 0x200c, 0x2102, 0x6050, 0x9084, 0xb7ef, 0x6052, 0x602f,
-	0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010, 0x00ce,
-	0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05, 0x9d05, 0x00fe, 0x00ee,
-	0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x1118, 0x012e,
-	0x0804, 0x35b5, 0x012e, 0x2021, 0x400c, 0x0804, 0x35b7, 0x9085,
-	0x0001, 0x1d04, 0x3f60, 0x2091, 0x6000, 0x8420, 0x9486, 0x0064,
-	0x0005, 0x2001, 0x0105, 0x2003, 0x0010, 0x2001, 0x032a, 0x2003,
-	0x0004, 0x2001, 0x1a65, 0x2003, 0x0000, 0x0071, 0x2009, 0x0048,
-	0x080c, 0x2409, 0x2001, 0x0227, 0x2024, 0x2402, 0x2001, 0x0109,
-	0x2003, 0x4000, 0x9026, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a69,
-	0x7000, 0x9086, 0x0000, 0x0520, 0x2079, 0x0090, 0x2009, 0x0206,
-	0x2104, 0x2009, 0x0203, 0x210c, 0x9106, 0x1120, 0x2009, 0x0040,
-	0x080c, 0x2409, 0x782c, 0xd0fc, 0x0d88, 0x080c, 0x41a4, 0x7000,
-	0x9086, 0x0000, 0x1d58, 0x782b, 0x0004, 0x782c, 0xd0ac, 0x1de8,
-	0x2009, 0x0040, 0x080c, 0x2409, 0x782b, 0x0002, 0x7003, 0x0000,
-	0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x2001, 0x1818,
-	0x200c, 0x7932, 0x7936, 0x080c, 0x28bc, 0x7850, 0x9084, 0xfbff,
-	0x9085, 0x0030, 0x7852, 0x2019, 0x01f4, 0x8319, 0x1df0, 0x9084,
-	0xffcf, 0x9085, 0x2000, 0x7852, 0x20a9, 0x0046, 0x1d04, 0x3fc6,
-	0x2091, 0x6000, 0x1f04, 0x3fc6, 0x7850, 0x9085, 0x0400, 0x9084,
-	0xdfff, 0x7852, 0x2001, 0x0021, 0x2004, 0x9084, 0x0003, 0x9086,
-	0x0001, 0x1120, 0x7850, 0x9084, 0xdfff, 0x7852, 0x784b, 0xf7f7,
-	0x7843, 0x0090, 0x7843, 0x0010, 0x20a9, 0x0028, 0xa001, 0x1f04,
-	0x3fe6, 0x7850, 0x9085, 0x1400, 0x7852, 0x2019, 0x61a8, 0x7854,
-	0xa001, 0xa001, 0xd08c, 0x1110, 0x8319, 0x1dc8, 0x7827, 0x0048,
-	0x7850, 0x9085, 0x0400, 0x7852, 0x7843, 0x0040, 0x2019, 0x01f4,
-	0xa001, 0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2d39,
-	0x7827, 0x0020, 0x7843, 0x0000, 0x9006, 0x080c, 0x2d39, 0x7827,
-	0x0048, 0x00fe, 0x0005, 0x7884, 0xd0ac, 0x11c8, 0x00f6, 0x00e6,
-	0x2071, 0x1a65, 0x2079, 0x0320, 0x2001, 0x0201, 0x2004, 0x9005,
-	0x0160, 0x7000, 0x9086, 0x0000, 0x1140, 0x0051, 0xd0bc, 0x0108,
-	0x8738, 0x7003, 0x0003, 0x782b, 0x0019, 0x00ee, 0x00fe, 0x0005,
-	0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070, 0x0178,
-	0x2009, 0x0032, 0x260a, 0x2009, 0x0033, 0x250a, 0xd0b4, 0x0108,
-	0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4, 0x0108, 0x8b58, 0x0005,
-	0x00f6, 0x2079, 0x0200, 0x781c, 0xd084, 0x0110, 0x7837, 0x0050,
-	0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100, 0x2001, 0x19ab, 0x2004,
-	0x70e2, 0x080c, 0x3d39, 0x1188, 0x2001, 0x1820, 0x2004, 0x2009,
-	0x181f, 0x210c, 0x918c, 0x00ff, 0x706e, 0x716a, 0x7066, 0x918d,
-	0x3200, 0x7162, 0x7073, 0xe109, 0x0080, 0x702c, 0x9085, 0x0002,
-	0x702e, 0x2009, 0x1818, 0x210c, 0x716e, 0x7063, 0x0100, 0x7166,
-	0x719e, 0x706b, 0x0000, 0x7073, 0x0809, 0x7077, 0x0008, 0x7078,
-	0x9080, 0x0100, 0x707a, 0x7080, 0x8000, 0x7082, 0x7087, 0xaaaa,
-	0x9006, 0x708a, 0x708e, 0x707e, 0x70d6, 0x70ab, 0x0036, 0x70af,
-	0x95d5, 0x7014, 0x9084, 0x1984, 0x9085, 0x0092, 0x7016, 0x080c,
-	0x41a4, 0x00f6, 0x2071, 0x1a65, 0x2079, 0x0320, 0x00d6, 0x2069,
-	0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c, 0x780e, 0x6898, 0x780a,
-	0x00de, 0x080c, 0x3d39, 0x0140, 0x2001, 0x199f, 0x200c, 0x2003,
-	0x0001, 0x918e, 0x0001, 0x0120, 0x2009, 0x03e8, 0x8109, 0x1df0,
-	0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004, 0x2011, 0x0011, 0x080c,
-	0x4130, 0x2011, 0x0001, 0x080c, 0x4130, 0x00fe, 0x00ee, 0x0005,
-	0x00f6, 0x00e6, 0x2071, 0x1a65, 0x2079, 0x0320, 0x792c, 0xd1fc,
-	0x0904, 0x412d, 0x782b, 0x0002, 0x9026, 0xd19c, 0x1904, 0x4129,
-	0x7000, 0x0002, 0x412d, 0x40de, 0x410e, 0x4129, 0xd1bc, 0x1170,
-	0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011, 0x0001, 0x080c, 0x4130,
-	0x0904, 0x412d, 0x080c, 0x4130, 0x0804, 0x412d, 0x00f6, 0x2079,
-	0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810, 0x7914, 0x782b, 0x0004,
-	0x7812, 0x7916, 0x2001, 0x0201, 0x200c, 0x81ff, 0x0de8, 0x080c,
-	0x4030, 0x2009, 0x0001, 0x00f6, 0x2079, 0x0300, 0x78b8, 0x00fe,
-	0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a, 0x00f8, 0x8001, 0x7002,
-	0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc, 0x1904, 0x40d2, 0x2011,
-	0x0001, 0x00b1, 0x0090, 0xa010, 0x9092, 0x0004, 0x9086, 0x0015,
-	0x1120, 0xa000, 0xa05a, 0x2011, 0x0031, 0xa212, 0xd1dc, 0x1960,
-	0x0828, 0x782b, 0x0004, 0x7003, 0x0000, 0x00ee, 0x00fe, 0x0005,
-	0xa014, 0x9005, 0x0550, 0x8001, 0x0036, 0x0096, 0xa016, 0xa058,
-	0x2048, 0xa010, 0x2009, 0x0031, 0x911a, 0x831c, 0x831c, 0x938a,
-	0x0007, 0x1a0c, 0x0dc5, 0x9398, 0x415e, 0x231d, 0x083f, 0x9080,
-	0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102, 0x009e, 0x003e, 0x908a,
-	0x0035, 0x1140, 0x0096, 0xa058, 0x2048, 0xa804, 0xa05a, 0x2001,
-	0x0019, 0x009e, 0xa012, 0x9085, 0x0001, 0x0005, 0x419b, 0x4192,
-	0x4189, 0x4180, 0x4177, 0x416e, 0x4165, 0xa964, 0x7902, 0xa968,
-	0x7906, 0xa96c, 0x7912, 0xa970, 0x7916, 0x0005, 0xa974, 0x7902,
-	0xa978, 0x7906, 0xa97c, 0x7912, 0xa980, 0x7916, 0x0005, 0xa984,
-	0x7902, 0xa988, 0x7906, 0xa98c, 0x7912, 0xa990, 0x7916, 0x0005,
-	0xa994, 0x7902, 0xa998, 0x7906, 0xa99c, 0x7912, 0xa9a0, 0x7916,
-	0x0005, 0xa9a4, 0x7902, 0xa9a8, 0x7906, 0xa9ac, 0x7912, 0xa9b0,
-	0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8, 0x7906, 0xa9bc, 0x7912,
-	0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902, 0xa9c8, 0x7906, 0xa9cc,
-	0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6, 0x00e6, 0x0086, 0x2071,
-	0x1a69, 0x2079, 0x0090, 0x792c, 0xd1fc, 0x01e8, 0x782b, 0x0002,
-	0x2940, 0x9026, 0x7000, 0x0002, 0x41cb, 0x41b7, 0x41c2, 0x8001,
-	0x7002, 0xd19c, 0x1180, 0x2011, 0x0001, 0x080c, 0x4130, 0x190c,
-	0x4130, 0x0048, 0x8001, 0x7002, 0x782c, 0xd0fc, 0x1d38, 0x2011,
-	0x0001, 0x080c, 0x4130, 0x008e, 0x00ee, 0x00fe, 0x0005, 0x00f6,
-	0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200, 0x2001, 0x19ab, 0x2004,
-	0x601a, 0x2061, 0x0100, 0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104,
-	0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004, 0x9005, 0x0520, 0x2038,
-	0x2001, 0x002e, 0x2024, 0x2001, 0x002f, 0x201c, 0x080c, 0x4be4,
-	0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220,
-	0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858,
-	0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4247, 0x1d68,
-	0x2900, 0xa85a, 0x00d0, 0x080c, 0x4be4, 0xa813, 0x0019, 0xa817,
-	0x0001, 0x2900, 0xa85a, 0x2001, 0x002e, 0x2004, 0xa866, 0x2001,
-	0x002f, 0x2004, 0xa86a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8,
-	0xa86e, 0x2001, 0x002b, 0x2004, 0xa872, 0x2061, 0x0090, 0x2079,
-	0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, 0x2009, 0x0040, 0x080c,
-	0x2409, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0x601a, 0x0006,
-	0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e, 0x78ca, 0x9006,
-	0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6,
-	0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0, 0x20e1, 0x0000, 0x2099,
-	0x0088, 0x702b, 0x0026, 0x7402, 0x7306, 0x9006, 0x700a, 0x700e,
-	0x810b, 0x810b, 0x21a8, 0x810b, 0x7112, 0x702b, 0x0041, 0x702c,
-	0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b, 0x0040, 0x4005, 0x7400,
-	0x7304, 0x87ff, 0x0190, 0x0086, 0x0096, 0x2940, 0x0086, 0x080c,
-	0x4be4, 0x008e, 0xa058, 0x00a6, 0x2050, 0x2900, 0xb006, 0xa05a,
-	0x00ae, 0x009e, 0x008e, 0x9085, 0x0001, 0x00ee, 0x0005, 0x00e6,
-	0x2001, 0x002d, 0x2004, 0x9005, 0x0528, 0x2038, 0x2001, 0x0030,
-	0x2024, 0x2001, 0x0031, 0x201c, 0x080c, 0x4be4, 0x2940, 0xa813,
-	0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a, 0x0007, 0x0220, 0x2138,
-	0x2009, 0x0007, 0x0010, 0x2708, 0x903e, 0x0096, 0xa858, 0x2048,
-	0xa85c, 0x9080, 0x0019, 0x009e, 0x080c, 0x4247, 0x1d68, 0x2900,
-	0xa85a, 0x00d8, 0x080c, 0x4be4, 0x2940, 0xa013, 0x0019, 0xa017,
-	0x0001, 0x2800, 0xa05a, 0x2001, 0x0030, 0x2004, 0xa066, 0x2001,
-	0x0031, 0x2004, 0xa06a, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8,
-	0xa06e, 0x2001, 0x002b, 0x2004, 0xa072, 0x2001, 0x032a, 0x2003,
-	0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001, 0x0101, 0x200c, 0x918d,
-	0x0200, 0x2102, 0xa017, 0x0000, 0x2001, 0x1a65, 0x2003, 0x0003,
-	0x2001, 0x032a, 0x2003, 0x0009, 0x2001, 0x0300, 0x2003, 0x0000,
-	0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d,
-	0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x20a9,
-	0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001, 0x9006, 0x4004, 0x20a9,
-	0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000, 0x9006, 0x4004, 0x2009,
-	0x013c, 0x200a, 0x012e, 0x7880, 0x9086, 0x0052, 0x0108, 0x0005,
-	0x0804, 0x35b5, 0x7d98, 0x7c9c, 0x0804, 0x36b9, 0x080c, 0x7637,
-	0x190c, 0x60f3, 0x6040, 0x9084, 0x0020, 0x09b1, 0x2069, 0x1847,
-	0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039,
-	0x0001, 0x080c, 0x4c2d, 0x701f, 0x4326, 0x0005, 0x080c, 0x57e4,
-	0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095, 0x20d8, 0x21d0, 0x2069,
-	0x1847, 0x6800, 0x9005, 0x0904, 0x35ea, 0x2001, 0x180d, 0x2004,
-	0xd08c, 0x6804, 0x0118, 0xc0a4, 0xc0ac, 0x6806, 0xd0ac, 0x0118,
-	0xd0a4, 0x0904, 0x35ea, 0xd094, 0x00c6, 0x2061, 0x0100, 0x6104,
-	0x0138, 0x6200, 0x9292, 0x0005, 0x0218, 0x918c, 0xffdf, 0x0010,
-	0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c, 0x00c6, 0x2061, 0x0100,
-	0x6104, 0x0118, 0x918d, 0x0010, 0x0010, 0x918c, 0xffef, 0x6106,
-	0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a, 0x007f, 0x1a04, 0x35ea,
-	0x9288, 0x33b6, 0x210d, 0x918c, 0x00ff, 0x6166, 0xd0dc, 0x0130,
-	0x6828, 0x908a, 0x007f, 0x1a04, 0x35ea, 0x605e, 0x6888, 0x9084,
-	0x0030, 0x8004, 0x8004, 0x8004, 0x8004, 0x0006, 0x2009, 0x19b2,
-	0x9080, 0x29b7, 0x2005, 0x200a, 0x000e, 0x2009, 0x19b3, 0x9080,
-	0x29bb, 0x2005, 0x200a, 0x6808, 0x908a, 0x0100, 0x0a04, 0x35ea,
-	0x908a, 0x0841, 0x1a04, 0x35ea, 0x9084, 0x0007, 0x1904, 0x35ea,
-	0x680c, 0x9005, 0x0904, 0x35ea, 0x6810, 0x9005, 0x0904, 0x35ea,
-	0x6848, 0x6940, 0x910a, 0x1a04, 0x35ea, 0x8001, 0x0904, 0x35ea,
-	0x684c, 0x6944, 0x910a, 0x1a04, 0x35ea, 0x8001, 0x0904, 0x35ea,
-	0x2009, 0x1981, 0x200b, 0x0000, 0x2001, 0x1869, 0x2004, 0xd0c4,
-	0x0140, 0x7884, 0x200a, 0x2008, 0x080c, 0x0e52, 0x3b00, 0xc085,
-	0x20d8, 0x6814, 0x908c, 0x00ff, 0x614e, 0x8007, 0x9084, 0x00ff,
-	0x6052, 0x080c, 0x7963, 0x080c, 0x6b8e, 0x080c, 0x6bf8, 0x6808,
-	0x602a, 0x080c, 0x237b, 0x2009, 0x0170, 0x200b, 0x0080, 0xa001,
-	0xa001, 0x200b, 0x0000, 0x0036, 0x6b08, 0x080c, 0x2916, 0x003e,
-	0x6000, 0x9086, 0x0000, 0x1904, 0x44cf, 0x6818, 0x691c, 0x6a20,
-	0x6b24, 0x8007, 0x810f, 0x8217, 0x831f, 0x6016, 0x611a, 0x621e,
-	0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830, 0x6934, 0x6a38, 0x6b3c,
-	0x8007, 0x810f, 0x8217, 0x831f, 0x0010, 0x9084, 0xf0ff, 0x6006,
-	0x610a, 0x620e, 0x6312, 0x8007, 0x810f, 0x8217, 0x831f, 0x20a9,
-	0x0004, 0x20a1, 0x19b4, 0x20e9, 0x0001, 0x4001, 0x20a9, 0x0004,
-	0x20a1, 0x19ce, 0x20e9, 0x0001, 0x4001, 0x080c, 0x8962, 0x00c6,
-	0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384, 0x0510, 0x0068, 0x2009,
-	0x0100, 0x210c, 0x918e, 0x0008, 0x1110, 0x839d, 0x0010, 0x83f5,
-	0x3e18, 0x12b0, 0x3508, 0x8109, 0x080c, 0x7f6f, 0x6878, 0x6016,
-	0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a, 0x9184, 0x00ff,
-	0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010, 0x6003, 0x0001,
-	0x1f04, 0x441f, 0x00ce, 0x00c6, 0x2061, 0x199c, 0x2001, 0x180d,
-	0x2004, 0xd08c, 0x11a8, 0x6a88, 0x9284, 0xc000, 0x2010, 0x9286,
-	0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001, 0x080c, 0x2bb1,
-	0x2001, 0x0001, 0x080c, 0x2b94, 0x0088, 0x9286, 0x4000, 0x1148,
-	0x2063, 0x0001, 0x9006, 0x080c, 0x2bb1, 0x9006, 0x080c, 0x2b94,
-	0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002, 0x00ce, 0x00e6,
-	0x2c70, 0x080c, 0x0ea3, 0x00ee, 0x6888, 0xd0ec, 0x0130, 0x2011,
-	0x0114, 0x2204, 0x9085, 0x0100, 0x2012, 0x6a80, 0x9284, 0x0030,
-	0x9086, 0x0030, 0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82,
-	0x2001, 0x197c, 0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170,
-	0x928e, 0x0010, 0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa,
-	0x080c, 0x298b, 0x2001, 0x196d, 0x2102, 0x0008, 0x2102, 0x00c6,
-	0x2061, 0x0100, 0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c,
-	0x7637, 0x0128, 0x080c, 0x50cb, 0x0110, 0x080c, 0x28dc, 0x60d4,
-	0x9005, 0x01c0, 0x6003, 0x0001, 0x2009, 0x44b7, 0x00e0, 0x080c,
-	0x7637, 0x1168, 0x2011, 0x74b2, 0x080c, 0x883d, 0x2011, 0x74a5,
-	0x080c, 0x8917, 0x080c, 0x7937, 0x080c, 0x7563, 0x0040, 0x080c,
-	0x5fed, 0x0028, 0x6003, 0x0004, 0x2009, 0x44cf, 0x0020, 0x080c,
-	0x6a05, 0x0804, 0x35b5, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff,
-	0x9086, 0x004c, 0x1118, 0x2091, 0x30bd, 0x0817, 0x2091, 0x303d,
-	0x0817, 0x6000, 0x9086, 0x0000, 0x0904, 0x35e7, 0x2069, 0x1847,
-	0x7890, 0x6842, 0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c,
-	0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x0804, 0x4c30, 0x9006,
-	0x080c, 0x28dc, 0x81ff, 0x1904, 0x35e7, 0x080c, 0x7637, 0x11b0,
-	0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x33aa, 0x0118, 0x6130,
-	0xc18d, 0x6132, 0x080c, 0xd7e3, 0x0130, 0x080c, 0x765a, 0x1118,
-	0x080c, 0x760f, 0x0038, 0x080c, 0x7563, 0x0020, 0x080c, 0x60f3,
-	0x080c, 0x5fed, 0x0804, 0x35b5, 0x81ff, 0x1904, 0x35e7, 0x080c,
-	0x7637, 0x1110, 0x0804, 0x35e7, 0x0126, 0x2091, 0x8000, 0x6194,
-	0x81ff, 0x0190, 0x704f, 0x0000, 0x2001, 0x1c80, 0x2009, 0x0040,
-	0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c30,
-	0x701f, 0x35b3, 0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069,
-	0x1c80, 0x20a9, 0x0040, 0x20e9, 0x0001, 0x20a1, 0x1c80, 0x2019,
-	0xffff, 0x4304, 0x655c, 0x9588, 0x33b6, 0x210d, 0x918c, 0x00ff,
-	0x216a, 0x900e, 0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c,
-	0x6724, 0x1190, 0xb814, 0x821c, 0x0238, 0x9398, 0x1c80, 0x9085,
-	0xff00, 0x8007, 0x201a, 0x0038, 0x9398, 0x1c80, 0x2324, 0x94a4,
-	0xff00, 0x9405, 0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208,
-	0x0c18, 0x8201, 0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9,
-	0x0040, 0x20a1, 0x1c80, 0x2099, 0x1c80, 0x080c, 0x607e, 0x0804,
-	0x452c, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x4be4, 0x1120,
-	0x2009, 0x0002, 0x0804, 0x35e7, 0x080c, 0x57d5, 0xd0b4, 0x0558,
-	0x7884, 0x908e, 0x007e, 0x0538, 0x908e, 0x007f, 0x0520, 0x908e,
-	0x0080, 0x0508, 0x080c, 0x33a5, 0x1148, 0xb800, 0xd08c, 0x11d8,
-	0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000,
-	0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2a3, 0x1120, 0x2009, 0x0003,
-	0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x45b7, 0x0005, 0x080c,
-	0x4c17, 0x0904, 0x35ea, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8,
-	0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003,
-	0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8,
-	0x9080, 0x0006, 0x2098, 0x080c, 0x0f8b, 0x0070, 0x20a9, 0x0004,
-	0xa85c, 0x9080, 0x000a, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080,
-	0x000a, 0x2098, 0x080c, 0x0f8b, 0x8906, 0x8006, 0x8007, 0x90bc,
-	0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c,
-	0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4c30, 0x81ff, 0x1904, 0x35e7,
-	0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6896, 0x0904, 0x35e7,
-	0x0058, 0xa878, 0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x35e7,
-	0xa974, 0xaa94, 0x0804, 0x35b5, 0x080c, 0x57dd, 0x0904, 0x35b5,
-	0x701f, 0x4601, 0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x35e7,
-	0x7888, 0x908a, 0x1000, 0x1a04, 0x35ea, 0x080c, 0x4c17, 0x0904,
-	0x35ea, 0x080c, 0x6aa3, 0x0120, 0x080c, 0x6aab, 0x1904, 0x35ea,
-	0x080c, 0x691b, 0x0904, 0x35e7, 0x2019, 0x0004, 0x900e, 0x080c,
-	0x68a8, 0x0904, 0x35e7, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c,
-	0x908a, 0x1000, 0x12f8, 0x080c, 0x4c15, 0x01e0, 0x080c, 0x6aa3,
-	0x0118, 0x080c, 0x6aab, 0x11b0, 0x080c, 0x691b, 0x2009, 0x0002,
-	0x0168, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x68a8, 0x2009,
-	0x0003, 0x0120, 0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005,
-	0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001,
-	0x0030, 0x0005, 0xa897, 0x4000, 0x080c, 0x57dd, 0x0110, 0x9006,
-	0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186,
-	0x00ff, 0x0110, 0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800,
-	0x645c, 0x2400, 0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8,
-	0x0005, 0x080c, 0x6724, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b,
-	0x9108, 0x080c, 0x884b, 0x0005, 0x81ff, 0x1904, 0x35e7, 0x798c,
-	0x2001, 0x1980, 0x918c, 0x8000, 0x2102, 0x080c, 0x4bfb, 0x0904,
-	0x35ea, 0x080c, 0x6aa3, 0x0120, 0x080c, 0x6aab, 0x1904, 0x35ea,
-	0x080c, 0x67eb, 0x0904, 0x35e7, 0x080c, 0x689f, 0x0904, 0x35e7,
-	0x2001, 0x1980, 0x2004, 0xd0fc, 0x1904, 0x35b5, 0x0804, 0x460c,
-	0xa9a0, 0x2001, 0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c,
-	0x4c08, 0x01a0, 0x080c, 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1170,
-	0x080c, 0x67eb, 0x2009, 0x0002, 0x0128, 0x080c, 0x689f, 0x1170,
-	0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006,
-	0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000,
-	0x2001, 0x1980, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57dd, 0x0110,
-	0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005,
-	0x81ff, 0x1904, 0x35e7, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000,
-	0x2102, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x0120,
-	0x080c, 0x6aab, 0x1904, 0x35ea, 0x080c, 0x67eb, 0x0904, 0x35e7,
-	0x080c, 0x688d, 0x0904, 0x35e7, 0x2001, 0x197f, 0x2004, 0xd0fc,
-	0x1904, 0x35b5, 0x0804, 0x460c, 0xa9a0, 0x2001, 0x197f, 0x918c,
-	0x8000, 0xc18d, 0x2102, 0x080c, 0x4c08, 0x01a0, 0x080c, 0x6aa3,
-	0x0118, 0x080c, 0x6aab, 0x1170, 0x080c, 0x67eb, 0x2009, 0x0002,
-	0x0128, 0x080c, 0x688d, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005,
-	0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001,
-	0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197f, 0x2004, 0xd0fc,
-	0x1128, 0x080c, 0x57dd, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085,
-	0x0001, 0x2001, 0x0000, 0x0005, 0x6100, 0x0804, 0x35b5, 0x080c,
-	0x4c17, 0x0904, 0x35ea, 0x080c, 0x57e9, 0x1904, 0x35e7, 0x79a8,
-	0xd184, 0x1158, 0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a,
-	0xbb2c, 0x831f, 0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e,
-	0xb820, 0x8007, 0x789a, 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900,
-	0x918c, 0x0202, 0x0804, 0x35b5, 0x78a8, 0x909c, 0x0003, 0xd0ac,
-	0x1158, 0xd0b4, 0x1148, 0x939a, 0x0003, 0x1a04, 0x35e7, 0x625c,
-	0x7884, 0x9206, 0x1904, 0x47c7, 0x080c, 0x894c, 0x2001, 0xffec,
-	0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000,
-	0x0006, 0x78a8, 0x9084, 0x0080, 0x1528, 0x0006, 0x0036, 0x2001,
-	0x1a83, 0x201c, 0x7b9a, 0x2003, 0x0000, 0x2001, 0x1a84, 0x201c,
-	0x7b9e, 0x2003, 0x0000, 0x2001, 0x1a85, 0x201c, 0x7bae, 0x2003,
-	0x0000, 0x2001, 0x1a7f, 0x201c, 0x7baa, 0x2003, 0x0000, 0x2001,
-	0x1a86, 0x201c, 0x7bb2, 0x2003, 0x0000, 0x003e, 0x000e, 0x000e,
-	0x0804, 0x4c30, 0x000e, 0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44,
-	0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a,
-	0x080c, 0x10f8, 0x7007, 0x0002, 0x701f, 0x47e7, 0x0005, 0x81ff,
-	0x1904, 0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x6aa3,
-	0x1904, 0x35e7, 0x00c6, 0x080c, 0x4be4, 0x00ce, 0x0904, 0x35e7,
-	0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7ea8, 0x080c, 0xd249,
-	0x0904, 0x35e7, 0x7007, 0x0003, 0x701f, 0x480d, 0x0005, 0x080c,
-	0x42ec, 0x0006, 0x0036, 0x2001, 0x1a83, 0x201c, 0x7b9a, 0x2003,
-	0x0000, 0x2001, 0x1a84, 0x201c, 0x7b9e, 0x2003, 0x0000, 0x2001,
-	0x1a85, 0x201c, 0x7bae, 0x2003, 0x0000, 0x2001, 0x1a7f, 0x201c,
-	0x7baa, 0x2003, 0x0000, 0x2001, 0x1a86, 0x201c, 0x7bb2, 0x2003,
-	0x0000, 0x003e, 0x000e, 0x0804, 0x35b5, 0xa830, 0x9086, 0x0100,
-	0x0904, 0x35e7, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084,
-	0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88, 0x7c9c,
-	0x7d98, 0x0804, 0x4c30, 0x9006, 0x080c, 0x28dc, 0x78a8, 0x9084,
-	0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x35e7, 0x080c,
-	0x7637, 0x0110, 0x080c, 0x60f3, 0x7888, 0x908a, 0x1000, 0x1a04,
-	0x35ea, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f, 0x1a04,
-	0x35ea, 0x2100, 0x080c, 0x28a6, 0x0026, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x2061, 0x19fb, 0x601b, 0x0000, 0x601f, 0x0000, 0x607b,
-	0x0000, 0x607f, 0x0000, 0x080c, 0x7637, 0x1158, 0x080c, 0x7932,
-	0x080c, 0x612e, 0x9085, 0x0001, 0x080c, 0x767b, 0x080c, 0x7563,
-	0x00d0, 0x080c, 0xb244, 0x2061, 0x0100, 0x2001, 0x1818, 0x2004,
-	0x9084, 0x00ff, 0x810f, 0x9105, 0x604a, 0x6043, 0x0090, 0x6043,
-	0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011,
-	0x6019, 0x080c, 0x88d5, 0x7984, 0x080c, 0x7637, 0x1110, 0x2009,
-	0x00ff, 0x7a88, 0x080c, 0x466f, 0x012e, 0x00ce, 0x002e, 0x0804,
-	0x35b5, 0x7984, 0x080c, 0x66b9, 0x2b08, 0x1904, 0x35ea, 0x0804,
-	0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x35e7, 0x60dc,
-	0xd0ac, 0x1130, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x35e7,
-	0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x7984,
-	0x81ff, 0x0904, 0x35ea, 0x9192, 0x0021, 0x1a04, 0x35ea, 0x7a8c,
-	0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60,
-	0x7736, 0x080c, 0x4c2d, 0x701f, 0x48c4, 0x7880, 0x9086, 0x006e,
-	0x0110, 0x701f, 0x527d, 0x0005, 0x2009, 0x0080, 0x080c, 0x6724,
-	0x1118, 0x080c, 0x6aa3, 0x0120, 0x2021, 0x400a, 0x0804, 0x35b7,
-	0x00d6, 0x0096, 0xa964, 0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c,
-	0xa884, 0x90be, 0x0100, 0x0904, 0x495d, 0x90be, 0x0112, 0x0904,
-	0x495d, 0x90be, 0x0113, 0x0904, 0x495d, 0x90be, 0x0114, 0x0904,
-	0x495d, 0x90be, 0x0117, 0x0904, 0x495d, 0x90be, 0x011a, 0x0904,
-	0x495d, 0x90be, 0x011c, 0x0904, 0x495d, 0x90be, 0x0121, 0x0904,
-	0x4944, 0x90be, 0x0131, 0x0904, 0x4944, 0x90be, 0x0171, 0x0904,
-	0x495d, 0x90be, 0x0173, 0x0904, 0x495d, 0x90be, 0x01a1, 0x1128,
-	0xa894, 0x8007, 0xa896, 0x0804, 0x4968, 0x90be, 0x0212, 0x0904,
-	0x4951, 0x90be, 0x0213, 0x05e8, 0x90be, 0x0214, 0x0500, 0x90be,
-	0x0217, 0x0188, 0x90be, 0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e,
-	0x04e0, 0x90be, 0x021f, 0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e,
-	0x00de, 0x0804, 0x35ea, 0x7028, 0x9080, 0x0010, 0x2098, 0x20a0,
-	0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0007, 0x080c, 0x49a6, 0x7028,
-	0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9,
-	0x0001, 0x080c, 0x49a6, 0x00c8, 0x7028, 0x9080, 0x000c, 0x2098,
-	0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x49b3,
-	0x00b8, 0x7028, 0x9080, 0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0,
-	0x20e8, 0x20a9, 0x0001, 0x080c, 0x49b3, 0x7028, 0x9080, 0x000c,
-	0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1,
-	0x00c6, 0x080c, 0x4be4, 0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867,
-	0x0119, 0x9006, 0xa882, 0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b,
-	0xa9ae, 0xa8b2, 0xaab6, 0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca,
-	0x00ce, 0x009e, 0x00de, 0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a,
-	0xa804, 0x2048, 0x080c, 0xd264, 0x1120, 0x2009, 0x0003, 0x0804,
-	0x35e7, 0x7007, 0x0003, 0x701f, 0x499d, 0x0005, 0x00ce, 0x009e,
-	0x00de, 0x2009, 0x0002, 0x0804, 0x35e7, 0xa820, 0x9086, 0x8001,
-	0x1904, 0x35b5, 0x2009, 0x0004, 0x0804, 0x35e7, 0x0016, 0x0026,
-	0x3510, 0x20a9, 0x0002, 0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8,
-	0x002e, 0x001e, 0x0005, 0x0016, 0x0026, 0x0036, 0x0046, 0x3520,
-	0x20a9, 0x0004, 0x4002, 0x4304, 0x4204, 0x4104, 0x4004, 0x8421,
-	0x1db8, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x81ff, 0x0120,
-	0x2009, 0x0001, 0x0804, 0x35e7, 0x60dc, 0xd0ac, 0x1188, 0x2009,
-	0x180d, 0x210c, 0xd18c, 0x0130, 0xd09c, 0x0120, 0x2009, 0x0016,
-	0x0804, 0x35e7, 0xd09c, 0x1120, 0x2009, 0x0005, 0x0804, 0x35e7,
-	0x7984, 0x78a8, 0x2040, 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f,
-	0x0a04, 0x35ea, 0x9186, 0x00ff, 0x0904, 0x35ea, 0x9182, 0x0800,
-	0x1a04, 0x35ea, 0x7a8c, 0x7b88, 0x607c, 0x9306, 0x1158, 0x6080,
-	0x924e, 0x0904, 0x35ea, 0x080c, 0xb23d, 0x1120, 0x99cc, 0xff00,
-	0x0904, 0x35ea, 0x0126, 0x2091, 0x8000, 0x2001, 0x180d, 0x2004,
-	0xd08c, 0x0198, 0x9386, 0x00ff, 0x0180, 0x0026, 0x2011, 0x8008,
-	0x080c, 0x6ac7, 0x002e, 0x0148, 0x918d, 0x8000, 0x080c, 0x6b11,
-	0x1120, 0x2001, 0x4009, 0x0804, 0x4a64, 0x080c, 0x4af7, 0x0904,
-	0x4a6a, 0x0086, 0x90c6, 0x4000, 0x008e, 0x1538, 0x00c6, 0x0006,
-	0x0036, 0xb818, 0xbb1c, 0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305,
-	0xbb28, 0x9305, 0xbb2c, 0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305,
-	0x003e, 0x0570, 0xd88c, 0x1128, 0x080c, 0x6aa3, 0x0110, 0xc89d,
-	0x0438, 0x900e, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc,
-	0x0108, 0xc18d, 0x000e, 0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110,
-	0x2408, 0x0090, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610, 0x0060,
-	0x90c6, 0x4009, 0x1108, 0x0040, 0x90c6, 0x4006, 0x1108, 0x0020,
-	0x2001, 0x4005, 0x2009, 0x000a, 0x2020, 0x012e, 0x0804, 0x35b7,
-	0x000e, 0x00ce, 0x2b00, 0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6,
-	0x2c70, 0x080c, 0xb325, 0x0904, 0x4abf, 0x2b00, 0x6012, 0x080c,
-	0xd554, 0x2e58, 0x00ee, 0x00e6, 0x00c6, 0x080c, 0x4be4, 0x00ce,
-	0x2b70, 0x1158, 0x080c, 0xb2d3, 0x00ee, 0x00ce, 0x00be, 0x001e,
-	0x012e, 0x2009, 0x0002, 0x0804, 0x35e7, 0x900e, 0xa966, 0xa96a,
-	0x2900, 0x6016, 0xa932, 0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5,
-	0xa86a, 0xd89c, 0x1110, 0x080c, 0x3250, 0x6023, 0x0001, 0x9006,
-	0x080c, 0x6656, 0xd89c, 0x0138, 0x2001, 0x0004, 0x080c, 0x666a,
-	0x2009, 0x0003, 0x0030, 0x2001, 0x0002, 0x080c, 0x666a, 0x2009,
-	0x0002, 0x080c, 0xb352, 0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024,
-	0x00e6, 0x2058, 0xb8cc, 0xc08d, 0xb8ce, 0x9085, 0x0001, 0x00ee,
-	0x00ce, 0x00be, 0x001e, 0x012e, 0x1120, 0x2009, 0x0003, 0x0804,
-	0x35e7, 0x7007, 0x0003, 0x701f, 0x4ace, 0x0005, 0xa830, 0x2009,
-	0x180d, 0x210c, 0xd18c, 0x0140, 0x2008, 0x918e, 0xdead, 0x1120,
-	0x2021, 0x4009, 0x0804, 0x35b7, 0x9086, 0x0100, 0x7024, 0x2058,
-	0x1138, 0x2009, 0x0004, 0xba04, 0x9294, 0x00ff, 0x0804, 0x5729,
-	0x900e, 0xa868, 0xd0f4, 0x1904, 0x35b5, 0x080c, 0x6944, 0x1108,
-	0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x35b5, 0x00e6,
-	0x00d6, 0x0096, 0x83ff, 0x0904, 0x4b46, 0x902e, 0x080c, 0xb23d,
-	0x0130, 0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021,
-	0x007f, 0x20a9, 0x0781, 0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8,
-	0x2100, 0x9406, 0x1904, 0x4b57, 0x2428, 0x94ce, 0x007f, 0x1120,
-	0x92ce, 0xfffd, 0x1558, 0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce,
-	0xfffc, 0x1520, 0x93ce, 0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058,
-	0xbf10, 0x2700, 0x9306, 0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8,
-	0x2400, 0x9106, 0x1180, 0xd884, 0x0598, 0xd894, 0x1588, 0x080c,
-	0x6a43, 0x1570, 0x2001, 0x4000, 0x0460, 0x080c, 0x6aa3, 0x1540,
-	0x2001, 0x4000, 0x0430, 0x2001, 0x4007, 0x0418, 0x2001, 0x4006,
-	0x0400, 0x2400, 0x9106, 0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff,
-	0x0918, 0x080c, 0xb23d, 0x1900, 0x2001, 0x4008, 0x0090, 0x8420,
-	0x8e70, 0x1f04, 0x4b0d, 0x85ff, 0x1130, 0x2001, 0x4009, 0x0048,
-	0x2001, 0x0001, 0x0030, 0x080c, 0x66b9, 0x1dd0, 0xbb12, 0xba16,
-	0x9006, 0x9005, 0x009e, 0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120,
-	0x2009, 0x0001, 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009,
-	0x0002, 0x0804, 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a,
-	0x7884, 0x9005, 0x0904, 0x35ea, 0x9096, 0x00ff, 0x0120, 0x9092,
-	0x0004, 0x1a04, 0x35ea, 0x2010, 0x2918, 0x080c, 0x31f6, 0x1120,
-	0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x4b99,
-	0x0005, 0xa830, 0x9086, 0x0100, 0x1904, 0x35b5, 0x2009, 0x0004,
-	0x0804, 0x35e7, 0x7984, 0x080c, 0xb23d, 0x1120, 0x9182, 0x007f,
-	0x0a04, 0x35ea, 0x9186, 0x00ff, 0x0904, 0x35ea, 0x9182, 0x0800,
-	0x1a04, 0x35ea, 0x2001, 0x9400, 0x080c, 0x5784, 0x1904, 0x35e7,
-	0x0804, 0x35b5, 0xa998, 0x080c, 0xb23d, 0x1118, 0x9182, 0x007f,
-	0x0280, 0x9186, 0x00ff, 0x0168, 0x9182, 0x0800, 0x1250, 0x2001,
-	0x9400, 0x080c, 0x5784, 0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a,
-	0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030,
-	0x0005, 0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000,
-	0x0005, 0x2009, 0x000a, 0x0c48, 0x080c, 0x100e, 0x0198, 0x9006,
-	0xa802, 0x7014, 0x9005, 0x1120, 0x2900, 0x7016, 0x701a, 0x0040,
-	0x7018, 0xa802, 0x0086, 0x2040, 0x2900, 0xa006, 0x701a, 0x008e,
-	0x9085, 0x0001, 0x0005, 0x7984, 0x080c, 0x6724, 0x1130, 0x7e88,
-	0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e, 0x8bff, 0x0005,
-	0xa998, 0x080c, 0x6724, 0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082,
-	0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84,
-	0x2608, 0x080c, 0x6724, 0x1108, 0x0008, 0x905e, 0x8bff, 0x0005,
-	0x0016, 0x7114, 0x81ff, 0x0128, 0x2148, 0xa904, 0x080c, 0x1040,
-	0x0cc8, 0x7116, 0x711a, 0x001e, 0x0005, 0x2031, 0x0001, 0x0010,
-	0x2031, 0x0000, 0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772,
-	0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10f8, 0x7007,
-	0x0002, 0x701f, 0x35b5, 0x0005, 0x00f6, 0x0126, 0x2091, 0x8000,
-	0x2079, 0x0000, 0x2001, 0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04,
-	0x4c61, 0x7a36, 0x7833, 0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091,
-	0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x0804,
-	0x4cc7, 0x0016, 0x0086, 0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e,
-	0x7044, 0x9005, 0x1540, 0x7148, 0x9182, 0x0010, 0x0288, 0x7038,
-	0x2060, 0x080c, 0x100e, 0x0904, 0x4cbf, 0xa84b, 0x0000, 0x2900,
-	0x7046, 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa846, 0x0098,
-	0x7038, 0x90e0, 0x0004, 0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210,
-	0x2061, 0x18ba, 0x2c00, 0x703a, 0x7148, 0x81ff, 0x1108, 0x703e,
-	0x8108, 0x714a, 0x0460, 0x7148, 0x8108, 0x714a, 0x7044, 0x2040,
-	0xa144, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x2060,
-	0x001e, 0x8108, 0x2105, 0x9005, 0xa146, 0x1520, 0x080c, 0x100e,
-	0x1130, 0x8109, 0xa946, 0x7148, 0x8109, 0x714a, 0x00d8, 0x9006,
-	0xa806, 0xa84a, 0xa046, 0x2800, 0xa802, 0x2900, 0xa006, 0x7046,
-	0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa846, 0x0058, 0x2262,
-	0x6306, 0x640a, 0x00ee, 0x00ce, 0x009e, 0x008e, 0x001e, 0x012e,
-	0x00fe, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4ce9, 0x4ce9,
-	0x4ceb, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cef, 0x4ce9, 0x4ce9, 0x4ce9,
-	0x4cf3, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cf7, 0x4ce9, 0x4ce9, 0x4ce9,
-	0x4cfb, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cff, 0x4ce9, 0x4ce9, 0x4ce9,
-	0x4d04, 0x080c, 0x0dc5, 0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286,
-	0xa38a, 0xa48e, 0x0878, 0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6,
-	0xa3aa, 0xa4ae, 0x0838, 0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6,
-	0xa3ca, 0xa4ce, 0x0804, 0x4cc2, 0xa2d6, 0xa3da, 0xa4de, 0x0804,
-	0x4cc2, 0x00e6, 0x2071, 0x189e, 0x7048, 0x9005, 0x0904, 0x4d9b,
-	0x0126, 0x2091, 0x8000, 0x0e04, 0x4d9a, 0x00f6, 0x2079, 0x0000,
-	0x00c6, 0x0096, 0x0086, 0x0076, 0x9006, 0x2038, 0x7040, 0x2048,
-	0x9005, 0x0500, 0xa948, 0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c,
-	0x0dc5, 0x2060, 0x001e, 0x8108, 0x2105, 0x9005, 0xa94a, 0x1904,
-	0x4d9d, 0xa804, 0x9005, 0x090c, 0x0dc5, 0x7042, 0x2938, 0x2040,
-	0xa003, 0x0000, 0x2001, 0x0002, 0x9080, 0x20c7, 0x2005, 0xa04a,
-	0x0804, 0x4d9d, 0x703c, 0x2060, 0x2c14, 0x6304, 0x6408, 0x650c,
-	0x2200, 0x7836, 0x7833, 0x0012, 0x7882, 0x2300, 0x7886, 0x2400,
-	0x788a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c,
-	0x11aa, 0x87ff, 0x0118, 0x2748, 0x080c, 0x1040, 0x7048, 0x8001,
-	0x704a, 0x9005, 0x1170, 0x7040, 0x2048, 0x9005, 0x0128, 0x080c,
-	0x1040, 0x9006, 0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba,
-	0x0420, 0x7040, 0x9005, 0x1508, 0x7238, 0x2c00, 0x9206, 0x0148,
-	0x9c80, 0x0004, 0x90fa, 0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e,
-	0x00a0, 0x9006, 0x703e, 0x703a, 0x7044, 0x9005, 0x090c, 0x0dc5,
-	0x2048, 0xa800, 0x9005, 0x1de0, 0x2900, 0x7042, 0x2001, 0x0002,
-	0x9080, 0x20c7, 0x2005, 0xa84a, 0x0000, 0x007e, 0x008e, 0x009e,
-	0x00ce, 0x00fe, 0x012e, 0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b,
-	0x0002, 0x4dbc, 0x4dbc, 0x4dbe, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dc3,
-	0x4dbc, 0x4dbc, 0x4dbc, 0x4dc8, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dcd,
-	0x4dbc, 0x4dbc, 0x4dbc, 0x4dd2, 0x4dbc, 0x4dbc, 0x4dbc, 0x4dd7,
-	0x4dbc, 0x4dbc, 0x4dbc, 0x4ddc, 0x080c, 0x0dc5, 0xaa74, 0xab78,
-	0xac7c, 0x0804, 0x4d48, 0xaa84, 0xab88, 0xac8c, 0x0804, 0x4d48,
-	0xaa94, 0xab98, 0xac9c, 0x0804, 0x4d48, 0xaaa4, 0xaba8, 0xacac,
-	0x0804, 0x4d48, 0xaab4, 0xabb8, 0xacbc, 0x0804, 0x4d48, 0xaac4,
-	0xabc8, 0xaccc, 0x0804, 0x4d48, 0xaad4, 0xabd8, 0xacdc, 0x0804,
-	0x4d48, 0x0016, 0x0026, 0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e,
-	0x080c, 0x6724, 0x2019, 0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019,
-	0x0000, 0x2011, 0x801b, 0x080c, 0x4c44, 0x00ce, 0x00be, 0x003e,
-	0x002e, 0x001e, 0x0005, 0x0026, 0x080c, 0x57d5, 0xd0c4, 0x0120,
-	0x2011, 0x8014, 0x080c, 0x4c44, 0x002e, 0x0005, 0x81ff, 0x1904,
-	0x35e7, 0x0126, 0x2091, 0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac,
-	0x6032, 0x080c, 0x7637, 0x1158, 0x080c, 0x7932, 0x080c, 0x612e,
-	0x9085, 0x0001, 0x080c, 0x767b, 0x080c, 0x7563, 0x0010, 0x080c,
-	0x5fed, 0x012e, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001,
-	0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804,
-	0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804, 0x35e7,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x0178, 0x0026, 0x2011, 0x0010,
-	0x080c, 0x6ac7, 0x002e, 0x0140, 0x7984, 0x080c, 0x6b11, 0x1120,
-	0x2009, 0x4009, 0x0804, 0x35e7, 0x7984, 0x080c, 0x66b9, 0x1904,
-	0x35ea, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x2b00, 0x7026, 0x080c,
-	0x6aa3, 0x7888, 0x1170, 0x9084, 0x0005, 0x1158, 0x900e, 0x080c,
-	0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804,
-	0x35b5, 0x080c, 0x4be4, 0x0904, 0x35e7, 0x9006, 0xa866, 0xa832,
-	0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd302, 0x0904, 0x35e7, 0x7888,
-	0xd094, 0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x7007, 0x0003, 0x701f,
-	0x4ecb, 0x0005, 0x2061, 0x1800, 0x080c, 0x57e9, 0x2009, 0x0007,
-	0x1560, 0x080c, 0x6a9b, 0x0118, 0x2009, 0x0008, 0x0430, 0xa998,
-	0x080c, 0x66b9, 0x1530, 0x080c, 0x4c15, 0x0518, 0x080c, 0x6aa3,
-	0xa89c, 0x1168, 0x9084, 0x0005, 0x1150, 0x900e, 0x080c, 0x6944,
-	0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868,
-	0xc0fc, 0xa86a, 0x080c, 0xd302, 0x11e0, 0xa89c, 0xd094, 0x0118,
-	0xb8cc, 0xc08d, 0xb8ce, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a,
-	0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030,
-	0x0005, 0xa897, 0x4000, 0xa99a, 0x9006, 0x918d, 0x0001, 0x2008,
-	0x0005, 0x9006, 0x0005, 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c,
-	0x0140, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804,
-	0x35b7, 0x9086, 0x0100, 0x7024, 0x2058, 0x1110, 0x0804, 0x5729,
-	0x900e, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108,
-	0xc18d, 0x0804, 0x35b5, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007,
-	0x0804, 0x35e7, 0x7f84, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c,
-	0x4be4, 0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x900e, 0x2130,
-	0x7126, 0x7132, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005,
-	0x702a, 0x20a0, 0x080c, 0x6724, 0x1904, 0x4f81, 0x080c, 0x6aa3,
-	0x0138, 0x080c, 0x6aab, 0x0120, 0x080c, 0x6a43, 0x1904, 0x4f81,
-	0xd794, 0x1110, 0xd784, 0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080,
-	0x0006, 0x2098, 0x3400, 0xd794, 0x0198, 0x20a9, 0x0008, 0x4003,
-	0x2098, 0x20a0, 0x3d00, 0x20e0, 0x20a9, 0x0002, 0x080c, 0x49b3,
-	0x0080, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098, 0x3400,
-	0x20a9, 0x0004, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c,
-	0x49b3, 0x9186, 0x007e, 0x0170, 0x9186, 0x0080, 0x0158, 0x080c,
-	0x6aa3, 0x90c2, 0x0006, 0x1210, 0xc1fd, 0x0020, 0x080c, 0x6944,
-	0x1108, 0xc1fd, 0x4104, 0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0,
-	0xb8c8, 0x2060, 0x9c80, 0x0000, 0x2098, 0x20a9, 0x0002, 0x4003,
-	0x9c80, 0x0003, 0x2098, 0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004,
-	0x2098, 0x3400, 0x20a9, 0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00,
-	0x20e0, 0x080c, 0x49a6, 0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0,
-	0x20a9, 0x0002, 0x4003, 0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0,
-	0x0005, 0x8108, 0x080c, 0xb23d, 0x0118, 0x9186, 0x0800, 0x0040,
-	0xd78c, 0x0120, 0x9186, 0x0800, 0x0170, 0x0018, 0x9186, 0x007e,
-	0x0150, 0xd794, 0x0118, 0x9686, 0x0020, 0x0010, 0x9686, 0x0028,
-	0x0150, 0x0804, 0x4f0a, 0x86ff, 0x1120, 0x7124, 0x810b, 0x0804,
-	0x35b5, 0x7033, 0x0001, 0x7122, 0x7024, 0x9600, 0x7026, 0x772e,
-	0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072,
-	0x7028, 0xa076, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x10f8,
-	0x7007, 0x0002, 0x701f, 0x4fbd, 0x0005, 0x7030, 0x9005, 0x1180,
-	0x7120, 0x7028, 0x20a0, 0x772c, 0x9036, 0x7034, 0x20e8, 0x2061,
-	0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494, 0xa598, 0x0804, 0x4f0a,
-	0x7124, 0x810b, 0x0804, 0x35b5, 0x2029, 0x007e, 0x7984, 0x7a88,
-	0x7b8c, 0x7c98, 0x9184, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04,
-	0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9184, 0x00ff, 0x90e2, 0x0020,
-	0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9284, 0xff00, 0x8007,
-	0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9284,
-	0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea,
-	0x9384, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x35ea, 0x9502,
-	0x0a04, 0x35ea, 0x9384, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x35ea,
-	0x9502, 0x0a04, 0x35ea, 0x9484, 0xff00, 0x8007, 0x90e2, 0x0020,
-	0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x9484, 0x00ff, 0x90e2,
-	0x0020, 0x0a04, 0x35ea, 0x9502, 0x0a04, 0x35ea, 0x2061, 0x1989,
-	0x6102, 0x6206, 0x630a, 0x640e, 0x0804, 0x35b5, 0x080c, 0x4be4,
-	0x0904, 0x35e7, 0x2009, 0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98,
-	0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x5041,
-	0x0005, 0x20a9, 0x0016, 0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0,
-	0x9080, 0x0019, 0x2098, 0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877,
-	0x20e9, 0x0001, 0x2da0, 0x4003, 0x6800, 0x9005, 0x0904, 0x50a8,
-	0x6804, 0x2008, 0x918c, 0xfff8, 0x1904, 0x50a8, 0x680c, 0x9005,
-	0x0904, 0x50a8, 0x9082, 0xff01, 0x1a04, 0x50a8, 0x6810, 0x9082,
-	0x005c, 0x06f0, 0x6824, 0x2008, 0x9082, 0x0008, 0x06c8, 0x9182,
-	0x0400, 0x16b0, 0x0056, 0x2029, 0x0000, 0x080c, 0x8e80, 0x005e,
-	0x6944, 0x6820, 0x9102, 0x0660, 0x6820, 0x9082, 0x0019, 0x1640,
-	0x6828, 0x6944, 0x810c, 0x9102, 0x0618, 0x6840, 0x9082, 0x000f,
-	0x12f8, 0x080c, 0x1027, 0x2900, 0x0590, 0x684e, 0x00e6, 0x2071,
-	0x1931, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8d3c, 0x00be, 0x00ee,
-	0x01e8, 0x080c, 0x8a84, 0x080c, 0x8ad3, 0x1160, 0x6857, 0x0000,
-	0x00c6, 0x6b10, 0x2061, 0x1a65, 0x630a, 0x00ce, 0x0804, 0x35b5,
-	0x0804, 0x35ea, 0x080c, 0x8acc, 0x00e6, 0x2071, 0x1931, 0x080c,
-	0x8f00, 0x080c, 0x8f0f, 0x080c, 0x8d21, 0x00ee, 0x2001, 0x188a,
-	0x204c, 0x080c, 0x1040, 0x2001, 0x188a, 0x2003, 0x0000, 0x0804,
-	0x35e7, 0x0126, 0x2091, 0x8000, 0x080c, 0x92bf, 0x080c, 0x8acc,
-	0x012e, 0x0804, 0x35b5, 0x0006, 0x080c, 0x57d5, 0xd0cc, 0x000e,
-	0x0005, 0x0006, 0x080c, 0x57d9, 0xd0bc, 0x000e, 0x0005, 0x6174,
-	0x7a84, 0x6300, 0x82ff, 0x1118, 0x7986, 0x0804, 0x35b5, 0x83ff,
-	0x1904, 0x35ea, 0x2001, 0xfff0, 0x9200, 0x1a04, 0x35ea, 0x2019,
-	0xffff, 0x6078, 0x9302, 0x9200, 0x0a04, 0x35ea, 0x7986, 0x6276,
-	0x0804, 0x35b5, 0x080c, 0x57e9, 0x1904, 0x35e7, 0x7c88, 0x7d84,
-	0x7e98, 0x7f8c, 0x080c, 0x4be4, 0x0904, 0x35e7, 0x900e, 0x901e,
-	0x7326, 0x7332, 0xa860, 0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003,
-	0x702a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c,
-	0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1148, 0x20a9, 0x0001, 0xb814,
-	0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182,
-	0x0800, 0x0120, 0x9386, 0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148,
-	0x7224, 0x900e, 0x2001, 0x0003, 0x080c, 0x9375, 0x2208, 0x0804,
-	0x35b5, 0x7033, 0x0001, 0x7122, 0x7024, 0x9300, 0x7026, 0x2061,
-	0x18b8, 0x2c44, 0xa06b, 0x0000, 0xa37a, 0x7028, 0xa076, 0x7034,
-	0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x10f8, 0x7007,
-	0x0002, 0x701f, 0x514c, 0x0005, 0x7030, 0x9005, 0x1178, 0x7120,
-	0x7028, 0x20a0, 0x901e, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44,
-	0xa48c, 0xa590, 0xa694, 0xa798, 0x0804, 0x510a, 0x7224, 0x900e,
-	0x2001, 0x0003, 0x080c, 0x9375, 0x2208, 0x0804, 0x35b5, 0x00f6,
-	0x00e6, 0x080c, 0x57e9, 0x2009, 0x0007, 0x1904, 0x51df, 0x2071,
-	0x189e, 0x745c, 0x84ff, 0x2009, 0x000e, 0x1904, 0x51df, 0xac9c,
-	0xad98, 0xaea4, 0xafa0, 0x0096, 0x080c, 0x1027, 0x2009, 0x0002,
-	0x0904, 0x51df, 0x2900, 0x705e, 0x900e, 0x901e, 0x7356, 0x7362,
-	0xa860, 0x7066, 0xa85c, 0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8,
-	0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6aa3, 0x0118, 0x080c,
-	0x6aab, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004,
-	0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386,
-	0x003c, 0x01e8, 0x0c20, 0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001,
-	0x0003, 0x080c, 0x9375, 0x2208, 0x009e, 0xa897, 0x4000, 0xa99a,
-	0x715c, 0x81ff, 0x090c, 0x0dc5, 0x2148, 0x080c, 0x1040, 0x9006,
-	0x705e, 0x918d, 0x0001, 0x2008, 0x0418, 0x7063, 0x0001, 0x7152,
-	0x7054, 0x9300, 0x7056, 0x2061, 0x18b9, 0x2c44, 0xa37a, 0x7058,
-	0xa076, 0x7064, 0xa072, 0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f,
-	0x51eb, 0x000e, 0xa0a2, 0x080c, 0x10f8, 0x9006, 0x0048, 0x009e,
-	0xa897, 0x4005, 0xa99a, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030,
-	0x00ee, 0x00fe, 0x0005, 0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0dc5,
-	0x00e6, 0x2071, 0x189e, 0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b,
-	0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x00d8, 0x7060, 0x9005,
-	0x1158, 0x7150, 0x7058, 0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c,
-	0xa590, 0xa694, 0xa798, 0x0428, 0xa87b, 0x0000, 0xa883, 0x0000,
-	0xa897, 0x4000, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x9375,
-	0xaa9a, 0x715c, 0x81ff, 0x090c, 0x0dc5, 0x2148, 0x080c, 0x1040,
-	0x705f, 0x0000, 0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x6e9f, 0x012e, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe,
-	0x0005, 0x91d8, 0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6aa3,
-	0x0118, 0x080c, 0x6aab, 0x1148, 0xb814, 0x20a9, 0x0001, 0x4004,
-	0xb810, 0x4004, 0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800,
-	0x0120, 0x9386, 0x003c, 0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154,
-	0x810c, 0xa99a, 0xa897, 0x4000, 0x715c, 0x81ff, 0x090c, 0x0dc5,
-	0x2148, 0x080c, 0x1040, 0x9006, 0x705e, 0x918d, 0x0001, 0x2008,
-	0xa0a0, 0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e,
-	0xa09f, 0x0000, 0xa0a3, 0x0000, 0x0070, 0x7063, 0x0001, 0x7152,
-	0x7054, 0x9300, 0x7056, 0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a,
-	0x080c, 0x10f8, 0x9006, 0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be,
-	0x7000, 0x0148, 0x90be, 0x7100, 0x0130, 0x90be, 0x7200, 0x0118,
-	0x009e, 0x0804, 0x35ea, 0xa884, 0xa988, 0x080c, 0x2873, 0x1518,
-	0x080c, 0x66b9, 0x1500, 0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c,
-	0x4be4, 0x01c8, 0x080c, 0x4be4, 0x01b0, 0x009e, 0xa867, 0x0000,
-	0xa868, 0xc0fd, 0xa86a, 0xa823, 0x0000, 0xa804, 0x2048, 0x080c,
-	0xd284, 0x1120, 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003,
-	0x701f, 0x52b8, 0x0005, 0x009e, 0x2009, 0x0002, 0x0804, 0x35e7,
-	0x7124, 0x080c, 0x334c, 0xa820, 0x9086, 0x8001, 0x1120, 0x2009,
-	0x0004, 0x0804, 0x35e7, 0x2900, 0x7022, 0xa804, 0x0096, 0x2048,
-	0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e,
-	0x9080, 0x0002, 0x0076, 0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8,
-	0x20a9, 0x002a, 0x080c, 0x0f8b, 0xaa6c, 0xab70, 0xac74, 0xad78,
-	0x2061, 0x18b8, 0x2c44, 0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6,
-	0x7000, 0x0118, 0x97c6, 0x7100, 0x1148, 0x96c2, 0x0004, 0x0600,
-	0x2009, 0x0004, 0x000e, 0x007e, 0x0804, 0x4c30, 0x97c6, 0x7200,
-	0x11b8, 0x96c2, 0x0054, 0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8,
-	0x2c44, 0xa076, 0xa772, 0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496,
-	0xa59a, 0x080c, 0x10f8, 0x7007, 0x0002, 0x701f, 0x5314, 0x0005,
-	0x000e, 0x007e, 0x0804, 0x35ea, 0x7020, 0x2048, 0xa804, 0x2048,
-	0xa804, 0x2048, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084,
-	0xffc0, 0x9080, 0x0002, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9,
-	0x002a, 0x080c, 0x0f8b, 0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44,
-	0xa28c, 0xa390, 0xa494, 0xa598, 0x2009, 0x002a, 0x0804, 0x4c30,
-	0x81ff, 0x1904, 0x35e7, 0x798c, 0x2001, 0x197e, 0x918c, 0x8000,
-	0x2102, 0x080c, 0x4bfb, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x0120,
-	0x080c, 0x6aab, 0x1904, 0x35ea, 0x080c, 0x67eb, 0x0904, 0x35e7,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x68b1, 0x012e, 0x0904, 0x35e7,
-	0x2001, 0x197e, 0x2004, 0xd0fc, 0x1904, 0x35b5, 0x0804, 0x460c,
-	0xa9a0, 0x2001, 0x197e, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c,
-	0x4c08, 0x01a0, 0x080c, 0x6aa3, 0x0118, 0x080c, 0x6aab, 0x1170,
-	0x080c, 0x67eb, 0x2009, 0x0002, 0x0128, 0x080c, 0x68b1, 0x1170,
-	0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006,
-	0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000,
-	0x2001, 0x197e, 0x2004, 0xd0fc, 0x1128, 0x080c, 0x57dd, 0x0110,
-	0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005,
-	0x78a8, 0xd08c, 0x1118, 0xd084, 0x0904, 0x4581, 0x080c, 0x4c17,
-	0x0904, 0x35ea, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804,
-	0x35e7, 0x080c, 0x6aa3, 0x0130, 0x908e, 0x0004, 0x0118, 0x908e,
-	0x0005, 0x15a0, 0x78a8, 0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802,
-	0x0028, 0x080c, 0x57d5, 0xd0b4, 0x0904, 0x45bb, 0x7884, 0x908e,
-	0x007e, 0x0904, 0x45bb, 0x908e, 0x007f, 0x0904, 0x45bb, 0x908e,
-	0x0080, 0x0904, 0x45bb, 0xb800, 0xd08c, 0x1904, 0x45bb, 0xa867,
-	0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2a3, 0x1120, 0x2009,
-	0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x53e0, 0x0005,
-	0x080c, 0x4c17, 0x0904, 0x35ea, 0x0804, 0x45bb, 0x080c, 0x33a5,
-	0x0108, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x0120, 0x2009,
-	0x0001, 0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007,
-	0x0804, 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804,
-	0x35e7, 0xb89c, 0xd0a4, 0x1118, 0xd0ac, 0x1904, 0x45bb, 0x9006,
-	0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd302, 0x1120,
-	0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x5419,
-	0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804,
-	0x5729, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x0804, 0x53b2, 0x81ff,
-	0x2009, 0x0001, 0x1904, 0x35e7, 0x080c, 0x57e9, 0x2009, 0x0007,
-	0x1904, 0x35e7, 0x080c, 0x6a9b, 0x0120, 0x2009, 0x0008, 0x0804,
-	0x35e7, 0x080c, 0x4c17, 0x0904, 0x35ea, 0x080c, 0x6aa3, 0x2009,
-	0x0009, 0x1904, 0x35e7, 0x080c, 0x4be4, 0x2009, 0x0002, 0x0904,
-	0x35e7, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988,
-	0xa95a, 0x9194, 0xfd00, 0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128,
-	0xc0ed, 0xa952, 0x798c, 0xa956, 0x0038, 0x928e, 0x0100, 0x1904,
-	0x35ea, 0xc0e5, 0xa952, 0xa956, 0xa83e, 0x080c, 0xd555, 0x2009,
-	0x0003, 0x0904, 0x35e7, 0x7007, 0x0003, 0x701f, 0x5470, 0x0005,
-	0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x35e7, 0x0804,
-	0x35b5, 0x7aa8, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c,
-	0x57e9, 0x1188, 0x2009, 0x0014, 0x0804, 0x35e7, 0xd2dc, 0x1578,
-	0x81ff, 0x2009, 0x0001, 0x1904, 0x35e7, 0x080c, 0x57e9, 0x2009,
-	0x0007, 0x1904, 0x35e7, 0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5,
-	0x080c, 0x57af, 0x0804, 0x35b5, 0xd2fc, 0x0160, 0x080c, 0x4c17,
-	0x0904, 0x35ea, 0x7984, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5784,
-	0x0804, 0x35b5, 0x080c, 0x4c17, 0x0904, 0x35ea, 0xb804, 0x9084,
-	0x00ff, 0x9086, 0x0006, 0x2009, 0x0009, 0x1904, 0x555f, 0x080c,
-	0x4be4, 0x2009, 0x0002, 0x0904, 0x555f, 0xa85c, 0x9080, 0x001b,
-	0xaf60, 0x2009, 0x0008, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c,
-	0x4c2d, 0x701f, 0x54cc, 0x0005, 0xa86c, 0x9086, 0x0500, 0x1138,
-	0xa870, 0x9005, 0x1120, 0xa874, 0x9084, 0xff00, 0x0110, 0x1904,
-	0x35ea, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4c17,
-	0x1110, 0x0804, 0x35ea, 0x2009, 0x0043, 0x080c, 0xd5c1, 0x2009,
-	0x0003, 0x0904, 0x555f, 0x7007, 0x0003, 0x701f, 0x54f0, 0x0005,
-	0xa830, 0x9086, 0x0100, 0x2009, 0x0004, 0x0904, 0x555f, 0x7984,
-	0x7aa8, 0x9284, 0x1000, 0xc0d5, 0x080c, 0x5784, 0x0804, 0x35b5,
-	0x00c6, 0xaab0, 0x9284, 0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c,
-	0x57e9, 0x1158, 0x2009, 0x0014, 0x0804, 0x554e, 0x2061, 0x1800,
-	0x080c, 0x57e9, 0x2009, 0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284,
-	0x5000, 0xc0d5, 0x080c, 0x57af, 0x0058, 0xd2fc, 0x0180, 0x080c,
-	0x4c15, 0x0590, 0xa998, 0x9284, 0x9000, 0xc0d5, 0x080c, 0x5784,
-	0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x0438, 0x080c,
-	0x4c15, 0x0510, 0x080c, 0x6aa3, 0x2009, 0x0009, 0x11b8, 0xa8c4,
-	0x9086, 0x0500, 0x11c8, 0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084,
-	0xff00, 0x1190, 0x080c, 0x4c15, 0x1108, 0x0070, 0x2009, 0x004b,
-	0x080c, 0xd5c1, 0x2009, 0x0003, 0x0108, 0x0078, 0x0431, 0x19c0,
-	0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085,
-	0x0001, 0x2001, 0x0030, 0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8,
-	0xd2dc, 0x0904, 0x35e7, 0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd,
-	0x080c, 0x5784, 0x001e, 0x1904, 0x35e7, 0x0804, 0x35b5, 0x00f6,
-	0x2d78, 0xaab0, 0x0021, 0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc,
-	0x0150, 0x0016, 0xa998, 0x9284, 0x1400, 0xc0fd, 0x080c, 0x5784,
-	0x001e, 0x9085, 0x0001, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001,
-	0x0804, 0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804,
-	0x35e7, 0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6724, 0x1904,
-	0x35ea, 0x9186, 0x007f, 0x0138, 0x080c, 0x6aa3, 0x0120, 0x2009,
-	0x0009, 0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002,
-	0x0804, 0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001,
-	0x0100, 0x8007, 0xa80a, 0x080c, 0xd2bd, 0x1120, 0x2009, 0x0003,
-	0x0804, 0x35e7, 0x7007, 0x0003, 0x701f, 0x55bf, 0x0005, 0xa808,
-	0x8007, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x35e7,
-	0xa8e0, 0xa866, 0xa810, 0x8007, 0x9084, 0x00ff, 0x800c, 0xa814,
-	0x8007, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0002, 0x9108, 0x8906,
-	0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0004,
-	0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x0804, 0x4c30, 0x080c, 0x4be4,
-	0x1120, 0x2009, 0x0002, 0x0804, 0x35e7, 0x7984, 0x9194, 0xff00,
-	0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x7023, 0x19b4, 0x0040,
-	0x92c6, 0x0001, 0x1118, 0x7023, 0x19ce, 0x0010, 0x0804, 0x35ea,
-	0x2009, 0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080,
-	0x0019, 0xaf60, 0x080c, 0x4c2d, 0x701f, 0x560f, 0x0005, 0x2001,
-	0x182e, 0x2003, 0x0001, 0xa85c, 0x9080, 0x0019, 0x2098, 0xa860,
-	0x20e0, 0x20a9, 0x001a, 0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003,
-	0x0804, 0x35b5, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804,
-	0x35e7, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff,
-	0x1118, 0x2099, 0x19b4, 0x0040, 0x92c6, 0x0001, 0x1118, 0x2099,
-	0x19ce, 0x0010, 0x0804, 0x35ea, 0xa85c, 0x9080, 0x0019, 0x20a0,
-	0xa860, 0x20e8, 0x20a9, 0x001a, 0x20e1, 0x0001, 0x4003, 0x2009,
-	0x001a, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019,
-	0xaf60, 0x0804, 0x4c30, 0x7884, 0x908a, 0x1000, 0x1a04, 0x35ea,
-	0x0126, 0x2091, 0x8000, 0x8003, 0x800b, 0x810b, 0x9108, 0x00c6,
-	0x2061, 0x19fb, 0x614a, 0x00ce, 0x012e, 0x0804, 0x35b5, 0x00c6,
-	0x080c, 0x7637, 0x1160, 0x080c, 0x7932, 0x080c, 0x612e, 0x9085,
-	0x0001, 0x080c, 0x767b, 0x080c, 0x7563, 0x080c, 0x0dc5, 0x2061,
-	0x1800, 0x6030, 0xc09d, 0x6032, 0x080c, 0x5fed, 0x00ce, 0x0005,
-	0x00c6, 0x2001, 0x1800, 0x2004, 0x908e, 0x0000, 0x0904, 0x35e7,
-	0x7884, 0x9005, 0x0188, 0x7888, 0x2061, 0x199c, 0x2c0c, 0x2062,
-	0x080c, 0x2c49, 0x01a0, 0x080c, 0x2c51, 0x0188, 0x080c, 0x2c59,
-	0x0170, 0x2162, 0x0804, 0x35ea, 0x2061, 0x0100, 0x6038, 0x9086,
-	0x0007, 0x1118, 0x2009, 0x0001, 0x0010, 0x2009, 0x0000, 0x7884,
-	0x9086, 0x0002, 0x1568, 0x2061, 0x0100, 0x6028, 0xc09c, 0x602a,
-	0x0026, 0x2011, 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c,
-	0xaac9, 0x002e, 0x080c, 0xa9d3, 0x0036, 0x901e, 0x080c, 0xaa49,
-	0x003e, 0x60e3, 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x9085,
-	0x0001, 0x080c, 0x767b, 0x9006, 0x080c, 0x2d39, 0x2001, 0x1800,
-	0x2003, 0x0004, 0x2001, 0x19a8, 0x2003, 0x0000, 0x6027, 0x0008,
-	0x00ce, 0x0804, 0x35b5, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
-	0x35e7, 0x080c, 0x57e9, 0x0120, 0x2009, 0x0007, 0x0804, 0x35e7,
-	0x7984, 0x7ea8, 0x96b4, 0x00ff, 0x080c, 0x6724, 0x1904, 0x35ea,
-	0x9186, 0x007f, 0x0138, 0x080c, 0x6aa3, 0x0120, 0x2009, 0x0009,
-	0x0804, 0x35e7, 0x080c, 0x4be4, 0x1120, 0x2009, 0x0002, 0x0804,
-	0x35e7, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd2c0,
-	0x1120, 0x2009, 0x0003, 0x0804, 0x35e7, 0x7007, 0x0003, 0x701f,
-	0x5712, 0x0005, 0xa830, 0x9086, 0x0100, 0x1120, 0x2009, 0x0004,
-	0x0804, 0x35e7, 0xa8e0, 0xa866, 0xa834, 0x8007, 0x800c, 0xa85c,
-	0x9080, 0x000c, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804,
-	0x4c30, 0xa898, 0x9086, 0x000d, 0x1904, 0x35e7, 0x2021, 0x4005,
-	0x0126, 0x2091, 0x8000, 0x0e04, 0x5736, 0x0010, 0x012e, 0x0cc0,
-	0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010, 0x7833,
-	0x0010, 0x7883, 0x4005, 0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8,
-	0x799e, 0x080c, 0x4c20, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004,
-	0xd084, 0x190c, 0x11aa, 0x7007, 0x0001, 0x2091, 0x5000, 0x700f,
-	0x0000, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x00c6, 0x2061,
-	0x19fb, 0x7984, 0x615a, 0x6156, 0x605f, 0x0000, 0x6053, 0x0009,
-	0x7898, 0x6072, 0x789c, 0x606e, 0x7888, 0x606a, 0x788c, 0x6066,
-	0x2001, 0x1a0b, 0x2044, 0x2001, 0x1a12, 0xa076, 0xa060, 0xa072,
-	0xa07b, 0x0001, 0xa07f, 0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000,
-	0x00ce, 0x012e, 0x0804, 0x35b5, 0x0126, 0x2091, 0x8000, 0x00b6,
-	0x00c6, 0x90e4, 0xc000, 0x0168, 0x0006, 0xd0d4, 0x0130, 0x0036,
-	0x2019, 0x0029, 0x080c, 0x336a, 0x003e, 0x080c, 0xd125, 0x000e,
-	0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000, 0x2004, 0x905d, 0x0160,
-	0x080c, 0x6148, 0x080c, 0xb23d, 0x0110, 0xb817, 0x0000, 0x9006,
-	0x00ce, 0x00be, 0x012e, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x0126,
-	0x2091, 0x8000, 0x0156, 0x2010, 0x900e, 0x20a9, 0x0800, 0x0016,
-	0x9180, 0x1000, 0x2004, 0x9005, 0x0188, 0x9186, 0x007e, 0x0170,
-	0x9186, 0x007f, 0x0158, 0x9186, 0x0080, 0x0140, 0x9186, 0x00ff,
-	0x0128, 0x0026, 0x2200, 0x080c, 0x5784, 0x002e, 0x001e, 0x8108,
-	0x1f04, 0x57b7, 0x015e, 0x012e, 0x0005, 0x2001, 0x1848, 0x2004,
-	0x0005, 0x2001, 0x1867, 0x2004, 0x0005, 0x0006, 0x2001, 0x1810,
-	0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0b4,
-	0x0005, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x0005, 0x0016,
-	0x00e6, 0x2071, 0x189e, 0x7108, 0x910d, 0x710a, 0x00ee, 0x001e,
-	0x0005, 0x79a4, 0x81ff, 0x0904, 0x35ea, 0x9182, 0x0081, 0x1a04,
-	0x35ea, 0x810c, 0x0016, 0x080c, 0x4be4, 0x0170, 0x080c, 0x0f16,
-	0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c, 0x7a90, 0x001e, 0x080c,
-	0x4c2d, 0x701f, 0x5819, 0x0005, 0x001e, 0x2009, 0x0002, 0x0804,
-	0x35e7, 0x2079, 0x0000, 0x7d94, 0x7c98, 0x7ba8, 0x7aac, 0x79a4,
-	0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770, 0xa074, 0x2071, 0x189e,
-	0x080c, 0x4c30, 0x701f, 0x582d, 0x0005, 0x2061, 0x18b8, 0x2c44,
-	0x0016, 0x0026, 0xa270, 0xa174, 0x080c, 0x0f1e, 0x002e, 0x001e,
-	0x080c, 0x0fcb, 0x9006, 0xa802, 0xa806, 0x0804, 0x35b5, 0x0126,
-	0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6,
-	0x00f6, 0x2061, 0x0100, 0x2069, 0x0200, 0x2071, 0x1800, 0x6044,
-	0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c, 0x59ed, 0x0068, 0xd08c,
-	0x0118, 0x080c, 0x58f6, 0x0040, 0xd094, 0x0118, 0x080c, 0x58c6,
-	0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe, 0x00ee, 0x00de, 0x00ce,
-	0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x012e, 0x0005, 0x0016,
-	0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a, 0x001e, 0x0c68, 0x7030,
-	0xd09c, 0x1120, 0x6004, 0x9085, 0x0002, 0x6006, 0x7098, 0x9005,
-	0x0120, 0x709b, 0x0000, 0x7093, 0x0000, 0x624c, 0x9286, 0xf0f0,
-	0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130, 0x624a, 0x6043, 0x0090,
-	0x6043, 0x0010, 0x0490, 0x9294, 0xff00, 0x9296, 0xf700, 0x0178,
-	0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295, 0x0100, 0x6242, 0x9294,
-	0x0010, 0x0128, 0x2009, 0x00f7, 0x080c, 0x60aa, 0x00f0, 0x6040,
-	0x9084, 0x0010, 0x9085, 0x0140, 0x6042, 0x6043, 0x0000, 0x7087,
-	0x0000, 0x70a3, 0x0001, 0x70c7, 0x0000, 0x70df, 0x0000, 0x2009,
-	0x1c80, 0x200b, 0x0000, 0x7097, 0x0000, 0x708b, 0x000f, 0x2009,
-	0x000f, 0x2011, 0x5f90, 0x080c, 0x88d5, 0x0005, 0x2001, 0x1869,
-	0x2004, 0xd08c, 0x0110, 0x705f, 0xffff, 0x7088, 0x9005, 0x1528,
-	0x2011, 0x5f90, 0x080c, 0x883d, 0x6040, 0x9094, 0x0010, 0x9285,
-	0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044, 0xd08c, 0x1168, 0x1f04,
-	0x58dc, 0x6242, 0x709b, 0x0000, 0x6040, 0x9094, 0x0010, 0x9285,
-	0x0080, 0x6042, 0x6242, 0x0048, 0x6242, 0x709b, 0x0000, 0x708f,
-	0x0000, 0x9006, 0x080c, 0x6133, 0x0000, 0x0005, 0x708c, 0x908a,
-	0x0003, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x5900, 0x5951, 0x59ec,
-	0x00f6, 0x0016, 0x6900, 0x918c, 0x0800, 0x708f, 0x0001, 0x2001,
-	0x015d, 0x2003, 0x0000, 0x6803, 0x00fc, 0x20a9, 0x0004, 0x6800,
-	0x9084, 0x00fc, 0x0120, 0x1f04, 0x590f, 0x080c, 0x0dc5, 0x68a0,
-	0x68a2, 0x689c, 0x689e, 0x6898, 0x689a, 0xa001, 0x918d, 0x1600,
-	0x6902, 0x001e, 0x6837, 0x0020, 0x080c, 0x610f, 0x2079, 0x1c00,
-	0x7833, 0x1101, 0x7837, 0x0000, 0x20e1, 0x0001, 0x2099, 0x1805,
-	0x20e9, 0x0001, 0x20a1, 0x1c0e, 0x20a9, 0x0004, 0x4003, 0x080c,
-	0xaf8e, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1,
-	0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x600f, 0x0000,
-	0x080c, 0x5fc1, 0x00fe, 0x9006, 0x7092, 0x6043, 0x0008, 0x6042,
-	0x0005, 0x00f6, 0x7090, 0x7093, 0x0000, 0x9025, 0x0904, 0x59c9,
-	0x6020, 0xd0b4, 0x1904, 0x59c7, 0x71a0, 0x81ff, 0x0904, 0x59b5,
-	0x9486, 0x000c, 0x1904, 0x59c2, 0x9480, 0x0018, 0x8004, 0x20a8,
-	0x080c, 0x6108, 0x2011, 0x0260, 0x2019, 0x1c00, 0x220c, 0x2304,
-	0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04, 0x596e, 0x6043, 0x0004,
-	0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100,
-	0x6043, 0x0006, 0x708f, 0x0002, 0x709b, 0x0002, 0x2009, 0x07d0,
-	0x2011, 0x5f97, 0x080c, 0x88d5, 0x080c, 0x610f, 0x04c0, 0x080c,
-	0x6108, 0x2079, 0x0260, 0x7930, 0x918e, 0x1101, 0x1558, 0x7834,
-	0x9005, 0x1540, 0x7900, 0x918c, 0x00ff, 0x1118, 0x7804, 0x9005,
-	0x0190, 0x080c, 0x6108, 0x2011, 0x026e, 0x2019, 0x1805, 0x20a9,
-	0x0004, 0x220c, 0x2304, 0x9102, 0x0230, 0x11a0, 0x8210, 0x8318,
-	0x1f04, 0x59a9, 0x0078, 0x70a3, 0x0000, 0x080c, 0x6108, 0x20e1,
-	0x0000, 0x2099, 0x0260, 0x20e9, 0x0001, 0x20a1, 0x1c00, 0x20a9,
-	0x0014, 0x4003, 0x6043, 0x0008, 0x6043, 0x0000, 0x0010, 0x00fe,
-	0x0005, 0x6040, 0x9085, 0x0100, 0x6042, 0x6020, 0xd0b4, 0x1db8,
-	0x080c, 0xaf8e, 0x20e1, 0x0001, 0x2099, 0x1c00, 0x20e9, 0x0000,
-	0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3, 0x000c, 0x2011,
-	0x19f2, 0x2013, 0x0000, 0x7093, 0x0000, 0x60a3, 0x0056, 0x60a7,
-	0x9575, 0x080c, 0xa6e0, 0x08d8, 0x0005, 0x7098, 0x908a, 0x001d,
-	0x1a0c, 0x0dc5, 0x000b, 0x0005, 0x5a1e, 0x5a31, 0x5a5a, 0x5a7a,
-	0x5aa0, 0x5acf, 0x5af5, 0x5b2d, 0x5b53, 0x5b81, 0x5bbc, 0x5bf4,
-	0x5c12, 0x5c3d, 0x5c5f, 0x5c7a, 0x5c84, 0x5cb8, 0x5cde, 0x5d0d,
-	0x5d33, 0x5d6b, 0x5daf, 0x5dec, 0x5e0d, 0x5e66, 0x5e88, 0x5eb6,
-	0x5eb6, 0x00c6, 0x2061, 0x1800, 0x6003, 0x0007, 0x2061, 0x0100,
-	0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce, 0x0005, 0x2061, 0x0140,
-	0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061, 0x0100, 0x6043, 0x0002,
-	0x709b, 0x0001, 0x2009, 0x07d0, 0x2011, 0x5f97, 0x080c, 0x88d5,
-	0x0005, 0x00f6, 0x7090, 0x9086, 0x0014, 0x1510, 0x6042, 0x6020,
-	0xd0b4, 0x11f0, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296,
-	0x1102, 0x11a0, 0x7834, 0x9005, 0x1188, 0x7a38, 0xd2fc, 0x0128,
-	0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x2011, 0x5f97, 0x080c,
-	0x883d, 0x709b, 0x0010, 0x080c, 0x5c84, 0x0010, 0x7093, 0x0000,
-	0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003, 0x6043, 0x0004, 0x2011,
-	0x5f97, 0x080c, 0x883d, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833,
-	0x1102, 0x7837, 0x0000, 0x20a9, 0x0008, 0x9f88, 0x000e, 0x200b,
-	0x0000, 0x8108, 0x1f04, 0x5a6f, 0x60c3, 0x0014, 0x080c, 0x5fc1,
-	0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97,
-	0x080c, 0x883d, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079,
-	0x0260, 0x7a30, 0x9296, 0x1102, 0x1178, 0x7834, 0x9005, 0x1160,
-	0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001,
-	0x709b, 0x0004, 0x0029, 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005,
-	0x00f6, 0x709b, 0x0005, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833,
-	0x1103, 0x7837, 0x0000, 0x080c, 0x6108, 0x080c, 0x60eb, 0x1170,
-	0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011,
-	0x0008, 0x080c, 0x5f44, 0x0168, 0x080c, 0x60c1, 0x20a9, 0x0008,
-	0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e,
-	0x4003, 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6,
-	0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086,
-	0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296,
-	0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128,
-	0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0006, 0x0029,
-	0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0007,
-	0x080c, 0x608c, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000,
-	0x080c, 0x6108, 0x080c, 0x60eb, 0x11b8, 0x7084, 0x9005, 0x11a0,
-	0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x33b6, 0x200d, 0x918c,
-	0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5f44, 0x0180, 0x080c,
-	0x50d1, 0x0110, 0x080c, 0x28dc, 0x20a9, 0x0008, 0x20e1, 0x0000,
-	0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3,
-	0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005,
-	0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8,
-	0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178,
-	0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005,
-	0x1110, 0x70c7, 0x0001, 0x709b, 0x0008, 0x0029, 0x0010, 0x080c,
-	0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0009, 0x080c, 0x608c,
-	0x2079, 0x0240, 0x7833, 0x1105, 0x7837, 0x0100, 0x080c, 0x60eb,
-	0x1150, 0x7084, 0x9005, 0x1138, 0x080c, 0x5eb7, 0x1188, 0x9085,
-	0x0001, 0x080c, 0x28dc, 0x20a9, 0x0008, 0x080c, 0x6108, 0x20e1,
-	0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003,
-	0x60c3, 0x0014, 0x080c, 0x5fc1, 0x0010, 0x080c, 0x5a11, 0x00fe,
-	0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8, 0x2011, 0x5f97, 0x080c,
-	0x883d, 0x9086, 0x0014, 0x1560, 0x080c, 0x6108, 0x2079, 0x0260,
-	0x7a30, 0x9296, 0x1105, 0x1520, 0x7834, 0x9084, 0x0100, 0x2011,
-	0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005,
-	0x1110, 0x70c7, 0x0001, 0x709b, 0x000a, 0x00b1, 0x0098, 0x9005,
-	0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7,
-	0x0001, 0x7097, 0x0000, 0x709b, 0x000e, 0x080c, 0x5c5f, 0x0010,
-	0x080c, 0x60e4, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000b, 0x2011,
-	0x1c0e, 0x20e9, 0x0001, 0x22a0, 0x20a9, 0x0040, 0x2019, 0xffff,
-	0x4304, 0x080c, 0x608c, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837,
-	0x0000, 0x080c, 0x60eb, 0x0118, 0x2013, 0x0000, 0x0020, 0x7060,
-	0x9085, 0x0100, 0x2012, 0x20a9, 0x0040, 0x2009, 0x024e, 0x2011,
-	0x1c0e, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1128, 0x6810,
-	0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5be1, 0x60c3, 0x0084,
-	0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01c0,
-	0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1178, 0x080c,
-	0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1138, 0x7834,
-	0x9005, 0x1120, 0x709b, 0x000c, 0x0029, 0x0010, 0x080c, 0x60e4,
-	0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d, 0x080c, 0x608c, 0x2079,
-	0x0240, 0x7833, 0x1107, 0x7837, 0x0000, 0x080c, 0x6108, 0x20a9,
-	0x0040, 0x2011, 0x026e, 0x2009, 0x024e, 0x220e, 0x8210, 0x8108,
-	0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240,
-	0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04, 0x5c25, 0x60c3,
-	0x0084, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005,
-	0x01e0, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1198,
-	0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107, 0x1158,
-	0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x605e, 0x709b,
-	0x000e, 0x0029, 0x0010, 0x080c, 0x60e4, 0x00fe, 0x0005, 0x918d,
-	0x0001, 0x080c, 0x6133, 0x709b, 0x000f, 0x7093, 0x0000, 0x2061,
-	0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5, 0x2061, 0x0100, 0x6043,
-	0x0005, 0x6043, 0x0004, 0x2009, 0x07d0, 0x2011, 0x5f97, 0x080c,
-	0x8831, 0x0005, 0x7090, 0x9005, 0x0130, 0x2011, 0x5f97, 0x080c,
-	0x883d, 0x709b, 0x0000, 0x0005, 0x709b, 0x0011, 0x080c, 0xaf8e,
-	0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0000,
-	0x20a1, 0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084,
-	0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c, 0x60eb, 0x11a0, 0x717c,
-	0x81ff, 0x0188, 0x900e, 0x7080, 0x9084, 0x00ff, 0x0160, 0x080c,
-	0x2873, 0x9186, 0x007e, 0x0138, 0x9186, 0x0080, 0x0120, 0x2011,
-	0x0008, 0x080c, 0x5f44, 0x60c3, 0x0014, 0x080c, 0x5fc1, 0x0005,
-	0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x5f97, 0x080c, 0x883d,
-	0x9086, 0x0014, 0x11b8, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30,
-	0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc,
-	0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0012,
-	0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b,
-	0x0013, 0x080c, 0x609a, 0x2079, 0x0240, 0x7833, 0x1103, 0x7837,
-	0x0000, 0x080c, 0x6108, 0x080c, 0x60eb, 0x1170, 0x7084, 0x9005,
-	0x1158, 0x715c, 0x9186, 0xffff, 0x0138, 0x2011, 0x0008, 0x080c,
-	0x5f44, 0x0168, 0x080c, 0x60c1, 0x20a9, 0x0008, 0x20e1, 0x0000,
-	0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3,
-	0x0014, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005,
-	0x0500, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x11b8,
-	0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1104, 0x1178,
-	0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005,
-	0x1110, 0x70c7, 0x0001, 0x709b, 0x0014, 0x0029, 0x0010, 0x7093,
-	0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0015, 0x080c, 0x609a,
-	0x2079, 0x0240, 0x7833, 0x1104, 0x7837, 0x0000, 0x080c, 0x6108,
-	0x080c, 0x60eb, 0x11b8, 0x7084, 0x9005, 0x11a0, 0x7164, 0x9186,
-	0xffff, 0x0180, 0x9180, 0x33b6, 0x200d, 0x918c, 0xff00, 0x810f,
-	0x2011, 0x0008, 0x080c, 0x5f44, 0x0180, 0x080c, 0x50d1, 0x0110,
-	0x080c, 0x28dc, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e,
-	0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c,
-	0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05f0, 0x2011,
-	0x5f97, 0x080c, 0x883d, 0x9086, 0x0014, 0x15a8, 0x080c, 0x6108,
-	0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1568, 0x7834, 0x9084,
-	0x0100, 0x2011, 0x0100, 0x921e, 0x1168, 0x9085, 0x0001, 0x080c,
-	0x6133, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7,
-	0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38, 0xd2fc, 0x0128, 0x70c4,
-	0x9005, 0x1110, 0x70c7, 0x0001, 0x9085, 0x0001, 0x080c, 0x6133,
-	0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110, 0x70df, 0x0008, 0x709b,
-	0x0016, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x080c,
-	0xaf8e, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9,
-	0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e, 0x4003, 0x2011, 0x026d,
-	0x2204, 0x9084, 0x0100, 0x2011, 0x024d, 0x2012, 0x2011, 0x026e,
-	0x709b, 0x0017, 0x080c, 0x60eb, 0x1150, 0x7084, 0x9005, 0x1138,
-	0x080c, 0x5eb7, 0x1188, 0x9085, 0x0001, 0x080c, 0x28dc, 0x20a9,
-	0x0008, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9,
-	0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x5fc1,
-	0x0010, 0x080c, 0x5a11, 0x0005, 0x00f6, 0x7090, 0x9005, 0x01d8,
-	0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084, 0x1190, 0x080c,
-	0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1106, 0x1150, 0x7834,
-	0x9005, 0x1138, 0x9006, 0x080c, 0x6133, 0x709b, 0x0018, 0x0029,
-	0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0019,
-	0x080c, 0x609a, 0x2079, 0x0240, 0x7833, 0x1106, 0x7837, 0x0000,
-	0x080c, 0x6108, 0x2009, 0x026e, 0x2039, 0x1c0e, 0x20a9, 0x0040,
-	0x213e, 0x8738, 0x8108, 0x9186, 0x0280, 0x1128, 0x6814, 0x8000,
-	0x6816, 0x2009, 0x0260, 0x1f04, 0x5e20, 0x2039, 0x1c0e, 0x080c,
-	0x60eb, 0x11e8, 0x2728, 0x2514, 0x8207, 0x9084, 0x00ff, 0x8000,
-	0x2018, 0x9294, 0x00ff, 0x8007, 0x9205, 0x202a, 0x7060, 0x2310,
-	0x8214, 0x92a0, 0x1c0e, 0x2414, 0x938c, 0x0001, 0x0118, 0x9294,
-	0xff00, 0x0018, 0x9294, 0x00ff, 0x8007, 0x9215, 0x2222, 0x20a9,
-	0x0040, 0x2009, 0x024e, 0x270e, 0x8738, 0x8108, 0x9186, 0x0260,
-	0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04, 0x5e53,
-	0x60c3, 0x0084, 0x080c, 0x5fc1, 0x00fe, 0x0005, 0x00f6, 0x7090,
-	0x9005, 0x01e0, 0x2011, 0x5f97, 0x080c, 0x883d, 0x9086, 0x0084,
-	0x1198, 0x080c, 0x6108, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1107,
-	0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001, 0x080c, 0x605e,
-	0x709b, 0x001a, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005,
-	0x9085, 0x0001, 0x080c, 0x6133, 0x709b, 0x001b, 0x080c, 0xaf8e,
-	0x080c, 0x6108, 0x2011, 0x0260, 0x2009, 0x0240, 0x7490, 0x9480,
-	0x0018, 0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x220e,
-	0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000, 0x6812,
-	0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260, 0x1f04,
-	0x5e9f, 0x60c3, 0x0084, 0x080c, 0x5fc1, 0x0005, 0x0005, 0x0086,
-	0x0096, 0x2029, 0x1848, 0x252c, 0x20a9, 0x0008, 0x2041, 0x1c0e,
-	0x20e9, 0x0001, 0x28a0, 0x080c, 0x6108, 0x20e1, 0x0000, 0x2099,
-	0x026e, 0x4003, 0x20a9, 0x0008, 0x2011, 0x0007, 0xd5d4, 0x0108,
-	0x9016, 0x2800, 0x9200, 0x200c, 0x91a6, 0xffff, 0x1148, 0xd5d4,
-	0x0110, 0x8210, 0x0008, 0x8211, 0x1f04, 0x5ed1, 0x0804, 0x5f40,
-	0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6, 0x3fff, 0x0d90, 0x0020,
-	0x91a6, 0x3fff, 0x0904, 0x5f40, 0x918d, 0xc000, 0x20a9, 0x0010,
-	0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019, 0x0010, 0x2120, 0xd5d4,
-	0x0110, 0x8423, 0x0008, 0x8424, 0x1240, 0xd5d4, 0x0110, 0x8319,
-	0x0008, 0x8318, 0x1f04, 0x5ef7, 0x04d8, 0x23a8, 0x2021, 0x0001,
-	0x8426, 0x8425, 0x1f04, 0x5f09, 0x2328, 0x8529, 0x92be, 0x0007,
-	0x0158, 0x0006, 0x2039, 0x0007, 0x2200, 0x973a, 0x000e, 0x27a8,
-	0x95a8, 0x0010, 0x1f04, 0x5f18, 0x755e, 0x95c8, 0x33b6, 0x292d,
-	0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c,
-	0x28bc, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x2018, 0x2304, 0x9405,
-	0x201a, 0x7087, 0x0001, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x20e1,
-	0x0001, 0x2898, 0x20a9, 0x0008, 0x4003, 0x9085, 0x0001, 0x0008,
-	0x9006, 0x009e, 0x008e, 0x0005, 0x0156, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000,
-	0x2011, 0x024e, 0x22a0, 0x4003, 0x014e, 0x013e, 0x01de, 0x01ce,
-	0x015e, 0x2118, 0x9026, 0x2001, 0x0007, 0x939a, 0x0010, 0x0218,
-	0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff, 0x0120, 0x939a, 0x0010,
-	0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff, 0x0118, 0x8423, 0x8319,
-	0x1de8, 0x9238, 0x2029, 0x026e, 0x9528, 0x2504, 0x942c, 0x11b8,
-	0x9405, 0x203a, 0x715e, 0x91a0, 0x33b6, 0x242d, 0x95ac, 0x00ff,
-	0x7582, 0x6532, 0x6536, 0x0016, 0x2508, 0x080c, 0x28bc, 0x001e,
-	0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001, 0x9084, 0x0000, 0x0005,
-	0x00e6, 0x2071, 0x1800, 0x708b, 0x0000, 0x00ee, 0x0005, 0x00e6,
-	0x00f6, 0x2079, 0x0100, 0x2071, 0x0140, 0x080c, 0x604d, 0x080c,
-	0xa6e9, 0x7004, 0x9084, 0x4000, 0x0110, 0x080c, 0x2d49, 0x0126,
-	0x2091, 0x8000, 0x2071, 0x1826, 0x2073, 0x0000, 0x7840, 0x0026,
-	0x0016, 0x2009, 0x00f7, 0x080c, 0x60aa, 0x001e, 0x9094, 0x0010,
-	0x9285, 0x0080, 0x7842, 0x7a42, 0x002e, 0x012e, 0x00fe, 0x00ee,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x2bce, 0x0228, 0x2011,
-	0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011, 0x19f2, 0x2013, 0x0000,
-	0x7093, 0x0000, 0x012e, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c,
-	0xa6e0, 0x6144, 0xd184, 0x0120, 0x7198, 0x918d, 0x2000, 0x0018,
-	0x718c, 0x918d, 0x1000, 0x2011, 0x1999, 0x2112, 0x2009, 0x07d0,
-	0x2011, 0x5f97, 0x080c, 0x88d5, 0x0005, 0x0016, 0x0026, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x080c, 0xb244, 0x2009, 0x00f7, 0x080c,
-	0x60aa, 0x2061, 0x19fb, 0x900e, 0x611a, 0x611e, 0x617a, 0x617e,
-	0x2061, 0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090,
-	0x6043, 0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d,
-	0x2011, 0x6019, 0x080c, 0x8831, 0x012e, 0x00ce, 0x002e, 0x001e,
-	0x0005, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071,
-	0x0100, 0x080c, 0xa6e9, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000,
-	0x0110, 0x080c, 0x2d49, 0x080c, 0x763f, 0x0188, 0x080c, 0x765a,
-	0x1170, 0x080c, 0x793c, 0x0016, 0x080c, 0x298b, 0x2001, 0x196d,
-	0x2102, 0x001e, 0x080c, 0x7937, 0x080c, 0x7563, 0x0050, 0x2009,
-	0x0001, 0x080c, 0x2c67, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c,
-	0x5fed, 0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004,
-	0xd0bc, 0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1999,
-	0x201c, 0x080c, 0x4c44, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012,
-	0x20e9, 0x0001, 0x20a1, 0x1c80, 0x080c, 0x6108, 0x20e9, 0x0000,
-	0x2099, 0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x6102, 0x2099,
-	0x0260, 0x20a1, 0x1c92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x6105,
-	0x2099, 0x0260, 0x20a1, 0x1cb2, 0x0009, 0x0005, 0x0016, 0x0026,
-	0x3410, 0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04,
-	0x6082, 0x002e, 0x001e, 0x0005, 0x080c, 0xaf8e, 0x20e1, 0x0001,
-	0x2099, 0x1c00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c,
-	0x4003, 0x0005, 0x080c, 0xaf8e, 0x080c, 0x6108, 0x20e1, 0x0000,
-	0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c,
-	0x4003, 0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001,
-	0x1834, 0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084,
-	0x00ff, 0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce,
-	0x0005, 0x0016, 0x0046, 0x080c, 0x6a9f, 0x0158, 0x9006, 0x2020,
-	0x2009, 0x002a, 0x080c, 0xec31, 0x2001, 0x180c, 0x200c, 0xc195,
-	0x2102, 0x2019, 0x002a, 0x900e, 0x080c, 0x321b, 0x080c, 0xd7e3,
-	0x0140, 0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4dfb,
-	0x003e, 0x004e, 0x001e, 0x0005, 0x080c, 0x5fed, 0x709b, 0x0000,
-	0x7093, 0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c,
-	0x0100, 0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000,
-	0x2001, 0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e,
-	0x000e, 0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008,
-	0x900e, 0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6,
-	0x0156, 0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001,
-	0x20a1, 0x1c00, 0x4004, 0x2079, 0x1c00, 0x7803, 0x2200, 0x7807,
-	0x00ef, 0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827,
-	0xffff, 0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800,
-	0x2003, 0x0001, 0x0005, 0x2001, 0x19a7, 0x0118, 0x2003, 0x0001,
-	0x0010, 0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009,
-	0x1000, 0x9006, 0x200a, 0x8108, 0x1f04, 0x6142, 0x015e, 0x0005,
-	0x00d6, 0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006,
-	0xb802, 0xb8ce, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198,
-	0x33b6, 0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb8c2,
-	0x080c, 0xb23d, 0x1120, 0x9192, 0x007e, 0x1208, 0xbbc2, 0x20a9,
-	0x0004, 0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0,
-	0x4004, 0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e,
-	0x001e, 0xb83e, 0xb842, 0xb84e, 0xb852, 0xb856, 0xb85a, 0xb85e,
-	0xb862, 0xb866, 0xb86a, 0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a,
-	0xb88a, 0xb88e, 0xb893, 0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be,
-	0xb9a2, 0x0096, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1040, 0xb8a7,
-	0x0000, 0x009e, 0x9006, 0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846,
-	0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82,
-	0x1cd0, 0x0a0c, 0x0dc5, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c,
-	0x0dc5, 0x080c, 0x8cf7, 0x00ce, 0x090c, 0x9096, 0xb8af, 0x0000,
-	0x6814, 0x9084, 0x00ff, 0xb842, 0x014e, 0x013e, 0x015e, 0x003e,
-	0x00de, 0x0005, 0x0126, 0x2091, 0x8000, 0xa974, 0xae78, 0x9684,
-	0x3fff, 0x9082, 0x4000, 0x1a04, 0x6230, 0x9182, 0x0800, 0x1a04,
-	0x6234, 0x2001, 0x180c, 0x2004, 0x9084, 0x0003, 0x1904, 0x623a,
-	0x9188, 0x1000, 0x2104, 0x905d, 0x0518, 0xb804, 0x9084, 0x00ff,
-	0x908e, 0x0006, 0x1508, 0xb8a4, 0x900d, 0x1904, 0x624c, 0xb850,
-	0x900d, 0x1148, 0xa802, 0x2900, 0xb852, 0xb84e, 0x080c, 0x951c,
-	0x9006, 0x012e, 0x0005, 0x00a6, 0x2150, 0x2900, 0xb002, 0xa803,
-	0x0000, 0x00ae, 0xb852, 0x0c90, 0x2001, 0x0005, 0x900e, 0x04b8,
-	0x2001, 0x0028, 0x900e, 0x0498, 0x9082, 0x0006, 0x1290, 0x080c,
-	0xb23d, 0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc,
-	0x0990, 0x2001, 0x0029, 0x2009, 0x1000, 0x0408, 0x2001, 0x0028,
-	0x00a8, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004,
-	0x0068, 0xd184, 0x0118, 0x2001, 0x0004, 0x0040, 0x2001, 0x0029,
-	0xb900, 0xd1fc, 0x0118, 0x2009, 0x1000, 0x0048, 0x900e, 0x0038,
-	0x2001, 0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005,
-	0x012e, 0x0005, 0x2001, 0x180c, 0x2004, 0xd084, 0x19d0, 0x9188,
-	0x1000, 0x2104, 0x905d, 0x09a8, 0x080c, 0x6aa3, 0x1990, 0xb800,
-	0xd0bc, 0x0978, 0x0804, 0x61e3, 0x080c, 0x68c0, 0x0904, 0x61fc,
-	0x0804, 0x61e7, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa874,
-	0x908e, 0x00ff, 0x1120, 0x2001, 0x196b, 0x205c, 0x0060, 0xa974,
-	0x9182, 0x0800, 0x1690, 0x9188, 0x1000, 0x2104, 0x905d, 0x01d0,
-	0x080c, 0x6a43, 0x11d0, 0x080c, 0xb27d, 0x0570, 0x2b00, 0x6012,
-	0x2900, 0x6016, 0x6023, 0x0009, 0x600b, 0x0000, 0xa874, 0x908e,
-	0x00ff, 0x1110, 0x600b, 0x8000, 0x2009, 0x0043, 0x080c, 0xb352,
-	0x9006, 0x00b0, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c,
-	0xd18c, 0x0118, 0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001,
-	0x0004, 0x0010, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005,
-	0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00b6,
-	0x00e6, 0x0126, 0x2091, 0x8000, 0xa974, 0x9182, 0x0800, 0x1a04,
-	0x631d, 0x9188, 0x1000, 0x2104, 0x905d, 0x0904, 0x62f5, 0xb8a0,
-	0x9086, 0x007f, 0x0190, 0xa87c, 0xd0fc, 0x1178, 0x080c, 0x6aab,
-	0x0160, 0xa994, 0x81ff, 0x0130, 0x908e, 0x0004, 0x0130, 0x908e,
-	0x0005, 0x0118, 0x080c, 0x6aa3, 0x1598, 0xa87c, 0xd0fc, 0x01e0,
-	0xa894, 0x9005, 0x01c8, 0x2060, 0x0026, 0x2010, 0x080c, 0xd0c6,
-	0x002e, 0x1120, 0x2001, 0x0008, 0x0804, 0x631f, 0x6020, 0x9086,
-	0x000a, 0x0120, 0x2001, 0x0008, 0x0804, 0x631f, 0x601a, 0x6003,
-	0x0008, 0x2900, 0x6016, 0x0058, 0x080c, 0xb27d, 0x05e8, 0x2b00,
-	0x6012, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0x2009,
-	0x0003, 0x080c, 0xb352, 0x9006, 0x0458, 0x2001, 0x0028, 0x0438,
-	0x9082, 0x0006, 0x1290, 0x080c, 0xb23d, 0x1160, 0xb8a0, 0x9084,
-	0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900, 0x2001, 0x0029, 0x2009,
-	0x1000, 0x00a8, 0x2001, 0x0028, 0x0090, 0x2009, 0x180c, 0x210c,
-	0xd18c, 0x0118, 0x2001, 0x0004, 0x0050, 0xd184, 0x0118, 0x2001,
-	0x0004, 0x0028, 0x2001, 0x0029, 0x0010, 0x2001, 0x0029, 0x9005,
-	0x012e, 0x00ee, 0x00be, 0x0005, 0x2001, 0x002c, 0x0cc0, 0x00f6,
-	0x00b6, 0x0126, 0x2091, 0x8000, 0xa8e0, 0x9005, 0x1550, 0xa8dc,
-	0x9082, 0x0101, 0x1630, 0xa8c8, 0x9005, 0x1518, 0xa8c4, 0x9082,
-	0x0101, 0x12f8, 0xa974, 0x2079, 0x1800, 0x9182, 0x0800, 0x12e8,
-	0x7830, 0x9084, 0x0003, 0x1130, 0xaa98, 0xab94, 0xa878, 0x9084,
-	0x0007, 0x00ea, 0x7930, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038,
-	0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e,
-	0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e,
-	0x9006, 0x0008, 0x9005, 0x012e, 0x00be, 0x00fe, 0x0005, 0x63b4,
-	0x636f, 0x6386, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x63b4, 0x2100,
-	0x9082, 0x007e, 0x1278, 0x080c, 0x66b9, 0x0148, 0x9046, 0xb810,
-	0x9306, 0x1904, 0x63bc, 0xb814, 0x9206, 0x15f0, 0x0028, 0xbb12,
-	0xba16, 0x0010, 0x080c, 0x4af7, 0x0150, 0x04b0, 0x080c, 0x6724,
-	0x1598, 0xb810, 0x9306, 0x1580, 0xb814, 0x9206, 0x1568, 0x080c,
-	0xb27d, 0x0530, 0x2b00, 0x6012, 0x080c, 0xd554, 0x2900, 0x6016,
-	0x600b, 0xffff, 0x6023, 0x000a, 0xa878, 0x9086, 0x0001, 0x1170,
-	0x080c, 0x3250, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002, 0x080c,
-	0x666a, 0x2001, 0x0200, 0xb86e, 0xb893, 0x0002, 0x2009, 0x0003,
-	0x080c, 0xb352, 0x9006, 0x0068, 0x2001, 0x0001, 0x900e, 0x0038,
-	0x2001, 0x002c, 0x900e, 0x0018, 0x2001, 0x0028, 0x900e, 0x9005,
-	0x0000, 0x012e, 0x00be, 0x00fe, 0x0005, 0x00b6, 0x00f6, 0x00e6,
-	0x0126, 0x2091, 0x8000, 0xa894, 0x90c6, 0x0015, 0x0904, 0x65a7,
-	0x90c6, 0x0056, 0x0904, 0x65ab, 0x90c6, 0x0066, 0x0904, 0x65af,
-	0x90c6, 0x0067, 0x0904, 0x65b3, 0x90c6, 0x0068, 0x0904, 0x65b7,
-	0x90c6, 0x0071, 0x0904, 0x65bb, 0x90c6, 0x0074, 0x0904, 0x65bf,
-	0x90c6, 0x007c, 0x0904, 0x65c3, 0x90c6, 0x007e, 0x0904, 0x65c7,
-	0x90c6, 0x0037, 0x0904, 0x65cb, 0x9016, 0x2079, 0x1800, 0xa974,
-	0x9186, 0x00ff, 0x0904, 0x65a2, 0x9182, 0x0800, 0x1a04, 0x65a2,
-	0x080c, 0x6724, 0x1198, 0xb804, 0x9084, 0x00ff, 0x9082, 0x0006,
-	0x1268, 0xa894, 0x90c6, 0x006f, 0x0148, 0x080c, 0xb23d, 0x1904,
-	0x658b, 0xb8a0, 0x9084, 0xff80, 0x1904, 0x658b, 0xa894, 0x90c6,
-	0x006f, 0x0158, 0x90c6, 0x005e, 0x0904, 0x64eb, 0x90c6, 0x0064,
-	0x0904, 0x6514, 0x2008, 0x0804, 0x64ad, 0xa998, 0xa8b0, 0x2040,
-	0x080c, 0xb23d, 0x1120, 0x9182, 0x007f, 0x0a04, 0x64ad, 0x9186,
-	0x00ff, 0x0904, 0x64ad, 0x9182, 0x0800, 0x1a04, 0x64ad, 0xaaa0,
-	0xab9c, 0x787c, 0x9306, 0x11a8, 0x7880, 0x0096, 0x924e, 0x1128,
-	0x2208, 0x2310, 0x009e, 0x0804, 0x64ad, 0x080c, 0xb23d, 0x1140,
-	0x99cc, 0xff00, 0x009e, 0x1128, 0x2208, 0x2310, 0x0804, 0x64ad,
-	0x009e, 0x080c, 0x4af7, 0x0904, 0x64b7, 0x900e, 0x9016, 0x90c6,
-	0x4000, 0x15e0, 0x0006, 0x080c, 0x6944, 0x1108, 0xc185, 0xb800,
-	0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c,
-	0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006,
-	0x2098, 0x080c, 0x0f8b, 0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c,
-	0x9080, 0x0035, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a,
-	0x2098, 0x080c, 0x0f8b, 0xa8c4, 0xabc8, 0x9305, 0xabcc, 0x9305,
-	0xabd0, 0x9305, 0xabd4, 0x9305, 0xabd8, 0x9305, 0xabdc, 0x9305,
-	0xabe0, 0x9305, 0x9005, 0x0510, 0x000e, 0x00c8, 0x90c6, 0x4007,
-	0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008, 0x1118, 0x2708, 0x2610,
-	0x0070, 0x90c6, 0x4009, 0x1108, 0x0050, 0x90c6, 0x4006, 0x0138,
-	0x2001, 0x4005, 0x2009, 0x000a, 0x0010, 0x2001, 0x4006, 0xa896,
-	0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e, 0x0478, 0x000e, 0x080c,
-	0xb27d, 0x1130, 0x2001, 0x4005, 0x2009, 0x0003, 0x9016, 0x0c78,
-	0x2b00, 0x6012, 0x080c, 0xd554, 0x2900, 0x6016, 0x6023, 0x0001,
-	0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x3250, 0x012e, 0x9006, 0x080c, 0x6656, 0x2001, 0x0002,
-	0x080c, 0x666a, 0x2009, 0x0002, 0x080c, 0xb352, 0xa8b0, 0xd094,
-	0x0118, 0xb8cc, 0xc08d, 0xb8ce, 0x9006, 0x9005, 0x012e, 0x00ee,
-	0x00fe, 0x00be, 0x0005, 0x080c, 0x57e9, 0x0118, 0x2009, 0x0007,
-	0x00f8, 0xa998, 0xaeb0, 0x080c, 0x6724, 0x1904, 0x64a8, 0x9186,
-	0x007f, 0x0130, 0x080c, 0x6aa3, 0x0118, 0x2009, 0x0009, 0x0080,
-	0x0096, 0x080c, 0x100e, 0x1120, 0x009e, 0x2009, 0x0002, 0x0040,
-	0x2900, 0x009e, 0xa806, 0x080c, 0xd2c0, 0x19b0, 0x2009, 0x0003,
-	0x2001, 0x4005, 0x0804, 0x64af, 0xa998, 0xaeb0, 0x080c, 0x6724,
-	0x1904, 0x64a8, 0x0096, 0x080c, 0x100e, 0x1128, 0x009e, 0x2009,
-	0x0002, 0x0804, 0x6568, 0x2900, 0x009e, 0xa806, 0x0096, 0x2048,
-	0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860, 0x20e8,
-	0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008, 0x9080,
-	0x0006, 0x20a0, 0xbbc8, 0x9398, 0x0006, 0x2398, 0x080c, 0x0f8b,
-	0x009e, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xd684,
-	0x1168, 0x080c, 0x57d5, 0xd0b4, 0x1118, 0xa89b, 0x000b, 0x00e0,
-	0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c, 0x00b0, 0x080c, 0x6aa3,
-	0x0118, 0xa89b, 0x0009, 0x0080, 0x080c, 0x57e9, 0x0118, 0xa89b,
-	0x0007, 0x0050, 0x080c, 0xd2a3, 0x1904, 0x64e4, 0x2009, 0x0003,
-	0x2001, 0x4005, 0x0804, 0x64af, 0xa87b, 0x0030, 0xa897, 0x4005,
-	0xa804, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0,
-	0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4,
-	0x2031, 0x0000, 0x2041, 0x1252, 0x080c, 0xb7f1, 0x1904, 0x64e4,
-	0x2009, 0x0002, 0x08e8, 0x2001, 0x0028, 0x900e, 0x0804, 0x64e5,
-	0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038,
-	0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x900e,
-	0x0804, 0x64e5, 0x2001, 0x0029, 0x900e, 0x0804, 0x64e5, 0x080c,
-	0x37e9, 0x0804, 0x64e6, 0x080c, 0x5500, 0x0804, 0x64e6, 0x080c,
-	0x4637, 0x0804, 0x64e6, 0x080c, 0x46b0, 0x0804, 0x64e6, 0x080c,
-	0x470c, 0x0804, 0x64e6, 0x080c, 0x4bba, 0x0804, 0x64e6, 0x080c,
-	0x4e82, 0x0804, 0x64e6, 0x080c, 0x5167, 0x0804, 0x64e6, 0x080c,
-	0x5360, 0x0804, 0x64e6, 0x080c, 0x3a25, 0x0804, 0x64e6, 0x00b6,
-	0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1618, 0x9182,
-	0x0800, 0x1268, 0x9188, 0x1000, 0x2104, 0x905d, 0x0140, 0x080c,
-	0x6aa3, 0x1148, 0x00e9, 0x080c, 0x684f, 0x9006, 0x00b0, 0x2001,
-	0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900, 0xd1fc,
-	0x0d88, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001, 0x0029,
-	0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be, 0x0005,
-	0x0126, 0x2091, 0x8000, 0xb850, 0x900d, 0x0150, 0x2900, 0x0096,
-	0x2148, 0xa802, 0x009e, 0xa803, 0x0000, 0xb852, 0x012e, 0x0005,
-	0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0, 0x0126, 0x2091,
-	0x8000, 0xb84c, 0x9005, 0x0170, 0x00e6, 0x2071, 0x19e8, 0x7004,
-	0x9086, 0x0002, 0x0168, 0x00ee, 0xb84c, 0xa802, 0x2900, 0xb84e,
-	0x012e, 0x0005, 0x2900, 0xb852, 0xb84e, 0xa803, 0x0000, 0x0cc0,
-	0x701c, 0x9b06, 0x1d80, 0xb84c, 0x00a6, 0x2050, 0xb000, 0xa802,
-	0x2900, 0xb002, 0x00ae, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091,
-	0x8000, 0xb84c, 0x904d, 0x0130, 0xa800, 0x9005, 0x1108, 0xb852,
-	0xb84e, 0x9905, 0x012e, 0x0005, 0xb84c, 0x904d, 0x0130, 0xa800,
-	0x9005, 0x1108, 0xb852, 0xb84e, 0x9905, 0x0005, 0x00b6, 0x0126,
-	0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005,
-	0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e,
-	0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210,
-	0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac,
-	0x0158, 0x080c, 0x6a9f, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086,
-	0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215,
-	0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c,
-	0x0dc5, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126,
-	0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086,
-	0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6a9b, 0x1138,
-	0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e,
-	0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be,
-	0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6,
-	0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c,
-	0x100e, 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca,
-	0xb860, 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x6148, 0x9006,
-	0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096,
-	0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085,
-	0x0001, 0x04a8, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0568,
-	0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x1040, 0x00d6,
-	0x00c6, 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014,
-	0x2048, 0x080c, 0xd0d8, 0x0110, 0x080c, 0x0fc0, 0x080c, 0xb2d3,
-	0x00ce, 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, 0x0128,
-	0x621c, 0xd2c4, 0x0110, 0x080c, 0x9096, 0x00ce, 0x2b48, 0xb8c8,
-	0xb85e, 0xb8c4, 0xb862, 0x080c, 0x1050, 0x00de, 0x9006, 0x002e,
-	0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218,
-	0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0,
-	0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006,
-	0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x7637, 0x1510,
-	0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xb23d, 0x11d8, 0x0078,
-	0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1982, 0x7048, 0x2062,
-	0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c,
-	0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069,
-	0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866,
-	0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, 0xb8c8, 0x9088,
-	0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088,
-	0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817,
-	0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050,
-	0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e,
-	0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008,
-	0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182,
-	0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218,
-	0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004,
-	0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009,
-	0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016,
-	0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a,
-	0x7054, 0xb89e, 0x0036, 0xbbcc, 0xc384, 0xba00, 0x2009, 0x1867,
-	0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac,
-	0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c,
-	0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbce, 0x003e, 0x00ee,
-	0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4,
-	0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010,
-	0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007,
-	0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098,
-	0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120,
-	0x8109, 0x1dd0, 0x080c, 0x0dc5, 0x3c00, 0x20e8, 0x3300, 0x8001,
-	0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e,
-	0x0060, 0x080c, 0x100e, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000,
-	0x080c, 0x68e0, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e,
-	0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096,
-	0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x68ef,
-	0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020,
-	0x080c, 0x1040, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x951c, 0x012e, 0x0005, 0x901e, 0x0010,
-	0x2019, 0x0001, 0x900e, 0x0126, 0x2091, 0x8000, 0xb84c, 0x2048,
-	0xb800, 0xd0dc, 0x1170, 0x89ff, 0x0500, 0x83ff, 0x0120, 0xa878,
-	0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506,
-	0x0120, 0x2908, 0xa800, 0x2048, 0x0c70, 0x080c, 0xaaf1, 0xaa00,
-	0xb84c, 0x9906, 0x1110, 0xba4e, 0x0020, 0x00a6, 0x2150, 0xb202,
-	0x00ae, 0x82ff, 0x1110, 0xb952, 0x89ff, 0x012e, 0x0005, 0x9016,
-	0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c, 0x6944, 0x0128,
-	0x080c, 0xd195, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c, 0x6944,
-	0x0128, 0x080c, 0xd13a, 0x0010, 0x9085, 0x0001, 0x0005, 0x080c,
-	0x6944, 0x0128, 0x080c, 0xd192, 0x0010, 0x9085, 0x0001, 0x0005,
-	0x080c, 0x6944, 0x0128, 0x080c, 0xd159, 0x0010, 0x9085, 0x0001,
-	0x0005, 0x080c, 0x6944, 0x0128, 0x080c, 0xd1d8, 0x0010, 0x9085,
-	0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085, 0x0001, 0x0005,
-	0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f,
-	0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098,
-	0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109,
-	0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce, 0x013e, 0x0005,
-	0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0004, 0x20a0,
-	0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de, 0x014e, 0x0136,
-	0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e, 0x810f, 0x9184,
-	0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004, 0x2098, 0x20a9,
-	0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128, 0x8109, 0x1dd8,
-	0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300, 0x8001, 0x20a0,
-	0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de, 0x014e, 0x9006,
-	0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4,
-	0x904d, 0x1128, 0x080c, 0x100e, 0x0168, 0x2900, 0xb8a6, 0x080c,
-	0x68e0, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085, 0x0001, 0x012e,
-	0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126, 0x2091, 0x8000,
-	0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c, 0x1040, 0x9085,
-	0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4, 0x0005, 0x00b6,
-	0x00f6, 0x080c, 0x7637, 0x01b0, 0x71c4, 0x81ff, 0x1198, 0x71dc,
-	0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000, 0x2004, 0x905d,
-	0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1118, 0xb800,
-	0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x01d0, 0x0156,
-	0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x6724, 0x1168, 0xb804,
-	0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118, 0x9086, 0x0006,
-	0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108, 0x1f04, 0x696b,
-	0x015e, 0x080c, 0x6a61, 0x0120, 0x2001, 0x1985, 0x200c, 0x0098,
-	0x2079, 0x1847, 0x7804, 0xd0a4, 0x0190, 0x2009, 0x07d0, 0x2001,
-	0x182c, 0x2004, 0x9005, 0x0138, 0x2001, 0x1867, 0x2004, 0xd0e4,
-	0x0110, 0x2009, 0x5dc0, 0x2011, 0x69a2, 0x080c, 0x88d5, 0x00fe,
-	0x00be, 0x0005, 0x00b6, 0x2011, 0x69a2, 0x080c, 0x883d, 0x080c,
-	0x6a61, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058, 0xb900, 0xc1ec,
-	0xb902, 0x080c, 0x6a9f, 0x0130, 0x2009, 0x07d0, 0x2011, 0x69a2,
-	0x080c, 0x88d5, 0x00e6, 0x2071, 0x1800, 0x9006, 0x707e, 0x7060,
-	0x7082, 0x080c, 0x3000, 0x00ee, 0x04b0, 0x0156, 0x00c6, 0x20a9,
-	0x007f, 0x900e, 0x0016, 0x080c, 0x6724, 0x1538, 0xb800, 0xd0ec,
-	0x0520, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x0029, 0x080c,
-	0xec31, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c, 0x6a9b, 0x2001,
-	0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085, 0x0700, 0xb806,
-	0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577,
-	0x900e, 0x080c, 0xe91c, 0x007e, 0x004e, 0x001e, 0x8108, 0x1f04,
-	0x69ca, 0x00ce, 0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058,
-	0xb800, 0xc0ec, 0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096,
-	0x080c, 0x1027, 0x090c, 0x0dc5, 0x2958, 0x009e, 0x2001, 0x196b,
-	0x2b02, 0x8b07, 0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c,
-	0xffc0, 0xb9ca, 0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x6148,
-	0xb807, 0x0006, 0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200,
-	0xb86c, 0xb893, 0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af,
-	0x0000, 0x00ce, 0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800,
-	0x00be, 0xd0ac, 0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800,
-	0x00be, 0xd0bc, 0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c,
-	0x00ff, 0x9196, 0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196,
-	0x0005, 0x0158, 0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128,
-	0x9196, 0x0004, 0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e,
-	0x0005, 0x00b6, 0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110,
-	0xb800, 0xd0ec, 0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091,
-	0x8000, 0x0006, 0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c,
-	0x0dc5, 0x000e, 0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc,
-	0xba02, 0x002e, 0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc,
-	0x0138, 0x2001, 0x1983, 0x200c, 0x2011, 0x6a91, 0x080c, 0x88d5,
-	0x0005, 0x2011, 0x6a91, 0x080c, 0x883d, 0x2011, 0x1837, 0x2204,
-	0xc0cc, 0x2012, 0x0005, 0x080c, 0x57d5, 0xd0ac, 0x0005, 0x080c,
-	0x57d5, 0xd0a4, 0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e,
-	0x0006, 0x001e, 0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007,
-	0x908e, 0x0006, 0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd7e3,
-	0x0158, 0x70dc, 0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004,
-	0x905d, 0x0110, 0xb8cc, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006,
-	0x0016, 0x0036, 0x0046, 0x0076, 0x00b6, 0x2001, 0x1818, 0x203c,
-	0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018,
-	0x2008, 0x9284, 0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff,
-	0x2100, 0x9706, 0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168,
-	0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118,
-	0xb89c, 0xd0a4, 0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120,
-	0x9182, 0x0800, 0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048,
-	0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e,
-	0x0005, 0x00be, 0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e,
-	0x0005, 0x0046, 0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff,
-	0x9080, 0x1000, 0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff,
-	0x9086, 0x0006, 0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1818,
-	0x203c, 0x9780, 0x33b6, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006,
-	0x2020, 0x2400, 0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d,
-	0x0178, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c,
-	0xd0a4, 0x0130, 0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128,
-	0x8420, 0x9482, 0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be,
-	0x007e, 0x005e, 0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff,
-	0x00be, 0x007e, 0x005e, 0x004e, 0x9006, 0x0005, 0x0006, 0x2001,
-	0x00a0, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005,
-	0x0006, 0x2001, 0x00f8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8,
-	0x000e, 0x0005, 0x0006, 0x2001, 0x00e8, 0x8001, 0xa001, 0xa001,
-	0xa001, 0x1dd8, 0x000e, 0x0005, 0x2071, 0x1910, 0x7003, 0x0001,
-	0x7007, 0x0000, 0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a,
-	0x7046, 0x2001, 0x1922, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6,
-	0x2071, 0x1948, 0x900e, 0x710a, 0x080c, 0x57d5, 0xd0fc, 0x1140,
-	0x080c, 0x57d5, 0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0470,
-	0x2001, 0x1867, 0x200c, 0x9184, 0x0007, 0x0006, 0x2001, 0x180d,
-	0x2004, 0xd08c, 0x000e, 0x0108, 0x9006, 0x0002, 0x6b98, 0x6b98,
-	0x6b98, 0x6b98, 0x6b98, 0x6bb6, 0x6bcb, 0x6bd9, 0x7003, 0x0003,
-	0x2009, 0x1868, 0x210c, 0x9184, 0xff00, 0x908e, 0xff00, 0x0140,
-	0x8007, 0x9005, 0x1110, 0x2001, 0x0002, 0x8003, 0x7006, 0x0030,
-	0x7007, 0x0001, 0x0018, 0x7003, 0x0005, 0x0c50, 0x2071, 0x1910,
-	0x704f, 0x0000, 0x2071, 0x1800, 0x70f3, 0x0001, 0x00ee, 0x001e,
-	0x0005, 0x7003, 0x0000, 0x2071, 0x1910, 0x2009, 0x1868, 0x210c,
-	0x9184, 0x7f00, 0x8007, 0x908c, 0x000f, 0x0160, 0x714e, 0x8004,
-	0x8004, 0x8004, 0x8004, 0x2071, 0x1800, 0x908c, 0x0007, 0x0128,
-	0x70f2, 0x0c20, 0x704f, 0x000f, 0x0c90, 0x70f3, 0x0005, 0x08f0,
-	0x00e6, 0x2071, 0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071,
-	0x1910, 0x7028, 0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488,
-	0x6844, 0x9005, 0x0158, 0x080c, 0x79a4, 0x6a60, 0x9200, 0x7002,
-	0x6864, 0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002,
-	0x6864, 0x7006, 0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005,
-	0x1110, 0x7012, 0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040,
-	0x701e, 0x7037, 0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910,
-	0x7028, 0xc084, 0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee,
-	0x9006, 0x00ee, 0x0005, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000,
-	0x9015, 0x0904, 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286,
-	0x0005, 0x0904, 0x6d3e, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904,
-	0x6c99, 0x7140, 0xa868, 0x9102, 0x0a04, 0x6ea5, 0xa878, 0xd084,
-	0x15d8, 0xa853, 0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910,
-	0x701c, 0x9005, 0x1904, 0x7073, 0x0e04, 0x70e1, 0x2071, 0x0000,
-	0xa850, 0x7032, 0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a,
-	0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156,
-	0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0,
-	0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e,
-	0x01de, 0x014e, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084,
-	0x190c, 0x11aa, 0x0804, 0x6d21, 0xa853, 0x001b, 0x2001, 0x8027,
-	0x0820, 0x7004, 0xd08c, 0x1904, 0x6ea5, 0xa853, 0x001a, 0x2001,
-	0x8024, 0x0804, 0x6c5d, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000,
-	0x9015, 0x0904, 0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286,
-	0x0005, 0x0904, 0x6d3e, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804,
-	0x6d06, 0xa868, 0xd0fc, 0x1508, 0x00e6, 0x0026, 0x2001, 0x1948,
-	0x2004, 0x9015, 0x0904, 0x6ea5, 0xa978, 0xa874, 0x9105, 0x1904,
-	0x6ea5, 0x9286, 0x0003, 0x0904, 0x6d3e, 0x9286, 0x0005, 0x0904,
-	0x6d3e, 0xa87c, 0xd0bc, 0x1904, 0x6ea5, 0x2200, 0x0002, 0x6ea5,
-	0x6d02, 0x6d3e, 0x6d3e, 0x6ea5, 0x6d3e, 0x0005, 0xa868, 0xd0fc,
-	0x1500, 0x00e6, 0x0026, 0x2009, 0x1948, 0x210c, 0x81ff, 0x0904,
-	0x6ea5, 0xa880, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x6ea5,
-	0x9186, 0x0003, 0x0904, 0x6d3e, 0x9186, 0x0005, 0x0904, 0x6d3e,
-	0xa87c, 0xd0cc, 0x0904, 0x6ea5, 0xa84f, 0x8021, 0xa853, 0x0017,
-	0x0028, 0x0005, 0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1910,
-	0x701c, 0x9005, 0x1904, 0x7073, 0x0e04, 0x70e1, 0x2071, 0x0000,
-	0xa84c, 0x7082, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870,
-	0x708a, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c,
-	0x11aa, 0x2071, 0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c,
-	0x1158, 0xa802, 0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c,
-	0x8725, 0x002e, 0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802,
-	0x8210, 0x2900, 0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000,
-	0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010,
-	0x9005, 0x1904, 0x6e29, 0x782c, 0x908c, 0x0780, 0x190c, 0x722f,
-	0x8004, 0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x6d5c, 0x6e29,
-	0x6d80, 0x6dc6, 0x080c, 0x0dc5, 0x2071, 0x1800, 0x2900, 0x7822,
-	0xa804, 0x900d, 0x1168, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320,
-	0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005,
-	0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff,
-	0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0c18,
-	0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1578, 0x7824,
-	0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1148, 0x2009, 0x1830,
-	0x210c, 0x918a, 0x0020, 0x0218, 0x7022, 0x00ee, 0x0058, 0x00ee,
-	0x2048, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2,
-	0x080c, 0x8725, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4,
-	0x19f0, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949,
-	0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c,
-	0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e,
-	0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0808, 0x0096, 0x00e6,
-	0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e,
-	0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x722f, 0xd09c, 0x1198, 0x009e, 0x2900, 0x7822, 0xa804,
-	0x900d, 0x1550, 0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001,
-	0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x009e,
-	0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110,
-	0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1168, 0x2071,
-	0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, 0x7046,
-	0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c,
-	0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e,
-	0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x00fe, 0x002e, 0x00ee,
-	0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a,
-	0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904,
-	0x6e7d, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x1198,
-	0x701c, 0x904d, 0x0180, 0x7010, 0x8001, 0x7012, 0x1108, 0x701a,
-	0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780, 0x190c,
-	0x722f, 0xd09c, 0x0d68, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f,
-	0xd0a4, 0x01b0, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c,
-	0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725,
-	0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee,
-	0x2071, 0x19fb, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004,
-	0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x1800,
-	0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff,
-	0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x00ee,
-	0x0804, 0x6e39, 0xa868, 0xd0fc, 0x1904, 0x6ef3, 0x0096, 0xa804,
-	0xa807, 0x0000, 0x904d, 0x190c, 0x0fc0, 0x009e, 0x0020, 0xa868,
-	0xd0fc, 0x1904, 0x6ef3, 0x00e6, 0x0026, 0xa84f, 0x0000, 0x00f6,
-	0x2079, 0x0050, 0x2071, 0x1800, 0x70ec, 0x8001, 0x0558, 0x1a04,
-	0x6ef0, 0x2071, 0x1910, 0xa803, 0x0000, 0xa864, 0x9084, 0x00ff,
-	0x908e, 0x0016, 0x01a8, 0x7010, 0x9005, 0x1904, 0x6fef, 0x782c,
-	0x908c, 0x0780, 0x190c, 0x722f, 0x8004, 0x8004, 0x8004, 0x9084,
-	0x0003, 0x0002, 0x6ef4, 0x6fef, 0x6f0f, 0x6f80, 0x080c, 0x0dc5,
-	0x2009, 0x1948, 0x2104, 0x0002, 0x6ebb, 0x6ebb, 0x6ebb, 0x6d47,
-	0x6ebb, 0x6d47, 0x70ef, 0x0fa0, 0x71e8, 0x8107, 0x9106, 0x9094,
-	0x00c0, 0x9184, 0xff3f, 0x9205, 0x70ea, 0x3b08, 0x3a00, 0x9104,
-	0x918d, 0x00c0, 0x21d8, 0x9084, 0xff3f, 0x9205, 0x20d0, 0x0808,
-	0x70ee, 0x0804, 0x6eb1, 0x0005, 0x2071, 0x1800, 0x2900, 0x7822,
-	0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016,
-	0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8,
-	0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0c60, 0x2071,
-	0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904, 0x6f6f, 0x7830,
-	0x8007, 0x908c, 0x001f, 0x70f0, 0x9102, 0x1220, 0x00fe, 0x002e,
-	0x00ee, 0x0005, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c,
-	0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022,
-	0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e,
-	0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x722f, 0xd0a4, 0x19f0, 0x0e04, 0x6f66, 0x7838, 0x7938,
-	0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013,
-	0x00de, 0x2001, 0x1921, 0x200c, 0xc184, 0x2102, 0x2091, 0x4080,
-	0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2001, 0x1922,
-	0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2001, 0x1921,
-	0x200c, 0xc185, 0x2102, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016,
-	0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8,
-	0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725, 0x0804, 0x6f22,
-	0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800, 0x702c, 0xa802,
-	0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c,
-	0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60, 0x00ee, 0x0e04,
-	0x6fc2, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000,
-	0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084, 0x7046, 0x2091,
-	0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x704b,
-	0x0000, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x1170,
-	0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x11e0, 0x00fe, 0x002e,
-	0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x0c58, 0x009e, 0x2908,
-	0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902,
-	0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e,
-	0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904,
-	0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200,
-	0x70c2, 0x080c, 0x8725, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908,
-	0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902,
-	0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1904, 0x705e, 0x782c,
-	0x9094, 0x0780, 0x190c, 0x722f, 0xd09c, 0x11b0, 0x701c, 0x904d,
-	0x0198, 0xa84c, 0x9005, 0x1180, 0x7010, 0x8001, 0x7012, 0x1108,
-	0x701a, 0xa800, 0x701e, 0x2900, 0x7822, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x722f, 0xd09c, 0x0d50, 0x782c, 0x9094, 0x0780, 0x190c,
-	0x722f, 0xd0a4, 0x05b8, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800,
-	0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c,
-	0x8725, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d60,
-	0x00ee, 0x0e04, 0x7057, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6,
-	0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044, 0xc084,
-	0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c,
-	0x11aa, 0x704b, 0x0000, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044,
-	0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x00e6, 0x2071,
-	0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900,
-	0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725,
-	0x00ee, 0x0804, 0x6fff, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908,
-	0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902,
-	0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1128, 0x1e04, 0x709e,
-	0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148,
-	0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0,
-	0x9200, 0x70c2, 0x080c, 0x8725, 0x0e04, 0x7088, 0x2071, 0x1910,
-	0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18, 0x2071, 0x0000, 0x7182,
-	0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850,
-	0x9082, 0x0019, 0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004,
-	0xd084, 0x190c, 0x11aa, 0x2071, 0x1910, 0x080c, 0x721b, 0x002e,
-	0x00ee, 0x0005, 0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e,
-	0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000,
-	0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080,
-	0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e,
-	0x0890, 0x2071, 0x1910, 0xa803, 0x0000, 0x2908, 0x7010, 0x8000,
-	0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e,
-	0x2148, 0xa804, 0x900d, 0x1118, 0x002e, 0x00ee, 0x0005, 0x2071,
-	0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900,
-	0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8725,
-	0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c, 0x0006, 0xa867, 0x0103,
-	0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001d, 0x20a0,
-	0x9006, 0x4004, 0x000e, 0x9084, 0x00ff, 0xa87e, 0x000e, 0xa87a,
-	0xa982, 0x0005, 0x2071, 0x1910, 0x7004, 0x0002, 0x712e, 0x712f,
-	0x721a, 0x712f, 0x712c, 0x721a, 0x080c, 0x0dc5, 0x0005, 0x2001,
-	0x1948, 0x2004, 0x0002, 0x7139, 0x7139, 0x71b3, 0x71b4, 0x7139,
-	0x71b4, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x723a, 0x701c, 0x904d,
-	0x0508, 0xa84c, 0x9005, 0x0904, 0x7184, 0x0e04, 0x7162, 0xa94c,
-	0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036,
-	0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080,
-	0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x2071, 0x1910,
-	0x080c, 0x721b, 0x012e, 0x0804, 0x71b2, 0xa850, 0x9082, 0x001c,
-	0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6,
-	0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860,
-	0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce,
-	0x013e, 0x01de, 0x014e, 0x0890, 0x2001, 0x005b, 0x2004, 0x9094,
-	0x0780, 0x190c, 0x722f, 0xd09c, 0x2071, 0x1910, 0x1510, 0x2071,
-	0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086, 0x0003,
-	0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e, 0x2900,
-	0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x2071, 0x1910, 0x701c,
-	0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108,
-	0x701a, 0x012e, 0x0005, 0x0005, 0x00d6, 0x2008, 0x2069, 0x19fb,
-	0x6844, 0x9005, 0x0760, 0x0158, 0x9186, 0x0003, 0x0540, 0x2001,
-	0x1815, 0x2004, 0x2009, 0x1ad1, 0x210c, 0x9102, 0x1500, 0x0126,
-	0x2091, 0x8000, 0x2069, 0x0050, 0x693c, 0x6838, 0x9106, 0x0190,
-	0x0e04, 0x71e6, 0x2069, 0x0000, 0x6837, 0x8040, 0x6833, 0x0012,
-	0x6883, 0x8040, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084,
-	0x190c, 0x11aa, 0x2069, 0x19fb, 0x6847, 0xffff, 0x012e, 0x00de,
-	0x0126, 0x2091, 0x8000, 0x1e0c, 0x72a5, 0x701c, 0x904d, 0x0540,
-	0x2001, 0x005b, 0x2004, 0x9094, 0x0780, 0x15c9, 0xd09c, 0x1500,
-	0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184, 0x00ff, 0x9086,
-	0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101, 0x0108, 0x710e,
-	0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de, 0x701c, 0x2048,
-	0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108, 0x701a,
-	0x012e, 0x0005, 0x0005, 0x0126, 0x2091, 0x8000, 0x701c, 0x904d,
-	0x0160, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e, 0x9005, 0x1108,
-	0x701a, 0x012e, 0x080c, 0x1040, 0x0005, 0x012e, 0x0005, 0x2091,
-	0x8000, 0x0e04, 0x7231, 0x0006, 0x0016, 0x2001, 0x8004, 0x0006,
-	0x0804, 0x0dce, 0x0096, 0x00f6, 0x2079, 0x0050, 0x7044, 0xd084,
-	0x01d0, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6,
-	0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091, 0x4080,
-	0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x704b, 0x0000,
-	0x00fe, 0x009e, 0x0005, 0x782c, 0x9094, 0x0780, 0x1981, 0xd0a4,
-	0x0db8, 0x7148, 0x704c, 0x8108, 0x714a, 0x9102, 0x0e88, 0x00e6,
-	0x2071, 0x1800, 0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c,
-	0x1148, 0x2009, 0x1830, 0x210c, 0x918a, 0x0020, 0x0218, 0x7022,
-	0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e,
-	0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x722f, 0xd0a4, 0x19f0, 0x7838, 0x7938, 0x910e, 0x1de0,
-	0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091,
-	0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa, 0x00ee,
-	0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050,
-	0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e,
-	0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de,
-	0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x11aa,
-	0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4,
-	0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802,
-	0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8725, 0x782c,
-	0x9094, 0x0780, 0x190c, 0x722f, 0xd0a4, 0x1d70, 0x00d6, 0x2069,
-	0x0050, 0x693c, 0x2069, 0x1948, 0x6808, 0x690a, 0x2069, 0x19fb,
-	0x9102, 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, 0x1949, 0x200c,
-	0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x002a,
-	0x1a0c, 0x0dc5, 0x9082, 0x001d, 0x001b, 0x6027, 0x1e00, 0x0005,
-	0x73e6, 0x7353, 0x736f, 0x7399, 0x73d5, 0x7415, 0x7427, 0x736f,
-	0x73fd, 0x730e, 0x733c, 0x73bf, 0x730d, 0x0005, 0x00d6, 0x2069,
-	0x0200, 0x6804, 0x9005, 0x1180, 0x6808, 0x9005, 0x1518, 0x709b,
-	0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x080c, 0x7774, 0x6028,
-	0x9085, 0x0600, 0x602a, 0x00b0, 0x709b, 0x0029, 0x2069, 0x198f,
-	0x2d04, 0x7002, 0x6028, 0x9085, 0x0600, 0x602a, 0x00e6, 0x0036,
-	0x0046, 0x0056, 0x2071, 0x1a65, 0x080c, 0x1ad9, 0x005e, 0x004e,
-	0x003e, 0x00ee, 0x00de, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804,
-	0x9005, 0x1178, 0x6808, 0x9005, 0x1160, 0x709b, 0x0029, 0x2069,
-	0x198f, 0x2d04, 0x7002, 0x080c, 0x7818, 0x6028, 0x9085, 0x0600,
-	0x602a, 0x00de, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2d39,
-	0x000e, 0x6124, 0xd1e4, 0x1190, 0x080c, 0x7494, 0xd1d4, 0x1160,
-	0xd1dc, 0x1138, 0xd1cc, 0x0150, 0x709b, 0x0020, 0x080c, 0x7494,
-	0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001,
-	0x0088, 0x080c, 0x2d39, 0x6124, 0xd1cc, 0x11e8, 0xd1dc, 0x11c0,
-	0xd1e4, 0x1198, 0x9184, 0x1e00, 0x11d8, 0x080c, 0x1b06, 0x60e3,
-	0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x7663, 0x2001, 0x0080,
-	0x080c, 0x2d39, 0x709b, 0x0029, 0x0058, 0x709b, 0x001e, 0x0040,
-	0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b, 0x001f,
-	0x0005, 0x080c, 0x1b06, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e,
-	0x080c, 0x7663, 0x2001, 0x0080, 0x080c, 0x2d39, 0x6124, 0xd1d4,
-	0x1198, 0xd1dc, 0x1170, 0xd1e4, 0x1148, 0x9184, 0x1e00, 0x1118,
-	0x709b, 0x0029, 0x0058, 0x709b, 0x0028, 0x0040, 0x709b, 0x001e,
-	0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x6124,
-	0xd1d4, 0x1180, 0xd1dc, 0x1158, 0xd1e4, 0x1130, 0x9184, 0x1e00,
-	0x1158, 0x709b, 0x0029, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b,
-	0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x2001, 0x00a0, 0x080c,
-	0x2d39, 0x6124, 0xd1dc, 0x1138, 0xd1e4, 0x0138, 0x080c, 0x1b06,
-	0x709b, 0x001e, 0x0010, 0x709b, 0x001d, 0x0005, 0x080c, 0x7517,
-	0x6124, 0xd1dc, 0x1188, 0x080c, 0x7494, 0x0016, 0x080c, 0x1b06,
-	0x001e, 0xd1d4, 0x1128, 0xd1e4, 0x0138, 0x709b, 0x001e, 0x0020,
-	0x709b, 0x001f, 0x080c, 0x7494, 0x0005, 0x0006, 0x2001, 0x00a0,
-	0x080c, 0x2d39, 0x000e, 0x6124, 0xd1d4, 0x1160, 0xd1cc, 0x1150,
-	0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b,
-	0x001d, 0x0010, 0x709b, 0x0021, 0x0005, 0x080c, 0x7517, 0x6124,
-	0xd1d4, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140, 0x709b, 0x001e,
-	0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f, 0x0005, 0x0006,
-	0x2001, 0x0090, 0x080c, 0x2d39, 0x000e, 0x6124, 0xd1d4, 0x1178,
-	0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0158, 0x709b, 0x001e,
-	0x0040, 0x709b, 0x001d, 0x0028, 0x709b, 0x0020, 0x0010, 0x709b,
-	0x001f, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x00e6, 0x0126, 0x2061,
-	0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2091, 0x8000, 0x080c,
-	0x7637, 0x11d8, 0x2001, 0x180c, 0x200c, 0xd1b4, 0x01b0, 0xc1b4,
-	0x2102, 0x6027, 0x0200, 0x080c, 0x2c61, 0x6024, 0xd0cc, 0x0148,
-	0x2001, 0x00a0, 0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e,
-	0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x7651, 0x0150,
-	0x080c, 0x7648, 0x1138, 0x2001, 0x0001, 0x080c, 0x281c, 0x080c,
-	0x760f, 0x00a0, 0x080c, 0x7514, 0x0178, 0x2001, 0x0001, 0x080c,
-	0x281c, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022,
-	0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee,
-	0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x74a5, 0x080c,
-	0x8917, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x74a5,
-	0x080c, 0x890e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016,
-	0x080c, 0xa6e9, 0x2071, 0x1800, 0x080c, 0x7442, 0x001e, 0x00fe,
-	0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6,
-	0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, 0xa6e9, 0x2061, 0x0100,
-	0x2069, 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x2011,
-	0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c,
-	0xa9d3, 0x080c, 0x88c3, 0x0036, 0x901e, 0x080c, 0xaa49, 0x003e,
-	0x60e3, 0x0000, 0x080c, 0xf07f, 0x080c, 0xf09a, 0x2009, 0x0004,
-	0x080c, 0x2c67, 0x080c, 0x2b82, 0x2001, 0x1800, 0x2003, 0x0004,
-	0x6027, 0x0008, 0x2011, 0x74a5, 0x080c, 0x8917, 0x080c, 0x7651,
-	0x0118, 0x9006, 0x080c, 0x2d39, 0x080c, 0x0ba0, 0x2001, 0x0001,
-	0x080c, 0x281c, 0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e,
-	0x002e, 0x001e, 0x0005, 0x0026, 0x00e6, 0x2011, 0x74b2, 0x2071,
-	0x19fb, 0x701c, 0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085,
-	0x0001, 0x00ee, 0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800,
-	0x9084, 0xfffe, 0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c,
-	0x2d39, 0x0156, 0x20a9, 0x002d, 0x1d04, 0x7524, 0x2091, 0x6000,
-	0x1f04, 0x7524, 0x015e, 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001,
-	0x0220, 0x0118, 0x689e, 0x00de, 0x0005, 0x689f, 0x0014, 0x68e8,
-	0xd0dc, 0x0dc8, 0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x8923,
-	0x0c90, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140,
-	0x2071, 0x1800, 0x080c, 0x7941, 0x2001, 0x196d, 0x2003, 0x0000,
-	0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28e7, 0x9006, 0x080c,
-	0x2d39, 0x080c, 0x5fed, 0x6027, 0xffff, 0x602b, 0x182f, 0x00ee,
-	0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100,
-	0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197d, 0x200c, 0x9186,
-	0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186, 0x0002, 0x0158,
-	0x9186, 0x0003, 0x0158, 0x0804, 0x75ff, 0x709b, 0x0022, 0x0040,
-	0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010, 0x709b, 0x0024,
-	0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28e7,
-	0x0026, 0x080c, 0xb244, 0x002e, 0x7000, 0x908e, 0x0004, 0x0118,
-	0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091,
-	0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e,
-	0x080c, 0xd7e3, 0x0118, 0x9006, 0x080c, 0x2d63, 0x0804, 0x760b,
-	0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2c61, 0x6904,
-	0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2d39, 0x1f04, 0x75a3,
-	0x080c, 0x768b, 0x012e, 0x015e, 0x080c, 0x7648, 0x01d8, 0x6044,
-	0x9005, 0x0198, 0x2011, 0x0114, 0x2204, 0x9085, 0x0100, 0x2012,
-	0x6050, 0x0006, 0x9085, 0x0020, 0x6052, 0x080c, 0x768b, 0x9006,
-	0x8001, 0x1df0, 0x000e, 0x6052, 0x0028, 0x6804, 0xd0d4, 0x1110,
-	0x080c, 0x768b, 0x080c, 0xd7e3, 0x0118, 0x9006, 0x080c, 0x2d63,
-	0x0016, 0x0026, 0x7000, 0x908e, 0x0004, 0x0130, 0x2009, 0x00c8,
-	0x2011, 0x74b2, 0x080c, 0x88d5, 0x002e, 0x001e, 0x080c, 0x871c,
-	0x7034, 0xc085, 0x7036, 0x2001, 0x197d, 0x2003, 0x0004, 0x080c,
-	0x72f5, 0x080c, 0x7648, 0x0138, 0x6804, 0xd0d4, 0x1120, 0xd0dc,
-	0x1100, 0x080c, 0x7937, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6,
-	0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800,
-	0x080c, 0x8733, 0x080c, 0x8725, 0x080c, 0x7941, 0x2001, 0x196d,
-	0x2003, 0x0000, 0x9006, 0x709a, 0x60e2, 0x6886, 0x080c, 0x28e7,
-	0x9006, 0x080c, 0x2d39, 0x6043, 0x0090, 0x6043, 0x0010, 0x6027,
-	0xffff, 0x602b, 0x182f, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006,
-	0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006,
-	0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005,
-	0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e,
-	0x0005, 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086, 0x0010,
-	0x000e, 0x0005, 0x0006, 0x080c, 0x57d9, 0x9084, 0x0030, 0x9086,
-	0x0020, 0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004,
-	0x908c, 0x0013, 0x0168, 0x0020, 0x080c, 0x2907, 0x900e, 0x0010,
-	0x2009, 0x0002, 0x2019, 0x0028, 0x080c, 0x321b, 0x9006, 0x0019,
-	0x001e, 0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130,
-	0x080c, 0xd7dc, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef,
-	0x2072, 0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c,
-	0x0006, 0x6004, 0x0006, 0x6028, 0x0006, 0x0016, 0x6138, 0x6050,
-	0x9084, 0xfbff, 0x9085, 0x2000, 0x6052, 0x613a, 0x20a9, 0x0012,
-	0x1d04, 0x76a0, 0x2091, 0x6000, 0x1f04, 0x76a0, 0x602f, 0x0100,
-	0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfff, 0x6052,
-	0x613a, 0x001e, 0x602f, 0x0040, 0x602f, 0x0000, 0x000e, 0x602a,
-	0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x60e3, 0x0000,
-	0x6887, 0x0001, 0x2001, 0x0001, 0x080c, 0x28e7, 0x2001, 0x00a0,
-	0x0006, 0x080c, 0xd7e3, 0x000e, 0x0130, 0x080c, 0x2d57, 0x9006,
-	0x080c, 0x2d63, 0x0010, 0x080c, 0x2d39, 0x000e, 0x6052, 0x6050,
-	0x0006, 0xc0e5, 0x6052, 0x00f6, 0x2079, 0x0100, 0x080c, 0x2bd6,
-	0x00fe, 0x000e, 0x6052, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036,
-	0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071,
-	0x1800, 0x6020, 0x9084, 0x0080, 0x0138, 0x2001, 0x180c, 0x200c,
-	0xc1c5, 0x2102, 0x0804, 0x7766, 0x2001, 0x180c, 0x200c, 0xc1c4,
-	0x2102, 0x6028, 0x9084, 0xe1ff, 0x602a, 0x6027, 0x0200, 0x2001,
-	0x0090, 0x080c, 0x2d39, 0x20a9, 0x0366, 0x6024, 0xd0cc, 0x1518,
-	0x1d04, 0x770d, 0x2091, 0x6000, 0x1f04, 0x770d, 0x2011, 0x0003,
-	0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, 0xa9d3,
-	0x901e, 0x080c, 0xaa49, 0x2001, 0x00a0, 0x080c, 0x2d39, 0x080c,
-	0x7932, 0x080c, 0x612e, 0x080c, 0xd7e3, 0x0110, 0x080c, 0x0d33,
-	0x9085, 0x0001, 0x04c8, 0x080c, 0x1b06, 0x60e3, 0x0000, 0x2001,
-	0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001, 0x196d,
-	0x2004, 0x080c, 0x28e7, 0x60e2, 0x2001, 0x0080, 0x080c, 0x2d39,
-	0x20a9, 0x0366, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61,
-	0x6024, 0x910c, 0x0140, 0x1d04, 0x774a, 0x2091, 0x6000, 0x1f04,
-	0x774a, 0x0804, 0x7716, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4,
-	0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd7e3,
-	0x0110, 0x080c, 0x0d33, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e,
-	0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036,
-	0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000,
-	0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540,
-	0x9086, 0x5540, 0x1128, 0x2069, 0x1a7c, 0x2d04, 0x8000, 0x206a,
-	0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005,
-	0x1904, 0x77d9, 0x2001, 0x0088, 0x080c, 0x2d39, 0x9006, 0x60e2,
-	0x6886, 0x080c, 0x28e7, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118,
-	0x6808, 0x9005, 0x01c0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x6027,
-	0x0400, 0x2069, 0x198f, 0x7000, 0x206a, 0x709b, 0x0026, 0x7003,
-	0x0001, 0x20a9, 0x0002, 0x1d04, 0x77bb, 0x2091, 0x6000, 0x1f04,
-	0x77bb, 0x0804, 0x7810, 0x2069, 0x0140, 0x20a9, 0x0384, 0x6027,
-	0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, 0x6024, 0x910c, 0x0508,
-	0x9084, 0x1a00, 0x11f0, 0x1d04, 0x77c7, 0x2091, 0x6000, 0x1f04,
-	0x77c7, 0x2011, 0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c,
-	0xaac9, 0x080c, 0xa9d3, 0x901e, 0x080c, 0xaa49, 0x2001, 0x00a0,
-	0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, 0x9085, 0x0001,
-	0x00f8, 0x080c, 0x1b06, 0x2001, 0x0080, 0x080c, 0x2d39, 0x2069,
-	0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001,
-	0x0008, 0x6886, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002,
-	0x1118, 0x2001, 0x196d, 0x2004, 0x080c, 0x28e7, 0x60e2, 0x9006,
-	0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005,
-	0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061,
-	0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01c8, 0x2011,
-	0x0003, 0x080c, 0xaabf, 0x2011, 0x0002, 0x080c, 0xaac9, 0x080c,
-	0xa9d3, 0x901e, 0x080c, 0xaa49, 0x2069, 0x0140, 0x2001, 0x00a0,
-	0x080c, 0x2d39, 0x080c, 0x7932, 0x080c, 0x612e, 0x0804, 0x78b2,
-	0x2001, 0x180c, 0x200c, 0xd1b4, 0x1160, 0xc1b5, 0x2102, 0x080c,
-	0x749a, 0x2069, 0x0140, 0x2001, 0x0080, 0x080c, 0x2d39, 0x60e3,
-	0x0000, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118, 0x6808, 0x9005,
-	0x0180, 0x6028, 0x9084, 0xfdff, 0x602a, 0x6027, 0x0200, 0x2069,
-	0x198f, 0x7000, 0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804,
-	0x78b2, 0x6027, 0x1e00, 0x2009, 0x1e00, 0x080c, 0x2c61, 0x6024,
-	0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x7869, 0x0006,
-	0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x8776, 0x00ee, 0x00de,
-	0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x19fb, 0x7078, 0x00ee,
-	0x9005, 0x19f8, 0x0438, 0x0026, 0x2011, 0x74b2, 0x080c, 0x883d,
-	0x2011, 0x74a5, 0x080c, 0x8917, 0x002e, 0x2069, 0x0140, 0x60e3,
-	0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001,
-	0x196d, 0x2004, 0x080c, 0x28e7, 0x60e2, 0x2001, 0x180c, 0x200c,
-	0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6,
-	0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xd7dc, 0x1904,
-	0x7920, 0x7130, 0xd184, 0x1170, 0x080c, 0x33aa, 0x0138, 0xc18d,
-	0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c,
-	0x0904, 0x7920, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016,
-	0x2019, 0x000e, 0x080c, 0xeba1, 0x0156, 0x00b6, 0x20a9, 0x007f,
-	0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c,
-	0x6724, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c,
-	0xec31, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8a50, 0x001e,
-	0x8108, 0x1f04, 0x78e9, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148,
-	0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x321b, 0x001e,
-	0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x6724,
-	0x1110, 0x080c, 0x6148, 0x8108, 0x1f04, 0x7916, 0x00be, 0x015e,
-	0x080c, 0x1b06, 0x080c, 0xb244, 0x60e3, 0x0000, 0x080c, 0x612e,
-	0x080c, 0x7563, 0x00ee, 0x00ce, 0x004e, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x0005, 0x2001, 0x197d, 0x2003, 0x0001, 0x0005, 0x2001,
-	0x197d, 0x2003, 0x0000, 0x0005, 0x2001, 0x197c, 0x2003, 0xaaaa,
-	0x0005, 0x2001, 0x197c, 0x2003, 0x0000, 0x0005, 0x2071, 0x18fa,
-	0x7003, 0x0000, 0x7007, 0x0000, 0x080c, 0x1027, 0x090c, 0x0dc5,
-	0xa8ab, 0xdcb0, 0x2900, 0x704e, 0x080c, 0x1027, 0x090c, 0x0dc5,
-	0xa8ab, 0xdcb0, 0x2900, 0x7052, 0xa867, 0x0000, 0xa86b, 0x0001,
-	0xa89f, 0x0000, 0x0005, 0x00e6, 0x2071, 0x0040, 0x6848, 0x9005,
-	0x1118, 0x9085, 0x0001, 0x04b0, 0x6840, 0x9005, 0x0150, 0x04a1,
-	0x6a50, 0x9200, 0x7002, 0x6854, 0x9101, 0x7006, 0x9006, 0x7012,
-	0x7016, 0x6850, 0x7002, 0x6854, 0x7006, 0x6858, 0x700a, 0x685c,
-	0x700e, 0x6840, 0x9005, 0x1110, 0x7012, 0x7016, 0x6848, 0x701a,
-	0x701c, 0x9085, 0x0040, 0x701e, 0x2001, 0x0019, 0x7036, 0x702b,
-	0x0001, 0x2001, 0x0004, 0x200c, 0x918c, 0xfff7, 0x918d, 0x8000,
-	0x2102, 0x00d6, 0x2069, 0x18fa, 0x6807, 0x0001, 0x00de, 0x080c,
-	0x7f74, 0x9006, 0x00ee, 0x0005, 0x900e, 0x0156, 0x20a9, 0x0006,
-	0x8003, 0x2011, 0x0100, 0x2214, 0x9296, 0x0008, 0x1110, 0x818d,
-	0x0010, 0x81f5, 0x3e08, 0x1f04, 0x79a8, 0x015e, 0x0005, 0x2079,
-	0x0040, 0x2071, 0x18fa, 0x7004, 0x0002, 0x79c7, 0x79c8, 0x7a00,
-	0x7a5b, 0x7bbb, 0x79c5, 0x79c5, 0x7be5, 0x080c, 0x0dc5, 0x0005,
-	0x2079, 0x0040, 0x782c, 0x908c, 0x0780, 0x190c, 0x8056, 0xd0a4,
-	0x01f8, 0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084,
-	0x00ff, 0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c,
-	0x9186, 0x0003, 0x1168, 0x7004, 0x0002, 0x79f0, 0x79ca, 0x79f0,
-	0x79ee, 0x79f0, 0x79f0, 0x79f0, 0x79f0, 0x79f0, 0x080c, 0x7a5b,
-	0x782c, 0xd09c, 0x090c, 0x7f74, 0x0005, 0x9082, 0x005a, 0x1218,
-	0x2100, 0x003b, 0x0c10, 0x080c, 0x7a91, 0x0c90, 0x00e3, 0x08e8,
-	0x0005, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91,
-	0x7a91, 0x7ab3, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91,
-	0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91,
-	0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a9d, 0x7a91, 0x7cdb,
-	0x7a91, 0x7a91, 0x7a91, 0x7ab3, 0x7a91, 0x7a9d, 0x7d1c, 0x7d5d,
-	0x7da4, 0x7db8, 0x7a91, 0x7a91, 0x7ab3, 0x7a9d, 0x7ac7, 0x7a91,
-	0x7b8f, 0x7e63, 0x7e7e, 0x7a91, 0x7ab3, 0x7a91, 0x7ac7, 0x7a91,
-	0x7a91, 0x7b85, 0x7e7e, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91,
-	0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7adb, 0x7a91, 0x7a91, 0x7a91,
-	0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7a91, 0x7ffa, 0x7a91,
-	0x7fa4, 0x7a91, 0x7fa4, 0x7a91, 0x7af0, 0x7a91, 0x7a91, 0x7a91,
-	0x7a91, 0x7a91, 0x7a91, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003,
-	0x1198, 0x782c, 0x080c, 0x7f9d, 0xd0a4, 0x0170, 0x7824, 0x2048,
-	0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a,
-	0x1210, 0x002b, 0x0c50, 0x00e9, 0x080c, 0x7f74, 0x0005, 0x7a91,
-	0x7a9d, 0x7cc7, 0x7a91, 0x7a9d, 0x7a91, 0x7a9d, 0x7a9d, 0x7a91,
-	0x7a9d, 0x7cc7, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a9d, 0x7a91,
-	0x7a9d, 0x7cc7, 0x7a91, 0x7a91, 0x7a9d, 0x7a91, 0x7a91, 0x7a91,
-	0x7a9d, 0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee,
-	0x0005, 0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029,
-	0x0005, 0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868,
-	0x9084, 0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x6e9f, 0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08,
-	0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7c64, 0x7007, 0x0003,
-	0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7c64, 0x0005, 0xa864,
-	0x8007, 0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001,
-	0x0804, 0x7c7f, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a,
-	0x704b, 0x7c7f, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904,
-	0x7a99, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7c9b, 0x7007,
-	0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7c9b, 0x0005,
-	0xa864, 0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7a99,
-	0x7007, 0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1904, 0x7b5c,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x0904, 0x7b47, 0xa99c, 0x9186,
-	0x00ff, 0x05e8, 0xa994, 0x9186, 0x006f, 0x0188, 0x9186, 0x0074,
-	0x15b0, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, 0x0578,
-	0x0016, 0xa998, 0x080c, 0x6b11, 0x001e, 0x1548, 0x0400, 0x080c,
-	0x7637, 0x0140, 0xa897, 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030,
-	0x900e, 0x0438, 0x0026, 0x2011, 0x8008, 0x080c, 0x6ac7, 0x002e,
-	0x01b0, 0x0016, 0x0026, 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d,
-	0x8000, 0x080c, 0x6b11, 0x003e, 0x002e, 0x001e, 0x1140, 0xa897,
-	0x4005, 0xa89b, 0x4009, 0x2001, 0x0030, 0x900e, 0x0050, 0xa868,
-	0x9084, 0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x63c5, 0x1108,
-	0x0005, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982,
-	0x080c, 0x6e9f, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904,
-	0x7b00, 0x9186, 0x0064, 0x0904, 0x7b00, 0x9186, 0x007c, 0x0904,
-	0x7b00, 0x9186, 0x0028, 0x0904, 0x7b00, 0x9186, 0x0038, 0x0904,
-	0x7b00, 0x9186, 0x0078, 0x0904, 0x7b00, 0x9186, 0x005f, 0x0904,
-	0x7b00, 0x9186, 0x0056, 0x0904, 0x7b00, 0xa897, 0x4005, 0xa89b,
-	0x0001, 0x2001, 0x0030, 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0,
-	0x9086, 0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x7e95, 0x2900,
-	0x7016, 0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080,
-	0x0030, 0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080,
-	0x0023, 0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04,
-	0x7aa1, 0xaab4, 0x928a, 0x0002, 0x1a04, 0x7aa1, 0x82ff, 0x1138,
-	0xa8b8, 0xa9bc, 0x9105, 0x0118, 0x2001, 0x7c22, 0x0018, 0x9280,
-	0x7c18, 0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7c03, 0x080c,
-	0x1027, 0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054,
-	0x2060, 0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100,
-	0xa076, 0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200,
-	0x7112, 0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108,
-	0xa17a, 0x810b, 0xa17e, 0x080c, 0x10f8, 0xa06c, 0x908e, 0x0100,
-	0x0170, 0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020,
-	0x2048, 0x080c, 0x1040, 0x7014, 0x2048, 0x0804, 0x7aa1, 0x7020,
-	0x2048, 0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906,
-	0x711a, 0x0804, 0x7bbb, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4,
-	0x9005, 0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864,
-	0x9084, 0x00ff, 0x9086, 0x001e, 0x0904, 0x7e95, 0x0804, 0x7c64,
-	0x7c1a, 0x7c1e, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b,
-	0x0005, 0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066,
-	0xafb8, 0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de,
-	0xb0b8, 0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca,
-	0xb0ac, 0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be,
-	0xb0a0, 0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e,
-	0xb6aa, 0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a,
-	0xb084, 0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e,
-	0xb078, 0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055,
-	0x1958, 0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff,
-	0x1178, 0x080c, 0x61c2, 0x1108, 0x0005, 0x080c, 0x710b, 0x0126,
-	0x2091, 0x8000, 0x080c, 0xd3ce, 0x080c, 0x6e9f, 0x012e, 0x0ca0,
-	0x080c, 0xd7dc, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009,
-	0x1834, 0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883,
-	0x0000, 0x080c, 0x6252, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x6e9f, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8,
-	0x2001, 0x0000, 0x0c90, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0,
-	0xa883, 0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x6327, 0x1138,
-	0x0005, 0x9006, 0xa87a, 0x080c, 0x629f, 0x1108, 0x0005, 0x0126,
-	0x2091, 0x8000, 0xa87a, 0xa982, 0x080c, 0x6e9f, 0x012e, 0x0cb0,
-	0x2001, 0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x00c6,
-	0x2061, 0x1800, 0x60d0, 0x9005, 0x0100, 0x00ce, 0x0005, 0x7018,
-	0xa802, 0x2908, 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012,
-	0x0118, 0x7007, 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001,
-	0x7048, 0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878,
-	0x9084, 0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096,
-	0x0001, 0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160,
-	0x9005, 0x11d8, 0xa974, 0x080c, 0x6724, 0x11b8, 0x0066, 0xae80,
-	0x080c, 0x6834, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224,
-	0xc484, 0x2412, 0x004e, 0x00c6, 0x080c, 0x6724, 0x1110, 0x080c,
-	0x6934, 0x8108, 0x1f04, 0x7d04, 0x00ce, 0xa87c, 0xd084, 0x1120,
-	0x080c, 0x1040, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x6e9f, 0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007,
-	0x0001, 0x080c, 0x6a9f, 0x0580, 0x2061, 0x1a74, 0x6100, 0xd184,
-	0x0178, 0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520,
-	0x6004, 0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8,
-	0x2011, 0x0001, 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000,
-	0x6016, 0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007,
-	0x9084, 0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d,
-	0x6202, 0x012e, 0x0804, 0x7f5e, 0x012e, 0x0804, 0x7f58, 0x012e,
-	0x0804, 0x7f52, 0x012e, 0x0804, 0x7f55, 0x0126, 0x2091, 0x8000,
-	0x7007, 0x0001, 0x080c, 0x6a9f, 0x05e0, 0x2061, 0x1a74, 0x6000,
-	0xd084, 0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484,
-	0x0003, 0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100,
-	0x9210, 0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0,
-	0x9484, 0x000c, 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082,
-	0x0004, 0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004,
-	0x1168, 0x2100, 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000,
-	0x6016, 0x6206, 0x630a, 0x012e, 0x0804, 0x7f5e, 0x012e, 0x0804,
-	0x7f5b, 0x012e, 0x0804, 0x7f58, 0x0126, 0x2091, 0x8000, 0x7007,
-	0x0001, 0x2061, 0x1a74, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318,
-	0x0220, 0x630a, 0x012e, 0x0804, 0x7f6c, 0x012e, 0x0804, 0x7f5b,
-	0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c,
-	0xd0ac, 0x0148, 0x00c6, 0x2061, 0x1a74, 0x6000, 0x9084, 0xfcff,
-	0x6002, 0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065,
-	0x0598, 0x2001, 0x1834, 0x2004, 0x9005, 0x0118, 0x080c, 0xb306,
-	0x0068, 0x6017, 0xf400, 0x605b, 0x0000, 0xa97c, 0xd1a4, 0x0110,
-	0xa980, 0x615a, 0x2009, 0x0041, 0x080c, 0xb352, 0xa988, 0x918c,
-	0xff00, 0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff,
-	0x080c, 0x8a50, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a74,
-	0x6000, 0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce,
-	0x012e, 0x00be, 0x0804, 0x7f5e, 0x00ce, 0x012e, 0x00be, 0x0804,
-	0x7f58, 0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18,
-	0x9186, 0x0045, 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c,
-	0x200c, 0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186,
-	0x0029, 0x1d10, 0xa974, 0x080c, 0x6724, 0x1968, 0xb800, 0xc0e4,
-	0xb802, 0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001,
-	0x1986, 0x2004, 0x601a, 0x0804, 0x7df3, 0xa88c, 0x9065, 0x0960,
-	0x00e6, 0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150,
-	0x080c, 0xb306, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xb306, 0x00ee,
-	0x0804, 0x7df3, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007,
-	0x003a, 0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e,
-	0xa8a8, 0x6016, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1,
-	0x00ee, 0x0804, 0x7df3, 0x2061, 0x1a74, 0x6000, 0xd084, 0x0190,
-	0xd08c, 0x1904, 0x7f6c, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210,
-	0x0220, 0x6206, 0x012e, 0x0804, 0x7f6c, 0x012e, 0xa883, 0x0016,
-	0x0804, 0x7f65, 0xa883, 0x0007, 0x0804, 0x7f65, 0xa864, 0x8007,
-	0x9084, 0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069,
-	0x0005, 0x080c, 0x7a99, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900,
-	0x7016, 0x701a, 0x704b, 0x7e95, 0x0005, 0x00b6, 0x00e6, 0x0126,
-	0x2091, 0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904,
-	0x7f17, 0x6130, 0xd194, 0x1904, 0x7f41, 0xa878, 0x2070, 0x9e82,
-	0x1cd0, 0x0a04, 0x7f0b, 0x6068, 0x9e02, 0x1a04, 0x7f0b, 0x7120,
-	0x9186, 0x0006, 0x1904, 0x7efd, 0x7010, 0x905d, 0x0904, 0x7f17,
-	0xb800, 0xd0e4, 0x1904, 0x7f3b, 0x2061, 0x1a74, 0x6100, 0x9184,
-	0x0301, 0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x7f44,
-	0xa883, 0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198,
-	0x7116, 0xa87c, 0xd0f4, 0x1904, 0x7f47, 0x080c, 0x57d5, 0xd09c,
-	0x1118, 0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x8970, 0x012e,
-	0x00ee, 0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902,
-	0x2148, 0xa87c, 0xd0f4, 0x1904, 0x7f47, 0x012e, 0x00ee, 0x00be,
-	0x0005, 0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x7f65,
-	0xd184, 0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x6724,
-	0x15d0, 0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118,
-	0xa883, 0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e,
-	0x0460, 0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c,
-	0x57d9, 0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1cd0, 0x02c0,
-	0x6068, 0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010,
-	0x905d, 0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000,
-	0x9086, 0x0007, 0x1904, 0x7ea1, 0x7003, 0x0002, 0x0804, 0x7ea1,
-	0xa883, 0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be,
-	0x0420, 0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60,
-	0x2019, 0x0002, 0x601b, 0x0014, 0x080c, 0xe754, 0x012e, 0x00ee,
-	0x00be, 0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040,
-	0x2009, 0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001,
-	0xa884, 0x9084, 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6e9f, 0x012e, 0x0005, 0x080c, 0x1040, 0x0005, 0x00d6,
-	0x080c, 0x8967, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091,
-	0x8000, 0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780,
-	0x190c, 0x8056, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea,
-	0x0020, 0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e,
-	0x9006, 0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c,
-	0x0c28, 0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780,
-	0x190c, 0x8056, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8,
-	0x080c, 0xb27d, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff,
-	0x9086, 0x0035, 0x1138, 0x6008, 0xc0fd, 0x600a, 0x2001, 0x196b,
-	0x2004, 0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00,
-	0x9105, 0xa99c, 0x918c, 0x00ff, 0x080c, 0x2873, 0x1540, 0x00b6,
-	0x080c, 0x6724, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001,
-	0x2009, 0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110,
-	0x2009, 0x0041, 0x080c, 0xb352, 0x0005, 0xa87b, 0x0101, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0005, 0xa87b, 0x002c,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x0005, 0xa87b,
-	0x0028, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e, 0x080c,
-	0xb2d3, 0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6,
-	0x7007, 0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x8047, 0xa97c,
-	0x9188, 0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8,
-	0x8007, 0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10,
-	0x080c, 0xb27d, 0x1118, 0x080c, 0xb325, 0x05a8, 0x6212, 0xa874,
-	0x0002, 0x8025, 0x802a, 0x802d, 0x8033, 0x2019, 0x0002, 0x080c,
-	0xeba1, 0x0060, 0x080c, 0xeb38, 0x0048, 0x2019, 0x0002, 0xa980,
-	0x080c, 0xeb53, 0x0018, 0xa980, 0x080c, 0xeb38, 0x080c, 0xb2d3,
-	0xa887, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e,
-	0x00be, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887,
-	0x0006, 0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50,
-	0xa887, 0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000,
-	0x0e04, 0x8058, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804,
-	0x0dce, 0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6,
-	0x2079, 0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102,
-	0x2009, 0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x15a0, 0x00fe,
-	0x0005, 0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe,
-	0x0005, 0x781c, 0xd08c, 0x0904, 0x80d8, 0x68c0, 0x90aa, 0x0005,
-	0x0a04, 0x871c, 0x7d44, 0x7c40, 0x9584, 0x00f6, 0x1510, 0x9484,
-	0x7000, 0x0140, 0x908a, 0x2000, 0x1260, 0x9584, 0x0700, 0x8007,
-	0x0804, 0x80df, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100, 0x0da8,
-	0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00, 0x9086,
-	0x8100, 0x11c0, 0x080c, 0xf057, 0x080c, 0x8601, 0x7817, 0x0140,
-	0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x865f, 0x19c0, 0xd5a4,
-	0x0148, 0x0046, 0x0056, 0x080c, 0x813a, 0x080c, 0x236e, 0x005e,
-	0x004e, 0x0020, 0x080c, 0xf057, 0x7817, 0x0140, 0x080c, 0x7637,
-	0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, 0x6893, 0x0000,
-	0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, 0x080c, 0x811b,
-	0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, 0x0005, 0x0002,
-	0x80f1, 0x8409, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8, 0x80e8,
-	0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1,
-	0x0005, 0x7000, 0x908c, 0xff00, 0x9194, 0xf000, 0x810f, 0x9484,
-	0x0fff, 0x6892, 0x9286, 0x2000, 0x1150, 0x6800, 0x9086, 0x0001,
-	0x1118, 0x080c, 0x583f, 0x0070, 0x080c, 0x815a, 0x0058, 0x9286,
-	0x3000, 0x1118, 0x080c, 0x8341, 0x0028, 0x9286, 0x8000, 0x1110,
-	0x080c, 0x8528, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005,
-	0x090c, 0x9ab1, 0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178,
-	0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036,
-	0x2011, 0x8048, 0x2518, 0x080c, 0x4c44, 0x003e, 0x002e, 0x0005,
-	0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe,
-	0x7c30, 0x0050, 0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200,
-	0x7d44, 0x7c40, 0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c,
-	0x0160, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026,
-	0x2011, 0x8048, 0x080c, 0x4c44, 0x002e, 0x00fe, 0x005e, 0x004e,
-	0x003e, 0x0005, 0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007,
-	0x9096, 0x0001, 0x0120, 0x9096, 0x0023, 0x1904, 0x8312, 0x9186,
-	0x0023, 0x15c0, 0x080c, 0x85c6, 0x0904, 0x8312, 0x6120, 0x9186,
-	0x0001, 0x0150, 0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120,
-	0x9186, 0x000a, 0x1904, 0x8312, 0x7124, 0x610a, 0x7030, 0x908e,
-	0x0200, 0x1130, 0x2009, 0x0015, 0x080c, 0xb352, 0x0804, 0x8312,
-	0x908e, 0x0214, 0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015,
-	0x080c, 0xb352, 0x0804, 0x8312, 0x908e, 0x0100, 0x1904, 0x8312,
-	0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0016, 0x080c, 0xb352,
-	0x0804, 0x8312, 0x9186, 0x0022, 0x1904, 0x8312, 0x7030, 0x908e,
-	0x0300, 0x1580, 0x68dc, 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100,
-	0x918c, 0x00ff, 0x697e, 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100,
-	0x79e6, 0x78ea, 0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c,
-	0x28bc, 0x7932, 0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x2873,
-	0x695e, 0x703c, 0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800,
-	0x70b6, 0x00ee, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0017,
-	0x0804, 0x82c2, 0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904,
-	0x8312, 0x080c, 0x7637, 0x0120, 0x2009, 0x001d, 0x0804, 0x82c2,
-	0x68dc, 0xc0a5, 0x68de, 0x2009, 0x0030, 0x0804, 0x82c2, 0x908e,
-	0x0500, 0x1140, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0018,
-	0x0804, 0x82c2, 0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804,
-	0x82c2, 0x908e, 0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x82c2,
-	0x908e, 0x5200, 0x1140, 0x7034, 0x9005, 0x1904, 0x8312, 0x2009,
-	0x001b, 0x0804, 0x82c2, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005,
-	0x1904, 0x8312, 0x2009, 0x001c, 0x0804, 0x82c2, 0x908e, 0x1300,
-	0x1120, 0x2009, 0x0034, 0x0804, 0x82c2, 0x908e, 0x1200, 0x1140,
-	0x7034, 0x9005, 0x1904, 0x8312, 0x2009, 0x0024, 0x0804, 0x82c2,
-	0x908c, 0xff00, 0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001,
-	0x1810, 0x2004, 0xd09c, 0x0904, 0x82c2, 0x080c, 0xdf1a, 0x1904,
-	0x8312, 0x0804, 0x82c0, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120,
-	0x2009, 0x002a, 0x0804, 0x82c2, 0x908e, 0x0f00, 0x1120, 0x2009,
-	0x0020, 0x0804, 0x82c2, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205,
-	0x2011, 0x026d, 0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004,
-	0x20a8, 0x2011, 0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c,
-	0x4c44, 0x004e, 0x8108, 0x0f04, 0x8276, 0x9186, 0x0280, 0x1d88,
-	0x2504, 0x8000, 0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000,
-	0x2009, 0x0023, 0x0804, 0x82c2, 0x908e, 0x6000, 0x1120, 0x2009,
-	0x003f, 0x0804, 0x82c2, 0x908e, 0x5400, 0x1138, 0x080c, 0x86cc,
-	0x1904, 0x8312, 0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148,
-	0x080c, 0x86f4, 0x1118, 0x2009, 0x0041, 0x0460, 0x2009, 0x0042,
-	0x0448, 0x908e, 0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e,
-	0x1000, 0x1118, 0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118,
-	0x2009, 0x004a, 0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118,
-	0x2009, 0x004f, 0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118,
-	0x2009, 0x0050, 0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110,
-	0x2009, 0x004c, 0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c,
-	0x080c, 0x2873, 0x1904, 0x8315, 0x080c, 0x66b9, 0x1904, 0x8315,
-	0xbe12, 0xbd16, 0x001e, 0x0016, 0x080c, 0x7637, 0x01c0, 0x68dc,
-	0xd08c, 0x1148, 0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084,
-	0xff00, 0x1168, 0x0040, 0x687c, 0x9606, 0x1148, 0x6880, 0x9506,
-	0x9084, 0xff00, 0x1120, 0x9584, 0x00ff, 0xb8c2, 0x0080, 0xb8c0,
-	0x9005, 0x1168, 0x9186, 0x0046, 0x1150, 0x687c, 0x9606, 0x1138,
-	0x6880, 0x9506, 0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c,
-	0xb27d, 0x01a8, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a,
-	0x001e, 0x9186, 0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e,
-	0x080c, 0xb352, 0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001,
-	0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4c44,
-	0x080c, 0xb325, 0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120,
-	0x610a, 0x001e, 0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030,
-	0x1128, 0x6007, 0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051,
-	0x6017, 0x0000, 0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x9547,
-	0x08a0, 0x080c, 0x873b, 0x1158, 0x080c, 0x3374, 0x1140, 0x7010,
-	0x9084, 0xff00, 0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005,
-	0x00b6, 0x00c6, 0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186,
-	0x0033, 0x11e8, 0x080c, 0x85c6, 0x0904, 0x83a1, 0x7124, 0x610a,
-	0x7030, 0x908e, 0x0200, 0x1140, 0x7034, 0x9005, 0x15d0, 0x2009,
-	0x0015, 0x080c, 0xb352, 0x04a8, 0x908e, 0x0100, 0x1590, 0x7034,
-	0x9005, 0x1578, 0x2009, 0x0016, 0x080c, 0xb352, 0x0450, 0x9186,
-	0x0032, 0x1538, 0x7030, 0x908e, 0x1400, 0x1518, 0x2009, 0x0038,
-	0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2873,
-	0x11b8, 0x080c, 0x66b9, 0x11a0, 0xbe12, 0xbd16, 0x080c, 0xb27d,
-	0x0178, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0004, 0x7120,
-	0x610a, 0x001e, 0x080c, 0xb352, 0x080c, 0x9ab1, 0x0010, 0x00ce,
-	0x001e, 0x004e, 0x00ce, 0x00be, 0x0005, 0x00b6, 0x0046, 0x00e6,
-	0x00d6, 0x2028, 0x2130, 0x9696, 0x00ff, 0x11b8, 0x9592, 0xfffc,
-	0x02a0, 0x9596, 0xfffd, 0x1120, 0x2009, 0x007f, 0x0804, 0x8403,
-	0x9596, 0xfffe, 0x1120, 0x2009, 0x007e, 0x0804, 0x8403, 0x9596,
-	0xfffc, 0x1118, 0x2009, 0x0080, 0x04f0, 0x2011, 0x0000, 0x2019,
-	0x1837, 0x231c, 0xd3ac, 0x0130, 0x9026, 0x20a9, 0x0800, 0x2071,
-	0x1000, 0x0030, 0x2021, 0x0081, 0x20a9, 0x077f, 0x2071, 0x1081,
-	0x2e1c, 0x93dd, 0x0000, 0x1140, 0x82ff, 0x11d0, 0x9496, 0x00ff,
-	0x01b8, 0x2410, 0xc2fd, 0x00a0, 0xbf10, 0x2600, 0x9706, 0xb814,
-	0x1120, 0x9546, 0x1110, 0x2408, 0x00b0, 0x9745, 0x1148, 0x94c6,
-	0x007e, 0x0130, 0x94c6, 0x007f, 0x0118, 0x94c6, 0x0080, 0x1d20,
-	0x8420, 0x8e70, 0x1f04, 0x83d8, 0x82ff, 0x1118, 0x9085, 0x0001,
-	0x0018, 0xc2fc, 0x2208, 0x9006, 0x00de, 0x00ee, 0x004e, 0x00be,
-	0x0005, 0x2001, 0x1837, 0x200c, 0x9184, 0x0080, 0x0110, 0xd18c,
-	0x0138, 0x7000, 0x908c, 0xff00, 0x810f, 0x9184, 0x000f, 0x004a,
-	0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1,
-	0x0005, 0x8431, 0x8431, 0x8431, 0x85d8, 0x8431, 0x843a, 0x8465,
-	0x84f3, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431, 0x8431,
-	0x8431, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c,
-	0x9ab1, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160,
-	0x9c8c, 0x0007, 0x11c0, 0x9c8a, 0x1cd0, 0x02a8, 0x6868, 0x9c02,
-	0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106,
-	0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009,
-	0x0046, 0x080c, 0xb352, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004,
-	0x9005, 0x090c, 0x9ab1, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x9484,
-	0x0fff, 0x0904, 0x84c9, 0x7110, 0xd1bc, 0x1904, 0x84c9, 0x7108,
-	0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094, 0xff00, 0x15b0,
-	0x81ff, 0x15a0, 0x9080, 0x33b6, 0x200d, 0x918c, 0xff00, 0x810f,
-	0x2001, 0x0080, 0x9106, 0x0904, 0x84c9, 0x080c, 0x66b9, 0x1904,
-	0x84c9, 0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15d8, 0xba04, 0x9294,
-	0xff00, 0x9286, 0x0600, 0x11a0, 0x080c, 0xb27d, 0x05e8, 0x2b08,
-	0x7028, 0x6046, 0x702c, 0x604a, 0x6112, 0x6023, 0x0006, 0x7120,
-	0x610a, 0x7130, 0x6156, 0x2009, 0x0044, 0x080c, 0xe192, 0x0408,
-	0x080c, 0x6aa3, 0x1138, 0xb807, 0x0606, 0x0c30, 0x190c, 0x83a5,
-	0x11c0, 0x0898, 0x080c, 0xb27d, 0x2b08, 0x0198, 0x6112, 0x6023,
-	0x0004, 0x7120, 0x610a, 0x9286, 0x0400, 0x1118, 0x6007, 0x0005,
-	0x0010, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c,
-	0x9ab1, 0x7817, 0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c,
-	0x9ab1, 0x00ce, 0x00be, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec,
-	0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, 0x080c, 0xb325, 0x0d48,
-	0x2b08, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a, 0x7130, 0x6156,
-	0x6017, 0xf300, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff,
-	0x080c, 0x9ab1, 0x08b0, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7020,
-	0x2060, 0x9c84, 0x0007, 0x11c0, 0x9c82, 0x1cd0, 0x02a8, 0x6868,
-	0x9c02, 0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910,
-	0x9106, 0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a,
-	0x2009, 0x0045, 0x080c, 0xb352, 0x7817, 0x0140, 0x2001, 0x19f1,
-	0x2004, 0x9005, 0x090c, 0x9ab1, 0x00be, 0x0005, 0x6120, 0x9186,
-	0x0002, 0x0128, 0x9186, 0x0005, 0x0110, 0x9085, 0x0001, 0x0005,
-	0x080c, 0x873b, 0x1180, 0x080c, 0x3374, 0x1168, 0x7010, 0x9084,
-	0xff00, 0x8007, 0x9086, 0x0000, 0x1130, 0x9184, 0x000f, 0x908a,
-	0x0006, 0x1208, 0x000b, 0x0005, 0x8542, 0x8543, 0x8542, 0x8542,
-	0x85a8, 0x85b7, 0x0005, 0x00b6, 0x700c, 0x7108, 0x080c, 0x2873,
-	0x1904, 0x85a6, 0x080c, 0x66b9, 0x1904, 0x85a6, 0xbe12, 0xbd16,
-	0x7110, 0xd1bc, 0x0540, 0x702c, 0xd084, 0x1120, 0xb800, 0xd0bc,
-	0x1904, 0x85a6, 0x080c, 0x6aa3, 0x0148, 0x9086, 0x0004, 0x0130,
-	0x080c, 0x6aab, 0x0118, 0x9086, 0x0004, 0x1588, 0x00c6, 0x080c,
-	0x85c6, 0x00ce, 0x05d8, 0x080c, 0xb27d, 0x2b08, 0x05b8, 0x6112,
-	0x080c, 0xd554, 0x6023, 0x0002, 0x7120, 0x610a, 0x2009, 0x0088,
-	0x080c, 0xb352, 0x0458, 0x080c, 0x6aa3, 0x0148, 0x9086, 0x0004,
-	0x0130, 0x080c, 0x6aab, 0x0118, 0x9086, 0x0004, 0x1180, 0x080c,
-	0xb27d, 0x2b08, 0x01d8, 0x6112, 0x080c, 0xd554, 0x6023, 0x0005,
-	0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xb352, 0x0078, 0x080c,
-	0xb27d, 0x2b08, 0x0158, 0x6112, 0x080c, 0xd554, 0x6023, 0x0004,
-	0x7120, 0x610a, 0x2009, 0x0001, 0x080c, 0xb352, 0x00be, 0x0005,
-	0x7110, 0xd1bc, 0x0158, 0x00d1, 0x0148, 0x080c, 0x851e, 0x1130,
-	0x7124, 0x610a, 0x2009, 0x0089, 0x080c, 0xb352, 0x0005, 0x7110,
-	0xd1bc, 0x0158, 0x0059, 0x0148, 0x080c, 0x851e, 0x1130, 0x7124,
-	0x610a, 0x2009, 0x008a, 0x080c, 0xb352, 0x0005, 0x7020, 0x2060,
-	0x9c84, 0x0007, 0x1158, 0x9c82, 0x1cd0, 0x0240, 0x2001, 0x181a,
-	0x2004, 0x9c02, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8,
-	0x00b6, 0x7110, 0xd1bc, 0x11d8, 0x7024, 0x2060, 0x9c84, 0x0007,
-	0x11b0, 0x9c82, 0x1cd0, 0x0298, 0x6868, 0x9c02, 0x1280, 0x7008,
-	0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106, 0x1140, 0x700c,
-	0xb914, 0x9106, 0x1120, 0x2009, 0x0051, 0x080c, 0xb352, 0x7817,
-	0x0140, 0x2001, 0x19f1, 0x2004, 0x9005, 0x090c, 0x9ab1, 0x00be,
-	0x0005, 0x2031, 0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049,
-	0x0005, 0x2031, 0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009,
-	0x0005, 0x00c6, 0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086,
-	0xc000, 0x05d0, 0x080c, 0xb27d, 0x05b8, 0x0066, 0x00c6, 0x0046,
-	0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x2873, 0x15a0,
-	0x080c, 0x66b9, 0x1588, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce,
-	0x6012, 0x080c, 0xd554, 0x080c, 0x100e, 0x0510, 0x2900, 0x605a,
-	0x9006, 0xa802, 0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9,
-	0x000e, 0xa860, 0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003,
-	0x006e, 0x6616, 0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001,
-	0x080c, 0x9547, 0x080c, 0x9ab1, 0x00fe, 0x009e, 0x00ce, 0x0005,
-	0x080c, 0xb2d3, 0x006e, 0x0cc0, 0x004e, 0x00ce, 0x0cc8, 0x00c6,
-	0x7000, 0x908c, 0xff00, 0x9184, 0xf000, 0x810f, 0x9086, 0x2000,
-	0x1904, 0x86b6, 0x9186, 0x0022, 0x15f0, 0x2001, 0x0111, 0x2004,
-	0x9005, 0x1904, 0x86b8, 0x7030, 0x908e, 0x0400, 0x0904, 0x86b8,
-	0x908e, 0x6000, 0x05e8, 0x908e, 0x5400, 0x05d0, 0x908e, 0x0300,
-	0x11d8, 0x2009, 0x1837, 0x210c, 0xd18c, 0x1590, 0xd1a4, 0x1580,
-	0x080c, 0x6a61, 0x0588, 0x68b0, 0x9084, 0x00ff, 0x7100, 0x918c,
-	0x00ff, 0x9106, 0x1518, 0x6880, 0x69b0, 0x918c, 0xff00, 0x9105,
-	0x7104, 0x9106, 0x11d8, 0x00e0, 0x2009, 0x0103, 0x210c, 0xd1b4,
-	0x11a8, 0x908e, 0x5200, 0x09e8, 0x908e, 0x0500, 0x09d0, 0x908e,
-	0x5000, 0x09b8, 0x0058, 0x9186, 0x0023, 0x1140, 0x080c, 0x85c6,
-	0x0128, 0x6004, 0x9086, 0x0002, 0x0118, 0x0000, 0x9006, 0x0010,
-	0x9085, 0x0001, 0x00ce, 0x0005, 0x7030, 0x908e, 0x0300, 0x0118,
-	0x908e, 0x5200, 0x1d98, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009,
-	0x9086, 0x0008, 0x0d68, 0x0c50, 0x0156, 0x0046, 0x0016, 0x0036,
-	0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9,
-	0x0004, 0x2019, 0x1805, 0x2011, 0x027a, 0x080c, 0xc365, 0x1178,
-	0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x027e,
-	0x080c, 0xc365, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e,
-	0x001e, 0x004e, 0x015e, 0x0005, 0x0156, 0x0046, 0x0016, 0x0036,
-	0x7038, 0x2020, 0x8427, 0x94a4, 0x0007, 0xd484, 0x0148, 0x20a9,
-	0x0004, 0x2019, 0x1805, 0x2011, 0x0272, 0x080c, 0xc365, 0x1178,
-	0xd48c, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1801, 0x2011, 0x0276,
-	0x080c, 0xc365, 0x1120, 0xd494, 0x0110, 0x9085, 0x0001, 0x003e,
-	0x001e, 0x004e, 0x015e, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7800,
-	0xc0e5, 0xc0cc, 0x7802, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x1800,
-	0x7834, 0xd084, 0x1130, 0x2079, 0x0200, 0x7800, 0x9085, 0x1200,
-	0x7802, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7034, 0xc084,
-	0x7036, 0x00ee, 0x0005, 0x0016, 0x2001, 0x1837, 0x200c, 0x9184,
-	0x0080, 0x0118, 0xd18c, 0x0118, 0x9006, 0x001e, 0x0005, 0x9085,
-	0x0001, 0x0cd8, 0x2071, 0x19fb, 0x7003, 0x0003, 0x700f, 0x0361,
-	0x9006, 0x701a, 0x707a, 0x7012, 0x7017, 0x1cd0, 0x7007, 0x0000,
-	0x7026, 0x702b, 0xa6ff, 0x7032, 0x703a, 0x703f, 0x0064, 0x7037,
-	0xa767, 0x7047, 0xffff, 0x704a, 0x704f, 0x5667, 0x7052, 0x7063,
-	0x88de, 0x080c, 0x1027, 0x090c, 0x0dc5, 0x2900, 0x7042, 0xa867,
-	0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x19fb,
-	0x1d04, 0x882c, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e, 0x1540,
-	0x2001, 0x013c, 0x2004, 0x9005, 0x190c, 0x894c, 0x2001, 0x1869,
-	0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1, 0x0000,
-	0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0dc5, 0x700f, 0x0361,
-	0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x080c, 0x8923, 0x7048,
-	0x900d, 0x0148, 0x8109, 0x714a, 0x1130, 0x704c, 0x080f, 0x0018,
-	0x0126, 0x2091, 0x8000, 0x7024, 0x900d, 0x0188, 0x7020, 0x8001,
-	0x7022, 0x1168, 0x7023, 0x0009, 0x8109, 0x7126, 0x9186, 0x03e8,
-	0x1110, 0x7028, 0x080f, 0x81ff, 0x1110, 0x7028, 0x080f, 0x7030,
-	0x900d, 0x05a8, 0x702c, 0x8001, 0x702e, 0x1588, 0x0016, 0x2009,
-	0x0306, 0x210c, 0x9184, 0x0030, 0x01e8, 0x9184, 0x0048, 0x9086,
-	0x0008, 0x11c0, 0x7038, 0x9005, 0x01a8, 0x8001, 0x703a, 0x1190,
-	0x080c, 0x7637, 0x0178, 0x00e6, 0x2071, 0x19e8, 0x080c, 0xa7f5,
-	0x00ee, 0x1140, 0x2009, 0x1a86, 0x2104, 0x8000, 0x0208, 0x200a,
-	0x001e, 0x0068, 0x001e, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128,
-	0x9184, 0x007f, 0x090c, 0xa8ab, 0x0010, 0x7034, 0x080f, 0x7044,
-	0x9005, 0x0118, 0x0310, 0x8001, 0x7046, 0x7054, 0x900d, 0x0168,
-	0x7050, 0x8001, 0x7052, 0x1148, 0x7053, 0x0009, 0x8109, 0x7156,
-	0x1120, 0x7158, 0x7156, 0x7060, 0x080f, 0x7018, 0x900d, 0x01d8,
-	0x0016, 0x7078, 0x900d, 0x0158, 0x7074, 0x8001, 0x7076, 0x1138,
-	0x7077, 0x0009, 0x8109, 0x717a, 0x1110, 0x707c, 0x080f, 0x001e,
-	0x7008, 0x8001, 0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a,
-	0x1110, 0x701c, 0x080f, 0x012e, 0x7004, 0x0002, 0x8854, 0x8855,
-	0x8871, 0x00e6, 0x2071, 0x19fb, 0x7018, 0x9005, 0x1120, 0x711a,
-	0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071,
-	0x19fb, 0x701c, 0x9206, 0x1120, 0x701a, 0x701e, 0x707a, 0x707e,
-	0x000e, 0x00ee, 0x0005, 0x00e6, 0x2071, 0x19fb, 0xb888, 0x9102,
-	0x0208, 0xb98a, 0x00ee, 0x0005, 0x0005, 0x00b6, 0x7110, 0x080c,
-	0x6724, 0x1168, 0xb888, 0x8001, 0x0250, 0xb88a, 0x1140, 0x0126,
-	0x2091, 0x8000, 0x0016, 0x080c, 0x9ab1, 0x001e, 0x012e, 0x8108,
-	0x9182, 0x0800, 0x0218, 0x900e, 0x7007, 0x0002, 0x7112, 0x00be,
-	0x0005, 0x7014, 0x2060, 0x0126, 0x2091, 0x8000, 0x6040, 0x9005,
-	0x0128, 0x8001, 0x6042, 0x1110, 0x080c, 0xd3e5, 0x6018, 0x9005,
-	0x0558, 0x8001, 0x601a, 0x1540, 0x6120, 0x9186, 0x0003, 0x0148,
-	0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c, 0xd1c4,
-	0x1100, 0x080c, 0xd0d8, 0x01b0, 0x6014, 0x2048, 0xa884, 0x908a,
-	0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a, 0x0210,
-	0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0xa87c,
-	0xd0e4, 0x0110, 0x080c, 0xcdbc, 0x012e, 0x9c88, 0x0018, 0x7116,
-	0x2001, 0x181a, 0x2004, 0x9102, 0x0220, 0x7017, 0x1cd0, 0x7007,
-	0x0000, 0x0005, 0x00e6, 0x2071, 0x19fb, 0x7027, 0x07d0, 0x7023,
-	0x0009, 0x00ee, 0x0005, 0x2001, 0x1a04, 0x2003, 0x0000, 0x0005,
-	0x00e6, 0x2071, 0x19fb, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005,
-	0x2011, 0x1a07, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x19fb,
-	0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026,
-	0x705c, 0x8000, 0x705e, 0x2001, 0x1a0b, 0x2044, 0xa06c, 0x9086,
-	0x0000, 0x0150, 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, 0xa092,
-	0x7064, 0xa08e, 0x080c, 0x10f8, 0x002e, 0x008e, 0x0005, 0x0006,
-	0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6,
-	0x0156, 0x080c, 0x8776, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce,
-	0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071,
-	0x19fb, 0x717a, 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, 0x00e6,
-	0x0006, 0x2071, 0x19fb, 0x707c, 0x9206, 0x1110, 0x707a, 0x707e,
-	0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, 0x69e8, 0xd1e4, 0x1518,
-	0x0026, 0xd1ec, 0x0140, 0x6a54, 0x6874, 0x9202, 0x0288, 0x8117,
-	0x9294, 0x00c0, 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184,
-	0x0007, 0x0110, 0x69ea, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d,
-	0x8107, 0x9106, 0x9094, 0x00c0, 0x9184, 0xff3f, 0x9205, 0x68ea,
-	0x080c, 0x0eee, 0x002e, 0x0005, 0x0016, 0x00c6, 0x2009, 0xfff4,
-	0x210d, 0x2061, 0x0100, 0x60f0, 0x9100, 0x60f3, 0x0000, 0x2009,
-	0xfff4, 0x200f, 0x1220, 0x8108, 0x2105, 0x8000, 0x200f, 0x00ce,
-	0x001e, 0x0005, 0x00c6, 0x2061, 0x1a74, 0x00ce, 0x0005, 0x9184,
-	0x000f, 0x8003, 0x8003, 0x8003, 0x9080, 0x1a74, 0x2060, 0x0005,
-	0xa884, 0x908a, 0x199a, 0x1638, 0x9005, 0x1150, 0x00c6, 0x2061,
-	0x1a74, 0x6014, 0x00ce, 0x9005, 0x1130, 0x2001, 0x001e, 0x0018,
-	0x908e, 0xffff, 0x01b0, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a,
-	0xa87c, 0x908c, 0x00c0, 0x918e, 0x00c0, 0x0904, 0x89fa, 0xd0b4,
-	0x1168, 0xd0bc, 0x1904, 0x89d3, 0x2009, 0x0006, 0x080c, 0x8a27,
-	0x0005, 0x900e, 0x0c60, 0x2001, 0x1999, 0x08b0, 0xd0fc, 0x0160,
-	0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x8a21, 0x908c,
-	0x2020, 0x918e, 0x2020, 0x01a8, 0x6024, 0xd0d4, 0x11e8, 0x2009,
-	0x1869, 0x2104, 0xd084, 0x1138, 0x87ff, 0x1120, 0x2009, 0x0043,
-	0x0804, 0xb352, 0x0005, 0x87ff, 0x1de8, 0x2009, 0x0042, 0x0804,
-	0xb352, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20,
-	0x6024, 0xc0cd, 0x6026, 0x0c00, 0xc0d4, 0x6026, 0xa890, 0x602e,
-	0xa88c, 0x6032, 0x08e0, 0xd0fc, 0x0160, 0x908c, 0x0003, 0x0120,
-	0x918e, 0x0003, 0x1904, 0x8a21, 0x908c, 0x2020, 0x918e, 0x2020,
-	0x0170, 0x0076, 0x00f6, 0x2c78, 0x080c, 0x1768, 0x00fe, 0x007e,
-	0x87ff, 0x1120, 0x2009, 0x0042, 0x080c, 0xb352, 0x0005, 0x6110,
-	0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d58, 0x6124, 0xc1cd,
-	0x6126, 0x0c38, 0xd0fc, 0x0188, 0x908c, 0x2020, 0x918e, 0x2020,
-	0x01a8, 0x9084, 0x0003, 0x908e, 0x0002, 0x0148, 0x87ff, 0x1120,
-	0x2009, 0x0041, 0x080c, 0xb352, 0x0005, 0x00b9, 0x0ce8, 0x87ff,
-	0x1dd8, 0x2009, 0x0043, 0x080c, 0xb352, 0x0cb0, 0x6110, 0x00b6,
-	0x2158, 0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6124, 0xc1cd, 0x6126,
-	0x0c00, 0x2009, 0x0004, 0x0019, 0x0005, 0x2009, 0x0001, 0x0096,
-	0x080c, 0xd0d8, 0x0518, 0x6014, 0x2048, 0xa982, 0xa800, 0x6016,
-	0x9186, 0x0001, 0x1188, 0xa97c, 0x918c, 0x8100, 0x918e, 0x8100,
-	0x1158, 0x00c6, 0x2061, 0x1a74, 0x6200, 0xd28c, 0x1120, 0x6204,
-	0x8210, 0x0208, 0x6206, 0x00ce, 0x080c, 0x6cde, 0x6014, 0x904d,
-	0x0076, 0x2039, 0x0000, 0x190c, 0x8970, 0x007e, 0x009e, 0x0005,
-	0x0156, 0x00c6, 0x2061, 0x1a74, 0x6000, 0x81ff, 0x0110, 0x9205,
-	0x0008, 0x9204, 0x6002, 0x00ce, 0x015e, 0x0005, 0x6800, 0xd08c,
-	0x1138, 0x6808, 0x9005, 0x0120, 0x8001, 0x680a, 0x9085, 0x0001,
-	0x0005, 0x2071, 0x1924, 0x7003, 0x0006, 0x7007, 0x0000, 0x700f,
-	0x0000, 0x7013, 0x0001, 0x080c, 0x1027, 0x090c, 0x0dc5, 0xa867,
-	0x0006, 0xa86b, 0x0001, 0xa8ab, 0xdcb0, 0xa89f, 0x0000, 0x2900,
-	0x702e, 0x7033, 0x0000, 0x0005, 0x0126, 0x2091, 0x8000, 0x0096,
-	0x00e6, 0x2071, 0x1924, 0x702c, 0x2048, 0x6a2c, 0x721e, 0x6b30,
-	0x7322, 0x6834, 0x7026, 0xa896, 0x6838, 0x702a, 0xa89a, 0x6824,
-	0x7016, 0x683c, 0x701a, 0x2009, 0x0028, 0x200a, 0x9005, 0x0148,
-	0x900e, 0x9188, 0x000c, 0x8001, 0x1de0, 0x2100, 0x9210, 0x1208,
-	0x8318, 0xaa8e, 0xab92, 0x7010, 0xd084, 0x0168, 0xc084, 0x7007,
-	0x0001, 0x700f, 0x0000, 0x0006, 0x2009, 0x1ad1, 0x2104, 0x9082,
-	0x0007, 0x200a, 0x000e, 0xc095, 0x7012, 0x2008, 0x2001, 0x003b,
-	0x080c, 0x1611, 0x9006, 0x2071, 0x193d, 0x7002, 0x7006, 0x702a,
-	0x00ee, 0x009e, 0x012e, 0x0005, 0x2009, 0x1ad1, 0x2104, 0x9080,
-	0x0007, 0x200a, 0x0005, 0x00e6, 0x0126, 0x0156, 0x2091, 0x8000,
-	0x2071, 0x1800, 0x7154, 0x2001, 0x0008, 0x910a, 0x0638, 0x2001,
-	0x187d, 0x20ac, 0x9006, 0x9080, 0x0008, 0x1f04, 0x8ae3, 0x71c0,
-	0x9102, 0x02e0, 0x2071, 0x1877, 0x20a9, 0x0007, 0x00c6, 0x080c,
-	0xb27d, 0x6023, 0x0009, 0x6003, 0x0004, 0x601f, 0x0101, 0x0089,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x8c61, 0x012e, 0x1f04, 0x8aef,
-	0x9006, 0x00ce, 0x015e, 0x012e, 0x00ee, 0x0005, 0x9085, 0x0001,
-	0x0cc8, 0x00e6, 0x00b6, 0x0096, 0x0086, 0x0056, 0x0046, 0x0026,
-	0x7118, 0x720c, 0x7620, 0x7004, 0xd084, 0x1128, 0x2021, 0x0024,
-	0x2029, 0x0002, 0x0020, 0x2021, 0x002c, 0x2029, 0x000a, 0x080c,
-	0x100e, 0x090c, 0x0dc5, 0x2900, 0x6016, 0x2058, 0xac66, 0x9006,
-	0xa802, 0xa806, 0xa86a, 0xa87a, 0xa8aa, 0xa887, 0x0005, 0xa87f,
-	0x0020, 0x7008, 0xa89a, 0x7010, 0xa89e, 0xae8a, 0xa8af, 0xffff,
-	0xa8b3, 0x0000, 0x8109, 0x0160, 0x080c, 0x100e, 0x090c, 0x0dc5,
-	0xad66, 0x2b00, 0xa802, 0x2900, 0xb806, 0x2058, 0x8109, 0x1da0,
-	0x002e, 0x004e, 0x005e, 0x008e, 0x009e, 0x00be, 0x00ee, 0x0005,
-	0x2079, 0x0000, 0x2071, 0x1924, 0x7004, 0x004b, 0x700c, 0x0002,
-	0x8b5b, 0x8b54, 0x8b54, 0x0005, 0x8b65, 0x8bbb, 0x8bbb, 0x8bbb,
-	0x8bbc, 0x8bcd, 0x8bcd, 0x700c, 0x0cba, 0x0126, 0x2091, 0x8000,
-	0x78a0, 0x79a0, 0x9106, 0x1904, 0x8bad, 0x7814, 0xd0bc, 0x1904,
-	0x8bb6, 0x012e, 0x7018, 0x910a, 0x1128, 0x7030, 0x9005, 0x1904,
-	0x8bff, 0x0005, 0x1210, 0x7114, 0x910a, 0x9192, 0x000a, 0x0210,
-	0x2009, 0x000a, 0x2001, 0x1888, 0x2014, 0x2001, 0x1936, 0x2004,
-	0x9100, 0x9202, 0x0e50, 0x080c, 0x8d5c, 0x2200, 0x9102, 0x0208,
-	0x2208, 0x0096, 0x702c, 0x2048, 0xa873, 0x0001, 0xa976, 0x080c,
-	0x8e65, 0x2100, 0xa87e, 0xa86f, 0x0000, 0x009e, 0x0126, 0x2091,
-	0x8000, 0x2009, 0x1a1b, 0x2104, 0xc085, 0x200a, 0x700f, 0x0002,
-	0x012e, 0x080c, 0x1117, 0x1de8, 0x0005, 0x78a0, 0x79a0, 0x9106,
-	0x0904, 0x8b6d, 0x080c, 0x8d34, 0x012e, 0x0005, 0x7810, 0xc0c5,
-	0x7812, 0x0804, 0x8b6d, 0x0005, 0x700c, 0x0002, 0x8bc1, 0x8bc4,
-	0x8bc3, 0x080c, 0x8b63, 0x0005, 0x8001, 0x700e, 0x0096, 0x702c,
-	0x2048, 0xa974, 0x009e, 0x0011, 0x0ca0, 0x0005, 0x0096, 0x702c,
-	0x2048, 0x7018, 0x9100, 0x7214, 0x921a, 0x1130, 0x701c, 0xa88e,
-	0x7020, 0xa892, 0x9006, 0x0068, 0x0006, 0x080c, 0x8e65, 0x2100,
-	0xaa8c, 0x9210, 0xaa8e, 0x1220, 0xa890, 0x9081, 0x0000, 0xa892,
-	0x000e, 0x009e, 0x0126, 0x2091, 0x8000, 0x78a2, 0x701a, 0x080c,
-	0x8d34, 0x012e, 0x0005, 0x00e6, 0x2071, 0x1924, 0x700c, 0x0002,
-	0x8bfd, 0x8bfd, 0x8bfb, 0x700f, 0x0001, 0x00ee, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x7030, 0x9005, 0x0508, 0x2078, 0x7814, 0x2048,
-	0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8c6a, 0x00be, 0x01b0,
-	0x00e6, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x00ee, 0x0178, 0x0096,
-	0x080c, 0x1027, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x04b9, 0x0041,
-	0x2001, 0x1947, 0x2003, 0x0000, 0x012e, 0x08c8, 0x012e, 0x0005,
-	0x00d6, 0x00c6, 0x0086, 0x00a6, 0x2940, 0x2650, 0x2600, 0x9005,
-	0x0180, 0xa864, 0x9084, 0x000f, 0x2068, 0x9d88, 0x20c7, 0x2165,
-	0x0056, 0x2029, 0x0000, 0x080c, 0x8dea, 0x080c, 0x207f, 0x1dd8,
-	0x005e, 0x00ae, 0x2001, 0x187f, 0x2004, 0xa88a, 0x080c, 0x1768,
-	0x781f, 0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x8cc0, 0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005,
-	0x0138, 0x2078, 0x780c, 0x7032, 0x2001, 0x1947, 0x2003, 0x0001,
-	0x0005, 0x00e6, 0x2071, 0x1924, 0x7030, 0x600e, 0x2c00, 0x7032,
-	0x00ee, 0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, 0x8f33, 0x2005,
-	0x906d, 0x090c, 0x0dc5, 0x9b80, 0x8f2b, 0x2005, 0x9065, 0x090c,
-	0x0dc5, 0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0,
-	0x9085, 0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094,
-	0x0148, 0x6854, 0xd084, 0x1178, 0xc085, 0x6856, 0x2011, 0x8026,
-	0x080c, 0x4c44, 0x684c, 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa804,
-	0x8000, 0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c,
-	0x1d08, 0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4c44, 0x684c,
-	0x0096, 0x904d, 0x090c, 0x0dc5, 0xa800, 0x8000, 0xa802, 0x009e,
-	0x0888, 0x7000, 0x2019, 0x0008, 0x8319, 0x7104, 0x9102, 0x1118,
-	0x2300, 0x9005, 0x0020, 0x0210, 0x9302, 0x0008, 0x8002, 0x0005,
-	0x00d6, 0x7814, 0x9005, 0x090c, 0x0dc5, 0x781c, 0x9084, 0x0101,
-	0x9086, 0x0101, 0x190c, 0x0dc5, 0x7827, 0x0000, 0x2069, 0x193d,
-	0x6804, 0x9080, 0x193f, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182,
-	0x0008, 0x0208, 0x900e, 0x6906, 0x9180, 0x193f, 0x2003, 0x0000,
-	0x00de, 0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8,
-	0x0096, 0x2048, 0x9005, 0x190c, 0x1040, 0x009e, 0xa8ab, 0x0000,
-	0x080c, 0x0fc0, 0x080c, 0xb2d3, 0x00ce, 0x009e, 0x0005, 0x6020,
-	0x9086, 0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, 0x0005,
-	0x9085, 0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0178, 0x6010,
-	0x9005, 0x0150, 0x00b6, 0x2058, 0x080c, 0x9067, 0x00be, 0x6013,
-	0x0000, 0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009,
-	0x1928, 0x210c, 0xd194, 0x0005, 0x2009, 0x1928, 0x210c, 0xd1c4,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1924, 0x7110,
-	0xc194, 0xc185, 0x7007, 0x0000, 0x7112, 0x2001, 0x003b, 0x080c,
-	0x1611, 0x00ee, 0x012e, 0x0005, 0x7814, 0xd0bc, 0x1108, 0x0005,
-	0x7810, 0xc0c5, 0x7812, 0x0cc0, 0x0096, 0x00d6, 0x9006, 0x7006,
-	0x700e, 0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, 0x702f,
-	0x0000, 0x080c, 0x8eb3, 0x0170, 0x080c, 0x8ee8, 0x0158, 0x2900,
-	0x7002, 0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, 0x00de,
-	0x009e, 0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, 0x00d6,
-	0x00c6, 0x2071, 0x1931, 0x721c, 0x2100, 0x9202, 0x1618, 0x080c,
-	0x8ee8, 0x090c, 0x0dc5, 0x7018, 0x9005, 0x1160, 0x2900, 0x7002,
-	0x700a, 0x701a, 0x9006, 0x7006, 0x700e, 0xa806, 0xa802, 0x7012,
-	0x701e, 0x0038, 0x2040, 0xa806, 0x2900, 0xa002, 0x701a, 0xa803,
-	0x0000, 0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e,
-	0x721c, 0x08d0, 0x721c, 0x00ce, 0x00de, 0x008e, 0x009e, 0x00ee,
-	0x0005, 0x0096, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091,
-	0x8000, 0x2071, 0x1931, 0x7300, 0x831f, 0x831e, 0x831e, 0x9384,
-	0x003f, 0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, 0x080c,
-	0x8e65, 0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, 0x0078,
-	0x9402, 0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0,
-	0xa001, 0xa001, 0x4005, 0x2508, 0x080c, 0x8e6e, 0x2130, 0x7014,
-	0x9600, 0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, 0x9600,
-	0x2008, 0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, 0x9005,
-	0x1148, 0x2009, 0x0001, 0x0026, 0x080c, 0x8d5c, 0x002e, 0x7000,
-	0x2048, 0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500,
-	0x9212, 0x1904, 0x8d9b, 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e,
-	0x009e, 0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, 0x8000,
-	0x9580, 0x8f2b, 0x2005, 0x9075, 0x090c, 0x0dc5, 0x080c, 0x8e40,
-	0x012e, 0x9580, 0x8f27, 0x2005, 0x9075, 0x090c, 0x0dc5, 0x0156,
-	0x0136, 0x01c6, 0x0146, 0x01d6, 0x831f, 0x831e, 0x831e, 0x9384,
-	0x003f, 0x20e0, 0x9384, 0xffc0, 0x9100, 0x2098, 0xa860, 0x20e8,
-	0xa95c, 0x2c05, 0x9100, 0x20a0, 0x20a9, 0x0002, 0x4003, 0x2e0c,
-	0x2d00, 0x0002, 0x8e2a, 0x8e2a, 0x8e2c, 0x8e2a, 0x8e2c, 0x8e2a,
-	0x8e2a, 0x8e2a, 0x8e2a, 0x8e2a, 0x8e32, 0x8e2a, 0x8e32, 0x8e2a,
-	0x8e2a, 0x8e2a, 0x080c, 0x0dc5, 0x4104, 0x20a9, 0x0002, 0x4002,
-	0x4003, 0x0028, 0x20a9, 0x0002, 0x4003, 0x4104, 0x4003, 0x01de,
-	0x014e, 0x01ce, 0x013e, 0x015e, 0x00ee, 0x002e, 0x001e, 0x0005,
-	0x0096, 0x7014, 0x8001, 0x7016, 0x710c, 0x2110, 0x00f1, 0x810c,
-	0x9188, 0x0003, 0x7308, 0x8210, 0x9282, 0x000a, 0x1198, 0x7008,
-	0x2048, 0xa800, 0x9005, 0x0158, 0x0006, 0x080c, 0x8ef7, 0x009e,
-	0xa807, 0x0000, 0x2900, 0x700a, 0x7010, 0x8001, 0x7012, 0x700f,
-	0x0000, 0x0008, 0x720e, 0x009e, 0x0005, 0x0006, 0x810b, 0x810b,
-	0x2100, 0x810b, 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026,
-	0x2100, 0x9005, 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, 0x8108,
-	0x9082, 0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, 0x0cd8,
-	0x2d00, 0x90b8, 0x0008, 0x2031, 0x8eb1, 0x901e, 0x6808, 0x9005,
-	0x0108, 0x8318, 0x690c, 0x910a, 0x0248, 0x0140, 0x8318, 0x6810,
-	0x9112, 0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x233a, 0x6804,
-	0xd084, 0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967,
-	0x0a67, 0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082,
-	0x0002, 0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67,
-	0x0cd0, 0x6c1a, 0x0005, 0x0096, 0x0046, 0x0126, 0x2091, 0x8000,
-	0x2b00, 0x9080, 0x8f2f, 0x2005, 0x9005, 0x090c, 0x0dc5, 0x2004,
-	0x90a0, 0x000a, 0x080c, 0x1027, 0x01d0, 0x2900, 0x7026, 0xa803,
-	0x0000, 0xa807, 0x0000, 0x080c, 0x1027, 0x0188, 0x7024, 0xa802,
-	0xa807, 0x0000, 0x2900, 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208,
-	0x0c90, 0x9085, 0x0001, 0x012e, 0x004e, 0x009e, 0x0005, 0x7024,
-	0x9005, 0x0dc8, 0x2048, 0xac00, 0x080c, 0x1040, 0x2400, 0x0cc0,
-	0x0126, 0x2091, 0x8000, 0x7024, 0x2048, 0x9005, 0x0130, 0xa800,
-	0x7026, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x7024, 0xa802, 0x2900, 0x7026, 0x012e, 0x0005,
-	0x0096, 0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, 0x2048, 0xa800,
-	0x0006, 0x080c, 0x1040, 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096,
-	0x7008, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x1040,
-	0x000e, 0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a,
-	0x701e, 0x7022, 0x702a, 0x7026, 0x702e, 0x009e, 0x0005, 0x1a67,
-	0x0000, 0x0000, 0x0000, 0x1931, 0x0000, 0x0000, 0x0000, 0x1888,
-	0x0000, 0x0000, 0x0000, 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6,
-	0x00c6, 0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c,
-	0x9053, 0xa067, 0x0023, 0x6010, 0x905d, 0x0904, 0x9028, 0xb814,
-	0xa06e, 0xb910, 0xa172, 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e,
-	0xa834, 0xa082, 0xa07b, 0x0000, 0xa898, 0x9005, 0x0118, 0xa078,
-	0xc085, 0xa07a, 0x2858, 0x2031, 0x0018, 0xa068, 0x908a, 0x0019,
-	0x1a0c, 0x0dc5, 0x2020, 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff,
-	0x908c, 0x000f, 0x91e0, 0x20c7, 0x2c65, 0x9786, 0x0024, 0x2c05,
-	0x1590, 0x908a, 0x0036, 0x1a0c, 0x0dc5, 0x9082, 0x001b, 0x0002,
-	0x8f93, 0x8f93, 0x8f95, 0x8f93, 0x8f93, 0x8f93, 0x8f97, 0x8f93,
-	0x8f93, 0x8f93, 0x8f99, 0x8f93, 0x8f93, 0x8f93, 0x8f9b, 0x8f93,
-	0x8f93, 0x8f93, 0x8f9d, 0x8f93, 0x8f93, 0x8f93, 0x8f9f, 0x8f93,
-	0x8f93, 0x8f93, 0x8fa1, 0x080c, 0x0dc5, 0xa180, 0x04b8, 0xa190,
-	0x04a8, 0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0,
-	0x0468, 0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, 0x0dc5, 0x9082,
-	0x001b, 0x0002, 0x8fc5, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3,
-	0x8fc7, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fc9, 0x8fc3,
-	0x8fc3, 0x8fc3, 0x8fc3, 0x8fc3, 0x8fcb, 0x8fc3, 0x8fc3, 0x8fc3,
-	0x8fc3, 0x8fc3, 0x8fcd, 0x080c, 0x0dc5, 0xa180, 0x0038, 0xa198,
-	0x0028, 0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002,
-	0x8fe9, 0x8feb, 0x8fed, 0x8fef, 0x8ff1, 0x8ff3, 0x8ff5, 0x8ff7,
-	0x8ff9, 0x8ffb, 0x8ffd, 0x8fff, 0x9001, 0x9003, 0x9005, 0x9007,
-	0x9009, 0x900b, 0x900d, 0x900f, 0x9011, 0x9013, 0x9015, 0x9017,
-	0x9019, 0x080c, 0x0dc5, 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da,
-	0x0448, 0xb9d6, 0x0438, 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca,
-	0x0408, 0xb9c6, 0x00f8, 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba,
-	0x00c8, 0xb9b6, 0x00b8, 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa,
-	0x0088, 0xb9a6, 0x0078, 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a,
-	0x0048, 0xb996, 0x0038, 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a,
-	0x0008, 0xb986, 0x8631, 0x8421, 0x0130, 0x080c, 0x207f, 0x090c,
-	0x0dc5, 0x0804, 0x8f6d, 0x00ae, 0x00be, 0x00ce, 0x00ee, 0x0005,
-	0xa86c, 0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, 0x9006, 0x0804,
-	0x8f4f, 0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, 0xb810, 0x9005,
-	0x01b0, 0x2001, 0x1925, 0x2004, 0x9005, 0x0188, 0x2001, 0x1800,
-	0x2004, 0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0xbba0, 0x2021,
-	0x0004, 0x2011, 0x8014, 0x080c, 0x4c44, 0x004e, 0x003e, 0x00be,
-	0x001e, 0x000e, 0x0005, 0x9016, 0x710c, 0xa834, 0x910a, 0xa936,
-	0x7008, 0x9005, 0x0120, 0x8210, 0x910a, 0x0230, 0x0128, 0x7010,
-	0x8210, 0x910a, 0x0208, 0x1de0, 0xaa8a, 0xa26a, 0x0005, 0x00f6,
-	0x00d6, 0x0036, 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094,
-	0x1dd8, 0x781b, 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0,
-	0xb8ac, 0x906d, 0x0198, 0x2079, 0x0000, 0x9c1e, 0x1118, 0x680c,
-	0xb8ae, 0x0050, 0x9c06, 0x0130, 0x2d78, 0x680c, 0x906d, 0x1dd0,
-	0x080c, 0x0dc5, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300,
-	0x781b, 0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6,
-	0x0096, 0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9,
-	0x01ff, 0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110,
-	0x1f04, 0x90a3, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094,
-	0x1d90, 0xb8ac, 0x9065, 0x01f0, 0x600c, 0xb8ae, 0x6024, 0xc08d,
-	0x6026, 0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f,
-	0x0101, 0x6014, 0x904d, 0x090c, 0x0dc5, 0xa88b, 0x0000, 0xa8a8,
-	0xa8ab, 0x0000, 0x904d, 0x090c, 0x0dc5, 0x080c, 0x1040, 0x080c,
-	0x8c61, 0x08f8, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, 0x012e,
-	0x003e, 0x00ce, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6,
-	0x0016, 0x0006, 0x0156, 0x080c, 0x2873, 0x015e, 0x11b0, 0x080c,
-	0x66b9, 0x190c, 0x0dc5, 0x000e, 0x001e, 0xb912, 0xb816, 0x080c,
-	0xb27d, 0x0140, 0x2b00, 0x6012, 0x6023, 0x0001, 0x2009, 0x0001,
-	0x080c, 0xb352, 0x00be, 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0,
-	0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e,
-	0x0005, 0x9119, 0x9119, 0x9119, 0x911b, 0x916c, 0x9119, 0x9119,
-	0x9119, 0x91e6, 0x9119, 0x9223, 0x9119, 0x9119, 0x9119, 0x9119,
-	0x9119, 0x080c, 0x0dc5, 0x9182, 0x0040, 0x0002, 0x912e, 0x912e,
-	0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x912e, 0x9130,
-	0x9145, 0x912e, 0x912e, 0x912e, 0x912e, 0x9158, 0x080c, 0x0dc5,
-	0x0096, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, 0x2148, 0xa87b,
-	0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c,
-	0x6ca3, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x080c, 0x9a61, 0x00d6,
-	0x6114, 0x080c, 0xd0d8, 0x0130, 0x0096, 0x6114, 0x2148, 0x080c,
-	0x6e9f, 0x009e, 0x00de, 0x080c, 0xb2d3, 0x080c, 0x9bd3, 0x0005,
-	0x080c, 0x9a61, 0x080c, 0x3250, 0x6114, 0x0096, 0x2148, 0x080c,
-	0xd0d8, 0x0120, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, 0x080c,
-	0xb2d3, 0x080c, 0x9bd3, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040,
-	0x0096, 0x0002, 0x9187, 0x9187, 0x9187, 0x9187, 0x9187, 0x9187,
-	0x9187, 0x9187, 0x9189, 0x9187, 0x9187, 0x9187, 0x91e2, 0x9187,
-	0x9187, 0x9187, 0x9187, 0x9187, 0x9187, 0x9190, 0x9187, 0x080c,
-	0x0dc5, 0x6114, 0x2148, 0xa938, 0x918e, 0xffff, 0x0904, 0x91e2,
-	0x6024, 0xd08c, 0x15d8, 0x080c, 0x8d17, 0x05e0, 0x00e6, 0x6114,
-	0x2148, 0x080c, 0x8f37, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6c3b,
-	0x009e, 0xa8ab, 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058,
-	0x080c, 0x9067, 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c,
-	0x8c6a, 0x00be, 0x01e0, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x01b8,
-	0x9086, 0x0001, 0x1128, 0x2001, 0x1947, 0x2004, 0x9005, 0x1178,
-	0x0096, 0x080c, 0x100e, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6,
-	0x2c78, 0x080c, 0x8c28, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c,
-	0x8c61, 0x0cd0, 0x080c, 0x8d1c, 0x1160, 0x6010, 0x9005, 0x0130,
-	0x2058, 0xb8ac, 0x9005, 0x190c, 0x0dc5, 0x6012, 0x2c00, 0x080c,
-	0x8ce2, 0x0005, 0x080c, 0x9290, 0x009e, 0x0005, 0x9182, 0x0040,
-	0x0096, 0x0002, 0x91fa, 0x91fa, 0x91fa, 0x91fc, 0x91fa, 0x91fa,
-	0x91fa, 0x9221, 0x91fa, 0x91fa, 0x91fa, 0x91fa, 0x91fa, 0x91fa,
-	0x91fa, 0x91fa, 0x080c, 0x0dc5, 0x6003, 0x0003, 0x6106, 0x6014,
-	0x2048, 0xa8ac, 0xa846, 0xa8b0, 0xa84a, 0xa837, 0x0000, 0xa83b,
-	0x0000, 0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003,
-	0x8013, 0x8213, 0x9210, 0x621a, 0x2c10, 0x080c, 0x1be0, 0x080c,
-	0x9564, 0x0126, 0x2091, 0x8000, 0x080c, 0x9bd3, 0x012e, 0x009e,
-	0x0005, 0x080c, 0x0dc5, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114,
-	0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500,
-	0x00be, 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x6000,
-	0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x0013, 0x009e, 0x0005,
-	0x9250, 0x9250, 0x9250, 0x9252, 0x9263, 0x9250, 0x9250, 0x9250,
-	0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250, 0x9250,
-	0x080c, 0x0dc5, 0x080c, 0xac2b, 0x6114, 0x2148, 0xa87b, 0x0006,
-	0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500, 0x00be, 0x080c, 0x6e9f,
-	0x080c, 0xb2d3, 0x0005, 0x0461, 0x0005, 0x6000, 0x908a, 0x0010,
-	0x1a0c, 0x0dc5, 0x0096, 0x0013, 0x009e, 0x0005, 0x927e, 0x927e,
-	0x927e, 0x9280, 0x9290, 0x927e, 0x927e, 0x927e, 0x927e, 0x927e,
-	0x927e, 0x927e, 0x927e, 0x927e, 0x927e, 0x927e, 0x080c, 0x0dc5,
-	0x0036, 0x00e6, 0x2071, 0x19e8, 0x703c, 0x9c06, 0x1120, 0x2019,
-	0x0000, 0x080c, 0xaa49, 0x080c, 0xac2b, 0x00ee, 0x003e, 0x0005,
-	0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, 0x0000, 0x6014,
-	0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c, 0x9067,
-	0x00be, 0x2071, 0x193d, 0x080c, 0x8cb1, 0x0160, 0x2001, 0x187f,
-	0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x8c28, 0x00ee,
-	0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048, 0x080c,
-	0x1040, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8c61, 0x0c80, 0x2001,
-	0x1925, 0x200c, 0x918e, 0x0000, 0x190c, 0x8d17, 0x05c8, 0x00e6,
-	0x2071, 0x1924, 0x7110, 0xc1c5, 0x7112, 0x080c, 0x8d21, 0x00f6,
-	0x00c6, 0x2071, 0x1000, 0x00b6, 0x2e04, 0x905d, 0x0138, 0xb8ac,
-	0x9065, 0x0120, 0x080c, 0x8cf7, 0x090c, 0x9096, 0x8e70, 0x9e86,
-	0x1800, 0x1d90, 0x00be, 0x00d6, 0x0096, 0x0046, 0x2061, 0x1cd0,
-	0x2001, 0x181a, 0x2024, 0x6020, 0x9086, 0x0000, 0x1191, 0x9ce0,
-	0x0018, 0x2400, 0x9c06, 0x1db8, 0x004e, 0x009e, 0x00de, 0x00d1,
-	0x00ce, 0x00fe, 0x2071, 0x1924, 0x7110, 0xc1c4, 0x7112, 0x00ee,
-	0x0005, 0x6020, 0x9086, 0x0009, 0x1160, 0x6100, 0x9186, 0x0004,
-	0x1138, 0x6110, 0x81ff, 0x190c, 0x0dc5, 0x2c00, 0x080c, 0x8ce2,
-	0x9006, 0x0005, 0x2071, 0x193f, 0x2073, 0x0000, 0x8e70, 0x9e86,
-	0x1947, 0x1dd0, 0x2071, 0x193d, 0x7006, 0x7002, 0x2001, 0x1930,
-	0x2064, 0x8cff, 0x0130, 0x6120, 0x918e, 0x0000, 0x190c, 0x0dc5,
-	0x2102, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0148, 0x0096, 0x2148,
-	0x080c, 0x1040, 0x009e, 0x2001, 0x188a, 0x2003, 0x0000, 0x2071,
-	0x1931, 0x080c, 0x8f00, 0x0804, 0x8f0f, 0x0000, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x187a, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091, 0x8000,
-	0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x2019, 0x0100,
-	0x231c, 0x93a6, 0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6,
-	0x3e00, 0x81f6, 0x3e08, 0x1208, 0x9200, 0x1f04, 0x9356, 0x93a6,
-	0x0008, 0x1118, 0x8086, 0x818e, 0x0020, 0x80f6, 0x3e00, 0x81f6,
-	0x3e08, 0x004e, 0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x0076, 0x0156, 0x20a9, 0x0010, 0x9005, 0x0510, 0x911a, 0x1600,
-	0x8213, 0x2039, 0x0100, 0x273c, 0x97be, 0x0008, 0x1110, 0x818d,
-	0x0010, 0x81f5, 0x3e08, 0x0228, 0x911a, 0x1220, 0x1f04, 0x9380,
-	0x0028, 0x911a, 0x2308, 0x8210, 0x1f04, 0x9380, 0x0006, 0x3200,
-	0x9084, 0xefff, 0x2080, 0x000e, 0x015e, 0x007e, 0x012e, 0x0005,
-	0x0006, 0x3200, 0x9085, 0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800,
-	0x2079, 0x19e8, 0x012e, 0x00d6, 0x2069, 0x19e8, 0x6803, 0x0005,
-	0x0156, 0x0146, 0x01d6, 0x20e9, 0x0000, 0x2069, 0x0200, 0x080c,
-	0xaf8e, 0x0401, 0x080c, 0xaf79, 0x00e9, 0x080c, 0xaf7c, 0x00d1,
-	0x080c, 0xaf7f, 0x00b9, 0x080c, 0xaf82, 0x00a1, 0x080c, 0xaf85,
-	0x0089, 0x080c, 0xaf88, 0x0071, 0x080c, 0xaf8b, 0x0059, 0x01de,
-	0x014e, 0x015e, 0x2069, 0x0004, 0x2d04, 0x9085, 0x8001, 0x206a,
-	0x00de, 0x0005, 0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000,
-	0x4004, 0x0005, 0x00c6, 0x6027, 0x0001, 0x7804, 0x9084, 0x0007,
-	0x0002, 0x93f3, 0x9417, 0x9458, 0x93f9, 0x9417, 0x93f3, 0x93f1,
-	0x93f1, 0x080c, 0x0dc5, 0x080c, 0x88c3, 0x080c, 0x9ab1, 0x00ce,
-	0x0005, 0x62c0, 0x82ff, 0x1110, 0x00ce, 0x0005, 0x2011, 0x5f97,
-	0x080c, 0x883d, 0x7828, 0x9092, 0x00c8, 0x1228, 0x8000, 0x782a,
-	0x080c, 0x5fd7, 0x0c88, 0x62c0, 0x080c, 0xb0ca, 0x080c, 0x5f97,
-	0x7807, 0x0003, 0x7827, 0x0000, 0x782b, 0x0000, 0x0c28, 0x080c,
-	0x88c3, 0x6220, 0xd2a4, 0x0170, 0xd2cc, 0x0160, 0x782b, 0x0000,
-	0x7824, 0x9065, 0x090c, 0x0dc5, 0x2009, 0x0013, 0x080c, 0xb352,
-	0x00ce, 0x0005, 0x00c6, 0x7824, 0x9065, 0x090c, 0x0dc5, 0x7828,
-	0x9092, 0xc350, 0x12c0, 0x8000, 0x782a, 0x00ce, 0x080c, 0x2bce,
-	0x0278, 0x00c6, 0x7924, 0x2160, 0x6010, 0x906d, 0x090c, 0x0dc5,
-	0x7807, 0x0000, 0x7827, 0x0000, 0x00ce, 0x080c, 0x9ab1, 0x0c00,
-	0x080c, 0xa6c5, 0x08e8, 0x2011, 0x0130, 0x2214, 0x080c, 0xb0ca,
-	0x080c, 0xf094, 0x2009, 0x0014, 0x080c, 0xb352, 0x00ce, 0x0880,
-	0x2001, 0x1a04, 0x2003, 0x0000, 0x62c0, 0x82ff, 0x1160, 0x782b,
-	0x0000, 0x7824, 0x9065, 0x090c, 0x0dc5, 0x2009, 0x0013, 0x080c,
-	0xb3a4, 0x00ce, 0x0005, 0x00b6, 0x00c6, 0x00d6, 0x7824, 0x9005,
-	0x090c, 0x0dc5, 0x7828, 0x9092, 0xc350, 0x1648, 0x8000, 0x782a,
-	0x00de, 0x00ce, 0x00be, 0x080c, 0x2bce, 0x02f0, 0x00b6, 0x00c6,
-	0x00d6, 0x781c, 0x905d, 0x090c, 0x0dc5, 0xb800, 0xc0dc, 0xb802,
-	0x7924, 0x2160, 0x080c, 0xb2d3, 0xb93c, 0x81ff, 0x090c, 0x0dc5,
-	0x8109, 0xb93e, 0x7807, 0x0000, 0x7827, 0x0000, 0x00de, 0x00ce,
-	0x00be, 0x080c, 0x9ab1, 0x0868, 0x080c, 0xa6c5, 0x0850, 0x2011,
-	0x0130, 0x2214, 0x080c, 0xb0ca, 0x080c, 0xf094, 0x7824, 0x9065,
-	0x2009, 0x0014, 0x080c, 0xb352, 0x00de, 0x00ce, 0x00be, 0x0804,
-	0x9469, 0x00c6, 0x2001, 0x009b, 0x2004, 0xd0fc, 0x190c, 0x1eeb,
-	0x6024, 0x6027, 0x0002, 0xd0f4, 0x15b8, 0x62c8, 0x60c4, 0x9205,
-	0x1170, 0x783c, 0x9065, 0x0130, 0x2009, 0x0049, 0x080c, 0xb352,
-	0x00ce, 0x0005, 0x2011, 0x1a07, 0x2013, 0x0000, 0x0cc8, 0x793c,
-	0x81ff, 0x0dc0, 0x7944, 0x9192, 0x7530, 0x1628, 0x8108, 0x7946,
-	0x793c, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1138, 0x6014,
-	0x9084, 0x1984, 0x9085, 0x0012, 0x6016, 0x0c10, 0x793c, 0x9188,
-	0x0008, 0x210c, 0x918e, 0x0009, 0x0d90, 0x6014, 0x9084, 0x1984,
-	0x9085, 0x0016, 0x6016, 0x08a0, 0x793c, 0x2160, 0x2009, 0x004a,
-	0x080c, 0xb352, 0x0868, 0x7848, 0xc085, 0x784a, 0x0848, 0x0006,
-	0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08,
-	0x2061, 0x19e8, 0x6020, 0x8000, 0x6022, 0x6010, 0x9005, 0x0148,
-	0x9080, 0x0003, 0x2102, 0x6112, 0x012e, 0x00ce, 0x001e, 0x000e,
-	0x0005, 0x6116, 0x6112, 0x0cc0, 0x00d6, 0x2069, 0x19e8, 0xb800,
-	0xd0d4, 0x0168, 0x6820, 0x8000, 0x6822, 0x9086, 0x0001, 0x1110,
-	0x2b00, 0x681e, 0x00de, 0x0804, 0x9ab1, 0x00de, 0x0005, 0xc0d5,
-	0xb802, 0x6818, 0x9005, 0x0168, 0xb856, 0xb85b, 0x0000, 0x0086,
-	0x0006, 0x2b00, 0x681a, 0x008e, 0xa05a, 0x008e, 0x2069, 0x19e8,
-	0x0c08, 0xb856, 0xb85a, 0x2b00, 0x681a, 0x681e, 0x08d8, 0x0006,
-	0x0016, 0x00c6, 0x0126, 0x2091, 0x8000, 0x600f, 0x0000, 0x2c08,
-	0x2061, 0x19e8, 0x6020, 0x8000, 0x6022, 0x6008, 0x9005, 0x0148,
-	0x9080, 0x0003, 0x2102, 0x610a, 0x012e, 0x00ce, 0x001e, 0x000e,
-	0x0005, 0x610e, 0x610a, 0x0cc0, 0x00c6, 0x600f, 0x0000, 0x2c08,
-	0x2061, 0x19e8, 0x6034, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102,
-	0x6136, 0x00ce, 0x0005, 0x613a, 0x6136, 0x00ce, 0x0005, 0x00f6,
-	0x00e6, 0x00d6, 0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056,
-	0x0036, 0x0026, 0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e8,
-	0x7638, 0x2660, 0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x95f3,
-	0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x95ee, 0x87ff, 0x0120,
-	0x6054, 0x9106, 0x1904, 0x95ee, 0x703c, 0x9c06, 0x1178, 0x0036,
-	0x2019, 0x0001, 0x080c, 0xaa49, 0x7033, 0x0000, 0x9006, 0x703e,
-	0x7042, 0x7046, 0x704a, 0x003e, 0x2029, 0x0001, 0x7038, 0x9c36,
-	0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36,
-	0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066,
-	0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000,
-	0x080c, 0xd0d8, 0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003,
-	0x15b8, 0x6004, 0x9086, 0x0040, 0x090c, 0xac1b, 0xa867, 0x0103,
-	0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xd3ce,
-	0x080c, 0xef85, 0x080c, 0x6e9f, 0x007e, 0x003e, 0x001e, 0x080c,
-	0xd2c3, 0x080c, 0xb306, 0x00ce, 0x0804, 0x958d, 0x2c78, 0x600c,
-	0x2060, 0x0804, 0x958d, 0x85ff, 0x0120, 0x0036, 0x080c, 0x9bd3,
-	0x003e, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e,
-	0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005,
-	0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c,
-	0xef85, 0x080c, 0xebd4, 0x007e, 0x003e, 0x001e, 0x0890, 0x6020,
-	0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, 0x0076,
-	0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x007e, 0x003e, 0x001e, 0x0818,
-	0x6020, 0x9086, 0x000a, 0x0904, 0x95d8, 0x0804, 0x95d1, 0x0006,
-	0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091,
-	0x8000, 0x2079, 0x19e8, 0x7838, 0x9065, 0x0904, 0x9684, 0x600c,
-	0x0006, 0x600f, 0x0000, 0x783c, 0x9c06, 0x1168, 0x0036, 0x2019,
-	0x0001, 0x080c, 0xaa49, 0x7833, 0x0000, 0x901e, 0x7b3e, 0x7b42,
-	0x7b46, 0x7b4a, 0x003e, 0x080c, 0xd0d8, 0x0548, 0x6014, 0x2048,
-	0x6020, 0x9086, 0x0003, 0x1590, 0x3e08, 0x918e, 0x0002, 0x1188,
-	0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc,
-	0x0140, 0x6040, 0x9005, 0x11a8, 0x2001, 0x1988, 0x2004, 0x6042,
-	0x0080, 0x6004, 0x9086, 0x0040, 0x090c, 0xac1b, 0xa867, 0x0103,
-	0xab7a, 0xa877, 0x0000, 0x080c, 0x6e92, 0x080c, 0xd2c3, 0x080c,
-	0xb306, 0x000e, 0x0804, 0x963c, 0x7e3a, 0x7e36, 0x012e, 0x00fe,
-	0x00de, 0x00ce, 0x009e, 0x006e, 0x000e, 0x0005, 0x6020, 0x9086,
-	0x0006, 0x1118, 0x080c, 0xebd4, 0x0c50, 0x6020, 0x9086, 0x0009,
-	0x1130, 0xab7a, 0x080c, 0x6e9f, 0x080c, 0xb2d3, 0x0c10, 0x6020,
-	0x9086, 0x000a, 0x09a8, 0x0868, 0x0016, 0x0026, 0x0086, 0x9046,
-	0x0099, 0x080c, 0x978f, 0x008e, 0x002e, 0x001e, 0x0005, 0x00f6,
-	0x0126, 0x2079, 0x19e8, 0x2091, 0x8000, 0x080c, 0x9826, 0x080c,
-	0x98b6, 0x012e, 0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6,
-	0x00d6, 0x00c6, 0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000,
-	0x2071, 0x19e8, 0x7614, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9754,
-	0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x974f, 0x88ff, 0x0120,
-	0x6054, 0x9106, 0x1904, 0x974f, 0x7024, 0x9c06, 0x1568, 0x2069,
-	0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x88c3,
-	0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000,
-	0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001,
-	0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0028, 0x6003,
-	0x0009, 0x630a, 0x0804, 0x974f, 0x7014, 0x9c36, 0x1110, 0x660c,
-	0x7616, 0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00,
-	0x7012, 0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06,
-	0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048,
-	0x080c, 0xd0d8, 0x01e8, 0x6020, 0x9086, 0x0003, 0x1580, 0x080c,
-	0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0098, 0xa867, 0x0103, 0xab7a,
-	0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c, 0xd3ce, 0x080c,
-	0xef85, 0x080c, 0x6e9f, 0x008e, 0x003e, 0x001e, 0x080c, 0xd2c3,
-	0x080c, 0xb306, 0x080c, 0xaaf1, 0x00ce, 0x0804, 0x96cd, 0x2c78,
-	0x600c, 0x2060, 0x0804, 0x96cd, 0x012e, 0x000e, 0x001e, 0x006e,
-	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e, 0x00be, 0x0005, 0x6020,
-	0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0086, 0x080c, 0xef85,
-	0x080c, 0xebd4, 0x008e, 0x003e, 0x001e, 0x08d0, 0x080c, 0xbcb6,
-	0x6020, 0x9086, 0x0002, 0x1160, 0x6004, 0x0006, 0x9086, 0x0085,
-	0x000e, 0x0904, 0x9735, 0x9086, 0x008b, 0x0904, 0x9735, 0x0840,
-	0x6020, 0x9086, 0x0005, 0x1920, 0x6004, 0x0006, 0x9086, 0x0085,
-	0x000e, 0x09c8, 0x9086, 0x008b, 0x09b0, 0x0804, 0x9748, 0x00b6,
-	0x00a6, 0x0096, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x9280,
-	0x1000, 0x2004, 0x905d, 0x0904, 0x981f, 0x00f6, 0x00e6, 0x00d6,
-	0x0066, 0x2071, 0x19e8, 0xbe54, 0x7018, 0x9b06, 0x1108, 0x761a,
-	0x701c, 0x9b06, 0x1130, 0x86ff, 0x1118, 0x7018, 0x701e, 0x0008,
-	0x761e, 0xb858, 0x904d, 0x0108, 0xae56, 0x96d5, 0x0000, 0x0110,
-	0x2900, 0xb05a, 0xb857, 0x0000, 0xb85b, 0x0000, 0xb800, 0xc0d4,
-	0xc0dc, 0xb802, 0x080c, 0x664c, 0x0904, 0x981b, 0x7624, 0x86ff,
-	0x0904, 0x980a, 0x9680, 0x0005, 0x2004, 0x9906, 0x15d8, 0x00d6,
-	0x2069, 0x0100, 0x68c0, 0x9005, 0x0560, 0x080c, 0x88c3, 0x080c,
-	0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036,
-	0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100,
-	0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824,
-	0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6, 0xb83c,
-	0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xb306, 0x00ce,
-	0x0048, 0x00de, 0x00c6, 0x2660, 0x6003, 0x0009, 0x630a, 0x00ce,
-	0x0804, 0x97c2, 0x89ff, 0x0158, 0xa867, 0x0103, 0xab7a, 0xa877,
-	0x0000, 0x080c, 0xd3ce, 0x080c, 0xef85, 0x080c, 0x6e9f, 0x080c,
-	0xaaf1, 0x0804, 0x97c2, 0x006e, 0x00de, 0x00ee, 0x00fe, 0x012e,
-	0x000e, 0x00ce, 0x009e, 0x00ae, 0x00be, 0x0005, 0x0096, 0x0006,
-	0x0066, 0x00c6, 0x00d6, 0x9036, 0x7814, 0x9065, 0x0904, 0x9889,
-	0x600c, 0x0006, 0x600f, 0x0000, 0x7824, 0x9c06, 0x1580, 0x2069,
-	0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x88c3,
-	0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7827, 0x0000,
-	0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001,
-	0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x080c,
-	0x6a3b, 0x1520, 0x6003, 0x0009, 0x630a, 0x2c30, 0x00f8, 0x6014,
-	0x2048, 0x080c, 0xd0d6, 0x01b0, 0x6020, 0x9086, 0x0003, 0x1508,
-	0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0060, 0x080c, 0x6a3b,
-	0x1168, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f,
-	0x080c, 0xd2c3, 0x080c, 0xb306, 0x080c, 0xaaf1, 0x000e, 0x0804,
-	0x982d, 0x7e16, 0x7e12, 0x00de, 0x00ce, 0x006e, 0x000e, 0x009e,
-	0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xebd4, 0x0c50,
-	0x080c, 0xbcb6, 0x6020, 0x9086, 0x0002, 0x1150, 0x6004, 0x0006,
-	0x9086, 0x0085, 0x000e, 0x0990, 0x9086, 0x008b, 0x0978, 0x08d0,
-	0x6020, 0x9086, 0x0005, 0x19b0, 0x6004, 0x0006, 0x9086, 0x0085,
-	0x000e, 0x0d18, 0x9086, 0x008b, 0x0d00, 0x0860, 0x0006, 0x0066,
-	0x0096, 0x00b6, 0x00c6, 0x00d6, 0x7818, 0x905d, 0x0904, 0x9936,
-	0xb854, 0x0006, 0x9006, 0xb856, 0xb85a, 0xb800, 0xc0d4, 0xc0dc,
-	0xb802, 0x080c, 0x664c, 0x0904, 0x9933, 0x7e24, 0x86ff, 0x0904,
-	0x9926, 0x9680, 0x0005, 0x2004, 0x9906, 0x1904, 0x9926, 0x00d6,
-	0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0x991d, 0x080c, 0x88c3,
-	0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7827, 0x0000,
-	0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001,
-	0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x00de, 0x00c6,
-	0x3e08, 0x918e, 0x0002, 0x1168, 0xb800, 0xd0bc, 0x0150, 0x9680,
-	0x0010, 0x200c, 0x81ff, 0x1518, 0x2009, 0x1988, 0x210c, 0x2102,
-	0x00f0, 0xb83c, 0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x600f,
-	0x0000, 0x080c, 0xb306, 0x00ce, 0x0048, 0x00de, 0x00c6, 0x2660,
-	0x6003, 0x0009, 0x630a, 0x00ce, 0x0804, 0x98c9, 0x89ff, 0x0138,
-	0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x080c,
-	0xaaf1, 0x0804, 0x98c9, 0x000e, 0x0804, 0x98bd, 0x781e, 0x781a,
-	0x00de, 0x00ce, 0x00be, 0x009e, 0x006e, 0x000e, 0x0005, 0x00e6,
-	0x00d6, 0x0096, 0x0066, 0xb800, 0xd0dc, 0x01a0, 0xb84c, 0x904d,
-	0x0188, 0xa878, 0x9606, 0x1170, 0x2071, 0x19e8, 0x7024, 0x9035,
-	0x0148, 0x9080, 0x0005, 0x2004, 0x9906, 0x1120, 0xb800, 0xc0dc,
-	0xb802, 0x0029, 0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00f6,
-	0x2079, 0x0100, 0x78c0, 0x9005, 0x1138, 0x00c6, 0x2660, 0x6003,
-	0x0009, 0x630a, 0x00ce, 0x04b8, 0x080c, 0xa6e9, 0x78c3, 0x0000,
-	0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2079, 0x0140, 0x7b04,
-	0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006,
-	0x080c, 0x2d39, 0x2079, 0x0100, 0x7824, 0xd084, 0x0110, 0x7827,
-	0x0001, 0x080c, 0xac1b, 0x003e, 0x080c, 0x664c, 0x00c6, 0xb83c,
-	0x9005, 0x0110, 0x8001, 0xb83e, 0x2660, 0x080c, 0xb2d3, 0x00ce,
-	0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd3ce, 0x080c,
-	0x6e9f, 0x080c, 0xaaf1, 0x00fe, 0x0005, 0x00b6, 0x00e6, 0x00c6,
-	0x2011, 0x0101, 0x2204, 0xc0c4, 0x2012, 0x2001, 0x180c, 0x2014,
-	0xc2e4, 0x2202, 0x2071, 0x19e8, 0x7004, 0x9084, 0x0007, 0x0002,
-	0x99c2, 0x99c6, 0x99e4, 0x9a0d, 0x9a4b, 0x99c2, 0x99dd, 0x99c0,
-	0x080c, 0x0dc5, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x7024, 0x9065,
-	0x0148, 0x7020, 0x8001, 0x7022, 0x600c, 0x9015, 0x0158, 0x7216,
-	0x600f, 0x0000, 0x7007, 0x0000, 0x7027, 0x0000, 0x00ce, 0x00ee,
-	0x00be, 0x0005, 0x7216, 0x7212, 0x0ca8, 0x7007, 0x0000, 0x7027,
-	0x0000, 0x7020, 0x9005, 0x0070, 0x6010, 0x2058, 0x080c, 0x664c,
-	0xb800, 0xc0dc, 0xb802, 0x7007, 0x0000, 0x7027, 0x0000, 0x7020,
-	0x8001, 0x7022, 0x1148, 0x2001, 0x180c, 0x2014, 0xd2ec, 0x1180,
-	0x00ce, 0x00ee, 0x00be, 0x0005, 0xb854, 0x9015, 0x0120, 0x721e,
-	0x080c, 0x9ab1, 0x0ca8, 0x7218, 0x721e, 0x080c, 0x9ab1, 0x0c80,
-	0xc2ec, 0x2202, 0x080c, 0x9bd3, 0x0c58, 0x7024, 0x9065, 0x05b8,
-	0x700c, 0x9c06, 0x1160, 0x080c, 0xaaf1, 0x600c, 0x9015, 0x0120,
-	0x720e, 0x600f, 0x0000, 0x0448, 0x720e, 0x720a, 0x0430, 0x7014,
-	0x9c06, 0x1160, 0x080c, 0xaaf1, 0x600c, 0x9015, 0x0120, 0x7216,
-	0x600f, 0x0000, 0x00d0, 0x7216, 0x7212, 0x00b8, 0x6020, 0x9086,
-	0x0003, 0x1198, 0x6010, 0x2058, 0x080c, 0x664c, 0xb800, 0xc0dc,
-	0xb802, 0x080c, 0xaaf1, 0x701c, 0x9065, 0x0138, 0xb854, 0x9015,
-	0x0110, 0x721e, 0x0010, 0x7218, 0x721e, 0x7027, 0x0000, 0x00ce,
-	0x00ee, 0x00be, 0x0005, 0x7024, 0x9065, 0x0140, 0x080c, 0xaaf1,
-	0x600c, 0x9015, 0x0158, 0x720e, 0x600f, 0x0000, 0x080c, 0xac1b,
-	0x7027, 0x0000, 0x00ce, 0x00ee, 0x00be, 0x0005, 0x720e, 0x720a,
-	0x0ca8, 0x00d6, 0x2069, 0x19e8, 0x6830, 0x9084, 0x0003, 0x0002,
-	0x9a6e, 0x9a70, 0x9a94, 0x9a6c, 0x080c, 0x0dc5, 0x00de, 0x0005,
-	0x00c6, 0x6840, 0x9086, 0x0001, 0x01b8, 0x683c, 0x9065, 0x0130,
-	0x600c, 0x9015, 0x0170, 0x6a3a, 0x600f, 0x0000, 0x6833, 0x0000,
-	0x683f, 0x0000, 0x2011, 0x1a07, 0x2013, 0x0000, 0x00ce, 0x00de,
-	0x0005, 0x683a, 0x6836, 0x0c90, 0x6843, 0x0000, 0x6838, 0x9065,
-	0x0d68, 0x6003, 0x0003, 0x0c50, 0x00c6, 0x9006, 0x6842, 0x6846,
-	0x684a, 0x683c, 0x9065, 0x0160, 0x600c, 0x9015, 0x0130, 0x6a3a,
-	0x600f, 0x0000, 0x683f, 0x0000, 0x0018, 0x683e, 0x683a, 0x6836,
-	0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x200c, 0xc1e5, 0x2102,
-	0x0005, 0x2001, 0x180c, 0x200c, 0xd1ec, 0x0120, 0xc1ec, 0x2102,
-	0x080c, 0x9bd3, 0x2001, 0x19f4, 0x2004, 0x9086, 0x0001, 0x0d58,
-	0x00d6, 0x2069, 0x19e8, 0x6804, 0x9084, 0x0007, 0x0006, 0x9005,
-	0x11c8, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1198, 0x2001,
-	0x197c, 0x2004, 0x9086, 0xaaaa, 0x0168, 0x2001, 0x188b, 0x2004,
-	0xd08c, 0x1118, 0xd084, 0x1118, 0x0028, 0x080c, 0x9bd3, 0x000e,
-	0x00de, 0x0005, 0x000e, 0x0002, 0x9aee, 0x9ba7, 0x9ba7, 0x9ba7,
-	0x9ba7, 0x9ba9, 0x9ba7, 0x9aec, 0x080c, 0x0dc5, 0x6820, 0x9005,
-	0x1110, 0x00de, 0x0005, 0x00c6, 0x680c, 0x9065, 0x01f0, 0x6104,
-	0x918e, 0x0040, 0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028,
-	0x1150, 0x080c, 0x7637, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104,
-	0xc095, 0x200a, 0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000,
-	0x080c, 0x9c7c, 0x00ce, 0x00de, 0x0005, 0x6814, 0x9065, 0x0150,
-	0x6807, 0x0001, 0x6826, 0x682b, 0x0000, 0x080c, 0x9c7c, 0x00ce,
-	0x00de, 0x0005, 0x00b6, 0x00e6, 0x6a1c, 0x92dd, 0x0000, 0x0904,
-	0x9b91, 0xb84c, 0x900d, 0x0118, 0xb888, 0x9005, 0x01a0, 0xb854,
-	0x905d, 0x0120, 0x920e, 0x0904, 0x9b91, 0x0028, 0x6818, 0x920e,
-	0x0904, 0x9b91, 0x2058, 0xb84c, 0x900d, 0x0d88, 0xb888, 0x9005,
-	0x1d70, 0x2b00, 0x681e, 0xbb3c, 0xb838, 0x9302, 0x1e40, 0x080c,
-	0xb2aa, 0x0904, 0x9b91, 0x8318, 0xbb3e, 0x6116, 0x2b10, 0x6212,
-	0x0096, 0x2148, 0xa880, 0x9084, 0x00ff, 0x605e, 0xa883, 0x0000,
-	0xa884, 0x009e, 0x908a, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003,
-	0x801b, 0x831b, 0x9318, 0x631a, 0x6114, 0x0096, 0x2148, 0xa964,
-	0x009e, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0538, 0x00f6, 0x2c78,
-	0x2061, 0x0100, 0xbac0, 0x629a, 0x2069, 0x0200, 0x2071, 0x0240,
-	0x080c, 0xa219, 0x2069, 0x19e8, 0xbb00, 0xc3dd, 0xbb02, 0x6807,
-	0x0002, 0x2f18, 0x6b26, 0x682b, 0x0000, 0x7823, 0x0003, 0x7803,
-	0x0001, 0x7807, 0x0040, 0x00fe, 0x00ee, 0x00be, 0x00ce, 0x00de,
-	0x0005, 0x00ee, 0x00be, 0x00ce, 0x0cd0, 0x6807, 0x0006, 0x2c18,
-	0x6b26, 0x6820, 0x8001, 0x6822, 0x682b, 0x0000, 0x080c, 0x664c,
-	0x080c, 0xb0ea, 0x00ee, 0x00be, 0x00ce, 0x00de, 0x0005, 0x00de,
-	0x0005, 0x00c6, 0x680c, 0x9065, 0x01d8, 0x6104, 0x918e, 0x0040,
-	0x1180, 0x2009, 0x1837, 0x210c, 0x918c, 0x0028, 0x1150, 0x080c,
-	0x7637, 0x0138, 0x0006, 0x2009, 0x188b, 0x2104, 0xc095, 0x200a,
-	0x000e, 0x6807, 0x0004, 0x6826, 0x682b, 0x0000, 0x080c, 0x9c7c,
-	0x00ce, 0x00de, 0x0005, 0x2001, 0x180c, 0x2014, 0xc2ed, 0x2202,
-	0x00de, 0x00fe, 0x0005, 0x00f6, 0x00d6, 0x2069, 0x19e8, 0x6830,
-	0x9086, 0x0000, 0x1570, 0x2001, 0x180c, 0x2014, 0xd2e4, 0x0130,
-	0xc2e4, 0x2202, 0x080c, 0x9ac0, 0x2069, 0x19e8, 0x2001, 0x180c,
-	0x200c, 0xd1c4, 0x1508, 0x6838, 0x907d, 0x01d8, 0x6a04, 0x9296,
-	0x0000, 0x1904, 0x9c70, 0x7920, 0x918e, 0x0009, 0x0568, 0x6833,
-	0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6,
-	0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x1158, 0x012e, 0x080c,
-	0xa546, 0x00de, 0x00fe, 0x0005, 0xc1c4, 0x2102, 0x080c, 0x76e4,
-	0x08d0, 0x012e, 0x6843, 0x0000, 0x7803, 0x0002, 0x780c, 0x9015,
-	0x0140, 0x6a3a, 0x780f, 0x0000, 0x6833, 0x0000, 0x683f, 0x0000,
-	0x0c40, 0x683a, 0x6836, 0x0cc0, 0x7908, 0xd1fc, 0x1198, 0x6833,
-	0x0001, 0x683e, 0x6847, 0x0000, 0x684b, 0x0000, 0x0126, 0x00f6,
-	0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x19d8, 0x012e, 0x080c,
-	0xa4c7, 0x0878, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1188,
-	0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x0158, 0x2001, 0x19e9,
-	0x2004, 0x9005, 0x11f0, 0x2001, 0x188b, 0x200c, 0xc185, 0xc18c,
-	0x2102, 0x2f00, 0x6833, 0x0001, 0x683e, 0x6847, 0x0000, 0x684b,
-	0x0000, 0x0126, 0x00f6, 0x2091, 0x2400, 0x002e, 0x080c, 0x1c79,
-	0x1904, 0x9c11, 0x012e, 0x6a3c, 0x2278, 0x080c, 0xa451, 0x0804,
-	0x9c09, 0x2011, 0x188b, 0x2204, 0xc08d, 0x2012, 0x0804, 0x9c09,
-	0x6a04, 0x9296, 0x0006, 0x1904, 0x9bcb, 0x6a30, 0x9296, 0x0000,
-	0x0904, 0x9bf3, 0x0804, 0x9bcb, 0x6020, 0x9084, 0x000f, 0x000b,
-	0x0005, 0x9c90, 0x9c95, 0xa149, 0xa1e2, 0x9c95, 0xa149, 0xa1e2,
-	0x9c90, 0x9c95, 0x9c90, 0x9c90, 0x9c90, 0x9c90, 0x9c90, 0x9c90,
-	0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0005, 0x00b6, 0x0156, 0x0136,
-	0x0146, 0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069,
-	0x0200, 0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dc5,
-	0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a,
-	0x0040, 0x1a04, 0x9d01, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce,
-	0x01de, 0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9eaa,
-	0x9ee5, 0x9f0e, 0x9fd8, 0x9ffa, 0xa000, 0xa00d, 0xa015, 0xa021,
-	0xa027, 0xa038, 0xa027, 0xa090, 0xa015, 0xa09c, 0xa0a2, 0xa021,
-	0xa0a2, 0xa0ae, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff,
-	0x9cff, 0x9cff, 0x9cff, 0x9cff, 0x9cff, 0xa900, 0xa923, 0xa934,
-	0xa954, 0xa986, 0xa00d, 0x9cff, 0xa00d, 0xa027, 0x9cff, 0x9f0e,
-	0x9fd8, 0x9cff, 0xad12, 0xa027, 0x9cff, 0xad2e, 0xa027, 0x9cff,
-	0xa021, 0x9ea4, 0x9d22, 0x9cff, 0xad4a, 0xadb7, 0xae92, 0x9cff,
-	0xae9f, 0xa00a, 0xaeca, 0x9cff, 0xa990, 0xaef7, 0x9cff, 0x080c,
-	0x0dc5, 0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de,
-	0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xaf92, 0xb044,
-	0x9d20, 0x9d5a, 0x9e06, 0x9e11, 0x9d20, 0xa00d, 0x9d20, 0x9e6b,
-	0x9e77, 0x9d75, 0x9d20, 0x9d90, 0x9dc4, 0xb1b1, 0xb1f6, 0xa027,
-	0x080c, 0x0dc5, 0x00d6, 0x0096, 0x080c, 0xa0c1, 0x0026, 0x0036,
-	0x7814, 0x2048, 0xa958, 0xd1cc, 0x1138, 0x2009, 0x2414, 0x2011,
-	0x0018, 0x2019, 0x0018, 0x0030, 0x2009, 0x2410, 0x2011, 0x0014,
-	0x2019, 0x0014, 0x7102, 0x7206, 0x700b, 0x0800, 0xa83c, 0x700e,
-	0xa850, 0x7022, 0xa854, 0x7026, 0x63c2, 0x080c, 0xa6bd, 0x003e,
-	0x002e, 0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0,
-	0x00be, 0x080c, 0xb23d, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085,
-	0x0001, 0x0005, 0x00d6, 0x0096, 0x080c, 0xa0c1, 0x7003, 0x0500,
-	0x7814, 0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012,
-	0xa880, 0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010,
-	0x080c, 0xa6bd, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c,
-	0xa0c1, 0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0,
-	0x700e, 0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0,
-	0x701e, 0x60c3, 0x0010, 0x080c, 0xa6bd, 0x009e, 0x00de, 0x0005,
-	0x00d6, 0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0xa0c1, 0x20e9,
-	0x0000, 0x2001, 0x19a4, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814,
-	0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080,
-	0x001b, 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x2001, 0x0001,
-	0x080c, 0x23ee, 0x080c, 0xde7c, 0x9006, 0x080c, 0x23ee, 0x001e,
-	0xa804, 0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa6bd,
-	0x012e, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091,
-	0x8000, 0x080c, 0xa10c, 0x20e9, 0x0000, 0x2001, 0x19a4, 0x2003,
-	0x0000, 0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814,
-	0x8003, 0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080,
-	0x001b, 0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x080c, 0xde7c,
-	0x001e, 0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814,
-	0x2048, 0x080c, 0x0fc0, 0x080c, 0xa6bd, 0x012e, 0x009e, 0x00de,
-	0x0005, 0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082,
-	0x0004, 0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0xa0c1,
-	0x7003, 0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804,
-	0xa6bd, 0x00d6, 0x00e6, 0x080c, 0xa10c, 0x7814, 0x9084, 0xff00,
-	0x2073, 0x0200, 0x8e70, 0x8e70, 0x9096, 0xdf00, 0x0138, 0x9096,
-	0xe000, 0x0120, 0x2073, 0x0010, 0x8e70, 0x0030, 0x9095, 0x0010,
-	0x2272, 0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9,
-	0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9e31, 0x2069, 0x1801,
-	0x20a9, 0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9e3a, 0x9096,
-	0xdf00, 0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0,
-	0x2069, 0x19b4, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19ce, 0x20a9,
-	0x001a, 0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010,
-	0x8000, 0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072,
-	0x8d68, 0x8e70, 0x1f04, 0x9e51, 0x60c3, 0x004c, 0x080c, 0xa6bd,
-	0x00ee, 0x00de, 0x0005, 0x080c, 0xa0c1, 0x7003, 0x6300, 0x7007,
-	0x0028, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x00d6,
-	0x0026, 0x0016, 0x080c, 0xa10c, 0x7003, 0x0200, 0x7814, 0x700e,
-	0x00e6, 0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2069,
-	0x1924, 0x6810, 0xd084, 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073,
-	0x0000, 0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70,
-	0x2073, 0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0xa6bd,
-	0x001e, 0x002e, 0x00de, 0x0005, 0x2001, 0x1818, 0x2004, 0x609a,
-	0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x5200, 0x2069, 0x1847,
-	0x6804, 0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x28a6, 0x710e,
-	0x001e, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9,
-	0x0000, 0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801,
-	0x20a1, 0x0254, 0x4003, 0x080c, 0xb23d, 0x1120, 0xb8a0, 0x9082,
-	0x007f, 0x0248, 0x2001, 0x181f, 0x2004, 0x7032, 0x2001, 0x1820,
-	0x2004, 0x7036, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff,
-	0x7036, 0x60c3, 0x001c, 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003,
-	0x0500, 0x080c, 0xb23d, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248,
-	0x2001, 0x181f, 0x2004, 0x700a, 0x2001, 0x1820, 0x2004, 0x700e,
-	0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9,
-	0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1,
-	0x0250, 0x4003, 0x60c3, 0x0010, 0x0804, 0xa6bd, 0x080c, 0xa0c1,
-	0x9006, 0x080c, 0x6a6d, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2011,
-	0x0240, 0x2013, 0x22ff, 0x2011, 0x0241, 0x2013, 0xfffe, 0x7003,
-	0x0400, 0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, 0x904d,
-	0x0120, 0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300,
-	0xb8a0, 0x9086, 0x007e, 0x1904, 0x9f98, 0x00d6, 0x2069, 0x196c,
-	0x2001, 0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808,
-	0x9084, 0x2000, 0x7012, 0x080c, 0xb254, 0x680c, 0x7016, 0x701f,
-	0x2710, 0x6818, 0x7022, 0x681c, 0x7026, 0x0428, 0x6800, 0x700a,
-	0x6804, 0x700e, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0110, 0x2001,
-	0x0002, 0x00f6, 0x2079, 0x0100, 0x080c, 0x7637, 0x1128, 0x78e3,
-	0x0000, 0x080c, 0x28e7, 0x78e2, 0x00fe, 0x6808, 0x080c, 0x7637,
-	0x1118, 0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c,
-	0xb254, 0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001,
-	0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9,
-	0x0004, 0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c,
-	0xaf79, 0x2069, 0x1974, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002,
-	0x080c, 0x57d9, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04e0,
-	0x2001, 0x1837, 0x2004, 0xd0a4, 0x01a8, 0x0016, 0x2001, 0x180d,
-	0x2004, 0xd08c, 0x2009, 0x0002, 0x1118, 0x2001, 0x196d, 0x200c,
-	0x60e0, 0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x28e7,
-	0x61e2, 0x001e, 0x20e1, 0x0001, 0x2099, 0x196c, 0x20e9, 0x0000,
-	0x20a1, 0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099,
-	0x1805, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801,
-	0x20a1, 0x025a, 0x4003, 0x080c, 0xaf79, 0x20a1, 0x024e, 0x20a9,
-	0x0008, 0x2099, 0x1974, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa6bd,
-	0x080c, 0xa0c1, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800,
-	0x700f, 0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe,
-	0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010,
-	0x9085, 0x0002, 0x00d6, 0x0804, 0xa071, 0x7026, 0x60c3, 0x0014,
-	0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x5000, 0x0804, 0x9f30,
-	0x080c, 0xa0c1, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014,
-	0x0804, 0xa6bd, 0x080c, 0xa103, 0x0010, 0x080c, 0xa10c, 0x7003,
-	0x0200, 0x60c3, 0x0004, 0x0804, 0xa6bd, 0x080c, 0xa10c, 0x7003,
-	0x0100, 0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804,
-	0xa6bd, 0x080c, 0xa10c, 0x7003, 0x0200, 0x0804, 0x9f30, 0x080c,
-	0xa10c, 0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010,
-	0x700b, 0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd,
-	0x00d6, 0x080c, 0xa10c, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b,
-	0x0800, 0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030,
-	0x0190, 0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f,
-	0x2100, 0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028,
-	0x700f, 0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1847,
-	0x7904, 0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110,
-	0x9085, 0x0010, 0x2009, 0x1869, 0x210c, 0xd184, 0x1110, 0x9085,
-	0x0002, 0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, 0x0150, 0xc0c5,
-	0xbacc, 0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010,
-	0x0140, 0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108,
-	0xc0bd, 0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0xa6bd,
-	0x080c, 0xa10c, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100,
-	0x60c3, 0x0014, 0x0804, 0xa6bd, 0x080c, 0xa10c, 0x7003, 0x0200,
-	0x0804, 0x9eae, 0x080c, 0xa10c, 0x7003, 0x0100, 0x700b, 0x0003,
-	0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x080c, 0xa10c,
-	0x7003, 0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa6bd,
-	0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800,
-	0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021,
-	0x0100, 0x080c, 0xaf8e, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006,
-	0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029,
-	0x7012, 0x004e, 0x003e, 0x00de, 0x080c, 0xa6ab, 0x721a, 0x9f95,
-	0x0000, 0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005,
-	0x0026, 0x080c, 0xaf8e, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6,
-	0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x00de, 0x7013,
-	0x2029, 0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02,
-	0x700f, 0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019,
-	0x3300, 0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046,
-	0x2019, 0x2300, 0x2021, 0x0100, 0x080c, 0xaf8e, 0xb810, 0x9305,
-	0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140,
-	0xb814, 0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020,
-	0x687c, 0x700a, 0x6880, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012,
-	0x004e, 0x003e, 0x00de, 0x080c, 0xa6ab, 0x721a, 0x7a08, 0x7222,
-	0x2f10, 0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa6ab,
-	0x721a, 0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e,
-	0x0005, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200,
-	0x2071, 0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a,
-	0x0092, 0x1a0c, 0x0dc5, 0x6110, 0x2158, 0xb9c0, 0x2c78, 0x2061,
-	0x0100, 0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de,
-	0x00ce, 0x00be, 0x0005, 0xa17a, 0xa189, 0xa194, 0xa178, 0xa178,
-	0xa178, 0xa17a, 0xa178, 0xa178, 0xa178, 0xa178, 0xa178, 0xa178,
-	0x080c, 0x0dc5, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2bce,
-	0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804,
-	0xa6bd, 0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff,
-	0x60c3, 0x000c, 0x0804, 0xa6bd, 0x04a1, 0x7003, 0x0003, 0x7007,
-	0x0300, 0x60c3, 0x0004, 0x0804, 0xa6bd, 0x0026, 0x080c, 0xaf8e,
-	0xb810, 0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800,
-	0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0xa0dc,
-	0x0026, 0x080c, 0xaf8e, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814,
-	0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001,
-	0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804,
-	0xa13e, 0x0026, 0x080c, 0xaf8e, 0xb810, 0x9085, 0x8500, 0x7002,
-	0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e,
-	0x2001, 0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012,
-	0x0804, 0xa13e, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78,
-	0x2069, 0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c,
-	0x0dc5, 0x908a, 0x0054, 0x1a0c, 0x0dc5, 0x7910, 0x2158, 0xb9c0,
-	0x2061, 0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee,
-	0x00de, 0x00ce, 0x00be, 0x0005, 0xa219, 0xa2e0, 0xa2b3, 0xa402,
-	0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xa217, 0xaad8,
-	0xaadd, 0xaae2, 0xaae7, 0xa217, 0xaed6, 0xa217, 0xaad3, 0x080c,
-	0x0dc5, 0x0096, 0x780b, 0xffff, 0x080c, 0xa284, 0x7914, 0x2148,
-	0xa978, 0x7956, 0xae64, 0x96b4, 0x00ff, 0x9686, 0x0008, 0x1148,
-	0xa8b4, 0x7032, 0xa8b8, 0x7036, 0xa8bc, 0x703a, 0xa8c0, 0x703e,
-	0x0008, 0x7132, 0xa97c, 0x9184, 0x000f, 0x1118, 0x2001, 0x0005,
-	0x0040, 0xd184, 0x0118, 0x2001, 0x0004, 0x0018, 0x9084, 0x0006,
-	0x8004, 0x2010, 0x785c, 0x9084, 0x00ff, 0x8007, 0x9205, 0x7042,
-	0xd1ac, 0x0158, 0x7047, 0x0002, 0x9686, 0x0008, 0x1118, 0x080c,
-	0x18f7, 0x0010, 0x080c, 0x1768, 0x0050, 0xd1b4, 0x0118, 0x7047,
-	0x0001, 0x0028, 0x7047, 0x0000, 0x9016, 0x2230, 0x0010, 0xaab0,
-	0xaeac, 0x726a, 0x766e, 0x20a9, 0x0008, 0x20e9, 0x0000, 0xa860,
-	0x20e0, 0xa85c, 0x9080, 0x0023, 0x2098, 0x20a1, 0x0252, 0x2069,
-	0x0200, 0x6813, 0x0018, 0x4003, 0x6813, 0x0008, 0x60c3, 0x0020,
-	0x6017, 0x0009, 0x2001, 0x1a04, 0x2003, 0x07d0, 0x2001, 0x1a03,
-	0x2003, 0x0009, 0x009e, 0x0005, 0x6813, 0x0008, 0xba8c, 0x8210,
-	0xb8cc, 0xd084, 0x0180, 0x2001, 0x1ad0, 0x200c, 0x8108, 0x2102,
-	0x2001, 0x1acf, 0x201c, 0x1218, 0x8318, 0x2302, 0x0ea0, 0x794a,
-	0x712e, 0x7b46, 0x732a, 0x9294, 0x00ff, 0xba8e, 0x8217, 0x721a,
-	0xba10, 0x9295, 0x0600, 0x7202, 0xba14, 0x7206, 0x2069, 0x1800,
-	0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0829, 0x2f10, 0x7222,
-	0x7027, 0xffff, 0x0005, 0x00d6, 0x0096, 0x0081, 0x7814, 0x2048,
-	0xa890, 0x7002, 0xa88c, 0x7006, 0xa8b0, 0x700a, 0xa8ac, 0x700e,
-	0x60c3, 0x000c, 0x009e, 0x00de, 0x0804, 0xa6bd, 0x6813, 0x0008,
-	0xb810, 0x9085, 0x0500, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800,
-	0x687c, 0x700a, 0x6880, 0x700e, 0x7013, 0x0889, 0x080c, 0xa6ab,
-	0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x0005,
-	0x00d6, 0x0096, 0x080c, 0xa3e0, 0x7814, 0x2048, 0x080c, 0xd0d6,
-	0x1130, 0x7814, 0x9084, 0x0700, 0x8007, 0x0033, 0x0010, 0x9006,
-	0x001b, 0x009e, 0x00de, 0x0005, 0xa2fe, 0xa367, 0xa377, 0xa39d,
-	0xa3a9, 0xa3ba, 0xa3c2, 0xa2fc, 0x080c, 0x0dc5, 0x0016, 0x0036,
-	0xa97c, 0x918c, 0x0003, 0x0118, 0x9186, 0x0003, 0x1198, 0xaba8,
-	0x7824, 0xd0cc, 0x1168, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e,
-	0x003e, 0x001e, 0x2001, 0x19b2, 0x2004, 0x60c2, 0x0804, 0xa6bd,
-	0xc3e5, 0x0c88, 0x9186, 0x0001, 0x190c, 0x0dc5, 0xaba8, 0x7824,
-	0xd0cc, 0x1904, 0xa364, 0x7316, 0xa898, 0x701a, 0xa894, 0x701e,
-	0xa8a4, 0x7026, 0xa8ac, 0x702e, 0x2009, 0x0018, 0x9384, 0x0300,
-	0x0570, 0xd3c4, 0x0110, 0xa8ac, 0x9108, 0xd3cc, 0x0110, 0xa8a4,
-	0x9108, 0x6810, 0x9085, 0x0010, 0x6812, 0x2011, 0x0258, 0x20e9,
-	0x0000, 0x22a0, 0x0156, 0x20a9, 0x0008, 0xa860, 0x20e0, 0xa85c,
-	0x9080, 0x002c, 0x2098, 0x4003, 0x6810, 0x8000, 0x6812, 0x2011,
-	0x0240, 0x22a0, 0x20a9, 0x0005, 0x4003, 0x6810, 0xc0a4, 0x6812,
-	0x015e, 0x9184, 0x0003, 0x0118, 0x2019, 0x0245, 0x201a, 0x61c2,
-	0x003e, 0x001e, 0x0804, 0xa6bd, 0xc3e5, 0x0804, 0xa323, 0x2011,
-	0x0008, 0x2001, 0x180f, 0x2004, 0xd0a4, 0x0110, 0x2011, 0x0028,
-	0x7824, 0xd0cc, 0x1110, 0x7216, 0x0470, 0x0ce8, 0xc2e5, 0x2011,
-	0x0302, 0x0016, 0x782c, 0x701a, 0x7930, 0x711e, 0x9105, 0x0108,
-	0xc2dd, 0x001e, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216, 0x7027,
-	0x0012, 0x702f, 0x0008, 0x7043, 0x7000, 0x7047, 0x0500, 0x704f,
-	0x000a, 0x2069, 0x0200, 0x6813, 0x0009, 0x2071, 0x0240, 0x700b,
-	0x2500, 0x60c3, 0x0032, 0x0804, 0xa6bd, 0x2011, 0x0028, 0x7824,
-	0xd0cc, 0x1128, 0x7216, 0x60c3, 0x0018, 0x0804, 0xa6bd, 0x0cd0,
-	0xc2e5, 0x2011, 0x0100, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216,
-	0x702f, 0x0008, 0x7858, 0x9084, 0x00ff, 0x7036, 0x60c3, 0x0020,
-	0x0804, 0xa6bd, 0x2011, 0x0008, 0x7824, 0xd0cc, 0x0108, 0xc2e5,
-	0x7216, 0x0c08, 0x0036, 0x7b14, 0x9384, 0xff00, 0x7816, 0x9384,
-	0x00ff, 0x8001, 0x1138, 0x7824, 0xd0cc, 0x0108, 0xc2e5, 0x7216,
-	0x003e, 0x0888, 0x0046, 0x2021, 0x0800, 0x0006, 0x7824, 0xd0cc,
-	0x000e, 0x0108, 0xc4e5, 0x7416, 0x004e, 0x701e, 0x003e, 0x0818,
-	0x00d6, 0x6813, 0x0008, 0xb810, 0x9085, 0x0700, 0x7002, 0xb814,
-	0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x7824,
-	0xd0cc, 0x1168, 0x7013, 0x0898, 0x080c, 0xa6ab, 0x721a, 0x7a08,
-	0x7222, 0x2f10, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x7013,
-	0x0889, 0x0c90, 0x0016, 0x7814, 0x9084, 0x0700, 0x8007, 0x0013,
-	0x001e, 0x0005, 0xa412, 0xa412, 0xa414, 0xa412, 0xa412, 0xa412,
-	0xa42e, 0xa412, 0x080c, 0x0dc5, 0x7914, 0x918c, 0x08ff, 0x918d,
-	0xf600, 0x7916, 0x2009, 0x0003, 0x00b9, 0x2069, 0x1847, 0x6804,
-	0xd0bc, 0x0130, 0x682c, 0x9084, 0x00ff, 0x8007, 0x7032, 0x0010,
-	0x7033, 0x3f00, 0x60c3, 0x0001, 0x0804, 0xa6bd, 0x2009, 0x0003,
-	0x0019, 0x7033, 0x7f00, 0x0cb0, 0x0016, 0x080c, 0xaf8e, 0x001e,
-	0xb810, 0x9085, 0x0100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800,
-	0x6a7c, 0x720a, 0x6a80, 0x720e, 0x7013, 0x0888, 0x918d, 0x0008,
-	0x7116, 0x080c, 0xa6ab, 0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226,
-	0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046,
-	0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058,
-	0x76dc, 0x96b4, 0x0028, 0x0110, 0x737c, 0x7480, 0x2500, 0x76dc,
-	0x96b4, 0x0028, 0x0140, 0x2001, 0x04ff, 0x6062, 0x6067, 0xffff,
-	0x636a, 0x646e, 0x0050, 0x2001, 0x00ff, 0x9085, 0x0400, 0x6062,
-	0x6067, 0xffff, 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6073, 0x0530,
-	0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007,
-	0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082, 0x6087,
-	0xffff, 0x7814, 0x0096, 0x2048, 0xa838, 0x608a, 0xa834, 0x608e,
-	0xa848, 0x60c6, 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab,
-	0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x2001, 0x1837, 0x2004,
-	0x9084, 0x0028, 0x0128, 0x609f, 0x0000, 0x2001, 0x0092, 0x0048,
-	0x6028, 0xc0bd, 0x602a, 0x609f, 0x00ff, 0x6027, 0xffff, 0x2001,
-	0x00b2, 0x6016, 0x2009, 0x07d0, 0x080c, 0x88c8, 0x003e, 0x004e,
-	0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6,
-	0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061,
-	0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0xb8a0, 0x2028,
-	0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250, 0x2500, 0x9094,
-	0xff80, 0x1130, 0x9080, 0x33b6, 0x2015, 0x9294, 0x00ff, 0x0020,
-	0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac, 0x1130, 0x9582,
-	0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185, 0x0400, 0x6062,
-	0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400, 0x6266, 0x606b,
-	0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000, 0xb864, 0xd0a4,
-	0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e,
-	0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000, 0x2b00, 0x6082,
-	0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa838, 0x608a, 0xa834,
-	0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca, 0x009e, 0xb86c, 0x60ce,
-	0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e,
-	0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe, 0x2009, 0x0092,
-	0x6116, 0x2009, 0x07d0, 0x080c, 0x88c8, 0x003e, 0x004e, 0x005e,
-	0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005, 0x00b6, 0x0096,
-	0x00e6, 0x00d6, 0x00c6, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100,
-	0x2071, 0x1800, 0x7810, 0x2058, 0xb8a0, 0x2028, 0xb910, 0xba14,
-	0x737c, 0x7480, 0x7820, 0x90be, 0x0006, 0x0904, 0xa61a, 0x90be,
-	0x000a, 0x1904, 0xa5d6, 0xb8c0, 0x609e, 0x7814, 0x2048, 0xa87c,
-	0xd0fc, 0x0558, 0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f,
-	0x9784, 0xff00, 0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005,
-	0x000e, 0x1160, 0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705,
-	0x6072, 0x7808, 0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200,
-	0x6062, 0x6073, 0x0129, 0x6077, 0x0000, 0xb8c0, 0x609e, 0x0050,
-	0x2039, 0x0029, 0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062,
-	0x6073, 0x2029, 0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120,
-	0x2f00, 0x6082, 0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077,
-	0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a,
-	0x607f, 0x0000, 0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6,
-	0xa844, 0x60ca, 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0x080c, 0xaf73, 0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005,
-	0x0110, 0x2009, 0x1b58, 0x080c, 0x88c8, 0x003e, 0x004e, 0x005e,
-	0x00ce, 0x00de, 0x00ee, 0x009e, 0x00be, 0x0005, 0x7804, 0x9086,
-	0x0040, 0x0904, 0xa656, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a,
-	0x646e, 0x6073, 0x0809, 0x6077, 0x0008, 0x60af, 0x95d5, 0x60d7,
-	0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a,
-	0x607f, 0x0000, 0x2f00, 0x6082, 0x7808, 0x6086, 0x7814, 0x2048,
-	0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca,
-	0xb86c, 0x60ce, 0xbac0, 0x629e, 0x080c, 0xaf73, 0x2009, 0x07d0,
-	0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009, 0x1b58, 0x080c,
-	0x88c8, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x009e,
-	0x00be, 0x0005, 0x7814, 0x2048, 0xa87c, 0x9084, 0x0003, 0x9086,
-	0x0002, 0x0904, 0xa672, 0x9185, 0x0100, 0x6062, 0x6266, 0x636a,
-	0x646e, 0x6073, 0x0880, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084,
-	0x00ff, 0xb88e, 0x8007, 0x607a, 0x7838, 0x607e, 0x2f00, 0x6086,
-	0x7808, 0x6082, 0xa890, 0x608a, 0xa88c, 0x608e, 0xa8b0, 0x60c6,
-	0xa8ac, 0x60ca, 0xa8ac, 0x7930, 0x9108, 0x7932, 0xa8b0, 0x792c,
-	0x9109, 0x792e, 0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0xbac0, 0x629e, 0x080c, 0xaf50, 0x0804, 0xa606, 0xb8cc, 0xd084,
-	0x0148, 0xb88c, 0x7814, 0x2048, 0xb88c, 0x784a, 0xa836, 0x2900,
-	0xa83a, 0xb046, 0x9185, 0x0600, 0x6062, 0x6266, 0x636a, 0x646e,
-	0x6073, 0x0829, 0x6077, 0x0000, 0x60af, 0x9575, 0x60d7, 0x0000,
-	0x0804, 0xa5e9, 0x9185, 0x0700, 0x6062, 0x6266, 0x636a, 0x646e,
-	0x7824, 0xd0cc, 0x7826, 0x0118, 0x6073, 0x0889, 0x0010, 0x6073,
-	0x0898, 0x6077, 0x0000, 0xb88c, 0x8000, 0x9084, 0x00ff, 0xb88e,
-	0x8007, 0x607a, 0x607f, 0x0000, 0x2f00, 0x6086, 0x7808, 0x6082,
-	0xa838, 0x608a, 0xa834, 0x608e, 0xa848, 0x60c6, 0xa844, 0x60ca,
-	0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0xbac0, 0x629e,
-	0x7824, 0xd0cc, 0x0120, 0x080c, 0xaf73, 0x0804, 0xa606, 0x080c,
-	0xaf50, 0x0804, 0xa606, 0x7a10, 0x00b6, 0x2258, 0xba8c, 0x8210,
-	0x9294, 0x00ff, 0xba8e, 0x00be, 0x8217, 0x0005, 0x00d6, 0x2069,
-	0x19e8, 0x6843, 0x0001, 0x00de, 0x0005, 0x60a3, 0x0056, 0x60a7,
-	0x9575, 0x00f1, 0x080c, 0x88ba, 0x0005, 0x0016, 0x2001, 0x180c,
-	0x200c, 0x9184, 0x0600, 0x9086, 0x0600, 0x0128, 0x0089, 0x080c,
-	0x88ba, 0x001e, 0x0005, 0xc1e5, 0x2001, 0x180c, 0x2102, 0x2001,
-	0x19e9, 0x2003, 0x0000, 0x2001, 0x19f1, 0x2003, 0x0000, 0x0c88,
-	0x0006, 0x6014, 0x9084, 0x1804, 0x9085, 0x0009, 0x6016, 0x000e,
-	0x0005, 0x0016, 0x00c6, 0x0006, 0x2061, 0x0100, 0x61a4, 0x60a7,
-	0x95f5, 0x6014, 0x9084, 0x1804, 0x9085, 0x0008, 0x6016, 0x000e,
-	0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005, 0x00c6,
-	0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c,
-	0x7637, 0x11c0, 0x2001, 0x1a04, 0x2004, 0x9005, 0x15d0, 0x080c,
-	0x76e4, 0x1160, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120, 0x6024,
-	0xd084, 0x090c, 0x0dc5, 0x080c, 0x88ba, 0x0458, 0x00c6, 0x2061,
-	0x19e8, 0x00c8, 0x6904, 0x9194, 0x4000, 0x0540, 0x0811, 0x080c,
-	0x2d49, 0x00c6, 0x2061, 0x19e8, 0x6128, 0x9192, 0x0008, 0x1258,
-	0x8108, 0x612a, 0x6124, 0x00ce, 0x81ff, 0x0198, 0x080c, 0x88ba,
-	0x080c, 0xa6e0, 0x0070, 0x6124, 0x91e5, 0x0000, 0x0140, 0x080c,
-	0xf094, 0x080c, 0x88c3, 0x2009, 0x0014, 0x080c, 0xb352, 0x00ce,
-	0x0000, 0x002e, 0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a04,
-	0x2004, 0x9005, 0x1db0, 0x00c6, 0x2061, 0x19e8, 0x6128, 0x9192,
-	0x0003, 0x1e08, 0x8108, 0x612a, 0x00ce, 0x080c, 0x88ba, 0x080c,
-	0x5fed, 0x2009, 0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096,
-	0x00c6, 0x00d6, 0x00e6, 0x0016, 0x0026, 0x080c, 0x88d0, 0x2071,
-	0x19e8, 0x713c, 0x81ff, 0x0904, 0xa7e9, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x080c, 0x7637, 0x11e0, 0x0036, 0x2019, 0x0002, 0x080c,
-	0xaa49, 0x003e, 0x713c, 0x2160, 0x080c, 0xf094, 0x2009, 0x004a,
-	0x6220, 0x9296, 0x0009, 0x1130, 0x6114, 0x2148, 0xa87b, 0x0006,
-	0x2009, 0x004a, 0x080c, 0xb352, 0x080c, 0x76e4, 0x0804, 0xa7e9,
-	0x080c, 0xa7f5, 0x0904, 0xa7e9, 0x6904, 0xd1f4, 0x0904, 0xa7f0,
-	0x080c, 0x2d49, 0x00c6, 0x703c, 0x9065, 0x090c, 0x0dc5, 0x6020,
-	0x00ce, 0x9086, 0x0006, 0x1528, 0x61c8, 0x60c4, 0x9105, 0x1508,
-	0x2009, 0x180c, 0x2104, 0xd0d4, 0x01e0, 0x6214, 0x9294, 0x1800,
-	0x1128, 0x6224, 0x9294, 0x0002, 0x1560, 0x0030, 0xc0d4, 0x200a,
-	0xd0cc, 0x0110, 0x080c, 0x2c7b, 0x6014, 0x9084, 0xe7fd, 0x9085,
-	0x0010, 0x6016, 0x703c, 0x2060, 0x2009, 0x0049, 0x080c, 0xb352,
-	0x00c0, 0x0036, 0x2019, 0x0001, 0x080c, 0xaa49, 0x003e, 0x713c,
-	0x2160, 0x080c, 0xf094, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009,
-	0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x080c,
-	0xb352, 0x002e, 0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005,
-	0xd1ec, 0x1904, 0xa7a0, 0x0804, 0xa7a2, 0x00d6, 0x00c6, 0x0096,
-	0x703c, 0x9065, 0x090c, 0x0dc5, 0x2001, 0x0306, 0x200c, 0x9184,
-	0x0030, 0x0904, 0xa8a8, 0x9184, 0x0048, 0x9086, 0x0008, 0x1904,
-	0xa8a8, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106,
-	0x1904, 0xa8a8, 0x2009, 0x022a, 0x2104, 0x2009, 0x022f, 0x210c,
-	0x9116, 0x9084, 0x03ff, 0x918c, 0x03ff, 0x9294, 0x0400, 0x0110,
-	0x9102, 0x0030, 0x2010, 0x2100, 0x9202, 0x2009, 0x0228, 0x9102,
-	0x9082, 0x0005, 0x0250, 0x2008, 0x2001, 0x013b, 0x2004, 0x8004,
-	0x8004, 0x8004, 0x9102, 0x1a04, 0xa8a8, 0x2009, 0x1a84, 0x2104,
-	0x8000, 0x0208, 0x200a, 0x2069, 0x0100, 0x6914, 0x918c, 0x1984,
-	0x918d, 0x0010, 0x6916, 0x69c8, 0x2011, 0x0020, 0x68c8, 0x9106,
-	0x15c0, 0x8211, 0x1dd8, 0x2001, 0x0306, 0x2003, 0x4800, 0x2001,
-	0x009a, 0x2003, 0x0004, 0x2001, 0x1a69, 0x2003, 0x0000, 0x2001,
-	0x1a72, 0x2003, 0x0000, 0x6a88, 0x698c, 0x2200, 0x9105, 0x1170,
-	0x0096, 0x6014, 0x2048, 0xa87c, 0xc0dc, 0xa87e, 0xa880, 0xc0fc,
-	0xa882, 0x009e, 0x2c10, 0x080c, 0x1be0, 0x0040, 0x6014, 0x2048,
-	0xaa3a, 0xa936, 0x6ac4, 0x69c8, 0xa946, 0xaa4a, 0x0126, 0x00c6,
-	0x2091, 0x2400, 0x002e, 0x080c, 0x1c79, 0x190c, 0x0dc5, 0x012e,
-	0x0090, 0x2009, 0x1a85, 0x2104, 0x8000, 0x0208, 0x200a, 0x69c8,
-	0x2011, 0x0020, 0x8211, 0x1df0, 0x68c8, 0x9106, 0x1dc0, 0x69c4,
-	0x68c8, 0x9105, 0x0160, 0x6824, 0xd08c, 0x0110, 0x6827, 0x0002,
-	0x7048, 0xc085, 0x704a, 0x0079, 0x7048, 0xc084, 0x704a, 0x2009,
-	0x07d0, 0x080c, 0x88c8, 0x9006, 0x009e, 0x00ce, 0x00de, 0x0005,
-	0x9085, 0x0001, 0x0cc8, 0x0026, 0x00e6, 0x2071, 0x19e8, 0x7048,
-	0xd084, 0x01d8, 0x713c, 0x81ff, 0x01c0, 0x2071, 0x0100, 0x9188,
-	0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x7014, 0x9084, 0x1984,
-	0x9085, 0x0012, 0x7016, 0x0048, 0x928e, 0x0009, 0x0db0, 0x7014,
-	0x9084, 0x1984, 0x9085, 0x0016, 0x7016, 0x00ee, 0x002e, 0x0005,
-	0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0006,
-	0x0126, 0x2091, 0x8000, 0x6010, 0x2058, 0xbca0, 0x2071, 0x19e8,
-	0x7018, 0x2058, 0x8bff, 0x0190, 0xb8a0, 0x9406, 0x0118, 0xb854,
-	0x2058, 0x0cc0, 0x6014, 0x0096, 0x2048, 0xac6c, 0xad70, 0xae78,
-	0x009e, 0x080c, 0x6856, 0x0110, 0x9085, 0x0001, 0x012e, 0x000e,
-	0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be, 0x0005,
-	0x080c, 0xa0c1, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c, 0x7016,
-	0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005, 0x0130,
-	0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061, 0x1800,
-	0x607c, 0x6180, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce, 0x60c3,
-	0x002c, 0x0804, 0xa6bd, 0x080c, 0xa0c1, 0x7003, 0x0f00, 0x7808,
-	0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814, 0x700e,
-	0x60c3, 0x0008, 0x0804, 0xa6bd, 0x0156, 0x080c, 0xa10c, 0x7003,
-	0x0200, 0x080c, 0x894c, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019,
-	0xffed, 0x9ef0, 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072,
-	0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xa943, 0x60c3,
-	0x001c, 0x015e, 0x0804, 0xa6bd, 0x0016, 0x0026, 0x080c, 0xa0e8,
-	0x080c, 0xa0fa, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0, 0x7814,
-	0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c, 0x9080,
-	0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8, 0x9192,
-	0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2, 0x080c,
-	0xa6bd, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003, 0x080c,
-	0xaf79, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c, 0xa0c1,
-	0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd,
-	0x0016, 0x0026, 0x080c, 0xa0c1, 0x20e9, 0x0000, 0x20a1, 0x024c,
-	0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c,
-	0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8,
-	0x4003, 0x8003, 0x60c2, 0x080c, 0xa6bd, 0x002e, 0x001e, 0x0005,
-	0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8,
-	0x700c, 0x2060, 0x8cff, 0x0178, 0x080c, 0xd2e0, 0x1110, 0x080c,
-	0xbcb6, 0x600c, 0x0006, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x080c,
-	0xaaf1, 0x00ce, 0x0c78, 0x2c00, 0x700e, 0x700a, 0x012e, 0x000e,
-	0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x0066, 0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001,
-	0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102, 0x2069, 0x0100, 0x2079,
-	0x0140, 0x2071, 0x19e8, 0x7024, 0x2060, 0x8cff, 0x01f8, 0x080c,
-	0xa6e9, 0x6ac0, 0x68c3, 0x0000, 0x080c, 0x88c3, 0x00c6, 0x2061,
-	0x0100, 0x080c, 0xb0ca, 0x00ce, 0x20a9, 0x01f4, 0x0461, 0x2009,
-	0x0013, 0x080c, 0xb352, 0x000e, 0x001e, 0x002e, 0x006e, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x2001, 0x1800,
-	0x2004, 0x9096, 0x0001, 0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c,
-	0x88c3, 0x6814, 0x9084, 0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817,
-	0x0008, 0x68c3, 0x0000, 0x2011, 0x5f97, 0x080c, 0x883d, 0x20a9,
-	0x01f4, 0x0009, 0x08c0, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004,
-	0x7804, 0x9084, 0x4000, 0x190c, 0x2d49, 0x0090, 0xd084, 0x0118,
-	0x6827, 0x4001, 0x0010, 0x1f04, 0xaa2b, 0x7804, 0x9084, 0x1000,
-	0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39,
-	0x0005, 0x0126, 0x0156, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066,
-	0x0026, 0x0016, 0x0006, 0x2091, 0x8000, 0x2001, 0x180c, 0x200c,
-	0x918c, 0xdbff, 0x2102, 0x2069, 0x0100, 0x2079, 0x0140, 0x2071,
-	0x19e8, 0x703c, 0x2060, 0x8cff, 0x0904, 0xaab4, 0x9386, 0x0002,
-	0x1128, 0x6814, 0x9084, 0x0002, 0x0904, 0xaab4, 0x68af, 0x95f5,
-	0x6817, 0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb,
-	0x0008, 0x080c, 0x88d0, 0x080c, 0x2031, 0x2001, 0x0032, 0x6920,
-	0xd1bc, 0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e,
-	0x20a9, 0x03e8, 0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804,
-	0x9084, 0x4000, 0x190c, 0x2d49, 0x0090, 0xd08c, 0x0118, 0x6827,
-	0x0002, 0x0010, 0x1f04, 0xaa8a, 0x7804, 0x9084, 0x1000, 0x0138,
-	0x2001, 0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x6827,
-	0x4000, 0x6824, 0x83ff, 0x1140, 0x2009, 0x0049, 0x6020, 0x9086,
-	0x0009, 0x0110, 0x080c, 0xb352, 0x000e, 0x001e, 0x002e, 0x006e,
-	0x00ce, 0x00de, 0x00ee, 0x00fe, 0x015e, 0x012e, 0x0005, 0x00d6,
-	0x0126, 0x2091, 0x8000, 0x2069, 0x19e8, 0x6a06, 0x012e, 0x00de,
-	0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069, 0x19e8, 0x6a32,
-	0x012e, 0x00de, 0x0005, 0x080c, 0xa284, 0x7047, 0x1000, 0x0098,
-	0x080c, 0xa284, 0x7047, 0x4000, 0x0070, 0x080c, 0xa284, 0x7047,
-	0x2000, 0x0048, 0x080c, 0xa284, 0x7047, 0x0400, 0x0020, 0x080c,
-	0xa284, 0x7047, 0x0200, 0x7854, 0x7032, 0x60c3, 0x0020, 0x0804,
-	0xa6bd, 0x00e6, 0x2071, 0x19e8, 0x7020, 0x9005, 0x0110, 0x8001,
-	0x7022, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0076,
-	0x0066, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7614,
-	0x2660, 0x2678, 0x2039, 0x0001, 0x87ff, 0x0904, 0xab96, 0x8cff,
-	0x0904, 0xab96, 0x6020, 0x9086, 0x0006, 0x1904, 0xab91, 0x88ff,
-	0x0138, 0x2800, 0x9c06, 0x1904, 0xab91, 0x2039, 0x0000, 0x0050,
-	0x6010, 0x9b06, 0x1904, 0xab91, 0x85ff, 0x0120, 0x6054, 0x9106,
-	0x1904, 0xab91, 0x7024, 0x9c06, 0x15b0, 0x2069, 0x0100, 0x68c0,
-	0x9005, 0x1160, 0x6824, 0xd084, 0x0148, 0x6827, 0x0001, 0x080c,
-	0x88c3, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0428, 0x080c, 0x88c3,
-	0x6820, 0xd0b4, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3,
-	0x0000, 0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140,
-	0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39,
-	0x9006, 0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110,
-	0x6827, 0x0001, 0x003e, 0x7014, 0x9c36, 0x1110, 0x660c, 0x7616,
-	0x7010, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x7012,
-	0x0010, 0x7013, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110,
-	0x7e0e, 0x0008, 0x2678, 0x89ff, 0x1168, 0x600f, 0x0000, 0x6014,
-	0x0096, 0x2048, 0x080c, 0xd0d6, 0x0110, 0x080c, 0xebd4, 0x009e,
-	0x080c, 0xb306, 0x080c, 0xaaf1, 0x88ff, 0x1190, 0x00ce, 0x0804,
-	0xab0c, 0x2c78, 0x600c, 0x2060, 0x0804, 0xab0c, 0x9006, 0x012e,
-	0x000e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005,
-	0x601b, 0x0000, 0x00ce, 0x98c5, 0x0001, 0x0c88, 0x00f6, 0x00e6,
-	0x00d6, 0x0096, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091,
-	0x8000, 0x2071, 0x19e8, 0x7638, 0x2660, 0x2678, 0x8cff, 0x0904,
-	0xac0a, 0x6020, 0x9086, 0x0006, 0x1904, 0xac05, 0x87ff, 0x0128,
-	0x2700, 0x9c06, 0x1904, 0xac05, 0x0040, 0x6010, 0x9b06, 0x15e8,
-	0x85ff, 0x0118, 0x6054, 0x9106, 0x15c0, 0x703c, 0x9c06, 0x1168,
-	0x0036, 0x2019, 0x0001, 0x080c, 0xaa49, 0x7033, 0x0000, 0x9006,
-	0x703e, 0x7042, 0x7046, 0x704a, 0x003e, 0x7038, 0x9c36, 0x1110,
-	0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118,
-	0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c, 0x0066, 0x2c00,
-	0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014,
-	0x2048, 0x080c, 0xd0d6, 0x0110, 0x080c, 0xebd4, 0x080c, 0xb306,
-	0x87ff, 0x1198, 0x00ce, 0x0804, 0xabb6, 0x2c78, 0x600c, 0x2060,
-	0x0804, 0xabb6, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce,
-	0x009e, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce,
-	0x97bd, 0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e8, 0x2001, 0x1800,
-	0x2004, 0x9086, 0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007,
-	0x0000, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026,
-	0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x2c10, 0x7638,
-	0x2660, 0x2678, 0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7038,
-	0x9c36, 0x1110, 0x660c, 0x763a, 0x7034, 0x9c36, 0x1140, 0x2c00,
-	0x9f36, 0x0118, 0x2f00, 0x7036, 0x0010, 0x7037, 0x0000, 0x660c,
-	0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000,
-	0x6004, 0x9086, 0x0040, 0x090c, 0x99a5, 0x9085, 0x0001, 0x0020,
-	0x2c78, 0x600c, 0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e,
-	0x00ce, 0x00ee, 0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x0066, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x19e8, 0x760c, 0x2660, 0x2678, 0x8cff, 0x0904, 0xad01, 0x6010,
-	0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x1904, 0xacfc, 0x7024,
-	0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xacd3,
-	0x080c, 0xa6e9, 0x68c3, 0x0000, 0x080c, 0xac1b, 0x7027, 0x0000,
-	0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001,
-	0x0100, 0x080c, 0x2d39, 0x9006, 0x080c, 0x2d39, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x700c, 0x9c36,
-	0x1110, 0x660c, 0x760e, 0x7008, 0x9c36, 0x1140, 0x2c00, 0x9f36,
-	0x0118, 0x2f00, 0x700a, 0x0010, 0x700b, 0x0000, 0x660c, 0x0066,
-	0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000,
-	0x080c, 0xd2cf, 0x1180, 0x080c, 0x3279, 0x080c, 0xd2e0, 0x1518,
-	0x080c, 0xbcb6, 0x0400, 0x080c, 0xac1b, 0x6824, 0xd084, 0x09b0,
-	0x6827, 0x0001, 0x0898, 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6,
-	0x0090, 0x6014, 0x2048, 0x080c, 0xd0d6, 0x0168, 0x6020, 0x9086,
-	0x0003, 0x1508, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c,
-	0x6e92, 0x080c, 0xd2c3, 0x080c, 0xd54c, 0x080c, 0xb306, 0x080c,
-	0xaaf1, 0x00ce, 0x0804, 0xac7c, 0x2c78, 0x600c, 0x2060, 0x0804,
-	0xac7c, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c,
-	0xebd4, 0x0c08, 0x00d6, 0x080c, 0xa10c, 0x7003, 0x0200, 0x7007,
-	0x0014, 0x60c3, 0x0014, 0x20e1, 0x0001, 0x2099, 0x1989, 0x20e9,
-	0x0000, 0x20a1, 0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004,
-	0x7027, 0x7878, 0x080c, 0xa6bd, 0x00de, 0x0005, 0x080c, 0xa10c,
-	0x700b, 0x0800, 0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084,
-	0x00ff, 0x7022, 0x782c, 0x7026, 0x7858, 0x9084, 0x00ff, 0x9085,
-	0x0200, 0x7002, 0x7858, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2,
-	0x0804, 0xa6bd, 0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009,
-	0x0035, 0x080c, 0xd759, 0x00de, 0x1904, 0xadaf, 0x080c, 0xa0c1,
-	0x7003, 0x1300, 0x782c, 0x080c, 0xaeb5, 0x2068, 0x6820, 0x9086,
-	0x0003, 0x0560, 0x7810, 0x2058, 0xbaa0, 0x080c, 0xb23d, 0x11d8,
-	0x9286, 0x007e, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498,
-	0x9286, 0x007f, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458,
-	0x9284, 0xff80, 0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff,
-	0x700f, 0xfffc, 0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a,
-	0xb814, 0x700e, 0x00c0, 0x6098, 0x700e, 0x00a8, 0x080c, 0xb23d,
-	0x1130, 0x7810, 0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6,
-	0x2069, 0x181f, 0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de,
-	0x0010, 0x6034, 0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3,
-	0x000c, 0x001e, 0x00de, 0x080c, 0xa6bd, 0x00be, 0x0005, 0x781b,
-	0x0001, 0x7803, 0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c,
-	0x9180, 0x0008, 0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003,
-	0x0904, 0xae2a, 0x9186, 0x0005, 0x0904, 0xae12, 0x9186, 0x0004,
-	0x05d8, 0x9186, 0x0008, 0x0904, 0xae1b, 0x7807, 0x0037, 0x782f,
-	0x0003, 0x7817, 0x1700, 0x080c, 0xae92, 0x0005, 0x080c, 0xae53,
-	0x00d6, 0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x0002,
-	0xadf3, 0xadfe, 0xadf5, 0xadfe, 0xadfa, 0xadf3, 0xadf3, 0xadfe,
-	0xadfe, 0xadfe, 0xadfe, 0xadf3, 0xadf3, 0xadf3, 0xadf3, 0xadf3,
-	0xadfe, 0xadf3, 0xadfe, 0x080c, 0x0dc5, 0x6824, 0xd0e4, 0x0110,
-	0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c, 0x7022,
-	0x6830, 0x7026, 0x0804, 0xae4c, 0x080c, 0xae53, 0x00d6, 0x0026,
-	0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002, 0x1108,
-	0x900e, 0x04d0, 0x080c, 0xae53, 0x00d6, 0x0026, 0x792c, 0x2168,
-	0x2009, 0x4000, 0x0488, 0x04b9, 0x00d6, 0x0026, 0x792c, 0x2168,
-	0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286, 0x0002, 0x1108,
-	0x900e, 0x0410, 0x0441, 0x00d6, 0x0026, 0x792c, 0x2168, 0x6814,
-	0x6924, 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac, 0xa834, 0x9112,
-	0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226, 0x792c, 0x9180,
-	0x0000, 0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118,
-	0x2009, 0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e,
-	0x00de, 0x0804, 0xa6bd, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066,
-	0x080c, 0xa10c, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c,
-	0x710e, 0x7810, 0x2058, 0xb8a0, 0x080c, 0xb23d, 0x1118, 0x9092,
-	0x007e, 0x0268, 0x00d6, 0x2069, 0x181f, 0x2d2c, 0x8d68, 0x2d34,
-	0x90d8, 0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e,
-	0x6498, 0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004,
-	0x9086, 0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020,
-	0x7312, 0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e,
-	0x00be, 0x0005, 0x080c, 0xa10c, 0x7003, 0x0100, 0x782c, 0x700a,
-	0x7814, 0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x080c,
-	0xa0b8, 0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e,
-	0x782c, 0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007,
-	0x701a, 0x60c3, 0x0010, 0x0804, 0xa6bd, 0x00e6, 0x2071, 0x0240,
-	0x0006, 0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8cc, 0xd084,
-	0x0120, 0x7844, 0x702a, 0x7848, 0x702e, 0x00be, 0x00fe, 0x000e,
-	0x00ee, 0x0005, 0x080c, 0xa103, 0x7003, 0x0100, 0x782c, 0x700a,
-	0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa6bd, 0x0021, 0x60c3,
-	0x0000, 0x0804, 0xa6bd, 0x00d6, 0x080c, 0xaf8e, 0xb810, 0x9085,
-	0x0300, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c, 0x700a,
-	0x6880, 0x700e, 0x7013, 0x0819, 0x080c, 0xa6ab, 0x721a, 0x2f10,
-	0x7222, 0x7a08, 0x7226, 0x2071, 0x024c, 0x00de, 0x0005, 0x00a9,
-	0x7914, 0x712a, 0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c,
-	0x2bce, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e,
-	0x080c, 0xa6e0, 0x080c, 0x88ba, 0x0005, 0x0036, 0x0096, 0x00d6,
-	0x00e6, 0x7858, 0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, 0x00fd,
-	0xaa7e, 0xaa80, 0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff,
-	0xab74, 0x9384, 0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00,
-	0x9215, 0xaa76, 0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069,
-	0x0200, 0x080c, 0xaf8e, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240,
-	0x20a9, 0x000a, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098,
-	0x4003, 0x60a3, 0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000,
-	0x0110, 0x60a3, 0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005,
-	0x900e, 0x7814, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084,
-	0x0003, 0x11a8, 0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824,
-	0xd0cc, 0x1168, 0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001,
-	0x180c, 0x200c, 0xc1d5, 0x2102, 0x2009, 0x19b3, 0x210c, 0x009e,
-	0x918d, 0x0092, 0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x6116,
-	0x0005, 0x2009, 0x0009, 0x00a0, 0x2009, 0x000a, 0x0088, 0x2009,
-	0x000b, 0x0070, 0x2009, 0x000c, 0x0058, 0x2009, 0x000d, 0x0040,
-	0x2009, 0x000e, 0x0028, 0x2009, 0x000f, 0x0010, 0x2009, 0x0008,
-	0x6912, 0x0005, 0x080c, 0xa0c1, 0x0016, 0x0026, 0x0096, 0x00d6,
-	0x7814, 0x2048, 0x7013, 0x0138, 0x2001, 0x1837, 0x2004, 0x9084,
-	0x0028, 0x1138, 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa, 0x1904,
-	0xb033, 0x7003, 0x5400, 0x00c6, 0x2061, 0x1800, 0x607c, 0x9084,
-	0x00ff, 0xa998, 0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0x6080,
-	0x700e, 0xa998, 0x918c, 0xff00, 0x7112, 0x20a9, 0x0004, 0x2009,
-	0x1805, 0x2e10, 0x9290, 0x0006, 0x2104, 0x2012, 0x8108, 0x8210,
-	0x1f04, 0xafc4, 0x20a9, 0x0004, 0x2009, 0x1801, 0x2104, 0x2012,
-	0x8108, 0x8210, 0x1f04, 0xafce, 0xa860, 0x20e0, 0xa85c, 0x9080,
-	0x0029, 0x2098, 0x2009, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007,
-	0x2012, 0x8210, 0x8109, 0x1dc0, 0x00d6, 0x2069, 0x0200, 0x080c,
-	0xaf79, 0x00de, 0x2071, 0x0240, 0x2011, 0x0240, 0x2009, 0x0002,
-	0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0,
-	0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210,
-	0x8109, 0x1dc0, 0xa85c, 0x9080, 0x0031, 0x2098, 0x2009, 0x0008,
-	0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0,
-	0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7, 0x9575, 0x2001,
-	0x1837, 0x2004, 0x9084, 0x0028, 0x1168, 0x080c, 0x7637, 0x0150,
-	0x6028, 0xc0bd, 0x602a, 0x6014, 0x9084, 0x1804, 0x9085, 0x0029,
-	0x6016, 0x0010, 0x080c, 0xa6bd, 0x080c, 0x88ba, 0x00de, 0x009e,
-	0x002e, 0x001e, 0x0005, 0x00e6, 0x2071, 0x0240, 0x2001, 0x2200,
-	0x9085, 0x00ff, 0x7002, 0x7007, 0xffff, 0x2071, 0x0100, 0x709b,
-	0x00ff, 0x00ee, 0x0804, 0xafa9, 0x080c, 0xa0c1, 0x0016, 0x0026,
-	0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x7003, 0x5500,
-	0x00c6, 0xa89c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00,
-	0x9105, 0x700a, 0xa99c, 0x918c, 0xff00, 0xa8a0, 0x9084, 0x00ff,
-	0x9105, 0x700e, 0xa998, 0x918c, 0xff00, 0x2061, 0x1800, 0x607c,
-	0x9084, 0x00ff, 0x910d, 0x7112, 0x6180, 0x7116, 0x2009, 0x0008,
-	0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2e10, 0x9290,
-	0x0006, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109,
-	0x1dc0, 0x20a9, 0x0004, 0x2009, 0x1805, 0x2104, 0x2012, 0x8108,
-	0x8210, 0x1f04, 0xb085, 0x20a9, 0x0002, 0x2009, 0x1801, 0x2104,
-	0x2012, 0x8108, 0x8210, 0x1f04, 0xb08f, 0x00d6, 0x0016, 0x2069,
-	0x0200, 0x080c, 0xaf79, 0x001e, 0x00de, 0x2071, 0x0240, 0x20a9,
-	0x0002, 0x2009, 0x1803, 0x2011, 0x0240, 0x2104, 0x2012, 0x8108,
-	0x8210, 0x1f04, 0xb0a5, 0x2009, 0x0008, 0x4002, 0x8007, 0x2012,
-	0x8210, 0x8109, 0x1dd0, 0x9006, 0x20a9, 0x0008, 0x2012, 0x8210,
-	0x1f04, 0xb0b6, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056, 0x60a7,
-	0x9575, 0x080c, 0xa6bd, 0x080c, 0x88ba, 0x00de, 0x009e, 0x002e,
-	0x001e, 0x0005, 0x00d6, 0x9290, 0x0018, 0x8214, 0x20e9, 0x0000,
-	0x2069, 0x0200, 0x6813, 0x0000, 0x22a8, 0x9284, 0x00e0, 0x0128,
-	0x20a9, 0x0020, 0x9292, 0x0020, 0x0008, 0x9016, 0x20a1, 0x0240,
-	0x9006, 0x4004, 0x82ff, 0x0120, 0x6810, 0x8000, 0x6812, 0x0c60,
-	0x00de, 0x0005, 0x00d6, 0x0096, 0x6014, 0x2048, 0xa878, 0x6056,
-	0x9006, 0xa836, 0xa83a, 0xa99c, 0xa946, 0xa84a, 0x6023, 0x0003,
-	0x6007, 0x0040, 0x6003, 0x0003, 0x600b, 0xffff, 0xa817, 0x0001,
-	0xa842, 0xa83e, 0x2900, 0xa85a, 0xa813, 0x20c5, 0x080c, 0x9564,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x9bd3, 0x012e, 0x009e, 0x00de,
-	0x0005, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x00a6, 0x0096, 0x0066,
-	0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x760c, 0x2660, 0x2678,
-	0x8cff, 0x0904, 0xb19d, 0x7024, 0x9c06, 0x1520, 0x2069, 0x0100,
-	0x68c0, 0x9005, 0x0904, 0xb16f, 0x080c, 0xa6e9, 0x68c3, 0x0000,
-	0x080c, 0xac1b, 0x7027, 0x0000, 0x0036, 0x2069, 0x0140, 0x6b04,
-	0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c, 0x2d39, 0x9006,
-	0x080c, 0x2d39, 0x2069, 0x0100, 0x6824, 0xd084, 0x0110, 0x6827,
-	0x0001, 0x003e, 0x700c, 0x9c36, 0x1110, 0x660c, 0x760e, 0x7008,
-	0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00, 0x700a, 0x0010,
-	0x700b, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e,
-	0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xd2cf, 0x1180, 0x080c,
-	0x3279, 0x080c, 0xd2e0, 0x1518, 0x080c, 0xbcb6, 0x0400, 0x080c,
-	0xac1b, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001, 0x0898, 0x080c,
-	0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0090, 0x6014, 0x2048, 0x080c,
-	0xd0d6, 0x0168, 0x6020, 0x9086, 0x0003, 0x1520, 0xa867, 0x0103,
-	0xab7a, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x080c,
-	0xd54c, 0x080c, 0xb306, 0x080c, 0xaaf1, 0x00ce, 0x0804, 0xb120,
-	0x2c78, 0x600c, 0x2060, 0x0804, 0xb120, 0x700f, 0x0000, 0x700b,
-	0x0000, 0x012e, 0x006e, 0x009e, 0x00ae, 0x00ce, 0x00de, 0x00ee,
-	0x00fe, 0x0005, 0x6020, 0x9086, 0x0006, 0x1d08, 0x080c, 0xebd4,
-	0x08f0, 0x00d6, 0x0156, 0x080c, 0xa10c, 0x7a14, 0x82ff, 0x0138,
-	0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003,
-	0x0200, 0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086,
-	0x0004, 0x1110, 0xc38d, 0x0060, 0x080c, 0x7637, 0x1110, 0xc3ad,
-	0x0008, 0xc3a5, 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d,
-	0x730e, 0x080c, 0x894c, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019,
-	0xffed, 0x2071, 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072,
-	0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xb1e3, 0x60c3,
-	0x0020, 0x080c, 0xa6bd, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c,
-	0xa10c, 0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282,
-	0x000e, 0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008,
-	0x0488, 0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011,
-	0x19be, 0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e,
-	0x0421, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f,
-	0x2004, 0x7022, 0x2001, 0x1820, 0x2004, 0x7026, 0x0030, 0x2001,
-	0x1818, 0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1,
-	0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003,
-	0x60c3, 0x001c, 0x015e, 0x0804, 0xa6bd, 0x0006, 0x2001, 0x1837,
-	0x2004, 0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xaabf,
-	0x2011, 0x0002, 0x080c, 0xaac9, 0x080c, 0xa9d3, 0x0036, 0x901e,
-	0x080c, 0xaa49, 0x003e, 0x0005, 0x080c, 0x33af, 0x0188, 0x0016,
-	0x00b6, 0x00c6, 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e,
-	0x080c, 0x6724, 0xb85c, 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e,
-	0x0005, 0x2071, 0x188d, 0x7000, 0x9005, 0x0140, 0x2001, 0x0976,
-	0x2071, 0x1800, 0x7076, 0x707a, 0x706b, 0xffe0, 0x2071, 0x1800,
-	0x7074, 0x7056, 0x705b, 0x1cd0, 0x0005, 0x00e6, 0x0126, 0x2071,
-	0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0010, 0x0608, 0x7058,
-	0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068,
-	0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008,
-	0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a,
-	0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0,
-	0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7554, 0x9582, 0x0010,
-	0x0600, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0,
-	0x0018, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98,
-	0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502,
-	0x1228, 0x755a, 0x9085, 0x0001, 0x00ee, 0x0005, 0x705b, 0x1cd0,
-	0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x1cd0, 0x0a0c, 0x0dc5, 0x2001,
-	0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0dc5, 0x9006, 0x6006, 0x600a,
-	0x600e, 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003, 0x0000,
-	0x601e, 0x6056, 0x605a, 0x6026, 0x602a, 0x602e, 0x6032, 0x6036,
-	0x603a, 0x603e, 0x6042, 0x602a, 0x2061, 0x1800, 0x6054, 0x8000,
-	0x6056, 0x9086, 0x0001, 0x0108, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x0016, 0x080c, 0x9ab1, 0x001e, 0x012e, 0x0cb0, 0x0006, 0x6000,
-	0x9086, 0x0000, 0x01c0, 0x601c, 0xd084, 0x190c, 0x1a8e, 0x6017,
-	0x0000, 0x6023, 0x0007, 0x2001, 0x1986, 0x2004, 0x0006, 0x9082,
-	0x0051, 0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xee87, 0x6043,
-	0x0000, 0x6013, 0x0000, 0x000e, 0x0005, 0x00e6, 0x0126, 0x2071,
-	0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, 0x0608, 0x7058,
-	0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x0018, 0x7068,
-	0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1cd0, 0x0c98, 0x6003, 0x0008,
-	0x8529, 0x7556, 0x9ca8, 0x0018, 0x7068, 0x9502, 0x1230, 0x755a,
-	0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1cd0, 0x0cc0,
-	0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0xb365, 0xb36e,
-	0xb389, 0xb3a4, 0xd82b, 0xd848, 0xd863, 0xb365, 0xb36e, 0x9100,
-	0xb3bd, 0xb365, 0xb365, 0xb365, 0xb365, 0x9186, 0x0013, 0x1128,
-	0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0005, 0x0005, 0x0066, 0x6000,
-	0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb387,
-	0xbb05, 0xbcfd, 0xb387, 0xbd93, 0xb6a0, 0xb387, 0xb387, 0xba87,
-	0xc3b1, 0xb387, 0xb387, 0xb387, 0xb387, 0xb387, 0xb387, 0x080c,
-	0x0dc5, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013,
-	0x006e, 0x0005, 0xb3a2, 0xca7e, 0xb3a2, 0xb3a2, 0xb3a2, 0xb3a2,
-	0xb3a2, 0xb3a2, 0xca15, 0xcc00, 0xb3a2, 0xcabf, 0xcb3e, 0xcabf,
-	0xcb3e, 0xb3a2, 0x080c, 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c,
-	0x0dc5, 0x6000, 0x0002, 0xb3bb, 0xc3f8, 0xc4c0, 0xc5f3, 0xc7a2,
-	0xb3bb, 0xb3bb, 0xb3bb, 0xc3cc, 0xc9a1, 0xc9a4, 0xb3bb, 0xb3bb,
-	0xb3bb, 0xb3bb, 0xc9d3, 0x080c, 0x0dc5, 0x0066, 0x6000, 0x90b2,
-	0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e, 0x0005, 0xb3d6, 0xb3d6,
-	0xb419, 0xb4b8, 0xb54d, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d8, 0xb3d6,
-	0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0xb3d6, 0x080c, 0x0dc5,
-	0x9186, 0x004c, 0x0588, 0x9186, 0x0003, 0x190c, 0x0dc5, 0x0096,
-	0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048,
-	0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac, 0xa846, 0xa8b0,
-	0xa84a, 0x9006, 0xa836, 0xa83a, 0xa884, 0x9092, 0x199a, 0x0210,
-	0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210, 0x621a, 0x009e,
-	0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x9bd3, 0x012e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0,
-	0x00be, 0x2c00, 0x080c, 0xb56f, 0x080c, 0xd7fb, 0x6003, 0x0007,
-	0x0005, 0x00d6, 0x0096, 0x00f6, 0x2079, 0x1800, 0x7a90, 0x6014,
-	0x2048, 0xa87c, 0xd0ec, 0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc,
-	0x0046, 0xa8e0, 0x9005, 0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220,
-	0xa87b, 0x0007, 0x2010, 0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b,
-	0x0000, 0x8214, 0xa883, 0x0000, 0xaa02, 0x0006, 0x0016, 0x0026,
-	0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2400, 0x9005, 0x1108, 0x009a,
-	0x2100, 0x9086, 0x0015, 0x1118, 0x2001, 0x0001, 0x0038, 0x2100,
-	0x9086, 0x0016, 0x0118, 0x2001, 0x0001, 0x002a, 0x94a4, 0x0007,
-	0x8423, 0x9405, 0x0002, 0xb480, 0xb480, 0xb47b, 0xb47e, 0xb480,
-	0xb478, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b, 0xb46b,
-	0xb46b, 0xb46b, 0xb46b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e,
-	0x001e, 0x000e, 0x004e, 0x00fe, 0x009e, 0x00de, 0x080c, 0x0dc5,
-	0x080c, 0xbfab, 0x0028, 0x080c, 0xc0e9, 0x0010, 0x080c, 0xc1df,
-	0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896,
-	0x000e, 0x080c, 0xb62d, 0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050,
-	0xb100, 0x00ae, 0x8006, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084,
-	0xffc0, 0x9080, 0x0002, 0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031,
-	0x0000, 0x2041, 0x126c, 0x080c, 0xb7f1, 0x0160, 0x000e, 0x9005,
-	0x0120, 0x00fe, 0x009e, 0x00de, 0x0005, 0x00fe, 0x009e, 0x00de,
-	0x0804, 0xb2d3, 0x2001, 0x002c, 0x900e, 0x080c, 0xb693, 0x0c70,
-	0x91b6, 0x0015, 0x0170, 0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047,
-	0x0a0c, 0x0dc5, 0x91b2, 0x0050, 0x1a0c, 0x0dc5, 0x9182, 0x0047,
-	0x00ca, 0x2001, 0x0109, 0x2004, 0xd08c, 0x0198, 0x0126, 0x2091,
-	0x2800, 0x0006, 0x0016, 0x0026, 0x080c, 0x94b1, 0x002e, 0x001e,
-	0x000e, 0x012e, 0xa001, 0x6000, 0x9086, 0x0002, 0x1110, 0x0804,
-	0xb419, 0x0005, 0xb4eb, 0xb4eb, 0xb4ed, 0xb523, 0xb4eb, 0xb4eb,
-	0xb4eb, 0xb4eb, 0xb536, 0x080c, 0x0dc5, 0x00d6, 0x0016, 0x0096,
-	0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6003, 0x0004, 0x6114, 0x2148,
-	0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894,
-	0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0xb693, 0x080c,
-	0xb2d3, 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178,
-	0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4,
-	0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e,
-	0x001e, 0x00de, 0x0005, 0x080c, 0x9a61, 0x00d6, 0x0096, 0x6114,
-	0x2148, 0x080c, 0xd0d8, 0x0120, 0xa87b, 0x0006, 0x080c, 0x6e9f,
-	0x009e, 0x00de, 0x080c, 0xb2d3, 0x0804, 0x9bd3, 0x080c, 0x9a61,
-	0x080c, 0x3250, 0x080c, 0xd7f8, 0x00d6, 0x0096, 0x6114, 0x2148,
-	0x080c, 0xd0d8, 0x0120, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e,
-	0x00de, 0x080c, 0xb2d3, 0x0804, 0x9bd3, 0x9182, 0x0047, 0x0002,
-	0xb55d, 0xb55f, 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55d,
-	0xb55d, 0xb55d, 0xb55d, 0xb55d, 0xb55f, 0x080c, 0x0dc5, 0x00d6,
-	0x0096, 0x601f, 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883,
-	0x0000, 0x080c, 0x6e9f, 0x009e, 0x00de, 0x0804, 0xb2d3, 0x0026,
-	0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c,
-	0x100e, 0x000e, 0x090c, 0x0dc5, 0xa960, 0x21e8, 0xa95c, 0x9188,
-	0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079,
-	0x1800, 0x7990, 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76,
-	0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029,
-	0x0001, 0x9182, 0x0035, 0x1228, 0x2011, 0x001f, 0x080c, 0xcc85,
-	0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xcc85,
-	0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, 0x0fc0, 0x080c,
-	0x100e, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920,
-	0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c,
-	0xcc85, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011,
-	0x001b, 0x080c, 0xcc85, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000,
-	0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072,
-	0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad,
-	0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c,
-	0x6e9f, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e,
-	0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096,
-	0x0006, 0x080c, 0x100e, 0x000e, 0x090c, 0x0dc5, 0xa960, 0x21e8,
-	0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104,
-	0xaa66, 0xa87a, 0x2079, 0x1800, 0x7990, 0x810c, 0x9188, 0x000c,
-	0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972,
-	0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205,
-	0x200c, 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c,
-	0x6e9f, 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6,
-	0x0096, 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102,
-	0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80,
-	0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218,
-	0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c,
-	0x100e, 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8,
-	0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140,
-	0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318,
-	0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006,
-	0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003,
-	0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000,
-	0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0xb642,
-	0x0804, 0xb644, 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe,
-	0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348,
-	0xa87a, 0xa982, 0x080c, 0x6e92, 0x009e, 0x003e, 0x00de, 0x0005,
-	0x91b6, 0x0015, 0x1118, 0x080c, 0xb2d3, 0x0030, 0x91b6, 0x0016,
-	0x190c, 0x0dc5, 0x080c, 0xb2d3, 0x0005, 0x20a9, 0x000e, 0x20e1,
-	0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c,
-	0x20a0, 0x009e, 0x4003, 0x9196, 0x0016, 0x01f0, 0x0136, 0x9080,
-	0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318,
-	0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011,
-	0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418,
-	0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xd0d8, 0x0130,
-	0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804,
-	0xb2d3, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8,
-	0x6010, 0x00b6, 0x2058, 0xb8cf, 0x0000, 0x00be, 0x6014, 0x9005,
-	0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c,
-	0xb2d3, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8,
-	0x0006, 0x0016, 0x080c, 0xd7e3, 0x0188, 0x6014, 0x9005, 0x1170,
-	0x600b, 0x0003, 0x601b, 0x0000, 0x6043, 0x0000, 0x2009, 0x0022,
-	0x080c, 0xbadd, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001,
-	0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1,
-	0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080,
-	0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099,
-	0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048,
-	0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001,
-	0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003,
-	0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103,
-	0x080c, 0xb2d3, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e,
-	0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c,
-	0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b,
-	0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xcc85,
-	0x080c, 0xd0d8, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864,
-	0xa8e2, 0xa867, 0x0103, 0x080c, 0xb2d3, 0x001e, 0x009e, 0x0005,
-	0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009,
-	0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0dc5, 0xa97a, 0x080c,
-	0x6e9f, 0x009e, 0x080c, 0xb2d3, 0x001e, 0x0005, 0x0016, 0x0096,
-	0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034,
-	0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048,
-	0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xcc85, 0x009e,
-	0x080c, 0xd0d8, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000,
-	0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb2d3, 0x009e, 0x001e,
-	0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118,
-	0x080c, 0xbcb6, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006,
-	0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b,
-	0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8,
-	0xada4, 0x2031, 0x0000, 0x2041, 0x1252, 0x0019, 0x0d08, 0x008e,
-	0x0898, 0x0096, 0x0006, 0x080c, 0x100e, 0x000e, 0x01b0, 0xa8ab,
-	0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e,
-	0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940,
-	0x080c, 0x10f8, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6,
-	0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258,
-	0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258,
-	0xba14, 0x00be, 0x9206, 0x11e0, 0x6043, 0x0000, 0x2c68, 0x0016,
-	0x2009, 0x0035, 0x080c, 0xd759, 0x001e, 0x1158, 0x622c, 0x2268,
-	0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006,
-	0x0128, 0x080c, 0xb2d3, 0x0020, 0x0039, 0x0010, 0x080c, 0xb910,
-	0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186,
-	0x0015, 0x0904, 0xb8f8, 0x918e, 0x0016, 0x1904, 0xb90e, 0x700c,
-	0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904,
-	0xb8d2, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb8b5,
-	0x0804, 0xb90c, 0x6808, 0x9086, 0xffff, 0x1904, 0xb8fa, 0xa87c,
-	0x9084, 0x0060, 0x9086, 0x0020, 0x1128, 0xa83c, 0xa940, 0x9105,
-	0x1904, 0xb8fa, 0x6824, 0xd084, 0x1904, 0xb8fa, 0xd0b4, 0x0158,
-	0x0016, 0x2001, 0x1986, 0x200c, 0x6018, 0x9102, 0x9082, 0x0005,
-	0x001e, 0x1a04, 0xb8fa, 0x080c, 0xd2c3, 0x685c, 0xa882, 0xa87c,
-	0xc0dc, 0xc0f4, 0xc0d4, 0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001,
-	0x000a, 0x080c, 0x9375, 0xa884, 0x920a, 0x0208, 0x8011, 0xaa86,
-	0x82ff, 0x002e, 0x1138, 0x00c6, 0x2d60, 0x080c, 0xcde3, 0x00ce,
-	0x0804, 0xb90c, 0x00c6, 0xa868, 0xd0fc, 0x1118, 0x080c, 0x61c2,
-	0x0010, 0x080c, 0x65cf, 0x00ce, 0x1904, 0xb8fa, 0x00c6, 0x2d60,
-	0x080c, 0xb2d3, 0x00ce, 0x0804, 0xb90c, 0x00c6, 0x080c, 0xb325,
-	0x0198, 0x6017, 0x0000, 0x6810, 0x6012, 0x080c, 0xd554, 0x6023,
-	0x0003, 0x6904, 0x00c6, 0x2d60, 0x080c, 0xb2d3, 0x00ce, 0x080c,
-	0xb352, 0x00ce, 0x0804, 0xb90c, 0x2001, 0x1988, 0x2004, 0x6842,
-	0x00ce, 0x04d0, 0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6,
-	0x2058, 0xb900, 0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b,
-	0x0003, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023,
-	0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x00e8, 0x700c,
-	0x9086, 0x2a00, 0x1138, 0x2001, 0x1988, 0x2004, 0x6842, 0x00a0,
-	0x0479, 0x00a0, 0x89ff, 0x090c, 0x0dc5, 0x00c6, 0x00d6, 0x2d60,
-	0xa867, 0x0103, 0xa87b, 0x0003, 0x080c, 0x6cb9, 0x080c, 0xd2c3,
-	0x080c, 0xb306, 0x00de, 0x00ce, 0x080c, 0xb2d3, 0x009e, 0x0005,
-	0x9186, 0x0015, 0x1128, 0x2001, 0x1988, 0x2004, 0x6842, 0x0068,
-	0x918e, 0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xee87,
-	0x080c, 0x8a25, 0x080c, 0xb2d3, 0x00ce, 0x080c, 0xb2d3, 0x0005,
-	0x0026, 0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130,
-	0x2001, 0x1988, 0x2004, 0x6842, 0x0804, 0xb98a, 0x00c6, 0x2d60,
-	0x080c, 0xcce6, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6,
-	0x2d00, 0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x080c, 0x94ff,
-	0x080c, 0x9ab1, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8,
-	0x89ff, 0x090c, 0x0dc5, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c,
-	0xd0ac, 0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc,
-	0xa882, 0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832,
-	0x00e0, 0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4,
-	0x1d48, 0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68,
-	0x7024, 0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e,
-	0x7024, 0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xd44b, 0x080c,
-	0x9ab1, 0x0010, 0x080c, 0xb2d3, 0x004e, 0x003e, 0x002e, 0x0005,
-	0x00e6, 0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6,
-	0x2258, 0xba10, 0x00be, 0x9206, 0x1904, 0xb9f5, 0x700c, 0x6210,
-	0x00b6, 0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb9f5, 0x6038,
-	0x2068, 0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904,
-	0xb9f5, 0x9286, 0x0002, 0x0904, 0xb9f5, 0x9286, 0x0000, 0x05e8,
-	0x6808, 0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015,
-	0x0570, 0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104,
-	0x9186, 0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d,
-	0x0190, 0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014,
-	0x0096, 0x2048, 0x080c, 0xd0d8, 0x090c, 0x0dc5, 0xa87b, 0x0003,
-	0x009e, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023,
-	0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x0030, 0x6038,
-	0x2070, 0x2001, 0x1988, 0x2004, 0x7042, 0x080c, 0xb2d3, 0x002e,
-	0x00de, 0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048,
-	0x6010, 0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00,
-	0xc48c, 0xbc02, 0x0470, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48,
-	0x9e90, 0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xc379,
-	0x002e, 0x003e, 0x015e, 0x009e, 0x1904, 0xba66, 0x0096, 0x0156,
-	0x0036, 0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9,
-	0x0004, 0x080c, 0xc379, 0x002e, 0x003e, 0x015e, 0x009e, 0x15b0,
-	0x7238, 0xba0a, 0x733c, 0xbb0e, 0x83ff, 0x0118, 0xbc00, 0xc48d,
-	0xbc02, 0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804,
-	0xb6dc, 0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006,
-	0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002,
-	0x2009, 0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000,
-	0x2041, 0x1252, 0x080c, 0xb7f1, 0x0130, 0x00fe, 0x009e, 0x080c,
-	0xb2d3, 0x00be, 0x0005, 0x080c, 0xbcb6, 0x0cb8, 0x2b78, 0x00f6,
-	0x080c, 0x3250, 0x080c, 0xd7f8, 0x00fe, 0x00c6, 0x080c, 0xb27d,
-	0x2f00, 0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001,
-	0x6003, 0x0001, 0x2001, 0x0007, 0x080c, 0x666a, 0x080c, 0x6696,
-	0x080c, 0x9547, 0x080c, 0x9ab1, 0x00ce, 0x0804, 0xba39, 0x2100,
-	0x91b2, 0x0053, 0x1a0c, 0x0dc5, 0x91b2, 0x0040, 0x1a04, 0xbaef,
-	0x0002, 0xbadd, 0xbadd, 0xbad3, 0xbadd, 0xbadd, 0xbadd, 0xbad1,
-	0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1,
-	0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1,
-	0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1,
-	0xbadd, 0xbad1, 0xbadd, 0xbadd, 0xbad1, 0xbad1, 0xbad1, 0xbad1,
-	0xbad1, 0xbad3, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1,
-	0xbad1, 0xbad1, 0xbad1, 0xbadd, 0xbadd, 0xbad1, 0xbad1, 0xbad1,
-	0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbad1, 0xbadd, 0xbad1,
-	0xbad1, 0x080c, 0x0dc5, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8cc,
-	0xc08c, 0xb8ce, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106,
-	0x9186, 0x0032, 0x0118, 0x080c, 0x9547, 0x0010, 0x080c, 0x94ff,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, 0x2600,
-	0x0002, 0xbadd, 0xbadd, 0xbb03, 0xbadd, 0xbadd, 0xbb03, 0xbb03,
-	0xbb03, 0xbb03, 0xbadd, 0xbb03, 0xbadd, 0xbb03, 0xbadd, 0xbb03,
-	0xbb03, 0xbb03, 0xbb03, 0x080c, 0x0dc5, 0x6004, 0x90b2, 0x0053,
-	0x1a0c, 0x0dc5, 0x91b6, 0x0013, 0x0904, 0xbbd8, 0x91b6, 0x0027,
-	0x1904, 0xbb82, 0x080c, 0x99a5, 0x6004, 0x080c, 0xd2cf, 0x01b0,
-	0x080c, 0xd2e0, 0x01a8, 0x908e, 0x0021, 0x0904, 0xbb7f, 0x908e,
-	0x0022, 0x1130, 0x080c, 0xb708, 0x0904, 0xbb7b, 0x0804, 0xbb7c,
-	0x908e, 0x003d, 0x0904, 0xbb7f, 0x0804, 0xbb75, 0x080c, 0x3279,
-	0x2001, 0x0007, 0x080c, 0x666a, 0x6010, 0x00b6, 0x2058, 0xb9a0,
-	0x00be, 0x080c, 0xbcb6, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837,
-	0x2014, 0xc285, 0x080c, 0x7637, 0x1108, 0xc2ad, 0x2202, 0x0036,
-	0x0026, 0x2019, 0x0028, 0x2110, 0x080c, 0xef94, 0x002e, 0x003e,
-	0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c, 0x96a4,
-	0x0076, 0x903e, 0x080c, 0x9577, 0x6010, 0x00b6, 0x905d, 0x0100,
-	0x00be, 0x2c08, 0x080c, 0xe91c, 0x007e, 0x003e, 0x002e, 0x001e,
-	0x080c, 0xd7f8, 0x0016, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x001e,
-	0x080c, 0x334c, 0x080c, 0x9ab1, 0x0030, 0x080c, 0xd54c, 0x080c,
-	0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, 0xbcb6, 0x0cb0, 0x080c,
-	0xbcf2, 0x0c98, 0x9186, 0x0015, 0x0118, 0x9186, 0x0016, 0x1148,
-	0x080c, 0xd809, 0x0d80, 0x6000, 0x9086, 0x0002, 0x0904, 0xbcfd,
-	0x0c50, 0x9186, 0x0014, 0x1d38, 0x080c, 0x99a5, 0x6004, 0x908e,
-	0x0022, 0x1118, 0x080c, 0xb708, 0x09f0, 0x080c, 0x3250, 0x080c,
-	0xd7f8, 0x080c, 0xd2cf, 0x1198, 0x080c, 0x3279, 0x6010, 0x00b6,
-	0x2058, 0xb9a0, 0x00be, 0x080c, 0xbcb6, 0x9186, 0x007e, 0x1128,
-	0x2001, 0x1837, 0x200c, 0xc185, 0x2102, 0x0804, 0xbb75, 0x080c,
-	0xd2e0, 0x1120, 0x080c, 0xbcb6, 0x0804, 0xbb75, 0x6004, 0x908e,
-	0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000,
-	0x080c, 0x35e7, 0x00fe, 0x00ee, 0x0804, 0xbb75, 0x6004, 0x908e,
-	0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, 0xbcb6, 0x0804, 0xbb75,
-	0x90b2, 0x0040, 0x1a04, 0xbc92, 0x2008, 0x0002, 0xbc20, 0xbc21,
-	0xbc24, 0xbc27, 0xbc2a, 0xbc37, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e,
-	0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e,
-	0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e,
-	0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc3a, 0xbc47, 0xbc1e, 0xbc49,
-	0xbc47, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc47, 0xbc47,
-	0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc1e,
-	0xbc79, 0xbc47, 0xbc1e, 0xbc43, 0xbc1e, 0xbc1e, 0xbc1e, 0xbc44,
-	0xbc1e, 0xbc1e, 0xbc1e, 0xbc47, 0xbc70, 0xbc1e, 0x080c, 0x0dc5,
-	0x0430, 0x2001, 0x000b, 0x0470, 0x2001, 0x0003, 0x0458, 0x2001,
-	0x0005, 0x0440, 0x6010, 0x00b6, 0x2058, 0xb804, 0x00be, 0x9084,
-	0x00ff, 0x9086, 0x0000, 0x1500, 0x2001, 0x0001, 0x00d8, 0x2001,
-	0x0009, 0x00c0, 0x080c, 0x99a5, 0x6003, 0x0005, 0x080c, 0xd7fb,
-	0x080c, 0x9ab1, 0x0070, 0x0018, 0x0010, 0x080c, 0x666a, 0x0804,
-	0xbc8a, 0x080c, 0x99a5, 0x080c, 0xd7fb, 0x6003, 0x0004, 0x080c,
-	0x9ab1, 0x0005, 0x080c, 0x666a, 0x080c, 0x99a5, 0x6003, 0x0002,
-	0x0036, 0x2019, 0x1852, 0x2304, 0x9084, 0xff00, 0x1120, 0x2001,
-	0x1986, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004, 0x0ec0, 0x8003,
-	0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c, 0x9ab1, 0x0c08,
-	0x080c, 0x99a5, 0x080c, 0xd54c, 0x080c, 0xb2d3, 0x080c, 0x9ab1,
-	0x08c0, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c,
-	0x35e7, 0x00fe, 0x00ee, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c,
-	0x9ab1, 0x0838, 0x080c, 0x99a5, 0x6003, 0x0002, 0x080c, 0xd7fb,
-	0x0804, 0x9ab1, 0x2600, 0x2008, 0x0002, 0xbca9, 0xbc8a, 0xbca7,
-	0xbc8a, 0xbc8a, 0xbca7, 0xbca7, 0xbca7, 0xbca7, 0xbc8a, 0xbca7,
-	0xbc8a, 0xbca7, 0xbc8a, 0xbca7, 0xbca7, 0xbca7, 0xbca7, 0x080c,
-	0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6014, 0x2048, 0x080c, 0x6e9f,
-	0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x00e6, 0x0096,
-	0x0026, 0x0016, 0x080c, 0xd0d8, 0x0568, 0x6014, 0x2048, 0xa864,
-	0x9086, 0x0139, 0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c,
-	0x556f, 0x0130, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028,
-	0x2001, 0x0030, 0x900e, 0x2011, 0x4005, 0x080c, 0xd6bd, 0x0090,
-	0xa868, 0xd0fc, 0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e,
-	0x0021, 0x0168, 0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103,
-	0xa833, 0x0100, 0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e,
-	0x0009, 0x0cc0, 0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867,
-	0x0103, 0xa823, 0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658,
-	0xb804, 0x9084, 0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0dc5, 0x6604,
-	0x96b6, 0x004d, 0x1120, 0x080c, 0xd5dc, 0x0804, 0xbd82, 0x6604,
-	0x96b6, 0x0043, 0x1120, 0x080c, 0xd625, 0x0804, 0xbd82, 0x6604,
-	0x96b6, 0x004b, 0x1120, 0x080c, 0xd651, 0x0804, 0xbd82, 0x6604,
-	0x96b6, 0x0033, 0x1120, 0x080c, 0xd56e, 0x0804, 0xbd82, 0x6604,
-	0x96b6, 0x0028, 0x1120, 0x080c, 0xd31e, 0x0804, 0xbd82, 0x6604,
-	0x96b6, 0x0029, 0x1120, 0x080c, 0xd35f, 0x0804, 0xbd82, 0x6604,
-	0x96b6, 0x001f, 0x1120, 0x080c, 0xb6ad, 0x0804, 0xbd82, 0x6604,
-	0x96b6, 0x0000, 0x1118, 0x080c, 0xb9fb, 0x04e0, 0x6604, 0x96b6,
-	0x0022, 0x1118, 0x080c, 0xb6e9, 0x04a8, 0x6604, 0x96b6, 0x0035,
-	0x1118, 0x080c, 0xb80f, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118,
-	0x080c, 0xb990, 0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c,
-	0xb721, 0x0400, 0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb75d,
-	0x00c8, 0x6604, 0x96b6, 0x0049, 0x1118, 0x080c, 0xb79e, 0x0090,
-	0x6604, 0x96b6, 0x0041, 0x1118, 0x080c, 0xb788, 0x0058, 0x91b6,
-	0x0015, 0x1110, 0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be,
-	0x0804, 0xc08e, 0x00be, 0x0005, 0x080c, 0xb36d, 0x0cd8, 0xbd9f,
-	0xbdad, 0xbd9f, 0xbdf4, 0xbd9f, 0xbfab, 0xc09b, 0xbd9f, 0xbd9f,
-	0xc064, 0xbd9f, 0xc07a, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048,
-	0xa800, 0x2048, 0xa867, 0x0103, 0x009e, 0x0804, 0xb2d3, 0xa001,
-	0xa001, 0x0005, 0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, 0x0001,
-	0x080c, 0x6656, 0x0804, 0xb2d3, 0x0005, 0x00e6, 0x2071, 0x1800,
-	0x7090, 0x9086, 0x0074, 0x1540, 0x080c, 0xe8ed, 0x11b0, 0x6010,
-	0x00b6, 0x2058, 0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110,
-	0xc0c5, 0xb802, 0x00f9, 0x00be, 0x2001, 0x0006, 0x080c, 0x666a,
-	0x080c, 0x3279, 0x080c, 0xb2d3, 0x0098, 0x2001, 0x000a, 0x080c,
-	0x666a, 0x080c, 0x3279, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c,
-	0x9547, 0x080c, 0x9ab1, 0x0020, 0x2001, 0x0001, 0x080c, 0xbf7b,
-	0x00ee, 0x0005, 0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c,
-	0x6656, 0x2069, 0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006,
-	0x080c, 0x6696, 0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011,
-	0x1824, 0x2204, 0x9086, 0x0074, 0x1904, 0xbf50, 0x6010, 0x2058,
-	0xbaa0, 0x9286, 0x007e, 0x1120, 0x080c, 0xc1ea, 0x0804, 0xbebd,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x0904, 0xbe5f, 0x00d6, 0x080c,
-	0x7637, 0x01a0, 0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e,
-	0x0904, 0xbe5e, 0x080c, 0x57e9, 0x1598, 0x6014, 0x2048, 0xa807,
-	0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6,
-	0x2058, 0xb910, 0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011,
-	0x8008, 0x080c, 0x6ac7, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c,
-	0x0dc5, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140,
-	0x2001, 0x0030, 0x900e, 0x2011, 0x4009, 0x080c, 0xd6bd, 0x0040,
-	0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead,
-	0x6010, 0x2058, 0xb9a0, 0x0016, 0x080c, 0x3279, 0x080c, 0xb2d3,
-	0x001e, 0x080c, 0x334c, 0x00de, 0x0804, 0xbf55, 0x00de, 0x080c,
-	0xc1df, 0x6010, 0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014,
-	0x9005, 0x01a8, 0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039,
-	0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd6bd,
-	0x0030, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001,
-	0x0006, 0x080c, 0x666a, 0x080c, 0x3279, 0x080c, 0xb2d3, 0x0804,
-	0xbf55, 0x080c, 0xbf63, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868,
-	0xd0f4, 0x01e8, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08,
-	0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd6bd, 0x08f8,
-	0x080c, 0xbf59, 0x0160, 0x9006, 0x080c, 0x6656, 0x2001, 0x0004,
-	0x080c, 0x6696, 0x2001, 0x0007, 0x080c, 0x666a, 0x08a0, 0x2001,
-	0x0004, 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c,
-	0x9547, 0x080c, 0x9ab1, 0x0804, 0xbf55, 0xb85c, 0xd0e4, 0x0178,
-	0x080c, 0xd4ee, 0x080c, 0x7637, 0x0118, 0xd0dc, 0x1904, 0xbe7f,
-	0x2011, 0x1837, 0x2204, 0xc0ad, 0x2012, 0x0804, 0xbe7f, 0x080c,
-	0xd52b, 0x2011, 0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c,
-	0xeab9, 0x000e, 0x1904, 0xbe7f, 0xc0b5, 0x2012, 0x2001, 0x0006,
-	0x080c, 0x666a, 0x9006, 0x080c, 0x6656, 0x00c6, 0x2001, 0x180f,
-	0x2004, 0xd09c, 0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071,
-	0x1800, 0x700c, 0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea,
-	0x7082, 0x908c, 0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe,
-	0x080c, 0x28bc, 0x00f6, 0x2100, 0x900e, 0x080c, 0x2873, 0x795e,
-	0x00fe, 0x9186, 0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009,
-	0x00ef, 0x00f6, 0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932,
-	0x7936, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x28bc, 0x00f6,
-	0x2079, 0x1800, 0x7982, 0x2100, 0x900e, 0x797e, 0x080c, 0x2873,
-	0x795e, 0x00fe, 0x8108, 0x080c, 0x66b9, 0x2b00, 0x00ce, 0x1904,
-	0xbe7f, 0x6012, 0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009,
-	0x027c, 0x210c, 0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c,
-	0xb916, 0x2001, 0x0002, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0028,
-	0x080c, 0xbcb6, 0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be,
-	0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848,
-	0x2004, 0xd0ac, 0x0005, 0x00e6, 0x080c, 0xefed, 0x0190, 0x2071,
-	0x0260, 0x7108, 0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00,
-	0x0140, 0x6010, 0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912,
-	0xba16, 0x00ee, 0x0005, 0x2030, 0x9005, 0x0158, 0x2001, 0x0007,
-	0x080c, 0x666a, 0x080c, 0x57e9, 0x1120, 0x2001, 0x0007, 0x080c,
-	0x6696, 0x2600, 0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868,
-	0x009e, 0xd0fc, 0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058,
-	0xbba0, 0x00be, 0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4c44,
-	0x004e, 0x003e, 0x080c, 0x3279, 0x6020, 0x9086, 0x000a, 0x1108,
-	0x0005, 0x0804, 0xb2d3, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071,
-	0x1800, 0x7090, 0x9086, 0x0014, 0x1904, 0xc05a, 0x2001, 0x180d,
-	0x2004, 0xd08c, 0x0904, 0xc00d, 0x00d6, 0x080c, 0x7637, 0x01a0,
-	0x0026, 0x2011, 0x0010, 0x080c, 0x6ac7, 0x002e, 0x0904, 0xc00c,
-	0x080c, 0x57e9, 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867,
-	0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910,
-	0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c,
-	0x6ac7, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, 0x0dc5, 0x2048,
-	0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030,
-	0x900e, 0x2011, 0x4009, 0x080c, 0xd6bd, 0x0040, 0x6014, 0x2048,
-	0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058,
-	0xb9a0, 0x0016, 0x080c, 0x3279, 0x080c, 0xb2d3, 0x001e, 0x080c,
-	0x334c, 0x00de, 0x0804, 0xc05f, 0x00de, 0x080c, 0x57e9, 0x1170,
-	0x6014, 0x9005, 0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0,
-	0x2021, 0x0006, 0x080c, 0x4dfb, 0x004e, 0x003e, 0x00d6, 0x6010,
-	0x2058, 0x080c, 0x67bf, 0x080c, 0xbde2, 0x00de, 0x080c, 0xc2b5,
-	0x1588, 0x6010, 0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006,
-	0x080c, 0x666a, 0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084,
-	0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011,
-	0x4000, 0x080c, 0xd6bd, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086,
-	0x0029, 0x0130, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200,
-	0x009e, 0x080c, 0x3279, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c,
-	0xb2d3, 0x0028, 0x080c, 0xbcb6, 0x9006, 0x080c, 0xbf7b, 0x001e,
-	0x002e, 0x00ee, 0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086,
-	0x0014, 0x1160, 0x2001, 0x0002, 0x080c, 0x666a, 0x6003, 0x0001,
-	0x6007, 0x0001, 0x080c, 0x9547, 0x0804, 0x9ab1, 0x2001, 0x0001,
-	0x0804, 0xbf7b, 0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004,
-	0x1148, 0x96b6, 0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x666a,
-	0x0804, 0xb2d3, 0x2001, 0x0001, 0x0804, 0xbf7b, 0x0002, 0xbd9f,
-	0xc0a6, 0xbd9f, 0xc0e9, 0xbd9f, 0xc196, 0xc09b, 0xbda2, 0xbd9f,
-	0xc1aa, 0xbd9f, 0xc1bc, 0x6604, 0x9686, 0x0003, 0x0904, 0xbfab,
-	0x96b6, 0x001e, 0x1110, 0x080c, 0xb2d3, 0x0005, 0x00b6, 0x00d6,
-	0x00c6, 0x080c, 0xc1ce, 0x11a0, 0x9006, 0x080c, 0x6656, 0x080c,
-	0x3250, 0x080c, 0xd7f8, 0x2001, 0x0002, 0x080c, 0x666a, 0x6003,
-	0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0428,
-	0x2009, 0x026e, 0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058,
-	0xb840, 0x9084, 0x00ff, 0x9005, 0x0180, 0x8001, 0xb842, 0x601b,
-	0x000a, 0x0098, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x908e,
-	0x1900, 0x0158, 0x908e, 0x1e00, 0x0990, 0x080c, 0x3250, 0x080c,
-	0xd7f8, 0x2001, 0x0001, 0x080c, 0xbf7b, 0x00ce, 0x00de, 0x00be,
-	0x0005, 0x0096, 0x00b6, 0x0026, 0x9016, 0x080c, 0xc1dc, 0x00d6,
-	0x2069, 0x197c, 0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0,
-	0x9086, 0x007e, 0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a,
-	0x00de, 0x0010, 0x00de, 0x0088, 0x9006, 0x080c, 0x6656, 0x2001,
-	0x0002, 0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c,
-	0x9547, 0x080c, 0x9ab1, 0x0804, 0xc166, 0x080c, 0xd0d8, 0x01b0,
-	0x6014, 0x2048, 0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007,
-	0x0016, 0x2001, 0x0002, 0x080c, 0xd71a, 0x00b0, 0x6014, 0x2048,
-	0xa864, 0xd0fc, 0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e,
-	0x2004, 0xd0dc, 0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff,
-	0x9005, 0x1110, 0x9006, 0x0c38, 0x080c, 0xbcb6, 0x2009, 0x026e,
-	0x2134, 0x96b4, 0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, 0x000b,
-	0x01c8, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686,
-	0x0009, 0x01c0, 0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0190,
-	0x2001, 0x0004, 0x080c, 0x666a, 0x2001, 0x0028, 0x601a, 0x6007,
-	0x0052, 0x0020, 0x2001, 0x0001, 0x080c, 0xbf7b, 0x002e, 0x00be,
-	0x009e, 0x0005, 0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c,
-	0xd0d8, 0x0140, 0xa864, 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc,
-	0x0108, 0x0c40, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005,
-	0x0138, 0x8001, 0xb842, 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0,
-	0xb8a0, 0x9086, 0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c,
-	0x60c1, 0x00ee, 0x0010, 0x080c, 0x3250, 0x0860, 0x2001, 0x0004,
-	0x080c, 0x666a, 0x080c, 0xc1dc, 0x1140, 0x6003, 0x0001, 0x6007,
-	0x0003, 0x080c, 0x9547, 0x0804, 0x9ab1, 0x080c, 0xbcb6, 0x9006,
-	0x0804, 0xbf7b, 0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x666a,
-	0x6003, 0x0001, 0x6007, 0x0005, 0x080c, 0x9547, 0x0804, 0x9ab1,
-	0x2001, 0x0001, 0x0804, 0xbf7b, 0x00f9, 0x1160, 0x2001, 0x000a,
-	0x080c, 0x666a, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9547,
-	0x0804, 0x9ab1, 0x2001, 0x0001, 0x0804, 0xbf7b, 0x2009, 0x026e,
-	0x2104, 0x9086, 0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084,
-	0xff00, 0x9086, 0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6,
-	0x00c6, 0x0016, 0x6110, 0x2158, 0x080c, 0x6733, 0x001e, 0x00ce,
-	0x00be, 0x0005, 0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016,
-	0x6010, 0x2058, 0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a,
-	0x080c, 0xc287, 0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a,
-	0x080c, 0x6a9f, 0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c,
-	0xec31, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a,
-	0x2009, 0x0001, 0x080c, 0x321b, 0x00e6, 0x2071, 0x1800, 0x080c,
-	0x3000, 0x00ee, 0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f,
-	0x080c, 0x334c, 0x8108, 0x1f04, 0xc220, 0x015e, 0x00ce, 0x080c,
-	0xc1df, 0x2071, 0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001,
-	0x1837, 0x200c, 0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118,
-	0x7038, 0xd0dc, 0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1837,
-	0x2102, 0x9184, 0x0050, 0x9086, 0x0050, 0x05d0, 0x2079, 0x0100,
-	0x2e04, 0x9084, 0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006,
-	0x8e70, 0x2e04, 0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836,
-	0x2010, 0x9084, 0xff00, 0x001e, 0x9105, 0x2009, 0x182c, 0x200a,
-	0x2200, 0x9084, 0x00ff, 0x2008, 0x080c, 0x28bc, 0x080c, 0x7637,
-	0x0170, 0x2071, 0x0260, 0x2069, 0x1982, 0x7048, 0x206a, 0x704c,
-	0x6806, 0x7050, 0x680a, 0x7054, 0x680e, 0x080c, 0xd4ee, 0x0040,
-	0x2001, 0x0006, 0x080c, 0x666a, 0x080c, 0x3279, 0x080c, 0xb2d3,
-	0x001e, 0x003e, 0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096,
-	0x0026, 0x0036, 0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff,
-	0x01f0, 0x2071, 0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084,
-	0xff00, 0x9205, 0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004,
-	0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, 0x1148, 0x2011, 0x027a,
-	0x20a9, 0x0004, 0x2019, 0x0006, 0x080c, 0xc379, 0x1100, 0x015e,
-	0x00ee, 0x003e, 0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260,
-	0x7034, 0x9086, 0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188,
-	0x703c, 0xd0ec, 0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138,
-	0x7054, 0xd0a4, 0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085,
-	0x0001, 0x00ee, 0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056,
-	0x0046, 0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f1,
-	0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0, 0x2071, 0x1800,
-	0x7254, 0x7074, 0x9202, 0x1a04, 0xc345, 0x080c, 0x8cf7, 0x0904,
-	0xc33e, 0x080c, 0xec62, 0x0904, 0xc33e, 0x6720, 0x9786, 0x0007,
-	0x0904, 0xc33e, 0x2500, 0x9c06, 0x0904, 0xc33e, 0x2400, 0x9c06,
-	0x05e8, 0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130,
-	0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1580, 0x00c6, 0x6000,
-	0x9086, 0x0004, 0x1110, 0x080c, 0x1a8e, 0x9786, 0x000a, 0x0148,
-	0x080c, 0xd2e0, 0x1130, 0x00ce, 0x080c, 0xbcb6, 0x080c, 0xb306,
-	0x00e8, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x01a8, 0x9786, 0x0003,
-	0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878,
-	0x2048, 0x080c, 0x0fc0, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c,
-	0x6e92, 0x080c, 0xd2c3, 0x080c, 0xb306, 0x00ce, 0x9ce0, 0x0018,
-	0x7068, 0x9c02, 0x1210, 0x0804, 0xc2e8, 0x012e, 0x000e, 0x002e,
-	0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005, 0x9786,
-	0x0006, 0x1118, 0x080c, 0xebd4, 0x0c30, 0x9786, 0x0009, 0x1148,
-	0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c, 0xb352,
-	0x08e0, 0x9786, 0x000a, 0x0980, 0x0820, 0x220c, 0x2304, 0x9106,
-	0x1130, 0x8210, 0x8318, 0x1f04, 0xc365, 0x9006, 0x0005, 0x2304,
-	0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d, 0x0001,
-	0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007, 0x908c,
-	0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518, 0x20a9,
-	0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319, 0x1dc8,
-	0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102, 0x0218,
-	0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001, 0x001e,
-	0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, 0x2304, 0x9106, 0x1130,
-	0x8210, 0x8318, 0x1f04, 0xc3a3, 0x9006, 0x0005, 0x918d, 0x0001,
-	0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0dc5, 0x080c, 0xd2cf,
-	0x0120, 0x080c, 0xd2e0, 0x0168, 0x0028, 0x080c, 0x3279, 0x080c,
-	0xd2e0, 0x0138, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, 0x9ab1,
-	0x0005, 0x080c, 0xbcb6, 0x0cb0, 0x9182, 0x0054, 0x1220, 0x9182,
-	0x0040, 0x0208, 0x000a, 0x0005, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8,
-	0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3ea,
-	0xc3ea, 0xc3ea, 0xc3ea, 0xc3e8, 0xc3e8, 0xc3e8, 0xc3ea, 0xc3e8,
-	0x080c, 0x0dc5, 0x600b, 0xffff, 0x6003, 0x0001, 0x6106, 0x080c,
-	0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005,
-	0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0040, 0x0804, 0xc482,
-	0x9186, 0x0027, 0x1520, 0x080c, 0x99a5, 0x080c, 0x3250, 0x080c,
-	0xd7f8, 0x0096, 0x6114, 0x2148, 0x080c, 0xd0d8, 0x0198, 0x080c,
-	0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0068, 0xa867, 0x0103, 0xa87b,
-	0x0029, 0xa877, 0x0000, 0xa97c, 0xc1c5, 0xa97e, 0x080c, 0x6e9f,
-	0x080c, 0xd2c3, 0x009e, 0x080c, 0xb2d3, 0x0804, 0x9ab1, 0x9186,
-	0x0014, 0x1120, 0x6004, 0x9082, 0x0040, 0x00b8, 0x9186, 0x0046,
-	0x0150, 0x9186, 0x0045, 0x0138, 0x9186, 0x0053, 0x0120, 0x9186,
-	0x0048, 0x190c, 0x0dc5, 0x080c, 0xd809, 0x0130, 0x6000, 0x9086,
-	0x0002, 0x1110, 0x0804, 0xc4c0, 0x0005, 0x0002, 0xc45c, 0xc45a,
-	0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a, 0xc45a,
-	0xc45a, 0xc477, 0xc477, 0xc477, 0xc477, 0xc45a, 0xc477, 0xc45a,
-	0xc477, 0xc45a, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6114,
-	0x2148, 0x080c, 0xd0d8, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006,
-	0xa877, 0x0000, 0xa880, 0xc0ec, 0xa882, 0x080c, 0x6e9f, 0x080c,
-	0xd2c3, 0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c,
-	0x99a5, 0x080c, 0xd2e0, 0x090c, 0xbcb6, 0x080c, 0xb2d3, 0x080c,
-	0x9ab1, 0x0005, 0x0002, 0xc499, 0xc497, 0xc497, 0xc497, 0xc497,
-	0xc497, 0xc497, 0xc497, 0xc497, 0xc497, 0xc497, 0xc4b0, 0xc4b0,
-	0xc4b0, 0xc4b0, 0xc497, 0xc4ba, 0xc497, 0xc4b0, 0xc497, 0x080c,
-	0x0dc5, 0x0096, 0x080c, 0x99a5, 0x6014, 0x2048, 0x2001, 0x1988,
-	0x2004, 0x6042, 0xa97c, 0xd1ac, 0x0140, 0x6003, 0x0004, 0xa87c,
-	0x9085, 0x0400, 0xa87e, 0x009e, 0x0005, 0x6003, 0x0002, 0x0cb8,
-	0x080c, 0x99a5, 0x080c, 0xd7fb, 0x080c, 0xd800, 0x6003, 0x000f,
-	0x0804, 0x9ab1, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x0804, 0x9ab1,
-	0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005,
-	0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4de, 0xc5be, 0xc4dc,
-	0xc5f2, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc, 0xc4dc,
-	0xc4dc, 0xc4dc, 0xc4dc, 0xc5f2, 0x080c, 0x0dc5, 0x00b6, 0x0096,
-	0x6114, 0x2148, 0x7644, 0x96b4, 0x0fff, 0x86ff, 0x1528, 0x6010,
-	0x2058, 0xb800, 0xd0bc, 0x1904, 0xc5ad, 0xa87b, 0x0000, 0xa867,
-	0x0103, 0xae76, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115,
-	0x190c, 0xc78b, 0x080c, 0x6cb9, 0x6210, 0x2258, 0xba3c, 0x82ff,
-	0x0110, 0x8211, 0xba3e, 0x7044, 0xd0e4, 0x1904, 0xc58e, 0x080c,
-	0xb2d3, 0x009e, 0x00be, 0x0005, 0x968c, 0x0c00, 0x0150, 0x6010,
-	0x2058, 0xb800, 0xd0bc, 0x1904, 0xc592, 0x7348, 0xab92, 0x734c,
-	0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508, 0x9186, 0x0028,
-	0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0, 0xa87b, 0x0015,
-	0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0148,
-	0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118, 0xa992, 0xaa8e,
-	0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b,
-	0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4, 0x01d8, 0x9686,
-	0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0x0804, 0xc4e5,
-	0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019,
-	0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c,
-	0xcc85, 0x003e, 0xd6cc, 0x0904, 0xc4fa, 0x7154, 0xa98a, 0x81ff,
-	0x0904, 0xc4fa, 0x9192, 0x0021, 0x1278, 0x8304, 0x9098, 0x0018,
-	0x2011, 0x0029, 0x080c, 0xcc85, 0x2011, 0x0205, 0x2013, 0x0000,
-	0x080c, 0xd786, 0x0804, 0xc4fa, 0xa868, 0xd0fc, 0x0120, 0x2009,
-	0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c, 0xcc24, 0x00ae,
-	0x080c, 0xd786, 0x080c, 0xcc75, 0x0804, 0xc4fc, 0x080c, 0xd3d8,
-	0x0804, 0xc509, 0xa87c, 0xd0ac, 0x0904, 0xc515, 0xa880, 0xd0bc,
-	0x1904, 0xc515, 0x9684, 0x0400, 0x0130, 0xa838, 0xab34, 0x9305,
-	0x0904, 0xc515, 0x00b8, 0x7348, 0xa838, 0x9306, 0x1198, 0x734c,
-	0xa834, 0x931e, 0x0904, 0xc515, 0x0068, 0xa87c, 0xd0ac, 0x0904,
-	0xc4ed, 0xa838, 0xa934, 0x9105, 0x0904, 0xc4ed, 0xa880, 0xd0bc,
-	0x1904, 0xc4ed, 0x080c, 0xd412, 0x0804, 0xc509, 0x0096, 0x00f6,
-	0x6003, 0x0003, 0x6007, 0x0043, 0x2079, 0x026c, 0x7c04, 0x7b00,
-	0x7e0c, 0x7d08, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0140, 0x6003,
-	0x0002, 0x00fe, 0x009e, 0x0005, 0x2130, 0x2228, 0x0058, 0x2400,
-	0xa9ac, 0x910a, 0x2300, 0xaab0, 0x9213, 0x2600, 0x9102, 0x2500,
-	0x9203, 0x0e90, 0xac36, 0xab3a, 0xae46, 0xad4a, 0x00fe, 0x6043,
-	0x0000, 0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x080c, 0x9bd3,
-	0x009e, 0x0005, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040,
-	0x0208, 0x000a, 0x0005, 0xc60f, 0xc60f, 0xc60f, 0xc60f, 0xc60f,
-	0xc611, 0xc6a7, 0xc60f, 0xc60f, 0xc6be, 0xc74e, 0xc60f, 0xc60f,
-	0xc60f, 0xc60f, 0xc763, 0xc60f, 0xc60f, 0xc60f, 0xc60f, 0x080c,
-	0x0dc5, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114,
-	0x2150, 0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e,
-	0x6210, 0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e,
-	0x00be, 0x86ff, 0x0904, 0xc6a2, 0x9694, 0xff00, 0x9284, 0x0c00,
-	0x0120, 0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904,
-	0xc6a2, 0x080c, 0x100e, 0x090c, 0x0dc5, 0x2900, 0xb07a, 0xb77c,
-	0xc7cd, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c, 0xa86e,
-	0xb070, 0xa872, 0xae76, 0x968c, 0x0c00, 0x0120, 0x7348, 0xab92,
-	0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0180, 0x9186,
-	0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b,
-	0x0015, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b,
-	0x0000, 0xaf7e, 0xb080, 0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4,
-	0x0190, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009, 0x0210,
-	0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011, 0x0025,
-	0x080c, 0xcc85, 0x003e, 0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff,
-	0x01c8, 0x9192, 0x0021, 0x1260, 0x8304, 0x9098, 0x0018, 0x2011,
-	0x0029, 0x080c, 0xcc85, 0x2011, 0x0205, 0x2013, 0x0000, 0x0050,
-	0xb068, 0xd0fc, 0x0120, 0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950,
-	0x080c, 0xcc24, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x00f6,
-	0x00a6, 0x6003, 0x0003, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c,
-	0x7d08, 0x6014, 0x2050, 0xb436, 0xb33a, 0xb646, 0xb54a, 0x00ae,
-	0x00fe, 0x2c10, 0x080c, 0x1be0, 0x0804, 0xa6b6, 0x6003, 0x0002,
-	0x6004, 0x9086, 0x0040, 0x11c8, 0x0096, 0x6014, 0x2048, 0xa87c,
-	0xd0ac, 0x0160, 0x601c, 0xd084, 0x1130, 0x00f6, 0x2c00, 0x2078,
-	0x080c, 0x1768, 0x00fe, 0x6003, 0x0004, 0x0010, 0x6003, 0x0002,
-	0x009e, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0096, 0x2001, 0x1988,
-	0x2004, 0x6042, 0x080c, 0x9a61, 0x080c, 0x9bd3, 0x6114, 0x2148,
-	0xa97c, 0xd1e4, 0x0904, 0xc749, 0xd1cc, 0x05c8, 0xa978, 0xa868,
-	0xd0fc, 0x0540, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006, 0xa860,
-	0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x810e, 0x810e, 0x810f,
-	0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0019, 0x2098,
-	0x0156, 0x20a9, 0x0020, 0x4003, 0x015e, 0x000e, 0xa882, 0x000e,
-	0xc0cc, 0xa87e, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fc0,
-	0x001e, 0x0458, 0x0016, 0x080c, 0x0fc0, 0x009e, 0xa87c, 0xc0cc,
-	0xa87e, 0xa974, 0x0016, 0x080c, 0xcc75, 0x001e, 0x00f0, 0xa867,
-	0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0180, 0x9086,
-	0x0028, 0x1118, 0xa87b, 0x001c, 0x0060, 0xd1dc, 0x0118, 0xa87b,
-	0x0015, 0x0038, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b,
-	0x0000, 0x0016, 0x080c, 0x6cb9, 0x001e, 0xd1e4, 0x1120, 0x080c,
-	0xb2d3, 0x009e, 0x0005, 0x080c, 0xd3d8, 0x0cd8, 0x6004, 0x9086,
-	0x0040, 0x1120, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x2019, 0x0001,
-	0x080c, 0xaa49, 0x6003, 0x0002, 0x080c, 0xd800, 0x080c, 0x9a61,
-	0x080c, 0x9bd3, 0x0005, 0x6004, 0x9086, 0x0040, 0x1120, 0x080c,
-	0x99a5, 0x080c, 0x9ab1, 0x2019, 0x0001, 0x080c, 0xaa49, 0x080c,
-	0x9a61, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x0096, 0x6114, 0x2148,
-	0x080c, 0xd0d8, 0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877,
-	0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb2d3,
-	0x080c, 0x9bd3, 0x0005, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b,
-	0x0007, 0x8002, 0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016,
-	0x2009, 0x1a7d, 0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992,
-	0xa88e, 0x0005, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040, 0x0208,
-	0x000a, 0x0005, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7c0,
-	0xc7be, 0xc7be, 0xc866, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be,
-	0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc7be, 0xc998, 0x080c, 0x0dc5,
-	0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071, 0x0260, 0x6114, 0x2150,
-	0x7644, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210,
-	0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be,
-	0x86ff, 0x0904, 0xc85f, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120,
-	0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc85f,
-	0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676,
-	0x0c38, 0x080c, 0x100e, 0x090c, 0x0dc5, 0x2900, 0xb07a, 0xb77c,
-	0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c,
-	0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76,
-	0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c,
-	0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b,
-	0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4,
-	0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080,
-	0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86,
-	0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036,
-	0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xcc85, 0x003e,
-	0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021,
-	0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xcc85,
-	0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120,
-	0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xcc24, 0x080c,
-	0x1a5a, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1988,
-	0x2004, 0x6042, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105,
-	0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0xa97c, 0xd1e4,
-	0x0904, 0xc993, 0x6043, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800,
-	0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc962, 0xa978, 0xa868,
-	0xd0fc, 0x0904, 0xc923, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006,
-	0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904,
-	0xc8f0, 0x9086, 0x0028, 0x1904, 0xc8dc, 0xa87b, 0x001c, 0xb07b,
-	0x001c, 0x0804, 0xc8f8, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34,
-	0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34,
-	0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102,
-	0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026,
-	0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x9006,
-	0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4, 0xa87e, 0xd0cc, 0x0140,
-	0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e,
-	0x080c, 0xd412, 0x0804, 0xc993, 0xd1dc, 0x0158, 0xa87b, 0x0015,
-	0xb07b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xb174, 0xc1dc, 0xb176,
-	0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040,
-	0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc78b,
-	0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa860, 0x20e8,
-	0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9, 0x0020, 0x8a06, 0x8006,
-	0x8007, 0x9094, 0x003f, 0x22e0, 0x9084, 0xffc0, 0x9080, 0x0019,
-	0x2098, 0x4003, 0x00ae, 0x000e, 0xa882, 0x000e, 0xc0cc, 0xa87e,
-	0x080c, 0xd786, 0x001e, 0xa874, 0x0006, 0x2148, 0x080c, 0x0fc0,
-	0x001e, 0x0804, 0xc98f, 0x0016, 0x00a6, 0x2150, 0xb174, 0x9184,
-	0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086, 0x0028, 0x1128, 0xa87b,
-	0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc, 0x0158, 0xa87b, 0x0015,
-	0xb07b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xb174, 0xc1dc, 0xb176,
-	0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007, 0xb07b, 0x0007, 0x0040,
-	0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc78b,
-	0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c, 0xb07e, 0x00ae, 0x080c,
-	0x0fc0, 0x009e, 0x080c, 0xd786, 0xa974, 0x0016, 0x080c, 0xcc75,
-	0x001e, 0x0468, 0xa867, 0x0103, 0xa974, 0x9184, 0x00ff, 0x90b6,
-	0x0002, 0x01b0, 0x9086, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00d0,
-	0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c, 0xd6a6, 0x0118, 0xa974,
-	0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118, 0xa87b, 0x0007, 0x0050,
-	0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115,
-	0x190c, 0xc78b, 0xa974, 0x0016, 0x080c, 0x6cb9, 0x001e, 0xd1e4,
-	0x1120, 0x080c, 0xb2d3, 0x009e, 0x0005, 0x080c, 0xd3d8, 0x0cd8,
-	0x6114, 0x0096, 0x2148, 0xa97c, 0xd1e4, 0x190c, 0x1a7a, 0x009e,
-	0x0005, 0x080c, 0x99a5, 0x0010, 0x080c, 0x9a61, 0x080c, 0xd0d8,
-	0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xd2e0, 0x1118, 0x080c,
-	0xbcb6, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c, 0xd18c,
-	0x11b8, 0xd184, 0x1190, 0x6108, 0xa97a, 0x918e, 0x0029, 0x1110,
-	0x080c, 0xef85, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x009e, 0x080c,
-	0xb2d3, 0x080c, 0x9ab1, 0x0804, 0x9bd3, 0xa87b, 0x0004, 0x0c90,
-	0xa87b, 0x0004, 0x0c78, 0x9182, 0x0054, 0x1220, 0x9182, 0x0040,
-	0x0208, 0x000a, 0x0005, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef,
-	0xc9f1, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef,
-	0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0xc9ef, 0x080c,
-	0x0dc5, 0x080c, 0x57dd, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff,
-	0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d,
-	0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867,
-	0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e,
-	0x080c, 0x6e9f, 0x009e, 0x0804, 0xb2d3, 0x9182, 0x0085, 0x0002,
-	0xca27, 0xca25, 0xca25, 0xca33, 0xca25, 0xca25, 0xca25, 0xca25,
-	0xca25, 0xca25, 0xca25, 0xca25, 0xca25, 0x080c, 0x0dc5, 0x6003,
-	0x0001, 0x6106, 0x080c, 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x9ab1, 0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071,
-	0x0260, 0x7224, 0x6216, 0x7220, 0x080c, 0xd0c6, 0x01f8, 0x2268,
-	0x6800, 0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0,
-	0x00c6, 0x2d60, 0x00d6, 0x080c, 0xcce6, 0x00de, 0x00ce, 0x0158,
-	0x702c, 0xd084, 0x1118, 0x080c, 0xccb0, 0x0010, 0x6803, 0x0002,
-	0x6007, 0x0086, 0x0028, 0x080c, 0xccd2, 0x0d90, 0x6007, 0x0087,
-	0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x7220, 0x080c,
-	0xd0c6, 0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc,
-	0x0140, 0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xd412,
-	0x00ce, 0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013,
-	0x1160, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, 0x0092,
-	0x1a0c, 0x0dc5, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120,
-	0x9186, 0x0014, 0x190c, 0x0dc5, 0x080c, 0x99a5, 0x0096, 0x6014,
-	0x2048, 0x080c, 0xd0d8, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000,
-	0xa87b, 0x0029, 0x080c, 0x6e9f, 0x009e, 0x080c, 0xb306, 0x0804,
-	0x9ab1, 0xcab6, 0xcab8, 0xcab8, 0xcab6, 0xcab6, 0xcab6, 0xcab6,
-	0xcab6, 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0xcab6, 0x080c, 0x0dc5,
-	0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x9186,
-	0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x04b8, 0x9186,
-	0x0027, 0x11f8, 0x080c, 0x99a5, 0x080c, 0x3250, 0x080c, 0xd7f8,
-	0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0150, 0xa867, 0x0103,
-	0xa877, 0x0000, 0xa87b, 0x0029, 0x080c, 0x6e9f, 0x080c, 0xd2c3,
-	0x009e, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x080c, 0xb36d,
-	0x0ce0, 0x9186, 0x0014, 0x1dd0, 0x080c, 0x99a5, 0x0096, 0x6014,
-	0x2048, 0x080c, 0xd0d8, 0x0d60, 0xa867, 0x0103, 0xa877, 0x0000,
-	0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x08f0, 0x0002, 0xcb0e,
-	0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0xcb26, 0xcb0c, 0xcb0c,
-	0xcb0c, 0xcb0c, 0xcb0c, 0xcb0c, 0x080c, 0x0dc5, 0x080c, 0x99a5,
-	0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186,
-	0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004,
-	0x601a, 0x6003, 0x000c, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x99a5,
-	0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186,
-	0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004,
-	0x601a, 0x6003, 0x000e, 0x080c, 0x9ab1, 0x0005, 0x9182, 0x0092,
-	0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xb36d, 0xcb54,
-	0xcb54, 0xcb54, 0xcb54, 0xcb56, 0xcba3, 0xcb54, 0xcb54, 0xcb54,
-	0xcb54, 0xcb54, 0xcb54, 0xcb54, 0x080c, 0x0dc5, 0x0096, 0x6010,
-	0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c,
-	0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118,
-	0x009e, 0x0804, 0xcbb7, 0x080c, 0xd0d8, 0x1118, 0x080c, 0xd2c3,
-	0x0068, 0x6014, 0x2048, 0xa87c, 0xd0e4, 0x1110, 0x080c, 0xd2c3,
-	0xa867, 0x0103, 0x080c, 0xd7c3, 0x080c, 0x6e9f, 0x00d6, 0x2c68,
-	0x080c, 0xb27d, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b,
-	0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c,
-	0x613e, 0x6910, 0x6112, 0x080c, 0xd554, 0x6954, 0x6156, 0x6023,
-	0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x2d60, 0x00de, 0x080c,
-	0xb2d3, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be,
-	0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035,
-	0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6,
-	0x2c68, 0x080c, 0xd759, 0x11f0, 0x080c, 0xb27d, 0x01d8, 0x6106,
-	0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e,
-	0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a,
-	0x693c, 0x613e, 0x6954, 0x6156, 0x080c, 0xd554, 0x080c, 0x94ff,
-	0x080c, 0x9ab1, 0x2d60, 0x00de, 0x0804, 0xb2d3, 0x0096, 0x6014,
-	0x2048, 0x080c, 0xd0d8, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4,
-	0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118,
-	0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd3d4, 0xa877,
-	0x0000, 0x080c, 0x6e9f, 0x080c, 0xd2c3, 0x009e, 0x0804, 0xb2d3,
-	0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0140, 0xa867,
-	0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x6e9f, 0x009e,
-	0x001e, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186,
-	0x0027, 0x0118, 0x080c, 0xb36d, 0x0030, 0x080c, 0x99a5, 0x080c,
-	0xb306, 0x080c, 0x9ab1, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6,
-	0x2029, 0x0001, 0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100,
-	0x2130, 0x8304, 0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029,
-	0x080c, 0xcc85, 0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c,
-	0x0fc0, 0x080c, 0x100e, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b,
-	0x0000, 0x2920, 0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011,
-	0x001b, 0x0499, 0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950,
-	0x2011, 0x001b, 0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000,
-	0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048,
-	0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003,
-	0xb566, 0x009e, 0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158,
-	0xa804, 0x9055, 0x0130, 0xa807, 0x0000, 0x080c, 0x6e9f, 0x2a48,
-	0x0cb8, 0x080c, 0x6e9f, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200,
-	0x7814, 0x9085, 0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c,
-	0x20a9, 0x0001, 0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1,
-	0x0000, 0x2300, 0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020,
-	0x1148, 0x2018, 0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085,
-	0x0080, 0x7816, 0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005,
-	0x6920, 0x9186, 0x0003, 0x0118, 0x9186, 0x0002, 0x11d0, 0x00c6,
-	0x00d6, 0x00e6, 0x2d60, 0x0096, 0x6014, 0x2048, 0x080c, 0xd0d8,
-	0x0150, 0x2001, 0x0006, 0xa980, 0xc1d5, 0x080c, 0x710b, 0x080c,
-	0x6e92, 0x080c, 0xd2c3, 0x009e, 0x080c, 0xb306, 0x00ee, 0x00de,
-	0x00ce, 0x0005, 0x00c6, 0x702c, 0xd084, 0x1170, 0x6008, 0x2060,
-	0x6020, 0x9086, 0x0002, 0x1140, 0x6104, 0x9186, 0x0085, 0x0118,
-	0x9186, 0x008b, 0x1108, 0x9006, 0x00ce, 0x0005, 0x0066, 0x0126,
-	0x2091, 0x8000, 0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083,
-	0x012e, 0x006e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031,
-	0x0000, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005,
-	0xcd1d, 0xcd1d, 0xcd18, 0xcd3f, 0xcd0f, 0xcd18, 0xcd3f, 0xcd18,
-	0xcd18, 0x9265, 0xcd18, 0xcd18, 0xcd18, 0xcd0f, 0xcd0f, 0x080c,
-	0x0dc5, 0x0036, 0x2019, 0x0010, 0x080c, 0xe746, 0x003e, 0x0005,
-	0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x0096, 0x86ff, 0x11d8,
-	0x6014, 0x2048, 0x080c, 0xd0d8, 0x01c0, 0xa864, 0x9086, 0x0139,
-	0x1128, 0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001,
-	0x0005, 0x080c, 0x710b, 0x080c, 0xd3d4, 0x080c, 0x6e92, 0x080c,
-	0xb306, 0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x6000,
-	0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0002, 0xcd55, 0xcd85, 0xcd57,
-	0xcda6, 0xcd80, 0xcd55, 0xcd18, 0xcd1d, 0xcd1d, 0xcd18, 0xcd18,
-	0xcd18, 0xcd18, 0xcd18, 0xcd18, 0xcd18, 0x080c, 0x0dc5, 0x86ff,
-	0x1520, 0x6020, 0x9086, 0x0006, 0x0500, 0x0096, 0x6014, 0x2048,
-	0x080c, 0xd0d8, 0x0168, 0xa87c, 0xd0cc, 0x0140, 0x0096, 0xc0cc,
-	0xa87e, 0xa878, 0x2048, 0x080c, 0x0fc0, 0x009e, 0x080c, 0xd3d4,
-	0x009e, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023,
-	0x0002, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x9085, 0x0001, 0x0005,
-	0x0066, 0x080c, 0x1a8e, 0x006e, 0x0890, 0x00e6, 0x2071, 0x19e8,
-	0x7024, 0x9c06, 0x1120, 0x080c, 0xa9d3, 0x00ee, 0x0840, 0x6020,
-	0x9084, 0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049,
-	0x0001, 0x2c40, 0x080c, 0xaafb, 0x009e, 0x008e, 0x0010, 0x080c,
-	0xa8d0, 0x00ee, 0x1904, 0xcd57, 0x0804, 0xcd18, 0x0036, 0x00e6,
-	0x2071, 0x19e8, 0x703c, 0x9c06, 0x1138, 0x901e, 0x080c, 0xaa49,
-	0x00ee, 0x003e, 0x0804, 0xcd57, 0x080c, 0xac2b, 0x00ee, 0x003e,
-	0x1904, 0xcd57, 0x0804, 0xcd18, 0x00c6, 0x6020, 0x9084, 0x000f,
-	0x0013, 0x00ce, 0x0005, 0xcdd9, 0xcea3, 0xd011, 0xcde3, 0xb306,
-	0xcdd9, 0xe73c, 0xd805, 0xcea3, 0x9237, 0xd09d, 0xcdd2, 0xcdd2,
-	0xcdd2, 0xcdd2, 0x080c, 0x0dc5, 0x080c, 0xd2e0, 0x1110, 0x080c,
-	0xbcb6, 0x0005, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0804, 0xb2d3,
-	0x601b, 0x0001, 0x0005, 0x080c, 0xd0d8, 0x0130, 0x6014, 0x0096,
-	0x2048, 0x2c00, 0xa896, 0x009e, 0x6000, 0x908a, 0x0010, 0x1a0c,
-	0x0dc5, 0x0002, 0xce02, 0xce04, 0xce28, 0xce3c, 0xce62, 0xce02,
-	0xcdd9, 0xcdd9, 0xcdd9, 0xce3c, 0xce3c, 0xce02, 0xce02, 0xce02,
-	0xce02, 0xce46, 0x080c, 0x0dc5, 0x00e6, 0x6014, 0x0096, 0x2048,
-	0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071, 0x19e8, 0x7024, 0x9c06,
-	0x01a0, 0x080c, 0xa8d0, 0x080c, 0xd79d, 0x6007, 0x0085, 0x6003,
-	0x000b, 0x6023, 0x0002, 0x2001, 0x1987, 0x2004, 0x601a, 0x080c,
-	0x94ff, 0x080c, 0x9ab1, 0x00ee, 0x0005, 0x601b, 0x0001, 0x0cd8,
-	0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x080c,
-	0xd79d, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x080c,
-	0x94ff, 0x080c, 0x9ab1, 0x0005, 0x0096, 0x601b, 0x0001, 0x6014,
-	0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x57dd,
-	0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103,
-	0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b,
-	0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, 0x6e9f, 0x009e,
-	0x0804, 0xb2d3, 0x6014, 0x0096, 0x904d, 0x05c0, 0xa97c, 0xd1e4,
-	0x05a8, 0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005,
-	0xa884, 0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001,
-	0x0030, 0x2c08, 0x080c, 0x1611, 0x2001, 0x030c, 0x2004, 0x9086,
-	0x0041, 0x1198, 0x6014, 0x0096, 0x904d, 0x090c, 0x0dc5, 0xa880,
-	0xd0f4, 0x1130, 0xc0f5, 0xa882, 0x009e, 0x601b, 0x0002, 0x0068,
-	0x009e, 0x00c6, 0x080c, 0x236e, 0x00ce, 0x6000, 0x9086, 0x0004,
-	0x1120, 0x2009, 0x0048, 0x080c, 0xb352, 0x0005, 0x009e, 0x080c,
-	0x1a8e, 0x0804, 0xce28, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5,
-	0x000b, 0x0005, 0xceba, 0xcde0, 0xcebc, 0xceba, 0xcebc, 0xcebc,
-	0xcdda, 0xceba, 0xcdd4, 0xcdd4, 0xceba, 0xceba, 0xceba, 0xceba,
-	0xceba, 0xceba, 0x080c, 0x0dc5, 0x6010, 0x00b6, 0x2058, 0xb804,
-	0x9084, 0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0dc5, 0x00b6,
-	0x0013, 0x00be, 0x0005, 0xced7, 0xcfa8, 0xced9, 0xcf19, 0xced9,
-	0xcf19, 0xced9, 0xcee7, 0xced7, 0xcf19, 0xced7, 0xcf08, 0x080c,
-	0x0dc5, 0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8,
-	0x908e, 0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xcfa4, 0x6004,
-	0x080c, 0xd2e0, 0x0904, 0xcfc1, 0x908e, 0x0004, 0x1110, 0x080c,
-	0x3279, 0x908e, 0x0021, 0x0904, 0xcfc5, 0x908e, 0x0022, 0x0904,
-	0xd00c, 0x908e, 0x003d, 0x0904, 0xcfc5, 0x908e, 0x0039, 0x0904,
-	0xcfc9, 0x908e, 0x0035, 0x0904, 0xcfc9, 0x908e, 0x001e, 0x0178,
-	0x908e, 0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff,
-	0x9086, 0x0006, 0x0110, 0x080c, 0x3250, 0x080c, 0xbcb6, 0x0804,
-	0xb306, 0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xcf95,
-	0x9186, 0x0002, 0x1904, 0xcf6a, 0x2001, 0x1837, 0x2004, 0xd08c,
-	0x11c8, 0x080c, 0x7637, 0x11b0, 0x080c, 0xd7e3, 0x0138, 0x080c,
-	0x765a, 0x1120, 0x080c, 0x7541, 0x0804, 0xcff5, 0x2001, 0x197d,
-	0x2003, 0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x7563,
-	0x0804, 0xcff5, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x0080, 0x0130,
-	0x2001, 0x1837, 0x2004, 0xd0ac, 0x1904, 0xcff5, 0xb8a0, 0x9082,
-	0x0081, 0x1a04, 0xcff5, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190,
-	0x8001, 0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398,
-	0x6043, 0x0000, 0x080c, 0xb27d, 0x0128, 0x2b00, 0x6012, 0x6023,
-	0x0001, 0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0,
-	0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837,
-	0x2104, 0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x60c1,
-	0x00ee, 0x080c, 0xbcb6, 0x0030, 0x080c, 0xbcb6, 0x080c, 0x3250,
-	0x080c, 0xd7f8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3279,
-	0x012e, 0x00ee, 0x080c, 0xb306, 0x0005, 0x2001, 0x0002, 0x080c,
-	0x666a, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c,
-	0x9ab1, 0x00de, 0x00ce, 0x0c80, 0x080c, 0x3279, 0x0804, 0xcf15,
-	0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058,
-	0xb840, 0x9084, 0x00ff, 0x9005, 0x0904, 0xcf6a, 0x8001, 0xb842,
-	0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00de, 0x00ce,
-	0x0898, 0x080c, 0xbcb6, 0x0804, 0xcf17, 0x080c, 0xbcf2, 0x0804,
-	0xcf17, 0x00d6, 0x2c68, 0x6104, 0x080c, 0xd759, 0x00de, 0x0118,
-	0x080c, 0xb2d3, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff,
-	0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002,
-	0x603c, 0x600a, 0x2001, 0x1987, 0x2004, 0x601a, 0x602c, 0x2c08,
-	0x2060, 0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160,
-	0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x00de, 0x00ce, 0x080c,
-	0xbcb6, 0x080c, 0x3250, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x3279, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x6043,
-	0x0000, 0x012e, 0x00ee, 0x0005, 0x080c, 0xb708, 0x1904, 0xcfc1,
-	0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x0096, 0x00d6,
-	0x001b, 0x00de, 0x009e, 0x0005, 0xd02c, 0xd02c, 0xd02c, 0xd02c,
-	0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xcdd9, 0xd02c, 0xcde0,
-	0xd02e, 0xcde0, 0xd048, 0xd02c, 0x080c, 0x0dc5, 0x6004, 0x9086,
-	0x008b, 0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035,
-	0x1130, 0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007,
-	0x008b, 0x6003, 0x000d, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005,
-	0x080c, 0xd7d7, 0x0118, 0x080c, 0xd7ea, 0x0010, 0x080c, 0xd7f8,
-	0x080c, 0xd2c3, 0x080c, 0xd0d8, 0x0570, 0x080c, 0x3250, 0x080c,
-	0xd0d8, 0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006,
-	0xa877, 0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x6e9f, 0x2c68,
-	0x080c, 0xb27d, 0x0150, 0x6810, 0x6012, 0x080c, 0xd554, 0x00c6,
-	0x2d60, 0x080c, 0xb306, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000,
-	0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547,
-	0x080c, 0x9ab1, 0x00c8, 0x080c, 0xd7d7, 0x0138, 0x6034, 0x9086,
-	0x4000, 0x1118, 0x080c, 0x3250, 0x08d0, 0x6034, 0x908c, 0xff00,
-	0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c,
-	0x3250, 0x0868, 0x080c, 0xb306, 0x0005, 0x6000, 0x908a, 0x0010,
-	0x1a0c, 0x0dc5, 0x0002, 0xd0b3, 0xd0b3, 0xd0b7, 0xd0b5, 0xd0c1,
-	0xd0b3, 0xd0b3, 0xb306, 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b3,
-	0xd0b3, 0xd0b3, 0xd0b3, 0x080c, 0x0dc5, 0x080c, 0xac2b, 0x6114,
-	0x0096, 0x2148, 0xa87b, 0x0006, 0x080c, 0x6e9f, 0x009e, 0x0804,
-	0xb2d3, 0x601c, 0xd084, 0x190c, 0x1a8e, 0x0c88, 0x9284, 0x0007,
-	0x1158, 0x9282, 0x1cd0, 0x0240, 0x2001, 0x181a, 0x2004, 0x9202,
-	0x1218, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0096, 0x0028,
-	0x0096, 0x0006, 0x6014, 0x2048, 0x000e, 0x0006, 0x9984, 0xf000,
-	0x9086, 0xf000, 0x0110, 0x080c, 0x10b9, 0x000e, 0x009e, 0x0005,
-	0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126, 0x2091, 0x8000, 0x2061,
-	0x1cd0, 0x2071, 0x1800, 0x7354, 0x7074, 0x9302, 0x1640, 0x6020,
-	0x9206, 0x11f8, 0x080c, 0xd7e3, 0x0180, 0x9286, 0x0001, 0x1168,
-	0x6004, 0x9086, 0x0004, 0x1148, 0x080c, 0x3250, 0x080c, 0xd7f8,
-	0x00c6, 0x080c, 0xb306, 0x00ce, 0x0060, 0x080c, 0xd4ce, 0x0148,
-	0x080c, 0xd2e0, 0x1110, 0x080c, 0xbcb6, 0x00c6, 0x080c, 0xb2d3,
-	0x00ce, 0x9ce0, 0x0018, 0x7068, 0x9c02, 0x1208, 0x08a0, 0x012e,
-	0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0016,
-	0x9188, 0x1000, 0x210c, 0x81ff, 0x0128, 0x2061, 0x1ab7, 0x6112,
-	0x080c, 0x3250, 0x9006, 0x0010, 0x9085, 0x0001, 0x001e, 0x00ce,
-	0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d,
-	0x01b0, 0x6656, 0x2b00, 0x6012, 0x080c, 0x57dd, 0x0118, 0x080c,
-	0xd207, 0x0168, 0x080c, 0xd554, 0x6023, 0x0003, 0x2009, 0x004b,
-	0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006,
-	0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0xbaa0, 0x080c, 0xb325,
-	0x0560, 0x6057, 0x0000, 0x2b00, 0x6012, 0x080c, 0xd554, 0x6023,
-	0x0003, 0x0016, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c, 0x9577,
-	0x2c08, 0x080c, 0xe91c, 0x007e, 0x001e, 0xd184, 0x0128, 0x080c,
-	0xb2d3, 0x9085, 0x0001, 0x0070, 0x080c, 0x57dd, 0x0128, 0xd18c,
-	0x1170, 0x080c, 0xd207, 0x0148, 0x2009, 0x004c, 0x080c, 0xb352,
-	0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900,
-	0x6016, 0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6,
-	0x00c6, 0x0046, 0x0016, 0x080c, 0xb27d, 0x2c78, 0x05a0, 0x7e56,
-	0x2b00, 0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c,
-	0xd219, 0x001e, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148,
-	0x2001, 0x1980, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xb2d3,
-	0x00d0, 0x2001, 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c,
-	0xb2d3, 0x0088, 0x2f60, 0x080c, 0x57dd, 0x0138, 0xd18c, 0x1118,
-	0x04f1, 0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c,
-	0xb352, 0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005,
-	0x00f6, 0x00c6, 0x0046, 0x080c, 0xb27d, 0x2c78, 0x0508, 0x7e56,
-	0x2b00, 0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489,
-	0x009e, 0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c,
-	0xb2d3, 0x0060, 0x2f60, 0x080c, 0x57dd, 0x0120, 0xd18c, 0x1160,
-	0x0071, 0x0130, 0x2009, 0x0052, 0x080c, 0xb352, 0x9085, 0x0001,
-	0x004e, 0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6,
-	0x080c, 0x4be4, 0x00ce, 0x1120, 0x080c, 0xb2d3, 0x9006, 0x0005,
-	0xa867, 0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001,
-	0x0005, 0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0x6858,
-	0x0158, 0x2001, 0xd21e, 0x0006, 0x900e, 0x2400, 0x080c, 0x710b,
-	0x080c, 0x6e9f, 0x000e, 0x0807, 0x2418, 0x080c, 0x993f, 0xbaa0,
-	0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c, 0x96bc,
-	0x008e, 0x080c, 0x9577, 0x2f08, 0x2648, 0x080c, 0xe91c, 0xb93c,
-	0x81ff, 0x090c, 0x978f, 0x080c, 0x9ab1, 0x012e, 0x007e, 0x009e,
-	0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0190,
-	0x660a, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900,
-	0x6016, 0x2009, 0x001f, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e,
-	0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000,
-	0x080c, 0xb325, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd554,
-	0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c, 0x1768,
-	0x00fe, 0x2009, 0x0021, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e,
-	0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6, 0x0126,
-	0x0016, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0198, 0x660a, 0x2b08,
-	0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900, 0x6016, 0x001e,
-	0x0016, 0x080c, 0xb352, 0x9085, 0x0001, 0x001e, 0x012e, 0x00ce,
-	0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c,
-	0xb325, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001,
-	0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xb352, 0x9085, 0x0001,
-	0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044, 0x0830,
-	0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258, 0xba3c,
-	0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be, 0x002e, 0x0005, 0x0006,
-	0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e, 0x0003, 0x0128,
-	0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005,
-	0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004, 0x01a8, 0x6014,
-	0x904d, 0x080c, 0xd0d8, 0x0180, 0xa864, 0x9086, 0x0139, 0x0170,
-	0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002, 0x0128, 0xa868,
-	0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x009e, 0x008e,
-	0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb325,
-	0x0198, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900,
-	0x6016, 0x080c, 0x3250, 0x2009, 0x0028, 0x080c, 0xb352, 0x9085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x9186, 0x0015,
-	0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074, 0x1178, 0x00b6,
-	0x080c, 0xbf63, 0x00be, 0x080c, 0xc1df, 0x6003, 0x0001, 0x6007,
-	0x0029, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0078, 0x6014, 0x0096,
-	0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001, 0x0001, 0x080c,
-	0xd71a, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x0005, 0x0096, 0x6014,
-	0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897,
-	0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6e9f, 0x012e, 0x009e, 0x080c, 0xb2d3, 0x0c30, 0x0096,
-	0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c, 0x666a, 0x00e8,
-	0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014,
-	0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x67bf, 0x00be, 0x080c,
-	0xc2b5, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890, 0x00be, 0x9005,
-	0x0160, 0x2001, 0x0006, 0x080c, 0x666a, 0x6014, 0x2048, 0xa868,
-	0xd0fc, 0x0170, 0x080c, 0xb6dc, 0x0048, 0x6014, 0x2048, 0xa868,
-	0xd0fc, 0x0528, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x009e, 0x0005,
-	0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0000,
-	0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c, 0x6944, 0x1108,
-	0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x08f8, 0x6014,
-	0x904d, 0x090c, 0x0dc5, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897,
-	0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x0840, 0xa878, 0x9086,
-	0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad, 0xa882, 0x0005,
-	0x6043, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001, 0x6007, 0x0050,
-	0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x00c6, 0x6010, 0x00b6,
-	0x2058, 0xb800, 0x00be, 0xd0bc, 0x0120, 0x6020, 0x9084, 0x000f,
-	0x0013, 0x00ce, 0x0005, 0xcdd9, 0xd404, 0xd404, 0xd407, 0xec80,
-	0xec9b, 0xec9e, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd9,
-	0xcdd9, 0xcdd9, 0x080c, 0x0dc5, 0xa001, 0xa001, 0x0005, 0x0096,
-	0x6014, 0x904d, 0x0118, 0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010,
-	0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc,
-	0x0550, 0x2001, 0x1834, 0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78,
-	0x080c, 0xb27d, 0x0508, 0x7810, 0x6012, 0x080c, 0xd554, 0x7820,
-	0x9086, 0x0003, 0x0128, 0x7808, 0x603a, 0x2f00, 0x603e, 0x0020,
-	0x7808, 0x603e, 0x2f00, 0x603a, 0x602e, 0x6023, 0x0001, 0x6007,
-	0x0035, 0x6003, 0x0001, 0x7954, 0x6156, 0x080c, 0x94ff, 0x080c,
-	0x9ab1, 0x2f60, 0x00fe, 0x0005, 0x2f60, 0x00fe, 0x2001, 0x1988,
-	0x2004, 0x6042, 0x0005, 0x0016, 0x0096, 0x6814, 0x2048, 0xa87c,
-	0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000, 0xa893, 0x0000,
-	0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e, 0xa878, 0x2048,
-	0x080c, 0x0fc0, 0x6830, 0x6036, 0x908e, 0x0001, 0x0148, 0x6803,
-	0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e, 0x6032, 0x00d0,
-	0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824, 0xc0f4, 0x9085,
-	0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938, 0x9102, 0xa8b0,
-	0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838, 0x9084, 0xfffc,
-	0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e, 0x6910, 0x6112,
-	0x6954, 0x6156, 0x6023, 0x0001, 0x6007, 0x0039, 0x6003, 0x0001,
-	0x080c, 0x94ff, 0x080c, 0x9ab1, 0x009e, 0x001e, 0x0005, 0x6024,
-	0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a, 0x603c, 0x9303,
-	0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5, 0x0098, 0x643a,
-	0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400, 0xacac, 0x9402,
-	0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e, 0x004e, 0x6024,
-	0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138, 0xa83c, 0x603a,
-	0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005, 0x0006, 0x0016,
-	0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035, 0x01a0, 0x908e,
-	0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e, 0x0038, 0x0158,
-	0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128, 0x908e, 0x003b,
-	0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016,
-	0x0026, 0x0036, 0x00e6, 0x2001, 0x1982, 0x200c, 0x8000, 0x2014,
-	0x2001, 0x0032, 0x080c, 0x9375, 0x2001, 0x1986, 0x82ff, 0x1110,
-	0x2011, 0x0014, 0x2202, 0x2001, 0x1984, 0x200c, 0x8000, 0x2014,
-	0x2071, 0x196c, 0x711a, 0x721e, 0x2001, 0x0064, 0x080c, 0x9375,
-	0x2001, 0x1987, 0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001,
-	0x1988, 0x9288, 0x000a, 0x2102, 0x2001, 0x1a98, 0x2102, 0x2001,
-	0x0032, 0x080c, 0x1611, 0x080c, 0x6a84, 0x00ee, 0x003e, 0x002e,
-	0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1986,
-	0x2003, 0x0028, 0x2001, 0x1987, 0x2003, 0x0014, 0x2071, 0x196c,
-	0x701b, 0x0000, 0x701f, 0x07d0, 0x2001, 0x1988, 0x2009, 0x001e,
-	0x2102, 0x2001, 0x1a98, 0x2102, 0x2001, 0x0032, 0x080c, 0x1611,
-	0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6058, 0x904d, 0x0110,
-	0x080c, 0x1040, 0x009e, 0x0005, 0x0005, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x080c, 0xb27d, 0x0180, 0x2b08, 0x6112, 0x0ca9, 0x6023,
-	0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c, 0xb352, 0x9085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x00e6,
-	0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1520, 0x7090, 0x9086,
-	0x0018, 0x0120, 0x7090, 0x9086, 0x0014, 0x11e0, 0x6014, 0x2048,
-	0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x9d4c, 0x01d8, 0x707c,
-	0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206, 0x1140, 0x6210,
-	0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c, 0x3299, 0x080c,
-	0xb6dc, 0x0020, 0x080c, 0xbcb6, 0x080c, 0xb2d3, 0x00fe, 0x00ee,
-	0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48, 0x0c80, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x080c, 0xb27d, 0x0188, 0x2b08, 0x6112,
-	0x080c, 0xd554, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x004d,
-	0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006,
-	0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016, 0x080c, 0xb27d,
-	0x0180, 0x2b08, 0x6112, 0x080c, 0xd554, 0x6023, 0x0001, 0x2900,
-	0x6016, 0x001e, 0x080c, 0xb352, 0x9085, 0x0001, 0x012e, 0x00ce,
-	0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026, 0x0036, 0x0046,
-	0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186,
-	0x0015, 0x1568, 0x7190, 0x6014, 0x2048, 0xa814, 0x8003, 0x9106,
-	0x1530, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, 0x0000, 0x6014,
-	0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007, 0x9094, 0x003f,
-	0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1,
-	0x0016, 0x200c, 0x080c, 0xde2e, 0x001e, 0xa804, 0x9005, 0x0110,
-	0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103, 0x0010, 0x080c,
-	0xbcb6, 0x080c, 0xb2d3, 0x00fe, 0x00ee, 0x009e, 0x006e, 0x005e,
-	0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096, 0x00e6, 0x00f6,
-	0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x7090, 0x9086, 0x0004,
-	0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9d4c, 0x01a8, 0x707c,
-	0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, 0x9206, 0x1110, 0x080c,
-	0x3250, 0x080c, 0xb6dc, 0x0020, 0x080c, 0xbcb6, 0x080c, 0xb2d3,
-	0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78, 0x9206, 0x0d78,
-	0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015,
-	0x1550, 0x7090, 0x9086, 0x0004, 0x1530, 0x6014, 0x2048, 0x2c78,
-	0x080c, 0x9d4c, 0x05f0, 0x707c, 0xaacc, 0x9206, 0x1180, 0x7080,
-	0xaad0, 0x9206, 0x1160, 0x080c, 0x3250, 0x0016, 0xa998, 0xaab0,
-	0x9284, 0x1000, 0xc0fd, 0x080c, 0x5784, 0x001e, 0x0010, 0x080c,
-	0x556f, 0x080c, 0xd0d8, 0x0508, 0xa87b, 0x0000, 0xa883, 0x0000,
-	0xa897, 0x4000, 0x0080, 0x080c, 0xd0d8, 0x01b8, 0x6014, 0x2048,
-	0x080c, 0x556f, 0x1d70, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897,
-	0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, 0x8000, 0xa867, 0x0139,
-	0x080c, 0x6e9f, 0x012e, 0x080c, 0xb2d3, 0x00fe, 0x00ee, 0x009e,
-	0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, 0x0888, 0x0016, 0x0026,
-	0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100, 0x9205, 0x0150,
-	0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120, 0xa992, 0xaa8e,
-	0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00b6, 0x00d6, 0x0036,
-	0x080c, 0xd0d8, 0x0904, 0xd716, 0x0096, 0x6314, 0x2348, 0xa87a,
-	0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6, 0x2358, 0x2009,
-	0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6944, 0x1108, 0xc185,
-	0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a, 0x20a9, 0x0004,
-	0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0,
-	0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0f8b, 0x20a9, 0x0004,
-	0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080, 0x000a, 0x2098,
-	0x080c, 0x0f8b, 0x00ce, 0x0090, 0xaa96, 0x3918, 0x9398, 0x0007,
-	0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b, 0x0004, 0xaba2,
-	0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, 0xa89e, 0xa868, 0xc0f4,
-	0xa86a, 0x080c, 0x6e92, 0x6017, 0x0000, 0x009e, 0x003e, 0x00de,
-	0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6, 0x0096, 0x00f6,
-	0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260, 0x9096, 0x0000,
-	0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c, 0x2873, 0x2118,
-	0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff, 0x931d, 0x7c3c,
-	0x2011, 0x8018, 0x080c, 0x4c44, 0x00a8, 0x9096, 0x0001, 0x1148,
-	0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6, 0x783c, 0xa8aa,
-	0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d, 0x7838, 0xa8a6,
-	0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e, 0x003e, 0x002e,
-	0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035, 0x0110, 0x6a38,
-	0x0008, 0x6a2c, 0x080c, 0xd0c6, 0x01f0, 0x2260, 0x6120, 0x9186,
-	0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838, 0x9206, 0x0140,
-	0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106, 0x1140, 0x0020,
-	0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910, 0x9106, 0x001e,
-	0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8, 0xa974, 0xd1cc,
-	0x0198, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1170, 0xa9a8, 0x918c,
-	0x000f, 0x918e, 0x0001, 0x1140, 0xa87c, 0xd0ac, 0x0128, 0xa834,
-	0xa938, 0x9115, 0x190c, 0xc78b, 0x0005, 0x0036, 0x2019, 0x0001,
-	0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c, 0xd0d8, 0x01c8,
-	0x080c, 0xd2c3, 0x6037, 0x4000, 0x6014, 0x6017, 0x0000, 0x0096,
-	0x2048, 0xa87c, 0x080c, 0xd2e0, 0x1118, 0x080c, 0xbcb6, 0x0040,
-	0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129, 0x080c, 0x6e9f,
-	0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128, 0xa87b, 0x0006,
-	0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b, 0x0002, 0x0020,
-	0xa87b, 0x0005, 0x080c, 0xd3d4, 0xa877, 0x0000, 0x0005, 0x2001,
-	0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004,
-	0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810, 0x2004, 0xd0e4,
-	0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0,
-	0x00be, 0x2021, 0x0007, 0x080c, 0x4dfb, 0x004e, 0x003e, 0x0005,
-	0x0c51, 0x1d81, 0x0005, 0x2001, 0x1986, 0x2004, 0x601a, 0x0005,
-	0x2001, 0x1988, 0x2004, 0x6042, 0x0005, 0x080c, 0xb2d3, 0x0804,
-	0x9ab1, 0x2001, 0x0109, 0x2004, 0xd084, 0x01e0, 0x0126, 0x2091,
-	0x2800, 0x0006, 0x0016, 0x0026, 0x0036, 0x00f6, 0x00e6, 0x00c6,
-	0x2079, 0x19e8, 0x2071, 0x1800, 0x2061, 0x0100, 0x080c, 0x93e2,
-	0x00ce, 0x00ee, 0x00fe, 0x003e, 0x002e, 0x001e, 0x000e, 0x012e,
-	0x9085, 0x0001, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010,
-	0x1a0c, 0x0dc5, 0x001b, 0x006e, 0x00be, 0x0005, 0xd846, 0xdf8d,
-	0xe102, 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0xd87d, 0xe186,
-	0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0xd846, 0x080c, 0x0dc5,
-	0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0dc5, 0x0013, 0x006e,
-	0x0005, 0xd861, 0xe6d5, 0xd861, 0xd861, 0xd861, 0xd861, 0xd861,
-	0xd861, 0xe682, 0xe729, 0xd861, 0xedb4, 0xedea, 0xedb4, 0xedea,
-	0xd861, 0x080c, 0x0dc5, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0dc5,
-	0x6000, 0x000a, 0x0005, 0xd87b, 0xe364, 0xe433, 0xe456, 0xe516,
-	0xd87b, 0xe5f5, 0xe59e, 0xe192, 0xe658, 0xe66d, 0xd87b, 0xd87b,
-	0xd87b, 0xd87b, 0xd87b, 0x080c, 0x0dc5, 0x91b2, 0x0053, 0x1a0c,
-	0x0dc5, 0x2100, 0x91b2, 0x0040, 0x1a04, 0xdcfd, 0x0002, 0xd8c7,
-	0xdacb, 0xd8c7, 0xd8c7, 0xd8c7, 0xdad4, 0xd8c7, 0xd8c7, 0xd8c7,
-	0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7,
-	0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c9, 0xd92c,
-	0xd93b, 0xd99f, 0xd9ca, 0xda43, 0xdab6, 0xd8c7, 0xd8c7, 0xdad7,
-	0xd8c7, 0xd8c7, 0xdaec, 0xdaf9, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7,
-	0xd8c7, 0xdb9f, 0xd8c7, 0xd8c7, 0xdbb3, 0xd8c7, 0xd8c7, 0xdb6e,
-	0xd8c7, 0xd8c7, 0xd8c7, 0xdbcb, 0xd8c7, 0xd8c7, 0xd8c7, 0xdc48,
-	0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xd8c7, 0xdcc5, 0x080c,
-	0x0dc5, 0x080c, 0x6a61, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc,
-	0x1128, 0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009,
-	0x602f, 0x0009, 0x6017, 0x0000, 0x0804, 0xdac4, 0x080c, 0x69fd,
-	0x00e6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0,
-	0x0026, 0x2019, 0x0029, 0x080c, 0x96a4, 0x0076, 0x903e, 0x080c,
-	0x9577, 0x2c08, 0x080c, 0xe91c, 0x007e, 0x001e, 0x001e, 0x002e,
-	0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658, 0x080c, 0x6733, 0xbe04,
-	0x9684, 0x00ff, 0x9082, 0x0006, 0x1268, 0x0016, 0x0026, 0x6210,
-	0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08, 0x080c, 0xf015, 0x002e,
-	0x001e, 0x1178, 0x080c, 0xe84e, 0x1904, 0xd997, 0x080c, 0xe7ea,
-	0x1120, 0x6007, 0x0008, 0x0804, 0xdac4, 0x6007, 0x0009, 0x0804,
-	0xdac4, 0x080c, 0xeab9, 0x0128, 0x080c, 0xe84e, 0x0d78, 0x0804,
-	0xd997, 0x6017, 0x1900, 0x0c88, 0x080c, 0x3374, 0x1904, 0xdcfa,
-	0x6106, 0x080c, 0xe78e, 0x6007, 0x0006, 0x0804, 0xdac4, 0x6007,
-	0x0007, 0x0804, 0xdac4, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c,
-	0x3374, 0x1904, 0xdcfa, 0x00d6, 0x6610, 0x2658, 0xbe04, 0x9684,
-	0x00ff, 0x9082, 0x0006, 0x1220, 0x2001, 0x0001, 0x080c, 0x6656,
-	0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0188, 0x9686, 0x0004,
-	0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0140, 0x9686,
-	0x0004, 0x0128, 0x9686, 0x0005, 0x0110, 0x00de, 0x0480, 0x00e6,
-	0x2071, 0x0260, 0x7034, 0x9084, 0x0003, 0x1140, 0x7034, 0x9082,
-	0x0014, 0x0220, 0x7030, 0x9084, 0x0003, 0x0130, 0x00ee, 0x6017,
-	0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee, 0x080c, 0xe8b2, 0x1190,
-	0x9686, 0x0006, 0x1140, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e,
-	0x080c, 0x3299, 0x002e, 0x080c, 0x67bf, 0x6007, 0x000a, 0x00de,
-	0x0804, 0xdac4, 0x6007, 0x000b, 0x00de, 0x0804, 0xdac4, 0x080c,
-	0x3250, 0x080c, 0xd7f8, 0x6007, 0x0001, 0x0804, 0xdac4, 0x080c,
-	0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2071,
-	0x0260, 0x7034, 0x90b4, 0x0003, 0x1948, 0x90b2, 0x0014, 0x0a30,
-	0x7030, 0x9084, 0x0003, 0x1910, 0x6610, 0x2658, 0xbe04, 0x9686,
-	0x0707, 0x09e8, 0x0026, 0x6210, 0x2258, 0xbaa0, 0x900e, 0x080c,
-	0x3299, 0x002e, 0x6007, 0x000c, 0x2001, 0x0001, 0x080c, 0xeff4,
-	0x0804, 0xdac4, 0x080c, 0x6a61, 0x1140, 0x2001, 0x1837, 0x2004,
-	0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd8d6, 0x080c,
-	0x69fd, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006,
-	0x06c8, 0x1138, 0x0026, 0x2001, 0x0006, 0x080c, 0x6696, 0x002e,
-	0x0050, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686,
-	0x0006, 0x1904, 0xd997, 0x080c, 0xe8bf, 0x1120, 0x6007, 0x000e,
-	0x0804, 0xdac4, 0x0046, 0x6410, 0x2458, 0xbca0, 0x0046, 0x080c,
-	0x3250, 0x080c, 0xd7f8, 0x004e, 0x0016, 0x9006, 0x2009, 0x1848,
-	0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c, 0xec31, 0x6010,
-	0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e, 0x6007, 0x0001,
-	0x0804, 0xdac4, 0x2001, 0x0001, 0x080c, 0x6656, 0x0156, 0x0016,
-	0x0026, 0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0270,
-	0x080c, 0xc365, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0168,
-	0x96b4, 0xff00, 0x8637, 0x9682, 0x0004, 0x0a04, 0xd997, 0x9682,
-	0x0007, 0x0a04, 0xd9f3, 0x0804, 0xd997, 0x6017, 0x1900, 0x6007,
-	0x0009, 0x0804, 0xdac4, 0x080c, 0x6a61, 0x1140, 0x2001, 0x1837,
-	0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110, 0x0804, 0xd8d6,
-	0x080c, 0x69fd, 0x6610, 0x2658, 0xbe04, 0x9684, 0x00ff, 0x0006,
-	0x0016, 0x908e, 0x0001, 0x0118, 0x908e, 0x0000, 0x1118, 0x001e,
-	0x000e, 0x0080, 0x001e, 0x000e, 0x9082, 0x0006, 0x06a0, 0x0150,
-	0x96b4, 0xff00, 0x8637, 0x9686, 0x0004, 0x0120, 0x9686, 0x0006,
-	0x1904, 0xd997, 0x080c, 0xe8ed, 0x1138, 0x080c, 0xe7ea, 0x1120,
-	0x6007, 0x0010, 0x0804, 0xdac4, 0x0046, 0x6410, 0x2458, 0xbca0,
-	0x0046, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x004e, 0x0016, 0x9006,
-	0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029, 0x080c,
-	0xec31, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e, 0x004e,
-	0x6007, 0x0001, 0x0448, 0x080c, 0xeab9, 0x0198, 0x0016, 0x968c,
-	0x00ff, 0x9186, 0x0002, 0x0160, 0x9186, 0x0003, 0x0148, 0x001e,
-	0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0920, 0x0804, 0xd997,
-	0x001e, 0x6017, 0x1900, 0x6007, 0x0009, 0x0070, 0x080c, 0x3374,
-	0x1904, 0xdcfa, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, 0xdecb,
-	0x1904, 0xd997, 0x6007, 0x0012, 0x6003, 0x0001, 0x080c, 0x9547,
-	0x080c, 0x9ab1, 0x0005, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c,
-	0x9547, 0x080c, 0x9ab1, 0x0cb0, 0x6007, 0x0005, 0x0c68, 0x080c,
-	0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x080c,
-	0xdecb, 0x1904, 0xd997, 0x6007, 0x0020, 0x6003, 0x0001, 0x080c,
-	0x9547, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x3374, 0x1904, 0xdcfa,
-	0x6007, 0x0023, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1,
-	0x0005, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c, 0x3374, 0x1904,
-	0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x0016, 0x0026, 0x00e6,
-	0x2071, 0x0260, 0x2c08, 0x2011, 0x1820, 0x2214, 0x703c, 0x9206,
-	0x11e0, 0x2011, 0x181f, 0x2214, 0x7038, 0x9084, 0x00ff, 0x9206,
-	0x11a0, 0x7240, 0x080c, 0xd0c6, 0x0570, 0x2260, 0x6008, 0x9086,
-	0xffff, 0x0120, 0x7244, 0x6008, 0x9206, 0x1528, 0x6020, 0x9086,
-	0x0007, 0x1508, 0x080c, 0xb2d3, 0x04a0, 0x7244, 0x9286, 0xffff,
-	0x0180, 0x2c08, 0x080c, 0xd0c6, 0x01b0, 0x2260, 0x7240, 0x6008,
-	0x9206, 0x1188, 0x6010, 0x9190, 0x0004, 0x2214, 0x9206, 0x01b8,
-	0x0050, 0x7240, 0x2c08, 0x9006, 0x080c, 0xebfb, 0x1180, 0x7244,
-	0x9286, 0xffff, 0x01b0, 0x2160, 0x6007, 0x0026, 0x6017, 0x1700,
-	0x7214, 0x9296, 0xffff, 0x1180, 0x6007, 0x0025, 0x0068, 0x6020,
-	0x9086, 0x0007, 0x1d80, 0x6004, 0x9086, 0x0024, 0x1110, 0x080c,
-	0xb2d3, 0x2160, 0x6007, 0x0025, 0x6003, 0x0001, 0x080c, 0x9547,
-	0x080c, 0x9ab1, 0x00ee, 0x002e, 0x001e, 0x0005, 0x2001, 0x0001,
-	0x080c, 0x6656, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004,
-	0x2019, 0x1805, 0x2011, 0x0276, 0x080c, 0xc365, 0x003e, 0x002e,
-	0x001e, 0x015e, 0x0120, 0x6007, 0x0031, 0x0804, 0xdac4, 0x080c,
-	0xbf7b, 0x080c, 0x7637, 0x1190, 0x0006, 0x0026, 0x0036, 0x080c,
-	0x7651, 0x1138, 0x080c, 0x7932, 0x080c, 0x612e, 0x080c, 0x7563,
-	0x0010, 0x080c, 0x760f, 0x003e, 0x002e, 0x000e, 0x0005, 0x080c,
-	0x3374, 0x1904, 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x6106,
-	0x080c, 0xdee7, 0x1120, 0x6007, 0x002b, 0x0804, 0xdac4, 0x6007,
-	0x002c, 0x0804, 0xdac4, 0x080c, 0xee26, 0x1904, 0xdcfa, 0x080c,
-	0x3374, 0x1904, 0xdcfa, 0x080c, 0xdecb, 0x1904, 0xd997, 0x6106,
-	0x080c, 0xdeec, 0x1120, 0x6007, 0x002e, 0x0804, 0xdac4, 0x6007,
-	0x002f, 0x0804, 0xdac4, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x00e6,
-	0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904, 0x9184, 0x00ff, 0x9086,
-	0x0006, 0x0158, 0x9184, 0xff00, 0x8007, 0x9086, 0x0006, 0x0128,
-	0x00ce, 0x00de, 0x00ee, 0x0804, 0xdacb, 0x080c, 0x57d9, 0xd0e4,
-	0x0904, 0xdc45, 0x2071, 0x026c, 0x7010, 0x603a, 0x7014, 0x603e,
-	0x7108, 0x720c, 0x080c, 0x6a9f, 0x0140, 0x6010, 0x2058, 0xb810,
-	0x9106, 0x1118, 0xb814, 0x9206, 0x0510, 0x080c, 0x6a9b, 0x15b8,
-	0x2069, 0x1800, 0x6880, 0x9206, 0x1590, 0x687c, 0x9106, 0x1578,
-	0x7210, 0x080c, 0xd0c6, 0x0590, 0x080c, 0xddb8, 0x0578, 0x080c,
-	0xecad, 0x0560, 0x622e, 0x6007, 0x0036, 0x6003, 0x0001, 0x080c,
-	0x94ff, 0x080c, 0x9ab1, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x7214,
-	0x9286, 0xffff, 0x0150, 0x080c, 0xd0c6, 0x01c0, 0x9280, 0x0002,
-	0x2004, 0x7110, 0x9106, 0x1190, 0x08e0, 0x7210, 0x2c08, 0x9085,
-	0x0001, 0x080c, 0xebfb, 0x2c10, 0x2160, 0x0140, 0x0890, 0x6007,
-	0x0037, 0x602f, 0x0009, 0x6017, 0x1500, 0x08b8, 0x6007, 0x0037,
-	0x602f, 0x0003, 0x6017, 0x1700, 0x0880, 0x6007, 0x0012, 0x0868,
-	0x080c, 0x3374, 0x1904, 0xdcfa, 0x6010, 0x2058, 0xb804, 0x9084,
-	0xff00, 0x8007, 0x9086, 0x0006, 0x1904, 0xdacb, 0x00e6, 0x00d6,
-	0x00c6, 0x080c, 0x57d9, 0xd0e4, 0x0904, 0xdcbd, 0x2069, 0x1800,
-	0x2071, 0x026c, 0x7008, 0x603a, 0x720c, 0x623e, 0x9286, 0xffff,
-	0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085, 0x0001, 0x080c, 0xebfb,
-	0x2c10, 0x00ce, 0x05e8, 0x080c, 0xd0c6, 0x05d0, 0x7108, 0x9280,
-	0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6, 0x0026, 0x2260, 0x080c,
-	0xcce6, 0x002e, 0x00ce, 0x7118, 0x918c, 0xff00, 0x810f, 0x9186,
-	0x0001, 0x0178, 0x9186, 0x0005, 0x0118, 0x9186, 0x0007, 0x1198,
-	0x9280, 0x0005, 0x2004, 0x9005, 0x0170, 0x080c, 0xddb8, 0x0904,
-	0xdc3e, 0x0056, 0x7510, 0x7614, 0x080c, 0xecc6, 0x005e, 0x00ce,
-	0x00de, 0x00ee, 0x0005, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017,
-	0x2a00, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0c78,
-	0x6007, 0x003b, 0x602f, 0x0003, 0x6017, 0x0300, 0x6003, 0x0001,
-	0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0c10, 0x6007, 0x003b, 0x602f,
-	0x000b, 0x6017, 0x0000, 0x0804, 0xdc15, 0x00e6, 0x0026, 0x080c,
-	0x6a61, 0x0550, 0x080c, 0x69fd, 0x080c, 0xee97, 0x1518, 0x2071,
-	0x1800, 0x70dc, 0x9085, 0x0003, 0x70de, 0x00f6, 0x2079, 0x0100,
-	0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6, 0x9284, 0xff00, 0x7280,
-	0x9205, 0x7082, 0x78ea, 0x00fe, 0x70e7, 0x0000, 0x080c, 0x6a9f,
-	0x0120, 0x2011, 0x1a01, 0x2013, 0x07d0, 0xd0ac, 0x1128, 0x080c,
-	0x3000, 0x0010, 0x080c, 0xeecb, 0x002e, 0x00ee, 0x080c, 0xb2d3,
-	0x0804, 0xdaca, 0x080c, 0xb2d3, 0x0005, 0x2600, 0x0002, 0xdd11,
-	0xdd3f, 0xdd50, 0xdd11, 0xdd11, 0xdd13, 0xdd61, 0xdd11, 0xdd11,
-	0xdd11, 0xdd2d, 0xdd11, 0xdd11, 0xdd11, 0xdd6c, 0xdd82, 0xddb3,
-	0xdd11, 0x080c, 0x0dc5, 0x080c, 0xee26, 0x1d20, 0x080c, 0x3374,
-	0x1d08, 0x7038, 0x6016, 0x6007, 0x0045, 0x6003, 0x0001, 0x080c,
-	0x9547, 0x0005, 0x080c, 0x3250, 0x080c, 0xd7f8, 0x6007, 0x0001,
-	0x6003, 0x0001, 0x080c, 0x9547, 0x0005, 0x080c, 0xee26, 0x1950,
-	0x080c, 0x3374, 0x1938, 0x080c, 0xdecb, 0x1d60, 0x703c, 0x6016,
-	0x6007, 0x004a, 0x6003, 0x0001, 0x080c, 0x9547, 0x0005, 0x080c,
-	0x3374, 0x1904, 0xdcfa, 0x2009, 0x0041, 0x080c, 0xeed4, 0x6007,
-	0x0047, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0005,
-	0x080c, 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0042, 0x080c, 0xeed4,
-	0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1,
-	0x0005, 0x080c, 0x3374, 0x1904, 0xdcfa, 0x2009, 0x0046, 0x080c,
-	0xeed4, 0x080c, 0xb2d3, 0x0005, 0x2001, 0x1824, 0x2004, 0x9082,
-	0x00e1, 0x1268, 0x080c, 0xddd5, 0x0904, 0xdcfa, 0x6007, 0x004e,
-	0x6003, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0005, 0x6007,
-	0x0012, 0x0cb0, 0x6007, 0x004f, 0x6017, 0x0000, 0x7134, 0x918c,
-	0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001, 0x1160, 0x7140, 0x2001,
-	0x19be, 0x2004, 0x9106, 0x11b0, 0x7144, 0x2001, 0x19bf, 0x2004,
-	0x9106, 0x0190, 0x9186, 0x0002, 0x1168, 0x2011, 0x0276, 0x20a9,
-	0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xc379,
-	0x009e, 0x0110, 0x6017, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547,
-	0x080c, 0x9ab1, 0x0005, 0x6007, 0x0050, 0x703c, 0x6016, 0x0ca0,
-	0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6, 0x00c6, 0x2260, 0x6010,
-	0x2058, 0xb8cc, 0xd084, 0x0150, 0x7128, 0x6044, 0x9106, 0x1120,
-	0x712c, 0x6048, 0x9106, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001,
-	0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005, 0x0016, 0x0096, 0x0086,
-	0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800,
-	0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003, 0x0000, 0x080c, 0x1027,
-	0x05a0, 0x2900, 0x6016, 0x7090, 0x8004, 0xa816, 0x908a, 0x001e,
-	0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e, 0xa860, 0x20e8, 0xa85c,
-	0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, 0x0016, 0x200c, 0x0471,
-	0x001e, 0x81ff, 0x01b8, 0x2940, 0x080c, 0x1027, 0x01b0, 0x2900,
-	0xa006, 0x2100, 0x0c18, 0xa832, 0x20a8, 0xa860, 0x20e8, 0xa85c,
-	0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1, 0x0016, 0x200c, 0x00b1,
-	0x001e, 0x0000, 0x9085, 0x0001, 0x0048, 0x2071, 0x1800, 0x7093,
-	0x0000, 0x6014, 0x2048, 0x080c, 0x0fc0, 0x9006, 0x012e, 0x01de,
-	0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e, 0x0005, 0x0006, 0x0016,
-	0x0026, 0x0036, 0x00c6, 0x918c, 0xffff, 0x11b0, 0x080c, 0x23e2,
-	0x2099, 0x026c, 0x2001, 0x0014, 0x3518, 0x9312, 0x0108, 0x1218,
-	0x23a8, 0x4003, 0x0400, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c,
-	0x23e2, 0x2099, 0x0260, 0x0ca8, 0x080c, 0x23e2, 0x2061, 0x19a1,
-	0x6004, 0x2098, 0x6008, 0x3518, 0x9312, 0x0108, 0x1218, 0x23a8,
-	0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8, 0x8108, 0x080c, 0x23e2,
-	0x2099, 0x0260, 0x0ca8, 0x2061, 0x19a1, 0x2019, 0x0280, 0x3300,
-	0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0260, 0x6006, 0x8108,
-	0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e,
-	0x002e, 0x001e, 0x000e, 0x0005, 0x0006, 0x0016, 0x0026, 0x0036,
-	0x00c6, 0x81ff, 0x11b8, 0x080c, 0x23fa, 0x20a1, 0x024c, 0x2001,
-	0x0014, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0418, 0x20a8,
-	0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108, 0x080c, 0x23fa, 0x20a1,
-	0x0240, 0x0c98, 0x080c, 0x23fa, 0x2061, 0x19a4, 0x6004, 0x20a0,
-	0x6008, 0x3518, 0x9312, 0x1218, 0x23a8, 0x4003, 0x0058, 0x20a8,
-	0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108, 0x080c, 0x23fa, 0x20a1,
-	0x0240, 0x0c98, 0x2061, 0x19a4, 0x2019, 0x0260, 0x3400, 0x931e,
-	0x0110, 0x6006, 0x0020, 0x2001, 0x0240, 0x6006, 0x8108, 0x2162,
-	0x9292, 0x0021, 0x9296, 0xffff, 0x620a, 0x00ce, 0x003e, 0x002e,
-	0x001e, 0x000e, 0x0005, 0x00b6, 0x0066, 0x6610, 0x2658, 0xbe04,
-	0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0170, 0x9686, 0x0004,
-	0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x0128, 0x9686,
-	0x0004, 0x0110, 0x9085, 0x0001, 0x006e, 0x00be, 0x0005, 0x00d6,
-	0x080c, 0xdf63, 0x00de, 0x0005, 0x00d6, 0x080c, 0xdf70, 0x1520,
-	0x680c, 0x908c, 0xff00, 0x6820, 0x9084, 0x00ff, 0x9115, 0x6216,
-	0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006, 0x080c, 0xeff4, 0x2009,
-	0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920, 0x918c, 0x00ff, 0x6824,
-	0x080c, 0x2873, 0x1148, 0x2001, 0x0001, 0x080c, 0xeff4, 0x2110,
-	0x900e, 0x080c, 0x3299, 0x0018, 0x9085, 0x0001, 0x0008, 0x9006,
-	0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c, 0xb325, 0x05a8, 0x0016,
-	0x0026, 0x00c6, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c,
-	0x2873, 0x1578, 0x080c, 0x66b9, 0x1560, 0xbe12, 0xbd16, 0x00ce,
-	0x002e, 0x001e, 0x2b00, 0x6012, 0x080c, 0xee26, 0x11d8, 0x080c,
-	0x3374, 0x11c0, 0x080c, 0xdecb, 0x0510, 0x2001, 0x0007, 0x080c,
-	0x666a, 0x2001, 0x0007, 0x080c, 0x6696, 0x6017, 0x0000, 0x6023,
-	0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x9547, 0x080c,
-	0x9ab1, 0x0010, 0x080c, 0xb2d3, 0x9085, 0x0001, 0x00ce, 0x00be,
-	0x0005, 0x080c, 0xb2d3, 0x00ce, 0x002e, 0x001e, 0x0ca8, 0x080c,
-	0xb2d3, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082, 0x0010,
-	0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006, 0x0005,
-	0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00, 0x9086,
-	0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186, 0x0014,
-	0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x615a, 0x908e,
-	0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2, 0x0053,
-	0x1a0c, 0x0dc5, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2, 0x0040,
-	0x1a04, 0xe0d2, 0x040a, 0x91b6, 0x0027, 0x0198, 0x9186, 0x0015,
-	0x0118, 0x9186, 0x0016, 0x1148, 0x080c, 0xd809, 0x0128, 0x6000,
-	0x9086, 0x0002, 0x0904, 0xbcfd, 0x0005, 0x91b6, 0x0014, 0x190c,
-	0x0dc5, 0x2001, 0x0007, 0x080c, 0x6696, 0x080c, 0x99a5, 0x080c,
-	0xb306, 0x080c, 0x9ab1, 0x0005, 0xdffc, 0xdffe, 0xdffc, 0xdffc,
-	0xdffc, 0xdffe, 0xe00d, 0xe0cb, 0xe051, 0xe0cb, 0xe079, 0xe0cb,
-	0xe00d, 0xe0cb, 0xe0c3, 0xe0cb, 0xe0c3, 0xe0cb, 0xe0cb, 0xdffc,
-	0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xdffc,
-	0xdffc, 0xdffc, 0xdffe, 0xdffc, 0xe0cb, 0xdffc, 0xdffc, 0xe0cb,
-	0xdffc, 0xe0c8, 0xe0cb, 0xdffc, 0xdffc, 0xdffc, 0xdffc, 0xe0cb,
-	0xe0cb, 0xdffc, 0xe0cb, 0xe0cb, 0xdffc, 0xe008, 0xdffc, 0xdffc,
-	0xdffc, 0xdffc, 0xe0c7, 0xe0cb, 0xdffc, 0xdffc, 0xe0cb, 0xe0cb,
-	0xdffc, 0xdffc, 0xdffc, 0xdffc, 0x080c, 0x0dc5, 0x080c, 0x99a5,
-	0x080c, 0xd7fb, 0x6003, 0x0002, 0x080c, 0x9ab1, 0x0804, 0xe0d1,
-	0x9006, 0x080c, 0x6656, 0x0804, 0xe0cb, 0x080c, 0x6a9b, 0x1904,
-	0xe0cb, 0x9006, 0x080c, 0x6656, 0x6010, 0x2058, 0xb810, 0x9086,
-	0x00ff, 0x1140, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa,
-	0x00fe, 0x00b8, 0x6010, 0x2058, 0xb8c0, 0x9005, 0x0904, 0xe0cb,
-	0x080c, 0x33a5, 0x1904, 0xe0cb, 0x2001, 0x1800, 0x2004, 0x9086,
-	0x0002, 0x1138, 0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa,
-	0x00fe, 0x2001, 0x0002, 0x080c, 0x666a, 0x080c, 0x99a5, 0x6023,
-	0x0001, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x9547, 0x080c,
-	0x9ab1, 0x6110, 0x2158, 0x2009, 0x0001, 0x080c, 0x884b, 0x0804,
-	0xe0d1, 0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686,
-	0x0006, 0x0148, 0x9686, 0x0004, 0x0130, 0x080c, 0x9031, 0x2001,
-	0x0004, 0x080c, 0x6696, 0x080c, 0xf043, 0x0904, 0xe0cb, 0x080c,
-	0x99a5, 0x2001, 0x0004, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003,
-	0x0001, 0x6007, 0x0003, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x0804,
-	0xe0d1, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036,
-	0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4dfb,
-	0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xe0ef, 0x6610, 0x2658,
-	0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e,
-	0x0180, 0x2001, 0x0006, 0x080c, 0x6696, 0x9284, 0x00ff, 0x908e,
-	0x0007, 0x0118, 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c,
-	0x666a, 0x080c, 0x6a9b, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4,
-	0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6,
-	0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xe039,
-	0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0449, 0x0020, 0x0018,
-	0x0010, 0x080c, 0x6696, 0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c,
-	0x9ab1, 0x0005, 0x2600, 0x0002, 0xe0e6, 0xe0e6, 0xe0e6, 0xe0e6,
-	0xe0e6, 0xe0e8, 0xe0e6, 0xe0e8, 0xe0e6, 0xe0e6, 0xe0e8, 0xe0e6,
-	0xe0e6, 0xe0e6, 0xe0e8, 0xe0e8, 0xe0e8, 0xe0e8, 0x080c, 0x0dc5,
-	0x080c, 0x99a5, 0x080c, 0xb2d3, 0x080c, 0x9ab1, 0x0005, 0x0016,
-	0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c,
-	0x666a, 0x9006, 0x080c, 0x6656, 0x080c, 0x3279, 0x00de, 0x00be,
-	0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007,
-	0x90b2, 0x000c, 0x1a0c, 0x0dc5, 0x91b6, 0x0015, 0x1110, 0x003b,
-	0x0028, 0x91b6, 0x0016, 0x190c, 0x0dc5, 0x006b, 0x0005, 0xbd9f,
-	0xbd9f, 0xbd9f, 0xbd9f, 0xe184, 0xbd9f, 0xe16e, 0xe12f, 0xbd9f,
-	0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0xe184,
-	0xbd9f, 0xe16e, 0xe175, 0xbd9f, 0xbd9f, 0xbd9f, 0xbd9f, 0x00f6,
-	0x080c, 0x6a9b, 0x11d8, 0x080c, 0xd7e3, 0x11c0, 0x6010, 0x905d,
-	0x01a8, 0xb8c0, 0x9005, 0x0190, 0x9006, 0x080c, 0x6656, 0x2001,
-	0x0002, 0x080c, 0x666a, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x080c, 0x9547, 0x080c, 0x9ab1, 0x00f0, 0x2011, 0x0263,
-	0x2204, 0x8211, 0x220c, 0x080c, 0x2873, 0x11b0, 0x080c, 0x6724,
-	0x0118, 0x080c, 0xb2d3, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006,
-	0xb8c0, 0x0006, 0x080c, 0x6148, 0x000e, 0xb8c2, 0x000e, 0xb816,
-	0x000e, 0xb812, 0x080c, 0xb2d3, 0x00fe, 0x0005, 0x6604, 0x96b6,
-	0x001e, 0x1110, 0x080c, 0xb2d3, 0x0005, 0x080c, 0xc1dc, 0x1148,
-	0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x9547, 0x080c, 0x9ab1,
-	0x0010, 0x080c, 0xb2d3, 0x0005, 0x0804, 0xb2d3, 0x6004, 0x908a,
-	0x0053, 0x1a0c, 0x0dc5, 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c,
-	0x9ab1, 0x0005, 0x9182, 0x0040, 0x0002, 0xe1a9, 0xe1a9, 0xe1a9,
-	0xe1a9, 0xe1ab, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9,
-	0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9, 0xe1a9,
-	0xe1a9, 0x080c, 0x0dc5, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6,
-	0x0046, 0x0026, 0x6210, 0x2258, 0xb8bc, 0x9005, 0x11a8, 0x6106,
-	0x2071, 0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xe211, 0x080c,
-	0xefe8, 0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011,
-	0x0200, 0x080c, 0x8a50, 0x0020, 0x9026, 0x080c, 0xee6b, 0x0c38,
-	0x080c, 0x100e, 0x090c, 0x0dc5, 0x6003, 0x0007, 0xa867, 0x010d,
-	0x9006, 0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2,
-	0x6010, 0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f,
-	0x0000, 0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x6e9f, 0x001e,
-	0x080c, 0xefe8, 0x1904, 0xe271, 0x9486, 0x2000, 0x1130, 0x2019,
-	0x0017, 0x080c, 0xeba1, 0x0804, 0xe271, 0x9486, 0x0200, 0x1120,
-	0x080c, 0xeb38, 0x0804, 0xe271, 0x9486, 0x0400, 0x0120, 0x9486,
-	0x1000, 0x1904, 0xe271, 0x2019, 0x0002, 0x080c, 0xeb53, 0x0804,
-	0xe271, 0x2069, 0x1a74, 0x6a00, 0xd284, 0x0904, 0xe2db, 0x9284,
-	0x0300, 0x1904, 0xe2d4, 0x6804, 0x9005, 0x0904, 0xe2bc, 0x2d78,
-	0x6003, 0x0007, 0x080c, 0x1027, 0x0904, 0xe27d, 0x7800, 0xd08c,
-	0x1118, 0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f,
-	0x2004, 0xd084, 0x1904, 0xe2df, 0x9006, 0xa802, 0xa867, 0x0116,
-	0xa86a, 0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0,
-	0x7130, 0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930,
-	0xa9c2, 0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003,
-	0x9080, 0xe279, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270,
-	0xaa5c, 0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1,
-	0x0000, 0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000,
-	0x2001, 0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c,
-	0x6e9f, 0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e,
-	0x0005, 0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004,
-	0xd084, 0x0120, 0x080c, 0x100e, 0x1904, 0xe226, 0x6017, 0xf100,
-	0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff, 0x080c, 0x9ab1,
-	0x0c00, 0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200,
-	0x1198, 0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700,
-	0x910d, 0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x080c,
-	0x94ff, 0x080c, 0x9ab1, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032,
-	0x6017, 0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff,
-	0x080c, 0x9ab1, 0x0804, 0xe271, 0x2001, 0x180e, 0x2004, 0xd0ec,
-	0x0120, 0x2011, 0x8049, 0x080c, 0x4c44, 0x6017, 0xf300, 0x0010,
-	0x6017, 0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x080c, 0x94ff,
-	0x080c, 0x9ab1, 0x0804, 0xe271, 0x6017, 0xf500, 0x0c98, 0x6017,
-	0xf600, 0x0804, 0xe291, 0x6017, 0xf200, 0x0804, 0xe291, 0xa867,
-	0x0146, 0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044,
-	0x9084, 0x0003, 0x9080, 0xe279, 0x2005, 0xa87e, 0x2928, 0x6010,
-	0x2058, 0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830,
-	0xa892, 0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104,
-	0x9085, 0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214,
-	0x9294, 0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0dc5, 0x8210,
-	0x821c, 0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080,
-	0x0029, 0x20a0, 0x2011, 0xe35b, 0x2041, 0x0001, 0x223d, 0x9784,
-	0x00ff, 0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530,
-	0x8210, 0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098,
-	0x0c68, 0x2950, 0x080c, 0x1027, 0x0170, 0x2900, 0xb002, 0xa867,
-	0x0147, 0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b,
-	0x20a0, 0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c,
-	0x1040, 0x0cc8, 0x080c, 0x1040, 0x0804, 0xe27d, 0x2548, 0x8847,
-	0x9885, 0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c,
-	0xebd4, 0x0804, 0xe271, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018,
-	0x0008, 0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004,
-	0x908a, 0x0054, 0x1a0c, 0x0dc5, 0x9082, 0x0040, 0x0a0c, 0x0dc5,
-	0x2008, 0x0804, 0xe3ea, 0x9186, 0x0051, 0x0108, 0x0048, 0x080c,
-	0xd809, 0x0500, 0x6000, 0x9086, 0x0002, 0x11e0, 0x0804, 0xe433,
-	0x9186, 0x0027, 0x0190, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014,
-	0x0160, 0x190c, 0x0dc5, 0x080c, 0xd809, 0x0160, 0x6000, 0x9086,
-	0x0004, 0x190c, 0x0dc5, 0x0804, 0xe516, 0x6004, 0x9082, 0x0040,
-	0x2008, 0x001a, 0x080c, 0xb36d, 0x0005, 0xe3b1, 0xe3b3, 0xe3b3,
-	0xe3da, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1,
-	0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1, 0xe3b1,
-	0xe3b1, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x0036,
-	0x0096, 0x6014, 0x904d, 0x01d8, 0x080c, 0xd0d8, 0x01c0, 0x6003,
-	0x0002, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x1178,
-	0x2019, 0x0004, 0x080c, 0xebd4, 0x6017, 0x0000, 0x6018, 0x9005,
-	0x1120, 0x2001, 0x1987, 0x2004, 0x601a, 0x6003, 0x0007, 0x009e,
-	0x003e, 0x0005, 0x0096, 0x080c, 0x99a5, 0x080c, 0x9ab1, 0x080c,
-	0xd0d8, 0x0120, 0x6014, 0x2048, 0x080c, 0x1040, 0x080c, 0xb306,
-	0x009e, 0x0005, 0x0002, 0xe3ff, 0xe416, 0xe401, 0xe42d, 0xe3ff,
-	0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff,
-	0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0xe3ff, 0x080c,
-	0x0dc5, 0x0096, 0x080c, 0x99a5, 0x6014, 0x2048, 0xa87c, 0xd0b4,
-	0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c, 0xb352, 0x0010,
-	0x6003, 0x0004, 0x080c, 0x9ab1, 0x009e, 0x0005, 0x080c, 0x99a5,
-	0x080c, 0xd0d8, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e,
-	0xd1ec, 0x1138, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x080c, 0x9ab1,
-	0x0005, 0x080c, 0xee2f, 0x0db0, 0x0cc8, 0x080c, 0x99a5, 0x2009,
-	0x0041, 0x0804, 0xe59e, 0x9182, 0x0040, 0x0002, 0xe44a, 0xe44c,
-	0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a,
-	0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44d,
-	0xe44a, 0xe44a, 0x080c, 0x0dc5, 0x0005, 0x00d6, 0x080c, 0x8a25,
-	0x00de, 0x080c, 0xee87, 0x080c, 0xb2d3, 0x0005, 0x9182, 0x0040,
-	0x0002, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0xe46d,
-	0xe46d, 0xe46d, 0xe46f, 0xe4de, 0xe46d, 0xe46d, 0xe46d, 0xe46d,
-	0xe4de, 0xe46d, 0xe46d, 0xe46d, 0xe46d, 0x080c, 0x0dc5, 0x2001,
-	0x0105, 0x2004, 0x9084, 0x1800, 0x01c8, 0x2001, 0x0132, 0x200c,
-	0x2001, 0x0131, 0x2004, 0x9105, 0x1904, 0xe4de, 0x2009, 0x180c,
-	0x2104, 0xd0d4, 0x0904, 0xe4de, 0xc0d4, 0x200a, 0x2009, 0x0105,
-	0x2104, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x200a, 0x2001, 0x1867,
-	0x2004, 0xd0e4, 0x1528, 0x603b, 0x0000, 0x080c, 0x9a61, 0x6014,
-	0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x908c, 0x0003, 0x918e,
-	0x0002, 0x0508, 0x2001, 0x180c, 0x2004, 0xd0d4, 0x11e0, 0x080c,
-	0x9bd3, 0x2009, 0x0041, 0x009e, 0x0804, 0xe59e, 0x080c, 0x9bd3,
-	0x6003, 0x0007, 0x601b, 0x0000, 0x080c, 0x8a25, 0x009e, 0x0005,
-	0x2001, 0x0100, 0x2004, 0x9082, 0x0005, 0x0aa8, 0x2001, 0x011f,
-	0x2004, 0x603a, 0x0890, 0x2001, 0x180c, 0x200c, 0xc1d4, 0x2102,
-	0xd1cc, 0x0110, 0x080c, 0x2c7b, 0x080c, 0x9bd3, 0x6014, 0x2048,
-	0xa97c, 0xd1ec, 0x1130, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x009e,
-	0x0005, 0x080c, 0xee2f, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c,
-	0x200c, 0xc1d4, 0x2102, 0x0036, 0x080c, 0x9a61, 0x080c, 0x9bd3,
-	0x6014, 0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be,
-	0xd0bc, 0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140,
-	0xa8ac, 0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e,
-	0x6003, 0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xebd4, 0x6018,
-	0x9005, 0x1128, 0x2001, 0x1987, 0x2004, 0x8003, 0x601a, 0x6017,
-	0x0000, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040,
-	0x0002, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d,
-	0xe52d, 0xe52f, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe52d,
-	0xe52d, 0xe52d, 0xe52d, 0xe52d, 0xe57a, 0x080c, 0x0dc5, 0x6014,
-	0x0096, 0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900,
-	0x00be, 0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128,
-	0x2009, 0x0041, 0x009e, 0x0804, 0xe59e, 0x6003, 0x0007, 0x601b,
-	0x0000, 0x080c, 0x8a25, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58,
-	0x0006, 0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030,
-	0x9420, 0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8,
-	0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009,
-	0x180e, 0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003,
-	0x0006, 0x00e9, 0x080c, 0x8a27, 0x009e, 0x0005, 0x6003, 0x0002,
-	0x009e, 0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x1608, 0x1904,
-	0xe52f, 0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e,
-	0x9105, 0x1120, 0x080c, 0x1608, 0x1904, 0xe52f, 0x0005, 0xd2fc,
-	0x0140, 0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009,
-	0x0010, 0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040,
-	0x0208, 0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c,
-	0x0dc5, 0x6024, 0xd0dc, 0x090c, 0x0dc5, 0x0005, 0xe5c2, 0xe5ce,
-	0xe5da, 0xe5e6, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c9, 0xe5c4,
-	0xe5c4, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c2, 0xe5c4, 0xe5c2, 0xe5c4,
-	0xe5c2, 0xe5c9, 0x080c, 0x0dc5, 0x6024, 0xd0dc, 0x090c, 0x0dc5,
-	0x0005, 0x6014, 0x9005, 0x190c, 0x0dc5, 0x0005, 0x6003, 0x0001,
-	0x6106, 0x080c, 0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1,
-	0x012e, 0x0005, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005, 0x6003, 0x0003,
-	0x6106, 0x2c10, 0x080c, 0x1be0, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x9564, 0x080c, 0x9bd3, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x0036, 0x0096, 0x9182, 0x0040, 0x0023, 0x009e, 0x003e, 0x012e,
-	0x0005, 0xe615, 0xe617, 0xe629, 0xe643, 0xe615, 0xe615, 0xe615,
-	0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0xe615,
-	0xe615, 0xe615, 0xe615, 0xe615, 0xe615, 0x080c, 0x0dc5, 0x6014,
-	0x2048, 0xa87c, 0xd0fc, 0x01f8, 0x909c, 0x0003, 0x939e, 0x0003,
-	0x01d0, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff, 0x080c, 0x9ab1,
-	0x0470, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003,
-	0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x080c, 0x94ff,
-	0x080c, 0x9ab1, 0x00e0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004,
-	0x080c, 0xebd4, 0x00a0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98,
-	0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106,
-	0x2c10, 0x080c, 0x1be0, 0x080c, 0x9564, 0x080c, 0x9bd3, 0x0005,
-	0x080c, 0x99a5, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c,
-	0xef85, 0x0036, 0x2019, 0x0029, 0x080c, 0xebd4, 0x003e, 0x009e,
-	0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x080c, 0x9a61, 0x6114,
-	0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xef85, 0x0036, 0x2019,
-	0x0029, 0x080c, 0xebd4, 0x003e, 0x009e, 0x080c, 0xb306, 0x080c,
-	0x9bd3, 0x0005, 0x9182, 0x0085, 0x0002, 0xe694, 0xe692, 0xe692,
-	0xe6a0, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692, 0xe692,
-	0xe692, 0xe692, 0x080c, 0x0dc5, 0x6003, 0x000b, 0x6106, 0x080c,
-	0x94ff, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ab1, 0x012e, 0x0005,
-	0x0026, 0x00e6, 0x080c, 0xee26, 0x0118, 0x080c, 0xb2d3, 0x0450,
-	0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4,
-	0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011,
-	0x014e, 0x080c, 0xb5f5, 0x7220, 0x080c, 0xea29, 0x0118, 0x6007,
-	0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110,
-	0x6007, 0x0086, 0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1,
-	0x080c, 0x9bd3, 0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160,
-	0x6004, 0x908a, 0x0085, 0x0a0c, 0x0dc5, 0x908a, 0x0092, 0x1a0c,
-	0x0dc5, 0x9082, 0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186,
-	0x0014, 0x0118, 0x080c, 0xb36d, 0x0050, 0x2001, 0x0007, 0x080c,
-	0x6696, 0x080c, 0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005,
-	0xe705, 0xe707, 0xe707, 0xe705, 0xe705, 0xe705, 0xe705, 0xe705,
-	0xe705, 0xe705, 0xe705, 0xe705, 0xe705, 0x080c, 0x0dc5, 0x080c,
-	0x99a5, 0x080c, 0xb306, 0x080c, 0x9ab1, 0x0005, 0x9182, 0x0085,
-	0x0a0c, 0x0dc5, 0x9182, 0x0092, 0x1a0c, 0x0dc5, 0x9182, 0x0085,
-	0x0002, 0xe726, 0xe726, 0xe726, 0xe728, 0xe726, 0xe726, 0xe726,
-	0xe726, 0xe726, 0xe726, 0xe726, 0xe726, 0xe726, 0x080c, 0x0dc5,
-	0x0005, 0x9186, 0x0013, 0x0148, 0x9186, 0x0014, 0x0130, 0x9186,
-	0x0027, 0x0118, 0x080c, 0xb36d, 0x0030, 0x080c, 0x99a5, 0x080c,
-	0xb306, 0x080c, 0x9ab1, 0x0005, 0x0036, 0x080c, 0xee87, 0x6043,
-	0x0000, 0x2019, 0x000b, 0x0011, 0x003e, 0x0005, 0x6010, 0x0006,
-	0x0059, 0x000e, 0x6012, 0x6023, 0x0006, 0x6003, 0x0007, 0x601b,
-	0x0000, 0x6043, 0x0000, 0x0005, 0x0126, 0x0036, 0x2091, 0x8000,
-	0x0086, 0x2c40, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e,
-	0x1550, 0x0076, 0x2c38, 0x080c, 0xaba6, 0x007e, 0x1520, 0x6000,
-	0x9086, 0x0000, 0x0500, 0x6020, 0x9086, 0x0007, 0x01e0, 0x0096,
-	0x601c, 0xd084, 0x0140, 0x080c, 0xee87, 0x080c, 0xd7fb, 0x080c,
-	0x1a8e, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xd0d8, 0x0110,
-	0x080c, 0xebd4, 0x009e, 0x6017, 0x0000, 0x080c, 0xee87, 0x6023,
-	0x0007, 0x080c, 0xd7fb, 0x003e, 0x012e, 0x0005, 0x00f6, 0x00c6,
-	0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c, 0x080c,
-	0x2873, 0x1904, 0xe7e4, 0x0016, 0x00c6, 0x080c, 0x6724, 0x1904,
-	0xe7e2, 0x001e, 0x00c6, 0x080c, 0xd7e3, 0x1130, 0xb8c0, 0x9005,
-	0x0118, 0x080c, 0x33a5, 0x0148, 0x2b10, 0x2160, 0x6010, 0x0006,
-	0x6212, 0x080c, 0xd7ea, 0x000e, 0x6012, 0x00ce, 0x002e, 0x0026,
-	0x0016, 0x2019, 0x0029, 0x080c, 0xac6c, 0x080c, 0x96a4, 0x0076,
-	0x903e, 0x080c, 0x9577, 0x007e, 0x001e, 0x0076, 0x903e, 0x080c,
-	0xe91c, 0x007e, 0x0026, 0xba04, 0x9294, 0xff00, 0x8217, 0x9286,
-	0x0006, 0x0118, 0x9286, 0x0004, 0x1118, 0xbaa0, 0x080c, 0x330e,
-	0x002e, 0xbcc0, 0x001e, 0x080c, 0x6148, 0xbe12, 0xbd16, 0xbcc2,
-	0x9006, 0x0010, 0x00ce, 0x001e, 0x015e, 0x003e, 0x00be, 0x00ce,
-	0x00fe, 0x0005, 0x00c6, 0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824,
-	0x2104, 0x9086, 0x0074, 0x1904, 0xe843, 0x2069, 0x0260, 0x6944,
-	0x9182, 0x0100, 0x06e0, 0x6940, 0x9184, 0x8000, 0x0904, 0xe840,
-	0x2001, 0x197c, 0x2004, 0x9005, 0x1140, 0x6010, 0x2058, 0xb8c0,
-	0x9005, 0x0118, 0x9184, 0x0800, 0x0598, 0x6948, 0x918a, 0x0001,
-	0x0648, 0x080c, 0xefed, 0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009,
-	0x0205, 0x200b, 0x0001, 0x693c, 0x81ff, 0x1198, 0x6944, 0x9182,
-	0x0100, 0x02a8, 0x6940, 0x81ff, 0x1178, 0x6948, 0x918a, 0x0001,
-	0x0288, 0x6950, 0x918a, 0x0001, 0x0298, 0x00d0, 0x6017, 0x0100,
-	0x00a0, 0x6017, 0x0300, 0x0088, 0x6017, 0x0500, 0x0070, 0x6017,
-	0x0700, 0x0058, 0x6017, 0x0900, 0x0040, 0x6017, 0x0b00, 0x0028,
-	0x6017, 0x0f00, 0x0010, 0x6017, 0x2d00, 0x9085, 0x0001, 0x0008,
-	0x9006, 0x001e, 0x00be, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6,
-	0x0026, 0x0036, 0x0156, 0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff,
-	0x9286, 0x0006, 0x0180, 0x9286, 0x0004, 0x0168, 0x9394, 0xff00,
-	0x8217, 0x9286, 0x0006, 0x0138, 0x9286, 0x0004, 0x0120, 0x080c,
-	0x6733, 0x0804, 0xe8ab, 0x2011, 0x0276, 0x20a9, 0x0004, 0x0096,
-	0x2b48, 0x2019, 0x000a, 0x080c, 0xc379, 0x009e, 0x15a8, 0x2011,
-	0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x0006, 0x080c,
-	0xc379, 0x009e, 0x1548, 0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006,
-	0x2009, 0x1848, 0x210c, 0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c,
-	0xec31, 0xb800, 0xc0e5, 0xb802, 0x2019, 0x0029, 0x080c, 0x96a4,
-	0x0076, 0x2039, 0x0000, 0x080c, 0x9577, 0x2c08, 0x080c, 0xe91c,
-	0x007e, 0x2001, 0x0007, 0x080c, 0x6696, 0x2001, 0x0007, 0x080c,
-	0x666a, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e, 0x00be,
-	0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086, 0x0800,
-	0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6,
-	0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c, 0x7930,
-	0x7834, 0x080c, 0x2873, 0x11d0, 0x080c, 0x6724, 0x11b8, 0x2011,
-	0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c,
-	0xc379, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004, 0x0096,
-	0x2b48, 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x015e, 0x003e,
-	0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006, 0x0016,
-	0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c,
-	0x080c, 0x2873, 0x11d0, 0x080c, 0x6724, 0x11b8, 0x2011, 0x0276,
-	0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c, 0xc379,
-	0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096, 0x2b48,
-	0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x015e, 0x003e, 0x002e,
-	0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086, 0x0076,
-	0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000, 0x2740,
-	0x2029, 0x19f1, 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0,
-	0x2071, 0x1800, 0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186,
-	0x1ab7, 0x000e, 0x0128, 0x8001, 0x9602, 0x1a04, 0xe9ba, 0x0018,
-	0x9606, 0x0904, 0xe9ba, 0x080c, 0x8cf7, 0x0904, 0xe9b1, 0x2100,
-	0x9c06, 0x0904, 0xe9b1, 0x6720, 0x9786, 0x0007, 0x0904, 0xe9b1,
-	0x080c, 0xec72, 0x1904, 0xe9b1, 0x080c, 0xf00b, 0x0904, 0xe9b1,
-	0x080c, 0xec62, 0x0904, 0xe9b1, 0x6720, 0x9786, 0x0001, 0x1148,
-	0x080c, 0x33a5, 0x0904, 0xe9f9, 0x6004, 0x9086, 0x0000, 0x1904,
-	0xe9f9, 0x9786, 0x0004, 0x0904, 0xe9f9, 0x2500, 0x9c06, 0x0904,
-	0xe9b1, 0x2400, 0x9c06, 0x05e8, 0x88ff, 0x0118, 0x6054, 0x9906,
-	0x15c0, 0x0096, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c,
-	0x1a8e, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xd2e0, 0x1130,
-	0x080c, 0xbcb6, 0x009e, 0x080c, 0xb306, 0x0418, 0x6014, 0x2048,
-	0x080c, 0xd0d8, 0x01d8, 0x9786, 0x0003, 0x1570, 0xa867, 0x0103,
-	0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c, 0x0fc0,
-	0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xef85, 0x0016, 0x080c,
-	0xd3ce, 0x080c, 0x6e92, 0x001e, 0x080c, 0xd2c3, 0x009e, 0x080c,
-	0xb306, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1210,
-	0x0804, 0xe930, 0x012e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e,
-	0x008e, 0x00ce, 0x00ee, 0x0005, 0x9786, 0x0006, 0x1150, 0x9386,
-	0x0005, 0x0128, 0x080c, 0xef85, 0x080c, 0xebd4, 0x08f8, 0x009e,
-	0x0c00, 0x9786, 0x0009, 0x11f8, 0x6000, 0x9086, 0x0004, 0x01c0,
-	0x6000, 0x9086, 0x0003, 0x11a0, 0x080c, 0x9a61, 0x0096, 0x6114,
-	0x2148, 0x080c, 0xd0d8, 0x0118, 0x6010, 0x080c, 0x6e9f, 0x009e,
-	0x00c6, 0x080c, 0xb2d3, 0x00ce, 0x0036, 0x080c, 0x9bd3, 0x003e,
-	0x009e, 0x0804, 0xe9b1, 0x9786, 0x000a, 0x0904, 0xe9a1, 0x0804,
-	0xe996, 0x81ff, 0x0904, 0xe9b1, 0x9180, 0x0001, 0x2004, 0x9086,
-	0x0018, 0x0138, 0x9180, 0x0001, 0x2004, 0x9086, 0x002d, 0x1904,
-	0xe9b1, 0x6000, 0x9086, 0x0002, 0x1904, 0xe9b1, 0x080c, 0xd2cf,
-	0x0138, 0x080c, 0xd2e0, 0x1904, 0xe9b1, 0x080c, 0xbcb6, 0x0038,
-	0x080c, 0x3279, 0x080c, 0xd2e0, 0x1110, 0x080c, 0xbcb6, 0x080c,
-	0xb306, 0x0804, 0xe9b1, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039,
-	0x0005, 0x00c6, 0x00e6, 0x0016, 0x2c08, 0x2170, 0x9006, 0x080c,
-	0xebfb, 0x001e, 0x0120, 0x6020, 0x9084, 0x000f, 0x001b, 0x00ee,
-	0x00ce, 0x0005, 0xea48, 0xea48, 0xea48, 0xea48, 0xea48, 0xea48,
-	0xea4a, 0xea48, 0xea48, 0xea48, 0xea73, 0xb306, 0xb306, 0xea48,
-	0x9006, 0x0005, 0x0036, 0x0046, 0x0016, 0x7010, 0x00b6, 0x2058,
-	0xbca0, 0x00be, 0x2c00, 0x2009, 0x0020, 0x080c, 0xec31, 0x001e,
-	0x004e, 0x2019, 0x0002, 0x080c, 0xe754, 0x003e, 0x9085, 0x0001,
-	0x0005, 0x0096, 0x080c, 0xd0d8, 0x0140, 0x6014, 0x904d, 0x080c,
-	0xccf3, 0x687b, 0x0005, 0x080c, 0x6e9f, 0x009e, 0x080c, 0xb306,
-	0x9085, 0x0001, 0x0005, 0x0019, 0x9085, 0x0001, 0x0005, 0x6000,
-	0x908a, 0x0010, 0x1a0c, 0x0dc5, 0x000b, 0x0005, 0xea8e, 0xea8e,
-	0xeaa5, 0xea95, 0xeab4, 0xea8e, 0xea8e, 0xea90, 0xea8e, 0xea8e,
-	0xea8e, 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0xea8e, 0x080c, 0x0dc5,
-	0x080c, 0xb306, 0x9085, 0x0001, 0x0005, 0x0036, 0x00e6, 0x2071,
-	0x19e8, 0x703c, 0x9c06, 0x1128, 0x2019, 0x0001, 0x080c, 0xaa49,
-	0x0010, 0x080c, 0xac2b, 0x00ee, 0x003e, 0x0096, 0x00d6, 0x6014,
-	0x2048, 0xa87b, 0x0005, 0x080c, 0x6e9f, 0x080c, 0xb306, 0x00de,
-	0x009e, 0x9085, 0x0001, 0x0005, 0x601c, 0xd084, 0x190c, 0x1a8e,
-	0x0c60, 0x2001, 0x0001, 0x080c, 0x6656, 0x0156, 0x0016, 0x0026,
-	0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c,
-	0xc365, 0x003e, 0x002e, 0x001e, 0x015e, 0x9005, 0x0005, 0x00f6,
-	0x00e6, 0x00c6, 0x0086, 0x0076, 0x0066, 0x00b6, 0x0126, 0x2091,
-	0x8000, 0x2740, 0x2061, 0x1cd0, 0x2079, 0x0001, 0x8fff, 0x0904,
-	0xeb2b, 0x2071, 0x1800, 0x7654, 0x7074, 0x8001, 0x9602, 0x1a04,
-	0xeb2b, 0x88ff, 0x0120, 0x2800, 0x9c06, 0x15a0, 0x2078, 0x080c,
-	0xec62, 0x0580, 0x2400, 0x9c06, 0x0568, 0x6720, 0x9786, 0x0006,
-	0x1548, 0x9786, 0x0007, 0x0530, 0x88ff, 0x1150, 0xd58c, 0x1118,
-	0x6010, 0x9b06, 0x11f8, 0xd584, 0x0118, 0x6054, 0x9106, 0x11d0,
-	0x0096, 0x601c, 0xd084, 0x0140, 0x080c, 0xee87, 0x080c, 0xd7fb,
-	0x080c, 0x1a8e, 0x6023, 0x0007, 0x6014, 0x2048, 0x080c, 0xd0d8,
-	0x0120, 0x0046, 0x080c, 0xebd4, 0x004e, 0x009e, 0x080c, 0xb306,
-	0x88ff, 0x1198, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02,
-	0x1210, 0x0804, 0xeade, 0x9006, 0x012e, 0x00be, 0x006e, 0x007e,
-	0x008e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x98c5, 0x0001, 0x0ca0,
-	0x00b6, 0x0076, 0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20,
-	0x2019, 0x0002, 0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xaafb,
-	0x009e, 0x008e, 0x903e, 0x080c, 0xaba6, 0x080c, 0xeacf, 0x005e,
-	0x007e, 0x00be, 0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6,
-	0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e, 0x0016, 0x0036,
-	0x080c, 0x6724, 0x1180, 0x0056, 0x0086, 0x9046, 0x2508, 0x2029,
-	0x0001, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e,
-	0x080c, 0xaba6, 0x005e, 0x003e, 0x001e, 0x8108, 0x1f04, 0xeb5e,
-	0x0036, 0x2508, 0x2029, 0x0003, 0x080c, 0xeacf, 0x003e, 0x015e,
-	0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x0005, 0x00b6, 0x0076,
-	0x0056, 0x6210, 0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019,
-	0x0048, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e,
-	0x080c, 0xaba6, 0x2c20, 0x080c, 0xeacf, 0x005e, 0x007e, 0x00be,
-	0x0005, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6, 0x0156, 0x2c20,
-	0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c, 0x6724, 0x1190,
-	0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001, 0x080c, 0xee6b,
-	0x004e, 0x0096, 0x904e, 0x080c, 0xaafb, 0x009e, 0x008e, 0x903e,
-	0x080c, 0xaba6, 0x003e, 0x001e, 0x8108, 0x1f04, 0xebab, 0x0036,
-	0x2029, 0x0002, 0x080c, 0xeacf, 0x003e, 0x015e, 0x00ce, 0x007e,
-	0x005e, 0x004e, 0x00be, 0x0005, 0x0016, 0x00f6, 0x080c, 0xd0d6,
-	0x0198, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0046, 0x0180, 0xa800,
-	0x907d, 0x0138, 0xa803, 0x0000, 0xab82, 0x080c, 0x6e9f, 0x2f48,
-	0x0cb0, 0xab82, 0x080c, 0x6e9f, 0x00fe, 0x001e, 0x0005, 0xa800,
-	0x907d, 0x0130, 0xa803, 0x0000, 0x080c, 0x6e9f, 0x2f48, 0x0cb8,
-	0x080c, 0x6e9f, 0x0c88, 0x00e6, 0x0046, 0x0036, 0x2061, 0x1cd0,
-	0x9005, 0x1138, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001, 0x9402,
-	0x12f8, 0x2100, 0x9c06, 0x0188, 0x6000, 0x9086, 0x0000, 0x0168,
-	0x6008, 0x9206, 0x1150, 0x6320, 0x9386, 0x0009, 0x01b0, 0x6010,
-	0x91a0, 0x0004, 0x2424, 0x9406, 0x0140, 0x9ce0, 0x0018, 0x2001,
-	0x181a, 0x2004, 0x9c02, 0x1220, 0x0c20, 0x9085, 0x0001, 0x0008,
-	0x9006, 0x003e, 0x004e, 0x00ee, 0x0005, 0x631c, 0xd3c4, 0x1d68,
-	0x0c30, 0x0096, 0x0006, 0x080c, 0x100e, 0x000e, 0x090c, 0x0dc5,
-	0xaae2, 0xa867, 0x010d, 0xa88e, 0x0026, 0x2010, 0x080c, 0xd0c6,
-	0x2001, 0x0000, 0x0120, 0x2200, 0x9080, 0x0015, 0x2004, 0x002e,
-	0xa87a, 0x9186, 0x0020, 0x0110, 0xa8e3, 0xffff, 0xa986, 0xac76,
-	0xa87f, 0x0000, 0x2001, 0x198e, 0x2004, 0xa882, 0x9006, 0xa802,
-	0xa86a, 0xa88a, 0x0126, 0x2091, 0x8000, 0x080c, 0x6e9f, 0x012e,
-	0x009e, 0x0005, 0x6700, 0x9786, 0x0000, 0x0158, 0x9786, 0x0001,
-	0x0140, 0x9786, 0x000a, 0x0128, 0x9786, 0x0009, 0x0110, 0x9085,
-	0x0001, 0x0005, 0x00e6, 0x6010, 0x9075, 0x0138, 0x00b6, 0x2058,
-	0xb8a0, 0x00be, 0x9206, 0x00ee, 0x0005, 0x9085, 0x0001, 0x0cd8,
-	0x0016, 0x6004, 0x908e, 0x001e, 0x11a0, 0x8007, 0x6134, 0x918c,
-	0x00ff, 0x9105, 0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023,
-	0x0005, 0x2001, 0x1987, 0x2004, 0x601a, 0x080c, 0x94ff, 0x080c,
-	0x9ab1, 0x001e, 0x0005, 0xa001, 0xa001, 0x0005, 0x6024, 0xd0e4,
-	0x0158, 0xd0cc, 0x0118, 0x080c, 0xd412, 0x0030, 0x080c, 0xee87,
-	0x080c, 0x8a25, 0x080c, 0xb2d3, 0x0005, 0x9280, 0x0008, 0x2004,
-	0x9084, 0x000f, 0x0002, 0xecc1, 0xecc1, 0xecc1, 0xecc3, 0xecc1,
-	0xecc3, 0xecc3, 0xecc1, 0xecc3, 0xecc1, 0xecc1, 0xecc1, 0xecc1,
-	0xecc1, 0x9006, 0x0005, 0x9085, 0x0001, 0x0005, 0x9280, 0x0008,
-	0x2004, 0x9084, 0x000f, 0x0002, 0xecda, 0xecda, 0xecda, 0xecda,
-	0xecda, 0xecda, 0xece7, 0xecda, 0xecda, 0xecda, 0xecda, 0xecda,
-	0xecda, 0xecda, 0x6007, 0x003b, 0x602f, 0x0009, 0x6017, 0x2a00,
-	0x6003, 0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x0005, 0x0096,
-	0x00c6, 0x2260, 0x080c, 0xee87, 0x6043, 0x0000, 0x6024, 0xc0f4,
-	0xc0e4, 0x6026, 0x603b, 0x0000, 0x00ce, 0x00d6, 0x2268, 0x9186,
-	0x0007, 0x1904, 0xed40, 0x6814, 0x9005, 0x0138, 0x2048, 0xa87c,
-	0xd0fc, 0x1118, 0x00de, 0x009e, 0x08a8, 0x6007, 0x003a, 0x6003,
-	0x0001, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x00c6, 0x2d60, 0x6100,
-	0x9186, 0x0002, 0x1904, 0xedb0, 0x6014, 0x9005, 0x1138, 0x6000,
-	0x9086, 0x0007, 0x190c, 0x0dc5, 0x0804, 0xedb0, 0x2048, 0x080c,
-	0xd0d8, 0x1130, 0x0028, 0x2048, 0xa800, 0x9005, 0x1de0, 0x2900,
-	0x2048, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x1168, 0xa87c,
-	0xc0dc, 0xc0f4, 0xa87e, 0xa880, 0xc0fc, 0xa882, 0x2009, 0x0043,
-	0x080c, 0xe59e, 0x0804, 0xedb0, 0x2009, 0x0041, 0x0804, 0xedaa,
-	0x9186, 0x0005, 0x15a0, 0x6814, 0x2048, 0xa87c, 0xd0bc, 0x1120,
-	0x00de, 0x009e, 0x0804, 0xecda, 0xd0b4, 0x0128, 0xd0fc, 0x090c,
-	0x0dc5, 0x0804, 0xecfb, 0x6007, 0x003a, 0x6003, 0x0001, 0x080c,
-	0x94ff, 0x080c, 0x9ab1, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002,
-	0x0120, 0x9186, 0x0004, 0x1904, 0xedb0, 0x6814, 0x2048, 0xa97c,
-	0xc1f4, 0xc1dc, 0xa97e, 0xa980, 0xc1fc, 0xc1bc, 0xa982, 0x00f6,
-	0x2c78, 0x080c, 0x1768, 0x00fe, 0x2009, 0x0042, 0x0498, 0x0036,
-	0x080c, 0x100e, 0x090c, 0x0dc5, 0xa867, 0x010d, 0x9006, 0xa802,
-	0xa86a, 0xa88a, 0x2d18, 0xab8e, 0xa887, 0x0045, 0x2c00, 0xa892,
-	0x6038, 0xa8a2, 0x2360, 0x6024, 0xc0dd, 0x6026, 0x6010, 0x00b6,
-	0x2058, 0xb8a0, 0x00be, 0x2004, 0x6354, 0xab7a, 0xa876, 0x9006,
-	0xa87e, 0xa882, 0xad9a, 0xae96, 0xa89f, 0x0001, 0x080c, 0x6e9f,
-	0x2019, 0x0045, 0x6008, 0x2068, 0x080c, 0xe746, 0x2d00, 0x600a,
-	0x003e, 0x0038, 0x6043, 0x0000, 0x6003, 0x0007, 0x080c, 0xe59e,
-	0x00ce, 0x00de, 0x009e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004,
-	0x9082, 0x0085, 0x2008, 0x00c2, 0x9186, 0x0027, 0x1178, 0x080c,
-	0x99a5, 0x0036, 0x0096, 0x6014, 0x2048, 0x2019, 0x0004, 0x080c,
-	0xebd4, 0x009e, 0x003e, 0x080c, 0x9ab1, 0x0005, 0x9186, 0x0014,
-	0x0d70, 0x080c, 0xb36d, 0x0005, 0xede3, 0xede1, 0xede1, 0xede1,
-	0xede1, 0xede1, 0xede3, 0xede1, 0xede1, 0xede1, 0xede1, 0xede1,
-	0xede1, 0x080c, 0x0dc5, 0x080c, 0x99a5, 0x6003, 0x000c, 0x080c,
-	0x9ab1, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182, 0x0085, 0x0208,
-	0x001a, 0x080c, 0xb36d, 0x0005, 0xee01, 0xee01, 0xee01, 0xee01,
-	0xee03, 0xee23, 0xee01, 0xee01, 0xee01, 0xee01, 0xee01, 0xee01,
-	0xee01, 0x080c, 0x0dc5, 0x00d6, 0x2c68, 0x080c, 0xb27d, 0x01b0,
-	0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e, 0x210c, 0x613a,
-	0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff, 0x6910, 0x6112,
-	0x6023, 0x0004, 0x080c, 0x94ff, 0x080c, 0x9ab1, 0x2d60, 0x080c,
-	0xb2d3, 0x00de, 0x0005, 0x080c, 0xb2d3, 0x0005, 0x00e6, 0x6010,
-	0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee, 0x0005, 0x2009,
-	0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002, 0x6024, 0xc0e5,
-	0x6026, 0xd0cc, 0x0150, 0x2001, 0x1988, 0x2004, 0x6042, 0x2009,
-	0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009, 0x1867, 0x210c,
-	0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006, 0x00d8, 0x2001,
-	0x1988, 0x200c, 0x2001, 0x1986, 0x2004, 0x9100, 0x9080, 0x000a,
-	0x6042, 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be, 0x0008, 0x2104,
-	0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a, 0x600f, 0x0000,
-	0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6, 0x6154, 0xb8bc,
-	0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x6054, 0x9106, 0x1138,
-	0x600c, 0x2072, 0x080c, 0x8a25, 0x080c, 0xb2d3, 0x0010, 0x9cf0,
-	0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e, 0x0005, 0x00d6,
-	0x00b6, 0x6010, 0x2058, 0xb8bc, 0x906d, 0x0130, 0x9c06, 0x0110,
-	0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de, 0x0005, 0x0026,
-	0x0036, 0x0156, 0x2011, 0x182c, 0x2204, 0x9084, 0x00ff, 0x2019,
-	0x026e, 0x2334, 0x96b4, 0x00ff, 0x9636, 0x1508, 0x8318, 0x2334,
-	0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011, 0x0270, 0x20a9,
-	0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a, 0x080c, 0xc379,
-	0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004, 0x6010, 0x0096,
-	0x2048, 0x2019, 0x0006, 0x080c, 0xc379, 0x009e, 0x1100, 0x015e,
-	0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800, 0x080c, 0x60c1,
-	0x080c, 0x3000, 0x00ee, 0x0005, 0x0096, 0x0026, 0x080c, 0x100e,
-	0x090c, 0x0dc5, 0xa85c, 0x9080, 0x001a, 0x20a0, 0x20a9, 0x000c,
-	0xa860, 0x20e8, 0x9006, 0x4004, 0x9186, 0x0046, 0x1118, 0xa867,
-	0x0136, 0x0038, 0xa867, 0x0138, 0x9186, 0x0041, 0x0110, 0xa87b,
-	0x0001, 0x7038, 0x9084, 0xff00, 0x7240, 0x9294, 0xff00, 0x8007,
-	0x9215, 0xaa9a, 0x9186, 0x0046, 0x1168, 0x7038, 0x9084, 0x00ff,
-	0x723c, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x723c, 0x9294, 0x00ff,
-	0xaaa2, 0x0060, 0x7040, 0x9084, 0x00ff, 0x7244, 0x9294, 0xff00,
-	0x9215, 0xaa9e, 0x7244, 0x9294, 0x00ff, 0xaaa2, 0x9186, 0x0046,
-	0x1118, 0x9e90, 0x0012, 0x0010, 0x9e90, 0x001a, 0x2204, 0x8007,
-	0xa8a6, 0x8210, 0x2204, 0x8007, 0xa8aa, 0x8210, 0x2204, 0x8007,
-	0xa8ae, 0x8210, 0x2204, 0x8007, 0xa8b2, 0x8210, 0x9186, 0x0046,
-	0x11b8, 0x9e90, 0x0016, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204,
-	0x8007, 0xa8ba, 0x8210, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204,
-	0x8007, 0xa8c2, 0x8210, 0x2011, 0x0205, 0x2013, 0x0001, 0x00b0,
-	0x9e90, 0x001e, 0x2204, 0x8007, 0xa8b6, 0x8210, 0x2204, 0x8007,
-	0xa8ba, 0x2011, 0x0205, 0x2013, 0x0001, 0x2011, 0x0260, 0x2204,
-	0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2, 0x9186, 0x0046,
-	0x1118, 0x2011, 0x0262, 0x0010, 0x2011, 0x026a, 0x0146, 0x01d6,
-	0x0036, 0x20a9, 0x0001, 0x2019, 0x0008, 0xa860, 0x20e8, 0xa85c,
-	0x9080, 0x0031, 0x20a0, 0x2204, 0x8007, 0x4004, 0x8210, 0x8319,
-	0x1dd0, 0x003e, 0x01ce, 0x013e, 0x2011, 0x0205, 0x2013, 0x0000,
-	0x002e, 0x080c, 0x6e9f, 0x009e, 0x0005, 0x00e6, 0x6010, 0x00b6,
-	0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011, 0x00ee, 0x0005,
-	0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x0076,
-	0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126, 0x2091, 0x8000,
-	0x2029, 0x19f1, 0x252c, 0x2021, 0x19f7, 0x2424, 0x2061, 0x1cd0,
-	0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578, 0x6720, 0x9786,
-	0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500, 0x9c06, 0x01e8,
-	0x2400, 0x9c06, 0x01d0, 0x080c, 0xec62, 0x01b8, 0x080c, 0xec72,
-	0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016, 0x080c, 0x1a8e,
-	0x001e, 0x080c, 0xd2cf, 0x1110, 0x080c, 0x3279, 0x080c, 0xd2e0,
-	0x1110, 0x080c, 0xbcb6, 0x080c, 0xb306, 0x9ce0, 0x0018, 0x2001,
-	0x181a, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e, 0x001e, 0x002e,
-	0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de, 0x00ee, 0x0005,
-	0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006, 0x2001, 0x1837,
-	0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036, 0x0046, 0x080c,
-	0xd7e3, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128, 0x6010, 0x00b6,
-	0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c, 0x4dfb, 0x004e,
-	0x003e, 0x000e, 0x0005, 0x6004, 0x9086, 0x0001, 0x1128, 0x080c,
-	0xac6c, 0x080c, 0xb306, 0x9006, 0x0005, 0x00e6, 0x00c6, 0x00b6,
-	0x0046, 0x2061, 0x1cd0, 0x2071, 0x1800, 0x7454, 0x7074, 0x8001,
-	0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000, 0x9086, 0x0000,
-	0x0148, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1120, 0x6004, 0x9086,
-	0x0002, 0x0140, 0x9ce0, 0x0018, 0x2001, 0x181a, 0x2004, 0x9c02,
-	0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006, 0x004e, 0x00be,
-	0x00ce, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0a4, 0x0160,
-	0x2001, 0x1837, 0x2004, 0xd0a4, 0x0138, 0x2001, 0x1848, 0x2004,
-	0xd0a4, 0x1118, 0x9085, 0x0001, 0x0005, 0x9006, 0x0ce8, 0x0126,
-	0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071, 0x1840, 0xd5a4,
-	0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, 0x0118, 0x7000, 0x8000,
-	0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007, 0x908e, 0x0003,
-	0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x2071,
-	0xfff6, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0126,
-	0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xffee, 0x0021, 0x00ee,
-	0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, 0x2077, 0x1220, 0x8e70,
-	0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, 0x2071, 0xffec, 0x0c99,
-	0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff0, 0x0c69, 0x00ee, 0x0005,
-	0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0x1840, 0x7014,
-	0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, 0x0005, 0x0003, 0x000b,
-	0x07d2, 0x0000, 0xc000, 0x0001, 0x8064, 0x0008, 0x0010, 0x0000,
-	0x8066, 0x0000, 0x0101, 0x0008, 0x4407, 0x0003, 0x8060, 0x0000,
-	0x0400, 0x0000, 0x580d, 0x000b, 0x79c0, 0x0003, 0x5106, 0x0003,
-	0x4c0a, 0x0003, 0xbac0, 0x0009, 0x008a, 0x0000, 0x0c0a, 0x000b,
-	0x15fe, 0x0008, 0x340a, 0x0003, 0xc4c0, 0x0009, 0x7000, 0x0000,
-	0xffa0, 0x0001, 0x2000, 0x0000, 0x1680, 0x000b, 0x808c, 0x0008,
-	0x0001, 0x0000, 0x0000, 0x0007, 0x4028, 0x0000, 0x4047, 0x000a,
-	0x808c, 0x0008, 0x0002, 0x0000, 0x0822, 0x0003, 0x4022, 0x0000,
-	0x0028, 0x000b, 0x4122, 0x0008, 0x94c0, 0x0009, 0xff00, 0x0008,
-	0xffe0, 0x0009, 0x0500, 0x0008, 0x0aab, 0x0003, 0x4447, 0x0002,
-	0x0ea8, 0x000b, 0x0bfe, 0x0008, 0x11a0, 0x0001, 0x1286, 0x0003,
-	0x0ca0, 0x0001, 0x1286, 0x0003, 0x9180, 0x0001, 0x0004, 0x0000,
-	0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000,
-	0x0009, 0x0008, 0x4436, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008,
-	0x0060, 0x0008, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000,
-	0x0411, 0x0000, 0x443e, 0x0003, 0x03fe, 0x0000, 0x43e0, 0x0001,
-	0x0e83, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008, 0x02e0, 0x0001,
-	0x0e83, 0x000b, 0x9180, 0x0001, 0x0005, 0x0008, 0x8060, 0x0000,
-	0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x0019, 0x0000,
-	0x444d, 0x000b, 0x0240, 0x0002, 0x0a80, 0x0003, 0x00fe, 0x0000,
-	0x3283, 0x000b, 0x0248, 0x000a, 0x085c, 0x0003, 0x9180, 0x0001,
-	0x0006, 0x0008, 0x7f62, 0x0008, 0x8002, 0x0008, 0x0003, 0x0008,
-	0x8066, 0x0000, 0x020a, 0x0000, 0x445b, 0x0003, 0x112a, 0x0000,
-	0x002e, 0x0008, 0x022c, 0x0008, 0x3a44, 0x0002, 0x0c0a, 0x000b,
-	0x808c, 0x0008, 0x0002, 0x0000, 0x1760, 0x0008, 0x8062, 0x0008,
-	0x000f, 0x0008, 0x8066, 0x0000, 0x0011, 0x0008, 0x4468, 0x0003,
-	0x01fe, 0x0008, 0x42e0, 0x0009, 0x0e74, 0x0003, 0x00fe, 0x0000,
-	0x43e0, 0x0001, 0x0e74, 0x0003, 0x1734, 0x0000, 0x1530, 0x0000,
-	0x1632, 0x0008, 0x0d2a, 0x0008, 0x9880, 0x0001, 0x0010, 0x0000,
-	0x8060, 0x0000, 0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000,
-	0x1e0a, 0x0008, 0x447a, 0x0003, 0x808a, 0x0008, 0x0003, 0x0008,
-	0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000, 0x5880, 0x000b,
-	0x8066, 0x0000, 0x3679, 0x0000, 0x4483, 0x0003, 0x5884, 0x0003,
-	0x3efe, 0x0008, 0x7f4f, 0x0002, 0x088a, 0x000b, 0x0d00, 0x0000,
-	0x0092, 0x000c, 0x8054, 0x0008, 0x0011, 0x0008, 0x8074, 0x0000,
-	0x1010, 0x0008, 0x1efe, 0x0000, 0x300a, 0x000b, 0x00e0, 0x000c,
-	0x000a, 0x000b, 0x00fe, 0x0000, 0x349a, 0x0003, 0x1a60, 0x0000,
-	0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008,
-	0x4499, 0x000b, 0x03fe, 0x0000, 0x04d0, 0x0001, 0x0cd4, 0x000b,
-	0x82c0, 0x0001, 0x1f00, 0x0000, 0xffa0, 0x0001, 0x0400, 0x0000,
-	0x08b2, 0x0003, 0x14dc, 0x0003, 0x01fe, 0x0008, 0x0580, 0x0009,
-	0x7f06, 0x0000, 0x8690, 0x0009, 0x0000, 0x0008, 0x7f0c, 0x0000,
-	0x02fe, 0x0008, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x0680, 0x0009,
-	0x10b2, 0x0003, 0x7f08, 0x0008, 0x84c0, 0x0001, 0xff00, 0x0008,
-	0x08d4, 0x0003, 0xb9c0, 0x0009, 0x0030, 0x0008, 0x0cc3, 0x000b,
-	0x8060, 0x0000, 0x0400, 0x0000, 0x80fe, 0x0008, 0x1a0a, 0x0009,
-	0x7f62, 0x0008, 0x8066, 0x0000, 0x0409, 0x0000, 0x44bc, 0x0003,
-	0x80fe, 0x0008, 0x1a09, 0x0009, 0x7f62, 0x0008, 0x8066, 0x0000,
-	0x040a, 0x0000, 0x44c2, 0x0003, 0x00fe, 0x0000, 0x34ca, 0x0003,
-	0x8072, 0x0000, 0x1010, 0x0008, 0x3944, 0x0002, 0x08c5, 0x0003,
-	0x00ce, 0x0003, 0x8072, 0x0000, 0x2020, 0x0008, 0x3945, 0x000a,
-	0x08ca, 0x0003, 0x3946, 0x000a, 0x0cdb, 0x000b, 0x0000, 0x0007,
-	0x3943, 0x000a, 0x08db, 0x0003, 0x00ce, 0x0003, 0x00fe, 0x0000,
-	0x34d9, 0x000b, 0x8072, 0x0000, 0x1000, 0x0000, 0x00db, 0x000b,
-	0x8072, 0x0000, 0x2000, 0x0000, 0x4000, 0x000f, 0x86c0, 0x0009,
-	0xfc00, 0x0008, 0x08d4, 0x0003, 0x00b2, 0x000b, 0x1c60, 0x0000,
-	0x1b62, 0x0000, 0x8066, 0x0000, 0x0231, 0x0008, 0x44e4, 0x000b,
-	0x58e5, 0x000b, 0x0140, 0x0008, 0x0242, 0x0000, 0x1f43, 0x0002,
-	0x0cf3, 0x000b, 0x0d44, 0x0000, 0x0d46, 0x0008, 0x0348, 0x0008,
-	0x044a, 0x0008, 0x030a, 0x0008, 0x040c, 0x0000, 0x0d06, 0x0000,
-	0x0d08, 0x0008, 0x00f7, 0x0003, 0x0344, 0x0008, 0x0446, 0x0008,
-	0x0548, 0x0008, 0x064a, 0x0000, 0x1948, 0x000a, 0x08fa, 0x0003,
-	0x0d4a, 0x0008, 0x58fa, 0x0003, 0x3efe, 0x0008, 0x7f4f, 0x0002,
-	0x0901, 0x0003, 0x8000, 0x0000, 0x0001, 0x0000, 0x0092, 0x000c,
-	0x8054, 0x0008, 0x0001, 0x0000, 0x8074, 0x0000, 0x2020, 0x0008,
-	0x4000, 0x000f, 0x3a40, 0x000a, 0x0c0d, 0x0003, 0x2b24, 0x0008,
-	0x2b24, 0x0008, 0x590a, 0x000b, 0x8054, 0x0008, 0x0002, 0x0000,
-	0x1242, 0x0002, 0x0958, 0x0003, 0x3a45, 0x000a, 0x0947, 0x000b,
-	0x8072, 0x0000, 0x1000, 0x0000, 0x3945, 0x000a, 0x0917, 0x000b,
-	0x8072, 0x0000, 0x3010, 0x0000, 0x1e10, 0x000a, 0x7f3c, 0x0000,
-	0x0942, 0x000b, 0x1d00, 0x0002, 0x7f3a, 0x0000, 0x0d60, 0x0000,
-	0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x4520, 0x000b,
-	0x00fe, 0x0000, 0x353f, 0x000b, 0x1c60, 0x0000, 0x8062, 0x0008,
-	0x0001, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008, 0x4528, 0x0003,
-	0x00fe, 0x0000, 0x325b, 0x000b, 0x0038, 0x0000, 0x0060, 0x0008,
-	0x8062, 0x0008, 0x0019, 0x0000, 0x8066, 0x0000, 0x0009, 0x0008,
-	0x4531, 0x000b, 0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f3e, 0x0008,
-	0x0d60, 0x0000, 0x0efe, 0x0008, 0x1f80, 0x0001, 0x7f62, 0x0008,
-	0x8066, 0x0000, 0x0009, 0x0008, 0x453b, 0x000b, 0x003a, 0x0008,
-	0x1dfe, 0x0000, 0x011c, 0x000b, 0x0036, 0x0008, 0x00e0, 0x000c,
-	0x0158, 0x000b, 0x8074, 0x0000, 0x2000, 0x0000, 0x8072, 0x0000,
-	0x2000, 0x0000, 0x0158, 0x000b, 0x3a44, 0x0002, 0x0a89, 0x0003,
-	0x8074, 0x0000, 0x1000, 0x0000, 0x8072, 0x0000, 0x1000, 0x0000,
-	0x2d0e, 0x0000, 0x2d0e, 0x0000, 0x3658, 0x0003, 0x26fe, 0x0008,
-	0x26fe, 0x0008, 0x2700, 0x0008, 0x2700, 0x0008, 0x00d0, 0x0009,
-	0x0d6a, 0x0003, 0x8074, 0x0000, 0x4040, 0x0008, 0x5958, 0x0003,
-	0x5106, 0x0003, 0x3a46, 0x000a, 0x0d6a, 0x0003, 0x3a47, 0x0002,
-	0x0965, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000,
-	0x8000, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x01b4, 0x0003,
-	0x92c0, 0x0009, 0x0fc8, 0x0000, 0x080a, 0x0003, 0x1246, 0x000a,
-	0x0e52, 0x000b, 0x1a60, 0x0000, 0x8062, 0x0008, 0x0002, 0x0000,
-	0x8066, 0x0000, 0x362a, 0x0000, 0x456f, 0x0003, 0x2000, 0x0000,
-	0x2000, 0x0000, 0x2102, 0x0000, 0x2102, 0x0000, 0x2204, 0x0000,
-	0x2204, 0x0000, 0x2306, 0x0000, 0x2306, 0x0000, 0x2408, 0x0000,
-	0x2408, 0x0000, 0x250a, 0x0000, 0x250a, 0x0000, 0x260c, 0x0000,
-	0x260c, 0x0000, 0x270e, 0x0000, 0x270e, 0x0000, 0x2810, 0x0000,
-	0x2810, 0x0000, 0x2912, 0x0000, 0x2912, 0x0000, 0x1a60, 0x0000,
-	0x8062, 0x0008, 0x0007, 0x0000, 0x8066, 0x0000, 0x0052, 0x0000,
-	0x4589, 0x000b, 0x92c0, 0x0009, 0x0780, 0x0008, 0x0e6e, 0x000b,
-	0x124b, 0x0002, 0x0992, 0x0003, 0x2e4d, 0x0002, 0x2e4d, 0x0002,
-	0x0a58, 0x0003, 0x3a46, 0x000a, 0x0da2, 0x000b, 0x5994, 0x0003,
-	0x8054, 0x0008, 0x0004, 0x0000, 0x1243, 0x000a, 0x09b0, 0x0003,
-	0x8010, 0x0008, 0x000d, 0x0000, 0x0233, 0x000c, 0x1948, 0x000a,
-	0x099f, 0x000b, 0x0228, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c,
-	0x01b0, 0x000b, 0x1948, 0x000a, 0x09a6, 0x000b, 0x1243, 0x000a,
-	0x0a5b, 0x0003, 0x194d, 0x000a, 0x09aa, 0x000b, 0x1243, 0x000a,
-	0x0a62, 0x0003, 0x59aa, 0x000b, 0x8054, 0x0008, 0x0004, 0x0000,
-	0x0228, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, 0x8074, 0x0000,
-	0xf000, 0x0008, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000,
-	0x3a42, 0x0002, 0x0dba, 0x000b, 0x15fe, 0x0008, 0x3461, 0x000b,
-	0x000a, 0x000b, 0x8074, 0x0000, 0x0501, 0x0000, 0x8010, 0x0008,
-	0x000c, 0x0008, 0x0233, 0x000c, 0x000a, 0x000b, 0xbbe0, 0x0009,
-	0x0030, 0x0008, 0x0dd0, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009,
-	0x09cd, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009, 0x09cd, 0x0003,
-	0x0223, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000, 0x0220, 0x000b,
-	0x8076, 0x0008, 0x0041, 0x0008, 0x0220, 0x000b, 0xbbe0, 0x0009,
-	0x0032, 0x0000, 0x0dd5, 0x000b, 0x3c1e, 0x0008, 0x0220, 0x000b,
-	0xbbe0, 0x0009, 0x003b, 0x0000, 0x0dda, 0x000b, 0x3c20, 0x0000,
-	0x0220, 0x000b, 0xbbe0, 0x0009, 0x0035, 0x0008, 0x0de0, 0x000b,
-	0x8072, 0x0000, 0x8000, 0x0000, 0x039e, 0x0003, 0xbbe0, 0x0009,
-	0x0036, 0x0008, 0x0abd, 0x000b, 0xbbe0, 0x0009, 0x0037, 0x0000,
-	0x0e01, 0x000b, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0dcd, 0x000b,
-	0x8076, 0x0008, 0x0040, 0x0000, 0x1a60, 0x0000, 0x8062, 0x0008,
-	0x000d, 0x0000, 0x2604, 0x0008, 0x2604, 0x0008, 0x2706, 0x0008,
-	0x2706, 0x0008, 0x2808, 0x0000, 0x2808, 0x0000, 0x290a, 0x0000,
-	0x290a, 0x0000, 0x8066, 0x0000, 0x0422, 0x0000, 0x45f8, 0x000b,
-	0x0228, 0x000c, 0x8054, 0x0008, 0x0004, 0x0000, 0x8074, 0x0000,
-	0xf000, 0x0008, 0x8072, 0x0000, 0xb000, 0x0000, 0x01b4, 0x0003,
-	0xbbe0, 0x0009, 0x0038, 0x0000, 0x0e13, 0x000b, 0x18fe, 0x0000,
-	0x3ce0, 0x0009, 0x0a10, 0x0003, 0x15fe, 0x0008, 0x3ce0, 0x0009,
-	0x0dc9, 0x0003, 0x0223, 0x0004, 0x8076, 0x0008, 0x0040, 0x0000,
-	0x8072, 0x0000, 0x8000, 0x0000, 0x0280, 0x000b, 0x8076, 0x0008,
-	0x0042, 0x0008, 0x0220, 0x000b, 0xbbe0, 0x0009, 0x0016, 0x0000,
-	0x0e20, 0x000b, 0x8074, 0x0000, 0x0808, 0x0008, 0x3a44, 0x0002,
-	0x0c0c, 0x000b, 0x8074, 0x0000, 0x0800, 0x0000, 0x8072, 0x0000,
-	0x8000, 0x0000, 0x8000, 0x000f, 0x000a, 0x000b, 0x8072, 0x0000,
-	0x8000, 0x0000, 0x000a, 0x000b, 0x3d30, 0x000a, 0x7f00, 0x0000,
-	0xbc80, 0x0001, 0x0007, 0x0000, 0x022c, 0x000b, 0x1930, 0x000a,
-	0x7f00, 0x0000, 0x9880, 0x0001, 0x0007, 0x0000, 0x8060, 0x0000,
-	0x0400, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000, 0x000a, 0x0008,
-	0x4631, 0x000b, 0x4000, 0x000f, 0x2236, 0x000b, 0x0870, 0x0008,
-	0x4000, 0x000f, 0x7e33, 0x000b, 0xbbe0, 0x0009, 0x0030, 0x0008,
-	0x0e33, 0x0003, 0x18fe, 0x0000, 0x3ce0, 0x0009, 0x0a44, 0x000b,
-	0x15fe, 0x0008, 0x3ce0, 0x0009, 0x0a44, 0x000b, 0x0223, 0x0004,
-	0x8076, 0x0008, 0x0040, 0x0000, 0x0246, 0x000b, 0x8076, 0x0008,
-	0x0041, 0x0008, 0x8072, 0x0000, 0x8000, 0x0000, 0x0233, 0x0003,
-	0xbac0, 0x0009, 0x0090, 0x0008, 0x0a4f, 0x0003, 0x8074, 0x0000,
-	0x0706, 0x0000, 0x0251, 0x000b, 0x8074, 0x0000, 0x0703, 0x0000,
-	0x4000, 0x000f, 0x8010, 0x0008, 0x0023, 0x0000, 0x028e, 0x0003,
-	0x8010, 0x0008, 0x0008, 0x0000, 0x028e, 0x0003, 0x8010, 0x0008,
-	0x0022, 0x0008, 0x028e, 0x0003, 0x0228, 0x000c, 0x8010, 0x0008,
-	0x0007, 0x0000, 0x0233, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c,
-	0x029a, 0x0003, 0x0228, 0x000c, 0x8010, 0x0008, 0x001b, 0x0008,
-	0x0233, 0x000c, 0x1810, 0x0000, 0x0233, 0x000c, 0x8074, 0x0000,
-	0xf080, 0x0000, 0x8072, 0x0000, 0x3000, 0x0008, 0x0d30, 0x0000,
-	0x000a, 0x000b, 0x8010, 0x0008, 0x0009, 0x0008, 0x028e, 0x0003,
-	0x8010, 0x0008, 0x0005, 0x0008, 0x028e, 0x0003, 0x1648, 0x000a,
-	0x0c6f, 0x000b, 0x808c, 0x0008, 0x0001, 0x0000, 0x8010, 0x0008,
-	0x0004, 0x0000, 0x4143, 0x000a, 0x086f, 0x0003, 0x3a44, 0x0002,
-	0x0c0a, 0x000b, 0x0d2a, 0x0008, 0x028e, 0x0003, 0x8010, 0x0008,
-	0x0003, 0x0008, 0x0292, 0x000b, 0x8010, 0x0008, 0x000b, 0x0000,
-	0x0292, 0x000b, 0x8010, 0x0008, 0x0002, 0x0000, 0x0292, 0x000b,
-	0x3a47, 0x0002, 0x0d58, 0x000b, 0x8010, 0x0008, 0x0006, 0x0008,
-	0x0292, 0x000b, 0x8074, 0x0000, 0xf000, 0x0008, 0x8072, 0x0000,
-	0x3000, 0x0008, 0x0233, 0x000c, 0x0249, 0x0004, 0x3a40, 0x000a,
-	0x080a, 0x0003, 0x8010, 0x0008, 0x000c, 0x0008, 0x0233, 0x000c,
-	0x000a, 0x000b, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000,
-	0x3000, 0x0008, 0x0d30, 0x0000, 0x2e4d, 0x0002, 0x2e4d, 0x0002,
-	0x0aa5, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000, 0x000a, 0x000b,
-	0x8054, 0x0008, 0x0009, 0x0008, 0x000a, 0x000b, 0x3a44, 0x0002,
-	0x0c0a, 0x000b, 0x0283, 0x000b, 0x808c, 0x0008, 0x0000, 0x0008,
-	0x4447, 0x0002, 0x0ad1, 0x000b, 0xc0c0, 0x0001, 0x00ff, 0x0008,
-	0xffe0, 0x0009, 0x00ff, 0x0008, 0x0ea8, 0x000b, 0xc1e0, 0x0001,
-	0xffff, 0x0008, 0x0ea8, 0x000b, 0x8010, 0x0008, 0x0013, 0x0000,
-	0x0233, 0x000c, 0x8074, 0x0000, 0x0202, 0x0008, 0x000a, 0x000b,
-	0x3a40, 0x000a, 0x0ece, 0x000b, 0x8074, 0x0000, 0x0200, 0x0000,
-	0x3d00, 0x0000, 0x3cfe, 0x0000, 0x8072, 0x0000, 0x8000, 0x0000,
-	0x43e0, 0x0001, 0x0ecc, 0x0003, 0x42fe, 0x0000, 0xffc0, 0x0001,
-	0x00ff, 0x0008, 0x00e0, 0x0009, 0x0aa8, 0x0003, 0x0d08, 0x0008,
-	0x0321, 0x000b, 0x8072, 0x0000, 0x8000, 0x0000, 0x000a, 0x000b,
-	0x03a7, 0x000c, 0x808c, 0x0008, 0x0001, 0x0000, 0x04fe, 0x0008,
-	0x338a, 0x0003, 0x0460, 0x0000, 0x8062, 0x0008, 0x0001, 0x0000,
-	0x8066, 0x0000, 0x0009, 0x0008, 0x46db, 0x0003, 0x0004, 0x0000,
-	0x80c0, 0x0009, 0x00ff, 0x0008, 0x7f00, 0x0000, 0x80e0, 0x0001,
-	0x0004, 0x0000, 0x0af5, 0x000b, 0x80e0, 0x0001, 0x0005, 0x0008,
-	0x0af5, 0x000b, 0x80e0, 0x0001, 0x0006, 0x0008, 0x0af5, 0x000b,
-	0x82c0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008, 0x82e0, 0x0009,
-	0x0600, 0x0008, 0x0af5, 0x000b, 0x82e0, 0x0009, 0x0500, 0x0008,
-	0x0af5, 0x000b, 0x82e0, 0x0009, 0x0400, 0x0000, 0x0f8a, 0x0003,
-	0xc4c0, 0x0009, 0x7000, 0x0000, 0xffe0, 0x0009, 0x1000, 0x0000,
-	0x0b21, 0x0003, 0x0398, 0x000c, 0x3941, 0x0002, 0x0b00, 0x0003,
-	0x8072, 0x0000, 0x0400, 0x0000, 0x000a, 0x000b, 0x0460, 0x0000,
-	0x80fe, 0x0008, 0x002b, 0x0008, 0x7f62, 0x0008, 0x8066, 0x0000,
-	0x2209, 0x0008, 0x4706, 0x000b, 0x11fe, 0x0000, 0x331c, 0x0003,
-	0x9180, 0x0001, 0x0002, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000,
-	0x7f62, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008, 0x4710, 0x0003,
-	0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x03e0, 0x0009,
-	0x0f19, 0x0003, 0x8072, 0x0000, 0x0400, 0x0000, 0x0046, 0x0003,
-	0x9180, 0x0001, 0x0003, 0x0008, 0x0303, 0x000b, 0x8072, 0x0000,
-	0x0400, 0x0000, 0x8010, 0x0008, 0x0010, 0x0000, 0x037b, 0x000b,
-	0x0398, 0x000c, 0x3941, 0x0002, 0x0b27, 0x0003, 0x8072, 0x0000,
-	0x0400, 0x0000, 0x000a, 0x000b, 0x1042, 0x000a, 0x0b2c, 0x000b,
-	0x0360, 0x0004, 0x11fe, 0x0000, 0x3731, 0x000b, 0x8072, 0x0000,
-	0x0400, 0x0000, 0x8010, 0x0008, 0x000e, 0x0000, 0x037b, 0x000b,
-	0x8060, 0x0000, 0x0400, 0x0000, 0x04fe, 0x0008, 0x3746, 0x000b,
-	0x808c, 0x0008, 0x0000, 0x0008, 0x9180, 0x0001, 0x0005, 0x0008,
-	0x7f62, 0x0008, 0x8066, 0x0000, 0x0009, 0x0008, 0x473c, 0x000b,
-	0x0060, 0x0008, 0x8062, 0x0008, 0x001b, 0x0008, 0x4304, 0x0008,
-	0x4206, 0x0008, 0x8066, 0x0000, 0x0412, 0x0000, 0x4744, 0x000b,
-	0x035d, 0x0003, 0x808c, 0x0008, 0x0001, 0x0000, 0x0460, 0x0000,
-	0x8062, 0x0008, 0x002b, 0x0008, 0x8066, 0x0000, 0x0609, 0x0008,
-	0x474d, 0x000b, 0x8066, 0x0000, 0x220a, 0x0008, 0x4750, 0x000b,
-	0x42fe, 0x0000, 0xffc0, 0x0001, 0xff00, 0x0008, 0x7f04, 0x0008,
-	0x8060, 0x0000, 0x0400, 0x0000, 0x9180, 0x0001, 0x0002, 0x0000,
-	0x7f62, 0x0008, 0x8066, 0x0000, 0x041a, 0x0008, 0x475c, 0x000b,
-	0x8072, 0x0000, 0x0400, 0x0000, 0x0046, 0x0003, 0x8060, 0x0000,
-	0x0400, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x0411, 0x0000,
-	0x4765, 0x000b, 0x02fe, 0x0008, 0x03e0, 0x0009, 0x0f6b, 0x0003,
-	0x0d22, 0x0000, 0x4000, 0x000f, 0x8280, 0x0009, 0x0002, 0x0000,
-	0x1380, 0x0001, 0x7f62, 0x0008, 0x8066, 0x0000, 0x2209, 0x0008,
-	0x4771, 0x000b, 0x0200, 0x000a, 0xffc0, 0x0001, 0x0007, 0x0000,
-	0x7f06, 0x0000, 0x1362, 0x0008, 0x8066, 0x0000, 0x060a, 0x0008,
-	0x4779, 0x0003, 0x4000, 0x000f, 0x3a44, 0x0002, 0x0c0a, 0x000b,
-	0x2f44, 0x000a, 0x2f44, 0x000a, 0x0e83, 0x000b, 0x808a, 0x0008,
-	0x0003, 0x0008, 0x8074, 0x0000, 0xf080, 0x0000, 0x8072, 0x0000,
-	0x3000, 0x0008, 0x5b86, 0x000b, 0x8054, 0x0008, 0x0019, 0x0000,
-	0x000a, 0x000b, 0x3a44, 0x0002, 0x0c0a, 0x000b, 0x808c, 0x0008,
-	0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0008, 0x0233, 0x000c,
-	0x42fe, 0x0000, 0xffc0, 0x0001, 0x00ff, 0x0008, 0x7f10, 0x0008,
-	0x0233, 0x000c, 0x4310, 0x0008, 0x0292, 0x000b, 0x3941, 0x0002,
-	0x0b9b, 0x000b, 0x4000, 0x000f, 0x8072, 0x0000, 0x0404, 0x0008,
-	0x4000, 0x000f, 0x8010, 0x0008, 0x0012, 0x0008, 0x0233, 0x000c,
-	0x0360, 0x0004, 0x1110, 0x0000, 0x0233, 0x000c, 0x11fe, 0x0000,
-	0x37a1, 0x000b, 0x000a, 0x000b, 0xc2c0, 0x0009, 0x00ff, 0x0008,
-	0x7f00, 0x0000, 0xc3c0, 0x0001, 0xff00, 0x0008, 0x00d0, 0x0009,
-	0x0bcc, 0x0003, 0x0d0a, 0x0000, 0x8580, 0x0001, 0x1000, 0x0000,
-	0x7f62, 0x0008, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066, 0x0000,
-	0x0809, 0x0000, 0x47b6, 0x0003, 0x04fe, 0x0008, 0x33c5, 0x000b,
-	0x0460, 0x0000, 0x8062, 0x0008, 0x0004, 0x0000, 0x8066, 0x0000,
-	0x0211, 0x0000, 0x47be, 0x000b, 0x01fe, 0x0008, 0x00e0, 0x0009,
-	0x0fc5, 0x000b, 0x02fe, 0x0008, 0x43e0, 0x0001, 0x0bcb, 0x000b,
-	0x0500, 0x0002, 0x7f0a, 0x0000, 0xffe0, 0x0009, 0x0800, 0x0000,
-	0x0faf, 0x000b, 0x0d08, 0x0008, 0x4000, 0x000f, 0x43fe, 0x0008,
-	0x3e80, 0x0001, 0xffc0, 0x0001, 0x7fff, 0x0000, 0x0d60, 0x0000,
-	0x7f62, 0x0008, 0x8066, 0x0000, 0x0809, 0x0000, 0x47d4, 0x000b,
-	0x8060, 0x0000, 0x0400, 0x0000, 0x84c0, 0x0001, 0xff00, 0x0008,
-	0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a,
-	0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a, 0x7f60, 0x000a,
-	0xff80, 0x0009, 0x1000, 0x0000, 0x7f62, 0x0008, 0x8066, 0x0000,
-	0x0809, 0x0000, 0x47e6, 0x0003, 0x4000, 0x000f, 0x8d5b, 0xeac4,
-	0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
-	0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
-	0x12b0
-};
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2300ipx_length01 = 0xf091;
-#else
-unsigned short risc_code_length01 = 0xf091;
-#endif
-
diff --git a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c
deleted file mode 100644
index 3c8cafc..0000000
--- a/drivers/scsi/qla2xxx/ql2322.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "qla_def.h"
-
-static char qla_driver_name[] = "qla2322";
-
-extern unsigned char  fw2322ipx_version[];
-extern unsigned char  fw2322ipx_version_str[];
-extern unsigned short fw2322ipx_addr01;
-extern unsigned short fw2322ipx_code01[];
-extern unsigned short fw2322ipx_length01;
-extern unsigned long rseqipx_code_addr01;
-extern unsigned short rseqipx_code01[];
-extern unsigned short rseqipx_code_length01;
-extern unsigned long xseqipx_code_addr01;
-extern unsigned short xseqipx_code01[];
-extern unsigned short xseqipx_code_length01;
-
-static struct qla_fw_info qla_fw_tbl[] = {
-	{
-		.addressing	= FW_INFO_ADDR_NORMAL,
-		.fwcode		= &fw2322ipx_code01[0],
-		.fwlen		= &fw2322ipx_length01,
-		.fwstart	= &fw2322ipx_addr01,
-	},
-	{
-		.addressing	= FW_INFO_ADDR_EXTENDED,
-		.fwcode		= &rseqipx_code01[0],
-		.fwlen		= &rseqipx_code_length01,
-		.lfwstart	= &rseqipx_code_addr01,
-	},
-	{
-		.addressing	= FW_INFO_ADDR_EXTENDED,
-		.fwcode		= &xseqipx_code01[0],
-		.fwlen		= &xseqipx_code_length01,
-		.lfwstart	= &xseqipx_code_addr01,
-	},
-	{ FW_INFO_ADDR_NOMORE, },
-};
-
-static struct qla_board_info qla_board_tbl[] = {
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP2322",
-		.fw_info	= qla_fw_tbl,
-	},
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP6322",
-		.fw_info	= qla_fw_tbl,
-	},
-};
-
-static struct pci_device_id qla2322_pci_tbl[] = {
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2322,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[0],
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP6322,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[1],
-	},
-	{0, 0},
-};
-MODULE_DEVICE_TABLE(pci, qla2322_pci_tbl);
-
-static int __devinit
-qla2322_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	return qla2x00_probe_one(pdev,
-	    (struct qla_board_info *)id->driver_data);
-}
-
-static void __devexit
-qla2322_remove_one(struct pci_dev *pdev)
-{
-	qla2x00_remove_one(pdev);
-}
-
-static struct pci_driver qla2322_pci_driver = {
-	.name		= "qla2322",
-	.id_table	= qla2322_pci_tbl,
-	.probe		= qla2322_probe_one,
-	.remove		= __devexit_p(qla2322_remove_one),
-};
-
-static int __init
-qla2322_init(void)
-{
-	return pci_module_init(&qla2322_pci_driver);
-}
-
-static void __exit
-qla2322_exit(void)
-{
-	pci_unregister_driver(&qla2322_pci_driver);
-}
-
-module_init(qla2322_init);
-module_exit(qla2322_exit);
-
-MODULE_AUTHOR("QLogic Corporation");
-MODULE_DESCRIPTION("QLogic ISP2322 FC-SCSI Host Bus Adapter driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2322_fw.c b/drivers/scsi/qla2xxx/ql2322_fw.c
deleted file mode 100644
index 53599a8..0000000
--- a/drivers/scsi/qla2xxx/ql2322_fw.c
+++ /dev/null
@@ -1,8376 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-
-/*
- *	Firmware Version 3.03.20 (15:42 Feb 01, 2006)
- */
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2322ipx_version = 3*1024+3;
-#else
-unsigned short risc_code_version = 3*1024+3;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned char fw2322ipx_version_str[] = {3, 3,20};
-#else
-unsigned char firmware_version[] = {3, 3,20};
-#endif
-
-#ifdef UNIQUE_FW_NAME
-#define fw2322ipx_VERSION_STRING "3.03.20"
-#else
-#define FW_VERSION_STRING "3.03.20"
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2322ipx_addr01 = 0x0800 ;
-#else
-unsigned short risc_code_addr01 = 0x0800 ;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2322ipx_code01[] = { 
-#else
-unsigned short risc_code01[] = { 
-#endif
-	0x0470, 0x0000, 0x0000, 0xe719, 0x0000, 0x0003, 0x0003, 0x0014,
-	0x0137, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2032, 0x3030,
-	0x3120, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
-	0x5449, 0x4f4e, 0x2049, 0x5350, 0x3233, 0x3030, 0x2046, 0x6972,
-	0x6d77, 0x6172, 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030,
-	0x332e, 0x3033, 0x2e32, 0x3020, 0x2020, 0x2020, 0x2400, 0x20a9,
-	0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2200, 0x20a9, 0x000f,
-	0x2001, 0x0000, 0x400f, 0x2091, 0x2400, 0x20a9, 0x000f, 0x2001,
-	0x0000, 0x400f, 0x2091, 0x2600, 0x20a9, 0x000f, 0x2001, 0x0000,
-	0x400f, 0x2091, 0x2800, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f,
-	0x2091, 0x2a00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091,
-	0x2c00, 0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2e00,
-	0x20a9, 0x000f, 0x2001, 0x0000, 0x400f, 0x2091, 0x2000, 0x2001,
-	0x0000, 0x20c1, 0x0004, 0x20c9, 0x1cff, 0x2059, 0x0000, 0x2b78,
-	0x7883, 0x0004, 0x2089, 0x2bc2, 0x2051, 0x1800, 0x2a70, 0x20e1,
-	0x0001, 0x20e9, 0x0001, 0x2009, 0x0000, 0x080c, 0x0e74, 0x00f6,
-	0x7888, 0x9005, 0x11f8, 0x2061, 0xc000, 0x080c, 0x20c6, 0x1170,
-	0x2079, 0x0300, 0x080c, 0x20dc, 0x2061, 0xe000, 0x080c, 0x20c6,
-	0x1128, 0x2079, 0x0380, 0x080c, 0x20dc, 0x0060, 0x00fe, 0x7883,
-	0x4010, 0x7837, 0x4010, 0x7833, 0x0011, 0x2091, 0x5000, 0x2091,
-	0x4080, 0x0cf8, 0x00fe, 0x2029, 0x5600, 0x2031, 0xffff, 0x2039,
-	0x55dc, 0x2021, 0x0200, 0x20e9, 0x0001, 0x20a1, 0x0000, 0x20a9,
-	0x0800, 0x900e, 0x4104, 0x20e9, 0x0001, 0x20a1, 0x1000, 0x900e,
-	0x2001, 0x0dc1, 0x9084, 0x0fff, 0x20a8, 0x4104, 0x2001, 0x0000,
-	0x9086, 0x0000, 0x0120, 0x21a8, 0x4104, 0x8001, 0x1de0, 0x756e,
-	0x7672, 0x776a, 0x7476, 0x747a, 0x00e6, 0x2071, 0x1b73, 0x2472,
-	0x00ee, 0x20a1, 0x1ddc, 0x7170, 0x810d, 0x810d, 0x810d, 0x810d,
-	0x918c, 0x000f, 0x2001, 0x0001, 0x9112, 0x900e, 0x21a8, 0x4104,
-	0x8211, 0x1de0, 0x7170, 0x3400, 0x8001, 0x9102, 0x0120, 0x0218,
-	0x20a8, 0x900e, 0x4104, 0x2009, 0x1800, 0x810d, 0x810d, 0x810d,
-	0x810d, 0x810d, 0x918c, 0x001f, 0x2001, 0x0001, 0x9112, 0x20e9,
-	0x0001, 0x20a1, 0x0800, 0x900e, 0x20a9, 0x0800, 0x4104, 0x8211,
-	0x1dd8, 0x080c, 0x0f71, 0x080c, 0x61ab, 0x080c, 0xb102, 0x080c,
-	0x1128, 0x080c, 0x1352, 0x080c, 0x1c1c, 0x080c, 0x9582, 0x080c,
-	0x0d17, 0x080c, 0x10ad, 0x080c, 0x358e, 0x080c, 0x7aca, 0x080c,
-	0x6cea, 0x080c, 0x8c5d, 0x080c, 0x88be, 0x080c, 0x22bf, 0x080c,
-	0x81f5, 0x080c, 0x20f5, 0x080c, 0x2233, 0x080c, 0x22b4, 0x2091,
-	0x3009, 0x7883, 0x0000, 0x1004, 0x0943, 0x7880, 0x9086, 0x0002,
-	0x1190, 0x7883, 0x4000, 0x7837, 0x4000, 0x7833, 0x0010, 0x0e04,
-	0x0937, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004,
-	0xd084, 0x190c, 0x1200, 0x2071, 0x1800, 0x7003, 0x0000, 0x780c,
-	0x9084, 0x0030, 0x9086, 0x0020, 0x1168, 0x7034, 0xc08d, 0x7036,
-	0x2001, 0x0050, 0x7076, 0x707a, 0x7056, 0x606b, 0x269c, 0x2071,
-	0x1b73, 0x2072, 0x2071, 0x1800, 0x7000, 0x908e, 0x0003, 0x1168,
-	0x080c, 0x4d66, 0x080c, 0x35b5, 0x080c, 0x7b32, 0x080c, 0x7275,
-	0x080c, 0x8d44, 0x080c, 0x88e7, 0x0c68, 0x000b, 0x0c88, 0x0979,
-	0x097a, 0x0b15, 0x0977, 0x0bcf, 0x0d16, 0x0d16, 0x0d16, 0x080c,
-	0x0d85, 0x0005, 0x0126, 0x00f6, 0x2091, 0x8000, 0x7000, 0x9086,
-	0x0001, 0x1904, 0x0ae8, 0x080c, 0x0ec4, 0x080c, 0x779e, 0x0150,
-	0x080c, 0x77c1, 0x15b0, 0x2079, 0x0100, 0x7828, 0x9085, 0x1800,
-	0x782a, 0x0478, 0x080c, 0x76cd, 0x7000, 0x9086, 0x0001, 0x1904,
-	0x0ae8, 0x7098, 0x9086, 0x0029, 0x1904, 0x0ae8, 0x080c, 0x88a7,
-	0x080c, 0x8899, 0x2001, 0x0161, 0x2003, 0x0001, 0x2079, 0x0100,
-	0x2011, 0xffff, 0x080c, 0x2ad3, 0x7a28, 0x9295, 0x5e2c, 0x7a2a,
-	0x2011, 0x7612, 0x080c, 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f,
-	0x2011, 0x6002, 0x080c, 0x8993, 0x2011, 0x8030, 0x901e, 0x7396,
-	0x04d0, 0x080c, 0x58aa, 0x2079, 0x0100, 0x7844, 0x9005, 0x1904,
-	0x0ae8, 0x2011, 0x6002, 0x080c, 0x8993, 0x2011, 0x7612, 0x080c,
-	0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f, 0x2001, 0x0265, 0x2001,
-	0x0205, 0x2003, 0x0000, 0x7840, 0x9084, 0xfffb, 0x7842, 0x2001,
-	0x19a7, 0x2004, 0x9005, 0x1140, 0x00c6, 0x2061, 0x0100, 0x080c,
-	0x6153, 0x00ce, 0x0804, 0x0ae8, 0x780f, 0x006b, 0x7a28, 0x080c,
-	0x77a6, 0x0118, 0x9295, 0x5e2c, 0x0010, 0x9295, 0x402c, 0x7a2a,
-	0x2011, 0x8010, 0x73d8, 0x2001, 0x19a8, 0x2003, 0x0001, 0x080c,
-	0x299b, 0x080c, 0x4ca1, 0x7248, 0xc284, 0x724a, 0x2001, 0x180c,
-	0x200c, 0xc1ac, 0xc1cc, 0x2102, 0x2001, 0x0390, 0x2003, 0x0400,
-	0x080c, 0xacfc, 0x080c, 0xa4f1, 0x2011, 0x0004, 0x080c, 0xcf2b,
-	0x080c, 0xad18, 0x080c, 0x6ab1, 0x080c, 0x779e, 0x1120, 0x080c,
-	0x29fc, 0x0600, 0x0420, 0x080c, 0x615a, 0x0140, 0x7097, 0x0001,
-	0x70d3, 0x0000, 0x080c, 0x5a7c, 0x0804, 0x0ae8, 0x2001, 0x0390,
-	0x2003, 0x0404, 0x080c, 0x5840, 0xd094, 0x0188, 0x2011, 0x180c,
-	0x2204, 0xc0cd, 0x2012, 0x080c, 0x5844, 0xd0d4, 0x1118, 0x080c,
-	0x29fc, 0x1270, 0x2011, 0x180c, 0x2204, 0xc0bc, 0x00a8, 0x080c,
-	0x5844, 0xd0d4, 0x1db8, 0x2011, 0x180c, 0x2204, 0xc0bd, 0x0060,
-	0x2011, 0x180c, 0x2204, 0xc0bd, 0x2012, 0x080c, 0x6c09, 0x1128,
-	0xd0a4, 0x0118, 0x2204, 0xc0fd, 0x2012, 0x080c, 0x6bcf, 0x0120,
-	0x7a0c, 0xc2b4, 0x7a0e, 0x00a8, 0x707f, 0x0000, 0x080c, 0x779e,
-	0x1130, 0x70b0, 0x9005, 0x1168, 0x080c, 0xd389, 0x0050, 0x080c,
-	0xd389, 0x70dc, 0xd09c, 0x1128, 0x70b0, 0x9005, 0x0110, 0x080c,
-	0x6130, 0x70e7, 0x0000, 0x70e3, 0x0000, 0x70a7, 0x0000, 0x080c,
-	0x2a04, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c4, 0x2012, 0x72dc,
-	0x080c, 0x779e, 0x1178, 0x9016, 0x0016, 0x080c, 0x27a4, 0x2019,
-	0x196d, 0x211a, 0x001e, 0x705f, 0xffff, 0x7063, 0x00ef, 0x7083,
-	0x0000, 0x0020, 0x2019, 0x196d, 0x201b, 0x0000, 0x2079, 0x1847,
-	0x7804, 0xd0ac, 0x0108, 0xc295, 0x72de, 0x080c, 0x779e, 0x0118,
-	0x9296, 0x0004, 0x0518, 0x2011, 0x0001, 0x080c, 0xcf2b, 0x70ab,
-	0x0000, 0x70af, 0xffff, 0x7003, 0x0002, 0x00fe, 0x080c, 0x30bf,
-	0x080c, 0xacfc, 0x2011, 0x0005, 0x080c, 0xa62b, 0x080c, 0xad18,
-	0x080c, 0x779e, 0x0148, 0x00c6, 0x2061, 0x0100, 0x0016, 0x080c,
-	0x27a4, 0x61e2, 0x001e, 0x00ce, 0x012e, 0x00e0, 0x70ab, 0x0000,
-	0x70af, 0xffff, 0x7003, 0x0002, 0x080c, 0xacfc, 0x2011, 0x0005,
-	0x080c, 0xa62b, 0x080c, 0xad18, 0x080c, 0x779e, 0x0148, 0x00c6,
-	0x2061, 0x0100, 0x0016, 0x080c, 0x27a4, 0x61e2, 0x001e, 0x00ce,
-	0x00fe, 0x012e, 0x0005, 0x00c6, 0x00b6, 0x080c, 0x779e, 0x1118,
-	0x20a9, 0x0800, 0x0010, 0x20a9, 0x0782, 0x080c, 0x779e, 0x1110,
-	0x900e, 0x0010, 0x2009, 0x007e, 0x86ff, 0x0138, 0x9180, 0x1000,
-	0x2004, 0x905d, 0x0110, 0xb800, 0xd0bc, 0x090c, 0x341e, 0x8108,
-	0x1f04, 0x0afc, 0x707f, 0x0000, 0x7080, 0x9084, 0x00ff, 0x7082,
-	0x70b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x00b6, 0x0126, 0x2091,
-	0x8000, 0x7000, 0x9086, 0x0002, 0x1904, 0x0bcc, 0x70ac, 0x9086,
-	0xffff, 0x0120, 0x080c, 0x30bf, 0x0804, 0x0bcc, 0x70dc, 0xd0ac,
-	0x1110, 0xd09c, 0x0538, 0xd084, 0x0528, 0x0006, 0x2001, 0x0103,
-	0x2003, 0x002b, 0x000e, 0xd08c, 0x01e8, 0x080c, 0x3487, 0x11b0,
-	0x70e0, 0x9086, 0xffff, 0x0190, 0x080c, 0x327b, 0x70dc, 0xd094,
-	0x1904, 0x0bcc, 0x2011, 0x0001, 0x080c, 0xd645, 0x0110, 0x2011,
-	0x0003, 0x901e, 0x080c, 0x32b5, 0x0804, 0x0bcc, 0x70e4, 0x9005,
-	0x1904, 0x0bcc, 0x70a8, 0x9005, 0x1904, 0x0bcc, 0x70dc, 0xd0a4,
-	0x0118, 0xd0b4, 0x0904, 0x0bcc, 0x080c, 0x6bcf, 0x1904, 0x0bcc,
-	0x080c, 0x6c22, 0x1904, 0x0bcc, 0x080c, 0x6c09, 0x01c0, 0x0156,
-	0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1118,
-	0xb800, 0xd0ec, 0x1138, 0x001e, 0x8108, 0x1f04, 0x0b6c, 0x00ce,
-	0x015e, 0x0028, 0x001e, 0x00ce, 0x015e, 0x0804, 0x0bcc, 0x0006,
-	0x2001, 0x0103, 0x2003, 0x002b, 0x000e, 0x2011, 0x19b4, 0x080c,
-	0x0fe1, 0x2011, 0x19ce, 0x080c, 0x0fe1, 0x7030, 0xc08c, 0x7032,
-	0x7003, 0x0003, 0x70af, 0xffff, 0x080c, 0x0e98, 0x9006, 0x080c,
-	0x2631, 0x080c, 0x3487, 0x0118, 0x080c, 0x4e3e, 0x0050, 0x0036,
-	0x0046, 0x2019, 0xffff, 0x2021, 0x0006, 0x080c, 0x4e58, 0x004e,
-	0x003e, 0x00f6, 0x2079, 0x0100, 0x080c, 0x77c1, 0x0150, 0x080c,
-	0x779e, 0x7828, 0x0118, 0x9084, 0xe1ff, 0x0010, 0x9084, 0xffdf,
-	0x782a, 0x00fe, 0x080c, 0xacfc, 0x2001, 0x19e9, 0x2004, 0x9086,
-	0x0005, 0x1120, 0x2011, 0x0000, 0x080c, 0xa62b, 0x2011, 0x0000,
-	0x080c, 0xa635, 0x080c, 0xad18, 0x012e, 0x00be, 0x0005, 0x0016,
-	0x0026, 0x0046, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100,
-	0x7904, 0x918c, 0xfffd, 0x7906, 0x2009, 0x00f7, 0x080c, 0x6119,
-	0x7940, 0x918c, 0x0010, 0x7942, 0x7924, 0xd1b4, 0x0120, 0x2011,
-	0x0040, 0x080c, 0x2ad3, 0xd19c, 0x0120, 0x2011, 0x0008, 0x080c,
-	0x2ad3, 0x0006, 0x0036, 0x0156, 0x0000, 0x2001, 0x19a8, 0x2004,
-	0x9005, 0x1518, 0x080c, 0x2a67, 0x1148, 0x2001, 0x0001, 0x080c,
-	0x29ca, 0x2001, 0x0001, 0x080c, 0x29ad, 0x00b8, 0x080c, 0x2a6f,
-	0x1138, 0x9006, 0x080c, 0x29ca, 0x9006, 0x080c, 0x29ad, 0x0068,
-	0x080c, 0x2a77, 0x1d50, 0x2001, 0x1998, 0x2004, 0xd0fc, 0x0108,
-	0x0020, 0x080c, 0x27d8, 0x0804, 0x0cc9, 0x20a9, 0x003a, 0x1d04,
-	0x0c1f, 0x080c, 0x8a7f, 0x1f04, 0x0c1f, 0x080c, 0x77af, 0x0148,
-	0x080c, 0x77c1, 0x1118, 0x080c, 0x7ac5, 0x0050, 0x080c, 0x77a6,
-	0x0dd0, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x080c, 0x76cd, 0x0020,
-	0x2009, 0x00f8, 0x080c, 0x6119, 0x7850, 0xc0e5, 0x7852, 0x080c,
-	0x779e, 0x0120, 0x7843, 0x0090, 0x7843, 0x0010, 0x2021, 0xe678,
-	0x2019, 0xea60, 0x0d0c, 0x8a7f, 0x7820, 0xd09c, 0x15a0, 0x080c,
-	0x779e, 0x0904, 0x0cab, 0x7824, 0xd0ac, 0x1904, 0x0cce, 0x080c,
-	0x77c1, 0x1548, 0x0046, 0x2021, 0x0320, 0x8421, 0x1df0, 0x004e,
-	0x2011, 0x1800, 0x080c, 0x2ad3, 0x080c, 0x2a7f, 0x7824, 0x9084,
-	0x1800, 0x1168, 0x9484, 0x0fff, 0x1140, 0x2001, 0x1810, 0x2004,
-	0x9084, 0x9000, 0x0110, 0x080c, 0x0cf1, 0x8421, 0x1160, 0x1d04,
-	0x0c7b, 0x080c, 0x8a7f, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x7003,
-	0x0001, 0x0804, 0x0cce, 0x8319, 0x1928, 0x2001, 0x1810, 0x2004,
-	0x9084, 0x9000, 0x0110, 0x080c, 0x0cf1, 0x1d04, 0x0c91, 0x080c,
-	0x8a7f, 0x2009, 0x199b, 0x2104, 0x9005, 0x0118, 0x8001, 0x200a,
-	0x1188, 0x200b, 0x000a, 0x2011, 0x0048, 0x080c, 0x2ad3, 0x20a9,
-	0x0002, 0x080c, 0x2a60, 0x7924, 0x080c, 0x2a7f, 0xd19c, 0x0110,
-	0x080c, 0x299b, 0x00f0, 0x080c, 0x77af, 0x1140, 0x94a2, 0x03e8,
-	0x1128, 0x080c, 0x7772, 0x7003, 0x0001, 0x00c0, 0x2011, 0x1800,
-	0x080c, 0x2ad3, 0x080c, 0x2a7f, 0x7824, 0x080c, 0x77b8, 0x0110,
-	0xd0ac, 0x1160, 0x9084, 0x1800, 0x0904, 0x0c83, 0x7003, 0x0001,
-	0x0028, 0x2001, 0x0001, 0x080c, 0x2631, 0x00a0, 0x7850, 0xc0e4,
-	0x7852, 0x2009, 0x180c, 0x210c, 0xd19c, 0x1120, 0x7904, 0x918d,
-	0x0002, 0x7906, 0x2011, 0x0048, 0x080c, 0x2ad3, 0x7828, 0x9085,
-	0x0028, 0x782a, 0x2001, 0x19a8, 0x2003, 0x0000, 0x9006, 0x78f2,
-	0x015e, 0x003e, 0x000e, 0x012e, 0x00fe, 0x004e, 0x002e, 0x001e,
-	0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x0046, 0x00b6, 0x00c6,
-	0x00d6, 0x00e6, 0x00f6, 0x0156, 0x0071, 0x0d0c, 0x8a7f, 0x015e,
-	0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x004e, 0x003e, 0x002e,
-	0x001e, 0x000e, 0x0005, 0x00e6, 0x2071, 0x189e, 0x7004, 0x9086,
-	0x0001, 0x1110, 0x080c, 0x35b5, 0x00ee, 0x0005, 0x0005, 0x2a70,
-	0x2061, 0x19ac, 0x2063, 0x0003, 0x6007, 0x0003, 0x600b, 0x0014,
-	0x600f, 0x0137, 0x2001, 0x197c, 0x900e, 0x2102, 0x7196, 0x2001,
-	0x0100, 0x2004, 0x9082, 0x0002, 0x0218, 0x705f, 0xffff, 0x0008,
-	0x715e, 0x7067, 0xffff, 0x717e, 0x7182, 0x080c, 0xd389, 0x70ef,
-	0x00c0, 0x2061, 0x196c, 0x6003, 0x0909, 0x6106, 0x600b, 0x8800,
-	0x600f, 0x0200, 0x6013, 0x00ff, 0x6017, 0x001f, 0x611a, 0x601f,
-	0x07d0, 0x2061, 0x1974, 0x6003, 0x8000, 0x6106, 0x610a, 0x600f,
-	0x0200, 0x6013, 0x00ff, 0x6116, 0x601b, 0x0001, 0x611e, 0x2061,
-	0x1989, 0x6003, 0x514c, 0x6007, 0x4f47, 0x600b, 0x4943, 0x600f,
-	0x2020, 0x2001, 0x182c, 0x2102, 0x0005, 0x9016, 0x080c, 0x67b4,
-	0x1178, 0xb804, 0x90c4, 0x00ff, 0x98c6, 0x0006, 0x0128, 0x90c4,
-	0xff00, 0x98c6, 0x0600, 0x1120, 0x9186, 0x0080, 0x0108, 0x8210,
-	0x8108, 0x9186, 0x0800, 0x1d50, 0x2208, 0x0005, 0x2091, 0x8000,
-	0x2079, 0x0000, 0x000e, 0x00f6, 0x0010, 0x2091, 0x8000, 0x0e04,
-	0x0d87, 0x0006, 0x0016, 0x2001, 0x8002, 0x0006, 0x2079, 0x0000,
-	0x000e, 0x7882, 0x7836, 0x001e, 0x798e, 0x000e, 0x788a, 0x000e,
-	0x7886, 0x3900, 0x789a, 0x00d6, 0x2069, 0x0300, 0x6818, 0x78ae,
-	0x681c, 0x78b2, 0x6808, 0x78be, 0x00de, 0x7833, 0x0012, 0x2091,
-	0x5000, 0x0156, 0x00d6, 0x0036, 0x0026, 0x2079, 0x0300, 0x2069,
-	0x1b2b, 0x7a08, 0x226a, 0x2069, 0x1b2c, 0x7a18, 0x226a, 0x8d68,
-	0x7a1c, 0x226a, 0x782c, 0x2019, 0x1b39, 0x201a, 0x2019, 0x1b3c,
-	0x9016, 0x7808, 0xd09c, 0x0168, 0x7820, 0x201a, 0x8210, 0x8318,
-	0x9386, 0x1b55, 0x0108, 0x0ca8, 0x7808, 0xd09c, 0x0110, 0x2011,
-	0xdead, 0x2019, 0x1b3a, 0x782c, 0x201a, 0x8318, 0x221a, 0x7803,
-	0x0000, 0x2069, 0x1a81, 0x901e, 0x20a9, 0x0020, 0x7b26, 0x7a28,
-	0x226a, 0x8d68, 0x8318, 0x1f04, 0x0dde, 0x2069, 0x1aa1, 0x2019,
-	0x0050, 0x20a9, 0x0020, 0x7b26, 0x7a28, 0x226a, 0x8d68, 0x8318,
-	0x1f04, 0x0deb, 0x0491, 0x002e, 0x003e, 0x00de, 0x015e, 0x2079,
-	0x1800, 0x7803, 0x0005, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004,
-	0xd084, 0x0180, 0x2001, 0x1a25, 0x2004, 0x9005, 0x0128, 0x2001,
-	0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a, 0x2003, 0x0002,
-	0x2003, 0x1001, 0x080c, 0x584f, 0x1170, 0x080c, 0x0f32, 0x0110,
-	0x080c, 0x0e85, 0x080c, 0x584f, 0x1130, 0x2071, 0x1800, 0x2011,
-	0x8000, 0x080c, 0x0f46, 0x0c70, 0x0005, 0x2001, 0x0382, 0x2004,
-	0x9084, 0x0007, 0x9086, 0x0001, 0x1120, 0x2001, 0x0015, 0x080c,
-	0xaced, 0x2079, 0x0380, 0x2069, 0x1b0b, 0x7818, 0x6802, 0x781c,
-	0x6806, 0x7840, 0x680a, 0x7844, 0x680e, 0x782c, 0x6812, 0x2019,
-	0x1b16, 0x9016, 0x7808, 0xd09c, 0x0150, 0x7820, 0x201a, 0x8210,
-	0x8318, 0x8210, 0x9282, 0x0011, 0x0ea8, 0x2011, 0xdead, 0x6a2a,
-	0x7830, 0x681a, 0x7834, 0x681e, 0x7838, 0x6822, 0x783c, 0x6826,
-	0x7803, 0x0000, 0x2069, 0x1acb, 0x901e, 0x20a9, 0x0020, 0x7b26,
-	0x7828, 0x206a, 0x8d68, 0x8318, 0x1f04, 0x0e5f, 0x2069, 0x1aeb,
-	0x2019, 0x00b0, 0x20a9, 0x0020, 0x7b26, 0x7828, 0x206a, 0x8d68,
-	0x8318, 0x1f04, 0x0e6c, 0x0005, 0x918c, 0x03ff, 0x2001, 0x0003,
-	0x2004, 0x9084, 0x0600, 0x1118, 0x918d, 0x6c00, 0x0010, 0x918d,
-	0x6400, 0x2001, 0x017f, 0x2102, 0x0005, 0x0026, 0x0126, 0x2011,
-	0x0080, 0x080c, 0x0f24, 0x20a9, 0x0900, 0x080c, 0x0f5a, 0x2011,
-	0x0040, 0x080c, 0x0f24, 0x20a9, 0x0900, 0x080c, 0x0f5a, 0x0c78,
-	0x0026, 0x080c, 0x0f32, 0x1188, 0x2011, 0x010e, 0x2214, 0x9294,
-	0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0x0947, 0x0010, 0x2011,
-	0x1b47, 0x080c, 0x0f46, 0x002e, 0x0005, 0x2011, 0x010e, 0x2214,
-	0x9294, 0x0007, 0x9296, 0x0007, 0x0118, 0x2011, 0xa880, 0x0010,
-	0x2011, 0x6840, 0xd0e4, 0x70f3, 0x0000, 0x1120, 0x70f3, 0x0fa0,
-	0x080c, 0x0f37, 0x002e, 0x0005, 0x0026, 0x080c, 0x0f32, 0x0148,
-	0xd0a4, 0x1138, 0x2011, 0xcdd5, 0x0010, 0x2011, 0x0080, 0x080c,
-	0x0f37, 0x002e, 0x0005, 0x0026, 0x70f3, 0x0000, 0x080c, 0x0f32,
-	0x1130, 0x2011, 0x8040, 0x080c, 0x0f46, 0x002e, 0x0005, 0x080c,
-	0x2a77, 0x1118, 0x2011, 0xcdc5, 0x0010, 0x2011, 0xcac2, 0x080c,
-	0x0f37, 0x002e, 0x0005, 0x00e6, 0x0016, 0x0006, 0x2071, 0x1800,
-	0xd0b4, 0x70ec, 0x71e8, 0x1118, 0xc0e4, 0xc1f4, 0x0050, 0x0006,
-	0x3b00, 0x9084, 0xff3e, 0x20d8, 0x000e, 0x70f3, 0x0000, 0xc0e5,
-	0xc1f5, 0x0099, 0x000e, 0x001e, 0x00ee, 0x0005, 0x00e6, 0x2071,
-	0x1800, 0xd0e4, 0x70ec, 0x1110, 0xc0dc, 0x0008, 0xc0dd, 0x0016,
-	0x71e8, 0x0019, 0x001e, 0x00ee, 0x0005, 0x70ee, 0x71ea, 0x7000,
-	0x9084, 0x0007, 0x000b, 0x0005, 0x0eea, 0x0ec4, 0x0ec4, 0x0e98,
-	0x0ed3, 0x0ec4, 0x0ec4, 0x0ed3, 0xc284, 0x0016, 0x3b08, 0x3a00,
-	0x9104, 0x918d, 0x00c1, 0x21d8, 0x9084, 0xff3e, 0x9205, 0x20d0,
-	0x001e, 0x0005, 0x2001, 0x183b, 0x2004, 0xd0dc, 0x0005, 0x9e86,
-	0x1800, 0x190c, 0x0d85, 0x70ec, 0xd0e4, 0x0108, 0xc2e5, 0x72ee,
-	0xd0e4, 0x1118, 0x9294, 0x00c1, 0x08f9, 0x0005, 0x9e86, 0x1800,
-	0x190c, 0x0d85, 0x70e8, 0xd0f4, 0x0108, 0xc2f5, 0x72ea, 0xd0f4,
-	0x1140, 0x9284, 0x8000, 0x8005, 0xc284, 0x9215, 0x9294, 0x00c1,
-	0x0861, 0x0005, 0x1d04, 0x0f5a, 0x2091, 0x6000, 0x1f04, 0x0f5a,
-	0x0005, 0x890e, 0x810e, 0x810f, 0x9194, 0x003f, 0x918c, 0xffc0,
-	0x0005, 0x0006, 0x2200, 0x914d, 0x894f, 0x894d, 0x894d, 0x000e,
-	0x0005, 0x01d6, 0x0146, 0x0036, 0x0096, 0x2061, 0x188d, 0x600b,
-	0x0000, 0x600f, 0x0000, 0x6003, 0x0000, 0x6007, 0x0000, 0x2009,
-	0xffc0, 0x2105, 0x0006, 0x2001, 0xaaaa, 0x200f, 0x2019, 0x5555,
-	0x9016, 0x2049, 0x0bff, 0xab02, 0xa001, 0xa001, 0xa800, 0x9306,
-	0x1138, 0x2105, 0x9306, 0x0120, 0x8210, 0x99c8, 0x0400, 0x0c98,
-	0x000e, 0x200f, 0x2001, 0x189d, 0x928a, 0x000e, 0x1638, 0x928a,
-	0x0006, 0x2011, 0x0006, 0x1210, 0x2011, 0x0000, 0x2202, 0x9006,
-	0x2008, 0x82ff, 0x01b0, 0x8200, 0x600a, 0x600f, 0xffff, 0x6003,
-	0x0002, 0x6007, 0x0000, 0x0026, 0x2019, 0x0010, 0x9280, 0x0001,
-	0x20e8, 0x21a0, 0x21a8, 0x4104, 0x8319, 0x1de0, 0x8211, 0x1da0,
-	0x002e, 0x009e, 0x003e, 0x014e, 0x01de, 0x0005, 0x2011, 0x000e,
-	0x08e8, 0x0016, 0x0026, 0x0096, 0x3348, 0x080c, 0x0f61, 0x2100,
-	0x9300, 0x2098, 0x22e0, 0x009e, 0x002e, 0x001e, 0x0036, 0x3518,
-	0x20a9, 0x0001, 0x4002, 0x8007, 0x4004, 0x8319, 0x1dd8, 0x003e,
-	0x0005, 0x20e9, 0x0001, 0x71b8, 0x81ff, 0x11c0, 0x9006, 0x2009,
-	0x0200, 0x20a9, 0x0002, 0x9298, 0x0018, 0x23a0, 0x4001, 0x2009,
-	0x0700, 0x20a9, 0x0002, 0x9298, 0x0008, 0x23a0, 0x4001, 0x707c,
-	0x8007, 0x7180, 0x810f, 0x20a9, 0x0002, 0x4001, 0x9298, 0x000c,
-	0x23a0, 0x900e, 0x080c, 0x0d65, 0x2001, 0x0000, 0x810f, 0x20a9,
-	0x0002, 0x4001, 0x0005, 0x89ff, 0x0140, 0xa804, 0xa807, 0x0000,
-	0x0006, 0x080c, 0x108b, 0x009e, 0x0cb0, 0x0005, 0x00e6, 0x2071,
-	0x1800, 0x080c, 0x1104, 0x090c, 0x0d85, 0x00ee, 0x0005, 0x0086,
-	0x00e6, 0x0006, 0x0026, 0x0036, 0x0126, 0x2091, 0x8000, 0x00c9,
-	0x2071, 0x1800, 0x73c0, 0x702c, 0x9016, 0x9045, 0x0158, 0x8210,
-	0x9906, 0x090c, 0x0d85, 0x2300, 0x9202, 0x0120, 0x1a0c, 0x0d85,
-	0xa000, 0x0c98, 0x012e, 0x003e, 0x002e, 0x000e, 0x00ee, 0x008e,
-	0x0005, 0x0086, 0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x1910, 0x7010, 0x9005, 0x0140, 0x7018, 0x9045, 0x0128, 0x9906,
-	0x090c, 0x0d85, 0xa000, 0x0cc8, 0x012e, 0x000e, 0x00ee, 0x008e,
-	0x0005, 0x00e6, 0x2071, 0x1800, 0x0126, 0x2091, 0x8000, 0x70c0,
-	0x8001, 0x0270, 0x70c2, 0x702c, 0x2048, 0x9085, 0x0001, 0xa800,
-	0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee, 0x0005,
-	0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071, 0x1800,
-	0x70c0, 0x90ca, 0x0020, 0x0268, 0x8001, 0x70c2, 0x702c, 0x2048,
-	0xa800, 0x702e, 0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x00ee,
-	0x0005, 0x904e, 0x0cd8, 0x00e6, 0x0126, 0x2091, 0x8000, 0x0016,
-	0x890e, 0x810e, 0x810f, 0x9184, 0x003f, 0xa862, 0x9184, 0xffc0,
-	0xa85e, 0x001e, 0x0020, 0x00e6, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2,
-	0x080c, 0x8899, 0x012e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9026,
-	0x2009, 0x0000, 0x2049, 0x0400, 0x2900, 0x702e, 0x8940, 0x2800,
-	0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0440, 0x0120,
-	0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7000, 0x9005,
-	0x11a0, 0x2001, 0x0558, 0xa802, 0x2048, 0x2009, 0x5600, 0x8940,
-	0x2800, 0xa802, 0xa95e, 0xa863, 0x0001, 0x8420, 0x9886, 0x0800,
-	0x0120, 0x2848, 0x9188, 0x0040, 0x0c90, 0x2071, 0x188d, 0x7104,
-	0x7200, 0x82ff, 0x01d0, 0x7308, 0x8318, 0x831f, 0x831b, 0x831b,
-	0x7312, 0x8319, 0x2001, 0x0800, 0xa802, 0x2048, 0x8900, 0xa802,
-	0x2040, 0xa95e, 0xaa62, 0x8420, 0x2300, 0x9906, 0x0130, 0x2848,
-	0x9188, 0x0040, 0x9291, 0x0000, 0x0c88, 0xa803, 0x0000, 0x2071,
-	0x1800, 0x74be, 0x74c2, 0x0005, 0x00e6, 0x0016, 0x9984, 0xfc00,
-	0x01e8, 0x908c, 0xf800, 0x1168, 0x9982, 0x0400, 0x02b8, 0x9982,
-	0x0440, 0x0278, 0x9982, 0x0558, 0x0288, 0x9982, 0x0800, 0x1270,
-	0x0040, 0x9982, 0x0800, 0x0250, 0x2071, 0x188d, 0x7010, 0x9902,
-	0x1228, 0x9085, 0x0001, 0x001e, 0x00ee, 0x0005, 0x9006, 0x0cd8,
-	0x00e6, 0x2071, 0x1a24, 0x7007, 0x0000, 0x9006, 0x701e, 0x7022,
-	0x7002, 0x2071, 0x0000, 0x7010, 0x9085, 0x8044, 0x7012, 0x2071,
-	0x0080, 0x9006, 0x702b, 0x0060, 0x20a9, 0x0040, 0x7022, 0x1f04,
-	0x113e, 0x702b, 0x0060, 0x702b, 0x0020, 0x20a9, 0x0040, 0x7022,
-	0x1f04, 0x1147, 0x702b, 0x0020, 0x00ee, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x00e6, 0xa06f, 0x0000, 0x2071, 0x1a24, 0x701c, 0x9088,
-	0x1a2e, 0x280a, 0x8000, 0x9084, 0x003f, 0x701e, 0x7120, 0x9106,
-	0x090c, 0x0d85, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079, 0x0080,
-	0x00a9, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000,
-	0x00e6, 0x2071, 0x1a24, 0x7004, 0x9005, 0x1128, 0x00f6, 0x2079,
-	0x0080, 0x0021, 0x00fe, 0x00ee, 0x012e, 0x0005, 0x7004, 0x9086,
-	0x0000, 0x1110, 0x7007, 0x0006, 0x7000, 0x0002, 0x1190, 0x1313,
-	0x118e, 0x118e, 0x1307, 0x1307, 0x1307, 0x1307, 0x080c, 0x0d85,
-	0x701c, 0x7120, 0x9106, 0x1148, 0x792c, 0x9184, 0x0001, 0x1120,
-	0xd1fc, 0x1110, 0x7007, 0x0000, 0x0005, 0x0096, 0x9180, 0x1a2e,
-	0x2004, 0x700a, 0x2048, 0x8108, 0x918c, 0x003f, 0x7122, 0x782b,
-	0x0026, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898,
-	0x780e, 0xa878, 0x700e, 0xa870, 0x7016, 0xa874, 0x701a, 0xa868,
-	0x009e, 0xd084, 0x0120, 0x7007, 0x0001, 0x0029, 0x0005, 0x7007,
-	0x0002, 0x00b1, 0x0005, 0x0016, 0x0026, 0x710c, 0x2011, 0x0040,
-	0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e, 0x7212, 0x8203,
-	0x7812, 0x782b, 0x0020, 0x782b, 0x0041, 0x002e, 0x001e, 0x0005,
-	0x0016, 0x0026, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e0, 0x7018,
-	0x2098, 0x20e9, 0x0000, 0x20a1, 0x0088, 0x782b, 0x0026, 0x710c,
-	0x2011, 0x0040, 0x9182, 0x0040, 0x1210, 0x2110, 0x9006, 0x700e,
-	0x22a8, 0x4006, 0x8203, 0x7812, 0x782b, 0x0020, 0x3300, 0x701a,
-	0x782b, 0x0001, 0x015e, 0x014e, 0x013e, 0x002e, 0x001e, 0x0005,
-	0x2009, 0x1a24, 0x2104, 0xc095, 0x200a, 0x080c, 0x116d, 0x0005,
-	0x0016, 0x00e6, 0x2071, 0x1a24, 0x00f6, 0x2079, 0x0080, 0x792c,
-	0xd1bc, 0x190c, 0x0d7e, 0x782b, 0x0002, 0xd1fc, 0x0120, 0x918c,
-	0x0700, 0x7004, 0x0023, 0x00fe, 0x00ee, 0x001e, 0x0005, 0x117e,
-	0x1226, 0x125a, 0x1332, 0x0d85, 0x134d, 0x0d85, 0x918c, 0x0700,
-	0x1550, 0x0136, 0x0146, 0x0156, 0x7014, 0x20e8, 0x7018, 0x20a0,
-	0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040, 0x7010, 0x20a8,
-	0x4005, 0x3400, 0x701a, 0x015e, 0x014e, 0x013e, 0x700c, 0x9005,
-	0x0578, 0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11c3, 0x0005,
-	0x7008, 0x0096, 0x2048, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000,
-	0x080c, 0x117e, 0x0005, 0x7008, 0x0096, 0x2048, 0xa86f, 0x0200,
-	0x009e, 0x0ca0, 0x918c, 0x0700, 0x1150, 0x700c, 0x9005, 0x0180,
-	0x7800, 0x7802, 0x7804, 0x7806, 0x080c, 0x11d8, 0x0005, 0x7008,
-	0x0096, 0x2048, 0xa86f, 0x0200, 0x009e, 0x7007, 0x0000, 0x0080,
-	0x0096, 0x7008, 0x2048, 0x7800, 0xa88e, 0x7804, 0xa892, 0x7808,
-	0xa896, 0x780c, 0xa89a, 0xa86f, 0x0100, 0x009e, 0x7007, 0x0000,
-	0x0096, 0x00d6, 0x7008, 0x2048, 0x2001, 0x18b9, 0x2004, 0x9906,
-	0x1128, 0xa89c, 0x080f, 0x00de, 0x009e, 0x00a0, 0x00de, 0x009e,
-	0x0096, 0x00d6, 0x7008, 0x2048, 0x0081, 0x0150, 0xa89c, 0x0086,
-	0x2940, 0x080f, 0x008e, 0x00de, 0x009e, 0x080c, 0x116d, 0x0005,
-	0x00de, 0x009e, 0x080c, 0x116d, 0x0005, 0xa8a8, 0xd08c, 0x0005,
-	0x0096, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0xa06c, 0x908e, 0x0100,
-	0x0130, 0xa87b, 0x0030, 0xa883, 0x0000, 0xa897, 0x4002, 0x080c,
-	0x7006, 0xa09f, 0x0000, 0xa0a3, 0x0000, 0x2848, 0x080c, 0x108b,
-	0x009e, 0x0005, 0x00a6, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0xa06c,
-	0x908e, 0x0100, 0x0128, 0xa87b, 0x0001, 0xa883, 0x0000, 0x00c0,
-	0xa80c, 0x2050, 0xb004, 0x9005, 0x0198, 0xa80e, 0x2050, 0x8006,
-	0x8006, 0x8007, 0x908c, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002,
-	0xa076, 0xa172, 0xb000, 0xa07a, 0x2810, 0x080c, 0x114e, 0x00e8,
-	0xa97c, 0xa894, 0x0016, 0x0006, 0x080c, 0x7006, 0x000e, 0x001e,
-	0xd1fc, 0x1138, 0xd1f4, 0x0128, 0x00c6, 0x2060, 0x080c, 0xb16c,
-	0x00ce, 0x7008, 0x2048, 0xa89f, 0x0000, 0xa8a3, 0x0000, 0x080c,
-	0x108b, 0x7007, 0x0000, 0x080c, 0x116d, 0x00ae, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x782b, 0x1001, 0x7007, 0x0005, 0x7000, 0xc094,
-	0x7002, 0x012e, 0x0005, 0x0096, 0x2001, 0x192f, 0x204c, 0xa87c,
-	0x7812, 0xa88c, 0x7802, 0xa890, 0x7806, 0xa894, 0x780a, 0xa898,
-	0x780e, 0x782b, 0x0020, 0x0126, 0x2091, 0x8000, 0x782b, 0x0041,
-	0x7007, 0x0003, 0x7000, 0xc084, 0x7002, 0x2900, 0x700a, 0x012e,
-	0x009e, 0x0005, 0x20e1, 0x0000, 0x2099, 0x0088, 0x782b, 0x0040,
-	0x0096, 0x2001, 0x192f, 0x204c, 0xaa7c, 0x009e, 0x080c, 0x8f88,
-	0x2009, 0x188c, 0x2104, 0x9084, 0xfffc, 0x200a, 0x080c, 0x8de7,
-	0x7007, 0x0000, 0x080c, 0x117e, 0x0005, 0x7007, 0x0000, 0x080c,
-	0x117e, 0x0005, 0x0126, 0x2091, 0x2200, 0x2079, 0x0300, 0x2071,
-	0x1a6e, 0x7003, 0x0000, 0x78bf, 0x00f6, 0x0041, 0x7807, 0x0007,
-	0x7803, 0x0000, 0x7803, 0x0001, 0x012e, 0x0005, 0x00c6, 0x7803,
-	0x0000, 0x2001, 0x0165, 0x2003, 0x4198, 0x7808, 0xd09c, 0x0120,
-	0x7820, 0x080c, 0x13b6, 0x0cc8, 0x2001, 0x1a6f, 0x2003, 0x0000,
-	0x78ab, 0x0004, 0x78ac, 0xd0ac, 0x1de8, 0x78ab, 0x0002, 0x7807,
-	0x0007, 0x7827, 0x0030, 0x782b, 0x0400, 0x7827, 0x0031, 0x782b,
-	0x1a81, 0x78e3, 0xff00, 0x781f, 0xff00, 0x781b, 0xff00, 0x2001,
-	0x1a70, 0x2003, 0x0000, 0x2001, 0x0200, 0x2004, 0xd0dc, 0x0110,
-	0x781f, 0x0303, 0x2061, 0x1a81, 0x602f, 0x1ddc, 0x2001, 0x181a,
-	0x2004, 0x9082, 0x1ddc, 0x6032, 0x603b, 0x1ec1, 0x602b, 0x1ac1,
-	0x6007, 0x1aa1, 0x2061, 0x1aa1, 0x606f, 0x193d, 0x2001, 0x1928,
-	0x2004, 0x607a, 0x783f, 0x348e, 0x00ce, 0x0005, 0x9086, 0x000d,
-	0x11d0, 0x7808, 0xd09c, 0x01b8, 0x7820, 0x0026, 0x2010, 0x080c,
-	0xcf09, 0x0180, 0x2260, 0x6000, 0x9086, 0x0004, 0x1158, 0x0016,
-	0x6120, 0x9186, 0x0009, 0x0108, 0x0020, 0x2009, 0x004c, 0x080c,
-	0xb20a, 0x001e, 0x002e, 0x0005, 0x0126, 0x2091, 0x2200, 0x7908,
-	0x9184, 0x0070, 0x190c, 0x0d7e, 0xd19c, 0x05a0, 0x7820, 0x908c,
-	0xf000, 0x0540, 0x2060, 0x6020, 0x9086, 0x0003, 0x1550, 0x6000,
-	0x9086, 0x0004, 0x1530, 0x6114, 0x2148, 0xa876, 0xa87a, 0xa867,
-	0x0103, 0x080c, 0x6e27, 0x00b6, 0x6010, 0x2058, 0xba3c, 0x8211,
-	0x0208, 0xba3e, 0xb8d0, 0x9005, 0x190c, 0x68df, 0x00be, 0x6044,
-	0xd0fc, 0x190c, 0xad25, 0x080c, 0xb195, 0x7808, 0xd09c, 0x19b0,
-	0x012e, 0x0005, 0x908a, 0x0024, 0x1a0c, 0x0d85, 0x002b, 0x012e,
-	0x0005, 0x04b0, 0x012e, 0x0005, 0x1438, 0x145e, 0x148e, 0x1493,
-	0x1497, 0x149c, 0x14c4, 0x14c8, 0x14d6, 0x14da, 0x1438, 0x15a7,
-	0x15ab, 0x161d, 0x1624, 0x1438, 0x1625, 0x1626, 0x1631, 0x1638,
-	0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x1438, 0x149e,
-	0x1438, 0x1466, 0x148b, 0x1452, 0x1438, 0x1472, 0x143c, 0x143a,
-	0x080c, 0x0d85, 0x080c, 0x0d7e, 0x080c, 0x1643, 0x2009, 0x1a7d,
-	0x2104, 0x8000, 0x200a, 0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0005,
-	0x6044, 0xd0fc, 0x190c, 0xad25, 0x2009, 0x0055, 0x080c, 0xb20a,
-	0x012e, 0x0005, 0x080c, 0x1643, 0x2060, 0x6044, 0xd0fc, 0x190c,
-	0xad25, 0x2009, 0x0055, 0x080c, 0xb20a, 0x0005, 0x2009, 0x0048,
-	0x080c, 0x1643, 0x2060, 0x080c, 0xb20a, 0x0005, 0x2009, 0x0054,
-	0x080c, 0x1643, 0x2060, 0x6044, 0xd0fc, 0x190c, 0xad25, 0x080c,
-	0xb20a, 0x0005, 0x080c, 0x1643, 0x2060, 0x0056, 0x0066, 0x080c,
-	0x1643, 0x2028, 0x080c, 0x1643, 0x2030, 0x0036, 0x0046, 0x2021,
-	0x0000, 0x2418, 0x2009, 0x0056, 0x080c, 0xb20a, 0x004e, 0x003e,
-	0x006e, 0x005e, 0x0005, 0x080c, 0x1643, 0x0005, 0x7004, 0xc085,
-	0xc0b5, 0x7006, 0x0005, 0x7004, 0xc085, 0x7006, 0x0005, 0x080c,
-	0x1643, 0x080c, 0x1740, 0x0005, 0x080c, 0x0d85, 0x080c, 0x1643,
-	0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff, 0x009e, 0x2009,
-	0x0048, 0x080c, 0xb20a, 0x2001, 0x015d, 0x2003, 0x0000, 0x2009,
-	0x03e8, 0x8109, 0x0160, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8,
-	0x2001, 0x0218, 0x2004, 0xd0ec, 0x1110, 0x080c, 0x1648, 0x2001,
-	0x0307, 0x2003, 0x8000, 0x0005, 0x7004, 0xc095, 0x7006, 0x0005,
-	0x080c, 0x1643, 0x2060, 0x6014, 0x0096, 0x2048, 0xa83b, 0xffff,
-	0x009e, 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0x080c, 0x1643,
-	0x080c, 0x0d85, 0x080c, 0x1643, 0x080c, 0x1592, 0x7827, 0x0018,
-	0x79ac, 0xd1dc, 0x0904, 0x1543, 0x7827, 0x0015, 0x7828, 0x782b,
-	0x0000, 0x9065, 0x0140, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003,
-	0x0020, 0x0804, 0x1549, 0x7004, 0x9005, 0x01c8, 0x1188, 0x78ab,
-	0x0004, 0x7827, 0x0018, 0x782b, 0x0000, 0xd1bc, 0x090c, 0x0d85,
-	0x2001, 0x020d, 0x2003, 0x0050, 0x2003, 0x0020, 0x0804, 0x1577,
-	0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x15ab, 0x0005, 0x7827,
-	0x0018, 0xa001, 0x7828, 0x7827, 0x0011, 0xa001, 0x7928, 0x9106,
-	0x0110, 0x79ac, 0x08e0, 0x00e6, 0x2071, 0x0200, 0x702c, 0xd0c4,
-	0x0140, 0x00ee, 0x080c, 0x1b1e, 0x080c, 0x1366, 0x7803, 0x0001,
-	0x0005, 0x7037, 0x0001, 0xa001, 0x7150, 0x00ee, 0x918c, 0xff00,
-	0x9186, 0x0500, 0x0110, 0x79ac, 0x0810, 0x7004, 0xc09d, 0x7006,
-	0x78ab, 0x0004, 0x7803, 0x0001, 0x080c, 0x15ab, 0x2001, 0x020d,
-	0x2003, 0x0020, 0x0005, 0x7828, 0x782b, 0x0000, 0x9065, 0x090c,
-	0x0d85, 0x6014, 0x2048, 0x78ab, 0x0004, 0x918c, 0x0700, 0x01a8,
-	0x080c, 0x82b8, 0x080c, 0x1b1e, 0x080c, 0xcf1b, 0x0158, 0xa9ac,
-	0xa936, 0xa9b0, 0xa93a, 0xa83f, 0xffff, 0xa843, 0xffff, 0xa880,
-	0xc0bd, 0xa882, 0x080c, 0xcae9, 0x0005, 0x6020, 0x9086, 0x0009,
-	0x1128, 0x2009, 0x004c, 0x080c, 0xb20a, 0x0048, 0x6010, 0x00b6,
-	0x2058, 0xb800, 0x00be, 0xd0bc, 0x6024, 0x190c, 0xd31e, 0x2029,
-	0x00c8, 0x8529, 0x0128, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8,
-	0x7dbc, 0x080c, 0xeeb1, 0xd5a4, 0x1118, 0x080c, 0x1648, 0x0005,
-	0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0005, 0x781f, 0x0300, 0x7803,
-	0x0001, 0x0005, 0x0016, 0x0066, 0x0076, 0x00f6, 0x2079, 0x0300,
-	0x7908, 0x918c, 0x0007, 0x9186, 0x0003, 0x0120, 0x2001, 0x0016,
-	0x080c, 0x16b9, 0x00fe, 0x007e, 0x006e, 0x001e, 0x0005, 0x7004,
-	0xc09d, 0x7006, 0x0005, 0x7104, 0x9184, 0x0004, 0x190c, 0x0d85,
-	0xd184, 0x11b1, 0xd19c, 0x0180, 0xc19c, 0x7106, 0x0016, 0x080c,
-	0x1723, 0x001e, 0x0148, 0x2001, 0x020d, 0x2003, 0x0050, 0x2003,
-	0x0020, 0x080c, 0x1648, 0x0005, 0x81ff, 0x190c, 0x0d85, 0x0005,
-	0x2100, 0xc184, 0xc1b4, 0x7106, 0xd0b4, 0x0016, 0x00e6, 0x1904,
-	0x1612, 0x2071, 0x0200, 0x080c, 0x1710, 0x05e0, 0x080c, 0x1723,
-	0x05b0, 0x6014, 0x9005, 0x05b0, 0x0096, 0x2048, 0xa864, 0x009e,
-	0x9084, 0x00ff, 0x908e, 0x0029, 0x0160, 0x908e, 0x0048, 0x1550,
-	0x601c, 0xd084, 0x11e0, 0x00f6, 0x2c78, 0x080c, 0x17ad, 0x00fe,
-	0x00b0, 0x00f6, 0x2c78, 0x080c, 0x1942, 0x00fe, 0x2009, 0x01f4,
-	0x8109, 0x0168, 0x2001, 0x0201, 0x2004, 0x9005, 0x0dc8, 0x2001,
-	0x0218, 0x2004, 0xd0ec, 0x1118, 0x080c, 0x1648, 0x0040, 0x2001,
-	0x020d, 0x2003, 0x0020, 0x080c, 0x1366, 0x7803, 0x0001, 0x00ee,
-	0x001e, 0x0005, 0x080c, 0x1723, 0x0dd0, 0x2001, 0x020d, 0x2003,
-	0x0050, 0x2003, 0x0020, 0x0461, 0x0c90, 0x0429, 0x2060, 0x2009,
-	0x0053, 0x080c, 0xb20a, 0x0005, 0x0005, 0x0005, 0x00e1, 0x2008,
-	0x00d1, 0x0006, 0x7004, 0xc09d, 0x7006, 0x000e, 0x080c, 0x92d5,
-	0x0005, 0x0089, 0x9005, 0x0118, 0x080c, 0x8ed9, 0x0cd0, 0x0005,
-	0x2001, 0x0036, 0x2009, 0x1820, 0x210c, 0x2011, 0x181f, 0x2214,
-	0x080c, 0x16b9, 0x0005, 0x7808, 0xd09c, 0x0de8, 0x7820, 0x0005,
-	0x080c, 0x1592, 0x00d6, 0x2069, 0x0200, 0x2009, 0x01f4, 0x8109,
-	0x0510, 0x6804, 0x9005, 0x0dd8, 0x2001, 0x015d, 0x2003, 0x0000,
-	0x79bc, 0xd1a4, 0x1528, 0x79b8, 0x918c, 0x0fff, 0x0180, 0x9182,
-	0x0841, 0x1268, 0x9188, 0x0007, 0x918c, 0x0ff8, 0x810c, 0x810c,
-	0x810c, 0x080c, 0x16ab, 0x6827, 0x0001, 0x8109, 0x1dd0, 0x04d9,
-	0x6827, 0x0002, 0x04c1, 0x6804, 0x9005, 0x1130, 0x682c, 0xd0e4,
-	0x1500, 0x6804, 0x9005, 0x0de8, 0x79b8, 0xd1ec, 0x1130, 0x08c0,
-	0x080c, 0x82b8, 0x080c, 0x1b1e, 0x0090, 0x7827, 0x0015, 0x782b,
-	0x0000, 0x7827, 0x0018, 0x782b, 0x0000, 0x2001, 0x020d, 0x2003,
-	0x0020, 0x2001, 0x0307, 0x2003, 0x0300, 0x7803, 0x0001, 0x00de,
-	0x0005, 0x682c, 0x9084, 0x5400, 0x9086, 0x5400, 0x0d30, 0x7827,
-	0x0015, 0x782b, 0x0000, 0x7803, 0x0001, 0x6800, 0x9085, 0x1800,
-	0x6802, 0x00de, 0x0005, 0x6824, 0x9084, 0x0003, 0x1de0, 0x0005,
-	0x2001, 0x0030, 0x2c08, 0x621c, 0x0021, 0x7830, 0x9086, 0x0041,
-	0x0005, 0x00f6, 0x00e6, 0x2079, 0x0300, 0x0006, 0x2071, 0x1a6e,
-	0x7008, 0x9005, 0x1110, 0x78e3, 0x0c0c, 0x8000, 0x700a, 0x0026,
-	0x2011, 0x0006, 0x7808, 0xd09c, 0x0150, 0x0016, 0x0026, 0x00c6,
-	0x080c, 0x13d4, 0x00ce, 0x002e, 0x001e, 0x8211, 0x1d98, 0x002e,
-	0x000e, 0x0006, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x00b9,
-	0x1178, 0x2071, 0x1a6e, 0x7008, 0x9005, 0x0130, 0x8001, 0x0a0c,
-	0x0d85, 0x700a, 0x78e3, 0x0c00, 0x000e, 0x00ee, 0x00fe, 0x0005,
-	0x000e, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d85, 0x2009,
-	0xff00, 0x8109, 0x0120, 0x7818, 0xd0bc, 0x1dd8, 0x0005, 0x9085,
-	0x0001, 0x0005, 0x7832, 0x7936, 0x7a3a, 0x781b, 0x8080, 0x0c79,
-	0x1108, 0x0005, 0x792c, 0x3900, 0x8000, 0x2004, 0x080c, 0x0d85,
-	0x7037, 0x0001, 0x7150, 0x7037, 0x0002, 0x7050, 0x2060, 0xd1bc,
-	0x1110, 0x7054, 0x2060, 0x918c, 0xff00, 0x9186, 0x0500, 0x0110,
-	0x9085, 0x0001, 0x0005, 0x0006, 0x0046, 0x00e6, 0x2071, 0x0200,
-	0x7037, 0x0002, 0x7058, 0x9084, 0xff00, 0x8007, 0x9086, 0x00bc,
-	0x1158, 0x2021, 0x1a7e, 0x2404, 0x8000, 0x0208, 0x2022, 0x080c,
-	0x82b8, 0x080c, 0x1b1e, 0x9006, 0x00ee, 0x004e, 0x000e, 0x0005,
-	0x0c11, 0x1108, 0x0005, 0x00e6, 0x0016, 0x2071, 0x0200, 0x0841,
-	0x6124, 0xd1dc, 0x01f8, 0x701c, 0xd08c, 0x0904, 0x17a2, 0x7017,
-	0x0000, 0x2001, 0x0264, 0x2004, 0xd0bc, 0x0904, 0x17a2, 0x2001,
-	0x0268, 0x00c6, 0x2064, 0x6104, 0x6038, 0x00ce, 0x918e, 0x0039,
-	0x1904, 0x17a2, 0x9c06, 0x15f0, 0x0126, 0x2091, 0x2600, 0x080c,
-	0x8210, 0x012e, 0x7358, 0x745c, 0x6014, 0x905d, 0x0598, 0x2b48,
-	0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x190c, 0xd2f9,
-	0xab42, 0xac3e, 0x2001, 0x1869, 0x2004, 0xd0b4, 0x1170, 0x601c,
-	0xd0e4, 0x1158, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc,
-	0x1120, 0xa83b, 0x7fff, 0xa837, 0xffff, 0x080c, 0x1ee1, 0x1190,
-	0x080c, 0x199f, 0x2a00, 0xa816, 0x0130, 0x2800, 0xa80e, 0x2c05,
-	0xa80a, 0x2c00, 0xa812, 0x7037, 0x0020, 0x781f, 0x0300, 0x001e,
-	0x00ee, 0x0005, 0x7037, 0x0050, 0x7037, 0x0020, 0x001e, 0x00ee,
-	0x080c, 0x1648, 0x0005, 0x080c, 0x0d85, 0x2001, 0x180d, 0x2004,
-	0xd08c, 0x190c, 0x6ccc, 0x2cf0, 0x0126, 0x2091, 0x2200, 0x0016,
-	0x00c6, 0x3e60, 0x6014, 0x2048, 0x2940, 0x903e, 0x2730, 0xa864,
-	0x2068, 0xa81a, 0x9d84, 0x000f, 0x9088, 0x1ec1, 0x2165, 0x0002,
-	0x17df, 0x184d, 0x17df, 0x17df, 0x17e3, 0x182e, 0x17df, 0x1803,
-	0x17d8, 0x1844, 0x17df, 0x17df, 0x17e8, 0x193a, 0x1817, 0x180d,
-	0xa964, 0x918c, 0x00ff, 0x918e, 0x0048, 0x0904, 0x1844, 0x9085,
-	0x0001, 0x0804, 0x1930, 0xa87c, 0xd0ac, 0x0dc8, 0x0804, 0x1854,
-	0xa87c, 0xd0ac, 0x0da0, 0x0804, 0x18bf, 0xa898, 0x901d, 0x1108,
-	0xab9c, 0x9016, 0xaab2, 0xaa3e, 0xaa42, 0x3e00, 0x9080, 0x0008,
-	0x2004, 0x9080, 0x9536, 0x2005, 0x9005, 0x090c, 0x0d85, 0x2004,
-	0xa8ae, 0x0804, 0x1918, 0xa87c, 0xd0bc, 0x09c8, 0xa890, 0xa842,
-	0xa88c, 0xa83e, 0xa888, 0x0804, 0x1854, 0xa87c, 0xd0bc, 0x0978,
-	0xa890, 0xa842, 0xa88c, 0xa83e, 0xa888, 0x0804, 0x18bf, 0xa87c,
-	0xd0bc, 0x0928, 0xa890, 0xa842, 0xa88c, 0xa83e, 0xa804, 0x9045,
-	0x090c, 0x0d85, 0xa164, 0xa91a, 0x91ec, 0x000f, 0x9d80, 0x1ec1,
-	0x2065, 0xa888, 0xd19c, 0x1904, 0x18bf, 0x0430, 0xa87c, 0xd0ac,
-	0x0904, 0x17df, 0xa804, 0x9045, 0x090c, 0x0d85, 0xa164, 0xa91a,
-	0x91ec, 0x000f, 0x9d80, 0x1ec1, 0x2065, 0x9006, 0xa842, 0xa83e,
-	0xd19c, 0x1904, 0x18bf, 0x0080, 0xa87c, 0xd0ac, 0x0904, 0x17df,
-	0x9006, 0xa842, 0xa83e, 0x0804, 0x18bf, 0xa87c, 0xd0ac, 0x0904,
-	0x17df, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0036, 0x1a0c,
-	0x0d85, 0x9082, 0x001b, 0x0002, 0x1877, 0x1877, 0x1879, 0x1877,
-	0x1877, 0x1877, 0x1883, 0x1877, 0x1877, 0x1877, 0x188d, 0x1877,
-	0x1877, 0x1877, 0x1897, 0x1877, 0x1877, 0x1877, 0x18a1, 0x1877,
-	0x1877, 0x1877, 0x18ab, 0x1877, 0x1877, 0x1877, 0x18b5, 0x080c,
-	0x0d85, 0xa574, 0xa478, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa37c,
-	0xa280, 0x0804, 0x1918, 0xa584, 0xa488, 0x9d86, 0x0024, 0x0904,
-	0x17ed, 0xa38c, 0xa290, 0x0804, 0x1918, 0xa594, 0xa498, 0x9d86,
-	0x0024, 0x0904, 0x17ed, 0xa39c, 0xa2a0, 0x0804, 0x1918, 0xa5a4,
-	0xa4a8, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa3ac, 0xa2b0, 0x0804,
-	0x1918, 0xa5b4, 0xa4b8, 0x9d86, 0x0024, 0x0904, 0x17ed, 0xa3bc,
-	0xa2c0, 0x0804, 0x1918, 0xa5c4, 0xa4c8, 0x9d86, 0x0024, 0x0904,
-	0x17ed, 0xa3cc, 0xa2d0, 0x0804, 0x1918, 0xa5d4, 0xa4d8, 0x9d86,
-	0x0024, 0x0904, 0x17ed, 0xa3dc, 0xa2e0, 0x0804, 0x1918, 0x2c05,
-	0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x18e2,
-	0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18ed, 0x18e0, 0x18e0,
-	0x18e0, 0x18e0, 0x18e0, 0x18f8, 0x18e0, 0x18e0, 0x18e0, 0x18e0,
-	0x18e0, 0x1903, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x18e0, 0x190e,
-	0x080c, 0x0d85, 0xa56c, 0xa470, 0xa774, 0xa678, 0x9d86, 0x002c,
-	0x0904, 0x17ed, 0xa37c, 0xa280, 0x0458, 0xa584, 0xa488, 0xa78c,
-	0xa690, 0x9d86, 0x002c, 0x0904, 0x17ed, 0xa394, 0xa298, 0x0400,
-	0xa59c, 0xa4a0, 0xa7a4, 0xa6a8, 0x9d86, 0x002c, 0x0904, 0x17ed,
-	0xa3ac, 0xa2b0, 0x00a8, 0xa5b4, 0xa4b8, 0xa7bc, 0xa6c0, 0x9d86,
-	0x002c, 0x0904, 0x17ed, 0xa3c4, 0xa2c8, 0x0050, 0xa5cc, 0xa4d0,
-	0xa7d4, 0xa6d8, 0x9d86, 0x002c, 0x0904, 0x17ed, 0xa3dc, 0xa2e0,
-	0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8c60,
-	0x2c1d, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x8109, 0xa916, 0x1160,
-	0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006,
-	0x00ce, 0x001e, 0x012e, 0x0005, 0x2800, 0xa80e, 0xab0a, 0x2c00,
-	0xa812, 0x0c70, 0x0804, 0x17df, 0x2001, 0x180d, 0x2004, 0xd08c,
-	0x190c, 0x6ccc, 0x2ff0, 0x0126, 0x2091, 0x2200, 0x0016, 0x00c6,
-	0x3e60, 0x6014, 0x2048, 0x2940, 0xa80e, 0x2061, 0x1ebc, 0xa813,
-	0x1ebc, 0x2c05, 0xa80a, 0xa964, 0xa91a, 0xa87c, 0xd0ac, 0x090c,
-	0x0d85, 0x9006, 0xa842, 0xa83e, 0x2c05, 0x908a, 0x0034, 0x1a0c,
-	0x0d85, 0xadcc, 0xacd0, 0xafd4, 0xaed8, 0xabdc, 0xaae0, 0xab2e,
-	0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa8ac, 0xaab0, 0xa836,
-	0xaa3a, 0xa988, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0008, 0x1120,
-	0x8109, 0xa916, 0x0128, 0x0080, 0x918a, 0x0002, 0xa916, 0x1160,
-	0x3e60, 0x601c, 0xc085, 0x601e, 0xa87c, 0xc0dd, 0xa87e, 0x9006,
-	0x00ce, 0x001e, 0x012e, 0x0005, 0xa804, 0x9045, 0x090c, 0x0d85,
-	0xa80e, 0xa064, 0xa81a, 0x9084, 0x000f, 0x9080, 0x1ec1, 0x2015,
-	0x82ff, 0x090c, 0x0d85, 0xaa12, 0x2205, 0xa80a, 0x0c08, 0x903e,
-	0x2730, 0xa880, 0xd0fc, 0x1190, 0x2d00, 0x0002, 0x1a94, 0x19f6,
-	0x19f6, 0x1a94, 0x1a94, 0x1a8e, 0x1a94, 0x19f6, 0x1a45, 0x1a45,
-	0x1a45, 0x1a94, 0x1a94, 0x1a94, 0x1a8b, 0x1a45, 0xc0fc, 0xa882,
-	0xab2c, 0xaa30, 0xad1c, 0xac20, 0xdd9c, 0x0904, 0x1a96, 0x2c05,
-	0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x19e2,
-	0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e6, 0x19e0, 0x19e0,
-	0x19e0, 0x19e0, 0x19e0, 0x19ea, 0x19e0, 0x19e0, 0x19e0, 0x19e0,
-	0x19e0, 0x19ee, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19e0, 0x19f2,
-	0x080c, 0x0d85, 0xa774, 0xa678, 0x0804, 0x1a96, 0xa78c, 0xa690,
-	0x0804, 0x1a96, 0xa7a4, 0xa6a8, 0x0804, 0x1a96, 0xa7bc, 0xa6c0,
-	0x0804, 0x1a96, 0xa7d4, 0xa6d8, 0x0804, 0x1a96, 0x2c05, 0x908a,
-	0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1a19, 0x1a19,
-	0x1a1b, 0x1a19, 0x1a19, 0x1a19, 0x1a21, 0x1a19, 0x1a19, 0x1a19,
-	0x1a27, 0x1a19, 0x1a19, 0x1a19, 0x1a2d, 0x1a19, 0x1a19, 0x1a19,
-	0x1a33, 0x1a19, 0x1a19, 0x1a19, 0x1a39, 0x1a19, 0x1a19, 0x1a19,
-	0x1a3f, 0x080c, 0x0d85, 0xa574, 0xa478, 0xa37c, 0xa280, 0x0804,
-	0x1a96, 0xa584, 0xa488, 0xa38c, 0xa290, 0x0804, 0x1a96, 0xa594,
-	0xa498, 0xa39c, 0xa2a0, 0x0804, 0x1a96, 0xa5a4, 0xa4a8, 0xa3ac,
-	0xa2b0, 0x0804, 0x1a96, 0xa5b4, 0xa4b8, 0xa3bc, 0xa2c0, 0x0804,
-	0x1a96, 0xa5c4, 0xa4c8, 0xa3cc, 0xa2d0, 0x0804, 0x1a96, 0xa5d4,
-	0xa4d8, 0xa3dc, 0xa2e0, 0x0804, 0x1a96, 0x2c05, 0x908a, 0x0034,
-	0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1a68, 0x1a66, 0x1a66,
-	0x1a66, 0x1a66, 0x1a66, 0x1a6f, 0x1a66, 0x1a66, 0x1a66, 0x1a66,
-	0x1a66, 0x1a76, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a7d,
-	0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a66, 0x1a84, 0x080c, 0x0d85,
-	0xa56c, 0xa470, 0xa774, 0xa678, 0xa37c, 0xa280, 0x0438, 0xa584,
-	0xa488, 0xa78c, 0xa690, 0xa394, 0xa298, 0x0400, 0xa59c, 0xa4a0,
-	0xa7a4, 0xa6a8, 0xa3ac, 0xa2b0, 0x00c8, 0xa5b4, 0xa4b8, 0xa7bc,
-	0xa6c0, 0xa3c4, 0xa2c8, 0x0090, 0xa5cc, 0xa4d0, 0xa7d4, 0xa6d8,
-	0xa3dc, 0xa2e0, 0x0058, 0x9d86, 0x000e, 0x1130, 0x080c, 0x1e97,
-	0x1904, 0x199f, 0x900e, 0x0050, 0x080c, 0x0d85, 0xab2e, 0xaa32,
-	0xad1e, 0xac22, 0xaf26, 0xae2a, 0x080c, 0x1e97, 0x0005, 0x6014,
-	0x2048, 0x6118, 0x81ff, 0x0148, 0x810c, 0x810c, 0x810c, 0x81ff,
-	0x1118, 0xa887, 0x0001, 0x0008, 0xa986, 0x601b, 0x0002, 0xa874,
-	0x9084, 0x00ff, 0x9084, 0x0008, 0x0150, 0x00e9, 0x6000, 0x9086,
-	0x0004, 0x1120, 0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0xa974,
-	0xd1dc, 0x1108, 0x0005, 0xa934, 0xa88c, 0x9106, 0x1158, 0xa938,
-	0xa890, 0x9106, 0x1138, 0x601c, 0xc084, 0x601e, 0x2009, 0x0048,
-	0x0804, 0xb20a, 0x0005, 0x0126, 0x00c6, 0x2091, 0x2200, 0x00ce,
-	0x7908, 0x918c, 0x0007, 0x9186, 0x0000, 0x05b0, 0x9186, 0x0003,
-	0x0598, 0x6020, 0x6023, 0x0000, 0x0006, 0x2031, 0x0008, 0x00c6,
-	0x781f, 0x0808, 0x7808, 0xd09c, 0x0120, 0x080c, 0x13d4, 0x8631,
-	0x1db8, 0x00ce, 0x781f, 0x0800, 0x2031, 0x0168, 0x00c6, 0x7808,
-	0xd09c, 0x190c, 0x13d4, 0x00ce, 0x2001, 0x0038, 0x080c, 0x1bae,
-	0x7930, 0x9186, 0x0040, 0x0160, 0x9186, 0x0042, 0x190c, 0x0d85,
-	0x2001, 0x001e, 0x8001, 0x1df0, 0x8631, 0x1d40, 0x080c, 0x1bbd,
-	0x000e, 0x6022, 0x012e, 0x0005, 0x080c, 0x1baa, 0x7827, 0x0015,
-	0x7828, 0x9c06, 0x1db8, 0x782b, 0x0000, 0x0ca0, 0x00f6, 0x2079,
-	0x0300, 0x7803, 0x0000, 0x78ab, 0x0004, 0x2001, 0xf000, 0x8001,
-	0x090c, 0x0d85, 0x7aac, 0xd2ac, 0x1dd0, 0x00fe, 0x080c, 0x779e,
-	0x1188, 0x2001, 0x0138, 0x2003, 0x0000, 0x2001, 0x0160, 0x2003,
-	0x0000, 0x2011, 0x012c, 0xa001, 0xa001, 0x8211, 0x1de0, 0x0059,
-	0x0804, 0x7840, 0x0479, 0x0039, 0x2001, 0x0160, 0x2502, 0x2001,
-	0x0138, 0x2202, 0x0005, 0x00e6, 0x2071, 0x0200, 0x080c, 0x2a8b,
-	0x2009, 0x003c, 0x080c, 0x2220, 0x2001, 0x015d, 0x2003, 0x0000,
-	0x7000, 0x9084, 0x003c, 0x1de0, 0x080c, 0x8899, 0x70a0, 0x70a2,
-	0x7098, 0x709a, 0x709c, 0x709e, 0x2001, 0x020d, 0x2003, 0x0020,
-	0x00f6, 0x2079, 0x0300, 0x080c, 0x1366, 0x7803, 0x0001, 0x00fe,
-	0x00ee, 0x0005, 0x2001, 0x0138, 0x2014, 0x2003, 0x0000, 0x2001,
-	0x0160, 0x202c, 0x2003, 0x0000, 0x080c, 0x779e, 0x1108, 0x0005,
-	0x2021, 0x0260, 0x2001, 0x0141, 0x201c, 0xd3dc, 0x1168, 0x2001,
-	0x0109, 0x201c, 0x939c, 0x0048, 0x1160, 0x2001, 0x0111, 0x201c,
-	0x83ff, 0x1110, 0x8421, 0x1d70, 0x2001, 0x015d, 0x2003, 0x0000,
-	0x0005, 0x0046, 0x2021, 0x0019, 0x2003, 0x0048, 0xa001, 0xa001,
-	0x201c, 0x939c, 0x0048, 0x0120, 0x8421, 0x1db0, 0x004e, 0x0c60,
-	0x004e, 0x0c40, 0x601c, 0xc084, 0x601e, 0x0005, 0x2c08, 0x621c,
-	0x080c, 0x16b9, 0x7930, 0x0005, 0x2c08, 0x621c, 0x080c, 0x1702,
-	0x7930, 0x0005, 0x8001, 0x1df0, 0x0005, 0x2031, 0x0064, 0x781c,
-	0x9084, 0x0007, 0x0170, 0x2001, 0x0038, 0x0c41, 0x9186, 0x0040,
-	0x0904, 0x1c1b, 0x2001, 0x001e, 0x0c69, 0x8631, 0x1d80, 0x080c,
-	0x0d85, 0x781f, 0x0202, 0x2001, 0x015d, 0x2003, 0x0000, 0x2001,
-	0x0dac, 0x0c01, 0x781c, 0xd084, 0x0110, 0x0861, 0x04e0, 0x2001,
-	0x0030, 0x0891, 0x9186, 0x0040, 0x0568, 0x781c, 0xd084, 0x1da8,
-	0x781f, 0x0101, 0x2001, 0x0014, 0x0869, 0x2001, 0x0037, 0x0821,
-	0x9186, 0x0040, 0x0140, 0x2001, 0x0030, 0x080c, 0x1bb4, 0x9186,
-	0x0040, 0x190c, 0x0d85, 0x00d6, 0x2069, 0x0200, 0x692c, 0xd1f4,
-	0x1170, 0xd1c4, 0x0160, 0xd19c, 0x0130, 0x6800, 0x9085, 0x1800,
-	0x6802, 0x00de, 0x0080, 0x6908, 0x9184, 0x0007, 0x1db0, 0x00de,
-	0x781f, 0x0100, 0x791c, 0x9184, 0x0007, 0x090c, 0x0d85, 0xa001,
-	0xa001, 0x781f, 0x0200, 0x0005, 0x0126, 0x2091, 0x2400, 0x2079,
-	0x0380, 0x2001, 0x19e8, 0x2070, 0x012e, 0x0005, 0x2cf0, 0x0126,
-	0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa964, 0xa91a, 0x918c,
-	0x00ff, 0x9184, 0x000f, 0x0002, 0x1c50, 0x1c50, 0x1c50, 0x1c52,
-	0x1c50, 0x1c50, 0x1c50, 0x1c50, 0x1c44, 0x1c5a, 0x1c50, 0x1c56,
-	0x1c50, 0x1c50, 0x1c50, 0x1c50, 0x9086, 0x0008, 0x1148, 0xa87c,
-	0xd0b4, 0x0904, 0x1dca, 0x2011, 0x1ebc, 0x2205, 0xab88, 0x00a8,
-	0x080c, 0x0d85, 0x9186, 0x0013, 0x0128, 0x0cd0, 0x9186, 0x001b,
-	0x0108, 0x0cb0, 0xa87c, 0xd0b4, 0x0904, 0x1dca, 0x9184, 0x000f,
-	0x9080, 0x1ec1, 0x2015, 0x2205, 0xab88, 0x2908, 0xa80a, 0xa90e,
-	0xaa12, 0xab16, 0x9006, 0xa842, 0xa83e, 0x012e, 0x0005, 0x2cf0,
-	0x0126, 0x2091, 0x2400, 0x3e60, 0x6014, 0x2048, 0xa88c, 0xa990,
-	0xaaac, 0xabb0, 0xaa36, 0xab3a, 0xa83e, 0xa942, 0xa846, 0xa94a,
-	0xa964, 0x918c, 0x00ff, 0x9186, 0x001e, 0x0198, 0x2940, 0xa064,
-	0xa81a, 0x90ec, 0x000f, 0x9d80, 0x1ec1, 0x2065, 0x2c05, 0x2808,
-	0x2c10, 0xab88, 0xa80a, 0xa90e, 0xaa12, 0xab16, 0x012e, 0x3e60,
-	0x0005, 0xa804, 0x2040, 0x0c58, 0x2cf0, 0x0126, 0x2091, 0x2400,
-	0x3e60, 0x6014, 0x2048, 0xa97c, 0x2950, 0xd1dc, 0x1904, 0x1d94,
-	0xc1dd, 0xa97e, 0x9006, 0xa842, 0xa83e, 0xa988, 0x8109, 0xa916,
-	0xa964, 0xa91a, 0x9184, 0x000f, 0x9088, 0x1ec1, 0x2145, 0x0002,
-	0x1cc8, 0x1cd6, 0x1cc8, 0x1cc8, 0x1cc8, 0x1cca, 0x1cc8, 0x1cc8,
-	0x1d2b, 0x1d2b, 0x1cc8, 0x1cc8, 0x1cc8, 0x1d29, 0x1cc8, 0x1cc8,
-	0x080c, 0x0d85, 0xa804, 0x2050, 0xb164, 0xa91a, 0x9184, 0x000f,
-	0x9080, 0x1ec1, 0x2045, 0xd19c, 0x1904, 0x1d2b, 0x9036, 0x2638,
-	0x2805, 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002,
-	0x1cfb, 0x1cfb, 0x1cfd, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d03, 0x1cfb,
-	0x1cfb, 0x1cfb, 0x1d09, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d0f, 0x1cfb,
-	0x1cfb, 0x1cfb, 0x1d15, 0x1cfb, 0x1cfb, 0x1cfb, 0x1d1b, 0x1cfb,
-	0x1cfb, 0x1cfb, 0x1d21, 0x080c, 0x0d85, 0xb574, 0xb478, 0xb37c,
-	0xb280, 0x0804, 0x1d70, 0xb584, 0xb488, 0xb38c, 0xb290, 0x0804,
-	0x1d70, 0xb594, 0xb498, 0xb39c, 0xb2a0, 0x0804, 0x1d70, 0xb5a4,
-	0xb4a8, 0xb3ac, 0xb2b0, 0x0804, 0x1d70, 0xb5b4, 0xb4b8, 0xb3bc,
-	0xb2c0, 0x0804, 0x1d70, 0xb5c4, 0xb4c8, 0xb3cc, 0xb2d0, 0x0804,
-	0x1d70, 0xb5d4, 0xb4d8, 0xb3dc, 0xb2e0, 0x0804, 0x1d70, 0x0804,
-	0x1d70, 0x080c, 0x0d85, 0x2805, 0x908a, 0x0034, 0x1a0c, 0x0d85,
-	0x9082, 0x001b, 0x0002, 0x1d4e, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c,
-	0x1d4c, 0x1d55, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d5c,
-	0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d4c, 0x1d63, 0x1d4c, 0x1d4c,
-	0x1d4c, 0x1d4c, 0x1d4c, 0x1d6a, 0x080c, 0x0d85, 0xb56c, 0xb470,
-	0xb774, 0xb678, 0xb37c, 0xb280, 0x00d8, 0xb584, 0xb488, 0xb78c,
-	0xb690, 0xb394, 0xb298, 0x00a0, 0xb59c, 0xb4a0, 0xb7a4, 0xb6a8,
-	0xb3ac, 0xb2b0, 0x0068, 0xb5b4, 0xb4b8, 0xb7bc, 0xb6c0, 0xb3c4,
-	0xb2c8, 0x0030, 0xb5cc, 0xb4d0, 0xb7d4, 0xb6d8, 0xb3dc, 0xb2e0,
-	0xab2e, 0xaa32, 0xad1e, 0xac22, 0xaf26, 0xae2a, 0xa988, 0x8109,
-	0xa916, 0x1118, 0x9006, 0x012e, 0x0005, 0x8840, 0x2805, 0x9005,
-	0x1168, 0xb004, 0x9005, 0x090c, 0x0d85, 0x2050, 0xb164, 0xa91a,
-	0x9184, 0x000f, 0x9080, 0x1ec1, 0x2045, 0x2805, 0x2810, 0x2a08,
-	0xa80a, 0xa90e, 0xaa12, 0x0c30, 0x3e60, 0x6344, 0xd3fc, 0x190c,
-	0x0d85, 0xa93c, 0xaa40, 0xa844, 0x9106, 0x1118, 0xa848, 0x9206,
-	0x0508, 0x2958, 0xab48, 0xac44, 0x2940, 0x080c, 0x1ee1, 0x1998,
-	0x2850, 0x2c40, 0xab14, 0xa880, 0xd0fc, 0x1140, 0xa810, 0x2005,
-	0xa80a, 0x2a00, 0xa80e, 0x2009, 0x8015, 0x0070, 0x00c6, 0x3e60,
-	0x6044, 0xc0a4, 0x9085, 0x8005, 0x6046, 0x00ce, 0x8319, 0xab16,
-	0x1904, 0x1d7d, 0x2009, 0x8005, 0x3e60, 0x6044, 0x9105, 0x6046,
-	0x0804, 0x1d7a, 0x080c, 0x0d85, 0x00f6, 0x00e6, 0x0096, 0x00c6,
-	0x0026, 0x704c, 0x9c06, 0x190c, 0x0d85, 0x2079, 0x0090, 0x2001,
-	0x0105, 0x2003, 0x0010, 0x782b, 0x0004, 0x7057, 0x0000, 0x6014,
-	0x2048, 0x080c, 0xcf1b, 0x0118, 0xa880, 0xc0bd, 0xa882, 0x6020,
-	0x9086, 0x0006, 0x1170, 0x2061, 0x0100, 0x62c8, 0x2001, 0x00fa,
-	0x8001, 0x1df0, 0x60c8, 0x9206, 0x1dc0, 0x60c4, 0xa89a, 0x60c8,
-	0xa896, 0x704c, 0x2060, 0x00c6, 0x080c, 0xcae9, 0x080c, 0xacfc,
-	0x00ce, 0x704c, 0x9c06, 0x1150, 0x2009, 0x0040, 0x080c, 0x2220,
-	0x080c, 0xa7a1, 0x2011, 0x0000, 0x080c, 0xa635, 0x002e, 0x00ce,
-	0x009e, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0090, 0x781c,
-	0x0006, 0x7818, 0x0006, 0x2079, 0x0100, 0x7a14, 0x9284, 0x1984,
-	0x9085, 0x0012, 0x7816, 0x2019, 0x1000, 0x8319, 0x090c, 0x0d85,
-	0x7820, 0xd0bc, 0x1dd0, 0x79c8, 0x000e, 0x9102, 0x001e, 0x0006,
-	0x0016, 0x79c4, 0x000e, 0x9103, 0x78c6, 0x000e, 0x78ca, 0x9284,
-	0x1984, 0x9085, 0x0012, 0x7816, 0x2079, 0x0090, 0x782b, 0x0008,
-	0x7057, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x19e8,
-	0x7054, 0x9086, 0x0000, 0x0904, 0x1e92, 0x2079, 0x0090, 0x2009,
-	0x0207, 0x210c, 0xd194, 0x01b8, 0x2009, 0x020c, 0x210c, 0x9184,
-	0x0003, 0x0188, 0x080c, 0xeefa, 0x2001, 0x0133, 0x2004, 0x9005,
-	0x090c, 0x0d85, 0x0016, 0x2009, 0x0040, 0x080c, 0x2220, 0x001e,
-	0x2001, 0x020c, 0x2102, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203,
-	0x210c, 0x9106, 0x1120, 0x2009, 0x0040, 0x080c, 0x2220, 0x782c,
-	0xd0fc, 0x09a8, 0x080c, 0xad18, 0x782c, 0xd0fc, 0x1de8, 0x080c,
-	0xacfc, 0x7054, 0x9086, 0x0000, 0x1950, 0x782b, 0x0004, 0x782c,
-	0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2220, 0x782b, 0x0002,
-	0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x080c, 0x0d85, 0x8c60,
-	0x2c05, 0x9005, 0x0110, 0x8a51, 0x0005, 0xa004, 0x9005, 0x0168,
-	0xa85a, 0x2040, 0xa064, 0x9084, 0x000f, 0x9080, 0x1ec1, 0x2065,
-	0x8cff, 0x090c, 0x0d85, 0x8a51, 0x0005, 0x2050, 0x0005, 0x0000,
-	0x001d, 0x0021, 0x0025, 0x0029, 0x002d, 0x0031, 0x0035, 0x0000,
-	0x001b, 0x0021, 0x0027, 0x002d, 0x0033, 0x0000, 0x0000, 0x0023,
-	0x0000, 0x0000, 0x1eb4, 0x1eb0, 0x1eb4, 0x1eb4, 0x1ebe, 0x0000,
-	0x1eb4, 0x1ebb, 0x1ebb, 0x1eb8, 0x1ebb, 0x1ebb, 0x0000, 0x1ebe,
-	0x1ebb, 0x0000, 0x1eb6, 0x1eb6, 0x0000, 0x1eb6, 0x1ebe, 0x0000,
-	0x1eb6, 0x1ebc, 0x1ebc, 0x1ebc, 0x0000, 0x1ebc, 0x0000, 0x1ebe,
-	0x1ebc, 0x00c6, 0x00d6, 0x0086, 0xab42, 0xac3e, 0xa888, 0x9055,
-	0x0904, 0x20c0, 0x2940, 0xa064, 0x90ec, 0x000f, 0x9084, 0x00ff,
-	0x9086, 0x0008, 0x1118, 0x2061, 0x1ebc, 0x00d0, 0x9de0, 0x1ec1,
-	0x9d86, 0x0007, 0x0130, 0x9d86, 0x000e, 0x0118, 0x9d86, 0x000f,
-	0x1120, 0xa08c, 0x9422, 0xa090, 0x931b, 0x2c05, 0x9065, 0x1140,
-	0x0310, 0x0804, 0x20c0, 0xa004, 0x9045, 0x0904, 0x20c0, 0x08d8,
-	0x2c05, 0x9005, 0x0904, 0x1fa8, 0xdd9c, 0x1904, 0x1f64, 0x908a,
-	0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x1f39, 0x1f39,
-	0x1f3b, 0x1f39, 0x1f39, 0x1f39, 0x1f41, 0x1f39, 0x1f39, 0x1f39,
-	0x1f47, 0x1f39, 0x1f39, 0x1f39, 0x1f4d, 0x1f39, 0x1f39, 0x1f39,
-	0x1f53, 0x1f39, 0x1f39, 0x1f39, 0x1f59, 0x1f39, 0x1f39, 0x1f39,
-	0x1f5f, 0x080c, 0x0d85, 0xa07c, 0x9422, 0xa080, 0x931b, 0x0804,
-	0x1f9e, 0xa08c, 0x9422, 0xa090, 0x931b, 0x0804, 0x1f9e, 0xa09c,
-	0x9422, 0xa0a0, 0x931b, 0x0804, 0x1f9e, 0xa0ac, 0x9422, 0xa0b0,
-	0x931b, 0x0804, 0x1f9e, 0xa0bc, 0x9422, 0xa0c0, 0x931b, 0x0804,
-	0x1f9e, 0xa0cc, 0x9422, 0xa0d0, 0x931b, 0x0804, 0x1f9e, 0xa0dc,
-	0x9422, 0xa0e0, 0x931b, 0x04d0, 0x908a, 0x0034, 0x1a0c, 0x0d85,
-	0x9082, 0x001b, 0x0002, 0x1f86, 0x1f84, 0x1f84, 0x1f84, 0x1f84,
-	0x1f84, 0x1f8b, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f90,
-	0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f84, 0x1f95, 0x1f84, 0x1f84,
-	0x1f84, 0x1f84, 0x1f84, 0x1f9a, 0x080c, 0x0d85, 0xa07c, 0x9422,
-	0xa080, 0x931b, 0x0098, 0xa094, 0x9422, 0xa098, 0x931b, 0x0070,
-	0xa0ac, 0x9422, 0xa0b0, 0x931b, 0x0048, 0xa0c4, 0x9422, 0xa0c8,
-	0x931b, 0x0020, 0xa0dc, 0x9422, 0xa0e0, 0x931b, 0x0630, 0x2300,
-	0x9405, 0x0160, 0x8a51, 0x0904, 0x20c0, 0x8c60, 0x0804, 0x1f10,
-	0xa004, 0x9045, 0x0904, 0x20c0, 0x0804, 0x1eeb, 0x8a51, 0x0904,
-	0x20c0, 0x8c60, 0x2c05, 0x9005, 0x1158, 0xa004, 0x9045, 0x0904,
-	0x20c0, 0xa064, 0x90ec, 0x000f, 0x9de0, 0x1ec1, 0x2c05, 0x2060,
-	0xa880, 0xc0fc, 0xa882, 0x0804, 0x20b5, 0x2c05, 0x8422, 0x8420,
-	0x831a, 0x9399, 0x0000, 0xac2e, 0xab32, 0xdd9c, 0x1904, 0x2052,
-	0x9082, 0x001b, 0x0002, 0x1fee, 0x1fee, 0x1ff0, 0x1fee, 0x1fee,
-	0x1fee, 0x1ffe, 0x1fee, 0x1fee, 0x1fee, 0x200c, 0x1fee, 0x1fee,
-	0x1fee, 0x201a, 0x1fee, 0x1fee, 0x1fee, 0x2028, 0x1fee, 0x1fee,
-	0x1fee, 0x2036, 0x1fee, 0x1fee, 0x1fee, 0x2044, 0x080c, 0x0d85,
-	0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d85,
-	0xa074, 0x9420, 0xa078, 0x9319, 0x0804, 0x20b0, 0xa18c, 0x2400,
-	0x9122, 0xa190, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa084, 0x9420,
-	0xa088, 0x9319, 0x0804, 0x20b0, 0xa19c, 0x2400, 0x9122, 0xa1a0,
-	0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa094, 0x9420, 0xa098, 0x9319,
-	0x0804, 0x20b0, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b,
-	0x0a0c, 0x0d85, 0xa0a4, 0x9420, 0xa0a8, 0x9319, 0x0804, 0x20b0,
-	0xa1bc, 0x2400, 0x9122, 0xa1c0, 0x2300, 0x911b, 0x0a0c, 0x0d85,
-	0xa0b4, 0x9420, 0xa0b8, 0x9319, 0x0804, 0x20b0, 0xa1cc, 0x2400,
-	0x9122, 0xa1d0, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0c4, 0x9420,
-	0xa0c8, 0x9319, 0x0804, 0x20b0, 0xa1dc, 0x2400, 0x9122, 0xa1e0,
-	0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0d4, 0x9420, 0xa0d8, 0x9319,
-	0x0804, 0x20b0, 0x9082, 0x001b, 0x0002, 0x2070, 0x206e, 0x206e,
-	0x206e, 0x206e, 0x206e, 0x207d, 0x206e, 0x206e, 0x206e, 0x206e,
-	0x206e, 0x208a, 0x206e, 0x206e, 0x206e, 0x206e, 0x206e, 0x2097,
-	0x206e, 0x206e, 0x206e, 0x206e, 0x206e, 0x20a4, 0x080c, 0x0d85,
-	0xa17c, 0x2400, 0x9122, 0xa180, 0x2300, 0x911b, 0x0a0c, 0x0d85,
-	0xa06c, 0x9420, 0xa070, 0x9319, 0x0498, 0xa194, 0x2400, 0x9122,
-	0xa198, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa084, 0x9420, 0xa088,
-	0x9319, 0x0430, 0xa1ac, 0x2400, 0x9122, 0xa1b0, 0x2300, 0x911b,
-	0x0a0c, 0x0d85, 0xa09c, 0x9420, 0xa0a0, 0x9319, 0x00c8, 0xa1c4,
-	0x2400, 0x9122, 0xa1c8, 0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0b4,
-	0x9420, 0xa0b8, 0x9319, 0x0060, 0xa1dc, 0x2400, 0x9122, 0xa1e0,
-	0x2300, 0x911b, 0x0a0c, 0x0d85, 0xa0cc, 0x9420, 0xa0d0, 0x9319,
-	0xac1e, 0xab22, 0xa880, 0xc0fd, 0xa882, 0x2800, 0xa85a, 0x2c00,
-	0xa812, 0x2a00, 0xa816, 0x000e, 0x000e, 0x000e, 0x9006, 0x0028,
-	0x008e, 0x00de, 0x00ce, 0x9085, 0x0001, 0x0005, 0x00c6, 0x610c,
-	0x0016, 0x9026, 0x2410, 0x6004, 0x9420, 0x9291, 0x0000, 0x2c04,
-	0x9210, 0x9ce0, 0x0002, 0x918a, 0x0002, 0x1da8, 0x9284, 0x000f,
-	0x9405, 0x001e, 0x00ce, 0x0005, 0x7803, 0x0003, 0x780f, 0x0000,
-	0x6004, 0x7812, 0x2c04, 0x7816, 0x9ce0, 0x0002, 0x918a, 0x0002,
-	0x1db8, 0x0005, 0x2001, 0x0005, 0x2004, 0xd0bc, 0x190c, 0x0d7e,
-	0xd094, 0x0110, 0x080c, 0x1208, 0x0005, 0x0126, 0x2091, 0x2600,
-	0x2079, 0x0200, 0x2071, 0x0260, 0x2069, 0x1800, 0x7817, 0x0000,
-	0x789b, 0x0814, 0x78a3, 0x0406, 0x789f, 0x0410, 0x2009, 0x013b,
-	0x200b, 0x0400, 0x781b, 0x0002, 0x783b, 0x001f, 0x7837, 0x0020,
-	0x7803, 0x1600, 0x012e, 0x0005, 0x2091, 0x2600, 0x781c, 0xd0a4,
-	0x190c, 0x221d, 0x7900, 0xd1dc, 0x1118, 0x9084, 0x0006, 0x001a,
-	0x9084, 0x000e, 0x0002, 0x213b, 0x2133, 0x8210, 0x2133, 0x2135,
-	0x2135, 0x2135, 0x2135, 0x81f6, 0x2133, 0x2137, 0x2133, 0x2135,
-	0x2133, 0x2135, 0x2133, 0x080c, 0x0d85, 0x0031, 0x0020, 0x080c,
-	0x81f6, 0x080c, 0x8210, 0x0005, 0x0006, 0x0016, 0x0026, 0x080c,
-	0xeefa, 0x7930, 0x9184, 0x0003, 0x0510, 0x080c, 0xacfc, 0x2001,
-	0x19fb, 0x2004, 0x9005, 0x01a0, 0x2001, 0x0133, 0x2004, 0x9005,
-	0x090c, 0x0d85, 0x00c6, 0x2001, 0x19fb, 0x2064, 0x080c, 0xad18,
-	0x080c, 0xcae9, 0x2009, 0x0040, 0x080c, 0x2220, 0x00ce, 0x0408,
-	0x2009, 0x0040, 0x080c, 0x2220, 0x080c, 0xad18, 0x00d0, 0x9184,
-	0x0014, 0x01a0, 0x6a00, 0x9286, 0x0003, 0x0160, 0x080c, 0x779e,
-	0x1138, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, 0x76cd, 0x0010,
-	0x080c, 0x6058, 0x080c, 0x82ae, 0x0041, 0x0018, 0x9184, 0x9540,
-	0x1dc8, 0x002e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x0036, 0x0046,
-	0x0056, 0x2071, 0x1a6e, 0x080c, 0x1b1e, 0x005e, 0x004e, 0x003e,
-	0x00ee, 0x0005, 0x0126, 0x2091, 0x2e00, 0x2071, 0x1800, 0x7128,
-	0x2001, 0x196f, 0x2102, 0x2001, 0x1977, 0x2102, 0x2001, 0x013b,
-	0x2102, 0x2079, 0x0200, 0x2001, 0x0201, 0x789e, 0x78a3, 0x0200,
-	0x9198, 0x0007, 0x831c, 0x831c, 0x831c, 0x9398, 0x0005, 0x2320,
-	0x9182, 0x0204, 0x1230, 0x2011, 0x0008, 0x8423, 0x8423, 0x8423,
-	0x0488, 0x9182, 0x024c, 0x1240, 0x2011, 0x0007, 0x8403, 0x8003,
-	0x9400, 0x9400, 0x9420, 0x0430, 0x9182, 0x02bc, 0x1238, 0x2011,
-	0x0006, 0x8403, 0x8003, 0x9400, 0x9420, 0x00e0, 0x9182, 0x034c,
-	0x1230, 0x2011, 0x0005, 0x8403, 0x8003, 0x9420, 0x0098, 0x9182,
-	0x042c, 0x1228, 0x2011, 0x0004, 0x8423, 0x8423, 0x0058, 0x9182,
-	0x059c, 0x1228, 0x2011, 0x0003, 0x8403, 0x9420, 0x0018, 0x2011,
-	0x0002, 0x8423, 0x9482, 0x0228, 0x8002, 0x8020, 0x8301, 0x9402,
-	0x0110, 0x0208, 0x8321, 0x8217, 0x8203, 0x9405, 0x789a, 0x012e,
-	0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6814, 0x9084, 0xffc0,
-	0x910d, 0x6916, 0x00de, 0x000e, 0x0005, 0x00d6, 0x2069, 0x0200,
-	0x9005, 0x6810, 0x0110, 0xc0a5, 0x0008, 0xc0a4, 0x6812, 0x00de,
-	0x0005, 0x0006, 0x00d6, 0x2069, 0x0200, 0x6810, 0x9084, 0xfff8,
-	0x910d, 0x6912, 0x00de, 0x000e, 0x0005, 0x7938, 0x080c, 0x0d7e,
-	0x00f6, 0x2079, 0x0200, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001,
-	0xa001, 0xa001, 0x7902, 0xa001, 0xa001, 0xa001, 0xa001, 0xa001,
-	0xa001, 0x00fe, 0x0005, 0x0126, 0x2091, 0x2800, 0x2061, 0x0100,
-	0x2071, 0x1800, 0x2009, 0x0000, 0x080c, 0x2a85, 0x080c, 0x299b,
-	0x2001, 0x199d, 0x2003, 0x0700, 0x2001, 0x199e, 0x2003, 0x0700,
-	0x080c, 0x2af6, 0x9006, 0x080c, 0x29ca, 0x9006, 0x080c, 0x29ad,
-	0x20a9, 0x0012, 0x1d04, 0x2252, 0x2091, 0x6000, 0x1f04, 0x2252,
-	0x602f, 0x0100, 0x602f, 0x0000, 0x6050, 0x9085, 0x0400, 0x9084,
-	0xdfff, 0x6052, 0x6224, 0x080c, 0x2ad3, 0x080c, 0x26c5, 0x2009,
-	0x00ef, 0x6132, 0x6136, 0x080c, 0x26d5, 0x60e7, 0x0000, 0x61ea,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1110, 0x2001,
-	0x0008, 0x60e2, 0x604b, 0xf7f7, 0x6043, 0x0000, 0x602f, 0x0080,
-	0x602f, 0x0000, 0x6007, 0x349f, 0x00c6, 0x2061, 0x0140, 0x608b,
-	0x000b, 0x608f, 0x10b8, 0x6093, 0x0000, 0x6097, 0x0198, 0x00ce,
-	0x6004, 0x9085, 0x8000, 0x6006, 0x60bb, 0x0000, 0x20a9, 0x0018,
-	0x60bf, 0x0000, 0x1f04, 0x2298, 0x60bb, 0x0000, 0x60bf, 0x0108,
-	0x60bf, 0x0012, 0x60bf, 0x0405, 0x60bf, 0x0014, 0x60bf, 0x0320,
-	0x60bf, 0x0018, 0x601b, 0x00f0, 0x601f, 0x001e, 0x600f, 0x006b,
-	0x602b, 0x402c, 0x012e, 0x0005, 0x00f6, 0x2079, 0x0140, 0x78c3,
-	0x0080, 0x78c3, 0x0083, 0x78c3, 0x0000, 0x00fe, 0x0005, 0x2001,
-	0x1835, 0x2003, 0x0000, 0x2001, 0x1834, 0x2003, 0x0001, 0x0005,
-	0x0126, 0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x6124, 0x6028,
-	0x910c, 0x0066, 0x2031, 0x1837, 0x2634, 0x96b4, 0x0028, 0x006e,
-	0x1138, 0x6020, 0xd1bc, 0x0120, 0xd0bc, 0x1168, 0xd0b4, 0x1198,
-	0x9184, 0x5e2c, 0x1118, 0x9184, 0x0007, 0x00aa, 0x9195, 0x0004,
-	0x9284, 0x0007, 0x0082, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1a4,
-	0x001e, 0x0d70, 0x0c98, 0x0016, 0x2001, 0x0387, 0x200c, 0xd1b4,
-	0x001e, 0x0d30, 0x0c58, 0x2306, 0x2303, 0x2303, 0x2303, 0x2305,
-	0x2303, 0x2303, 0x2303, 0x080c, 0x0d85, 0x0029, 0x002e, 0x001e,
-	0x000e, 0x012e, 0x0005, 0x00a6, 0x6124, 0x6028, 0xd09c, 0x0118,
-	0xd19c, 0x1904, 0x258b, 0xd1f4, 0x190c, 0x0d7e, 0x080c, 0x779e,
-	0x0904, 0x2363, 0x080c, 0xd645, 0x1120, 0x7000, 0x9086, 0x0003,
-	0x0580, 0x6024, 0x9084, 0x1800, 0x0560, 0x080c, 0x77c1, 0x0118,
-	0x080c, 0x77af, 0x1530, 0x2011, 0x0020, 0x080c, 0x2ad3, 0x6043,
-	0x0000, 0x080c, 0xd645, 0x0168, 0x080c, 0x77c1, 0x1150, 0x2001,
-	0x19a8, 0x2003, 0x0001, 0x6027, 0x1800, 0x080c, 0x7612, 0x0804,
-	0x258e, 0x70a4, 0x9005, 0x1150, 0x70a7, 0x0001, 0x00d6, 0x2069,
-	0x0140, 0x080c, 0x77f2, 0x00de, 0x1904, 0x258e, 0x080c, 0x7ac0,
-	0x0428, 0x080c, 0x77c1, 0x1590, 0x6024, 0x9084, 0x1800, 0x1108,
-	0x0468, 0x080c, 0x7ac0, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c,
-	0x76cd, 0x0804, 0x258b, 0xd1ac, 0x1508, 0x6024, 0xd0dc, 0x1170,
-	0xd0e4, 0x1178, 0xd0d4, 0x1190, 0xd0cc, 0x0130, 0x7098, 0x9086,
-	0x0029, 0x1110, 0x080c, 0x7990, 0x0804, 0x258b, 0x080c, 0x7abb,
-	0x0048, 0x2001, 0x197d, 0x2003, 0x0002, 0x0020, 0x080c, 0x78e4,
-	0x0804, 0x258b, 0x080c, 0x7a3a, 0x0804, 0x258b, 0x6220, 0xd1bc,
-	0x0138, 0xd2bc, 0x1904, 0x25f6, 0xd2b4, 0x1904, 0x2608, 0x0000,
-	0xd1ac, 0x0904, 0x2498, 0x0036, 0x6328, 0xc3bc, 0x632a, 0x003e,
-	0x080c, 0x779e, 0x11d0, 0x2011, 0x0020, 0x080c, 0x2ad3, 0x0006,
-	0x0026, 0x0036, 0x080c, 0x77b8, 0x1158, 0x080c, 0x7ab6, 0x080c,
-	0x619d, 0x080c, 0x76cd, 0x003e, 0x002e, 0x000e, 0x00ae, 0x0005,
-	0x003e, 0x002e, 0x000e, 0x080c, 0x7772, 0x0016, 0x0046, 0x00c6,
-	0x644c, 0x9486, 0xf0f0, 0x1138, 0x2061, 0x0100, 0x644a, 0x6043,
-	0x0090, 0x6043, 0x0010, 0x74da, 0x948c, 0xff00, 0x7038, 0xd084,
-	0x0190, 0x080c, 0xd645, 0x1118, 0x9186, 0xf800, 0x1160, 0x7048,
-	0xd084, 0x1148, 0xc085, 0x704a, 0x0036, 0x2418, 0x2011, 0x8016,
-	0x080c, 0x4ca1, 0x003e, 0x080c, 0xd63e, 0x1904, 0x246d, 0x9196,
-	0xff00, 0x05a8, 0x7060, 0x9084, 0x00ff, 0x810f, 0x81ff, 0x0110,
-	0x9116, 0x0568, 0x7130, 0xd184, 0x1550, 0x080c, 0x3482, 0x0128,
-	0xc18d, 0x7132, 0x080c, 0x6c09, 0x1510, 0x6240, 0x9294, 0x0010,
-	0x0130, 0x6248, 0x9294, 0xff00, 0x9296, 0xff00, 0x01c0, 0x7030,
-	0xd08c, 0x0904, 0x246d, 0x7038, 0xd08c, 0x1140, 0x2001, 0x180c,
-	0x200c, 0xd1ac, 0x1904, 0x246d, 0xc1ad, 0x2102, 0x0036, 0x73d8,
-	0x2011, 0x8013, 0x080c, 0x4ca1, 0x003e, 0x0804, 0x246d, 0x7038,
-	0xd08c, 0x1140, 0x2001, 0x180c, 0x200c, 0xd1ac, 0x1904, 0x246d,
-	0xc1ad, 0x2102, 0x0036, 0x73d8, 0x2011, 0x8013, 0x080c, 0x4ca1,
-	0x003e, 0x7130, 0xc185, 0x7132, 0x2011, 0x1848, 0x220c, 0xd1a4,
-	0x01f0, 0x0016, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8c44,
-	0x2019, 0x000e, 0x00c6, 0x2061, 0x0000, 0x080c, 0xe9f9, 0x00ce,
-	0x9484, 0x00ff, 0x9080, 0x348e, 0x200d, 0x918c, 0xff00, 0x810f,
-	0x2120, 0x9006, 0x2009, 0x000e, 0x080c, 0xea8d, 0x001e, 0x0016,
-	0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x32da, 0x001e, 0x00a8,
-	0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x67b4, 0x1140,
-	0x7030, 0xd084, 0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x61b7,
-	0x8108, 0x1f04, 0x245d, 0x00be, 0x015e, 0x00ce, 0x004e, 0x080c,
-	0xacfc, 0x080c, 0xafd2, 0x080c, 0xb09b, 0x080c, 0xad18, 0x60e3,
-	0x0000, 0x001e, 0x2001, 0x1800, 0x2014, 0x9296, 0x0004, 0x1170,
-	0xd19c, 0x11b0, 0x2011, 0x180c, 0x2214, 0xd29c, 0x1120, 0x6204,
-	0x9295, 0x0002, 0x6206, 0x6228, 0xc29d, 0x622a, 0x2003, 0x0001,
-	0x2001, 0x1826, 0x2003, 0x0000, 0x2011, 0x0020, 0x080c, 0x2ad3,
-	0xd194, 0x0904, 0x258b, 0x0016, 0x080c, 0xacfc, 0x6220, 0xd2b4,
-	0x0904, 0x2526, 0x080c, 0x8a4b, 0x080c, 0xa2a0, 0x2011, 0x0004,
-	0x080c, 0x2ad3, 0x00f6, 0x2019, 0x19f4, 0x2304, 0x907d, 0x0904,
-	0x24f3, 0x7804, 0x9086, 0x0032, 0x15f0, 0x00d6, 0x00c6, 0x00e6,
-	0x0096, 0x2069, 0x0140, 0x782c, 0x685e, 0x7808, 0x685a, 0x6043,
-	0x0002, 0x2001, 0x0003, 0x8001, 0x1df0, 0x6043, 0x0000, 0x2001,
-	0x003c, 0x8001, 0x1df0, 0x080c, 0x2aa9, 0x2001, 0x001e, 0x8001,
-	0x0240, 0x20a9, 0x0009, 0x080c, 0x2a60, 0x6904, 0xd1dc, 0x1140,
-	0x0cb0, 0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99,
-	0x080c, 0x99ed, 0x080c, 0xad18, 0x7814, 0x2048, 0xa867, 0x0103,
-	0x2f60, 0x080c, 0xb16c, 0x009e, 0x00ee, 0x00ce, 0x00de, 0x00fe,
-	0x001e, 0x00ae, 0x0005, 0x00fe, 0x00d6, 0x2069, 0x0140, 0x6804,
-	0x9084, 0x4000, 0x0110, 0x080c, 0x2aa9, 0x00de, 0x00c6, 0x2061,
-	0x19e8, 0x6034, 0x080c, 0xd645, 0x0120, 0x909a, 0x0003, 0x1258,
-	0x0018, 0x909a, 0x00c8, 0x1238, 0x8000, 0x6036, 0x00ce, 0x080c,
-	0xa278, 0x0804, 0x2588, 0x2061, 0x0100, 0x62c0, 0x080c, 0xac2d,
-	0x2019, 0x19f4, 0x2304, 0x9065, 0x0130, 0x6003, 0x0001, 0x2009,
-	0x0027, 0x080c, 0xb20a, 0x00ce, 0x0804, 0x2588, 0xd2bc, 0x0904,
-	0x256b, 0x080c, 0x8a58, 0x2011, 0x0004, 0x080c, 0x2ad3, 0x00d6,
-	0x2069, 0x0140, 0x6804, 0x9084, 0x4000, 0x0110, 0x080c, 0x2aa9,
-	0x00de, 0x00c6, 0x2061, 0x19e8, 0x6050, 0x080c, 0xd645, 0x0120,
-	0x909a, 0x0003, 0x1668, 0x0018, 0x909a, 0x00c8, 0x1648, 0x8000,
-	0x6052, 0x604c, 0x00ce, 0x9005, 0x05d8, 0x2009, 0x07d0, 0x080c,
-	0x8a50, 0x9080, 0x0008, 0x2004, 0x9086, 0x0006, 0x1138, 0x2009,
-	0x1984, 0x2011, 0x0012, 0x080c, 0x2ae2, 0x0450, 0x9080, 0x0008,
-	0x2004, 0x9086, 0x0009, 0x0d98, 0x2009, 0x1984, 0x2011, 0x0016,
-	0x080c, 0x2ae2, 0x00e8, 0x2011, 0x0004, 0x080c, 0x2ad3, 0x00c0,
-	0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x2019, 0x19fb,
-	0x2304, 0x9065, 0x0160, 0x2009, 0x004f, 0x6020, 0x9086, 0x0009,
-	0x1110, 0x2009, 0x004f, 0x6003, 0x0003, 0x080c, 0xb20a, 0x00ce,
-	0x080c, 0xad18, 0x001e, 0xd19c, 0x0904, 0x25ef, 0x7038, 0xd0ac,
-	0x1558, 0x0016, 0x0156, 0x2011, 0x0008, 0x080c, 0x2ad3, 0x080c,
-	0x2af6, 0x080c, 0x2b29, 0x6050, 0xc0e5, 0x6052, 0x20a9, 0x0367,
-	0x0f04, 0x25ba, 0x1d04, 0x25a2, 0x080c, 0x8a7f, 0x6020, 0xd09c,
-	0x1db8, 0x00f6, 0x2079, 0x0100, 0x080c, 0x2a0c, 0x00fe, 0x1d80,
-	0x6050, 0xc0e4, 0x6052, 0x2011, 0x0008, 0x080c, 0x2ad3, 0x015e,
-	0x001e, 0x04a8, 0x015e, 0x001e, 0x0016, 0x6028, 0xc09c, 0x602a,
-	0x080c, 0xacfc, 0x080c, 0xafd2, 0x080c, 0xb09b, 0x080c, 0xad18,
-	0x60e3, 0x0000, 0x080c, 0xeed9, 0x080c, 0xeef4, 0x080c, 0x5844,
-	0xd0fc, 0x1138, 0x080c, 0xd63e, 0x1120, 0x9085, 0x0001, 0x080c,
-	0x77e2, 0x9006, 0x080c, 0x2a99, 0x2009, 0x0002, 0x080c, 0x2a85,
-	0x00e6, 0x2071, 0x1800, 0x7003, 0x0004, 0x080c, 0x0ed3, 0x00ee,
-	0x2011, 0x0008, 0x080c, 0x2ad3, 0x080c, 0x0bcf, 0x001e, 0x918c,
-	0xffd0, 0x2110, 0x080c, 0x2ad3, 0x00ae, 0x0005, 0x0016, 0x2001,
-	0x0387, 0x200c, 0xd1a4, 0x001e, 0x0904, 0x2390, 0x0016, 0x2009,
-	0x2602, 0x00c0, 0x2001, 0x0387, 0x2003, 0x1000, 0x001e, 0x0c38,
-	0x0016, 0x2001, 0x0387, 0x200c, 0xd1b4, 0x001e, 0x0904, 0x2390,
-	0x0016, 0x2009, 0x2614, 0x0030, 0x2001, 0x0387, 0x2003, 0x4000,
-	0x001e, 0x08a8, 0x6028, 0xc0bc, 0x602a, 0x2001, 0x0156, 0x2003,
-	0xbc91, 0x8000, 0x2003, 0xffff, 0x6043, 0x0001, 0x080c, 0x2a7f,
-	0x2011, 0x0080, 0x080c, 0x2ad3, 0x6017, 0x0000, 0x6043, 0x0000,
-	0x0817, 0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x00f6, 0x0126,
-	0x2091, 0x8000, 0x2071, 0x1800, 0x71d0, 0x70d2, 0x9116, 0x0904,
-	0x2684, 0x81ff, 0x01a0, 0x2009, 0x0000, 0x080c, 0x2a85, 0x2011,
-	0x8011, 0x2019, 0x010e, 0x231c, 0x939e, 0x0007, 0x1118, 0x2019,
-	0x0001, 0x0010, 0x2019, 0x0000, 0x080c, 0x4ca1, 0x0468, 0x2001,
-	0x19a9, 0x200c, 0x81ff, 0x1140, 0x2001, 0x0109, 0x2004, 0xd0b4,
-	0x0118, 0x2019, 0x0003, 0x0008, 0x2118, 0x2011, 0x8012, 0x080c,
-	0x4ca1, 0x080c, 0x0ed3, 0x080c, 0x5844, 0xd0fc, 0x11a8, 0x080c,
-	0xd63e, 0x1190, 0x00c6, 0x080c, 0x2720, 0x080c, 0xacfc, 0x080c,
-	0xa4f1, 0x080c, 0xad18, 0x2061, 0x0100, 0x2019, 0x0028, 0x2009,
-	0x0002, 0x080c, 0x32da, 0x00ce, 0x012e, 0x00fe, 0x00ee, 0x003e,
-	0x002e, 0x001e, 0x000e, 0x0005, 0x2028, 0x918c, 0x00ff, 0x2130,
-	0x9094, 0xff00, 0x11f0, 0x2011, 0x1837, 0x2214, 0xd2ac, 0x11c8,
-	0x81ff, 0x01e8, 0x2011, 0x181f, 0x2204, 0x9106, 0x1190, 0x2011,
-	0x1820, 0x2214, 0x9294, 0xff00, 0x9584, 0xff00, 0x9206, 0x1148,
-	0x2011, 0x1820, 0x2214, 0x9294, 0x00ff, 0x9584, 0x00ff, 0x9206,
-	0x1120, 0x2500, 0x080c, 0x8521, 0x0048, 0x9584, 0x00ff, 0x9080,
-	0x348e, 0x200d, 0x918c, 0xff00, 0x810f, 0x9006, 0x0005, 0x9080,
-	0x348e, 0x200d, 0x918c, 0x00ff, 0x0005, 0x00d6, 0x2069, 0x0140,
-	0x2001, 0x1818, 0x2003, 0x00ef, 0x20a9, 0x0010, 0x9006, 0x6852,
-	0x6856, 0x1f04, 0x26d0, 0x00de, 0x0005, 0x0006, 0x00d6, 0x0026,
-	0x2069, 0x0140, 0x2001, 0x1818, 0x2102, 0x8114, 0x8214, 0x8214,
-	0x8214, 0x20a9, 0x0010, 0x6853, 0x0000, 0x9006, 0x82ff, 0x1128,
-	0x9184, 0x000f, 0x9080, 0xef08, 0x2005, 0x6856, 0x8211, 0x1f04,
-	0x26e5, 0x002e, 0x00de, 0x000e, 0x0005, 0x00c6, 0x2061, 0x1800,
-	0x6030, 0x0110, 0xc09d, 0x0008, 0xc09c, 0x6032, 0x00ce, 0x0005,
-	0x0156, 0x00d6, 0x0026, 0x0016, 0x0006, 0x2069, 0x0140, 0x6980,
-	0x9116, 0x0180, 0x9112, 0x1230, 0x8212, 0x8210, 0x22a8, 0x2001,
-	0x0402, 0x0018, 0x22a8, 0x2001, 0x0404, 0x680e, 0x1f04, 0x2715,
-	0x680f, 0x0000, 0x000e, 0x001e, 0x002e, 0x00de, 0x015e, 0x0005,
-	0x080c, 0x5840, 0xd0c4, 0x0150, 0xd0a4, 0x0140, 0x9006, 0x0046,
-	0x2020, 0x2009, 0x002e, 0x080c, 0xea8d, 0x004e, 0x0005, 0x00f6,
-	0x0016, 0x0026, 0x2079, 0x0140, 0x78c4, 0xd0dc, 0x0904, 0x278c,
-	0x080c, 0x29fc, 0x0660, 0x9084, 0x0700, 0x908e, 0x0600, 0x1120,
-	0x2011, 0x4000, 0x900e, 0x0458, 0x908e, 0x0500, 0x1120, 0x2011,
-	0x8000, 0x900e, 0x0420, 0x908e, 0x0400, 0x1120, 0x9016, 0x2009,
-	0x0001, 0x00e8, 0x908e, 0x0300, 0x1120, 0x9016, 0x2009, 0x0002,
-	0x00b0, 0x908e, 0x0200, 0x1120, 0x9016, 0x2009, 0x0004, 0x0078,
-	0x908e, 0x0100, 0x1548, 0x9016, 0x2009, 0x0008, 0x0040, 0x9084,
-	0x0700, 0x908e, 0x0300, 0x1500, 0x2011, 0x0030, 0x0058, 0x2300,
-	0x9080, 0x0020, 0x2018, 0x080c, 0x955b, 0x928c, 0xff00, 0x0110,
-	0x2011, 0x00ff, 0x2200, 0x8007, 0x9085, 0x004c, 0x78c2, 0x2009,
-	0x0138, 0x220a, 0x080c, 0x779e, 0x1118, 0x2009, 0x196d, 0x220a,
-	0x002e, 0x001e, 0x00fe, 0x0005, 0x78c3, 0x0000, 0x0cc8, 0x0126,
-	0x2091, 0x2800, 0x0006, 0x0016, 0x0026, 0x2001, 0x0170, 0x200c,
-	0x8000, 0x2014, 0x9184, 0x0003, 0x0110, 0x080c, 0x0d7e, 0x002e,
-	0x001e, 0x000e, 0x012e, 0x0005, 0x2001, 0x180d, 0x2004, 0xd08c,
-	0x0118, 0x2009, 0x0002, 0x0005, 0x2001, 0x0171, 0x2004, 0xd0dc,
-	0x0168, 0x2001, 0x0170, 0x200c, 0x918c, 0x00ff, 0x918e, 0x004c,
-	0x1128, 0x200c, 0x918c, 0xff00, 0x810f, 0x0005, 0x900e, 0x2001,
-	0x0227, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x2001,
-	0x0226, 0x2004, 0x8007, 0x9084, 0x00ff, 0x8004, 0x9108, 0x0005,
-	0x0018, 0x000c, 0x0018, 0x0020, 0x1000, 0x0800, 0x1000, 0x1800,
-	0x0156, 0x0006, 0x0016, 0x0026, 0x00e6, 0x2001, 0x1990, 0x2004,
-	0x908a, 0x0007, 0x1a0c, 0x0d85, 0x0033, 0x00ee, 0x002e, 0x001e,
-	0x000e, 0x015e, 0x0005, 0x27f2, 0x2810, 0x2834, 0x2836, 0x285f,
-	0x2861, 0x2863, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, 0x2a4a,
-	0x2001, 0x1992, 0x2003, 0x0000, 0x7828, 0x9084, 0xe1d7, 0x782a,
-	0x9006, 0x20a9, 0x0009, 0x080c, 0x2a18, 0x2001, 0x1990, 0x2003,
-	0x0006, 0x2009, 0x001e, 0x2011, 0x2864, 0x080c, 0x8a5d, 0x0005,
-	0x2009, 0x1995, 0x200b, 0x0000, 0x2001, 0x199a, 0x2003, 0x0036,
-	0x2001, 0x1999, 0x2003, 0x002a, 0x2001, 0x1992, 0x2003, 0x0001,
-	0x9006, 0x080c, 0x29ad, 0x2001, 0xffff, 0x20a9, 0x0009, 0x080c,
-	0x2a18, 0x2001, 0x1990, 0x2003, 0x0006, 0x2009, 0x001e, 0x2011,
-	0x2864, 0x080c, 0x8a5d, 0x0005, 0x080c, 0x0d85, 0x2001, 0x199a,
-	0x2003, 0x0036, 0x2001, 0x1992, 0x2003, 0x0003, 0x7a38, 0x9294,
-	0x0005, 0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001,
-	0x080c, 0x29ad, 0x2001, 0x1996, 0x2003, 0x0000, 0x2001, 0xffff,
-	0x20a9, 0x0009, 0x080c, 0x2a18, 0x2001, 0x1990, 0x2003, 0x0006,
-	0x2009, 0x001e, 0x2011, 0x2864, 0x080c, 0x8a5d, 0x0005, 0x080c,
-	0x0d85, 0x080c, 0x0d85, 0x0005, 0x0006, 0x0016, 0x0026, 0x00e6,
-	0x00f6, 0x0156, 0x0126, 0x2091, 0x8000, 0x2079, 0x0100, 0x2001,
-	0x1992, 0x2004, 0x908a, 0x0007, 0x1a0c, 0x0d85, 0x0043, 0x012e,
-	0x015e, 0x00fe, 0x00ee, 0x002e, 0x001e, 0x000e, 0x0005, 0x2886,
-	0x28a2, 0x28de, 0x290a, 0x292a, 0x2936, 0x2938, 0x080c, 0x2a0c,
-	0x1190, 0x2009, 0x1998, 0x2104, 0x7a38, 0x9294, 0x0005, 0x9296,
-	0x0004, 0x0110, 0xc08d, 0x0008, 0xc085, 0x200a, 0x2001, 0x1990,
-	0x2003, 0x0001, 0x0030, 0x080c, 0x295c, 0x2001, 0xffff, 0x080c,
-	0x2801, 0x0005, 0x080c, 0x293a, 0x05c0, 0x2009, 0x1999, 0x2104,
-	0x8001, 0x200a, 0x080c, 0x2a0c, 0x1158, 0x7a38, 0x9294, 0x0005,
-	0x9296, 0x0005, 0x0518, 0x2009, 0x1998, 0x2104, 0xc085, 0x200a,
-	0x2009, 0x1995, 0x2104, 0x8000, 0x200a, 0x9086, 0x0005, 0x0118,
-	0x080c, 0x2942, 0x00c0, 0x200b, 0x0000, 0x7a38, 0x9294, 0x0006,
-	0x9296, 0x0004, 0x0110, 0x9006, 0x0010, 0x2001, 0x0001, 0x080c,
-	0x29ca, 0x2001, 0x1992, 0x2003, 0x0002, 0x0028, 0x2001, 0x1990,
-	0x2003, 0x0003, 0x0010, 0x080c, 0x2823, 0x0005, 0x080c, 0x293a,
-	0x0540, 0x2009, 0x1999, 0x2104, 0x8001, 0x200a, 0x080c, 0x2a0c,
-	0x1148, 0x2001, 0x1990, 0x2003, 0x0003, 0x2001, 0x1991, 0x2003,
-	0x0000, 0x00b8, 0x2009, 0x1999, 0x2104, 0x9005, 0x1118, 0x080c,
-	0x297f, 0x0010, 0x080c, 0x294f, 0x080c, 0x2942, 0x2009, 0x1995,
-	0x200b, 0x0000, 0x2001, 0x1992, 0x2003, 0x0001, 0x080c, 0x2823,
-	0x0000, 0x0005, 0x0479, 0x01e8, 0x080c, 0x2a0c, 0x1198, 0x2009,
-	0x1996, 0x2104, 0x8000, 0x200a, 0x9086, 0x0007, 0x0108, 0x0078,
-	0x2001, 0x199b, 0x2003, 0x000a, 0x2009, 0x1998, 0x2104, 0xc0fd,
-	0x200a, 0x0038, 0x00f9, 0x2001, 0x1992, 0x2003, 0x0004, 0x080c,
-	0x284e, 0x0005, 0x0079, 0x0148, 0x080c, 0x2a0c, 0x1118, 0x080c,
-	0x283a, 0x0018, 0x0079, 0x080c, 0x284e, 0x0005, 0x080c, 0x0d85,
-	0x080c, 0x0d85, 0x2009, 0x199a, 0x2104, 0x8001, 0x200a, 0x090c,
-	0x299b, 0x0005, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110,
-	0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ca, 0x0005, 0x7a38,
-	0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001,
-	0x0001, 0x080c, 0x29ad, 0x0005, 0x2009, 0x1995, 0x2104, 0x8000,
-	0x200a, 0x9086, 0x0005, 0x0108, 0x0068, 0x200b, 0x0000, 0x7a38,
-	0x9294, 0x0006, 0x9296, 0x0006, 0x0110, 0x9006, 0x0010, 0x2001,
-	0x0001, 0x04d9, 0x7a38, 0x9294, 0x0005, 0x9296, 0x0005, 0x0110,
-	0x9006, 0x0010, 0x2001, 0x0001, 0x080c, 0x29ca, 0x0005, 0x0086,
-	0x2001, 0x1998, 0x2004, 0x9084, 0x7fff, 0x090c, 0x0d85, 0x2009,
-	0x1997, 0x2144, 0x8846, 0x280a, 0x9844, 0x0dd8, 0xd08c, 0x1120,
-	0xd084, 0x1120, 0x080c, 0x0d85, 0x9006, 0x0010, 0x2001, 0x0001,
-	0x00a1, 0x008e, 0x0005, 0x0006, 0x0156, 0x2001, 0x1990, 0x20a9,
-	0x0009, 0x2003, 0x0000, 0x8000, 0x1f04, 0x29a1, 0x2001, 0x1997,
-	0x2003, 0x8000, 0x015e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0100,
-	0x9085, 0x0000, 0x0158, 0x7838, 0x9084, 0xfff9, 0x9085, 0x0004,
-	0x783a, 0x2009, 0x199d, 0x210c, 0x795a, 0x0050, 0x7838, 0x9084,
-	0xfffb, 0x9085, 0x0006, 0x783a, 0x2009, 0x199e, 0x210c, 0x795a,
-	0x00fe, 0x0005, 0x00f6, 0x2079, 0x0100, 0x9085, 0x0000, 0x0158,
-	0x7838, 0x9084, 0xfffa, 0x9085, 0x0004, 0x783a, 0x7850, 0x9084,
-	0xfff0, 0x7852, 0x00f8, 0x7838, 0x9084, 0xfffb, 0x9085, 0x0005,
-	0x783a, 0x7850, 0x9084, 0xfff0, 0x0016, 0x2009, 0x017f, 0x210c,
-	0x918e, 0x0005, 0x0140, 0x2009, 0x0003, 0x210c, 0x918c, 0x0600,
-	0x918e, 0x0400, 0x0118, 0x9085, 0x000a, 0x0010, 0x9085, 0x0000,
-	0x001e, 0x7852, 0x00fe, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004,
-	0x9082, 0x0007, 0x000e, 0x0005, 0x0006, 0x2001, 0x0100, 0x2004,
-	0x9082, 0x0009, 0x000e, 0x0005, 0x0156, 0x20a9, 0x0064, 0x7820,
-	0x080c, 0x2a7f, 0xd09c, 0x1110, 0x1f04, 0x2a0f, 0x015e, 0x0005,
-	0x0126, 0x0016, 0x0006, 0x2091, 0x8000, 0x000e, 0x2008, 0x9186,
-	0x0000, 0x1118, 0x783b, 0x0007, 0x0090, 0x9186, 0x0001, 0x1118,
-	0x783b, 0x0006, 0x0060, 0x9186, 0x0002, 0x1118, 0x783b, 0x0005,
-	0x0030, 0x9186, 0x0003, 0x1118, 0x783b, 0x0004, 0x0000, 0x0006,
-	0x1d04, 0x2a38, 0x080c, 0x8a7f, 0x1f04, 0x2a38, 0x080c, 0x2af6,
-	0x080c, 0x2b29, 0x7850, 0x9085, 0x1000, 0x7852, 0x000e, 0x001e,
-	0x012e, 0x0005, 0x080c, 0x2b29, 0x0005, 0x0006, 0x0156, 0x00f6,
-	0x2079, 0x0100, 0x20a9, 0x000a, 0x7854, 0xd0ac, 0x1100, 0x7854,
-	0xd08c, 0x1110, 0x1f04, 0x2a57, 0x00fe, 0x015e, 0x000e, 0x0005,
-	0x1d04, 0x2a60, 0x080c, 0x8a7f, 0x1f04, 0x2a60, 0x0005, 0x0006,
-	0x2001, 0x199c, 0x2004, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006,
-	0x2001, 0x199c, 0x2004, 0x9086, 0x0001, 0x000e, 0x0005, 0x0006,
-	0x2001, 0x199c, 0x2004, 0x9086, 0x0002, 0x000e, 0x0005, 0xa001,
-	0xa001, 0xa001, 0xa001, 0xa001, 0x0005, 0x0006, 0x2001, 0x19a9,
-	0x2102, 0x000e, 0x0005, 0x2009, 0x0171, 0x2104, 0xd0dc, 0x0140,
-	0x2009, 0x0170, 0x2104, 0x200b, 0x0080, 0xa001, 0xa001, 0x200a,
-	0x0005, 0x0016, 0x0026, 0x080c, 0x77b8, 0x0108, 0xc0bc, 0x2009,
-	0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a, 0x002e, 0x001e,
-	0x0005, 0x0016, 0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001,
-	0x9285, 0x1000, 0x200a, 0x220a, 0x002e, 0x001e, 0x0005, 0x0016,
-	0x0026, 0x2009, 0x0140, 0x2114, 0x9294, 0x0001, 0x9215, 0x220a,
-	0x002e, 0x001e, 0x0005, 0x0006, 0x0016, 0x2009, 0x0140, 0x2104,
-	0x1128, 0x080c, 0x77b8, 0x0110, 0xc0bc, 0x0008, 0xc0bd, 0x200a,
-	0x001e, 0x000e, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0101,
-	0x7844, 0xd084, 0x1de8, 0x2001, 0x0109, 0x2202, 0x7843, 0x0100,
-	0x00fe, 0x0005, 0x00f6, 0x2079, 0x0380, 0x7843, 0x0202, 0x7844,
-	0xd08c, 0x1de8, 0x2079, 0x0100, 0x7814, 0x9104, 0x9205, 0x7a16,
-	0x2079, 0x0380, 0x7843, 0x0200, 0x00fe, 0x0005, 0x0016, 0x0026,
-	0x0036, 0x00c6, 0x2061, 0x0100, 0x6050, 0x9084, 0xfbff, 0x9085,
-	0x0040, 0x6052, 0x20a9, 0x0002, 0x080c, 0x2a60, 0x6050, 0x9085,
-	0x0400, 0x9084, 0xff9f, 0x6052, 0x20a9, 0x0005, 0x080c, 0x2a60,
-	0x6054, 0xd0bc, 0x090c, 0x0d85, 0x20a9, 0x0005, 0x080c, 0x2a60,
-	0x6054, 0xd0ac, 0x090c, 0x0d85, 0x2009, 0x19b0, 0x9084, 0x7e00,
-	0x8007, 0x8004, 0x8004, 0x200a, 0x00ce, 0x003e, 0x002e, 0x001e,
-	0x0005, 0x0006, 0x00c6, 0x2061, 0x0100, 0x6050, 0xc0cd, 0x6052,
-	0x00ce, 0x000e, 0x0005, 0x0016, 0x00c6, 0x00d6, 0x0006, 0x2061,
-	0x0100, 0x2069, 0x0140, 0x6030, 0x0006, 0x6048, 0x0006, 0x60e4,
-	0x0006, 0x60e8, 0x0006, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c,
-	0x0006, 0x6004, 0x0006, 0xc0fc, 0x6006, 0x2009, 0x0800, 0x2001,
-	0x0338, 0x2003, 0x0301, 0x8109, 0x090c, 0x0d85, 0x2001, 0x0338,
-	0x2004, 0xd084, 0x1dc0, 0x6028, 0x0006, 0x60e0, 0x0006, 0x6888,
-	0x0006, 0x688c, 0x0006, 0x6890, 0x0006, 0x080c, 0x779e, 0x1110,
-	0x6884, 0x0006, 0x602f, 0x0100, 0x602f, 0x0000, 0xa001, 0xa001,
-	0xa001, 0xa001, 0x602f, 0x0040, 0x602f, 0x0000, 0x080c, 0x779e,
-	0x1120, 0x6803, 0x0080, 0x000e, 0x6886, 0x6897, 0x4198, 0x000e,
-	0x6892, 0x000e, 0x688e, 0x000e, 0x688a, 0x000e, 0x60e2, 0x000e,
-	0x602a, 0x000e, 0x6006, 0x000e, 0x600e, 0x000e, 0x60ee, 0x000e,
-	0x6052, 0x000e, 0x60ea, 0x000e, 0x60e6, 0x000e, 0x604a, 0x000e,
-	0x6032, 0x6036, 0x2008, 0x080c, 0x26d5, 0x000e, 0x00de, 0x00ce,
-	0x001e, 0x0005, 0x0006, 0x0156, 0x6050, 0x9085, 0x0040, 0x6052,
-	0x6050, 0x9084, 0xfbcf, 0x6052, 0x080c, 0x2a7f, 0x9085, 0x2000,
-	0x6052, 0x20a9, 0x0012, 0x1d04, 0x2bb3, 0x080c, 0x8a7f, 0x1f04,
-	0x2bb3, 0x6050, 0x9085, 0x0400, 0x9084, 0xdfbf, 0x6052, 0x015e,
-	0x000e, 0x0005, 0x30be, 0x30be, 0x2cc2, 0x2cc2, 0x2cce, 0x2cce,
-	0x2cda, 0x2cda, 0x2ce8, 0x2ce8, 0x2cf4, 0x2cf4, 0x2d02, 0x2d02,
-	0x2d10, 0x2d10, 0x2d22, 0x2d22, 0x2d2e, 0x2d2e, 0x2d3c, 0x2d3c,
-	0x2d5a, 0x2d5a, 0x2d7a, 0x2d7a, 0x2d4a, 0x2d4a, 0x2d6a, 0x2d6a,
-	0x2d88, 0x2d88, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d9a, 0x2d9a, 0x2da6, 0x2da6, 0x2db4, 0x2db4,
-	0x2dc2, 0x2dc2, 0x2dd2, 0x2dd2, 0x2de0, 0x2de0, 0x2df0, 0x2df0,
-	0x2e00, 0x2e00, 0x2e12, 0x2e12, 0x2e20, 0x2e20, 0x2e30, 0x2e30,
-	0x2e52, 0x2e52, 0x2e76, 0x2e76, 0x2e40, 0x2e40, 0x2e64, 0x2e64,
-	0x2e86, 0x2e86, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2e9a, 0x2e9a, 0x2ea6, 0x2ea6, 0x2eb4, 0x2eb4,
-	0x2ec2, 0x2ec2, 0x2ed2, 0x2ed2, 0x2ee0, 0x2ee0, 0x2ef0, 0x2ef0,
-	0x2f00, 0x2f00, 0x2f12, 0x2f12, 0x2f20, 0x2f20, 0x2f30, 0x2f30,
-	0x2f40, 0x2f40, 0x2f52, 0x2f52, 0x2f62, 0x2f62, 0x2f74, 0x2f74,
-	0x2f86, 0x2f86, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2f9a, 0x2f9a, 0x2fa8, 0x2fa8, 0x2fb8, 0x2fb8,
-	0x2fc8, 0x2fc8, 0x2fda, 0x2fda, 0x2fea, 0x2fea, 0x2ffc, 0x2ffc,
-	0x300e, 0x300e, 0x3022, 0x3022, 0x3032, 0x3032, 0x3044, 0x3044,
-	0x3056, 0x3056, 0x306a, 0x306a, 0x307b, 0x307b, 0x308e, 0x308e,
-	0x30a1, 0x30a1, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20, 0x2d20,
-	0x2d20, 0x2d20, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22c8, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0xa001, 0x0cf0, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x22c8,
-	0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x13d4,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0x13d4, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f,
-	0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x13d4, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x13d4, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0x22c8,
-	0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea,
-	0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f,
-	0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f,
-	0x080c, 0x20ea, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0xad62, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0xad62,
-	0x080c, 0x22c8, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x13d4, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4,
-	0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea, 0x080c, 0xad62,
-	0x080c, 0x13d4, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x20ea,
-	0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x0804, 0x30b6,
-	0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156,
-	0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8,
-	0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea,
-	0x080c, 0xad62, 0x080c, 0x2114, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f,
-	0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x2114,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x13d4,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x22c8,
-	0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6,
-	0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0x20ea,
-	0x080c, 0xad62, 0x080c, 0x13d4, 0x0804, 0x30b6, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f,
-	0x080c, 0x20ea, 0x080c, 0xad62, 0x080c, 0x22c8, 0x080c, 0x13d4,
-	0x0804, 0x30b6, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136,
-	0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c, 0x13d4,
-	0x080c, 0x2114, 0x04d8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6,
-	0x0136, 0x0146, 0x0156, 0x080c, 0x278f, 0x080c, 0xad62, 0x080c,
-	0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0440, 0x0106, 0x0006,
-	0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146, 0x0156, 0x080c, 0x278f,
-	0x080c, 0x20ea, 0x080c, 0x13d4, 0x080c, 0xad62, 0x080c, 0x2114,
-	0x00a8, 0x0106, 0x0006, 0x0126, 0x01c6, 0x01d6, 0x0136, 0x0146,
-	0x0156, 0x080c, 0x278f, 0x080c, 0x20ea, 0x080c, 0xad62, 0x080c,
-	0x22c8, 0x080c, 0x13d4, 0x080c, 0x2114, 0x0000, 0x015e, 0x014e,
-	0x013e, 0x01de, 0x01ce, 0x012e, 0x000e, 0x010e, 0x000d, 0x00b6,
-	0x00c6, 0x0026, 0x0046, 0x9026, 0x080c, 0x6bcf, 0x1904, 0x31f6,
-	0x72dc, 0x2001, 0x197c, 0x2004, 0x9005, 0x1110, 0xd29c, 0x0148,
-	0xd284, 0x1138, 0xd2bc, 0x1904, 0x31f6, 0x080c, 0x31fb, 0x0804,
-	0x31f6, 0xd2cc, 0x1904, 0x31f6, 0x080c, 0x779e, 0x1120, 0x70af,
-	0xffff, 0x0804, 0x31f6, 0xd294, 0x0120, 0x70af, 0xffff, 0x0804,
-	0x31f6, 0x080c, 0x347d, 0x0160, 0x080c, 0xd645, 0x0128, 0x2001,
-	0x1818, 0x203c, 0x0804, 0x316f, 0x70af, 0xffff, 0x0804, 0x31f6,
-	0x2001, 0x1818, 0x203c, 0x7294, 0xd284, 0x0904, 0x316f, 0xd28c,
-	0x1904, 0x316f, 0x0036, 0x73ac, 0x938e, 0xffff, 0x1110, 0x2019,
-	0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04, 0x938c, 0x0001, 0x0120,
-	0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff, 0x970e, 0x0904,
-	0x3165, 0x908e, 0x0000, 0x0904, 0x3165, 0x908e, 0x00ff, 0x1160,
-	0x7230, 0xd284, 0x1904, 0x316a, 0x7294, 0xc28d, 0x7296, 0x70af,
-	0xffff, 0x003e, 0x0804, 0x316f, 0x2009, 0x180d, 0x210c, 0xd18c,
-	0x0150, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0118,
-	0x70af, 0xffff, 0x0488, 0x900e, 0x080c, 0x268c, 0x080c, 0x6749,
-	0x1538, 0x9006, 0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6,
-	0x2060, 0x080c, 0x8eee, 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000,
-	0x080c, 0x6c11, 0x1168, 0x7030, 0xd08c, 0x0130, 0xb800, 0xd0bc,
-	0x0138, 0x080c, 0x6aae, 0x0120, 0x080c, 0x3214, 0x0148, 0x0028,
-	0x080c, 0x3360, 0x080c, 0x3240, 0x0118, 0x8318, 0x0804, 0x3109,
-	0x73ae, 0x0010, 0x70af, 0xffff, 0x003e, 0x0804, 0x31f6, 0x9780,
-	0x348e, 0x203d, 0x97bc, 0xff00, 0x873f, 0x2041, 0x007e, 0x70ac,
-	0x9096, 0xffff, 0x1118, 0x900e, 0x28a8, 0x0050, 0x9812, 0x0220,
-	0x2008, 0x9802, 0x20a8, 0x0020, 0x70af, 0xffff, 0x0804, 0x31f6,
-	0x2700, 0x0156, 0x0016, 0x9106, 0x0904, 0x31eb, 0x2001, 0x180d,
-	0x2004, 0xd08c, 0x0158, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35,
-	0x002e, 0x0120, 0x2009, 0xffff, 0x0804, 0x31f3, 0xc484, 0x080c,
-	0x67b4, 0x0168, 0x080c, 0xd645, 0x1904, 0x31eb, 0x080c, 0x347d,
-	0x1904, 0x31eb, 0x080c, 0x6749, 0x1904, 0x31f3, 0x0008, 0xc485,
-	0xb8bb, 0x0520, 0xb8ac, 0x9005, 0x0148, 0x00c6, 0x2060, 0x080c,
-	0x8eee, 0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, 0x080c, 0x6c11,
-	0x1130, 0x7030, 0xd08c, 0x01f8, 0xb800, 0xd0bc, 0x11e0, 0x7294,
-	0xd28c, 0x0180, 0x080c, 0x6c11, 0x9082, 0x0006, 0x02e0, 0xd484,
-	0x1118, 0x080c, 0x676e, 0x0028, 0x080c, 0x33f3, 0x01a0, 0x080c,
-	0x341e, 0x0088, 0x080c, 0x3360, 0x080c, 0xd645, 0x1160, 0x080c,
-	0x3240, 0x0188, 0x0040, 0x080c, 0xd645, 0x1118, 0x080c, 0x33f3,
-	0x0110, 0x0451, 0x0140, 0x001e, 0x8108, 0x015e, 0x1f04, 0x3188,
-	0x70af, 0xffff, 0x0018, 0x001e, 0x015e, 0x71ae, 0x004e, 0x002e,
-	0x00ce, 0x00be, 0x0005, 0x00c6, 0x0016, 0x70af, 0x0001, 0x2009,
-	0x007e, 0x080c, 0x6749, 0x1168, 0xb813, 0x00ff, 0xb817, 0xfffe,
-	0x080c, 0x3360, 0x04a9, 0x0128, 0x70dc, 0xc0bd, 0x70de, 0x080c,
-	0xd389, 0x001e, 0x00ce, 0x0005, 0x0016, 0x0076, 0x00d6, 0x00c6,
-	0x2001, 0x184c, 0x2004, 0x9084, 0x00ff, 0xb842, 0x080c, 0xb1dd,
-	0x01d0, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x9006,
-	0x080c, 0x66e6, 0x2001, 0x0000, 0x080c, 0x66fa, 0x0126, 0x2091,
-	0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e, 0x2009, 0x0004, 0x080c,
-	0xb20a, 0x9085, 0x0001, 0x00ce, 0x00de, 0x007e, 0x001e, 0x0005,
-	0x0016, 0x0076, 0x00d6, 0x00c6, 0x2001, 0x184c, 0x2004, 0x9084,
-	0x00ff, 0xb842, 0x080c, 0xb1dd, 0x0548, 0x2b00, 0x6012, 0xb800,
-	0xc0c4, 0xb802, 0xb8a0, 0x9086, 0x007e, 0x0140, 0xb804, 0x9084,
-	0x00ff, 0x9086, 0x0006, 0x1110, 0x080c, 0x3315, 0x080c, 0xd3b6,
-	0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0002, 0x080c,
-	0x66fa, 0x0126, 0x2091, 0x8000, 0x70a8, 0x8000, 0x70aa, 0x012e,
-	0x2009, 0x0002, 0x080c, 0xb20a, 0x9085, 0x0001, 0x00ce, 0x00de,
-	0x007e, 0x001e, 0x0005, 0x00b6, 0x00c6, 0x0026, 0x2009, 0x0080,
-	0x080c, 0x6749, 0x1140, 0xb813, 0x00ff, 0xb817, 0xfffc, 0x0039,
-	0x0110, 0x70e3, 0xffff, 0x002e, 0x00ce, 0x00be, 0x0005, 0x0016,
-	0x0076, 0x00d6, 0x00c6, 0x080c, 0xb116, 0x01d0, 0x2b00, 0x6012,
-	0x080c, 0xd3b6, 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0x2001,
-	0x0002, 0x080c, 0x66fa, 0x0126, 0x2091, 0x8000, 0x70e4, 0x8000,
-	0x70e6, 0x012e, 0x2009, 0x0002, 0x080c, 0xb20a, 0x9085, 0x0001,
-	0x00ce, 0x00de, 0x007e, 0x001e, 0x0005, 0x00c6, 0x00d6, 0x0126,
-	0x2091, 0x8000, 0x2009, 0x007f, 0x080c, 0x6749, 0x11b8, 0xb813,
-	0x00ff, 0xb817, 0xfffd, 0xb8d7, 0x0004, 0x080c, 0xb116, 0x0170,
-	0x2b00, 0x6012, 0x6316, 0x6023, 0x0001, 0x620a, 0x080c, 0xd3b6,
-	0x2009, 0x0022, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, 0x00de,
-	0x00ce, 0x0005, 0x00e6, 0x00c6, 0x0066, 0x0036, 0x0026, 0x00b6,
-	0x21f0, 0x080c, 0xacfc, 0x0106, 0x080c, 0x97bb, 0x080c, 0x9727,
-	0x080c, 0xac4d, 0x080c, 0xc179, 0x010e, 0x090c, 0xad18, 0x3e08,
-	0x2130, 0x81ff, 0x0120, 0x20a9, 0x007e, 0x900e, 0x0018, 0x20a9,
-	0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1140, 0x9686, 0x0002,
-	0x1118, 0xb800, 0xd0bc, 0x1110, 0x080c, 0x61b7, 0x001e, 0x8108,
-	0x1f04, 0x32fa, 0x9686, 0x0001, 0x190c, 0x3451, 0x00be, 0x002e,
-	0x003e, 0x006e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x00c6, 0x0046,
-	0x0036, 0x0026, 0x0016, 0x00b6, 0x080c, 0xacfc, 0x0106, 0x6210,
-	0x2258, 0xbaa0, 0x0026, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076,
-	0x2039, 0x0000, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e,
-	0x001e, 0x010e, 0x090c, 0xad18, 0xba10, 0xbb14, 0xbc84, 0x080c,
-	0x61b7, 0xba12, 0xbb16, 0xbc86, 0x00be, 0x001e, 0x002e, 0x003e,
-	0x004e, 0x00ce, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x00b6, 0x6010,
-	0x2058, 0xb8a0, 0x00be, 0x9086, 0x0080, 0x0150, 0x2071, 0x1800,
-	0x70a8, 0x9005, 0x0110, 0x8001, 0x70aa, 0x000e, 0x00ee, 0x0005,
-	0x2071, 0x1800, 0x70e4, 0x9005, 0x0dc0, 0x8001, 0x70e6, 0x0ca8,
-	0xb800, 0xc08c, 0xb802, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x00b6,
-	0x0046, 0x0036, 0x0026, 0x0016, 0x0156, 0x2178, 0x080c, 0xacfc,
-	0x0106, 0x81ff, 0x1118, 0x20a9, 0x0001, 0x0078, 0x080c, 0x5840,
-	0xd0c4, 0x0140, 0xd0a4, 0x0130, 0x9006, 0x2020, 0x2009, 0x002d,
-	0x080c, 0xea8d, 0x20a9, 0x0800, 0x9016, 0x0026, 0x928e, 0x007e,
-	0x0904, 0x33cf, 0x928e, 0x007f, 0x0904, 0x33cf, 0x928e, 0x0080,
-	0x05f0, 0x9288, 0x1000, 0x210c, 0x81ff, 0x05c8, 0x8fff, 0x1150,
-	0x2001, 0x198e, 0x0006, 0x2003, 0x0001, 0x080c, 0x33e0, 0x000e,
-	0x2003, 0x0000, 0x00b6, 0x00c6, 0x2158, 0x2001, 0x0001, 0x080c,
-	0x6bdb, 0x00ce, 0x00be, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076,
-	0x2039, 0x0000, 0x080c, 0x966d, 0x00b6, 0x00c6, 0x0026, 0x2158,
-	0xba04, 0x9294, 0x00ff, 0x9286, 0x0006, 0x1118, 0xb807, 0x0404,
-	0x0028, 0x2001, 0x0004, 0x8007, 0x9215, 0xba06, 0x002e, 0x00ce,
-	0x00be, 0x0016, 0x2c08, 0x080c, 0xe75d, 0x001e, 0x007e, 0x002e,
-	0x8210, 0x1f04, 0x3385, 0x010e, 0x090c, 0xad18, 0x015e, 0x001e,
-	0x002e, 0x003e, 0x004e, 0x00be, 0x00ce, 0x00ee, 0x00fe, 0x0005,
-	0x0046, 0x0026, 0x0016, 0x080c, 0x5840, 0xd0c4, 0x0140, 0xd0a4,
-	0x0130, 0x9006, 0x2220, 0x2009, 0x0029, 0x080c, 0xea8d, 0x001e,
-	0x002e, 0x004e, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x7294,
-	0x82ff, 0x01e8, 0x080c, 0x6c09, 0x11d0, 0x2100, 0x080c, 0x26bf,
-	0x81ff, 0x01b8, 0x2019, 0x0001, 0x8314, 0x92e0, 0x1d80, 0x2c04,
-	0xd384, 0x0120, 0x9084, 0xff00, 0x8007, 0x0010, 0x9084, 0x00ff,
-	0x9116, 0x0138, 0x9096, 0x00ff, 0x0110, 0x8318, 0x0c68, 0x9085,
-	0x0001, 0x00ce, 0x003e, 0x002e, 0x001e, 0x0005, 0x0016, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, 0x0106, 0x0036, 0x2019,
-	0x0029, 0x00c1, 0x003e, 0x010e, 0x090c, 0xad18, 0x9180, 0x1000,
-	0x2004, 0x9065, 0x0158, 0x0016, 0x00c6, 0x2061, 0x1b39, 0x001e,
-	0x6112, 0x080c, 0x3315, 0x001e, 0x080c, 0x676e, 0x012e, 0x00ce,
-	0x001e, 0x0005, 0x0016, 0x0026, 0x2110, 0x080c, 0xa7e2, 0x080c,
-	0xedee, 0x002e, 0x001e, 0x0005, 0x2001, 0x1837, 0x2004, 0xd0cc,
-	0x0005, 0x00c6, 0x00b6, 0x080c, 0x779e, 0x1118, 0x20a9, 0x0800,
-	0x0010, 0x20a9, 0x0782, 0x080c, 0x779e, 0x1110, 0x900e, 0x0010,
-	0x2009, 0x007e, 0x9180, 0x1000, 0x2004, 0x905d, 0x0130, 0x86ff,
-	0x0110, 0xb800, 0xd0bc, 0x090c, 0x676e, 0x8108, 0x1f04, 0x3462,
-	0x2061, 0x1800, 0x607f, 0x0000, 0x6080, 0x9084, 0x00ff, 0x6082,
-	0x60b3, 0x0000, 0x00be, 0x00ce, 0x0005, 0x2001, 0x1869, 0x2004,
-	0xd0bc, 0x0005, 0x2011, 0x1848, 0x2214, 0xd2ec, 0x0005, 0x0026,
-	0x2011, 0x1867, 0x2214, 0xd2dc, 0x002e, 0x0005, 0x7eef, 0x7de8,
-	0x7ce4, 0x80e2, 0x7be1, 0x80e0, 0x80dc, 0x80da, 0x7ad9, 0x80d6,
-	0x80d5, 0x80d4, 0x80d3, 0x80d2, 0x80d1, 0x79ce, 0x78cd, 0x80cc,
-	0x80cb, 0x80ca, 0x80c9, 0x80c7, 0x80c6, 0x77c5, 0x76c3, 0x80bc,
-	0x80ba, 0x75b9, 0x80b6, 0x74b5, 0x73b4, 0x72b3, 0x80b2, 0x80b1,
-	0x80ae, 0x71ad, 0x80ac, 0x70ab, 0x6faa, 0x6ea9, 0x80a7, 0x6da6,
-	0x6ca5, 0x6ba3, 0x6a9f, 0x699e, 0x689d, 0x809b, 0x8098, 0x6797,
-	0x6690, 0x658f, 0x6488, 0x6384, 0x6282, 0x8081, 0x8080, 0x617c,
-	0x607a, 0x8079, 0x5f76, 0x8075, 0x8074, 0x8073, 0x8072, 0x8071,
-	0x806e, 0x5e6d, 0x806c, 0x5d6b, 0x5c6a, 0x5b69, 0x8067, 0x5a66,
-	0x5965, 0x5863, 0x575c, 0x565a, 0x5559, 0x8056, 0x8055, 0x5454,
-	0x5353, 0x5252, 0x5151, 0x504e, 0x4f4d, 0x804c, 0x804b, 0x4e4a,
-	0x4d49, 0x8047, 0x4c46, 0x8045, 0x8043, 0x803c, 0x803a, 0x8039,
-	0x8036, 0x4b35, 0x8034, 0x4a33, 0x4932, 0x4831, 0x802e, 0x472d,
-	0x462c, 0x452b, 0x442a, 0x4329, 0x4227, 0x8026, 0x8025, 0x4123,
-	0x401f, 0x3f1e, 0x3e1d, 0x3d1b, 0x3c18, 0x8017, 0x8010, 0x3b0f,
-	0x3a08, 0x8004, 0x3902, 0x8001, 0x8000, 0x8000, 0x3800, 0x3700,
-	0x3600, 0x8000, 0x3500, 0x8000, 0x8000, 0x8000, 0x3400, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3300, 0x3200, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x3100, 0x3000, 0x8000,
-	0x8000, 0x2f00, 0x8000, 0x2e00, 0x2d00, 0x2c00, 0x8000, 0x8000,
-	0x8000, 0x2b00, 0x8000, 0x2a00, 0x2900, 0x2800, 0x8000, 0x2700,
-	0x2600, 0x2500, 0x2400, 0x2300, 0x2200, 0x8000, 0x8000, 0x2100,
-	0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x8000, 0x8000, 0x1b00,
-	0x1a00, 0x8000, 0x1900, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x1800, 0x8000, 0x1700, 0x1600, 0x1500, 0x8000, 0x1400,
-	0x1300, 0x1200, 0x1100, 0x1000, 0x0f00, 0x8000, 0x8000, 0x0e00,
-	0x0d00, 0x0c00, 0x0b00, 0x0a00, 0x0900, 0x8000, 0x8000, 0x0800,
-	0x0700, 0x8000, 0x0600, 0x8000, 0x8000, 0x8000, 0x0500, 0x0400,
-	0x0300, 0x8000, 0x0200, 0x8000, 0x8000, 0x8000, 0x0100, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x0000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,
-	0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x2071, 0x189e,
-	0x7003, 0x0002, 0x9006, 0x7016, 0x701a, 0x704a, 0x704e, 0x700e,
-	0x7042, 0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x7007, 0x0001,
-	0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x706a, 0xa867, 0x0002,
-	0xa8ab, 0xdcb0, 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x706e,
-	0xa867, 0x0002, 0xa8ab, 0xdcb0, 0x0005, 0x2071, 0x189e, 0x7004,
-	0x0002, 0x35bd, 0x35be, 0x35d1, 0x35e5, 0x0005, 0x1004, 0x35ce,
-	0x0e04, 0x35ce, 0x2079, 0x0000, 0x0126, 0x2091, 0x8000, 0x700c,
-	0x9005, 0x1128, 0x700f, 0x0001, 0x012e, 0x0468, 0x0005, 0x012e,
-	0x0ce8, 0x2079, 0x0000, 0x2061, 0x18b8, 0x2c4c, 0xa86c, 0x908e,
-	0x0100, 0x0128, 0x9086, 0x0200, 0x0904, 0x36b9, 0x0005, 0x7018,
-	0x2048, 0x2061, 0x1800, 0x701c, 0x0807, 0x7014, 0x2048, 0xa864,
-	0x9094, 0x00ff, 0x9296, 0x0029, 0x1120, 0xaa78, 0xd2fc, 0x0128,
-	0x0005, 0x9086, 0x0103, 0x0108, 0x0005, 0x2079, 0x0000, 0x2061,
-	0x1800, 0x701c, 0x0807, 0x2061, 0x1800, 0x7880, 0x908a, 0x0040,
-	0x1210, 0x61d0, 0x0042, 0x2100, 0x908a, 0x003f, 0x1a04, 0x36b6,
-	0x61d0, 0x0804, 0x364b, 0x368d, 0x36c5, 0x36b6, 0x36d1, 0x36db,
-	0x36e1, 0x36e5, 0x36f5, 0x36f9, 0x370f, 0x3715, 0x371b, 0x3726,
-	0x3731, 0x3740, 0x374f, 0x375d, 0x3774, 0x378f, 0x36b6, 0x383a,
-	0x3878, 0x391d, 0x392e, 0x3951, 0x36b6, 0x36b6, 0x36b6, 0x3989,
-	0x39a9, 0x39b2, 0x39de, 0x39e4, 0x36b6, 0x3a2a, 0x36b6, 0x36b6,
-	0x36b6, 0x36b6, 0x36b6, 0x3a35, 0x3a3e, 0x3a46, 0x3a48, 0x36b6,
-	0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x3a78, 0x36b6, 0x36b6,
-	0x36b6, 0x36b6, 0x36b6, 0x3a95, 0x3b19, 0x36b6, 0x36b6, 0x36b6,
-	0x36b6, 0x36b6, 0x36b6, 0x0002, 0x3b43, 0x3b46, 0x3ba5, 0x3bbe,
-	0x3bee, 0x3e94, 0x36b6, 0x53f5, 0x36b6, 0x36b6, 0x36b6, 0x36b6,
-	0x36b6, 0x36b6, 0x36b6, 0x36b6, 0x370f, 0x3715, 0x4397, 0x5864,
-	0x43b5, 0x5484, 0x54d6, 0x55e1, 0x36b6, 0x5643, 0x567f, 0x56b0,
-	0x57c0, 0x56dd, 0x5740, 0x36b6, 0x43b9, 0x457f, 0x4595, 0x45ba,
-	0x461f, 0x4693, 0x46b3, 0x472a, 0x4786, 0x47e2, 0x47e5, 0x480a,
-	0x487c, 0x48e6, 0x48ee, 0x4a23, 0x4bcb, 0x4bff, 0x4e63, 0x36b6,
-	0x4e81, 0x4f48, 0x5031, 0x508b, 0x36b6, 0x511e, 0x36b6, 0x5134,
-	0x514f, 0x48ee, 0x5395, 0x714c, 0x0000, 0x2021, 0x4000, 0x080c,
-	0x4c7d, 0x0126, 0x2091, 0x8000, 0x0e04, 0x3697, 0x0010, 0x012e,
-	0x0cc0, 0x7c36, 0x9486, 0x4000, 0x0118, 0x7833, 0x0011, 0x0010,
-	0x7833, 0x0010, 0x7c82, 0x7986, 0x7a8a, 0x7b8e, 0x2091, 0x4080,
-	0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x7007, 0x0001,
-	0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005, 0x2021, 0x4001,
-	0x08b0, 0x2021, 0x4002, 0x0898, 0x2021, 0x4003, 0x0880, 0x2021,
-	0x4005, 0x0868, 0x2021, 0x4006, 0x0850, 0x2039, 0x0001, 0x902e,
-	0x2520, 0x7b88, 0x7a8c, 0x7884, 0x7990, 0x81ff, 0x0d98, 0x0804,
-	0x4c8a, 0x2039, 0x0001, 0x902e, 0x2520, 0x7b88, 0x7a8c, 0x7884,
-	0x7990, 0x0804, 0x4c8d, 0x7984, 0x7888, 0x2114, 0x200a, 0x0804,
-	0x368d, 0x7984, 0x2114, 0x0804, 0x368d, 0x20e1, 0x0000, 0x2099,
-	0x0021, 0x20e9, 0x0000, 0x20a1, 0x0021, 0x20a9, 0x001f, 0x4003,
-	0x7984, 0x7a88, 0x7b8c, 0x0804, 0x368d, 0x7884, 0x2060, 0x0804,
-	0x3742, 0x2009, 0x0003, 0x2011, 0x0003, 0x2019, 0x0014, 0x789b,
-	0x0137, 0x7893, 0xffff, 0x2001, 0x188f, 0x2004, 0x9005, 0x0118,
-	0x7896, 0x0804, 0x368d, 0x7897, 0x0001, 0x0804, 0x368d, 0x2039,
-	0x0001, 0x7d98, 0x7c9c, 0x0804, 0x36c9, 0x2039, 0x0001, 0x7d98,
-	0x7c9c, 0x0804, 0x36d5, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804,
-	0x36c2, 0x2138, 0x7d98, 0x7c9c, 0x0804, 0x36c9, 0x79a0, 0x9182,
-	0x0040, 0x0210, 0x0804, 0x36c2, 0x2138, 0x7d98, 0x7c9c, 0x0804,
-	0x36d5, 0x79a0, 0x9182, 0x0040, 0x0210, 0x0804, 0x36c2, 0x21e8,
-	0x7984, 0x7888, 0x20a9, 0x0001, 0x21a0, 0x4004, 0x0804, 0x368d,
-	0x2061, 0x0800, 0xe10c, 0x9006, 0x2c15, 0x9200, 0x8c60, 0x8109,
-	0x1dd8, 0x2010, 0x9005, 0x0904, 0x368d, 0x0804, 0x36bc, 0x79a0,
-	0x9182, 0x0040, 0x0210, 0x0804, 0x36c2, 0x21e0, 0x20a9, 0x0001,
-	0x7984, 0x2198, 0x4012, 0x0804, 0x368d, 0x2069, 0x1847, 0x7884,
-	0x7990, 0x911a, 0x1a04, 0x36c2, 0x8019, 0x0904, 0x36c2, 0x684a,
-	0x6942, 0x788c, 0x6852, 0x7888, 0x6856, 0x9006, 0x685a, 0x685e,
-	0x080c, 0x7ae7, 0x0804, 0x368d, 0x2069, 0x1847, 0x7884, 0x7994,
-	0x911a, 0x1a04, 0x36c2, 0x8019, 0x0904, 0x36c2, 0x684e, 0x6946,
-	0x788c, 0x6862, 0x7888, 0x6866, 0x9006, 0x686a, 0x686e, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x6d66, 0x012e, 0x0804, 0x368d, 0x902e,
-	0x2520, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x7984,
-	0x7b88, 0x7a8c, 0x20a9, 0x0005, 0x20e9, 0x0001, 0x20a1, 0x18a6,
-	0x4101, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf,
-	0x2009, 0x0020, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c8a,
-	0x701f, 0x37b3, 0x0005, 0xa864, 0x2008, 0x9084, 0x00ff, 0x9096,
-	0x0011, 0x0168, 0x9096, 0x0019, 0x0150, 0x9096, 0x0015, 0x0138,
-	0x9096, 0x0048, 0x0120, 0x9096, 0x0029, 0x1904, 0x36bf, 0x810f,
-	0x918c, 0x00ff, 0x0904, 0x36bf, 0x7112, 0x7010, 0x8001, 0x0560,
-	0x7012, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf,
-	0x2009, 0x0020, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494, 0xa598,
-	0x9290, 0x0040, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9, 0x0000,
-	0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c, 0x4c8a, 0x701f, 0x37f1,
-	0x0005, 0xa864, 0x9084, 0x00ff, 0x9096, 0x0002, 0x0120, 0x9096,
-	0x000a, 0x1904, 0x36bf, 0x0888, 0x0126, 0x2091, 0x8000, 0x7014,
-	0x2048, 0xa868, 0xc0fd, 0xa86a, 0xa864, 0x9084, 0x00ff, 0x9096,
-	0x0029, 0x1148, 0xc2fd, 0xaa7a, 0x080c, 0x630a, 0x0138, 0xa87a,
-	0xa982, 0x012e, 0x0060, 0x080c, 0x663a, 0x1130, 0x7007, 0x0003,
-	0x701f, 0x381f, 0x012e, 0x0005, 0x080c, 0x725e, 0x012e, 0x0126,
-	0x2091, 0x8000, 0x20a9, 0x0005, 0x20e1, 0x0001, 0x2099, 0x18a6,
-	0x400a, 0x2100, 0x9210, 0x9399, 0x0000, 0x94a1, 0x0000, 0x95a9,
-	0x0000, 0xa85c, 0x9080, 0x0019, 0x2009, 0x0020, 0x012e, 0xaf60,
-	0x0804, 0x4c8d, 0x2091, 0x8000, 0x7837, 0x4000, 0x7833, 0x0010,
-	0x7883, 0x4000, 0x7887, 0x4953, 0x788b, 0x5020, 0x788f, 0x2020,
-	0x2009, 0x017f, 0x2104, 0x7892, 0x3f00, 0x7896, 0x2061, 0x0100,
-	0x6200, 0x2061, 0x0200, 0x603c, 0x8007, 0x9205, 0x789a, 0x2009,
-	0x04fd, 0x2104, 0x789e, 0x2091, 0x5000, 0x2091, 0x4080, 0x2001,
-	0x0089, 0x2004, 0xd084, 0x0180, 0x2001, 0x1a25, 0x2004, 0x9005,
-	0x0128, 0x2001, 0x008b, 0x2004, 0xd0fc, 0x0dd8, 0x2001, 0x008a,
-	0x2003, 0x0002, 0x2003, 0x1001, 0x2071, 0x0080, 0x0804, 0x0427,
-	0x81ff, 0x1904, 0x36bf, 0x7984, 0x080c, 0x67b4, 0x1904, 0x36c2,
-	0x7e98, 0x9684, 0x3fff, 0x9082, 0x4000, 0x1a04, 0x36c2, 0x7c88,
-	0x7d8c, 0x080c, 0x69f1, 0x080c, 0x697e, 0x1518, 0x2061, 0x1ddc,
-	0x0126, 0x2091, 0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014,
-	0x904d, 0x0130, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0150,
-	0x012e, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1a04,
-	0x36bf, 0x0c30, 0x080c, 0xcae9, 0x012e, 0x0904, 0x36bf, 0x0804,
-	0x368d, 0x900e, 0x2001, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091,
-	0x8000, 0x080c, 0xd226, 0x080c, 0x7012, 0x012e, 0x0804, 0x368d,
-	0x00a6, 0x2950, 0xb198, 0x080c, 0x67b4, 0x1904, 0x390a, 0xb6a4,
-	0x9684, 0x3fff, 0x9082, 0x4000, 0x16e8, 0xb49c, 0xb5a0, 0x080c,
-	0x69f1, 0x080c, 0x697e, 0x1520, 0x2061, 0x1ddc, 0x0126, 0x2091,
-	0x8000, 0x6000, 0x9086, 0x0000, 0x0148, 0x6014, 0x904d, 0x0130,
-	0xa86c, 0x9406, 0x1118, 0xa870, 0x9506, 0x0158, 0x012e, 0x9ce0,
-	0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x2009, 0x000d, 0x12b0,
-	0x0c28, 0x080c, 0xcae9, 0x012e, 0x2009, 0x0003, 0x0178, 0x00e0,
-	0x900e, 0x2001, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091, 0x8000,
-	0x080c, 0xd226, 0x080c, 0x7006, 0x012e, 0x0070, 0xb097, 0x4005,
-	0xb19a, 0x0010, 0xb097, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001,
-	0x0030, 0x2a48, 0x00ae, 0x0005, 0xb097, 0x4000, 0x9006, 0x918d,
-	0x0001, 0x2008, 0x2a48, 0x00ae, 0x0005, 0x81ff, 0x1904, 0x36bf,
-	0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf,
-	0x080c, 0x69f7, 0x0904, 0x36bf, 0x0804, 0x46aa, 0x81ff, 0x1904,
-	0x36bf, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c, 0x6a85, 0x0904,
-	0x36bf, 0x2019, 0x0005, 0x79a8, 0x080c, 0x6a12, 0x0904, 0x36bf,
-	0x7888, 0x908a, 0x1000, 0x1a04, 0x36c2, 0x8003, 0x800b, 0x810b,
-	0x9108, 0x080c, 0x89a1, 0x79a8, 0xd184, 0x1904, 0x368d, 0x0804,
-	0x46aa, 0x0126, 0x2091, 0x8000, 0x81ff, 0x0118, 0x2009, 0x0001,
-	0x0450, 0x2029, 0x07ff, 0x645c, 0x2400, 0x9506, 0x01f8, 0x2508,
-	0x080c, 0x67b4, 0x11d8, 0x080c, 0x6a85, 0x1128, 0x2009, 0x0002,
-	0x62c0, 0x2518, 0x00c0, 0x2019, 0x0004, 0x900e, 0x080c, 0x6a12,
-	0x1118, 0x2009, 0x0006, 0x0078, 0x7884, 0x908a, 0x1000, 0x1270,
-	0x8003, 0x800b, 0x810b, 0x9108, 0x080c, 0x89a1, 0x8529, 0x1ae0,
-	0x012e, 0x0804, 0x368d, 0x012e, 0x0804, 0x36bf, 0x012e, 0x0804,
-	0x36c2, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x687b, 0x0904,
-	0x36bf, 0x080c, 0xacfc, 0xbaa0, 0x2019, 0x0005, 0x00c6, 0x9066,
-	0x080c, 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c,
-	0xe75d, 0x007e, 0x00ce, 0x080c, 0xad18, 0x080c, 0x69f1, 0x0804,
-	0x368d, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c, 0x69f1, 0x2208,
-	0x0804, 0x368d, 0x0156, 0x00d6, 0x00e6, 0x00c6, 0x2069, 0x1910,
-	0x6810, 0x6914, 0x910a, 0x1208, 0x900e, 0x6816, 0x9016, 0x901e,
-	0x2071, 0x19e8, 0x7028, 0x9065, 0x0118, 0x8210, 0x600c, 0x0cd8,
-	0x2300, 0x9218, 0x00ce, 0x00ee, 0x00de, 0x015e, 0x0804, 0x368d,
-	0x00f6, 0x0016, 0x907d, 0x0138, 0x9006, 0x8000, 0x2f0c, 0x81ff,
-	0x0110, 0x2178, 0x0cd0, 0x001e, 0x00fe, 0x0005, 0x2069, 0x1910,
-	0x6910, 0x62bc, 0x0804, 0x368d, 0x81ff, 0x0120, 0x2009, 0x0001,
-	0x0804, 0x36bf, 0x0126, 0x2091, 0x8000, 0x080c, 0x5854, 0x0128,
-	0x2009, 0x0007, 0x012e, 0x0804, 0x36bf, 0x012e, 0x615c, 0x9190,
-	0x348e, 0x2215, 0x9294, 0x00ff, 0x637c, 0x83ff, 0x0108, 0x6280,
-	0x67dc, 0x97c4, 0x000a, 0x98c6, 0x000a, 0x1118, 0x2031, 0x0001,
-	0x00e8, 0x97c4, 0x0022, 0x98c6, 0x0022, 0x1118, 0x2031, 0x0003,
-	0x00a8, 0x97c4, 0x0012, 0x98c6, 0x0012, 0x1118, 0x2031, 0x0002,
-	0x0068, 0x080c, 0x779e, 0x1118, 0x2031, 0x0004, 0x0038, 0xd79c,
-	0x0120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x9036, 0x7e9a, 0x7f9e,
-	0x0804, 0x368d, 0x614c, 0x6250, 0x2019, 0x1986, 0x231c, 0x2001,
-	0x1987, 0x2004, 0x789a, 0x0804, 0x368d, 0x0126, 0x2091, 0x8000,
-	0x6138, 0x623c, 0x6340, 0x012e, 0x0804, 0x368d, 0x080c, 0x4c74,
-	0x0904, 0x36c2, 0xba44, 0xbb38, 0x0804, 0x368d, 0x080c, 0x0d85,
-	0x080c, 0x4c74, 0x2110, 0x0904, 0x36c2, 0xb804, 0x908c, 0x00ff,
-	0x918e, 0x0006, 0x0140, 0x9084, 0xff00, 0x9086, 0x0600, 0x2009,
-	0x0009, 0x1904, 0x36bf, 0x0126, 0x2091, 0x8000, 0x2019, 0x0005,
-	0x00c6, 0x9066, 0x080c, 0xacfc, 0x080c, 0xa7e2, 0x080c, 0x97b0,
-	0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, 0xe75d, 0x007e,
-	0x00ce, 0x080c, 0xad18, 0xb807, 0x0407, 0x012e, 0x0804, 0x368d,
-	0x614c, 0x6250, 0x7884, 0x604e, 0x7b88, 0x6352, 0x2069, 0x1847,
-	0x831f, 0x9305, 0x6816, 0x788c, 0x2069, 0x1986, 0x2d1c, 0x206a,
-	0x7e98, 0x9682, 0x0014, 0x1210, 0x2031, 0x07d0, 0x2069, 0x1987,
-	0x2d04, 0x266a, 0x789a, 0x0804, 0x368d, 0x0126, 0x2091, 0x8000,
-	0x6138, 0x7884, 0x603a, 0x910e, 0xd1b4, 0x190c, 0x0eeb, 0xd0c4,
-	0x01a8, 0x00d6, 0x78a8, 0x2009, 0x199d, 0x200a, 0x78ac, 0x2011,
-	0x199e, 0x2012, 0x2069, 0x0100, 0x6838, 0x9086, 0x0007, 0x1118,
-	0x2214, 0x6a5a, 0x0010, 0x210c, 0x695a, 0x00de, 0x7888, 0xd0ec,
-	0x0178, 0x6034, 0xc08d, 0x6036, 0x2001, 0x0050, 0x6076, 0x607a,
-	0x6056, 0x606b, 0x269c, 0x00c6, 0x2061, 0x1b73, 0x2062, 0x00ce,
-	0x2011, 0x0116, 0x220c, 0x7888, 0xd08c, 0x0118, 0x918d, 0x0040,
-	0x0010, 0x918c, 0xff7f, 0x2112, 0x6134, 0xd18c, 0x2001, 0x0000,
-	0x0108, 0x603c, 0x7988, 0x613e, 0x6140, 0x910d, 0x788c, 0x6042,
-	0x6234, 0xd28c, 0x0120, 0x7a88, 0x9294, 0x1000, 0x9205, 0x910e,
-	0xd1e4, 0x190c, 0x0f06, 0x9084, 0x0020, 0x0130, 0x78b4, 0x6046,
-	0x9084, 0x0001, 0x090c, 0x4397, 0x6040, 0xd0cc, 0x0120, 0x78b0,
-	0x2011, 0x0114, 0x2012, 0x012e, 0x0804, 0x368d, 0x00f6, 0x2079,
-	0x1800, 0x7a38, 0xa898, 0x9084, 0xfebf, 0x9215, 0xa89c, 0x9084,
-	0xfebf, 0x8002, 0x9214, 0x7838, 0x9084, 0x0140, 0x9215, 0x7a3a,
-	0xa897, 0x4000, 0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x00fe,
-	0x0005, 0x7898, 0x9005, 0x01a8, 0x7888, 0x9025, 0x0904, 0x36c2,
-	0x788c, 0x902d, 0x0904, 0x36c2, 0x900e, 0x080c, 0x67b4, 0x1120,
-	0xba44, 0xbb38, 0xbc46, 0xbd3a, 0x9186, 0x07ff, 0x0190, 0x8108,
-	0x0ca0, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x7888, 0x900d, 0x0904,
-	0x36c2, 0x788c, 0x9005, 0x0904, 0x36c2, 0xba44, 0xb946, 0xbb38,
-	0xb83a, 0x0804, 0x368d, 0x2011, 0xbc09, 0x0010, 0x2011, 0xbc05,
-	0x080c, 0x5854, 0x1904, 0x36bf, 0x00c6, 0x2061, 0x0100, 0x7984,
-	0x9186, 0x00ff, 0x1130, 0x2001, 0x1818, 0x2004, 0x9085, 0xff00,
-	0x0088, 0x9182, 0x007f, 0x16e0, 0x9188, 0x348e, 0x210d, 0x918c,
-	0x00ff, 0x2001, 0x1818, 0x2004, 0x0026, 0x9116, 0x002e, 0x0580,
-	0x810f, 0x9105, 0x0126, 0x2091, 0x8000, 0x0006, 0x080c, 0xb116,
-	0x000e, 0x0510, 0x602e, 0x620a, 0x7984, 0x00b6, 0x080c, 0x674f,
-	0x2b08, 0x00be, 0x1500, 0x6112, 0x6023, 0x0001, 0x080c, 0x4c41,
-	0x01d0, 0x9006, 0xa866, 0x7007, 0x0003, 0xa832, 0xa868, 0xc0fd,
-	0xa86a, 0x701f, 0x3b9e, 0x2900, 0x6016, 0x2009, 0x0032, 0x080c,
-	0xb20a, 0x012e, 0x00ce, 0x0005, 0x012e, 0x00ce, 0x0804, 0x36bf,
-	0x00ce, 0x0804, 0x36c2, 0x080c, 0xb16c, 0x0cb0, 0xa830, 0x9086,
-	0x0100, 0x0904, 0x36bf, 0x0804, 0x368d, 0x2061, 0x1a73, 0x0126,
-	0x2091, 0x8000, 0x6000, 0xd084, 0x0170, 0x6104, 0x6208, 0x2061,
-	0x1800, 0x6354, 0x6074, 0x789a, 0x60c0, 0x789e, 0x60bc, 0x78aa,
-	0x012e, 0x0804, 0x368d, 0x900e, 0x2110, 0x0c88, 0x81ff, 0x1904,
-	0x36bf, 0x080c, 0x779e, 0x0904, 0x36bf, 0x0126, 0x2091, 0x8000,
-	0x6254, 0x6074, 0x9202, 0x0248, 0x9085, 0x0001, 0x080c, 0x26f5,
-	0x080c, 0x5a7c, 0x012e, 0x0804, 0x368d, 0x012e, 0x0804, 0x36c2,
-	0x0006, 0x0016, 0x00c6, 0x00e6, 0x2001, 0x19aa, 0x2070, 0x2061,
-	0x1847, 0x6008, 0x2072, 0x900e, 0x2011, 0x1400, 0x080c, 0x955b,
-	0x7206, 0x00ee, 0x00ce, 0x001e, 0x000e, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x81ff, 0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x368f,
-	0x7884, 0xd0fc, 0x0158, 0x2001, 0x002a, 0x2004, 0x9005, 0x0180,
-	0x9082, 0x00e1, 0x0298, 0x012e, 0x0804, 0x36c2, 0x2001, 0x002a,
-	0x2004, 0x9005, 0x0128, 0x2069, 0x1847, 0x6908, 0x9102, 0x1230,
-	0x012e, 0x0804, 0x36c2, 0x012e, 0x0804, 0x36bf, 0x080c, 0xb094,
-	0x0dd0, 0x7884, 0xd0fc, 0x0904, 0x3c6d, 0x00c6, 0x080c, 0x4c41,
-	0x00ce, 0x0d88, 0xa867, 0x0000, 0x7884, 0xa80a, 0x7898, 0xa80e,
-	0x789c, 0xa812, 0x2001, 0x002e, 0x2004, 0xa81a, 0x2001, 0x002f,
-	0x2004, 0xa81e, 0x2001, 0x0030, 0x2004, 0xa822, 0x2001, 0x0031,
-	0x2004, 0xa826, 0x2001, 0x0034, 0x2004, 0xa82a, 0x2001, 0x0035,
-	0x2004, 0xa82e, 0x2001, 0x002a, 0x2004, 0x9080, 0x0003, 0x9084,
-	0x00fc, 0x8004, 0xa816, 0x080c, 0x3df7, 0x0928, 0x7014, 0x2048,
-	0xad2c, 0xac28, 0xab1c, 0xaa18, 0xa930, 0xa808, 0xd0b4, 0x1120,
-	0x2029, 0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc,
-	0x003f, 0x9084, 0xffc0, 0x9080, 0x001b, 0x080c, 0x4c8a, 0x701f,
-	0x3d34, 0x7023, 0x0001, 0x012e, 0x0005, 0x080c, 0xacfc, 0x0046,
-	0x0086, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6,
-	0x080c, 0x3bd8, 0x2001, 0x19a0, 0x2003, 0x0000, 0x2021, 0x000a,
-	0x2061, 0x0100, 0x6104, 0x0016, 0x60bb, 0x0000, 0x60bf, 0x32e1,
-	0x60bf, 0x0012, 0x080c, 0x3e66, 0x080c, 0x3e25, 0x00f6, 0x00e6,
-	0x0086, 0x2940, 0x2071, 0x19e8, 0x2079, 0x0090, 0x00d6, 0x2069,
-	0x0000, 0x6884, 0xd0b4, 0x0140, 0x2001, 0x0035, 0x2004, 0x780e,
-	0x2001, 0x0034, 0x2004, 0x780a, 0x00de, 0x2011, 0x0001, 0x080c,
-	0x41db, 0x008e, 0x00ee, 0x00fe, 0x080c, 0x40fd, 0x080c, 0x402a,
-	0x05b8, 0x2001, 0x020b, 0x2004, 0x9084, 0x0140, 0x1db8, 0x080c,
-	0x424f, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe, 0x908c, 0x0070,
-	0x1560, 0x2071, 0x0200, 0x7037, 0x0000, 0x7050, 0x9084, 0xff00,
-	0x9086, 0x3200, 0x1510, 0x7037, 0x0001, 0x7050, 0x9084, 0xff00,
-	0x9086, 0xe100, 0x11d0, 0x7037, 0x0000, 0x7054, 0x7037, 0x0000,
-	0x715c, 0x9106, 0x1190, 0x2001, 0x1820, 0x2004, 0x9106, 0x1168,
-	0x00c6, 0x2061, 0x0100, 0x6024, 0x9084, 0x1e00, 0x00ce, 0x0138,
-	0x080c, 0x4034, 0x080c, 0x3e20, 0x0058, 0x080c, 0x3e20, 0x080c,
-	0x4173, 0x080c, 0x40f3, 0x2001, 0x020b, 0x2004, 0xd0e4, 0x0dd8,
-	0x2001, 0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002,
-	0x001e, 0x6106, 0x2011, 0x020d, 0x2013, 0x0020, 0x60bb, 0x0000,
-	0x60bf, 0x0108, 0x60bf, 0x0012, 0x2001, 0x0004, 0x200c, 0x918c,
-	0xfffd, 0x2102, 0x080c, 0x1352, 0x2009, 0x0028, 0x080c, 0x2220,
-	0x2001, 0x0227, 0x200c, 0x2102, 0x080c, 0xad18, 0x00fe, 0x00ee,
-	0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e, 0x008e, 0x004e, 0x2001,
-	0x19a0, 0x2004, 0x9005, 0x1118, 0x012e, 0x0804, 0x368d, 0x012e,
-	0x2021, 0x400c, 0x0804, 0x368f, 0x0016, 0x0026, 0x0036, 0x0046,
-	0x0056, 0x0076, 0x0086, 0x0096, 0x00d6, 0x0156, 0x7014, 0x2048,
-	0x7020, 0x20a8, 0x8000, 0x7022, 0xa804, 0x9005, 0x0904, 0x3d90,
-	0x2048, 0x1f04, 0x3d44, 0x7068, 0x2040, 0xa28c, 0xa390, 0xa494,
-	0xa598, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029, 0x0000, 0x2021,
-	0x0000, 0x0096, 0x7014, 0x2048, 0xa864, 0x009e, 0x9086, 0x0103,
-	0x0170, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0,
-	0x9080, 0x001b, 0x080c, 0x4c8a, 0x701f, 0x3d34, 0x00b0, 0x8906,
-	0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x001b,
-	0x21a8, 0x27e0, 0x2098, 0x27e8, 0x20a0, 0x0006, 0x080c, 0x0fd6,
-	0x000e, 0x080c, 0x4c8d, 0x701f, 0x3d34, 0x015e, 0x00de, 0x009e,
-	0x008e, 0x007e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005,
-	0x7014, 0x2048, 0xa864, 0x9086, 0x0103, 0x1118, 0x701f, 0x3df5,
-	0x0450, 0x7014, 0x2048, 0xa868, 0xc0fd, 0xa86a, 0x2009, 0x007f,
-	0x080c, 0x6749, 0x0110, 0x9006, 0x0030, 0xb813, 0x00ff, 0xb817,
-	0xfffd, 0x080c, 0xd409, 0x015e, 0x00de, 0x009e, 0x008e, 0x007e,
-	0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0904, 0x36bf, 0x0016,
-	0x0026, 0x0036, 0x0046, 0x0056, 0x0076, 0x0086, 0x0096, 0x00d6,
-	0x0156, 0x701f, 0x3dc7, 0x7007, 0x0003, 0x0804, 0x3d85, 0xa830,
-	0x9086, 0x0100, 0x2021, 0x400c, 0x0904, 0x368f, 0x0076, 0xad10,
-	0xac0c, 0xab24, 0xaa20, 0xa930, 0xa808, 0xd0b4, 0x1120, 0x2029,
-	0x0000, 0x2021, 0x0000, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f,
-	0x9084, 0xffc0, 0x9080, 0x001b, 0x21a8, 0x27e0, 0x2098, 0x27e8,
-	0x20a0, 0x0006, 0x080c, 0x0fd6, 0x000e, 0x080c, 0x4c8d, 0x007e,
-	0x701f, 0x3d34, 0x7023, 0x0001, 0x0005, 0x0804, 0x368d, 0x0156,
-	0x00c6, 0xa814, 0x908a, 0x001e, 0x0218, 0xa833, 0x001e, 0x0010,
-	0xa832, 0x0078, 0x81ff, 0x0168, 0x0016, 0x080c, 0x4c41, 0x001e,
-	0x0130, 0xa800, 0x2040, 0xa008, 0xa80a, 0x2100, 0x0c58, 0x9006,
-	0x0010, 0x9085, 0x0001, 0x00ce, 0x015e, 0x0005, 0x0006, 0x00f6,
-	0x2079, 0x0000, 0x7880, 0x9086, 0x0044, 0x00fe, 0x000e, 0x0005,
-	0x2001, 0x19a0, 0x2003, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x00c6,
-	0x2061, 0x0200, 0x2001, 0x19ab, 0x2004, 0x601a, 0x2061, 0x0100,
-	0x2001, 0x19aa, 0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x080c,
-	0x4c41, 0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001,
-	0x002e, 0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2061,
-	0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036, 0x2009,
-	0x0040, 0x080c, 0x2220, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8,
-	0xa86e, 0x601a, 0xa873, 0x0000, 0x601f, 0x0000, 0x78ca, 0x9006,
-	0x600a, 0x600e, 0x00ce, 0x00ee, 0x00fe, 0x0005, 0x00e6, 0x080c,
-	0x4c41, 0x2940, 0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a,
-	0x2001, 0x0030, 0x2004, 0xa866, 0x2001, 0x0031, 0x2004, 0xa86a,
-	0x2001, 0x002a, 0x2004, 0x9084, 0xfff8, 0xa86e, 0xa873, 0x0000,
-	0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x0300, 0x2003, 0x0000,
-	0x2001, 0x020d, 0x2003, 0x0000, 0x2001, 0x0004, 0x200c, 0x918d,
-	0x0002, 0x2102, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x81ff,
-	0x0148, 0x080c, 0x2a77, 0x1130, 0x9006, 0x080c, 0x29ca, 0x9006,
-	0x080c, 0x29ad, 0x2001, 0x199f, 0x2003, 0x0000, 0x7884, 0x9084,
-	0x0007, 0x0002, 0x3eb5, 0x3eb6, 0x3eb7, 0x3eb2, 0x3eb2, 0x3eb2,
-	0x3eb2, 0x3eb2, 0x012e, 0x0804, 0x36c2, 0x0ce0, 0x0cd8, 0x080c,
-	0x779e, 0x1128, 0x012e, 0x2009, 0x0016, 0x0804, 0x36bf, 0x81ff,
-	0x0128, 0x012e, 0x2021, 0x400b, 0x0804, 0x368f, 0x2001, 0x0141,
-	0x2004, 0xd0dc, 0x0db0, 0x080c, 0xacfc, 0x0086, 0x0096, 0x00a6,
-	0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x080c, 0x3bd8, 0x2009,
-	0x0101, 0x210c, 0x0016, 0x7ec8, 0x7dcc, 0x9006, 0x2068, 0x2060,
-	0x2058, 0x080c, 0x432a, 0x080c, 0x427a, 0x903e, 0x2720, 0x00f6,
-	0x00e6, 0x0086, 0x2940, 0x2071, 0x19e8, 0x2079, 0x0090, 0x00d6,
-	0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x68d4, 0x780e, 0x68d0,
-	0x780a, 0x00de, 0x2011, 0x0001, 0x080c, 0x41db, 0x080c, 0x2a7f,
-	0x080c, 0x2a7f, 0x080c, 0x2a7f, 0x080c, 0x2a7f, 0x080c, 0x41db,
-	0x008e, 0x00ee, 0x00fe, 0x080c, 0x40fd, 0x2009, 0x9c40, 0x8109,
-	0x11b0, 0x080c, 0x4034, 0x2001, 0x0004, 0x200c, 0x918c, 0xfffd,
-	0x2102, 0x001e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae,
-	0x009e, 0x008e, 0x2009, 0x0017, 0x080c, 0x36bf, 0x0cf8, 0x2001,
-	0x020b, 0x2004, 0x9084, 0x0140, 0x1d10, 0x00f6, 0x2079, 0x0000,
-	0x7884, 0x00fe, 0xd0bc, 0x0178, 0x2001, 0x0201, 0x200c, 0x81ff,
-	0x0150, 0x080c, 0x40db, 0x2d00, 0x9c05, 0x9b05, 0x0120, 0x080c,
-	0x4034, 0x0804, 0x3fdd, 0x080c, 0x424f, 0x080c, 0x4173, 0x080c,
-	0x40be, 0x080c, 0x40f3, 0x00f6, 0x2079, 0x0100, 0x7824, 0xd0ac,
-	0x0130, 0x8b58, 0x080c, 0x4034, 0x00fe, 0x0804, 0x3fdd, 0x00fe,
-	0x080c, 0x402a, 0x1150, 0x8d68, 0x2001, 0x0032, 0x2602, 0x2001,
-	0x0033, 0x2502, 0x080c, 0x4034, 0x0080, 0x87ff, 0x0138, 0x2001,
-	0x0201, 0x2004, 0x9005, 0x1908, 0x8739, 0x0038, 0x2001, 0x1a6e,
-	0x2004, 0x9086, 0x0000, 0x1904, 0x3f2d, 0x2001, 0x032f, 0x2003,
-	0x00f6, 0x8631, 0x1208, 0x8529, 0x2500, 0x9605, 0x0904, 0x3fdd,
-	0x7884, 0xd0bc, 0x0128, 0x2d00, 0x9c05, 0x9b05, 0x1904, 0x3fdd,
-	0xa013, 0x0019, 0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac,
-	0x1148, 0x2001, 0x1a6e, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003,
-	0x0009, 0x0030, 0xa017, 0x0001, 0x78b4, 0x9005, 0x0108, 0xa016,
-	0x2800, 0xa05a, 0x2009, 0x0040, 0x080c, 0x2220, 0x2900, 0xa85a,
-	0xa813, 0x0019, 0x7884, 0xd0a4, 0x1180, 0xa817, 0x0000, 0x00c6,
-	0x20a9, 0x0004, 0x2061, 0x0090, 0x602b, 0x0008, 0x2001, 0x0203,
-	0x2004, 0x1f04, 0x3fb4, 0x00ce, 0x0030, 0xa817, 0x0001, 0x78b0,
-	0x9005, 0x0108, 0xa816, 0x00f6, 0x00c6, 0x2079, 0x0100, 0x2061,
-	0x0090, 0x7827, 0x0002, 0x2001, 0x002a, 0x2004, 0x9084, 0xfff8,
-	0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6, 0x000e,
-	0x78ca, 0x00ce, 0x00fe, 0x0804, 0x3ee7, 0x001e, 0x00c6, 0x2001,
-	0x032a, 0x2003, 0x0004, 0x2061, 0x0100, 0x6027, 0x0002, 0x6106,
-	0x2011, 0x020d, 0x2013, 0x0020, 0x2001, 0x0004, 0x200c, 0x918c,
-	0xfffd, 0x2102, 0x080c, 0x1352, 0x7884, 0x9084, 0x0003, 0x9086,
-	0x0002, 0x01b0, 0x2009, 0x0028, 0x080c, 0x2220, 0x2001, 0x0227,
-	0x200c, 0x2102, 0x6050, 0x9084, 0xb7ff, 0x080c, 0x2b29, 0x6052,
-	0x602f, 0x0000, 0x604b, 0xf7f7, 0x6043, 0x0090, 0x6043, 0x0010,
-	0x080c, 0xad18, 0x00ce, 0x2d08, 0x2c10, 0x2b18, 0x2b00, 0x9c05,
-	0x9d05, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x00be, 0x00ae, 0x009e,
-	0x008e, 0x1118, 0x012e, 0x0804, 0x368d, 0x012e, 0x2021, 0x400c,
-	0x0804, 0x368f, 0x9085, 0x0001, 0x1d04, 0x4033, 0x2091, 0x6000,
-	0x8420, 0x9486, 0x0064, 0x0005, 0x2001, 0x0105, 0x2003, 0x0010,
-	0x2001, 0x032a, 0x2003, 0x0004, 0x2001, 0x1a6e, 0x2003, 0x0000,
-	0x0071, 0x2009, 0x0048, 0x080c, 0x2220, 0x2001, 0x0227, 0x2024,
-	0x2402, 0x2001, 0x0109, 0x2003, 0x4000, 0x9026, 0x0005, 0x00f6,
-	0x00e6, 0x2071, 0x19e8, 0x7054, 0x9086, 0x0000, 0x0520, 0x2079,
-	0x0090, 0x2009, 0x0206, 0x2104, 0x2009, 0x0203, 0x210c, 0x9106,
-	0x1120, 0x2009, 0x0040, 0x080c, 0x2220, 0x782c, 0xd0fc, 0x0d88,
-	0x080c, 0x424f, 0x7054, 0x9086, 0x0000, 0x1d58, 0x782b, 0x0004,
-	0x782c, 0xd0ac, 0x1de8, 0x2009, 0x0040, 0x080c, 0x2220, 0x782b,
-	0x0002, 0x7057, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079,
-	0x0100, 0x2001, 0x1818, 0x200c, 0x7932, 0x7936, 0x080c, 0x26d5,
-	0x080c, 0x2af6, 0x080c, 0x2b29, 0x784b, 0xf7f7, 0x7843, 0x0090,
-	0x7843, 0x0010, 0x7850, 0xc0e5, 0x7852, 0x2019, 0x61a8, 0x7820,
-	0xd09c, 0x0110, 0x8319, 0x1dd8, 0x7850, 0xc0e4, 0x7852, 0x2011,
-	0x0048, 0x080c, 0x2ad3, 0x7843, 0x0040, 0x2019, 0x01f4, 0xa001,
-	0xa001, 0x8319, 0x1de0, 0x2001, 0x0100, 0x080c, 0x2a99, 0x2011,
-	0x0020, 0x080c, 0x2ad3, 0x7843, 0x0000, 0x9006, 0x080c, 0x2a99,
-	0x2011, 0x0048, 0x080c, 0x2ad3, 0x00fe, 0x0005, 0x7884, 0xd0ac,
-	0x11c8, 0x00f6, 0x00e6, 0x2071, 0x1a6e, 0x2079, 0x0320, 0x2001,
-	0x0201, 0x2004, 0x9005, 0x0160, 0x7000, 0x9086, 0x0000, 0x1140,
-	0x0051, 0xd0bc, 0x0108, 0x8738, 0x7003, 0x0003, 0x782b, 0x0019,
-	0x00ee, 0x00fe, 0x0005, 0x00f6, 0x2079, 0x0300, 0x78bc, 0x00fe,
-	0x908c, 0x0070, 0x0178, 0x2009, 0x0032, 0x260a, 0x2009, 0x0033,
-	0x250a, 0xd0b4, 0x0108, 0x8c60, 0xd0ac, 0x0108, 0x8d68, 0xd0a4,
-	0x0108, 0x8b58, 0x0005, 0x00f6, 0x2079, 0x0200, 0x781c, 0xd084,
-	0x0110, 0x7837, 0x0050, 0x00fe, 0x0005, 0x00e6, 0x2071, 0x0100,
-	0x2001, 0x19ab, 0x2004, 0x70e2, 0x080c, 0x3e16, 0x1188, 0x2001,
-	0x1820, 0x2004, 0x2009, 0x181f, 0x210c, 0x918c, 0x00ff, 0x706e,
-	0x716a, 0x7066, 0x918d, 0x3200, 0x7162, 0x7073, 0xe109, 0x0080,
-	0x702c, 0x9085, 0x0002, 0x702e, 0x2009, 0x1818, 0x210c, 0x716e,
-	0x7063, 0x0100, 0x7166, 0x719e, 0x706b, 0x0000, 0x7073, 0x0809,
-	0x7077, 0x0008, 0x7078, 0x9080, 0x0100, 0x707a, 0x7080, 0x8000,
-	0x7082, 0x7087, 0xaaaa, 0x9006, 0x708a, 0x708e, 0x707e, 0x70d6,
-	0x70ab, 0x0036, 0x70af, 0x95d5, 0x7014, 0x9084, 0x1984, 0x9085,
-	0x0092, 0x7016, 0x080c, 0x424f, 0x00f6, 0x2071, 0x1a6e, 0x2079,
-	0x0320, 0x00d6, 0x2069, 0x0000, 0x6884, 0xd0b4, 0x0120, 0x689c,
-	0x780e, 0x6898, 0x780a, 0x00de, 0x080c, 0x3e16, 0x0140, 0x2001,
-	0x199f, 0x200c, 0x2003, 0x0001, 0x918e, 0x0001, 0x0120, 0x2009,
-	0x03e8, 0x8109, 0x1df0, 0x792c, 0xd1fc, 0x0110, 0x782b, 0x0004,
-	0x2011, 0x0011, 0x080c, 0x41db, 0x2011, 0x0001, 0x080c, 0x41db,
-	0x00fe, 0x00ee, 0x0005, 0x00f6, 0x00e6, 0x2071, 0x1a6e, 0x2079,
-	0x0320, 0x792c, 0xd1fc, 0x0904, 0x41d8, 0x782b, 0x0002, 0x9026,
-	0xd19c, 0x1904, 0x41d4, 0x7000, 0x0002, 0x41d8, 0x4189, 0x41b9,
-	0x41d4, 0xd1bc, 0x1170, 0xd1dc, 0x1190, 0x8001, 0x7002, 0x2011,
-	0x0001, 0x080c, 0x41db, 0x0904, 0x41d8, 0x080c, 0x41db, 0x0804,
-	0x41d8, 0x00f6, 0x2079, 0x0300, 0x78bf, 0x0000, 0x00fe, 0x7810,
-	0x7914, 0x782b, 0x0004, 0x7812, 0x7916, 0x2001, 0x0201, 0x200c,
-	0x81ff, 0x0de8, 0x080c, 0x40db, 0x2009, 0x0001, 0x00f6, 0x2079,
-	0x0300, 0x78b8, 0x00fe, 0xd0ec, 0x0110, 0x2009, 0x0011, 0x792a,
-	0x00f8, 0x8001, 0x7002, 0x9184, 0x0880, 0x1140, 0x782c, 0xd0fc,
-	0x1904, 0x417d, 0x2011, 0x0001, 0x00b1, 0x0090, 0xa010, 0x9092,
-	0x0004, 0x9086, 0x0015, 0x1120, 0xa000, 0xa05a, 0x2011, 0x0031,
-	0xa212, 0xd1dc, 0x1960, 0x0828, 0x782b, 0x0004, 0x7003, 0x0000,
-	0x00ee, 0x00fe, 0x0005, 0xa014, 0x9005, 0x0550, 0x8001, 0x0036,
-	0x0096, 0xa016, 0xa058, 0x2048, 0xa010, 0x2009, 0x0031, 0x911a,
-	0x831c, 0x831c, 0x938a, 0x0007, 0x1a0c, 0x0d85, 0x9398, 0x4209,
-	0x231d, 0x083f, 0x9080, 0x0004, 0x7a2a, 0x7100, 0x8108, 0x7102,
-	0x009e, 0x003e, 0x908a, 0x0035, 0x1140, 0x0096, 0xa058, 0x2048,
-	0xa804, 0xa05a, 0x2001, 0x0019, 0x009e, 0xa012, 0x9085, 0x0001,
-	0x0005, 0x4246, 0x423d, 0x4234, 0x422b, 0x4222, 0x4219, 0x4210,
-	0xa964, 0x7902, 0xa968, 0x7906, 0xa96c, 0x7912, 0xa970, 0x7916,
-	0x0005, 0xa974, 0x7902, 0xa978, 0x7906, 0xa97c, 0x7912, 0xa980,
-	0x7916, 0x0005, 0xa984, 0x7902, 0xa988, 0x7906, 0xa98c, 0x7912,
-	0xa990, 0x7916, 0x0005, 0xa994, 0x7902, 0xa998, 0x7906, 0xa99c,
-	0x7912, 0xa9a0, 0x7916, 0x0005, 0xa9a4, 0x7902, 0xa9a8, 0x7906,
-	0xa9ac, 0x7912, 0xa9b0, 0x7916, 0x0005, 0xa9b4, 0x7902, 0xa9b8,
-	0x7906, 0xa9bc, 0x7912, 0xa9c0, 0x7916, 0x0005, 0xa9c4, 0x7902,
-	0xa9c8, 0x7906, 0xa9cc, 0x7912, 0xa9d0, 0x7916, 0x0005, 0x00f6,
-	0x00e6, 0x0086, 0x2071, 0x19e8, 0x2079, 0x0090, 0x792c, 0xd1fc,
-	0x01e8, 0x782b, 0x0002, 0x2940, 0x9026, 0x7054, 0x0002, 0x4276,
-	0x4262, 0x426d, 0x8001, 0x7056, 0xd19c, 0x1180, 0x2011, 0x0001,
-	0x080c, 0x41db, 0x190c, 0x41db, 0x0048, 0x8001, 0x7056, 0x782c,
-	0xd0fc, 0x1d38, 0x2011, 0x0001, 0x080c, 0x41db, 0x008e, 0x00ee,
-	0x00fe, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x2061, 0x0200,
-	0x2001, 0x19ab, 0x2004, 0x601a, 0x2061, 0x0100, 0x2001, 0x19aa,
-	0x2004, 0x60ce, 0x6104, 0xc1ac, 0x6106, 0x2001, 0x002c, 0x2004,
-	0x9005, 0x0520, 0x2038, 0x2001, 0x002e, 0x2024, 0x2001, 0x002f,
-	0x201c, 0x080c, 0x4c41, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a,
-	0x978a, 0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708,
-	0x903e, 0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e,
-	0x080c, 0x42f2, 0x1d68, 0x2900, 0xa85a, 0x00d0, 0x080c, 0x4c41,
-	0xa813, 0x0019, 0xa817, 0x0001, 0x2900, 0xa85a, 0x2001, 0x002e,
-	0x2004, 0xa866, 0x2001, 0x002f, 0x2004, 0xa86a, 0x2001, 0x002a,
-	0x2004, 0x9084, 0xfff8, 0xa86e, 0x2001, 0x002b, 0x2004, 0xa872,
-	0x2061, 0x0090, 0x2079, 0x0100, 0x2001, 0x19aa, 0x2004, 0x6036,
-	0x2009, 0x0040, 0x080c, 0x2220, 0x2001, 0x002a, 0x2004, 0x9084,
-	0xfff8, 0x601a, 0x0006, 0x2001, 0x002b, 0x2004, 0x601e, 0x78c6,
-	0x000e, 0x78ca, 0x9006, 0x600a, 0x600e, 0x008e, 0x00ce, 0x00ee,
-	0x00fe, 0x0005, 0x00e6, 0x2071, 0x0080, 0xaa60, 0x22e8, 0x20a0,
-	0x20e1, 0x0000, 0x2099, 0x0088, 0x702b, 0x0026, 0x7402, 0x7306,
-	0x9006, 0x700a, 0x700e, 0x810b, 0x810b, 0x21a8, 0x810b, 0x7112,
-	0x702b, 0x0041, 0x702c, 0xd0fc, 0x0de8, 0x702b, 0x0002, 0x702b,
-	0x0040, 0x4005, 0x7400, 0x7304, 0x87ff, 0x0190, 0x0086, 0x0096,
-	0x2940, 0x0086, 0x080c, 0x4c41, 0x008e, 0xa058, 0x00a6, 0x2050,
-	0x2900, 0xb006, 0xa05a, 0x00ae, 0x009e, 0x008e, 0x9085, 0x0001,
-	0x00ee, 0x0005, 0x00e6, 0x2001, 0x002d, 0x2004, 0x9005, 0x0528,
-	0x2038, 0x2001, 0x0030, 0x2024, 0x2001, 0x0031, 0x201c, 0x080c,
-	0x4c41, 0x2940, 0xa813, 0x0019, 0xaf16, 0x2900, 0xa85a, 0x978a,
-	0x0007, 0x0220, 0x2138, 0x2009, 0x0007, 0x0010, 0x2708, 0x903e,
-	0x0096, 0xa858, 0x2048, 0xa85c, 0x9080, 0x0019, 0x009e, 0x080c,
-	0x42f2, 0x1d68, 0x2900, 0xa85a, 0x00d8, 0x080c, 0x4c41, 0x2940,
-	0xa013, 0x0019, 0xa017, 0x0001, 0x2800, 0xa05a, 0x2001, 0x0030,
-	0x2004, 0xa066, 0x2001, 0x0031, 0x2004, 0xa06a, 0x2001, 0x002a,
-	0x2004, 0x9084, 0xfff8, 0xa06e, 0x2001, 0x002b, 0x2004, 0xa072,
-	0x2001, 0x032a, 0x2003, 0x0004, 0x7884, 0xd0ac, 0x1180, 0x2001,
-	0x0101, 0x200c, 0x918d, 0x0200, 0x2102, 0xa017, 0x0000, 0x2001,
-	0x1a6e, 0x2003, 0x0003, 0x2001, 0x032a, 0x2003, 0x0009, 0x2001,
-	0x0300, 0x2003, 0x0000, 0x2001, 0x020d, 0x2003, 0x0000, 0x2001,
-	0x0004, 0x200c, 0x918d, 0x0002, 0x2102, 0x00ee, 0x0005, 0x0126,
-	0x2091, 0x8000, 0x20a9, 0x0007, 0x20a1, 0x1840, 0x20e9, 0x0001,
-	0x9006, 0x4004, 0x20a9, 0x0014, 0x20a1, 0xffec, 0x20e9, 0x0000,
-	0x9006, 0x4004, 0x2009, 0x013c, 0x200a, 0x012e, 0x7880, 0x9086,
-	0x0052, 0x0108, 0x0005, 0x0804, 0x368d, 0x7d98, 0x7c9c, 0x0804,
-	0x3791, 0x080c, 0x779e, 0x190c, 0x6162, 0x6040, 0x9084, 0x0020,
-	0x09b1, 0x2069, 0x1847, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88,
-	0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c8a, 0x701f, 0x43d1,
-	0x0005, 0x080c, 0x584f, 0x1130, 0x3b00, 0x3a08, 0xc194, 0xc095,
-	0x20d8, 0x21d0, 0x2069, 0x1847, 0x6800, 0x9005, 0x0904, 0x36c2,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x6804, 0x0118, 0xc0a4, 0xc0ac,
-	0x6806, 0xd0ac, 0x0118, 0xd0a4, 0x0904, 0x36c2, 0xd094, 0x00c6,
-	0x2061, 0x0100, 0x6104, 0x0138, 0x6200, 0x9292, 0x0005, 0x0218,
-	0x918c, 0xffdf, 0x0010, 0x918d, 0x0020, 0x6106, 0x00ce, 0xd08c,
-	0x00c6, 0x2061, 0x0100, 0x6104, 0x0118, 0x918d, 0x0010, 0x0010,
-	0x918c, 0xffef, 0x6106, 0x00ce, 0xd084, 0x0158, 0x6a28, 0x928a,
-	0x007f, 0x1a04, 0x36c2, 0x9288, 0x348e, 0x210d, 0x918c, 0x00ff,
-	0x6166, 0xd0dc, 0x0130, 0x6828, 0x908a, 0x007f, 0x1a04, 0x36c2,
-	0x605e, 0x6888, 0x9084, 0x0030, 0x8004, 0x8004, 0x8004, 0x8004,
-	0x0006, 0x2009, 0x19b2, 0x9080, 0x27d0, 0x2005, 0x200a, 0x2008,
-	0x2001, 0x0018, 0x080c, 0xaced, 0x2009, 0x0390, 0x200b, 0x0400,
-	0x000e, 0x2009, 0x19b3, 0x9080, 0x27d4, 0x2005, 0x200a, 0x6808,
-	0x908a, 0x0100, 0x0a04, 0x36c2, 0x908a, 0x0841, 0x1a04, 0x36c2,
-	0x9084, 0x0007, 0x1904, 0x36c2, 0x680c, 0x9005, 0x0904, 0x36c2,
-	0x6810, 0x9005, 0x0904, 0x36c2, 0x6848, 0x6940, 0x910a, 0x1a04,
-	0x36c2, 0x8001, 0x0904, 0x36c2, 0x684c, 0x6944, 0x910a, 0x1a04,
-	0x36c2, 0x8001, 0x0904, 0x36c2, 0x6814, 0x908c, 0x00ff, 0x614e,
-	0x8007, 0x9084, 0x00ff, 0x6052, 0x080c, 0x7ae7, 0x080c, 0x6cfc,
-	0x080c, 0x6d66, 0x6808, 0x602a, 0x080c, 0x2192, 0x2009, 0x0170,
-	0x200b, 0x0080, 0xa001, 0xa001, 0x200b, 0x0000, 0x0036, 0x6b08,
-	0x080c, 0x272f, 0x003e, 0x6000, 0x9086, 0x0000, 0x1904, 0x456d,
-	0x6818, 0x691c, 0x6a20, 0x6b24, 0x8007, 0x810f, 0x8217, 0x831f,
-	0x6016, 0x611a, 0x621e, 0x6322, 0x6c04, 0xd4f4, 0x0148, 0x6830,
-	0x6934, 0x6a38, 0x6b3c, 0x8007, 0x810f, 0x8217, 0x831f, 0x0010,
-	0x9084, 0xf0ff, 0x6006, 0x610a, 0x620e, 0x6312, 0x8007, 0x810f,
-	0x8217, 0x831f, 0x20a9, 0x0004, 0x20a1, 0x19b4, 0x20e9, 0x0001,
-	0x4001, 0x20a9, 0x0004, 0x20a1, 0x19ce, 0x20e9, 0x0001, 0x4001,
-	0x080c, 0x8b26, 0x00c6, 0x900e, 0x20a9, 0x0001, 0x6b70, 0xd384,
-	0x01c8, 0x0020, 0x839d, 0x12b0, 0x3508, 0x8109, 0x080c, 0x80fe,
-	0x6878, 0x6016, 0x6874, 0x2008, 0x9084, 0xff00, 0x8007, 0x600a,
-	0x9184, 0x00ff, 0x6006, 0x8108, 0x1118, 0x6003, 0x0003, 0x0010,
-	0x6003, 0x0001, 0x1f04, 0x44c2, 0x00ce, 0x00c6, 0x2061, 0x199c,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x11a8, 0x6a88, 0x9284, 0xc000,
-	0x2010, 0x9286, 0x0000, 0x1158, 0x2063, 0x0000, 0x2001, 0x0001,
-	0x080c, 0x29ca, 0x2001, 0x0001, 0x080c, 0x29ad, 0x0088, 0x9286,
-	0x4000, 0x1148, 0x2063, 0x0001, 0x9006, 0x080c, 0x29ca, 0x9006,
-	0x080c, 0x29ad, 0x0028, 0x9286, 0x8000, 0x1d30, 0x2063, 0x0002,
-	0x00ce, 0x00e6, 0x2c70, 0x080c, 0x0ed3, 0x00ee, 0x080c, 0x2af6,
-	0x080c, 0x2b29, 0x6888, 0xd0ec, 0x0130, 0x2011, 0x0114, 0x2204,
-	0x9085, 0x0180, 0x2012, 0x6a80, 0x9284, 0x0030, 0x9086, 0x0030,
-	0x1128, 0x9294, 0xffcf, 0x9295, 0x0020, 0x6a82, 0x2001, 0x197c,
-	0x6a80, 0x9294, 0x0030, 0x928e, 0x0000, 0x0170, 0x928e, 0x0010,
-	0x0118, 0x928e, 0x0020, 0x0140, 0x2003, 0xaaaa, 0x080c, 0x27a4,
-	0x2001, 0x196d, 0x2102, 0x0008, 0x2102, 0x00c6, 0x2061, 0x0100,
-	0x602f, 0x0040, 0x602f, 0x0000, 0x00ce, 0x080c, 0x779e, 0x0128,
-	0x080c, 0x5128, 0x0110, 0x080c, 0x26f5, 0x60d4, 0x9005, 0x01c0,
-	0x6003, 0x0001, 0x2009, 0x4555, 0x00e0, 0x080c, 0x779e, 0x1168,
-	0x2011, 0x7612, 0x080c, 0x8993, 0x2011, 0x7605, 0x080c, 0x8a9f,
-	0x080c, 0x7abb, 0x080c, 0x76cd, 0x0040, 0x080c, 0x6058, 0x0028,
-	0x6003, 0x0004, 0x2009, 0x456d, 0x0020, 0x080c, 0x6b73, 0x0804,
-	0x368d, 0x2001, 0x0170, 0x2004, 0x9084, 0x00ff, 0x9086, 0x004c,
-	0x1118, 0x2091, 0x31bd, 0x0817, 0x2091, 0x313d, 0x0817, 0x6000,
-	0x9086, 0x0000, 0x0904, 0x36bf, 0x2069, 0x1847, 0x7890, 0x6842,
-	0x7894, 0x6846, 0x2d00, 0x2009, 0x0030, 0x7a8c, 0x7b88, 0x7c9c,
-	0x7d98, 0x2039, 0x0001, 0x0804, 0x4c8d, 0x9006, 0x080c, 0x26f5,
-	0x81ff, 0x1904, 0x36bf, 0x080c, 0x779e, 0x11b0, 0x080c, 0x7ab6,
-	0x080c, 0x619d, 0x080c, 0x3482, 0x0118, 0x6130, 0xc18d, 0x6132,
-	0x080c, 0xd645, 0x0130, 0x080c, 0x77c1, 0x1118, 0x080c, 0x7772,
-	0x0038, 0x080c, 0x76cd, 0x0020, 0x080c, 0x6162, 0x080c, 0x6058,
-	0x0804, 0x368d, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x779e, 0x1110,
-	0x0804, 0x36bf, 0x0126, 0x2091, 0x8000, 0x6194, 0x81ff, 0x0190,
-	0x704f, 0x0000, 0x2001, 0x1d80, 0x2009, 0x0040, 0x7a8c, 0x7b88,
-	0x7c9c, 0x7d98, 0x2039, 0x0001, 0x080c, 0x4c8d, 0x701f, 0x368b,
-	0x012e, 0x0005, 0x704f, 0x0001, 0x00d6, 0x2069, 0x1d80, 0x20a9,
-	0x0040, 0x20e9, 0x0001, 0x20a1, 0x1d80, 0x2019, 0xffff, 0x4304,
-	0x655c, 0x9588, 0x348e, 0x210d, 0x918c, 0x00ff, 0x216a, 0x900e,
-	0x2011, 0x0002, 0x2100, 0x9506, 0x01a8, 0x080c, 0x67b4, 0x1190,
-	0xb814, 0x821c, 0x0238, 0x9398, 0x1d80, 0x9085, 0xff00, 0x8007,
-	0x201a, 0x0038, 0x9398, 0x1d80, 0x2324, 0x94a4, 0xff00, 0x9405,
-	0x201a, 0x8210, 0x8108, 0x9182, 0x0080, 0x1208, 0x0c18, 0x8201,
-	0x8007, 0x2d0c, 0x9105, 0x206a, 0x00de, 0x20a9, 0x0040, 0x20a1,
-	0x1d80, 0x2099, 0x1d80, 0x080c, 0x60ed, 0x0804, 0x45ca, 0x080c,
-	0x4c74, 0x0904, 0x36c2, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002,
-	0x0804, 0x36bf, 0x080c, 0x5840, 0xd0b4, 0x0558, 0x7884, 0x908e,
-	0x007e, 0x0538, 0x908e, 0x007f, 0x0520, 0x908e, 0x0080, 0x0508,
-	0x080c, 0x347d, 0x1148, 0xb800, 0xd08c, 0x11d8, 0xb804, 0x9084,
-	0x00ff, 0x9086, 0x0006, 0x11a8, 0xa867, 0x0000, 0xa868, 0xc0fd,
-	0xa86a, 0x080c, 0xd0ec, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf,
-	0x7007, 0x0003, 0x701f, 0x4655, 0x0005, 0x080c, 0x4c74, 0x0904,
-	0x36c2, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8, 0x2098, 0xa860,
-	0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x20a9, 0x0008,
-	0x9080, 0x0006, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006,
-	0x2098, 0x080c, 0x0fd6, 0x0070, 0x20a9, 0x0004, 0xa85c, 0x9080,
-	0x000a, 0x20a0, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x000a, 0x2098,
-	0x080c, 0x0fd6, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f, 0x9084,
-	0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0x7a8c, 0x7b88, 0x7c9c,
-	0x7d98, 0x0804, 0x4c8d, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x4c58,
-	0x0904, 0x36c2, 0x080c, 0x6a00, 0x0904, 0x36bf, 0x0058, 0xa878,
-	0x9005, 0x0120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa974, 0xaa94,
-	0x0804, 0x368d, 0x080c, 0x5848, 0x0904, 0x368d, 0x701f, 0x469f,
-	0x7007, 0x0003, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x7888, 0x908a,
-	0x1000, 0x1a04, 0x36c2, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c,
-	0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, 0x36c2, 0x080c, 0x6a85,
-	0x0904, 0x36bf, 0x2019, 0x0004, 0x900e, 0x080c, 0x6a12, 0x0904,
-	0x36bf, 0x7984, 0x7a88, 0x04c9, 0x08a8, 0xa89c, 0x908a, 0x1000,
-	0x12f8, 0x080c, 0x4c72, 0x01e0, 0x080c, 0x6c11, 0x0118, 0x080c,
-	0x6c19, 0x11b0, 0x080c, 0x6a85, 0x2009, 0x0002, 0x0168, 0x2009,
-	0x0002, 0x2019, 0x0004, 0x080c, 0x6a12, 0x2009, 0x0003, 0x0120,
-	0xa998, 0xaa9c, 0x00d1, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010,
-	0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005,
-	0xa897, 0x4000, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, 0x900e,
-	0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x9186, 0x00ff, 0x0110,
-	0x0071, 0x0060, 0x2029, 0x007e, 0x2061, 0x1800, 0x645c, 0x2400,
-	0x9506, 0x0110, 0x2508, 0x0019, 0x8529, 0x1ec8, 0x0005, 0x080c,
-	0x67b4, 0x1138, 0x2200, 0x8003, 0x800b, 0x810b, 0x9108, 0x080c,
-	0x89a1, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x798c, 0x2001, 0x1980,
-	0x918c, 0x8000, 0x2102, 0x080c, 0x4c58, 0x0904, 0x36c2, 0x080c,
-	0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904, 0x36c2, 0x080c, 0x687b,
-	0x0904, 0x36bf, 0x080c, 0x6a09, 0x0904, 0x36bf, 0x2001, 0x1980,
-	0x2004, 0xd0fc, 0x1904, 0x368d, 0x0804, 0x46aa, 0xa9a0, 0x2001,
-	0x1980, 0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c65, 0x01a0,
-	0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1170, 0x080c, 0x687b,
-	0x2009, 0x0002, 0x0128, 0x080c, 0x6a09, 0x1170, 0x2009, 0x0003,
-	0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085,
-	0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x1980,
-	0x2004, 0xd0fc, 0x1128, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018,
-	0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x81ff, 0x1904,
-	0x36bf, 0x798c, 0x2001, 0x197f, 0x918c, 0x8000, 0x2102, 0x080c,
-	0x4c58, 0x0904, 0x36c2, 0x080c, 0x6c11, 0x0120, 0x080c, 0x6c19,
-	0x1904, 0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, 0x080c, 0x69f7,
-	0x0904, 0x36bf, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1904, 0x368d,
-	0x0804, 0x46aa, 0xa9a0, 0x2001, 0x197f, 0x918c, 0x8000, 0xc18d,
-	0x2102, 0x080c, 0x4c65, 0x01a0, 0x080c, 0x6c11, 0x0118, 0x080c,
-	0x6c19, 0x1170, 0x080c, 0x687b, 0x2009, 0x0002, 0x0128, 0x080c,
-	0x69f7, 0x1170, 0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010,
-	0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005,
-	0xa897, 0x4000, 0x2001, 0x197f, 0x2004, 0xd0fc, 0x1128, 0x080c,
-	0x5848, 0x0110, 0x9006, 0x0018, 0x900e, 0x9085, 0x0001, 0x2001,
-	0x0000, 0x0005, 0x6100, 0x0804, 0x368d, 0x080c, 0x4c74, 0x0904,
-	0x36c2, 0x080c, 0x5854, 0x1904, 0x36bf, 0x79a8, 0xd184, 0x1158,
-	0xb834, 0x8007, 0x789e, 0xb830, 0x8007, 0x789a, 0xbb2c, 0x831f,
-	0xba28, 0x8217, 0x0050, 0xb824, 0x8007, 0x789e, 0xb820, 0x8007,
-	0x789a, 0xbb1c, 0x831f, 0xba18, 0x8217, 0xb900, 0x918c, 0x0202,
-	0x0804, 0x368d, 0x78a8, 0x909c, 0x0003, 0xd0ac, 0x1150, 0xd0b4,
-	0x1140, 0x939a, 0x0003, 0x1a04, 0x36bf, 0x625c, 0x7884, 0x9206,
-	0x1548, 0x080c, 0x8b10, 0x2001, 0xffec, 0x2009, 0x000c, 0x7a8c,
-	0x7b88, 0x7c9c, 0x7d98, 0x2039, 0x0000, 0x0006, 0x78a8, 0x9084,
-	0x0080, 0x1118, 0x000e, 0x0804, 0x4c8d, 0x000e, 0x2031, 0x0000,
-	0x2061, 0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e,
-	0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f,
-	0x4862, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x080c, 0x4c74, 0x0904,
-	0x36c2, 0x080c, 0x6c11, 0x1904, 0x36bf, 0x00c6, 0x080c, 0x4c41,
-	0x00ce, 0x0904, 0x36bf, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a,
-	0x7ea8, 0x080c, 0xd092, 0x0904, 0x36bf, 0x7007, 0x0003, 0x701f,
-	0x4866, 0x0005, 0x080c, 0x4397, 0x0804, 0x368d, 0xa830, 0x9086,
-	0x0100, 0x0904, 0x36bf, 0x8906, 0x8006, 0x8007, 0x90bc, 0x003f,
-	0x9084, 0xffc0, 0x9080, 0x001b, 0x2009, 0x000c, 0x7a8c, 0x7b88,
-	0x7c9c, 0x7d98, 0x0804, 0x4c8d, 0x9006, 0x080c, 0x26f5, 0x78a8,
-	0x9084, 0x00ff, 0x9086, 0x00ff, 0x0118, 0x81ff, 0x1904, 0x36bf,
-	0x080c, 0x779e, 0x0110, 0x080c, 0x6162, 0x7888, 0x908a, 0x1000,
-	0x1a04, 0x36c2, 0x7984, 0x9186, 0x00ff, 0x0138, 0x9182, 0x007f,
-	0x1a04, 0x36c2, 0x2100, 0x080c, 0x26bf, 0x0026, 0x00c6, 0x0126,
-	0x2091, 0x8000, 0x2061, 0x1a04, 0x601b, 0x0000, 0x601f, 0x0000,
-	0x607b, 0x0000, 0x607f, 0x0000, 0x080c, 0x779e, 0x1158, 0x080c,
-	0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, 0x77e2, 0x080c,
-	0x76cd, 0x00f0, 0x080c, 0xacfc, 0x080c, 0xb09b, 0x080c, 0xad18,
-	0x2061, 0x0100, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x810f,
-	0x9105, 0x604a, 0x6043, 0x0090, 0x6043, 0x0010, 0x2009, 0x1999,
-	0x200b, 0x0000, 0x2009, 0x002d, 0x2011, 0x6088, 0x080c, 0x8a5d,
-	0x7984, 0x080c, 0x779e, 0x1110, 0x2009, 0x00ff, 0x7a88, 0x080c,
-	0x470d, 0x012e, 0x00ce, 0x002e, 0x0804, 0x368d, 0x7984, 0x080c,
-	0x6749, 0x2b08, 0x1904, 0x36c2, 0x0804, 0x368d, 0x81ff, 0x0120,
-	0x2009, 0x0001, 0x0804, 0x36bf, 0x60dc, 0xd0ac, 0x1130, 0xd09c,
-	0x1120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x080c, 0x4c41, 0x1120,
-	0x2009, 0x0002, 0x0804, 0x36bf, 0x7984, 0x81ff, 0x0904, 0x36c2,
-	0x9192, 0x0021, 0x1a04, 0x36c2, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98,
-	0xa85c, 0x9080, 0x0019, 0x702a, 0xaf60, 0x7736, 0x080c, 0x4c8a,
-	0x701f, 0x4921, 0x7880, 0x9086, 0x006e, 0x0110, 0x701f, 0x52da,
-	0x0005, 0x2009, 0x0080, 0x080c, 0x67b4, 0x1118, 0x080c, 0x6c11,
-	0x0120, 0x2021, 0x400a, 0x0804, 0x368f, 0x00d6, 0x0096, 0xa964,
-	0xaa6c, 0xab70, 0xac74, 0xad78, 0xae7c, 0xa884, 0x90be, 0x0100,
-	0x0904, 0x49ba, 0x90be, 0x0112, 0x0904, 0x49ba, 0x90be, 0x0113,
-	0x0904, 0x49ba, 0x90be, 0x0114, 0x0904, 0x49ba, 0x90be, 0x0117,
-	0x0904, 0x49ba, 0x90be, 0x011a, 0x0904, 0x49ba, 0x90be, 0x011c,
-	0x0904, 0x49ba, 0x90be, 0x0121, 0x0904, 0x49a1, 0x90be, 0x0131,
-	0x0904, 0x49a1, 0x90be, 0x0171, 0x0904, 0x49ba, 0x90be, 0x0173,
-	0x0904, 0x49ba, 0x90be, 0x01a1, 0x1128, 0xa894, 0x8007, 0xa896,
-	0x0804, 0x49c5, 0x90be, 0x0212, 0x0904, 0x49ae, 0x90be, 0x0213,
-	0x05e8, 0x90be, 0x0214, 0x0500, 0x90be, 0x0217, 0x0188, 0x90be,
-	0x021a, 0x1120, 0xa89c, 0x8007, 0xa89e, 0x04e0, 0x90be, 0x021f,
-	0x05c8, 0x90be, 0x0300, 0x05b0, 0x009e, 0x00de, 0x0804, 0x36c2,
-	0x7028, 0x9080, 0x0010, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8,
-	0x20a9, 0x0007, 0x080c, 0x4a03, 0x7028, 0x9080, 0x000e, 0x2098,
-	0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001, 0x080c, 0x4a03,
-	0x00c8, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034, 0x20e0,
-	0x20e8, 0x20a9, 0x0001, 0x080c, 0x4a10, 0x00b8, 0x7028, 0x9080,
-	0x000e, 0x2098, 0x20a0, 0x7034, 0x20e0, 0x20e8, 0x20a9, 0x0001,
-	0x080c, 0x4a10, 0x7028, 0x9080, 0x000c, 0x2098, 0x20a0, 0x7034,
-	0x20e0, 0x20e8, 0x20a9, 0x0001, 0x04f1, 0x00c6, 0x080c, 0x4c41,
-	0x0550, 0xa868, 0xc0fd, 0xa86a, 0xa867, 0x0119, 0x9006, 0xa882,
-	0xa87f, 0x0020, 0xa88b, 0x0001, 0x810b, 0xa9ae, 0xa8b2, 0xaab6,
-	0xabba, 0xacbe, 0xadc2, 0xa9c6, 0xa8ca, 0x00ce, 0x009e, 0x00de,
-	0xa866, 0xa822, 0xa868, 0xc0fd, 0xa86a, 0xa804, 0x2048, 0x080c,
-	0xd0ad, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003,
-	0x701f, 0x49fa, 0x0005, 0x00ce, 0x009e, 0x00de, 0x2009, 0x0002,
-	0x0804, 0x36bf, 0xa820, 0x9086, 0x8001, 0x1904, 0x368d, 0x2009,
-	0x0004, 0x0804, 0x36bf, 0x0016, 0x0026, 0x3510, 0x20a9, 0x0002,
-	0x4002, 0x4104, 0x4004, 0x8211, 0x1dc8, 0x002e, 0x001e, 0x0005,
-	0x0016, 0x0026, 0x0036, 0x0046, 0x3520, 0x20a9, 0x0004, 0x4002,
-	0x4304, 0x4204, 0x4104, 0x4004, 0x8421, 0x1db8, 0x004e, 0x003e,
-	0x002e, 0x001e, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
-	0x36bf, 0x60dc, 0xd0ac, 0x1188, 0x2009, 0x180d, 0x210c, 0xd18c,
-	0x0130, 0xd09c, 0x0120, 0x2009, 0x0016, 0x0804, 0x36bf, 0xd09c,
-	0x1120, 0x2009, 0x0005, 0x0804, 0x36bf, 0x7984, 0x78a8, 0x2040,
-	0x080c, 0xb094, 0x1120, 0x9182, 0x007f, 0x0a04, 0x36c2, 0x9186,
-	0x00ff, 0x0904, 0x36c2, 0x9182, 0x0800, 0x1a04, 0x36c2, 0x7a8c,
-	0x7b88, 0x607c, 0x9306, 0x1158, 0x6080, 0x924e, 0x0904, 0x36c2,
-	0x080c, 0xb094, 0x1120, 0x99cc, 0xff00, 0x0904, 0x36c2, 0x0126,
-	0x2091, 0x8000, 0x2001, 0x180d, 0x2004, 0xd08c, 0x0198, 0x9386,
-	0x00ff, 0x0180, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e,
-	0x0148, 0x918d, 0x8000, 0x080c, 0x6c7f, 0x1120, 0x2001, 0x4009,
-	0x0804, 0x4ac1, 0x080c, 0x4b54, 0x0904, 0x4ac7, 0x0086, 0x90c6,
-	0x4000, 0x008e, 0x1538, 0x00c6, 0x0006, 0x0036, 0xb818, 0xbb1c,
-	0x9305, 0xbb20, 0x9305, 0xbb24, 0x9305, 0xbb28, 0x9305, 0xbb2c,
-	0x9305, 0xbb30, 0x9305, 0xbb34, 0x9305, 0x003e, 0x0570, 0xd88c,
-	0x1128, 0x080c, 0x6c11, 0x0110, 0xc89d, 0x0438, 0x900e, 0x080c,
-	0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x000e,
-	0x00ce, 0x00b8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x0090, 0x90c6,
-	0x4008, 0x1118, 0x2708, 0x2610, 0x0060, 0x90c6, 0x4009, 0x1108,
-	0x0040, 0x90c6, 0x4006, 0x1108, 0x0020, 0x2001, 0x4005, 0x2009,
-	0x000a, 0x2020, 0x012e, 0x0804, 0x368f, 0x000e, 0x00ce, 0x2b00,
-	0x7026, 0x0016, 0x00b6, 0x00c6, 0x00e6, 0x2c70, 0x080c, 0xb1dd,
-	0x0904, 0x4b1c, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x2e58, 0x00ee,
-	0x00e6, 0x00c6, 0x080c, 0x4c41, 0x00ce, 0x2b70, 0x1158, 0x080c,
-	0xb16c, 0x00ee, 0x00ce, 0x00be, 0x001e, 0x012e, 0x2009, 0x0002,
-	0x0804, 0x36bf, 0x900e, 0xa966, 0xa96a, 0x2900, 0x6016, 0xa932,
-	0xa868, 0xc0fd, 0xd88c, 0x0108, 0xc0f5, 0xa86a, 0xd89c, 0x1110,
-	0x080c, 0x3315, 0x6023, 0x0001, 0x9006, 0x080c, 0x66e6, 0xd89c,
-	0x0138, 0x2001, 0x0004, 0x080c, 0x66fa, 0x2009, 0x0003, 0x0030,
-	0x2001, 0x0002, 0x080c, 0x66fa, 0x2009, 0x0002, 0x080c, 0xb20a,
-	0x78a8, 0xd094, 0x0138, 0x00ee, 0x7024, 0x00e6, 0x2058, 0xb8d4,
-	0xc08d, 0xb8d6, 0x9085, 0x0001, 0x00ee, 0x00ce, 0x00be, 0x001e,
-	0x012e, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007, 0x0003,
-	0x701f, 0x4b2b, 0x0005, 0xa830, 0x2009, 0x180d, 0x210c, 0xd18c,
-	0x0140, 0x2008, 0x918e, 0xdead, 0x1120, 0x2021, 0x4009, 0x0804,
-	0x368f, 0x9086, 0x0100, 0x7024, 0x2058, 0x1138, 0x2009, 0x0004,
-	0xba04, 0x9294, 0x00ff, 0x0804, 0x578e, 0x900e, 0xa868, 0xd0f4,
-	0x1904, 0x368d, 0x080c, 0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc,
-	0x0108, 0xc18d, 0x0804, 0x368d, 0x00e6, 0x00d6, 0x0096, 0x83ff,
-	0x0904, 0x4ba3, 0x902e, 0x080c, 0xb094, 0x0130, 0x9026, 0x20a9,
-	0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x007f, 0x20a9, 0x0781,
-	0x2071, 0x107f, 0x2e04, 0x9005, 0x11b8, 0x2100, 0x9406, 0x1904,
-	0x4bb4, 0x2428, 0x94ce, 0x007f, 0x1120, 0x92ce, 0xfffd, 0x1558,
-	0x0030, 0x94ce, 0x0080, 0x1130, 0x92ce, 0xfffc, 0x1520, 0x93ce,
-	0x00ff, 0x1508, 0xc5fd, 0x0480, 0x2058, 0xbf10, 0x2700, 0x9306,
-	0x11e8, 0xbe14, 0x2600, 0x9206, 0x11c8, 0x2400, 0x9106, 0x1180,
-	0xd884, 0x0598, 0xd894, 0x1588, 0x080c, 0x6bb1, 0x1570, 0x2001,
-	0x4000, 0x0460, 0x080c, 0x6c11, 0x1540, 0x2001, 0x4000, 0x0430,
-	0x2001, 0x4007, 0x0418, 0x2001, 0x4006, 0x0400, 0x2400, 0x9106,
-	0x1158, 0xbe14, 0x87ff, 0x1128, 0x86ff, 0x0918, 0x080c, 0xb094,
-	0x1900, 0x2001, 0x4008, 0x0090, 0x8420, 0x8e70, 0x1f04, 0x4b6a,
-	0x85ff, 0x1130, 0x2001, 0x4009, 0x0048, 0x2001, 0x0001, 0x0030,
-	0x080c, 0x6749, 0x1dd0, 0xbb12, 0xba16, 0x9006, 0x9005, 0x009e,
-	0x00de, 0x00ee, 0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804,
-	0x36bf, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf,
-	0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a, 0x7884, 0x9005, 0x0904,
-	0x36c2, 0x9096, 0x00ff, 0x0120, 0x9092, 0x0004, 0x1a04, 0x36c2,
-	0x2010, 0x2918, 0x080c, 0x32b5, 0x1120, 0x2009, 0x0003, 0x0804,
-	0x36bf, 0x7007, 0x0003, 0x701f, 0x4bf6, 0x0005, 0xa830, 0x9086,
-	0x0100, 0x1904, 0x368d, 0x2009, 0x0004, 0x0804, 0x36bf, 0x7984,
-	0x080c, 0xb094, 0x1120, 0x9182, 0x007f, 0x0a04, 0x36c2, 0x9186,
-	0x00ff, 0x0904, 0x36c2, 0x9182, 0x0800, 0x1a04, 0x36c2, 0x2001,
-	0x9400, 0x080c, 0x57e9, 0x1904, 0x36bf, 0x0804, 0x368d, 0xa998,
-	0x080c, 0xb094, 0x1118, 0x9182, 0x007f, 0x0280, 0x9186, 0x00ff,
-	0x0168, 0x9182, 0x0800, 0x1250, 0x2001, 0x9400, 0x080c, 0x57e9,
-	0x11a8, 0x0060, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006,
-	0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000,
-	0x900e, 0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x2009, 0x000a,
-	0x0c48, 0x080c, 0x1059, 0x0198, 0x9006, 0xa802, 0x7014, 0x9005,
-	0x1120, 0x2900, 0x7016, 0x701a, 0x0040, 0x7018, 0xa802, 0x0086,
-	0x2040, 0x2900, 0xa006, 0x701a, 0x008e, 0x9085, 0x0001, 0x0005,
-	0x7984, 0x080c, 0x67b4, 0x1130, 0x7e88, 0x9684, 0x3fff, 0x9082,
-	0x4000, 0x0208, 0x905e, 0x8bff, 0x0005, 0xa998, 0x080c, 0x67b4,
-	0x1130, 0xae9c, 0x9684, 0x3fff, 0x9082, 0x4000, 0x0208, 0x905e,
-	0x8bff, 0x0005, 0xae98, 0x0008, 0x7e84, 0x2608, 0x080c, 0x67b4,
-	0x1108, 0x0008, 0x905e, 0x8bff, 0x0005, 0x0016, 0x7114, 0x81ff,
-	0x0128, 0x2148, 0xa904, 0x080c, 0x108b, 0x0cc8, 0x7116, 0x711a,
-	0x001e, 0x0005, 0x2031, 0x0001, 0x0010, 0x2031, 0x0000, 0x2061,
-	0x18b8, 0x2c44, 0xa66a, 0xa17a, 0xa772, 0xa076, 0xa28e, 0xa392,
-	0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, 0x368d,
-	0x0005, 0x00f6, 0x0126, 0x2091, 0x8000, 0x2079, 0x0000, 0x2001,
-	0x18b0, 0x2004, 0x9005, 0x1190, 0x0e04, 0x4cbe, 0x7a36, 0x7833,
-	0x0012, 0x7a82, 0x7b86, 0x7c8a, 0x2091, 0x4080, 0x2001, 0x0089,
-	0x2004, 0xd084, 0x190c, 0x1200, 0x0804, 0x4d24, 0x0016, 0x0086,
-	0x0096, 0x00c6, 0x00e6, 0x2071, 0x189e, 0x7044, 0x9005, 0x1540,
-	0x7148, 0x9182, 0x0010, 0x0288, 0x7038, 0x2060, 0x080c, 0x1059,
-	0x0904, 0x4d1c, 0xa84b, 0x0000, 0x2900, 0x7046, 0x2001, 0x0002,
-	0x9080, 0x1ec1, 0x2005, 0xa846, 0x0098, 0x7038, 0x90e0, 0x0004,
-	0x2001, 0x18ba, 0x9c82, 0x18fa, 0x0210, 0x2061, 0x18ba, 0x2c00,
-	0x703a, 0x7148, 0x81ff, 0x1108, 0x703e, 0x8108, 0x714a, 0x0460,
-	0x7148, 0x8108, 0x714a, 0x7044, 0x2040, 0xa144, 0x2105, 0x0016,
-	0x908a, 0x0036, 0x1a0c, 0x0d85, 0x2060, 0x001e, 0x8108, 0x2105,
-	0x9005, 0xa146, 0x1520, 0x080c, 0x1059, 0x1130, 0x8109, 0xa946,
-	0x7148, 0x8109, 0x714a, 0x00d8, 0x9006, 0xa806, 0xa84a, 0xa046,
-	0x2800, 0xa802, 0x2900, 0xa006, 0x7046, 0x2001, 0x0002, 0x9080,
-	0x1ec1, 0x2005, 0xa846, 0x0058, 0x2262, 0x6306, 0x640a, 0x00ee,
-	0x00ce, 0x009e, 0x008e, 0x001e, 0x012e, 0x00fe, 0x0005, 0x2c00,
-	0x9082, 0x001b, 0x0002, 0x4d46, 0x4d46, 0x4d48, 0x4d46, 0x4d46,
-	0x4d46, 0x4d4c, 0x4d46, 0x4d46, 0x4d46, 0x4d50, 0x4d46, 0x4d46,
-	0x4d46, 0x4d54, 0x4d46, 0x4d46, 0x4d46, 0x4d58, 0x4d46, 0x4d46,
-	0x4d46, 0x4d5c, 0x4d46, 0x4d46, 0x4d46, 0x4d61, 0x080c, 0x0d85,
-	0xa276, 0xa37a, 0xa47e, 0x0898, 0xa286, 0xa38a, 0xa48e, 0x0878,
-	0xa296, 0xa39a, 0xa49e, 0x0858, 0xa2a6, 0xa3aa, 0xa4ae, 0x0838,
-	0xa2b6, 0xa3ba, 0xa4be, 0x0818, 0xa2c6, 0xa3ca, 0xa4ce, 0x0804,
-	0x4d1f, 0xa2d6, 0xa3da, 0xa4de, 0x0804, 0x4d1f, 0x00e6, 0x2071,
-	0x189e, 0x7048, 0x9005, 0x0904, 0x4df8, 0x0126, 0x2091, 0x8000,
-	0x0e04, 0x4df7, 0x00f6, 0x2079, 0x0000, 0x00c6, 0x0096, 0x0086,
-	0x0076, 0x9006, 0x2038, 0x7040, 0x2048, 0x9005, 0x0500, 0xa948,
-	0x2105, 0x0016, 0x908a, 0x0036, 0x1a0c, 0x0d85, 0x2060, 0x001e,
-	0x8108, 0x2105, 0x9005, 0xa94a, 0x1904, 0x4dfa, 0xa804, 0x9005,
-	0x090c, 0x0d85, 0x7042, 0x2938, 0x2040, 0xa003, 0x0000, 0x2001,
-	0x0002, 0x9080, 0x1ec1, 0x2005, 0xa04a, 0x0804, 0x4dfa, 0x703c,
-	0x2060, 0x2c14, 0x6304, 0x6408, 0x650c, 0x2200, 0x7836, 0x7833,
-	0x0012, 0x7882, 0x2300, 0x7886, 0x2400, 0x788a, 0x2091, 0x4080,
-	0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x87ff, 0x0118,
-	0x2748, 0x080c, 0x108b, 0x7048, 0x8001, 0x704a, 0x9005, 0x1170,
-	0x7040, 0x2048, 0x9005, 0x0128, 0x080c, 0x108b, 0x9006, 0x7042,
-	0x7046, 0x703b, 0x18ba, 0x703f, 0x18ba, 0x0420, 0x7040, 0x9005,
-	0x1508, 0x7238, 0x2c00, 0x9206, 0x0148, 0x9c80, 0x0004, 0x90fa,
-	0x18fa, 0x0210, 0x2001, 0x18ba, 0x703e, 0x00a0, 0x9006, 0x703e,
-	0x703a, 0x7044, 0x9005, 0x090c, 0x0d85, 0x2048, 0xa800, 0x9005,
-	0x1de0, 0x2900, 0x7042, 0x2001, 0x0002, 0x9080, 0x1ec1, 0x2005,
-	0xa84a, 0x0000, 0x007e, 0x008e, 0x009e, 0x00ce, 0x00fe, 0x012e,
-	0x00ee, 0x0005, 0x2c00, 0x9082, 0x001b, 0x0002, 0x4e19, 0x4e19,
-	0x4e1b, 0x4e19, 0x4e19, 0x4e19, 0x4e20, 0x4e19, 0x4e19, 0x4e19,
-	0x4e25, 0x4e19, 0x4e19, 0x4e19, 0x4e2a, 0x4e19, 0x4e19, 0x4e19,
-	0x4e2f, 0x4e19, 0x4e19, 0x4e19, 0x4e34, 0x4e19, 0x4e19, 0x4e19,
-	0x4e39, 0x080c, 0x0d85, 0xaa74, 0xab78, 0xac7c, 0x0804, 0x4da5,
-	0xaa84, 0xab88, 0xac8c, 0x0804, 0x4da5, 0xaa94, 0xab98, 0xac9c,
-	0x0804, 0x4da5, 0xaaa4, 0xaba8, 0xacac, 0x0804, 0x4da5, 0xaab4,
-	0xabb8, 0xacbc, 0x0804, 0x4da5, 0xaac4, 0xabc8, 0xaccc, 0x0804,
-	0x4da5, 0xaad4, 0xabd8, 0xacdc, 0x0804, 0x4da5, 0x0016, 0x0026,
-	0x0036, 0x00b6, 0x00c6, 0x2009, 0x007e, 0x080c, 0x67b4, 0x2019,
-	0x0001, 0xb85c, 0xd0ac, 0x0110, 0x2019, 0x0000, 0x2011, 0x801b,
-	0x080c, 0x4ca1, 0x00ce, 0x00be, 0x003e, 0x002e, 0x001e, 0x0005,
-	0x0026, 0x080c, 0x5840, 0xd0c4, 0x0120, 0x2011, 0x8014, 0x080c,
-	0x4ca1, 0x002e, 0x0005, 0x81ff, 0x1904, 0x36bf, 0x0126, 0x2091,
-	0x8000, 0x6030, 0xc08d, 0xc085, 0xc0ac, 0x6032, 0x080c, 0x779e,
-	0x1158, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c,
-	0x77e2, 0x080c, 0x76cd, 0x0010, 0x080c, 0x6058, 0x012e, 0x0804,
-	0x368d, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c,
-	0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x080c, 0x6c09,
-	0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0x2001, 0x180d, 0x2004,
-	0xd08c, 0x0178, 0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e,
-	0x0140, 0x7984, 0x080c, 0x6c7f, 0x1120, 0x2009, 0x4009, 0x0804,
-	0x36bf, 0x7984, 0x080c, 0x6749, 0x1904, 0x36c2, 0x080c, 0x4c74,
-	0x0904, 0x36c2, 0x2b00, 0x7026, 0x080c, 0x6c11, 0x7888, 0x1170,
-	0x9084, 0x0005, 0x1158, 0x900e, 0x080c, 0x6aae, 0x1108, 0xc185,
-	0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x368d, 0x080c, 0x4c41,
-	0x0904, 0x36bf, 0x9006, 0xa866, 0xa832, 0xa868, 0xc0fd, 0xa86a,
-	0x080c, 0xd154, 0x0904, 0x36bf, 0x7888, 0xd094, 0x0118, 0xb8d4,
-	0xc08d, 0xb8d6, 0x7007, 0x0003, 0x701f, 0x4f28, 0x0005, 0x2061,
-	0x1800, 0x080c, 0x5854, 0x2009, 0x0007, 0x1560, 0x080c, 0x6c09,
-	0x0118, 0x2009, 0x0008, 0x0430, 0xa998, 0x080c, 0x6749, 0x1530,
-	0x080c, 0x4c72, 0x0518, 0x080c, 0x6c11, 0xa89c, 0x1168, 0x9084,
-	0x0005, 0x1150, 0x900e, 0x080c, 0x6aae, 0x1108, 0xc185, 0xb800,
-	0xd0bc, 0x0108, 0xc18d, 0x00d0, 0xa868, 0xc0fc, 0xa86a, 0x080c,
-	0xd154, 0x11e0, 0xa89c, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6,
-	0x2009, 0x0003, 0xa897, 0x4005, 0xa99a, 0x0010, 0xa897, 0x4006,
-	0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x0005, 0xa897, 0x4000,
-	0xa99a, 0x9006, 0x918d, 0x0001, 0x2008, 0x0005, 0x9006, 0x0005,
-	0xa830, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0140, 0x2008, 0x918e,
-	0xdead, 0x1120, 0x2021, 0x4009, 0x0804, 0x368f, 0x9086, 0x0100,
-	0x7024, 0x2058, 0x1110, 0x0804, 0x578e, 0x900e, 0x080c, 0x6aae,
-	0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x0804, 0x368d,
-	0x080c, 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7f84,
-	0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4c41, 0x1120, 0x2009,
-	0x0002, 0x0804, 0x36bf, 0x900e, 0x2130, 0x7126, 0x7132, 0xa860,
-	0x20e8, 0x7036, 0xa85c, 0x9080, 0x0005, 0x702a, 0x20a0, 0x080c,
-	0x67b4, 0x1904, 0x4fde, 0x080c, 0x6c11, 0x0138, 0x080c, 0x6c19,
-	0x0120, 0x080c, 0x6bb1, 0x1904, 0x4fde, 0xd794, 0x1110, 0xd784,
-	0x01a8, 0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x3400,
-	0xd794, 0x0198, 0x20a9, 0x0008, 0x4003, 0x2098, 0x20a0, 0x3d00,
-	0x20e0, 0x20a9, 0x0002, 0x080c, 0x4a10, 0x0080, 0xb8c4, 0x20e0,
-	0xb8c8, 0x9080, 0x000a, 0x2098, 0x3400, 0x20a9, 0x0004, 0x4003,
-	0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x4a10, 0x9186, 0x007e,
-	0x0170, 0x9186, 0x0080, 0x0158, 0x080c, 0x6c11, 0x90c2, 0x0006,
-	0x1210, 0xc1fd, 0x0020, 0x080c, 0x6aae, 0x1108, 0xc1fd, 0x4104,
-	0xc1fc, 0xd794, 0x0528, 0xb8c4, 0x20e0, 0xb8c8, 0x2060, 0x9c80,
-	0x0000, 0x2098, 0x20a9, 0x0002, 0x4003, 0x9c80, 0x0003, 0x2098,
-	0x20a9, 0x0001, 0x4005, 0x9c80, 0x0004, 0x2098, 0x3400, 0x20a9,
-	0x0002, 0x4003, 0x2098, 0x20a0, 0x3d00, 0x20e0, 0x080c, 0x4a03,
-	0x9c80, 0x0026, 0x2098, 0xb8c4, 0x20e0, 0x20a9, 0x0002, 0x4003,
-	0xd794, 0x0110, 0x96b0, 0x000b, 0x96b0, 0x0005, 0x8108, 0x080c,
-	0xb094, 0x0118, 0x9186, 0x0800, 0x0040, 0xd78c, 0x0120, 0x9186,
-	0x0800, 0x0170, 0x0018, 0x9186, 0x007e, 0x0150, 0xd794, 0x0118,
-	0x9686, 0x0020, 0x0010, 0x9686, 0x0028, 0x0150, 0x0804, 0x4f67,
-	0x86ff, 0x1120, 0x7124, 0x810b, 0x0804, 0x368d, 0x7033, 0x0001,
-	0x7122, 0x7024, 0x9600, 0x7026, 0x772e, 0x2061, 0x18b8, 0x2c44,
-	0xa06b, 0x0000, 0xa67a, 0x7034, 0xa072, 0x7028, 0xa076, 0xa28e,
-	0xa392, 0xa496, 0xa59a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f,
-	0x501a, 0x0005, 0x7030, 0x9005, 0x1180, 0x7120, 0x7028, 0x20a0,
-	0x772c, 0x9036, 0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa28c,
-	0xa390, 0xa494, 0xa598, 0x0804, 0x4f67, 0x7124, 0x810b, 0x0804,
-	0x368d, 0x2029, 0x007e, 0x7984, 0x7a88, 0x7b8c, 0x7c98, 0x9184,
-	0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04,
-	0x36c2, 0x9184, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502,
-	0x0a04, 0x36c2, 0x9284, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04,
-	0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9284, 0x00ff, 0x90e2, 0x0020,
-	0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9384, 0xff00, 0x8007,
-	0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2, 0x9384,
-	0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502, 0x0a04, 0x36c2,
-	0x9484, 0xff00, 0x8007, 0x90e2, 0x0020, 0x0a04, 0x36c2, 0x9502,
-	0x0a04, 0x36c2, 0x9484, 0x00ff, 0x90e2, 0x0020, 0x0a04, 0x36c2,
-	0x9502, 0x0a04, 0x36c2, 0x2061, 0x1989, 0x6102, 0x6206, 0x630a,
-	0x640e, 0x0804, 0x368d, 0x080c, 0x4c41, 0x0904, 0x36bf, 0x2009,
-	0x0016, 0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019,
-	0xaf60, 0x080c, 0x4c8a, 0x701f, 0x509e, 0x0005, 0x20a9, 0x0016,
-	0x896e, 0x8d6e, 0x8d6f, 0x9d84, 0xffc0, 0x9080, 0x0019, 0x2098,
-	0x9d84, 0x003f, 0x20e0, 0x2069, 0x1877, 0x20e9, 0x0001, 0x2da0,
-	0x4003, 0x6800, 0x9005, 0x0904, 0x5105, 0x6804, 0x2008, 0x918c,
-	0xfff8, 0x1904, 0x5105, 0x680c, 0x9005, 0x0904, 0x5105, 0x9082,
-	0xff01, 0x1a04, 0x5105, 0x6810, 0x9082, 0x005c, 0x06f0, 0x6824,
-	0x2008, 0x9082, 0x0008, 0x06c8, 0x9182, 0x0400, 0x16b0, 0x0056,
-	0x2029, 0x0000, 0x080c, 0x9077, 0x005e, 0x6944, 0x6820, 0x9102,
-	0x0660, 0x6820, 0x9082, 0x0019, 0x1640, 0x6828, 0x6944, 0x810c,
-	0x9102, 0x0618, 0x6840, 0x9082, 0x000f, 0x12f8, 0x080c, 0x1072,
-	0x2900, 0x0590, 0x684e, 0x00e6, 0x2071, 0x1931, 0x00b6, 0x2059,
-	0x0000, 0x080c, 0x8f33, 0x00be, 0x00ee, 0x01e8, 0x080c, 0x8c78,
-	0x080c, 0x8cc7, 0x1160, 0x6857, 0x0000, 0x00c6, 0x6b10, 0x2061,
-	0x1a6e, 0x630e, 0x00ce, 0x0804, 0x368d, 0x0804, 0x36c2, 0x080c,
-	0x8cc0, 0x00e6, 0x2071, 0x1931, 0x080c, 0x90f7, 0x080c, 0x9106,
-	0x080c, 0x8f18, 0x00ee, 0x2001, 0x188a, 0x204c, 0x080c, 0x108b,
-	0x2001, 0x188a, 0x2003, 0x0000, 0x0804, 0x36bf, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x94b8, 0x080c, 0x8cc0, 0x012e, 0x0804, 0x368d,
-	0x0006, 0x080c, 0x5840, 0xd0cc, 0x000e, 0x0005, 0x0006, 0x080c,
-	0x5844, 0xd0bc, 0x000e, 0x0005, 0x6174, 0x7a84, 0x6300, 0x82ff,
-	0x1118, 0x7986, 0x0804, 0x368d, 0x83ff, 0x1904, 0x36c2, 0x2001,
-	0xfff0, 0x9200, 0x1a04, 0x36c2, 0x2019, 0xffff, 0x6078, 0x9302,
-	0x9200, 0x0a04, 0x36c2, 0x7986, 0x6276, 0x0804, 0x368d, 0x080c,
-	0x5854, 0x1904, 0x36bf, 0x7c88, 0x7d84, 0x7e98, 0x7f8c, 0x080c,
-	0x4c41, 0x0904, 0x36bf, 0x900e, 0x901e, 0x7326, 0x7332, 0xa860,
-	0x20e8, 0x7036, 0xa85c, 0x9080, 0x0003, 0x702a, 0x20a0, 0x91d8,
-	0x1000, 0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c,
-	0x6c19, 0x1148, 0x20a9, 0x0001, 0xb814, 0x4004, 0xb810, 0x4004,
-	0x4104, 0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386,
-	0x003c, 0x0170, 0x0c20, 0x83ff, 0x1148, 0x7224, 0x900e, 0x2001,
-	0x0003, 0x080c, 0x955b, 0x2208, 0x0804, 0x368d, 0x7033, 0x0001,
-	0x7122, 0x7024, 0x9300, 0x7026, 0x2061, 0x18b8, 0x2c44, 0xa06b,
-	0x0000, 0xa37a, 0x7028, 0xa076, 0x7034, 0xa072, 0xa48e, 0xa592,
-	0xa696, 0xa79a, 0x080c, 0x114e, 0x7007, 0x0002, 0x701f, 0x51a9,
-	0x0005, 0x7030, 0x9005, 0x1178, 0x7120, 0x7028, 0x20a0, 0x901e,
-	0x7034, 0x20e8, 0x2061, 0x18b8, 0x2c44, 0xa48c, 0xa590, 0xa694,
-	0xa798, 0x0804, 0x5167, 0x7224, 0x900e, 0x2001, 0x0003, 0x080c,
-	0x955b, 0x2208, 0x0804, 0x368d, 0x00f6, 0x00e6, 0x080c, 0x5854,
-	0x2009, 0x0007, 0x1904, 0x523c, 0x2071, 0x189e, 0x745c, 0x84ff,
-	0x2009, 0x000e, 0x1904, 0x523c, 0xac9c, 0xad98, 0xaea4, 0xafa0,
-	0x0096, 0x080c, 0x1072, 0x2009, 0x0002, 0x0904, 0x523c, 0x2900,
-	0x705e, 0x900e, 0x901e, 0x7356, 0x7362, 0xa860, 0x7066, 0xa85c,
-	0x9080, 0x0003, 0x705a, 0x20a0, 0x91d8, 0x1000, 0x2b5c, 0x8bff,
-	0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19, 0x1148, 0xb814,
-	0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104, 0x9398, 0x0003,
-	0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c, 0x01e8, 0x0c20,
-	0x83ff, 0x11c0, 0x7254, 0x900e, 0x2001, 0x0003, 0x080c, 0x955b,
-	0x2208, 0x009e, 0xa897, 0x4000, 0xa99a, 0x715c, 0x81ff, 0x090c,
-	0x0d85, 0x2148, 0x080c, 0x108b, 0x9006, 0x705e, 0x918d, 0x0001,
-	0x2008, 0x0418, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056,
-	0x2061, 0x18b9, 0x2c44, 0xa37a, 0x7058, 0xa076, 0x7064, 0xa072,
-	0xa48e, 0xa592, 0xa696, 0xa79a, 0xa09f, 0x5248, 0x000e, 0xa0a2,
-	0x080c, 0x114e, 0x9006, 0x0048, 0x009e, 0xa897, 0x4005, 0xa99a,
-	0x900e, 0x9085, 0x0001, 0x2001, 0x0030, 0x00ee, 0x00fe, 0x0005,
-	0x00f6, 0xa0a0, 0x904d, 0x090c, 0x0d85, 0x00e6, 0x2071, 0x189e,
-	0xa06c, 0x908e, 0x0100, 0x0138, 0xa87b, 0x0030, 0xa883, 0x0000,
-	0xa897, 0x4002, 0x00d8, 0x7060, 0x9005, 0x1158, 0x7150, 0x7058,
-	0x20a0, 0x901e, 0x7064, 0x20e8, 0xa48c, 0xa590, 0xa694, 0xa798,
-	0x0428, 0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x7254,
-	0x900e, 0x2001, 0x0003, 0x080c, 0x955b, 0xaa9a, 0x715c, 0x81ff,
-	0x090c, 0x0d85, 0x2148, 0x080c, 0x108b, 0x705f, 0x0000, 0xa0a0,
-	0x2048, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0xa09f,
-	0x0000, 0xa0a3, 0x0000, 0x00ee, 0x00fe, 0x0005, 0x91d8, 0x1000,
-	0x2b5c, 0x8bff, 0x0178, 0x080c, 0x6c11, 0x0118, 0x080c, 0x6c19,
-	0x1148, 0xb814, 0x20a9, 0x0001, 0x4004, 0xb810, 0x4004, 0x4104,
-	0x9398, 0x0003, 0x8108, 0x9182, 0x0800, 0x0120, 0x9386, 0x003c,
-	0x0518, 0x0c20, 0x83ff, 0x11f0, 0x7154, 0x810c, 0xa99a, 0xa897,
-	0x4000, 0x715c, 0x81ff, 0x090c, 0x0d85, 0x2148, 0x080c, 0x108b,
-	0x9006, 0x705e, 0x918d, 0x0001, 0x2008, 0xa0a0, 0x2048, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0xa09f, 0x0000, 0xa0a3,
-	0x0000, 0x0070, 0x7063, 0x0001, 0x7152, 0x7054, 0x9300, 0x7056,
-	0xa37a, 0xa48e, 0xa592, 0xa696, 0xa79a, 0x080c, 0x114e, 0x9006,
-	0x00ee, 0x0005, 0x0096, 0xa88c, 0x90be, 0x7000, 0x0148, 0x90be,
-	0x7100, 0x0130, 0x90be, 0x7200, 0x0118, 0x009e, 0x0804, 0x36c2,
-	0xa884, 0xa988, 0x080c, 0x268c, 0x1518, 0x080c, 0x6749, 0x1500,
-	0x7126, 0xbe12, 0xbd16, 0xae7c, 0x080c, 0x4c41, 0x01c8, 0x080c,
-	0x4c41, 0x01b0, 0x009e, 0xa867, 0x0000, 0xa868, 0xc0fd, 0xa86a,
-	0xa823, 0x0000, 0xa804, 0x2048, 0x080c, 0xd0cd, 0x1120, 0x2009,
-	0x0003, 0x0804, 0x36bf, 0x7007, 0x0003, 0x701f, 0x5315, 0x0005,
-	0x009e, 0x2009, 0x0002, 0x0804, 0x36bf, 0x7124, 0x080c, 0x341e,
-	0xa820, 0x9086, 0x8001, 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf,
-	0x2900, 0x7022, 0xa804, 0x0096, 0x2048, 0x8906, 0x8006, 0x8007,
-	0x90bc, 0x003f, 0x9084, 0xffc0, 0x009e, 0x9080, 0x0002, 0x0076,
-	0x0006, 0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c,
-	0x0fd6, 0xaa6c, 0xab70, 0xac74, 0xad78, 0x2061, 0x18b8, 0x2c44,
-	0xa06b, 0x0000, 0xae64, 0xaf8c, 0x97c6, 0x7000, 0x0118, 0x97c6,
-	0x7100, 0x1148, 0x96c2, 0x0004, 0x0600, 0x2009, 0x0004, 0x000e,
-	0x007e, 0x0804, 0x4c8d, 0x97c6, 0x7200, 0x11b8, 0x96c2, 0x0054,
-	0x02a0, 0x000e, 0x007e, 0x2061, 0x18b8, 0x2c44, 0xa076, 0xa772,
-	0xa07b, 0x002a, 0xa28e, 0xa392, 0xa496, 0xa59a, 0x080c, 0x114e,
-	0x7007, 0x0002, 0x701f, 0x5371, 0x0005, 0x000e, 0x007e, 0x0804,
-	0x36c2, 0x7020, 0x2048, 0xa804, 0x2048, 0xa804, 0x2048, 0x8906,
-	0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002,
-	0x2098, 0x20a0, 0x27e0, 0x27e8, 0x20a9, 0x002a, 0x080c, 0x0fd6,
-	0x2100, 0x2238, 0x2061, 0x18b8, 0x2c44, 0xa28c, 0xa390, 0xa494,
-	0xa598, 0x2009, 0x002a, 0x0804, 0x4c8d, 0x81ff, 0x1904, 0x36bf,
-	0x798c, 0x2001, 0x197e, 0x918c, 0x8000, 0x2102, 0x080c, 0x4c58,
-	0x0904, 0x36c2, 0x080c, 0x6c11, 0x0120, 0x080c, 0x6c19, 0x1904,
-	0x36c2, 0x080c, 0x687b, 0x0904, 0x36bf, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x6a1b, 0x012e, 0x0904, 0x36bf, 0x2001, 0x197e, 0x2004,
-	0xd0fc, 0x1904, 0x368d, 0x0804, 0x46aa, 0xa9a0, 0x2001, 0x197e,
-	0x918c, 0x8000, 0xc18d, 0x2102, 0x080c, 0x4c65, 0x01a0, 0x080c,
-	0x6c11, 0x0118, 0x080c, 0x6c19, 0x1170, 0x080c, 0x687b, 0x2009,
-	0x0002, 0x0128, 0x080c, 0x6a1b, 0x1170, 0x2009, 0x0003, 0xa897,
-	0x4005, 0xa99a, 0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001,
-	0x2001, 0x0030, 0x0005, 0xa897, 0x4000, 0x2001, 0x197e, 0x2004,
-	0xd0fc, 0x1128, 0x080c, 0x5848, 0x0110, 0x9006, 0x0018, 0x900e,
-	0x9085, 0x0001, 0x2001, 0x0000, 0x0005, 0x78a8, 0xd08c, 0x1118,
-	0xd084, 0x0904, 0x461f, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x080c,
-	0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0x080c, 0x6c11,
-	0x0130, 0x908e, 0x0004, 0x0118, 0x908e, 0x0005, 0x15a0, 0x78a8,
-	0xd08c, 0x0120, 0xb800, 0xc08c, 0xb802, 0x0028, 0x080c, 0x5840,
-	0xd0b4, 0x0904, 0x4659, 0x7884, 0x908e, 0x007e, 0x0904, 0x4659,
-	0x908e, 0x007f, 0x0904, 0x4659, 0x908e, 0x0080, 0x0904, 0x4659,
-	0xb800, 0xd08c, 0x1904, 0x4659, 0xa867, 0x0000, 0xa868, 0xc0fd,
-	0xa86a, 0x080c, 0xd0ec, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf,
-	0x7007, 0x0003, 0x701f, 0x543d, 0x0005, 0x080c, 0x4c74, 0x0904,
-	0x36c2, 0x0804, 0x4659, 0x080c, 0x347d, 0x0108, 0x0005, 0x2009,
-	0x1834, 0x210c, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf,
-	0x080c, 0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x080c,
-	0x6c09, 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0xb89c, 0xd0a4,
-	0x1118, 0xd0ac, 0x1904, 0x4659, 0x9006, 0xa866, 0xa832, 0xa868,
-	0xc0fd, 0xa86a, 0x080c, 0xd154, 0x1120, 0x2009, 0x0003, 0x0804,
-	0x36bf, 0x7007, 0x0003, 0x701f, 0x5476, 0x0005, 0xa830, 0x9086,
-	0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x578e, 0x080c, 0x4c74,
-	0x0904, 0x36c2, 0x0804, 0x540f, 0x81ff, 0x2009, 0x0001, 0x1904,
-	0x36bf, 0x080c, 0x5854, 0x2009, 0x0007, 0x1904, 0x36bf, 0x080c,
-	0x6c09, 0x0120, 0x2009, 0x0008, 0x0804, 0x36bf, 0x080c, 0x4c74,
-	0x0904, 0x36c2, 0x080c, 0x6c11, 0x2009, 0x0009, 0x1904, 0x36bf,
-	0x080c, 0x4c41, 0x2009, 0x0002, 0x0904, 0x36bf, 0x9006, 0xa866,
-	0xa832, 0xa868, 0xc0fd, 0xa86a, 0x7988, 0xa95a, 0x9194, 0xfd00,
-	0x918c, 0x00ff, 0x9006, 0x82ff, 0x1128, 0xc0ed, 0xa952, 0x798c,
-	0xa956, 0x0038, 0x928e, 0x0100, 0x1904, 0x36c2, 0xc0e5, 0xa952,
-	0xa956, 0xa83e, 0x080c, 0xd3b7, 0x2009, 0x0003, 0x0904, 0x36bf,
-	0x7007, 0x0003, 0x701f, 0x54cd, 0x0005, 0xa830, 0x9086, 0x0100,
-	0x2009, 0x0004, 0x0904, 0x36bf, 0x0804, 0x368d, 0x7aa8, 0x9284,
-	0xc000, 0x0148, 0xd2ec, 0x01a0, 0x080c, 0x5854, 0x1188, 0x2009,
-	0x0014, 0x0804, 0x36bf, 0xd2dc, 0x1578, 0x81ff, 0x2009, 0x0001,
-	0x1904, 0x36bf, 0x080c, 0x5854, 0x2009, 0x0007, 0x1904, 0x36bf,
-	0xd2f4, 0x0138, 0x9284, 0x5000, 0xc0d5, 0x080c, 0x581a, 0x0804,
-	0x368d, 0xd2fc, 0x0160, 0x080c, 0x4c74, 0x0904, 0x36c2, 0x7984,
-	0x9284, 0x9000, 0xc0d5, 0x080c, 0x57e9, 0x0804, 0x368d, 0x080c,
-	0x4c74, 0x0904, 0x36c2, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006,
-	0x2009, 0x0009, 0x1904, 0x55bc, 0x080c, 0x4c41, 0x2009, 0x0002,
-	0x0904, 0x55bc, 0xa85c, 0x9080, 0x001b, 0xaf60, 0x2009, 0x0008,
-	0x7a8c, 0x7b88, 0x7c9c, 0x7d98, 0x080c, 0x4c8a, 0x701f, 0x5529,
-	0x0005, 0xa86c, 0x9086, 0x0500, 0x1138, 0xa870, 0x9005, 0x1120,
-	0xa874, 0x9084, 0xff00, 0x0110, 0x1904, 0x36c2, 0xa866, 0xa832,
-	0xa868, 0xc0fd, 0xa86a, 0x080c, 0x4c74, 0x1110, 0x0804, 0x36c2,
-	0x2009, 0x0043, 0x080c, 0xd423, 0x2009, 0x0003, 0x0904, 0x55bc,
-	0x7007, 0x0003, 0x701f, 0x554d, 0x0005, 0xa830, 0x9086, 0x0100,
-	0x2009, 0x0004, 0x0904, 0x55bc, 0x7984, 0x7aa8, 0x9284, 0x1000,
-	0xc0d5, 0x080c, 0x57e9, 0x0804, 0x368d, 0x00c6, 0xaab0, 0x9284,
-	0xc000, 0x0148, 0xd2ec, 0x0170, 0x080c, 0x5854, 0x1158, 0x2009,
-	0x0014, 0x0804, 0x55ab, 0x2061, 0x1800, 0x080c, 0x5854, 0x2009,
-	0x0007, 0x15c8, 0xd2f4, 0x0130, 0x9284, 0x5000, 0xc0d5, 0x080c,
-	0x581a, 0x0058, 0xd2fc, 0x0180, 0x080c, 0x4c72, 0x0590, 0xa998,
-	0x9284, 0x9000, 0xc0d5, 0x080c, 0x57e9, 0xa87b, 0x0000, 0xa883,
-	0x0000, 0xa897, 0x4000, 0x0438, 0x080c, 0x4c72, 0x0510, 0x080c,
-	0x6c11, 0x2009, 0x0009, 0x11b8, 0xa8c4, 0x9086, 0x0500, 0x11c8,
-	0xa8c8, 0x9005, 0x11b0, 0xa8cc, 0x9084, 0xff00, 0x1190, 0x080c,
-	0x4c72, 0x1108, 0x0070, 0x2009, 0x004b, 0x080c, 0xd423, 0x2009,
-	0x0003, 0x0108, 0x0078, 0x0431, 0x19c0, 0xa897, 0x4005, 0xa99a,
-	0x0010, 0xa897, 0x4006, 0x900e, 0x9085, 0x0001, 0x2001, 0x0030,
-	0x00ce, 0x0005, 0x9006, 0x0ce0, 0x7aa8, 0xd2dc, 0x0904, 0x36bf,
-	0x0016, 0x7984, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57e9, 0x001e,
-	0x1904, 0x36bf, 0x0804, 0x368d, 0x00f6, 0x2d78, 0xaab0, 0x0021,
-	0x00fe, 0x0005, 0xaab0, 0xc2d5, 0xd2dc, 0x0150, 0x0016, 0xa998,
-	0x9284, 0x1400, 0xc0fd, 0x080c, 0x57e9, 0x001e, 0x9085, 0x0001,
-	0x0005, 0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c,
-	0x5854, 0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7984, 0x7ea8,
-	0x96b4, 0x00ff, 0x080c, 0x67b4, 0x1904, 0x36c2, 0x9186, 0x007f,
-	0x0138, 0x080c, 0x6c11, 0x0120, 0x2009, 0x0009, 0x0804, 0x36bf,
-	0x080c, 0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0xa867,
-	0x0000, 0xa868, 0xc0fd, 0xa86a, 0x2001, 0x0100, 0x8007, 0xa80a,
-	0x080c, 0xd106, 0x1120, 0x2009, 0x0003, 0x0804, 0x36bf, 0x7007,
-	0x0003, 0x701f, 0x561c, 0x0005, 0xa808, 0x8007, 0x9086, 0x0100,
-	0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa8e0, 0xa866, 0xa810,
-	0x8007, 0x9084, 0x00ff, 0x800c, 0xa814, 0x8007, 0x9084, 0x00ff,
-	0x8004, 0x9080, 0x0002, 0x9108, 0x8906, 0x8006, 0x8007, 0x90bc,
-	0x003f, 0x9084, 0xffc0, 0x9080, 0x0004, 0x7a8c, 0x7b88, 0x7c9c,
-	0x7d98, 0x0804, 0x4c8d, 0x080c, 0x4c41, 0x1120, 0x2009, 0x0002,
-	0x0804, 0x36bf, 0x7984, 0x9194, 0xff00, 0x918c, 0x00ff, 0x8217,
-	0x82ff, 0x1118, 0x7023, 0x19b4, 0x0040, 0x92c6, 0x0001, 0x1118,
-	0x7023, 0x19ce, 0x0010, 0x0804, 0x36c2, 0x2009, 0x001a, 0x7a8c,
-	0x7b88, 0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x080c,
-	0x4c8a, 0x701f, 0x566c, 0x0005, 0x2001, 0x182e, 0x2003, 0x0001,
-	0xa85c, 0x9080, 0x0019, 0x2098, 0xa860, 0x20e0, 0x20a9, 0x001a,
-	0x7020, 0x20a0, 0x20e9, 0x0001, 0x4003, 0x0804, 0x368d, 0x080c,
-	0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0x7984, 0x9194,
-	0xff00, 0x918c, 0x00ff, 0x8217, 0x82ff, 0x1118, 0x2099, 0x19b4,
-	0x0040, 0x92c6, 0x0001, 0x1118, 0x2099, 0x19ce, 0x0010, 0x0804,
-	0x36c2, 0xa85c, 0x9080, 0x0019, 0x20a0, 0xa860, 0x20e8, 0x20a9,
-	0x001a, 0x20e1, 0x0001, 0x4003, 0x2009, 0x001a, 0x7a8c, 0x7b88,
-	0x7c9c, 0x7d98, 0xa85c, 0x9080, 0x0019, 0xaf60, 0x0804, 0x4c8d,
-	0x7884, 0x908a, 0x1000, 0x1a04, 0x36c2, 0x0126, 0x2091, 0x8000,
-	0x8003, 0x800b, 0x810b, 0x9108, 0x00c6, 0x2061, 0x1a04, 0x614a,
-	0x00ce, 0x012e, 0x0804, 0x368d, 0x00c6, 0x080c, 0x779e, 0x1160,
-	0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001, 0x080c, 0x77e2,
-	0x080c, 0x76cd, 0x080c, 0x0d85, 0x2061, 0x1800, 0x6030, 0xc09d,
-	0x6032, 0x080c, 0x6058, 0x00ce, 0x0005, 0x00c6, 0x2001, 0x1800,
-	0x2004, 0x908e, 0x0000, 0x0904, 0x36bf, 0x7884, 0x9005, 0x0188,
-	0x7888, 0x2061, 0x199c, 0x2c0c, 0x2062, 0x080c, 0x2a67, 0x01a0,
-	0x080c, 0x2a6f, 0x0188, 0x080c, 0x2a77, 0x0170, 0x2162, 0x0804,
-	0x36c2, 0x2061, 0x0100, 0x6038, 0x9086, 0x0007, 0x1118, 0x2009,
-	0x0001, 0x0010, 0x2009, 0x0000, 0x7884, 0x9086, 0x0002, 0x15a8,
-	0x2061, 0x0100, 0x6028, 0xc09c, 0x602a, 0x080c, 0xacfc, 0x0026,
-	0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, 0xa635,
-	0x002e, 0x080c, 0xa516, 0x0036, 0x901e, 0x080c, 0xa596, 0x003e,
-	0x080c, 0xad18, 0x60e3, 0x0000, 0x080c, 0xeed9, 0x080c, 0xeef4,
-	0x9085, 0x0001, 0x080c, 0x77e2, 0x9006, 0x080c, 0x2a99, 0x2001,
-	0x1800, 0x2003, 0x0004, 0x2001, 0x19a8, 0x2003, 0x0000, 0x0026,
-	0x2011, 0x0008, 0x080c, 0x2ad3, 0x002e, 0x00ce, 0x0804, 0x368d,
-	0x81ff, 0x0120, 0x2009, 0x0001, 0x0804, 0x36bf, 0x080c, 0x5854,
-	0x0120, 0x2009, 0x0007, 0x0804, 0x36bf, 0x7984, 0x7ea8, 0x96b4,
-	0x00ff, 0x080c, 0x67b4, 0x1904, 0x36c2, 0x9186, 0x007f, 0x0138,
-	0x080c, 0x6c11, 0x0120, 0x2009, 0x0009, 0x0804, 0x36bf, 0x080c,
-	0x4c41, 0x1120, 0x2009, 0x0002, 0x0804, 0x36bf, 0xa867, 0x0000,
-	0xa868, 0xc0fd, 0xa86a, 0x080c, 0xd109, 0x1120, 0x2009, 0x0003,
-	0x0804, 0x36bf, 0x7007, 0x0003, 0x701f, 0x5777, 0x0005, 0xa830,
-	0x9086, 0x0100, 0x1120, 0x2009, 0x0004, 0x0804, 0x36bf, 0xa8e0,
-	0xa866, 0xa834, 0x8007, 0x800c, 0xa85c, 0x9080, 0x000c, 0x7a8c,
-	0x7b88, 0x7c9c, 0x7d98, 0xaf60, 0x0804, 0x4c8d, 0xa898, 0x9086,
-	0x000d, 0x1904, 0x36bf, 0x2021, 0x4005, 0x0126, 0x2091, 0x8000,
-	0x0e04, 0x579b, 0x0010, 0x012e, 0x0cc0, 0x7c36, 0x9486, 0x4000,
-	0x0118, 0x7833, 0x0011, 0x0010, 0x7833, 0x0010, 0x7883, 0x4005,
-	0xa998, 0x7986, 0xa9a4, 0x799a, 0xa9a8, 0x799e, 0x080c, 0x4c7d,
-	0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200,
-	0x7007, 0x0001, 0x2091, 0x5000, 0x700f, 0x0000, 0x012e, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x00c6, 0x2061, 0x1a04, 0x7984, 0x615a,
-	0x6156, 0x605f, 0x0000, 0x6053, 0x0009, 0x7898, 0x6072, 0x789c,
-	0x606e, 0x7888, 0x606a, 0x788c, 0x6066, 0x2001, 0x1a14, 0x2044,
-	0x2001, 0x1a1b, 0xa076, 0xa060, 0xa072, 0xa07b, 0x0001, 0xa07f,
-	0x0002, 0xa06b, 0x0000, 0xa09f, 0x0000, 0x00ce, 0x012e, 0x0804,
-	0x368d, 0x0126, 0x2091, 0x8000, 0x00b6, 0x00c6, 0x90e4, 0xc000,
-	0x0198, 0x0006, 0xd0d4, 0x0160, 0x0036, 0x2019, 0x0029, 0x080c,
-	0xacfc, 0x0106, 0x080c, 0x3442, 0x010e, 0x090c, 0xad18, 0x003e,
-	0x080c, 0xcf68, 0x000e, 0x1198, 0xd0e4, 0x0160, 0x9180, 0x1000,
-	0x2004, 0x905d, 0x0160, 0x080c, 0x61b7, 0x080c, 0xb094, 0x0110,
-	0xb817, 0x0000, 0x9006, 0x00ce, 0x00be, 0x012e, 0x0005, 0x9085,
-	0x0001, 0x0cc8, 0x0126, 0x2091, 0x8000, 0x0156, 0x2010, 0x900e,
-	0x20a9, 0x0800, 0x0016, 0x9180, 0x1000, 0x2004, 0x9005, 0x0188,
-	0x9186, 0x007e, 0x0170, 0x9186, 0x007f, 0x0158, 0x9186, 0x0080,
-	0x0140, 0x9186, 0x00ff, 0x0128, 0x0026, 0x2200, 0x080c, 0x57e9,
-	0x002e, 0x001e, 0x8108, 0x1f04, 0x5822, 0x015e, 0x012e, 0x0005,
-	0x2001, 0x1848, 0x2004, 0x0005, 0x2001, 0x1867, 0x2004, 0x0005,
-	0x0006, 0x2001, 0x1810, 0x2004, 0xd0d4, 0x000e, 0x0005, 0x2001,
-	0x180e, 0x2004, 0xd0b4, 0x0005, 0x2001, 0x1800, 0x2004, 0x9086,
-	0x0003, 0x0005, 0x0016, 0x00e6, 0x2071, 0x189e, 0x7108, 0x910d,
-	0x710a, 0x00ee, 0x001e, 0x0005, 0x79a4, 0x81ff, 0x0904, 0x36c2,
-	0x9182, 0x0081, 0x1a04, 0x36c2, 0x810c, 0x0016, 0x080c, 0x4c41,
-	0x0170, 0x080c, 0x0f61, 0x2100, 0x2238, 0x7d84, 0x7c88, 0x7b8c,
-	0x7a90, 0x001e, 0x080c, 0x4c8a, 0x701f, 0x5884, 0x0005, 0x001e,
-	0x2009, 0x0002, 0x0804, 0x36bf, 0x2079, 0x0000, 0x7d94, 0x7c98,
-	0x7ba8, 0x7aac, 0x79a4, 0x810c, 0x2061, 0x18b8, 0x2c44, 0xa770,
-	0xa074, 0x2071, 0x189e, 0x080c, 0x4c8d, 0x701f, 0x5898, 0x0005,
-	0x2061, 0x18b8, 0x2c44, 0x0016, 0x0026, 0xa270, 0xa174, 0x080c,
-	0x0f69, 0x002e, 0x001e, 0x080c, 0x1016, 0x9006, 0xa802, 0xa806,
-	0x0804, 0x368d, 0x0126, 0x0156, 0x0136, 0x0146, 0x01c6, 0x01d6,
-	0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2061, 0x0100, 0x2069, 0x0200,
-	0x2071, 0x1800, 0x6044, 0xd0a4, 0x11e8, 0xd084, 0x0118, 0x080c,
-	0x5a58, 0x0068, 0xd08c, 0x0118, 0x080c, 0x5961, 0x0040, 0xd094,
-	0x0118, 0x080c, 0x5931, 0x0018, 0xd09c, 0x0108, 0x0099, 0x00fe,
-	0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce, 0x014e, 0x013e, 0x015e,
-	0x012e, 0x0005, 0x0016, 0x6128, 0xd19c, 0x1110, 0xc19d, 0x612a,
-	0x001e, 0x0c68, 0x7030, 0xd09c, 0x1120, 0x6004, 0x9085, 0x0002,
-	0x6006, 0x7098, 0x9005, 0x0120, 0x709b, 0x0000, 0x7093, 0x0000,
-	0x624c, 0x9286, 0xf0f0, 0x1150, 0x6048, 0x9086, 0xf0f0, 0x0130,
-	0x624a, 0x6043, 0x0090, 0x6043, 0x0010, 0x0490, 0x9294, 0xff00,
-	0x9296, 0xf700, 0x0178, 0x7138, 0xd1a4, 0x1160, 0x6240, 0x9295,
-	0x0100, 0x6242, 0x9294, 0x0010, 0x0128, 0x2009, 0x00f7, 0x080c,
-	0x6119, 0x00f0, 0x6040, 0x9084, 0x0010, 0x9085, 0x0140, 0x6042,
-	0x6043, 0x0000, 0x7087, 0x0000, 0x70a3, 0x0001, 0x70c7, 0x0000,
-	0x70df, 0x0000, 0x2009, 0x1d80, 0x200b, 0x0000, 0x7097, 0x0000,
-	0x708b, 0x000f, 0x2009, 0x000f, 0x2011, 0x5ffb, 0x080c, 0x8a5d,
-	0x0005, 0x2001, 0x1869, 0x2004, 0xd08c, 0x0110, 0x705f, 0xffff,
-	0x7088, 0x9005, 0x1528, 0x2011, 0x5ffb, 0x080c, 0x8993, 0x6040,
-	0x9094, 0x0010, 0x9285, 0x0020, 0x6042, 0x20a9, 0x00c8, 0x6044,
-	0xd08c, 0x1168, 0x1f04, 0x5947, 0x6242, 0x709b, 0x0000, 0x6040,
-	0x9094, 0x0010, 0x9285, 0x0080, 0x6042, 0x6242, 0x0048, 0x6242,
-	0x709b, 0x0000, 0x708f, 0x0000, 0x9006, 0x080c, 0x61a2, 0x0000,
-	0x0005, 0x708c, 0x908a, 0x0003, 0x1a0c, 0x0d85, 0x000b, 0x0005,
-	0x596b, 0x59bc, 0x5a57, 0x00f6, 0x0016, 0x6900, 0x918c, 0x0800,
-	0x708f, 0x0001, 0x2001, 0x015d, 0x2003, 0x0000, 0x6803, 0x00fc,
-	0x20a9, 0x0004, 0x6800, 0x9084, 0x00fc, 0x0120, 0x1f04, 0x597a,
-	0x080c, 0x0d85, 0x68a0, 0x68a2, 0x689c, 0x689e, 0x6898, 0x689a,
-	0xa001, 0x918d, 0x1600, 0x6902, 0x001e, 0x6837, 0x0020, 0x080c,
-	0x617e, 0x2079, 0x1d00, 0x7833, 0x1101, 0x7837, 0x0000, 0x20e1,
-	0x0001, 0x2099, 0x1805, 0x20e9, 0x0001, 0x20a1, 0x1d0e, 0x20a9,
-	0x0004, 0x4003, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099, 0x1d00,
-	0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003, 0x60c3,
-	0x000c, 0x600f, 0x0000, 0x080c, 0x602c, 0x00fe, 0x9006, 0x7092,
-	0x6043, 0x0008, 0x6042, 0x0005, 0x00f6, 0x7090, 0x7093, 0x0000,
-	0x9025, 0x0904, 0x5a34, 0x6020, 0xd0b4, 0x1904, 0x5a32, 0x71a0,
-	0x81ff, 0x0904, 0x5a20, 0x9486, 0x000c, 0x1904, 0x5a2d, 0x9480,
-	0x0018, 0x8004, 0x20a8, 0x080c, 0x6177, 0x2011, 0x0260, 0x2019,
-	0x1d00, 0x220c, 0x2304, 0x9106, 0x11e8, 0x8210, 0x8318, 0x1f04,
-	0x59d9, 0x6043, 0x0004, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f,
-	0xf0f0, 0x2061, 0x0100, 0x6043, 0x0006, 0x708f, 0x0002, 0x709b,
-	0x0002, 0x2009, 0x07d0, 0x2011, 0x6002, 0x080c, 0x8a5d, 0x080c,
-	0x617e, 0x04c0, 0x080c, 0x6177, 0x2079, 0x0260, 0x7930, 0x918e,
-	0x1101, 0x1558, 0x7834, 0x9005, 0x1540, 0x7900, 0x918c, 0x00ff,
-	0x1118, 0x7804, 0x9005, 0x0190, 0x080c, 0x6177, 0x2011, 0x026e,
-	0x2019, 0x1805, 0x20a9, 0x0004, 0x220c, 0x2304, 0x9102, 0x0230,
-	0x11a0, 0x8210, 0x8318, 0x1f04, 0x5a14, 0x0078, 0x70a3, 0x0000,
-	0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, 0x0260, 0x20e9, 0x0001,
-	0x20a1, 0x1d00, 0x20a9, 0x0014, 0x4003, 0x6043, 0x0008, 0x6043,
-	0x0000, 0x0010, 0x00fe, 0x0005, 0x6040, 0x9085, 0x0100, 0x6042,
-	0x6020, 0xd0b4, 0x1db8, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099,
-	0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x0014, 0x4003,
-	0x60c3, 0x000c, 0x2011, 0x19f5, 0x2013, 0x0000, 0x7093, 0x0000,
-	0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa293, 0x08d8, 0x0005,
-	0x7098, 0x908a, 0x001d, 0x1a0c, 0x0d85, 0x000b, 0x0005, 0x5a89,
-	0x5a9c, 0x5ac5, 0x5ae5, 0x5b0b, 0x5b3a, 0x5b60, 0x5b98, 0x5bbe,
-	0x5bec, 0x5c27, 0x5c5f, 0x5c7d, 0x5ca8, 0x5cca, 0x5ce5, 0x5cef,
-	0x5d23, 0x5d49, 0x5d78, 0x5d9e, 0x5dd6, 0x5e1a, 0x5e57, 0x5e78,
-	0x5ed1, 0x5ef3, 0x5f21, 0x5f21, 0x00c6, 0x2061, 0x1800, 0x6003,
-	0x0007, 0x2061, 0x0100, 0x6004, 0x9084, 0xfff9, 0x6006, 0x00ce,
-	0x0005, 0x2061, 0x0140, 0x605b, 0xbc94, 0x605f, 0xf0f0, 0x2061,
-	0x0100, 0x6043, 0x0002, 0x709b, 0x0001, 0x2009, 0x07d0, 0x2011,
-	0x6002, 0x080c, 0x8a5d, 0x0005, 0x00f6, 0x7090, 0x9086, 0x0014,
-	0x1510, 0x6042, 0x6020, 0xd0b4, 0x11f0, 0x080c, 0x6177, 0x2079,
-	0x0260, 0x7a30, 0x9296, 0x1102, 0x11a0, 0x7834, 0x9005, 0x1188,
-	0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001,
-	0x2011, 0x6002, 0x080c, 0x8993, 0x709b, 0x0010, 0x080c, 0x5cef,
-	0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0003,
-	0x6043, 0x0004, 0x2011, 0x6002, 0x080c, 0x8993, 0x080c, 0x60fb,
-	0x2079, 0x0240, 0x7833, 0x1102, 0x7837, 0x0000, 0x20a9, 0x0008,
-	0x9f88, 0x000e, 0x200b, 0x0000, 0x8108, 0x1f04, 0x5ada, 0x60c3,
-	0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005,
-	0x0500, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8,
-	0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1102, 0x1178,
-	0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005,
-	0x1110, 0x70c7, 0x0001, 0x709b, 0x0004, 0x0029, 0x0010, 0x080c,
-	0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x0005, 0x080c, 0x60fb,
-	0x2079, 0x0240, 0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x6177,
-	0x080c, 0x615a, 0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186,
-	0xffff, 0x0138, 0x2011, 0x0008, 0x080c, 0x5faf, 0x0168, 0x080c,
-	0x6130, 0x20a9, 0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9,
-	0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c,
-	0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002,
-	0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079,
-	0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005, 0x1160,
-	0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001,
-	0x709b, 0x0006, 0x0029, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005,
-	0x00f6, 0x709b, 0x0007, 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833,
-	0x1104, 0x7837, 0x0000, 0x080c, 0x6177, 0x080c, 0x615a, 0x11b8,
-	0x7084, 0x9005, 0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180,
-	0x348e, 0x200d, 0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c,
-	0x5faf, 0x0180, 0x080c, 0x512e, 0x0110, 0x080c, 0x26f5, 0x20a9,
-	0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1,
-	0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005,
-	0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, 0x080c, 0x8993,
-	0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30,
-	0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc,
-	0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0008,
-	0x0029, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b,
-	0x0009, 0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, 0x1105, 0x7837,
-	0x0100, 0x080c, 0x615a, 0x1150, 0x7084, 0x9005, 0x1138, 0x080c,
-	0x5f22, 0x1188, 0x9085, 0x0001, 0x080c, 0x26f5, 0x20a9, 0x0008,
-	0x080c, 0x6177, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000,
-	0x20a1, 0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x0010,
-	0x080c, 0x5a7c, 0x00fe, 0x0005, 0x00f6, 0x7090, 0x9005, 0x05a8,
-	0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x1560, 0x080c,
-	0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105, 0x1520, 0x7834,
-	0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1160, 0x7a38, 0xd2fc,
-	0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x000a,
-	0x00b1, 0x0098, 0x9005, 0x1178, 0x7a38, 0xd2fc, 0x0128, 0x70c4,
-	0x9005, 0x1110, 0x70c7, 0x0001, 0x7097, 0x0000, 0x709b, 0x000e,
-	0x080c, 0x5cca, 0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6,
-	0x709b, 0x000b, 0x2011, 0x1d0e, 0x20e9, 0x0001, 0x22a0, 0x20a9,
-	0x0040, 0x2019, 0xffff, 0x4304, 0x080c, 0x60fb, 0x2079, 0x0240,
-	0x7833, 0x1106, 0x7837, 0x0000, 0x080c, 0x615a, 0x0118, 0x2013,
-	0x0000, 0x0020, 0x7060, 0x9085, 0x0100, 0x2012, 0x20a9, 0x0040,
-	0x2009, 0x024e, 0x2011, 0x1d0e, 0x220e, 0x8210, 0x8108, 0x9186,
-	0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x1f04,
-	0x5c4c, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6,
-	0x7090, 0x9005, 0x01c0, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086,
-	0x0084, 0x1178, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296,
-	0x1106, 0x1138, 0x7834, 0x9005, 0x1120, 0x709b, 0x000c, 0x0029,
-	0x0010, 0x080c, 0x6153, 0x00fe, 0x0005, 0x00f6, 0x709b, 0x000d,
-	0x080c, 0x60fb, 0x2079, 0x0240, 0x7833, 0x1107, 0x7837, 0x0000,
-	0x080c, 0x6177, 0x20a9, 0x0040, 0x2011, 0x026e, 0x2009, 0x024e,
-	0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150, 0x6810, 0x8000,
-	0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816, 0x2011, 0x0260,
-	0x1f04, 0x5c90, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe, 0x0005,
-	0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x6002, 0x080c, 0x8993,
-	0x9086, 0x0084, 0x1198, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30,
-	0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097, 0x0001,
-	0x080c, 0x60cd, 0x709b, 0x000e, 0x0029, 0x0010, 0x080c, 0x6153,
-	0x00fe, 0x0005, 0x918d, 0x0001, 0x080c, 0x61a2, 0x709b, 0x000f,
-	0x7093, 0x0000, 0x2061, 0x0140, 0x605b, 0xbc85, 0x605f, 0xb5b5,
-	0x2061, 0x0100, 0x6043, 0x0005, 0x6043, 0x0004, 0x2009, 0x07d0,
-	0x2011, 0x6002, 0x080c, 0x8987, 0x0005, 0x7090, 0x9005, 0x0130,
-	0x2011, 0x6002, 0x080c, 0x8993, 0x709b, 0x0000, 0x0005, 0x709b,
-	0x0011, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099,
-	0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x7490, 0x9480, 0x0018,
-	0x9080, 0x0007, 0x9084, 0x03f8, 0x8004, 0x20a8, 0x4003, 0x080c,
-	0x615a, 0x11a0, 0x717c, 0x81ff, 0x0188, 0x900e, 0x7080, 0x9084,
-	0x00ff, 0x0160, 0x080c, 0x268c, 0x9186, 0x007e, 0x0138, 0x9186,
-	0x0080, 0x0120, 0x2011, 0x0008, 0x080c, 0x5faf, 0x60c3, 0x0014,
-	0x080c, 0x602c, 0x0005, 0x00f6, 0x7090, 0x9005, 0x0500, 0x2011,
-	0x6002, 0x080c, 0x8993, 0x9086, 0x0014, 0x11b8, 0x080c, 0x6177,
-	0x2079, 0x0260, 0x7a30, 0x9296, 0x1103, 0x1178, 0x7834, 0x9005,
-	0x1160, 0x7a38, 0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7,
-	0x0001, 0x709b, 0x0012, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe,
-	0x0005, 0x00f6, 0x709b, 0x0013, 0x080c, 0x6109, 0x2079, 0x0240,
-	0x7833, 0x1103, 0x7837, 0x0000, 0x080c, 0x6177, 0x080c, 0x615a,
-	0x1170, 0x7084, 0x9005, 0x1158, 0x715c, 0x9186, 0xffff, 0x0138,
-	0x2011, 0x0008, 0x080c, 0x5faf, 0x0168, 0x080c, 0x6130, 0x20a9,
-	0x0008, 0x20e1, 0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1,
-	0x024e, 0x4003, 0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005,
-	0x00f6, 0x7090, 0x9005, 0x0500, 0x2011, 0x6002, 0x080c, 0x8993,
-	0x9086, 0x0014, 0x11b8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30,
-	0x9296, 0x1104, 0x1178, 0x7834, 0x9005, 0x1160, 0x7a38, 0xd2fc,
-	0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x709b, 0x0014,
-	0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005, 0x00f6, 0x709b,
-	0x0015, 0x080c, 0x6109, 0x2079, 0x0240, 0x7833, 0x1104, 0x7837,
-	0x0000, 0x080c, 0x6177, 0x080c, 0x615a, 0x11b8, 0x7084, 0x9005,
-	0x11a0, 0x7164, 0x9186, 0xffff, 0x0180, 0x9180, 0x348e, 0x200d,
-	0x918c, 0xff00, 0x810f, 0x2011, 0x0008, 0x080c, 0x5faf, 0x0180,
-	0x080c, 0x512e, 0x0110, 0x080c, 0x26f5, 0x20a9, 0x0008, 0x20e1,
-	0x0000, 0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003,
-	0x60c3, 0x0014, 0x080c, 0x602c, 0x00fe, 0x0005, 0x00f6, 0x7090,
-	0x9005, 0x05f0, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086, 0x0014,
-	0x15a8, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296, 0x1105,
-	0x1568, 0x7834, 0x9084, 0x0100, 0x2011, 0x0100, 0x921e, 0x1168,
-	0x9085, 0x0001, 0x080c, 0x61a2, 0x7a38, 0xd2fc, 0x0128, 0x70c4,
-	0x9005, 0x1110, 0x70c7, 0x0001, 0x0080, 0x9005, 0x11b8, 0x7a38,
-	0xd2fc, 0x0128, 0x70c4, 0x9005, 0x1110, 0x70c7, 0x0001, 0x9085,
-	0x0001, 0x080c, 0x61a2, 0x7097, 0x0000, 0x7a38, 0xd2f4, 0x0110,
-	0x70df, 0x0008, 0x709b, 0x0016, 0x0029, 0x0010, 0x7093, 0x0000,
-	0x00fe, 0x0005, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000,
-	0x2099, 0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000e,
-	0x4003, 0x2011, 0x026d, 0x2204, 0x9084, 0x0100, 0x2011, 0x024d,
-	0x2012, 0x2011, 0x026e, 0x709b, 0x0017, 0x080c, 0x615a, 0x1150,
-	0x7084, 0x9005, 0x1138, 0x080c, 0x5f22, 0x1188, 0x9085, 0x0001,
-	0x080c, 0x26f5, 0x20a9, 0x0008, 0x080c, 0x6177, 0x20e1, 0x0000,
-	0x2099, 0x026e, 0x20e9, 0x0000, 0x20a1, 0x024e, 0x4003, 0x60c3,
-	0x0014, 0x080c, 0x602c, 0x0010, 0x080c, 0x5a7c, 0x0005, 0x00f6,
-	0x7090, 0x9005, 0x01d8, 0x2011, 0x6002, 0x080c, 0x8993, 0x9086,
-	0x0084, 0x1190, 0x080c, 0x6177, 0x2079, 0x0260, 0x7a30, 0x9296,
-	0x1106, 0x1150, 0x7834, 0x9005, 0x1138, 0x9006, 0x080c, 0x61a2,
-	0x709b, 0x0018, 0x0029, 0x0010, 0x7093, 0x0000, 0x00fe, 0x0005,
-	0x00f6, 0x709b, 0x0019, 0x080c, 0x6109, 0x2079, 0x0240, 0x7833,
-	0x1106, 0x7837, 0x0000, 0x080c, 0x6177, 0x2009, 0x026e, 0x2039,
-	0x1d0e, 0x20a9, 0x0040, 0x213e, 0x8738, 0x8108, 0x9186, 0x0280,
-	0x1128, 0x6814, 0x8000, 0x6816, 0x2009, 0x0260, 0x1f04, 0x5e8b,
-	0x2039, 0x1d0e, 0x080c, 0x615a, 0x11e8, 0x2728, 0x2514, 0x8207,
-	0x9084, 0x00ff, 0x8000, 0x2018, 0x9294, 0x00ff, 0x8007, 0x9205,
-	0x202a, 0x7060, 0x2310, 0x8214, 0x92a0, 0x1d0e, 0x2414, 0x938c,
-	0x0001, 0x0118, 0x9294, 0xff00, 0x0018, 0x9294, 0x00ff, 0x8007,
-	0x9215, 0x2222, 0x20a9, 0x0040, 0x2009, 0x024e, 0x270e, 0x8738,
-	0x8108, 0x9186, 0x0260, 0x1128, 0x6810, 0x8000, 0x6812, 0x2009,
-	0x0240, 0x1f04, 0x5ebe, 0x60c3, 0x0084, 0x080c, 0x602c, 0x00fe,
-	0x0005, 0x00f6, 0x7090, 0x9005, 0x01e0, 0x2011, 0x6002, 0x080c,
-	0x8993, 0x9086, 0x0084, 0x1198, 0x080c, 0x6177, 0x2079, 0x0260,
-	0x7a30, 0x9296, 0x1107, 0x1158, 0x7834, 0x9005, 0x1140, 0x7097,
-	0x0001, 0x080c, 0x60cd, 0x709b, 0x001a, 0x0029, 0x0010, 0x7093,
-	0x0000, 0x00fe, 0x0005, 0x9085, 0x0001, 0x080c, 0x61a2, 0x709b,
-	0x001b, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x2011, 0x0260, 0x2009,
-	0x0240, 0x7490, 0x9480, 0x0018, 0x9080, 0x0007, 0x9084, 0x03f8,
-	0x8004, 0x20a8, 0x220e, 0x8210, 0x8108, 0x9186, 0x0260, 0x1150,
-	0x6810, 0x8000, 0x6812, 0x2009, 0x0240, 0x6814, 0x8000, 0x6816,
-	0x2011, 0x0260, 0x1f04, 0x5f0a, 0x60c3, 0x0084, 0x080c, 0x602c,
-	0x0005, 0x0005, 0x0086, 0x0096, 0x2029, 0x1848, 0x252c, 0x20a9,
-	0x0008, 0x2041, 0x1d0e, 0x20e9, 0x0001, 0x28a0, 0x080c, 0x6177,
-	0x20e1, 0x0000, 0x2099, 0x026e, 0x4003, 0x20a9, 0x0008, 0x2011,
-	0x0007, 0xd5d4, 0x0108, 0x9016, 0x2800, 0x9200, 0x200c, 0x91a6,
-	0xffff, 0x1148, 0xd5d4, 0x0110, 0x8210, 0x0008, 0x8211, 0x1f04,
-	0x5f3c, 0x0804, 0x5fab, 0x82ff, 0x1160, 0xd5d4, 0x0120, 0x91a6,
-	0x3fff, 0x0d90, 0x0020, 0x91a6, 0x3fff, 0x0904, 0x5fab, 0x918d,
-	0xc000, 0x20a9, 0x0010, 0x2019, 0x0001, 0xd5d4, 0x0110, 0x2019,
-	0x0010, 0x2120, 0xd5d4, 0x0110, 0x8423, 0x0008, 0x8424, 0x1240,
-	0xd5d4, 0x0110, 0x8319, 0x0008, 0x8318, 0x1f04, 0x5f62, 0x04d8,
-	0x23a8, 0x2021, 0x0001, 0x8426, 0x8425, 0x1f04, 0x5f74, 0x2328,
-	0x8529, 0x92be, 0x0007, 0x0158, 0x0006, 0x2039, 0x0007, 0x2200,
-	0x973a, 0x000e, 0x27a8, 0x95a8, 0x0010, 0x1f04, 0x5f83, 0x755e,
-	0x95c8, 0x348e, 0x292d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536,
-	0x0016, 0x2508, 0x080c, 0x26d5, 0x001e, 0x60e7, 0x0000, 0x65ea,
-	0x2018, 0x2304, 0x9405, 0x201a, 0x7087, 0x0001, 0x20e9, 0x0000,
-	0x20a1, 0x024e, 0x20e1, 0x0001, 0x2898, 0x20a9, 0x0008, 0x4003,
-	0x9085, 0x0001, 0x0008, 0x9006, 0x009e, 0x008e, 0x0005, 0x0156,
-	0x01c6, 0x01d6, 0x0136, 0x0146, 0x22a8, 0x20e1, 0x0000, 0x2099,
-	0x026e, 0x20e9, 0x0000, 0x2011, 0x024e, 0x22a0, 0x4003, 0x014e,
-	0x013e, 0x01de, 0x01ce, 0x015e, 0x2118, 0x9026, 0x2001, 0x0007,
-	0x939a, 0x0010, 0x0218, 0x8420, 0x8001, 0x0cd0, 0x2118, 0x84ff,
-	0x0120, 0x939a, 0x0010, 0x8421, 0x1de0, 0x2021, 0x0001, 0x83ff,
-	0x0118, 0x8423, 0x8319, 0x1de8, 0x9238, 0x2029, 0x026e, 0x9528,
-	0x2504, 0x942c, 0x11b8, 0x9405, 0x203a, 0x715e, 0x91a0, 0x348e,
-	0x242d, 0x95ac, 0x00ff, 0x7582, 0x6532, 0x6536, 0x0016, 0x2508,
-	0x080c, 0x26d5, 0x001e, 0x60e7, 0x0000, 0x65ea, 0x7087, 0x0001,
-	0x9084, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1800, 0x708b, 0x0000,
-	0x00ee, 0x0005, 0x00e6, 0x00f6, 0x2079, 0x0100, 0x2071, 0x0140,
-	0x080c, 0x60bc, 0x080c, 0xa2a0, 0x7004, 0x9084, 0x4000, 0x0110,
-	0x080c, 0x2aa9, 0x0126, 0x2091, 0x8000, 0x2071, 0x1826, 0x2073,
-	0x0000, 0x7840, 0x0026, 0x0016, 0x2009, 0x00f7, 0x080c, 0x6119,
-	0x001e, 0x9094, 0x0010, 0x9285, 0x0080, 0x7842, 0x7a42, 0x002e,
-	0x012e, 0x00fe, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x2a04, 0x0228, 0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x2011,
-	0x19f5, 0x2013, 0x0000, 0x7093, 0x0000, 0x012e, 0x60a3, 0x0056,
-	0x60a7, 0x9575, 0x080c, 0xa293, 0x6144, 0xd184, 0x0120, 0x7198,
-	0x918d, 0x2000, 0x0018, 0x718c, 0x918d, 0x1000, 0x2011, 0x1999,
-	0x2112, 0x2009, 0x07d0, 0x2011, 0x6002, 0x080c, 0x8a5d, 0x0005,
-	0x0016, 0x0026, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc,
-	0x080c, 0xb09b, 0x080c, 0xad18, 0x2009, 0x00f7, 0x080c, 0x6119,
-	0x2061, 0x1a04, 0x900e, 0x611a, 0x611e, 0x617a, 0x617e, 0x2061,
-	0x1800, 0x6003, 0x0001, 0x2061, 0x0100, 0x6043, 0x0090, 0x6043,
-	0x0010, 0x2009, 0x1999, 0x200b, 0x0000, 0x2009, 0x002d, 0x2011,
-	0x6088, 0x080c, 0x8987, 0x012e, 0x00ce, 0x002e, 0x001e, 0x0005,
-	0x00e6, 0x0006, 0x0126, 0x2091, 0x8000, 0x0471, 0x2071, 0x0100,
-	0x080c, 0xa2a0, 0x2071, 0x0140, 0x7004, 0x9084, 0x4000, 0x0110,
-	0x080c, 0x2aa9, 0x080c, 0x77a6, 0x0188, 0x080c, 0x77c1, 0x1170,
-	0x080c, 0x7ac0, 0x0016, 0x080c, 0x27a4, 0x2001, 0x196d, 0x2102,
-	0x001e, 0x080c, 0x7abb, 0x080c, 0x76cd, 0x0050, 0x2009, 0x0001,
-	0x080c, 0x2a85, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c, 0x6058,
-	0x012e, 0x000e, 0x00ee, 0x0005, 0x2001, 0x180e, 0x2004, 0xd0bc,
-	0x0158, 0x0026, 0x0036, 0x2011, 0x8017, 0x2001, 0x1999, 0x201c,
-	0x080c, 0x4ca1, 0x003e, 0x002e, 0x0005, 0x20a9, 0x0012, 0x20e9,
-	0x0001, 0x20a1, 0x1d80, 0x080c, 0x6177, 0x20e9, 0x0000, 0x2099,
-	0x026e, 0x0099, 0x20a9, 0x0020, 0x080c, 0x6171, 0x2099, 0x0260,
-	0x20a1, 0x1d92, 0x0051, 0x20a9, 0x000e, 0x080c, 0x6174, 0x2099,
-	0x0260, 0x20a1, 0x1db2, 0x0009, 0x0005, 0x0016, 0x0026, 0x3410,
-	0x3308, 0x2104, 0x8007, 0x2012, 0x8108, 0x8210, 0x1f04, 0x60f1,
-	0x002e, 0x001e, 0x0005, 0x080c, 0xaaf1, 0x20e1, 0x0001, 0x2099,
-	0x1d00, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003,
-	0x0005, 0x080c, 0xaaf1, 0x080c, 0x6177, 0x20e1, 0x0000, 0x2099,
-	0x0260, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000c, 0x4003,
-	0x0005, 0x00c6, 0x0006, 0x2061, 0x0100, 0x810f, 0x2001, 0x1834,
-	0x2004, 0x9005, 0x1138, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff,
-	0x9105, 0x0010, 0x9185, 0x00f7, 0x604a, 0x000e, 0x00ce, 0x0005,
-	0x0016, 0x0046, 0x080c, 0x6c0d, 0x0158, 0x9006, 0x2020, 0x2009,
-	0x002a, 0x080c, 0xea8d, 0x2001, 0x180c, 0x200c, 0xc195, 0x2102,
-	0x2019, 0x002a, 0x900e, 0x080c, 0x32da, 0x080c, 0xd645, 0x0140,
-	0x0036, 0x2019, 0xffff, 0x2021, 0x0007, 0x080c, 0x4e58, 0x003e,
-	0x004e, 0x001e, 0x0005, 0x080c, 0x6058, 0x709b, 0x0000, 0x7093,
-	0x0000, 0x0005, 0x0006, 0x2001, 0x180c, 0x2004, 0xd09c, 0x0100,
-	0x000e, 0x0005, 0x0006, 0x0016, 0x0126, 0x2091, 0x8000, 0x2001,
-	0x0101, 0x200c, 0x918d, 0x0006, 0x2102, 0x012e, 0x001e, 0x000e,
-	0x0005, 0x2009, 0x0001, 0x0020, 0x2009, 0x0002, 0x0008, 0x900e,
-	0x6814, 0x9084, 0xffc0, 0x910d, 0x6916, 0x0005, 0x00f6, 0x0156,
-	0x0146, 0x01d6, 0x9006, 0x20a9, 0x0080, 0x20e9, 0x0001, 0x20a1,
-	0x1d00, 0x4004, 0x2079, 0x1d00, 0x7803, 0x2200, 0x7807, 0x00ef,
-	0x780f, 0x00ef, 0x7813, 0x0138, 0x7823, 0xffff, 0x7827, 0xffff,
-	0x01de, 0x014e, 0x015e, 0x00fe, 0x0005, 0x2001, 0x1800, 0x2003,
-	0x0001, 0x0005, 0x2001, 0x19a7, 0x0118, 0x2003, 0x0001, 0x0010,
-	0x2003, 0x0000, 0x0005, 0x0156, 0x20a9, 0x0800, 0x2009, 0x1000,
-	0x9006, 0x200a, 0x8108, 0x1f04, 0x61b1, 0x015e, 0x0005, 0x00d6,
-	0x0036, 0x0156, 0x0136, 0x0146, 0x2069, 0x1847, 0x9006, 0xb802,
-	0xb8d6, 0xb807, 0x0707, 0xb80a, 0xb80e, 0xb812, 0x9198, 0x348e,
-	0x231d, 0x939c, 0x00ff, 0xbb16, 0x0016, 0x0026, 0xb886, 0x080c,
-	0xb094, 0x1120, 0x9192, 0x007e, 0x1208, 0xbb86, 0x20a9, 0x0004,
-	0xb8c4, 0x20e8, 0xb9c8, 0x9198, 0x0006, 0x9006, 0x23a0, 0x4004,
-	0x20a9, 0x0004, 0x9198, 0x000a, 0x23a0, 0x4004, 0x002e, 0x001e,
-	0xb83e, 0xb842, 0xb8ce, 0xb8d2, 0xb85e, 0xb862, 0xb866, 0xb86a,
-	0xb86f, 0x0100, 0xb872, 0xb876, 0xb87a, 0xb88a, 0xb88e, 0xb893,
-	0x0008, 0xb896, 0xb89a, 0xb89e, 0xb8be, 0xb9a2, 0x0096, 0xb8a4,
-	0x904d, 0x0110, 0x080c, 0x108b, 0xb8a7, 0x0000, 0x009e, 0x9006,
-	0xb84a, 0x6810, 0xb83a, 0x680c, 0xb846, 0xb8bb, 0x0520, 0xb8ac,
-	0x9005, 0x0198, 0x00c6, 0x2060, 0x9c82, 0x1ddc, 0x0a0c, 0x0d85,
-	0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d85, 0x080c, 0x8eee,
-	0x00ce, 0x090c, 0x928d, 0xb8af, 0x0000, 0x6814, 0x9084, 0x00ff,
-	0xb842, 0x014e, 0x013e, 0x015e, 0x003e, 0x00de, 0x0005, 0x0126,
-	0x2091, 0x8000, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082, 0x4000,
-	0x1a04, 0x628d, 0x9182, 0x0800, 0x1a04, 0x6291, 0x2001, 0x180c,
-	0x2004, 0x9084, 0x0003, 0x1904, 0x6297, 0x9188, 0x1000, 0x2104,
-	0x905d, 0x0198, 0xb804, 0x9084, 0x00ff, 0x908e, 0x0006, 0x1188,
-	0xb8a4, 0x900d, 0x1904, 0x62a9, 0x080c, 0x6669, 0x9006, 0x012e,
-	0x0005, 0x2001, 0x0005, 0x900e, 0x04b8, 0x2001, 0x0028, 0x900e,
-	0x0498, 0x9082, 0x0006, 0x1290, 0x080c, 0xb094, 0x1160, 0xb8a0,
-	0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0d10, 0x2001, 0x0029,
-	0x2009, 0x1000, 0x0408, 0x2001, 0x0028, 0x00a8, 0x2009, 0x180c,
-	0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0068, 0xd184, 0x0118,
-	0x2001, 0x0004, 0x0040, 0x2001, 0x0029, 0xb900, 0xd1fc, 0x0118,
-	0x2009, 0x1000, 0x0048, 0x900e, 0x0038, 0x2001, 0x0029, 0x900e,
-	0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x012e, 0x0005, 0x2001,
-	0x180c, 0x2004, 0xd084, 0x19d0, 0x9188, 0x1000, 0x2104, 0x9065,
-	0x09a8, 0x080c, 0x6c11, 0x1990, 0xb800, 0xd0bc, 0x0978, 0x0804,
-	0x6250, 0x080c, 0x6a2a, 0x0904, 0x6259, 0x0804, 0x6254, 0x00e6,
-	0x2071, 0x19e8, 0x7004, 0x9086, 0x0002, 0x1128, 0x7030, 0x9080,
-	0x0004, 0x2004, 0x9b06, 0x00ee, 0x0005, 0x00b6, 0x00e6, 0x0126,
-	0x2091, 0x8000, 0xa874, 0x908e, 0x00ff, 0x1120, 0x2001, 0x196b,
-	0x205c, 0x0060, 0xa974, 0x9182, 0x0800, 0x1690, 0x9188, 0x1000,
-	0x2104, 0x905d, 0x01d0, 0x080c, 0x6bb1, 0x11d0, 0x080c, 0xb116,
-	0x0570, 0x2b00, 0x6012, 0x2900, 0x6016, 0x6023, 0x0009, 0x602b,
-	0x0000, 0xa874, 0x908e, 0x00ff, 0x1110, 0x602b, 0x8000, 0x2009,
-	0x0043, 0x080c, 0xb20a, 0x9006, 0x00b0, 0x2001, 0x0028, 0x0090,
-	0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0038,
-	0xd184, 0x0118, 0x2001, 0x0004, 0x0010, 0x2001, 0x0029, 0x0010,
-	0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001,
-	0x002c, 0x0cc0, 0x00b6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa974,
-	0x9182, 0x0800, 0x1a04, 0x6388, 0x9188, 0x1000, 0x2104, 0x905d,
-	0x0904, 0x6360, 0xb8a0, 0x9086, 0x007f, 0x0190, 0xa87c, 0xd0fc,
-	0x1178, 0x080c, 0x6c19, 0x0160, 0xa994, 0x81ff, 0x0130, 0x908e,
-	0x0004, 0x0130, 0x908e, 0x0005, 0x0118, 0x080c, 0x6c11, 0x1598,
-	0xa87c, 0xd0fc, 0x01e0, 0xa894, 0x9005, 0x01c8, 0x2060, 0x0026,
-	0x2010, 0x080c, 0xcf09, 0x002e, 0x1120, 0x2001, 0x0008, 0x0804,
-	0x638a, 0x6020, 0x9086, 0x000a, 0x0120, 0x2001, 0x0008, 0x0804,
-	0x638a, 0x601a, 0x6003, 0x0008, 0x2900, 0x6016, 0x0058, 0x080c,
-	0xb116, 0x05e8, 0x2b00, 0x6012, 0x2900, 0x6016, 0x600b, 0xffff,
-	0x6023, 0x000a, 0x2009, 0x0003, 0x080c, 0xb20a, 0x9006, 0x0458,
-	0x2001, 0x0028, 0x0438, 0x9082, 0x0006, 0x1290, 0x080c, 0xb094,
-	0x1160, 0xb8a0, 0x9084, 0xff80, 0x1140, 0xb900, 0xd1fc, 0x0900,
-	0x2001, 0x0029, 0x2009, 0x1000, 0x00a8, 0x2001, 0x0028, 0x0090,
-	0x2009, 0x180c, 0x210c, 0xd18c, 0x0118, 0x2001, 0x0004, 0x0050,
-	0xd184, 0x0118, 0x2001, 0x0004, 0x0028, 0x2001, 0x0029, 0x0010,
-	0x2001, 0x0029, 0x9005, 0x012e, 0x00ee, 0x00be, 0x0005, 0x2001,
-	0x002c, 0x0cc0, 0x00f6, 0x00b6, 0x0126, 0x2091, 0x8000, 0xa8e0,
-	0x9005, 0x1550, 0xa8dc, 0x9082, 0x0101, 0x1630, 0xa8c8, 0x9005,
-	0x1518, 0xa8c4, 0x9082, 0x0101, 0x12f8, 0xa974, 0x2079, 0x1800,
-	0x9182, 0x0800, 0x12e8, 0x7830, 0x9084, 0x0003, 0x1130, 0xaa98,
-	0xab94, 0xa878, 0x9084, 0x0007, 0x00ea, 0x7930, 0xd18c, 0x0118,
-	0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010,
-	0x2001, 0x0029, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018,
-	0x2001, 0x0029, 0x900e, 0x9006, 0x0008, 0x9005, 0x012e, 0x00be,
-	0x00fe, 0x0005, 0x641f, 0x63da, 0x63f1, 0x641f, 0x641f, 0x641f,
-	0x641f, 0x641f, 0x2100, 0x9082, 0x007e, 0x1278, 0x080c, 0x6749,
-	0x0148, 0x9046, 0xb810, 0x9306, 0x1904, 0x6427, 0xb814, 0x9206,
-	0x15f0, 0x0028, 0xbb12, 0xba16, 0x0010, 0x080c, 0x4b54, 0x0150,
-	0x04b0, 0x080c, 0x67b4, 0x1598, 0xb810, 0x9306, 0x1580, 0xb814,
-	0x9206, 0x1568, 0x080c, 0xb116, 0x0530, 0x2b00, 0x6012, 0x080c,
-	0xd3b6, 0x2900, 0x6016, 0x600b, 0xffff, 0x6023, 0x000a, 0xa878,
-	0x9086, 0x0001, 0x1170, 0x080c, 0x3315, 0x9006, 0x080c, 0x66e6,
-	0x2001, 0x0002, 0x080c, 0x66fa, 0x2001, 0x0200, 0xb86e, 0xb893,
-	0x0002, 0x2009, 0x0003, 0x080c, 0xb20a, 0x9006, 0x0068, 0x2001,
-	0x0001, 0x900e, 0x0038, 0x2001, 0x002c, 0x900e, 0x0018, 0x2001,
-	0x0028, 0x900e, 0x9005, 0x0000, 0x012e, 0x00be, 0x00fe, 0x0005,
-	0x00b6, 0x00f6, 0x00e6, 0x0126, 0x2091, 0x8000, 0xa894, 0x90c6,
-	0x0015, 0x0904, 0x6612, 0x90c6, 0x0056, 0x0904, 0x6616, 0x90c6,
-	0x0066, 0x0904, 0x661a, 0x90c6, 0x0067, 0x0904, 0x661e, 0x90c6,
-	0x0068, 0x0904, 0x6622, 0x90c6, 0x0071, 0x0904, 0x6626, 0x90c6,
-	0x0074, 0x0904, 0x662a, 0x90c6, 0x007c, 0x0904, 0x662e, 0x90c6,
-	0x007e, 0x0904, 0x6632, 0x90c6, 0x0037, 0x0904, 0x6636, 0x9016,
-	0x2079, 0x1800, 0xa974, 0x9186, 0x00ff, 0x0904, 0x660d, 0x9182,
-	0x0800, 0x1a04, 0x660d, 0x080c, 0x67b4, 0x1198, 0xb804, 0x9084,
-	0x00ff, 0x9082, 0x0006, 0x1268, 0xa894, 0x90c6, 0x006f, 0x0148,
-	0x080c, 0xb094, 0x1904, 0x65f6, 0xb8a0, 0x9084, 0xff80, 0x1904,
-	0x65f6, 0xa894, 0x90c6, 0x006f, 0x0158, 0x90c6, 0x005e, 0x0904,
-	0x6556, 0x90c6, 0x0064, 0x0904, 0x657f, 0x2008, 0x0804, 0x6518,
-	0xa998, 0xa8b0, 0x2040, 0x080c, 0xb094, 0x1120, 0x9182, 0x007f,
-	0x0a04, 0x6518, 0x9186, 0x00ff, 0x0904, 0x6518, 0x9182, 0x0800,
-	0x1a04, 0x6518, 0xaaa0, 0xab9c, 0x787c, 0x9306, 0x11a8, 0x7880,
-	0x0096, 0x924e, 0x1128, 0x2208, 0x2310, 0x009e, 0x0804, 0x6518,
-	0x080c, 0xb094, 0x1140, 0x99cc, 0xff00, 0x009e, 0x1128, 0x2208,
-	0x2310, 0x0804, 0x6518, 0x009e, 0x080c, 0x4b54, 0x0904, 0x6522,
-	0x900e, 0x9016, 0x90c6, 0x4000, 0x15e0, 0x0006, 0x080c, 0x6aae,
-	0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0x20a9, 0x0004,
-	0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0xb8c4, 0x20e0,
-	0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fd6, 0x20a9, 0x0004,
-	0xa860, 0x20e8, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c4, 0x20e0,
-	0xb8c8, 0x9080, 0x000a, 0x2098, 0x080c, 0x0fd6, 0xa8c4, 0xabc8,
-	0x9305, 0xabcc, 0x9305, 0xabd0, 0x9305, 0xabd4, 0x9305, 0xabd8,
-	0x9305, 0xabdc, 0x9305, 0xabe0, 0x9305, 0x9005, 0x0510, 0x000e,
-	0x00c8, 0x90c6, 0x4007, 0x1110, 0x2408, 0x00a0, 0x90c6, 0x4008,
-	0x1118, 0x2708, 0x2610, 0x0070, 0x90c6, 0x4009, 0x1108, 0x0050,
-	0x90c6, 0x4006, 0x0138, 0x2001, 0x4005, 0x2009, 0x000a, 0x0010,
-	0x2001, 0x4006, 0xa896, 0xa99a, 0xaa9e, 0x2001, 0x0030, 0x900e,
-	0x0478, 0x000e, 0x080c, 0xb116, 0x1130, 0x2001, 0x4005, 0x2009,
-	0x0003, 0x9016, 0x0c78, 0x2b00, 0x6012, 0x080c, 0xd3b6, 0x2900,
-	0x6016, 0x6023, 0x0001, 0xa868, 0xd88c, 0x0108, 0xc0f5, 0xa86a,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x3315, 0x012e, 0x9006, 0x080c,
-	0x66e6, 0x2001, 0x0002, 0x080c, 0x66fa, 0x2009, 0x0002, 0x080c,
-	0xb20a, 0xa8b0, 0xd094, 0x0118, 0xb8d4, 0xc08d, 0xb8d6, 0x9006,
-	0x9005, 0x012e, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x080c, 0x5854,
-	0x0118, 0x2009, 0x0007, 0x00f8, 0xa998, 0xaeb0, 0x080c, 0x67b4,
-	0x1904, 0x6513, 0x9186, 0x007f, 0x0130, 0x080c, 0x6c11, 0x0118,
-	0x2009, 0x0009, 0x0080, 0x0096, 0x080c, 0x1059, 0x1120, 0x009e,
-	0x2009, 0x0002, 0x0040, 0x2900, 0x009e, 0xa806, 0x080c, 0xd109,
-	0x19b0, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x651a, 0xa998,
-	0xaeb0, 0x080c, 0x67b4, 0x1904, 0x6513, 0x0096, 0x080c, 0x1059,
-	0x1128, 0x009e, 0x2009, 0x0002, 0x0804, 0x65d3, 0x2900, 0x009e,
-	0xa806, 0x0096, 0x2048, 0x20a9, 0x002b, 0xb8c4, 0x20e0, 0xb8c8,
-	0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003,
-	0x20a9, 0x0008, 0x9080, 0x0006, 0x20a0, 0xbbc8, 0x9398, 0x0006,
-	0x2398, 0x080c, 0x0fd6, 0x009e, 0xa87b, 0x0000, 0xa883, 0x0000,
-	0xa897, 0x4000, 0xd684, 0x1168, 0x080c, 0x5840, 0xd0b4, 0x1118,
-	0xa89b, 0x000b, 0x00e0, 0xb800, 0xd08c, 0x0118, 0xa89b, 0x000c,
-	0x00b0, 0x080c, 0x6c11, 0x0118, 0xa89b, 0x0009, 0x0080, 0x080c,
-	0x5854, 0x0118, 0xa89b, 0x0007, 0x0050, 0x080c, 0xd0ec, 0x1904,
-	0x654f, 0x2009, 0x0003, 0x2001, 0x4005, 0x0804, 0x651a, 0xa87b,
-	0x0030, 0xa897, 0x4005, 0xa804, 0x8006, 0x8006, 0x8007, 0x90bc,
-	0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009, 0x002b, 0xaaa0,
-	0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041, 0x12a8, 0x080c,
-	0xb691, 0x1904, 0x654f, 0x2009, 0x0002, 0x08e8, 0x2001, 0x0028,
-	0x900e, 0x0804, 0x6550, 0x2009, 0x180c, 0x210c, 0xd18c, 0x0118,
-	0x2001, 0x0004, 0x0038, 0xd184, 0x0118, 0x2001, 0x0004, 0x0010,
-	0x2001, 0x0029, 0x900e, 0x0804, 0x6550, 0x2001, 0x0029, 0x900e,
-	0x0804, 0x6550, 0x080c, 0x38c0, 0x0804, 0x6551, 0x080c, 0x555d,
-	0x0804, 0x6551, 0x080c, 0x46d5, 0x0804, 0x6551, 0x080c, 0x474e,
-	0x0804, 0x6551, 0x080c, 0x47aa, 0x0804, 0x6551, 0x080c, 0x4c17,
-	0x0804, 0x6551, 0x080c, 0x4edf, 0x0804, 0x6551, 0x080c, 0x51c4,
-	0x0804, 0x6551, 0x080c, 0x53bd, 0x0804, 0x6551, 0x080c, 0x3afe,
-	0x0804, 0x6551, 0x00b6, 0xa974, 0xae78, 0x9684, 0x3fff, 0x9082,
-	0x4000, 0x1608, 0x9182, 0x0800, 0x1258, 0x9188, 0x1000, 0x2104,
-	0x905d, 0x0130, 0x080c, 0x6c11, 0x1138, 0x00d9, 0x9006, 0x00b0,
-	0x2001, 0x0028, 0x900e, 0x0090, 0x9082, 0x0006, 0x1240, 0xb900,
-	0xd1fc, 0x0d98, 0x2001, 0x0029, 0x2009, 0x1000, 0x0038, 0x2001,
-	0x0029, 0x900e, 0x0018, 0x2001, 0x0029, 0x900e, 0x9005, 0x00be,
-	0x0005, 0xa877, 0x0000, 0xb8d0, 0x9005, 0x1904, 0x66da, 0xb888,
-	0x9005, 0x1904, 0x66da, 0xb838, 0xb93c, 0x9102, 0x1a04, 0x66da,
-	0x2b10, 0x080c, 0xb143, 0x0904, 0x66d6, 0x8108, 0xb93e, 0x6212,
-	0x2900, 0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040,
-	0xa878, 0x605e, 0xa880, 0x6066, 0xa883, 0x0000, 0xa87c, 0xd0ac,
-	0x05b8, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1560, 0x2011, 0x180d,
-	0x2214, 0xd28c, 0x190c, 0x6cd6, 0xa816, 0xa864, 0x9094, 0x00f7,
-	0x9296, 0x0011, 0x11f8, 0x9084, 0x00ff, 0xc0bd, 0x601e, 0xa8ac,
-	0xaab0, 0xa836, 0xaa3a, 0x2001, 0x000f, 0x8001, 0x1df0, 0x2001,
-	0x8004, 0x6003, 0x0004, 0x6046, 0x00f6, 0x2079, 0x0380, 0x7818,
-	0xd0bc, 0x1de8, 0x7833, 0x0010, 0x2c00, 0x7836, 0x781b, 0x8080,
-	0x00fe, 0x0005, 0x080c, 0x17ad, 0x601c, 0xc0bd, 0x601e, 0x0c38,
-	0x2009, 0x180d, 0x210c, 0xd18c, 0x190c, 0x6ce0, 0xd0b4, 0x190c,
-	0x1c9c, 0x2001, 0x8004, 0x6003, 0x0002, 0x08e8, 0x81ff, 0x1110,
-	0xb88b, 0x0001, 0x2908, 0xb8cc, 0xb9ce, 0x9005, 0x1110, 0xb9d2,
-	0x0020, 0x0096, 0x2048, 0xa902, 0x009e, 0x0005, 0x00b6, 0x0126,
-	0x00c6, 0x0026, 0x2091, 0x8000, 0x6210, 0x2258, 0xba00, 0x9005,
-	0x0110, 0xc285, 0x0008, 0xc284, 0xba02, 0x002e, 0x00ce, 0x012e,
-	0x00be, 0x0005, 0x00b6, 0x0126, 0x00c6, 0x2091, 0x8000, 0x6210,
-	0x2258, 0xba04, 0x0006, 0x9086, 0x0006, 0x1170, 0xb89c, 0xd0ac,
-	0x0158, 0x080c, 0x6c0d, 0x0140, 0x9284, 0xff00, 0x8007, 0x9086,
-	0x0007, 0x1110, 0x2011, 0x0600, 0x000e, 0x9294, 0xff00, 0x9215,
-	0xba06, 0x0006, 0x9086, 0x0006, 0x1120, 0xba90, 0x82ff, 0x090c,
-	0x0d85, 0x000e, 0x00ce, 0x012e, 0x00be, 0x0005, 0x00b6, 0x0126,
-	0x00c6, 0x2091, 0x8000, 0x6210, 0x2258, 0xba04, 0x0006, 0x9086,
-	0x0006, 0x1168, 0xb89c, 0xd0a4, 0x0150, 0x080c, 0x6c09, 0x1138,
-	0x9284, 0x00ff, 0x9086, 0x0007, 0x1110, 0x2011, 0x0006, 0x000e,
-	0x9294, 0x00ff, 0x8007, 0x9215, 0xba06, 0x00ce, 0x012e, 0x00be,
-	0x0005, 0x9182, 0x0800, 0x0218, 0x9085, 0x0001, 0x0005, 0x00d6,
-	0x0026, 0x9190, 0x1000, 0x2204, 0x905d, 0x1188, 0x0096, 0x080c,
-	0x1059, 0x2958, 0x009e, 0x0168, 0x2b00, 0x2012, 0xb85c, 0xb8ca,
-	0xb860, 0xb8c6, 0x9006, 0xb8a6, 0xb8ae, 0x080c, 0x61b7, 0x9006,
-	0x0010, 0x9085, 0x0001, 0x002e, 0x00de, 0x0005, 0x00b6, 0x0096,
-	0x0126, 0x2091, 0x8000, 0x0026, 0x9182, 0x0800, 0x0218, 0x9085,
-	0x0001, 0x04a8, 0x00d6, 0x9190, 0x1000, 0x2204, 0x905d, 0x0568,
-	0x2013, 0x0000, 0xb8a4, 0x904d, 0x0110, 0x080c, 0x108b, 0x00d6,
-	0x00c6, 0xb8bc, 0x2060, 0x8cff, 0x0168, 0x600c, 0x0006, 0x6014,
-	0x2048, 0x080c, 0xcf1b, 0x0110, 0x080c, 0x100b, 0x080c, 0xb16c,
-	0x00ce, 0x0c88, 0x00ce, 0x00de, 0x00c6, 0xb8ac, 0x9065, 0x0128,
-	0x621c, 0xd2c4, 0x0110, 0x080c, 0x928d, 0x00ce, 0x2b48, 0xb8c8,
-	0xb85e, 0xb8c4, 0xb862, 0x080c, 0x109b, 0x00de, 0x9006, 0x002e,
-	0x012e, 0x009e, 0x00be, 0x0005, 0x0016, 0x9182, 0x0800, 0x0218,
-	0x9085, 0x0001, 0x0030, 0x9188, 0x1000, 0x2104, 0x905d, 0x0dc0,
-	0x9006, 0x001e, 0x0005, 0x00d6, 0x0156, 0x0136, 0x0146, 0x9006,
-	0xb80a, 0xb80e, 0xb800, 0xc08c, 0xb802, 0x080c, 0x779e, 0x1510,
-	0xb8a0, 0x9086, 0x007e, 0x0120, 0x080c, 0xb094, 0x11d8, 0x0078,
-	0x7040, 0xd0e4, 0x01b8, 0x00c6, 0x2061, 0x1982, 0x7048, 0x2062,
-	0x704c, 0x6006, 0x7050, 0x600a, 0x7054, 0x600e, 0x00ce, 0x703c,
-	0x2069, 0x0140, 0x9005, 0x1110, 0x2001, 0x0001, 0x6886, 0x2069,
-	0x1800, 0x68b6, 0x7040, 0xb85e, 0x7048, 0xb862, 0x704c, 0xb866,
-	0x20e1, 0x0000, 0x2099, 0x0276, 0xb8c4, 0x20e8, 0xb8c8, 0x9088,
-	0x000a, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2099, 0x027a, 0x9088,
-	0x0006, 0x21a0, 0x20a9, 0x0004, 0x4003, 0x2069, 0x0200, 0x6817,
-	0x0001, 0x7040, 0xb86a, 0x7144, 0xb96e, 0x7048, 0xb872, 0x7050,
-	0xb876, 0x2069, 0x0200, 0x6817, 0x0000, 0xb8a0, 0x9086, 0x007e,
-	0x1110, 0x7144, 0xb96e, 0x9182, 0x0211, 0x1218, 0x2009, 0x0008,
-	0x0400, 0x9182, 0x0259, 0x1218, 0x2009, 0x0007, 0x00d0, 0x9182,
-	0x02c1, 0x1218, 0x2009, 0x0006, 0x00a0, 0x9182, 0x0349, 0x1218,
-	0x2009, 0x0005, 0x0070, 0x9182, 0x0421, 0x1218, 0x2009, 0x0004,
-	0x0040, 0x9182, 0x0581, 0x1218, 0x2009, 0x0003, 0x0010, 0x2009,
-	0x0002, 0xb992, 0x014e, 0x013e, 0x015e, 0x00de, 0x0005, 0x0016,
-	0x0026, 0x00e6, 0x2071, 0x0260, 0x7034, 0xb896, 0x703c, 0xb89a,
-	0x7054, 0xb89e, 0x0036, 0xbbd4, 0xc384, 0xba00, 0x2009, 0x1867,
-	0x210c, 0xd0bc, 0x0120, 0xd1ec, 0x0110, 0xc2ad, 0x0008, 0xc2ac,
-	0xd0c4, 0x0148, 0xd1e4, 0x0138, 0xc2bd, 0xd0cc, 0x0128, 0xd38c,
-	0x1108, 0xc385, 0x0008, 0xc2bc, 0xba02, 0xbbd6, 0x003e, 0x00ee,
-	0x002e, 0x001e, 0x0005, 0x0096, 0x0126, 0x2091, 0x8000, 0xb8a4,
-	0x904d, 0x0578, 0xa900, 0x81ff, 0x15c0, 0xaa04, 0x9282, 0x0010,
-	0x16c8, 0x0136, 0x0146, 0x01c6, 0x01d6, 0x8906, 0x8006, 0x8007,
-	0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9080, 0x0004, 0x2098,
-	0x2009, 0x0010, 0x20a9, 0x0001, 0x4002, 0x9086, 0xffff, 0x0120,
-	0x8109, 0x1dd0, 0x080c, 0x0d85, 0x3c00, 0x20e8, 0x3300, 0x8001,
-	0x20a0, 0x4604, 0x8210, 0xaa06, 0x01de, 0x01ce, 0x014e, 0x013e,
-	0x0060, 0x080c, 0x1059, 0x0170, 0x2900, 0xb8a6, 0xa803, 0x0000,
-	0x080c, 0x6a4a, 0xa807, 0x0001, 0xae12, 0x9085, 0x0001, 0x012e,
-	0x009e, 0x0005, 0x9006, 0x0cd8, 0x0126, 0x2091, 0x8000, 0x0096,
-	0xb8a4, 0x904d, 0x0188, 0xa800, 0x9005, 0x1150, 0x080c, 0x6a59,
-	0x1158, 0xa804, 0x908a, 0x0002, 0x0218, 0x8001, 0xa806, 0x0020,
-	0x080c, 0x108b, 0xb8a7, 0x0000, 0x009e, 0x012e, 0x0005, 0x0096,
-	0x00c6, 0xb888, 0x9005, 0x1904, 0x693f, 0xb8d0, 0x904d, 0x0904,
-	0x693f, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001,
-	0x1904, 0x693d, 0x080c, 0xb143, 0x0904, 0x693d, 0x8210, 0xba3e,
-	0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x2b00, 0x6012, 0x2900,
-	0x6016, 0x6023, 0x0003, 0x600b, 0xffff, 0x6007, 0x0040, 0xa878,
-	0x605e, 0xa880, 0x9084, 0x00ff, 0x6066, 0xa883, 0x0000, 0xa87c,
-	0xd0ac, 0x01c8, 0xc0dd, 0xa87e, 0xa888, 0x8001, 0x1558, 0xa816,
-	0xa864, 0x9094, 0x00f7, 0x9296, 0x0011, 0x1520, 0x9084, 0x00ff,
-	0xc0bd, 0x601e, 0xa8ac, 0xaab0, 0xa836, 0xaa3a, 0x2001, 0x8004,
-	0x6003, 0x0004, 0x0030, 0x080c, 0x1c9c, 0x2001, 0x8004, 0x6003,
-	0x0002, 0x6046, 0x2001, 0x0010, 0x2c08, 0x080c, 0xaced, 0xb838,
-	0xba3c, 0x9202, 0x0a04, 0x68e5, 0x0010, 0xb88b, 0x0001, 0x00ce,
-	0x009e, 0x0005, 0x080c, 0x17ad, 0x601c, 0xc0bd, 0x601e, 0x08f0,
-	0x00b6, 0x0096, 0x0016, 0x20a9, 0x0800, 0x900e, 0x0016, 0x080c,
-	0x67b4, 0x1158, 0xb8d0, 0x904d, 0x0140, 0x3e00, 0x9086, 0x0002,
-	0x1118, 0xb800, 0xd0bc, 0x1108, 0x0041, 0x001e, 0x8108, 0x1f04,
-	0x694e, 0x001e, 0x00be, 0x009e, 0x0005, 0x0096, 0x0016, 0xb8d0,
-	0x904d, 0x0188, 0xa800, 0xb8d2, 0x9005, 0x1108, 0xb8ce, 0x9006,
-	0xa802, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd220,
-	0x080c, 0x7012, 0x0c60, 0x001e, 0x009e, 0x0005, 0x0086, 0x9046,
-	0xb8d0, 0x904d, 0x01b0, 0xa86c, 0x9406, 0x1118, 0xa870, 0x9506,
-	0x0128, 0x2940, 0xa800, 0x904d, 0x0160, 0x0ca8, 0xa800, 0x88ff,
-	0x1128, 0xb8d2, 0x9005, 0x1118, 0xb8ce, 0x0008, 0xa002, 0xa803,
-	0x0000, 0x008e, 0x0005, 0x901e, 0x0010, 0x2019, 0x0001, 0x0126,
-	0x2091, 0x8000, 0x00e6, 0x0096, 0x00c6, 0x0086, 0x0026, 0x2071,
-	0x19e8, 0x9046, 0x7028, 0x9065, 0x01e8, 0x6014, 0x2068, 0x83ff,
-	0x0120, 0x605c, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118,
-	0xa870, 0x9506, 0x0120, 0x2c40, 0x600c, 0x2060, 0x0c60, 0x600c,
-	0x0006, 0x0066, 0x2830, 0x080c, 0xa420, 0x006e, 0x000e, 0x83ff,
-	0x0508, 0x0c08, 0x9046, 0xb8d0, 0x904d, 0x01e0, 0x83ff, 0x0120,
-	0xa878, 0x9606, 0x0158, 0x0030, 0xa86c, 0x9406, 0x1118, 0xa870,
-	0x9506, 0x0120, 0x2940, 0xa800, 0x2048, 0x0c70, 0xb8d0, 0xaa00,
-	0x0026, 0x9906, 0x1110, 0xbad2, 0x0008, 0xa202, 0x000e, 0x83ff,
-	0x0108, 0x0c10, 0x002e, 0x008e, 0x00ce, 0x009e, 0x00ee, 0x012e,
-	0x0005, 0x9016, 0x0489, 0x1110, 0x2011, 0x0001, 0x0005, 0x080c,
-	0x6aae, 0x0128, 0x080c, 0xcfdc, 0x0010, 0x9085, 0x0001, 0x0005,
-	0x080c, 0x6aae, 0x0128, 0x080c, 0xcf7d, 0x0010, 0x9085, 0x0001,
-	0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xcfd9, 0x0010, 0x9085,
-	0x0001, 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xcf9c, 0x0010,
-	0x9085, 0x0001, 0x0005, 0x080c, 0x6aae, 0x0128, 0x080c, 0xd01f,
-	0x0010, 0x9085, 0x0001, 0x0005, 0xb8a4, 0x900d, 0x1118, 0x9085,
-	0x0001, 0x0005, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e,
-	0x810e, 0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080,
-	0x0004, 0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606,
-	0x0128, 0x8109, 0x1dd8, 0x9085, 0x0001, 0x0008, 0x9006, 0x01ce,
-	0x013e, 0x0005, 0x0146, 0x01d6, 0xa860, 0x20e8, 0xa85c, 0x9080,
-	0x0004, 0x20a0, 0x20a9, 0x0010, 0x2009, 0xffff, 0x4104, 0x01de,
-	0x014e, 0x0136, 0x01c6, 0xa800, 0x9005, 0x11b8, 0x890e, 0x810e,
-	0x810f, 0x9184, 0x003f, 0x20e0, 0x9184, 0xffc0, 0x9080, 0x0004,
-	0x2098, 0x20a9, 0x0001, 0x2009, 0x0010, 0x4002, 0x9606, 0x0128,
-	0x8109, 0x1dd8, 0x9085, 0x0001, 0x0068, 0x0146, 0x01d6, 0x3300,
-	0x8001, 0x20a0, 0x3c00, 0x20e8, 0x2001, 0xffff, 0x4004, 0x01de,
-	0x014e, 0x9006, 0x01ce, 0x013e, 0x0005, 0x0096, 0x0126, 0x2091,
-	0x8000, 0xb8a4, 0x904d, 0x1128, 0x080c, 0x1059, 0x0168, 0x2900,
-	0xb8a6, 0x080c, 0x6a4a, 0xa803, 0x0001, 0xa807, 0x0000, 0x9085,
-	0x0001, 0x012e, 0x009e, 0x0005, 0x9006, 0x0cd8, 0x0096, 0x0126,
-	0x2091, 0x8000, 0xb8a4, 0x904d, 0x0130, 0xb8a7, 0x0000, 0x080c,
-	0x108b, 0x9085, 0x0001, 0x012e, 0x009e, 0x0005, 0xb89c, 0xd0a4,
-	0x0005, 0x00b6, 0x00f6, 0x080c, 0x779e, 0x01b0, 0x71c4, 0x81ff,
-	0x1198, 0x71dc, 0xd19c, 0x0180, 0x2001, 0x007e, 0x9080, 0x1000,
-	0x2004, 0x905d, 0x0148, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006,
-	0x1118, 0xb800, 0xc0ed, 0xb802, 0x2079, 0x1847, 0x7804, 0xd0a4,
-	0x01d0, 0x0156, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4,
-	0x1168, 0xb804, 0x9084, 0xff00, 0x8007, 0x9096, 0x0004, 0x0118,
-	0x9086, 0x0006, 0x1118, 0xb800, 0xc0ed, 0xb802, 0x001e, 0x8108,
-	0x1f04, 0x6ad5, 0x015e, 0x080c, 0x6bcf, 0x0120, 0x2001, 0x1985,
-	0x200c, 0x0098, 0x2079, 0x1847, 0x7804, 0xd0a4, 0x0190, 0x2009,
-	0x07d0, 0x2001, 0x182c, 0x2004, 0x9005, 0x0138, 0x2001, 0x1867,
-	0x2004, 0xd0e4, 0x0110, 0x2009, 0x5dc0, 0x2011, 0x6b0c, 0x080c,
-	0x8a5d, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x2011, 0x6b0c, 0x080c,
-	0x8993, 0x080c, 0x6bcf, 0x01d8, 0x2001, 0x107e, 0x2004, 0x2058,
-	0xb900, 0xc1ec, 0xb902, 0x080c, 0x6c0d, 0x0130, 0x2009, 0x07d0,
-	0x2011, 0x6b0c, 0x080c, 0x8a5d, 0x00e6, 0x2071, 0x1800, 0x9006,
-	0x707e, 0x7060, 0x7082, 0x080c, 0x30bf, 0x00ee, 0x04d0, 0x0156,
-	0x00c6, 0x20a9, 0x007f, 0x900e, 0x0016, 0x080c, 0x67b4, 0x1558,
-	0xb800, 0xd0ec, 0x0540, 0x0046, 0xbaa0, 0x2220, 0x9006, 0x2009,
-	0x0029, 0x080c, 0xea8d, 0xb800, 0xc0e5, 0xc0ec, 0xb802, 0x080c,
-	0x6c09, 0x2001, 0x0707, 0x1128, 0xb804, 0x9084, 0x00ff, 0x9085,
-	0x0700, 0xb806, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0x97b0,
-	0x0076, 0x903e, 0x080c, 0x966d, 0x900e, 0x080c, 0xe75d, 0x007e,
-	0x004e, 0x080c, 0xad18, 0x001e, 0x8108, 0x1f04, 0x6b34, 0x00ce,
-	0x015e, 0x00be, 0x0005, 0x00b6, 0x6010, 0x2058, 0xb800, 0xc0ec,
-	0xb802, 0x00be, 0x0005, 0x00b6, 0x00c6, 0x0096, 0x080c, 0x1072,
-	0x090c, 0x0d85, 0x2958, 0x009e, 0x2001, 0x196b, 0x2b02, 0x8b07,
-	0x8006, 0x8006, 0x908c, 0x003f, 0xb9c6, 0x908c, 0xffc0, 0xb9ca,
-	0xb8af, 0x0000, 0x2009, 0x00ff, 0x080c, 0x61b7, 0xb807, 0x0006,
-	0xb813, 0x00ff, 0xb817, 0xffff, 0xb86f, 0x0200, 0xb86c, 0xb893,
-	0x0002, 0xb8bb, 0x0520, 0xb8a3, 0x00ff, 0xb8af, 0x0000, 0x00ce,
-	0x00be, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ac,
-	0x0005, 0x6010, 0x00b6, 0x905d, 0x0108, 0xb800, 0x00be, 0xd0bc,
-	0x0005, 0x0006, 0x0016, 0x0026, 0xb804, 0x908c, 0x00ff, 0x9196,
-	0x0006, 0x0188, 0x9196, 0x0004, 0x0170, 0x9196, 0x0005, 0x0158,
-	0x908c, 0xff00, 0x810f, 0x9196, 0x0006, 0x0128, 0x9196, 0x0004,
-	0x0110, 0x9196, 0x0005, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6,
-	0x00f6, 0x2001, 0x107e, 0x2004, 0x905d, 0x0110, 0xb800, 0xd0ec,
-	0x00fe, 0x00be, 0x0005, 0x0126, 0x0026, 0x2091, 0x8000, 0x0006,
-	0xbaa0, 0x9290, 0x1000, 0x2204, 0x9b06, 0x190c, 0x0d85, 0x000e,
-	0xba00, 0x9005, 0x0110, 0xc2fd, 0x0008, 0xc2fc, 0xba02, 0x002e,
-	0x012e, 0x0005, 0x2011, 0x1837, 0x2204, 0xd0cc, 0x0138, 0x2001,
-	0x1983, 0x200c, 0x2011, 0x6bff, 0x080c, 0x8a5d, 0x0005, 0x2011,
-	0x6bff, 0x080c, 0x8993, 0x2011, 0x1837, 0x2204, 0xc0cc, 0x2012,
-	0x0005, 0x080c, 0x5840, 0xd0ac, 0x0005, 0x080c, 0x5840, 0xd0a4,
-	0x0005, 0x0016, 0xb904, 0x9184, 0x00ff, 0x908e, 0x0006, 0x001e,
-	0x0005, 0x0016, 0xb904, 0x9184, 0xff00, 0x8007, 0x908e, 0x0006,
-	0x001e, 0x0005, 0x00b6, 0x00f6, 0x080c, 0xd645, 0x0158, 0x70dc,
-	0x9084, 0x0028, 0x0138, 0x2001, 0x107f, 0x2004, 0x905d, 0x0110,
-	0xb8d4, 0xd094, 0x00fe, 0x00be, 0x0005, 0x0006, 0x0016, 0x0036,
-	0x0046, 0x0076, 0x00b6, 0x2001, 0x1818, 0x203c, 0x9780, 0x348e,
-	0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2018, 0x2008, 0x9284,
-	0x8000, 0x0110, 0x2019, 0x0001, 0x9294, 0x7fff, 0x2100, 0x9706,
-	0x0190, 0x91a0, 0x1000, 0x2404, 0x905d, 0x0168, 0xb804, 0x9084,
-	0x00ff, 0x9086, 0x0006, 0x1138, 0x83ff, 0x0118, 0xb89c, 0xd0a4,
-	0x0110, 0x8211, 0x0158, 0x8108, 0x83ff, 0x0120, 0x9182, 0x0800,
-	0x0e28, 0x0068, 0x9182, 0x007e, 0x0e08, 0x0048, 0x00be, 0x007e,
-	0x004e, 0x003e, 0x001e, 0x9085, 0x0001, 0x000e, 0x0005, 0x00be,
-	0x007e, 0x004e, 0x003e, 0x001e, 0x9006, 0x000e, 0x0005, 0x0046,
-	0x0056, 0x0076, 0x00b6, 0x2100, 0x9084, 0x7fff, 0x9080, 0x1000,
-	0x2004, 0x905d, 0x0130, 0xb804, 0x9084, 0x00ff, 0x9086, 0x0006,
-	0x0550, 0x9184, 0x8000, 0x0580, 0x2001, 0x1818, 0x203c, 0x9780,
-	0x348e, 0x203d, 0x97bc, 0xff00, 0x873f, 0x9006, 0x2020, 0x2400,
-	0x9706, 0x01a0, 0x94a8, 0x1000, 0x2504, 0x905d, 0x0178, 0xb804,
-	0x9084, 0x00ff, 0x9086, 0x0006, 0x1148, 0xb89c, 0xd0a4, 0x0130,
-	0xb814, 0x9206, 0x1118, 0xb810, 0x9306, 0x0128, 0x8420, 0x9482,
-	0x0800, 0x0e28, 0x0048, 0x918c, 0x7fff, 0x00be, 0x007e, 0x005e,
-	0x004e, 0x9085, 0x0001, 0x0005, 0x918c, 0x7fff, 0x00be, 0x007e,
-	0x005e, 0x004e, 0x9006, 0x0005, 0x0006, 0x2001, 0x00a0, 0x8001,
-	0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005, 0x0006, 0x2001,
-	0x00f8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8, 0x000e, 0x0005,
-	0x0006, 0x2001, 0x00e8, 0x8001, 0xa001, 0xa001, 0xa001, 0x1dd8,
-	0x000e, 0x0005, 0x2071, 0x1910, 0x7003, 0x0001, 0x7007, 0x0000,
-	0x9006, 0x7012, 0x7016, 0x701a, 0x701e, 0x700a, 0x7046, 0x2001,
-	0x1922, 0x2003, 0x0000, 0x0005, 0x0016, 0x00e6, 0x2071, 0x1948,
-	0x900e, 0x710a, 0x080c, 0x5840, 0xd0fc, 0x1140, 0x080c, 0x5840,
-	0x900e, 0xd09c, 0x0108, 0x8108, 0x7102, 0x0470, 0x2001, 0x1867,
-	0x200c, 0x9184, 0x0007, 0x0006, 0x2001, 0x180d, 0x2004, 0xd08c,
-	0x000e, 0x0108, 0x9006, 0x0002, 0x6d06, 0x6d06, 0x6d06, 0x6d06,
-	0x6d06, 0x6d24, 0x6d39, 0x6d47, 0x7003, 0x0003, 0x2009, 0x1868,
-	0x210c, 0x9184, 0xff00, 0x908e, 0xff00, 0x0140, 0x8007, 0x9005,
-	0x1110, 0x2001, 0x0002, 0x8003, 0x7006, 0x0030, 0x7007, 0x0001,
-	0x0018, 0x7003, 0x0005, 0x0c50, 0x2071, 0x1910, 0x704f, 0x0000,
-	0x2071, 0x1800, 0x70f7, 0x0001, 0x00ee, 0x001e, 0x0005, 0x7003,
-	0x0000, 0x2071, 0x1910, 0x2009, 0x1868, 0x210c, 0x9184, 0x7f00,
-	0x8007, 0x908c, 0x000f, 0x0160, 0x714e, 0x8004, 0x8004, 0x8004,
-	0x8004, 0x2071, 0x1800, 0x908c, 0x0007, 0x0128, 0x70f6, 0x0c20,
-	0x704f, 0x000f, 0x0c90, 0x70f7, 0x0005, 0x08f0, 0x00e6, 0x2071,
-	0x0050, 0x684c, 0x9005, 0x1150, 0x00e6, 0x2071, 0x1910, 0x7028,
-	0xc085, 0x702a, 0x00ee, 0x9085, 0x0001, 0x0488, 0x6844, 0x9005,
-	0x0158, 0x080c, 0x7b28, 0x6a60, 0x9200, 0x7002, 0x6864, 0x9101,
-	0x7006, 0x9006, 0x7012, 0x7016, 0x6860, 0x7002, 0x6864, 0x7006,
-	0x6868, 0x700a, 0x686c, 0x700e, 0x6844, 0x9005, 0x1110, 0x7012,
-	0x7016, 0x684c, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e, 0x7037,
-	0x0019, 0x702b, 0x0001, 0x00e6, 0x2071, 0x1910, 0x7028, 0xc084,
-	0x702a, 0x7007, 0x0001, 0x700b, 0x0000, 0x00ee, 0x9006, 0x00ee,
-	0x0005, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, 0x9015, 0x0904,
-	0x7017, 0x9286, 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904,
-	0x6eac, 0x2071, 0x1877, 0xa87c, 0x9005, 0x0904, 0x6e07, 0x7140,
-	0xa868, 0x9102, 0x0a04, 0x7017, 0xa878, 0xd084, 0x15d8, 0xa853,
-	0x0019, 0x2001, 0x8023, 0xa84e, 0x2071, 0x1910, 0x701c, 0x9005,
-	0x1904, 0x71c6, 0x0e04, 0x7234, 0x2071, 0x0000, 0xa850, 0x7032,
-	0xa84c, 0x7082, 0xa870, 0x7086, 0xa86c, 0x708a, 0xa880, 0x708e,
-	0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000,
-	0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080,
-	0x0021, 0x2098, 0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e,
-	0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200,
-	0x0804, 0x6e8f, 0xa853, 0x001b, 0x2001, 0x8027, 0x0820, 0x7004,
-	0xd08c, 0x1904, 0x7017, 0xa853, 0x001a, 0x2001, 0x8024, 0x0804,
-	0x6dcb, 0x00e6, 0x0026, 0x2071, 0x1948, 0x7000, 0x9015, 0x0904,
-	0x7017, 0x9286, 0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904,
-	0x6eac, 0xa84f, 0x8022, 0xa853, 0x0018, 0x0804, 0x6e74, 0xa868,
-	0xd0fc, 0x1508, 0x00e6, 0x0026, 0x2001, 0x1948, 0x2004, 0x9015,
-	0x0904, 0x7017, 0xa978, 0xa874, 0x9105, 0x1904, 0x7017, 0x9286,
-	0x0003, 0x0904, 0x6eac, 0x9286, 0x0005, 0x0904, 0x6eac, 0xa87c,
-	0xd0bc, 0x1904, 0x7017, 0x2200, 0x0002, 0x7017, 0x6e70, 0x6eac,
-	0x6eac, 0x7017, 0x6eac, 0x0005, 0xa868, 0xd0fc, 0x1500, 0x00e6,
-	0x0026, 0x2009, 0x1948, 0x210c, 0x81ff, 0x0904, 0x7017, 0xa880,
-	0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7017, 0x9186, 0x0003,
-	0x0904, 0x6eac, 0x9186, 0x0005, 0x0904, 0x6eac, 0xa87c, 0xd0cc,
-	0x0904, 0x7017, 0xa84f, 0x8021, 0xa853, 0x0017, 0x0028, 0x0005,
-	0xa84f, 0x8020, 0xa853, 0x0016, 0x2071, 0x1910, 0x701c, 0x9005,
-	0x1904, 0x71c6, 0x0e04, 0x7234, 0x2071, 0x0000, 0xa84c, 0x7082,
-	0xa850, 0x7032, 0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0x2091,
-	0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2071,
-	0x1800, 0x2011, 0x0001, 0xa804, 0x900d, 0x702c, 0x1158, 0xa802,
-	0x2900, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x002e,
-	0x00ee, 0x0005, 0x0096, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900,
-	0x81ff, 0x1dc8, 0x009e, 0x0c58, 0xa84f, 0x0000, 0x00f6, 0x2079,
-	0x0050, 0x2071, 0x1910, 0xa803, 0x0000, 0x7010, 0x9005, 0x1904,
-	0x6f9d, 0x782c, 0x908c, 0x0780, 0x190c, 0x7382, 0x8004, 0x8004,
-	0x8004, 0x9084, 0x0003, 0x0002, 0x6eca, 0x6f9d, 0x6eee, 0x6f3a,
-	0x080c, 0x0d85, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d,
-	0x1168, 0x2071, 0x1a04, 0x7044, 0x9005, 0x1320, 0x2001, 0x1949,
-	0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x9016, 0x702c,
-	0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e,
-	0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x0c18, 0x2071, 0x1800,
-	0x2900, 0x7822, 0xa804, 0x900d, 0x15a0, 0x7824, 0x00e6, 0x2071,
-	0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a,
-	0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102,
-	0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e,
-	0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x7382, 0xd0a4, 0x19c8, 0x2071, 0x1a04, 0x7044, 0x9005,
-	0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee,
-	0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900,
-	0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899,
-	0x0804, 0x6ef5, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071, 0x1800,
-	0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c,
-	0x8899, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x1d60,
-	0x00ee, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x1198,
-	0x009e, 0x2900, 0x7822, 0xa804, 0x900d, 0x1550, 0x2071, 0x1a04,
-	0x7044, 0x9005, 0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe,
-	0x002e, 0x00ee, 0x0005, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012,
-	0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148,
-	0xa804, 0x900d, 0x1168, 0x2071, 0x1a04, 0x7044, 0x9005, 0x1320,
-	0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee, 0x0005,
-	0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210,
-	0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c,
-	0x8899, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2908, 0x7010, 0x8000,
-	0x7012, 0x7018, 0x904d, 0x711a, 0x0110, 0xa902, 0x0008, 0x711e,
-	0x2148, 0xa804, 0x900d, 0x1904, 0x6ff1, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x7382, 0xd09c, 0x1198, 0x701c, 0x904d, 0x0180, 0x7010,
-	0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822,
-	0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x0d68, 0x782c,
-	0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x01b0, 0x00e6, 0x7824,
-	0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0,
-	0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c,
-	0x7382, 0xd0a4, 0x1d60, 0x00ee, 0x2071, 0x1a04, 0x7044, 0x9005,
-	0x1320, 0x2001, 0x1949, 0x2004, 0x7046, 0x00fe, 0x002e, 0x00ee,
-	0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904,
-	0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200,
-	0x70c2, 0x080c, 0x8899, 0x00ee, 0x0804, 0x6fad, 0xa868, 0xd0fc,
-	0x15e0, 0x0096, 0xa804, 0xa807, 0x0000, 0x904d, 0x190c, 0x100b,
-	0x009e, 0x0018, 0xa868, 0xd0fc, 0x1580, 0x00e6, 0x0026, 0xa84f,
-	0x0000, 0x00f6, 0x2079, 0x0050, 0x2071, 0x1910, 0xa803, 0x0000,
-	0xa864, 0x9084, 0x00ff, 0x908e, 0x0016, 0x01a8, 0x7010, 0x9005,
-	0x1904, 0x7142, 0x782c, 0x908c, 0x0780, 0x190c, 0x7382, 0x8004,
-	0x8004, 0x8004, 0x9084, 0x0003, 0x0002, 0x7046, 0x7142, 0x7061,
-	0x70d3, 0x080c, 0x0d85, 0x2009, 0x1948, 0x2104, 0x0002, 0x7026,
-	0x7026, 0x7026, 0x6eb5, 0x7026, 0x6eb5, 0x0005, 0x2071, 0x1800,
-	0x2900, 0x7822, 0xa804, 0x900d, 0x1120, 0x00fe, 0x002e, 0x00ee,
-	0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900,
-	0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899,
-	0x0c60, 0x2071, 0x1800, 0x2900, 0x7822, 0xa804, 0x900d, 0x1904,
-	0x70c2, 0x7830, 0xd0dc, 0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005,
-	0x7824, 0x00e6, 0x2071, 0x0040, 0x712c, 0xd19c, 0x1170, 0x2009,
-	0x1830, 0x210c, 0x918a, 0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0,
-	0x200c, 0x8108, 0x2102, 0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c,
-	0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899,
-	0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x19c8, 0x0e04,
-	0x70b9, 0x7838, 0x7938, 0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000,
-	0x6836, 0x6833, 0x0013, 0x00de, 0x2001, 0x1921, 0x200c, 0xc184,
-	0x2102, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c,
-	0x1200, 0x2001, 0x1922, 0x2003, 0x0000, 0x00fe, 0x002e, 0x00ee,
-	0x0005, 0x2001, 0x1921, 0x200c, 0xc185, 0x2102, 0x00fe, 0x002e,
-	0x00ee, 0x0005, 0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210,
-	0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c,
-	0x8899, 0x0804, 0x7070, 0x0096, 0x00e6, 0x7824, 0x2048, 0x2071,
-	0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2,
-	0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4,
-	0x1d60, 0x00ee, 0x0e04, 0x7115, 0x7838, 0x7938, 0x910e, 0x1de0,
-	0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x7044,
-	0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084,
-	0x190c, 0x1200, 0x704b, 0x0000, 0x782c, 0x9094, 0x0780, 0x190c,
-	0x7382, 0xd09c, 0x1170, 0x009e, 0x2900, 0x7822, 0xa804, 0x900d,
-	0x11e0, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x7044, 0xc085, 0x7046,
-	0x0c58, 0x009e, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d,
-	0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d,
-	0x1120, 0x00fe, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800, 0x9016,
-	0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8,
-	0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x00fe, 0x002e,
-	0x00ee, 0x0005, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d,
-	0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d,
-	0x1904, 0x71b1, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c,
-	0x11b0, 0x701c, 0x904d, 0x0198, 0xa84c, 0x9005, 0x1180, 0x7010,
-	0x8001, 0x7012, 0x1108, 0x701a, 0xa800, 0x701e, 0x2900, 0x7822,
-	0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x0d50, 0x782c,
-	0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x05b8, 0x00e6, 0x7824,
-	0x2048, 0x2071, 0x1800, 0x702c, 0xa802, 0x2900, 0x702e, 0x70c0,
-	0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780, 0x190c,
-	0x7382, 0xd0a4, 0x1d60, 0x00ee, 0x0e04, 0x71aa, 0x7838, 0x7938,
-	0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013,
-	0x00de, 0x7044, 0xc084, 0x7046, 0x2091, 0x4080, 0x2001, 0x0089,
-	0x2004, 0xd084, 0x190c, 0x1200, 0x704b, 0x0000, 0x00fe, 0x002e,
-	0x00ee, 0x0005, 0x7044, 0xc085, 0x7046, 0x00fe, 0x002e, 0x00ee,
-	0x0005, 0x00e6, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904,
-	0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200,
-	0x70c2, 0x080c, 0x8899, 0x00ee, 0x0804, 0x7152, 0x2071, 0x1910,
-	0xa803, 0x0000, 0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d,
-	0x711a, 0x0110, 0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d,
-	0x1128, 0x1e04, 0x71f1, 0x002e, 0x00ee, 0x0005, 0x2071, 0x1800,
-	0x9016, 0x702c, 0x2148, 0xa904, 0xa802, 0x8210, 0x2900, 0x81ff,
-	0x1dc8, 0x702e, 0x70c0, 0x9200, 0x70c2, 0x080c, 0x8899, 0x0e04,
-	0x71db, 0x2071, 0x1910, 0x701c, 0x2048, 0xa84c, 0x900d, 0x0d18,
-	0x2071, 0x0000, 0x7182, 0xa850, 0x7032, 0xa86c, 0x7086, 0x7036,
-	0xa870, 0x708a, 0xa850, 0x9082, 0x0019, 0x1278, 0x2091, 0x4080,
-	0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2071, 0x1910,
-	0x080c, 0x736e, 0x002e, 0x00ee, 0x0005, 0xa850, 0x9082, 0x001c,
-	0x1e68, 0xa880, 0x708e, 0x7036, 0x0146, 0x01d6, 0x0136, 0x01c6,
-	0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a, 0xa868, 0x20a8, 0xa860,
-	0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098, 0x4003, 0x015e, 0x01ce,
-	0x013e, 0x01de, 0x014e, 0x0890, 0x2071, 0x1910, 0xa803, 0x0000,
-	0x2908, 0x7010, 0x8000, 0x7012, 0x7018, 0x904d, 0x711a, 0x0110,
-	0xa902, 0x0008, 0x711e, 0x2148, 0xa804, 0x900d, 0x1118, 0x002e,
-	0x00ee, 0x0005, 0x2071, 0x1800, 0x9016, 0x702c, 0x2148, 0xa904,
-	0xa802, 0x8210, 0x2900, 0x81ff, 0x1dc8, 0x702e, 0x70c0, 0x9200,
-	0x70c2, 0x080c, 0x8899, 0x002e, 0x00ee, 0x0005, 0x0006, 0xa87c,
-	0x0006, 0xa867, 0x0103, 0x20a9, 0x001c, 0xa860, 0x20e8, 0xa85c,
-	0x9080, 0x001d, 0x20a0, 0x9006, 0x4004, 0x000e, 0x9084, 0x00ff,
-	0xa87e, 0x000e, 0xa87a, 0xa982, 0x0005, 0x2071, 0x1910, 0x7004,
-	0x0002, 0x7281, 0x7282, 0x736d, 0x7282, 0x727f, 0x736d, 0x080c,
-	0x0d85, 0x0005, 0x2001, 0x1948, 0x2004, 0x0002, 0x728c, 0x728c,
-	0x7306, 0x7307, 0x728c, 0x7307, 0x0126, 0x2091, 0x8000, 0x1e0c,
-	0x738d, 0x701c, 0x904d, 0x0508, 0xa84c, 0x9005, 0x0904, 0x72d7,
-	0x0e04, 0x72b5, 0xa94c, 0x2071, 0x0000, 0x7182, 0xa850, 0x7032,
-	0xa86c, 0x7086, 0x7036, 0xa870, 0x708a, 0xa850, 0x9082, 0x0019,
-	0x1278, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c,
-	0x1200, 0x2071, 0x1910, 0x080c, 0x736e, 0x012e, 0x0804, 0x7305,
-	0xa850, 0x9082, 0x001c, 0x1e68, 0xa880, 0x708e, 0x7036, 0x0146,
-	0x01d6, 0x0136, 0x01c6, 0x0156, 0x20e9, 0x0000, 0x20a1, 0x002a,
-	0xa868, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0021, 0x2098,
-	0x4003, 0x015e, 0x01ce, 0x013e, 0x01de, 0x014e, 0x0890, 0x2001,
-	0x005b, 0x2004, 0x9094, 0x0780, 0x190c, 0x7382, 0xd09c, 0x2071,
-	0x1910, 0x1510, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964, 0x9184,
-	0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff, 0x8101,
-	0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822, 0x00de,
-	0x2071, 0x1910, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800,
-	0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x00d6,
-	0x2008, 0x2069, 0x1a04, 0x6844, 0x9005, 0x0760, 0x0158, 0x9186,
-	0x0003, 0x0540, 0x2001, 0x1815, 0x2004, 0x2009, 0x1b73, 0x210c,
-	0x9102, 0x1500, 0x0126, 0x2091, 0x8000, 0x2069, 0x0050, 0x693c,
-	0x6838, 0x9106, 0x0190, 0x0e04, 0x7339, 0x2069, 0x0000, 0x6837,
-	0x8040, 0x6833, 0x0012, 0x6883, 0x8040, 0x2091, 0x4080, 0x2001,
-	0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x2069, 0x1a04, 0x6847,
-	0xffff, 0x012e, 0x00de, 0x0126, 0x2091, 0x8000, 0x1e0c, 0x73fd,
-	0x701c, 0x904d, 0x0540, 0x2001, 0x005b, 0x2004, 0x9094, 0x0780,
-	0x15c9, 0xd09c, 0x1500, 0x2071, 0x1910, 0x700f, 0x0001, 0xa964,
-	0x9184, 0x00ff, 0x9086, 0x0003, 0x1130, 0x810f, 0x918c, 0x00ff,
-	0x8101, 0x0108, 0x710e, 0x2900, 0x00d6, 0x2069, 0x0050, 0x6822,
-	0x00de, 0x701c, 0x2048, 0x7010, 0x8001, 0x7012, 0xa800, 0x701e,
-	0x9005, 0x1108, 0x701a, 0x012e, 0x0005, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x701c, 0x904d, 0x0160, 0x7010, 0x8001, 0x7012, 0xa800,
-	0x701e, 0x9005, 0x1108, 0x701a, 0x012e, 0x080c, 0x108b, 0x0005,
-	0x012e, 0x0005, 0x2091, 0x8000, 0x0e04, 0x7384, 0x0006, 0x0016,
-	0x2001, 0x8004, 0x0006, 0x0804, 0x0d8e, 0x0096, 0x00f6, 0x2079,
-	0x0050, 0x7044, 0xd084, 0x01d0, 0xc084, 0x7046, 0x7838, 0x7938,
-	0x910e, 0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013,
-	0x00de, 0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c,
-	0x1200, 0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x782c, 0x9094,
-	0x0780, 0x1981, 0xd0a4, 0x0db8, 0x7148, 0x704c, 0x8108, 0x714a,
-	0x9102, 0x0e88, 0x00e6, 0x2071, 0x1800, 0x7824, 0x00e6, 0x2071,
-	0x0040, 0x712c, 0xd19c, 0x1170, 0x2009, 0x1830, 0x210c, 0x918a,
-	0x0020, 0x0240, 0x7022, 0x2001, 0x1dc0, 0x200c, 0x8108, 0x2102,
-	0x00ee, 0x0058, 0x00ee, 0x2048, 0x702c, 0xa802, 0x2900, 0x702e,
-	0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c, 0x9094, 0x0780,
-	0x190c, 0x7382, 0xd0a4, 0x19c8, 0x7838, 0x7938, 0x910e, 0x1de0,
-	0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de, 0x2091,
-	0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200, 0x00ee,
-	0x704b, 0x0000, 0x00fe, 0x009e, 0x0005, 0x00f6, 0x2079, 0x0050,
-	0x7044, 0xd084, 0x01b8, 0xc084, 0x7046, 0x7838, 0x7938, 0x910e,
-	0x1de0, 0x00d6, 0x2069, 0x0000, 0x6836, 0x6833, 0x0013, 0x00de,
-	0x2091, 0x4080, 0x2001, 0x0089, 0x2004, 0xd084, 0x190c, 0x1200,
-	0x00fe, 0x0005, 0x782c, 0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4,
-	0x0db8, 0x00e6, 0x2071, 0x1800, 0x7824, 0x2048, 0x702c, 0xa802,
-	0x2900, 0x702e, 0x70c0, 0x8000, 0x70c2, 0x080c, 0x8899, 0x782c,
-	0x9094, 0x0780, 0x190c, 0x7382, 0xd0a4, 0x1d70, 0x00d6, 0x2069,
-	0x0050, 0x693c, 0x2069, 0x1948, 0x6808, 0x690a, 0x2069, 0x1a04,
-	0x9102, 0x1118, 0x6844, 0x9005, 0x1320, 0x2001, 0x1949, 0x200c,
-	0x6946, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x7098, 0x908a, 0x002a,
-	0x1a0c, 0x0d85, 0x9082, 0x001d, 0x003b, 0x0026, 0x2011, 0x1e00,
-	0x080c, 0x2ad3, 0x002e, 0x0005, 0x7542, 0x74af, 0x74cb, 0x74f5,
-	0x7531, 0x7571, 0x7583, 0x74cb, 0x7559, 0x746a, 0x7498, 0x751b,
-	0x7469, 0x0005, 0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1180,
-	0x6808, 0x9005, 0x1518, 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04,
-	0x7002, 0x080c, 0x78e4, 0x6028, 0x9085, 0x0600, 0x602a, 0x00b0,
-	0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x6028, 0x9085,
-	0x0600, 0x602a, 0x00e6, 0x0036, 0x0046, 0x0056, 0x2071, 0x1a6e,
-	0x080c, 0x1b1e, 0x005e, 0x004e, 0x003e, 0x00ee, 0x00de, 0x0005,
-	0x00d6, 0x2069, 0x0200, 0x6804, 0x9005, 0x1178, 0x6808, 0x9005,
-	0x1160, 0x709b, 0x0029, 0x2069, 0x198f, 0x2d04, 0x7002, 0x080c,
-	0x7990, 0x6028, 0x9085, 0x0600, 0x602a, 0x00de, 0x0005, 0x0006,
-	0x2001, 0x0090, 0x080c, 0x2a99, 0x000e, 0x6124, 0xd1e4, 0x1190,
-	0x080c, 0x75f4, 0xd1d4, 0x1160, 0xd1dc, 0x1138, 0xd1cc, 0x0150,
-	0x709b, 0x0020, 0x080c, 0x75f4, 0x0028, 0x709b, 0x001d, 0x0010,
-	0x709b, 0x001f, 0x0005, 0x2001, 0x0088, 0x080c, 0x2a99, 0x6124,
-	0xd1cc, 0x11e8, 0xd1dc, 0x11c0, 0xd1e4, 0x1198, 0x9184, 0x1e00,
-	0x11d8, 0x080c, 0x1b4b, 0x60e3, 0x0001, 0x600c, 0xc0b4, 0x600e,
-	0x080c, 0x77ca, 0x2001, 0x0080, 0x080c, 0x2a99, 0x709b, 0x0029,
-	0x0058, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028, 0x709b,
-	0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x080c, 0x1b4b, 0x60e3,
-	0x0001, 0x600c, 0xc0b4, 0x600e, 0x080c, 0x77ca, 0x2001, 0x0080,
-	0x080c, 0x2a99, 0x6124, 0xd1d4, 0x1198, 0xd1dc, 0x1170, 0xd1e4,
-	0x1148, 0x9184, 0x1e00, 0x1118, 0x709b, 0x0029, 0x0058, 0x709b,
-	0x0028, 0x0040, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010,
-	0x709b, 0x001f, 0x0005, 0x6124, 0xd1d4, 0x1180, 0xd1dc, 0x1158,
-	0xd1e4, 0x1130, 0x9184, 0x1e00, 0x1158, 0x709b, 0x0029, 0x0040,
-	0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x001f,
-	0x0005, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x6124, 0xd1dc, 0x1138,
-	0xd1e4, 0x0138, 0x080c, 0x1b4b, 0x709b, 0x001e, 0x0010, 0x709b,
-	0x001d, 0x0005, 0x080c, 0x767d, 0x6124, 0xd1dc, 0x1188, 0x080c,
-	0x75f4, 0x0016, 0x080c, 0x1b4b, 0x001e, 0xd1d4, 0x1128, 0xd1e4,
-	0x0138, 0x709b, 0x001e, 0x0020, 0x709b, 0x001f, 0x080c, 0x75f4,
-	0x0005, 0x0006, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x000e, 0x6124,
-	0xd1d4, 0x1160, 0xd1cc, 0x1150, 0xd1dc, 0x1128, 0xd1e4, 0x0140,
-	0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010, 0x709b, 0x0021,
-	0x0005, 0x080c, 0x767d, 0x6124, 0xd1d4, 0x1150, 0xd1dc, 0x1128,
-	0xd1e4, 0x0140, 0x709b, 0x001e, 0x0028, 0x709b, 0x001d, 0x0010,
-	0x709b, 0x001f, 0x0005, 0x0006, 0x2001, 0x0090, 0x080c, 0x2a99,
-	0x000e, 0x6124, 0xd1d4, 0x1178, 0xd1cc, 0x1150, 0xd1dc, 0x1128,
-	0xd1e4, 0x0158, 0x709b, 0x001e, 0x0040, 0x709b, 0x001d, 0x0028,
-	0x709b, 0x0020, 0x0010, 0x709b, 0x001f, 0x0005, 0x0016, 0x00c6,
-	0x00d6, 0x00e6, 0x0126, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071,
-	0x1800, 0x2091, 0x8000, 0x080c, 0x779e, 0x11f8, 0x2001, 0x180c,
-	0x200c, 0xd1b4, 0x01d0, 0xc1b4, 0x2102, 0x0026, 0x2011, 0x0200,
-	0x080c, 0x2ad3, 0x002e, 0x080c, 0x2a7f, 0x6024, 0xd0cc, 0x0148,
-	0x2001, 0x00a0, 0x080c, 0x2a99, 0x080c, 0x7ab6, 0x080c, 0x619d,
-	0x0428, 0x6028, 0xc0cd, 0x602a, 0x0408, 0x080c, 0x77b8, 0x0150,
-	0x080c, 0x77af, 0x1138, 0x2001, 0x0001, 0x080c, 0x2631, 0x080c,
-	0x7772, 0x00a0, 0x080c, 0x767a, 0x0178, 0x2001, 0x0001, 0x080c,
-	0x2631, 0x7098, 0x9086, 0x001e, 0x0120, 0x7098, 0x9086, 0x0022,
-	0x1118, 0x709b, 0x0025, 0x0010, 0x709b, 0x0021, 0x012e, 0x00ee,
-	0x00de, 0x00ce, 0x001e, 0x0005, 0x0026, 0x2011, 0x7605, 0x080c,
-	0x8a9f, 0x002e, 0x0016, 0x0026, 0x2009, 0x0064, 0x2011, 0x7605,
-	0x080c, 0x8a96, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00f6, 0x0016,
-	0x080c, 0xa2a0, 0x2071, 0x1800, 0x080c, 0x759e, 0x001e, 0x00fe,
-	0x00ee, 0x0005, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6,
-	0x00f6, 0x0126, 0x2071, 0x1800, 0x080c, 0xa2a0, 0x2061, 0x0100,
-	0x2069, 0x0140, 0x2091, 0x8000, 0x6028, 0xc09c, 0x602a, 0x080c,
-	0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c,
-	0xa635, 0x080c, 0xa516, 0x080c, 0x8a4b, 0x0036, 0x901e, 0x080c,
-	0xa596, 0x003e, 0x080c, 0xad18, 0x60e3, 0x0000, 0x080c, 0xeed9,
-	0x080c, 0xeef4, 0x2009, 0x0004, 0x080c, 0x2a85, 0x080c, 0x299b,
-	0x2001, 0x1800, 0x2003, 0x0004, 0x2011, 0x0008, 0x080c, 0x2ad3,
-	0x2011, 0x7605, 0x080c, 0x8a9f, 0x080c, 0x77b8, 0x0118, 0x9006,
-	0x080c, 0x2a99, 0x080c, 0x0bcf, 0x2001, 0x0001, 0x080c, 0x2631,
-	0x012e, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
-	0x0005, 0x0026, 0x00e6, 0x2011, 0x7612, 0x2071, 0x1a04, 0x701c,
-	0x9206, 0x1118, 0x7018, 0x9005, 0x0110, 0x9085, 0x0001, 0x00ee,
-	0x002e, 0x0005, 0x6020, 0xd09c, 0x0005, 0x6800, 0x9084, 0xfffe,
-	0x9086, 0x00c0, 0x01b8, 0x2001, 0x00c0, 0x080c, 0x2a99, 0x0156,
-	0x20a9, 0x002d, 0x1d04, 0x768a, 0x2091, 0x6000, 0x1f04, 0x768a,
-	0x015e, 0x00d6, 0x2069, 0x1800, 0x689c, 0x8001, 0x0220, 0x0118,
-	0x689e, 0x00de, 0x0005, 0x689f, 0x0014, 0x68ec, 0xd0dc, 0x0dc8,
-	0x6800, 0x9086, 0x0001, 0x1da8, 0x080c, 0x8aab, 0x0c90, 0x00c6,
-	0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800,
-	0x080c, 0x7ac5, 0x2001, 0x196d, 0x2003, 0x0000, 0x9006, 0x709a,
-	0x60e2, 0x6886, 0x080c, 0x2700, 0x9006, 0x080c, 0x2a99, 0x080c,
-	0x6058, 0x0026, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x002e, 0x602b,
-	0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6,
-	0x2061, 0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x2001, 0x197d,
-	0x200c, 0x9186, 0x0000, 0x0158, 0x9186, 0x0001, 0x0158, 0x9186,
-	0x0002, 0x0158, 0x9186, 0x0003, 0x0158, 0x0804, 0x7762, 0x709b,
-	0x0022, 0x0040, 0x709b, 0x0021, 0x0028, 0x709b, 0x0023, 0x0010,
-	0x709b, 0x0024, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001,
-	0x080c, 0x2700, 0x080c, 0xacfc, 0x0026, 0x080c, 0xafd2, 0x080c,
-	0xb09b, 0x002e, 0x080c, 0xad18, 0x7000, 0x908e, 0x0004, 0x0118,
-	0x602b, 0x0028, 0x0010, 0x602b, 0x0020, 0x0156, 0x0126, 0x2091,
-	0x8000, 0x20a9, 0x0005, 0x6024, 0xd0ac, 0x0150, 0x012e, 0x015e,
-	0x080c, 0xd645, 0x0118, 0x9006, 0x080c, 0x2ac3, 0x0804, 0x776e,
-	0x6800, 0x9084, 0x00a1, 0xc0bd, 0x6802, 0x080c, 0x2a7f, 0x6904,
-	0xd1d4, 0x1140, 0x2001, 0x0100, 0x080c, 0x2a99, 0x1f04, 0x7713,
-	0x080c, 0x77f2, 0x012e, 0x015e, 0x080c, 0x77af, 0x0170, 0x6044,
-	0x9005, 0x0130, 0x080c, 0x77f2, 0x9006, 0x8001, 0x1df0, 0x0028,
-	0x6804, 0xd0d4, 0x1110, 0x080c, 0x77f2, 0x080c, 0xd645, 0x0118,
-	0x9006, 0x080c, 0x2ac3, 0x0016, 0x0026, 0x7000, 0x908e, 0x0004,
-	0x0130, 0x2009, 0x00c8, 0x2011, 0x7612, 0x080c, 0x8a5d, 0x002e,
-	0x001e, 0x080c, 0x8890, 0x7034, 0xc085, 0x7036, 0x2001, 0x197d,
-	0x2003, 0x0004, 0x080c, 0x744d, 0x080c, 0x77af, 0x0138, 0x6804,
-	0xd0d4, 0x1120, 0xd0dc, 0x1100, 0x080c, 0x7abb, 0x00ee, 0x00de,
-	0x00ce, 0x0005, 0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2069,
-	0x0140, 0x2071, 0x1800, 0x080c, 0x88a7, 0x080c, 0x8899, 0x080c,
-	0x7ac5, 0x2001, 0x196d, 0x2003, 0x0000, 0x9006, 0x709a, 0x60e2,
-	0x6886, 0x080c, 0x2700, 0x9006, 0x080c, 0x2a99, 0x6043, 0x0090,
-	0x6043, 0x0010, 0x0026, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x002e,
-	0x602b, 0x182c, 0x00ee, 0x00de, 0x00ce, 0x0005, 0x0006, 0x2001,
-	0x197c, 0x2004, 0x9086, 0xaaaa, 0x000e, 0x0005, 0x0006, 0x080c,
-	0x5844, 0x9084, 0x0030, 0x9086, 0x0000, 0x000e, 0x0005, 0x0006,
-	0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0030, 0x000e, 0x0005,
-	0x0006, 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0010, 0x000e,
-	0x0005, 0x0006, 0x080c, 0x5844, 0x9084, 0x0030, 0x9086, 0x0020,
-	0x000e, 0x0005, 0x0036, 0x0016, 0x2001, 0x180c, 0x2004, 0x908c,
-	0x0013, 0x0168, 0x0020, 0x080c, 0x2720, 0x900e, 0x0010, 0x2009,
-	0x0002, 0x2019, 0x0028, 0x080c, 0x32da, 0x9006, 0x0019, 0x001e,
-	0x003e, 0x0005, 0x00e6, 0x2071, 0x180c, 0x2e04, 0x0130, 0x080c,
-	0xd63e, 0x1128, 0x9085, 0x0010, 0x0010, 0x9084, 0xffef, 0x2072,
-	0x00ee, 0x0005, 0x6050, 0x0006, 0x60ec, 0x0006, 0x600c, 0x0006,
-	0x6004, 0x0006, 0x6028, 0x0006, 0x080c, 0x2af6, 0x080c, 0x2b29,
-	0x602f, 0x0100, 0x602f, 0x0000, 0x602f, 0x0040, 0x602f, 0x0000,
-	0x20a9, 0x0002, 0x080c, 0x2a60, 0x0026, 0x2011, 0x0040, 0x080c,
-	0x2ad3, 0x002e, 0x000e, 0x602a, 0x000e, 0x6006, 0x000e, 0x600e,
-	0x000e, 0x60ee, 0x60e3, 0x0000, 0x6887, 0x0001, 0x2001, 0x0001,
-	0x080c, 0x2700, 0x2001, 0x00a0, 0x0006, 0x080c, 0xd645, 0x000e,
-	0x0130, 0x080c, 0x2ab7, 0x9006, 0x080c, 0x2ac3, 0x0010, 0x080c,
-	0x2a99, 0x000e, 0x6052, 0x6050, 0x0006, 0xc0e5, 0x6052, 0x00f6,
-	0x2079, 0x0100, 0x080c, 0x2a0c, 0x00fe, 0x000e, 0x6052, 0x0005,
-	0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061,
-	0x0100, 0x2069, 0x0140, 0x2071, 0x1800, 0x080c, 0xad5a, 0x0158,
-	0x2001, 0x0386, 0x2004, 0xd0b4, 0x1130, 0x2001, 0x0016, 0x080c,
-	0xaced, 0x0804, 0x78d6, 0x2001, 0x180c, 0x200c, 0xc1c4, 0x2102,
-	0x6028, 0x9084, 0xe1ff, 0x602a, 0x2011, 0x0200, 0x080c, 0x2ad3,
-	0x2001, 0x0090, 0x080c, 0x2a99, 0x20a9, 0x0366, 0x6024, 0xd0cc,
-	0x1560, 0x1d04, 0x786e, 0x2091, 0x6000, 0x1f04, 0x786e, 0x080c,
-	0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c,
-	0xa635, 0x080c, 0xa516, 0x901e, 0x080c, 0xa596, 0x2001, 0x0386,
-	0x2003, 0x7000, 0x080c, 0xad18, 0x2001, 0x00a0, 0x080c, 0x2a99,
-	0x080c, 0x7ab6, 0x080c, 0x619d, 0x080c, 0xd645, 0x0110, 0x080c,
-	0x0cf1, 0x9085, 0x0001, 0x0804, 0x78dc, 0x080c, 0x1b4b, 0x60e3,
-	0x0000, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118,
-	0x2001, 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x2001, 0x0080,
-	0x080c, 0x2a99, 0x20a9, 0x0366, 0x2011, 0x1e00, 0x080c, 0x2ad3,
-	0x2009, 0x1e00, 0x080c, 0x2a7f, 0x6024, 0x910c, 0x0140, 0x1d04,
-	0x78b4, 0x2091, 0x6000, 0x1f04, 0x78b4, 0x0804, 0x7877, 0x2001,
-	0x0386, 0x2003, 0x7000, 0x6028, 0x9085, 0x1e00, 0x602a, 0x70b4,
-	0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886, 0x080c, 0xd645,
-	0x0110, 0x080c, 0x0cf1, 0x9006, 0x00ee, 0x00de, 0x00ce, 0x003e,
-	0x002e, 0x001e, 0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036,
-	0x00c6, 0x00d6, 0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x7000,
-	0x9086, 0x0003, 0x1168, 0x2001, 0x020b, 0x2004, 0x9084, 0x5540,
-	0x9086, 0x5540, 0x1128, 0x2069, 0x1a7b, 0x2d04, 0x8000, 0x206a,
-	0x2069, 0x0140, 0x6020, 0x9084, 0x00c0, 0x0120, 0x6884, 0x9005,
-	0x1904, 0x794d, 0x2001, 0x0088, 0x080c, 0x2a99, 0x9006, 0x60e2,
-	0x6886, 0x080c, 0x2700, 0x2069, 0x0200, 0x6804, 0x9005, 0x1118,
-	0x6808, 0x9005, 0x01d0, 0x6028, 0x9084, 0xfbff, 0x602a, 0x2011,
-	0x0400, 0x080c, 0x2ad3, 0x2069, 0x198f, 0x7000, 0x206a, 0x709b,
-	0x0026, 0x7003, 0x0001, 0x20a9, 0x0002, 0x1d04, 0x792d, 0x2091,
-	0x6000, 0x1f04, 0x792d, 0x0804, 0x7988, 0x2069, 0x0140, 0x20a9,
-	0x0384, 0x2011, 0x1e00, 0x080c, 0x2ad3, 0x2009, 0x1e00, 0x080c,
-	0x2a7f, 0x6024, 0x910c, 0x0528, 0x9084, 0x1a00, 0x1510, 0x1d04,
-	0x7939, 0x2091, 0x6000, 0x1f04, 0x7939, 0x080c, 0xacfc, 0x2011,
-	0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c, 0xa635, 0x080c,
-	0xa516, 0x901e, 0x080c, 0xa596, 0x080c, 0xad18, 0x2001, 0x00a0,
-	0x080c, 0x2a99, 0x080c, 0x7ab6, 0x080c, 0x619d, 0x9085, 0x0001,
-	0x00f8, 0x080c, 0x1b4b, 0x2001, 0x0080, 0x080c, 0x2a99, 0x2069,
-	0x0140, 0x60e3, 0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001,
-	0x0008, 0x6886, 0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002,
-	0x1118, 0x2001, 0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x9006,
-	0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005,
-	0x0156, 0x0016, 0x0026, 0x0036, 0x00c6, 0x00d6, 0x00e6, 0x2061,
-	0x0100, 0x2071, 0x1800, 0x6020, 0x9084, 0x00c0, 0x01e8, 0x080c,
-	0xacfc, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011, 0x0002, 0x080c,
-	0xa635, 0x080c, 0xa516, 0x901e, 0x080c, 0xa596, 0x080c, 0xad18,
-	0x2069, 0x0140, 0x2001, 0x00a0, 0x080c, 0x2a99, 0x080c, 0x7ab6,
-	0x080c, 0x619d, 0x0804, 0x7a32, 0x2001, 0x180c, 0x200c, 0xd1b4,
-	0x1160, 0xc1b5, 0x2102, 0x080c, 0x75fa, 0x2069, 0x0140, 0x2001,
-	0x0080, 0x080c, 0x2a99, 0x60e3, 0x0000, 0x2069, 0x0200, 0x6804,
-	0x9005, 0x1118, 0x6808, 0x9005, 0x0190, 0x6028, 0x9084, 0xfdff,
-	0x602a, 0x2011, 0x0200, 0x080c, 0x2ad3, 0x2069, 0x198f, 0x7000,
-	0x206a, 0x709b, 0x0027, 0x7003, 0x0001, 0x0804, 0x7a32, 0x2011,
-	0x1e00, 0x080c, 0x2ad3, 0x2009, 0x1e00, 0x080c, 0x2a7f, 0x6024,
-	0x910c, 0x01c8, 0x9084, 0x1c00, 0x11b0, 0x1d04, 0x79e7, 0x0006,
-	0x0016, 0x00c6, 0x00d6, 0x00e6, 0x080c, 0x88e7, 0x00ee, 0x00de,
-	0x00ce, 0x001e, 0x000e, 0x00e6, 0x2071, 0x1a04, 0x7078, 0x00ee,
-	0x9005, 0x19e8, 0x0438, 0x0026, 0x2011, 0x7612, 0x080c, 0x8993,
-	0x2011, 0x7605, 0x080c, 0x8a9f, 0x002e, 0x2069, 0x0140, 0x60e3,
-	0x0000, 0x70b4, 0x9005, 0x1118, 0x6887, 0x0001, 0x0008, 0x6886,
-	0x2001, 0x180d, 0x2004, 0xd08c, 0x2001, 0x0002, 0x1118, 0x2001,
-	0x196d, 0x2004, 0x080c, 0x2700, 0x60e2, 0x2001, 0x180c, 0x200c,
-	0xc1b4, 0x2102, 0x00ee, 0x00de, 0x00ce, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x0005, 0x0156, 0x0016, 0x0026, 0x0036, 0x0046, 0x00c6,
-	0x00e6, 0x2061, 0x0100, 0x2071, 0x1800, 0x080c, 0xd63e, 0x1904,
-	0x7aa0, 0x7130, 0xd184, 0x1170, 0x080c, 0x3482, 0x0138, 0xc18d,
-	0x7132, 0x2011, 0x1848, 0x2214, 0xd2ac, 0x1120, 0x7030, 0xd08c,
-	0x0904, 0x7aa0, 0x2011, 0x1848, 0x220c, 0xd1a4, 0x0538, 0x0016,
-	0x2019, 0x000e, 0x080c, 0xe9f9, 0x0156, 0x00b6, 0x20a9, 0x007f,
-	0x900e, 0x9186, 0x007e, 0x01a0, 0x9186, 0x0080, 0x0188, 0x080c,
-	0x67b4, 0x1170, 0x2120, 0x9006, 0x0016, 0x2009, 0x000e, 0x080c,
-	0xea8d, 0x2009, 0x0001, 0x2011, 0x0100, 0x080c, 0x8c44, 0x001e,
-	0x8108, 0x1f04, 0x7a69, 0x00be, 0x015e, 0x001e, 0xd1ac, 0x1148,
-	0x0016, 0x2009, 0x0002, 0x2019, 0x0004, 0x080c, 0x32da, 0x001e,
-	0x0078, 0x0156, 0x00b6, 0x20a9, 0x007f, 0x900e, 0x080c, 0x67b4,
-	0x1110, 0x080c, 0x61b7, 0x8108, 0x1f04, 0x7a96, 0x00be, 0x015e,
-	0x080c, 0x1b4b, 0x080c, 0xacfc, 0x080c, 0xb09b, 0x080c, 0xad18,
-	0x60e3, 0x0000, 0x080c, 0x619d, 0x080c, 0x76cd, 0x00ee, 0x00ce,
-	0x004e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0005, 0x2001, 0x197d,
-	0x2003, 0x0001, 0x0005, 0x2001, 0x197d, 0x2003, 0x0000, 0x0005,
-	0x2001, 0x197c, 0x2003, 0xaaaa, 0x0005, 0x2001, 0x197c, 0x2003,
-	0x0000, 0x0005, 0x2071, 0x18fa, 0x7003, 0x0000, 0x7007, 0x0000,
-	0x080c, 0x1072, 0x090c, 0x0d85, 0xa8ab, 0xdcb0, 0x2900, 0x704e,
-	0x080c, 0x1072, 0x090c, 0x0d85, 0xa8ab, 0xdcb0, 0x2900, 0x7052,
-	0xa867, 0x0000, 0xa86b, 0x0001, 0xa89f, 0x0000, 0x0005, 0x00e6,
-	0x2071, 0x0040, 0x6848, 0x9005, 0x1118, 0x9085, 0x0001, 0x04b0,
-	0x6840, 0x9005, 0x0150, 0x04a1, 0x6a50, 0x9200, 0x7002, 0x6854,
-	0x9101, 0x7006, 0x9006, 0x7012, 0x7016, 0x6850, 0x7002, 0x6854,
-	0x7006, 0x6858, 0x700a, 0x685c, 0x700e, 0x6840, 0x9005, 0x1110,
-	0x7012, 0x7016, 0x6848, 0x701a, 0x701c, 0x9085, 0x0040, 0x701e,
-	0x2001, 0x0019, 0x7036, 0x702b, 0x0001, 0x2001, 0x0004, 0x200c,
-	0x918c, 0xfff7, 0x918d, 0x8000, 0x2102, 0x00d6, 0x2069, 0x18fa,
-	0x6807, 0x0001, 0x00de, 0x080c, 0x8103, 0x9006, 0x00ee, 0x0005,
-	0x900e, 0x0156, 0x20a9, 0x0006, 0x8003, 0x818d, 0x1f04, 0x7b2c,
-	0x015e, 0x0005, 0x2079, 0x0040, 0x2071, 0x18fa, 0x7004, 0x0002,
-	0x7b42, 0x7b43, 0x7b8f, 0x7bea, 0x7d4a, 0x7b40, 0x7b40, 0x7d74,
-	0x080c, 0x0d85, 0x0005, 0x2079, 0x0040, 0x2001, 0x1dc0, 0x2003,
-	0x0000, 0x782c, 0x908c, 0x0780, 0x190c, 0x81e5, 0xd0a4, 0x0578,
-	0x2001, 0x1dc0, 0x2004, 0x9082, 0x0080, 0x1648, 0x1d04, 0x7b60,
-	0x2001, 0x1a07, 0x200c, 0x8109, 0x0510, 0x2091, 0x6000, 0x2102,
-	0x7824, 0x2048, 0x9006, 0xa802, 0xa806, 0xa864, 0x9084, 0x00ff,
-	0x908a, 0x0040, 0x0610, 0x00c0, 0x2001, 0x1800, 0x200c, 0x9186,
-	0x0003, 0x1168, 0x7004, 0x0002, 0x7b7f, 0x7b49, 0x7b7f, 0x7b7d,
-	0x7b7f, 0x7b7f, 0x7b7f, 0x7b7f, 0x7b7f, 0x080c, 0x7bea, 0x782c,
-	0xd09c, 0x090c, 0x8103, 0x0005, 0x9082, 0x005a, 0x1218, 0x2100,
-	0x003b, 0x0c10, 0x080c, 0x7c20, 0x0c90, 0x00e3, 0x08e8, 0x0005,
-	0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20,
-	0x7c42, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20,
-	0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20,
-	0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c2c, 0x7c20, 0x7e6a, 0x7c20,
-	0x7c20, 0x7c20, 0x7c42, 0x7c20, 0x7c2c, 0x7eab, 0x7eec, 0x7f33,
-	0x7f47, 0x7c20, 0x7c20, 0x7c42, 0x7c2c, 0x7c56, 0x7c20, 0x7d1e,
-	0x7ff2, 0x800d, 0x7c20, 0x7c42, 0x7c20, 0x7c56, 0x7c20, 0x7c20,
-	0x7d14, 0x800d, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20,
-	0x7c20, 0x7c20, 0x7c20, 0x7c6a, 0x7c20, 0x7c20, 0x7c20, 0x7c20,
-	0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x7c20, 0x8189, 0x7c20, 0x8133,
-	0x7c20, 0x8133, 0x7c20, 0x7c7f, 0x7c20, 0x7c20, 0x7c20, 0x7c20,
-	0x7c20, 0x7c20, 0x2079, 0x0040, 0x7004, 0x9086, 0x0003, 0x1198,
-	0x782c, 0x080c, 0x812c, 0xd0a4, 0x0170, 0x7824, 0x2048, 0x9006,
-	0xa802, 0xa806, 0xa864, 0x9084, 0x00ff, 0x908a, 0x001a, 0x1210,
-	0x002b, 0x0c50, 0x00e9, 0x080c, 0x8103, 0x0005, 0x7c20, 0x7c2c,
-	0x7e56, 0x7c20, 0x7c2c, 0x7c20, 0x7c2c, 0x7c2c, 0x7c20, 0x7c2c,
-	0x7e56, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c2c, 0x7c20, 0x7c2c,
-	0x7e56, 0x7c20, 0x7c20, 0x7c2c, 0x7c20, 0x7c20, 0x7c20, 0x7c2c,
-	0x00e6, 0x2071, 0x18fa, 0x2009, 0x0400, 0x0071, 0x00ee, 0x0005,
-	0x2009, 0x1000, 0x0049, 0x0005, 0x2009, 0x2000, 0x0029, 0x0005,
-	0x2009, 0x0800, 0x0009, 0x0005, 0x7007, 0x0001, 0xa868, 0x9084,
-	0x00ff, 0x9105, 0xa86a, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012,
-	0x012e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0d08, 0x8001,
-	0x1120, 0x7007, 0x0001, 0x0804, 0x7df3, 0x7007, 0x0003, 0x7012,
-	0x2900, 0x7016, 0x701a, 0x704b, 0x7df3, 0x0005, 0xa864, 0x8007,
-	0x9084, 0x00ff, 0x0968, 0x8001, 0x1120, 0x7007, 0x0001, 0x0804,
-	0x7e0e, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016, 0x701a, 0x704b,
-	0x7e0e, 0x0005, 0xa864, 0x8007, 0x9084, 0x00ff, 0x0904, 0x7c28,
-	0x8001, 0x1120, 0x7007, 0x0001, 0x0804, 0x7e2a, 0x7007, 0x0003,
-	0x7012, 0x2900, 0x7016, 0x701a, 0x704b, 0x7e2a, 0x0005, 0xa864,
-	0x8007, 0x9084, 0x00ff, 0x9086, 0x0001, 0x1904, 0x7c28, 0x7007,
-	0x0001, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1904, 0x7ceb, 0x2001,
-	0x180d, 0x2004, 0xd08c, 0x0904, 0x7cd6, 0xa99c, 0x9186, 0x00ff,
-	0x05e8, 0xa994, 0x9186, 0x006f, 0x0188, 0x9186, 0x0074, 0x15b0,
-	0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0578, 0x0016,
-	0xa998, 0x080c, 0x6c7f, 0x001e, 0x1548, 0x0400, 0x080c, 0x779e,
-	0x0140, 0xa897, 0x4005, 0xa89b, 0x0016, 0x2001, 0x0030, 0x900e,
-	0x0438, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e, 0x01b0,
-	0x0016, 0x0026, 0x0036, 0xa998, 0xaaa0, 0xab9c, 0x918d, 0x8000,
-	0x080c, 0x6c7f, 0x003e, 0x002e, 0x001e, 0x1140, 0xa897, 0x4005,
-	0xa89b, 0x4009, 0x2001, 0x0030, 0x900e, 0x0050, 0xa868, 0x9084,
-	0x00ff, 0xa86a, 0xa883, 0x0000, 0x080c, 0x6430, 0x1108, 0x0005,
-	0x0126, 0x2091, 0x8000, 0xa867, 0x0139, 0xa87a, 0xa982, 0x080c,
-	0x7012, 0x012e, 0x0ca0, 0xa994, 0x9186, 0x0071, 0x0904, 0x7c8f,
-	0x9186, 0x0064, 0x0904, 0x7c8f, 0x9186, 0x007c, 0x0904, 0x7c8f,
-	0x9186, 0x0028, 0x0904, 0x7c8f, 0x9186, 0x0038, 0x0904, 0x7c8f,
-	0x9186, 0x0078, 0x0904, 0x7c8f, 0x9186, 0x005f, 0x0904, 0x7c8f,
-	0x9186, 0x0056, 0x0904, 0x7c8f, 0xa897, 0x4005, 0xa89b, 0x0001,
-	0x2001, 0x0030, 0x900e, 0x0860, 0xa87c, 0x9084, 0x00c0, 0x9086,
-	0x00c0, 0x1120, 0x7007, 0x0001, 0x0804, 0x8024, 0x2900, 0x7016,
-	0x701a, 0x20a9, 0x0004, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0030,
-	0x2098, 0x7050, 0x2040, 0xa060, 0x20e8, 0xa05c, 0x9080, 0x0023,
-	0x20a0, 0x4003, 0xa888, 0x7012, 0x9082, 0x0401, 0x1a04, 0x7c30,
-	0xaab4, 0x928a, 0x0002, 0x1a04, 0x7c30, 0x82ff, 0x1138, 0xa8b8,
-	0xa9bc, 0x9105, 0x0118, 0x2001, 0x7db1, 0x0018, 0x9280, 0x7da7,
-	0x2005, 0x7056, 0x7010, 0x9015, 0x0904, 0x7d92, 0x080c, 0x1072,
-	0x1118, 0x7007, 0x0004, 0x0005, 0x2900, 0x7022, 0x7054, 0x2060,
-	0xe000, 0xa866, 0x7050, 0x2040, 0xa95c, 0xe004, 0x9100, 0xa076,
-	0xa860, 0xa072, 0xe008, 0x920a, 0x1210, 0x900e, 0x2200, 0x7112,
-	0xe20c, 0x8003, 0x800b, 0x9296, 0x0004, 0x0108, 0x9108, 0xa17a,
-	0x810b, 0xa17e, 0x080c, 0x114e, 0xa06c, 0x908e, 0x0100, 0x0170,
-	0x9086, 0x0200, 0x0118, 0x7007, 0x0007, 0x0005, 0x7020, 0x2048,
-	0x080c, 0x108b, 0x7014, 0x2048, 0x0804, 0x7c30, 0x7020, 0x2048,
-	0x7018, 0xa802, 0xa807, 0x0000, 0x2908, 0x2048, 0xa906, 0x711a,
-	0x0804, 0x7d4a, 0x7014, 0x2048, 0x7007, 0x0001, 0xa8b4, 0x9005,
-	0x1128, 0xa8b8, 0xa9bc, 0x9105, 0x0108, 0x00b9, 0xa864, 0x9084,
-	0x00ff, 0x9086, 0x001e, 0x0904, 0x8024, 0x0804, 0x7df3, 0x7da9,
-	0x7dad, 0x0002, 0x001d, 0x0007, 0x0004, 0x000a, 0x001b, 0x0005,
-	0x0006, 0x000a, 0x001d, 0x0005, 0x0004, 0x0076, 0x0066, 0xafb8,
-	0xaebc, 0xa804, 0x2050, 0xb0c0, 0xb0e2, 0xb0bc, 0xb0de, 0xb0b8,
-	0xb0d2, 0xb0b4, 0xb0ce, 0xb6da, 0xb7d6, 0xb0b0, 0xb0ca, 0xb0ac,
-	0xb0c6, 0xb0a8, 0xb0ba, 0xb0a4, 0xb0b6, 0xb6c2, 0xb7be, 0xb0a0,
-	0xb0b2, 0xb09c, 0xb0ae, 0xb098, 0xb0a2, 0xb094, 0xb09e, 0xb6aa,
-	0xb7a6, 0xb090, 0xb09a, 0xb08c, 0xb096, 0xb088, 0xb08a, 0xb084,
-	0xb086, 0xb692, 0xb78e, 0xb080, 0xb082, 0xb07c, 0xb07e, 0xb078,
-	0xb072, 0xb074, 0xb06e, 0xb67a, 0xb776, 0xb004, 0x9055, 0x1958,
-	0x006e, 0x007e, 0x0005, 0x2009, 0x1834, 0x210c, 0x81ff, 0x1178,
-	0x080c, 0x622f, 0x1108, 0x0005, 0x080c, 0x725e, 0x0126, 0x2091,
-	0x8000, 0x080c, 0xd220, 0x080c, 0x7012, 0x012e, 0x0ca0, 0x080c,
-	0xd63e, 0x1d70, 0x2001, 0x0028, 0x900e, 0x0c70, 0x2009, 0x1834,
-	0x210c, 0x81ff, 0x1188, 0xa888, 0x9005, 0x0188, 0xa883, 0x0000,
-	0x080c, 0x62bd, 0x1108, 0x0005, 0xa87a, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x7012, 0x012e, 0x0cb8, 0x2001, 0x0028, 0x0ca8, 0x2001,
-	0x0000, 0x0c90, 0x0419, 0x11d8, 0xa888, 0x9005, 0x01e0, 0xa883,
-	0x0000, 0xa87c, 0xd0f4, 0x0120, 0x080c, 0x6392, 0x1138, 0x0005,
-	0x9006, 0xa87a, 0x080c, 0x630a, 0x1108, 0x0005, 0x0126, 0x2091,
-	0x8000, 0xa87a, 0xa982, 0x080c, 0x7012, 0x012e, 0x0cb0, 0x2001,
-	0x0028, 0x900e, 0x0c98, 0x2001, 0x0000, 0x0c80, 0x00c6, 0x2061,
-	0x1800, 0x60d0, 0x9005, 0x0100, 0x00ce, 0x0005, 0x7018, 0xa802,
-	0x2908, 0x2048, 0xa906, 0x711a, 0x7010, 0x8001, 0x7012, 0x0118,
-	0x7007, 0x0003, 0x0030, 0x7014, 0x2048, 0x7007, 0x0001, 0x7048,
-	0x080f, 0x0005, 0x00b6, 0x7007, 0x0001, 0xa974, 0xa878, 0x9084,
-	0x00ff, 0x9096, 0x0004, 0x0540, 0x20a9, 0x0001, 0x9096, 0x0001,
-	0x0190, 0x900e, 0x20a9, 0x0800, 0x9096, 0x0002, 0x0160, 0x9005,
-	0x11d8, 0xa974, 0x080c, 0x67b4, 0x11b8, 0x0066, 0xae80, 0x080c,
-	0x68c4, 0x006e, 0x0088, 0x0046, 0x2011, 0x180c, 0x2224, 0xc484,
-	0x2412, 0x004e, 0x00c6, 0x080c, 0x67b4, 0x1110, 0x080c, 0x6a9e,
-	0x8108, 0x1f04, 0x7e93, 0x00ce, 0xa87c, 0xd084, 0x1120, 0x080c,
-	0x108b, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012,
-	0x012e, 0x00be, 0x0005, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001,
-	0x080c, 0x6c0d, 0x0580, 0x2061, 0x1a73, 0x6100, 0xd184, 0x0178,
-	0xa888, 0x9084, 0x00ff, 0x1550, 0x6000, 0xd084, 0x0520, 0x6004,
-	0x9005, 0x1538, 0x6003, 0x0000, 0x600b, 0x0000, 0x00c8, 0x2011,
-	0x0001, 0xa890, 0x9005, 0x1110, 0x2001, 0x001e, 0x8000, 0x6016,
-	0xa888, 0x9084, 0x00ff, 0x0178, 0x6006, 0xa888, 0x8007, 0x9084,
-	0x00ff, 0x0148, 0x600a, 0xa888, 0x8000, 0x1108, 0xc28d, 0x6202,
-	0x012e, 0x0804, 0x80ed, 0x012e, 0x0804, 0x80e7, 0x012e, 0x0804,
-	0x80e1, 0x012e, 0x0804, 0x80e4, 0x0126, 0x2091, 0x8000, 0x7007,
-	0x0001, 0x080c, 0x6c0d, 0x05e0, 0x2061, 0x1a73, 0x6000, 0xd084,
-	0x05b8, 0x6204, 0x6308, 0xd08c, 0x1530, 0xac78, 0x9484, 0x0003,
-	0x0170, 0xa988, 0x918c, 0x00ff, 0x8001, 0x1120, 0x2100, 0x9210,
-	0x0620, 0x0028, 0x8001, 0x1508, 0x2100, 0x9212, 0x02f0, 0x9484,
-	0x000c, 0x0188, 0xa988, 0x810f, 0x918c, 0x00ff, 0x9082, 0x0004,
-	0x1120, 0x2100, 0x9318, 0x0288, 0x0030, 0x9082, 0x0004, 0x1168,
-	0x2100, 0x931a, 0x0250, 0xa890, 0x9005, 0x0110, 0x8000, 0x6016,
-	0x6206, 0x630a, 0x012e, 0x0804, 0x80ed, 0x012e, 0x0804, 0x80ea,
-	0x012e, 0x0804, 0x80e7, 0x0126, 0x2091, 0x8000, 0x7007, 0x0001,
-	0x2061, 0x1a73, 0x6300, 0xd38c, 0x1120, 0x6308, 0x8318, 0x0220,
-	0x630a, 0x012e, 0x0804, 0x80fb, 0x012e, 0x0804, 0x80ea, 0x00b6,
-	0x0126, 0x00c6, 0x2091, 0x8000, 0x7007, 0x0001, 0xa87c, 0xd0ac,
-	0x0148, 0x00c6, 0x2061, 0x1a73, 0x6000, 0x9084, 0xfcff, 0x6002,
-	0x00ce, 0x0440, 0xa888, 0x9005, 0x05d8, 0xa88c, 0x9065, 0x0598,
-	0x2001, 0x1834, 0x2004, 0x9005, 0x0118, 0x080c, 0xb1a7, 0x0068,
-	0x6017, 0xf400, 0x6063, 0x0000, 0xa97c, 0xd1a4, 0x0110, 0xa980,
-	0x6162, 0x2009, 0x0041, 0x080c, 0xb20a, 0xa988, 0x918c, 0xff00,
-	0x9186, 0x2000, 0x1138, 0x0026, 0x900e, 0x2011, 0xfdff, 0x080c,
-	0x8c44, 0x002e, 0xa87c, 0xd0c4, 0x0148, 0x2061, 0x1a73, 0x6000,
-	0xd08c, 0x1120, 0x6008, 0x8000, 0x0208, 0x600a, 0x00ce, 0x012e,
-	0x00be, 0x0804, 0x80ed, 0x00ce, 0x012e, 0x00be, 0x0804, 0x80e7,
-	0xa984, 0x9186, 0x002e, 0x0d30, 0x9186, 0x002d, 0x0d18, 0x9186,
-	0x0045, 0x0510, 0x9186, 0x002a, 0x1130, 0x2001, 0x180c, 0x200c,
-	0xc194, 0x2102, 0x08b8, 0x9186, 0x0020, 0x0158, 0x9186, 0x0029,
-	0x1d10, 0xa974, 0x080c, 0x67b4, 0x1968, 0xb800, 0xc0e4, 0xb802,
-	0x0848, 0xa88c, 0x9065, 0x09b8, 0x6007, 0x0024, 0x2001, 0x1986,
-	0x2004, 0x601a, 0x0804, 0x7f82, 0xa88c, 0x9065, 0x0960, 0x00e6,
-	0xa890, 0x9075, 0x2001, 0x1834, 0x2004, 0x9005, 0x0150, 0x080c,
-	0xb1a7, 0x8eff, 0x0118, 0x2e60, 0x080c, 0xb1a7, 0x00ee, 0x0804,
-	0x7f82, 0x6024, 0xc0dc, 0xc0d5, 0x6026, 0x2e60, 0x6007, 0x003a,
-	0xa8a0, 0x9005, 0x0130, 0x6007, 0x003b, 0xa8a4, 0x602e, 0xa8a8,
-	0x6016, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00ee,
-	0x0804, 0x7f82, 0x2061, 0x1a73, 0x6000, 0xd084, 0x0190, 0xd08c,
-	0x1904, 0x80fb, 0x0126, 0x2091, 0x8000, 0x6204, 0x8210, 0x0220,
-	0x6206, 0x012e, 0x0804, 0x80fb, 0x012e, 0xa883, 0x0016, 0x0804,
-	0x80f4, 0xa883, 0x0007, 0x0804, 0x80f4, 0xa864, 0x8007, 0x9084,
-	0x00ff, 0x0130, 0x8001, 0x1138, 0x7007, 0x0001, 0x0069, 0x0005,
-	0x080c, 0x7c28, 0x0040, 0x7007, 0x0003, 0x7012, 0x2900, 0x7016,
-	0x701a, 0x704b, 0x8024, 0x0005, 0x00b6, 0x00e6, 0x0126, 0x2091,
-	0x8000, 0x903e, 0x2061, 0x1800, 0x61d0, 0x81ff, 0x1904, 0x80a6,
-	0x6130, 0xd194, 0x1904, 0x80d0, 0xa878, 0x2070, 0x9e82, 0x1ddc,
-	0x0a04, 0x809a, 0x6068, 0x9e02, 0x1a04, 0x809a, 0x7120, 0x9186,
-	0x0006, 0x1904, 0x808c, 0x7010, 0x905d, 0x0904, 0x80a6, 0xb800,
-	0xd0e4, 0x1904, 0x80ca, 0x2061, 0x1a73, 0x6100, 0x9184, 0x0301,
-	0x9086, 0x0001, 0x15a0, 0x7024, 0xd0dc, 0x1904, 0x80d3, 0xa883,
-	0x0000, 0xa803, 0x0000, 0x2908, 0x7014, 0x9005, 0x1198, 0x7116,
-	0xa87c, 0xd0f4, 0x1904, 0x80d6, 0x080c, 0x5840, 0xd09c, 0x1118,
-	0xa87c, 0xc0cc, 0xa87e, 0x2e60, 0x080c, 0x8b34, 0x012e, 0x00ee,
-	0x00be, 0x0005, 0x2048, 0xa800, 0x9005, 0x1de0, 0xa902, 0x2148,
-	0xa87c, 0xd0f4, 0x1904, 0x80d6, 0x012e, 0x00ee, 0x00be, 0x0005,
-	0x012e, 0x00ee, 0xa883, 0x0006, 0x00be, 0x0804, 0x80f4, 0xd184,
-	0x0db8, 0xd1c4, 0x1190, 0x00a0, 0xa974, 0x080c, 0x67b4, 0x15d0,
-	0xb800, 0xd0e4, 0x15b8, 0x7120, 0x9186, 0x0007, 0x1118, 0xa883,
-	0x0002, 0x0490, 0xa883, 0x0008, 0x0478, 0xa883, 0x000e, 0x0460,
-	0xa883, 0x0017, 0x0448, 0xa883, 0x0035, 0x0430, 0x080c, 0x5844,
-	0xd0fc, 0x01e8, 0xa878, 0x2070, 0x9e82, 0x1ddc, 0x02c0, 0x6068,
-	0x9e02, 0x12a8, 0x7120, 0x9186, 0x0006, 0x1188, 0x7010, 0x905d,
-	0x0170, 0xb800, 0xd0bc, 0x0158, 0x2039, 0x0001, 0x7000, 0x9086,
-	0x0007, 0x1904, 0x8030, 0x7003, 0x0002, 0x0804, 0x8030, 0xa883,
-	0x0028, 0x0010, 0xa883, 0x0029, 0x012e, 0x00ee, 0x00be, 0x0420,
-	0xa883, 0x002a, 0x0cc8, 0xa883, 0x0045, 0x0cb0, 0x2e60, 0x2019,
-	0x0002, 0x601b, 0x0014, 0x080c, 0xe586, 0x012e, 0x00ee, 0x00be,
-	0x0005, 0x2009, 0x003e, 0x0058, 0x2009, 0x0004, 0x0040, 0x2009,
-	0x0006, 0x0028, 0x2009, 0x0016, 0x0010, 0x2009, 0x0001, 0xa884,
-	0x9084, 0xff00, 0x9105, 0xa886, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x7012, 0x012e, 0x0005, 0x080c, 0x108b, 0x0005, 0x00d6, 0x080c,
-	0x8b2b, 0x00de, 0x0005, 0x00d6, 0x00e6, 0x0126, 0x2091, 0x8000,
-	0x2071, 0x0040, 0x702c, 0xd084, 0x01d8, 0x908c, 0x0780, 0x190c,
-	0x81e5, 0xd09c, 0x11a8, 0x2071, 0x1800, 0x70c0, 0x90ea, 0x0020,
-	0x0278, 0x8001, 0x70c2, 0x702c, 0x2048, 0xa800, 0x702e, 0x9006,
-	0xa802, 0xa806, 0x2071, 0x0040, 0x2900, 0x7022, 0x702c, 0x0c28,
-	0x012e, 0x00ee, 0x00de, 0x0005, 0x0006, 0x9084, 0x0780, 0x190c,
-	0x81e5, 0x000e, 0x0005, 0xa898, 0x9084, 0x0003, 0x05a8, 0x080c,
-	0xb116, 0x05d8, 0x2900, 0x6016, 0xa864, 0x9084, 0x00ff, 0x9086,
-	0x0035, 0x1138, 0x6028, 0xc0fd, 0x602a, 0x2001, 0x196b, 0x2004,
-	0x0098, 0xa8a0, 0x9084, 0x00ff, 0xa99c, 0x918c, 0xff00, 0x9105,
-	0xa99c, 0x918c, 0x00ff, 0x080c, 0x268c, 0x1540, 0x00b6, 0x080c,
-	0x67b4, 0x2b00, 0x00be, 0x1510, 0x6012, 0x6023, 0x0001, 0x2009,
-	0x0040, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0035, 0x0110, 0x2009,
-	0x0041, 0x080c, 0xb20a, 0x0005, 0xa87b, 0x0101, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x7012, 0x012e, 0x0005, 0xa87b, 0x002c, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x0005, 0xa87b, 0x0028,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c,
-	0x0005, 0x00d6, 0x00c6, 0x0036, 0x0026, 0x0016, 0x00b6, 0x7007,
-	0x0001, 0xaa74, 0x9282, 0x0004, 0x1a04, 0x81d6, 0xa97c, 0x9188,
-	0x1000, 0x2104, 0x905d, 0xb804, 0xd284, 0x0140, 0x05e8, 0x8007,
-	0x9084, 0x00ff, 0x9084, 0x0006, 0x1108, 0x04b0, 0x2b10, 0x080c,
-	0xb116, 0x1118, 0x080c, 0xb1dd, 0x05a8, 0x6212, 0xa874, 0x0002,
-	0x81b4, 0x81b9, 0x81bc, 0x81c2, 0x2019, 0x0002, 0x080c, 0xe9f9,
-	0x0060, 0x080c, 0xe984, 0x0048, 0x2019, 0x0002, 0xa980, 0x080c,
-	0xe9a3, 0x0018, 0xa980, 0x080c, 0xe984, 0x080c, 0xb16c, 0xa887,
-	0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x00be,
-	0x001e, 0x002e, 0x003e, 0x00ce, 0x00de, 0x0005, 0xa887, 0x0006,
-	0x0c80, 0xa887, 0x0002, 0x0c68, 0xa887, 0x0005, 0x0c50, 0xa887,
-	0x0004, 0x0c38, 0xa887, 0x0007, 0x0c20, 0x2091, 0x8000, 0x0e04,
-	0x81e7, 0x0006, 0x0016, 0x2001, 0x8003, 0x0006, 0x0804, 0x0d8e,
-	0x2001, 0x1834, 0x2004, 0x9005, 0x0005, 0x0005, 0x00f6, 0x2079,
-	0x0300, 0x2001, 0x0200, 0x200c, 0xc1e5, 0xc1dc, 0x2102, 0x2009,
-	0x0218, 0x210c, 0xd1ec, 0x1120, 0x080c, 0x1648, 0x00fe, 0x0005,
-	0x2001, 0x020d, 0x2003, 0x0020, 0x781f, 0x0300, 0x00fe, 0x0005,
-	0x781c, 0xd08c, 0x0904, 0x8268, 0x68c0, 0x90aa, 0x0005, 0x0a04,
-	0x8890, 0x7d44, 0x7c40, 0xd59c, 0x190c, 0x0d85, 0x9584, 0x00f6,
-	0x1508, 0x9484, 0x7000, 0x0138, 0x908a, 0x2000, 0x1258, 0x9584,
-	0x0700, 0x8007, 0x04f0, 0x7000, 0x9084, 0xff00, 0x9086, 0x8100,
-	0x0db0, 0x00b0, 0x9484, 0x0fff, 0x1130, 0x7000, 0x9084, 0xff00,
-	0x9086, 0x8100, 0x11c0, 0x080c, 0xeeb1, 0x080c, 0x8777, 0x7817,
-	0x0140, 0x00a8, 0x9584, 0x0076, 0x1118, 0x080c, 0x87d3, 0x19c8,
-	0xd5a4, 0x0148, 0x0046, 0x0056, 0x080c, 0x82b8, 0x080c, 0x2185,
-	0x005e, 0x004e, 0x0020, 0x080c, 0xeeb1, 0x7817, 0x0140, 0x080c,
-	0x779e, 0x0168, 0x2001, 0x0111, 0x2004, 0xd08c, 0x0140, 0x6893,
-	0x0000, 0x2001, 0x0110, 0x2003, 0x0008, 0x2003, 0x0000, 0x0489,
-	0x0005, 0x0002, 0x8275, 0x8585, 0x8272, 0x8272, 0x8272, 0x8272,
-	0x8272, 0x8272, 0x7817, 0x0140, 0x0005, 0x7000, 0x908c, 0xff00,
-	0x9194, 0xf000, 0x810f, 0x9484, 0x0fff, 0x6892, 0x9286, 0x2000,
-	0x1150, 0x6800, 0x9086, 0x0001, 0x1118, 0x080c, 0x58aa, 0x0070,
-	0x080c, 0x82d8, 0x0058, 0x9286, 0x3000, 0x1118, 0x080c, 0x84bf,
-	0x0028, 0x9286, 0x8000, 0x1110, 0x080c, 0x86a4, 0x7817, 0x0140,
-	0x0005, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0178, 0x2001, 0x1800,
-	0x2004, 0x9086, 0x0003, 0x1148, 0x0026, 0x0036, 0x2011, 0x8048,
-	0x2518, 0x080c, 0x4ca1, 0x003e, 0x002e, 0x0005, 0x0036, 0x0046,
-	0x0056, 0x00f6, 0x2079, 0x0200, 0x2019, 0xfffe, 0x7c30, 0x0050,
-	0x0036, 0x0046, 0x0056, 0x00f6, 0x2079, 0x0200, 0x7d44, 0x7c40,
-	0x2019, 0xffff, 0x2001, 0x1810, 0x2004, 0xd08c, 0x0160, 0x2001,
-	0x1800, 0x2004, 0x9086, 0x0003, 0x1130, 0x0026, 0x2011, 0x8048,
-	0x080c, 0x4ca1, 0x002e, 0x00fe, 0x005e, 0x004e, 0x003e, 0x0005,
-	0x00b6, 0x00c6, 0x7010, 0x9084, 0xff00, 0x8007, 0x9096, 0x0001,
-	0x0120, 0x9096, 0x0023, 0x1904, 0x8490, 0x9186, 0x0023, 0x15c0,
-	0x080c, 0x8742, 0x0904, 0x8490, 0x6120, 0x9186, 0x0001, 0x0150,
-	0x9186, 0x0004, 0x0138, 0x9186, 0x0008, 0x0120, 0x9186, 0x000a,
-	0x1904, 0x8490, 0x7124, 0x610a, 0x7030, 0x908e, 0x0200, 0x1130,
-	0x2009, 0x0015, 0x080c, 0xb20a, 0x0804, 0x8490, 0x908e, 0x0214,
-	0x0118, 0x908e, 0x0210, 0x1130, 0x2009, 0x0015, 0x080c, 0xb20a,
-	0x0804, 0x8490, 0x908e, 0x0100, 0x1904, 0x8490, 0x7034, 0x9005,
-	0x1904, 0x8490, 0x2009, 0x0016, 0x080c, 0xb20a, 0x0804, 0x8490,
-	0x9186, 0x0022, 0x1904, 0x8490, 0x7030, 0x908e, 0x0300, 0x1580,
-	0x68dc, 0xd0a4, 0x0528, 0xc0b5, 0x68de, 0x7100, 0x918c, 0x00ff,
-	0x697e, 0x7004, 0x6882, 0x00f6, 0x2079, 0x0100, 0x79e6, 0x78ea,
-	0x0006, 0x9084, 0x00ff, 0x0016, 0x2008, 0x080c, 0x26d5, 0x7932,
-	0x7936, 0x001e, 0x000e, 0x00fe, 0x080c, 0x268c, 0x695e, 0x703c,
-	0x00e6, 0x2071, 0x0140, 0x7086, 0x2071, 0x1800, 0x70b6, 0x00ee,
-	0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x0017, 0x0804, 0x8440,
-	0x908e, 0x0400, 0x1190, 0x7034, 0x9005, 0x1904, 0x8490, 0x080c,
-	0x779e, 0x0120, 0x2009, 0x001d, 0x0804, 0x8440, 0x68dc, 0xc0a5,
-	0x68de, 0x2009, 0x0030, 0x0804, 0x8440, 0x908e, 0x0500, 0x1140,
-	0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x0018, 0x0804, 0x8440,
-	0x908e, 0x2010, 0x1120, 0x2009, 0x0019, 0x0804, 0x8440, 0x908e,
-	0x2110, 0x1120, 0x2009, 0x001a, 0x0804, 0x8440, 0x908e, 0x5200,
-	0x1140, 0x7034, 0x9005, 0x1904, 0x8490, 0x2009, 0x001b, 0x0804,
-	0x8440, 0x908e, 0x5000, 0x1140, 0x7034, 0x9005, 0x1904, 0x8490,
-	0x2009, 0x001c, 0x0804, 0x8440, 0x908e, 0x1300, 0x1120, 0x2009,
-	0x0034, 0x0804, 0x8440, 0x908e, 0x1200, 0x1140, 0x7034, 0x9005,
-	0x1904, 0x8490, 0x2009, 0x0024, 0x0804, 0x8440, 0x908c, 0xff00,
-	0x918e, 0x2400, 0x1170, 0x2009, 0x002d, 0x2001, 0x1810, 0x2004,
-	0xd09c, 0x0904, 0x8440, 0x080c, 0xdd8d, 0x1904, 0x8490, 0x0804,
-	0x843e, 0x908c, 0xff00, 0x918e, 0x5300, 0x1120, 0x2009, 0x002a,
-	0x0804, 0x8440, 0x908e, 0x0f00, 0x1120, 0x2009, 0x0020, 0x0804,
-	0x8440, 0x908e, 0x6104, 0x1530, 0x2029, 0x0205, 0x2011, 0x026d,
-	0x8208, 0x2204, 0x9082, 0x0004, 0x8004, 0x8004, 0x20a8, 0x2011,
-	0x8015, 0x211c, 0x8108, 0x0046, 0x2124, 0x080c, 0x4ca1, 0x004e,
-	0x8108, 0x0f04, 0x83f4, 0x9186, 0x0280, 0x1d88, 0x2504, 0x8000,
-	0x202a, 0x2009, 0x0260, 0x0c58, 0x202b, 0x0000, 0x2009, 0x0023,
-	0x0804, 0x8440, 0x908e, 0x6000, 0x1120, 0x2009, 0x003f, 0x0804,
-	0x8440, 0x908e, 0x5400, 0x1138, 0x080c, 0x8840, 0x1904, 0x8490,
-	0x2009, 0x0046, 0x04a8, 0x908e, 0x5500, 0x1148, 0x080c, 0x8868,
-	0x1118, 0x2009, 0x0041, 0x0460, 0x2009, 0x0042, 0x0448, 0x908e,
-	0x7800, 0x1118, 0x2009, 0x0045, 0x0418, 0x908e, 0x1000, 0x1118,
-	0x2009, 0x004e, 0x00e8, 0x908e, 0x6300, 0x1118, 0x2009, 0x004a,
-	0x00b8, 0x908c, 0xff00, 0x918e, 0x5600, 0x1118, 0x2009, 0x004f,
-	0x0078, 0x908c, 0xff00, 0x918e, 0x5700, 0x1118, 0x2009, 0x0050,
-	0x0038, 0x2009, 0x001d, 0x6838, 0xd0d4, 0x0110, 0x2009, 0x004c,
-	0x0016, 0x2011, 0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x268c,
-	0x1904, 0x8493, 0x080c, 0x6749, 0x1904, 0x8493, 0xbe12, 0xbd16,
-	0x001e, 0x0016, 0x080c, 0x779e, 0x01c0, 0x68dc, 0xd08c, 0x1148,
-	0x7000, 0x9084, 0x00ff, 0x1188, 0x7004, 0x9084, 0xff00, 0x1168,
-	0x0040, 0x687c, 0x9606, 0x1148, 0x6880, 0x9506, 0x9084, 0xff00,
-	0x1120, 0x9584, 0x00ff, 0xb886, 0x0080, 0xb884, 0x9005, 0x1168,
-	0x9186, 0x0046, 0x1150, 0x687c, 0x9606, 0x1138, 0x6880, 0x9506,
-	0x9084, 0xff00, 0x1110, 0x001e, 0x0098, 0x080c, 0xb116, 0x01a8,
-	0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e, 0x9186,
-	0x004c, 0x1110, 0x6023, 0x000a, 0x0016, 0x001e, 0x080c, 0xb20a,
-	0x00ce, 0x00be, 0x0005, 0x001e, 0x0cd8, 0x2001, 0x180e, 0x2004,
-	0xd0ec, 0x0120, 0x2011, 0x8049, 0x080c, 0x4ca1, 0x080c, 0xb1dd,
-	0x0d90, 0x2b08, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e,
-	0x0016, 0x9186, 0x0017, 0x0118, 0x9186, 0x0030, 0x1128, 0x6007,
-	0x0009, 0x6017, 0x2900, 0x0020, 0x6007, 0x0051, 0x6017, 0x0000,
-	0x602f, 0x0009, 0x6003, 0x0001, 0x080c, 0x961e, 0x08a0, 0x080c,
-	0x88af, 0x1158, 0x080c, 0x344c, 0x1140, 0x7010, 0x9084, 0xff00,
-	0x8007, 0x908e, 0x0008, 0x1108, 0x0009, 0x0005, 0x00b6, 0x00c6,
-	0x0046, 0x7000, 0x908c, 0xff00, 0x810f, 0x9186, 0x0033, 0x11e8,
-	0x080c, 0x8742, 0x0904, 0x851d, 0x7124, 0x610a, 0x7030, 0x908e,
-	0x0200, 0x1140, 0x7034, 0x9005, 0x15c0, 0x2009, 0x0015, 0x080c,
-	0xb20a, 0x0498, 0x908e, 0x0100, 0x1580, 0x7034, 0x9005, 0x1568,
-	0x2009, 0x0016, 0x080c, 0xb20a, 0x0440, 0x9186, 0x0032, 0x1528,
-	0x7030, 0x908e, 0x1400, 0x1508, 0x2009, 0x0038, 0x0016, 0x2011,
-	0x0263, 0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x11a8, 0x080c,
-	0x6749, 0x1190, 0xbe12, 0xbd16, 0x080c, 0xb116, 0x0168, 0x2b08,
-	0x6112, 0x080c, 0xd3b6, 0x6023, 0x0004, 0x7120, 0x610a, 0x001e,
-	0x080c, 0xb20a, 0x0010, 0x00ce, 0x001e, 0x004e, 0x00ce, 0x00be,
-	0x0005, 0x00b6, 0x0046, 0x00e6, 0x00d6, 0x2028, 0x2130, 0x9696,
-	0x00ff, 0x11b8, 0x9592, 0xfffc, 0x02a0, 0x9596, 0xfffd, 0x1120,
-	0x2009, 0x007f, 0x0804, 0x857f, 0x9596, 0xfffe, 0x1120, 0x2009,
-	0x007e, 0x0804, 0x857f, 0x9596, 0xfffc, 0x1118, 0x2009, 0x0080,
-	0x04f0, 0x2011, 0x0000, 0x2019, 0x1837, 0x231c, 0xd3ac, 0x0130,
-	0x9026, 0x20a9, 0x0800, 0x2071, 0x1000, 0x0030, 0x2021, 0x0081,
-	0x20a9, 0x077f, 0x2071, 0x1081, 0x2e1c, 0x93dd, 0x0000, 0x1140,
-	0x82ff, 0x11d0, 0x9496, 0x00ff, 0x01b8, 0x2410, 0xc2fd, 0x00a0,
-	0xbf10, 0x2600, 0x9706, 0xb814, 0x1120, 0x9546, 0x1110, 0x2408,
-	0x00b0, 0x9745, 0x1148, 0x94c6, 0x007e, 0x0130, 0x94c6, 0x007f,
-	0x0118, 0x94c6, 0x0080, 0x1d20, 0x8420, 0x8e70, 0x1f04, 0x8554,
-	0x82ff, 0x1118, 0x9085, 0x0001, 0x0018, 0xc2fc, 0x2208, 0x9006,
-	0x00de, 0x00ee, 0x004e, 0x00be, 0x0005, 0x2001, 0x1837, 0x200c,
-	0x9184, 0x0080, 0x0110, 0xd18c, 0x0138, 0x7000, 0x908c, 0xff00,
-	0x810f, 0x9184, 0x000f, 0x001a, 0x7817, 0x0140, 0x0005, 0x85a7,
-	0x85a7, 0x85a7, 0x8754, 0x85a7, 0x85aa, 0x85cf, 0x8658, 0x85a7,
-	0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x85a7, 0x7817,
-	0x0140, 0x0005, 0x00b6, 0x7110, 0xd1bc, 0x01e8, 0x7120, 0x2160,
-	0x9c8c, 0x0003, 0x11c0, 0x9c8a, 0x1ddc, 0x02a8, 0x6868, 0x9c02,
-	0x1290, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158, 0xb910, 0x9106,
-	0x1150, 0x700c, 0xb914, 0x9106, 0x1130, 0x7124, 0x610a, 0x2009,
-	0x0046, 0x080c, 0xb20a, 0x7817, 0x0140, 0x00be, 0x0005, 0x00b6,
-	0x00c6, 0x9484, 0x0fff, 0x0904, 0x8634, 0x7110, 0xd1bc, 0x1904,
-	0x8634, 0x7108, 0x700c, 0x2028, 0x918c, 0x00ff, 0x2130, 0x9094,
-	0xff00, 0x15c8, 0x81ff, 0x15b8, 0x9080, 0x348e, 0x200d, 0x918c,
-	0xff00, 0x810f, 0x2001, 0x0080, 0x9106, 0x0904, 0x8634, 0x9182,
-	0x0801, 0x1a04, 0x8634, 0x9190, 0x1000, 0x2204, 0x905d, 0x05e0,
-	0xbe12, 0xbd16, 0xb800, 0xd0ec, 0x15b8, 0xba04, 0x9294, 0xff00,
-	0x9286, 0x0600, 0x1190, 0x080c, 0xb116, 0x0598, 0x2b08, 0x7028,
-	0x604e, 0x702c, 0x6052, 0x6112, 0x6023, 0x0006, 0x7120, 0x610a,
-	0x7130, 0x615e, 0x080c, 0xe009, 0x00f8, 0x080c, 0x6c11, 0x1138,
-	0xb807, 0x0606, 0x0c40, 0x190c, 0x8521, 0x11b0, 0x0880, 0x080c,
-	0xb116, 0x2b08, 0x0188, 0x6112, 0x6023, 0x0004, 0x7120, 0x610a,
-	0x9286, 0x0400, 0x1118, 0x6007, 0x0005, 0x0010, 0x6007, 0x0001,
-	0x6003, 0x0001, 0x080c, 0x961e, 0x7817, 0x0140, 0x00ce, 0x00be,
-	0x0005, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120, 0x2011, 0x8049,
-	0x080c, 0x4ca1, 0x080c, 0xb1dd, 0x0d78, 0x2b08, 0x6112, 0x6023,
-	0x0006, 0x7120, 0x610a, 0x7130, 0x615e, 0x6017, 0xf300, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x08e0,
-	0x00b6, 0x7110, 0xd1bc, 0x05d0, 0x7020, 0x2060, 0x9c84, 0x0003,
-	0x15a8, 0x9c82, 0x1ddc, 0x0690, 0x6868, 0x9c02, 0x1678, 0x9484,
-	0x0fff, 0x9082, 0x000c, 0x0650, 0x7008, 0x9084, 0x00ff, 0x6110,
-	0x2158, 0xb910, 0x9106, 0x1510, 0x700c, 0xb914, 0x9106, 0x11f0,
-	0x7124, 0x610a, 0x601c, 0xd0fc, 0x11c8, 0x2001, 0x0271, 0x2004,
-	0x9005, 0x1180, 0x9484, 0x0fff, 0x9082, 0x000c, 0x0158, 0x0066,
-	0x2031, 0x0100, 0xa001, 0xa001, 0x8631, 0x1de0, 0x006e, 0x601c,
-	0xd0fc, 0x1120, 0x2009, 0x0045, 0x080c, 0xb20a, 0x7817, 0x0140,
-	0x00be, 0x0005, 0x6120, 0x9186, 0x0002, 0x0128, 0x9186, 0x0005,
-	0x0110, 0x9085, 0x0001, 0x0005, 0x080c, 0x88af, 0x1180, 0x080c,
-	0x344c, 0x1168, 0x7010, 0x9084, 0xff00, 0x8007, 0x9086, 0x0000,
-	0x1130, 0x9184, 0x000f, 0x908a, 0x0006, 0x1208, 0x000b, 0x0005,
-	0x86be, 0x86bf, 0x86be, 0x86be, 0x8724, 0x8733, 0x0005, 0x00b6,
-	0x700c, 0x7108, 0x080c, 0x268c, 0x1904, 0x8722, 0x080c, 0x6749,
-	0x1904, 0x8722, 0xbe12, 0xbd16, 0x7110, 0xd1bc, 0x0540, 0x702c,
-	0xd084, 0x1120, 0xb800, 0xd0bc, 0x1904, 0x8722, 0x080c, 0x6c11,
-	0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6c19, 0x0118, 0x9086,
-	0x0004, 0x1588, 0x00c6, 0x080c, 0x8742, 0x00ce, 0x05d8, 0x080c,
-	0xb116, 0x2b08, 0x05b8, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0002,
-	0x7120, 0x610a, 0x2009, 0x0088, 0x080c, 0xb20a, 0x0458, 0x080c,
-	0x6c11, 0x0148, 0x9086, 0x0004, 0x0130, 0x080c, 0x6c19, 0x0118,
-	0x9086, 0x0004, 0x1180, 0x080c, 0xb116, 0x2b08, 0x01d8, 0x6112,
-	0x080c, 0xd3b6, 0x6023, 0x0005, 0x7120, 0x610a, 0x2009, 0x0088,
-	0x080c, 0xb20a, 0x0078, 0x080c, 0xb116, 0x2b08, 0x0158, 0x6112,
-	0x080c, 0xd3b6, 0x6023, 0x0004, 0x7120, 0x610a, 0x2009, 0x0001,
-	0x080c, 0xb20a, 0x00be, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x00d1,
-	0x0148, 0x080c, 0x869a, 0x1130, 0x7124, 0x610a, 0x2009, 0x0089,
-	0x080c, 0xb20a, 0x0005, 0x7110, 0xd1bc, 0x0158, 0x0059, 0x0148,
-	0x080c, 0x869a, 0x1130, 0x7124, 0x610a, 0x2009, 0x008a, 0x080c,
-	0xb20a, 0x0005, 0x7020, 0x2060, 0x9c84, 0x0003, 0x1158, 0x9c82,
-	0x1ddc, 0x0240, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1218, 0x9085,
-	0x0001, 0x0005, 0x9006, 0x0ce8, 0x00b6, 0x7110, 0xd1bc, 0x11d8,
-	0x7024, 0x2060, 0x9c84, 0x0003, 0x11b0, 0x9c82, 0x1ddc, 0x0298,
-	0x6868, 0x9c02, 0x1280, 0x7008, 0x9084, 0x00ff, 0x6110, 0x2158,
-	0xb910, 0x9106, 0x1140, 0x700c, 0xb914, 0x9106, 0x1120, 0x2009,
-	0x0051, 0x080c, 0xb20a, 0x7817, 0x0140, 0x00be, 0x0005, 0x2031,
-	0x0105, 0x0069, 0x0005, 0x2031, 0x0206, 0x0049, 0x0005, 0x2031,
-	0x0207, 0x0029, 0x0005, 0x2031, 0x0213, 0x0009, 0x0005, 0x00c6,
-	0x0096, 0x00f6, 0x7000, 0x9084, 0xf000, 0x9086, 0xc000, 0x05c0,
-	0x080c, 0xb116, 0x05a8, 0x0066, 0x00c6, 0x0046, 0x2011, 0x0263,
-	0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x1590, 0x080c, 0x6749,
-	0x1578, 0xbe12, 0xbd16, 0x2b00, 0x004e, 0x00ce, 0x6012, 0x080c,
-	0xd3b6, 0x080c, 0x1059, 0x0500, 0x2900, 0x6062, 0x9006, 0xa802,
-	0xa866, 0xac6a, 0xa85c, 0x90f8, 0x001b, 0x20a9, 0x000e, 0xa860,
-	0x20e8, 0x20e1, 0x0000, 0x2fa0, 0x2e98, 0x4003, 0x006e, 0x6616,
-	0x6007, 0x003e, 0x6023, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e,
-	0x00fe, 0x009e, 0x00ce, 0x0005, 0x080c, 0xb16c, 0x006e, 0x0cc0,
-	0x004e, 0x00ce, 0x0cc8, 0x00c6, 0x7000, 0x908c, 0xff00, 0x9184,
-	0xf000, 0x810f, 0x9086, 0x2000, 0x1904, 0x882a, 0x9186, 0x0022,
-	0x15f0, 0x2001, 0x0111, 0x2004, 0x9005, 0x1904, 0x882c, 0x7030,
-	0x908e, 0x0400, 0x0904, 0x882c, 0x908e, 0x6000, 0x05e8, 0x908e,
-	0x5400, 0x05d0, 0x908e, 0x0300, 0x11d8, 0x2009, 0x1837, 0x210c,
-	0xd18c, 0x1590, 0xd1a4, 0x1580, 0x080c, 0x6bcf, 0x0588, 0x68b0,
-	0x9084, 0x00ff, 0x7100, 0x918c, 0x00ff, 0x9106, 0x1518, 0x6880,
-	0x69b0, 0x918c, 0xff00, 0x9105, 0x7104, 0x9106, 0x11d8, 0x00e0,
-	0x2009, 0x0103, 0x210c, 0xd1b4, 0x11a8, 0x908e, 0x5200, 0x09e8,
-	0x908e, 0x0500, 0x09d0, 0x908e, 0x5000, 0x09b8, 0x0058, 0x9186,
-	0x0023, 0x1140, 0x080c, 0x8742, 0x0128, 0x6004, 0x9086, 0x0002,
-	0x0118, 0x0000, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ce, 0x0005,
-	0x7030, 0x908e, 0x0300, 0x0118, 0x908e, 0x5200, 0x1d98, 0x2001,
-	0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x0d68, 0x0c50,
-	0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4,
-	0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011,
-	0x027a, 0x080c, 0xc20e, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004,
-	0x2019, 0x1801, 0x2011, 0x027e, 0x080c, 0xc20e, 0x1120, 0xd494,
-	0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, 0x0005,
-	0x0156, 0x0046, 0x0016, 0x0036, 0x7038, 0x2020, 0x8427, 0x94a4,
-	0x0007, 0xd484, 0x0148, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011,
-	0x0272, 0x080c, 0xc20e, 0x1178, 0xd48c, 0x0148, 0x20a9, 0x0004,
-	0x2019, 0x1801, 0x2011, 0x0276, 0x080c, 0xc20e, 0x1120, 0xd494,
-	0x0110, 0x9085, 0x0001, 0x003e, 0x001e, 0x004e, 0x015e, 0x0005,
-	0x00f6, 0x2079, 0x0200, 0x7800, 0xc0e5, 0xc0cc, 0x7802, 0x00fe,
-	0x0005, 0x00f6, 0x2079, 0x1800, 0x7834, 0xd084, 0x1130, 0x2079,
-	0x0200, 0x7800, 0x9085, 0x1200, 0x7802, 0x00fe, 0x0005, 0x00e6,
-	0x2071, 0x1800, 0x7034, 0xc084, 0x7036, 0x00ee, 0x0005, 0x0016,
-	0x2001, 0x1837, 0x200c, 0x9184, 0x0080, 0x0118, 0xd18c, 0x0118,
-	0x9006, 0x001e, 0x0005, 0x9085, 0x0001, 0x0cd8, 0x2071, 0x1a04,
-	0x7003, 0x0003, 0x700f, 0x0361, 0x9006, 0x701a, 0x707a, 0x7012,
-	0x7017, 0x1ddc, 0x7007, 0x0000, 0x7026, 0x702b, 0xa2c0, 0x7032,
-	0x7037, 0xa33d, 0x7047, 0xffff, 0x704a, 0x704f, 0x56c4, 0x7052,
-	0x7063, 0x8a66, 0x080c, 0x1072, 0x090c, 0x0d85, 0x2900, 0x7042,
-	0xa867, 0x0003, 0xa86f, 0x0100, 0xa8ab, 0xdcb0, 0x0005, 0x2071,
-	0x1a04, 0x1d04, 0x8982, 0x2091, 0x6000, 0x700c, 0x8001, 0x700e,
-	0x1590, 0x2001, 0x013c, 0x2004, 0x9005, 0x190c, 0x8b10, 0x2001,
-	0x1869, 0x2004, 0xd0c4, 0x0158, 0x3a00, 0xd08c, 0x1140, 0x20d1,
-	0x0000, 0x20d1, 0x0001, 0x20d1, 0x0000, 0x080c, 0x0d85, 0x700f,
-	0x0361, 0x7007, 0x0001, 0x0126, 0x2091, 0x8000, 0x2069, 0x1800,
-	0x69ec, 0xd1e4, 0x1138, 0xd1dc, 0x1118, 0x080c, 0x8ad4, 0x0010,
-	0x080c, 0x8aab, 0x7048, 0x900d, 0x0148, 0x8109, 0x714a, 0x1130,
-	0x704c, 0x080f, 0x0018, 0x0126, 0x2091, 0x8000, 0x7024, 0x900d,
-	0x0188, 0x7020, 0x8001, 0x7022, 0x1168, 0x7023, 0x0009, 0x8109,
-	0x7126, 0x9186, 0x03e8, 0x1110, 0x7028, 0x080f, 0x81ff, 0x1110,
-	0x7028, 0x080f, 0x7030, 0x900d, 0x0180, 0x702c, 0x8001, 0x702e,
-	0x1160, 0x702f, 0x0009, 0x8109, 0x7132, 0x0128, 0x9184, 0x007f,
-	0x090c, 0xa3eb, 0x0010, 0x7034, 0x080f, 0x7044, 0x9005, 0x0118,
-	0x0310, 0x8001, 0x7046, 0x7054, 0x900d, 0x0168, 0x7050, 0x8001,
-	0x7052, 0x1148, 0x7053, 0x0009, 0x8109, 0x7156, 0x1120, 0x7158,
-	0x7156, 0x7060, 0x080f, 0x7018, 0x900d, 0x01d8, 0x0016, 0x7078,
-	0x900d, 0x0158, 0x7074, 0x8001, 0x7076, 0x1138, 0x7077, 0x0009,
-	0x8109, 0x717a, 0x1110, 0x707c, 0x080f, 0x001e, 0x7008, 0x8001,
-	0x700a, 0x1138, 0x700b, 0x0009, 0x8109, 0x711a, 0x1110, 0x701c,
-	0x080f, 0x012e, 0x7004, 0x0002, 0x89aa, 0x89ab, 0x89d5, 0x00e6,
-	0x2071, 0x1a04, 0x7018, 0x9005, 0x1120, 0x711a, 0x721e, 0x700b,
-	0x0009, 0x00ee, 0x0005, 0x00e6, 0x0006, 0x2071, 0x1a04, 0x701c,
-	0x9206, 0x1120, 0x701a, 0x701e, 0x707a, 0x707e, 0x000e, 0x00ee,
-	0x0005, 0x00e6, 0x2071, 0x1a04, 0xb888, 0x9102, 0x0208, 0xb98a,
-	0x00ee, 0x0005, 0x0005, 0x00b6, 0x2031, 0x0010, 0x7110, 0x080c,
-	0x67b4, 0x11a8, 0xb888, 0x8001, 0x0290, 0xb88a, 0x1180, 0x0126,
-	0x2091, 0x8000, 0x0066, 0xb8d0, 0x9005, 0x0138, 0x0026, 0xba3c,
-	0x0016, 0x080c, 0x68df, 0x001e, 0x002e, 0x006e, 0x012e, 0x8108,
-	0x9182, 0x0800, 0x1220, 0x8631, 0x0128, 0x7112, 0x0c00, 0x900e,
-	0x7007, 0x0002, 0x7112, 0x00be, 0x0005, 0x2031, 0x0010, 0x7014,
-	0x2060, 0x0126, 0x2091, 0x8000, 0x6048, 0x9005, 0x0128, 0x8001,
-	0x604a, 0x1110, 0x080c, 0xd237, 0x6018, 0x9005, 0x0904, 0x8a2d,
-	0x00f6, 0x2079, 0x0300, 0x7918, 0xd1b4, 0x1904, 0x8a40, 0x781b,
-	0x2020, 0xa001, 0x7918, 0xd1b4, 0x0120, 0x781b, 0x2000, 0x0804,
-	0x8a40, 0x8001, 0x601a, 0x0106, 0x781b, 0x2000, 0xa001, 0x7918,
-	0xd1ac, 0x1dd0, 0x010e, 0x00fe, 0x1540, 0x6120, 0x9186, 0x0003,
-	0x0148, 0x9186, 0x0006, 0x0130, 0x9186, 0x0009, 0x11e0, 0x611c,
-	0xd1c4, 0x1100, 0x080c, 0xcf1b, 0x01b0, 0x6014, 0x2048, 0xa884,
-	0x908a, 0x199a, 0x0280, 0x9082, 0x1999, 0xa886, 0x908a, 0x199a,
-	0x0210, 0x2001, 0x1999, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a,
-	0x080c, 0xd671, 0x0110, 0x080c, 0xcbd9, 0x012e, 0x9c88, 0x001c,
-	0x7116, 0x2001, 0x181a, 0x2004, 0x9102, 0x1228, 0x8631, 0x0138,
-	0x2160, 0x0804, 0x89d9, 0x7017, 0x1ddc, 0x7007, 0x0000, 0x0005,
-	0x00fe, 0x0c58, 0x00e6, 0x2071, 0x1a04, 0x7027, 0x07d0, 0x7023,
-	0x0009, 0x00ee, 0x0005, 0x2001, 0x1a0d, 0x2003, 0x0000, 0x0005,
-	0x00e6, 0x2071, 0x1a04, 0x7132, 0x702f, 0x0009, 0x00ee, 0x0005,
-	0x2011, 0x1a10, 0x2013, 0x0000, 0x0005, 0x00e6, 0x2071, 0x1a04,
-	0x711a, 0x721e, 0x700b, 0x0009, 0x00ee, 0x0005, 0x0086, 0x0026,
-	0x705c, 0x8000, 0x705e, 0x2001, 0x1a14, 0x2044, 0xa06c, 0x9086,
-	0x0000, 0x0150, 0x7070, 0xa09a, 0x706c, 0xa096, 0x7068, 0xa092,
-	0x7064, 0xa08e, 0x080c, 0x114e, 0x002e, 0x008e, 0x0005, 0x0006,
-	0x0016, 0x0096, 0x00a6, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6,
-	0x0156, 0x080c, 0x88e7, 0x015e, 0x00fe, 0x00ee, 0x00de, 0x00ce,
-	0x00be, 0x00ae, 0x009e, 0x001e, 0x000e, 0x0005, 0x00e6, 0x2071,
-	0x1a04, 0x717a, 0x727e, 0x7077, 0x0009, 0x00ee, 0x0005, 0x00e6,
-	0x0006, 0x2071, 0x1a04, 0x707c, 0x9206, 0x1110, 0x707a, 0x707e,
-	0x000e, 0x00ee, 0x0005, 0x2069, 0x1800, 0x69ec, 0xd1e4, 0x1518,
-	0x0026, 0xd1ec, 0x0140, 0x6a54, 0x6874, 0x9202, 0x0288, 0x8117,
-	0x9294, 0x00c1, 0x0088, 0x9184, 0x0007, 0x01a0, 0x8109, 0x9184,
-	0x0007, 0x0110, 0x69ee, 0x0070, 0x8107, 0x9084, 0x0007, 0x910d,
-	0x8107, 0x9106, 0x9094, 0x00c1, 0x9184, 0xff3e, 0x9205, 0x68ee,
-	0x080c, 0x0f24, 0x002e, 0x0005, 0x69e8, 0x9184, 0x003f, 0x05b8,
-	0x8109, 0x9184, 0x003f, 0x01a8, 0x6a54, 0x6874, 0x9202, 0x0220,
-	0xd1bc, 0x0168, 0xc1bc, 0x0018, 0xd1bc, 0x1148, 0xc1bd, 0x2110,
-	0x00e6, 0x2071, 0x1800, 0x080c, 0x0f46, 0x00ee, 0x0400, 0x69ea,
-	0x00f0, 0x0026, 0x8107, 0x9094, 0x0007, 0x0128, 0x8001, 0x8007,
-	0x9085, 0x0007, 0x0050, 0x2010, 0x8004, 0x8004, 0x8004, 0x9084,
-	0x0007, 0x9205, 0x8007, 0x9085, 0x0028, 0x9086, 0x0040, 0x2010,
-	0x00e6, 0x2071, 0x1800, 0x080c, 0x0f46, 0x00ee, 0x002e, 0x0005,
-	0x0016, 0x00c6, 0x2009, 0xfff4, 0x210d, 0x2061, 0x0100, 0x60f0,
-	0x9100, 0x60f3, 0x0000, 0x2009, 0xfff4, 0x200f, 0x1220, 0x8108,
-	0x2105, 0x8000, 0x200f, 0x00ce, 0x001e, 0x0005, 0x00c6, 0x2061,
-	0x1a73, 0x00ce, 0x0005, 0x9184, 0x000f, 0x8003, 0x8003, 0x8003,
-	0x9080, 0x1a73, 0x2060, 0x0005, 0xa884, 0x908a, 0x199a, 0x1638,
-	0x9005, 0x1150, 0x00c6, 0x2061, 0x1a73, 0x6014, 0x00ce, 0x9005,
-	0x1130, 0x2001, 0x001e, 0x0018, 0x908e, 0xffff, 0x01b0, 0x8003,
-	0x800b, 0x810b, 0x9108, 0x611a, 0xa87c, 0x908c, 0x00c0, 0x918e,
-	0x00c0, 0x0904, 0x8bee, 0xd0b4, 0x1168, 0xd0bc, 0x1904, 0x8bc7,
-	0x2009, 0x0006, 0x080c, 0x8c1b, 0x0005, 0x900e, 0x0c60, 0x2001,
-	0x1999, 0x08b0, 0xd0fc, 0x05e0, 0x908c, 0x2023, 0x1568, 0x87ff,
-	0x1558, 0xa9a8, 0x81ff, 0x1540, 0x6124, 0x918c, 0x0500, 0x1520,
-	0x6100, 0x918e, 0x0007, 0x1500, 0x2009, 0x1869, 0x210c, 0xd184,
-	0x11d8, 0x6003, 0x0003, 0x6007, 0x0043, 0x6047, 0xb035, 0x080c,
-	0x1c6f, 0xa87c, 0xc0dd, 0xa87e, 0x600f, 0x0000, 0x00f6, 0x2079,
-	0x0380, 0x7818, 0xd0bc, 0x1de8, 0x7833, 0x0013, 0x2c00, 0x7836,
-	0x781b, 0x8080, 0x00fe, 0x0005, 0x908c, 0x0003, 0x0120, 0x918e,
-	0x0003, 0x1904, 0x8c15, 0x908c, 0x2020, 0x918e, 0x2020, 0x01a8,
-	0x6024, 0xd0d4, 0x11e8, 0x2009, 0x1869, 0x2104, 0xd084, 0x1138,
-	0x87ff, 0x1120, 0x2009, 0x0043, 0x0804, 0xb20a, 0x0005, 0x87ff,
-	0x1de8, 0x2009, 0x0042, 0x0804, 0xb20a, 0x6110, 0x00b6, 0x2158,
-	0xb900, 0x00be, 0xd1ac, 0x0d20, 0x6024, 0xc0cd, 0x6026, 0x0c00,
-	0xc0d4, 0x6026, 0xa890, 0x602e, 0xa88c, 0x6032, 0x08e0, 0xd0fc,
-	0x0160, 0x908c, 0x0003, 0x0120, 0x918e, 0x0003, 0x1904, 0x8c15,
-	0x908c, 0x2020, 0x918e, 0x2020, 0x0170, 0x0076, 0x00f6, 0x2c78,
-	0x080c, 0x17ad, 0x00fe, 0x007e, 0x87ff, 0x1120, 0x2009, 0x0042,
-	0x080c, 0xb20a, 0x0005, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be,
-	0xd1ac, 0x0d58, 0x6124, 0xc1cd, 0x6126, 0x0c38, 0xd0fc, 0x0188,
-	0x908c, 0x2020, 0x918e, 0x2020, 0x01a8, 0x9084, 0x0003, 0x908e,
-	0x0002, 0x0148, 0x87ff, 0x1120, 0x2009, 0x0041, 0x080c, 0xb20a,
-	0x0005, 0x00b9, 0x0ce8, 0x87ff, 0x1dd8, 0x2009, 0x0043, 0x080c,
-	0xb20a, 0x0cb0, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be, 0xd1ac,
-	0x0d20, 0x6124, 0xc1cd, 0x6126, 0x0c00, 0x2009, 0x0004, 0x0019,
-	0x0005, 0x2009, 0x0001, 0x0096, 0x080c, 0xcf1b, 0x0518, 0x6014,
-	0x2048, 0xa982, 0xa800, 0x6016, 0x9186, 0x0001, 0x1188, 0xa97c,
-	0x918c, 0x8100, 0x918e, 0x8100, 0x1158, 0x00c6, 0x2061, 0x1a73,
-	0x6200, 0xd28c, 0x1120, 0x6204, 0x8210, 0x0208, 0x6206, 0x00ce,
-	0x080c, 0x6e4c, 0x6014, 0x904d, 0x0076, 0x2039, 0x0000, 0x190c,
-	0x8b34, 0x007e, 0x009e, 0x0005, 0x0156, 0x00c6, 0x2061, 0x1a73,
-	0x6000, 0x81ff, 0x0110, 0x9205, 0x0008, 0x9204, 0x6002, 0x00ce,
-	0x015e, 0x0005, 0x6800, 0xd08c, 0x1138, 0x6808, 0x9005, 0x0120,
-	0x8001, 0x680a, 0x9085, 0x0001, 0x0005, 0x2071, 0x1924, 0x7003,
-	0x0006, 0x7007, 0x0000, 0x700f, 0x0000, 0x7013, 0x0001, 0x080c,
-	0x1072, 0x090c, 0x0d85, 0xa867, 0x0006, 0xa86b, 0x0001, 0xa8ab,
-	0xdcb0, 0xa89f, 0x0000, 0x2900, 0x702e, 0x7033, 0x0000, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x0096, 0x00e6, 0x2071, 0x1924, 0x702c,
-	0x2048, 0x6a2c, 0x721e, 0x6b30, 0x7322, 0x6834, 0x7026, 0xa896,
-	0x6838, 0x702a, 0xa89a, 0x6824, 0x7016, 0x683c, 0x701a, 0x2009,
-	0x0028, 0x200a, 0x9005, 0x0148, 0x900e, 0x9188, 0x000c, 0x8001,
-	0x1de0, 0x2100, 0x9210, 0x1208, 0x8318, 0xaa8e, 0xab92, 0x7010,
-	0xd084, 0x0168, 0xc084, 0x7007, 0x0001, 0x700f, 0x0000, 0x0006,
-	0x2009, 0x1b73, 0x2104, 0x9082, 0x0007, 0x200a, 0x000e, 0xc095,
-	0x7012, 0x2008, 0x2001, 0x003b, 0x080c, 0x16b9, 0x9006, 0x2071,
-	0x193d, 0x7002, 0x7006, 0x702a, 0x00ee, 0x009e, 0x012e, 0x0005,
-	0x2009, 0x1b73, 0x2104, 0x9080, 0x0007, 0x200a, 0x0005, 0x00e6,
-	0x0126, 0x0156, 0x2091, 0x8000, 0x2071, 0x1800, 0x7154, 0x2001,
-	0x0008, 0x910a, 0x0638, 0x2001, 0x187d, 0x20ac, 0x9006, 0x9080,
-	0x0008, 0x1f04, 0x8cd7, 0x71c0, 0x9102, 0x02e0, 0x2071, 0x1877,
-	0x20a9, 0x0007, 0x00c6, 0x080c, 0xb116, 0x6023, 0x0009, 0x6003,
-	0x0004, 0x601f, 0x0101, 0x0089, 0x0126, 0x2091, 0x8000, 0x080c,
-	0x8e58, 0x012e, 0x1f04, 0x8ce3, 0x9006, 0x00ce, 0x015e, 0x012e,
-	0x00ee, 0x0005, 0x9085, 0x0001, 0x0cc8, 0x00e6, 0x00b6, 0x0096,
-	0x0086, 0x0056, 0x0046, 0x0026, 0x7118, 0x720c, 0x7620, 0x7004,
-	0xd084, 0x1128, 0x2021, 0x0024, 0x2029, 0x0002, 0x0020, 0x2021,
-	0x002c, 0x2029, 0x000a, 0x080c, 0x1059, 0x090c, 0x0d85, 0x2900,
-	0x6016, 0x2058, 0xac66, 0x9006, 0xa802, 0xa806, 0xa86a, 0xa87a,
-	0xa8aa, 0xa887, 0x0005, 0xa87f, 0x0020, 0x7008, 0xa89a, 0x7010,
-	0xa89e, 0xae8a, 0xa8af, 0xffff, 0xa8b3, 0x0000, 0x8109, 0x0160,
-	0x080c, 0x1059, 0x090c, 0x0d85, 0xad66, 0x2b00, 0xa802, 0x2900,
-	0xb806, 0x2058, 0x8109, 0x1da0, 0x002e, 0x004e, 0x005e, 0x008e,
-	0x009e, 0x00be, 0x00ee, 0x0005, 0x2079, 0x0000, 0x2071, 0x1924,
-	0x7004, 0x004b, 0x700c, 0x0002, 0x8d4f, 0x8d48, 0x8d48, 0x0005,
-	0x8d59, 0x8daf, 0x8daf, 0x8daf, 0x8db0, 0x8dc1, 0x8dc1, 0x700c,
-	0x0cba, 0x0126, 0x2091, 0x8000, 0x78a0, 0x79a0, 0x9106, 0x1904,
-	0x8da1, 0x7814, 0xd0bc, 0x1904, 0x8daa, 0x012e, 0x7018, 0x910a,
-	0x1128, 0x7030, 0x9005, 0x1904, 0x8df3, 0x0005, 0x1210, 0x7114,
-	0x910a, 0x9192, 0x000a, 0x0210, 0x2009, 0x000a, 0x2001, 0x1888,
-	0x2014, 0x2001, 0x1936, 0x2004, 0x9100, 0x9202, 0x0e50, 0x080c,
-	0x8f53, 0x2200, 0x9102, 0x0208, 0x2208, 0x0096, 0x702c, 0x2048,
-	0xa873, 0x0001, 0xa976, 0x080c, 0x905c, 0x2100, 0xa87e, 0xa86f,
-	0x0000, 0x009e, 0x0126, 0x2091, 0x8000, 0x2009, 0x1a24, 0x2104,
-	0xc085, 0x200a, 0x700f, 0x0002, 0x012e, 0x080c, 0x116d, 0x1de8,
-	0x0005, 0x78a0, 0x79a0, 0x9106, 0x0904, 0x8d61, 0x080c, 0x8f2b,
-	0x012e, 0x0005, 0x7810, 0xc0c5, 0x7812, 0x0804, 0x8d61, 0x0005,
-	0x700c, 0x0002, 0x8db5, 0x8db8, 0x8db7, 0x080c, 0x8d57, 0x0005,
-	0x8001, 0x700e, 0x0096, 0x702c, 0x2048, 0xa974, 0x009e, 0x0011,
-	0x0ca0, 0x0005, 0x0096, 0x702c, 0x2048, 0x7018, 0x9100, 0x7214,
-	0x921a, 0x1130, 0x701c, 0xa88e, 0x7020, 0xa892, 0x9006, 0x0068,
-	0x0006, 0x080c, 0x905c, 0x2100, 0xaa8c, 0x9210, 0xaa8e, 0x1220,
-	0xa890, 0x9081, 0x0000, 0xa892, 0x000e, 0x009e, 0x0126, 0x2091,
-	0x8000, 0x78a2, 0x701a, 0x080c, 0x8f2b, 0x012e, 0x0005, 0x00e6,
-	0x2071, 0x1924, 0x700c, 0x0002, 0x8df1, 0x8df1, 0x8def, 0x700f,
-	0x0001, 0x00ee, 0x0005, 0x0126, 0x2091, 0x8000, 0x7030, 0x9005,
-	0x0508, 0x2078, 0x7814, 0x2048, 0xae88, 0x00b6, 0x2059, 0x0000,
-	0x080c, 0x8e61, 0x00be, 0x01b0, 0x00e6, 0x2071, 0x193d, 0x080c,
-	0x8ea8, 0x00ee, 0x0178, 0x0096, 0x080c, 0x1072, 0x2900, 0x009e,
-	0x0148, 0xa8aa, 0x04d1, 0x0041, 0x2001, 0x1947, 0x2003, 0x0000,
-	0x012e, 0x08c8, 0x012e, 0x0005, 0x00d6, 0x00c6, 0x0086, 0x00a6,
-	0x2940, 0x2650, 0x2600, 0x9005, 0x0180, 0xa864, 0x9084, 0x000f,
-	0x2068, 0x9d88, 0x1ec1, 0x2165, 0x0056, 0x2029, 0x0000, 0x080c,
-	0x8fe1, 0x080c, 0x1e97, 0x1dd8, 0x005e, 0x00ae, 0x2001, 0x187f,
-	0x2004, 0xa88a, 0x00c6, 0x2f60, 0x080c, 0x17ad, 0x00ce, 0x781f,
-	0x0101, 0x7813, 0x0000, 0x0126, 0x2091, 0x8000, 0x080c, 0x8eb7,
-	0x012e, 0x008e, 0x00ce, 0x00de, 0x0005, 0x7030, 0x9005, 0x0138,
-	0x2078, 0x780c, 0x7032, 0x2001, 0x1947, 0x2003, 0x0001, 0x0005,
-	0x00e6, 0x2071, 0x1924, 0x7030, 0x600e, 0x2c00, 0x7032, 0x00ee,
-	0x0005, 0x00d6, 0x00c6, 0x0026, 0x9b80, 0x912a, 0x2005, 0x906d,
-	0x090c, 0x0d85, 0x9b80, 0x9122, 0x2005, 0x9065, 0x090c, 0x0d85,
-	0x6114, 0x2600, 0x9102, 0x0248, 0x6828, 0x9102, 0x02f0, 0x9085,
-	0x0001, 0x002e, 0x00ce, 0x00de, 0x0005, 0x6804, 0xd094, 0x0148,
-	0x6854, 0xd084, 0x1178, 0xc085, 0x6856, 0x2011, 0x8026, 0x080c,
-	0x4ca1, 0x684c, 0x0096, 0x904d, 0x090c, 0x0d85, 0xa804, 0x8000,
-	0xa806, 0x009e, 0x9006, 0x2030, 0x0c20, 0x6854, 0xd08c, 0x1d08,
-	0xc08d, 0x6856, 0x2011, 0x8025, 0x080c, 0x4ca1, 0x684c, 0x0096,
-	0x904d, 0x090c, 0x0d85, 0xa800, 0x8000, 0xa802, 0x009e, 0x0888,
-	0x7000, 0x2019, 0x0008, 0x8319, 0x7104, 0x9102, 0x1118, 0x2300,
-	0x9005, 0x0020, 0x0210, 0x9302, 0x0008, 0x8002, 0x0005, 0x00d6,
-	0x7814, 0x9005, 0x090c, 0x0d85, 0x781c, 0x9084, 0x0101, 0x9086,
-	0x0101, 0x190c, 0x0d85, 0x7827, 0x0000, 0x2069, 0x193d, 0x6804,
-	0x9080, 0x193f, 0x2f08, 0x2102, 0x6904, 0x8108, 0x9182, 0x0008,
-	0x0208, 0x900e, 0x6906, 0x9180, 0x193f, 0x2003, 0x0000, 0x00de,
-	0x0005, 0x0096, 0x00c6, 0x2060, 0x6014, 0x2048, 0xa8a8, 0x0096,
-	0x2048, 0x9005, 0x190c, 0x108b, 0x009e, 0xa8ab, 0x0000, 0x080c,
-	0x100b, 0x080c, 0xb16c, 0x00ce, 0x009e, 0x0005, 0x6020, 0x9086,
-	0x0009, 0x1128, 0x601c, 0xd0c4, 0x0110, 0x9006, 0x0005, 0x9085,
-	0x0001, 0x0005, 0x6000, 0x9086, 0x0000, 0x0178, 0x6010, 0x9005,
-	0x0150, 0x00b6, 0x2058, 0x080c, 0x925e, 0x00be, 0x6013, 0x0000,
-	0x601b, 0x0000, 0x0010, 0x2c00, 0x0861, 0x0005, 0x2009, 0x1928,
-	0x210c, 0xd194, 0x0005, 0x2009, 0x1928, 0x210c, 0xd1c4, 0x0005,
-	0x0126, 0x2091, 0x8000, 0x00e6, 0x2071, 0x1924, 0x7110, 0xc194,
-	0xc185, 0x7007, 0x0000, 0x7112, 0x2001, 0x003b, 0x080c, 0x16b9,
-	0x00ee, 0x012e, 0x0005, 0x7814, 0xd0bc, 0x1108, 0x0005, 0x7810,
-	0xc0c5, 0x7812, 0x0cc0, 0x0096, 0x00d6, 0x9006, 0x7006, 0x700e,
-	0x701a, 0x701e, 0x7022, 0x7016, 0x702a, 0x7026, 0x702f, 0x0000,
-	0x080c, 0x90aa, 0x0170, 0x080c, 0x90df, 0x0158, 0x2900, 0x7002,
-	0x700a, 0x701a, 0x7013, 0x0001, 0x701f, 0x000a, 0x00de, 0x009e,
-	0x0005, 0x900e, 0x0cd8, 0x00e6, 0x0096, 0x0086, 0x00d6, 0x00c6,
-	0x2071, 0x1931, 0x721c, 0x2100, 0x9202, 0x1618, 0x080c, 0x90df,
-	0x090c, 0x0d85, 0x7018, 0x9005, 0x1160, 0x2900, 0x7002, 0x700a,
-	0x701a, 0x9006, 0x7006, 0x700e, 0xa806, 0xa802, 0x7012, 0x701e,
-	0x0038, 0x2040, 0xa806, 0x2900, 0xa002, 0x701a, 0xa803, 0x0000,
-	0x7010, 0x8000, 0x7012, 0x701c, 0x9080, 0x000a, 0x701e, 0x721c,
-	0x08d0, 0x721c, 0x00ce, 0x00de, 0x008e, 0x009e, 0x00ee, 0x0005,
-	0x0096, 0x0156, 0x0136, 0x0146, 0x00e6, 0x0126, 0x2091, 0x8000,
-	0x2071, 0x1931, 0x7300, 0x831f, 0x831e, 0x831e, 0x9384, 0x003f,
-	0x20e8, 0x939c, 0xffc0, 0x9398, 0x0003, 0x7104, 0x080c, 0x905c,
-	0x810c, 0x2100, 0x9318, 0x8003, 0x2228, 0x2021, 0x0078, 0x9402,
-	0x9532, 0x0208, 0x2028, 0x2500, 0x8004, 0x20a8, 0x23a0, 0xa001,
-	0xa001, 0x4005, 0x2508, 0x080c, 0x9065, 0x2130, 0x7014, 0x9600,
-	0x7016, 0x2600, 0x711c, 0x9102, 0x701e, 0x7004, 0x9600, 0x2008,
-	0x9082, 0x000a, 0x1190, 0x7000, 0x2048, 0xa800, 0x9005, 0x1148,
-	0x2009, 0x0001, 0x0026, 0x080c, 0x8f53, 0x002e, 0x7000, 0x2048,
-	0xa800, 0x7002, 0x7007, 0x0000, 0x0008, 0x7106, 0x2500, 0x9212,
-	0x1904, 0x8f92, 0x012e, 0x00ee, 0x014e, 0x013e, 0x015e, 0x009e,
-	0x0005, 0x0016, 0x0026, 0x00e6, 0x0126, 0x2091, 0x8000, 0x9580,
-	0x9122, 0x2005, 0x9075, 0x090c, 0x0d85, 0x080c, 0x9037, 0x012e,
-	0x9580, 0x911e, 0x2005, 0x9075, 0x090c, 0x0d85, 0x0156, 0x0136,
-	0x01c6, 0x0146, 0x01d6, 0x831f, 0x831e, 0x831e, 0x9384, 0x003f,
-	0x20e0, 0x9384, 0xffc0, 0x9100, 0x2098, 0xa860, 0x20e8, 0xa95c,
-	0x2c05, 0x9100, 0x20a0, 0x20a9, 0x0002, 0x4003, 0x2e0c, 0x2d00,
-	0x0002, 0x9021, 0x9021, 0x9023, 0x9021, 0x9023, 0x9021, 0x9021,
-	0x9021, 0x9021, 0x9021, 0x9029, 0x9021, 0x9029, 0x9021, 0x9021,
-	0x9021, 0x080c, 0x0d85, 0x4104, 0x20a9, 0x0002, 0x4002, 0x4003,
-	0x0028, 0x20a9, 0x0002, 0x4003, 0x4104, 0x4003, 0x01de, 0x014e,
-	0x01ce, 0x013e, 0x015e, 0x00ee, 0x002e, 0x001e, 0x0005, 0x0096,
-	0x7014, 0x8001, 0x7016, 0x710c, 0x2110, 0x00f1, 0x810c, 0x9188,
-	0x0003, 0x7308, 0x8210, 0x9282, 0x000a, 0x1198, 0x7008, 0x2048,
-	0xa800, 0x9005, 0x0158, 0x0006, 0x080c, 0x90ee, 0x009e, 0xa807,
-	0x0000, 0x2900, 0x700a, 0x7010, 0x8001, 0x7012, 0x700f, 0x0000,
-	0x0008, 0x720e, 0x009e, 0x0005, 0x0006, 0x810b, 0x810b, 0x2100,
-	0x810b, 0x9100, 0x2008, 0x000e, 0x0005, 0x0006, 0x0026, 0x2100,
-	0x9005, 0x0158, 0x9092, 0x000c, 0x0240, 0x900e, 0x8108, 0x9082,
-	0x000c, 0x1de0, 0x002e, 0x000e, 0x0005, 0x900e, 0x0cd8, 0x2d00,
-	0x90b8, 0x0008, 0x2031, 0x90a8, 0x901e, 0x6808, 0x9005, 0x0108,
-	0x8318, 0x690c, 0x910a, 0x0248, 0x0140, 0x8318, 0x6810, 0x9112,
-	0x0220, 0x0118, 0x8318, 0x2208, 0x0cd0, 0x233a, 0x6804, 0xd084,
-	0x2300, 0x2021, 0x0001, 0x1150, 0x9082, 0x0003, 0x0967, 0x0a67,
-	0x8420, 0x9082, 0x0007, 0x0967, 0x0a67, 0x0cd0, 0x9082, 0x0002,
-	0x0967, 0x0a67, 0x8420, 0x9082, 0x0005, 0x0967, 0x0a67, 0x0cd0,
-	0x6c1a, 0x0005, 0x0096, 0x0046, 0x0126, 0x2091, 0x8000, 0x2b00,
-	0x9080, 0x9126, 0x2005, 0x9005, 0x090c, 0x0d85, 0x2004, 0x90a0,
-	0x000a, 0x080c, 0x1072, 0x01d0, 0x2900, 0x7026, 0xa803, 0x0000,
-	0xa807, 0x0000, 0x080c, 0x1072, 0x0188, 0x7024, 0xa802, 0xa807,
-	0x0000, 0x2900, 0x7026, 0x94a2, 0x000a, 0x0110, 0x0208, 0x0c90,
-	0x9085, 0x0001, 0x012e, 0x004e, 0x009e, 0x0005, 0x7024, 0x9005,
-	0x0dc8, 0x2048, 0xac00, 0x080c, 0x108b, 0x2400, 0x0cc0, 0x0126,
-	0x2091, 0x8000, 0x7024, 0x2048, 0x9005, 0x0130, 0xa800, 0x7026,
-	0xa803, 0x0000, 0xa807, 0x0000, 0x012e, 0x0005, 0x0126, 0x2091,
-	0x8000, 0x7024, 0xa802, 0x2900, 0x7026, 0x012e, 0x0005, 0x0096,
-	0x9e80, 0x0009, 0x2004, 0x9005, 0x0138, 0x2048, 0xa800, 0x0006,
-	0x080c, 0x108b, 0x000e, 0x0cb8, 0x009e, 0x0005, 0x0096, 0x7008,
-	0x9005, 0x0138, 0x2048, 0xa800, 0x0006, 0x080c, 0x108b, 0x000e,
-	0x0cb8, 0x9006, 0x7002, 0x700a, 0x7006, 0x700e, 0x701a, 0x701e,
-	0x7022, 0x702a, 0x7026, 0x702e, 0x009e, 0x0005, 0x1a71, 0x0000,
-	0x0000, 0x0000, 0x1931, 0x0000, 0x0000, 0x0000, 0x1888, 0x0000,
-	0x0000, 0x0000, 0x1877, 0x0000, 0x0000, 0x0000, 0x00e6, 0x00c6,
-	0x00b6, 0x00a6, 0xa8a8, 0x2040, 0x2071, 0x1877, 0x080c, 0x924a,
-	0xa067, 0x0023, 0x6010, 0x905d, 0x0904, 0x921f, 0xb814, 0xa06e,
-	0xb910, 0xa172, 0xb9a0, 0xa176, 0x2001, 0x0003, 0xa07e, 0xa834,
-	0xa082, 0xa07b, 0x0000, 0xa898, 0x9005, 0x0118, 0xa078, 0xc085,
-	0xa07a, 0x2858, 0x2031, 0x0018, 0xa068, 0x908a, 0x0019, 0x1a0c,
-	0x0d85, 0x2020, 0x2050, 0x2940, 0xa864, 0x90bc, 0x00ff, 0x908c,
-	0x000f, 0x91e0, 0x1ec1, 0x2c65, 0x9786, 0x0024, 0x2c05, 0x1590,
-	0x908a, 0x0036, 0x1a0c, 0x0d85, 0x9082, 0x001b, 0x0002, 0x918a,
-	0x918a, 0x918c, 0x918a, 0x918a, 0x918a, 0x918e, 0x918a, 0x918a,
-	0x918a, 0x9190, 0x918a, 0x918a, 0x918a, 0x9192, 0x918a, 0x918a,
-	0x918a, 0x9194, 0x918a, 0x918a, 0x918a, 0x9196, 0x918a, 0x918a,
-	0x918a, 0x9198, 0x080c, 0x0d85, 0xa180, 0x04b8, 0xa190, 0x04a8,
-	0xa1a0, 0x0498, 0xa1b0, 0x0488, 0xa1c0, 0x0478, 0xa1d0, 0x0468,
-	0xa1e0, 0x0458, 0x908a, 0x0034, 0x1a0c, 0x0d85, 0x9082, 0x001b,
-	0x0002, 0x91bc, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91be,
-	0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91ba, 0x91c0, 0x91ba, 0x91ba,
-	0x91ba, 0x91ba, 0x91ba, 0x91c2, 0x91ba, 0x91ba, 0x91ba, 0x91ba,
-	0x91ba, 0x91c4, 0x080c, 0x0d85, 0xa180, 0x0038, 0xa198, 0x0028,
-	0xa1b0, 0x0018, 0xa1c8, 0x0008, 0xa1e0, 0x2600, 0x0002, 0x91e0,
-	0x91e2, 0x91e4, 0x91e6, 0x91e8, 0x91ea, 0x91ec, 0x91ee, 0x91f0,
-	0x91f2, 0x91f4, 0x91f6, 0x91f8, 0x91fa, 0x91fc, 0x91fe, 0x9200,
-	0x9202, 0x9204, 0x9206, 0x9208, 0x920a, 0x920c, 0x920e, 0x9210,
-	0x080c, 0x0d85, 0xb9e2, 0x0468, 0xb9de, 0x0458, 0xb9da, 0x0448,
-	0xb9d6, 0x0438, 0xb9d2, 0x0428, 0xb9ce, 0x0418, 0xb9ca, 0x0408,
-	0xb9c6, 0x00f8, 0xb9c2, 0x00e8, 0xb9be, 0x00d8, 0xb9ba, 0x00c8,
-	0xb9b6, 0x00b8, 0xb9b2, 0x00a8, 0xb9ae, 0x0098, 0xb9aa, 0x0088,
-	0xb9a6, 0x0078, 0xb9a2, 0x0068, 0xb99e, 0x0058, 0xb99a, 0x0048,
-	0xb996, 0x0038, 0xb992, 0x0028, 0xb98e, 0x0018, 0xb98a, 0x0008,
-	0xb986, 0x8631, 0x8421, 0x0130, 0x080c, 0x1e97, 0x090c, 0x0d85,
-	0x0804, 0x9164, 0x00ae, 0x00be, 0x00ce, 0x00ee, 0x0005, 0xa86c,
-	0xa06e, 0xa870, 0xa072, 0xa077, 0x00ff, 0x9006, 0x0804, 0x9146,
-	0x0006, 0x0016, 0x00b6, 0x6010, 0x2058, 0xb810, 0x9005, 0x01b0,
-	0x2001, 0x1925, 0x2004, 0x9005, 0x0188, 0x2001, 0x1800, 0x2004,
-	0x9086, 0x0003, 0x1158, 0x0036, 0x0046, 0xbba0, 0x2021, 0x0004,
-	0x2011, 0x8014, 0x080c, 0x4ca1, 0x004e, 0x003e, 0x00be, 0x001e,
-	0x000e, 0x0005, 0x9016, 0x710c, 0xa834, 0x910a, 0xa936, 0x7008,
-	0x9005, 0x0120, 0x8210, 0x910a, 0x0230, 0x0128, 0x7010, 0x8210,
-	0x910a, 0x0208, 0x1de0, 0xaa8a, 0xa26a, 0x0005, 0x00f6, 0x00d6,
-	0x0036, 0x2079, 0x0300, 0x781b, 0x0200, 0x7818, 0xd094, 0x1dd8,
-	0x781b, 0x0202, 0xa001, 0xa001, 0x7818, 0xd094, 0x1da0, 0xb8ac,
-	0x906d, 0x0198, 0x2079, 0x0000, 0x9c1e, 0x1118, 0x680c, 0xb8ae,
-	0x0050, 0x9c06, 0x0130, 0x2d78, 0x680c, 0x906d, 0x1dd0, 0x080c,
-	0x0d85, 0x6b0c, 0x7b0e, 0x600f, 0x0000, 0x2079, 0x0300, 0x781b,
-	0x0200, 0x003e, 0x00de, 0x00fe, 0x0005, 0x00e6, 0x00d6, 0x0096,
-	0x00c6, 0x0036, 0x0126, 0x2091, 0x8000, 0x0156, 0x20a9, 0x01ff,
-	0x2071, 0x0300, 0x701b, 0x0200, 0x7018, 0xd094, 0x0110, 0x1f04,
-	0x929a, 0x701b, 0x0202, 0xa001, 0xa001, 0x7018, 0xd094, 0x1d90,
-	0xb8ac, 0x9065, 0x01f0, 0x600c, 0xb8ae, 0x6024, 0xc08d, 0x6026,
-	0x6003, 0x0004, 0x601b, 0x0000, 0x6013, 0x0000, 0x601f, 0x0101,
-	0x6014, 0x904d, 0x090c, 0x0d85, 0xa88b, 0x0000, 0xa8a8, 0xa8ab,
-	0x0000, 0x904d, 0x090c, 0x0d85, 0x080c, 0x108b, 0x080c, 0x8e58,
-	0x08f8, 0x2071, 0x0300, 0x701b, 0x0200, 0x015e, 0x012e, 0x003e,
-	0x00ce, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x00b6, 0x0016,
-	0x0006, 0x0156, 0x080c, 0x268c, 0x015e, 0x11b0, 0x080c, 0x6749,
-	0x190c, 0x0d85, 0x000e, 0x001e, 0xb912, 0xb816, 0x080c, 0xb116,
-	0x0140, 0x2b00, 0x6012, 0x6023, 0x0001, 0x2009, 0x0001, 0x080c,
-	0xb20a, 0x00be, 0x00ce, 0x0005, 0x000e, 0x001e, 0x0cd0, 0x0066,
-	0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005,
-	0x9310, 0x9310, 0x9310, 0x9312, 0x935b, 0x9310, 0x9310, 0x9310,
-	0x93d5, 0x9310, 0x940d, 0x9310, 0x9310, 0x9310, 0x9310, 0x9310,
-	0x080c, 0x0d85, 0x9182, 0x0040, 0x0002, 0x9325, 0x9325, 0x9325,
-	0x9325, 0x9325, 0x9325, 0x9325, 0x9325, 0x9325, 0x9327, 0x9338,
-	0x9325, 0x9325, 0x9325, 0x9325, 0x9349, 0x080c, 0x0d85, 0x0096,
-	0x6114, 0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb,
-	0x0500, 0x00be, 0x080c, 0x6e11, 0x080c, 0xb16c, 0x009e, 0x0005,
-	0x080c, 0x9a48, 0x00d6, 0x6114, 0x080c, 0xcf1b, 0x0130, 0x0096,
-	0x6114, 0x2148, 0x080c, 0x7012, 0x009e, 0x00de, 0x080c, 0xb16c,
-	0x0005, 0x080c, 0x9a48, 0x080c, 0x3315, 0x6114, 0x0096, 0x2148,
-	0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0029, 0x080c, 0x7012, 0x009e,
-	0x080c, 0xb16c, 0x0005, 0x601b, 0x0000, 0x9182, 0x0040, 0x0096,
-	0x0002, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376, 0x9376,
-	0x9376, 0x9378, 0x9376, 0x9376, 0x9376, 0x93d1, 0x9376, 0x9376,
-	0x9376, 0x9376, 0x9376, 0x9376, 0x937f, 0x9376, 0x080c, 0x0d85,
-	0x6114, 0x2148, 0xa938, 0x918e, 0xffff, 0x0904, 0x93d1, 0x6024,
-	0xd08c, 0x15d8, 0x080c, 0x8f0e, 0x05e0, 0x00e6, 0x6114, 0x2148,
-	0x080c, 0x912e, 0x0096, 0xa8a8, 0x2048, 0x080c, 0x6da9, 0x009e,
-	0xa8ab, 0x0000, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c,
-	0x925e, 0x00be, 0xae88, 0x00b6, 0x2059, 0x0000, 0x080c, 0x8e61,
-	0x00be, 0x01e0, 0x2071, 0x193d, 0x080c, 0x8ea8, 0x01b8, 0x9086,
-	0x0001, 0x1128, 0x2001, 0x1947, 0x2004, 0x9005, 0x1178, 0x0096,
-	0x080c, 0x1059, 0x2900, 0x009e, 0x0148, 0xa8aa, 0x00f6, 0x2c78,
-	0x080c, 0x8e1c, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x080c, 0x8e58,
-	0x0cd0, 0x080c, 0x8f13, 0x1160, 0x6010, 0x9005, 0x0130, 0x2058,
-	0xb8ac, 0x9005, 0x190c, 0x0d85, 0x6012, 0x2c00, 0x080c, 0x8ed9,
-	0x0005, 0x080c, 0x9489, 0x009e, 0x0005, 0x9182, 0x0040, 0x0096,
-	0x0002, 0x93e9, 0x93e9, 0x93e9, 0x93eb, 0x93e9, 0x93e9, 0x93e9,
-	0x940b, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9, 0x93e9,
-	0x93e9, 0x080c, 0x0d85, 0x6003, 0x0003, 0x6106, 0x6014, 0x2048,
-	0xa8ac, 0xa836, 0xa8b0, 0xa83a, 0xa847, 0x0000, 0xa84b, 0x0000,
-	0xa884, 0x9092, 0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013,
-	0x8213, 0x9210, 0x621a, 0x080c, 0x1c26, 0x2009, 0x8030, 0x080c,
-	0x965e, 0x009e, 0x0005, 0x080c, 0x0d85, 0x080c, 0x9a48, 0x6114,
-	0x2148, 0xa87b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500,
-	0x00be, 0x080c, 0x7012, 0x080c, 0xb16c, 0x009e, 0x0005, 0x080c,
-	0xacfc, 0x6144, 0xd1fc, 0x0120, 0xd1ac, 0x1110, 0x6003, 0x0003,
-	0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x0096, 0x0023, 0x009e,
-	0x080c, 0xad18, 0x0005, 0x9443, 0x9443, 0x9443, 0x9445, 0x9456,
-	0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443, 0x9443,
-	0x9443, 0x9443, 0x9443, 0x080c, 0x0d85, 0x080c, 0xaee3, 0x6114,
-	0x2148, 0xa87b, 0x0006, 0x6010, 0x00b6, 0x2058, 0xb8bb, 0x0500,
-	0x00be, 0x080c, 0x7012, 0x080c, 0xb16c, 0x0005, 0x0491, 0x0005,
-	0x080c, 0xacfc, 0x6000, 0x6144, 0xd1fc, 0x0130, 0xd1ac, 0x1120,
-	0x6003, 0x0003, 0x2009, 0x0003, 0x908a, 0x0010, 0x1a0c, 0x0d85,
-	0x0096, 0x0033, 0x009e, 0x0106, 0x080c, 0xad18, 0x010e, 0x0005,
-	0x9480, 0x9480, 0x9480, 0x9482, 0x9489, 0x9480, 0x9480, 0x9480,
-	0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480, 0x9480,
-	0x080c, 0x0d85, 0x0036, 0x00e6, 0x080c, 0xaee3, 0x00ee, 0x003e,
-	0x0005, 0x6024, 0xd08c, 0x11f0, 0x00f6, 0x00e6, 0x601b, 0x0000,
-	0x6014, 0x2048, 0x6010, 0x9005, 0x0128, 0x00b6, 0x2058, 0x080c,
-	0x925e, 0x00be, 0x2071, 0x193d, 0x080c, 0x8ea8, 0x0160, 0x2001,
-	0x187f, 0x2004, 0xa88a, 0x2031, 0x0000, 0x2c78, 0x080c, 0x8e1c,
-	0x00ee, 0x00fe, 0x0005, 0x0096, 0xa88b, 0x0000, 0xa8a8, 0x2048,
-	0x080c, 0x108b, 0x009e, 0xa8ab, 0x0000, 0x080c, 0x8e58, 0x0c80,
-	0x2001, 0x1925, 0x200c, 0x918e, 0x0000, 0x190c, 0x8f0e, 0x05c8,
-	0x00e6, 0x2071, 0x1924, 0x7110, 0xc1c5, 0x7112, 0x080c, 0x8f18,
-	0x00f6, 0x00c6, 0x2071, 0x1000, 0x00b6, 0x2e04, 0x905d, 0x0138,
-	0xb8ac, 0x9065, 0x0120, 0x080c, 0x8eee, 0x090c, 0x928d, 0x8e70,
-	0x9e86, 0x1800, 0x1d90, 0x00be, 0x00d6, 0x0096, 0x0046, 0x2061,
-	0x1ddc, 0x2001, 0x181a, 0x2024, 0x6020, 0x9086, 0x0000, 0x1191,
-	0x9ce0, 0x001c, 0x2400, 0x9c06, 0x1db8, 0x004e, 0x009e, 0x00de,
-	0x00d1, 0x00ce, 0x00fe, 0x2071, 0x1924, 0x7110, 0xc1c4, 0x7112,
-	0x00ee, 0x0005, 0x6020, 0x9086, 0x0009, 0x1160, 0x6100, 0x9186,
-	0x0004, 0x1138, 0x6110, 0x81ff, 0x190c, 0x0d85, 0x2c00, 0x080c,
-	0x8ed9, 0x9006, 0x0005, 0x2071, 0x193f, 0x2073, 0x0000, 0x8e70,
-	0x9e86, 0x1947, 0x1dd0, 0x2071, 0x193d, 0x7006, 0x7002, 0x2001,
-	0x1930, 0x2064, 0x8cff, 0x0130, 0x6120, 0x918e, 0x0000, 0x190c,
-	0x0d85, 0x2102, 0x2001, 0x188a, 0x200c, 0x81ff, 0x0148, 0x0096,
-	0x2148, 0x080c, 0x108b, 0x009e, 0x2001, 0x188a, 0x2003, 0x0000,
-	0x2071, 0x1931, 0x080c, 0x90f7, 0x0804, 0x9106, 0x0000, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x187a,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0126, 0x2091,
-	0x8000, 0x0036, 0x0046, 0x20a9, 0x0010, 0x9006, 0x8004, 0x8086,
-	0x818e, 0x1208, 0x9200, 0x1f04, 0x954f, 0x8086, 0x818e, 0x004e,
-	0x003e, 0x012e, 0x0005, 0x0126, 0x2091, 0x8000, 0x0076, 0x0156,
-	0x20a9, 0x0010, 0x9005, 0x01c8, 0x911a, 0x12b8, 0x8213, 0x818d,
-	0x0228, 0x911a, 0x1220, 0x1f04, 0x9566, 0x0028, 0x911a, 0x2308,
-	0x8210, 0x1f04, 0x9566, 0x0006, 0x3200, 0x9084, 0xefff, 0x2080,
-	0x000e, 0x015e, 0x007e, 0x012e, 0x0005, 0x0006, 0x3200, 0x9085,
-	0x1000, 0x0ca8, 0x0126, 0x2091, 0x2800, 0x2079, 0x19e8, 0x012e,
-	0x00d6, 0x2069, 0x19e8, 0x6803, 0x0005, 0x0156, 0x0146, 0x01d6,
-	0x20e9, 0x0000, 0x2069, 0x0200, 0x080c, 0xaaf1, 0x04c9, 0x080c,
-	0xaadc, 0x04b1, 0x080c, 0xaadf, 0x0499, 0x080c, 0xaae2, 0x0481,
-	0x080c, 0xaae5, 0x0469, 0x080c, 0xaae8, 0x0451, 0x080c, 0xaaeb,
-	0x0439, 0x080c, 0xaaee, 0x0421, 0x01de, 0x014e, 0x015e, 0x6857,
-	0x0000, 0x00f6, 0x2079, 0x0380, 0x0419, 0x7807, 0x0003, 0x7803,
-	0x0000, 0x7803, 0x0001, 0x2069, 0x0004, 0x2d04, 0x9084, 0xfffe,
-	0x9085, 0x8000, 0x206a, 0x2069, 0x0100, 0x6828, 0x9084, 0xfffc,
-	0x682a, 0x00fe, 0x2001, 0x1b5d, 0x2003, 0x0000, 0x00de, 0x0005,
-	0x20a9, 0x0020, 0x20a1, 0x0240, 0x2001, 0x0000, 0x4004, 0x0005,
-	0x00c6, 0x7803, 0x0000, 0x9006, 0x7827, 0x0030, 0x782b, 0x0400,
-	0x7827, 0x0031, 0x782b, 0x1af6, 0x781f, 0xff00, 0x781b, 0xff00,
-	0x2061, 0x1aeb, 0x602f, 0x19e8, 0x6033, 0x1800, 0x6037, 0x1a04,
-	0x603b, 0x1ec1, 0x603f, 0x1ed1, 0x6042, 0x6047, 0x1ac1, 0x00ce,
-	0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0001,
-	0x01b0, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08, 0x2061, 0x19e8,
-	0x602c, 0x8000, 0x602e, 0x601c, 0x9005, 0x0130, 0x9080, 0x0003,
-	0x2102, 0x611e, 0x00ce, 0x0005, 0x6122, 0x611e, 0x0cd8, 0x6146,
-	0x2c08, 0x2001, 0x0012, 0x080c, 0xaced, 0x0005, 0x0016, 0x2009,
-	0x8020, 0x6146, 0x2c08, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007,
-	0x9086, 0x0001, 0x1128, 0x2001, 0x0019, 0x080c, 0xaced, 0x0088,
-	0x00c6, 0x2061, 0x19e8, 0x602c, 0x8000, 0x602e, 0x600c, 0x9005,
-	0x0128, 0x9080, 0x0003, 0x2102, 0x610e, 0x0010, 0x6112, 0x610e,
-	0x00ce, 0x001e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007,
-	0x9086, 0x0001, 0x0198, 0x00c6, 0x6146, 0x600f, 0x0000, 0x2c08,
-	0x2061, 0x19e8, 0x6044, 0x9005, 0x0130, 0x9080, 0x0003, 0x2102,
-	0x6146, 0x00ce, 0x0005, 0x614a, 0x6146, 0x0cd8, 0x6146, 0x600f,
-	0x0000, 0x2c08, 0x2001, 0x0013, 0x080c, 0xaced, 0x0005, 0x6044,
-	0xd0dc, 0x0110, 0x080c, 0xa78a, 0x0005, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x00b6, 0x0096, 0x0076, 0x0066, 0x0056, 0x0036, 0x0026,
-	0x0016, 0x0006, 0x0126, 0x902e, 0x2071, 0x19e8, 0x7648, 0x2660,
-	0x2678, 0x2091, 0x8000, 0x8cff, 0x0904, 0x96f1, 0x9c86, 0x1b55,
-	0x0904, 0x96ec, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1904, 0x96ec,
-	0x87ff, 0x0120, 0x605c, 0x9106, 0x1904, 0x96ec, 0x704c, 0x9c06,
-	0x1188, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x703f, 0x0000,
-	0x9006, 0x704e, 0x706a, 0x7052, 0x706e, 0x080c, 0xaff4, 0x003e,
-	0x2029, 0x0001, 0x080c, 0x9667, 0x7048, 0x9c36, 0x1110, 0x660c,
-	0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00,
-	0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06,
-	0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xcf1b,
-	0x01f0, 0x6014, 0x2048, 0x6020, 0x9086, 0x0003, 0x1588, 0x6004,
-	0x9086, 0x0040, 0x090c, 0xa78a, 0xa867, 0x0103, 0xab7a, 0xa877,
-	0x0000, 0x0016, 0x0036, 0x0076, 0x080c, 0xd220, 0x080c, 0xeddf,
-	0x080c, 0x7012, 0x007e, 0x003e, 0x001e, 0x080c, 0xd10c, 0x080c,
-	0xb1a7, 0x00ce, 0x0804, 0x9683, 0x2c78, 0x600c, 0x2060, 0x0804,
-	0x9683, 0x012e, 0x000e, 0x001e, 0x002e, 0x003e, 0x005e, 0x006e,
-	0x007e, 0x009e, 0x00be, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005,
-	0x6020, 0x9086, 0x0006, 0x1158, 0x0016, 0x0036, 0x0076, 0x080c,
-	0xeddf, 0x080c, 0xea30, 0x007e, 0x003e, 0x001e, 0x08c0, 0x6020,
-	0x9086, 0x0009, 0x1168, 0xa87b, 0x0006, 0x0016, 0x0036, 0x0076,
-	0x080c, 0x7012, 0x080c, 0xb16c, 0x007e, 0x003e, 0x001e, 0x0848,
-	0x6020, 0x9086, 0x000a, 0x0904, 0x96d6, 0x0804, 0x96cf, 0x0006,
-	0x0066, 0x0096, 0x00c6, 0x00d6, 0x00f6, 0x9036, 0x0126, 0x2091,
-	0x8000, 0x2079, 0x19e8, 0x7848, 0x9065, 0x0904, 0x9790, 0x600c,
-	0x0006, 0x600f, 0x0000, 0x784c, 0x9c06, 0x11b0, 0x0036, 0x2019,
-	0x0001, 0x080c, 0xa596, 0x783f, 0x0000, 0x901e, 0x7b4e, 0x7b6a,
-	0x7b52, 0x7b6e, 0x080c, 0xaff4, 0x003e, 0x000e, 0x9005, 0x1118,
-	0x600c, 0x600f, 0x0000, 0x0006, 0x9c86, 0x1b55, 0x05b0, 0x00e6,
-	0x2f70, 0x080c, 0x9667, 0x00ee, 0x080c, 0xcf1b, 0x0548, 0x6014,
-	0x2048, 0x6020, 0x9086, 0x0003, 0x15a8, 0x3e08, 0x918e, 0x0002,
-	0x1188, 0x6010, 0x9005, 0x0170, 0x00b6, 0x2058, 0xb800, 0x00be,
-	0xd0bc, 0x0140, 0x6048, 0x9005, 0x11c0, 0x2001, 0x1988, 0x2004,
-	0x604a, 0x0098, 0x6004, 0x9086, 0x0040, 0x090c, 0xa78a, 0xa867,
-	0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7006, 0x080c, 0xd10c,
-	0x6044, 0xc0fc, 0x6046, 0x080c, 0xb1a7, 0x000e, 0x0804, 0x9734,
-	0x7e4a, 0x7e46, 0x012e, 0x00fe, 0x00de, 0x00ce, 0x009e, 0x006e,
-	0x000e, 0x0005, 0x6020, 0x9086, 0x0006, 0x1118, 0x080c, 0xea30,
-	0x0c38, 0x6020, 0x9086, 0x0009, 0x1130, 0xab7a, 0x080c, 0x7012,
-	0x080c, 0xb16c, 0x0c10, 0x6020, 0x9086, 0x000a, 0x0990, 0x0850,
-	0x0016, 0x0026, 0x0086, 0x9046, 0x00a9, 0x080c, 0x98a3, 0x008e,
-	0x002e, 0x001e, 0x0005, 0x00f6, 0x0126, 0x2079, 0x19e8, 0x2091,
-	0x8000, 0x080c, 0x98ec, 0x080c, 0x9982, 0x080c, 0x6948, 0x012e,
-	0x00fe, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6,
-	0x0066, 0x0016, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8,
-	0x7620, 0x2660, 0x2678, 0x8cff, 0x0904, 0x9868, 0x6010, 0x2058,
-	0xb8a0, 0x9206, 0x1904, 0x9863, 0x88ff, 0x0120, 0x605c, 0x9106,
-	0x1904, 0x9863, 0x7030, 0x9c06, 0x1580, 0x2069, 0x0100, 0x6820,
-	0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c, 0x8a4b, 0x080c, 0xa2a0,
-	0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, 0x0036, 0x2069,
-	0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c,
-	0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x0040, 0x7008, 0xc0ad, 0x700a,
-	0x6003, 0x0009, 0x630a, 0x0804, 0x9863, 0x7020, 0x9c36, 0x1110,
-	0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118,
-	0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c, 0x0066, 0x2c00,
-	0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6044,
-	0xc0fc, 0x6046, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x01e8, 0x6020,
-	0x9086, 0x0003, 0x1580, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c,
-	0x0098, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036,
-	0x0086, 0x080c, 0xd220, 0x080c, 0xeddf, 0x080c, 0x7012, 0x008e,
-	0x003e, 0x001e, 0x080c, 0xd10c, 0x080c, 0xb1a7, 0x080c, 0xa65d,
-	0x00ce, 0x0804, 0x97db, 0x2c78, 0x600c, 0x2060, 0x0804, 0x97db,
-	0x012e, 0x000e, 0x001e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe,
-	0x009e, 0x00be, 0x0005, 0x6020, 0x9086, 0x0006, 0x1158, 0x0016,
-	0x0036, 0x0086, 0x080c, 0xeddf, 0x080c, 0xea30, 0x008e, 0x003e,
-	0x001e, 0x08d0, 0x080c, 0xbb5c, 0x6020, 0x9086, 0x0002, 0x1160,
-	0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0904, 0x9849, 0x9086,
-	0x008b, 0x0904, 0x9849, 0x0840, 0x6020, 0x9086, 0x0005, 0x1920,
-	0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x09c8, 0x9086, 0x008b,
-	0x09b0, 0x0804, 0x985c, 0x0006, 0x00f6, 0x00e6, 0x0096, 0x00b6,
-	0x00c6, 0x0066, 0x0016, 0x0126, 0x2091, 0x8000, 0x9280, 0x1000,
-	0x2004, 0x905d, 0x2079, 0x19e8, 0x9036, 0x7828, 0x2060, 0x8cff,
-	0x0538, 0x6010, 0x9b06, 0x1500, 0x6043, 0xffff, 0x080c, 0xaf2e,
-	0x01d8, 0x610c, 0x0016, 0x080c, 0xa420, 0x6014, 0x2048, 0xa867,
-	0x0103, 0xab7a, 0xa877, 0x0000, 0x0016, 0x0036, 0x0086, 0x080c,
-	0xd220, 0x080c, 0xeddf, 0x080c, 0x7012, 0x008e, 0x003e, 0x001e,
-	0x080c, 0xb1a7, 0x00ce, 0x08d8, 0x2c30, 0x600c, 0x2060, 0x08b8,
-	0x080c, 0x6965, 0x012e, 0x001e, 0x006e, 0x00ce, 0x00be, 0x009e,
-	0x00ee, 0x00fe, 0x000e, 0x0005, 0x0096, 0x0006, 0x0066, 0x00c6,
-	0x00d6, 0x9036, 0x7820, 0x9065, 0x0904, 0x9955, 0x600c, 0x0006,
-	0x6044, 0xc0fc, 0x6046, 0x600f, 0x0000, 0x7830, 0x9c06, 0x1598,
-	0x2069, 0x0100, 0x6820, 0xd0a4, 0x0110, 0xd0cc, 0x1508, 0x080c,
-	0x8a4b, 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7833,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138,
-	0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069,
-	0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x0058,
-	0x080c, 0x6ba9, 0x1538, 0x6003, 0x0009, 0x630a, 0x7808, 0xc0ad,
-	0x780a, 0x2c30, 0x00f8, 0x6014, 0x2048, 0x080c, 0xcf19, 0x01b0,
-	0x6020, 0x9086, 0x0003, 0x1508, 0x080c, 0xd132, 0x1118, 0x080c,
-	0xbb5c, 0x0060, 0x080c, 0x6ba9, 0x1168, 0xa867, 0x0103, 0xab7a,
-	0xa877, 0x0000, 0x080c, 0x7012, 0x080c, 0xd10c, 0x080c, 0xb1a7,
-	0x080c, 0xa65d, 0x000e, 0x0804, 0x98f3, 0x7e22, 0x7e1e, 0x00de,
-	0x00ce, 0x006e, 0x000e, 0x009e, 0x0005, 0x6020, 0x9086, 0x0006,
-	0x1118, 0x080c, 0xea30, 0x0c50, 0x080c, 0xbb5c, 0x6020, 0x9086,
-	0x0002, 0x1150, 0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0990,
-	0x9086, 0x008b, 0x0978, 0x08d0, 0x6020, 0x9086, 0x0005, 0x19b0,
-	0x6004, 0x0006, 0x9086, 0x0085, 0x000e, 0x0d18, 0x9086, 0x008b,
-	0x0d00, 0x0860, 0x0006, 0x0096, 0x00b6, 0x00c6, 0x0066, 0x9036,
-	0x7828, 0x9065, 0x0510, 0x6010, 0x2058, 0x600c, 0x0006, 0x3e08,
-	0x918e, 0x0002, 0x1118, 0xb800, 0xd0bc, 0x11a8, 0x6043, 0xffff,
-	0x080c, 0xaf2e, 0x0180, 0x610c, 0x080c, 0xa420, 0x6014, 0x2048,
-	0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7012, 0x080c,
-	0xb1a7, 0x000e, 0x08f0, 0x2c30, 0x0ce0, 0x006e, 0x00ce, 0x00be,
-	0x009e, 0x000e, 0x0005, 0x00e6, 0x00d6, 0x0096, 0x0066, 0x080c,
-	0x62af, 0x11b0, 0x2071, 0x19e8, 0x7030, 0x9080, 0x0005, 0x2004,
-	0x904d, 0x0170, 0xa878, 0x9606, 0x1158, 0x2071, 0x19e8, 0x7030,
-	0x9035, 0x0130, 0x9080, 0x0005, 0x2004, 0x9906, 0x1108, 0x0029,
-	0x006e, 0x009e, 0x00de, 0x00ee, 0x0005, 0x00c6, 0x2660, 0x6043,
-	0xffff, 0x080c, 0xaf2e, 0x0178, 0x080c, 0xa420, 0x6014, 0x2048,
-	0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0xd220, 0x080c,
-	0x7012, 0x080c, 0xb1a7, 0x00ce, 0x0005, 0x00b6, 0x00e6, 0x00c6,
-	0x080c, 0xacfc, 0x0106, 0x2071, 0x0101, 0x2e04, 0xc0c4, 0x2072,
-	0x6044, 0xd0fc, 0x1138, 0x010e, 0x090c, 0xad18, 0x00ce, 0x00ee,
-	0x00be, 0x0005, 0x2071, 0x19e8, 0x7030, 0x9005, 0x0da0, 0x9c06,
-	0x190c, 0x0d85, 0x7036, 0x080c, 0x8a4b, 0x7004, 0x9084, 0x0007,
-	0x0002, 0x9a1b, 0x9a1d, 0x9a24, 0x9a2e, 0x9a3c, 0x9a1b, 0x9a29,
-	0x9a19, 0x080c, 0x0d85, 0x0428, 0x0005, 0x080c, 0xaf19, 0x7007,
-	0x0000, 0x7033, 0x0000, 0x00e8, 0x0066, 0x9036, 0x080c, 0xa420,
-	0x006e, 0x7007, 0x0000, 0x7033, 0x0000, 0x0098, 0x080c, 0xaf04,
-	0x0140, 0x080c, 0xaf19, 0x0128, 0x0066, 0x9036, 0x080c, 0xa420,
-	0x006e, 0x7033, 0x0000, 0x0028, 0x080c, 0xaf04, 0x080c, 0xa78a,
-	0x0000, 0x010e, 0x090c, 0xad18, 0x00ce, 0x00ee, 0x00be, 0x0005,
-	0x00d6, 0x00c6, 0x080c, 0xacfc, 0x0106, 0x6044, 0xd0fc, 0x1130,
-	0x010e, 0x090c, 0xad18, 0x00ce, 0x00de, 0x0005, 0x2069, 0x19e8,
-	0x684c, 0x9005, 0x0da8, 0x9c06, 0x190c, 0x0d85, 0x6852, 0x00e6,
-	0x2d70, 0x080c, 0x9667, 0x00ee, 0x080c, 0x8a58, 0x0016, 0x2009,
-	0x0040, 0x080c, 0x2220, 0x001e, 0x683c, 0x9084, 0x0003, 0x0002,
-	0x9a76, 0x9a77, 0x9a96, 0x9a74, 0x080c, 0x0d85, 0x0490, 0x6868,
-	0x9086, 0x0001, 0x0198, 0x600c, 0x9015, 0x0168, 0x6a4a, 0x600f,
-	0x0000, 0x6044, 0x9084, 0x7f7f, 0x6046, 0x9006, 0x6842, 0x684e,
-	0x683f, 0x0000, 0x00f0, 0x684a, 0x6846, 0x0c98, 0x686b, 0x0000,
-	0x6848, 0x9065, 0x0d70, 0x6003, 0x0002, 0x0c58, 0x6044, 0x9084,
-	0x7f7f, 0x6046, 0x9006, 0x6842, 0x684e, 0x686a, 0x6852, 0x686e,
-	0x600c, 0x9015, 0x0120, 0x6a4a, 0x600f, 0x0000, 0x0010, 0x684a,
-	0x6846, 0x080c, 0xaff4, 0x684f, 0x0000, 0x010e, 0x090c, 0xad18,
-	0x00ce, 0x00de, 0x0005, 0x0005, 0x6020, 0x9084, 0x000f, 0x000b,
-	0x0005, 0x9ac9, 0x9acc, 0x9f80, 0xa019, 0x9acc, 0x9f80, 0xa019,
-	0x9ac9, 0x9acc, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9, 0x9ac9,
-	0x9ac9, 0x080c, 0x99ed, 0x0005, 0x00b6, 0x0156, 0x0136, 0x0146,
-	0x01c6, 0x01d6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200,
-	0x2071, 0x0240, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d85, 0x6110,
-	0x2158, 0xb984, 0x2c78, 0x2061, 0x0100, 0x619a, 0x908a, 0x0040,
-	0x1a04, 0x9b38, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de,
-	0x01ce, 0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0x9ce1, 0x9d1c,
-	0x9d45, 0x9e0f, 0x9e31, 0x9e37, 0x9e44, 0x9e4c, 0x9e58, 0x9e5e,
-	0x9e6f, 0x9e5e, 0x9ec7, 0x9e4c, 0x9ed3, 0x9ed9, 0x9e58, 0x9ed9,
-	0x9ee5, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36, 0x9b36,
-	0x9b36, 0x9b36, 0x9b36, 0x9b36, 0xa441, 0xa464, 0xa475, 0xa495,
-	0xa4c7, 0x9e44, 0x9b36, 0x9e44, 0x9e5e, 0x9b36, 0x9d45, 0x9e0f,
-	0x9b36, 0xa888, 0x9e5e, 0x9b36, 0xa8a4, 0x9e5e, 0x9b36, 0x9e58,
-	0x9cdb, 0x9b59, 0x9b36, 0xa8c0, 0xa92d, 0xaa11, 0x9b36, 0xaa1e,
-	0x9e41, 0xaa49, 0x9b36, 0xa4d1, 0xaa55, 0x9b36, 0x080c, 0x0d85,
-	0x2100, 0x005b, 0x00fe, 0x00ee, 0x00de, 0x00ce, 0x01de, 0x01ce,
-	0x014e, 0x013e, 0x015e, 0x00be, 0x0005, 0xaaf5, 0xaba7, 0x9b57,
-	0x9b91, 0x9c3d, 0x9c48, 0x9b57, 0x9e44, 0x9b57, 0x9ca2, 0x9cae,
-	0x9bac, 0x9b57, 0x9bc7, 0x9bfb, 0xb008, 0xb04d, 0x9e5e, 0x080c,
-	0x0d85, 0x00d6, 0x0096, 0x080c, 0x9ef8, 0x0026, 0x0036, 0x7814,
-	0x2048, 0xa958, 0xd1cc, 0x1138, 0x2009, 0x2414, 0x2011, 0x0018,
-	0x2019, 0x0018, 0x0030, 0x2009, 0x2410, 0x2011, 0x0014, 0x2019,
-	0x0014, 0x7102, 0x7206, 0x700b, 0x0800, 0xa83c, 0x700e, 0xa850,
-	0x7022, 0xa854, 0x7026, 0x63c2, 0x080c, 0xa270, 0x003e, 0x002e,
-	0x009e, 0x00de, 0x0005, 0x7810, 0x00b6, 0x2058, 0xb8a0, 0x00be,
-	0x080c, 0xb094, 0x1118, 0x9084, 0xff80, 0x0110, 0x9085, 0x0001,
-	0x0005, 0x00d6, 0x0096, 0x080c, 0x9ef8, 0x7003, 0x0500, 0x7814,
-	0x2048, 0xa874, 0x700a, 0xa878, 0x700e, 0xa87c, 0x7012, 0xa880,
-	0x7016, 0xa884, 0x701a, 0xa888, 0x701e, 0x60c3, 0x0010, 0x080c,
-	0xa270, 0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x080c, 0x9ef8,
-	0x7003, 0x0500, 0x7814, 0x2048, 0xa8cc, 0x700a, 0xa8d0, 0x700e,
-	0xa8d4, 0x7012, 0xa8d8, 0x7016, 0xa8dc, 0x701a, 0xa8e0, 0x701e,
-	0x60c3, 0x0010, 0x080c, 0xa270, 0x009e, 0x00de, 0x0005, 0x00d6,
-	0x0096, 0x0126, 0x2091, 0x8000, 0x080c, 0x9ef8, 0x20e9, 0x0000,
-	0x2001, 0x19a4, 0x2003, 0x0000, 0x7814, 0x2048, 0xa814, 0x8003,
-	0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b,
-	0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x2001, 0x0001, 0x080c,
-	0x2205, 0x080c, 0xdcef, 0x9006, 0x080c, 0x2205, 0x001e, 0xa804,
-	0x9005, 0x0110, 0x2048, 0x0c28, 0x04d9, 0x080c, 0xa270, 0x012e,
-	0x009e, 0x00de, 0x0005, 0x00d6, 0x0096, 0x0126, 0x2091, 0x8000,
-	0x080c, 0x9f43, 0x20e9, 0x0000, 0x2001, 0x19a4, 0x2003, 0x0000,
-	0x7814, 0x2048, 0xa86f, 0x0200, 0xa873, 0x0000, 0xa814, 0x8003,
-	0x60c2, 0xa830, 0x20a8, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b,
-	0x2098, 0x2001, 0x19a4, 0x0016, 0x200c, 0x080c, 0xdcef, 0x001e,
-	0xa804, 0x9005, 0x0110, 0x2048, 0x0c60, 0x0051, 0x7814, 0x2048,
-	0x080c, 0x100b, 0x080c, 0xa270, 0x012e, 0x009e, 0x00de, 0x0005,
-	0x60c0, 0x8004, 0x9084, 0x0003, 0x9005, 0x0130, 0x9082, 0x0004,
-	0x20a3, 0x0000, 0x8000, 0x1de0, 0x0005, 0x080c, 0x9ef8, 0x7003,
-	0x7800, 0x7808, 0x8007, 0x700a, 0x60c3, 0x0008, 0x0804, 0xa270,
-	0x00d6, 0x00e6, 0x080c, 0x9f43, 0x7814, 0x9084, 0xff00, 0x2073,
-	0x0200, 0x8e70, 0x8e70, 0x9096, 0xdf00, 0x0138, 0x9096, 0xe000,
-	0x0120, 0x2073, 0x0010, 0x8e70, 0x0030, 0x9095, 0x0010, 0x2272,
-	0x8e70, 0x2073, 0x0034, 0x8e70, 0x2069, 0x1805, 0x20a9, 0x0004,
-	0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9c68, 0x2069, 0x1801, 0x20a9,
-	0x0004, 0x2d76, 0x8d68, 0x8e70, 0x1f04, 0x9c71, 0x9096, 0xdf00,
-	0x0130, 0x9096, 0xe000, 0x0118, 0x60c3, 0x0018, 0x00f0, 0x2069,
-	0x19b4, 0x9086, 0xdf00, 0x0110, 0x2069, 0x19ce, 0x20a9, 0x001a,
-	0x9e86, 0x0260, 0x1148, 0x00c6, 0x2061, 0x0200, 0x6010, 0x8000,
-	0x6012, 0x00ce, 0x2071, 0x0240, 0x2d04, 0x8007, 0x2072, 0x8d68,
-	0x8e70, 0x1f04, 0x9c88, 0x60c3, 0x004c, 0x080c, 0xa270, 0x00ee,
-	0x00de, 0x0005, 0x080c, 0x9ef8, 0x7003, 0x6300, 0x7007, 0x0028,
-	0x7808, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00d6, 0x0026,
-	0x0016, 0x080c, 0x9f43, 0x7003, 0x0200, 0x7814, 0x700e, 0x00e6,
-	0x9ef0, 0x0004, 0x2009, 0x0001, 0x2011, 0x000c, 0x2069, 0x1924,
-	0x6810, 0xd084, 0x1148, 0x2073, 0x0500, 0x8e70, 0x2073, 0x0000,
-	0x8e70, 0x8108, 0x9290, 0x0004, 0x2073, 0x0800, 0x8e70, 0x2073,
-	0x0000, 0x00ee, 0x7206, 0x710a, 0x62c2, 0x080c, 0xa270, 0x001e,
-	0x002e, 0x00de, 0x0005, 0x2001, 0x1818, 0x2004, 0x609a, 0x0804,
-	0xa270, 0x080c, 0x9ef8, 0x7003, 0x5200, 0x2069, 0x1847, 0x6804,
-	0xd084, 0x0130, 0x6828, 0x0016, 0x080c, 0x26bf, 0x710e, 0x001e,
-	0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000,
-	0x20a1, 0x0250, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1,
-	0x0254, 0x4003, 0x080c, 0xb094, 0x1120, 0xb8a0, 0x9082, 0x007f,
-	0x0248, 0x2001, 0x181f, 0x2004, 0x7032, 0x2001, 0x1820, 0x2004,
-	0x7036, 0x0030, 0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x7036,
-	0x60c3, 0x001c, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x7003, 0x0500,
-	0x080c, 0xb094, 0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001,
-	0x181f, 0x2004, 0x700a, 0x2001, 0x1820, 0x2004, 0x700e, 0x0030,
-	0x2001, 0x1818, 0x2004, 0x9084, 0x00ff, 0x700e, 0x20a9, 0x0004,
-	0x20e1, 0x0001, 0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0250,
-	0x4003, 0x60c3, 0x0010, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x9006,
-	0x080c, 0x6bdb, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2011, 0x0240,
-	0x2013, 0x22ff, 0x2011, 0x0241, 0x2013, 0xfffe, 0x7003, 0x0400,
-	0x620c, 0xc2b4, 0x620e, 0x0058, 0x7814, 0x0096, 0x904d, 0x0120,
-	0x9006, 0xa89a, 0xa8a6, 0xa8aa, 0x009e, 0x7003, 0x0300, 0xb8a0,
-	0x9086, 0x007e, 0x1904, 0x9dcf, 0x00d6, 0x2069, 0x196c, 0x2001,
-	0x1837, 0x2004, 0xd0a4, 0x0188, 0x6800, 0x700a, 0x6808, 0x9084,
-	0x2000, 0x7012, 0x080c, 0xb0ab, 0x680c, 0x7016, 0x701f, 0x2710,
-	0x6818, 0x7022, 0x681c, 0x7026, 0x0428, 0x6800, 0x700a, 0x6804,
-	0x700e, 0x2009, 0x180d, 0x210c, 0xd18c, 0x0110, 0x2001, 0x0002,
-	0x00f6, 0x2079, 0x0100, 0x080c, 0x779e, 0x1128, 0x78e3, 0x0000,
-	0x080c, 0x2700, 0x78e2, 0x00fe, 0x6808, 0x080c, 0x779e, 0x1118,
-	0x9084, 0x37ff, 0x0010, 0x9084, 0x3fff, 0x7012, 0x080c, 0xb0ab,
-	0x680c, 0x7016, 0x00de, 0x20a9, 0x0004, 0x20e1, 0x0001, 0x2099,
-	0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004,
-	0x2099, 0x1801, 0x20a1, 0x025a, 0x4003, 0x00d6, 0x080c, 0xaadc,
-	0x2069, 0x1974, 0x2071, 0x024e, 0x6800, 0xc0dd, 0x7002, 0x080c,
-	0x5844, 0xd0e4, 0x0110, 0x680c, 0x700e, 0x00de, 0x04e0, 0x2001,
-	0x1837, 0x2004, 0xd0a4, 0x01a8, 0x0016, 0x2001, 0x180d, 0x2004,
-	0xd08c, 0x2009, 0x0002, 0x1118, 0x2001, 0x196d, 0x200c, 0x60e0,
-	0x9106, 0x0130, 0x2100, 0x60e3, 0x0000, 0x080c, 0x2700, 0x61e2,
-	0x001e, 0x20e1, 0x0001, 0x2099, 0x196c, 0x20e9, 0x0000, 0x20a1,
-	0x024e, 0x20a9, 0x0008, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1805,
-	0x20a1, 0x0256, 0x4003, 0x20a9, 0x0004, 0x2099, 0x1801, 0x20a1,
-	0x025a, 0x4003, 0x080c, 0xaadc, 0x20a1, 0x024e, 0x20a9, 0x0008,
-	0x2099, 0x1974, 0x4003, 0x60c3, 0x0074, 0x0804, 0xa270, 0x080c,
-	0x9ef8, 0x7003, 0x2010, 0x7007, 0x0014, 0x700b, 0x0800, 0x700f,
-	0x2000, 0x9006, 0x00f6, 0x2079, 0x1847, 0x7904, 0x00fe, 0xd1ac,
-	0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085, 0x0010, 0x9085,
-	0x0002, 0x00d6, 0x0804, 0x9ea8, 0x7026, 0x60c3, 0x0014, 0x0804,
-	0xa270, 0x080c, 0x9ef8, 0x7003, 0x5000, 0x0804, 0x9d67, 0x080c,
-	0x9ef8, 0x7003, 0x2110, 0x7007, 0x0014, 0x60c3, 0x0014, 0x0804,
-	0xa270, 0x080c, 0x9f3a, 0x0010, 0x080c, 0x9f43, 0x7003, 0x0200,
-	0x60c3, 0x0004, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, 0x0100,
-	0x700b, 0x0003, 0x700f, 0x2a00, 0x60c3, 0x0008, 0x0804, 0xa270,
-	0x080c, 0x9f43, 0x7003, 0x0200, 0x0804, 0x9d67, 0x080c, 0x9f43,
-	0x7003, 0x0100, 0x782c, 0x9005, 0x0110, 0x700a, 0x0010, 0x700b,
-	0x0003, 0x7814, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00d6,
-	0x080c, 0x9f43, 0x7003, 0x0210, 0x7007, 0x0014, 0x700b, 0x0800,
-	0xb894, 0x9086, 0x0014, 0x1198, 0xb99c, 0x9184, 0x0030, 0x0190,
-	0xb998, 0x9184, 0xc000, 0x1140, 0xd1ec, 0x0118, 0x700f, 0x2100,
-	0x0058, 0x700f, 0x0100, 0x0040, 0x700f, 0x0400, 0x0028, 0x700f,
-	0x0700, 0x0010, 0x700f, 0x0800, 0x00f6, 0x2079, 0x1847, 0x7904,
-	0x00fe, 0xd1ac, 0x1110, 0x9085, 0x0020, 0xd1a4, 0x0110, 0x9085,
-	0x0010, 0x2009, 0x1869, 0x210c, 0xd184, 0x1110, 0x9085, 0x0002,
-	0x0026, 0x2009, 0x1867, 0x210c, 0xd1e4, 0x0150, 0xc0c5, 0xbad4,
-	0xd28c, 0x1108, 0xc0cd, 0x9094, 0x0030, 0x9296, 0x0010, 0x0140,
-	0xd1ec, 0x0130, 0x9094, 0x0030, 0x9296, 0x0010, 0x0108, 0xc0bd,
-	0x002e, 0x7026, 0x60c3, 0x0014, 0x00de, 0x0804, 0xa270, 0x080c,
-	0x9f43, 0x7003, 0x0210, 0x7007, 0x0014, 0x700f, 0x0100, 0x60c3,
-	0x0014, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003, 0x0200, 0x0804,
-	0x9ce5, 0x080c, 0x9f43, 0x7003, 0x0100, 0x700b, 0x0003, 0x700f,
-	0x2a00, 0x60c3, 0x0008, 0x0804, 0xa270, 0x080c, 0x9f43, 0x7003,
-	0x0100, 0x700b, 0x000b, 0x60c3, 0x0008, 0x0804, 0xa270, 0x0026,
-	0x00d6, 0x0036, 0x0046, 0x2019, 0x3200, 0x2021, 0x0800, 0x0040,
-	0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x2200, 0x2021, 0x0100,
-	0x080c, 0xaaf1, 0xb810, 0x9305, 0x7002, 0xb814, 0x7006, 0x2069,
-	0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x9485, 0x0029, 0x7012,
-	0x004e, 0x003e, 0x00de, 0x080c, 0xa264, 0x721a, 0x9f95, 0x0000,
-	0x7222, 0x7027, 0xffff, 0x2071, 0x024c, 0x002e, 0x0005, 0x0026,
-	0x080c, 0xaaf1, 0x7003, 0x02ff, 0x7007, 0xfffc, 0x00d6, 0x2069,
-	0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x00de, 0x7013, 0x2029,
-	0x0c10, 0x7003, 0x0100, 0x7007, 0x0000, 0x700b, 0xfc02, 0x700f,
-	0x0000, 0x0005, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019, 0x3300,
-	0x2021, 0x0800, 0x0040, 0x0026, 0x00d6, 0x0036, 0x0046, 0x2019,
-	0x2300, 0x2021, 0x0100, 0x080c, 0xaaf1, 0xb810, 0x9305, 0x7002,
-	0xb814, 0x7006, 0x2069, 0x1800, 0xb810, 0x9005, 0x1140, 0xb814,
-	0x9005, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0020, 0x687c,
-	0x700a, 0x6880, 0x700e, 0x0000, 0x9485, 0x0098, 0x7012, 0x004e,
-	0x003e, 0x00de, 0x080c, 0xa264, 0x721a, 0x7a08, 0x7222, 0x2f10,
-	0x7226, 0x2071, 0x024c, 0x002e, 0x0005, 0x080c, 0xa264, 0x721a,
-	0x7a08, 0x7222, 0x7814, 0x7026, 0x2071, 0x024c, 0x002e, 0x0005,
-	0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2069, 0x0200, 0x2071,
-	0x0240, 0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092,
-	0x1a0c, 0x0d85, 0x6110, 0x2158, 0xb984, 0x2c78, 0x2061, 0x0100,
-	0x619a, 0x9082, 0x0085, 0x0033, 0x00fe, 0x00ee, 0x00de, 0x00ce,
-	0x00be, 0x0005, 0x9fb1, 0x9fc0, 0x9fcb, 0x9faf, 0x9faf, 0x9faf,
-	0x9fb1, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x9faf, 0x080c,
-	0x0d85, 0x0411, 0x60c3, 0x0000, 0x0026, 0x080c, 0x2a04, 0x0228,
-	0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x0804, 0xa270,
-	0x0431, 0x7808, 0x700a, 0x7814, 0x700e, 0x7017, 0xffff, 0x60c3,
-	0x000c, 0x0804, 0xa270, 0x04a1, 0x7003, 0x0003, 0x7007, 0x0300,
-	0x60c3, 0x0004, 0x0804, 0xa270, 0x0026, 0x080c, 0xaaf1, 0xb810,
-	0x9085, 0x8100, 0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x687c,
-	0x700a, 0x6880, 0x700e, 0x7013, 0x0009, 0x0804, 0x9f13, 0x0026,
-	0x080c, 0xaaf1, 0xb810, 0x9085, 0x8400, 0x7002, 0xb814, 0x7006,
-	0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001, 0x0099,
-	0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804, 0x9f75,
-	0x0026, 0x080c, 0xaaf1, 0xb810, 0x9085, 0x8500, 0x7002, 0xb814,
-	0x7006, 0x2069, 0x1800, 0x687c, 0x700a, 0x6880, 0x700e, 0x2001,
-	0x0099, 0x7a20, 0x9296, 0x0005, 0x0108, 0xc0bc, 0x7012, 0x0804,
-	0x9f75, 0x00b6, 0x00c6, 0x00d6, 0x00e6, 0x00f6, 0x2c78, 0x2069,
-	0x0200, 0x2071, 0x0240, 0x7804, 0x908a, 0x0040, 0x0a0c, 0x0d85,
-	0x908a, 0x0057, 0x1a0c, 0x0d85, 0x7910, 0x2158, 0xb984, 0x2061,
-	0x0100, 0x619a, 0x9082, 0x0040, 0x0033, 0x00fe, 0x00ee, 0x00de,
-	0x00ce, 0x00be, 0x0005, 0xa04e, 0xa04e, 0xa04e, 0xa07f, 0xa04e,
-	0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa04e, 0xa644, 0xa649,
-	0xa64e, 0xa653, 0xa04e, 0xa04e, 0xa04e, 0xa63f, 0x080c, 0x0d85,
-	0x6813, 0x0008, 0xba8c, 0x8210, 0xb8d4, 0xd084, 0x0180, 0x2001,
-	0x1b72, 0x200c, 0x8108, 0x2102, 0x2001, 0x1b71, 0x201c, 0x1218,
-	0x8318, 0x2302, 0x0ea0, 0x7952, 0x712e, 0x7b4e, 0x732a, 0x9294,
-	0x00ff, 0xba8e, 0x8217, 0x721a, 0xba10, 0x9295, 0x0600, 0x7202,
-	0xba14, 0x7206, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80, 0x720e,
-	0x7013, 0x0829, 0x2f10, 0x7222, 0x7027, 0xffff, 0x0005, 0x0016,
-	0x7814, 0x9084, 0x0700, 0x8007, 0x0013, 0x001e, 0x0005, 0xa08f,
-	0xa08f, 0xa091, 0xa08f, 0xa08f, 0xa08f, 0xa0ab, 0xa08f, 0x080c,
-	0x0d85, 0x7914, 0x918c, 0x08ff, 0x918d, 0xf600, 0x7916, 0x2009,
-	0x0003, 0x00b9, 0x2069, 0x1847, 0x6804, 0xd0bc, 0x0130, 0x682c,
-	0x9084, 0x00ff, 0x8007, 0x7032, 0x0010, 0x7033, 0x3f00, 0x60c3,
-	0x0001, 0x0804, 0xa270, 0x2009, 0x0003, 0x0019, 0x7033, 0x7f00,
-	0x0cb0, 0x0016, 0x080c, 0xaaf1, 0x001e, 0xb810, 0x9085, 0x0100,
-	0x7002, 0xb814, 0x7006, 0x2069, 0x1800, 0x6a7c, 0x720a, 0x6a80,
-	0x720e, 0x7013, 0x0888, 0x918d, 0x0008, 0x7116, 0x080c, 0xa264,
-	0x721a, 0x7a08, 0x7222, 0x2f10, 0x7226, 0x0005, 0x00b6, 0x00e6,
-	0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046, 0x0036, 0x2061, 0x0100,
-	0x2071, 0x1800, 0x7160, 0x7810, 0x2058, 0x76dc, 0x96b4, 0x0028,
-	0x0110, 0x737c, 0x7480, 0x2500, 0x76dc, 0x96b4, 0x0028, 0x0140,
-	0x2001, 0x04ff, 0x6062, 0x6067, 0xffff, 0x636a, 0x646e, 0x0050,
-	0x2001, 0x00ff, 0x9085, 0x0400, 0x6062, 0x6067, 0xffff, 0x606b,
-	0x0000, 0x616e, 0xb8b8, 0x6073, 0x0530, 0x6077, 0x0008, 0xb88c,
-	0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a,
-	0x607f, 0x0000, 0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096,
-	0x2048, 0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834,
-	0x60ca, 0x009e, 0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5,
-	0x60d7, 0x0000, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x0128,
-	0x609f, 0x0000, 0x2001, 0x0092, 0x0058, 0x6028, 0xc0bd, 0x602a,
-	0x609f, 0x00ff, 0x2011, 0xffff, 0x080c, 0x2ad3, 0x2001, 0x00b2,
-	0x2010, 0x900e, 0x080c, 0x2ae2, 0x2009, 0x07d0, 0x080c, 0x8a50,
-	0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00be,
-	0x0005, 0x00b6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0056, 0x0046,
-	0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7160, 0x7810, 0x2058,
-	0xb8a0, 0x2028, 0x76dc, 0xd6ac, 0x1168, 0x9582, 0x007e, 0x1250,
-	0x2500, 0x9094, 0xff80, 0x1130, 0x9080, 0x348e, 0x2015, 0x9294,
-	0x00ff, 0x0020, 0xb910, 0xba14, 0x737c, 0x7480, 0x70dc, 0xd0ac,
-	0x1130, 0x9582, 0x007e, 0x1218, 0x9584, 0xff80, 0x0138, 0x9185,
-	0x0400, 0x6062, 0x6266, 0x636a, 0x646e, 0x0030, 0x6063, 0x0400,
-	0x6266, 0x606b, 0x0000, 0x616e, 0xb8b8, 0x6072, 0x6077, 0x0000,
-	0xb864, 0xd0a4, 0x0110, 0x6077, 0x0008, 0xb88c, 0x8000, 0x9084,
-	0x00ff, 0xb88e, 0x8007, 0x9085, 0x0020, 0x607a, 0x607f, 0x0000,
-	0x2b00, 0x6082, 0x6087, 0xffff, 0x7814, 0x0096, 0x2048, 0xa848,
-	0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca, 0x009e,
-	0xb86c, 0x60ce, 0x60ab, 0x0036, 0x60af, 0x95d5, 0x60d7, 0x0000,
-	0xba84, 0x629e, 0x00f6, 0x2079, 0x0140, 0x7803, 0x0000, 0x00fe,
-	0x900e, 0x2011, 0x0092, 0x080c, 0x2ae2, 0x2009, 0x07d0, 0x080c,
-	0x8a50, 0x003e, 0x004e, 0x005e, 0x006e, 0x00ce, 0x00de, 0x00ee,
-	0x00be, 0x0005, 0x00b6, 0x0096, 0x00e6, 0x00d6, 0x00c6, 0x0056,
-	0x0046, 0x0036, 0x2061, 0x0100, 0x2071, 0x1800, 0x7810, 0x2058,
-	0xb8a0, 0x2028, 0xb910, 0xba14, 0x737c, 0x7480, 0x7820, 0x0002,
-	0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef,
-	0xa1ef, 0xa1ef, 0xa1f1, 0xa1ef, 0xa1ef, 0xa1ef, 0xa1ef, 0x080c,
-	0x0d85, 0xb884, 0x609e, 0x7814, 0x2048, 0xa87c, 0xd0fc, 0x0558,
-	0xaf90, 0x9784, 0xff00, 0x9105, 0x6062, 0x873f, 0x9784, 0xff00,
-	0x0006, 0x7814, 0x2048, 0xa878, 0xc0fc, 0x9005, 0x000e, 0x1160,
-	0xaf94, 0x87ff, 0x0198, 0x2039, 0x0098, 0x9705, 0x6072, 0x7808,
-	0x6082, 0x2f00, 0x6086, 0x0038, 0x9185, 0x2200, 0x6062, 0x6073,
-	0x0129, 0x6077, 0x0000, 0xb884, 0x609e, 0x0050, 0x2039, 0x0029,
-	0x9705, 0x6072, 0x0cc0, 0x9185, 0x0200, 0x6062, 0x6073, 0x2029,
-	0xa87c, 0xd0fc, 0x0118, 0xaf94, 0x87ff, 0x1120, 0x2f00, 0x6082,
-	0x7808, 0x6086, 0x6266, 0x636a, 0x646e, 0x6077, 0x0000, 0xb88c,
-	0x8000, 0x9084, 0x00ff, 0xb88e, 0x8007, 0x607a, 0x607f, 0x0000,
-	0xa848, 0x608a, 0xa844, 0x608e, 0xa838, 0x60c6, 0xa834, 0x60ca,
-	0xb86c, 0x60ce, 0x60af, 0x95d5, 0x60d7, 0x0000, 0x080c, 0xaad1,
-	0x2009, 0x07d0, 0x60c4, 0x9084, 0xfff0, 0x9005, 0x0110, 0x2009,
-	0x1b58, 0x080c, 0x8a50, 0x003e, 0x004e, 0x005e, 0x00ce, 0x00de,
-	0x00ee, 0x009e, 0x00be, 0x0005, 0x7a40, 0x9294, 0x00ff, 0x8217,
-	0x0005, 0x00d6, 0x2069, 0x19e8, 0x686b, 0x0001, 0x00de, 0x0005,
-	0x60a3, 0x0056, 0x60a7, 0x9575, 0x00f1, 0x080c, 0x8a42, 0x0005,
-	0x0016, 0x2001, 0x180c, 0x200c, 0x9184, 0x0600, 0x9086, 0x0600,
-	0x0128, 0x0089, 0x080c, 0x8a42, 0x001e, 0x0005, 0xc1e5, 0x2001,
-	0x180c, 0x2102, 0x2001, 0x19e9, 0x2003, 0x0000, 0x2001, 0x19f4,
-	0x2003, 0x0000, 0x0c88, 0x0006, 0x0016, 0x0026, 0x2009, 0x1804,
-	0x2011, 0x0009, 0x080c, 0x2ae2, 0x002e, 0x001e, 0x000e, 0x0005,
-	0x0016, 0x00c6, 0x0006, 0x080c, 0xacfc, 0x0106, 0x2061, 0x0100,
-	0x61a4, 0x60a7, 0x95f5, 0x0016, 0x0026, 0x2009, 0x1804, 0x2011,
-	0x0008, 0x080c, 0x2ae2, 0x002e, 0x001e, 0x010e, 0x090c, 0xad18,
-	0x000e, 0xa001, 0xa001, 0xa001, 0x61a6, 0x00ce, 0x001e, 0x0005,
-	0x00c6, 0x00d6, 0x0016, 0x0026, 0x2061, 0x0100, 0x2069, 0x0140,
-	0x080c, 0x779e, 0x1510, 0x2001, 0x1a0d, 0x2004, 0x9005, 0x1904,
-	0xa31f, 0x080c, 0x7840, 0x11a8, 0x2069, 0x0380, 0x6843, 0x0101,
-	0x6844, 0xd084, 0x1de8, 0x2061, 0x0100, 0x6020, 0xd0b4, 0x1120,
-	0x6024, 0xd084, 0x090c, 0x0d85, 0x6843, 0x0100, 0x080c, 0x8a42,
-	0x04b0, 0x00c6, 0x2061, 0x19e8, 0x00f0, 0x6904, 0x9194, 0x4000,
-	0x0598, 0x080c, 0xa2a0, 0x080c, 0x2aa9, 0x00c6, 0x2061, 0x19e8,
-	0x6134, 0x9192, 0x0008, 0x1278, 0x8108, 0x6136, 0x080c, 0xacfc,
-	0x6130, 0x080c, 0xad18, 0x00ce, 0x81ff, 0x01c8, 0x080c, 0x8a42,
-	0x080c, 0xa293, 0x00a0, 0x080c, 0xacfc, 0x6130, 0x91e5, 0x0000,
-	0x0150, 0x080c, 0xeeee, 0x080c, 0x8a4b, 0x6003, 0x0001, 0x2009,
-	0x0014, 0x080c, 0xb20a, 0x080c, 0xad18, 0x00ce, 0x0000, 0x002e,
-	0x001e, 0x00de, 0x00ce, 0x0005, 0x2001, 0x1a0d, 0x2004, 0x9005,
-	0x1db0, 0x00c6, 0x2061, 0x19e8, 0x6134, 0x9192, 0x0003, 0x1ad8,
-	0x8108, 0x6136, 0x00ce, 0x080c, 0x8a42, 0x080c, 0x6058, 0x2009,
-	0x1846, 0x2114, 0x8210, 0x220a, 0x0c10, 0x0096, 0x00c6, 0x00d6,
-	0x00e6, 0x0016, 0x0026, 0x080c, 0x8a58, 0x080c, 0xacfc, 0x2001,
-	0x0387, 0x2003, 0x0202, 0x2071, 0x19e8, 0x714c, 0x81ff, 0x0904,
-	0xa3d9, 0x2061, 0x0100, 0x2069, 0x0140, 0x080c, 0x779e, 0x1518,
-	0x0036, 0x2019, 0x0002, 0x080c, 0xa596, 0x003e, 0x080c, 0xeeee,
-	0x704c, 0x9065, 0x0180, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009,
-	0x1130, 0x6114, 0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003,
-	0x0003, 0x080c, 0xb20a, 0x2001, 0x0386, 0x2003, 0x5040, 0x080c,
-	0x7840, 0x0804, 0xa3d9, 0x6904, 0xd1f4, 0x0904, 0xa3e6, 0x080c,
-	0x2aa9, 0x00c6, 0x704c, 0x9065, 0x090c, 0x0d85, 0x6020, 0x00ce,
-	0x9086, 0x0006, 0x1520, 0x61c8, 0x60c4, 0x9105, 0x1500, 0x714c,
-	0x9188, 0x0011, 0x2104, 0xd0e4, 0x01d0, 0x6214, 0x9294, 0x1800,
-	0x1128, 0x6224, 0x9294, 0x0002, 0x15e0, 0x0010, 0xc0e4, 0x200a,
-	0x6014, 0x9084, 0xe7fd, 0x9085, 0x0010, 0x6016, 0x704c, 0x2060,
-	0x080c, 0x9a48, 0x2009, 0x0049, 0x080c, 0xb20a, 0x0450, 0x080c,
-	0xeeee, 0x704c, 0x9065, 0x9086, 0x1b55, 0x1158, 0x080c, 0xafd2,
-	0x1500, 0x2061, 0x1b55, 0x6064, 0x8000, 0x6066, 0x080c, 0x6058,
-	0x00c0, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x714c,
-	0x2160, 0x2009, 0x004a, 0x6220, 0x9296, 0x0009, 0x1130, 0x6114,
-	0x2148, 0xa87b, 0x0006, 0x2009, 0x004a, 0x6003, 0x0003, 0x080c,
-	0xb20a, 0x2001, 0x0387, 0x2003, 0x0200, 0x080c, 0xad18, 0x002e,
-	0x001e, 0x00ee, 0x00de, 0x00ce, 0x009e, 0x0005, 0xd1ec, 0x1904,
-	0xa37f, 0x0804, 0xa381, 0x0026, 0x00e6, 0x2071, 0x19e8, 0x706c,
-	0xd084, 0x01e8, 0xc084, 0x706e, 0x714c, 0x81ff, 0x01c0, 0x2071,
-	0x0100, 0x9188, 0x0008, 0x2114, 0x928e, 0x0006, 0x1138, 0x2009,
-	0x1984, 0x2011, 0x0012, 0x080c, 0x2ae2, 0x0048, 0x928e, 0x0009,
-	0x0db0, 0x2009, 0x1984, 0x2011, 0x0016, 0x080c, 0x2ae2, 0x00ee,
-	0x002e, 0x0005, 0x9036, 0x2001, 0x19f2, 0x2004, 0x9005, 0x0128,
-	0x9c06, 0x0128, 0x2c30, 0x600c, 0x0cc8, 0x9085, 0x0001, 0x0005,
-	0x00f6, 0x2079, 0x19e8, 0x610c, 0x9006, 0x600e, 0x6044, 0xc0fc,
-	0x6046, 0x86ff, 0x1140, 0x7824, 0x9c06, 0x1118, 0x7826, 0x782a,
-	0x0050, 0x792a, 0x0040, 0x00c6, 0x2660, 0x610e, 0x00ce, 0x7824,
-	0x9c06, 0x1108, 0x7e26, 0x080c, 0xa65d, 0x080c, 0xd10c, 0x00fe,
-	0x0005, 0x080c, 0x9ef8, 0x7003, 0x1200, 0x7838, 0x7012, 0x783c,
-	0x7016, 0x00c6, 0x7820, 0x9086, 0x0004, 0x1148, 0x7810, 0x9005,
-	0x0130, 0x00b6, 0x2058, 0xb810, 0xb914, 0x00be, 0x0020, 0x2061,
-	0x1800, 0x607c, 0x6180, 0x9084, 0x00ff, 0x700a, 0x710e, 0x00ce,
-	0x60c3, 0x002c, 0x0804, 0xa270, 0x080c, 0x9ef8, 0x7003, 0x0f00,
-	0x7808, 0xd09c, 0x0128, 0xb810, 0x9084, 0x00ff, 0x700a, 0xb814,
-	0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x0156, 0x080c, 0x9f43,
-	0x7003, 0x0200, 0x080c, 0x8b10, 0x20a9, 0x0006, 0x2011, 0xffec,
-	0x2019, 0xffed, 0x9ef0, 0x0002, 0x2305, 0x2072, 0x8e70, 0x2205,
-	0x2072, 0x8e70, 0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xa484,
-	0x60c3, 0x001c, 0x015e, 0x0804, 0xa270, 0x0016, 0x0026, 0x080c,
-	0x9f1f, 0x080c, 0x9f31, 0x9e80, 0x0004, 0x20e9, 0x0000, 0x20a0,
-	0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0, 0xa85c,
-	0x9080, 0x0021, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002, 0x21a8,
-	0x9192, 0x0010, 0x1250, 0x4003, 0x9080, 0x0004, 0x8003, 0x60c2,
-	0x080c, 0xa270, 0x002e, 0x001e, 0x0005, 0x20a9, 0x0010, 0x4003,
-	0x080c, 0xaadc, 0x20a1, 0x0240, 0x22a8, 0x4003, 0x0c68, 0x080c,
-	0x9ef8, 0x7003, 0x6200, 0x7808, 0x700e, 0x60c3, 0x0008, 0x0804,
-	0xa270, 0x0016, 0x0026, 0x080c, 0x9ef8, 0x20e9, 0x0000, 0x20a1,
-	0x024c, 0x7814, 0x0096, 0x2048, 0xa800, 0x2048, 0xa860, 0x20e0,
-	0xa85c, 0x9080, 0x0023, 0x2098, 0x009e, 0x7808, 0x9088, 0x0002,
-	0x21a8, 0x4003, 0x8003, 0x60c2, 0x080c, 0xa270, 0x002e, 0x001e,
-	0x0005, 0x00e6, 0x00c6, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x19e8, 0x7010, 0x2060, 0x8cff, 0x0188, 0x080c, 0xd132, 0x1110,
-	0x080c, 0xbb5c, 0x600c, 0x0006, 0x080c, 0xd3ae, 0x600f, 0x0000,
-	0x080c, 0xb16c, 0x080c, 0xa65d, 0x00ce, 0x0c68, 0x2c00, 0x7012,
-	0x700e, 0x012e, 0x000e, 0x00ce, 0x00ee, 0x0005, 0x0126, 0x0156,
-	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006,
-	0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xe7ff, 0x2102,
-	0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x19e8, 0x7030, 0x2060,
-	0x8cff, 0x0548, 0x080c, 0xa2a0, 0x6ac0, 0x68c3, 0x0000, 0x080c,
-	0x8a4b, 0x00c6, 0x2061, 0x0100, 0x080c, 0xac2d, 0x00ce, 0x20a9,
-	0x01f4, 0x04b1, 0x080c, 0x99ed, 0x6044, 0xd0ac, 0x1128, 0x2001,
-	0x1988, 0x2004, 0x604a, 0x0020, 0x2009, 0x0013, 0x080c, 0xb20a,
-	0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe,
-	0x015e, 0x012e, 0x0005, 0x2001, 0x1800, 0x2004, 0x9096, 0x0001,
-	0x0d78, 0x9096, 0x0004, 0x0d60, 0x080c, 0x8a4b, 0x6814, 0x9084,
-	0x0001, 0x0110, 0x68a7, 0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000,
-	0x2011, 0x6002, 0x080c, 0x8993, 0x20a9, 0x01f4, 0x0009, 0x08c0,
-	0x6824, 0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000,
-	0x190c, 0x2aa9, 0x0090, 0xd084, 0x0118, 0x6827, 0x4001, 0x0010,
-	0x1f04, 0xa578, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100,
-	0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x0005, 0x0126, 0x0156,
-	0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066, 0x0026, 0x0016, 0x0006,
-	0x2091, 0x8000, 0x2001, 0x180c, 0x200c, 0x918c, 0xdbff, 0x2102,
-	0x2069, 0x0100, 0x2079, 0x0140, 0x2071, 0x0380, 0x701c, 0x0006,
-	0x701f, 0x0202, 0x2071, 0x19e8, 0x704c, 0x2060, 0x8cff, 0x0904,
-	0xa619, 0x080c, 0xaf84, 0x0904, 0xa619, 0x9386, 0x0002, 0x1128,
-	0x6814, 0x9084, 0x0002, 0x0904, 0xa619, 0x68af, 0x95f5, 0x6817,
-	0x0010, 0x2009, 0x00fa, 0x8109, 0x1df0, 0x69c6, 0x68cb, 0x0008,
-	0x080c, 0x8a58, 0x080c, 0x1e44, 0x2001, 0x0032, 0x6920, 0xd1bc,
-	0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x0016,
-	0x2009, 0x0040, 0x080c, 0x2220, 0x001e, 0x20a9, 0x03e8, 0x6824,
-	0xd094, 0x0140, 0x6827, 0x0004, 0x7804, 0x9084, 0x4000, 0x190c,
-	0x2aa9, 0x0090, 0xd08c, 0x0118, 0x6827, 0x0002, 0x0010, 0x1f04,
-	0xa5e7, 0x7804, 0x9084, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c,
-	0x2a99, 0x9006, 0x080c, 0x2a99, 0x6827, 0x4000, 0x6824, 0x83ff,
-	0x1180, 0x2009, 0x0049, 0x6020, 0x9086, 0x0009, 0x0150, 0x080c,
-	0x9a48, 0x6044, 0xd0ac, 0x1118, 0x6003, 0x0002, 0x0010, 0x080c,
-	0xb20a, 0x000e, 0x2071, 0x0380, 0xd08c, 0x1110, 0x701f, 0x0200,
-	0x000e, 0x001e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe,
-	0x015e, 0x012e, 0x0005, 0x00d6, 0x0126, 0x2091, 0x8000, 0x2069,
-	0x19e8, 0x6a06, 0x012e, 0x00de, 0x0005, 0x00d6, 0x0126, 0x2091,
-	0x8000, 0x2069, 0x19e8, 0x6a3e, 0x012e, 0x00de, 0x0005, 0x080c,
-	0xa050, 0x7047, 0x1000, 0x0098, 0x080c, 0xa050, 0x7047, 0x4000,
-	0x0070, 0x080c, 0xa050, 0x7047, 0x2000, 0x0048, 0x080c, 0xa050,
-	0x7047, 0x0400, 0x0020, 0x080c, 0xa050, 0x7047, 0x0200, 0x785c,
-	0x7032, 0x60c3, 0x0020, 0x0804, 0xa270, 0x00e6, 0x2071, 0x19e8,
-	0x702c, 0x9005, 0x0110, 0x8001, 0x702e, 0x00ee, 0x0005, 0x00f6,
-	0x00e6, 0x00d6, 0x00c6, 0x0076, 0x0066, 0x0006, 0x0126, 0x2091,
-	0x8000, 0x2071, 0x19e8, 0x7620, 0x2660, 0x2678, 0x2039, 0x0001,
-	0x87ff, 0x0904, 0xa702, 0x8cff, 0x0904, 0xa702, 0x6020, 0x9086,
-	0x0006, 0x1904, 0xa6fd, 0x88ff, 0x0138, 0x2800, 0x9c06, 0x1904,
-	0xa6fd, 0x2039, 0x0000, 0x0050, 0x6010, 0x9b06, 0x1904, 0xa6fd,
-	0x85ff, 0x0120, 0x605c, 0x9106, 0x1904, 0xa6fd, 0x7030, 0x9c06,
-	0x15b0, 0x2069, 0x0100, 0x68c0, 0x9005, 0x1160, 0x6824, 0xd084,
-	0x0148, 0x6827, 0x0001, 0x080c, 0x8a4b, 0x080c, 0xa78a, 0x7033,
-	0x0000, 0x0428, 0x080c, 0x8a4b, 0x6820, 0xd0b4, 0x0110, 0x68a7,
-	0x95f5, 0x6817, 0x0008, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033,
-	0x0000, 0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138,
-	0x2001, 0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069,
-	0x0100, 0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7020,
-	0x9c36, 0x1110, 0x660c, 0x7622, 0x701c, 0x9c36, 0x1140, 0x2c00,
-	0x9f36, 0x0118, 0x2f00, 0x701e, 0x0010, 0x701f, 0x0000, 0x660c,
-	0x0066, 0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x89ff,
-	0x1168, 0x600f, 0x0000, 0x6014, 0x0096, 0x2048, 0x080c, 0xcf19,
-	0x0110, 0x080c, 0xea30, 0x009e, 0x080c, 0xb1a7, 0x080c, 0xa65d,
-	0x88ff, 0x1190, 0x00ce, 0x0804, 0xa678, 0x2c78, 0x600c, 0x2060,
-	0x0804, 0xa678, 0x9006, 0x012e, 0x000e, 0x006e, 0x007e, 0x00ce,
-	0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x98c5,
-	0x0001, 0x0c88, 0x00f6, 0x00e6, 0x00d6, 0x0096, 0x00c6, 0x0066,
-	0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7648,
-	0x2660, 0x2678, 0x8cff, 0x0904, 0xa779, 0x6020, 0x9086, 0x0006,
-	0x1904, 0xa774, 0x87ff, 0x0128, 0x2700, 0x9c06, 0x1904, 0xa774,
-	0x0048, 0x6010, 0x9b06, 0x1904, 0xa774, 0x85ff, 0x0118, 0x605c,
-	0x9106, 0x15d0, 0x704c, 0x9c06, 0x1178, 0x0036, 0x2019, 0x0001,
-	0x080c, 0xa596, 0x703f, 0x0000, 0x9006, 0x704e, 0x706a, 0x7052,
-	0x706e, 0x080c, 0xaff4, 0x003e, 0x7048, 0x9c36, 0x1110, 0x660c,
-	0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00,
-	0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06,
-	0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6014, 0x2048,
-	0x080c, 0xcf19, 0x0110, 0x080c, 0xea30, 0x080c, 0xb1a7, 0x87ff,
-	0x1198, 0x00ce, 0x0804, 0xa722, 0x2c78, 0x600c, 0x2060, 0x0804,
-	0xa722, 0x9006, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x009e,
-	0x00de, 0x00ee, 0x00fe, 0x0005, 0x601b, 0x0000, 0x00ce, 0x97bd,
-	0x0001, 0x0c80, 0x00e6, 0x2071, 0x19e8, 0x9006, 0x7032, 0x700a,
-	0x7004, 0x9086, 0x0003, 0x0158, 0x2001, 0x1800, 0x2004, 0x9086,
-	0x0002, 0x1118, 0x7007, 0x0005, 0x0010, 0x7007, 0x0000, 0x00ee,
-	0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0066, 0x0026, 0x0006, 0x0126,
-	0x2091, 0x8000, 0x2071, 0x19e8, 0x2c10, 0x7648, 0x2660, 0x2678,
-	0x8cff, 0x0540, 0x2200, 0x9c06, 0x1508, 0x7048, 0x9c36, 0x1110,
-	0x660c, 0x764a, 0x7044, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118,
-	0x2f00, 0x7046, 0x0010, 0x7047, 0x0000, 0x660c, 0x2c00, 0x9f06,
-	0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x6004, 0x9086,
-	0x0040, 0x090c, 0x99ed, 0x9085, 0x0001, 0x0020, 0x2c78, 0x600c,
-	0x2060, 0x08b0, 0x012e, 0x000e, 0x002e, 0x006e, 0x00ce, 0x00ee,
-	0x00fe, 0x0005, 0x0096, 0x00f6, 0x00e6, 0x00d6, 0x00c6, 0x0066,
-	0x0026, 0x0006, 0x0126, 0x2091, 0x8000, 0x2071, 0x19e8, 0x7610,
-	0x2660, 0x2678, 0x8cff, 0x0904, 0xa877, 0x6010, 0x00b6, 0x2058,
-	0xb8a0, 0x00be, 0x9206, 0x1904, 0xa872, 0x7030, 0x9c06, 0x1520,
-	0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xa849, 0x080c, 0xa2a0,
-	0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000, 0x0036, 0x2069,
-	0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100, 0x080c,
-	0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824, 0xd084,
-	0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36, 0x1110, 0x660c,
-	0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36, 0x0118, 0x2f00,
-	0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066, 0x2c00, 0x9f06,
-	0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000, 0x080c, 0xd121,
-	0x1180, 0x080c, 0x3344, 0x080c, 0xd132, 0x1518, 0x080c, 0xbb5c,
-	0x0400, 0x080c, 0xa78a, 0x6824, 0xd084, 0x09b0, 0x6827, 0x0001,
-	0x0898, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c, 0x0090, 0x6014,
-	0x2048, 0x080c, 0xcf19, 0x0168, 0x6020, 0x9086, 0x0003, 0x1508,
-	0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c, 0x7006, 0x080c,
-	0xd10c, 0x080c, 0xd3ae, 0x080c, 0xb1a7, 0x080c, 0xa65d, 0x00ce,
-	0x0804, 0xa7f2, 0x2c78, 0x600c, 0x2060, 0x0804, 0xa7f2, 0x012e,
-	0x000e, 0x002e, 0x006e, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x009e,
-	0x0005, 0x6020, 0x9086, 0x0006, 0x1d20, 0x080c, 0xea30, 0x0c08,
-	0x00d6, 0x080c, 0x9f43, 0x7003, 0x0200, 0x7007, 0x0014, 0x60c3,
-	0x0014, 0x20e1, 0x0001, 0x2099, 0x1989, 0x20e9, 0x0000, 0x20a1,
-	0x0250, 0x20a9, 0x0004, 0x4003, 0x7023, 0x0004, 0x7027, 0x7878,
-	0x080c, 0xa270, 0x00de, 0x0005, 0x080c, 0x9f43, 0x700b, 0x0800,
-	0x7814, 0x9084, 0xff00, 0x700e, 0x7814, 0x9084, 0x00ff, 0x7022,
-	0x782c, 0x7026, 0x7860, 0x9084, 0x00ff, 0x9085, 0x0200, 0x7002,
-	0x7860, 0x9084, 0xff00, 0x8007, 0x7006, 0x60c2, 0x0804, 0xa270,
-	0x00b6, 0x00d6, 0x0016, 0x00d6, 0x2f68, 0x2009, 0x0035, 0x080c,
-	0xd5bb, 0x00de, 0x1904, 0xa925, 0x080c, 0x9ef8, 0x7003, 0x1300,
-	0x782c, 0x080c, 0xaa34, 0x2068, 0x6820, 0x9086, 0x0003, 0x0560,
-	0x7810, 0x2058, 0xbaa0, 0x080c, 0xb094, 0x11d8, 0x9286, 0x007e,
-	0x1128, 0x700b, 0x00ff, 0x700f, 0xfffe, 0x0498, 0x9286, 0x007f,
-	0x1128, 0x700b, 0x00ff, 0x700f, 0xfffd, 0x0458, 0x9284, 0xff80,
-	0x0180, 0x9286, 0x0080, 0x1128, 0x700b, 0x00ff, 0x700f, 0xfffc,
-	0x0400, 0x92d8, 0x1000, 0x2b5c, 0xb810, 0x700a, 0xb814, 0x700e,
-	0x00c0, 0xb884, 0x700e, 0x00a8, 0x080c, 0xb094, 0x1130, 0x7810,
-	0x2058, 0xb8a0, 0x9082, 0x007e, 0x0250, 0x00d6, 0x2069, 0x181f,
-	0x2d04, 0x700a, 0x8d68, 0x2d04, 0x700e, 0x00de, 0x0010, 0x6034,
-	0x700e, 0x7838, 0x7012, 0x783c, 0x7016, 0x60c3, 0x000c, 0x001e,
-	0x00de, 0x080c, 0xa270, 0x00be, 0x0005, 0x781b, 0x0001, 0x7803,
-	0x0006, 0x001e, 0x00de, 0x00be, 0x0005, 0x792c, 0x9180, 0x0008,
-	0x200c, 0x9186, 0x0006, 0x01c0, 0x9186, 0x0003, 0x0904, 0xa9a4,
-	0x9186, 0x0005, 0x0904, 0xa98c, 0x9186, 0x0004, 0x05f0, 0x9186,
-	0x0008, 0x0904, 0xa995, 0x7807, 0x0037, 0x782f, 0x0003, 0x7817,
-	0x1700, 0x080c, 0xaa11, 0x0005, 0x080c, 0xa9d2, 0x00d6, 0x0026,
-	0x792c, 0x2168, 0x2009, 0x4000, 0x6800, 0x6a44, 0xd2fc, 0x11f8,
-	0x0002, 0xa96c, 0xa977, 0xa96e, 0xa977, 0xa973, 0xa96c, 0xa96c,
-	0xa977, 0xa977, 0xa977, 0xa977, 0xa96c, 0xa96c, 0xa96c, 0xa96c,
-	0xa96c, 0xa977, 0xa96c, 0xa977, 0x080c, 0x0d85, 0x6824, 0xd0e4,
-	0x0110, 0xd0cc, 0x0110, 0x900e, 0x0010, 0x2009, 0x2000, 0x682c,
-	0x7022, 0x6830, 0x7026, 0x0804, 0xa9cb, 0x080c, 0xa9d2, 0x00d6,
-	0x0026, 0x792c, 0x2168, 0x2009, 0x4000, 0x6a00, 0x9286, 0x0002,
-	0x1108, 0x900e, 0x0804, 0xa9cb, 0x080c, 0xa9d2, 0x00d6, 0x0026,
-	0x792c, 0x2168, 0x2009, 0x4000, 0x04b0, 0x04e1, 0x00d6, 0x0026,
-	0x792c, 0x2168, 0x2009, 0x4000, 0x9286, 0x0005, 0x0118, 0x9286,
-	0x0002, 0x1108, 0x900e, 0x0438, 0x0469, 0x00d6, 0x0026, 0x792c,
-	0x2168, 0x6814, 0x6924, 0xc185, 0x6926, 0x0096, 0x2048, 0xa9ac,
-	0xa834, 0x9112, 0xa9b0, 0xa838, 0x009e, 0x9103, 0x7022, 0x7226,
-	0x792c, 0x9180, 0x0011, 0x2004, 0xd0fc, 0x1148, 0x9180, 0x0000,
-	0x2004, 0x908e, 0x0002, 0x0130, 0x908e, 0x0004, 0x0118, 0x2009,
-	0x4000, 0x0008, 0x900e, 0x712a, 0x60c3, 0x0018, 0x002e, 0x00de,
-	0x0804, 0xa270, 0x00b6, 0x0036, 0x0046, 0x0056, 0x0066, 0x080c,
-	0x9f43, 0x9006, 0x7003, 0x0200, 0x7938, 0x710a, 0x793c, 0x710e,
-	0x7810, 0x2058, 0xb8a0, 0x080c, 0xb094, 0x1118, 0x9092, 0x007e,
-	0x0268, 0x00d6, 0x2069, 0x181f, 0x2d2c, 0x8d68, 0x2d34, 0x90d8,
-	0x1000, 0x2b5c, 0xbb10, 0xbc14, 0x00de, 0x0028, 0x901e, 0xbc84,
-	0x2029, 0x0000, 0x6634, 0x782c, 0x9080, 0x0008, 0x2004, 0x9086,
-	0x0003, 0x1128, 0x7512, 0x7616, 0x731a, 0x741e, 0x0020, 0x7312,
-	0x7416, 0x751a, 0x761e, 0x006e, 0x005e, 0x004e, 0x003e, 0x00be,
-	0x0005, 0x080c, 0x9f43, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814,
-	0x700e, 0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x080c, 0x9eef,
-	0x7003, 0x1400, 0x7838, 0x700a, 0x0079, 0x783c, 0x700e, 0x782c,
-	0x7012, 0x7830, 0x7016, 0x7834, 0x9084, 0x00ff, 0x8007, 0x701a,
-	0x60c3, 0x0010, 0x0804, 0xa270, 0x00e6, 0x2071, 0x0240, 0x0006,
-	0x00f6, 0x2078, 0x7810, 0x00b6, 0x2058, 0xb8d4, 0xd084, 0x0120,
-	0x784c, 0x702a, 0x7850, 0x702e, 0x00be, 0x00fe, 0x000e, 0x00ee,
-	0x0005, 0x080c, 0x9f3a, 0x7003, 0x0100, 0x782c, 0x700a, 0x7814,
-	0x700e, 0x60c3, 0x0008, 0x0804, 0xa270, 0x00a9, 0x7914, 0x712a,
-	0x60c3, 0x0000, 0x60a7, 0x9575, 0x0026, 0x080c, 0x2a04, 0x0228,
-	0x2011, 0x0101, 0x2204, 0xc0c5, 0x2012, 0x002e, 0x080c, 0xa293,
-	0x080c, 0x8a42, 0x0005, 0x0036, 0x0096, 0x00d6, 0x00e6, 0x7860,
-	0x2048, 0xaa7c, 0x9296, 0x00c0, 0x9294, 0x00fd, 0xaa7e, 0xaa80,
-	0x9294, 0x0300, 0xaa82, 0xa96c, 0x9194, 0x00ff, 0xab74, 0x9384,
-	0x00ff, 0x908d, 0xc200, 0xa96e, 0x9384, 0xff00, 0x9215, 0xaa76,
-	0xa870, 0xaa78, 0xa87a, 0xaa72, 0x00d6, 0x2069, 0x0200, 0x080c,
-	0xaaf1, 0x00de, 0x20e9, 0x0000, 0x20a1, 0x0240, 0x20a9, 0x000a,
-	0xa860, 0x20e0, 0xa85c, 0x9080, 0x001b, 0x2098, 0x4003, 0x60a3,
-	0x0035, 0xaa68, 0x9294, 0x7000, 0x9286, 0x3000, 0x0110, 0x60a3,
-	0x0037, 0x00ee, 0x00de, 0x009e, 0x003e, 0x0005, 0x900e, 0x7814,
-	0x0096, 0x2048, 0xa87c, 0xd0fc, 0x01c0, 0x9084, 0x0003, 0x11a8,
-	0x2001, 0x180c, 0x2004, 0xd0bc, 0x0180, 0x7824, 0xd0cc, 0x1168,
-	0xd0c4, 0x1158, 0xa8a8, 0x9005, 0x1140, 0x2001, 0x180c, 0x200c,
-	0xc1d5, 0x2102, 0x2009, 0x19b3, 0x210c, 0x009e, 0x918d, 0x0092,
-	0x0010, 0x2009, 0x0096, 0x60ab, 0x0036, 0x0026, 0x2110, 0x900e,
-	0x080c, 0x2ae2, 0x002e, 0x0005, 0x2009, 0x0009, 0x00a0, 0x2009,
-	0x000a, 0x0088, 0x2009, 0x000b, 0x0070, 0x2009, 0x000c, 0x0058,
-	0x2009, 0x000d, 0x0040, 0x2009, 0x000e, 0x0028, 0x2009, 0x000f,
-	0x0010, 0x2009, 0x0008, 0x6912, 0x0005, 0x080c, 0x9ef8, 0x0016,
-	0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013, 0x0138, 0x2001,
-	0x1837, 0x2004, 0x9084, 0x0028, 0x1138, 0x2001, 0x197c, 0x2004,
-	0x9086, 0xaaaa, 0x1904, 0xab96, 0x7003, 0x5400, 0x00c6, 0x2061,
-	0x1800, 0x607c, 0x9084, 0x00ff, 0xa998, 0x810f, 0x918c, 0xff00,
-	0x9105, 0x700a, 0x6080, 0x700e, 0xa998, 0x918c, 0xff00, 0x7112,
-	0x20a9, 0x0004, 0x2009, 0x1805, 0x2e10, 0x9290, 0x0006, 0x2104,
-	0x2012, 0x8108, 0x8210, 0x1f04, 0xab27, 0x20a9, 0x0004, 0x2009,
-	0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xab31, 0xa860,
-	0x20e0, 0xa85c, 0x9080, 0x0029, 0x2098, 0x2009, 0x0006, 0x20a9,
-	0x0001, 0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0x00d6,
-	0x2069, 0x0200, 0x080c, 0xaadc, 0x00de, 0x2071, 0x0240, 0x2011,
-	0x0240, 0x2009, 0x0002, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012,
-	0x8210, 0x8109, 0x1dc0, 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002,
-	0x8007, 0x2012, 0x8210, 0x8109, 0x1dc0, 0xa85c, 0x9080, 0x0031,
-	0x2098, 0x2009, 0x0008, 0x20a9, 0x0001, 0x4002, 0x8007, 0x2012,
-	0x8210, 0x8109, 0x1dc0, 0x00ce, 0x60c3, 0x004c, 0x60a3, 0x0056,
-	0x60a7, 0x9575, 0x2001, 0x1837, 0x2004, 0x9084, 0x0028, 0x1168,
-	0x080c, 0x779e, 0x0150, 0x6028, 0xc0bd, 0x602a, 0x2009, 0x1804,
-	0x2011, 0x0029, 0x080c, 0x2ae2, 0x0010, 0x080c, 0xa270, 0x080c,
-	0x8a42, 0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x2071,
-	0x0240, 0x2001, 0x2200, 0x9085, 0x00ff, 0x7002, 0x7007, 0xffff,
-	0x2071, 0x0100, 0x709b, 0x00ff, 0x00ee, 0x0804, 0xab0c, 0x080c,
-	0x9ef8, 0x0016, 0x0026, 0x0096, 0x00d6, 0x7814, 0x2048, 0x7013,
-	0x0138, 0x7003, 0x5500, 0x00c6, 0xa89c, 0x9084, 0x00ff, 0xa998,
-	0x810f, 0x918c, 0xff00, 0x9105, 0x700a, 0xa99c, 0x918c, 0xff00,
-	0xa8a0, 0x9084, 0x00ff, 0x9105, 0x700e, 0xa998, 0x918c, 0xff00,
-	0x2061, 0x1800, 0x607c, 0x9084, 0x00ff, 0x910d, 0x7112, 0x6180,
-	0x7116, 0x2009, 0x0008, 0xa860, 0x20e0, 0xa85c, 0x9080, 0x0029,
-	0x2098, 0x2e10, 0x9290, 0x0006, 0x20a9, 0x0001, 0x4002, 0x8007,
-	0x2012, 0x8210, 0x8109, 0x1dc0, 0x20a9, 0x0004, 0x2009, 0x1805,
-	0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xabe8, 0x20a9, 0x0002,
-	0x2009, 0x1801, 0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xabf2,
-	0x00d6, 0x0016, 0x2069, 0x0200, 0x080c, 0xaadc, 0x001e, 0x00de,
-	0x2071, 0x0240, 0x20a9, 0x0002, 0x2009, 0x1803, 0x2011, 0x0240,
-	0x2104, 0x2012, 0x8108, 0x8210, 0x1f04, 0xac08, 0x2009, 0x0008,
-	0x4002, 0x8007, 0x2012, 0x8210, 0x8109, 0x1dd0, 0x9006, 0x20a9,
-	0x0008, 0x2012, 0x8210, 0x1f04, 0xac19, 0x00ce, 0x60c3, 0x004c,
-	0x60a3, 0x0056, 0x60a7, 0x9575, 0x080c, 0xa270, 0x080c, 0x8a42,
-	0x00de, 0x009e, 0x002e, 0x001e, 0x0005, 0x00d6, 0x9290, 0x0018,
-	0x8214, 0x20e9, 0x0000, 0x2069, 0x0200, 0x6813, 0x0000, 0x22a8,
-	0x9284, 0x00e0, 0x0128, 0x20a9, 0x0020, 0x9292, 0x0020, 0x0008,
-	0x9016, 0x20a1, 0x0240, 0x9006, 0x4004, 0x82ff, 0x0120, 0x6810,
-	0x8000, 0x6812, 0x0c60, 0x00de, 0x0005, 0x00f6, 0x00e6, 0x00d6,
-	0x00c6, 0x00a6, 0x0096, 0x0066, 0x0126, 0x2091, 0x8000, 0x2071,
-	0x19e8, 0x7610, 0x2660, 0x2678, 0x8cff, 0x0904, 0xacd9, 0x7030,
-	0x9c06, 0x1520, 0x2069, 0x0100, 0x68c0, 0x9005, 0x0904, 0xacab,
-	0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a, 0x7033, 0x0000,
-	0x0036, 0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001,
-	0x0100, 0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100,
-	0x6824, 0xd084, 0x0110, 0x6827, 0x0001, 0x003e, 0x7010, 0x9c36,
-	0x1110, 0x660c, 0x7612, 0x700c, 0x9c36, 0x1140, 0x2c00, 0x9f36,
-	0x0118, 0x2f00, 0x700e, 0x0010, 0x700f, 0x0000, 0x660c, 0x0066,
-	0x2c00, 0x9f06, 0x0110, 0x7e0e, 0x0008, 0x2678, 0x600f, 0x0000,
-	0x080c, 0xd121, 0x1180, 0x080c, 0x3344, 0x080c, 0xd132, 0x1518,
-	0x080c, 0xbb5c, 0x0400, 0x080c, 0xa78a, 0x6824, 0xd084, 0x09b0,
-	0x6827, 0x0001, 0x0898, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c,
-	0x0090, 0x6014, 0x2048, 0x080c, 0xcf19, 0x0168, 0x6020, 0x9086,
-	0x0003, 0x1520, 0xa867, 0x0103, 0xab7a, 0xa877, 0x0000, 0x080c,
-	0x7012, 0x080c, 0xd10c, 0x080c, 0xd3ae, 0x080c, 0xb1a7, 0x080c,
-	0xa65d, 0x00ce, 0x0804, 0xac5c, 0x2c78, 0x600c, 0x2060, 0x0804,
-	0xac5c, 0x7013, 0x0000, 0x700f, 0x0000, 0x012e, 0x006e, 0x009e,
-	0x00ae, 0x00ce, 0x00de, 0x00ee, 0x00fe, 0x0005, 0x6020, 0x9086,
-	0x0006, 0x1d08, 0x080c, 0xea30, 0x08f0, 0x00f6, 0x0036, 0x2079,
-	0x0380, 0x7b18, 0xd3bc, 0x1de8, 0x7832, 0x7936, 0x7a3a, 0x781b,
-	0x8080, 0x003e, 0x00fe, 0x0005, 0x0016, 0x2001, 0x0382, 0x2004,
-	0x9084, 0x0007, 0x9086, 0x0001, 0x1188, 0x2001, 0x0015, 0x0c29,
-	0x2009, 0x1000, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086,
-	0x0003, 0x0120, 0x8109, 0x1db0, 0x080c, 0x0d85, 0x001e, 0x0005,
-	0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086, 0x0003, 0x1120,
-	0x2001, 0x0380, 0x2003, 0x0001, 0x0005, 0x0156, 0x0016, 0x0026,
-	0x00e6, 0x900e, 0x2071, 0x19e8, 0x0469, 0x0106, 0x0190, 0x7004,
-	0x9086, 0x0003, 0x0148, 0x20a9, 0x1000, 0x6044, 0xd0fc, 0x01d8,
-	0x1f04, 0xad35, 0x080c, 0x0d85, 0x080c, 0xacfc, 0x6044, 0xd0fc,
-	0x0190, 0x7030, 0x9c06, 0x1148, 0x080c, 0x99ed, 0x6044, 0xd0dc,
-	0x0150, 0xc0dc, 0x6046, 0x700a, 0x7042, 0x704c, 0x9c06, 0x190c,
-	0x0d85, 0x080c, 0x9a48, 0x010e, 0x1919, 0x00ee, 0x002e, 0x001e,
-	0x015e, 0x0005, 0x2001, 0x0382, 0x2004, 0x9084, 0x0007, 0x9086,
-	0x0003, 0x0005, 0x0126, 0x2091, 0x2400, 0x7808, 0xd0a4, 0x190c,
-	0x0d7e, 0xd09c, 0x0128, 0x7820, 0x908c, 0xf000, 0x11b8, 0x0012,
-	0x012e, 0x0005, 0xad82, 0xadc0, 0xadef, 0xae37, 0xae47, 0xae58,
-	0xae67, 0xae75, 0xaea2, 0xaea6, 0xad82, 0xad82, 0xaea9, 0xaec5,
-	0xad82, 0xad82, 0x080c, 0x0d85, 0x012e, 0x0005, 0x2060, 0x6044,
-	0xd0bc, 0x0140, 0xc0bc, 0x6046, 0x6000, 0x908a, 0x0010, 0x1a0c,
-	0x0d85, 0x0012, 0x012e, 0x0005, 0xada7, 0xada9, 0xada7, 0xadaf,
-	0xada7, 0xada7, 0xada7, 0xada7, 0xada7, 0xada9, 0xada7, 0xada9,
-	0xada7, 0xada9, 0xada7, 0xada7, 0xada7, 0xada9, 0xada7, 0x080c,
-	0x0d85, 0x2009, 0x0013, 0x080c, 0xb20a, 0x012e, 0x0005, 0x6014,
-	0x2048, 0xa87c, 0xd0dc, 0x0130, 0x080c, 0x8c19, 0x080c, 0xb16c,
-	0x012e, 0x0005, 0x2009, 0x0049, 0x080c, 0xb20a, 0x012e, 0x0005,
-	0x080c, 0xacfc, 0x2001, 0x1a0d, 0x2003, 0x0000, 0x7030, 0x9065,
-	0x1130, 0x7004, 0x9086, 0x0003, 0x01e0, 0x080c, 0x0d85, 0x7034,
-	0x9092, 0xc350, 0x1258, 0x8000, 0x7036, 0x7004, 0x9086, 0x0003,
-	0x0110, 0x7007, 0x0000, 0x781f, 0x0808, 0x0058, 0x080c, 0xb0c0,
-	0x0140, 0x080c, 0xeeee, 0x6003, 0x0001, 0x2009, 0x0014, 0x080c,
-	0xb20a, 0x781f, 0x0100, 0x080c, 0xad18, 0x012e, 0x0005, 0x080c,
-	0xacfc, 0x714c, 0x81ff, 0x1128, 0x2011, 0x1a10, 0x2013, 0x0000,
-	0x04c0, 0x2061, 0x0100, 0x7150, 0x9192, 0x7530, 0x1678, 0x8108,
-	0x7152, 0x714c, 0x9186, 0x1b55, 0x0120, 0x2001, 0x0391, 0x2003,
-	0x0400, 0x9188, 0x0008, 0x210c, 0x918e, 0x0006, 0x1160, 0x6014,
-	0x9084, 0x1984, 0x9085, 0x0012, 0x714c, 0x918e, 0x1b55, 0x1108,
-	0xc0fd, 0x6016, 0x00b0, 0x714c, 0x9188, 0x0008, 0x210c, 0x918e,
-	0x0009, 0x0d68, 0x6014, 0x9084, 0x1984, 0x9085, 0x0016, 0x714c,
-	0x918e, 0x1b55, 0x1108, 0xc0fd, 0x6016, 0x0018, 0x706c, 0xc085,
-	0x706e, 0x781f, 0x0200, 0x080c, 0xad18, 0x012e, 0x0005, 0x080c,
-	0xacfc, 0x714c, 0x2160, 0x6003, 0x0003, 0x2009, 0x004a, 0x080c,
-	0xb20a, 0x781f, 0x0200, 0x080c, 0xad18, 0x012e, 0x0005, 0x7808,
-	0xd09c, 0x0de8, 0x7820, 0x2060, 0x6003, 0x0003, 0x080c, 0xacfc,
-	0x080c, 0x1dcc, 0x781f, 0x0400, 0x080c, 0xad18, 0x012e, 0x0005,
-	0x7808, 0xd09c, 0x0de8, 0x7820, 0x2060, 0x080c, 0xacfc, 0x080c,
-	0x1e14, 0x781f, 0x0400, 0x080c, 0xad18, 0x012e, 0x0005, 0x7030,
-	0x9065, 0x0148, 0x6044, 0xc0bc, 0x6046, 0x7104, 0x9186, 0x0003,
-	0x0110, 0x080c, 0x9ab4, 0x012e, 0x0005, 0x00f6, 0x703c, 0x9086,
-	0x0002, 0x0528, 0x704c, 0x907d, 0x0510, 0x7844, 0xc0bc, 0x7846,
-	0x7820, 0x9086, 0x0009, 0x0118, 0x080c, 0xa1ca, 0x00c0, 0x7828,
-	0xd0fc, 0x1118, 0x080c, 0xa149, 0x0090, 0x2001, 0x1837, 0x2004,
-	0x9084, 0x0028, 0x1130, 0x2001, 0x197c, 0x2004, 0x9086, 0xaaaa,
-	0x1120, 0x2001, 0x0387, 0x2003, 0x1000, 0x080c, 0xa0ce, 0x00fe,
-	0x012e, 0x0005, 0x080c, 0x7840, 0x012e, 0x0005, 0x080c, 0x0d85,
-	0x0005, 0x2009, 0x1b66, 0x2104, 0xd0bc, 0x01a8, 0xc0bc, 0x200a,
-	0x2009, 0x010b, 0x2104, 0x9085, 0x0002, 0x200a, 0x2009, 0x0101,
-	0x2104, 0xc0ac, 0x200a, 0x2009, 0x0105, 0x2104, 0x9084, 0x1984,
-	0x9085, 0x8092, 0x200a, 0x012e, 0x0005, 0x080c, 0x8a58, 0x2009,
-	0x010b, 0x2104, 0xd08c, 0x01a8, 0xc08c, 0x200a, 0x2001, 0x1848,
-	0x2004, 0xd094, 0x1130, 0x2009, 0x0101, 0x2104, 0x9085, 0x0020,
-	0x200a, 0x2009, 0x1b66, 0x200b, 0x0000, 0x2001, 0x001b, 0x080c,
-	0xaced, 0x012e, 0x0005, 0x00e6, 0x2071, 0x19e8, 0x6044, 0xc0bc,
-	0x6046, 0xd0fc, 0x01b8, 0x704c, 0x9c06, 0x1190, 0x2019, 0x0001,
-	0x080c, 0xa596, 0x704f, 0x0000, 0x2001, 0x0109, 0x2004, 0xd08c,
-	0x1138, 0x2001, 0x0108, 0x2004, 0xd0bc, 0x1110, 0x703f, 0x0000,
-	0x080c, 0xa7a1, 0x00ee, 0x0005, 0x0026, 0x7010, 0x9c06, 0x1178,
-	0x080c, 0xa65d, 0x6044, 0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120,
-	0x7212, 0x600f, 0x0000, 0x0010, 0x7212, 0x720e, 0x9006, 0x002e,
-	0x0005, 0x0026, 0x7020, 0x9c06, 0x1178, 0x080c, 0xa65d, 0x6044,
-	0xc0fc, 0x6046, 0x600c, 0x9015, 0x0120, 0x7222, 0x600f, 0x0000,
-	0x0010, 0x7222, 0x721e, 0x9006, 0x002e, 0x0005, 0x00d6, 0x0036,
-	0x7830, 0x9c06, 0x1558, 0x2069, 0x0100, 0x68c0, 0x9005, 0x01f8,
-	0x080c, 0x8a4b, 0x080c, 0xa2a0, 0x68c3, 0x0000, 0x080c, 0xa78a,
-	0x2069, 0x0140, 0x6b04, 0x9384, 0x1000, 0x0138, 0x2001, 0x0100,
-	0x080c, 0x2a99, 0x9006, 0x080c, 0x2a99, 0x2069, 0x0100, 0x6824,
-	0xd084, 0x0110, 0x6827, 0x0001, 0x9085, 0x0001, 0x0038, 0x7808,
-	0xc0ad, 0x780a, 0x6003, 0x0009, 0x630a, 0x9006, 0x003e, 0x00de,
-	0x0005, 0x0016, 0x0026, 0x0036, 0x6100, 0x2019, 0x0100, 0x2001,
-	0x0382, 0x2004, 0xd09c, 0x0190, 0x00c6, 0x0126, 0x2091, 0x2800,
-	0x0016, 0x0036, 0x080c, 0xad62, 0x003e, 0x001e, 0x012e, 0x00ce,
-	0x6200, 0x2200, 0x9106, 0x0d58, 0x2200, 0x0010, 0x8319, 0x1d38,
-	0x003e, 0x002e, 0x001e, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x080c,
-	0xacfc, 0x0106, 0x2071, 0x19e8, 0x2069, 0x0100, 0x704c, 0x2060,
-	0x9086, 0x1b55, 0x15b8, 0x6814, 0xd08c, 0x0188, 0x6817, 0x0010,
-	0x2009, 0x0019, 0x8109, 0x1df0, 0x2001, 0x0032, 0x6920, 0xd1bc,
-	0x0130, 0x8001, 0x1dd8, 0x692c, 0x918d, 0x0008, 0x692e, 0x6824,
-	0xd08c, 0x0110, 0x6827, 0x0002, 0x68d0, 0x9005, 0x0118, 0x9082,
-	0x0005, 0x0238, 0x6060, 0x8000, 0x6062, 0x2001, 0x0391, 0x2003,
-	0x0400, 0x080c, 0x9a48, 0x682c, 0x9084, 0xfffd, 0x682e, 0x2001,
-	0x1848, 0x2004, 0xd094, 0x1120, 0x6804, 0x9085, 0x0020, 0x6806,
-	0x2069, 0x0000, 0x010e, 0x090c, 0xad18, 0x8dff, 0x00ce, 0x00de,
-	0x00ee, 0x0005, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0xacfc, 0x0106,
-	0x2071, 0x19e8, 0x2069, 0x0100, 0x080c, 0xaf84, 0x68d0, 0x9005,
-	0x0158, 0x9082, 0x0005, 0x1240, 0x080c, 0x2b33, 0x2001, 0x0391,
-	0x2003, 0x0400, 0x2069, 0x0000, 0x010e, 0x090c, 0xad18, 0x8dff,
-	0x00ce, 0x00de, 0x00ee, 0x0005, 0x0016, 0x2001, 0x0134, 0x2004,
-	0x9005, 0x0140, 0x9082, 0x0005, 0x1228, 0x2001, 0x0391, 0x2003,
-	0x0404, 0x0020, 0x2001, 0x0391, 0x2003, 0x0400, 0x001e, 0x0005,
-	0x00d6, 0x0156, 0x080c, 0x9f43, 0x7a14, 0x82ff, 0x0138, 0x7003,
-	0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0490, 0x7003, 0x0200,
-	0x7007, 0x0000, 0x2069, 0x1800, 0x901e, 0x6800, 0x9086, 0x0004,
-	0x1110, 0xc38d, 0x0060, 0x080c, 0x779e, 0x1110, 0xc3ad, 0x0008,
-	0xc3a5, 0x6adc, 0xd29c, 0x1110, 0xd2ac, 0x0108, 0xc39d, 0x730e,
-	0x080c, 0x8b10, 0x20a9, 0x0006, 0x2011, 0xffec, 0x2019, 0xffed,
-	0x2071, 0x0250, 0x2305, 0x2072, 0x8e70, 0x2205, 0x2072, 0x8e70,
-	0x9398, 0x0002, 0x9290, 0x0002, 0x1f04, 0xb03a, 0x60c3, 0x0020,
-	0x080c, 0xa270, 0x015e, 0x00de, 0x0005, 0x0156, 0x080c, 0x9f43,
-	0x7a14, 0x82ff, 0x0168, 0x9286, 0xffff, 0x0118, 0x9282, 0x000e,
-	0x1238, 0x7003, 0x0100, 0x700b, 0x0003, 0x60c3, 0x0008, 0x0488,
-	0x7003, 0x0200, 0x7007, 0x001c, 0x700f, 0x0001, 0x2011, 0x19be,
-	0x2204, 0x8007, 0x701a, 0x8210, 0x2204, 0x8007, 0x701e, 0x0421,
-	0x1120, 0xb8a0, 0x9082, 0x007f, 0x0248, 0x2001, 0x181f, 0x2004,
-	0x7022, 0x2001, 0x1820, 0x2004, 0x7026, 0x0030, 0x2001, 0x1818,
-	0x2004, 0x9084, 0x00ff, 0x7026, 0x20a9, 0x0004, 0x20e1, 0x0001,
-	0x2099, 0x1805, 0x20e9, 0x0000, 0x20a1, 0x0256, 0x4003, 0x60c3,
-	0x001c, 0x015e, 0x0804, 0xa270, 0x0006, 0x2001, 0x1837, 0x2004,
-	0xd0ac, 0x000e, 0x0005, 0x2011, 0x0003, 0x080c, 0xa62b, 0x2011,
-	0x0002, 0x080c, 0xa635, 0x080c, 0xa516, 0x0036, 0x901e, 0x080c,
-	0xa596, 0x003e, 0x0005, 0x080c, 0x3487, 0x0188, 0x0016, 0x00b6,
-	0x00c6, 0x7010, 0x9085, 0x0020, 0x7012, 0x2009, 0x007e, 0x080c,
-	0x67b4, 0xb85c, 0xc0ac, 0xb85e, 0x00ce, 0x00be, 0x001e, 0x0005,
-	0x00d6, 0x00f6, 0x7104, 0x9186, 0x0004, 0x1130, 0x7410, 0x9e90,
-	0x0004, 0x9e98, 0x0003, 0x0088, 0x9186, 0x0001, 0x1130, 0x7420,
-	0x9e90, 0x0008, 0x9e98, 0x0007, 0x0040, 0x9186, 0x0002, 0x1538,
-	0x7428, 0x9e90, 0x000a, 0x9e98, 0x0009, 0x6110, 0x2468, 0x680c,
-	0x907d, 0x01e8, 0x7810, 0x9106, 0x1128, 0x2f68, 0x780c, 0x907d,
-	0x1dc8, 0x00a8, 0x780c, 0x680e, 0x7c0e, 0x2f12, 0x2304, 0x9f06,
-	0x1108, 0x2d1a, 0x9006, 0x7032, 0x7036, 0x7004, 0x9086, 0x0003,
-	0x0110, 0x7007, 0x0000, 0x9006, 0x00fe, 0x00de, 0x0005, 0x9085,
-	0x0001, 0x0cd0, 0x2071, 0x188d, 0x7000, 0x9005, 0x0140, 0x2001,
-	0x0812, 0x2071, 0x1800, 0x7076, 0x707a, 0x706b, 0xffd4, 0x2071,
-	0x1800, 0x7074, 0x7056, 0x705b, 0x1ddc, 0x0005, 0x00e6, 0x0126,
-	0x2071, 0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0010, 0x0608,
-	0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c,
-	0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003,
-	0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1230,
-	0x755a, 0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1ddc,
-	0x0cc0, 0x9006, 0x0cc0, 0x00e6, 0x2071, 0x1800, 0x7554, 0x9582,
-	0x0010, 0x0600, 0x7058, 0x2060, 0x6000, 0x9086, 0x0000, 0x0148,
-	0x9ce0, 0x001c, 0x7068, 0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc,
-	0x0c98, 0x6003, 0x0008, 0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068,
-	0x9502, 0x1228, 0x755a, 0x9085, 0x0001, 0x00ee, 0x0005, 0x705b,
-	0x1ddc, 0x0cc8, 0x9006, 0x0cc8, 0x9c82, 0x1ddc, 0x0a0c, 0x0d85,
-	0x2001, 0x181a, 0x2004, 0x9c02, 0x1a0c, 0x0d85, 0x9006, 0x6006,
-	0x600a, 0x600e, 0x6016, 0x601a, 0x6012, 0x6023, 0x0000, 0x6003,
-	0x0000, 0x601e, 0x605e, 0x6062, 0x6026, 0x602a, 0x602e, 0x6032,
-	0x6036, 0x603a, 0x603e, 0x604a, 0x602a, 0x6046, 0x6042, 0x2061,
-	0x1800, 0x6054, 0x8000, 0x6056, 0x0005, 0x9006, 0x600e, 0x6016,
-	0x601a, 0x6012, 0x6022, 0x6002, 0x601e, 0x605e, 0x6062, 0x604a,
-	0x6046, 0x2061, 0x1800, 0x6054, 0x8000, 0x6056, 0x0005, 0x0006,
-	0x6000, 0x9086, 0x0000, 0x01d8, 0x601c, 0xd084, 0x190c, 0x1ad3,
-	0x6023, 0x0007, 0x2001, 0x1986, 0x2004, 0x0006, 0x9082, 0x0051,
-	0x000e, 0x0208, 0x8004, 0x601a, 0x080c, 0xece1, 0x604b, 0x0000,
-	0x6044, 0xd0fc, 0x1131, 0x9006, 0x6046, 0x6016, 0x6012, 0x000e,
-	0x0005, 0x080c, 0xacfc, 0x0106, 0x2001, 0x19fb, 0x2004, 0x9c06,
-	0x1130, 0x0036, 0x2019, 0x0001, 0x080c, 0xa596, 0x003e, 0x080c,
-	0xa7a1, 0x010e, 0x090c, 0xad18, 0x0005, 0x00e6, 0x0126, 0x2071,
-	0x1800, 0x2091, 0x8000, 0x7554, 0x9582, 0x0001, 0x0608, 0x7058,
-	0x2060, 0x6000, 0x9086, 0x0000, 0x0148, 0x9ce0, 0x001c, 0x7068,
-	0x9c02, 0x1208, 0x0cb0, 0x2061, 0x1ddc, 0x0c98, 0x6003, 0x0008,
-	0x8529, 0x7556, 0x9ca8, 0x001c, 0x7068, 0x9502, 0x1230, 0x755a,
-	0x9085, 0x0001, 0x012e, 0x00ee, 0x0005, 0x705b, 0x1ddc, 0x0cc0,
-	0x9006, 0x0cc0, 0x6020, 0x9084, 0x000f, 0x0002, 0xb21e, 0xb228,
-	0xb243, 0xb25e, 0xd69a, 0xd6b7, 0xd6d2, 0xb21e, 0xb228, 0x92f7,
-	0xb277, 0xb21e, 0xb21e, 0xb21e, 0xb21e, 0xb21e, 0x9186, 0x0013,
-	0x1130, 0x6044, 0xd0fc, 0x0110, 0x080c, 0x99ed, 0x0005, 0x0005,
-	0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e,
-	0x0005, 0xb241, 0xb9bc, 0xbba3, 0xb241, 0xbc39, 0xb540, 0xb241,
-	0xb241, 0xb93e, 0xc25a, 0xb241, 0xb241, 0xb241, 0xb241, 0xb241,
-	0xb241, 0x080c, 0x0d85, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c,
-	0x0d85, 0x0013, 0x006e, 0x0005, 0xb25c, 0xc875, 0xb25c, 0xb25c,
-	0xb25c, 0xb25c, 0xb25c, 0xb25c, 0xc80c, 0xc9f8, 0xb25c, 0xc8b2,
-	0xc936, 0xc8b2, 0xc936, 0xb25c, 0x080c, 0x0d85, 0x6000, 0x9082,
-	0x0010, 0x1a0c, 0x0d85, 0x6000, 0x0002, 0xb275, 0xc2a4, 0xc33e,
-	0xc4c1, 0xc530, 0xb275, 0xb275, 0xb275, 0xc273, 0xc78d, 0xc790,
-	0xb275, 0xb275, 0xb275, 0xb275, 0xc7c0, 0x080c, 0x0d85, 0x0066,
-	0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005,
-	0xb290, 0xb290, 0xb2ce, 0xb36d, 0xb3ed, 0xb290, 0xb290, 0xb290,
-	0xb292, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290, 0xb290,
-	0x080c, 0x0d85, 0x9186, 0x004c, 0x0560, 0x9186, 0x0003, 0x190c,
-	0x0d85, 0x0096, 0x601c, 0xc0ed, 0x601e, 0x6003, 0x0003, 0x6106,
-	0x6014, 0x2048, 0xa87c, 0x9084, 0xa000, 0xc0b5, 0xa87e, 0xa8ac,
-	0xa836, 0xa8b0, 0xa83a, 0x9006, 0xa846, 0xa84a, 0xa884, 0x9092,
-	0x199a, 0x0210, 0x2001, 0x1999, 0x8003, 0x8013, 0x8213, 0x9210,
-	0x621a, 0x009e, 0x080c, 0x1c26, 0x2009, 0x8030, 0x080c, 0x965e,
-	0x0005, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x080c,
-	0xb40f, 0x080c, 0xd65d, 0x6003, 0x0007, 0x0005, 0x00d6, 0x0096,
-	0x00f6, 0x2079, 0x1800, 0x7a90, 0x6014, 0x2048, 0xa87c, 0xd0ec,
-	0x1110, 0x9290, 0x0018, 0xac78, 0xc4fc, 0x0046, 0xa8e0, 0x9005,
-	0x1140, 0xa8dc, 0x921a, 0x0140, 0x0220, 0xa87b, 0x0007, 0x2010,
-	0x0028, 0xa87b, 0x0015, 0x0010, 0xa87b, 0x0000, 0x8214, 0xa883,
-	0x0000, 0xaa02, 0x0006, 0x0016, 0x0026, 0x00c6, 0x00d6, 0x00e6,
-	0x00f6, 0x2400, 0x9005, 0x1108, 0x009a, 0x2100, 0x9086, 0x0015,
-	0x1118, 0x2001, 0x0001, 0x0038, 0x2100, 0x9086, 0x0016, 0x0118,
-	0x2001, 0x0001, 0x002a, 0x94a4, 0x0007, 0x8423, 0x9405, 0x0002,
-	0xb335, 0xb335, 0xb330, 0xb333, 0xb335, 0xb32d, 0xb320, 0xb320,
-	0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320, 0xb320,
-	0x00fe, 0x00ee, 0x00de, 0x00ce, 0x002e, 0x001e, 0x000e, 0x004e,
-	0x00fe, 0x009e, 0x00de, 0x080c, 0x0d85, 0x080c, 0xbe51, 0x0028,
-	0x080c, 0xbf8f, 0x0010, 0x080c, 0xc085, 0x00fe, 0x00ee, 0x00de,
-	0x00ce, 0x002e, 0x001e, 0x2c00, 0xa896, 0x000e, 0x080c, 0xb4cd,
-	0x0530, 0xa804, 0xa80e, 0x00a6, 0x2050, 0xb100, 0x00ae, 0x8006,
-	0x8006, 0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002,
-	0xaacc, 0xabd0, 0xacd4, 0xadd8, 0x2031, 0x0000, 0x2041, 0x12c2,
-	0x080c, 0xb691, 0x0160, 0x000e, 0x9005, 0x0120, 0x00fe, 0x009e,
-	0x00de, 0x0005, 0x00fe, 0x009e, 0x00de, 0x0804, 0xb16c, 0x2001,
-	0x002c, 0x900e, 0x080c, 0xb533, 0x0c70, 0x91b6, 0x0015, 0x0170,
-	0x91b6, 0x0016, 0x0158, 0x91b2, 0x0047, 0x0a0c, 0x0d85, 0x91b2,
-	0x0050, 0x1a0c, 0x0d85, 0x9182, 0x0047, 0x0042, 0x080c, 0xaf61,
-	0x0120, 0x9086, 0x0002, 0x0904, 0xb2ce, 0x0005, 0xb38f, 0xb38f,
-	0xb391, 0xb3c3, 0xb38f, 0xb38f, 0xb38f, 0xb38f, 0xb3d6, 0x080c,
-	0x0d85, 0x00d6, 0x0016, 0x0096, 0x6003, 0x0004, 0x6114, 0x2148,
-	0xa87c, 0xd0fc, 0x01c0, 0xa878, 0xc0fc, 0x9005, 0x1158, 0xa894,
-	0x9005, 0x0140, 0x2001, 0x0000, 0x900e, 0x080c, 0xb533, 0x080c,
-	0xb16c, 0x00a8, 0x6003, 0x0002, 0xa8a4, 0xa9a8, 0x9105, 0x1178,
-	0xa8ae, 0xa8b2, 0x0c78, 0xa87f, 0x0020, 0xa88c, 0xa88a, 0xa8a4,
-	0xa8ae, 0xa8a8, 0xa8b2, 0xa8c7, 0x0000, 0xa8cb, 0x0000, 0x009e,
-	0x001e, 0x00de, 0x0005, 0x080c, 0x9a48, 0x00d6, 0x0096, 0x6114,
-	0x2148, 0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0006, 0x080c, 0x7012,
-	0x009e, 0x00de, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x080c, 0x9a48,
-	0x080c, 0x3315, 0x080c, 0xd65a, 0x00d6, 0x0096, 0x6114, 0x2148,
-	0x080c, 0xcf1b, 0x0120, 0xa87b, 0x0029, 0x080c, 0x7012, 0x009e,
-	0x00de, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x9182, 0x0047, 0x0002,
-	0xb3fd, 0xb3ff, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd,
-	0xb3fd, 0xb3fd, 0xb3fd, 0xb3fd, 0xb3ff, 0x080c, 0x0d85, 0x00d6,
-	0x0096, 0x601f, 0x0000, 0x6114, 0x2148, 0xa87b, 0x0000, 0xa883,
-	0x0000, 0x080c, 0x7012, 0x009e, 0x00de, 0x0804, 0xb16c, 0x0026,
-	0x0036, 0x0056, 0x0066, 0x0096, 0x00a6, 0x00f6, 0x0006, 0x080c,
-	0x1059, 0x000e, 0x090c, 0x0d85, 0xa960, 0x21e8, 0xa95c, 0x9188,
-	0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104, 0xa87a, 0x2079,
-	0x1800, 0x7990, 0x9188, 0x0018, 0x918c, 0x0fff, 0xa972, 0xac76,
-	0x2950, 0x00a6, 0x2001, 0x0205, 0x2003, 0x0000, 0x901e, 0x2029,
-	0x0001, 0x9182, 0x0035, 0x1228, 0x2011, 0x001f, 0x080c, 0xca7b,
-	0x04c0, 0x2130, 0x2009, 0x0034, 0x2011, 0x001f, 0x080c, 0xca7b,
-	0x96b2, 0x0034, 0xb004, 0x904d, 0x0110, 0x080c, 0x100b, 0x080c,
-	0x1059, 0x01d0, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920,
-	0xb406, 0x968a, 0x003d, 0x1230, 0x2608, 0x2011, 0x001b, 0x080c,
-	0xca7b, 0x00b8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011,
-	0x001b, 0x080c, 0xca7b, 0x0c18, 0x2001, 0x0205, 0x2003, 0x0000,
-	0x00ae, 0x852f, 0x95ad, 0x0050, 0xb566, 0xb070, 0xc0fd, 0xb072,
-	0x0048, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad,
-	0x0050, 0xb566, 0x2a48, 0xa804, 0xa807, 0x0000, 0x0006, 0x080c,
-	0x7012, 0x000e, 0x2048, 0x9005, 0x1db0, 0x00fe, 0x00ae, 0x009e,
-	0x006e, 0x005e, 0x003e, 0x002e, 0x0005, 0x00d6, 0x00f6, 0x0096,
-	0x0006, 0x080c, 0x1059, 0x000e, 0x090c, 0x0d85, 0xa960, 0x21e8,
-	0xa95c, 0x9188, 0x0019, 0x21a0, 0x900e, 0x20a9, 0x0020, 0x4104,
-	0xaa66, 0xa87a, 0x2079, 0x1800, 0x7990, 0x810c, 0x9188, 0x000c,
-	0x9182, 0x001a, 0x0210, 0x2009, 0x001a, 0x21a8, 0x810b, 0xa972,
-	0xac76, 0x2e98, 0xa85c, 0x9080, 0x001f, 0x20a0, 0x2001, 0x0205,
-	0x200c, 0x918d, 0x0080, 0x2102, 0x4003, 0x2003, 0x0000, 0x080c,
-	0x7012, 0x009e, 0x00fe, 0x00de, 0x0005, 0x0016, 0x00d6, 0x00f6,
-	0x0096, 0x0016, 0x2001, 0x0205, 0x200c, 0x918d, 0x0080, 0x2102,
-	0x001e, 0x2079, 0x0200, 0x2e98, 0xa87c, 0xd0ec, 0x0118, 0x9e80,
-	0x000c, 0x2098, 0x2021, 0x003e, 0x901e, 0x9282, 0x0020, 0x0218,
-	0x2011, 0x0020, 0x2018, 0x9486, 0x003e, 0x1170, 0x0096, 0x080c,
-	0x1059, 0x2900, 0x009e, 0x05c0, 0xa806, 0x2048, 0xa860, 0x20e8,
-	0xa85c, 0x9080, 0x0002, 0x20a0, 0x3300, 0x908e, 0x0260, 0x0140,
-	0x2009, 0x0280, 0x9102, 0x920a, 0x0218, 0x2010, 0x2100, 0x9318,
-	0x2200, 0x9402, 0x1228, 0x2400, 0x9202, 0x2410, 0x9318, 0x9006,
-	0x2020, 0x22a8, 0xa800, 0x9200, 0xa802, 0x20e1, 0x0000, 0x4003,
-	0x83ff, 0x0180, 0x3300, 0x9086, 0x0280, 0x1130, 0x7814, 0x8000,
-	0x9085, 0x0080, 0x7816, 0x2e98, 0x2310, 0x84ff, 0x0904, 0xb4e2,
-	0x0804, 0xb4e4, 0x9085, 0x0001, 0x7817, 0x0000, 0x009e, 0x00fe,
-	0x00de, 0x001e, 0x0005, 0x00d6, 0x0036, 0x0096, 0x6314, 0x2348,
-	0xa87a, 0xa982, 0x080c, 0x7006, 0x009e, 0x003e, 0x00de, 0x0005,
-	0x91b6, 0x0015, 0x1118, 0x080c, 0xb16c, 0x0030, 0x91b6, 0x0016,
-	0x190c, 0x0d85, 0x080c, 0xb16c, 0x0005, 0x20a9, 0x000e, 0x20e1,
-	0x0000, 0x2e98, 0x6014, 0x0096, 0x2048, 0xa860, 0x20e8, 0xa85c,
-	0x20a0, 0x009e, 0x4003, 0x9196, 0x0016, 0x01f0, 0x0136, 0x9080,
-	0x001b, 0x20a0, 0x2011, 0x0006, 0x20a9, 0x0001, 0x3418, 0x8318,
-	0x23a0, 0x4003, 0x3318, 0x8318, 0x2398, 0x8211, 0x1db8, 0x2011,
-	0x0006, 0x013e, 0x20a0, 0x3318, 0x8318, 0x2398, 0x4003, 0x3418,
-	0x8318, 0x23a0, 0x8211, 0x1db8, 0x0096, 0x080c, 0xcf1b, 0x0130,
-	0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0x009e, 0x0804,
-	0xb16c, 0x0096, 0x00d6, 0x0036, 0x7330, 0x9386, 0x0200, 0x11a8,
-	0x6010, 0x00b6, 0x2058, 0xb8d7, 0x0000, 0x00be, 0x6014, 0x9005,
-	0x0130, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xab32, 0x080c,
-	0xb16c, 0x003e, 0x00de, 0x009e, 0x0005, 0x0011, 0x1d48, 0x0cc8,
-	0x0006, 0x0016, 0x080c, 0xd645, 0x0188, 0x6014, 0x9005, 0x1170,
-	0x600b, 0x0003, 0x601b, 0x0000, 0x604b, 0x0000, 0x2009, 0x0022,
-	0x080c, 0xb994, 0x9006, 0x001e, 0x000e, 0x0005, 0x9085, 0x0001,
-	0x0cd0, 0x0096, 0x0016, 0x20a9, 0x0014, 0x9e80, 0x000c, 0x20e1,
-	0x0000, 0x2098, 0x6014, 0x2048, 0xa860, 0x20e8, 0xa85c, 0x9080,
-	0x0002, 0x20a0, 0x4003, 0x2001, 0x0205, 0x2003, 0x0001, 0x2099,
-	0x0260, 0x20a9, 0x0016, 0x4003, 0x20a9, 0x000a, 0xa804, 0x2048,
-	0xa860, 0x20e8, 0xa85c, 0x9080, 0x0002, 0x20a0, 0x4003, 0x2001,
-	0x0205, 0x2003, 0x0002, 0x2099, 0x0260, 0x20a9, 0x0020, 0x4003,
-	0x2003, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103,
-	0x080c, 0xb16c, 0x001e, 0x009e, 0x0005, 0x0096, 0x0016, 0x900e,
-	0x7030, 0x9086, 0x0100, 0x0140, 0x7038, 0x9084, 0x00ff, 0x800c,
-	0x703c, 0x9084, 0x00ff, 0x8004, 0x9080, 0x0004, 0x9108, 0x810b,
-	0x2011, 0x0002, 0x2019, 0x000c, 0x6014, 0x2048, 0x080c, 0xca7b,
-	0x080c, 0xcf1b, 0x0140, 0x6014, 0x2048, 0xa807, 0x0000, 0xa864,
-	0xa8e2, 0xa867, 0x0103, 0x080c, 0xb16c, 0x001e, 0x009e, 0x0005,
-	0x0016, 0x2009, 0x0000, 0x7030, 0x9086, 0x0200, 0x0110, 0x2009,
-	0x0001, 0x0096, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa97a, 0x080c,
-	0x7012, 0x009e, 0x080c, 0xb16c, 0x001e, 0x0005, 0x0016, 0x0096,
-	0x7030, 0x9086, 0x0100, 0x1118, 0x2009, 0x0004, 0x0010, 0x7034,
-	0x800c, 0x810b, 0x2011, 0x000c, 0x2019, 0x000c, 0x6014, 0x2048,
-	0xa804, 0x0096, 0x9005, 0x0108, 0x2048, 0x080c, 0xca7b, 0x009e,
-	0x080c, 0xcf1b, 0x0148, 0xa804, 0x9005, 0x1158, 0xa807, 0x0000,
-	0xa864, 0xa8e2, 0xa867, 0x0103, 0x080c, 0xb16c, 0x009e, 0x001e,
-	0x0005, 0x0086, 0x2040, 0xa030, 0x8007, 0x9086, 0x0100, 0x1118,
-	0x080c, 0xbb5c, 0x00e0, 0xa034, 0x8007, 0x800c, 0x8806, 0x8006,
-	0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x000c, 0xa87b,
-	0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0xaaa0, 0xab9c, 0xaca8,
-	0xada4, 0x2031, 0x0000, 0x2041, 0x12a8, 0x0019, 0x0d08, 0x008e,
-	0x0898, 0x0096, 0x0006, 0x080c, 0x1059, 0x000e, 0x01b0, 0xa8ab,
-	0x0dcb, 0xa876, 0x000e, 0xa8a2, 0x0006, 0xae6a, 0x2800, 0xa89e,
-	0xa97a, 0xaf72, 0xaa8e, 0xab92, 0xac96, 0xad9a, 0x0086, 0x2940,
-	0x080c, 0x114e, 0x008e, 0x9085, 0x0001, 0x009e, 0x0005, 0x00e6,
-	0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258,
-	0xba10, 0x00be, 0x9206, 0x1520, 0x700c, 0x6210, 0x00b6, 0x2258,
-	0xba14, 0x00be, 0x9206, 0x11e0, 0x604b, 0x0000, 0x2c68, 0x0016,
-	0x2009, 0x0035, 0x080c, 0xd5bb, 0x001e, 0x1158, 0x622c, 0x2268,
-	0x2071, 0x026c, 0x6b20, 0x9386, 0x0003, 0x0130, 0x9386, 0x0006,
-	0x0128, 0x080c, 0xb16c, 0x0020, 0x0039, 0x0010, 0x080c, 0xb7c7,
-	0x002e, 0x00de, 0x00ee, 0x0005, 0x0096, 0x6814, 0x2048, 0x9186,
-	0x0015, 0x0904, 0xb7a6, 0x918e, 0x0016, 0x1904, 0xb7c5, 0x700c,
-	0x908c, 0xff00, 0x9186, 0x1700, 0x0120, 0x9186, 0x0300, 0x1904,
-	0xb780, 0x89ff, 0x1138, 0x6800, 0x9086, 0x000f, 0x0904, 0xb762,
-	0x0804, 0xb7c3, 0x6808, 0x9086, 0xffff, 0x1904, 0xb7a8, 0xa87c,
-	0x9084, 0x0060, 0x9086, 0x0020, 0x1150, 0xa8ac, 0xa934, 0x9106,
-	0x1904, 0xb7a8, 0xa8b0, 0xa938, 0x9106, 0x1904, 0xb7a8, 0x6824,
-	0xd084, 0x1904, 0xb7a8, 0xd0b4, 0x0158, 0x0016, 0x2001, 0x1986,
-	0x200c, 0x6018, 0x9102, 0x9082, 0x0005, 0x001e, 0x1a04, 0xb7a8,
-	0x080c, 0xd10c, 0x6810, 0x0096, 0x2048, 0xa9a0, 0x009e, 0x685c,
-	0xa87a, 0xa976, 0x6864, 0xa882, 0xa87c, 0xc0dc, 0xc0f4, 0xc0d4,
-	0xa87e, 0x0026, 0x900e, 0x6a18, 0x2001, 0x000a, 0x080c, 0x955b,
-	0xa884, 0x920a, 0x0208, 0x8011, 0xaa86, 0x82ff, 0x002e, 0x1138,
-	0x00c6, 0x2d60, 0x080c, 0xcc01, 0x00ce, 0x0804, 0xb7c3, 0x00c6,
-	0xa868, 0xd0fc, 0x1118, 0x080c, 0x622f, 0x0010, 0x080c, 0x663a,
-	0x00ce, 0x1904, 0xb7a8, 0x00c6, 0x2d60, 0x080c, 0xb16c, 0x00ce,
-	0x0804, 0xb7c3, 0x00c6, 0x080c, 0xb1dd, 0x0198, 0x6017, 0x0000,
-	0x6810, 0x6012, 0x080c, 0xd3b6, 0x6023, 0x0003, 0x6904, 0x00c6,
-	0x2d60, 0x080c, 0xb16c, 0x00ce, 0x080c, 0xb20a, 0x00ce, 0x0804,
-	0xb7c3, 0x2001, 0x1988, 0x2004, 0x684a, 0x00ce, 0x0804, 0xb7c3,
-	0x7008, 0x9086, 0x000b, 0x11c8, 0x6010, 0x00b6, 0x2058, 0xb900,
-	0xc1bc, 0xb902, 0x00be, 0x00c6, 0x2d60, 0xa87b, 0x0003, 0x080c,
-	0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x2009,
-	0x8020, 0x080c, 0x9617, 0x00ce, 0x0430, 0x700c, 0x9086, 0x2a00,
-	0x1138, 0x2001, 0x1988, 0x2004, 0x684a, 0x00e8, 0x04c1, 0x00e8,
-	0x89ff, 0x090c, 0x0d85, 0x00c6, 0x00d6, 0x2d60, 0xa867, 0x0103,
-	0xa87b, 0x0003, 0x080c, 0x6e27, 0x080c, 0xd10c, 0x080c, 0xb1a7,
-	0x0026, 0x6010, 0x00b6, 0x2058, 0xba3c, 0x080c, 0x68df, 0x00be,
-	0x002e, 0x00de, 0x00ce, 0x080c, 0xb16c, 0x009e, 0x0005, 0x9186,
-	0x0015, 0x1128, 0x2001, 0x1988, 0x2004, 0x684a, 0x0068, 0x918e,
-	0x0016, 0x1160, 0x00c6, 0x2d00, 0x2060, 0x080c, 0xece1, 0x080c,
-	0x8c19, 0x080c, 0xb16c, 0x00ce, 0x080c, 0xb16c, 0x0005, 0x0026,
-	0x0036, 0x0046, 0x7228, 0xacb0, 0xabac, 0xd2f4, 0x0130, 0x2001,
-	0x1988, 0x2004, 0x684a, 0x0804, 0xb841, 0x00c6, 0x2d60, 0x080c,
-	0xcadc, 0x00ce, 0x6804, 0x9086, 0x0050, 0x1168, 0x00c6, 0x2d00,
-	0x2060, 0x6003, 0x0001, 0x6007, 0x0050, 0x2009, 0x8023, 0x080c,
-	0x9617, 0x00ce, 0x04f0, 0x6800, 0x9086, 0x000f, 0x01a8, 0x89ff,
-	0x090c, 0x0d85, 0x6800, 0x9086, 0x0004, 0x1190, 0xa87c, 0xd0ac,
-	0x0178, 0xa843, 0x0fff, 0xa83f, 0x0fff, 0xa880, 0xc0fc, 0xa882,
-	0x2001, 0x0001, 0x6832, 0x0400, 0x2001, 0x0007, 0x6832, 0x00e0,
-	0xa87c, 0xd0b4, 0x1150, 0xd0ac, 0x0db8, 0x6824, 0xd0f4, 0x1d48,
-	0xa838, 0xa934, 0x9105, 0x0d80, 0x0c20, 0xd2ec, 0x1d68, 0x7024,
-	0x9306, 0x1118, 0x7020, 0x9406, 0x0d38, 0x7020, 0x683e, 0x7024,
-	0x683a, 0x2001, 0x0005, 0x6832, 0x080c, 0xd2a0, 0x080c, 0x9ab3,
-	0x0010, 0x080c, 0xb16c, 0x004e, 0x003e, 0x002e, 0x0005, 0x00e6,
-	0x00d6, 0x0026, 0x7008, 0x9084, 0x00ff, 0x6210, 0x00b6, 0x2258,
-	0xba10, 0x00be, 0x9206, 0x1904, 0xb8ac, 0x700c, 0x6210, 0x00b6,
-	0x2258, 0xba14, 0x00be, 0x9206, 0x1904, 0xb8ac, 0x6038, 0x2068,
-	0x6824, 0xc0dc, 0x6826, 0x6a20, 0x9286, 0x0007, 0x0904, 0xb8ac,
-	0x9286, 0x0002, 0x0904, 0xb8ac, 0x9286, 0x0000, 0x05e8, 0x6808,
-	0x633c, 0x9306, 0x15c8, 0x2071, 0x026c, 0x9186, 0x0015, 0x0570,
-	0x918e, 0x0016, 0x1100, 0x00c6, 0x6038, 0x2060, 0x6104, 0x9186,
-	0x004b, 0x01c0, 0x9186, 0x004c, 0x01a8, 0x9186, 0x004d, 0x0190,
-	0x9186, 0x004e, 0x0178, 0x9186, 0x0052, 0x0160, 0x6014, 0x0096,
-	0x2048, 0x080c, 0xcf1b, 0x090c, 0x0d85, 0xa87b, 0x0003, 0x009e,
-	0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002,
-	0x2009, 0x8020, 0x080c, 0x9617, 0x00ce, 0x0030, 0x6038, 0x2070,
-	0x2001, 0x1988, 0x2004, 0x704a, 0x080c, 0xb16c, 0x002e, 0x00de,
-	0x00ee, 0x0005, 0x00b6, 0x0096, 0x00f6, 0x6014, 0x2048, 0x6010,
-	0x2058, 0x91b6, 0x0015, 0x0130, 0xba08, 0xbb0c, 0xbc00, 0xc48c,
-	0xbc02, 0x0470, 0x0096, 0x0156, 0x0036, 0x0026, 0x2b48, 0x9e90,
-	0x0010, 0x2019, 0x000a, 0x20a9, 0x0004, 0x080c, 0xc222, 0x002e,
-	0x003e, 0x015e, 0x009e, 0x1904, 0xb91d, 0x0096, 0x0156, 0x0036,
-	0x0026, 0x2b48, 0x9e90, 0x0014, 0x2019, 0x0006, 0x20a9, 0x0004,
-	0x080c, 0xc222, 0x002e, 0x003e, 0x015e, 0x009e, 0x15b0, 0x7238,
-	0xba0a, 0x733c, 0xbb0e, 0x83ff, 0x0118, 0xbc00, 0xc48d, 0xbc02,
-	0xa804, 0x9005, 0x1128, 0x00fe, 0x009e, 0x00be, 0x0804, 0xb57c,
-	0x0096, 0x2048, 0xaa12, 0xab16, 0xac0a, 0x009e, 0x8006, 0x8006,
-	0x8007, 0x90bc, 0x003f, 0x9084, 0xffc0, 0x9080, 0x0002, 0x2009,
-	0x002b, 0xaaa0, 0xab9c, 0xaca8, 0xada4, 0x2031, 0x0000, 0x2041,
-	0x12a8, 0x080c, 0xb691, 0x0130, 0x00fe, 0x009e, 0x080c, 0xb16c,
-	0x00be, 0x0005, 0x080c, 0xbb5c, 0x0cb8, 0x2b78, 0x00f6, 0x080c,
-	0x3315, 0x080c, 0xd65a, 0x00fe, 0x00c6, 0x080c, 0xb116, 0x2f00,
-	0x6012, 0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003,
-	0x0001, 0x2001, 0x0007, 0x080c, 0x66fa, 0x080c, 0x6726, 0x080c,
-	0x961e, 0x080c, 0x9ab3, 0x00ce, 0x0804, 0xb8f0, 0x2100, 0x91b2,
-	0x0053, 0x1a0c, 0x0d85, 0x91b2, 0x0040, 0x1a04, 0xb9a6, 0x0002,
-	0xb994, 0xb994, 0xb98a, 0xb994, 0xb994, 0xb994, 0xb988, 0xb988,
-	0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988,
-	0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988,
-	0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb994,
-	0xb988, 0xb994, 0xb994, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988,
-	0xb98a, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb988,
-	0xb988, 0xb988, 0xb994, 0xb994, 0xb988, 0xb988, 0xb988, 0xb988,
-	0xb988, 0xb988, 0xb988, 0xb988, 0xb988, 0xb994, 0xb988, 0xb988,
-	0x080c, 0x0d85, 0x0066, 0x00b6, 0x6610, 0x2658, 0xb8d4, 0xc08c,
-	0xb8d6, 0x00be, 0x006e, 0x0000, 0x6003, 0x0001, 0x6106, 0x9186,
-	0x0032, 0x0118, 0x080c, 0x961e, 0x0010, 0x080c, 0x9617, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x9ab3, 0x012e, 0x0005, 0x2600, 0x0002,
-	0xb994, 0xb994, 0xb9ba, 0xb994, 0xb994, 0xb9ba, 0xb9ba, 0xb9ba,
-	0xb9ba, 0xb994, 0xb9ba, 0xb994, 0xb9ba, 0xb994, 0xb9ba, 0xb9ba,
-	0xb9ba, 0xb9ba, 0x080c, 0x0d85, 0x6004, 0x90b2, 0x0053, 0x1a0c,
-	0x0d85, 0x91b6, 0x0013, 0x0904, 0xba91, 0x91b6, 0x0027, 0x1904,
-	0xba3d, 0x080c, 0x99ed, 0x6004, 0x080c, 0xd121, 0x01b0, 0x080c,
-	0xd132, 0x01a8, 0x908e, 0x0021, 0x0904, 0xba3a, 0x908e, 0x0022,
-	0x1130, 0x080c, 0xb5a8, 0x0904, 0xba36, 0x0804, 0xba37, 0x908e,
-	0x003d, 0x0904, 0xba3a, 0x0804, 0xba30, 0x080c, 0x3344, 0x2001,
-	0x0007, 0x080c, 0x66fa, 0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be,
-	0x080c, 0xbb5c, 0x9186, 0x007e, 0x1148, 0x2001, 0x1837, 0x2014,
-	0xc285, 0x080c, 0x779e, 0x1108, 0xc2ad, 0x2202, 0x080c, 0xacfc,
-	0x0036, 0x0026, 0x2019, 0x0028, 0x2110, 0x080c, 0xedee, 0x002e,
-	0x003e, 0x0016, 0x0026, 0x0036, 0x2110, 0x2019, 0x0028, 0x080c,
-	0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x6010, 0x00b6, 0x905d,
-	0x0100, 0x00be, 0x2c08, 0x080c, 0xe75d, 0x007e, 0x003e, 0x002e,
-	0x001e, 0x080c, 0xad18, 0x080c, 0xd65a, 0x0016, 0x080c, 0xd3ae,
-	0x080c, 0xb16c, 0x001e, 0x080c, 0x341e, 0x080c, 0x9ab3, 0x0030,
-	0x080c, 0xd3ae, 0x080c, 0xb16c, 0x080c, 0x9ab3, 0x0005, 0x080c,
-	0xbb5c, 0x0cb0, 0x080c, 0xbb98, 0x0c98, 0x9186, 0x0015, 0x0118,
-	0x9186, 0x0016, 0x1140, 0x080c, 0xaf61, 0x0d80, 0x9086, 0x0002,
-	0x0904, 0xbba3, 0x0c58, 0x9186, 0x0014, 0x1d40, 0x080c, 0x99ed,
-	0x6004, 0x908e, 0x0022, 0x1118, 0x080c, 0xb5a8, 0x09f8, 0x080c,
-	0x3315, 0x080c, 0xd65a, 0x080c, 0xd121, 0x1190, 0x080c, 0x3344,
-	0x6010, 0x00b6, 0x2058, 0xb9a0, 0x00be, 0x080c, 0xbb5c, 0x9186,
-	0x007e, 0x1128, 0x2001, 0x1837, 0x200c, 0xc185, 0x2102, 0x0800,
-	0x080c, 0xd132, 0x1120, 0x080c, 0xbb5c, 0x0804, 0xba30, 0x6004,
-	0x908e, 0x0032, 0x1160, 0x00e6, 0x00f6, 0x2071, 0x189e, 0x2079,
-	0x0000, 0x080c, 0x36bf, 0x00fe, 0x00ee, 0x0804, 0xba30, 0x6004,
-	0x908e, 0x0021, 0x0d40, 0x908e, 0x0022, 0x090c, 0xbb5c, 0x0804,
-	0xba30, 0x90b2, 0x0040, 0x1a04, 0xbb3c, 0x2008, 0x0002, 0xbad9,
-	0xbada, 0xbadd, 0xbae0, 0xbae3, 0xbaf0, 0xbad7, 0xbad7, 0xbad7,
-	0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7,
-	0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7,
-	0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbaf3, 0xbafe, 0xbad7,
-	0xbaff, 0xbafe, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbafe,
-	0xbafe, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7, 0xbad7,
-	0xbad7, 0xbb27, 0xbafe, 0xbad7, 0xbafa, 0xbad7, 0xbad7, 0xbad7,
-	0xbafb, 0xbad7, 0xbad7, 0xbad7, 0xbafe, 0xbb22, 0xbad7, 0x080c,
-	0x0d85, 0x0420, 0x2001, 0x000b, 0x0448, 0x2001, 0x0003, 0x0430,
-	0x2001, 0x0005, 0x0418, 0x6010, 0x00b6, 0x2058, 0xb804, 0x00be,
-	0x9084, 0x00ff, 0x9086, 0x0000, 0x11d8, 0x2001, 0x0001, 0x00b0,
-	0x2001, 0x0009, 0x0098, 0x6003, 0x0005, 0x080c, 0xd65d, 0x080c,
-	0x9ab3, 0x0058, 0x0018, 0x0010, 0x080c, 0x66fa, 0x04b8, 0x080c,
-	0xd65d, 0x6003, 0x0004, 0x080c, 0x9ab3, 0x0005, 0x080c, 0x66fa,
-	0x6003, 0x0002, 0x0036, 0x2019, 0x1852, 0x2304, 0x9084, 0xff00,
-	0x1120, 0x2001, 0x1986, 0x201c, 0x0040, 0x8007, 0x909a, 0x0004,
-	0x0ec0, 0x8003, 0x801b, 0x831b, 0x9318, 0x631a, 0x003e, 0x080c,
-	0x9ab3, 0x0c18, 0x080c, 0xd3ae, 0x080c, 0xb16c, 0x08f0, 0x00e6,
-	0x00f6, 0x2071, 0x189e, 0x2079, 0x0000, 0x080c, 0x36bf, 0x00fe,
-	0x00ee, 0x080c, 0x99ed, 0x080c, 0xb16c, 0x0878, 0x6003, 0x0002,
-	0x080c, 0xd65d, 0x0804, 0x9ab3, 0x2600, 0x2008, 0x0002, 0xbb53,
-	0xbb36, 0xbb51, 0xbb36, 0xbb36, 0xbb51, 0xbb51, 0xbb51, 0xbb51,
-	0xbb36, 0xbb51, 0xbb36, 0xbb51, 0xbb36, 0xbb51, 0xbb51, 0xbb51,
-	0xbb51, 0x080c, 0x0d85, 0x0096, 0x6014, 0x2048, 0x080c, 0x7012,
-	0x009e, 0x080c, 0xb16c, 0x0005, 0x00e6, 0x0096, 0x0026, 0x0016,
-	0x080c, 0xcf1b, 0x0568, 0x6014, 0x2048, 0xa864, 0x9086, 0x0139,
-	0x11a8, 0xa894, 0x9086, 0x0056, 0x1148, 0x080c, 0x55cc, 0x0130,
-	0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x0028, 0x2001, 0x0030,
-	0x900e, 0x2011, 0x4005, 0x080c, 0xd51f, 0x0090, 0xa868, 0xd0fc,
-	0x0178, 0xa807, 0x0000, 0x0016, 0x6004, 0x908e, 0x0021, 0x0168,
-	0x908e, 0x003d, 0x0150, 0x001e, 0xa867, 0x0103, 0xa833, 0x0100,
-	0x001e, 0x002e, 0x009e, 0x00ee, 0x0005, 0x001e, 0x0009, 0x0cc0,
-	0x0096, 0x6014, 0x2048, 0xa800, 0x2048, 0xa867, 0x0103, 0xa823,
-	0x8001, 0x009e, 0x0005, 0x00b6, 0x6610, 0x2658, 0xb804, 0x9084,
-	0x00ff, 0x90b2, 0x000c, 0x1a0c, 0x0d85, 0x6604, 0x96b6, 0x004d,
-	0x1120, 0x080c, 0xd43e, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0043,
-	0x1120, 0x080c, 0xd487, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x004b,
-	0x1120, 0x080c, 0xd4b3, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0033,
-	0x1120, 0x080c, 0xd3d0, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0028,
-	0x1120, 0x080c, 0xd170, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0029,
-	0x1120, 0x080c, 0xd1b1, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x001f,
-	0x1120, 0x080c, 0xb54d, 0x0804, 0xbc28, 0x6604, 0x96b6, 0x0000,
-	0x1118, 0x080c, 0xb8b2, 0x04e0, 0x6604, 0x96b6, 0x0022, 0x1118,
-	0x080c, 0xb589, 0x04a8, 0x6604, 0x96b6, 0x0035, 0x1118, 0x080c,
-	0xb6af, 0x0470, 0x6604, 0x96b6, 0x0039, 0x1118, 0x080c, 0xb847,
-	0x0438, 0x6604, 0x96b6, 0x003d, 0x1118, 0x080c, 0xb5c1, 0x0400,
-	0x6604, 0x96b6, 0x0044, 0x1118, 0x080c, 0xb5fd, 0x00c8, 0x6604,
-	0x96b6, 0x0049, 0x1118, 0x080c, 0xb63e, 0x0090, 0x6604, 0x96b6,
-	0x0041, 0x1118, 0x080c, 0xb628, 0x0058, 0x91b6, 0x0015, 0x1110,
-	0x0063, 0x0030, 0x91b6, 0x0016, 0x1128, 0x00be, 0x0804, 0xbf34,
-	0x00be, 0x0005, 0x080c, 0xb227, 0x0cd8, 0xbc45, 0xbc53, 0xbc45,
-	0xbc9a, 0xbc45, 0xbe51, 0xbf41, 0xbc45, 0xbc45, 0xbf0a, 0xbc45,
-	0xbf20, 0x0096, 0x601f, 0x0000, 0x6014, 0x2048, 0xa800, 0x2048,
-	0xa867, 0x0103, 0x009e, 0x0804, 0xb16c, 0xa001, 0xa001, 0x0005,
-	0x6604, 0x96b6, 0x0004, 0x1130, 0x2001, 0x0001, 0x080c, 0x66e6,
-	0x0804, 0xb16c, 0x0005, 0x00e6, 0x2071, 0x1800, 0x7090, 0x9086,
-	0x0074, 0x1540, 0x080c, 0xe72e, 0x11b0, 0x6010, 0x00b6, 0x2058,
-	0x7030, 0xd08c, 0x0128, 0xb800, 0xd0bc, 0x0110, 0xc0c5, 0xb802,
-	0x00f9, 0x00be, 0x2001, 0x0006, 0x080c, 0x66fa, 0x080c, 0x3344,
-	0x080c, 0xb16c, 0x0098, 0x2001, 0x000a, 0x080c, 0x66fa, 0x080c,
-	0x3344, 0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x080c,
-	0x9ab3, 0x0020, 0x2001, 0x0001, 0x080c, 0xbe21, 0x00ee, 0x0005,
-	0x00d6, 0xb800, 0xd084, 0x0160, 0x9006, 0x080c, 0x66e6, 0x2069,
-	0x1847, 0x6804, 0xd0a4, 0x0120, 0x2001, 0x0006, 0x080c, 0x6726,
-	0x00de, 0x0005, 0x00b6, 0x0096, 0x00d6, 0x2011, 0x1824, 0x2204,
-	0x9086, 0x0074, 0x1904, 0xbdf6, 0x6010, 0x2058, 0xbaa0, 0x9286,
-	0x007e, 0x1120, 0x080c, 0xc090, 0x0804, 0xbd63, 0x2001, 0x180d,
-	0x2004, 0xd08c, 0x0904, 0xbd05, 0x00d6, 0x080c, 0x779e, 0x01a0,
-	0x0026, 0x2011, 0x0010, 0x080c, 0x6c35, 0x002e, 0x0904, 0xbd04,
-	0x080c, 0x5854, 0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867,
-	0x0103, 0xa833, 0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910,
-	0x00be, 0x9186, 0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c,
-	0x6c35, 0x002e, 0x0548, 0x6014, 0x9005, 0x090c, 0x0d85, 0x2048,
-	0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030,
-	0x900e, 0x2011, 0x4009, 0x080c, 0xd51f, 0x0040, 0x6014, 0x2048,
-	0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058,
-	0xb9a0, 0x0016, 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x080c,
-	0x341e, 0x00de, 0x0804, 0xbdfb, 0x00de, 0x080c, 0xc085, 0x6010,
-	0x2058, 0xbaa0, 0x9286, 0x0080, 0x1510, 0x6014, 0x9005, 0x01a8,
-	0x2048, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1140, 0x2001,
-	0x0000, 0x900e, 0x2011, 0x4000, 0x080c, 0xd51f, 0x0030, 0xa807,
-	0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x2001, 0x0006, 0x080c,
-	0x66fa, 0x080c, 0x3344, 0x080c, 0xb16c, 0x0804, 0xbdfb, 0x080c,
-	0xbe09, 0x6014, 0x9005, 0x0190, 0x2048, 0xa868, 0xd0f4, 0x01e8,
-	0xa864, 0x9084, 0x00ff, 0x9086, 0x0039, 0x1d08, 0x2001, 0x0000,
-	0x900e, 0x2011, 0x4000, 0x080c, 0xd51f, 0x08f8, 0x080c, 0xbdff,
-	0x0160, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0004, 0x080c, 0x6726,
-	0x2001, 0x0007, 0x080c, 0x66fa, 0x08a0, 0x2001, 0x0004, 0x080c,
-	0x66fa, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x961e, 0x080c,
-	0x9ab3, 0x0804, 0xbdfb, 0xb85c, 0xd0e4, 0x0178, 0x080c, 0xd348,
-	0x080c, 0x779e, 0x0118, 0xd0dc, 0x1904, 0xbd25, 0x2011, 0x1837,
-	0x2204, 0xc0ad, 0x2012, 0x0804, 0xbd25, 0x080c, 0xd389, 0x2011,
-	0x1837, 0x2204, 0xc0a5, 0x2012, 0x0006, 0x080c, 0xe905, 0x000e,
-	0x1904, 0xbd25, 0xc0b5, 0x2012, 0x2001, 0x0006, 0x080c, 0x66fa,
-	0x9006, 0x080c, 0x66e6, 0x00c6, 0x2001, 0x180f, 0x2004, 0xd09c,
-	0x0520, 0x00f6, 0x2079, 0x0100, 0x00e6, 0x2071, 0x1800, 0x700c,
-	0x9084, 0x00ff, 0x78e6, 0x707e, 0x7010, 0x78ea, 0x7082, 0x908c,
-	0x00ff, 0x00ee, 0x780c, 0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26d5,
-	0x00f6, 0x2100, 0x900e, 0x080c, 0x268c, 0x795e, 0x00fe, 0x9186,
-	0x0081, 0x01f0, 0x2009, 0x0081, 0x00e0, 0x2009, 0x00ef, 0x00f6,
-	0x2079, 0x0100, 0x79ea, 0x78e7, 0x0000, 0x7932, 0x7936, 0x780c,
-	0xc0b5, 0x780e, 0x00fe, 0x080c, 0x26d5, 0x00f6, 0x2079, 0x1800,
-	0x7982, 0x2100, 0x900e, 0x797e, 0x080c, 0x268c, 0x795e, 0x00fe,
-	0x8108, 0x080c, 0x6749, 0x2b00, 0x00ce, 0x1904, 0xbd25, 0x6012,
-	0x2009, 0x180f, 0x210c, 0xd19c, 0x0150, 0x2009, 0x027c, 0x210c,
-	0x918c, 0x00ff, 0xb912, 0x2009, 0x027d, 0x210c, 0xb916, 0x2001,
-	0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0028, 0x080c, 0xbb5c,
-	0x2001, 0x0001, 0x0431, 0x00de, 0x009e, 0x00be, 0x0005, 0x2001,
-	0x1810, 0x2004, 0xd0a4, 0x0120, 0x2001, 0x1848, 0x2004, 0xd0ac,
-	0x0005, 0x00e6, 0x080c, 0xee47, 0x0190, 0x2071, 0x0260, 0x7108,
-	0x720c, 0x918c, 0x00ff, 0x1118, 0x9284, 0xff00, 0x0140, 0x6010,
-	0x2058, 0xb8a0, 0x9084, 0xff80, 0x1110, 0xb912, 0xba16, 0x00ee,
-	0x0005, 0x2030, 0x9005, 0x0158, 0x2001, 0x0007, 0x080c, 0x66fa,
-	0x080c, 0x5854, 0x1120, 0x2001, 0x0007, 0x080c, 0x6726, 0x2600,
-	0x9005, 0x11b0, 0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc,
-	0x1178, 0x0036, 0x0046, 0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be,
-	0x2021, 0x0004, 0x2011, 0x8014, 0x080c, 0x4ca1, 0x004e, 0x003e,
-	0x080c, 0x3344, 0x6020, 0x9086, 0x000a, 0x1108, 0x0005, 0x0804,
-	0xb16c, 0x00b6, 0x00e6, 0x0026, 0x0016, 0x2071, 0x1800, 0x7090,
-	0x9086, 0x0014, 0x1904, 0xbf00, 0x2001, 0x180d, 0x2004, 0xd08c,
-	0x0904, 0xbeb3, 0x00d6, 0x080c, 0x779e, 0x01a0, 0x0026, 0x2011,
-	0x0010, 0x080c, 0x6c35, 0x002e, 0x0904, 0xbeb2, 0x080c, 0x5854,
-	0x1598, 0x6014, 0x2048, 0xa807, 0x0000, 0xa867, 0x0103, 0xa833,
-	0xdead, 0x0450, 0x6010, 0x00b6, 0x2058, 0xb910, 0x00be, 0x9186,
-	0x00ff, 0x0580, 0x0026, 0x2011, 0x8008, 0x080c, 0x6c35, 0x002e,
-	0x0548, 0x6014, 0x9005, 0x090c, 0x0d85, 0x2048, 0xa864, 0x9084,
-	0x00ff, 0x9086, 0x0039, 0x1140, 0x2001, 0x0030, 0x900e, 0x2011,
-	0x4009, 0x080c, 0xd51f, 0x0040, 0x6014, 0x2048, 0xa807, 0x0000,
-	0xa867, 0x0103, 0xa833, 0xdead, 0x6010, 0x2058, 0xb9a0, 0x0016,
-	0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x080c, 0x341e, 0x00de,
-	0x0804, 0xbf05, 0x00de, 0x080c, 0x5854, 0x1170, 0x6014, 0x9005,
-	0x1158, 0x0036, 0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006,
-	0x080c, 0x4e58, 0x004e, 0x003e, 0x00d6, 0x6010, 0x2058, 0x080c,
-	0x684f, 0x080c, 0xbc88, 0x00de, 0x080c, 0xc15b, 0x1588, 0x6010,
-	0x2058, 0xb890, 0x9005, 0x0560, 0x2001, 0x0006, 0x080c, 0x66fa,
-	0x0096, 0x6014, 0x904d, 0x01d0, 0xa864, 0x9084, 0x00ff, 0x9086,
-	0x0039, 0x1140, 0x2001, 0x0000, 0x900e, 0x2011, 0x4000, 0x080c,
-	0xd51f, 0x0060, 0xa864, 0x9084, 0x00ff, 0x9086, 0x0029, 0x0130,
-	0xa807, 0x0000, 0xa867, 0x0103, 0xa833, 0x0200, 0x009e, 0x080c,
-	0x3344, 0x6020, 0x9086, 0x000a, 0x0140, 0x080c, 0xb16c, 0x0028,
-	0x080c, 0xbb5c, 0x9006, 0x080c, 0xbe21, 0x001e, 0x002e, 0x00ee,
-	0x00be, 0x0005, 0x2011, 0x1824, 0x2204, 0x9086, 0x0014, 0x1160,
-	0x2001, 0x0002, 0x080c, 0x66fa, 0x6003, 0x0001, 0x6007, 0x0001,
-	0x080c, 0x961e, 0x0804, 0x9ab3, 0x2001, 0x0001, 0x0804, 0xbe21,
-	0x2030, 0x2011, 0x1824, 0x2204, 0x9086, 0x0004, 0x1148, 0x96b6,
-	0x000b, 0x1120, 0x2001, 0x0007, 0x080c, 0x66fa, 0x0804, 0xb16c,
-	0x2001, 0x0001, 0x0804, 0xbe21, 0x0002, 0xbc45, 0xbf4c, 0xbc45,
-	0xbf8f, 0xbc45, 0xc03c, 0xbf41, 0xbc48, 0xbc45, 0xc050, 0xbc45,
-	0xc062, 0x6604, 0x9686, 0x0003, 0x0904, 0xbe51, 0x96b6, 0x001e,
-	0x1110, 0x080c, 0xb16c, 0x0005, 0x00b6, 0x00d6, 0x00c6, 0x080c,
-	0xc074, 0x11a0, 0x9006, 0x080c, 0x66e6, 0x080c, 0x3315, 0x080c,
-	0xd65a, 0x2001, 0x0002, 0x080c, 0x66fa, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0428, 0x2009, 0x026e,
-	0x2104, 0x9086, 0x0009, 0x1160, 0x6010, 0x2058, 0xb840, 0x9084,
-	0x00ff, 0x9005, 0x0180, 0x8001, 0xb842, 0x601b, 0x000a, 0x0098,
-	0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x908e, 0x1900, 0x0158,
-	0x908e, 0x1e00, 0x0990, 0x080c, 0x3315, 0x080c, 0xd65a, 0x2001,
-	0x0001, 0x080c, 0xbe21, 0x00ce, 0x00de, 0x00be, 0x0005, 0x0096,
-	0x00b6, 0x0026, 0x9016, 0x080c, 0xc082, 0x00d6, 0x2069, 0x197c,
-	0x2d04, 0x9005, 0x0168, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x007e,
-	0x1138, 0x2069, 0x1820, 0x2d04, 0x8000, 0x206a, 0x00de, 0x0010,
-	0x00de, 0x0088, 0x9006, 0x080c, 0x66e6, 0x2001, 0x0002, 0x080c,
-	0x66fa, 0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x961e, 0x080c,
-	0x9ab3, 0x0804, 0xc00c, 0x080c, 0xcf1b, 0x01b0, 0x6014, 0x2048,
-	0xa864, 0x2010, 0x9086, 0x0139, 0x1138, 0x6007, 0x0016, 0x2001,
-	0x0002, 0x080c, 0xd57c, 0x00b0, 0x6014, 0x2048, 0xa864, 0xd0fc,
-	0x0118, 0x2001, 0x0001, 0x0ca8, 0x2001, 0x180e, 0x2004, 0xd0dc,
-	0x0148, 0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x1110,
-	0x9006, 0x0c38, 0x080c, 0xbb5c, 0x2009, 0x026e, 0x2134, 0x96b4,
-	0x00ff, 0x9686, 0x0005, 0x0520, 0x9686, 0x000b, 0x01c8, 0x2009,
-	0x026f, 0x2104, 0x9084, 0xff00, 0x1118, 0x9686, 0x0009, 0x01c0,
-	0x9086, 0x1900, 0x1168, 0x9686, 0x0009, 0x0190, 0x2001, 0x0004,
-	0x080c, 0x66fa, 0x2001, 0x0028, 0x601a, 0x6007, 0x0052, 0x0020,
-	0x2001, 0x0001, 0x080c, 0xbe21, 0x002e, 0x00be, 0x009e, 0x0005,
-	0x9286, 0x0139, 0x0160, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0140,
-	0xa864, 0x9086, 0x0139, 0x0118, 0xa868, 0xd0fc, 0x0108, 0x0c40,
-	0x6010, 0x2058, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0138, 0x8001,
-	0xb842, 0x601b, 0x000a, 0x6007, 0x0016, 0x08f0, 0xb8a0, 0x9086,
-	0x007e, 0x1138, 0x00e6, 0x2071, 0x1800, 0x080c, 0x6130, 0x00ee,
-	0x0010, 0x080c, 0x3315, 0x0860, 0x2001, 0x0004, 0x080c, 0x66fa,
-	0x080c, 0xc082, 0x1140, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c,
-	0x961e, 0x0804, 0x9ab3, 0x080c, 0xbb5c, 0x9006, 0x0804, 0xbe21,
-	0x0489, 0x1160, 0x2001, 0x0008, 0x080c, 0x66fa, 0x6003, 0x0001,
-	0x6007, 0x0005, 0x080c, 0x961e, 0x0804, 0x9ab3, 0x2001, 0x0001,
-	0x0804, 0xbe21, 0x00f9, 0x1160, 0x2001, 0x000a, 0x080c, 0x66fa,
-	0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x0804, 0x9ab3,
-	0x2001, 0x0001, 0x0804, 0xbe21, 0x2009, 0x026e, 0x2104, 0x9086,
-	0x0003, 0x1138, 0x2009, 0x026f, 0x2104, 0x9084, 0xff00, 0x9086,
-	0x2a00, 0x0005, 0x9085, 0x0001, 0x0005, 0x00b6, 0x00c6, 0x0016,
-	0x6110, 0x2158, 0x080c, 0x67c3, 0x001e, 0x00ce, 0x00be, 0x0005,
-	0x00b6, 0x00f6, 0x00e6, 0x00d6, 0x0036, 0x0016, 0x6010, 0x2058,
-	0x2009, 0x1837, 0x2104, 0x9085, 0x0003, 0x200a, 0x080c, 0xc12d,
-	0x0560, 0x2009, 0x1837, 0x2104, 0xc0cd, 0x200a, 0x080c, 0x6c0d,
-	0x0158, 0x9006, 0x2020, 0x2009, 0x002a, 0x080c, 0xea8d, 0x2001,
-	0x180c, 0x200c, 0xc195, 0x2102, 0x2019, 0x002a, 0x2009, 0x0001,
-	0x080c, 0x32da, 0x00e6, 0x2071, 0x1800, 0x080c, 0x30bf, 0x00ee,
-	0x00c6, 0x0156, 0x20a9, 0x0781, 0x2009, 0x007f, 0x080c, 0x341e,
-	0x8108, 0x1f04, 0xc0c6, 0x015e, 0x00ce, 0x080c, 0xc085, 0x2071,
-	0x0260, 0x2079, 0x0200, 0x7817, 0x0001, 0x2001, 0x1837, 0x200c,
-	0xc1c5, 0x7018, 0xd0fc, 0x0110, 0xd0dc, 0x0118, 0x7038, 0xd0dc,
-	0x1108, 0xc1c4, 0x7817, 0x0000, 0x2001, 0x1837, 0x2102, 0x9184,
-	0x0050, 0x9086, 0x0050, 0x05d0, 0x2079, 0x0100, 0x2e04, 0x9084,
-	0x00ff, 0x2069, 0x181f, 0x206a, 0x78e6, 0x0006, 0x8e70, 0x2e04,
-	0x2069, 0x1820, 0x206a, 0x78ea, 0x7832, 0x7836, 0x2010, 0x9084,
-	0xff00, 0x001e, 0x9105, 0x2009, 0x182c, 0x200a, 0x2200, 0x9084,
-	0x00ff, 0x2008, 0x080c, 0x26d5, 0x080c, 0x779e, 0x0170, 0x2071,
-	0x0260, 0x2069, 0x1982, 0x7048, 0x206a, 0x704c, 0x6806, 0x7050,
-	0x680a, 0x7054, 0x680e, 0x080c, 0xd348, 0x0040, 0x2001, 0x0006,
-	0x080c, 0x66fa, 0x080c, 0x3344, 0x080c, 0xb16c, 0x001e, 0x003e,
-	0x00de, 0x00ee, 0x00fe, 0x00be, 0x0005, 0x0096, 0x0026, 0x0036,
-	0x00e6, 0x0156, 0x2019, 0x182c, 0x231c, 0x83ff, 0x01f0, 0x2071,
-	0x0260, 0x7200, 0x9294, 0x00ff, 0x7004, 0x9084, 0xff00, 0x9205,
-	0x9306, 0x1198, 0x2011, 0x0276, 0x20a9, 0x0004, 0x2b48, 0x2019,
-	0x000a, 0x080c, 0xc222, 0x1148, 0x2011, 0x027a, 0x20a9, 0x0004,
-	0x2019, 0x0006, 0x080c, 0xc222, 0x1100, 0x015e, 0x00ee, 0x003e,
-	0x002e, 0x009e, 0x0005, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9086,
-	0x0014, 0x11a8, 0x7038, 0x9086, 0x0800, 0x1188, 0x703c, 0xd0ec,
-	0x0160, 0x9084, 0x0f00, 0x9086, 0x0100, 0x1138, 0x7054, 0xd0a4,
-	0x1110, 0xd0ac, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001, 0x00ee,
-	0x0005, 0x00e6, 0x0096, 0x00c6, 0x0076, 0x0056, 0x0046, 0x0026,
-	0x0006, 0x0126, 0x2091, 0x8000, 0x2029, 0x19f4, 0x252c, 0x2021,
-	0x19fb, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7254, 0x7074,
-	0x9202, 0x1a04, 0xc1ee, 0x080c, 0x8eee, 0x0904, 0xc1e7, 0x080c,
-	0xeabe, 0x0904, 0xc1e7, 0x6720, 0x9786, 0x0007, 0x0904, 0xc1e7,
-	0x2500, 0x9c06, 0x0904, 0xc1e7, 0x2400, 0x9c06, 0x0904, 0xc1e7,
-	0x3e08, 0x9186, 0x0002, 0x1148, 0x6010, 0x9005, 0x0130, 0x00b6,
-	0x2058, 0xb800, 0x00be, 0xd0bc, 0x1590, 0x00c6, 0x6043, 0xffff,
-	0x6000, 0x9086, 0x0004, 0x1110, 0x080c, 0x1ad3, 0x9786, 0x000a,
-	0x0148, 0x080c, 0xd132, 0x1130, 0x00ce, 0x080c, 0xbb5c, 0x080c,
-	0xb1a7, 0x00e8, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x01a8, 0x9786,
-	0x0003, 0x1530, 0xa867, 0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096,
-	0xa878, 0x2048, 0x080c, 0x100b, 0x009e, 0xab7a, 0xa877, 0x0000,
-	0x080c, 0x7006, 0x080c, 0xd10c, 0x080c, 0xb1a7, 0x00ce, 0x9ce0,
-	0x001c, 0x7068, 0x9c02, 0x1210, 0x0804, 0xc18e, 0x012e, 0x000e,
-	0x002e, 0x004e, 0x005e, 0x007e, 0x00ce, 0x009e, 0x00ee, 0x0005,
-	0x9786, 0x0006, 0x1118, 0x080c, 0xea30, 0x0c30, 0x9786, 0x0009,
-	0x1148, 0x6000, 0x9086, 0x0004, 0x0d08, 0x2009, 0x004c, 0x080c,
-	0xb20a, 0x08e0, 0x9786, 0x000a, 0x0980, 0x0820, 0x220c, 0x2304,
-	0x9106, 0x1130, 0x8210, 0x8318, 0x1f04, 0xc20e, 0x9006, 0x0005,
-	0x2304, 0x9102, 0x0218, 0x2001, 0x0001, 0x0008, 0x9006, 0x918d,
-	0x0001, 0x0005, 0x0136, 0x01c6, 0x0016, 0x8906, 0x8006, 0x8007,
-	0x908c, 0x003f, 0x21e0, 0x9084, 0xffc0, 0x9300, 0x2098, 0x3518,
-	0x20a9, 0x0001, 0x220c, 0x4002, 0x910e, 0x1140, 0x8210, 0x8319,
-	0x1dc8, 0x9006, 0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x9102,
-	0x0218, 0x2001, 0x0001, 0x0010, 0x2001, 0x0000, 0x918d, 0x0001,
-	0x001e, 0x01ce, 0x013e, 0x0005, 0x220c, 0x810f, 0x2304, 0x9106,
-	0x1130, 0x8210, 0x8318, 0x1f04, 0xc24c, 0x9006, 0x0005, 0x918d,
-	0x0001, 0x0005, 0x6004, 0x908a, 0x0053, 0x1a0c, 0x0d85, 0x080c,
-	0xd121, 0x0120, 0x080c, 0xd132, 0x0158, 0x0028, 0x080c, 0x3344,
-	0x080c, 0xd132, 0x0128, 0x080c, 0x99ed, 0x080c, 0xb16c, 0x0005,
-	0x080c, 0xbb5c, 0x0cc0, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040,
-	0x0208, 0x000a, 0x0005, 0xc292, 0xc292, 0xc292, 0xc292, 0xc292,
-	0xc292, 0xc292, 0xc292, 0xc292, 0xc292, 0xc292, 0xc294, 0xc294,
-	0xc294, 0xc294, 0xc292, 0xc292, 0xc292, 0xc294, 0xc292, 0xc292,
-	0xc292, 0xc292, 0x080c, 0x0d85, 0x600b, 0xffff, 0x6003, 0x000f,
-	0x6106, 0x0126, 0x2091, 0x8000, 0x080c, 0xd65d, 0x2009, 0x8000,
-	0x080c, 0x9617, 0x012e, 0x0005, 0x9186, 0x0013, 0x1128, 0x6004,
-	0x9082, 0x0040, 0x0804, 0xc31c, 0x9186, 0x0027, 0x1520, 0x080c,
-	0x99ed, 0x080c, 0x3315, 0x080c, 0xd65a, 0x0096, 0x6114, 0x2148,
-	0x080c, 0xcf1b, 0x0198, 0x080c, 0xd132, 0x1118, 0x080c, 0xbb5c,
-	0x0068, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0xa97c,
-	0xc1c5, 0xa97e, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c,
-	0xb16c, 0x0804, 0x9ab3, 0x9186, 0x0014, 0x1120, 0x6004, 0x9082,
-	0x0040, 0x0030, 0x9186, 0x0053, 0x0110, 0x080c, 0x0d85, 0x0005,
-	0x0002, 0xc2fa, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8,
-	0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8, 0xc313, 0xc313, 0xc313, 0xc313,
-	0xc2f8, 0xc313, 0xc2f8, 0xc313, 0xc2f8, 0xc2f8, 0xc2f8, 0xc2f8,
-	0x080c, 0x0d85, 0x080c, 0x99ed, 0x0096, 0x6114, 0x2148, 0x080c,
-	0xcf1b, 0x0168, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877, 0x0000,
-	0xa880, 0xc0ec, 0xa882, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e,
-	0x080c, 0xb16c, 0x0005, 0x080c, 0x99ed, 0x080c, 0xd132, 0x090c,
-	0xbb5c, 0x080c, 0xb16c, 0x0005, 0x0002, 0xc336, 0xc334, 0xc334,
-	0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334, 0xc334,
-	0xc338, 0xc338, 0xc338, 0xc338, 0xc334, 0xc33a, 0xc334, 0xc338,
-	0xc334, 0xc334, 0xc334, 0xc334, 0x080c, 0x0d85, 0x080c, 0x0d85,
-	0x080c, 0x0d85, 0x080c, 0xb16c, 0x0804, 0x9ab3, 0x9182, 0x0057,
-	0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005, 0xc35d, 0xc35d,
-	0xc35d, 0xc35d, 0xc35d, 0xc396, 0xc488, 0xc35d, 0xc494, 0xc35d,
-	0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d, 0xc35d,
-	0xc35d, 0xc494, 0xc35f, 0xc35d, 0xc492, 0x080c, 0x0d85, 0x00b6,
-	0x0096, 0x6114, 0x2148, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1508,
-	0xa87b, 0x0000, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87c, 0xd0ac,
-	0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x080c, 0x6e27,
-	0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0xb8d0,
-	0x9005, 0x0110, 0x080c, 0x68df, 0x080c, 0xb16c, 0x009e, 0x00be,
-	0x0005, 0xa87c, 0xd0ac, 0x09e0, 0xa838, 0xa934, 0x9105, 0x09c0,
-	0xa880, 0xd0bc, 0x19a8, 0x080c, 0xd267, 0x0c80, 0x00b6, 0x0096,
-	0x6114, 0x2148, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008, 0x9036,
-	0x96b4, 0x0fff, 0x86ff, 0x1590, 0x6010, 0x2058, 0xb800, 0xd0bc,
-	0x1904, 0xc477, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0xa87c,
-	0xd0ac, 0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x080c,
-	0x6e27, 0x6210, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e,
-	0xb8d0, 0x9005, 0x0110, 0x080c, 0x68df, 0x601c, 0xd0fc, 0x1148,
-	0x7044, 0xd0e4, 0x1904, 0xc458, 0x080c, 0xb16c, 0x009e, 0x00be,
-	0x0005, 0x2009, 0x0211, 0x210c, 0x080c, 0x0d85, 0x968c, 0x0c00,
-	0x0150, 0x6010, 0x2058, 0xb800, 0xd0bc, 0x1904, 0xc45c, 0x7348,
-	0xab92, 0x734c, 0xab8e, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0508,
-	0x9186, 0x0028, 0x1118, 0xa87b, 0x001c, 0x00e8, 0xd6dc, 0x01a0,
-	0xa87b, 0x0015, 0xa87c, 0xd0ac, 0x0170, 0xa938, 0xaa34, 0x2100,
-	0x9205, 0x0148, 0x7048, 0x9106, 0x1118, 0x704c, 0x9206, 0x0118,
-	0xa992, 0xaa8e, 0xc6dc, 0x0038, 0xd6d4, 0x0118, 0xa87b, 0x0007,
-	0x0010, 0xa87b, 0x0000, 0xa867, 0x0103, 0xae76, 0x901e, 0xd6c4,
-	0x01d8, 0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4,
-	0x0804, 0xc3a2, 0x735c, 0xab86, 0x83ff, 0x0170, 0x938a, 0x0009,
-	0x0210, 0x2019, 0x0008, 0x0036, 0x2308, 0x2019, 0x0018, 0x2011,
-	0x0025, 0x080c, 0xca7b, 0x003e, 0xd6cc, 0x0904, 0xc3b7, 0x7154,
-	0xa98a, 0x81ff, 0x0904, 0xc3b7, 0x9192, 0x0021, 0x1278, 0x8304,
-	0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xca7b, 0x2011, 0x0205,
-	0x2013, 0x0000, 0x080c, 0xd5e8, 0x0804, 0xc3b7, 0xa868, 0xd0fc,
-	0x0120, 0x2009, 0x0020, 0xa98a, 0x0c50, 0x00a6, 0x2950, 0x080c,
-	0xca1a, 0x00ae, 0x080c, 0xd5e8, 0x080c, 0xca6b, 0x0804, 0xc3b9,
-	0x080c, 0xd22a, 0x0804, 0xc3ce, 0xa87c, 0xd0ac, 0x0904, 0xc3df,
-	0xa880, 0xd0bc, 0x1904, 0xc3df, 0x9684, 0x0400, 0x0130, 0xa838,
-	0xab34, 0x9305, 0x0904, 0xc3df, 0x00b8, 0x7348, 0xa838, 0x9306,
-	0x1198, 0x734c, 0xa834, 0x931e, 0x0904, 0xc3df, 0x0068, 0xa87c,
-	0xd0ac, 0x0904, 0xc3aa, 0xa838, 0xa934, 0x9105, 0x0904, 0xc3aa,
-	0xa880, 0xd0bc, 0x1904, 0xc3aa, 0x080c, 0xd267, 0x0804, 0xc3ce,
-	0x00f6, 0x2079, 0x026c, 0x7c04, 0x7b00, 0x7e0c, 0x7d08, 0x00fe,
-	0x0021, 0x0005, 0x0011, 0x0005, 0x0005, 0x0096, 0x6003, 0x0002,
-	0x6007, 0x0043, 0x6014, 0x2048, 0xa87c, 0xd0ac, 0x0128, 0x009e,
-	0x0005, 0x2130, 0x2228, 0x0058, 0x2400, 0xa9ac, 0x910a, 0x2300,
-	0xaab0, 0x9213, 0x2600, 0x9102, 0x2500, 0x9203, 0x0e90, 0xac46,
-	0xab4a, 0xae36, 0xad3a, 0x6044, 0xd0fc, 0x190c, 0xad25, 0x604b,
-	0x0000, 0x080c, 0x1c9c, 0x1118, 0x6144, 0x080c, 0x9643, 0x009e,
-	0x0005, 0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a,
-	0x0005, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0,
-	0xc4e0, 0xc4e0, 0xc4e0, 0xc4e2, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0,
-	0xc4f3, 0xc4e0, 0xc4e0, 0xc4e0, 0xc4e0, 0xc517, 0xc4e0, 0xc4e0,
-	0x080c, 0x0d85, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c, 0x99ed,
-	0x2019, 0x0001, 0x080c, 0xa596, 0x6003, 0x0002, 0x080c, 0xd662,
-	0x080c, 0x9a48, 0x0005, 0x6004, 0x9086, 0x0040, 0x1110, 0x080c,
-	0x99ed, 0x2019, 0x0001, 0x080c, 0xa596, 0x080c, 0x9a48, 0x080c,
-	0x3315, 0x080c, 0xd65a, 0x0096, 0x6114, 0x2148, 0x080c, 0xcf1b,
-	0x0150, 0xa867, 0x0103, 0xa87b, 0x0029, 0xa877, 0x0000, 0x080c,
-	0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, 0xb16c, 0x0005, 0x080c,
-	0x0d85, 0xa87b, 0x0015, 0xd1fc, 0x0180, 0xa87b, 0x0007, 0x8002,
-	0x8000, 0x810a, 0x9189, 0x0000, 0x0006, 0x0016, 0x2009, 0x1a7c,
-	0x2104, 0x8000, 0x200a, 0x001e, 0x000e, 0xa992, 0xa88e, 0x0005,
-	0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005,
-	0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc551, 0xc54f, 0xc54f,
-	0xc60e, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f, 0xc54f,
-	0xc54f, 0xc54f, 0xc54f, 0xc74e, 0xc54f, 0xc758, 0xc54f, 0x080c,
-	0x0d85, 0x601c, 0xd0bc, 0x0178, 0xd084, 0x0168, 0xd0f4, 0x0120,
-	0xc084, 0x601e, 0x0804, 0xc33e, 0x6114, 0x0096, 0x2148, 0xa87c,
-	0xc0e5, 0xa87e, 0x009e, 0x0076, 0x00a6, 0x00e6, 0x0096, 0x2071,
-	0x0260, 0x6114, 0x2150, 0x601c, 0xd0fc, 0x1110, 0x7644, 0x0008,
-	0x9036, 0xb676, 0x96b4, 0x0fff, 0xb77c, 0xc7e5, 0xb77e, 0x6210,
-	0x00b6, 0x2258, 0xba3c, 0x82ff, 0x0110, 0x8211, 0xba3e, 0x00be,
-	0x86ff, 0x0904, 0xc607, 0x9694, 0xff00, 0x9284, 0x0c00, 0x0120,
-	0x7048, 0xb092, 0x704c, 0xb08e, 0x9284, 0x0300, 0x0904, 0xc607,
-	0x9686, 0x0100, 0x1130, 0x7064, 0x9005, 0x1118, 0xc6c4, 0xb676,
-	0x0c38, 0x080c, 0x1059, 0x090c, 0x0d85, 0x2900, 0xb07a, 0xb77c,
-	0x97bd, 0x0200, 0xb77e, 0xa867, 0x0103, 0xb068, 0xa86a, 0xb06c,
-	0xa86e, 0xb070, 0xa872, 0x7044, 0x9084, 0xf000, 0x9635, 0xae76,
-	0x968c, 0x0c00, 0x0120, 0x7348, 0xab92, 0x734c, 0xab8e, 0x968c,
-	0x00ff, 0x9186, 0x0002, 0x0180, 0x9186, 0x0028, 0x1118, 0xa87b,
-	0x001c, 0x0060, 0xd6dc, 0x0118, 0xa87b, 0x0015, 0x0038, 0xd6d4,
-	0x0118, 0xa87b, 0x0007, 0x0010, 0xa87b, 0x0000, 0xaf7e, 0xb080,
-	0xa882, 0xb084, 0xa886, 0x901e, 0xd6c4, 0x0190, 0x735c, 0xab86,
-	0x83ff, 0x0170, 0x938a, 0x0009, 0x0210, 0x2019, 0x0008, 0x0036,
-	0x2308, 0x2019, 0x0018, 0x2011, 0x0025, 0x080c, 0xca7b, 0x003e,
-	0xd6cc, 0x01e8, 0x7154, 0xa98a, 0x81ff, 0x01c8, 0x9192, 0x0021,
-	0x1260, 0x8304, 0x9098, 0x0018, 0x2011, 0x0029, 0x080c, 0xca7b,
-	0x2011, 0x0205, 0x2013, 0x0000, 0x0050, 0xb068, 0xd0fc, 0x0120,
-	0x2009, 0x0020, 0xa98a, 0x0c68, 0x2950, 0x080c, 0xca1a, 0x080c,
-	0x1a9f, 0x009e, 0x00ee, 0x00ae, 0x007e, 0x0005, 0x2001, 0x1988,
-	0x2004, 0x604a, 0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105,
-	0x1118, 0xa87c, 0xc0dc, 0xa87e, 0x6003, 0x0002, 0x080c, 0xd66b,
-	0x0904, 0xc749, 0x604b, 0x0000, 0x6010, 0x00b6, 0x2058, 0xb800,
-	0x00be, 0xd0bc, 0x1500, 0xd1cc, 0x0904, 0xc70d, 0xa978, 0xa868,
-	0xd0fc, 0x0904, 0xc6ce, 0x0016, 0xa87c, 0x0006, 0xa880, 0x0006,
-	0x00a6, 0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x0904,
-	0xc69b, 0x9086, 0x0028, 0x1904, 0xc687, 0xa87b, 0x001c, 0xb07b,
-	0x001c, 0x0804, 0xc6a3, 0x6024, 0xd0f4, 0x11d0, 0xa838, 0xaa34,
-	0x9205, 0x09c8, 0xa838, 0xaa90, 0x9206, 0x1120, 0xa88c, 0xaa34,
-	0x9206, 0x0988, 0x6024, 0xd0d4, 0x1148, 0xa9ac, 0xa834, 0x9102,
-	0x603a, 0xa9b0, 0xa838, 0x9103, 0x603e, 0x6024, 0xc0f5, 0x6026,
-	0x6010, 0x00b6, 0x2058, 0xb83c, 0x8000, 0xb83e, 0x00be, 0x601c,
-	0xc0fc, 0x601e, 0x9006, 0xa876, 0xa892, 0xa88e, 0xa87c, 0xc0e4,
-	0xa87e, 0xd0cc, 0x0140, 0xc0cc, 0xa87e, 0x0096, 0xa878, 0x2048,
-	0x080c, 0x100b, 0x009e, 0x080c, 0xd267, 0x0804, 0xc749, 0xd1dc,
-	0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd508, 0x0118,
-	0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007,
-	0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938,
-	0x9115, 0x190c, 0xc519, 0xa87c, 0xb07e, 0xa890, 0xb092, 0xa88c,
-	0xb08e, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0019, 0x20a0, 0x20a9,
-	0x0020, 0x8a06, 0x8006, 0x8007, 0x9094, 0x003f, 0x22e0, 0x9084,
-	0xffc0, 0x9080, 0x0019, 0x2098, 0x4003, 0x00ae, 0x000e, 0xa882,
-	0x000e, 0xc0cc, 0xa87e, 0x080c, 0xd5e8, 0x001e, 0xa874, 0x0006,
-	0x2148, 0x080c, 0x100b, 0x001e, 0x0804, 0xc73a, 0x0016, 0x00a6,
-	0x2150, 0xb174, 0x9184, 0x00ff, 0x90b6, 0x0002, 0x01e0, 0x9086,
-	0x0028, 0x1128, 0xa87b, 0x001c, 0xb07b, 0x001c, 0x00e0, 0xd1dc,
-	0x0158, 0xa87b, 0x0015, 0xb07b, 0x0015, 0x080c, 0xd508, 0x0118,
-	0xb174, 0xc1dc, 0xb176, 0x0078, 0xd1d4, 0x0128, 0xa87b, 0x0007,
-	0xb07b, 0x0007, 0x0040, 0xa87c, 0xd0ac, 0x0128, 0xa834, 0xa938,
-	0x9115, 0x190c, 0xc519, 0xa890, 0xb092, 0xa88c, 0xb08e, 0xa87c,
-	0xb07e, 0x00ae, 0x080c, 0x100b, 0x009e, 0x080c, 0xd5e8, 0xa974,
-	0x0016, 0x080c, 0xca6b, 0x001e, 0x0468, 0xa867, 0x0103, 0xa974,
-	0x9184, 0x00ff, 0x90b6, 0x0002, 0x01b0, 0x9086, 0x0028, 0x1118,
-	0xa87b, 0x001c, 0x00d0, 0xd1dc, 0x0148, 0xa87b, 0x0015, 0x080c,
-	0xd508, 0x0118, 0xa974, 0xc1dc, 0xa976, 0x0078, 0xd1d4, 0x0118,
-	0xa87b, 0x0007, 0x0050, 0xa87b, 0x0000, 0xa87c, 0xd0ac, 0x0128,
-	0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0xa974, 0x0016, 0x080c,
-	0x6e27, 0x001e, 0x6010, 0x00b6, 0x2058, 0xba3c, 0xb8d0, 0x0016,
-	0x9005, 0x190c, 0x68df, 0x001e, 0x00be, 0xd1e4, 0x1120, 0x080c,
-	0xb16c, 0x009e, 0x0005, 0x080c, 0xd22a, 0x0cd8, 0x6114, 0x0096,
-	0x2148, 0xa97c, 0x080c, 0xd66b, 0x190c, 0x1abf, 0x009e, 0x0005,
-	0x0096, 0x6114, 0x2148, 0xa83c, 0xa940, 0x9105, 0x01e8, 0xa877,
-	0x0000, 0xa87b, 0x0000, 0xa867, 0x0103, 0x00b6, 0x6010, 0x2058,
-	0xa834, 0xa938, 0x9115, 0x11a0, 0x080c, 0x6e27, 0xba3c, 0x8211,
-	0x0208, 0xba3e, 0xb8d0, 0x9005, 0x0110, 0x080c, 0x68df, 0x080c,
-	0xb16c, 0x00be, 0x009e, 0x0005, 0xa87c, 0xc0dc, 0xa87e, 0x08f8,
-	0xb800, 0xd0bc, 0x1120, 0xa834, 0x080c, 0xc519, 0x0c28, 0xa880,
-	0xd0bc, 0x1dc8, 0x080c, 0xd267, 0x0c60, 0x080c, 0x99ed, 0x0010,
-	0x080c, 0x9a48, 0x601c, 0xd084, 0x0110, 0x080c, 0x1ad3, 0x080c,
-	0xcf1b, 0x01f0, 0x0096, 0x6114, 0x2148, 0x080c, 0xd132, 0x1118,
-	0x080c, 0xbb5c, 0x00a0, 0xa867, 0x0103, 0x2009, 0x180c, 0x210c,
-	0xd18c, 0x1198, 0xd184, 0x1170, 0x6108, 0xa97a, 0x918e, 0x0029,
-	0x1110, 0x080c, 0xeddf, 0xa877, 0x0000, 0x080c, 0x7012, 0x009e,
-	0x0804, 0xb1a7, 0xa87b, 0x0004, 0x0cb0, 0xa87b, 0x0004, 0x0c98,
-	0x9182, 0x0057, 0x1220, 0x9182, 0x0040, 0x0208, 0x000a, 0x0005,
-	0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7e1, 0xc7df, 0xc7df,
-	0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc7df,
-	0xc7df, 0xc7df, 0xc7df, 0xc7df, 0xc805, 0xc7df, 0xc7df, 0x080c,
-	0x0d85, 0x080c, 0x5848, 0x01f8, 0x6014, 0x7144, 0x918c, 0x0fff,
-	0x9016, 0xd1c4, 0x0118, 0x7264, 0x9294, 0x00ff, 0x0096, 0x904d,
-	0x0188, 0xa87b, 0x0000, 0xa864, 0x9086, 0x0139, 0x0128, 0xa867,
-	0x0103, 0xa976, 0xaa96, 0x0030, 0xa897, 0x4000, 0xa99a, 0xaa9e,
-	0x080c, 0x7012, 0x009e, 0x0804, 0xb16c, 0x080c, 0x5848, 0x0dd8,
-	0x6014, 0x900e, 0x9016, 0x0c10, 0x9182, 0x0085, 0x0002, 0xc81e,
-	0xc81c, 0xc81c, 0xc82a, 0xc81c, 0xc81c, 0xc81c, 0xc81c, 0xc81c,
-	0xc81c, 0xc81c, 0xc81c, 0xc81c, 0x080c, 0x0d85, 0x6003, 0x0001,
-	0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x9617,
-	0x012e, 0x0005, 0x0026, 0x0056, 0x00d6, 0x00e6, 0x2071, 0x0260,
-	0x7224, 0x6216, 0x7220, 0x080c, 0xcf09, 0x01f8, 0x2268, 0x6800,
-	0x9086, 0x0000, 0x01d0, 0x6010, 0x6d10, 0x952e, 0x11b0, 0x00c6,
-	0x2d60, 0x00d6, 0x080c, 0xcadc, 0x00de, 0x00ce, 0x0158, 0x702c,
-	0xd084, 0x1118, 0x080c, 0xcaa6, 0x0010, 0x6803, 0x0002, 0x6007,
-	0x0086, 0x0028, 0x080c, 0xcac8, 0x0d90, 0x6007, 0x0087, 0x6003,
-	0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x7220, 0x080c, 0xcf09,
-	0x0178, 0x6810, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0140,
-	0x6824, 0xd0ec, 0x0128, 0x00c6, 0x2d60, 0x080c, 0xd267, 0x00ce,
-	0x00ee, 0x00de, 0x005e, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160,
-	0x6004, 0x908a, 0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, 0x1a0c,
-	0x0d85, 0x9082, 0x0085, 0x00e2, 0x9186, 0x0027, 0x0120, 0x9186,
-	0x0014, 0x190c, 0x0d85, 0x080c, 0x99ed, 0x0096, 0x6014, 0x2048,
-	0x080c, 0xcf1b, 0x0140, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b,
-	0x0029, 0x080c, 0x7012, 0x009e, 0x080c, 0xb1a7, 0x0804, 0x9ab3,
-	0xc8ad, 0xc8af, 0xc8af, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad,
-	0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0xc8ad, 0x080c, 0x0d85, 0x080c,
-	0xb1a7, 0x0005, 0x9186, 0x0013, 0x1130, 0x6004, 0x9082, 0x0085,
-	0x2008, 0x0804, 0xc8fe, 0x9186, 0x0027, 0x1558, 0x080c, 0x99ed,
-	0x080c, 0x3315, 0x080c, 0xd65a, 0x0096, 0x6014, 0x2048, 0x080c,
-	0xcf1b, 0x0150, 0xa867, 0x0103, 0xa877, 0x0000, 0xa87b, 0x0029,
-	0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x080c, 0xb16c, 0x0005,
-	0x9186, 0x0089, 0x0118, 0x9186, 0x008a, 0x1140, 0x080c, 0xaf61,
-	0x0128, 0x9086, 0x000c, 0x0904, 0xc936, 0x0000, 0x080c, 0xb227,
-	0x0c70, 0x9186, 0x0014, 0x1d60, 0x080c, 0x99ed, 0x0096, 0x6014,
-	0x2048, 0x080c, 0xcf1b, 0x0d00, 0xa867, 0x0103, 0xa877, 0x0000,
-	0xa87b, 0x0006, 0xa880, 0xc0ec, 0xa882, 0x0890, 0x0002, 0xc90e,
-	0xc90c, 0xc90c, 0xc90c, 0xc90c, 0xc90c, 0xc922, 0xc90c, 0xc90c,
-	0xc90c, 0xc90c, 0xc90c, 0xc90c, 0x080c, 0x0d85, 0x6034, 0x908c,
-	0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118,
-	0x2001, 0x1986, 0x0010, 0x2001, 0x1987, 0x2004, 0x601a, 0x6003,
-	0x000c, 0x0005, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0039,
-	0x0118, 0x9186, 0x0035, 0x1118, 0x2001, 0x1986, 0x0010, 0x2001,
-	0x1987, 0x2004, 0x601a, 0x6003, 0x000e, 0x0005, 0x9182, 0x0092,
-	0x1220, 0x9182, 0x0085, 0x0208, 0x0012, 0x0804, 0xb227, 0xc94c,
-	0xc94c, 0xc94c, 0xc94c, 0xc94e, 0xc99b, 0xc94c, 0xc94c, 0xc94c,
-	0xc94c, 0xc94c, 0xc94c, 0xc94c, 0x080c, 0x0d85, 0x0096, 0x6010,
-	0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0168, 0x6034, 0x908c,
-	0xff00, 0x810f, 0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118,
-	0x009e, 0x0804, 0xc9af, 0x080c, 0xcf1b, 0x1118, 0x080c, 0xd10c,
-	0x0068, 0x6014, 0x2048, 0x080c, 0xd671, 0x1110, 0x080c, 0xd10c,
-	0xa867, 0x0103, 0x080c, 0xd625, 0x080c, 0x7012, 0x00d6, 0x2c68,
-	0x080c, 0xb116, 0x01d0, 0x6003, 0x0001, 0x6007, 0x001e, 0x600b,
-	0xffff, 0x2009, 0x026e, 0x210c, 0x613a, 0x2009, 0x026f, 0x210c,
-	0x613e, 0x6910, 0x6112, 0x080c, 0xd3b6, 0x695c, 0x615e, 0x6023,
-	0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x2d60, 0x00de, 0x080c,
-	0xb16c, 0x009e, 0x0005, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be,
-	0xd0bc, 0x05a0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035,
-	0x0130, 0x9186, 0x001e, 0x0118, 0x9186, 0x0039, 0x1538, 0x00d6,
-	0x2c68, 0x080c, 0xd5bb, 0x11f0, 0x080c, 0xb116, 0x01d8, 0x6106,
-	0x6003, 0x0001, 0x6023, 0x0001, 0x6910, 0x6112, 0x692c, 0x612e,
-	0x6930, 0x6132, 0x6934, 0x918c, 0x00ff, 0x6136, 0x6938, 0x613a,
-	0x693c, 0x613e, 0x695c, 0x615e, 0x080c, 0xd3b6, 0x2009, 0x8020,
-	0x080c, 0x9617, 0x2d60, 0x00de, 0x0804, 0xb16c, 0x0096, 0x6014,
-	0x2048, 0x080c, 0xcf1b, 0x01c8, 0xa867, 0x0103, 0xa880, 0xd0b4,
-	0x0128, 0xc0ec, 0xa882, 0xa87b, 0x0006, 0x0048, 0xd0bc, 0x0118,
-	0xa87b, 0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd226, 0xa877,
-	0x0000, 0x080c, 0x7012, 0x080c, 0xd10c, 0x009e, 0x0804, 0xb16c,
-	0x0016, 0x0096, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0140, 0xa867,
-	0x0103, 0xa87b, 0x0028, 0xa877, 0x0000, 0x080c, 0x7012, 0x009e,
-	0x001e, 0x9186, 0x0013, 0x0158, 0x9186, 0x0014, 0x0130, 0x9186,
-	0x0027, 0x0118, 0x080c, 0xb227, 0x0020, 0x080c, 0x99ed, 0x080c,
-	0xb1a7, 0x0005, 0x0056, 0x0066, 0x0096, 0x00a6, 0x2029, 0x0001,
-	0x9182, 0x0101, 0x1208, 0x0010, 0x2009, 0x0100, 0x2130, 0x8304,
-	0x9098, 0x0018, 0x2009, 0x0020, 0x2011, 0x0029, 0x080c, 0xca7b,
-	0x96b2, 0x0020, 0xb004, 0x904d, 0x0110, 0x080c, 0x100b, 0x080c,
-	0x1059, 0x0520, 0x8528, 0xa867, 0x0110, 0xa86b, 0x0000, 0x2920,
-	0xb406, 0x968a, 0x003d, 0x1228, 0x2608, 0x2011, 0x001b, 0x0499,
-	0x00a8, 0x96b2, 0x003c, 0x2009, 0x003c, 0x2950, 0x2011, 0x001b,
-	0x0451, 0x0c28, 0x2001, 0x0205, 0x2003, 0x0000, 0x00ae, 0x852f,
-	0x95ad, 0x0003, 0xb566, 0x95ac, 0x0000, 0x0048, 0x2001, 0x0205,
-	0x2003, 0x0000, 0x00ae, 0x852f, 0x95ad, 0x0003, 0xb566, 0x009e,
-	0x006e, 0x005e, 0x0005, 0x00a6, 0x89ff, 0x0158, 0xa804, 0x9055,
-	0x0130, 0xa807, 0x0000, 0x080c, 0x7012, 0x2a48, 0x0cb8, 0x080c,
-	0x7012, 0x00ae, 0x0005, 0x00f6, 0x2079, 0x0200, 0x7814, 0x9085,
-	0x0080, 0x7816, 0xd184, 0x0108, 0x8108, 0x810c, 0x20a9, 0x0001,
-	0xa860, 0x20e8, 0xa85c, 0x9200, 0x20a0, 0x20e1, 0x0000, 0x2300,
-	0x9e00, 0x2098, 0x4003, 0x8318, 0x9386, 0x0020, 0x1148, 0x2018,
-	0x2300, 0x9e00, 0x2098, 0x7814, 0x8000, 0x9085, 0x0080, 0x7816,
-	0x8109, 0x1d80, 0x7817, 0x0000, 0x00fe, 0x0005, 0x6920, 0x9186,
-	0x0003, 0x0118, 0x9186, 0x0002, 0x11d0, 0x00c6, 0x00d6, 0x00e6,
-	0x2d60, 0x0096, 0x6014, 0x2048, 0x080c, 0xcf1b, 0x0150, 0x2001,
-	0x0006, 0xa980, 0xc1d5, 0x080c, 0x725e, 0x080c, 0x7006, 0x080c,
-	0xd10c, 0x009e, 0x080c, 0xb1a7, 0x00ee, 0x00de, 0x00ce, 0x0005,
-	0x00c6, 0x702c, 0xd084, 0x1170, 0x6008, 0x2060, 0x6020, 0x9086,
-	0x0002, 0x1140, 0x6104, 0x9186, 0x0085, 0x0118, 0x9186, 0x008b,
-	0x1108, 0x9006, 0x00ce, 0x0005, 0x0066, 0x0126, 0x2091, 0x8000,
-	0x2031, 0x0001, 0x6020, 0x9084, 0x000f, 0x0083, 0x012e, 0x006e,
-	0x0005, 0x0126, 0x2091, 0x8000, 0x0066, 0x2031, 0x0000, 0x6020,
-	0x9084, 0x000f, 0x001b, 0x006e, 0x012e, 0x0005, 0xcb2a, 0xcb2a,
-	0xcb25, 0xcb4e, 0xcb06, 0xcb25, 0xcb08, 0xcb25, 0xcb25, 0x9458,
-	0xcb25, 0xcb25, 0xcb25, 0xcb06, 0xcb06, 0xcb06, 0x080c, 0x0d85,
-	0x6010, 0x9080, 0x0000, 0x2004, 0xd0bc, 0x190c, 0xcb4e, 0x0036,
-	0x6014, 0x0096, 0x2048, 0xa880, 0x009e, 0xd0cc, 0x0118, 0x2019,
-	0x000c, 0x0038, 0xd094, 0x0118, 0x2019, 0x000d, 0x0010, 0x2019,
-	0x0010, 0x080c, 0xe578, 0x003e, 0x0005, 0x9006, 0x0005, 0x9085,
-	0x0001, 0x0005, 0x0096, 0x86ff, 0x11e8, 0x6014, 0x2048, 0x080c,
-	0xcf1b, 0x01d0, 0x6043, 0xffff, 0xa864, 0x9086, 0x0139, 0x1128,
-	0xa87b, 0x0005, 0xa883, 0x0000, 0x0028, 0x900e, 0x2001, 0x0005,
-	0x080c, 0x725e, 0x080c, 0xd226, 0x080c, 0x7006, 0x080c, 0xb1a7,
-	0x9085, 0x0001, 0x009e, 0x0005, 0x9006, 0x0ce0, 0x080c, 0xacfc,
-	0x080c, 0xd67f, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x002b, 0x0106,
-	0x080c, 0xad18, 0x010e, 0x0005, 0xcb6c, 0xcb9c, 0xcb6e, 0xcbc3,
-	0xcb97, 0xcb6c, 0xcb25, 0xcb2a, 0xcb2a, 0xcb25, 0xcb25, 0xcb25,
-	0xcb25, 0xcb25, 0xcb25, 0xcb25, 0x080c, 0x0d85, 0x86ff, 0x1520,
-	0x6020, 0x9086, 0x0006, 0x0500, 0x0096, 0x6014, 0x2048, 0x080c,
-	0xcf1b, 0x0168, 0xa87c, 0xd0cc, 0x0140, 0x0096, 0xc0cc, 0xa87e,
-	0xa878, 0x2048, 0x080c, 0x100b, 0x009e, 0x080c, 0xd226, 0x009e,
-	0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002,
-	0x2009, 0x8020, 0x080c, 0x95f9, 0x9085, 0x0001, 0x0005, 0x0066,
-	0x080c, 0x1ad3, 0x006e, 0x0890, 0x00e6, 0x2071, 0x19e8, 0x7030,
-	0x9c06, 0x1120, 0x080c, 0xa516, 0x00ee, 0x0840, 0x6020, 0x9084,
-	0x000f, 0x9086, 0x0006, 0x1150, 0x0086, 0x0096, 0x2049, 0x0001,
-	0x2c40, 0x080c, 0xa667, 0x009e, 0x008e, 0x0040, 0x0066, 0x080c,
-	0xa412, 0x190c, 0x0d85, 0x080c, 0xa420, 0x006e, 0x00ee, 0x1904,
-	0xcb6e, 0x0804, 0xcb25, 0x0036, 0x00e6, 0x2071, 0x19e8, 0x704c,
-	0x9c06, 0x1138, 0x901e, 0x080c, 0xa596, 0x00ee, 0x003e, 0x0804,
-	0xcb6e, 0x080c, 0xa7a1, 0x00ee, 0x003e, 0x1904, 0xcb6e, 0x0804,
-	0xcb25, 0x00c6, 0x0066, 0x6020, 0x9084, 0x000f, 0x001b, 0x006e,
-	0x00ce, 0x0005, 0xcbf9, 0xcce2, 0xce50, 0xcc01, 0xb1a7, 0xcbf9,
-	0xe56e, 0xd667, 0xcce2, 0x941f, 0xcedc, 0xcbf2, 0xcbf2, 0xcbf2,
-	0xcbf2, 0xcbf2, 0x080c, 0x0d85, 0x080c, 0xd132, 0x1110, 0x080c,
-	0xbb5c, 0x0005, 0x080c, 0x99ed, 0x0804, 0xb16c, 0x601b, 0x0001,
-	0x0005, 0x080c, 0xcf1b, 0x0130, 0x6014, 0x0096, 0x2048, 0x2c00,
-	0xa896, 0x009e, 0x080c, 0xacfc, 0x080c, 0xd67f, 0x908a, 0x0010,
-	0x1a0c, 0x0d85, 0x0013, 0x0804, 0xad18, 0xcc25, 0xcc27, 0xcc51,
-	0xcc65, 0xcc92, 0xcc25, 0xcbf9, 0xcbf9, 0xcbf9, 0xcc6c, 0xcc6c,
-	0xcc25, 0xcc25, 0xcc25, 0xcc25, 0xcc76, 0x080c, 0x0d85, 0x00e6,
-	0x6014, 0x0096, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x2071,
-	0x19e8, 0x7030, 0x9c06, 0x01d0, 0x0066, 0x080c, 0xa412, 0x190c,
-	0x0d85, 0x080c, 0xa420, 0x006e, 0x080c, 0xd5ff, 0x6007, 0x0085,
-	0x6003, 0x000b, 0x6023, 0x0002, 0x2001, 0x1987, 0x2004, 0x601a,
-	0x2009, 0x8020, 0x080c, 0x95f9, 0x00ee, 0x0005, 0x601b, 0x0001,
-	0x0cd8, 0x0096, 0x6014, 0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e,
-	0x080c, 0xd5ff, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002,
-	0x2009, 0x8020, 0x080c, 0x95f9, 0x0005, 0x080c, 0xacfc, 0x080c,
-	0xaee3, 0x080c, 0xad18, 0x0c28, 0x0096, 0x601b, 0x0001, 0x6014,
-	0x2048, 0xa880, 0xc0b5, 0xa882, 0x009e, 0x0005, 0x080c, 0x5848,
-	0x01b8, 0x6014, 0x0096, 0x904d, 0x0190, 0xa864, 0xa867, 0x0103,
-	0xa87b, 0x0006, 0x9086, 0x0139, 0x1150, 0xa867, 0x0139, 0xa87b,
-	0x0030, 0xa897, 0x4005, 0xa89b, 0x0004, 0x080c, 0x7012, 0x009e,
-	0x0804, 0xb16c, 0x6014, 0x0096, 0x904d, 0x0904, 0xccdd, 0xa97c,
-	0xd1e4, 0x1160, 0x611c, 0xd1fc, 0x0904, 0xccdd, 0x6110, 0x00b6,
-	0x2158, 0xb93c, 0x8109, 0x0208, 0xb93e, 0x00be, 0x080c, 0xad18,
-	0x2001, 0x180f, 0x2004, 0xd0c4, 0x0110, 0x009e, 0x0005, 0xa884,
-	0x009e, 0x8003, 0x800b, 0x810b, 0x9108, 0x611a, 0x2001, 0x0030,
-	0x2c08, 0x080c, 0x16b9, 0x2001, 0x030c, 0x2004, 0x9086, 0x0041,
-	0x1198, 0x6014, 0x0096, 0x904d, 0x090c, 0x0d85, 0xa880, 0xd0f4,
-	0x1130, 0xc0f5, 0xa882, 0x009e, 0x601b, 0x0002, 0x0068, 0x009e,
-	0x00c6, 0x080c, 0x2185, 0x00ce, 0x6000, 0x9086, 0x0004, 0x1120,
-	0x2009, 0x0048, 0x080c, 0xb20a, 0x0005, 0x009e, 0x080c, 0x1ad3,
-	0x0804, 0xcc51, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x000b,
-	0x0005, 0xccf9, 0xcbfe, 0xccfb, 0xccf9, 0xccfb, 0xccfb, 0xcbfa,
-	0xccf9, 0xcbf4, 0xcbf4, 0xccf9, 0xccf9, 0xccf9, 0xccf9, 0xccf9,
-	0xccf9, 0x080c, 0x0d85, 0x6010, 0x00b6, 0x2058, 0xb804, 0x9084,
-	0x00ff, 0x00be, 0x908a, 0x000c, 0x1a0c, 0x0d85, 0x00b6, 0x0013,
-	0x00be, 0x0005, 0xcd16, 0xcde7, 0xcd18, 0xcd58, 0xcd18, 0xcd58,
-	0xcd18, 0xcd26, 0xcd16, 0xcd58, 0xcd16, 0xcd47, 0x080c, 0x0d85,
-	0x6004, 0x908e, 0x0016, 0x05c0, 0x908e, 0x0004, 0x05a8, 0x908e,
-	0x0002, 0x0590, 0x908e, 0x0052, 0x0904, 0xcde3, 0x6004, 0x080c,
-	0xd132, 0x0904, 0xce00, 0x908e, 0x0004, 0x1110, 0x080c, 0x3344,
-	0x908e, 0x0021, 0x0904, 0xce04, 0x908e, 0x0022, 0x0904, 0xce4b,
-	0x908e, 0x003d, 0x0904, 0xce04, 0x908e, 0x0039, 0x0904, 0xce08,
-	0x908e, 0x0035, 0x0904, 0xce08, 0x908e, 0x001e, 0x0178, 0x908e,
-	0x0001, 0x1140, 0x6010, 0x2058, 0xb804, 0x9084, 0x00ff, 0x9086,
-	0x0006, 0x0110, 0x080c, 0x3315, 0x080c, 0xbb5c, 0x0804, 0xb1a7,
-	0x00c6, 0x00d6, 0x6104, 0x9186, 0x0016, 0x0904, 0xcdd4, 0x9186,
-	0x0002, 0x1904, 0xcda9, 0x2001, 0x1837, 0x2004, 0xd08c, 0x11c8,
-	0x080c, 0x779e, 0x11b0, 0x080c, 0xd645, 0x0138, 0x080c, 0x77c1,
-	0x1120, 0x080c, 0x76a7, 0x0804, 0xce34, 0x2001, 0x197d, 0x2003,
-	0x0001, 0x2001, 0x1800, 0x2003, 0x0001, 0x080c, 0x76cd, 0x0804,
-	0xce34, 0x6010, 0x2058, 0xb8a0, 0x9086, 0x0080, 0x0130, 0x2001,
-	0x1837, 0x2004, 0xd0ac, 0x1904, 0xce34, 0xb8a0, 0x9082, 0x0081,
-	0x1a04, 0xce34, 0xb840, 0x9084, 0x00ff, 0x9005, 0x0190, 0x8001,
-	0xb842, 0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b,
-	0x0000, 0x080c, 0xb116, 0x0128, 0x2b00, 0x6012, 0x6023, 0x0001,
-	0x0458, 0x00de, 0x00ce, 0x6004, 0x908e, 0x0002, 0x11a0, 0x6010,
-	0x2058, 0xb8a0, 0x9086, 0x007e, 0x1170, 0x2009, 0x1837, 0x2104,
-	0xc085, 0x200a, 0x00e6, 0x2071, 0x1800, 0x080c, 0x6130, 0x00ee,
-	0x080c, 0xbb5c, 0x0030, 0x080c, 0xbb5c, 0x080c, 0x3315, 0x080c,
-	0xd65a, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3344, 0x012e,
-	0x00ee, 0x080c, 0xb1a7, 0x0005, 0x2001, 0x0002, 0x080c, 0x66fa,
-	0x6003, 0x0001, 0x6007, 0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3,
-	0x00de, 0x00ce, 0x0c80, 0x080c, 0x3344, 0x0804, 0xcd54, 0x00c6,
-	0x00d6, 0x6104, 0x9186, 0x0016, 0x0d38, 0x6010, 0x2058, 0xb840,
-	0x9084, 0x00ff, 0x9005, 0x0904, 0xcda9, 0x8001, 0xb842, 0x6003,
-	0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00de, 0x00ce, 0x0898,
-	0x080c, 0xbb5c, 0x0804, 0xcd56, 0x080c, 0xbb98, 0x0804, 0xcd56,
-	0x00d6, 0x2c68, 0x6104, 0x080c, 0xd5bb, 0x00de, 0x0118, 0x080c,
-	0xb16c, 0x0408, 0x6004, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105,
-	0x6036, 0x6007, 0x0085, 0x6003, 0x000b, 0x6023, 0x0002, 0x603c,
-	0x600a, 0x2001, 0x1987, 0x2004, 0x601a, 0x602c, 0x2c08, 0x2060,
-	0x6024, 0xd0b4, 0x0108, 0xc085, 0xc0b5, 0x6026, 0x2160, 0x2009,
-	0x8020, 0x080c, 0x9617, 0x0005, 0x00de, 0x00ce, 0x080c, 0xbb5c,
-	0x080c, 0x3315, 0x00e6, 0x0126, 0x2091, 0x8000, 0x080c, 0x3344,
-	0x6017, 0x0000, 0x6023, 0x0007, 0x601b, 0x0398, 0x604b, 0x0000,
-	0x012e, 0x00ee, 0x0005, 0x080c, 0xb5a8, 0x1904, 0xce00, 0x0005,
-	0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85, 0x0096, 0x00d6, 0x001b,
-	0x00de, 0x009e, 0x0005, 0xce6b, 0xce6b, 0xce6b, 0xce6b, 0xce6b,
-	0xce6b, 0xce6b, 0xce6b, 0xce6b, 0xcbf9, 0xce6b, 0xcbfe, 0xce6d,
-	0xcbfe, 0xce87, 0xce6b, 0x080c, 0x0d85, 0x6004, 0x9086, 0x008b,
-	0x01b0, 0x6034, 0x908c, 0xff00, 0x810f, 0x9186, 0x0035, 0x1130,
-	0x602c, 0x9080, 0x0009, 0x200c, 0xc185, 0x2102, 0x6007, 0x008b,
-	0x6003, 0x000d, 0x2009, 0x8020, 0x080c, 0x9617, 0x0005, 0x080c,
-	0xd639, 0x0118, 0x080c, 0xd64c, 0x0010, 0x080c, 0xd65a, 0x080c,
-	0xd10c, 0x080c, 0xcf1b, 0x0570, 0x080c, 0x3315, 0x080c, 0xcf1b,
-	0x0168, 0x6014, 0x2048, 0xa867, 0x0103, 0xa87b, 0x0006, 0xa877,
-	0x0000, 0xa880, 0xc0ed, 0xa882, 0x080c, 0x7012, 0x2c68, 0x080c,
-	0xb116, 0x0150, 0x6810, 0x6012, 0x080c, 0xd3b6, 0x00c6, 0x2d60,
-	0x080c, 0xb1a7, 0x00ce, 0x0008, 0x2d60, 0x6017, 0x0000, 0x6023,
-	0x0001, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, 0x080c,
-	0x9ab3, 0x00c8, 0x080c, 0xd639, 0x0138, 0x6034, 0x9086, 0x4000,
-	0x1118, 0x080c, 0x3315, 0x08d0, 0x6034, 0x908c, 0xff00, 0x810f,
-	0x9186, 0x0039, 0x0118, 0x9186, 0x0035, 0x1118, 0x080c, 0x3315,
-	0x0868, 0x080c, 0xb1a7, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c,
-	0x0d85, 0x0002, 0xcef2, 0xcef2, 0xcefa, 0xcef4, 0xcf04, 0xcef2,
-	0xcef2, 0xb1a7, 0xcef2, 0xcef2, 0xcef2, 0xcef2, 0xcef2, 0xcef2,
-	0xcef2, 0xcef2, 0x080c, 0x0d85, 0x080c, 0xacfc, 0x080c, 0xaee3,
-	0x080c, 0xad18, 0x6114, 0x0096, 0x2148, 0xa87b, 0x0006, 0x080c,
-	0x7012, 0x009e, 0x0804, 0xb16c, 0x601c, 0xd084, 0x190c, 0x1ad3,
-	0x0c88, 0x9284, 0x0003, 0x1158, 0x9282, 0x1ddc, 0x0240, 0x2001,
-	0x181a, 0x2004, 0x9202, 0x1218, 0x9085, 0x0001, 0x0005, 0x9006,
-	0x0ce8, 0x0096, 0x0028, 0x0096, 0x0006, 0x6014, 0x2048, 0x000e,
-	0x0006, 0x9984, 0xf000, 0x9086, 0xf000, 0x0110, 0x080c, 0x1104,
-	0x000e, 0x009e, 0x0005, 0x00e6, 0x00c6, 0x0036, 0x0006, 0x0126,
-	0x2091, 0x8000, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7354, 0x7074,
-	0x9302, 0x1640, 0x6020, 0x9206, 0x11f8, 0x080c, 0xd645, 0x0180,
-	0x9286, 0x0001, 0x1168, 0x6004, 0x9086, 0x0004, 0x1148, 0x080c,
-	0x3315, 0x080c, 0xd65a, 0x00c6, 0x080c, 0xb1a7, 0x00ce, 0x0060,
-	0x080c, 0xd328, 0x0148, 0x080c, 0xd132, 0x1110, 0x080c, 0xbb5c,
-	0x00c6, 0x080c, 0xb16c, 0x00ce, 0x9ce0, 0x001c, 0x7068, 0x9c02,
-	0x1208, 0x08a0, 0x012e, 0x000e, 0x003e, 0x00ce, 0x00ee, 0x0005,
-	0x00e6, 0x00c6, 0x0016, 0x9188, 0x1000, 0x210c, 0x81ff, 0x0128,
-	0x2061, 0x1b39, 0x6112, 0x080c, 0x3315, 0x9006, 0x0010, 0x9085,
-	0x0001, 0x001e, 0x00ce, 0x00ee, 0x0005, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x080c, 0xb116, 0x01b0, 0x665e, 0x2b00, 0x6012, 0x080c,
-	0x5848, 0x0118, 0x080c, 0xd04e, 0x0168, 0x080c, 0xd3b6, 0x6023,
-	0x0003, 0x2009, 0x004b, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e,
-	0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000,
-	0xbaa0, 0x080c, 0xb1dd, 0x0580, 0x605f, 0x0000, 0x2b00, 0x6012,
-	0x080c, 0xd3b6, 0x6023, 0x0003, 0x0016, 0x080c, 0xacfc, 0x080c,
-	0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d,
-	0x007e, 0x080c, 0xad18, 0x001e, 0xd184, 0x0128, 0x080c, 0xb16c,
-	0x9085, 0x0001, 0x0070, 0x080c, 0x5848, 0x0128, 0xd18c, 0x1170,
-	0x080c, 0xd04e, 0x0148, 0x2009, 0x004c, 0x080c, 0xb20a, 0x9085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2900, 0x6016,
-	0x0c90, 0x2009, 0x004d, 0x0010, 0x2009, 0x004e, 0x00f6, 0x00c6,
-	0x0046, 0x0016, 0x080c, 0xb116, 0x2c78, 0x05a0, 0x7e5e, 0x2b00,
-	0x7812, 0x7823, 0x0003, 0x0016, 0x2021, 0x0005, 0x080c, 0xd060,
-	0x001e, 0x9186, 0x004d, 0x0118, 0x9186, 0x004e, 0x0148, 0x2001,
-	0x1980, 0x200c, 0xd1fc, 0x0168, 0x2f60, 0x080c, 0xb16c, 0x00d0,
-	0x2001, 0x197f, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb16c,
-	0x0088, 0x2f60, 0x080c, 0x5848, 0x0138, 0xd18c, 0x1118, 0x04f1,
-	0x0148, 0x0010, 0x2900, 0x7816, 0x001e, 0x0016, 0x080c, 0xb20a,
-	0x9085, 0x0001, 0x001e, 0x004e, 0x00ce, 0x00fe, 0x0005, 0x00f6,
-	0x00c6, 0x0046, 0x080c, 0xb116, 0x2c78, 0x0508, 0x7e5e, 0x2b00,
-	0x7812, 0x7823, 0x0003, 0x0096, 0x2021, 0x0004, 0x0489, 0x009e,
-	0x2001, 0x197e, 0x200c, 0xd1fc, 0x0120, 0x2f60, 0x080c, 0xb16c,
-	0x0060, 0x2f60, 0x080c, 0x5848, 0x0120, 0xd18c, 0x1160, 0x0071,
-	0x0130, 0x2009, 0x0052, 0x080c, 0xb20a, 0x9085, 0x0001, 0x004e,
-	0x00ce, 0x00fe, 0x0005, 0x2900, 0x7816, 0x0c98, 0x00c6, 0x080c,
-	0x4c41, 0x00ce, 0x1120, 0x080c, 0xb16c, 0x9006, 0x0005, 0xa867,
-	0x0000, 0xa86b, 0x8000, 0x2900, 0x6016, 0x9085, 0x0001, 0x0005,
-	0x0096, 0x0076, 0x0126, 0x2091, 0x8000, 0x080c, 0xacfc, 0x080c,
-	0x699d, 0x0158, 0x2001, 0xd067, 0x0006, 0x900e, 0x2400, 0x080c,
-	0x725e, 0x080c, 0x7012, 0x000e, 0x0807, 0x2418, 0x080c, 0x99b3,
-	0xbaa0, 0x0086, 0x2041, 0x0001, 0x2039, 0x0001, 0x2608, 0x080c,
-	0x97ca, 0x008e, 0x080c, 0x966d, 0x2f08, 0x2648, 0x080c, 0xe75d,
-	0xb93c, 0x81ff, 0x090c, 0x98a3, 0x080c, 0xad18, 0x012e, 0x007e,
-	0x009e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb116,
-	0x0190, 0x660a, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001,
-	0x2900, 0x6016, 0x2009, 0x001f, 0x080c, 0xb20a, 0x9085, 0x0001,
-	0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091,
-	0x8000, 0x080c, 0xb1dd, 0x01b8, 0x660a, 0x2b08, 0x6112, 0x080c,
-	0xd3b6, 0x6023, 0x0008, 0x2900, 0x6016, 0x00f6, 0x2c78, 0x080c,
-	0x17ad, 0x00fe, 0x2009, 0x0021, 0x080c, 0xb20a, 0x9085, 0x0001,
-	0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x003d, 0x00c6,
-	0x0126, 0x0016, 0x2091, 0x8000, 0x080c, 0xb116, 0x0198, 0x660a,
-	0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x2900, 0x6016,
-	0x001e, 0x0016, 0x080c, 0xb20a, 0x9085, 0x0001, 0x001e, 0x012e,
-	0x00ce, 0x0005, 0x9006, 0x0cd0, 0x00c6, 0x0126, 0x2091, 0x8000,
-	0x080c, 0xb1dd, 0x0188, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023,
-	0x0001, 0x2900, 0x6016, 0x2009, 0x0000, 0x080c, 0xb20a, 0x9085,
-	0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8, 0x2009, 0x0044,
-	0x0830, 0x2009, 0x0049, 0x0818, 0x0026, 0x00b6, 0x6210, 0x2258,
-	0xba3c, 0x82ff, 0x0118, 0x8211, 0xba3e, 0x1140, 0xb8d0, 0x9005,
-	0x0128, 0xb888, 0x9005, 0x1110, 0xb88b, 0x0001, 0x00be, 0x002e,
-	0x0005, 0x0006, 0x0016, 0x6004, 0x908e, 0x0002, 0x0140, 0x908e,
-	0x0003, 0x0128, 0x908e, 0x0004, 0x0110, 0x9085, 0x0001, 0x001e,
-	0x000e, 0x0005, 0x0006, 0x0086, 0x0096, 0x6020, 0x9086, 0x0004,
-	0x01a8, 0x6014, 0x904d, 0x080c, 0xcf1b, 0x0180, 0xa864, 0x9086,
-	0x0139, 0x0170, 0x6020, 0x90c6, 0x0003, 0x0140, 0x90c6, 0x0002,
-	0x0128, 0xa868, 0xd0fc, 0x0110, 0x9006, 0x0010, 0x9085, 0x0001,
-	0x009e, 0x008e, 0x000e, 0x0005, 0x00c6, 0x0126, 0x2091, 0x8000,
-	0x080c, 0xb1dd, 0x0198, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023,
-	0x0001, 0x2900, 0x6016, 0x080c, 0x3315, 0x2009, 0x0028, 0x080c,
-	0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8,
-	0x9186, 0x0015, 0x11a8, 0x2011, 0x1824, 0x2204, 0x9086, 0x0074,
-	0x1178, 0x00b6, 0x080c, 0xbe09, 0x00be, 0x080c, 0xc085, 0x6003,
-	0x0001, 0x6007, 0x0029, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0078,
-	0x6014, 0x0096, 0x2048, 0xa868, 0x009e, 0xd0fc, 0x0148, 0x2001,
-	0x0001, 0x080c, 0xd57c, 0x080c, 0xbb5c, 0x080c, 0xb16c, 0x0005,
-	0x0096, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa87b, 0x0030, 0xa883,
-	0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x009e, 0x080c, 0xb16c,
-	0x0c30, 0x0096, 0x9186, 0x0016, 0x1128, 0x2001, 0x0004, 0x080c,
-	0x66fa, 0x00e8, 0x9186, 0x0015, 0x1510, 0x2011, 0x1824, 0x2204,
-	0x9086, 0x0014, 0x11e0, 0x6010, 0x00b6, 0x2058, 0x080c, 0x684f,
-	0x00be, 0x080c, 0xc15b, 0x1198, 0x6010, 0x00b6, 0x2058, 0xb890,
-	0x00be, 0x9005, 0x0160, 0x2001, 0x0006, 0x080c, 0x66fa, 0x6014,
-	0x2048, 0xa868, 0xd0fc, 0x0170, 0x080c, 0xb57c, 0x0048, 0x6014,
-	0x2048, 0xa868, 0xd0fc, 0x0528, 0x080c, 0xbb5c, 0x080c, 0xb16c,
-	0x009e, 0x0005, 0x6014, 0x6310, 0x2358, 0x904d, 0x090c, 0x0d85,
-	0xa87b, 0x0000, 0xa883, 0x0000, 0xa897, 0x4000, 0x900e, 0x080c,
-	0x6aae, 0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xa99a,
-	0x0126, 0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c,
-	0x08f8, 0x6014, 0x904d, 0x090c, 0x0d85, 0xa87b, 0x0030, 0xa883,
-	0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0xa867, 0x0139, 0x0126,
-	0x2091, 0x8000, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, 0x0840,
-	0xa878, 0x9086, 0x0005, 0x1108, 0x0009, 0x0005, 0xa880, 0xc0ad,
-	0xa882, 0x0005, 0x604b, 0x0000, 0x6017, 0x0000, 0x6003, 0x0001,
-	0x6007, 0x0050, 0x2009, 0x8023, 0x080c, 0x9617, 0x0005, 0x00c6,
-	0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0130, 0x0066,
-	0x6020, 0x9084, 0x000f, 0x001b, 0x006e, 0x00ce, 0x0005, 0xcbf9,
-	0xd259, 0xd259, 0xd25c, 0xeadc, 0xeaf7, 0xeafa, 0xcbf9, 0xcbf9,
-	0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0xcbf9, 0x080c,
-	0x0d85, 0xa001, 0xa001, 0x0005, 0x0096, 0x6014, 0x904d, 0x0118,
-	0xa87c, 0xd0e4, 0x1110, 0x009e, 0x0010, 0x009e, 0x0005, 0x6010,
-	0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc, 0x0550, 0x2001, 0x1834,
-	0x2004, 0x9005, 0x1540, 0x00f6, 0x2c78, 0x080c, 0xb116, 0x0508,
-	0x7810, 0x6012, 0x080c, 0xd3b6, 0x7820, 0x9086, 0x0003, 0x0128,
-	0x7808, 0x603a, 0x2f00, 0x603e, 0x0020, 0x7808, 0x603e, 0x2f00,
-	0x603a, 0x602e, 0x6023, 0x0001, 0x6007, 0x0035, 0x6003, 0x0001,
-	0x795c, 0x615e, 0x2009, 0x8020, 0x080c, 0x9617, 0x2f60, 0x00fe,
-	0x0005, 0x2f60, 0x00fe, 0x2001, 0x1988, 0x2004, 0x604a, 0x0005,
-	0x0016, 0x0096, 0x6814, 0x2048, 0x681c, 0xd0fc, 0xc0fc, 0x681e,
-	0xa87c, 0x1108, 0xd0e4, 0x0180, 0xc0e4, 0xa87e, 0xa877, 0x0000,
-	0xa893, 0x0000, 0xa88f, 0x0000, 0xd0cc, 0x0130, 0xc0cc, 0xa87e,
-	0xa878, 0x2048, 0x080c, 0x100b, 0x6830, 0x6036, 0x908e, 0x0001,
-	0x0148, 0x6803, 0x0002, 0x9086, 0x0005, 0x0170, 0x9006, 0x602e,
-	0x6032, 0x00d0, 0x681c, 0xc085, 0x681e, 0x6803, 0x0004, 0x6824,
-	0xc0f4, 0x9085, 0x0c00, 0x6826, 0x6814, 0x2048, 0xa8ac, 0x6938,
-	0x9102, 0xa8b0, 0x693c, 0x9103, 0x1e48, 0x683c, 0x602e, 0x6838,
-	0x9084, 0xfffc, 0x683a, 0x6032, 0x2d00, 0x603a, 0x6808, 0x603e,
-	0x6910, 0x6112, 0x695c, 0x615e, 0x6023, 0x0001, 0x6007, 0x0039,
-	0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x009e, 0x001e,
-	0x0005, 0x6024, 0xd0d4, 0x0510, 0xd0f4, 0x11f8, 0x6038, 0x940a,
-	0x603c, 0x9303, 0x0230, 0x9105, 0x0120, 0x6024, 0xc0d4, 0xc0f5,
-	0x0098, 0x643a, 0x633e, 0xac3e, 0xab42, 0x0046, 0x0036, 0x2400,
-	0xacac, 0x9402, 0xa836, 0x2300, 0xabb0, 0x9303, 0xa83a, 0x003e,
-	0x004e, 0x6024, 0xc0d4, 0x0000, 0x6026, 0x0005, 0xd0f4, 0x1138,
-	0xa83c, 0x603a, 0xa840, 0x603e, 0x6024, 0xc0f5, 0x6026, 0x0005,
-	0x0006, 0x0016, 0x6004, 0x908e, 0x0034, 0x01b8, 0x908e, 0x0035,
-	0x01a0, 0x908e, 0x0036, 0x0188, 0x908e, 0x0037, 0x0170, 0x908e,
-	0x0038, 0x0158, 0x908e, 0x0039, 0x0140, 0x908e, 0x003a, 0x0128,
-	0x908e, 0x003b, 0x0110, 0x9085, 0x0001, 0x001e, 0x000e, 0x0005,
-	0x0006, 0x0016, 0x0026, 0x0036, 0x00e6, 0x2001, 0x1982, 0x200c,
-	0x8000, 0x2014, 0x2001, 0x0032, 0x080c, 0x955b, 0x2001, 0x1986,
-	0x82ff, 0x1110, 0x2011, 0x0014, 0x2202, 0x2001, 0x1984, 0x200c,
-	0x8000, 0x2014, 0x2071, 0x196c, 0x711a, 0x721e, 0x2001, 0x0064,
-	0x080c, 0x955b, 0x2001, 0x1987, 0x82ff, 0x1110, 0x2011, 0x0014,
-	0x2202, 0x2001, 0x1988, 0x9288, 0x000a, 0x2102, 0x2001, 0x0017,
-	0x080c, 0xaced, 0x2001, 0x1a90, 0x2102, 0x2001, 0x0032, 0x080c,
-	0x16b9, 0x080c, 0x6bf2, 0x00ee, 0x003e, 0x002e, 0x001e, 0x000e,
-	0x0005, 0x0006, 0x0016, 0x00e6, 0x2001, 0x1986, 0x2003, 0x0028,
-	0x2001, 0x1987, 0x2003, 0x0014, 0x2071, 0x196c, 0x701b, 0x0000,
-	0x701f, 0x07d0, 0x2001, 0x1988, 0x2009, 0x001e, 0x2102, 0x2001,
-	0x0017, 0x080c, 0xaced, 0x2001, 0x1a90, 0x2102, 0x2001, 0x0032,
-	0x080c, 0x16b9, 0x00ee, 0x001e, 0x000e, 0x0005, 0x0096, 0x6060,
-	0x904d, 0x0110, 0x080c, 0x108b, 0x009e, 0x0005, 0x0005, 0x00c6,
-	0x0126, 0x2091, 0x8000, 0x080c, 0xb116, 0x0180, 0x2b08, 0x6112,
-	0x0ca9, 0x6023, 0x0001, 0x2900, 0x6016, 0x2009, 0x0033, 0x080c,
-	0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce, 0x0005, 0x9006, 0x0cd8,
-	0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x1520,
-	0x7090, 0x9086, 0x0018, 0x0120, 0x7090, 0x9086, 0x0014, 0x11e0,
-	0x6014, 0x2048, 0xaa3c, 0xd2e4, 0x1160, 0x2c78, 0x080c, 0x9b83,
-	0x01d8, 0x707c, 0xaa50, 0x9206, 0x1160, 0x7080, 0xaa54, 0x9206,
-	0x1140, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x900e, 0x080c,
-	0x3364, 0x080c, 0xb57c, 0x0020, 0x080c, 0xbb5c, 0x080c, 0xb16c,
-	0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa54, 0x9206, 0x0d48,
-	0x0c80, 0x00c6, 0x0126, 0x2091, 0x8000, 0x080c, 0xb116, 0x0188,
-	0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023, 0x0001, 0x2900, 0x6016,
-	0x2009, 0x004d, 0x080c, 0xb20a, 0x9085, 0x0001, 0x012e, 0x00ce,
-	0x0005, 0x9006, 0x0cd8, 0x00c6, 0x0126, 0x2091, 0x8000, 0x0016,
-	0x080c, 0xb116, 0x0180, 0x2b08, 0x6112, 0x080c, 0xd3b6, 0x6023,
-	0x0001, 0x2900, 0x6016, 0x001e, 0x080c, 0xb20a, 0x9085, 0x0001,
-	0x012e, 0x00ce, 0x0005, 0x001e, 0x9006, 0x0cd0, 0x0016, 0x0026,
-	0x0036, 0x0046, 0x0056, 0x0066, 0x0096, 0x00e6, 0x00f6, 0x2071,
-	0x1800, 0x9186, 0x0015, 0x1568, 0x7190, 0x6014, 0x2048, 0xa814,
-	0x8003, 0x9106, 0x1530, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003,
-	0x0000, 0x6014, 0x2048, 0xa830, 0x20a8, 0x8906, 0x8006, 0x8007,
-	0x9094, 0x003f, 0x22e8, 0x9084, 0xffc0, 0x9080, 0x001b, 0x20a0,
-	0x2001, 0x19a1, 0x0016, 0x200c, 0x080c, 0xdca1, 0x001e, 0xa804,
-	0x9005, 0x0110, 0x2048, 0x0c38, 0x6014, 0x2048, 0xa867, 0x0103,
-	0x0010, 0x080c, 0xbb5c, 0x080c, 0xb16c, 0x00fe, 0x00ee, 0x009e,
-	0x006e, 0x005e, 0x004e, 0x003e, 0x002e, 0x001e, 0x0005, 0x0096,
-	0x00e6, 0x00f6, 0x2071, 0x1800, 0x9186, 0x0015, 0x11b8, 0x7090,
-	0x9086, 0x0004, 0x1198, 0x6014, 0x2048, 0x2c78, 0x080c, 0x9b83,
-	0x01a8, 0x707c, 0xaa74, 0x9206, 0x1130, 0x7080, 0xaa78, 0x9206,
-	0x1110, 0x080c, 0x3315, 0x080c, 0xb57c, 0x0020, 0x080c, 0xbb5c,
-	0x080c, 0xb16c, 0x00fe, 0x00ee, 0x009e, 0x0005, 0x7060, 0xaa78,
-	0x9206, 0x0d78, 0x0c80, 0x0096, 0x00e6, 0x00f6, 0x2071, 0x1800,
-	0x9186, 0x0015, 0x1550, 0x7090, 0x9086, 0x0004, 0x1530, 0x6014,
-	0x2048, 0x2c78, 0x080c, 0x9b83, 0x05f0, 0x707c, 0xaacc, 0x9206,
-	0x1180, 0x7080, 0xaad0, 0x9206, 0x1160, 0x080c, 0x3315, 0x0016,
-	0xa998, 0xaab0, 0x9284, 0x1000, 0xc0fd, 0x080c, 0x57e9, 0x001e,
-	0x0010, 0x080c, 0x55cc, 0x080c, 0xcf1b, 0x0508, 0xa87b, 0x0000,
-	0xa883, 0x0000, 0xa897, 0x4000, 0x0080, 0x080c, 0xcf1b, 0x01b8,
-	0x6014, 0x2048, 0x080c, 0x55cc, 0x1d70, 0xa87b, 0x0030, 0xa883,
-	0x0000, 0xa897, 0x4005, 0xa89b, 0x0004, 0x0126, 0x2091, 0x8000,
-	0xa867, 0x0139, 0x080c, 0x7012, 0x012e, 0x080c, 0xb16c, 0x00fe,
-	0x00ee, 0x009e, 0x0005, 0x7060, 0xaad0, 0x9206, 0x0930, 0x0888,
-	0x0016, 0x0026, 0xa87c, 0xd0ac, 0x0178, 0xa938, 0xaa34, 0x2100,
-	0x9205, 0x0150, 0xa890, 0x9106, 0x1118, 0xa88c, 0x9206, 0x0120,
-	0xa992, 0xaa8e, 0x9085, 0x0001, 0x002e, 0x001e, 0x0005, 0x00b6,
-	0x00d6, 0x0036, 0x080c, 0xcf1b, 0x0904, 0xd578, 0x0096, 0x6314,
-	0x2348, 0xa87a, 0xa982, 0x929e, 0x4000, 0x1580, 0x6310, 0x00c6,
-	0x2358, 0x2009, 0x0000, 0xa868, 0xd0f4, 0x1140, 0x080c, 0x6aae,
-	0x1108, 0xc185, 0xb800, 0xd0bc, 0x0108, 0xc18d, 0xaa96, 0xa99a,
-	0x20a9, 0x0004, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0,
-	0xb8c4, 0x20e0, 0xb8c8, 0x9080, 0x0006, 0x2098, 0x080c, 0x0fd6,
-	0x20a9, 0x0004, 0xa85c, 0x9080, 0x0035, 0x20a0, 0xb8c8, 0x9080,
-	0x000a, 0x2098, 0x080c, 0x0fd6, 0x00ce, 0x0090, 0xaa96, 0x3918,
-	0x9398, 0x0007, 0x231c, 0x6004, 0x9086, 0x0016, 0x0110, 0xa89b,
-	0x0004, 0xaba2, 0x6310, 0x2358, 0xb804, 0x9084, 0x00ff, 0xa89e,
-	0xa868, 0xc0f4, 0xa86a, 0x080c, 0x7006, 0x6017, 0x0000, 0x009e,
-	0x003e, 0x00de, 0x00be, 0x0005, 0x0026, 0x0036, 0x0046, 0x00b6,
-	0x0096, 0x00f6, 0x6214, 0x2248, 0x6210, 0x2258, 0x2079, 0x0260,
-	0x9096, 0x0000, 0x11a0, 0xb814, 0x9084, 0x00ff, 0x900e, 0x080c,
-	0x268c, 0x2118, 0x831f, 0x939c, 0xff00, 0x7838, 0x9084, 0x00ff,
-	0x931d, 0x7c3c, 0x2011, 0x8018, 0x080c, 0x4ca1, 0x00a8, 0x9096,
-	0x0001, 0x1148, 0x89ff, 0x0180, 0xa89b, 0x000d, 0x7838, 0xa8a6,
-	0x783c, 0xa8aa, 0x0048, 0x9096, 0x0002, 0x1130, 0xa89b, 0x000d,
-	0x7838, 0xa8a6, 0x783c, 0xa8aa, 0x00fe, 0x009e, 0x00be, 0x004e,
-	0x003e, 0x002e, 0x0005, 0x00c6, 0x0026, 0x0016, 0x9186, 0x0035,
-	0x0110, 0x6a38, 0x0008, 0x6a2c, 0x080c, 0xcf09, 0x01f0, 0x2260,
-	0x6120, 0x9186, 0x0003, 0x0118, 0x9186, 0x0006, 0x1190, 0x6838,
-	0x9206, 0x0140, 0x683c, 0x9206, 0x1160, 0x6108, 0x6838, 0x9106,
-	0x1140, 0x0020, 0x6008, 0x693c, 0x9106, 0x1118, 0x6010, 0x6910,
-	0x9106, 0x001e, 0x002e, 0x00ce, 0x0005, 0x9085, 0x0001, 0x0cc8,
-	0xa974, 0xd1cc, 0x0198, 0x918c, 0x00ff, 0x918e, 0x0002, 0x1170,
-	0xa9a8, 0x918c, 0x000f, 0x918e, 0x0001, 0x1140, 0xa87c, 0xd0ac,
-	0x0128, 0xa834, 0xa938, 0x9115, 0x190c, 0xc519, 0x0005, 0x0036,
-	0x2019, 0x0001, 0x0010, 0x0036, 0x901e, 0x0499, 0x01e0, 0x080c,
-	0xcf1b, 0x01c8, 0x080c, 0xd10c, 0x6037, 0x4000, 0x6014, 0x6017,
-	0x0000, 0x0096, 0x2048, 0xa87c, 0x080c, 0xd132, 0x1118, 0x080c,
-	0xbb5c, 0x0040, 0xa867, 0x0103, 0xa877, 0x0000, 0x83ff, 0x1129,
-	0x080c, 0x7012, 0x009e, 0x003e, 0x0005, 0xa880, 0xd0b4, 0x0128,
-	0xa87b, 0x0006, 0xc0ec, 0xa882, 0x0048, 0xd0bc, 0x0118, 0xa87b,
-	0x0002, 0x0020, 0xa87b, 0x0005, 0x080c, 0xd226, 0xa877, 0x0000,
-	0x0005, 0x2001, 0x1810, 0x2004, 0xd0ec, 0x0005, 0x0006, 0x2001,
-	0x1810, 0x2004, 0xd0f4, 0x000e, 0x0005, 0x0006, 0x2001, 0x1810,
-	0x2004, 0xd0e4, 0x000e, 0x0005, 0x0036, 0x0046, 0x6010, 0x00b6,
-	0x2058, 0xbba0, 0x00be, 0x2021, 0x0007, 0x080c, 0x4e58, 0x004e,
-	0x003e, 0x0005, 0x0c51, 0x1d81, 0x0005, 0x2001, 0x1986, 0x2004,
-	0x601a, 0x0005, 0x2001, 0x1988, 0x2004, 0x604a, 0x0005, 0x080c,
-	0xb16c, 0x0804, 0x9ab3, 0x611c, 0xd1fc, 0xa97c, 0x1108, 0xd1e4,
-	0x0005, 0x601c, 0xd0fc, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x601c,
-	0xd0fc, 0xc0fc, 0x601e, 0xa87c, 0x1108, 0xd0e4, 0x0005, 0x6044,
-	0xd0fc, 0x1138, 0xd0bc, 0x01a0, 0xc0bc, 0x6046, 0x2001, 0x0002,
-	0x0080, 0xd0ac, 0x1168, 0xd0dc, 0x1128, 0x908c, 0x000f, 0x9186,
-	0x0005, 0x1118, 0x2001, 0x0003, 0x0020, 0x2001, 0x0001, 0x0008,
-	0x6000, 0x0005, 0x00b6, 0x0066, 0x6000, 0x90b2, 0x0010, 0x1a0c,
-	0x0d85, 0x001b, 0x006e, 0x00be, 0x0005, 0xd6b5, 0xddfe, 0xdf62,
-	0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6ec, 0xdfe6, 0xd6b5,
-	0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0xd6b5, 0x080c, 0x0d85, 0x0066,
-	0x6000, 0x90b2, 0x0010, 0x1a0c, 0x0d85, 0x0013, 0x006e, 0x0005,
-	0xd6d0, 0xe50b, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0, 0xd6d0,
-	0xe4ba, 0xe55d, 0xd6d0, 0xec10, 0xec44, 0xec10, 0xec44, 0xd6d0,
-	0x080c, 0x0d85, 0x6000, 0x9082, 0x0010, 0x1a0c, 0x0d85, 0x6000,
-	0x000a, 0x0005, 0xd6ea, 0xe1c3, 0xe28e, 0xe2b1, 0xe32d, 0xd6ea,
-	0xe42a, 0xe3b5, 0xdff0, 0xe492, 0xe4a7, 0xd6ea, 0xd6ea, 0xd6ea,
-	0xd6ea, 0xd6ea, 0x080c, 0x0d85, 0x91b2, 0x0053, 0x1a0c, 0x0d85,
-	0x2100, 0x91b2, 0x0040, 0x1a04, 0xdb70, 0x0002, 0xd736, 0xd93e,
-	0xd736, 0xd736, 0xd736, 0xd947, 0xd736, 0xd736, 0xd736, 0xd736,
-	0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736,
-	0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xd738, 0xd79f, 0xd7ae,
-	0xd812, 0xd83d, 0xd8b6, 0xd929, 0xd736, 0xd736, 0xd94a, 0xd736,
-	0xd736, 0xd95f, 0xd96c, 0xd736, 0xd736, 0xd736, 0xd736, 0xd736,
-	0xda12, 0xd736, 0xd736, 0xda26, 0xd736, 0xd736, 0xd9e1, 0xd736,
-	0xd736, 0xd736, 0xda3e, 0xd736, 0xd736, 0xd736, 0xdabb, 0xd736,
-	0xd736, 0xd736, 0xd736, 0xd736, 0xd736, 0xdb38, 0x080c, 0x0d85,
-	0x080c, 0x6bcf, 0x1150, 0x2001, 0x1837, 0x2004, 0xd0cc, 0x1128,
-	0x9084, 0x0009, 0x9086, 0x0008, 0x1140, 0x6007, 0x0009, 0x602f,
-	0x0009, 0x6017, 0x0000, 0x0804, 0xd937, 0x080c, 0x6b6b, 0x00e6,
-	0x00c6, 0x0036, 0x0026, 0x0016, 0x6210, 0x2258, 0xbaa0, 0x0026,
-	0x2019, 0x0029, 0x080c, 0xacfc, 0x080c, 0x97b0, 0x0076, 0x903e,
-	0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e, 0x001e, 0x080c,
-	0xad18, 0x001e, 0x002e, 0x003e, 0x00ce, 0x00ee, 0x6610, 0x2658,
-	0x080c, 0x67c3, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1268,
-	0x0016, 0x0026, 0x6210, 0x00b6, 0x2258, 0xbaa0, 0x00be, 0x2c08,
-	0x080c, 0xee6f, 0x002e, 0x001e, 0x1178, 0x080c, 0xe68b, 0x1904,
-	0xd80a, 0x080c, 0xe627, 0x1120, 0x6007, 0x0008, 0x0804, 0xd937,
-	0x6007, 0x0009, 0x0804, 0xd937, 0x080c, 0xe905, 0x0128, 0x080c,
-	0xe68b, 0x0d78, 0x0804, 0xd80a, 0x6017, 0x1900, 0x0c88, 0x080c,
-	0x344c, 0x1904, 0xdb6d, 0x6106, 0x080c, 0xe5c7, 0x6007, 0x0006,
-	0x0804, 0xd937, 0x6007, 0x0007, 0x0804, 0xd937, 0x080c, 0xec80,
-	0x1904, 0xdb6d, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x00d6, 0x6610,
-	0x2658, 0xbe04, 0x9684, 0x00ff, 0x9082, 0x0006, 0x1220, 0x2001,
-	0x0001, 0x080c, 0x66e6, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006,
-	0x0188, 0x9686, 0x0004, 0x0170, 0xbe04, 0x96b4, 0x00ff, 0x9686,
-	0x0006, 0x0140, 0x9686, 0x0004, 0x0128, 0x9686, 0x0005, 0x0110,
-	0x00de, 0x0480, 0x00e6, 0x2071, 0x0260, 0x7034, 0x9084, 0x0003,
-	0x1140, 0x7034, 0x9082, 0x0014, 0x0220, 0x7030, 0x9084, 0x0003,
-	0x0130, 0x00ee, 0x6017, 0x0000, 0x602f, 0x0007, 0x00b0, 0x00ee,
-	0x080c, 0xe6f3, 0x1190, 0x9686, 0x0006, 0x1140, 0x0026, 0x6210,
-	0x2258, 0xbaa0, 0x900e, 0x080c, 0x3364, 0x002e, 0x080c, 0x684f,
-	0x6007, 0x000a, 0x00de, 0x0804, 0xd937, 0x6007, 0x000b, 0x00de,
-	0x0804, 0xd937, 0x080c, 0x3315, 0x080c, 0xd65a, 0x6007, 0x0001,
-	0x0804, 0xd937, 0x080c, 0xec80, 0x1904, 0xdb6d, 0x080c, 0x344c,
-	0x1904, 0xdb6d, 0x2071, 0x0260, 0x7034, 0x90b4, 0x0003, 0x1948,
-	0x90b2, 0x0014, 0x0a30, 0x7030, 0x9084, 0x0003, 0x1910, 0x6610,
-	0x2658, 0xbe04, 0x9686, 0x0707, 0x09e8, 0x0026, 0x6210, 0x2258,
-	0xbaa0, 0x900e, 0x080c, 0x3364, 0x002e, 0x6007, 0x000c, 0x2001,
-	0x0001, 0x080c, 0xee4e, 0x0804, 0xd937, 0x080c, 0x6bcf, 0x1140,
-	0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008, 0x1110,
-	0x0804, 0xd745, 0x080c, 0x6b6b, 0x6610, 0x2658, 0xbe04, 0x9684,
-	0x00ff, 0x9082, 0x0006, 0x06c8, 0x1138, 0x0026, 0x2001, 0x0006,
-	0x080c, 0x6726, 0x002e, 0x0050, 0x96b4, 0xff00, 0x8637, 0x9686,
-	0x0004, 0x0120, 0x9686, 0x0006, 0x1904, 0xd80a, 0x080c, 0xe700,
-	0x1120, 0x6007, 0x000e, 0x0804, 0xd937, 0x0046, 0x6410, 0x2458,
-	0xbca0, 0x0046, 0x080c, 0x3315, 0x080c, 0xd65a, 0x004e, 0x0016,
-	0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148, 0x2009, 0x0029,
-	0x080c, 0xea8d, 0x6010, 0x2058, 0xb800, 0xc0e5, 0xb802, 0x001e,
-	0x004e, 0x6007, 0x0001, 0x0804, 0xd937, 0x2001, 0x0001, 0x080c,
-	0x66e6, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019,
-	0x1805, 0x2011, 0x0270, 0x080c, 0xc20e, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x9005, 0x0168, 0x96b4, 0xff00, 0x8637, 0x9682, 0x0004,
-	0x0a04, 0xd80a, 0x9682, 0x0007, 0x0a04, 0xd866, 0x0804, 0xd80a,
-	0x6017, 0x1900, 0x6007, 0x0009, 0x0804, 0xd937, 0x080c, 0x6bcf,
-	0x1140, 0x2001, 0x1837, 0x2004, 0x9084, 0x0009, 0x9086, 0x0008,
-	0x1110, 0x0804, 0xd745, 0x080c, 0x6b6b, 0x6610, 0x2658, 0xbe04,
-	0x9684, 0x00ff, 0x0006, 0x0016, 0x908e, 0x0001, 0x0118, 0x908e,
-	0x0000, 0x1118, 0x001e, 0x000e, 0x0080, 0x001e, 0x000e, 0x9082,
-	0x0006, 0x06a0, 0x0150, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0004,
-	0x0120, 0x9686, 0x0006, 0x1904, 0xd80a, 0x080c, 0xe72e, 0x1138,
-	0x080c, 0xe627, 0x1120, 0x6007, 0x0010, 0x0804, 0xd937, 0x0046,
-	0x6410, 0x2458, 0xbca0, 0x0046, 0x080c, 0x3315, 0x080c, 0xd65a,
-	0x004e, 0x0016, 0x9006, 0x2009, 0x1848, 0x210c, 0xd1a4, 0x0148,
-	0x2009, 0x0029, 0x080c, 0xea8d, 0x6010, 0x2058, 0xb800, 0xc0e5,
-	0xb802, 0x001e, 0x004e, 0x6007, 0x0001, 0x0448, 0x080c, 0xe905,
-	0x0198, 0x0016, 0x968c, 0x00ff, 0x9186, 0x0002, 0x0160, 0x9186,
-	0x0003, 0x0148, 0x001e, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006,
-	0x0920, 0x0804, 0xd80a, 0x001e, 0x6017, 0x1900, 0x6007, 0x0009,
-	0x0070, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xec80, 0x1904,
-	0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, 0x6007, 0x0012, 0x6003,
-	0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x6007, 0x0001,
-	0x6003, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0cb0, 0x6007,
-	0x0005, 0x0c68, 0x080c, 0xec80, 0x1904, 0xdb6d, 0x080c, 0x344c,
-	0x1904, 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a, 0x6007, 0x0020,
-	0x6003, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c,
-	0x344c, 0x1904, 0xdb6d, 0x6007, 0x0023, 0x6003, 0x0001, 0x080c,
-	0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, 0xec80, 0x1904, 0xdb6d,
-	0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e, 0x1904, 0xd80a,
-	0x0016, 0x0026, 0x00e6, 0x2071, 0x0260, 0x2c08, 0x2011, 0x1820,
-	0x2214, 0x703c, 0x9206, 0x11e0, 0x2011, 0x181f, 0x2214, 0x7038,
-	0x9084, 0x00ff, 0x9206, 0x11a0, 0x7240, 0x080c, 0xcf09, 0x0570,
-	0x2260, 0x6008, 0x9086, 0xffff, 0x0120, 0x7244, 0x6008, 0x9206,
-	0x1528, 0x6020, 0x9086, 0x0007, 0x1508, 0x080c, 0xb16c, 0x04a0,
-	0x7244, 0x9286, 0xffff, 0x0180, 0x2c08, 0x080c, 0xcf09, 0x01b0,
-	0x2260, 0x7240, 0x6008, 0x9206, 0x1188, 0x6010, 0x9190, 0x0004,
-	0x2214, 0x9206, 0x01b8, 0x0050, 0x7240, 0x2c08, 0x9006, 0x080c,
-	0xea57, 0x1180, 0x7244, 0x9286, 0xffff, 0x01b0, 0x2160, 0x6007,
-	0x0026, 0x6017, 0x1700, 0x7214, 0x9296, 0xffff, 0x1180, 0x6007,
-	0x0025, 0x0068, 0x6020, 0x9086, 0x0007, 0x1d80, 0x6004, 0x9086,
-	0x0024, 0x1110, 0x080c, 0xb16c, 0x2160, 0x6007, 0x0025, 0x6003,
-	0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00ee, 0x002e, 0x001e,
-	0x0005, 0x2001, 0x0001, 0x080c, 0x66e6, 0x0156, 0x0016, 0x0026,
-	0x0036, 0x20a9, 0x0004, 0x2019, 0x1805, 0x2011, 0x0276, 0x080c,
-	0xc20e, 0x003e, 0x002e, 0x001e, 0x015e, 0x0120, 0x6007, 0x0031,
-	0x0804, 0xd937, 0x080c, 0xbe21, 0x080c, 0x779e, 0x1190, 0x0006,
-	0x0026, 0x0036, 0x080c, 0x77b8, 0x1138, 0x080c, 0x7ab6, 0x080c,
-	0x619d, 0x080c, 0x76cd, 0x0010, 0x080c, 0x7772, 0x003e, 0x002e,
-	0x000e, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e,
-	0x1904, 0xd80a, 0x6106, 0x080c, 0xdd5a, 0x1120, 0x6007, 0x002b,
-	0x0804, 0xd937, 0x6007, 0x002c, 0x0804, 0xd937, 0x080c, 0xec80,
-	0x1904, 0xdb6d, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x080c, 0xdd3e,
-	0x1904, 0xd80a, 0x6106, 0x080c, 0xdd5f, 0x1120, 0x6007, 0x002e,
-	0x0804, 0xd937, 0x6007, 0x002f, 0x0804, 0xd937, 0x080c, 0x344c,
-	0x1904, 0xdb6d, 0x00e6, 0x00d6, 0x00c6, 0x6010, 0x2058, 0xb904,
-	0x9184, 0x00ff, 0x9086, 0x0006, 0x0158, 0x9184, 0xff00, 0x8007,
-	0x9086, 0x0006, 0x0128, 0x00ce, 0x00de, 0x00ee, 0x0804, 0xd93e,
-	0x080c, 0x5844, 0xd0e4, 0x0904, 0xdab8, 0x2071, 0x026c, 0x7010,
-	0x603a, 0x7014, 0x603e, 0x7108, 0x720c, 0x080c, 0x6c0d, 0x0140,
-	0x6010, 0x2058, 0xb810, 0x9106, 0x1118, 0xb814, 0x9206, 0x0510,
-	0x080c, 0x6c09, 0x15b8, 0x2069, 0x1800, 0x6880, 0x9206, 0x1590,
-	0x687c, 0x9106, 0x1578, 0x7210, 0x080c, 0xcf09, 0x0590, 0x080c,
-	0xdc2b, 0x0578, 0x080c, 0xeb09, 0x0560, 0x622e, 0x6007, 0x0036,
-	0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00ce, 0x00de,
-	0x00ee, 0x0005, 0x7214, 0x9286, 0xffff, 0x0150, 0x080c, 0xcf09,
-	0x01c0, 0x9280, 0x0002, 0x2004, 0x7110, 0x9106, 0x1190, 0x08e0,
-	0x7210, 0x2c08, 0x9085, 0x0001, 0x080c, 0xea57, 0x2c10, 0x2160,
-	0x0140, 0x0890, 0x6007, 0x0037, 0x602f, 0x0009, 0x6017, 0x1500,
-	0x08b8, 0x6007, 0x0037, 0x602f, 0x0003, 0x6017, 0x1700, 0x0880,
-	0x6007, 0x0012, 0x0868, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x6010,
-	0x2058, 0xb804, 0x9084, 0xff00, 0x8007, 0x9086, 0x0006, 0x1904,
-	0xd93e, 0x00e6, 0x00d6, 0x00c6, 0x080c, 0x5844, 0xd0e4, 0x0904,
-	0xdb30, 0x2069, 0x1800, 0x2071, 0x026c, 0x7008, 0x603a, 0x720c,
-	0x623e, 0x9286, 0xffff, 0x1150, 0x7208, 0x00c6, 0x2c08, 0x9085,
-	0x0001, 0x080c, 0xea57, 0x2c10, 0x00ce, 0x05e8, 0x080c, 0xcf09,
-	0x05d0, 0x7108, 0x9280, 0x0002, 0x2004, 0x9106, 0x15a0, 0x00c6,
-	0x0026, 0x2260, 0x080c, 0xcadc, 0x002e, 0x00ce, 0x7118, 0x918c,
-	0xff00, 0x810f, 0x9186, 0x0001, 0x0178, 0x9186, 0x0005, 0x0118,
-	0x9186, 0x0007, 0x1198, 0x9280, 0x0005, 0x2004, 0x9005, 0x0170,
-	0x080c, 0xdc2b, 0x0904, 0xdab1, 0x0056, 0x7510, 0x7614, 0x080c,
-	0xeb22, 0x005e, 0x00ce, 0x00de, 0x00ee, 0x0005, 0x6007, 0x003b,
-	0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020,
-	0x080c, 0x9617, 0x0c78, 0x6007, 0x003b, 0x602f, 0x0003, 0x6017,
-	0x0300, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x0c10,
-	0x6007, 0x003b, 0x602f, 0x000b, 0x6017, 0x0000, 0x0804, 0xda88,
-	0x00e6, 0x0026, 0x080c, 0x6bcf, 0x0550, 0x080c, 0x6b6b, 0x080c,
-	0xecf1, 0x1518, 0x2071, 0x1800, 0x70dc, 0x9085, 0x0003, 0x70de,
-	0x00f6, 0x2079, 0x0100, 0x72b0, 0x9284, 0x00ff, 0x707e, 0x78e6,
-	0x9284, 0xff00, 0x7280, 0x9205, 0x7082, 0x78ea, 0x00fe, 0x70e7,
-	0x0000, 0x080c, 0x6c0d, 0x0120, 0x2011, 0x1a0a, 0x2013, 0x07d0,
-	0xd0ac, 0x1128, 0x080c, 0x30bf, 0x0010, 0x080c, 0xed25, 0x002e,
-	0x00ee, 0x080c, 0xb16c, 0x0804, 0xd93d, 0x080c, 0xb16c, 0x0005,
-	0x2600, 0x0002, 0xdb84, 0xdbb2, 0xdbc3, 0xdb84, 0xdb84, 0xdb86,
-	0xdbd4, 0xdb84, 0xdb84, 0xdb84, 0xdba0, 0xdb84, 0xdb84, 0xdb84,
-	0xdbdf, 0xdbf5, 0xdc26, 0xdb84, 0x080c, 0x0d85, 0x080c, 0xec80,
-	0x1d20, 0x080c, 0x344c, 0x1d08, 0x7038, 0x6016, 0x6007, 0x0045,
-	0x6003, 0x0001, 0x080c, 0x961e, 0x0005, 0x080c, 0x3315, 0x080c,
-	0xd65a, 0x6007, 0x0001, 0x6003, 0x0001, 0x080c, 0x961e, 0x0005,
-	0x080c, 0xec80, 0x1950, 0x080c, 0x344c, 0x1938, 0x080c, 0xdd3e,
-	0x1d60, 0x703c, 0x6016, 0x6007, 0x004a, 0x6003, 0x0001, 0x080c,
-	0x961e, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x2009, 0x0041,
-	0x080c, 0xed2e, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c, 0x961e,
-	0x080c, 0x9ab3, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d, 0x2009,
-	0x0042, 0x080c, 0xed2e, 0x6007, 0x0047, 0x6003, 0x0001, 0x080c,
-	0x961e, 0x080c, 0x9ab3, 0x0005, 0x080c, 0x344c, 0x1904, 0xdb6d,
-	0x2009, 0x0046, 0x080c, 0xed2e, 0x080c, 0xb16c, 0x0005, 0x2001,
-	0x1824, 0x2004, 0x9082, 0x00e1, 0x1268, 0x080c, 0xdc48, 0x0904,
-	0xdb6d, 0x6007, 0x004e, 0x6003, 0x0001, 0x080c, 0x961e, 0x080c,
-	0x9ab3, 0x0005, 0x6007, 0x0012, 0x0cb0, 0x6007, 0x004f, 0x6017,
-	0x0000, 0x7134, 0x918c, 0x00ff, 0x81ff, 0x0508, 0x9186, 0x0001,
-	0x1160, 0x7140, 0x2001, 0x19be, 0x2004, 0x9106, 0x11b0, 0x7144,
-	0x2001, 0x19bf, 0x2004, 0x9106, 0x0190, 0x9186, 0x0002, 0x1168,
-	0x2011, 0x0276, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019,
-	0x000a, 0x080c, 0xc222, 0x009e, 0x0110, 0x6017, 0x0001, 0x6003,
-	0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x0005, 0x6007, 0x0050,
-	0x703c, 0x6016, 0x0ca0, 0x0016, 0x00e6, 0x2071, 0x0260, 0x00b6,
-	0x00c6, 0x2260, 0x6010, 0x2058, 0xb8d4, 0xd084, 0x0150, 0x7128,
-	0x604c, 0x9106, 0x1120, 0x712c, 0x6050, 0x9106, 0x0110, 0x9006,
-	0x0010, 0x9085, 0x0001, 0x00ce, 0x00be, 0x00ee, 0x001e, 0x0005,
-	0x0016, 0x0096, 0x0086, 0x00e6, 0x01c6, 0x01d6, 0x0126, 0x2091,
-	0x8000, 0x2071, 0x1800, 0x20e1, 0x0000, 0x2001, 0x19a1, 0x2003,
-	0x0000, 0x080c, 0x1072, 0x05a0, 0x2900, 0x6016, 0x7090, 0x8004,
-	0xa816, 0x908a, 0x001e, 0x02d0, 0xa833, 0x001e, 0x20a9, 0x001e,
-	0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1,
-	0x0016, 0x200c, 0x0471, 0x001e, 0x81ff, 0x01b8, 0x2940, 0x080c,
-	0x1072, 0x01b0, 0x2900, 0xa006, 0x2100, 0x0c18, 0xa832, 0x20a8,
-	0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0, 0x2001, 0x19a1,
-	0x0016, 0x200c, 0x00b1, 0x001e, 0x0000, 0x9085, 0x0001, 0x0048,
-	0x2071, 0x1800, 0x7093, 0x0000, 0x6014, 0x2048, 0x080c, 0x100b,
-	0x9006, 0x012e, 0x01de, 0x01ce, 0x00ee, 0x008e, 0x009e, 0x001e,
-	0x0005, 0x0006, 0x0016, 0x0026, 0x0036, 0x00c6, 0x918c, 0xffff,
-	0x11b0, 0x080c, 0x21f9, 0x2099, 0x026c, 0x2001, 0x0014, 0x3518,
-	0x9312, 0x0108, 0x1218, 0x23a8, 0x4003, 0x0400, 0x20a8, 0x4003,
-	0x22a8, 0x8108, 0x080c, 0x21f9, 0x2099, 0x0260, 0x0ca8, 0x080c,
-	0x21f9, 0x2061, 0x19a1, 0x6004, 0x2098, 0x6008, 0x3518, 0x9312,
-	0x0108, 0x1218, 0x23a8, 0x4003, 0x0048, 0x20a8, 0x4003, 0x22a8,
-	0x8108, 0x080c, 0x21f9, 0x2099, 0x0260, 0x0ca8, 0x2061, 0x19a1,
-	0x2019, 0x0280, 0x3300, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001,
-	0x0260, 0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff,
-	0x620a, 0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x0006,
-	0x0016, 0x0026, 0x0036, 0x00c6, 0x81ff, 0x11b8, 0x080c, 0x2211,
-	0x20a1, 0x024c, 0x2001, 0x0014, 0x3518, 0x9312, 0x1218, 0x23a8,
-	0x4003, 0x0418, 0x20a8, 0x4003, 0x82ff, 0x01f8, 0x22a8, 0x8108,
-	0x080c, 0x2211, 0x20a1, 0x0240, 0x0c98, 0x080c, 0x2211, 0x2061,
-	0x19a4, 0x6004, 0x20a0, 0x6008, 0x3518, 0x9312, 0x1218, 0x23a8,
-	0x4003, 0x0058, 0x20a8, 0x4003, 0x82ff, 0x0138, 0x22a8, 0x8108,
-	0x080c, 0x2211, 0x20a1, 0x0240, 0x0c98, 0x2061, 0x19a4, 0x2019,
-	0x0260, 0x3400, 0x931e, 0x0110, 0x6006, 0x0020, 0x2001, 0x0240,
-	0x6006, 0x8108, 0x2162, 0x9292, 0x0021, 0x9296, 0xffff, 0x620a,
-	0x00ce, 0x003e, 0x002e, 0x001e, 0x000e, 0x0005, 0x00b6, 0x0066,
-	0x6610, 0x2658, 0xbe04, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006,
-	0x0170, 0x9686, 0x0004, 0x0158, 0xbe04, 0x96b4, 0x00ff, 0x9686,
-	0x0006, 0x0128, 0x9686, 0x0004, 0x0110, 0x9085, 0x0001, 0x006e,
-	0x00be, 0x0005, 0x00d6, 0x080c, 0xddd4, 0x00de, 0x0005, 0x00d6,
-	0x080c, 0xdde1, 0x1520, 0x680c, 0x908c, 0xff00, 0x6820, 0x9084,
-	0x00ff, 0x9115, 0x6216, 0x6824, 0x602e, 0xd1e4, 0x0130, 0x9006,
-	0x080c, 0xee4e, 0x2009, 0x0001, 0x0078, 0xd1ec, 0x0180, 0x6920,
-	0x918c, 0x00ff, 0x6824, 0x080c, 0x268c, 0x1148, 0x2001, 0x0001,
-	0x080c, 0xee4e, 0x2110, 0x900e, 0x080c, 0x3364, 0x0018, 0x9085,
-	0x0001, 0x0008, 0x9006, 0x00de, 0x0005, 0x00b6, 0x00c6, 0x080c,
-	0xb1dd, 0x0598, 0x0016, 0x0026, 0x00c6, 0x2011, 0x0263, 0x2204,
-	0x8211, 0x220c, 0x080c, 0x268c, 0x1568, 0x080c, 0x6749, 0x1550,
-	0xbe12, 0xbd16, 0x00ce, 0x002e, 0x001e, 0x2b00, 0x6012, 0x080c,
-	0xec80, 0x11c8, 0x080c, 0x344c, 0x11b0, 0x080c, 0xdd3e, 0x0500,
-	0x2001, 0x0007, 0x080c, 0x66fa, 0x2001, 0x0007, 0x080c, 0x6726,
-	0x6017, 0x0000, 0x6023, 0x0001, 0x6007, 0x0001, 0x6003, 0x0001,
-	0x080c, 0x961e, 0x0010, 0x080c, 0xb16c, 0x9085, 0x0001, 0x00ce,
-	0x00be, 0x0005, 0x080c, 0xb16c, 0x00ce, 0x002e, 0x001e, 0x0ca8,
-	0x080c, 0xb16c, 0x9006, 0x0c98, 0x2069, 0x026d, 0x6800, 0x9082,
-	0x0010, 0x1228, 0x6017, 0x0000, 0x9085, 0x0001, 0x0008, 0x9006,
-	0x0005, 0x6017, 0x0000, 0x2069, 0x026c, 0x6808, 0x9084, 0xff00,
-	0x9086, 0x0800, 0x1190, 0x6904, 0x9186, 0x0018, 0x0118, 0x9186,
-	0x0014, 0x1158, 0x810f, 0x6800, 0x9084, 0x00ff, 0x910d, 0x6162,
-	0x908e, 0x0014, 0x0110, 0x908e, 0x0010, 0x0005, 0x6004, 0x90b2,
-	0x0053, 0x1a0c, 0x0d85, 0x91b6, 0x0013, 0x1130, 0x2008, 0x91b2,
-	0x0040, 0x1a04, 0xdf36, 0x0402, 0x91b6, 0x0027, 0x0190, 0x9186,
-	0x0015, 0x0118, 0x9186, 0x0016, 0x1140, 0x080c, 0xaf61, 0x0120,
-	0x9086, 0x0002, 0x0904, 0xbba3, 0x0005, 0x91b6, 0x0014, 0x190c,
-	0x0d85, 0x2001, 0x0007, 0x080c, 0x6726, 0x080c, 0x99ed, 0x080c,
-	0xb1a7, 0x080c, 0x9ab3, 0x0005, 0xde6c, 0xde6e, 0xde6c, 0xde6c,
-	0xde6c, 0xde6e, 0xde7b, 0xdf33, 0xdebd, 0xdf33, 0xdee1, 0xdf33,
-	0xde7b, 0xdf33, 0xdf2b, 0xdf33, 0xdf2b, 0xdf33, 0xdf33, 0xde6c,
-	0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xde6c,
-	0xde6c, 0xde6c, 0xde6e, 0xde6c, 0xdf33, 0xde6c, 0xde6c, 0xdf33,
-	0xde6c, 0xdf30, 0xdf33, 0xde6c, 0xde6c, 0xde6c, 0xde6c, 0xdf33,
-	0xdf33, 0xde6c, 0xdf33, 0xdf33, 0xde6c, 0xde76, 0xde6c, 0xde6c,
-	0xde6c, 0xde6c, 0xdf2f, 0xdf33, 0xde6c, 0xde6c, 0xdf33, 0xdf33,
-	0xde6c, 0xde6c, 0xde6c, 0xde6c, 0x080c, 0x0d85, 0x080c, 0xd65d,
-	0x6003, 0x0002, 0x080c, 0x9ab3, 0x0804, 0xdf35, 0x9006, 0x080c,
-	0x66e6, 0x0804, 0xdf33, 0x080c, 0x6c09, 0x1904, 0xdf33, 0x9006,
-	0x080c, 0x66e6, 0x6010, 0x2058, 0xb810, 0x9086, 0x00ff, 0x1140,
-	0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x00b8,
-	0x6010, 0x2058, 0xb884, 0x9005, 0x0904, 0xdf33, 0x080c, 0x347d,
-	0x1904, 0xdf33, 0x2001, 0x1800, 0x2004, 0x9086, 0x0002, 0x1138,
-	0x00f6, 0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x2001,
-	0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x6110, 0x2158, 0x2009,
-	0x0001, 0x080c, 0x89a1, 0x0804, 0xdf35, 0x6610, 0x2658, 0xbe04,
-	0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x0148, 0x9686, 0x0004,
-	0x0130, 0x080c, 0x9228, 0x2001, 0x0004, 0x080c, 0x6726, 0x080c,
-	0xee9d, 0x0904, 0xdf33, 0x2001, 0x0004, 0x080c, 0x66fa, 0x6023,
-	0x0001, 0x6003, 0x0001, 0x6007, 0x0003, 0x080c, 0x961e, 0x0804,
-	0xdf35, 0x2001, 0x1800, 0x2004, 0x9086, 0x0003, 0x1158, 0x0036,
-	0x0046, 0x6010, 0x2058, 0xbba0, 0x2021, 0x0006, 0x080c, 0x4e58,
-	0x004e, 0x003e, 0x2001, 0x0006, 0x080c, 0xdf4f, 0x6610, 0x2658,
-	0xbe04, 0x0066, 0x96b4, 0xff00, 0x8637, 0x9686, 0x0006, 0x006e,
-	0x0180, 0x2001, 0x0006, 0x080c, 0x6726, 0x9284, 0x00ff, 0x908e,
-	0x0007, 0x0118, 0x908e, 0x0004, 0x1120, 0x2001, 0x0006, 0x080c,
-	0x66fa, 0x080c, 0x6c09, 0x11f8, 0x2001, 0x1837, 0x2004, 0xd0a4,
-	0x01d0, 0xbe04, 0x96b4, 0x00ff, 0x9686, 0x0006, 0x01a0, 0x00f6,
-	0x2079, 0x1800, 0x78a8, 0x8000, 0x78aa, 0x00fe, 0x0804, 0xdea7,
-	0x2001, 0x0004, 0x0030, 0x2001, 0x0006, 0x0409, 0x0020, 0x0018,
-	0x0010, 0x080c, 0x6726, 0x080c, 0xb16c, 0x0005, 0x2600, 0x0002,
-	0xdf4a, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4a, 0xdf4c,
-	0xdf4a, 0xdf4a, 0xdf4c, 0xdf4a, 0xdf4a, 0xdf4a, 0xdf4c, 0xdf4c,
-	0xdf4c, 0xdf4c, 0x080c, 0x0d85, 0x080c, 0xb16c, 0x0005, 0x0016,
-	0x00b6, 0x00d6, 0x6110, 0x2158, 0xb900, 0xd184, 0x0138, 0x080c,
-	0x66fa, 0x9006, 0x080c, 0x66e6, 0x080c, 0x3344, 0x00de, 0x00be,
-	0x001e, 0x0005, 0x6610, 0x2658, 0xb804, 0x9084, 0xff00, 0x8007,
-	0x90b2, 0x000c, 0x1a0c, 0x0d85, 0x91b6, 0x0015, 0x1110, 0x003b,
-	0x0028, 0x91b6, 0x0016, 0x190c, 0x0d85, 0x006b, 0x0005, 0xbc45,
-	0xbc45, 0xbc45, 0xbc45, 0xdfe4, 0xbc45, 0xdfce, 0xdf8f, 0xbc45,
-	0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0xdfe4,
-	0xbc45, 0xdfce, 0xdfd5, 0xbc45, 0xbc45, 0xbc45, 0xbc45, 0x00f6,
-	0x080c, 0x6c09, 0x11d8, 0x080c, 0xd645, 0x11c0, 0x6010, 0x905d,
-	0x01a8, 0xb884, 0x9005, 0x0190, 0x9006, 0x080c, 0x66e6, 0x2001,
-	0x0002, 0x080c, 0x66fa, 0x6023, 0x0001, 0x6003, 0x0001, 0x6007,
-	0x0002, 0x080c, 0x961e, 0x080c, 0x9ab3, 0x00f0, 0x2011, 0x0263,
-	0x2204, 0x8211, 0x220c, 0x080c, 0x268c, 0x11b0, 0x080c, 0x67b4,
-	0x0118, 0x080c, 0xb16c, 0x0080, 0xb810, 0x0006, 0xb814, 0x0006,
-	0xb884, 0x0006, 0x080c, 0x61b7, 0x000e, 0xb886, 0x000e, 0xb816,
-	0x000e, 0xb812, 0x080c, 0xb16c, 0x00fe, 0x0005, 0x6604, 0x96b6,
-	0x001e, 0x1110, 0x080c, 0xb16c, 0x0005, 0x080c, 0xc082, 0x1148,
-	0x6003, 0x0001, 0x6007, 0x0001, 0x080c, 0x961e, 0x080c, 0x9ab3,
-	0x0010, 0x080c, 0xb16c, 0x0005, 0x0804, 0xb16c, 0x6004, 0x908a,
-	0x0053, 0x1a0c, 0x0d85, 0x080c, 0x99ed, 0x080c, 0xb1a7, 0x0005,
-	0x9182, 0x0040, 0x0002, 0xe007, 0xe007, 0xe007, 0xe007, 0xe009,
-	0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007,
-	0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0xe007, 0x080c,
-	0x0d85, 0x0096, 0x00b6, 0x00d6, 0x00e6, 0x00f6, 0x0046, 0x0026,
-	0x6210, 0x2258, 0xb8bc, 0x9005, 0x11b0, 0x6007, 0x0044, 0x2071,
-	0x0260, 0x7444, 0x94a4, 0xff00, 0x0904, 0xe070, 0x080c, 0xee42,
-	0x1170, 0x9486, 0x2000, 0x1158, 0x2009, 0x0001, 0x2011, 0x0200,
-	0x080c, 0x8c44, 0x0020, 0x9026, 0x080c, 0xecc5, 0x0c30, 0x080c,
-	0x1059, 0x090c, 0x0d85, 0x6003, 0x0007, 0xa867, 0x010d, 0x9006,
-	0xa802, 0xa86a, 0xac8a, 0x2c00, 0xa88e, 0x6008, 0xa8e2, 0x6010,
-	0x2058, 0xb8a0, 0x7130, 0xa97a, 0x0016, 0xa876, 0xa87f, 0x0000,
-	0xa883, 0x0000, 0xa887, 0x0036, 0x080c, 0x7012, 0x001e, 0x080c,
-	0xee42, 0x1904, 0xe0d0, 0x9486, 0x2000, 0x1130, 0x2019, 0x0017,
-	0x080c, 0xe9f9, 0x0804, 0xe0d0, 0x9486, 0x0200, 0x1120, 0x080c,
-	0xe984, 0x0804, 0xe0d0, 0x9486, 0x0400, 0x0120, 0x9486, 0x1000,
-	0x1904, 0xe0d0, 0x2019, 0x0002, 0x080c, 0xe9a3, 0x0804, 0xe0d0,
-	0x2069, 0x1a73, 0x6a00, 0xd284, 0x0904, 0xe13a, 0x9284, 0x0300,
-	0x1904, 0xe133, 0x6804, 0x9005, 0x0904, 0xe11b, 0x2d78, 0x6003,
-	0x0007, 0x080c, 0x1072, 0x0904, 0xe0dc, 0x7800, 0xd08c, 0x1118,
-	0x7804, 0x8001, 0x7806, 0x6017, 0x0000, 0x2001, 0x180f, 0x2004,
-	0xd084, 0x1904, 0xe13e, 0x9006, 0xa802, 0xa867, 0x0116, 0xa86a,
-	0x6008, 0xa8e2, 0x2c00, 0xa87a, 0x6010, 0x2058, 0xb8a0, 0x7130,
-	0xa9b6, 0xa876, 0xb928, 0xa9ba, 0xb92c, 0xa9be, 0xb930, 0xa9c2,
-	0xb934, 0xa9c6, 0xa883, 0x003d, 0x7044, 0x9084, 0x0003, 0x9080,
-	0xe0d8, 0x2005, 0xa87e, 0x20a9, 0x000a, 0x2001, 0x0270, 0xaa5c,
-	0x9290, 0x0021, 0x2009, 0x0205, 0x200b, 0x0080, 0x20e1, 0x0000,
-	0xab60, 0x23e8, 0x2098, 0x22a0, 0x4003, 0x200b, 0x0000, 0x2001,
-	0x027a, 0x200c, 0xa9b2, 0x8000, 0x200c, 0xa9ae, 0x080c, 0x7015,
-	0x002e, 0x004e, 0x00fe, 0x00ee, 0x00de, 0x00be, 0x009e, 0x0005,
-	0x0000, 0x0080, 0x0040, 0x0000, 0x2001, 0x1810, 0x2004, 0xd084,
-	0x0120, 0x080c, 0x1059, 0x1904, 0xe085, 0x6017, 0xf100, 0x6003,
-	0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x0c00,
-	0x2069, 0x0260, 0x6848, 0x9084, 0xff00, 0x9086, 0x1200, 0x1198,
-	0x686c, 0x9084, 0x00ff, 0x0016, 0x6114, 0x918c, 0xf700, 0x910d,
-	0x6116, 0x001e, 0x6003, 0x0001, 0x6007, 0x0043, 0x2009, 0xa025,
-	0x080c, 0x9617, 0x0828, 0x6868, 0x602e, 0x686c, 0x6032, 0x6017,
-	0xf200, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c,
-	0x9617, 0x0804, 0xe0d0, 0x2001, 0x180e, 0x2004, 0xd0ec, 0x0120,
-	0x2011, 0x8049, 0x080c, 0x4ca1, 0x6017, 0xf300, 0x0010, 0x6017,
-	0xf100, 0x6003, 0x0001, 0x6007, 0x0041, 0x2009, 0xa022, 0x080c,
-	0x9617, 0x0804, 0xe0d0, 0x6017, 0xf500, 0x0c98, 0x6017, 0xf600,
-	0x0804, 0xe0f0, 0x6017, 0xf200, 0x0804, 0xe0f0, 0xa867, 0x0146,
-	0xa86b, 0x0000, 0x6008, 0xa886, 0x2c00, 0xa87a, 0x7044, 0x9084,
-	0x0003, 0x9080, 0xe0d8, 0x2005, 0xa87e, 0x2928, 0x6010, 0x2058,
-	0xb8a0, 0xa876, 0xb828, 0xa88a, 0xb82c, 0xa88e, 0xb830, 0xa892,
-	0xb834, 0xa896, 0xa883, 0x003d, 0x2009, 0x0205, 0x2104, 0x9085,
-	0x0080, 0x200a, 0x20e1, 0x0000, 0x2011, 0x0210, 0x2214, 0x9294,
-	0x0fff, 0xaaa2, 0x9282, 0x0111, 0x1a0c, 0x0d85, 0x8210, 0x821c,
-	0x2001, 0x026c, 0x2098, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x0029,
-	0x20a0, 0x2011, 0xe1ba, 0x2041, 0x0001, 0x223d, 0x9784, 0x00ff,
-	0x9322, 0x1208, 0x2300, 0x20a8, 0x4003, 0x931a, 0x0530, 0x8210,
-	0xd7fc, 0x1130, 0x8d68, 0x2d0a, 0x2001, 0x0260, 0x2098, 0x0c68,
-	0x2950, 0x080c, 0x1072, 0x0170, 0x2900, 0xb002, 0xa867, 0x0147,
-	0xa86b, 0x0000, 0xa860, 0x20e8, 0xa85c, 0x9080, 0x001b, 0x20a0,
-	0x8840, 0x08d8, 0x2548, 0xa800, 0x902d, 0x0118, 0x080c, 0x108b,
-	0x0cc8, 0x080c, 0x108b, 0x0804, 0xe0dc, 0x2548, 0x8847, 0x9885,
-	0x0046, 0xa866, 0x2009, 0x0205, 0x200b, 0x0000, 0x080c, 0xea30,
-	0x0804, 0xe0d0, 0x8010, 0x0004, 0x801a, 0x0006, 0x8018, 0x0008,
-	0x8016, 0x000a, 0x8014, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a,
-	0x0057, 0x1a0c, 0x0d85, 0x9082, 0x0040, 0x0a0c, 0x0d85, 0x2008,
-	0x0804, 0xe246, 0x9186, 0x0051, 0x0108, 0x0040, 0x080c, 0xaf61,
-	0x01e8, 0x9086, 0x0002, 0x0904, 0xe28e, 0x00c0, 0x9186, 0x0027,
-	0x0180, 0x9186, 0x0048, 0x0128, 0x9186, 0x0014, 0x0150, 0x190c,
-	0x0d85, 0x080c, 0xaf61, 0x0150, 0x9086, 0x0004, 0x0904, 0xe32d,
-	0x0028, 0x6004, 0x9082, 0x0040, 0x2008, 0x001a, 0x080c, 0xb227,
-	0x0005, 0xe20d, 0xe20f, 0xe20f, 0xe236, 0xe20d, 0xe20d, 0xe20d,
-	0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d,
-	0xe20d, 0xe20d, 0xe20d, 0xe20d, 0xe20d, 0x080c, 0x0d85, 0x080c,
-	0x99ed, 0x080c, 0x9ab3, 0x0036, 0x0096, 0x6014, 0x904d, 0x01d8,
-	0x080c, 0xcf1b, 0x01c0, 0x6003, 0x0002, 0x6010, 0x00b6, 0x2058,
-	0xb800, 0x00be, 0xd0bc, 0x1178, 0x2019, 0x0004, 0x080c, 0xea30,
-	0x6017, 0x0000, 0x6018, 0x9005, 0x1120, 0x2001, 0x1987, 0x2004,
-	0x601a, 0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x0096, 0x080c,
-	0x99ed, 0x080c, 0x9ab3, 0x080c, 0xcf1b, 0x0120, 0x6014, 0x2048,
-	0x080c, 0x108b, 0x080c, 0xb1a7, 0x009e, 0x0005, 0x0002, 0xe25b,
-	0xe270, 0xe25d, 0xe285, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b,
-	0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b, 0xe25b,
-	0xe25b, 0xe25b, 0xe25b, 0x080c, 0x0d85, 0x0096, 0x6014, 0x2048,
-	0xa87c, 0xd0b4, 0x0138, 0x6003, 0x0007, 0x2009, 0x0043, 0x080c,
-	0xb20a, 0x0010, 0x6003, 0x0004, 0x080c, 0x9ab3, 0x009e, 0x0005,
-	0x080c, 0xcf1b, 0x0138, 0x6114, 0x0096, 0x2148, 0xa97c, 0x009e,
-	0xd1ec, 0x1138, 0x080c, 0x8c19, 0x080c, 0xb16c, 0x080c, 0x9ab3,
-	0x0005, 0x080c, 0xec89, 0x0db0, 0x0cc8, 0x6003, 0x0001, 0x6007,
-	0x0041, 0x2009, 0xa022, 0x080c, 0x9617, 0x0005, 0x9182, 0x0040,
-	0x0002, 0xe2a5, 0xe2a7, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5,
-	0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5, 0xe2a5,
-	0xe2a5, 0xe2a5, 0xe2a8, 0xe2a5, 0xe2a5, 0x080c, 0x0d85, 0x0005,
-	0x00d6, 0x080c, 0x8c19, 0x00de, 0x080c, 0xece1, 0x080c, 0xb16c,
-	0x0005, 0x9182, 0x0040, 0x0002, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8,
-	0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2ca, 0xe2f5, 0xe2c8,
-	0xe2c8, 0xe2c8, 0xe2c8, 0xe2f5, 0xe2c8, 0xe2c8, 0xe2c8, 0xe2c8,
-	0x080c, 0x0d85, 0x6014, 0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0168,
-	0x908c, 0x0003, 0x918e, 0x0002, 0x0180, 0x6144, 0xd1e4, 0x1168,
-	0x2009, 0x0041, 0x009e, 0x0804, 0xe3b5, 0x6003, 0x0007, 0x601b,
-	0x0000, 0x080c, 0x8c19, 0x009e, 0x0005, 0x6014, 0x2048, 0xa97c,
-	0xd1ec, 0x1130, 0x080c, 0x8c19, 0x080c, 0xb16c, 0x009e, 0x0005,
-	0x080c, 0xec89, 0x0db8, 0x009e, 0x0005, 0x2001, 0x180c, 0x200c,
-	0xc1d4, 0x2102, 0x0036, 0x080c, 0x9a48, 0x080c, 0x9ab3, 0x6014,
-	0x0096, 0x2048, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0bc,
-	0x0188, 0xa87c, 0x9084, 0x0003, 0x9086, 0x0002, 0x0140, 0xa8ac,
-	0x6330, 0x931a, 0x6332, 0xa8b0, 0x632c, 0x931b, 0x632e, 0x6003,
-	0x0002, 0x0080, 0x2019, 0x0004, 0x080c, 0xea30, 0x6018, 0x9005,
-	0x1128, 0x2001, 0x1987, 0x2004, 0x8003, 0x601a, 0x6017, 0x0000,
-	0x6003, 0x0007, 0x009e, 0x003e, 0x0005, 0x9182, 0x0040, 0x0002,
-	0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344,
-	0xe346, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344, 0xe344,
-	0xe344, 0xe344, 0xe344, 0xe391, 0x080c, 0x0d85, 0x6014, 0x0096,
-	0x2048, 0xa834, 0xaa38, 0x6110, 0x00b6, 0x2158, 0xb900, 0x00be,
-	0xd1bc, 0x1190, 0x920d, 0x1518, 0xa87c, 0xd0fc, 0x0128, 0x2009,
-	0x0041, 0x009e, 0x0804, 0xe3b5, 0x6003, 0x0007, 0x601b, 0x0000,
-	0x080c, 0x8c19, 0x009e, 0x0005, 0x6124, 0xd1f4, 0x1d58, 0x0006,
-	0x0046, 0xacac, 0x9422, 0xa9b0, 0x2200, 0x910b, 0x6030, 0x9420,
-	0x6432, 0x602c, 0x9109, 0x612e, 0x004e, 0x000e, 0x08d8, 0x6110,
-	0x00b6, 0x2158, 0xb900, 0x00be, 0xd1bc, 0x1178, 0x2009, 0x180e,
-	0x210c, 0xd19c, 0x0118, 0x6003, 0x0007, 0x0010, 0x6003, 0x0006,
-	0x00e9, 0x080c, 0x8c1b, 0x009e, 0x0005, 0x6003, 0x0002, 0x009e,
-	0x0005, 0x6024, 0xd0f4, 0x0128, 0x080c, 0x16b0, 0x1904, 0xe346,
-	0x0005, 0x6014, 0x0096, 0x2048, 0xa834, 0xa938, 0x009e, 0x9105,
-	0x1120, 0x080c, 0x16b0, 0x1904, 0xe346, 0x0005, 0xd2fc, 0x0140,
-	0x8002, 0x8000, 0x8212, 0x9291, 0x0000, 0x2009, 0x0009, 0x0010,
-	0x2009, 0x0015, 0xaa9a, 0xa896, 0x0005, 0x9182, 0x0040, 0x0208,
-	0x0062, 0x9186, 0x0013, 0x0120, 0x9186, 0x0014, 0x190c, 0x0d85,
-	0x6024, 0xd0dc, 0x090c, 0x0d85, 0x0005, 0xe3d9, 0xe3e5, 0xe3f1,
-	0xe3fd, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3e0, 0xe3db, 0xe3db,
-	0xe3d9, 0xe3d9, 0xe3d9, 0xe3d9, 0xe3db, 0xe3d9, 0xe3db, 0xe3d9,
-	0xe3e0, 0x080c, 0x0d85, 0x6024, 0xd0dc, 0x090c, 0x0d85, 0x0005,
-	0x6014, 0x9005, 0x190c, 0x0d85, 0x0005, 0x6003, 0x0001, 0x6106,
-	0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x95f9, 0x012e,
-	0x0005, 0x6003, 0x0004, 0x6106, 0x0126, 0x2091, 0x8000, 0x2009,
-	0xa001, 0x080c, 0x9617, 0x012e, 0x0005, 0x6003, 0x0003, 0x6106,
-	0x6047, 0x0000, 0x080c, 0x1c6f, 0x0126, 0x2091, 0x8000, 0x6014,
-	0x0096, 0x2048, 0xa87c, 0xd0fc, 0x0188, 0x9084, 0x0003, 0x9086,
-	0x0002, 0x01a0, 0x6024, 0xd0cc, 0x1148, 0xd0c4, 0x1138, 0xa8a8,
-	0x9005, 0x1120, 0x6144, 0x918d, 0xb035, 0x0018, 0x6144, 0x918d,
-	0xa035, 0x009e, 0x080c, 0x965e, 0x012e, 0x0005, 0x6144, 0x918d,
-	0xa032, 0x0cb8, 0x0126, 0x2091, 0x8000, 0x0036, 0x0096, 0x9182,
-	0x0040, 0x0023, 0x009e, 0x003e, 0x012e, 0x0005, 0xe44a, 0xe44c,
-	0xe461, 0xe47b, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a,
-	0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a, 0xe44a,
-	0xe44a, 0xe44a, 0x080c, 0x0d85, 0x6014, 0x2048, 0xa87c, 0xd0fc,
-	0x0510, 0x909c, 0x0003, 0x939e, 0x0003, 0x01e8, 0x6003, 0x0001,
-	0x6106, 0x0126, 0x2091, 0x8000, 0x2009, 0xa022, 0x080c, 0x9617,
-	0x0480, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0168, 0x909c, 0x0003,
-	0x939e, 0x0003, 0x0140, 0x6003, 0x0001, 0x6106, 0x2009, 0xa001,
-	0x080c, 0x9617, 0x00f0, 0x901e, 0x6316, 0x631a, 0x2019, 0x0004,
-	0x080c, 0xea30, 0x00b0, 0x6014, 0x2048, 0xa87c, 0xd0fc, 0x0d98,
-	0x909c, 0x0003, 0x939e, 0x0003, 0x0d70, 0x6003, 0x0003, 0x6106,
-	0x6047, 0x0000, 0x080c, 0x1c6f, 0x6144, 0x918d, 0xa035, 0x080c,
-	0x965e, 0x0005, 0x080c, 0x99ed, 0x6114, 0x81ff, 0x0158, 0x0096,
-	0x2148, 0x080c, 0xeddf, 0x0036, 0x2019, 0x0029, 0x080c, 0xea30,
-	0x003e, 0x009e, 0x080c, 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0x080c,
-	0x9a48, 0x6114, 0x81ff, 0x0158, 0x0096, 0x2148, 0x080c, 0xeddf,
-	0x0036, 0x2019, 0x0029, 0x080c, 0xea30, 0x003e, 0x009e, 0x080c,
-	0xb1a7, 0x0005, 0x9182, 0x0085, 0x0002, 0xe4cc, 0xe4ca, 0xe4ca,
-	0xe4d8, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca, 0xe4ca,
-	0xe4ca, 0xe4ca, 0x080c, 0x0d85, 0x6003, 0x000b, 0x6106, 0x0126,
-	0x2091, 0x8000, 0x2009, 0x8020, 0x080c, 0x9617, 0x012e, 0x0005,
-	0x0026, 0x00e6, 0x080c, 0xec80, 0x0118, 0x080c, 0xb16c, 0x0440,
-	0x2071, 0x0260, 0x7224, 0x6216, 0x2001, 0x180e, 0x2004, 0xd0e4,
-	0x0150, 0x6010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2011,
-	0x014e, 0x080c, 0xb495, 0x7220, 0x080c, 0xe875, 0x0118, 0x6007,
-	0x0086, 0x0040, 0x6007, 0x0087, 0x7224, 0x9296, 0xffff, 0x1110,
-	0x6007, 0x0086, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617,
-	0x00ee, 0x002e, 0x0005, 0x9186, 0x0013, 0x1160, 0x6004, 0x908a,
-	0x0085, 0x0a0c, 0x0d85, 0x908a, 0x0092, 0x1a0c, 0x0d85, 0x9082,
-	0x0085, 0x00a2, 0x9186, 0x0027, 0x0130, 0x9186, 0x0014, 0x0118,
-	0x080c, 0xb227, 0x0050, 0x2001, 0x0007, 0x080c, 0x6726, 0x080c,
-	0x99ed, 0x080c, 0xb1a7, 0x080c, 0x9ab3, 0x0005, 0xe53b, 0xe53d,
-	0xe53d, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b, 0xe53b,
-	0xe53b, 0xe53b, 0xe53b, 0x080c, 0x0d85, 0x080c, 0xb1a7, 0x080c,
-	0x9ab3, 0x0005, 0x9182, 0x0085, 0x0a0c, 0x0d85, 0x9182, 0x0092,
-	0x1a0c, 0x0d85, 0x9182, 0x0085, 0x0002, 0xe55a, 0xe55a, 0xe55a,
-	0xe55c, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a, 0xe55a,
-	0xe55a, 0xe55a, 0x080c, 0x0d85, 0x0005, 0x9186, 0x0013, 0x0148,
-	0x9186, 0x0014, 0x0130, 0x9186, 0x0027, 0x0118, 0x080c, 0xb227,
-	0x0020, 0x080c, 0x99ed, 0x080c, 0xb1a7, 0x0005, 0x0036, 0x080c,
-	0xece1, 0x604b, 0x0000, 0x2019, 0x000b, 0x0011, 0x003e, 0x0005,
-	0x6010, 0x0006, 0x0059, 0x000e, 0x6012, 0x6023, 0x0006, 0x6003,
-	0x0007, 0x601b, 0x0000, 0x604b, 0x0000, 0x0005, 0x0126, 0x0036,
-	0x2091, 0x8000, 0x080c, 0xacfc, 0x0106, 0x0086, 0x2c40, 0x0096,
-	0x904e, 0x080c, 0xa667, 0x009e, 0x008e, 0x1558, 0x0076, 0x2c38,
-	0x080c, 0xa712, 0x007e, 0x1528, 0x6000, 0x9086, 0x0000, 0x0508,
-	0x6020, 0x9086, 0x0007, 0x01e8, 0x0096, 0x601c, 0xd084, 0x0140,
-	0x080c, 0xece1, 0x080c, 0xd65d, 0x080c, 0x1ad3, 0x6023, 0x0007,
-	0x6014, 0x2048, 0x080c, 0xcf1b, 0x0110, 0x080c, 0xea30, 0x009e,
-	0x9006, 0x6046, 0x6016, 0x080c, 0xece1, 0x6023, 0x0007, 0x080c,
-	0xd65d, 0x010e, 0x090c, 0xad18, 0x003e, 0x012e, 0x0005, 0x00f6,
-	0x00c6, 0x00b6, 0x0036, 0x0156, 0x2079, 0x0260, 0x7938, 0x783c,
-	0x080c, 0x268c, 0x1904, 0xe621, 0x0016, 0x00c6, 0x080c, 0x67b4,
-	0x1904, 0xe61f, 0x001e, 0x00c6, 0x080c, 0xd645, 0x1130, 0xb884,
-	0x9005, 0x0118, 0x080c, 0x347d, 0x0148, 0x2b10, 0x2160, 0x6010,
-	0x0006, 0x6212, 0x080c, 0xd64c, 0x000e, 0x6012, 0x00ce, 0x002e,
-	0x0026, 0x0016, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0xa7e2,
-	0x080c, 0x97b0, 0x0076, 0x903e, 0x080c, 0x966d, 0x007e, 0x001e,
-	0x0076, 0x903e, 0x080c, 0xe75d, 0x007e, 0x080c, 0xad18, 0x0026,
-	0xba04, 0x9294, 0xff00, 0x8217, 0x9286, 0x0006, 0x0118, 0x9286,
-	0x0004, 0x1118, 0xbaa0, 0x080c, 0x33e0, 0x002e, 0xbc84, 0x001e,
-	0x080c, 0x61b7, 0xbe12, 0xbd16, 0xbc86, 0x9006, 0x0010, 0x00ce,
-	0x001e, 0x015e, 0x003e, 0x00be, 0x00ce, 0x00fe, 0x0005, 0x00c6,
-	0x00d6, 0x00b6, 0x0016, 0x2009, 0x1824, 0x2104, 0x9086, 0x0074,
-	0x1904, 0xe680, 0x2069, 0x0260, 0x6944, 0x9182, 0x0100, 0x06e0,
-	0x6940, 0x9184, 0x8000, 0x0904, 0xe67d, 0x2001, 0x197c, 0x2004,
-	0x9005, 0x1140, 0x6010, 0x2058, 0xb884, 0x9005, 0x0118, 0x9184,
-	0x0800, 0x0598, 0x6948, 0x918a, 0x0001, 0x0648, 0x080c, 0xee47,
-	0x0118, 0x6978, 0xd1fc, 0x11b8, 0x2009, 0x0205, 0x200b, 0x0001,
-	0x693c, 0x81ff, 0x1198, 0x6944, 0x9182, 0x0100, 0x02a8, 0x6940,
-	0x81ff, 0x1178, 0x6948, 0x918a, 0x0001, 0x0288, 0x6950, 0x918a,
-	0x0001, 0x0298, 0x00d0, 0x6017, 0x0100, 0x00a0, 0x6017, 0x0300,
-	0x0088, 0x6017, 0x0500, 0x0070, 0x6017, 0x0700, 0x0058, 0x6017,
-	0x0900, 0x0040, 0x6017, 0x0b00, 0x0028, 0x6017, 0x0f00, 0x0010,
-	0x6017, 0x2d00, 0x9085, 0x0001, 0x0008, 0x9006, 0x001e, 0x00be,
-	0x00de, 0x00ce, 0x0005, 0x00c6, 0x00b6, 0x0026, 0x0036, 0x0156,
-	0x6210, 0x2258, 0xbb04, 0x9394, 0x00ff, 0x9286, 0x0006, 0x0180,
-	0x9286, 0x0004, 0x0168, 0x9394, 0xff00, 0x8217, 0x9286, 0x0006,
-	0x0138, 0x9286, 0x0004, 0x0120, 0x080c, 0x67c3, 0x0804, 0xe6ec,
-	0x2011, 0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a,
-	0x080c, 0xc222, 0x009e, 0x15c8, 0x2011, 0x027a, 0x20a9, 0x0004,
-	0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x1568,
-	0x0046, 0x0016, 0xbaa0, 0x2220, 0x9006, 0x2009, 0x1848, 0x210c,
-	0xd1a4, 0x0138, 0x2009, 0x0029, 0x080c, 0xea8d, 0xb800, 0xc0e5,
-	0xb802, 0x080c, 0xacfc, 0x2019, 0x0029, 0x080c, 0x97b0, 0x0076,
-	0x2039, 0x0000, 0x080c, 0x966d, 0x2c08, 0x080c, 0xe75d, 0x007e,
-	0x080c, 0xad18, 0x2001, 0x0007, 0x080c, 0x6726, 0x2001, 0x0007,
-	0x080c, 0x66fa, 0x001e, 0x004e, 0x9006, 0x015e, 0x003e, 0x002e,
-	0x00be, 0x00ce, 0x0005, 0x00d6, 0x2069, 0x026e, 0x6800, 0x9086,
-	0x0800, 0x0118, 0x6017, 0x0000, 0x0008, 0x9006, 0x00de, 0x0005,
-	0x00b6, 0x00f6, 0x0016, 0x0026, 0x0036, 0x0156, 0x2079, 0x026c,
-	0x7930, 0x7834, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8,
-	0x2011, 0x0270, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a,
-	0x080c, 0xc222, 0x009e, 0x1158, 0x2011, 0x0274, 0x20a9, 0x0004,
-	0x0096, 0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x015e,
-	0x003e, 0x002e, 0x001e, 0x00fe, 0x00be, 0x0005, 0x00b6, 0x0006,
-	0x0016, 0x0026, 0x0036, 0x0156, 0x2011, 0x0263, 0x2204, 0x8211,
-	0x220c, 0x080c, 0x268c, 0x11d0, 0x080c, 0x67b4, 0x11b8, 0x2011,
-	0x0276, 0x20a9, 0x0004, 0x0096, 0x2b48, 0x2019, 0x000a, 0x080c,
-	0xc222, 0x009e, 0x1158, 0x2011, 0x027a, 0x20a9, 0x0004, 0x0096,
-	0x2b48, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e, 0x015e, 0x003e,
-	0x002e, 0x001e, 0x000e, 0x00be, 0x0005, 0x00e6, 0x00c6, 0x0086,
-	0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0126, 0x2091, 0x8000,
-	0x080c, 0xad5a, 0x0106, 0x190c, 0xacfc, 0x2740, 0x2029, 0x19f4,
-	0x252c, 0x2021, 0x19fb, 0x2424, 0x2061, 0x1ddc, 0x2071, 0x1800,
-	0x7654, 0x7074, 0x81ff, 0x0150, 0x0006, 0x9186, 0x1b39, 0x000e,
-	0x0128, 0x8001, 0x9602, 0x1a04, 0xe803, 0x0018, 0x9606, 0x0904,
-	0xe803, 0x080c, 0x8eee, 0x0904, 0xe7fa, 0x2100, 0x9c06, 0x0904,
-	0xe7fa, 0x6720, 0x9786, 0x0007, 0x0904, 0xe7fa, 0x080c, 0xeace,
-	0x1904, 0xe7fa, 0x080c, 0xee65, 0x0904, 0xe7fa, 0x080c, 0xeabe,
-	0x0904, 0xe7fa, 0x6720, 0x9786, 0x0001, 0x1148, 0x080c, 0x347d,
-	0x0904, 0xe845, 0x6004, 0x9086, 0x0000, 0x1904, 0xe845, 0x9786,
-	0x0004, 0x0904, 0xe845, 0x2500, 0x9c06, 0x0904, 0xe7fa, 0x2400,
-	0x9c06, 0x0904, 0xe7fa, 0x88ff, 0x0118, 0x605c, 0x9906, 0x15d0,
-	0x0096, 0x6043, 0xffff, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016,
-	0x080c, 0x1ad3, 0x001e, 0x9786, 0x000a, 0x0148, 0x080c, 0xd132,
-	0x1130, 0x080c, 0xbb5c, 0x009e, 0x080c, 0xb1a7, 0x0418, 0x6014,
-	0x2048, 0x080c, 0xcf1b, 0x01d8, 0x9786, 0x0003, 0x1588, 0xa867,
-	0x0103, 0xa87c, 0xd0cc, 0x0130, 0x0096, 0xa878, 0x2048, 0x080c,
-	0x100b, 0x009e, 0xab7a, 0xa877, 0x0000, 0x080c, 0xeddf, 0x0016,
-	0x080c, 0xd220, 0x080c, 0x7006, 0x001e, 0x080c, 0xd10c, 0x009e,
-	0x080c, 0xb1a7, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02,
-	0x1210, 0x0804, 0xe776, 0x010e, 0x190c, 0xad18, 0x012e, 0x002e,
-	0x004e, 0x005e, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x0005,
-	0x9786, 0x0006, 0x1150, 0x9386, 0x0005, 0x0128, 0x080c, 0xeddf,
-	0x080c, 0xea30, 0x08e0, 0x009e, 0x08e8, 0x9786, 0x0009, 0x11f8,
-	0x6000, 0x9086, 0x0004, 0x01c0, 0x6000, 0x9086, 0x0003, 0x11a0,
-	0x080c, 0x9a48, 0x0096, 0x6114, 0x2148, 0x080c, 0xcf1b, 0x0118,
-	0x6010, 0x080c, 0x7012, 0x009e, 0x00c6, 0x080c, 0xb16c, 0x00ce,
-	0x0036, 0x080c, 0x9ab3, 0x003e, 0x009e, 0x0804, 0xe7fa, 0x9786,
-	0x000a, 0x0904, 0xe7ea, 0x0804, 0xe7df, 0x81ff, 0x0904, 0xe7fa,
-	0x9180, 0x0001, 0x2004, 0x9086, 0x0018, 0x0138, 0x9180, 0x0001,
-	0x2004, 0x9086, 0x002d, 0x1904, 0xe7fa, 0x6000, 0x9086, 0x0002,
-	0x1904, 0xe7fa, 0x080c, 0xd121, 0x0138, 0x080c, 0xd132, 0x1904,
-	0xe7fa, 0x080c, 0xbb5c, 0x0038, 0x080c, 0x3344, 0x080c, 0xd132,
-	0x1110, 0x080c, 0xbb5c, 0x080c, 0xb1a7, 0x0804, 0xe7fa, 0xa864,
-	0x9084, 0x00ff, 0x9086, 0x0039, 0x0005, 0x00c6, 0x00e6, 0x0016,
-	0x2c08, 0x2170, 0x9006, 0x080c, 0xea57, 0x001e, 0x0120, 0x6020,
-	0x9084, 0x000f, 0x001b, 0x00ee, 0x00ce, 0x0005, 0xe894, 0xe894,
-	0xe894, 0xe894, 0xe894, 0xe894, 0xe896, 0xe894, 0xe894, 0xe894,
-	0xe8bf, 0xb1a7, 0xb1a7, 0xe894, 0x9006, 0x0005, 0x0036, 0x0046,
-	0x0016, 0x7010, 0x00b6, 0x2058, 0xbca0, 0x00be, 0x2c00, 0x2009,
-	0x0020, 0x080c, 0xea8d, 0x001e, 0x004e, 0x2019, 0x0002, 0x080c,
-	0xe586, 0x003e, 0x9085, 0x0001, 0x0005, 0x0096, 0x080c, 0xcf1b,
-	0x0140, 0x6014, 0x904d, 0x080c, 0xcae9, 0x687b, 0x0005, 0x080c,
-	0x7012, 0x009e, 0x080c, 0xb1a7, 0x9085, 0x0001, 0x0005, 0x0019,
-	0x9085, 0x0001, 0x0005, 0x6000, 0x908a, 0x0010, 0x1a0c, 0x0d85,
-	0x000b, 0x0005, 0xe8da, 0xe8da, 0xe8f1, 0xe8e1, 0xe900, 0xe8da,
-	0xe8da, 0xe8dc, 0xe8da, 0xe8da, 0xe8da, 0xe8da, 0xe8da, 0xe8da,
-	0xe8da, 0xe8da, 0x080c, 0x0d85, 0x080c, 0xb1a7, 0x9085, 0x0001,
-	0x0005, 0x0036, 0x00e6, 0x2071, 0x19e8, 0x704c, 0x9c06, 0x1128,
-	0x2019, 0x0001, 0x080c, 0xa596, 0x0010, 0x080c, 0xa7a1, 0x00ee,
-	0x003e, 0x0096, 0x00d6, 0x6014, 0x2048, 0xa87b, 0x0005, 0x080c,
-	0x7012, 0x080c, 0xb1a7, 0x00de, 0x009e, 0x9085, 0x0001, 0x0005,
-	0x601c, 0xd084, 0x190c, 0x1ad3, 0x0c60, 0x2001, 0x0001, 0x080c,
-	0x66e6, 0x0156, 0x0016, 0x0026, 0x0036, 0x20a9, 0x0004, 0x2019,
-	0x1805, 0x2011, 0x0276, 0x080c, 0xc20e, 0x003e, 0x002e, 0x001e,
-	0x015e, 0x9005, 0x0005, 0x00f6, 0x00e6, 0x00c6, 0x0086, 0x0076,
-	0x0066, 0x00b6, 0x0126, 0x2091, 0x8000, 0x2740, 0x2061, 0x1ddc,
-	0x2079, 0x0001, 0x8fff, 0x0904, 0xe977, 0x2071, 0x1800, 0x7654,
-	0x7074, 0x8001, 0x9602, 0x1a04, 0xe977, 0x88ff, 0x0120, 0x2800,
-	0x9c06, 0x15a0, 0x2078, 0x080c, 0xeabe, 0x0580, 0x2400, 0x9c06,
-	0x0568, 0x6720, 0x9786, 0x0006, 0x1548, 0x9786, 0x0007, 0x0530,
-	0x88ff, 0x1150, 0xd58c, 0x1118, 0x6010, 0x9b06, 0x11f8, 0xd584,
-	0x0118, 0x605c, 0x9106, 0x11d0, 0x0096, 0x601c, 0xd084, 0x0140,
-	0x080c, 0xece1, 0x080c, 0xd65d, 0x080c, 0x1ad3, 0x6023, 0x0007,
-	0x6014, 0x2048, 0x080c, 0xcf1b, 0x0120, 0x0046, 0x080c, 0xea30,
-	0x004e, 0x009e, 0x080c, 0xb1a7, 0x88ff, 0x1198, 0x9ce0, 0x001c,
-	0x2001, 0x181a, 0x2004, 0x9c02, 0x1210, 0x0804, 0xe92a, 0x9006,
-	0x012e, 0x00be, 0x006e, 0x007e, 0x008e, 0x00ce, 0x00ee, 0x00fe,
-	0x0005, 0x98c5, 0x0001, 0x0ca0, 0x080c, 0xacfc, 0x00b6, 0x0076,
-	0x0056, 0x0086, 0x9046, 0x2029, 0x0001, 0x2c20, 0x2019, 0x0002,
-	0x6210, 0x2258, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e, 0x008e,
-	0x903e, 0x080c, 0xa712, 0x080c, 0xe91b, 0x005e, 0x007e, 0x00be,
-	0x080c, 0xad18, 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0046, 0x0056,
-	0x0076, 0x00c6, 0x0156, 0x2c20, 0x2128, 0x20a9, 0x007f, 0x900e,
-	0x0016, 0x0036, 0x080c, 0x67b4, 0x1180, 0x0056, 0x0086, 0x9046,
-	0x2508, 0x2029, 0x0001, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e,
-	0x008e, 0x903e, 0x080c, 0xa712, 0x005e, 0x003e, 0x001e, 0x8108,
-	0x1f04, 0xe9b0, 0x0036, 0x2508, 0x2029, 0x0003, 0x080c, 0xe91b,
-	0x003e, 0x015e, 0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c,
-	0xad18, 0x0005, 0x080c, 0xacfc, 0x00b6, 0x0076, 0x0056, 0x6210,
-	0x2258, 0x0086, 0x9046, 0x2029, 0x0001, 0x2019, 0x0048, 0x0096,
-	0x904e, 0x080c, 0xa667, 0x009e, 0x008e, 0x903e, 0x080c, 0xa712,
-	0x2c20, 0x080c, 0xe91b, 0x005e, 0x007e, 0x00be, 0x080c, 0xad18,
-	0x0005, 0x080c, 0xacfc, 0x00b6, 0x0046, 0x0056, 0x0076, 0x00c6,
-	0x0156, 0x2c20, 0x20a9, 0x0800, 0x900e, 0x0016, 0x0036, 0x080c,
-	0x67b4, 0x1190, 0x0086, 0x9046, 0x2828, 0x0046, 0x2021, 0x0001,
-	0x080c, 0xecc5, 0x004e, 0x0096, 0x904e, 0x080c, 0xa667, 0x009e,
-	0x008e, 0x903e, 0x080c, 0xa712, 0x003e, 0x001e, 0x8108, 0x1f04,
-	0xea05, 0x0036, 0x2029, 0x0002, 0x080c, 0xe91b, 0x003e, 0x015e,
-	0x00ce, 0x007e, 0x005e, 0x004e, 0x00be, 0x080c, 0xad18, 0x0005,
-	0x0016, 0x00f6, 0x080c, 0xcf19, 0x0198, 0xa864, 0x9084, 0x00ff,
-	0x9086, 0x0046, 0x0180, 0xa800, 0x907d, 0x0138, 0xa803, 0x0000,
-	0xab82, 0x080c, 0x7012, 0x2f48, 0x0cb0, 0xab82, 0x080c, 0x7012,
-	0x00fe, 0x001e, 0x0005, 0xa800, 0x907d, 0x0130, 0xa803, 0x0000,
-	0x080c, 0x7012, 0x2f48, 0x0cb8, 0x080c, 0x7012, 0x0c88, 0x00e6,
-	0x0046, 0x0036, 0x2061, 0x1ddc, 0x9005, 0x1138, 0x2071, 0x1800,
-	0x7454, 0x7074, 0x8001, 0x9402, 0x12f8, 0x2100, 0x9c06, 0x0188,
-	0x6000, 0x9086, 0x0000, 0x0168, 0x6008, 0x9206, 0x1150, 0x6320,
-	0x9386, 0x0009, 0x01b0, 0x6010, 0x91a0, 0x0004, 0x2424, 0x9406,
-	0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1220,
-	0x0c20, 0x9085, 0x0001, 0x0008, 0x9006, 0x003e, 0x004e, 0x00ee,
-	0x0005, 0x631c, 0xd3c4, 0x1d68, 0x0c30, 0x0096, 0x0006, 0x080c,
-	0x1059, 0x000e, 0x090c, 0x0d85, 0xaae2, 0xa867, 0x010d, 0xa88e,
-	0x0026, 0x2010, 0x080c, 0xcf09, 0x2001, 0x0000, 0x0120, 0x2200,
-	0x9080, 0x0017, 0x2004, 0x002e, 0xa87a, 0x9186, 0x0020, 0x0110,
-	0xa8e3, 0xffff, 0xa986, 0xac76, 0xa87f, 0x0000, 0x2001, 0x198e,
-	0x2004, 0xa882, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x0126, 0x2091,
-	0x8000, 0x080c, 0x7012, 0x012e, 0x009e, 0x0005, 0x6700, 0x9786,
-	0x0000, 0x0158, 0x9786, 0x0001, 0x0140, 0x9786, 0x000a, 0x0128,
-	0x9786, 0x0009, 0x0110, 0x9085, 0x0001, 0x0005, 0x00e6, 0x6010,
-	0x9075, 0x0138, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x9206, 0x00ee,
-	0x0005, 0x9085, 0x0001, 0x0cd8, 0x0016, 0x6004, 0x908e, 0x001e,
-	0x11a0, 0x8007, 0x6134, 0x918c, 0x00ff, 0x9105, 0x6036, 0x6007,
-	0x0085, 0x6003, 0x000b, 0x6023, 0x0005, 0x2001, 0x1987, 0x2004,
-	0x601a, 0x2009, 0x8020, 0x080c, 0x9617, 0x001e, 0x0005, 0xa001,
-	0xa001, 0x0005, 0x6024, 0xd0e4, 0x0158, 0xd0cc, 0x0118, 0x080c,
-	0xd267, 0x0030, 0x080c, 0xece1, 0x080c, 0x8c19, 0x080c, 0xb16c,
-	0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002, 0xeb1d,
-	0xeb1d, 0xeb1d, 0xeb1f, 0xeb1d, 0xeb1f, 0xeb1f, 0xeb1d, 0xeb1f,
-	0xeb1d, 0xeb1d, 0xeb1d, 0xeb1d, 0xeb1d, 0x9006, 0x0005, 0x9085,
-	0x0001, 0x0005, 0x9280, 0x0008, 0x2004, 0x9084, 0x000f, 0x0002,
-	0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb43, 0xeb36,
-	0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0xeb36, 0x6007, 0x003b,
-	0x602f, 0x0009, 0x6017, 0x2a00, 0x6003, 0x0001, 0x2009, 0x8020,
-	0x080c, 0x9617, 0x0005, 0x0096, 0x00c6, 0x2260, 0x080c, 0xece1,
-	0x604b, 0x0000, 0x6024, 0xc0f4, 0xc0e4, 0x6026, 0x603b, 0x0000,
-	0x00ce, 0x00d6, 0x2268, 0x9186, 0x0007, 0x1904, 0xeb9c, 0x6814,
-	0x9005, 0x0138, 0x2048, 0xa87c, 0xd0fc, 0x1118, 0x00de, 0x009e,
-	0x08a8, 0x6007, 0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c,
-	0x9617, 0x00c6, 0x2d60, 0x6100, 0x9186, 0x0002, 0x1904, 0xec0c,
-	0x6014, 0x9005, 0x1138, 0x6000, 0x9086, 0x0007, 0x190c, 0x0d85,
-	0x0804, 0xec0c, 0x2048, 0x080c, 0xcf1b, 0x1130, 0x0028, 0x2048,
-	0xa800, 0x9005, 0x1de0, 0x2900, 0x2048, 0xa87c, 0x9084, 0x0003,
-	0x9086, 0x0002, 0x1168, 0xa87c, 0xc0dc, 0xc0f4, 0xa87e, 0xa880,
-	0xc0fc, 0xa882, 0x2009, 0x0043, 0x080c, 0xe3b5, 0x0804, 0xec0c,
-	0x2009, 0x0041, 0x0804, 0xec06, 0x9186, 0x0005, 0x15a0, 0x6814,
-	0x2048, 0xa87c, 0xd0bc, 0x1120, 0x00de, 0x009e, 0x0804, 0xeb36,
-	0xd0b4, 0x0128, 0xd0fc, 0x090c, 0x0d85, 0x0804, 0xeb57, 0x6007,
-	0x003a, 0x6003, 0x0001, 0x2009, 0x8020, 0x080c, 0x9617, 0x00c6,
-	0x2d60, 0x6100, 0x9186, 0x0002, 0x0120, 0x9186, 0x0004, 0x1904,
-	0xec0c, 0x6814, 0x2048, 0xa97c, 0xc1f4, 0xc1dc, 0xa97e, 0xa980,
-	0xc1fc, 0xc1bc, 0xa982, 0x00f6, 0x2c78, 0x080c, 0x17ad, 0x00fe,
-	0x2009, 0x0042, 0x0498, 0x0036, 0x080c, 0x1059, 0x090c, 0x0d85,
-	0xa867, 0x010d, 0x9006, 0xa802, 0xa86a, 0xa88a, 0x2d18, 0xab8e,
-	0xa887, 0x0045, 0x2c00, 0xa892, 0x6038, 0xa8a2, 0x2360, 0x6024,
-	0xc0dd, 0x6026, 0x6010, 0x00b6, 0x2058, 0xb8a0, 0x00be, 0x2004,
-	0x635c, 0xab7a, 0xa876, 0x9006, 0xa87e, 0xa882, 0xad9a, 0xae96,
-	0xa89f, 0x0001, 0x080c, 0x7012, 0x2019, 0x0045, 0x6008, 0x2068,
-	0x080c, 0xe578, 0x2d00, 0x600a, 0x003e, 0x0038, 0x604b, 0x0000,
-	0x6003, 0x0007, 0x080c, 0xe3b5, 0x00ce, 0x00de, 0x009e, 0x0005,
-	0x9186, 0x0013, 0x1128, 0x6004, 0x9082, 0x0085, 0x2008, 0x00c2,
-	0x9186, 0x0027, 0x1178, 0x080c, 0x99ed, 0x0036, 0x0096, 0x6014,
-	0x2048, 0x2019, 0x0004, 0x080c, 0xea30, 0x009e, 0x003e, 0x080c,
-	0x9ab3, 0x0005, 0x9186, 0x0014, 0x0d70, 0x080c, 0xb227, 0x0005,
-	0xec3f, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3f, 0xec3d,
-	0xec3d, 0xec3d, 0xec3d, 0xec3d, 0xec3d, 0x080c, 0x0d85, 0x6003,
-	0x000c, 0x080c, 0x9ab3, 0x0005, 0x9182, 0x0092, 0x1220, 0x9182,
-	0x0085, 0x0208, 0x001a, 0x080c, 0xb227, 0x0005, 0xec5b, 0xec5b,
-	0xec5b, 0xec5b, 0xec5d, 0xec7d, 0xec5b, 0xec5b, 0xec5b, 0xec5b,
-	0xec5b, 0xec5b, 0xec5b, 0x080c, 0x0d85, 0x00d6, 0x2c68, 0x080c,
-	0xb116, 0x01b0, 0x6003, 0x0001, 0x6007, 0x001e, 0x2009, 0x026e,
-	0x210c, 0x613a, 0x2009, 0x026f, 0x210c, 0x613e, 0x600b, 0xffff,
-	0x6910, 0x6112, 0x6023, 0x0004, 0x2009, 0x8020, 0x080c, 0x9617,
-	0x2d60, 0x080c, 0xb16c, 0x00de, 0x0005, 0x080c, 0xb16c, 0x0005,
-	0x00e6, 0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0ec, 0x00ee,
-	0x0005, 0x2009, 0x1867, 0x210c, 0xd1ec, 0x05b0, 0x6003, 0x0002,
-	0x6024, 0xc0e5, 0x6026, 0xd0cc, 0x0150, 0x2001, 0x1988, 0x2004,
-	0x604a, 0x2009, 0x1867, 0x210c, 0xd1f4, 0x1520, 0x00a0, 0x2009,
-	0x1867, 0x210c, 0xd1f4, 0x0128, 0x6024, 0xc0e4, 0x6026, 0x9006,
-	0x00d8, 0x2001, 0x1988, 0x200c, 0x2001, 0x1986, 0x2004, 0x9100,
-	0x9080, 0x000a, 0x604a, 0x6010, 0x00b6, 0x2058, 0xb8bc, 0x00be,
-	0x0008, 0x2104, 0x9005, 0x0118, 0x9088, 0x0003, 0x0cd0, 0x2c0a,
-	0x600f, 0x0000, 0x9085, 0x0001, 0x0005, 0x0016, 0x00c6, 0x00e6,
-	0x615c, 0xb8bc, 0x2060, 0x8cff, 0x0180, 0x84ff, 0x1118, 0x605c,
-	0x9106, 0x1138, 0x600c, 0x2072, 0x080c, 0x8c19, 0x080c, 0xb16c,
-	0x0010, 0x9cf0, 0x0003, 0x2e64, 0x0c70, 0x00ee, 0x00ce, 0x001e,
-	0x0005, 0x00d6, 0x00b6, 0x6010, 0x2058, 0xb8bc, 0x906d, 0x0130,
-	0x9c06, 0x0110, 0x680c, 0x0cd0, 0x600c, 0x680e, 0x00be, 0x00de,
-	0x0005, 0x0026, 0x0036, 0x0156, 0x2011, 0x182c, 0x2204, 0x9084,
-	0x00ff, 0x2019, 0x026e, 0x2334, 0x96b4, 0x00ff, 0x9636, 0x1508,
-	0x8318, 0x2334, 0x2204, 0x9084, 0xff00, 0x9636, 0x11d0, 0x2011,
-	0x0270, 0x20a9, 0x0004, 0x6010, 0x0096, 0x2048, 0x2019, 0x000a,
-	0x080c, 0xc222, 0x009e, 0x1168, 0x2011, 0x0274, 0x20a9, 0x0004,
-	0x6010, 0x0096, 0x2048, 0x2019, 0x0006, 0x080c, 0xc222, 0x009e,
-	0x1100, 0x015e, 0x003e, 0x002e, 0x0005, 0x00e6, 0x2071, 0x1800,
-	0x080c, 0x6130, 0x080c, 0x30bf, 0x00ee, 0x0005, 0x0096, 0x0026,
-	0x080c, 0x1059, 0x090c, 0x0d85, 0xa85c, 0x9080, 0x001a, 0x20a0,
-	0x20a9, 0x000c, 0xa860, 0x20e8, 0x9006, 0x4004, 0x9186, 0x0046,
-	0x1118, 0xa867, 0x0136, 0x0038, 0xa867, 0x0138, 0x9186, 0x0041,
-	0x0110, 0xa87b, 0x0001, 0x7038, 0x9084, 0xff00, 0x7240, 0x9294,
-	0xff00, 0x8007, 0x9215, 0xaa9a, 0x9186, 0x0046, 0x1168, 0x7038,
-	0x9084, 0x00ff, 0x723c, 0x9294, 0xff00, 0x9215, 0xaa9e, 0x723c,
-	0x9294, 0x00ff, 0xaaa2, 0x0060, 0x7040, 0x9084, 0x00ff, 0x7244,
-	0x9294, 0xff00, 0x9215, 0xaa9e, 0x7244, 0x9294, 0x00ff, 0xaaa2,
-	0x9186, 0x0046, 0x1118, 0x9e90, 0x0012, 0x0010, 0x9e90, 0x001a,
-	0x2204, 0x8007, 0xa8a6, 0x8210, 0x2204, 0x8007, 0xa8aa, 0x8210,
-	0x2204, 0x8007, 0xa8ae, 0x8210, 0x2204, 0x8007, 0xa8b2, 0x8210,
-	0x9186, 0x0046, 0x11b8, 0x9e90, 0x0016, 0x2204, 0x8007, 0xa8b6,
-	0x8210, 0x2204, 0x8007, 0xa8ba, 0x8210, 0x2204, 0x8007, 0xa8be,
-	0x8210, 0x2204, 0x8007, 0xa8c2, 0x8210, 0x2011, 0x0205, 0x2013,
-	0x0001, 0x00b0, 0x9e90, 0x001e, 0x2204, 0x8007, 0xa8b6, 0x8210,
-	0x2204, 0x8007, 0xa8ba, 0x2011, 0x0205, 0x2013, 0x0001, 0x2011,
-	0x0260, 0x2204, 0x8007, 0xa8be, 0x8210, 0x2204, 0x8007, 0xa8c2,
-	0x9186, 0x0046, 0x1118, 0x2011, 0x0262, 0x0010, 0x2011, 0x026a,
-	0x0146, 0x01d6, 0x0036, 0x20a9, 0x0001, 0x2019, 0x0008, 0xa860,
-	0x20e8, 0xa85c, 0x9080, 0x0031, 0x20a0, 0x2204, 0x8007, 0x4004,
-	0x8210, 0x8319, 0x1dd0, 0x003e, 0x01ce, 0x013e, 0x2011, 0x0205,
-	0x2013, 0x0000, 0x002e, 0x080c, 0x7012, 0x009e, 0x0005, 0x00e6,
-	0x6010, 0x00b6, 0x2058, 0xb800, 0x00be, 0xd0fc, 0x0108, 0x0011,
-	0x00ee, 0x0005, 0xa880, 0xc0e5, 0xa882, 0x0005, 0x00e6, 0x00d6,
-	0x00c6, 0x0076, 0x0066, 0x0056, 0x0046, 0x0026, 0x0016, 0x0126,
-	0x2091, 0x8000, 0x2029, 0x19f4, 0x252c, 0x2021, 0x19fb, 0x2424,
-	0x2061, 0x1ddc, 0x2071, 0x1800, 0x7654, 0x7074, 0x9606, 0x0578,
-	0x6720, 0x9786, 0x0001, 0x0118, 0x9786, 0x0008, 0x1500, 0x2500,
-	0x9c06, 0x01e8, 0x2400, 0x9c06, 0x01d0, 0x080c, 0xeabe, 0x01b8,
-	0x080c, 0xeace, 0x11a0, 0x6000, 0x9086, 0x0004, 0x1120, 0x0016,
-	0x080c, 0x1ad3, 0x001e, 0x080c, 0xd121, 0x1110, 0x080c, 0x3344,
-	0x080c, 0xd132, 0x1110, 0x080c, 0xbb5c, 0x080c, 0xb1a7, 0x9ce0,
-	0x001c, 0x2001, 0x181a, 0x2004, 0x9c02, 0x1208, 0x0858, 0x012e,
-	0x001e, 0x002e, 0x004e, 0x005e, 0x006e, 0x007e, 0x00ce, 0x00de,
-	0x00ee, 0x0005, 0x2001, 0x1810, 0x2004, 0xd0dc, 0x0005, 0x0006,
-	0x2001, 0x1837, 0x2004, 0xd09c, 0x000e, 0x0005, 0x0006, 0x0036,
-	0x0046, 0x080c, 0xd645, 0x0168, 0x2019, 0xffff, 0x9005, 0x0128,
-	0x6010, 0x00b6, 0x2058, 0xbba0, 0x00be, 0x2021, 0x0004, 0x080c,
-	0x4e58, 0x004e, 0x003e, 0x000e, 0x0005, 0x6004, 0x9086, 0x0001,
-	0x1128, 0x080c, 0xa7e2, 0x080c, 0xb1a7, 0x9006, 0x0005, 0x00e6,
-	0x00c6, 0x00b6, 0x0046, 0x2061, 0x1ddc, 0x2071, 0x1800, 0x7454,
-	0x7074, 0x8001, 0x9402, 0x12d8, 0x2100, 0x9c06, 0x0168, 0x6000,
-	0x9086, 0x0000, 0x0148, 0x6010, 0x2058, 0xb8a0, 0x9206, 0x1120,
-	0x6004, 0x9086, 0x0002, 0x0140, 0x9ce0, 0x001c, 0x2001, 0x181a,
-	0x2004, 0x9c02, 0x1220, 0x0c40, 0x9085, 0x0001, 0x0008, 0x9006,
-	0x004e, 0x00be, 0x00ce, 0x00ee, 0x0005, 0x2001, 0x1810, 0x2004,
-	0xd0a4, 0x0160, 0x2001, 0x1837, 0x2004, 0xd0a4, 0x0138, 0x2001,
-	0x1848, 0x2004, 0xd0a4, 0x1118, 0x9085, 0x0001, 0x0005, 0x9006,
-	0x0ce8, 0x0126, 0x0006, 0x00e6, 0x0016, 0x2091, 0x8000, 0x2071,
-	0x1840, 0xd5a4, 0x0118, 0x7004, 0x8000, 0x7006, 0xd5b4, 0x0118,
-	0x7000, 0x8000, 0x7002, 0xd5ac, 0x0178, 0x2500, 0x9084, 0x0007,
-	0x908e, 0x0003, 0x0148, 0x908e, 0x0004, 0x0130, 0x908e, 0x0005,
-	0x0118, 0x2071, 0xfff6, 0x0089, 0x001e, 0x00ee, 0x000e, 0x012e,
-	0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071, 0xffee,
-	0x0021, 0x00ee, 0x000e, 0x012e, 0x0005, 0x2e05, 0x8000, 0x2077,
-	0x1220, 0x8e70, 0x2e05, 0x8000, 0x2077, 0x0005, 0x00e6, 0x2071,
-	0xffec, 0x0c99, 0x00ee, 0x0005, 0x00e6, 0x2071, 0xfff0, 0x0c69,
-	0x00ee, 0x0005, 0x0126, 0x0006, 0x00e6, 0x2091, 0x8000, 0x2071,
-	0x1840, 0x7014, 0x8000, 0x7016, 0x00ee, 0x000e, 0x012e, 0x0005,
-	0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
-	0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
-	0xaa6e
-};
-#ifdef UNIQUE_FW_NAME
-unsigned short fw2322ipx_length01 = 0xe719;
-#else
-unsigned short risc_code_length01 = 0xe719;
-#endif
-
-/*
- *
- */
-
-unsigned long rseqipx_code_addr01 = 0x0001c000 ;
-unsigned short rseqipx_code01[] = { 
-0x000b, 0x0003, 0x0000, 0x0a4e, 0x0001, 0xc000, 0x0008, 0x8064,
-	0x0000, 0x0010, 0x0000, 0x8066, 0x0008, 0x0101, 0x0003, 0xc007,
-	0x0008, 0x80e0, 0x0008, 0xff00, 0x0000, 0x80e2, 0x0008, 0xff00,
-	0x0008, 0x0162, 0x0000, 0x8066, 0x0008, 0xa101, 0x000b, 0xc00f,
-	0x0008, 0x0d02, 0x0000, 0x8060, 0x0000, 0x0400, 0x000b, 0x60c6,
-	0x0008, 0x80e0, 0x0000, 0x0100, 0x000b, 0x5819, 0x0003, 0x7b08,
-	0x0003, 0x5241, 0x000b, 0xc813, 0x0009, 0xbac0, 0x0000, 0x008a,
-	0x0003, 0x8813, 0x000a, 0x7042, 0x0003, 0x8813, 0x0000, 0x15fc,
-	0x000b, 0xb013, 0x0009, 0xc4c0, 0x0000, 0x7000, 0x0001, 0xffa0,
-	0x0000, 0x2000, 0x0003, 0x93cd, 0x0008, 0x808c, 0x0000, 0x0001,
-	0x0007, 0x0000, 0x0007, 0x0000, 0x0000, 0x40d4, 0x000a, 0x4047,
-	0x0008, 0x808c, 0x0000, 0x0002, 0x0007, 0x0000, 0x000b, 0x0832,
-	0x0000, 0x4022, 0x0003, 0x0038, 0x0008, 0x4122, 0x0009, 0xeac0,
-	0x0008, 0xff00, 0x0009, 0xffe0, 0x0008, 0x0500, 0x000b, 0x0bf4,
-	0x0002, 0x4447, 0x0003, 0x8bf1, 0x0008, 0x0bfe, 0x0001, 0x11a0,
-	0x000b, 0x13d3, 0x0001, 0x0ca0, 0x000b, 0x13d3, 0x0001, 0x9180,
-	0x0000, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62,
-	0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc046, 0x0008, 0x808c,
-	0x0008, 0x0000, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x0004,
-	0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc04e, 0x0000, 0x03fe,
-	0x0001, 0x43e0, 0x0003, 0x8bd0, 0x0009, 0xc2c0, 0x0008, 0x00ff,
-	0x0001, 0x02e0, 0x0003, 0x8bd0, 0x0001, 0x9180, 0x0008, 0x0005,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0000, 0x0019, 0x0003, 0xc05d, 0x0002, 0x0240, 0x000b, 0x0bcd,
-	0x0008, 0x00fc, 0x0003, 0x33d0, 0x000a, 0x0244, 0x0003, 0x086f,
-	0x0004, 0x021a, 0x0001, 0x9180, 0x0000, 0x0007, 0x0008, 0x7f62,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0002, 0x0234, 0x0008, 0x7f04,
-	0x0000, 0x8066, 0x0000, 0x040a, 0x0003, 0xc06e, 0x000a, 0x0248,
-	0x000b, 0x0879, 0x0001, 0x9180, 0x0008, 0x0006, 0x0008, 0x7f62,
-	0x0008, 0x8002, 0x0008, 0x0003, 0x0000, 0x8066, 0x0000, 0x020a,
-	0x000b, 0xc078, 0x0000, 0x112a, 0x0008, 0x002e, 0x0008, 0x022c,
-	0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x808c, 0x0000, 0x0002,
-	0x0008, 0x1760, 0x0008, 0x8062, 0x0008, 0x000f, 0x0000, 0x8066,
-	0x0008, 0x0011, 0x0003, 0xc085, 0x0008, 0x01fe, 0x0009, 0x42e0,
-	0x000b, 0x8bc0, 0x0000, 0x00fe, 0x0001, 0x43e0, 0x000b, 0x8bc0,
-	0x0000, 0x1734, 0x0000, 0x1530, 0x0008, 0x1632, 0x0008, 0x0d2a,
-	0x0001, 0x9880, 0x0008, 0x0012, 0x0000, 0x8060, 0x0000, 0x0400,
-	0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x1e0a, 0x0003, 0xc097,
-	0x0008, 0x808a, 0x0008, 0x0003, 0x0000, 0x1a60, 0x0008, 0x8062,
-	0x0000, 0x0002, 0x000b, 0x589d, 0x0000, 0x8066, 0x0000, 0x3679,
-	0x000b, 0xc0a0, 0x000b, 0x58a1, 0x0008, 0x8054, 0x0008, 0x0011,
-	0x0000, 0x8074, 0x0008, 0x1010, 0x0008, 0x1efc, 0x0003, 0x3013,
-	0x0004, 0x00aa, 0x0003, 0x0013, 0x0000, 0x1c60, 0x0000, 0x1b62,
-	0x0000, 0x8066, 0x0008, 0x0231, 0x0003, 0xc0ae, 0x0003, 0x58af,
-	0x0008, 0x0140, 0x0000, 0x0242, 0x0002, 0x1f43, 0x0003, 0x88b9,
-	0x0000, 0x0d44, 0x0008, 0x0d46, 0x0008, 0x0348, 0x0008, 0x044a,
-	0x000b, 0x00bd, 0x0008, 0x0344, 0x0008, 0x0446, 0x0008, 0x0548,
-	0x0000, 0x064a, 0x000a, 0x1948, 0x0003, 0x08c0, 0x0008, 0x0d4a,
-	0x0003, 0x58c0, 0x0008, 0x8054, 0x0000, 0x0001, 0x0000, 0x8074,
-	0x0008, 0x2020, 0x000f, 0x4000, 0x0002, 0x7043, 0x0003, 0x8816,
-	0x0002, 0x7040, 0x000b, 0x8949, 0x0000, 0x4820, 0x0008, 0x0bfe,
-	0x0009, 0x10a0, 0x0003, 0x1140, 0x0001, 0x0ca0, 0x0003, 0x1140,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0008,
-	0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc0d7,
-	0x0001, 0x80e0, 0x0008, 0x0003, 0x000b, 0x8940, 0x0000, 0x8060,
-	0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0004, 0x0008, 0x7f62,
-	0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc0e2, 0x0008, 0x0060,
-	0x0008, 0x8062, 0x0000, 0x0004, 0x0000, 0x8066, 0x0000, 0x0411,
-	0x000b, 0xc0e8, 0x0008, 0x4afe, 0x0009, 0x03e0, 0x000b, 0x8940,
-	0x0009, 0xcbc0, 0x0008, 0x00ff, 0x0001, 0x02e0, 0x000b, 0x8940,
-	0x0000, 0x49b4, 0x0002, 0x4b4e, 0x000b, 0x8951, 0x0008, 0x808a,
-	0x0000, 0x0004, 0x0000, 0x18fe, 0x0001, 0x10e0, 0x000b, 0x88fa,
-	0x0002, 0x192f, 0x0008, 0x7f32, 0x0008, 0x15fe, 0x0001, 0x10e0,
-	0x000b, 0x88ff, 0x0002, 0x162f, 0x0008, 0x7f2c, 0x0000, 0x8060,
-	0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0007, 0x0008, 0x7f62,
-	0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc106, 0x000a, 0x004f,
-	0x000b, 0x8937, 0x000a, 0x0040, 0x000b, 0x0921, 0x0002, 0x004e,
-	0x000b, 0x0921, 0x0002, 0x0030, 0x0002, 0x7f2f, 0x0000, 0x7f00,
-	0x0000, 0x8066, 0x0008, 0x000a, 0x0003, 0xc112, 0x0008, 0x1010,
-	0x0004, 0x0201, 0x0003, 0xb11a, 0x0004, 0x0387, 0x000c, 0x01eb,
-	0x0003, 0x7816, 0x0003, 0x0013, 0x0000, 0x0806, 0x0008, 0x8010,
-	0x0000, 0x001f, 0x0004, 0x0387, 0x0000, 0x0310, 0x0004, 0x0387,
-	0x0003, 0x0118, 0x000a, 0x002f, 0x0000, 0x7f00, 0x0000, 0x8066,
-	0x0008, 0x000a, 0x000b, 0xc125, 0x0004, 0x01c4, 0x000a, 0x0040,
-	0x000b, 0x093a, 0x0004, 0x0231, 0x0000, 0x8000, 0x0000, 0x0002,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0008, 0x0006,
-	0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x000a, 0x0003, 0xc133,
-	0x0000, 0x8072, 0x0000, 0x4000, 0x0003, 0x0118, 0x0008, 0x8010,
-	0x0008, 0x001e, 0x0003, 0x013c, 0x0008, 0x8010, 0x0008, 0x001d,
-	0x0004, 0x0387, 0x0008, 0x1010, 0x0004, 0x0387, 0x0003, 0x0016,
-	0x0002, 0x4b4e, 0x0003, 0x0946, 0x0008, 0x808a, 0x0000, 0x0004,
-	0x000b, 0x6146, 0x000f, 0x8000, 0x0008, 0x808a, 0x0000, 0x0004,
-	0x0003, 0x0016, 0x0008, 0x808a, 0x0000, 0x0004, 0x0007, 0x0000,
-	0x0007, 0x0000, 0x0008, 0x80e0, 0x0008, 0x0202, 0x000b, 0x6149,
-	0x000b, 0x0014, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080,
-	0x0008, 0x0011, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009,
-	0x000b, 0xc158, 0x000a, 0x004f, 0x000b, 0x89b5, 0x0000, 0x8060,
-	0x0000, 0x0400, 0x0009, 0x9080, 0x0008, 0x0005, 0x0008, 0x7f62,
-	0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc162, 0x0008, 0x0060,
-	0x0008, 0x8062, 0x0000, 0x001f, 0x0000, 0x8066, 0x0000, 0x0209,
-	0x000b, 0xc168, 0x000a, 0x014b, 0x0003, 0x09b5, 0x0008, 0x8062,
-	0x0008, 0x000f, 0x0000, 0x8066, 0x0000, 0x0211, 0x0003, 0xc16f,
-	0x0008, 0x01fe, 0x0001, 0x02d0, 0x000b, 0x89b5, 0x0004, 0x01cd,
-	0x0003, 0x09b5, 0x0008, 0x03a0, 0x0008, 0x8004, 0x0000, 0x0002,
-	0x0000, 0x8006, 0x0000, 0x0043, 0x0008, 0x4908, 0x0008, 0x808a,
-	0x0000, 0x0004, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080,
-	0x0008, 0x0000, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x041a,
-	0x0003, 0xc184, 0x0003, 0xe185, 0x0008, 0x4908, 0x0008, 0x480a,
-	0x0008, 0x808a, 0x0000, 0x0004, 0x0008, 0x0060, 0x0008, 0x8062,
-	0x0008, 0x002b, 0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc18f,
-	0x0008, 0x04fe, 0x0009, 0x02a0, 0x0003, 0x9196, 0x0002, 0x0500,
-	0x000b, 0x09b2, 0x000b, 0x0197, 0x0000, 0x05fe, 0x0001, 0x03a0,
-	0x000b, 0x11b2, 0x0000, 0x0d0c, 0x0008, 0x0d0e, 0x0008, 0x0d10,
-	0x0000, 0x0d12, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x000d,
-	0x0000, 0x8066, 0x0008, 0x0832, 0x000b, 0xc1a2, 0x0000, 0x800a,
-	0x0000, 0x8005, 0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080,
-	0x0008, 0x0011, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0a12,
-	0x0003, 0xc1ac, 0x0008, 0x5006, 0x0008, 0x100e, 0x000c, 0x01d8,
-	0x0003, 0x7816, 0x0003, 0x0013, 0x0008, 0x0208, 0x0008, 0x030a,
-	0x0003, 0x0199, 0x0004, 0x01c4, 0x0008, 0x808a, 0x0000, 0x0004,
-	0x0008, 0x8010, 0x0008, 0x0021, 0x0004, 0x0387, 0x0008, 0x1010,
-	0x0004, 0x0387, 0x0000, 0x4810, 0x0004, 0x0387, 0x0008, 0x4910,
-	0x0004, 0x0387, 0x0008, 0x808a, 0x0000, 0x0004, 0x0003, 0x0016,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0009, 0x9080, 0x0000, 0x0002,
-	0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0xb40a, 0x000b, 0xc1cb,
-	0x000f, 0x4000, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x0a62,
-	0x0000, 0x8066, 0x0000, 0x0411, 0x0003, 0xc1d2, 0x0002, 0x0210,
-	0x0001, 0xffc0, 0x0000, 0x0007, 0x0009, 0x03e0, 0x000f, 0x4000,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0001, 0x8380, 0x0000, 0x0002,
-	0x0009, 0x0a80, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0000, 0x0e0a,
-	0x000b, 0xc1e0, 0x0002, 0x0300, 0x0001, 0xffc0, 0x0000, 0x0007,
-	0x0000, 0x7f06, 0x0002, 0x0a00, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0008, 0x060a, 0x000b, 0xc1e9, 0x000f, 0x4000, 0x0000, 0x0da0,
-	0x0008, 0x0da2, 0x0008, 0x0da4, 0x0009, 0x8880, 0x0000, 0x0001,
-	0x0008, 0x7f62, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066,
-	0x0008, 0xa012, 0x0000, 0x0da6, 0x0008, 0x0da8, 0x0000, 0x0daa,
-	0x0000, 0x0dac, 0x0003, 0xc1f9, 0x0009, 0x8880, 0x0008, 0x0009,
-	0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0xa03a, 0x0003, 0xc1ff,
-	0x000f, 0x4000, 0x0009, 0x8880, 0x0008, 0x0005, 0x0000, 0x8060,
-	0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x0009,
-	0x000b, 0xc208, 0x0008, 0x0060, 0x0008, 0x8062, 0x0000, 0x000d,
-	0x0000, 0x8066, 0x0008, 0x0021, 0x000b, 0xc20e, 0x0000, 0x00fe,
-	0x0001, 0x01d0, 0x0003, 0x8a17, 0x0008, 0x02fe, 0x0009, 0x03d0,
-	0x000b, 0x0a17, 0x0000, 0x0d06, 0x000f, 0x4000, 0x0000, 0x8006,
-	0x0000, 0x0001, 0x000f, 0x4000, 0x0008, 0x0060, 0x0008, 0x8062,
-	0x0008, 0x002b, 0x0000, 0x8066, 0x0008, 0xa041, 0x000b, 0xc21f,
-	0x0002, 0x0243, 0x000b, 0x8a26, 0x0000, 0x54ac, 0x0000, 0x55ae,
-	0x0008, 0x0da8, 0x0000, 0x0daa, 0x0000, 0x50b0, 0x0000, 0x51b2,
-	0x0000, 0x0db4, 0x0008, 0x0db6, 0x0008, 0x0060, 0x0008, 0x8062,
-	0x0000, 0x0007, 0x0000, 0x8066, 0x0008, 0xa452, 0x000b, 0xc22f,
-	0x000f, 0x4000, 0x000a, 0x3945, 0x000b, 0x8a3b, 0x0000, 0x8072,
-	0x0008, 0x4040, 0x0007, 0x0000, 0x000a, 0x3945, 0x0003, 0x8a39,
-	0x000f, 0x4000, 0x0000, 0x8072, 0x0000, 0x4000, 0x0007, 0x0000,
-	0x0007, 0x0000, 0x0007, 0x0000, 0x000a, 0x3945, 0x000b, 0x0a33,
-	0x000b, 0x023b, 0x000a, 0x3a40, 0x0003, 0x8819, 0x0001, 0xabd0,
-	0x0008, 0x0000, 0x0000, 0x7f24, 0x0003, 0x5a46, 0x0008, 0x8054,
-	0x0000, 0x0002, 0x0002, 0x1242, 0x0003, 0x0a8c, 0x000a, 0x3a45,
-	0x000b, 0x0a7b, 0x000a, 0x1e10, 0x0000, 0x7f3c, 0x000b, 0x0a78,
-	0x0002, 0x1d00, 0x0000, 0x7f3a, 0x0000, 0x0d60, 0x0008, 0x7f62,
-	0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc256, 0x0008, 0x00fc,
-	0x0003, 0xb275, 0x0000, 0x1c60, 0x0008, 0x8062, 0x0000, 0x0001,
-	0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc25e, 0x0008, 0x00fc,
-	0x000b, 0x33a9, 0x0000, 0x0038, 0x0008, 0x0060, 0x0008, 0x8062,
-	0x0000, 0x0019, 0x0000, 0x8066, 0x0008, 0x0009, 0x000b, 0xc267,
-	0x0009, 0x80c0, 0x0008, 0x00ff, 0x0008, 0x7f3e, 0x0000, 0x0d60,
-	0x0008, 0x0efe, 0x0001, 0x1f80, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0008, 0x0009, 0x0003, 0xc271, 0x0008, 0x003a, 0x0000, 0x1dfe,
-	0x000b, 0x0252, 0x0008, 0x0036, 0x0004, 0x00aa, 0x000b, 0x028c,
-	0x0000, 0x8074, 0x0000, 0x2000, 0x000b, 0x028c, 0x0002, 0x3a44,
-	0x000b, 0x0bd6, 0x0000, 0x8074, 0x0000, 0x1000, 0x0001, 0xadd0,
-	0x0008, 0x0000, 0x0008, 0x7f0e, 0x0003, 0xb3a6, 0x0001, 0xa7d0,
-	0x0008, 0x0000, 0x0000, 0x7f00, 0x0009, 0xa6d0, 0x0008, 0x0000,
-	0x0009, 0x00d0, 0x0003, 0x8a9c, 0x0000, 0x8074, 0x0008, 0x4040,
-	0x0003, 0x5a8c, 0x0003, 0x5241, 0x000a, 0x3a46, 0x0003, 0x8a9c,
-	0x0002, 0x3a47, 0x0003, 0x0a97, 0x0008, 0x8054, 0x0000, 0x0004,
-	0x0000, 0x8074, 0x0000, 0x8000, 0x0003, 0x02fc, 0x0009, 0x92c0,
-	0x0000, 0x0fc8, 0x000b, 0x0813, 0x000a, 0x1246, 0x000b, 0x8ba0,
-	0x0000, 0x1a60, 0x0008, 0x8062, 0x0000, 0x0002, 0x0000, 0x8066,
-	0x0000, 0x367a, 0x000b, 0xc2a1, 0x0009, 0x92c0, 0x0008, 0x0780,
-	0x0003, 0x8bba, 0x0002, 0x124b, 0x000b, 0x0aaa, 0x0002, 0x2e4d,
-	0x0002, 0x2e4d, 0x0003, 0x0ba6, 0x000a, 0x3a46, 0x000b, 0x8aba,
-	0x000b, 0x5aac, 0x0008, 0x8054, 0x0000, 0x0004, 0x000a, 0x1243,
-	0x000b, 0x0afa, 0x0008, 0x8010, 0x0000, 0x000d, 0x0004, 0x0387,
-	0x000a, 0x1948, 0x000b, 0x0ab7, 0x000c, 0x037c, 0x0000, 0x1810,
-	0x0004, 0x0387, 0x0003, 0x02fa, 0x000a, 0x1948, 0x000b, 0x0abe,
-	0x000a, 0x1243, 0x0003, 0x0ba9, 0x000a, 0x194d, 0x0003, 0x0ac2,
-	0x000a, 0x1243, 0x000b, 0x0bb0, 0x0003, 0x5ac2, 0x0008, 0x8054,
-	0x0000, 0x0004, 0x000a, 0x192e, 0x0008, 0x7f32, 0x000a, 0x1947,
-	0x0003, 0x0af4, 0x0002, 0x194f, 0x000b, 0x0ad2, 0x000c, 0x037c,
-	0x0000, 0x1810, 0x0004, 0x0201, 0x000b, 0xb2ed, 0x0004, 0x0387,
-	0x000c, 0x01eb, 0x0003, 0x02fa, 0x0000, 0x1a60, 0x0008, 0x8062,
-	0x0000, 0x001f, 0x0000, 0x8066, 0x0008, 0x0009, 0x0003, 0xc2d7,
-	0x000a, 0x004c, 0x000b, 0x8af4, 0x0000, 0x8060, 0x0000, 0x0400,
-	0x0001, 0x9880, 0x0000, 0x0007, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0000, 0x320a, 0x0003, 0xc2e1, 0x0000, 0x8060, 0x0000, 0x0400,
-	0x0001, 0x9880, 0x0008, 0x0012, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0008, 0x1e0a, 0x000b, 0xc2e9, 0x0000, 0x1826, 0x0000, 0x1928,
-	0x0003, 0x02fa, 0x0000, 0x0806, 0x0008, 0x8010, 0x0000, 0x001f,
-	0x0004, 0x0387, 0x0000, 0x0310, 0x0004, 0x0387, 0x0003, 0x02fa,
-	0x000c, 0x037c, 0x0008, 0x8010, 0x0000, 0x0001, 0x0004, 0x0387,
-	0x0000, 0x1810, 0x0004, 0x0387, 0x0000, 0x8074, 0x0008, 0xf000,
-	0x0000, 0x0d30, 0x0002, 0x3a42, 0x0003, 0x8b02, 0x0000, 0x15fc,
-	0x0003, 0xb07e, 0x0003, 0x0013, 0x0000, 0x8074, 0x0000, 0x0501,
-	0x0008, 0x8010, 0x0008, 0x000c, 0x0004, 0x0387, 0x0003, 0x0013,
-	0x0009, 0xbbe0, 0x0008, 0x0030, 0x000b, 0x8b1e, 0x0000, 0x18fe,
-	0x0009, 0x3ce0, 0x0003, 0x0b1b, 0x0008, 0x15fe, 0x0009, 0x3ce0,
-	0x0003, 0x0b1b, 0x0008, 0x13fe, 0x0009, 0x3ce0, 0x000b, 0x8b17,
-	0x000c, 0x0375, 0x0008, 0x0d26, 0x000b, 0x0318, 0x0004, 0x0377,
-	0x0008, 0x8076, 0x0000, 0x0040, 0x000b, 0x0372, 0x0008, 0x8076,
-	0x0008, 0x0041, 0x000b, 0x0372, 0x0009, 0xbbe0, 0x0000, 0x0032,
-	0x0003, 0x8b23, 0x0008, 0x3c1e, 0x000b, 0x0372, 0x0009, 0xbbe0,
-	0x0000, 0x003b, 0x000b, 0x8b28, 0x0000, 0x3cdc, 0x000b, 0x0372,
-	0x0009, 0xbbe0, 0x0008, 0x0035, 0x000b, 0x8b2e, 0x0000, 0x8072,
-	0x0000, 0x8000, 0x000b, 0x04e5, 0x0009, 0xbbe0, 0x0008, 0x0036,
-	0x000b, 0x0c06, 0x0009, 0xbbe0, 0x0000, 0x0037, 0x000b, 0x8b53,
-	0x0000, 0x18fe, 0x0009, 0x3ce0, 0x000b, 0x8b1b, 0x0008, 0x8076,
-	0x0000, 0x0040, 0x0000, 0x1a60, 0x0008, 0x8062, 0x0000, 0x000d,
-	0x0009, 0xa6d0, 0x0008, 0x0000, 0x0008, 0x7f04, 0x0001, 0xa7d0,
-	0x0008, 0x0000, 0x0000, 0x7f06, 0x0001, 0xa8d0, 0x0008, 0x0000,
-	0x0008, 0x7f08, 0x0009, 0xa9d0, 0x0008, 0x0000, 0x0000, 0x7f0a,
-	0x0000, 0x8066, 0x0000, 0x0422, 0x0003, 0xc34a, 0x000c, 0x037c,
-	0x0008, 0x8054, 0x0000, 0x0004, 0x0000, 0x8074, 0x0008, 0xf000,
-	0x0000, 0x8072, 0x0000, 0x8000, 0x0003, 0x02fc, 0x0009, 0xbbe0,
-	0x0000, 0x0038, 0x000b, 0x8b65, 0x0000, 0x18fe, 0x0009, 0x3ce0,
-	0x000b, 0x0b62, 0x0008, 0x15fe, 0x0009, 0x3ce0, 0x000b, 0x8b11,
-	0x0004, 0x0377, 0x0008, 0x8076, 0x0000, 0x0040, 0x0000, 0x8072,
-	0x0000, 0x8000, 0x0003, 0x03cd, 0x0008, 0x8076, 0x0008, 0x0042,
-	0x000b, 0x0372, 0x0009, 0xbbe0, 0x0000, 0x0016, 0x000b, 0x8b72,
-	0x0000, 0x8074, 0x0008, 0x0808, 0x0002, 0x3a44, 0x000b, 0x8818,
-	0x0000, 0x8074, 0x0000, 0x0800, 0x0000, 0x8072, 0x0000, 0x8000,
-	0x000f, 0x8000, 0x0003, 0x0013, 0x0000, 0x8072, 0x0000, 0x8000,
-	0x0003, 0x0013, 0x0002, 0x1430, 0x000b, 0x0378, 0x000a, 0x3d30,
-	0x0000, 0x7f00, 0x0001, 0xbc80, 0x0000, 0x0007, 0x0003, 0x0380,
-	0x000a, 0x1930, 0x0000, 0x7f00, 0x0001, 0x9880, 0x0000, 0x0007,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0008, 0x000a, 0x0003, 0xc385, 0x000f, 0x4000, 0x000b, 0x238a,
-	0x0008, 0x0870, 0x000f, 0x4000, 0x0002, 0x7040, 0x0003, 0x0b87,
-	0x000b, 0xe394, 0x0008, 0x808a, 0x0000, 0x0004, 0x0007, 0x0000,
-	0x0007, 0x0000, 0x0008, 0x80e0, 0x0008, 0x0202, 0x000b, 0x638d,
-	0x0008, 0x80e0, 0x0000, 0x0100, 0x000b, 0x0387, 0x0009, 0xbac0,
-	0x0008, 0x0090, 0x000b, 0x0b9d, 0x0000, 0x8074, 0x0000, 0x0706,
-	0x000b, 0x039f, 0x0000, 0x8074, 0x0000, 0x0703, 0x000f, 0x4000,
-	0x0008, 0x8010, 0x0000, 0x0023, 0x000b, 0x03db, 0x0008, 0x8010,
-	0x0000, 0x0008, 0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0022,
-	0x000b, 0x03db, 0x000c, 0x037c, 0x0008, 0x8010, 0x0000, 0x0007,
-	0x0004, 0x0387, 0x0000, 0x1810, 0x0004, 0x0387, 0x0003, 0x03e5,
-	0x000c, 0x037c, 0x0008, 0x8010, 0x0008, 0x001b, 0x0004, 0x0387,
-	0x0000, 0x1810, 0x0004, 0x0387, 0x0000, 0x8074, 0x0000, 0xf080,
-	0x0000, 0x0d30, 0x0003, 0x0013, 0x0008, 0x8010, 0x0008, 0x0009,
-	0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0005, 0x000b, 0x03db,
-	0x000a, 0x1648, 0x0003, 0x888c, 0x0008, 0x808c, 0x0000, 0x0001,
-	0x0007, 0x0000, 0x0008, 0x8010, 0x0000, 0x0004, 0x000a, 0x4143,
-	0x000b, 0x088c, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x0d2a,
-	0x000b, 0x03db, 0x0008, 0x8010, 0x0008, 0x0003, 0x000b, 0x03dd,
-	0x0008, 0x8010, 0x0000, 0x000b, 0x000b, 0x03dd, 0x0008, 0x8010,
-	0x0000, 0x0002, 0x000b, 0x03dd, 0x0002, 0x3a47, 0x000b, 0x8a8c,
-	0x0008, 0x8010, 0x0008, 0x0006, 0x000b, 0x03dd, 0x0000, 0x8074,
-	0x0008, 0xf000, 0x0004, 0x0387, 0x000c, 0x0397, 0x000a, 0x3a40,
-	0x000b, 0x0813, 0x0008, 0x8010, 0x0008, 0x000c, 0x0004, 0x0387,
-	0x0003, 0x0013, 0x0000, 0x8074, 0x0000, 0xf080, 0x0000, 0x0d30,
-	0x0002, 0x2e4d, 0x0002, 0x2e4d, 0x0003, 0x0bee, 0x0008, 0x8054,
-	0x0000, 0x0019, 0x0003, 0x0013, 0x0008, 0x8054, 0x0008, 0x0009,
-	0x0003, 0x0013, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0003, 0x03d0,
-	0x0008, 0x808c, 0x0008, 0x0000, 0x0002, 0x4447, 0x0003, 0x0c1a,
-	0x0001, 0xc0c0, 0x0008, 0x00ff, 0x0009, 0xffe0, 0x0008, 0x00ff,
-	0x0003, 0x8bf1, 0x0001, 0xc1e0, 0x0008, 0xffff, 0x0003, 0x8bf1,
-	0x0008, 0x8010, 0x0000, 0x0013, 0x0004, 0x0387, 0x0000, 0x8074,
-	0x0008, 0x0202, 0x0003, 0x0013, 0x000a, 0x3a40, 0x0003, 0x8c17,
-	0x0000, 0x8074, 0x0000, 0x0200, 0x0000, 0x3d00, 0x0000, 0x3cfe,
-	0x0000, 0x8072, 0x0000, 0x8000, 0x0001, 0x43e0, 0x000b, 0x8c15,
-	0x0000, 0x42fe, 0x0001, 0xffc0, 0x0008, 0x00ff, 0x0009, 0x00e0,
-	0x000b, 0x0bf1, 0x0008, 0x0d08, 0x0003, 0x046a, 0x0000, 0x8072,
-	0x0000, 0x8000, 0x0003, 0x0013, 0x000c, 0x04ee, 0x0008, 0x808c,
-	0x0000, 0x0001, 0x0000, 0x04fc, 0x0003, 0x34d1, 0x0000, 0x0460,
-	0x0008, 0x8062, 0x0000, 0x0001, 0x0000, 0x8066, 0x0008, 0x0009,
-	0x0003, 0xc424, 0x0000, 0x0004, 0x0009, 0x80c0, 0x0008, 0x00ff,
-	0x0000, 0x7f00, 0x0001, 0x80e0, 0x0000, 0x0004, 0x0003, 0x0c3e,
-	0x0001, 0x80e0, 0x0008, 0x0005, 0x0003, 0x0c3e, 0x0001, 0x80e0,
-	0x0008, 0x0006, 0x0003, 0x0c3e, 0x0001, 0x82c0, 0x0008, 0xff00,
-	0x0008, 0x7f04, 0x0009, 0x82e0, 0x0008, 0x0600, 0x0003, 0x0c3e,
-	0x0009, 0x82e0, 0x0008, 0x0500, 0x0003, 0x0c3e, 0x0009, 0x82e0,
-	0x0000, 0x0400, 0x0003, 0x8cd1, 0x0009, 0xc4c0, 0x0000, 0x7000,
-	0x0009, 0xffe0, 0x0000, 0x1000, 0x000b, 0x0c6a, 0x0004, 0x04df,
-	0x0002, 0x3941, 0x0003, 0x0c49, 0x0000, 0x8072, 0x0000, 0x0400,
-	0x0003, 0x0013, 0x0000, 0x0460, 0x0008, 0x80fe, 0x0008, 0x002b,
-	0x0008, 0x7f62, 0x0000, 0x8066, 0x0008, 0x2209, 0x000b, 0xc44f,
-	0x0008, 0x11fc, 0x0003, 0x3465, 0x0001, 0x9180, 0x0000, 0x0002,
-	0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0008, 0x0609, 0x0003, 0xc459, 0x0000, 0x42fe, 0x0001, 0xffc0,
-	0x0008, 0xff00, 0x0009, 0x03e0, 0x000b, 0x8c62, 0x0000, 0x8072,
-	0x0000, 0x0400, 0x000b, 0x0056, 0x0001, 0x9180, 0x0008, 0x0003,
-	0x000b, 0x044c, 0x0000, 0x8072, 0x0000, 0x0400, 0x0008, 0x8010,
-	0x0000, 0x0010, 0x000b, 0x04c4, 0x0004, 0x04df, 0x0002, 0x3941,
-	0x0003, 0x0c70, 0x0000, 0x8072, 0x0000, 0x0400, 0x0003, 0x0013,
-	0x000a, 0x6e42, 0x0003, 0x0c75, 0x000c, 0x04a9, 0x0008, 0x11fc,
-	0x0003, 0xb47a, 0x0000, 0x8072, 0x0000, 0x0400, 0x0008, 0x8010,
-	0x0000, 0x000e, 0x000b, 0x04c4, 0x0000, 0x8060, 0x0000, 0x0400,
-	0x0000, 0x04fc, 0x0003, 0xb48f, 0x0008, 0x808c, 0x0008, 0x0000,
-	0x0001, 0x9180, 0x0008, 0x0005, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0008, 0x0009, 0x000b, 0xc485, 0x0008, 0x0060, 0x0008, 0x8062,
-	0x0008, 0x001b, 0x0008, 0x4304, 0x0008, 0x4206, 0x0000, 0x8066,
-	0x0000, 0x0412, 0x0003, 0xc48d, 0x0003, 0x04a6, 0x0008, 0x808c,
-	0x0000, 0x0001, 0x0000, 0x0460, 0x0008, 0x8062, 0x0008, 0x002b,
-	0x0000, 0x8066, 0x0008, 0x0609, 0x0003, 0xc496, 0x0000, 0x8066,
-	0x0008, 0x220a, 0x0003, 0xc499, 0x0000, 0x42fe, 0x0001, 0xffc0,
-	0x0008, 0xff00, 0x0008, 0x7f04, 0x0000, 0x8060, 0x0000, 0x0400,
-	0x0001, 0x9180, 0x0000, 0x0002, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0008, 0x041a, 0x0003, 0xc4a5, 0x0000, 0x8072, 0x0000, 0x0400,
-	0x000b, 0x0056, 0x0000, 0x8060, 0x0000, 0x0400, 0x0008, 0x6b62,
-	0x0000, 0x8066, 0x0000, 0x0411, 0x000b, 0xc4ae, 0x0008, 0x02fe,
-	0x0009, 0x03e0, 0x0003, 0x8cb4, 0x0000, 0x0d22, 0x000f, 0x4000,
-	0x0009, 0x8280, 0x0000, 0x0002, 0x0001, 0x6b80, 0x0008, 0x7f62,
-	0x0000, 0x8066, 0x0008, 0x2209, 0x000b, 0xc4ba, 0x000a, 0x0200,
-	0x0001, 0xffc0, 0x0000, 0x0007, 0x0000, 0x7f06, 0x0008, 0x6b62,
-	0x0000, 0x8066, 0x0008, 0x060a, 0x000b, 0xc4c2, 0x000f, 0x4000,
-	0x0002, 0x3a44, 0x0003, 0x8813, 0x000a, 0x2f44, 0x000a, 0x2f44,
-	0x0003, 0x8bd0, 0x0008, 0x808a, 0x0008, 0x0003, 0x0000, 0x8074,
-	0x0000, 0xf080, 0x0003, 0x5ccd, 0x0008, 0x8054, 0x0000, 0x0019,
-	0x0003, 0x0013, 0x0002, 0x3a44, 0x0003, 0x8813, 0x0008, 0x808c,
-	0x0008, 0x0000, 0x0008, 0x8010, 0x0008, 0x0011, 0x0004, 0x0387,
-	0x0000, 0x42fe, 0x0001, 0xffc0, 0x0008, 0x00ff, 0x0008, 0x7f10,
-	0x0004, 0x0387, 0x0008, 0x4310, 0x000b, 0x03dd, 0x0002, 0x3941,
-	0x000b, 0x0ce2, 0x000f, 0x4000, 0x0000, 0x8072, 0x0008, 0x0404,
-	0x000f, 0x4000, 0x0008, 0x8010, 0x0008, 0x0012, 0x0004, 0x0387,
-	0x000c, 0x04a9, 0x0000, 0x1110, 0x0004, 0x0387, 0x0008, 0x11fc,
-	0x000b, 0xb4e8, 0x0003, 0x0013, 0x0009, 0xc2c0, 0x0008, 0x00ff,
-	0x0000, 0x7f00, 0x0001, 0xc3c0, 0x0008, 0xff00, 0x0009, 0x00d0,
-	0x000b, 0x0d13, 0x0000, 0x0d0a, 0x0001, 0x8580, 0x0000, 0x1000,
-	0x0008, 0x7f62, 0x0000, 0x8060, 0x0000, 0x0400, 0x0000, 0x8066,
-	0x0000, 0x0809, 0x000b, 0xc4fd, 0x0000, 0x04fc, 0x000b, 0x350c,
-	0x0000, 0x0460, 0x0008, 0x8062, 0x0000, 0x0004, 0x0000, 0x8066,
-	0x0000, 0x0211, 0x000b, 0xc505, 0x0008, 0x01fe, 0x0009, 0x00e0,
-	0x000b, 0x8d0c, 0x0008, 0x02fe, 0x0001, 0x43e0, 0x0003, 0x0d12,
-	0x0002, 0x0500, 0x0000, 0x7f0a, 0x0009, 0xffe0, 0x0000, 0x0800,
-	0x0003, 0x8cf6, 0x0008, 0x0d08, 0x000f, 0x4000, 0x0008, 0x43fe,
-	0x0001, 0x3e80, 0x0000, 0x0d60, 0x0008, 0x7f62, 0x0000, 0x8066,
-	0x0000, 0x0809, 0x0003, 0xc519, 0x0000, 0x8060, 0x0000, 0x0400,
-	0x0001, 0x84c0, 0x0008, 0xff00, 0x0002, 0x7f70, 0x0009, 0xff80,
-	0x0000, 0x1000, 0x0008, 0x7f62, 0x0000, 0x8066, 0x0000, 0x0809,
-	0x000b, 0xc524, 0x000f, 0x4000, 0xe4a8, 0xa3b9
-};
-unsigned short rseqipx_code_length01 = 0x0a4e;
-/*
- *
- */
-
-unsigned long xseqipx_code_addr01 = 0x0001e000 ;
-unsigned short xseqipx_code01[] = { 
-0x0013, 0x0003, 0x0000, 0x1252, 0x0001, 0xe000, 0x0005, 0x0032,
-	0x0000, 0x0010, 0x0015, 0x0033, 0x0010, 0xbb39, 0x000b, 0x8007,
-	0x0004, 0x0113, 0x0004, 0x0125, 0x0010, 0xc000, 0x0000, 0xc001,
-	0x0000, 0xc0b0, 0x0010, 0xc0b1, 0x0010, 0xc0b2, 0x0000, 0xc0b3,
-	0x0010, 0xc0b4, 0x0000, 0xc0b5, 0x0000, 0xc0b6, 0x0010, 0xc0b7,
-	0x0010, 0xc0b8, 0x0000, 0xc0b9, 0x0000, 0xc0ba, 0x0000, 0xc0c2,
-	0x0010, 0xc0c3, 0x0000, 0xc0c4, 0x0010, 0xc0c5, 0x0010, 0xc0c6,
-	0x0000, 0xc0c7, 0x0000, 0xc0c8, 0x0010, 0xc0c9, 0x0010, 0xc0ca,
-	0x0000, 0xc0cb, 0x0010, 0xc0cc, 0x0000, 0xc0cd, 0x0000, 0xc0ce,
-	0x0010, 0xc0cf, 0x0015, 0x0039, 0x0010, 0xff00, 0x0015, 0x003a,
-	0x0010, 0xff00, 0x0005, 0x00d0, 0x0010, 0xff00, 0x0015, 0x00d1,
-	0x0010, 0xff00, 0x0012, 0x3a40, 0x000b, 0x1031, 0x0002, 0x7940,
-	0x001b, 0x1137, 0x0002, 0x3a42, 0x001b, 0x1035, 0x0003, 0xb035,
-	0x0003, 0xa1e2, 0x0002, 0x3a41, 0x001b, 0x1039, 0x0012, 0x7941,
-	0x001b, 0x1317, 0x0013, 0xe054, 0x0001, 0x0fe8, 0x0000, 0x0001,
-	0x0013, 0x1054, 0x0000, 0x0cfe, 0x0013, 0x6047, 0x0002, 0x3a44,
-	0x001b, 0x1047, 0x0011, 0x02e8, 0x0010, 0x0000, 0x0013, 0x13cd,
-	0x0011, 0x02e8, 0x0010, 0x0005, 0x0013, 0x145f, 0x0012, 0x3a46,
-	0x000b, 0x1054, 0x0011, 0x02e8, 0x0010, 0x0000, 0x0013, 0x104f,
-	0x0011, 0x02e8, 0x0010, 0x0005, 0x000b, 0x1054, 0x0000, 0x12fe,
-	0x0003, 0x6054, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0003, 0x1695,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0010, 0xc131, 0x0015, 0x0033,
-	0x0010, 0xb211, 0x001b, 0x8059, 0x0010, 0xb2ff, 0x0001, 0xb3e0,
-	0x001c, 0x10d5, 0x000b, 0xf02d, 0x0011, 0x3be8, 0x0000, 0x0010,
-	0x001b, 0x1071, 0x0000, 0x0afe, 0x000b, 0x6065, 0x0000, 0x3c0b,
-	0x0003, 0x006d, 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x0a88,
-	0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a,
-	0x001b, 0x806c, 0x0010, 0x3c0a, 0x0002, 0x0c00, 0x0010, 0xff0c,
-	0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x0012, 0x001b, 0x1084,
-	0x0010, 0x08fe, 0x000b, 0x6078, 0x0010, 0x3c09, 0x0003, 0x0080,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0888, 0x0010, 0x0003,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a, 0x000b, 0x807f,
-	0x0000, 0x3c08, 0x0002, 0x0c00, 0x0010, 0xff0c, 0x0013, 0x00d2,
-	0x0011, 0x3be8, 0x0000, 0x0013, 0x000b, 0x108a, 0x0000, 0x3cb0,
-	0x0014, 0x00e5, 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0000, 0x0019,
-	0x000b, 0x109d, 0x0010, 0x04fe, 0x001b, 0x6091, 0x0010, 0x3c05,
-	0x0013, 0x0099, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0488,
-	0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x3c0a,
-	0x000b, 0x8098, 0x0000, 0x3c04, 0x0002, 0x0c00, 0x0010, 0xff0c,
-	0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x001b, 0x001b, 0x10a6,
-	0x0010, 0xc014, 0x0000, 0xc013, 0x0000, 0xc010, 0x0015, 0x000f,
-	0x0010, 0x0000, 0x0013, 0x00d2, 0x0011, 0x3be8, 0x0000, 0x0015,
-	0x001b, 0x10b2, 0x0004, 0x011c, 0x0014, 0x012e, 0x0015, 0x0039,
-	0x0000, 0x8000, 0x0017, 0x8000, 0x0004, 0x0113, 0x0004, 0x0125,
-	0x0014, 0x00fe, 0x0013, 0x002d, 0x0011, 0x3be8, 0x0000, 0x0016,
-	0x000b, 0x10c4, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0003, 0x10be,
-	0x0001, 0x0fe8, 0x0000, 0x0002, 0x0003, 0x10be, 0x0015, 0x0039,
-	0x0010, 0x1010, 0x0013, 0x00d2, 0x0015, 0x0039, 0x0000, 0x5040,
-	0x0015, 0x00b8, 0x0000, 0x0008, 0x0014, 0x0925, 0x0013, 0x00d2,
-	0x0011, 0x3be8, 0x0010, 0x0017, 0x001b, 0x10c9, 0x0010, 0x3cc3,
-	0x0013, 0x00d2, 0x0011, 0x3be8, 0x0010, 0x0018, 0x000b, 0x10ce,
-	0x0000, 0x3cc2, 0x0013, 0x00d2, 0x0005, 0x00ce, 0x0000, 0x0001,
-	0x0000, 0x3bcf, 0x0014, 0x08e7, 0x0015, 0x0039, 0x0000, 0x8000,
-	0x0013, 0x002d, 0x0001, 0xb288, 0x0000, 0x0002, 0x0001, 0xc180,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x80db,
-	0x0002, 0xb200, 0x0011, 0xffc8, 0x0000, 0x0007, 0x0010, 0xffb2,
-	0x0010, 0xc131, 0x0015, 0x0033, 0x0010, 0xb20a, 0x0001, 0xb0d0,
-	0x001b, 0x80e4, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0xb088,
-	0x0000, 0x0010, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb109,
-	0x000b, 0x80ec, 0x0001, 0xb1e8, 0x0010, 0xffff, 0x0013, 0x10fd,
-	0x0000, 0x11fe, 0x001b, 0x60f4, 0x0000, 0xb012, 0x0013, 0x00fc,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x1188, 0x0010, 0x0003,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb00a, 0x000b, 0x80fb,
-	0x0000, 0xb011, 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0xbc88, 0x0000, 0x001f, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xc411, 0x000b, 0x8105, 0x0011, 0xbc88, 0x0010, 0x0018,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc609, 0x001b, 0x810b,
-	0x0011, 0xbc88, 0x0000, 0x0037, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xc709, 0x000b, 0x8111, 0x0017, 0x4000, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0001, 0xbb88, 0x0000, 0x0001, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0x0269, 0x001b, 0x811a, 0x0017, 0x4000,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbb88, 0x0000, 0x0001,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0x026a, 0x001b, 0x8123,
-	0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbb88,
-	0x0010, 0x000f, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x0f59,
-	0x001b, 0x812c, 0x0017, 0x4000, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0001, 0xbb88, 0x0010, 0x000f, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0x0f5a, 0x000b, 0x8135, 0x0017, 0x4000, 0x0000, 0xd0ff,
-	0x0012, 0xff40, 0x000b, 0x1031, 0x0015, 0x00d1, 0x0010, 0x0101,
-	0x0003, 0x913c, 0x0005, 0x0079, 0x0000, 0x0001, 0x0003, 0x913f,
-	0x0015, 0x00d1, 0x0000, 0x0100, 0x0011, 0x02e8, 0x0000, 0x0002,
-	0x0003, 0x1167, 0x0011, 0x02e8, 0x0000, 0x0001, 0x0003, 0x117f,
-	0x0011, 0x02e8, 0x0000, 0x0004, 0x0003, 0x119d, 0x0011, 0x02e8,
-	0x0010, 0x0003, 0x0003, 0x11ce, 0x0005, 0x0002, 0x0010, 0x0000,
-	0x0000, 0xc00e, 0x0000, 0xc00d, 0x0010, 0xc003, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0001, 0xbd88, 0x0010, 0x0009, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x815a, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x815e, 0x0012, 0x3a45,
-	0x0013, 0x1166, 0x0015, 0x003a, 0x0000, 0x2000, 0x0015, 0x003a,
-	0x0010, 0x1010, 0x0004, 0x0911, 0x0003, 0x004f, 0x0012, 0x7849,
-	0x0003, 0x11dc, 0x0010, 0x0dfe, 0x0003, 0x6150, 0x0012, 0x0c10,
-	0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88,
-	0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309,
-	0x000b, 0x8174, 0x0010, 0xb3fe, 0x0013, 0x617c, 0x0010, 0xb30b,
-	0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x817a, 0x0003, 0x01d1,
-	0x0000, 0xc00b, 0x0010, 0xc00a, 0x0003, 0x01d1, 0x0000, 0x78b0,
-	0x0012, 0xb044, 0x0003, 0x11dc, 0x0002, 0xb049, 0x0003, 0x11dc,
-	0x0010, 0x71ff, 0x0012, 0xff38, 0x0010, 0xff71, 0x0010, 0x0dfe,
-	0x0003, 0x614e, 0x0012, 0x0c10, 0x0010, 0xff0c, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0003, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb309, 0x001b, 0x8192, 0x0010, 0xb3fe,
-	0x0003, 0x619a, 0x0000, 0xb309, 0x0015, 0x0033, 0x0010, 0xc00a,
-	0x001b, 0x8198, 0x0003, 0x01d1, 0x0010, 0xc009, 0x0000, 0xc008,
-	0x0003, 0x01d1, 0x0000, 0x78b0, 0x0012, 0xb044, 0x0003, 0x11dc,
-	0x0002, 0xb049, 0x0003, 0x11dc, 0x0010, 0x71ff, 0x0012, 0xff38,
-	0x0010, 0xff71, 0x0010, 0x0dfe, 0x0003, 0x614e, 0x0012, 0x0c10,
-	0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88,
-	0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309,
-	0x001b, 0x81b0, 0x0010, 0xb3fe, 0x0003, 0x61b8, 0x0000, 0xb305,
-	0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x81b6, 0x0013, 0x01ba,
-	0x0010, 0xc005, 0x0000, 0xc004, 0x0002, 0x033f, 0x0002, 0xff27,
-	0x0000, 0x0db8, 0x0014, 0x03c2, 0x0000, 0x0db8, 0x0014, 0x0925,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0xbc88, 0x0010, 0x0000,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb309, 0x001b, 0x81c7,
-	0x0011, 0xb3e8, 0x0000, 0x0002, 0x000b, 0x114e, 0x0005, 0x0002,
-	0x0010, 0x0005, 0x0003, 0x0150, 0x0012, 0x7849, 0x0003, 0x11dc,
-	0x0003, 0x0150, 0x0000, 0x0db8, 0x0012, 0x0345, 0x000b, 0x11d7,
-	0x0002, 0x033f, 0x0014, 0x03c2, 0x0003, 0x014e, 0x0002, 0x033f,
-	0x0002, 0xff27, 0x0014, 0x03c2, 0x0014, 0x0925, 0x0003, 0x014e,
-	0x0015, 0x00b8, 0x0000, 0x0001, 0x0015, 0x003a, 0x0010, 0x0101,
-	0x0014, 0x0925, 0x0003, 0x015f, 0x0001, 0x2bd8, 0x0010, 0x0000,
-	0x0000, 0xffba, 0x0003, 0xb1e5, 0x0005, 0x002a, 0x0000, 0x0002,
-	0x0001, 0xbac8, 0x0000, 0x0700, 0x000b, 0x12d2, 0x0011, 0x15e8,
-	0x0000, 0x0002, 0x0013, 0x1248, 0x0011, 0x15e8, 0x0000, 0x0001,
-	0x0003, 0x11f4, 0x0005, 0x0015, 0x0010, 0x0000, 0x0003, 0x022b,
-	0x0005, 0x0015, 0x0010, 0x0000, 0x0002, 0xba43, 0x0003, 0x122c,
-	0x0003, 0xb1f8, 0x0005, 0x002a, 0x0000, 0x0004, 0x0012, 0xba42,
-	0x0003, 0x1232, 0x0012, 0x104b, 0x000b, 0x122b, 0x0000, 0x1a30,
-	0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b2a,
-	0x001b, 0x8204, 0x0011, 0x20d8, 0x0010, 0x0000, 0x0000, 0xffb0,
-	0x0001, 0x21d8, 0x0010, 0x0000, 0x0010, 0xffb1, 0x0001, 0x22d8,
-	0x0010, 0x0000, 0x0010, 0xffb2, 0x0011, 0x23d8, 0x0010, 0x0000,
-	0x0000, 0xffb3, 0x0001, 0x24d8, 0x0010, 0x0000, 0x0010, 0xffb4,
-	0x0011, 0x25d8, 0x0010, 0x0000, 0x0000, 0xffb5, 0x0001, 0x28d8,
-	0x0010, 0x0000, 0x0010, 0xffb8, 0x0011, 0x29d8, 0x0010, 0x0000,
-	0x0000, 0xffb9, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x0007,
-	0x0015, 0x0033, 0x0010, 0xb032, 0x000b, 0x8222, 0x0000, 0x1a30,
-	0x0005, 0x0031, 0x0010, 0x000f, 0x0015, 0x0033, 0x0010, 0xb812,
-	0x000b, 0x8228, 0x0005, 0x0015, 0x0010, 0x0000, 0x0013, 0x0035,
-	0x0000, 0x1efe, 0x0013, 0x6240, 0x0014, 0x0277, 0x0000, 0x1efe,
-	0x000c, 0x6277, 0x0003, 0x022b, 0x0000, 0x1a30, 0x0005, 0x0031,
-	0x0000, 0x0020, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x8237,
-	0x0002, 0xb02f, 0x0000, 0xffb0, 0x0005, 0x0031, 0x0000, 0x0020,
-	0x0015, 0x0033, 0x0000, 0xb00a, 0x001b, 0x823e, 0x0003, 0x01ff,
-	0x0015, 0x00b8, 0x0010, 0x0005, 0x0014, 0x0925, 0x0000, 0x13b8,
-	0x0015, 0x003a, 0x0010, 0x0404, 0x0014, 0x0925, 0x0003, 0x022b,
-	0x0005, 0x0015, 0x0000, 0x0001, 0x0012, 0xba42, 0x0013, 0x1256,
-	0x0003, 0xb24c, 0x0001, 0x2bd8, 0x0010, 0x0000, 0x0012, 0xff4f,
-	0x000b, 0x11e2, 0x0002, 0xba43, 0x001b, 0x1232, 0x0000, 0x1efe,
-	0x000c, 0x6277, 0x0003, 0x022b, 0x0001, 0x28d8, 0x0010, 0x0000,
-	0x0010, 0xffb8, 0x0011, 0x29d8, 0x0010, 0x0000, 0x0000, 0xffb9,
-	0x0014, 0x02e8, 0x0002, 0x3a42, 0x000b, 0x122b, 0x0000, 0x1c30,
-	0x0015, 0x00ff, 0x0000, 0x0002, 0x0002, 0x1f43, 0x001b, 0x1267,
-	0x0001, 0xff88, 0x0000, 0x0002, 0x0003, 0x0269, 0x0001, 0xff88,
-	0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb011,
-	0x000b, 0x826c, 0x0000, 0xb0ff, 0x0011, 0x16a0, 0x0000, 0xff16,
-	0x001b, 0x2273, 0x0002, 0xb100, 0x0003, 0x0274, 0x0010, 0xb1ff,
-	0x0001, 0x17a0, 0x0010, 0xff17, 0x0013, 0x0232, 0x0000, 0x16ff,
-	0x0001, 0x18a0, 0x0010, 0xff00, 0x000b, 0x227e, 0x0002, 0x1700,
-	0x0013, 0x12d1, 0x0013, 0x027f, 0x0010, 0x17ff, 0x0011, 0x19a0,
-	0x0013, 0x22d1, 0x0011, 0x00d0, 0x0013, 0x12d1, 0x0000, 0x1c30,
-	0x0000, 0x1b31, 0x0015, 0x0033, 0x0000, 0xb131, 0x000b, 0x8287,
-	0x0013, 0xb288, 0x0000, 0xb120, 0x0010, 0xb221, 0x0002, 0x1f43,
-	0x001b, 0x1294, 0x0010, 0xc022, 0x0000, 0xc023, 0x0000, 0xb324,
-	0x0000, 0xb425, 0x0010, 0xb3b5, 0x0000, 0xb4b6, 0x0013, 0x0298,
-	0x0000, 0xb322, 0x0000, 0xb423, 0x0000, 0xb524, 0x0010, 0xb625,
-	0x0003, 0xb298, 0x0005, 0x002a, 0x0000, 0x0001, 0x0012, 0x1500,
-	0x0000, 0xff15, 0x0000, 0x16ff, 0x0001, 0xb580, 0x0000, 0xff16,
-	0x000b, 0x22a3, 0x0002, 0x1700, 0x0013, 0x02a4, 0x0010, 0x17ff,
-	0x0001, 0xb680, 0x0010, 0xff17, 0x0012, 0x1e10, 0x0010, 0xff1e,
-	0x0003, 0x62d1, 0x0002, 0x1d00, 0x0010, 0xff1d, 0x0010, 0xc030,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82af,
-	0x0010, 0xb0fe, 0x000b, 0x62d0, 0x0000, 0x1c30, 0x0005, 0x0031,
-	0x0000, 0x0001, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82b7,
-	0x0010, 0xb0fe, 0x001b, 0x62bd, 0x0005, 0x00ce, 0x0010, 0x0005,
-	0x0003, 0x08e7, 0x0010, 0xb01c, 0x0000, 0x1c30, 0x0005, 0x0031,
-	0x0000, 0x0019, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x82c3,
-	0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0000, 0xff1f, 0x0010, 0xc030,
-	0x0011, 0xbe80, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x000b, 0x82cc, 0x0000, 0xb01d, 0x0010, 0x1dff, 0x0013, 0x02ab,
-	0x0000, 0xb01b, 0x0017, 0x4000, 0x0002, 0x3a41, 0x0003, 0x12da,
-	0x0013, 0xb2d4, 0x0005, 0x002a, 0x0000, 0x0004, 0x0005, 0x0015,
-	0x0010, 0x0000, 0x0003, 0x022b, 0x0000, 0x1a30, 0x0005, 0x0031,
-	0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b2a, 0x001b, 0x82df,
-	0x0015, 0x00b8, 0x0000, 0x0004, 0x0014, 0x0925, 0x0000, 0x13b8,
-	0x0015, 0x003a, 0x0010, 0x0404, 0x0014, 0x0925, 0x0013, 0x0039,
-	0x0002, 0x1e00, 0x0010, 0xff1e, 0x0012, 0x1d10, 0x0010, 0xff1d,
-	0x0010, 0xc030, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x000b, 0x82f0, 0x0010, 0xb0fe, 0x001b, 0x6315, 0x0000, 0x1cff,
-	0x0001, 0x1ae0, 0x0013, 0x12ff, 0x0000, 0x1c30, 0x0005, 0x0031,
-	0x0010, 0x0000, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x82fb,
-	0x0010, 0xb0fe, 0x001b, 0x62ff, 0x0000, 0x1aff, 0x0000, 0xff1c,
-	0x0000, 0x1c30, 0x0005, 0x0031, 0x0000, 0x0019, 0x0015, 0x0033,
-	0x0000, 0xb009, 0x001b, 0x8305, 0x0001, 0xb0c8, 0x0010, 0x000f,
-	0x0000, 0xff1f, 0x0001, 0xbf80, 0x0010, 0xff1d, 0x0010, 0xc030,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x830f,
-	0x0010, 0xb0fe, 0x001b, 0x6315, 0x0005, 0x00ce, 0x0010, 0x0006,
-	0x0003, 0x08e7, 0x0000, 0xb01b, 0x0017, 0x4000, 0x0010, 0x79b0,
-	0x0000, 0xd0ff, 0x0012, 0xff40, 0x001b, 0x1039, 0x0015, 0x00d1,
-	0x0010, 0x0101, 0x0013, 0x931d, 0x0005, 0x0079, 0x0000, 0x0002,
-	0x0003, 0x9320, 0x0015, 0x00d1, 0x0000, 0x0100, 0x0010, 0x13fe,
-	0x0013, 0x6371, 0x0012, 0xb04e, 0x001b, 0x139a, 0x0000, 0x78b0,
-	0x0002, 0xb045, 0x0003, 0x13a0, 0x0012, 0x784a, 0x0003, 0x13a0,
-	0x0000, 0x75ff, 0x0011, 0xffc8, 0x0010, 0x1800, 0x001b, 0x13a0,
-	0x0001, 0x0fe8, 0x0000, 0x0001, 0x001b, 0x133c, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x000e, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0x8f0a, 0x001b, 0x833a, 0x0013, 0x03a6,
-	0x0001, 0x0fe8, 0x0000, 0x0002, 0x001b, 0x1347, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0005, 0x0031, 0x0000, 0x001a, 0x0015, 0x0033,
-	0x0010, 0xc00a, 0x000b, 0x8345, 0x0013, 0x03a6, 0x0001, 0x0fe8,
-	0x0010, 0x0000, 0x0003, 0x134e, 0x0005, 0x00ce, 0x0000, 0x0007,
-	0x0010, 0x0fcf, 0x0003, 0x08e1, 0x0002, 0xd142, 0x0013, 0x1367,
-	0x0015, 0x00d1, 0x0000, 0x0400, 0x0011, 0x13e8, 0x0001, 0x1b55,
-	0x000b, 0x1367, 0x0005, 0x0031, 0x0011, 0x1b6d, 0x0015, 0x0033,
-	0x0010, 0xb409, 0x001b, 0x8359, 0x0002, 0xb400, 0x0010, 0xffb4,
-	0x0005, 0x0031, 0x0011, 0x1b6d, 0x0015, 0x0033, 0x0010, 0xb40a,
-	0x001b, 0x8360, 0x0012, 0xd042, 0x0003, 0x1371, 0x0015, 0x00b8,
-	0x0000, 0x000d, 0x0014, 0x0925, 0x0003, 0x0054, 0x0000, 0x13b8,
-	0x0002, 0x1045, 0x0003, 0x136f, 0x0012, 0x103f, 0x0002, 0xff27,
-	0x0014, 0x03c2, 0x0014, 0x0925, 0x0013, 0x0371, 0x0012, 0x103f,
-	0x0014, 0x03c2, 0x0015, 0x000f, 0x0010, 0x0000, 0x0002, 0x3944,
-	0x0013, 0x137a, 0x0015, 0x0039, 0x0000, 0x5040, 0x0015, 0x00b8,
-	0x0000, 0x0008, 0x0014, 0x0925, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0001, 0xbd88, 0x0010, 0x000c, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0xc00a, 0x001b, 0x8381, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0xc00a, 0x000b, 0x8385, 0x0010, 0xc014, 0x0000, 0xc013,
-	0x0000, 0xc010, 0x0000, 0xa4ff, 0x0003, 0x6392, 0x0011, 0xffa8,
-	0x0010, 0x0005, 0x000b, 0x2392, 0x0015, 0x00d1, 0x0010, 0x0404,
-	0x0015, 0x003a, 0x0000, 0x8000, 0x0002, 0x3a47, 0x0003, 0x1399,
-	0x0015, 0x003a, 0x0000, 0x8000, 0x0015, 0x003a, 0x0010, 0x4040,
-	0x0004, 0x08ec, 0x0013, 0x0039, 0x0015, 0x00b8, 0x0010, 0x0003,
-	0x0015, 0x003a, 0x0010, 0x0202, 0x0014, 0x0925, 0x0003, 0x0389,
-	0x0015, 0x00b8, 0x0000, 0x0002, 0x0015, 0x003a, 0x0010, 0x0202,
-	0x0014, 0x0925, 0x0003, 0x0389, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x1388, 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xb009, 0x000b, 0x83ad, 0x0011, 0x1388, 0x0010, 0x0003,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x83b3,
-	0x0010, 0xb0fe, 0x0013, 0x63b8, 0x0000, 0xb012, 0x0003, 0x03ba,
-	0x0010, 0xc012, 0x0010, 0xc011, 0x0012, 0x104b, 0x0003, 0x134e,
-	0x0002, 0x103b, 0x0010, 0xff03, 0x0005, 0x0002, 0x0010, 0x0000,
-	0x0000, 0xc00d, 0x0013, 0x034e, 0x0000, 0xffb0, 0x0010, 0xc3b1,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xb888, 0x0010, 0x0011,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb012, 0x000b, 0x83cb,
-	0x0017, 0x4000, 0x0002, 0xd142, 0x001b, 0x1485, 0x0012, 0x3a43,
-	0x0003, 0x13de, 0x0015, 0x003a, 0x0000, 0x0800, 0x0010, 0x0db0,
-	0x0013, 0x63de, 0x0000, 0x0bff, 0x0001, 0xb0e0, 0x0003, 0x1407,
-	0x0010, 0x09ff, 0x0001, 0xb0e0, 0x0003, 0x13eb, 0x0010, 0x05ff,
-	0x0001, 0xb0e0, 0x0003, 0x13e2, 0x0000, 0xc00e, 0x0000, 0x05fe,
-	0x0013, 0x63e8, 0x0000, 0x050d, 0x0005, 0x0002, 0x0000, 0x0004,
-	0x0014, 0x046c, 0x0002, 0x3a47, 0x001b, 0x146b, 0x0013, 0x0402,
-	0x0000, 0x09fe, 0x0013, 0x6404, 0x0000, 0x090d, 0x0005, 0x0002,
-	0x0000, 0x0001, 0x0014, 0x049a, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x0d88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xba09, 0x001b, 0x83f5, 0x0011, 0x03c8, 0x0010, 0x000f,
-	0x0000, 0xffb6, 0x0011, 0xb6e8, 0x0000, 0x0001, 0x0003, 0x153f,
-	0x0011, 0xb6e8, 0x0000, 0x0002, 0x0013, 0x1561, 0x0011, 0xb6e8,
-	0x0010, 0x0003, 0x0003, 0x1653, 0x0004, 0x08ec, 0x0013, 0x046b,
-	0x0010, 0x0bfe, 0x0013, 0x646b, 0x0010, 0x0b0d, 0x0005, 0x0002,
-	0x0000, 0x0002, 0x0014, 0x049a, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x0d88, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xba09, 0x000b, 0x8411, 0x0000, 0xb930, 0x0005, 0x0031,
-	0x0010, 0x0021, 0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x8417,
-	0x0001, 0xb0a8, 0x0000, 0x199a, 0x0013, 0x241d, 0x0005, 0x00b0,
-	0x0000, 0x1999, 0x0012, 0xb050, 0x0000, 0xffb0, 0x0002, 0xff50,
-	0x0002, 0xff50, 0x0001, 0xb080, 0x0000, 0xffb0, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0006, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb00a, 0x001b, 0x842a, 0x0000, 0xb930,
-	0x0005, 0x0031, 0x0000, 0x0019, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x000b, 0x8430, 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0001, 0xffe8,
-	0x0010, 0x0048, 0x000b, 0x14a9, 0x0005, 0x0002, 0x0010, 0x0006,
-	0x0012, 0x0c10, 0x0010, 0xff0c, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x0d88, 0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0xb109, 0x000b, 0x8441, 0x0000, 0xb10b, 0x000b, 0x6445,
-	0x0010, 0xb10a, 0x0015, 0x0033, 0x0010, 0xc00a, 0x000b, 0x8447,
-	0x0002, 0x032b, 0x0010, 0xff03, 0x0011, 0x0d88, 0x0010, 0x0011,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0x030a, 0x001b, 0x844f,
-	0x0000, 0x11fe, 0x000b, 0x6454, 0x0000, 0x0d12, 0x0013, 0x045d,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0x1188, 0x0010, 0x0003,
-	0x0000, 0xff31, 0x0010, 0x0db0, 0x0015, 0x0033, 0x0000, 0xb00a,
-	0x000b, 0x845c, 0x0000, 0x0d11, 0x0013, 0x046b, 0x0002, 0xd142,
-	0x0003, 0x1462, 0x0013, 0x0485, 0x0000, 0x05fe, 0x0013, 0x646b,
-	0x0005, 0x0002, 0x0000, 0x0004, 0x0000, 0x050d, 0x0014, 0x046c,
-	0x0002, 0x3a47, 0x001b, 0x146b, 0x0004, 0x08ec, 0x0013, 0x0047,
-	0x0001, 0xc7c8, 0x0010, 0x0028, 0x000b, 0x1484, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x000a, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x8476, 0x0002, 0xb04f,
-	0x0013, 0x1484, 0x0001, 0x0fe8, 0x0010, 0x0000, 0x0013, 0x1482,
-	0x0001, 0x0fe8, 0x0000, 0x0002, 0x0013, 0x1482, 0x0015, 0x003a,
-	0x0010, 0x8080, 0x0003, 0x0484, 0x0015, 0x003a, 0x0010, 0x4040,
-	0x0017, 0x4000, 0x0000, 0x12fe, 0x001b, 0x604f, 0x0015, 0x0012,
-	0x0001, 0x1b55, 0x0015, 0x0011, 0x0001, 0x1b55, 0x0001, 0x1288,
-	0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a,
-	0x000b, 0x8490, 0x0005, 0x00b0, 0x0000, 0x8000, 0x0001, 0x1288,
-	0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb00a,
-	0x001b, 0x8498, 0x0003, 0x004f, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0x0309, 0x001b, 0x84a1, 0x0011, 0x0d88, 0x0010, 0x0005,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb909, 0x001b, 0x84a7,
-	0x0017, 0x4000, 0x0005, 0x00b6, 0x0010, 0x0600, 0x0014, 0x0683,
-	0x0004, 0x051b, 0x0000, 0xb05a, 0x0000, 0xb15b, 0x0005, 0x0054,
-	0x0010, 0x0829, 0x0010, 0x0d58, 0x0015, 0x0059, 0x0010, 0xffff,
-	0x0000, 0xb930, 0x0005, 0x0031, 0x0010, 0x001e, 0x0015, 0x0033,
-	0x0000, 0xb009, 0x001b, 0x84b9, 0x0000, 0xb05c, 0x0005, 0x0031,
-	0x0000, 0x001f, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x84bf,
-	0x0001, 0xb0c8, 0x0010, 0x000f, 0x000b, 0x14c6, 0x0015, 0x00ff,
-	0x0010, 0x0005, 0x0013, 0x04ce, 0x0002, 0xb040, 0x0003, 0x14cb,
-	0x0015, 0x00ff, 0x0000, 0x0004, 0x0013, 0x04ce, 0x0001, 0xb0c8,
-	0x0010, 0x0006, 0x0002, 0xff60, 0x0010, 0xffb2, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0019, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0010, 0xb109, 0x001b, 0x84d6, 0x0012, 0xb170,
-	0x0011, 0xffc8, 0x0010, 0xff00, 0x0011, 0xb2d0, 0x0010, 0xff60,
-	0x0002, 0xb045, 0x0013, 0x14e1, 0x0015, 0x00b2, 0x0000, 0x0002,
-	0x0003, 0x04eb, 0x0002, 0xb046, 0x0003, 0x14e6, 0x0015, 0x00b2,
-	0x0000, 0x0001, 0x0003, 0x04eb, 0x0015, 0x00b2, 0x0010, 0x0000,
-	0x0000, 0xc0b0, 0x0010, 0xc0b1, 0x0013, 0x04f1, 0x0000, 0xb930,
-	0x0005, 0x0031, 0x0010, 0x002b, 0x0015, 0x0033, 0x0000, 0xb011,
-	0x000b, 0x84f0, 0x0010, 0xb16a, 0x0010, 0xb06b, 0x0000, 0xb261,
-	0x0015, 0x0044, 0x0010, 0x0018, 0x0000, 0xb930, 0x0005, 0x0031,
-	0x0000, 0x0023, 0x0015, 0x0033, 0x0000, 0x6241, 0x001b, 0x84fb,
-	0x0003, 0x94fc, 0x0015, 0x00a0, 0x0000, 0x0020, 0x0012, 0xd041,
-	0x000b, 0x14ff, 0x0015, 0x00d1, 0x0010, 0x0202, 0x0013, 0x9503,
-	0x0000, 0x75ff, 0x0011, 0xffc8, 0x0000, 0x1804, 0x0001, 0xffd8,
-	0x0010, 0x0009, 0x0013, 0x9509, 0x0000, 0xff75, 0x0003, 0x950b,
-	0x0015, 0x00d1, 0x0000, 0x0200, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0001, 0xbd88, 0x0000, 0x0008, 0x0000, 0xff31, 0x0015, 0x00b1,
-	0x0010, 0x07d0, 0x0005, 0x00b0, 0x0010, 0x0009, 0x0015, 0x0033,
-	0x0000, 0xb012, 0x000b, 0x8519, 0x0013, 0x046b, 0x0000, 0xba30,
-	0x0005, 0x0031, 0x0010, 0x0035, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x000b, 0x8520, 0x0002, 0xb040, 0x0003, 0x153c, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0005, 0x0031, 0x0001, 0x1b71, 0x0015, 0x0033,
-	0x0000, 0xb011, 0x000b, 0x8529, 0x0002, 0xb100, 0x0010, 0xffb1,
-	0x001b, 0x2530, 0x0012, 0xb000, 0x0000, 0xffb0, 0x0013, 0x252a,
-	0x0015, 0x0033, 0x0000, 0xb012, 0x000b, 0x8532, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0013, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb012, 0x001b, 0x853a, 0x0003, 0x053e,
-	0x0010, 0xc0b1, 0x0000, 0xc0b0, 0x0017, 0x4000, 0x0005, 0x00b6,
-	0x0010, 0x0500, 0x0014, 0x0683, 0x0005, 0x0054, 0x0010, 0x0889,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0002,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x854b,
-	0x0010, 0xb058, 0x0000, 0x0d59, 0x0000, 0xb930, 0x0005, 0x0031,
-	0x0000, 0x0023, 0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x8553,
-	0x0010, 0xb15c, 0x0010, 0xb05d, 0x0005, 0x0031, 0x0010, 0x002b,
-	0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x855a, 0x0000, 0xb15e,
-	0x0000, 0xb05f, 0x0003, 0x955d, 0x0015, 0x00a0, 0x0010, 0x000c,
-	0x0003, 0x0668, 0x0005, 0x00b6, 0x0000, 0x0700, 0x0014, 0x0683,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0009,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb709, 0x000b, 0x856b,
-	0x0012, 0xb749, 0x0003, 0x1571, 0x0005, 0x0054, 0x0010, 0x0889,
-	0x0003, 0x0573, 0x0005, 0x0054, 0x0010, 0x0898, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x0002, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x857a, 0x0010, 0xb058,
-	0x0000, 0x0d59, 0x0001, 0xb9c8, 0x0010, 0xf000, 0x0001, 0xffe8,
-	0x0010, 0xf000, 0x001b, 0x15a3, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x0d88, 0x0010, 0x0005, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xb009, 0x000b, 0x8589, 0x0001, 0xb0c8, 0x0000, 0xf700,
-	0x0000, 0xffb0, 0x0011, 0xb0e8, 0x0000, 0xf100, 0x0013, 0x15ea,
-	0x0011, 0xb0e8, 0x0000, 0xf200, 0x0013, 0x15ef, 0x0011, 0xb0e8,
-	0x0010, 0xf300, 0x0003, 0x1614, 0x0011, 0xb0e8, 0x0000, 0xf400,
-	0x0013, 0x1619, 0x0011, 0xb0e8, 0x0010, 0xf500, 0x0013, 0x15ea,
-	0x0011, 0xb0e8, 0x0010, 0xf600, 0x0003, 0x162b, 0x0005, 0x00ce,
-	0x0010, 0x0009, 0x0000, 0xb0cf, 0x0003, 0x08e1, 0x0000, 0xb930,
-	0x0005, 0x0031, 0x0000, 0x0025, 0x0015, 0x0033, 0x0000, 0xb039,
-	0x000b, 0x85a8, 0x0012, 0xb749, 0x0013, 0x15ad, 0x0002, 0xb52c,
-	0x0000, 0xffb5, 0x0000, 0xb162, 0x0000, 0xb063, 0x0005, 0x0031,
-	0x0000, 0x001f, 0x0015, 0x0033, 0x0000, 0xb309, 0x000b, 0x85b3,
-	0x0001, 0xb3c8, 0x0010, 0x0003, 0x0003, 0x15bb, 0x0010, 0xffb2,
-	0x0001, 0xffe8, 0x0010, 0x0003, 0x001b, 0x15bd, 0x0000, 0xc2b7,
-	0x0013, 0x0647, 0x0001, 0xb2e8, 0x0000, 0x0001, 0x0013, 0x15c4,
-	0x0005, 0x00ce, 0x0010, 0x000a, 0x0010, 0xb2cf, 0x0003, 0x08e1,
-	0x0010, 0xb465, 0x0010, 0xb667, 0x0015, 0x00b7, 0x0010, 0x0018,
-	0x0001, 0xb5c8, 0x0010, 0x0300, 0x0013, 0x15e9, 0x0012, 0xb548,
-	0x0013, 0x15d0, 0x0000, 0xb6ff, 0x0011, 0xb780, 0x0010, 0xffb7,
-	0x0002, 0xb549, 0x0013, 0x15d5, 0x0010, 0xb4ff, 0x0011, 0xb780,
-	0x0010, 0xffb7, 0x0015, 0x0044, 0x0010, 0x0018, 0x0005, 0x0031,
-	0x0000, 0x002c, 0x0015, 0x0033, 0x0000, 0x6841, 0x001b, 0x85db,
-	0x0015, 0x0044, 0x0000, 0x0019, 0x0005, 0x0031, 0x0000, 0x0034,
-	0x0015, 0x0033, 0x0000, 0x5029, 0x001b, 0x85e2, 0x0015, 0x0044,
-	0x0000, 0x0008, 0x0011, 0xb7c8, 0x0010, 0x0003, 0x0013, 0x15e9,
-	0x0010, 0xff55, 0x0013, 0x0647, 0x0005, 0x00b5, 0x0000, 0x0008,
-	0x0015, 0x00b7, 0x0010, 0x0018, 0x0013, 0x0647, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0000, 0x000b, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb011, 0x001b, 0x85f6, 0x0010, 0xb1ff,
-	0x0001, 0xb0d0, 0x0003, 0x15ff, 0x0005, 0x00b5, 0x0010, 0x0b02,
-	0x0010, 0xb062, 0x0010, 0xb163, 0x0003, 0x0601, 0x0005, 0x00b5,
-	0x0000, 0x0302, 0x0015, 0x0065, 0x0010, 0x0012, 0x0005, 0x0067,
-	0x0000, 0x0008, 0x0015, 0x006c, 0x0000, 0x7000, 0x0005, 0x006d,
-	0x0010, 0x0500, 0x0015, 0x006f, 0x0010, 0x000a, 0x0015, 0x0044,
-	0x0000, 0x0001, 0x0005, 0x0052, 0x0000, 0x2500, 0x0015, 0x0044,
-	0x0000, 0x0008, 0x0015, 0x00b7, 0x0000, 0x0032, 0x0013, 0x0647,
-	0x0005, 0x00b5, 0x0010, 0x0028, 0x0015, 0x00b7, 0x0010, 0x0018,
-	0x0013, 0x0647, 0x0005, 0x00b5, 0x0000, 0x0100, 0x0005, 0x0067,
-	0x0000, 0x0008, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88,
-	0x0010, 0x0018, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x001b, 0x8624, 0x0001, 0xb0c8, 0x0010, 0x00ff, 0x0010, 0xff69,
-	0x0015, 0x00b7, 0x0000, 0x0020, 0x0013, 0x0647, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0005, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb609, 0x000b, 0x8632, 0x0001, 0xb6c8,
-	0x0010, 0xff00, 0x0000, 0xffb0, 0x0015, 0x0033, 0x0000, 0xb00a,
-	0x000b, 0x8638, 0x0001, 0xb6c8, 0x0010, 0x00ff, 0x0012, 0xff10,
-	0x001b, 0x1641, 0x0000, 0xffb5, 0x0015, 0x00b7, 0x0010, 0x0018,
-	0x0013, 0x0647, 0x0010, 0xff63, 0x0005, 0x00b5, 0x0000, 0x0800,
-	0x0015, 0x00b7, 0x0010, 0x0018, 0x0013, 0x0647, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x0d88, 0x0010, 0x0009, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x864e, 0x0010, 0xb561,
-	0x0013, 0x9650, 0x0010, 0xb7a0, 0x0003, 0x0668, 0x0005, 0x00b6,
-	0x0010, 0x0300, 0x0014, 0x0683, 0x0005, 0x0054, 0x0010, 0x0819,
-	0x0010, 0x0d58, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88,
-	0x0000, 0x0002, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x001b, 0x8660, 0x0000, 0xb059, 0x0003, 0x9662, 0x0010, 0xc0a0,
-	0x0010, 0x71ff, 0x0002, 0xff28, 0x0010, 0xff71, 0x0003, 0x0668,
-	0x0012, 0xd041, 0x000b, 0x1668, 0x0015, 0x00d1, 0x0010, 0x0202,
-	0x0000, 0x75ff, 0x0011, 0xffc8, 0x0000, 0x1804, 0x0001, 0xffd8,
-	0x0010, 0x0009, 0x0013, 0x9671, 0x0000, 0xff75, 0x0003, 0x9673,
-	0x0015, 0x00d1, 0x0000, 0x0200, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0001, 0xbd88, 0x0000, 0x0008, 0x0000, 0xff31, 0x0005, 0x00b0,
-	0x0010, 0x0009, 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0015, 0x0033,
-	0x0000, 0xb012, 0x001b, 0x8681, 0x0013, 0x046b, 0x0015, 0x0044,
-	0x0000, 0x0008, 0x0005, 0x0098, 0x0010, 0x0056, 0x0015, 0x0099,
-	0x0000, 0x9575, 0x0004, 0x08a8, 0x0000, 0xb096, 0x0012, 0xb270,
-	0x0010, 0xff56, 0x0014, 0x08ca, 0x0010, 0xb052, 0x0010, 0xb153,
-	0x0000, 0xb6ff, 0x0011, 0xb2d0, 0x0010, 0xff50, 0x0010, 0xb351,
-	0x0017, 0x4000, 0x0001, 0x12e8, 0x0001, 0x1b55, 0x0003, 0x1845,
-	0x0015, 0x00d1, 0x0000, 0x0400, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0001, 0x1288, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0x1009, 0x000b, 0x86a1, 0x0015, 0x000f, 0x0000, 0x0001,
-	0x0010, 0xc014, 0x0000, 0x1213, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x1388, 0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xba09, 0x000b, 0x86ad, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x1388, 0x0010, 0x0005, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0x1a09, 0x000b, 0x86b5, 0x0012, 0x104b, 0x001b, 0x16be,
-	0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x000b, 0x0015, 0x0033,
-	0x0000, 0x1621, 0x001b, 0x86bd, 0x0010, 0x15fe, 0x000b, 0x66dd,
-	0x0004, 0x0704, 0x0002, 0x3a42, 0x000b, 0x1703, 0x0001, 0x10c8,
-	0x0010, 0x000f, 0x000b, 0x1766, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x1388, 0x0000, 0x0008, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xb009, 0x000b, 0x86cd, 0x0011, 0xb0e8, 0x0010, 0x0009,
-	0x0003, 0x16d4, 0x0011, 0xb0e8, 0x0000, 0x0001, 0x001b, 0x1702,
-	0x0011, 0x1388, 0x0010, 0x000a, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xb009, 0x000b, 0x86d9, 0x0002, 0xb04f, 0x001b, 0x16f9,
-	0x0013, 0x0702, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x1388,
-	0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x001b, 0x86e4, 0x0015, 0x0033, 0x0010, 0xc00a, 0x001b, 0x86e7,
-	0x0010, 0xb0fe, 0x0003, 0x66ec, 0x0000, 0xb012, 0x0013, 0x06ee,
-	0x0010, 0xc012, 0x0010, 0xc011, 0x0015, 0x000f, 0x0010, 0x0000,
-	0x0002, 0x3944, 0x0013, 0x16f7, 0x0015, 0x0039, 0x0000, 0x5040,
-	0x0015, 0x00b8, 0x0000, 0x0008, 0x0014, 0x0925, 0x0000, 0xc013,
-	0x0003, 0x0703, 0x0010, 0x02fe, 0x0003, 0x66fe, 0x0015, 0x003a,
-	0x0010, 0x2020, 0x0003, 0x0703, 0x0015, 0x003a, 0x0000, 0x2000,
-	0x0015, 0x003a, 0x0010, 0x1010, 0x0004, 0x0911, 0x0003, 0x0054,
-	0x0003, 0xb704, 0x0005, 0x002a, 0x0000, 0x0004, 0x0000, 0xba30,
-	0x0005, 0x0031, 0x0010, 0x001b, 0x0015, 0x0033, 0x0000, 0xb009,
-	0x000b, 0x870c, 0x0000, 0xc02c, 0x0000, 0xb02d, 0x0012, 0x104b,
-	0x0013, 0x1727, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0000, 0x0023,
-	0x0015, 0x0033, 0x0000, 0xb129, 0x001b, 0x8716, 0x0000, 0xb120,
-	0x0010, 0xb221, 0x0000, 0xb322, 0x0000, 0xb423, 0x0000, 0xb524,
-	0x0000, 0xc025, 0x0010, 0xb526, 0x0010, 0xc027, 0x0010, 0xb516,
-	0x0010, 0xc017, 0x0000, 0xb518, 0x0000, 0xc019, 0x0010, 0xc028,
-	0x0000, 0xc029, 0x0010, 0xc01e, 0x0013, 0x075d, 0x0012, 0x1044,
-	0x0003, 0x1757, 0x0002, 0x1034, 0x0000, 0xff10, 0x0000, 0x1a30,
-	0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b29,
-	0x000b, 0x8730, 0x0000, 0x1c30, 0x0000, 0x1b31, 0x0015, 0x0033,
-	0x0000, 0xb131, 0x000b, 0x8735, 0x0002, 0x1f43, 0x000b, 0x173c,
-	0x0010, 0xb3b5, 0x0000, 0xb4b6, 0x0000, 0xc0b3, 0x0010, 0xc0b4,
-	0x0000, 0xb120, 0x0010, 0xb221, 0x0000, 0xb322, 0x0000, 0xb423,
-	0x0000, 0xb524, 0x0010, 0xb625, 0x0010, 0xb516, 0x0000, 0xb617,
-	0x0000, 0x1826, 0x0000, 0x1927, 0x0000, 0x1a30, 0x0005, 0x0031,
-	0x0010, 0x000f, 0x0015, 0x0033, 0x0000, 0xb011, 0x000b, 0x874b,
-	0x0000, 0xb028, 0x0000, 0xb129, 0x0012, 0x1e10, 0x0010, 0xff1e,
-	0x0013, 0x675d, 0x0002, 0x1d00, 0x0010, 0xff1d, 0x0004, 0x02ab,
-	0x0002, 0x3a42, 0x0003, 0x175d, 0x0003, 0x0765, 0x0000, 0x1a30,
-	0x0005, 0x0031, 0x0000, 0x0002, 0x0015, 0x0033, 0x0000, 0x1b79,
-	0x000b, 0x875c, 0x0003, 0xb75d, 0x0005, 0x002a, 0x0000, 0x0001,
-	0x0005, 0x0015, 0x0000, 0x0001, 0x0000, 0x1efe, 0x0003, 0x6765,
-	0x0003, 0x0277, 0x0017, 0x4000, 0x0000, 0xba30, 0x0005, 0x0031,
-	0x0010, 0x001b, 0x0015, 0x0033, 0x0010, 0xb051, 0x001b, 0x876b,
-	0x0000, 0xb0a3, 0x0010, 0xb697, 0x0010, 0xb946, 0x0015, 0x00a5,
-	0x0000, 0x0010, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x1388,
-	0x0000, 0x0002, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb509,
-	0x000b, 0x8778, 0x0014, 0x08ca, 0x0004, 0x08b9, 0x0012, 0xb470,
-	0x0010, 0xffb4, 0x0010, 0xb48e, 0x0010, 0xb08a, 0x0010, 0xb18b,
-	0x0012, 0x104d, 0x0003, 0x1783, 0x0013, 0x07b0, 0x0012, 0x104b,
-	0x0013, 0x1796, 0x0005, 0x008c, 0x0010, 0x0829, 0x0010, 0xc08d,
-	0x0001, 0xb2d8, 0x0010, 0x0600, 0x0010, 0xff88, 0x0010, 0xb389,
-	0x0000, 0x1390, 0x0010, 0xb591, 0x0000, 0xc08f, 0x0010, 0x1ab9,
-	0x0004, 0x051b, 0x0013, 0x9791, 0x0010, 0xb092, 0x0010, 0xb193,
-	0x0013, 0x9794, 0x0013, 0x07ab, 0x0005, 0x008c, 0x0000, 0x0809,
-	0x0015, 0x008d, 0x0000, 0x0008, 0x0001, 0xb2d8, 0x0000, 0x0100,
-	0x0010, 0xff88, 0x0010, 0xb389, 0x0000, 0x1390, 0x0010, 0xb591,
-	0x0000, 0xc08f, 0x0000, 0x1a30, 0x0005, 0x0031, 0x0010, 0x000f,
-	0x0015, 0x0033, 0x0000, 0xb011, 0x000b, 0x87a6, 0x0013, 0x97a7,
-	0x0000, 0xb192, 0x0000, 0xb093, 0x0003, 0x97aa, 0x0010, 0x19a1,
-	0x0000, 0x18a2, 0x0015, 0x00b1, 0x0010, 0x0096, 0x0003, 0x0821,
-	0x0000, 0xb590, 0x0010, 0x1391, 0x0001, 0x10c8, 0x0010, 0x000f,
-	0x0001, 0xffe8, 0x0010, 0x0005, 0x0013, 0x17d7, 0x0001, 0xb2d8,
-	0x0000, 0x0700, 0x0010, 0xff88, 0x0010, 0xb389, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x1388, 0x0010, 0x0009, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x87c2, 0x0002, 0xb049,
-	0x0013, 0x17ca, 0x0005, 0x008c, 0x0010, 0x0889, 0x0015, 0x00b1,
-	0x0010, 0x0096, 0x0013, 0x07ce, 0x0005, 0x008c, 0x0010, 0x0898,
-	0x0015, 0x00b1, 0x0000, 0x0092, 0x0010, 0xc08d, 0x0000, 0xc08f,
-	0x0013, 0x97d0, 0x0000, 0xc092, 0x0010, 0xc093, 0x0013, 0x97d3,
-	0x0010, 0x19a1, 0x0000, 0x18a2, 0x0003, 0x0821, 0x0001, 0xb2d8,
-	0x0000, 0x0100, 0x0010, 0xff88, 0x0010, 0xb389, 0x0005, 0x008c,
-	0x0010, 0x0880, 0x0015, 0x008d, 0x0000, 0x0008, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x000e, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb009, 0x001b, 0x87e6, 0x0010, 0xb08f,
-	0x0000, 0xb590, 0x0010, 0x1391, 0x0000, 0x1a30, 0x0005, 0x0031,
-	0x0000, 0x000d, 0x0015, 0x0033, 0x0000, 0xb021, 0x001b, 0x87ef,
-	0x0003, 0x97f0, 0x0010, 0xb392, 0x0010, 0xb293, 0x0003, 0x97f3,
-	0x0000, 0xb1a1, 0x0010, 0xb0a2, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x1388, 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0xb211, 0x001b, 0x87fd, 0x0000, 0xb3ff, 0x0001, 0xb080,
-	0x0000, 0xffb3, 0x001b, 0x2804, 0x0002, 0xb200, 0x0003, 0x0805,
-	0x0010, 0xb2ff, 0x0011, 0xb180, 0x0010, 0xffb2, 0x0011, 0x1388,
-	0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xb212,
-	0x000b, 0x880c, 0x0015, 0x00b1, 0x0000, 0x0092, 0x0002, 0x104c,
-	0x0003, 0x181f, 0x0011, 0xc2e8, 0x0010, 0x000c, 0x000b, 0x1817,
-	0x0015, 0x00ff, 0x0000, 0x0800, 0x0013, 0x081f, 0x0011, 0xc2e8,
-	0x0000, 0x0020, 0x000b, 0x181d, 0x0015, 0x00ff, 0x0010, 0x1800,
-	0x0013, 0x081f, 0x0015, 0x00ff, 0x0000, 0x1000, 0x0011, 0xb1d0,
-	0x0010, 0xffb1, 0x0015, 0x009a, 0x0010, 0x0036, 0x0005, 0x009b,
-	0x0000, 0x95d5, 0x0012, 0xd041, 0x001b, 0x1825, 0x0015, 0x00d1,
-	0x0010, 0x0202, 0x0013, 0x9829, 0x0012, 0x104e, 0x0013, 0x182e,
-	0x0012, 0xb12f, 0x0010, 0xffb1, 0x0000, 0xb175, 0x0013, 0x982f,
-	0x0015, 0x00d1, 0x0000, 0x0200, 0x0001, 0x19c8, 0x0010, 0xfff0,
-	0x001b, 0x1838, 0x0015, 0x00b1, 0x0010, 0x07d0, 0x0003, 0x083a,
-	0x0015, 0x00b1, 0x0000, 0x1b58, 0x0005, 0x00b0, 0x0010, 0x0009,
-	0x0015, 0x0030, 0x0000, 0x0400, 0x0001, 0xbd88, 0x0000, 0x000b,
-	0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xb012, 0x001b, 0x8843,
-	0x0003, 0x0703, 0x0015, 0x0030, 0x0000, 0x0400, 0x0000, 0xa4ff,
-	0x0003, 0x6893, 0x0011, 0xffa8, 0x0010, 0x0005, 0x000b, 0x2893,
-	0x0005, 0x0031, 0x0001, 0x1b6c, 0x0015, 0x0033, 0x0010, 0xb211,
-	0x000b, 0x8850, 0x0002, 0xb200, 0x0010, 0xffb2, 0x0005, 0x0031,
-	0x0001, 0x1b6c, 0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8857,
-	0x0015, 0x000f, 0x0000, 0x0001, 0x0000, 0x1213, 0x0005, 0x0010,
-	0x0000, 0x8000, 0x0015, 0x00a3, 0x0000, 0x0200, 0x0000, 0xc697,
-	0x0005, 0x0046, 0x0000, 0x0002, 0x0015, 0x00a5, 0x0000, 0x0010,
-	0x0011, 0xc4d8, 0x0000, 0x3200, 0x0010, 0xff88, 0x0000, 0xc589,
-	0x0010, 0xc48a, 0x0010, 0xc58b, 0x0010, 0xc08e, 0x0005, 0x008c,
-	0x0010, 0xe109, 0x0010, 0xc08d, 0x0015, 0x0090, 0x0001, 0x1b55,
-	0x0005, 0x0091, 0x0010, 0xffff, 0x0000, 0xb292, 0x0000, 0xb393,
-	0x0015, 0x009a, 0x0010, 0x0056, 0x0005, 0x009b, 0x0010, 0x95f5,
-	0x0012, 0xd042, 0x0003, 0x1886, 0x0005, 0x00b0, 0x0010, 0x8080,
-	0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xb00a, 0x000b, 0x8881, 0x0015, 0x00b8, 0x0010, 0x000c,
-	0x0014, 0x0925, 0x0003, 0x0888, 0x0005, 0x0075, 0x0010, 0x8092,
-	0x0015, 0x00b1, 0x0010, 0x07d0, 0x0005, 0x00b0, 0x0010, 0x0009,
-	0x0001, 0xbd88, 0x0000, 0x000b, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0000, 0xb012, 0x001b, 0x8891, 0x0003, 0x0703, 0x0015, 0x00d1,
-	0x0000, 0x0400, 0x0001, 0x1288, 0x0010, 0x0003, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0000, 0xb009, 0x000b, 0x889a, 0x0001, 0x1288,
-	0x0010, 0x0003, 0x0000, 0xff31, 0x0015, 0x0033, 0x0010, 0xc00a,
-	0x000b, 0x88a0, 0x0010, 0xb0fe, 0x0003, 0x68a5, 0x0000, 0xb012,
-	0x0003, 0x0703, 0x0010, 0xc012, 0x0010, 0xc011, 0x0003, 0x0703,
-	0x0000, 0xba30, 0x0005, 0x0031, 0x0010, 0x0021, 0x0015, 0x0033,
-	0x0010, 0xb019, 0x001b, 0x88ad, 0x0002, 0xb200, 0x0011, 0xffc8,
-	0x0010, 0x00ff, 0x0010, 0xffb2, 0x0010, 0xb2b7, 0x0005, 0x0031,
-	0x0000, 0x0023, 0x0015, 0x0033, 0x0010, 0xb20a, 0x000b, 0x88b7,
-	0x0017, 0x4000, 0x0000, 0xba30, 0x0005, 0x0031, 0x0000, 0x0023,
-	0x0015, 0x0033, 0x0010, 0xb409, 0x000b, 0x88be, 0x0002, 0xb400,
-	0x0011, 0xffc8, 0x0010, 0x00ff, 0x0010, 0xffb4, 0x0010, 0xb4b7,
-	0x0005, 0x0031, 0x0000, 0x0023, 0x0015, 0x0033, 0x0010, 0xb40a,
-	0x001b, 0x88c8, 0x0017, 0x4000, 0x0000, 0xba30, 0x0001, 0xc7c8,
-	0x0000, 0x0020, 0x001b, 0x18d6, 0x0005, 0x0031, 0x0010, 0x0028,
-	0x0015, 0x0033, 0x0010, 0xb209, 0x000b, 0x88d2, 0x0011, 0xb2c8,
-	0x0000, 0xff80, 0x0003, 0x18d9, 0x0010, 0xc4b0, 0x0010, 0xc5b1,
-	0x0003, 0x08db, 0x0010, 0xc6b1, 0x0000, 0xc0b0, 0x0005, 0x0031,
-	0x0000, 0x0004, 0x0015, 0x0033, 0x0010, 0xb211, 0x001b, 0x88df,
-	0x0017, 0x4000, 0x0015, 0x00b8, 0x0010, 0x0009, 0x0015, 0x003a,
-	0x0010, 0x0707, 0x0014, 0x0925, 0x0013, 0x002d, 0x0015, 0x00b8,
-	0x0010, 0x0009, 0x0015, 0x003a, 0x0010, 0x0707, 0x0003, 0x0925,
-	0x0004, 0x011c, 0x0015, 0x0030, 0x0000, 0x0400, 0x0011, 0x0d88,
-	0x0000, 0x0004, 0x0000, 0xff31, 0x0015, 0x0033, 0x0000, 0xba09,
-	0x001b, 0x88f4, 0x0004, 0x08a8, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x0d88, 0x0000, 0x0010, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0xb20a, 0x001b, 0x88fd, 0x0015, 0x0030, 0x0000, 0x0400,
-	0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0x0309, 0x001b, 0x8905, 0x0002, 0x0327, 0x0010, 0xffb2,
-	0x0011, 0x0d88, 0x0010, 0x0011, 0x0000, 0xff31, 0x0015, 0x0033,
-	0x0010, 0xb20a, 0x000b, 0x890d, 0x0015, 0x00b8, 0x0010, 0x0006,
-	0x0003, 0x0925, 0x0014, 0x012e, 0x0004, 0x08a8, 0x0015, 0x0030,
-	0x0000, 0x0400, 0x0011, 0x1388, 0x0000, 0x0010, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0010, 0xb20a, 0x000b, 0x891a, 0x0012, 0x1027,
-	0x0010, 0xffb2, 0x0011, 0x1388, 0x0010, 0x0011, 0x0000, 0xff31,
-	0x0015, 0x0033, 0x0010, 0xb20a, 0x001b, 0x8922, 0x0015, 0x00b8,
-	0x0000, 0x0007, 0x0013, 0x4925, 0x0000, 0xb838, 0x0017, 0x4000,
-	0x9a8c, 0xaf3d
-};
-unsigned short xseqipx_code_length01 = 0x1252;
diff --git a/drivers/scsi/qla2xxx/ql2400.c b/drivers/scsi/qla2xxx/ql2400.c
deleted file mode 100644
index 77914fc..0000000
--- a/drivers/scsi/qla2xxx/ql2400.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-#include "qla_def.h"
-
-static char qla_driver_name[] = "qla2400";
-
-extern uint32_t fw2400_version_str[];
-extern uint32_t fw2400_addr01;
-extern uint32_t fw2400_code01[];
-extern uint32_t fw2400_length01;
-extern uint32_t fw2400_addr02;
-extern uint32_t fw2400_code02[];
-extern uint32_t fw2400_length02;
-
-static struct qla_fw_info qla_fw_tbl[] = {
-	{
-		.addressing	= FW_INFO_ADDR_EXTENDED,
-		.fwcode		= (unsigned short *)&fw2400_code01[0],
-		.fwlen		= (unsigned short *)&fw2400_length01,
-		.lfwstart	= (unsigned long *)&fw2400_addr01,
-	},
-	{
-		.addressing	= FW_INFO_ADDR_EXTENDED,
-		.fwcode		= (unsigned short *)&fw2400_code02[0],
-		.fwlen		= (unsigned short *)&fw2400_length02,
-		.lfwstart	= (unsigned long *)&fw2400_addr02,
-	},
-	{ FW_INFO_ADDR_NOMORE, },
-};
-
-static struct qla_board_info qla_board_tbl[] = {
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP2422",
-		.fw_info	= qla_fw_tbl,
-		.fw_fname	= "ql2400_fw.bin",
-	},
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP2432",
-		.fw_info	= qla_fw_tbl,
-		.fw_fname	= "ql2400_fw.bin",
-	},
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP5422",
-		.fw_info	= qla_fw_tbl,
-		.fw_fname	= "ql2400_fw.bin",
-	},
-	{
-		.drv_name	= qla_driver_name,
-		.isp_name	= "ISP5432",
-		.fw_info	= qla_fw_tbl,
-		.fw_fname	= "ql2400_fw.bin",
-	},
-};
-
-static struct pci_device_id qla24xx_pci_tbl[] = {
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2422,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[0],
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP2432,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[1],
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP5422,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[2],
-	},
-	{
-		.vendor		= PCI_VENDOR_ID_QLOGIC,
-		.device		= PCI_DEVICE_ID_QLOGIC_ISP5432,
-		.subvendor	= PCI_ANY_ID,
-		.subdevice	= PCI_ANY_ID,
-		.driver_data	= (unsigned long)&qla_board_tbl[3],
-	},
-
-	{0, 0},
-};
-MODULE_DEVICE_TABLE(pci, qla24xx_pci_tbl);
-
-static int __devinit
-qla24xx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	return qla2x00_probe_one(pdev,
-	    (struct qla_board_info *)id->driver_data);
-}
-
-static void __devexit
-qla24xx_remove_one(struct pci_dev *pdev)
-{
-	qla2x00_remove_one(pdev);
-}
-
-static struct pci_driver qla24xx_pci_driver = {
-	.name		= "qla2400",
-	.id_table	= qla24xx_pci_tbl,
-	.probe		= qla24xx_probe_one,
-	.remove		= __devexit_p(qla24xx_remove_one),
-};
-
-static int __init
-qla24xx_init(void)
-{
-	return pci_module_init(&qla24xx_pci_driver);
-}
-
-static void __exit
-qla24xx_exit(void)
-{
-	pci_unregister_driver(&qla24xx_pci_driver);
-}
-
-module_init(qla24xx_init);
-module_exit(qla24xx_exit);
-
-MODULE_AUTHOR("QLogic Corporation");
-MODULE_DESCRIPTION("QLogic ISP24xx FC-SCSI Host Bus Adapter driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(QLA2XXX_VERSION);
diff --git a/drivers/scsi/qla2xxx/ql2400_fw.c b/drivers/scsi/qla2xxx/ql2400_fw.c
deleted file mode 100644
index 282b2d3..0000000
--- a/drivers/scsi/qla2xxx/ql2400_fw.c
+++ /dev/null
@@ -1,12346 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-#include <linux/types.h>
-
-/*
- *	Firmware Version 4.00.18 (14:53 Jan 30, 2006)
- */
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_version = 4*1024+0;
-#else
-uint32_t risc_code_version = 4*1024+0;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_version_str[] = {4, 0,18};
-#else
-uint32_t firmware_version[] = {4, 0,18};
-#endif
-
-#ifdef UNIQUE_FW_NAME
-#define fw2400_VERSION_STRING "4.00.18"
-#else
-#define FW_VERSION_STRING "4.00.18"
-#endif
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_addr01 = 0x00100000 ;
-#else
-uint32_t risc_code_addr01 = 0x00100000 ;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_code01[] = {
-#else
-uint32_t risc_code01[] = {
-#endif
-	0x0401f17c, 0x0010d000, 0x00100000, 0x0000a971,
-	0x00000004, 0x00000000, 0x00000012, 0x00000002,
-	0x00000003, 0x00000000, 0x20434f50, 0x59524947,
-	0x48542032, 0x30303520, 0x514c4f47, 0x49432043,
-	0x4f52504f, 0x52415449, 0x4f4e2020, 0x20495350,
-	0x32347878, 0x20466972, 0x6d776172, 0x65202020,
-	0x56657273, 0x696f6e20, 0x342e302e, 0x31382020,
-	0x20202024, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x42001800, 0x0010014f, 0x42002000, 0x0010b6fd,
-	0x500c0800, 0x800c1800, 0x500c1000, 0x800c1800,
-	0x54042000, 0x80102000, 0x80040800, 0x80081040,
-	0x040207fc, 0x500c0800, 0x800409c0, 0x040207f6,
-	0x44002000, 0x80102000, 0x40100000, 0x44040000,
-	0x80000000, 0x44080000, 0x80000000, 0x440c0000,
-	0x80000000, 0x44100000, 0x80000000, 0x44140000,
-	0x80000000, 0x44180000, 0x80000000, 0x441c0000,
-	0x80000000, 0x44200000, 0x80000000, 0x44240000,
-	0x80000000, 0x44280000, 0x80000000, 0x442c0000,
-	0x80000000, 0x44300000, 0x80000000, 0x44340000,
-	0x80000000, 0x44380000, 0x80000000, 0x443c0000,
-	0x80000000, 0x44400000, 0x80000000, 0x44440000,
-	0x80000000, 0x44480000, 0x80000000, 0x444c0000,
-	0x80000000, 0x44500000, 0x80000000, 0x44540000,
-	0x80000000, 0x44580000, 0x80000000, 0x445c0000,
-	0x80000000, 0x44600000, 0x80000000, 0x44640000,
-	0x80000000, 0x44680000, 0x80000000, 0x446c0000,
-	0x80000000, 0x44700000, 0x80000000, 0x44740000,
-	0x80000000, 0x44780000, 0x80000000, 0x447c0000,
-	0x80000000, 0x44800000, 0x80000000, 0x44840000,
-	0x80000000, 0x44880000, 0x80000000, 0x448c0000,
-	0x80000000, 0x44900000, 0x80000000, 0x44940000,
-	0x80000000, 0x44980000, 0x80000000, 0x449c0000,
-	0x80000000, 0x44a00000, 0x80000000, 0x44a40000,
-	0x80000000, 0x44a80000, 0x80000000, 0x44ac0000,
-	0x80000000, 0x44b00000, 0x80000000, 0x44b40000,
-	0x80000000, 0x44b80000, 0x80000000, 0x44bc0000,
-	0x80000000, 0x44c00000, 0x80000000, 0x44c40000,
-	0x80000000, 0x44c80000, 0x80000000, 0x44cc0000,
-	0x80000000, 0x44d00000, 0x80000000, 0x44d80000,
-	0x80000000, 0x44d40000, 0x80000000, 0x44dc0000,
-	0x80000000, 0x44e00000, 0x80000000, 0x44e40000,
-	0x80000000, 0x44e80000, 0x80000000, 0x44ec0000,
-	0x80000000, 0x44f00000, 0x80000000, 0x44f40000,
-	0x80000000, 0x44f80000, 0x80000000, 0x44fc0000,
-	0x80000000, 0x45000000, 0x80000000, 0x45040000,
-	0x80000000, 0x45080000, 0x80000000, 0x450c0000,
-	0x80000000, 0x45100000, 0x80000000, 0x45140000,
-	0x80000000, 0x45180000, 0x80000000, 0x451c0000,
-	0x80000000, 0x45200000, 0x80000000, 0x45240000,
-	0x80000000, 0x45280000, 0x80000000, 0x452c0000,
-	0x80000000, 0x45300000, 0x80000000, 0x45340000,
-	0x80000000, 0x45380000, 0x80000000, 0x453c0000,
-	0x80000000, 0x45400000, 0x80000000, 0x45440000,
-	0x80000000, 0x45480000, 0x80000000, 0x454c0000,
-	0x80000000, 0x45500000, 0x80000000, 0x45540000,
-	0x80000000, 0x45580000, 0x80000000, 0x455c0000,
-	0x80000000, 0x45600000, 0x80000000, 0x45640000,
-	0x80000000, 0x45680000, 0x80000000, 0x456c0000,
-	0x80000000, 0x45700000, 0x80000000, 0x45740000,
-	0x80000000, 0x45780000, 0x80000000, 0x457c0000,
-	0x80000000, 0x45800000, 0x80000000, 0x45840000,
-	0x80000000, 0x45880000, 0x80000000, 0x458c0000,
-	0x80000000, 0x45900000, 0x80000000, 0x45940000,
-	0x80000000, 0x45980000, 0x80000000, 0x459c0000,
-	0x80000000, 0x45a00000, 0x80000000, 0x45a40000,
-	0x80000000, 0x45a80000, 0x80000000, 0x45ac0000,
-	0x80000000, 0x45b00000, 0x80000000, 0x45b40000,
-	0x80000000, 0x45b80000, 0x80000000, 0x45bc0000,
-	0x80000000, 0x45c00000, 0x80000000, 0x45c40000,
-	0x80000000, 0x45c80000, 0x80000000, 0x45cc0000,
-	0x80000000, 0x45d00000, 0x80000000, 0x45d40000,
-	0x80000000, 0x45d80000, 0x80000000, 0x45dc0000,
-	0x80000000, 0x45e00000, 0x80000000, 0x45e40000,
-	0x80000000, 0x45e80000, 0x80000000, 0x45ec0000,
-	0x80000000, 0x45f00000, 0x80000000, 0x45f40000,
-	0x80000000, 0x45f80000, 0x80000000, 0x45fc0000,
-	0x4a03c020, 0x00004000, 0x4a03c011, 0x40000010,
-	0x04006000, 0x4203e000, 0x40000000, 0x59e00017,
-	0x8c000508, 0x04000003, 0x4a03c017, 0x00000000,
-	0x4203e000, 0x30000001, 0x0401f000, 0x0000bf00,
-	0x00000080, 0x0000bfe0, 0x00000020, 0x0000ff00,
-	0x00000080, 0x0000ffd0, 0x00000030, 0x00007100,
-	0x00000010, 0x00007200, 0x00000008, 0x00007209,
-	0x00000007, 0x00007300, 0x00000008, 0x00007309,
-	0x00000007, 0x00007400, 0x00000008, 0x00007409,
-	0x00000007, 0x00007600, 0x000000b0, 0x00007700,
-	0x00000040, 0x00003000, 0x00000070, 0x00004000,
-	0x000000c0, 0x00006000, 0x00000050, 0x00006100,
-	0x00000010, 0x00006130, 0x00000010, 0x00006150,
-	0x00000010, 0x00006170, 0x00000010, 0x00006190,
-	0x00000010, 0x000061b0, 0x00000010, 0x00000000,
-	0x42000000, 0x00000100, 0x4202f000, 0x00000000,
-	0x42000800, 0x00021f00, 0x45780800, 0x80040800,
-	0x80000040, 0x040207fd, 0x4203f000, 0x00021fff,
-	0x40000000, 0x4203e000, 0x90000100, 0x40000000,
-	0x0201f800, 0x00100743, 0x42000000, 0x00001000,
-	0x50000000, 0x82000480, 0x24320002, 0x04020015,
-	0x42000800, 0x00000064, 0x80040840, 0x04000007,
-	0x4a030000, 0x00000001, 0x40000000, 0x59800000,
-	0x8c000500, 0x040007f9, 0x04000008, 0x42000800,
-	0x00007a17, 0x50040000, 0x8c00050e, 0x04020003,
-	0x8400054e, 0x44000800, 0x4a030000, 0x00000000,
-	0x4a03c020, 0x00000004, 0x4203e000, 0x6000000f,
-	0x59e00023, 0x8c000500, 0x04020039, 0x42000000,
-	0x00100001, 0x50000800, 0x82040c00, 0x00000004,
-	0x58042003, 0x42001000, 0xffffffff, 0x0201f800,
-	0x0010073a, 0x0402004e, 0x58042003, 0x42001000,
-	0xffffffff, 0x0201f800, 0x0010073a, 0x04020048,
-	0x58042003, 0x42001000, 0x00ffffff, 0x0201f800,
-	0x0010073a, 0x04020042, 0x58042003, 0x42001000,
-	0x00ffffff, 0x0201f800, 0x0010073a, 0x0402003c,
-	0x42000000, 0x00100001, 0x5000a000, 0x8250a400,
-	0x00000004, 0x4200a800, 0x00020000, 0x5850b003,
-	0x0201f800, 0x0010a93e, 0x8250a400, 0x00000005,
-	0x4a0370e8, 0x00000003, 0x4200a800, 0x0000c000,
-	0x5850b003, 0x0201f800, 0x0010a93e, 0x4a0378e8,
-	0x00000003, 0x4200a800, 0x00008000, 0x5850b003,
-	0x0201f800, 0x0010a93e, 0x0401f02b, 0x42000800,
-	0x00020000, 0x58042003, 0x42001000, 0xffffffff,
-	0x0201f800, 0x0010073a, 0x04020019, 0x4a0370e8,
-	0x00000003, 0x42000800, 0x0000c000, 0x58042003,
-	0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff,
-	0x0201f800, 0x0010073a, 0x0402000d, 0x4a0378e8,
-	0x00000003, 0x42000800, 0x00008000, 0x58042003,
-	0x82102500, 0x00ffffff, 0x42001000, 0x00ffffff,
-	0x0201f800, 0x0010073a, 0x0400000b, 0x4a03c020,
-	0x00004010, 0x4a03c011, 0x40100011, 0x04006000,
-	0x4203e000, 0x40000000, 0x4203e000, 0x30000001,
-	0x0401f000, 0x0201f800, 0x001007d7, 0x42001000,
-	0x0010a971, 0x40080000, 0x80140480, 0x82001d00,
-	0xffffff00, 0x04020003, 0x40001800, 0x0401f003,
-	0x42001800, 0x000000ff, 0x480bc840, 0x480fc842,
-	0x04011000, 0x400c0000, 0x80081400, 0x40140000,
-	0x80080580, 0x040207f0, 0x4817500d, 0x45782800,
-	0x59c40000, 0x82000500, 0xffff0000, 0x80000120,
-	0x82000580, 0x00002422, 0x04020005, 0x59a8006f,
-	0x84000540, 0x4803506f, 0x0401f00a, 0x59e00003,
-	0x82000500, 0x00030000, 0x82000580, 0x00010000,
-	0x04020004, 0x59a8006f, 0x84000542, 0x4803506f,
-	0x42000800, 0x00000040, 0x59a8006f, 0x8c000502,
-	0x0402000e, 0x42000800, 0x00001000, 0x82141480,
-	0x0017ffff, 0x04021009, 0x80040902, 0x82141480,
-	0x0013ffff, 0x04021005, 0x80040902, 0x82141480,
-	0x0011ffff, 0x04001bc8, 0x4807500e, 0x42001000,
-	0x00000024, 0x0201f800, 0x001063cf, 0x82040c00,
-	0x0010cfc0, 0x4807500b, 0x4a03c810, 0x00100000,
-	0x4a03c811, 0x0010a971, 0x4a03c829, 0x00000004,
-	0x59e40001, 0x82000540, 0x0003001d, 0x4803c801,
-	0x4a03c014, 0x001c001c, 0x42001000, 0x0000001c,
-	0x0201f800, 0x00100728, 0x4202c000, 0x0010cfc0,
-	0x59aab00b, 0x59aaa00b, 0x59aaa80b, 0x59aac80e,
-	0x49675069, 0x59a8000b, 0x4803500c, 0x0201f800,
-	0x001006a3, 0x0201f800, 0x0010768a, 0x0201f800,
-	0x00100804, 0x0201f800, 0x0010084d, 0x0201f800,
-	0x00101a60, 0x0201f800, 0x001013a4, 0x0201f800,
-	0x001009b6, 0x0201f800, 0x001013a4, 0x0201f800,
-	0x00100f9a, 0x0201f800, 0x0010640f, 0x0401fb54,
-	0x0201f800, 0x00101fb5, 0x0201f800, 0x0010508b,
-	0x0201f800, 0x00104b36, 0x0201f800, 0x00105ecd,
-	0x0201f800, 0x00105c61, 0x0201f800, 0x0010143d,
-	0x0201f800, 0x001012bf, 0x4203e000, 0xf0000001,
-	0x4a035070, 0x00000014, 0x4a035071, 0x0000000b,
-	0x4a035072, 0x00000001, 0x4a035073, 0x00000000,
-	0x42000000, 0x00001000, 0x50000000, 0x82000480,
-	0x24220001, 0x0400004a, 0x59e00002, 0x8c00051e,
-	0x42000000, 0x7ffe00fe, 0x04000003, 0x42000000,
-	0x7ffe01fe, 0x50000800, 0x48075058, 0x80040920,
-	0x82040580, 0x0000013e, 0x0402000b, 0x59a8006f,
-	0x84000548, 0x4803506f, 0x4a035070, 0x00000055,
-	0x4a035071, 0x00000051, 0x4a035073, 0x0000000f,
-	0x0401f033, 0x82040580, 0x0000013f, 0x0402000b,
-	0x59a8006f, 0x8400054a, 0x4803506f, 0x4a035070,
-	0x00000055, 0x4a035071, 0x00000051, 0x4a035073,
-	0x0000000f, 0x0401f026, 0x59e00003, 0x82000500,
-	0x00030000, 0x82000580, 0x00000000, 0x04020020,
-	0x82040580, 0x00000147, 0x04000010, 0x82040580,
-	0x00000145, 0x0402001a, 0x59a8006f, 0x84000546,
-	0x4803506f, 0x4a035070, 0x00000033, 0x4a035071,
-	0x00000030, 0x4a035072, 0x00000020, 0x4a035073,
-	0x00000001, 0x0401f00c, 0x59a8006f, 0x84000544,
-	0x4803506f, 0x4a035070, 0x00000033, 0x4a035071,
-	0x00000030, 0x4a035072, 0x00000020, 0x4a035073,
-	0x00000001, 0x4a0378e4, 0x000c0000, 0x59a8006f,
-	0x8c000502, 0x04000004, 0x82000500, 0x00000030,
-	0x04000b25, 0x4a03c018, 0x0000000f, 0x4203e000,
-	0x20000511, 0x4203e000, 0x50010000, 0x4a03c020,
-	0x00000000, 0x04027013, 0x59e00020, 0x82000580,
-	0x00000002, 0x0402000f, 0x4a03c020, 0x00004000,
-	0x4a03c011, 0x40000010, 0x04006000, 0x4203e000,
-	0x40000000, 0x59e00017, 0x8c000508, 0x04000003,
-	0x4a03c017, 0x00000000, 0x4203e000, 0x30000001,
-	0x4202d800, 0x00000000, 0x4203e000, 0xb0600000,
-	0x59a80873, 0x4007f800, 0x0201f000, 0x00020004,
-	0x4df00000, 0x4203e000, 0x50000000, 0x416c0000,
-	0x82000c80, 0x00000008, 0x04021afb, 0x0c01f804,
-	0x5c03e000, 0x0201f000, 0x00020008, 0x00100328,
-	0x0010033b, 0x00100411, 0x00100327, 0x0010048c,
-	0x00100327, 0x00100327, 0x001005d0, 0x0401faee,
-	0x42000800, 0x0010b2a0, 0x5804001d, 0x4803c857,
-	0x8c000500, 0x0400000d, 0x84000500, 0x4800081d,
-	0x4202d800, 0x00000004, 0x0401fbe8, 0x49f3c857,
-	0x5c000800, 0x5c000000, 0x82000540, 0x00003e00,
-	0x4c000000, 0x4c040000, 0x1c01f000, 0x0401fbd2,
-	0x0201f800, 0x00104e0d, 0x04000010, 0x0201f800,
-	0x00104e23, 0x04020035, 0x59940023, 0x82000580,
-	0x0010401b, 0x04020004, 0x59940022, 0x800001c0,
-	0x0402002e, 0x59c40006, 0x82000540, 0x000000c0,
-	0x48038806, 0x0401f029, 0x0201f800, 0x00104d76,
-	0x836c0580, 0x00000001, 0x040200be, 0x59a80017,
-	0x82000580, 0x00000009, 0x040200ba, 0x497b5010,
-	0x4a038893, 0x00000001, 0x42001000, 0x000000f0,
-	0x0201f800, 0x001019aa, 0x0201f800, 0x00104e1b,
-	0x59c41006, 0x04020006, 0x82081540, 0x000000f1,
-	0x82081500, 0xbbffffff, 0x0401f003, 0x82081540,
-	0x440000f1, 0x480b8806, 0x0201f800, 0x00105de2,
-	0x0201f800, 0x001069b8, 0x42000000, 0x0010b638,
-	0x0201f800, 0x0010a86e, 0x42001000, 0x00008030,
-	0x497b5013, 0x0401f037, 0x0201f800, 0x00103951,
-	0x59c400a4, 0x82000500, 0x0000000f, 0x82000480,
-	0x00000007, 0x04021093, 0x0201f800, 0x00105de2,
-	0x59c400a3, 0x82000500, 0xffefffff, 0x480388a3,
-	0x59a8004b, 0x800001c0, 0x04020004, 0x0201f800,
-	0x00103f53, 0x0401f087, 0x59a80015, 0x84000546,
-	0x48035015, 0x0201f800, 0x00104e13, 0x59c41006,
-	0x04020006, 0x82081540, 0x44000001, 0x82081500,
-	0xffffff0f, 0x0401f003, 0x82081540, 0x440000f1,
-	0x480b8806, 0x497b9005, 0x4a038802, 0x0000ffff,
-	0x4a0378e4, 0x00003000, 0x4a0378e4, 0x000c0000,
-	0x42000000, 0x0010b60a, 0x0201f800, 0x0010a86e,
-	0x59a81010, 0x42000800, 0x00000003, 0x0201f800,
-	0x001069af, 0x42001000, 0x00008010, 0x59a8180a,
-	0x0201f800, 0x00103857, 0x0201f800, 0x00101886,
-	0x59a80805, 0x82040d00, 0xffffffdf, 0x48075005,
-	0x0201f800, 0x0010468b, 0x0201f800, 0x00104e0d,
-	0x0400000a, 0x0201f800, 0x00103f58, 0x04000007,
-	0x4a035013, 0x00000001, 0x497b5021, 0x0201f800,
-	0x00103a9f, 0x0401f04f, 0x0201f800, 0x0010473b,
-	0x04000005, 0x59c41002, 0x8408150c, 0x480b8802,
-	0x0401f012, 0x0201f800, 0x00104e0d, 0x04020006,
-	0x59a8001d, 0x80000540, 0x02000800, 0x001090d5,
-	0x0401f00a, 0x0201f800, 0x001090d5, 0x59a80026,
-	0x8c000506, 0x04020005, 0x59a8001d, 0x80000540,
-	0x02020800, 0x00104075, 0x497b5028, 0x497b5027,
-	0x497b5018, 0x0201f800, 0x00104e0d, 0x59a81026,
-	0x0402000a, 0x0201f800, 0x00101694, 0x80001580,
-	0x59a8002a, 0x82000500, 0xffff0000, 0x80040d40,
-	0x4807502a, 0x0401f005, 0x59a8002a, 0x82000500,
-	0xffff0000, 0x4803502a, 0x599c0017, 0x8c00050a,
-	0x04000002, 0x84081544, 0x480b5026, 0x0201f800,
-	0x00104e0d, 0x04000004, 0x0201f800, 0x00101694,
-	0x48078880, 0x42001000, 0x00000005, 0x0201f800,
-	0x00106e07, 0x497b5028, 0x497b501b, 0x4a03501c,
-	0x0000ffff, 0x4a0378e4, 0x000000c0, 0x4202d800,
-	0x00000002, 0x0201f800, 0x00104e0d, 0x04000007,
-	0x59a80026, 0x82000500, 0x0000000c, 0x82000580,
-	0x00000004, 0x04000003, 0x0201f800, 0x00101bf0,
-	0x1c01f000, 0x59a8001c, 0x82000580, 0x0000ffff,
-	0x04000004, 0x0201f800, 0x00101bf0, 0x0401f074,
-	0x59a80026, 0x8c00050a, 0x04020003, 0x8c000506,
-	0x0400001c, 0x8c000500, 0x0400001a, 0x4a038802,
-	0x0000ffbf, 0x8c000502, 0x04000016, 0x599c0018,
-	0x8c000516, 0x04020010, 0x59a80027, 0x82000580,
-	0x0000ffff, 0x0400000c, 0x0201f800, 0x00101d45,
-	0x59a80026, 0x8c000504, 0x0402005d, 0x42001000,
-	0x00000003, 0x417a5800, 0x0201f800, 0x00101d6a,
-	0x0401f057, 0x59a80028, 0x80000540, 0x04020054,
-	0x59a80026, 0x8c000508, 0x04020005, 0x59a8001b,
-	0x80000540, 0x0402004e, 0x0401f003, 0x8c000516,
-	0x0400004b, 0x0201f800, 0x0010473b, 0x04020048,
-	0x599c0018, 0x8c000516, 0x04020004, 0x0201f800,
-	0x00104abe, 0x04020042, 0x599c0017, 0x8c00050a,
-	0x0400000d, 0x4200b000, 0x000007f0, 0x417a8800,
-	0x0201f800, 0x00020267, 0x04020004, 0x59340200,
-	0x8c00051a, 0x04020036, 0x81468800, 0x8058b040,
-	0x040207f8, 0x4a038802, 0x0000ffff, 0x42001800,
-	0x0010b2e7, 0x0401fb98, 0x42001800, 0x0010b2f4,
-	0x0401fb95, 0x59a80005, 0x84000502, 0x48035005,
-	0x4a0378e4, 0x00000080, 0x4202d800, 0x00000003,
-	0x4a03501c, 0x0000ffff, 0x0401fa8b, 0x80000580,
-	0x0201f800, 0x001015fa, 0x599c0018, 0x8c000516,
-	0x04000004, 0x0201f800, 0x00103929, 0x0401f009,
-	0x42001800, 0x0000ffff, 0x42002000, 0x00000006,
-	0x42003000, 0x00000000, 0x0201f800, 0x001038c7,
-	0x0201f800, 0x00104e23, 0x0400000b, 0x59c40006,
-	0x0201f800, 0x00104e0d, 0x04000004, 0x82000500,
-	0xffffff0f, 0x0401f003, 0x82000500, 0xfbffffff,
-	0x48038806, 0x0201f800, 0x00106c8a, 0x1c01f000,
-	0x4c040000, 0x4c080000, 0x4c100000, 0x59a8003e,
-	0x82000c80, 0x00000004, 0x04021983, 0x0c01f805,
-	0x5c002000, 0x5c001000, 0x5c000800, 0x1c01f000,
-	0x0010049c, 0x00100527, 0x00100553, 0x001005b4,
-	0x42000000, 0x00000001, 0x0201f800, 0x001015fa,
-	0x0201f800, 0x00105de2, 0x59c408a3, 0x82040d00,
-	0xfffffff7, 0x480788a3, 0x0201f800, 0x00104e13,
-	0x0400000e, 0x0201f800, 0x00104e23, 0x0400000b,
-	0x0201f800, 0x00104e1b, 0x04020967, 0x59c400a3,
-	0x84000532, 0x84000570, 0x480388a3, 0x4a038808,
-	0x00000008, 0x0401f013, 0x59c400a3, 0x84000530,
-	0x82000500, 0xbf7fffff, 0x480388a3, 0x42000800,
-	0x000000f8, 0x0201f800, 0x00104030, 0x59c400a3,
-	0x82000540, 0x00018000, 0x8400051c, 0x480388a3,
-	0x82000500, 0xfffeffff, 0x480388a3, 0x497b8808,
-	0x59c40006, 0x82000500, 0xfbffff0e, 0x48038806,
-	0x497b2822, 0x497b2823, 0x42000800, 0x000001f4,
-	0x42001000, 0x001005ce, 0x0201f800, 0x00105cbc,
-	0x59c40805, 0x42001000, 0x00000001, 0x0201f800,
-	0x001019aa, 0x0201f800, 0x001016ac, 0x0402000a,
-	0x42000000, 0x00000001, 0x0201f800, 0x001018fa,
-	0x42000000, 0x00000001, 0x0201f800, 0x00101892,
-	0x0401f022, 0x0201f800, 0x001016b3, 0x04020008,
-	0x41780000, 0x0201f800, 0x001018fa, 0x41780000,
-	0x0201f800, 0x00101892, 0x0401f018, 0x0201f800,
-	0x001016ba, 0x0402000a, 0x42000000, 0x00000002,
-	0x0201f800, 0x001018fa, 0x42000000, 0x00000002,
-	0x0201f800, 0x00101892, 0x0401f00c, 0x0201f800,
-	0x001016c1, 0x04020918, 0x59a80049, 0x800001c0,
-	0x04000006, 0x0201f800, 0x001016c7, 0x4a03503e,
-	0x00000001, 0x0401f021, 0x0201f800, 0x00101994,
-	0x4a03503e, 0x00000001, 0x0201f800, 0x00104e13,
-	0x0400000c, 0x0201f800, 0x00104e23, 0x04000009,
-	0x0201f800, 0x00104e1b, 0x04020903, 0x4a035033,
-	0x00000001, 0x0201f800, 0x00104d76, 0x0401f00f,
-	0x59c400a4, 0x82000500, 0x0000000f, 0x82000580,
-	0x00000008, 0x04000003, 0x4a038805, 0x04000000,
-	0x59c400a3, 0x82000540, 0x0001c000, 0x480388a3,
-	0x84000520, 0x480388a3, 0x1c01f000, 0x0401f8a3,
-	0x04020004, 0x4a03503e, 0x00000003, 0x0401f027,
-	0x0201f800, 0x001016c1, 0x04020011, 0x59a80049,
-	0x800001c0, 0x0400000e, 0x0201f800, 0x001016c7,
-	0x59a80048, 0x8c00051e, 0x0400001c, 0x0201f800,
-	0x00104e1b, 0x04020009, 0x4a035033, 0x00000001,
-	0x0201f800, 0x00104d76, 0x0401f004, 0x0201f800,
-	0x00101941, 0x04020011, 0x0201f800, 0x00101886,
-	0x4a03503e, 0x00000002, 0x497b5049, 0x59c400a3,
-	0x84000520, 0x480388a3, 0x497b2822, 0x497b2823,
-	0x42000800, 0x0000002d, 0x42001000, 0x001005ce,
-	0x0201f800, 0x00105cbc, 0x1c01f000, 0x0401f877,
-	0x04020004, 0x4a03503e, 0x00000003, 0x0401f05b,
-	0x4a038805, 0x000000f0, 0x0201f800, 0x00101941,
-	0x04020050, 0x0201f800, 0x00104e1b, 0x04000044,
-	0x59c400a4, 0x82000500, 0x0000000f, 0x82000580,
-	0x00000008, 0x04000020, 0x59c40005, 0x8c000534,
-	0x0402001d, 0x59940022, 0x82000580, 0x00000001,
-	0x04020046, 0x0201f800, 0x00104e23, 0x04020043,
-	0x4a038805, 0x000000f0, 0x0201f800, 0x00104e67,
-	0x4a035032, 0x0000aaaa, 0x4a035033, 0x00000000,
-	0x59c408a3, 0x82040d40, 0x00000008, 0x480788a3,
-	0x4202d800, 0x00000001, 0x4a03503e, 0x00000000,
-	0x4a038805, 0x00000001, 0x497b2822, 0x497b2823,
-	0x0401f01f, 0x0201f800, 0x00104e23, 0x04020007,
-	0x59a80032, 0x82000580, 0x0000aaaa, 0x04020003,
-	0x4a035010, 0x00ffffff, 0x497b5032, 0x59c40006,
-	0x82000540, 0x04000001, 0x48038806, 0x59a80805,
-	0x8c040d06, 0x04020005, 0x59c408a3, 0x82040d40,
-	0x00000008, 0x480788a3, 0x4202d800, 0x00000001,
-	0x4a03503e, 0x00000000, 0x4a038805, 0x00000001,
-	0x497b2822, 0x497b2823, 0x0401f010, 0x59c40005,
-	0x82000500, 0x000000c0, 0x0400000c, 0x59c40006,
-	0x82000540, 0x000000f1, 0x48038806, 0x0401f7ef,
-	0x0201f800, 0x001016c1, 0x04020004, 0x59a80049,
-	0x800001c0, 0x040207a4, 0x497b8885, 0x1c01f000,
-	0x4803c856, 0x42000000, 0x00000001, 0x0201f800,
-	0x001015fa, 0x4a03503e, 0x00000000, 0x0201f800,
-	0x001016c1, 0x0402000b, 0x59a80052, 0x800001c0,
-	0x04000004, 0x80000040, 0x48035052, 0x04020005,
-	0x4a035052, 0x0000000a, 0x4a035049, 0x00000001,
-	0x497b8885, 0x0401f0f6, 0x59940022, 0x59940823,
-	0x80040540, 0x1c01f000, 0x497b2823, 0x1c01f000,
-	0x4c080000, 0x42001000, 0x000000f0, 0x0201f800,
-	0x001019aa, 0x5c001000, 0x1c01f000, 0x4a03505c,
-	0x00000004, 0x4a03505d, 0x00000000, 0x4a03505e,
-	0x00000012, 0x4a03505f, 0x00000002, 0x4a035010,
-	0x00ffffff, 0x0201f800, 0x001090d5, 0x4a03502a,
-	0x20200000, 0x4a03502b, 0x88000200, 0x4a03502c,
-	0x00ff001f, 0x4a03502d, 0x000007d0, 0x4a03502e,
-	0x80000000, 0x4a03502f, 0x00000200, 0x4a035030,
-	0x00ff0000, 0x4a035031, 0x00010000, 0x4a03503a,
-	0x514c4f47, 0x4a03503b, 0x49432020, 0x1c01f000,
-	0x4d440000, 0x417a8800, 0x41780800, 0x0201f800,
-	0x00020267, 0x04020005, 0x0201f800, 0x00104836,
-	0x04020002, 0x80040800, 0x81468800, 0x83440580,
-	0x000007f0, 0x040207f6, 0x5c028800, 0x1c01f000,
-	0x4803c857, 0x5c000000, 0x4c000000, 0x4803c857,
-	0x0401f809, 0x485fc857, 0x4203e000, 0x50000000,
-	0x5c000000, 0x4d780000, 0x4200b800, 0x00008002,
-	0x0401f006, 0x485fc857, 0x4203e000, 0x50000000,
-	0x4200b800, 0x00008002, 0x04006000, 0x4c000000,
-	0x4c040000, 0x59bc00ea, 0x82000500, 0x00000007,
-	0x82000580, 0x00000001, 0x04020005, 0x42000800,
-	0x00000000, 0x0201f800, 0x001069a3, 0x5c000800,
-	0x4807c025, 0x80040920, 0x4807c026, 0x5c000000,
-	0x4803c023, 0x80000120, 0x4803c024, 0x5c000000,
-	0x4803c857, 0x4803c021, 0x80000120, 0x4803c022,
-	0x41f80000, 0x4803c027, 0x80000120, 0x4803c028,
-	0x42000000, 0x00001000, 0x50000000, 0x82000480,
-	0x24320001, 0x4803c857, 0x04001053, 0x42000800,
-	0x00000064, 0x80040840, 0x04000007, 0x4a030000,
-	0x00000001, 0x40000000, 0x59800000, 0x8c000500,
-	0x040007f9, 0x04000046, 0x42000800, 0x0010bfa2,
-	0x46000800, 0xfaceface, 0x80040800, 0x4c080000,
-	0x4c0c0000, 0x42001000, 0x00007a00, 0x58080013,
-	0x44000800, 0x80040800, 0x58080019, 0x44000800,
-	0x80040800, 0x5808001a, 0x44000800, 0x80040800,
-	0x5808001b, 0x44000800, 0x80040800, 0x5808001c,
-	0x44000800, 0x80040800, 0x5808001f, 0x44000800,
-	0x80040800, 0x42001000, 0x00007a40, 0x42001800,
-	0x0000000b, 0x50080000, 0x44000800, 0x80081000,
-	0x80040800, 0x800c1840, 0x040207fb, 0x42001800,
-	0x00000003, 0x42001000, 0x00007b00, 0x480c1003,
-	0x58080005, 0x44000800, 0x80040800, 0x800c1840,
-	0x040217fb, 0x42001000, 0x00007c00, 0x58080002,
-	0x44000800, 0x80040800, 0x58080003, 0x44000800,
-	0x80040800, 0x58080020, 0x44000800, 0x80040800,
-	0x58080021, 0x44000800, 0x80040800, 0x58080022,
-	0x44000800, 0x80040800, 0x58080023, 0x44000800,
-	0x80040800, 0x5c001800, 0x5c001000, 0x4a030000,
-	0x00000000, 0x485fc020, 0x905cb9c0, 0x825cbd40,
-	0x00000012, 0x485fc011, 0x4203e000, 0x40000000,
-	0x4202d800, 0x00000005, 0x59e00017, 0x8c000508,
-	0x04000003, 0x4a03c017, 0x00000002, 0x4203e000,
-	0x30000001, 0x0401f81f, 0x0401f7ff, 0x4a03c850,
-	0x0010bfbe, 0x4a03c851, 0x0010cfbd, 0x4a03c853,
-	0x00000800, 0x4a03c855, 0x0001eb5a, 0x59e40001,
-	0x82000540, 0x00003f00, 0x4803c801, 0x4a03b104,
-	0x70000002, 0x4a03a804, 0x70000002, 0x4a03b004,
-	0x70000002, 0x42000000, 0x0010b6eb, 0x49780001,
-	0x49780002, 0x1c01f000, 0x5c036000, 0x4db00000,
-	0x49b3c857, 0x4803c857, 0x1c01f000, 0x1c01f000,
-	0x59a8006b, 0x8c000530, 0x040207fe, 0x4c080000,
-	0x42001000, 0x00000004, 0x0401f862, 0x5c001000,
-	0x4201d000, 0x00028b0a, 0x0201f800, 0x00105dd2,
-	0x4c080000, 0x42001000, 0x00000008, 0x0401f859,
-	0x5c001000, 0x4201d000, 0x00028b0a, 0x0201f800,
-	0x00105dd2, 0x4c080000, 0x42001000, 0x00000010,
-	0x0401f850, 0x5c001000, 0x4201d000, 0x00028b0a,
-	0x0201f800, 0x00105dd2, 0x0401f7e2, 0x8c00050c,
-	0x59a8086b, 0x04020003, 0x84040d30, 0x0401f006,
-	0x84040d70, 0x4807506b, 0x42001000, 0x00000000,
-	0x0401f040, 0x4807506b, 0x836c0500, 0x00000007,
-	0x0c01f001, 0x00100727, 0x0010070d, 0x0010070d,
-	0x001006f5, 0x0010071a, 0x0010070d, 0x0010070d,
-	0x0010071a, 0x59a8006f, 0x8c000502, 0x04020013,
-	0x59c40801, 0x82040d00, 0x00018000, 0x82040580,
-	0x00010000, 0x0400000a, 0x82040580, 0x00008000,
-	0x04000004, 0x42001000, 0x42004000, 0x0401f006,
-	0x42001000, 0x22002000, 0x0401f003, 0x42001000,
-	0x12001000, 0x0401f025, 0x42001000, 0x00001004,
-	0x0401f022, 0x59a8006f, 0x8c000502, 0x04020008,
-	0x59a8006b, 0x8c000534, 0x04020004, 0x42001000,
-	0x74057005, 0x0401f819, 0x1c01f000, 0x42001000,
-	0x00002008, 0x0401f7fc, 0x59a8006b, 0x8c000534,
-	0x0402000a, 0x59a8006f, 0x8c000502, 0x04000004,
-	0x42001000, 0x24052005, 0x0401f00c, 0x42001000,
-	0x74057005, 0x0401f009, 0x1c01f000, 0x1c01f000,
-	0x82081500, 0x0000001c, 0x82081540, 0x001c0000,
-	0x480bc013, 0x1c01f000, 0x59a8006b, 0x8c000530,
-	0x04000002, 0x84081570, 0x480b506b, 0x8c000530,
-	0x04020005, 0x82081500, 0x00007000, 0x80081114,
-	0x0401fff0, 0x1c01f000, 0x41780000, 0x50041800,
-	0x800c0400, 0x80040800, 0x80102040, 0x040207fc,
-	0x80080500, 0x80000540, 0x1c01f000, 0x4202f000,
-	0x00000000, 0x41780000, 0x41780800, 0x41781000,
-	0x41781800, 0x41782000, 0x41782800, 0x41783000,
-	0x41783800, 0x41784000, 0x41784800, 0x41785000,
-	0x41785800, 0x41786000, 0x41786800, 0x41787000,
-	0x41787800, 0x41788000, 0x41788800, 0x41789000,
-	0x41789800, 0x4178a000, 0x4178a800, 0x4178b000,
-	0x4178b800, 0x4178c000, 0x4178c800, 0x4178d000,
-	0x4178d800, 0x4178e000, 0x4178e800, 0x4178f000,
-	0x4178f800, 0x41790000, 0x41790800, 0x41791000,
-	0x41791800, 0x41792000, 0x41792800, 0x41793000,
-	0x41793800, 0x41794000, 0x41794800, 0x41795000,
-	0x41795800, 0x41796000, 0x41796800, 0x41797000,
-	0x41797800, 0x41798000, 0x41798800, 0x42019000,
-	0x0010b333, 0x42019800, 0x0010b30a, 0x4179a000,
-	0x4179a800, 0x4179b000, 0x4179b800, 0x4179c800,
-	0x4179c000, 0x4179d000, 0x4179d800, 0x4179e000,
-	0x4179e800, 0x4179f000, 0x4179f800, 0x417a0000,
-	0x417a0800, 0x417a1000, 0x417a1800, 0x417a2000,
-	0x42022800, 0x00006100, 0x417a3000, 0x417a3800,
-	0x417a4000, 0x417a4800, 0x417a5000, 0x417a5800,
-	0x417a6000, 0x417a6800, 0x417a7000, 0x417a7800,
-	0x417a8000, 0x417a8800, 0x417a9000, 0x417a9800,
-	0x417ae800, 0x417af800, 0x42030000, 0x00007c00,
-	0x42031000, 0x0010b604, 0x42031800, 0x0000bf1d,
-	0x42032000, 0x0000bf32, 0x42032800, 0x0010b5cc,
-	0x42033000, 0x0010b274, 0x42034000, 0x0010b2a0,
-	0x42033800, 0x0010b2bf, 0x42034800, 0x0010b342,
-	0x42035000, 0x0010b200, 0x42035800, 0x0010aa00,
-	0x42030800, 0x0010b301, 0x417b6000, 0x42036800,
-	0x00006f00, 0x4203c800, 0x00003000, 0x42037000,
-	0x0000ff00, 0x42037800, 0x0000bf00, 0x42038000,
-	0x00007700, 0x42038800, 0x00004000, 0x42039000,
-	0x00006000, 0x42039800, 0x0010bcda, 0x4203a000,
-	0x00007600, 0x4203a800, 0x00007400, 0x4203b000,
-	0x00007200, 0x4203b800, 0x00007100, 0x4203c000,
-	0x00007000, 0x4203d000, 0x00000000, 0x4203e800,
-	0x000200f9, 0x417bd800, 0x1c01f000, 0x42000800,
-	0x00100000, 0x50040000, 0x4c000000, 0x42000000,
-	0x0000aaaa, 0x44000800, 0x42001800, 0x00005555,
-	0x41782000, 0x82102400, 0x00010000, 0x40100000,
-	0x80042c00, 0x440c2800, 0x42003000, 0x0000000a,
-	0x80183040, 0x040207ff, 0x50140000, 0x800c0580,
-	0x04020004, 0x50040000, 0x800c0580, 0x040207f2,
-	0x5c000000, 0x44000800, 0x80142840, 0x4817c861,
-	0x1c01f000, 0x59a8081f, 0x800409c0, 0x04020009,
-	0x49781c0c, 0x4a001a0c, 0x00000200, 0x4a001804,
-	0x07000000, 0x59a80010, 0x9c0001c0, 0x48001805,
-	0x0401fdf8, 0x9c0409c0, 0x48041806, 0x1c01f000,
-	0x59a8080c, 0x4006d000, 0x4202b800, 0x00000001,
-	0x59a8180d, 0x480fc857, 0x82041400, 0x00000014,
-	0x82082400, 0x00000014, 0x40100000, 0x800c0480,
-	0x04001006, 0x44080800, 0x40080800, 0x40101000,
-	0x815eb800, 0x0401f7f7, 0x45780800, 0x495f5020,
-	0x1c01f000, 0x835c0480, 0x00000020, 0x04001009,
-	0x496bc857, 0x815eb840, 0x416a5800, 0x592ed000,
-	0x497a5800, 0x497a5801, 0x812e59c0, 0x1c01f000,
-	0x42000000, 0x0010b652, 0x0201f800, 0x0010a86e,
-	0x417a5800, 0x0401f7f9, 0x815eb840, 0x04001008,
-	0x416a5800, 0x492fc857, 0x592ed000, 0x497a5800,
-	0x497a5801, 0x812e59c0, 0x1c01f000, 0x42000000,
-	0x0010b652, 0x0201f800, 0x0010a86e, 0x417ab800,
-	0x417a5800, 0x0401f7f8, 0x492fc857, 0x496a5800,
-	0x412ed000, 0x815eb800, 0x59c80000, 0x82000540,
-	0x00001200, 0x48039000, 0x1c01f000, 0x492fc857,
-	0x812e59c0, 0x04000007, 0x592c0001, 0x497a5801,
-	0x4c000000, 0x0401fff1, 0x5c025800, 0x0401f7f9,
-	0x1c01f000, 0x4807c856, 0x42007000, 0x0010b5f6,
-	0x4a007001, 0x00000000, 0x59e00003, 0x82000540,
-	0x00008080, 0x4803c003, 0x4a03b805, 0x90000001,
-	0x59dc0006, 0x4a03b805, 0x70000000, 0x59dc0006,
-	0x4a03b805, 0x30000000, 0x59dc0006, 0x4a03b805,
-	0x80000000, 0x4200b000, 0x00000020, 0x497bb807,
-	0x8058b040, 0x040207fe, 0x4a03b805, 0x30000000,
-	0x59dc0006, 0x4a03b805, 0x60000001, 0x59dc0006,
-	0x4a03b805, 0x70000001, 0x59dc0006, 0x4a03b805,
-	0x30000002, 0x4200b000, 0x00000020, 0x497bb807,
-	0x8058b040, 0x040207fe, 0x4a03b805, 0x30000000,
-	0x59dc0006, 0x4a03b805, 0x60000001, 0x0401ff9e,
-	0x04000d99, 0x42001000, 0x0010b5f4, 0x452c1000,
-	0x4a025801, 0x00000001, 0x4a025802, 0x00000100,
-	0x4a025809, 0x00106eac, 0x497a580a, 0x497a580b,
-	0x497a580c, 0x0401ff90, 0x04000d8b, 0x42001000,
-	0x0010b5f5, 0x452c1000, 0x4a025801, 0x00000000,
-	0x4a025802, 0x00000100, 0x4a025809, 0x0010120c,
-	0x497a5803, 0x497a5807, 0x497a5808, 0x497a580a,
-	0x59a8006f, 0x8c000500, 0x04000006, 0x4a03b805,
-	0xe0000001, 0x59dc0006, 0x8c000522, 0x040007fc,
-	0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
-	0x4c380000, 0x40087000, 0x4a007002, 0x00000000,
-	0x42007000, 0x0010b5f6, 0x82080400, 0x00000000,
-	0x45780000, 0x58380005, 0x48087005, 0x80000540,
-	0x04000006, 0x480bc857, 0x82000400, 0x00000000,
-	0x44080000, 0x0401f003, 0x480bc857, 0x48087006,
-	0x58380001, 0x80000540, 0x0400080c, 0x5c007000,
-	0x5c03e000, 0x1c01f000, 0x4c380000, 0x42007000,
-	0x0010b5f6, 0x58380001, 0x80000540, 0x04000803,
-	0x5c007000, 0x1c01f000, 0x42007000, 0x0010b5f6,
-	0x58380001, 0x82000580, 0x00000000, 0x04020012,
-	0x58380000, 0x0c01f001, 0x001008d7, 0x001008d6,
-	0x001008d6, 0x001008d6, 0x001008d6, 0x001008d6,
-	0x001008d6, 0x001008d6, 0x0401fd3f, 0x58380808,
-	0x800409c0, 0x04020027, 0x58380006, 0x80000540,
-	0x04020002, 0x1c01f000, 0x4803c857, 0x48007002,
-	0x40006800, 0x58340000, 0x80000540, 0x04020002,
-	0x48007005, 0x48007006, 0x4a03b805, 0x20000000,
-	0x59dc0006, 0x4a03b805, 0x30000000, 0x58340007,
-	0x4803b800, 0x4803c857, 0x58340008, 0x4803b801,
-	0x4803c857, 0x58340004, 0x48007003, 0x58340003,
-	0x48007004, 0x4803b803, 0x4803c857, 0x58340001,
-	0x8c000500, 0x04000004, 0x4a007001, 0x00000001,
-	0x0401f028, 0x4a007001, 0x00000002, 0x0401f03e,
-	0x0201f800, 0x001091b3, 0x0201f800, 0x0010a4b8,
-	0x04000017, 0x4a03b805, 0x20000000, 0x59dc0006,
-	0x4a03b805, 0x30000000, 0x4807b800, 0x480bb801,
-	0x4a007003, 0x00000010, 0x480c7009, 0x42001000,
-	0x001008be, 0x0201f800, 0x00105cd3, 0x58380008,
-	0x82000400, 0x00000004, 0x48007004, 0x4803b803,
-	0x4a007001, 0x00000007, 0x0401f023, 0x0201f800,
-	0x001091cb, 0x42000800, 0x00000001, 0x42001000,
-	0x001008be, 0x0201f800, 0x00105caf, 0x0401f7b7,
-	0x4c040000, 0x4c080000, 0x58380803, 0x42001000,
-	0x00003fff, 0x82040480, 0x00003fff, 0x04021003,
-	0x40041000, 0x80000580, 0x48007003, 0x4803c857,
-	0x800800c4, 0x4803b802, 0x4a03b805, 0x30000002,
-	0x59dc0006, 0x4a03b805, 0x70000001, 0x59dc0006,
-	0x4a03b805, 0x10000000, 0x5c001000, 0x5c000800,
-	0x1c01f000, 0x483bc857, 0x4c040000, 0x4c080000,
-	0x58380803, 0x42001000, 0x00003fff, 0x82040480,
-	0x00003fff, 0x04021003, 0x40041000, 0x80000580,
-	0x48007003, 0x800800c4, 0x4803b802, 0x4803c857,
-	0x4a03b805, 0x10000002, 0x5c001000, 0x5c000800,
-	0x1c01f000, 0x4c040000, 0x4c380000, 0x42007000,
-	0x0010b5f6, 0x59dc0806, 0x4807c857, 0x4a03b805,
-	0x20000000, 0x8c040d3e, 0x04000007, 0x8c040d08,
-	0x04020cb9, 0x58380001, 0x82000500, 0x00000007,
-	0x0c01f804, 0x5c007000, 0x5c000800, 0x1c01f000,
-	0x001008c6, 0x0010096c, 0x0010097c, 0x00100615,
-	0x00100615, 0x00100615, 0x00100615, 0x0010123a,
-	0x4807c856, 0x82040d00, 0x43000f80, 0x04020009,
-	0x58380003, 0x80000540, 0x0400001c, 0x59dc0000,
-	0x4803b800, 0x59dc0001, 0x4803b801, 0x0401f7ad,
-	0x58380802, 0x4a000802, 0x00000200, 0x0401f01d,
-	0x4807c856, 0x82040d00, 0x43000f80, 0x04020009,
-	0x58380003, 0x80000540, 0x0400000c, 0x59dc0000,
-	0x4803b800, 0x59dc0001, 0x4803b801, 0x0401f7b6,
-	0x58380002, 0x82000400, 0x00000002, 0x46000000,
-	0x00000200, 0x0401f00b, 0x4c340000, 0x58386802,
-	0x59dc0000, 0x4803c857, 0x48006807, 0x59dc0001,
-	0x48006808, 0x4a006802, 0x00000100, 0x5c006800,
-	0x4a007001, 0x00000000, 0x4c300000, 0x58386002,
-	0x4833c857, 0x0401f80c, 0x04000009, 0x58300009,
-	0x82000c80, 0x0010a971, 0x04021c73, 0x82000c80,
-	0x00020000, 0x04001c70, 0x0801f800, 0x5c006000,
-	0x0401f71e, 0x803061c0, 0x04000009, 0x59a8000c,
-	0x80300480, 0x04001007, 0x59a8000d, 0x80300480,
-	0x04021004, 0x82000540, 0x00000001, 0x1c01f000,
-	0x80000580, 0x1c01f000, 0x4803c856, 0x4dc00000,
-	0x42007000, 0x0010b601, 0x4a007400, 0x00000000,
-	0x49787001, 0x42038000, 0x00007720, 0x4a038006,
-	0x60000001, 0x4a038009, 0xf4f60000, 0x42038000,
-	0x00007700, 0x4a038006, 0x60000001, 0x4a038009,
-	0xf4f60000, 0x4a03c822, 0x00000010, 0x4a0370e8,
-	0x00000000, 0x0401f809, 0x4a0370e9, 0x00003a0f,
-	0x4a0370e8, 0x00000000, 0x4a0370e8, 0x00000001,
-	0x5c038000, 0x1c01f000, 0x4c5c0000, 0x4178b800,
-	0x0401f80a, 0x5c00b800, 0x1c01f000, 0x4803c856,
-	0x4c5c0000, 0x825cbd40, 0x00000001, 0x0401f803,
-	0x5c00b800, 0x1c01f000, 0x4803c856, 0x4dc00000,
-	0x4c500000, 0x4c580000, 0x4c540000, 0x4a0370e8,
-	0x00000000, 0x805cb9c0, 0x04000009, 0x4a038807,
-	0x00000004, 0x59b800ea, 0x8c000510, 0x04000004,
-	0x59b800e0, 0x0401f87b, 0x0401f7fb, 0x42038000,
-	0x00007720, 0x0201f800, 0x00100f0f, 0x59c00007,
-	0x4a038006, 0x20000000, 0x59c00007, 0x4a038006,
-	0x8000000a, 0x59c00007, 0x4a038006, 0x8000000b,
-	0x59c00007, 0x4a038006, 0x40000001, 0x83c00580,
-	0x00007700, 0x04000004, 0x42038000, 0x00007700,
-	0x0401f7ed, 0x42038000, 0x00007720, 0x42000800,
-	0x00000800, 0x59c00007, 0x8c00051e, 0x04000006,
-	0x4a038006, 0x90000001, 0x80040840, 0x040207fa,
-	0x0401fc01, 0x83c00580, 0x00007700, 0x04000004,
-	0x42038000, 0x00007700, 0x0401f7f1, 0x805cb9c0,
-	0x0402001d, 0x4200b000, 0x00000020, 0x83b8ac00,
-	0x00000020, 0x0201f800, 0x0010a947, 0x4a0370fb,
-	0x00000001, 0x4a037020, 0x0010110d, 0x59a80039,
-	0x82000500, 0x0000ffff, 0x48037021, 0x4a037035,
-	0x0010bbda, 0x4a037030, 0x0010b210, 0x4a037031,
-	0x0010aa00, 0x4a037032, 0x0010b315, 0x4a037036,
-	0x0010b320, 0x59840002, 0x48037034, 0x4a037038,
-	0x00101104, 0x4a0370fb, 0x00000001, 0x4178a000,
-	0x4200b000, 0x00000020, 0x83b8ac00, 0x00000000,
-	0x0201f800, 0x0010a947, 0x4200b000, 0x00000040,
-	0x83b8ac00, 0x00000040, 0x0201f800, 0x0010a947,
-	0x805cb9c0, 0x04020004, 0x4a0370e4, 0xaaaaaaaa,
-	0x0401f003, 0x4a0370e4, 0xa2aaaa82, 0x4a0370e5,
-	0xaaaaaaaa, 0x4a0370e6, 0xaaaaaaaa, 0x4a0370fb,
-	0x00000000, 0x4a0370e6, 0xaaaaaaaa, 0x42038000,
-	0x00007720, 0x4a038006, 0x90000000, 0x59c00007,
-	0x8c00051e, 0x02020800, 0x00100615, 0x42038000,
-	0x00007700, 0x4a038006, 0x90000000, 0x59c00007,
-	0x8c00051e, 0x02020800, 0x00100615, 0x5c00a800,
-	0x5c00b000, 0x5c00a000, 0x5c038000, 0x1c01f000,
-	0x4d300000, 0x4d380000, 0x40026000, 0x82000500,
-	0x7f000000, 0x82000580, 0x00000003, 0x0402000f,
-	0x83326500, 0x00ffffff, 0x59300203, 0x82000580,
-	0x00000004, 0x04020009, 0x59300c06, 0x82040580,
-	0x00000009, 0x04020005, 0x42027000, 0x00000047,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x5c026000,
-	0x1c01f000, 0x4d300000, 0x4d2c0000, 0x4d340000,
-	0x4d400000, 0x4cfc0000, 0x4d380000, 0x4d3c0000,
-	0x4d440000, 0x4d4c0000, 0x4d480000, 0x4c5c0000,
-	0x4c600000, 0x4c640000, 0x4d040000, 0x4cc80000,
-	0x4ccc0000, 0x4cf40000, 0x4cf80000, 0x4cfc0000,
-	0x0201f800, 0x00020016, 0x5c01f800, 0x5c01f000,
-	0x5c01e800, 0x5c019800, 0x5c019000, 0x5c020800,
-	0x5c00c800, 0x5c00c000, 0x5c00b800, 0x5c029000,
-	0x5c029800, 0x5c028800, 0x5c027800, 0x5c027000,
-	0x5c01f800, 0x5c028000, 0x5c026800, 0x5c025800,
-	0x5c026000, 0x1c01f000, 0x493bc857, 0x0201f000,
-	0x00020045, 0x83300500, 0x1f000000, 0x04000008,
-	0x81326580, 0x80000130, 0x82000c80, 0x00000014,
-	0x02021800, 0x00100615, 0x0c01f013, 0x83300500,
-	0x000000ff, 0x82000c80, 0x00000007, 0x02021800,
-	0x00100615, 0x0c01f025, 0x1c01f000, 0x82000d00,
-	0xc0000038, 0x02020800, 0x0010060d, 0x0201f800,
-	0x00100615, 0x00000000, 0x00000048, 0x00000054,
-	0x00000053, 0x00100ae4, 0x00100b08, 0x00100b03,
-	0x00100b28, 0x00100aef, 0x00100afb, 0x00100ae4,
-	0x00100b23, 0x00100b64, 0x00100ae4, 0x00100ae4,
-	0x00100ae4, 0x00100ae4, 0x00100b67, 0x00100b6d,
-	0x00100b7e, 0x00100b8f, 0x00100ae4, 0x00100b98,
-	0x00100ba4, 0x00100ae4, 0x00100ae4, 0x00100ae4,
-	0x0201f800, 0x00100615, 0x00100aed, 0x00100c3f,
-	0x00100b35, 0x00100b59, 0x00100aed, 0x00100aed,
-	0x00100aed, 0x0201f800, 0x00100615, 0x4803c856,
-	0x59300004, 0x8c00053e, 0x04020005, 0x42027000,
-	0x00000055, 0x0201f000, 0x000208d8, 0x0201f800,
-	0x00106cb4, 0x040007fa, 0x1c01f000, 0x4803c856,
-	0x0401f8aa, 0x40002800, 0x41782000, 0x42027000,
-	0x00000056, 0x0201f000, 0x000208d8, 0x4803c856,
-	0x42027000, 0x00000057, 0x0201f000, 0x000208d8,
-	0x4803c856, 0x59300007, 0x8c00051a, 0x04020010,
-	0x59325808, 0x812e59c0, 0x04000014, 0x592c0408,
-	0x8c00051c, 0x04020003, 0x4a026011, 0xffffffff,
-	0x59300004, 0x8c00053e, 0x04020009, 0x42027000,
-	0x00000048, 0x0201f000, 0x000208d8, 0x59325808,
-	0x4a025a06, 0x00000007, 0x0401f7f4, 0x0201f800,
-	0x00106cb4, 0x040007f6, 0x1c01f000, 0x4803c856,
-	0x83300500, 0x00ffffff, 0x0201f000, 0x0010620f,
-	0x1c01f000, 0x4c040000, 0x59b808ea, 0x82040d00,
-	0x00000007, 0x82040580, 0x00000003, 0x04000004,
-	0x42000000, 0x60000000, 0x0401f8ac, 0x5c000800,
-	0x1c01f000, 0x0401f8fa, 0x0400001b, 0x59325808,
-	0x812e59c0, 0x04000018, 0x592c0204, 0x82000500,
-	0x000000ff, 0x82000d80, 0x00000029, 0x04020012,
-	0x59300203, 0x82000580, 0x00000003, 0x0400000b,
-	0x59300807, 0x84040d26, 0x48066007, 0x0201f800,
-	0x00020087, 0x4a03900d, 0x00000040, 0x4a0370e5,
-	0x00000008, 0x1c01f000, 0x0201f800, 0x00106cb4,
-	0x040007f4, 0x59880053, 0x80000000, 0x48031053,
-	0x4a03900d, 0x00000040, 0x42000000, 0xc0000000,
-	0x0401f05a, 0x42007800, 0x0010bbe1, 0x42002000,
-	0x00003000, 0x42003000, 0x00000105, 0x0201f800,
-	0x00105b3d, 0x4a0370e4, 0x02000000, 0x1c01f000,
-	0x4933c857, 0x0201f000, 0x000208b4, 0x41300800,
-	0x800409c0, 0x02020800, 0x00100615, 0x0201f800,
-	0x0010060d, 0x4933c857, 0x813261c0, 0x02000800,
-	0x00100615, 0x0401f835, 0x40002800, 0x0201f800,
-	0x0010a7c3, 0x0401f8ae, 0x04000007, 0x59326809,
-	0x59340200, 0x8c00050e, 0x59300414, 0x02020800,
-	0x00109094, 0x1c01f000, 0x4933c857, 0x813261c0,
-	0x02000800, 0x00100615, 0x0401f8a1, 0x0400000b,
-	0x59325808, 0x0201f800, 0x00108df4, 0x04000007,
-	0x592c0208, 0x8400054e, 0x48025a08, 0x417a7800,
-	0x0201f800, 0x00108997, 0x1c01f000, 0x485fc857,
-	0x5c000000, 0x4d780000, 0x4203e000, 0x50000000,
-	0x4200b800, 0x00008005, 0x0201f000, 0x0010061a,
-	0x4933c857, 0x83300480, 0x00000020, 0x02021800,
-	0x00100615, 0x83300c00, 0x0010b6cb, 0x50040000,
-	0x80000000, 0x04001002, 0x44000800, 0x1c01f000,
-	0x4933c857, 0x0401f7f4, 0x4807c856, 0x59b800ea,
-	0x8c000510, 0x040007fd, 0x59b800e0, 0x4803c857,
-	0x1c01f000, 0x4803c856, 0x42000000, 0x10000000,
-	0x41300800, 0x0401f02d, 0x82000500, 0xf0000000,
-	0x82040d00, 0x0fffffff, 0x80040d40, 0x4807c857,
-	0x59b800ea, 0x8c000516, 0x04020003, 0x480770e1,
-	0x1c01f000, 0x8c000510, 0x040007fa, 0x4c040000,
-	0x0401f809, 0x5c000800, 0x82100480, 0x00000008,
-	0x040017f4, 0x4c040000, 0x0401febf, 0x5c000800,
-	0x0401f7f0, 0x59b800e2, 0x59b820e2, 0x80100580,
-	0x040207fd, 0x80102114, 0x0401f006, 0x59b800e2,
-	0x59b820e2, 0x80100580, 0x040207fd, 0x0401f001,
-	0x40101800, 0x800c190a, 0x82100500, 0x0000001f,
-	0x820c1d00, 0x0000001f, 0x800c2480, 0x82102500,
-	0x0000001f, 0x1c01f000, 0x82000500, 0xf0000000,
-	0x82040d00, 0x0fffffff, 0x80040d40, 0x4807c857,
-	0x42001000, 0x0010b602, 0x50080000, 0x80000540,
-	0x04020005, 0x4a0370e5, 0x00000003, 0x4a0370e4,
-	0x00000300, 0x80000000, 0x44001000, 0x42001000,
-	0x00000400, 0x59b800ea, 0x8c000510, 0x0400000c,
-	0x0401ffd5, 0x82100480, 0x00000008, 0x04001007,
-	0x4c040000, 0x4c080000, 0x0401fe8b, 0x5c001000,
-	0x5c000800, 0x0401f020, 0x59b800ea, 0x8c000516,
-	0x0402001d, 0x4a0370e4, 0x00300000, 0x480770e1,
-	0x42001000, 0x0000ff00, 0x80081040, 0x04000012,
-	0x59b808e4, 0x8c040d28, 0x040207fc, 0x42001000,
-	0x0010b602, 0x50080000, 0x80000040, 0x04020005,
-	0x4a0370e5, 0x00000002, 0x4a0370e4, 0x00000200,
-	0x02001800, 0x00100615, 0x44001000, 0x8c040d2c,
-	0x1c01f000, 0x41f80000, 0x50000000, 0x0201f800,
-	0x00100615, 0x80081040, 0x040207d3, 0x41f80000,
-	0x50000000, 0x0201f800, 0x00100615, 0x4d380000,
-	0x59300c06, 0x82040580, 0x00000009, 0x04020006,
-	0x42027000, 0x00000047, 0x0201f800, 0x000208d8,
-	0x80000580, 0x5c027000, 0x1c01f000, 0x4c500000,
-	0x4a03900d, 0x00000001, 0x59c8a020, 0x4a03900d,
-	0x00000002, 0x59c80820, 0x8c50a52e, 0x04000002,
-	0x900409c0, 0x82040d00, 0x0000ffff, 0x0201f800,
-	0x00105b0f, 0x5c00a000, 0x1c01f000, 0x0401fff0,
-	0x04000045, 0x4933c857, 0x59300406, 0x82000580,
-	0x00000000, 0x04000040, 0x59c82021, 0x4a03900d,
-	0x00000001, 0x59c82821, 0x82142d00, 0x0000ffff,
-	0x59325808, 0x812e59c0, 0x04000037, 0x59326809,
-	0x0201f800, 0x00104728, 0x02020800, 0x0010907c,
-	0x599c0019, 0x8c00050c, 0x04020018, 0x0201f800,
-	0x00104728, 0x04020015, 0x59300811, 0x4807c857,
-	0x592c0408, 0x8c00051c, 0x0402000e, 0x8400055c,
-	0x48025c08, 0x592c0a04, 0x82040d00, 0x000000ff,
-	0x82040580, 0x00000048, 0x04000004, 0x82040580,
-	0x00000018, 0x04020003, 0x59300811, 0x48065803,
-	0x4a026011, 0x7fffffff, 0x48166013, 0x0201f800,
-	0x0010112d, 0x04020014, 0x0401fa07, 0x40280000,
-	0x4802600d, 0x04000005, 0x4832600b, 0x50200000,
-	0x4802600a, 0x4822600c, 0x59300414, 0x8c00051c,
-	0x04020004, 0x599c0019, 0x8c00050c, 0x0402086e,
-	0x4a03900d, 0x00000040, 0x4a0370e5, 0x00000008,
-	0x1c01f000, 0x59880053, 0x80000000, 0x48031053,
-	0x4a03900d, 0x00000040, 0x42000000, 0xc0000000,
-	0x0401f726, 0x4cf80000, 0x58f40000, 0x8001f540,
-	0x0401f820, 0x41781800, 0x0401f8e7, 0x04020014,
-	0x44140800, 0x0401f82a, 0x04000011, 0x40043800,
-	0x42001800, 0x00000001, 0x40142000, 0x0401f8de,
-	0x0402000b, 0x801c3800, 0x501c0000, 0x44000800,
-	0x0401f810, 0x801c0580, 0x04000004, 0x44103800,
-	0x801c3840, 0x44143800, 0x0401f819, 0x5c01f000,
-	0x1c01f000, 0x80f9f1c0, 0x04020003, 0x58f41202,
-	0x0401f003, 0x42001000, 0x00000007, 0x1c01f000,
-	0x80f9f1c0, 0x04020006, 0x58f40401, 0x82000480,
-	0x00000002, 0x80f40400, 0x0401f005, 0x58f80401,
-	0x82000480, 0x00000002, 0x80f80400, 0x50002800,
-	0x80000000, 0x50002000, 0x1c01f000, 0x80f9f1c0,
-	0x04020008, 0x58f40401, 0x82000480, 0x00000002,
-	0x02001800, 0x00100615, 0x4801ec01, 0x0401f00b,
-	0x58f80401, 0x82000480, 0x00000002, 0x02001800,
-	0x00100615, 0x4801f401, 0x82000580, 0x00000002,
-	0x04020002, 0x0401f809, 0x58f40202, 0x80000040,
-	0x4801ea02, 0x02000800, 0x00100615, 0x82000580,
-	0x00000001, 0x1c01f000, 0x4d2c0000, 0x40fa5800,
-	0x0201f800, 0x0010083a, 0x4979e800, 0x4179f000,
-	0x5c025800, 0x1c01f000, 0x80f5e9c0, 0x04000009,
-	0x80f9f1c0, 0x04020ff5, 0x4d2c0000, 0x40f65800,
-	0x0201f800, 0x0010083a, 0x4179e800, 0x5c025800,
-	0x1c01f000, 0x4cf40000, 0x0201f800, 0x00104728,
-	0x04020036, 0x59300807, 0x82040500, 0x00003100,
-	0x04020032, 0x8c040d22, 0x04000032, 0x5930001f,
-	0x8001ed40, 0x02000800, 0x00100615, 0x82000580,
-	0xffffffff, 0x04000029, 0x58f40201, 0x82000580,
-	0x0000dcb3, 0x02020800, 0x00100615, 0x58f40a02,
-	0x82040500, 0x0000fffe, 0x04000003, 0x0401ff86,
-	0x58f40a02, 0x82040480, 0x0000000f, 0x04021059,
-	0x80040800, 0x4805ea02, 0x82040580, 0x00000008,
-	0x0400005d, 0x82040480, 0x00000008, 0x0400100a,
-	0x58f40000, 0x8001ed40, 0x02000800, 0x00100615,
-	0x58f40201, 0x82000580, 0x0000ddb9, 0x02020800,
-	0x00100615, 0x58f40401, 0x82000c00, 0x00000002,
-	0x4805ec01, 0x80f40400, 0x59300812, 0x44040000,
-	0x80000000, 0x45780000, 0x5c01e800, 0x1c01f000,
-	0x42001000, 0x00000400, 0x59b800e4, 0x8c000524,
-	0x04020023, 0x4a0370e4, 0x00030000, 0x40000000,
-	0x59b800e4, 0x8c000524, 0x0402001b, 0x59300807,
-	0x84040d62, 0x48066007, 0x4a0370e4, 0x00020000,
-	0x4d2c0000, 0x0201f800, 0x00100819, 0x04000025,
-	0x492e601f, 0x4a025a01, 0x0000dcb3, 0x59300008,
-	0x80001d40, 0x02000800, 0x00100615, 0x580c080f,
-	0x48065803, 0x59301811, 0x40040000, 0x800c0580,
-	0x0402000d, 0x497a5a02, 0x4a025c01, 0x00000004,
-	0x0401f011, 0x4a0370e4, 0x00020000, 0x40000000,
-	0x40000000, 0x80081040, 0x02000800, 0x00100615,
-	0x0401f7d6, 0x4a025a02, 0x00000001, 0x4a025c01,
-	0x00000006, 0x497a5804, 0x400c0000, 0x80040480,
-	0x48025805, 0x412de800, 0x5c025800, 0x0401f7a9,
-	0x5c025800, 0x4a02601f, 0xffffffff, 0x0401f7c3,
-	0x4d2c0000, 0x58f65800, 0x0201f800, 0x0010083a,
-	0x40f65800, 0x0201f800, 0x0010083a, 0x5c025800,
-	0x0401f7f5, 0x4d2c0000, 0x0201f800, 0x00100819,
-	0x040007f8, 0x4a025a01, 0x0000ddb9, 0x4a025c01,
-	0x00000002, 0x492de800, 0x412de800, 0x5c025800,
-	0x0401f7a5, 0x0401ff30, 0x82f40400, 0x00000004,
-	0x800c0400, 0x40000800, 0x50040000, 0x80100580,
-	0x04000016, 0x82040c00, 0x00000002, 0x80081040,
-	0x040207fa, 0x80f9f1c0, 0x04000011, 0x58f41202,
-	0x82081480, 0x00000007, 0x82f80400, 0x00000002,
-	0x800c0400, 0x40000800, 0x50040000, 0x80100580,
-	0x04000006, 0x82040c00, 0x00000002, 0x80081040,
-	0x040207fa, 0x0401f002, 0x1c01f000, 0x82000540,
-	0x00000001, 0x0401f7fd, 0x4cf40000, 0x4cf80000,
-	0x4001e800, 0x592c0a06, 0x800409c0, 0x04020021,
-	0x82f40580, 0xffffffff, 0x0400001b, 0x58f40201,
-	0x82000580, 0x0000dcb3, 0x02020800, 0x00100615,
-	0x58f40000, 0x8001f540, 0x04000006, 0x58f80201,
-	0x82000580, 0x0000ddb9, 0x02020800, 0x00100615,
-	0x41783800, 0x58f44003, 0x0401f83d, 0x04020009,
-	0x0401ff2e, 0x497a601f, 0x59300807, 0x84040d22,
-	0x48066007, 0x5c01f000, 0x5c01e800, 0x1c01f000,
-	0x0401ff26, 0x4a025a06, 0x00000011, 0x0401f7f6,
-	0x82f40580, 0xffffffff, 0x04020f20, 0x0401f7f2,
-	0x4cf40000, 0x4cf80000, 0x4001e800, 0x82040580,
-	0x00000001, 0x04020020, 0x82f40580, 0xffffffff,
-	0x0400001a, 0x58f40201, 0x82000580, 0x0000dcb3,
-	0x02020800, 0x00100615, 0x58f40000, 0x8001f540,
-	0x04000006, 0x58f80201, 0x82000580, 0x0000ddb9,
-	0x02020800, 0x00100615, 0x41783800, 0x58f44003,
-	0x0401f813, 0x04020008, 0x0401ff04, 0x42000800,
-	0x00000001, 0x497a601f, 0x5c01f000, 0x5c01e800,
-	0x1c01f000, 0x0401fefd, 0x42000800, 0x00000011,
-	0x0401f7f9, 0x4c040000, 0x82f40580, 0xffffffff,
-	0x04020ef6, 0x5c000800, 0x0401f7f3, 0x4803c856,
-	0x401c2000, 0x41781800, 0x4c200000, 0x0401ff86,
-	0x5c004000, 0x0402002c, 0x40202000, 0x42001800,
-	0x00000001, 0x0401ff80, 0x04020027, 0x0401feae,
-	0x40082800, 0x82f40400, 0x00000004, 0x40003000,
-	0x50182000, 0x40100000, 0x801c0580, 0x04000005,
-	0x42001800, 0x00000001, 0x0401ff73, 0x0402001a,
-	0x82183400, 0x00000002, 0x80142840, 0x040207f5,
-	0x80f9f1c0, 0x04000013, 0x58f42a02, 0x82142c80,
-	0x00000007, 0x82f80400, 0x00000003, 0x40003000,
-	0x50182000, 0x40100000, 0x801c0580, 0x04000005,
-	0x42001800, 0x00000001, 0x0401ff5f, 0x04020006,
-	0x82183400, 0x00000002, 0x80142840, 0x040207f5,
-	0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fd,
-	0x0201f800, 0x00100615, 0x58380207, 0x8c000502,
-	0x040007fc, 0x50200000, 0x80387c00, 0x583c2800,
-	0x583c2001, 0x58380404, 0x80001540, 0x04020002,
-	0x58381407, 0x58c83401, 0x58380c08, 0x59303807,
-	0x497a6012, 0x497a6013, 0x0201f000, 0x000200bf,
-	0x592c0408, 0x8c000502, 0x040007ea, 0x592c0409,
-	0x80000540, 0x040007e7, 0x82000c80, 0x00000002,
-	0x04001011, 0x58380001, 0x80007540, 0x02000800,
-	0x00100615, 0x58380204, 0x82000500, 0x0000000f,
-	0x82000400, 0x0010110d, 0x50004000, 0x40040000,
-	0x800409c0, 0x04000005, 0x82040c80, 0x00000005,
-	0x040217f1, 0x80204400, 0x50200000, 0x80387c00,
-	0x583c2800, 0x583c2001, 0x583c1002, 0x592c0a07,
-	0x592c4c08, 0x592c300d, 0x59303807, 0x497a6012,
-	0x497a6013, 0x4816600e, 0x4812600f, 0x480a6010,
-	0x481a6011, 0x80040840, 0x4806600d, 0x02000000,
-	0x000200c7, 0x80204000, 0x50201800, 0x800c19c0,
-	0x0402000c, 0x58380001, 0x80007540, 0x02000800,
-	0x00100615, 0x58380204, 0x82000500, 0x0000000f,
-	0x82000400, 0x0010110d, 0x50004000, 0x50201800,
-	0x483a600b, 0x480e600a, 0x4822600c, 0x0201f000,
-	0x000200c7, 0x4803c856, 0x592c0208, 0x8c00051e,
-	0x04020017, 0x50200000, 0x80306c00, 0x40240000,
-	0x0c01f001, 0x00100e91, 0x00100e91, 0x00100e9a,
-	0x00100e91, 0x00100e91, 0x00100e91, 0x00100e91,
-	0x00100e91, 0x00100e9a, 0x00100e91, 0x00100e9a,
-	0x00100e91, 0x00100e91, 0x00100e9a, 0x00100e91,
-	0x00100e91, 0x0201f800, 0x00100615, 0x8400051e,
-	0x48025a08, 0x50200000, 0x80306c00, 0x58343801,
-	0x481e600f, 0x0401f007, 0x58341802, 0x58342800,
-	0x58343801, 0x480e6010, 0x4816600e, 0x481e600f,
-	0x0401f24b, 0x4933c857, 0x5931f808, 0x59300a06,
-	0x800409c0, 0x04000005, 0x80040906, 0x04020002,
-	0x80040800, 0x4805fc06, 0x4a026206, 0x00000002,
-	0x592c0409, 0x82000500, 0x00000008, 0x0400000b,
-	0x0401f834, 0x59300203, 0x82000580, 0x00000004,
-	0x04020005, 0x42027000, 0x00000048, 0x0201f800,
-	0x000208d8, 0x1c01f000, 0x4cfc0000, 0x58fc0204,
-	0x82000500, 0x000000ff, 0x82000580, 0x00000048,
-	0x0402000c, 0x58fc000b, 0x800001c0, 0x04000009,
-	0x58fc0407, 0x800001c0, 0x04000006, 0x58fc080b,
-	0x8c040d16, 0x04000017, 0x58fc0007, 0x0401f00a,
-	0x58fc0408, 0x8c000512, 0x04020014, 0x58fc0c09,
-	0x8c040d16, 0x04020003, 0x5c01f800, 0x1c01f000,
-	0x58fc000a, 0x59300811, 0x80040580, 0x04020009,
-	0x59300007, 0x84000500, 0x48026007, 0x42027000,
-	0x00000048, 0x5c01f800, 0x0201f000, 0x000208d8,
-	0x5c01f800, 0x1c01f000, 0x58fdf809, 0x0401f7ec,
-	0x5c000000, 0x4c000000, 0x4803c857, 0x4933c857,
-	0x59b808ea, 0x82040d00, 0x00000007, 0x82040580,
-	0x00000000, 0x0400001e, 0x82040580, 0x00000003,
-	0x0400001b, 0x59300406, 0x4c000000, 0x4a026406,
-	0x00000000, 0x42003000, 0x00000041, 0x42000000,
-	0x50000000, 0x41300800, 0x4c180000, 0x0401fce3,
-	0x5c003000, 0x0400000b, 0x42000000, 0x0000001e,
-	0x80000040, 0x040207ff, 0x80183040, 0x040207f4,
-	0x42000000, 0x40000000, 0x41300800, 0x0401fcd7,
-	0x5c000000, 0x48026406, 0x1c01f000, 0x59300007,
-	0x84000500, 0x48026007, 0x0401f7fc, 0x59c00007,
-	0x4a038006, 0x30000000, 0x40000000, 0x59c00007,
-	0x8c00050a, 0x040207fe, 0x1c01f000, 0x5c000000,
-	0x4c000000, 0x4803c857, 0x4dc00000, 0x4a0370e8,
-	0x00000000, 0x42038000, 0x00007720, 0x0401fff0,
-	0x42038000, 0x00007700, 0x0401ffed, 0x0201f800,
-	0x00104e0d, 0x04020013, 0x4a038891, 0x0000ffff,
-	0x497b8880, 0x497b8892, 0x42001000, 0x00000190,
-	0x40000000, 0x40000000, 0x80081040, 0x040207fd,
-	0x42000000, 0x0010b6a5, 0x0201f800, 0x0010a86e,
-	0x0401f80e, 0x5c038000, 0x0201f000, 0x00104f29,
-	0x0401f82d, 0x42000000, 0x0010b6a6, 0x0201f800,
-	0x0010a86e, 0x0401f805, 0x48178892, 0x480b8880,
-	0x5c038000, 0x1c01f000, 0x496fc857, 0x836c0580,
-	0x00000003, 0x0402000b, 0x4c080000, 0x4c0c0000,
-	0x42001000, 0x00008048, 0x42001800, 0x0000ffff,
-	0x0201f800, 0x00103857, 0x5c001800, 0x5c001000,
-	0x42000800, 0x0000003c, 0x0201f800, 0x00101395,
-	0x59a8006c, 0x80000540, 0x04000006, 0x59a8106d,
-	0x800811c0, 0x04000003, 0x0201f800, 0x00101b0a,
-	0x4a038891, 0x0000ffff, 0x4a03900d, 0x00000040,
-	0x0201f800, 0x001009db, 0x4a0370e8, 0x00000001,
-	0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857,
-	0x59c41080, 0x497b8880, 0x59c42892, 0x497b8892,
-	0x0201f800, 0x00104e0d, 0x04020002, 0x1c01f000,
-	0x42002000, 0x00000260, 0x59c418a4, 0x820c1d00,
-	0x0000000f, 0x820c0580, 0x00000000, 0x04000010,
-	0x59c41805, 0x820c1d00, 0x00000001, 0x0402000e,
-	0x59c418a4, 0x820c1d00, 0x0000000f, 0x820c0480,
-	0x00000007, 0x04001004, 0x820c0480, 0x0000000c,
-	0x04001003, 0x80102040, 0x040207ec, 0x497b8891,
-	0x1c01f000, 0x4c100000, 0x42002000, 0x00000019,
-	0x46000000, 0x00000001, 0x0201f800, 0x001019a4,
-	0x50001800, 0x820c1d00, 0x00000001, 0x04000005,
-	0x80102040, 0x040207f7, 0x5c002000, 0x0401f7f0,
-	0x5c002000, 0x0401f7ec, 0x4803c856, 0x1c01f000,
-	0x4d2c0000, 0x59325808, 0x592c0a04, 0x4807c857,
-	0x82040d00, 0x000000ff, 0x82040500, 0x0000000f,
-	0x0c01f001, 0x00100fb5, 0x00100fb5, 0x00100fb5,
-	0x00100fcd, 0x00100fb5, 0x00100fb5, 0x00100fb5,
-	0x00100fb5, 0x00100fb5, 0x00100fcd, 0x00100fb5,
-	0x00100fb7, 0x00100fb5, 0x00100fb5, 0x00100fb5,
-	0x00100fb5, 0x0201f800, 0x00100615, 0x82040580,
-	0x0000003b, 0x02020800, 0x00100615, 0x592c020a,
-	0x8c000500, 0x0400005f, 0x592c1a07, 0x82040500,
-	0x0000000f, 0x82000400, 0x0010110d, 0x50001000,
-	0x50080000, 0x59302013, 0x4802600a, 0x492e600b,
-	0x480a600c, 0x480e600d, 0x48126012, 0x5c025800,
-	0x1c01f000, 0x82040500, 0x0000000f, 0x82000400,
-	0x0010110d, 0x50001000, 0x50080000, 0x592c1a07,
-	0x4802600a, 0x492e600b, 0x480a600c, 0x480e600d,
-	0x497a6012, 0x0401f7f2, 0x8c040d00, 0x04020041,
-	0x82040d00, 0x00000080, 0x0400003e, 0x0201f000,
-	0x000200d0, 0x59300013, 0x59301012, 0x80080580,
-	0x0402000c, 0x42007800, 0x80000005, 0x592c1208,
-	0x82080500, 0xffff7fff, 0x48025a08, 0x8c08151e,
-	0x0402002d, 0x823c7d40, 0x00000020, 0x0401f02a,
-	0x480bc857, 0x42000000, 0x0010b64f, 0x0201f800,
-	0x0010a86e, 0x59300414, 0x4803c857, 0x8c000514,
-	0x04020007, 0x599c1819, 0x8c0c1d12, 0x04020004,
-	0x820c1d40, 0x00000001, 0x0401f01d, 0x59302013,
-	0x0401f92d, 0x0402001a, 0x42007800, 0x80000005,
-	0x5930500d, 0x592c0208, 0x4803c857, 0x8c00051e,
-	0x04020005, 0x823c7d40, 0x00000020, 0x5930400c,
-	0x0401f004, 0x8400051e, 0x48025a08, 0x0401f8dc,
-	0x50201800, 0x480e600a, 0x4832600b, 0x4822600c,
-	0x482a600d, 0x480fc857, 0x4833c857, 0x4823c857,
-	0x482bc857, 0x80000580, 0x483e6004, 0x1c01f000,
-	0x0201f800, 0x00100615, 0x4933c857, 0x4d2c0000,
-	0x59900004, 0x81300580, 0x02020800, 0x00100615,
-	0x0201f800, 0x00108df4, 0x02000800, 0x00100615,
-	0x59325808, 0x4d3c0000, 0x4d400000, 0x59300004,
-	0x4803c857, 0x4c000000, 0x0201f800, 0x00106b13,
-	0x0201f800, 0x001068c1, 0x5c000000, 0x8c000516,
-	0x04000010, 0x592c000f, 0x4803c857, 0x48025807,
-	0x41780800, 0x42028000, 0x00000002, 0x0201f800,
-	0x00104bee, 0x4a025c06, 0x0000ffff, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00107698, 0x0401f015,
-	0x4a026203, 0x00000002, 0x592c0208, 0x8400054e,
-	0x48025a08, 0x59300406, 0x82000580, 0x00000006,
-	0x04020009, 0x811800ca, 0x81c80c00, 0x58040939,
-	0x592c000d, 0x80040480, 0x592c080f, 0x80040480,
-	0x4802580b, 0x417a7800, 0x0201f800, 0x00108997,
-	0x5c028000, 0x5c027800, 0x5c025800, 0x1c01f000,
-	0x4933c857, 0x4d2c0000, 0x59900004, 0x81300580,
-	0x02020800, 0x00100615, 0x0201f800, 0x00108df4,
-	0x02000800, 0x00100615, 0x59325808, 0x592c0208,
-	0x84000540, 0x48025a08, 0x0401f7bf, 0x491bc857,
-	0x49d3c857, 0x4dd00000, 0x41780800, 0x8007a0ca,
-	0x83d3a400, 0x00007600, 0x4a03a005, 0x80000002,
-	0x42000000, 0x00001000, 0x50000000, 0x82000480,
-	0x24220001, 0x04020029, 0x59d01006, 0x82080500,
-	0x00006000, 0x82000580, 0x00006000, 0x04000031,
-	0x82080500, 0x40008000, 0x040007f8, 0x800409c0,
-	0x0402002c, 0x811a31c0, 0x0400002a, 0x42000000,
-	0x00001002, 0x50001000, 0x46000000, 0x00000512,
-	0x42001800, 0x0000000a, 0x59e00000, 0x8c00051a,
-	0x040207fc, 0x800c1840, 0x040207fc, 0x42000000,
-	0x00001002, 0x46000000, 0x00000514, 0x42001800,
-	0x0000000a, 0x59e00000, 0x8c00053a, 0x040207fc,
-	0x800c1840, 0x040207fc, 0x42000000, 0x00001002,
-	0x44080000, 0x0401f00f, 0x02004800, 0x000207c8,
-	0x59d01006, 0x82080500, 0x00006000, 0x82000580,
-	0x00006000, 0x04000007, 0x8c08151e, 0x040007f7,
-	0x59d01006, 0x82080500, 0x00006000, 0x040207f3,
-	0x83d3a400, 0x00000020, 0x80040800, 0x82040480,
-	0x00000005, 0x040017bd, 0x5c03a000, 0x1c01f000,
-	0x491bc857, 0x49d3c857, 0x4dd00000, 0x41780800,
-	0x8007a0ca, 0x83d3a400, 0x00007600, 0x4a03a005,
-	0x80000001, 0x59d00006, 0x83d3a400, 0x00000020,
-	0x80040800, 0x82040480, 0x00000005, 0x040017f8,
-	0x5c03a000, 0x1c01f000, 0x59d00006, 0x8c00053e,
-	0x0400001e, 0x59902804, 0x4817c857, 0x801429c0,
-	0x04000013, 0x5990000a, 0x5990080b, 0x5990100c,
-	0x5990180d, 0x4800280a, 0x4804280b, 0x4808280c,
-	0x480c280d, 0x59d00000, 0x59d00801, 0x59d01002,
-	0x59d01803, 0x59d02004, 0x4800280e, 0x4804280f,
-	0x48082810, 0x480c2811, 0x48102812, 0x59900006,
-	0x82000500, 0xffff0000, 0x48032006, 0x4a03a005,
-	0x30000000, 0x59d00006, 0x1c01f000, 0x4803c856,
-	0x80204000, 0x50200000, 0x80000540, 0x04000003,
-	0x80285040, 0x1c01f000, 0x58300001, 0x80000540,
-	0x0400000e, 0x4802600b, 0x40006000, 0x58300204,
-	0x82000500, 0x0000000f, 0x82000400, 0x0010110d,
-	0x50004000, 0x802041c0, 0x02000800, 0x00100615,
-	0x80285040, 0x1c01f000, 0x40005000, 0x1c01f000,
-	0x00000005, 0x00000008, 0x0000000b, 0x0000000e,
-	0x00000011, 0x00000000, 0x00000000, 0x0000000b,
-	0x00000000, 0x00000000, 0x00000000, 0x00101108,
-	0x00101107, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00101108, 0x00101107, 0x00101104,
-	0x00101108, 0x00101107, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00101108,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00101108, 0x00101108, 0x00101108,
-	0x00000000, 0x00101108, 0x00000000, 0x00000000,
-	0x00000000, 0x4813c857, 0x492fc857, 0x4933c857,
-	0x48126012, 0x592c5207, 0x802851c0, 0x0400004a,
-	0x412c6000, 0x0401f84b, 0x04000009, 0x82240580,
-	0x00000002, 0x04020003, 0x5830000d, 0x80102480,
-	0x50200000, 0x80004540, 0x0400003f, 0x50200000,
-	0x80000540, 0x0400000b, 0x80301400, 0x58080002,
-	0x80102480, 0x0400101e, 0x801021c0, 0x04000009,
-	0x80285040, 0x04000034, 0x80204000, 0x0401f7f4,
-	0x58300001, 0x80006540, 0x0400002f, 0x0401f7e6,
-	0x80285040, 0x0400002c, 0x80204000, 0x50200000,
-	0x80000540, 0x0402000a, 0x58300001, 0x80006540,
-	0x04000025, 0x58300204, 0x82004d00, 0x0000000f,
-	0x82244400, 0x0010110d, 0x50204000, 0x592c0208,
-	0x8400051e, 0x48025a08, 0x0401f013, 0x80102080,
-	0x80102000, 0x48126010, 0x4813c857, 0x58080802,
-	0x40100000, 0x80042480, 0x02001800, 0x00100615,
-	0x58080000, 0x58081801, 0x80102400, 0x4812600e,
-	0x480e600f, 0x4813c857, 0x592c0208, 0x8400055e,
-	0x48025a08, 0x4833c857, 0x4823c857, 0x482bc857,
-	0x4832600b, 0x4822600c, 0x482a600d, 0x80000580,
-	0x0401f003, 0x82000540, 0x00000001, 0x1c01f000,
-	0x58300204, 0x82004d00, 0x0000000f, 0x82244400,
-	0x0010110d, 0x82000500, 0x000000ff, 0x82000580,
-	0x00000029, 0x0402001b, 0x50204000, 0x592c0409,
-	0x80000540, 0x02000800, 0x00100615, 0x82000c80,
-	0x00000002, 0x04001011, 0x58300001, 0x80006540,
-	0x02000800, 0x00100615, 0x58300204, 0x82000500,
-	0x0000000f, 0x82000400, 0x0010110d, 0x50004000,
-	0x40040000, 0x800409c0, 0x04000006, 0x82040c80,
-	0x00000005, 0x040217f1, 0x80204400, 0x80000580,
-	0x1c01f000, 0x59e00004, 0x8c00050e, 0x02020000,
-	0x00100951, 0x1c01f000, 0x4c5c0000, 0x59e4b800,
-	0x485fc857, 0x825c0500, 0x0000001f, 0x04000004,
-	0x59e40862, 0x0201f800, 0x00100615, 0x825c0500,
-	0x000000e0, 0x02000800, 0x00100615, 0x8c5cbd0e,
-	0x04020807, 0x8c5cbd0c, 0x04020809, 0x8c5cbd0a,
-	0x04020878, 0x5c00b800, 0x1c01f000, 0x4803c856,
-	0x4a03c800, 0x00000080, 0x1c01f000, 0x4d2c0000,
-	0x42007800, 0x0010b6eb, 0x583c0001, 0x583c0802,
-	0x80040540, 0x0400003f, 0x42000800, 0x0010b5f5,
-	0x50065800, 0x592c0002, 0x82000580, 0x00000000,
-	0x0400000e, 0x59e40850, 0x59e41853, 0x400c0000,
-	0x80040400, 0x59e40852, 0x4807c857, 0x80041480,
-	0x04021008, 0x40001000, 0x480bc857, 0x4a007800,
-	0x00000001, 0x0401f006, 0x4803c857, 0x0401f029,
-	0x59e41050, 0x480bc857, 0x49787800, 0x480bc857,
-	0x480fc857, 0x592c0003, 0x80000540, 0x04000006,
-	0x80080580, 0x04020004, 0x592c0003, 0x4803c857,
-	0x480bc857, 0x480a5803, 0x592c0007, 0x800001c0,
-	0x04000007, 0x592c1007, 0x480bc857, 0x583c0003,
-	0x4803c857, 0x80080480, 0x04001003, 0x583c1001,
-	0x480bc857, 0x583c0802, 0x480bc857, 0x4807c857,
-	0x4a025801, 0x00000000, 0x4a025809, 0x0010120c,
-	0x480a5807, 0x48065808, 0x59e40053, 0x48025804,
-	0x412c1000, 0x492fc857, 0x0201f800, 0x001008a1,
-	0x5c025800, 0x4a03c800, 0x00000040, 0x1c01f000,
-	0x42007800, 0x0010b5f5, 0x503c7800, 0x4a007802,
-	0x00000100, 0x42007800, 0x0010b6eb, 0x583c0000,
-	0x4803c857, 0x82000d80, 0x00000001, 0x04000004,
-	0x80000000, 0x48007800, 0x0401f019, 0x49787800,
-	0x583c1806, 0x583c0005, 0x800c1800, 0x480c7806,
-	0x800c0580, 0x04020002, 0x49787806, 0x583c0807,
-	0x800409c0, 0x0400000e, 0x583c0008, 0x80000000,
-	0x48007808, 0x80040580, 0x04020009, 0x49787808,
-	0x583c2006, 0x42001800, 0x00000001, 0x42001000,
-	0x00008028, 0x0201f800, 0x00103857, 0x1c01f000,
-	0x4a03c800, 0x00000020, 0x0201f800, 0x0010a867,
-	0x59e40000, 0x1c01f000, 0x4d2c0000, 0x4a007001,
-	0x00000000, 0x82040d00, 0x43000f80, 0x02020800,
-	0x00100615, 0x58380009, 0x4803c00f, 0x0201f800,
-	0x001091cb, 0x583a5808, 0x592c0000, 0x48007008,
-	0x800001c0, 0x04020002, 0x49787007, 0x0201f800,
-	0x0010083a, 0x5c025800, 0x0201f000, 0x001008c6,
-	0x4803c856, 0x4c3c0000, 0x4d2c0000, 0x4d300000,
-	0x5830000a, 0x80025d40, 0x02000800, 0x00100615,
-	0x592e6008, 0x4c300000, 0x0201f800, 0x001091e3,
-	0x5c006000, 0x02000800, 0x00100615, 0x58300002,
-	0x82000580, 0x00000100, 0x04020010, 0x5930780b,
-	0x583c0001, 0x80000540, 0x0400000e, 0x4802600b,
-	0x40007800, 0x82000400, 0x00000002, 0x48006003,
-	0x583c0000, 0x48006004, 0x40301000, 0x0201f800,
-	0x001008a1, 0x0401f00c, 0x4a025a06, 0x00000002,
-	0x4c300000, 0x0201f800, 0x00020381, 0x5c006000,
-	0x40325800, 0x0201f800, 0x0010083a, 0x0201f800,
-	0x000208b4, 0x5c026000, 0x5c025800, 0x5c007800,
-	0x1c01f000, 0x4803c856, 0x4d2c0000, 0x4d300000,
-	0x42007000, 0x0010b5f6, 0x58380801, 0x82040580,
-	0x00000002, 0x04020011, 0x58386002, 0x5830000a,
-	0x812c0580, 0x0402000d, 0x59e00004, 0x8c00050e,
-	0x040007fe, 0x59dc0006, 0x4803c857, 0x4a03b805,
-	0x20000000, 0x8c00053e, 0x040007f8, 0x4a007001,
-	0x00000000, 0x0401f019, 0x58386006, 0x40305000,
-	0x803061c0, 0x02000800, 0x00100615, 0x5830000a,
-	0x812c0580, 0x04000004, 0x40305000, 0x58306000,
-	0x0401f7f8, 0x40280000, 0x80300580, 0x58300000,
-	0x04000006, 0x48005000, 0x800001c0, 0x04020007,
-	0x48287005, 0x0401f005, 0x800001c0, 0x04020002,
-	0x48007005, 0x48007006, 0x40325800, 0x0201f800,
-	0x0010083a, 0x42007000, 0x0010b5f6, 0x58380001,
-	0x82000580, 0x00000000, 0x02000800, 0x001008c6,
-	0x5c026000, 0x5c025800, 0x1c01f000, 0x4803c856,
-	0x42000800, 0x0000003c, 0x48079000, 0x59c80000,
-	0x80040500, 0x040207fe, 0x497b9005, 0x4a039035,
-	0x00880200, 0x59a8000e, 0x800000e0, 0x4803900e,
-	0x4a039011, 0x00000024, 0x4a03900f, 0x0010cfc0,
-	0x4a039010, 0x0010cfc0, 0x4a039015, 0x0000007f,
-	0x4a03900d, 0x00000040, 0x4a039000, 0x00001600,
-	0x1c01f000, 0x59c80007, 0x8c000508, 0x040208b7,
-	0x59c80800, 0x8c040d16, 0x04020004, 0x82000500,
-	0x00000006, 0x0c01f005, 0x4807c857, 0x82000500,
-	0x0000000e, 0x0c01f001, 0x001012f8, 0x001012f6,
-	0x0010567d, 0x001012f6, 0x001012fa, 0x001012f6,
-	0x001012fa, 0x001012fa, 0x001012f6, 0x001012f6,
-	0x001012f6, 0x001012f6, 0x001012fa, 0x001012f6,
-	0x001012fa, 0x001012f6, 0x0201f800, 0x00100615,
-	0x4803c857, 0x1c01f000, 0x59c8080c, 0x4807c857,
-	0x82040500, 0x00006000, 0x04000004, 0x0201f800,
-	0x0010a82a, 0x0401f006, 0x82040500, 0x007f0000,
-	0x04000006, 0x0201f800, 0x0010a7fc, 0x0201f800,
-	0x00106c07, 0x0401f02b, 0x82040500, 0x00000014,
-	0x04000014, 0x0201f800, 0x0010a859, 0x836c0580,
-	0x00000003, 0x0400000d, 0x0201f800, 0x00104e0d,
-	0x04000004, 0x0201f800, 0x00103f37, 0x0401f007,
-	0x4a035033, 0x00000001, 0x4202d800, 0x00000001,
-	0x0201f800, 0x00104d76, 0x0401f817, 0x0401f015,
-	0x82040500, 0x00001c00, 0x04000005, 0x0201f800,
-	0x0010a838, 0x0401f810, 0x0401f00e, 0x82040500,
-	0x00000140, 0x04000005, 0x0201f800, 0x0010a84b,
-	0x0401f809, 0x0401f007, 0x82040500, 0x00008000,
-	0x04000004, 0x0201f800, 0x0010a823, 0x0401f802,
-	0x1c01f000, 0x4c0c0000, 0x4c100000, 0x4c140000,
-	0x0201f800, 0x00100f17, 0x5c002800, 0x5c002000,
-	0x5c001800, 0x1c01f000, 0x4803c856, 0x59a80804,
-	0x59a8002b, 0x82000500, 0xfffff000, 0x80040540,
-	0x4803502b, 0x59a8002f, 0x82000500, 0xfffff000,
-	0x80040540, 0x4803502f, 0x48078882, 0x82041c00,
-	0x0000000f, 0x800c1908, 0x820c1c00, 0x00000004,
-	0x400c2000, 0x901029c0, 0x82040480, 0x000001e4,
-	0x04021005, 0x42001000, 0x00000008, 0x801020c6,
-	0x0401f031, 0x82040480, 0x00000230, 0x04021009,
-	0x42001000, 0x00000007, 0x801000c2, 0x800000c2,
-	0x80100400, 0x80100400, 0x80102400, 0x0401f026,
-	0x82040480, 0x00000298, 0x04021008, 0x42001000,
-	0x00000006, 0x801000c2, 0x800000c2, 0x80100400,
-	0x80102400, 0x0401f01c, 0x82040480, 0x00000328,
-	0x04021007, 0x42001000, 0x00000005, 0x801000c2,
-	0x800000c2, 0x80102400, 0x0401f013, 0x82040480,
-	0x00000404, 0x04021005, 0x42001000, 0x00000004,
-	0x801020c4, 0x0401f00c, 0x82040480, 0x0000056c,
-	0x04021006, 0x42001000, 0x00000003, 0x801000c2,
-	0x80102400, 0x0401f004, 0x42001000, 0x00000002,
-	0x801020c2, 0x82100480, 0x00000110, 0x80000080,
-	0x80002000, 0x800800d0, 0x80140540, 0x80100540,
-	0x48039035, 0x1c01f000, 0x59c80815, 0x0201f800,
-	0x0010060d, 0x82040d00, 0x0000007c, 0x48079000,
-	0x59c80000, 0x80040500, 0x040207fe, 0x8c040d04,
-	0x04000003, 0x59c80035, 0x48039035, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x1c01f000,
-	0x4803c856, 0x497b88a9, 0x4a038807, 0x00000001,
-	0x497b8807, 0x59c40005, 0x48038805, 0x0201f800,
-	0x00101886, 0x4201d000, 0x000001f4, 0x0201f800,
-	0x00105dd2, 0x497b880e, 0x4200b000, 0x000001f4,
-	0x42000000, 0x00000001, 0x42000800, 0x00000014,
-	0x0201f800, 0x001019b1, 0x42000800, 0x00000014,
-	0x0201f800, 0x001019ac, 0x8c040d00, 0x04000005,
-	0x8058b040, 0x040207f3, 0x0201f800, 0x00100615,
-	0x4200b000, 0x00000032, 0x42000000, 0x00000001,
-	0x42000800, 0x000000b4, 0x0201f800, 0x001019b1,
-	0x42000800, 0x000000b4, 0x0201f800, 0x001019ac,
-	0x8c040d00, 0x04000005, 0x8058b040, 0x040207f3,
-	0x0201f800, 0x00100615, 0x59c40005, 0x48038805,
-	0x42000000, 0x00000089, 0x800008d0, 0x48075054,
-	0x48075055, 0x48075056, 0x42000800, 0x000000e0,
-	0x0201f800, 0x001019b1, 0x42000800, 0x000000f4,
-	0x0201f800, 0x001019ac, 0x82040500, 0xffffffd1,
-	0x82000540, 0x00000002, 0x42000800, 0x000000f4,
-	0x0201f800, 0x001019b1, 0x42000800, 0x000000a0,
-	0x0201f800, 0x001019ac, 0x82040540, 0x00000001,
-	0x42000800, 0x000000a0, 0x0201f800, 0x001019b1,
-	0x42000800, 0x00000000, 0x0201f800, 0x001019ac,
-	0x82040540, 0x00000001, 0x42000800, 0x00000000,
-	0x0201f800, 0x001019b1, 0x4201d000, 0x0001d4c0,
-	0x0201f800, 0x00105dd2, 0x0401fa45, 0x4a0388a7,
-	0x0000f7f7, 0x4a0388a3, 0x8000403c, 0x4a0388ae,
-	0x000061a8, 0x4a038801, 0x00032063, 0x4a038810,
-	0x00410108, 0x4a038811, 0x00520608, 0x4a038812,
-	0x00450320, 0x4a038813, 0x00440405, 0x4a03881c,
-	0x004132e1, 0x4a038850, 0x80000108, 0x4a038860,
-	0x00000008, 0x4a038870, 0x00000008, 0x4a038851,
-	0x80000508, 0x4a038861, 0x00800000, 0x4a038871,
-	0x00800000, 0x4a038852, 0x80000708, 0x4a038862,
-	0x00800000, 0x4a038872, 0x00800000, 0x4a038853,
-	0x80000608, 0x497b8863, 0x4a038873, 0x00800000,
-	0x4a038882, 0x00000840, 0x4a0388a5, 0x0000001e,
-	0x4a0388a6, 0x0000001e, 0x4a0388b0, 0x00007530,
-	0x4a038802, 0x0000ffff, 0x4a038806, 0xc0e00800,
-	0x1c01f000, 0x497b5022, 0x4a035021, 0x00000001,
-	0x42000800, 0x00000040, 0x0201f800, 0x001019ac,
-	0x82040500, 0xffffffaf, 0x82000540, 0x00000000,
-	0x42000800, 0x00000040, 0x0201f800, 0x001019b1,
-	0x42000800, 0x000000f4, 0x0201f800, 0x001019ac,
-	0x4c040000, 0x40040000, 0x84000548, 0x42000800,
-	0x000000f4, 0x0201f800, 0x001019b1, 0x42000800,
-	0x00000000, 0x0201f800, 0x001019ac, 0x82040500,
-	0xffffffc1, 0x82000540, 0x00000038, 0x42000800,
-	0x00000000, 0x0201f800, 0x001019b1, 0x5c000000,
-	0x42000800, 0x000000f4, 0x0201f000, 0x001019b1,
-	0x59c40805, 0x59c40006, 0x80040d00, 0x02000800,
-	0x00100615, 0x82040500, 0x00e00800, 0x04020004,
-	0x8c040d3e, 0x040208df, 0x0401f007, 0x82040500,
-	0x00800800, 0x02020800, 0x0010060d, 0x0201f800,
-	0x00100615, 0x4c5c0000, 0x4c600000, 0x59c4b805,
-	0x59c40006, 0x8c000500, 0x04000003, 0x8c5cbd00,
-	0x04020095, 0x485fc857, 0x0201f800, 0x00104e0d,
-	0x0400001e, 0x59c40005, 0x82000500, 0x000000c0,
-	0x0400004b, 0x0201f800, 0x00104e23, 0x04020048,
-	0x59c40006, 0x82000500, 0x000000f0, 0x04020004,
-	0x4a038805, 0x000000c0, 0x0401f041, 0x59a80015,
-	0x84000506, 0x48035015, 0x42006000, 0xff203fff,
-	0x42006800, 0x40000000, 0x0201f800, 0x001040ad,
-	0x42000800, 0x00000010, 0x42001000, 0x00104020,
-	0x0201f800, 0x00105dc7, 0x8c5cbd34, 0x04020030,
-	0x4a035032, 0x0000aaaa, 0x59c40005, 0x8c00050c,
-	0x04020012, 0x8c00050e, 0x0402001c, 0x8c00050a,
-	0x0402001d, 0x8c000508, 0x0400000b, 0x59a80017,
-	0x82000580, 0x00000009, 0x04020007, 0x42000000,
-	0x0010b642, 0x0201f800, 0x0010a86e, 0x0201f800,
-	0x00104fe9, 0x0401f05a, 0x0201f800, 0x00104e23,
-	0x04020007, 0x42000800, 0x0000000f, 0x42001000,
-	0x00103f37, 0x0201f800, 0x00105da7, 0x4a035033,
-	0x00000000, 0x0401f00b, 0x4a035033, 0x00000002,
-	0x0401f008, 0x42000000, 0x0010b644, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x00104f93, 0x0401f044,
-	0x0201f800, 0x00105049, 0x0401f041, 0x8c5cbd34,
-	0x0400003d, 0x59c40005, 0x8c00053a, 0x04020005,
-	0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e,
-	0x4a038805, 0x02000000, 0x0201f800, 0x00104e0d,
-	0x04020010, 0x4a038805, 0x04000000, 0x0201f800,
-	0x00104e1b, 0x04020008, 0x4a035033, 0x00000001,
-	0x4202d800, 0x00000001, 0x0201f800, 0x00104d76,
-	0x0401f061, 0x41780000, 0x0201f800, 0x00104de5,
-	0x0201f800, 0x00101a59, 0x4000c000, 0x0201f800,
-	0x001019d0, 0x836c1580, 0x00000004, 0x0402000d,
-	0x8c5cbd00, 0x04020018, 0x59a81005, 0x8c081506,
-	0x04020005, 0x59c410a3, 0x82081540, 0x00000008,
-	0x480b88a3, 0x59c41006, 0x84081540, 0x480b8806,
-	0x4a038805, 0x04000000, 0x4202d800, 0x00000001,
-	0x497b5014, 0x59a80005, 0x8c000518, 0x04020004,
-	0x0401f95c, 0x0201f800, 0x00103f5c, 0x0201f800,
-	0x00103951, 0x8c5cbd3c, 0x04020858, 0x8c5cbd00,
-	0x04000036, 0x42000000, 0x0010b6c9, 0x0201f800,
-	0x0010a86e, 0x4a038805, 0x00000001, 0x4200b000,
-	0x00000352, 0x4201d000, 0x00000064, 0x4c580000,
-	0x0201f800, 0x00105dd2, 0x0201f800, 0x00101941,
-	0x5c00b000, 0x04000004, 0x8058b040, 0x040207f6,
-	0x0401f004, 0x4a038805, 0x00000001, 0x0401f01f,
-	0x59c40006, 0x84000500, 0x48038806, 0x0201f800,
-	0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7,
-	0x59c4000d, 0x8c000500, 0x02020800, 0x0010a7f5,
-	0x59c400a3, 0x82000500, 0xfcf8ffff, 0x480388a3,
-	0x4a03504c, 0x00000002, 0x4202d800, 0x00000004,
-	0x4a038805, 0x00000001, 0x0201f800, 0x0010071a,
-	0x0401fb42, 0x497b5052, 0x4a035049, 0x00000001,
-	0x0201f800, 0x0010048c, 0x825cbd00, 0xbbfffffe,
-	0x485f8805, 0x5c00c000, 0x5c00b800, 0x1c01f000,
-	0x59c41004, 0x480bc857, 0x8c081500, 0x04000006,
-	0x4803c856, 0x497b2807, 0x0201f800, 0x00106cf9,
-	0x0401f00a, 0x82080500, 0x000001f0, 0x04000007,
-	0x4803c856, 0x417a3000, 0x0201f800, 0x00105d9b,
-	0x0201f800, 0x00106d1b, 0x4a038805, 0x80000000,
-	0x1c01f000, 0x59c408a3, 0x4807c857, 0x84040d40,
-	0x480788a3, 0x1c01f000, 0x4d900000, 0x4dd00000,
-	0x4da40000, 0x4d140000, 0x4a038805, 0x40000000,
-	0x42000000, 0x0010b6c5, 0x0201f800, 0x0010a86e,
-	0x0201f800, 0x0010698c, 0x59c41004, 0x8c081500,
-	0x04000054, 0x598e600d, 0x497b2807, 0x813261c0,
-	0x04000032, 0x59300403, 0x82000580, 0x00000032,
-	0x0402002e, 0x5930001c, 0x48038833, 0x4a038807,
-	0x00018000, 0x4201d000, 0x00000002, 0x0201f800,
-	0x00105dd2, 0x497b8807, 0x4201d000, 0x00000002,
-	0x0201f800, 0x00105dd2, 0x0201f800, 0x00106b71,
-	0x4201d000, 0x00007530, 0x0201f800, 0x00105dd2,
-	0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80,
-	0x00000000, 0x04000005, 0x42000000, 0x00200000,
-	0x0201f800, 0x001019b6, 0x0201f800, 0x001068f6,
-	0x59300008, 0x80000540, 0x02000800, 0x00100615,
-	0x40025800, 0x4a025a04, 0x00000103, 0x5931d821,
-	0x58ef400b, 0x58ec0009, 0x0801f800, 0x0201f800,
-	0x000208b4, 0x0401f047, 0x598c000f, 0x82001c80,
-	0x000000c8, 0x0402100f, 0x80000000, 0x4803180f,
-	0x59c400a4, 0x82000500, 0x0000000f, 0x82000580,
-	0x00000002, 0x04020004, 0x42000000, 0x00200000,
-	0x0401fbfa, 0x0201f800, 0x00105d86, 0x0401f035,
-	0x4933c857, 0x0201f800, 0x00106b71, 0x813261c0,
-	0x04000030, 0x4a026203, 0x00000001, 0x42027000,
-	0x00000027, 0x0201f800, 0x000208d8, 0x0401f029,
-	0x8c081508, 0x04000027, 0x417a3000, 0x0201f800,
-	0x00106e2f, 0x42032000, 0x0000bf32, 0x0201f800,
-	0x00105d9b, 0x59926004, 0x813261c0, 0x04000012,
-	0x42001800, 0x000000c8, 0x0201f800, 0x00106dfb,
-	0x0402000d, 0x59c400a4, 0x82000500, 0x0000000f,
-	0x82000580, 0x00000002, 0x04020004, 0x42000000,
-	0x00200000, 0x0401fbd1, 0x0201f800, 0x00105d8b,
-	0x0401f00c, 0x4933c857, 0x0201f800, 0x00106b13,
-	0x813261c0, 0x04000007, 0x42027000, 0x0000004f,
-	0x4a026203, 0x00000003, 0x0201f800, 0x000208d8,
-	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
-	0x0201f000, 0x00106982, 0x4803c857, 0x59a80821,
-	0x48035021, 0x80041580, 0x04000045, 0x800409c0,
-	0x04000023, 0x497b504c, 0x42000000, 0x0010b60b,
-	0x0201f800, 0x0010a86e, 0x0201f800, 0x0010a920,
-	0x42001000, 0x00008011, 0x59c40001, 0x82000500,
-	0x00018000, 0x82001d80, 0x00000000, 0x04000009,
-	0x82001d80, 0x00008000, 0x04000009, 0x82001d80,
-	0x00010000, 0x04000009, 0x0201f800, 0x00100615,
-	0x42001800, 0x00000000, 0x0401f006, 0x42001800,
-	0x00000001, 0x0401f003, 0x42001800, 0x00000003,
-	0x0201f800, 0x00103857, 0x0401f021, 0x59a8084c,
-	0x800409c0, 0x04020007, 0x59c4000d, 0x8c000520,
-	0x04000004, 0x42001800, 0x00000003, 0x0401f002,
-	0x40041800, 0x0201f800, 0x0010a904, 0x42001000,
-	0x00008012, 0x0201f800, 0x00103857, 0x0201f800,
-	0x0010071a, 0x0201f800, 0x0010a95a, 0x0402000c,
-	0x0401f853, 0x4d400000, 0x4d3c0000, 0x42028000,
-	0x00000028, 0x42027800, 0x00000008, 0x0201f800,
-	0x00101d90, 0x5c027800, 0x5c028000, 0x1c01f000,
-	0x4803c857, 0x82000400, 0x00101eb5, 0x50000800,
-	0x82040d00, 0x000000ff, 0x1c01f000, 0x4803c856,
-	0x4c580000, 0x4200b000, 0x00000010, 0x497b88ac,
-	0x497b88ad, 0x8058b040, 0x040207fe, 0x5c00b000,
-	0x1c01f000, 0x4807c857, 0x48075010, 0x80041108,
-	0x4200b000, 0x00000010, 0x497b88ac, 0x80000580,
-	0x800811c0, 0x04020006, 0x82040500, 0x0000000f,
-	0x82000400, 0x0010a95f, 0x50000000, 0x480388ad,
-	0x80081040, 0x8058b040, 0x040207f5, 0x1c01f000,
-	0x59a80005, 0x04000003, 0x84000546, 0x0401f002,
-	0x84000506, 0x48035005, 0x4803c857, 0x1c01f000,
-	0x4803c857, 0x4c080000, 0x4c040000, 0x4c000000,
-	0x59c40892, 0x4807c857, 0x80041580, 0x04000010,
-	0x80041480, 0x04021007, 0x80081080, 0x80081000,
-	0x4008b000, 0x42000000, 0x00000201, 0x0401f004,
-	0x4008b000, 0x42000000, 0x00000210, 0x48038886,
-	0x8058b040, 0x040207fe, 0x497b8886, 0x5c000000,
-	0x5c000800, 0x5c001000, 0x1c01f000, 0x4803c856,
-	0x0201f800, 0x0010393e, 0x04000005, 0x42028000,
-	0x0000002e, 0x0201f000, 0x0010a25b, 0x1c01f000,
-	0x59a8086f, 0x82040500, 0x00000010, 0x04000004,
-	0x42000800, 0x00000002, 0x0401f010, 0x82040500,
-	0x00000020, 0x42000800, 0x00000002, 0x0402000b,
-	0x59c80835, 0x82040d00, 0x00001f00, 0x80040910,
-	0x80040800, 0x59a8006c, 0x80000540, 0x04000003,
-	0x42000800, 0x0000025a, 0x4807c857, 0x1c01f000,
-	0x4c000000, 0x59a80053, 0x4803c857, 0x82000580,
-	0x00000000, 0x5c000000, 0x1c01f000, 0x4c000000,
-	0x59a80053, 0x4803c857, 0x82000580, 0x00000001,
-	0x5c000000, 0x1c01f000, 0x4c000000, 0x59a80053,
-	0x4803c857, 0x82000580, 0x00000003, 0x5c000000,
-	0x1c01f000, 0x4c000000, 0x59a80053, 0x82000580,
-	0x00000002, 0x5c000000, 0x1c01f000, 0x4c000000,
-	0x4c040000, 0x4c080000, 0x4c380000, 0x59a80040,
-	0x82000c80, 0x00000007, 0x02021800, 0x00100615,
-	0x0c01f806, 0x5c007000, 0x5c001000, 0x5c000800,
-	0x5c000000, 0x1c01f000, 0x001016dd, 0x001016f0,
-	0x00101704, 0x00101706, 0x0010172d, 0x0010172f,
-	0x00101731, 0x4803c856, 0x4a035042, 0x00000000,
-	0x42000000, 0x00000002, 0x0401fa18, 0x42000000,
-	0x00000002, 0x0401f9ad, 0x0401faae, 0x4803c856,
-	0x4a035040, 0x00000006, 0x42000800, 0x0000001e,
-	0x42001000, 0x00101732, 0x0201f000, 0x00105da7,
-	0x497b5045, 0x4a035050, 0x00000036, 0x4a03504f,
-	0x0000002a, 0x4803c856, 0x4a035042, 0x00000001,
-	0x42000000, 0x00000002, 0x0401f998, 0x4803c856,
-	0x4a035040, 0x00000006, 0x42000800, 0x0000001e,
-	0x42001000, 0x00101732, 0x0201f000, 0x00105da7,
-	0x0201f800, 0x00100615, 0x4a035050, 0x00000036,
-	0x4803c856, 0x4a035042, 0x00000003, 0x42000800,
-	0x00000000, 0x0401fa9f, 0x82040d00, 0x00000090,
-	0x82040580, 0x00000090, 0x04000009, 0x82040580,
-	0x00000010, 0x04000009, 0x82040580, 0x00000000,
-	0x04000008, 0x0201f800, 0x00100615, 0x42000000,
-	0x00000001, 0x0401f005, 0x41780000, 0x0401f003,
-	0x42000000, 0x00000002, 0x0401f970, 0x497b5046,
-	0x4803c856, 0x4a035040, 0x00000006, 0x42000800,
-	0x0000001e, 0x42001000, 0x00101732, 0x0201f000,
-	0x00105da7, 0x0201f800, 0x00100615, 0x0201f800,
-	0x00100615, 0x1c01f000, 0x4c000000, 0x4c040000,
-	0x4c080000, 0x4c380000, 0x59a80042, 0x82000c80,
-	0x00000007, 0x02021800, 0x00100615, 0x0c01f806,
-	0x5c007000, 0x5c001000, 0x5c000800, 0x5c000000,
-	0x1c01f000, 0x00101748, 0x00101767, 0x001017bb,
-	0x001017d2, 0x001017e9, 0x001017f2, 0x001017f4,
-	0x0401f9f9, 0x0402001b, 0x59a81048, 0x42000800,
-	0x00000000, 0x0401fa5f, 0x82040d00, 0x00000090,
-	0x82040580, 0x00000090, 0x04000009, 0x82040580,
-	0x00000010, 0x04000008, 0x82040580, 0x00000000,
-	0x04000007, 0x0201f800, 0x00100615, 0x84081540,
-	0x0401f004, 0x84081542, 0x0401f002, 0x84081544,
-	0x480b5048, 0x4a035040, 0x00000001, 0x0401f003,
-	0x0401f8cb, 0x0401ff82, 0x1c01f000, 0x0401f88f,
-	0x04000052, 0x0401f9d8, 0x0402002a, 0x42000800,
-	0x00000000, 0x0401fa3f, 0x82040d00, 0x00000090,
-	0x82040580, 0x00000000, 0x04000044, 0x82040580,
-	0x00000010, 0x04000006, 0x82040580, 0x00000090,
-	0x04000009, 0x0201f800, 0x00100615, 0x59c40801,
-	0x82040d00, 0x00018000, 0x82040580, 0x00000000,
-	0x04000036, 0x42000800, 0x00000000, 0x0401fa29,
-	0x82040d00, 0x00000090, 0x82040580, 0x00000010,
-	0x04000006, 0x82040580, 0x00000090, 0x04000006,
-	0x02020800, 0x00100615, 0x59a80048, 0x84000542,
-	0x0401f003, 0x59a80048, 0x84000540, 0x48035048,
-	0x59a80045, 0x80000000, 0x48035045, 0x82000580,
-	0x00000005, 0x04000003, 0x0401f861, 0x0401f01e,
-	0x497b5045, 0x59c40801, 0x82040d00, 0x00018000,
-	0x82040580, 0x00000000, 0x04000009, 0x82040580,
-	0x00008000, 0x04000009, 0x82040580, 0x00010000,
-	0x04000008, 0x0201f800, 0x00100615, 0x42000000,
-	0x00000001, 0x0401f005, 0x41780000, 0x0401f003,
-	0x42000000, 0x00000002, 0x0401f948, 0x4a035042,
-	0x00000002, 0x0401f004, 0x4a035040, 0x00000003,
-	0x0401f002, 0x0401ff42, 0x1c01f000, 0x0401f83b,
-	0x04000015, 0x59a8004f, 0x80000040, 0x4803504f,
-	0x0401f981, 0x04020005, 0x4a035040, 0x00000003,
-	0x497b5041, 0x0401f00c, 0x59a8004f, 0x80000540,
-	0x04020003, 0x0401f89e, 0x0401f002, 0x0401f84b,
-	0x0401f82f, 0x497b5045, 0x4a035042, 0x00000001,
-	0x0401ff2b, 0x1c01f000, 0x0401f824, 0x04000015,
-	0x0401f96d, 0x0402000f, 0x59a80046, 0x80000000,
-	0x48035046, 0x82000580, 0x00000007, 0x0402000c,
-	0x4a035052, 0x0000000a, 0x497b5049, 0x59a80048,
-	0x8400055e, 0x48035048, 0x4803c857, 0x0401f005,
-	0x0401f817, 0x4a035042, 0x00000004, 0x0401ff3d,
-	0x1c01f000, 0x0401f80d, 0x04000007, 0x0401f956,
-	0x04020003, 0x0401ff1b, 0x0401f003, 0x0401f80c,
-	0x0401ff34, 0x1c01f000, 0x0201f800, 0x00100615,
-	0x0201f800, 0x00100615, 0x59a80050, 0x80000040,
-	0x48035050, 0x0400088d, 0x1c01f000, 0x4c040000,
-	0x42000800, 0x00000000, 0x0401f9ae, 0x82040d00,
-	0x00000090, 0x82040580, 0x00000090, 0x04000009,
-	0x82040580, 0x00000010, 0x04000009, 0x82040580,
-	0x00000000, 0x04000009, 0x0201f800, 0x00100615,
-	0x42000000, 0x00000002, 0x0401f005, 0x42000000,
-	0x00000001, 0x0401f002, 0x41780000, 0x0401f8e7,
-	0x5c000800, 0x1c01f000, 0x4c040000, 0x59c40801,
-	0x82040d00, 0x00018000, 0x82040580, 0x00000000,
-	0x04000009, 0x82040580, 0x00008000, 0x04000009,
-	0x82040580, 0x00010000, 0x04000009, 0x0201f800,
-	0x00100615, 0x42000000, 0x00000002, 0x0401f005,
-	0x42000000, 0x00000001, 0x0401f002, 0x41780000,
-	0x0401f866, 0x5c000800, 0x1c01f000, 0x4c040000,
-	0x59a80045, 0x80000000, 0x48035045, 0x82000580,
-	0x00000005, 0x04020018, 0x497b5045, 0x59c40801,
-	0x82040d00, 0x00018000, 0x82040580, 0x00000000,
-	0x04000009, 0x82040580, 0x00008000, 0x04000009,
-	0x82040580, 0x00010000, 0x04000009, 0x0201f800,
-	0x00100615, 0x42000000, 0x00000002, 0x0401f005,
-	0x42000000, 0x00000001, 0x0401f002, 0x41780000,
-	0x0401f846, 0x42000800, 0x00000000, 0x0401f95d,
-	0x82040d00, 0x00000090, 0x82040580, 0x00000090,
-	0x04000009, 0x82040580, 0x00000010, 0x04000009,
-	0x82040580, 0x00000000, 0x04000009, 0x0201f800,
-	0x00100615, 0x42000000, 0x00000002, 0x0401f005,
-	0x42000000, 0x00000001, 0x0401f002, 0x41780000,
-	0x0401f896, 0x5c000800, 0x1c01f000, 0x4c200000,
-	0x59a80048, 0x82000500, 0x00007fff, 0x02000800,
-	0x00100615, 0x59a84047, 0x80204102, 0x02001800,
-	0x00100615, 0x48235047, 0x80204500, 0x040007fa,
-	0x8c000504, 0x04020007, 0x8c000502, 0x04020008,
-	0x8c000500, 0x04020008, 0x0201f800, 0x00100615,
-	0x42000000, 0x00000002, 0x0401f005, 0x41780000,
-	0x0401f003, 0x42000000, 0x00000001, 0x0401f80f,
-	0x5c004000, 0x1c01f000, 0x04011000, 0x4a03c840,
-	0x0010b240, 0x4a03c842, 0x00000009, 0x40000000,
-	0x040117ff, 0x4a035047, 0x00000004, 0x4a03503e,
-	0x00000000, 0x1c01f000, 0x59a80858, 0x82040d80,
-	0x01391077, 0x04020008, 0x59e00813, 0x8c040d00,
-	0x04000005, 0x82000d80, 0x00000002, 0x04020002,
-	0x41780000, 0x800001c0, 0x04000040, 0x82000d80,
-	0x00000001, 0x0402001d, 0x42000800, 0x000000a0,
-	0x0401f908, 0x82040540, 0x00000004, 0x42000800,
-	0x000000a0, 0x0401f908, 0x42000800, 0x000000c0,
-	0x0401f900, 0x82040540, 0x00000020, 0x42000800,
-	0x000000c0, 0x0401f900, 0x59c40001, 0x82000500,
-	0xfffe7fff, 0x82000540, 0x00000000, 0x48038801,
-	0x59a80054, 0x80000110, 0x42000800, 0x000000e0,
-	0x0401f8f5, 0x0401f03c, 0x82000d80, 0x00000002,
-	0x02020800, 0x00100615, 0x42000800, 0x000000a0,
-	0x0401f8e8, 0x82040500, 0xfffffffb, 0x42000800,
-	0x000000a0, 0x0401f8e8, 0x42000800, 0x000000c0,
-	0x0401f8e0, 0x82040500, 0xffffffdf, 0x42000800,
-	0x000000c0, 0x0401f8e0, 0x59c40001, 0x82000500,
-	0xfffe7fff, 0x82000540, 0x00010000, 0x48038801,
-	0x59a80056, 0x80000110, 0x42000800, 0x000000e0,
-	0x0401f8d5, 0x0401f01c, 0x42000800, 0x000000a0,
-	0x0401f8cc, 0x82040540, 0x00000004, 0x42000800,
-	0x000000a0, 0x0401f8cc, 0x42000800, 0x000000c0,
-	0x0401f8c4, 0x82040500, 0xffffffdf, 0x42000800,
-	0x000000c0, 0x0401f8c4, 0x59c40001, 0x82000500,
-	0xfffe7fff, 0x82000540, 0x00008000, 0x48038801,
-	0x59a80055, 0x80000110, 0x42000800, 0x000000e0,
-	0x0401f8b9, 0x1c01f000, 0x4803c857, 0x59a80858,
-	0x82040d80, 0x01391077, 0x04020008, 0x59e00813,
-	0x8c040d00, 0x04000005, 0x82000d80, 0x00000002,
-	0x04020002, 0x41780000, 0x4c000000, 0x0401f942,
-	0x5c000000, 0x800001c0, 0x04000026, 0x82000d80,
-	0x00000001, 0x04020010, 0x59a8006c, 0x80000540,
-	0x04000004, 0x42001000, 0x00000000, 0x0401f9f7,
-	0x42000800, 0x00000000, 0x0401f896, 0x82040540,
-	0x00000090, 0x42000800, 0x00000000, 0x0401f896,
-	0x0401f024, 0x82000d80, 0x00000002, 0x02020800,
-	0x00100615, 0x59a8006c, 0x80000540, 0x04000004,
-	0x42001000, 0x00010000, 0x0401f9e4, 0x42000800,
-	0x00000000, 0x0401f883, 0x82040500, 0xffffff6f,
-	0x42000800, 0x00000000, 0x0401f883, 0x0401f011,
-	0x59a8006c, 0x80000540, 0x04000004, 0x42001000,
-	0x00008000, 0x0401f9d5, 0x42000800, 0x00000000,
-	0x0401f874, 0x82040500, 0xffffff6f, 0x82000540,
-	0x00000010, 0x42000800, 0x00000000, 0x0401f872,
-	0x0401f111, 0x4c580000, 0x4200b000, 0x00000014,
-	0x8058b040, 0x04000042, 0x59c4000d, 0x8c000520,
-	0x040207fc, 0x0401f85b, 0x59c4000d, 0x8c000520,
-	0x040207f8, 0x59c40808, 0x84040d50, 0x48078808,
-	0x4200b000, 0x000000c8, 0x8058b040, 0x040207ff,
-	0x4200b000, 0x00000014, 0x8058b040, 0x04000030,
-	0x59c4000d, 0x8c000520, 0x0402002d, 0x42000800,
-	0x00001000, 0x50040800, 0x82040c80, 0x24220001,
-	0x04020003, 0x8c000504, 0x040007f4, 0x0401f841,
-	0x59c4000d, 0x8c000520, 0x04020021, 0x42000800,
-	0x00001000, 0x50040800, 0x82040c80, 0x24220001,
-	0x04020003, 0x8c000504, 0x040007e8, 0x4200b000,
-	0x0000000a, 0x8058b040, 0x04000003, 0x0401f831,
-	0x0401f7fd, 0x4200b000, 0x00000064, 0x59c4000d,
-	0x8c00051e, 0x0400000e, 0x8058b040, 0x040207fc,
-	0x42000000, 0x00001000, 0x50000000, 0x82000480,
-	0x24220001, 0x04020004, 0x59c40808, 0x84040d10,
-	0x48078808, 0x80000580, 0x0401f00c, 0x42000000,
-	0x00001000, 0x50000000, 0x82000480, 0x24220001,
-	0x04020004, 0x59c40808, 0x84040d10, 0x48078808,
-	0x82000540, 0x00000001, 0x5c00b000, 0x1c01f000,
-	0x42000800, 0x000000a0, 0x0401f816, 0x82040500,
-	0xfffffffe, 0x42000800, 0x000000a0, 0x0401f816,
-	0x42000800, 0x00000000, 0x0401f80e, 0x82040500,
-	0xfffffffe, 0x42000800, 0x00000000, 0x0401f00e,
-	0x40000000, 0x40000000, 0x40000000, 0x40000000,
-	0x40000000, 0x1c01f000, 0x480b8805, 0x1c01f000,
-	0x4807880e, 0x59c4080f, 0x82040d00, 0x000000ff,
-	0x1c01f000, 0x900001c0, 0x80040d40, 0x84040d40,
-	0x4807880e, 0x1c01f000, 0x82000d80, 0x00200000,
-	0x04000009, 0x82000d80, 0x02000000, 0x04000006,
-	0x82000d80, 0x01000000, 0x04000006, 0x59c408a3,
-	0x0401f006, 0x59c408a3, 0x84040d30, 0x0401f003,
-	0x59c408a3, 0x84040d32, 0x80040540, 0x480388a3,
-	0x480788a3, 0x1c01f000, 0x59c400a3, 0x84000556,
-	0x480388a3, 0x84000516, 0x480388a3, 0x1c01f000,
-	0x485fc857, 0x4863c857, 0x4c640000, 0x4d3c0000,
-	0x4d400000, 0x0201f800, 0x00106c32, 0x4863500a,
-	0x0201f800, 0x0010a95a, 0x0402006a, 0x82600d00,
-	0x0000ff00, 0x800409c0, 0x0400000c, 0x4200c800,
-	0x00000001, 0x59a80010, 0x82000500, 0x000000ff,
-	0x80041110, 0x80081580, 0x04000021, 0x82041580,
-	0x0000ff00, 0x0400000a, 0x59c410a3, 0x82081500,
-	0x00008000, 0x04000009, 0x59c410a7, 0x82081500,
-	0x0000ff00, 0x82081580, 0x0000ff00, 0x4200c800,
-	0x00000000, 0x04000012, 0x59a80005, 0x8c000502,
-	0x04020008, 0x8c000500, 0x0402000d, 0x599c1017,
-	0x8c08151a, 0x0400003c, 0x84000542, 0x48035005,
-	0x4200c800, 0x00000002, 0x42028000, 0x00000004,
-	0x42027800, 0x00000008, 0x0401f007, 0x59a80805,
-	0x84040d40, 0x48075005, 0x42028000, 0x00000004,
-	0x417a7800, 0x59a80006, 0x8c000502, 0x04020006,
-	0x59a80805, 0x8c040d0a, 0x04020032, 0x84040d4a,
-	0x48075005, 0x42000000, 0x0010b610, 0x0201f800,
-	0x0010a86e, 0x59a8180a, 0x42001000, 0x00008013,
-	0x0201f800, 0x00103857, 0x0201f800, 0x0010393e,
-	0x04000015, 0x4d400000, 0x82600500, 0x000000ff,
-	0x42028800, 0x0000ffff, 0x40643000, 0x42028000,
-	0x0000000e, 0x0201f800, 0x0010a258, 0x42000800,
-	0x00000001, 0x42001000, 0x00000100, 0x0201f800,
-	0x00105ec4, 0x5c028000, 0x599c0817, 0x8c040d0a,
-	0x04020010, 0x493fc857, 0x4943c857, 0x0401fb59,
-	0x0401f00c, 0x0201f800, 0x0010393e, 0x04000009,
-	0x42028000, 0x0000000f, 0x42028800, 0x0000ffff,
-	0x42003000, 0x00000000, 0x0201f800, 0x0010a25b,
-	0x497b8880, 0x5c028000, 0x5c027800, 0x5c00c800,
-	0x1c01f000, 0x42000800, 0x00000000, 0x0401ff61,
-	0x82040540, 0x00000002, 0x42000800, 0x00000000,
-	0x0401f761, 0x42000800, 0x00000000, 0x0401ff59,
-	0x82040500, 0xfffffffd, 0x42000800, 0x00000000,
-	0x0401f759, 0x59c408a8, 0x0401ff4a, 0x0401ff49,
-	0x59c400a8, 0x80040d80, 0x040207fb, 0x1c01f000,
-	0x4803c856, 0x4a038807, 0x00000001, 0x497b8807,
-	0x59c40005, 0x48038805, 0x497b506c, 0x497b506d,
-	0x41785800, 0x42006000, 0x00000001, 0x42006800,
-	0x00000003, 0x0401f824, 0x0401f82f, 0x40400000,
-	0x4803c857, 0x82408580, 0x00000000, 0x0402001d,
-	0x41785800, 0x42006000, 0x0000001e, 0x42006800,
-	0x00000014, 0x0401f818, 0x0401f823, 0x40400000,
-	0x4803c857, 0x82408580, 0x00000800, 0x04020011,
-	0x42005800, 0x00000001, 0x42006000, 0x0000001e,
-	0x42006800, 0x00000014, 0x0401f80b, 0x0401f816,
-	0x40400000, 0x4803c857, 0x82408580, 0x0000ffff,
-	0x04020004, 0x4a03506c, 0x00000001, 0x4803c856,
-	0x1c01f000, 0x41785000, 0x0401f812, 0x0401f838,
-	0x40347000, 0x40340800, 0x0401f03d, 0x42005000,
-	0x00000001, 0x0401f80b, 0x0401f831, 0x40340800,
-	0x0401f037, 0x42005000, 0x00000002, 0x0401f805,
-	0x0401f81d, 0x0401f835, 0x40048000, 0x1c01f000,
-	0x0401f808, 0x0401f814, 0x40280800, 0x0401f826,
-	0x402c0800, 0x0401f827, 0x40300800, 0x0401f025,
-	0x42000800, 0x0000ffff, 0x42001000, 0x00000001,
-	0x0401f829, 0x42001000, 0x00000010, 0x0401f826,
-	0x42000800, 0x0000ffff, 0x42001000, 0x00000010,
-	0x0401f021, 0x41780800, 0x42001000, 0x00000002,
-	0x0401f01d, 0x0401f92e, 0x4a03d000, 0x00050004,
-	0x0401f92b, 0x4a03d000, 0x00050005, 0x0401f928,
-	0x4a03d000, 0x00050004, 0x42000800, 0x00000001,
-	0x42001000, 0x00000001, 0x0401f00f, 0x42000800,
-	0x00000002, 0x42001000, 0x00000002, 0x0401f00a,
-	0x42001000, 0x00000005, 0x0401f007, 0x42001000,
-	0x00000010, 0x0401f004, 0x42001000, 0x00000010,
-	0x0401f01b, 0x0401f912, 0x82082c00, 0x0010a95f,
-	0x50142800, 0x82081500, 0xffffffff, 0x04000013,
-	0x0401f90b, 0x80081040, 0x80142902, 0x40040000,
-	0x80140500, 0x04000007, 0x4a03d000, 0x00070006,
-	0x0401f903, 0x4a03d000, 0x00070007, 0x0401f006,
-	0x4a03d000, 0x00070004, 0x0401f8fd, 0x4a03d000,
-	0x00070005, 0x0401f7ec, 0x1c01f000, 0x41780800,
-	0x82082c00, 0x0010a95f, 0x50142800, 0x82081500,
-	0xffffffff, 0x04000010, 0x0401f8f1, 0x4a03d000,
-	0x00050001, 0x0401f8ee, 0x59e81800, 0x80081040,
-	0x80142902, 0x8c0c1d06, 0x04000004, 0x40140000,
-	0x80040d40, 0x0401f8e6, 0x4a03d000, 0x00070000,
-	0x0401f7ef, 0x1c01f000, 0x480bc857, 0x480b506d,
-	0x59c40001, 0x82000500, 0xffffefff, 0x48038801,
-	0x41781800, 0x0401f8c4, 0x41785800, 0x42006000,
-	0x0000001e, 0x42006800, 0x00000004, 0x0401ff7a,
-	0x42006800, 0x0000003c, 0x0401ff7d, 0x41785800,
-	0x42006000, 0x0000001e, 0x42006800, 0x00000004,
-	0x0401ff71, 0x41786800, 0x0401ff75, 0x41785800,
-	0x42006000, 0x0000001e, 0x41786800, 0x0401ff6a,
-	0x42006800, 0x00000002, 0x0401ff6d, 0x42006800,
-	0x00000001, 0x0401ff64, 0x42006800, 0x000000f5,
-	0x0401ff67, 0x41785800, 0x42006000, 0x0000001e,
-	0x42006800, 0x00000004, 0x0401ff5b, 0x42006800,
-	0x00000020, 0x0401ff5e, 0x59a8106d, 0x0401f865,
-	0x42001800, 0x000200f5, 0x0401f897, 0x59a8106d,
-	0x0401f879, 0x41785800, 0x42006000, 0x0000001e,
-	0x42006800, 0x00000004, 0x0401ff4b, 0x41786800,
-	0x0401ff4f, 0x59c40001, 0x82000540, 0x00001000,
-	0x48038801, 0x41785800, 0x42006000, 0x0000001e,
-	0x42006800, 0x00000015, 0x0401ff3f, 0x0401ff4a,
-	0x40400000, 0x82000540, 0x00000002, 0x4c000000,
-	0x41785800, 0x42006000, 0x0000001e, 0x42006800,
-	0x00000015, 0x0401ff34, 0x5c000000, 0x40006800,
-	0x0401ff37, 0x41785800, 0x42006000, 0x0000001e,
-	0x42006800, 0x00000015, 0x0401ff2b, 0x0401ff36,
-	0x40400000, 0x82000500, 0x0000fffd, 0x4c000000,
-	0x41785800, 0x42006000, 0x0000001e, 0x42006800,
-	0x00000015, 0x0401ff20, 0x5c000000, 0x40006800,
-	0x0401ff23, 0x41785800, 0x42006000, 0x0000001e,
-	0x42006800, 0x00000014, 0x0401ff17, 0x0401ff22,
-	0x40400000, 0x82000540, 0x00000040, 0x4c000000,
-	0x41785800, 0x42006000, 0x0000001e, 0x42006800,
-	0x00000014, 0x0401ff0c, 0x5c000000, 0x40006800,
-	0x0401ff0f, 0x41785800, 0x42006000, 0x0000001e,
-	0x42006800, 0x00000014, 0x0401ff03, 0x0401ff0e,
-	0x40400000, 0x82000500, 0x0000ffbf, 0x4c000000,
-	0x41785800, 0x42006000, 0x0000001e, 0x42006800,
-	0x00000014, 0x0401fef8, 0x5c000000, 0x40006800,
-	0x0401fefb, 0x4a038886, 0x00002020, 0x0401f04c,
-	0x480bc857, 0x82080580, 0x00010000, 0x04020007,
-	0x82040d40, 0x00010000, 0x42001800, 0x00000001,
-	0x0401f82d, 0x0401f00f, 0x82080580, 0x00008000,
-	0x04000007, 0x82040d40, 0x00000000, 0x42001800,
-	0x00900001, 0x0401f824, 0x0401f006, 0x82040d40,
-	0x00008000, 0x42001800, 0x00100001, 0x0401f81e,
-	0x1c01f000, 0x480bc857, 0x82080580, 0x00010000,
-	0x04020008, 0x42001800, 0x000000a1, 0x0401f816,
-	0x42001800, 0x000000c1, 0x0401f813, 0x0401f011,
-	0x82080580, 0x00008000, 0x04000008, 0x42001800,
-	0x000400a1, 0x0401f80c, 0x42001800, 0x002000c1,
-	0x0401f809, 0x0401f007, 0x42001800, 0x000400a1,
-	0x0401f805, 0x42001800, 0x000000c1, 0x0401f802,
-	0x1c01f000, 0x480fc857, 0x41785800, 0x42006000,
-	0x0000001e, 0x41786800, 0x0401feb7, 0x400c6800,
-	0x80346960, 0x0401feba, 0x42006800, 0x00000001,
-	0x0401feb1, 0x400c6800, 0x0401feb5, 0x42006800,
-	0x00000003, 0x0401feac, 0x0401feb7, 0x40400000,
-	0x8c000504, 0x040207fc, 0x1c01f000, 0x42000000,
-	0x00000064, 0x80000040, 0x040207ff, 0x1c01f000,
-	0x4c5c0000, 0x4c600000, 0x4178b800, 0x0201f800,
-	0x0010473b, 0x040200fd, 0x59a8c026, 0x0201f800,
-	0x00104e0d, 0x04000003, 0x8c60c506, 0x0400000e,
-	0x8c60c500, 0x04020004, 0x8c60c50e, 0x040008f6,
-	0x0401f0f2, 0x0401faaf, 0x040200f0, 0x0201f800,
-	0x00104e0d, 0x04020004, 0x4a03501c, 0x0000ffff,
-	0x0401f0ea, 0x8c60c504, 0x04000004, 0x4a03501c,
-	0x0000ffff, 0x0401f0e5, 0x59a8c010, 0x8260c500,
-	0x000000ff, 0x59a81013, 0x8c081500, 0x0400005d,
-	0x8c081502, 0x0402005b, 0x59a8b81c, 0x825c0d80,
-	0x0000ffff, 0x04020003, 0x4200b800, 0x00000001,
-	0x805c1104, 0x82086400, 0x0010bc20, 0x50300800,
-	0x825c0500, 0x00000003, 0x0c01f001, 0x00101c2c,
-	0x00101c27, 0x00101c2b, 0x00101c29, 0x80040910,
-	0x0401f004, 0x80040930, 0x0401f002, 0x80040920,
-	0x82040500, 0x000000ff, 0x82000d80, 0x000000ff,
-	0x0400000f, 0x4c000000, 0x82000400, 0x00101eb5,
-	0x50000800, 0x80040910, 0x82040580, 0x00000080,
-	0x5c000000, 0x04000030, 0x80600d80, 0x0400002e,
-	0x80000540, 0x0400002c, 0x0401f00b, 0x59a81005,
-	0x82081500, 0x00000003, 0x0402002b, 0x59a81013,
-	0x84081542, 0x480b5013, 0x4a03501c, 0x0000ffff,
-	0x0401f028, 0x4c000000, 0x59a8006f, 0x8c000502,
-	0x42001000, 0x00000010, 0x02020800, 0x00104ada,
-	0x5c000000, 0x0402001c, 0x417a8800, 0x0201f800,
-	0x001059b9, 0x04020016, 0x0201f800, 0x0010443b,
-	0x04000006, 0x0201f800, 0x00104acf, 0x0401f8b1,
-	0x0400000f, 0x0401f00c, 0x599c0019, 0x8c00050e,
-	0x04020009, 0x0201f800, 0x001043fc, 0x04020008,
-	0x0201f800, 0x00104acf, 0x0401f9dd, 0x0401f8be,
-	0x04000003, 0x805cb800, 0x0401f7b2, 0x485f501c,
-	0x0401f086, 0x4a03501c, 0x0000ffff, 0x0401f083,
-	0x42003000, 0x0000007e, 0x59a8001c, 0x82001580,
-	0x0000ffff, 0x04020005, 0x80000d80, 0x4018b000,
-	0x4803c856, 0x0401f009, 0x8018b480, 0x04001004,
-	0x40000800, 0x4803c856, 0x0401f004, 0x4a03501c,
-	0x0000ffff, 0x0401f071, 0x4c040000, 0x4c580000,
-	0x82040400, 0x00101eb5, 0x50000000, 0x82000500,
-	0x000000ff, 0x80604580, 0x0400005c, 0x0201f800,
-	0x001059ba, 0x04020061, 0x59a8006f, 0x8c000502,
-	0x42001000, 0x00000010, 0x02020800, 0x00104ada,
-	0x5c00b000, 0x5c000800, 0x040207d7, 0x4c040000,
-	0x4c580000, 0x845cbd00, 0x0201f800, 0x00020267,
-	0x04000008, 0x599c0019, 0x8c00050e, 0x04020047,
-	0x0201f800, 0x00104401, 0x0402004c, 0x0401f002,
-	0x845cbd40, 0x0201f800, 0x00104acf, 0x0201f800,
-	0x00104836, 0x04020007, 0x59a80005, 0x8c000502,
-	0x04000033, 0x59340200, 0x8c00050e, 0x04020030,
-	0x59a81013, 0x8c081502, 0x04000025, 0x0201f800,
-	0x00104858, 0x04000031, 0x8c5cbd00, 0x04020004,
-	0x0201f800, 0x00104455, 0x0401f02c, 0x0401f9c8,
-	0x0400002a, 0x42026000, 0x0010bbe8, 0x49366009,
-	0x497a6008, 0x417a7800, 0x0401f920, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800,
-	0x0010393e, 0x0400001d, 0x41782800, 0x42003000,
-	0x00000008, 0x4d400000, 0x4d440000, 0x59368c03,
-	0x42028000, 0x00000029, 0x0201f800, 0x0010a258,
-	0x5c028800, 0x5c028000, 0x0401f010, 0x4937c857,
-	0x599c0019, 0x8c00050e, 0x0402000c, 0x0401f968,
-	0x0401f849, 0x04000011, 0x0401f008, 0x59a80013,
-	0x8c000500, 0x04000003, 0x0401f9a1, 0x04000003,
-	0x0401f828, 0x04000009, 0x5c00b000, 0x5c000800,
-	0x80040800, 0x8058b040, 0x04020798, 0x4a03501c,
-	0x0000ffff, 0x0401f005, 0x4937c857, 0x5c00b000,
-	0x5c000800, 0x4807501c, 0x5c00c000, 0x5c00b800,
-	0x1c01f000, 0x4803c856, 0x4a03501c, 0x00000001,
-	0x42028800, 0x000007fe, 0x42003000, 0x00fffffe,
-	0x0201f800, 0x001043fc, 0x0402000c, 0x0401f944,
-	0x0401f825, 0x04000009, 0x59a80026, 0x8400054e,
-	0x48035026, 0x0201f800, 0x001090d5, 0x82000540,
-	0x00000001, 0x1c01f000, 0x80000580, 0x0401f7fe,
-	0x4937c857, 0x0201f800, 0x001076c9, 0x04000015,
-	0x49366009, 0x4a026406, 0x00000001, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x59a8001b, 0x80000000,
-	0x4803501b, 0x42027000, 0x00000004, 0x599c0019,
-	0x8c00050e, 0x04000003, 0x42027000, 0x00000000,
-	0x0201f800, 0x000208d8, 0x82000540, 0x00000001,
-	0x1c01f000, 0x4937c857, 0x0201f800, 0x001076c9,
-	0x0400001c, 0x49366009, 0x59340403, 0x82000580,
-	0x000007fe, 0x04000005, 0x4d3c0000, 0x417a7800,
-	0x0401f8b2, 0x5c027800, 0x4a026406, 0x00000001,
-	0x417a7800, 0x0201f800, 0x001043bd, 0x42000800,
-	0x00000003, 0x0201f800, 0x001043c7, 0x59a8001b,
-	0x80000000, 0x4803501b, 0x42027000, 0x00000002,
-	0x0201f800, 0x000208d8, 0x82000540, 0x00000001,
-	0x1c01f000, 0x4803c856, 0x42028800, 0x000007fc,
-	0x42003000, 0x00fffffc, 0x0201f800, 0x001043fc,
-	0x04020005, 0x0401f805, 0x04000003, 0x4a035027,
-	0x0000ffff, 0x1c01f000, 0x4937c857, 0x0201f800,
-	0x001076c9, 0x04000014, 0x49366009, 0x4a026406,
-	0x00000001, 0x417a7800, 0x0201f800, 0x001043bd,
-	0x42000800, 0x00000003, 0x0201f800, 0x001043c7,
-	0x59a80028, 0x80000000, 0x48035028, 0x42027000,
-	0x00000002, 0x0201f800, 0x000208d8, 0x82000540,
-	0x00000001, 0x1c01f000, 0x480bc857, 0x492fc857,
-	0x4c5c0000, 0x4008b800, 0x42028800, 0x000007fd,
-	0x42003000, 0x00fffffd, 0x0201f800, 0x001043fc,
-	0x0402001a, 0x0201f800, 0x00020892, 0x04000017,
-	0x49366009, 0x5934000a, 0x84000544, 0x4802680a,
-	0x812e59c0, 0x04000005, 0x592c0404, 0x8c00051e,
-	0x04000002, 0x48ee6021, 0x492e6008, 0x4a026406,
-	0x00000001, 0x485e601c, 0x42027000, 0x00000022,
-	0x0201f800, 0x000208d8, 0x82000540, 0x00000001,
-	0x5c00b800, 0x1c01f000, 0x80000580, 0x0401f7fd,
-	0x5c000000, 0x4c000000, 0x4803c857, 0x4943c857,
-	0x493fc857, 0x4d340000, 0x4d440000, 0x4c580000,
-	0x4d2c0000, 0x4c5c0000, 0x0201f800, 0x0010698c,
-	0x4df00000, 0x0201f800, 0x0010673a, 0x0201f800,
-	0x001067ee, 0x0201f800, 0x0010647f, 0x0201f800,
-	0x0010822b, 0x5c03e000, 0x02000800, 0x00106982,
-	0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800,
-	0x00020267, 0x0402001a, 0x8d3e7d06, 0x04000004,
-	0x59340200, 0x8c00050e, 0x04020015, 0x8d3e7d18,
-	0x04000010, 0x5934b80f, 0x805cb9c0, 0x04000009,
-	0x49425a06, 0x592cb800, 0x0201f800, 0x00020381,
-	0x805cb9c0, 0x040207fb, 0x497a680f, 0x497a6810,
-	0x4937c857, 0x4a026c00, 0x00000707, 0x0401f004,
-	0x4937c857, 0x0201f800, 0x001040e4, 0x81468800,
-	0x8058b040, 0x040207e2, 0x8d3e7d02, 0x04000011,
-	0x497b501d, 0x42028800, 0x000007f0, 0x4200b000,
-	0x00000010, 0x0201f800, 0x00020267, 0x04020006,
-	0x4937c857, 0x4a026c00, 0x00000707, 0x0201f800,
-	0x001040e4, 0x81468800, 0x8058b040, 0x040207f6,
-	0x5c00b800, 0x5c025800, 0x5c00b000, 0x5c028800,
-	0x5c026800, 0x1c01f000, 0x5c000000, 0x4c000000,
-	0x4803c857, 0x4933c857, 0x493fc857, 0x4d340000,
-	0x4d400000, 0x4d440000, 0x4d2c0000, 0x4c5c0000,
-	0x0201f800, 0x0010698c, 0x4df00000, 0x59326809,
-	0x813669c0, 0x04000021, 0x59368c03, 0x42028000,
-	0x00000029, 0x0201f800, 0x0010679b, 0x0201f800,
-	0x001067f6, 0x0201f800, 0x00106543, 0x0201f800,
-	0x0010a0da, 0x4937c857, 0x8d3e7d18, 0x04000011,
-	0x5934b80f, 0x805cb9c0, 0x0400000a, 0x405e5800,
-	0x49425a06, 0x592cb800, 0x0201f800, 0x00020381,
-	0x805cb9c0, 0x040207fa, 0x497a680f, 0x497a6810,
-	0x4937c857, 0x4a026c00, 0x00000707, 0x0401f003,
-	0x0201f800, 0x001040e4, 0x5c03e000, 0x02000800,
-	0x00106982, 0x5c00b800, 0x5c025800, 0x5c028800,
-	0x5c028000, 0x5c026800, 0x1c01f000, 0x4933c857,
-	0x59a80026, 0x8c000508, 0x04020012, 0x59305009,
-	0x482bc857, 0x836c0580, 0x00000002, 0x0402000d,
-	0x0401f813, 0x0402000b, 0x58280403, 0x82000580,
-	0x000007fc, 0x04000008, 0x59a8001b, 0x80000040,
-	0x4803c857, 0x02001800, 0x00100615, 0x4803501b,
-	0x1c01f000, 0x59a80028, 0x80000040, 0x4803c857,
-	0x040017fc, 0x48035028, 0x1c01f000, 0x59300008,
-	0x800001c0, 0x04020009, 0x59300403, 0x82000580,
-	0x00000001, 0x04020004, 0x82000540, 0x00000001,
-	0x0401f002, 0x80000580, 0x1c01f000, 0x4937c857,
-	0x59340200, 0x84000502, 0x48026a00, 0x1c01f000,
-	0x4933c857, 0x493fc857, 0x4947c857, 0x4d400000,
-	0x4d340000, 0x4d440000, 0x4c580000, 0x0201f800,
-	0x0010698c, 0x4df00000, 0x8060c1c0, 0x04020004,
-	0x4200b000, 0x00000001, 0x0401f004, 0x4200b000,
-	0x000007f0, 0x417a8800, 0x41440000, 0x81ac0400,
-	0x50000000, 0x80026d40, 0x0400001a, 0x4d3c0000,
-	0x42027800, 0x00000001, 0x0201f800, 0x00104745,
-	0x5c027800, 0x42028000, 0x00000029, 0x0201f800,
-	0x0010679b, 0x0201f800, 0x001067f6, 0x0201f800,
-	0x00106543, 0x0201f800, 0x00104836, 0x04020005,
-	0x4937c857, 0x4a026c00, 0x00000404, 0x0401f003,
-	0x0201f800, 0x00104863, 0x0201f800, 0x0010a0da,
-	0x81468800, 0x8058b040, 0x040207e0, 0x5c03e000,
-	0x02000800, 0x00106982, 0x5c00b000, 0x5c028800,
-	0x5c026800, 0x5c028000, 0x1c01f000, 0x4937c857,
-	0x4947c857, 0x4c5c0000, 0x4c600000, 0x4c640000,
-	0x59a80013, 0x8c000500, 0x0400001f, 0x599c0017,
-	0x8c00050a, 0x0402001c, 0x5934ba02, 0x825cbd00,
-	0x000000ff, 0x485fc857, 0x4178c000, 0x4178c800,
-	0x82600400, 0x0010bc20, 0x50002000, 0x8060c1c0,
-	0x04000008, 0x82100500, 0x000000ff, 0x82002d80,
-	0x000000ff, 0x0400000c, 0x805c0580, 0x0400000d,
-	0x80102110, 0x8064c800, 0x82640580, 0x00000004,
-	0x040207f5, 0x8060c000, 0x82600580, 0x00000020,
-	0x040207eb, 0x4813c857, 0x82000540, 0x00000001,
-	0x5c00c800, 0x5c00c000, 0x5c00b800, 0x1c01f000,
-	0x59a80026, 0x8c000512, 0x02020800, 0x001006ba,
-	0x1c01f000, 0x00007eef, 0x00007de8, 0x00007ce4,
-	0x000080e2, 0x00007be1, 0x000080e0, 0x000080dc,
-	0x000080da, 0x00007ad9, 0x000080d6, 0x000080d5,
-	0x000080d4, 0x000080d3, 0x000080d2, 0x000080d1,
-	0x000079ce, 0x000078cd, 0x000080cc, 0x000080cb,
-	0x000080ca, 0x000080c9, 0x000080c7, 0x000080c6,
-	0x000077c5, 0x000076c3, 0x000080bc, 0x000080ba,
-	0x000075b9, 0x000080b6, 0x000074b5, 0x000073b4,
-	0x000072b3, 0x000080b2, 0x000080b1, 0x000080ae,
-	0x000071ad, 0x000080ac, 0x000070ab, 0x00006faa,
-	0x00006ea9, 0x000080a7, 0x00006da6, 0x00006ca5,
-	0x00006ba3, 0x00006a9f, 0x0000699e, 0x0000689d,
-	0x0000809b, 0x00008098, 0x00006797, 0x00006690,
-	0x0000658f, 0x00006488, 0x00006384, 0x00006282,
-	0x00008081, 0x00008080, 0x0000617c, 0x0000607a,
-	0x00008079, 0x00005f76, 0x00008075, 0x00008074,
-	0x00008073, 0x00008072, 0x00008071, 0x0000806e,
-	0x00005e6d, 0x0000806c, 0x00005d6b, 0x00005c6a,
-	0x00005b69, 0x00008067, 0x00005a66, 0x00005965,
-	0x00005863, 0x0000575c, 0x0000565a, 0x00005559,
-	0x00008056, 0x00008055, 0x00005454, 0x00005353,
-	0x00005252, 0x00005151, 0x0000504e, 0x00004f4d,
-	0x0000804c, 0x0000804b, 0x00004e4a, 0x00004d49,
-	0x00008047, 0x00004c46, 0x00008045, 0x00008043,
-	0x0000803c, 0x0000803a, 0x00008039, 0x00008036,
-	0x00004b35, 0x00008034, 0x00004a33, 0x00004932,
-	0x00004831, 0x0000802e, 0x0000472d, 0x0000462c,
-	0x0000452b, 0x0000442a, 0x00004329, 0x00004227,
-	0x00008026, 0x00008025, 0x00004123, 0x0000401f,
-	0x00003f1e, 0x00003e1d, 0x00003d1b, 0x00003c18,
-	0x00008017, 0x00008010, 0x00003b0f, 0x00003a08,
-	0x00008004, 0x00003902, 0x00008001, 0x00008000,
-	0x00008000, 0x00003800, 0x00003700, 0x00003600,
-	0x00008000, 0x00003500, 0x00008000, 0x00008000,
-	0x00008000, 0x00003400, 0x00008000, 0x00008000,
-	0x00008000, 0x00008000, 0x00008000, 0x00008000,
-	0x00003300, 0x00003200, 0x00008000, 0x00008000,
-	0x00008000, 0x00008000, 0x00008000, 0x00008000,
-	0x00003100, 0x00003000, 0x00008000, 0x00008000,
-	0x00002f00, 0x00008000, 0x00002e00, 0x00002d00,
-	0x00002c00, 0x00008000, 0x00008000, 0x00008000,
-	0x00002b00, 0x00008000, 0x00002a00, 0x00002900,
-	0x00002800, 0x00008000, 0x00002700, 0x00002600,
-	0x00002500, 0x00002400, 0x00002300, 0x00002200,
-	0x00008000, 0x00008000, 0x00002100, 0x00002000,
-	0x00001f00, 0x00001e00, 0x00001d00, 0x00001c00,
-	0x00008000, 0x00008000, 0x00001b00, 0x00001a00,
-	0x00008000, 0x00001900, 0x00008000, 0x00008000,
-	0x00008000, 0x00008000, 0x00008000, 0x00008000,
-	0x00001800, 0x00008000, 0x00001700, 0x00001600,
-	0x00001500, 0x00008000, 0x00001400, 0x00001300,
-	0x00001200, 0x00001100, 0x00001000, 0x00000f00,
-	0x00008000, 0x00008000, 0x00000e00, 0x00000d00,
-	0x00000c00, 0x00000b00, 0x00000a00, 0x00000900,
-	0x00008000, 0x00008000, 0x00000800, 0x00000700,
-	0x00008000, 0x00000600, 0x00008000, 0x00008000,
-	0x00008000, 0x00000500, 0x00000400, 0x00000300,
-	0x00008000, 0x00000200, 0x00008000, 0x00008000,
-	0x00008000, 0x00000100, 0x00008000, 0x00008000,
-	0x00008000, 0x00008000, 0x00008000, 0x00008000,
-	0x00000000, 0x00008000, 0x00008000, 0x00008000,
-	0x00008000, 0x00008000, 0x00008000, 0x00008000,
-	0x00008000, 0x00008000, 0x00008000, 0x00008000,
-	0x00008000, 0x00008000, 0x00008000, 0x00008000,
-	0x00008000, 0x0201f800, 0x00100819, 0x02000800,
-	0x00100615, 0x492f4016, 0x1c01f000, 0x83a0ac00,
-	0x00000006, 0x83a00580, 0x0010b2a0, 0x0400000c,
-	0x492fc857, 0x812e59c0, 0x02000800, 0x00100615,
-	0x832ca400, 0x00000006, 0x4200b000, 0x0000000d,
-	0x0201f800, 0x0010a93e, 0x0401f00f, 0x4200b000,
-	0x00000010, 0x83e0a400, 0x00000020, 0x50500000,
-	0x8050a000, 0x50500800, 0x900409c0, 0x80040540,
-	0x4400a800, 0x8050a000, 0x8054a800, 0x8058b040,
-	0x040207f7, 0x1c01f000, 0x59a00206, 0x82000c80,
-	0x0000007f, 0x040210c9, 0x59a80821, 0x0c01f001,
-	0x00102066, 0x001020a6, 0x001020a6, 0x001020f0,
-	0x00102112, 0x001020a6, 0x00102066, 0x00102134,
-	0x00102145, 0x001020a6, 0x001020a6, 0x00102152,
-	0x0010216a, 0x00102182, 0x001020a6, 0x001021b1,
-	0x001021e3, 0x001020a6, 0x0010220c, 0x001020a6,
-	0x00102269, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001020a6, 0x00102280, 0x001022b9, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001022ee, 0x001020a6, 0x00102340, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x00102345,
-	0x001023be, 0x001020a6, 0x001023c5, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001023c7, 0x00102445, 0x00102585, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x00102594, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001025b1, 0x00102604, 0x00102660, 0x00102674,
-	0x00102696, 0x001028d1, 0x00102c60, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001020a6, 0x001020a6, 0x001020a6, 0x00102d9f,
-	0x00102e13, 0x001020a6, 0x001020a6, 0x00102e81,
-	0x001020a6, 0x00102f1f, 0x00102fd1, 0x001020a6,
-	0x001020a6, 0x00103008, 0x00103064, 0x001020a6,
-	0x001030bc, 0x00103220, 0x001020a6, 0x00103234,
-	0x001032bf, 0x001020a6, 0x001020a6, 0x001020a6,
-	0x001020a6, 0x0010332f, 0x00103333, 0x00103352,
-	0x001020a6, 0x001033f4, 0x001020a6, 0x001020a6,
-	0x00103421, 0x001020a6, 0x0010344f, 0x001020a6,
-	0x001020a6, 0x001034b6, 0x001035c3, 0x00103620,
-	0x001020a6, 0x00103686, 0x001020a6, 0x001020a6,
-	0x001036db, 0x0010373e, 0x001020a6, 0x48efc857,
-	0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
-	0x00000200, 0x04000045, 0x48efc857, 0x4a034206,
-	0x00004000, 0x0201f800, 0x0010382f, 0x83a00580,
-	0x0010b2a0, 0x0400000d, 0x58ee580a, 0x4d2c0000,
-	0x0401f856, 0x41a25800, 0x0201f800, 0x0010083a,
-	0x40ee5800, 0x0201f800, 0x0010083a, 0x5c025800,
-	0x0201f000, 0x00020381, 0x04026007, 0x59a0001d,
-	0x84000542, 0x4803401d, 0x4a01d809, 0x0010207a,
-	0x1c01f000, 0x59a00206, 0x82000d80, 0x00004000,
-	0x04000006, 0x900001c0, 0x82000540, 0x00000011,
-	0x4803c011, 0x0401f005, 0x900001c0, 0x82000540,
-	0x00000010, 0x4803c011, 0x0401f844, 0x59e00017,
-	0x8c000508, 0x0402000c, 0x4203e000, 0x30000001,
-	0x4203e000, 0x40000000, 0x40ee5800, 0x0201f800,
-	0x0010083a, 0x59a0001d, 0x84000504, 0x4803401d,
-	0x1c01f000, 0x4a03c017, 0x00000000, 0x59a00206,
-	0x82000d80, 0x00004000, 0x040007f0, 0x4a03c017,
-	0x00000001, 0x0401f7ed, 0x4803c856, 0x4a034206,
-	0x00004001, 0x0401f7c0, 0x4803c856, 0x4a034206,
-	0x00004002, 0x0401f7bc, 0x4803c856, 0x4a034206,
-	0x00004003, 0x0401f7b8, 0x4803c856, 0x4a034206,
-	0x00004005, 0x0401f7b4, 0x4803c856, 0x4a034206,
-	0x00004006, 0x0401f7b0, 0x4803c856, 0x4a034206,
-	0x0000400b, 0x0401f7ac, 0x4803c856, 0x4a034206,
-	0x0000400c, 0x0401f7a8, 0x4803c856, 0x4a034206,
-	0x0000400c, 0x0401f7a4, 0x58eca80a, 0x8054a9c0,
-	0x02000800, 0x00100615, 0x83a0a400, 0x00000006,
-	0x8254ac00, 0x00000006, 0x4200b000, 0x0000000d,
-	0x0201f000, 0x0010a93e, 0x59a00206, 0x4803c857,
-	0x59a00406, 0x4803c857, 0x59a00207, 0x4803c857,
-	0x59a00407, 0x4803c857, 0x59a00208, 0x4803c857,
-	0x59a00408, 0x4803c857, 0x59a00209, 0x4803c857,
-	0x83e0ac00, 0x00000020, 0x83a0a400, 0x00000006,
-	0x4200b000, 0x00000010, 0x50500000, 0x4400a800,
-	0x8054a800, 0x900001c0, 0x4400a800, 0x8054a800,
-	0x8050a000, 0x8058b040, 0x040207f8, 0x1c01f000,
-	0x59a00406, 0x800000c2, 0x59a00a07, 0x900409c0,
-	0x80040540, 0x84000540, 0x59a00c07, 0x8c040d00,
-	0x04000018, 0x59a8086f, 0x8c040d00, 0x040207bb,
-	0x42000800, 0x00000064, 0x80040840, 0x04000007,
-	0x4a030000, 0x00000001, 0x40000000, 0x59801000,
-	0x8c081500, 0x040007f9, 0x04000005, 0x48030004,
-	0x4a030000, 0x00000000, 0x0401f75c, 0x4a030000,
-	0x00000000, 0x4a034406, 0x00000004, 0x040007a3,
-	0x4803880e, 0x0401f755, 0x59a00406, 0x800000c2,
-	0x59a00c07, 0x8c040d00, 0x0400001a, 0x59a8086f,
-	0x8c040d00, 0x0402079d, 0x42000800, 0x00000064,
-	0x80040840, 0x04000007, 0x4a030000, 0x00000001,
-	0x40000000, 0x59801000, 0x8c081500, 0x040007f9,
-	0x04000007, 0x48030004, 0x59800805, 0x48074406,
-	0x4a030000, 0x00000000, 0x0401f73c, 0x4a030000,
-	0x00000000, 0x4a034406, 0x00000004, 0x04000783,
-	0x4803880e, 0x59c4080f, 0x48074406, 0x0401f733,
-	0x59a01c06, 0x59a00207, 0x900c19c0, 0x800c1d40,
-	0x580c0803, 0x80000580, 0x500c1000, 0x80080400,
-	0x800c1800, 0x80040840, 0x040207fc, 0x48034406,
-	0x900001c0, 0x48034207, 0x800001c0, 0x04000723,
-	0x0401f76a, 0x4a034406, 0x00000004, 0x4a034207,
-	0x00000000, 0x4a034407, 0x00000012, 0x59a8000d,
-	0x48034208, 0x900001c0, 0x48034408, 0x4a034209,
-	0x00000002, 0x0401f715, 0x59a00407, 0x59a01207,
-	0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09,
-	0x900c19c0, 0x800c1d40, 0x59a00a08, 0x59a00408,
-	0x900409c0, 0x80040d40, 0x59a0020a, 0x82002480,
-	0x00000010, 0x04001755, 0x59a02406, 0x900001c0,
-	0x80100540, 0x59a8280d, 0x80142480, 0x0400174f,
-	0x0201f000, 0x0010383e, 0x59a00407, 0x59a01207,
-	0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09,
-	0x900c19c0, 0x800c1d40, 0x59a00a08, 0x59a00408,
-	0x900409c0, 0x80040d40, 0x59a0020a, 0x82002480,
-	0x00000010, 0x0400173d, 0x59a02406, 0x900001c0,
-	0x80100540, 0x59a8280d, 0x80142480, 0x04001737,
-	0x0201f000, 0x00103841, 0x59a02407, 0x59a00207,
-	0x901021c0, 0x80102540, 0x59a01a0a, 0x59a00406,
-	0x900c19c0, 0x800c1d40, 0x41781000, 0x42000000,
-	0x00001000, 0x50000000, 0x82000480, 0x24320001,
-	0x04001016, 0x820c0580, 0x00007c00, 0x04000013,
-	0x820c0480, 0x00007a00, 0x04001010, 0x820c0480,
-	0x00007cff, 0x0402100d, 0x42000800, 0x00000064,
-	0x80040840, 0x04000007, 0x4a030000, 0x00000001,
-	0x40000000, 0x59800000, 0x8c000500, 0x040007f9,
-	0x04000008, 0x80081000, 0x44101800, 0x800811c0,
-	0x040006be, 0x4a030000, 0x00000000, 0x0401f6bb,
-	0x4a030000, 0x00000000, 0x4a034406, 0x00000004,
-	0x0401f702, 0x59a01a0a, 0x59a00406, 0x900c19c0,
-	0x800c1d40, 0x41781000, 0x42000000, 0x00001000,
-	0x50000000, 0x82000480, 0x24320001, 0x04001016,
-	0x820c0580, 0x00007c00, 0x04000013, 0x820c0480,
-	0x00007a00, 0x04001010, 0x820c0480, 0x00007cff,
-	0x0402100d, 0x42000800, 0x00000064, 0x80040840,
-	0x04000007, 0x4a030000, 0x00000001, 0x40000000,
-	0x59800000, 0x8c000500, 0x040007f9, 0x0400000f,
-	0x80081000, 0x500c0000, 0x82000d00, 0x0000ffff,
-	0x48074207, 0x82000d00, 0xffff0000, 0x900409c0,
-	0x48074407, 0x800811c0, 0x0400068c, 0x4a030000,
-	0x00000000, 0x0401f689, 0x4a030000, 0x00000000,
-	0x4a034406, 0x00000004, 0x0401f6d0, 0x59a00406,
-	0x8c000500, 0x04000020, 0x59a01207, 0x59a01c07,
-	0x59a02208, 0x480b5054, 0x480f5055, 0x48135056,
-	0x59c40801, 0x82040d00, 0x00018000, 0x82040580,
-	0x00000000, 0x04000009, 0x82040580, 0x00008000,
-	0x04000008, 0x82040580, 0x00010000, 0x04000007,
-	0x0201f800, 0x00100615, 0x40080000, 0x0401f004,
-	0x400c0000, 0x0401f002, 0x40100000, 0x80000110,
-	0x42000800, 0x000000e0, 0x0201f800, 0x001019b1,
-	0x0401f007, 0x59a81054, 0x59a81855, 0x59a82056,
-	0x480b4207, 0x480f4407, 0x48134208, 0x0401f65b,
-	0x4d2c0000, 0x4d340000, 0x4d300000, 0x4d440000,
-	0x59a28c06, 0x0201f800, 0x00020267, 0x04000006,
-	0x5c028800, 0x5c026000, 0x5c026800, 0x5c025800,
-	0x0401f69e, 0x59a04407, 0x59a00207, 0x900001c0,
-	0x80204540, 0x0401f81e, 0x04000009, 0x4a034208,
-	0x00000001, 0x4a034406, 0x0000ffff, 0x4a034207,
-	0x0000ffff, 0x497b4407, 0x0401f00b, 0x0401f822,
-	0x0400000e, 0x4a034208, 0x00000002, 0x59300402,
-	0x48034406, 0x59300202, 0x48034207, 0x59300206,
-	0x48034407, 0x5c028800, 0x5c026000, 0x5c026800,
-	0x5c025800, 0x0401f631, 0x5c028800, 0x5c026000,
-	0x5c026800, 0x5c025800, 0x0401f678, 0x4937c856,
-	0x4823c856, 0x4d2c0000, 0x5934000f, 0x80025d40,
-	0x04000007, 0x592c0005, 0x80200580, 0x592c0000,
-	0x040207fb, 0x82000540, 0x00000001, 0x5c025800,
-	0x1c01f000, 0x4823c857, 0x4d2c0000, 0x4d300000,
-	0x42026000, 0x0010cfc0, 0x59300406, 0x82000d80,
-	0x00000003, 0x04000004, 0x82000d80, 0x00000006,
-	0x04020007, 0x59325808, 0x812e59c0, 0x04000004,
-	0x592c0005, 0x80200580, 0x0400000a, 0x83326400,
-	0x00000024, 0x41580000, 0x81300480, 0x040017ef,
-	0x80000580, 0x5c026000, 0x5c025800, 0x1c01f000,
-	0x82000540, 0x00000001, 0x5c026000, 0x5c025800,
-	0x1c01f000, 0x83a00580, 0x0010b2a0, 0x0402063b,
-	0x59a8006f, 0x8c000500, 0x04020003, 0x4a030000,
-	0x00000000, 0x4a034206, 0x00004000, 0x4a03c011,
-	0x40000010, 0x0401fe5d, 0x59e00017, 0x8c000508,
-	0x04000003, 0x4a03c017, 0x00000000, 0x4203e000,
-	0x30000001, 0x4203e000, 0x40000000, 0x0401f000,
-	0x59a00c06, 0x800409c0, 0x04000007, 0x836c0580,
-	0x00000000, 0x04000004, 0x4a034406, 0x0000001a,
-	0x0401f62a, 0x42007000, 0x0010b33f, 0x58381c01,
-	0x58382202, 0x8c040d00, 0x0400000b, 0x59a01207,
-	0x82080500, 0x0000f003, 0x04020624, 0x82080480,
-	0x00000841, 0x04021621, 0x82080480, 0x00000100,
-	0x0400161e, 0x8c040d06, 0x04000003, 0x4a0378e4,
-	0x000c0000, 0x8c040d04, 0x0400000c, 0x42000000,
-	0x00001000, 0x50000000, 0x82000480, 0x24220001,
-	0x04020003, 0x84040d04, 0x0401f004, 0x59e00002,
-	0x84000548, 0x4803c002, 0x8c040d02, 0x04000005,
-	0x42002800, 0x00007600, 0x4a002805, 0xd0000000,
-	0x40040000, 0x800c0540, 0x48007401, 0x8c040d00,
-	0x04000002, 0x48087202, 0x480f4406, 0x48134207,
-	0x0401f5ae, 0x4d440000, 0x4d340000, 0x59a28c06,
-	0x0201f800, 0x00020267, 0x04020009, 0x0201f800,
-	0x00104842, 0x04000009, 0x4a034406, 0x00000009,
-	0x5c026800, 0x5c028800, 0x0401f5ec, 0x5c026800,
-	0x5c028800, 0x0401f5ed, 0x59a01207, 0x59a01c07,
-	0x5934400a, 0x82203d00, 0x0000e000, 0x801c391a,
-	0x8c081500, 0x04000019, 0x820c0d00, 0x00000007,
-	0x82040580, 0x00000000, 0x04000007, 0x82040580,
-	0x00000001, 0x04000004, 0x82040580, 0x00000003,
-	0x040207eb, 0x82204500, 0xffff1fff, 0x800400da,
-	0x80200540, 0x4802680a, 0x4c1c0000, 0x0201f800,
-	0x0010698c, 0x0201f800, 0x00104afd, 0x0201f800,
-	0x00106982, 0x5c003800, 0x481f4407, 0x5c026800,
-	0x5c028800, 0x0401f579, 0x800409c0, 0x04000004,
-	0x4a034406, 0x00000001, 0x0401f5c0, 0x836c0580,
-	0x00000003, 0x04020010, 0x59a80010, 0x497b4406,
-	0x0201f800, 0x00104e0d, 0x0400000f, 0x82000d00,
-	0x00ffff00, 0x0402000c, 0x82000c00, 0x00101eb5,
-	0x50040800, 0x80040910, 0x82041580, 0x00000080,
-	0x04020004, 0x4a034406, 0x00000007, 0x0401f5ab,
-	0x48074406, 0x82000d00, 0x0000ffff, 0x48074207,
-	0x80000120, 0x48034407, 0x59a80026, 0x82001500,
-	0x00000100, 0x480b4409, 0x8c000502, 0x0400001f,
-	0x8c000506, 0x04000009, 0x82000d00, 0x0000000a,
-	0x82040d80, 0x0000000a, 0x04020004, 0x4a034209,
-	0x00000001, 0x0401f022, 0x8c00050a, 0x04000009,
-	0x82000d00, 0x00000022, 0x82040d80, 0x00000022,
-	0x04020004, 0x4a034209, 0x00000003, 0x0401f018,
-	0x8c000508, 0x04000009, 0x82000d00, 0x00000012,
-	0x82040d80, 0x00000012, 0x04020004, 0x4a034209,
-	0x00000002, 0x0401f00e, 0x0201f800, 0x00104e0d,
-	0x04020004, 0x4a034209, 0x00000004, 0x0401f52f,
-	0x8c000506, 0x04000004, 0x4a034406, 0x00000005,
-	0x0401f576, 0x4a034209, 0x00000000, 0x0401f527,
-	0x59a80037, 0x48034407, 0x59a80038, 0x48034209,
-	0x0401f522, 0x42007800, 0x0010b6eb, 0x59a00406,
-	0x4803c857, 0x82000c80, 0x00000007, 0x0402156b,
-	0x0c01f001, 0x00102354, 0x00102355, 0x00102363,
-	0x00102376, 0x00102397, 0x00102354, 0x00102354,
-	0x0401f562, 0x836c0580, 0x00000000, 0x0400055b,
-	0x59a00a07, 0x59a00407, 0x900001c0, 0x80040d40,
-	0x4807c857, 0x59a00a08, 0x59a00408, 0x900001c0,
-	0x80040d40, 0x4807c857, 0x0401f056, 0x836c0580,
-	0x00000000, 0x0400054d, 0x59a00407, 0x59a01207,
-	0x900001c0, 0x80081540, 0x59a00408, 0x59a01a08,
-	0x900001c0, 0x800c1d40, 0x42000000, 0x0010bfbe,
-	0x480fc857, 0x480bc857, 0x42000800, 0x00001000,
-	0x0201f000, 0x00103841, 0x59a00a07, 0x59a00407,
-	0x900001c0, 0x80041d40, 0x820c0c80, 0x0010a971,
-	0x0402153a, 0x820c0c80, 0x00100000, 0x04001537,
-	0x480fc857, 0x823c7c00, 0x00000009, 0x503c0800,
-	0x800409c0, 0x04000006, 0x823c0580, 0x0000000d,
-	0x0400052e, 0x803c7800, 0x0401f7f9, 0x59e41001,
-	0x82080d00, 0xfffeffcf, 0x4807c801, 0x440c7800,
-	0x46001800, 0x0201f800, 0x800c1800, 0x46001800,
-	0x00100608, 0x480bc801, 0x0401f022, 0x59a01a07,
-	0x59a00407, 0x900001c0, 0x800c1d40, 0x480c7801,
-	0x59a02208, 0x59a00408, 0x900001c0, 0x80102540,
-	0x48107802, 0x59a00209, 0x80000040, 0x04001513,
-	0x48007806, 0x80000000, 0x48007805, 0x42000800,
-	0x00004000, 0x40001000, 0x0201f800, 0x001063cf,
-	0x80000540, 0x04000003, 0x49787801, 0x0401f507,
-	0x40040000, 0x800c1c00, 0x04001504, 0x480c7803,
-	0x48107804, 0x49787808, 0x59a00409, 0x48007807,
-	0x59e40001, 0x4803c857, 0x82000540, 0x00040000,
-	0x4803c801, 0x0401f4a9, 0x59a80006, 0x48034406,
-	0x59a80007, 0x48034207, 0x59a80008, 0x48034407,
-	0x0401f4a2, 0x0201f800, 0x00100615, 0x4803c856,
-	0x4a03c013, 0x03800300, 0x4a03c014, 0x03800380,
-	0x59a00c06, 0x82040580, 0x000000a0, 0x04000004,
-	0x82040580, 0x000000a2, 0x04020028, 0x59a0140a,
-	0x82080480, 0x00000100, 0x04021024, 0x59a0020b,
-	0x8c000500, 0x0402002b, 0x59a00a0a, 0x800409c0,
-	0x0400001e, 0x82040480, 0x00000041, 0x0402101b,
-	0x82040c00, 0x00000003, 0x82040d00, 0x000000fc,
-	0x80040904, 0x59a00407, 0x59a01207, 0x900811c0,
-	0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
-	0x800c1d40, 0x0201f800, 0x0010381a, 0x04020006,
-	0x4a034406, 0x00000002, 0x4a03c014, 0x03800000,
-	0x0401f4be, 0x0201f800, 0x0010383e, 0x4a01d809,
-	0x001023fd, 0x1c01f000, 0x4a03c014, 0x03800000,
-	0x0401f4ba, 0x4031d800, 0x58ef400b, 0x58ee580d,
-	0x58ec0002, 0x82000580, 0x00000200, 0x040004a7,
-	0x59a00c06, 0x59a0140a, 0x59a0020b, 0x8c000500,
-	0x04020031, 0x832e5c00, 0x00000004, 0x41783800,
-	0x59a04a0a, 0x401c0000, 0x812c0400, 0x50004000,
-	0x82201d00, 0x000000ff, 0x4c040000, 0x0401f8af,
-	0x5c000800, 0x0400002d, 0x80244840, 0x04000028,
-	0x80081000, 0x82201d00, 0x0000ff00, 0x800c1910,
-	0x4c040000, 0x0401f8a5, 0x5c000800, 0x04000023,
-	0x80244840, 0x0400001e, 0x80081000, 0x82201d00,
-	0x00ff0000, 0x800c1920, 0x4c040000, 0x0401f89b,
-	0x5c000800, 0x04000019, 0x80244840, 0x04000014,
-	0x80081000, 0x82201d00, 0xff000000, 0x800c1930,
-	0x4c040000, 0x0401f891, 0x5c000800, 0x0400000f,
-	0x80244840, 0x0400000a, 0x80081000, 0x801c3800,
-	0x0401f7d5, 0x59a0020a, 0x82000500, 0x000000ff,
-	0x40001800, 0x0401f885, 0x04000004, 0x4a03c014,
-	0x03800000, 0x0401f425, 0x4a03c014, 0x03800000,
-	0x0401f46e, 0x4803c856, 0x4a03c013, 0x03800300,
-	0x4a03c014, 0x03800380, 0x59a00c06, 0x82040580,
-	0x000000a0, 0x04000004, 0x82040580, 0x000000a2,
-	0x0402006e, 0x59a0140a, 0x82080480, 0x00000100,
-	0x0402106a, 0x59a0020b, 0x8c000500, 0x0402005c,
-	0x59a01a0a, 0x800c19c0, 0x04000064, 0x820c0480,
-	0x00000041, 0x04021061, 0x0201f800, 0x0010381a,
-	0x04020006, 0x4a034406, 0x00000002, 0x4a03c014,
-	0x03800000, 0x0401f44d, 0x832e5c00, 0x00000004,
-	0x41783800, 0x59a04a0a, 0x401c0000, 0x812c0400,
-	0x40004000, 0x4c040000, 0x4c080000, 0x0401f877,
-	0x5c001000, 0x5c000800, 0x04000048, 0x44144000,
-	0x80244840, 0x0400002b, 0x80081000, 0x4c040000,
-	0x4c080000, 0x0401f86d, 0x5c001000, 0x5c000800,
-	0x0400003e, 0x50200000, 0x801428d0, 0x80140540,
-	0x44004000, 0x80244840, 0x0400001e, 0x80081000,
-	0x4c040000, 0x4c080000, 0x0401f860, 0x5c001000,
-	0x5c000800, 0x04000031, 0x50200000, 0x801428e0,
-	0x80140540, 0x44004000, 0x80244840, 0x04000011,
-	0x80081000, 0x4c040000, 0x4c080000, 0x0401f853,
-	0x5c001000, 0x5c000800, 0x04000024, 0x50200000,
-	0x801428f0, 0x80140540, 0x44004000, 0x80244840,
-	0x04000004, 0x80081000, 0x801c3800, 0x0401f7cb,
-	0x59a00a0a, 0x82040c00, 0x00000003, 0x82040d00,
-	0x000000fc, 0x80040904, 0x59a00407, 0x59a01207,
-	0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09,
-	0x900c19c0, 0x800c1d40, 0x4a03c014, 0x03800000,
-	0x412c0000, 0x0201f000, 0x00103841, 0x0401f833,
-	0x04000006, 0x48174406, 0x4a03c014, 0x03800000,
-	0x0201f000, 0x00102066, 0x4a03c014, 0x03800000,
-	0x0201f000, 0x001020b2, 0x4a03c014, 0x03800000,
-	0x0201f000, 0x001020b6, 0x0401f836, 0x04000010,
-	0x0401f862, 0x0402000f, 0x40080800, 0x0401f85f,
-	0x0402000c, 0x400c0800, 0x0401f85c, 0x04020009,
-	0x0401f84b, 0x42000000, 0x00030d40, 0x80000040,
-	0x040207ff, 0x82000540, 0x00000001, 0x1c01f000,
-	0x0401f843, 0x80000580, 0x0401f7fd, 0x0401f821,
-	0x0400000a, 0x82040d40, 0x00000001, 0x0401f84b,
-	0x04020007, 0x0401f87e, 0x0401f898, 0x0401f838,
-	0x82000540, 0x00000001, 0x1c01f000, 0x0401f834,
-	0x80000580, 0x0401f7fd, 0x40041800, 0x0401f811,
-	0x0400000c, 0x0401f83d, 0x0402000b, 0x40080800,
-	0x0401f83a, 0x04020008, 0x400c0800, 0x0401ffe8,
-	0x04000004, 0x0401f826, 0x82000540, 0x00000001,
-	0x1c01f000, 0x0401f822, 0x80000580, 0x0401f7fd,
-	0x4c040000, 0x42000800, 0x00000064, 0x4a03c013,
-	0x03800300, 0x80040840, 0x04000016, 0x59e00013,
-	0x82000500, 0x00000300, 0x82000580, 0x00000300,
-	0x040207f7, 0x42000000, 0x00000064, 0x80000040,
-	0x040207ff, 0x4a03c013, 0x01000000, 0x42000000,
-	0x00000064, 0x80000040, 0x040207ff, 0x4a03c013,
-	0x02000000, 0x82000540, 0x00000001, 0x0401f002,
-	0x80000580, 0x5c000800, 0x1c01f000, 0x4a03c013,
-	0x01000000, 0x42000000, 0x00000064, 0x80000040,
-	0x040207ff, 0x4a03c013, 0x02000200, 0x42000000,
-	0x00000064, 0x80000040, 0x040207ff, 0x4a03c013,
-	0x01000100, 0x1c01f000, 0x42002000, 0x00000008,
-	0x82040500, 0x00000080, 0x800000c2, 0x82000540,
-	0x01000000, 0x4803c013, 0x42000000, 0x00000064,
-	0x80000040, 0x040207ff, 0x4a03c013, 0x02000200,
-	0x42000000, 0x00000064, 0x80000040, 0x040207ff,
-	0x4a03c013, 0x02000000, 0x800408c2, 0x80102040,
-	0x040207ec, 0x4a03c013, 0x01000100, 0x42000000,
-	0x00000064, 0x80000040, 0x040207ff, 0x4a03c013,
-	0x02000200, 0x42000000, 0x00000064, 0x80000040,
-	0x040207ff, 0x59e00013, 0x82000500, 0x00000100,
-	0x4a03c013, 0x02000000, 0x4c040000, 0x42000800,
-	0x00000064, 0x59e00013, 0x82000500, 0x00000100,
-	0x80040840, 0x04000003, 0x80000540, 0x040207fa,
-	0x80000540, 0x5c000800, 0x1c01f000, 0x4a03c013,
-	0x01000100, 0x42001000, 0x00000008, 0x80000d80,
-	0x42000000, 0x00000064, 0x80000040, 0x040207ff,
-	0x4a03c013, 0x02000200, 0x42000000, 0x00000064,
-	0x80000040, 0x040207ff, 0x59e00013, 0x82000500,
-	0x00000100, 0x80000110, 0x800408c2, 0x80040d40,
-	0x4a03c013, 0x02000000, 0x80081040, 0x040207ed,
-	0x40042800, 0x1c01f000, 0x4a03c013, 0x01000100,
-	0x42000000, 0x00000064, 0x80000040, 0x040207ff,
-	0x4a03c013, 0x02000200, 0x42000000, 0x00000064,
-	0x80000040, 0x040207ff, 0x4a03c013, 0x02000000,
-	0x1c01f000, 0x59a00407, 0x59a80837, 0x48035037,
-	0x48074407, 0x59a00a09, 0x82040480, 0x00000014,
-	0x04021003, 0x42000800, 0x000007d0, 0x59a80038,
-	0x48075038, 0x48034209, 0x0201f000, 0x00102066,
-	0x836c0580, 0x00000000, 0x0400000e, 0x59a80006,
-	0x59a00c06, 0x80041580, 0x82081500, 0x00000040,
-	0x02000000, 0x00102066, 0x80080580, 0x48035006,
-	0x0201f800, 0x001006df, 0x0201f000, 0x00102066,
-	0x59a00406, 0x59a80806, 0x48035006, 0x80040d80,
-	0x8c040d0c, 0x02020800, 0x001006df, 0x59a00207,
-	0x48035007, 0x59a00407, 0x48035008, 0x0201f000,
-	0x00102066, 0x800409c0, 0x04000005, 0x4a034406,
-	0x00000001, 0x0201f000, 0x001020b2, 0x0201f800,
-	0x00104e0d, 0x04020005, 0x4a034406, 0x00000016,
-	0x0201f000, 0x001020b2, 0x836c0580, 0x00000003,
-	0x04000005, 0x4a034406, 0x00000007, 0x0201f000,
-	0x001020b2, 0x59a00c06, 0x82040500, 0xffffff00,
-	0x02020000, 0x001020b6, 0x82041580, 0x000000ff,
-	0x04020007, 0x59a80010, 0x82000500, 0x000000ff,
-	0x82001540, 0x0000ff00, 0x0401f011, 0x82040400,
-	0x00101eb5, 0x50000000, 0x80000110, 0x82000580,
-	0x00000080, 0x02000000, 0x001020b6, 0x59a80010,
-	0x82000500, 0x000000ff, 0x80041580, 0x02000000,
-	0x001020b6, 0x840409c0, 0x80041540, 0x0201f800,
-	0x00020892, 0x04020005, 0x4a034406, 0x00000003,
-	0x0201f000, 0x001020b2, 0x48ee6021, 0x480a621c,
-	0x4a02641c, 0x0000bc09, 0x4a026406, 0x00000001,
-	0x0201f800, 0x0010381a, 0x04020007, 0x0201f800,
-	0x000208b4, 0x4a034406, 0x00000002, 0x0201f000,
-	0x001020b2, 0x497a5a04, 0x497a5805, 0x4a025c04,
-	0x00008000, 0x4a01d809, 0x00102657, 0x492e6008,
-	0x42027000, 0x00000032, 0x0201f000, 0x000208d8,
-	0x800409c0, 0x04000005, 0x4a034406, 0x00000001,
-	0x0201f000, 0x001020b2, 0x0201f800, 0x00104e0d,
-	0x04020005, 0x4a034406, 0x00000016, 0x0201f000,
-	0x001020b2, 0x836c0580, 0x00000003, 0x04000005,
-	0x4a034406, 0x00000007, 0x0201f000, 0x001020b2,
-	0x59a00c06, 0x82040500, 0xffffff00, 0x02020000,
-	0x001020b6, 0x82041580, 0x000000ff, 0x04020007,
-	0x59a80010, 0x82000500, 0x000000ff, 0x82001540,
-	0x0000ff00, 0x0401f011, 0x82040400, 0x00101eb5,
-	0x50000000, 0x80000110, 0x82000580, 0x00000080,
-	0x02000000, 0x001020b6, 0x59a80010, 0x82000500,
-	0x000000ff, 0x80041580, 0x02000000, 0x001020b6,
-	0x840409c0, 0x80041540, 0x0201f800, 0x00020892,
-	0x04020005, 0x4a034406, 0x00000003, 0x0201f000,
-	0x001020b2, 0x48ee6021, 0x480a621c, 0x4a02641c,
-	0x0000bc05, 0x4a026406, 0x00000001, 0x0201f800,
-	0x0010381a, 0x04020007, 0x0201f800, 0x000208b4,
-	0x4a034406, 0x00000002, 0x0201f000, 0x001020b2,
-	0x497a5a04, 0x497a5805, 0x4a025c04, 0x00008000,
-	0x4a01d809, 0x00102657, 0x492e6008, 0x42027000,
-	0x00000032, 0x0201f000, 0x000208d8, 0x592c0005,
-	0x82000580, 0x01000000, 0x02020000, 0x00102066,
-	0x4a034406, 0x00000004, 0x0201f000, 0x001020b2,
-	0x497b4406, 0x497b4207, 0x0201f800, 0x0010393e,
-	0x04000008, 0x59a80066, 0x59a8086a, 0x80040480,
-	0x59a80867, 0x48074406, 0x80041480, 0x480b4207,
-	0x49674407, 0x59a8000e, 0x48034209, 0x495f4409,
-	0x59a80020, 0x4803420b, 0x0201f000, 0x00102066,
-	0x800409c0, 0x04000005, 0x4a034406, 0x00000001,
-	0x0201f000, 0x001020b2, 0x59a00406, 0x8c000500,
-	0x0402000f, 0x59a80069, 0x81640480, 0x04001008,
-	0x59a8000b, 0x81500580, 0x04000009, 0x59a8006a,
-	0x59a81066, 0x80080580, 0x04000005, 0x4a034406,
-	0x00000018, 0x0201f000, 0x001020b2, 0x59a80005,
-	0x84000558, 0x48035005, 0x82000540, 0x00000001,
-	0x0201f800, 0x00101668, 0x0201f800, 0x00103a9f,
-	0x0201f000, 0x00102066, 0x4803c856, 0x800409c0,
-	0x02020000, 0x001020ba, 0x59a00406, 0x8c00051e,
-	0x04000008, 0x4803c856, 0x59a0020b, 0x82000480,
-	0x00000800, 0x04001015, 0x0201f000, 0x001020b6,
-	0x4803c856, 0x59a0020b, 0x599c0a01, 0x80040480,
-	0x04021003, 0x0201f000, 0x001020b6, 0x59a8000e,
-	0x81640580, 0x04000009, 0x4a034406, 0x00000018,
-	0x0201f000, 0x001020b2, 0x4a034406, 0x00000005,
-	0x0201f000, 0x001020b2, 0x59a80026, 0x8c00050a,
-	0x040007fa, 0x59a00406, 0x8c00051e, 0x04000036,
-	0x0201f800, 0x00020892, 0x040007f4, 0x0201f800,
-	0x0010381a, 0x040007f1, 0x497a5a04, 0x59a00406,
-	0x4802620a, 0x59a00209, 0x4802640a, 0x59a00409,
-	0x4802620b, 0x59a0020d, 0x4802620c, 0x59a0040d,
-	0x4802640c, 0x59a0020e, 0x4802620d, 0x59a0040e,
-	0x4802640d, 0x59a00210, 0x4802620e, 0x59a00410,
-	0x4802640e, 0x59a0020b, 0x82000500, 0x0000fffc,
-	0x80000104, 0x4802640b, 0x0401f9d9, 0x040007d7,
-	0x48ee6021, 0x58ee580d, 0x5930020e, 0x59301c0e,
-	0x900c19c0, 0x800c1d40, 0x5930020c, 0x5930140c,
-	0x900811c0, 0x80081540, 0x592c0a05, 0x832c0400,
-	0x00000006, 0x0201f800, 0x0010383e, 0x4a01d809,
-	0x00102846, 0x4a034000, 0x00000001, 0x49334001,
-	0x1c01f000, 0x0201f800, 0x0010698c, 0x0201f800,
-	0x00100b29, 0x0401f86d, 0x497b5057, 0x4201d000,
-	0x00002710, 0x0201f800, 0x00105e06, 0x59c40880,
-	0x4c040000, 0x59c408a3, 0x4c040000, 0x497b4002,
-	0x0401f876, 0x0401f893, 0x4a03a005, 0x10000000,
-	0x0401f8b4, 0x0401f901, 0x04000048, 0x59c80001,
-	0x800001c0, 0x040007fc, 0x59c80018, 0x82000500,
-	0xf0000000, 0x59c00808, 0x82040d00, 0x0fffffff,
-	0x80040540, 0x48038008, 0x0201f800, 0x00100f0f,
-	0x59c00006, 0x4a038006, 0x10000000, 0x59c00009,
-	0x82000d00, 0x00e00000, 0x04020024, 0x4a03900d,
-	0x00000000, 0x59c80020, 0x82000500, 0xff000000,
-	0x82000580, 0x32000000, 0x0402001c, 0x4a03900d,
-	0x00000001, 0x59c80020, 0x82000500, 0xff000000,
-	0x82000580, 0xe1000000, 0x04020014, 0x4a03900d,
-	0x00000000, 0x59c80020, 0x82000500, 0x00ffffff,
-	0x4a03900d, 0x00000000, 0x59c80821, 0x82040d00,
-	0x00ffffff, 0x80040580, 0x04020008, 0x59a80010,
-	0x80040580, 0x04020005, 0x59c40005, 0x82000500,
-	0x000000f0, 0x04000006, 0x4803c856, 0x0401f8d7,
-	0x4a035057, 0x00000001, 0x0401f002, 0x0401f8e1,
-	0x42000000, 0x00000064, 0x80000040, 0x02000800,
-	0x00100615, 0x59c00807, 0x82040d00, 0x0000000c,
-	0x040007fa, 0x0401f003, 0x4a035057, 0x00000001,
-	0x0401f8da, 0x0201f800, 0x00106c8a, 0x0401f818,
-	0x4201d000, 0x000186a0, 0x0201f800, 0x00105e06,
-	0x5c000800, 0x480788a3, 0x5c000800, 0x48078880,
-	0x59a80057, 0x800001c0, 0x02000000, 0x00102066,
-	0x0201f000, 0x001020be, 0x599c0201, 0x48035059,
-	0x41780800, 0x42001000, 0x00003b10, 0x0201f800,
-	0x001063ee, 0x480b505a, 0x1c01f000, 0x0201f800,
-	0x00106982, 0x59b800ea, 0x82000500, 0x00000007,
-	0x82000580, 0x00000003, 0x04020003, 0x4a0370e8,
-	0x00000001, 0x1c01f000, 0x42038000, 0x00007700,
-	0x4a038006, 0x30000000, 0x59c00007, 0x8c00050a,
-	0x040207fe, 0x59c00006, 0x59a00209, 0x59a00c09,
-	0x900409c0, 0x80040d40, 0x48078001, 0x59a0020e,
-	0x59a00c0e, 0x900409c0, 0x80040d40, 0x48078000,
-	0x59a0020b, 0x82000500, 0x0000fffc, 0x48038002,
-	0x48038003, 0x48038005, 0x497b9009, 0x59e00003,
-	0x82000540, 0x00008060, 0x4803c003, 0x1c01f000,
-	0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600,
-	0x42000800, 0x00000040, 0x0201f800, 0x00101395,
-	0x4a03a00a, 0x00000001, 0x4a03a005, 0x20000000,
-	0x59d00006, 0x4a03a005, 0x30000000, 0x59d00006,
-	0x8c00050a, 0x040207fe, 0x59d00005, 0x59a00210,
-	0x59a00c10, 0x900409c0, 0x80040d40, 0x4807a001,
-	0x59a0020d, 0x59a00c0d, 0x900409c0, 0x80040d40,
-	0x4807a000, 0x59a0020b, 0x82000500, 0x0000fffc,
-	0x4803a003, 0x4803a002, 0x4803a008, 0x1c01f000,
-	0x59a00002, 0x4803c857, 0x800001c0, 0x0402004a,
-	0x59a8005a, 0x48038880, 0x59c400a3, 0x82000540,
-	0x00002008, 0x8400053a, 0x480388a3, 0x59c40008,
-	0x8400054e, 0x82000500, 0xffffffe1, 0x48038808,
-	0x59c80040, 0x84000534, 0x48039040, 0x0401f902,
-	0x04020013, 0x59a80010, 0x800000d0, 0x82000540,
-	0x00000011, 0x48039120, 0x59a80010, 0x82000500,
-	0x00ffffff, 0x82000540, 0x32000000, 0x48039121,
-	0x4a039123, 0xe1290008, 0x59a80010, 0x82000500,
-	0x00ffffff, 0x48039122, 0x0401f016, 0x59a80010,
-	0x82000500, 0x000000ff, 0x900009c0, 0x840001c0,
-	0x80040540, 0x82000540, 0x00000000, 0x48039120,
-	0x59a80010, 0x82000500, 0x000000ff, 0x82000540,
-	0x01000000, 0x48039121, 0x4a039123, 0x08210008,
-	0x59a80010, 0x82000500, 0x000000ff, 0x48039122,
-	0x497b9124, 0x59a80c5b, 0x80040800, 0x4807545b,
-	0x900409c0, 0x82040540, 0x0000aaaa, 0x48039125,
-	0x497b9126, 0x497b9127, 0x0401f8cf, 0x04020004,
-	0x4a039100, 0x0000e980, 0x0401f003, 0x4a039100,
-	0x0000e9a0, 0x1c01f000, 0x82000540, 0x00000001,
-	0x0402500d, 0x4203e000, 0x80000000, 0x40e81000,
-	0x41780800, 0x42000000, 0x00000064, 0x0201f800,
-	0x001063ee, 0x59940024, 0x80080400, 0x48032824,
-	0x80000580, 0x1c01f000, 0x4d900000, 0x4dd00000,
-	0x4da40000, 0x4d140000, 0x417a3000, 0x0201f800,
-	0x00106e2f, 0x0201f800, 0x00106b13, 0x5c022800,
-	0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000,
-	0x59c80007, 0x8c000500, 0x04000003, 0x4a03900d,
-	0x00000030, 0x1c01f000, 0x4a038805, 0x00020000,
-	0x42000800, 0x0000003c, 0x0201f800, 0x00101395,
-	0x4a038891, 0x0000ffff, 0x59c80035, 0x48039035,
-	0x4a03900d, 0x00000040, 0x42038000, 0x00007700,
-	0x0201f800, 0x00100f0f, 0x42038000, 0x00007720,
-	0x0201f800, 0x00100f0f, 0x4a03a005, 0x20000000,
-	0x4a03a005, 0x30000000, 0x59d00806, 0x8c040d0a,
-	0x040207fe, 0x1c01f000, 0x4d300000, 0x4031d800,
-	0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
-	0x00000200, 0x5c026000, 0x02000000, 0x001020aa,
-	0x4d300000, 0x59a26001, 0x59a00000, 0x4000b000,
-	0x80000000, 0x48034000, 0x592c0001, 0x80000540,
-	0x0400001e, 0x40025800, 0x8058b040, 0x040207fb,
-	0x58ec1007, 0x58ec1808, 0x592c0a05, 0x4d2c0000,
-	0x58ec000d, 0x40025800, 0x592c0204, 0x5c025800,
-	0x82000580, 0x00000103, 0x04000008, 0x832c0400,
-	0x00000006, 0x0201f800, 0x0010383e, 0x4a01d809,
-	0x00102846, 0x0401f007, 0x832c0400, 0x00000006,
-	0x0201f800, 0x00103841, 0x4a01d809, 0x00102846,
-	0x5c026000, 0x1c01f000, 0x58ec000d, 0x40025800,
-	0x592c0204, 0x82000580, 0x00000103, 0x04020006,
-	0x0201f800, 0x000208b4, 0x5c026000, 0x0201f000,
-	0x00102066, 0x58ec000d, 0x40025800, 0x592c0404,
-	0x8400055e, 0x48025c04, 0x42028800, 0x000007fd,
-	0x42003000, 0x00fffffd, 0x0201f800, 0x001043fc,
-	0x04000003, 0x80000580, 0x0401f004, 0x59a26001,
-	0x0201f800, 0x00109146, 0x5c026000, 0x02000000,
-	0x001020b2, 0x4d300000, 0x4a01d809, 0x00102899,
-	0x0401f7dc, 0x592c0005, 0x82000580, 0x01000000,
-	0x02000000, 0x001020be, 0x4d300000, 0x59a26001,
-	0x5930020b, 0x59301c0a, 0x900001c0, 0x800c1d40,
-	0x5930040d, 0x5930120d, 0x900001c0, 0x80081540,
-	0x592c0a05, 0x832c0400, 0x00000006, 0x0201f800,
-	0x00103841, 0x4a01d809, 0x00102846, 0x4a034000,
-	0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857,
-	0x4c300000, 0x5930040b, 0x82000c80, 0x0000000e,
-	0x04001004, 0x4a025a05, 0x0000000e, 0x0401f003,
-	0x48025a05, 0x0401f00c, 0x800409c0, 0x0400000a,
-	0x4c040000, 0x0201f800, 0x0010381a, 0x5c000800,
-	0x04000003, 0x40040000, 0x0401f7f0, 0x80000580,
-	0x0401f003, 0x82000540, 0x00000001, 0x5c006000,
-	0x1c01f000, 0x59a00206, 0x82000580, 0x00000044,
-	0x1c01f000, 0x4807c857, 0x800409c0, 0x0400000c,
-	0x0201f800, 0x001016c1, 0x04020009, 0x42000000,
-	0x00000002, 0x0201f800, 0x001018fa, 0x42000000,
-	0x00000002, 0x0201f800, 0x00101892, 0x59a00406,
-	0x82000500, 0x00000007, 0x0c01f001, 0x001028ed,
-	0x00102902, 0x00102918, 0x001028eb, 0x001028eb,
-	0x001028eb, 0x001028eb, 0x001028eb, 0x0201f000,
-	0x001020b6, 0x42000800, 0x000000c0, 0x0201f800,
-	0x001019ac, 0x82040540, 0x00000002, 0x42000800,
-	0x000000c0, 0x0201f800, 0x001019b1, 0x42000800,
-	0x00000000, 0x0201f800, 0x001019ac, 0x82040540,
-	0x00000008, 0x42000800, 0x00000000, 0x0201f800,
-	0x001019b1, 0x0401f00b, 0x42000800, 0x000000c0,
-	0x0201f800, 0x001019ac, 0x82040540, 0x00000001,
-	0x42000800, 0x000000c0, 0x0201f800, 0x001019b1,
-	0x59c80040, 0x4c000000, 0x59a80010, 0x4c000000,
-	0x59c400a3, 0x4c000000, 0x59c40008, 0x4c000000,
-	0x0401f911, 0x04000021, 0x0201f800, 0x00100615,
-	0x59a80821, 0x800409c0, 0x02020000, 0x001020ba,
-	0x0201f800, 0x00104e0d, 0x04020005, 0x4a034406,
-	0x00000016, 0x0201f000, 0x001020b2, 0x836c0580,
-	0x00000003, 0x02020000, 0x001020ba, 0x59c408a4,
-	0x82040d00, 0x0000000f, 0x82040580, 0x00000000,
-	0x02020000, 0x001020ba, 0x59c80040, 0x4c000000,
-	0x59a80010, 0x4c000000, 0x59c400a3, 0x4c000000,
-	0x59c40008, 0x4c000000, 0x59c40080, 0x4c000000,
-	0x59a0020f, 0x59a0bc0f, 0x905cb9c0, 0x805cbd40,
-	0x41784800, 0x41785000, 0x41785800, 0x41789000,
-	0x41789800, 0x0401fe21, 0x0201f800, 0x0010698c,
-	0x0201f800, 0x00100b29, 0x4178c000, 0x497b4002,
-	0x0401f95c, 0x0401f9aa, 0x59a0020c, 0x59a00c0c,
-	0x80040d40, 0x04000002, 0x0401f9fb, 0x0401f9fa,
-	0x0401fe68, 0x8060c1c0, 0x04020014, 0x0401fa98,
-	0x0401feb2, 0x0402000e, 0x0201f800, 0x00101941,
-	0x04020008, 0x4a034406, 0x00000017, 0x0201f800,
-	0x001020b2, 0x4203e000, 0x50000000, 0x0401f000,
-	0x42005800, 0x0000aaaa, 0x0401f058, 0x59c80001,
-	0x800001c0, 0x040007ee, 0x59c80801, 0x800409c0,
-	0x04000006, 0x0401fa70, 0x40240000, 0x80280540,
-	0x802c0540, 0x0402004d, 0x59a00002, 0x82000580,
-	0xfeedbeef, 0x04000004, 0x42008800, 0x10000000,
-	0x0401f003, 0x42008800, 0x10000004, 0x0401fa19,
-	0x4a034002, 0xfeedbeef, 0x0401fa71, 0x0401fa97,
-	0x0401fea8, 0x59c40005, 0x8c000534, 0x04000004,
-	0x42005800, 0x0000bbbb, 0x0401f038, 0x0401fe83,
-	0x04020007, 0x42005800, 0x0000cccc, 0x485f420f,
-	0x905cb9c0, 0x485f440f, 0x0401f030, 0x59a0040c,
-	0x800001c0, 0x0400000e, 0x59a26000, 0x5930000d,
-	0x800001c0, 0x040207be, 0x59a26001, 0x5930080d,
-	0x800409c0, 0x040207ba, 0x804891c0, 0x040207b8,
-	0x804c99c0, 0x040207b6, 0x0401f87a, 0x805cb840,
-	0x04000005, 0x40240000, 0x80280540, 0x802c0540,
-	0x0402001a, 0x42000000, 0x00030d40, 0x80000040,
-	0x04020012, 0x59c00007, 0x82000500, 0x000501c0,
-	0x0402000b, 0x0201f800, 0x00101941, 0x04020008,
-	0x4a034406, 0x00000017, 0x0201f800, 0x001020b2,
-	0x4203e000, 0x50000000, 0x0401f000, 0x42005800,
-	0x0000dddd, 0x0401f005, 0x59c00807, 0x82040d00,
-	0x0000000c, 0x040007ea, 0x0401fe5c, 0x59a0040c,
-	0x800001c0, 0x04000002, 0x0401f856, 0x0401fe6b,
-	0x40240000, 0x80280540, 0x802c0540, 0x04020003,
-	0x805cb9c0, 0x04020781, 0x0201f800, 0x00106c8a,
-	0x0401fda3, 0x4201d000, 0x000186a0, 0x0201f800,
-	0x00105e06, 0x5c000800, 0x48078880, 0x5c000800,
-	0x48078808, 0x5c000800, 0x480788a3, 0x5c000800,
-	0x48075010, 0x5c000800, 0x48079040, 0x0201f800,
-	0x001009b6, 0x59a00406, 0x82000500, 0x00000003,
-	0x82000580, 0x00000002, 0x0400002c, 0x42000800,
-	0x000000c0, 0x0201f800, 0x001019ac, 0x82040500,
-	0xfffffffc, 0x42000800, 0x000000c0, 0x0201f800,
-	0x001019b1, 0x42000800, 0x00000000, 0x0201f800,
-	0x001019ac, 0x82040500, 0xfffffff7, 0x42000800,
-	0x00000000, 0x0201f800, 0x001019b1, 0x42000800,
-	0x00000000, 0x0201f800, 0x001019ac, 0x82040500,
-	0xfffffffb, 0x42000800, 0x00000000, 0x0201f800,
-	0x001019b1, 0x4a0388a7, 0x0000f7f7, 0x42006000,
-	0xbeffffff, 0x42006800, 0x80018000, 0x0201f800,
-	0x001040ad, 0x42006000, 0xfffeffff, 0x41786800,
-	0x0201f800, 0x001040ad, 0x402c0000, 0x80280540,
-	0x80240540, 0x02000000, 0x00102066, 0x48274406,
-	0x482b4207, 0x482f4407, 0x0201f000, 0x001020c2,
-	0x59a26000, 0x813261c0, 0x0400000e, 0x59325808,
-	0x812e59c0, 0x0400000b, 0x0201f800, 0x000208b4,
-	0x0201f800, 0x00100843, 0x59a26001, 0x59325808,
-	0x0201f800, 0x000208b4, 0x0201f800, 0x00100843,
-	0x1c01f000, 0x42000800, 0x000000ef, 0x0201f800,
-	0x00101655, 0x59c400a3, 0x8400055a, 0x8400053a,
-	0x480388a3, 0x0201f800, 0x001016ac, 0x0402000a,
-	0x42000000, 0x00000001, 0x0201f800, 0x001018fa,
-	0x42000000, 0x00000001, 0x0201f800, 0x00101892,
-	0x0401f013, 0x0201f800, 0x001016b3, 0x04020008,
-	0x41780000, 0x0201f800, 0x001018fa, 0x41780000,
-	0x0201f800, 0x00101892, 0x0401f009, 0x42000000,
-	0x00000002, 0x0201f800, 0x001018fa, 0x42000000,
-	0x00000002, 0x0201f800, 0x00101892, 0x42000800,
-	0x00000000, 0x0201f800, 0x001019ac, 0x82040540,
-	0x00000004, 0x42000800, 0x00000000, 0x0201f800,
-	0x001019b1, 0x4201d000, 0x00000014, 0x0201f800,
-	0x00105dd2, 0x59c40008, 0x8400054e, 0x82000500,
-	0xffffffe1, 0x48038808, 0x4a0388a7, 0x0000f7f7,
-	0x42001000, 0x04000001, 0x0201f800, 0x001019aa,
-	0x42006000, 0xbe20bfff, 0x42006800, 0x80018000,
-	0x0201f800, 0x001040ad, 0x42006000, 0xfffeffff,
-	0x41786800, 0x0201f800, 0x001040ad, 0x4200b000,
-	0x00001388, 0x4201d000, 0x00000014, 0x4c580000,
-	0x0201f800, 0x00105dd2, 0x0201f800, 0x00101941,
-	0x5c00b000, 0x04000004, 0x8058b040, 0x040207f6,
-	0x0401f025, 0x59c40005, 0x8c000534, 0x04020007,
-	0x59c400a4, 0x82000500, 0x0000000f, 0x82000580,
-	0x00000008, 0x0402001c, 0x42006000, 0x00020000,
-	0x0201f800, 0x001040b2, 0x4201d000, 0x00000064,
-	0x0201f800, 0x00105dd2, 0x42006000, 0xfeffffff,
-	0x42006800, 0x02000000, 0x0201f800, 0x001040ad,
-	0x42006000, 0xfdffffff, 0x41786800, 0x0201f800,
-	0x001040ad, 0x4a038805, 0x04000001, 0x59c400a4,
-	0x82000500, 0x0000000f, 0x82000580, 0x00000000,
-	0x04000003, 0x82000540, 0x00000001, 0x1c01f000,
-	0x4803c856, 0x42038000, 0x00007700, 0x0201f800,
-	0x00100f0f, 0x59c00006, 0x59a0040c, 0x800001c0,
-	0x0400003f, 0x59a03c0c, 0x59a00209, 0x59a01c09,
-	0x900c19c0, 0x800c1d40, 0x59a0020e, 0x59a0240e,
-	0x901021c0, 0x80102540, 0x59a0020b, 0x82000500,
-	0x0000fffc, 0x59a0140b, 0x900811c0, 0x80081540,
-	0x480b8003, 0x0201f800, 0x00020892, 0x02000800,
-	0x00100615, 0x49334000, 0x0201f800, 0x0010082a,
-	0x4a025a04, 0x00000018, 0x4a025805, 0x00abcdef,
-	0x492e6008, 0x492e600b, 0x481e600d, 0x4a02600c,
-	0x00000004, 0x832c0400, 0x00000011, 0x4802600a,
-	0x42001000, 0x0000000c, 0x821c0d80, 0x00000001,
-	0x04000004, 0x801c3840, 0x0401f963, 0x0401f004,
-	0x41783800, 0x0401f960, 0x0401f011, 0x821c0c80,
-	0x00000005, 0x04001005, 0x40043800, 0x42001000,
-	0x0000003c, 0x0401f006, 0x80001580, 0x82081400,
-	0x0000000c, 0x801c3840, 0x040207fd, 0x832c0400,
-	0x00000005, 0x0401f950, 0x040207f1, 0x497b9009,
-	0x59e00003, 0x82000540, 0x00008060, 0x4803c003,
-	0x4a038009, 0x00e00000, 0x1c01f000, 0x4803c856,
-	0x41780800, 0x8007a0ca, 0x83d3a400, 0x00007600,
-	0x42000800, 0x00000040, 0x0201f800, 0x00101395,
-	0x4a03a00a, 0x00000001, 0x4a03a005, 0x20000000,
-	0x59d00006, 0x4a03a005, 0x30000000, 0x59d00006,
-	0x8c00050a, 0x040207fe, 0x59d00005, 0x59a0020c,
-	0x800001c0, 0x0400003f, 0x59a03a0c, 0x59a00210,
-	0x59a01c10, 0x900c19c0, 0x800c1d40, 0x59a0020d,
-	0x59a0240d, 0x901021c0, 0x80102540, 0x59a0120b,
-	0x82081500, 0x0000fffc, 0x59a0040b, 0x900001c0,
-	0x80081540, 0x480ba003, 0x0201f800, 0x00020892,
-	0x02000800, 0x00100615, 0x49334001, 0x0201f800,
-	0x0010082a, 0x4a025a04, 0x00000018, 0x4a025805,
-	0x00abcdef, 0x492e6008, 0x492e600b, 0x481e600d,
-	0x4a02600c, 0x00000004, 0x832c0400, 0x00000011,
-	0x4802600a, 0x42001000, 0x0000000c, 0x821c0d80,
-	0x00000001, 0x04000004, 0x801c3840, 0x0401f906,
-	0x0401f004, 0x41783800, 0x0401f903, 0x0401f011,
-	0x821c0c80, 0x00000005, 0x04001005, 0x40043800,
-	0x42001000, 0x0000003c, 0x0401f006, 0x80001580,
-	0x82081400, 0x0000000c, 0x801c3840, 0x040207fd,
-	0x832c0400, 0x00000005, 0x0401f8f3, 0x040207f1,
-	0x1c01f000, 0x4803c856, 0x59a0020c, 0x800001c0,
-	0x04000024, 0x824c0580, 0x00000002, 0x04000040,
-	0x59a26001, 0x5930380d, 0x801c39c0, 0x0400003c,
-	0x801c3840, 0x481e600d, 0x5932580b, 0x5930080a,
-	0x50042000, 0x58041801, 0x58041002, 0x82081500,
-	0xfffffffc, 0x5930000c, 0x80000000, 0x82000d80,
-	0x00000005, 0x04020009, 0x497a600c, 0x592e5801,
-	0x812e59c0, 0x0400001a, 0x492e600b, 0x832c0c00,
-	0x00000005, 0x0401f005, 0x4802600c, 0x5930080a,
-	0x82040c00, 0x00000003, 0x4806600a, 0x0401f010,
-	0x59a0120b, 0x82081500, 0x0000fffc, 0x59a0040b,
-	0x900001c0, 0x80081540, 0x480ba003, 0x59a0020d,
-	0x59a0240d, 0x901021c0, 0x80102540, 0x59a00210,
-	0x59a01c10, 0x900c19c0, 0x800c1d40, 0x4201d000,
-	0x00003a98, 0x0201f800, 0x00105e06, 0x480ba002,
-	0x59a80059, 0x4803a008, 0x4813a000, 0x480fa001,
-	0x4a03a005, 0x10000000, 0x02005800, 0x00100615,
-	0x804c9800, 0x82000540, 0x00000001, 0x1c01f000,
-	0x4847c857, 0x59a0040c, 0x800001c0, 0x04000024,
-	0x82480580, 0x00000002, 0x04000042, 0x59a26000,
-	0x5930380d, 0x801c39c0, 0x0400003e, 0x801c3840,
-	0x481e600d, 0x5932580b, 0x5930080a, 0x50042000,
-	0x58041801, 0x58041002, 0x82081500, 0xfffffffc,
-	0x5930000c, 0x80000000, 0x82000d80, 0x00000005,
-	0x04020009, 0x497a600c, 0x592e5801, 0x812e59c0,
-	0x0400001d, 0x492e600b, 0x832c0c00, 0x00000005,
-	0x0401f005, 0x4802600c, 0x5930080a, 0x82040c00,
-	0x00000003, 0x4806600a, 0x0401f013, 0x82440580,
-	0x10000000, 0x0402001f, 0x59a0020e, 0x59a0240e,
-	0x901021c0, 0x80102540, 0x59a00209, 0x59a01c09,
-	0x900c19c0, 0x800c1d40, 0x59a0020b, 0x82000500,
-	0x0000fffc, 0x59a0140b, 0x900811c0, 0x80081540,
-	0x480b8003, 0x48138000, 0x480f8001, 0x480b8002,
-	0x59c80018, 0x82000500, 0xf0000000, 0x59c02008,
-	0x82102500, 0x0fffffff, 0x80100540, 0x48038008,
-	0x48478006, 0x80489000, 0x8260c540, 0x00000001,
-	0x1c01f000, 0x59c00009, 0x4803c857, 0x82000d00,
-	0x00e00000, 0x0400000d, 0x485f420f, 0x905cb9c0,
-	0x485f440f, 0x8c00052e, 0x04000002, 0x80285000,
-	0x8c00052c, 0x04000002, 0x80244800, 0x8c00052a,
-	0x04000002, 0x802c5800, 0x1c01f000, 0x59a0020c,
-	0x800001c0, 0x04000024, 0x59d00806, 0x4807c857,
-	0x8c040d3e, 0x04000020, 0x4a03a005, 0x20000000,
-	0x4a03a005, 0x30000000, 0x59d00806, 0x8c040d0a,
-	0x040207fe, 0x824c0480, 0x00000003, 0x02021800,
-	0x00100615, 0x404c0000, 0x0c01f001, 0x00102c02,
-	0x00102c04, 0x00102c0a, 0x0201f800, 0x00100615,
-	0x80000040, 0x40009800, 0x0401ff43, 0x0400000a,
-	0x0401ff41, 0x0401f008, 0x80000040, 0x40009800,
-	0x59d00806, 0x4807c857, 0x8c040d3e, 0x040207e3,
-	0x0401ff39, 0x1c01f000, 0x59a0040c, 0x800001c0,
-	0x04000024, 0x59c00807, 0x4807c857, 0x8c040d3e,
-	0x04000020, 0x59c00807, 0x4a038006, 0x20000000,
-	0x82480480, 0x00000003, 0x02021800, 0x00100615,
-	0x40480000, 0x0c01f001, 0x00102c25, 0x00102c27,
-	0x00102c2f, 0x0201f800, 0x00100615, 0x80000040,
-	0x40009000, 0x42008800, 0x10000004, 0x0401ff65,
-	0x0400000c, 0x0401ff63, 0x0401f00a, 0x80000040,
-	0x40009000, 0x59c00807, 0x4807c857, 0x8c040d3e,
-	0x040207e5, 0x42008800, 0x10000004, 0x0401ff59,
-	0x1c01f000, 0x492fc857, 0x4000a800, 0x4a03b805,
-	0x20000000, 0x59dc0006, 0x4a03b805, 0x30000000,
-	0x4813b800, 0x480fb801, 0x480bb802, 0x4857b803,
-	0x4a03b805, 0x30000002, 0x59dc0006, 0x4a03b805,
-	0x70000001, 0x59dc0006, 0x4a03b805, 0x10000000,
-	0x59dc0006, 0x8c00053e, 0x040007fe, 0x4a03b805,
-	0x20000000, 0x59dc0006, 0x59dc2000, 0x59dc1801,
-	0x801c39c0, 0x0400000a, 0x4d2c0000, 0x0201f800,
-	0x0010082a, 0x5c000800, 0x02000800, 0x00100615,
-	0x4a025a04, 0x0000000a, 0x492c0801, 0x1c01f000,
-	0x42006000, 0x00102d9d, 0x42000800, 0x0000007c,
-	0x0201f800, 0x00101395, 0x4a03902c, 0x00200000,
-	0x4200b000, 0x000001f4, 0x59c8002c, 0x8c00052c,
-	0x04000007, 0x8058b040, 0x040207fc, 0x42000000,
-	0x00004003, 0x41781000, 0x0401f11e, 0x50301000,
-	0x41784800, 0x4a03902d, 0x00008000, 0x4200b000,
-	0x000001f4, 0x59c8002c, 0x8c000534, 0x04000007,
-	0x8058b040, 0x040207fc, 0x42000000, 0x00004003,
-	0x41781000, 0x0401f10f, 0x0401f895, 0x80244800,
-	0x82240580, 0x000003b1, 0x040207fc, 0x0401f911,
-	0x41784800, 0x0401f8bb, 0x80244800, 0x82240580,
-	0x000003b1, 0x040207fc, 0x80306000, 0x82300580,
-	0x00102d9f, 0x040207e2, 0x59a80863, 0x800409c0,
-	0x04000007, 0x42000000, 0x00004004, 0x42001000,
-	0x00000002, 0x59a81862, 0x0401f0f6, 0x42006000,
-	0x00102d9d, 0x50301000, 0x41784800, 0x4a03902d,
-	0x00000800, 0x0401f876, 0x80244800, 0x82240580,
-	0x00000018, 0x040207fc, 0x0401f8f2, 0x41784800,
-	0x0401f89c, 0x80244800, 0x82240580, 0x00000018,
-	0x040207fc, 0x80306000, 0x82300580, 0x00102d9f,
-	0x040207ed, 0x59a80863, 0x800409c0, 0x04000007,
-	0x42000000, 0x00004004, 0x42001000, 0x00000010,
-	0x59a81862, 0x0401f0d7, 0x42006000, 0x00102d9d,
-	0x50301000, 0x41784800, 0x4a03902d, 0x00000400,
-	0x0401f857, 0x80244800, 0x82240580, 0x00000088,
-	0x040207fc, 0x0401f8d3, 0x41784800, 0x0401f87d,
-	0x80244800, 0x82240580, 0x00000088, 0x040207fc,
-	0x80306000, 0x82300580, 0x00102d9f, 0x040207ed,
-	0x59a80863, 0x800409c0, 0x04000007, 0x42000000,
-	0x00004004, 0x42001000, 0x00000008, 0x59a81862,
-	0x0401f0b8, 0x42006000, 0x00102d9d, 0x50301000,
-	0x41784800, 0x4a03902d, 0x00002000, 0x4200b000,
-	0x000001f4, 0x59c8002c, 0x8c000530, 0x04000007,
-	0x8058b040, 0x040207fc, 0x42000000, 0x00004003,
-	0x41781000, 0x0401f0a7, 0x59c8002c, 0x82000500,
-	0xffe0ffff, 0x82080d00, 0x001f0000, 0x80040540,
-	0x4803902c, 0x0401f826, 0x80244800, 0x82240580,
-	0x00000110, 0x040207fc, 0x0401f8a2, 0x41784800,
-	0x0401f84c, 0x59c80034, 0x82080d00, 0x001f0000,
-	0x82000500, 0x001f0000, 0x80040580, 0x04000006,
-	0x59a80063, 0x80000000, 0x48035063, 0x40240000,
-	0x48035062, 0x80244800, 0x82240580, 0x00000110,
-	0x040207f0, 0x80306000, 0x82300580, 0x00102d9f,
-	0x040207cf, 0x59a80863, 0x800409c0, 0x04000006,
-	0x42000000, 0x00004004, 0x42001000, 0x00000020,
-	0x59a81862, 0x0201f000, 0x00102066, 0x59c8002c,
-	0x82000500, 0xffff0000, 0x82080d00, 0x0000ffff,
-	0x80040540, 0x4803902c, 0x480b9028, 0x480b9029,
-	0x59a80064, 0x82000580, 0x00000004, 0x04000003,
-	0x480b902a, 0x480b902b, 0x59c8002d, 0x82000500,
-	0xfffffc00, 0x80240540, 0x4803902d, 0x4200b000,
-	0x000001f4, 0x59c8002c, 0x82000500, 0x18000000,
-	0x04000007, 0x8058b040, 0x040207fb, 0x42000000,
-	0x00004003, 0x41781000, 0x0401f05a, 0x4a03902e,
-	0x00000001, 0x4200b000, 0x000001f4, 0x59c8002e,
-	0x8c000500, 0x04000006, 0x8058b040, 0x040207fc,
-	0x42000000, 0x00004003, 0x0401f04e, 0x1c01f000,
-	0x41783800, 0x59c8002d, 0x82000500, 0xfffffc00,
-	0x80240d40, 0x4807902d, 0x4200b000, 0x000001f4,
-	0x59c8002c, 0x82000500, 0x18000000, 0x04000007,
-	0x8058b040, 0x040207fb, 0x42000000, 0x00004003,
-	0x41781000, 0x0401f03b, 0x59c81830, 0x59c80030,
-	0x800c0d80, 0x040207fd, 0x80080d80, 0x04000002,
-	0x801c3800, 0x59c82031, 0x59c80031, 0x80100d80,
-	0x040207fd, 0x80080d80, 0x04000002, 0x801c3800,
-	0x59a80064, 0x82000580, 0x00000004, 0x04000019,
-	0x59c82832, 0x59c80032, 0x80140d80, 0x040207fd,
-	0x80080d80, 0x04000002, 0x801c3800, 0x59c83033,
-	0x59c80033, 0x80180d80, 0x040207fd, 0x80080d80,
-	0x04000002, 0x801c3800, 0x59c80034, 0x59c80834,
-	0x80040d80, 0x040207fd, 0x80080d80, 0x82040d00,
-	0x0000ffff, 0x0400000c, 0x801c3800, 0x0401f00a,
-	0x59c80034, 0x59c80834, 0x80040d80, 0x040207fd,
-	0x80080d80, 0x82040d00, 0x000000ff, 0x04000002,
-	0x801c3800, 0x801c39c0, 0x04000005, 0x59a80063,
-	0x801c0400, 0x48035063, 0x48275062, 0x1c01f000,
-	0x48034206, 0x48074406, 0x480b4207, 0x480f4407,
-	0x48134208, 0x48174408, 0x0201f000, 0x00102069,
-	0x42000000, 0x00600000, 0x80000040, 0x040207ff,
-	0x1c01f000, 0x5a5a5a5a, 0xa5a5a5a5, 0x59a00c0a,
-	0x800409c0, 0x02000000, 0x001020b6, 0x82040480,
-	0x00000021, 0x02021000, 0x001020b6, 0x82040480,
-	0x00000011, 0x04001003, 0x42000800, 0x00000010,
-	0x59a00208, 0x59a01407, 0x900811c0, 0x80081540,
-	0x59a00207, 0x59a01c06, 0x900c19c0, 0x800c1d40,
-	0x0201f800, 0x0010381a, 0x04000006, 0x0201f800,
-	0x0010383e, 0x4a01d809, 0x00102dc0, 0x1c01f000,
-	0x4a034406, 0x00000002, 0x0201f000, 0x001020b2,
-	0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
-	0x00000200, 0x02000000, 0x001020aa, 0x59a00c0a,
-	0x82040480, 0x00000011, 0x04001003, 0x42000800,
-	0x00000010, 0x59a0040b, 0x59a0120b, 0x900811c0,
-	0x80081540, 0x59a00209, 0x59a01c08, 0x900c19c0,
-	0x800c1d40, 0x58ec0003, 0x0201f800, 0x00103841,
-	0x4a01d809, 0x00102ddb, 0x1c01f000, 0x4031d800,
-	0x58ef400b, 0x58ec0002, 0x82000580, 0x00000200,
-	0x02000000, 0x001020aa, 0x59a00c0a, 0x82040480,
-	0x00000011, 0x02001000, 0x00102066, 0x82040c80,
-	0x00000010, 0x59a00208, 0x59a01407, 0x900811c0,
-	0x80081540, 0x59a00207, 0x59a01c06, 0x900c19c0,
-	0x800c1d40, 0x82081400, 0x00000040, 0x58ec0003,
-	0x0201f800, 0x0010383e, 0x4a01d809, 0x00102df9,
-	0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002,
-	0x82000580, 0x00000200, 0x02000000, 0x001020aa,
-	0x59a0040a, 0x82000c80, 0x00000010, 0x59a0040b,
-	0x59a0120b, 0x900811c0, 0x80081540, 0x59a00209,
-	0x59a01c08, 0x900c19c0, 0x800c1d40, 0x82081400,
-	0x00000040, 0x58ec0003, 0x0201f800, 0x00103841,
-	0x4a01d809, 0x0010205f, 0x1c01f000, 0x48efc857,
-	0x59a00207, 0x59a01407, 0x900001c0, 0x80081540,
-	0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40,
-	0x59a00406, 0x48034000, 0x480b4001, 0x480f4002,
-	0x0201f800, 0x0010381a, 0x04020005, 0x4a034406,
-	0x00000002, 0x0201f000, 0x001020b2, 0x42000800,
-	0x00000010, 0x0201f800, 0x0010383e, 0x4a01d809,
-	0x00102e2e, 0x1c01f000, 0x4031d800, 0x58ef400b,
-	0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
-	0x02000000, 0x001020aa, 0x48efc857, 0x49a3c857,
-	0x492fc857, 0x592c0a04, 0x80040910, 0x04020005,
-	0x4a034406, 0x00000019, 0x0201f000, 0x001020b2,
-	0x4805d80c, 0x0401f00a, 0x4031d800, 0x58ef400b,
-	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
-	0x001020aa, 0x48efc857, 0x49a3c857, 0x48efc857,
-	0x49a3c857, 0x58ec000c, 0x80000040, 0x04000012,
-	0x4801d80c, 0x0201f800, 0x0010381a, 0x04020005,
-	0x4a034406, 0x00000002, 0x0201f000, 0x001020b2,
-	0x42000800, 0x00000010, 0x58ec1007, 0x58ec1808,
-	0x0201f800, 0x0010383e, 0x4a01d809, 0x00102e42,
-	0x1c01f000, 0x58ee580d, 0x48efc857, 0x49a3c857,
-	0x492fc857, 0x492f3006, 0x592c0404, 0x8400055e,
-	0x48025c04, 0x4a01d809, 0x00102e6c, 0x1c01f000,
-	0x4d2c0000, 0x58ee580d, 0x48efc857, 0x49a3c857,
-	0x492fc857, 0x592c0404, 0x8400051e, 0x48025c04,
-	0x59a00000, 0x59a01001, 0x59a01802, 0x80081400,
-	0x820c1c40, 0x00000000, 0x832c0400, 0x00000004,
-	0x42000800, 0x00000010, 0x5c025800, 0x0201f000,
-	0x00103841, 0x800409c0, 0x04000005, 0x4a034406,
-	0x00000001, 0x0201f000, 0x001020b2, 0x836c0580,
-	0x00000003, 0x04000005, 0x4a034406, 0x00000007,
-	0x0201f000, 0x001020b2, 0x59a0320b, 0x82183500,
-	0x000000ff, 0x59a28c06, 0x0201f800, 0x00020267,
-	0x02020000, 0x001020b6, 0x83440580, 0x000007fd,
-	0x04000008, 0x0201f800, 0x00104836, 0x04000005,
-	0x4a034406, 0x00000009, 0x0201f000, 0x001020b2,
-	0x0201f800, 0x0010381a, 0x04020005, 0x4a034406,
-	0x00000002, 0x0201f000, 0x001020b2, 0x801831c0,
-	0x0400000a, 0x412c0800, 0x0201f800, 0x0010381a,
-	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
-	0x001020b2, 0x40065800, 0x4a025c04, 0x00008000,
-	0x497a5a04, 0x0201f800, 0x00108ebd, 0x04020005,
-	0x4a034406, 0x00000003, 0x0201f000, 0x001020b2,
-	0x4a01d809, 0x00102ebf, 0x1c01f000, 0x592c0005,
-	0x82000580, 0x01000000, 0x04020005, 0x4a034406,
-	0x00000004, 0x0201f000, 0x001020b2, 0x592c0406,
-	0x82002d00, 0x0000ff00, 0x82000500, 0x000000ff,
-	0x80000904, 0x80040800, 0x82040480, 0x00000006,
-	0x04001003, 0x42000800, 0x00000005, 0x4c500000,
-	0x4c540000, 0x4c580000, 0x832ca400, 0x00000006,
-	0x4050a800, 0x4004b000, 0x0201f800, 0x0010a94f,
-	0x59a00407, 0x59a01207, 0x900811c0, 0x80081540,
-	0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40,
-	0x832c0400, 0x00000006, 0x4c140000, 0x0201f800,
-	0x00103841, 0x5c002800, 0x801429c0, 0x04000003,
-	0x4a01d809, 0x00102ef2, 0x5c00b000, 0x5c00a800,
-	0x5c00a000, 0x1c01f000, 0x4031d800, 0x58ef400b,
-	0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
-	0x02000000, 0x001020aa, 0x812e59c0, 0x02000800,
-	0x00100615, 0x592c0006, 0x82000500, 0xff000000,
-	0x80000904, 0x800409c0, 0x02000000, 0x001020aa,
-	0x82040480, 0x0000000e, 0x04001003, 0x42000800,
-	0x0000000d, 0x592e5801, 0x812e59c0, 0x02000800,
-	0x00100615, 0x4c500000, 0x4c540000, 0x4c580000,
-	0x832ca400, 0x00000005, 0x4050a800, 0x4004b000,
-	0x0201f800, 0x0010a94f, 0x5c00b000, 0x5c00a800,
-	0x5c00a000, 0x58ec1007, 0x58ec1808, 0x832c0400,
-	0x00000005, 0x0201f000, 0x00103841, 0x0201f800,
-	0x0010381a, 0x04020005, 0x4a034406, 0x00000002,
-	0x0201f000, 0x001020b2, 0x59a00c06, 0x82040500,
-	0x0000ff00, 0x840001c0, 0x82001480, 0x00000007,
-	0x02021000, 0x001020b6, 0x0c01f001, 0x00102f36,
-	0x00102f3d, 0x00102f44, 0x00102f44, 0x00102f44,
-	0x00102f46, 0x00102f4b, 0x42000800, 0x0000000d,
-	0x42003800, 0x00102f5f, 0x4a034000, 0x0010b2e7,
-	0x0401f013, 0x42000800, 0x0000000d, 0x42003800,
-	0x00102f5f, 0x4a034000, 0x0010b2f4, 0x0401f00c,
-	0x0201f000, 0x001020b6, 0x42000800, 0x00000008,
-	0x42003800, 0x00102f72, 0x0401f005, 0x42000800,
-	0x00000004, 0x42003800, 0x00102fbc, 0x59a00207,
-	0x59a01407, 0x900001c0, 0x80081540, 0x59a00209,
-	0x59a01c09, 0x900001c0, 0x800c1d40, 0x832c0400,
-	0x00000005, 0x4c1c0000, 0x0201f800, 0x0010383e,
-	0x5c003800, 0x481dd809, 0x1c01f000, 0x4031d800,
-	0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
-	0x00000200, 0x02000000, 0x001020aa, 0x4a03501f,
-	0x00000001, 0x4200b000, 0x0000000d, 0x59a0a800,
-	0x832ca400, 0x00000005, 0x0201f800, 0x0010a93e,
-	0x0201f000, 0x00102066, 0x4031d800, 0x58ef400b,
-	0x58ee580d, 0x58ec0002, 0x82000580, 0x00000200,
-	0x02000000, 0x001020aa, 0x832ca400, 0x00000005,
-	0x50500000, 0x82001500, 0x000c0016, 0x02020000,
-	0x001020b6, 0x82500c00, 0x00000003, 0x50040000,
-	0x82001500, 0x00000001, 0x02020000, 0x001020b6,
-	0x50500000, 0x82001500, 0x00000028, 0x0400001d,
-	0x82081580, 0x00000028, 0x02020000, 0x001020b6,
-	0x80500800, 0x50040000, 0x82001500, 0x00000013,
-	0x82081580, 0x00000013, 0x02020000, 0x001020b6,
-	0x80040800, 0x50040000, 0x82001500, 0x00010000,
-	0x82081580, 0x00010000, 0x02020000, 0x001020b6,
-	0x836c0580, 0x00000000, 0x04000012, 0x599c0019,
-	0x8c00050e, 0x0402000f, 0x0201f000, 0x001020b6,
-	0x80500800, 0x50040000, 0x82001500, 0x00000013,
-	0x02020000, 0x001020b6, 0x80040800, 0x50040000,
-	0x82001500, 0x00010000, 0x02020000, 0x001020b6,
-	0x4200b000, 0x00000008, 0x4200a800, 0x0010b2df,
-	0x0201f800, 0x0010a93e, 0x0201f000, 0x00102066,
-	0x4031d800, 0x58ef400b, 0x58ee580d, 0x58ec0002,
-	0x82000580, 0x00000200, 0x02000000, 0x001020aa,
-	0x4200b000, 0x00000004, 0x4200a800, 0x0010b6f9,
-	0x832ca400, 0x00000005, 0x0201f800, 0x0010a93e,
-	0x59a80005, 0x84000550, 0x48035005, 0x0201f000,
-	0x00102066, 0x0201f800, 0x0010381a, 0x04020005,
-	0x4a034406, 0x00000002, 0x0201f000, 0x001020b2,
-	0x59a00c06, 0x82040500, 0x0000ff00, 0x840001c0,
-	0x82001480, 0x00000006, 0x02021000, 0x001020b6,
-	0x0c01f001, 0x00102fe7, 0x00102fec, 0x00102ff1,
-	0x00102ff1, 0x00102ff1, 0x00102ff3, 0x42000800,
-	0x0000000d, 0x4200a000, 0x0010b2e7, 0x0401f00c,
-	0x42000800, 0x0000000d, 0x4200a000, 0x0010b2f4,
-	0x0401f007, 0x0201f000, 0x001020b6, 0x42000800,
-	0x00000008, 0x4200a000, 0x0010b2df, 0x4004b000,
-	0x832cac00, 0x00000005, 0x0201f800, 0x0010a93e,
-	0x59a00207, 0x59a01407, 0x900001c0, 0x80081540,
-	0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40,
-	0x832c0400, 0x00000005, 0x0201f000, 0x00103841,
-	0x836c0580, 0x00000000, 0x04020005, 0x4a034406,
-	0x00000007, 0x0201f000, 0x001020b2, 0x59a01406,
-	0x800811c0, 0x04020017, 0x59c40801, 0x82040d00,
-	0x00018000, 0x82040580, 0x00000000, 0x04020004,
-	0x4a034406, 0x00000000, 0x0401f048, 0x82040580,
-	0x00008000, 0x04020004, 0x4a034406, 0x00000001,
-	0x0401f042, 0x82040580, 0x00010000, 0x02020800,
-	0x00100615, 0x4a034406, 0x00000003, 0x0401f03b,
-	0x59a8006f, 0x8c000508, 0x04000005, 0x42000000,
-	0x00000001, 0x40000800, 0x0401f003, 0x59a00207,
-	0x59a80853, 0x48035053, 0x0201f800, 0x001016ac,
-	0x0400000d, 0x0201f800, 0x001016b3, 0x0400000a,
-	0x0201f800, 0x001016ba, 0x04000007, 0x0201f800,
-	0x001016c1, 0x04000004, 0x48075053, 0x0201f000,
-	0x001020b6, 0x82080580, 0x00000002, 0x0402001f,
-	0x59c40006, 0x84000500, 0x48038806, 0x0201f800,
-	0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7,
-	0x0201f800, 0x0010a7f5, 0x42000000, 0x0010b6c9,
-	0x0201f800, 0x0010a86e, 0x82000540, 0x00000001,
-	0x0201f800, 0x00104e5d, 0x4a038808, 0x00000000,
-	0x4202d800, 0x00000004, 0x42001000, 0x00000001,
-	0x0201f800, 0x001019aa, 0x4a035049, 0x00000001,
-	0x0201f800, 0x0010071a, 0x0201f000, 0x00102066,
-	0x800409c0, 0x04000005, 0x4a034406, 0x00000001,
-	0x0201f000, 0x001020b2, 0x836c0580, 0x00000003,
-	0x04000005, 0x4a034406, 0x00000007, 0x0201f000,
-	0x001020b2, 0x59a28c06, 0x59a0320b, 0x82183500,
-	0x000000ff, 0x0201f800, 0x00020267, 0x02020000,
-	0x001020b6, 0x83440580, 0x000007fd, 0x04000008,
-	0x0201f800, 0x00104836, 0x04000005, 0x42000800,
-	0x00000009, 0x0201f000, 0x001020b2, 0x0201f800,
-	0x0010381a, 0x04020005, 0x4a034406, 0x00000002,
-	0x0201f000, 0x001020b2, 0x497a5a04, 0x4a025c04,
-	0x00008000, 0x0201f800, 0x00108ed2, 0x04020005,
-	0x4a034406, 0x00000003, 0x0201f000, 0x001020b2,
-	0x4a01d809, 0x00103097, 0x1c01f000, 0x592c0005,
-	0x82000d00, 0x0000ffff, 0x82000500, 0xffff0000,
-	0x82000580, 0x01000000, 0x04020005, 0x4a034406,
-	0x00000004, 0x0201f000, 0x001020b2, 0x80040904,
-	0x4c500000, 0x4c540000, 0x4c580000, 0x832ca400,
-	0x00000005, 0x4050a800, 0x4004b000, 0x0201f800,
-	0x0010a94f, 0x5c00b000, 0x5c00a800, 0x5c00a000,
-	0x59a00207, 0x59a01407, 0x900001c0, 0x80081540,
-	0x59a00209, 0x59a01c09, 0x900001c0, 0x800c1d40,
-	0x832c0400, 0x00000005, 0x0201f000, 0x00103841,
-	0x496fc857, 0x836c0580, 0x00000000, 0x04000005,
-	0x4a034406, 0x0000001a, 0x0201f000, 0x001020b2,
-	0x0201f800, 0x00104e0d, 0x02020800, 0x00103f5c,
-	0x42000800, 0x00000020, 0x59a00407, 0x59a01207,
-	0x900811c0, 0x80081540, 0x59a00409, 0x59a01a09,
-	0x900c19c0, 0x800c1d40, 0x419c0000, 0x49a3c857,
-	0x0201f800, 0x0010383e, 0x4a01d809, 0x001030d9,
-	0x1c01f000, 0x4833c857, 0x4031d800, 0x58ef400b,
-	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
-	0x001020aa, 0x599c0200, 0x800001c0, 0x02000000,
-	0x001020b6, 0x59a8006f, 0x8c000504, 0x04020003,
-	0x8c000506, 0x04000004, 0x599c0019, 0x8400050c,
-	0x48033819, 0x0201f800, 0x001095a3, 0x59a8006f,
-	0x8c000502, 0x04000004, 0x599c0017, 0x84000508,
-	0x48033817, 0x0201f800, 0x0010393e, 0x04020004,
-	0x8c00050a, 0x02020000, 0x001020b6, 0x4803c857,
-	0x8c000504, 0x04020004, 0x59c408a3, 0x84040d7a,
-	0x480788a3, 0x8c000502, 0x04020004, 0x59c408a3,
-	0x84040d08, 0x480788a3, 0x599c0c02, 0x8c000500,
-	0x04020004, 0x8c000516, 0x04000012, 0x0401f001,
-	0x82041480, 0x0000007f, 0x02021000, 0x001020b6,
-	0x82041400, 0x00101eb5, 0x50081000, 0x82081500,
-	0x000000ff, 0x8c000500, 0x04020006, 0x480b5010,
-	0x42000800, 0x00000003, 0x0201f800, 0x001069af,
-	0x599c0019, 0x8c000506, 0x04000003, 0x4a03b805,
-	0x90000000, 0x8c00050e, 0x0402000b, 0x59a80806,
-	0x8c040d14, 0x04000008, 0x42000800, 0x0010b2df,
-	0x50040800, 0x82040d00, 0x00000028, 0x02020000,
-	0x001020b6, 0x82000500, 0x00000030, 0x04000003,
-	0x80000108, 0x0401f003, 0x42000000, 0x00000002,
-	0x48039040, 0x42000800, 0x00000002, 0x82000400,
-	0x0010321c, 0x50001000, 0x0201f800, 0x001069af,
-	0x599c0201, 0x82000c80, 0x00000100, 0x02001000,
-	0x001020b6, 0x82000c80, 0x00000841, 0x02021000,
-	0x001020b6, 0x82000500, 0x00000007, 0x02020000,
-	0x001020b6, 0x599c0401, 0x80000540, 0x02000000,
-	0x001020b6, 0x599c0409, 0x599c0c07, 0x80040c80,
-	0x02021000, 0x001020b6, 0x80000040, 0x02000000,
-	0x001020b6, 0x599c0209, 0x599c0a07, 0x80040c80,
-	0x02021000, 0x001020b6, 0x80000040, 0x02000000,
-	0x001020b6, 0x0201f800, 0x0010509d, 0x0201f800,
-	0x00104b53, 0x599c0201, 0x48035004, 0x0201f800,
-	0x0010133e, 0x599c020a, 0x800001c0, 0x04000003,
-	0x4803504d, 0x0401f003, 0x4a03504d, 0x000000c8,
-	0x0201f800, 0x0010393e, 0x04000004, 0x0201f800,
-	0x00105e18, 0x417a5000, 0x836c0580, 0x00000000,
-	0x0402009a, 0x599c0003, 0x599c0804, 0x9c0001c0,
-	0x9c0409c0, 0x48035002, 0x48075003, 0x599c1017,
-	0x8c08151c, 0x04000006, 0x599c0005, 0x599c0806,
-	0x9c0001c0, 0x9c0409c0, 0x0401f003, 0x82000500,
-	0xf0ffffff, 0x48035000, 0x48075001, 0x42001000,
-	0x0010b2e7, 0x48001000, 0x48041001, 0x42001000,
-	0x0010b2f4, 0x48001000, 0x48041001, 0x59a8006f,
-	0x8c000508, 0x04020017, 0x8c00050a, 0x04020021,
-	0x599c1019, 0x82081500, 0x0000e000, 0x82080580,
-	0x00000000, 0x0402000c, 0x4a035053, 0x00000000,
-	0x42000000, 0x00000001, 0x0201f800, 0x001018fa,
-	0x42000000, 0x00000001, 0x0201f800, 0x00101892,
-	0x0401f02b, 0x82080580, 0x00002000, 0x0402000a,
-	0x4a035053, 0x00000001, 0x41780000, 0x0201f800,
-	0x001018fa, 0x41780000, 0x0201f800, 0x00101892,
-	0x0401f01f, 0x82080580, 0x00004000, 0x04020006,
-	0x4a035053, 0x00000002, 0x4a035049, 0x00000001,
-	0x0401f017, 0x82080580, 0x00006000, 0x02020000,
-	0x001020b6, 0x59a80858, 0x82040d80, 0x01391077,
-	0x04020005, 0x59e00813, 0x8c040d00, 0x02020000,
-	0x001020b6, 0x4a035053, 0x00000003, 0x42000000,
-	0x00000002, 0x0201f800, 0x001018fa, 0x42000000,
-	0x00000002, 0x0201f800, 0x00101892, 0x599c0019,
-	0x8c000520, 0x0400000d, 0x42000000, 0x00000004,
-	0x42000800, 0x00000040, 0x0201f800, 0x001019b1,
-	0x42000000, 0x00000010, 0x42000800, 0x000000c0,
-	0x0201f800, 0x001019b1, 0x4a035032, 0x0000aaaa,
-	0x599c1018, 0x82081500, 0x00000030, 0x59a8006c,
-	0x80000540, 0x0400000c, 0x82080580, 0x00000000,
-	0x02000000, 0x001020b6, 0x599c1018, 0x82081500,
-	0xffffffcf, 0x82081540, 0x00000010, 0x480b3818,
-	0x0401f010, 0x82080d80, 0x00000000, 0x04000007,
-	0x82080d80, 0x00000010, 0x0400000a, 0x82080d80,
-	0x00000020, 0x04020002, 0x48075032, 0x0201f800,
-	0x001038d3, 0x04000008, 0x0201f800, 0x00101668,
-	0x0201f800, 0x00101694, 0x59a8002a, 0x80040540,
-	0x4803502a, 0x49f3c857, 0x42001000, 0x00104d39,
-	0x0201f800, 0x00105cc9, 0x42001000, 0x00104d2c,
-	0x0201f800, 0x00105dbd, 0x4a038805, 0xffffffff,
-	0x4a03c014, 0x00400040, 0x4a03c013, 0x00400000,
-	0x0201f800, 0x00104717, 0x59a0001d, 0x84000540,
-	0x4803401d, 0x49f3c857, 0x0201f000, 0x00102066,
-	0x00000018, 0x0000000c, 0x00000018, 0x00000020,
-	0x836c0580, 0x00000000, 0x04020005, 0x42000800,
-	0x00000007, 0x0201f000, 0x001020b2, 0x42000800,
-	0x00000020, 0x59a00407, 0x59a01207, 0x900811c0,
-	0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
-	0x800c1d40, 0x419c0000, 0x0201f000, 0x00103841,
-	0x800409c0, 0x04000005, 0x4a034406, 0x00000001,
-	0x0201f000, 0x001020b2, 0x0201f800, 0x00104e0d,
-	0x04020005, 0x4a034406, 0x00000016, 0x0201f000,
-	0x001020b2, 0x59a80013, 0x8c000500, 0x04000011,
-	0x4a034406, 0x00000000, 0x42000800, 0x00000020,
-	0x59a00407, 0x59a01207, 0x900811c0, 0x80081540,
-	0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40,
-	0x42000000, 0x0010bc20, 0x0201f000, 0x00103841,
-	0x4a034406, 0x00000001, 0x4200b000, 0x00000020,
-	0x4200a800, 0x0010bc20, 0x4200a000, 0xffffffff,
-	0x4450a800, 0x8054a800, 0x8058b040, 0x040207fd,
-	0x4d440000, 0x4d340000, 0x42028800, 0xffffffff,
-	0x42002000, 0xffffffff, 0x42003000, 0x00000001,
-	0x42003800, 0x00000001, 0x42001800, 0x0010bc20,
-	0x59a81010, 0x82081500, 0x000000ff, 0x40180000,
-	0x0c01f001, 0x00103275, 0x00103278, 0x0010327c,
-	0x00103280, 0x82102500, 0xffffff00, 0x0401f014,
-	0x82102500, 0xffff00ff, 0x840811c0, 0x0401f010,
-	0x82102500, 0xff00ffff, 0x900811c0, 0x0401f00c,
-	0x82102500, 0x00ffffff, 0x9c0801c0, 0x80102540,
-	0x44101800, 0x42003000, 0xffffffff, 0x42002000,
-	0xffffffff, 0x800c1800, 0x0401f003, 0x40080000,
-	0x80102540, 0x81468800, 0x83442c80, 0x0000007f,
-	0x04021014, 0x4c080000, 0x4c0c0000, 0x4c180000,
-	0x4c1c0000, 0x0201f800, 0x00020267, 0x5c003800,
-	0x5c003000, 0x5c001800, 0x5c001000, 0x040207f2,
-	0x0201f800, 0x00104842, 0x040207ef, 0x80183000,
-	0x801c3800, 0x59341202, 0x40180000, 0x0c01f7ce,
-	0x82100580, 0xffffffff, 0x04000002, 0x44101800,
-	0x42001800, 0x0010bc20, 0x500c0000, 0x82000500,
-	0xffffff00, 0x801c0540, 0x44001800, 0x5c026800,
-	0x5c028800, 0x42000800, 0x00000020, 0x59a00407,
-	0x59a01207, 0x900811c0, 0x80081540, 0x59a00409,
-	0x59a01a09, 0x900c19c0, 0x800c1d40, 0x42000000,
-	0x0010bc20, 0x0201f000, 0x00103841, 0x59a28c06,
-	0x59a0020b, 0x8c000500, 0x0400000e, 0x59a01208,
-	0x59a00408, 0x82000500, 0x000000ff, 0x900001c0,
-	0x80081540, 0x41784000, 0x0201f800, 0x00104768,
-	0x04000008, 0x48034406, 0x0201f000, 0x001020b6,
-	0x0201f800, 0x00020267, 0x02020000, 0x001020b6,
-	0x0201f800, 0x0010381a, 0x04020005, 0x4a034406,
-	0x00000002, 0x0201f000, 0x001020b2, 0x59a0020b,
-	0x8c000500, 0x04000005, 0x0201f800, 0x00104842,
-	0x02020000, 0x001038dd, 0x59a0020b, 0x8c000502,
-	0x04000019, 0x83440480, 0x000007f0, 0x04021016,
-	0x0201f800, 0x0010484b, 0x04020013, 0x497a5a04,
-	0x4a025c04, 0x00008000, 0x0201f800, 0x00108ea3,
-	0x04020005, 0x4a034406, 0x00000003, 0x0201f000,
-	0x001020b2, 0x4a01d809, 0x001032f8, 0x1c01f000,
-	0x59a28c06, 0x0201f800, 0x00020267, 0x02020000,
-	0x001020b6, 0x4c580000, 0x4c500000, 0x4c540000,
-	0x4200b000, 0x0000000a, 0x4134a000, 0x832e5c00,
-	0x00000002, 0x412ca800, 0x0201f800, 0x0010a93e,
-	0x832cac00, 0x00000006, 0x4054a000, 0x4200b000,
-	0x00000004, 0x0201f800, 0x0010a94f, 0x5c00a800,
-	0x5c00a000, 0x5c00b000, 0x592c0802, 0x82040500,
-	0x00ff00ff, 0x900001c0, 0x82041500, 0xff00ff00,
-	0x80080540, 0x48025802, 0x592c0801, 0x82040500,
-	0x00ff00ff, 0x900001c0, 0x82041500, 0xff00ff00,
-	0x80080540, 0x48025801, 0x42000800, 0x0000000a,
-	0x59a00407, 0x59a01207, 0x900811c0, 0x80081540,
-	0x59a00409, 0x59a01a09, 0x900c19c0, 0x800c1d40,
-	0x412c0000, 0x0201f000, 0x00103841, 0x496fc857,
-	0x496f4406, 0x0201f000, 0x00102066, 0x59a28c06,
-	0x0201f800, 0x00020267, 0x02020000, 0x001020b6,
-	0x836c0580, 0x00000003, 0x04000005, 0x4a034406,
-	0x00000007, 0x0201f000, 0x001020b2, 0x83340c00,
-	0x00000006, 0x59a0020b, 0x8c000500, 0x04000003,
-	0x83340c00, 0x00000008, 0x58040001, 0x48034409,
-	0x900001c0, 0x48034209, 0x50040000, 0x48034407,
-	0x900001c0, 0x48034207, 0x59340200, 0x48034406,
-	0x0201f000, 0x00102066, 0x800409c0, 0x04000005,
-	0x4a034406, 0x00000001, 0x0201f000, 0x001020b2,
-	0x59a0220b, 0x8c102500, 0x0402002e, 0x8c102506,
-	0x04020006, 0x59a03208, 0x82180480, 0x00000003,
-	0x02021000, 0x001020b6, 0x59a28c06, 0x0201f800,
-	0x00020267, 0x02020000, 0x001020b6, 0x0201f800,
-	0x00104836, 0x04000005, 0x4a034406, 0x00000009,
-	0x0201f000, 0x001020b2, 0x0201f800, 0x0010381a,
-	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
-	0x001020b2, 0x59a0220b, 0x8c102506, 0x04000004,
-	0x59343002, 0x82183500, 0x00ffffff, 0x497a5a04,
-	0x4a025c04, 0x00008000, 0x0201f800, 0x00108e65,
-	0x04020005, 0x4a034406, 0x00000003, 0x0201f000,
-	0x001020b2, 0x4a01d809, 0x001033de, 0x1c01f000,
-	0x59a28c06, 0x0201f800, 0x00020267, 0x02020000,
-	0x001020b6, 0x0201f800, 0x00104836, 0x04000005,
-	0x4a034406, 0x00000009, 0x0201f000, 0x001020b2,
-	0x0201f800, 0x0010381a, 0x04020005, 0x4a034406,
-	0x00000002, 0x0201f000, 0x001020b2, 0x497a5a04,
-	0x4a025c04, 0x00008000, 0x0201f800, 0x0010381a,
-	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
-	0x001020b2, 0x592e5800, 0x0201f800, 0x00108e7a,
-	0x04020005, 0x4a034406, 0x00000003, 0x0201f000,
-	0x001020b2, 0x4a01d809, 0x001033b0, 0x1c01f000,
-	0x592c2805, 0x82140d80, 0x01000000, 0x04020005,
-	0x4a034406, 0x00000004, 0x0201f000, 0x001020b2,
-	0x42000800, 0x00000008, 0x59a00207, 0x59a01407,
-	0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09,
-	0x900001c0, 0x800c1d40, 0x832c0400, 0x00000005,
-	0x0201f800, 0x00103841, 0x8c142d00, 0x04000003,
-	0x4a01d809, 0x001033cb, 0x1c01f000, 0x4031d800,
-	0x58ef400b, 0x58ee580e, 0x58ec0002, 0x82000580,
-	0x00000200, 0x02000000, 0x001020aa, 0x812e59c0,
-	0x02000800, 0x00100615, 0x42000800, 0x00000008,
-	0x832c0400, 0x00000005, 0x58ec1007, 0x58ec1808,
-	0x0201f000, 0x00103841, 0x592c0005, 0x82000580,
-	0x01000000, 0x04020005, 0x4a034406, 0x00000004,
-	0x0201f000, 0x001020b2, 0x59a00207, 0x59a01407,
-	0x900001c0, 0x80081540, 0x59a00209, 0x59a01c09,
-	0x900001c0, 0x800c1d40, 0x42000800, 0x00000006,
-	0x832c0400, 0x00000006, 0x0201f000, 0x00103841,
-	0x59a00a0a, 0x800409c0, 0x02000000, 0x001020b6,
-	0x82040480, 0x000000e8, 0x04001003, 0x42000800,
-	0x000000e7, 0x59a00207, 0x59a01407, 0x900001c0,
-	0x80081540, 0x59a00209, 0x59a01c09, 0x900001c0,
-	0x800c1d40, 0x83880400, 0x00000000, 0x0201f800,
-	0x00103841, 0x4a01d809, 0x0010340c, 0x1c01f000,
-	0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
-	0x00000200, 0x02000000, 0x001020aa, 0x59a0020b,
-	0x8c000500, 0x04000008, 0x83880400, 0x00000000,
-	0x4803c840, 0x4a03c842, 0x00000006, 0x04011000,
-	0x497b8885, 0x4a034207, 0x000000e7, 0x0201f000,
-	0x00102066, 0x800409c0, 0x04000005, 0x4a034406,
-	0x00000001, 0x0201f000, 0x001020b2, 0x0401fbf3,
-	0x04020005, 0x4a034406, 0x00000002, 0x0201f000,
-	0x001020b2, 0x497a5a04, 0x4a025c04, 0x00008000,
-	0x59a00406, 0x800001c0, 0x02000000, 0x001020b6,
-	0x82001580, 0x000000ff, 0x04000005, 0x82001480,
-	0x00000004, 0x02021000, 0x001020b6, 0x40001000,
-	0x0201f800, 0x00101d6a, 0x04020005, 0x4a034406,
-	0x00000003, 0x0201f000, 0x001020b2, 0x4a01d809,
-	0x00103446, 0x1c01f000, 0x592c0005, 0x82000580,
-	0x01000000, 0x02020000, 0x00102066, 0x4a034406,
-	0x00000004, 0x0201f000, 0x001020b2, 0x59a01406,
-	0x8c081508, 0x04020007, 0x800409c0, 0x04000005,
-	0x4a034406, 0x00000001, 0x0201f000, 0x001020b2,
-	0x59a01c07, 0x820c0480, 0x00001000, 0x02021000,
-	0x001020b6, 0x497b2804, 0x497b2805, 0x497b281c,
-	0x497b281d, 0x497b281f, 0x497b2820, 0x497b2822,
-	0x497b2823, 0x80000580, 0x0201f800, 0x00101668,
-	0x59a80805, 0x8c081500, 0x04000004, 0x82040d40,
-	0x00000011, 0x0401f004, 0x8c081506, 0x04000002,
-	0x84040d42, 0x84040d0a, 0x48075005, 0x4202d800,
-	0x00000001, 0x82081500, 0x000000e0, 0x8008010a,
-	0x0c020036, 0x0201f800, 0x00104e0d, 0x04020009,
-	0x4a035033, 0x00000001, 0x0201f800, 0x00104d76,
-	0x0401f01f, 0x4a035033, 0x00000000, 0x0401f7fb,
-	0x497b5032, 0x0201f800, 0x00103f5c, 0x0201f800,
-	0x0010698c, 0x0201f800, 0x00106c32, 0x0201f800,
-	0x00106982, 0x59a00a07, 0x480788a7, 0x59c400a3,
-	0x82000500, 0xfeffffff, 0x82000540, 0x80018000,
-	0x40000800, 0x84040d20, 0x480388a3, 0x480788a3,
-	0x497b504e, 0x42000800, 0x0000002d, 0x42001000,
-	0x00103fe4, 0x0201f800, 0x00105ca2, 0x59a00407,
-	0x800000c2, 0x800008c4, 0x8005d400, 0x42000000,
-	0x0000ffff, 0x0201f800, 0x00104e0d, 0x04000003,
-	0x59a00207, 0x80000110, 0x0201f800, 0x00103915,
-	0x0201f000, 0x00102066, 0x00103479, 0x0010347c,
-	0x00103484, 0x001020b6, 0x00103481, 0x001020b6,
-	0x001020b6, 0x001020b6, 0x836c0580, 0x00000003,
-	0x04000005, 0x4a034406, 0x00000007, 0x0201f000,
-	0x001020b2, 0x59a03c06, 0x59a00407, 0x59a04a07,
-	0x902449c0, 0x80244d40, 0x59a00409, 0x59a05209,
-	0x902851c0, 0x80285540, 0x0401fb54, 0x04020005,
-	0x4a034406, 0x00000002, 0x0201f000, 0x001020b2,
-	0x417a8800, 0x41783000, 0x497b4001, 0x497b4004,
-	0x832c4400, 0x00000005, 0x48234002, 0x8c1c3d04,
-	0x04020078, 0x0201f800, 0x00020267, 0x0402002a,
-	0x0201f800, 0x00104836, 0x04000004, 0x0201f800,
-	0x00104732, 0x04020024, 0x8c1c3d00, 0x04000008,
-	0x59340009, 0x44004000, 0x59340008, 0x80204000,
-	0x44004000, 0x80204000, 0x0401f007, 0x59340007,
-	0x44004000, 0x59340006, 0x80204000, 0x44004000,
-	0x80204000, 0x83440580, 0x000007fe, 0x0400000d,
-	0x83440580, 0x000007fc, 0x0400000a, 0x0201f800,
-	0x00104842, 0x04000003, 0x85468d5e, 0x0401f005,
-	0x0201f800, 0x00104686, 0x04020002, 0x85468d5e,
-	0x45444000, 0x85468d1e, 0x80204000, 0x82183400,
-	0x00000003, 0x81468800, 0x83440480, 0x000007f0,
-	0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580,
-	0x000007f0, 0x04020004, 0x42028800, 0x000007fe,
-	0x0401f006, 0x83440580, 0x000007ff, 0x04020007,
-	0x42028800, 0x000007fc, 0x82180580, 0x0000000f,
-	0x0400000b, 0x0401f7c0, 0x801831c0, 0x04020006,
-	0x59a00801, 0x800408c4, 0x48074406, 0x0201f000,
-	0x00102066, 0x4a034004, 0x00000001, 0x49474000,
-	0x59a00001, 0x80180400, 0x48034001, 0x481f4003,
-	0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002,
-	0x4801d803, 0x4825d807, 0x4829d808, 0x4000a800,
-	0x4000a000, 0x4018b000, 0x0201f800, 0x0010a93e,
-	0x40ec1000, 0x0201f800, 0x001008a1, 0x4a01d809,
-	0x00103536, 0x1c01f000, 0x4031d800, 0x58ef400b,
-	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
-	0x001020aa, 0x59a00004, 0x80000540, 0x04020008,
-	0x59a28800, 0x59a04002, 0x59a03803, 0x41783000,
-	0x58ec4807, 0x58ec5008, 0x0401f78f, 0x59a00801,
-	0x800408c4, 0x48074406, 0x0201f000, 0x00102066,
-	0x0201f800, 0x00020267, 0x0402002f, 0x0201f800,
-	0x00104836, 0x04000004, 0x0201f800, 0x00104732,
-	0x04020029, 0x83440580, 0x000007fe, 0x04000011,
-	0x83440580, 0x000007fc, 0x0400000e, 0x0201f800,
-	0x00104842, 0x04000005, 0x59340403, 0x8400055e,
-	0x48026c03, 0x0401f007, 0x0201f800, 0x00104686,
-	0x04020004, 0x59340403, 0x8400055e, 0x48026c03,
-	0x4134a000, 0x4020a800, 0x4200b000, 0x00000006,
-	0x0201f800, 0x0010a93e, 0x59340007, 0x4400a800,
-	0x59340006, 0x4800a801, 0x59340009, 0x4800a802,
-	0x59340008, 0x4800a803, 0x59340403, 0x8400051e,
-	0x48026c03, 0x82204400, 0x0000000a, 0x82183400,
-	0x0000000a, 0x81468800, 0x83440480, 0x000007f0,
-	0x0400100e, 0x8c1c3d06, 0x04000010, 0x83440580,
-	0x000007f0, 0x04020004, 0x42028800, 0x000007fe,
-	0x0401f006, 0x83440580, 0x000007ff, 0x04020007,
-	0x42028800, 0x000007fc, 0x82180580, 0x0000000a,
-	0x0400000b, 0x0401f7bb, 0x801831c0, 0x04020006,
-	0x59a00801, 0x800408c4, 0x48074406, 0x0201f000,
-	0x00102066, 0x4a034004, 0x00000001, 0x49474000,
-	0x59a00001, 0x80180400, 0x48034001, 0x481f4003,
-	0x4a01d801, 0x00000000, 0x4819d804, 0x59a00002,
-	0x4801d803, 0x4825d807, 0x4829d808, 0x40ec1000,
-	0x0201f800, 0x001008a1, 0x4a01d809, 0x001035ad,
-	0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ec0002,
-	0x82000580, 0x00000200, 0x02000000, 0x001020aa,
-	0x59a00004, 0x80000540, 0x04020008, 0x59a28800,
-	0x59a04002, 0x59a03803, 0x41783000, 0x58ec4807,
-	0x58ec5008, 0x0401f78f, 0x59a00801, 0x800408c4,
-	0x48074406, 0x0201f000, 0x00102066, 0x42002800,
-	0x0000007e, 0x59a00c06, 0x59a01207, 0x59a01c07,
-	0x59a02209, 0x82040500, 0x0000ff00, 0x840001c0,
-	0x82003480, 0x00000020, 0x02001000, 0x001020b6,
-	0x80140480, 0x02001000, 0x001020b6, 0x82040500,
-	0x000000ff, 0x82003480, 0x00000020, 0x02001000,
-	0x001020b6, 0x80140480, 0x02001000, 0x001020b6,
-	0x82080500, 0x0000ff00, 0x840001c0, 0x82003480,
-	0x00000020, 0x02001000, 0x001020b6, 0x80140480,
-	0x02001000, 0x001020b6, 0x82080500, 0x000000ff,
-	0x82003480, 0x00000020, 0x02001000, 0x001020b6,
-	0x80140480, 0x02001000, 0x001020b6, 0x820c0500,
-	0x0000ff00, 0x840001c0, 0x82003480, 0x00000020,
-	0x02001000, 0x001020b6, 0x80140480, 0x02001000,
-	0x001020b6, 0x820c0500, 0x000000ff, 0x82003480,
-	0x00000020, 0x02001000, 0x001020b6, 0x80140480,
-	0x02001000, 0x001020b6, 0x82100500, 0x0000ff00,
-	0x840001c0, 0x82003480, 0x00000020, 0x02001000,
-	0x001020b6, 0x80140480, 0x02001000, 0x001020b6,
-	0x82100500, 0x000000ff, 0x82003480, 0x00000020,
-	0x02001000, 0x001020b6, 0x80140480, 0x02001000,
-	0x001020b6, 0x900401c0, 0x80080d40, 0x900c01c0,
-	0x80101d40, 0x83a83400, 0x0000003a, 0x44043000,
-	0x80183000, 0x440c3000, 0x0201f000, 0x00102066,
-	0x0401f9fa, 0x04020005, 0x4a034406, 0x00000002,
-	0x0201f000, 0x001020b2, 0x42000800, 0x0000000c,
-	0x0401f853, 0x4a01d809, 0x0010362c, 0x1c01f000,
-	0x4031d800, 0x58ee580d, 0x58ef400b, 0x58ec0002,
-	0x82000580, 0x00000200, 0x02000000, 0x001020aa,
-	0x832ca400, 0x00000004, 0x4200b000, 0x0000000c,
-	0x40c8a800, 0x0201f800, 0x0010a93e, 0x58c80200,
-	0x80000540, 0x04000034, 0x58c80400, 0x82000500,
-	0xfffffffb, 0x04020030, 0x58c80401, 0x80000540,
-	0x0400002d, 0x82000480, 0x0000ff01, 0x0402102a,
-	0x58c80202, 0x82000480, 0x0000005c, 0x04001026,
-	0x0201f800, 0x001060db, 0x58c80c08, 0x58c80204,
-	0x80040480, 0x04001020, 0x58c80204, 0x82000480,
-	0x00000005, 0x0402101c, 0x58c80205, 0x58c80c08,
-	0x80040902, 0x80040480, 0x04001017, 0x58c80c08,
-	0x0201f800, 0x0010602a, 0x0400001b, 0x0201f800,
-	0x00105ef2, 0x04020012, 0x4979940b, 0x59c408a3,
-	0x82040d40, 0x00000002, 0x480788a3, 0x4a038830,
-	0x00000001, 0x4a038832, 0x01ffffff, 0x58c80202,
-	0x48030804, 0x0201f800, 0x00105ed4, 0x0201f000,
-	0x00102066, 0x0201f000, 0x001020b6, 0x0201f800,
-	0x0010612d, 0x0201f800, 0x0010613a, 0x0201f800,
-	0x0010601d, 0x0201f000, 0x001020b2, 0x4c000000,
-	0x59a01207, 0x59a00407, 0x900811c0, 0x80081540,
-	0x59a01a09, 0x59a00409, 0x900c19c0, 0x800c1d40,
-	0x5c000000, 0x0401f1b9, 0x59840000, 0x82000580,
-	0x00000000, 0x04000050, 0x59840002, 0x8c000504,
-	0x0400004d, 0x84000546, 0x48030802, 0x0201f800,
-	0x0010601d, 0x59c408a3, 0x82040d00, 0xfffffffd,
-	0x480788a3, 0x4c5c0000, 0x4200b800, 0x0010aa00,
-	0x505e6800, 0x813669c0, 0x04000008, 0x5936600e,
-	0x813261c0, 0x04000005, 0x0201f800, 0x0010600e,
-	0x02000800, 0x001061e5, 0x805cb800, 0x825c0580,
-	0x0010b1f0, 0x040207f3, 0x59866003, 0x813261c0,
-	0x0400000b, 0x59300406, 0x82000580, 0x00000009,
-	0x02020800, 0x00100615, 0x5930b800, 0x0201f800,
-	0x00105ffa, 0x405e6000, 0x0401f7f5, 0x497b0803,
-	0x4200b800, 0x0010b317, 0x505e6000, 0x813261c0,
-	0x04000011, 0x59300406, 0x82000580, 0x00000009,
-	0x0402000d, 0x59300203, 0x82000580, 0x00000004,
-	0x04020009, 0x59326809, 0x813669c0, 0x02020800,
-	0x00100615, 0x0201f800, 0x00100ee4, 0x0201f800,
-	0x00105ffa, 0x4578b800, 0x805cb800, 0x825c0580,
-	0x0010b31f, 0x040207e9, 0x42000800, 0x0010b315,
-	0x49780801, 0x49780800, 0x0201f800, 0x0010612d,
-	0x0201f800, 0x0010613a, 0x5c00b800, 0x0201f800,
-	0x00105eed, 0x0201f000, 0x00102066, 0x836c0580,
-	0x00000003, 0x04000005, 0x4a034406, 0x00000007,
-	0x0201f000, 0x001020b2, 0x59a00407, 0x59a02207,
-	0x901021c0, 0x80102540, 0x59a00409, 0x59a02a09,
-	0x901429c0, 0x80142d40, 0x0401f930, 0x04020005,
-	0x4a034406, 0x00000002, 0x0201f000, 0x001020b2,
-	0x417a8800, 0x41781800, 0x497b4001, 0x497b4003,
-	0x832c3400, 0x00000004, 0x481b4002, 0x41440000,
-	0x81ac0400, 0x50026800, 0x813669c0, 0x0400000b,
-	0x0201f800, 0x00104836, 0x04020008, 0x59340002,
-	0x48003000, 0x49443001, 0x82183400, 0x00000002,
-	0x820c1c00, 0x00000002, 0x81468800, 0x83440480,
-	0x00000800, 0x04000005, 0x820c0480, 0x00000010,
-	0x0402100b, 0x0401f7ea, 0x800c19c0, 0x04020006,
-	0x59a00801, 0x80040902, 0x48074406, 0x0201f000,
-	0x00102066, 0x4a034003, 0x00000001, 0x49474000,
-	0x59a00001, 0x800c0400, 0x48034001, 0x40ec1000,
-	0x4a001001, 0x00000000, 0x480c1004, 0x59a00002,
-	0x48001003, 0x48101007, 0x48141008, 0x0201f800,
-	0x001008a1, 0x4a01d809, 0x00103728, 0x1c01f000,
-	0x4031d800, 0x58ef400b, 0x58ec0002, 0x82000580,
-	0x00000200, 0x02000000, 0x001020aa, 0x59a00003,
-	0x80000540, 0x04020008, 0x59a28800, 0x59a03002,
-	0x41781800, 0x40ec1000, 0x58082007, 0x58082808,
-	0x0401f7bf, 0x59a00801, 0x80040902, 0x48074406,
-	0x0201f000, 0x00102066, 0x800409c0, 0x04000005,
-	0x4a034406, 0x00000001, 0x0201f000, 0x001020b2,
-	0x59a80026, 0x8c00050a, 0x04020007, 0x8c000506,
-	0x04020005, 0x4a034406, 0x00000016, 0x0201f000,
-	0x001020b2, 0x0401f8cd, 0x04020005, 0x4a034406,
-	0x00000002, 0x0201f000, 0x001020b2, 0x59a00c06,
-	0x80040902, 0x59a00407, 0x59a01207, 0x900811c0,
-	0x80081540, 0x59a00409, 0x59a01a09, 0x900c19c0,
-	0x800c1d40, 0x832c0400, 0x00000005, 0x0401f8df,
-	0x4a01d809, 0x00103763, 0x1c01f000, 0x4031d800,
-	0x58ef400b, 0x58ee580d, 0x58ec0002, 0x82000580,
-	0x00000200, 0x02000000, 0x001020aa, 0x592c0009,
-	0x0201f800, 0x001059b9, 0x02000800, 0x001043fc,
-	0x02020000, 0x001020b6, 0x49474001, 0x481a6802,
-	0x592c000a, 0x82001d80, 0x70000000, 0x04020007,
-	0x0401f8a2, 0x04020011, 0x4a034406, 0x00000002,
-	0x0201f000, 0x001020b2, 0x82001d80, 0x72000000,
-	0x02020000, 0x001020b6, 0x0401f898, 0x04020897,
-	0x04020896, 0x04020005, 0x4a034406, 0x00000002,
-	0x0201f000, 0x001020b2, 0x58ee580d, 0x4a025c04,
-	0x00008000, 0x497a5a04, 0x592c3208, 0x80183102,
-	0x592c1801, 0x4a001805, 0x01000000, 0x0201f800,
-	0x00108e8e, 0x04020005, 0x4a034406, 0x00000003,
-	0x0201f000, 0x001020b2, 0x4a01d809, 0x0010379d,
-	0x1c01f000, 0x592c4000, 0x592c0005, 0x82000580,
-	0x01000000, 0x04020005, 0x4a034406, 0x00000004,
-	0x0201f000, 0x001020b2, 0x4c580000, 0x4c500000,
-	0x4c540000, 0x832c3c00, 0x00000005, 0x401ca000,
-	0x401ca800, 0x5820280a, 0x4200b000, 0x00000002,
-	0x82143580, 0x70000000, 0x04000003, 0x4200b000,
-	0x0000000f, 0x0201f800, 0x0010a94f, 0x5c00a800,
-	0x5c00a000, 0x5c00b000, 0x401c0000, 0x58201006,
-	0x58201807, 0x58202205, 0x80102102, 0x82143580,
-	0x70000000, 0x04020008, 0x82103480, 0x00000002,
-	0x02001000, 0x001020b6, 0x42000800, 0x00000002,
-	0x0401f079, 0x82143580, 0x72000000, 0x02020000,
-	0x001020b6, 0x82103480, 0x0000002a, 0x02001000,
-	0x001020b6, 0x42000800, 0x0000000f, 0x0401f86e,
-	0x4a01d809, 0x001037d7, 0x1c01f000, 0x4031d800,
-	0x58ef400b, 0x58ee580e, 0x58ec0002, 0x82000580,
-	0x00000200, 0x02000000, 0x001020aa, 0x592e5800,
-	0x832c0c00, 0x00000005, 0x4c580000, 0x4c500000,
-	0x4c540000, 0x4004a000, 0x4004a800, 0x4200b000,
-	0x0000000f, 0x0201f800, 0x0010a94f, 0x5c00a800,
-	0x5c00a000, 0x5c00b000, 0x40ec1000, 0x4a001001,
-	0x00000000, 0x4a001004, 0x0000000f, 0x48041003,
-	0x0201f800, 0x001008a1, 0x4a01d809, 0x001037f9,
-	0x1c01f000, 0x4031d800, 0x58ef400b, 0x58ee580e,
-	0x58ec0002, 0x82000580, 0x00000200, 0x02000000,
-	0x001020aa, 0x832c0c00, 0x00000005, 0x4c580000,
-	0x4c500000, 0x4c540000, 0x4004a000, 0x4004a800,
-	0x4200b000, 0x0000000c, 0x0201f800, 0x0010a94f,
-	0x5c00a800, 0x5c00a000, 0x5c00b000, 0x40ec1000,
-	0x4a001001, 0x00000000, 0x4a001004, 0x0000000c,
-	0x48041003, 0x0201f800, 0x001008a1, 0x4a01d809,
-	0x0010205f, 0x1c01f000, 0x0201f800, 0x0010082a,
-	0x04000010, 0x497a5800, 0x58ec000d, 0x80000540,
-	0x04020004, 0x492dd80d, 0x492dd80e, 0x0401f007,
-	0x58ec000e, 0x48025800, 0x82000400, 0x00000001,
-	0x452c0000, 0x492dd80e, 0x832c0400, 0x00000004,
-	0x492fc857, 0x4803c857, 0x1c01f000, 0x4d2c0000,
-	0x58ec400d, 0x802041c0, 0x04000008, 0x4823c857,
-	0x40225800, 0x592c4001, 0x497a5801, 0x0201f800,
-	0x0010083a, 0x0401f7f8, 0x4979d80d, 0x4979d80e,
-	0x5c025800, 0x1c01f000, 0x42003000, 0x00000001,
-	0x0401f003, 0x42003000, 0x00000000, 0x4803c857,
-	0x4807c857, 0x480bc857, 0x480fc857, 0x481bc857,
-	0x48efc857, 0x4819d801, 0x800409c0, 0x02000800,
-	0x00100615, 0x4805d804, 0x4801d803, 0x4809d807,
-	0x480dd808, 0x40ec1000, 0x0201f800, 0x001008a1,
-	0x4a01d809, 0x0010205f, 0x1c01f000, 0x80002d80,
-	0x480bc857, 0x480fc857, 0x4813c857, 0x4817c857,
-	0x4d2c0000, 0x4da00000, 0x42034000, 0x0010b2a0,
-	0x59a00017, 0x800001c0, 0x04020013, 0x04006012,
-	0x480bc020, 0x480fc021, 0x4813c022, 0x4817c023,
-	0x900811c0, 0x82081540, 0x00000012, 0x480bc011,
-	0x59e00017, 0x8c000508, 0x04020004, 0x4203e000,
-	0x30000001, 0x0401f053, 0x4a03c017, 0x00000002,
-	0x0401f7fb, 0x4c040000, 0x4c1c0000, 0x80000800,
-	0x48074017, 0x59a0381a, 0x481fc857, 0x801c39c0,
-	0x04020027, 0x82000480, 0x0000000a, 0x04021010,
-	0x59a00018, 0x80000000, 0x48034018, 0x59a00219,
-	0x82000400, 0x00000002, 0x82000c80, 0x00000013,
-	0x48034219, 0x04001003, 0x497b4219, 0x41780000,
-	0x59a03816, 0x801c3c00, 0x0401f030, 0x4803c856,
-	0x0201f800, 0x0010082a, 0x04000007, 0x492f401a,
-	0x492f401b, 0x412c3800, 0x497b421c, 0x497a5813,
-	0x0401f026, 0x59880052, 0x80000000, 0x48031052,
-	0x59a00017, 0x80000040, 0x48034017, 0x59a00219,
-	0x59a03816, 0x801c3c00, 0x0401f01c, 0x59a0021c,
-	0x82000400, 0x00000002, 0x82000c80, 0x00000012,
-	0x04021004, 0x4803421c, 0x801c3c00, 0x0401f013,
-	0x0201f800, 0x0010082a, 0x0402000b, 0x59880052,
-	0x80000000, 0x48031052, 0x59a00017, 0x80000040,
-	0x48034017, 0x4803c856, 0x59a0021c, 0x801c3c00,
-	0x0401f006, 0x492f401a, 0x492c3813, 0x412c3800,
-	0x497b421c, 0x497a5813, 0x48083c00, 0x480c3a00,
-	0x48103c01, 0x48143a01, 0x5c003800, 0x5c000800,
-	0x5c034000, 0x5c025800, 0x1c01f000, 0x480fc857,
-	0x4813c857, 0x481bc857, 0x42000000, 0x0010b611,
-	0x0201f800, 0x0010a86e, 0x801800d0, 0x40002800,
-	0x42001000, 0x00008014, 0x0401f786, 0x4c000000,
-	0x599c0017, 0x8c000512, 0x5c000000, 0x1c01f000,
-	0x4c000000, 0x599c0018, 0x8c00050e, 0x5c000000,
-	0x1c01f000, 0x59a80821, 0x800409c0, 0x04000005,
-	0x4a034406, 0x00000001, 0x0201f000, 0x001020b2,
-	0x836c0580, 0x00000003, 0x04000005, 0x4a034406,
-	0x00000007, 0x0201f000, 0x001020b2, 0x599c0017,
-	0x8c00050a, 0x04000005, 0x4a034406, 0x00000008,
-	0x0201f000, 0x001020b2, 0x59340405, 0x8c000508,
-	0x04020004, 0x8c00050a, 0x02020000, 0x001032e2,
-	0x497a5a04, 0x497a5805, 0x4a025c04, 0x00008000,
-	0x0201f800, 0x00108f2d, 0x04020005, 0x4a034406,
-	0x00000003, 0x0201f000, 0x001020b2, 0x4a01d809,
-	0x00103906, 0x1c01f000, 0x592c0005, 0x82000580,
-	0x01000000, 0x04020005, 0x4a034406, 0x00000004,
-	0x0201f000, 0x001020b2, 0x59a28c06, 0x0201f800,
-	0x00020267, 0x02020000, 0x001020b6, 0x0201f000,
-	0x001032e2, 0x82001580, 0x0000ffff, 0x04000009,
-	0x0201f800, 0x001059b9, 0x02000800, 0x00020267,
-	0x0402000c, 0x0201f800, 0x00105ce7, 0x0401f009,
-	0x42028800, 0x000007ef, 0x0201f800, 0x00020267,
-	0x02000800, 0x00105ce7, 0x81468840, 0x040217fb,
-	0x1c01f000, 0x4803c856, 0x4c0c0000, 0x4d340000,
-	0x4d440000, 0x42028800, 0x000007fe, 0x0201f800,
-	0x00020267, 0x04020009, 0x5934180a, 0x820c1d00,
-	0x00000001, 0x820c1d80, 0x00000001, 0x42001000,
-	0x0000801b, 0x0401ff1e, 0x5c028800, 0x5c026800,
-	0x5c001800, 0x1c01f000, 0x599c0017, 0x8c000508,
-	0x1c01f000, 0x48efc857, 0x04011000, 0x48efc840,
-	0x4a03c842, 0x00000011, 0x40000000, 0x040117ff,
-	0x4a01d80f, 0xbeefbeef, 0x1c01f000, 0x497b4000,
-	0x497b4001, 0x497b4002, 0x497b4003, 0x497b4004,
-	0x1c01f000, 0x59c400a4, 0x4c580000, 0x4c500000,
-	0x4c540000, 0x82000500, 0x0000000f, 0x82000480,
-	0x00000007, 0x0400100a, 0x82006c80, 0x00000007,
-	0x02021800, 0x00100615, 0x0c01f807, 0x5c00a800,
-	0x5c00a000, 0x5c00b000, 0x1c01f000, 0x0401f90c,
-	0x0401f7fb, 0x0010396c, 0x00103972, 0x00103997,
-	0x001039b9, 0x00103a78, 0x0010396b, 0x1c01f000,
-	0x59c40806, 0x8c040d00, 0x04020003, 0x84040d40,
-	0x48078806, 0x1c01f000, 0x59c40005, 0x8c000534,
-	0x02020000, 0x001040ce, 0x4a038805, 0xffffffff,
-	0x42006000, 0x00020000, 0x0201f800, 0x001040b2,
-	0x59a80015, 0x82000500, 0xfffffffa, 0x84000542,
-	0x48035015, 0x497b5026, 0x42000800, 0x0010bc20,
-	0x45780800, 0x497b5013, 0x42006000, 0xffefffff,
-	0x42006800, 0x40000000, 0x0201f800, 0x001040ad,
-	0x59c40006, 0x82000500, 0xffffff0f, 0x48038806,
-	0x42000800, 0x00000010, 0x42001000, 0x0010401b,
-	0x0201f800, 0x00105cbc, 0x0401f001, 0x42006000,
-	0xffffffff, 0x42006800, 0x00800000, 0x0201f800,
-	0x001040ad, 0x4200b000, 0x000000c8, 0x59c400a4,
-	0x82000500, 0x0000000f, 0x82000580, 0x0000000a,
-	0x0400000f, 0x8058b040, 0x040207f9, 0x497b5014,
-	0x42006000, 0xbf7fffff, 0x42006800, 0x00018000,
-	0x0201f800, 0x001040ad, 0x42006000, 0xfffeffff,
-	0x41786800, 0x0201f000, 0x001040ad, 0x497b5014,
-	0x4a035012, 0x00000000, 0x80000580, 0x0201f000,
-	0x001040b9, 0x4a038805, 0xffffffff, 0x59a80012,
-	0x82000c80, 0x00000004, 0x02021800, 0x00100615,
-	0x0c01f001, 0x001039c4, 0x001039f1, 0x00103a6e,
-	0x4803c856, 0x59c400a3, 0x8400051e, 0x480388a3,
-	0x4a035012, 0x00000001, 0x59c40008, 0x8400054e,
-	0x48038808, 0x0201f800, 0x00104093, 0x42007800,
-	0x0010b34a, 0x4a007806, 0x11010000, 0x4200a000,
-	0x0010b202, 0x4200a800, 0x0010b351, 0x4200b000,
-	0x00000002, 0x0201f800, 0x0010a93e, 0x497b8802,
-	0x42000800, 0x00000003, 0x497b504a, 0x0201f800,
-	0x00103f8e, 0x4a03504a, 0x00000001, 0x497b5016,
-	0x0201f800, 0x001040c0, 0x42006000, 0xffffffff,
-	0x42006800, 0x00080000, 0x0201f800, 0x001040ad,
-	0x42006000, 0xfff7ffff, 0x41786800, 0x0201f000,
-	0x001040ad, 0x59a80016, 0x497b5016, 0x80002540,
-	0x0400006a, 0x59c40004, 0x82000500, 0x00000003,
-	0x04020075, 0x59a80815, 0x8c040d02, 0x0400004f,
-	0x82100580, 0x0000000c, 0x04020053, 0x82100400,
-	0x00000018, 0x8000b104, 0x41cc1000, 0x42001800,
-	0x0010b34a, 0x50080800, 0x500c0000, 0x80040580,
-	0x0402001e, 0x80081000, 0x800c1800, 0x8058b040,
-	0x040207f9, 0x0201f800, 0x001040c0, 0x42006000,
-	0xffffffff, 0x42006800, 0x00500000, 0x0201f800,
-	0x001040ad, 0x4a035012, 0x00000002, 0x4a035014,
-	0x00000002, 0x0201f800, 0x0010164b, 0x42000800,
-	0x000007d0, 0x42001000, 0x00103f62, 0x0201f800,
-	0x00105da7, 0x59a80015, 0x84000506, 0x48035015,
-	0x0201f000, 0x00104093, 0x59cc0806, 0x82040d80,
-	0x11010000, 0x04020028, 0x59cc0800, 0x82040500,
-	0x00ffffff, 0x0400001a, 0x82000580, 0x000000ef,
-	0x04020017, 0x59cc0801, 0x82040500, 0x00ffffff,
-	0x82000580, 0x000000ef, 0x04020011, 0x83cca400,
-	0x00000007, 0x4200a800, 0x0010b202, 0x4200b000,
-	0x00000002, 0x50500800, 0x50540000, 0x80040480,
-	0x04001007, 0x04020010, 0x8050a000, 0x8054a800,
-	0x8058b040, 0x040207f8, 0x0401f00b, 0x59a80015,
-	0x84000502, 0x48035015, 0x41cca000, 0x4200a800,
-	0x0010b34a, 0x4200b000, 0x00000009, 0x0201f800,
-	0x0010a93e, 0x0201f800, 0x001040c0, 0x42006000,
-	0xffffffff, 0x42006800, 0x00080000, 0x0201f800,
-	0x001040ad, 0x42006000, 0xfff7ffff, 0x41786800,
-	0x0201f800, 0x001040ad, 0x42006000, 0xffffffff,
-	0x42006800, 0x00004000, 0x0201f800, 0x001040ad,
-	0x59c40004, 0x82000500, 0x00000003, 0x04020006,
-	0x497b5016, 0x42000800, 0x00000003, 0x0201f000,
-	0x00103f8e, 0x1c01f000, 0x1c01f000, 0x59a80014,
-	0x82006d80, 0x0000000f, 0x04000005, 0x82000580,
-	0x0000001b, 0x02020800, 0x00103f53, 0x1c01f000,
-	0x59a80015, 0x84000506, 0x48035015, 0x497b504a,
-	0x59a80014, 0x82000c80, 0x0000001e, 0x02021800,
-	0x00100615, 0x0c01f001, 0x00103ab6, 0x00103acd,
-	0x00103af6, 0x00103b11, 0x00103b34, 0x00103b65,
-	0x00103b87, 0x00103bba, 0x00103bdc, 0x00103c00,
-	0x00103c3c, 0x00103c63, 0x00103c79, 0x00103c8b,
-	0x00103ca3, 0x00103cba, 0x00103cbf, 0x00103ce7,
-	0x00103d0a, 0x00103d30, 0x00103d53, 0x00103d86,
-	0x00103dc8, 0x00103df2, 0x00103e0a, 0x00103e4a,
-	0x00103e63, 0x00103e76, 0x00103e77, 0x4803c856,
-	0x4202d800, 0x00000007, 0x0201f800, 0x00104e0d,
-	0x04000007, 0x42006000, 0xffffffd7, 0x41786800,
-	0x0201f800, 0x001040ad, 0x0401f00b, 0x59c40006,
-	0x82000500, 0xffffff0f, 0x48038806, 0x42001000,
-	0x000000f0, 0x0201f800, 0x001019aa, 0x0201f800,
-	0x00104d6c, 0x1c01f000, 0x4803c856, 0x42006000,
-	0xbf7fffff, 0x42006800, 0x00400000, 0x0201f800,
-	0x001040ad, 0x0201f800, 0x0010164b, 0x4a035014,
-	0x00000001, 0x42001000, 0x0010401b, 0x0201f800,
-	0x00105cdd, 0x0201f800, 0x00104024, 0x42000800,
-	0x000007d0, 0x42001000, 0x00103f62, 0x0201f000,
-	0x00105da7, 0x59a80016, 0x82000580, 0x00000014,
-	0x04020023, 0x4803c857, 0x42006000, 0xffbfffff,
-	0x41786800, 0x0201f800, 0x001040ad, 0x59c40004,
-	0x82000500, 0x00000003, 0x04020019, 0x42001000,
-	0x00103f62, 0x0201f800, 0x00105cc9, 0x59cc1006,
-	0x82081580, 0x11020000, 0x04020012, 0x59cc1007,
-	0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504,
-	0x04020008, 0x42000000, 0x0010b63d, 0x0201f800,
-	0x0010a86e, 0x59a80015, 0x84000544, 0x48035015,
-	0x4a035014, 0x00000010, 0x0401f1cd, 0x1c01f000,
-	0x0201f000, 0x00103f53, 0x4803c856, 0x4a035014,
-	0x00000003, 0x42006000, 0xbf3fffff, 0x42006800,
-	0x00100000, 0x0201f800, 0x001040ad, 0x42001000,
-	0x0010401b, 0x0201f800, 0x00105cdd, 0x0201f800,
-	0x00104024, 0x42001000, 0x00103f62, 0x0201f800,
-	0x00105cc9, 0x42007800, 0x0010b350, 0x46007800,
-	0x11020000, 0x42000800, 0x00000005, 0x0201f000,
-	0x00103f8e, 0x59a80016, 0x80000540, 0x0400001e,
-	0x4803c857, 0x42001000, 0x00103f62, 0x0201f800,
-	0x00105cc9, 0x59a80016, 0x82000580, 0x00000014,
-	0x04020016, 0x59cc1006, 0x82081580, 0x11020000,
-	0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b,
-	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
-	0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015,
-	0x84000544, 0x48035015, 0x4a035014, 0x00000004,
-	0x0401f004, 0x1c01f000, 0x0201f000, 0x00103f53,
-	0x4803c856, 0x4a035014, 0x00000005, 0x83cca400,
-	0x00000006, 0x4200a800, 0x0010b350, 0x4200b000,
-	0x00000005, 0x0201f800, 0x0010a93e, 0x42007800,
-	0x0010b350, 0x46007800, 0x11030000, 0x0201f800,
-	0x00103f58, 0x04020014, 0x59a80015, 0x8c000500,
-	0x04020011, 0x59a80810, 0x82040580, 0x00ffffff,
-	0x0400000d, 0x82040d00, 0x000000ff, 0x82040400,
-	0x00101eb5, 0x50000800, 0x80040910, 0x42001000,
-	0x00000004, 0x0401fb95, 0x0400000b, 0x0201f800,
-	0x0010403d, 0x4200b000, 0x00000004, 0x83cca400,
-	0x00000007, 0x4200a800, 0x0010b351, 0x0201f800,
-	0x0010a93e, 0x42000800, 0x00000005, 0x0201f000,
-	0x00103f8e, 0x59a80016, 0x80000540, 0x0400001e,
-	0x4803c857, 0x42001000, 0x00103f62, 0x0201f800,
-	0x00105cc9, 0x59a80016, 0x82000580, 0x00000014,
-	0x04020016, 0x59cc1006, 0x82081580, 0x11030000,
-	0x04020012, 0x59cc1007, 0x8c08153e, 0x0400000b,
-	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
-	0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015,
-	0x84000544, 0x48035015, 0x4a035014, 0x00000006,
-	0x0401f003, 0x1c01f000, 0x0401f3cd, 0x4803c856,
-	0x4a035014, 0x00000007, 0x83cca400, 0x00000006,
-	0x4200a800, 0x0010b350, 0x4200b000, 0x00000005,
-	0x0201f800, 0x0010a93e, 0x42007800, 0x0010b350,
-	0x46007800, 0x11040000, 0x0401fbc2, 0x04020020,
-	0x59a80015, 0x8c000500, 0x0402001d, 0x599c0017,
-	0x8c000500, 0x0400001a, 0x599c1402, 0x82080480,
-	0x0000007f, 0x02021800, 0x00100615, 0x4c080000,
-	0x82081400, 0x00101eb5, 0x50081000, 0x82081500,
-	0x000000ff, 0x480b5010, 0x42000800, 0x00000003,
-	0x0201f800, 0x001069af, 0x5c000800, 0x42001000,
-	0x00000004, 0x0401fb39, 0x04000005, 0x0401fd25,
-	0x04000003, 0x0201f800, 0x00101668, 0x42000800,
-	0x00000005, 0x0401f3d5, 0x59a80016, 0x80000540,
-	0x0400001e, 0x4803c857, 0x42001000, 0x00103f62,
-	0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580,
-	0x00000014, 0x04020016, 0x59cc1006, 0x82081580,
-	0x11040000, 0x04020012, 0x59cc1007, 0x8c08153e,
-	0x0400000b, 0x59a80015, 0x8c000504, 0x04020008,
-	0x42000000, 0x0010b63d, 0x0201f800, 0x0010a86e,
-	0x59a80015, 0x84000544, 0x48035015, 0x4a035014,
-	0x00000008, 0x0401f003, 0x1c01f000, 0x0401f378,
-	0x4803c856, 0x4a035014, 0x00000009, 0x83cca400,
-	0x00000006, 0x4200a800, 0x0010b350, 0x4200b000,
-	0x00000005, 0x0201f800, 0x0010a93e, 0x42007800,
-	0x0010b350, 0x46007800, 0x11050100, 0x0401fb6d,
-	0x0402000a, 0x59a80015, 0x8c000500, 0x04020007,
-	0x0401fa88, 0x04020005, 0x82000540, 0x00000001,
-	0x0201f800, 0x00101668, 0x42000800, 0x00000005,
-	0x0401fb96, 0x4d3c0000, 0x42027800, 0x00000001,
-	0x0201f800, 0x00109640, 0x5c027800, 0x1c01f000,
-	0x59a80016, 0x80000540, 0x04000038, 0x4803c857,
-	0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9,
-	0x59a80016, 0x82000580, 0x00000014, 0x04020030,
-	0x59cc1006, 0x82080500, 0x11050000, 0x82000580,
-	0x11050000, 0x0402002a, 0x8c081510, 0x04000014,
-	0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015,
-	0x8c000504, 0x04020008, 0x42000000, 0x0010b63d,
-	0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544,
-	0x48035015, 0x4a035013, 0x00000001, 0x4a035014,
-	0x0000000a, 0x0401f817, 0x0401f014, 0x80000540,
-	0x04020013, 0x59cc1007, 0x8c08153e, 0x0400000b,
-	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
-	0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015,
-	0x84000544, 0x48035015, 0x497b5013, 0x4a035014,
-	0x0000000e, 0x0401f06a, 0x1c01f000, 0x0401f318,
-	0x4803c856, 0x4a035014, 0x0000000b, 0x42001000,
-	0x0010b351, 0x4008a800, 0x4200b000, 0x00000020,
-	0x4600a800, 0xffffffff, 0x8054a800, 0x8058b040,
-	0x040207fc, 0x42007800, 0x0010b350, 0x46007800,
-	0x11060000, 0x42001000, 0x0010b351, 0x0401fb09,
-	0x04000005, 0x50080000, 0x46001000, 0x00ffffff,
-	0x0401f00c, 0x50080800, 0x82040d00, 0x0000ffff,
-	0x59a80010, 0x82000500, 0x000000ff, 0x82000540,
-	0x00000100, 0x800000e0, 0x80040d40, 0x44041000,
-	0x42000800, 0x00000021, 0x0401f32c, 0x59a80016,
-	0x80000540, 0x04000012, 0x4803c857, 0x59a80016,
-	0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9,
-	0x59a80016, 0x82000580, 0x00000084, 0x04020009,
-	0x59cc1006, 0x82081580, 0x11060000, 0x04020005,
-	0x4a035014, 0x0000000c, 0x0401f003, 0x1c01f000,
-	0x0401f2db, 0x4803c856, 0x4a035014, 0x0000000d,
-	0x83cca400, 0x00000006, 0x4200a800, 0x0010b350,
-	0x4200b000, 0x00000021, 0x0201f800, 0x0010a93e,
-	0x42007800, 0x0010b350, 0x46007800, 0x11070000,
-	0x42000800, 0x00000021, 0x0401f304, 0x59a80016,
-	0x80000540, 0x04000014, 0x4803c857, 0x59a80016,
-	0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9,
-	0x82000580, 0x00000084, 0x0402000c, 0x59cc1006,
-	0x82081580, 0x11070000, 0x04020008, 0x4a035013,
-	0x00000001, 0x0401fa91, 0x4a035014, 0x0000000e,
-	0x0401f003, 0x1c01f000, 0x0401f2b1, 0x4803c856,
-	0x82040d40, 0x00000001, 0x0201f800, 0x001040b9,
-	0x4a035014, 0x0000000f, 0x497b5016, 0x42006000,
-	0xffffffff, 0x42006800, 0x00300000, 0x0401fbfe,
-	0x42006000, 0xffdfffff, 0x41786800, 0x0401fbfa,
-	0x42000800, 0x000007d0, 0x42001000, 0x00103f62,
-	0x0201f000, 0x00105ca2, 0x4803c856, 0x59a80016,
-	0x80000540, 0x04020296, 0x1c01f000, 0x4803c856,
-	0x4a035014, 0x00000011, 0x83cca400, 0x00000006,
-	0x4200a800, 0x0010b350, 0x4200b000, 0x00000005,
-	0x0201f800, 0x0010a93e, 0x4200a800, 0x0010b350,
-	0x4600a800, 0x11020000, 0x0401fa8a, 0x04020015,
-	0x59a80010, 0x82000d00, 0xffff0000, 0x04000011,
-	0x82000500, 0x000000ff, 0x0400000e, 0x82000c00,
-	0x00101eb5, 0x50040800, 0x80040910, 0x82040580,
-	0x0000007e, 0x04000007, 0x82040580, 0x00000080,
-	0x04000004, 0x42001000, 0x00000004, 0x0401fa07,
-	0x42000800, 0x00000005, 0x0401f2a8, 0x59a80016,
-	0x80000540, 0x04000020, 0x4803c857, 0x42001000,
-	0x00103f62, 0x0201f800, 0x00105cc9, 0x59a80016,
-	0x82000580, 0x00000014, 0x04020016, 0x59cc1006,
-	0x82081580, 0x11030000, 0x04020012, 0x59cc1007,
-	0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504,
-	0x04020008, 0x42000000, 0x0010b63d, 0x0201f800,
-	0x0010a86e, 0x59a80015, 0x84000544, 0x48035015,
-	0x4a035014, 0x00000012, 0x0401f804, 0x0401f002,
-	0x0401fa4b, 0x1c01f000, 0x4803c856, 0x4a035014,
-	0x00000013, 0x83cca400, 0x00000006, 0x4200a800,
-	0x0010b350, 0x4200b000, 0x00000005, 0x0201f800,
-	0x0010a93e, 0x4200a800, 0x0010b350, 0x4600a800,
-	0x11030000, 0x0401fa3f, 0x04020013, 0x59a80015,
-	0x8c000500, 0x04020010, 0x59a80810, 0x82040580,
-	0x00ffffff, 0x0400000c, 0x82040d00, 0x000000ff,
-	0x82040400, 0x00101eb5, 0x50000800, 0x80040910,
-	0x42001000, 0x00000004, 0x0401f9c0, 0x04000002,
-	0x0401fb11, 0x42000800, 0x00000005, 0x0401f25f,
-	0x59a80016, 0x80000540, 0x04000020, 0x4803c857,
-	0x42001000, 0x00103f62, 0x0201f800, 0x00105cc9,
-	0x59a80016, 0x82000580, 0x00000014, 0x04020016,
-	0x59cc1006, 0x82081580, 0x11040000, 0x04020012,
-	0x59cc1007, 0x8c08153e, 0x0400000b, 0x59a80015,
-	0x8c000504, 0x04020008, 0x42000000, 0x0010b63d,
-	0x0201f800, 0x0010a86e, 0x59a80015, 0x84000544,
-	0x48035015, 0x4a035014, 0x00000014, 0x0401f804,
-	0x0401f002, 0x0401fa02, 0x1c01f000, 0x4803c856,
-	0x4a035014, 0x00000015, 0x83cca400, 0x00000006,
-	0x4200a800, 0x0010b350, 0x4200b000, 0x00000005,
-	0x0201f800, 0x0010a93e, 0x4200a800, 0x0010b350,
-	0x4600a800, 0x11040000, 0x0401f9f6, 0x04020020,
-	0x59a80015, 0x8c000500, 0x0402001d, 0x599c0017,
-	0x8c000500, 0x0400001a, 0x599c1402, 0x82080480,
-	0x0000007f, 0x02021800, 0x00100615, 0x4c080000,
-	0x82081400, 0x00101eb5, 0x50081000, 0x82081500,
-	0x000000ff, 0x480b5010, 0x42000800, 0x00000003,
-	0x0201f800, 0x001069af, 0x5c000800, 0x42001000,
-	0x00000004, 0x0401f96d, 0x04000005, 0x0201f800,
-	0x001038d8, 0x02020800, 0x00101668, 0x42000800,
-	0x00000005, 0x0401f209, 0x59a80016, 0x80000540,
-	0x0400003f, 0x4803c857, 0x42001000, 0x00103f62,
-	0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580,
-	0x00000014, 0x04020035, 0x59cc1006, 0x82080500,
-	0x11050000, 0x82000580, 0x11050000, 0x0402002f,
-	0x8c081510, 0x04000010, 0x0401fb1f, 0x59cc1007,
-	0x8c08153e, 0x0400000b, 0x59a80015, 0x8c000504,
-	0x04020008, 0x42000000, 0x0010b63d, 0x0201f800,
-	0x0010a86e, 0x59a80015, 0x84000544, 0x48035015,
-	0x0401f013, 0x59cc1007, 0x8c08153e, 0x0400000b,
-	0x59a80015, 0x8c000504, 0x04020008, 0x42000000,
-	0x0010b63d, 0x0201f800, 0x0010a86e, 0x59a80015,
-	0x84000544, 0x48035015, 0x82000540, 0x00000001,
-	0x0401fb01, 0x497b5013, 0x0401f003, 0x4a035013,
-	0x00000001, 0x59cc1007, 0x8c08153c, 0x04000003,
-	0x4a035026, 0x00000008, 0x4a035014, 0x00000016,
-	0x0401f804, 0x0401f002, 0x0401f98d, 0x1c01f000,
-	0x4803c856, 0x83cca400, 0x00000006, 0x4200a800,
-	0x0010b350, 0x4200b000, 0x00000005, 0x0201f800,
-	0x0010a93e, 0x4a035014, 0x00000017, 0x59a80013,
-	0x8c000500, 0x04000006, 0x42001000, 0x0010b350,
-	0x46001000, 0x11050100, 0x0401f003, 0x4a035014,
-	0x0000001b, 0x0401f97b, 0x0402000a, 0x59a80015,
-	0x8c000500, 0x04020007, 0x0401f896, 0x04020005,
-	0x82000540, 0x00000001, 0x0201f800, 0x00101668,
-	0x42000800, 0x00000005, 0x0401f9a4, 0x4d3c0000,
-	0x42027800, 0x00000001, 0x0201f800, 0x00109640,
-	0x5c027800, 0x1c01f000, 0x59a80016, 0x80000540,
-	0x04000015, 0x4803c857, 0x42001000, 0x00103f62,
-	0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580,
-	0x00000084, 0x0402000b, 0x59cc1006, 0x82081580,
-	0x11060000, 0x04020007, 0x80000580, 0x0401fab6,
-	0x4a035014, 0x00000018, 0x0401f804, 0x0401f002,
-	0x0401f94b, 0x1c01f000, 0x4803c856, 0x4a035014,
-	0x00000019, 0x83cca400, 0x00000006, 0x4200a800,
-	0x0010b350, 0x4200b000, 0x00000021, 0x0201f800,
-	0x0010a93e, 0x42003800, 0x0010b351, 0x0401f941,
-	0x04020018, 0x401c2800, 0x50141000, 0x80080130,
-	0x80000000, 0x40001800, 0x82081500, 0x00ffffff,
-	0x800000f0, 0x80080540, 0x44002800, 0x59a80810,
-	0x82040d00, 0x000000ff, 0x400c1000, 0x80081104,
-	0x82082400, 0x0010b351, 0x50101000, 0x820c0500,
-	0x00000003, 0x0c01f806, 0x80081540, 0x44082000,
-	0x42000800, 0x00000021, 0x0401f15c, 0x00103e37,
-	0x00103e3c, 0x00103e41, 0x00103e46, 0x800408f0,
-	0x40040000, 0x82081500, 0x00ffffff, 0x1c01f000,
-	0x800408e0, 0x40040000, 0x82081500, 0xff00ffff,
-	0x1c01f000, 0x800408d0, 0x40040000, 0x82081500,
-	0xffff00ff, 0x1c01f000, 0x40040000, 0x82081500,
-	0xffffff00, 0x1c01f000, 0x59a80016, 0x80000540,
-	0x04000016, 0x4803c857, 0x42001000, 0x00103f62,
-	0x0201f800, 0x00105cc9, 0x59a80016, 0x82000580,
-	0x00000084, 0x0402000c, 0x59cc1006, 0x82081580,
-	0x11070000, 0x04020008, 0x4a035013, 0x00000001,
-	0x0401f8d2, 0x4a035014, 0x0000001a, 0x0401f804,
-	0x0401f002, 0x0401f8f2, 0x1c01f000, 0x82000540,
-	0x00000001, 0x0401fa54, 0x4a035014, 0x0000001b,
-	0x83cca400, 0x00000006, 0x4200a800, 0x0010b350,
-	0x59a82016, 0x40100000, 0x8000b104, 0x40580800,
-	0x5450a800, 0x8050a000, 0x8054a800, 0x8058b040,
-	0x040207fc, 0x0401f119, 0x1c01f000, 0x1c01f000,
-	0x4803c856, 0x42003000, 0x00000004, 0x42004000,
-	0x0010b351, 0x599c2817, 0x8c142d14, 0x0402001f,
-	0x42001000, 0x00000003, 0x40200000, 0x80080400,
-	0x50000800, 0x82042580, 0xffffffff, 0x04020005,
-	0x80081040, 0x80183040, 0x040207f8, 0x0401f05e,
-	0x800811c0, 0x04020006, 0x82042580, 0x3fffffff,
-	0x04000058, 0x82040d40, 0xc0000000, 0x4200b000,
-	0x00000020, 0x42001800, 0x00000001, 0x40042000,
-	0x80102102, 0x04021021, 0x800c18c2, 0x8058b040,
-	0x040207fc, 0x0401f04b, 0x41781000, 0x40200000,
-	0x80080400, 0x50000800, 0x82042580, 0xffffffff,
-	0x04020005, 0x80081000, 0x80183040, 0x040207f8,
-	0x0401f040, 0x800811c0, 0x04020003, 0x82040d40,
-	0xc0000000, 0x4200b000, 0x00000001, 0x42001800,
-	0x80000000, 0x40042000, 0x801020c2, 0x04021007,
-	0x800c1902, 0x8058b000, 0x82580480, 0x00000021,
-	0x040017fa, 0x0401f02f, 0x40200000, 0x80082400,
-	0x50100000, 0x800c0540, 0x44002000, 0x59a80015,
-	0x84000540, 0x48035015, 0x40580000, 0x42002800,
-	0x00000020, 0x80142c80, 0x40080000, 0x42003800,
-	0x00000003, 0x801c0480, 0x800000ca, 0x80142d40,
-	0x82144c00, 0x00101eb5, 0x50242800, 0x82142d00,
-	0x000000ff, 0x48175010, 0x4c040000, 0x40140800,
-	0x0201f800, 0x00101655, 0x5c000800, 0x40001800,
-	0x500c0000, 0x80100540, 0x44001800, 0x59a80015,
-	0x84000540, 0x48035015, 0x4200a800, 0x0010b351,
-	0x4020a000, 0x4200b000, 0x00000004, 0x0201f800,
-	0x0010a93e, 0x82000540, 0x00000001, 0x0401f002,
-	0x80000580, 0x1c01f000, 0x4807c857, 0x480bc857,
-	0x4008b000, 0x83cca400, 0x00000007, 0x4200a800,
-	0x0010b351, 0x40541000, 0x0201f800, 0x0010a93e,
-	0x40041800, 0x41782000, 0x42000000, 0x00000003,
-	0x820c1c80, 0x00000020, 0x04001004, 0x80102000,
-	0x80000040, 0x0401f7fb, 0x40041800, 0x801021c0,
-	0x04000005, 0x820c1c80, 0x00000020, 0x80102040,
-	0x040207fd, 0x42002000, 0x00000001, 0x800c19c0,
-	0x04000004, 0x801020c2, 0x800c1840, 0x040207fe,
-	0x80083c00, 0x83cc2c00, 0x00000007, 0x80142c00,
-	0x50140000, 0x80102d00, 0x04020012, 0x80100540,
-	0x44003800, 0x82042400, 0x00101eb5, 0x50102800,
-	0x82142d00, 0x000000ff, 0x48175010, 0x4c040000,
-	0x40140800, 0x0201f800, 0x00101655, 0x5c000800,
-	0x59a80015, 0x84000540, 0x48035015, 0x80000580,
-	0x1c01f000, 0x4807c856, 0x42001000, 0x00008017,
-	0x59a8184e, 0x0201f800, 0x0010a876, 0x0201f800,
-	0x00103857, 0x1c01f000, 0x4807c856, 0x4200b000,
-	0x00000020, 0x83cca400, 0x00000007, 0x4200a800,
-	0x0010bc20, 0x0201f000, 0x0010a94f, 0x4807c856,
-	0x0201f800, 0x00106c32, 0x42000800, 0x000000f7,
-	0x0401f8f4, 0x497b2804, 0x497b2805, 0x497b281c,
-	0x497b281d, 0x4202d800, 0x00000001, 0x42006000,
-	0xbf7fffff, 0x42006800, 0x00018000, 0x0401f966,
-	0x42006000, 0xfffeffff, 0x41786800, 0x0401f962,
-	0x497b504e, 0x42000800, 0x0000002d, 0x42001000,
-	0x00103fe4, 0x0201f000, 0x00105ca2, 0x4807c856,
-	0x0401ffe3, 0x497b5014, 0x497b5016, 0x1c01f000,
-	0x4807c856, 0x59a80005, 0x8c000506, 0x1c01f000,
-	0x4807c856, 0x42006000, 0xffffffff, 0x42006800,
-	0x00000028, 0x0401f14c, 0x4807c856, 0x0401ffc2,
-	0x0201f800, 0x0010698c, 0x4df00000, 0x0201f800,
-	0x00106b71, 0x5c03e000, 0x02000800, 0x00106982,
-	0x59c400a4, 0x82000500, 0x0000000f, 0x82000580,
-	0x00000002, 0x0402000a, 0x42006000, 0xffffffff,
-	0x42006800, 0x00200000, 0x0401f937, 0x42006000,
-	0xffdfffff, 0x41786800, 0x0401f933, 0x497b5014,
-	0x42000800, 0x000000f7, 0x0401f8b2, 0x59c400a3,
-	0x82000500, 0xbf20bfff, 0x82000540, 0x0001c000,
-	0x480388a3, 0x84000520, 0x480388a3, 0x497b504e,
-	0x42000800, 0x0000002d, 0x42001000, 0x00103fe4,
-	0x0201f000, 0x00105ca2, 0x497b5016, 0x59b400f5,
-	0x8c000500, 0x04020004, 0x82000540, 0x00000001,
-	0x480368f5, 0x800400c4, 0x82000400, 0x00002000,
-	0x4803910a, 0x59b400f6, 0x82000500, 0x00000018,
-	0x040207fd, 0x4a0368f0, 0x0010b349, 0x42000000,
-	0x0010b350, 0x4c040000, 0x50000800, 0x82040d80,
-	0x11010000, 0x04000003, 0x50000800, 0x4807c857,
-	0x5c000800, 0x480368f1, 0x82040400, 0x0000dc00,
-	0x480368f3, 0x59c400a4, 0x82000500, 0x0000000f,
-	0x82000580, 0x00000008, 0x04020017, 0x4c5c0000,
-	0x4c600000, 0x59c4b805, 0x8c5cbd3a, 0x04020005,
-	0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e,
-	0x4a038805, 0x02000000, 0x0201f800, 0x00101a59,
-	0x4000c000, 0x0201f800, 0x001019d0, 0x4202d800,
-	0x00000001, 0x497b5014, 0x5c00c000, 0x5c00b800,
-	0x1c01f000, 0x59c8010b, 0x8c000502, 0x040007e2,
-	0x59c408a4, 0x82040d00, 0x0000000f, 0x82040d80,
-	0x0000000b, 0x04020005, 0x59a80814, 0x82040d40,
-	0x00002000, 0x0401f004, 0x59a80812, 0x82040d40,
-	0x00001000, 0x4807504e, 0x59a8084a, 0x800409c0,
-	0x04020007, 0x42000800, 0x000007d0, 0x42001000,
-	0x00103f62, 0x0201f800, 0x00105da7, 0x1c01f000,
-	0x4807c856, 0x0401ff40, 0x0201f800, 0x0010698c,
-	0x4df00000, 0x0201f800, 0x00106b71, 0x5c03e000,
-	0x02000800, 0x00106982, 0x59c400a4, 0x82000500,
-	0x0000000f, 0x82000580, 0x00000002, 0x0402000a,
-	0x42006000, 0xffffffff, 0x42006800, 0x00200000,
-	0x0401f8b5, 0x42006000, 0xffdfffff, 0x41786800,
-	0x0401f8b1, 0x0201f800, 0x00104e13, 0x04000014,
-	0x0201f800, 0x00104e23, 0x04020011, 0x4a035032,
-	0x0000aaaa, 0x4c040000, 0x0201f800, 0x00101694,
-	0x59a8002a, 0x82000500, 0xffff0000, 0x80040540,
-	0x4803502a, 0x5c000800, 0x4a035033, 0x00000000,
-	0x0201f800, 0x00104d76, 0x0401f008, 0x4a03504c,
-	0x00000005, 0x42000000, 0x00000001, 0x0201f800,
-	0x001015fa, 0x0401ff1e, 0x1c01f000, 0x0401f809,
-	0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f08e,
-	0x42006000, 0xbf7f7fff, 0x41786800, 0x0401f08a,
-	0x0201f800, 0x00104e23, 0x04020009, 0x59c40006,
-	0x82000540, 0x000000f0, 0x48038806, 0x42006000,
-	0xbfffffff, 0x41786800, 0x0401f87f, 0x1c01f000,
-	0x800408d0, 0x59a80015, 0x8c000506, 0x04000006,
-	0x59a80010, 0x82000500, 0x000000ff, 0x80040540,
-	0x0401f003, 0x82040540, 0x000000f7, 0x480388a7,
-	0x1c01f000, 0x4807c856, 0x42000000, 0x0010b639,
-	0x0201f800, 0x0010a86e, 0x42003000, 0x00000005,
-	0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000d,
-	0x42027800, 0x00000002, 0x0401f038, 0x4807c856,
-	0x42000000, 0x0010b66a, 0x0201f800, 0x0010a86e,
-	0x42003000, 0x00000000, 0x4d3c0000, 0x4c180000,
-	0x42003000, 0x0000000f, 0x42027800, 0x00000002,
-	0x0401f02a, 0x4807c856, 0x42000000, 0x0010b669,
-	0x0201f800, 0x0010a86e, 0x42003000, 0x00000003,
-	0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000e,
-	0x42027800, 0x00000202, 0x0401f01c, 0x4807c856,
-	0x42000000, 0x0010b668, 0x0201f800, 0x0010a86e,
-	0x42003000, 0x00000004, 0x4d3c0000, 0x4c180000,
-	0x42003000, 0x00000010, 0x42027800, 0x00000202,
-	0x0401f00e, 0x4807c856, 0x42000000, 0x0010b63c,
-	0x0201f800, 0x0010a86e, 0x42003000, 0x00000001,
-	0x4d3c0000, 0x4c180000, 0x42003000, 0x0000000c,
-	0x42027800, 0x00000202, 0x42001800, 0x0000ffff,
-	0x42002000, 0x00000007, 0x0201f800, 0x001038c7,
-	0x5c003000, 0x4d400000, 0x0201f800, 0x0010a784,
-	0x42028000, 0x0000002a, 0x0201f800, 0x00101d90,
-	0x5c028000, 0x5c027800, 0x1c01f000, 0x4807c856,
-	0x04011000, 0x4a03c840, 0x0010b349, 0x4a03c842,
-	0x00000040, 0x40000000, 0x040117ff, 0x42007800,
-	0x0010b349, 0x46007800, 0x00000011, 0x803c7800,
-	0x4a007800, 0x220000ef, 0x4a007801, 0x000000ef,
-	0x4a007802, 0x01380000, 0x4a007803, 0x00000000,
-	0x4a007804, 0xffffffff, 0x4a007805, 0x00000000,
-	0x1c01f000, 0x59c400a3, 0x80300500, 0x80340540,
-	0x480388a3, 0x1c01f000, 0x4833c857, 0x59c400a3,
-	0x80300540, 0x480388a3, 0x80300580, 0x480388a3,
-	0x1c01f000, 0x4803c856, 0x04000004, 0x4a03504b,
-	0x00000001, 0x0401f002, 0x497b504b, 0x1c01f000,
-	0x4803c856, 0x59c80002, 0x80000540, 0x0400000a,
-	0x80000040, 0x04000008, 0x4a039005, 0x00000140,
-	0x42000000, 0x00000006, 0x80000040, 0x040207ff,
-	0x0401f7f4, 0x1c01f000, 0x4c5c0000, 0x4c600000,
-	0x59c4b805, 0x485fc856, 0x8c5cbd3a, 0x04020005,
-	0x42000000, 0x0010b616, 0x0201f800, 0x0010a86e,
-	0x4a038805, 0x02000000, 0x0201f800, 0x00101a59,
-	0x4000c000, 0x0201f800, 0x001019d0, 0x4a038805,
-	0x04000000, 0x5c00c000, 0x5c00b800, 0x1c01f000,
-	0x497a6a00, 0x4a026c00, 0x00000707, 0x497a6801,
-	0x497a6808, 0x497a6809, 0x497a6806, 0x497a6807,
-	0x497a6c0b, 0x497a680c, 0x0201f800, 0x0010393e,
-	0x04020006, 0x5934080f, 0x59340010, 0x80040540,
-	0x02020800, 0x00100615, 0x4a026a04, 0x00000100,
-	0x497a6a03, 0x59340402, 0x82000500, 0x000000ff,
-	0x48026c02, 0x497a6c04, 0x497a6a05, 0x497a6c05,
-	0x497a6811, 0x4d2c0000, 0x5934000d, 0x49466c03,
-	0x80025d40, 0x04000004, 0x0201f800, 0x00100843,
-	0x497a680d, 0x5c025800, 0x599c0401, 0x48026a0b,
-	0x599c0208, 0x48026c12, 0x4a02680a, 0x00006000,
-	0x0201f000, 0x00104acf, 0x42000000, 0x00000005,
-	0x80000d80, 0x0401f02d, 0x0201f800, 0x00104858,
-	0x04020017, 0x59a80026, 0x8c00050a, 0x04020010,
-	0x59340212, 0x82000500, 0x0000ff00, 0x4803c857,
-	0x0400000b, 0x59340a00, 0x8c040d1e, 0x02000000,
-	0x000201f8, 0x42000000, 0x00000029, 0x42000800,
-	0x00001000, 0x492fc857, 0x0401f018, 0x492fc857,
-	0x42000000, 0x00000028, 0x0401f012, 0x59a80805,
-	0x8c040d02, 0x04020003, 0x8c040d00, 0x04000004,
-	0x42000000, 0x00000004, 0x0401f00a, 0x42000000,
-	0x00000029, 0x59340a00, 0x8c040d1e, 0x04000005,
-	0x492fc857, 0x42000800, 0x00001000, 0x0401f003,
-	0x492fc857, 0x80000d80, 0x4803c857, 0x80028540,
-	0x1c01f000, 0x4803c857, 0x59a80005, 0x8c000500,
-	0x040207ec, 0x0201f800, 0x00104836, 0x040207e4,
-	0x59340200, 0x8c00050e, 0x040007e1, 0x0201f000,
-	0x000201f8, 0x0201f800, 0x00104639, 0x040007bf,
-	0x0201f000, 0x000201fc, 0x592c0206, 0x492fc857,
-	0x82000d80, 0x000007ff, 0x04020006, 0x4a025c0a,
-	0x00000030, 0x42026800, 0x0010b320, 0x0401f021,
-	0x82000c80, 0x000007f0, 0x04021046, 0x81ac0400,
-	0x50000000, 0x80026d40, 0x04000038, 0x0201f800,
-	0x00104732, 0x04020038, 0x592c040a, 0x8c00050a,
-	0x04020014, 0x592e6009, 0x83300480, 0x0010cfc0,
-	0x0400103b, 0x41580000, 0x81300480, 0x04021038,
-	0x59300c06, 0x82040580, 0x00000009, 0x04020037,
-	0x4a025a06, 0x00000000, 0x497a5800, 0x59300008,
-	0x80000540, 0x04020018, 0x492e6008, 0x0401f010,
-	0x0201f800, 0x00020892, 0x04000019, 0x592c0206,
-	0x49366009, 0x492e6008, 0x4a026406, 0x00000009,
-	0x497a6015, 0x49325809, 0x82000d80, 0x000007ff,
-	0x04020003, 0x4a026015, 0x00008000, 0x42027000,
-	0x00000043, 0x0201f800, 0x000208d8, 0x80000580,
-	0x0401f020, 0x40000800, 0x58040000, 0x80000d40,
-	0x040207fd, 0x492c0800, 0x0401f01a, 0x42000000,
-	0x0000002c, 0x0401f016, 0x42000000, 0x00000028,
-	0x0401f013, 0x59a80805, 0x82040500, 0x00000003,
-	0x04000004, 0x42000000, 0x00000004, 0x0401f00c,
-	0x42000000, 0x00000029, 0x0401f009, 0x42000000,
-	0x00000008, 0x0401f006, 0x82040580, 0x00000007,
-	0x040207fb, 0x42000000, 0x00000005, 0x80000540,
-	0x1c01f000, 0x492fc857, 0x592e8c06, 0x83440d80,
-	0x000007fc, 0x04000004, 0x83440480, 0x000007f0,
-	0x04021014, 0x0201f800, 0x00020267, 0x04020011,
-	0x0201f800, 0x00104842, 0x04020011, 0x0201f800,
-	0x00020892, 0x0400001c, 0x49366009, 0x492e6008,
-	0x4a026406, 0x0000000a, 0x42027000, 0x00000040,
-	0x0201f800, 0x000208d8, 0x80000580, 0x0401f011,
-	0x42000000, 0x00000028, 0x0401f00d, 0x0201f800,
-	0x00104858, 0x040007fb, 0x59a80805, 0x82040d00,
-	0x00000003, 0x04000004, 0x42000000, 0x00000004,
-	0x0401f003, 0x42000000, 0x00000029, 0x80000540,
-	0x1c01f000, 0x42000000, 0x0000002c, 0x0401f7fc,
-	0x492fc857, 0x592e8c06, 0x4947c857, 0x83440c80,
-	0x00000800, 0x42000000, 0x0000000a, 0x0402119c,
-	0x592c4207, 0x4823c857, 0x82200500, 0x0000000f,
-	0x0c01f001, 0x00104205, 0x0010428d, 0x001042dd,
-	0x001042e8, 0x001042f3, 0x00104201, 0x00104201,
-	0x00104201, 0x00104303, 0x00104361, 0x00104386,
-	0x00104201, 0x00104201, 0x00104201, 0x00104201,
-	0x00104201, 0x4803c857, 0x42000000, 0x0000000c,
-	0x0401f183, 0x592c1008, 0x82081500, 0x00ffffff,
-	0x59a80010, 0x80084d80, 0x42000000, 0x00000010,
-	0x0400017b, 0x0201f800, 0x00104768, 0x04000036,
-	0x4803c857, 0x82004d80, 0x0000001d, 0x0402001a,
-	0x0201f800, 0x00105439, 0x59340405, 0x4c000000,
-	0x0201f800, 0x00104836, 0x5c000000, 0x04000004,
-	0x8c20450a, 0x04000028, 0x80000580, 0x44002800,
-	0x59340008, 0x48002802, 0x59340009, 0x48002801,
-	0x59340006, 0x48002804, 0x59340007, 0x48002803,
-	0x4200b000, 0x00000005, 0x0201f800, 0x00109328,
-	0x0401f18c, 0x4803c857, 0x82004d80, 0x0000001a,
-	0x04020003, 0x40101000, 0x0401f15c, 0x4803c857,
-	0x82004d80, 0x0000001b, 0x04020003, 0x40181000,
-	0x0401f156, 0x4803c857, 0x82004d80, 0x0000001c,
-	0x04000157, 0x82004d80, 0x00000019, 0x42000000,
-	0x0000000a, 0x04000146, 0x42000000, 0x0000000a,
-	0x0402015d, 0x59a8006f, 0x8c000502, 0x0400001b,
-	0x0201f800, 0x00104836, 0x04000018, 0x59340212,
-	0x82000500, 0x0000ff00, 0x42001000, 0x00000010,
-	0x0402000c, 0x42001000, 0x00000008, 0x59a80026,
-	0x8c000506, 0x04020009, 0x59340002, 0x82000500,
-	0x00ff0000, 0x82000580, 0x00ff0000, 0x04000007,
-	0x0201f800, 0x00104ada, 0x42000000, 0x0000001c,
-	0x40181000, 0x0402012d, 0x0201f800, 0x00020892,
-	0x04000137, 0x49366009, 0x492e6008, 0x4a026406,
-	0x00000001, 0x8c20450a, 0x04000004, 0x592c0404,
-	0x8400055c, 0x48025c04, 0x4c200000, 0x4d3c0000,
-	0x42027800, 0x00001800, 0x0201f800, 0x00101de2,
-	0x5c027800, 0x5c004000, 0x8c204512, 0x0400000b,
-	0x599c0018, 0x8c000518, 0x04000008, 0x592c0009,
-	0x82000500, 0x00000380, 0x5934080a, 0x80040d40,
-	0x84040d54, 0x4806680a, 0x417a7800, 0x0401f93a,
-	0x42000800, 0x00000003, 0x0401f941, 0x42027000,
-	0x00000002, 0x0201f800, 0x000208d8, 0x80000580,
-	0x0401f130, 0x0201f800, 0x00020267, 0x04020112,
-	0x0201f800, 0x0010483c, 0x0400000c, 0x0201f800,
-	0x00104836, 0x04020112, 0x4c600000, 0x4178c000,
-	0x42027800, 0x00001800, 0x417a6000, 0x0201f800,
-	0x00101e48, 0x5c00c000, 0x59a8006f, 0x8c000502,
-	0x0400001b, 0x0201f800, 0x00104836, 0x04000018,
-	0x59340212, 0x82000500, 0x0000ff00, 0x42001000,
-	0x00000010, 0x0402000c, 0x42001000, 0x00000008,
-	0x59a80026, 0x8c000506, 0x04020009, 0x59340002,
-	0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
-	0x04000007, 0x0201f800, 0x00104ada, 0x42000000,
-	0x0000001c, 0x40181000, 0x040200d4, 0x0201f800,
-	0x00020892, 0x040000de, 0x5934080a, 0x8c204512,
-	0x0400000c, 0x599c0018, 0x8c000518, 0x04000009,
-	0x592c0009, 0x82000500, 0x00000380, 0x82041500,
-	0xfffffc7f, 0x80080d40, 0x84040d54, 0x0401f002,
-	0x84040d14, 0x4806680a, 0x49366009, 0x492e6008,
-	0x4a026406, 0x00000001, 0x417a7800, 0x0401f8ea,
-	0x42000800, 0x00000005, 0x0401f8f1, 0x42027000,
-	0x00000003, 0x0201f800, 0x000208d8, 0x80000580,
-	0x0401f0e0, 0x0201f800, 0x00020267, 0x040200c2,
-	0x0201f800, 0x0010484b, 0x040200c5, 0x0201f800,
-	0x001092e0, 0x040000b6, 0x80000580, 0x0401f0d5,
-	0x0201f800, 0x00020267, 0x040200b7, 0x0201f800,
-	0x0010484b, 0x040200ba, 0x0201f800, 0x00108ea3,
-	0x040000ab, 0x80000580, 0x0401f0ca, 0x0201f800,
-	0x00020267, 0x040200ac, 0x83444d80, 0x000007fe,
-	0x42000000, 0x0000000a, 0x0402008d, 0x0201f800,
-	0x00104836, 0x040200aa, 0x0201f800, 0x001092f8,
-	0x0400009b, 0x80000580, 0x0401f0ba, 0x82200500,
-	0x00000070, 0x04020005, 0x8c20450e, 0x42000000,
-	0x0000000c, 0x0402007e, 0x8c20450a, 0x0400000d,
-	0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e,
-	0x04020002, 0x853e7d56, 0x82200500, 0x000000a0,
-	0x0201f800, 0x00104822, 0x5c027800, 0x0401f0a1,
-	0x8c204508, 0x04020024, 0x592c1008, 0x82081500,
-	0x00ffffff, 0x59a80010, 0x80084d80, 0x42000000,
-	0x00000010, 0x04000066, 0x0201f800, 0x00104768,
-	0x0400002b, 0x4803c857, 0x82004d80, 0x0000001a,
-	0x04020003, 0x40101000, 0x0401f064, 0x4803c857,
-	0x82004d80, 0x0000001b, 0x04020003, 0x40181000,
-	0x0401f05e, 0x4803c857, 0x82004d80, 0x0000001c,
-	0x0400005f, 0x82004d80, 0x00000019, 0x42000000,
-	0x0000000a, 0x0400004e, 0x42000000, 0x0000000a,
-	0x0401f065, 0x0201f800, 0x00020267, 0x04020062,
-	0x4d3c0000, 0x42027800, 0x00001000, 0x8c20450e,
-	0x04020002, 0x853e7d56, 0x82200500, 0x00000090,
-	0x0201f800, 0x0010480a, 0x5c027800, 0x42000000,
-	0x0000000a, 0x0402003a, 0x0401f06a, 0x836c0580,
-	0x00000003, 0x42000800, 0x00000007, 0x04020006,
-	0x0201f800, 0x0010928e, 0x04000007, 0x80000580,
-	0x0401f064, 0x0201f800, 0x00104871, 0x04000059,
-	0x0401f05c, 0x0201f800, 0x00104871, 0x0400003c,
-	0x0401f058, 0x0201f800, 0x00020267, 0x0402003e,
-	0x836c0580, 0x00000003, 0x04020048, 0x8c204508,
-	0x0400000a, 0x4c600000, 0x4178c000, 0x42027800,
-	0x00001800, 0x417a6000, 0x0201f800, 0x00101e48,
-	0x5c00c000, 0x0401f047, 0x0201f800, 0x0010483c,
-	0x0400000c, 0x0201f800, 0x00104836, 0x04020030,
-	0x4c600000, 0x4178c000, 0x42027800, 0x00001800,
-	0x417a6000, 0x0201f800, 0x00101e48, 0x5c00c000,
-	0x480bc856, 0x0201f800, 0x001090f8, 0x04000018,
-	0x80000580, 0x0401f037, 0x0401f7db, 0x480bc857,
-	0x42000800, 0x00000019, 0x40001000, 0x4200b000,
-	0x00000002, 0x0401f00a, 0x480bc857, 0x40000800,
-	0x4200b000, 0x00000002, 0x0401f005, 0x480bc857,
-	0x40000800, 0x4200b000, 0x00000001, 0x480bc857,
-	0x42028000, 0x00000031, 0x0401f020, 0x480bc857,
-	0x42000800, 0x00000003, 0x4200b000, 0x00000001,
-	0x0401f7f7, 0x480bc857, 0x42000800, 0x0000000a,
-	0x4200b000, 0x00000001, 0x0401f7f1, 0x480bc857,
-	0x42000800, 0x00000009, 0x40001000, 0x4200b000,
-	0x00000002, 0x0401f7ea, 0x480bc857, 0x42000800,
-	0x00000007, 0x4200b000, 0x00000001, 0x0401f7e4,
-	0x480bc857, 0x4200b000, 0x00000001, 0x0401f7e0,
-	0x80028580, 0x4178b000, 0x82000540, 0x00000001,
-	0x1c01f000, 0x4937c857, 0x59326809, 0x59341200,
-	0x813e79c0, 0x04000003, 0x84081540, 0x0401f002,
-	0x84081500, 0x480a6a00, 0x1c01f000, 0x59326809,
-	0x5c000000, 0x4c000000, 0x4803c857, 0x4937c857,
-	0x82040580, 0x00000006, 0x04020004, 0x42000000,
-	0x00000606, 0x0401f021, 0x82040580, 0x00000004,
-	0x04020004, 0x42000000, 0x00000404, 0x0401f01b,
-	0x82040580, 0x00000007, 0x42000000, 0x00000707,
-	0x04000016, 0x82040580, 0x00000003, 0x42000000,
-	0x00000703, 0x04000011, 0x82040580, 0x00000005,
-	0x42000000, 0x00000405, 0x0400000c, 0x82040580,
-	0x00000009, 0x42000000, 0x00000409, 0x04000007,
-	0x82040580, 0x0000000b, 0x42000000, 0x0000070b,
-	0x02020800, 0x00100615, 0x4803c857, 0x48026c00,
-	0x82040d80, 0x00000006, 0x04020005, 0x59341404,
-	0x800811c0, 0x02000800, 0x00100615, 0x1c01f000,
-	0x5c000000, 0x4c000000, 0x4803c857, 0x4947c857,
-	0x481bc857, 0x83440480, 0x00000800, 0x04021034,
-	0x83441400, 0x0010aa00, 0x50080000, 0x80026d40,
-	0x04020011, 0x4c180000, 0x4d2c0000, 0x0201f800,
-	0x00100819, 0x412e6800, 0x5c025800, 0x5c003000,
-	0x04000027, 0x45341000, 0x497a680d, 0x497a6810,
-	0x497a680f, 0x497a680e, 0x4c180000, 0x0401fccd,
-	0x5c003000, 0x59340a12, 0x4c040000, 0x0201f800,
-	0x00104e0d, 0x5c000800, 0x04000009, 0x82180500,
-	0x00ffff00, 0x04000008, 0x59a81010, 0x82081500,
-	0x00ffff00, 0x80080580, 0x04000003, 0x80000580,
-	0x0401f004, 0x82180500, 0x000000ff, 0x800000d0,
-	0x80040d80, 0x04000003, 0x4803c857, 0x48026a12,
-	0x59340002, 0x80180580, 0x04000003, 0x481bc857,
-	0x481a6802, 0x80000580, 0x1c01f000, 0x4803c856,
-	0x82000540, 0x00000001, 0x0401f7fc, 0x4947c857,
-	0x83440480, 0x00000800, 0x04021011, 0x83441400,
-	0x0010aa00, 0x50080000, 0x80026d40, 0x0400000b,
-	0x0401fbf2, 0x0402000a, 0x59a80005, 0x8c000502,
-	0x04000004, 0x59340200, 0x8c00050e, 0x04000004,
-	0x82000540, 0x00000001, 0x1c01f000, 0x80000580,
-	0x0401f7fe, 0x5c000000, 0x4c000000, 0x4803c857,
-	0x4947c857, 0x4d2c0000, 0x4d300000, 0x83440480,
-	0x00000800, 0x04021024, 0x83441400, 0x0010aa00,
-	0x50080000, 0x80026d40, 0x0400001b, 0x45781000,
-	0x5934000d, 0x80025d40, 0x02020800, 0x00100843,
-	0x59366011, 0x813261c0, 0x0400000e, 0x4c640000,
-	0x5930c800, 0x59325808, 0x0201f800, 0x00108df4,
-	0x02020800, 0x00100843, 0x0201f800, 0x000208b4,
-	0x82666540, 0x00000000, 0x040207f6, 0x5c00c800,
-	0x0201f800, 0x00104acf, 0x41365800, 0x0201f800,
-	0x0010083b, 0x80000580, 0x5c026000, 0x5c025800,
-	0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fb,
-	0x4937c857, 0x4c580000, 0x59cc0001, 0x82000500,
-	0x00ffffff, 0x48026802, 0x497a6c01, 0x497a6a01,
-	0x59340200, 0x84000502, 0x48026a00, 0x0201f800,
-	0x00104e0d, 0x04020017, 0x59340403, 0x82000580,
-	0x000007fe, 0x04000005, 0x59a80026, 0x8c00050a,
-	0x04020010, 0x0401f008, 0x59cc0408, 0x8c000518,
-	0x0400000c, 0x59cc0009, 0x48035035, 0x59cc000a,
-	0x48035036, 0x59cc0207, 0x80000540, 0x04020003,
-	0x42000000, 0x00000001, 0x48038893, 0x4803501e,
-	0x59cc0a09, 0x82040d00, 0x00000010, 0x59cc0408,
-	0x82000500, 0x00000020, 0x04000002, 0x84040d40,
-	0x5934000a, 0x82000500, 0xffffffee, 0x80040540,
-	0x4802680a, 0x83cca400, 0x0000000b, 0x8334ac00,
-	0x00000006, 0x4200b000, 0x00000002, 0x0201f800,
-	0x0010a93e, 0x83cca400, 0x0000000d, 0x8334ac00,
-	0x00000008, 0x4200b000, 0x00000002, 0x0201f800,
-	0x0010a93e, 0x59cc0a18, 0x82040480, 0x00000800,
-	0x0402100c, 0x82040480, 0x00000400, 0x04001004,
-	0x42000800, 0x00000400, 0x0401f006, 0x82040480,
-	0x00000200, 0x04001003, 0x42000800, 0x00000200,
-	0x42001000, 0x0010b33f, 0x58080202, 0x80041480,
-	0x04001002, 0x40000800, 0x48066a04, 0x59340403,
-	0x82000580, 0x000007fe, 0x04020003, 0x59cc0a08,
-	0x48066a04, 0x0201f800, 0x00104afd, 0x5c00b000,
-	0x1c01f000, 0x4937c857, 0x59a80026, 0x8c000508,
-	0x04000004, 0x84000556, 0x4803c857, 0x48035026,
-	0x59cc0207, 0x4803c857, 0x48026a05, 0x59cc020a,
-	0x4803c857, 0x48026c05, 0x59341200, 0x599c0818,
-	0x5934180a, 0x4807c857, 0x480bc857, 0x480fc857,
-	0x59cc2006, 0x82102500, 0xff000000, 0x82102580,
-	0x02000000, 0x04000007, 0x8c00050e, 0x04000009,
-	0x8c0c1d14, 0x04000003, 0x8c0c1d0e, 0x04000005,
-	0x8c040d18, 0x04000003, 0x8408154a, 0x0401f002,
-	0x8408150a, 0x8c000510, 0x04000009, 0x8c0c1d14,
-	0x04000003, 0x8c0c1d10, 0x04000005, 0x8c040d18,
-	0x04000003, 0x8408154e, 0x0401f002, 0x8408150e,
-	0x8c000512, 0x04000009, 0x8c0c1d14, 0x04000003,
-	0x8c0c1d12, 0x04000005, 0x8c040d18, 0x04000003,
-	0x8408155c, 0x0401f002, 0x8408151c, 0x480a6a00,
-	0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4d2c0000,
-	0x4c580000, 0x5934000d, 0x80025d40, 0x04000029,
-	0x592c0003, 0x82000480, 0x00000008, 0x0400100b,
-	0x412cb800, 0x592c0001, 0x80025d40, 0x040207f9,
-	0x0201f800, 0x0010082a, 0x04000037, 0x492fc857,
-	0x492cb801, 0x0401f020, 0x832c0c00, 0x00000004,
-	0x4200b000, 0x00000008, 0x50040000, 0x82000580,
-	0xffffffff, 0x04020006, 0x80041000, 0x50080000,
-	0x82000580, 0xffffffff, 0x04000007, 0x82040c00,
-	0x00000002, 0x8058b040, 0x040207f4, 0x0201f800,
-	0x00100615, 0x45480800, 0x454c1000, 0x592c1803,
-	0x800c1800, 0x480e5803, 0x480fc857, 0x0401f014,
-	0x0201f800, 0x0010082a, 0x04000017, 0x492fc857,
-	0x492e680d, 0x497a5802, 0x4a025803, 0x00000001,
-	0x494a5804, 0x494e5805, 0x832c0c00, 0x00000006,
-	0x4200b000, 0x0000000e, 0x46000800, 0xffffffff,
-	0x80040800, 0x8058b040, 0x040207fc, 0x82000540,
-	0x00000001, 0x5c00b000, 0x5c025800, 0x5c00b800,
-	0x1c01f000, 0x80000580, 0x0401f7fb, 0x4803c856,
-	0x4d3c0000, 0x4d2c0000, 0x5934000d, 0x80025d40,
-	0x0400001f, 0x592c0002, 0x80000540, 0x0402001f,
-	0x412e7800, 0x0401f8c8, 0x0402001c, 0x46000800,
-	0xffffffff, 0x46001000, 0xffffffff, 0x4813c857,
-	0x480fc857, 0x580c0003, 0x82000c80, 0x00000002,
-	0x04021014, 0x480fc857, 0x400c0000, 0x812c0580,
-	0x04020004, 0x580c0001, 0x4802680d, 0x0401f003,
-	0x580c0001, 0x48002001, 0x400e5800, 0x0201f800,
-	0x0010083a, 0x82000540, 0x00000001, 0x5c025800,
-	0x5c027800, 0x1c01f000, 0x80000580, 0x0401f7fc,
-	0x80000040, 0x48001803, 0x4803c857, 0x0401f7f6,
-	0x0201f800, 0x00020087, 0x59300007, 0x8400054e,
-	0x48026007, 0x592c1a04, 0x820c1d00, 0x000000ff,
-	0x820c0580, 0x00000048, 0x04000013, 0x0201f000,
-	0x000202b0, 0x8c000500, 0x02020800, 0x000200e6,
-	0x4a026203, 0x00000002, 0x592c1a04, 0x820c1d00,
-	0x000000ff, 0x820c0580, 0x00000018, 0x02000000,
-	0x000202b0, 0x820c0580, 0x00000048, 0x02020000,
-	0x000202b0, 0x42000800, 0x80000804, 0x0201f800,
-	0x00106466, 0x0201f000, 0x000202b9, 0x4a025a06,
-	0x00000008, 0x0201f000, 0x00020381, 0x4a025a06,
-	0x00000029, 0x0201f000, 0x00020381, 0x4a025a06,
-	0x0000002a, 0x0201f000, 0x00020381, 0x4a025a06,
-	0x00000028, 0x0201f000, 0x00020381, 0x4943c857,
-	0x4d440000, 0x4d340000, 0x4d2c0000, 0x4c580000,
-	0x4200b000, 0x000007f0, 0x417a8800, 0x0201f800,
-	0x00020267, 0x04020007, 0x8d3e7d06, 0x04000004,
-	0x59340200, 0x8c00050e, 0x04020002, 0x0401f813,
-	0x81468800, 0x8058b040, 0x040207f5, 0x83440480,
-	0x00000800, 0x04021008, 0x8d3e7d02, 0x04000006,
-	0x42028800, 0x000007f0, 0x4200b000, 0x00000010,
-	0x0401f7eb, 0x5c00b000, 0x5c025800, 0x5c026800,
-	0x5c028800, 0x1c01f000, 0x4d2c0000, 0x41783000,
-	0x5936580f, 0x812e59c0, 0x04000029, 0x592c0204,
-	0x82000500, 0x000000ff, 0x82000580, 0x00000012,
-	0x04000020, 0x8d3e7d00, 0x04000003, 0x0401f83c,
-	0x0402001c, 0x592c2000, 0x497a5800, 0x801831c0,
-	0x04020009, 0x59340010, 0x812c0580, 0x04020004,
-	0x497a680f, 0x497a6810, 0x0401f008, 0x4812680f,
-	0x0401f006, 0x48103000, 0x59340010, 0x812c0580,
-	0x04020002, 0x481a6810, 0x4a025a04, 0x00000103,
-	0x49425a06, 0x497a5c09, 0x0201f800, 0x00108f7d,
-	0x0201f800, 0x00020381, 0x40125800, 0x0401f7da,
-	0x412c3000, 0x592e5800, 0x0401f7d7, 0x5c025800,
-	0x1c01f000, 0x4803c856, 0x41781800, 0x5934000f,
-	0x80025d40, 0x04000010, 0x592c0005, 0x80200580,
-	0x592c0000, 0x04000003, 0x412c1800, 0x0401f7f9,
-	0x497a5800, 0x800c19c0, 0x04000008, 0x48001800,
-	0x80000540, 0x04020004, 0x480e6810, 0x82000540,
-	0x00000001, 0x1c01f000, 0x4802680f, 0x80000540,
-	0x040207fd, 0x497a6810, 0x0401f7f9, 0x592c0008,
-	0x81480580, 0x04020003, 0x592c0009, 0x814c0580,
-	0x1c01f000, 0x4803c856, 0x4c580000, 0x413c1800,
-	0x400c2000, 0x593c0002, 0x80000540, 0x04020018,
-	0x4200b000, 0x00000008, 0x820c0c00, 0x00000004,
-	0x50040000, 0x81480580, 0x04020005, 0x80041000,
-	0x50080000, 0x814c0580, 0x0400000d, 0x82040c00,
-	0x00000002, 0x8058b040, 0x040207f6, 0x400c2000,
-	0x580c0001, 0x80001d40, 0x040207ee, 0x82000540,
-	0x00000001, 0x5c00b000, 0x1c01f000, 0x80000580,
-	0x0401f7fd, 0x4937c857, 0x4c580000, 0x4d2c0000,
-	0x5934000d, 0x80025d40, 0x04020016, 0x0201f800,
-	0x0010082a, 0x04000010, 0x492e680d, 0x4a025802,
-	0x00000001, 0x497a5803, 0x832c0c00, 0x00000004,
-	0x4200b000, 0x00000010, 0x46000800, 0xffffffff,
-	0x80040800, 0x8058b040, 0x040207fc, 0x82000540,
-	0x00000001, 0x5c025800, 0x5c00b000, 0x1c01f000,
-	0x4d2c0000, 0x592e5801, 0x0201f800, 0x00100843,
-	0x5c025800, 0x0401f7ea, 0x4d2c0000, 0x5936580d,
-	0x812e59c0, 0x04000007, 0x4937c857, 0x497a680d,
-	0x0201f800, 0x00100843, 0x82000540, 0x00000001,
-	0x5c025800, 0x1c01f000, 0x59340405, 0x4937c857,
-	0x4803c857, 0x8c000508, 0x1c01f000, 0x4803c856,
-	0x0201f800, 0x00104e0d, 0x04000011, 0x59a80815,
-	0x8c040d04, 0x0402000e, 0x59a80826, 0x8c040d06,
-	0x0400000b, 0x83ac0400, 0x000007fe, 0x50000000,
-	0x80026d40, 0x04000006, 0x0401f9a8, 0x04020004,
-	0x59340200, 0x8400055a, 0x48026a00, 0x599c0017,
-	0x8c000508, 0x04000015, 0x4200b000, 0x000007f0,
-	0x417a8800, 0x0201f800, 0x00020267, 0x0402000c,
-	0x0401f99a, 0x0402000a, 0x59a80010, 0x59340802,
-	0x80040580, 0x82000500, 0x00ffff00, 0x04020004,
-	0x59340200, 0x8400055a, 0x48026a00, 0x81468800,
-	0x8058b040, 0x040207f0, 0x0401f885, 0x04000003,
-	0x59a80836, 0x0401f006, 0x599c0017, 0x8c000508,
-	0x04000007, 0x42000800, 0x000007d0, 0x42001000,
-	0x001046c4, 0x0201f800, 0x00105da7, 0x1c01f000,
-	0x4803c856, 0x4d300000, 0x4d340000, 0x4d440000,
-	0x4d3c0000, 0x4c580000, 0x42001000, 0x001046c4,
-	0x0201f800, 0x00105cc9, 0x59a80826, 0x8c040d06,
-	0x04000015, 0x0401f86a, 0x04000013, 0x83ae6c00,
-	0x000007fe, 0x51366800, 0x59340200, 0x8400051a,
-	0x48026a00, 0x599c0017, 0x8c000508, 0x04000007,
-	0x42000800, 0x000007d0, 0x42001000, 0x001046c4,
-	0x0201f800, 0x00105da7, 0x0201f800, 0x00101bf0,
-	0x0401f027, 0x4200b000, 0x000007f0, 0x80028d80,
-	0x0201f800, 0x00020267, 0x0402001e, 0x59340200,
-	0x8c00051a, 0x0400001b, 0x59368c03, 0x417a7800,
-	0x42028000, 0x00000029, 0x41783000, 0x0201f800,
-	0x0010a258, 0x59340200, 0x84000558, 0x8400051a,
-	0x48026a00, 0x4937c857, 0x4a026c00, 0x00000707,
-	0x42028000, 0x00000029, 0x0201f800, 0x001067f6,
-	0x417a7800, 0x0201f800, 0x00106543, 0x417a6000,
-	0x0201f800, 0x0010a0da, 0x0201f800, 0x00106982,
-	0x81468800, 0x8058b040, 0x040207de, 0x5c00b000,
-	0x5c027800, 0x5c028800, 0x5c026800, 0x5c026000,
-	0x1c01f000, 0x4933c857, 0x59303809, 0x581c0200,
-	0x8400051a, 0x48003a00, 0x1c01f000, 0x42026800,
-	0x0010b320, 0x497a680e, 0x42028800, 0x000007ff,
-	0x0201f800, 0x001040e4, 0x4937c857, 0x4a026c00,
-	0x00000606, 0x4a026802, 0x00ffffff, 0x4a026a04,
-	0x00000200, 0x4a026c04, 0x00000002, 0x1c01f000,
-	0x59300009, 0x50000000, 0x4933c857, 0x4803c857,
-	0x8c00050e, 0x1c01f000, 0x59300009, 0x50000000,
-	0x8c00050a, 0x1c01f000, 0x4933c856, 0x0401f90f,
-	0x04000006, 0x59340400, 0x82000d00, 0x000000ff,
-	0x82041580, 0x00000005, 0x1c01f000, 0x4d340000,
-	0x83ac0400, 0x000007fe, 0x50000000, 0x80026d40,
-	0x04000003, 0x59340200, 0x8c00051a, 0x5c026800,
-	0x1c01f000, 0x4937c857, 0x493fc857, 0x59340403,
-	0x81ac0400, 0x50000000, 0x81340580, 0x02020800,
-	0x00100615, 0x59341200, 0x813e79c0, 0x04000003,
-	0x8408155e, 0x0401f002, 0x8408151e, 0x480a6a00,
-	0x1c01f000, 0x4937c857, 0x0201f800, 0x00101eb0,
-	0x04000006, 0x59a80835, 0x42001000, 0x0010475f,
-	0x0201f800, 0x00105da7, 0x1c01f000, 0x4937c857,
-	0x42001000, 0x0010475f, 0x0201f800, 0x00105cc9,
-	0x59a81026, 0x84081512, 0x480b5026, 0x1c01f000,
-	0x4c380000, 0x4c340000, 0x4c240000, 0x4c600000,
-	0x4008c000, 0x83440480, 0x00000800, 0x04021045,
-	0x80002d80, 0x41442000, 0x83447400, 0x0010aa00,
-	0x4200b000, 0x000007f0, 0x83444c80, 0x000007f0,
-	0x04001003, 0x4200b000, 0x00000010, 0x50380000,
-	0x80000540, 0x0402001e, 0x41440000, 0x80100580,
-	0x04020043, 0x40102800, 0x82104c80, 0x000007f0,
-	0x04001015, 0x82104d80, 0x000007fc, 0x04020005,
-	0x82604d80, 0x00fffffc, 0x0402002a, 0x0401f00e,
-	0x82104d80, 0x000007fd, 0x04020005, 0x82604d80,
-	0x00fffffd, 0x04020023, 0x0401f007, 0x82104d80,
-	0x000007ff, 0x0402001f, 0x82604d80, 0x00ffffff,
-	0x0402001c, 0x84142d5e, 0x0401f029, 0x40006800,
-	0x58343002, 0x82183500, 0x00ffffff, 0x40180000,
-	0x80600580, 0x04020019, 0x40100000, 0x81440580,
-	0x0402000a, 0x40366800, 0x8c204508, 0x04000053,
-	0x0401ff8a, 0x04020051, 0x4947c857, 0x42000000,
-	0x0000001d, 0x0401f04e, 0x4947c857, 0x480bc857,
-	0x4823c857, 0x42000000, 0x0000001a, 0x0401f048,
-	0x4947c857, 0x4863c857, 0x4813c857, 0x42000000,
-	0x00000019, 0x0401f042, 0x40100000, 0x81440580,
-	0x04020007, 0x58343002, 0x4947c857, 0x481bc857,
-	0x42000000, 0x0000001b, 0x0401f039, 0x80102000,
-	0x80387000, 0x83444c80, 0x000007f0, 0x04001009,
-	0x82104d80, 0x00000800, 0x0402000c, 0x42002000,
-	0x000007f0, 0x42007000, 0x0010b1f0, 0x0401f007,
-	0x82104d80, 0x000007f0, 0x04020004, 0x41782000,
-	0x42007000, 0x0010aa00, 0x8058b040, 0x040207a4,
-	0x801429c0, 0x04020007, 0x0201f800, 0x00100615,
-	0x4947c857, 0x42000000, 0x0000000a, 0x0401f01c,
-	0x4d2c0000, 0x4c180000, 0x40603000, 0x0401fc19,
-	0x4947c857, 0x4937c857, 0x5c003000, 0x5c025800,
-	0x040207f4, 0x497a6a12, 0x59a80026, 0x8c00050a,
-	0x0402000d, 0x82600500, 0x00ffff00, 0x04000006,
-	0x59a84810, 0x82244d00, 0x00ffff00, 0x80240580,
-	0x04020005, 0x82600500, 0x000000ff, 0x800000d0,
-	0x48026a12, 0x48626802, 0x80000580, 0x80000540,
-	0x5c00c000, 0x5c004800, 0x5c006800, 0x5c007000,
-	0x1c01f000, 0x5934000f, 0x5934140b, 0x80081040,
-	0x04001002, 0x480a6c0b, 0x80000540, 0x02020800,
-	0x00020275, 0x1c01f000, 0x4803c857, 0x4947c857,
-	0x4c300000, 0x82006500, 0x00000030, 0x04000006,
-	0x4c000000, 0x0201f800, 0x001091f3, 0x5c000000,
-	0x0402000b, 0x8c00050e, 0x04000006, 0x0201f800,
-	0x00020267, 0x04020006, 0x4937c857, 0x0401fc36,
-	0x80000580, 0x5c006000, 0x1c01f000, 0x82000540,
-	0x00000001, 0x0401f7fc, 0x4803c857, 0x4c580000,
-	0x4d440000, 0x40001000, 0x80000d80, 0x4200b000,
-	0x000007f0, 0x4c040000, 0x40068800, 0x4c080000,
-	0x40080000, 0x0401ffdd, 0x5c001000, 0x5c000800,
-	0x80040800, 0x8058b040, 0x040207f7, 0x5c028800,
-	0x5c00b000, 0x1c01f000, 0x4c5c0000, 0x59340400,
-	0x8200bd80, 0x00000606, 0x5c00b800, 0x1c01f000,
-	0x4c5c0000, 0x59340400, 0x8200bd80, 0x00000404,
-	0x5c00b800, 0x1c01f000, 0x4c5c0000, 0x59340400,
-	0x8200bd80, 0x00000404, 0x04000003, 0x8200bd80,
-	0x00000606, 0x5c00b800, 0x1c01f000, 0x4c5c0000,
-	0x4c600000, 0x59340400, 0x8200bd00, 0x0000ff00,
-	0x825cc580, 0x00000400, 0x04000003, 0x825cc580,
-	0x00000600, 0x5c00c000, 0x5c00b800, 0x1c01f000,
-	0x4c5c0000, 0x59340400, 0x82000500, 0x000000ff,
-	0x8200bd80, 0x00000003, 0x04000003, 0x8200bd80,
-	0x00000005, 0x5c00b800, 0x1c01f000, 0x5c000000,
-	0x4c000000, 0x4803c857, 0x4c5c0000, 0x59340400,
-	0x82000500, 0x0000ff00, 0x8400b9c0, 0x805c0580,
-	0x4937c857, 0x4803c857, 0x48026c00, 0x5c00b800,
-	0x1c01f000, 0x4c040000, 0x4c080000, 0x592c0207,
-	0x8c00050c, 0x0400000f, 0x592e8c06, 0x82000500,
-	0x00000080, 0x84000548, 0x4d3c0000, 0x42027800,
-	0x00001000, 0x0401ff8d, 0x5c027800, 0x82000540,
-	0x00000001, 0x5c001000, 0x5c000800, 0x1c01f000,
-	0x80000580, 0x0401f7fc, 0x592c040b, 0x82000500,
-	0x0000e000, 0x82000580, 0x00006000, 0x04000019,
-	0x836c0580, 0x00000003, 0x04000016, 0x836c0580,
-	0x00000002, 0x04020106, 0x59a80026, 0x82000d00,
-	0x00000038, 0x04020005, 0x59a80832, 0x800409c0,
-	0x0400000c, 0x0401f0fe, 0x82000d00, 0x00000003,
-	0x82040d80, 0x00000003, 0x040200f9, 0x82000d00,
-	0x00000028, 0x04020003, 0x8c00050c, 0x040000f4,
-	0x592c100a, 0x82080500, 0xff000000, 0x040200d2,
-	0x59a80010, 0x80080580, 0x040000cc, 0x592c0c0b,
-	0x82040d00, 0x0000e000, 0x82040480, 0x00008000,
-	0x040210cc, 0x592e8c06, 0x83440480, 0x00000800,
-	0x04001007, 0x83440580, 0x0000ffff, 0x040200b3,
-	0x800409c0, 0x040200fe, 0x0401f0b0, 0x800409c0,
-	0x040200fb, 0x41784000, 0x0401feaa, 0x040200e2,
-	0x59342204, 0x592c000d, 0x80100480, 0x040010bc,
-	0x42027000, 0x00000053, 0x592c2409, 0x82100500,
-	0xffffff00, 0x040200aa, 0x4813c857, 0x592c000c,
-	0x800001c0, 0x04000083, 0x82100580, 0x00000004,
-	0x040000a0, 0x82100580, 0x00000051, 0x0400009d,
-	0x82100580, 0x00000003, 0x04000016, 0x82100580,
-	0x00000020, 0x0400004b, 0x82100580, 0x00000024,
-	0x04000042, 0x82100580, 0x00000021, 0x04000042,
-	0x82100580, 0x00000050, 0x04000037, 0x82100580,
-	0x00000052, 0x04000031, 0x82100580, 0x00000005,
-	0x0402006b, 0x42027000, 0x00000001, 0x0401f01b,
-	0x42027000, 0x00000002, 0x59a8006f, 0x8c000502,
-	0x04000016, 0x0401ff45, 0x04000014, 0x59340212,
-	0x82000500, 0x0000ff00, 0x42001000, 0x00000010,
-	0x0402000c, 0x59a80026, 0x8c000506, 0x0402006f,
-	0x42001000, 0x00000008, 0x59340002, 0x82000500,
-	0x00ff0000, 0x82000580, 0x00ff0000, 0x04000003,
-	0x0401f9d6, 0x04020065, 0x0201f800, 0x00020892,
-	0x04000081, 0x4a026406, 0x00000010, 0x49366009,
-	0x42000800, 0x00000003, 0x83380580, 0x00000002,
-	0x04000003, 0x42000800, 0x0000000b, 0x0201f800,
-	0x001043c7, 0x0401f044, 0x42027000, 0x00000000,
-	0x0401f003, 0x42027000, 0x00000004, 0x0401ff30,
-	0x04020074, 0x0401f036, 0x42027000, 0x00000033,
-	0x0401f006, 0x42027000, 0x00000005, 0x0401f003,
-	0x42027000, 0x00000003, 0x0401ff1c, 0x04020069,
-	0x59a8006f, 0x8c000502, 0x04000016, 0x0401ff0b,
-	0x04000014, 0x59340212, 0x82000500, 0x0000ff00,
-	0x42001000, 0x00000010, 0x0402000c, 0x59a80026,
-	0x8c000506, 0x04020035, 0x42001000, 0x00000008,
-	0x59340002, 0x82000500, 0x00ff0000, 0x82000580,
-	0x00ff0000, 0x04000003, 0x0401f99c, 0x0402002b,
-	0x0201f800, 0x00020892, 0x04000047, 0x4a026406,
-	0x00000010, 0x49366009, 0x42000800, 0x00000005,
-	0x83380580, 0x00000003, 0x04000003, 0x42000800,
-	0x00000009, 0x0201f800, 0x001043c7, 0x0401f00a,
-	0x82102580, 0x00000011, 0x04020030, 0x0201f800,
-	0x00020892, 0x04000034, 0x4a026406, 0x00000010,
-	0x49366009, 0x492e6008, 0x49325808, 0x813669c0,
-	0x04000007, 0x592c0c0b, 0x8c040d18, 0x04000004,
-	0x59340200, 0x84000514, 0x48026a00, 0x0201f800,
-	0x000208d8, 0x80000580, 0x1c01f000, 0x82000540,
-	0x00000001, 0x0401f7fd, 0x42001000, 0x0000000a,
-	0x0401f018, 0x42001000, 0x00000010, 0x0401f015,
-	0x42001000, 0x00000016, 0x0401f012, 0x42001000,
-	0x00000017, 0x0401f00f, 0x42001000, 0x00000018,
-	0x0401f00c, 0x42001000, 0x0000001b, 0x0401f009,
-	0x42001000, 0x0000001e, 0x0401f006, 0x42001000,
-	0x00000024, 0x0401f003, 0x42001000, 0x00000020,
-	0x42000800, 0x00000019, 0x42028000, 0x00000031,
-	0x0401f7df, 0x42000800, 0x00000003, 0x0401f003,
-	0x42000800, 0x0000000a, 0x41781000, 0x0401f7f7,
-	0x42000800, 0x00000009, 0x59341400, 0x0401f7f3,
-	0x42028000, 0x00000008, 0x0401f005, 0x42000800,
-	0x00000007, 0x416c1000, 0x0401f7ec, 0x41780800,
-	0x41781000, 0x0401f7ca, 0x42028000, 0x00000000,
-	0x0401f7fb, 0x82004d80, 0x0000001d, 0x02000800,
-	0x00100615, 0x82004d80, 0x0000001a, 0x04020004,
-	0x40101000, 0x40000800, 0x0401f7dc, 0x82004d80,
-	0x0000001b, 0x04020003, 0x40181000, 0x0401f7fa,
-	0x82004d80, 0x0000001c, 0x040007f7, 0x82004d80,
-	0x00000019, 0x040007b5, 0x0401f7d6, 0x592e6008,
-	0x0201f800, 0x001091e3, 0x040007b3, 0x59300c06,
-	0x82040580, 0x00000011, 0x040207d6, 0x83440580,
-	0x0000ffff, 0x04020005, 0x59326809, 0x813669c0,
-	0x0400000e, 0x0401f7cf, 0x592c100a, 0x82081500,
-	0x00ffffff, 0x41784000, 0x0401fd9e, 0x040207d6,
-	0x59300009, 0x800001c0, 0x04000003, 0x81340580,
-	0x040207c4, 0x49366009, 0x592c0c0b, 0x82041500,
-	0x0000e000, 0x82080580, 0x00006000, 0x04000011,
-	0x42000800, 0x00000100, 0x813669c0, 0x04000002,
-	0x59340a04, 0x592c000d, 0x80040480, 0x040017a0,
-	0x59300a03, 0x82040580, 0x00000007, 0x040207b1,
-	0x492e6008, 0x42027000, 0x00000054, 0x0401f774,
-	0x0201f800, 0x0010a6e6, 0x040007b4, 0x0401f7a9,
-	0x492fc857, 0x592e6008, 0x4933c857, 0x0201f800,
-	0x001091e3, 0x04000047, 0x59301406, 0x82080580,
-	0x00000005, 0x04020061, 0x592c0207, 0x8c000500,
-	0x04020085, 0x59a80021, 0x800001c0, 0x0402006a,
-	0x59301203, 0x82080580, 0x00000007, 0x04020057,
-	0x592e8c06, 0x83440480, 0x00000800, 0x04021032,
-	0x41784000, 0x592c1009, 0x82081500, 0x00ffffff,
-	0x0401fd60, 0x0402005f, 0x59300009, 0x800001c0,
-	0x04000003, 0x81340580, 0x04020048, 0x4d300000,
-	0x592e6013, 0x4933c857, 0x83300580, 0xffffffff,
-	0x0400000d, 0x0201f800, 0x001091e3, 0x5c026000,
-	0x04000029, 0x591c1406, 0x82080580, 0x00000006,
-	0x04000046, 0x82080580, 0x00000011, 0x04000043,
-	0x0401f002, 0x5c026000, 0x59a80010, 0x592c100a,
-	0x82081500, 0x00ffffff, 0x80081580, 0x04020017,
-	0x592c1009, 0x82081500, 0x00ffffff, 0x80081580,
-	0x0400000f, 0x49366009, 0x492e6008, 0x42027000,
-	0x00000092, 0x0201f800, 0x000208d8, 0x80000580,
-	0x1c01f000, 0x42001000, 0x0000000a, 0x0401f00c,
-	0x42001000, 0x00000010, 0x0401f009, 0x42001000,
-	0x00000014, 0x0401f006, 0x42001000, 0x00000018,
-	0x0401f003, 0x42001000, 0x0000003c, 0x492fc857,
-	0x480bc857, 0x42000800, 0x00000019, 0x42028000,
-	0x00000031, 0x82000540, 0x00000001, 0x0401f7e9,
-	0x492fc857, 0x4803c857, 0x480bc857, 0x40000800,
-	0x0401f7f7, 0x492fc857, 0x42000800, 0x0000000a,
-	0x41781000, 0x0401f7f2, 0x4933c857, 0x59300406,
-	0x4803c857, 0x59300203, 0x4803c857, 0x59300009,
-	0x4803c857, 0x42028000, 0x00000008, 0x41780800,
-	0x41781000, 0x0401f7e8, 0x42000800, 0x0000001e,
-	0x0401f7f0, 0x42000800, 0x00000001, 0x0401f7ed,
-	0x82004d80, 0x0000001d, 0x02000800, 0x00100615,
-	0x82004d80, 0x0000001a, 0x04020003, 0x40101000,
-	0x0401f7dc, 0x82004d80, 0x0000001b, 0x04020003,
-	0x40181000, 0x0401f7d7, 0x82004d80, 0x0000001c,
-	0x040007d4, 0x82004d80, 0x00000019, 0x040007d1,
-	0x0401f7d5, 0x0201f800, 0x0010a6e6, 0x040207d7,
-	0x42028000, 0x00000000, 0x0401f7dd, 0x5c000000,
-	0x4c000000, 0x4803c857, 0x59302009, 0x801021c0,
-	0x04000035, 0x58101400, 0x4813c857, 0x480bc857,
-	0x82081d00, 0x000000ff, 0x59300c03, 0x82040580,
-	0x00000008, 0x04000022, 0x82040580, 0x0000000a,
-	0x04000017, 0x82040580, 0x0000000c, 0x04000010,
-	0x82040580, 0x00000002, 0x04000019, 0x82040580,
-	0x00000001, 0x04000012, 0x82040580, 0x00000003,
-	0x0400000b, 0x82040580, 0x00000005, 0x04000004,
-	0x82040580, 0x00000033, 0x04020017, 0x820c0580,
-	0x00000009, 0x0400000d, 0x0401f013, 0x820c0580,
-	0x00000005, 0x04000009, 0x0401f00f, 0x820c0580,
-	0x0000000b, 0x04000005, 0x0401f00b, 0x820c0580,
-	0x00000003, 0x04020008, 0x82081d00, 0xffffff00,
-	0x840c01c0, 0x800c0540, 0x4807c857, 0x4803c857,
-	0x48002400, 0x1c01f000, 0x599c0017, 0x8c00050a,
-	0x04000003, 0x80000580, 0x1c01f000, 0x59a80026,
-	0x82000500, 0x00000028, 0x04000008, 0x42028800,
-	0x000007fd, 0x0201f800, 0x00020267, 0x04020003,
-	0x5934000a, 0x8c000504, 0x1c01f000, 0x4d300000,
-	0x5934000e, 0x80026540, 0x04000006, 0x0201f800,
-	0x0010600e, 0x02000800, 0x001061e5, 0x497a680e,
-	0x5c026000, 0x1c01f000, 0x4d440000, 0x4d340000,
-	0x80000580, 0x40001800, 0x40028800, 0x82080580,
-	0x00000008, 0x04020003, 0x42001800, 0x00000001,
-	0x0201f800, 0x00020267, 0x0402000a, 0x0401fd4f,
-	0x04020008, 0x800c19c0, 0x04000004, 0x59340405,
-	0x8c000508, 0x04000003, 0x80081040, 0x04000009,
-	0x81468800, 0x83440480, 0x00000800, 0x040017f1,
-	0x80000580, 0x5c026800, 0x5c028800, 0x1c01f000,
-	0x82000540, 0x00000001, 0x5c026800, 0x5c028800,
-	0x1c01f000, 0x42000800, 0x00000001, 0x0401fb0e,
-	0x04020034, 0x59a80026, 0x8c000508, 0x04020031,
-	0x5934100a, 0x82081500, 0x0000e000, 0x42007000,
-	0x0010b33f, 0x58380401, 0x8c000504, 0x0402001c,
-	0x42000800, 0x00000001, 0x82080580, 0x00006000,
-	0x04000024, 0x59341a04, 0x820c0480, 0x00000800,
-	0x04001004, 0x42000800, 0x00000a00, 0x0401f009,
-	0x820c0480, 0x00000400, 0x04001004, 0x42000800,
-	0x00000500, 0x0401f003, 0x42000800, 0x00000200,
-	0x82080580, 0x00002000, 0x04000002, 0x800408c2,
-	0x82040d40, 0x00000001, 0x0401f00e, 0x42000800,
-	0x00000008, 0x82080580, 0x00002000, 0x04020004,
-	0x42000800, 0x00000004, 0x0401f006, 0x82080580,
-	0x00000000, 0x04020003, 0x42000800, 0x00000002,
-	0x48066c04, 0x1c01f000, 0x4a033020, 0x00000000,
-	0x4a03b104, 0x80000000, 0x497b3026, 0x497b3027,
-	0x497b3028, 0x497b3029, 0x497b302b, 0x497b3021,
-	0x4a03b104, 0x60000001, 0x1c01f000, 0x599c0018,
-	0x4803c856, 0x497b3024, 0x497b3025, 0x82000500,
-	0x0000000f, 0x48033022, 0x04000008, 0x599c0216,
-	0x82000500, 0x0000ffff, 0x04020003, 0x42000000,
-	0x00000002, 0x48033023, 0x1c01f000, 0x0401fff0,
-	0x4a03c826, 0x00000004, 0x599c0209, 0x80000540,
-	0x0400001f, 0x599c0207, 0x80000540, 0x04000007,
-	0x800000cc, 0x599c080d, 0x80040400, 0x4803b100,
-	0x497bb102, 0x59d80101, 0x599c000d, 0x4803b100,
-	0x599c000e, 0x4803b101, 0x599c0207, 0x80000540,
-	0x04020002, 0x497bb102, 0x599c0a09, 0x82040540,
-	0x00400000, 0x59980822, 0x4803b103, 0x4a03b109,
-	0x00000004, 0x4a03b104, 0x10000001, 0x800409c0,
-	0x04020004, 0x4a033020, 0x00000001, 0x1c01f000,
-	0x4a033020, 0x00000002, 0x0401f7fd, 0x592c0204,
-	0x492fc857, 0x80000540, 0x04000008, 0x42034000,
-	0x0010b2a0, 0x59a1d81e, 0x80edd9c0, 0x02000800,
-	0x00100615, 0x0401f003, 0x5931d821, 0x58ef400b,
-	0x58ec0009, 0x800001c0, 0x08020000, 0x0201f800,
-	0x00100615, 0x5998002b, 0x84000540, 0x4803302b,
-	0x0201f000, 0x00020403, 0x42000000, 0x0010b654,
-	0x0201f800, 0x0010a86e, 0x492fc857, 0x59980026,
-	0x59980828, 0x80000000, 0x48033026, 0x800409c0,
-	0x492f3028, 0x04000003, 0x492c0800, 0x0401f002,
-	0x492f3029, 0x592c0001, 0x80000d40, 0x02020000,
-	0x000202fb, 0x1c01f000, 0x59980026, 0x59980828,
-	0x80000000, 0x48033026, 0x492fc857, 0x800409c0,
-	0x492f3028, 0x04000003, 0x492c0800, 0x0401f002,
-	0x492f3029, 0x592c0001, 0x80000d40, 0x02020800,
-	0x000202fb, 0x0402d00e, 0x59980029, 0x80025d40,
-	0x0400000f, 0x59980026, 0x80000040, 0x48033026,
-	0x04020002, 0x48033028, 0x592c0000, 0x48033029,
-	0x492fc857, 0x492fb107, 0x0400d7f4, 0x42000000,
-	0x0010b654, 0x0201f800, 0x0010a86e, 0x0402e01d,
-	0x59da5908, 0x496a5800, 0x412ed000, 0x815eb800,
-	0x0400e7fc, 0x59c80000, 0x82000540, 0x00001200,
-	0x48039000, 0x04006019, 0x59d8010a, 0x59d8090a,
-	0x80040d80, 0x040207fd, 0x900001c0, 0x82000540,
-	0x00000013, 0x4803c011, 0x5998002b, 0x84000500,
-	0x4803302b, 0x59e00017, 0x8c000508, 0x04000003,
-	0x4a03c017, 0x00000003, 0x4203e000, 0x30000001,
-	0x59d80105, 0x82000500, 0x00018780, 0x02020000,
-	0x00020482, 0x1c01f000, 0x5998002b, 0x84000540,
-	0x4803302b, 0x0401f7f7, 0x5c000000, 0x4c000000,
-	0x4803c857, 0x492fc857, 0x4943c857, 0x4807c857,
-	0x4a025a04, 0x00000103, 0x49425a06, 0x48065a08,
-	0x4a025c06, 0x0000ffff, 0x813261c0, 0x04000003,
-	0x59300402, 0x48025c06, 0x832c0400, 0x00000009,
-	0x04011000, 0x4803c840, 0x4a03c842, 0x0000000b,
-	0x04011000, 0x1c01f000, 0x42000000, 0x0010b654,
-	0x0201f800, 0x0010a86e, 0x0201f000, 0x00020464,
-	0x59a80017, 0x82000c80, 0x0000000a, 0x02021800,
-	0x00100615, 0x0c01f809, 0x4a038805, 0x000000f0,
-	0x59c400a3, 0x82000500, 0x02870000, 0x02020800,
-	0x00100615, 0x1c01f000, 0x00104c99, 0x00104c25,
-	0x00104c40, 0x00104c69, 0x00104c8c, 0x00104cc6,
-	0x00104cd8, 0x00104c40, 0x00104caa, 0x00104c24,
-	0x1c01f000, 0x4a038808, 0x00000004, 0x0401f8f9,
-	0x0201f800, 0x0010507b, 0x59c40805, 0x8c040d0e,
-	0x04020013, 0x8c040d0a, 0x0402000b, 0x8c040d0c,
-	0x04020006, 0x8c040d08, 0x0400000d, 0x4a035017,
-	0x00000003, 0x0401f00a, 0x4a035017, 0x00000000,
-	0x0401f007, 0x42000000, 0x0010b642, 0x0201f800,
-	0x0010a86e, 0x4a035017, 0x00000002, 0x1c01f000,
-	0x4a038808, 0x00000002, 0x0401f8de, 0x59c40805,
-	0x8c040d08, 0x04020021, 0x8c040d0c, 0x0402001c,
-	0x8c040d0e, 0x04020017, 0x82040500, 0x000000f0,
-	0x0402001c, 0x0201f800, 0x0010507b, 0x4a038808,
-	0x00000080, 0x59c40002, 0x8400050c, 0x48038802,
-	0x0401f9d7, 0x4d3c0000, 0x42027800, 0x00000001,
-	0x0201f800, 0x00109640, 0x5c027800, 0x4a038808,
-	0x00000080, 0x4a035017, 0x00000009, 0x0401f009,
-	0x4a035017, 0x00000001, 0x0401f006, 0x4a035017,
-	0x00000000, 0x0401f003, 0x4a035017, 0x00000003,
-	0x1c01f000, 0x0401f8b7, 0x4a038808, 0x00000080,
-	0x59c40805, 0x8c040d0a, 0x0402001b, 0x8c040d0c,
-	0x04020016, 0x8c040d0e, 0x04020011, 0x82040500,
-	0x000000f0, 0x04020016, 0x59c40002, 0x8400050c,
-	0x48038802, 0x0401f9b2, 0x4d3c0000, 0x42027800,
-	0x00000001, 0x0201f800, 0x00109640, 0x5c027800,
-	0x4a035017, 0x00000009, 0x0401f009, 0x4a035017,
-	0x00000001, 0x0401f006, 0x4a035017, 0x00000000,
-	0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
-	0x4a038808, 0x00000008, 0x59c40805, 0x8c040d0c,
-	0x04020006, 0x8c040d0e, 0x04000006, 0x4a035017,
-	0x00000001, 0x0401f003, 0x4a035017, 0x00000000,
-	0x1c01f000, 0x0401f8d3, 0x59c40805, 0x8c040d0c,
-	0x0402000d, 0x4c040000, 0x0401f882, 0x5c000800,
-	0x8c040d0a, 0x04020006, 0x8c040d0e, 0x04000006,
-	0x4a035017, 0x00000001, 0x0401f003, 0x4a035017,
-	0x00000002, 0x1c01f000, 0x4a038808, 0x00000008,
-	0x42001000, 0x00104d2c, 0x0201f800, 0x00105dbd,
-	0x59c40805, 0x8c040d0a, 0x0402000d, 0x8c040d08,
-	0x0402000b, 0x8c040d0c, 0x04020006, 0x8c040d0e,
-	0x0400000d, 0x4a035017, 0x00000001, 0x0401f00a,
-	0x4a035017, 0x00000000, 0x0401f007, 0x42000000,
-	0x0010b642, 0x0201f800, 0x0010a86e, 0x4a035017,
-	0x00000004, 0x1c01f000, 0x0401f8a6, 0x0401f859,
-	0x59c40805, 0x8c040d0a, 0x0402000b, 0x8c040d0c,
-	0x04020006, 0x8c040d0e, 0x04000009, 0x4a035017,
-	0x00000001, 0x0401f006, 0x4a035017, 0x00000000,
-	0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
-	0x4a038808, 0x00000004, 0x0401f846, 0x59c40805,
-	0x8c040d0a, 0x04020010, 0x8c040d08, 0x0402000b,
-	0x8c040d0c, 0x04020006, 0x8c040d0e, 0x0400000c,
-	0x4a035017, 0x00000001, 0x0401f009, 0x4a035017,
-	0x00000000, 0x0401f006, 0x4a035017, 0x00000003,
-	0x0401f003, 0x4a035017, 0x00000002, 0x1c01f000,
-	0x0401f91d, 0x02020800, 0x00100615, 0x59a80805,
-	0x8c040d0c, 0x04000015, 0x84040d0c, 0x48075005,
-	0x4a038805, 0x00000010, 0x0201f800, 0x001019a4,
-	0x59c40005, 0x8c000508, 0x04000008, 0x4a038808,
-	0x00000008, 0x4a035033, 0x00000001, 0x4202d800,
-	0x00000001, 0x0401f01a, 0x59c40006, 0x84000548,
-	0x48038806, 0x0401f016, 0x59a80017, 0x82000580,
-	0x00000001, 0x0400000c, 0x59a80017, 0x82000580,
-	0x00000005, 0x0402000c, 0x42000000, 0x0010b642,
-	0x0201f800, 0x0010a86e, 0x4a035017, 0x00000008,
-	0x0401f007, 0x42000000, 0x0010b642, 0x0201f800,
-	0x0010a86e, 0x4a035017, 0x00000004, 0x1c01f000,
-	0x4803c856, 0x4c040000, 0x4c080000, 0x42000800,
-	0x00000064, 0x42001000, 0x00104d2c, 0x0201f800,
-	0x00105db2, 0x5c001000, 0x5c000800, 0x1c01f000,
-	0x4803c856, 0x4c040000, 0x0201f800, 0x0010698c,
-	0x4df00000, 0x0201f800, 0x00106b71, 0x5c03e000,
-	0x02000800, 0x00106982, 0x0401ffba, 0x5c000800,
-	0x1c01f000, 0x4803c856, 0x4c040000, 0x4c080000,
-	0x0201f800, 0x0010698c, 0x4df00000, 0x0201f800,
-	0x00106b71, 0x5c03e000, 0x02000800, 0x00106982,
-	0x59c40006, 0x84000500, 0x48038806, 0x0201f800,
-	0x00106c32, 0x497b8880, 0x0201f800, 0x0010a7e7,
-	0x0201f800, 0x0010a7f5, 0x0201f800, 0x00101886,
-	0x4a03504c, 0x00000004, 0x4202d800, 0x00000004,
-	0x4a038805, 0x00000001, 0x42001000, 0x00104d2c,
-	0x0201f800, 0x00105dbd, 0x0201f800, 0x0010071a,
-	0x0401f8bf, 0x04000006, 0x42006000, 0xfeffffff,
-	0x41786800, 0x0201f800, 0x001040ad, 0x0201f800,
-	0x0010048c, 0x42000000, 0x00000001, 0x0201f800,
-	0x001015fa, 0x5c001000, 0x5c000800, 0x1c01f000,
-	0x59c40008, 0x8c000508, 0x04020007, 0x4a038808,
-	0x00000010, 0x4201d000, 0x00001388, 0x0201f800,
-	0x00105dd2, 0x1c01f000, 0x4c040000, 0x59a80833,
-	0x82040580, 0x00000000, 0x0400000b, 0x82040580,
-	0x00000001, 0x0400000b, 0x82040580, 0x00000002,
-	0x0400000b, 0x82040580, 0x00000003, 0x0400000b,
-	0x0401f055, 0x4a035017, 0x00000000, 0x0401f009,
-	0x4a035017, 0x00000004, 0x0401f006, 0x4a035017,
-	0x00000001, 0x0401f003, 0x4a035017, 0x00000007,
-	0x497b8880, 0x4a038893, 0x00000001, 0x41780000,
-	0x0201f800, 0x00101670, 0x0201f800, 0x00106c32,
-	0x836c0d80, 0x00000004, 0x04000008, 0x59c40006,
-	0x82000500, 0xffffff0f, 0x82000540, 0x04000001,
-	0x48038806, 0x0401f007, 0x59c40006, 0x82000500,
-	0xffffff0f, 0x82000540, 0x04000000, 0x48038806,
-	0x0401f873, 0x04020005, 0x59c40806, 0x82040d00,
-	0xfbffff0f, 0x48078806, 0x59c40005, 0x8c000534,
-	0x04020033, 0x42006000, 0xfc18ffff, 0x42006800,
-	0x01000000, 0x0201f800, 0x001040ad, 0x0201f800,
-	0x001019a4, 0x59c408a4, 0x82040d00, 0x0000000f,
-	0x82040d80, 0x0000000c, 0x040208a9, 0x0401f85c,
-	0x04000006, 0x42006000, 0xfeffffff, 0x41786800,
-	0x0201f800, 0x001040ad, 0x836c0d80, 0x00000004,
-	0x0400000f, 0x0401f85a, 0x04020008, 0x59940005,
-	0x82000580, 0x00103f37, 0x04020004, 0x59940004,
-	0x800001c0, 0x04020006, 0x59a8084d, 0x42001000,
-	0x00104d39, 0x0201f800, 0x00105da7, 0x4a035033,
-	0x00000004, 0x0401fe33, 0x0401f841, 0x04020008,
-	0x59c408a4, 0x82040d00, 0x0000000f, 0x82040580,
-	0x0000000c, 0x02020800, 0x00100615, 0x5c000800,
-	0x1c01f000, 0x4803c856, 0x4c000000, 0x0201f800,
-	0x00105de2, 0x4a035010, 0x00ffffff, 0x497b5032,
-	0x59a8002a, 0x82000500, 0xffff0000, 0x4803502a,
-	0x497b8880, 0x497b8893, 0x41780000, 0x0201f800,
-	0x00101670, 0x59c40001, 0x82000500, 0xfffffcff,
-	0x48038801, 0x42006000, 0xfc18ffff, 0x41786800,
-	0x0201f800, 0x001040ad, 0x4a038808, 0x00000000,
-	0x5c000000, 0x800001c0, 0x02020800, 0x00103f37,
-	0x4a038805, 0x040000f0, 0x59c40006, 0x82000500,
-	0xffffffcf, 0x82000540, 0x440000c1, 0x48038806,
-	0x1c01f000, 0x4c5c0000, 0x59a8b832, 0x825cbd80,
-	0x0000aaaa, 0x5c00b800, 0x1c01f000, 0x4c5c0000,
-	0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80,
-	0x00000000, 0x5c00b800, 0x1c01f000, 0x4c5c0000,
-	0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80,
-	0x00000010, 0x5c00b800, 0x1c01f000, 0x4c5c0000,
-	0x599cb818, 0x825cbd00, 0x00000030, 0x825cbd80,
-	0x00000020, 0x5c00b800, 0x1c01f000, 0x59a80005,
-	0x4803c857, 0x82000d00, 0x00000013, 0x04000024,
-	0x599c1017, 0x4d3c0000, 0x82000500, 0x00000011,
-	0x04000006, 0x417a7800, 0x0201f800, 0x0010393e,
-	0x0402000a, 0x0401f012, 0x42027800, 0x00000008,
-	0x0201f800, 0x0010393e, 0x0400000d, 0x42003000,
-	0x00000003, 0x0401f003, 0x42003000, 0x00000004,
-	0x42028000, 0x0000000e, 0x0201f800, 0x0010a25b,
-	0x599c1017, 0x8c08150a, 0x04020007, 0x42028000,
-	0x00000004, 0x0201f800, 0x00101d90, 0x80000580,
-	0x0401f80d, 0x5c027800, 0x0401f00a, 0x0201f800,
-	0x0010393e, 0x04000007, 0x42028000, 0x0000000f,
-	0x42003000, 0x00000001, 0x0201f800, 0x0010a25b,
-	0x1c01f000, 0x59a80005, 0x04000004, 0x82000540,
-	0x00000010, 0x0401f003, 0x82000500, 0xffffffef,
-	0x48035005, 0x4803c857, 0x1c01f000, 0x4803c856,
-	0x4c580000, 0x42000000, 0x0010b6ca, 0x0201f800,
-	0x0010a86e, 0x42000800, 0x0010bef0, 0x59c40003,
-	0x44000800, 0x59c40004, 0x48000801, 0x59c4000b,
-	0x48000802, 0x59c4008e, 0x48000803, 0x59c4008f,
-	0x48000804, 0x59c40090, 0x48000805, 0x59c40091,
-	0x48000806, 0x59c40092, 0x48000807, 0x59c40093,
-	0x48000808, 0x59c40099, 0x48000809, 0x59c4009e,
-	0x4800080a, 0x59c400aa, 0x4800080b, 0x59c400af,
-	0x4800080c, 0x59c400b2, 0x4800080d, 0x59c400b1,
-	0x4800080e, 0x82040c00, 0x0000000f, 0x41c41800,
-	0x4200b000, 0x00000030, 0x580c0050, 0x44000800,
-	0x80040800, 0x800c1800, 0x8058b040, 0x040207fb,
-	0x41c41800, 0x4200b000, 0x00000020, 0x580c0010,
-	0x44000800, 0x80040800, 0x800c1800, 0x8058b040,
-	0x040207fb, 0x497b8830, 0x4200b000, 0x00000040,
-	0x59c40031, 0x44000800, 0x80040800, 0x8058b040,
-	0x040207fc, 0x497b88ac, 0x4200b000, 0x00000010,
-	0x59c400ad, 0x44000800, 0x80040800, 0x8058b040,
-	0x040207fc, 0x59c41001, 0x4c080000, 0x8408150c,
-	0x480b8801, 0x4a0370e4, 0x00000300, 0x4a0370e5,
-	0xb0000000, 0x42000800, 0x00000800, 0x80040840,
-	0x02000800, 0x00100615, 0x59b800e5, 0x8c000538,
-	0x040207fb, 0x4a0370e4, 0x00000200, 0x42006000,
-	0xffffffff, 0x42006800, 0x80000000, 0x0201f800,
-	0x001040ad, 0x4a038807, 0x00000001, 0x497b8807,
-	0x4a038808, 0x00000010, 0x42006000, 0xfcf8ffff,
-	0x42006800, 0x01000000, 0x0201f800, 0x001040ad,
-	0x5c001000, 0x480b8801, 0x42000800, 0x0010bef0,
-	0x50040000, 0x48038803, 0x58040001, 0x48038804,
-	0x58040002, 0x4803880b, 0x58040003, 0x4803888e,
-	0x58040004, 0x4803888f, 0x58040005, 0x48038890,
-	0x58040006, 0x48038891, 0x58040007, 0x48038892,
-	0x58040008, 0x48038893, 0x58040009, 0x48038899,
-	0x5804000a, 0x4803889e, 0x5804000b, 0x480388aa,
-	0x5804000c, 0x480388af, 0x5804000d, 0x480388b2,
-	0x5804000e, 0x480388b1, 0x82040c00, 0x0000000f,
-	0x41c41800, 0x4200b000, 0x00000030, 0x50040000,
-	0x48001850, 0x80040800, 0x800c1800, 0x8058b040,
-	0x040207fb, 0x41c41800, 0x4200b000, 0x00000020,
-	0x50040000, 0x48001810, 0x80040800, 0x800c1800,
-	0x8058b040, 0x040207fb, 0x497b8830, 0x4200b000,
-	0x00000040, 0x50040000, 0x48038831, 0x80040800,
-	0x8058b040, 0x040207fc, 0x497b88ac, 0x4200b000,
-	0x00000010, 0x50040000, 0x480388ad, 0x80040800,
-	0x8058b040, 0x040207fc, 0x497b8880, 0x41780000,
-	0x0201f800, 0x00101670, 0x59c408a4, 0x82040d00,
-	0x0000000f, 0x82040580, 0x0000000c, 0x02020800,
-	0x00100615, 0x4a038805, 0x04000000, 0x5c00b000,
-	0x1c01f000, 0x4803c856, 0x4c580000, 0x4ce80000,
-	0x42000000, 0x0010b643, 0x0201f800, 0x0010a86e,
-	0x59c41008, 0x4c080000, 0x82080500, 0xffffff7f,
-	0x48038808, 0x59c40004, 0x82000500, 0x00003e02,
-	0x04000005, 0x4201d000, 0x00000014, 0x0201f800,
-	0x00105dd2, 0x59c40006, 0x82000500, 0xffffff0f,
-	0x48038806, 0x4a038805, 0x00000010, 0x4a038808,
-	0x00000004, 0x4200b000, 0x00000065, 0x59c40005,
-	0x8c000508, 0x04020012, 0x4201d000, 0x000003e8,
-	0x0201f800, 0x00105dd2, 0x8058b040, 0x040207f8,
-	0x0201f800, 0x00106c32, 0x4a038808, 0x00000008,
-	0x4a035033, 0x00000001, 0x4202d800, 0x00000001,
-	0x82000540, 0x00000001, 0x0401f030, 0x0201f800,
-	0x00100b29, 0x42000000, 0x0010b6a7, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x00100f42, 0x497b8880,
-	0x59a8002a, 0x82000500, 0x0000ffff, 0x4c000000,
-	0x0201f800, 0x00101670, 0x5c000000, 0x48038880,
-	0x4a038808, 0x00000000, 0x4200b000, 0x00000065,
-	0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4,
-	0x42000800, 0x000000f0, 0x59c40005, 0x80040d00,
-	0x04000008, 0x4201d000, 0x000003e8, 0x0201f800,
-	0x00105dd2, 0x8058b040, 0x040207f2, 0x0401f7d1,
-	0x59c40006, 0x82000540, 0x000000f0, 0x48038806,
-	0x59a8001e, 0x80000540, 0x04020002, 0x80000000,
-	0x48038893, 0x80000580, 0x5c001000, 0x4df00000,
-	0x0201f800, 0x001019ca, 0x5c03e000, 0x480b8808,
-	0x5c01d000, 0x5c00b000, 0x1c01f000, 0x4803c856,
-	0x4c580000, 0x4ce80000, 0x59c41008, 0x82080500,
-	0xffffff7f, 0x48038808, 0x4c080000, 0x59c40004,
-	0x82000500, 0x00003e02, 0x04000005, 0x4201d000,
-	0x00000014, 0x0201f800, 0x00105dd2, 0x0201f800,
-	0x00100b29, 0x42000000, 0x0010b6a8, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x00100f42, 0x4a038808,
-	0x00000002, 0x80000580, 0x48038880, 0x48038893,
-	0x0201f800, 0x00101670, 0x4200b000, 0x00000384,
-	0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4,
-	0x42000800, 0x000000f0, 0x59c40005, 0x80040d00,
-	0x04000015, 0x82000500, 0x000000d0, 0x04020012,
-	0x4201d000, 0x00000067, 0x0201f800, 0x00105dd2,
-	0x8058b040, 0x040207ef, 0x0201f800, 0x00106c32,
-	0x4a038808, 0x00000008, 0x4a035033, 0x00000001,
-	0x4202d800, 0x00000001, 0x82000540, 0x00000001,
-	0x0401f010, 0x497b8880, 0x59a8001e, 0x80000540,
-	0x04020002, 0x80000000, 0x48038893, 0x59a8002a,
-	0x82000500, 0x0000ffff, 0x4c000000, 0x0201f800,
-	0x00101670, 0x5c000000, 0x48038880, 0x80000580,
-	0x5c001000, 0x4df00000, 0x0201f800, 0x001019ca,
-	0x5c03e000, 0x480b8808, 0x5c01d000, 0x5c00b000,
-	0x1c01f000, 0x4803c856, 0x59c40004, 0x82000500,
-	0x00003e02, 0x0400000a, 0x0201f800, 0x00106c32,
-	0x4a038808, 0x00000008, 0x4a035033, 0x00000001,
-	0x4202d800, 0x00000001, 0x0401f052, 0x0201f800,
-	0x00100b29, 0x42000000, 0x0010b6a9, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x00100f42, 0x59c40006,
-	0x84000508, 0x48038806, 0x4a038805, 0x00000010,
-	0x59a80805, 0x84040d4c, 0x48075005, 0x42000800,
-	0x00000064, 0x42001000, 0x00104d2c, 0x0201f800,
-	0x00105da7, 0x4a038808, 0x00000000, 0x497b8880,
-	0x4a038805, 0x000000f0, 0x0201f800, 0x001019a4,
-	0x42000800, 0x000000f0, 0x59c40005, 0x80040d00,
-	0x0400000e, 0x82000500, 0x000000e0, 0x0402000b,
-	0x4201d000, 0x000003e8, 0x0201f800, 0x00105dd2,
-	0x0201f800, 0x00105c81, 0x59940004, 0x80000540,
-	0x040207ec, 0x0401f023, 0x4c080000, 0x42001000,
-	0x00104d39, 0x0201f800, 0x00105cc9, 0x42001000,
-	0x00104d2c, 0x0201f800, 0x00105dbd, 0x5c001000,
-	0x497b8880, 0x59a8001e, 0x80000540, 0x04020002,
-	0x80000000, 0x48038893, 0x59a8002a, 0x82000500,
-	0x0000ffff, 0x4c000000, 0x0201f800, 0x00101670,
-	0x5c000000, 0x48038880, 0x59a80805, 0x84040d0c,
-	0x48075005, 0x59c40006, 0x84000548, 0x48038806,
-	0x0201f800, 0x001019ca, 0x4a038808, 0x00000080,
-	0x1c01f000, 0x4803c856, 0x4d400000, 0x4d3c0000,
-	0x0201f800, 0x00106c32, 0x0201f800, 0x0010a95a,
-	0x04020024, 0x599c1017, 0x59a80805, 0x8c040d00,
-	0x0402000c, 0x8c08151a, 0x0400001e, 0x84040d42,
-	0x48075005, 0x42028000, 0x00000004, 0x42027800,
-	0x00000008, 0x8c081508, 0x04020007, 0x0401f011,
-	0x42028000, 0x00000004, 0x417a7800, 0x8c081508,
-	0x0400000c, 0x4d400000, 0x42028000, 0x0000000e,
-	0x42028800, 0x0000ffff, 0x0201f800, 0x0010a258,
-	0x5c028000, 0x599c0817, 0x8c040d0a, 0x04020005,
-	0x4943c857, 0x493fc857, 0x0201f800, 0x00101d90,
-	0x497b8880, 0x4202d800, 0x00000001, 0x0401fcff,
-	0x5c027800, 0x5c028000, 0x1c01f000, 0x0201f800,
-	0x00100b29, 0x42000000, 0x0010b6aa, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x00100f42, 0x42000000,
-	0x00000001, 0x0201f800, 0x00101670, 0x4a038880,
-	0x00000001, 0x0201f000, 0x001019ca, 0x4202e000,
-	0x00000000, 0x4a033015, 0x00000001, 0x497b301d,
-	0x497b3006, 0x4a03b004, 0x60000001, 0x59d80005,
-	0x4a03b004, 0x90000001, 0x4a03a804, 0x60000001,
-	0x59d40005, 0x4a03a804, 0x90000001, 0x0201f000,
-	0x00105667, 0x4a03c825, 0x00000004, 0x4a03c827,
-	0x00000004, 0x599c0409, 0x80000d40, 0x04000020,
-	0x599c0407, 0x80000540, 0x04000007, 0x800000cc,
-	0x599c100b, 0x80080400, 0x4803b000, 0x497bb002,
-	0x59d80001, 0x599c000b, 0x4803b000, 0x599c000c,
-	0x4803b001, 0x599c0407, 0x80000540, 0x04020002,
-	0x497bb002, 0x599c0c09, 0x82040540, 0x00400000,
-	0x4803b003, 0x4a03b009, 0x00000004, 0x4a03b004,
-	0x10000001, 0x59e00803, 0x82040d00, 0xfffffeff,
-	0x82040d40, 0x00008000, 0x4807c003, 0x599c040a,
-	0x80000540, 0x04000020, 0x599c0408, 0x80000540,
-	0x04000007, 0x800000cc, 0x599c100f, 0x80080400,
-	0x4803a800, 0x497ba802, 0x59d40001, 0x599c000f,
-	0x4803a800, 0x599c0010, 0x4803a801, 0x599c0408,
-	0x80000540, 0x04020002, 0x497ba802, 0x599c0c0a,
-	0x82040540, 0x00400000, 0x4803a803, 0x4a03a809,
-	0x00000004, 0x4a03a804, 0x10000001, 0x59e00803,
-	0x82040d00, 0xfffffbff, 0x82040d40, 0x00008000,
-	0x4807c003, 0x800409c0, 0x04000007, 0x4202e000,
-	0x00000001, 0x0200b800, 0x00020685, 0x0200f000,
-	0x0002069a, 0x1c01f000, 0x0201f800, 0x00100615,
-	0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
-	0x59981005, 0x800811c0, 0x0400001e, 0x58080005,
-	0x82000d00, 0x43018780, 0x02020000, 0x0010552a,
-	0x8c000508, 0x04000015, 0x580a5808, 0x592c0204,
-	0x497a5800, 0x497a5801, 0x82000500, 0x000000ff,
-	0x82000c80, 0x0000004b, 0x0402100b, 0x0c01f80f,
-	0x5c03e000, 0x83700580, 0x00000003, 0x040007e6,
-	0x0200f800, 0x0002069a, 0x0200b000, 0x00020685,
-	0x1c01f000, 0x0401f850, 0x5c03e000, 0x0401f7f9,
-	0x0401f8ee, 0x0401f7fd, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105171, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x001051f9, 0x00105161, 0x00105161, 0x00105171,
-	0x00105171, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x492fc857, 0x42000000, 0x0010b65d,
-	0x0201f800, 0x0010a86e, 0x42000000, 0x00000400,
-	0x0401f019, 0x492fc857, 0x42000000, 0x0010b65c,
-	0x0201f800, 0x0010a86e, 0x42000000, 0x00001000,
-	0x0401f011, 0x492fc857, 0x42000000, 0x0010b65b,
-	0x0201f800, 0x0010a86e, 0x42000000, 0x00002000,
-	0x0401f009, 0x492fc857, 0x42000000, 0x0010b65e,
-	0x0201f800, 0x0010a86e, 0x42000000, 0x00000800,
-	0x0401f001, 0x4803c857, 0x4202e000, 0x00000001,
-	0x592c0c04, 0x82040d00, 0xffff80ff, 0x80040540,
-	0x48025c04, 0x0201f000, 0x00020381, 0x592c0204,
-	0x492fc857, 0x80000110, 0x040007db, 0x80000040,
-	0x04000035, 0x48033002, 0x492f3003, 0x492f3004,
-	0x4a033008, 0x001051c5, 0x4202e000, 0x00000003,
-	0x1c01f000, 0x592c0204, 0x492fc857, 0x80000110,
-	0x040007cd, 0x80000040, 0x04000043, 0x48033002,
-	0x492f3003, 0x492f3004, 0x4a033008, 0x001051e1,
-	0x4202e000, 0x00000003, 0x1c01f000, 0x492fc857,
-	0x0201f800, 0x0010a95a, 0x02020000, 0x0002060c,
-	0x492fc857, 0x592e8a06, 0x83440c80, 0x000007f0,
-	0x0402100b, 0x83440400, 0x0010aa00, 0x50000000,
-	0x80026d40, 0x04000006, 0x4937c857, 0x59340200,
-	0x8c00050e, 0x02020000, 0x0002060c, 0x42028000,
-	0x00000028, 0x41780800, 0x417a6000, 0x0201f800,
-	0x00104bee, 0x0201f800, 0x00108f7d, 0x0201f000,
-	0x00020381, 0x592c0a0a, 0x8c040d02, 0x04020016,
-	0x59a80021, 0x492fc857, 0x80000540, 0x0402000f,
-	0x592c0207, 0x80000540, 0x04000005, 0x0201f800,
-	0x00104156, 0x04020004, 0x1c01f000, 0x42000000,
-	0x00000000, 0x592c0a06, 0x48065c06, 0x48025a06,
-	0x0201f000, 0x00020381, 0x42000000, 0x00000028,
-	0x0401f7f9, 0x42000800, 0x00000009, 0x0201f000,
-	0x001063a9, 0x592c0208, 0x492fc857, 0x82000c80,
-	0x0000199a, 0x04021794, 0x592c0408, 0x80000540,
-	0x04020791, 0x59a80821, 0x800409c0, 0x04020009,
-	0x592c0207, 0x80000540, 0x0400078b, 0x497a5a06,
-	0x0201f800, 0x001041b5, 0x04020004, 0x1c01f000,
-	0x42000000, 0x00000028, 0x48025a06, 0x0201f000,
-	0x00020381, 0x59980804, 0x59980002, 0x48065800,
-	0x492c0801, 0x492f3004, 0x80000040, 0x48033002,
-	0x04000002, 0x1c01f000, 0x599a5803, 0x59980008,
-	0x4202e000, 0x00000001, 0x0801f000, 0x592e8a06,
-	0x592c0406, 0x4803c856, 0x82000500, 0x000000ff,
-	0x4200b800, 0x00000001, 0x82000d80, 0x00000001,
-	0x04000015, 0x417a8800, 0x4200b800, 0x000007f0,
-	0x82000d80, 0x00000002, 0x0400000f, 0x80000540,
-	0x02020000, 0x00020381, 0x592e8a06, 0x0201f800,
-	0x00020267, 0x02020000, 0x00020381, 0x592e9008,
-	0x592e9809, 0x0201f800, 0x00104567, 0x0201f000,
-	0x00020381, 0x59a80805, 0x84040d00, 0x48075005,
-	0x0201f800, 0x00020267, 0x02000800, 0x0010467a,
-	0x81468800, 0x805cb840, 0x040207fa, 0x0201f000,
-	0x00020381, 0x592c0a08, 0x4807c857, 0x82040580,
-	0x0000000e, 0x04000045, 0x82040580, 0x00000046,
-	0x04000046, 0x82040580, 0x00000045, 0x04000020,
-	0x82040580, 0x00000029, 0x04000010, 0x82040580,
-	0x0000002a, 0x04000009, 0x82040580, 0x0000000f,
-	0x04000200, 0x82040580, 0x0000002e, 0x040001fd,
-	0x4807c856, 0x0401f1f6, 0x59a80805, 0x84040d04,
-	0x48075005, 0x0401f1f7, 0x592e8a06, 0x0201f800,
-	0x00020267, 0x040201f3, 0x59340200, 0x84000518,
-	0x48026a00, 0x592e6009, 0x4933c857, 0x83300580,
-	0xffffffff, 0x0402002a, 0x0401f1ea, 0x592c1407,
-	0x480bc857, 0x0201f800, 0x001091d9, 0x411e6000,
-	0x04020003, 0x4803c856, 0x0401f1dd, 0x592e3809,
-	0x591c1414, 0x84081516, 0x84081554, 0x480a3c14,
-	0x4a026403, 0x0000003a, 0x592c040b, 0x80000540,
-	0x04000007, 0x4a026403, 0x0000003b, 0x592c020c,
-	0x4802641a, 0x592c040c, 0x4802621a, 0x4a026203,
-	0x00000001, 0x42000800, 0x80000040, 0x0201f800,
-	0x00020855, 0x0401f1cb, 0x59a80068, 0x84000510,
-	0x48035068, 0x0401f1c7, 0x592c1207, 0x8c081500,
-	0x040201c4, 0x592e8a06, 0x592e6009, 0x0201f800,
-	0x001091e3, 0x04020003, 0x4803c856, 0x0401f1b8,
-	0x59300c06, 0x82040580, 0x00000004, 0x04000003,
-	0x4803c856, 0x0401f1b2, 0x59300a03, 0x82040580,
-	0x00000007, 0x04000003, 0x4803c856, 0x0401f1ac,
-	0x59300c03, 0x82040580, 0x00000001, 0x04000025,
-	0x82040580, 0x00000003, 0x0400001a, 0x82040580,
-	0x00000006, 0x04000024, 0x82040580, 0x00000008,
-	0x04000019, 0x82040580, 0x0000000a, 0x0400000a,
-	0x82040580, 0x0000000c, 0x04000004, 0x82040580,
-	0x0000002e, 0x0402001c, 0x42000800, 0x00000009,
-	0x0401f017, 0x59326809, 0x0201f800, 0x0010484b,
-	0x04020015, 0x42000800, 0x00000005, 0x0401f010,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406,
-	0x00000001, 0x42000800, 0x00000003, 0x0401f008,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x4a026406,
-	0x00000001, 0x42000800, 0x0000000b, 0x0201f800,
-	0x001043c7, 0x4a026203, 0x00000001, 0x0201f800,
-	0x00106470, 0x0401f17b, 0x40000800, 0x58040000,
-	0x80000540, 0x040207fd, 0x492c0800, 0x1c01f000,
-	0x492fc857, 0x59300c06, 0x82040580, 0x00000006,
-	0x04020094, 0x0201f800, 0x00104836, 0x04020005,
-	0x59340200, 0x8c00051a, 0x02000000, 0x00020667,
-	0x59340200, 0x8c00050e, 0x0400008a, 0x59300203,
-	0x42027800, 0x00000001, 0x82000580, 0x00000007,
-	0x02020000, 0x00020667, 0x4a026203, 0x00000002,
-	0x0201f000, 0x00020667, 0x42028000, 0x00000002,
-	0x4a026206, 0x00000014, 0x4d2c0000, 0x0201f800,
-	0x00109fc0, 0x5c025800, 0x59300c06, 0x4807c857,
-	0x82040580, 0x00000007, 0x04020063, 0x492fc857,
-	0x4a025a06, 0x00000001, 0x0201f000, 0x00020381,
-	0x592c240a, 0x492fc857, 0x4813c857, 0x8c10251c,
-	0x04020016, 0x8c10251a, 0x04000003, 0x8c10250a,
-	0x04000069, 0x59340a00, 0x8c040d0e, 0x04000003,
-	0x8c10251e, 0x04000064, 0x0201f800, 0x00020892,
-	0x0400006b, 0x592c240a, 0x49366009, 0x49325809,
-	0x4a026406, 0x00000006, 0x4a026203, 0x00000007,
-	0x0201f000, 0x00020663, 0x592c0a0c, 0x5934000f,
-	0x41784000, 0x80001540, 0x0400006d, 0x58080204,
-	0x82000500, 0x000000ff, 0x82000580, 0x00000012,
-	0x04020004, 0x5808020c, 0x80040580, 0x04000004,
-	0x58080000, 0x40084000, 0x0401f7f3, 0x58080000,
-	0x49781000, 0x802041c0, 0x04000006, 0x48004000,
-	0x80000540, 0x04020007, 0x48226810, 0x0401f005,
-	0x4802680f, 0x80000540, 0x04020002, 0x497a6810,
-	0x4d2c0000, 0x400a5800, 0x4a025a06, 0x00000002,
-	0x0201f800, 0x00020381, 0x5c025800, 0x0401f7bc,
-	0x592c040a, 0x8c00051c, 0x04000016, 0x592c0206,
-	0x82000580, 0x0000ffff, 0x04020012, 0x592e6009,
-	0x83300580, 0xffffffff, 0x040007b1, 0x83300480,
-	0x0010cfc0, 0x04001010, 0x59a8000b, 0x81300480,
-	0x0402100d, 0x59300008, 0x800001c0, 0x04020005,
-	0x59300203, 0x82000580, 0x00000007, 0x04000797,
-	0x492fc857, 0x4a025a06, 0x00000029, 0x0201f000,
-	0x00020381, 0x492fc857, 0x4a025a06, 0x00000008,
-	0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06,
-	0x00000045, 0x0201f000, 0x00020381, 0x492fc857,
-	0x4a025a06, 0x0000002a, 0x0201f000, 0x00020381,
-	0x492fc857, 0x4a025a06, 0x00000028, 0x0201f000,
-	0x00020381, 0x492fc857, 0x4a025a06, 0x00000006,
-	0x0201f000, 0x00020381, 0x492fc857, 0x4a025a06,
-	0x0000000e, 0x0201f000, 0x00020381, 0x59340010,
-	0x492e6810, 0x492fc857, 0x80000d40, 0x04000003,
-	0x492c0800, 0x1c01f000, 0x5934040b, 0x492e680f,
-	0x492fc857, 0x4803c857, 0x80000540, 0x04020003,
-	0x4a026a03, 0x00000001, 0x1c01f000, 0x59a8000e,
-	0x81640480, 0x0402176e, 0x42026000, 0x0010cfc0,
-	0x59300009, 0x81340580, 0x04020004, 0x59300202,
-	0x80040580, 0x04000759, 0x83326400, 0x00000024,
-	0x41580000, 0x81300480, 0x040017f6, 0x0401f760,
-	0x492fc857, 0x592c0407, 0x82000c80, 0x0000199a,
-	0x040215dd, 0x592c0204, 0x80000112, 0x040205ca,
-	0x592e8a06, 0x0201f800, 0x00020267, 0x04020059,
-	0x0201f800, 0x00104836, 0x04020059, 0x592e780a,
-	0x493fc857, 0x8d3e7d3e, 0x04020007, 0x59a80021,
-	0x80000540, 0x0402004f, 0x0201f800, 0x00104686,
-	0x040005c9, 0x833c1d00, 0x0000001f, 0x040005c6,
-	0x592c0207, 0x82000c80, 0x00001000, 0x040215c2,
-	0x800000c2, 0x800008c4, 0x8005d400, 0x592e9008,
-	0x592e9809, 0x5934080d, 0x800409c0, 0x0402002e,
-	0x833c1d00, 0x0000001f, 0x81780040, 0x80000000,
-	0x800c1902, 0x040217fe, 0x040205b3, 0x0c01f001,
-	0x001053cd, 0x001053d0, 0x001053dd, 0x001053e0,
-	0x001053e3, 0x0201f800, 0x00108dfb, 0x0401f01a,
-	0x0201f800, 0x00104659, 0x04000027, 0x80e9d1c0,
-	0x02020800, 0x00105ce7, 0x42028000, 0x00000005,
-	0x417a9000, 0x417a9800, 0x0201f800, 0x00108e0b,
-	0x0401f00d, 0x42027000, 0x0000004d, 0x0401f006,
-	0x42027000, 0x0000004e, 0x0401f003, 0x42027000,
-	0x00000052, 0x0201f800, 0x0010451d, 0x02020800,
-	0x00108e3b, 0x04000010, 0x8d3e7d3e, 0x04020017,
-	0x1c01f000, 0x58040002, 0x80000540, 0x04020007,
-	0x4d3c0000, 0x40067800, 0x0201f800, 0x00104639,
-	0x5c027800, 0x040207cb, 0x4a025a06, 0x00000030,
-	0x0401f00d, 0x4a025a06, 0x0000002c, 0x0401f00a,
-	0x4a025a06, 0x00000028, 0x0401f007, 0x4a025a06,
-	0x00000029, 0x0401f004, 0x497a5c09, 0x4a025a06,
-	0x00000000, 0x4a025a04, 0x00000103, 0x0201f000,
-	0x00020381, 0x492fc857, 0x592c0204, 0x80000110,
-	0x80000040, 0x04000002, 0x0401f55b, 0x592c0207,
-	0x82000500, 0x000003ff, 0x48025a07, 0x8c000506,
-	0x04000004, 0x82000500, 0x00000070, 0x04020004,
-	0x59a80821, 0x800409c0, 0x04020018, 0x4a025a06,
-	0x0000dead, 0x592c0408, 0x82000500, 0x0000f0ff,
-	0x48025c08, 0x0201f800, 0x001041e4, 0x04020002,
-	0x1c01f000, 0x49425a06, 0x8058b1c0, 0x04000009,
-	0x0201f800, 0x00109328, 0x0401f80f, 0x44042800,
-	0x82580580, 0x00000002, 0x04020002, 0x48082801,
-	0x0201f000, 0x00020381, 0x42028000, 0x00000031,
-	0x42000800, 0x00000001, 0x4200b000, 0x00000001,
-	0x0401f7ed, 0x592c0408, 0x80000118, 0x832c2c00,
-	0x00000009, 0x80142c00, 0x1c01f000, 0x492fc857,
-	0x4a025a08, 0x00000006, 0x0201f000, 0x00020381,
-	0x492fc857, 0x4a025a08, 0x00000001, 0x0201f000,
-	0x00020381, 0x492fc857, 0x592c040a, 0x82000500,
-	0x00000003, 0x04000020, 0x0201f800, 0x00020892,
-	0x04000021, 0x592c0204, 0x492e6008, 0x82000500,
-	0x000000ff, 0x82000580, 0x00000045, 0x0400000e,
-	0x592c000b, 0x0201f800, 0x001059b9, 0x02000800,
-	0x00020267, 0x04020018, 0x42027000, 0x00000041,
-	0x49366009, 0x4a026406, 0x00000001, 0x0201f000,
-	0x000208d8, 0x59300015, 0x8400055e, 0x48026015,
-	0x42026800, 0x0010b320, 0x42027000, 0x00000040,
-	0x0401f7f4, 0x4a025a06, 0x00000101, 0x0201f000,
-	0x00020381, 0x4a025a06, 0x0000002c, 0x0201f000,
-	0x00020381, 0x4a025a06, 0x00000028, 0x0201f800,
-	0x00020381, 0x0201f000, 0x000208b4, 0x492fc857,
-	0x0201f800, 0x0010601a, 0x0400000b, 0x592c0204,
-	0x80000110, 0x80000040, 0x040204e7, 0x592c0c06,
-	0x800409c0, 0x04000009, 0x42000000, 0x00000102,
-	0x0401f003, 0x42000000, 0x00000104, 0x48025a06,
-	0x0201f000, 0x00020381, 0x592c0c07, 0x800409c0,
-	0x04000024, 0x82040480, 0x00000005, 0x04021021,
-	0x4c040000, 0x80040800, 0x0201f800, 0x0010603f,
-	0x5c001000, 0x04020018, 0x832c0400, 0x00000008,
-	0x4000a000, 0x0201f800, 0x00106068, 0x04020012,
-	0x592c1207, 0x82cc0580, 0x0010b30a, 0x04020009,
-	0x58c80c0b, 0x84040d00, 0x84040d02, 0x8c081500,
-	0x04000002, 0x84040d5e, 0x4805940b, 0x0401f001,
-	0x42000000, 0x00000000, 0x48025a06, 0x0201f000,
-	0x00020381, 0x42000000, 0x00000103, 0x0401f7fb,
-	0x42000000, 0x00000102, 0x0401f7f8, 0x492fc857,
-	0x592e7c06, 0x833c0500, 0xfffffffe, 0x04020043,
-	0x592c4007, 0x42026000, 0x0010cfc0, 0x41581800,
-	0x400c0000, 0x81300480, 0x04021023, 0x59300203,
-	0x82000580, 0x00000000, 0x04000007, 0x59300008,
-	0x80000d40, 0x04000004, 0x58040005, 0x80200580,
-	0x04000004, 0x83326400, 0x00000024, 0x0401f7f1,
-	0x58040204, 0x82000500, 0x000000ff, 0x82000d80,
-	0x00000053, 0x04000007, 0x82000d80, 0x00000048,
-	0x04000004, 0x82000580, 0x00000018, 0x04020023,
-	0x4d2c0000, 0x0201f800, 0x00108997, 0x5c025800,
-	0x0400001e, 0x4a025a06, 0x00000000, 0x0201f000,
-	0x00020381, 0x592e8a06, 0x83440480, 0x000007f0,
-	0x04021016, 0x83440400, 0x0010aa00, 0x50000000,
-	0x80026d40, 0x04000011, 0x4d2c0000, 0x0201f800,
-	0x00104619, 0x0400000c, 0x42028000, 0x00000005,
-	0x592c0a08, 0x0201f800, 0x00104bee, 0x0201f800,
-	0x00108f83, 0x0201f800, 0x00020381, 0x5c025800,
-	0x0401f7e5, 0x5c025800, 0x4a025a06, 0x00000031,
-	0x0201f000, 0x00020381, 0x492fc857, 0x4d2c0000,
-	0x0201f800, 0x0010082a, 0x04000016, 0x492fc857,
-	0x412f4000, 0x0201f800, 0x0010082a, 0x0400000e,
-	0x492fc857, 0x412dd800, 0x0201f800, 0x00103941,
-	0x0201f800, 0x0010394b, 0x49a1d80b, 0x5c025800,
-	0x492dd80a, 0x0201f800, 0x00101fbb, 0x0201f000,
-	0x00101fda, 0x41a25800, 0x0201f800, 0x0010083a,
-	0x5c025800, 0x4a025a06, 0x00004005, 0x4a025c06,
-	0x00000002, 0x0201f000, 0x00020381, 0x4807c857,
-	0x485fc857, 0x4200b800, 0x00000001, 0x5c000800,
-	0x4c5c0000, 0x0401f005, 0x4807c857, 0x485fc857,
-	0x5c000800, 0x4d780000, 0x4803c857, 0x492fc857,
-	0x8c00050e, 0x02020800, 0x0010060d, 0x4203e000,
-	0x50000000, 0x4200b800, 0x00008003, 0x0201f000,
-	0x0010061a, 0x592c0204, 0x80000110, 0x80000040,
-	0x0402042d, 0x0201f800, 0x00104886, 0x04020002,
-	0x1c01f000, 0x49425a06, 0x4806580d, 0x480a580e,
-	0x4943c857, 0x4807c857, 0x480bc857, 0x0201f000,
-	0x00020381, 0x592c0204, 0x80000110, 0x80000040,
-	0x0402041d, 0x0201f800, 0x001049ec, 0x04020002,
-	0x1c01f000, 0x49425a06, 0x48065811, 0x480a5812,
-	0x0201f000, 0x00020381, 0x592c0204, 0x80000110,
-	0x04000411, 0x80000040, 0x0402000c, 0x4202e000,
-	0x00000001, 0x592c020a, 0x8c000504, 0x02000000,
-	0x00020603, 0x592c0207, 0x82000c80, 0x00001001,
-	0x04021415, 0x0401f009, 0x4202e000, 0x00000003,
-	0x48033002, 0x492f3003, 0x492f3004, 0x4a033008,
-	0x00020603, 0x1c01f000, 0x4202e000, 0x00000002,
-	0x42000000, 0x0010bcd9, 0x50007000, 0x492c700b,
-	0x4978700e, 0x4978700c, 0x592c0011, 0x592c0812,
-	0x48007007, 0x48047008, 0x592c1013, 0x82080500,
-	0xffff0000, 0x04000003, 0x0201f800, 0x00100615,
-	0x4978700d, 0x82080480, 0x00000180, 0x4803c857,
-	0x04001007, 0x4800700f, 0x4a007005, 0x00000180,
-	0x4a007004, 0x00000060, 0x0401f005, 0x4978700f,
-	0x48087005, 0x80081104, 0x48087004, 0x5838000a,
-	0x48007003, 0x40381000, 0x0201f000, 0x001008a1,
-	0x0201f800, 0x00100819, 0x04000003, 0x59980007,
-	0x0801f000, 0x1c01f000, 0x40307000, 0x5838000b,
-	0x80025d40, 0x0400001b, 0x58380002, 0x82000580,
-	0x00000100, 0x0400001d, 0x4c380000, 0x592c0204,
-	0x82000500, 0x000000ff, 0x82000580, 0x00000012,
-	0x0400000b, 0x592c0208, 0x8400054e, 0x48025a08,
-	0x4a025a06, 0x00000002, 0x4a025a04, 0x00000103,
-	0x0201f800, 0x00020381, 0x0401f005, 0x4a025a06,
-	0x00000010, 0x0201f800, 0x00020381, 0x5c007000,
-	0x4202e000, 0x00000001, 0x4a007002, 0x00000100,
-	0x49787010, 0x1c01f000, 0x58380004, 0x82000480,
-	0x00000003, 0x04000087, 0x58380010, 0x8c000500,
-	0x04020019, 0x4200b000, 0x00000003, 0x832cac00,
-	0x00000011, 0x5838000a, 0x5838100d, 0x8008a400,
-	0x4c380000, 0x0201f800, 0x0010a93e, 0x5c007000,
-	0x5838000d, 0x82000400, 0x00000003, 0x4800700d,
-	0x4a007010, 0x00000001, 0x58380004, 0x82000480,
-	0x00000003, 0x48007004, 0x82000580, 0x00000003,
-	0x0400006c, 0x5838000e, 0x80001d40, 0x04020020,
-	0x4c380000, 0x0201f800, 0x00100819, 0x5c007000,
-	0x04000010, 0x4a025a04, 0x0000010a, 0x42001800,
-	0x00000005, 0x480c700e, 0x5838000c, 0x80000540,
-	0x04020002, 0x5838000b, 0x40000800, 0x492c0801,
-	0x492c700c, 0x42000800, 0x0000000f, 0x0401f011,
-	0x4202e000, 0x00000008, 0x4a033007, 0x001055f9,
-	0x1c01f000, 0x4202e000, 0x00000002, 0x42000000,
-	0x0010bcd9, 0x50007000, 0x0401f7e7, 0x583a580c,
-	0x400c0000, 0x42000800, 0x00000014, 0x80040c80,
-	0x58381004, 0x5838000f, 0x41783000, 0x80000540,
-	0x04020005, 0x84183540, 0x82081480, 0x00000003,
-	0x0400003c, 0x40080000, 0x80040480, 0x04001002,
-	0x40080800, 0x4004b000, 0x412c0000, 0x800c0400,
-	0x4000a800, 0x5838000a, 0x5838100d, 0x8008a400,
-	0x4c080000, 0x4c040000, 0x4c0c0000, 0x4c380000,
-	0x0201f800, 0x0010a93e, 0x5c007000, 0x5c001800,
-	0x5c000800, 0x40040000, 0x58381004, 0x80080480,
-	0x48007004, 0x82000580, 0x00000003, 0x04000002,
-	0x84183500, 0x5c000000, 0x80041400, 0x82080480,
-	0x00000060, 0x04020003, 0x84183542, 0x41781000,
-	0x400c0000, 0x80041c00, 0x820c0480, 0x00000014,
-	0x04020003, 0x84183544, 0x40001800, 0x40080800,
-	0x4804700d, 0x480c700e, 0x40180000, 0x0c01f001,
-	0x00105644, 0x00105648, 0x00105646, 0x00105644,
-	0x001055e0, 0x00105648, 0x00105646, 0x00105644,
-	0x0201f800, 0x00100615, 0x5838100f, 0x0401f739,
-	0x5838080d, 0x82040400, 0x00000002, 0x5838100a,
-	0x80080400, 0x50001000, 0x800811c0, 0x0402000f,
-	0x4202e000, 0x00000001, 0x583a580b, 0x4978700b,
-	0x49787010, 0x592c0204, 0x82000500, 0x000000ff,
-	0x82000580, 0x00000012, 0x02000000, 0x0002063b,
-	0x0201f000, 0x00020603, 0x5838000a, 0x80040c00,
-	0x82381c00, 0x00000007, 0x54041800, 0x80040800,
-	0x800c1800, 0x54041800, 0x0401f71a, 0x0201f800,
-	0x00100819, 0x02000800, 0x00100615, 0x4a02580a,
-	0x0010bc78, 0x42000800, 0x0010bcd9, 0x452c0800,
-	0x497a580b, 0x497a580c, 0x497a580d, 0x497a580e,
-	0x497a580f, 0x4a025809, 0x0010559a, 0x497a5810,
-	0x4a025802, 0x00000100, 0x4a025801, 0x00000001,
-	0x1c01f000, 0x59c80007, 0x8c000502, 0x04000071,
-	0x835c2c80, 0x00000005, 0x02001000, 0x00105c5c,
-	0x59c82817, 0x4817506e, 0x497b9005, 0x82140500,
-	0x00e00000, 0x0402004f, 0x82140500, 0x000003ff,
-	0x82001c00, 0x00000006, 0x41cc2000, 0x42003000,
-	0x00006080, 0x820c0480, 0x00000040, 0x04001006,
-	0x42001000, 0x00000040, 0x820c1c80, 0x00000040,
-	0x0401f003, 0x400c1000, 0x41781800, 0x54182000,
-	0x80102000, 0x80183000, 0x80081040, 0x040207fc,
-	0x800c19c0, 0x04000005, 0x59c80005, 0x80000000,
-	0x48039005, 0x0401f7ea, 0x82140500, 0x01f60000,
-	0x04020029, 0x82140500, 0x0000f000, 0x0400000b,
-	0x82000c80, 0x00002000, 0x0402100f, 0x4a039005,
-	0x00000140, 0x82140500, 0x0e000000, 0x80000132,
-	0x0c01f83e, 0x1c01f000, 0x59cc0400, 0x82000500,
-	0x0000ff00, 0x82000580, 0x00008100, 0x040007f4,
-	0x0401f01c, 0x4817c857, 0x82140500, 0x000003ff,
-	0x04020007, 0x59cc0400, 0x82000500, 0x0000ff00,
-	0x82000580, 0x00008100, 0x04020012, 0x42000000,
-	0x0010b6bc, 0x0201f800, 0x0010a86e, 0x0201f800,
-	0x00105b32, 0x4803c856, 0x4a039005, 0x00000140,
-	0x0401f020, 0x4817c857, 0x82140500, 0x00f60000,
-	0x04020004, 0x0201f800, 0x00105b6e, 0x040207d2,
-	0x0201f800, 0x00104e0d, 0x04000010, 0x59c400a4,
-	0x4803c857, 0x82000500, 0x0000000f, 0x82000580,
-	0x0000000a, 0x04020009, 0x497b5016, 0x59c400a3,
-	0x82000540, 0x00080000, 0x480388a3, 0x82000500,
-	0xfff7ffff, 0x480388a3, 0x4817c856, 0x0201f800,
-	0x0010a79f, 0x4a039005, 0x00000140, 0x0401f842,
-	0x4803c856, 0x1c01f000, 0x00105702, 0x00105a13,
-	0x001056fa, 0x001056fa, 0x001056fa, 0x001056fa,
-	0x001056fa, 0x001056fa, 0x4803c857, 0x42000000,
-	0x0010b659, 0x0201f800, 0x0010a86e, 0x4a039005,
-	0x00000140, 0x1c01f000, 0x59cc0400, 0x82000d00,
-	0x0000ff00, 0x82041500, 0x0000f000, 0x840409c0,
-	0x82140500, 0x000003ff, 0x800018c4, 0x8c142d14,
-	0x04000005, 0x59cc0002, 0x82000500, 0x00000003,
-	0x800c1c80, 0x480f5016, 0x82080580, 0x00002000,
-	0x04020013, 0x836c0580, 0x00000001, 0x0402000e,
-	0x59cc0006, 0x82000500, 0xff000000, 0x82000580,
-	0x11000000, 0x02020800, 0x001006ba, 0x04020011,
-	0x0201f800, 0x00103951, 0x0201f800, 0x00105c81,
-	0x0401f00c, 0x0401f81f, 0x0401f00a, 0x82080580,
-	0x00003000, 0x04020003, 0x0401fa40, 0x0401f005,
-	0x82080580, 0x00008000, 0x04020002, 0x0401fb36,
-	0x1c01f000, 0x4817c857, 0x42000000, 0x0010b658,
-	0x0201f800, 0x0010a86e, 0x836c0580, 0x00000003,
-	0x0402000b, 0x4c080000, 0x4c0c0000, 0x42001000,
-	0x00008048, 0x40141800, 0x80142120, 0x0201f800,
-	0x00103857, 0x5c001800, 0x5c001000, 0x1c01f000,
-	0x59cc0002, 0x82000500, 0xff000000, 0x82001580,
-	0x01000000, 0x04000006, 0x82001580, 0x23000000,
-	0x02020800, 0x001006ba, 0x040201c9, 0x82040580,
-	0x00000023, 0x04020055, 0x59cc0004, 0x4803c857,
-	0x59cc0006, 0x82000500, 0xff000000, 0x59cc0801,
-	0x82040d00, 0x00ffffff, 0x80040540, 0x4803c857,
-	0x0401fbb2, 0x02000800, 0x001006ba, 0x040001b8,
-	0x59300c06, 0x82040580, 0x00000010, 0x04000012,
-	0x82040580, 0x00000011, 0x0400000f, 0x82040580,
-	0x00000001, 0x0400000c, 0x82040580, 0x00000004,
-	0x04000009, 0x82040580, 0x00000008, 0x04000006,
-	0x82040580, 0x0000000a, 0x02020800, 0x001006ba,
-	0x040201a3, 0x59300004, 0x82000500, 0x80010000,
-	0x04000006, 0x0201f800, 0x00106cb4, 0x02020800,
-	0x001006ba, 0x0402019a, 0x59cc0a04, 0x48066202,
-	0x59a80016, 0x800001c0, 0x02000800, 0x001006ba,
-	0x04000193, 0x59cc0006, 0x82000500, 0xffff0000,
-	0x82000d80, 0x02000000, 0x04020005, 0x42027000,
-	0x00000015, 0x0201f000, 0x000208d8, 0x82000d80,
-	0x02140000, 0x040007fa, 0x82000d80, 0x02100000,
-	0x040007f7, 0x82000d80, 0x02100000, 0x040007f4,
-	0x82000d80, 0x01000000, 0x02020800, 0x001006ba,
-	0x0402017b, 0x59cc0006, 0x82000500, 0x0000ffff,
-	0x02020800, 0x001006ba, 0x04020175, 0x42027000,
-	0x00000016, 0x0401f7e8, 0x82040580, 0x00000022,
-	0x02020800, 0x001006ba, 0x0402016d, 0x59cc0004,
-	0x4803c857, 0x59cc0006, 0x4803c857, 0x59cc0001,
-	0x4803c857, 0x59a80016, 0x800001c0, 0x02000800,
-	0x001006ba, 0x04000162, 0x59a80806, 0x8c040d14,
-	0x04000011, 0x0401f97d, 0x0402000f, 0x0401f993,
-	0x0400000d, 0x42027000, 0x0000004c, 0x59cc0001,
-	0x82000500, 0x00ffffff, 0x0201f800, 0x00105c25,
-	0x0400013e, 0x42028800, 0x0000ffff, 0x417a6800,
-	0x0401f13a, 0x59cc0006, 0x82000500, 0xffff0000,
-	0x82000d80, 0x03000000, 0x04020023, 0x59a80026,
-	0x8c000508, 0x04000017, 0x8400054c, 0x48035026,
-	0x59cc0800, 0x82040d00, 0x00ffffff, 0x48075010,
-	0x497b8830, 0x84040d70, 0x48078832, 0x59c40802,
-	0x84040d4c, 0x48078802, 0x59cc0007, 0x82000500,
-	0x0000ffff, 0x48038893, 0x4803501e, 0x42000800,
-	0x00000003, 0x59a81010, 0x0201f800, 0x001069af,
-	0x59cc0006, 0x82000500, 0x0000ffff, 0x02020800,
-	0x001006ba, 0x0402012a, 0x42027000, 0x00000017,
-	0x0401f0e5, 0x82000d80, 0x04000000, 0x04020013,
-	0x59cc0006, 0x82000500, 0x0000ffff, 0x02020800,
-	0x001006ba, 0x0402011e, 0x0201f800, 0x00104e0d,
-	0x04000004, 0x42027000, 0x0000001d, 0x0401f0d6,
-	0x59a80026, 0x84000548, 0x48035026, 0x42027000,
-	0x00000030, 0x0401f0d0, 0x82000d80, 0x05000000,
-	0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff,
-	0x02020800, 0x001006ba, 0x04020109, 0x42027000,
-	0x00000018, 0x0401f0c4, 0x82000d80, 0x20100000,
-	0x04020004, 0x42027000, 0x00000019, 0x0401f0be,
-	0x82000d80, 0x21100000, 0x04020004, 0x42027000,
-	0x0000001a, 0x0401f0b8, 0x82000d80, 0x52000000,
-	0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff,
-	0x02020800, 0x001006ba, 0x040200f1, 0x42027000,
-	0x0000001b, 0x0401f0ac, 0x82000d80, 0x50000000,
-	0x0402000a, 0x59cc0006, 0x82000500, 0x0000ffff,
-	0x02020800, 0x001006ba, 0x040200e5, 0x42027000,
-	0x0000001c, 0x0401f0a0, 0x82000d80, 0x13000000,
-	0x04020004, 0x42027000, 0x00000034, 0x0401f09a,
-	0x82000d80, 0x12000000, 0x0402000a, 0x59cc0006,
-	0x82000500, 0x0000ffff, 0x02020800, 0x001006ba,
-	0x040200d3, 0x42027000, 0x00000024, 0x0401f08e,
-	0x82000d00, 0xff000000, 0x82040d80, 0x24000000,
-	0x04020004, 0x42027000, 0x0000002d, 0x0401f086,
-	0x82000d00, 0xff000000, 0x82040d80, 0x53000000,
-	0x04020004, 0x42027000, 0x0000002a, 0x0401f07e,
-	0x82000d80, 0x0f000000, 0x04020004, 0x42027000,
-	0x00000020, 0x0401f078, 0x82000d80, 0x61040000,
-	0x04020036, 0x83cc1400, 0x00000006, 0x80080800,
-	0x50080000, 0x82000500, 0x0000ffff, 0x82000480,
-	0x00000004, 0x4c580000, 0x8000b104, 0x8058b1c0,
-	0x04000026, 0x4c100000, 0x50041800, 0x820c1500,
-	0x03000000, 0x80081130, 0x42000000, 0x0010b615,
-	0x82082580, 0x00000000, 0x04020004, 0x42000000,
-	0x0010b612, 0x0401f00c, 0x82082580, 0x00000001,
-	0x04020004, 0x42000000, 0x0010b613, 0x0401f006,
-	0x82082580, 0x00000002, 0x04020003, 0x42000000,
-	0x0010b614, 0x0201f800, 0x0010a86e, 0x42001000,
-	0x00008015, 0x820c2500, 0x0000ffff, 0x800c1920,
-	0x0201f800, 0x00103857, 0x5c002000, 0x80040800,
-	0x8058b040, 0x040207da, 0x5c00b000, 0x42027000,
-	0x00000023, 0x0401f040, 0x82000d80, 0x60000000,
-	0x04020004, 0x42027000, 0x0000003f, 0x0401f03a,
-	0x82000d80, 0x54000000, 0x04020008, 0x0401fb36,
-	0x02020800, 0x001006ba, 0x04020075, 0x42027000,
-	0x00000046, 0x0401f030, 0x82000d80, 0x55000000,
-	0x04020009, 0x0401fb54, 0x04020004, 0x42027000,
-	0x00000041, 0x0401f028, 0x42027000, 0x00000042,
-	0x0401f025, 0x82000d80, 0x78000000, 0x04020004,
-	0x42027000, 0x00000045, 0x0401f01f, 0x82000d80,
-	0x10000000, 0x04020004, 0x42027000, 0x0000004e,
-	0x0401f019, 0x82000d80, 0x63000000, 0x04020004,
-	0x42027000, 0x0000004a, 0x0401f013, 0x82000d00,
-	0xff000000, 0x82040d80, 0x56000000, 0x04020004,
-	0x42027000, 0x0000004f, 0x0401f00b, 0x82000d00,
-	0xff000000, 0x82040d80, 0x57000000, 0x04020004,
-	0x42027000, 0x00000050, 0x0401f003, 0x42027000,
-	0x0000001d, 0x59cc3800, 0x821c3d00, 0x00ffffff,
-	0x821c0580, 0x00fffffe, 0x59cc0001, 0x04020005,
-	0x40003000, 0x42028800, 0x000007fe, 0x0401f005,
-	0x0401f8da, 0x02020800, 0x001006ba, 0x04020034,
-	0x0201f800, 0x00104401, 0x02020800, 0x001006ba,
-	0x0402002f, 0x83380580, 0x00000046, 0x04020006,
-	0x59a80010, 0x80180580, 0x02000800, 0x001006ba,
-	0x04000027, 0x59340200, 0x8c000514, 0x0400000f,
-	0x83380580, 0x00000030, 0x0400000c, 0x83380580,
-	0x0000003f, 0x04000009, 0x83380580, 0x00000034,
-	0x04000006, 0x83380580, 0x00000024, 0x04000003,
-	0x42027000, 0x0000004c, 0x0201f800, 0x00020892,
-	0x04000018, 0x49366009, 0x4a026406, 0x00000004,
-	0x59cc0c04, 0x48066202, 0x83380580, 0x0000004c,
-	0x04020009, 0x4a026406, 0x00000011, 0x813669c0,
-	0x04020005, 0x59cc0001, 0x82000500, 0x00ffffff,
-	0x4802601e, 0x0201f000, 0x000208d8, 0x59880053,
-	0x4803c857, 0x80000000, 0x48031053, 0x1c01f000,
-	0x42001000, 0x00008049, 0x59cc1806, 0x800c1930,
-	0x0201f800, 0x00103857, 0x0201f800, 0x001076c9,
-	0x02000800, 0x001006ba, 0x040007f1, 0x49366009,
-	0x4a026406, 0x00000004, 0x59cc0c04, 0x48066202,
-	0x4a026403, 0x00000009, 0x4a02641a, 0x00000009,
-	0x4a02621a, 0x00002900, 0x4a026203, 0x00000001,
-	0x0201f000, 0x00106470, 0x59a80026, 0x4803c857,
-	0x8c000508, 0x04000010, 0x59cc0006, 0x82000500,
-	0xff000000, 0x82000d80, 0x03000000, 0x0400000c,
-	0x82000d80, 0x20000000, 0x04000009, 0x82000d80,
-	0x05000000, 0x04000006, 0x82000d80, 0x21000000,
-	0x04000003, 0x80000580, 0x1c01f000, 0x82000540,
-	0x00000001, 0x0401f7fd, 0x59cc2006, 0x82102500,
-	0xff000000, 0x9c1021c0, 0x0401f807, 0x820c1c00,
-	0x0010b2df, 0x500c1800, 0x800c0500, 0x4803c857,
-	0x1c01f000, 0x40100800, 0x41781800, 0x82040480,
-	0x00000020, 0x04001004, 0x800c1800, 0x40000800,
-	0x0401f7fb, 0x82040500, 0x0000000f, 0x82000400,
-	0x0010a95f, 0x50000000, 0x8c040d08, 0x04000002,
-	0x900001c0, 0x1c01f000, 0x4803c856, 0x0401fadd,
-	0x0402000a, 0x0201f800, 0x00101eb0, 0x04020007,
-	0x59cc0002, 0x82000500, 0xff000000, 0x82000d80,
-	0x08000000, 0x04000802, 0x1c01f000, 0x4803c856,
-	0x59cc0400, 0x82000d00, 0x0000ff00, 0x840409c0,
-	0x82040580, 0x00000033, 0x0402001f, 0x0401f98f,
-	0x04000038, 0x59cc0a04, 0x48066202, 0x59cc0006,
-	0x4803c857, 0x82000500, 0xffff0000, 0x82000d80,
-	0x02000000, 0x04020009, 0x59cc0006, 0x82000500,
-	0x0000ffff, 0x0402002b, 0x42027000, 0x00000015,
-	0x0201f000, 0x000208d8, 0x82000d80, 0x01000000,
-	0x04020024, 0x59cc0006, 0x82000500, 0x0000ffff,
-	0x04020020, 0x42027000, 0x00000016, 0x0201f000,
-	0x000208d8, 0x82040580, 0x00000032, 0x04020019,
-	0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80,
-	0x14000000, 0x04020013, 0x42027000, 0x00000038,
-	0x59cc0001, 0x0401f810, 0x0402000e, 0x0201f800,
-	0x001043fc, 0x0402000b, 0x0201f800, 0x00020892,
-	0x04000008, 0x49366009, 0x4a026406, 0x00000004,
-	0x59cc0c04, 0x48066202, 0x0201f000, 0x000208d8,
-	0x1c01f000, 0x4803c857, 0x4c580000, 0x4c100000,
-	0x4c380000, 0x4c340000, 0x82003500, 0x00ffffff,
-	0x82181500, 0x00ff0000, 0x82081580, 0x00ff0000,
-	0x04020016, 0x82181480, 0x00fffffc, 0x04001013,
-	0x82181580, 0x00fffffd, 0x04020004, 0x42028800,
-	0x000007fd, 0x0401f040, 0x82181580, 0x00fffffe,
-	0x04020004, 0x42028800, 0x000007fe, 0x0401f03a,
-	0x82181580, 0x00fffffc, 0x04020004, 0x42028800,
-	0x000007fc, 0x0401f034, 0x41781000, 0x42002000,
-	0x00000000, 0x4200b000, 0x000007f0, 0x41ac7000,
-	0x50380000, 0x80006d40, 0x04020005, 0x800811c0,
-	0x0402001e, 0x8410155e, 0x0401f01c, 0x58340212,
-	0x82000500, 0x0000ff00, 0x04000011, 0x59a84010,
-	0x82204500, 0x00ffff00, 0x82180500, 0x00ffff00,
-	0x04000002, 0x80200580, 0x58340002, 0x0402000f,
-	0x82000500, 0x000000ff, 0x82184500, 0x000000ff,
-	0x80204580, 0x04020009, 0x0401f006, 0x58340002,
-	0x82000500, 0x00ffffff, 0x80184580, 0x04020003,
-	0x40128800, 0x0401f00c, 0x80102000, 0x80387000,
-	0x8058b040, 0x040207db, 0x800811c0, 0x04020005,
-	0x481bc857, 0x82000540, 0x00000001, 0x0401f003,
-	0x840a8d1e, 0x80000580, 0x5c006800, 0x5c007000,
-	0x5c002000, 0x5c00b000, 0x1c01f000, 0x59a80026,
-	0x8c00050e, 0x04000003, 0x8c000502, 0x04000006,
-	0x59cc0c00, 0x80040910, 0x82040500, 0x0000000f,
-	0x0c01f002, 0x1c01f000, 0x00105a2e, 0x00105a2e,
-	0x00105a2e, 0x00105b1d, 0x00105a2e, 0x00105a30,
-	0x00105a48, 0x00105a4b, 0x00105a2e, 0x00105a2e,
-	0x00105a2e, 0x00105a2e, 0x00105a2e, 0x00105a2e,
-	0x00105a2e, 0x00105a2e, 0x4803c856, 0x1c01f000,
-	0x0401f8de, 0x04000014, 0x82140500, 0x000003ff,
-	0x800000c4, 0x82000480, 0x00000008, 0x0400100e,
-	0x59cc0001, 0x59326809, 0x59340802, 0x80040580,
-	0x82000500, 0x00ffffff, 0x04020007, 0x59cc0a04,
-	0x48066202, 0x42027000, 0x00000046, 0x0201f000,
-	0x000208d8, 0x59cc0004, 0x4803c857, 0x1c01f000,
-	0x59cc0004, 0x4803c857, 0x1c01f000, 0x0401f8c3,
-	0x04000016, 0x82140500, 0x000003ff, 0x800000c4,
-	0x82000480, 0x0000000c, 0x04001010, 0x59cc0001,
-	0x82000500, 0x00ffffff, 0x59326809, 0x59340802,
-	0x82040d00, 0x00ffffff, 0x80040580, 0x04020007,
-	0x59cc0a04, 0x48066202, 0x42027000, 0x00000045,
-	0x0201f000, 0x000208d8, 0x59cc0004, 0x4803c857,
-	0x1c01f000, 0x59cc0004, 0x4803c857, 0x59cc0000,
-	0x82000500, 0xff000000, 0x59cc1001, 0x82081500,
-	0x00ffffff, 0x80080540, 0x4803c857, 0x4817c857,
-	0x0401f9d8, 0x02020800, 0x001006ba, 0x04020016,
-	0x0201f800, 0x00101eb0, 0x02020800, 0x001006ba,
-	0x04020011, 0x59cc0002, 0x82000500, 0xff000000,
-	0x82000580, 0x00000000, 0x02020800, 0x001006ba,
-	0x04020009, 0x82040500, 0x0000000f, 0x82000c80,
-	0x00000006, 0x02021800, 0x001006ba, 0x04021002,
-	0x0c01f003, 0x4803c856, 0x1c01f000, 0x00105a91,
-	0x00105a93, 0x00105a91, 0x00105a91, 0x00105aec,
-	0x00105afb, 0x4803c856, 0x1c01f000, 0x59a80016,
-	0x800001c0, 0x02020800, 0x001006ba, 0x040207fa,
-	0x59cc0802, 0x4807c856, 0x8c040d2e, 0x0402001d,
-	0x0201f800, 0x001076c9, 0x02000800, 0x00100615,
-	0x59cc0001, 0x0401ff18, 0x0402000d, 0x0201f800,
-	0x00020267, 0x0402000a, 0x4a026406, 0x00000005,
-	0x49366009, 0x59cc0804, 0x4806601c, 0x42027000,
-	0x00000088, 0x0201f000, 0x000208d8, 0x4803c857,
-	0x42028800, 0x0000ffff, 0x417a6800, 0x59cc0001,
-	0x82000500, 0x00ffffff, 0x4802601e, 0x0401f7ef,
-	0x59cc0001, 0x4803c857, 0x0401feff, 0x02020800,
-	0x001006ba, 0x040207d4, 0x0201f800, 0x001043fc,
-	0x02020800, 0x001006ba, 0x040207cf, 0x59cc0005,
-	0x8c000500, 0x04020006, 0x59340200, 0x8c00050e,
-	0x02020800, 0x001006ba, 0x040207c7, 0x0201f800,
-	0x00104842, 0x04020013, 0x0401f840, 0x02000800,
-	0x001006ba, 0x040007c0, 0x0201f800, 0x00020892,
-	0x02000800, 0x001006ba, 0x040007bb, 0x49366009,
-	0x4a026406, 0x00000002, 0x59cc0804, 0x4806601c,
-	0x42027000, 0x00000088, 0x0201f000, 0x000208d8,
-	0x0201f800, 0x00020892, 0x040007af, 0x49366009,
-	0x4a026406, 0x00000004, 0x59cc0c04, 0x48066202,
-	0x42027000, 0x00000001, 0x0201f000, 0x000208d8,
-	0x59cc0802, 0x8c040d2e, 0x0400000b, 0x0401f81f,
-	0x04000009, 0x0401f961, 0x04020007, 0x59cc0a04,
-	0x48066202, 0x42027000, 0x00000089, 0x0201f000,
-	0x000208d8, 0x4933c857, 0x1c01f000, 0x59cc0004,
-	0x4803c857, 0x59cc0802, 0x8c040d2e, 0x0400000b,
-	0x0401f80e, 0x04000009, 0x0401f950, 0x04020007,
-	0x59cc0a04, 0x48066202, 0x42027000, 0x0000008a,
-	0x0201f000, 0x000208d8, 0x4933c857, 0x1c01f000,
-	0x59cc0a04, 0x0401f002, 0x59cc0c04, 0x59a8000e,
-	0x59a81067, 0x80080400, 0x80040480, 0x04021008,
-	0x40040000, 0x800000c4, 0x800408ca, 0x80040c00,
-	0x82066400, 0x0010cfc0, 0x1c01f000, 0x80000580,
-	0x0401f7fe, 0x59cc0802, 0x8c040d2e, 0x04020010,
-	0x0401ffec, 0x0400000e, 0x59cc0001, 0x82000500,
-	0x00ffffff, 0x59326809, 0x59340802, 0x82040d00,
-	0x00ffffff, 0x80040580, 0x04020005, 0x42027000,
-	0x00000051, 0x0201f000, 0x000208d8, 0x59cc0004,
-	0x4803c857, 0x1c01f000, 0x4803c856, 0x42003000,
-	0x00000105, 0x0401f001, 0x4803c856, 0x4c3c0000,
-	0x41cc7800, 0x40142000, 0x0401f803, 0x5c007800,
-	0x1c01f000, 0x4803c856, 0x4c580000, 0x583c0400,
-	0x82000500, 0x0000f000, 0x82000580, 0x0000c000,
-	0x04000024, 0x0201f800, 0x00020892, 0x04000021,
-	0x4c180000, 0x583c0001, 0x0401fe6f, 0x0402001f,
-	0x0201f800, 0x001043fc, 0x0402001c, 0x49366009,
-	0x0201f800, 0x0010082a, 0x04000018, 0x492e6017,
-	0x497a5800, 0x497a5a04, 0x48125c04, 0x832cac00,
-	0x00000005, 0x4200b000, 0x00000007, 0x403ca000,
-	0x0201f800, 0x0010a93e, 0x5c003000, 0x481a641a,
-	0x4a026403, 0x0000003e, 0x4a026406, 0x00000001,
-	0x4a026203, 0x00000001, 0x0201f800, 0x00106470,
-	0x5c00b000, 0x1c01f000, 0x0201f800, 0x000208b4,
-	0x5c003000, 0x0401f7fb, 0x4803c856, 0x59cc0400,
-	0x82000d00, 0x0000ff00, 0x82040500, 0x0000f000,
-	0x840409c0, 0x82000580, 0x00002000, 0x04020049,
-	0x82040580, 0x00000022, 0x0402003a, 0x59c400a4,
-	0x82000500, 0x0000000f, 0x82000c80, 0x00000007,
-	0x04001004, 0x82000480, 0x0000000c, 0x0400103f,
-	0x59cc0006, 0x82000500, 0xffff0000, 0x82000d80,
-	0x04000000, 0x04000039, 0x82000d80, 0x60000000,
-	0x04000036, 0x82000d80, 0x54000000, 0x04000033,
-	0x82000d80, 0x03000000, 0x04020015, 0x59a80826,
-	0x8c040d02, 0x0402002d, 0x8c040d08, 0x0402002b,
-	0x0201f800, 0x0010473b, 0x0400002b, 0x59a8001d,
-	0x800000d0, 0x59a80810, 0x82040d00, 0x000000ff,
-	0x80040540, 0x59cc0800, 0x82040d00, 0x00ffffff,
-	0x80040580, 0x0402001b, 0x0401f01c, 0x59c40802,
-	0x8c040d0c, 0x04020017, 0x82000d80, 0x52000000,
-	0x040007ec, 0x82000d80, 0x05000000, 0x040007e9,
-	0x82000d80, 0x50000000, 0x040007e6, 0x0401f00d,
-	0x82040580, 0x00000023, 0x0402000a, 0x0401ff57,
-	0x04000008, 0x59300c03, 0x82040580, 0x00000002,
-	0x04000006, 0x82040580, 0x00000051, 0x04000003,
-	0x80000580, 0x0401f003, 0x82000540, 0x00000001,
-	0x1c01f000, 0x59cc0006, 0x82000500, 0xffff0000,
-	0x82000d80, 0x03000000, 0x04000004, 0x82000d80,
-	0x52000000, 0x040207f3, 0x59a80026, 0x82000500,
-	0x00000009, 0x82000580, 0x00000008, 0x040007ef,
-	0x0401f7ec, 0x4803c856, 0x4c5c0000, 0x4c580000,
-	0x59a80016, 0x82000580, 0x0000004c, 0x0402001f,
-	0x59ccb807, 0x9c5cb9c0, 0x825cbd00, 0x00000007,
-	0x8c5cbd00, 0x0400000a, 0x4200b000, 0x00000002,
-	0x83a81c00, 0x00000002, 0x83cc1400, 0x0000000d,
-	0x0201f800, 0x001082ff, 0x04020010, 0x8c5cbd02,
-	0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00,
-	0x00000000, 0x83cc1400, 0x0000000f, 0x0201f800,
-	0x001082ff, 0x04020005, 0x8c5cbd04, 0x04000003,
-	0x82000540, 0x00000001, 0x5c00b000, 0x5c00b800,
-	0x1c01f000, 0x4803c856, 0x4c5c0000, 0x4c580000,
-	0x59a80016, 0x82000580, 0x0000004c, 0x0402001f,
-	0x59ccb807, 0x9c5cb9c0, 0x825cbd00, 0x00000007,
-	0x8c5cbd00, 0x0400000a, 0x4200b000, 0x00000002,
-	0x83a81c00, 0x00000002, 0x83cc1400, 0x00000009,
-	0x0201f800, 0x001082ff, 0x04020010, 0x8c5cbd02,
-	0x0400000a, 0x4200b000, 0x00000002, 0x83a81c00,
-	0x00000000, 0x83cc1400, 0x0000000b, 0x0201f800,
-	0x001082ff, 0x04020005, 0x8c5cbd04, 0x04000003,
-	0x82000540, 0x00000001, 0x5c00b000, 0x5c00b800,
-	0x1c01f000, 0x4803c857, 0x4c580000, 0x40003000,
-	0x42002000, 0x000007f0, 0x4200b000, 0x00000010,
-	0x83ac7400, 0x000007f0, 0x50380000, 0x80026d40,
-	0x04000006, 0x59340002, 0x82000500, 0x00ffffff,
-	0x80180580, 0x04000010, 0x80102000, 0x80387000,
-	0x8058b040, 0x040207f5, 0x82100480, 0x00000800,
-	0x42002000, 0x00000000, 0x4200b000, 0x000007f0,
-	0x41ac7000, 0x040217ed, 0x82000540, 0x00000001,
-	0x0401f002, 0x40128800, 0x5c00b000, 0x1c01f000,
-	0x59a80026, 0x8c00050e, 0x04000004, 0x8c000502,
-	0x04000003, 0x80000580, 0x1c01f000, 0x82000540,
-	0x00000001, 0x0401f7fd, 0x59300c06, 0x82040580,
-	0x00000002, 0x04000006, 0x82040580, 0x00000005,
-	0x04000003, 0x82000540, 0x00000001, 0x1c01f000,
-	0x59c80000, 0x84000558, 0x84000512, 0x48039000,
-	0x1c01f000, 0x4a03281a, 0x000003e8, 0x4a032802,
-	0x0010cfc0, 0x4a032800, 0x00000000, 0x4a032808,
-	0x00106d9f, 0x42000000, 0x00000005, 0x83947c00,
-	0x00000009, 0x49787801, 0x4a007802, 0x00106d54,
-	0x823c7c00, 0x00000003, 0x80000040, 0x040207fa,
-	0x4a032819, 0xffff0000, 0x4201d000, 0x00000064,
-	0x0401f97c, 0x4201d000, 0x000186a0, 0x0401f18b,
-	0x00000000, 0x00000003, 0x00000006, 0x00000009,
-	0x0000000c, 0x4d300000, 0x4d2c0000, 0x4d340000,
-	0x4d400000, 0x4cfc0000, 0x4d380000, 0x4d3c0000,
-	0x4d440000, 0x4d4c0000, 0x4d480000, 0x4c5c0000,
-	0x4c600000, 0x4c640000, 0x4cc80000, 0x4ccc0000,
-	0x0201f800, 0x000206af, 0x5c019800, 0x5c019000,
-	0x5c00c800, 0x5c00c000, 0x5c00b800, 0x5c029000,
-	0x5c029800, 0x5c028800, 0x5c027800, 0x5c027000,
-	0x5c01f800, 0x5c028000, 0x5c026800, 0x5c025800,
-	0x5c026000, 0x1c01f000, 0x59940004, 0x80000540,
-	0x0402000a, 0x59940025, 0x80040400, 0x02001800,
-	0x00100615, 0x48032804, 0x480b2805, 0x4a032803,
-	0x0000000a, 0x80000580, 0x1c01f000, 0x5994001f,
-	0x80000540, 0x0402000a, 0x59940025, 0x80040400,
-	0x02001800, 0x00100615, 0x4803281f, 0x480b2820,
-	0x4a03281e, 0x00000001, 0x80000580, 0x1c01f000,
-	0x59940022, 0x80000540, 0x0402000a, 0x59940025,
-	0x80040400, 0x02001800, 0x00100615, 0x48032822,
-	0x480b2823, 0x4a032821, 0x0000000a, 0x80000580,
-	0x1c01f000, 0x4c000000, 0x59940005, 0x4803c857,
-	0x480bc857, 0x80080580, 0x04020003, 0x497b2804,
-	0x497b2805, 0x5c000000, 0x1c01f000, 0x4c000000,
-	0x59940020, 0x4803c857, 0x480bc857, 0x80080580,
-	0x04020003, 0x497b281f, 0x497b2820, 0x5c000000,
-	0x1c01f000, 0x4c000000, 0x59940023, 0x4803c857,
-	0x480bc857, 0x80080580, 0x04020003, 0x497b2822,
-	0x497b2823, 0x5c000000, 0x1c01f000, 0x4937c857,
-	0x48ebc857, 0x59340203, 0x80e80480, 0x04001002,
-	0x48ea6a03, 0x1c01f000, 0x5c03e000, 0x1c01f000,
-	0x4d440000, 0x42007800, 0x00000010, 0x59968801,
-	0x0201f800, 0x00020267, 0x04020012, 0x59341a03,
-	0x800c1840, 0x0400100f, 0x59940027, 0x800c0480,
-	0x04000003, 0x48026a03, 0x0402100a, 0x5934000f,
-	0x497a6a03, 0x80000540, 0x04000006, 0x4c3c0000,
-	0x5934140b, 0x0201f800, 0x00020275, 0x5c007800,
-	0x81468800, 0x83440480, 0x00000800, 0x04021007,
-	0x803c7840, 0x040207e7, 0x49472801, 0x5c028800,
-	0x5c03e000, 0x1c01f000, 0x4a032800, 0x00000002,
-	0x497b2801, 0x0401f7fa, 0x42007800, 0x00000010,
-	0x59966002, 0x59300205, 0x80000d40, 0x04000006,
-	0x59940027, 0x80040480, 0x48026205, 0x0400102d,
-	0x0400002c, 0x59300206, 0x80000d40, 0x04000014,
-	0x59b800e4, 0x8c000524, 0x04020011, 0x4a0370e4,
-	0x00030000, 0x40000000, 0x59b800e4, 0x8c000524,
-	0x04000004, 0x4a0370e4, 0x00020000, 0x0401f008,
-	0x59940027, 0x80040480, 0x48026206, 0x4a0370e4,
-	0x00020000, 0x0400101c, 0x0400001b, 0x83326400,
-	0x00000024, 0x49332802, 0x41540000, 0x81300480,
-	0x04021005, 0x803c7840, 0x040207db, 0x5c03e000,
-	0x1c01f000, 0x59940026, 0x48032827, 0x4a032802,
-	0x0010cfc0, 0x497b2826, 0x80000540, 0x0400000f,
-	0x4a032800, 0x00000001, 0x5c03e000, 0x1c01f000,
-	0x4c3c0000, 0x0201f800, 0x00108f92, 0x5c007800,
-	0x0401f7d1, 0x4c3c0000, 0x0201f800, 0x00108b11,
-	0x5c007800, 0x0401f7e2, 0x4a032800, 0x00000000,
-	0x5c03e000, 0x1c01f000, 0x59a8086b, 0x8c040d30,
-	0x04020029, 0x8c040d32, 0x0400000f, 0x59a80069,
-	0x81640480, 0x04001019, 0x59a8000b, 0x81500580,
-	0x04000005, 0x59a8006a, 0x59a81066, 0x80080580,
-	0x04020012, 0x900411c0, 0x82081500, 0x00007000,
-	0x0401f012, 0x82040500, 0x0000001f, 0x04000016,
-	0x80040840, 0x82040500, 0x0000001f, 0x04000003,
-	0x4807506b, 0x0401f010, 0x900401c0, 0x82000500,
-	0x0000001f, 0x80040d40, 0x900401c0, 0x80040580,
-	0x82001500, 0x00007000, 0x82040500, 0xffff8fff,
-	0x80080540, 0x4803506b, 0x80081114, 0x0201f800,
-	0x00100728, 0x1c01f000, 0x4a032807, 0x000007d0,
-	0x4a032806, 0x0000000a, 0x1c01f000, 0x42000800,
-	0x000007d0, 0x83180480, 0x00000005, 0x02021800,
-	0x00100615, 0x83947c00, 0x00000009, 0x83180400,
-	0x00105c7c, 0x50000000, 0x803c7c00, 0x48047801,
-	0x4a007800, 0x0000000a, 0x1c01f000, 0x83180480,
-	0x00000005, 0x02021800, 0x00100615, 0x83947c00,
-	0x00000009, 0x83180400, 0x00105c7c, 0x50000000,
-	0x803c7c00, 0x49787801, 0x1c01f000, 0x4807c857,
-	0x480bc857, 0x59940025, 0x80040400, 0x02001800,
-	0x00100615, 0x48032804, 0x480b2805, 0x4a032803,
-	0x0000000a, 0x1c01f000, 0x4807c857, 0x480bc857,
-	0x59940025, 0x80040400, 0x02001800, 0x00100615,
-	0x4803281c, 0x480b281d, 0x4a03281b, 0x0000000a,
-	0x1c01f000, 0x4c000000, 0x5994001d, 0x4803c857,
-	0x480bc857, 0x80080580, 0x04020003, 0x4803281c,
-	0x4803281d, 0x5c000000, 0x1c01f000, 0x4807c857,
-	0x480bc857, 0x59940025, 0x80040400, 0x02001800,
-	0x00100615, 0x48032822, 0x480b2823, 0x4a032821,
-	0x0000000a, 0x1c01f000, 0x80e9d1c0, 0x0400000e,
-	0x0401f832, 0x04025000, 0x4203e000, 0x80000000,
-	0x40e81000, 0x41780800, 0x42000000, 0x00000064,
-	0x0201f800, 0x001063ee, 0x59940024, 0x80080400,
-	0x48032824, 0x1c01f000, 0x42001000, 0x00104d39,
-	0x0401fee5, 0x42001000, 0x00104d2c, 0x0401ffd6,
-	0x42001000, 0x00103f62, 0x0401fedf, 0x42001000,
-	0x00103fe4, 0x0401fedc, 0x42001000, 0x00103f37,
-	0x0401fed9, 0x42001000, 0x0010401b, 0x0401f6ea,
-	0x4203e000, 0x70000000, 0x4203e000, 0xb0300000,
-	0x40ebf800, 0x42000000, 0x0000003c, 0x04004004,
-	0x80000040, 0x040207fe, 0x0401f007, 0x4203e000,
-	0x70000000, 0x42000000, 0x0010b67d, 0x0201f800,
-	0x0010a86e, 0x1c01f000, 0x4203e000, 0x80000000,
-	0x4203e000, 0xb0400000, 0x40ebf800, 0x42000000,
-	0x0000003c, 0x04005004, 0x80000040, 0x040207fe,
-	0x0401f007, 0x4203e000, 0x80000000, 0x42000000,
-	0x0010b67e, 0x0201f800, 0x0010a86e, 0x1c01f000,
-	0x59a8000e, 0x82000480, 0x00000100, 0x599c0a02,
-	0x800409c0, 0x04020002, 0x80040800, 0x80041480,
-	0x04001002, 0x40000800, 0x48075067, 0x59a8100e,
-	0x40040000, 0x800acc80, 0x4967500e, 0x49675069,
-	0x59aaa80b, 0x41640800, 0x42001000, 0x00000024,
-	0x0201f800, 0x001063cf, 0x8206a400, 0x0010cfc0,
-	0x49535065, 0x4152b000, 0x42006000, 0x0010bc64,
-	0x4a006004, 0x0000012c, 0x4a006005, 0xda10da10,
-	0x4a006008, 0x00000011, 0x4a006009, 0x0010bc64,
-	0x4a00600a, 0x00101108, 0x599c0014, 0x48006011,
-	0x599c0015, 0x48006012, 0x42006000, 0x0010bc40,
-	0x4a006203, 0x00000008, 0x4a006406, 0x00000006,
-	0x4a006002, 0xffff0000, 0x4a006008, 0x0010bc64,
-	0x4a006014, 0x0010bc64, 0x599c0014, 0x48006015,
-	0x599c0015, 0x48006016, 0x599c0413, 0x48006017,
-	0x49506018, 0x49546019, 0x59a80067, 0x4800601a,
-	0x4a00601b, 0x0010b265, 0x4a00601c, 0x0010b266,
-	0x4a00601d, 0x0010b26a, 0x42000000, 0xb0000000,
-	0x42000800, 0x0010bc40, 0x0201f800, 0x00100bb2,
-	0x1c01f000, 0x82000d00, 0x000000c0, 0x04000004,
-	0x82040d80, 0x000000c0, 0x04020055, 0x82000d00,
-	0x00002020, 0x59300414, 0x84000512, 0x82040d80,
-	0x00002020, 0x0400000b, 0x8c000514, 0x0402000f,
-	0x48026414, 0x813e79c0, 0x02020000, 0x00020804,
-	0x42027000, 0x00000043, 0x0201f000, 0x000208d8,
-	0x59326809, 0x59340a00, 0x8c040d0a, 0x040007f3,
-	0x84000552, 0x0401f7f1, 0x84000514, 0x592c080d,
-	0x48066015, 0x0401f7ef, 0x59326809, 0x59340a00,
-	0x8c040d0a, 0x02000000, 0x00020817, 0x59300c14,
-	0x84040d52, 0x48066414, 0x0201f000, 0x00020817,
-	0x0201f800, 0x00020087, 0x813e79c0, 0x02020000,
-	0x00020804, 0x0201f000, 0x00020825, 0x8c00051e,
-	0x02000000, 0x00020831, 0x82000d00, 0x00002020,
-	0x82040d80, 0x00002020, 0x04000014, 0x82000500,
-	0x000000c0, 0x82000d80, 0x00000080, 0x04000008,
-	0x813e79c0, 0x02020000, 0x00020804, 0x42027000,
-	0x00000041, 0x0201f000, 0x000208d8, 0x813e79c0,
-	0x02020000, 0x00020804, 0x42027000, 0x00000043,
-	0x0201f000, 0x000208d8, 0x59326809, 0x59340a00,
-	0x8c040d0a, 0x040007ea, 0x59300c14, 0x84040d52,
-	0x48066414, 0x0401f7e6, 0x492fc857, 0x42000800,
-	0x00000006, 0x0201f000, 0x0002082c, 0x492fc857,
-	0x42000800, 0x00000004, 0x0201f000, 0x0002082c,
-	0x4807c856, 0x59a80068, 0x800409c0, 0x04000003,
-	0x80080540, 0x0401f002, 0x80080500, 0x48035068,
-	0x1c01f000, 0x4a030800, 0x00000000, 0x4a030802,
-	0x00000001, 0x497b0803, 0x497b0804, 0x1c01f000,
-	0x59840002, 0x8c000500, 0x04000004, 0x84000500,
-	0x4a030800, 0x00000001, 0x84000544, 0x84000506,
-	0x48030802, 0x82000d00, 0x0fffffff, 0x42000000,
-	0x90000000, 0x0201f800, 0x00100bde, 0x59a80069,
-	0x82000480, 0x00000007, 0x48035069, 0x80000580,
-	0x42000800, 0x0010b315, 0x48000800, 0x48000801,
-	0x1c01f000, 0x59a80069, 0x82000400, 0x00000007,
-	0x48035069, 0x1c01f000, 0x83640480, 0x00000008,
-	0x0400101b, 0x58c80a03, 0x80000580, 0x82000400,
-	0x00000008, 0x80040840, 0x040207fd, 0x815c0480,
-	0x04001013, 0x4200b000, 0x00000007, 0x0201f800,
-	0x00020892, 0x4a026203, 0x00000004, 0x4a026406,
-	0x00000009, 0x4a026203, 0x00000004, 0x4a026007,
-	0x00000101, 0x0401f809, 0x0401f880, 0x8058b040,
-	0x040207f3, 0x80000580, 0x1c01f000, 0x82000540,
-	0x00000001, 0x0401f7fd, 0x0201f800, 0x0010082a,
-	0x492e6008, 0x58c80a03, 0x4a025a04, 0x0000002c,
-	0x497a5800, 0x497a5801, 0x497a5c04, 0x497a5c06,
-	0x497a5805, 0x4a025a08, 0x00000005, 0x4a025a07,
-	0x00000002, 0x58c80201, 0x48025c04, 0x58c80202,
-	0x48025c07, 0x58c80204, 0x48025c08, 0x4a02580d,
-	0x0000ffff, 0x80040840, 0x0400000c, 0x412c2000,
-	0x0201f800, 0x0010082a, 0x4a025a04, 0x0000000a,
-	0x497a5c04, 0x48125800, 0x492c2001, 0x412c2000,
-	0x80040840, 0x040207f7, 0x1c01f000, 0x4d7c0000,
-	0x4202f800, 0x00000010, 0x4df00000, 0x4203e000,
-	0x50000000, 0x59847803, 0x803c79c0, 0x0400001e,
-	0x4c5c0000, 0x583cb808, 0x585c3408, 0x801831c0,
-	0x0400000b, 0x0401f84a, 0x04000016, 0x42001000,
-	0x0010b315, 0x0401f87f, 0x04000012, 0x0201f800,
-	0x00100819, 0x0400000f, 0x492cb805, 0x585c0005,
-	0x80000540, 0x02000800, 0x00100615, 0x0401f830,
-	0x585c5408, 0x0401f80b, 0x5c00b800, 0x5c03e000,
-	0x817ef840, 0x040207e1, 0x5c02f800, 0x1c01f000,
-	0x5c00b800, 0x5c03e000, 0x5c02f800, 0x1c01f000,
-	0x4803c856, 0x405c6000, 0x802851c0, 0x04000018,
-	0x585c0204, 0x82000d00, 0x0000000f, 0x82040c00,
-	0x0010110d, 0x50044000, 0x4c600000, 0x4c640000,
-	0x4d040000, 0x4020c000, 0x40320800, 0x5984c804,
-	0x4c280000, 0x0401f934, 0x5c005000, 0x40604000,
-	0x41046000, 0x0201f800, 0x001010eb, 0x040207f6,
-	0x5c020800, 0x5c00c800, 0x5c00c000, 0x58c80204,
-	0x4800bc08, 0x0201f800, 0x00020087, 0x4a026007,
-	0x00000101, 0x497a6009, 0x0401f055, 0x4803c856,
-	0x59840003, 0x80026540, 0x04000003, 0x59300000,
-	0x48030803, 0x1c01f000, 0x4803c856, 0x59840003,
-	0x48026000, 0x49330803, 0x1c01f000, 0x58cc0805,
-	0x40180000, 0x80040480, 0x0400100d, 0x82cc0580,
-	0x0010b30a, 0x02020800, 0x00100615, 0x58c80205,
-	0x80040480, 0x0400101d, 0x82000540, 0x00000001,
-	0x1c01f000, 0x80003580, 0x0401f7fe, 0x82cc0580,
-	0x0010b30a, 0x02020800, 0x00100615, 0x58c80400,
-	0x8c000504, 0x040007f8, 0x58c8040b, 0x8c00051e,
-	0x040007f5, 0x8c000500, 0x040207f3, 0x84000540,
-	0x4801940b, 0x42000000, 0x0010b637, 0x0201f800,
-	0x0010a86e, 0x42001000, 0x00008026, 0x0201f800,
-	0x00103857, 0x0401f7e8, 0x58c8040b, 0x8c00051e,
-	0x040007e2, 0x8c000502, 0x040207e0, 0x84000542,
-	0x4801940b, 0x42000000, 0x0010b636, 0x0201f800,
-	0x0010a86e, 0x42001000, 0x00008025, 0x42001800,
-	0x00000000, 0x0201f800, 0x00103857, 0x0401f7d3,
-	0x4803c856, 0x58080000, 0x42001800, 0x00000007,
-	0x58080801, 0x80040480, 0x04020004, 0x400c0000,
-	0x80000540, 0x0401f005, 0x04001003, 0x800c0480,
-	0x0401f002, 0x80000080, 0x1c01f000, 0x4803c856,
-	0x59300008, 0x80000d40, 0x02000800, 0x00100615,
-	0x58040005, 0x80000540, 0x02000800, 0x00100615,
-	0x59300007, 0x82000500, 0x00000101, 0x82000580,
-	0x00000101, 0x02020800, 0x00100615, 0x42001000,
-	0x0010b315, 0x58080801, 0x82040400, 0x0010b317,
-	0x497a6414, 0x4a026015, 0x0000ffff, 0x45300000,
-	0x80040800, 0x82040480, 0x00000008, 0x04001002,
-	0x80000d80, 0x48041001, 0x82040400, 0x0010b317,
-	0x45780000, 0x1c01f000, 0x4933c857, 0x59300808,
-	0x800409c0, 0x02000800, 0x00100615, 0x4d2c0000,
-	0x58065805, 0x812e59c0, 0x02020800, 0x0010083a,
-	0x49780805, 0x40065800, 0x0201f800, 0x00100843,
-	0x5c025800, 0x4d300000, 0x0201f800, 0x000208b4,
-	0x5c026000, 0x1c01f000, 0x59300406, 0x82000580,
-	0x00000009, 0x04020006, 0x59300007, 0x8c000510,
-	0x04000003, 0x80000580, 0x1c01f000, 0x82000540,
-	0x00000001, 0x1c01f000, 0x59840802, 0x8c040d04,
-	0x1c01f000, 0x4803c856, 0x59840802, 0x84040d04,
-	0x84040d40, 0x4a030800, 0x00000000, 0x48070802,
-	0x82040d00, 0x0fffffff, 0x42000000, 0x90000000,
-	0x0201f000, 0x00100bde, 0x4807c857, 0x4805980a,
-	0x49799801, 0x49799803, 0x49799806, 0x49799807,
-	0x49799808, 0x49799805, 0x49799809, 0x0401f8c8,
-	0x0400000a, 0x0401f8ea, 0x04000008, 0x48359800,
-	0x48359802, 0x48359806, 0x4a019804, 0x00000001,
-	0x4a019807, 0x00000005, 0x1c01f000, 0x4807c857,
-	0x58cc1007, 0x40040000, 0x80080480, 0x04021020,
-	0x4c040000, 0x4c080000, 0x0401f8d9, 0x5c001000,
-	0x5c000800, 0x0400001c, 0x58cc0006, 0x80006540,
-	0x0402000b, 0x48359800, 0x48359802, 0x48359806,
-	0x49799801, 0x49799803, 0x49786801, 0x49786800,
-	0x49799804, 0x49799807, 0x0401f005, 0x48306801,
-	0x48346000, 0x48359806, 0x49786800, 0x58cc0004,
-	0x58cc1007, 0x80000000, 0x82081400, 0x00000005,
-	0x48019804, 0x48099807, 0x0401f7df, 0x80000580,
-	0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000,
-	0x480bc857, 0x4c500000, 0x4c540000, 0x4c580000,
-	0x40083000, 0x58cc0801, 0x82040480, 0x00000005,
-	0x02021800, 0x00100615, 0x82040400, 0x00106150,
-	0x50000000, 0x58cca800, 0x8054ac00, 0x42001800,
-	0x00000005, 0x40040000, 0x800c0480, 0x80082480,
-	0x04021002, 0x40080000, 0x8000b0c2, 0x8058b400,
-	0x5450a800, 0x8050a000, 0x8054a800, 0x8058b040,
-	0x040207fc, 0x40001000, 0x58cc2805, 0x58cc0807,
-	0x58cc2001, 0x80142c00, 0x80040c80, 0x80102400,
-	0x48159805, 0x48059807, 0x48119801, 0x82100580,
-	0x00000005, 0x0400000c, 0x48119801, 0x40080000,
-	0x80181480, 0x40083000, 0x04000003, 0x040217d6,
-	0x80000580, 0x5c00b000, 0x5c00a800, 0x5c00a000,
-	0x1c01f000, 0x58cc0800, 0x800409c0, 0x02000800,
-	0x00100615, 0x58040800, 0x48059800, 0x41782000,
-	0x0401f7ee, 0x0401f812, 0x50600000, 0x81041c00,
-	0x585c0204, 0x4803c857, 0x82000580, 0x0000002c,
-	0x02020800, 0x00100615, 0x58040202, 0x800000e0,
-	0x80640540, 0x48001802, 0x58040000, 0x48001800,
-	0x58040001, 0x48001801, 0x1c01f000, 0x4807c856,
-	0x58cc0005, 0x80000040, 0x02001800, 0x00100615,
-	0x48019805, 0x58cc1003, 0x82080480, 0x00000005,
-	0x02021800, 0x00100615, 0x82080400, 0x00106150,
-	0x50000000, 0x58cc0802, 0x80040c00, 0x80081000,
-	0x82080480, 0x00000005, 0x0402000f, 0x58cc2002,
-	0x58100000, 0x80006d40, 0x04000009, 0x4c340000,
-	0x0401f858, 0x5c006800, 0x49786801, 0x48359802,
-	0x58cc0004, 0x80000040, 0x48019804, 0x49799803,
-	0x0401f002, 0x48099803, 0x1c01f000, 0x4807c856,
-	0x41781800, 0x58c80201, 0x80000540, 0x04000002,
-	0x800c1800, 0x58c80c01, 0x80040c80, 0x0400100a,
-	0x04000009, 0x800c1800, 0x58c80202, 0x80041480,
-	0x04001005, 0x04000004, 0x800c1800, 0x40080800,
-	0x0401f7fb, 0x480d9204, 0x400c0000, 0x42002000,
-	0x00000001, 0x80000040, 0x04000007, 0x04001006,
-	0x80102000, 0x82000480, 0x00000005, 0x04000002,
-	0x040217fc, 0x48119203, 0x1c01f000, 0x4807c856,
-	0x4d2c0000, 0x58cc000a, 0x80000540, 0x02000800,
-	0x00100615, 0x82002400, 0x00000005, 0x0201f800,
-	0x00100819, 0x04000012, 0x492d9809, 0x497a5800,
-	0x497a5801, 0x0201f800, 0x00100819, 0x0400000c,
-	0x58cc0009, 0x48025800, 0x497a5801, 0x492d9809,
-	0x82102480, 0x00000005, 0x040217f7, 0x82000540,
-	0x00000001, 0x5c025800, 0x1c01f000, 0x58cc0009,
-	0x80025d40, 0x040007fc, 0x592c2000, 0x0201f800,
-	0x0010083a, 0x40100000, 0x0401f7fa, 0x58cc0009,
-	0x48cfc857, 0x80006d40, 0x04000005, 0x50340000,
-	0x48019809, 0x49786800, 0x49786801, 0x1c01f000,
-	0x4813c857, 0x58cc0009, 0x48002000, 0x48119809,
-	0x1c01f000, 0x4807c856, 0x4d2c0000, 0x58cc0009,
-	0x80025d40, 0x04000007, 0x592c0000, 0x4c000000,
-	0x0201f800, 0x0010083a, 0x5c000000, 0x0401f7f9,
-	0x5c025800, 0x1c01f000, 0x4807c856, 0x4d2c0000,
-	0x58cc0002, 0x80025d40, 0x04000007, 0x592c0000,
-	0x4c000000, 0x0201f800, 0x0010083a, 0x5c000000,
-	0x0401f7f9, 0x49799800, 0x49799802, 0x49799801,
-	0x49799803, 0x49799806, 0x49799807, 0x49799808,
-	0x49799809, 0x4979980a, 0x5c025800, 0x1c01f000,
-	0x00000003, 0x00000006, 0x00000009, 0x0000000c,
-	0x0000000f, 0x00000012, 0x4803c856, 0x0401f857,
-	0x4a00c204, 0x0000003c, 0x59301009, 0x82080580,
-	0x0010b320, 0x04000013, 0x58080802, 0x82040d00,
-	0x00ffffff, 0x58080403, 0x4804c005, 0x4800c406,
-	0x4a00c207, 0x00000003, 0x59300811, 0x585c0404,
-	0x4978c206, 0x4804c407, 0x80000540, 0x0400000d,
-	0x58600206, 0x84000540, 0x4800c206, 0x0401f009,
-	0x585c080a, 0x82040d00, 0x00ffffff, 0x4804c005,
-	0x4a00c406, 0x000007ff, 0x4978c207, 0x0401f7ef,
-	0x82603c00, 0x00000008, 0x58605404, 0x40282000,
-	0x405c6000, 0x585c0a04, 0x82040d00, 0x0000000f,
-	0x82040c00, 0x0010110d, 0x50044000, 0x80004d80,
-	0x50200000, 0x80307400, 0x58380402, 0x8c244d00,
-	0x04020003, 0x48003a00, 0x0401f003, 0x48003c00,
-	0x801c3800, 0x80244800, 0x80102040, 0x04000006,
-	0x0201f800, 0x001010eb, 0x02000800, 0x00100615,
-	0x0401f7f0, 0x1c01f000, 0x4803c856, 0x4d340000,
-	0x59300009, 0x80026d40, 0x02000800, 0x00100615,
-	0x59340401, 0x80000540, 0x0400000e, 0x59840000,
-	0x80000540, 0x0400000b, 0x836c0580, 0x00000003,
-	0x04020008, 0x59341c03, 0x42002000, 0x00000004,
-	0x42003000, 0x00000004, 0x0201f800, 0x001038c7,
-	0x5c026800, 0x1c01f000, 0x4803c856, 0x80001580,
-	0x58c80c01, 0x59300011, 0x80040c80, 0x48066011,
-	0x58c80201, 0x80000540, 0x04000005, 0x80081000,
-	0x80040c80, 0x04001007, 0x04000006, 0x58c80202,
-	0x80081000, 0x80040c80, 0x04001002, 0x040207fd,
-	0x4808bc08, 0x4808c404, 0x1c01f000, 0x4803c856,
-	0x4a0370e5, 0x00020000, 0x59b800e5, 0x8c000524,
-	0x040207fc, 0x4a0370e5, 0x00030000, 0x40000000,
-	0x40000000, 0x59b800e5, 0x8c000524, 0x040207f5,
-	0x5934000e, 0x80006d40, 0x04000010, 0x81300580,
-	0x04020004, 0x58340000, 0x4802680e, 0x0401f00a,
-	0x40347800, 0x58340000, 0x80006d40, 0x02000800,
-	0x00100615, 0x81300580, 0x040207fa, 0x58340000,
-	0x48007800, 0x497a6000, 0x4a0370e5, 0x00020000,
-	0x1c01f000, 0x4803c856, 0x4d300000, 0x4d2c0000,
-	0x42000800, 0x000003ff, 0x4a0370e5, 0x00020000,
-	0x59b800e5, 0x8c000524, 0x04000005, 0x80040840,
-	0x040207fa, 0x0201f800, 0x00100615, 0x4a0370e5,
-	0x00030000, 0x40000000, 0x40000000, 0x59b800e5,
-	0x8c000524, 0x040207f1, 0x5934000e, 0x80026540,
-	0x0400000e, 0x4933c857, 0x59300000, 0x4802680e,
-	0x4a026203, 0x00000004, 0x497a6206, 0x497a6009,
-	0x4a026007, 0x00000101, 0x59325808, 0x497a5c08,
-	0x0401fd82, 0x0401f7f1, 0x4a0370e5, 0x00020000,
-	0x5c025800, 0x5c026000, 0x1c01f000, 0x4803c856,
-	0x4c000000, 0x0201f800, 0x001059b9, 0x04020011,
-	0x0201f800, 0x001043fc, 0x02020800, 0x00100615,
-	0x5c000000, 0x48026802, 0x0201f800, 0x00020892,
-	0x04000009, 0x49366009, 0x4a026406, 0x00000001,
-	0x42027000, 0x00000001, 0x0201f000, 0x000208d8,
-	0x5c000000, 0x1c01f000, 0x59300203, 0x82000c80,
-	0x0000000e, 0x02021800, 0x00100615, 0x4803c857,
-	0x0c01f001, 0x0010623b, 0x0010623b, 0x0010623b,
-	0x0010623d, 0x0010629d, 0x0010623b, 0x0010623b,
-	0x001062ef, 0x001062f0, 0x0010623b, 0x0010623b,
-	0x0010623b, 0x0010623b, 0x0010623b, 0x0201f800,
-	0x00100615, 0x493bc857, 0x83380480, 0x00000050,
-	0x02021800, 0x00100615, 0x83380480, 0x00000049,
-	0x02001800, 0x00100615, 0x0c01f001, 0x00106250,
-	0x00106272, 0x0010624e, 0x0010624e, 0x0010624e,
-	0x0010624e, 0x00106281, 0x0201f800, 0x00100615,
-	0x4d2c0000, 0x59325808, 0x592c0206, 0x48025c06,
-	0x4a025a06, 0x00000000, 0x4c5c0000, 0x592cbc0a,
-	0x592c0000, 0x48026008, 0x0201f800, 0x00020385,
-	0x59300008, 0x80000540, 0x04000008, 0x4a026203,
-	0x00000007, 0x42027000, 0x00000043, 0x5c00b800,
-	0x5c025800, 0x0401f08a, 0x8c5cbd08, 0x04020006,
-	0x4a026203, 0x00000007, 0x497a6206, 0x497a6008,
-	0x0401f003, 0x0201f800, 0x000208b4, 0x5c00b800,
-	0x5c025800, 0x1c01f000, 0x0201f800, 0x001068c1,
-	0x4d2c0000, 0x59325808, 0x0201f800, 0x00108df4,
-	0x04000006, 0x4d400000, 0x42028000, 0x00000001,
-	0x0401f90e, 0x5c028000, 0x5c025800, 0x0201f000,
-	0x000208b4, 0x0201f800, 0x001068c1, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x42003000, 0x00000014, 0x0201f800, 0x0010a766,
-	0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e,
-	0x4d2c0000, 0x59325808, 0x0201f800, 0x00108df4,
-	0x04000006, 0x4d400000, 0x42028000, 0x00000029,
-	0x0401f8f2, 0x5c028000, 0x5c025800, 0x0201f000,
-	0x000208b4, 0x493bc857, 0x497a6206, 0x83380480,
-	0x00000054, 0x02021800, 0x00100615, 0x83380480,
-	0x00000047, 0x02001800, 0x00100615, 0x0c01f001,
-	0x001062ee, 0x001062b7, 0x001062b5, 0x001062b5,
-	0x001062b5, 0x001062b5, 0x001062b5, 0x001062b5,
-	0x001062b5, 0x001062b5, 0x001062b5, 0x001062b5,
-	0x001062bb, 0x0201f800, 0x00100615, 0x59300011,
-	0x82000500, 0xffff0000, 0x04020034, 0x59840802,
-	0x8c040d04, 0x04000025, 0x59300009, 0x80026d40,
-	0x0400001f, 0x4c5c0000, 0x4c600000, 0x497a6206,
-	0x5930b808, 0x585c0005, 0x8000c540, 0x02000800,
-	0x00100615, 0x0401fe8d, 0x40625800, 0x0201f800,
-	0x00020385, 0x4978b805, 0x0401fef5, 0x497a6009,
-	0x585c3408, 0x0401fcbe, 0x0400000e, 0x42001000,
-	0x0010b315, 0x0401fcf3, 0x0400000a, 0x0201f800,
-	0x0010082a, 0x04000007, 0x492cb805, 0x585c5408,
-	0x0401fc84, 0x5c00c000, 0x5c00b800, 0x1c01f000,
-	0x0401fcaa, 0x0401f7fc, 0x8c040d06, 0x040207fc,
-	0x59300009, 0x80026d40, 0x04000006, 0x5934000e,
-	0x80000540, 0x02020800, 0x00100615, 0x497a6009,
-	0x0401fd0e, 0x0401f7f2, 0x0401f085, 0x4803c856,
-	0x4803c856, 0x83380580, 0x00000043, 0x02020800,
-	0x00100615, 0x4a026203, 0x00000003, 0x493a6403,
-	0x59325808, 0x592c000f, 0x48026011, 0x497a6013,
-	0x592c0406, 0x800000c2, 0x800010c4, 0x80081400,
-	0x480a6206, 0x0201f800, 0x00100f9c, 0x42000800,
-	0x80000060, 0x0401f161, 0x42000000, 0x0010b674,
-	0x0201f800, 0x0010a86e, 0x59300203, 0x82000c80,
-	0x0000000e, 0x02021800, 0x00100615, 0x4803c857,
-	0x82000d80, 0x00000003, 0x04000006, 0x82000d80,
-	0x00000004, 0x0400005b, 0x0201f800, 0x00100615,
-	0x0201f800, 0x0010698c, 0x59300004, 0x8c00053e,
-	0x04020007, 0x0201f800, 0x001068a3, 0x02020800,
-	0x00100615, 0x0201f000, 0x00106982, 0x0401f9d3,
-	0x0201f800, 0x00106982, 0x59325808, 0x42028000,
-	0x00000006, 0x0401f861, 0x0201f000, 0x000208b4,
-	0x4803c856, 0x59300203, 0x82000c80, 0x0000000e,
-	0x02021800, 0x00100615, 0x82000d80, 0x00000002,
-	0x04000009, 0x82000d80, 0x00000003, 0x04000019,
-	0x82000d80, 0x00000004, 0x04000036, 0x0201f800,
-	0x00100615, 0x4933c857, 0x4d2c0000, 0x59325808,
-	0x812e59c0, 0x02000800, 0x00100615, 0x592c1a08,
-	0x8c0c1d0e, 0x02000800, 0x00100615, 0x4d400000,
-	0x42028000, 0x00000001, 0x0401f840, 0x0201f800,
-	0x00107698, 0x5c028000, 0x5c025800, 0x1c01f000,
-	0x4933c857, 0x0201f800, 0x0010698c, 0x4df00000,
-	0x59300004, 0x8c00053e, 0x04020006, 0x0201f800,
-	0x00106cb4, 0x02020800, 0x00100615, 0x0401f010,
-	0x0201f800, 0x00108a8a, 0x04020004, 0x0201f800,
-	0x00106bb2, 0x0402000a, 0x0401f994, 0x02020800,
-	0x00100615, 0x5c03e000, 0x02000800, 0x00106982,
-	0x82000540, 0x00000001, 0x1c01f000, 0x5c03e000,
-	0x02000800, 0x00106982, 0x80000580, 0x1c01f000,
-	0x4933c857, 0x0201f800, 0x00100ee4, 0x4933c857,
-	0x4c5c0000, 0x4d340000, 0x497a6206, 0x5930b808,
-	0x59300009, 0x80026d40, 0x04020e49, 0x42001000,
-	0x0010b315, 0x0401fc4b, 0x04000009, 0x58c80204,
-	0x4800bc08, 0x41785000, 0x0201f800, 0x00105f60,
-	0x5c026800, 0x5c00b800, 0x1c01f000, 0x4978bc08,
-	0x0401fc02, 0x0401f7fb, 0x4803c856, 0x0201f800,
-	0x00108df4, 0x0400000f, 0x592c0000, 0x80000d40,
-	0x04000009, 0x497a5800, 0x49425a06, 0x4c040000,
-	0x0201f800, 0x00020381, 0x5c000800, 0x40065800,
-	0x0401f7f6, 0x49425a06, 0x0201f800, 0x00020381,
-	0x1c01f000, 0x4933c857, 0x59300c06, 0x82040580,
-	0x0000000e, 0x04000004, 0x82040580, 0x00000009,
-	0x04020004, 0x0401ffe5, 0x497a6008, 0x80000580,
-	0x1c01f000, 0x592e6009, 0x83300480, 0x0010cfc0,
-	0x04001016, 0x41580000, 0x81300480, 0x04021013,
-	0x40040000, 0x59300c06, 0x80040580, 0x04020012,
-	0x59300a03, 0x82040580, 0x00000007, 0x02020800,
-	0x00100615, 0x59300008, 0x80000540, 0x02020800,
-	0x00100615, 0x0201f800, 0x000208b4, 0x42000000,
-	0x00000000, 0x0401f009, 0x42000000, 0x00000008,
-	0x0401f006, 0x82040580, 0x00000007, 0x040207fb,
-	0x42000000, 0x00000005, 0x592c0a06, 0x48065c06,
-	0x48025a06, 0x0201f000, 0x00020381, 0x4c0c0000,
-	0x4c100000, 0x4c140000, 0x4c180000, 0x80001d80,
-	0x80002580, 0x42003000, 0x00000020, 0x82040500,
-	0x00000001, 0x04000003, 0x40080000, 0x800c1c00,
-	0x400c2800, 0x800c1902, 0x80102102, 0x82140500,
-	0x00000001, 0x04000003, 0x82102540, 0x80000000,
-	0x80040902, 0x80183040, 0x040207f1, 0x40100800,
-	0x400c0000, 0x5c003000, 0x5c002800, 0x5c002000,
-	0x5c001800, 0x1c01f000, 0x4c580000, 0x4200b000,
-	0x00000020, 0x80000540, 0x04000018, 0x80041c80,
-	0x04021016, 0x800810c2, 0x80040982, 0x04001006,
-	0x80041c80, 0x04021005, 0x8058b040, 0x040207fa,
-	0x0401f006, 0x80041c80, 0x400c0800, 0x80081000,
-	0x8058b040, 0x040207f4, 0x4c000000, 0x41f00000,
-	0x82000500, 0xf7ffffff, 0x4003e000, 0x5c000000,
-	0x5c00b000, 0x1c01f000, 0x4c000000, 0x41f00000,
-	0x82000540, 0x08000000, 0x0401f7f8, 0x42007000,
-	0x0010b33f, 0x4a007000, 0x00000005, 0x4a007401,
-	0x00000000, 0x4a007202, 0x00000840, 0x4a0378e8,
-	0x00000000, 0x4a03c821, 0x00000010, 0x4a03c823,
-	0x00000004, 0x0401f81d, 0x4a0378e9, 0x00003a0d,
-	0x4a0378e8, 0x00000001, 0x42000800, 0x00000005,
-	0x4203a000, 0x00007600, 0x4a03a005, 0xd0000001,
-	0x59d00006, 0x4a03a005, 0x90000001, 0x83d3a400,
-	0x00000020, 0x80040840, 0x040207fa, 0x59e00003,
-	0x82000500, 0xffffffe0, 0x82000540, 0x00008000,
-	0x4803c003, 0x59c40006, 0x82000500, 0xfffcffff,
-	0x48038806, 0x1c01f000, 0x4d900000, 0x4d180000,
-	0x4a0378e7, 0xaaaaaaaa, 0x4a0378e6, 0xaaaaaaaa,
-	0x4a0378e5, 0xaaaaaaaa, 0x4a0378e4, 0xaaaaaaaa,
-	0x4a03781a, 0x0010b5d2, 0x4a03781b, 0x0010110d,
-	0x4a03781c, 0x0010111d, 0x4a031800, 0x00000000,
-	0x4a031801, 0x0010b342, 0x4a031802, 0x0010b349,
-	0x42000800, 0x0010b5d5, 0x417a3000, 0x811b20c8,
-	0x83932400, 0x0000bf32, 0x48072000, 0x4a032001,
-	0x00000000, 0x83180400, 0x00106e41, 0x50000000,
-	0x48032002, 0x82040c00, 0x00000003, 0x811a3000,
-	0x83180480, 0x00000005, 0x040017f1, 0x5c023000,
-	0x5c032000, 0x1c01f000, 0x48066004, 0x497a6000,
-	0x497a6001, 0x59bc00ea, 0x8c000516, 0x040207fe,
-	0x83300400, 0xa0000000, 0x480378e1, 0x1c01f000,
-	0x4933c857, 0x59300804, 0x82040d00, 0x00000100,
-	0x82040d40, 0x80000040, 0x48066004, 0x497a6000,
-	0x59bc00ea, 0x8c000516, 0x040207fe, 0x83300400,
-	0x60000000, 0x480378e1, 0x1c01f000, 0x0201f800,
-	0x0010698c, 0x4df00000, 0x4d300000, 0x4d340000,
-	0x4d2c0000, 0x4d180000, 0x4c5c0000, 0x4c600000,
-	0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
-	0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0,
-	0x0400002c, 0x41302800, 0x4178c000, 0x59300000,
-	0x4c000000, 0x59326809, 0x5930b801, 0x59300406,
-	0x82000d80, 0x00000006, 0x04020003, 0x8d3e7d18,
-	0x04000010, 0x8d3e7d06, 0x04000007, 0x82000580,
-	0x00000003, 0x04020004, 0x59340200, 0x8c00050e,
-	0x04020008, 0x0401f92d, 0x4c0c0000, 0x4c140000,
-	0x0401fb59, 0x5c002800, 0x5c001800, 0x0401f005,
-	0x41301800, 0x8060c1c0, 0x04020002, 0x400cc000,
-	0x805cb9c0, 0x04000003, 0x405e6000, 0x0401f7e3,
-	0x5c026000, 0x813261c0, 0x04000006, 0x8060c1c0,
-	0x04000002, 0x40602800, 0x4178c000, 0x0401f7d8,
-	0x417a3000, 0x0201f800, 0x00106e2f, 0x59926004,
-	0x813261c0, 0x04000023, 0x59326809, 0x4130c000,
-	0x59300001, 0x8000bd40, 0x04000016, 0x40026000,
-	0x40602800, 0x5930b801, 0x59300406, 0x82000d80,
-	0x00000006, 0x0400000e, 0x8d3e7d06, 0x04000007,
-	0x82000580, 0x00000003, 0x04020004, 0x59340200,
-	0x8c00050e, 0x04020006, 0x0401f8da, 0x4c140000,
-	0x0401fb29, 0x5c002800, 0x0401f002, 0x41302800,
-	0x405e6000, 0x813261c0, 0x040207eb, 0x8060c1c0,
-	0x04000004, 0x40626000, 0x4178c000, 0x0401f7e7,
-	0x811a3000, 0x83180480, 0x00000005, 0x040017d6,
-	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
-	0x5c00c000, 0x5c00b800, 0x5c023000, 0x5c025800,
-	0x5c026800, 0x5c026000, 0x5c03e000, 0x02000800,
-	0x00106982, 0x1c01f000, 0x4933c857, 0x0201f800,
-	0x0010698c, 0x4df00000, 0x4d340000, 0x4d180000,
-	0x4d900000, 0x42003000, 0x0000bf2e, 0x59326809,
-	0x58182001, 0x40102800, 0x801021c0, 0x04000016,
-	0x41300000, 0x80100580, 0x04000011, 0x58100009,
-	0x81340580, 0x0402000b, 0x40101800, 0x58102001,
-	0x41300000, 0x801021c0, 0x0400000b, 0x80100d80,
-	0x04000007, 0x40101800, 0x58102001, 0x0401f7fa,
-	0x40102800, 0x58102000, 0x0401f7ec, 0x0401f8bb,
-	0x0401f01a, 0x42032000, 0x0000bf32, 0x417a3000,
-	0x59902004, 0x40102800, 0x801021c0, 0x0400000b,
-	0x58100009, 0x81340580, 0x04020008, 0x41300000,
-	0x80100580, 0x0400000c, 0x40102800, 0x58102001,
-	0x801021c0, 0x040207fa, 0x811a3000, 0x83180480,
-	0x00000005, 0x0402100d, 0x83932400, 0x00000010,
-	0x0401f7ec, 0x0401f87f, 0x5c032000, 0x5c023000,
-	0x5c026800, 0x5c03e000, 0x02000800, 0x00106982,
-	0x80000580, 0x1c01f000, 0x5c032000, 0x5c023000,
-	0x5c026800, 0x5c03e000, 0x02000800, 0x00106982,
-	0x82000540, 0x00000001, 0x1c01f000, 0x0201f800,
-	0x0010698c, 0x4df00000, 0x4d300000, 0x4d340000,
-	0x4d180000, 0x4d2c0000, 0x4c5c0000, 0x4c600000,
-	0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
-	0x42003000, 0x0000bf2e, 0x581a6001, 0x813261c0,
-	0x04000023, 0x41302800, 0x5930b800, 0x59326809,
-	0x59340403, 0x81440580, 0x04000006, 0x805cb9c0,
-	0x0400001b, 0x41302800, 0x405e6000, 0x0401f7f7,
-	0x5930b801, 0x8d3e7d00, 0x04000003, 0x0401fb58,
-	0x0402000e, 0x59300406, 0x82000580, 0x00000006,
-	0x04020003, 0x8d3e7d18, 0x04000008, 0x0401f867,
-	0x4c0c0000, 0x4c140000, 0x0401fa93, 0x5c002800,
-	0x5c001800, 0x0401f002, 0x41301800, 0x405e6000,
-	0x813261c0, 0x040207eb, 0x0401f02d, 0x417a3000,
-	0x0201f800, 0x00106e2f, 0x59926004, 0x813261c0,
-	0x04000005, 0x59326809, 0x59340403, 0x81440580,
-	0x04000006, 0x811a3000, 0x83180480, 0x00000005,
-	0x040017f4, 0x0401f01e, 0x4130c000, 0x59300001,
-	0x8000bd40, 0x04000012, 0x40026000, 0x40602800,
-	0x5930b801, 0x8d3e7d00, 0x04000003, 0x0401fb2c,
-	0x0402000a, 0x59300406, 0x82000580, 0x00000006,
-	0x04000006, 0x0401f81b, 0x4c140000, 0x0401fa6a,
-	0x5c002800, 0x0401f002, 0x41302800, 0x405e6000,
-	0x813261c0, 0x040207ef, 0x8060c1c0, 0x04000004,
-	0x40626000, 0x4178c000, 0x0401f7eb, 0x5c022800,
-	0x5c034800, 0x5c03a000, 0x5c032000, 0x5c00c000,
-	0x5c00b800, 0x5c025800, 0x5c023000, 0x5c026800,
-	0x5c026000, 0x5c03e000, 0x04000bd4, 0x1c01f000,
-	0x0401fbb9, 0x59900004, 0x81300580, 0x04020018,
-	0x4c140000, 0x0201f800, 0x00106b13, 0x0401fba9,
-	0x5c002800, 0x59300001, 0x800001c0, 0x04020003,
-	0x497a680c, 0x1c01f000, 0x42003000, 0x0000bf2e,
-	0x497a6001, 0x58180801, 0x800409c0, 0x04020004,
-	0x48003000, 0x48003001, 0x1c01f000, 0x58180800,
-	0x48000800, 0x48003000, 0x1c01f000, 0x59300001,
-	0x48002801, 0x800001c0, 0x04020002, 0x4816680c,
-	0x497a6001, 0x1c01f000, 0x0401fb97, 0x42003000,
-	0x0000bf2e, 0x58180001, 0x81300580, 0x0402001c,
-	0x59300801, 0x800409c0, 0x0400000e, 0x59300000,
-	0x800001c0, 0x04020005, 0x48043001, 0x48043000,
-	0x497a6001, 0x1c01f000, 0x59300000, 0x48000800,
-	0x48043001, 0x497a6000, 0x497a6001, 0x1c01f000,
-	0x59300800, 0x800409c0, 0x04020005, 0x49783001,
-	0x49783000, 0x497a680c, 0x1c01f000, 0x48043001,
-	0x497a6000, 0x497a680c, 0x1c01f000, 0x58180000,
-	0x81300580, 0x0402000c, 0x59300001, 0x800001c0,
-	0x04020005, 0x48143000, 0x49782800, 0x497a680c,
-	0x1c01f000, 0x48003000, 0x48002800, 0x497a6001,
-	0x1c01f000, 0x59300000, 0x800001c0, 0x04020008,
-	0x59300001, 0x48001801, 0x800001c0, 0x04020002,
-	0x480e680c, 0x497a6001, 0x1c01f000, 0x59300801,
-	0x800409c0, 0x04020006, 0x59300800, 0x48042800,
-	0x497a6000, 0x497a680c, 0x1c01f000, 0x59300000,
-	0x48000800, 0x48042800, 0x497a6000, 0x497a6001,
-	0x1c01f000, 0x0401fb73, 0x4df00000, 0x0401f83a,
-	0x040208c7, 0x0402094a, 0x04020005, 0x5c03e000,
-	0x04000b62, 0x80000580, 0x1c01f000, 0x5c03e000,
-	0x04000b5e, 0x82000540, 0x00000001, 0x1c01f000,
-	0x4d2c0000, 0x4d340000, 0x4d300000, 0x41783000,
-	0x598e6009, 0x813261c0, 0x04000023, 0x59300406,
-	0x82000580, 0x00000006, 0x04020004, 0x8d3e7d18,
-	0x0402000c, 0x0401f019, 0x82040580, 0x00000005,
-	0x04020008, 0x8d3e7d18, 0x04000003, 0x8d3e7d16,
-	0x04000004, 0x59300420, 0x8c000500, 0x0402000f,
-	0x0401fa49, 0x59300000, 0x4c000000, 0x8d3e7d06,
-	0x04000004, 0x0201f800, 0x0010909d, 0x04000005,
-	0x0401f869, 0x4c180000, 0x0401f9b7, 0x5c003000,
-	0x5c026000, 0x0401f7e0, 0x41303000, 0x59326000,
-	0x0401f7dd, 0x5c026000, 0x5c026800, 0x5c025800,
-	0x1c01f000, 0x4933c857, 0x4c5c0000, 0x813261c0,
-	0x02000800, 0x00100615, 0x41300000, 0x598cb809,
-	0x41783000, 0x805cb9c0, 0x04000013, 0x805c0d80,
-	0x04000004, 0x405c3000, 0x5818b800, 0x0401f7fa,
-	0x0401f84d, 0x598c000d, 0x81300580, 0x02000800,
-	0x00106e10, 0x59300403, 0x82000580, 0x00000042,
-	0x04020002, 0x497a6007, 0x80000580, 0x5c00b800,
-	0x1c01f000, 0x82000540, 0x00000001, 0x5c00b800,
-	0x1c01f000, 0x0401fb17, 0x4df00000, 0x4d2c0000,
-	0x4d340000, 0x4d300000, 0x41783000, 0x598e6009,
-	0x813261c0, 0x0400002e, 0x59300c06, 0x82040580,
-	0x00000006, 0x04020004, 0x8d3e7d18, 0x0402000c,
-	0x0401f024, 0x82040580, 0x00000005, 0x04020008,
-	0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004,
-	0x59300420, 0x8c000500, 0x0402001a, 0x59326809,
-	0x59340403, 0x81440580, 0x04020016, 0x8d3e7d00,
-	0x04000006, 0x82040580, 0x00000003, 0x04020011,
-	0x0401fa23, 0x0402000f, 0x0401f9ef, 0x59300000,
-	0x4c000000, 0x8d3e7d06, 0x04000004, 0x0201f800,
-	0x0010909d, 0x04000005, 0x0401f80f, 0x4c180000,
-	0x0401f95d, 0x5c003000, 0x5c026000, 0x0401f7d5,
-	0x41303000, 0x59326000, 0x0401f7d2, 0x5c026000,
-	0x5c026800, 0x5c025800, 0x5c03e000, 0x04000ad3,
-	0x1c01f000, 0x59300800, 0x497a6000, 0x0401fab6,
-	0x801831c0, 0x04020009, 0x598c0008, 0x81300580,
-	0x04020004, 0x48031808, 0x48031809, 0x0401f008,
-	0x48071809, 0x0401f006, 0x48043000, 0x598c0008,
-	0x81300580, 0x04020002, 0x481b1808, 0x0401f2b8,
-	0x4d2c0000, 0x4d300000, 0x4d340000, 0x41783000,
-	0x598e600b, 0x813261c0, 0x04000013, 0x8d3e7d06,
-	0x04000005, 0x59326809, 0x59340200, 0x8c00050e,
-	0x0402000a, 0x0401f9b8, 0x59300000, 0x4c000000,
-	0x0401f853, 0x4c180000, 0x0401f92b, 0x5c003000,
-	0x5c026000, 0x0401f7f0, 0x41303000, 0x59326000,
-	0x0401f7ed, 0x0201f800, 0x001045c7, 0x5c026800,
-	0x5c026000, 0x5c025800, 0x1c01f000, 0x4933c857,
-	0x4c5c0000, 0x813261c0, 0x02000800, 0x00100615,
-	0x41300000, 0x598cb80b, 0x41783000, 0x805cb9c0,
-	0x0400000f, 0x805c0d80, 0x04000004, 0x405c3000,
-	0x5818b800, 0x0401f7fa, 0x0401f835, 0x598c000d,
-	0x81300580, 0x02000800, 0x00106e10, 0x497a6007,
-	0x80000580, 0x5c00b800, 0x1c01f000, 0x82000540,
-	0x00000001, 0x5c00b800, 0x1c01f000, 0x0401fa8d,
-	0x4df00000, 0x4d340000, 0x4d300000, 0x4d2c0000,
-	0x0201f800, 0x00020267, 0x02020800, 0x00100615,
-	0x41783000, 0x598e600b, 0x813261c0, 0x04000014,
-	0x59300009, 0x81340580, 0x0402000e, 0x8d3e7d00,
-	0x04000003, 0x0401f9aa, 0x0402000a, 0x0401f976,
-	0x59300000, 0x4c000000, 0x0401f811, 0x4c180000,
-	0x0401f8e9, 0x5c003000, 0x5c026000, 0x0401f7ef,
-	0x41303000, 0x59326000, 0x0401f7ec, 0x0201f800,
-	0x001045ea, 0x5c025800, 0x5c026000, 0x5c026800,
-	0x5c03e000, 0x04000a5d, 0x1c01f000, 0x59300800,
-	0x497a6000, 0x0401fa40, 0x801831c0, 0x04020009,
-	0x598c000a, 0x81300580, 0x04020004, 0x4803180a,
-	0x4803180b, 0x0401f008, 0x4807180b, 0x0401f006,
-	0x48043000, 0x598c000a, 0x81300580, 0x04020002,
-	0x481b180a, 0x0401f242, 0x0401fa52, 0x4df00000,
-	0x4d300000, 0x4c5c0000, 0x4178b800, 0x8d3e7d18,
-	0x04000004, 0x8d3e7d16, 0x04020002, 0x805cb800,
-	0x598e6005, 0x813261c0, 0x0400001a, 0x59300000,
-	0x4c000000, 0x805cb9c0, 0x0402000b, 0x59300c06,
-	0x82040580, 0x00000011, 0x04000010, 0x82040580,
-	0x00000004, 0x04020004, 0x59300420, 0x8c000500,
-	0x0402000a, 0x0201f800, 0x00108f05, 0x02000800,
-	0x00107da6, 0x0201f800, 0x001090ec, 0x0201f800,
-	0x000208b4, 0x0401fa1e, 0x5c026000, 0x0401f7e6,
-	0x497b1805, 0x497b1804, 0x5c00b800, 0x5c026000,
-	0x5c03e000, 0x04000a1d, 0x1c01f000, 0x4933c857,
-	0x4c5c0000, 0x4c600000, 0x813261c0, 0x02000800,
-	0x00100615, 0x41300000, 0x598cb805, 0x405cc000,
-	0x805cb9c0, 0x04000025, 0x805c0d80, 0x04000004,
-	0x405cc000, 0x5860b800, 0x0401f7fa, 0x598c000d,
-	0x81300580, 0x02000800, 0x00106e10, 0x0401f9ee,
-	0x598c0005, 0x805c0580, 0x04020009, 0x585c0000,
-	0x48031805, 0x4978b800, 0x598c0004, 0x805c0580,
-	0x0402000d, 0x497b1804, 0x0401f00b, 0x598c0004,
-	0x805c0580, 0x04020005, 0x48631804, 0x4978b800,
-	0x4978c000, 0x0401f004, 0x585c0000, 0x4800c000,
-	0x4978b800, 0x0401f9ea, 0x80000580, 0x5c00c000,
-	0x5c00b800, 0x1c01f000, 0x82000540, 0x00000001,
-	0x5c00c000, 0x5c00b800, 0x1c01f000, 0x4933c857,
-	0x0401f9f0, 0x4df00000, 0x4d2c0000, 0x4d340000,
-	0x4d300000, 0x4c5c0000, 0x4178b800, 0x8d3e7d18,
-	0x04000004, 0x8d3e7d16, 0x04020002, 0x805cb800,
-	0x41783000, 0x598e6005, 0x813261c0, 0x04000029,
-	0x59326809, 0x813669c0, 0x04000023, 0x59340403,
-	0x81440580, 0x04020020, 0x805cb9c0, 0x0402000b,
-	0x59300c06, 0x82040580, 0x00000011, 0x0400001a,
-	0x82040580, 0x00000004, 0x04020004, 0x59300420,
-	0x8c000500, 0x04020014, 0x0201f800, 0x00108df4,
-	0x04000008, 0x0201f800, 0x00109360, 0x04020005,
-	0x59300403, 0x82000580, 0x00000043, 0x0400000a,
-	0x0401f8c1, 0x59300000, 0x4c000000, 0x0401f810,
-	0x4c180000, 0x0401f834, 0x5c003000, 0x5c026000,
-	0x0401f7da, 0x41303000, 0x59326000, 0x0401f7d7,
-	0x5c00b800, 0x5c026000, 0x5c026800, 0x5c025800,
-	0x5c03e000, 0x040009a9, 0x1c01f000, 0x59300800,
-	0x497a6000, 0x0401f98c, 0x801831c0, 0x04020009,
-	0x598c0004, 0x81300580, 0x04020004, 0x48031804,
-	0x48031805, 0x0401f008, 0x48071805, 0x0401f006,
-	0x48043000, 0x598c0004, 0x81300580, 0x04020002,
-	0x481b1804, 0x0401f18e, 0x4943c857, 0x0401f99d,
-	0x4df00000, 0x0401fe37, 0x0401fed2, 0x5c03e000,
-	0x0400098e, 0x1c01f000, 0x4947c857, 0x0401f995,
-	0x4df00000, 0x4d3c0000, 0x853e7d00, 0x0401fe7a,
-	0x0401ff03, 0x5c027800, 0x5c03e000, 0x04000983,
-	0x1c01f000, 0x5c000000, 0x4c000000, 0x4803c857,
-	0x4d340000, 0x4d2c0000, 0x59326809, 0x59325808,
-	0x59300406, 0x82000c80, 0x00000012, 0x02021800,
-	0x00100615, 0x4933c857, 0x4943c857, 0x493fc857,
-	0x4803c857, 0x0c01f804, 0x5c025800, 0x5c026800,
-	0x1c01f000, 0x00106827, 0x00106829, 0x00106833,
-	0x0010684d, 0x00106829, 0x0010683d, 0x00106865,
-	0x00106827, 0x00106827, 0x00106878, 0x0010686f,
-	0x00106827, 0x00106827, 0x00106827, 0x00106827,
-	0x00106827, 0x0010687e, 0x0010687e, 0x0201f800,
-	0x00100615, 0x0201f800, 0x00108ef1, 0x02000800,
-	0x00101e1b, 0x0201f800, 0x001090ec, 0x0201f800,
-	0x00107da6, 0x0201f000, 0x00107698, 0x812e59c0,
-	0x02020800, 0x00100615, 0x5930021d, 0x82000580,
-	0x00000003, 0x02000800, 0x00108ee7, 0x0201f000,
-	0x00107698, 0x0201f800, 0x00108df4, 0x02000000,
-	0x00107698, 0x592c1204, 0x82081500, 0x000000ff,
-	0x82080580, 0x00000055, 0x02020800, 0x00100615,
-	0x49425a06, 0x0201f800, 0x00020381, 0x0201f000,
-	0x00107698, 0x59300004, 0x8400055c, 0x48026004,
-	0x59300007, 0x8c000500, 0x02020800, 0x00100ee4,
-	0x0201f800, 0x00108df4, 0x0400000d, 0x4a025a04,
-	0x00000103, 0x49425a06, 0x497a5c09, 0x0201f800,
-	0x00108f7d, 0x0201f800, 0x0010a4ae, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00108ee7, 0x0201f000,
-	0x00107698, 0x59300007, 0x8c000500, 0x02020800,
-	0x00100ee4, 0x0201f800, 0x00108df4, 0x02020800,
-	0x0010a201, 0x0201f000, 0x00107698, 0x0201f800,
-	0x00108df4, 0x04000005, 0x49425a06, 0x497a5c09,
-	0x0201f800, 0x00020381, 0x0201f000, 0x00107698,
-	0x0201f800, 0x00108df4, 0x02020800, 0x0010639d,
-	0x0201f000, 0x00107698, 0x0201f800, 0x00108df4,
-	0x04000004, 0x49425a06, 0x0201f800, 0x00020381,
-	0x59325817, 0x0201f800, 0x00100843, 0x0201f000,
-	0x00107698, 0x598c000d, 0x81300580, 0x04000003,
-	0x497a6007, 0x1c01f000, 0x59c40004, 0x82000500,
-	0x0000000c, 0x04000005, 0x4a038804, 0x0000000c,
-	0x497b2807, 0x0401f00a, 0x0401fadb, 0x59300403,
-	0x82000d80, 0x00000040, 0x04000004, 0x82000580,
-	0x00000042, 0x04020002, 0x497a6007, 0x0201f800,
-	0x00106e10, 0x80000580, 0x1c01f000, 0x59300804,
-	0x8c040d20, 0x04020004, 0x82000540, 0x00000001,
-	0x1c01f000, 0x4933c857, 0x4d380000, 0x59300804,
-	0x84040d20, 0x48066004, 0x42027000, 0x00000049,
-	0x59300203, 0x82000580, 0x00000003, 0x04000003,
-	0x42027000, 0x00000013, 0x0201f800, 0x000208d8,
-	0x80000580, 0x5c027000, 0x1c01f000, 0x59300017,
-	0x81480580, 0x04020003, 0x59300018, 0x814c0580,
-	0x1c01f000, 0x4d2c0000, 0x4d300000, 0x0401f8c9,
-	0x4df00000, 0x0201f800, 0x00105d9b, 0x59900001,
-	0x82000500, 0x00000003, 0x0c01f001, 0x001068f1,
-	0x001068d1, 0x001068cf, 0x001068cf, 0x0201f800,
-	0x00100615, 0x59926004, 0x0401f88e, 0x813261c0,
-	0x0400001d, 0x59300004, 0x8c000516, 0x04000004,
-	0x59325808, 0x497a5808, 0x497a5809, 0x0401f88e,
-	0x59300001, 0x800001c0, 0x0400000e, 0x497a6001,
-	0x42003000, 0x0000bf2e, 0x58180801, 0x800409c0,
-	0x04020004, 0x48003001, 0x48003000, 0x0401f00a,
-	0x58180800, 0x48000800, 0x48003000, 0x0401f006,
-	0x59300809, 0x800409c0, 0x02000800, 0x00100615,
-	0x4978080c, 0x5c03e000, 0x04000890, 0x5c026000,
-	0x5c025800, 0x1c01f000, 0x4d300000, 0x497b2807,
-	0x0401f894, 0x4df00000, 0x598c0000, 0x82000500,
-	0x00000007, 0x4803c857, 0x0c01f001, 0x00106926,
-	0x00106909, 0x00106912, 0x00106916, 0x00106921,
-	0x00106926, 0x00106907, 0x00106907, 0x0201f800,
-	0x00100615, 0x598c000d, 0x80026540, 0x04000004,
-	0x0401f81e, 0x02020800, 0x00100615, 0x0201f800,
-	0x00106e10, 0x0401f015, 0x0401f827, 0x0201f800,
-	0x00106e10, 0x0401f011, 0x598c000d, 0x80026540,
-	0x0400000e, 0x0401f838, 0x04000004, 0x0401f80f,
-	0x04000002, 0x0401f81c, 0x0201f800, 0x00106e10,
-	0x0401f006, 0x0401f830, 0x02020800, 0x00100615,
-	0x0201f800, 0x00106e10, 0x5c03e000, 0x0400085b,
-	0x5c026000, 0x1c01f000, 0x598c0009, 0x81300580,
-	0x0402000c, 0x0401f84e, 0x0401f83b, 0x59300000,
-	0x800001c0, 0x04000004, 0x48031809, 0x497a6000,
-	0x0401f003, 0x497b1809, 0x497b1808, 0x80000580,
-	0x1c01f000, 0x4d2c0000, 0x59300406, 0x82000580,
-	0x00000003, 0x04020012, 0x598c000b, 0x81300580,
-	0x0402000f, 0x0401f83a, 0x59325808, 0x497a5808,
-	0x497a5809, 0x0401f824, 0x59300000, 0x800001c0,
-	0x04000004, 0x4803180b, 0x497a6000, 0x0401f003,
-	0x497b180a, 0x497b180b, 0x80000580, 0x5c025800,
-	0x1c01f000, 0x598c0005, 0x81300580, 0x0402000c,
-	0x0401f827, 0x0401f814, 0x59300000, 0x800001c0,
-	0x04000004, 0x48031805, 0x497a6000, 0x0401f003,
-	0x497b1805, 0x497b1804, 0x80000580, 0x1c01f000,
-	0x4a032001, 0x00000000, 0x497b2004, 0x497b2005,
-	0x59900006, 0x82000500, 0x0000ffff, 0x48032006,
-	0x1c01f000, 0x4c040000, 0x59300004, 0x82000500,
-	0x7ffeffff, 0x48026004, 0x59bc00e4, 0x8c000514,
-	0x04000009, 0x42000800, 0x0000bf00, 0x58040012,
-	0x81300580, 0x04020004, 0x49780812, 0x4a0378e4,
-	0x00000800, 0x5c000800, 0x1c01f000, 0x4803c856,
-	0x598c000c, 0x80000540, 0x04000003, 0x80000040,
-	0x4803180c, 0x1c01f000, 0x59bc00ea, 0x82000500,
-	0x00000007, 0x82000580, 0x00000003, 0x04020004,
-	0x4803c856, 0x4a0378e8, 0x00000001, 0x1c01f000,
-	0x59bc00ea, 0x82000500, 0x00000007, 0x82000580,
-	0x00000001, 0x04020011, 0x4803c856, 0x42000800,
-	0x00000000, 0x0401f80e, 0x42000800, 0x00001000,
-	0x59bc00ea, 0x82000500, 0x00000007, 0x82000580,
-	0x00000003, 0x04000005, 0x80040840, 0x040207f9,
-	0x0201f800, 0x00100615, 0x1c01f000, 0x59bc00ea,
-	0x82000500, 0x00000007, 0x82000580, 0x00000001,
-	0x02020800, 0x00100615, 0x59bc00ea, 0x8c000516,
-	0x040207fe, 0x480778e1, 0x1c01f000, 0x59bc00ea,
-	0x8c000516, 0x040207fe, 0x480778e1, 0x59bc00ea,
-	0x8c000516, 0x040207fe, 0x480b78e1, 0x1c01f000,
-	0x4a0378e4, 0x00002000, 0x59a8006f, 0x82000500,
-	0x0000000c, 0x04020008, 0x42007000, 0x0010b33f,
-	0x58380401, 0x8c000506, 0x04020003, 0x4a0378e4,
-	0x00080000, 0x1c01f000, 0x82000d00, 0x80000018,
-	0x02020800, 0x0010060d, 0x0201f800, 0x00100615,
-	0x001069dc, 0x00106a81, 0x00106a9b, 0x001069dc,
-	0x001069de, 0x001069ff, 0x00106a1e, 0x00106a53,
-	0x001069dc, 0x00106a7f, 0x001069dc, 0x001069dc,
-	0x001069dc, 0x001069dc, 0x001069dc, 0x001069dc,
-	0x0201f800, 0x00100615, 0x4d300000, 0x4d900000,
-	0x4dd00000, 0x4da40000, 0x4d140000, 0x0201f800,
-	0x00106e2f, 0x59bc00ea, 0x8c000510, 0x040007fe,
-	0x59be60e0, 0x59300004, 0x8c000520, 0x04000011,
-	0x82000500, 0xfffefeff, 0x48026004, 0x4a026203,
-	0x00000003, 0x0401ff9b, 0x0201f800, 0x0010101e,
-	0x5c022800, 0x5c034800, 0x5c03a000, 0x5c032000,
-	0x5c026000, 0x4a0378e4, 0x00000008, 0x0401f787,
-	0x84000510, 0x48026004, 0x0401f7f6, 0x4d300000,
-	0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
-	0x0201f800, 0x00106e2f, 0x59bc00ea, 0x8c000510,
-	0x040007fe, 0x59be60e0, 0x59300004, 0x8c000520,
-	0x0400000f, 0x82000500, 0xfffefeff, 0x48026004,
-	0x0401ff7c, 0x0201f800, 0x0010105c, 0x5c022800,
-	0x5c034800, 0x5c03a000, 0x5c032000, 0x5c026000,
-	0x4a0378e4, 0x00000008, 0x0401f768, 0x84000510,
-	0x48026004, 0x0401f7f6, 0x4d300000, 0x4d2c0000,
-	0x4d340000, 0x4da40000, 0x4cd00000, 0x59bc00ea,
-	0x8c000510, 0x040007fe, 0x59be60e0, 0x813261c0,
-	0x02000800, 0x00100615, 0x59300004, 0x8c000520,
-	0x0400001e, 0x82000500, 0xfffefeff, 0x48026004,
-	0x59326809, 0x42034800, 0x0010b342, 0x04011000,
-	0x4a03c840, 0x0010b349, 0x4a03c842, 0x00000012,
-	0x04011000, 0x4a03c840, 0x0010b35b, 0x4a03c842,
-	0x000000ff, 0x04011000, 0x4a03c840, 0x0010b45a,
-	0x4a03c842, 0x000000ff, 0x0201f800, 0x00106e46,
-	0x5c01a000, 0x5c034800, 0x5c026800, 0x5c025800,
-	0x5c026000, 0x1c01f000, 0x84000510, 0x48026004,
-	0x5c01a000, 0x5c034800, 0x5c026800, 0x5c025800,
-	0x5c026000, 0x1c01f000, 0x1c01f000, 0x4d300000,
-	0x4d2c0000, 0x4d340000, 0x4cd00000, 0x4d900000,
-	0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fbd4,
-	0x59bc00ea, 0x8c000510, 0x040007fe, 0x59be60e0,
-	0x813261c0, 0x02000800, 0x00100615, 0x59300004,
-	0x8c000520, 0x0400000f, 0x82000500, 0xfffefeff,
-	0x48026004, 0x0201f800, 0x001075b9, 0x5c022800,
-	0x5c034800, 0x5c03a000, 0x5c032000, 0x5c01a000,
-	0x5c026800, 0x5c025800, 0x5c026000, 0x1c01f000,
-	0x84000510, 0x48026004, 0x5c022800, 0x5c034800,
-	0x5c03a000, 0x5c032000, 0x5c01a000, 0x5c026800,
-	0x5c025800, 0x5c026000, 0x1c01f000, 0x0201f800,
-	0x00100615, 0x4d300000, 0x4d380000, 0x42000000,
-	0x0010b6c3, 0x0201f800, 0x0010a86e, 0x0401ff05,
-	0x598e600d, 0x59c40004, 0x8c000506, 0x04000004,
-	0x0401f8e5, 0x4a038804, 0x00000008, 0x813261c0,
-	0x04000006, 0x0401fb98, 0x42027000, 0x00000014,
-	0x0201f800, 0x000208d8, 0x4a0378e4, 0x00000002,
-	0x5c027000, 0x5c026000, 0x0401f6e8, 0x4d180000,
-	0x4d300000, 0x4d380000, 0x4d900000, 0x4dd00000,
-	0x4da40000, 0x4d140000, 0x0401feea, 0x417a3000,
-	0x59c40804, 0x83180400, 0x00106df6, 0x50000000,
-	0x80040500, 0x0400001b, 0x42000000, 0x0010b6c4,
-	0x0201f800, 0x0010a86e, 0x0401fb81, 0x59926004,
-	0x0401f863, 0x83180400, 0x00106df6, 0x50000000,
-	0x48038804, 0x813261c0, 0x0400000a, 0x59300004,
-	0x8c00050c, 0x04020003, 0x4a026203, 0x00000003,
-	0x42027000, 0x0000004a, 0x0201f800, 0x000208d8,
-	0x59c40004, 0x82000500, 0x00f80000, 0x04000005,
-	0x811a3000, 0x83180480, 0x00000005, 0x040017dd,
-	0x4a0378e4, 0x00000008, 0x5c022800, 0x5c034800,
-	0x5c03a000, 0x5c032000, 0x5c027000, 0x5c026000,
-	0x5c023000, 0x0401f6b1, 0x4d2c0000, 0x4d340000,
-	0x59326809, 0x598c0800, 0x82040580, 0x00000004,
-	0x04020006, 0x838c1400, 0x00000005, 0x838c1c00,
-	0x00000004, 0x0401f010, 0x82040580, 0x00000001,
-	0x04020006, 0x838c1400, 0x00000009, 0x838c1c00,
-	0x00000008, 0x0401f008, 0x82040580, 0x00000002,
-	0x04020028, 0x838c1400, 0x0000000b, 0x838c1c00,
-	0x0000000a, 0x41306800, 0x58340000, 0x80007d40,
-	0x04000020, 0x583c0009, 0x81340580, 0x04020006,
-	0x403c6800, 0x583c0000, 0x80007d40, 0x040207fa,
-	0x0401f018, 0x4933c857, 0x483fc857, 0x583c0000,
-	0x48006800, 0x49307800, 0x443c1000, 0x500c0000,
-	0x803c0580, 0x04020002, 0x44341800, 0x80000580,
-	0x4803180d, 0x4803180f, 0x598c0000, 0x82000580,
-	0x00000003, 0x04000003, 0x4a031800, 0x00000000,
-	0x80000580, 0x5c026800, 0x5c025800, 0x1c01f000,
-	0x82000540, 0x00000001, 0x0401f7fb, 0x491bc857,
-	0x59c80840, 0x82040540, 0x00000010, 0x48039040,
-	0x59c41008, 0x82080500, 0xffffff7f, 0x48038808,
-	0x4c040000, 0x4c080000, 0x0401fac2, 0x04020007,
-	0x0401fac6, 0x04000022, 0x48038804, 0x0201f800,
-	0x001010ca, 0x0401f042, 0x4a038803, 0x00000008,
-	0x59c40003, 0x82000500, 0x00000003, 0x040007fd,
-	0x8c000502, 0x04020007, 0x0401fab8, 0x04000014,
-	0x48038804, 0x0201f800, 0x001010ca, 0x0401f034,
-	0x59c80040, 0x8400056a, 0x48039040, 0x59c80040,
-	0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500,
-	0xc0000000, 0x04000006, 0x59c400a3, 0x84000540,
-	0x480388a3, 0x4a038805, 0xc0000000, 0x0201f800,
-	0x0010106b, 0x4a03a005, 0x30000000, 0x59d00006,
-	0x4a03a005, 0x30000000, 0x59900006, 0x82000500,
-	0xffff0000, 0x48032006, 0x59d00005, 0x8c000504,
-	0x040207fe, 0x42000800, 0x00007600, 0x83180540,
-	0x60000000, 0x480008a1, 0x811800dc, 0x59c80840,
-	0x80040540, 0x48039040, 0x82000540, 0x00003000,
-	0x48039040, 0x59c80040, 0x82000500, 0x00003000,
-	0x040207fd, 0x0201f800, 0x001010b8, 0x83180400,
-	0x00106df6, 0x50000000, 0x48038804, 0x80000580,
-	0x4df00000, 0x0201f800, 0x00105d9b, 0x5c03e000,
-	0x5c001000, 0x5c000800, 0x480b8808, 0x48079040,
-	0x1c01f000, 0x4803c856, 0x59c80840, 0x82040540,
-	0x00000010, 0x48039040, 0x59c41008, 0x82080500,
-	0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000,
-	0x59c40004, 0x82000500, 0x00000003, 0x04020010,
-	0x59c40004, 0x82000500, 0x0000000c, 0x04000005,
-	0x4a038804, 0x0000000c, 0x8c000504, 0x0401f025,
-	0x59c80040, 0x8400056e, 0x48039040, 0x59c80040,
-	0x8c00052e, 0x040207fe, 0x0401f01e, 0x4a038803,
-	0x00000008, 0x59c40003, 0x82000500, 0x00000003,
-	0x040007fd, 0x8c000502, 0x04020006, 0x59c40004,
-	0x4a038804, 0x0000000c, 0x8c000504, 0x0401f011,
-	0x59c80040, 0x8400056a, 0x48039040, 0x59c80040,
-	0x8c00052a, 0x040207fe, 0x59c40005, 0x82000500,
-	0xc0000000, 0x04000007, 0x59c400a3, 0x84000540,
-	0x480388a3, 0x4a038805, 0xc0000000, 0x80000580,
-	0x497b2807, 0x5c001000, 0x5c000800, 0x480b8808,
-	0x48079040, 0x1c01f000, 0x5c000000, 0x4c000000,
-	0x4803c857, 0x491bc857, 0x4933c857, 0x4d900000,
-	0x4dd00000, 0x4da40000, 0x4d140000, 0x0401fdd1,
-	0x4df00000, 0x0401fa72, 0x59900004, 0x800001c0,
-	0x04000011, 0x81300580, 0x0402000f, 0x59300004,
-	0x84000520, 0x48026004, 0x0401ff4d, 0x04020009,
-	0x5c03e000, 0x04000db9, 0x80000580, 0x5c022800,
-	0x5c034800, 0x5c03a000, 0x5c032000, 0x1c01f000,
-	0x0401fcf1, 0x42027000, 0x00000049, 0x59300004,
-	0x84000520, 0x48026004, 0x8c00050c, 0x02020800,
-	0x000208d8, 0x5c03e000, 0x04000da8, 0x82000540,
-	0x00000001, 0x5c022800, 0x5c034800, 0x5c03a000,
-	0x5c032000, 0x1c01f000, 0x4933c857, 0x0401fda9,
-	0x4df00000, 0x598c000d, 0x80026540, 0x04000012,
-	0x59300004, 0x84000520, 0x48026004, 0x0401ff86,
-	0x04000017, 0x0401fd09, 0x42027000, 0x00000013,
-	0x59300004, 0x8c00050c, 0x02020800, 0x000208d8,
-	0x5c03e000, 0x04000d8d, 0x82000540, 0x00000001,
-	0x1c01f000, 0x836c1580, 0x00000001, 0x040007f9,
-	0x836c1580, 0x00000004, 0x040007f6, 0x42001000,
-	0x00103f62, 0x0201f800, 0x00105cc9, 0x5c03e000,
-	0x04000d7e, 0x80000580, 0x1c01f000, 0x4d300000,
-	0x4d180000, 0x4d3c0000, 0x0401fd82, 0x4df00000,
-	0x4a0378e4, 0x0000000f, 0x0401fa02, 0x417a3000,
-	0x59926004, 0x813261c0, 0x04000010, 0x417a7800,
-	0x0201f800, 0x00104728, 0x0400000a, 0x59300c06,
-	0x82040580, 0x00000003, 0x04000004, 0x82040580,
-	0x00000006, 0x04020003, 0x42027800, 0x00000002,
-	0x0201f800, 0x00108997, 0x811a3000, 0x83180480,
-	0x00000005, 0x040017eb, 0x42000800, 0x00000040,
-	0x0201f800, 0x00101395, 0x4a0378e4, 0x0000000a,
-	0x5c03e000, 0x04000d55, 0x5c027800, 0x5c023000,
-	0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
-	0x0401fd58, 0x4df00000, 0x59c80840, 0x82040540,
-	0x00000010, 0x48039040, 0x59c41008, 0x82080500,
-	0xffffff7f, 0x48038808, 0x4c040000, 0x4c080000,
-	0x42001000, 0x00000003, 0x0401f9c5, 0x598e600d,
-	0x813261c0, 0x04020f9d, 0x040009ca, 0x497b2807,
-	0x0401f80a, 0x5c001000, 0x5c000800, 0x480b8808,
-	0x84040d74, 0x48079040, 0x5c03e000, 0x04000d33,
-	0x5c026000, 0x1c01f000, 0x4d380000, 0x4d180000,
-	0x4d300000, 0x4d900000, 0x4dd00000, 0x4da40000,
-	0x4d140000, 0x59c41004, 0x480bc857, 0x82080500,
-	0x00003ff0, 0x04000025, 0x417a3000, 0x4c080000,
-	0x0201f800, 0x00105d9b, 0x5c001000, 0x82080500,
-	0x00000210, 0x04020004, 0x811a3000, 0x80081102,
-	0x0401f7f7, 0x0401f9c6, 0x59926004, 0x4933c857,
-	0x813261c0, 0x04020005, 0x59c400a3, 0x8c00051a,
-	0x02000800, 0x00100615, 0x0401fea1, 0x04000009,
-	0x0401fc4d, 0x42027000, 0x00000049, 0x59300004,
-	0x8c00050c, 0x02020800, 0x000208d8, 0x0401f007,
-	0x42027000, 0x0000004a, 0x4a026203, 0x00000003,
-	0x0201f800, 0x000208d8, 0x5c022800, 0x5c034800,
-	0x5c03a000, 0x5c032000, 0x5c026000, 0x5c023000,
-	0x5c027000, 0x1c01f000, 0x4d300000, 0x4d180000,
-	0x4d900000, 0x0401fcff, 0x42001000, 0x00000000,
-	0x598c0000, 0x82000580, 0x00000005, 0x04000974,
-	0x417a3000, 0x811b20c8, 0x83932400, 0x0000bf32,
-	0x59900001, 0x82000580, 0x00000001, 0x0402000d,
-	0x42000800, 0x000007d0, 0x59926004, 0x59300011,
-	0x82000500, 0xfff00000, 0x80000540, 0x04000003,
-	0x42000800, 0x00001b58, 0x0201f800, 0x00105d8d,
-	0x811a3000, 0x83180480, 0x00000005, 0x040017ea,
-	0x59c81040, 0x84081534, 0x480b9040, 0x0401fcd3,
-	0x5c032000, 0x5c023000, 0x5c026000, 0x1c01f000,
-	0x4933c857, 0x4d900000, 0x4dd00000, 0x4da40000,
-	0x4d140000, 0x4d380000, 0x0401fcd2, 0x4df00000,
-	0x59300004, 0x8c00053e, 0x04020007, 0x8c000520,
-	0x04000026, 0x0201f800, 0x001068a3, 0x04000023,
-	0x0401f02b, 0x598c000d, 0x81300580, 0x04000012,
-	0x0201f800, 0x00108a8a, 0x04020025, 0x0401f91b,
-	0x04000023, 0x48038804, 0x0401f961, 0x0201f800,
-	0x001010ca, 0x0201f800, 0x001068c1, 0x42027000,
-	0x00000049, 0x59300004, 0x8c00050c, 0x0402000d,
-	0x0401f00e, 0x59c40004, 0x8c000504, 0x04000014,
-	0x4a038804, 0x00000004, 0x0401fc18, 0x42027000,
-	0x00000013, 0x59300004, 0x8c00050c, 0x04000003,
-	0x0201f800, 0x000208d8, 0x5c03e000, 0x04000c9b,
-	0x5c027000, 0x5c022800, 0x5c034800, 0x5c03a000,
-	0x5c032000, 0x80000580, 0x1c01f000, 0x5c03e000,
-	0x04000c92, 0x5c027000, 0x5c022800, 0x5c034800,
-	0x5c03a000, 0x5c032000, 0x82000540, 0x00000001,
-	0x1c01f000, 0x497b2807, 0x0401fc92, 0x59c400af,
-	0x800001c0, 0x04020004, 0x0401fc84, 0x0201f000,
-	0x00101565, 0x598c000f, 0x82001480, 0x00000002,
-	0x04021007, 0x80000000, 0x4803180f, 0x80000580,
-	0x0201f800, 0x00105d86, 0x0400000e, 0x0401fed7,
-	0x0402000c, 0x0401fdc5, 0x0400000a, 0x0201f800,
-	0x0010a7ee, 0x0401f918, 0x4d380000, 0x42027000,
-	0x00000014, 0x0201f800, 0x000208d8, 0x5c027000,
-	0x0401fc6a, 0x0201f000, 0x00101565, 0x4d900000,
-	0x4dd00000, 0x4da40000, 0x4d140000, 0x4d300000,
-	0x0201f800, 0x00105d9b, 0x0401fc6a, 0x59c400af,
-	0x800001c0, 0x04000027, 0x0401f909, 0x59926004,
-	0x4933c857, 0x59300004, 0x8c000516, 0x0400000b,
-	0x0401fe86, 0x0402001f, 0x0201f800, 0x001068c1,
-	0x0401fc52, 0x42000800, 0x80000804, 0x0201f800,
-	0x00106466, 0x0401f017, 0x42001800, 0x00007530,
-	0x0401f8c3, 0x04020004, 0x0201f800, 0x00105d8b,
-	0x0401f010, 0x0401fe75, 0x0402000e, 0x0201f800,
-	0x0010a7ee, 0x59300004, 0x8c00050c, 0x04020003,
-	0x4a026203, 0x00000003, 0x4d380000, 0x42027000,
-	0x0000004a, 0x0201f800, 0x000208d8, 0x5c027000,
-	0x0401fc36, 0x5c026000, 0x5c022800, 0x5c034800,
-	0x5c03a000, 0x5c032000, 0x0201f000, 0x00101565,
-	0x4d900000, 0x4dd00000, 0x4da40000, 0x4d140000,
-	0x4d300000, 0x4d2c0000, 0x0401fc32, 0x0401f8d4,
-	0x59926004, 0x4933c857, 0x0401f882, 0x04000016,
-	0x0201f800, 0x00105d9b, 0x813261c0, 0x04000034,
-	0x59325808, 0x812e59c0, 0x02000800, 0x00100615,
-	0x0201f800, 0x00104e0d, 0x0402001d, 0x592c0208,
-	0x84000550, 0x48025a08, 0x0201f800, 0x00104f29,
-	0x04020027, 0x592c0208, 0x84000510, 0x48025a08,
-	0x0401f023, 0x0201f800, 0x00105d8b, 0x0401f020,
-	0x0201f800, 0x0010a7ee, 0x0401fd99, 0x592c0208,
-	0x84000550, 0x48025a08, 0x4d380000, 0x42027000,
-	0x0000004a, 0x4a026203, 0x00000003, 0x0201f800,
-	0x000208d8, 0x5c027000, 0x0401f011, 0x59900006,
-	0x82000500, 0xffff0000, 0x040207ee, 0x59c408af,
-	0x82040480, 0x000003e8, 0x040217ea, 0x59900006,
-	0x82000400, 0x00010000, 0x48032006, 0x0201f800,
-	0x00105d8b, 0x0201f800, 0x00103f37, 0x5c025800,
-	0x5c026000, 0x5c022800, 0x5c034800, 0x5c03a000,
-	0x5c032000, 0x0201f000, 0x00106982, 0x4d300000,
-	0x4d2c0000, 0x0201f800, 0x0010698c, 0x598e600d,
-	0x4933c857, 0x59c41004, 0x8c081500, 0x04000007,
-	0x0201f800, 0x00104e0d, 0x04020007, 0x0201f800,
-	0x00104f29, 0x0402002f, 0x0201f800, 0x00105d86,
-	0x0401f02c, 0x598c000f, 0x80000540, 0x04020011,
-	0x59c408af, 0x82040480, 0x000003e8, 0x0402100d,
-	0x598c080f, 0x80040800, 0x4807180f, 0x0201f800,
-	0x00105d86, 0x42000000, 0x0010b650, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x00103f37, 0x0401f019,
-	0x0401fdad, 0x813261c0, 0x04020003, 0x0401f849,
-	0x0401f014, 0x0201f800, 0x0010a7ee, 0x59300406,
-	0x82000580, 0x00000003, 0x04020007, 0x59325808,
-	0x812e59c0, 0x04000004, 0x592c0208, 0x84000550,
-	0x48025a08, 0x0401f854, 0x4d380000, 0x42027000,
-	0x00000014, 0x0201f800, 0x000208d8, 0x5c027000,
-	0x5c025800, 0x5c026000, 0x0201f000, 0x00106982,
-	0x59c40804, 0x83180400, 0x00106dec, 0x50000000,
-	0x80040500, 0x1c01f000, 0x59c40804, 0x83180400,
-	0x00106df1, 0x50000000, 0x80040500, 0x1c01f000,
-	0x00000210, 0x00000420, 0x00000840, 0x00001080,
-	0x00002100, 0x00004000, 0x00008000, 0x00010000,
-	0x00020000, 0x00040000, 0x00080000, 0x00100000,
-	0x00200000, 0x00400000, 0x00800000, 0x59900806,
-	0x80040120, 0x800c0480, 0x04021004, 0x82000540,
-	0x00000001, 0x0401f005, 0x82040c00, 0x00010000,
-	0x48072006, 0x80000580, 0x1c01f000, 0x480bc857,
-	0x0201f800, 0x0010698c, 0x4df00000, 0x480b1800,
-	0x5c03e000, 0x02000800, 0x00106982, 0x1c01f000,
-	0x4803c856, 0x0201f800, 0x0010698c, 0x4df00000,
-	0x497b180d, 0x497b1803, 0x497b180e, 0x497b180f,
-	0x497b1810, 0x598c0000, 0x82000580, 0x00000003,
-	0x04000009, 0x836c0580, 0x00000002, 0x04020004,
-	0x4a031800, 0x00000005, 0x0401f003, 0x4a031800,
-	0x00000000, 0x5c03e000, 0x02000800, 0x00106982,
-	0x1c01f000, 0x59300004, 0x8c00050c, 0x04020003,
-	0x4a026203, 0x00000001, 0x1c01f000, 0x83180480,
-	0x00000005, 0x02021800, 0x00100615, 0x491bc857,
-	0x811b20c8, 0x83932400, 0x0000bf32, 0x811ba0ca,
-	0x83d3a400, 0x00007600, 0x83180400, 0x00106e41,
-	0x50034800, 0x811a28c2, 0x83162c00, 0x00006100,
-	0x1c01f000, 0x0010b559, 0x0010b570, 0x0010b587,
-	0x0010b59e, 0x0010b5b5, 0x4933c857, 0x59300406,
-	0x82000c80, 0x00000012, 0x04021016, 0x4803c857,
-	0x04011000, 0x0c01f001, 0x00106e60, 0x00106f03,
-	0x00107249, 0x001072cf, 0x00106f03, 0x00107249,
-	0x001072cf, 0x00106e60, 0x00106f03, 0x00106e60,
-	0x00106e60, 0x00106e60, 0x00106e60, 0x00106e60,
-	0x00106e60, 0x00106e60, 0x00106e66, 0x00106e66,
-	0x0201f800, 0x0010698c, 0x0201f800, 0x001068f6,
-	0x0201f000, 0x00106982, 0x42001000, 0x0010b5f4,
-	0x50081000, 0x4930100c, 0x58080002, 0x82000580,
-	0x00000100, 0x0402003e, 0x59325808, 0x812e59c0,
-	0x02000800, 0x00100615, 0x59326809, 0x813669c0,
-	0x04000025, 0x592c040b, 0x82000500, 0x0000e000,
-	0x04000003, 0x0401fbc9, 0x0401f002, 0x0401fbb9,
-	0x592c000d, 0x82000500, 0x00000003, 0x04000007,
-	0x82000580, 0x00000003, 0x80000000, 0x58d00802,
-	0x80040540, 0x4801a002, 0x42001000, 0x0010b5f4,
-	0x50081000, 0x4930100b, 0x492c100a, 0x82d00400,
-	0x00000006, 0x48001003, 0x592c000d, 0x82000400,
-	0x00000003, 0x80000104, 0x48001004, 0x592c000e,
-	0x48001007, 0x592c000f, 0x48001008, 0x0201f000,
-	0x001008a1, 0x42026800, 0x0010bc0c, 0x592c080a,
-	0x48066802, 0x82040500, 0x00ffff00, 0x04000007,
-	0x497a6a12, 0x59a81010, 0x82081500, 0x00ffff00,
-	0x80080580, 0x040207d0, 0x82040d00, 0x000000ff,
-	0x800408d0, 0x48066a12, 0x0401f7cb, 0x1c01f000,
-	0x4d2c0000, 0x4d300000, 0x4c580000, 0x4c540000,
-	0x4c500000, 0x5832580a, 0x812e59c0, 0x02000800,
-	0x00100615, 0x58300002, 0x4a006002, 0x00000100,
-	0x82000580, 0x00000100, 0x04020020, 0x5830000b,
-	0x5832600c, 0x81300580, 0x04020012, 0x0401f82f,
-	0x04020014, 0x592c080d, 0x82040c00, 0x00000003,
-	0x80040904, 0x4004b000, 0x4200a000, 0x0010b349,
-	0x4050a800, 0x0201f800, 0x0010a94f, 0x42001000,
-	0x0000dc00, 0x0201f800, 0x0010763b, 0x0401f005,
-	0x4803c857, 0x4933c857, 0x0401f81c, 0x04000f93,
-	0x5c00a000, 0x5c00a800, 0x5c00b000, 0x5c026000,
-	0x5c025800, 0x1c01f000, 0x5830000b, 0x5832600c,
-	0x4803c857, 0x4933c857, 0x81300580, 0x040207f1,
-	0x0401f80e, 0x040207f3, 0x4803c857, 0x0201f800,
-	0x00106619, 0x02020800, 0x00100615, 0x4a025a06,
-	0x00000002, 0x0201f800, 0x00020381, 0x0201f800,
-	0x00107698, 0x0401f7e7, 0x0201f800, 0x0010698c,
-	0x4df00000, 0x598c000d, 0x81300580, 0x04020009,
-	0x598c0005, 0x81300580, 0x04020006, 0x5c03e000,
-	0x02000800, 0x00106982, 0x80000580, 0x1c01f000,
-	0x4803c857, 0x5c03e000, 0x02000800, 0x00106982,
-	0x82000540, 0x00000001, 0x1c01f000, 0x59300403,
-	0x82000c80, 0x00000056, 0x02021800, 0x00100615,
-	0x4803c857, 0x0c01f001, 0x0010707a, 0x00107095,
-	0x001070a6, 0x001071a9, 0x00107169, 0x0010716d,
-	0x0010717e, 0x00107192, 0x00107187, 0x00107192,
-	0x001071cd, 0x00107192, 0x0010720f, 0x00107192,
-	0x0010721d, 0x00107192, 0x00107187, 0x00107192,
-	0x00107221, 0x00106f60, 0x00106f60, 0x00106f60,
-	0x00106f60, 0x00106f60, 0x00106f60, 0x00106f60,
-	0x00106f60, 0x00106f60, 0x00106f60, 0x00106f60,
-	0x001072ed, 0x0010730c, 0x00107316, 0x00106f60,
-	0x0010732c, 0x0010717e, 0x00106f60, 0x0010717e,
-	0x00107192, 0x00106f60, 0x001070a6, 0x001071a9,
-	0x00106f60, 0x0010737c, 0x00107192, 0x00106f60,
-	0x0010738c, 0x00107192, 0x00106f60, 0x00107187,
-	0x0010706b, 0x00106f62, 0x00106f60, 0x001073a3,
-	0x001073dc, 0x00107456, 0x00106f60, 0x00107466,
-	0x0010717c, 0x00107459, 0x00106f60, 0x00107338,
-	0x0010747f, 0x00106f60, 0x001074b4, 0x00107507,
-	0x00106f60, 0x00106f77, 0x00106fdd, 0x00106fea,
-	0x00106f60, 0x0010717e, 0x00106f60, 0x00107031,
-	0x0010703c, 0x00106f60, 0x00106f60, 0x00106f8b,
-	0x00106fb0, 0x00107546, 0x00107587, 0x001075ad,
-	0x00106f60, 0x00106f60, 0x00106f60, 0x0010757b,
-	0x0201f800, 0x00100615, 0x0401fad2, 0x59325808,
-	0x592c0009, 0x4801a006, 0x592c000a, 0x4801a007,
-	0x592c000b, 0x4801a008, 0x592c000c, 0x4801a009,
-	0x592c000d, 0x4801a00a, 0x4979a00b, 0x592c0809,
-	0x82040d00, 0x00000fff, 0x80040904, 0x42001000,
-	0x0000dc00, 0x0201f000, 0x0010763b, 0x4a026202,
-	0x0000ffff, 0x0401fabb, 0x4d2c0000, 0x4a01a006,
-	0x05000000, 0x59325808, 0x592c0009, 0x4801a007,
-	0x592c000a, 0x4801a008, 0x592c000b, 0x4801a009,
-	0x42000800, 0x00000004, 0x42001000, 0x0000dc00,
-	0x5c025800, 0x0201f000, 0x0010763b, 0x4c580000,
-	0x4c500000, 0x4c540000, 0x4d2c0000, 0x0401faa5,
-	0x59325808, 0x5930040b, 0x800000c2, 0x4200a800,
-	0x0010b349, 0x592cb205, 0x832ca400, 0x00000006,
-	0x0201f800, 0x0010a93e, 0x40580000, 0x8054ac00,
-	0x592c0001, 0x80000540, 0x04000003, 0x40025800,
-	0x0401f7f5, 0x4200a000, 0x0010b349, 0x4050a800,
-	0x5930b40b, 0x0201f800, 0x0010a94f, 0x59300c0b,
-	0x42001000, 0x0000dc00, 0x5c025800, 0x5c00a800,
-	0x5c00b000, 0x5c00a000, 0x0201f000, 0x0010763b,
-	0x4c580000, 0x4c500000, 0x4c540000, 0x4d2c0000,
-	0x42034800, 0x0010b342, 0x0401fa8c, 0x59325808,
-	0x592c0802, 0x4807c857, 0x40041000, 0x80040904,
-	0x82081500, 0x00000003, 0x04000008, 0x80040800,
-	0x82081580, 0x00000003, 0x80081000, 0x58d00002,
-	0x80080540, 0x4801a002, 0x4a025805, 0x02000000,
-	0x82d0ac00, 0x00000006, 0x592cb011, 0x832ca400,
-	0x00000005, 0x0201f800, 0x0010a93e, 0x40580000,
-	0x8054ac00, 0x592e5801, 0x41780000, 0x812e5d40,
-	0x040207f6, 0x42001000, 0x0000dc00, 0x5c025800,
-	0x5c00a800, 0x5c00b000, 0x5c00a000, 0x0201f000,
-	0x0010763b, 0x0401fa57, 0x4a01a006, 0x78000000,
-	0x5930001c, 0x840001c0, 0x4801a407, 0x4979a207,
-	0x42000800, 0x00000002, 0x42001000, 0x0000dc00,
-	0x0201f000, 0x0010763b, 0x4c580000, 0x4c540000,
-	0x4c500000, 0x0401fa55, 0x4a01a006, 0x02000000,
-	0x59a80002, 0x4801a008, 0x59a80003, 0x4801a009,
-	0x59a80000, 0x4801a00a, 0x59a80001, 0x4801a00b,
-	0x5930001c, 0x82000d80, 0x0000e000, 0x04000016,
-	0x82000d80, 0x0000df00, 0x04000006, 0x4a01a407,
-	0x00000010, 0x42000800, 0x00000006, 0x0401f027,
-	0x4a03c840, 0x0010b2e7, 0x4a03c842, 0x0000000d,
-	0x42001800, 0x0010b2e7, 0x0201f800, 0x001007f5,
-	0x42000000, 0x0000df00, 0x4200a000, 0x0010b2e7,
-	0x0401f00d, 0x4a03c840, 0x0010b2f4, 0x4a03c842,
-	0x0000000d, 0x42001800, 0x0010b2f4, 0x0201f800,
-	0x001007f5, 0x42000000, 0x0000e000, 0x4200a000,
-	0x0010b2f4, 0x82000540, 0x00000010, 0x4801a407,
-	0x4a01a207, 0x00000034, 0x4200b000, 0x0000000d,
-	0x82d0ac00, 0x0000000c, 0x0201f800, 0x0010a93e,
-	0x42000800, 0x00000013, 0x42001000, 0x0000dc00,
-	0x5c00a000, 0x5c00a800, 0x5c00b000, 0x0201f000,
-	0x0010763b, 0x0401fa03, 0x4a01a006, 0x63000028,
-	0x5930001c, 0x4801a007, 0x42000800, 0x00000002,
-	0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b,
-	0x0401fa06, 0x41780000, 0x41780800, 0x42002000,
-	0x00080000, 0x0c01f81b, 0x80000000, 0x80040800,
-	0x42001000, 0x0000000c, 0x59841802, 0x8c0c1d00,
-	0x04020008, 0x42002000, 0x00050000, 0x0c01f811,
-	0x80000000, 0x80040800, 0x82081400, 0x00000004,
-	0x82080540, 0x02000000, 0x4801a006, 0x800408e0,
-	0x5930001c, 0x80040540, 0x4801a007, 0x80080904,
-	0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b,
-	0x00107061, 0x00107063, 0x00107065, 0x00107067,
-	0x00107069, 0x4811a008, 0x1c01f000, 0x4811a009,
-	0x1c01f000, 0x4811a00a, 0x1c01f000, 0x4811a00b,
-	0x1c01f000, 0x4811a00c, 0x1c01f000, 0x4a026009,
-	0x0010bc0c, 0x59a80010, 0x82000500, 0x000000ff,
-	0x800000d0, 0x42026800, 0x0010bc0c, 0x48026a12,
-	0x0401fa3c, 0x41780800, 0x42001000, 0x00005c00,
-	0x0201f000, 0x0010763b, 0x0401f9ba, 0x4a01a006,
-	0x52000000, 0x4979a007, 0x599c0017, 0x8c000500,
-	0x04000005, 0x599c0402, 0x0201f800, 0x00101644,
-	0x4805a007, 0x59a80002, 0x4801a008, 0x59a80003,
-	0x4801a009, 0x59a80000, 0x4801a00a, 0x59a80001,
-	0x4801a00b, 0x59a80010, 0x4801a00c, 0x42000800,
-	0x00000007, 0x42001000, 0x0000dc00, 0x0201f000,
-	0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f99d,
-	0x4a01a006, 0x05000000, 0x59a80010, 0x4801a007,
-	0x59a80002, 0x59a80803, 0x4801a008, 0x4805a009,
-	0x42000800, 0x00000004, 0x42001000, 0x0000dc00,
-	0x0201f000, 0x0010763b, 0x4a026202, 0x0000ffff,
-	0x0401f98c, 0x4d3c0000, 0x417a7800, 0x0201f800,
-	0x00104745, 0x5c027800, 0x4a01a006, 0x03000000,
-	0x59340403, 0x82000580, 0x000007fe, 0x0402006e,
-	0x4a01a006, 0x04000000, 0x81a40800, 0x4a000800,
-	0x22fffffe, 0x5934000a, 0x84000500, 0x4802680a,
-	0x59c41002, 0x8408150c, 0x480b8802, 0x59a80026,
-	0x8c000508, 0x04000010, 0x59a8002a, 0x4801a007,
-	0x59a8002b, 0x82000500, 0xffff2000, 0x599c0818,
-	0x8c040d16, 0x04000002, 0x8400056a, 0x4801a008,
-	0x4a01a009, 0x00002710, 0x59a8002d, 0x4801a00a,
-	0x0401f039, 0x59a8002a, 0x4801a007, 0x0201f800,
-	0x00104e0d, 0x04020009, 0x497b8880, 0x82000500,
-	0x0000ffff, 0x4c000000, 0x0201f800, 0x00101670,
-	0x5c000000, 0x48038880, 0x59a8002b, 0x0201f800,
-	0x00104e0d, 0x04020004, 0x82000500, 0x37ffffff,
-	0x0401f003, 0x82000500, 0x3fffffff, 0x599c0818,
-	0x8c040d16, 0x04000002, 0x8400056a, 0x59a80805,
-	0x8c040d10, 0x04000019, 0x59300c03, 0x82041580,
-	0x00000051, 0x04000015, 0x82041580, 0x00000031,
-	0x04000012, 0x4c580000, 0x4c500000, 0x4c540000,
-	0x4200b000, 0x00000004, 0x4200a000, 0x0010b6f9,
-	0x82d0ac00, 0x0000001f, 0x4c000000, 0x0201f800,
-	0x0010a93e, 0x5c000000, 0x5c00a800, 0x5c00a000,
-	0x5c00b000, 0x8400057a, 0x4801a008, 0x4979a009,
-	0x4979a00a, 0x59a80002, 0x59a80803, 0x4801a00b,
-	0x4805a00c, 0x59a80000, 0x59a80801, 0x4801a00d,
-	0x4805a00e, 0x4979a00f, 0x4979a010, 0x4979a011,
-	0x4979a012, 0x4979a013, 0x4979a014, 0x4979a015,
-	0x4979a016, 0x59a8002e, 0x84000576, 0x4801a017,
-	0x59a8002f, 0x4801a018, 0x4979a019, 0x4979a01a,
-	0x0401f043, 0x59a80026, 0x8c000508, 0x0400000d,
-	0x59a8002a, 0x82000500, 0x0000ffff, 0x59c40880,
-	0x80040d80, 0x04000007, 0x497b8880, 0x4c000000,
-	0x0201f800, 0x00101670, 0x5c000000, 0x48038880,
-	0x59a8002a, 0x4801a007, 0x4c640000, 0x4d2c0000,
-	0x59a8c82b, 0x0201f800, 0x00108df4, 0x0400000d,
-	0x0201f800, 0x00109360, 0x0402000a, 0x592c0207,
-	0x8c00050e, 0x04000007, 0x8264cd00, 0x0000ffff,
-	0x592c0009, 0x82000500, 0xffff0000, 0x8064cd40,
-	0x4865a008, 0x5c025800, 0x5c00c800, 0x59a8002c,
-	0x4801a009, 0x59a8002d, 0x4801a00a, 0x59a80002,
-	0x59a80803, 0x4801a00b, 0x4805a00c, 0x59a80000,
-	0x59a80801, 0x4801a00d, 0x4805a00e, 0x4979a00f,
-	0x4979a010, 0x4979a011, 0x4979a012, 0x4979a013,
-	0x4979a014, 0x4979a015, 0x4979a016, 0x59a8002e,
-	0x4801a017, 0x59a8002f, 0x4801a018, 0x59a80030,
-	0x4801a019, 0x59a80031, 0x4801a01a, 0x42000800,
-	0x0000001d, 0x42001000, 0x0000dc00, 0x0201f000,
-	0x0010763b, 0x0401f8cb, 0x4a01a006, 0x50000000,
-	0x0401f7b5, 0x0401f8c7, 0x4a01a406, 0x21000010,
-	0x4a01a206, 0x00000014, 0x4979a007, 0x4979a008,
-	0x4979a009, 0x4979a00a, 0x42000800, 0x00000005,
-	0x42001000, 0x0000dc00, 0x0201f000, 0x0010763b,
-	0x0401f8bf, 0x0401f002, 0x0401f8c4, 0x4a01a006,
-	0x02000000, 0x42000800, 0x00000001, 0x42001000,
-	0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f8bb,
-	0x4a01a006, 0x02000000, 0x59300403, 0x82000580,
-	0x00000031, 0x04020794, 0x81a40800, 0x4a000801,
-	0x00fffffe, 0x0401f72b, 0x0401f8b0, 0x4a01a006,
-	0x01000000, 0x5930041a, 0x80000540, 0x04000003,
-	0x4801a407, 0x0401f003, 0x4a01a407, 0x00000003,
-	0x5930021a, 0x80000540, 0x04000003, 0x4801a207,
-	0x0401f003, 0x4a01a207, 0x00002a00, 0x42000800,
-	0x00000002, 0x42001000, 0x0000dc00, 0x0201f000,
-	0x0010763b, 0x4a026202, 0x0000ffff, 0x0401f889,
-	0x4a01a406, 0x00002010, 0x4a01a206, 0x00000014,
-	0x4a01a407, 0x00000800, 0x4a01a207, 0x00002000,
-	0x80000580, 0x599c0817, 0x8c040d0a, 0x04020003,
-	0x82000540, 0x00000020, 0x8c040d08, 0x04000003,
-	0x82000540, 0x00000010, 0x82000540, 0x00000002,
-	0x5934080a, 0x8c040d14, 0x04000005, 0x82040d00,
-	0x00000380, 0x80040540, 0x0401f006, 0x599c0818,
-	0x8c040d18, 0x04000003, 0x82000540, 0x00000380,
-	0x0401f03c, 0x0401f875, 0x4a01a406, 0x00000210,
-	0x4a01a206, 0x00000014, 0x4a01a407, 0x00000800,
-	0x5934000a, 0x8c000516, 0x04000014, 0x59340c05,
-	0x82040500, 0x00000030, 0x04000013, 0x59340a05,
-	0x82040500, 0x0000c000, 0x04020009, 0x8c040d1a,
-	0x04000004, 0x4a01a207, 0x00002100, 0x0401f00c,
-	0x4a01a207, 0x00000100, 0x0401f009, 0x4a01a207,
-	0x00000400, 0x0401f006, 0x4a01a207, 0x00000700,
-	0x0401f003, 0x4a01a207, 0x00000800, 0x80000580,
-	0x599c0817, 0x8c040d0a, 0x04020003, 0x82000540,
-	0x00000020, 0x8c040d08, 0x04000003, 0x82000540,
-	0x00000010, 0x82000540, 0x00000002, 0x59340a00,
-	0x8c040d0e, 0x0400000b, 0x84000550, 0x599c1017,
-	0x8c08150a, 0x04020004, 0x8c040d0a, 0x04000002,
-	0x8400054e, 0x8c040d1c, 0x04000002, 0x84000552,
-	0x4801a20a, 0x42000800, 0x00000005, 0x42001000,
-	0x0000dc00, 0x0201f000, 0x0010763b, 0x0401f833,
-	0x4a01a006, 0x02100014, 0x4a01a007, 0x01000000,
-	0x4979a008, 0x4979a009, 0x4979a00a, 0x42000800,
-	0x00000005, 0x42001000, 0x0000dc00, 0x0201f000,
-	0x0010763b, 0x0401f825, 0x4a01a006, 0x02000000,
-	0x0401f65d, 0x4933c857, 0x0401f820, 0x4a01a006,
-	0x01000000, 0x4a01a407, 0x0000000b, 0x42000800,
-	0x00000002, 0x42001000, 0x0000dc00, 0x0201f000,
-	0x0010763b, 0x42005000, 0x32000000, 0x42006000,
-	0x08290000, 0x41786800, 0x41787800, 0x0401f3e6,
-	0x42005000, 0x22000000, 0x42006000, 0x01290000,
-	0x41786800, 0x41787800, 0x0401f3df, 0x42005000,
-	0x33000000, 0x42006000, 0x08980000, 0x41786800,
-	0x41787800, 0x0401f3d8, 0x42005000, 0x23000000,
-	0x42006000, 0x01980000, 0x41786800, 0x41787800,
-	0x0401f3d1, 0x59300403, 0x82000c80, 0x00000085,
-	0x02001800, 0x00100615, 0x82000c80, 0x00000093,
-	0x02021800, 0x00100615, 0x82000480, 0x00000085,
-	0x0c01f001, 0x00107263, 0x00107265, 0x00107272,
-	0x00107263, 0x00107263, 0x00107263, 0x00107263,
-	0x00107263, 0x00107263, 0x00107263, 0x00107263,
-	0x00107263, 0x00107263, 0x0010727f, 0x0201f800,
-	0x00100615, 0x4933c857, 0x0401f851, 0x5930001c,
-	0x4801a004, 0x4801a007, 0x4979a408, 0x4a01a208,
-	0x0000ffff, 0x42000800, 0x00000003, 0x42001000,
-	0x0000dc00, 0x0401f3ca, 0x4933c857, 0x0401f850,
-	0x5930001c, 0x4801a004, 0x4a01a406, 0x00000003,
-	0x4a01a206, 0x00000300, 0x42000800, 0x00000001,
-	0x42001000, 0x0000dc00, 0x0401f3bd, 0x4d2c0000,
-	0x59325808, 0x4933c857, 0x492fc857, 0x812e59c0,
-	0x02000800, 0x00100615, 0x59340a12, 0x82040d00,
-	0x0000ff00, 0x592c000a, 0x82000500, 0x000000ff,
-	0x900001c0, 0x80040540, 0x82000540, 0x00000011,
-	0x44034800, 0x81a5a000, 0x42001000, 0x00000009,
-	0x42000800, 0x00000003, 0x592c0009, 0x82000500,
-	0xff000000, 0x82001d80, 0x84000000, 0x04000009,
-	0x82001d80, 0x85000000, 0x02020800, 0x00100615,
-	0x42001000, 0x00000007, 0x42000800, 0x00000001,
-	0x832c1c00, 0x00000009, 0x500c0000, 0x4401a000,
-	0x800c1800, 0x80d1a000, 0x80081040, 0x040207fb,
-	0x42001000, 0x0000dc00, 0x5c025800, 0x0401f38c,
-	0x42005000, 0x81000000, 0x42006000, 0x00090000,
-	0x41786800, 0x41787800, 0x0401f363, 0x42005000,
-	0x84000000, 0x42006000, 0x00990000, 0x59300406,
-	0x82000580, 0x00000005, 0x04000002, 0x8430652e,
-	0x41786800, 0x41787800, 0x0401f357, 0x42005000,
-	0x85000000, 0x42006000, 0x00990000, 0x59300406,
-	0x82000580, 0x00000005, 0x04000002, 0x8430652e,
-	0x41786800, 0x41787800, 0x0401f34b, 0x59300403,
-	0x82000c80, 0x00000053, 0x02021800, 0x00100615,
-	0x82000480, 0x0000004b, 0x02001800, 0x00100615,
-	0x59326809, 0x59368c03, 0x4803c857, 0x0c01f001,
-	0x00107353, 0x0010735b, 0x00107363, 0x0010736b,
-	0x001072e4, 0x001072e4, 0x001072e4, 0x0010734b,
-	0x0201f800, 0x00100615, 0x42005000, 0x06000000,
-	0x42006000, 0x08290000, 0x41786800, 0x41787800,
-	0x0401f32d, 0x4933c857, 0x0401ff46, 0x4a01a006,
-	0x12000000, 0x59300406, 0x82000580, 0x00000004,
-	0x04020003, 0x59340002, 0x0401f002, 0x59a80010,
-	0x82000500, 0x00ffffff, 0x4801a007, 0x59300419,
-	0x4801a408, 0x59300219, 0x4801a208, 0x4979a009,
-	0x4979a00a, 0x4979a00b, 0x4979a00c, 0x4979a00d,
-	0x4979a00e, 0x4979a00f, 0x4979a010, 0x42000800,
-	0x0000000b, 0x42001000, 0x0000dc00, 0x0401f330,
-	0x0401ff28, 0x4a01a006, 0x0f000000, 0x5930001c,
-	0x4801a007, 0x42000800, 0x00000002, 0x42001000,
-	0x0000dc00, 0x0401f326, 0x0401ff2c, 0x4a01a006,
-	0x02000000, 0x59c40085, 0x48031004, 0x59880000,
-	0x4801a007, 0x59880001, 0x4801a008, 0x59880002,
-	0x4801a009, 0x59880003, 0x4801a00a, 0x59880004,
-	0x4801a00b, 0x59880005, 0x4801a00c, 0x42000800,
-	0x00000007, 0x42001000, 0x0000dc00, 0x0401f310,
-	0x4a026202, 0x0000ffff, 0x0401ff06, 0x4a01a006,
-	0x62000000, 0x5930001c, 0x4801a007, 0x42000800,
-	0x00000002, 0x42001000, 0x0000dc00, 0x0401f304,
-	0x0401fefc, 0x59300808, 0x4c500000, 0x4c540000,
-	0x4c580000, 0x8204a400, 0x0000000a, 0x5930b01c,
-	0x82d0ac00, 0x00000006, 0x0201f800, 0x0010a93e,
-	0x5930081c, 0x42001000, 0x0000dc00, 0x5c00b000,
-	0x5c00a800, 0x5c00a000, 0x0401f2f1, 0x0401ff9b,
-	0x59300017, 0x4801a006, 0x59300018, 0x4801a007,
-	0x4a01a008, 0x00001000, 0x0401f020, 0x0401ff93,
-	0x59300017, 0x4801a006, 0x59300018, 0x4801a007,
-	0x4a01a008, 0x00004000, 0x0401f018, 0x0401ff8b,
-	0x59300017, 0x4801a006, 0x59300018, 0x4801a007,
-	0x4a01a008, 0x00002000, 0x0401f010, 0x0401ff83,
-	0x59300017, 0x4801a006, 0x59300018, 0x4801a007,
-	0x4a01a008, 0x00000400, 0x0401f008, 0x0401ff7b,
-	0x59300017, 0x4801a006, 0x59300018, 0x4801a007,
-	0x4a01a008, 0x00000200, 0x4979a009, 0x4979a00a,
-	0x4979a00b, 0x4979a00c, 0x4979a00d, 0x42000800,
-	0x00000008, 0x42001000, 0x0000dc00, 0x0401f2c0,
-	0x0401fec6, 0x4a01a006, 0x02000014, 0x4979a407,
-	0x4979a207, 0x59a8003a, 0x4801a008, 0x59a8003b,
-	0x4801a009, 0x4a01a00a, 0x00047878, 0x42000800,
-	0x00000005, 0x42001000, 0x0000dc00, 0x0401f2b0,
-	0x0401feb6, 0x4a01a006, 0x02140018, 0x4a01a407,
-	0x00000800, 0x5930001c, 0x82000d00, 0xff000000,
-	0x900409c0, 0x4805a207, 0x82000500, 0x00ffffff,
-	0x4801a00a, 0x4979a408, 0x4979a208, 0x4979a409,
-	0x4979a209, 0x4979a00b, 0x42000800, 0x00000006,
-	0x42001000, 0x0000dc00, 0x0401f299, 0x4933c857,
-	0x4937c857, 0x4d380000, 0x4d1c0000, 0x42027000,
-	0x00000035, 0x0201f800, 0x00109183, 0x04020022,
-	0x0401fe88, 0x4a01a006, 0x13000000, 0x5932381e,
-	0x591c0414, 0x8c000502, 0x02000800, 0x00100615,
-	0x591c0019, 0x4801a005, 0x591c0406, 0x82000580,
-	0x00000003, 0x04000007, 0x59300809, 0x58040002,
-	0x82000500, 0x00ffffff, 0x4801a007, 0x0401f003,
-	0x59a80010, 0x4801a007, 0x59300419, 0x4801a408,
-	0x59300219, 0x4801a208, 0x42000800, 0x00000003,
-	0x42001000, 0x0000dc00, 0x5c023800, 0x5c027000,
-	0x0401f26f, 0x4803c856, 0x0201f800, 0x0010698c,
-	0x598c000d, 0x81300580, 0x02020800, 0x00100615,
-	0x0201f800, 0x001068f6, 0x0201f800, 0x000208b4,
-	0x5c023800, 0x5c027000, 0x0201f000, 0x00106982,
-	0x4803c856, 0x4d2c0000, 0x4d1c0000, 0x5932381e,
-	0x811e39c0, 0x02000800, 0x00100615, 0x591c0c06,
-	0x82040580, 0x00000006, 0x0400000d, 0x82040580,
-	0x00000003, 0x04000036, 0x4a026403, 0x00000037,
-	0x4a02641a, 0x00000003, 0x4a02621a, 0x00001700,
-	0x5c023800, 0x5c025800, 0x0401f064, 0x0401f84b,
-	0x42001000, 0x40000000, 0x591c0203, 0x591c0804,
-	0x8c040d3e, 0x04020023, 0x82000c80, 0x0000000e,
-	0x0c001003, 0x0201f800, 0x00100615, 0x00107410,
-	0x0010741c, 0x00107412, 0x0010741c, 0x00107418,
-	0x00107410, 0x00107410, 0x0010741c, 0x0010741c,
-	0x00107410, 0x00107410, 0x00107410, 0x00107410,
-	0x00107410, 0x0010741c, 0x00107410, 0x0010741c,
-	0x0201f800, 0x00100615, 0x591c0414, 0x4803c857,
-	0x8c000518, 0x04000003, 0x8c000512, 0x04000003,
-	0x80001580, 0x0401f003, 0x42001000, 0x20000000,
-	0x591c0015, 0x4801a00a, 0x0401f018, 0x0401f81f,
-	0x591e5808, 0x812e59c0, 0x02000800, 0x00100615,
-	0x592c100f, 0x591c0011, 0x80080480, 0x4801a00a,
-	0x591c0203, 0x591c0804, 0x8c040d3e, 0x04020007,
-	0x82000d80, 0x00000002, 0x04000007, 0x82000d80,
-	0x00000004, 0x04000004, 0x42001000, 0x40000000,
-	0x0401f002, 0x80001580, 0x4809a00b, 0x42000800,
-	0x00000006, 0x42001000, 0x0000dc00, 0x5c023800,
-	0x5c025800, 0x0401f1fe, 0x4803c856, 0x0401fe03,
-	0x4a01a006, 0x02000000, 0x59300c19, 0x4805a407,
-	0x59300a19, 0x4805a207, 0x59a81010, 0x59300809,
-	0x58041802, 0x820c1d00, 0x00ffffff, 0x5930081e,
-	0x58040406, 0x82000580, 0x00000003, 0x04020004,
-	0x4809a008, 0x480da009, 0x0401f003, 0x480da008,
-	0x4809a009, 0x1c01f000, 0x4803c856, 0x0401fdeb,
-	0x0401f003, 0x4803c856, 0x0401fde1, 0x4a01a006,
-	0x01000000, 0x5930041a, 0x4801a407, 0x5930021a,
-	0x4801a207, 0x42000800, 0x00000002, 0x42001000,
-	0x0000dc00, 0x0401f1d6, 0x4803c856, 0x4d1c0000,
-	0x0401fdc5, 0x4a01a006, 0x14000000, 0x5932381e,
-	0x591c0019, 0x4801a005, 0x59300419, 0x4801a407,
-	0x59300219, 0x4801a207, 0x59300015, 0x4801a008,
-	0x59300216, 0x82000500, 0x000000ff, 0x840001c0,
-	0x4801a409, 0x42000800, 0x00000004, 0x42001000,
-	0x0000dc00, 0x5c023800, 0x0401f1bd, 0x4803c856,
-	0x0401f80b, 0x5930041a, 0x900001c0, 0x4801a005,
-	0x0401f9f4, 0x41780800, 0x42001000, 0x00005c00,
-	0x0401f9b3, 0x0201f000, 0x00105d86, 0x4803c856,
-	0x59300817, 0x82041c00, 0x00000005, 0x46034800,
-	0x00000021, 0x58040404, 0x82000500, 0x0000f000,
-	0x82000580, 0x00003000, 0x04000003, 0x46034800,
-	0x00000041, 0x81a5a000, 0x580c0001, 0x82000d00,
-	0x00ffffff, 0x82040d40, 0xc2000000, 0x4805a000,
-	0x580c0800, 0x82041500, 0x00ffffff, 0x82000500,
-	0xff000000, 0x80080540, 0x4801a001, 0x580c0002,
-	0x82000580, 0x00c00000, 0x82000500, 0x00fd0300,
-	0x4801a002, 0x580c0003, 0x4801a003, 0x580c0404,
-	0x4801a404, 0x580c0204, 0x4801a204, 0x1c01f000,
-	0x4803c856, 0x59a80026, 0x82000500, 0x00000028,
-	0x04020009, 0x59a80026, 0x82000500, 0x00000028,
-	0x04000003, 0x497a6a12, 0x0401f003, 0x4a026a12,
-	0x0000ff00, 0x42005000, 0x22000000, 0x42006000,
-	0x01380000, 0x41786800, 0x41787800, 0x0401f952,
-	0x59301008, 0x4a01a006, 0x54000000, 0x59a80010,
-	0x82000500, 0x00ffffff, 0x58080c0a, 0x800408f0,
-	0x80040540, 0x4801a007, 0x5808000a, 0x82000500,
-	0xff000000, 0x4801a008, 0x59a80002, 0x4801a009,
-	0x59a80003, 0x4801a00a, 0x59a80000, 0x4801a00b,
-	0x59a80001, 0x4801a00c, 0x5808000c, 0x9c0001c0,
-	0x4801a00d, 0x5808000d, 0x9c0001c0, 0x4801a00e,
-	0x5808000e, 0x9c0001c0, 0x4801a00f, 0x5808000f,
-	0x9c0001c0, 0x4801a010, 0x58080010, 0x9c0001c0,
-	0x4801a011, 0x58080011, 0x9c0001c0, 0x4801a012,
-	0x58080012, 0x9c0001c0, 0x4801a013, 0x58080013,
-	0x9c0001c0, 0x4801a014, 0x58080010, 0x9c0001c0,
-	0x4801a015, 0x58080011, 0x9c0001c0, 0x4801a016,
-	0x58080012, 0x9c0001c0, 0x4801a017, 0x58080013,
-	0x9c0001c0, 0x4801a018, 0x42000800, 0x00000013,
-	0x42001000, 0x0000dc00, 0x0401f135, 0x4803c856,
-	0x42005000, 0x22000000, 0x42006000, 0x01290000,
-	0x41786800, 0x41787800, 0x0401f90b, 0x59301008,
-	0x4a01a006, 0x55000000, 0x5808000b, 0x82000500,
-	0x00ffffff, 0x58080c0a, 0x800408f0, 0x80040540,
-	0x4801a007, 0x5808080a, 0x82040d00, 0xff000000,
-	0x59a80010, 0x82000500, 0x00ffffff, 0x80040540,
-	0x4801a008, 0x5808000c, 0x9c0001c0, 0x4801a009,
-	0x5808000d, 0x9c0001c0, 0x4801a00a, 0x5808000e,
-	0x9c0001c0, 0x4801a00b, 0x5808000f, 0x9c0001c0,
-	0x4801a00c, 0x59a80002, 0x4801a00d, 0x59a80003,
-	0x4801a00e, 0x59a80000, 0x4801a00f, 0x59a80001,
-	0x4801a010, 0x58080010, 0x4801a011, 0x58080011,
-	0x4801a012, 0x58080012, 0x4801a013, 0x58080013,
-	0x4801a014, 0x4979a015, 0x4979a016, 0x4979a017,
-	0x4979a018, 0x42000800, 0x00000013, 0x42001000,
-	0x0000dc00, 0x0401f0f6, 0x0401fcfc, 0x5930001c,
-	0x800001c0, 0x04000008, 0x4a01a006, 0x01000000,
-	0x4a01a407, 0x00000003, 0x42000800, 0x00000002,
-	0x0401f028, 0x4a01a006, 0x02000000, 0x41780800,
-	0x836c0580, 0x00000004, 0x04020003, 0x84040d42,
-	0x0401f00d, 0x0201f800, 0x00104e0d, 0x04020003,
-	0x84040d4a, 0x0401f002, 0x84040d48, 0x59a80026,
-	0x8c000506, 0x04020003, 0x8c00050a, 0x04000002,
-	0x84040d46, 0x4805a207, 0x59c40085, 0x48031004,
-	0x4c580000, 0x4c500000, 0x4c540000, 0x4200b000,
-	0x00000006, 0x8388a400, 0x00000000, 0x82d0ac00,
-	0x00000008, 0x0201f800, 0x0010a93e, 0x5c00a800,
-	0x5c00a000, 0x5c00b000, 0x42000800, 0x00000008,
-	0x42001000, 0x0000dc00, 0x0401f0c1, 0x0401fcb9,
-	0x4a01a006, 0x56000000, 0x59340006, 0x4801a007,
-	0x59340007, 0x4801a008, 0x42000800, 0x00000003,
-	0x42001000, 0x0000dc00, 0x0401f0b5, 0x4803c856,
-	0x0401fcba, 0x5930081c, 0x800409c0, 0x0400000e,
-	0x82040580, 0x0000ffff, 0x04000004, 0x82040480,
-	0x00000007, 0x04021008, 0x4a01a006, 0x01000000,
-	0x4a01a407, 0x00000003, 0x42000800, 0x00000002,
-	0x0401f012, 0x4a01a006, 0x0200001c, 0x4a01a007,
-	0x00000001, 0x42001000, 0x0010b2ec, 0x50080000,
-	0x9c0001c0, 0x4801a009, 0x59a80010, 0x4801a00a,
-	0x59a80002, 0x59a80803, 0x4801a00b, 0x4805a00c,
-	0x42000800, 0x00000007, 0x42001000, 0x0000dc00,
-	0x0401f08f, 0x4d2c0000, 0x0401fc86, 0x59325808,
-	0x592c0008, 0x82000500, 0x00ffffff, 0x4801a001,
-	0x4a01a006, 0x51000000, 0x5c025800, 0x0201f000,
-	0x001070bc, 0x4803c856, 0x59a80810, 0x82040d00,
-	0x000000ff, 0x59325808, 0x59326809, 0x59a83026,
-	0x8c18350a, 0x04020008, 0x8c00050e, 0x04020006,
-	0x80001d80, 0x59a82010, 0x82102500, 0x000000ff,
-	0x0401f001, 0x59300406, 0x4803c857, 0x82000d80,
-	0x00000009, 0x04000006, 0x82000d80, 0x0000000a,
-	0x0400002e, 0x0201f800, 0x00100615, 0x59300015,
-	0x8c00051e, 0x04020020, 0x42005000, 0x04000000,
-	0x42006000, 0x05000000, 0x592c040a, 0x82000500,
-	0x00000030, 0x800000e0, 0x80306540, 0x5934000a,
-	0x8c000508, 0x04000002, 0x84306546, 0x41786800,
-	0x41787800, 0x0401f831, 0x59300c14, 0x80040000,
-	0x48026414, 0x40040000, 0x800000d0, 0x82000540,
-	0x00000020, 0x4801a403, 0x83180d40, 0x00000038,
-	0x42001000, 0x0000c920, 0x0401f868, 0x0201f000,
-	0x00105d8b, 0x59a80026, 0x82000500, 0x00000028,
-	0x04000003, 0x497a6a12, 0x0401f7dc, 0x4a026a12,
-	0x0000ff00, 0x0401f7d9, 0x42005000, 0x02000000,
-	0x42006000, 0x20290000, 0x41786800, 0x41787800,
-	0x0401f812, 0x83180d40, 0x00000038, 0x42001000,
-	0x0000c9a0, 0x0401f851, 0x42000800, 0x000007d0,
-	0x59300011, 0x82000500, 0xfff00000, 0x80000540,
-	0x04000003, 0x42000800, 0x00001b58, 0x41781000,
-	0x0201f000, 0x00105d8d, 0x4201a000, 0x00000000,
-	0x0401f003, 0x4201a000, 0x00000011, 0x59340a12,
-	0x82040d00, 0x0000ff00, 0x59a80010, 0x82000500,
-	0x000000ff, 0x900001c0, 0x80040540, 0x80d00540,
-	0x44034800, 0x81a5a000, 0x59340002, 0x82000500,
-	0x00ffffff, 0x80280540, 0x4801a000, 0x59a80010,
-	0x4801a001, 0x4831a002, 0x82340540, 0x00000000,
-	0x4801a003, 0x59300402, 0x4801a404, 0x59300a02,
-	0x4805a204, 0x8c30652e, 0x04000003, 0x4805a404,
-	0x4801a204, 0x483da005, 0x1c01f000, 0x4807c857,
-	0x4c040000, 0x0401f82a, 0x5c000800, 0x40040000,
-	0x80081540, 0x800000c4, 0x82000540, 0x00002000,
-	0x4803910a, 0x59b400f6, 0x82000500, 0x00000018,
-	0x040207fd, 0x4a0368f0, 0x0010b342, 0x42001800,
-	0x0010b343, 0x580c0000, 0x4803c857, 0x580c0002,
-	0x4803c857, 0x580c0004, 0x4803c857, 0x4a0368f1,
-	0x0010b349, 0x480b68f3, 0x4a0378e4, 0x00008000,
-	0x0201f000, 0x00105d86, 0x4807c857, 0x480a2800,
-	0x4c040000, 0x0401f80a, 0x5c000800, 0x59b400f6,
-	0x8c00050a, 0x040207fe, 0x49a768f2, 0x480768f4,
-	0x4a0378e4, 0x00008000, 0x1c01f000, 0x4a0378e4,
-	0x0000c000, 0x59bc00e4, 0x8c000520, 0x0400000c,
-	0x4a0378e4, 0x00008000, 0x42007000, 0x000003e8,
-	0x59bc00e4, 0x8c000520, 0x040007f5, 0x80387040,
-	0x02000800, 0x00100615, 0x0401f7fa, 0x1c01f000,
-	0x82000500, 0xffff0000, 0x82000580, 0x01050000,
-	0x0402000d, 0x599c0818, 0x8c040d10, 0x0400000a,
-	0x59a80807, 0x8c040d0a, 0x04000007, 0x42001000,
-	0x0000804f, 0x41781800, 0x41782000, 0x0201f800,
-	0x00103857, 0x1c01f000, 0x41781000, 0x42026000,
-	0x0010cfc0, 0x59a8180e, 0x480a6402, 0x4a026202,
-	0x0000ffff, 0x80081000, 0x800c1840, 0x04000004,
-	0x83326400, 0x00000024, 0x0401f7f8, 0x1c01f000,
-	0x4933c857, 0x59300203, 0x82000580, 0x00000000,
-	0x0400002c, 0x59300406, 0x4803c857, 0x82000d80,
-	0x00000004, 0x04000011, 0x82000d80, 0x00000001,
-	0x0400000e, 0x82000d80, 0x00000003, 0x04000006,
-	0x82000d80, 0x00000006, 0x04020011, 0x0201f800,
-	0x0010a3fa, 0x5930001c, 0x800001c0, 0x02020800,
-	0x0010961a, 0x0401f00a, 0x5930081e, 0x4807c857,
-	0x800409c0, 0x04000006, 0x5804001c, 0x4803c857,
-	0x81300580, 0x04020002, 0x4978081c, 0x497a6008,
-	0x4a026004, 0x00004000, 0x59a80037, 0x82000c80,
-	0x00000051, 0x04001002, 0x80000102, 0x48026206,
-	0x497a6205, 0x497a6009, 0x4a026406, 0x00000007,
-	0x1c01f000, 0x8166c9c0, 0x0400001c, 0x41626000,
-	0x41580000, 0x59300a03, 0x82040d80, 0x00000000,
-	0x04000008, 0x83326400, 0x00000024, 0x81300c80,
-	0x040017f9, 0x42026000, 0x0010cfc0, 0x0401f7f6,
-	0x4933c857, 0x8166c840, 0x83300c00, 0x00000024,
-	0x80040480, 0x04021006, 0x4006c000, 0x4a026203,
-	0x00000008, 0x813261c0, 0x1c01f000, 0x4202c000,
-	0x0010cfc0, 0x0401f7fa, 0x42000000, 0x0010b653,
-	0x0201f800, 0x0010a86e, 0x4933c856, 0x417a6000,
-	0x0401f7f5, 0x4933c857, 0x83380580, 0x00000013,
-	0x0402000b, 0x59300004, 0x8c00053e, 0x04000007,
-	0x0201f800, 0x0010698c, 0x0201f800, 0x001068f6,
-	0x0201f800, 0x00106982, 0x1c01f000, 0x4933c857,
-	0x59880053, 0x80000000, 0x48031053, 0x1c01f000,
-	0x4933c857, 0x59300203, 0x82003480, 0x0000000e,
-	0x02021800, 0x00100615, 0x4d2c0000, 0x0c01f803,
-	0x5c025800, 0x1c01f000, 0x00107718, 0x00107c84,
-	0x00107dd4, 0x00107718, 0x00107e3a, 0x0010787c,
-	0x00107718, 0x00107718, 0x00107c1a, 0x00107718,
-	0x00107718, 0x00107718, 0x00107718, 0x00107718,
-	0x0201f800, 0x00100615, 0x4933c857, 0x59300203,
-	0x82003480, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f001, 0x0010772f, 0x001087f0, 0x0010772f,
-	0x0010772f, 0x0010772f, 0x0010772f, 0x0010772f,
-	0x0010772f, 0x0010879a, 0x0010880c, 0x0010887a,
-	0x0010880c, 0x0010887a, 0x0010772f, 0x0201f800,
-	0x00100615, 0x0201f800, 0x00100615, 0x4933c857,
-	0x4d2c0000, 0x59325808, 0x59300203, 0x82003480,
-	0x0000000e, 0x02021800, 0x00100615, 0x0c01f803,
-	0x5c025800, 0x1c01f000, 0x0010774c, 0x0010774c,
-	0x0010774c, 0x00107768, 0x001077b4, 0x0010774c,
-	0x0010774c, 0x0010774c, 0x0010774e, 0x0010774c,
-	0x0010774c, 0x0010774c, 0x0010774c, 0x0010774c,
-	0x0201f800, 0x00100615, 0x4933c857, 0x83380580,
-	0x00000040, 0x02020800, 0x00100615, 0x4a026007,
-	0x00082000, 0x4a026203, 0x00000003, 0x493a6403,
-	0x4a025c08, 0x00000001, 0x592c000d, 0x48026011,
-	0x497a6013, 0x592c0208, 0x800000c2, 0x800010c4,
-	0x80081400, 0x480a6206, 0x0201f800, 0x00100f9c,
-	0x42000800, 0x80000060, 0x0201f000, 0x00106466,
-	0x4933c857, 0x83380480, 0x00000050, 0x02021800,
-	0x00100615, 0x83380480, 0x00000049, 0x02001800,
-	0x00100615, 0x0c01f001, 0x0010777b, 0x00107786,
-	0x00107779, 0x00107779, 0x00107779, 0x00107779,
-	0x00107791, 0x0201f800, 0x00100615, 0x4a026203,
-	0x00000004, 0x4a025c08, 0x00000002, 0x592c0207,
-	0x48025c09, 0x592c0209, 0x48025a07, 0x592c000c,
-	0x4802580d, 0x1c01f000, 0x0201f800, 0x001068c1,
-	0x0201f800, 0x00108df4, 0x04000005, 0x4a025a06,
-	0x00000006, 0x0201f800, 0x00020381, 0x0201f000,
-	0x000208b4, 0x0201f800, 0x001068c1, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x42003000, 0x00000014, 0x41782800, 0x42002000,
-	0x00000002, 0x4d400000, 0x4d440000, 0x59368c03,
-	0x42028000, 0x00000029, 0x0201f800, 0x0010962a,
-	0x5c028800, 0x5c028000, 0x42000000, 0x0010b663,
-	0x0201f800, 0x0010a86e, 0x0201f800, 0x00108df4,
-	0x02000000, 0x000208b4, 0x4a025a06, 0x00000029,
-	0x0201f800, 0x00020381, 0x0201f000, 0x000208b4,
-	0x4933c857, 0x83380580, 0x00000048, 0x04000005,
-	0x83380580, 0x00000053, 0x02020800, 0x00100615,
-	0x592c0206, 0x82000580, 0x00000007, 0x04000009,
-	0x59300011, 0x80000540, 0x04000006, 0x592c080c,
-	0x80040480, 0x4802580c, 0x4a025a06, 0x00000015,
-	0x592c0206, 0x80000540, 0x04020003, 0x4a025a06,
-	0x00000000, 0x0201f800, 0x00020381, 0x0201f000,
-	0x000208b4, 0x4933c857, 0x4d2c0000, 0x4c500000,
-	0x4c540000, 0x4c580000, 0x0201f800, 0x0010082a,
-	0x02000800, 0x00100615, 0x497a5a06, 0x59a8006e,
-	0x82000500, 0x0000f000, 0x48025c07, 0x59a80816,
-	0x82040c00, 0x00000018, 0x48065a07, 0x412c7800,
-	0x4d2c0000, 0x41cca000, 0x42002800, 0x00000001,
-	0x42001000, 0x0000002c, 0x82040480, 0x0000002d,
-	0x04021006, 0x832cac00, 0x00000009, 0x0201f800,
-	0x0010894a, 0x0401f02e, 0x40043000, 0x42000800,
-	0x0000002c, 0x832cac00, 0x00000009, 0x0201f800,
-	0x0010894a, 0x82183480, 0x0000002c, 0x0201f800,
-	0x0010082a, 0x0400001a, 0x80142800, 0x4a025804,
-	0x00000110, 0x492c7801, 0x82180c80, 0x0000003d,
-	0x04021007, 0x40180800, 0x832cac00, 0x00000005,
-	0x0201f800, 0x0010894a, 0x0401f015, 0x82081400,
-	0x0000003c, 0x82183480, 0x0000003c, 0x42000800,
-	0x0000003c, 0x412c7800, 0x832cac00, 0x00000005,
-	0x0201f800, 0x0010894a, 0x0401f7e5, 0x5c025800,
-	0x592c0206, 0x8400055e, 0x48025a06, 0x592c0407,
-	0x80080540, 0x48025c07, 0x0401f002, 0x5c025800,
-	0x813669c0, 0x04000003, 0x59343403, 0x0401f003,
-	0x42003000, 0x0000ffff, 0x49325808, 0x481a5c06,
-	0x82100580, 0x00000054, 0x04020002, 0x491e5813,
-	0x841401c0, 0x80100540, 0x48025804, 0x592c0001,
-	0x497a5801, 0x4c000000, 0x0201f800, 0x00020381,
-	0x5c025800, 0x812e59c0, 0x040207f9, 0x5c00b000,
-	0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000,
-	0x4803c856, 0x4c5c0000, 0x4d2c0000, 0x4c500000,
-	0x4c540000, 0x4c580000, 0x412cb800, 0x592c040b,
-	0x8c000516, 0x04000003, 0x41cca000, 0x0401f003,
-	0x83cca400, 0x00000006, 0x4008b000, 0x41781000,
-	0x82580480, 0x00000012, 0x04001004, 0x4200b000,
-	0x00000012, 0x40001000, 0x4c080000, 0x4d2c0000,
-	0x0201f800, 0x0010082a, 0x04000023, 0x5c001800,
-	0x492c1801, 0x485a5800, 0x832cac00, 0x00000002,
-	0x0201f800, 0x0010a94f, 0x585c040b, 0x8c000500,
-	0x0400000e, 0x832c1400, 0x00000002, 0x8c000516,
-	0x04000003, 0x82081400, 0x00000006, 0x46001000,
-	0x00000001, 0x80081000, 0x46001000, 0x00000900,
-	0x84000500, 0x4800bc0b, 0x5c001000, 0x800811c0,
-	0x040207da, 0x82000540, 0x00000001, 0x5c00b000,
-	0x5c00a800, 0x5c00a000, 0x5c025800, 0x5c00b800,
-	0x1c01f000, 0x5c025800, 0x5c001000, 0x0401f7f8,
-	0x4933c857, 0x83380d80, 0x00000015, 0x04020003,
-	0x0201f000, 0x000208b4, 0x83380d80, 0x00000016,
-	0x02020800, 0x00100615, 0x0201f000, 0x000208b4,
-	0x4933c857, 0x4d2c0000, 0x4c500000, 0x4c540000,
-	0x4c580000, 0x59325808, 0x83cca400, 0x00000006,
-	0x59cc1806, 0x820c0580, 0x01000000, 0x04020004,
-	0x4200b000, 0x00000002, 0x0401f00f, 0x4200b000,
-	0x00000008, 0x832cac00, 0x00000005, 0x0201f800,
-	0x0010a93e, 0x8c0c1d00, 0x0400000b, 0x4200b000,
-	0x00000008, 0x592e5801, 0x812e59c0, 0x02000800,
-	0x00100615, 0x832cac00, 0x00000005, 0x0201f800,
-	0x0010a93e, 0x0401f816, 0x5c00b000, 0x5c00a800,
-	0x5c00a000, 0x5c025800, 0x1c01f000, 0x4933c857,
-	0x4c500000, 0x4c540000, 0x4c580000, 0x83cca400,
-	0x00000006, 0x5930a808, 0x8254ac00, 0x00000005,
-	0x4200b000, 0x00000007, 0x0201f800, 0x0010a93e,
-	0x5c00b000, 0x5c00a800, 0x5c00a000, 0x4933c857,
-	0x0201f800, 0x00108df4, 0x02000000, 0x000208b4,
-	0x4d2c0000, 0x0201f800, 0x00109360, 0x0402000b,
-	0x41780800, 0x4d400000, 0x42028000, 0x00000000,
-	0x0201f800, 0x00109204, 0x5c028000, 0x5c025800,
-	0x0201f000, 0x000208b4, 0x5931d821, 0x58ef400b,
-	0x58ee580d, 0x4a025a04, 0x00000103, 0x58ec0009,
-	0x0801f800, 0x5c025800, 0x0201f000, 0x000208b4,
-	0x4933c857, 0x59cc1806, 0x820c0580, 0x02000000,
-	0x04020014, 0x4a026802, 0x00fffffd, 0x5934000a,
-	0x84000504, 0x4802680a, 0x59300808, 0x800409c0,
-	0x02000000, 0x000208b4, 0x4a000a04, 0x00000103,
-	0x480c0805, 0x5931d821, 0x58ef400b, 0x58ee580d,
-	0x58ec0009, 0x0801f800, 0x0201f000, 0x000208b4,
-	0x42000000, 0x0010b66b, 0x0201f800, 0x0010a86e,
-	0x4c0c0000, 0x0401f804, 0x5c001800, 0x040207eb,
-	0x1c01f000, 0x4933c857, 0x4d2c0000, 0x59325808,
-	0x812e59c0, 0x04020009, 0x497a6206, 0x497a6205,
-	0x4d380000, 0x42027000, 0x00000022, 0x0401fb77,
-	0x5c027000, 0x80000580, 0x5c025800, 0x1c01f000,
-	0x4933c857, 0x4d2c0000, 0x4c500000, 0x4c540000,
-	0x4c580000, 0x59325808, 0x592e5801, 0x832cac00,
-	0x00000005, 0x83cca400, 0x00000006, 0x59a8086e,
-	0x82040d00, 0x000003ff, 0x82041480, 0x0000000f,
-	0x0400101b, 0x4200b000, 0x0000000f, 0x0201f800,
-	0x0010a93e, 0x592e5801, 0x832cac00, 0x00000005,
-	0x82080c80, 0x0000000f, 0x0400100d, 0x4200b000,
-	0x0000000f, 0x0201f800, 0x0010a93e, 0x592e5801,
-	0x832cac00, 0x00000005, 0x82041480, 0x0000000f,
-	0x04001007, 0x42001000, 0x0000000f, 0x4008b000,
-	0x0201f800, 0x0010a93e, 0x0401f004, 0x4004b000,
-	0x0201f800, 0x0010a93e, 0x5931d821, 0x58ef400b,
-	0x58ee580d, 0x4a025a04, 0x00000103, 0x592e5801,
-	0x58ec0009, 0x0801f800, 0x0201f800, 0x000208b4,
-	0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800,
-	0x1c01f000, 0x4933c857, 0x4d2c0000, 0x4c500000,
-	0x4c540000, 0x4c580000, 0x59cc0006, 0x82000d80,
-	0x01000000, 0x0400002c, 0x59cc0007, 0x9000b1c0,
-	0x8258b500, 0x000000ff, 0x8058b104, 0x8258b400,
-	0x00000002, 0x82580c80, 0x00000007, 0x04001003,
-	0x4200b000, 0x00000006, 0x83cca400, 0x00000006,
-	0x59301008, 0x800811c0, 0x02000800, 0x00100615,
-	0x8208ac00, 0x00000005, 0x0201f800, 0x0010a93e,
-	0x82000d00, 0xff000000, 0x800409c0, 0x04000019,
-	0x8200b500, 0x000000ff, 0x8058b104, 0x82580c80,
-	0x0000000e, 0x04001003, 0x4200b000, 0x0000000d,
-	0x58081001, 0x800811c0, 0x02000800, 0x00100615,
-	0x8208ac00, 0x00000005, 0x0201f800, 0x0010a93e,
-	0x0401f008, 0x59301008, 0x800811c0, 0x02000800,
-	0x00100615, 0x48001005, 0x59cc0007, 0x48001006,
-	0x0401ff3b, 0x5c00b000, 0x5c00a800, 0x5c00a000,
-	0x5c025800, 0x1c01f000, 0x4933c857, 0x42000800,
-	0x00000000, 0x59cc0006, 0x82000580, 0x02000000,
-	0x04000003, 0x42000800, 0x00000001, 0x4d2c0000,
-	0x59325808, 0x812e59c0, 0x02000800, 0x00100615,
-	0x48065a06, 0x0201f800, 0x00020381, 0x5c025800,
-	0x0201f000, 0x000208b4, 0x4933c857, 0x4d2c0000,
-	0x4c500000, 0x4c540000, 0x4c580000, 0x4200b000,
-	0x00000002, 0x59cc0806, 0x82040580, 0x01000000,
-	0x04000004, 0x8204b500, 0x0000ffff, 0x8058b104,
-	0x83cca400, 0x00000006, 0x59300008, 0x8200ac00,
-	0x00000005, 0x0201f800, 0x0010a93e, 0x0401ff0c,
-	0x5c00b000, 0x5c00a800, 0x5c00a000, 0x5c025800,
-	0x1c01f000, 0x4933c857, 0x4803c857, 0x4807c857,
-	0x480bc857, 0x480fc857, 0x4813c857, 0x481bc857,
-	0x492fc857, 0x4d2c0000, 0x4c000000, 0x0201f800,
-	0x00100819, 0x5c000000, 0x0400000f, 0x48025803,
-	0x5c000000, 0x4802580a, 0x4c000000, 0x481a5801,
-	0x48125809, 0x48065804, 0x480a5807, 0x480e5808,
-	0x412c1000, 0x0201f800, 0x001008a1, 0x82000540,
-	0x00000001, 0x5c025800, 0x1c01f000, 0x4933c857,
-	0x4d1c0000, 0x59cc0001, 0x82000500, 0x00ffffff,
-	0x59341002, 0x82081500, 0x00ffffff, 0x80080580,
-	0x0402001f, 0x497a6205, 0x4d380000, 0x42027000,
-	0x00000035, 0x0201f800, 0x00109183, 0x5c027000,
-	0x04020012, 0x591c001c, 0x800001c0, 0x0400000f,
-	0x497a381c, 0x591c0414, 0x8c000502, 0x02000800,
-	0x00100615, 0x84000502, 0x48023c14, 0x591c1406,
-	0x82080580, 0x00000003, 0x04000006, 0x82080580,
-	0x00000006, 0x04000005, 0x0401fc9e, 0x0401f004,
-	0x0401f805, 0x0401f002, 0x0401f8c0, 0x5c023800,
-	0x1c01f000, 0x4d2c0000, 0x591e5808, 0x4933c857,
-	0x491fc857, 0x493bc857, 0x492fc857, 0x83380580,
-	0x00000015, 0x040000b3, 0x83380580, 0x00000016,
-	0x040200ae, 0x4d300000, 0x411e6000, 0x59cc0207,
-	0x4803c857, 0x82000d00, 0x0000ff00, 0x82040580,
-	0x00001700, 0x04000004, 0x82040580, 0x00000300,
-	0x0402005b, 0x591c0203, 0x4803c857, 0x82000580,
-	0x0000000d, 0x0400003f, 0x812e59c0, 0x0400009a,
-	0x591c0202, 0x4803c857, 0x82000580, 0x0000ffff,
-	0x0402007e, 0x592c020a, 0x4803c857, 0x82000500,
-	0x00000003, 0x82000580, 0x00000002, 0x04020007,
-	0x592c080f, 0x591c0011, 0x4803c857, 0x4807c857,
-	0x80040580, 0x04020071, 0x591c0414, 0x4803c857,
-	0x8c000500, 0x0402006d, 0x41780800, 0x591c1206,
-	0x42000000, 0x0000000a, 0x0201f800, 0x001063ee,
-	0x592c0406, 0x4803c857, 0x800001c0, 0x0400000c,
-	0x80080c80, 0x04001004, 0x02020800, 0x00100615,
-	0x80001040, 0x480a5c06, 0x800811c0, 0x04020004,
-	0x0201f800, 0x00108b3c, 0x0401f06b, 0x0201f800,
-	0x00108ee7, 0x591c0817, 0x591c0018, 0x48065808,
-	0x48025809, 0x59300007, 0x8c000500, 0x02020800,
-	0x00100ee4, 0x497a3808, 0x0201f800, 0x000201ee,
-	0x0402004a, 0x411e6000, 0x0401fc3e, 0x0401f05a,
-	0x0401fc6d, 0x04000013, 0x49366009, 0x4a026406,
-	0x00000003, 0x492e6008, 0x591c0817, 0x591c1018,
-	0x48066017, 0x480a6018, 0x4d380000, 0x591e7403,
-	0x4d300000, 0x411e6000, 0x0401fc2e, 0x5c026000,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x0401f046,
-	0x59a80039, 0x48023a05, 0x0401f043, 0x59cc0407,
-	0x82000580, 0x0000000b, 0x04020025, 0x59340a00,
-	0x84040d0e, 0x48066a00, 0x592c0a04, 0x82040d00,
-	0x000000ff, 0x82040d80, 0x00000014, 0x04000003,
-	0x4a02621d, 0x00000003, 0x59300007, 0x8c000500,
-	0x02020800, 0x00100ee4, 0x4d400000, 0x42028000,
-	0x00000003, 0x592c0a08, 0x0201f800, 0x00104bee,
-	0x0201f800, 0x00020381, 0x5c028000, 0x497a6008,
-	0x4a026403, 0x00000085, 0x4a026203, 0x00000009,
-	0x4a026406, 0x00000002, 0x42000800, 0x8000404b,
-	0x0201f800, 0x00020855, 0x0401f01b, 0x59cc0207,
-	0x82000580, 0x00002a00, 0x04020004, 0x59a80039,
-	0x48023a05, 0x0401f014, 0x812e59c0, 0x02000800,
-	0x00100615, 0x4a025a04, 0x00000103, 0x591c0007,
-	0x8c000500, 0x02020800, 0x00100ee4, 0x591c0402,
-	0x48025c06, 0x4a025a06, 0x00000003, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00107698, 0x0201f800,
-	0x00104801, 0x5c026000, 0x0201f800, 0x000208b4,
-	0x0401f002, 0x5c026000, 0x5c025800, 0x1c01f000,
-	0x0401f819, 0x0401f7fd, 0x4933c857, 0x83380580,
-	0x00000015, 0x04020004, 0x59a80039, 0x48023a05,
-	0x0401f00d, 0x83380580, 0x00000016, 0x0402000d,
-	0x4d300000, 0x411e6000, 0x0201f800, 0x0010a3fa,
-	0x0201f800, 0x00020831, 0x0201f800, 0x000208b4,
-	0x5c026000, 0x497a381c, 0x0201f800, 0x000208b4,
-	0x1c01f000, 0x591c0414, 0x84000540, 0x48023c14,
-	0x59cc100b, 0x4933c857, 0x491fc857, 0x492fc857,
-	0x4803c857, 0x480bc857, 0x8c08153c, 0x04000006,
-	0x59a80039, 0x48023a05, 0x497a381c, 0x0201f000,
-	0x000208b4, 0x4d300000, 0x411e6000, 0x0201f800,
-	0x0010898b, 0x5c026000, 0x591c0406, 0x82000580,
-	0x00000000, 0x02000000, 0x000208b4, 0x591c0403,
-	0x82000580, 0x00000050, 0x0402000d, 0x4d300000,
-	0x411e6000, 0x4a026203, 0x00000001, 0x42000800,
-	0x80000043, 0x0201f800, 0x00020855, 0x5c026000,
-	0x497a381c, 0x0201f000, 0x000208b4, 0x591c0203,
-	0x82000580, 0x0000000d, 0x04000014, 0x812e59c0,
-	0x02000800, 0x00100615, 0x591c0203, 0x82000580,
-	0x00000004, 0x04020011, 0x592c020a, 0x8c000502,
-	0x0400000e, 0x4a023812, 0x0fffffff, 0x592c0208,
-	0x8400051e, 0x48025a08, 0x42000000, 0x00000001,
-	0x48023a14, 0x0401f021, 0x42000000, 0x00000007,
-	0x48023a14, 0x0401f01d, 0x592c020a, 0x4803c857,
-	0x8c000500, 0x0402000b, 0x8c000502, 0x040007f7,
-	0x591c0414, 0x8c00051c, 0x040207eb, 0x591c0011,
-	0x4803c857, 0x800001c0, 0x040007f0, 0x0401f7e6,
-	0x8c08153a, 0x040207ed, 0x59cc000a, 0x592c180f,
-	0x4803c857, 0x480fc857, 0x800c0580, 0x040007e7,
-	0x59cc000a, 0x4803c857, 0x48023816, 0x42000000,
-	0x00000005, 0x48023a14, 0x0201f000, 0x0010901b,
-	0x4933c857, 0x4d1c0000, 0x59cc0001, 0x59341002,
-	0x80080580, 0x82000500, 0x00ffffff, 0x04020041,
-	0x59301419, 0x0201f800, 0x001091d9, 0x02000800,
-	0x00100615, 0x591c1406, 0x82080580, 0x00000007,
-	0x04000038, 0x82080580, 0x00000002, 0x04000035,
-	0x82080580, 0x00000000, 0x04000032, 0x591c0202,
-	0x82000d80, 0x0000ffff, 0x04000004, 0x59301a19,
-	0x800c0580, 0x0402002b, 0x83380580, 0x00000015,
-	0x04000026, 0x4d300000, 0x4d2c0000, 0x411e6000,
-	0x59325808, 0x0201f800, 0x00108df4, 0x02000800,
-	0x00100615, 0x592c0204, 0x82000500, 0x000000ff,
-	0x82000580, 0x00000014, 0x04000003, 0x4a02621d,
-	0x00000003, 0x42028000, 0x00000003, 0x592c0a08,
-	0x0201f800, 0x00104bee, 0x0201f800, 0x00020381,
-	0x5c025800, 0x497a6008, 0x4a026403, 0x00000085,
-	0x4a026203, 0x00000009, 0x4a026406, 0x00000002,
-	0x42000800, 0x8000404b, 0x0201f800, 0x00020855,
-	0x5c026000, 0x0401f003, 0x59a80039, 0x48023a05,
-	0x497a381c, 0x0201f800, 0x000208b4, 0x5c023800,
-	0x1c01f000, 0x4933c857, 0x4c580000, 0x4d2c0000,
-	0x59325808, 0x83383580, 0x00000015, 0x04000010,
-	0x59342200, 0x84102502, 0x48126a00, 0x0201f800,
-	0x00108df4, 0x04000066, 0x0201f800, 0x00109360,
-	0x04020005, 0x4200b000, 0x00000002, 0x0201f800,
-	0x00109346, 0x0401fa0d, 0x0401f079, 0x83cc1400,
-	0x00000008, 0x4200b000, 0x00000002, 0x83341c00,
-	0x00000006, 0x0201f800, 0x001082ff, 0x04020015,
-	0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002,
-	0x83341c00, 0x00000008, 0x0201f800, 0x001082ff,
-	0x0402000c, 0x0201f800, 0x00101e1b, 0x59342200,
-	0x59cc1007, 0x800811c0, 0x04000003, 0x480a6801,
-	0x84102542, 0x8410251a, 0x48126a00, 0x0401f05f,
-	0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2,
-	0x5c027800, 0x42000000, 0x0010b663, 0x0201f800,
-	0x0010a86e, 0x59340200, 0x84000558, 0x48026a00,
-	0x4d300000, 0x0201f800, 0x00020892, 0x02000800,
-	0x00100615, 0x49366009, 0x497a6008, 0x4a026406,
-	0x00000001, 0x4a026403, 0x00000001, 0x42003000,
-	0x00000003, 0x0201f800, 0x0010a766, 0x0201f800,
-	0x0010393e, 0x04000011, 0x41782800, 0x42003000,
-	0x00000001, 0x4d400000, 0x42028000, 0x00000029,
-	0x0201f800, 0x0010a250, 0x5c028000, 0x4a026406,
-	0x00000004, 0x4a026203, 0x00000007, 0x4a026420,
-	0x00000001, 0x0401f009, 0x4a026203, 0x00000001,
-	0x42000800, 0x0000000b, 0x0201f800, 0x001043c7,
-	0x0201f800, 0x00106470, 0x5c026000, 0x0201f800,
-	0x00108df4, 0x04000022, 0x0201f800, 0x00109360,
-	0x04020022, 0x0401f9b1, 0x0401f01d, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200,
-	0x84000558, 0x48026a00, 0x42003000, 0x00000003,
-	0x41782800, 0x42002000, 0x00000005, 0x4d400000,
-	0x4d440000, 0x59368c03, 0x42028000, 0x00000029,
-	0x0201f800, 0x0010962a, 0x5c028800, 0x5c028000,
-	0x5c027800, 0x0201f800, 0x00101e1b, 0x0201f800,
-	0x000208b4, 0x0401f002, 0x0401fca9, 0x5c025800,
-	0x5c00b000, 0x1c01f000, 0x4933c857, 0x41380000,
-	0x83383480, 0x00000056, 0x02021800, 0x00100615,
-	0x0c01f001, 0x00107c7e, 0x00107c79, 0x00107c7e,
-	0x00107c7e, 0x00107c7e, 0x00107c7e, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c7e, 0x00107c77, 0x00107c7e, 0x00107c7e,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c7e, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c7e,
-	0x00107c7e, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77,
-	0x00107c77, 0x00107c7e, 0x00107c7e, 0x00107c77,
-	0x00107c7e, 0x00107c7e, 0x00107c77, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c7e, 0x00107c77,
-	0x00107c77, 0x00107c77, 0x00107c7e, 0x0201f800,
-	0x00100615, 0x4a026203, 0x00000001, 0x493a6403,
-	0x0201f000, 0x00106470, 0x4933c857, 0x4a026203,
-	0x00000001, 0x493a6403, 0x0201f000, 0x00106470,
-	0x59300403, 0x82003480, 0x00000056, 0x02021800,
-	0x00100615, 0x83383580, 0x00000013, 0x04000096,
-	0x83383580, 0x00000027, 0x0402004c, 0x4933c857,
-	0x0201f800, 0x001068f6, 0x0201f800, 0x00108ef1,
-	0x0400000b, 0x0201f800, 0x00108f05, 0x04000041,
-	0x59300403, 0x82000d80, 0x00000022, 0x04020038,
-	0x0401fc61, 0x0400003a, 0x0401f03a, 0x0201f800,
-	0x00101e1b, 0x42000800, 0x00000007, 0x0201f800,
-	0x001043c7, 0x0401f901, 0x4d440000, 0x59368c03,
-	0x83440580, 0x000007fe, 0x04020008, 0x59a81026,
-	0x84081540, 0x0201f800, 0x00104e0d, 0x04020002,
-	0x8408154a, 0x480b5026, 0x42028000, 0x00000029,
-	0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2,
-	0x5c027800, 0x836c0580, 0x00000003, 0x0400000c,
-	0x59326809, 0x59340008, 0x800001c0, 0x04020008,
-	0x59368c03, 0x4933c857, 0x4937c857, 0x4947c857,
-	0x0201f800, 0x00104451, 0x0401f00c, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x42003000,
-	0x00000015, 0x41782800, 0x42002000, 0x00000003,
-	0x0201f800, 0x0010962a, 0x5c028800, 0x0201f800,
-	0x001090ec, 0x0201f000, 0x000208b4, 0x1c01f000,
-	0x0401f8ce, 0x0401f7fa, 0x83380580, 0x00000014,
-	0x0400000c, 0x4933c857, 0x0201f800, 0x00106cb4,
-	0x02020000, 0x001076fb, 0x59300203, 0x82000580,
-	0x00000002, 0x040000ef, 0x0201f800, 0x00100615,
-	0x4933c857, 0x0201f800, 0x001068f6, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x42003000, 0x00000016, 0x41782800, 0x4d400000,
-	0x4d440000, 0x59368c03, 0x42002000, 0x00000009,
-	0x42028000, 0x00000029, 0x0201f800, 0x0010962a,
-	0x5c028800, 0x5c028000, 0x42000000, 0x0010b663,
-	0x0201f800, 0x0010a86e, 0x0201f800, 0x00108ef1,
-	0x0402000c, 0x0201f800, 0x00101e1b, 0x0401f89f,
-	0x59340c03, 0x82040580, 0x000007fe, 0x040207c8,
-	0x59a80826, 0x84040d40, 0x48075026, 0x0401f7c4,
-	0x0201f800, 0x00108f05, 0x04020003, 0x0401f893,
-	0x0401f7bf, 0x59300403, 0x82000d80, 0x00000032,
-	0x04020004, 0x0201f800, 0x001020b2, 0x0401f7b8,
-	0x59300403, 0x82000d80, 0x00000022, 0x04000887,
-	0x0401f7b3, 0x4933c857, 0x4803c857, 0x0c01f001,
-	0x00107da0, 0x00107da0, 0x00107da0, 0x00107da0,
-	0x00107da0, 0x00107da0, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d83, 0x00107da0,
-	0x00107d7a, 0x00107da0, 0x00107da0, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107da0, 0x00107da0, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d7a, 0x00107d91, 0x00107da0,
-	0x00107d7a, 0x00107d8a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107d8a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107da0, 0x00107d8d, 0x00107d7a,
-	0x00107d7c, 0x00107da0, 0x00107d7a, 0x00107da0,
-	0x00107da0, 0x00107d7a, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107da0, 0x00107d7a, 0x00107d7a,
-	0x00107d7a, 0x00107da0, 0x0201f800, 0x00100615,
-	0x4d2c0000, 0x59325808, 0x0201f800, 0x00020381,
-	0x5c025800, 0x0201f000, 0x000208b4, 0x4a026203,
-	0x00000005, 0x59a80039, 0x48026205, 0x59a80037,
-	0x48026206, 0x1c01f000, 0x5930081e, 0x49780a05,
-	0x0401f014, 0x0201f800, 0x001090ec, 0x0201f000,
-	0x000208b4, 0x0201f800, 0x001020b2, 0x0201f800,
-	0x0010698c, 0x04000005, 0x0201f800, 0x001068f6,
-	0x0201f000, 0x000208b4, 0x0201f800, 0x001068f6,
-	0x0201f800, 0x000208b4, 0x0201f000, 0x00106982,
-	0x4933c857, 0x4a026203, 0x00000002, 0x59a80037,
-	0x48026206, 0x1c01f000, 0x4933c857, 0x0201f800,
-	0x00108df4, 0x0400002a, 0x4d2c0000, 0x0201f800,
-	0x00109360, 0x0402000a, 0x4d400000, 0x42028000,
-	0x00000031, 0x42000800, 0x00000004, 0x0201f800,
-	0x00109204, 0x5c028000, 0x0401f01c, 0x59300c06,
-	0x82040580, 0x00000010, 0x04000004, 0x82040580,
-	0x00000011, 0x0402000a, 0x4a025a06, 0x00000031,
-	0x4a02580d, 0x00000004, 0x4a02580e, 0x000000ff,
-	0x0201f800, 0x00020381, 0x0401f00c, 0x592c0404,
-	0x8c00051e, 0x04000009, 0x4a025a04, 0x00000103,
-	0x4a025805, 0x01000000, 0x5931d821, 0x58ef400b,
-	0x58ec0009, 0x0801f800, 0x5c025800, 0x1c01f000,
-	0x4933c857, 0x59340400, 0x82000500, 0x000000ff,
-	0x82003480, 0x0000000c, 0x02021800, 0x00100615,
-	0x59303403, 0x82180d80, 0x0000004d, 0x02000000,
-	0x00109154, 0x82180d80, 0x00000033, 0x02000000,
-	0x0010910f, 0x82180d80, 0x00000028, 0x02000000,
-	0x00108f46, 0x82180d80, 0x00000029, 0x02000000,
-	0x00108f5a, 0x82180d80, 0x0000001f, 0x02000000,
-	0x001078af, 0x82180d80, 0x00000055, 0x02000000,
-	0x00107888, 0x82180d80, 0x00000000, 0x0400058e,
-	0x82180d80, 0x00000022, 0x02000000, 0x001078dc,
-	0x82180d80, 0x00000035, 0x02000000, 0x001079d7,
-	0x82180d80, 0x00000039, 0x04000536, 0x82180d80,
-	0x0000003d, 0x02000000, 0x0010790c, 0x82180d80,
-	0x00000044, 0x02000000, 0x00107949, 0x82180d80,
-	0x00000049, 0x02000000, 0x0010799e, 0x82180d80,
-	0x00000041, 0x02000000, 0x0010798a, 0x82180d80,
-	0x00000043, 0x02000000, 0x001092a5, 0x82180d80,
-	0x00000051, 0x02000000, 0x0010930b, 0x82180d80,
-	0x00000004, 0x04020003, 0x42000000, 0x00000001,
-	0x83380d80, 0x00000015, 0x04000006, 0x83380d80,
-	0x00000016, 0x02020000, 0x001076fb, 0x0401f226,
-	0x4d2c0000, 0x4d3c0000, 0x0c01f804, 0x5c027800,
-	0x5c025800, 0x1c01f000, 0x00107e42, 0x00107e46,
-	0x00107e42, 0x00107ebb, 0x00107e42, 0x00107fc7,
-	0x00108060, 0x00107e42, 0x00107e42, 0x00108029,
-	0x00107e42, 0x0010803b, 0x4933c857, 0x497a6007,
-	0x59300808, 0x58040000, 0x4a000a04, 0x00000103,
-	0x0201f000, 0x000208b4, 0x4933c857, 0x40000000,
-	0x40000000, 0x1c01f000, 0x4933c857, 0x59a80016,
-	0x82000580, 0x00000074, 0x0402005c, 0x0201f800,
-	0x0010a0b1, 0x04020016, 0x0401f85c, 0x0201f800,
-	0x00108df4, 0x0400000c, 0x0201f800, 0x00109360,
-	0x04020009, 0x41780800, 0x4d400000, 0x42028000,
-	0x00000000, 0x0201f800, 0x00109204, 0x5c028000,
-	0x0401f003, 0x0201f800, 0x00101e1b, 0x0201f800,
-	0x00104711, 0x0201f000, 0x000208b4, 0x0201f800,
-	0x00108df4, 0x04000007, 0x0201f800, 0x00109360,
-	0x04020004, 0x0401ff3d, 0x0201f000, 0x000208b4,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200,
-	0x84000558, 0x48026a00, 0x42003000, 0x00000003,
-	0x0201f800, 0x0010a766, 0x4d300000, 0x0201f800,
-	0x00020892, 0x02000800, 0x00100615, 0x49366009,
-	0x497a6008, 0x4a026406, 0x00000001, 0x4a026403,
-	0x00000001, 0x0201f800, 0x0010393e, 0x04000011,
-	0x4a026406, 0x00000004, 0x4a026203, 0x00000007,
-	0x4a026420, 0x00000001, 0x42003000, 0x00000001,
-	0x4d400000, 0x42028000, 0x00000029, 0x41782800,
-	0x0201f800, 0x0010a250, 0x5c028000, 0x0401f009,
-	0x42000800, 0x0000000b, 0x0201f800, 0x001043c7,
-	0x4a026203, 0x00000001, 0x0201f800, 0x00106470,
-	0x5c026000, 0x0401ff05, 0x0201f800, 0x00101e1b,
-	0x0201f000, 0x000208b4, 0x0401ff00, 0x42000000,
-	0x00000001, 0x0401f0de, 0x4933c857, 0x59340200,
-	0x8c000500, 0x0400000d, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x5c027800, 0x0201f800,
-	0x0010393e, 0x04000005, 0x42000800, 0x00000006,
-	0x0201f800, 0x001043c7, 0x1c01f000, 0x4933c857,
-	0x59a80816, 0x82040580, 0x00000074, 0x0400000e,
-	0x4807c857, 0x82040580, 0x00000100, 0x040200b7,
-	0x59cc0408, 0x4803c857, 0x8c000500, 0x040000b3,
-	0x59341403, 0x82080580, 0x000007fe, 0x04000006,
-	0x0401f0ae, 0x59341403, 0x82080580, 0x000007fe,
-	0x0402001a, 0x59a80026, 0x8c000506, 0x04000015,
-	0x59cc0000, 0x82000500, 0x000000ff, 0x59a80810,
-	0x82040d00, 0x000000ff, 0x80040580, 0x0400000d,
-	0x0201f800, 0x00101e1b, 0x0201f800, 0x000208b4,
-	0x42000000, 0x0010b651, 0x0201f800, 0x0010a86e,
-	0x4202d800, 0x00000001, 0x0201f000, 0x00103f37,
-	0x0401fa9c, 0x0401f04c, 0x0201f800, 0x00104480,
-	0x59341403, 0x82080580, 0x000007fc, 0x0402001f,
-	0x4a026802, 0x00fffffc, 0x0201f800, 0x00108df4,
-	0x04000012, 0x0201f800, 0x00109360, 0x0402000f,
-	0x0401f8a9, 0x41780800, 0x4d400000, 0x42028000,
-	0x00000000, 0x0201f800, 0x00109204, 0x5c028000,
-	0x42000800, 0x00000004, 0x0201f800, 0x001043c7,
-	0x0201f000, 0x000208b4, 0x42000800, 0x00000004,
-	0x0201f800, 0x001043c7, 0x0201f800, 0x00101e1b,
-	0x0201f000, 0x000208b4, 0x59a8006f, 0x8c000502,
-	0x04000011, 0x0201f800, 0x00104e0d, 0x42001000,
-	0x00000010, 0x04020009, 0x59340002, 0x82000500,
-	0x00ff0000, 0x82000580, 0x00ff0000, 0x04000006,
-	0x42001000, 0x00000008, 0x0201f800, 0x00104ada,
-	0x0402005a, 0x0201f800, 0x00108df4, 0x0400005b,
-	0x0201f800, 0x00109360, 0x04020005, 0x592c0404,
-	0x8c00051c, 0x040207c9, 0x0401f877, 0x42000800,
-	0x00000005, 0x0201f800, 0x001043c7, 0x4a026203,
-	0x00000001, 0x4a026403, 0x00000003, 0x0201f000,
-	0x00106470, 0x59cc0408, 0x8c000518, 0x04000010,
-	0x0201f800, 0x001090ab, 0x0201f800, 0x00104e0d,
-	0x04000004, 0x59cc0408, 0x8c000516, 0x040207b3,
-	0x59a80026, 0x8400054a, 0x48035026, 0x59a80010,
-	0x84000570, 0x48038832, 0x0401f7ac, 0x42001000,
-	0x000000ef, 0x480b5010, 0x497b8830, 0x84081570,
-	0x480b8832, 0x59c40802, 0x84040d4c, 0x48078802,
-	0x0201f800, 0x001090d5, 0x59a80026, 0x84000548,
-	0x48035026, 0x0201f800, 0x0010a1ec, 0x0402079b,
-	0x59a80026, 0x8400054c, 0x48035026, 0x42000800,
-	0x00000006, 0x0201f800, 0x001043c7, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x42000000, 0x000000e8,
-	0x0201f800, 0x001059b9, 0x02000800, 0x001043fc,
-	0x02020800, 0x00100615, 0x49366009, 0x59340200,
-	0x8400051a, 0x48026a00, 0x42000800, 0x00000003,
-	0x0201f800, 0x001043c7, 0x4a026406, 0x00000001,
-	0x4a026203, 0x00000001, 0x4a026403, 0x00000002,
-	0x0201f000, 0x00106470, 0x0401fe2c, 0x42000000,
-	0x00000001, 0x0401f00a, 0x599c0017, 0x8c00050a,
-	0x040007ab, 0x42000800, 0x00000004, 0x0201f800,
-	0x001043c7, 0x0201f000, 0x000208b4, 0x4933c857,
-	0x80003540, 0x04000005, 0x42000800, 0x00000007,
-	0x0201f800, 0x001043c7, 0x801831c0, 0x0402000e,
-	0x59302008, 0x801021c0, 0x04000004, 0x58100404,
-	0x8c00051e, 0x04020008, 0x59341c03, 0x42002000,
-	0x00000004, 0x42003000, 0x00000012, 0x0201f800,
-	0x001038c7, 0x0201f800, 0x00101e1b, 0x0201f000,
-	0x000208b4, 0x4c5c0000, 0x4d2c0000, 0x59325808,
-	0x0201f800, 0x00105439, 0x5c025800, 0x59cc0008,
-	0x48002805, 0x59cc0009, 0x48002806, 0x49782807,
-	0x49782808, 0x49782809, 0x4978280a, 0x59cc0013,
-	0x8c00053e, 0x04000009, 0x59cc0414, 0x900001c0,
-	0x59ccbc15, 0x805c0540, 0x48002807, 0x59cc0416,
-	0x900001c0, 0x48002808, 0x59cc0017, 0x8c00053e,
-	0x04000009, 0x59cc0418, 0x900001c0, 0x59ccbc19,
-	0x805c0540, 0x48002809, 0x59cc041a, 0x900001c0,
-	0x4800280a, 0x5c00b800, 0x1c01f000, 0x4933c857,
-	0x59a80016, 0x82000580, 0x00000014, 0x04020048,
-	0x59a8006f, 0x8c000502, 0x04000015, 0x0201f800,
-	0x00104e0d, 0x42001000, 0x00000010, 0x04020009,
-	0x59340002, 0x82000500, 0x00ff0000, 0x82000580,
-	0x00ff0000, 0x0400000a, 0x42001000, 0x00000008,
-	0x0201f800, 0x00104ada, 0x04000005, 0x59a8006f,
-	0x8400054c, 0x4803506f, 0x0401f031, 0x836c0580,
-	0x00000003, 0x0402000b, 0x59300008, 0x80000540,
-	0x04020008, 0x59341c03, 0x42002000, 0x00000006,
-	0x42003000, 0x00000013, 0x0201f800, 0x001038c7,
-	0x0201f800, 0x001044e1, 0x0401feb8, 0x0401fa1d,
-	0x0402001f, 0x59340404, 0x80000540, 0x0400001c,
-	0x42000800, 0x00000006, 0x0201f800, 0x001043c7,
-	0x0201f800, 0x00108df4, 0x04000011, 0x0201f800,
-	0x00109360, 0x0402000a, 0x41780800, 0x4d400000,
-	0x42028000, 0x00000000, 0x0201f800, 0x00109204,
-	0x5c028000, 0x0201f000, 0x000208b4, 0x4a025a04,
-	0x00000103, 0x4a025805, 0x02000000, 0x0201f800,
-	0x00101e1b, 0x0201f000, 0x000208b4, 0x0201f800,
-	0x00104a83, 0x0201f800, 0x00108df4, 0x04000007,
-	0x0201f800, 0x00109360, 0x04020004, 0x0401fd8b,
-	0x0201f000, 0x000208b4, 0x0401fd88, 0x80000580,
-	0x59a8006f, 0x8c00050c, 0x04000005, 0x8400050c,
-	0x4803506f, 0x82000540, 0x00000001, 0x0401ff60,
-	0x1c01f000, 0x4933c857, 0x59a80016, 0x82000580,
-	0x00000014, 0x0402000b, 0x42000800, 0x0000000b,
-	0x0201f800, 0x001043c7, 0x4a026203, 0x00000001,
-	0x4a026403, 0x00000001, 0x0201f000, 0x00106470,
-	0x42000000, 0x00000001, 0x0401f74d, 0x4933c857,
-	0x40003000, 0x59a80016, 0x82000580, 0x00000004,
-	0x0402000a, 0x82183580, 0x0000000b, 0x04020005,
-	0x42000800, 0x00000007, 0x0201f800, 0x001043c7,
-	0x0201f000, 0x000208b4, 0x42000000, 0x00000001,
-	0x0401f73b, 0x4803c857, 0x4d2c0000, 0x4d3c0000,
-	0x0c01f804, 0x5c027800, 0x5c025800, 0x1c01f000,
-	0x00107e42, 0x0010806f, 0x00107e42, 0x001080c4,
-	0x00107e42, 0x00108132, 0x00108060, 0x00107e42,
-	0x00107e42, 0x00108152, 0x00107e42, 0x00108162,
-	0x4933c857, 0x4d1c0000, 0x59301403, 0x82080580,
-	0x00000003, 0x04000008, 0x82081580, 0x0000001e,
-	0x04020003, 0x0201f800, 0x000208b4, 0x5c023800,
-	0x1c01f000, 0x0401ff5a, 0x0401f7fd, 0x4933c857,
-	0x0201f800, 0x00108df4, 0x0400000b, 0x0201f800,
-	0x00109360, 0x04020008, 0x4200b000, 0x00000002,
-	0x0201f800, 0x00109346, 0x0401fd2c, 0x0201f000,
-	0x000208b4, 0x0401f8f5, 0x04020030, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x417a7800, 0x0201f800,
-	0x00101de2, 0x42000000, 0x0010b663, 0x0201f800,
-	0x0010a86e, 0x59340200, 0x84000558, 0x48026a00,
-	0x4a026403, 0x00000002, 0x42003000, 0x00000003,
-	0x0201f800, 0x0010a766, 0x0201f800, 0x0010393e,
-	0x04000011, 0x4d400000, 0x41782800, 0x42003000,
-	0x00000005, 0x42028000, 0x00000029, 0x0201f800,
-	0x0010a250, 0x5c028000, 0x4a026203, 0x00000007,
-	0x4a026406, 0x00000004, 0x4a026420, 0x00000001,
-	0x1c01f000, 0x42000800, 0x00000003, 0x0201f800,
-	0x001043c7, 0x4a026203, 0x00000001, 0x0201f800,
-	0x00106470, 0x0401f7f7, 0x59cc0407, 0x82000580,
-	0x00000009, 0x0402000a, 0x59340412, 0x82000500,
-	0x000000ff, 0x0400000c, 0x80000040, 0x48026c12,
-	0x4a026206, 0x0000000a, 0x0401f7ea, 0x59cc0207,
-	0x82000500, 0x0000ff00, 0x82000580, 0x00001900,
-	0x040007c2, 0x0401fce5, 0x80000580, 0x0401f6c4,
-	0x4933c857, 0x59a80032, 0x80000540, 0x04000015,
-	0x59340403, 0x82000580, 0x000007fe, 0x04020011,
-	0x59a80010, 0x80000000, 0x48035010, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x42000800, 0x00000003,
-	0x0201f800, 0x001043c7, 0x4a026203, 0x00000001,
-	0x4a026403, 0x00000002, 0x0201f000, 0x00106470,
-	0x0201f800, 0x00108df4, 0x04000011, 0x0201f800,
-	0x00109360, 0x0402000e, 0x4c580000, 0x4200b000,
-	0x00000002, 0x0201f800, 0x00109346, 0x5c00b000,
-	0x0401fcbe, 0x42000800, 0x00000007, 0x0201f800,
-	0x001043c7, 0x0201f000, 0x000208b4, 0x0401fcb7,
-	0x59cc3407, 0x82183500, 0x000000ff, 0x82180580,
-	0x00000005, 0x0400001c, 0x82180580, 0x0000000b,
-	0x04000016, 0x59cc0207, 0x82000500, 0x0000ff00,
-	0x04020004, 0x82180580, 0x00000009, 0x04000012,
-	0x82000580, 0x00001900, 0x0402000c, 0x82180580,
-	0x00000009, 0x0400000c, 0x42000800, 0x00000004,
-	0x0201f800, 0x001043c7, 0x0201f800, 0x00101e1b,
-	0x0201f000, 0x000208b4, 0x42000000, 0x00000001,
-	0x0401f677, 0x0201f800, 0x00108df4, 0x59325808,
-	0x04000008, 0x592c0204, 0x82000580, 0x00000139,
-	0x040007f6, 0x592c0404, 0x8c00051e, 0x040207f3,
-	0x59340403, 0x82000580, 0x000007fe, 0x04020007,
-	0x59a80026, 0x84000540, 0x48035026, 0x0201f800,
-	0x00104059, 0x0401f7e9, 0x417a7800, 0x0201f800,
-	0x00101de2, 0x42003000, 0x00000005, 0x0201f800,
-	0x0010a766, 0x42000000, 0x0010b663, 0x0201f800,
-	0x0010a86e, 0x0401f7dd, 0x4933c857, 0x0401f84d,
-	0x0402000b, 0x42000800, 0x00000005, 0x0201f800,
-	0x001043c7, 0x4a026203, 0x00000001, 0x4a026403,
-	0x00000003, 0x0201f000, 0x00106470, 0x42000800,
-	0x00000004, 0x0201f800, 0x001043c7, 0x0201f800,
-	0x00109360, 0x0402000a, 0x4c580000, 0x4200b000,
-	0x00000002, 0x0201f800, 0x00109346, 0x5c00b000,
-	0x0401fc5a, 0x0201f000, 0x000208b4, 0x0401fc57,
-	0x80000580, 0x0401f636, 0x4933c857, 0x0401f82d,
-	0x0402000b, 0x42000800, 0x00000009, 0x0201f800,
-	0x001043c7, 0x4a026203, 0x00000001, 0x4a026403,
-	0x00000005, 0x0201f000, 0x00106470, 0x42000000,
-	0x00000001, 0x0401f626, 0x4933c857, 0x0401f81d,
-	0x0402000b, 0x42000800, 0x0000000b, 0x0201f800,
-	0x001043c7, 0x4a026203, 0x00000001, 0x4a026403,
-	0x00000001, 0x0201f000, 0x00106470, 0x42000000,
-	0x00000001, 0x0401f616, 0x4933c857, 0x59cc0407,
-	0x82000580, 0x00000003, 0x04020009, 0x59cc0207,
-	0x82000500, 0x0000ff00, 0x82000d80, 0x00002a00,
-	0x04000003, 0x82000d80, 0x00001e00, 0x1c01f000,
-	0x4933c857, 0x82000540, 0x00000001, 0x1c01f000,
-	0x4933c857, 0x4d400000, 0x4c580000, 0x59a80026,
-	0x82000540, 0x00000003, 0x48035026, 0x0401f85c,
-	0x04000038, 0x4d340000, 0x4d440000, 0x59a80026,
-	0x84000552, 0x48035026, 0x0201f800, 0x0010393e,
-	0x0400000c, 0x42028000, 0x0000002a, 0x42028800,
-	0x0000ffff, 0x42003000, 0x00000002, 0x0201f800,
-	0x0010a258, 0x59a80805, 0x84040d44, 0x48075005,
-	0x42028000, 0x0000002a, 0x4d3c0000, 0x42027800,
-	0x00000200, 0x0201f800, 0x00101d90, 0x5c027800,
-	0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e,
-	0x0201f800, 0x00101bf0, 0x4200b000, 0x00000010,
-	0x42028800, 0x000007f0, 0x4d2c0000, 0x83440580,
-	0x000007fe, 0x04000003, 0x0201f800, 0x00104451,
-	0x81468800, 0x8058b040, 0x040207f9, 0x5c025800,
-	0x59cc0408, 0x8c00051e, 0x04000004, 0x59a80026,
-	0x84000512, 0x48035026, 0x5c028800, 0x5c026800,
-	0x0201f800, 0x00104480, 0x4a026802, 0x00fffffe,
-	0x59a80826, 0x84040d50, 0x59cc0013, 0x8c00053e,
-	0x04000003, 0x8c000536, 0x04000004, 0x59cc0017,
-	0x8c000536, 0x04020002, 0x84040d10, 0x48075026,
-	0x59cc0800, 0x82040d00, 0x00ffffff, 0x48075010,
-	0x80040110, 0x4803501d, 0x48038881, 0x0201f800,
-	0x00104e0d, 0x04000007, 0x59cc0009, 0x48035035,
-	0x59cc000a, 0x48035036, 0x0201f800, 0x001090ab,
-	0x5c00b000, 0x5c028000, 0x1c01f000, 0x4933c857,
-	0x4c580000, 0x59a80010, 0x82000500, 0x00ffff00,
-	0x04000022, 0x59cc1000, 0x82081500, 0x00ffff00,
-	0x80080580, 0x04000004, 0x42000000, 0x0010b639,
-	0x0401f016, 0x83cc1400, 0x0000000b, 0x4200b000,
-	0x00000002, 0x83341c00, 0x00000006, 0x0401f904,
-	0x04000004, 0x42000000, 0x0010b63a, 0x0401f00b,
-	0x83cc1400, 0x0000000d, 0x4200b000, 0x00000002,
-	0x83341c00, 0x00000008, 0x0401f8f9, 0x04000007,
-	0x42000000, 0x0010b63b, 0x0201f800, 0x0010a86e,
-	0x82000540, 0x00000001, 0x5c00b000, 0x1c01f000,
-	0x4933c857, 0x59cc0206, 0x82000580, 0x00000014,
-	0x04020016, 0x59cc0407, 0x82000580, 0x00000800,
-	0x04020012, 0x59cc0207, 0x8c00051a, 0x0400000d,
-	0x82000500, 0x00000f00, 0x82000580, 0x00000100,
-	0x04020008, 0x59cc020a, 0x8c000508, 0x04020003,
-	0x8c00050a, 0x04000003, 0x80000580, 0x1c01f000,
-	0x82000540, 0x00000001, 0x1c01f000, 0x4933c857,
-	0x4943c857, 0x493fc857, 0x4c5c0000, 0x4d300000,
-	0x4d340000, 0x4d2c0000, 0x4d380000, 0x4130b800,
-	0x42026000, 0x0010cfc0, 0x59a8000e, 0x81640480,
-	0x040210c1, 0x8d3e7d12, 0x04000004, 0x405c0000,
-	0x81300580, 0x040000b7, 0x59300406, 0x82000c80,
-	0x00000012, 0x04021015, 0x59326809, 0x0c01f001,
-	0x001082f4, 0x0010825f, 0x00108278, 0x00108283,
-	0x00108258, 0x00108271, 0x001082ac, 0x001082f4,
-	0x00108256, 0x001082c0, 0x001082cf, 0x00108256,
-	0x00108256, 0x00108256, 0x00108256, 0x001082f4,
-	0x001082e5, 0x001082dd, 0x0201f800, 0x00100615,
-	0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004,
-	0x59300420, 0x8c000500, 0x04020096, 0x59300403,
-	0x82000580, 0x00000043, 0x04000092, 0x0201f800,
-	0x00108ef1, 0x02000800, 0x00101e1b, 0x0201f800,
-	0x00108f05, 0x02000800, 0x00107da6, 0x8d3e7d06,
-	0x04000086, 0x0201f800, 0x0010909d, 0x04000085,
-	0x0401f082, 0x8d3e7d18, 0x04000003, 0x8d3e7d16,
-	0x04000004, 0x59300420, 0x8c000500, 0x0402007d,
-	0x59325808, 0x0201f800, 0x00108df4, 0x04000077,
-	0x49425a06, 0x497a5c09, 0x0201f800, 0x00020381,
-	0x0201f800, 0x00108ee7, 0x0401f070, 0x813669c0,
-	0x02000800, 0x00100615, 0x8d3e7d06, 0x04000004,
-	0x59340200, 0x8c00050e, 0x0402006a, 0x59300004,
-	0x8400055c, 0x48026004, 0x59300203, 0x82000580,
-	0x00000004, 0x02000800, 0x00100ee4, 0x59325808,
-	0x0201f800, 0x00108df4, 0x0400005c, 0x4a025a04,
-	0x00000103, 0x59300402, 0x48025c06, 0x592c0408,
-	0x8c000512, 0x04000006, 0x4d2c0000, 0x592e5809,
-	0x0201f800, 0x00100843, 0x5c025800, 0x49425a06,
-	0x497a5c09, 0x0201f800, 0x00109365, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00108ee7, 0x0401f047,
-	0x8c000518, 0x04000047, 0x59300203, 0x82000580,
-	0x00000004, 0x02000800, 0x00100ee4, 0x59325808,
-	0x0201f800, 0x00108df4, 0x0400003c, 0x49425a06,
-	0x497a5c09, 0x0201f800, 0x0010a4ae, 0x0201f800,
-	0x00109365, 0x0201f800, 0x00020381, 0x0401f033,
-	0x0201f800, 0x0010600e, 0x04000032, 0x59300203,
-	0x82000580, 0x00000004, 0x04020004, 0x0201f800,
-	0x00100ee4, 0x0401f02b, 0x42027000, 0x00000047,
-	0x0201f800, 0x000208d8, 0x0401f026, 0x59300203,
-	0x82000580, 0x00000004, 0x02000800, 0x00100ee4,
-	0x59325808, 0x0201f800, 0x00108df4, 0x0400001b,
-	0x49425a06, 0x497a5c09, 0x0201f800, 0x00020381,
-	0x0401f016, 0x833c0500, 0x00001800, 0x04000015,
-	0x8d3e7d16, 0x04020013, 0x59325817, 0x0201f800,
-	0x00100843, 0x59300203, 0x82000580, 0x00000004,
-	0x02000800, 0x00100ee4, 0x59325808, 0x0201f800,
-	0x00108df4, 0x04000005, 0x49425a06, 0x497a5c09,
-	0x0201f800, 0x00020381, 0x0201f800, 0x00107698,
-	0x83326400, 0x00000024, 0x41580000, 0x81300480,
-	0x0400173e, 0x5c027000, 0x5c025800, 0x5c026800,
-	0x5c026000, 0x5c00b800, 0x1c01f000, 0x5c000000,
-	0x4c000000, 0x4803c857, 0x480bc857, 0x480fc857,
-	0x485bc857, 0x50080800, 0x500c0000, 0x80042580,
-	0x04020007, 0x80081000, 0x800c1800, 0x8058b040,
-	0x040207f9, 0x80000580, 0x1c01f000, 0x4803c857,
-	0x4807c857, 0x480bc857, 0x480fc857, 0x80040480,
-	0x04001006, 0x42000000, 0x00000001, 0x82040d40,
-	0x00000001, 0x1c01f000, 0x41780000, 0x0401f7fc,
-	0x83380480, 0x00000053, 0x02021800, 0x00100615,
-	0x83380480, 0x0000004b, 0x02001800, 0x00100615,
-	0x0c01f001, 0x0010832f, 0x0010832f, 0x0010832f,
-	0x0010832f, 0x0010832d, 0x0010832d, 0x0010832d,
-	0x0010832f, 0x0201f800, 0x00100615, 0x493bc857,
-	0x4a026203, 0x0000000d, 0x493a6403, 0x42000800,
-	0x80000000, 0x0201f000, 0x00020855, 0x83380580,
-	0x00000013, 0x04020008, 0x59300403, 0x82000580,
-	0x00000050, 0x02020800, 0x00100615, 0x0201f000,
-	0x000208b4, 0x4933c857, 0x83380580, 0x00000027,
-	0x04020030, 0x4933c857, 0x0201f800, 0x001068f6,
-	0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2,
-	0x5c027800, 0x42000000, 0x0010b663, 0x0201f800,
-	0x0010a86e, 0x4d2c0000, 0x59325808, 0x0201f800,
-	0x00108df4, 0x492fc857, 0x0400000d, 0x4a025a04,
-	0x00000103, 0x59300c02, 0x48065c06, 0x4a025a06,
-	0x00000029, 0x497a5c09, 0x592c0c08, 0x84040d50,
-	0x48065c08, 0x0201f800, 0x00020381, 0x5c025800,
-	0x42003000, 0x00000015, 0x41782800, 0x42002000,
-	0x00000003, 0x4d400000, 0x4d440000, 0x59368c03,
-	0x42028000, 0x00000029, 0x0201f800, 0x0010962a,
-	0x5c028800, 0x5c028000, 0x0201f000, 0x000208b4,
-	0x83380580, 0x00000014, 0x0402000d, 0x59300403,
-	0x82000c80, 0x00000053, 0x02021800, 0x00100615,
-	0x82000480, 0x00000040, 0x02001800, 0x00100615,
-	0x4933c857, 0x4803c857, 0x0c01f00e, 0x83380580,
-	0x00000053, 0x0400000a, 0x83380580, 0x00000048,
-	0x02020800, 0x00100615, 0x59300403, 0x82000580,
-	0x00000050, 0x02020800, 0x00100615, 0x1c01f000,
-	0x001083a5, 0x001083a3, 0x001083a3, 0x001083a3,
-	0x001083a3, 0x001083a3, 0x001083a3, 0x001083a3,
-	0x001083a3, 0x001083a3, 0x001083a3, 0x001083bc,
-	0x001083bc, 0x001083bc, 0x001083bc, 0x001083a3,
-	0x001083bc, 0x001083a3, 0x001083bc, 0x0201f800,
-	0x00100615, 0x4933c857, 0x0201f800, 0x001068f6,
-	0x0201f800, 0x00108df4, 0x02000000, 0x000208b4,
-	0x4d2c0000, 0x59325808, 0x4a025a04, 0x00000103,
-	0x59300402, 0x48025c06, 0x4a025a06, 0x00000006,
-	0x497a5c09, 0x0201f800, 0x00020381, 0x5c025800,
-	0x0201f800, 0x00108ee7, 0x0201f000, 0x000208b4,
-	0x4933c857, 0x0201f800, 0x001068f6, 0x0201f000,
-	0x000208b4, 0x0201f800, 0x00100615, 0x5930001c,
-	0x800001c0, 0x02020800, 0x0010961a, 0x59300004,
-	0x8c00053e, 0x04020029, 0x59325808, 0x592c0c08,
-	0x59cc2a08, 0x82141d00, 0x00000c00, 0x04000002,
-	0x59cc1809, 0x84040d58, 0x48065c08, 0x82143500,
-	0x00000fff, 0x04020027, 0x59340200, 0x8c00050e,
-	0x04020080, 0x0201f800, 0x00020962, 0x04020006,
-	0x4a025a06, 0x00000000, 0x59300811, 0x800409c0,
-	0x04020951, 0x4a025a04, 0x00000103, 0x48065807,
-	0x480e580a, 0x48165c09, 0x59300c02, 0x48065c06,
-	0x0201f800, 0x00020381, 0x0201f800, 0x00104801,
-	0x59cc0208, 0x8c000518, 0x02020000, 0x00108f88,
-	0x0201f000, 0x000208b4, 0x0201f800, 0x00106cb4,
-	0x040007d6, 0x4d3c0000, 0x42027800, 0x00000002,
-	0x0201f800, 0x00108997, 0x5c027800, 0x0401f7cf,
-	0x4817c857, 0x480fc857, 0x82180500, 0x000000ff,
-	0x0400000e, 0x592c0204, 0x82000500, 0x000000ff,
-	0x82000580, 0x00000048, 0x04020008, 0x592c0407,
-	0x800001c0, 0x04000005, 0x0201f800, 0x0010950b,
-	0x0201f000, 0x00109553, 0x82180d00, 0x00000c00,
-	0x04000004, 0x59340200, 0x8c00050e, 0x04020032,
-	0x4a025a06, 0x00000000, 0x41782000, 0x8c183510,
-	0x04000007, 0x59cc000c, 0x82000500, 0x000000ff,
-	0x04000002, 0x4803c857, 0x59cc200b, 0x4812580c,
-	0x41780000, 0x8c183512, 0x04000002, 0x59cc000a,
-	0x4802580b, 0x80100c00, 0x040007b8, 0x82041480,
-	0x0000001d, 0x04001006, 0x592c0404, 0x8c00051e,
-	0x0400000e, 0x42000800, 0x0000001c, 0x4c500000,
-	0x4c540000, 0x83cca400, 0x0000000c, 0x832cac00,
-	0x0000000d, 0x0201f800, 0x00108953, 0x5c00a800,
-	0x5c00a000, 0x0401f7a5, 0x59300011, 0x59301402,
-	0x480a5c06, 0x48025807, 0x480e580a, 0x48165c09,
-	0x0201f800, 0x001088fc, 0x0201f800, 0x00108938,
-	0x0401f7a6, 0x592c020a, 0x8c000502, 0x040007cd,
-	0x592c0208, 0x8c00050e, 0x040207ca, 0x59300011,
-	0x800c0d80, 0x040007c7, 0x4803c857, 0x480fc857,
-	0x8c183514, 0x02000000, 0x00108fc6, 0x80000540,
-	0x040007c0, 0x4807c856, 0x0201f000, 0x00108fc6,
-	0x592c020a, 0x8c000502, 0x04000782, 0x59300011,
-	0x800001c0, 0x0400077f, 0x592c0208, 0x8c00050e,
-	0x0402077c, 0x0201f000, 0x00108fc6, 0x59cc2006,
-	0x59cc2807, 0x0401f037, 0x0401f036, 0x1c01f000,
-	0x4933c857, 0x5930001c, 0x800001c0, 0x02020800,
-	0x0010961a, 0x59325808, 0x592c0c08, 0x41782800,
-	0x41781800, 0x84040d58, 0x48065c08, 0x41783000,
-	0x59340200, 0x8c00050e, 0x0402001a, 0x0201f800,
-	0x00020962, 0x04020007, 0x4a025a06, 0x00000000,
-	0x59300811, 0x4807c857, 0x800409c0, 0x040208b2,
-	0x4a025a04, 0x00000103, 0x48065807, 0x480e580a,
-	0x48165c09, 0x4933c857, 0x59300c02, 0x48065c06,
-	0x0201f800, 0x00109365, 0x0201f800, 0x00020381,
-	0x0201f800, 0x00104801, 0x0201f000, 0x000208b4,
-	0x592c020a, 0x8c000502, 0x040007e8, 0x59300011,
-	0x4803c857, 0x800001c0, 0x040007e4, 0x592c0208,
-	0x8c00050e, 0x040207e1, 0x0201f000, 0x00108fc6,
-	0x5930001c, 0x800001c0, 0x4c100000, 0x4c140000,
-	0x02020800, 0x0010961a, 0x5c002800, 0x5c002000,
-	0x4a026203, 0x00000002, 0x4a026403, 0x00000043,
-	0x59325808, 0x592c020a, 0x8c000502, 0x0402001c,
-	0x40100000, 0x592c080f, 0x80040c80, 0x40140000,
-	0x80040480, 0x04001018, 0x59300004, 0x8c00053e,
-	0x0402000a, 0x48126013, 0x48166011, 0x497a6205,
-	0x0201f800, 0x00100fe1, 0x0402000d, 0x59300804,
-	0x0201f000, 0x00106466, 0x4c100000, 0x4c140000,
-	0x0201f800, 0x00106cb4, 0x5c002800, 0x5c002000,
-	0x040007f1, 0x0201f000, 0x001076fb, 0x4933c857,
-	0x1c01f000, 0x4807c857, 0x40042800, 0x0401f7e7,
-	0x83380480, 0x00000058, 0x04021005, 0x83380480,
-	0x00000040, 0x04001002, 0x0c01f002, 0x1c01f000,
-	0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec,
-	0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec,
-	0x001084ec, 0x001084ec, 0x001084ee, 0x001084ec,
-	0x001084ec, 0x001084ec, 0x001084ec, 0x001084fb,
-	0x001084ec, 0x001084ec, 0x001084ec, 0x001084ec,
-	0x00108529, 0x001084ec, 0x001084ec, 0x001084ec,
-	0x0201f800, 0x00100615, 0x4933c857, 0x0201f800,
-	0x00106b13, 0x4a026203, 0x00000002, 0x59a80039,
-	0x48026205, 0x59300011, 0x59300815, 0x80040c80,
-	0x48066015, 0x0201f000, 0x001068c1, 0x4933c857,
-	0x0201f800, 0x001068c1, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x00101de2, 0x5c027800, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800,
-	0x00108df4, 0x04000010, 0x4d2c0000, 0x59325808,
-	0x4a025a04, 0x00000103, 0x59300402, 0x48025c06,
-	0x4a025a06, 0x00000029, 0x497a5c09, 0x592c0c08,
-	0x84040d50, 0x48065c08, 0x0201f800, 0x00020381,
-	0x5c025800, 0x42003000, 0x00000014, 0x41782800,
-	0x4d400000, 0x4d440000, 0x59368c03, 0x42002000,
-	0x00000002, 0x42028000, 0x00000029, 0x0201f800,
-	0x0010962a, 0x5c028800, 0x5c028000, 0x0201f000,
-	0x000208b4, 0x4933c857, 0x59300808, 0x49780c09,
-	0x4978080a, 0x58041408, 0x84081558, 0x48080c08,
-	0x1c01f000, 0x4807c857, 0x8c040d3e, 0x04020024,
-	0x497a5a06, 0x5930001f, 0x80000540, 0x04000018,
-	0x497a5a06, 0x4c040000, 0x4c080000, 0x4c0c0000,
-	0x4c100000, 0x4c140000, 0x40002800, 0x58141003,
-	0x40040000, 0x80081480, 0x48082803, 0x40140000,
-	0x0201f800, 0x00100d9a, 0x5c002800, 0x5c002000,
-	0x5c001800, 0x5c001000, 0x5c000800, 0x592c0206,
-	0x80000540, 0x04020009, 0x0401f005, 0x592c0408,
-	0x8c00051c, 0x04000002, 0x592c0803, 0x4807c857,
-	0x4a025a06, 0x00000015, 0x1c01f000, 0x5930001f,
-	0x80000540, 0x04000009, 0x4a025a06, 0x00000011,
-	0x5930001f, 0x4c040000, 0x0201f800, 0x00100d9a,
-	0x5c000800, 0x0401f7f5, 0x4807c856, 0x4a025a06,
-	0x00000007, 0x1c01f000, 0x83380480, 0x00000058,
-	0x04021007, 0x83380480, 0x00000040, 0x04001004,
-	0x4d2c0000, 0x0c01f803, 0x5c025800, 0x1c01f000,
-	0x00108588, 0x00108588, 0x00108588, 0x00108588,
-	0x00108588, 0x0010858a, 0x00108588, 0x00108588,
-	0x0010860d, 0x00108588, 0x00108588, 0x00108588,
-	0x00108588, 0x00108588, 0x00108588, 0x00108588,
-	0x00108588, 0x00108588, 0x00108588, 0x001086c5,
-	0x001086ee, 0x001086cd, 0x00108588, 0x001086fa,
-	0x0201f800, 0x00100615, 0x5930001c, 0x800001c0,
-	0x02020800, 0x0010961a, 0x59300007, 0x8c00050e,
-	0x0400007c, 0x8c000500, 0x0400006e, 0x8c00051c,
-	0x04000009, 0x84000500, 0x48026007, 0x59325808,
-	0x592c3c08, 0x841c3d58, 0x481e5c08, 0x0201f000,
-	0x00020914, 0x59325808, 0x592c3c08, 0x841c3d58,
-	0x59300007, 0x8c00051c, 0x040207f3, 0x481e5c08,
-	0x42000000, 0x00000005, 0x40000000, 0x80000040,
-	0x040207fe, 0x59300007, 0x8c00051c, 0x040207ea,
-	0x59cc0a08, 0x592c0204, 0x82000500, 0x000000ff,
-	0x82000580, 0x00000048, 0x0402000c, 0x497a580b,
-	0x82040500, 0x000000ff, 0x04000008, 0x592c0407,
-	0x800001c0, 0x04000005, 0x0201f800, 0x0010950b,
-	0x0201f000, 0x00100ea1, 0x48065c09, 0x41782000,
-	0x82040500, 0x00000c00, 0x04000002, 0x59cc2009,
-	0x82043500, 0x00000fff, 0x04020027, 0x481e5c08,
-	0x4a025a06, 0x00000000, 0x801831c0, 0x02000000,
-	0x00100ea1, 0x41782000, 0x8c183510, 0x04000002,
-	0x59cc200b, 0x4812580c, 0x41780000, 0x8c183512,
-	0x04000002, 0x59cc000a, 0x4802580b, 0x80100c00,
-	0x02001800, 0x00100615, 0x02000000, 0x00100ea1,
-	0x82041480, 0x0000001d, 0x0402100c, 0x4c500000,
-	0x4c540000, 0x83cca400, 0x0000000c, 0x832cac00,
-	0x0000000d, 0x0401fb6e, 0x5c00a800, 0x5c00a000,
-	0x0201f000, 0x00100ea1, 0x0401fb12, 0x0201f000,
-	0x00100ea1, 0x412c7800, 0x0201f800, 0x0010082a,
-	0x02000800, 0x00100615, 0x492c7809, 0x841c3d52,
-	0x481c7c08, 0x4a025a04, 0x00000103, 0x4812580a,
-	0x48065c09, 0x583c0404, 0x583c1005, 0x583c2208,
-	0x48025c04, 0x480a5805, 0x48125a08, 0x0401f7c8,
-	0x8c000524, 0x04000794, 0x59325808, 0x4c000000,
-	0x592c0408, 0x8c00051c, 0x5c000000, 0x04020003,
-	0x4a026011, 0xffffffff, 0x84000524, 0x0401f78a,
-	0x1c01f000, 0x59a80039, 0x48026205, 0x59325808,
-	0x4a026203, 0x00000002, 0x592c2408, 0x59300807,
-	0x4933c857, 0x4807c857, 0x592c0204, 0x82000500,
-	0x000000ff, 0x82000580, 0x00000048, 0x04020004,
-	0x8c102500, 0x02020000, 0x00109553, 0x4a025a06,
-	0x00000000, 0x8c040d1e, 0x04000027, 0x41780800,
-	0x497a5c09, 0x592c1c09, 0x59300011, 0x59341200,
-	0x497a6205, 0x8c08150e, 0x0402006e, 0x4807c857,
-	0x4806580a, 0x80000d40, 0x04020f03, 0x59300402,
-	0x48025c06, 0x48065807, 0x4a025a04, 0x00000103,
-	0x4c040000, 0x4c0c0000, 0x4c100000, 0x0201f800,
-	0x00109365, 0x5c002000, 0x5c001800, 0x5c000800,
-	0x8c102512, 0x0402001a, 0x4c0c0000, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00104801, 0x5c001800,
-	0x8c0c1d18, 0x02000000, 0x000208b4, 0x0201f000,
-	0x00108f88, 0x4813c857, 0x8c102518, 0x0400004b,
-	0x41780800, 0x592c1c09, 0x820c0580, 0x00001000,
-	0x040007d6, 0x8c102512, 0x040007d4, 0x592c7809,
-	0x583c080a, 0x583c1c09, 0x0401f7d0, 0x4807c857,
-	0x592c7809, 0x59300402, 0x592c1404, 0x8c08151e,
-	0x0402000d, 0x592c1206, 0x48007c06, 0x48047807,
-	0x48087a06, 0x84102512, 0x48107c08, 0x4c0c0000,
-	0x0201f800, 0x00100843, 0x403e5800, 0x0401fad1,
-	0x0401f7d9, 0x48025c06, 0x48065807, 0x583c080c,
-	0x583c000b, 0x80040c00, 0x82041480, 0x0000001d,
-	0x04001006, 0x583c1001, 0x480a5801, 0x49787801,
-	0x42000800, 0x0000001c, 0x82040c00, 0x00000014,
-	0x4c0c0000, 0x4c500000, 0x4c540000, 0x823ca400,
-	0x00000008, 0x832cac00, 0x00000008, 0x4c100000,
-	0x4c3c0000, 0x0401fad2, 0x5c007800, 0x5c002000,
-	0x5c00a800, 0x5c00a000, 0x84102512, 0x48125c08,
-	0x403e5800, 0x0201f800, 0x00100843, 0x42034000,
-	0x0010b2a0, 0x59a1d81e, 0x80edd9c0, 0x02000800,
-	0x00100615, 0x48efc857, 0x58ec0009, 0x4803c857,
-	0x0801f800, 0x0401f7ac, 0x4933c857, 0x1c01f000,
-	0x59301414, 0x480bc857, 0x8c08151c, 0x0402000e,
-	0x80000540, 0x4803c857, 0x0400078d, 0x80042c80,
-	0x0402178b, 0x8c081514, 0x04020005, 0x592c080f,
-	0x4807c857, 0x80040480, 0x48026016, 0x8408155c,
-	0x480a6414, 0x59301007, 0x8408151e, 0x480a6007,
-	0x4c100000, 0x4c3c0000, 0x4d400000, 0x592e8206,
-	0x4a025a06, 0x00000001, 0x0201f800, 0x00109365,
-	0x49425a06, 0x5c028000, 0x5c007800, 0x5c002000,
-	0x497a5c09, 0x8c102512, 0x04000006, 0x4d2c0000,
-	0x403e5800, 0x0201f800, 0x00100843, 0x5c025800,
-	0x82102500, 0xffffedff, 0x48125c08, 0x0201f000,
-	0x00108fc6, 0x59325808, 0x592c0408, 0x8c000518,
-	0x04000004, 0x412df800, 0x0201f000, 0x00100eba,
-	0x1c01f000, 0x4933c857, 0x59325808, 0x497a5c09,
-	0x4a025a06, 0x00000000, 0x4a025a04, 0x00000103,
-	0x59300811, 0x4807c857, 0x800409c0, 0x0402000a,
-	0x48065807, 0x59300c02, 0x48065c06, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00104801, 0x0201f000,
-	0x000208b4, 0x59340200, 0x8c00050e, 0x04020005,
-	0x59300811, 0x0401fe4c, 0x48065807, 0x0401f7f2,
-	0x592c0208, 0x8c00050e, 0x040207fa, 0x4933c857,
-	0x0201f000, 0x00108fc6, 0x4933c857, 0x59325808,
-	0x812e59c0, 0x02000800, 0x00100615, 0x592c020a,
-	0x8c000502, 0x02000800, 0x00100615, 0x4a026206,
-	0x00000002, 0x1c01f000, 0x5930001c, 0x800001c0,
-	0x02020800, 0x0010961a, 0x59300007, 0x4933c857,
-	0x4803c857, 0x8c00050e, 0x04000037, 0x8c000500,
-	0x04000029, 0x8c00051c, 0x0400000a, 0x84000500,
-	0x48026007, 0x59325808, 0x592c3c08, 0x481fc857,
-	0x841c3d58, 0x481e5c08, 0x0201f000, 0x00020914,
-	0x59325808, 0x592c3c08, 0x841c3d58, 0x59300007,
-	0x8c00051c, 0x040207f2, 0x481e5c08, 0x42000000,
-	0x00000005, 0x40000000, 0x80000040, 0x040207fe,
-	0x59300007, 0x8c00051c, 0x040207e9, 0x592c0204,
-	0x82000500, 0x000000ff, 0x82000580, 0x00000048,
-	0x04020003, 0x497a580b, 0x0401f002, 0x497a5c09,
-	0x481e5c08, 0x4a025a06, 0x00000000, 0x0201f000,
-	0x00100ea1, 0x8c000524, 0x040007d9, 0x59325808,
-	0x4c000000, 0x592c0408, 0x8c00051c, 0x5c000000,
-	0x04020003, 0x4a026011, 0xffffffff, 0x84000524,
-	0x0401f7cf, 0x1c01f000, 0x4933c857, 0x41780800,
-	0x83380480, 0x00000058, 0x0402100b, 0x83380480,
-	0x00000040, 0x04001008, 0x4d2c0000, 0x59325808,
-	0x812e59c0, 0x0c020806, 0x5c025800, 0x0201f000,
-	0x000208b4, 0x493bc857, 0x1c01f000, 0x00108763,
-	0x00108763, 0x00108763, 0x00108763, 0x00108763,
-	0x00108765, 0x00108763, 0x00108763, 0x00108763,
-	0x00108763, 0x00108763, 0x00108763, 0x00108763,
-	0x00108763, 0x00108763, 0x00108763, 0x00108763,
-	0x00108763, 0x00108763, 0x00108763, 0x0010876a,
-	0x00108763, 0x00108763, 0x00108763, 0x0201f800,
-	0x00100615, 0x59cc0a08, 0x497a5807, 0x4807c857,
-	0x82040d00, 0x00000fff, 0x59300402, 0x48025c06,
-	0x4a025a04, 0x00000103, 0x48065c09, 0x4a025a06,
-	0x00000000, 0x800409c0, 0x02000000, 0x00020381,
-	0x59cc0009, 0x4802580a, 0x82042500, 0x00000100,
-	0x04000002, 0x59cc200b, 0x4812580c, 0x82040500,
-	0x00000200, 0x04000002, 0x59cc000a, 0x4802580b,
-	0x80100c00, 0x02001800, 0x00100615, 0x02000000,
-	0x00020381, 0x82041480, 0x0000001d, 0x04001006,
-	0x592c0404, 0x8c00051e, 0x0400000e, 0x42000800,
-	0x0000001c, 0x4c500000, 0x4c540000, 0x83cca400,
-	0x0000000c, 0x832cac00, 0x0000000d, 0x0401f9c0,
-	0x5c00a800, 0x5c00a000, 0x0201f000, 0x00020381,
-	0x0401f964, 0x0401f19f, 0x83380480, 0x00000093,
-	0x02021800, 0x00100615, 0x83380480, 0x00000085,
-	0x02001800, 0x00100615, 0x0c01f001, 0x001087b2,
-	0x001087b0, 0x001087b0, 0x001087b9, 0x001087b0,
-	0x001087b0, 0x001087b0, 0x001087b0, 0x001087b0,
-	0x001087b0, 0x001087b0, 0x001087b0, 0x001087b0,
-	0x0201f800, 0x00100615, 0x4a026203, 0x00000001,
-	0x493a6403, 0x42000800, 0x80000040, 0x0201f000,
-	0x00020855, 0x4933c857, 0x59cc1404, 0x0201f800,
-	0x001091d9, 0x0400001b, 0x591c0203, 0x82000580,
-	0x00000000, 0x04000017, 0x591c0009, 0x81340580,
-	0x04020014, 0x4d300000, 0x4d1c0000, 0x411e6000,
-	0x0401f9c3, 0x5c023800, 0x5c026000, 0x0400000b,
-	0x59cc0005, 0x8c000500, 0x04020003, 0x0401f98d,
-	0x0401f003, 0x4a023a03, 0x00000002, 0x4a026403,
-	0x00000086, 0x0401f005, 0x0401f9a7, 0x040007f5,
-	0x4a026403, 0x00000087, 0x4a026203, 0x00000001,
-	0x42000800, 0x80000040, 0x0201f800, 0x00020855,
-	0x59340200, 0x8c00050e, 0x0400000d, 0x59cc1404,
-	0x0201f800, 0x001091d9, 0x04000009, 0x591c0414,
-	0x8c00051a, 0x04000006, 0x4d300000, 0x411e6000,
-	0x0201f800, 0x00108fdb, 0x5c026000, 0x1c01f000,
-	0x83380580, 0x00000013, 0x0402000b, 0x59300403,
-	0x4803c857, 0x82000d80, 0x00000086, 0x04000012,
-	0x82000d80, 0x00000087, 0x02020800, 0x00100615,
-	0x0401f00d, 0x83380580, 0x00000027, 0x04000005,
-	0x83380580, 0x00000014, 0x02020800, 0x00100615,
-	0x493bc857, 0x0201f800, 0x001068f6, 0x0201f000,
-	0x00107698, 0x4933c857, 0x0201f000, 0x00107698,
-	0x83380580, 0x00000013, 0x04020005, 0x59300403,
-	0x82000480, 0x00000085, 0x0c01f04d, 0x83380580,
-	0x00000027, 0x04020041, 0x4933c857, 0x0201f800,
-	0x001068f6, 0x4d3c0000, 0x417a7800, 0x0201f800,
-	0x00101de2, 0x5c027800, 0x42003000, 0x00000015,
-	0x41782800, 0x42002000, 0x00000003, 0x42028000,
-	0x00000029, 0x4d400000, 0x4d440000, 0x59368c03,
-	0x0201f800, 0x0010962a, 0x5c028800, 0x5c028000,
-	0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e,
-	0x0201f800, 0x00108df4, 0x0400000c, 0x4d2c0000,
-	0x59325808, 0x4a025a04, 0x00000103, 0x59300402,
-	0x48025c06, 0x497a5c09, 0x49425a06, 0x0201f800,
-	0x00020381, 0x5c025800, 0x0201f800, 0x00108ee7,
-	0x0201f000, 0x000208b4, 0x83380580, 0x00000089,
-	0x04000005, 0x83380580, 0x0000008a, 0x02020000,
-	0x001076fb, 0x0201f800, 0x00106cb4, 0x02020000,
-	0x001076fb, 0x59300a03, 0x82040580, 0x0000000a,
-	0x0400002a, 0x82040580, 0x0000000c, 0x04000027,
-	0x0201f800, 0x00100615, 0x83380580, 0x00000014,
-	0x040207ea, 0x4933c857, 0x0201f800, 0x001068f6,
-	0x42028000, 0x00000006, 0x0401f7d2, 0x0010886e,
-	0x0010886c, 0x0010886c, 0x0010886c, 0x0010886c,
-	0x0010886c, 0x00108874, 0x0010886c, 0x0010886c,
-	0x0010886c, 0x0010886c, 0x0010886c, 0x0010886c,
-	0x0201f800, 0x00100615, 0x4933c857, 0x59a80037,
-	0x48026206, 0x4a026203, 0x0000000a, 0x1c01f000,
-	0x4933c857, 0x59a80037, 0x48026206, 0x4a026203,
-	0x0000000c, 0x1c01f000, 0x83380580, 0x00000089,
-	0x04000008, 0x83380580, 0x0000008a, 0x04000032,
-	0x4933c857, 0x493bc857, 0x0201f000, 0x001076fb,
-	0x4933c857, 0x59325808, 0x59300a1d, 0x82040580,
-	0x00000003, 0x04020004, 0x0201f800, 0x00104801,
-	0x0401f00c, 0x5930021d, 0x82000580, 0x00000001,
-	0x04020008, 0x59300c16, 0x82040580, 0x00000039,
-	0x0400002c, 0x82040580, 0x00000035, 0x04000029,
-	0x4c5c0000, 0x4130b800, 0x0201f800, 0x00020892,
-	0x04000010, 0x4a026203, 0x00000001, 0x4a026403,
-	0x0000001e, 0x59cc0c07, 0x48066419, 0x59cc0a07,
-	0x48066219, 0x49366009, 0x4a026406, 0x00000001,
-	0x42000800, 0x80000040, 0x0201f800, 0x00020855,
-	0x405e6000, 0x0201f800, 0x000208b4, 0x5c00b800,
-	0x1c01f000, 0x4933c857, 0x5930021d, 0x82000580,
-	0x00000001, 0x04020040, 0x59300c16, 0x82040580,
-	0x00000035, 0x04000007, 0x82040580, 0x0000001e,
-	0x04000004, 0x82040580, 0x00000039, 0x04020036,
-	0x4933c857, 0x4c500000, 0x4d1c0000, 0x4130a000,
-	0x40067000, 0x0201f800, 0x00109183, 0x04020029,
-	0x0201f800, 0x00020892, 0x04000026, 0x491fc857,
-	0x4933c857, 0x83380580, 0x00000035, 0x04000004,
-	0x83380580, 0x00000039, 0x04020002, 0x4932381c,
-	0x493a6403, 0x4a026203, 0x00000001, 0x4a026406,
-	0x00000001, 0x58500809, 0x4807c857, 0x48066009,
-	0x58500c15, 0x4807c857, 0x48066415, 0x58500a15,
-	0x4807c857, 0x48066215, 0x58500a16, 0x4807c857,
-	0x48066216, 0x58500c19, 0x4807c857, 0x48066419,
-	0x58500a19, 0x4807c857, 0x48066219, 0x491e601e,
-	0x42000800, 0x80000040, 0x0201f800, 0x00020855,
-	0x40526000, 0x5c023800, 0x5c00a000, 0x0201f000,
-	0x000208b4, 0x5930021d, 0x82000580, 0x00000003,
-	0x02000800, 0x00104801, 0x0201f000, 0x000208b4,
-	0x4803c856, 0x4c500000, 0x4c540000, 0x412c7800,
-	0x4c3c0000, 0x42002800, 0x00000001, 0x82040480,
-	0x00000101, 0x04001003, 0x42000800, 0x00000100,
-	0x40043000, 0x42000800, 0x0000001c, 0x83cca400,
-	0x0000000c, 0x832cac00, 0x0000000d, 0x0401f844,
-	0x82183480, 0x0000001c, 0x592e5801, 0x812e59c0,
-	0x02020800, 0x00100843, 0x0201f800, 0x0010082a,
-	0x04000017, 0x80142800, 0x4a025a04, 0x00000110,
-	0x497a5c04, 0x492c7801, 0x82180c80, 0x0000003d,
-	0x04021006, 0x40180800, 0x832cac00, 0x00000005,
-	0x0401f82f, 0x0401f00a, 0x82183480, 0x0000003c,
-	0x42000800, 0x0000003c, 0x412c7800, 0x832cac00,
-	0x00000005, 0x0401f826, 0x0401f7e8, 0x5c007800,
-	0x841429c0, 0x82142d40, 0x00000003, 0x48147a04,
-	0x403e5800, 0x5c00a800, 0x5c00a000, 0x1c01f000,
-	0x492fc857, 0x812e59c0, 0x0400000f, 0x4d2c0000,
-	0x4c3c0000, 0x592c7801, 0x803c79c0, 0x04000006,
-	0x497a5801, 0x0201f800, 0x00020381, 0x403e5800,
-	0x0401f7f9, 0x5c007800, 0x0201f800, 0x00020381,
-	0x5c025800, 0x1c01f000, 0x4803c856, 0x4c580000,
-	0x82040c00, 0x00000003, 0x8004b104, 0x0201f800,
-	0x0010a93e, 0x5c00b000, 0x1c01f000, 0x4803c856,
-	0x4c580000, 0x82040c00, 0x00000003, 0x8004b104,
-	0x0201f800, 0x0010a93e, 0x5c00b000, 0x1c01f000,
-	0x591c0c06, 0x82040580, 0x00000003, 0x04000004,
-	0x82040580, 0x00000002, 0x0402001a, 0x4d300000,
-	0x4d2c0000, 0x411e6000, 0x59325808, 0x0201f800,
-	0x00108df4, 0x0400000f, 0x4d400000, 0x42028000,
-	0x00000013, 0x592c0a08, 0x84040d54, 0x0201f800,
-	0x00104bee, 0x5c028000, 0x0201f800, 0x00109365,
-	0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7,
-	0x0201f800, 0x00107698, 0x5c025800, 0x5c026000,
-	0x1c01f000, 0x59cc0005, 0x8c000500, 0x0402000b,
-	0x591c0406, 0x82000580, 0x00000002, 0x04020007,
-	0x591c0c03, 0x82040580, 0x00000085, 0x04000003,
-	0x82040580, 0x0000008b, 0x1c01f000, 0x4933c857,
-	0x4d3c0000, 0x42027800, 0x00000002, 0x59300406,
-	0x82000c80, 0x00000012, 0x02021800, 0x00100615,
-	0x0c01f80a, 0x5c027800, 0x1c01f000, 0x4933c857,
-	0x59300406, 0x82000c80, 0x00000012, 0x02021800,
-	0x00100615, 0x0c01f001, 0x001089b5, 0x001089b2,
-	0x001089b2, 0x001089dd, 0x001089b0, 0x001089b2,
-	0x001089ce, 0x001089b2, 0x001089b0, 0x0010632c,
-	0x001089b2, 0x001089b2, 0x001089b2, 0x001089b0,
-	0x001089b0, 0x001089b0, 0x00108aad, 0x001089b2,
-	0x0201f800, 0x00100615, 0x4803c856, 0x80000580,
-	0x1c01f000, 0x4803c856, 0x8d3e7d02, 0x04020016,
-	0x0201f800, 0x00108df4, 0x0400000f, 0x59325808,
-	0x41780800, 0x4d400000, 0x42028000, 0x00000005,
-	0x0201f800, 0x00104bee, 0x5c028000, 0x0201f800,
-	0x00109365, 0x0201f800, 0x00108f83, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00107698, 0x82000540,
-	0x00000001, 0x1c01f000, 0x4933c857, 0x0201f800,
-	0x00104728, 0x0402000c, 0x4d400000, 0x42028000,
-	0x00000010, 0x0201f800, 0x00109fc0, 0x4a026406,
-	0x00000006, 0x4a026203, 0x00000007, 0x5c028000,
-	0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c,
-	0x4df00000, 0x0401f8b8, 0x82000c80, 0x0000000e,
-	0x02021800, 0x00100615, 0x0c01f001, 0x001089f7,
-	0x00108a64, 0x00108a0e, 0x00108a77, 0x00108a5f,
-	0x001089f5, 0x001089f7, 0x001089f7, 0x001089fb,
-	0x001089f7, 0x001089f7, 0x001089f7, 0x001089f7,
-	0x00108a0e, 0x0201f800, 0x00100615, 0x5c03e000,
-	0x02000800, 0x00106982, 0x0401f7b8, 0x5c03e000,
-	0x02000800, 0x00106982, 0x59300406, 0x82000580,
-	0x00000003, 0x040207b4, 0x59300203, 0x82000580,
-	0x0000000d, 0x040007b0, 0x8d3e7d02, 0x040207ae,
-	0x4d340000, 0x59326809, 0x0201f800, 0x00104801,
-	0x5c026800, 0x0401f7a8, 0x59300004, 0x8400055c,
-	0x48026004, 0x0201f800, 0x00106982, 0x59300406,
-	0x82000580, 0x00000006, 0x04000043, 0x8d3e7d02,
-	0x04020041, 0x497a621d, 0x59300203, 0x82000580,
-	0x0000000d, 0x04000003, 0x4a02621d, 0x00000003,
-	0x0401fbd4, 0x04000024, 0x4d2c0000, 0x4d400000,
-	0x59325808, 0x0201f800, 0x00108f83, 0x592c0408,
-	0x8c000512, 0x04000009, 0x4d2c0000, 0x84000512,
-	0x48025c08, 0x592c0809, 0x40065800, 0x0201f800,
-	0x00100843, 0x5c025800, 0x4d400000, 0x42028000,
-	0x00000005, 0x592c0a08, 0x8c040d0e, 0x04000004,
-	0x42028000, 0x00000002, 0x0401f001, 0x0201f800,
-	0x00104bee, 0x5c028000, 0x0201f800, 0x00109365,
-	0x0201f800, 0x00020381, 0x497a6008, 0x5c028000,
-	0x5c025800, 0x8d3e7d00, 0x04000009, 0x4d340000,
-	0x59326809, 0x0201f800, 0x00104801, 0x5c026800,
-	0x0201f800, 0x00107698, 0x0401f00b, 0x4a026403,
-	0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
-	0x00000002, 0x42000800, 0x8000404b, 0x0201f800,
-	0x00020855, 0x5c03e000, 0x02020800, 0x0010698c,
-	0x82000540, 0x00000001, 0x1c01f000, 0x0201f800,
-	0x00106982, 0x0201f800, 0x00100ee4, 0x0401f7ab,
-	0x598c000d, 0x81300580, 0x04020004, 0x0201f800,
-	0x00106be2, 0x0402001b, 0x0201f800, 0x00106619,
-	0x04020006, 0x59300c03, 0x82040580, 0x00000040,
-	0x0400078b, 0x0401f79d, 0x0201f800, 0x001068a3,
-	0x04000010, 0x0201f800, 0x00100615, 0x0401f813,
-	0x04020004, 0x0201f800, 0x00106bb2, 0x04020009,
-	0x0201f800, 0x001064f6, 0x040207f4, 0x59300c03,
-	0x82040580, 0x00000040, 0x04000779, 0x0401f78b,
-	0x59300203, 0x82000c80, 0x0000000e, 0x02021800,
-	0x00100615, 0x0c01f75e, 0x417a3000, 0x42032000,
-	0x0000bf32, 0x59900004, 0x81300580, 0x04000009,
-	0x83932400, 0x00000010, 0x811a3000, 0x83180480,
-	0x00000005, 0x040017f8, 0x82000540, 0x00000001,
-	0x1c01f000, 0x59300004, 0x8c00053e, 0x04000010,
-	0x8c00050c, 0x0402000e, 0x8c000516, 0x04020006,
-	0x82000d00, 0x0000001f, 0x82040580, 0x00000005,
-	0x04020004, 0x42000000, 0x00000003, 0x0401f005,
-	0x42000000, 0x00000001, 0x0401f002, 0x59300203,
-	0x1c01f000, 0x4933c857, 0x0201f800, 0x0010698c,
-	0x4df00000, 0x59300203, 0x82000c80, 0x0000000e,
-	0x02021800, 0x00100615, 0x0c01f001, 0x00108ac7,
-	0x00108ae4, 0x00108acb, 0x00108ac5, 0x00108ac5,
-	0x00108ac5, 0x00108ac5, 0x00108ac5, 0x00108ac5,
-	0x00108ac5, 0x00108ac5, 0x00108ac5, 0x00108ac5,
-	0x00108ac5, 0x0201f800, 0x00100615, 0x5c03e000,
-	0x02000800, 0x00106982, 0x0401f6e8, 0x5c03e000,
-	0x02000800, 0x00106982, 0x4d2c0000, 0x59325808,
-	0x59300403, 0x82000580, 0x00000052, 0x02000800,
-	0x00101281, 0x0401fb1f, 0x02000800, 0x00100615,
-	0x4a025a06, 0x00000005, 0x0201f800, 0x00020381,
-	0x0201f800, 0x00104a83, 0x0201f800, 0x00107698,
-	0x5c025800, 0x82000540, 0x00000001, 0x1c01f000,
-	0x598c000d, 0x81300580, 0x0402001a, 0x59300004,
-	0x8c000520, 0x04000004, 0x84000520, 0x48026004,
-	0x0401f01a, 0x42001000, 0x0010b5f4, 0x50081000,
-	0x58080002, 0x82000580, 0x00000100, 0x0400000a,
-	0x5808000c, 0x81300580, 0x02020800, 0x00100615,
-	0x0201f800, 0x00106619, 0x02020800, 0x00100615,
-	0x0401f7cf, 0x0201f800, 0x00106be2, 0x0402000c,
-	0x59300004, 0x8c000520, 0x04000004, 0x84000520,
-	0x48026004, 0x0401f7c6, 0x0201f800, 0x00106619,
-	0x040007c3, 0x0201f800, 0x00100615, 0x59300203,
-	0x82000c80, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f7a7, 0x59300406, 0x4933c857, 0x4803c857,
-	0x82000c80, 0x00000012, 0x02021800, 0x00100615,
-	0x0c01f001, 0x00108b30, 0x00108bfe, 0x00108d36,
-	0x00108b3c, 0x00107698, 0x00108b30, 0x00109faf,
-	0x000208b4, 0x00108bfe, 0x00106306, 0x00108d97,
-	0x00108b2b, 0x00108b2b, 0x00108b2b, 0x00108b2b,
-	0x00108b2b, 0x001094b7, 0x001094b7, 0x0201f800,
-	0x00100615, 0x0401fbd8, 0x02000000, 0x00107da6,
-	0x1c01f000, 0x0201f800, 0x0010698c, 0x0201f800,
-	0x001068f6, 0x0201f800, 0x00106982, 0x0201f000,
-	0x000208b4, 0x4a026206, 0x00000001, 0x1c01f000,
-	0x42000000, 0x0010b671, 0x0201f800, 0x0010a86e,
-	0x4d2c0000, 0x4d400000, 0x417a5800, 0x0401fab1,
-	0x04000007, 0x59325808, 0x592c0208, 0x8400054c,
-	0x48025a08, 0x42028000, 0x00000006, 0x0201f800,
-	0x0010698c, 0x0401ff4c, 0x4803c857, 0x82000c80,
-	0x0000000e, 0x02021800, 0x00100615, 0x0c01f806,
-	0x0201f800, 0x00106982, 0x5c028000, 0x5c025800,
-	0x1c01f000, 0x00108bfd, 0x00108b69, 0x00108b79,
-	0x00108ba0, 0x00108bce, 0x00108b67, 0x00108b30,
-	0x00108b30, 0x00108b30, 0x00108b67, 0x00108b67,
-	0x00108b67, 0x00108b67, 0x00108b79, 0x0201f800,
-	0x00100615, 0x598c000d, 0x4803c857, 0x81300580,
-	0x04020004, 0x0201f800, 0x00106be2, 0x0402003f,
-	0x0201f800, 0x00106619, 0x04000043, 0x4803c856,
-	0x0201f800, 0x001068a3, 0x04000038, 0x0201f800,
-	0x00100615, 0x497a621d, 0x812e59c0, 0x02000800,
-	0x00100615, 0x592c0204, 0x4803c857, 0x82000500,
-	0x000000ff, 0x82000580, 0x00000014, 0x04000003,
-	0x4a02621d, 0x00000003, 0x592c0a08, 0x0201f800,
-	0x00104bee, 0x0201f800, 0x00109365, 0x0201f800,
-	0x00020381, 0x497a6008, 0x4a026403, 0x00000085,
-	0x4a026203, 0x00000009, 0x4a026406, 0x00000002,
-	0x59300804, 0x82040d00, 0x00000100, 0x82040d40,
-	0x8000404b, 0x48066004, 0x0201f800, 0x00106982,
-	0x42000800, 0x8000404b, 0x0201f000, 0x00020855,
-	0x0401feea, 0x04020004, 0x0201f800, 0x00106bb2,
-	0x0402000a, 0x0201f800, 0x001064f6, 0x040207cc,
-	0x59300c03, 0x4807c857, 0x82040580, 0x00000040,
-	0x04000009, 0x0401f7cc, 0x59300203, 0x4803c857,
-	0x82000c80, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f7a5, 0x0201f800, 0x00106982, 0x812e59c0,
-	0x04000013, 0x592c0a08, 0x0201f800, 0x00104bee,
-	0x0201f800, 0x00109365, 0x0201f800, 0x00020381,
-	0x59300203, 0x82000580, 0x0000000d, 0x04000008,
-	0x0201f800, 0x00106982, 0x4d340000, 0x59326809,
-	0x0201f800, 0x00104801, 0x5c026800, 0x0201f800,
-	0x00107698, 0x0401f030, 0x812e59c0, 0x02000800,
-	0x00100615, 0x0201f800, 0x001091d3, 0x04020004,
-	0x0201f800, 0x00100ee4, 0x0401f7a3, 0x0201f800,
-	0x00106982, 0x592c0208, 0x8400050c, 0x48025a08,
-	0x592c0406, 0x800000c2, 0x800008c4, 0x80040c00,
-	0x48066206, 0x42000000, 0x10000000, 0x41300800,
-	0x0201f800, 0x00100bde, 0x0400000d, 0x592c0208,
-	0x8c00051c, 0x04020006, 0x8400055c, 0x48025a08,
-	0x4a026206, 0x00000002, 0x0401f00f, 0x4d300000,
-	0x0201f800, 0x00101335, 0x5c026000, 0x59300203,
-	0x82000580, 0x00000004, 0x04020007, 0x4d380000,
-	0x42027000, 0x00000048, 0x0201f800, 0x000208d8,
-	0x5c027000, 0x1c01f000, 0x42000000, 0x0010b66d,
-	0x0201f800, 0x0010a86e, 0x59300203, 0x82000c80,
-	0x0000000e, 0x02021800, 0x00100615, 0x4803c857,
-	0x0c01f001, 0x00108c17, 0x00108b39, 0x00108c19,
-	0x00108c17, 0x00108c19, 0x00108c19, 0x00108b31,
-	0x00108c17, 0x00108b2d, 0x00108c17, 0x00108c17,
-	0x00108c17, 0x00108c17, 0x00108c17, 0x0201f800,
-	0x00100615, 0x4d340000, 0x4d2c0000, 0x59326809,
-	0x59340400, 0x82000500, 0x000000ff, 0x82000c80,
-	0x0000000c, 0x02021800, 0x00100615, 0x59303403,
-	0x82180d80, 0x00000004, 0x04020004, 0x42000000,
-	0x00000001, 0x0401f006, 0x82180d80, 0x00000000,
-	0x04020003, 0x42000000, 0x00000001, 0x4803c857,
-	0x0c01f804, 0x5c025800, 0x5c026800, 0x1c01f000,
-	0x00108c40, 0x00108cdf, 0x00108c42, 0x00108c77,
-	0x00108c42, 0x00108cfc, 0x00108c42, 0x00108c4c,
-	0x00108c40, 0x00108cfc, 0x00108c40, 0x00108c5b,
-	0x0201f800, 0x00100615, 0x59300403, 0x82000d80,
-	0x00000016, 0x0400002e, 0x82000d80, 0x00000004,
-	0x0400002b, 0x82000d80, 0x00000002, 0x04000028,
-	0x0401fab9, 0x04000079, 0x59300403, 0x82000d80,
-	0x00000022, 0x040000ae, 0x82000d80, 0x00000039,
-	0x040000b3, 0x82000d80, 0x00000035, 0x040000b0,
-	0x82000d80, 0x0000001e, 0x0400001b, 0x0401f999,
-	0x04000007, 0x0201f800, 0x00109360, 0x04020004,
-	0x0201f800, 0x00104863, 0x0401f011, 0x59300403,
-	0x82000d80, 0x00000001, 0x04020004, 0x0201f800,
-	0x00104836, 0x0400000a, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x00101de2, 0x5c027800, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x0201f800,
-	0x00107da6, 0x0201f000, 0x00107698, 0x0401f97d,
-	0x04000004, 0x0201f800, 0x00109360, 0x040000a9,
-	0x59300c03, 0x82040580, 0x00000016, 0x04000056,
-	0x82040580, 0x00000002, 0x04020034, 0x59a80026,
-	0x8c000502, 0x04020013, 0x0201f800, 0x00104e0d,
-	0x04020010, 0x0201f800, 0x00104e23, 0x04020006,
-	0x42000000, 0x00000001, 0x0201f800, 0x00104de5,
-	0x0401f094, 0x4a035033, 0x00000001, 0x4202d800,
-	0x00000001, 0x0201f800, 0x00104d76, 0x0401f08d,
-	0x59340403, 0x82000580, 0x000007fc, 0x04000008,
-	0x59a80026, 0x8c00050a, 0x04020084, 0x59340212,
-	0x82000500, 0x0000ff00, 0x04000082, 0x59340412,
-	0x82000500, 0x000000ff, 0x04000010, 0x80000040,
-	0x48026c12, 0x497a6008, 0x4a026406, 0x00000007,
-	0x4a026206, 0x00000398, 0x497a6205, 0x0201f800,
-	0x00020892, 0x04000005, 0x49366009, 0x4a026406,
-	0x00000001, 0x0401f020, 0x59300403, 0x82000d80,
-	0x00000002, 0x0402000d, 0x59340403, 0x82000580,
-	0x000007fe, 0x04020009, 0x59a80026, 0x84000540,
-	0x48035026, 0x0201f800, 0x00104067, 0x0201f800,
-	0x00107da6, 0x0401f00c, 0x0201f800, 0x00107da6,
-	0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2,
-	0x5c027800, 0x42000000, 0x0010b663, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x00101e1b, 0x0201f000,
-	0x00107698, 0x42000800, 0x00000003, 0x0201f800,
-	0x001043c7, 0x4a026203, 0x00000001, 0x4a026403,
-	0x00000002, 0x0201f000, 0x00106470, 0x0401f915,
-	0x04020793, 0x0201f800, 0x00101e1b, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e,
-	0x42003000, 0x00000018, 0x41782800, 0x42002000,
-	0x00000000, 0x4d400000, 0x4d440000, 0x59368c03,
-	0x42028000, 0x00000029, 0x0201f800, 0x0010962a,
-	0x5c028800, 0x5c028000, 0x0201f000, 0x00107698,
-	0x0201f800, 0x00104863, 0x0401f7c8, 0x42000000,
-	0x0010b66c, 0x0201f800, 0x0010a86e, 0x0201f800,
-	0x001078fd, 0x040207c1, 0x1c01f000, 0x4d380000,
-	0x59327403, 0x0201f800, 0x00109183, 0x5c027000,
-	0x02020000, 0x000208b4, 0x836c0580, 0x00000003,
-	0x04000004, 0x4a026206, 0x00000002, 0x1c01f000,
-	0x59300403, 0x48026416, 0x4a02621d, 0x00000001,
-	0x4a026403, 0x00000085, 0x4a026203, 0x00000009,
-	0x4a026406, 0x00000002, 0x42000800, 0x8000004b,
-	0x0201f000, 0x00020855, 0x0201f800, 0x00101e1b,
-	0x0201f800, 0x00107da6, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x00101de2, 0x5c027800, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x497a6008,
-	0x4a026406, 0x00000007, 0x4a026206, 0x00000398,
-	0x497a6205, 0x1c01f000, 0x42000000, 0x0010b66f,
-	0x0201f800, 0x0010a86e, 0x4d340000, 0x59326809,
-	0x59300203, 0x82000c80, 0x0000000e, 0x02021800,
-	0x00100615, 0x4803c857, 0x0c01f803, 0x5c026800,
-	0x1c01f000, 0x00108d53, 0x00108b39, 0x00108d53,
-	0x00108d53, 0x00108d53, 0x00108d53, 0x00108d53,
-	0x00108d53, 0x00108d53, 0x00108b39, 0x00108d55,
-	0x00108b39, 0x00108d5d, 0x00108d53, 0x0201f800,
-	0x00100615, 0x4a026403, 0x0000008b, 0x4a026203,
-	0x0000000b, 0x42000800, 0x8000404b, 0x0201f000,
-	0x00020855, 0x59300a1d, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x00101de2, 0x5c027800, 0x42003000,
-	0x00000011, 0x0201f800, 0x0010a766, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x41306800,
-	0x0201f800, 0x00020892, 0x04000008, 0x49366009,
-	0x4d300000, 0x40366000, 0x0201f800, 0x00107698,
-	0x5c026000, 0x0401f002, 0x40366000, 0x497a6008,
-	0x4a026406, 0x00000001, 0x4a026403, 0x00000001,
-	0x0201f800, 0x0010393e, 0x04000011, 0x4a026406,
-	0x00000004, 0x4a026203, 0x00000007, 0x4a026420,
-	0x00000001, 0x42003000, 0x00000004, 0x4d400000,
-	0x42028000, 0x00000029, 0x41782800, 0x0201f800,
-	0x0010a250, 0x5c028000, 0x1c01f000, 0x42000800,
-	0x0000000b, 0x0201f800, 0x001043c7, 0x4a026203,
-	0x00000001, 0x0201f000, 0x00106470, 0x42000000,
-	0x0010b675, 0x0201f800, 0x0010a86e, 0x59300203,
-	0x82000c80, 0x0000000e, 0x02021800, 0x00100615,
-	0x4803c857, 0x0c01f001, 0x00108dc8, 0x00108db0,
-	0x00108db4, 0x00108dc9, 0x00108db2, 0x00108db0,
-	0x00108db0, 0x00108db0, 0x00108db0, 0x00108db0,
-	0x00108db0, 0x00108db0, 0x00108db0, 0x00108db0,
-	0x0201f800, 0x00100615, 0x0201f800, 0x00100ee4,
-	0x4d2c0000, 0x59325808, 0x4a025a06, 0x00000006,
-	0x0201f800, 0x00020381, 0x5c025800, 0x497a6008,
-	0x4a02621d, 0x0000000a, 0x4a026403, 0x00000085,
-	0x4a026203, 0x00000009, 0x4a026406, 0x00000002,
-	0x42000800, 0x8000404b, 0x0201f000, 0x00020855,
-	0x1c01f000, 0x0201f800, 0x0010698c, 0x4df00000,
-	0x0401fcbe, 0x04020004, 0x0201f800, 0x00106bb2,
-	0x0402000c, 0x0201f800, 0x001064f6, 0x04020005,
-	0x5c03e000, 0x0201f800, 0x00106982, 0x0401f7dd,
-	0x0201f800, 0x001068a3, 0x02020800, 0x00100615,
-	0x5c03e000, 0x0201f800, 0x00106982, 0x59300203,
-	0x82000d80, 0x00000003, 0x02000800, 0x00100615,
-	0x82000c80, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f7ba, 0x4803c856, 0x59a8000e, 0x59a80867,
-	0x80040400, 0x80080480, 0x04021004, 0x82000540,
-	0x00000001, 0x1c01f000, 0x80000580, 0x1c01f000,
-	0x4803c856, 0x4c080000, 0x59301008, 0x82081500,
-	0xfff00000, 0x5c001000, 0x1c01f000, 0x4803c856,
-	0x4d300000, 0x0201f800, 0x00020892, 0x0400000a,
-	0x0401f82f, 0x4d380000, 0x42027000, 0x0000004b,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x82000540,
-	0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856,
-	0x4d300000, 0x0201f800, 0x001076c9, 0x0400001b,
-	0x0401f81f, 0x4d300000, 0x0201f800, 0x0010698c,
-	0x4d3c0000, 0x417a7800, 0x0201f800, 0x001067f6,
-	0x0201f800, 0x00106543, 0x5c027800, 0x0201f800,
-	0x0010a0da, 0x0201f800, 0x00106982, 0x5c026000,
-	0x8d3e7d3e, 0x0402000b, 0x4d380000, 0x42027000,
-	0x0000004c, 0x0201f800, 0x000208d8, 0x5c027000,
-	0x82000540, 0x00000001, 0x5c026000, 0x1c01f000,
-	0x0201f800, 0x000208b4, 0x0401f7fa, 0x592c0407,
-	0x494a6017, 0x494e6018, 0x49366009, 0x492e6008,
-	0x4a026406, 0x00000003, 0x800000c2, 0x800008c4,
-	0x80040400, 0x48026206, 0x1c01f000, 0x493bc857,
-	0x4d300000, 0x0201f800, 0x00020892, 0x0400000d,
-	0x0401ffef, 0x4d400000, 0x42028000, 0x00000005,
-	0x0401f80d, 0x5c028000, 0x8d3e7d3e, 0x04020007,
-	0x0201f800, 0x000208d8, 0x82000540, 0x00000001,
-	0x5c026000, 0x1c01f000, 0x0201f800, 0x000208b4,
-	0x0401f7fa, 0x4803c856, 0x0201f800, 0x0010698c,
-	0x4d3c0000, 0x4d440000, 0x59368c03, 0x42027800,
-	0x00000001, 0x0201f800, 0x001066ff, 0x0201f800,
-	0x00106675, 0x0201f800, 0x00106543, 0x0201f800,
-	0x0010a0da, 0x5c028800, 0x5c027800, 0x0201f000,
-	0x00106982, 0x4803c856, 0x4d300000, 0x0201f800,
-	0x00020892, 0x0400000f, 0x481a601c, 0x48ee6021,
-	0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
-	0x4d380000, 0x42027000, 0x0000001f, 0x0201f800,
-	0x000208d8, 0x5c027000, 0x82000540, 0x00000001,
-	0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
-	0x0201f800, 0x00020892, 0x0400000e, 0x48ee6021,
-	0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
-	0x4d380000, 0x42027000, 0x00000055, 0x0201f800,
-	0x000208d8, 0x5c027000, 0x82000540, 0x00000001,
-	0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
-	0x0201f800, 0x00020892, 0x0400000f, 0x481a601c,
-	0x48ee6021, 0x49366009, 0x4a026406, 0x00000001,
-	0x492e6008, 0x4d380000, 0x42027000, 0x0000003d,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x82000540,
-	0x00000001, 0x5c026000, 0x1c01f000, 0x4803c856,
-	0x4d300000, 0x0201f800, 0x001076c9, 0x04000014,
-	0x49366009, 0x492fc857, 0x4933c857, 0x592c0404,
-	0x8c00051e, 0x04000003, 0x48efc857, 0x48ee6021,
-	0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
-	0x42027000, 0x00000000, 0x0201f800, 0x000208d8,
-	0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
-	0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
-	0x00020892, 0x0400000f, 0x48ee6021, 0x481a601c,
-	0x49366009, 0x4a026406, 0x00000001, 0x492e6008,
-	0x4d380000, 0x42027000, 0x00000044, 0x0201f800,
-	0x000208d8, 0x5c027000, 0x82000540, 0x00000001,
-	0x5c026000, 0x1c01f000, 0x4803c856, 0x4d300000,
-	0x0201f800, 0x00020892, 0x0400000f, 0x481a601c,
-	0x48ee6021, 0x49366009, 0x4a026406, 0x00000001,
-	0x492e6008, 0x4d380000, 0x42027000, 0x00000049,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x82000540,
-	0x00000001, 0x5c026000, 0x1c01f000, 0x59300009,
-	0x80001540, 0x02000800, 0x00100615, 0x5808040b,
-	0x4803c856, 0x80000040, 0x04001002, 0x4800140b,
-	0x1c01f000, 0x4803c856, 0x59300403, 0x82000d80,
-	0x00000002, 0x0400000f, 0x82000d80, 0x00000003,
-	0x0400000c, 0x82000d80, 0x00000004, 0x04000009,
-	0x599c0819, 0x8c040d0e, 0x04000004, 0x82000d80,
-	0x00000000, 0x04000003, 0x82000540, 0x00000001,
-	0x1c01f000, 0x4803c856, 0x4c000000, 0x4d2c0000,
-	0x59300406, 0x82000580, 0x00000004, 0x0400001d,
-	0x59300008, 0x80025d40, 0x800001c0, 0x04000019,
-	0x0201f800, 0x00109360, 0x04000014, 0x59300406,
-	0x82004580, 0x00000010, 0x04000010, 0x82004580,
-	0x00000011, 0x0400000d, 0x82004580, 0x00000003,
-	0x0400000c, 0x82004580, 0x00000002, 0x04000009,
-	0x82004580, 0x0000000a, 0x04000006, 0x592c0404,
-	0x8c00051e, 0x04000003, 0x80000580, 0x0401f003,
-	0x82000540, 0x00000001, 0x5c025800, 0x5c000000,
-	0x1c01f000, 0x4803c856, 0x4d300000, 0x0201f800,
-	0x001076c9, 0x04000013, 0x49366009, 0x48ee6021,
-	0x4a026406, 0x00000001, 0x492e6008, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x4d380000, 0x42027000, 0x00000028, 0x0201f800,
-	0x000208d8, 0x5c027000, 0x82000540, 0x00000001,
-	0x5c026000, 0x1c01f000, 0x4803c856, 0x83380580,
-	0x00000015, 0x0402000d, 0x59a80016, 0x82000580,
-	0x00000074, 0x04020009, 0x0201f800, 0x00104480,
-	0x4a026203, 0x00000001, 0x4a026403, 0x00000029,
-	0x0201f000, 0x00106470, 0x0201f800, 0x00107da6,
-	0x0201f000, 0x000208b4, 0x4803c856, 0x83380580,
-	0x00000016, 0x04020007, 0x42000800, 0x00000004,
-	0x0201f800, 0x001043c7, 0x0201f000, 0x001078bf,
-	0x83380580, 0x00000015, 0x04020013, 0x59a80016,
-	0x82000580, 0x00000014, 0x0402000f, 0x0201f800,
-	0x001044e1, 0x0201f800, 0x00108210, 0x0402000a,
-	0x59340404, 0x80000540, 0x04000007, 0x42000800,
-	0x00000006, 0x0201f800, 0x001043c7, 0x0201f000,
-	0x001078bf, 0x0201f800, 0x00107da6, 0x0201f000,
-	0x000208b4, 0x4803c856, 0x592c0206, 0x82000580,
-	0x00000005, 0x04000002, 0x1c01f000, 0x4803c856,
-	0x592c0208, 0x8400054a, 0x48025a08, 0x1c01f000,
-	0x497a6205, 0x497a6008, 0x4a026203, 0x00000001,
-	0x4a026403, 0x00000050, 0x42000800, 0x80000043,
-	0x0201f000, 0x00020855, 0x4933c857, 0x4d340000,
-	0x59326809, 0x59340200, 0x8c00050e, 0x04000006,
-	0x59300406, 0x82000c80, 0x00000012, 0x04021004,
-	0x0c01f806, 0x5c026800, 0x1c01f000, 0x0201f800,
-	0x00108b30, 0x0401f7fc, 0x00108b30, 0x00108fb4,
-	0x00108fb8, 0x00108fbb, 0x0010a2b9, 0x0010a2d6,
-	0x0010a2da, 0x00108b30, 0x00108b30, 0x00108b30,
-	0x00108b30, 0x00108b30, 0x00108b30, 0x00108b30,
-	0x00108b30, 0x00108b30, 0x00108b30, 0x00108b30,
-	0x4803c856, 0x40000000, 0x40000000, 0x1c01f000,
-	0x40000000, 0x40000000, 0x1c01f000, 0x5930001c,
-	0x4803c857, 0x59300414, 0x4933c857, 0x4803c857,
-	0x8c000502, 0x04000005, 0x4803c857, 0x84000540,
-	0x48026414, 0x1c01f000, 0x42000000, 0xd0000000,
-	0x41300800, 0x0201f800, 0x00100bde, 0x0401f810,
-	0x0402000e, 0x59300c14, 0x59300403, 0x82000580,
-	0x00000040, 0x04000003, 0x84040d40, 0x0401f005,
-	0x59a80037, 0x82000400, 0x0000000a, 0x48026205,
-	0x84040d42, 0x48066414, 0x1c01f000, 0x4933c857,
-	0x4d340000, 0x59326809, 0x59340200, 0x8c00050e,
-	0x02000800, 0x00100615, 0x5930001c, 0x80000540,
-	0x04020034, 0x59300403, 0x4803c857, 0x82000580,
-	0x00000040, 0x04000004, 0x59a80021, 0x80000540,
-	0x0402002a, 0x4d1c0000, 0x41323800, 0x0201f800,
-	0x00020892, 0x04000023, 0x4932381c, 0x591c0414,
-	0x84000542, 0x48023c14, 0x49366009, 0x591c0406,
-	0x82000580, 0x00000003, 0x04000006, 0x591c0202,
-	0x48026419, 0x591c0402, 0x48026219, 0x0401f005,
-	0x591c0202, 0x48026219, 0x591c0402, 0x48026419,
-	0x491e601e, 0x4a026406, 0x00000001, 0x4a026403,
-	0x00000035, 0x4a026203, 0x00000001, 0x42000800,
-	0x80000040, 0x0201f800, 0x00020855, 0x411e6000,
-	0x5c023800, 0x80000580, 0x5c026800, 0x1c01f000,
-	0x411e6000, 0x5c023800, 0x59a80039, 0x48026205,
-	0x82000540, 0x00000001, 0x0401f7f8, 0x4933c857,
-	0x4d2c0000, 0x4932381c, 0x4a026202, 0x0000ffff,
-	0x591e5808, 0x591c0007, 0x8c00051e, 0x04000005,
-	0x8400051e, 0x48023807, 0x497a5c09, 0x0401f018,
-	0x592c0408, 0x8c000518, 0x04000015, 0x84000518,
-	0x48025c08, 0x4d400000, 0x592e8206, 0x4a025a06,
-	0x00000001, 0x0401fb34, 0x49425a06, 0x5c028000,
-	0x497a5c09, 0x592c0408, 0x8c000512, 0x04000008,
-	0x4d2c0000, 0x84000512, 0x48025c08, 0x592e5809,
-	0x0201f800, 0x00100843, 0x5c025800, 0x59a80039,
-	0x48026205, 0x591c0214, 0x48026216, 0x82000d80,
-	0x00000001, 0x04000008, 0x4a023a03, 0x00000002,
-	0x82000580, 0x00000005, 0x04000008, 0x497a6015,
-	0x0401f01e, 0x591c0007, 0x84000540, 0x48023807,
-	0x4a023a03, 0x00000004, 0x591c0414, 0x4803c857,
-	0x8400051c, 0x84000554, 0x48023c14, 0x592c000f,
-	0x40001000, 0x591c0816, 0x80040480, 0x040217f0,
-	0x591c0016, 0x82000500, 0xfffffffc, 0x48026015,
-	0x48023816, 0x591c0a14, 0x4807c857, 0x82040d80,
-	0x00000005, 0x04020005, 0x480bc857, 0x4803c857,
-	0x4a023812, 0xffffffff, 0x591c0402, 0x48026419,
-	0x591c0202, 0x48026219, 0x591e6809, 0x49366009,
-	0x4a026406, 0x00000001, 0x4a026403, 0x00000039,
-	0x4a026203, 0x00000001, 0x42000800, 0x80000040,
-	0x0201f800, 0x00020855, 0x5c025800, 0x1c01f000,
-	0x4933c857, 0x59300414, 0x8c000514, 0x04000015,
-	0x8c00051c, 0x04020012, 0x59300016, 0x80100480,
-	0x04001006, 0x04000005, 0x59300414, 0x84000514,
-	0x8400055c, 0x0401f009, 0x48126016, 0x48126012,
-	0x40100000, 0x592c180f, 0x800c0480, 0x48026011,
-	0x59300414, 0x84000514, 0x48026414, 0x1c01f000,
-	0x4933c857, 0x8c00051c, 0x04020006, 0x59300012,
-	0x48026016, 0x59300414, 0x8400055c, 0x48026414,
-	0x1c01f000, 0x59300c03, 0x4933c857, 0x4807c857,
-	0x82040480, 0x00000034, 0x04001006, 0x82040480,
-	0x0000003c, 0x04021003, 0x80000580, 0x1c01f000,
-	0x82000540, 0x00000001, 0x0401f7fd, 0x41780800,
-	0x59a81035, 0x42000000, 0x00000032, 0x0201f800,
-	0x001063ee, 0x800811c0, 0x04020003, 0x42001000,
-	0x00000014, 0x480b5037, 0x59a81036, 0x480b502d,
-	0x41780800, 0x42000000, 0x00000064, 0x0201f800,
-	0x001063ee, 0x800811c0, 0x04020003, 0x42001000,
-	0x00000014, 0x480b5038, 0x82081400, 0x0000000a,
-	0x480b5039, 0x42000800, 0x00000001, 0x0201f800,
-	0x001069af, 0x42000000, 0x30000000, 0x40080800,
-	0x0201f800, 0x00100bb2, 0x42000800, 0x00000003,
-	0x59a81010, 0x0201f800, 0x001069af, 0x0201f000,
-	0x00104755, 0x4a035037, 0x00000028, 0x4a035038,
-	0x00000014, 0x4a03502d, 0x000007d0, 0x42001000,
-	0x0000001e, 0x480b5039, 0x42000800, 0x00000001,
-	0x0201f800, 0x001069af, 0x42000000, 0x30000000,
-	0x40080800, 0x0201f800, 0x00100bb2, 0x42000800,
-	0x00000003, 0x59a81010, 0x0201f000, 0x001069af,
-	0x4933c857, 0x4d2c0000, 0x59300403, 0x82000580,
-	0x0000003e, 0x04020005, 0x59325817, 0x812e59c0,
-	0x02020800, 0x0010083a, 0x5c025800, 0x1c01f000,
-	0x4937c857, 0x4d300000, 0x0201f800, 0x00020892,
-	0x04000011, 0x49366009, 0x4a026406, 0x00000001,
-	0x492e6008, 0x42000800, 0x00000009, 0x0201f800,
-	0x001043c7, 0x4d380000, 0x42027000, 0x00000033,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x82000540,
-	0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857,
-	0x4d2c0000, 0x4c580000, 0x4d3c0000, 0x59325808,
-	0x83380580, 0x00000015, 0x04020025, 0x59a8b016,
-	0x82580c80, 0x00000019, 0x04001003, 0x4200b000,
-	0x00000018, 0x8058b104, 0x0401fa0a, 0x80000580,
-	0x0401fa1a, 0x832cac00, 0x00000009, 0x83cca400,
-	0x00000006, 0x0201f800, 0x0010a93e, 0x4c600000,
-	0x4200c000, 0x00000001, 0x592c100a, 0x8c081518,
-	0x04020006, 0x59a80010, 0x592c100d, 0x80080580,
-	0x04020007, 0x4178c000, 0x59301009, 0x58081403,
-	0x417a7800, 0x0201f800, 0x00101e48, 0x5c00c000,
-	0x0201f800, 0x001078bf, 0x0401f008, 0x4200b000,
-	0x00000002, 0x0401fa09, 0x0201f800, 0x00107da6,
-	0x0201f800, 0x000208b4, 0x5c027800, 0x5c00b000,
-	0x5c025800, 0x1c01f000, 0x4933c856, 0x49366009,
-	0x4a026406, 0x00000001, 0x492e6008, 0x4d380000,
-	0x42027000, 0x0000004d, 0x0201f800, 0x000208d8,
-	0x5c027000, 0x82000540, 0x00000001, 0x1c01f000,
-	0x4803c856, 0x4d2c0000, 0x83380580, 0x00000015,
-	0x04020027, 0x59a80816, 0x59325808, 0x5930040b,
-	0x800000c4, 0x80040580, 0x04020021, 0x4c500000,
-	0x4c540000, 0x4c580000, 0x83cca400, 0x00000006,
-	0x4050a800, 0x5930b40b, 0x0201f800, 0x0010a94f,
-	0x83cca400, 0x00000006, 0x592cb205, 0x832cac00,
-	0x00000006, 0x0201f800, 0x0010a93e, 0x592e5801,
-	0x812e59c0, 0x040207f9, 0x5931d821, 0x58ef400b,
-	0x58ee580d, 0x4a025a04, 0x00000103, 0x58ec0009,
-	0x0801f800, 0x59300402, 0x5c00b000, 0x5c00a800,
-	0x5c00a000, 0x5c025800, 0x1c01f000, 0x0201f800,
-	0x00107da6, 0x5c025800, 0x1c01f000, 0x4933c857,
-	0x83380580, 0x00000035, 0x04000005, 0x59301419,
-	0x0401f851, 0x04000027, 0x0401f006, 0x4d300000,
-	0x5932601e, 0x0401f856, 0x5c026000, 0x04000020,
-	0x591c0c06, 0x82040580, 0x00000003, 0x04000004,
-	0x82040580, 0x00000006, 0x0402001c, 0x591c0c02,
-	0x59300419, 0x80040580, 0x04000009, 0x59300219,
-	0x80040580, 0x04020015, 0x591c0a02, 0x59300419,
-	0x80040580, 0x04020011, 0x0401f009, 0x59300a19,
-	0x82040580, 0x0000ffff, 0x04000005, 0x591c0202,
-	0x59300a19, 0x80040580, 0x04020008, 0x591c0009,
-	0x59300809, 0x80040580, 0x1c01f000, 0x417a3800,
-	0x82000540, 0x00000001, 0x1c01f000, 0x4803c856,
-	0x59b800e4, 0x8c000538, 0x02020800, 0x00100615,
-	0x42000800, 0x0000012c, 0x4a0370e4, 0x20000000,
-	0x59b800e4, 0x80040840, 0x02000800, 0x00100615,
-	0x8c00053c, 0x040207f9, 0x4a0370e4, 0x30000000,
-	0x40000000, 0x40000000, 0x40000000, 0x59b800e4,
-	0x8c00053c, 0x040207f1, 0x1c01f000, 0x4803c856,
-	0x4a0370e4, 0x20000000, 0x40000000, 0x59b800e4,
-	0x8c000538, 0x040207fb, 0x1c01f000, 0x59300807,
-	0x8c040d1e, 0x592c0c08, 0x04020002, 0x8c040d18,
-	0x1c01f000, 0x0401fc10, 0x04000008, 0x42000800,
-	0x00000024, 0x0201f800, 0x001063cf, 0x82063c00,
-	0x0010cfc0, 0x491fc857, 0x1c01f000, 0x83300480,
-	0x0010cfc0, 0x0400100a, 0x59a8000b, 0x81300480,
-	0x04021007, 0x59301402, 0x0401ffef, 0x04000007,
-	0x411c0000, 0x81300580, 0x04000003, 0x81780500,
-	0x0401f002, 0x81300540, 0x1c01f000, 0x4947c857,
-	0x4d300000, 0x0201f800, 0x00020267, 0x0402000a,
-	0x42026000, 0x0010bbe8, 0x49366009, 0x492e6008,
-	0x0201f800, 0x00101de2, 0x80000580, 0x5c026000,
-	0x1c01f000, 0x82000540, 0x00000001, 0x0401f7fc,
-	0x4933c857, 0x0201f800, 0x00108df4, 0x02000800,
-	0x00100615, 0x4d2c0000, 0x4d340000, 0x4d440000,
-	0x4c580000, 0x59325808, 0x59326809, 0x49425a06,
-	0x0201f800, 0x00105439, 0x592e8c06, 0x592c4207,
-	0x82200500, 0x0000000f, 0x0c01f806, 0x5c00b000,
-	0x5c028800, 0x5c026800, 0x5c025800, 0x1c01f000,
-	0x0010922f, 0x00109251, 0x00109258, 0x0010925c,
-	0x00109265, 0x0010922c, 0x0010922c, 0x0010922c,
-	0x00109269, 0x00109275, 0x00109275, 0x0010922c,
-	0x0010922c, 0x0010922c, 0x0010922c, 0x0010922c,
-	0x4803c857, 0x0201f800, 0x00100615, 0x814281c0,
-	0x04020012, 0x41785800, 0x592c0404, 0x8c00051c,
-	0x04020002, 0x59345c05, 0x442c2800, 0x59340008,
-	0x48002802, 0x59340009, 0x48002801, 0x59340006,
-	0x48002804, 0x59340007, 0x48002803, 0x4200b000,
-	0x0000000b, 0x0401f037, 0x592c0207, 0x8c00051e,
-	0x4200b000, 0x00000002, 0x04020032, 0x8204b540,
-	0x00000000, 0x0400002f, 0x44042800, 0x59326809,
-	0x59340400, 0x48002801, 0x4200b000, 0x00000002,
-	0x0401f028, 0x814281c0, 0x04020030, 0x59345c05,
-	0x442c2800, 0x4200b000, 0x00000001, 0x0401f021,
-	0x8340b540, 0x00000000, 0x0400001e, 0x0401f027,
-	0x814281c0, 0x04020025, 0x59340200, 0x44002800,
-	0x59340001, 0x48002801, 0x4200b000, 0x00000002,
-	0x0401f014, 0x8340b540, 0x00000000, 0x0402001b,
-	0x0401f010, 0x8340b540, 0x00000000, 0x0400000d,
-	0x0201f800, 0x00104871, 0x04000014, 0x8c20450e,
-	0x04000002, 0x497a6009, 0x4178b000, 0x497a5a06,
-	0x0401f004, 0x8340b540, 0x00000000, 0x0402000b,
-	0x592c0404, 0x8400051c, 0x48025c04, 0x592c0207,
-	0x8400051e, 0x48025a07, 0x0401f8aa, 0x497a6008,
-	0x0201f000, 0x00020381, 0x592c0207, 0x8c00051e,
-	0x4200b000, 0x00000002, 0x040207f2, 0x8204b540,
-	0x00000000, 0x040007ef, 0x44042800, 0x4200b000,
-	0x00000001, 0x0401f7eb, 0x4937c857, 0x4d300000,
-	0x0201f800, 0x00020892, 0x04000011, 0x49366009,
-	0x4a026406, 0x00000001, 0x492e6008, 0x42000800,
-	0x0000000b, 0x0201f800, 0x001043c7, 0x4d380000,
-	0x42027000, 0x00000043, 0x0201f800, 0x000208d8,
-	0x5c027000, 0x82000540, 0x00000001, 0x5c026000,
-	0x1c01f000, 0x4937c857, 0x4d2c0000, 0x59325808,
-	0x83380580, 0x00000015, 0x04020025, 0x59a80016,
-	0x82000580, 0x00000004, 0x04020021, 0x59a80010,
-	0x592c1009, 0x80080580, 0x04020010, 0x4d440000,
-	0x592e8c06, 0x592c0207, 0x4803c856, 0x82000500,
-	0x00000080, 0x84000548, 0x4d3c0000, 0x42027800,
-	0x00001000, 0x0201f800, 0x0010480a, 0x5c027800,
-	0x5c028800, 0x0401f004, 0x4803c856, 0x0201f800,
-	0x00104871, 0x0201f800, 0x00108df4, 0x04000017,
-	0x4d400000, 0x42028000, 0x00000000, 0x41780800,
-	0x0401ff38, 0x5c028000, 0x0401f00e, 0x0201f800,
-	0x00104871, 0x040207f4, 0x0201f800, 0x00108df4,
-	0x0400000a, 0x4c580000, 0x4200b000, 0x00000002,
-	0x0401f86e, 0x5c00b000, 0x0201f800, 0x00107da6,
-	0x0201f800, 0x000208b4, 0x5c025800, 0x1c01f000,
-	0x4937c857, 0x4d300000, 0x0201f800, 0x00020892,
-	0x04000012, 0x49366009, 0x4a026406, 0x00000001,
-	0x4d3c0000, 0x4d380000, 0x417a7800, 0x0201f800,
-	0x001043bd, 0x492e6008, 0x42027000, 0x00000004,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x5c027800,
-	0x82000540, 0x00000001, 0x5c026000, 0x1c01f000,
-	0x4937c857, 0x4d300000, 0x0201f800, 0x001076c9,
-	0x0400000d, 0x49366009, 0x4a026406, 0x00000001,
-	0x492e6008, 0x4d380000, 0x42027000, 0x00000051,
-	0x0201f800, 0x000208d8, 0x5c027000, 0x82000540,
-	0x00000001, 0x5c026000, 0x1c01f000, 0x4933c857,
-	0x4c580000, 0x59325808, 0x83383580, 0x00000015,
-	0x04020011, 0x592c0008, 0x82000500, 0x00ffffff,
-	0x0402000a, 0x0201f800, 0x00105439, 0x59cc0000,
-	0x82000500, 0x00ffffff, 0x44002800, 0x4200b000,
-	0x00000001, 0x0401f80b, 0x0201f800, 0x001078bf,
-	0x0401f006, 0x4200b000, 0x00000002, 0x0401f823,
-	0x0201f800, 0x00107da6, 0x5c00b000, 0x1c01f000,
-	0x492fc857, 0x4c580000, 0x4c000000, 0x8058b1c0,
-	0x0400000b, 0x82580500, 0xfffffff0, 0x02020800,
-	0x00100615, 0x8058b0d0, 0x592c0408, 0x82000500,
-	0xfffff0ff, 0x80580540, 0x48025c08, 0x5c000000,
-	0x5c00b000, 0x1c01f000, 0x492fc857, 0x4c000000,
-	0x4c040000, 0x800000d8, 0x592c0c08, 0x82040d00,
-	0xffff0fff, 0x80040540, 0x48025c08, 0x5c000800,
-	0x5c000000, 0x1c01f000, 0x4933c857, 0x4d2c0000,
-	0x59325808, 0x592c0207, 0x8400055e, 0x48025a07,
-	0x4c500000, 0x4c540000, 0x4c580000, 0x0401ffd9,
-	0x0201f800, 0x00105439, 0x46002800, 0x00000018,
-	0x80142800, 0x8058b040, 0x83cca400, 0x00000007,
-	0x4014a800, 0x0201f800, 0x0010a93e, 0x5c00b000,
-	0x5c00a800, 0x5c00a000, 0x5c025800, 0x1c01f000,
-	0x59325808, 0x592c0204, 0x82000580, 0x00000152,
-	0x1c01f000, 0x5930001f, 0x80000540, 0x02020800,
-	0x00100d9a, 0x1c01f000, 0x4d2c0000, 0x59325808,
-	0x59300203, 0x4933c857, 0x492fc857, 0x493bc857,
-	0x4803c857, 0x82003480, 0x0000000e, 0x02021800,
-	0x00100615, 0x0c01f803, 0x5c025800, 0x1c01f000,
-	0x00109386, 0x00109391, 0x001093cf, 0x00109386,
-	0x00109386, 0x00109386, 0x00109386, 0x00109386,
-	0x00109388, 0x00109386, 0x00109386, 0x00109386,
-	0x00109386, 0x00109386, 0x0201f800, 0x00100615,
-	0x83383480, 0x00000056, 0x02021800, 0x00100615,
-	0x493a6403, 0x4a026203, 0x00000001, 0x0201f000,
-	0x00106470, 0x83380580, 0x00000013, 0x04020010,
-	0x4937c857, 0x592c000c, 0x800001c0, 0x04000006,
-	0x4a026203, 0x00000002, 0x59a80037, 0x48026206,
-	0x1c01f000, 0x4a025a06, 0x00000000, 0x0201f800,
-	0x00020381, 0x0201f000, 0x000208b4, 0x83380580,
-	0x00000027, 0x0400001b, 0x83380580, 0x00000014,
-	0x04000012, 0x83380580, 0x00000015, 0x04000005,
-	0x83380580, 0x00000016, 0x02020800, 0x00100615,
-	0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb,
-	0x59300203, 0x82000580, 0x00000002, 0x02020800,
-	0x00100615, 0x0401f016, 0x4937c857, 0x0201f800,
-	0x001068f6, 0x4a02580e, 0x00000011, 0x0401f006,
-	0x4937c857, 0x0201f800, 0x001068f6, 0x4a02580e,
-	0x00000010, 0x4a025a06, 0x00000031, 0x4a02580d,
-	0x00000004, 0x0201f800, 0x00020381, 0x0201f800,
-	0x00104a83, 0x0201f000, 0x00107698, 0x59341400,
-	0x82081d00, 0x000000ff, 0x59300c03, 0x480bc857,
-	0x4807c857, 0x82040580, 0x00000053, 0x0400002e,
-	0x82040580, 0x00000002, 0x04000016, 0x82040580,
-	0x00000001, 0x04000017, 0x82040580, 0x00000003,
-	0x0400001c, 0x82040580, 0x00000005, 0x0400001d,
-	0x82040580, 0x00000033, 0x0400001a, 0x82040580,
-	0x00000000, 0x0400001b, 0x82040580, 0x00000004,
-	0x02020800, 0x00100615, 0x0401f8a1, 0x0401f016,
-	0x820c0580, 0x00000003, 0x0400084c, 0x0401f012,
-	0x820c0580, 0x0000000b, 0x0402000f, 0x42000800,
-	0x00000007, 0x0201f800, 0x001043c7, 0x0401f00a,
-	0x820c0580, 0x00000005, 0x04000864, 0x0401f006,
-	0x820c0580, 0x00000009, 0x04000889, 0x0401f002,
-	0x0401f893, 0x4a026403, 0x00000052, 0x59a81016,
-	0x592c040b, 0x8c000500, 0x04000003, 0x42001000,
-	0x00000008, 0x592c040b, 0x8c000516, 0x04000003,
-	0x82081400, 0x00000018, 0x592c000c, 0x497a580d,
-	0x497a580e, 0x80080c80, 0x04000009, 0x04001005,
-	0x4a025a06, 0x00000007, 0x40001000, 0x0401f006,
-	0x4a025a06, 0x00000015, 0x0401f003, 0x4a025a06,
-	0x00000000, 0x480a580c, 0x82081400, 0x00000003,
-	0x80081104, 0x0201f800, 0x0010783c, 0x04000010,
-	0x592c1001, 0x480a600b, 0x58080800, 0x82080400,
-	0x00000002, 0x592c1011, 0x592c1812, 0x42003000,
-	0x00000000, 0x42002000, 0x00101250, 0x0201f800,
-	0x001079b9, 0x04000002, 0x1c01f000, 0x4a025a06,
-	0x0000002c, 0x497a580c, 0x0201f800, 0x00020381,
-	0x0201f000, 0x000208b4, 0x83380580, 0x00000015,
-	0x0402000a, 0x59a8006f, 0x8c000502, 0x0402000b,
-	0x0201f800, 0x00104480, 0x42000800, 0x00000004,
-	0x0201f000, 0x001043c7, 0x42000800, 0x00000007,
-	0x0201f000, 0x001043c7, 0x0201f800, 0x00104e0d,
-	0x42001000, 0x00000010, 0x04020009, 0x59340002,
-	0x82000500, 0x00ff0000, 0x82000580, 0x00ff0000,
-	0x040007ec, 0x42001000, 0x00000008, 0x0201f800,
-	0x00104ada, 0x040007e7, 0x592c040b, 0x84000540,
-	0x48025c0b, 0x0401f7e9, 0x83380580, 0x00000015,
-	0x0402000f, 0x59a8006f, 0x8c000502, 0x04020010,
-	0x0201f800, 0x001044e1, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x5c027800, 0x42000800,
-	0x00000006, 0x0201f000, 0x001043c7, 0x42000800,
-	0x00000004, 0x0201f000, 0x001043c7, 0x0201f800,
-	0x00104e0d, 0x42001000, 0x00000010, 0x04020009,
-	0x59340002, 0x82000500, 0x00ff0000, 0x82000580,
-	0x00ff0000, 0x040007e7, 0x42001000, 0x00000008,
-	0x0201f800, 0x00104ada, 0x040007e2, 0x592c040b,
-	0x84000540, 0x48025c0b, 0x0401f7e9, 0x42000800,
-	0x00000004, 0x0201f000, 0x001043c7, 0x83380580,
-	0x00000015, 0x04020005, 0x0201f800, 0x0010a0b1,
-	0x02000800, 0x00104711, 0x1c01f000, 0x83380580,
-	0x00000015, 0x0402001d, 0x4c580000, 0x83cc1400,
-	0x00000008, 0x4200b000, 0x00000002, 0x83341c00,
-	0x00000006, 0x0201f800, 0x001082ff, 0x04020012,
-	0x83cc1400, 0x0000000a, 0x4200b000, 0x00000002,
-	0x83341c00, 0x00000008, 0x0201f800, 0x001082ff,
-	0x04020009, 0x59342200, 0x59cc1007, 0x800811c0,
-	0x04000003, 0x480a6801, 0x84102542, 0x8410251a,
-	0x48126a00, 0x5c00b000, 0x1c01f000, 0x42000000,
-	0x0010b67a, 0x0201f800, 0x0010a86e, 0x0201f800,
-	0x0010698c, 0x59300203, 0x4933c857, 0x4803c857,
-	0x82000c80, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f803, 0x0201f000, 0x00106982, 0x001094d7,
-	0x001094e6, 0x001094d8, 0x001094d5, 0x001094d5,
-	0x001094d5, 0x001094d5, 0x001094d5, 0x001094d5,
-	0x001094d5, 0x001094d5, 0x001094d5, 0x001094d5,
-	0x001094d5, 0x0201f800, 0x00100615, 0x1c01f000,
-	0x59300403, 0x82000580, 0x00000052, 0x02000000,
-	0x00108b39, 0x0201f800, 0x00104a83, 0x59325808,
-	0x4a025a06, 0x00000006, 0x0201f800, 0x00020381,
-	0x0201f000, 0x00107698, 0x59301804, 0x840c0520,
-	0x48026004, 0x598c000d, 0x81300580, 0x04020010,
-	0x8c0c1d20, 0x04020010, 0x42001000, 0x0010b5f4,
-	0x50081000, 0x58080002, 0x82000580, 0x00000100,
-	0x0400000e, 0x5808000c, 0x81300580, 0x02020800,
-	0x00100615, 0x4978100c, 0x0401f003, 0x8c0c1d20,
-	0x040207dc, 0x0201f800, 0x00106619, 0x040007d9,
-	0x0201f800, 0x00100615, 0x0201f800, 0x00106be2,
-	0x040007f9, 0x59300203, 0x82000c80, 0x0000000e,
-	0x02021800, 0x00100615, 0x0c01f7bd, 0x4933c857,
-	0x4c500000, 0x4c540000, 0x4c580000, 0x592c0c07,
-	0x4806580a, 0x59cc0809, 0x48065807, 0x59cc0a08,
-	0x4806580b, 0x59a8086e, 0x82040500, 0x000003ff,
-	0x800010c4, 0x8c040d14, 0x04000005, 0x59cc0002,
-	0x82000500, 0x00000003, 0x80081480, 0x82080480,
-	0x000000f1, 0x02021800, 0x00100615, 0x480a621a,
-	0x412c0800, 0x0201f800, 0x00100819, 0x02000800,
-	0x00100615, 0x492c0809, 0x58040408, 0x84000552,
-	0x84000540, 0x48000c08, 0x82081400, 0x00000003,
-	0x80081104, 0x83cca400, 0x00000006, 0x832cac00,
-	0x00000004, 0x42000800, 0x00000010, 0x82080480,
-	0x00000010, 0x04021003, 0x40080800, 0x80000580,
-	0x4004b000, 0x4c000000, 0x0201f800, 0x0010a94f,
-	0x5c000000, 0x800001c0, 0x0400000d, 0x412c1000,
-	0x4c000000, 0x0201f800, 0x00100819, 0x02000800,
-	0x00100615, 0x492c1001, 0x832cac00, 0x00000004,
-	0x5c000000, 0x40001000, 0x0401f7e9, 0x5c00b000,
-	0x5c00a800, 0x5c00a000, 0x1c01f000, 0x4933c857,
-	0x4d2c0000, 0x4c380000, 0x59325808, 0x5930021a,
-	0x48025a08, 0x59301011, 0x800811c0, 0x04020008,
-	0x4a025a06, 0x00000000, 0x592c000b, 0x82000500,
-	0x00000c00, 0x0400000b, 0x0401f00b, 0x8c08153e,
-	0x04000006, 0x4a025a06, 0x00000007, 0x80081080,
-	0x80081000, 0x0401f003, 0x4a025a06, 0x00000015,
-	0x480a5807, 0x42000000, 0x0010bcd8, 0x50007000,
-	0x5838000b, 0x80000540, 0x04020008, 0x4930700c,
-	0x4930700b, 0x58380002, 0x82000580, 0x00000000,
-	0x04020809, 0x0401f005, 0x82001400, 0x00000000,
-	0x45301000, 0x4930700b, 0x5c007000, 0x5c025800,
-	0x1c01f000, 0x4933c857, 0x592c0009, 0x40001000,
-	0x4800700a, 0x82080400, 0x00000004, 0x48007003,
-	0x592c000d, 0x592c100e, 0x48007007, 0x48087008,
-	0x592c000a, 0x592c1208, 0x80080c80, 0x04001002,
-	0x40001000, 0x82081400, 0x00000003, 0x80081104,
-	0x82080480, 0x00000010, 0x04021003, 0x80000580,
-	0x0401f003, 0x42001000, 0x00000010, 0x4800700d,
-	0x48087004, 0x800810c4, 0x48087005, 0x40381000,
-	0x0201f800, 0x001008a1, 0x1c01f000, 0x4d2c0000,
-	0x0201f800, 0x00100819, 0x02000800, 0x00100615,
-	0x42000800, 0x0010bcd8, 0x452c0800, 0x497a580b,
-	0x497a580c, 0x497a580d, 0x4a025809, 0x001095b6,
-	0x4a025802, 0x00000100, 0x4a025801, 0x00000000,
-	0x5c025800, 0x1c01f000, 0x4833c857, 0x4d300000,
-	0x4d2c0000, 0x4c5c0000, 0x4030b800, 0x585c000a,
-	0x80025d40, 0x04020004, 0x585c000c, 0x4c000000,
-	0x0401f044, 0x585c0002, 0x82000580, 0x00000100,
-	0x04020022, 0x592c0801, 0x4c040000, 0x0201f800,
-	0x0010083a, 0x5c000800, 0x800409c0, 0x0400001c,
-	0x4804b80a, 0x585c100d, 0x800811c0, 0x04020005,
-	0x40065800, 0x0201f800, 0x00100843, 0x0401f014,
-	0x82080480, 0x00000010, 0x04021003, 0x80000580,
-	0x0401f003, 0x42001000, 0x00000010, 0x4800b80d,
-	0x4808b804, 0x800810c4, 0x4808b805, 0x82040400,
-	0x00000004, 0x4800b803, 0x405c1000, 0x0201f800,
-	0x001008a1, 0x0401f025, 0x0401f828, 0x585c000c,
-	0x80026540, 0x59300000, 0x80000d40, 0x04020002,
-	0x4800b80b, 0x4800b80c, 0x497a6000, 0x4c000000,
-	0x4978b80a, 0x59325808, 0x4a025a04, 0x00000103,
-	0x59300402, 0x48025c06, 0x592c100b, 0x4c080000,
-	0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7,
-	0x5c001000, 0x8c081518, 0x04000004, 0x0201f800,
-	0x00108f88, 0x0401f003, 0x0201f800, 0x000208b4,
-	0x405c7000, 0x5c000000, 0x80026540, 0x04000003,
-	0x59325808, 0x0401ff78, 0x5c00b800, 0x5c025800,
-	0x5c026000, 0x1c01f000, 0x483bc857, 0x5838000a,
-	0x40025800, 0x0201f800, 0x00100843, 0x5838000c,
-	0x80026540, 0x59300008, 0x80025d40, 0x4a025a06,
-	0x00000002, 0x1c01f000, 0x4803c857, 0x4d1c0000,
-	0x497a601c, 0x41323800, 0x40026000, 0x4d3c0000,
-	0x42027800, 0x00000005, 0x0401f840, 0x5c027800,
-	0x411e6000, 0x59300414, 0x84000502, 0x48026414,
-	0x5c023800, 0x1c01f000, 0x481bc857, 0x4933c857,
-	0x4c5c0000, 0x4c600000, 0x4010b800, 0x4014c000,
-	0x0201f800, 0x0010a766, 0x0201f800, 0x0010393e,
-	0x04000008, 0x40602800, 0x405c3000, 0x0201f800,
-	0x0010a258, 0x82000540, 0x00000001, 0x0401f002,
-	0x80000580, 0x5c00c000, 0x5c00b800, 0x1c01f000,
-	0x4803c856, 0x4d300000, 0x42026000, 0x0010cfc0,
-	0x59a8000e, 0x81640580, 0x0400001a, 0x59300c06,
-	0x82040580, 0x00000001, 0x0400000d, 0x82040580,
-	0x00000004, 0x04000006, 0x82040580, 0x00000010,
-	0x02000800, 0x00108aad, 0x0401f009, 0x59300203,
-	0x82000d80, 0x00000007, 0x04000005, 0x4807c857,
-	0x0201f800, 0x0010909d, 0x04020808, 0x83326400,
-	0x00000024, 0x41580000, 0x81300480, 0x040017e5,
-	0x5c026000, 0x1c01f000, 0x4933c857, 0x59300403,
-	0x4803c857, 0x0201f800, 0x0010698c, 0x4df00000,
-	0x59300406, 0x4803c857, 0x82000d80, 0x00000002,
-	0x04000018, 0x82000d80, 0x00000001, 0x04000009,
-	0x82000d80, 0x00000004, 0x04000006, 0x4933c856,
-	0x5c03e000, 0x02000800, 0x00106982, 0x0401f03c,
-	0x59300203, 0x82000d80, 0x00000001, 0x04000018,
-	0x82000d80, 0x00000002, 0x04000026, 0x82000d80,
-	0x00000005, 0x04000023, 0x0201f800, 0x00100615,
-	0x59300203, 0x82000d80, 0x00000009, 0x0400000c,
-	0x82000d80, 0x0000000b, 0x04000009, 0x82000d80,
-	0x0000000a, 0x04000017, 0x82000d80, 0x0000000c,
-	0x04000014, 0x0201f800, 0x00100615, 0x598c000d,
-	0x81300580, 0x04020004, 0x0201f800, 0x00106be2,
-	0x0402000c, 0x59300004, 0x4803c857, 0x8c000520,
-	0x04000004, 0x84000520, 0x48026004, 0x0401f005,
-	0x0201f800, 0x00106619, 0x02020800, 0x00100615,
-	0x5c03e000, 0x02000800, 0x00106982, 0x59300406,
-	0x82000d80, 0x00000002, 0x04000009, 0x0201f800,
-	0x00104a83, 0x0201f800, 0x00108f05, 0x02000800,
-	0x00107da6, 0x8d3e7d00, 0x04000003, 0x0201f000,
-	0x00107698, 0x4a02621d, 0x00000001, 0x4a026403,
-	0x00000085, 0x4a026203, 0x00000009, 0x4a026406,
-	0x00000002, 0x42000800, 0x8000004b, 0x0201f000,
-	0x00020855, 0x4933c857, 0x59368c03, 0x4c180000,
-	0x59300203, 0x82003480, 0x0000000e, 0x02021800,
-	0x00100615, 0x0c01f803, 0x5c003000, 0x1c01f000,
-	0x001096da, 0x00109bb9, 0x00109cbd, 0x001096da,
-	0x001096da, 0x001096da, 0x001096da, 0x001096da,
-	0x001096fd, 0x001096da, 0x001096da, 0x001096da,
-	0x001096da, 0x001096da, 0x0201f800, 0x00100615,
-	0x4933c857, 0x42028800, 0x0000ffff, 0x813669c0,
-	0x04000002, 0x59368c03, 0x4c180000, 0x59300203,
-	0x82003480, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f803, 0x5c003000, 0x1c01f000, 0x001096f9,
-	0x00109f70, 0x001096f9, 0x001096f9, 0x001096f9,
-	0x001096f9, 0x001096f9, 0x0010a779, 0x00109edd,
-	0x0010a34a, 0x0010a380, 0x0010a34a, 0x0010a380,
-	0x001096f9, 0x0201f800, 0x00100615, 0x0201f800,
-	0x00100615, 0x83383480, 0x00000051, 0x02021800,
-	0x00100615, 0x41380000, 0x493bc857, 0x4d1c0000,
-	0x4d400000, 0x0c01f804, 0x5c028000, 0x5c023800,
-	0x1c01f000, 0x0010975a, 0x0010993d, 0x0010975a,
-	0x0010975a, 0x0010975a, 0x00109948, 0x0010975a,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a,
-	0x0010977c, 0x001097ba, 0x001097d1, 0x0010982d,
-	0x00109894, 0x001098d2, 0x00109902, 0x0010975a,
-	0x0010975a, 0x00109950, 0x0010975a, 0x0010975a,
-	0x0010995e, 0x00109967, 0x0010975a, 0x0010975a,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x001099e9,
-	0x0010975a, 0x0010975a, 0x00109868, 0x0010975a,
-	0x0010975a, 0x001099c0, 0x0010975a, 0x0010975a,
-	0x0010975a, 0x001099f7, 0x0010975a, 0x0010975a,
-	0x0010975a, 0x00109a40, 0x0010975a, 0x0010975a,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x0010975a,
-	0x00109a8d, 0x0010975a, 0x00109ab9, 0x00109ac4,
-	0x0010975a, 0x0010975a, 0x0010975c, 0x00109acf,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x0010976b,
-	0x0010975a, 0x0010975a, 0x0010975a, 0x00109ad6,
-	0x00109ade, 0x00109afc, 0x0201f800, 0x00100615,
-	0x4933c857, 0x0201f800, 0x0010a3b0, 0x040203a8,
-	0x0201f800, 0x00101eb0, 0x040203a5, 0x59cc0407,
-	0x4802601c, 0x4a026403, 0x00000045, 0x4a026203,
-	0x00000001, 0x0201f000, 0x00106470, 0x4933c857,
-	0x0201f800, 0x0010a3b0, 0x04020399, 0x0201f800,
-	0x00101eb0, 0x04020396, 0x0401fbd6, 0x0402019e,
-	0x59cc0007, 0x4802601c, 0x4a026403, 0x0000004a,
-	0x4a026203, 0x00000001, 0x0201f000, 0x00106470,
-	0x4933c857, 0x0201f800, 0x00101eb0, 0x04020009,
-	0x0201f800, 0x0010473b, 0x04020006, 0x82000500,
-	0x00000009, 0x82000580, 0x00000008, 0x04020008,
-	0x4a026403, 0x00000009, 0x4a02641a, 0x00000009,
-	0x4a02621a, 0x00000000, 0x0401f1b6, 0x0201f800,
-	0x00104858, 0x04000018, 0x0201f800, 0x0010a041,
-	0x0402001f, 0x42028000, 0x00000029, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x0201f800, 0x00104480, 0x4a026403, 0x00000008,
-	0x42003000, 0x00000003, 0x0201f800, 0x0010393e,
-	0x040001a0, 0x4a026203, 0x00000007, 0x41782800,
-	0x0401f18b, 0x0201f800, 0x0010a1ec, 0x040207e7,
-	0x4a026403, 0x00000009, 0x4a02641a, 0x0000000e,
-	0x4a02621a, 0x00001900, 0x0401f192, 0x4a026403,
-	0x00000009, 0x4a02641a, 0x00000003, 0x4a02621a,
-	0x00000f00, 0x0401f18b, 0x4933c857, 0x0201f800,
-	0x00101eb0, 0x0402034a, 0x0201f800, 0x0010473b,
-	0x04020347, 0x493a6403, 0x0201f800, 0x0010a01c,
-	0x04020006, 0x42003000, 0x00000005, 0x4a026403,
-	0x00000006, 0x0401f7d9, 0x4a026403, 0x00000007,
-	0x4a02641a, 0x00000009, 0x4a02621a, 0x00000000,
-	0x0401f174, 0x4933c857, 0x0201f800, 0x0010473b,
-	0x04020333, 0x0201f800, 0x0010a3b0, 0x02000800,
-	0x00101eb0, 0x0402032e, 0x0201f800, 0x00104858,
-	0x04020005, 0x42027800, 0x00000001, 0x0201f800,
-	0x001043bd, 0x0201f800, 0x0010484b, 0x04020031,
-	0x59cc0206, 0x82003500, 0x00000003, 0x04020034,
-	0x82003480, 0x00000014, 0x04001031, 0x5934300a,
-	0x84183516, 0x82000580, 0x00000014, 0x04020002,
-	0x84183556, 0x481a680a, 0x59cc0406, 0x82000500,
-	0x00000003, 0x04020026, 0x0201f800, 0x0010a08e,
-	0x0402002e, 0x0201f800, 0x00104836, 0x04020007,
-	0x4c600000, 0x4178c000, 0x417a7800, 0x0201f800,
-	0x00101e48, 0x5c00c000, 0x836c0580, 0x00000003,
-	0x04020009, 0x42003000, 0x00000006, 0x0201f800,
-	0x0010a75e, 0x42000000, 0x0010b664, 0x0201f800,
-	0x0010a86e, 0x0201f800, 0x001044e1, 0x4a026403,
-	0x0000000a, 0x42003000, 0x00000020, 0x0401f78f,
-	0x4a026403, 0x0000000b, 0x4a02641a, 0x00000009,
-	0x4a02621a, 0x00001e00, 0x0401f12a, 0x42000000,
-	0x0010b65f, 0x0201f800, 0x0010a86e, 0x4a026403,
-	0x0000000b, 0x4a02641a, 0x00000007, 0x4a02621a,
-	0x00000000, 0x0401f11f, 0x4a026403, 0x0000000b,
-	0x4a02641a, 0x00000003, 0x4a02621a, 0x00000000,
-	0x0401f118, 0x4933c857, 0x0201f800, 0x0010473b,
-	0x040202d7, 0x0201f800, 0x0010a3b0, 0x040202d4,
-	0x0201f800, 0x00101eb0, 0x040202d1, 0x59cc0206,
-	0x82003500, 0x00000003, 0x04020020, 0x82003480,
-	0x00000014, 0x0400101d, 0x59cc0406, 0x82000500,
-	0x00000003, 0x04020019, 0x59340400, 0x82000580,
-	0x00000707, 0x0400001c, 0x417a7800, 0x4c600000,
-	0x4178c000, 0x0201f800, 0x00101e48, 0x5c00c000,
-	0x42003000, 0x0000000a, 0x0201f800, 0x0010a75e,
-	0x42000000, 0x0010b661, 0x0201f800, 0x0010a86e,
-	0x4a026403, 0x0000000c, 0x41782800, 0x42003000,
-	0x00000021, 0x0401f749, 0x4a026403, 0x0000000d,
-	0x4a02641a, 0x00000007, 0x4a02621a, 0x00000000,
-	0x0401f0e4, 0x4a026403, 0x0000000d, 0x4a02641a,
-	0x00000009, 0x4a02621a, 0x00001e00, 0x0401f0dd,
-	0x4933c857, 0x0201f800, 0x0010473b, 0x0402029c,
-	0x0201f800, 0x0010a3b0, 0x04020299, 0x0201f800,
-	0x00101eb0, 0x04020296, 0x0401fad6, 0x0402001a,
-	0x493a6403, 0x4c5c0000, 0x0401fadc, 0x0402000e,
-	0x4a026403, 0x0000002e, 0x4014b800, 0x0201f800,
-	0x0010393e, 0x0400000e, 0x4a026203, 0x00000007,
-	0x405c2800, 0x42003000, 0x00000024, 0x5c00b800,
-	0x0401f0af, 0x4a026403, 0x0000000d, 0x4a02641a,
-	0x00000007, 0x4a02621a, 0x00000000, 0x5c00b800,
-	0x0401f0b8, 0x4a026403, 0x0000000d, 0x4a02641a,
-	0x00000009, 0x4a02621a, 0x00001e00, 0x0401f0b1,
-	0x4933c857, 0x0201f800, 0x0010473b, 0x040206f1,
-	0x59a80026, 0x82000500, 0x00000009, 0x82000580,
-	0x00000008, 0x040006eb, 0x0201f800, 0x0010484b,
-	0x0402002d, 0x0201f800, 0x0010a096, 0x04020007,
-	0x4a026403, 0x0000000e, 0x41782800, 0x42003000,
-	0x00000052, 0x0401f6f9, 0x4933c857, 0x42003000,
-	0x00000003, 0x0201f800, 0x0010a766, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e,
-	0x59340200, 0x84000558, 0x48026a00, 0x42000800,
-	0x0000000b, 0x0201f800, 0x001043c7, 0x0201f800,
-	0x0010393e, 0x0400007c, 0x42003000, 0x00000007,
-	0x0401f061, 0x4933c857, 0x4a026403, 0x0000000f,
-	0x4a02641a, 0x00000003, 0x4a02621a, 0x00001e00,
-	0x0401f078, 0x59340400, 0x82000580, 0x00000703,
-	0x040007f5, 0x0401f040, 0x4933c857, 0x0201f800,
-	0x0010473b, 0x04020232, 0x59a80026, 0x82000500,
-	0x00000009, 0x82000580, 0x00000008, 0x0400022c,
-	0x0201f800, 0x00104842, 0x0402002f, 0x0201f800,
-	0x0010a0b1, 0x02000800, 0x0010a041, 0x04020007,
-	0x4a026403, 0x00000010, 0x41782800, 0x42003000,
-	0x00000050, 0x0401f6b9, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x00101de2, 0x5c027800, 0x42003000,
-	0x00000003, 0x0201f800, 0x0010a766, 0x42000000,
-	0x0010b663, 0x0201f800, 0x0010a86e, 0x59340200,
-	0x84000558, 0x48026a00, 0x0401f7c5, 0x4a026403,
-	0x00000011, 0x4a02641a, 0x00000003, 0x4a02621a,
-	0x00001e00, 0x0401f043, 0x4933c857, 0x0201f800,
-	0x00101eb0, 0x02000800, 0x0010a3b0, 0x04020200,
-	0x0401fa40, 0x04020008, 0x4a026403, 0x00000012,
-	0x0401f038, 0x59340400, 0x82000580, 0x00000703,
-	0x040007eb, 0x4d3c0000, 0x417a7800, 0x42028000,
-	0x00000029, 0x0201f800, 0x00101de2, 0x5c027800,
-	0x42003000, 0x00000017, 0x0201f800, 0x0010a766,
-	0x42000000, 0x0010b663, 0x0201f800, 0x0010a86e,
-	0x0201f800, 0x0010393e, 0x0400001b, 0x42003000,
-	0x00000006, 0x42028000, 0x00000029, 0x4933c857,
-	0x4a026403, 0x00000001, 0x4a026203, 0x00000007,
-	0x4c180000, 0x0201f800, 0x0010a79b, 0x5c003000,
-	0x41782800, 0x0201f000, 0x0010a250, 0x42028000,
-	0x00000046, 0x4c140000, 0x4c180000, 0x0201f800,
-	0x0010a79b, 0x5c003000, 0x5c002800, 0x0201f000,
-	0x0010a250, 0x4933c857, 0x4a026403, 0x00000001,
-	0x42000800, 0x0000000b, 0x0201f800, 0x001043c7,
-	0x4a026203, 0x00000001, 0x0201f000, 0x00106470,
-	0x4933c857, 0x42000800, 0x00000009, 0x0201f800,
-	0x001043c7, 0x4a026403, 0x00000005, 0x0401f7f5,
-	0x0201f800, 0x0010a3b0, 0x040201b5, 0x0201f800,
-	0x00101eb0, 0x040201b2, 0x0401f9f2, 0x040207ba,
-	0x4a026403, 0x00000020, 0x4a026203, 0x00000001,
-	0x0201f000, 0x00106470, 0x0201f800, 0x00101eb0,
-	0x040201a7, 0x4a026403, 0x00000023, 0x4a026203,
-	0x00000001, 0x0201f000, 0x00106470, 0x0201f800,
-	0x0010a3b0, 0x02000800, 0x00101eb0, 0x0402019c,
-	0x0401f9dc, 0x040207a4, 0x40300800, 0x59a81010,
-	0x59cc0007, 0x82000500, 0x00ffffff, 0x80080580,
-	0x04000019, 0x59cc1408, 0x0201f800, 0x00108de9,
-	0x0400002d, 0x59cc0c08, 0x4d300000, 0x0201f800,
-	0x00105b0f, 0x41323800, 0x5c026000, 0x04000026,
-	0x591c0202, 0x82000580, 0x0000ffff, 0x04000005,
-	0x59cc1208, 0x591c0202, 0x80080580, 0x0402001e,
-	0x591c0406, 0x82000580, 0x00000007, 0x0402001a,
-	0x0401f02c, 0x59cc1208, 0x82080580, 0x0000ffff,
-	0x0400000c, 0x0201f800, 0x001091d9, 0x04000012,
-	0x59cc1408, 0x591c0202, 0x80080580, 0x0402000e,
-	0x591c0009, 0x81340580, 0x04000016, 0x0401f00a,
-	0x59cc1408, 0x417a7800, 0x0201f800, 0x0010a217,
-	0x04020010, 0x59cc1208, 0x82080580, 0x0000ffff,
-	0x04000019, 0x4a026403, 0x00000026, 0x4a02621a,
-	0x00001700, 0x59cc1204, 0x82081580, 0x0000ffff,
-	0x04020798, 0x4a026403, 0x00000025, 0x0401f795,
-	0x591c0406, 0x82000580, 0x00000007, 0x040207f2,
-	0x591c0403, 0x82000580, 0x00000024, 0x04020006,
-	0x4d300000, 0x411e6000, 0x0201f800, 0x000208b4,
-	0x5c026000, 0x4a026403, 0x00000025, 0x0401f785,
-	0x4933c857, 0x4d3c0000, 0x42027800, 0x00000001,
-	0x0201f800, 0x001043bd, 0x5c027800, 0x4c580000,
-	0x4200b000, 0x00000002, 0x83a81c00, 0x00000002,
-	0x83cc1400, 0x0000000b, 0x0201f800, 0x001082ff,
-	0x5c00b000, 0x04000004, 0x4a026403, 0x00000031,
-	0x0401f770, 0x0201f800, 0x00107698, 0x0201f800,
-	0x00104e0d, 0x0402000f, 0x0201f800, 0x00104e1b,
-	0x04020008, 0x4a035033, 0x00000001, 0x4202d800,
-	0x00000001, 0x0201f800, 0x00104d76, 0x0401f005,
-	0x42000000, 0x00000001, 0x0201f800, 0x00104de5,
-	0x1c01f000, 0x0201f800, 0x00101eb0, 0x0402011c,
-	0x0401f95c, 0x04020724, 0x493a6403, 0x0401f9ac,
-	0x04020004, 0x4a026403, 0x0000002b, 0x0401f751,
-	0x4a026403, 0x0000002c, 0x0401f74e, 0x4933c857,
-	0x0201f800, 0x00101eb0, 0x0402010d, 0x0201f800,
-	0x00104836, 0x04020740, 0x0201f800, 0x00104728,
-	0x0400003c, 0x59cc0408, 0x48026419, 0x59cc0208,
-	0x48026219, 0x59cc0807, 0x59340002, 0x82000500,
-	0x00ffffff, 0x80040580, 0x04000012, 0x59a80010,
-	0x80040580, 0x04020021, 0x59cc1408, 0x0201f800,
-	0x001091d9, 0x04000023, 0x0201f800, 0x0010a2e8,
-	0x04000020, 0x0201f800, 0x0010a745, 0x0400001d,
-	0x491e601e, 0x4a026403, 0x00000036, 0x0401f0e6,
-	0x59cc1208, 0x82080580, 0x0000ffff, 0x04000009,
-	0x0201f800, 0x001091d9, 0x04000012, 0x591c0202,
-	0x59cc0c08, 0x80040580, 0x0402000e, 0x0401f7eb,
-	0x59cc1408, 0x41327800, 0x0201f800, 0x0010a217,
-	0x04000008, 0x0401f7e5, 0x4803c856, 0x4a02641a,
-	0x00000009, 0x4a02621a, 0x00001500, 0x0401f006,
-	0x4803c856, 0x4a02641a, 0x00000003, 0x4a02621a,
-	0x00001700, 0x4a026403, 0x00000037, 0x0401f0c6,
-	0x4803c856, 0x4a026403, 0x00000012, 0x0401f0c2,
-	0x4933c857, 0x0201f800, 0x00101eb0, 0x040200c4,
-	0x0201f800, 0x00104836, 0x040206f7, 0x0201f800,
-	0x00104728, 0x0400003e, 0x59cc0407, 0x48026419,
-	0x59cc1207, 0x480a6219, 0x82080580, 0x0000ffff,
-	0x04000005, 0x0201f800, 0x001091d9, 0x0400002c,
-	0x0401f006, 0x59cc1407, 0x41327800, 0x0201f800,
-	0x0010a217, 0x04000026, 0x59cc0c07, 0x591c0202,
-	0x80040580, 0x04020022, 0x4d300000, 0x411e6000,
-	0x0201f800, 0x0010898b, 0x5c026000, 0x59cc0c09,
-	0x82040d00, 0x0000ff00, 0x840409c0, 0x0201f800,
-	0x0010a745, 0x04000016, 0x82040580, 0x00000001,
-	0x0400000a, 0x82040580, 0x00000005, 0x04000004,
-	0x82040580, 0x00000007, 0x04020007, 0x591c0008,
-	0x80000540, 0x04000004, 0x59cc2808, 0x0201f000,
-	0x0010a2fc, 0x4803c856, 0x4a02641a, 0x00000009,
-	0x4a02621a, 0x00002a00, 0x0401f006, 0x4803c856,
-	0x4a02641a, 0x00000003, 0x4a02621a, 0x00000300,
-	0x4a026403, 0x0000003b, 0x0401f07b, 0x4803c856,
-	0x4a02641a, 0x0000000b, 0x4a02621a, 0x00000000,
-	0x0401f7f8, 0x4c080000, 0x0201f800, 0x0010473b,
-	0x04000026, 0x0201f800, 0x00104711, 0x0201f800,
-	0x0010a41c, 0x0402001e, 0x59a80026, 0x82000540,
-	0x00000003, 0x48035026, 0x59a8001d, 0x800000d0,
-	0x59a80810, 0x82040d00, 0x000000ff, 0x80041540,
-	0x480b5010, 0x42000800, 0x00000003, 0x0201f800,
-	0x001069af, 0x497b5028, 0x0201f800, 0x0010393e,
-	0x04000003, 0x4a032804, 0x000007d0, 0x8c00050a,
-	0x0402000a, 0x0201f800, 0x000208b4, 0x0201f800,
-	0x00101bf0, 0x5c001000, 0x1c01f000, 0x0201f800,
-	0x0010a43e, 0x0401f7fc, 0x5c001000, 0x0201f000,
-	0x000208b4, 0x0201f800, 0x00101eb0, 0x0402004c,
-	0x0201f800, 0x0010a443, 0x4a026403, 0x00000047,
-	0x4a026203, 0x00000001, 0x0201f000, 0x00106470,
-	0x0201f800, 0x00101eb0, 0x04020041, 0x0201f800,
-	0x0010a443, 0x4a026403, 0x00000047, 0x4a026203,
-	0x00000001, 0x0201f000, 0x00106470, 0x0201f800,
-	0x00101eb0, 0x04020036, 0x0201f800, 0x0010a443,
-	0x0201f000, 0x000208b4, 0x0401f834, 0x04000030,
-	0x4a026403, 0x0000004e, 0x4a026203, 0x00000001,
-	0x0201f000, 0x00106470, 0x4a026403, 0x0000004f,
-	0x497a601c, 0x59cc0a06, 0x82040d00, 0x000000ff,
-	0x800409c0, 0x0400065f, 0x82040580, 0x00000001,
-	0x04020005, 0x59cc0808, 0x59a80005, 0x80040580,
-	0x04000658, 0x82040580, 0x00000002, 0x0402000a,
-	0x83cc1400, 0x0000000b, 0x4200b000, 0x00000002,
-	0x83341c00, 0x00000006, 0x0201f800, 0x001082ff,
-	0x0400064c, 0x4a02601c, 0x00000001, 0x0401f649,
-	0x4a026403, 0x00000050, 0x59cc0207, 0x4802601c,
-	0x0401f644, 0x4a026203, 0x00000001, 0x42000800,
-	0x80000040, 0x0201f000, 0x00020855, 0x4803c857,
-	0x0201f000, 0x000208b4, 0x4d2c0000, 0x4c500000,
-	0x4c580000, 0x4c540000, 0x59a80016, 0x82000c80,
-	0x00000841, 0x0402102d, 0x0201f800, 0x00100819,
-	0x0400002a, 0x492e6008, 0x59a80016, 0x48025802,
-	0x82000400, 0x00000003, 0x80000104, 0x83cca400,
-	0x00000006, 0x82000c80, 0x0000000b, 0x04001015,
-	0x4a025811, 0x0000000b, 0x4200b000, 0x0000000b,
-	0x832c0400, 0x00000005, 0x4000a800, 0x0201f800,
-	0x0010a93e, 0x412c7000, 0x800409c0, 0x04020003,
-	0x49787001, 0x0401f00e, 0x0201f800, 0x00100819,
-	0x0400000e, 0x492c7001, 0x40040000, 0x0401f7ea,
-	0x48025811, 0x4000b000, 0x832c0400, 0x00000005,
-	0x4000a800, 0x0201f800, 0x0010a93e, 0x82000540,
-	0x00000001, 0x0401f006, 0x497b5016, 0x59325808,
-	0x0201f800, 0x00100843, 0x80000580, 0x5c00a800,
-	0x5c00b000, 0x5c00a000, 0x5c025800, 0x1c01f000,
-	0x4d340000, 0x59326809, 0x59343400, 0x4933c857,
-	0x4937c857, 0x481bc857, 0x0201f800, 0x00104842,
-	0x5c026800, 0x1c01f000, 0x4933c857, 0x4c600000,
-	0x4c5c0000, 0x4d3c0000, 0x4d440000, 0x4d340000,
-	0x0401f84f, 0x04020037, 0x59cc0207, 0x82000d00,
-	0x0000ff00, 0x900411c0, 0x59cc000a, 0x82000500,
-	0x00ffffff, 0x80081540, 0x480a601c, 0x8c040d18,
-	0x04000011, 0x42003000, 0x00000008, 0x0201f800,
-	0x0010a756, 0x42000000, 0x0010b662, 0x0201f800,
-	0x0010a86e, 0x4200b800, 0x00000002, 0x4200c000,
-	0x00000001, 0x417a7800, 0x0201f800, 0x00101e48,
-	0x0401f01f, 0x4178b800, 0x8c040d1a, 0x04000019,
-	0x59cc000a, 0x0201f800, 0x001059b9, 0x02000800,
-	0x00020267, 0x04020013, 0x59300009, 0x4c000000,
-	0x49366009, 0x42003000, 0x00000009, 0x0201f800,
-	0x0010a75e, 0x42000000, 0x0010b662, 0x0201f800,
-	0x0010a86e, 0x417a7800, 0x4178c000, 0x0201f800,
-	0x00101e48, 0x5c000000, 0x48026009, 0x0401f004,
-	0x82000540, 0x00000001, 0x0401f003, 0x405c2800,
-	0x80000580, 0x5c026800, 0x5c028800, 0x5c027800,
-	0x5c00b800, 0x5c00c000, 0x1c01f000, 0x4933c857,
-	0x59cc0206, 0x82000480, 0x00000010, 0x04021006,
-	0x4a02621a, 0x00000000, 0x82000540, 0x00000001,
-	0x0401f002, 0x80000580, 0x1c01f000, 0x4933c857,
-	0x4a02621a, 0x00000000, 0x59cc0407, 0x82000500,
-	0x0000ff00, 0x82000580, 0x00000800, 0x04020009,
-	0x59cc0006, 0x82000500, 0x00ff0000, 0x82000d80,
-	0x00140000, 0x04000003, 0x82000d80, 0x00100000,
-	0x1c01f000, 0x59300403, 0x82003480, 0x00000051,
-	0x02021800, 0x00100615, 0x83383580, 0x00000013,
-	0x04020003, 0x4803c857, 0x0c01f016, 0x4933c857,
-	0x493bc857, 0x83383580, 0x00000027, 0x04000005,
-	0x83383580, 0x00000014, 0x02020800, 0x00100615,
-	0x493bc857, 0x4937c857, 0x0201f800, 0x00104711,
-	0x42000800, 0x00000007, 0x0201f800, 0x001043c7,
-	0x0201f800, 0x001068f6, 0x0201f000, 0x00107698,
-	0x00109c29, 0x00109c32, 0x00109c29, 0x00109c29,
-	0x00109c29, 0x00109c32, 0x00109c3d, 0x00109cb0,
-	0x00109c82, 0x00109cb0, 0x00109c9a, 0x00109cb0,
-	0x00109ca1, 0x00109cb0, 0x00109ca9, 0x00109cb0,
-	0x00109ca9, 0x00109cb0, 0x00109cb0, 0x00109c29,
-	0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29,
-	0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29,
-	0x00109c29, 0x00109c29, 0x00109c32, 0x00109c29,
-	0x00109cb0, 0x00109c29, 0x00109c29, 0x00109cb0,
-	0x00109c29, 0x00109cad, 0x00109cb0, 0x00109c29,
-	0x00109c29, 0x00109c29, 0x00109c29, 0x00109cb0,
-	0x00109cb0, 0x00109c29, 0x00109ca6, 0x00109cb0,
-	0x00109c29, 0x00109c37, 0x00109c29, 0x00109c29,
-	0x00109c29, 0x00109c29, 0x00109cac, 0x00109cb0,
-	0x00109c29, 0x00109c29, 0x00109cb0, 0x00109cb0,
-	0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29,
-	0x00109c29, 0x00109c29, 0x00109c29, 0x00109c29,
-	0x00109c29, 0x00109c2b, 0x00109c29, 0x00109c2b,
-	0x00109c29, 0x00109c29, 0x00109c2b, 0x00109c29,
-	0x00109c29, 0x00109c29, 0x00109c2b, 0x00109c2b,
-	0x00109c2b, 0x0201f800, 0x00100615, 0x4d2c0000,
-	0x59325808, 0x0201f800, 0x00100843, 0x5c025800,
-	0x0201f000, 0x000208b4, 0x59a80037, 0x48026206,
-	0x4a026203, 0x00000002, 0x1c01f000, 0x4d3c0000,
-	0x417a7800, 0x0201f800, 0x001043bd, 0x5c027800,
-	0x0401f074, 0x42000800, 0x00000007, 0x0201f800,
-	0x001043c7, 0x59a80026, 0x8c000508, 0x04000012,
-	0x59326809, 0x4c580000, 0x4200b000, 0x00000002,
-	0x83a81c00, 0x00000002, 0x83341400, 0x00000006,
-	0x0201f800, 0x001082ff, 0x80000540, 0x5c00b000,
-	0x04020060, 0x59340200, 0x8400051a, 0x48026a00,
-	0x0401f01b, 0x599c0017, 0x8c00050a, 0x04020059,
-	0x4d3c0000, 0x417a7800, 0x0201f800, 0x001043bd,
-	0x5c027800, 0x42000800, 0x00000007, 0x0201f800,
-	0x001043c7, 0x59340212, 0x82000500, 0x0000ff00,
-	0x0400004c, 0x599c0019, 0x8c00050e, 0x04020049,
-	0x416c0000, 0x82000580, 0x00000002, 0x04020004,
-	0x59a8001b, 0x80000000, 0x4803501b, 0x42000800,
-	0x00000003, 0x0201f800, 0x001043c7, 0x4a026406,
-	0x00000001, 0x4a026203, 0x00000001, 0x4a026403,
-	0x00000002, 0x0201f800, 0x00106470, 0x4ce80000,
-	0x4201d000, 0x00000001, 0x0201f800, 0x00105ce7,
-	0x5c01d000, 0x1c01f000, 0x0201f800, 0x00104842,
-	0x0400002c, 0x0201f800, 0x00106196, 0x42000800,
-	0x00000004, 0x0201f800, 0x001043c7, 0x0201f800,
-	0x0010a791, 0x04020023, 0x42000800, 0x00000005,
-	0x0201f800, 0x001043c7, 0x4a026406, 0x00000001,
-	0x4a026203, 0x00000001, 0x4a026403, 0x00000003,
-	0x0201f000, 0x00106470, 0x0201f800, 0x0010484b,
-	0x04020014, 0x42000800, 0x00000006, 0x0401f813,
-	0x0401f010, 0x42000800, 0x00000004, 0x0201f800,
-	0x001043c7, 0x0401f79c, 0x42000800, 0x00000004,
-	0x0401f006, 0x0201f800, 0x00104711, 0x0401f005,
-	0x0401f004, 0x0401f003, 0x0201f800, 0x001043c7,
-	0x0201f000, 0x000208b4, 0x4933c857, 0x4807c857,
-	0x0201f800, 0x001043c7, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x5c027800, 0x0201f000,
-	0x00104711, 0x59340400, 0x4803c857, 0x80000110,
-	0x82003480, 0x0000000c, 0x02021800, 0x00100615,
-	0x83383580, 0x00000015, 0x04020002, 0x0c01f006,
-	0x83383580, 0x00000016, 0x02020800, 0x00100615,
-	0x0c01f00d, 0x00107e42, 0x00107e42, 0x00107e42,
-	0x00107e42, 0x00107e42, 0x00107e42, 0x00109d11,
-	0x00109ce5, 0x00107e42, 0x00107e42, 0x00107e42,
-	0x00107e42, 0x00107e42, 0x00107e42, 0x00107e42,
-	0x00107e42, 0x00107e42, 0x00107e42, 0x00109d11,
-	0x00109d18, 0x00107e42, 0x00107e42, 0x00107e42,
-	0x00107e42, 0x4933c857, 0x599c0017, 0x8c00050a,
-	0x0402001b, 0x813669c0, 0x04000019, 0x59340212,
-	0x82000500, 0x0000ff00, 0x04000015, 0x599c0019,
-	0x8c00050e, 0x04020012, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x001043bd, 0x5c027800, 0x42000800,
-	0x00000003, 0x0201f800, 0x001043c7, 0x4a026406,
-	0x00000001, 0x4a026203, 0x00000001, 0x4a026403,
-	0x00000002, 0x0201f000, 0x00106470, 0x59cc0001,
-	0x59340802, 0x80040580, 0x82000500, 0x00ffffff,
-	0x02020000, 0x000208b4, 0x59345002, 0x0201f800,
-	0x001040e4, 0x482a6802, 0x0201f000, 0x000208b4,
-	0x1c01f000, 0x4933c857, 0x59303403, 0x82183580,
-	0x0000001e, 0x02000000, 0x000208b4, 0x1c01f000,
-	0x4933c857, 0x0201f800, 0x00108180, 0x02020000,
-	0x000208b4, 0x4a026203, 0x00000001, 0x4a026403,
-	0x00000001, 0x0201f000, 0x00106470, 0x493bc857,
-	0x83380580, 0x00000051, 0x0402000b, 0x0201f800,
-	0x00106cb4, 0x02020000, 0x001076fb, 0x59300203,
-	0x82000580, 0x00000002, 0x0400006e, 0x0201f800,
-	0x00100615, 0x83380580, 0x00000027, 0x04000014,
-	0x83380580, 0x00000048, 0x04000006, 0x83380580,
-	0x00000014, 0x0400000e, 0x02020800, 0x00100615,
-	0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb,
-	0x59300203, 0x82000580, 0x00000004, 0x02000000,
-	0x000209a5, 0x0201f800, 0x00100615, 0x4933c857,
-	0x59300403, 0x82000c80, 0x00000044, 0x02021800,
-	0x00100615, 0x82000480, 0x00000040, 0x02001800,
-	0x00100615, 0x40027000, 0x4803c857, 0x0c01f001,
-	0x00109d58, 0x00109d5a, 0x00109d5a, 0x00109d75,
-	0x0201f800, 0x00100615, 0x0201f800, 0x001068f6,
-	0x59325808, 0x812e59c0, 0x04000016, 0x832c0500,
-	0x00ff0000, 0x04000013, 0x4a026203, 0x00000002,
-	0x59326809, 0x59340200, 0x8c00050e, 0x0402000d,
-	0x42028000, 0x00000004, 0x0201f800, 0x0010a201,
-	0x497a6008, 0x59300206, 0x80000540, 0x04020003,
-	0x59a80038, 0x48026206, 0x4a026203, 0x00000007,
-	0x1c01f000, 0x0201f800, 0x001068f6, 0x0201f800,
-	0x00108df4, 0x02000000, 0x00107698, 0x59325808,
-	0x0201f800, 0x0010083a, 0x0201f000, 0x00107698,
-	0x0201f800, 0x00100615, 0x59325808, 0x592c040a,
-	0x8c000502, 0x04000007, 0x4a026203, 0x00000007,
-	0x42027000, 0x00000043, 0x0201f000, 0x000208d8,
-	0x4a026203, 0x00000004, 0x1c01f000, 0x0201f800,
-	0x0010a3b6, 0x02000000, 0x000209a3, 0x1c01f000,
-	0x4a026203, 0x00000001, 0x4a026403, 0x00000041,
-	0x42027800, 0x80002042, 0x0201f000, 0x00020855,
-	0x83380580, 0x00000051, 0x04000006, 0x83380580,
-	0x00000041, 0x02020800, 0x00100615, 0x1c01f000,
-	0x0201f800, 0x00020831, 0x0201f800, 0x0010a3fa,
-	0x0201f000, 0x000208b4, 0x83380480, 0x00000052,
-	0x02021800, 0x00100615, 0x83380480, 0x00000049,
-	0x02001800, 0x00100615, 0x0c01f001, 0x00109dbe,
-	0x00109ddf, 0x00109dbc, 0x00109dbc, 0x00109dbc,
-	0x00109dbc, 0x00109ddf, 0x00109dbc, 0x00109e01,
-	0x0201f800, 0x00100615, 0x59325808, 0x592c040a,
-	0x8c00051e, 0x0400000d, 0x82000d00, 0x000000c0,
-	0x82040d80, 0x00000080, 0x0400000d, 0x59300804,
-	0x8c040d18, 0x0402000a, 0x42027000, 0x00000041,
-	0x0201f000, 0x000209c4, 0x4a026203, 0x00000007,
-	0x497a6206, 0x0201f000, 0x00020831, 0x59325808,
-	0x592c0c0a, 0x8c040d1a, 0x04020005, 0x0201f800,
-	0x00020831, 0x0201f000, 0x000208b4, 0x0201f800,
-	0x0010a3b6, 0x040007fa, 0x1c01f000, 0x0201f800,
-	0x001068c1, 0x59325808, 0x59326809, 0x59340200,
-	0x8c00050e, 0x0400000e, 0x592c040a, 0x82000500,
-	0x000000c0, 0x82000580, 0x00000080, 0x04000005,
-	0x592c000f, 0x59301815, 0x800c1c80, 0x480e6015,
-	0x4a026203, 0x00000002, 0x0401f00e, 0x42028000,
-	0x00000004, 0x0201f800, 0x0010a201, 0x59300206,
-	0x80000540, 0x04020004, 0x59a80038, 0x800000c2,
-	0x48026206, 0x497a6008, 0x4a026203, 0x00000007,
-	0x1c01f000, 0x4933c857, 0x0201f800, 0x00106cb4,
-	0x02020800, 0x00100615, 0x59300203, 0x82000580,
-	0x00000002, 0x04000793, 0x0201f800, 0x00100615,
-	0x4a026203, 0x00000007, 0x497a6206, 0x0201f000,
-	0x00020831, 0x4a026203, 0x00000007, 0x497a6206,
-	0x0201f000, 0x0002082c, 0x59300414, 0x8c00051c,
-	0x02020000, 0x000209b5, 0x59325808, 0x592c200f,
-	0x40080000, 0x80102480, 0x59300015, 0x80102400,
-	0x48126015, 0x0201f000, 0x000209b5, 0x8c040d0e,
-	0x0402000a, 0x4a026203, 0x00000006, 0x0401f823,
-	0x5930001f, 0x80000540, 0x02020800, 0x00100dc4,
-	0x0201f000, 0x0002082c, 0x4a026203, 0x00000002,
-	0x1c01f000, 0x42000800, 0x00000001, 0x0201f800,
-	0x00100dc4, 0x82040580, 0x00000001, 0x02000000,
-	0x000209bc, 0x0401f7d8, 0x59300414, 0x8c00051c,
-	0x04000006, 0x0201f800, 0x00100bad, 0x02000000,
-	0x000209ae, 0x1c01f000, 0x59300011, 0x80000540,
-	0x04020005, 0x0201f800, 0x00100bad, 0x02000000,
-	0x000209ae, 0x1c01f000, 0x492fc857, 0x480bc857,
-	0x8c08153e, 0x04000006, 0x80081080, 0x80081000,
-	0x42000800, 0x00000009, 0x0401f003, 0x42000800,
-	0x00000015, 0x480a580b, 0x1c01f000, 0x83380580,
-	0x00000013, 0x04000005, 0x83380580, 0x00000014,
-	0x02020800, 0x00100615, 0x59300414, 0x8c000516,
-	0x02000800, 0x00100615, 0x1c01f000, 0x0201f800,
-	0x00100615, 0x59300008, 0x80000540, 0x02020800,
-	0x00100615, 0x1c01f000, 0x59300414, 0x8c000516,
-	0x02000800, 0x00100615, 0x1c01f000, 0x4a026203,
-	0x00000004, 0x493a6403, 0x42000800, 0x80002001,
-	0x0201f000, 0x00020855, 0x4a026203, 0x00000003,
-	0x493a6403, 0x0201f800, 0x000200ca, 0x59325808,
-	0x592c040a, 0x8c00051e, 0x04000012, 0x82000500,
-	0x000000c0, 0x82000580, 0x00000080, 0x04000011,
-	0x59300414, 0x8c000512, 0x0402000a, 0x8c000510,
-	0x04020008, 0x592c040c, 0x80000540, 0x04020005,
-	0x82080d40, 0x80003065, 0x0201f000, 0x00106466,
-	0x82080d40, 0x80002065, 0x0201f000, 0x00106466,
-	0x82080d40, 0x80002042, 0x0201f000, 0x00106466,
-	0x4933c857, 0x493bc857, 0x83380480, 0x00000044,
-	0x02021800, 0x00100615, 0x83380480, 0x00000041,
-	0x02001800, 0x00100615, 0x0c01f001, 0x00109ea6,
-	0x00109eb6, 0x00109ecb, 0x59325808, 0x592c040a,
-	0x8c00051e, 0x0400001d, 0x82001d00, 0x000000c0,
-	0x820c1d80, 0x000000c0, 0x04000018, 0x4a026203,
-	0x00000001, 0x493a6403, 0x42000800, 0x80002042,
-	0x0201f000, 0x00020855, 0x59325808, 0x592c040a,
-	0x8c00051e, 0x0400000d, 0x82001d00, 0x000000c0,
-	0x820c1d80, 0x000000c0, 0x04000008, 0x4a026203,
-	0x00000001, 0x493a6403, 0x42000800, 0x80002001,
-	0x0201f000, 0x00020855, 0x497a6008, 0x497a6206,
-	0x42028000, 0x00000004, 0x0401f337, 0x59325808,
-	0x592c040a, 0x8c00051e, 0x040007f8, 0x82001d00,
-	0x000000c0, 0x820c1d80, 0x000000c0, 0x040007f3,
-	0x4a026203, 0x00000003, 0x493a6403, 0x0201f800,
-	0x000200ca, 0x82080d40, 0x80002065, 0x0201f000,
-	0x00106466, 0x4933c857, 0x493bc857, 0x83380580,
-	0x00000085, 0x04000006, 0x83380580, 0x00000088,
-	0x0400000a, 0x0201f800, 0x00100615, 0x4a026203,
-	0x00000009, 0x493a6403, 0x42000800, 0x8000004b,
-	0x0201f000, 0x00020855, 0x4d1c0000, 0x813669c0,
-	0x04000004, 0x0201f800, 0x0010a3b0, 0x04020044,
-	0x59cc1404, 0x0401f846, 0x04000018, 0x591c0406,
-	0x82000500, 0x0000001f, 0x82002580, 0x00000006,
-	0x04000007, 0x82002580, 0x00000004, 0x0400002e,
-	0x82002580, 0x00000011, 0x0402000c, 0x497a3a05,
-	0x42002000, 0x00000054, 0x0201f800, 0x001077d1,
-	0x4a026203, 0x00000007, 0x493a6403, 0x0201f800,
-	0x0010a79b, 0x0401f02c, 0x0201f800, 0x0010393e,
-	0x04000004, 0x42023800, 0xffffffff, 0x0401f7f1,
-	0x813669c0, 0x04020009, 0x59cc0001, 0x0201f800,
-	0x001059b9, 0x0402001e, 0x0201f800, 0x001043fc,
-	0x0402001b, 0x49366009, 0x4a026403, 0x00000087,
-	0x59cc1204, 0x82081580, 0x0000ffff, 0x04020003,
-	0x4a026403, 0x00000086, 0x4a026203, 0x00000001,
-	0x42000800, 0x80000040, 0x0201f800, 0x00020855,
-	0x0401f00d, 0x591c0203, 0x82000580, 0x00000007,
-	0x040207de, 0x4d300000, 0x411e6000, 0x0201f800,
-	0x00107698, 0x5c026000, 0x0401f7d8, 0x0201f800,
-	0x00107698, 0x5c023800, 0x1c01f000, 0x4933c857,
-	0x480bc857, 0x42002800, 0x0010cfc0, 0x41300000,
-	0x80140580, 0x04000017, 0x58140203, 0x82000580,
-	0x00000000, 0x04000013, 0x58140202, 0x80080580,
-	0x04020010, 0x58141c06, 0x820c0580, 0x00000005,
-	0x0400000c, 0x820c0580, 0x00000009, 0x0400001d,
-	0x59302009, 0x58140009, 0x800001c0, 0x0400000b,
-	0x801021c0, 0x04000003, 0x80100580, 0x04000010,
-	0x82142c00, 0x00000024, 0x41540000, 0x80140480,
-	0x0402100e, 0x0401f7e2, 0x5814001e, 0x801021c0,
-	0x04000005, 0x58102002, 0x82102500, 0x00ffffff,
-	0x0401f7f2, 0x5810201e, 0x0401f7f0, 0x40163800,
-	0x81300540, 0x0401f002, 0x80000580, 0x1c01f000,
-	0x58141807, 0x8c0c1d10, 0x040207ea, 0x0401f7e1,
-	0x83380580, 0x00000013, 0x0402000e, 0x59300403,
-	0x4803c857, 0x82000c80, 0x00000085, 0x02001800,
-	0x00100615, 0x82000c80, 0x00000093, 0x02021800,
-	0x00100615, 0x82000480, 0x00000085, 0x0c01f019,
-	0x83380580, 0x00000027, 0x04000005, 0x83380580,
-	0x00000014, 0x02020000, 0x001076fb, 0x493bc857,
-	0x0201f800, 0x001068f6, 0x59325808, 0x812e59c0,
-	0x02000000, 0x00107698, 0x4a025a06, 0x00000031,
-	0x4a025811, 0x00000004, 0x4a025812, 0x000000ff,
-	0x0201f800, 0x00020381, 0x0201f000, 0x00107698,
-	0x00109fa6, 0x00109fad, 0x00109fad, 0x00109fa6,
-	0x00109fa6, 0x00109fa6, 0x00109fa6, 0x00109fa6,
-	0x00109fa6, 0x00109fa6, 0x00109fa6, 0x00109fa6,
-	0x00109fa6, 0x00109fa8, 0x0201f800, 0x00100615,
-	0x59325808, 0x4a025a06, 0x00000000, 0x0201f800,
-	0x00020381, 0x0201f000, 0x000208b4, 0x4933c857,
-	0x42000000, 0x0010b672, 0x0201f800, 0x0010a86e,
-	0x0201f800, 0x0010a3fa, 0x497a6205, 0x42028000,
-	0x0000000b, 0x0401f807, 0x4a026406, 0x00000006,
-	0x4a026203, 0x00000007, 0x497a6206, 0x1c01f000,
-	0x4933c857, 0x4943c857, 0x59300406, 0x82000580,
-	0x00000007, 0x04020002, 0x1c01f000, 0x0201f800,
-	0x0010698c, 0x4df00000, 0x0201f800, 0x00108a99,
-	0x82000c80, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f001, 0x00109ff4, 0x00109ff8, 0x00109fdf,
-	0x0010a006, 0x0010a019, 0x00109fdf, 0x00109fdf,
-	0x00109fdf, 0x00109fdf, 0x00109fdf, 0x00109fdf,
-	0x00109fdf, 0x00109fdf, 0x00109fdf, 0x4d400000,
-	0x5930001f, 0x80000540, 0x04000005, 0x41400800,
-	0x0201f800, 0x00100dc4, 0x40068000, 0x4d2c0000,
-	0x59325808, 0x0201f800, 0x00108df4, 0x04020a16,
-	0x4c5c0000, 0x5930b809, 0x0201f800, 0x00107698,
-	0x485e6009, 0x5c00b800, 0x5c025800, 0x5c028000,
-	0x5c03e000, 0x02000000, 0x00106982, 0x1c01f000,
-	0x598c000d, 0x81300580, 0x04020004, 0x0201f800,
-	0x00106be2, 0x04020016, 0x0201f800, 0x00106619,
-	0x040007df, 0x0201f800, 0x001068a3, 0x04000010,
-	0x0201f800, 0x00100615, 0x0201f800, 0x00108a8a,
-	0x04020004, 0x0201f800, 0x00106bb2, 0x04020008,
-	0x0201f800, 0x001064f6, 0x040007d1, 0x0201f800,
-	0x001068a3, 0x02020800, 0x00100615, 0x59300203,
-	0x82000c80, 0x0000000e, 0x02021800, 0x00100615,
-	0x0c01f7b9, 0x0201f800, 0x00100ee4, 0x0401f7c4,
-	0x4933c857, 0x4d440000, 0x4d340000, 0x59cc0007,
-	0x0201f800, 0x001059b9, 0x02000800, 0x00020267,
-	0x0402001a, 0x59300009, 0x4c000000, 0x49366009,
-	0x42003000, 0x0000000b, 0x0201f800, 0x0010a766,
-	0x42000000, 0x0010b660, 0x0201f800, 0x0010a86e,
-	0x4d3c0000, 0x4d400000, 0x42028000, 0x00000029,
-	0x417a7800, 0x0201f800, 0x00101de2, 0x5c028000,
-	0x5c027800, 0x5c000000, 0x48026009, 0x59cc0007,
-	0x48026802, 0x80000580, 0x5c026800, 0x5c028800,
-	0x1c01f000, 0x4933c857, 0x4c040000, 0x59a80016,
-	0x82000580, 0x00000074, 0x04020040, 0x59cc0a08,
-	0x82040480, 0x00000100, 0x04001033, 0x59cc0c08,
-	0x82040500, 0x00008000, 0x04000035, 0x59a80032,
-	0x80000540, 0x04020009, 0x59301009, 0x58080212,
-	0x82000500, 0x0000ff00, 0x04000004, 0x82040500,
-	0x00000800, 0x0400002a, 0x59cc0c09, 0x80040840,
-	0x04001024, 0x59a80826, 0x8c040d06, 0x04000004,
-	0x59cc0c0f, 0x8c040d1e, 0x04020012, 0x59cc0a17,
-	0x800409c0, 0x04020012, 0x59cc0a18, 0x82040480,
-	0x00000100, 0x04001014, 0x59cc0c18, 0x800409c0,
-	0x0402000e, 0x59cc0c19, 0x80040840, 0x04001011,
-	0x59cc0c1a, 0x80040840, 0x04001011, 0x0401f018,
-	0x4a02621a, 0x00000100, 0x0401f012, 0x4a02621a,
-	0x00000300, 0x0401f00f, 0x4a02621a, 0x00000500,
-	0x0401f00c, 0x4a02621a, 0x00000700, 0x0401f009,
-	0x4a02621a, 0x00000900, 0x0401f006, 0x4a02621a,
-	0x00000f00, 0x0401f003, 0x4a02621a, 0x00002d00,
-	0x82000540, 0x00000001, 0x0401f002, 0x80000580,
-	0x5c000800, 0x1c01f000, 0x59cc0407, 0x4803c857,
-	0x82000580, 0x00000800, 0x04000003, 0x4a02621a,
-	0x00000000, 0x1c01f000, 0x4933c857, 0x4c580000,
-	0x59cc000c, 0x59340802, 0x82040d00, 0x00ffffff,
-	0x80040580, 0x04020012, 0x83cc1400, 0x00000008,
-	0x4200b000, 0x00000002, 0x83341c00, 0x00000006,
-	0x0201f800, 0x001082ff, 0x04020009, 0x83cc1400,
-	0x0000000a, 0x4200b000, 0x00000002, 0x83341c00,
-	0x00000008, 0x0201f800, 0x001082ff, 0x5c00b000,
-	0x1c01f000, 0x4933c857, 0x4c580000, 0x83cc1400,
-	0x0000000b, 0x4200b000, 0x00000002, 0x83341c00,
-	0x00000006, 0x0201f800, 0x001082ff, 0x0402000c,
-	0x83cc1400, 0x0000000d, 0x4200b000, 0x00000002,
-	0x83341c00, 0x00000008, 0x0201f800, 0x001082ff,
-	0x04000014, 0x4933c856, 0x4933c856, 0x4933c857,
-	0x59340009, 0x4803c857, 0x5934000e, 0x4803c857,
-	0x59340008, 0x4803c857, 0x5934000d, 0x4803c857,
-	0x59340007, 0x4803c857, 0x5934000c, 0x4803c857,
-	0x59340006, 0x4803c857, 0x5934000b, 0x4803c857,
-	0x5c00b000, 0x1c01f000, 0x4933c857, 0x4947c857,
-	0x4943c857, 0x4c600000, 0x0201f800, 0x0010698c,
-	0x4df00000, 0x4d2c0000, 0x4d300000, 0x4d340000,
-	0x0401f8d8, 0x4130c000, 0x42026000, 0x0010cfc0,
-	0x59a8000e, 0x8060c1c0, 0x04000005, 0x82601580,
-	0x0010bbe8, 0x04000002, 0x80000040, 0x81640480,
-	0x040210c4, 0x40600000, 0x81300580, 0x040000bc,
-	0x0401f9bc, 0x040200ba, 0x59326809, 0x59300406,
-	0x82000c80, 0x00000012, 0x02021800, 0x00100615,
-	0x0c01f001, 0x0010a1af, 0x0010a118, 0x0010a133,
-	0x0010a13e, 0x0010a111, 0x0010a12c, 0x0010a169,
-	0x0010a1af, 0x0010a10f, 0x0010a17c, 0x0010a190,
-	0x0010a10f, 0x0010a10f, 0x0010a10f, 0x0010a10f,
-	0x0010a1af, 0x0010a1a6, 0x0010a19e, 0x0201f800,
-	0x00100615, 0x8d3e7d18, 0x04000003, 0x8d3e7d16,
-	0x04000004, 0x59300420, 0x8c000500, 0x04020098,
-	0x59300403, 0x82000580, 0x00000043, 0x04000094,
-	0x0201f800, 0x00108ef1, 0x04000007, 0x0201f800,
-	0x00108f05, 0x0402008c, 0x0201f800, 0x00107da6,
-	0x0401f089, 0x0201f800, 0x00101e1b, 0x0201f800,
-	0x00108f05, 0x02000800, 0x00107da6, 0x0401f082,
-	0x8d3e7d18, 0x04000003, 0x8d3e7d16, 0x04000004,
-	0x59300420, 0x8c000500, 0x0402007d, 0x59325808,
-	0x0201f800, 0x00108df4, 0x04000077, 0x49425a06,
-	0x497a5c09, 0x0201f800, 0x00020381, 0x0201f800,
-	0x00108ee7, 0x0401f070, 0x8d3e7d00, 0x04000007,
-	0x59300017, 0x81480580, 0x0402006d, 0x59300018,
-	0x814c0580, 0x0402006a, 0x59300203, 0x82000580,
-	0x00000004, 0x02000800, 0x00100ee4, 0x59325808,
-	0x0201f800, 0x00108df4, 0x0400005f, 0x4a025a04,
-	0x00000103, 0x59300004, 0x8400055c, 0x48026004,
-	0x592c0408, 0x8c000512, 0x04000007, 0x4d2c0000,
-	0x592c0009, 0x40025800, 0x0201f800, 0x00100843,
-	0x5c025800, 0x49425a06, 0x497a5c09, 0x0401fb4f,
-	0x0201f800, 0x00109365, 0x0201f800, 0x00108f7d,
-	0x0201f800, 0x00020381, 0x0201f800, 0x00108ee7,
-	0x0401f045, 0x8d3e7d18, 0x04000045, 0x59300203,
-	0x82000580, 0x00000004, 0x02000800, 0x00100ee4,
-	0x59325808, 0x0201f800, 0x00108df4, 0x0400003a,
-	0x49425a06, 0x497a5c09, 0x0401fb38, 0x0201f800,
-	0x00109365, 0x0201f800, 0x00020381, 0x0401f032,
-	0x0201f800, 0x0010600e, 0x04000031, 0x59300203,
-	0x82000580, 0x00000004, 0x0400002d, 0x59300203,
-	0x82000580, 0x00000003, 0x04020029, 0x0201f800,
-	0x001068c1, 0x59325808, 0x0201f800, 0x00108df4,
-	0x04000021, 0x0201f800, 0x00020381, 0x0401f01e,
-	0x59300203, 0x82000580, 0x00000004, 0x02000800,
-	0x00100ee4, 0x59325808, 0x0201f800, 0x00108df4,
-	0x04000015, 0x49425a06, 0x497a5c09, 0x0201f800,
-	0x00020381, 0x0401f010, 0x833c0500, 0x00001800,
-	0x0400000f, 0x8d3e7d16, 0x0402000d, 0x59325817,
-	0x0201f800, 0x00100843, 0x59325808, 0x0201f800,
-	0x00108df4, 0x04000004, 0x49425a06, 0x0201f800,
-	0x00020381, 0x0201f800, 0x00107698, 0x83326400,
-	0x00000024, 0x41580000, 0x81300480, 0x04001735,
-	0x5c026800, 0x5c026000, 0x5c025800, 0x5c03e000,
-	0x02000800, 0x00106982, 0x5c00c000, 0x1c01f000,
-	0x4933c857, 0x813261c0, 0x0400002d, 0x83300d80,
-	0x0010bbe8, 0x0400002a, 0x8d3e7d06, 0x04020028,
-	0x59300c06, 0x82040580, 0x00000001, 0x0400000a,
-	0x82040580, 0x00000002, 0x04020021, 0x5930021d,
-	0x82000580, 0x00000001, 0x0402001d, 0x59300c16,
-	0x0401f002, 0x59300c03, 0x82040580, 0x00000039,
-	0x04000004, 0x82040580, 0x00000035, 0x04020014,
-	0x4d300000, 0x4d1c0000, 0x5932601e, 0x4933c857,
-	0x0201f800, 0x001091e3, 0x02000800, 0x00100615,
-	0x591c001c, 0x497a381c, 0x591c0c14, 0x84040d02,
-	0x48063c14, 0x5c023800, 0x5c026000, 0x81300580,
-	0x02020800, 0x00100615, 0x497a601e, 0x1c01f000,
-	0x5c000000, 0x4c000000, 0x4803c857, 0x4d3c0000,
-	0x42027800, 0x00000001, 0x0201f800, 0x001043bd,
-	0x5c027800, 0x4c580000, 0x4200b000, 0x00000002,
-	0x83a81c00, 0x00000002, 0x83cc1400, 0x0000000b,
-	0x0201f800, 0x001082ff, 0x5c00b000, 0x80000540,
-	0x1c01f000, 0x492fc857, 0x4943c857, 0x59a8000c,
-	0x812c0480, 0x04001011, 0x59a8000d, 0x812c0480,
-	0x0402100e, 0x592c0000, 0x80005d40, 0x04000008,
-	0x497a5800, 0x49425a06, 0x4c2c0000, 0x0201f800,
-	0x00020381, 0x5c025800, 0x0401f7f7, 0x49425a06,
-	0x0201f000, 0x00020381, 0x1c01f000, 0x493fc857,
-	0x4933c857, 0x480bc857, 0x0201f800, 0x0010393e,
-	0x0400002e, 0x41502800, 0x813e79c0, 0x04020006,
-	0x59a80066, 0x80000000, 0x59a8086a, 0x80040580,
-	0x04000026, 0x41300000, 0x80140580, 0x0400001a,
-	0x58140203, 0x82000580, 0x00000000, 0x04000016,
-	0x58140202, 0x80080580, 0x04020013, 0x58141c06,
-	0x820c0580, 0x00000005, 0x0400000f, 0x820c0580,
-	0x00000009, 0x04000017, 0x59300009, 0x58142009,
-	0x801021c0, 0x04020006, 0x5814201e, 0x59301809,
-	0x580c0002, 0x82000500, 0x00ffffff, 0x80100580,
-	0x04000007, 0x82142c00, 0x00000024, 0x41540000,
-	0x80140480, 0x04021005, 0x0401f7df, 0x40163800,
-	0x81300540, 0x0401f002, 0x80000580, 0x1c01f000,
-	0x58141807, 0x8c0c1d10, 0x040207f3, 0x0401f7e7,
-	0x42002000, 0x0000ffff, 0x59301009, 0x800811c0,
-	0x04000002, 0x58082403, 0x41301000, 0x0401f007,
-	0x41781000, 0x41442000, 0x0401f004, 0x41781000,
-	0x42002000, 0x0000ffff, 0x5c000000, 0x4c000000,
-	0x4803c857, 0x480bc857, 0x4813c857, 0x492fc857,
-	0x4943c857, 0x4d2c0000, 0x4c080000, 0x4c100000,
-	0x4c140000, 0x4c180000, 0x0201f800, 0x0010082a,
-	0x02000800, 0x00100615, 0x5c003000, 0x5c002800,
-	0x5c002000, 0x5c001000, 0x4a025a04, 0x0000010d,
-	0x800811c0, 0x04000017, 0x83400580, 0x00000029,
-	0x04020010, 0x82180580, 0x00000002, 0x0400000a,
-	0x82180580, 0x00000003, 0x04000007, 0x82180580,
-	0x00000008, 0x04000004, 0x82180580, 0x00000009,
-	0x04020004, 0x4a025809, 0xffffffff, 0x0401f002,
-	0x480a5809, 0x58080202, 0x48025c13, 0x0401f005,
-	0x4a025809, 0xffffffff, 0x4a025c13, 0x0000ffff,
-	0x49425a08, 0x48125a06, 0x82100580, 0x0000ffff,
-	0x04000012, 0x4c140000, 0x4c180000, 0x4d440000,
-	0x4d340000, 0x40128800, 0x0201f800, 0x00020267,
-	0x02020800, 0x00100615, 0x59340002, 0x82000500,
-	0x00ffffff, 0x48025812, 0x5c026800, 0x5c028800,
-	0x5c003000, 0x5c002800, 0x497a5800, 0x497a5c04,
-	0x83400580, 0x00000046, 0x04020002, 0x48165a07,
-	0x481a5c08, 0x0401fbe0, 0x5c025800, 0x1c01f000,
-	0x59300809, 0x800409c0, 0x04000004, 0x58040403,
-	0x81440580, 0x1c01f000, 0x82000540, 0x00000001,
-	0x0401f7fd, 0x4933c857, 0x4c040000, 0x59300403,
-	0x82000d80, 0x0000001e, 0x04020016, 0x800000d0,
-	0x59300a16, 0x82040d00, 0x000000ff, 0x80040540,
-	0x4803c857, 0x48026416, 0x4a026403, 0x00000085,
-	0x4a026203, 0x00000009, 0x4a026406, 0x00000005,
-	0x4a02621d, 0x00000004, 0x59a80038, 0x48026206,
-	0x42000800, 0x8000004b, 0x0201f800, 0x00020855,
-	0x5c000800, 0x1c01f000, 0x4933c857, 0x40000000,
-	0x40000000, 0x1c01f000, 0x59300414, 0x4933c857,
-	0x4803c857, 0x8c000518, 0x04000009, 0x8c000512,
-	0x02020000, 0x00108fdb, 0x0401f918, 0x0201f800,
-	0x00020831, 0x0201f800, 0x000208b4, 0x1c01f000,
-	0x591c0406, 0x4803c857, 0x82000c80, 0x00000009,
-	0x0402100b, 0x0c01f001, 0x0010a2f7, 0x0010a2f7,
-	0x0010a2f7, 0x0010a2f9, 0x0010a2f7, 0x0010a2f9,
-	0x0010a2f9, 0x0010a2f7, 0x0010a2f9, 0x80000580,
-	0x1c01f000, 0x82000540, 0x00000001, 0x1c01f000,
-	0x591c0406, 0x82000500, 0x0000001f, 0x82000580,
-	0x00000006, 0x0400000e, 0x4803c857, 0x4a026403,
-	0x0000003b, 0x4a02641a, 0x00000009, 0x4a02621a,
-	0x00002a00, 0x4a026203, 0x00000001, 0x42000800,
-	0x80000040, 0x0201f000, 0x00020855, 0x4803c856,
-	0x4c040000, 0x4c140000, 0x4d300000, 0x411e6000,
-	0x0401f8e6, 0x497a6205, 0x59300414, 0x4803c857,
-	0x82000500, 0xffffadff, 0x48026414, 0x497a6405,
-	0x5c026000, 0x0201f800, 0x0010082a, 0x02000800,
-	0x00100615, 0x5c002800, 0x5c000800, 0x4a025a04,
-	0x0000010d, 0x497a5800, 0x497a5c04, 0x4a025a08,
-	0x00000045, 0x491e5809, 0x59300402, 0x48025c07,
-	0x59300419, 0x48025c0b, 0x591c0414, 0x84000556,
-	0x48023c14, 0x591c1809, 0x580c0403, 0x48025a06,
-	0x4816580a, 0x48065a0b, 0x0401fb57, 0x4d400000,
-	0x42028000, 0x00000045, 0x591c0202, 0x4c000000,
-	0x4d300000, 0x411e6000, 0x0401fc82, 0x5c026000,
-	0x5c000000, 0x48023a02, 0x5c028000, 0x4a023c06,
-	0x00000006, 0x4a023a03, 0x00000007, 0x497a3a06,
-	0x497a3a05, 0x1c01f000, 0x4933c857, 0x83380580,
-	0x00000013, 0x0402000b, 0x59300403, 0x4803c857,
-	0x82000d80, 0x00000085, 0x0400002b, 0x82000d80,
-	0x0000008b, 0x04000028, 0x0201f800, 0x00100615,
-	0x83380580, 0x00000027, 0x0402000c, 0x0201f800,
-	0x001068f6, 0x4d2c0000, 0x4d400000, 0x59325808,
-	0x42028000, 0x00000004, 0x0401fe9f, 0x5c028000,
-	0x5c025800, 0x1c01f000, 0x83380580, 0x00000014,
-	0x040007f3, 0x83380580, 0x00000089, 0x04000005,
-	0x83380580, 0x0000008a, 0x02020000, 0x001076fb,
-	0x0201f800, 0x00106cb4, 0x02020000, 0x001076fb,
-	0x59300a03, 0x82040580, 0x0000000a, 0x04000009,
-	0x82040580, 0x0000000c, 0x04000006, 0x0201f800,
-	0x00100615, 0x4a026203, 0x0000000a, 0x1c01f000,
-	0x83380480, 0x00000093, 0x0402100c, 0x83380480,
-	0x00000085, 0x04001009, 0x83380580, 0x00000089,
-	0x0400000a, 0x83380580, 0x0000008a, 0x04000022,
-	0x0201f800, 0x00100615, 0x493bc857, 0x4933c857,
-	0x0201f000, 0x001076fb, 0x4933c857, 0x4c340000,
-	0x41306800, 0x0201f800, 0x00020892, 0x04000011,
-	0x4a026203, 0x00000001, 0x4a026403, 0x0000001e,
-	0x59cc0c07, 0x48066419, 0x59cc0a07, 0x48066219,
-	0x58340809, 0x48066009, 0x4a026406, 0x00000004,
-	0x42000800, 0x80000040, 0x0201f800, 0x00020855,
-	0x40366000, 0x0201f800, 0x000208b4, 0x5c006800,
-	0x1c01f000, 0x4933c857, 0x0201f000, 0x000208b4,
-	0x59300809, 0x58040200, 0x8c00051a, 0x02020800,
-	0x001006ba, 0x1c01f000, 0x0201f800, 0x0010472e,
-	0x0400001e, 0x4a026203, 0x00000002, 0x59300414,
-	0x84000558, 0x48026414, 0x8c000512, 0x04000004,
-	0x59a80039, 0x48026205, 0x0401f007, 0x59a80839,
-	0x59a80037, 0x80040400, 0x82000400, 0x0000001e,
-	0x48026205, 0x59300009, 0x82000c00, 0x00000011,
-	0x50040000, 0x80000540, 0x04000004, 0x82000c00,
-	0x00000000, 0x0401f7fb, 0x45300800, 0x497a6000,
-	0x82000540, 0x00000001, 0x1c01f000, 0x82100500,
-	0xfffffeef, 0x0402001c, 0x4d2c0000, 0x4937c857,
-	0x59340811, 0x83341400, 0x00000011, 0x800409c0,
-	0x0400000e, 0x40040000, 0x81300580, 0x04000005,
-	0x58040800, 0x82041400, 0x00000000, 0x0401f7f8,
-	0x59300800, 0x497a6000, 0x44041000, 0x0201f800,
-	0x00020831, 0x0401f002, 0x4933c857, 0x5c025800,
-	0x492e6008, 0x0201f800, 0x00020831, 0x0201f000,
-	0x000208b4, 0x492fc857, 0x4a025a06, 0x00000006,
-	0x0201f000, 0x00020381, 0x4c340000, 0x59300009,
-	0x800001c0, 0x04000010, 0x82006c00, 0x00000011,
-	0x50340000, 0x80000540, 0x04000009, 0x81300580,
-	0x04000005, 0x50340000, 0x82006c00, 0x00000000,
-	0x0401f7f8, 0x59300000, 0x44006800, 0x5c006800,
-	0x1c01f000, 0x59300c06, 0x82040580, 0x00000005,
-	0x040007fb, 0x82040580, 0x00000011, 0x040007f8,
-	0x82040580, 0x00000006, 0x040007f5, 0x82040580,
-	0x00000001, 0x040007f2, 0x0201f800, 0x00100615,
-	0x4933c857, 0x4c080000, 0x4c0c0000, 0x4c580000,
-	0x59a8101d, 0x59cc1807, 0x820c1d00, 0x00ffffff,
-	0x800c0110, 0x80083580, 0x04020014, 0x83cc1400,
-	0x00000008, 0x4200b000, 0x00000002, 0x59300009,
-	0x82001c00, 0x00000006, 0x0201f800, 0x001082ff,
-	0x0402000a, 0x83cc1400, 0x0000000a, 0x4200b000,
-	0x00000002, 0x59300009, 0x82001c00, 0x00000008,
-	0x0201f800, 0x001082ff, 0x5c00b000, 0x5c001800,
-	0x5c001000, 0x1c01f000, 0x4933c856, 0x0201f800,
-	0x0010404b, 0x0201f000, 0x00101bf0, 0x493bc857,
-	0x4d2c0000, 0x0201f800, 0x0010082a, 0x02000800,
-	0x00100615, 0x832cac00, 0x00000005, 0x4c580000,
-	0x4c540000, 0x4200b000, 0x00000006, 0x4578a800,
-	0x8054a800, 0x8058b040, 0x040207fd, 0x83380580,
-	0x00000046, 0x04020004, 0x4a025a04, 0x00000144,
-	0x0401f008, 0x4a025a04, 0x00000146, 0x83380580,
-	0x00000041, 0x04000003, 0x4a025a06, 0x00000001,
-	0x59cc0007, 0x82000500, 0xff000000, 0x80000110,
-	0x59cc1008, 0x82081500, 0xff000000, 0x80081540,
-	0x480a580a, 0x83380580, 0x00000046, 0x04020006,
-	0x59cc0007, 0x82000500, 0x00ffffff, 0x4802580b,
-	0x0401f005, 0x59cc0008, 0x82000500, 0x00ffffff,
-	0x4802580b, 0x83380580, 0x00000046, 0x04020004,
-	0x83cc1400, 0x00000009, 0x0401f003, 0x83cc1400,
-	0x0000000d, 0x50080000, 0x9c0001c0, 0x4802580c,
-	0x80081000, 0x50080000, 0x9c0001c0, 0x4802580d,
-	0x83380580, 0x00000046, 0x04020008, 0x59cc000b,
-	0x9c0001c0, 0x4802580e, 0x59cc000c, 0x9c0001c0,
-	0x4802580f, 0x0401f007, 0x59cc000f, 0x9c0001c0,
-	0x4802580e, 0x59cc0010, 0x9c0001c0, 0x4802580f,
-	0x83380580, 0x00000046, 0x04020004, 0x83cc1400,
-	0x00000011, 0x0401f003, 0x83cc1400, 0x00000015,
-	0x412c3000, 0x82183400, 0x00000010, 0x4200b000,
-	0x00000004, 0x50080000, 0x9c0001c0, 0x44003000,
-	0x80081000, 0x80183000, 0x8058b040, 0x040207fa,
-	0x5c00a800, 0x5c00b000, 0x0201f800, 0x00020381,
-	0x5c025800, 0x1c01f000, 0x4933c857, 0x492fc857,
-	0x59300809, 0x58040200, 0x8c00051e, 0x04000004,
-	0x592c0208, 0x84000558, 0x48025a08, 0x1c01f000,
-	0x59e0180f, 0x599c0413, 0x800c1000, 0x80080580,
-	0x04020002, 0x41781000, 0x59e00010, 0x59e00810,
-	0x80040d80, 0x040207fd, 0x80080580, 0x0400000b,
-	0x4c080000, 0x599c0814, 0x599c1015, 0x800c00cc,
-	0x80040c00, 0x82081440, 0x00000000, 0x5c001800,
-	0x82000540, 0x00000001, 0x4803c857, 0x1c01f000,
-	0x59300203, 0x4933c857, 0x4937c857, 0x493bc857,
-	0x4803c857, 0x82003480, 0x0000000e, 0x02021800,
-	0x00100615, 0x0c01f001, 0x0010a4e8, 0x0010a63a,
-	0x0010a4e8, 0x0010a4e8, 0x0010a4e8, 0x0010a4e8,
-	0x0010a4e8, 0x0010a59f, 0x0010a4ea, 0x0010a4e8,
-	0x0010a4e8, 0x0010a4e8, 0x0010a4e8, 0x0010a4e8,
-	0x0201f800, 0x00100615, 0x83380580, 0x0000004c,
-	0x02020800, 0x00100615, 0x0201f800, 0x0010473b,
-	0x04020020, 0x59a80826, 0x82040500, 0x00000009,
-	0x82000580, 0x00000008, 0x0400001a, 0x8c040d12,
-	0x0400003d, 0x59cc0806, 0x82040d00, 0xff000000,
-	0x82040580, 0x03000000, 0x0400001f, 0x82040580,
-	0x50000000, 0x04000005, 0x82040580, 0x52000000,
-	0x02020000, 0x000208b4, 0x813669c0, 0x04000006,
-	0x4d3c0000, 0x417a7800, 0x0201f800, 0x00101de2,
-	0x5c027800, 0x4a026403, 0x00000001, 0x0401f014,
-	0x59cc0806, 0x82040d00, 0xff000000, 0x82040580,
-	0x03000000, 0x04000008, 0x82040580, 0x50000000,
-	0x04000005, 0x82040580, 0x52000000, 0x02020000,
-	0x000208b4, 0x4a026403, 0x00000009, 0x4a02641a,
-	0x00000009, 0x4a02621a, 0x00000000, 0x813669c0,
-	0x0402000b, 0x59cc0001, 0x0201f800, 0x001059b9,
-	0x02020000, 0x000208b4, 0x0201f800, 0x001043fc,
-	0x02020000, 0x000208b4, 0x49366009, 0x4a026406,
-	0x00000004, 0x4a026203, 0x00000001, 0x0201f000,
-	0x00106470, 0x0201f800, 0x0010393e, 0x04000023,
-	0x59cc0806, 0x4807c857, 0x82040d00, 0xff000000,
-	0x82040580, 0x03000000, 0x04000033, 0x82040580,
-	0x20000000, 0x04000041, 0x82040580, 0x21000000,
-	0x04000052, 0x82040580, 0x24000000, 0x0400004f,
-	0x82040580, 0x50000000, 0x0400004c, 0x82040580,
-	0x52000000, 0x04000049, 0x82040580, 0x05000000,
-	0x0402000d, 0x59cc0806, 0x82040d00, 0xff000000,
-	0x9c0431c0, 0x42028000, 0x00000046, 0x42002800,
-	0x00000001, 0x0401fcf7, 0x0401f940, 0x02000800,
-	0x00100615, 0x42002000, 0x00000051, 0x0201f800,
-	0x001077d1, 0x59cc0000, 0x82000500, 0x00ffffff,
-	0x82000580, 0x00ffffff, 0x04000005, 0x4a026203,
-	0x00000007, 0x493a6403, 0x1c01f000, 0x59325817,
-	0x812e59c0, 0x02020800, 0x00100843, 0x0201f000,
-	0x000208b4, 0x813669c0, 0x040007df, 0x59340400,
-	0x82000500, 0x000000ff, 0x82000580, 0x00000003,
-	0x040207d9, 0x0401fc73, 0x040207d7, 0x4a026403,
-	0x00000009, 0x4a02641a, 0x0000000e, 0x4a02621a,
-	0x00001900, 0x0401f7a2, 0x813669c0, 0x0400000c,
-	0x59340c00, 0x82040500, 0x000000ff, 0x82000580,
-	0x00000009, 0x04000794, 0x82040500, 0x0000ff00,
-	0x82000580, 0x00000700, 0x040207c3, 0x4a026403,
-	0x00000009, 0x4a02641a, 0x00000009, 0x4a02621a,
-	0x00001e00, 0x0401f78e, 0x813669c0, 0x040007f8,
-	0x59340c00, 0x82040500, 0x0000ff00, 0x82000580,
-	0x00000700, 0x040007f2, 0x0401f7b3, 0x4d2c0000,
-	0x4c580000, 0x4c500000, 0x4c540000, 0x41385000,
-	0x83380580, 0x00000054, 0x02020800, 0x00100615,
-	0x59325808, 0x592c0c0b, 0x82040d00, 0x0000e000,
-	0x82040580, 0x00002000, 0x04020076, 0x59300817,
-	0x800409c0, 0x04000014, 0x58041404, 0x41cca800,
-	0x8204a400, 0x00000005, 0x82080480, 0x00000010,
-	0x04021004, 0x4008b000, 0x0401fb84, 0x0401f00a,
-	0x40001000, 0x4200b000, 0x0000000f, 0x0401fb7f,
-	0x58040801, 0x800409c0, 0x040207f2, 0x0201f800,
-	0x00100615, 0x813669c0, 0x0400005e, 0x59344c00,
-	0x592c0c09, 0x4807c857, 0x4827c857, 0x82040d00,
-	0x000000ff, 0x82040580, 0x00000003, 0x0400002a,
-	0x82040580, 0x00000005, 0x04000032, 0x82040580,
-	0x00000020, 0x04000036, 0x82040580, 0x00000052,
-	0x04000042, 0x82040580, 0x00000050, 0x04000042,
-	0x82040580, 0x00000021, 0x04000004, 0x82040580,
-	0x00000024, 0x04020043, 0x82240500, 0x0000ff00,
-	0x82000580, 0x00000007, 0x04000008, 0x42000800,
-	0x00000009, 0x0201f800, 0x001043c7, 0x42005000,
-	0x0000000c, 0x0401f037, 0x4a025a06, 0x00000031,
-	0x4a02580d, 0x00000009, 0x59340400, 0x4802580e,
-	0x0201f800, 0x00020381, 0x0201f800, 0x00107698,
-	0x0401f03d, 0x0201f800, 0x001040e4, 0x0201f800,
-	0x00104480, 0x42000800, 0x00000003, 0x0201f800,
-	0x001043c7, 0x42005000, 0x00000008, 0x0401f021,
-	0x59cc0007, 0x0201f800, 0x00105c25, 0x0402001d,
-	0x0201f800, 0x001040e4, 0x0401f01a, 0x82240500,
-	0x0000ff00, 0x82000580, 0x00000007, 0x040007df,
-	0x82240500, 0x000000ff, 0x82000580, 0x00000009,
-	0x040007da, 0x0201f800, 0x001044e1, 0x42005000,
-	0x0000000a, 0x0401f00b, 0x42005000, 0x0000000e,
-	0x0401f003, 0x42005000, 0x00000010, 0x82240500,
-	0x0000ff00, 0x82000580, 0x00000007, 0x040007cb,
-	0x482a6403, 0x4a026203, 0x00000001, 0x592c000d,
-	0x48026011, 0x497a6013, 0x59a80038, 0x48026206,
-	0x417a7800, 0x0201f800, 0x00106470, 0x59325817,
-	0x812e59c0, 0x04000004, 0x0201f800, 0x00100843,
-	0x497a6017, 0x5c00a800, 0x5c00a000, 0x5c00b000,
-	0x5c025800, 0x1c01f000, 0x4d2c0000, 0x59325808,
-	0x83380580, 0x00000013, 0x0402002a, 0x492fc857,
-	0x59300c03, 0x82040580, 0x00000054, 0x0400001e,
-	0x82040580, 0x00000010, 0x04000018, 0x82040580,
-	0x0000000e, 0x04000015, 0x82040580, 0x00000008,
-	0x0400000d, 0x82040580, 0x0000000c, 0x0400000a,
-	0x82040580, 0x0000000a, 0x02020800, 0x00100615,
-	0x42000800, 0x00000006, 0x0201f800, 0x001043c7,
-	0x0401f009, 0x42000800, 0x00000004, 0x0201f800,
-	0x001043c7, 0x0401f004, 0x59340200, 0x8400051a,
-	0x48026a00, 0x4a025a06, 0x00000000, 0x0201f800,
-	0x00020381, 0x0201f800, 0x000208b4, 0x0401f024,
-	0x83380580, 0x00000027, 0x0400000f, 0x83380580,
-	0x00000014, 0x02020800, 0x00100615, 0x492fc857,
-	0x0201f800, 0x001068f6, 0x42028000, 0x00000031,
-	0x42000800, 0x00000004, 0x42001000, 0x000000ff,
-	0x0401f00a, 0x492fc857, 0x0201f800, 0x001068f6,
-	0x42028000, 0x00000031, 0x42000800, 0x00000004,
-	0x42001000, 0x00000010, 0x49425a06, 0x4806580d,
-	0x480a580e, 0x0201f800, 0x00020381, 0x0201f800,
-	0x00104a83, 0x0201f800, 0x00107698, 0x5c025800,
-	0x1c01f000, 0x492fc857, 0x42007000, 0x0010b5f6,
-	0x58380807, 0x800409c0, 0x04020005, 0x492c7008,
-	0x492c7007, 0x0201f000, 0x001008be, 0x492c0800,
-	0x492c7007, 0x1c01f000, 0x4d2c0000, 0x4c580000,
-	0x4c500000, 0x4c540000, 0x4933c857, 0x4937c857,
-	0x59cc0806, 0x4807c857, 0x82040d00, 0xff000000,
-	0x82040580, 0x03000000, 0x0400000d, 0x82040580,
-	0x05000000, 0x0400000a, 0x82040580, 0x21000000,
-	0x04000030, 0x82040580, 0x24000000, 0x0400002d,
-	0x82040580, 0x20000000, 0x0402002f, 0x0201f800,
-	0x0010082a, 0x0400002c, 0x492fc857, 0x492e6017,
-	0x59a8b016, 0x8258b400, 0x0000001b, 0x8258b500,
-	0xfffffffc, 0x8058b104, 0x485a5c04, 0x412c7800,
-	0x41cca000, 0x82580480, 0x00000010, 0x04021005,
-	0x832cac00, 0x00000005, 0x0401fa78, 0x0401f015,
-	0x40580800, 0x4200b000, 0x0000000f, 0x832cac00,
-	0x00000005, 0x0401fa71, 0x8204b480, 0x0000000f,
-	0x0201f800, 0x0010082a, 0x04000004, 0x492c7801,
-	0x412c7800, 0x0401f7ec, 0x59325817, 0x0201f800,
-	0x00100843, 0x497a6017, 0x80000580, 0x0401f006,
-	0x59340200, 0x84000554, 0x48026a00, 0x82000540,
-	0x00000001, 0x5c00a800, 0x5c00a000, 0x5c00b000,
-	0x5c025800, 0x1c01f000, 0x4933c857, 0x492fc857,
-	0x4d2c0000, 0x4c5c0000, 0x5930bc06, 0x59300a03,
-	0x82040580, 0x00000007, 0x0400003c, 0x82040580,
-	0x00000001, 0x02020800, 0x00100615, 0x0201f800,
-	0x0010698c, 0x4df00000, 0x598c000d, 0x81300580,
-	0x04020019, 0x59300004, 0x8c000520, 0x04000004,
-	0x84000520, 0x48026004, 0x0401f019, 0x825c0580,
-	0x00000011, 0x0402000d, 0x42001000, 0x0010b5f4,
-	0x50081000, 0x58080002, 0x82000580, 0x00000100,
-	0x04000006, 0x5808000c, 0x81300580, 0x02020800,
-	0x00100615, 0x0401f00a, 0x0201f800, 0x00106be2,
-	0x04020027, 0x59300004, 0x8c000520, 0x04000004,
-	0x84000520, 0x48026004, 0x0401f003, 0x0201f800,
-	0x00106619, 0x5c03e000, 0x02000800, 0x00106982,
-	0x0201f800, 0x00108df4, 0x02000800, 0x00100615,
-	0x59325808, 0x4a025a06, 0x00000005, 0x0201f800,
-	0x00020381, 0x825c0580, 0x00000005, 0x0400001b,
-	0x0201f800, 0x00104a83, 0x825c0580, 0x00000005,
-	0x04000016, 0x59325817, 0x812e59c0, 0x02020800,
-	0x00100843, 0x0201f800, 0x00107698, 0x80000580,
-	0x5c00b800, 0x5c025800, 0x1c01f000, 0x5c03e000,
-	0x02000800, 0x00106982, 0x59300c06, 0x82040580,
-	0x00000011, 0x040007ae, 0x82040580, 0x00000005,
-	0x040007ab, 0x0401f7f3, 0x0201f800, 0x000208b4,
-	0x0401f7ef, 0x4c040000, 0x59340200, 0x4803c857,
-	0x8c00051c, 0x04000009, 0x59cc0805, 0x591c0019,
-	0x4803c857, 0x80040580, 0x04000004, 0x80000580,
-	0x4803c856, 0x0401f003, 0x82000540, 0x00000001,
-	0x5c000800, 0x1c01f000, 0x4c000000, 0x4c0c0000,
-	0x4c100000, 0x42001800, 0x0000ffff, 0x42002000,
-	0x00000004, 0x0401f013, 0x4c000000, 0x4c0c0000,
-	0x4c100000, 0x59302009, 0x58101c03, 0x42002000,
-	0x00000004, 0x0401f00b, 0x4c000000, 0x4c0c0000,
-	0x4c100000, 0x59302009, 0x801021c0, 0x02000800,
-	0x00100615, 0x58101c03, 0x42002000, 0x00000007,
-	0x480fc857, 0x4813c857, 0x481bc857, 0x0201f800,
-	0x001038c7, 0x5c002000, 0x5c001800, 0x5c000000,
-	0x1c01f000, 0x83380580, 0x00000092, 0x02020800,
-	0x00100615, 0x42000800, 0x80000040, 0x4a026203,
-	0x00000001, 0x493a6403, 0x0201f000, 0x00020855,
-	0x4d400000, 0x0201f800, 0x0010393e, 0x04000008,
-	0x59a80005, 0x84000544, 0x48035005, 0x42028000,
-	0x0000002a, 0x0201f800, 0x0010a25b, 0x5c028000,
-	0x1c01f000, 0x59a80026, 0x8c000508, 0x04000005,
-	0x599c0017, 0x8c00050a, 0x04020002, 0x1c01f000,
-	0x82000540, 0x00000001, 0x1c01f000, 0x59300420,
-	0x84000540, 0x48026420, 0x1c01f000, 0x4817c857,
-	0x4c000000, 0x4c040000, 0x8c142d2a, 0x04000004,
-	0x598800b9, 0x80000000, 0x480310b9, 0x8c142d2e,
-	0x04000004, 0x598800ba, 0x80000000, 0x480310ba,
-	0x8c142d2c, 0x04000013, 0x40140000, 0x82000500,
-	0x00070000, 0x82000d80, 0x00030000, 0x0400000d,
-	0x82000d80, 0x00040000, 0x0400000a, 0x82000d80,
-	0x00050000, 0x04000007, 0x59880005, 0x80000000,
-	0x48031005, 0x598800bb, 0x80000000, 0x480310bb,
-	0x5c000800, 0x5c000000, 0x1c01f000, 0x4817c857,
-	0x4c000000, 0x4c040000, 0x8c142d2a, 0x04000004,
-	0x598800bc, 0x80000000, 0x480310bc, 0x8c142d2e,
-	0x04000004, 0x598800bd, 0x80000000, 0x480310bd,
-	0x8c142d2c, 0x04000013, 0x40140000, 0x82000500,
-	0x00070000, 0x82000d80, 0x00030000, 0x0400000d,
-	0x82000d80, 0x00040000, 0x0400000a, 0x82000d80,
-	0x00050000, 0x04000007, 0x59880005, 0x80000000,
-	0x48031005, 0x598800be, 0x80000000, 0x480310be,
-	0x5c000800, 0x5c000000, 0x1c01f000, 0x4c000000,
-	0x59880001, 0x80000000, 0x4803c857, 0x48031001,
-	0x5c000000, 0x1c01f000, 0x4c000000, 0x59880000,
-	0x80000000, 0x4803c857, 0x48031000, 0x5c000000,
-	0x1c01f000, 0x4c000000, 0x59880002, 0x80000000,
-	0x4803c857, 0x48031002, 0x5c000000, 0x1c01f000,
-	0x4807c857, 0x4c000000, 0x8c040d2c, 0x04000004,
-	0x598800a7, 0x80000000, 0x480310a7, 0x8c040d2a,
-	0x04000004, 0x598800a8, 0x80000000, 0x480310a8,
-	0x8c040d28, 0x04000004, 0x598800a9, 0x80000000,
-	0x480310a9, 0x8c040d26, 0x04000004, 0x598800aa,
-	0x80000000, 0x480310aa, 0x8c040d24, 0x04000004,
-	0x598800ab, 0x80000000, 0x480310ab, 0x8c040d22,
-	0x04000004, 0x598800ac, 0x80000000, 0x480310ac,
-	0x8c040d20, 0x04000004, 0x598800ad, 0x80000000,
-	0x480310ad, 0x5c000000, 0x1c01f000, 0x4807c857,
-	0x4c000000, 0x598800ae, 0x80000000, 0x480310ae,
-	0x5c000000, 0x1c01f000, 0x4807c857, 0x4c000000,
-	0x8c040d1c, 0x04000004, 0x598800af, 0x80000000,
-	0x480310af, 0x8c040d1a, 0x04000004, 0x598800b0,
-	0x80000000, 0x480310b0, 0x5c000000, 0x1c01f000,
-	0x4807c857, 0x4c000000, 0x8c040d18, 0x04000004,
-	0x598800b1, 0x80000000, 0x480310b1, 0x8c040d16,
-	0x04000004, 0x598800b2, 0x80000000, 0x480310b2,
-	0x8c040d14, 0x04000004, 0x598800b3, 0x80000000,
-	0x480310b3, 0x5c000000, 0x1c01f000, 0x4807c857,
-	0x4c000000, 0x8c040d10, 0x04000004, 0x598800b4,
-	0x80000000, 0x480310b4, 0x8c040d0c, 0x04000004,
-	0x598800b5, 0x80000000, 0x480310b5, 0x5c000000,
-	0x1c01f000, 0x4807c857, 0x4c000000, 0x8c040d08,
-	0x04000004, 0x598800b6, 0x80000000, 0x480310b6,
-	0x8c040d04, 0x04000004, 0x598800b7, 0x80000000,
-	0x480310b7, 0x5c000000, 0x1c01f000, 0x4807c856,
-	0x4c000000, 0x59880080, 0x80000000, 0x48031080,
-	0x5c000000, 0x1c01f000, 0x4803c857, 0x4c040000,
-	0x50000800, 0x80040800, 0x4807c857, 0x44040000,
-	0x5c000800, 0x1c01f000, 0x480fc857, 0x4c000000,
-	0x820c0580, 0x00000000, 0x04020004, 0x42000000,
-	0x0010b617, 0x0401f014, 0x820c0580, 0x00001001,
-	0x04020004, 0x42000000, 0x0010b618, 0x0401f00e,
-	0x820c0580, 0x00001002, 0x04020004, 0x42000000,
-	0x0010b619, 0x0401f008, 0x820c0c80, 0x0000201c,
-	0x02021800, 0x00100615, 0x820c0500, 0x0000001f,
-	0x0c01f804, 0x0401ffdd, 0x5c000000, 0x1c01f000,
-	0x0010a8b0, 0x0010a8b3, 0x0010a8b6, 0x0010a8b9,
-	0x0010a8bc, 0x0010a8bf, 0x0010a8c2, 0x0010a8c5,
-	0x0010a8c8, 0x0010a8cb, 0x0010a8ce, 0x0010a8d1,
-	0x0010a8d4, 0x0010a8d7, 0x0010a8da, 0x0010a8dd,
-	0x0010a8e0, 0x0010a8e3, 0x0010a8e6, 0x0010a8e9,
-	0x0010a8ec, 0x0010a8ef, 0x0010a8f2, 0x0010a8f5,
-	0x0010a8f8, 0x0010a8fb, 0x0010a8fe, 0x0010a901,
-	0x42000000, 0x0010b61a, 0x1c01f000, 0x42000000,
-	0x0010b61b, 0x1c01f000, 0x42000000, 0x0010b61c,
-	0x1c01f000, 0x42000000, 0x0010b61d, 0x1c01f000,
-	0x42000000, 0x0010b61e, 0x1c01f000, 0x42000000,
-	0x0010b61f, 0x1c01f000, 0x42000000, 0x0010b620,
-	0x1c01f000, 0x42000000, 0x0010b621, 0x1c01f000,
-	0x42000000, 0x0010b622, 0x1c01f000, 0x42000000,
-	0x0010b623, 0x1c01f000, 0x42000000, 0x0010b624,
-	0x1c01f000, 0x42000000, 0x0010b625, 0x1c01f000,
-	0x42000000, 0x0010b626, 0x1c01f000, 0x42000000,
-	0x0010b627, 0x1c01f000, 0x42000000, 0x0010b628,
-	0x1c01f000, 0x42000000, 0x0010b629, 0x1c01f000,
-	0x42000000, 0x0010b62a, 0x1c01f000, 0x42000000,
-	0x0010b62b, 0x1c01f000, 0x42000000, 0x0010b62c,
-	0x1c01f000, 0x42000000, 0x0010b62d, 0x1c01f000,
-	0x42000000, 0x0010b62e, 0x1c01f000, 0x42000000,
-	0x0010b62f, 0x1c01f000, 0x42000000, 0x0010b630,
-	0x1c01f000, 0x42000000, 0x0010b631, 0x1c01f000,
-	0x42000000, 0x0010b632, 0x1c01f000, 0x42000000,
-	0x0010b633, 0x1c01f000, 0x42000000, 0x0010b634,
-	0x1c01f000, 0x42000000, 0x0010b635, 0x1c01f000,
-	0x480fc857, 0x4c000000, 0x820c0580, 0x00000001,
-	0x04020004, 0x42000000, 0x0010b60c, 0x0401f012,
-	0x820c0580, 0x00000002, 0x04020004, 0x42000000,
-	0x0010b60d, 0x0401f00c, 0x820c0580, 0x00000003,
-	0x04020004, 0x42000000, 0x0010b60e, 0x0401f006,
-	0x820c0580, 0x00000004, 0x04020004, 0x42000000,
-	0x0010b60f, 0x0401ff51, 0x5c000000, 0x1c01f000,
-	0x4c000000, 0x59a80026, 0x4803c857, 0x8c000502,
-	0x04000010, 0x8c000506, 0x04000004, 0x42000000,
-	0x0010b63f, 0x0401f012, 0x8c00050a, 0x04000004,
-	0x42000000, 0x0010b63e, 0x0401f00d, 0x8c000508,
-	0x04000004, 0x42000000, 0x0010b641, 0x0401f008,
-	0x0201f800, 0x00104e0d, 0x04000006, 0x8c000506,
-	0x04020004, 0x42000000, 0x0010b640, 0x0401ff33,
-	0x5c000000, 0x1c01f000, 0x8058b1c0, 0x02000800,
-	0x00100615, 0x5450a800, 0x8050a000, 0x8054a800,
-	0x8058b040, 0x040207fc, 0x1c01f000, 0x8058b1c0,
-	0x02000800, 0x00100615, 0x4450a800, 0x8054a800,
-	0x8058b040, 0x040207fd, 0x1c01f000, 0x8058b1c0,
-	0x02000800, 0x00100615, 0x50500000, 0x9c0001c0,
-	0x4400a800, 0x8050a000, 0x8054a800, 0x8058b040,
-	0x040207fa, 0x1c01f000, 0x4c000000, 0x59a80008,
-	0x8c00051c, 0x5c000000, 0x1c01f000, 0x00000001,
-	0x00000002, 0x00000004, 0x00000008, 0x00000010,
-	0x00000020, 0x00000040, 0x00000080, 0x00000100,
-	0x00000200, 0x00000400, 0x00000800, 0x00001000,
-	0x00002000, 0x00004000, 0x00008000, 0x00010000,
-	0xd2764e14
-};
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_length01 = 0x0000a971 ;
-#else
-uint32_t risc_code_length01 = 0x0000a971 ;
-#endif
-
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_addr02 = 0x0010d000  ;
-#else
-uint32_t risc_code_addr02 = 0x0010d000 ;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_code02[] = {
-#else
-uint32_t risc_code02[] = {
-#endif
-	0x00000000, 0x00000000, 0x0010d000, 0x0000165e,
-	0x00000000, 0x00000000, 0x00020000, 0x000009f7,
-	0x836c0580, 0x00000003, 0x02020000, 0x00100314,
-	0x42000000, 0x0010b2b7, 0x50000000, 0x800001c0,
-	0x0402098a, 0x0401f94d, 0x0201f800, 0x00020524,
-	0x0401fbfe, 0x0201f800, 0x0002084c, 0x0201f800,
-	0x000206af, 0x0401f7ef, 0x59b800ea, 0x82000d00,
-	0xf0000038, 0x02020000, 0x00100ac3, 0x8c000510,
-	0x02000000, 0x00100ac2, 0x59ba60e0, 0x81300182,
-	0x0402104e, 0x04002030, 0x8532653e, 0x59300406,
-	0x82000580, 0x00000003, 0x04020028, 0x59300203,
-	0x82000580, 0x00000004, 0x04020024, 0x59325808,
-	0x59300402, 0x4a025a04, 0x00000103, 0x900001c0,
-	0x48025806, 0x497a5807, 0x497a5c09, 0x5930001f,
-	0x80000540, 0x02020800, 0x00100d9a, 0x59300004,
-	0x8c00053e, 0x04020010, 0x0401fb47, 0x59326809,
-	0x0201f800, 0x000208b4, 0x5934000f, 0x5934140b,
-	0x80081040, 0x04001002, 0x480a6c0b, 0x80000540,
-	0x04020a31, 0x59b800ea, 0x8c000510, 0x040207d7,
-	0x1c01f000, 0x0201f800, 0x00106cb4, 0x040007ef,
-	0x0201f000, 0x00100aae, 0x42027000, 0x00000055,
-	0x0401f027, 0x83326500, 0x3fffffff, 0x59300406,
-	0x82000580, 0x00000003, 0x04020015, 0x59325808,
-	0x59326809, 0x59301402, 0x4a025a04, 0x00000103,
-	0x900811c0, 0x480a5806, 0x497a5c09, 0x497a5807,
-	0x0401fb21, 0x0201f800, 0x000208b4, 0x5934000f,
-	0x5934140b, 0x80081040, 0x04001002, 0x480a6c0b,
-	0x80000540, 0x04020a0c, 0x0401f7db, 0x42027000,
-	0x00000054, 0x0401f00a, 0x83300500, 0x60000000,
-	0x02000000, 0x00100ab1, 0x81326580, 0x8000013a,
-	0x82000400, 0x00100ac9, 0x50027000, 0x59300c06,
-	0x82040580, 0x00000002, 0x02000000, 0x00100aae,
-	0x59300004, 0x8c00053e, 0x04020004, 0x0201f800,
-	0x000208d8, 0x0401f7c4, 0x0201f800, 0x00106cb4,
-	0x040007fb, 0x0201f000, 0x00100aae, 0x59325808,
-	0x412c7000, 0x58380a04, 0x82040500, 0x0000000f,
-	0x82000c00, 0x0010110d, 0x50044000, 0x0c01f001,
-	0x00100e24, 0x00100e24, 0x000200a0, 0x00100e24,
-	0x00100e24, 0x00100e24, 0x00100e24, 0x00100e24,
-	0x000200b0, 0x00100e38, 0x00100e24, 0x00100e24,
-	0x00100e26, 0x00100e24, 0x00100e24, 0x00100e24,
-	0x5838040a, 0x8c000500, 0x02000800, 0x00100615,
-	0x50200000, 0x80387c00, 0x583c1002, 0x583c2800,
-	0x583c2001, 0x58380a07, 0x5838300f, 0x59303807,
-	0x58384c08, 0x5838000d, 0x48026012, 0x0401f010,
-	0x5838020a, 0x8c000502, 0x02000000, 0x00100e24,
-	0x50200000, 0x80387c00, 0x583c2800, 0x583c2001,
-	0x583c1002, 0x592c0a07, 0x592c4c08, 0x592c300f,
-	0x59303807, 0x497a6012, 0x497a6013, 0x4816600e,
-	0x4812600f, 0x480a6010, 0x481a6011, 0x80040840,
-	0x4806600d, 0x02020000, 0x00100e65, 0x841c3d40,
-	0x481e6007, 0x1c01f000, 0x41787800, 0x59325808,
-	0x592c0c0a, 0x8c040d02, 0x02000000, 0x00100fda,
-	0x592c000d, 0x592c100f, 0x592c0a04, 0x480a6011,
-	0x48026012, 0x48026013, 0x412c3000, 0x82040500,
-	0x0000000f, 0x82000400, 0x0010110d, 0x50003800,
-	0x501c0000, 0x401c1000, 0x592c1a07, 0x4802600a,
-	0x481a600b, 0x480a600c, 0x480e600d, 0x843c7d4a,
-	0x403c1000, 0x1c01f000, 0x41787800, 0x497a6012,
-	0x592c0a04, 0x412c3000, 0x592c1a07, 0x82040500,
-	0x0000000f, 0x82000400, 0x0010110d, 0x50004000,
-	0x50200000, 0x40201000, 0x4802600a, 0x481a600b,
-	0x480a600c, 0x480e600d, 0x80000580, 0x483e6004,
-	0x1c01f000, 0x0002014c, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x00020139, 0x00020139, 0x00020139,
-	0x00020139, 0x4c000000, 0x4df00000, 0x4203e000,
-	0xb0100000, 0x41f00000, 0x81fe1500, 0x8d0a1512,
-	0x02020800, 0x00101468, 0x8d0a1518, 0x02020800,
-	0x00020861, 0x8d0a151a, 0x04020ed0, 0x83080500,
-	0x00000d00, 0x04020804, 0x5c03e000, 0x5c000000,
-	0x1801f000, 0x8d0a1516, 0x02020800, 0x001012d9,
-	0x8d0a1514, 0x02020800, 0x001011a5, 0x8d0a1508,
-	0x02020800, 0x001011aa, 0x8d0a1500, 0x02020000,
-	0x000207c8, 0x1c01f000, 0x42000000, 0x0010b2bd,
-	0x50000000, 0x8c000504, 0x04000014, 0x42000000,
-	0x0010b2bd, 0x50000000, 0x8c000502, 0x04020002,
-	0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
-	0x42034000, 0x0010b2a0, 0x59a0001d, 0x59a1d81e,
-	0x84000502, 0x4803401d, 0x58ec0009, 0x0801f800,
-	0x5c03e000, 0x1c01f000, 0x04027002, 0x04026002,
-	0x1c01f000, 0x4df00000, 0x4203e000, 0x50000000,
-	0x0201f800, 0x0010082a, 0x0400001a, 0x412dd800,
-	0x48efc857, 0x0201f800, 0x00103941, 0x42034000,
-	0x0010b2a0, 0x49a1d80b, 0x48ef401e, 0x59a0001d,
-	0x84000544, 0x4803401d, 0x59e00020, 0x4803c857,
-	0x59e00021, 0x4803c857, 0x59e00022, 0x4803c857,
-	0x59e00023, 0x4803c857, 0x59e00024, 0x4803c857,
-	0x0201f800, 0x00101fbb, 0x0201f800, 0x00101fda,
-	0x5c03e000, 0x1c01f000, 0x4da00000, 0x4df00000,
-	0x4203e000, 0x50000000, 0x04006051, 0x42034000,
-	0x0010b2a0, 0x59a01017, 0x59a01818, 0x800c19c0,
-	0x04020008, 0x59a0381b, 0x801c39c0, 0x02000800,
-	0x00100615, 0x59a0041c, 0x801c3c00, 0x0401f00c,
-	0x59a00419, 0x82000400, 0x00000002, 0x48034419,
-	0x82000c80, 0x00000013, 0x04001003, 0x497b4419,
-	0x41780000, 0x59a03816, 0x801c3c00, 0x80081040,
-	0x480b4017, 0x581c0200, 0x4803c021, 0x581c0401,
-	0x4803c022, 0x581c0201, 0x4803c023, 0x581c0400,
-	0x4803c020, 0x900001c0, 0x82000540, 0x00000012,
-	0x4803c011, 0x59e00017, 0x8c000508, 0x04000003,
-	0x4a03c017, 0x00000002, 0x4203e000, 0x30000001,
-	0x800c19c0, 0x04000007, 0x800c1840, 0x480f4018,
-	0x0402001f, 0x497b4419, 0x497b4219, 0x0401f01c,
-	0x800811c0, 0x0402000b, 0x4d2c0000, 0x59a2581b,
-	0x0201f800, 0x0010083a, 0x5c025800, 0x497b401b,
-	0x497b401a, 0x497b441c, 0x497b421c, 0x0401f010,
-	0x59a0041c, 0x82000400, 0x00000002, 0x82000c80,
-	0x00000012, 0x4803441c, 0x04001009, 0x4d2c0000,
-	0x59a2581b, 0x592c3813, 0x481f401b, 0x497b441c,
-	0x0201f800, 0x0010083a, 0x5c025800, 0x5c03e000,
-	0x5c034000, 0x1c01f000, 0x59a80005, 0x82000500,
-	0x00000003, 0x02020000, 0x00104145, 0x59340400,
-	0x82000580, 0x00000606, 0x02020000, 0x00104116,
-	0x5934000d, 0x80027d40, 0x02020000, 0x00104151,
-	0x0401f803, 0x80000580, 0x1c01f000, 0x5934000f,
-	0x59341203, 0x80080540, 0x0402005d, 0x5934020b,
-	0x5934140b, 0x80080480, 0x04021059, 0x0201f800,
-	0x00020892, 0x04000052, 0x592c0406, 0x49366009,
-	0x492e6008, 0x4a026406, 0x00000003, 0x4a026403,
-	0x00000040, 0x80081000, 0x480a6c0b, 0x800000c2,
-	0x800018c4, 0x800c0400, 0x48026206, 0x592c0808,
-	0x592c1809, 0x592c020a, 0x48066017, 0x480e6018,
-	0x8c000502, 0x0400002a, 0x4a026203, 0x00000004,
-	0x592c0207, 0x80000040, 0x0402001a, 0x59a80070,
-	0x80000040, 0x040207ff, 0x592c0204, 0x82000500,
-	0x000000ff, 0x82000580, 0x00000018, 0x04020011,
-	0x592c180f, 0x59300007, 0x82000540, 0x00000091,
-	0x480e6011, 0x48026007, 0x42000000, 0x80000004,
-	0x48026004, 0x59bc00ea, 0x8c000516, 0x040207fe,
-	0x83300400, 0x20000000, 0x480378e1, 0x1c01f000,
-	0x0401fe4b, 0x59300007, 0x8400054e, 0x48026007,
-	0x592c1a04, 0x820c1d00, 0x000000ff, 0x820c0580,
-	0x00000048, 0x04000012, 0x0401f7ec, 0x8c000500,
-	0x04020e9e, 0x4a026203, 0x00000002, 0x59a80071,
-	0x80000040, 0x040207ff, 0x592c1a04, 0x820c1d00,
-	0x000000ff, 0x820c0580, 0x00000018, 0x040007df,
-	0x820c0580, 0x00000048, 0x040207dc, 0x42000800,
-	0x80000804, 0x0201f000, 0x00106466, 0x800811c0,
-	0x04020003, 0x4a026a03, 0x00000001, 0x59340010,
-	0x492e6810, 0x80000d40, 0x04020003, 0x492e680f,
-	0x1c01f000, 0x492c0800, 0x1c01f000, 0x83440c80,
-	0x00000800, 0x04021009, 0x83440400, 0x0010aa00,
-	0x50000000, 0x80000540, 0x04000004, 0x40026800,
-	0x80000580, 0x1c01f000, 0x82000540, 0x00000001,
-	0x1c01f000, 0x59340203, 0x80000540, 0x0402004b,
-	0x4d300000, 0x4d2c0000, 0x5934000f, 0x80025d40,
-	0x04000044, 0x0201f800, 0x00020892, 0x0400003f,
-	0x592c0000, 0x4802680f, 0x80000540, 0x04020002,
-	0x48026810, 0x592c2a04, 0x80081000, 0x480a6c0b,
-	0x49366009, 0x492e6008, 0x82142d00, 0x000000ff,
-	0x82140580, 0x00000012, 0x04000035, 0x4a026406,
-	0x00000003, 0x4a026403, 0x00000040, 0x592c0406,
-	0x800000c2, 0x800018c4, 0x800c0400, 0x48026206,
-	0x592c0808, 0x592c1809, 0x592c020a, 0x48066017,
-	0x480e6018, 0x8c000502, 0x02000000, 0x001045a1,
-	0x4a026203, 0x00000004, 0x592c0207, 0x80000040,
-	0x02020000, 0x00104594, 0x82140580, 0x00000018,
-	0x02020000, 0x00104594, 0x592c180f, 0x59300007,
-	0x82000540, 0x00000091, 0x480e6011, 0x48026007,
-	0x42000000, 0x80000004, 0x48026004, 0x59bc00ea,
-	0x8c000516, 0x040207fe, 0x83300400, 0x20000000,
-	0x480378e1, 0x5934020b, 0x5934140b, 0x80080480,
-	0x040017be, 0x0401f003, 0x4a026a03, 0x00000001,
-	0x5c025800, 0x5c026000, 0x1c01f000, 0x497a5800,
-	0x49325809, 0x4a026406, 0x00000006, 0x4a026203,
-	0x00000007, 0x0401f802, 0x0401f7ef, 0x59a80021,
-	0x800001c0, 0x02020000, 0x001045c3, 0x59a80005,
-	0x8c000504, 0x02020000, 0x001045bf, 0x59340200,
-	0x8c000518, 0x02020000, 0x001045bb, 0x592c0a0c,
-	0x48066202, 0x4a025a06, 0x00000000, 0x8c000508,
-	0x02020000, 0x001045b7, 0x4d3c0000, 0x417a7800,
-	0x0201f800, 0x000207ce, 0x5c027800, 0x1c01f000,
-	0x59980026, 0x497a5800, 0x80000540, 0x04020067,
-	0x59d80105, 0x82000d00, 0x00018780, 0x04020197,
-	0x800000f6, 0x8000013c, 0x0c01f001, 0x000202f3,
-	0x0002034e, 0x00020308, 0x00020326, 0x592c0001,
-	0x492fb107, 0x80000d40, 0x04020805, 0x59940019,
-	0x80000540, 0x04002085, 0x1c01f000, 0x497a5801,
-	0x40065800, 0x592c0001, 0x496a5800, 0x815eb800,
-	0x412ed000, 0x80000d40, 0x040207f9, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x1c01f000,
-	0x492fb107, 0x592c0001, 0x80000d40, 0x04020ff0,
-	0x59da5908, 0x835c0480, 0x00000020, 0x0400100d,
-	0x0402b00b, 0x492fb007, 0x0400e7fa, 0x59d80105,
-	0x82000500, 0x00018780, 0x0402016c, 0x59940019,
-	0x80000540, 0x04002065, 0x1c01f000, 0x0400f009,
-	0x496a5800, 0x412ed000, 0x815eb800, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x0401f7ef,
-	0x492fa807, 0x0401f7ed, 0x59d81108, 0x45681000,
-	0x400ad000, 0x815eb800, 0x0400e7fc, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x0402d009,
-	0x592c0001, 0x492fb107, 0x80000d40, 0x04020fc8,
-	0x59940019, 0x80000540, 0x04002048, 0x1c01f000,
-	0x59d80105, 0x82000500, 0x00018780, 0x04020147,
-	0x42000000, 0x0010b654, 0x0201f800, 0x0010a86e,
-	0x59980026, 0x59980828, 0x80000000, 0x48033026,
-	0x492f3028, 0x800409c0, 0x04000003, 0x492c0800,
-	0x0401f002, 0x492f3029, 0x592c0001, 0x80000d40,
-	0x04020faf, 0x0401f7e7, 0x59980026, 0x59980828,
-	0x80000000, 0x48033026, 0x492f3028, 0x800409c0,
-	0x04000003, 0x492c0800, 0x0401f002, 0x492f3029,
-	0x592c0001, 0x80000d40, 0x04020fa1, 0x0402d00d,
-	0x59980029, 0x80025d40, 0x0400000e, 0x59980026,
-	0x80000040, 0x48033026, 0x04020002, 0x48033028,
-	0x592c0000, 0x48033029, 0x492fb107, 0x0400d7f5,
-	0x42000000, 0x0010b654, 0x0201f800, 0x0010a86e,
-	0x0402e00a, 0x59da5908, 0x496a5800, 0x412ed000,
-	0x815eb800, 0x0400e7fc, 0x59c80000, 0x82000540,
-	0x00001200, 0x48039000, 0x59d80105, 0x82000500,
-	0x00018780, 0x04020109, 0x59940019, 0x80000540,
-	0x04002002, 0x1c01f000, 0x59980023, 0x48032819,
-	0x1c01f000, 0x592c0404, 0x8c00051e, 0x02020000,
-	0x00104b7b, 0x59980022, 0x80000540, 0x0402075d,
-	0x59980026, 0x497a5800, 0x80000540, 0x02020000,
-	0x00104ba6, 0x59d80105, 0x82000d00, 0x00018780,
-	0x040200f2, 0x800000f6, 0x8000013c, 0x0c01f001,
-	0x00020398, 0x00104ba6, 0x0002039d, 0x000203e6,
-	0x592c0001, 0x492fb107, 0x80000d40, 0x04020760,
-	0x1c01f000, 0x592c0001, 0x492fb107, 0x80000d40,
-	0x04020f5b, 0x59da5908, 0x835c0480, 0x00000020,
-	0x0400102b, 0x0402b033, 0x492fb007, 0x0400e7fa,
-	0x59d80105, 0x82000500, 0x00018780, 0x040200d7,
-	0x0400601f, 0x59d8010a, 0x59d8090a, 0x80040580,
-	0x040207fd, 0x800408e0, 0x599c1017, 0x8c081508,
-	0x04020028, 0x82040d40, 0x00000013, 0x5998002b,
-	0x4807c011, 0x84000500, 0x4803302b, 0x59e00017,
-	0x8c000508, 0x04020004, 0x4203e000, 0x30000001,
-	0x1c01f000, 0x4a03c017, 0x00000003, 0x82040500,
-	0x000000ff, 0x82000580, 0x0000001d, 0x040207f7,
-	0x4a03c017, 0x0000000d, 0x0401f7f4, 0x5998082b,
-	0x84040d40, 0x4807302b, 0x1c01f000, 0x496a5800,
-	0x412ed000, 0x815eb800, 0x59c80000, 0x82000540,
-	0x00001200, 0x48039000, 0x0400e7cb, 0x0401f7d1,
-	0x0402f7f7, 0x492fa807, 0x0400e7c7, 0x0401f7cd,
-	0x59e0000f, 0x59e0100f, 0x80081580, 0x040207fd,
-	0x81281580, 0x040007d4, 0x40025000, 0x82040d40,
-	0x0000001d, 0x0401f7d2, 0x59d80908, 0x45680800,
-	0x4006d000, 0x815eb800, 0x0400e7fc, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x02006000,
-	0x00104b8d, 0x59d8010a, 0x59d8090a, 0x80040d80,
-	0x040207fd, 0x900001c0, 0x82000540, 0x00000013,
-	0x4803c011, 0x5998002b, 0x84000500, 0x4803302b,
-	0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017,
-	0x00000003, 0x4203e000, 0x30000001, 0x59d80105,
-	0x82000500, 0x00018780, 0x0402007c, 0x0202d000,
-	0x00104b92, 0x592c0001, 0x492fb107, 0x80000d40,
-	0x040206ef, 0x1c01f000, 0x59980020, 0x0c01f001,
-	0x00020413, 0x00020414, 0x00020434, 0x1c01f000,
-	0x4df00000, 0x4203e000, 0x50000000, 0x04026876,
-	0x04006004, 0x599c0017, 0x8c000508, 0x040208f5,
-	0x59980029, 0x80025d40, 0x0400000a, 0x0402d00b,
-	0x59980026, 0x80000040, 0x48033026, 0x592c0000,
-	0x492fb107, 0x48033029, 0x04020002, 0x48033028,
-	0x5c03e000, 0x1c01f000, 0x59d80105, 0x82000500,
-	0x00018780, 0x04020055, 0x42000000, 0x0010b654,
-	0x0201f800, 0x0010a86e, 0x5c03e000, 0x1c01f000,
-	0x4df00000, 0x4203e000, 0x50000000, 0x599cb817,
-	0x59940019, 0x80000540, 0x04002023, 0x0400000e,
-	0x59980022, 0x82000580, 0x00000005, 0x0400001e,
-	0x59a80069, 0x81640580, 0x0402001b, 0x8c5cbd08,
-	0x04000007, 0x59a8006a, 0x59a80866, 0x80040580,
-	0x04020015, 0x8c5cbd08, 0x0402002b, 0x59d8090b,
-	0x59d8010a, 0x80040580, 0x0400000d, 0x0400600e,
-	0x4a03c011, 0x80400012, 0x4a03c020, 0x00008040,
-	0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017,
-	0x00000002, 0x4203e000, 0x30000001, 0x4a032819,
-	0xffff0000, 0x0400e879, 0x04006003, 0x8c5cbd08,
-	0x0402088e, 0x59980029, 0x80025d40, 0x04020003,
-	0x5c03e000, 0x1c01f000, 0x59d80105, 0x82000500,
-	0x00018780, 0x04020019, 0x0202d000, 0x00104c06,
-	0x59980826, 0x592c0000, 0x80040840, 0x48073026,
-	0x492fb107, 0x48033029, 0x040207f2, 0x48033028,
-	0x0401f7f0, 0x59e0000f, 0x59e0080f, 0x80040580,
-	0x040207fd, 0x59e00010, 0x59e01010, 0x80081580,
-	0x040207fd, 0x40065000, 0x80041580, 0x040007cc,
-	0x040067e1, 0x0401f7cf, 0x4803c857, 0x485fc857,
-	0x8c00050e, 0x02020800, 0x0010060d, 0x4203e000,
-	0x50000000, 0x4200b800, 0x00008004, 0x0201f000,
-	0x0010061a, 0x5998002b, 0x8c000500, 0x04020039,
-	0x0400e006, 0x59d80105, 0x82000500, 0x00018780,
-	0x040207ee, 0x1c01f000, 0x59da5908, 0x835c0c80,
-	0x00000020, 0x04001003, 0x0400b028, 0x0400f02a,
-	0x496a5800, 0x412ed000, 0x815eb800, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x0400e7f3,
-	0x59d8010a, 0x59d8090a, 0x80040580, 0x040207fd,
-	0x800408e0, 0x599c1017, 0x8c081508, 0x04020021,
-	0x82040d40, 0x00000013, 0x4807c011, 0x59e00017,
-	0x8c000508, 0x0400000a, 0x4a03c017, 0x00000003,
-	0x82040500, 0x000000ff, 0x82000580, 0x0000001d,
-	0x04020003, 0x4a03c017, 0x0000000d, 0x4203e000,
-	0x30000001, 0x59d80105, 0x82000500, 0x00018780,
-	0x040207c2, 0x1c01f000, 0x492fb007, 0x0400e7d3,
-	0x0401f7e0, 0x492fa807, 0x0400e7d0, 0x0401f7dd,
-	0x84000500, 0x4803302b, 0x0400e7cc, 0x0401f7d9,
-	0x59e0000f, 0x59e0100f, 0x80081580, 0x040207fd,
-	0x81281580, 0x040007db, 0x40025000, 0x82040d40,
-	0x0000001d, 0x0401f7d9, 0x59da5908, 0x496a5800,
-	0x412ed000, 0x815eb800, 0x0400e7fc, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x59d8090b,
-	0x59980024, 0x48073024, 0x80040480, 0x04020004,
-	0x59940019, 0x80000540, 0x04022003, 0x59980823,
-	0x48072819, 0x59d80105, 0x82000500, 0x00018780,
-	0x04020796, 0x1c01f000, 0x59981025, 0x59e00010,
-	0x59e00810, 0x80041d80, 0x040207fd, 0x80080580,
-	0x04000011, 0x48073025, 0x59e0000f, 0x59e0100f,
-	0x80081d80, 0x040207fd, 0x81280580, 0x04000006,
-	0x400a5000, 0x40080000, 0x80040580, 0x0402067f,
-	0x1c01f000, 0x59940019, 0x80000540, 0x040227fa,
-	0x1c01f000, 0x59e0000f, 0x59e0100f, 0x80081d80,
-	0x040207fd, 0x81280580, 0x040007f6, 0x400a5000,
-	0x59940019, 0x80000540, 0x040027ef, 0x1c01f000,
-	0x59e0000f, 0x59e0100f, 0x80080d80, 0x040207fd,
-	0x81280580, 0x04020002, 0x1c01f000, 0x400a5000,
-	0x900811c0, 0x82081540, 0x0000001c, 0x480bc011,
-	0x59e00017, 0x8c000508, 0x04000003, 0x4a03c017,
-	0x0000000c, 0x4203e000, 0x30000001, 0x1c01f000,
-	0x41700000, 0x0c01f001, 0x001050f0, 0x0002052f,
-	0x001050f0, 0x001050f1, 0x001050ee, 0x001050ee,
-	0x001050ee, 0x001050ee, 0x00105594, 0x04010037,
-	0x59980006, 0x80000540, 0x0402003c, 0x0402c01c,
-	0x4202f800, 0x00000010, 0x4df00000, 0x4203e000,
-	0x50000000, 0x49db3005, 0x59da5808, 0x592c0204,
-	0x497a5800, 0x497a5801, 0x82000500, 0x000000ff,
-	0x82000c80, 0x00000079, 0x04021036, 0x0c01f839,
-	0x5c03e000, 0x817ef840, 0x04000009, 0x836c0580,
-	0x00000003, 0x04020006, 0x83700580, 0x00000001,
-	0x04020010, 0x0401001b, 0x0400c7e8, 0x0400f94b,
-	0x0400b135, 0x59d40005, 0x82000500, 0x43018780,
-	0x02020000, 0x00105523, 0x59d80005, 0x82000500,
-	0x43018780, 0x02020000, 0x0010552a, 0x1c01f000,
-	0x83700580, 0x00000003, 0x02000800, 0x001050f1,
-	0x83700580, 0x00000001, 0x040207ed, 0x04010005,
-	0x0400c7d2, 0x0401f7ea, 0x4202f800, 0x00000010,
-	0x4df00000, 0x4203e000, 0x50000000, 0x49d73005,
-	0x59d65808, 0x0401f7ce, 0x4df00000, 0x4203e000,
-	0x50000000, 0x40025800, 0x592c0204, 0x497b3005,
-	0x497b3006, 0x4202f800, 0x00000010, 0x0401f7c7,
-	0x0201f800, 0x00105161, 0x5c03e000, 0x0401f7d4,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105207, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105171, 0x00105161,
-	0x00105161, 0x00105161, 0x00105231, 0x00105161,
-	0x00105161, 0x00105161, 0x00020623, 0x00105161,
-	0x00105398, 0x00105161, 0x00105161, 0x00105161,
-	0x000205f5, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105199, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x001054b7,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105502, 0x00105161, 0x0010518b,
-	0x00105161, 0x0010547b, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105449, 0x00105161, 0x00105449,
-	0x00105556, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105409, 0x00105539,
-	0x00105161, 0x00105549, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x00105161, 0x00105161, 0x00105161,
-	0x00105161, 0x592c0204, 0x80000110, 0x80000040,
-	0x0400000b, 0x02001000, 0x00105169, 0x48033002,
-	0x492f3003, 0x492f3004, 0x4a033008, 0x00020603,
-	0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406,
-	0x82000c80, 0x0000199a, 0x02021000, 0x00105179,
-	0x59a80021, 0x80000540, 0x02020000, 0x001051a7,
-	0x592e8a06, 0x83440c80, 0x000007f0, 0x02021000,
-	0x00105179, 0x83440400, 0x0010aa00, 0x50000000,
-	0x80026d40, 0x02000000, 0x001051bb, 0x59340002,
-	0x592c0810, 0x80040580, 0x82000500, 0x00ffffff,
-	0x02020000, 0x00105179, 0x0201f800, 0x000201ee,
-	0x02020000, 0x001051be, 0x1c01f000, 0x592c0204,
-	0x80000110, 0x02000000, 0x00105169, 0x80000040,
-	0x0402000b, 0x592c040a, 0x8c000504, 0x04000010,
-	0x592c0207, 0x82000c80, 0x00001001, 0x02021000,
-	0x00105179, 0x0201f000, 0x0010556e, 0x48033002,
-	0x492f3003, 0x492f3004, 0x4a033008, 0x0002063b,
-	0x4202e000, 0x00000003, 0x1c01f000, 0x592c0406,
-	0x82000c80, 0x0000199a, 0x02021000, 0x00105179,
-	0x592e8a06, 0x417a7800, 0x0401fc25, 0x02020000,
-	0x0010533c, 0x59340002, 0x592c0808, 0x80040580,
-	0x82000500, 0x00ffffff, 0x02020000, 0x00105179,
-	0x497a5808, 0x592e6009, 0x83300580, 0xffffffff,
-	0x02000000, 0x001052fc, 0x83300480, 0x0010cfc0,
-	0x02001000, 0x00105359, 0x59a8000b, 0x81300480,
-	0x02021000, 0x00105359, 0x592c240a, 0x49366009,
-	0x8c10251c, 0x02020000, 0x001052ea, 0x59a80068,
-	0x8c000510, 0x02020000, 0x00105372, 0x59a80821,
-	0x800409c0, 0x02020000, 0x001052d0, 0x59a80805,
-	0x8c040d04, 0x02020000, 0x00105363, 0x59340200,
-	0x8c000518, 0x02020000, 0x00105354, 0x59300c06,
-	0x82040580, 0x00000006, 0x02020000, 0x001052f4,
-	0x59300414, 0x8c000516, 0x02020000, 0x0010535e,
-	0x8c102508, 0x02020000, 0x0010a3d7, 0x59300808,
-	0x4a025a06, 0x00000000, 0x800409c0, 0x02020000,
-	0x001052cb, 0x592c0a0c, 0x48066202, 0x492e6008,
-	0x0401f14a, 0x4df00000, 0x4203e000, 0x50000000,
-	0x0402b00b, 0x835c0480, 0x00000020, 0x0400100d,
-	0x815eb840, 0x416a5800, 0x592ed000, 0x492fb007,
-	0x497a5800, 0x497a5801, 0x0400b7f7, 0x59d80005,
-	0x82000500, 0x43018780, 0x02020000, 0x0010552a,
-	0x5c03e000, 0x1c01f000, 0x4df00000, 0x4203e000,
-	0x50000000, 0x0402f00b, 0x835c0480, 0x00000020,
-	0x0400100d, 0x815eb840, 0x416a5800, 0x592ed000,
-	0x492fa807, 0x497a5800, 0x497a5801, 0x0400f7f7,
-	0x59d40005, 0x82000500, 0x43018780, 0x02020000,
-	0x00105523, 0x5c03e000, 0x1c01f000, 0x4df00000,
-	0x4203e000, 0x50000000, 0x59940024, 0x80000540,
-	0x0400010f, 0x4c000000, 0x42000000, 0x00001000,
-	0x50000000, 0x82000480, 0x24320001, 0x04020015,
-	0x42000800, 0x00000064, 0x80040840, 0x04000007,
-	0x4a030000, 0x00000001, 0x40000000, 0x59800000,
-	0x8c000500, 0x040007f9, 0x04000008, 0x42000800,
-	0x00007a01, 0x50040000, 0x8c000510, 0x04000003,
-	0x84000510, 0x44000800, 0x4a030000, 0x00000000,
-	0x59e00002, 0x8c00051e, 0x0402001b, 0x42000000,
-	0x00001000, 0x50000000, 0x82000480, 0x24320002,
-	0x04020015, 0x42000800, 0x00000064, 0x80040840,
-	0x04000007, 0x4a030000, 0x00000001, 0x40000000,
-	0x59800000, 0x8c000500, 0x040007f9, 0x04000008,
-	0x42000800, 0x00007a17, 0x50040000, 0x8c00050e,
-	0x04020003, 0x8400054e, 0x44000800, 0x4a030000,
-	0x00000000, 0x5c000000, 0x5994781a, 0x48032825,
-	0x803c0480, 0x04001004, 0x04000003, 0x4803281a,
-	0x0401f022, 0x41787800, 0x803c7800, 0x82000400,
-	0x000003e8, 0x040027fd, 0x4803281a, 0x59a80024,
-	0x803c1400, 0x480b5024, 0x803c0040, 0x04000002,
-	0x483fc857, 0x59e40852, 0x59a80025, 0x80040580,
-	0x04000004, 0x480bc857, 0x59e40052, 0x48035025,
-	0x59940026, 0x803c0400, 0x48032826, 0x0201f800,
-	0x00105d5a, 0x59940000, 0x82000580, 0x00000000,
-	0x04020006, 0x59940026, 0x48032827, 0x497b2826,
-	0x4a032800, 0x00000001, 0x4c0c0000, 0x59940007,
-	0x80000d40, 0x0400001d, 0x59941006, 0x59940025,
-	0x80081c80, 0x04001004, 0x04000003, 0x480f2806,
-	0x0401f016, 0x80040840, 0x48072807, 0x82040580,
-	0x000003e8, 0x04020007, 0x4c040000, 0x4c0c0000,
-	0x59940008, 0x0801f800, 0x5c001800, 0x5c000800,
-	0x800409c0, 0x04020004, 0x59940008, 0x0801f800,
-	0x0401f006, 0x400c0000, 0x820c1c00, 0x0000000a,
-	0x040027ed, 0x480f2806, 0x5c001800, 0x4d180000,
-	0x59c40008, 0x8c000534, 0x04020025, 0x417a3000,
-	0x83947c00, 0x00000009, 0x583c0001, 0x80000d40,
-	0x04020008, 0x823c7c00, 0x00000003, 0x811a3000,
-	0x83180580, 0x00000005, 0x040207f8, 0x0401f018,
-	0x583c1000, 0x59940025, 0x80080480, 0x04001005,
-	0x04000004, 0x48007800, 0x80000040, 0x04021010,
-	0x80040840, 0x48047801, 0x04000008, 0x82000400,
-	0x0000000a, 0x48007800, 0x040027fa, 0x82040500,
-	0x0000007f, 0x0401f7e8, 0x583c0002, 0x4c3c0000,
-	0x0801f800, 0x5c007800, 0x0401f7e3, 0x5c023000,
-	0x59940019, 0x80001540, 0x04000007, 0x04002006,
-	0x59940025, 0x80080480, 0x04021002, 0x80000580,
-	0x48032819, 0x5994001c, 0x80000d40, 0x04000013,
-	0x5994101b, 0x59940025, 0x80080480, 0x04001005,
-	0x04000004, 0x4803281b, 0x80000040, 0x0402100b,
-	0x80040840, 0x4807281c, 0x04020004, 0x5994001d,
-	0x0801f800, 0x0401f005, 0x82000400, 0x0000000a,
-	0x4803281b, 0x040027f7, 0x59940004, 0x80000d40,
-	0x04000013, 0x59941003, 0x59940025, 0x80080480,
-	0x04001005, 0x04000004, 0x48032803, 0x80000040,
-	0x0402100b, 0x80040840, 0x48072804, 0x04020004,
-	0x59940005, 0x0801f800, 0x0401f005, 0x82000400,
-	0x0000000a, 0x48032803, 0x040027f7, 0x5994001f,
-	0x80000d40, 0x04000013, 0x5994101e, 0x59940025,
-	0x80080480, 0x04001005, 0x04000004, 0x4803281e,
-	0x80000040, 0x0402100b, 0x80040840, 0x4807281f,
-	0x04020004, 0x59940020, 0x0801f800, 0x0401f005,
-	0x82000400, 0x00000001, 0x4803281e, 0x040027f7,
-	0x59940022, 0x80000d40, 0x04000013, 0x59941021,
-	0x59940025, 0x80080480, 0x04001005, 0x04000004,
-	0x48032821, 0x80000040, 0x0402100b, 0x80040840,
-	0x48072822, 0x04020004, 0x59940023, 0x0801f800,
-	0x0401f005, 0x82000400, 0x0000000a, 0x48032821,
-	0x040027f7, 0x59940824, 0x59940025, 0x80040480,
-	0x02001800, 0x00100615, 0x48032824, 0x59940000,
-	0x0c01f001, 0x00105cee, 0x00105cf0, 0x00105d16,
-	0x59940024, 0x80000000, 0x48032824, 0x4203e000,
-	0x70000000, 0x1c01f000, 0x592c0406, 0x800000c2,
-	0x800008c4, 0x80040c00, 0x592c040a, 0x48066206,
-	0x82000d00, 0x00000003, 0x02000000, 0x00105e97,
-	0x8c000500, 0x0402002c, 0x59a80872, 0x80040840,
-	0x040207ff, 0x8c00051e, 0x02000000, 0x00105e72,
-	0x82000d00, 0x000000c0, 0x02020000, 0x00105e68,
-	0x82000d00, 0x00002020, 0x02020000, 0x00105e65,
-	0x813e79c0, 0x02020000, 0x00105e65, 0x592c0c0c,
-	0x800409c0, 0x02020000, 0x00105e65, 0x59300a03,
-	0x82040d80, 0x00000007, 0x02020000, 0x00105e65,
-	0x4a026203, 0x00000003, 0x4a026403, 0x00000043,
-	0x0201f800, 0x000200ca, 0x82080d40, 0x80003465,
-	0x48066004, 0x497a6000, 0x59bc00ea, 0x8c000516,
-	0x040207fe, 0x83300400, 0xa0000000, 0x480378e1,
-	0x1c01f000, 0x8c000502, 0x02020000, 0x00105eba,
-	0x8c00051e, 0x0400000e, 0x82000d00, 0x000000c0,
-	0x04000005, 0x82040d80, 0x000000c0, 0x02020000,
-	0x00105ebf, 0x82000d00, 0x00002020, 0x82040d80,
-	0x00002020, 0x02000000, 0x00105e86, 0x592c0207,
-	0x80000040, 0x02020000, 0x00105e90, 0x592c180d,
-	0x800c19c0, 0x02020000, 0x00105e90, 0x592c180f,
-	0x59300007, 0x82000540, 0x00000011, 0x480e6011,
-	0x48026007, 0x4a026203, 0x00000004, 0x4a026403,
-	0x00000042, 0x42000800, 0x80002001, 0x0401f02a,
-	0x5c000000, 0x4c000000, 0x4803c857, 0x4807c857,
-	0x0401f003, 0x42000800, 0x00000001, 0x59325808,
-	0x832c0500, 0x00ff0000, 0x0400000d, 0x592c0000,
-	0x48065a06, 0x48026008, 0x592c040a, 0x8c000510,
-	0x04020008, 0x0201f800, 0x00020381, 0x417a7800,
-	0x59300008, 0x80025d40, 0x0402078c, 0x1c01f000,
-	0x456a5800, 0x412ed000, 0x815eb800, 0x59c80000,
-	0x82000540, 0x00001200, 0x48039000, 0x0401f7f4,
-	0x59840000, 0x80000540, 0x04020002, 0x1c01f000,
-	0x59840003, 0x80000540, 0x02020000, 0x00105f37,
-	0x1c01f000, 0x59300004, 0x82000500, 0x00000100,
-	0x80040d40, 0x48066004, 0x59bc00ea, 0x8c000516,
-	0x040207fe, 0x83300400, 0x40000000, 0x480378e1,
-	0x1c01f000, 0x59bc00ea, 0x82001500, 0xb0000018,
-	0x02020000, 0x001069c6, 0x8c000510, 0x0400002a,
-	0x59bc10e0, 0x82080500, 0xfffff000, 0x0402000a,
-	0x80080108, 0x820a3500, 0x0000000f, 0x4803c857,
-	0x1201f000, 0x001069cc, 0x84000510, 0x48026004,
-	0x0401f016, 0x840a653e, 0x59300004, 0x8c000520,
-	0x040007fa, 0x82000500, 0xfffefeff, 0x48026004,
-	0x8c08153e, 0x04020005, 0x42027000, 0x00000013,
-	0x0401f858, 0x0401f009, 0x59300004, 0x8c000514,
-	0x04000003, 0x0401ffac, 0x0401f02e, 0x42027000,
-	0x00000049, 0x0401f84f, 0x59bc00ea, 0x82001500,
-	0xb0000018, 0x02020000, 0x001069c6, 0x8c000510,
-	0x040207d8, 0x1c01f000, 0x83640480, 0x00000010,
-	0x04001019, 0x41626000, 0x41580000, 0x59300a03,
-	0x82040d80, 0x00000000, 0x04000008, 0x83326400,
-	0x00000024, 0x81300c80, 0x040017f9, 0x42026000,
-	0x0010cfc0, 0x0401f7f6, 0x4a026203, 0x00000008,
-	0x8166c840, 0x8332c400, 0x00000024, 0x81600480,
-	0x04021002, 0x1c01f000, 0x837ac540, 0x0010cfc0,
-	0x1c01f000, 0x42000000, 0x0010b653, 0x0201f800,
-	0x0010a86e, 0x4967c857, 0x80026580, 0x1c01f000,
-	0x83300480, 0x0010cfc0, 0x02001800, 0x00100615,
-	0x41580000, 0x81300480, 0x0402100c, 0x04011000,
-	0x457a6000, 0x4a026202, 0x0000ffff, 0x83300400,
-	0x00000003, 0x4803c840, 0x4a03c842, 0x00000021,
-	0x8166c800, 0x1c01f000, 0x41540000, 0x81300480,
-	0x02021800, 0x00100615, 0x04011000, 0x457a6000,
-	0x4a026202, 0x0000ffff, 0x83300400, 0x00000003,
-	0x4803c840, 0x4a03c842, 0x00000021, 0x59a80066,
-	0x49335065, 0x80000000, 0x48035066, 0x1c01f000,
-	0x4d340000, 0x59326809, 0x59300406, 0x82000500,
-	0x0000001f, 0x0c01f803, 0x5c026800, 0x1c01f000,
-	0x001076ed, 0x00107700, 0x0010771a, 0x00020900,
-	0x001096c1, 0x001096dc, 0x00020975, 0x001076ed,
-	0x00107700, 0x00106226, 0x00107733, 0x001076ed,
-	0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed,
-	0x0010936a, 0x0010a4d0, 0x001076ed, 0x001076ed,
-	0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed,
-	0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed,
-	0x001076ed, 0x001076ed, 0x001076ed, 0x001076ed,
-	0x59300203, 0x82000c80, 0x0000000e, 0x02021800,
-	0x00100615, 0x0c01f001, 0x00107731, 0x00108337,
-	0x00020914, 0x001084cc, 0x00108566, 0x00107731,
-	0x00107731, 0x00107731, 0x0010831c, 0x00107731,
-	0x00107731, 0x00107731, 0x00107731, 0x0010873a,
-	0x83380480, 0x00000058, 0x04021007, 0x83380480,
-	0x00000040, 0x04001004, 0x4d2c0000, 0x0c01f803,
-	0x5c025800, 0x1c01f000, 0x001083c1, 0x001083c1,
-	0x001083c1, 0x001083c1, 0x001083c1, 0x001083c3,
-	0x00108463, 0x001083c1, 0x001083c1, 0x001083c1,
-	0x001083c1, 0x001083c1, 0x001083c1, 0x001083c1,
-	0x001083c1, 0x001083c1, 0x001083c1, 0x001083c1,
-	0x001083c1, 0x00108467, 0x00020936, 0x001083c1,
-	0x00108466, 0x00108468, 0x59325808, 0x59300811,
-	0x59301402, 0x59340200, 0x8c00050e, 0x0402001c,
-	0x0401f826, 0x04000005, 0x4a025a04, 0x00000103,
-	0x497a5c09, 0x0401f009, 0x4a025a04, 0x00000103,
-	0x4a025a06, 0x00000000, 0x497a5c09, 0x800409c0,
-	0x02020800, 0x00108531, 0x48065807, 0x480a5c06,
-	0x0201f800, 0x00020381, 0x5934000f, 0x5934140b,
-	0x80081040, 0x04001002, 0x480a6c0b, 0x80000540,
-	0x02020800, 0x00020275, 0x0401f75e, 0x592c020a,
-	0x8c000502, 0x040007e9, 0x800409c0, 0x040007e7,
-	0x592c0208, 0x8c00050e, 0x040207e4, 0x4933c857,
-	0x0201f000, 0x00108fc6, 0x592c020a, 0x8c000500,
-	0x04000010, 0x59300015, 0x592c380f, 0x801c3c80,
-	0x0400000c, 0x4a025a06, 0x00000015, 0x8c1c3d3e,
-	0x04000005, 0x4a025a06, 0x00000007, 0x801c3880,
-	0x801c3800, 0x481fc857, 0x821c0d40, 0x00000000,
-	0x1c01f000, 0x59300203, 0x82003480, 0x0000000e,
-	0x02021800, 0x00100615, 0x0c01f001, 0x001096fb,
-	0x00020989, 0x00109d9c, 0x00109daa, 0x000209a5,
-	0x001096fb, 0x00109e98, 0x000209c4, 0x001096fb,
-	0x001096fb, 0x001096fb, 0x001096fb, 0x001096fb,
-	0x001096fb, 0x83380580, 0x00000013, 0x02020000,
-	0x00109d23, 0x59300403, 0x82027480, 0x00000044,
-	0x02021800, 0x00100615, 0x82000480, 0x00000040,
-	0x02001800, 0x00100615, 0x0c01f001, 0x00109d80,
-	0x0002099b, 0x00109d82, 0x00109d94, 0x59325808,
-	0x832c0500, 0x00ff0000, 0x04000005, 0x592c0c0a,
-	0x8c040d1a, 0x02020000, 0x00109d8f, 0x0401fe8e,
-	0x0401f710, 0x83380580, 0x00000048, 0x04000007,
-	0x83380580, 0x00000053, 0x02000000, 0x00109e3a,
-	0x0201f800, 0x00100615, 0x5930001f, 0x59301011,
-	0x59300809, 0x58040a00, 0x8c040d0e, 0x02020000,
-	0x00109e16, 0x800811c0, 0x02020000, 0x00109e23,
-	0x5930001f, 0x80000540, 0x02020000, 0x00109e31,
-	0x59325808, 0x592c040a, 0x8c00051e, 0x02000000,
-	0x00109e0c, 0x42027000, 0x00000041, 0x0401f001,
-	0x83380480, 0x00000054, 0x02021800, 0x00100615,
-	0x83380480, 0x00000040, 0x02001000, 0x00109e57,
-	0x0c01f001, 0x00109e63, 0x000209e1, 0x00109e6f,
-	0x00109e76, 0x00109e63, 0x00109e63, 0x00109e63,
-	0x00109e63, 0x00109e65, 0x00109e6a, 0x00109e6a,
-	0x00109e63, 0x00109e63, 0x00109e63, 0x00109e63,
-	0x00109e6a, 0x00109e63, 0x00109e6a, 0x00109e63,
-	0x00109e65, 0x4a026203, 0x00000001, 0x493a6403,
-	0x42000800, 0x80002042, 0x0401f66f, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0x00000000, 0x00000000,
-	0x00000000, 0x00000000, 0xa36ec441, 0x00000000,
-	0x00000000, 0x00000000, 0x00000005, 0xfffffffb,
-	0x02800004, 0x00000000, 0x0000c000, 0x0000071b,
-	0x073fca5a, 0x0705a5a5, 0x01928009, 0x070ff0e1,
-	0x03800006, 0x04958010, 0x05308000, 0x05008000,
-	0x0600902f, 0x04a004dc, 0x0202f051, 0x042e4020,
-	0x018f021b, 0x033e5000, 0x03020000, 0x078d0018,
-	0x0493041a, 0x0092041c, 0x038a0305, 0x078b0303,
-	0x048e8010, 0x0678aae5, 0x06000001, 0x07818174,
-	0x040010e6, 0x0448e0e6, 0x04818010, 0x002fb008,
-	0x0448e0e6, 0x04818010, 0x060ff0e6, 0x00580401,
-	0x054880ff, 0x04818010, 0x022a5001, 0x030430d4,
-	0x06780043, 0x030e0000, 0x030450ff, 0x06780043,
-	0x03019000, 0x048185c4, 0x027c0045, 0x03020000,
-	0x06810037, 0x027c0045, 0x03040000, 0x068100c7,
-	0x027c0045, 0x03080000, 0x0681061c, 0x04908037,
-	0x029105c2, 0x010410a6, 0x0379ff41, 0x037fffff,
-	0x072d6000, 0x07601241, 0x050f80ff, 0x032fa009,
-	0x05600400, 0x050f80ff, 0x056c04ff, 0x068105da,
-	0x073fa009, 0x06000001, 0x0279ff02, 0x0700ffff,
-	0x070ff0d1, 0x0179feff, 0x0700ffff, 0x045c0402,
-	0x048185da, 0x060ff0d0, 0x0179feff, 0x0700ffff,
-	0x057dfeff, 0x0700ffff, 0x068105bc, 0x05600e41,
-	0x050f80ff, 0x032fa069, 0x07480000, 0x068105ce,
-	0x06780043, 0x070000f0, 0x0781005f, 0x037c00ff,
-	0x06000010, 0x0781005f, 0x038005ca, 0x0379ff00,
-	0x070fffff, 0x06780043, 0x07f00000, 0x075a0000,
-	0x020ef001, 0x038605cc, 0x05484000, 0x02a1819e,
-	0x062d6001, 0x002fb001, 0x070ff069, 0x01868072,
-	0x060ff079, 0x055c0441, 0x06810010, 0x012fb000,
-	0x060560fb, 0x03800078, 0x060ff079, 0x02868198,
-	0x070ff069, 0x055c0441, 0x06810010, 0x060560fb,
-	0x0400d0d0, 0x062d6002, 0x0648300d, 0x06810086,
-	0x070ff0d1, 0x062d6001, 0x045c040b, 0x06810089,
-	0x05488000, 0x04818086, 0x072e500c, 0x00208001,
-	0x05a004e1, 0x02800010, 0x062d6001, 0x07f00000,
-	0x07f00000, 0x070ff0d1, 0x0179feff, 0x070000ff,
-	0x055c040c, 0x058180bb, 0x0007b001, 0x03079041,
-	0x0307a000, 0x06600a79, 0x050f80ff, 0x053fa80a,
-	0x06000010, 0x072d5003, 0x078d0096, 0x0307c003,
-	0x0007d004, 0x0107e005, 0x0307f006, 0x02080007,
-	0x00081008, 0x01082009, 0x0308300a, 0x0008400b,
-	0x0308500c, 0x068d00a1, 0x0678007a, 0x07f00000,
-	0x010880ff, 0x03386000, 0x03010000, 0x072e6300,
-	0x020ef07f, 0x02860010, 0x070ff07d, 0x0450047c,
-	0x050f80ff, 0x002fa819, 0x068d00ae, 0x02080001,
-	0x00081002, 0x0448807a, 0x068100b5, 0x0379ff03,
-	0x070000ff, 0x01082003, 0x068d00b6, 0x02386004,
-	0x03010000, 0x072e6c00, 0x02800010, 0x06780043,
-	0x070000f0, 0x068105d5, 0x050020ff, 0x027c0002,
-	0x06000010, 0x078100c3, 0x028005d5, 0x0700c0d1,
-	0x0379ff0c, 0x070000ff, 0x0380008e, 0x0204a051,
-	0x06780043, 0x070000f0, 0x037c00ff, 0x06000010,
-	0x0781816a, 0x072d6000, 0x019485be, 0x050fb056,
-	0x044880e6, 0x04818010, 0x060ff0d0, 0x0179feff,
-	0x0700ffff, 0x057dfeff, 0x0700ffff, 0x068105bc,
-	0x05a00212, 0x0349c0e4, 0x0781811d, 0x070ff093,
-	0x050010ff, 0x070ff093, 0x045c0401, 0x058180db,
-	0x02046092, 0x04002046, 0x04600202, 0x00540401,
-	0x048280e6, 0x04500425, 0x070060ff, 0x0730ffff,
-	0x0700000f, 0x0742000f, 0x05810190, 0x06a005a4,
-	0x0648a002, 0x048180e9, 0x00047089, 0x070ff047,
-	0x045c0443, 0x077800ff, 0x07f00000, 0x0781818e,
-	0x07780047, 0x0500e000, 0x048185ab, 0x070ff006,
-	0x01860117, 0x0179fe47, 0x0700000f, 0x010480ff,
-	0x056c7048, 0x06818102, 0x007a0d4a, 0x04003801,
-	0x0220f001, 0x0180010f, 0x07608e48, 0x034a60ff,
-	0x0700f0ff, 0x074b88ff, 0x037000ff, 0x07000600,
-	0x05500448, 0x074d00ff, 0x045a044a, 0x0304a0ff,
-	0x070ff00f, 0x01540406, 0x05820117, 0x04950120,
-	0x05a001bd, 0x02868123, 0x0134bfff, 0x070fffff,
-	0x0104102e, 0x050fd041, 0x00800126, 0x0595011d,
-	0x05a001bd, 0x0186011d, 0x0202f00e, 0x052e4030,
-	0x040fd02f, 0x070fc0ff, 0x05a00218, 0x02800010,
-	0x0400e02f, 0x042e4020, 0x0202f051, 0x0004100e,
-	0x0004b00e, 0x050fd041, 0x024a6c46, 0x04500423,
-	0x050070ff, 0x03620024, 0x050080ff, 0x04004046,
-	0x0700500f, 0x03206000, 0x05601048, 0x0700a0ff,
-	0x0700900a, 0x070ff005, 0x04500446, 0x00540425,
-	0x04820157, 0x05601622, 0x050f80ff, 0x063fa032,
-	0x06000002, 0x03203000, 0x01204000, 0x03205000,
-	0x0120b000, 0x0320c000, 0x07601441, 0x050f80ff,
-	0x043fa852, 0x06000001, 0x070ff056, 0x056c02ff,
-	0x050fb0ff, 0x070560ff, 0x03079041, 0x05600e41,
-	0x050f80ff, 0x073fa011, 0x0600003d, 0x06780043,
-	0x07f00000, 0x065a007a, 0x010880ff, 0x04a001b6,
-	0x058d0150, 0x0208a04a, 0x0108b04b, 0x02386001,
-	0x03010000, 0x072e6300, 0x028000a8, 0x0500d00a,
-	0x05500405, 0x014a68ff, 0x070090ff, 0x0154040a,
-	0x0700c0ff, 0x0600a023, 0x0500b024, 0x02206001,
-	0x05601622, 0x050f80ff, 0x063fa04a, 0x06000002,
-	0x05601022, 0x050f80ff, 0x043fa819, 0x06000001,
-	0x0600a00d, 0x0180013c, 0x06780043, 0x070000f0,
-	0x050010ff, 0x027c0001, 0x07000030, 0x078105b2,
-	0x027c0001, 0x06000020, 0x078105b2, 0x038005ca,
-	0x054880ff, 0x06810010, 0x070ff056, 0x050fb0ff,
-	0x044880e5, 0x0581017d, 0x044880e6, 0x04818010,
-	0x00800183, 0x056c02ff, 0x050fb0ff, 0x070560ff,
-	0x072e5300, 0x044880e6, 0x04818010, 0x072d5003,
-	0x06780043, 0x07f00000, 0x010880ff, 0x058d0187,
-	0x03386005, 0x03010000, 0x033e6000, 0x0700000c,
-	0x052e5200, 0x02800010, 0x0120918e, 0x018004e4,
-	0x01209190, 0x018004e4, 0x00209192, 0x018004e4,
-	0x03209000, 0x018004e4, 0x01209196, 0x018004e4,
-	0x00209198, 0x018004e4, 0x02493075, 0x0681050b,
-	0x0120919a, 0x018004e4, 0x06601e01, 0x050f80ff,
-	0x063fa029, 0x06000008, 0x02015010, 0x02016051,
-	0x00017051, 0x00011051, 0x05601a41, 0x050f80ff,
-	0x053fa83a, 0x06000008, 0x05600e41, 0x050f80ff,
-	0x01464000, 0x032fa00a, 0x07006011, 0x05007012,
-	0x04008013, 0x07009014, 0x0600a015, 0x0400b016,
-	0x0700c017, 0x07c00000, 0x072d5003, 0x06601479,
-	0x050f80ff, 0x048d01b9, 0x063fa051, 0x0600003e,
-	0x07c00000, 0x06005051, 0x0400e02c, 0x0660060e,
-	0x050f80ff, 0x032fa009, 0x0379ff00, 0x070000ff,
-	0x076c0000, 0x058101dd, 0x0660480e, 0x0500e0ff,
-	0x034000ff, 0x01540427, 0x0582020a, 0x03400005,
-	0x070ff005, 0x055c0428, 0x0481020e, 0x01680e05,
-	0x056c0405, 0x068181bf, 0x040f8029, 0x053fa809,
-	0x07000024, 0x06600649, 0x050f80ff, 0x032fa009,
-	0x0379ff00, 0x070000ff, 0x076c0000, 0x068181bf,
-	0x0400e049, 0x0340002d, 0x050f802b, 0x053fa80a,
-	0x06000016, 0x0660480e, 0x0302c0ff, 0x034000ff,
-	0x01540427, 0x0582020c, 0x072d6000, 0x0460040e,
-	0x050f80ff, 0x0104e0d1, 0x0379ff4e, 0x0700ffff,
-	0x062d6002, 0x032fa009, 0x0004d0d0, 0x074b004d,
-	0x07780000, 0x07ffff00, 0x055a044d, 0x070000ff,
-	0x00201008, 0x04002051, 0x06003051, 0x05304000,
-	0x07000060, 0x03205009, 0x07006022, 0x0460040e,
-	0x050f80ff, 0x032fa03a, 0x06603c0e, 0x050f80ff,
-	0x073fa00a, 0x07000027, 0x050010d1, 0x0460320e,
-	0x050f80ff, 0x012fa80a, 0x060ff00e, 0x055c042e,
-	0x04810210, 0x07c00000, 0x0400e026, 0x008001cb,
-	0x0202c026, 0x008001e6, 0x0500e02e, 0x008001e6,
-	0x0400e051, 0x01800209, 0x0349c0e4, 0x04810215,
-	0x07c00000, 0x013e4000, 0x070c0000, 0x07c00000,
-	0x013e4000, 0x03080000, 0x07c00000, 0x009702f4,
-	0x022a5002, 0x0790821d, 0x00910291, 0x030400a6,
-	0x0678aae5, 0x06000001, 0x01a1860c, 0x06600c40,
-	0x050f80ff, 0x032fa021, 0x074b0000, 0x076c0600,
-	0x07818293, 0x05600403, 0x050f80ff, 0x073fa009,
-	0x06000002, 0x0279ff04, 0x0700ffff, 0x010440d7,
-	0x0179fe44, 0x0700ffff, 0x045c0404, 0x07818295,
-	0x0349f044, 0x0681829e, 0x02495001, 0x06818297,
-	0x060ff079, 0x045c0440, 0x0781823c, 0x0644f07a,
-	0x002fb008, 0x060ff079, 0x045c0440, 0x07818241,
-	0x0644f07a, 0x002fb008, 0x0648f001, 0x07818288,
-	0x04600e40, 0x050f80ff, 0x06480001, 0x04810257,
-	0x0448e001, 0x04810273, 0x02460001, 0x0644f001,
-	0x012fa80a, 0x04008040, 0x05a004ee, 0x0286828c,
-	0x05a004d8, 0x062da001, 0x013e4000, 0x06000080,
-	0x06930013, 0x02920013, 0x02800010, 0x0644f001,
-	0x012fa80a, 0x020ef002, 0x00860275, 0x04600840,
-	0x050f80ff, 0x053fa809, 0x06000002, 0x05780105,
-	0x00800440, 0x017c0105, 0x05000400, 0x06818275,
-	0x06601e02, 0x050f80ff, 0x053fa809, 0x06000002,
-	0x04602a40, 0x050f80ff, 0x070ff005, 0x053fa809,
-	0x06000002, 0x055c0405, 0x06818275, 0x04008040,
-	0x0045e008, 0x05a004d8, 0x00800251, 0x0644f001,
-	0x012fa80a, 0x050020d8, 0x04600440, 0x050f80ff,
-	0x073fa00a, 0x06000001, 0x06480001, 0x07818281,
-	0x05308000, 0x03040000, 0x06009040, 0x04a004dc,
-	0x00800251, 0x07a0060c, 0x054b0800, 0x056a0700,
-	0x06600c40, 0x050f80ff, 0x032fa00a, 0x00800251,
-	0x013e4000, 0x06000080, 0x01209288, 0x018004e4,
-	0x06009008, 0x05308000, 0x05004000, 0x04a004dc,
-	0x00800251, 0x02209002, 0x008002e5, 0x03209000,
-	0x008002e5, 0x02209004, 0x008002e5, 0x04a002fd,
-	0x062da001, 0x05308000, 0x05002000, 0x06009040,
-	0x04a004dc, 0x00800252, 0x013e4000, 0x06000080,
-	0x02495001, 0x078182db, 0x04600840, 0x050f80ff,
-	0x053fa809, 0x06000001, 0x0721f000, 0x0349f003,
-	0x058102aa, 0x0245f01f, 0x06000002, 0x018602db,
-	0x07601400, 0x050f80ff, 0x012fa809, 0x06480001,
-	0x058102db, 0x06602440, 0x050f80ff, 0x012fa809,
-	0x020ef001, 0x038682db, 0x019b02db, 0x050020d8,
-	0x062da001, 0x06303002, 0x05000430, 0x04600440,
-	0x050f80ff, 0x073fa012, 0x06000001, 0x028f82bf,
-	0x050040d8, 0x062da001, 0x07601e00, 0x050f80ff,
-	0x073fa009, 0x06000001, 0x060ff004, 0x00540402,
-	0x048202d9, 0x06005051, 0x06006051, 0x06602240,
-	0x050f80ff, 0x063fa01a, 0x06000002, 0x06600a40,
-	0x050f80ff, 0x073fa00a, 0x07000003, 0x060ff040,
-	0x045a041f, 0x010eb0ff, 0x06930013, 0x02920013,
-	0x02800010, 0x04004002, 0x018002c9, 0x04a002fd,
-	0x062da001, 0x05308000, 0x07005000, 0x06009040,
-	0x04a004dc, 0x050080d8, 0x05a004e1, 0x062da001,
-	0x02800013, 0x050fd009, 0x050fd041, 0x013e4000,
-	0x06000080, 0x05308000, 0x03013000, 0x04a004dc,
-	0x010440d7, 0x0349f044, 0x048102f2, 0x062da001,
-	0x008f02f2, 0x03e00000, 0x062da001, 0x02800013,
-	0x0249c0e5, 0x06810013, 0x062da001, 0x07f00000,
-	0x07f00000, 0x033e5000, 0x070c0000, 0x018f02f6,
-	0x03800011, 0x050020d8, 0x04600440, 0x050f80ff,
-	0x073fa00a, 0x06000001, 0x07c00000, 0x002fb001,
-	0x03800306, 0x012fb000, 0x03075087, 0x068d0307,
-	0x03386000, 0x03020000, 0x04482075, 0x06810352,
-	0x0648a0e6, 0x07810347, 0x0642007f, 0x06810345,
-	0x0340007e, 0x060ff038, 0x0154047e, 0x02d00334,
-	0x0560027d, 0x050f80ff, 0x032fa009, 0x030ef000,
-	0x02860504, 0x0107d000, 0x05600800, 0x050f80ff,
-	0x032fa009, 0x03681e00, 0x04500420, 0x050f80ff,
-	0x073fa009, 0x0700003f, 0x03800311, 0x070ff07d,
-	0x0450047c, 0x050f80ff, 0x002fa819, 0x078d0327,
-	0x02080001, 0x00081002, 0x0448807a, 0x0781032e,
-	0x0379ff03, 0x070000ff, 0x01082003, 0x068d032f,
-	0x02386004, 0x03010000, 0x072e6c00, 0x02800352,
-	0x0380033a, 0x0380033c, 0x0280033e, 0x02800340,
-	0x03800342, 0x03800344, 0x0727c005, 0x02800323,
-	0x0627c008, 0x02800323, 0x0627c00b, 0x02800323,
-	0x0627c00e, 0x02800323, 0x0727c011, 0x02800323,
-	0x03800314, 0x052e6800, 0x02800352, 0x044880e6,
-	0x06810531, 0x052e6200, 0x070ff088, 0x0179feff,
-	0x070fffff, 0x04818501, 0x060ff083, 0x0086836d,
-	0x033e6000, 0x07000003, 0x068d0352, 0x07286000,
-	0x07f00000, 0x078d0355, 0x038c0306, 0x0648c0e6,
-	0x05818372, 0x0448e0e6, 0x0781036a, 0x004920e6,
-	0x07810365, 0x06a0056d, 0x05001088, 0x00700101,
-	0x03100000, 0x00088001, 0x033e6000, 0x07000088,
-	0x0280055e, 0x02386001, 0x07030000, 0x033e6000,
-	0x06000008, 0x028003f1, 0x02799075, 0x0500040f,
-	0x06810010, 0x06601479, 0x050080ff, 0x06309052,
-	0x0600003e, 0x02800376, 0x06602279, 0x050080ff,
-	0x05309812, 0x07000041, 0x0648007a, 0x0781037e,
-	0x04488075, 0x0581837e, 0x040f8008, 0x070fa009,
-	0x0049107a, 0x01a183f3, 0x00798075, 0x06000507,
-	0x0481851c, 0x0448b075, 0x06810385, 0x02493075,
-	0x07810509, 0x0249c0e6, 0x048183e0, 0x0648c0e6,
-	0x0581839a, 0x068d0389, 0x02386001, 0x07030000,
-	0x0049107a, 0x07810390, 0x020ef083, 0x0386039a,
-	0x06483075, 0x068103ef, 0x0678007a, 0x07000035,
-	0x03a184cf, 0x05308000, 0x07060000, 0x06009079,
-	0x04a004dc, 0x028003ef, 0x0448807a, 0x0681039e,
-	0x06483075, 0x058104f9, 0x0448d07a, 0x068103a2,
-	0x06483075, 0x058104f9, 0x068d03a2, 0x02386001,
-	0x07030000, 0x0444e07a, 0x0648307a, 0x048183c7,
-	0x0448707a, 0x068103ea, 0x0648f07a, 0x078103b2,
-	0x05a004cf, 0x04008079, 0x05a004ee, 0x008683c2,
-	0x05a004d8, 0x028003ef, 0x0560107b, 0x050f80ff,
-	0x032fa009, 0x0349c000, 0x058183c0, 0x04600e79,
-	0x050f80ff, 0x073fa00a, 0x0600003d, 0x06600a79,
-	0x050f80ff, 0x053fa80a, 0x06000010, 0x028003ef,
-	0x0046e07a, 0x028003ea, 0x06009008, 0x05308000,
-	0x05004000, 0x04a004dc, 0x028003ef, 0x0560167b,
-	0x050f80ff, 0x032fa011, 0x070ff000, 0x04500401,
-	0x030460ff, 0x060ff025, 0x00540446, 0x078203d1,
-	0x030460ff, 0x04092046, 0x05a00218, 0x06600679,
-	0x050f80ff, 0x00201007, 0x012fa80a, 0x0046047a,
-	0x034630ff, 0x050020ff, 0x06003051, 0x04600e79,
-	0x050f80ff, 0x073fa012, 0x06000001, 0x028003ef,
-	0x033e6a00, 0x0202000e, 0x02079051, 0x07000088,
-	0x078d03e4, 0x0744c000, 0x01088000, 0x03386006,
-	0x03010000, 0x02800010, 0x05a004cf, 0x05308000,
-	0x03020000, 0x06009079, 0x04a004dc, 0x033e6a00,
-	0x0302000a, 0x02079051, 0x02800010, 0x04603e79,
-	0x050f80ff, 0x032fa009, 0x070ff000, 0x0186040c,
-	0x057dfeff, 0x07ffffff, 0x0581040c, 0x050f8000,
-	0x012fa811, 0x0079fe02, 0x070000ff, 0x077d66ff,
-	0x060000dc, 0x0781840c, 0x060ff001, 0x0286840d,
-	0x064b0002, 0x06420002, 0x060ff002, 0x05500400,
-	0x050f80ff, 0x05004084, 0x073fa00a, 0x06000002,
-	0x07c00000, 0x04600201, 0x050f80ff, 0x073fa009,
-	0x06000001, 0x0079fe02, 0x070000ff, 0x077d72ff,
-	0x070000dd, 0x0781840c, 0x064b0002, 0x06420002,
-	0x06000001, 0x01800406, 0x0605004c, 0x0180041e,
-	0x0493041a, 0x04a004d5, 0x054bc450, 0x05810421,
-	0x01d00422, 0x01800421, 0x00800432, 0x00800434,
-	0x00800432, 0x008004a7, 0x0180043f, 0x00800434,
-	0x01800471, 0x00800432, 0x00800432, 0x008004ab,
-	0x00800432, 0x018004af, 0x008004c4, 0x01800488,
-	0x00800432, 0x00800432, 0x00209432, 0x018004e4,
-	0x0379ff50, 0x070fffff, 0x060ff079, 0x055c0450,
-	0x048104a4, 0x002fb008, 0x060ff079, 0x055c0450,
-	0x058104a3, 0x04a004c7, 0x0180049c, 0x0179fe50,
-	0x070fffff, 0x070050ff, 0x060ff079, 0x055c0405,
-	0x04810449, 0x002fb008, 0x060ff079, 0x055c0405,
-	0x078184a0, 0x070ff087, 0x017980ff, 0x06000507,
-	0x06818451, 0x02203040, 0x05002087, 0x0049d002,
-	0x0481046b, 0x04930458, 0x01257000, 0x073c3fff,
-	0x0700000f, 0x052e4003, 0x072e5030, 0x0304c050,
-	0x02400057, 0x06740057, 0x06000002, 0x06820016,
-	0x04002083, 0x07003084, 0x04004085, 0x06602279,
-	0x050f80ff, 0x063fa01a, 0x06000001, 0x05a004cf,
-	0x06a00576, 0x033e6a00, 0x0302000a, 0x062e5020,
-	0x003e4002, 0x07000a00, 0x028003f1, 0x07420003,
-	0x0781844e, 0x00798002, 0x06000507, 0x06818451,
-	0x0180045c, 0x05930478, 0x01257000, 0x073c3fff,
-	0x0700000f, 0x052e4003, 0x072e5030, 0x0304c050,
-	0x067800e6, 0x07000041, 0x0581047d, 0x06a0057f,
-	0x04818016, 0x002fb008, 0x067800e6, 0x07000041,
-	0x04810483, 0x06a0057f, 0x04818016, 0x062e5020,
-	0x003e4002, 0x07000a00, 0x03e00000, 0x02800010,
-	0x0379ff50, 0x070fffff, 0x060ff079, 0x055c0450,
-	0x0781848e, 0x0245507a, 0x002fb008, 0x060ff079,
-	0x055c0450, 0x07818493, 0x0245507a, 0x002fb008,
-	0x05600e50, 0x050f80ff, 0x012fa809, 0x02455001,
-	0x05600e50, 0x050f80ff, 0x012fa80a, 0x0080049d,
-	0x002fb008, 0x003e4002, 0x07000a00, 0x02800016,
-	0x079384a3, 0x062e5020, 0x042e4002, 0x002fb008,
-	0x013e4000, 0x05000e00, 0x02800016, 0x0179fe50,
-	0x070fffff, 0x010210ff, 0x02800016, 0x0179fe50,
-	0x070fffff, 0x050340ff, 0x0080049d, 0x0179fe50,
-	0x070fffff, 0x0102e0ff, 0x0760282e, 0x050f80ff,
-	0x05222000, 0x07223000, 0x05224000, 0x07225000,
-	0x07226000, 0x05227000, 0x05228000, 0x07229000,
-	0x0722a000, 0x0522b000, 0x063fa051, 0x07000011,
-	0x0202c026, 0x0522d000, 0x052e400c, 0x02800016,
-	0x030430d4, 0x062e5008, 0x00800176, 0x05600e50,
-	0x050f80ff, 0x032fa009, 0x03460000, 0x018004d2,
-	0x0246007a, 0x0045207a, 0x008004d0, 0x0246007a,
-	0x0600007a, 0x04600e79, 0x050f80ff, 0x032fa00a,
-	0x07c00000, 0x029284d5, 0x070500e1, 0x07c00000,
-	0x0245f008, 0x048404d9, 0x020e0008, 0x07c00000,
-	0x070ff009, 0x065a0008, 0x058404de, 0x020e0008,
-	0x07c00000, 0x058404e1, 0x020e0008, 0x07c00000,
-	0x05308000, 0x0500d000, 0x04a004dc, 0x04a004e9,
-	0x02800010, 0x052e4300, 0x072e500c, 0x073c3fff,
-	0x0700000f, 0x07c00000, 0x06602208, 0x050f80ff,
-	0x032fa011, 0x076a0000, 0x068184f7, 0x066a0001,
-	0x048104f7, 0x04002051, 0x07c00000, 0x00202001,
-	0x07c00000, 0x0648307a, 0x01a18606, 0x05a004cc,
-	0x05308000, 0x05001000, 0x06009079, 0x04a004dc,
-	0x0280055e, 0x0249c0e6, 0x058104f9, 0x0280036d,
-	0x0648307a, 0x07818196, 0x05a004cf, 0x02209504,
-	0x018004e4, 0x02490075, 0x06810519, 0x04002089,
-	0x04780102, 0x07f00000, 0x05001088, 0x06a0056d,
-	0x04740101, 0x03100000, 0x060ff002, 0x045c0401,
-	0x0481851a, 0x00088001, 0x033e6000, 0x070000c0,
-	0x0380055a, 0x07f00000, 0x0220951a, 0x018004e4,
-	0x040fd075, 0x040fd07a, 0x040fd079, 0x0648307a,
-	0x06810525, 0x06780075, 0x06000007, 0x0481852c,
-	0x07a00606, 0x06486075, 0x06818194, 0x02490075,
-	0x0781819a, 0x04487075, 0x04818534, 0x0280053b,
-	0x05308000, 0x03010000, 0x06009079, 0x04a004dc,
-	0x02800010, 0x0448e0e6, 0x04818352, 0x00800192,
-	0x05308000, 0x0500e000, 0x06009079, 0x04a004dc,
-	0x04008089, 0x05a004e1, 0x0380055a, 0x05a004cc,
-	0x05308000, 0x0700f000, 0x06009079, 0x07000088,
-	0x06a00543, 0x04a004dc, 0x02800010, 0x03386000,
-	0x07030000, 0x07f00000, 0x068d0546, 0x033e6a00,
-	0x0202000e, 0x02079051, 0x0448b075, 0x06810551,
-	0x02493075, 0x06810551, 0x05301005, 0x03010000,
-	0x03800553, 0x05301006, 0x03010000, 0x05002087,
-	0x06485002, 0x05818553, 0x0744c000, 0x01088000,
-	0x02086001, 0x07c00000, 0x05001088, 0x06a0056d,
-	0x0644c001, 0x00088001, 0x033e6a00, 0x0202000e,
-	0x004920e6, 0x05818563, 0x02079051, 0x078d0563,
-	0x060ff089, 0x034990ff, 0x0781056a, 0x03386005,
-	0x03010000, 0x02800010, 0x03386006, 0x03010000,
-	0x02800010, 0x068d056d, 0x03386000, 0x07030000,
-	0x07f00000, 0x078d0571, 0x070ff087, 0x074850ff,
-	0x05818572, 0x07c00000, 0x068d0576, 0x02386001,
-	0x07030000, 0x07f00000, 0x068d057a, 0x070ff087,
-	0x074850ff, 0x0581857b, 0x07c00000, 0x05002087,
-	0x0049d002, 0x0581858e, 0x002fb008, 0x067800e6,
-	0x07000041, 0x002fb008, 0x0581858e, 0x06a005a4,
-	0x0448e002, 0x06810591, 0x0648a002, 0x0481859b,
-	0x06486002, 0x07810595, 0x02400057, 0x056a02ff,
-	0x07c00000, 0x06a005a4, 0x06788102, 0x06000004,
-	0x0581858e, 0x04002089, 0x070ff0d4, 0x045c0402,
-	0x077800ff, 0x07f00000, 0x0581858e, 0x00202010,
-	0x038c058e, 0x07f00000, 0x06420002, 0x0581859c,
-	0x06a00576, 0x033e6a00, 0x0302000a, 0x07c00000,
-	0x07f00000, 0x060ff0a2, 0x050020ff, 0x060ff0a2,
-	0x045c0402, 0x058185a5, 0x07c00000, 0x05a00218,
-	0x03495047, 0x068105b0, 0x0320901d, 0x02800602,
-	0x0220901f, 0x02800602, 0x014980e4, 0x04818010,
-	0x013e4000, 0x07003000, 0x05600e35, 0x050f80ff,
-	0x07a006fa, 0x01208003, 0x05a004e1, 0x038005ca,
-	0x03209009, 0x02800602, 0x03209011, 0x02800602,
-	0x02209007, 0x02800602, 0x03209003, 0x02800602,
-	0x00498043, 0x048185bc, 0x00497043, 0x058185c0,
-	0x02209001, 0x02800602, 0x0220900d, 0x02800602,
-	0x0320900f, 0x02800602, 0x03493000, 0x068105d3,
-	0x027c0045, 0x070a0000, 0x068105dc, 0x0220900b,
-	0x02800602, 0x02209013, 0x05308000, 0x01012000,
-	0x04a004dc, 0x00800183, 0x03209005, 0x02800602,
-	0x072e500c, 0x00208002, 0x05a004e1, 0x02800010,
-	0x02209015, 0x02800602, 0x072d6000, 0x05308000,
-	0x05007000, 0x07f00000, 0x070090d1, 0x0379ff09,
-	0x0700ffff, 0x04a004dc, 0x03209017, 0x02800602,
-	0x033e5000, 0x06000080, 0x02209019, 0x02800602,
-	0x072d6000, 0x033e5000, 0x06000080, 0x07f00000,
-	0x060ff0d0, 0x0179feff, 0x0700ffff, 0x057dfeff,
-	0x0700ffff, 0x04818010, 0x02400058, 0x00642058,
-	0x06820010, 0x033e5000, 0x06000080, 0x04058051,
-	0x0320901b, 0x02800602, 0x05308000, 0x01012000,
-	0x04a004dc, 0x00800176, 0x05a00218, 0x05308000,
-	0x05008000, 0x06009079, 0x04a004dc, 0x07c00000,
-	0x034900e4, 0x04818616, 0x013e4000, 0x070000c0,
-	0x07f00000, 0x034900e4, 0x05818614, 0x07c00000,
-	0x013e4000, 0x06000080, 0x07f00000, 0x07f00000,
-	0x07f00000, 0x034900e4, 0x0681060e, 0x02800616,
-	0x072d6000, 0x00498043, 0x07810630, 0x060ff0d0,
-	0x0179feff, 0x0700ffff, 0x057dfeff, 0x0700ffff,
-	0x048185e0, 0x050f8030, 0x032fa009, 0x0379ff00,
-	0x0700ffff, 0x070ff0d1, 0x0179feff, 0x0700ffff,
-	0x055c0400, 0x068105e0, 0x04004051, 0x03800678,
-	0x06a006da, 0x062d6001, 0x020ef004, 0x038605e2,
-	0x06600004, 0x050f80ff, 0x032fa009, 0x074b0000,
-	0x05002000, 0x0769ff00, 0x01640800, 0x078205e2,
-	0x01640e00, 0x058285e2, 0x070ff036, 0x045c0404,
-	0x0581864b, 0x072d6000, 0x050f8030, 0x032fa009,
-	0x0379ff00, 0x0700ffff, 0x070ff0d1, 0x0179feff,
-	0x0700ffff, 0x055c0400, 0x068105e0, 0x04482034,
-	0x068105fd, 0x06483034, 0x048185fd, 0x070ff0d4,
-	0x077800ff, 0x070000f0, 0x037c00ff, 0x06000010,
-	0x07810678, 0x07a006d4, 0x024900e5, 0x0681065b,
-	0x033e5000, 0x06000080, 0x02800010, 0x04601c04,
-	0x050f80ff, 0x053fa809, 0x06000020, 0x030ef041,
-	0x028605ec, 0x062d6002, 0x05602a41, 0x050f80ff,
-	0x012fa809, 0x060ff0d0, 0x074b00ff, 0x045c0401,
-	0x04818676, 0x062d6001, 0x07602841, 0x050f80ff,
-	0x053fa809, 0x06000001, 0x070ff0d1, 0x054b80ff,
-	0x074b0003, 0x055c0403, 0x04818676, 0x033e5000,
-	0x06000080, 0x0180070c, 0x07600041, 0x0380065c,
-	0x07a006d4, 0x024900e5, 0x0781067e, 0x033e5000,
-	0x06000080, 0x02800010, 0x07a006c0, 0x030ef041,
-	0x038605f0, 0x04058051, 0x072d6000, 0x05601041,
-	0x050f80ff, 0x012fa809, 0x0600a0d0, 0x0500b0d1,
-	0x062d6001, 0x07f00000, 0x07f00000, 0x0600c0d0,
-	0x0500d0d1, 0x062d6002, 0x0279ff0d, 0x07ff0000,
-	0x044d800d, 0x060ff0d0, 0x074b00ff, 0x065a000d,
-	0x06601201, 0x050f80ff, 0x073fa022, 0x07000005,
-	0x0079fe0d, 0x070000ff, 0x050020ff, 0x05602a41,
-	0x050f80ff, 0x073fa00a, 0x06000001, 0x020ef004,
-	0x038606bd, 0x04601c04, 0x050f80ff, 0x053fa809,
-	0x06000001, 0x050f80ff, 0x053fa80a, 0x06000020,
-	0x07602841, 0x050f80ff, 0x073fa009, 0x06000001,
-	0x0279ff02, 0x070000ff, 0x0678000d, 0x0700ff00,
-	0x065a0002, 0x07602841, 0x050f80ff, 0x073fa00a,
-	0x06000001, 0x07600041, 0x050f80ff, 0x053fa80a,
-	0x06000001, 0x07601241, 0x050f80ff, 0x073fa00a,
-	0x06000002, 0x033e5000, 0x06000080, 0x0180070c,
-	0x040f8032, 0x073fa011, 0x06000001, 0x060ff002,
-	0x055c0403, 0x048186c8, 0x00041051, 0x07c00000,
-	0x04600402, 0x04500432, 0x050f80ff, 0x053fa809,
-	0x06000020, 0x00400402, 0x01680eff, 0x070030ff,
-	0x040f8032, 0x053fa80a, 0x06000001, 0x07c00000,
-	0x024900e5, 0x078106d7, 0x07c00000, 0x033e5000,
-	0x070000c0, 0x07c00000, 0x05004036, 0x060000d0,
-	0x0179fe00, 0x0700ffff, 0x057dfeff, 0x0700ffff,
-	0x078106f9, 0x070000d1, 0x0379ff00, 0x0700ffff,
-	0x06005051, 0x060ff031, 0x05500405, 0x050f80ff,
-	0x073fa009, 0x06000002, 0x020ef004, 0x038606f3,
-	0x04600404, 0x050f80ff, 0x012fa809, 0x0079fe01,
-	0x0700ffff, 0x055c0400, 0x078106f9, 0x01400405,
-	0x070050ff, 0x057de0ff, 0x06000007, 0x048186e5,
-	0x04004051, 0x07c00000, 0x072d6000, 0x07f00000,
-	0x07f00000, 0x000110d0, 0x010120d1, 0x062d6001,
-	0x07f00000, 0x07f00000, 0x020130d0, 0x010140d1,
-	0x062d6002, 0x010170d4, 0x07f00000, 0x020150d0,
-	0x030160d1, 0x053fa83a, 0x06000008, 0x07c00000,
-	0x07600c41, 0x050f80ff, 0x073fa009, 0x06000001,
-	0x04780102, 0x07ffff00, 0x046a0702, 0x050f80ff,
-	0x073fa00a, 0x06000001, 0x05600e41, 0x050f80ff,
-	0x032fa069, 0x03800053, 0xdb4ee9e2, 0x02800004,
-	0x00000000, 0x00008000, 0x00000542, 0x040f801f,
-	0x012fa8c9, 0x040f801f, 0x073fa081, 0x06000010,
-	0x03200005, 0x07420000, 0x050fb000, 0x040f801f,
-	0x073fa011, 0x06000038, 0x040f801f, 0x053fa859,
-	0x0700003a, 0x050fe000, 0x0581800a, 0x0784003c,
-	0x04958019, 0x030e0011, 0x072e4200, 0x03800014,
-	0x0291001f, 0x050010c0, 0x04482001, 0x058180fa,
-	0x06483001, 0x0681815d, 0x02920029, 0x068b0029,
-	0x008a0162, 0x050010c0, 0x06780001, 0x050007c0,
-	0x06818240, 0x06780001, 0x0500f800, 0x06818280,
-	0x03910030, 0x040fe029, 0x03860030, 0x076c001d,
-	0x058102b1, 0x076c0a1d, 0x048102da, 0x029200ab,
-	0x040fe02f, 0x0386003c, 0x06000013, 0x050fb000,
-	0x066c0073, 0x068103ec, 0x014920e4, 0x0581803c,
-	0x03400000, 0x076c0a00, 0x04818034, 0x0696003e,
-	0x03b900ca, 0x05908014, 0x010170e1, 0x07780017,
-	0x03e00000, 0x06810091, 0x050010ff, 0x0179fe17,
-	0x031fffff, 0x070000ff, 0x05600800, 0x050f80ff,
-	0x073fa009, 0x06000001, 0x06780002, 0x02800040,
-	0x037c00ff, 0x03800000, 0x0681005d, 0x0249f002,
-	0x078100aa, 0x0448e002, 0x0681005d, 0x07600c00,
-	0x050f80ff, 0x073fa009, 0x06000001, 0x06780002,
-	0x07ffff00, 0x037c00ff, 0x05000200, 0x058180aa,
-	0x064bd401, 0x03d0005f, 0x028000a8, 0x02800067,
-	0x03800071, 0x0380007b, 0x02800085, 0x0280008f,
-	0x028000a8, 0x028000a8, 0x050fe027, 0x0086806b,
-	0x01028000, 0x0280006e, 0x07600027, 0x050f80ff,
-	0x032fa00a, 0x01027000, 0x02400029, 0x038000aa,
-	0x040fe025, 0x00868075, 0x03026000, 0x03800078,
-	0x06600025, 0x050f80ff, 0x032fa00a, 0x03025000,
-	0x02400029, 0x038000aa, 0x050fe021, 0x0086807f,
-	0x01022000, 0x03800082, 0x07600021, 0x050f80ff,
-	0x032fa00a, 0x01021000, 0x02400029, 0x038000aa,
-	0x040fe023, 0x00868089, 0x01024000, 0x0280008c,
-	0x06600023, 0x050f80ff, 0x032fa00a, 0x03023000,
-	0x02400029, 0x038000aa, 0x06a000da, 0x038000aa,
-	0x01640817, 0x048280a8, 0x070ff017, 0x03d00095,
-	0x0280009d, 0x0380009f, 0x028000a2, 0x038000a5,
-	0x028000a8, 0x028000a8, 0x028000a8, 0x028000a8,
-	0x03e00000, 0x03800014, 0x0590809f, 0x030160e1,
-	0x038000aa, 0x049080a2, 0x030150e1, 0x038000aa,
-	0x059080a5, 0x010140e1, 0x038000aa, 0x060fc013,
-	0x07a0053a, 0x03800014, 0x014940e4, 0x00a180ae,
-	0x0380003c, 0x02681e0d, 0x050fb0ff, 0x04600876,
-	0x050f80ff, 0x053fa809, 0x06000001, 0x05488003,
-	0x058180bd, 0x0400800d, 0x0120d000, 0x013e4000,
-	0x05000200, 0x06009076, 0x04002075, 0x06a00526,
-	0x07c00000, 0x072e4800, 0x07000012, 0x028000cd,
-	0x0747f000, 0x05600800, 0x050f80ff, 0x012fa809,
-	0x0249f001, 0x068100cd, 0x01012000, 0x052e4c00,
-	0x07c00000, 0x070000eb, 0x0349f000, 0x048180c1,
-	0x05600800, 0x050f80ff, 0x012fa809, 0x0448e001,
-	0x068100d3, 0x07c00000, 0x0079c101, 0x07ffffff,
-	0x027a4b01, 0x03800000, 0x05600800, 0x050f80ff,
-	0x012fa80a, 0x07600c00, 0x050f80ff, 0x012fa821,
-	0x06780001, 0x07ffff00, 0x037c00ff, 0x05000700,
-	0x068100ef, 0x06601804, 0x070030ff, 0x050f80ff,
-	0x012fa809, 0x05002000, 0x050f8003, 0x073fa00a,
-	0x06000001, 0x040fe001, 0x038600f0, 0x04600201,
-	0x050f80ff, 0x032fa00a, 0x07c00000, 0x050fe02e,
-	0x018680f5, 0x0102e000, 0x0302f000, 0x038000f9,
-	0x0760002e, 0x050f80ff, 0x032fa00a, 0x0102e000,
-	0x07c00000, 0x022c0004, 0x056c041d, 0x0481010e,
-	0x056c021d, 0x04810125, 0x056c081d, 0x04810137,
-	0x076c061d, 0x04810151, 0x0521d000, 0x0202c013,
-	0x0202a013, 0x02020013, 0x0460021a, 0x050f80ff,
-	0x053fa80a, 0x07000009, 0x03b600be, 0x0484801f,
-	0x0380003c, 0x040fe02a, 0x00860104, 0x06000013,
-	0x04001013, 0x0560102b, 0x050f80ff, 0x032fa012,
-	0x06420029, 0x0660002a, 0x050f80ff, 0x053fa809,
-	0x06000001, 0x050fe003, 0x01860122, 0x01028003,
-	0x0660002a, 0x050f80ff, 0x053fa80a, 0x07000009,
-	0x00800152, 0x00028013, 0x00027013, 0x00800152,
-	0x040fe02a, 0x01860103, 0x06420029, 0x0660002a,
-	0x050f80ff, 0x053fa809, 0x06000001, 0x050fe003,
-	0x00860134, 0x03026003, 0x0660002a, 0x050f80ff,
-	0x053fa80a, 0x07000009, 0x00800152, 0x02026013,
-	0x02025013, 0x00800152, 0x040fe02a, 0x01860103,
-	0x06420029, 0x0660002a, 0x050f80ff, 0x053fa809,
-	0x06000001, 0x050fe003, 0x00860146, 0x01022003,
-	0x0660002a, 0x050f80ff, 0x053fa80a, 0x07000009,
-	0x01800148, 0x00022013, 0x00021013, 0x0647f020,
-	0x007a0120, 0x04000101, 0x04a002a2, 0x0400802a,
-	0x06a0051f, 0x03948103, 0x0521d005, 0x00800104,
-	0x0180010c, 0x0647f020, 0x06486020, 0x06818157,
-	0x04a002a2, 0x01800103, 0x007a0120, 0x04000101,
-	0x04a002a2, 0x0400802a, 0x06a0051f, 0x01800103,
-	0x040fd02a, 0x052e4003, 0x00208010, 0x06a0051f,
-	0x0180010c, 0x00018098, 0x07480018, 0x06818173,
-	0x05481018, 0x07818171, 0x05482018, 0x0781816f,
-	0x07483018, 0x0681816d, 0x002fb004, 0x01800174,
-	0x012fb003, 0x01800174, 0x002fb002, 0x01800174,
-	0x002fb001, 0x01800174, 0x012fb000, 0x0179fe78,
-	0x070000ff, 0x030190ff, 0x00017086, 0x058b0178,
-	0x03385000, 0x03020000, 0x07780017, 0x00430407,
-	0x07818200, 0x046c0419, 0x058101b4, 0x046c0219,
-	0x05810184, 0x07219000, 0x00800198, 0x07219000,
-	0x07483017, 0x0481019e, 0x05482017, 0x058101a5,
-	0x0448b075, 0x06818198, 0x06601476, 0x050f80ff,
-	0x073fa022, 0x0600003e, 0x06000080, 0x05001081,
-	0x05002082, 0x06003083, 0x05004084, 0x04601c76,
-	0x050f80ff, 0x022fa02a, 0x07219000, 0x07780078,
-	0x07ffff00, 0x045a0419, 0x010780ff, 0x0484801f,
-	0x0380003c, 0x040fe07f, 0x008601ad, 0x04a001cd,
-	0x00920198, 0x040fe07f, 0x06a681cd, 0x00800198,
-	0x0560107b, 0x050f80ff, 0x032fa009, 0x0744f000,
-	0x0560107b, 0x050f80ff, 0x032fa00a, 0x0180018b,
-	0x052e400c, 0x040080fb, 0x046aa108, 0x06009076,
-	0x04002075, 0x06a00526, 0x00800198, 0x06219001,
-	0x05482017, 0x048101c1, 0x058b01b7, 0x060ff086,
-	0x0349f0ff, 0x07818177, 0x07483017, 0x058101be,
-	0x050fd0ff, 0x040fe07f, 0x06a681cd, 0x00800198,
-	0x05004084, 0x05a00222, 0x00920198, 0x070ff07d,
-	0x0450047c, 0x056004ff, 0x050f80ff, 0x032fa009,
-	0x070ff000, 0x00540479, 0x030790ff, 0x018001a5,
-	0x060ff079, 0x0054047a, 0x058201f9, 0x058101f9,
-	0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819,
-	0x048b01d5, 0x02080001, 0x00081002, 0x01082003,
-	0x048b01d9, 0x03385000, 0x03010000, 0x02400019,
-	0x070ff003, 0x04500479, 0x030790ff, 0x0340007e,
-	0x0642007f, 0x058101f9, 0x070ff07e, 0x050f80ff,
-	0x032fa009, 0x050fe000, 0x028681f8, 0x070ff07d,
-	0x056002ff, 0x050f80ff, 0x032fa009, 0x0107d000,
-	0x018601fa, 0x0560087d, 0x050f80ff, 0x032fa009,
-	0x03681e00, 0x0550041b, 0x050f80ff, 0x032fa009,
-	0x0107e000, 0x070ff07e, 0x018001e4, 0x0307c000,
-	0x07c00000, 0x052e400c, 0x040080fb, 0x046aa108,
-	0x06009076, 0x04002075, 0x02800526, 0x040fd076,
-	0x050fd017, 0x060ff086, 0x077800ff, 0x07000060,
-	0x037c00ff, 0x07000060, 0x06818202, 0x07780078,
-	0x07ffff00, 0x045a0419, 0x010780ff, 0x06601476,
-	0x050f80ff, 0x073fa022, 0x0600003e, 0x052e400c,
-	0x04600876, 0x050f80ff, 0x053fa809, 0x06000001,
-	0x05488003, 0x0481021c, 0x0400d0fb, 0x066a810d,
-	0x013e4000, 0x07000300, 0x02800029, 0x040080fb,
-	0x066a8108, 0x06009076, 0x04002075, 0x06a00526,
-	0x02800029, 0x0240007f, 0x0742007e, 0x050f807e,
-	0x032fa009, 0x050fe000, 0x0386823c, 0x070ff07d,
-	0x055c047b, 0x04810231, 0x0760007d, 0x050f80ff,
-	0x032fa009, 0x050fe000, 0x02868231, 0x070ff07b,
-	0x0107d0ff, 0x0560087d, 0x050f80ff, 0x032fa009,
-	0x03681e00, 0x0450041c, 0x0107e0ff, 0x050f80ff,
-	0x032fa009, 0x050fe000, 0x0086023e, 0x0307c000,
-	0x07c00000, 0x040fd076, 0x0380053a, 0x010180c0,
-	0x0548e018, 0x07818259, 0x0748f018, 0x07818255,
-	0x03490018, 0x06818251, 0x01491018, 0x0781824d,
-	0x073c0000, 0x06000040, 0x02200004, 0x0180025c,
-	0x073c0000, 0x06000020, 0x03200003, 0x0180025c,
-	0x073c0000, 0x06000010, 0x02200002, 0x0180025c,
-	0x073c0000, 0x06000008, 0x02200001, 0x0180025c,
-	0x073c0000, 0x06000004, 0x06000013, 0x050fb000,
-	0x040fe076, 0x00860275, 0x046c0273, 0x04810285,
-	0x066c0073, 0x05810266, 0x040fd076, 0x07a0053a,
-	0x03800014, 0x040fd076, 0x01800269, 0x00452075,
-	0x00077013, 0x0647f075, 0x06486075, 0x0781826f,
-	0x04a002a8, 0x00800275, 0x007a0175, 0x04000101,
-	0x04a002a8, 0x04008076, 0x0245f008, 0x06a0051f,
-	0x07273000, 0x05600272, 0x050f80ff, 0x053fa80a,
-	0x07000009, 0x0379ff78, 0x070000ff, 0x02076013,
-	0x02075013, 0x0484801f, 0x0380003c, 0x070fc0ff,
-	0x052e400c, 0x00208020, 0x06a0051f, 0x0180027e,
-	0x04600276, 0x050010ff, 0x040f8001, 0x032fa009,
-	0x040f8001, 0x053fa80a, 0x07000009, 0x070ff000,
-	0x02868297, 0x06601276, 0x050f80ff, 0x073fa009,
-	0x0700000c, 0x07601818, 0x050f80ff, 0x053fa80a,
-	0x07000009, 0x00800298, 0x07a000f0, 0x0448b075,
-	0x04810268, 0x06000013, 0x04001013, 0x0560107b,
-	0x050f80ff, 0x032fa012, 0x0046b075, 0x03b600be,
-	0x01800269, 0x06000020, 0x04001016, 0x0460082a,
-	0x050f80ff, 0x032fa012, 0x07c00000, 0x06000075,
-	0x040010a2, 0x044b0801, 0x060ff016, 0x065a0001,
-	0x04600876, 0x050f80ff, 0x032fa012, 0x07c00000,
-	0x050fe022, 0x008602bc, 0x0421d004, 0x0302a022,
-	0x04a002e9, 0x04488020, 0x048102ce, 0x040fd02a,
-	0x0521d000, 0x0202a013, 0x02020013, 0x040fe026,
-	0x018602d4, 0x0421d001, 0x0202a026, 0x04a002e9,
-	0x0202c013, 0x00683e20, 0x070060ff, 0x056c0206,
-	0x0681031c, 0x056c0406, 0x06810332, 0x076c0606,
-	0x078103a3, 0x04488020, 0x068182d0, 0x056c1606,
-	0x078103b1, 0x06a00516, 0x018002e2, 0x040fd02a,
-	0x0521d000, 0x0202a013, 0x02020013, 0x050fe028,
-	0x018602e2, 0x0302a028, 0x0421d002, 0x04a002e9,
-	0x018002f0, 0x050fe022, 0x018602e2, 0x0421d004,
-	0x0302a022, 0x04a002e9, 0x04488020, 0x078182e4,
-	0x06a00516, 0x05848030, 0x0380003c, 0x040fd02a,
-	0x0521d000, 0x0202a013, 0x02020013, 0x018002e2,
-	0x0460082a, 0x050f80ff, 0x022fa031, 0x03020000,
-	0x0002b004, 0x01018005, 0x07c00000, 0x0400702a,
-	0x07a003e4, 0x007a0101, 0x07060000, 0x07303000,
-	0x07008290, 0x07600018, 0x050f80ff, 0x053fa809,
-	0x07000003, 0x0448e007, 0x068182fe, 0x06006013,
-	0x03800305, 0x02400010, 0x048102fe, 0x06006010,
-	0x0460322a, 0x050f80ff, 0x073fa00a, 0x07000003,
-	0x050f801e, 0x032fa03a, 0x063aa020, 0x06000002,
-	0x013e4000, 0x07000030, 0x0298030b, 0x070ff0f6,
-	0x036830ff, 0x0581830c, 0x070f001e, 0x0560102b,
-	0x050f10ff, 0x063f3c08, 0x0600000d, 0x013e4000,
-	0x06000020, 0x040f801a, 0x0320000a, 0x022017d0,
-	0x032fa012, 0x0202c013, 0x018002e2, 0x04007013,
-	0x07a003e4, 0x007a0101, 0x07050000, 0x07303000,
-	0x07008890, 0x074d0005, 0x06006013, 0x050f801e,
-	0x032fa03a, 0x05601a2b, 0x050f80ff, 0x022fa019,
-	0x04001002, 0x04002013, 0x040f801f, 0x022fa01a,
-	0x073aa00c, 0x06000002, 0x07300c03, 0x0600000d,
-	0x038003d1, 0x04007013, 0x07a003e4, 0x007a0101,
-	0x03070000, 0x0660282a, 0x050f80ff, 0x073fa009,
-	0x06000004, 0x02499008, 0x0781033f, 0x07303000,
-	0x07008890, 0x03800341, 0x07303000, 0x04008980,
-	0x05007003, 0x074d0005, 0x06006013, 0x050f801e,
-	0x032fa03a, 0x0760142b, 0x050f80ff, 0x032fa021,
-	0x064b0002, 0x02499008, 0x0781034d, 0x0644c002,
-	0x054b0400, 0x050040ff, 0x06698104, 0x04818362,
-	0x06000013, 0x04001013, 0x04780102, 0x06000010,
-	0x06003013, 0x04004013, 0x06005013, 0x06006013,
-	0x04007013, 0x00644015, 0x0682035e, 0x04448002,
-	0x02205008, 0x040f801f, 0x032fa042, 0x04008015,
-	0x0280039b, 0x046c8004, 0x04818370, 0x01208018,
-	0x06780002, 0x07000003, 0x04818373, 0x06003001,
-	0x06000013, 0x04001013, 0x04004013, 0x06005013,
-	0x040f801f, 0x022fa032, 0x0280039b, 0x040fd02a,
-	0x07a0053a, 0x03800014, 0x0379ff03, 0x070000ff,
-	0x04488002, 0x0681037a, 0x070ff003, 0x04500408,
-	0x050080ff, 0x0379ff00, 0x070000ff, 0x06489002,
-	0x07810381, 0x070ff000, 0x04500408, 0x050080ff,
-	0x07005003, 0x05004000, 0x06003001, 0x06000013,
-	0x04001013, 0x040f801f, 0x022fa032, 0x05601c2b,
-	0x050f80ff, 0x022fa031, 0x06600c1f, 0x050f80ff,
-	0x022fa032, 0x02680608, 0x0681039b, 0x016408ff,
-	0x057dfeff, 0x07ffffff, 0x034000ff, 0x045a0407,
-	0x070000ff, 0x0760061e, 0x050f80ff, 0x032fa00a,
-	0x06600908, 0x0669f908, 0x027a0008, 0x06000020,
-	0x070aa0ff, 0x014a20ff, 0x037a00ff, 0x060000dc,
-	0x070000ff, 0x038003d1, 0x04007013, 0x07a003e4,
-	0x007a0101, 0x07030000, 0x07303000, 0x07008190,
-	0x06006013, 0x050f801e, 0x032fa03a, 0x073aa000,
-	0x06000002, 0x07300c00, 0x07000005, 0x038003d1,
-	0x04007013, 0x07a003e4, 0x007a0101, 0x07810000,
-	0x07303000, 0x07000090, 0x06006013, 0x06600c2a,
-	0x050f80ff, 0x053fa809, 0x07000003, 0x04780107,
-	0x07ffff00, 0x007c0107, 0x07000500, 0x048183c4,
-	0x07303000, 0x05000890, 0x074d0005, 0x0660282a,
-	0x050f80ff, 0x053fa809, 0x07000003, 0x0049d007,
-	0x068103cb, 0x02206001, 0x050f801e, 0x032fa03a,
-	0x073aa000, 0x06000002, 0x07300c00, 0x07000005,
-	0x013e4000, 0x07000030, 0x029803d3, 0x070ff0f6,
-	0x036830ff, 0x058183d4, 0x070f001e, 0x040f101f,
-	0x070f3000, 0x013e4000, 0x06000020, 0x040f801a,
-	0x0320000a, 0x022017d0, 0x032fa012, 0x018002e2,
-	0x03200000, 0x06006076, 0x028003e6, 0x03200011,
-	0x0600602a, 0x04a0046b, 0x05600406, 0x050f80ff,
-	0x053fa809, 0x06000002, 0x07c00000, 0x0207602f,
-	0x04600876, 0x050f80ff, 0x022fa031, 0x03075000,
-	0x0007b004, 0x01018005, 0x06600076, 0x050020ff,
-	0x050f80ff, 0x012fa809, 0x0202f001, 0x018683fa,
-	0x0002e013, 0x040f8002, 0x053fa80a, 0x07000009,
-	0x06273001, 0x0448b075, 0x06818404, 0x04602076,
-	0x050f80ff, 0x053fa811, 0x0700003c, 0x0179fe78,
-	0x070000ff, 0x030190ff, 0x0386840c, 0x04a00420,
-	0x00078019, 0x0092041f, 0x00800464, 0x040fd076,
-	0x040fd019, 0x04600276, 0x050020ff, 0x050f80ff,
-	0x032fa009, 0x040f8002, 0x053fa80a, 0x07000009,
-	0x050fe000, 0x0286841c, 0x07601818, 0x050f80ff,
-	0x053fa80a, 0x07000009, 0x0180041d, 0x07a000f0,
-	0x07273000, 0x02076013, 0x0380003c, 0x048b0420,
-	0x03385000, 0x07030000, 0x05600818, 0x050f80ff,
-	0x032fa009, 0x054b0400, 0x0308a0ff, 0x0179fe00,
-	0x070000ff, 0x010880ff, 0x0448b075, 0x0581043a,
-	0x0760147b, 0x050f80ff, 0x002fa819, 0x064b0001,
-	0x02080002, 0x01081003, 0x00082001, 0x02083001,
-	0x02079001, 0x0207a001, 0x00084013, 0x0207f013,
-	0x0180045c, 0x06485075, 0x04810452, 0x02465075,
-	0x06601476, 0x050f80ff, 0x073fa021, 0x0600003e,
-	0x070ff07d, 0x0450047c, 0x050f80ff, 0x002fa819,
-	0x048b0445, 0x02080001, 0x00081002, 0x01082003,
-	0x03079003, 0x0208307a, 0x0340007e, 0x0642007f,
-	0x04810457, 0x070ff07e, 0x05a001e4, 0x02928457,
-	0x01800463, 0x048b0452, 0x06601476, 0x050f80ff,
-	0x073fa041, 0x0600003e, 0x06602476, 0x050f80ff,
-	0x073fa009, 0x06000007, 0x0008400e, 0x058b045c,
-	0x03385000, 0x03010000, 0x06219001, 0x040fe07f,
-	0x01860463, 0x008001cd, 0x07c00000, 0x00683e75,
-	0x05810469, 0x0448d075, 0x0481048f, 0x018004bd,
-	0x06a0051a, 0x0080041f, 0x02978476, 0x07602418,
-	0x050f80ff, 0x012fa809, 0x06780001, 0x070000ff,
-	0x075a0000, 0x070ff014, 0x0569feff, 0x054b08ff,
-	0x075a0000, 0x05600418, 0x050f80ff, 0x012fa809,
-	0x040fe007, 0x0386847d, 0x01204000, 0x0180048b,
-	0x00700101, 0x03010000, 0x06780001, 0x07ff0000,
-	0x076c00ff, 0x06818485, 0x00700101, 0x03010000,
-	0x05600418, 0x050f80ff, 0x012fa80a, 0x06780001,
-	0x07ff0000, 0x050040ff, 0x0279ff01, 0x0700ffff,
-	0x05002014, 0x07c00000, 0x04007076, 0x0448b075,
-	0x058104a9, 0x03200011, 0x06006076, 0x06a003e6,
-	0x007a0101, 0x07060000, 0x07303000, 0x07008290,
-	0x07600018, 0x050f80ff, 0x053fa809, 0x07000003,
-	0x0448e007, 0x068184a1, 0x06006013, 0x018004b8,
-	0x02400010, 0x048104a1, 0x06006010, 0x04603276,
-	0x050f80ff, 0x073fa00a, 0x07000003, 0x018004b8,
-	0x04602a76, 0x050f80ff, 0x032fa009, 0x060ff07a,
-	0x05500400, 0x070000ff, 0x04602a76, 0x050f80ff,
-	0x032fa00a, 0x07a003e1, 0x007a0101, 0x03010000,
-	0x06303008, 0x05008000, 0x0600600e, 0x050f8074,
-	0x032fa03a, 0x053079a0, 0x0700000c, 0x008004fd,
-	0x00683e75, 0x076c0aff, 0x048104dc, 0x04007013,
-	0x03200011, 0x06006076, 0x06a003e6, 0x007a0101,
-	0x03070000, 0x06602876, 0x050f80ff, 0x053fa809,
-	0x06000001, 0x03499003, 0x058104d1, 0x07303000,
-	0x07008890, 0x053079a0, 0x0700000c, 0x008004d5,
-	0x07303000, 0x04008980, 0x04307920, 0x0700000c,
-	0x074d0005, 0x06006013, 0x050f8074, 0x032fa03a,
-	0x04307920, 0x0700000c, 0x008004fd, 0x04602a76,
-	0x050f80ff, 0x032fa009, 0x060ff07a, 0x05500400,
-	0x070000ff, 0x04602a76, 0x050f80ff, 0x032fa00a,
-	0x04007076, 0x07a003e1, 0x007a0101, 0x03010000,
-	0x06303008, 0x07008800, 0x074d0005, 0x06600a76,
-	0x050f80ff, 0x073fa009, 0x07000003, 0x054b0406,
-	0x045a0404, 0x050040ff, 0x0600600e, 0x050f8074,
-	0x032fa03a, 0x0648c075, 0x048104fb, 0x06307d20,
-	0x0700000c, 0x008004fd, 0x04307920, 0x0700000c,
-	0x013e4000, 0x07000030, 0x019804ff, 0x070ff0f6,
-	0x074850ff, 0x05818500, 0x050f2074, 0x060a0007,
-	0x040070fb, 0x046a7007, 0x050f40ff, 0x013e4000,
-	0x06000020, 0x0678007a, 0x07fff000, 0x04818510,
-	0x0320000a, 0x022017d0, 0x02800513, 0x0320000a,
-	0x06301b58, 0x06000001, 0x050f8072, 0x032fa012,
-	0x0080041f, 0x01208060, 0x0600902a, 0x04002020,
-	0x02800526, 0x040080fb, 0x066ae108, 0x06009076,
-	0x04002075, 0x02800526, 0x03201100, 0x05848524,
-	0x06420001, 0x04818520, 0x0280053d, 0x020e0008,
-	0x07c00000, 0x050fd009, 0x040fd008, 0x03201100,
-	0x0584852d, 0x06420001, 0x04818529, 0x0280053d,
-	0x007a0102, 0x04000101, 0x05600809, 0x050f80ff,
-	0x073fa00a, 0x06000001, 0x020e0008, 0x06840537,
-	0x030e0009, 0x07c00000, 0x01011009, 0x052e4300,
-	0x07c00000, 0x052e400f, 0x01208090, 0x0280051f,
-	0x070fc0ff, 0x040f8013, 0x032fa009, 0x02800540,
-	0x6321d92e, 0xffef19a2
-};
-
-#ifdef UNIQUE_FW_NAME
-uint32_t fw2400_length02 = 0x0000165e ;
-#else
-uint32_t risc_code_length02 = 0x0000165e ;
-#endif
-
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index fee0c49..e96d58d 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -46,22 +46,16 @@
 	case 0:
 		if (ha->fw_dump_reading == 1) {
 			qla_printk(KERN_INFO, ha,
-			    "Firmware dump cleared on (%ld).\n",
-			    ha->host_no);
+			    "Firmware dump cleared on (%ld).\n", ha->host_no);
 
 			vfree(ha->fw_dump_buffer);
-			if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
-				free_pages((unsigned long)ha->fw_dump,
-				    ha->fw_dump_order);
-
-			ha->fw_dump_reading = 0;
 			ha->fw_dump_buffer = NULL;
-			ha->fw_dump = NULL;
+			ha->fw_dump_reading = 0;
 			ha->fw_dumped = 0;
 		}
 		break;
 	case 1:
-		if ((ha->fw_dump || ha->fw_dumped) && !ha->fw_dump_reading) {
+		if (ha->fw_dumped && !ha->fw_dump_reading) {
 			ha->fw_dump_reading = 1;
 
 			if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 2d9b12f..74e5471 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -28,7 +28,7 @@
 	uint16_t __iomem *dmp_reg;
 	unsigned long	flags;
 	struct qla2300_fw_dump	*fw;
-	uint32_t	dump_size, data_ram_cnt;
+	uint32_t	data_ram_cnt;
 
 	risc_address = data_ram_cnt = 0;
 	mb0 = mb2 = 0;
@@ -37,23 +37,16 @@
 	if (!hardware_locked)
 		spin_lock_irqsave(&ha->hardware_lock, flags);
 
-	if (ha->fw_dump != NULL) {
+	if (!ha->fw_dump) {
 		qla_printk(KERN_WARNING, ha,
-		    "Firmware has been previously dumped (%p) -- ignoring "
-		    "request...\n", ha->fw_dump);
+		    "No buffer available for dump!!!\n");
 		goto qla2300_fw_dump_failed;
 	}
 
-	/* Allocate (large) dump buffer. */
-	dump_size = sizeof(struct qla2300_fw_dump);
-	dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t);
-	ha->fw_dump_order = get_order(dump_size);
-	ha->fw_dump = (struct qla2300_fw_dump *) __get_free_pages(GFP_ATOMIC,
-	    ha->fw_dump_order);
-	if (ha->fw_dump == NULL) {
+	if (ha->fw_dumped) {
 		qla_printk(KERN_WARNING, ha,
-		    "Unable to allocated memory for firmware dump (%d/%d).\n",
-		    ha->fw_dump_order, dump_size);
+		    "Firmware has been previously dumped (%p) -- ignoring "
+		    "request...\n", ha->fw_dump);
 		goto qla2300_fw_dump_failed;
 	}
 	fw = ha->fw_dump;
@@ -358,17 +351,16 @@
 		}
 	}
 
-
 	if (rval != QLA_SUCCESS) {
 		qla_printk(KERN_WARNING, ha,
 		    "Failed to dump firmware (%x)!!!\n", rval);
+		ha->fw_dumped = 0;
 
-		free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order);
-		ha->fw_dump = NULL;
 	} else {
 		qla_printk(KERN_INFO, ha,
 		    "Firmware dump saved to temp buffer (%ld/%p).\n",
 		    ha->host_no, ha->fw_dump);
+		ha->fw_dumped = 1;
 	}
 
 qla2300_fw_dump_failed:
@@ -587,21 +579,16 @@
 	if (!hardware_locked)
 		spin_lock_irqsave(&ha->hardware_lock, flags);
 
-	if (ha->fw_dump != NULL) {
+	if (!ha->fw_dump) {
 		qla_printk(KERN_WARNING, ha,
-		    "Firmware has been previously dumped (%p) -- ignoring "
-		    "request...\n", ha->fw_dump);
+		    "No buffer available for dump!!!\n");
 		goto qla2100_fw_dump_failed;
 	}
 
-	/* Allocate (large) dump buffer. */
-	ha->fw_dump_order = get_order(sizeof(struct qla2100_fw_dump));
-	ha->fw_dump = (struct qla2100_fw_dump *) __get_free_pages(GFP_ATOMIC,
-	    ha->fw_dump_order);
-	if (ha->fw_dump == NULL) {
+	if (ha->fw_dumped) {
 		qla_printk(KERN_WARNING, ha,
-		    "Unable to allocated memory for firmware dump (%d/%Zd).\n",
-		    ha->fw_dump_order, sizeof(struct qla2100_fw_dump));
+		    "Firmware has been previously dumped (%p) -- ignoring "
+		    "request...\n", ha->fw_dump);
 		goto qla2100_fw_dump_failed;
 	}
 	fw = ha->fw_dump;
@@ -777,13 +764,13 @@
 	if (rval != QLA_SUCCESS) {
 		qla_printk(KERN_WARNING, ha,
 		    "Failed to dump firmware (%x)!!!\n", rval);
+		ha->fw_dumped = 0;
 
-		free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order);
-		ha->fw_dump = NULL;
 	} else {
 		qla_printk(KERN_INFO, ha,
 		    "Firmware dump saved to temp buffer (%ld/%p).\n",
 		    ha->host_no, ha->fw_dump);
+		ha->fw_dumped = 1;
 	}
 
 qla2100_fw_dump_failed:
@@ -988,7 +975,7 @@
 	if (!hardware_locked)
 		spin_lock_irqsave(&ha->hardware_lock, flags);
 
-	if (!ha->fw_dump24) {
+	if (!ha->fw_dump) {
 		qla_printk(KERN_WARNING, ha,
 		    "No buffer available for dump!!!\n");
 		goto qla24xx_fw_dump_failed;
@@ -997,10 +984,10 @@
 	if (ha->fw_dumped) {
 		qla_printk(KERN_WARNING, ha,
 		    "Firmware has been previously dumped (%p) -- ignoring "
-		    "request...\n", ha->fw_dump24);
+		    "request...\n", ha->fw_dump);
 		goto qla24xx_fw_dump_failed;
 	}
-	fw = (struct qla24xx_fw_dump *) ha->fw_dump24;
+	fw = ha->fw_dump;
 
 	rval = QLA_SUCCESS;
 	fw->host_status = RD_REG_DWORD(&reg->host_status);
@@ -1654,7 +1641,7 @@
 	} else {
 		qla_printk(KERN_INFO, ha,
 		    "Firmware dump saved to temp buffer (%ld/%p).\n",
-		    ha->host_no, ha->fw_dump24);
+		    ha->host_no, ha->fw_dump);
 		ha->fw_dumped = 1;
 	}
 
@@ -1672,7 +1659,7 @@
 	uint32_t ext_mem_cnt;
 
 	uiter = ha->fw_dump_buffer;
-	fw = ha->fw_dump24;
+	fw = ha->fw_dump;
 
 	qla_uprintf(&uiter, "ISP FW Version %d.%02d.%02d Attributes %04x\n",
 	    ha->fw_major_version, ha->fw_minor_version,
@@ -1995,7 +1982,6 @@
 		return;
 
 	printk("  sp flags=0x%x\n", sp->flags);
-	printk("  state=%d\n", sp->state);
 }
 
 void
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 53508f3..d6f6579 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -31,6 +31,8 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_transport_fc.h>
 
+#define QLA2XXX_DRIVER_NAME  "qla2xxx"
+
 /*
  * We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
  * but that's fine as we don't look at the last 24 ones for
@@ -189,22 +191,13 @@
 
 	struct scsi_cmnd *cmd;		/* Linux SCSI command pkt */
 
-	struct timer_list timer;	/* Command timer */
-	atomic_t ref_count;	/* Reference count for this structure */
 	uint16_t flags;
 
-	/* Request state */
-	uint16_t state;
-
 	/* Single transfer DMA context */
 	dma_addr_t dma_handle;
 
 	uint32_t request_sense_length;
 	uint8_t *request_sense_ptr;
-
-	/* SRB magic number */
-	uint16_t magic;
-#define SRB_MAGIC       0x10CB
 } srb_t;
 
 /*
@@ -226,21 +219,6 @@
 #define SRB_TAPE		BIT_11	/* FCP2 (Tape) command. */
 
 /*
- * SRB state definitions
- */
-#define SRB_FREE_STATE		0	/*   returned back */
-#define SRB_PENDING_STATE	1	/*   queued in LUN Q */
-#define SRB_ACTIVE_STATE	2	/*   in Active Array */
-#define SRB_DONE_STATE		3	/*   queued in Done Queue */
-#define SRB_RETRY_STATE		4	/*   in Retry Queue */
-#define SRB_SUSPENDED_STATE	5	/*   in suspended state */
-#define SRB_NO_QUEUE_STATE	6	/*   is in between states */
-#define SRB_ACTIVE_TIMEOUT_STATE 7	/*   in Active Array but timed out */
-#define SRB_FAILOVER_STATE	8	/*   in Failover Queue */
-#define SRB_SCSI_RETRY_STATE	9	/*   in Scsi Retry Queue */
-
-
-/*
  * ISP I/O Register Set structure definitions.
  */
 struct device_reg_2xxx {
@@ -270,6 +248,8 @@
 #define NVR_SELECT		BIT_1
 #define NVR_CLOCK		BIT_0
 
+#define NVR_WAIT_CNT		20000
+
 	union {
 		struct {
 			uint16_t mailbox0;
@@ -1514,62 +1494,6 @@
 } sw_info_t;
 
 /*
- * Inquiry command structure.
- */
-#define INQ_DATA_SIZE	36
-
-/*
- * Inquiry mailbox IOCB packet definition.
- */
-typedef struct {
-	union {
-		cmd_a64_entry_t cmd;
-		sts_entry_t rsp;
-		struct cmd_type_7 cmd24;
-		struct sts_entry_24xx rsp24;
-	} p;
-	uint8_t inq[INQ_DATA_SIZE];
-} inq_cmd_rsp_t;
-
-/*
- * Report LUN command structure.
- */
-#define CHAR_TO_SHORT(a, b)	(uint16_t)((uint8_t)b << 8 | (uint8_t)a)
-
-typedef struct {
-	uint32_t len;
-	uint32_t rsrv;
-} rpt_hdr_t;
-
-typedef struct {
-	struct {
-		uint8_t b : 6;
-		uint8_t address_method : 2;
-	} msb;
-	uint8_t lsb;
-	uint8_t unused[6];
-} rpt_lun_t;
-
-typedef struct {
-	rpt_hdr_t hdr;
-	rpt_lun_t lst[MAX_LUNS];
-} rpt_lun_lst_t;
-
-/*
- * Report Lun mailbox IOCB packet definition.
- */
-typedef struct {
-	union {
-		cmd_a64_entry_t cmd;
-		sts_entry_t rsp;
-		struct cmd_type_7 cmd24;
-		struct sts_entry_24xx rsp24;
-	} p;
-	rpt_lun_lst_t list;
-} rpt_lun_cmd_rsp_t;
-
-
-/*
  * Fibre channel port type.
  */
  typedef enum {
@@ -1587,7 +1511,6 @@
 typedef struct fc_port {
 	struct list_head list;
 	struct scsi_qla_host *ha;
-	struct scsi_qla_host *vis_ha;	/* only used when suspending lun */
 
 	uint8_t node_name[WWN_SIZE];
 	uint8_t port_name[WWN_SIZE];
@@ -1602,23 +1525,13 @@
 
 	unsigned int os_target_id;
 
-	uint16_t iodesc_idx_sent;
-
 	int port_login_retry_count;
 	int login_retry;
 	atomic_t port_down_timer;
 
-	uint8_t device_type;
-	uint8_t unused;
-
-	uint8_t mp_byte;		/* multi-path byte (not used) */
-    	uint8_t cur_path;		/* current path id */
-
 	spinlock_t rport_lock;
 	struct fc_rport *rport, *drport;
 	u32 supported_classes;
-	struct work_struct rport_add_work;
-	struct work_struct rport_del_work;
 } fc_port_t;
 
 /*
@@ -2027,54 +1940,6 @@
 	} p;
 };
 
-/* IO descriptors */
-#define MAX_IO_DESCRIPTORS	32
-
-#define ABORT_IOCB_CB		0
-#define ADISC_PORT_IOCB_CB	1
-#define LOGOUT_PORT_IOCB_CB	2
-#define LOGIN_PORT_IOCB_CB	3
-#define LAST_IOCB_CB		4
-
-#define IODESC_INVALID_INDEX	0xFFFF
-#define IODESC_ADISC_NEEDED	0xFFFE
-#define IODESC_LOGIN_NEEDED	0xFFFD
-
-struct io_descriptor {
-	uint16_t used:1;
-	uint16_t idx:11;
-	uint16_t cb_idx:4;
-
-	struct timer_list timer;
-
-	struct scsi_qla_host *ha;
-
-	port_id_t d_id;
-	fc_port_t *remote_fcport;
-
-	uint32_t signature;
-};
-
-struct qla_fw_info {
-	unsigned short addressing;	/* addressing method used to load fw */
-#define FW_INFO_ADDR_NORMAL	0
-#define FW_INFO_ADDR_EXTENDED	1
-#define FW_INFO_ADDR_NOMORE	0xffff
-	unsigned short *fwcode;		/* pointer to FW array */
-	unsigned short *fwlen;		/* number of words in array */
-	unsigned short *fwstart;	/* start address for F/W */
-	unsigned long *lfwstart;	/* start address (long) for F/W */
-};
-
-struct qla_board_info {
-	char *drv_name;
-
-	char isp_name[8];
-	struct qla_fw_info *fw_info;
-	char *fw_fname;
-	struct scsi_host_template *sht;
-};
-
 struct fw_blob {
 	char *name;
 	uint32_t segs[4];
@@ -2303,9 +2168,6 @@
 	uint32_t	current_outstanding_cmd;
 	srb_t		*status_srb;	/* Status continuation entry. */
 
-	uint16_t           revision;
-	uint8_t           ports;
-
 	/* ISP configuration data. */
 	uint16_t	loop_id;		/* Host adapter loop id */
 	uint16_t	fb_rev;
@@ -2361,10 +2223,6 @@
 
 	/* Fibre Channel Device List. */
 	struct list_head	fcports;
-	struct list_head	rscn_fcports;
-
-	struct io_descriptor	io_descriptors[MAX_IO_DESCRIPTORS];
-	uint16_t		iodesc_signature;
 
 	/* RSCN queue. */
 	uint32_t rscn_queue[MAX_RSCN_COUNT];
@@ -2395,9 +2253,6 @@
 	struct gid_list_info *gid_list;
 	int		gid_list_info_size;
 
-	dma_addr_t	rlc_rsp_dma;
-	rpt_lun_cmd_rsp_t *rlc_rsp;
-
 	/* Small DMA pool allocations -- maximum 256 bytes in length. */
 #define DMA_POOL_SIZE	256
 	struct dma_pool *s_dma_pool;
@@ -2406,9 +2261,6 @@
 	init_cb_t	*init_cb;
 	int		init_cb_size;
 
-	dma_addr_t	iodesc_pd_dma;
-	port_database_t *iodesc_pd;
-
 	/* These are used by mailbox operations. */
 	volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
 
@@ -2435,13 +2287,16 @@
 	mbx_cmd_t 	mc;
 
 	/* Basic firmware related information. */
-	struct qla_board_info	*brd_info;
 	uint16_t	fw_major_version;
 	uint16_t	fw_minor_version;
 	uint16_t	fw_subminor_version;
 	uint16_t	fw_attributes;
 	uint32_t	fw_memory_size;
 	uint32_t	fw_transfer_size;
+	uint32_t	fw_srisc_address;
+#define RISC_START_ADDRESS_2100 0x1000
+#define RISC_START_ADDRESS_2300 0x800
+#define RISC_START_ADDRESS_2400 0x100000
 
 	uint16_t	fw_options[16];		/* slots: 1,2,3,10,11 */
 	uint8_t		fw_seriallink_options[4];
@@ -2449,15 +2304,11 @@
 
 	/* Firmware dump information. */
 	void		*fw_dump;
-	int		fw_dump_order;
+	int		fw_dumped;
 	int		fw_dump_reading;
 	char		*fw_dump_buffer;
 	int		fw_dump_buffer_len;
 
-	int		fw_dumped;
-	void		*fw_dump24;
-	int		fw_dump24_len;
-
 	uint8_t		host_str[16];
 	uint32_t	pci_attr;
 
@@ -2503,8 +2354,6 @@
 	 test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
 	 atomic_read(&ha->loop_state) == LOOP_DOWN)
 
-#define TGT_Q(ha, t) (ha->otgt[t])
-
 #define to_qla_host(x)		((scsi_qla_host_t *) (x)->hostdata)
 
 #define qla_printk(level, ha, format, arg...) \
@@ -2537,19 +2386,6 @@
 #define QLA_RSCNS_HANDLED		0x108
 #define QLA_ALREADY_REGISTERED		0x109
 
-/*
-* Stat info for all adpaters
-*/
-struct _qla2x00stats  {
-        unsigned long   mboxtout;            /* mailbox timeouts */
-        unsigned long   mboxerr;             /* mailbox errors */
-        unsigned long   ispAbort;            /* ISP aborts */
-        unsigned long   debugNo;
-        unsigned long   loop_resync;
-        unsigned long   outarray_full;
-        unsigned long   retry_q_cnt;
-};
-
 #define NVRAM_DELAY()		udelay(10)
 
 #define INVALID_HANDLE	(MAX_OUTSTANDING_COMMANDS+1)
@@ -2565,12 +2401,6 @@
 #include "qla_dbg.h"
 #include "qla_inline.h"
 
-/*
-* String arrays
-*/
-#define LINESIZE    256
-#define MAXARGS      26
-
 #define CMD_SP(Cmnd)		((Cmnd)->SCp.ptr)
 #define CMD_COMPL_STATUS(Cmnd)  ((Cmnd)->SCp.this_residual)
 #define CMD_RESID_LEN(Cmnd)	((Cmnd)->SCp.buffers_residual)
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 1ee58ad..3af47866 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -7,7 +7,6 @@
 #ifndef __QLA_FW_H
 #define __QLA_FW_H
 
-#define RISC_SADDRESS		0x100000
 #define MBS_CHECKSUM_ERROR	0x4010
 
 /*
@@ -463,7 +462,7 @@
 	uint16_t comp_status;		/* Completion status. */
 	uint16_t ox_id;			/* OX_ID used by the firmware. */
 
-	uint32_t residual_len;		/* Residual transfer length. */
+	uint32_t residual_len;		/* FW calc residual transfer length. */
 
 	uint16_t reserved_1;
 	uint16_t state_flags;		/* State flags. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 91e83e2..164d53c 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -9,9 +9,6 @@
 
 #include <linux/interrupt.h>
 
-extern void qla2x00_remove_one(struct pci_dev *);
-extern int qla2x00_probe_one(struct pci_dev *, struct qla_board_info *);
-
 /*
  * Global Function Prototypes in qla_init.c source file.
  */
@@ -64,14 +61,11 @@
 extern int ql2xplogiabsentdevice;
 extern int ql2xloginretrycount;
 extern int ql2xfdmienable;
-extern int ql2xprocessrscn;
 
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
 extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
 
-extern void qla2x00_cmd_timeout(srb_t *);
-
 extern void qla2x00_mark_device_lost(scsi_qla_host_t *, fc_port_t *, int, int);
 extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
 
@@ -286,15 +280,6 @@
 extern int qla2x00_fdmi_register(scsi_qla_host_t *);
 
 /*
- * Global Function Prototypes in qla_rscn.c source file.
- */
-extern fc_port_t *qla2x00_alloc_rscn_fcport(scsi_qla_host_t *, gfp_t);
-extern int qla2x00_handle_port_rscn(scsi_qla_host_t *, uint32_t, fc_port_t *,
-    int);
-extern void qla2x00_process_iodesc(scsi_qla_host_t *, struct mbx_entry *);
-extern void qla2x00_cancel_io_descriptors(scsi_qla_host_t *);
-
-/*
  * Global Function Prototypes in qla_xioctl.c source file.
  */
 #define qla2x00_enqueue_aen(ha, cmd, mode)	do { } while (0)
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 89a3fc0..3d4487e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -194,7 +194,6 @@
 	mwi = 0;
 	if (pci_set_mwi(ha->pdev))
 		mwi = PCI_COMMAND_INVALIDATE;
-	pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision);
 
 	pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
 	w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
@@ -232,7 +231,6 @@
 	mwi = 0;
 	if (pci_set_mwi(ha->pdev))
 		mwi = PCI_COMMAND_INVALIDATE;
-	pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision);
 
 	pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
 	w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
@@ -320,7 +318,6 @@
 	mwi = 0;
 	if (pci_set_mwi(ha->pdev))
 		mwi = PCI_COMMAND_INVALIDATE;
-	pci_read_config_word(ha->pdev, PCI_REVISION_ID, &ha->revision);
 
 	pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
 	w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
@@ -386,9 +383,7 @@
 		qla_printk(KERN_INFO, ha, "RISC CODE NOT loaded\n");
 
 		/* Verify checksum of loaded RISC code. */
-		rval = qla2x00_verify_checksum(ha,
-		    IS_QLA24XX(ha) || IS_QLA54XX(ha) ? RISC_SADDRESS :
-		    *ha->brd_info->fw_info[0].fwstart);
+		rval = qla2x00_verify_checksum(ha, ha->fw_srisc_address);
 	}
 
 	if (rval) {
@@ -411,7 +406,6 @@
 	unsigned long   flags = 0;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 	uint32_t	cnt;
-	unsigned long	mbx_flags = 0;
 	uint16_t	cmd;
 
 	ha->isp_ops.disable_intrs(ha);
@@ -519,20 +513,8 @@
 
 	if (IS_QLA2100(ha) || IS_QLA2200(ha) || IS_QLA2300(ha)) {
 		for (cnt = 0; cnt < 30000; cnt++) {
-			if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)))
-				spin_lock_irqsave(&ha->mbx_reg_lock, mbx_flags);
-
-			if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY) {
-				if (!(test_bit(ABORT_ISP_ACTIVE,
-				    &ha->dpc_flags)))
-					spin_unlock_irqrestore(
-					    &ha->mbx_reg_lock, mbx_flags);
+			if (RD_MAILBOX_REG(ha, reg, 0) != MBS_BUSY)
 				break;
-			}
-
-			if (!(test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags)))
-				spin_unlock_irqrestore(&ha->mbx_reg_lock,
-				    mbx_flags);
 
 			udelay(100);
 		}
@@ -791,16 +773,26 @@
 static void
 qla2x00_alloc_fw_dump(scsi_qla_host_t *ha)
 {
+	uint32_t dump_size = 0;
+
 	ha->fw_dumped = 0;
-	ha->fw_dump24_len = sizeof(struct qla24xx_fw_dump);
-	ha->fw_dump24_len += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t);
-	ha->fw_dump24 = vmalloc(ha->fw_dump24_len);
-	if (ha->fw_dump24)
+	if (IS_QLA2100(ha) || IS_QLA2200(ha)) {
+		dump_size = sizeof(struct qla2100_fw_dump);
+	} else if (IS_QLA23XX(ha)) {
+		dump_size = sizeof(struct qla2300_fw_dump);
+		dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t);
+        } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
+		dump_size = sizeof(struct qla24xx_fw_dump);
+		dump_size += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t);
+	}
+
+	ha->fw_dump = vmalloc(dump_size);
+	if (ha->fw_dump)
 		qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware "
-		    "dump...\n", ha->fw_dump24_len / 1024);
+		    "dump...\n", dump_size / 1024);
 	else
 		qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for "
-		    "firmware dump!!!\n", ha->fw_dump24_len / 1024);
+		    "firmware dump!!!\n", dump_size / 1024);
 }
 
 /**
@@ -818,13 +810,12 @@
 	dma_addr_t request_dma;
 	request_t *request_ring;
 
+	qla2x00_alloc_fw_dump(ha);
+
 	/* Valid only on recent ISPs. */
 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 		return;
 
-	if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
-		qla2x00_alloc_fw_dump(ha);
-
 	/* Retrieve IOCB counts available to the firmware. */
 	rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt);
 	if (rval)
@@ -1545,6 +1536,12 @@
 	while (cnt--)
 		*dptr1++ = *dptr2++;
 
+	/* Use alternate WWN? */
+	if (nv->host_p[1] & BIT_7) {
+		memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
+		memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
+	}
+
 	/* Prepare nodename */
 	if ((icb->firmware_options[1] & BIT_6) == 0) {
 		/*
@@ -1682,14 +1679,6 @@
 }
 
 static void
-qla2x00_rport_add(void *data)
-{
-	fc_port_t *fcport = data;
-
-	qla2x00_reg_remote_port(fcport->ha, fcport);
-}
-
-static void
 qla2x00_rport_del(void *data)
 {
 	fc_port_t *fcport = data;
@@ -1726,13 +1715,10 @@
 	fcport->ha = ha;
 	fcport->port_type = FCT_UNKNOWN;
 	fcport->loop_id = FC_NO_LOOP_ID;
-	fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
 	atomic_set(&fcport->state, FCS_UNCONFIGURED);
 	fcport->flags = FCF_RLC_SUPPORT;
 	fcport->supported_classes = FC_COS_UNSPECIFIED;
 	spin_lock_init(&fcport->rport_lock);
-	INIT_WORK(&fcport->rport_add_work, qla2x00_rport_add, fcport);
-	INIT_WORK(&fcport->rport_del_work, qla2x00_rport_del, fcport);
 
 	return (fcport);
 }
@@ -1792,6 +1778,9 @@
 		set_bit(RSCN_UPDATE, &flags);
 		clear_bit(LOCAL_LOOP_UPDATE, &flags);
 
+	} else if (ha->current_topology == ISP_CFG_N) {
+		clear_bit(RSCN_UPDATE, &flags);
+
 	} else if (!ha->flags.online ||
 	    (test_bit(ABORT_ISP_ACTIVE, &flags))) {
 
@@ -2055,10 +2044,6 @@
 	    PORT_RETRY_TIME);
 	fcport->flags &= ~FCF_LOGIN_NEEDED;
 
-	if (fcport->port_type == FCT_INITIATOR ||
-	    fcport->port_type == FCT_BROADCAST)
-		fcport->device_type = TYPE_PROCESSOR;
-
 	atomic_set(&fcport->state, FCS_ONLINE);
 
 	if (ha->flags.init_done)
@@ -2273,8 +2258,7 @@
 			}
 
 			/* Remove device from the new list and add it to DB */
-			list_del(&fcport->list);
-			list_add_tail(&fcport->list, &ha->fcports);
+			list_move_tail(&fcport->list, &ha->fcports);
 
 			/* Login and update database */
 			qla2x00_fabric_dev_login(ha, fcport, &next_loopid);
@@ -2587,7 +2571,6 @@
 qla2x00_device_resync(scsi_qla_host_t *ha)
 {
 	int	rval;
-	int	rval2;
 	uint32_t mask;
 	fc_port_t *fcport;
 	uint32_t rscn_entry;
@@ -2643,17 +2626,6 @@
 
 		switch (format) {
 		case 0:
-			if (ql2xprocessrscn &&
-			    !IS_QLA2100(ha) && !IS_QLA2200(ha) &&
-			    !IS_QLA6312(ha) && !IS_QLA6322(ha) &&
-			    !IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
-			    ha->flags.init_done) {
-				/* Handle port RSCN via asyncronous IOCBs */
-				rval2 = qla2x00_handle_port_rscn(ha, rscn_entry,
-				    NULL, 0);
-				if (rval2 == QLA_SUCCESS)
-					continue;
-			}
 			mask = 0xffffff;
 			break;
 		case 1:
@@ -2671,10 +2643,6 @@
 
 		rval = QLA_SUCCESS;
 
-		/* Abort any outstanding IO descriptors. */
-		if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
-			qla2x00_cancel_io_descriptors(ha);
-
 		list_for_each_entry(fcport, &ha->fcports, list) {
 			if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 ||
 			    (fcport->d_id.b24 & mask) != d_id.b24 ||
@@ -3383,8 +3351,14 @@
 	} else
 		strcpy(ha->model_number, "QLA2462");
 
+	/* Use alternate WWN? */
+	if (nv->host_p & __constant_cpu_to_le32(BIT_15)) {
+		memcpy(icb->node_name, nv->alternate_node_name, WWN_SIZE);
+		memcpy(icb->port_name, nv->alternate_port_name, WWN_SIZE);
+	}
+
 	/* Prepare nodename */
-	if ((icb->firmware_options_1 & BIT_14) == 0) {
+	if ((icb->firmware_options_1 & __constant_cpu_to_le32(BIT_14)) == 0) {
 		/*
 		 * Firmware will apply the following mask if the nodename was
 		 * not provided.
@@ -3400,8 +3374,8 @@
 	ha->flags.enable_target_reset = 1;
 	ha->flags.enable_led_scheme = 0;
 
-	ha->operating_mode =
-	    (icb->firmware_options_2 & (BIT_6 | BIT_5 | BIT_4)) >> 4;
+	ha->operating_mode = (le32_to_cpu(icb->firmware_options_2) &
+	    (BIT_6 | BIT_5 | BIT_4)) >> 4;
 
 	memcpy(ha->fw_seriallink_options24, nv->seriallink_options,
 	    sizeof(ha->fw_seriallink_options24));
@@ -3498,133 +3472,6 @@
 	return (rval);
 }
 
-#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
-
-int
-qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
-{
-	int	rval, num, i;
-	uint32_t cnt;
-	uint16_t *risc_code;
-	uint32_t risc_addr, risc_size;
-	uint16_t *req_ring;
-	struct qla_fw_info *fw_iter;
-
-	rval = QLA_SUCCESS;
-
-	/* Load firmware sequences */
-	fw_iter = ha->brd_info->fw_info;
-	*srisc_addr = *ha->brd_info->fw_info->fwstart;
-	while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
-		risc_code = fw_iter->fwcode;
-		risc_size = *fw_iter->fwlen;
-		if (fw_iter->addressing == FW_INFO_ADDR_NORMAL)
-			risc_addr = *fw_iter->fwstart;
-		else
-			risc_addr = *fw_iter->lfwstart;
-
-		num = 0;
-		rval = 0;
-		while (risc_size > 0 && !rval) {
-			cnt = (uint16_t)(ha->fw_transfer_size >> 1);
-			if (cnt > risc_size)
-				cnt = risc_size;
-
-			DEBUG7(printk("scsi(%ld): Loading risc segment@ "
-			    "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
-			    ha->host_no, risc_code, cnt, risc_addr));
-
-			req_ring = (uint16_t *)ha->request_ring;
-			for (i = 0; i < cnt; i++)
-				req_ring[i] = cpu_to_le16(risc_code[i]);
-
-			rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
-			    cnt);
-			if (rval) {
-				DEBUG(printk("scsi(%ld): [ERROR] Failed to "
-				    "load segment %d of firmware\n",
-				    ha->host_no, num));
-				qla_printk(KERN_WARNING, ha,
-				    "[ERROR] Failed to load segment %d of "
-				    "firmware\n", num);
-
-				qla2x00_dump_regs(ha);
-				break;
-			}
-
-			risc_code += cnt;
-			risc_addr += cnt;
-			risc_size -= cnt;
-			num++;
-		}
-
-		/* Next firmware sequence */
-		fw_iter++;
-	}
-	return rval;
-}
-
-int
-qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
-{
-	int	rval, num, i;
-	uint32_t cnt;
-	uint32_t *risc_code;
-	uint32_t risc_addr, risc_size;
-	uint32_t *req_ring;
-	struct qla_fw_info *fw_iter;
-
-	rval = QLA_SUCCESS;
-
-	/* Load firmware sequences */
-	fw_iter = ha->brd_info->fw_info;
-	*srisc_addr = *((uint32_t *)fw_iter->lfwstart);
-	while (fw_iter->addressing != FW_INFO_ADDR_NOMORE) {
-		risc_code = (uint32_t *)fw_iter->fwcode;
-		risc_size = *((uint32_t *)fw_iter->fwlen);
-		risc_addr = *((uint32_t *)fw_iter->lfwstart);
-
-		num = 0;
-		rval = 0;
-		while (risc_size > 0 && !rval) {
-			cnt = (uint32_t)(ha->fw_transfer_size >> 2);
-			if (cnt > risc_size)
-				cnt = risc_size;
-
-			DEBUG7(printk("scsi(%ld): Loading risc segment@ "
-			    "addr %p, number of bytes 0x%x, offset 0x%lx.\n",
-			    ha->host_no, risc_code, cnt, risc_addr));
-
-			req_ring = (uint32_t *)ha->request_ring;
-			for (i = 0; i < cnt; i++)
-				req_ring[i] = cpu_to_le32(risc_code[i]);
-
-			rval = qla2x00_load_ram(ha, ha->request_dma, risc_addr,
-			    cnt);
-			if (rval) {
-				DEBUG(printk("scsi(%ld): [ERROR] Failed to "
-				    "load segment %d of firmware\n",
-				    ha->host_no, num));
-				qla_printk(KERN_WARNING, ha,
-				    "[ERROR] Failed to load segment %d of "
-				    "firmware\n", num);
-
-				qla2x00_dump_regs(ha);
-				break;
-			}
-
-			risc_code += cnt;
-			risc_addr += cnt;
-			risc_size -= cnt;
-			num++;
-		}
-
-		/* Next firmware sequence */
-		fw_iter++;
-	}
-	return rval;
-}
-
 int
 qla24xx_load_risc_flash(scsi_qla_host_t *ha, uint32_t *srisc_addr)
 {
@@ -3707,7 +3554,7 @@
 	return rval;
 }
 
-#else	/* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
+#define QLA_FW_URL "ftp://ftp.qlogic.com/outgoing/linux/firmware/"
 
 int
 qla2x00_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr)
@@ -3722,6 +3569,8 @@
 	blob = qla2x00_request_firmware(ha);
 	if (!blob) {
 		qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
+		qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
+		    "from: " QLA_FW_URL ".\n");
 		return QLA_FUNCTION_FAILED;
 	}
 
@@ -3823,7 +3672,13 @@
 	blob = qla2x00_request_firmware(ha);
 	if (!blob) {
 		qla_printk(KERN_ERR, ha, "Firmware image unavailable.\n");
-		return QLA_FUNCTION_FAILED;
+		qla_printk(KERN_ERR, ha, "Firmware images can be retrieved "
+		    "from: " QLA_FW_URL ".\n");
+
+		/* Try to load RISC code from flash. */
+		qla_printk(KERN_ERR, ha, "Attempting to load (potentially "
+		    "outdated) firmware from flash.\n");
+		return qla24xx_load_risc_flash(ha, srisc_addr);
 	}
 
 	rval = QLA_SUCCESS;
@@ -3909,4 +3764,3 @@
 fail_fw_integrity:
 	return QLA_FUNCTION_FAILED;
 }
-#endif
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 8f0f4a2..8c769cf 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -408,7 +408,6 @@
 		ha->request_ring_ptr++;
 
 	sp->flags |= SRB_DMA_VALID;
-	sp->state = SRB_ACTIVE_STATE;
 
 	/* Set chip new ring index. */
 	WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index);
@@ -838,7 +837,6 @@
 		ha->request_ring_ptr++;
 
 	sp->flags |= SRB_DMA_VALID;
-	sp->state = SRB_ACTIVE_STATE;
 
 	/* Set chip new ring index. */
 	WRT_REG_DWORD(&reg->req_q_in, ha->req_ring_index);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 2003dbb..b28ac0a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -515,47 +515,6 @@
 
 	case MBA_PORT_UPDATE:		/* Port database update */
 		/*
-		 * If a single remote port just logged into (or logged out of)
-		 * us, create a new entry in our rscn fcports list and handle
-		 * the event like an RSCN.
-		 */
-		if (ql2xprocessrscn &&
-		    !IS_QLA2100(ha) && !IS_QLA2200(ha) && !IS_QLA6312(ha) &&
-		    !IS_QLA6322(ha) && !IS_QLA24XX(ha) && !IS_QLA54XX(ha) &&
-		    ha->flags.init_done && mb[1] != 0xffff &&
-		    ((ha->operating_mode == P2P && mb[1] != 0) ||
-		    (ha->operating_mode != P2P && mb[1] !=
-			SNS_FIRST_LOOP_ID)) && (mb[2] == 6 || mb[2] == 7)) {
-			int rval;
-			fc_port_t *rscn_fcport;
-
-			/* Create new fcport for login. */
-			rscn_fcport = qla2x00_alloc_rscn_fcport(ha, GFP_ATOMIC);
-			if (rscn_fcport) {
-				DEBUG14(printk("scsi(%ld): Port Update -- "
-				    "creating RSCN fcport %p for %x/%x/%x.\n",
-				    ha->host_no, rscn_fcport, mb[1], mb[2],
-				    mb[3]));
-
-				rscn_fcport->loop_id = mb[1];
-				rscn_fcport->d_id.b24 = INVALID_PORT_ID;
-				atomic_set(&rscn_fcport->state,
-				    FCS_DEVICE_LOST);
-				list_add_tail(&rscn_fcport->list,
-				    &ha->rscn_fcports);
-
-				rval = qla2x00_handle_port_rscn(ha, 0,
-				    rscn_fcport, 1);
-				if (rval == QLA_SUCCESS)
-					break;
-			} else {
-				DEBUG14(printk("scsi(%ld): Port Update -- "
-				    "-- unable to allocate RSCN fcport "
-				    "login.\n", ha->host_no));
-			}
-		}
-
-		/*
 		 * If PORT UPDATE is global (recieved LIP_OCCURED/LIP_RESET
 		 * event etc. earlier indicating loop is down) then process
 		 * it.  Otherwise ignore it and Wait for RSCN to come in.
@@ -753,25 +712,6 @@
 		case MS_IOCB_TYPE:
 			qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
 			break;
-		case MBX_IOCB_TYPE:
-			if (!IS_QLA2100(ha) && !IS_QLA2200(ha) &&
-			    !IS_QLA6312(ha) && !IS_QLA6322(ha)) {
-				if (pkt->sys_define == SOURCE_ASYNC_IOCB) {
-					qla2x00_process_iodesc(ha,
-					    (struct mbx_entry *)pkt);
-				} else {
-					/* MBX IOCB Type Not Supported. */
-					DEBUG4(printk(KERN_WARNING
-					    "scsi(%ld): Received unknown MBX "
-					    "IOCB response pkt type=%x "
-					    "source=%x entry status=%x.\n",
-					    ha->host_no, pkt->entry_type,
-					    pkt->sys_define,
-					    pkt->entry_status));
-				}
-				break;
-			}
-			/* Fallthrough. */
 		default:
 			/* Type Not Supported. */
 			DEBUG4(printk(KERN_WARNING
@@ -805,7 +745,7 @@
 	uint16_t	scsi_status;
 	uint8_t		lscsi_status;
 	int32_t		resid;
-	uint32_t	sense_len, rsp_info_len, resid_len;
+	uint32_t	sense_len, rsp_info_len, resid_len, fw_resid_len;
 	uint8_t		*rsp_info, *sense_data;
 
 	sts = (sts_entry_t *) pkt;
@@ -844,8 +784,7 @@
 	cp = sp->cmd;
 	if (cp == NULL) {
 		DEBUG2(printk("scsi(%ld): Command already returned back to OS "
-		    "pkt->handle=%d sp=%p sp->state:%d\n",
-		    ha->host_no, sts->handle, sp, sp->state));
+		    "pkt->handle=%d sp=%p.\n", ha->host_no, sts->handle, sp));
 		qla_printk(KERN_WARNING, ha,
 		    "Command is NULL: already returned to OS (sp=%p)\n", sp);
 
@@ -859,11 +798,12 @@
 
 	fcport = sp->fcport;
 
-	sense_len = rsp_info_len = resid_len = 0;
+	sense_len = rsp_info_len = resid_len = fw_resid_len = 0;
 	if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) {
 		sense_len = le32_to_cpu(sts24->sense_len);
 		rsp_info_len = le32_to_cpu(sts24->rsp_data_len);
 		resid_len = le32_to_cpu(sts24->rsp_residual_count);
+		fw_resid_len = le32_to_cpu(sts24->residual_len);
 		rsp_info = sts24->data;
 		sense_data = sts24->data;
 		host_to_fcp_swap(sts24->data, sizeof(sts24->data));
@@ -963,14 +903,21 @@
 
 	case CS_DATA_UNDERRUN:
 		resid = resid_len;
+		/* Use F/W calculated residual length. */
+		if (IS_QLA24XX(ha) || IS_QLA54XX(ha))
+			resid = fw_resid_len;
+
 		if (scsi_status & SS_RESIDUAL_UNDER) {
 			cp->resid = resid;
 			CMD_RESID_LEN(cp) = resid;
 		} else {
 			DEBUG2(printk(KERN_INFO
 			    "scsi(%ld:%d:%d) UNDERRUN status detected "
-			    "0x%x-0x%x.\n", ha->host_no, cp->device->id,
-			    cp->device->lun, comp_status, scsi_status));
+			    "0x%x-0x%x. resid=0x%x fw_resid=0x%x cdb=0x%x "
+			    "os_underflow=0x%x\n", ha->host_no,
+			    cp->device->id, cp->device->lun, comp_status,
+			    scsi_status, resid_len, resid, cp->cmnd[0],
+			    cp->underflow));
 
 		}
 
@@ -1181,7 +1128,7 @@
 		cp = sp->cmd;
 		if (cp == NULL) {
 			DEBUG2(printk("%s(): Cmd already returned back to OS "
-			    "sp=%p sp->state:%d\n", __func__, sp, sp->state));
+			    "sp=%p.\n", __func__, sp));
 			qla_printk(KERN_INFO, ha,
 			    "cmd is NULL: already returned to OS (sp=%p)\n",
 			    sp);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 584fe5d..ccaad0b 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -54,13 +54,6 @@
 MODULE_PARM_DESC(ql2xloginretrycount,
 		"Specify an alternate value for the NVRAM login retry count.");
 
-#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
-int ql2xfwloadflash;
-module_param(ql2xfwloadflash, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ql2xfwloadflash,
-		"Load ISP24xx firmware image from FLASH (onboard memory).");
-#endif
-
 static void qla2x00_free_device(scsi_qla_host_t *);
 
 static void qla2x00_config_dma_addressing(scsi_qla_host_t *ha);
@@ -71,12 +64,6 @@
 		"Enables FDMI registratons "
 		"Default is 0 - no FDMI. 1 - perfom FDMI.");
 
-int ql2xprocessrscn;
-module_param(ql2xprocessrscn, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ql2xprocessrscn,
-		"Option to enable port RSCN handling via a series of less"
-		"fabric intrusive ADISCs and PLOGIs.");
-
 /*
  * SCSI host template entry points
  */
@@ -99,7 +86,7 @@
 
 static struct scsi_host_template qla2x00_driver_template = {
 	.module			= THIS_MODULE,
-	.name			= "qla2xxx",
+	.name			= QLA2XXX_DRIVER_NAME,
 	.queuecommand		= qla2x00_queuecommand,
 
 	.eh_abort_handler	= qla2xxx_eh_abort,
@@ -128,7 +115,7 @@
 
 static struct scsi_host_template qla24xx_driver_template = {
 	.module			= THIS_MODULE,
-	.name			= "qla2xxx",
+	.name			= QLA2XXX_DRIVER_NAME,
 	.queuecommand		= qla24xx_queuecommand,
 
 	.eh_abort_handler	= qla2xxx_eh_abort,
@@ -340,7 +327,6 @@
 	if (!sp)
 		return sp;
 
-	atomic_set(&sp->ref_count, 1);
 	sp->ha = ha;
 	sp->fcport = fcport;
 	sp->cmd = cmd;
@@ -577,6 +563,10 @@
 	while ((!atomic_read(&ha->loop_down_timer) &&
 	    atomic_read(&ha->loop_state) == LOOP_DOWN) ||
 	    atomic_read(&ha->loop_state) != LOOP_READY) {
+		if (atomic_read(&ha->loop_state) == LOOP_DEAD) {
+			return_status = QLA_FUNCTION_FAILED;
+			break;
+		}
 		msleep(1000);
 		if (time_after_eq(jiffies, loop_timeout)) {
 			return_status = QLA_FUNCTION_FAILED;
@@ -632,9 +622,8 @@
 		if (sp->cmd != cmd)
 			continue;
 
-		DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld "
-		    "sp->state=%x\n", __func__, ha->host_no, sp, serial,
-		    sp->state));
+		DEBUG2(printk("%s(%ld): aborting sp %p from RISC. pid=%ld.\n",
+		    __func__, ha->host_no, sp, serial));
 		DEBUG3(qla2x00_print_scsi_cmd(cmd);)
 
 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -1157,18 +1146,22 @@
 	case PCI_DEVICE_ID_QLOGIC_ISP2100:
 		ha->device_type |= DT_ISP2100;
 		ha->device_type &= ~DT_EXTENDED_IDS;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP2200:
 		ha->device_type |= DT_ISP2200;
 		ha->device_type &= ~DT_EXTENDED_IDS;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2100;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP2300:
 		ha->device_type |= DT_ISP2300;
 		ha->device_type |= DT_ZIO_SUPPORTED;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP2312:
 		ha->device_type |= DT_ISP2312;
 		ha->device_type |= DT_ZIO_SUPPORTED;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP2322:
 		ha->device_type |= DT_ISP2322;
@@ -1176,26 +1169,33 @@
 		if (ha->pdev->subsystem_vendor == 0x1028 &&
 		    ha->pdev->subsystem_device == 0x0170)
 			ha->device_type |= DT_OEM_001;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP6312:
 		ha->device_type |= DT_ISP6312;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP6322:
 		ha->device_type |= DT_ISP6322;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2300;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP2422:
 		ha->device_type |= DT_ISP2422;
 		ha->device_type |= DT_ZIO_SUPPORTED;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP2432:
 		ha->device_type |= DT_ISP2432;
 		ha->device_type |= DT_ZIO_SUPPORTED;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP5422:
 		ha->device_type |= DT_ISP5422;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
 		break;
 	case PCI_DEVICE_ID_QLOGIC_ISP5432:
 		ha->device_type |= DT_ISP5432;
+		ha->fw_srisc_address = RISC_START_ADDRESS_2400;
 		break;
 	}
 }
@@ -1242,7 +1242,7 @@
 		goto iospace_error_exit;
 	}
 
-	if (pci_request_regions(ha->pdev, ha->brd_info->drv_name)) {
+	if (pci_request_regions(ha->pdev, QLA2XXX_DRIVER_NAME)) {
 		qla_printk(KERN_WARNING, ha,
 		    "Failed to reserve PIO/MMIO regions (%s)\n",
 		    pci_name(ha->pdev));
@@ -1324,7 +1324,7 @@
 /*
  * PCI driver interface
  */
-int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
+static int qla2x00_probe_one(struct pci_dev *pdev)
 {
 	int	ret = -ENODEV;
 	device_reg_t __iomem *reg;
@@ -1358,8 +1358,7 @@
 	ha->pdev = pdev;
 	ha->host = host;
 	ha->host_no = host->host_no;
-	ha->brd_info = brd_info;
-	sprintf(ha->host_str, "%s_%ld", ha->brd_info->drv_name, ha->host_no);
+	sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no);
 
 	/* Set ISP-type information. */
 	qla2x00_set_isp_flags(ha);
@@ -1376,7 +1375,6 @@
 	spin_lock_init(&ha->hardware_lock);
 
 	ha->prev_topology = 0;
-	ha->ports = MAX_BUSES;
 	ha->init_cb_size = sizeof(init_cb_t);
 	ha->mgmt_svr_loop_id = MANAGEMENT_SERVER;
 	ha->link_data_rate = LDR_UNKNOWN;
@@ -1457,10 +1455,6 @@
 		ha->isp_ops.nvram_config = qla24xx_nvram_config;
 		ha->isp_ops.update_fw_options = qla24xx_update_fw_options;
 		ha->isp_ops.load_risc = qla24xx_load_risc;
-#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
-		if (ql2xfwloadflash)
-			ha->isp_ops.load_risc = qla24xx_load_risc_flash;
-#endif
 		ha->isp_ops.pci_info_str = qla24xx_pci_info_str;
 		ha->isp_ops.fw_version_str = qla24xx_fw_version_str;
 		ha->isp_ops.intr_handler = qla24xx_intr_handler;
@@ -1494,7 +1488,6 @@
 
 	INIT_LIST_HEAD(&ha->list);
 	INIT_LIST_HEAD(&ha->fcports);
-	INIT_LIST_HEAD(&ha->rscn_fcports);
 
 	/*
 	 * These locks are used to prevent more than one CPU
@@ -1543,12 +1536,12 @@
 	host->cmd_per_lun = 3;
 	host->unique_id = ha->instance;
 	host->max_cmd_len = MAX_CMDSZ;
-	host->max_channel = ha->ports - 1;
+	host->max_channel = MAX_BUSES - 1;
 	host->max_lun = MAX_LUNS;
 	host->transportt = qla2xxx_transport_template;
 
 	ret = request_irq(pdev->irq, ha->isp_ops.intr_handler,
-	    SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
+	    SA_INTERRUPT|SA_SHIRQ, QLA2XXX_DRIVER_NAME, ha);
 	if (ret) {
 		qla_printk(KERN_WARNING, ha,
 		    "Failed to reserve interrupt %d already in use.\n",
@@ -1646,9 +1639,8 @@
 probe_out:
 	return ret;
 }
-EXPORT_SYMBOL_GPL(qla2x00_probe_one);
 
-void qla2x00_remove_one(struct pci_dev *pdev)
+static void qla2x00_remove_one(struct pci_dev *pdev)
 {
 	scsi_qla_host_t *ha;
 
@@ -1666,15 +1658,10 @@
 
 	pci_set_drvdata(pdev, NULL);
 }
-EXPORT_SYMBOL_GPL(qla2x00_remove_one);
 
 static void
 qla2x00_free_device(scsi_qla_host_t *ha)
 {
-	/* Abort any outstanding IO descriptors. */
-	if (!IS_QLA2100(ha) && !IS_QLA2200(ha))
-		qla2x00_cancel_io_descriptors(ha);
-
 	/* Disable timer */
 	if (ha->timer_active)
 		qla2x00_stop_timer(ha);
@@ -1884,19 +1871,8 @@
 			continue;
 		}
 
-		ha->rlc_rsp = dma_alloc_coherent(&ha->pdev->dev,
-		    sizeof(rpt_lun_cmd_rsp_t), &ha->rlc_rsp_dma, GFP_KERNEL);
-		if (ha->rlc_rsp == NULL) {
-			qla_printk(KERN_WARNING, ha,
-				"Memory Allocation failed - rlc");
-
-			qla2x00_mem_free(ha);
-			msleep(100);
-
-			continue;
-		}
-
-		snprintf(name, sizeof(name), "qla2xxx_%ld", ha->host_no);
+		snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME,
+		    ha->host_no);
 		ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev,
 		    DMA_POOL_SIZE, 8, 0);
 		if (ha->s_dma_pool == NULL) {
@@ -1923,21 +1899,6 @@
 		}
 		memset(ha->init_cb, 0, ha->init_cb_size);
 
-		/* Get consistent memory allocated for Get Port Database cmd */
-		ha->iodesc_pd = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
-		    &ha->iodesc_pd_dma);
-		if (ha->iodesc_pd == NULL) {
-			/* error */
-			qla_printk(KERN_WARNING, ha,
-			    "Memory Allocation failed - iodesc_pd\n");
-
-			qla2x00_mem_free(ha);
-			msleep(100);
-
-			continue;
-		}
-		memset(ha->iodesc_pd, 0, PORT_DATABASE_SIZE);
-
 		/* Allocate ioctl related memory. */
 		if (qla2x00_alloc_ioctl_mem(ha)) {
 			qla_printk(KERN_WARNING, ha,
@@ -2062,20 +2023,12 @@
 	if (ha->ms_iocb)
 		dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
 
-	if (ha->iodesc_pd)
-		dma_pool_free(ha->s_dma_pool, ha->iodesc_pd, ha->iodesc_pd_dma);
-
 	if (ha->init_cb)
 		dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma);
 
 	if (ha->s_dma_pool)
 		dma_pool_destroy(ha->s_dma_pool);
 
-	if (ha->rlc_rsp)
-		dma_free_coherent(&ha->pdev->dev,
-		    sizeof(rpt_lun_cmd_rsp_t), ha->rlc_rsp,
-		    ha->rlc_rsp_dma);
-
 	if (ha->gid_list)
 		dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
 		    ha->gid_list_dma);
@@ -2096,15 +2049,11 @@
 	ha->ct_sns_dma = 0;
 	ha->ms_iocb = NULL;
 	ha->ms_iocb_dma = 0;
-	ha->iodesc_pd = NULL;
-	ha->iodesc_pd_dma = 0;
 	ha->init_cb = NULL;
 	ha->init_cb_dma = 0;
 
 	ha->s_dma_pool = NULL;
 
-	ha->rlc_rsp = NULL;
-	ha->rlc_rsp_dma = 0;
 	ha->gid_list = NULL;
 	ha->gid_list_dma = 0;
 
@@ -2122,15 +2071,10 @@
 	}
 	INIT_LIST_HEAD(&ha->fcports);
 
-	if (ha->fw_dump)
-		free_pages((unsigned long)ha->fw_dump, ha->fw_dump_order);
-
-	vfree(ha->fw_dump24);
-
+	vfree(ha->fw_dump);
 	vfree(ha->fw_dump_buffer);
 
 	ha->fw_dump = NULL;
-	ha->fw_dump24 = NULL;
 	ha->fw_dumped = 0;
 	ha->fw_dump_reading = 0;
 	ha->fw_dump_buffer = NULL;
@@ -2148,8 +2092,6 @@
  *
  * Context:
  *      Kernel context.
- *
- * Note: Sets the ref_count for non Null sp to one.
  */
 static int
 qla2x00_allocate_sp_pool(scsi_qla_host_t *ha)
@@ -2593,14 +2535,6 @@
 	return -ETIMEDOUT;
 }
 
-#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
-
-#define qla2x00_release_firmware()	do { } while (0)
-#define qla2x00_pci_module_init()	(0)
-#define qla2x00_pci_module_exit()	do { } while (0)
-
-#else	/* !defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE) */
-
 /* Firmware interface routines. */
 
 #define FW_BLOBS	5
@@ -2667,33 +2601,18 @@
 	up(&qla_fw_lock);
 }
 
-static struct qla_board_info qla_board_tbl = {
-	.drv_name       = "qla2xxx",
-};
-
 static struct pci_device_id qla2xxx_pci_tbl[] = {
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432,
-		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2300) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2312) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2322) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6312) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP6322) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2422) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2432) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5422) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP5432) },
 	{ 0 },
 };
 MODULE_DEVICE_TABLE(pci, qla2xxx_pci_tbl);
@@ -2701,7 +2620,7 @@
 static int __devinit
 qla2xxx_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	return qla2x00_probe_one(pdev, &qla_board_tbl);
+	return qla2x00_probe_one(pdev);
 }
 
 static void __devexit
@@ -2711,7 +2630,7 @@
 }
 
 static struct pci_driver qla2xxx_pci_driver = {
-	.name		= "qla2xxx",
+	.name		= QLA2XXX_DRIVER_NAME,
 	.driver		= {
 		.owner		= THIS_MODULE,
 	},
@@ -2732,8 +2651,6 @@
 	pci_unregister_driver(&qla2xxx_pci_driver);
 }
 
-#endif
-
 /**
  * qla2x00_module_init - Module initialization.
  **/
@@ -2753,9 +2670,6 @@
 
 	/* Derive version string. */
 	strcpy(qla2x00_version_str, QLA2XXX_VERSION);
-#if defined(CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE)
-	strcat(qla2x00_version_str, "-fw");
-#endif
 #if DEBUG_QLA2100
 	strcat(qla2x00_version_str, "-debug");
 #endif
diff --git a/drivers/scsi/qla2xxx/qla_rscn.c b/drivers/scsi/qla2xxx/qla_rscn.c
deleted file mode 100644
index b70bebe..0000000
--- a/drivers/scsi/qla2xxx/qla_rscn.c
+++ /dev/null
@@ -1,1426 +0,0 @@
-/*
- * QLogic Fibre Channel HBA Driver
- * Copyright (c)  2003-2005 QLogic Corporation
- *
- * See LICENSE.qla2xxx for copyright and licensing details.
- */
-#include "qla_def.h"
-
-/**
- * IO descriptor handle definitions.
- *
- * Signature form:
- *
- *	|31------28|27-------------------12|11-------0|
- *	|   Type   |   Rolling Signature   |   Index  |
- *	|----------|-----------------------|----------|
- *
- **/
-
-#define HDL_TYPE_SCSI		0
-#define HDL_TYPE_ASYNC_IOCB	0x0A
-
-#define HDL_INDEX_BITS	12
-#define HDL_ITER_BITS	16
-#define HDL_TYPE_BITS	4
-
-#define HDL_INDEX_MASK	((1UL << HDL_INDEX_BITS) - 1)
-#define HDL_ITER_MASK	((1UL << HDL_ITER_BITS) - 1)
-#define HDL_TYPE_MASK	((1UL << HDL_TYPE_BITS) - 1)
-
-#define HDL_INDEX_SHIFT	0
-#define HDL_ITER_SHIFT	(HDL_INDEX_SHIFT + HDL_INDEX_BITS)
-#define HDL_TYPE_SHIFT	(HDL_ITER_SHIFT + HDL_ITER_BITS)
-
-/* Local Prototypes. */
-static inline uint32_t qla2x00_to_handle(uint16_t, uint16_t, uint16_t);
-static inline uint16_t qla2x00_handle_to_idx(uint32_t);
-static inline uint32_t qla2x00_iodesc_to_handle(struct io_descriptor *);
-static inline struct io_descriptor *qla2x00_handle_to_iodesc(scsi_qla_host_t *,
-    uint32_t);
-
-static inline struct io_descriptor *qla2x00_alloc_iodesc(scsi_qla_host_t *);
-static inline void qla2x00_free_iodesc(struct io_descriptor *);
-static inline void qla2x00_init_io_descriptors(scsi_qla_host_t *);
-
-static void qla2x00_iodesc_timeout(unsigned long);
-static inline void qla2x00_add_iodesc_timer(struct io_descriptor *);
-static inline void qla2x00_remove_iodesc_timer(struct io_descriptor *);
-
-static inline void qla2x00_update_login_fcport(scsi_qla_host_t *,
-    struct mbx_entry *, fc_port_t *);
-
-static int qla2x00_send_abort_iocb(scsi_qla_host_t *, struct io_descriptor *,
-    uint32_t, int);
-static int qla2x00_send_abort_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
-    struct mbx_entry *);
-
-static int qla2x00_send_adisc_iocb(scsi_qla_host_t *, struct io_descriptor *,
-    int);
-static int qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
-    struct mbx_entry *);
-
-static int qla2x00_send_logout_iocb(scsi_qla_host_t *, struct io_descriptor *,
-    int);
-static int qla2x00_send_logout_iocb_cb(scsi_qla_host_t *,
-    struct io_descriptor *, struct mbx_entry *);
-
-static int qla2x00_send_login_iocb(scsi_qla_host_t *, struct io_descriptor *,
-    port_id_t *, int);
-static int qla2x00_send_login_iocb_cb(scsi_qla_host_t *, struct io_descriptor *,
-    struct mbx_entry *);
-
-/**
- * Mailbox IOCB callback array.
- **/
-static int (*iocb_function_cb_list[LAST_IOCB_CB])
-	(scsi_qla_host_t *, struct io_descriptor *, struct mbx_entry *) = {
-
-	qla2x00_send_abort_iocb_cb,
-	qla2x00_send_adisc_iocb_cb,
-	qla2x00_send_logout_iocb_cb,
-	qla2x00_send_login_iocb_cb,
-};
-
-
-/**
- * Generic IO descriptor handle routines.
- **/
-
-/**
- * qla2x00_to_handle() - Create a descriptor handle.
- * @type: descriptor type
- * @iter: descriptor rolling signature
- * @idx: index to the descriptor array
- *
- * Returns a composite handle based in the @type, @iter, and @idx.
- */
-static inline uint32_t
-qla2x00_to_handle(uint16_t type, uint16_t iter, uint16_t idx)
-{
-	return ((uint32_t)(((uint32_t)type << HDL_TYPE_SHIFT) |
-	    ((uint32_t)iter << HDL_ITER_SHIFT) |
-	    ((uint32_t)idx << HDL_INDEX_SHIFT)));
-}
-
-/**
- * qla2x00_handle_to_idx() - Retrive the index for a given handle.
- * @handle: descriptor handle
- *
- * Returns the index specified by the @handle.
- */
-static inline uint16_t
-qla2x00_handle_to_idx(uint32_t handle)
-{
-	return ((uint16_t)(((handle) >> HDL_INDEX_SHIFT) & HDL_INDEX_MASK));
-}
-
-/**
- * qla2x00_iodesc_to_handle() - Convert an IO descriptor to a unique handle.
- * @iodesc: io descriptor
- *
- * Returns a unique handle for @iodesc.
- */
-static inline uint32_t
-qla2x00_iodesc_to_handle(struct io_descriptor *iodesc)
-{
-	uint32_t handle;
-
-	handle = qla2x00_to_handle(HDL_TYPE_ASYNC_IOCB,
-	    ++iodesc->ha->iodesc_signature, iodesc->idx);
-	iodesc->signature = handle;
-
-	return (handle);
-}
-
-/**
- * qla2x00_handle_to_iodesc() - Retrieve an IO descriptor given a unique handle.
- * @ha: HA context
- * @handle: handle to io descriptor
- *
- * Returns a pointer to the io descriptor, or NULL, if the io descriptor does
- * not exist or the io descriptors signature does not @handle.
- */
-static inline struct io_descriptor *
-qla2x00_handle_to_iodesc(scsi_qla_host_t *ha, uint32_t handle)
-{
-	uint16_t idx;
-	struct io_descriptor *iodesc;
-
-	idx = qla2x00_handle_to_idx(handle);
-	iodesc = &ha->io_descriptors[idx];
-	if (iodesc)
-		if (iodesc->signature != handle)
-			iodesc = NULL;
-
-	return (iodesc);
-}
-
-
-/**
- * IO descriptor allocation routines.
- **/
-
-/**
- * qla2x00_alloc_iodesc() - Allocate an IO descriptor from the pool.
- * @ha: HA context
- *
- * Returns a pointer to the allocated io descriptor, or NULL, if none available.
- */
-static inline struct io_descriptor *
-qla2x00_alloc_iodesc(scsi_qla_host_t *ha)
-{
-	uint16_t iter;
-	struct io_descriptor *iodesc;
-
-	iodesc = NULL;
-	for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {
-		if (ha->io_descriptors[iter].used)
-			continue;
-
-		iodesc = &ha->io_descriptors[iter];
-		iodesc->used = 1;
-		iodesc->idx = iter;
-		init_timer(&iodesc->timer);
-		iodesc->ha = ha;
-		iodesc->signature = qla2x00_iodesc_to_handle(iodesc);
-		break;
-	}
-
-	return (iodesc);
-}
-
-/**
- * qla2x00_free_iodesc() - Free an IO descriptor.
- * @iodesc: io descriptor
- *
- * NOTE: The io descriptors timer *must* be stopped before it can be free'd.
- */
-static inline void
-qla2x00_free_iodesc(struct io_descriptor *iodesc)
-{
-	iodesc->used = 0;
-	iodesc->signature = 0;
-}
-
-/**
- * qla2x00_remove_iodesc_timer() - Remove an active timer from an IO descriptor.
- * @iodesc: io descriptor
- */
-static inline void
-qla2x00_remove_iodesc_timer(struct io_descriptor *iodesc)
-{
-	if (iodesc->timer.function != NULL) {
-		del_timer_sync(&iodesc->timer);
-		iodesc->timer.data = (unsigned long) NULL;
-		iodesc->timer.function = NULL;
-	}
-}
-
-/**
- * qla2x00_init_io_descriptors() - Initialize the pool of IO descriptors.
- * @ha: HA context
- */
-static inline void
-qla2x00_init_io_descriptors(scsi_qla_host_t *ha)
-{
-	uint16_t iter;
-
-	for (iter = 0; iter < MAX_IO_DESCRIPTORS; iter++) {
-		if (!ha->io_descriptors[iter].used)
-			continue;
-
-		qla2x00_remove_iodesc_timer(&ha->io_descriptors[iter]);
-		qla2x00_free_iodesc(&ha->io_descriptors[iter]);
-	}
-}
-
-
-/**
- * IO descriptor timer routines.
- **/
-
-/**
- * qla2x00_iodesc_timeout() - Timeout IO descriptor handler.
- * @data: io descriptor
- */
-static void
-qla2x00_iodesc_timeout(unsigned long data)
-{
-	struct io_descriptor *iodesc;
-
-	iodesc = (struct io_descriptor *) data;
-
-	DEBUG14(printk("scsi(%ld): IO descriptor timeout, index=%x "
-	    "signature=%08x, scheduling ISP abort.\n", iodesc->ha->host_no,
-	    iodesc->idx, iodesc->signature));
-
-	qla2x00_free_iodesc(iodesc);
-
-	qla_printk(KERN_WARNING, iodesc->ha,
-	    "IO descriptor timeout. Scheduling ISP abort.\n");
-	set_bit(ISP_ABORT_NEEDED, &iodesc->ha->dpc_flags);
-}
-
-/**
- * qla2x00_add_iodesc_timer() - Add and start a timer for an IO descriptor.
- * @iodesc: io descriptor
- *
- * NOTE:
- * The firmware shall timeout an outstanding mailbox IOCB in 2 * R_A_TOV (in
- * tenths of a second) after it hits the wire.  But, if there are any request
- * resource contraints (i.e. during heavy I/O), exchanges can be held off for
- * at most R_A_TOV.  Therefore, the driver will wait 4 * R_A_TOV before
- * scheduling a recovery (big hammer).
- */
-static inline void
-qla2x00_add_iodesc_timer(struct io_descriptor *iodesc)
-{
-	unsigned long timeout;
-
-	timeout = (iodesc->ha->r_a_tov * 4) / 10;
-	init_timer(&iodesc->timer);
-	iodesc->timer.data = (unsigned long) iodesc;
-	iodesc->timer.expires = jiffies + (timeout * HZ);
-	iodesc->timer.function =
-	    (void (*) (unsigned long)) qla2x00_iodesc_timeout;
-	add_timer(&iodesc->timer);
-}
-
-/**
- * IO descriptor support routines.
- **/
-
-/**
- * qla2x00_update_login_fcport() - Update fcport data after login processing.
- * @ha: HA context
- * @mbxstat: Mailbox command status IOCB
- * @fcport: port to update
- */
-static inline void
-qla2x00_update_login_fcport(scsi_qla_host_t *ha, struct mbx_entry *mbxstat,
-    fc_port_t *fcport)
-{
-	if (le16_to_cpu(mbxstat->mb1) & BIT_0) {
-		fcport->port_type = FCT_INITIATOR;
-	} else {
-		fcport->port_type = FCT_TARGET;
-		if (le16_to_cpu(mbxstat->mb1) & BIT_1) {
-			fcport->flags |= FCF_TAPE_PRESENT;
-		}
-	}
-	fcport->login_retry = 0;
-	fcport->port_login_retry_count = ha->port_down_retry_count *
-	    PORT_RETRY_TIME;
-	atomic_set(&fcport->port_down_timer, ha->port_down_retry_count *
-	    PORT_RETRY_TIME);
-	fcport->flags |= FCF_FABRIC_DEVICE;
-	fcport->flags &= ~FCF_FAILOVER_NEEDED;
-	fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
-	atomic_set(&fcport->state, FCS_ONLINE);
-	schedule_work(&fcport->rport_add_work);
-}
-
-
-/**
- * Mailbox IOCB commands.
- **/
-
-/**
- * qla2x00_get_mbx_iocb_entry() - Retrieve an IOCB from the request queue.
- * @ha: HA context
- * @handle: handle to io descriptor
- *
- * Returns a pointer to the reqest entry, or NULL, if none were available.
- */
-static inline struct mbx_entry *
-qla2x00_get_mbx_iocb_entry(scsi_qla_host_t *ha, uint32_t handle)
-{
-	uint16_t cnt;
-	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
-	struct mbx_entry *mbxentry;
-
-	mbxentry = NULL;
-
-	if (ha->req_q_cnt < 3) {
-		cnt = qla2x00_debounce_register(ISP_REQ_Q_OUT(ha, reg));
-		if  (ha->req_ring_index < cnt)
-			ha->req_q_cnt = cnt - ha->req_ring_index;
-		else
-			ha->req_q_cnt = ha->request_q_length -
-			    (ha->req_ring_index - cnt);
-	}
-	if (ha->req_q_cnt >= 3) {
-		mbxentry = (struct mbx_entry *)ha->request_ring_ptr;
-
-		memset(mbxentry, 0, sizeof(struct mbx_entry));
-		mbxentry->entry_type = MBX_IOCB_TYPE;
-		mbxentry->entry_count = 1;
-		mbxentry->sys_define1 = SOURCE_ASYNC_IOCB;
-		mbxentry->handle = handle;
-	}
-	return (mbxentry);
-}
-
-/**
- * qla2x00_send_abort_iocb() - Issue an abort IOCB to the firmware.
- * @ha: HA context
- * @iodesc: io descriptor
- * @handle_to_abort: firmware handle to abort
- * @ha_locked: is function called with the hardware lock
- *
- * Returns QLA_SUCCESS if the IOCB was issued.
- */
-static int
-qla2x00_send_abort_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    uint32_t handle_to_abort, int ha_locked)
-{
-	unsigned long flags = 0;
-	struct mbx_entry *mbxentry;
-
-	/* Send marker if required. */
-	if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
-		return (QLA_FUNCTION_FAILED);
-
-	if (!ha_locked)
-		spin_lock_irqsave(&ha->hardware_lock, flags);
-
-	/* Build abort mailbox IOCB. */
-	mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
-	if (mbxentry == NULL) {
-		if (!ha_locked)
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-		return (QLA_FUNCTION_FAILED);
-	}
-	mbxentry->mb0 = __constant_cpu_to_le16(MBC_ABORT_COMMAND);
-	mbxentry->mb1 = mbxentry->loop_id.extended =
-	    cpu_to_le16(iodesc->remote_fcport->loop_id);
-	mbxentry->mb2 = LSW(handle_to_abort);
-	mbxentry->mb3 = MSW(handle_to_abort);
-	wmb();
-
-	qla2x00_add_iodesc_timer(iodesc);
-
-	/* Issue command to ISP. */
-	qla2x00_isp_cmd(ha);
-
-	if (!ha_locked)
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-	DEBUG14(printk("scsi(%ld): Sending Abort IOCB (%08x) to [%x], aborting "
-	    "%08x.\n", ha->host_no, iodesc->signature,
-	    iodesc->remote_fcport->loop_id, handle_to_abort));
-
-	return (QLA_SUCCESS);
-}
-
-/**
- * qla2x00_send_abort_iocb_cb() - Abort IOCB callback.
- * @ha: HA context
- * @iodesc: io descriptor
- * @mbxstat: mailbox status IOCB
- *
- * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
- * will be used for a retry.
- */
-static int
-qla2x00_send_abort_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    struct mbx_entry *mbxstat)
-{
-	DEBUG14(printk("scsi(%ld): Abort IOCB -- sent to [%x/%02x%02x%02x], "
-	    "status=%x mb0=%x.\n", ha->host_no, iodesc->remote_fcport->loop_id,
-	    iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa,
-	    le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
-
-	return (QLA_SUCCESS);
-}
-
-
-/**
- * qla2x00_send_adisc_iocb() - Issue a Get Port Database IOCB to the firmware.
- * @ha: HA context
- * @iodesc: io descriptor
- * @ha_locked: is function called with the hardware lock
- *
- * Returns QLA_SUCCESS if the IOCB was issued.
- */
-static int
-qla2x00_send_adisc_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    int ha_locked)
-{
-	unsigned long flags = 0;
-	struct mbx_entry *mbxentry;
-
-	/* Send marker if required. */
-	if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
-		return (QLA_FUNCTION_FAILED);
-
-	if (!ha_locked)
-		spin_lock_irqsave(&ha->hardware_lock, flags);
-
-	/* Build Get Port Database IOCB. */
-	mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
-	if (mbxentry == NULL) {
-		if (!ha_locked)
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-		return (QLA_FUNCTION_FAILED);
-	}
-	mbxentry->mb0 = __constant_cpu_to_le16(MBC_GET_PORT_DATABASE);
-	mbxentry->mb1 = mbxentry->loop_id.extended =
-	    cpu_to_le16(iodesc->remote_fcport->loop_id);
-	mbxentry->mb2 = cpu_to_le16(MSW(LSD(ha->iodesc_pd_dma)));
-	mbxentry->mb3 = cpu_to_le16(LSW(LSD(ha->iodesc_pd_dma)));
-	mbxentry->mb6 = cpu_to_le16(MSW(MSD(ha->iodesc_pd_dma)));
-	mbxentry->mb7 = cpu_to_le16(LSW(MSD(ha->iodesc_pd_dma)));
-	mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
-	wmb();
-
-	qla2x00_add_iodesc_timer(iodesc);
-
-	/* Issue command to ISP. */
-	qla2x00_isp_cmd(ha);
-
-	if (!ha_locked)
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-	DEBUG14(printk("scsi(%ld): Sending Adisc IOCB (%08x) to [%x].\n",
-	    ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
-
-	return (QLA_SUCCESS);
-}
-
-/**
- * qla2x00_send_adisc_iocb_cb() - Get Port Database IOCB callback.
- * @ha: HA context
- * @iodesc: io descriptor
- * @mbxstat: mailbox status IOCB
- *
- * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
- * will be used for a retry.
- */
-static int
-qla2x00_send_adisc_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    struct mbx_entry *mbxstat)
-{
-	fc_port_t *remote_fcport;
-
-	remote_fcport = iodesc->remote_fcport;
-
-	/* Ensure the port IDs are consistent. */
-	if (remote_fcport->d_id.b24 != iodesc->d_id.b24) {
-		DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, remote port "
-		    "id changed from [%02x%02x%02x] to [%02x%02x%02x].\n",
-		    ha->host_no, remote_fcport->d_id.b.domain,
-		    remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
-		    iodesc->d_id.b.domain, iodesc->d_id.b.area,
-		    iodesc->d_id.b.al_pa));
-
-		return (QLA_SUCCESS);
-	}
-
-	/* Only process the last command. */
-	if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
-		DEBUG14(printk("scsi(%ld): Adisc IOCB -- ignoring, sent to "
-		    "[%02x%02x%02x], expected %x, received %x.\n", ha->host_no,
-		    iodesc->d_id.b.domain, iodesc->d_id.b.area,
-		    iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
-		    iodesc->idx));
-
-		return (QLA_SUCCESS);
-	}
-
-	if (le16_to_cpu(mbxstat->status) == CS_COMPLETE) {
-		DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
-		    "[%x/%02x%02x%02x] online.\n", ha->host_no,
-		    remote_fcport->loop_id, remote_fcport->d_id.b.domain,
-		    remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
-
-		atomic_set(&remote_fcport->state, FCS_ONLINE);
-	} else {
-		DEBUG14(printk("scsi(%ld): Adisc IOCB -- marking "
-		    "[%x/%02x%02x%02x] lost, status=%x mb0=%x.\n", ha->host_no,
-		    remote_fcport->loop_id, remote_fcport->d_id.b.domain,
-		    remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa,
-		    le16_to_cpu(mbxstat->status), le16_to_cpu(mbxstat->mb0)));
-
-		if (atomic_read(&remote_fcport->state) != FCS_DEVICE_DEAD)
-			atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
-	}
-	remote_fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
-
-	return (QLA_SUCCESS);
-}
-
-
-/**
- * qla2x00_send_logout_iocb() - Issue a fabric port logout IOCB to the firmware.
- * @ha: HA context
- * @iodesc: io descriptor
- * @ha_locked: is function called with the hardware lock
- *
- * Returns QLA_SUCCESS if the IOCB was issued.
- */
-static int
-qla2x00_send_logout_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    int ha_locked)
-{
-	unsigned long flags = 0;
-	struct mbx_entry *mbxentry;
-
-	/* Send marker if required. */
-	if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
-		return (QLA_FUNCTION_FAILED);
-
-	if (!ha_locked)
-		spin_lock_irqsave(&ha->hardware_lock, flags);
-
-	/* Build fabric port logout mailbox IOCB. */
-	mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
-	if (mbxentry == NULL) {
-		if (!ha_locked)
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-		return (QLA_FUNCTION_FAILED);
-	}
-	mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGOUT_FABRIC_PORT);
-	mbxentry->mb1 = mbxentry->loop_id.extended =
-	    cpu_to_le16(iodesc->remote_fcport->loop_id);
-	wmb();
-
-	qla2x00_add_iodesc_timer(iodesc);
-
-	/* Issue command to ISP. */
-	qla2x00_isp_cmd(ha);
-
-	if (!ha_locked)
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-	DEBUG14(printk("scsi(%ld): Sending Logout IOCB (%08x) to [%x].\n",
-	    ha->host_no, iodesc->signature, iodesc->remote_fcport->loop_id));
-
-	return (QLA_SUCCESS);
-}
-
-/**
- * qla2x00_send_logout_iocb_cb() - Fabric port logout IOCB callback.
- * @ha: HA context
- * @iodesc: io descriptor
- * @mbxstat: mailbox status IOCB
- *
- * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
- * will be used for a retry.
- */
-static int
-qla2x00_send_logout_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    struct mbx_entry *mbxstat)
-{
-	DEBUG14(printk("scsi(%ld): Logout IOCB -- sent to [%x/%02x%02x%02x], "
-	    "status=%x mb0=%x mb1=%x.\n", ha->host_no,
-	    iodesc->remote_fcport->loop_id,
-	    iodesc->remote_fcport->d_id.b.domain,
-	    iodesc->remote_fcport->d_id.b.area,
-	    iodesc->remote_fcport->d_id.b.al_pa, le16_to_cpu(mbxstat->status),
-	    le16_to_cpu(mbxstat->mb0), le16_to_cpu(mbxstat->mb1)));
-
-	return (QLA_SUCCESS);
-}
-
-
-/**
- * qla2x00_send_login_iocb() - Issue a fabric port login IOCB to the firmware.
- * @ha: HA context
- * @iodesc: io descriptor
- * @d_id: port id for device
- * @ha_locked: is function called with the hardware lock
- *
- * Returns QLA_SUCCESS if the IOCB was issued.
- */
-static int
-qla2x00_send_login_iocb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    port_id_t *d_id, int ha_locked)
-{
-	unsigned long flags = 0;
-	struct mbx_entry *mbxentry;
-
-	/* Send marker if required. */
-	if (qla2x00_issue_marker(ha, ha_locked) != QLA_SUCCESS)
-		return (QLA_FUNCTION_FAILED);
-
-	if (!ha_locked)
-		spin_lock_irqsave(&ha->hardware_lock, flags);
-
-	/* Build fabric port login mailbox IOCB. */
-	mbxentry = qla2x00_get_mbx_iocb_entry(ha, iodesc->signature);
-	if (mbxentry == NULL) {
-		if (!ha_locked)
-			spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-		return (QLA_FUNCTION_FAILED);
-	}
-	mbxentry->mb0 = __constant_cpu_to_le16(MBC_LOGIN_FABRIC_PORT);
-	mbxentry->mb1 = mbxentry->loop_id.extended =
-	    cpu_to_le16(iodesc->remote_fcport->loop_id);
-	mbxentry->mb2 = cpu_to_le16(d_id->b.domain);
-	mbxentry->mb3 = cpu_to_le16(d_id->b.area << 8 | d_id->b.al_pa);
-	mbxentry->mb10 = __constant_cpu_to_le16(BIT_0);
-	wmb();
-
-	qla2x00_add_iodesc_timer(iodesc);
-
-	/* Issue command to ISP. */
-	qla2x00_isp_cmd(ha);
-
-	if (!ha_locked)
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
-
-	DEBUG14(printk("scsi(%ld): Sending Login IOCB (%08x) to "
-	    "[%x/%02x%02x%02x].\n", ha->host_no, iodesc->signature,
-	    iodesc->remote_fcport->loop_id, d_id->b.domain, d_id->b.area,
-	    d_id->b.al_pa));
-
-	return (QLA_SUCCESS);
-}
-
-/**
- * qla2x00_send_login_iocb_cb() - Fabric port logout IOCB callback.
- * @ha: HA context
- * @iodesc: io descriptor
- * @mbxstat: mailbox status IOCB
- *
- * Returns QLA_SUCCESS if @iodesc can be freed by the caller, else, @iodesc
- * will be used for a retry.
- */
-static int
-qla2x00_send_login_iocb_cb(scsi_qla_host_t *ha, struct io_descriptor *iodesc,
-    struct mbx_entry *mbxstat)
-{
-	int rval;
-	fc_port_t *fcport, *remote_fcport, *exist_fcport;
-	struct io_descriptor *abort_iodesc, *login_iodesc;
-	uint16_t status, mb[8];
-	uint16_t reuse;
-	uint16_t remote_loopid;
-	port_id_t remote_did, inuse_did;
-
-	remote_fcport = iodesc->remote_fcport;
-
-	/* Only process the last command. */
-	if (remote_fcport->iodesc_idx_sent != iodesc->idx) {
-		DEBUG14(printk("scsi(%ld): Login IOCB -- ignoring, sent to "
-		    "[%02x%02x%02x], expected %x, received %x.\n",
-		    ha->host_no, iodesc->d_id.b.domain, iodesc->d_id.b.area,
-		    iodesc->d_id.b.al_pa, remote_fcport->iodesc_idx_sent,
-		    iodesc->idx));
-
-		/* Free RSCN fcport resources. */
-		if (remote_fcport->port_type == FCT_RSCN) {
-			DEBUG14(printk("scsi(%ld): Login IOCB -- Freeing RSCN "
-			    "fcport %p [%x/%02x%02x%02x] given ignored Login "
-			    "IOCB.\n", ha->host_no, remote_fcport,
-			    remote_fcport->loop_id,
-			    remote_fcport->d_id.b.domain,
-			    remote_fcport->d_id.b.area,
-			    remote_fcport->d_id.b.al_pa));
-
-			list_del(&remote_fcport->list);
-			kfree(remote_fcport);
-		}
-		return (QLA_SUCCESS);
-	}
-
-	status = le16_to_cpu(mbxstat->status);
-	mb[0] = le16_to_cpu(mbxstat->mb0);
-	mb[1] = le16_to_cpu(mbxstat->mb1);
-	mb[2] = le16_to_cpu(mbxstat->mb2);
-	mb[6] = le16_to_cpu(mbxstat->mb6);
-	mb[7] = le16_to_cpu(mbxstat->mb7);
-
-	/* Good status? */
-	if ((status == CS_COMPLETE || status == CS_COMPLETE_CHKCOND) &&
-	    mb[0] == MBS_COMMAND_COMPLETE) {
-
-		DEBUG14(printk("scsi(%ld): Login IOCB -- status=%x mb1=%x pn="
-		    "%02x%02x%02x%02x%02x%02x%02x%02x.\n", ha->host_no, status,
-		    mb[1], mbxstat->port_name[0], mbxstat->port_name[1],
-		    mbxstat->port_name[2], mbxstat->port_name[3],
-		    mbxstat->port_name[4], mbxstat->port_name[5],
-		    mbxstat->port_name[6], mbxstat->port_name[7]));
-
-		memcpy(remote_fcport->node_name, mbxstat->node_name, WWN_SIZE);
-		memcpy(remote_fcport->port_name, mbxstat->port_name, WWN_SIZE);
-
-		/* Is the device already in our fcports list? */
-		if (remote_fcport->port_type != FCT_RSCN) {
-			DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
-			    "[%x/%02x%02x%02x] online.\n", ha->host_no,
-			    remote_fcport->loop_id,
-			    remote_fcport->d_id.b.domain,
-			    remote_fcport->d_id.b.area,
-			    remote_fcport->d_id.b.al_pa));
-
-			qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
-
-			return (QLA_SUCCESS);
-		}
-
-		/* Does the RSCN portname already exist in our fcports list? */
-		exist_fcport = NULL;
-		list_for_each_entry(fcport, &ha->fcports, list) {
-			if (memcmp(remote_fcport->port_name, fcport->port_name,
-			    WWN_SIZE) == 0) {
-				exist_fcport = fcport;
-				break;
-			}
-		}
-		if (exist_fcport != NULL) {
-			DEBUG14(printk("scsi(%ld): Login IOCB -- found RSCN "
-			    "fcport in fcports list [%p].\n", ha->host_no,
-			    exist_fcport));
-
-			/* Abort any ADISC that could have been sent. */
-			if (exist_fcport->iodesc_idx_sent != iodesc->idx &&
-			    exist_fcport->iodesc_idx_sent <
-			    MAX_IO_DESCRIPTORS &&
-			    ha->io_descriptors[exist_fcport->iodesc_idx_sent].
-			    cb_idx == ADISC_PORT_IOCB_CB) {
-
-				abort_iodesc = qla2x00_alloc_iodesc(ha);
-				if (abort_iodesc) {
-					DEBUG14(printk("scsi(%ld): Login IOCB "
-					    "-- issuing abort to outstanding "
-					    "Adisc [%x/%02x%02x%02x].\n",
-					    ha->host_no, remote_fcport->loop_id,
-					    exist_fcport->d_id.b.domain,
-					    exist_fcport->d_id.b.area,
-					    exist_fcport->d_id.b.al_pa));
-
-					abort_iodesc->cb_idx = ABORT_IOCB_CB;
-					abort_iodesc->d_id.b24 =
-					    exist_fcport->d_id.b24;
-					abort_iodesc->remote_fcport =
-					    exist_fcport;
-					exist_fcport->iodesc_idx_sent =
-					    abort_iodesc->idx;
-					qla2x00_send_abort_iocb(ha,
-					    abort_iodesc, ha->io_descriptors[
-					     exist_fcport->iodesc_idx_sent].
-					      signature, 1);
-				} else {
-					DEBUG14(printk("scsi(%ld): Login IOCB "
-					    "-- unable to abort outstanding "
-					    "Adisc [%x/%02x%02x%02x].\n",
-					    ha->host_no, remote_fcport->loop_id,
-					    exist_fcport->d_id.b.domain,
-					    exist_fcport->d_id.b.area,
-					    exist_fcport->d_id.b.al_pa));
-				}
-			}
-
-			/*
-			 * If the existing fcport is waiting to send an ADISC
-			 * or LOGIN, then reuse remote fcport (RSCN) to
-			 * continue waiting.
-			 */
-			reuse = 0;
-			remote_loopid = remote_fcport->loop_id;
-			remote_did.b24 = remote_fcport->d_id.b24;
-			if (exist_fcport->iodesc_idx_sent ==
-			    IODESC_ADISC_NEEDED ||
-			    exist_fcport->iodesc_idx_sent ==
-			    IODESC_LOGIN_NEEDED) {
-				DEBUG14(printk("scsi(%ld): Login IOCB -- "
-				    "existing fcport [%x/%02x%02x%02x] "
-				    "waiting for IO descriptor, reuse RSCN "
-				    "fcport.\n", ha->host_no,
-				    exist_fcport->loop_id,
-				    exist_fcport->d_id.b.domain,
-				    exist_fcport->d_id.b.area,
-				    exist_fcport->d_id.b.al_pa));
-
-				reuse++;
-				remote_fcport->iodesc_idx_sent =
-				    exist_fcport->iodesc_idx_sent;
-				exist_fcport->iodesc_idx_sent =
-				    IODESC_INVALID_INDEX;
-				remote_fcport->loop_id = exist_fcport->loop_id;
-				remote_fcport->d_id.b24 =
-				    exist_fcport->d_id.b24;
-			}
-
-			/* Logout the old loopid. */
-			if (!reuse &&
-			    exist_fcport->loop_id != remote_fcport->loop_id &&
-			    exist_fcport->loop_id != FC_NO_LOOP_ID) {
-				login_iodesc = qla2x00_alloc_iodesc(ha);
-				if (login_iodesc) {
-					DEBUG14(printk("scsi(%ld): Login IOCB "
-					    "-- issuing logout to free old "
-					    "loop id [%x/%02x%02x%02x].\n",
-					    ha->host_no, exist_fcport->loop_id,
-					    exist_fcport->d_id.b.domain,
-					    exist_fcport->d_id.b.area,
-					    exist_fcport->d_id.b.al_pa));
-
-					login_iodesc->cb_idx =
-					    LOGOUT_PORT_IOCB_CB;
-					login_iodesc->d_id.b24 =
-					    exist_fcport->d_id.b24;
-					login_iodesc->remote_fcport =
-					    exist_fcport;
-					exist_fcport->iodesc_idx_sent =
-					    login_iodesc->idx;
-					qla2x00_send_logout_iocb(ha,
-					    login_iodesc, 1);
-				} else {
-					/* Ran out of IO descriptiors. */
-					DEBUG14(printk("scsi(%ld): Login IOCB "
-					    "-- unable to logout to free old "
-					    "loop id [%x/%02x%02x%02x].\n",
-					    ha->host_no, exist_fcport->loop_id,
-					    exist_fcport->d_id.b.domain,
-					    exist_fcport->d_id.b.area,
-					    exist_fcport->d_id.b.al_pa));
-
-					exist_fcport->iodesc_idx_sent =
-					    IODESC_INVALID_INDEX;
-				}
-
-			}
-
-			/* Update existing fcport with remote fcport info. */
-			DEBUG14(printk("scsi(%ld): Login IOCB -- marking "
-			    "existing fcport [%x/%02x%02x%02x] online.\n",
-			    ha->host_no, remote_loopid, remote_did.b.domain,
-			    remote_did.b.area, remote_did.b.al_pa));
-
-			memcpy(exist_fcport->node_name,
-			    remote_fcport->node_name, WWN_SIZE);
-			exist_fcport->loop_id = remote_loopid;
-			exist_fcport->d_id.b24 = remote_did.b24;
-			qla2x00_update_login_fcport(ha, mbxstat, exist_fcport);
-
-			/* Finally, free the remote (RSCN) fcport. */
-			if (!reuse) {
-				DEBUG14(printk("scsi(%ld): Login IOCB -- "
-				    "Freeing RSCN fcport %p "
-				    "[%x/%02x%02x%02x].\n", ha->host_no,
-				    remote_fcport, remote_fcport->loop_id,
-				    remote_fcport->d_id.b.domain,
-				    remote_fcport->d_id.b.area,
-				    remote_fcport->d_id.b.al_pa));
-
-				list_del(&remote_fcport->list);
-				kfree(remote_fcport);
-			}
-
-			return (QLA_SUCCESS);
-		}
-
-		/*
-		 * A new device has been added, move the RSCN fcport to our
-		 * fcports list.
-		 */
-		DEBUG14(printk("scsi(%ld): Login IOCB -- adding RSCN fcport "
-		    "[%x/%02x%02x%02x] to fcports list.\n", ha->host_no,
-		    remote_fcport->loop_id, remote_fcport->d_id.b.domain,
-		    remote_fcport->d_id.b.area, remote_fcport->d_id.b.al_pa));
-
-		list_del(&remote_fcport->list);
-		remote_fcport->flags = (FCF_RLC_SUPPORT | FCF_RESCAN_NEEDED);
-		qla2x00_update_login_fcport(ha, mbxstat, remote_fcport);
-		list_add_tail(&remote_fcport->list, &ha->fcports);
-		set_bit(FCPORT_RESCAN_NEEDED, &ha->dpc_flags);
-	} else {
-		/* Handle login failure. */
-		if (remote_fcport->login_retry != 0) {
-			if (mb[0] == MBS_LOOP_ID_USED) {
-				inuse_did.b.domain = LSB(mb[1]);
-				inuse_did.b.area = MSB(mb[2]);
-				inuse_did.b.al_pa = LSB(mb[2]);
-
-				DEBUG14(printk("scsi(%ld): Login IOCB -- loop "
-				    "id [%x] used by port id [%02x%02x%02x].\n",
-				    ha->host_no, remote_fcport->loop_id,
-				    inuse_did.b.domain, inuse_did.b.area,
-				    inuse_did.b.al_pa));
-
-				if (remote_fcport->d_id.b24 ==
-				    INVALID_PORT_ID) {
-					/*
-					 * Invalid port id means we are trying
-					 * to login to a remote port with just
-					 * a loop id without knowing about the
-					 * port id.  Copy the port id and try
-					 * again.
-					 */
-					remote_fcport->d_id.b24 = inuse_did.b24;
-					iodesc->d_id.b24 = inuse_did.b24;
-				} else {
-					remote_fcport->loop_id++;
-					rval = qla2x00_find_new_loop_id(ha,
-					    remote_fcport);
-					if (rval == QLA_FUNCTION_FAILED) {
-						/* No more loop ids. */
-						return (QLA_SUCCESS);
-					}
-				}
-			} else if (mb[0] == MBS_PORT_ID_USED) {
-				/*
-				 * Device has another loop ID.  The firmware
-				 * group recommends the driver perform an
-				 * implicit login with the specified ID.
-				 */
-				DEBUG14(printk("scsi(%ld): Login IOCB -- port "
-				    "id [%02x%02x%02x] already assigned to "
-				    "loop id [%x].\n", ha->host_no,
-				    iodesc->d_id.b.domain, iodesc->d_id.b.area,
-				    iodesc->d_id.b.al_pa, mb[1]));
-
-				remote_fcport->loop_id = mb[1];
-
-			} else {
-				/* Unable to perform login, try again. */
-				DEBUG14(printk("scsi(%ld): Login IOCB -- "
-				    "failed login [%x/%02x%02x%02x], status=%x "
-				    "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
-				    ha->host_no, remote_fcport->loop_id,
-				    iodesc->d_id.b.domain, iodesc->d_id.b.area,
-				    iodesc->d_id.b.al_pa, status, mb[0], mb[1],
-				    mb[2], mb[6], mb[7]));
-			}
-
-			/* Reissue Login with the same IO descriptor. */
-			iodesc->signature =
-			    qla2x00_iodesc_to_handle(iodesc);
-			iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
-			iodesc->d_id.b24 = remote_fcport->d_id.b24;
-			remote_fcport->iodesc_idx_sent = iodesc->idx;
-			remote_fcport->login_retry--;
-
-			DEBUG14(printk("scsi(%ld): Login IOCB -- retrying "
-			    "login to [%x/%02x%02x%02x] (%d).\n", ha->host_no,
-			    remote_fcport->loop_id,
-			    remote_fcport->d_id.b.domain,
-			    remote_fcport->d_id.b.area,
-			    remote_fcport->d_id.b.al_pa,
-			    remote_fcport->login_retry));
-
-			qla2x00_send_login_iocb(ha, iodesc,
-			    &remote_fcport->d_id, 1);
-
-			return (QLA_FUNCTION_FAILED);
-		} else {
-			/* No more logins, mark device dead. */
-			DEBUG14(printk("scsi(%ld): Login IOCB -- failed "
-			    "login [%x/%02x%02x%02x] after retries, status=%x "
-			    "mb0=%x mb1=%x mb2=%x mb6=%x mb7=%x.\n",
-			    ha->host_no, remote_fcport->loop_id,
-			    iodesc->d_id.b.domain, iodesc->d_id.b.area,
-			    iodesc->d_id.b.al_pa, status, mb[0], mb[1],
-			    mb[2], mb[6], mb[7]));
-
-			atomic_set(&remote_fcport->state, FCS_DEVICE_DEAD);
-			if (remote_fcport->port_type == FCT_RSCN) {
-				DEBUG14(printk("scsi(%ld): Login IOCB -- "
-				    "Freeing dead RSCN fcport %p "
-				    "[%x/%02x%02x%02x].\n", ha->host_no,
-				    remote_fcport, remote_fcport->loop_id,
-				    remote_fcport->d_id.b.domain,
-				    remote_fcport->d_id.b.area,
-				    remote_fcport->d_id.b.al_pa));
-
-				list_del(&remote_fcport->list);
-				kfree(remote_fcport);
-			}
-		}
-	}
-
-	return (QLA_SUCCESS);
-}
-
-
-/**
- * IO descriptor processing routines.
- **/
-
-/**
- * qla2x00_alloc_rscn_fcport() - Allocate an RSCN type fcport.
- * @ha: HA context
- * @flags: allocation flags
- *
- * Returns a pointer to the allocated RSCN fcport, or NULL, if none available.
- */
-fc_port_t *
-qla2x00_alloc_rscn_fcport(scsi_qla_host_t *ha, gfp_t flags)
-{
-	fc_port_t *fcport;
-
-	fcport = qla2x00_alloc_fcport(ha, flags);
-	if (fcport == NULL)
-		return (fcport);
-
-	/* Setup RSCN fcport structure. */
-	fcport->port_type = FCT_RSCN;
-
-	return (fcport);
-}
-
-/**
- * qla2x00_handle_port_rscn() - Handle port RSCN.
- * @ha: HA context
- * @rscn_entry: RSCN entry
- * @fcport: fcport entry to updated
- *
- * Returns QLA_SUCCESS if the port RSCN was handled.
- */
-int
-qla2x00_handle_port_rscn(scsi_qla_host_t *ha, uint32_t rscn_entry,
-    fc_port_t *known_fcport, int ha_locked)
-{
-	int	rval;
-	port_id_t rscn_pid;
-	fc_port_t *fcport, *remote_fcport, *rscn_fcport;
-	struct io_descriptor *iodesc;
-
-	remote_fcport = NULL;
-	rscn_fcport = NULL;
-
-	/* Prepare port id based on incoming entries. */
-	if (known_fcport) {
-		rscn_pid.b24 = known_fcport->d_id.b24;
-		remote_fcport = known_fcport;
-
-		DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
-		    "fcport [%02x%02x%02x].\n", ha->host_no,
-		    remote_fcport->d_id.b.domain, remote_fcport->d_id.b.area,
-		    remote_fcport->d_id.b.al_pa));
-	} else {
-		rscn_pid.b.domain = LSB(MSW(rscn_entry));
-		rscn_pid.b.area = MSB(LSW(rscn_entry));
-		rscn_pid.b.al_pa = LSB(LSW(rscn_entry));
-
-		DEBUG14(printk("scsi(%ld): Handle RSCN -- process RSCN for "
-		    "port id [%02x%02x%02x].\n", ha->host_no,
-		    rscn_pid.b.domain, rscn_pid.b.area, rscn_pid.b.al_pa));
-
-		/*
-		 * Search fcport lists for a known entry at the specified port
-		 * ID.
-		 */
-		list_for_each_entry(fcport, &ha->fcports, list) {
-		    if (rscn_pid.b24 == fcport->d_id.b24) {
-			    remote_fcport = fcport;
-			    break;
-		    }
-		}
-		list_for_each_entry(fcport, &ha->rscn_fcports, list) {
-		    if (rscn_pid.b24 == fcport->d_id.b24) {
-			    rscn_fcport = fcport;
-			    break;
-		    }
-		}
-		if (remote_fcport == NULL)
-		    remote_fcport = rscn_fcport;
-	}
-
-	/*
-	 * If the port is already in our fcport list and online, send an ADISC
-	 * to see if it's still alive.  Issue login if a new fcport or the known
-	 * fcport is currently offline.
-	 */
-	if (remote_fcport) {
-		/*
-		 * No need to send request if the remote fcport is currently
-		 * waiting for an available io descriptor.
-		 */
-		if (known_fcport == NULL &&
-		    (remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
-		    remote_fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED)) {
-			/*
-			 * If previous waiting io descriptor is an ADISC, then
-			 * the new RSCN may come from a new remote fcport being
-			 * plugged into the same location.
-			 */
-			if (remote_fcport->port_type == FCT_RSCN) {
-			    remote_fcport->iodesc_idx_sent =
-				IODESC_LOGIN_NEEDED;
-			} else if (remote_fcport->iodesc_idx_sent ==
-			    IODESC_ADISC_NEEDED) {
-				fc_port_t *new_fcport;
-
-				remote_fcport->iodesc_idx_sent =
-				    IODESC_INVALID_INDEX;
-
-				/* Create new fcport for later login. */
-				new_fcport = qla2x00_alloc_rscn_fcport(ha,
-				    ha_locked ? GFP_ATOMIC: GFP_KERNEL);
-				if (new_fcport) {
-					DEBUG14(printk("scsi(%ld): Handle RSCN "
-					    "-- creating RSCN fcport %p for "
-					    "future login.\n", ha->host_no,
-					    new_fcport));
-
-					new_fcport->d_id.b24 =
-					    remote_fcport->d_id.b24;
-					new_fcport->iodesc_idx_sent =
-					    IODESC_LOGIN_NEEDED;
-
-					list_add_tail(&new_fcport->list,
-					    &ha->rscn_fcports);
-					set_bit(IODESC_PROCESS_NEEDED,
-					    &ha->dpc_flags);
-				} else {
-					DEBUG14(printk("scsi(%ld): Handle RSCN "
-					    "-- unable to allocate RSCN fcport "
-					    "for future login.\n",
-					    ha->host_no));
-				}
-			}
-			return (QLA_SUCCESS);
-		}
-
-		/* Send ADISC if the fcport is online */
-		if (atomic_read(&remote_fcport->state) == FCS_ONLINE ||
-		    remote_fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED) {
-
-			atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
-
-			iodesc = qla2x00_alloc_iodesc(ha);
-			if (iodesc == NULL) {
-				/* Mark fcport for later adisc processing */
-				DEBUG14(printk("scsi(%ld): Handle RSCN -- not "
-				    "enough IO descriptors for Adisc, flag "
-				    "for later processing.\n", ha->host_no));
-
-				remote_fcport->iodesc_idx_sent =
-				    IODESC_ADISC_NEEDED;
-				set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
-
-				return (QLA_SUCCESS);
-			}
-
-			iodesc->cb_idx = ADISC_PORT_IOCB_CB;
-			iodesc->d_id.b24 = rscn_pid.b24;
-			iodesc->remote_fcport = remote_fcport;
-			remote_fcport->iodesc_idx_sent = iodesc->idx;
-			qla2x00_send_adisc_iocb(ha, iodesc, ha_locked);
-
-			return (QLA_SUCCESS);
-		} else if (remote_fcport->iodesc_idx_sent <
-		    MAX_IO_DESCRIPTORS &&
-		    ha->io_descriptors[remote_fcport->iodesc_idx_sent].cb_idx ==
-		    ADISC_PORT_IOCB_CB) {
-			/*
-			 * Receiving another RSCN while an ADISC is pending,
-			 * abort the IOCB.  Use the same descriptor for the
-			 * abort.
-			 */
-			uint32_t handle_to_abort;
-
-			iodesc = &ha->io_descriptors[
-				remote_fcport->iodesc_idx_sent];
-			qla2x00_remove_iodesc_timer(iodesc);
-			handle_to_abort = iodesc->signature;
-			iodesc->signature = qla2x00_iodesc_to_handle(iodesc);
-			iodesc->cb_idx = ABORT_IOCB_CB;
-			iodesc->d_id.b24 = remote_fcport->d_id.b24;
-			iodesc->remote_fcport = remote_fcport;
-			remote_fcport->iodesc_idx_sent = iodesc->idx;
-
-			DEBUG14(printk("scsi(%ld): Handle RSCN -- issuing "
-			    "abort to outstanding Adisc [%x/%02x%02x%02x].\n",
-			    ha->host_no, remote_fcport->loop_id,
-			    iodesc->d_id.b.domain, iodesc->d_id.b.area,
-			    iodesc->d_id.b.al_pa));
-
-			qla2x00_send_abort_iocb(ha, iodesc, handle_to_abort,
-			    ha_locked);
-		}
-	}
-
-	/* We need to login to the remote port, find it. */
-	if (known_fcport) {
-		remote_fcport = known_fcport;
-	} else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
-	    rscn_fcport->iodesc_idx_sent < MAX_IO_DESCRIPTORS &&
-	    ha->io_descriptors[rscn_fcport->iodesc_idx_sent].cb_idx ==
-	    LOGIN_PORT_IOCB_CB) {
-		/*
-		 * Ignore duplicate RSCN on fcport which has already
-		 * initiated a login IOCB.
-		 */
-		DEBUG14(printk("scsi(%ld): Handle RSCN -- ignoring, login "
-		    "already sent to [%02x%02x%02x].\n", ha->host_no,
-		    rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
-		    rscn_fcport->d_id.b.al_pa));
-
-		return (QLA_SUCCESS);
-	} else if (rscn_fcport && rscn_fcport->d_id.b24 != INVALID_PORT_ID &&
-	    rscn_fcport != remote_fcport) {
-		/* Reuse same rscn fcport. */
-		DEBUG14(printk("scsi(%ld): Handle RSCN -- reusing RSCN fcport "
-		    "[%02x%02x%02x].\n", ha->host_no,
-		    rscn_fcport->d_id.b.domain, rscn_fcport->d_id.b.area,
-		    rscn_fcport->d_id.b.al_pa));
-
-		remote_fcport = rscn_fcport;
-	} else {
-		/* Create new fcport for later login. */
-		remote_fcport = qla2x00_alloc_rscn_fcport(ha,
-		    ha_locked ? GFP_ATOMIC: GFP_KERNEL);
-		list_add_tail(&remote_fcport->list, &ha->rscn_fcports);
-	}
-	if (remote_fcport == NULL)
-		return (QLA_SUCCESS);
-
-	/* Prepare fcport for login. */
-	atomic_set(&remote_fcport->state, FCS_DEVICE_LOST);
-	remote_fcport->login_retry = 3; /* ha->login_retry_count; */
-	remote_fcport->d_id.b24 = rscn_pid.b24;
-
-	iodesc = qla2x00_alloc_iodesc(ha);
-	if (iodesc == NULL) {
-		/* Mark fcport for later adisc processing. */
-		DEBUG14(printk("scsi(%ld): Handle RSCN -- not enough IO "
-		    "descriptors for Login, flag for later processing.\n",
-		    ha->host_no));
-
-		remote_fcport->iodesc_idx_sent = IODESC_LOGIN_NEEDED;
-		set_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
-
-		return (QLA_SUCCESS);
-	}
-
-	if (known_fcport == NULL || rscn_pid.b24 != INVALID_PORT_ID) {
-		remote_fcport->loop_id = ha->min_external_loopid;
-
-		rval = qla2x00_find_new_loop_id(ha, remote_fcport);
-		if (rval == QLA_FUNCTION_FAILED) {
-			/* No more loop ids, failed. */
-			DEBUG14(printk("scsi(%ld): Handle RSCN -- no available "
-			    "loop id to perform Login, failed.\n",
-			    ha->host_no));
-
-			return (rval);
-		}
-	}
-
-	iodesc->cb_idx = LOGIN_PORT_IOCB_CB;
-	iodesc->d_id.b24 = rscn_pid.b24;
-	iodesc->remote_fcport = remote_fcport;
-	remote_fcport->iodesc_idx_sent = iodesc->idx;
-
-	DEBUG14(printk("scsi(%ld): Handle RSCN -- attempting login to "
-	    "[%x/%02x%02x%02x].\n", ha->host_no, remote_fcport->loop_id,
-	    iodesc->d_id.b.domain, iodesc->d_id.b.area, iodesc->d_id.b.al_pa));
-
-	qla2x00_send_login_iocb(ha, iodesc, &rscn_pid, ha_locked);
-
-	return (QLA_SUCCESS);
-}
-
-/**
- * qla2x00_process_iodesc() - Complete IO descriptor processing.
- * @ha: HA context
- * @mbxstat: Mailbox IOCB status
- */
-void
-qla2x00_process_iodesc(scsi_qla_host_t *ha, struct mbx_entry *mbxstat)
-{
-	int rval;
-	uint32_t signature;
-	fc_port_t *fcport;
-	struct io_descriptor *iodesc;
-
-	signature = mbxstat->handle;
-
-	DEBUG14(printk("scsi(%ld): Process IODesc -- processing %08x.\n",
-	    ha->host_no, signature));
-
-	/* Retrieve proper IO descriptor. */
-	iodesc = qla2x00_handle_to_iodesc(ha, signature);
-	if (iodesc == NULL) {
-		DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
-		    "incorrect signature %08x.\n", ha->host_no, signature));
-
-		return;
-	}
-
-	/* Stop IO descriptor timer. */
-	qla2x00_remove_iodesc_timer(iodesc);
-
-	/* Verify signature match. */
-	if (iodesc->signature != signature) {
-		DEBUG14(printk("scsi(%ld): Process IODesc -- ignoring, "
-		    "signature mismatch, sent %08x, received %08x.\n",
-		    ha->host_no, iodesc->signature, signature));
-
-		return;
-	}
-
-	/* Go with IOCB callback. */
-	rval = iocb_function_cb_list[iodesc->cb_idx](ha, iodesc, mbxstat);
-	if (rval != QLA_SUCCESS) {
-		/* IO descriptor reused by callback. */
-		return;
-	}
-
-	qla2x00_free_iodesc(iodesc);
-
-	if (test_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags)) {
-		/* Scan our fcports list for any RSCN requests. */
-		list_for_each_entry(fcport, &ha->fcports, list) {
-			if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
-			    fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
-				qla2x00_handle_port_rscn(ha, 0, fcport, 1);
-				return;
-			}
-		}
-
-		/* Scan our RSCN fcports list for any RSCN requests. */
-		list_for_each_entry(fcport, &ha->rscn_fcports, list) {
-			if (fcport->iodesc_idx_sent == IODESC_ADISC_NEEDED ||
-			    fcport->iodesc_idx_sent == IODESC_LOGIN_NEEDED) {
-				qla2x00_handle_port_rscn(ha, 0, fcport, 1);
-				return;
-			}
-		}
-	}
-	clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
-}
-
-/**
- * qla2x00_cancel_io_descriptors() - Cancel all outstanding io descriptors.
- * @ha: HA context
- *
- * This routine will also delete any RSCN entries related to the outstanding
- * IO descriptors.
- */
-void
-qla2x00_cancel_io_descriptors(scsi_qla_host_t *ha)
-{
-	fc_port_t *fcport, *fcptemp;
-
-	clear_bit(IODESC_PROCESS_NEEDED, &ha->dpc_flags);
-
-	/* Abort all IO descriptors. */
-	qla2x00_init_io_descriptors(ha);
-
-	/* Reset all pending IO descriptors in fcports list. */
-	list_for_each_entry(fcport, &ha->fcports, list) {
-		fcport->iodesc_idx_sent = IODESC_INVALID_INDEX;
-	}
-
-	/* Reset all pending IO descriptors in rscn fcports list. */
-	list_for_each_entry_safe(fcport, fcptemp, &ha->rscn_fcports, list) {
-		DEBUG14(printk("scsi(%ld): Cancel IOs -- Freeing RSCN fcport "
-		    "%p [%x/%02x%02x%02x].\n", ha->host_no, fcport,
-		    fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
-		    fcport->d_id.b.al_pa));
-
-		list_del(&fcport->list);
-		kfree(fcport);
-	}
-}
diff --git a/drivers/scsi/qla2xxx/qla_settings.h b/drivers/scsi/qla2xxx/qla_settings.h
index 363205c..249e4d9 100644
--- a/drivers/scsi/qla2xxx/qla_settings.h
+++ b/drivers/scsi/qla2xxx/qla_settings.h
@@ -16,7 +16,6 @@
 
 /* Max time to wait for the loop to be in LOOP_READY state */
 #define MAX_LOOP_TIMEOUT	(60 * 5)
-#define EH_ACTIVE		1	/* Error handler active */
 
 /*
  * Some vendor subsystems do not recover properly after a device reset.  Define
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 8b0121d..c71dbd5 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -97,7 +97,7 @@
 {
 	int count;
 	uint16_t word;
-	uint32_t nv_cmd;
+	uint32_t nv_cmd, wait_cnt;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
 
 	qla2x00_nv_write(ha, NVR_DATA_OUT);
@@ -127,7 +127,13 @@
 	/* Wait for NVRAM to become ready */
 	WRT_REG_WORD(&reg->nvram, NVR_SELECT);
 	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */
+	wait_cnt = NVR_WAIT_CNT;
 	do {
+		if (!--wait_cnt) {
+			DEBUG9_10(printk("%s(%ld): NVRAM didn't go ready...\n",
+			    __func__, ha->host_no));
+			break;
+		}
 		NVRAM_DELAY();
 		word = RD_REG_WORD(&reg->nvram);
 	} while ((word & NVR_DATA_IN) == 0);
@@ -301,16 +307,17 @@
 {
 	int ret, stat;
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
-	uint32_t word;
+	uint32_t word, wait_cnt;
 	uint16_t wprot, wprot_old;
 
 	/* Clear NVRAM write protection. */
 	ret = QLA_FUNCTION_FAILED;
-	wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, 0));
-	stat = qla2x00_write_nvram_word_tmo(ha, 0,
+
+	wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base));
+	stat = qla2x00_write_nvram_word_tmo(ha, ha->nvram_base,
 	    __constant_cpu_to_le16(0x1234), 100000);
-	wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, 0));
-	if (stat != QLA_SUCCESS || wprot != __constant_cpu_to_le16(0x1234)) {
+	wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, ha->nvram_base));
+	if (stat != QLA_SUCCESS || wprot != 0x1234) {
 		/* Write enable. */
 		qla2x00_nv_write(ha, NVR_DATA_OUT);
 		qla2x00_nv_write(ha, 0);
@@ -341,14 +348,22 @@
 		/* Wait for NVRAM to become ready. */
 		WRT_REG_WORD(&reg->nvram, NVR_SELECT);
 		RD_REG_WORD(&reg->nvram);	/* PCI Posting. */
+		wait_cnt = NVR_WAIT_CNT;
 		do {
+			if (!--wait_cnt) {
+				DEBUG9_10(printk("%s(%ld): NVRAM didn't go "
+				    "ready...\n", __func__,
+				    ha->host_no));
+				break;
+			}
 			NVRAM_DELAY();
 			word = RD_REG_WORD(&reg->nvram);
 		} while ((word & NVR_DATA_IN) == 0);
 
-		ret = QLA_SUCCESS;
+		if (wait_cnt)
+			ret = QLA_SUCCESS;
 	} else
-		qla2x00_write_nvram_word(ha, 0, wprot_old);
+		qla2x00_write_nvram_word(ha, ha->nvram_base, wprot_old);
 
 	return ret;
 }
@@ -357,7 +372,7 @@
 qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat)
 {
 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
-	uint32_t word;
+	uint32_t word, wait_cnt;
 
 	if (stat != QLA_SUCCESS)
 		return;
@@ -393,7 +408,13 @@
 	/* Wait for NVRAM to become ready. */
 	WRT_REG_WORD(&reg->nvram, NVR_SELECT);
 	RD_REG_WORD(&reg->nvram);		/* PCI Posting. */
+	wait_cnt = NVR_WAIT_CNT;
 	do {
+		if (!--wait_cnt) {
+			DEBUG9_10(printk("%s(%ld): NVRAM didn't go ready...\n",
+			    __func__, ha->host_no));
+			break;
+		}
 		NVRAM_DELAY();
 		word = RD_REG_WORD(&reg->nvram);
 	} while ((word & NVR_DATA_IN) == 0);
@@ -500,6 +521,20 @@
 	ids = qla24xx_read_flash_dword(ha, flash_data_to_access_addr(0xd03ab));
 	*man_id = LSB(ids);
 	*flash_id = MSB(ids);
+
+	/* Check if man_id and flash_id are valid. */
+	if (ids != 0xDEADDEAD && (*man_id == 0 || *flash_id == 0)) {
+		/* Read information using 0x9f opcode
+		 * Device ID, Mfg ID would be read in the format:
+		 *   <Ext Dev Info><Device ID Part2><Device ID Part 1><Mfg ID>
+		 * Example: ATMEL 0x00 01 45 1F
+		 * Extract MFG and Dev ID from last two bytes.
+		 */
+		ids = qla24xx_read_flash_dword(ha,
+		    flash_data_to_access_addr(0xd009f));
+		*man_id = LSB(ids);
+		*flash_id = MSB(ids);
+	}
 }
 
 int
@@ -508,8 +543,8 @@
 {
 	int ret;
 	uint32_t liter;
-	uint32_t sec_mask, rest_addr, conf_addr;
-	uint32_t fdata;
+	uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask;
+	uint32_t fdata, findex ;
 	uint8_t	man_id, flash_id;
 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
 
@@ -519,6 +554,7 @@
 	DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
 	    ha->host_no, man_id, flash_id));
 
+	sec_end_mask = 0;
 	conf_addr = flash_conf_to_access_addr(0x03d8);
 	switch (man_id) {
 	case 0xbf: /* STT flash. */
@@ -531,6 +567,12 @@
 		rest_addr = 0x3fff;
 		sec_mask = 0x3c000;
 		break;
+	case 0x1f: // Atmel 26DF081A
+		rest_addr = 0x0fff;
+		sec_mask = 0xff000;
+		sec_end_mask = 0x003ff;
+		conf_addr = flash_conf_to_access_addr(0x0320);
+		break;
 	default:
 		/* Default to 64 kb sector size. */
 		rest_addr = 0x3fff;
@@ -545,11 +587,30 @@
 
 	/* Disable flash write-protection. */
 	qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
+	/* Some flash parts need an additional zero-write to clear bits.*/
+	qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
 
 	do {    /* Loop once to provide quick error exit. */
 		for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
+			if (man_id == 0x1f) {
+				findex = faddr << 2;
+				fdata = findex & sec_mask;
+			} else {
+				findex = faddr;
+				fdata = (findex & sec_mask) << 2;
+			}
+
 			/* Are we at the beginning of a sector? */
-			if ((faddr & rest_addr) == 0) {
+			if ((findex & rest_addr) == 0) {
+				/*
+				 * Do sector unprotect at 4K boundry for Atmel
+				 * part.
+				 */
+				if (man_id == 0x1f)
+					qla24xx_write_flash_dword(ha,
+					    flash_conf_to_access_addr(0x0339),
+					    (fdata & 0xff00) | ((fdata << 16) &
+					    0xff0000) | ((fdata >> 16) & 0xff));
 				fdata = (faddr & sec_mask) << 2;
 				ret = qla24xx_write_flash_dword(ha, conf_addr,
 				    (fdata & 0xff00) |((fdata << 16) &
@@ -570,6 +631,14 @@
 				    ha->host_no, faddr, *dwptr));
 				break;
 			}
+
+			/* Do sector protect at 4K boundry for Atmel part. */
+			if (man_id == 0x1f &&
+			    ((faddr & sec_end_mask) == 0x3ff))
+				qla24xx_write_flash_dword(ha,
+				    flash_conf_to_access_addr(0x0336),
+				    (fdata & 0xff00) | ((fdata << 16) &
+				    0xff0000) | ((fdata >> 16) & 0xff));
 		}
 	} while (0);
 
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index d537192..6b31552 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.01.04-k"
+#define QLA2XXX_VERSION      "8.01.05-k2"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	1
-#define QLA_DRIVER_PATCH_VER	4
+#define QLA_DRIVER_PATCH_VER	5
 #define QLA_DRIVER_BETA_VER	0
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index c7e78dc..329ead2 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1,6 +1,6 @@
 /* qlogicpti.c: Performance Technologies QlogicISP sbus card driver.
  *
- * Copyright (C) 1996 David S. Miller (davem@caipfs.rutgers.edu)
+ * Copyright (C) 1996, 2006 David S. Miller (davem@davemloft.net)
  *
  * A lot of this driver was directly stolen from Erik H. Moe's PCI
  * Qlogic ISP driver.  Mucho kudos to him for this code.
@@ -43,12 +43,9 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_eh.h>
-#include <scsi/scsi_request.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi_host.h>
 
-
-
 #define MAX_TARGETS	16
 #define MAX_LUNS	8	/* 32 for 1.31 F/W */
 
@@ -58,7 +55,6 @@
 
 static struct qlogicpti *qptichain = NULL;
 static DEFINE_SPINLOCK(qptichain_lock);
-static int qptis_running = 0;
 
 #define PACKB(a, b)			(((a)<<4)|(b))
 
@@ -132,7 +128,7 @@
 	PACKB(0, 0)	/* 0x0042 */
 };
 
-#define MAX_MBOX_COMMAND	(sizeof(mbox_param)/sizeof(u_short))
+#define MAX_MBOX_COMMAND	ARRAY_SIZE(mbox_param)
 
 /* queue length's _must_ be power of two: */
 #define QUEUE_DEPTH(in, out, ql)	((in - out) & (ql))
@@ -725,7 +721,7 @@
 			SA_SHIRQ, "Qlogic/PTI", qpti))
 		goto fail;
 
-	printk("qpti%d: IRQ %s ", qpti->qpti_id, __irq_itoa(qpti->irq));
+	printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->irq);
 
 	return 0;
 
@@ -816,180 +812,13 @@
 	return 0;
 }
 
-/* Detect all PTI Qlogic ISP's in the machine. */
-static int __init qlogicpti_detect(struct scsi_host_template *tpnt)
-{
-	struct qlogicpti *qpti;
-	struct Scsi_Host *qpti_host;
-	struct sbus_bus *sbus;
-	struct sbus_dev *sdev;
-	int nqptis = 0, nqptis_in_use = 0;
-
-	tpnt->proc_name = "qlogicpti";
-	for_each_sbus(sbus) {
-		for_each_sbusdev(sdev, sbus) {
-			/* Is this a red snapper? */
-			if (strcmp(sdev->prom_name, "ptisp") &&
-			    strcmp(sdev->prom_name, "PTI,ptisp") &&
-			    strcmp(sdev->prom_name, "QLGC,isp") &&
-			    strcmp(sdev->prom_name, "SUNW,isp"))
-				continue;
-
-			/* Sometimes Antares cards come up not completely
-			 * setup, and we get a report of a zero IRQ.
-			 * Skip over them in such cases so we survive.
-			 */
-			if (sdev->irqs[0] == 0) {
-				printk("qpti%d: Adapter reports no interrupt, "
-				       "skipping over this card.", nqptis);
-				continue;
-			}
-
-			/* Yep, register and allocate software state. */
-			qpti_host = scsi_register(tpnt, sizeof(struct qlogicpti));
-			if (!qpti_host) {
-				printk("QPTI: Cannot register PTI Qlogic ISP SCSI host");
-				continue;
-			}
-			qpti = (struct qlogicpti *) qpti_host->hostdata;
-
-			/* We are wide capable, 16 targets. */
-			qpti_host->max_id = MAX_TARGETS;
-
-			/* Setup back pointers and misc. state. */
-			qpti->qhost = qpti_host;
-			qpti->sdev = sdev;
-			qpti->qpti_id = nqptis++;
-			qpti->prom_node = sdev->prom_node;
-			prom_getstring(qpti->prom_node, "name",
-				       qpti->prom_name,
-				       sizeof(qpti->prom_name));
-
-			/* This is not correct, actually. There's a switch
-			 * on the PTI cards that put them into "emulation"
-			 * mode- i.e., report themselves as QLGC,isp
-			 * instead of PTI,ptisp. The only real substantive
-			 * difference between non-pti and pti cards is
-			 * the tmon register. Which is possibly even
-			 * there for Qlogic cards, but non-functional.
-			 */
-			qpti->is_pti = (strcmp (qpti->prom_name, "QLGC,isp") != 0);
-
-			qpti_chain_add(qpti);
-			if (qpti_map_regs(qpti) < 0)
-				goto fail_unlink;
-
-			if (qpti_register_irq(qpti) < 0)
-				goto fail_unmap_regs;
-
-			qpti_get_scsi_id(qpti);
-			qpti_get_bursts(qpti);
-			qpti_get_clock(qpti);
-
-			/* Clear out scsi_cmnd array. */
-			memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots));
-
-			if (qpti_map_queues(qpti) < 0)
-				goto fail_free_irq;
-
-			/* Load the firmware. */
-			if (qlogicpti_load_firmware(qpti))
-				goto fail_unmap_queues;
-			if (qpti->is_pti) {
-				/* Check the PTI status reg. */
-				if (qlogicpti_verify_tmon(qpti))
-					goto fail_unmap_queues;
-			}
-
-			/* Reset the ISP and init res/req queues. */
-			if (qlogicpti_reset_hardware(qpti_host))
-				goto fail_unmap_queues;
-
-			printk("(Firmware v%d.%d.%d)", qpti->fware_majrev,
-			    qpti->fware_minrev, qpti->fware_micrev);
-			{
-				char buffer[60];
-				
-				prom_getstring (qpti->prom_node,
-						"isp-fcode", buffer, 60);
-				if (buffer[0])
-					printk("(Firmware %s)", buffer);
-				if (prom_getbool(qpti->prom_node, "differential"))
-					qpti->differential = 1;
-			}
-			
-			printk (" [%s Wide, using %s interface]\n",
-			       (qpti->ultra ? "Ultra" : "Fast"),
-			       (qpti->differential ? "differential" : "single ended"));
-
-			nqptis_in_use++;
-			continue;
-
-		fail_unmap_queues:
-#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
-			sbus_free_consistent(qpti->sdev,
-					     QSIZE(RES_QUEUE_LEN),
-					     qpti->res_cpu, qpti->res_dvma);
-			sbus_free_consistent(qpti->sdev,
-					     QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
-					     qpti->req_cpu, qpti->req_dvma);
-#undef QSIZE
-		fail_free_irq:
-			free_irq(qpti->irq, qpti);
-
-		fail_unmap_regs:
-			sbus_iounmap(qpti->qregs,
-				     qpti->sdev->reg_addrs[0].reg_size);
-			if (qpti->is_pti)
-				sbus_iounmap(qpti->sreg, sizeof(unsigned char));
-		fail_unlink:
-			qpti_chain_del(qpti);
-			scsi_unregister(qpti->qhost);
-		}
-	}
-	if (nqptis)
-		printk("QPTI: Total of %d PTI Qlogic/ISP hosts found, %d actually in use.\n",
-		       nqptis, nqptis_in_use);
-	qptis_running = nqptis_in_use;
-	return nqptis;
-}
-
-static int qlogicpti_release(struct Scsi_Host *host)
-{
-	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
-
-	/* Remove visibility from IRQ handlers. */
-	qpti_chain_del(qpti);
-
-	/* Shut up the card. */
-	sbus_writew(0, qpti->qregs + SBUS_CTRL);
-
-	/* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */
-	free_irq(qpti->irq, qpti);
-
-#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
-	sbus_free_consistent(qpti->sdev,
-			     QSIZE(RES_QUEUE_LEN),
-			     qpti->res_cpu, qpti->res_dvma);
-	sbus_free_consistent(qpti->sdev,
-			     QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
-			     qpti->req_cpu, qpti->req_dvma);
-#undef QSIZE
-
-	sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size);
-	if (qpti->is_pti)
-		sbus_iounmap(qpti->sreg, sizeof(unsigned char));
-
-	return 0;
-}
-
 const char *qlogicpti_info(struct Scsi_Host *host)
 {
 	static char buf[80];
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
 
-	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %p",
-		__irq_itoa(qpti->qhost->irq), qpti->qregs);
+	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %d regs at %p",
+		qpti->qhost->irq, qpti->qregs);
 	return buf;
 }
 
@@ -1552,9 +1381,9 @@
 	return return_status;
 }
 
-static struct scsi_host_template driver_template = {
-	.detect			= qlogicpti_detect,
-	.release		= qlogicpti_release,
+static struct scsi_host_template qpti_template = {
+	.module			= THIS_MODULE,
+	.name			= "qlogicpti",
 	.info			= qlogicpti_info,
 	.queuecommand		= qlogicpti_queuecommand_slow,
 	.eh_abort_handler	= qlogicpti_abort,
@@ -1566,8 +1395,189 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 };
 
+static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	static int nqptis;
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+	struct device_node *dp = dev->node;
+	struct scsi_host_template *tpnt = match->data;
+	struct Scsi_Host *host;
+	struct qlogicpti *qpti;
+	char *fcode;
 
-#include "scsi_module.c"
+	/* Sometimes Antares cards come up not completely
+	 * setup, and we get a report of a zero IRQ.
+	 */
+	if (sdev->irqs[0] == 0)
+		return -ENODEV;
 
+	host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti));
+	if (!host)
+		return -ENOMEM;
+
+	qpti = (struct qlogicpti *) host->hostdata;
+
+	host->max_id = MAX_TARGETS;
+	qpti->qhost = host;
+	qpti->sdev = sdev;
+	qpti->qpti_id = nqptis;
+	qpti->prom_node = sdev->prom_node;
+	strcpy(qpti->prom_name, sdev->ofdev.node->name);
+	qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp");
+
+	if (qpti_map_regs(qpti) < 0)
+		goto fail_unlink;
+
+	if (qpti_register_irq(qpti) < 0)
+		goto fail_unmap_regs;
+
+	qpti_get_scsi_id(qpti);
+	qpti_get_bursts(qpti);
+	qpti_get_clock(qpti);
+
+	/* Clear out scsi_cmnd array. */
+	memset(qpti->cmd_slots, 0, sizeof(qpti->cmd_slots));
+
+	if (qpti_map_queues(qpti) < 0)
+		goto fail_free_irq;
+
+	/* Load the firmware. */
+	if (qlogicpti_load_firmware(qpti))
+		goto fail_unmap_queues;
+	if (qpti->is_pti) {
+		/* Check the PTI status reg. */
+		if (qlogicpti_verify_tmon(qpti))
+			goto fail_unmap_queues;
+	}
+
+	/* Reset the ISP and init res/req queues. */
+	if (qlogicpti_reset_hardware(host))
+		goto fail_unmap_queues;
+
+	if (scsi_add_host(host, &dev->dev))
+		goto fail_unmap_queues;
+
+	printk("(Firmware v%d.%d.%d)", qpti->fware_majrev,
+	       qpti->fware_minrev, qpti->fware_micrev);
+
+	fcode = of_get_property(dp, "isp-fcode", NULL);
+	if (fcode && fcode[0])
+		printk("(Firmware %s)", fcode);
+	if (of_find_property(dp, "differential", NULL) != NULL)
+		qpti->differential = 1;
+			
+	printk (" [%s Wide, using %s interface]\n",
+		(qpti->ultra ? "Ultra" : "Fast"),
+		(qpti->differential ? "differential" : "single ended"));
+
+	dev_set_drvdata(&sdev->ofdev.dev, qpti);
+
+	qpti_chain_add(qpti);
+
+	scsi_scan_host(host);
+	nqptis++;
+
+	return 0;
+
+fail_unmap_queues:
+#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
+	sbus_free_consistent(qpti->sdev,
+			     QSIZE(RES_QUEUE_LEN),
+			     qpti->res_cpu, qpti->res_dvma);
+	sbus_free_consistent(qpti->sdev,
+			     QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+			     qpti->req_cpu, qpti->req_dvma);
+#undef QSIZE
+
+fail_unmap_regs:
+	sbus_iounmap(qpti->qregs,
+		     qpti->sdev->reg_addrs[0].reg_size);
+	if (qpti->is_pti)
+		sbus_iounmap(qpti->sreg, sizeof(unsigned char));
+
+fail_free_irq:
+	free_irq(qpti->irq, qpti);
+
+fail_unlink:
+	scsi_host_put(host);
+
+	return -ENODEV;
+}
+
+static int __devexit qpti_sbus_remove(struct of_device *dev)
+{
+	struct qlogicpti *qpti = dev_get_drvdata(&dev->dev);
+
+	qpti_chain_del(qpti);
+
+	scsi_remove_host(qpti->qhost);
+
+	/* Shut up the card. */
+	sbus_writew(0, qpti->qregs + SBUS_CTRL);
+
+	/* Free IRQ handler and unmap Qlogic,ISP and PTI status regs. */
+	free_irq(qpti->irq, qpti);
+
+#define QSIZE(entries)	(((entries) + 1) * QUEUE_ENTRY_LEN)
+	sbus_free_consistent(qpti->sdev,
+			     QSIZE(RES_QUEUE_LEN),
+			     qpti->res_cpu, qpti->res_dvma);
+	sbus_free_consistent(qpti->sdev,
+			     QSIZE(QLOGICPTI_REQ_QUEUE_LEN),
+			     qpti->req_cpu, qpti->req_dvma);
+#undef QSIZE
+
+	sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size);
+	if (qpti->is_pti)
+		sbus_iounmap(qpti->sreg, sizeof(unsigned char));
+
+	scsi_host_put(qpti->qhost);
+
+	return 0;
+}
+
+static struct of_device_id qpti_match[] = {
+	{
+		.name = "ptisp",
+		.data = &qpti_template,
+	},
+	{
+		.name = "PTI,ptisp",
+		.data = &qpti_template,
+	},
+	{
+		.name = "QLGC,isp",
+		.data = &qpti_template,
+	},
+	{
+		.name = "SUNW,isp",
+		.data = &qpti_template,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, qpti_match);
+
+static struct of_platform_driver qpti_sbus_driver = {
+	.name		= "qpti",
+	.match_table	= qpti_match,
+	.probe		= qpti_sbus_probe,
+	.remove		= __devexit_p(qpti_sbus_remove),
+};
+
+static int __init qpti_init(void)
+{
+	return of_register_driver(&qpti_sbus_driver, &sbus_bus_type);
+}
+
+static void __exit qpti_exit(void)
+{
+	of_unregister_driver(&qpti_sbus_driver);
+}
+
+MODULE_DESCRIPTION("QlogicISP SBUS driver");
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
 MODULE_LICENSE("GPL");
+MODULE_VERSION("2.0");
 
+module_init(qpti_init);
+module_exit(qpti_exit);
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c
index 50c398a..327b33a 100644
--- a/drivers/scsi/raid_class.c
+++ b/drivers/scsi/raid_class.c
@@ -131,7 +131,7 @@
 	int i;
 	char *name = NULL;
 
-	for (i = 0; i < sizeof(raid_states)/sizeof(raid_states[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(raid_states); i++) {
 		if (raid_states[i].value == state) {
 			name = raid_states[i].name;
 			break;
@@ -161,7 +161,7 @@
 	int i;
 	char *name = NULL;
 
-	for (i = 0; i < sizeof(raid_levels)/sizeof(raid_levels[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(raid_levels); i++) {
 		if (raid_levels[i].value == level) {
 			name = raid_levels[i].name;
 			break;
diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c
index f16f92a..4a71578 100644
--- a/drivers/scsi/sata_mv.c
+++ b/drivers/scsi/sata_mv.c
@@ -93,7 +93,7 @@
 	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
 	MV_COMMON_FLAGS		= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				   ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO |
-				   ATA_FLAG_NO_ATAPI),
+				   ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING),
 	MV_6XXX_FLAGS		= MV_FLAG_IRQ_COALESCE,
 
 	CRQB_FLAG_READ		= (1 << 0),
@@ -272,33 +272,33 @@
 
 /* Command ReQuest Block: 32B */
 struct mv_crqb {
-	u32			sg_addr;
-	u32			sg_addr_hi;
-	u16			ctrl_flags;
-	u16			ata_cmd[11];
+	__le32			sg_addr;
+	__le32			sg_addr_hi;
+	__le16			ctrl_flags;
+	__le16			ata_cmd[11];
 };
 
 struct mv_crqb_iie {
-	u32			addr;
-	u32			addr_hi;
-	u32			flags;
-	u32			len;
-	u32			ata_cmd[4];
+	__le32			addr;
+	__le32			addr_hi;
+	__le32			flags;
+	__le32			len;
+	__le32			ata_cmd[4];
 };
 
 /* Command ResPonse Block: 8B */
 struct mv_crpb {
-	u16			id;
-	u16			flags;
-	u32			tmstmp;
+	__le16			id;
+	__le16			flags;
+	__le32			tmstmp;
 };
 
 /* EDMA Physical Region Descriptor (ePRD); A.K.A. SG */
 struct mv_sg {
-	u32			addr;
-	u32			flags_size;
-	u32			addr_hi;
-	u32			reserved;
+	__le32			addr;
+	__le32			flags_size;
+	__le32			addr_hi;
+	__le32			reserved;
 };
 
 struct mv_port_priv {
@@ -390,6 +390,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= MV_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -406,6 +407,7 @@
 
 	.qc_prep		= mv_qc_prep,
 	.qc_issue		= mv_qc_issue,
+	.data_xfer		= ata_mmio_data_xfer,
 
 	.eng_timeout		= mv_eng_timeout,
 
@@ -433,6 +435,7 @@
 
 	.qc_prep		= mv_qc_prep,
 	.qc_issue		= mv_qc_issue,
+	.data_xfer		= ata_mmio_data_xfer,
 
 	.eng_timeout		= mv_eng_timeout,
 
@@ -683,7 +686,7 @@
 	}
 
 	if (EDMA_EN & reg) {
-		printk(KERN_ERR "ata%u: Unable to stop eDMA\n", ap->id);
+		ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n");
 		/* FIXME: Consider doing a reset here to recover */
 	}
 }
@@ -1028,7 +1031,7 @@
 	return (index + 1) & MV_MAX_Q_DEPTH_MASK;
 }
 
-static inline void mv_crqb_pack_cmd(u16 *cmdw, u8 data, u8 addr, unsigned last)
+static inline void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last)
 {
 	u16 tmp = data | (addr << CRQB_CMD_ADDR_SHIFT) | CRQB_CMD_CS |
 		(last ? CRQB_CMD_LAST : 0);
@@ -1051,7 +1054,7 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct mv_port_priv *pp = ap->private_data;
-	u16 *cw;
+	__le16 *cw;
 	struct ata_taskfile *tf;
 	u16 flags = 0;
 	unsigned in_index;
@@ -1307,8 +1310,8 @@
 	edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
 
 	if (EDMA_ERR_SERR & edma_err_cause) {
-		serr = scr_read(ap, SCR_ERROR);
-		scr_write_flush(ap, SCR_ERROR, serr);
+		sata_scr_read(ap, SCR_ERROR, &serr);
+		sata_scr_write_flush(ap, SCR_ERROR, serr);
 	}
 	if (EDMA_ERR_SELF_DIS & edma_err_cause) {
 		struct mv_port_priv *pp	= ap->private_data;
@@ -1377,7 +1380,7 @@
 		/* Note that DEV_IRQ might happen spuriously during EDMA,
 		 * and should be ignored in such cases.
 		 * The cause of this is still under investigation.
-		 */ 
+		 */
 		if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
 			/* EDMA: check for response queue interrupt */
 			if ((CRPB_DMA_DONE << hard_port) & hc_irq_cause) {
@@ -1398,7 +1401,7 @@
 			}
 		}
 
-		if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))
+		if (ap && (ap->flags & ATA_FLAG_DISABLED))
 			continue;
 
 		err_mask = ac_err_mask(ata_status);
@@ -1419,7 +1422,7 @@
 				VPRINTK("port %u IRQ found for qc, "
 					"ata_status 0x%x\n", port,ata_status);
 				/* mark qc status appropriately */
-				if (!(qc->tf.ctl & ATA_NIEN)) {
+				if (!(qc->tf.flags & ATA_TFLAG_POLLING)) {
 					qc->err_mask |= err_mask;
 					ata_qc_complete(qc);
 				}
@@ -1949,15 +1952,16 @@
 
 	/* Issue COMRESET via SControl */
 comreset_retry:
-	scr_write_flush(ap, SCR_CONTROL, 0x301);
+	sata_scr_write_flush(ap, SCR_CONTROL, 0x301);
 	__msleep(1, can_sleep);
 
-	scr_write_flush(ap, SCR_CONTROL, 0x300);
+	sata_scr_write_flush(ap, SCR_CONTROL, 0x300);
 	__msleep(20, can_sleep);
 
 	timeout = jiffies + msecs_to_jiffies(200);
 	do {
-		sstatus = scr_read(ap, SCR_STATUS) & 0x3;
+		sata_scr_read(ap, SCR_STATUS, &sstatus);
+		sstatus &= 0x3;
 		if ((sstatus == 3) || (sstatus == 0))
 			break;
 
@@ -1974,11 +1978,12 @@
 		"SCtrl 0x%08x\n", mv_scr_read(ap, SCR_STATUS),
 		mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL));
 
-	if (sata_dev_present(ap)) {
+	if (ata_port_online(ap)) {
 		ata_port_probe(ap);
 	} else {
-		printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
-		       ap->id, scr_read(ap, SCR_STATUS));
+		sata_scr_read(ap, SCR_STATUS, &sstatus);
+		ata_port_printk(ap, KERN_INFO,
+				"no device found (phy stat %08x)\n", sstatus);
 		ata_port_disable(ap);
 		return;
 	}
@@ -2005,7 +2010,7 @@
 	tf.nsect = readb((void __iomem *) ap->ioaddr.nsect_addr);
 
 	dev->class = ata_dev_classify(&tf);
-	if (!ata_dev_present(dev)) {
+	if (!ata_dev_enabled(dev)) {
 		VPRINTK("Port disabled post-sig: No device present.\n");
 		ata_port_disable(ap);
 	}
@@ -2037,7 +2042,7 @@
 	struct ata_queued_cmd *qc;
 	unsigned long flags;
 
-	printk(KERN_ERR "ata%u: Entering mv_eng_timeout\n",ap->id);
+	ata_port_printk(ap, KERN_ERR, "Entering mv_eng_timeout\n");
 	DPRINTK("All regs @ start of eng_timeout\n");
 	mv_dump_all_regs(ap->host_set->mmio_base, ap->port_no,
 			 to_pci_dev(ap->host_set->dev));
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 9f55308..5cc42c6 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -44,7 +44,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"0.8"
+#define DRV_VERSION			"2.0"
 
 enum {
 	NV_PORTS			= 2,
@@ -54,40 +54,25 @@
 	NV_PORT0_SCR_REG_OFFSET		= 0x00,
 	NV_PORT1_SCR_REG_OFFSET		= 0x40,
 
+	/* INT_STATUS/ENABLE */
 	NV_INT_STATUS			= 0x10,
-	NV_INT_STATUS_CK804		= 0x440,
-	NV_INT_STATUS_PDEV_INT		= 0x01,
-	NV_INT_STATUS_PDEV_PM		= 0x02,
-	NV_INT_STATUS_PDEV_ADDED	= 0x04,
-	NV_INT_STATUS_PDEV_REMOVED	= 0x08,
-	NV_INT_STATUS_SDEV_INT		= 0x10,
-	NV_INT_STATUS_SDEV_PM		= 0x20,
-	NV_INT_STATUS_SDEV_ADDED	= 0x40,
-	NV_INT_STATUS_SDEV_REMOVED	= 0x80,
-	NV_INT_STATUS_PDEV_HOTPLUG	= (NV_INT_STATUS_PDEV_ADDED |
-					   NV_INT_STATUS_PDEV_REMOVED),
-	NV_INT_STATUS_SDEV_HOTPLUG	= (NV_INT_STATUS_SDEV_ADDED |
-					   NV_INT_STATUS_SDEV_REMOVED),
-	NV_INT_STATUS_HOTPLUG		= (NV_INT_STATUS_PDEV_HOTPLUG |
-					   NV_INT_STATUS_SDEV_HOTPLUG),
-
 	NV_INT_ENABLE			= 0x11,
+	NV_INT_STATUS_CK804		= 0x440,
 	NV_INT_ENABLE_CK804		= 0x441,
-	NV_INT_ENABLE_PDEV_MASK		= 0x01,
-	NV_INT_ENABLE_PDEV_PM		= 0x02,
-	NV_INT_ENABLE_PDEV_ADDED	= 0x04,
-	NV_INT_ENABLE_PDEV_REMOVED	= 0x08,
-	NV_INT_ENABLE_SDEV_MASK		= 0x10,
-	NV_INT_ENABLE_SDEV_PM		= 0x20,
-	NV_INT_ENABLE_SDEV_ADDED	= 0x40,
-	NV_INT_ENABLE_SDEV_REMOVED	= 0x80,
-	NV_INT_ENABLE_PDEV_HOTPLUG	= (NV_INT_ENABLE_PDEV_ADDED |
-					   NV_INT_ENABLE_PDEV_REMOVED),
-	NV_INT_ENABLE_SDEV_HOTPLUG	= (NV_INT_ENABLE_SDEV_ADDED |
-					   NV_INT_ENABLE_SDEV_REMOVED),
-	NV_INT_ENABLE_HOTPLUG		= (NV_INT_ENABLE_PDEV_HOTPLUG |
-					   NV_INT_ENABLE_SDEV_HOTPLUG),
 
+	/* INT_STATUS/ENABLE bits */
+	NV_INT_DEV			= 0x01,
+	NV_INT_PM			= 0x02,
+	NV_INT_ADDED			= 0x04,
+	NV_INT_REMOVED			= 0x08,
+
+	NV_INT_PORT_SHIFT		= 4,	/* each port occupies 4 bits */
+
+	NV_INT_ALL			= 0x0f,
+	NV_INT_MASK			= NV_INT_DEV |
+					  NV_INT_ADDED | NV_INT_REMOVED,
+
+	/* INT_CONFIG */
 	NV_INT_CONFIG			= 0x12,
 	NV_INT_CONFIG_METHD		= 0x01, // 0 = INT, 1 = SMI
 
@@ -97,23 +82,27 @@
 };
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-static irqreturn_t nv_interrupt (int irq, void *dev_instance,
-				 struct pt_regs *regs);
+static void nv_ck804_host_stop(struct ata_host_set *host_set);
+static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
+					struct pt_regs *regs);
+static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
+				    struct pt_regs *regs);
+static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
+				      struct pt_regs *regs);
 static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
-static void nv_host_stop (struct ata_host_set *host_set);
-static void nv_enable_hotplug(struct ata_probe_ent *probe_ent);
-static void nv_disable_hotplug(struct ata_host_set *host_set);
-static int nv_check_hotplug(struct ata_host_set *host_set);
-static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent);
-static void nv_disable_hotplug_ck804(struct ata_host_set *host_set);
-static int nv_check_hotplug_ck804(struct ata_host_set *host_set);
+
+static void nv_nf2_freeze(struct ata_port *ap);
+static void nv_nf2_thaw(struct ata_port *ap);
+static void nv_ck804_freeze(struct ata_port *ap);
+static void nv_ck804_thaw(struct ata_port *ap);
+static void nv_error_handler(struct ata_port *ap);
 
 enum nv_host_type
 {
 	GENERIC,
 	NFORCE2,
-	NFORCE3,
+	NFORCE3 = NFORCE2,	/* NF2 == NF3 as far as sata_nv is concerned */
 	CK804
 };
 
@@ -140,6 +129,16 @@
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2,
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, 0x045c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, 0x045d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, 0x045e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
+	{ PCI_VENDOR_ID_NVIDIA, 0x045f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GENERIC },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
 		PCI_ANY_ID, PCI_ANY_ID,
 		PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
@@ -149,46 +148,6 @@
 	{ 0, } /* terminate list */
 };
 
-struct nv_host_desc
-{
-	enum nv_host_type	host_type;
-	void			(*enable_hotplug)(struct ata_probe_ent *probe_ent);
-	void			(*disable_hotplug)(struct ata_host_set *host_set);
-	int			(*check_hotplug)(struct ata_host_set *host_set);
-
-};
-static struct nv_host_desc nv_device_tbl[] = {
-	{
-		.host_type	= GENERIC,
-		.enable_hotplug	= NULL,
-		.disable_hotplug= NULL,
-		.check_hotplug	= NULL,
-	},
-	{
-		.host_type	= NFORCE2,
-		.enable_hotplug	= nv_enable_hotplug,
-		.disable_hotplug= nv_disable_hotplug,
-		.check_hotplug	= nv_check_hotplug,
-	},
-	{
-		.host_type	= NFORCE3,
-		.enable_hotplug	= nv_enable_hotplug,
-		.disable_hotplug= nv_disable_hotplug,
-		.check_hotplug	= nv_check_hotplug,
-	},
-	{	.host_type	= CK804,
-		.enable_hotplug	= nv_enable_hotplug_ck804,
-		.disable_hotplug= nv_disable_hotplug_ck804,
-		.check_hotplug	= nv_check_hotplug_ck804,
-	},
-};
-
-struct nv_host
-{
-	struct nv_host_desc	*host_desc;
-	unsigned long		host_flags;
-};
-
 static struct pci_driver nv_pci_driver = {
 	.name			= DRV_NAME,
 	.id_table		= nv_pci_tbl,
@@ -210,51 +169,119 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
-static const struct ata_port_operations nv_ops = {
+static const struct ata_port_operations nv_generic_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= ata_tf_load,
 	.tf_read		= ata_tf_read,
 	.exec_command		= ata_exec_command,
 	.check_status		= ata_check_status,
 	.dev_select		= ata_std_dev_select,
-	.phy_reset		= sata_phy_reset,
 	.bmdma_setup		= ata_bmdma_setup,
 	.bmdma_start		= ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.eng_timeout		= ata_eng_timeout,
-	.irq_handler		= nv_interrupt,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= nv_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+	.data_xfer		= ata_pio_data_xfer,
+	.irq_handler		= nv_generic_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= nv_scr_read,
 	.scr_write		= nv_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
-	.host_stop		= nv_host_stop,
+	.host_stop		= ata_pci_host_stop,
 };
 
-/* FIXME: The hardware provides the necessary SATA PHY controls
- * to support ATA_FLAG_SATA_RESET.  However, it is currently
- * necessary to disable that flag, to solve misdetection problems.
- * See http://bugme.osdl.org/show_bug.cgi?id=3352 for more info.
- *
- * This problem really needs to be investigated further.  But in the
- * meantime, we avoid ATA_FLAG_SATA_RESET to get people working.
- */
-static struct ata_port_info nv_port_info = {
-	.sht		= &nv_sht,
-	.host_flags	= ATA_FLAG_SATA |
-			  /* ATA_FLAG_SATA_RESET | */
-			  ATA_FLAG_SRST |
-			  ATA_FLAG_NO_LEGACY,
-	.pio_mask	= NV_PIO_MASK,
-	.mwdma_mask	= NV_MWDMA_MASK,
-	.udma_mask	= NV_UDMA_MASK,
-	.port_ops	= &nv_ops,
+static const struct ata_port_operations nv_nf2_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
+	.dev_select		= ata_std_dev_select,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
+	.bmdma_stop		= ata_bmdma_stop,
+	.bmdma_status		= ata_bmdma_status,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.freeze			= nv_nf2_freeze,
+	.thaw			= nv_nf2_thaw,
+	.error_handler		= nv_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+	.data_xfer		= ata_pio_data_xfer,
+	.irq_handler		= nv_nf2_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.scr_read		= nv_scr_read,
+	.scr_write		= nv_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+	.host_stop		= ata_pci_host_stop,
+};
+
+static const struct ata_port_operations nv_ck804_ops = {
+	.port_disable		= ata_port_disable,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
+	.dev_select		= ata_std_dev_select,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
+	.bmdma_stop		= ata_bmdma_stop,
+	.bmdma_status		= ata_bmdma_status,
+	.qc_prep		= ata_qc_prep,
+	.qc_issue		= ata_qc_issue_prot,
+	.freeze			= nv_ck804_freeze,
+	.thaw			= nv_ck804_thaw,
+	.error_handler		= nv_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+	.data_xfer		= ata_pio_data_xfer,
+	.irq_handler		= nv_ck804_interrupt,
+	.irq_clear		= ata_bmdma_irq_clear,
+	.scr_read		= nv_scr_read,
+	.scr_write		= nv_scr_write,
+	.port_start		= ata_port_start,
+	.port_stop		= ata_port_stop,
+	.host_stop		= nv_ck804_host_stop,
+};
+
+static struct ata_port_info nv_port_info[] = {
+	/* generic */
+	{
+		.sht		= &nv_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.pio_mask	= NV_PIO_MASK,
+		.mwdma_mask	= NV_MWDMA_MASK,
+		.udma_mask	= NV_UDMA_MASK,
+		.port_ops	= &nv_generic_ops,
+	},
+	/* nforce2/3 */
+	{
+		.sht		= &nv_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.pio_mask	= NV_PIO_MASK,
+		.mwdma_mask	= NV_MWDMA_MASK,
+		.udma_mask	= NV_UDMA_MASK,
+		.port_ops	= &nv_nf2_ops,
+	},
+	/* ck804 */
+	{
+		.sht		= &nv_sht,
+		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.pio_mask	= NV_PIO_MASK,
+		.mwdma_mask	= NV_MWDMA_MASK,
+		.udma_mask	= NV_UDMA_MASK,
+		.port_ops	= &nv_ck804_ops,
+	},
 };
 
 MODULE_AUTHOR("NVIDIA");
@@ -263,11 +290,10 @@
 MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
-static irqreturn_t nv_interrupt (int irq, void *dev_instance,
-				 struct pt_regs *regs)
+static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance,
+					struct pt_regs *regs)
 {
 	struct ata_host_set *host_set = dev_instance;
-	struct nv_host *host = host_set->private_data;
 	unsigned int i;
 	unsigned int handled = 0;
 	unsigned long flags;
@@ -279,11 +305,11 @@
 
 		ap = host_set->ports[i];
 		if (ap &&
-		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
+		    !(ap->flags & ATA_FLAG_DISABLED)) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
 				handled += ata_host_intr(ap, qc);
 			else
 				// No request pending?  Clear interrupt status
@@ -293,14 +319,88 @@
 
 	}
 
-	if (host->host_desc->check_hotplug)
-		handled += host->host_desc->check_hotplug(host_set);
-
 	spin_unlock_irqrestore(&host_set->lock, flags);
 
 	return IRQ_RETVAL(handled);
 }
 
+static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
+{
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+	int handled;
+
+	/* freeze if hotplugged */
+	if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
+		ata_port_freeze(ap);
+		return 1;
+	}
+
+	/* bail out if not our interrupt */
+	if (!(irq_stat & NV_INT_DEV))
+		return 0;
+
+	/* DEV interrupt w/ no active qc? */
+	if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
+		ata_check_status(ap);
+		return 1;
+	}
+
+	/* handle interrupt */
+	handled = ata_host_intr(ap, qc);
+	if (unlikely(!handled)) {
+		/* spurious, clear it */
+		ata_check_status(ap);
+	}
+
+	return 1;
+}
+
+static irqreturn_t nv_do_interrupt(struct ata_host_set *host_set, u8 irq_stat)
+{
+	int i, handled = 0;
+
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap = host_set->ports[i];
+
+		if (ap && !(ap->flags & ATA_FLAG_DISABLED))
+			handled += nv_host_intr(ap, irq_stat);
+
+		irq_stat >>= NV_INT_PORT_SHIFT;
+	}
+
+	return IRQ_RETVAL(handled);
+}
+
+static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance,
+				    struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	u8 irq_stat;
+	irqreturn_t ret;
+
+	spin_lock(&host_set->lock);
+	irq_stat = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
+	ret = nv_do_interrupt(host_set, irq_stat);
+	spin_unlock(&host_set->lock);
+
+	return ret;
+}
+
+static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance,
+				      struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	u8 irq_stat;
+	irqreturn_t ret;
+
+	spin_lock(&host_set->lock);
+	irq_stat = readb(host_set->mmio_base + NV_INT_STATUS_CK804);
+	ret = nv_do_interrupt(host_set, irq_stat);
+	spin_unlock(&host_set->lock);
+
+	return ret;
+}
+
 static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
 	if (sc_reg > SCR_CONTROL)
@@ -317,23 +417,74 @@
 	iowrite32(val, (void __iomem *)ap->ioaddr.scr_addr + (sc_reg * 4));
 }
 
-static void nv_host_stop (struct ata_host_set *host_set)
+static void nv_nf2_freeze(struct ata_port *ap)
 {
-	struct nv_host *host = host_set->private_data;
+	unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
+	int shift = ap->port_no * NV_INT_PORT_SHIFT;
+	u8 mask;
 
-	// Disable hotplug event interrupts.
-	if (host->host_desc->disable_hotplug)
-		host->host_desc->disable_hotplug(host_set);
+	mask = inb(scr_addr + NV_INT_ENABLE);
+	mask &= ~(NV_INT_ALL << shift);
+	outb(mask, scr_addr + NV_INT_ENABLE);
+}
 
-	kfree(host);
+static void nv_nf2_thaw(struct ata_port *ap)
+{
+	unsigned long scr_addr = ap->host_set->ports[0]->ioaddr.scr_addr;
+	int shift = ap->port_no * NV_INT_PORT_SHIFT;
+	u8 mask;
 
-	ata_pci_host_stop(host_set);
+	outb(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
+
+	mask = inb(scr_addr + NV_INT_ENABLE);
+	mask |= (NV_INT_MASK << shift);
+	outb(mask, scr_addr + NV_INT_ENABLE);
+}
+
+static void nv_ck804_freeze(struct ata_port *ap)
+{
+	void __iomem *mmio_base = ap->host_set->mmio_base;
+	int shift = ap->port_no * NV_INT_PORT_SHIFT;
+	u8 mask;
+
+	mask = readb(mmio_base + NV_INT_ENABLE_CK804);
+	mask &= ~(NV_INT_ALL << shift);
+	writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
+}
+
+static void nv_ck804_thaw(struct ata_port *ap)
+{
+	void __iomem *mmio_base = ap->host_set->mmio_base;
+	int shift = ap->port_no * NV_INT_PORT_SHIFT;
+	u8 mask;
+
+	writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804);
+
+	mask = readb(mmio_base + NV_INT_ENABLE_CK804);
+	mask |= (NV_INT_MASK << shift);
+	writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
+}
+
+static int nv_hardreset(struct ata_port *ap, unsigned int *class)
+{
+	unsigned int dummy;
+
+	/* SATA hardreset fails to retrieve proper device signature on
+	 * some controllers.  Don't classify on hardreset.  For more
+	 * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
+	 */
+	return sata_std_hardreset(ap, &dummy);
+}
+
+static void nv_error_handler(struct ata_port *ap)
+{
+	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
+			   nv_hardreset, ata_std_postreset);
 }
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version = 0;
-	struct nv_host *host;
 	struct ata_port_info *ppi;
 	struct ata_probe_ent *probe_ent;
 	int pci_dev_busy = 0;
@@ -370,24 +521,15 @@
 
 	rc = -ENOMEM;
 
-	ppi = &nv_port_info;
+	ppi = &nv_port_info[ent->driver_data];
 	probe_ent = ata_pci_init_native_mode(pdev, &ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
 	if (!probe_ent)
 		goto err_out_regions;
 
-	host = kmalloc(sizeof(struct nv_host), GFP_KERNEL);
-	if (!host)
-		goto err_out_free_ent;
-
-	memset(host, 0, sizeof(struct nv_host));
-	host->host_desc = &nv_device_tbl[ent->driver_data];
-
-	probe_ent->private_data = host;
-
 	probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
 	if (!probe_ent->mmio_base) {
 		rc = -EIO;
-		goto err_out_free_host;
+		goto err_out_free_ent;
 	}
 
 	base = (unsigned long)probe_ent->mmio_base;
@@ -395,24 +537,27 @@
 	probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
 	probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
 
+	/* enable SATA space for CK804 */
+	if (ent->driver_data == CK804) {
+		u8 regval;
+
+		pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
+		regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
+		pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
+	}
+
 	pci_set_master(pdev);
 
 	rc = ata_device_add(probe_ent);
 	if (rc != NV_PORTS)
 		goto err_out_iounmap;
 
-	// Enable hotplug event interrupts.
-	if (host->host_desc->enable_hotplug)
-		host->host_desc->enable_hotplug(probe_ent);
-
 	kfree(probe_ent);
 
 	return 0;
 
 err_out_iounmap:
 	pci_iounmap(pdev, probe_ent->mmio_base);
-err_out_free_host:
-	kfree(host);
 err_out_free_ent:
 	kfree(probe_ent);
 err_out_regions:
@@ -424,127 +569,17 @@
 	return rc;
 }
 
-static void nv_enable_hotplug(struct ata_probe_ent *probe_ent)
-{
-	u8 intr_mask;
-
-	outb(NV_INT_STATUS_HOTPLUG,
-		probe_ent->port[0].scr_addr + NV_INT_STATUS);
-
-	intr_mask = inb(probe_ent->port[0].scr_addr + NV_INT_ENABLE);
-	intr_mask |= NV_INT_ENABLE_HOTPLUG;
-
-	outb(intr_mask, probe_ent->port[0].scr_addr + NV_INT_ENABLE);
-}
-
-static void nv_disable_hotplug(struct ata_host_set *host_set)
-{
-	u8 intr_mask;
-
-	intr_mask = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
-
-	intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
-
-	outb(intr_mask, host_set->ports[0]->ioaddr.scr_addr + NV_INT_ENABLE);
-}
-
-static int nv_check_hotplug(struct ata_host_set *host_set)
-{
-	u8 intr_status;
-
-	intr_status = inb(host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
-
-	// Clear interrupt status.
-	outb(0xff, host_set->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
-
-	if (intr_status & NV_INT_STATUS_HOTPLUG) {
-		if (intr_status & NV_INT_STATUS_PDEV_ADDED)
-			printk(KERN_WARNING "nv_sata: "
-				"Primary device added\n");
-
-		if (intr_status & NV_INT_STATUS_PDEV_REMOVED)
-			printk(KERN_WARNING "nv_sata: "
-				"Primary device removed\n");
-
-		if (intr_status & NV_INT_STATUS_SDEV_ADDED)
-			printk(KERN_WARNING "nv_sata: "
-				"Secondary device added\n");
-
-		if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
-			printk(KERN_WARNING "nv_sata: "
-				"Secondary device removed\n");
-
-		return 1;
-	}
-
-	return 0;
-}
-
-static void nv_enable_hotplug_ck804(struct ata_probe_ent *probe_ent)
-{
-	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-	u8 intr_mask;
-	u8 regval;
-
-	pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
-	regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
-	pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
-
-	writeb(NV_INT_STATUS_HOTPLUG, probe_ent->mmio_base + NV_INT_STATUS_CK804);
-
-	intr_mask = readb(probe_ent->mmio_base + NV_INT_ENABLE_CK804);
-	intr_mask |= NV_INT_ENABLE_HOTPLUG;
-
-	writeb(intr_mask, probe_ent->mmio_base + NV_INT_ENABLE_CK804);
-}
-
-static void nv_disable_hotplug_ck804(struct ata_host_set *host_set)
+static void nv_ck804_host_stop(struct ata_host_set *host_set)
 {
 	struct pci_dev *pdev = to_pci_dev(host_set->dev);
-	u8 intr_mask;
 	u8 regval;
 
-	intr_mask = readb(host_set->mmio_base + NV_INT_ENABLE_CK804);
-
-	intr_mask &= ~(NV_INT_ENABLE_HOTPLUG);
-
-	writeb(intr_mask, host_set->mmio_base + NV_INT_ENABLE_CK804);
-
+	/* disable SATA space for CK804 */
 	pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, &regval);
 	regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
 	pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
-}
 
-static int nv_check_hotplug_ck804(struct ata_host_set *host_set)
-{
-	u8 intr_status;
-
-	intr_status = readb(host_set->mmio_base + NV_INT_STATUS_CK804);
-
-	// Clear interrupt status.
-	writeb(0xff, host_set->mmio_base + NV_INT_STATUS_CK804);
-
-	if (intr_status & NV_INT_STATUS_HOTPLUG) {
-		if (intr_status & NV_INT_STATUS_PDEV_ADDED)
-			printk(KERN_WARNING "nv_sata: "
-				"Primary device added\n");
-
-		if (intr_status & NV_INT_STATUS_PDEV_REMOVED)
-			printk(KERN_WARNING "nv_sata: "
-				"Primary device removed\n");
-
-		if (intr_status & NV_INT_STATUS_SDEV_ADDED)
-			printk(KERN_WARNING "nv_sata: "
-				"Secondary device added\n");
-
-		if (intr_status & NV_INT_STATUS_SDEV_REMOVED)
-			printk(KERN_WARNING "nv_sata: "
-				"Secondary device removed\n");
-
-		return 1;
-	}
-
-	return 0;
+	ata_pci_host_stop(host_set);
 }
 
 static int __init nv_init(void)
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 7eb67a6..b2b6ed5 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -76,7 +76,8 @@
 	PDC_RESET		= (1 << 11), /* HDMA reset */
 
 	PDC_COMMON_FLAGS	= ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
-				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI,
+				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+				  ATA_FLAG_PIO_POLLING,
 };
 
 
@@ -120,6 +121,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -136,6 +138,7 @@
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
 	.eng_timeout		= pdc_eng_timeout,
+	.data_xfer		= ata_mmio_data_xfer,
 	.irq_handler		= pdc_interrupt,
 	.irq_clear		= pdc_irq_clear,
 
@@ -158,6 +161,7 @@
 
 	.qc_prep		= pdc_qc_prep,
 	.qc_issue		= pdc_qc_issue_prot,
+	.data_xfer		= ata_mmio_data_xfer,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc_interrupt,
 	.irq_clear		= pdc_irq_clear,
@@ -363,12 +367,23 @@
 	sata_phy_reset(ap);
 }
 
+static void pdc_pata_cbl_detect(struct ata_port *ap)
+{
+	u8 tmp;
+	void __iomem *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
+
+	tmp = readb(mmio);
+
+	if (tmp & 0x01) {
+		ap->cbl = ATA_CBL_PATA40;
+		ap->udma_mask &= ATA_UDMA_MASK_40C;
+	} else
+		ap->cbl = ATA_CBL_PATA80;
+}
+
 static void pdc_pata_phy_reset(struct ata_port *ap)
 {
-	/* FIXME: add cable detect.  Don't assume 40-pin cable */
-	ap->cbl = ATA_CBL_PATA40;
-	ap->udma_mask &= ATA_UDMA_MASK_40C;
-
+	pdc_pata_cbl_detect(ap);
 	pdc_reset_port(ap);
 	ata_port_probe(ap);
 	ata_bus_reset(ap);
@@ -435,7 +450,7 @@
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
-		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_port_printk(ap, KERN_ERR, "command timeout\n");
 		drv_stat = ata_wait_idle(ap);
 		qc->err_mask |= __ac_err_mask(drv_stat);
 		break;
@@ -443,8 +458,9 @@
 	default:
 		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 
-		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
+		ata_port_printk(ap, KERN_ERR,
+				"unknown timeout, cmd 0x%x stat 0x%x\n",
+				qc->tf.command, drv_stat);
 
 		qc->err_mask |= ac_err_mask(drv_stat);
 		break;
@@ -533,11 +549,11 @@
 		ap = host_set->ports[i];
 		tmp = mask & (1 << (i + 1));
 		if (tmp && ap &&
-		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
+		    !(ap->flags & ATA_FLAG_DISABLED)) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
 				handled += pdc_host_intr(ap, qc);
 		}
 	}
@@ -676,10 +692,6 @@
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	/*
-	 * If this driver happens to only be useful on Apple's K2, then
-	 * we should check that here as it has a normal Serverworks ID
-	 */
 	rc = pci_enable_device(pdev);
 	if (rc)
 		return rc;
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index 886f344..98ddc25 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -41,7 +41,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_qstor"
-#define DRV_VERSION	"0.05"
+#define DRV_VERSION	"0.06"
 
 enum {
 	QS_PORTS		= 4,
@@ -142,6 +142,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= QS_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -156,6 +157,7 @@
 	.phy_reset		= qs_phy_reset,
 	.qc_prep		= qs_qc_prep,
 	.qc_issue		= qs_qc_issue,
+	.data_xfer		= ata_mmio_data_xfer,
 	.eng_timeout		= qs_eng_timeout,
 	.irq_handler		= qs_intr,
 	.irq_clear		= qs_irq_clear,
@@ -175,7 +177,7 @@
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SATA_RESET |
 				  //FIXME ATA_FLAG_SRST |
-				  ATA_FLAG_MMIO,
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x10, /* pio4 */
 		.udma_mask	= 0x7f, /* udma0-6 */
 		.port_ops	= &qs_ata_ops,
@@ -394,14 +396,13 @@
 			DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n",
 					sff1, sff0, port_no, sHST, sDST);
 			handled = 1;
-			if (ap && !(ap->flags &
-				    (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
+			if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
 				struct ata_queued_cmd *qc;
 				struct qs_port_priv *pp = ap->private_data;
 				if (!pp || pp->state != qs_state_pkt)
 					continue;
 				qc = ata_qc_from_tag(ap, ap->active_tag);
-				if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+				if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
 					switch (sHST) {
 					case 0: /* successful CPB */
 					case 3: /* device error */
@@ -428,13 +429,13 @@
 		struct ata_port *ap;
 		ap = host_set->ports[port_no];
 		if (ap &&
-		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
+		    !(ap->flags & ATA_FLAG_DISABLED)) {
 			struct ata_queued_cmd *qc;
 			struct qs_port_priv *pp = ap->private_data;
 			if (!pp || pp->state != qs_state_mmio)
 				continue;
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
 
 				/* check main status, clearing INTRQ */
 				u8 status = ata_check_status(ap);
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 1066272..51d86d7 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -46,23 +46,26 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_sil"
-#define DRV_VERSION	"0.9"
+#define DRV_VERSION	"2.0"
 
 enum {
 	/*
 	 * host flags
 	 */
+	SIL_FLAG_NO_SATA_IRQ	= (1 << 28),
 	SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
 	SIL_FLAG_MOD15WRITE	= (1 << 30),
+
 	SIL_DFL_HOST_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO,
+				  ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME,
 
 	/*
 	 * Controller IDs
 	 */
 	sil_3112		= 0,
-	sil_3512		= 1,
-	sil_3114		= 2,
+	sil_3112_no_sata_irq	= 1,
+	sil_3512		= 2,
+	sil_3114		= 3,
 
 	/*
 	 * Register offsets
@@ -84,6 +87,20 @@
 	/* BMDMA/BMDMA2 */
 	SIL_INTR_STEERING	= (1 << 1),
 
+	SIL_DMA_ENABLE		= (1 << 0),  /* DMA run switch */
+	SIL_DMA_RDWR		= (1 << 3),  /* DMA Rd-Wr */
+	SIL_DMA_SATA_IRQ	= (1 << 4),  /* OR of all SATA IRQs */
+	SIL_DMA_ACTIVE		= (1 << 16), /* DMA running */
+	SIL_DMA_ERROR		= (1 << 17), /* PCI bus error */
+	SIL_DMA_COMPLETE	= (1 << 18), /* cmd complete / IRQ pending */
+	SIL_DMA_N_SATA_IRQ	= (1 << 6),  /* SATA_IRQ for the next channel */
+	SIL_DMA_N_ACTIVE	= (1 << 24), /* ACTIVE for the next channel */
+	SIL_DMA_N_ERROR		= (1 << 25), /* ERROR for the next channel */
+	SIL_DMA_N_COMPLETE	= (1 << 26), /* COMPLETE for the next channel */
+
+	/* SIEN */
+	SIL_SIEN_N		= (1 << 16), /* triggered by SError.N */
+
 	/*
 	 * Others
 	 */
@@ -96,6 +113,10 @@
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void sil_post_set_mode (struct ata_port *ap);
+static irqreturn_t sil_interrupt(int irq, void *dev_instance,
+				 struct pt_regs *regs);
+static void sil_freeze(struct ata_port *ap);
+static void sil_thaw(struct ata_port *ap);
 
 
 static const struct pci_device_id sil_pci_tbl[] = {
@@ -104,8 +125,8 @@
 	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
 	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
 	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
+	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
 	{ }	/* terminate list */
 };
 
@@ -155,6 +176,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -166,7 +188,6 @@
 	.check_status		= ata_check_status,
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
-	.probe_reset		= ata_std_probe_reset,
 	.post_set_mode		= sil_post_set_mode,
 	.bmdma_setup            = ata_bmdma_setup,
 	.bmdma_start            = ata_bmdma_start,
@@ -174,8 +195,12 @@
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.eng_timeout		= ata_eng_timeout,
-	.irq_handler		= ata_interrupt,
+	.data_xfer		= ata_mmio_data_xfer,
+	.freeze			= sil_freeze,
+	.thaw			= sil_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+	.irq_handler		= sil_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= sil_scr_read,
 	.scr_write		= sil_scr_write,
@@ -194,6 +219,16 @@
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	},
+	/* sil_3112_no_sata_irq */
+	{
+		.sht		= &sil_sht,
+		.host_flags	= SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE |
+				  SIL_FLAG_NO_SATA_IRQ,
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil_ops,
+	},
 	/* sil_3512 */
 	{
 		.sht		= &sil_sht,
@@ -220,6 +255,7 @@
 	unsigned long tf;	/* ATA taskfile register block */
 	unsigned long ctl;	/* ATA control/altstatus register block */
 	unsigned long bmdma;	/* DMA register block */
+	unsigned long bmdma2;	/* DMA register block #2 */
 	unsigned long fifo_cfg;	/* FIFO Valid Byte Count and Control */
 	unsigned long scr;	/* SATA control register block */
 	unsigned long sien;	/* SATA Interrupt Enable register */
@@ -227,10 +263,10 @@
 	unsigned long sfis_cfg;	/* SATA FIS reception config register */
 } sil_port[] = {
 	/* port 0 ... */
-	{ 0x80, 0x8A, 0x00, 0x40, 0x100, 0x148, 0xb4, 0x14c },
-	{ 0xC0, 0xCA, 0x08, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
-	{ 0x280, 0x28A, 0x200, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
-	{ 0x2C0, 0x2CA, 0x208, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
+	{ 0x80, 0x8A, 0x00, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c },
+	{ 0xC0, 0xCA, 0x08, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc },
+	{ 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c },
+	{ 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc },
 	/* ... port 3 */
 };
 
@@ -263,7 +299,7 @@
 
 	for (i = 0; i < 2; i++) {
 		dev = &ap->device[i];
-		if (!ata_dev_present(dev))
+		if (!ata_dev_enabled(dev))
 			dev_mode[i] = 0;	/* PIO0/1/2 */
 		else if (dev->flags & ATA_DFLAG_PIO)
 			dev_mode[i] = 1;	/* PIO3/4 */
@@ -314,6 +350,156 @@
 		writel(val, mmio);
 }
 
+static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+{
+	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
+	u8 status;
+
+	if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) {
+		u32 serror;
+
+		/* SIEN doesn't mask SATA IRQs on some 3112s.  Those
+		 * controllers continue to assert IRQ as long as
+		 * SError bits are pending.  Clear SError immediately.
+		 */
+		serror = sil_scr_read(ap, SCR_ERROR);
+		sil_scr_write(ap, SCR_ERROR, serror);
+
+		/* Trigger hotplug and accumulate SError only if the
+		 * port isn't already frozen.  Otherwise, PHY events
+		 * during hardreset makes controllers with broken SIEN
+		 * repeat probing needlessly.
+		 */
+		if (!(ap->flags & ATA_FLAG_FROZEN)) {
+			ata_ehi_hotplugged(&ap->eh_info);
+			ap->eh_info.serror |= serror;
+		}
+
+		goto freeze;
+	}
+
+	if (unlikely(!qc || qc->tf.ctl & ATA_NIEN))
+		goto freeze;
+
+	/* Check whether we are expecting interrupt in this state */
+	switch (ap->hsm_task_state) {
+	case HSM_ST_FIRST:
+		/* Some pre-ATAPI-4 devices assert INTRQ
+		 * at this state when ready to receive CDB.
+		 */
+
+		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+		 * The flag was turned on only for atapi devices.
+		 * No need to check is_atapi_taskfile(&qc->tf) again.
+		 */
+		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+			goto err_hsm;
+		break;
+	case HSM_ST_LAST:
+		if (qc->tf.protocol == ATA_PROT_DMA ||
+		    qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+			/* clear DMA-Start bit */
+			ap->ops->bmdma_stop(qc);
+
+			if (bmdma2 & SIL_DMA_ERROR) {
+				qc->err_mask |= AC_ERR_HOST_BUS;
+				ap->hsm_task_state = HSM_ST_ERR;
+			}
+		}
+		break;
+	case HSM_ST:
+		break;
+	default:
+		goto err_hsm;
+	}
+
+	/* check main status, clearing INTRQ */
+	status = ata_chk_status(ap);
+	if (unlikely(status & ATA_BUSY))
+		goto err_hsm;
+
+	/* ack bmdma irq events */
+	ata_bmdma_irq_clear(ap);
+
+	/* kick HSM in the ass */
+	ata_hsm_move(ap, qc, status, 0);
+
+	return;
+
+ err_hsm:
+	qc->err_mask |= AC_ERR_HSM;
+ freeze:
+	ata_port_freeze(ap);
+}
+
+static irqreturn_t sil_interrupt(int irq, void *dev_instance,
+				 struct pt_regs *regs)
+{
+	struct ata_host_set *host_set = dev_instance;
+	void __iomem *mmio_base = host_set->mmio_base;
+	int handled = 0;
+	int i;
+
+	spin_lock(&host_set->lock);
+
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap = host_set->ports[i];
+		u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2);
+
+		if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
+			continue;
+
+		/* turn off SATA_IRQ if not supported */
+		if (ap->flags & SIL_FLAG_NO_SATA_IRQ)
+			bmdma2 &= ~SIL_DMA_SATA_IRQ;
+
+		if (bmdma2 == 0xffffffff ||
+		    !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ)))
+			continue;
+
+		sil_host_intr(ap, bmdma2);
+		handled = 1;
+	}
+
+	spin_unlock(&host_set->lock);
+
+	return IRQ_RETVAL(handled);
+}
+
+static void sil_freeze(struct ata_port *ap)
+{
+	void __iomem *mmio_base = ap->host_set->mmio_base;
+	u32 tmp;
+
+	/* global IRQ mask doesn't block SATA IRQ, turn off explicitly */
+	writel(0, mmio_base + sil_port[ap->port_no].sien);
+
+	/* plug IRQ */
+	tmp = readl(mmio_base + SIL_SYSCFG);
+	tmp |= SIL_MASK_IDE0_INT << ap->port_no;
+	writel(tmp, mmio_base + SIL_SYSCFG);
+	readl(mmio_base + SIL_SYSCFG);	/* flush */
+}
+
+static void sil_thaw(struct ata_port *ap)
+{
+	void __iomem *mmio_base = ap->host_set->mmio_base;
+	u32 tmp;
+
+	/* clear IRQ */
+	ata_chk_status(ap);
+	ata_bmdma_irq_clear(ap);
+
+	/* turn on SATA IRQ if supported */
+	if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
+		writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien);
+
+	/* turn on IRQ */
+	tmp = readl(mmio_base + SIL_SYSCFG);
+	tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no);
+	writel(tmp, mmio_base + SIL_SYSCFG);
+}
+
 /**
  *	sil_dev_config - Apply device/host-specific errata fixups
  *	@ap: Port containing device to be examined
@@ -360,16 +546,16 @@
 	if (slow_down ||
 	    ((ap->flags & SIL_FLAG_MOD15WRITE) &&
 	     (quirks & SIL_QUIRK_MOD15WRITE))) {
-		printk(KERN_INFO "ata%u(%u): applying Seagate errata fix (mod15write workaround)\n",
-		       ap->id, dev->devno);
+		ata_dev_printk(dev, KERN_INFO, "applying Seagate errata fix "
+			       "(mod15write workaround)\n");
 		dev->max_sectors = 15;
 		return;
 	}
 
 	/* limit to udma5 */
 	if (quirks & SIL_QUIRK_UDMA5MAX) {
-		printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n",
-		       ap->id, dev->devno, model_num);
+		ata_dev_printk(dev, KERN_INFO,
+			       "applying Maxtor errata fix %s\n", model_num);
 		dev->udma_mask &= ATA_UDMA5;
 		return;
 	}
@@ -384,16 +570,12 @@
 	int rc;
 	unsigned int i;
 	int pci_dev_busy = 0;
-	u32 tmp, irq_mask;
+	u32 tmp;
 	u8 cls;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	/*
-	 * If this driver happens to only be useful on Apple's K2, then
-	 * we should check that here as it has a normal Serverworks ID
-	 */
 	rc = pci_enable_device(pdev);
 	if (rc)
 		return rc;
@@ -478,31 +660,13 @@
 	}
 
 	if (ent->driver_data == sil_3114) {
-		irq_mask = SIL_MASK_4PORT;
-
 		/* flip the magic "make 4 ports work" bit */
 		tmp = readl(mmio_base + sil_port[2].bmdma);
 		if ((tmp & SIL_INTR_STEERING) == 0)
 			writel(tmp | SIL_INTR_STEERING,
 			       mmio_base + sil_port[2].bmdma);
-
-	} else {
-		irq_mask = SIL_MASK_2PORT;
 	}
 
-	/* make sure IDE0/1/2/3 interrupts are not masked */
-	tmp = readl(mmio_base + SIL_SYSCFG);
-	if (tmp & irq_mask) {
-		tmp &= ~irq_mask;
-		writel(tmp, mmio_base + SIL_SYSCFG);
-		readl(mmio_base + SIL_SYSCFG);	/* flush */
-	}
-
-	/* mask all SATA phy-related interrupts */
-	/* TODO: unmask bit 6 (SError N bit) for hotplug */
-	for (i = 0; i < probe_ent->n_ports; i++)
-		writel(0, mmio_base + sil_port[i].sien);
-
 	pci_set_master(pdev);
 
 	/* FIXME: check ata_device_add return value */
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index cb9082f..b5f8fa9 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -31,15 +31,15 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"sata_sil24"
-#define DRV_VERSION	"0.23"
+#define DRV_VERSION	"0.3"
 
 /*
  * Port request block (PRB) 32 bytes
  */
 struct sil24_prb {
-	u16	ctrl;
-	u16	prot;
-	u32	rx_cnt;
+	__le16	ctrl;
+	__le16	prot;
+	__le32	rx_cnt;
 	u8	fis[6 * 4];
 };
 
@@ -47,17 +47,17 @@
  * Scatter gather entry (SGE) 16 bytes
  */
 struct sil24_sge {
-	u64	addr;
-	u32	cnt;
-	u32	flags;
+	__le64	addr;
+	__le32	cnt;
+	__le32	flags;
 };
 
 /*
  * Port multiplier
  */
 struct sil24_port_multiplier {
-	u32	diag;
-	u32	sactive;
+	__le32	diag;
+	__le32	sactive;
 };
 
 enum {
@@ -86,12 +86,21 @@
 	/* HOST_SLOT_STAT bits */
 	HOST_SSTAT_ATTN		= (1 << 31),
 
+	/* HOST_CTRL bits */
+	HOST_CTRL_M66EN		= (1 << 16), /* M66EN PCI bus signal */
+	HOST_CTRL_TRDY		= (1 << 17), /* latched PCI TRDY */
+	HOST_CTRL_STOP		= (1 << 18), /* latched PCI STOP */
+	HOST_CTRL_DEVSEL	= (1 << 19), /* latched PCI DEVSEL */
+	HOST_CTRL_REQ64		= (1 << 20), /* latched PCI REQ64 */
+
 	/*
 	 * Port registers
 	 * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2)
 	 */
 	PORT_REGS_SIZE		= 0x2000,
-	PORT_PRB		= 0x0000, /* (32 bytes PRB + 16 bytes SGEs * 6) * 31 (3968 bytes) */
+
+	PORT_LRAM		= 0x0000, /* 31 LRAM slots and PM regs */
+	PORT_LRAM_SLOT_SZ	= 0x0080, /* 32 bytes PRB + 2 SGE, ACT... */
 
 	PORT_PM			= 0x0f80, /* 8 bytes PM * 16 (128 bytes) */
 		/* 32 bit regs */
@@ -142,8 +151,16 @@
 	PORT_IRQ_PWR_CHG	= (1 << 3), /* power management change */
 	PORT_IRQ_PHYRDY_CHG	= (1 << 4), /* PHY ready change */
 	PORT_IRQ_COMWAKE	= (1 << 5), /* COMWAKE received */
-	PORT_IRQ_UNK_FIS	= (1 << 6), /* Unknown FIS received */
-	PORT_IRQ_SDB_FIS	= (1 << 11), /* SDB FIS received */
+	PORT_IRQ_UNK_FIS	= (1 << 6), /* unknown FIS received */
+	PORT_IRQ_DEV_XCHG	= (1 << 7), /* device exchanged */
+	PORT_IRQ_8B10B		= (1 << 8), /* 8b/10b decode error threshold */
+	PORT_IRQ_CRC		= (1 << 9), /* CRC error threshold */
+	PORT_IRQ_HANDSHAKE	= (1 << 10), /* handshake error threshold */
+	PORT_IRQ_SDB_NOTIFY	= (1 << 11), /* SDB notify received */
+
+	DEF_PORT_IRQ		= PORT_IRQ_COMPLETE | PORT_IRQ_ERROR |
+				  PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG |
+				  PORT_IRQ_UNK_FIS,
 
 	/* bits[27:16] are unmasked (raw) */
 	PORT_IRQ_RAW_SHIFT	= 16,
@@ -174,7 +191,7 @@
 	PORT_CERR_CMD_PCIPERR	= 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */
 	PORT_CERR_XFR_UNDEF	= 32, /* PSD ecode 00 - undefined */
 	PORT_CERR_XFR_TGTABRT	= 33, /* PSD ecode 01 - target abort */
-	PORT_CERR_XFR_MSGABRT	= 34, /* PSD ecode 10 - master abort */
+	PORT_CERR_XFR_MSTABRT	= 34, /* PSD ecode 10 - master abort */
 	PORT_CERR_XFR_PCIPERR	= 35, /* PSD ecode 11 - PCI prity err during transfer */
 	PORT_CERR_SENDSERVICE	= 36, /* FIS received while sending service */
 
@@ -202,11 +219,19 @@
 	SGE_DRD			= (1 << 29), /* discard data read (/dev/null)
 						data address ignored */
 
+	SIL24_MAX_CMDS		= 31,
+
 	/* board id */
 	BID_SIL3124		= 0,
 	BID_SIL3132		= 1,
 	BID_SIL3131		= 2,
 
+	/* host flags */
+	SIL24_COMMON_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+				  ATA_FLAG_NCQ | ATA_FLAG_SKIP_D2H_BSY,
+	SIL24_FLAG_PCIX_IRQ_WOC	= (1 << 24), /* IRQ loss errata on PCI-X */
+
 	IRQ_STAT_4PORTS		= 0xf,
 };
 
@@ -226,6 +251,58 @@
 	struct sil24_atapi_block atapi;
 };
 
+static struct sil24_cerr_info {
+	unsigned int err_mask, action;
+	const char *desc;
+} sil24_cerr_db[] = {
+	[0]			= { AC_ERR_DEV, ATA_EH_REVALIDATE,
+				    "device error" },
+	[PORT_CERR_DEV]		= { AC_ERR_DEV, ATA_EH_REVALIDATE,
+				    "device error via D2H FIS" },
+	[PORT_CERR_SDB]		= { AC_ERR_DEV, ATA_EH_REVALIDATE,
+				    "device error via SDB FIS" },
+	[PORT_CERR_DATA]	= { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+				    "error in data FIS" },
+	[PORT_CERR_SEND]	= { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
+				    "failed to transmit command FIS" },
+	[PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET,
+				     "protocol mismatch" },
+	[PORT_CERR_DIRECTION]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
+				    "data directon mismatch" },
+	[PORT_CERR_UNDERRUN]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
+				    "ran out of SGEs while writing" },
+	[PORT_CERR_OVERRUN]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
+				    "ran out of SGEs while reading" },
+	[PORT_CERR_PKT_PROT]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
+				    "invalid data directon for ATAPI CDB" },
+	[PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+				     "SGT no on qword boundary" },
+	[PORT_CERR_SGT_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI target abort while fetching SGT" },
+	[PORT_CERR_SGT_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI master abort while fetching SGT" },
+	[PORT_CERR_SGT_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI parity error while fetching SGT" },
+	[PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET,
+				     "PRB not on qword boundary" },
+	[PORT_CERR_CMD_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI target abort while fetching PRB" },
+	[PORT_CERR_CMD_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI master abort while fetching PRB" },
+	[PORT_CERR_CMD_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI parity error while fetching PRB" },
+	[PORT_CERR_XFR_UNDEF]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "undefined error while transferring data" },
+	[PORT_CERR_XFR_TGTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI target abort while transferring data" },
+	[PORT_CERR_XFR_MSTABRT]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI master abort while transferring data" },
+	[PORT_CERR_XFR_PCIPERR]	= { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET,
+				    "PCI parity error while transferring data" },
+	[PORT_CERR_SENDSERVICE]	= { AC_ERR_HSM, ATA_EH_SOFTRESET,
+				    "FIS received while sending service FIS" },
+};
+
 /*
  * ap->private_data
  *
@@ -249,12 +326,14 @@
 static u32 sil24_scr_read(struct ata_port *ap, unsigned sc_reg);
 static void sil24_scr_write(struct ata_port *ap, unsigned sc_reg, u32 val);
 static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
-static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes);
 static void sil24_qc_prep(struct ata_queued_cmd *qc);
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc);
 static void sil24_irq_clear(struct ata_port *ap);
-static void sil24_eng_timeout(struct ata_port *ap);
 static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static void sil24_freeze(struct ata_port *ap);
+static void sil24_thaw(struct ata_port *ap);
+static void sil24_error_handler(struct ata_port *ap);
+static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
 static int sil24_port_start(struct ata_port *ap);
 static void sil24_port_stop(struct ata_port *ap);
 static void sil24_host_stop(struct ata_host_set *host_set);
@@ -281,7 +360,8 @@
 	.name			= DRV_NAME,
 	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
-	.can_queue		= ATA_DEF_QUEUE,
+	.change_queue_depth	= ata_scsi_change_queue_depth,
+	.can_queue		= SIL24_MAX_CMDS,
 	.this_id		= ATA_SHT_THIS_ID,
 	.sg_tablesize		= LIBATA_MAX_PRD,
 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
@@ -290,6 +370,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -304,19 +385,20 @@
 
 	.tf_read		= sil24_tf_read,
 
-	.probe_reset		= sil24_probe_reset,
-
 	.qc_prep		= sil24_qc_prep,
 	.qc_issue		= sil24_qc_issue,
 
-	.eng_timeout		= sil24_eng_timeout,
-
 	.irq_handler		= sil24_interrupt,
 	.irq_clear		= sil24_irq_clear,
 
 	.scr_read		= sil24_scr_read,
 	.scr_write		= sil24_scr_write,
 
+	.freeze			= sil24_freeze,
+	.thaw			= sil24_thaw,
+	.error_handler		= sil24_error_handler,
+	.post_internal_cmd	= sil24_post_internal_cmd,
+
 	.port_start		= sil24_port_start,
 	.port_stop		= sil24_port_stop,
 	.host_stop		= sil24_host_stop,
@@ -333,9 +415,8 @@
 	/* sil_3124 */
 	{
 		.sht		= &sil24_sht,
-		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-				  SIL24_NPORTS2FLAG(4),
+		.host_flags	= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) |
+				  SIL24_FLAG_PCIX_IRQ_WOC,
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
@@ -344,9 +425,7 @@
 	/* sil_3132 */
 	{
 		.sht		= &sil24_sht,
-		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-				  SIL24_NPORTS2FLAG(2),
+		.host_flags	= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2),
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
@@ -355,9 +434,7 @@
 	/* sil_3131/sil_3531 */
 	{
 		.sht		= &sil24_sht,
-		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-				  SIL24_NPORTS2FLAG(1),
+		.host_flags	= SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1),
 		.pio_mask	= 0x1f,			/* pio0-4 */
 		.mwdma_mask	= 0x07,			/* mwdma0-2 */
 		.udma_mask	= 0x3f,			/* udma0-5 */
@@ -365,6 +442,13 @@
 	},
 };
 
+static int sil24_tag(int tag)
+{
+	if (unlikely(ata_tag_internal(tag)))
+		return 0;
+	return tag;
+}
+
 static void sil24_dev_config(struct ata_port *ap, struct ata_device *dev)
 {
 	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
@@ -426,56 +510,65 @@
 	*tf = pp->tf;
 }
 
-static int sil24_softreset(struct ata_port *ap, int verbose,
-			   unsigned int *class)
+static int sil24_init_port(struct ata_port *ap)
+{
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	u32 tmp;
+
+	writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
+	ata_wait_register(port + PORT_CTRL_STAT,
+			  PORT_CS_INIT, PORT_CS_INIT, 10, 100);
+	tmp = ata_wait_register(port + PORT_CTRL_STAT,
+				PORT_CS_RDY, 0, 10, 100);
+
+	if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY)
+		return -EIO;
+	return 0;
+}
+
+static int sil24_softreset(struct ata_port *ap, unsigned int *class)
 {
 	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 	struct sil24_port_priv *pp = ap->private_data;
 	struct sil24_prb *prb = &pp->cmd_block[0].ata.prb;
 	dma_addr_t paddr = pp->cmd_block_dma;
-	unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ;
-	u32 irq_enable, irq_stat;
+	u32 mask, irq_stat;
+	const char *reason;
 
 	DPRINTK("ENTER\n");
 
-	if (!sata_dev_present(ap)) {
+	if (ata_port_offline(ap)) {
 		DPRINTK("PHY reports no device\n");
 		*class = ATA_DEV_NONE;
 		goto out;
 	}
 
-	/* temporarily turn off IRQs during SRST */
-	irq_enable = readl(port + PORT_IRQ_ENABLE_SET);
-	writel(irq_enable, port + PORT_IRQ_ENABLE_CLR);
+	/* put the port into known state */
+	if (sil24_init_port(ap)) {
+		reason ="port not ready";
+		goto err;
+	}
 
-	/*
-	 * XXX: Not sure whether the following sleep is needed or not.
-	 * The original driver had it.  So....
-	 */
-	msleep(10);
-
+	/* do SRST */
 	prb->ctrl = cpu_to_le16(PRB_CTRL_SRST);
 	prb->fis[1] = 0; /* no PM yet */
 
 	writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+	writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4);
 
-	do {
-		irq_stat = readl(port + PORT_IRQ_STAT);
-		writel(irq_stat, port + PORT_IRQ_STAT);		/* clear irq */
+	mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT;
+	irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0,
+				     100, ATA_TMOUT_BOOT / HZ * 1000);
 
-		irq_stat >>= PORT_IRQ_RAW_SHIFT;
-		if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR))
-			break;
-
-		msleep(100);
-	} while (time_before(jiffies, timeout));
-
-	/* restore IRQs */
-	writel(irq_enable, port + PORT_IRQ_ENABLE_SET);
+	writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */
+	irq_stat >>= PORT_IRQ_RAW_SHIFT;
 
 	if (!(irq_stat & PORT_IRQ_COMPLETE)) {
-		DPRINTK("EXIT, srst failed\n");
-		return -EIO;
+		if (irq_stat & PORT_IRQ_ERROR)
+			reason = "SRST command error";
+		else
+			reason = "timeout";
+		goto err;
 	}
 
 	sil24_update_tf(ap);
@@ -487,22 +580,57 @@
  out:
 	DPRINTK("EXIT, class=%u\n", *class);
 	return 0;
+
+ err:
+	ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason);
+	return -EIO;
 }
 
-static int sil24_hardreset(struct ata_port *ap, int verbose,
-			   unsigned int *class)
+static int sil24_hardreset(struct ata_port *ap, unsigned int *class)
 {
-	unsigned int dummy_class;
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	const char *reason;
+	int tout_msec, rc;
+	u32 tmp;
 
-	/* sil24 doesn't report device signature after hard reset */
-	return sata_std_hardreset(ap, verbose, &dummy_class);
-}
+	/* sil24 does the right thing(tm) without any protection */
+	sata_set_spd(ap);
 
-static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes)
-{
-	return ata_drive_probe_reset(ap, ata_std_probeinit,
-				     sil24_softreset, sil24_hardreset,
-				     ata_std_postreset, classes);
+	tout_msec = 100;
+	if (ata_port_online(ap))
+		tout_msec = 5000;
+
+	writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+	tmp = ata_wait_register(port + PORT_CTRL_STAT,
+				PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec);
+
+	/* SStatus oscillates between zero and valid status after
+	 * DEV_RST, debounce it.
+	 */
+	rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst);
+	if (rc) {
+		reason = "PHY debouncing failed";
+		goto err;
+	}
+
+	if (tmp & PORT_CS_DEV_RST) {
+		if (ata_port_offline(ap))
+			return 0;
+		reason = "link not ready";
+		goto err;
+	}
+
+	/* Sil24 doesn't store signature FIS after hardreset, so we
+	 * can't wait for BSY to clear.  Some devices take a long time
+	 * to get ready and those devices will choke if we don't wait
+	 * for BSY clearance here.  Tell libata to perform follow-up
+	 * softreset.
+	 */
+	return -EAGAIN;
+
+ err:
+	ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason);
+	return -EIO;
 }
 
 static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
@@ -528,17 +656,20 @@
 {
 	struct ata_port *ap = qc->ap;
 	struct sil24_port_priv *pp = ap->private_data;
-	union sil24_cmd_block *cb = pp->cmd_block + qc->tag;
+	union sil24_cmd_block *cb;
 	struct sil24_prb *prb;
 	struct sil24_sge *sge;
+	u16 ctrl = 0;
+
+	cb = &pp->cmd_block[sil24_tag(qc->tag)];
 
 	switch (qc->tf.protocol) {
 	case ATA_PROT_PIO:
 	case ATA_PROT_DMA:
+	case ATA_PROT_NCQ:
 	case ATA_PROT_NODATA:
 		prb = &cb->ata.prb;
 		sge = cb->ata.sge;
-		prb->ctrl = 0;
 		break;
 
 	case ATA_PROT_ATAPI:
@@ -551,12 +682,10 @@
 
 		if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
 			if (qc->tf.flags & ATA_TFLAG_WRITE)
-				prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_WRITE);
+				ctrl = PRB_CTRL_PACKET_WRITE;
 			else
-				prb->ctrl = cpu_to_le16(PRB_CTRL_PACKET_READ);
-		} else
-			prb->ctrl = 0;
-
+				ctrl = PRB_CTRL_PACKET_READ;
+		}
 		break;
 
 	default:
@@ -565,6 +694,7 @@
 		BUG();
 	}
 
+	prb->ctrl = cpu_to_le16(ctrl);
 	ata_tf_to_fis(&qc->tf, prb->fis, 0);
 
 	if (qc->flags & ATA_QCFLAG_DMAMAP)
@@ -574,11 +704,18 @@
 static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
 	struct sil24_port_priv *pp = ap->private_data;
-	dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block);
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	unsigned int tag = sil24_tag(qc->tag);
+	dma_addr_t paddr;
+	void __iomem *activate;
 
-	writel((u32)paddr, port + PORT_CMD_ACTIVATE);
+	paddr = pp->cmd_block_dma + tag * sizeof(*pp->cmd_block);
+	activate = port + PORT_CMD_ACTIVATE + tag * 8;
+
+	writel((u32)paddr, activate);
+	writel((u64)paddr >> 32, activate + 4);
+
 	return 0;
 }
 
@@ -587,162 +724,139 @@
 	/* unused */
 }
 
-static int __sil24_restart_controller(void __iomem *port)
+static void sil24_freeze(struct ata_port *ap)
 {
-	u32 tmp;
-	int cnt;
-
-	writel(PORT_CS_INIT, port + PORT_CTRL_STAT);
-
-	/* Max ~10ms */
-	for (cnt = 0; cnt < 10000; cnt++) {
-		tmp = readl(port + PORT_CTRL_STAT);
-		if (tmp & PORT_CS_RDY)
-			return 0;
-		udelay(1);
-	}
-
-	return -1;
-}
-
-static void sil24_restart_controller(struct ata_port *ap)
-{
-	if (__sil24_restart_controller((void __iomem *)ap->ioaddr.cmd_addr))
-		printk(KERN_ERR DRV_NAME
-		       " ata%u: failed to restart controller\n", ap->id);
-}
-
-static int __sil24_reset_controller(void __iomem *port)
-{
-	int cnt;
-	u32 tmp;
-
-	/* Reset controller state.  Is this correct? */
-	writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
-	readl(port + PORT_CTRL_STAT);	/* sync */
-
-	/* Max ~100ms */
-	for (cnt = 0; cnt < 1000; cnt++) {
-		udelay(100);
-		tmp = readl(port + PORT_CTRL_STAT);
-		if (!(tmp & PORT_CS_DEV_RST))
-			break;
-	}
-
-	if (tmp & PORT_CS_DEV_RST)
-		return -1;
-
-	if (tmp & PORT_CS_RDY)
-		return 0;
-
-	return __sil24_restart_controller(port);
-}
-
-static void sil24_reset_controller(struct ata_port *ap)
-{
-	printk(KERN_NOTICE DRV_NAME
-	       " ata%u: resetting controller...\n", ap->id);
-	if (__sil24_reset_controller((void __iomem *)ap->ioaddr.cmd_addr))
-                printk(KERN_ERR DRV_NAME
-                       " ata%u: failed to reset controller\n", ap->id);
-}
-
-static void sil24_eng_timeout(struct ata_port *ap)
-{
-	struct ata_queued_cmd *qc;
-
-	qc = ata_qc_from_tag(ap, ap->active_tag);
-
-	printk(KERN_ERR "ata%u: command timeout\n", ap->id);
-	qc->err_mask |= AC_ERR_TIMEOUT;
-	ata_eh_qc_complete(qc);
-
-	sil24_reset_controller(ap);
-}
-
-static void sil24_error_intr(struct ata_port *ap, u32 slot_stat)
-{
-	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
-	struct sil24_port_priv *pp = ap->private_data;
 	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-	u32 irq_stat, cmd_err, sstatus, serror;
-	unsigned int err_mask;
 
-	irq_stat = readl(port + PORT_IRQ_STAT);
-	writel(irq_stat, port + PORT_IRQ_STAT);		/* clear irq */
-
-	if (!(irq_stat & PORT_IRQ_ERROR)) {
-		/* ignore non-completion, non-error irqs for now */
-		printk(KERN_WARNING DRV_NAME
-		       "ata%u: non-error exception irq (irq_stat %x)\n",
-		       ap->id, irq_stat);
-		return;
-	}
-
-	cmd_err = readl(port + PORT_CMD_ERR);
-	sstatus = readl(port + PORT_SSTATUS);
-	serror = readl(port + PORT_SERROR);
-	if (serror)
-		writel(serror, port + PORT_SERROR);
-
-	/*
-	 * Don't log ATAPI device errors.  They're supposed to happen
-	 * and any serious errors will be logged using sense data by
-	 * the SCSI layer.
+	/* Port-wide IRQ mask in HOST_CTRL doesn't really work, clear
+	 * PORT_IRQ_ENABLE instead.
 	 */
-	if (ap->device[0].class != ATA_DEV_ATAPI || cmd_err > PORT_CERR_SDB)
-		printk("ata%u: error interrupt on port%d\n"
-		       "  stat=0x%x irq=0x%x cmd_err=%d sstatus=0x%x serror=0x%x\n",
-		       ap->id, ap->port_no, slot_stat, irq_stat, cmd_err, sstatus, serror);
+	writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
+}
 
-	if (cmd_err == PORT_CERR_DEV || cmd_err == PORT_CERR_SDB) {
-		/*
-		 * Device is reporting error, tf registers are valid.
-		 */
-		sil24_update_tf(ap);
-		err_mask = ac_err_mask(pp->tf.command);
-		sil24_restart_controller(ap);
-	} else {
-		/*
-		 * Other errors.  libata currently doesn't have any
-		 * mechanism to report these errors.  Just turn on
-		 * ATA_ERR.
-		 */
-		err_mask = AC_ERR_OTHER;
-		sil24_reset_controller(ap);
+static void sil24_thaw(struct ata_port *ap)
+{
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	u32 tmp;
+
+	/* clear IRQ */
+	tmp = readl(port + PORT_IRQ_STAT);
+	writel(tmp, port + PORT_IRQ_STAT);
+
+	/* turn IRQ back on */
+	writel(DEF_PORT_IRQ, port + PORT_IRQ_ENABLE_SET);
+}
+
+static void sil24_error_intr(struct ata_port *ap)
+{
+	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
+	struct ata_eh_info *ehi = &ap->eh_info;
+	int freeze = 0;
+	u32 irq_stat;
+
+	/* on error, we need to clear IRQ explicitly */
+	irq_stat = readl(port + PORT_IRQ_STAT);
+	writel(irq_stat, port + PORT_IRQ_STAT);
+
+	/* first, analyze and record host port events */
+	ata_ehi_clear_desc(ehi);
+
+	ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat);
+
+	if (irq_stat & (PORT_IRQ_PHYRDY_CHG | PORT_IRQ_DEV_XCHG)) {
+		ata_ehi_hotplugged(ehi);
+		ata_ehi_push_desc(ehi, ", %s",
+			       irq_stat & PORT_IRQ_PHYRDY_CHG ?
+			       "PHY RDY changed" : "device exchanged");
+		freeze = 1;
 	}
 
-	if (qc) {
-		qc->err_mask |= err_mask;
-		ata_qc_complete(qc);
+	if (irq_stat & PORT_IRQ_UNK_FIS) {
+		ehi->err_mask |= AC_ERR_HSM;
+		ehi->action |= ATA_EH_SOFTRESET;
+		ata_ehi_push_desc(ehi , ", unknown FIS");
+		freeze = 1;
 	}
+
+	/* deal with command error */
+	if (irq_stat & PORT_IRQ_ERROR) {
+		struct sil24_cerr_info *ci = NULL;
+		unsigned int err_mask = 0, action = 0;
+		struct ata_queued_cmd *qc;
+		u32 cerr;
+
+		/* analyze CMD_ERR */
+		cerr = readl(port + PORT_CMD_ERR);
+		if (cerr < ARRAY_SIZE(sil24_cerr_db))
+			ci = &sil24_cerr_db[cerr];
+
+		if (ci && ci->desc) {
+			err_mask |= ci->err_mask;
+			action |= ci->action;
+			ata_ehi_push_desc(ehi, ", %s", ci->desc);
+		} else {
+			err_mask |= AC_ERR_OTHER;
+			action |= ATA_EH_SOFTRESET;
+			ata_ehi_push_desc(ehi, ", unknown command error %d",
+					  cerr);
+		}
+
+		/* record error info */
+		qc = ata_qc_from_tag(ap, ap->active_tag);
+		if (qc) {
+			sil24_update_tf(ap);
+			qc->err_mask |= err_mask;
+		} else
+			ehi->err_mask |= err_mask;
+
+		ehi->action |= action;
+	}
+
+	/* freeze or abort */
+	if (freeze)
+		ata_port_freeze(ap);
+	else
+		ata_port_abort(ap);
+}
+
+static void sil24_finish_qc(struct ata_queued_cmd *qc)
+{
+	if (qc->flags & ATA_QCFLAG_RESULT_TF)
+		sil24_update_tf(qc->ap);
 }
 
 static inline void sil24_host_intr(struct ata_port *ap)
 {
-	struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
 	void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;
-	u32 slot_stat;
+	u32 slot_stat, qc_active;
+	int rc;
 
 	slot_stat = readl(port + PORT_SLOT_STAT);
-	if (!(slot_stat & HOST_SSTAT_ATTN)) {
-		struct sil24_port_priv *pp = ap->private_data;
-		/*
-		 * !HOST_SSAT_ATTN guarantees successful completion,
-		 * so reading back tf registers is unnecessary for
-		 * most commands.  TODO: read tf registers for
-		 * commands which require these values on successful
-		 * completion (EXECUTE DEVICE DIAGNOSTIC, CHECK POWER,
-		 * DEVICE RESET and READ PORT MULTIPLIER (any more?).
-		 */
-		sil24_update_tf(ap);
 
-		if (qc) {
-			qc->err_mask |= ac_err_mask(pp->tf.command);
-			ata_qc_complete(qc);
-		}
-	} else
-		sil24_error_intr(ap, slot_stat);
+	if (unlikely(slot_stat & HOST_SSTAT_ATTN)) {
+		sil24_error_intr(ap);
+		return;
+	}
+
+	if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC)
+		writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT);
+
+	qc_active = slot_stat & ~HOST_SSTAT_ATTN;
+	rc = ata_qc_complete_multiple(ap, qc_active, sil24_finish_qc);
+	if (rc > 0)
+		return;
+	if (rc < 0) {
+		struct ata_eh_info *ehi = &ap->eh_info;
+		ehi->err_mask |= AC_ERR_HSM;
+		ehi->action |= ATA_EH_SOFTRESET;
+		ata_port_freeze(ap);
+		return;
+	}
+
+	if (ata_ratelimit())
+		ata_port_printk(ap, KERN_INFO, "spurious interrupt "
+			"(slot_stat 0x%x active_tag %d sactive 0x%x)\n",
+			slot_stat, ap->active_tag, ap->sactive);
 }
 
 static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
@@ -769,7 +883,7 @@
 	for (i = 0; i < host_set->n_ports; i++)
 		if (status & (1 << i)) {
 			struct ata_port *ap = host_set->ports[i];
-			if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) {
+			if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
 				sil24_host_intr(host_set->ports[i]);
 				handled++;
 			} else
@@ -782,9 +896,35 @@
 	return IRQ_RETVAL(handled);
 }
 
+static void sil24_error_handler(struct ata_port *ap)
+{
+	struct ata_eh_context *ehc = &ap->eh_context;
+
+	if (sil24_init_port(ap)) {
+		ata_eh_freeze_port(ap);
+		ehc->i.action |= ATA_EH_HARDRESET;
+	}
+
+	/* perform recovery */
+	ata_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
+		  ata_std_postreset);
+}
+
+static void sil24_post_internal_cmd(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+
+	if (qc->flags & ATA_QCFLAG_FAILED)
+		qc->err_mask |= AC_ERR_OTHER;
+
+	/* make DMA engine forget about the failed command */
+	if (qc->err_mask)
+		sil24_init_port(ap);
+}
+
 static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev)
 {
-	const size_t cb_size = sizeof(*pp->cmd_block);
+	const size_t cb_size = sizeof(*pp->cmd_block) * SIL24_MAX_CMDS;
 
 	dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma);
 }
@@ -794,7 +934,7 @@
 	struct device *dev = ap->host_set->dev;
 	struct sil24_port_priv *pp;
 	union sil24_cmd_block *cb;
-	size_t cb_size = sizeof(*cb);
+	size_t cb_size = sizeof(*cb) * SIL24_MAX_CMDS;
 	dma_addr_t cb_dma;
 	int rc = -ENOMEM;
 
@@ -858,6 +998,7 @@
 	void __iomem *host_base = NULL;
 	void __iomem *port_base = NULL;
 	int i, rc;
+	u32 tmp;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -910,37 +1051,53 @@
 	/*
 	 * Configure the device
 	 */
-	/*
-	 * FIXME: This device is certainly 64-bit capable.  We just
-	 * don't know how to use it.  After fixing 32bit activation in
-	 * this function, enable 64bit masks here.
-	 */
-	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "32-bit DMA enable failed\n");
-		goto out_free;
-	}
-	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-	if (rc) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "32-bit consistent DMA enable failed\n");
-		goto out_free;
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+		if (rc) {
+			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+			if (rc) {
+				dev_printk(KERN_ERR, &pdev->dev,
+					   "64-bit DMA enable failed\n");
+				goto out_free;
+			}
+		}
+	} else {
+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+		if (rc) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "32-bit DMA enable failed\n");
+			goto out_free;
+		}
+		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+		if (rc) {
+			dev_printk(KERN_ERR, &pdev->dev,
+				   "32-bit consistent DMA enable failed\n");
+			goto out_free;
+		}
 	}
 
 	/* GPIO off */
 	writel(0, host_base + HOST_FLASH_CMD);
 
-	/* Mask interrupts during initialization */
+	/* Apply workaround for completion IRQ loss on PCI-X errata */
+	if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
+		tmp = readl(host_base + HOST_CTRL);
+		if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL))
+			dev_printk(KERN_INFO, &pdev->dev,
+				   "Applying completion IRQ loss on PCI-X "
+				   "errata fix\n");
+		else
+			probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
+	}
+
+	/* clear global reset & mask interrupts during initialization */
 	writel(0, host_base + HOST_CTRL);
 
 	for (i = 0; i < probe_ent->n_ports; i++) {
 		void __iomem *port = port_base + i * PORT_REGS_SIZE;
 		unsigned long portu = (unsigned long)port;
-		u32 tmp;
-		int cnt;
 
-		probe_ent->port[i].cmd_addr = portu + PORT_PRB;
+		probe_ent->port[i].cmd_addr = portu;
 		probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
 
 		ata_std_ports(&probe_ent->port[i]);
@@ -952,18 +1109,20 @@
 		tmp = readl(port + PORT_CTRL_STAT);
 		if (tmp & PORT_CS_PORT_RST) {
 			writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-			readl(port + PORT_CTRL_STAT);	/* sync */
-			for (cnt = 0; cnt < 10; cnt++) {
-				msleep(10);
-				tmp = readl(port + PORT_CTRL_STAT);
-				if (!(tmp & PORT_CS_PORT_RST))
-					break;
-			}
+			tmp = ata_wait_register(port + PORT_CTRL_STAT,
+						PORT_CS_PORT_RST,
+						PORT_CS_PORT_RST, 10, 100);
 			if (tmp & PORT_CS_PORT_RST)
 				dev_printk(KERN_ERR, &pdev->dev,
 				           "failed to clear port RST\n");
 		}
 
+		/* Configure IRQ WoC */
+		if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
+			writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
+		else
+			writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
 		/* Zero error counters. */
 		writel(0x8000, port + PORT_DECODE_ERR_THRESH);
 		writel(0x8000, port + PORT_CRC_ERR_THRESH);
@@ -972,26 +1131,11 @@
 		writel(0x0000, port + PORT_CRC_ERR_CNT);
 		writel(0x0000, port + PORT_HSHK_ERR_CNT);
 
-		/* FIXME: 32bit activation? */
-		writel(0, port + PORT_ACTIVATE_UPPER_ADDR);
-		writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT);
-
-		/* Configure interrupts */
-		writel(0xffff, port + PORT_IRQ_ENABLE_CLR);
-		writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS,
-		       port + PORT_IRQ_ENABLE_SET);
-
-		/* Clear interrupts */
-		writel(0x0fff0fff, port + PORT_IRQ_STAT);
-		writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+		/* Always use 64bit activation */
+		writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
 
 		/* Clear port multiplier enable and resume bits */
 		writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
-
-		/* Reset itself */
-		if (__sil24_reset_controller(port))
-			dev_printk(KERN_ERR, &pdev->dev,
-			           "failed to reset controller\n");
 	}
 
 	/* Turn on interrupts */
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 728530d..809d337 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -43,7 +43,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_sis"
-#define DRV_VERSION	"0.5"
+#define DRV_VERSION	"0.6"
 
 enum {
 	sis_180			= 0,
@@ -96,6 +96,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -106,14 +107,17 @@
 	.check_status		= ata_check_status,
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
-	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup,
 	.bmdma_start            = ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.eng_timeout		= ata_eng_timeout,
+	.data_xfer		= ata_pio_data_xfer,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= sis_scr_read,
@@ -125,8 +129,7 @@
 
 static struct ata_port_info sis_port_info = {
 	.sht		= &sis_sht,
-	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-			  ATA_FLAG_NO_LEGACY,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x7,
 	.udma_mask	= 0x7f,
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 53b0d5c..7566c2ca 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -54,7 +54,7 @@
 #endif /* CONFIG_PPC_OF */
 
 #define DRV_NAME	"sata_svw"
-#define DRV_VERSION	"1.07"
+#define DRV_VERSION	"2.0"
 
 enum {
 	/* Taskfile registers offsets */
@@ -257,7 +257,7 @@
 	int len, index;
 
 	/* Find  the ata_port */
-	ap = (struct ata_port *) &shost->hostdata[0];
+	ap = ata_shost_to_port(shost);
 	if (ap == NULL)
 		return 0;
 
@@ -299,6 +299,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 #ifdef CONFIG_PPC_OF
 	.proc_info		= k2_sata_proc_info,
 #endif
@@ -313,14 +314,17 @@
 	.check_status		= k2_stat_check_status,
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
-	.phy_reset		= sata_phy_reset,
 	.bmdma_setup		= k2_bmdma_setup_mmio,
 	.bmdma_start		= k2_bmdma_start_mmio,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.eng_timeout		= ata_eng_timeout,
+	.data_xfer		= ata_mmio_data_xfer,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= k2_sata_scr_read,
@@ -420,8 +424,8 @@
 	writel(0x0, mmio_base + K2_SATA_SIM_OFFSET);
 
 	probe_ent->sht = &k2_sata_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-				ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
+	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+				ATA_FLAG_MMIO;
 	probe_ent->port_ops = &k2_sata_ops;
 	probe_ent->n_ports = 4;
 	probe_ent->irq = pdev->irq;
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 4139ad4..7f86441 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -46,7 +46,7 @@
 #include "sata_promise.h"
 
 #define DRV_NAME	"sata_sx4"
-#define DRV_VERSION	"0.8"
+#define DRV_VERSION	"0.9"
 
 
 enum {
@@ -191,6 +191,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -204,6 +205,7 @@
 	.phy_reset		= pdc_20621_phy_reset,
 	.qc_prep		= pdc20621_qc_prep,
 	.qc_issue		= pdc20621_qc_issue_prot,
+	.data_xfer		= ata_mmio_data_xfer,
 	.eng_timeout		= pdc_eng_timeout,
 	.irq_handler		= pdc20621_interrupt,
 	.irq_clear		= pdc20621_irq_clear,
@@ -218,7 +220,7 @@
 		.sht		= &pdc_sata_sht,
 		.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
 				  ATA_FLAG_SRST | ATA_FLAG_MMIO |
-				  ATA_FLAG_NO_ATAPI,
+				  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= 0x1f, /* pio0-4 */
 		.mwdma_mask	= 0x07, /* mwdma0-2 */
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
@@ -833,11 +835,11 @@
 		tmp = mask & (1 << i);
 		VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp);
 		if (tmp && ap &&
-		    !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) {
+		    !(ap->flags & ATA_FLAG_DISABLED)) {
 			struct ata_queued_cmd *qc;
 
 			qc = ata_qc_from_tag(ap, ap->active_tag);
-			if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+			if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
 				handled += pdc20621_host_intr(ap, qc, (i > 4),
 							      mmio_base);
 		}
@@ -868,15 +870,16 @@
 	switch (qc->tf.protocol) {
 	case ATA_PROT_DMA:
 	case ATA_PROT_NODATA:
-		printk(KERN_ERR "ata%u: command timeout\n", ap->id);
+		ata_port_printk(ap, KERN_ERR, "command timeout\n");
 		qc->err_mask |= __ac_err_mask(ata_wait_idle(ap));
 		break;
 
 	default:
 		drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
 
-		printk(KERN_ERR "ata%u: unknown timeout, cmd 0x%x stat 0x%x\n",
-		       ap->id, qc->tf.command, drv_stat);
+		ata_port_printk(ap, KERN_ERR,
+				"unknown timeout, cmd 0x%x stat 0x%x\n",
+				qc->tf.command, drv_stat);
 
 		qc->err_mask |= ac_err_mask(drv_stat);
 		break;
@@ -1375,10 +1378,6 @@
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
-	/*
-	 * If this driver happens to only be useful on Apple's K2, then
-	 * we should check that here as it has a normal Serverworks ID
-	 */
 	rc = pci_enable_device(pdev);
 	if (rc)
 		return rc;
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 38b52bd..64f3c1a 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -37,7 +37,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_uli"
-#define DRV_VERSION	"0.5"
+#define DRV_VERSION	"1.0"
 
 enum {
 	uli_5289		= 0,
@@ -90,6 +90,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -102,16 +103,18 @@
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
 
-	.phy_reset		= sata_phy_reset,
-
 	.bmdma_setup            = ata_bmdma_setup,
 	.bmdma_start            = ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
@@ -126,8 +129,7 @@
 
 static struct ata_port_info uli_port_info = {
 	.sht            = &uli_sht,
-	.host_flags     = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-			  ATA_FLAG_NO_LEGACY,
+	.host_flags     = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask       = 0x1f,		/* pio0-4 */
 	.udma_mask      = 0x7f,		/* udma0-6 */
 	.port_ops       = &uli_ops,
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 9e7ae4e..67c3d29 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -47,7 +47,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"sata_via"
-#define DRV_VERSION	"1.1"
+#define DRV_VERSION	"2.0"
 
 enum board_ids_enum {
 	vt6420,
@@ -103,6 +103,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -115,8 +116,6 @@
 	.exec_command		= ata_exec_command,
 	.dev_select		= ata_std_dev_select,
 
-	.phy_reset		= sata_phy_reset,
-
 	.bmdma_setup            = ata_bmdma_setup,
 	.bmdma_start            = ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
@@ -124,8 +123,12 @@
 
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
+	.data_xfer		= ata_pio_data_xfer,
 
-	.eng_timeout		= ata_eng_timeout,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 
 	.irq_handler		= ata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
@@ -140,7 +143,7 @@
 
 static struct ata_port_info svia_port_info = {
 	.sht		= &svia_sht,
-	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 	.pio_mask	= 0x1f,
 	.mwdma_mask	= 0x07,
 	.udma_mask	= 0x7f,
@@ -235,8 +238,7 @@
 	INIT_LIST_HEAD(&probe_ent->node);
 
 	probe_ent->sht		= &svia_sht;
-	probe_ent->host_flags	= ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-				  ATA_FLAG_NO_LEGACY;
+	probe_ent->host_flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY;
 	probe_ent->port_ops	= &svia_sata_ops;
 	probe_ent->n_ports	= N_PORTS;
 	probe_ent->irq		= pdev->irq;
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 8a29ce3..616fd96 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -47,7 +47,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_vsc"
-#define DRV_VERSION	"1.2"
+#define DRV_VERSION	"2.0"
 
 enum {
 	/* Interrupt register offsets (from chip base address) */
@@ -221,14 +221,21 @@
 
 			ap = host_set->ports[i];
 
-			if (ap && !(ap->flags &
-				    (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) {
+			if (is_vsc_sata_int_err(i, int_status)) {
+				u32 err_status;
+				printk(KERN_DEBUG "%s: ignoring interrupt(s)\n", __FUNCTION__);
+				err_status = ap ? vsc_sata_scr_read(ap, SCR_ERROR) : 0;
+				vsc_sata_scr_write(ap, SCR_ERROR, err_status);
+				handled++;
+			}
+
+			if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
 				struct ata_queued_cmd *qc;
 
 				qc = ata_qc_from_tag(ap, ap->active_tag);
-				if (qc && (!(qc->tf.ctl & ATA_NIEN))) {
+				if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
 					handled += ata_host_intr(ap, qc);
-				} else if (is_vsc_sata_int_err(i, int_status)) {
+				else if (is_vsc_sata_int_err(i, int_status)) {
 					/*
 					 * On some chips (i.e. Intel 31244), an error
 					 * interrupt will sneak in at initialization
@@ -272,6 +279,7 @@
 	.proc_name		= DRV_NAME,
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
+	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
 };
 
@@ -283,14 +291,17 @@
 	.exec_command		= ata_exec_command,
 	.check_status		= ata_check_status,
 	.dev_select		= ata_std_dev_select,
-	.phy_reset		= sata_phy_reset,
 	.bmdma_setup            = ata_bmdma_setup,
 	.bmdma_start            = ata_bmdma_start,
 	.bmdma_stop		= ata_bmdma_stop,
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.eng_timeout		= ata_eng_timeout,
+	.data_xfer		= ata_pio_data_xfer,
+	.freeze			= ata_bmdma_freeze,
+	.thaw			= ata_bmdma_thaw,
+	.error_handler		= ata_bmdma_error_handler,
+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 	.irq_handler		= vsc_sata_interrupt,
 	.irq_clear		= ata_bmdma_irq_clear,
 	.scr_read		= vsc_sata_scr_read,
@@ -385,7 +396,7 @@
 
 	probe_ent->sht = &vsc_sata_sht;
 	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET;
+				ATA_FLAG_MMIO;
 	probe_ent->port_ops = &vsc_sata_ops;
 	probe_ent->n_ports = 4;
 	probe_ent->irq = pdev->irq;
@@ -432,15 +443,12 @@
 }
 
 
-/*
- * 0x1725/0x7174 is the Vitesse VSC-7174
- * 0x8086/0x3200 is the Intel 31244, which is supposed to be identical
- * compatibility is untested as of yet
- */
 static const struct pci_device_id vsc_sata_pci_tbl[] = {
-	{ 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
-	{ 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
-	{ }
+	{ PCI_VENDOR_ID_VITESSE, 0x7174,
+	  PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
+	{ PCI_VENDOR_ID_INTEL, 0x3200,
+	  PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
+	{ }	/* terminate list */
 };
 
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 73994e2..2ab7df0 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -63,7 +63,6 @@
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
-#include <scsi/scsi_request.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
@@ -116,79 +115,6 @@
 };
 EXPORT_SYMBOL(scsi_device_types);
 
-/*
- * Function:    scsi_allocate_request
- *
- * Purpose:     Allocate a request descriptor.
- *
- * Arguments:   device		- device for which we want a request
- *		gfp_mask	- allocation flags passed to kmalloc
- *
- * Lock status: No locks assumed to be held.  This function is SMP-safe.
- *
- * Returns:     Pointer to request block.
- */
-struct scsi_request *scsi_allocate_request(struct scsi_device *sdev,
-					   gfp_t gfp_mask)
-{
-	const int offset = ALIGN(sizeof(struct scsi_request), 4);
-	const int size = offset + sizeof(struct request);
-	struct scsi_request *sreq;
-  
-	sreq = kzalloc(size, gfp_mask);
-	if (likely(sreq != NULL)) {
-		sreq->sr_request = (struct request *)(((char *)sreq) + offset);
-		sreq->sr_device = sdev;
-		sreq->sr_host = sdev->host;
-		sreq->sr_magic = SCSI_REQ_MAGIC;
-		sreq->sr_data_direction = DMA_BIDIRECTIONAL;
-	}
-
-	return sreq;
-}
-EXPORT_SYMBOL(scsi_allocate_request);
-
-void __scsi_release_request(struct scsi_request *sreq)
-{
-	struct request *req = sreq->sr_request;
-
-	/* unlikely because the tag was usually ended earlier by the
-	 * mid-layer. However, for layering reasons ULD's don't end
-	 * the tag of commands they generate. */
-	if (unlikely(blk_rq_tagged(req))) {
-		unsigned long flags;
-		struct request_queue *q = req->q;
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_queue_end_tag(q, req);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-	}
-
-
-	if (likely(sreq->sr_command != NULL)) {
-		struct scsi_cmnd *cmd = sreq->sr_command;
-
-		sreq->sr_command = NULL;
-		scsi_next_command(cmd);
-	}
-}
-
-/*
- * Function:    scsi_release_request
- *
- * Purpose:     Release a request descriptor.
- *
- * Arguments:   sreq    - request to release
- *
- * Lock status: No locks assumed to be held.  This function is SMP-safe.
- */
-void scsi_release_request(struct scsi_request *sreq)
-{
-	__scsi_release_request(sreq);
-	kfree(sreq);
-}
-EXPORT_SYMBOL(scsi_release_request);
-
 struct scsi_host_cmd_pool {
 	kmem_cache_t	*slab;
 	unsigned int	users;
@@ -646,73 +572,6 @@
 	return rtn;
 }
 
-/*
- * Function:    scsi_init_cmd_from_req
- *
- * Purpose:     Queue a SCSI command
- * Purpose:     Initialize a struct scsi_cmnd from a struct scsi_request
- *
- * Arguments:   cmd       - command descriptor.
- *              sreq      - Request from the queue.
- *
- * Lock status: None needed.
- *
- * Returns:     Nothing.
- *
- * Notes:       Mainly transfer data from the request structure to the
- *              command structure.  The request structure is allocated
- *              using the normal memory allocator, and requests can pile
- *              up to more or less any depth.  The command structure represents
- *              a consumable resource, as these are allocated into a pool
- *              when the SCSI subsystem initializes.  The preallocation is
- *              required so that in low-memory situations a disk I/O request
- *              won't cause the memory manager to try and write out a page.
- *              The request structure is generally used by ioctls and character
- *              devices.
- */
-void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, struct scsi_request *sreq)
-{
-	sreq->sr_command = cmd;
-
-	cmd->cmd_len = sreq->sr_cmd_len;
-	cmd->use_sg = sreq->sr_use_sg;
-
-	cmd->request = sreq->sr_request;
-	memcpy(cmd->data_cmnd, sreq->sr_cmnd, sizeof(cmd->data_cmnd));
-	cmd->serial_number = 0;
-	cmd->bufflen = sreq->sr_bufflen;
-	cmd->buffer = sreq->sr_buffer;
-	cmd->retries = 0;
-	cmd->allowed = sreq->sr_allowed;
-	cmd->done = sreq->sr_done;
-	cmd->timeout_per_command = sreq->sr_timeout_per_command;
-	cmd->sc_data_direction = sreq->sr_data_direction;
-	cmd->sglist_len = sreq->sr_sglist_len;
-	cmd->underflow = sreq->sr_underflow;
-	cmd->sc_request = sreq;
-	memcpy(cmd->cmnd, sreq->sr_cmnd, sizeof(sreq->sr_cmnd));
-
-	/*
-	 * Zero the sense buffer.  Some host adapters automatically request
-	 * sense on error.  0 is not a valid sense code.
-	 */
-	memset(cmd->sense_buffer, 0, sizeof(sreq->sr_sense_buffer));
-	cmd->request_buffer = sreq->sr_buffer;
-	cmd->request_bufflen = sreq->sr_bufflen;
-	cmd->old_use_sg = cmd->use_sg;
-	if (cmd->cmd_len == 0)
-		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
-	cmd->old_cmd_len = cmd->cmd_len;
-	cmd->sc_old_data_direction = cmd->sc_data_direction;
-	cmd->old_underflow = cmd->underflow;
-
-	/*
-	 * Start the timer ticking.
-	 */
-	cmd->result = 0;
-
-	SCSI_LOG_MLQUEUE(3, printk("Leaving scsi_init_cmd_from_req()\n"));
-}
 
 /*
  * Per-CPU I/O completion queue.
@@ -720,6 +579,24 @@
 static DEFINE_PER_CPU(struct list_head, scsi_done_q);
 
 /**
+ * scsi_req_abort_cmd -- Request command recovery for the specified command
+ * cmd: pointer to the SCSI command of interest
+ *
+ * This function requests that SCSI Core start recovery for the
+ * command by deleting the timer and adding the command to the eh
+ * queue.  It can be called by either LLDDs or SCSI Core.  LLDDs who
+ * implement their own error recovery MAY ignore the timeout event if
+ * they generated scsi_req_abort_cmd.
+ */
+void scsi_req_abort_cmd(struct scsi_cmnd *cmd)
+{
+	if (!scsi_delete_timer(cmd))
+		return;
+	scsi_times_out(cmd);
+}
+EXPORT_SYMBOL(scsi_req_abort_cmd);
+
+/**
  * scsi_done - Enqueue the finished SCSI command into the done queue.
  * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives
  * ownership back to SCSI Core -- i.e. the LLDD has finished with it.
@@ -809,7 +686,6 @@
 {
 	struct scsi_device *sdev = cmd->device;
 	struct Scsi_Host *shost = sdev->host;
-	struct scsi_request *sreq;
 
 	scsi_device_unbusy(sdev);
 
@@ -839,21 +715,6 @@
 	 * We can get here with use_sg=0, causing a panic in the upper level
 	 */
 	cmd->use_sg = cmd->old_use_sg;
-
-	/*
-	 * If there is an associated request structure, copy the data over
-	 * before we call the completion function.
-	 */
-	sreq = cmd->sc_request;
-	if (sreq) {
-	       sreq->sr_result = sreq->sr_command->result;
-	       if (sreq->sr_result) {
-		       memcpy(sreq->sr_sense_buffer,
-			      sreq->sr_command->sense_buffer,
-			      sizeof(sreq->sr_sense_buffer));
-	       }
-	}
-
 	cmd->done(cmd);
 }
 EXPORT_SYMBOL(scsi_finish_command);
diff --git a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h
index 5ee5d80a..f51e466 100644
--- a/drivers/scsi/scsi.h
+++ b/drivers/scsi/scsi.h
@@ -25,7 +25,6 @@
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_eh.h>
-#include <scsi/scsi_request.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsi.h>
 
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 62f8cb7..fb5cb4c 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -159,6 +159,8 @@
 	{"HITACHI", "DF400", "*", BLIST_SPARSELUN},
 	{"HITACHI", "DF500", "*", BLIST_SPARSELUN},
 	{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
+	{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
+	{"HITACHI", "OPEN-E", "*", BLIST_ATTACH_PQ3 | BLIST_SPARSELUN | BLIST_LARGELUN},
 	{"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN},	/* HP VA7400 */
 	{"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */
 	{"HP", "NetRAID-4M", NULL, BLIST_FORCELUN},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 1c75646..6a7a60f 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -26,13 +26,13 @@
 #include <linux/delay.h>
 
 #include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
@@ -58,6 +58,28 @@
 }
 
 /**
+ * scsi_schedule_eh - schedule EH for SCSI host
+ * @shost:	SCSI host to invoke error handling on.
+ *
+ * Schedule SCSI EH without scmd.
+ **/
+void scsi_schedule_eh(struct Scsi_Host *shost)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(shost->host_lock, flags);
+
+	if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
+	    scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
+		shost->host_eh_scheduled++;
+		scsi_eh_wakeup(shost);
+	}
+
+	spin_unlock_irqrestore(shost->host_lock, flags);
+}
+EXPORT_SYMBOL_GPL(scsi_schedule_eh);
+
+/**
  * scsi_eh_scmd_add - add scsi cmd to error handling.
  * @scmd:	scmd to run eh on.
  * @eh_flag:	optional SCSI_EH flag.
@@ -452,7 +474,6 @@
 			(sdev->lun << 5 & 0xe0);
 
 	shost->eh_action = &done;
-	scmd->request->rq_status = RQ_SCSI_BUSY;
 
 	spin_lock_irqsave(shost->host_lock, flags);
 	scsi_log_send(scmd);
@@ -461,7 +482,6 @@
 
 	timeleft = wait_for_completion_timeout(&done, timeout);
 
-	scmd->request->rq_status = RQ_SCSI_DONE;
 	shost->eh_action = NULL;
 
 	scsi_log_completion(scmd, SUCCESS);
@@ -1517,7 +1537,7 @@
 	 */
 	set_current_state(TASK_INTERRUPTIBLE);
 	while (!kthread_should_stop()) {
-		if (shost->host_failed == 0 ||
+		if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) ||
 		    shost->host_failed != shost->host_busy) {
 			SCSI_LOG_ERROR_RECOVERY(1,
 				printk("Error handler scsi_eh_%d sleeping\n",
@@ -1657,7 +1677,6 @@
 
 	scmd->request = &req;
 	memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
-	scmd->request->rq_status      	= RQ_SCSI_BUSY;
 
 	memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
     
@@ -1671,8 +1690,6 @@
 	scmd->cmd_len			= 0;
 
 	scmd->sc_data_direction		= DMA_BIDIRECTIONAL;
-	scmd->sc_request		= NULL;
-	scmd->sc_magic			= SCSI_CMND_MAGIC;
 
 	init_timer(&scmd->eh_timeout);
 
@@ -1769,14 +1786,6 @@
 }
 EXPORT_SYMBOL(scsi_normalize_sense);
 
-int scsi_request_normalize_sense(struct scsi_request *sreq,
-				 struct scsi_sense_hdr *sshdr)
-{
-	return scsi_normalize_sense(sreq->sr_sense_buffer,
-			sizeof(sreq->sr_sense_buffer), sshdr);
-}
-EXPORT_SYMBOL(scsi_request_normalize_sense);
-
 int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
 				 struct scsi_sense_hdr *sshdr)
 {
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index a89aff6..a89c411 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -15,11 +15,11 @@
 #include <asm/uaccess.h>
 
 #include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
-#include <scsi/scsi_request.h>
 #include <scsi/sg.h>
 #include <scsi/scsi_dbg.h>
 
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index faee475..3d04a9f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -19,18 +19,18 @@
 #include <linux/hardirq.h>
 
 #include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_dbg.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_host.h>
-#include <scsi/scsi_request.h>
 
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
 
-#define SG_MEMPOOL_NR		(sizeof(scsi_sg_pools)/sizeof(struct scsi_host_sg_pool))
+#define SG_MEMPOOL_NR		ARRAY_SIZE(scsi_sg_pools)
 #define SG_MEMPOOL_SIZE		32
 
 struct scsi_host_sg_pool {
@@ -83,7 +83,7 @@
 	struct scsi_cmnd *cmd = req->special;
 
 	req->flags &= ~REQ_DONTPREP;
-	req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
+	req->special = NULL;
 
 	scsi_put_command(cmd);
 }
@@ -161,72 +161,6 @@
 	return 0;
 }
 
-/*
- * Function:    scsi_do_req
- *
- * Purpose:     Queue a SCSI request
- *
- * Arguments:   sreq	  - command descriptor.
- *              cmnd      - actual SCSI command to be performed.
- *              buffer    - data buffer.
- *              bufflen   - size of data buffer.
- *              done      - completion function to be run.
- *              timeout   - how long to let it run before timeout.
- *              retries   - number of retries we allow.
- *
- * Lock status: No locks held upon entry.
- *
- * Returns:     Nothing.
- *
- * Notes:	This function is only used for queueing requests for things
- *		like ioctls and character device requests - this is because
- *		we essentially just inject a request into the queue for the
- *		device.
- *
- *		In order to support the scsi_device_quiesce function, we
- *		now inject requests on the *head* of the device queue
- *		rather than the tail.
- */
-void scsi_do_req(struct scsi_request *sreq, const void *cmnd,
-		 void *buffer, unsigned bufflen,
-		 void (*done)(struct scsi_cmnd *),
-		 int timeout, int retries)
-{
-	/*
-	 * If the upper level driver is reusing these things, then
-	 * we should release the low-level block now.  Another one will
-	 * be allocated later when this request is getting queued.
-	 */
-	__scsi_release_request(sreq);
-
-	/*
-	 * Our own function scsi_done (which marks the host as not busy,
-	 * disables the timeout counter, etc) will be called by us or by the
-	 * scsi_hosts[host].queuecommand() function needs to also call
-	 * the completion function for the high level driver.
-	 */
-	memcpy(sreq->sr_cmnd, cmnd, sizeof(sreq->sr_cmnd));
-	sreq->sr_bufflen = bufflen;
-	sreq->sr_buffer = buffer;
-	sreq->sr_allowed = retries;
-	sreq->sr_done = done;
-	sreq->sr_timeout_per_command = timeout;
-
-	if (sreq->sr_cmd_len == 0)
-		sreq->sr_cmd_len = COMMAND_SIZE(sreq->sr_cmnd[0]);
-
-	/*
-	 * head injection *required* here otherwise quiesce won't work
-	 *
-	 * Because users of this function are apt to reuse requests with no
-	 * modification, we have to sanitise the request flags here
-	 */
-	sreq->sr_request->flags &= ~REQ_DONTPREP;
-	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
-		       	   1, sreq);
-}
-EXPORT_SYMBOL(scsi_do_req);
-
 /**
  * scsi_execute - insert request and wait for the result
  * @sdev:	scsi device
@@ -566,7 +500,7 @@
 	spin_lock_irqsave(shost->host_lock, flags);
 	shost->host_busy--;
 	if (unlikely(scsi_host_in_recovery(shost) &&
-		     shost->host_failed))
+		     (shost->host_failed || shost->host_eh_scheduled)))
 		scsi_eh_wakeup(shost);
 	spin_unlock(shost->host_lock);
 	spin_lock(sdev->request_queue->queue_lock);
@@ -1300,15 +1234,7 @@
 	 * at request->cmd, as this tells us the real story.
 	 */
 	if (req->flags & REQ_SPECIAL && req->special) {
-		struct scsi_request *sreq = req->special;
-
-		if (sreq->sr_magic == SCSI_REQ_MAGIC) {
-			cmd = scsi_get_command(sreq->sr_device, GFP_ATOMIC);
-			if (unlikely(!cmd))
-				goto defer;
-			scsi_init_cmd_from_req(cmd, sreq);
-		} else
-			cmd = req->special;
+		cmd = req->special;
 	} else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) {
 
 		if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {
@@ -2363,3 +2289,61 @@
 		device_for_each_child(dev, NULL, target_unblock);
 }
 EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+/**
+ * scsi_kmap_atomic_sg - find and atomically map an sg-elemnt
+ * @sg:		scatter-gather list
+ * @sg_count:	number of segments in sg
+ * @offset:	offset in bytes into sg, on return offset into the mapped area
+ * @len:	bytes to map, on return number of bytes mapped
+ *
+ * Returns virtual address of the start of the mapped page
+ */
+void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
+			  size_t *offset, size_t *len)
+{
+	int i;
+	size_t sg_len = 0, len_complete = 0;
+	struct page *page;
+
+	for (i = 0; i < sg_count; i++) {
+		len_complete = sg_len; /* Complete sg-entries */
+		sg_len += sg[i].length;
+		if (sg_len > *offset)
+			break;
+	}
+
+	if (unlikely(i == sg_count)) {
+		printk(KERN_ERR "%s: Bytes in sg: %zu, requested offset %zu, "
+			"elements %d\n",
+		       __FUNCTION__, sg_len, *offset, sg_count);
+		WARN_ON(1);
+		return NULL;
+	}
+
+	/* Offset starting from the beginning of first page in this sg-entry */
+	*offset = *offset - len_complete + sg[i].offset;
+
+	/* Assumption: contiguous pages can be accessed as "page + i" */
+	page = nth_page(sg[i].page, (*offset >> PAGE_SHIFT));
+	*offset &= ~PAGE_MASK;
+
+	/* Bytes in this sg-entry from *offset to the end of the page */
+	sg_len = PAGE_SIZE - *offset;
+	if (*len > sg_len)
+		*len = sg_len;
+
+	return kmap_atomic(page, KM_BIO_SRC_IRQ);
+}
+EXPORT_SYMBOL(scsi_kmap_atomic_sg);
+
+/**
+ * scsi_kunmap_atomic_sg - atomically unmap a virtual address, previously
+ *			   mapped with scsi_kmap_atomic_sg
+ * @virt:	virtual address to be unmapped
+ */
+void scsi_kunmap_atomic_sg(void *virt)
+{
+	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
+}
+EXPORT_SYMBOL(scsi_kunmap_atomic_sg);
diff --git a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h
index e1722ba..a3e2af6 100644
--- a/drivers/scsi/scsi_logging.h
+++ b/drivers/scsi/scsi_logging.h
@@ -45,10 +45,12 @@
         ((scsi_logging_level >> (SHIFT)) & ((1 << (BITS)) - 1))
 
 #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)		\
-{								\
+do {								\
         if (unlikely((SCSI_LOG_LEVEL(SHIFT, BITS)) > (LEVEL)))	\
-		(CMD);						\
-}
+		do {						\
+			CMD;					\
+		} while (0);					\
+} while (0)
 #else
 #define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)
 #endif /* CONFIG_SCSI_LOGGING */
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 27c4827..a1727a0 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -8,17 +8,10 @@
 struct scsi_cmnd;
 struct scsi_device;
 struct scsi_host_template;
-struct scsi_request;
 struct Scsi_Host;
 
 
 /*
- * Magic values for certain scsi structs. Shouldn't ever be used.
- */
-#define SCSI_CMND_MAGIC		0xE25C23A5
-#define SCSI_REQ_MAGIC		0x75F6D354
-
-/*
  * Scsi Error Handler Flags
  */
 #define SCSI_EH_CANCEL_CMD	0x0001	/* Cancel this cmd */
@@ -34,9 +27,6 @@
 extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
-extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
-		struct scsi_request *sreq);
-extern void __scsi_release_request(struct scsi_request *sreq);
 extern void __scsi_done(struct scsi_cmnd *cmd);
 extern int scsi_retry_command(struct scsi_cmnd *cmd);
 #ifdef CONFIG_SCSI_LOGGING
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 07be62b..55200e4 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -266,8 +266,6 @@
 		lun = simple_strtoul(p + 1, &p, 0);
 
 		err = scsi_add_single_device(host, channel, id, lun);
-		if (err >= 0)
-			err = length;
 
 	/*
 	 * Usage: echo "scsi remove-single-device 0 1 2 3" >/proc/scsi/scsi
@@ -284,6 +282,13 @@
 		err = scsi_remove_single_device(host, channel, id, lun);
 	}
 
+	/*
+	 * convert success returns so that we return the 
+	 * number of bytes consumed.
+	 */
+	if (!err)
+		err = length;
+
  out:
 	free_page((unsigned long)buffer);
 	return err;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 1a5474b..0f7e6f9 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -33,11 +33,11 @@
 #include <asm/semaphore.h>
 
 #include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_driver.h>
 #include <scsi/scsi_devinfo.h>
 #include <scsi/scsi_host.h>
-#include <scsi/scsi_request.h>
 #include <scsi/scsi_transport.h>
 #include <scsi/scsi_eh.h>
 
@@ -816,6 +816,32 @@
 	put_device(&sdev->sdev_gendev);
 }
 
+#ifdef CONFIG_SCSI_LOGGING
+/** 
+ * scsi_inq_str - print INQUIRY data from min to max index,
+ * strip trailing whitespace
+ * @buf:   Output buffer with at least end-first+1 bytes of space
+ * @inq:   Inquiry buffer (input)
+ * @first: Offset of string into inq
+ * @end:   Index after last character in inq
+ */
+static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq,
+				   unsigned first, unsigned end)
+{
+	unsigned term = 0, idx;
+
+	for (idx = 0; idx + first < end && idx + first < inq[4] + 5; idx++) {
+		if (inq[idx+first] > ' ') {
+			buf[idx] = inq[idx+first];
+			term = idx+1;
+		} else {
+			buf[idx] = ' ';
+		}
+	}
+	buf[term] = 0;
+	return buf;
+}
+#endif
 
 /**
  * scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
@@ -880,10 +906,12 @@
 	if (scsi_probe_lun(sdev, result, result_len, &bflags))
 		goto out_free_result;
 
+	if (bflagsp)
+		*bflagsp = bflags;
 	/*
 	 * result contains valid SCSI INQUIRY data.
 	 */
-	if ((result[0] >> 5) == 3) {
+	if (((result[0] >> 5) == 3) && !(bflags & BLIST_ATTACH_PQ3)) {
 		/*
 		 * For a Peripheral qualifier 3 (011b), the SCSI
 		 * spec says: The device server is not capable of
@@ -894,9 +922,22 @@
 		 * logical disk configured at sdev->lun, but there
 		 * is a target id responding.
 		 */
-		SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
-					"scsi scan: peripheral qualifier of 3,"
-					" no device added\n"));
+		SCSI_LOG_SCAN_BUS(2, sdev_printk(KERN_INFO, sdev, "scsi scan:"
+				   " peripheral qualifier of 3, device not"
+				   " added\n"))
+		if (lun == 0) {
+			SCSI_LOG_SCAN_BUS(1, {
+				unsigned char vend[9];
+				unsigned char mod[17];
+
+				sdev_printk(KERN_INFO, sdev,
+					"scsi scan: consider passing scsi_mod."
+					"dev_flags=%s:%s:0x240 or 0x800240\n",
+					scsi_inq_str(vend, result, 8, 16),
+					scsi_inq_str(mod, result, 16, 32));
+			});
+		}
+		
 		res = SCSI_SCAN_TARGET_PRESENT;
 		goto out_free_result;
 	}
@@ -920,8 +961,6 @@
 			sdev->lockable = 0;
 			scsi_unlock_floptical(sdev, result);
 		}
-		if (bflagsp)
-			*bflagsp = bflags;
 	}
 
  out_free_result:
@@ -946,7 +985,6 @@
  * scsi_sequential_lun_scan - sequentially scan a SCSI target
  * @starget:	pointer to target structure to scan
  * @bflags:	black/white list flag for LUN 0
- * @lun0_res:	result of scanning LUN 0
  *
  * Description:
  *     Generally, scan from LUN 1 (LUN 0 is assumed to already have been
@@ -956,8 +994,7 @@
  *     Modifies sdevscan->lun.
  **/
 static void scsi_sequential_lun_scan(struct scsi_target *starget,
-				     int bflags, int lun0_res, int scsi_level,
-				     int rescan)
+				     int bflags, int scsi_level, int rescan)
 {
 	unsigned int sparse_lun, lun, max_dev_lun;
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -978,13 +1015,6 @@
 		sparse_lun = 0;
 
 	/*
-	 * If not sparse lun and no device attached at LUN 0 do not scan
-	 * any further.
-	 */
-	if (!sparse_lun && (lun0_res != SCSI_SCAN_LUN_PRESENT))
-		return;
-
-	/*
 	 * If less than SCSI_1_CSS, and no special lun scaning, stop
 	 * scanning; this matches 2.4 behaviour, but could just be a bug
 	 * (to continue scanning a SCSI_1_CSS device).
@@ -1395,7 +1425,7 @@
 			 * do a sequential scan.
 			 */
 			scsi_sequential_lun_scan(starget, bflags,
-				       	res, starget->scsi_level, rescan);
+						 starget->scsi_level, rescan);
 	}
 
  out_reap:
@@ -1473,7 +1503,7 @@
 		__FUNCTION__, channel, id, lun));
 
 	if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) ||
-	    ((id != SCAN_WILD_CARD) && (id > shost->max_id)) ||
+	    ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) ||
 	    ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
 		return -EINVAL;
 
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index a6fde52..5ec7a4f 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -39,7 +39,7 @@
 	int i;
 	char *name = NULL;
 
-	for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
 		if (sdev_states[i].value == state) {
 			name = sdev_states[i].name;
 			break;
@@ -65,7 +65,7 @@
 	int i;
 	char *name = NULL;
 
-	for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
 		if (shost_states[i].value == state) {
 			name = shost_states[i].name;
 			break;
@@ -160,7 +160,7 @@
 	struct Scsi_Host *shost = class_to_shost(class_dev);
 	enum scsi_host_state state = 0;
 
-	for (i = 0; i < sizeof(shost_states)/sizeof(shost_states[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(shost_states); i++) {
 		const int len = strlen(shost_states[i].name);
 		if (strncmp(shost_states[i].name, buf, len) == 0 &&
 		   buf[len] == '\n') {
@@ -466,7 +466,7 @@
 	struct scsi_device *sdev = to_scsi_device(dev);
 	enum scsi_device_state state = 0;
 
-	for (i = 0; i < sizeof(sdev_states)/sizeof(sdev_states[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(sdev_states); i++) {
 		const int len = strlen(sdev_states[i].name);
 		if (strncmp(sdev_states[i].name, buf, len) == 0 &&
 		   buf[len] == '\n') {
diff --git a/drivers/scsi/scsi_transport_api.h b/drivers/scsi/scsi_transport_api.h
new file mode 100644
index 0000000..934f0e6
--- /dev/null
+++ b/drivers/scsi/scsi_transport_api.h
@@ -0,0 +1,6 @@
+#ifndef _SCSI_TRANSPORT_API_H
+#define _SCSI_TRANSPORT_API_H
+
+void scsi_schedule_eh(struct Scsi_Host *shost);
+
+#endif /* _SCSI_TRANSPORT_API_H */
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 95c5478..f2db7a4 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -50,7 +50,7 @@
 	int i;								\
 	char *name = NULL;						\
 									\
-	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {		\
+	for (i = 0; i < ARRAY_SIZE(table); i++) {			\
 		if (table[i].value == table_key) {			\
 			name = table[i].name;				\
 			break;						\
@@ -65,7 +65,7 @@
 {									\
 	int i;								\
 									\
-	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {		\
+	for (i = 0; i < ARRAY_SIZE(table); i++) {			\
 		if (strncmp(table_key, table[i].name,			\
 				table[i].matchlen) == 0) {		\
 			*value = table[i].value;			\
@@ -140,7 +140,7 @@
 	ssize_t len = 0;					\
 	int i;							\
 								\
-	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {	\
+	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
 		if (table[i].value & table_key) {		\
 			len += sprintf(buf + len, "%s%s",	\
 				prefix, table[i].name);		\
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 2730d50..5569fdc 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -31,31 +31,26 @@
 #include <scsi/scsi_transport_iscsi.h>
 #include <scsi/iscsi_if.h>
 
-#define ISCSI_SESSION_ATTRS 8
-#define ISCSI_CONN_ATTRS 6
+#define ISCSI_SESSION_ATTRS 11
+#define ISCSI_CONN_ATTRS 11
+#define ISCSI_HOST_ATTRS 0
 
 struct iscsi_internal {
+	int daemon_pid;
 	struct scsi_transport_template t;
 	struct iscsi_transport *iscsi_transport;
 	struct list_head list;
-	/*
-	 * based on transport capabilities, at register time we set these
-	 * bits to tell the transport class it wants attributes displayed
-	 * in sysfs or that it can support different iSCSI Data-Path
-	 * capabilities
-	 */
-	uint32_t param_mask;
-
 	struct class_device cdev;
-	/*
-	 * We do not have any private or other attrs.
-	 */
+
+	struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
 	struct transport_container conn_cont;
 	struct class_device_attribute *conn_attrs[ISCSI_CONN_ATTRS + 1];
 	struct transport_container session_cont;
 	struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
 };
 
+static int iscsi_session_nr;	/* sysfs session id for next new session */
+
 /*
  * list of registered transports and lock that must
  * be held while accessing list. The iscsi_transport_lock must
@@ -120,6 +115,24 @@
 	.attrs = iscsi_transport_attrs,
 };
 
+static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+			    struct class_device *cdev)
+{
+	struct Scsi_Host *shost = dev_to_shost(dev);
+	struct iscsi_host *ihost = shost->shost_data;
+
+	memset(ihost, 0, sizeof(*ihost));
+	INIT_LIST_HEAD(&ihost->sessions);
+	mutex_init(&ihost->mutex);
+	return 0;
+}
+
+static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+			       "iscsi_host",
+			       iscsi_setup_host,
+			       NULL,
+			       NULL);
+
 static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
 			       "iscsi_session",
 			       NULL,
@@ -133,7 +146,6 @@
 			       NULL);
 
 static struct sock *nls;
-static int daemon_pid;
 static DEFINE_MUTEX(rx_queue_mutex);
 
 struct mempool_zone {
@@ -165,14 +177,23 @@
 static LIST_HEAD(connlist);
 static DEFINE_SPINLOCK(connlock);
 
-static struct iscsi_cls_session *iscsi_session_lookup(uint64_t handle)
+static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
+{
+	struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
+	return sess->sid;
+}
+
+/*
+ * Returns the matching session to a given sid
+ */
+static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
 {
 	unsigned long flags;
 	struct iscsi_cls_session *sess;
 
 	spin_lock_irqsave(&sesslock, flags);
 	list_for_each_entry(sess, &sesslist, sess_list) {
-		if (sess == iscsi_ptr(handle)) {
+		if (sess->sid == sid) {
 			spin_unlock_irqrestore(&sesslock, flags);
 			return sess;
 		}
@@ -181,14 +202,17 @@
 	return NULL;
 }
 
-static struct iscsi_cls_conn *iscsi_conn_lookup(uint64_t handle)
+/*
+ * Returns the matching connection to a given sid / cid tuple
+ */
+static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
 {
 	unsigned long flags;
 	struct iscsi_cls_conn *conn;
 
 	spin_lock_irqsave(&connlock, flags);
 	list_for_each_entry(conn, &connlist, conn_list) {
-		if (conn == iscsi_ptr(handle)) {
+		if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
 			spin_unlock_irqrestore(&connlock, flags);
 			return conn;
 		}
@@ -209,6 +233,7 @@
 
 	shost = iscsi_session_to_shost(session);
 	scsi_host_put(shost);
+	kfree(session->targetname);
 	kfree(session);
 	module_put(transport->owner);
 }
@@ -218,30 +243,95 @@
 	return dev->release == iscsi_session_release;
 }
 
+static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+			   uint id, uint lun)
+{
+	struct iscsi_host *ihost = shost->shost_data;
+	struct iscsi_cls_session *session;
+
+	mutex_lock(&ihost->mutex);
+	list_for_each_entry(session, &ihost->sessions, host_list) {
+		if ((channel == SCAN_WILD_CARD ||
+		     channel == session->channel) &&
+		    (id == SCAN_WILD_CARD || id == session->target_id))
+			scsi_scan_target(&session->dev, session->channel,
+					 session->target_id, lun, 1);
+	}
+	mutex_unlock(&ihost->mutex);
+
+	return 0;
+}
+
+static void session_recovery_timedout(void *data)
+{
+	struct iscsi_cls_session *session = data;
+
+	dev_printk(KERN_INFO, &session->dev, "iscsi: session recovery timed "
+		  "out after %d secs\n", session->recovery_tmo);
+
+	if (session->transport->session_recovery_timedout)
+		session->transport->session_recovery_timedout(session);
+
+	scsi_target_unblock(&session->dev);
+}
+
+void iscsi_unblock_session(struct iscsi_cls_session *session)
+{
+	if (!cancel_delayed_work(&session->recovery_work))
+		flush_scheduled_work();
+	scsi_target_unblock(&session->dev);
+}
+EXPORT_SYMBOL_GPL(iscsi_unblock_session);
+
+void iscsi_block_session(struct iscsi_cls_session *session)
+{
+	scsi_target_block(&session->dev);
+	schedule_delayed_work(&session->recovery_work,
+			     session->recovery_tmo * HZ);
+}
+EXPORT_SYMBOL_GPL(iscsi_block_session);
+
 /**
  * iscsi_create_session - create iscsi class session
  * @shost: scsi host
  * @transport: iscsi transport
  *
- * This can be called from a LLD or iscsi_transport
+ * This can be called from a LLD or iscsi_transport.
  **/
 struct iscsi_cls_session *
-iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport)
+iscsi_create_session(struct Scsi_Host *shost,
+		     struct iscsi_transport *transport, int channel)
 {
+	struct iscsi_host *ihost;
 	struct iscsi_cls_session *session;
 	int err;
 
 	if (!try_module_get(transport->owner))
 		return NULL;
 
-	session = kzalloc(sizeof(*session), GFP_KERNEL);
+	session = kzalloc(sizeof(*session) + transport->sessiondata_size,
+			  GFP_KERNEL);
 	if (!session)
 		goto module_put;
 	session->transport = transport;
+	session->recovery_tmo = 120;
+	INIT_WORK(&session->recovery_work, session_recovery_timedout, session);
+	INIT_LIST_HEAD(&session->host_list);
+	INIT_LIST_HEAD(&session->sess_list);
+
+	if (transport->sessiondata_size)
+		session->dd_data = &session[1];
 
 	/* this is released in the dev's release function */
 	scsi_host_get(shost);
-	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", shost->host_no);
+	ihost = shost->shost_data;
+
+	session->sid = iscsi_session_nr++;
+	session->channel = channel;
+	session->target_id = ihost->next_target_id++;
+
+	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",
+		 session->sid);
 	session->dev.parent = &shost->shost_gendev;
 	session->dev.release = iscsi_session_release;
 	err = device_register(&session->dev);
@@ -252,6 +342,10 @@
 	}
 	transport_register_device(&session->dev);
 
+	mutex_lock(&ihost->mutex);
+	list_add(&session->host_list, &ihost->sessions);
+	mutex_unlock(&ihost->mutex);
+
 	return session;
 
 free_session:
@@ -272,6 +366,16 @@
  **/
 int iscsi_destroy_session(struct iscsi_cls_session *session)
 {
+	struct Scsi_Host *shost = iscsi_session_to_shost(session);
+	struct iscsi_host *ihost = shost->shost_data;
+
+	if (!cancel_delayed_work(&session->recovery_work))
+		flush_scheduled_work();
+
+	mutex_lock(&ihost->mutex);
+	list_del(&session->host_list);
+	mutex_unlock(&ihost->mutex);
+
 	transport_unregister_device(&session->dev);
 	device_unregister(&session->dev);
 	return 0;
@@ -284,6 +388,7 @@
 	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
 	struct device *parent = conn->dev.parent;
 
+	kfree(conn->persistent_address);
 	kfree(conn);
 	put_device(parent);
 }
@@ -301,12 +406,16 @@
  * This can be called from a LLD or iscsi_transport. The connection
  * is child of the session so cid must be unique for all connections
  * on the session.
+ *
+ * Since we do not support MCS, cid will normally be zero. In some cases
+ * for software iscsi we could be trying to preallocate a connection struct
+ * in which case there could be two connection structs and cid would be
+ * non-zero.
  **/
 struct iscsi_cls_conn *
 iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid)
 {
 	struct iscsi_transport *transport = session->transport;
-	struct Scsi_Host *shost = iscsi_session_to_shost(session);
 	struct iscsi_cls_conn *conn;
 	int err;
 
@@ -319,12 +428,14 @@
 
 	INIT_LIST_HEAD(&conn->conn_list);
 	conn->transport = transport;
+	conn->cid = cid;
 
 	/* this is released in the dev's release function */
 	if (!get_device(&session->dev))
 		goto free_conn;
+
 	snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u",
-		 shost->host_no, cid);
+		 session->sid, cid);
 	conn->dev.parent = &session->dev;
 	conn->dev.release = iscsi_conn_release;
 	err = device_register(&conn->dev);
@@ -361,105 +472,6 @@
 EXPORT_SYMBOL_GPL(iscsi_destroy_conn);
 
 /*
- * These functions are used only by software iscsi_transports
- * which do not allocate and more their scsi_hosts since this
- * is initiated from userspace.
- */
-
-/*
- * iSCSI Session's hostdata organization:
- *
- *    *------------------* <== hostdata_session(host->hostdata)
- *    | ptr to class sess|
- *    |------------------| <== iscsi_hostdata(host->hostdata)
- *    | transport's data |
- *    *------------------*
- */
-
-#define hostdata_privsize(_t)	(sizeof(unsigned long) + _t->hostdata_size + \
-				 _t->hostdata_size % sizeof(unsigned long))
-
-#define hostdata_session(_hostdata) (iscsi_ptr(*(unsigned long *)_hostdata))
-
-/**
- * iscsi_transport_create_session - create iscsi cls session and host
- * scsit: scsi transport template
- * transport: iscsi transport template
- *
- * This can be used by software iscsi_transports that allocate
- * a session per scsi host.
- **/
-struct Scsi_Host *
-iscsi_transport_create_session(struct scsi_transport_template *scsit,
-			       struct iscsi_transport *transport)
-{
-	struct iscsi_cls_session *session;
-	struct Scsi_Host *shost;
-	unsigned long flags;
-
-	shost = scsi_host_alloc(transport->host_template,
-				hostdata_privsize(transport));
-	if (!shost) {
-		printk(KERN_ERR "iscsi: can not allocate SCSI host for "
-			"session\n");
-		return NULL;
-	}
-
-	shost->max_id = 1;
-	shost->max_channel = 0;
-	shost->max_lun = transport->max_lun;
-	shost->max_cmd_len = transport->max_cmd_len;
-	shost->transportt = scsit;
-	shost->transportt->create_work_queue = 1;
-
-	if (scsi_add_host(shost, NULL))
-		goto free_host;
-
-	session = iscsi_create_session(shost, transport);
-	if (!session)
-		goto remove_host;
-
-	*(unsigned long*)shost->hostdata = (unsigned long)session;
-	spin_lock_irqsave(&sesslock, flags);
-	list_add(&session->sess_list, &sesslist);
-	spin_unlock_irqrestore(&sesslock, flags);
-	return shost;
-
-remove_host:
-	scsi_remove_host(shost);
-free_host:
-	scsi_host_put(shost);
-	return NULL;
-}
-
-EXPORT_SYMBOL_GPL(iscsi_transport_create_session);
-
-/**
- * iscsi_transport_destroy_session - destroy session and scsi host
- * shost: scsi host
- *
- * This can be used by software iscsi_transports that allocate
- * a session per scsi host.
- **/
-int iscsi_transport_destroy_session(struct Scsi_Host *shost)
-{
-	struct iscsi_cls_session *session;
-	unsigned long flags;
-
-	scsi_remove_host(shost);
-	session = hostdata_session(shost->hostdata);
-	spin_lock_irqsave(&sesslock, flags);
-	list_del(&session->sess_list);
-	spin_unlock_irqrestore(&sesslock, flags);
-	iscsi_destroy_session(session);
-	/* ref from host alloc */
-	scsi_host_put(shost);
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(iscsi_transport_destroy_session);
-
-/*
  * iscsi interface functions
  */
 static struct iscsi_internal *
@@ -560,13 +572,13 @@
 }
 
 static int
-iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb)
+iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid)
 {
 	unsigned long flags;
 	int rc;
 
 	skb_get(skb);
-	rc = netlink_unicast(nls, skb, daemon_pid, MSG_DONTWAIT);
+	rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT);
 	if (rc < 0) {
 		mempool_free(skb, zone->pool);
 		printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc);
@@ -574,6 +586,7 @@
 	}
 
 	spin_lock_irqsave(&zone->freelock, flags);
+	INIT_LIST_HEAD(skb_to_lh(skb));
 	list_add(skb_to_lh(skb), &zone->freequeue);
 	spin_unlock_irqrestore(&zone->freelock, flags);
 
@@ -587,9 +600,14 @@
 	struct sk_buff *skb;
 	struct iscsi_uevent *ev;
 	char *pdu;
+	struct iscsi_internal *priv;
 	int len = NLMSG_SPACE(sizeof(*ev) + sizeof(struct iscsi_hdr) +
 			      data_size);
 
+	priv = iscsi_if_transport_lookup(conn->transport);
+	if (!priv)
+		return -EINVAL;
+
 	mempool_zone_complete(conn->z_pdu);
 
 	skb = mempool_zone_get_skb(conn->z_pdu);
@@ -600,19 +618,20 @@
 		return -ENOMEM;
 	}
 
-	nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
+	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
 	ev = NLMSG_DATA(nlh);
 	memset(ev, 0, sizeof(*ev));
 	ev->transport_handle = iscsi_handle(conn->transport);
 	ev->type = ISCSI_KEVENT_RECV_PDU;
 	if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
 		ev->iferror = -ENOMEM;
-	ev->r.recv_req.conn_handle = iscsi_handle(conn);
+	ev->r.recv_req.cid = conn->cid;
+	ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
 	pdu = (char*)ev + sizeof(*ev);
 	memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
 	memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
 
-	return iscsi_unicast_skb(conn->z_pdu, skb);
+	return iscsi_unicast_skb(conn->z_pdu, skb, priv->daemon_pid);
 }
 EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
 
@@ -621,8 +640,13 @@
 	struct nlmsghdr	*nlh;
 	struct sk_buff	*skb;
 	struct iscsi_uevent *ev;
+	struct iscsi_internal *priv;
 	int len = NLMSG_SPACE(sizeof(*ev));
 
+	priv = iscsi_if_transport_lookup(conn->transport);
+	if (!priv)
+		return;
+
 	mempool_zone_complete(conn->z_error);
 
 	skb = mempool_zone_get_skb(conn->z_error);
@@ -632,16 +656,17 @@
 		return;
 	}
 
-	nlh = __nlmsg_put(skb, daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
+	nlh = __nlmsg_put(skb, priv->daemon_pid, 0, 0, (len - sizeof(*nlh)), 0);
 	ev = NLMSG_DATA(nlh);
 	ev->transport_handle = iscsi_handle(conn->transport);
 	ev->type = ISCSI_KEVENT_CONN_ERROR;
 	if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat)
 		ev->iferror = -ENOMEM;
 	ev->r.connerror.error = error;
-	ev->r.connerror.conn_handle = iscsi_handle(conn);
+	ev->r.connerror.cid = conn->cid;
+	ev->r.connerror.sid = iscsi_conn_get_sid(conn);
 
-	iscsi_unicast_skb(conn->z_error, skb);
+	iscsi_unicast_skb(conn->z_error, skb, priv->daemon_pid);
 
 	dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n",
 		   error);
@@ -671,7 +696,7 @@
 	nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0);
 	nlh->nlmsg_flags = flags;
 	memcpy(NLMSG_DATA(nlh), payload, size);
-	return iscsi_unicast_skb(z_reply, skb);
+	return iscsi_unicast_skb(z_reply, skb, pid);
 }
 
 static int
@@ -683,13 +708,18 @@
 	struct iscsi_cls_conn *conn;
 	struct nlmsghdr	*nlhstat;
 	struct iscsi_uevent *evstat;
+	struct iscsi_internal *priv;
 	int len = NLMSG_SPACE(sizeof(*ev) +
 			      sizeof(struct iscsi_stats) +
 			      sizeof(struct iscsi_stats_custom) *
 			      ISCSI_STATS_CUSTOM_MAX);
 	int err = 0;
 
-	conn = iscsi_conn_lookup(ev->u.get_stats.conn_handle);
+	priv = iscsi_if_transport_lookup(transport);
+	if (!priv)
+		return -EINVAL;
+
+	conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
 	if (!conn)
 		return -EEXIST;
 
@@ -705,7 +735,7 @@
 			return -ENOMEM;
 		}
 
-		nlhstat = __nlmsg_put(skbstat, daemon_pid, 0, 0,
+		nlhstat = __nlmsg_put(skbstat, priv->daemon_pid, 0, 0,
 				      (len - sizeof(*nlhstat)), 0);
 		evstat = NLMSG_DATA(nlhstat);
 		memset(evstat, 0, sizeof(*evstat));
@@ -713,8 +743,10 @@
 		evstat->type = nlh->nlmsg_type;
 		if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat)
 			evstat->iferror = -ENOMEM;
-		evstat->u.get_stats.conn_handle =
-			ev->u.get_stats.conn_handle;
+		evstat->u.get_stats.cid =
+			ev->u.get_stats.cid;
+		evstat->u.get_stats.sid =
+			ev->u.get_stats.sid;
 		stats = (struct iscsi_stats *)
 			((char*)evstat + sizeof(*evstat));
 		memset(stats, 0, sizeof(*stats));
@@ -729,7 +761,7 @@
 		skb_trim(skbstat, NLMSG_ALIGN(actual_size));
 		nlhstat->nlmsg_len = actual_size;
 
-		err = iscsi_unicast_skb(conn->z_pdu, skbstat);
+		err = iscsi_unicast_skb(conn->z_pdu, skbstat, priv->daemon_pid);
 	} while (err < 0 && err != -ECONNREFUSED);
 
 	return err;
@@ -740,16 +772,21 @@
 {
 	struct iscsi_transport *transport = priv->iscsi_transport;
 	struct iscsi_cls_session *session;
-	uint32_t sid;
+	unsigned long flags;
+	uint32_t hostno;
 
-	session = transport->create_session(&priv->t,
+	session = transport->create_session(transport, &priv->t,
 					    ev->u.c_session.initial_cmdsn,
-					    &sid);
+					    &hostno);
 	if (!session)
 		return -ENOMEM;
 
-	ev->r.c_session_ret.session_handle = iscsi_handle(session);
-	ev->r.c_session_ret.sid = sid;
+	spin_lock_irqsave(&sesslock, flags);
+	list_add(&session->sess_list, &sesslist);
+	spin_unlock_irqrestore(&sesslock, flags);
+
+	ev->r.c_session_ret.host_no = hostno;
+	ev->r.c_session_ret.sid = session->sid;
 	return 0;
 }
 
@@ -760,13 +797,20 @@
 	struct iscsi_cls_session *session;
 	unsigned long flags;
 
-	session = iscsi_session_lookup(ev->u.c_conn.session_handle);
-	if (!session)
+	session = iscsi_session_lookup(ev->u.c_conn.sid);
+	if (!session) {
+		printk(KERN_ERR "iscsi: invalid session %d\n",
+		       ev->u.c_conn.sid);
 		return -EINVAL;
+	}
 
 	conn = transport->create_conn(session, ev->u.c_conn.cid);
-	if (!conn)
+	if (!conn) {
+		printk(KERN_ERR "iscsi: couldn't create a new "
+			   "connection for session %d\n",
+			   session->sid);
 		return -ENOMEM;
+	}
 
 	conn->z_pdu = mempool_zone_init(Z_MAX_PDU,
 			NLMSG_SPACE(sizeof(struct iscsi_uevent) +
@@ -788,7 +832,8 @@
 		goto free_pdu_pool;
 	}
 
-	ev->r.handle = iscsi_handle(conn);
+	ev->r.c_conn_ret.sid = session->sid;
+	ev->r.c_conn_ret.cid = conn->cid;
 
 	spin_lock_irqsave(&connlock, flags);
 	list_add(&conn->conn_list, &connlist);
@@ -812,7 +857,7 @@
 	struct iscsi_cls_conn *conn;
 	struct mempool_zone *z_error, *z_pdu;
 
-	conn = iscsi_conn_lookup(ev->u.d_conn.conn_handle);
+	conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
 	if (!conn)
 		return -EINVAL;
 	spin_lock_irqsave(&connlock, flags);
@@ -832,6 +877,106 @@
 	return 0;
 }
 
+static void
+iscsi_copy_param(struct iscsi_uevent *ev, uint32_t *value, char *data)
+{
+	if (ev->u.set_param.len != sizeof(uint32_t))
+		BUG();
+	memcpy(value, data, min_t(uint32_t, sizeof(uint32_t),
+		ev->u.set_param.len));
+}
+
+static int
+iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+{
+	char *data = (char*)ev + sizeof(*ev);
+	struct iscsi_cls_conn *conn;
+	struct iscsi_cls_session *session;
+	int err = 0;
+	uint32_t value = 0;
+
+	session = iscsi_session_lookup(ev->u.set_param.sid);
+	conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
+	if (!conn || !session)
+		return -EINVAL;
+
+	switch (ev->u.set_param.param) {
+	case ISCSI_PARAM_SESS_RECOVERY_TMO:
+		iscsi_copy_param(ev, &value, data);
+		if (value != 0)
+			session->recovery_tmo = value;
+		break;
+	case ISCSI_PARAM_TARGET_NAME:
+		/* this should not change between logins */
+		if (session->targetname)
+			return 0;
+
+		session->targetname = kstrdup(data, GFP_KERNEL);
+		if (!session->targetname)
+			return -ENOMEM;
+		break;
+	case ISCSI_PARAM_TPGT:
+		iscsi_copy_param(ev, &value, data);
+		session->tpgt = value;
+		break;
+	case ISCSI_PARAM_PERSISTENT_PORT:
+		iscsi_copy_param(ev, &value, data);
+		conn->persistent_port = value;
+		break;
+	case ISCSI_PARAM_PERSISTENT_ADDRESS:
+		/*
+		 * this is the address returned in discovery so it should
+		 * not change between logins.
+		 */
+		if (conn->persistent_address)
+			return 0;
+
+		conn->persistent_address = kstrdup(data, GFP_KERNEL);
+		if (!conn->persistent_address)
+			return -ENOMEM;
+		break;
+	default:
+		iscsi_copy_param(ev, &value, data);
+		err = transport->set_param(conn, ev->u.set_param.param, value);
+	}
+
+	return err;
+}
+
+static int
+iscsi_if_transport_ep(struct iscsi_transport *transport,
+		      struct iscsi_uevent *ev, int msg_type)
+{
+	struct sockaddr *dst_addr;
+	int rc = 0;
+
+	switch (msg_type) {
+	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
+		if (!transport->ep_connect)
+			return -EINVAL;
+
+		dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
+		rc = transport->ep_connect(dst_addr,
+					   ev->u.ep_connect.non_blocking,
+					   &ev->r.ep_connect_ret.handle);
+		break;
+	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+		if (!transport->ep_poll)
+			return -EINVAL;
+
+		ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle,
+						   ev->u.ep_poll.timeout_ms);
+		break;
+	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+		if (!transport->ep_disconnect)
+			return -EINVAL;
+
+		transport->ep_disconnect(ev->u.ep_disconnect.ep_handle);
+		break;
+	}
+	return rc;
+}
+
 static int
 iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
@@ -841,6 +986,7 @@
 	struct iscsi_internal *priv;
 	struct iscsi_cls_session *session;
 	struct iscsi_cls_conn *conn;
+	unsigned long flags;
 
 	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
 	if (!priv)
@@ -850,15 +996,21 @@
 	if (!try_module_get(transport->owner))
 		return -EINVAL;
 
+	priv->daemon_pid = NETLINK_CREDS(skb)->pid;
+
 	switch (nlh->nlmsg_type) {
 	case ISCSI_UEVENT_CREATE_SESSION:
 		err = iscsi_if_create_session(priv, ev);
 		break;
 	case ISCSI_UEVENT_DESTROY_SESSION:
-		session = iscsi_session_lookup(ev->u.d_session.session_handle);
-		if (session)
+		session = iscsi_session_lookup(ev->u.d_session.sid);
+		if (session) {
+			spin_lock_irqsave(&sesslock, flags);
+			list_del(&session->sess_list);
+			spin_unlock_irqrestore(&sesslock, flags);
+
 			transport->destroy_session(session);
-		else
+		} else
 			err = -EINVAL;
 		break;
 	case ISCSI_UEVENT_CREATE_CONN:
@@ -868,41 +1020,35 @@
 		err = iscsi_if_destroy_conn(transport, ev);
 		break;
 	case ISCSI_UEVENT_BIND_CONN:
-		session = iscsi_session_lookup(ev->u.b_conn.session_handle);
-		conn = iscsi_conn_lookup(ev->u.b_conn.conn_handle);
+		session = iscsi_session_lookup(ev->u.b_conn.sid);
+		conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
 
 		if (session && conn)
 			ev->r.retcode =	transport->bind_conn(session, conn,
-					ev->u.b_conn.transport_fd,
+					ev->u.b_conn.transport_eph,
 					ev->u.b_conn.is_leading);
 		else
 			err = -EINVAL;
 		break;
 	case ISCSI_UEVENT_SET_PARAM:
-		conn = iscsi_conn_lookup(ev->u.set_param.conn_handle);
-		if (conn)
-			ev->r.retcode =	transport->set_param(conn,
-				ev->u.set_param.param, ev->u.set_param.value);
-		else
-			err = -EINVAL;
+		err = iscsi_set_param(transport, ev);
 		break;
 	case ISCSI_UEVENT_START_CONN:
-		conn = iscsi_conn_lookup(ev->u.start_conn.conn_handle);
+		conn = iscsi_conn_lookup(ev->u.start_conn.sid, ev->u.start_conn.cid);
 		if (conn)
 			ev->r.retcode = transport->start_conn(conn);
 		else
 			err = -EINVAL;
-
 		break;
 	case ISCSI_UEVENT_STOP_CONN:
-		conn = iscsi_conn_lookup(ev->u.stop_conn.conn_handle);
+		conn = iscsi_conn_lookup(ev->u.stop_conn.sid, ev->u.stop_conn.cid);
 		if (conn)
 			transport->stop_conn(conn, ev->u.stop_conn.flag);
 		else
 			err = -EINVAL;
 		break;
 	case ISCSI_UEVENT_SEND_PDU:
-		conn = iscsi_conn_lookup(ev->u.send_pdu.conn_handle);
+		conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
 		if (conn)
 			ev->r.retcode =	transport->send_pdu(conn,
 				(struct iscsi_hdr*)((char*)ev + sizeof(*ev)),
@@ -914,6 +1060,11 @@
 	case ISCSI_UEVENT_GET_STATS:
 		err = iscsi_if_get_stats(transport, nlh);
 		break;
+	case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
+	case ISCSI_UEVENT_TRANSPORT_EP_POLL:
+	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
+		err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type);
+		break;
 	default:
 		err = -EINVAL;
 		break;
@@ -923,9 +1074,11 @@
 	return err;
 }
 
-/* Get message from skb (based on rtnetlink_rcv_skb).  Each message is
- * processed by iscsi_if_recv_msg.  Malformed skbs with wrong length are
- * or invalid creds discarded silently.  */
+/*
+ * Get message from skb (based on rtnetlink_rcv_skb).  Each message is
+ * processed by iscsi_if_recv_msg.  Malformed skbs with wrong lengths or
+ * invalid creds are discarded silently.
+ */
 static void
 iscsi_if_rx(struct sock *sk, int len)
 {
@@ -937,7 +1090,6 @@
 			skb_pull(skb, skb->len);
 			goto free_skb;
 		}
-		daemon_pid = NETLINK_CREDS(skb)->pid;
 
 		while (skb->len >= NLMSG_SPACE(0)) {
 			int err;
@@ -988,6 +1140,10 @@
 #define iscsi_cdev_to_conn(_cdev) \
 	iscsi_dev_to_conn(_cdev->dev)
 
+#define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store)		\
+struct class_device_attribute class_device_attr_##_prefix##_##_name =	\
+	__ATTR(_name,_mode,_show,_store)
+
 /*
  * iSCSI connection attrs
  */
@@ -1005,7 +1161,8 @@
 
 #define iscsi_conn_int_attr(field, param, format)			\
 	iscsi_conn_int_attr_show(param, format)				\
-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_conn_int_param_##param, NULL);
+static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_int_param_##param, \
+			NULL);
 
 iscsi_conn_int_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH, "%u");
 iscsi_conn_int_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH, "%u");
@@ -1013,6 +1170,26 @@
 iscsi_conn_int_attr(data_digest, ISCSI_PARAM_DATADGST_EN, "%d");
 iscsi_conn_int_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN, "%d");
 iscsi_conn_int_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN, "%d");
+iscsi_conn_int_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT, "%d");
+iscsi_conn_int_attr(port, ISCSI_PARAM_CONN_PORT, "%d");
+iscsi_conn_int_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN, "%u");
+
+#define iscsi_conn_str_attr_show(param)					\
+static ssize_t								\
+show_conn_str_param_##param(struct class_device *cdev, char *buf)	\
+{									\
+	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
+	struct iscsi_transport *t = conn->transport;			\
+	return t->get_conn_str_param(conn, param, buf);			\
+}
+
+#define iscsi_conn_str_attr(field, param)				\
+	iscsi_conn_str_attr_show(param)					\
+static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_str_param_##param, \
+			NULL);
+
+iscsi_conn_str_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
+iscsi_conn_str_attr(address, ISCSI_PARAM_CONN_ADDRESS);
 
 #define iscsi_cdev_to_session(_cdev) \
 	iscsi_dev_to_session(_cdev->dev)
@@ -1034,7 +1211,8 @@
 
 #define iscsi_session_int_attr(field, param, format)			\
 	iscsi_session_int_attr_show(param, format)			\
-static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_int_param_##param, NULL);
+static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_int_param_##param, \
+			NULL);
 
 iscsi_session_int_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, "%d");
 iscsi_session_int_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, "%hu");
@@ -1044,18 +1222,89 @@
 iscsi_session_int_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, "%d");
 iscsi_session_int_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, "%d");
 iscsi_session_int_attr(erl, ISCSI_PARAM_ERL, "%d");
+iscsi_session_int_attr(tpgt, ISCSI_PARAM_TPGT, "%d");
 
-#define SETUP_SESSION_RD_ATTR(field, param)				\
-	if (priv->param_mask & (1 << param)) {				\
-		priv->session_attrs[count] = &class_device_attr_##field;\
-		count++;						\
-	}
+#define iscsi_session_str_attr_show(param)				\
+static ssize_t								\
+show_session_str_param_##param(struct class_device *cdev, char *buf)	\
+{									\
+	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+	struct iscsi_transport *t = session->transport;			\
+	return t->get_session_str_param(session, param, buf);		\
+}
 
-#define SETUP_CONN_RD_ATTR(field, param)				\
-	if (priv->param_mask & (1 << param)) {				\
-		priv->conn_attrs[count] = &class_device_attr_##field;	\
+#define iscsi_session_str_attr(field, param)				\
+	iscsi_session_str_attr_show(param)				\
+static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_str_param_##param, \
+			NULL);
+
+iscsi_session_str_attr(targetname, ISCSI_PARAM_TARGET_NAME);
+
+/*
+ * Private session and conn attrs. userspace uses several iscsi values
+ * to identify each session between reboots. Some of these values may not
+ * be present in the iscsi_transport/LLD driver becuase userspace handles
+ * login (and failback for login redirect) so for these type of drivers
+ * the class manages the attrs and values for the iscsi_transport/LLD
+ */
+#define iscsi_priv_session_attr_show(field, format)			\
+static ssize_t								\
+show_priv_session_##field(struct class_device *cdev, char *buf)	\
+{									\
+	struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \
+	return sprintf(buf, format"\n", session->field);		\
+}
+
+#define iscsi_priv_session_attr(field, format)				\
+	iscsi_priv_session_attr_show(field, format)			\
+static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO, show_priv_session_##field, \
+			NULL)
+iscsi_priv_session_attr(targetname, "%s");
+iscsi_priv_session_attr(tpgt, "%d");
+iscsi_priv_session_attr(recovery_tmo, "%d");
+
+#define iscsi_priv_conn_attr_show(field, format)			\
+static ssize_t								\
+show_priv_conn_##field(struct class_device *cdev, char *buf)		\
+{									\
+	struct iscsi_cls_conn *conn = iscsi_cdev_to_conn(cdev);		\
+	return sprintf(buf, format"\n", conn->field);			\
+}
+
+#define iscsi_priv_conn_attr(field, format)				\
+	iscsi_priv_conn_attr_show(field, format)			\
+static ISCSI_CLASS_ATTR(priv_conn, field, S_IRUGO, show_priv_conn_##field, \
+			NULL)
+iscsi_priv_conn_attr(persistent_address, "%s");
+iscsi_priv_conn_attr(persistent_port, "%d");
+
+#define SETUP_PRIV_SESSION_RD_ATTR(field)				\
+do {									\
+	priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \
+	count++;							\
+} while (0)
+
+#define SETUP_SESSION_RD_ATTR(field, param_flag)			\
+do {									\
+	if (tt->param_mask & param_flag) {				\
+		priv->session_attrs[count] = &class_device_attr_sess_##field; \
 		count++;						\
-	}
+	}								\
+} while (0)
+
+#define SETUP_PRIV_CONN_RD_ATTR(field)					\
+do {									\
+	priv->conn_attrs[count] = &class_device_attr_priv_conn_##field; \
+	count++;							\
+} while (0)
+
+#define SETUP_CONN_RD_ATTR(field, param_flag)				\
+do {									\
+	if (tt->param_mask & param_flag) {				\
+		priv->conn_attrs[count] = &class_device_attr_conn_##field; \
+		count++;						\
+	}								\
+} while (0)
 
 static int iscsi_session_match(struct attribute_container *cont,
 			   struct device *dev)
@@ -1104,6 +1353,24 @@
 	return &priv->conn_cont.ac == cont;
 }
 
+static int iscsi_host_match(struct attribute_container *cont,
+			    struct device *dev)
+{
+	struct Scsi_Host *shost;
+	struct iscsi_internal *priv;
+
+	if (!scsi_is_host_device(dev))
+		return 0;
+
+	shost = dev_to_shost(dev);
+	if (!shost->transportt  ||
+	    shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
+		return 0;
+
+        priv = to_iscsi_internal(shost->transportt);
+        return &priv->t.host_attrs.ac == cont;
+}
+
 struct scsi_transport_template *
 iscsi_register_transport(struct iscsi_transport *tt)
 {
@@ -1122,6 +1389,7 @@
 		return NULL;
 	INIT_LIST_HEAD(&priv->list);
 	priv->iscsi_transport = tt;
+	priv->t.user_scan = iscsi_user_scan;
 
 	priv->cdev.class = &iscsi_transport_class;
 	snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
@@ -1133,18 +1401,13 @@
 	if (err)
 		goto unregister_cdev;
 
-	/* setup parameters mask */
-	priv->param_mask = 0xFFFFFFFF;
-	if (!(tt->caps & CAP_MULTI_R2T))
-		priv->param_mask &= ~(1 << ISCSI_PARAM_MAX_R2T);
-	if (!(tt->caps & CAP_HDRDGST))
-		priv->param_mask &= ~(1 << ISCSI_PARAM_HDRDGST_EN);
-	if (!(tt->caps & CAP_DATADGST))
-		priv->param_mask &= ~(1 << ISCSI_PARAM_DATADGST_EN);
-	if (!(tt->caps & CAP_MARKERS)) {
-		priv->param_mask &= ~(1 << ISCSI_PARAM_IFMARKER_EN);
-		priv->param_mask &= ~(1 << ISCSI_PARAM_OFMARKER_EN);
-	}
+	/* host parameters */
+	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+	priv->t.host_attrs.ac.match = iscsi_host_match;
+	priv->t.host_size = sizeof(struct iscsi_host);
+	priv->host_attrs[0] = NULL;
+	transport_container_register(&priv->t.host_attrs);
 
 	/* connection parameters */
 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
@@ -1152,12 +1415,25 @@
 	priv->conn_cont.ac.match = iscsi_conn_match;
 	transport_container_register(&priv->conn_cont);
 
-	SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
-	SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
-	SETUP_CONN_RD_ATTR(header_digest, ISCSI_PARAM_HDRDGST_EN);
-	SETUP_CONN_RD_ATTR(data_digest, ISCSI_PARAM_DATADGST_EN);
-	SETUP_CONN_RD_ATTR(ifmarker, ISCSI_PARAM_IFMARKER_EN);
-	SETUP_CONN_RD_ATTR(ofmarker, ISCSI_PARAM_OFMARKER_EN);
+	SETUP_CONN_RD_ATTR(max_recv_dlength, ISCSI_MAX_RECV_DLENGTH);
+	SETUP_CONN_RD_ATTR(max_xmit_dlength, ISCSI_MAX_XMIT_DLENGTH);
+	SETUP_CONN_RD_ATTR(header_digest, ISCSI_HDRDGST_EN);
+	SETUP_CONN_RD_ATTR(data_digest, ISCSI_DATADGST_EN);
+	SETUP_CONN_RD_ATTR(ifmarker, ISCSI_IFMARKER_EN);
+	SETUP_CONN_RD_ATTR(ofmarker, ISCSI_OFMARKER_EN);
+	SETUP_CONN_RD_ATTR(address, ISCSI_CONN_ADDRESS);
+	SETUP_CONN_RD_ATTR(port, ISCSI_CONN_PORT);
+	SETUP_CONN_RD_ATTR(exp_statsn, ISCSI_EXP_STATSN);
+
+	if (tt->param_mask & ISCSI_PERSISTENT_ADDRESS)
+		SETUP_CONN_RD_ATTR(persistent_address, ISCSI_PERSISTENT_ADDRESS);
+	else
+		SETUP_PRIV_CONN_RD_ATTR(persistent_address);
+
+	if (tt->param_mask & ISCSI_PERSISTENT_PORT)
+		SETUP_CONN_RD_ATTR(persistent_port, ISCSI_PERSISTENT_PORT);
+	else
+		SETUP_PRIV_CONN_RD_ATTR(persistent_port);
 
 	BUG_ON(count > ISCSI_CONN_ATTRS);
 	priv->conn_attrs[count] = NULL;
@@ -1169,14 +1445,25 @@
 	priv->session_cont.ac.match = iscsi_session_match;
 	transport_container_register(&priv->session_cont);
 
-	SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN);
-	SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T);
-	SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_PARAM_IMM_DATA_EN);
-	SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_PARAM_FIRST_BURST);
-	SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_PARAM_MAX_BURST);
-	SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN);
-	SETUP_SESSION_RD_ATTR(data_seq_in_order,ISCSI_PARAM_DATASEQ_INORDER_EN)
-	SETUP_SESSION_RD_ATTR(erl, ISCSI_PARAM_ERL);
+	SETUP_SESSION_RD_ATTR(initial_r2t, ISCSI_INITIAL_R2T_EN);
+	SETUP_SESSION_RD_ATTR(max_outstanding_r2t, ISCSI_MAX_R2T);
+	SETUP_SESSION_RD_ATTR(immediate_data, ISCSI_IMM_DATA_EN);
+	SETUP_SESSION_RD_ATTR(first_burst_len, ISCSI_FIRST_BURST);
+	SETUP_SESSION_RD_ATTR(max_burst_len, ISCSI_MAX_BURST);
+	SETUP_SESSION_RD_ATTR(data_pdu_in_order, ISCSI_PDU_INORDER_EN);
+	SETUP_SESSION_RD_ATTR(data_seq_in_order, ISCSI_DATASEQ_INORDER_EN);
+	SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL);
+	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);
+
+	if (tt->param_mask & ISCSI_TARGET_NAME)
+		SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME);
+	else
+		SETUP_PRIV_SESSION_RD_ATTR(targetname);
+
+	if (tt->param_mask & ISCSI_TPGT)
+		SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT);
+	else
+		SETUP_PRIV_SESSION_RD_ATTR(tpgt);
 
 	BUG_ON(count > ISCSI_SESSION_ATTRS);
 	priv->session_attrs[count] = NULL;
@@ -1214,6 +1501,7 @@
 
 	transport_container_unregister(&priv->conn_cont);
 	transport_container_unregister(&priv->session_cont);
+	transport_container_unregister(&priv->t.host_attrs);
 
 	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
 	class_device_unregister(&priv->cdev);
@@ -1257,10 +1545,14 @@
 	if (err)
 		return err;
 
-	err = transport_class_register(&iscsi_connection_class);
+	err = transport_class_register(&iscsi_host_class);
 	if (err)
 		goto unregister_transport_class;
 
+	err = transport_class_register(&iscsi_connection_class);
+	if (err)
+		goto unregister_host_class;
+
 	err = transport_class_register(&iscsi_session_class);
 	if (err)
 		goto unregister_conn_class;
@@ -1288,6 +1580,8 @@
 	transport_class_unregister(&iscsi_session_class);
 unregister_conn_class:
 	transport_class_unregister(&iscsi_connection_class);
+unregister_host_class:
+	transport_class_unregister(&iscsi_host_class);
 unregister_transport_class:
 	class_unregister(&iscsi_transport_class);
 	return err;
@@ -1300,6 +1594,7 @@
 	netlink_unregister_notifier(&iscsi_nl_notifier);
 	transport_class_unregister(&iscsi_connection_class);
 	transport_class_unregister(&iscsi_session_class);
+	transport_class_unregister(&iscsi_host_class);
 	class_unregister(&iscsi_transport_class);
 }
 
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index f3b1606..1fe6b2d 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -65,7 +65,7 @@
 	ssize_t len = 0;					\
 	int i;							\
 								\
-	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {	\
+	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
 		if (table[i].value & table_key) {		\
 			len += sprintf(buf + len, "%s%s",	\
 				prefix, table[i].name);		\
@@ -83,7 +83,7 @@
 	ssize_t len = 0;					\
 	int i;							\
 								\
-	for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) {	\
+	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
 		if (table[i].value == table_key) {		\
 			len += sprintf(buf + len, "%s",		\
 				table[i].name);			\
@@ -748,6 +748,18 @@
 }
 
 /**
+ * sas_rphy_initialize - common rphy intialization
+ * @rphy:	rphy to initialise
+ *
+ * Used by both sas_end_device_alloc() and sas_expander_alloc() to
+ * initialise the common rphy component of each.
+ */
+static void sas_rphy_initialize(struct sas_rphy *rphy)
+{
+	INIT_LIST_HEAD(&rphy->list);
+}
+
+/**
  * sas_end_device_alloc - allocate an rphy for an end device
  *
  * Allocates an SAS remote PHY structure, connected to @parent.
@@ -771,6 +783,7 @@
 	sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d-%d",
 		shost->host_no, parent->port_identifier, parent->number);
 	rdev->rphy.identify.device_type = SAS_END_DEVICE;
+	sas_rphy_initialize(&rdev->rphy);
 	transport_setup_device(&rdev->rphy.dev);
 
 	return &rdev->rphy;
@@ -809,6 +822,7 @@
 	sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d",
 		shost->host_no, rdev->rphy.scsi_target_id);
 	rdev->rphy.identify.device_type = type;
+	sas_rphy_initialize(&rdev->rphy);
 	transport_setup_device(&rdev->rphy.dev);
 
 	return &rdev->rphy;
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 780aaed..ace49d5 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -146,7 +146,7 @@
 {
 	int i;
 
-	for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(signal_types); i++) {
 		if (type == signal_types[i].value)
 			return signal_types[i].name;
 	}
@@ -156,7 +156,7 @@
 {
 	int i, len;
 
-	for (i = 0; i < sizeof(signal_types)/sizeof(signal_types[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(signal_types); i++) {
 		len =  strlen(signal_types[i].name);
 		if (strncmp(name, signal_types[i].name, len) == 0 &&
 		    (name[len] == '\n' || name[len] == '\0'))
@@ -785,6 +785,7 @@
 {
 	struct spi_internal *i = to_spi_internal(sdev->host->transportt);
 	struct scsi_target *starget = sdev->sdev_target;
+	struct Scsi_Host *shost = sdev->host;
 	int len = sdev->inquiry_len;
 	/* first set us up for narrow async */
 	DV_SET(offset, 0);
@@ -844,6 +845,14 @@
 		if (spi_min_period(starget) == 8)
 			DV_SET(pcomp_en, 1);
 	}
+	/* now that we've done all this, actually check the bus
+	 * signal type (if known).  Some devices are stupid on
+	 * a SE bus and still claim they can try LVD only settings */
+	if (i->f->get_signalling)
+		i->f->get_signalling(shost);
+	if (spi_signalling(shost) == SPI_SIGNAL_SE ||
+	    spi_signalling(shost) == SPI_SIGNAL_HVD)
+		DV_SET(dt, 0);
 	/* Do the read only INQUIRY tests */
 	spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len,
 		       spi_dv_device_compare_inquiry);
diff --git a/drivers/scsi/scsi_typedefs.h b/drivers/scsi/scsi_typedefs.h
index 29f038b..2ed4c5c 100644
--- a/drivers/scsi/scsi_typedefs.h
+++ b/drivers/scsi/scsi_typedefs.h
@@ -1,3 +1,2 @@
 
 typedef struct scsi_cmnd Scsi_Cmnd;
-typedef struct scsi_request Scsi_Request;
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index c647d85..3541990 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -175,7 +175,7 @@
 		 * it's not worth the risk */
 		return -EINVAL;
 
-	for (i = 0; i < sizeof(sd_cache_types)/sizeof(sd_cache_types[0]); i++) {
+	for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) {
 		const int len = strlen(sd_cache_types[i]);
 		if (strncmp(sd_cache_types[i], buf, len) == 0 &&
 		    buf[len] == '\n') {
@@ -891,7 +891,7 @@
 static void sd_rw_intr(struct scsi_cmnd * SCpnt)
 {
 	int result = SCpnt->result;
-	int this_count = SCpnt->bufflen;
+	int this_count = SCpnt->request_bufflen;
 	int good_bytes = (result == 0 ? this_count : 0);
 	sector_t block_sectors = 1;
 	u64 first_err_block;
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 0ff83dd..7fa4da4 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -312,7 +312,7 @@
 	{"IBM F1 V1.2009/22/93", 5, 25, FD},
 };
 
-#define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
+#define NUM_SIGNATURES ARRAY_SIZE(signatures)
 #endif				/* n OVERRIDE */
 
 /*
@@ -457,7 +457,7 @@
  * space for the on-board RAM instead.
  */
 
-		for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i) {
+		for (i = 0; i < ARRAY_SIZE(seagate_bases); ++i) {
 			void __iomem *p = ioremap(seagate_bases[i], 0x2000);
 			if (!p)
 				continue;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b098942..98b9312b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -2635,8 +2635,7 @@
 sg_proc_init(void)
 {
 	int k, mask;
-	int num_leaves =
-	    sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]);
+	int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr);
 	struct proc_dir_entry *pdep;
 	struct sg_proc_leaf * leaf;
 
@@ -2661,8 +2660,7 @@
 sg_proc_cleanup(void)
 {
 	int k;
-	int num_leaves =
-	    sizeof (sg_proc_leaf_arr) / sizeof (sg_proc_leaf_arr[0]);
+	int num_leaves = ARRAY_SIZE(sg_proc_leaf_arr);
 
 	if (!sg_proc_sgp)
 		return;
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 7c80711..ebf6579 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -217,7 +217,7 @@
 static void rw_intr(struct scsi_cmnd * SCpnt)
 {
 	int result = SCpnt->result;
-	int this_count = SCpnt->bufflen;
+	int this_count = SCpnt->request_bufflen;
 	int good_bytes = (result == 0 ? this_count : 0);
 	int block_sectors = 0;
 	long error_sector;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 56cb490..b5218fc 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -1193,7 +1193,7 @@
 
 
 /* Flush the tape buffer before close */
-static int st_flush(struct file *filp)
+static int st_flush(struct file *filp, fl_owner_t id)
 {
 	int result = 0, result2;
 	unsigned char cmd[MAX_COMMAND_SIZE];
@@ -2818,7 +2818,7 @@
 		    (cmdstatp->sense_hdr.sense_key == NO_SENSE ||
 		     cmdstatp->sense_hdr.sense_key == RECOVERED_ERROR) &&
 		    undone == 0) {
-			ioctl_result = 0;	/* EOF written succesfully at EOM */
+			ioctl_result = 0;	/* EOF written successfully at EOM */
 			if (fileno >= 0)
 				fileno++;
 			STps->drv_file = fileno;
@@ -3839,7 +3839,7 @@
 					break;
 				}
 			}
-			if (i >= sizeof(parms) / sizeof(struct st_dev_parm))
+			if (i >= ARRAY_SIZE(parms))
 				 printk(KERN_WARNING "st: invalid parameter in '%s'\n",
 					stp);
 			stp = strchr(stp, ',');
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index cc990be..2e2c1eb 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -332,11 +332,11 @@
     struct scatterlist *sg = sp->SCp.buffer;
 
     while (sz >= 0) {
-	    sg[sz].dvma_address = dvma_map((unsigned long)page_address(sg[sz].page) +
+	    sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) +
 					   sg[sz].offset, sg[sz].length);
 	    sz--;
     }
-    sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address);
+    sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address);
 }
 
 static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
@@ -350,14 +350,14 @@
     struct scatterlist *sg = (struct scatterlist *)sp->buffer;
                         
     while(sz >= 0) {
-        dvma_unmap((char *)sg[sz].dvma_address);
+        dvma_unmap((char *)sg[sz].dma_address);
         sz--;
     }
 }
 
 static void dma_advance_sg (Scsi_Cmnd *sp)
 {
-    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
+    sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dma_address);
 }
 
 static int sun3x_esp_release(struct Scsi_Host *instance)
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 9c83b4d..ea82d3d 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -54,14 +54,8 @@
 #define NAME53C		"sym53c"
 #define NAME53C8XX	"sym53c8xx"
 
-/* SPARC just has to be different ... */
-#ifdef __sparc__
-#define IRQ_FMT "%s"
-#define IRQ_PRM(x) __irq_itoa(x)
-#else
 #define IRQ_FMT "%d"
 #define IRQ_PRM(x) (x)
-#endif
 
 struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
 unsigned int sym_debug_flags = 0;
@@ -156,7 +150,7 @@
 
 	switch(SYM_UCMD_PTR(cmd)->data_mapped) {
 	case 2:
-		pci_unmap_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
+		pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir);
 		break;
 	case 1:
 		pci_unmap_single(pdev, SYM_UCMD_PTR(cmd)->data_mapping,
@@ -186,7 +180,7 @@
 	int use_sg;
 	int dma_dir = cmd->sc_data_direction;
 
-	use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
+	use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir);
 	if (use_sg > 0) {
 		SYM_UCMD_PTR(cmd)->data_mapped  = 2;
 		SYM_UCMD_PTR(cmd)->data_mapping = use_sg;
@@ -376,7 +370,7 @@
 	if (!use_sg)
 		segment = sym_scatter_no_sglist(np, cp, cmd);
 	else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
-		struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+		struct scatterlist *scatter = (struct scatterlist *)cmd->request_buffer;
 		struct sym_tcb *tp = &np->target[cp->target];
 		struct sym_tblmove *data;
 
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index a671bdc..940fa1e 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -1276,8 +1276,7 @@
  FE_RAM|FE_IO256|FE_LEDC}
 };
 
-#define sym_num_devs \
-	(sizeof(sym_dev_table) / sizeof(sym_dev_table[0]))
+#define sym_num_devs (ARRAY_SIZE(sym_dev_table))
 
 /*
  *  Look up the chip table.
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index 21305fc..a24f661 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -126,15 +126,15 @@
 static struct override {
     unsigned long address;
     int irq;
-} overrides 
+} overrides
 #ifdef T128_OVERRIDE
     [] __initdata = T128_OVERRIDE;
 #else
-    [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, 
+    [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO},
         {0 ,IRQ_AUTO}, {0, IRQ_AUTO}};
 #endif
 
-#define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
+#define NO_OVERRIDES ARRAY_SIZE(overrides)
 
 static struct base {
     unsigned int address;
@@ -143,7 +143,7 @@
     { 0xcc000, 0}, { 0xc8000, 0}, { 0xdc000, 0}, { 0xd8000, 0}
 };
 
-#define NO_BASES (sizeof (bases) / sizeof (struct base))
+#define NO_BASES ARRAY_SIZE(bases)
 
 static struct signature {
     const char *string;
@@ -152,7 +152,7 @@
 {"TSROM: SCSI BIOS, Version 1.12", 0x36},
 };
 
-#define NO_SIGNATURES (sizeof (signatures) /  sizeof (struct signature))
+#define NO_SIGNATURES ARRAY_SIZE(signatures)
 
 /*
  * Function : t128_setup(char *str, int *ints)
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index d8a7260..27307fe 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -939,6 +939,7 @@
 		DB(DB_INTR, printk("%02x", cmd->SCp.Status))
 		    if (hostdata->level2 >= L2_BASIC) {
 			sr = read_wd33c93(regs, WD_SCSI_STATUS);	/* clear interrupt */
+			udelay(7);
 			hostdata->state = S_RUNNING_LEVEL2;
 			write_wd33c93(regs, WD_COMMAND_PHASE, 0x50);
 			write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
@@ -955,6 +956,7 @@
 
 		msg = read_1_byte(regs);
 		sr = read_wd33c93(regs, WD_SCSI_STATUS);	/* clear interrupt */
+		udelay(7);
 
 		hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
 		if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
@@ -1358,6 +1360,7 @@
 			} else {
 				/* Verify this is a change to MSG_IN and read the message */
 				sr = read_wd33c93(regs, WD_SCSI_STATUS);
+				udelay(7);
 				if (sr == (CSR_ABORT | PHS_MESS_IN) ||
 				    sr == (CSR_UNEXP | PHS_MESS_IN) ||
 				    sr == (CSR_SRV_REQ | PHS_MESS_IN)) {
@@ -1374,6 +1377,7 @@
 							     asr);
 					}
 					sr = read_wd33c93(regs, WD_SCSI_STATUS);
+					udelay(7);
 					if (sr != CSR_MSGIN)
 						printk
 						    ("wd33c93: Not paused with ACK on RESEL (%02x)\n",
@@ -1701,7 +1705,7 @@
 }
 
 #define MAX_WD33C93_HOSTS 4
-#define MAX_SETUP_ARGS ((int)(sizeof(setup_args) / sizeof(char *)))
+#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args)
 #define SETUP_BUFFER_SIZE 200
 static char setup_buffer[SETUP_BUFFER_SIZE];
 static char setup_used[MAX_SETUP_ARGS];
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index fb54a87..574955b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -267,7 +267,7 @@
 	0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000,
 	0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000
 };
-#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long))
+#define NUM_ADDRS ARRAY_SIZE(wd7000_biosaddr)
 
 static const unsigned short wd7000_iobase[] = {
 	0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338,
@@ -275,13 +275,13 @@
 	0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8,
 	0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8
 };
-#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short))
+#define NUM_IOPORTS ARRAY_SIZE(wd7000_iobase)
 
 static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 };
-#define NUM_IRQS (sizeof(wd7000_irq)/sizeof(short))
+#define NUM_IRQS ARRAY_SIZE(wd7000_irq)
 
 static const short wd7000_dma[] = { 5, 6, 7 };
-#define NUM_DMAS (sizeof(wd7000_dma)/sizeof(short))
+#define NUM_DMAS ARRAY_SIZE(wd7000_dma)
 
 /*
  * The following is set up by wd7000_detect, and used thereafter for
@@ -317,7 +317,7 @@
 	{7, 6, 0x350, BUS_ON, BUS_OFF},	/* My configuration (Zaga)     */
 	{-1, -1, 0x0, BUS_ON, BUS_OFF}	/* Empty slot                  */
 };
-#define NUM_CONFIGS (sizeof(configs)/sizeof(Config))
+#define NUM_CONFIGS ARRAY_SIZE(configs)
 
 /*
  *  The following list defines strings to look for in the BIOS that identify
@@ -333,7 +333,7 @@
 static const Signature signatures[] = {
 	{"SSTBIOS", 0x0000d, 7}	/* "SSTBIOS" @ offset 0x0000d */
 };
-#define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
+#define NUM_SIGNATURES ARRAY_SIZE(signatures)
 
 
 /*
@@ -1391,7 +1391,7 @@
  *
  */
 
-static int wd7000_detect(struct scsi_host_template *tpnt)
+static __init int wd7000_detect(struct scsi_host_template *tpnt)
 {
 	short present = 0, biosaddr_ptr, sig_ptr, i, pass;
 	short biosptr[NUM_CONFIGS];
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index b88a7c1..bff9454 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -131,17 +131,6 @@
 static int m68328_console_cbaud   = DEFAULT_CBAUD;
 
 
-/*
- * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */
-
 static inline int serial_paranoia_check(struct m68k_serial *info,
 					char *name, const char *routine)
 {
@@ -211,16 +200,16 @@
 	if (serial_paranoia_check(info, tty->name, "rs_stop"))
 		return;
 	
-	save_flags(flags); cli();
+	local_irq_save(flags);
 	uart->ustcnt &= ~USTCNT_TXEN;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static void rs_put_char(char ch)
 {
         int flags, loops = 0;
 
-        save_flags(flags); cli();
+        local_irq_save(flags);
 
 	while (!(UTX & UTX_TX_AVAIL) && (loops < 1000)) {
         	loops++;
@@ -229,7 +218,7 @@
 
 	UTX_TXDATA = ch;
         udelay(5);
-        restore_flags(flags);
+        local_irq_restore(flags);
 }
 
 static void rs_start(struct tty_struct *tty)
@@ -241,7 +230,7 @@
 	if (serial_paranoia_check(info, tty->name, "rs_start"))
 		return;
 	
-	save_flags(flags); cli();
+	local_irq_save(flags);
 	if (info->xmit_cnt && info->xmit_buf && !(uart->ustcnt & USTCNT_TXEN)) {
 #ifdef USE_INTS
 		uart->ustcnt |= USTCNT_TXEN | USTCNT_TX_INTR_MASK;
@@ -249,7 +238,7 @@
 		uart->ustcnt |= USTCNT_TXEN;
 #endif
 	}
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 /* Drop into either the boot monitor or kadb upon receiving a break
@@ -327,14 +316,6 @@
 		if(!tty)
 			goto clear_and_exit;
 		
-		/*
-		 * Make sure that we do not overflow the buffer
-		 */
-		if (tty_request_buffer_room(tty, 1) == 0) {
-			tty_schedule_flip(tty);
-			return;
-		}
-
 		flag = TTY_NORMAL;
 
 		if(rx & URX_PARITY_ERROR) {
@@ -473,7 +454,7 @@
 			return -ENOMEM;
 	}
 
-	save_flags(flags); cli();
+	local_irq_save(flags);
 
 	/*
 	 * Clear the FIFO buffers and disable them
@@ -506,7 +487,7 @@
 	change_speed(info);
 
 	info->flags |= S_INITIALIZED;
-	restore_flags(flags);
+	local_irq_restore(flags);
 	return 0;
 }
 
@@ -523,7 +504,7 @@
 	if (!(info->flags & S_INITIALIZED))
 		return;
 
-	save_flags(flags); cli(); /* Disable interrupts */
+	local_irq_save(flags);
 	
 	if (info->xmit_buf) {
 		free_page((unsigned long) info->xmit_buf);
@@ -534,7 +515,7 @@
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
 	
 	info->flags &= ~S_INITIALIZED;
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 struct {
@@ -655,24 +636,24 @@
 	if (info == 0) return;
 	if (info->xmit_buf == 0) return;
 
-	save_flags(flags);  cli();
+	local_irq_save(flags);
 	left = info->xmit_cnt;
 	while (left != 0) {
 		c = info->xmit_buf[info->xmit_tail];
 		info->xmit_tail = (info->xmit_tail+1) & (SERIAL_XMIT_SIZE-1);
 		info->xmit_cnt--;
-		restore_flags(flags);
+		local_irq_restore(flags);
 
 		rs_put_char(c);
 
-		save_flags(flags);  cli();
+		local_irq_save(flags);
 		left = min(info->xmit_cnt, left-1);
 	}
 
 	/* Last character is being transmitted now (hopefully). */
 	udelay(5);
 
-	restore_flags(flags);
+	local_irq_restore(flags);
 	return;
 }
 
@@ -720,11 +701,11 @@
 #endif
 
 	/* Enable transmitter */
-	save_flags(flags); cli();
+	local_irq_save(flags);
 
 	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
 			!info->xmit_buf) {
-		restore_flags(flags);
+		local_irq_restore(flags);
 		return;
 	}
 
@@ -749,7 +730,7 @@
 	while (!(uart->utx.w & UTX_TX_AVAIL)) udelay(5);
 	}
 #endif
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 extern void console_printn(const char * b, int count);
@@ -768,18 +749,22 @@
 	if (!tty || !info->xmit_buf)
 		return 0;
 
-	save_flags(flags);
+	local_save_flags(flags);
 	while (1) {
-		cli();		
+		local_irq_disable();		
 		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				   SERIAL_XMIT_SIZE - info->xmit_head));
+		local_irq_restore(flags);
+
 		if (c <= 0)
 			break;
 
 		memcpy(info->xmit_buf + info->xmit_head, buf, c);
+
+		local_irq_disable();
 		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
 		info->xmit_cnt += c;
-		restore_flags(flags);
+		local_irq_restore(flags);
 		buf += c;
 		count -= c;
 		total += c;
@@ -787,7 +772,7 @@
 
 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
 		/* Enable transmitter */
-		cli();		
+		local_irq_disable();		
 #ifndef USE_INTS
 		while(info->xmit_cnt) {
 #endif
@@ -807,9 +792,9 @@
 #ifndef USE_INTS
 		}
 #endif
-		restore_flags(flags);
+		local_irq_restore(flags);
 	}
-	restore_flags(flags);
+
 	return total;
 }
 
@@ -838,12 +823,13 @@
 static void rs_flush_buffer(struct tty_struct *tty)
 {
 	struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
+	unsigned long flags;
 				
 	if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
 		return;
-	cli();
+	local_irq_save(flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	sti();
+	local_irq_restore(flags);
 	tty_wakeup(tty);
 }
 
@@ -973,14 +959,15 @@
 	m68328_uart *uart = &uart_addr[info->line];
 #endif
 	unsigned char status;
+	unsigned long flags;
 
-	cli();
+	local_irq_save(flags);
 #ifdef CONFIG_SERIAL_68328_RTS_CTS
 	status = (uart->utx.w & UTX_CTS_STAT) ? 1 : 0;
 #else
 	status = 0;
 #endif
-	sti();
+	local_irq_restore(flags);
 	put_user(status,value);
 	return 0;
 }
@@ -994,14 +981,13 @@
         unsigned long flags;
         if (!info->port)
                 return;
-        save_flags(flags);
-        cli();
+        local_irq_save(flags);
 #ifdef USE_INTS	
 	uart->utx.w |= UTX_SEND_BREAK;
 	msleep_interruptible(duration);
 	uart->utx.w &= ~UTX_SEND_BREAK;
 #endif		
-        restore_flags(flags);
+        local_irq_restore(flags);
 }
 
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
@@ -1060,7 +1046,7 @@
 					       (struct serial_struct *) arg);
 		case TIOCSERGETLSR: /* Get line status register */
 			if (access_ok(VERIFY_WRITE, (void *) arg,
-						sizeof(unsigned int));
+						sizeof(unsigned int)))
 				return get_lsr_info(info, (unsigned int *) arg);
 			return -EFAULT;
 		case TIOCSERGSTRUCT:
@@ -1113,10 +1099,10 @@
 	if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
 		return;
 	
-	save_flags(flags); cli();
+	local_irq_save(flags);
 	
 	if (tty_hung_up_p(filp)) {
-		restore_flags(flags);
+		local_irq_restore(flags);
 		return;
 	}
 	
@@ -1138,7 +1124,7 @@
 		info->count = 0;
 	}
 	if (info->count) {
-		restore_flags(flags);
+		local_irq_restore(flags);
 		return;
 	}
 	info->flags |= S_CLOSING;
@@ -1186,7 +1172,7 @@
 	}
 	info->flags &= ~(S_NORMAL_ACTIVE|S_CLOSING);
 	wake_up_interruptible(&info->close_wait);
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 /*
@@ -1262,9 +1248,9 @@
 	info->count--;
 	info->blocked_open++;
 	while (1) {
-		cli();
+		local_irq_disable();
 		m68k_rtsdtr(info, 1);
-		sti();
+		local_irq_enable();
 		current->state = TASK_INTERRUPTIBLE;
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & S_INITIALIZED)) {
@@ -1444,7 +1430,7 @@
 		return -ENOMEM;
 	}
 
-	save_flags(flags); cli();
+	local_irq_save(flags);
 
 	for(i=0;i<NR_PORTS;i++) {
 
@@ -1489,7 +1475,7 @@
 		    serial_pm[i]->data = info;
 #endif
 	}
-	restore_flags(flags);
+	local_irq_restore(flags);
 	return 0;
 }
 
diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
index b79ed06..739bc84 100644
--- a/drivers/serial/8250_pnp.c
+++ b/drivers/serial/8250_pnp.c
@@ -323,8 +323,10 @@
 	{	"USR9180",		0	},
 	/* U.S. Robotics 56K Voice INT PnP*/
 	{	"USR9190",		0	},
-	/* HP Compaq Tablet PC tc1100 Wacom tablet */
+	/* Wacom tablets */
+	{	"WACF004",		0	},
 	{	"WACF005",		0	},
+	{       "WACF006",              0       },
 	/* Rockwell's (PORALiNK) 33600 INT PNP */
 	{	"WCI0003",		0	},
 	/* Unkown PnP modems */
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 7d22dc0..5b48ac2 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -300,21 +300,22 @@
 	  kernel at boot time.)
 
 config SERIAL_AT91
-	bool "AT91RM9200 serial port support"
-	depends on ARM && ARCH_AT91RM9200
+	bool "AT91RM9200 / AT91SAM9261 serial port support"
+	depends on ARM && (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
 	select SERIAL_CORE
 	help
-	  This enables the driver for the on-chip UARTs of the AT91RM9200
-	  processor.
+	  This enables the driver for the on-chip UARTs of the Atmel
+	  AT91RM9200 and AT91SAM926 processor.
 
 config SERIAL_AT91_CONSOLE
-	bool "Support for console on AT91RM9200 serial port"
+	bool "Support for console on AT91RM9200 / AT91SAM9261 serial port"
 	depends on SERIAL_AT91=y
 	select SERIAL_CORE_CONSOLE
 	help
-	  Say Y here if you wish to use a UART on the AT91RM9200 as the system
-	  console (the system console is the device which receives all kernel
-	  messages and warnings and which allows logins in single user mode).
+	  Say Y here if you wish to use a UART on the Atmel AT91RM9200 or
+	  AT91SAM9261 as the system console (the system console is the device
+	  which receives all kernel messages and warnings and which allows
+	  logins in single user mode).
 
 config SERIAL_AT91_TTYAT
 	bool "Install as device ttyAT0-4 instead of ttyS0-4"
@@ -353,21 +354,24 @@
 	  kernel at boot time.)
 
 config SERIAL_S3C2410
-	tristate "Samsung S3C2410 Serial port support"
+	tristate "Samsung S3C2410/S3C2440/S3C2442/S3C2412 Serial port support"
 	depends on ARM && ARCH_S3C2410
 	select SERIAL_CORE
 	help
-	  Support for the on-chip UARTs on the Samsung S3C2410X CPU,
+	  Support for the on-chip UARTs on the Samsung S3C24XX series CPUs,
 	  providing /dev/ttySAC0, 1 and 2 (note, some machines may not
 	  provide all of these ports, depending on how the serial port
 	  pins are configured.
 
+	  Currently this driver supports the UARTS on the S3C2410, S3C2440,
+	  S3C2442, S3C2412 and S3C2413 CPUs.
+
 config SERIAL_S3C2410_CONSOLE
 	bool "Support for console on S3C2410 serial port"
 	depends on SERIAL_S3C2410=y
 	select SERIAL_CORE_CONSOLE
 	help
-	  Allow selection of the S3C2410 on-board serial ports for use as
+	  Allow selection of the S3C24XX on-board serial ports for use as
 	  an virtual console.
 
 	  Even if you say Y here, the currently visible virtual console
@@ -936,4 +940,23 @@
 	  If you have an SGI Altix with an IOC3 serial card,
 	  say Y or M.  Otherwise, say N.
 
+config SERIAL_NETX
+	bool "NetX serial port support"
+	depends on ARM && ARCH_NETX
+	select SERIAL_CORE
+	help
+	  If you have a machine based on a Hilscher NetX SoC you
+	  can enable its onboard serial port by enabling this option.
+
+          To compile this driver as a module, choose M here: the
+          module will be called netx-serial.
+
+config SERIAL_NETX_CONSOLE
+	bool "Console on NetX serial port"
+	depends on SERIAL_NETX
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you have enabled the serial port on the Motorola IMX
+	  CPU you can make it the console by answering Y to this option.
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 0a71bf6..927faee 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -55,3 +55,4 @@
 obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
 obj-$(CONFIG_SERIAL_SGI_IOC3) += ioc3_serial.o
 obj-$(CONFIG_SERIAL_AT91) += at91_serial.o
+obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 1631414..e920d19 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -52,7 +52,7 @@
 
 #include <asm/io.h>
 
-#define UART_NR		2
+#define UART_NR		8
 
 #define SERIAL_AMBA_MAJOR	204
 #define SERIAL_AMBA_MINOR	16
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c
index 6547fe0..db5b25f 100644
--- a/drivers/serial/at91_serial.c
+++ b/drivers/serial/at91_serial.c
@@ -2,7 +2,6 @@
  *  linux/drivers/char/at91_serial.c
  *
  *  Driver for Atmel AT91RM9200 Serial ports
- *
  *  Copyright (C) 2003 Rick Bronson
  *
  *  Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd.
@@ -30,17 +29,19 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/serial.h>
+#include <linux/clk.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/tty_flip.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 
 #include <asm/arch/at91rm9200_usart.h>
-#include <asm/mach/serial_at91rm9200.h>
+#include <asm/arch/at91rm9200_pdc.h>
+#include <asm/mach/serial_at91.h>
 #include <asm/arch/board.h>
-#include <asm/arch/pio.h>
-
+#include <asm/arch/system.h>
 
 #if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -67,7 +68,6 @@
 
 #endif
 
-#define AT91_VA_BASE_DBGU	((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU)
 #define AT91_ISR_PASS_LIMIT	256
 
 #define UART_PUT_CR(port,v)	writel(v, (port)->membase + AT91_US_CR)
@@ -87,16 +87,33 @@
 
  /* PDC registers */
 #define UART_PUT_PTCR(port,v)	writel(v, (port)->membase + AT91_PDC_PTCR)
+#define UART_GET_PTSR(port)	readl((port)->membase + AT91_PDC_PTSR)
+
 #define UART_PUT_RPR(port,v)	writel(v, (port)->membase + AT91_PDC_RPR)
+#define UART_GET_RPR(port)	readl((port)->membase + AT91_PDC_RPR)
 #define UART_PUT_RCR(port,v)	writel(v, (port)->membase + AT91_PDC_RCR)
-#define UART_GET_RCR(port)	readl((port)->membase + AT91_PDC_RCR)
 #define UART_PUT_RNPR(port,v)	writel(v, (port)->membase + AT91_PDC_RNPR)
 #define UART_PUT_RNCR(port,v)	writel(v, (port)->membase + AT91_PDC_RNCR)
 
+#define UART_PUT_TPR(port,v)	writel(v, (port)->membase + AT91_PDC_TPR)
+#define UART_PUT_TCR(port,v)	writel(v, (port)->membase + AT91_PDC_TCR)
+//#define UART_PUT_TNPR(port,v)	writel(v, (port)->membase + AT91_PDC_TNPR)
+//#define UART_PUT_TNCR(port,v)	writel(v, (port)->membase + AT91_PDC_TNCR)
 
 static int (*at91_open)(struct uart_port *);
 static void (*at91_close)(struct uart_port *);
 
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct at91_uart_port {
+	struct uart_port	uart;		/* uart */
+	struct clk		*clk;		/* uart clock */
+	unsigned short		suspended;	/* is port suspended? */
+};
+
+static struct at91_uart_port at91_ports[AT91_NR_UART];
+
 #ifdef SUPPORT_SYSRQ
 static struct console at91_console;
 #endif
@@ -115,16 +132,19 @@
 static void at91_set_mctrl(struct uart_port *port, u_int mctrl)
 {
 	unsigned int control = 0;
+	unsigned int mode;
 
-	/*
-	 * Errata #39: RTS0 is not internally connected to PA21.  We need to drive
-	 *  the pin manually.
-	 */
-	if (port->mapbase == AT91_VA_BASE_US0) {
-		if (mctrl & TIOCM_RTS)
-			at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0);
-		else
-			at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
+	if (arch_identify() == ARCH_ID_AT91RM9200) {
+		/*
+		 * AT91RM9200 Errata #39: RTS0 is not internally connected to PA21.
+		 *  We need to drive the pin manually.
+		 */
+		if (port->mapbase == AT91_BASE_US0) {
+			if (mctrl & TIOCM_RTS)
+				at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0);
+			else
+				at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
+		}
 	}
 
 	if (mctrl & TIOCM_RTS)
@@ -137,7 +157,15 @@
 	else
 		control |= AT91_US_DTRDIS;
 
-	UART_PUT_CR(port,control);
+	UART_PUT_CR(port, control);
+
+	/* Local loopback mode? */
+	mode = UART_GET_MR(port) & ~AT91_US_CHMODE;
+	if (mctrl & TIOCM_LOOP)
+		mode |= AT91_US_CHMODE_LOC_LOOP;
+	else
+		mode |= AT91_US_CHMODE_NORMAL;
+	UART_PUT_MR(port, mode);
 }
 
 /*
@@ -169,8 +197,9 @@
  */
 static void at91_stop_tx(struct uart_port *port)
 {
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
 	UART_PUT_IDR(port, AT91_US_TXRDY);
-	port->read_status_mask &= ~AT91_US_TXRDY;
 }
 
 /*
@@ -178,7 +207,8 @@
  */
 static void at91_start_tx(struct uart_port *port)
 {
-	port->read_status_mask |= AT91_US_TXRDY;
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
 	UART_PUT_IER(port, AT91_US_TXRDY);
 }
 
@@ -187,6 +217,8 @@
  */
 static void at91_stop_rx(struct uart_port *port)
 {
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
 	UART_PUT_IDR(port, AT91_US_RXRDY);
 }
 
@@ -195,7 +227,6 @@
  */
 static void at91_enable_ms(struct uart_port *port)
 {
-	port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
 	UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC);
 }
 
@@ -218,8 +249,8 @@
 	struct tty_struct *tty = port->info->tty;
 	unsigned int status, ch, flg;
 
-	status = UART_GET_CSR(port) & port->read_status_mask;
-	while (status & (AT91_US_RXRDY)) {
+	status = UART_GET_CSR(port);
+	while (status & AT91_US_RXRDY) {
 		ch = UART_GET_CHAR(port);
 
 		port->icount.rx++;
@@ -230,40 +261,38 @@
 		 * note that the error handling code is
 		 * out of the main execution path
 		 */
-		if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) {
+		if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE | AT91_US_RXBRK))) {
 			UART_PUT_CR(port, AT91_US_RSTSTA);	/* clear error */
-			if (status & (AT91_US_PARE))
+			if (status & AT91_US_RXBRK) {
+				status &= ~(AT91_US_PARE | AT91_US_FRAME);	/* ignore side-effect */
+				port->icount.brk++;
+				if (uart_handle_break(port))
+					goto ignore_char;
+			}
+			if (status & AT91_US_PARE)
 				port->icount.parity++;
-			if (status & (AT91_US_FRAME))
+			if (status & AT91_US_FRAME)
 				port->icount.frame++;
-			if (status & (AT91_US_OVRE))
+			if (status & AT91_US_OVRE)
 				port->icount.overrun++;
 
-			if (status & AT91_US_PARE)
+			status &= port->read_status_mask;
+
+			if (status & AT91_US_RXBRK)
+				flg = TTY_BREAK;
+			else if (status & AT91_US_PARE)
 				flg = TTY_PARITY;
 			else if (status & AT91_US_FRAME)
 				flg = TTY_FRAME;
-			if (status & AT91_US_OVRE) {
-				/*
-				 * overrun does *not* affect the character
-				 * we read from the FIFO
-				 */
-				tty_insert_flip_char(tty, ch, flg);
-				ch = 0;
-				flg = TTY_OVERRUN;
-			}
-#ifdef SUPPORT_SYSRQ
-			port->sysrq = 0;
-#endif
 		}
 
 		if (uart_handle_sysrq_char(port, ch, regs))
 			goto ignore_char;
 
-		tty_insert_flip_char(tty, ch, flg);
+		uart_insert_char(port, status, AT91_US_OVRE, ch, flg);
 
 	ignore_char:
-		status = UART_GET_CSR(port) & port->read_status_mask;
+		status = UART_GET_CSR(port);
 	}
 
 	tty_flip_buffer_push(tty);
@@ -308,40 +337,35 @@
 static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct uart_port *port = dev_id;
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
 	unsigned int status, pending, pass_counter = 0;
 
 	status = UART_GET_CSR(port);
-	pending = status & port->read_status_mask;
-	if (pending) {
-		do {
-			if (pending & AT91_US_RXRDY)
-				at91_rx_chars(port, regs);
+	pending = status & UART_GET_IMR(port);
+	while (pending) {
+		/* Interrupt receive */
+		if (pending & AT91_US_RXRDY)
+			at91_rx_chars(port, regs);
 
-			/* Clear the relevent break bits */
-			if (pending & AT91_US_RXBRK) {
-				UART_PUT_CR(port, AT91_US_RSTSTA);
-				port->icount.brk++;
-				uart_handle_break(port);
-			}
+		// TODO: All reads to CSR will clear these interrupts!
+		if (pending & AT91_US_RIIC) port->icount.rng++;
+		if (pending & AT91_US_DSRIC) port->icount.dsr++;
+		if (pending & AT91_US_DCDIC)
+			uart_handle_dcd_change(port, !(status & AT91_US_DCD));
+		if (pending & AT91_US_CTSIC)
+			uart_handle_cts_change(port, !(status & AT91_US_CTS));
+		if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC))
+			wake_up_interruptible(&port->info->delta_msr_wait);
 
-			// TODO: All reads to CSR will clear these interrupts!
-			if (pending & AT91_US_RIIC) port->icount.rng++;
-			if (pending & AT91_US_DSRIC) port->icount.dsr++;
-			if (pending & AT91_US_DCDIC)
-				uart_handle_dcd_change(port, !(status & AT91_US_DCD));
-			if (pending & AT91_US_CTSIC)
-				uart_handle_cts_change(port, !(status & AT91_US_CTS));
-			if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC))
-				wake_up_interruptible(&port->info->delta_msr_wait);
+		/* Interrupt transmit */
+		if (pending & AT91_US_TXRDY)
+			at91_tx_chars(port);
 
-			if (pending & AT91_US_TXRDY)
-				at91_tx_chars(port);
-			if (pass_counter++ > AT91_ISR_PASS_LIMIT)
-				break;
+		if (pass_counter++ > AT91_ISR_PASS_LIMIT)
+			break;
 
-			status = UART_GET_CSR(port);
-			pending = status & port->read_status_mask;
-		} while (pending);
+		status = UART_GET_CSR(port);
+		pending = status & UART_GET_IMR(port);
 	}
 	return IRQ_HANDLED;
 }
@@ -351,6 +375,7 @@
  */
 static int at91_startup(struct uart_port *port)
 {
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
 	int retval;
 
 	/*
@@ -381,14 +406,14 @@
 		}
 	}
 
-	port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE
-			| AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK;
 	/*
 	 * Finally, enable the serial port
 	 */
 	UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
 	UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN);		/* enable xmit & rcvr */
-	UART_PUT_IER(port, AT91_US_RXRDY);			/* do receive only */
+
+	UART_PUT_IER(port, AT91_US_RXRDY);		/* enable receive only */
+
 	return 0;
 }
 
@@ -397,6 +422,8 @@
  */
 static void at91_shutdown(struct uart_port *port)
 {
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
 	/*
 	 * Disable all interrupts, port and break condition.
 	 */
@@ -421,21 +448,22 @@
  */
 static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
 {
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
 	switch (state) {
 		case 0:
 			/*
 			 * Enable the peripheral clock for this serial port.
 			 * This is called on uart_open() or a resume event.
 			 */
-			at91_sys_write(AT91_PMC_PCER, 1 << port->irq);
+			clk_enable(at91_port->clk);
 			break;
 		case 3:
 			/*
 			 * Disable the peripheral clock for this serial port.
 			 * This is called on uart_close() or a suspend event.
 			 */
-			if (port->irq != AT91_ID_SYS)			/* is this a shared clock? */
-				at91_sys_write(AT91_PMC_PCDR, 1 << port->irq);
+			clk_disable(at91_port->clk);
 			break;
 		default:
 			printk(KERN_ERR "at91_serial: unknown pm %d\n", state);
@@ -494,9 +522,9 @@
 
 	spin_lock_irqsave(&port->lock, flags);
 
-	port->read_status_mask |= AT91_US_OVRE;
+	port->read_status_mask = AT91_US_OVRE;
 	if (termios->c_iflag & INPCK)
-		port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE;
+		port->read_status_mask |= (AT91_US_FRAME | AT91_US_PARE);
 	if (termios->c_iflag & (BRKINT | PARMRK))
 		port->read_status_mask |= AT91_US_RXBRK;
 
@@ -552,7 +580,7 @@
  */
 static const char *at91_type(struct uart_port *port)
 {
-	return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL;
+	return (port->type == PORT_AT91) ? "AT91_SERIAL" : NULL;
 }
 
 /*
@@ -560,8 +588,15 @@
  */
 static void at91_release_port(struct uart_port *port)
 {
-	release_mem_region(port->mapbase,
-		(port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K);
+	struct platform_device *pdev = to_platform_device(port->dev);
+	int size = pdev->resource[0].end - pdev->resource[0].start + 1;
+
+	release_mem_region(port->mapbase, size);
+
+	if (port->flags & UPF_IOREMAP) {
+		iounmap(port->membase);
+		port->membase = NULL;
+	}
 }
 
 /*
@@ -569,10 +604,21 @@
  */
 static int at91_request_port(struct uart_port *port)
 {
-	return request_mem_region(port->mapbase,
-		(port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K,
-		"at91_serial") != NULL ? 0 : -EBUSY;
+	struct platform_device *pdev = to_platform_device(port->dev);
+	int size = pdev->resource[0].end - pdev->resource[0].start + 1;
 
+	if (!request_mem_region(port->mapbase, size, "at91_serial"))
+		return -EBUSY;
+
+	if (port->flags & UPF_IOREMAP) {
+		port->membase = ioremap(port->mapbase, size);
+		if (port->membase == NULL) {
+			release_mem_region(port->mapbase, size);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
 }
 
 /*
@@ -581,7 +627,7 @@
 static void at91_config_port(struct uart_port *port, int flags)
 {
 	if (flags & UART_CONFIG_TYPE) {
-		port->type = PORT_AT91RM9200;
+		port->type = PORT_AT91;
 		at91_request_port(port);
 	}
 }
@@ -592,7 +638,7 @@
 static int at91_verify_port(struct uart_port *port, struct serial_struct *ser)
 {
 	int ret = 0;
-	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200)
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91)
 		ret = -EINVAL;
 	if (port->irq != ser->irq)
 		ret = -EINVAL;
@@ -624,33 +670,47 @@
 	.type		= at91_type,
 	.release_port	= at91_release_port,
 	.request_port	= at91_request_port,
-	.config_port 	= at91_config_port,
-	.verify_port 	= at91_verify_port,
+	.config_port	= at91_config_port,
+	.verify_port	= at91_verify_port,
 	.pm		= at91_serial_pm,
 };
 
-static struct uart_port at91_ports[AT91_NR_UART];
-
-void __init at91_init_ports(void)
+/*
+ * Configure the port from the platform device resource info.
+ */
+static void __devinit at91_init_port(struct at91_uart_port *at91_port, struct platform_device *pdev)
 {
-	static int first = 1;
-	int i;
+	struct uart_port *port = &at91_port->uart;
+	struct at91_uart_data *data = pdev->dev.platform_data;
 
-	if (!first)
-		return;
-	first = 0;
+	port->iotype	= UPIO_MEM;
+	port->flags     = UPF_BOOT_AUTOCONF;
+	port->ops	= &at91_pops;
+	port->fifosize  = 1;
+	port->line	= pdev->id;
+	port->dev	= &pdev->dev;
 
-	for (i = 0; i < AT91_NR_UART; i++) {
-		at91_ports[i].iotype	= UPIO_MEM;
-		at91_ports[i].flags     = UPF_BOOT_AUTOCONF;
-		at91_ports[i].uartclk   = at91_master_clock;
-		at91_ports[i].ops	= &at91_pops;
-		at91_ports[i].fifosize  = 1;
-		at91_ports[i].line	= i;
- 	}
+	port->mapbase	= pdev->resource[0].start;
+	port->irq	= pdev->resource[1].start;
+
+	if (port->mapbase == AT91_VA_BASE_SYS + AT91_DBGU)		/* Part of system perpherals - already mapped */
+		port->membase = (void __iomem *) port->mapbase;
+	else {
+		port->flags	|= UPF_IOREMAP;
+		port->membase	= NULL;
+	}
+
+	if (!at91_port->clk) {		/* for console, the clock could already be configured */
+		at91_port->clk = clk_get(&pdev->dev, "usart");
+		clk_enable(at91_port->clk);
+		port->uartclk = clk_get_rate(at91_port->clk);
+	}
 }
 
-void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns)
+/*
+ * Register board-specific modem-control line handlers.
+ */
+void __init at91_register_uart_fns(struct at91_port_fns *fns)
 {
 	if (fns->enable_ms)
 		at91_pops.enable_ms = fns->enable_ms;
@@ -664,51 +724,6 @@
 	at91_pops.set_wake = fns->set_wake;
 }
 
-/*
- * Setup ports.
- */
-void __init at91_register_uart(int idx, int port)
-{
-	if ((idx < 0) || (idx >= AT91_NR_UART)) {
-		printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx);
-		return;
-	}
-
-	switch (port) {
-	case 0:
-		at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0;
-		at91_ports[idx].mapbase = AT91_VA_BASE_US0;
-		at91_ports[idx].irq     = AT91_ID_US0;
-		AT91_CfgPIO_USART0();
-		break;
-	case 1:
-		at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1;
-		at91_ports[idx].mapbase = AT91_VA_BASE_US1;
-		at91_ports[idx].irq     = AT91_ID_US1;
-		AT91_CfgPIO_USART1();
-		break;
-	case 2:
-		at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2;
-		at91_ports[idx].mapbase = AT91_VA_BASE_US2;
-		at91_ports[idx].irq     = AT91_ID_US2;
-		AT91_CfgPIO_USART2();
-		break;
-	case 3:
-		at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3;
-		at91_ports[idx].mapbase = AT91_VA_BASE_US3;
-		at91_ports[idx].irq     = AT91_ID_US3;
-		AT91_CfgPIO_USART3();
-		break;
-	case 4:
-		at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU;
-		at91_ports[idx].mapbase = AT91_VA_BASE_DBGU;
-		at91_ports[idx].irq     = AT91_ID_SYS;
-		AT91_CfgPIO_DBGU();
-		break;
-	default:
-		printk(KERN_ERR  "%s : bad port number %d\n", __FUNCTION__, port);
-	}
-}
 
 #ifdef CONFIG_SERIAL_AT91_CONSOLE
 static void at91_console_putchar(struct uart_port *port, int ch)
@@ -723,7 +738,7 @@
  */
 static void at91_console_write(struct console *co, const char *s, u_int count)
 {
-	struct uart_port *port = at91_ports + co->index;
+	struct uart_port *port = &at91_ports[co->index].uart;
 	unsigned int status, imr;
 
 	/*
@@ -778,23 +793,15 @@
 
 static int __init at91_console_setup(struct console *co, char *options)
 {
-	struct uart_port *port;
+	struct uart_port *port = &at91_ports[co->index].uart;
 	int baud = 115200;
 	int bits = 8;
 	int parity = 'n';
 	int flow = 'n';
 
-	/*
-	 * Check whether an invalid uart number has been specified, and
-	 * if so, search for the first available port that does have
-	 * console support.
-	 */
-	port = uart_get_console(at91_ports, AT91_NR_UART, co);
+	if (port->membase == 0)		/* Port not initialized yet - delay setup */
+		return -ENODEV;
 
-	/*
-	 * Enable the serial console, in-case bootloader did not do it.
-	 */
-	at91_sys_write(AT91_PMC_PCER, 1 << port->irq);	/* enable clock */
 	UART_PUT_IDR(port, -1);				/* disable interrupts */
 	UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX);
 	UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN);
@@ -821,23 +828,40 @@
 
 #define AT91_CONSOLE_DEVICE	&at91_console
 
-static int  __init at91_console_init(void)
+/*
+ * Early console initialization (before VM subsystem initialized).
+ */
+static int __init at91_console_init(void)
 {
-	at91_init_ports();
+	if (at91_default_console_device) {
+		add_preferred_console(AT91_DEVICENAME, at91_default_console_device->id, NULL);
+		at91_init_port(&(at91_ports[at91_default_console_device->id]), at91_default_console_device);
+		register_console(&at91_console);
+	}
 
-	at91_console.index = at91_console_port;
-	register_console(&at91_console);
 	return 0;
 }
 console_initcall(at91_console_init);
 
+/*
+ * Late console initialization.
+ */
+static int __init at91_late_console_init(void)
+{
+	if (at91_default_console_device && !(at91_console.flags & CON_ENABLED))
+		register_console(&at91_console);
+
+	return 0;
+}
+core_initcall(at91_late_console_init);
+
 #else
 #define AT91_CONSOLE_DEVICE	NULL
 #endif
 
 static struct uart_driver at91_uart = {
 	.owner			= THIS_MODULE,
-	.driver_name		= AT91_DEVICENAME,
+	.driver_name		= "at91_serial",
 	.dev_name		= AT91_DEVICENAME,
 	.devfs_name		= AT91_DEVICENAME,
 	.major			= SERIAL_AT91_MAJOR,
@@ -846,33 +870,106 @@
 	.cons			= AT91_CONSOLE_DEVICE,
 };
 
-static int __init at91_serial_init(void)
+#ifdef CONFIG_PM
+static int at91_serial_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	int ret, i;
+	struct uart_port *port = platform_get_drvdata(pdev);
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
 
-	at91_init_ports();
-
-	ret = uart_register_driver(&at91_uart);
-	if (ret)
-		return ret;
-
-	for (i = 0; i < AT91_NR_UART; i++) {
-		if (at91_serial_map[i] >= 0)
-			uart_add_one_port(&at91_uart, &at91_ports[i]);
+	if (device_may_wakeup(&pdev->dev) && !at91_suspend_entering_slow_clock())
+		enable_irq_wake(port->irq);
+	else {
+		disable_irq_wake(port->irq);
+		uart_suspend_port(&at91_uart, port);
+		at91_port->suspended = 1;
 	}
 
 	return 0;
 }
 
+static int at91_serial_resume(struct platform_device *pdev)
+{
+	struct uart_port *port = platform_get_drvdata(pdev);
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+
+	if (at91_port->suspended) {
+		uart_resume_port(&at91_uart, port);
+		at91_port->suspended = 0;
+	}
+
+	return 0;
+}
+#else
+#define at91_serial_suspend NULL
+#define at91_serial_resume NULL
+#endif
+
+static int __devinit at91_serial_probe(struct platform_device *pdev)
+{
+	struct at91_uart_port *port;
+	int ret;
+
+	port = &at91_ports[pdev->id];
+	at91_init_port(port, pdev);
+
+	ret = uart_add_one_port(&at91_uart, &port->uart);
+	if (!ret) {
+		device_init_wakeup(&pdev->dev, 1);
+		platform_set_drvdata(pdev, port);
+	}
+
+	return ret;
+}
+
+static int __devexit at91_serial_remove(struct platform_device *pdev)
+{
+	struct uart_port *port = platform_get_drvdata(pdev);
+	struct at91_uart_port *at91_port = (struct at91_uart_port *) port;
+	int ret = 0;
+
+	clk_disable(at91_port->clk);
+	clk_put(at91_port->clk);
+
+	device_init_wakeup(&pdev->dev, 0);
+	platform_set_drvdata(pdev, NULL);
+
+	if (port) {
+		ret = uart_remove_one_port(&at91_uart, port);
+		kfree(port);
+	}
+
+	return ret;
+}
+
+static struct platform_driver at91_serial_driver = {
+	.probe		= at91_serial_probe,
+	.remove		= __devexit_p(at91_serial_remove),
+	.suspend	= at91_serial_suspend,
+	.resume		= at91_serial_resume,
+	.driver		= {
+		.name	= "at91_usart",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init at91_serial_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&at91_uart);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&at91_serial_driver);
+	if (ret)
+		uart_unregister_driver(&at91_uart);
+
+	return ret;
+}
+
 static void __exit at91_serial_exit(void)
 {
-	int i;
-
-	for (i = 0; i < AT91_NR_UART; i++) {
- 		if (at91_serial_map[i] >= 0)
-			uart_remove_one_port(&at91_uart, &at91_ports[i]);
-  	}
-
+	platform_driver_unregister(&at91_serial_driver);
 	uart_unregister_driver(&at91_uart);
 }
 
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 8970014..5cacc5e 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -2573,12 +2573,6 @@
 
 	DFLIP(
 	  if (1) {
-
-		  if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
-			  DEBUG_LOG(info->line, "*** TTY_DONT_FLIP set flip.count %i ***\n", tty->flip.count);
-			  DEBUG_LOG(info->line, "*** recv_cnt %i\n", info->recv_cnt);
-		  } else {
-		  }
 		  DEBUG_LOG(info->line, "*** rxtot %i\n", info->icount.rx);
 		  DEBUG_LOG(info->line, "ldisc %lu\n", tty->ldisc.chars_in_buffer(tty));
 		  DEBUG_LOG(info->line, "room  %lu\n", tty->ldisc.receive_room(tty));
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index c620209..717e47b 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -2646,7 +2646,10 @@
 	struct ioc4_port *port;
 	struct ioc4_soft *soft;
 
+	/* If serial driver did not attach, don't try to detach */
 	control = idd->idd_serial_data;
+	if (!control)
+		return 0;
 
 	for (port_num = 0; port_num < IOC4_NUM_SERIAL_PORTS; port_num++) {
 		for (port_type = UART_PORT_MIN;
@@ -2778,6 +2781,12 @@
 	DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev,
 							idd->idd_pci_id));
 
+	/* PCI-RT does not bring out serial connections.
+	 * Do not attach to this particular IOC4.
+	 */
+	if (idd->idd_variant == IOC4_VARIANT_PCI_RT)
+		return 0;
+
 	/* request serial registers */
 	tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
 
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c
index 7d82370..f8262e6 100644
--- a/drivers/serial/jsm/jsm_tty.c
+++ b/drivers/serial/jsm/jsm_tty.c
@@ -589,13 +589,6 @@
 	ld = tty_ldisc_ref(tp);
 
 	/*
-	 * If the DONT_FLIP flag is on, don't flush our buffer, and act
-	 * like the ld doesn't have any space to put the data right now.
-	 */
-	if (test_bit(TTY_DONT_FLIP, &tp->flags))
-		len = 0;
-
-	/*
 	 * If we were unable to get a reference to the ld,
 	 * don't flush our buffer, and act like the ld doesn't
 	 * have any space to put the data right now.
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 8cbbb95..8ad2429 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -60,11 +60,11 @@
 #if defined(CONFIG_HW_FEITH)
 #define	CONSOLE_BAUD_RATE	38400
 #define	DEFAULT_CBAUD		B38400
-#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB)
+#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || defined(CONFIG_M5329EVB)
 #define CONSOLE_BAUD_RATE 	115200
 #define DEFAULT_CBAUD		B115200
 #elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \
-      defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
+      defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET)
 #define	CONSOLE_BAUD_RATE	19200
 #define	DEFAULT_CBAUD		B19200
 #endif
@@ -93,7 +93,7 @@
 #undef SERIAL_DEBUG_FLOW
 
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x)
 #define	IRQBASE	(MCFINT_VECBASE+MCFINT_UART0)
 #else
 #define	IRQBASE	73
@@ -1545,6 +1545,28 @@
 			*feci2c_par |=  MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2
 				    | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
 		}
+#elif defined(CONFIG_M532x)
+	volatile unsigned char *uartp;
+	uartp = info->addr;
+	switch (info->line) {
+	case 0:
+		MCF_INTC0_ICR26 = 0x3;
+		MCF_INTC0_CIMR = 26;
+		/* GPIO initialization */
+		MCF_GPIO_PAR_UART |= 0x000F;
+		break;
+	case 1:
+		MCF_INTC0_ICR27 = 0x3;
+		MCF_INTC0_CIMR = 27;
+		/* GPIO initialization */
+		MCF_GPIO_PAR_UART |= 0x0FF0;
+		break;
+	case 2:
+		MCF_INTC0_ICR28 = 0x3;
+		MCF_INTC0_CIMR = 28;
+		/* GPIOs also must be initalized, depends on board */
+		break;
+	}
 #else
 	volatile unsigned char	*icrp, *uartp;
 
diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c
new file mode 100644
index 0000000..c1adc9e
--- /dev/null
+++ b/drivers/serial/netx-serial.c
@@ -0,0 +1,749 @@
+/*
+ * drivers/serial/netx-serial.c
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/netx-regs.h>
+
+/* We've been assigned a range on the "Low-density serial ports" major */
+#define SERIAL_NX_MAJOR	204
+#define MINOR_START	170
+
+#ifdef CONFIG_SERIAL_NETX_CONSOLE
+
+enum uart_regs {
+	UART_DR              = 0x00,
+	UART_SR              = 0x04,
+	UART_LINE_CR         = 0x08,
+	UART_BAUDDIV_MSB     = 0x0c,
+	UART_BAUDDIV_LSB     = 0x10,
+	UART_CR              = 0x14,
+	UART_FR              = 0x18,
+	UART_IIR             = 0x1c,
+	UART_ILPR            = 0x20,
+	UART_RTS_CR          = 0x24,
+	UART_RTS_LEAD        = 0x28,
+	UART_RTS_TRAIL       = 0x2c,
+	UART_DRV_ENABLE      = 0x30,
+	UART_BRM_CR          = 0x34,
+	UART_RXFIFO_IRQLEVEL = 0x38,
+	UART_TXFIFO_IRQLEVEL = 0x3c,
+};
+
+#define SR_FE (1<<0)
+#define SR_PE (1<<1)
+#define SR_BE (1<<2)
+#define SR_OE (1<<3)
+
+#define LINE_CR_BRK       (1<<0)
+#define LINE_CR_PEN       (1<<1)
+#define LINE_CR_EPS       (1<<2)
+#define LINE_CR_STP2      (1<<3)
+#define LINE_CR_FEN       (1<<4)
+#define LINE_CR_5BIT      (0<<5)
+#define LINE_CR_6BIT      (1<<5)
+#define LINE_CR_7BIT      (2<<5)
+#define LINE_CR_8BIT      (3<<5)
+#define LINE_CR_BITS_MASK (3<<5)
+
+#define CR_UART_EN (1<<0)
+#define CR_SIREN   (1<<1)
+#define CR_SIRLP   (1<<2)
+#define CR_MSIE    (1<<3)
+#define CR_RIE     (1<<4)
+#define CR_TIE     (1<<5)
+#define CR_RTIE    (1<<6)
+#define CR_LBE     (1<<7)
+
+#define FR_CTS  (1<<0)
+#define FR_DSR  (1<<1)
+#define FR_DCD  (1<<2)
+#define FR_BUSY (1<<3)
+#define FR_RXFE (1<<4)
+#define FR_TXFF (1<<5)
+#define FR_RXFF (1<<6)
+#define FR_TXFE (1<<7)
+
+#define IIR_MIS (1<<0)
+#define IIR_RIS (1<<1)
+#define IIR_TIS (1<<2)
+#define IIR_RTIS (1<<3)
+#define IIR_MASK 0xf
+
+#define RTS_CR_AUTO (1<<0)
+#define RTS_CR_RTS  (1<<1)
+#define RTS_CR_COUNT (1<<2)
+#define RTS_CR_MOD2  (1<<3)
+#define RTS_CR_RTS_POL (1<<4)
+#define RTS_CR_CTS_CTR (1<<5)
+#define RTS_CR_CTS_POL (1<<6)
+#define RTS_CR_STICK   (1<<7)
+
+#define UART_PORT_SIZE 0x40
+#define DRIVER_NAME "netx-uart"
+
+struct netx_port {
+	struct uart_port	port;
+};
+
+static void netx_stop_tx(struct uart_port *port)
+{
+	unsigned int val;
+	val = readl(port->membase + UART_CR);
+	writel(val & ~CR_TIE,  port->membase + UART_CR);
+}
+
+static void netx_stop_rx(struct uart_port *port)
+{
+	unsigned int val;
+	val = readl(port->membase + UART_CR);
+	writel(val & ~CR_RIE,  port->membase + UART_CR);
+}
+
+static void netx_enable_ms(struct uart_port *port)
+{
+	unsigned int val;
+	val = readl(port->membase + UART_CR);
+	writel(val | CR_MSIE, port->membase + UART_CR);
+}
+
+static inline void netx_transmit_buffer(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->info->xmit;
+
+	if (port->x_char) {
+		writel(port->x_char, port->membase + UART_DR);
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
+		netx_stop_tx(port);
+		return;
+	}
+
+	do {
+		/* send xmit->buf[xmit->tail]
+		 * out the port here */
+		writel(xmit->buf[xmit->tail], port->membase + UART_DR);
+		xmit->tail = (xmit->tail + 1) &
+		         (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (!(readl(port->membase + UART_FR) & FR_TXFF));
+
+	if (uart_circ_empty(xmit))
+		netx_stop_tx(port);
+}
+
+static void netx_start_tx(struct uart_port *port)
+{
+	writel(
+	    readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR);
+
+	if (!(readl(port->membase + UART_FR) & FR_TXFF))
+		netx_transmit_buffer(port);
+}
+
+static unsigned int netx_tx_empty(struct uart_port *port)
+{
+	return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT;
+}
+
+static void netx_txint(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->info->xmit;
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		netx_stop_tx(port);
+		return;
+	}
+
+	netx_transmit_buffer(port);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+}
+
+static void netx_rxint(struct uart_port *port, struct pt_regs *regs)
+{
+	unsigned char rx, flg, status;
+	struct tty_struct *tty = port->info->tty;
+
+	while (!(readl(port->membase + UART_FR) & FR_RXFE)) {
+		rx = readl(port->membase + UART_DR);
+		flg = TTY_NORMAL;
+		port->icount.rx++;
+		status = readl(port->membase + UART_SR);
+		if (status & SR_BE) {
+			writel(0, port->membase + UART_SR);
+			if (uart_handle_break(port))
+				continue;
+		}
+
+		if (unlikely(status & (SR_FE | SR_PE | SR_OE))) {
+
+			if (status & SR_PE)
+				port->icount.parity++;
+			else if (status & SR_FE)
+				port->icount.frame++;
+			if (status & SR_OE)
+				port->icount.overrun++;
+
+			status &= port->read_status_mask;
+
+			if (status & SR_BE)
+				flg = TTY_BREAK;
+			else if (status & SR_PE)
+				flg = TTY_PARITY;
+			else if (status & SR_FE)
+				flg = TTY_FRAME;
+		}
+
+		if (uart_handle_sysrq_char(port, rx, regs))
+			continue;
+
+		uart_insert_char(port, status, SR_OE, rx, flg);
+	}
+
+	tty_flip_buffer_push(tty);
+	return;
+}
+
+static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port = (struct uart_port *)dev_id;
+	unsigned long flags;
+	unsigned char status;
+
+	spin_lock_irqsave(&port->lock,flags);
+
+	status = readl(port->membase + UART_IIR) & IIR_MASK;
+	while (status) {
+		if (status & IIR_RIS)
+			netx_rxint(port, regs);
+		if (status & IIR_TIS)
+			netx_txint(port);
+		if (status & IIR_MIS) {
+			if (readl(port->membase + UART_FR) & FR_CTS)
+				uart_handle_cts_change(port, 1);
+			else
+				uart_handle_cts_change(port, 0);
+		}
+		writel(0, port->membase + UART_IIR);
+		status = readl(port->membase + UART_IIR) & IIR_MASK;
+	}
+
+	spin_unlock_irqrestore(&port->lock,flags);
+	return IRQ_HANDLED;
+}
+
+static unsigned int netx_get_mctrl(struct uart_port *port)
+{
+	unsigned int ret = TIOCM_DSR | TIOCM_CAR;
+
+	if (readl(port->membase + UART_FR) & FR_CTS)
+		ret |= TIOCM_CTS;
+
+	return ret;
+}
+
+static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	unsigned int val;
+
+	if (mctrl & TIOCM_RTS) {
+		val = readl(port->membase + UART_RTS_CR);
+		writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);
+	}
+}
+
+static void netx_break_ctl(struct uart_port *port, int break_state)
+{
+	unsigned int line_cr;
+	spin_lock_irq(&port->lock);
+
+	line_cr = readl(port->membase + UART_LINE_CR);
+	if (break_state != 0)
+		line_cr |= LINE_CR_BRK;
+	else
+		line_cr &= ~LINE_CR_BRK;
+	writel(line_cr, port->membase + UART_LINE_CR);
+
+	spin_unlock_irq(&port->lock);
+}
+
+static int netx_startup(struct uart_port *port)
+{
+	int ret;
+
+	ret = request_irq(port->irq, netx_int, 0,
+			     DRIVER_NAME, port);
+	if (ret) {
+		dev_err(port->dev, "unable to grab irq%d\n",port->irq);
+		goto exit;
+	}
+
+	writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN,
+		port->membase + UART_LINE_CR);
+
+	writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN,
+		port->membase + UART_CR);
+
+exit:
+	return ret;
+}
+
+static void netx_shutdown(struct uart_port *port)
+{
+	writel(0, port->membase + UART_CR) ;
+
+	free_irq(port->irq, port);
+}
+
+static void
+netx_set_termios(struct uart_port *port, struct termios *termios,
+		   struct termios *old)
+{
+	unsigned int baud, quot;
+	unsigned char old_cr;
+	unsigned char line_cr = LINE_CR_FEN;
+	unsigned char rts_cr = 0;
+
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		line_cr |= LINE_CR_5BIT;
+		break;
+	case CS6:
+		line_cr |= LINE_CR_6BIT;
+		break;
+	case CS7:
+		line_cr |= LINE_CR_7BIT;
+		break;
+	case CS8:
+		line_cr |= LINE_CR_8BIT;
+		break;
+	}
+
+	if (termios->c_cflag & CSTOPB)
+		line_cr |= LINE_CR_STP2;
+
+	if (termios->c_cflag & PARENB) {
+		line_cr |= LINE_CR_PEN;
+		if (!(termios->c_cflag & PARODD))
+			line_cr |= LINE_CR_EPS;
+	}
+
+	if (termios->c_cflag & CRTSCTS)
+		rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL;
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+	quot = baud * 4096;
+	quot /= 1000;
+	quot *= 256;
+	quot /= 100000;
+
+	spin_lock_irq(&port->lock);
+
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	old_cr = readl(port->membase + UART_CR);
+
+	/* disable interrupts */
+	writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE),
+		port->membase + UART_CR);
+
+	/* drain transmitter */
+	while (readl(port->membase + UART_FR) & FR_BUSY);
+
+	/* disable UART */
+	writel(old_cr & ~CR_UART_EN, port->membase + UART_CR);
+
+	/* modem status interrupts */
+	old_cr &= ~CR_MSIE;
+	if (UART_ENABLE_MS(port, termios->c_cflag))
+		old_cr |= CR_MSIE;
+
+	writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB);
+	writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB);
+	writel(line_cr, port->membase + UART_LINE_CR);
+
+	writel(rts_cr, port->membase + UART_RTS_CR);
+
+	/*
+	 * Characters to ignore
+	 */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= SR_PE;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= SR_BE;
+		/*
+		 * If we're ignoring parity and break indicators,
+		 * ignore overruns too (for real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= SR_PE;
+	}
+
+	port->read_status_mask = 0;
+	if (termios->c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= SR_BE;
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= SR_PE | SR_FE;
+
+	writel(old_cr, port->membase + UART_CR);
+
+	spin_unlock_irq(&port->lock);
+}
+
+static const char *netx_type(struct uart_port *port)
+{
+	return port->type == PORT_NETX ? "NETX" : NULL;
+}
+
+static void netx_release_port(struct uart_port *port)
+{
+	release_mem_region(port->mapbase, UART_PORT_SIZE);
+}
+
+static int netx_request_port(struct uart_port *port)
+{
+	return request_mem_region(port->mapbase, UART_PORT_SIZE,
+			DRIVER_NAME) != NULL ? 0 : -EBUSY;
+}
+
+static void netx_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0)
+		port->type = PORT_NETX;
+}
+
+static int
+netx_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+	int ret = 0;
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX)
+		ret = -EINVAL;
+
+	return ret;
+}
+
+static struct uart_ops netx_pops = {
+	.tx_empty	= netx_tx_empty,
+	.set_mctrl	= netx_set_mctrl,
+	.get_mctrl	= netx_get_mctrl,
+	.stop_tx	= netx_stop_tx,
+	.start_tx	= netx_start_tx,
+	.stop_rx	= netx_stop_rx,
+	.enable_ms	= netx_enable_ms,
+	.break_ctl	= netx_break_ctl,
+	.startup	= netx_startup,
+	.shutdown	= netx_shutdown,
+	.set_termios	= netx_set_termios,
+	.type		= netx_type,
+	.release_port	= netx_release_port,
+	.request_port	= netx_request_port,
+	.config_port	= netx_config_port,
+	.verify_port	= netx_verify_port,
+};
+
+static struct netx_port netx_ports[] = {
+	{
+	.port = {
+		.type = PORT_NETX,
+		.iotype = UPIO_MEM,
+		.membase = (char __iomem *)io_p2v(NETX_PA_UART0),
+		.mapbase = NETX_PA_UART0,
+		.irq = NETX_IRQ_UART0,
+		.uartclk = 100000000,
+		.fifosize = 16,
+		.flags = UPF_BOOT_AUTOCONF,
+		.ops = &netx_pops,
+		.line = 0,
+	},
+	}, {
+	.port = {
+		.type = PORT_NETX,
+		.iotype = UPIO_MEM,
+		.membase = (char __iomem *)io_p2v(NETX_PA_UART1),
+		.mapbase = NETX_PA_UART1,
+		.irq = NETX_IRQ_UART1,
+		.uartclk = 100000000,
+		.fifosize = 16,
+		.flags = UPF_BOOT_AUTOCONF,
+		.ops = &netx_pops,
+		.line = 1,
+	},
+	}, {
+	.port = {
+		.type = PORT_NETX,
+		.iotype = UPIO_MEM,
+		.membase = (char __iomem *)io_p2v(NETX_PA_UART2),
+		.mapbase = NETX_PA_UART2,
+		.irq = NETX_IRQ_UART2,
+		.uartclk = 100000000,
+		.fifosize = 16,
+		.flags = UPF_BOOT_AUTOCONF,
+		.ops = &netx_pops,
+		.line = 2,
+	},
+	}
+};
+
+static void netx_console_putchar(struct uart_port *port, int ch)
+{
+	while (readl(port->membase + UART_FR) & FR_BUSY);
+	writel(ch, port->membase + UART_DR);
+}
+
+static void
+netx_console_write(struct console *co, const char *s, unsigned int count)
+{
+	struct uart_port *port = &netx_ports[co->index].port;
+	unsigned char cr_save;
+
+	cr_save = readl(port->membase + UART_CR);
+	writel(cr_save | CR_UART_EN, port->membase + UART_CR);
+
+	uart_console_write(port, s, count, netx_console_putchar);
+
+	while (readl(port->membase + UART_FR) & FR_BUSY);
+	writel(cr_save, port->membase + UART_CR);
+}
+
+static void __init
+netx_console_get_options(struct uart_port *port, int *baud,
+			int *parity, int *bits, int *flow)
+{
+	unsigned char line_cr;
+
+	*baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) |
+		readl(port->membase + UART_BAUDDIV_LSB);
+	*baud *= 1000;
+	*baud /= 4096;
+	*baud *= 1000;
+	*baud /= 256;
+	*baud *= 100;
+
+	line_cr = readl(port->membase + UART_LINE_CR);
+	*parity = 'n';
+	if (line_cr & LINE_CR_PEN) {
+		if (line_cr & LINE_CR_EPS)
+			*parity = 'e';
+		else
+			*parity = 'o';
+	}
+
+	switch (line_cr & LINE_CR_BITS_MASK) {
+	case LINE_CR_8BIT:
+		*bits = 8;
+		break;
+	case LINE_CR_7BIT:
+		*bits = 7;
+		break;
+	case LINE_CR_6BIT:
+		*bits = 6;
+		break;
+	case LINE_CR_5BIT:
+		*bits = 5;
+		break;
+	}
+
+	if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO)
+		*flow = 'r';
+}
+
+static int __init
+netx_console_setup(struct console *co, char *options)
+{
+	struct netx_port *sport;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	/*
+	 * Check whether an invalid uart number has been specified, and
+	 * if so, search for the first available port that does have
+	 * console support.
+	 */
+	if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports))
+		co->index = 0;
+	sport = &netx_ports[co->index];
+
+	if (options) {
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	} else {
+		/* if the UART is enabled, assume it has been correctly setup
+		 * by the bootloader and get the options
+		 */
+		if (readl(sport->port.membase + UART_CR) & CR_UART_EN) {
+			netx_console_get_options(&sport->port, &baud,
+			&parity, &bits, &flow);
+		}
+
+	}
+
+	return uart_set_options(&sport->port, co, baud, parity, bits, flow);
+}
+
+static struct uart_driver netx_reg;
+static struct console netx_console = {
+	.name		= "ttyNX",
+	.write		= netx_console_write,
+	.device		= uart_console_device,
+	.setup		= netx_console_setup,
+	.flags		= CON_PRINTBUFFER,
+	.index		= -1,
+	.data		= &netx_reg,
+};
+
+static int __init netx_console_init(void)
+{
+	register_console(&netx_console);
+	return 0;
+}
+console_initcall(netx_console_init);
+
+#define NETX_CONSOLE	&netx_console
+#else
+#define NETX_CONSOLE	NULL
+#endif
+
+static struct uart_driver netx_reg = {
+	.owner          = THIS_MODULE,
+	.driver_name    = DRIVER_NAME,
+	.dev_name       = "ttyNX",
+	.major          = SERIAL_NX_MAJOR,
+	.minor          = MINOR_START,
+	.nr             = ARRAY_SIZE(netx_ports),
+	.cons           = NETX_CONSOLE,
+};
+
+static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct netx_port *sport = platform_get_drvdata(pdev);
+
+	if (sport)
+		uart_suspend_port(&netx_reg, &sport->port);
+
+	return 0;
+}
+
+static int serial_netx_resume(struct platform_device *pdev)
+{
+	struct netx_port *sport = platform_get_drvdata(pdev);
+
+	if (sport)
+		uart_resume_port(&netx_reg, &sport->port);
+
+	return 0;
+}
+
+static int serial_netx_probe(struct platform_device *pdev)
+{
+	struct uart_port *port = &netx_ports[pdev->id].port;
+
+	dev_info(&pdev->dev, "initialising\n");
+
+	port->dev = &pdev->dev;
+
+	writel(1, port->membase + UART_RXFIFO_IRQLEVEL);
+	uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port);
+	platform_set_drvdata(pdev, &netx_ports[pdev->id]);
+
+	return 0;
+}
+
+static int serial_netx_remove(struct platform_device *pdev)
+{
+	struct netx_port *sport = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (sport)
+		uart_remove_one_port(&netx_reg, &sport->port);
+
+	return 0;
+}
+
+static struct platform_driver serial_netx_driver = {
+	.probe          = serial_netx_probe,
+	.remove         = serial_netx_remove,
+
+	.suspend	= serial_netx_suspend,
+	.resume		= serial_netx_resume,
+
+	.driver		= {
+		.name   = DRIVER_NAME,
+	},
+};
+
+static int __init netx_serial_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Serial: NetX driver\n");
+
+	ret = uart_register_driver(&netx_reg);
+	if (ret)
+		return ret;
+
+	ret = platform_driver_register(&serial_netx_driver);
+	if (ret != 0)
+		uart_unregister_driver(&netx_reg);
+
+	return 0;
+}
+
+static void __exit netx_serial_exit(void)
+{
+	platform_driver_unregister(&serial_netx_driver);
+	uart_unregister_driver(&netx_reg);
+}
+
+module_init(netx_serial_init);
+module_exit(netx_serial_exit);
+
+MODULE_AUTHOR("Sascha Hauer");
+MODULE_DESCRIPTION("NetX serial port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 77d4568..ae36495 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -269,7 +269,6 @@
 	unsigned char status;
 	unsigned int ret;
 
-return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
 	status = serial_in(up, UART_MSR);
 
 	ret = 0;
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index f5aac92..837b6da 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -872,6 +872,8 @@
 		return "S3C2410";
 	case PORT_S3C2440:
 		return "S3C2440";
+	case PORT_S3C2412:
+		return "S3C2412";
 	default:
 		return NULL;
 	}
@@ -1365,7 +1367,7 @@
 
 #endif /* CONFIG_CPU_S3C2410 */
 
-#ifdef CONFIG_CPU_S3C2440
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
 
 static int s3c2440_serial_setsource(struct uart_port *port,
 				     struct s3c24xx_uart_clksrc *clk)
@@ -1528,6 +1530,141 @@
 #define s3c2440_uart_inf_at NULL
 #endif /* CONFIG_CPU_S3C2440 */
 
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+
+static int s3c2412_serial_setsource(struct uart_port *port,
+				     struct s3c24xx_uart_clksrc *clk)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	ucon &= ~S3C2412_UCON_CLKMASK;
+
+	if (strcmp(clk->name, "uclk") == 0)
+		ucon |= S3C2440_UCON_UCLK;
+	else if (strcmp(clk->name, "pclk") == 0)
+		ucon |= S3C2440_UCON_PCLK;
+	else if (strcmp(clk->name, "usysclk") == 0)
+		ucon |= S3C2412_UCON_USYSCLK;
+	else {
+		printk(KERN_ERR "unknown clock source %s\n", clk->name);
+		return -EINVAL;
+	}
+
+	wr_regl(port, S3C2410_UCON, ucon);
+	return 0;
+}
+
+
+static int s3c2412_serial_getsource(struct uart_port *port,
+				    struct s3c24xx_uart_clksrc *clk)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	switch (ucon & S3C2412_UCON_CLKMASK) {
+	case S3C2412_UCON_UCLK:
+		clk->divisor = 1;
+		clk->name = "uclk";
+		break;
+
+	case S3C2412_UCON_PCLK:
+	case S3C2412_UCON_PCLK2:
+		clk->divisor = 1;
+		clk->name = "pclk";
+		break;
+
+	case S3C2412_UCON_USYSCLK:
+		clk->divisor = 1;
+		clk->name = "usysclk";
+		break;
+	}
+
+	return 0;
+}
+
+static int s3c2412_serial_resetport(struct uart_port *port,
+				    struct s3c2410_uartcfg *cfg)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	dbg("%s: port=%p (%08lx), cfg=%p\n",
+	    __FUNCTION__, port, port->mapbase, cfg);
+
+	/* ensure we don't change the clock settings... */
+
+	ucon &= S3C2412_UCON_CLKMASK;
+
+	wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
+	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+	/* reset both fifos */
+
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+	return 0;
+}
+
+static struct s3c24xx_uart_info s3c2412_uart_inf = {
+	.name		= "Samsung S3C2412 UART",
+	.type		= PORT_S3C2412,
+	.fifosize	= 64,
+	.rx_fifomask	= S3C2440_UFSTAT_RXMASK,
+	.rx_fifoshift	= S3C2440_UFSTAT_RXSHIFT,
+	.rx_fifofull	= S3C2440_UFSTAT_RXFULL,
+	.tx_fifofull	= S3C2440_UFSTAT_TXFULL,
+	.tx_fifomask	= S3C2440_UFSTAT_TXMASK,
+	.tx_fifoshift	= S3C2440_UFSTAT_TXSHIFT,
+	.get_clksrc	= s3c2412_serial_getsource,
+	.set_clksrc	= s3c2412_serial_setsource,
+	.reset_port	= s3c2412_serial_resetport,
+};
+
+/* device management */
+
+static int s3c2412_serial_probe(struct platform_device *dev)
+{
+	dbg("s3c2440_serial_probe: dev=%p\n", dev);
+	return s3c24xx_serial_probe(dev, &s3c2440_uart_inf);
+}
+
+static struct platform_driver s3c2412_serial_drv = {
+	.probe		= s3c2412_serial_probe,
+	.remove		= s3c24xx_serial_remove,
+	.suspend	= s3c24xx_serial_suspend,
+	.resume		= s3c24xx_serial_resume,
+	.driver		= {
+		.name	= "s3c2412-uart",
+		.owner	= THIS_MODULE,
+	},
+};
+
+
+static inline int s3c2412_serial_init(void)
+{
+	return s3c24xx_serial_init(&s3c2412_serial_drv, &s3c2412_uart_inf);
+}
+
+static inline void s3c2412_serial_exit(void)
+{
+	platform_driver_unregister(&s3c2412_serial_drv);
+}
+
+#define s3c2412_uart_inf_at &s3c2412_uart_inf
+#else
+
+static inline int s3c2412_serial_init(void)
+{
+	return 0;
+}
+
+static inline void s3c2412_serial_exit(void)
+{
+}
+
+#define s3c2412_uart_inf_at NULL
+#endif /* CONFIG_CPU_S3C2440 */
+
+
 /* module initialisation code */
 
 static int __init s3c24xx_serial_modinit(void)
@@ -1542,6 +1679,7 @@
 
 	s3c2400_serial_init();
 	s3c2410_serial_init();
+	s3c2412_serial_init();
 	s3c2440_serial_init();
 
 	return 0;
@@ -1551,6 +1689,7 @@
 {
 	s3c2400_serial_exit();
 	s3c2410_serial_exit();
+	s3c2412_serial_exit();
 	s3c2440_serial_exit();
 
 	uart_unregister_driver(&s3c24xx_uart_drv);
@@ -1773,6 +1912,8 @@
 		info = s3c2410_uart_inf_at;
 	} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
 		info = s3c2440_uart_inf_at;
+	} else if (strcmp(dev->name, "s3c2412-uart") == 0) {
+		info = s3c2412_uart_inf_at;
 	} else {
 		printk(KERN_ERR "s3c24xx: no driver for %s\n", dev->name);
 		return 0;
@@ -1796,4 +1937,4 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
-MODULE_DESCRIPTION("Samsung S3C2410/S3C2440 Serial port driver");
+MODULE_DESCRIPTION("Samsung S3C2410/S3C2440/S3C2412 Serial port driver");
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index aa521b8..776d4ff 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -145,14 +145,15 @@
 {
 	struct tty_struct* tty = port->info->tty;
 	int cbRxMax = 256;	/* (Gross) limit on receive */
-	unsigned int data, flag;/* Received data and status */
+	unsigned int data;	/* Received data and status */
+	unsigned int flag;
 
 	while (!(UR (port, UART_R_STATUS) & nRxRdy) && --cbRxMax) {
 		data = UR (port, UART_R_DATA);
 		flag = TTY_NORMAL;
 		++port->icount.rx;
 
-		if (unlikely(data & RxError)) {	/* Quick check, short-circuit */
+		if (unlikely(data & RxError)) {
 			if (data & RxBreak) {
 				data &= ~(RxFramingError | RxParityError);
 				++port->icount.brk;
@@ -303,7 +304,7 @@
 	/* Note, kernel appears to be setting DTR and RTS on console. */
 
 	/* *** FIXME: this deserves more work.  There's some work in
-               tracing all of the IO pins. */
+	       tracing all of the IO pins. */
 #if 0
 	if( port->mapbase == UART1_PHYS) {
 		gpioRegs_t *gpio = (gpioRegs_t *)IO_ADDRESS(GPIO_PHYS);
@@ -662,9 +663,13 @@
 	if (ret == 0) {
 		int i;
 
-		for (i = 0; i < DEV_NR; i++)
+		for (i = 0; i < DEV_NR; i++) {
+			/* UART3, when used, requires GPIO pin reallocation */
+			if (lh7a40x_ports[i].port.mapbase == UART3_PHYS)
+				GPIO_PINMUX |= 1<<3;
 			uart_add_one_port (&lh7a40x_reg,
 					   &lh7a40x_ports[i].port);
+		}
 	}
 	return ret;
 }
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index f137804..ba22e25 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -427,31 +427,32 @@
 
 static unsigned int __init get_interrupt(void)
 {
-	const char *cons_str = "console";
-	const char *compat_str = "compatible";
-	int node = prom_getchild(sun4v_vdev_root);
-	char buf[64];
-	int err, len;
+	struct device_node *dev_node;
 
-	node = prom_searchsiblings(node, cons_str);
-	if (!node)
-		return 0;
+	dev_node = sun4v_vdev_root->child;
+	while (dev_node != NULL) {
+		struct property *prop;
 
-	len = prom_getproplen(node, compat_str);
-	if (len == 0 || len == -1)
-		return 0;
+		if (strcmp(dev_node->name, "console"))
+			goto next_sibling;
 
-	err = prom_getproperty(node, compat_str, buf, 64);
-	if (err == -1)
-		return 0;
+		prop = of_find_property(dev_node, "compatible", NULL);
+		if (!prop)
+			goto next_sibling;
 
-	if (!hv_console_compatible(buf, len))
+		if (hv_console_compatible(prop->value, prop->length))
+			break;
+
+	next_sibling:
+		dev_node = dev_node->sibling;
+	}
+	if (!dev_node)
 		return 0;
 
 	/* Ok, the this is the OBP node for the sun4v hypervisor
 	 * console device.  Decode the interrupt.
 	 */
-	return sun4v_vdev_device_interrupt(node);
+	return sun4v_vdev_device_interrupt(dev_node);
 }
 
 static int __init sunhv_init(void)
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index bfbe9dc..e4c0fd2 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -984,19 +984,19 @@
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
-			if (!strcmp(edev->prom_name, "se")) {
+			if (!strcmp(edev->prom_node->name, "se")) {
 				callback(edev, arg);
 				continue;
-			} else if (!strcmp(edev->prom_name, "serial")) {
-				char compat[32];
+			} else if (!strcmp(edev->prom_node->name, "serial")) {
+				char *compat;
 				int clen;
 
 				/* On RIO this can be an SE, check it.  We could
 				 * just check ebus->is_rio, but this is more portable.
 				 */
-				clen = prom_getproperty(edev->prom_node, "compatible",
-							compat, sizeof(compat));
-				if (clen > 0) {
+				compat = of_get_property(edev->prom_node,
+							 "compatible", &clen);
+				if (compat && clen > 0) {
 					if (strncmp(compat, "sab82532", 8) == 0) {
 						callback(edev, arg);
 						continue;
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 2b4f965..0268b30 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1053,7 +1053,7 @@
 	 */
 	for_each_ebus(ebus) {
 		for_each_ebusdev(dev, ebus) {
-			if (dev->prom_node == up->port_node) {
+			if (dev->prom_node->node == up->port_node) {
 				/*
 				 * The EBus is broken on sparc; it delivers
 				 * virtual addresses in resources. Oh well...
@@ -1073,7 +1073,7 @@
 #ifdef CONFIG_SPARC64
 	for_each_isa(isa_br) {
 		for_each_isadev(isa_dev, isa_br) {
-			if (isa_dev->prom_node == up->port_node) {
+			if (isa_dev->prom_node->node == up->port_node) {
 				/* Same on sparc64. Cool architecure... */
 				up->port.membase = (char *) isa_dev->resource.start;
 				up->port.mapbase = isa_dev->resource.start;
@@ -1295,9 +1295,9 @@
 	if (up->port.type == PORT_UNKNOWN)
 		return -1;
 
-	printk(KERN_INFO "su%d at 0x%p (irq = %s) is a %s\n",
+	printk(KERN_INFO "su%d at 0x%p (irq = %d) is a %s\n",
 	       channel,
-	       up->port.membase, __irq_itoa(up->port.irq),
+	       up->port.membase, up->port.irq,
 	       sunsu_type(&up->port));
 
 #ifdef CONFIG_SERIO
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index cd49ebb..76c9bac 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1106,7 +1106,7 @@
 				+ FHC_UREGS_ICLR;
 			imap = central_bus->child->fhc_regs.uregs
 				+ FHC_UREGS_IMAP;
-			zilog_irq = build_irq(12, 0, iclr, imap);
+			zilog_irq = build_irq(0, iclr, imap);
 		} else {
 			err = prom_getproperty(zsnode, "interrupts",
 					       (char *) &sun4u_ino,
@@ -1540,8 +1540,8 @@
 		up->cflag = B4800 | CS8 | CLOCAL | CREAD;
 		baud = 4800;
 	}
-	printk(KERN_INFO "zs%d at 0x%p (irq = %s) is a SunZilog\n",
-	       channel, up->port.membase, __irq_itoa(zilog_irq));
+	printk(KERN_INFO "zs%d at 0x%p (irq = %d) is a SunZilog\n",
+	       channel, up->port.membase, zilog_irq);
 
 	up->curregs[R15] = BRKIE;
 	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c
index 501316b..ed94631 100644
--- a/drivers/sn/ioc3.c
+++ b/drivers/sn/ioc3.c
@@ -26,7 +26,7 @@
 
 static struct ioc3_submodule *ioc3_submodules[IOC3_MAX_SUBMODULES];
 static struct ioc3_submodule *ioc3_ethernet;
-static rwlock_t ioc3_submodules_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ioc3_submodules_lock);
 
 /* NIC probing code */
 
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index cdeff90..8256a97 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -160,9 +160,6 @@
 	writel(0, &idd->idd_misc_regs->int_out.raw);
 	mmiowb();
 
-	printk(KERN_INFO
-	       "%s: Calibrating PCI bus speed "
-	       "for pci_dev %s ... ", __FUNCTION__, pci_name(idd->idd_pdev));
 	/* Set up square wave */
 	int_out.raw = 0;
 	int_out.fields.count = IOC4_CALIBRATE_COUNT;
@@ -206,11 +203,16 @@
 	/* Bounds check the result. */
 	if (period > IOC4_CALIBRATE_LOW_LIMIT ||
 	    period < IOC4_CALIBRATE_HIGH_LIMIT) {
-		printk("failed. Assuming PCI clock ticks are %d ns.\n",
+		printk(KERN_INFO
+		       "IOC4 %s: Clock calibration failed.  Assuming"
+		       "PCI clock is %d ns.\n",
+		       pci_name(idd->idd_pdev),
 		       IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
 		period = IOC4_CALIBRATE_DEFAULT;
 	} else {
-		printk("succeeded. PCI clock ticks are %ld ns.\n",
+		printk(KERN_DEBUG
+		       "IOC4 %s: PCI clock is %ld ns.\n",
+		       pci_name(idd->idd_pdev),
 		       period / IOC4_EXTINT_COUNT_DIVISOR);
 	}
 
@@ -222,6 +224,51 @@
 	idd->count_period = period;
 }
 
+/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT.
+ * Each brings out different combinations of IOC4 signals, thus.
+ * the IOC4 subdrivers need to know to which we're attached.
+ *
+ * We look for the presence of a SCSI (IO9) or SATA (IO10) controller
+ * on the same PCI bus at slot number 3 to differentiate IO9 from IO10.
+ * If neither is present, it's a PCI-RT.
+ */
+static unsigned int
+ioc4_variant(struct ioc4_driver_data *idd)
+{
+	struct pci_dev *pdev = NULL;
+	int found = 0;
+
+	/* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */
+	do {
+		pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC,
+				      PCI_DEVICE_ID_QLOGIC_ISP12160, pdev);
+		if (pdev &&
+		    idd->idd_pdev->bus->number == pdev->bus->number &&
+		    3 == PCI_SLOT(pdev->devfn))
+			found = 1;
+		pci_dev_put(pdev);
+	} while (pdev && !found);
+	if (NULL != pdev)
+		return IOC4_VARIANT_IO9;
+
+	/* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */
+	pdev = NULL;
+	do {
+		pdev = pci_get_device(PCI_VENDOR_ID_VITESSE,
+				      PCI_DEVICE_ID_VITESSE_VSC7174, pdev);
+		if (pdev &&
+		    idd->idd_pdev->bus->number == pdev->bus->number &&
+		    3 == PCI_SLOT(pdev->devfn))
+			found = 1;
+		pci_dev_put(pdev);
+	} while (pdev && !found);
+	if (NULL != pdev)
+		return IOC4_VARIANT_IO10;
+
+	/* PCI-RT: No SCSI/SATA controller will be present */
+	return IOC4_VARIANT_PCI_RT;
+}
+
 /* Adds a new instance of an IOC4 card */
 static int
 ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
@@ -286,6 +333,13 @@
 
 	/* Failsafe portion of per-IOC4 initialization */
 
+	/* Detect card variant */
+	idd->idd_variant = ioc4_variant(idd);
+	printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev),
+	       idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" :
+	       idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" :
+	       idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown");
+
 	/* Initialize IOC4 */
 	pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
 	pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 1cea4a6..ed1cdf6 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -210,6 +210,7 @@
 	proxy->master = master;
 	proxy->chip_select = chip->chip_select;
 	proxy->max_speed_hz = chip->max_speed_hz;
+	proxy->mode = chip->mode;
 	proxy->irq = chip->irq;
 	proxy->modalias = chip->modalias;
 
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index 5578a9d..f6b2948 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -5712,7 +5712,7 @@
 	return 1;
 }
 
-int ixj_set_tone_off(unsigned short arg, IXJ *j)
+static int ixj_set_tone_off(unsigned short arg, IXJ *j)
 {
 	j->tone_off_time = arg;
 	if (ixj_WriteDSPCommand(0x6E05, j))		/* Set Tone Off Period */
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 9b7d976..c7123bf 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -48,6 +48,7 @@
 obj-$(CONFIG_USB_SERIAL)	+= serial/
 
 obj-$(CONFIG_USB_AUERSWALD)	+= misc/
+obj-$(CONFIG_USB_CY7C63)	+= misc/
 obj-$(CONFIG_USB_CYTHERM)	+= misc/
 obj-$(CONFIG_USB_EMI26)		+= misc/
 obj-$(CONFIG_USB_EMI62)		+= misc/
@@ -61,6 +62,7 @@
 obj-$(CONFIG_USB_USS720)	+= misc/
 obj-$(CONFIG_USB_PHIDGETSERVO)	+= misc/
 obj-$(CONFIG_USB_SISUSBVGA)	+= misc/
+obj-$(CONFIG_USB_APPLEDISPLAY)	+= misc/
 
 obj-$(CONFIG_USB_ATM)		+= atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)	+= atm/
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 5462498..a38701c 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -1039,7 +1039,7 @@
 	tasklet_schedule((struct tasklet_struct *) data);
 }
 
-static inline void usbatm_init_channel(struct usbatm_channel *channel)
+static void usbatm_init_channel(struct usbatm_channel *channel)
 {
 	spin_lock_init(&channel->lock);
 	INIT_LIST_HEAD(&channel->list);
diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c
index 42d6823..70125c6 100644
--- a/drivers/usb/atm/xusbatm.c
+++ b/drivers/usb/atm/xusbatm.c
@@ -20,7 +20,6 @@
  ******************************************************************************/
 
 #include <linux/module.h>
-#include <linux/netdevice.h>		/* FIXME: required by linux/etherdevice.h */
 #include <linux/etherdevice.h>		/* for random_ether_addr() */
 
 #include "usbatm.h"
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 6dd339f..d41dc67 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -63,7 +63,7 @@
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
-#include <linux/usb_cdc.h>
+#include <linux/usb/cdc.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 #include <linux/list.h>
@@ -127,8 +127,8 @@
 			wb->use = 1;
 			return wbn;
 		}
-		wbn = (wbn + 1) % ACM_NWB;
-		if (++i >= ACM_NWB)
+		wbn = (wbn + 1) % ACM_NW;
+		if (++i >= ACM_NW)
 			return -1;
 	}
 }
@@ -142,10 +142,9 @@
 {
 	int i, n;
 
-	n = 0;
-	for (i = 0; i < ACM_NWB; i++) {
-		if (!acm->wb[i].use)
-			n++;
+	n = ACM_NW;
+	for (i = 0; i < ACM_NW; i++) {
+		n -= acm->wb[i].use;
 	}
 	return n;
 }
@@ -167,7 +166,7 @@
 	acm->write_ready = 1;
 	wbn = acm->write_current;
 	acm_wb_free(acm, wbn);
-	acm->write_current = (wbn + 1) % ACM_NWB;
+	acm->write_current = (wbn + 1) % ACM_NW;
 	spin_unlock_irqrestore(&acm->write_lock, flags);
 }
 
@@ -291,22 +290,32 @@
 	struct acm_rb *buf;
 	struct acm_ru *rcv = urb->context;
 	struct acm *acm = rcv->instance;
+	int status = urb->status;
 	dbg("Entering acm_read_bulk with status %d\n", urb->status);
 
 	if (!ACM_READY(acm))
 		return;
 
-	if (urb->status)
-		dev_dbg(&acm->data->dev, "bulk rx status %d\n", urb->status);
+	if (status)
+		dev_dbg(&acm->data->dev, "bulk rx status %d\n", status);
 
 	buf = rcv->buffer;
 	buf->size = urb->actual_length;
 
-	spin_lock(&acm->read_lock);
-	list_add_tail(&rcv->list, &acm->spare_read_urbs);
-	list_add_tail(&buf->list, &acm->filled_read_bufs);
-	spin_unlock(&acm->read_lock);
-
+	if (likely(status == 0)) {
+		spin_lock(&acm->read_lock);
+		list_add_tail(&rcv->list, &acm->spare_read_urbs);
+		list_add_tail(&buf->list, &acm->filled_read_bufs);
+		spin_unlock(&acm->read_lock);
+	} else {
+		/* we drop the buffer due to an error */
+		spin_lock(&acm->read_lock);
+		list_add_tail(&rcv->list, &acm->spare_read_urbs);
+		list_add(&buf->list, &acm->spare_read_bufs);
+		spin_unlock(&acm->read_lock);
+		/* nevertheless the tasklet must be kicked unconditionally
+		so the queue cannot dry up */
+	}
 	tasklet_schedule(&acm->urb_task);
 }
 
@@ -464,10 +473,10 @@
 	INIT_LIST_HEAD(&acm->spare_read_urbs);
 	INIT_LIST_HEAD(&acm->spare_read_bufs);
 	INIT_LIST_HEAD(&acm->filled_read_bufs);
-	for (i = 0; i < ACM_NRU; i++) {
+	for (i = 0; i < acm->rx_buflimit; i++) {
 		list_add(&(acm->ru[i].list), &acm->spare_read_urbs);
 	}
-	for (i = 0; i < ACM_NRB; i++) {
+	for (i = 0; i < acm->rx_buflimit; i++) {
 		list_add(&(acm->rb[i].list), &acm->spare_read_bufs);
 	}
 
@@ -488,14 +497,15 @@
 
 static void acm_tty_unregister(struct acm *acm)
 {
-	int i;
+	int i,nr;
 
+	nr = acm->rx_buflimit;
 	tty_unregister_device(acm_tty_driver, acm->minor);
 	usb_put_intf(acm->control);
 	acm_table[acm->minor] = NULL;
 	usb_free_urb(acm->ctrlurb);
 	usb_free_urb(acm->writeurb);
-	for (i = 0; i < ACM_NRU; i++)
+	for (i = 0; i < nr; i++)
 		usb_free_urb(acm->ru[i].urb);
 	kfree(acm);
 }
@@ -503,18 +513,19 @@
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct acm *acm = tty->driver_data;
-	int i;
+	int i,nr;
 
 	if (!acm || !acm->used)
 		return;
 
+	nr = acm->rx_buflimit;
 	mutex_lock(&open_mutex);
 	if (!--acm->used) {
 		if (acm->dev) {
 			acm_set_control(acm, acm->ctrlout = 0);
 			usb_kill_urb(acm->ctrlurb);
 			usb_kill_urb(acm->writeurb);
-			for (i = 0; i < ACM_NRU; i++)
+			for (i = 0; i < nr; i++)
 				usb_kill_urb(acm->ru[i].urb);
 		} else
 			acm_tty_unregister(acm);
@@ -576,7 +587,7 @@
 	/*
 	 * This is inaccurate (overcounts), but it works.
 	 */
-	return (ACM_NWB - acm_wb_is_avail(acm)) * acm->writesize;
+	return (ACM_NW - acm_wb_is_avail(acm)) * acm->writesize;
 }
 
 static void acm_tty_throttle(struct tty_struct *tty)
@@ -712,7 +723,7 @@
 	int i;
 	struct acm_wb *wb;
 
-	for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {
+	for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
 		usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah);
 	}
 }
@@ -723,7 +734,7 @@
 	int i;
 	struct acm_wb *wb;
 
-	for (wb = &acm->wb[0], i = 0; i < ACM_NWB; i++, wb++) {
+	for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) {
 		wb->buf = usb_buffer_alloc(acm->dev, acm->writesize, GFP_KERNEL,
 		    &wb->dmah);
 		if (!wb->buf) {
@@ -760,10 +771,14 @@
 	int call_interface_num = -1;
 	int data_interface_num;
 	unsigned long quirks;
+	int num_rx_buf;
 	int i;
 
-	/* handle quirks deadly to normal probing*/
+	/* normal quirks */
 	quirks = (unsigned long)id->driver_info;
+	num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR;
+
+	/* handle quirks deadly to normal probing*/
 	if (quirks == NO_UNION_NORMAL) {
 		data_interface = usb_ifnum_to_if(usb_dev, 1);
 		control_interface = usb_ifnum_to_if(usb_dev, 0);
@@ -900,7 +915,7 @@
 	}
 
 	ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
-	readsize = le16_to_cpu(epread->wMaxPacketSize)*2;
+	readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2);
 	acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
 	acm->control = control_interface;
 	acm->data = data_interface;
@@ -909,6 +924,7 @@
 	acm->ctrl_caps = ac_management_function;
 	acm->ctrlsize = ctrlsize;
 	acm->readsize = readsize;
+	acm->rx_buflimit = num_rx_buf;
 	acm->urb_task.func = acm_rx_tasklet;
 	acm->urb_task.data = (unsigned long) acm;
 	INIT_WORK(&acm->work, acm_softint, acm);
@@ -935,7 +951,7 @@
 		dev_dbg(&intf->dev, "out of memory (ctrlurb kmalloc)\n");
 		goto alloc_fail5;
 	}
-	for (i = 0; i < ACM_NRU; i++) {
+	for (i = 0; i < num_rx_buf; i++) {
 		struct acm_ru *rcv = &(acm->ru[i]);
 
 		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
@@ -946,10 +962,9 @@
 		rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 		rcv->instance = acm;
 	}
-	for (i = 0; i < ACM_NRB; i++) {
+	for (i = 0; i < num_rx_buf; i++) {
 		struct acm_rb *buf = &(acm->rb[i]);
 
-		// Using usb_buffer_alloc instead of kmalloc as Oliver suggested
 		if (!(buf->base = usb_buffer_alloc(acm->dev, readsize, GFP_KERNEL, &buf->dma))) {
 			dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n");
 			goto alloc_fail7;
@@ -988,9 +1003,9 @@
 	return 0;
 
 alloc_fail7:
-	for (i = 0; i < ACM_NRB; i++)
+	for (i = 0; i < num_rx_buf; i++)
 		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
-	for (i = 0; i < ACM_NRU; i++)
+	for (i = 0; i < num_rx_buf; i++)
 		usb_free_urb(acm->ru[i].urb);
 	usb_free_urb(acm->ctrlurb);
 alloc_fail5:
@@ -1027,7 +1042,7 @@
 
 	usb_kill_urb(acm->ctrlurb);
 	usb_kill_urb(acm->writeurb);
-	for (i = 0; i < ACM_NRU; i++)
+	for (i = 0; i < acm->rx_buflimit; i++)
 		usb_kill_urb(acm->ru[i].urb);
 
 	INIT_LIST_HEAD(&acm->filled_read_bufs);
@@ -1039,7 +1054,7 @@
 
 	acm_write_buffers_free(acm);
 	usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma);
-	for (i = 0; i < ACM_NRB; i++)
+	for (i = 0; i < acm->rx_buflimit; i++)
 		usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma);
 
 	usb_driver_release_interface(&acm_driver, intf == acm->control ? acm->data : intf);
@@ -1068,6 +1083,9 @@
 	{ USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
+	{ USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */
+	.driver_info = SINGLE_RX_URB, /* firmware bug */
+	},
 	/* control interfaces with various AT-command sets */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_ACM_PROTO_AT_V25TER) },
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index fd2aaccd..1bcaea3 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -56,11 +56,11 @@
  * in line disciplines. They ask for empty space amount, receive our URB size,
  * and proceed to issue several 1-character writes, assuming they will fit.
  * The very first write takes a complete URB. Fortunately, this only happens
- * when processing onlcr, so we only need 2 buffers.
+ * when processing onlcr, so we only need 2 buffers. These values must be
+ * powers of 2.
  */
-#define ACM_NWB  2
-#define ACM_NRU  16
-#define ACM_NRB  16
+#define ACM_NW  2
+#define ACM_NR  16
 
 struct acm_wb {
 	unsigned char *buf;
@@ -91,9 +91,10 @@
 	struct urb *ctrlurb, *writeurb;			/* urbs */
 	u8 *ctrl_buffer;				/* buffers of urbs */
 	dma_addr_t ctrl_dma;				/* dma handles of buffers */
-	struct acm_wb wb[ACM_NWB];
-	struct acm_ru ru[ACM_NRU];
-	struct acm_rb rb[ACM_NRB];
+	struct acm_wb wb[ACM_NW];
+	struct acm_ru ru[ACM_NR];
+	struct acm_rb rb[ACM_NR];
+	int rx_buflimit;
 	int rx_endpoint;
 	spinlock_t read_lock;
 	struct list_head spare_read_urbs;
@@ -122,3 +123,4 @@
 
 /* constants describing various quirks and errors */
 #define NO_UNION_NORMAL			1
+#define SINGLE_RX_URB			2
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
index 28329dd..ec51092 100644
--- a/drivers/usb/core/Makefile
+++ b/drivers/usb/core/Makefile
@@ -3,7 +3,8 @@
 #
 
 usbcore-objs	:= usb.o hub.o hcd.o urb.o message.o driver.o \
-			config.o file.o buffer.o sysfs.o devio.o notify.o
+			config.o file.o buffer.o sysfs.o endpoint.o \
+			devio.o notify.o
 
 ifeq ($(CONFIG_PCI),y)
 	usbcore-objs	+= hcd-pci.o
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 545da37..bcbeaf7 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -515,19 +515,19 @@
 
 static struct usb_device *usbdev_lookup_minor(int minor)
 {
-	struct class_device *class_dev;
-	struct usb_device *dev = NULL;
+	struct device *device;
+	struct usb_device *udev = NULL;
 
 	down(&usb_device_class->sem);
-	list_for_each_entry(class_dev, &usb_device_class->children, node) {
-		if (class_dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
-			dev = class_dev->class_data;
+	list_for_each_entry(device, &usb_device_class->devices, node) {
+		if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) {
+			udev = device->platform_data;
 			break;
 		}
 	}
 	up(&usb_device_class->sem);
 
-	return dev;
+	return udev;
 };
 
 /*
@@ -823,8 +823,7 @@
 
 static int proc_resetdevice(struct dev_state *ps)
 {
-	return usb_reset_device(ps->dev);
-
+	return usb_reset_composite_device(ps->dev, NULL);
 }
 
 static int proc_setintf(struct dev_state *ps, void __user *arg)
@@ -923,8 +922,8 @@
 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 				!= USB_ENDPOINT_XFER_CONTROL)
 			return -EINVAL;
-		/* min 8 byte setup packet, max arbitrary */
-		if (uurb->buffer_length < 8 || uurb->buffer_length > PAGE_SIZE)
+		/* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */
+		if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
 			return -EINVAL;
 		if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
 			return -ENOMEM;
@@ -982,7 +981,8 @@
 			return -EFAULT;
 		}
 		for (totlen = u = 0; u < uurb->number_of_packets; u++) {
-			if (isopkt[u].length > 1023) {
+			/* arbitrary limit, sufficient for USB 2.0 high-bandwidth iso */
+			if (isopkt[u].length > 8192) {
 				kfree(isopkt);
 				return -EINVAL;
 			}
@@ -1576,16 +1576,16 @@
 {
 	int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1);
 
-	dev->class_dev = class_device_create(usb_device_class, NULL,
-				MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev,
+	dev->usbfs_dev = device_create(usb_device_class, &dev->dev,
+				MKDEV(USB_DEVICE_MAJOR, minor),
 				"usbdev%d.%d", dev->bus->busnum, dev->devnum);
 
-	dev->class_dev->class_data = dev;
+	dev->usbfs_dev->platform_data = dev;
 }
 
 static void usbdev_remove(struct usb_device *dev)
 {
-	class_device_unregister(dev->class_dev);
+	device_unregister(dev->usbfs_dev);
 }
 
 static int usbdev_notify(struct notifier_block *self, unsigned long action,
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
new file mode 100644
index 0000000..247b5a4
--- /dev/null
+++ b/drivers/usb/core/endpoint.c
@@ -0,0 +1,275 @@
+/*
+ * drivers/usb/core/endpoint.c
+ *
+ * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman
+ * (C) Copyright 2002,2004 IBM Corp.
+ * (C) Copyright 2006 Novell Inc.
+ *
+ * Endpoint sysfs stuff
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include "usb.h"
+
+/* endpoint stuff */
+
+struct ep_device {
+	struct usb_endpoint_descriptor *desc;
+	struct usb_device *udev;
+	struct device dev;
+};
+#define to_ep_device(_dev) \
+	container_of(_dev, struct ep_device, dev)
+
+struct ep_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct usb_device *,
+			struct usb_endpoint_descriptor *, char *);
+};
+#define to_ep_attribute(_attr) \
+	container_of(_attr, struct ep_attribute, attr)
+
+#define usb_ep_attr(field, format_string)			\
+static ssize_t show_ep_##field(struct device *dev,		\
+			       struct device_attribute *attr,	\
+			       char *buf)			\
+{								\
+	struct ep_device *ep = to_ep_device(dev);		\
+	return sprintf(buf, format_string, ep->desc->field);	\
+}								\
+static DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL);
+
+usb_ep_attr(bLength, "%02x\n")
+usb_ep_attr(bEndpointAddress, "%02x\n")
+usb_ep_attr(bmAttributes, "%02x\n")
+usb_ep_attr(bInterval, "%02x\n")
+
+static ssize_t show_ep_wMaxPacketSize(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct ep_device *ep = to_ep_device(dev);
+	return sprintf(buf, "%04x\n",
+			le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff);
+}
+static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL);
+
+static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct ep_device *ep = to_ep_device(dev);
+	char *type = "unknown";
+
+	switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		type = "Control";
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		type = "Isoc";
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		type = "Bulk";
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		type = "Interrupt";
+		break;
+	}
+	return sprintf(buf, "%s\n", type);
+}
+static DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL);
+
+static ssize_t show_ep_interval(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ep_device *ep = to_ep_device(dev);
+	char unit;
+	unsigned interval = 0;
+	unsigned in;
+
+	in = (ep->desc->bEndpointAddress & USB_DIR_IN);
+
+	switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+	case USB_ENDPOINT_XFER_CONTROL:
+		if (ep->udev->speed == USB_SPEED_HIGH) 	/* uframes per NAK */
+			interval = ep->desc->bInterval;
+		break;
+	case USB_ENDPOINT_XFER_ISOC:
+		interval = 1 << (ep->desc->bInterval - 1);
+		break;
+	case USB_ENDPOINT_XFER_BULK:
+		if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
+			interval = ep->desc->bInterval;
+		break;
+	case USB_ENDPOINT_XFER_INT:
+		if (ep->udev->speed == USB_SPEED_HIGH)
+			interval = 1 << (ep->desc->bInterval - 1);
+		else
+			interval = ep->desc->bInterval;
+		break;
+	}
+	interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
+	if (interval % 1000)
+		unit = 'u';
+	else {
+		unit = 'm';
+		interval /= 1000;
+	}
+
+	return sprintf(buf, "%d%cs\n", interval, unit);
+}
+static DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL);
+
+static ssize_t show_ep_direction(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct ep_device *ep = to_ep_device(dev);
+	char *direction;
+
+	if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+			USB_ENDPOINT_XFER_CONTROL)
+		direction = "both";
+	else if (ep->desc->bEndpointAddress & USB_DIR_IN)
+		direction = "in";
+	else
+		direction = "out";
+	return sprintf(buf, "%s\n", direction);
+}
+static DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL);
+
+static struct attribute *ep_dev_attrs[] = {
+	&dev_attr_bLength.attr,
+	&dev_attr_bEndpointAddress.attr,
+	&dev_attr_bmAttributes.attr,
+	&dev_attr_bInterval.attr,
+	&dev_attr_wMaxPacketSize.attr,
+	&dev_attr_interval.attr,
+	&dev_attr_type.attr,
+	&dev_attr_direction.attr,
+	NULL,
+};
+static struct attribute_group ep_dev_attr_grp = {
+	.attrs = ep_dev_attrs,
+};
+
+static struct endpoint_class {
+	struct kref kref;
+	struct class *class;
+} *ep_class;
+
+static int init_endpoint_class(void)
+{
+	int result = 0;
+
+	if (ep_class != NULL) {
+		kref_get(&ep_class->kref);
+		goto exit;
+	}
+
+	ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL);
+	if (!ep_class) {
+		result = -ENOMEM;
+		goto exit;
+	}
+
+	kref_init(&ep_class->kref);
+	ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
+	if (IS_ERR(ep_class->class)) {
+		result = IS_ERR(ep_class->class);
+		kfree(ep_class);
+		ep_class = NULL;
+		goto exit;
+	}
+
+exit:
+	return result;
+}
+
+static void release_endpoint_class(struct kref *kref)
+{
+	/* Ok, we cheat as we know we only have one ep_class */
+	class_destroy(ep_class->class);
+	kfree(ep_class);
+	ep_class = NULL;
+}
+
+static void destroy_endpoint_class(void)
+{
+	if (ep_class)
+		kref_put(&ep_class->kref, release_endpoint_class);
+}
+
+static void ep_device_release(struct device *dev)
+{
+	struct ep_device *ep_dev = to_ep_device(dev);
+
+	dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id);
+	kfree(ep_dev);
+}
+
+void usb_create_ep_files(struct device *parent,
+			 struct usb_host_endpoint *endpoint,
+			 struct usb_device *udev)
+{
+	char name[8];
+	struct ep_device *ep_dev;
+	int minor;
+	int retval;
+
+	retval = init_endpoint_class();
+	if (retval)
+		goto exit;
+
+	ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
+	if (!ep_dev) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
+	/* fun calculation to determine the minor of this endpoint */
+	minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1);
+
+	ep_dev->desc = &endpoint->desc;
+	ep_dev->udev = udev;
+	ep_dev->dev.devt = MKDEV(442, minor);	// FIXME fake number...
+	ep_dev->dev.class = ep_class->class;
+	ep_dev->dev.parent = parent;
+	ep_dev->dev.release = ep_device_release;
+	snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x",
+		 udev->bus->busnum, udev->devnum,
+		 endpoint->desc.bEndpointAddress);
+
+	retval = device_register(&ep_dev->dev);
+	if (retval)
+		goto error;
+	sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+
+	endpoint->ep_dev = ep_dev;
+
+	/* create the symlink to the old-style "ep_XX" directory */
+	sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
+	sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name);
+
+exit:
+	return;
+error:
+	kfree(ep_dev);
+	return;
+}
+
+void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
+{
+
+	if (endpoint->ep_dev) {
+		char name[8];
+
+		sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
+		sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name);
+		sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
+		device_unregister(&endpoint->ep_dev->dev);
+		endpoint->ep_dev = NULL;
+	}
+	destroy_endpoint_class();
+}
+
+
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index b263a54..f65b193c 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -61,33 +61,66 @@
 	.open =		usb_open,
 };
 
-static struct class *usb_class;
+static struct usb_class {
+	struct kref kref;
+	struct class *class;
+} *usb_class;
+
+static int init_usb_class(void)
+{
+	int result = 0;
+
+	if (usb_class != NULL) {
+		kref_get(&usb_class->kref);
+		goto exit;
+	}
+
+	usb_class = kmalloc(sizeof(*usb_class), GFP_KERNEL);
+	if (!usb_class) {
+		result = -ENOMEM;
+		goto exit;
+	}
+
+	kref_init(&usb_class->kref);
+	usb_class->class = class_create(THIS_MODULE, "usb");
+	if (IS_ERR(usb_class->class)) {
+		result = IS_ERR(usb_class->class);
+		err("class_create failed for usb devices");
+		kfree(usb_class);
+		usb_class = NULL;
+	}
+
+exit:
+	return result;
+}
+
+static void release_usb_class(struct kref *kref)
+{
+	/* Ok, we cheat as we know we only have one usb_class */
+	class_destroy(usb_class->class);
+	kfree(usb_class);
+	usb_class = NULL;
+}
+
+static void destroy_usb_class(void)
+{
+	if (usb_class)
+		kref_put(&usb_class->kref, release_usb_class);
+}
 
 int usb_major_init(void)
 {
 	int error;
 
 	error = register_chrdev(USB_MAJOR, "usb", &usb_fops);
-	if (error) {
+	if (error)
 		err("unable to get major %d for usb devices", USB_MAJOR);
-		goto out;
-	}
 
-	usb_class = class_create(THIS_MODULE, "usb");
-	if (IS_ERR(usb_class)) {
-		error = PTR_ERR(usb_class);
-		err("class_create failed for usb devices");
-		unregister_chrdev(USB_MAJOR, "usb");
-		goto out;
-	}
-
-out:
 	return error;
 }
 
 void usb_major_cleanup(void)
 {
-	class_destroy(usb_class);
 	unregister_chrdev(USB_MAJOR, "usb");
 }
 
@@ -149,6 +182,10 @@
 	if (retval)
 		goto exit;
 
+	retval = init_usb_class();
+	if (retval)
+		goto exit;
+
 	intf->minor = minor;
 
 	/* create a usb class device for this usb interface */
@@ -158,14 +195,13 @@
 		++temp;
 	else
 		temp = name;
-	intf->class_dev = class_device_create(usb_class, NULL,
-					      MKDEV(USB_MAJOR, minor),
-					      &intf->dev, "%s", temp);
-	if (IS_ERR(intf->class_dev)) {
+	intf->usb_dev = device_create(usb_class->class, &intf->dev,
+				      MKDEV(USB_MAJOR, minor), "%s", temp);
+	if (IS_ERR(intf->usb_dev)) {
 		spin_lock (&minor_lock);
 		usb_minors[intf->minor] = NULL;
 		spin_unlock (&minor_lock);
-		retval = PTR_ERR(intf->class_dev);
+		retval = PTR_ERR(intf->usb_dev);
 	}
 exit:
 	return retval;
@@ -206,9 +242,10 @@
 	spin_unlock (&minor_lock);
 
 	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
-	class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));
-	intf->class_dev = NULL;
+	device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
+	intf->usb_dev = NULL;
 	intf->minor = -1;
+	destroy_usb_class();
 }
 EXPORT_SYMBOL(usb_deregister_dev);
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e2e00ba..4bf914d 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1826,24 +1826,16 @@
 
 	/* enable irqs just before we start the controller */
 	if (hcd->driver->irq) {
-		char	buf[8], *bufp = buf;
-
-#ifdef __sparc__
-		bufp = __irq_itoa(irqnum);
-#else
-		sprintf(buf, "%d", irqnum);
-#endif
-
 		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
 				hcd->driver->description, hcd->self.busnum);
 		if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
 				hcd->irq_descr, hcd)) != 0) {
 			dev_err(hcd->self.controller,
-					"request interrupt %s failed\n", bufp);
+					"request interrupt %d failed\n", irqnum);
 			goto err_request_irq;
 		}
 		hcd->irq = irqnum;
-		dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
+		dev_info(hcd->self.controller, "irq %d, %s 0x%08llx\n", irqnum,
 				(hcd->driver->flags & HCD_MEMORY) ?
 					"io mem" : "io base",
 					(unsigned long long)hcd->rsrc_start);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 90b8d43..e1731ff 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -432,15 +432,22 @@
 {
 	int port1;
 	unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
-	u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics);
+	u16 wHubCharacteristics =
+			le16_to_cpu(hub->descriptor->wHubCharacteristics);
 
-	/* if hub supports power switching, enable power on each port */
-	if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
+	/* Enable power on each port.  Some hubs have reserved values
+	 * of LPSM (> 2) in their descriptors, even though they are
+	 * USB 2.0 hubs.  Some hubs do not implement port-power switching
+	 * but only emulate it.  In all cases, the ports won't work
+	 * unless we send these messages to the hub.
+	 */
+	if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2)
 		dev_dbg(hub->intfdev, "enabling power on all ports\n");
-		for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
-			set_port_feature(hub->hdev, port1,
-					USB_PORT_FEAT_POWER);
-	}
+	else
+		dev_dbg(hub->intfdev, "trying to enable port power on "
+				"non-switchable hub\n");
+	for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
+		set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
 
 	/* Wait at least 100 msec for power to become stable */
 	msleep(max(pgood_delay, (unsigned) 100));
@@ -518,15 +525,16 @@
 
 
 /* caller has locked the hub device */
-static void hub_pre_reset(struct usb_hub *hub, int disable_ports)
+static void hub_pre_reset(struct usb_interface *intf)
 {
+	struct usb_hub *hub = usb_get_intfdata(intf);
 	struct usb_device *hdev = hub->hdev;
 	int port1;
 
 	for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
 		if (hdev->children[port1 - 1]) {
 			usb_disconnect(&hdev->children[port1 - 1]);
-			if (disable_ports)
+			if (hub->error == 0)
 				hub_port_disable(hub, port1, 0);
 		}
 	}
@@ -534,8 +542,10 @@
 }
 
 /* caller has locked the hub device */
-static void hub_post_reset(struct usb_hub *hub)
+static void hub_post_reset(struct usb_interface *intf)
 {
+	struct usb_hub *hub = usb_get_intfdata(intf);
+
 	hub_activate(hub);
 	hub_power_on(hub);
 }
@@ -795,15 +805,16 @@
 	struct usb_hub *hub = usb_get_intfdata (intf);
 	struct usb_device *hdev;
 
+	/* Disconnect all children and quiesce the hub */
+	hub->error = 0;
+	hub_pre_reset(intf);
+
 	usb_set_intfdata (intf, NULL);
 	hdev = hub->hdev;
 
 	if (hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs--;
 
-	/* Disconnect all children and quiesce the hub */
-	hub_pre_reset(hub, 1);
-
 	usb_free_urb(hub->urb);
 	hub->urb = NULL;
 
@@ -1169,6 +1180,7 @@
 {
 	int i;
 	int num_configs;
+	int insufficient_power = 0;
 	struct usb_host_config *c, *best;
 
 	best = NULL;
@@ -1221,8 +1233,10 @@
 		 */
 
 		/* Rule out configs that draw too much bus current */
-		if (c->desc.bMaxPower * 2 > udev->bus_mA)
+		if (c->desc.bMaxPower * 2 > udev->bus_mA) {
+			insufficient_power++;
 			continue;
+		}
 
 		/* If the first config's first interface is COMM/2/0xff
 		 * (MSFT RNDIS), rule it out unless Linux has host-side
@@ -1231,7 +1245,7 @@
 				&& desc->bInterfaceClass == USB_CLASS_COMM
 				&& desc->bInterfaceSubClass == 2
 				&& desc->bInterfaceProtocol == 0xff) {
-#ifndef CONFIG_USB_NET_RNDIS
+#ifndef CONFIG_USB_NET_RNDIS_HOST
 			continue;
 #else
 			best = c;
@@ -1256,6 +1270,11 @@
 			best = c;
 	}
 
+	if (insufficient_power > 0)
+		dev_info(&udev->dev, "rejected %d configuration%s "
+			"due to insufficient available bus power\n",
+			insufficient_power, plural(insufficient_power));
+
 	if (best) {
 		i = best->desc.bConfigurationValue;
 		dev_info(&udev->dev,
@@ -2732,7 +2751,8 @@
 
 		/* If the hub has died, clean up after it */
 		if (hdev->state == USB_STATE_NOTATTACHED) {
-			hub_pre_reset(hub, 0);
+			hub->error = -ENODEV;
+			hub_pre_reset(intf);
 			goto loop;
 		}
 
@@ -2744,7 +2764,7 @@
 			dev_dbg (hub_dev, "resetting for error %d\n",
 				hub->error);
 
-			ret = usb_reset_device(hdev);
+			ret = usb_reset_composite_device(hdev, intf);
 			if (ret) {
 				dev_dbg (hub_dev,
 					"error resetting hub: %d\n", ret);
@@ -2913,6 +2933,8 @@
 	.disconnect =	hub_disconnect,
 	.suspend =	hub_suspend,
 	.resume =	hub_resume,
+	.pre_reset =	hub_pre_reset,
+	.post_reset =	hub_post_reset,
 	.ioctl =	hub_ioctl,
 	.id_table =	hub_id_table,
 };
@@ -2992,9 +3014,9 @@
  * usb_reset_device - perform a USB port reset to reinitialize a device
  * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
  *
- * WARNING - don't reset any device unless drivers for all of its
- * interfaces are expecting that reset!  Maybe some driver->reset()
- * method should eventually help ensure sufficient cooperation.
+ * WARNING - don't use this routine to reset a composite device
+ * (one with multiple interfaces owned by separate drivers)!
+ * Use usb_reset_composite_device() instead.
  *
  * Do a port reset, reassign the device's address, and establish its
  * former operating configuration.  If the reset fails, or the device's
@@ -3018,7 +3040,6 @@
 	struct usb_device		*parent_hdev = udev->parent;
 	struct usb_hub			*parent_hub;
 	struct usb_device_descriptor	descriptor = udev->descriptor;
-	struct usb_hub			*hub = NULL;
 	int 				i, ret = 0;
 	int				port1 = udev->portnum;
 
@@ -3036,14 +3057,6 @@
 	}
 	parent_hub = hdev_to_hub(parent_hdev);
 
-	/* If we're resetting an active hub, take some special actions */
-	if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 &&
-			udev->actconfig->interface[0]->dev.driver ==
-				&hub_driver.driver &&
-			(hub = hdev_to_hub(udev)) != NULL) {
-		hub_pre_reset(hub, 0);
-	}
-
 	set_bit(port1, parent_hub->busy_bits);
 	for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
@@ -3102,11 +3115,87 @@
 	}
 
 done:
-	if (hub)
-		hub_post_reset(hub);
 	return 0;
  
 re_enumerate:
 	hub_port_logical_disconnect(parent_hub, port1);
 	return -ENODEV;
 }
+
+/**
+ * usb_reset_composite_device - warn interface drivers and perform a USB port reset
+ * @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
+ * @iface: interface bound to the driver making the request (optional)
+ *
+ * Warns all drivers bound to registered interfaces (using their pre_reset
+ * method), performs the port reset, and then lets the drivers know that
+ * the reset is over (using their post_reset method).
+ *
+ * Return value is the same as for usb_reset_device().
+ *
+ * The caller must own the device lock.  For example, it's safe to use
+ * this from a driver probe() routine after downloading new firmware.
+ * For calls that might not occur during probe(), drivers should lock
+ * the device using usb_lock_device_for_reset().
+ *
+ * The interface locks are acquired during the pre_reset stage and released
+ * during the post_reset stage.  However if iface is not NULL and is
+ * currently being probed, we assume that the caller already owns its
+ * lock.
+ */
+int usb_reset_composite_device(struct usb_device *udev,
+		struct usb_interface *iface)
+{
+	int ret;
+	struct usb_host_config *config = udev->actconfig;
+
+	if (udev->state == USB_STATE_NOTATTACHED ||
+			udev->state == USB_STATE_SUSPENDED) {
+		dev_dbg(&udev->dev, "device reset not allowed in state %d\n",
+				udev->state);
+		return -EINVAL;
+	}
+
+	if (iface && iface->condition != USB_INTERFACE_BINDING)
+		iface = NULL;
+
+	if (config) {
+		int i;
+		struct usb_interface *cintf;
+		struct usb_driver *drv;
+
+		for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+			cintf = config->interface[i];
+			if (cintf != iface)
+				down(&cintf->dev.sem);
+			if (device_is_registered(&cintf->dev) &&
+					cintf->dev.driver) {
+				drv = to_usb_driver(cintf->dev.driver);
+				if (drv->pre_reset)
+					(drv->pre_reset)(cintf);
+			}
+		}
+	}
+
+	ret = usb_reset_device(udev);
+
+	if (config) {
+		int i;
+		struct usb_interface *cintf;
+		struct usb_driver *drv;
+
+		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
+			cintf = config->interface[i];
+			if (device_is_registered(&cintf->dev) &&
+					cintf->dev.driver) {
+				drv = to_usb_driver(cintf->dev.driver);
+				if (drv->post_reset)
+					(drv->post_reset)(cintf);
+			}
+			if (cintf != iface)
+				up(&cintf->dev.sem);
+		}
+	}
+
+	return ret;
+}
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 3cf945c..bfc9b28 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -543,10 +543,10 @@
 
 /* --------------------------------------------------------------------- */
 
-static struct super_block *usb_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int usb_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, usbfs_fill_super);
+	return get_sb_single(fs_type, flags, data, usbfs_fill_super, mnt);
 }
 
 static struct file_system_type usb_fs_type = {
@@ -569,7 +569,7 @@
 	ignore_mount = 1;
 
 	/* create the devices special file */
-	retval = simple_pin_fs("usbfs", &usbfs_mount, &usbfs_mount_count);
+	retval = simple_pin_fs(&usb_fs_type, &usbfs_mount, &usbfs_mount_count);
 	if (retval) {
 		err ("Unable to get usbfs mount");
 		goto exit;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 08fb20f..8569600 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -158,6 +158,37 @@
 
 
 /**
+ * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
+ * @usb_dev: pointer to the usb device to send the message to
+ * @pipe: endpoint "pipe" to send the message to
+ * @data: pointer to the data to send
+ * @len: length in bytes of the data to send
+ * @actual_length: pointer to a location to put the actual length transferred in bytes
+ * @timeout: time in msecs to wait for the message to complete before
+ *	timing out (if 0 the wait is forever)
+ * Context: !in_interrupt ()
+ *
+ * This function sends a simple interrupt message to a specified endpoint and
+ * waits for the message to complete, or timeout.
+ *
+ * If successful, it returns 0, otherwise a negative error number.  The number
+ * of actual bytes transferred will be stored in the actual_length paramater.
+ *
+ * Don't use this function from within an interrupt context, like a bottom half
+ * handler.  If you need an asynchronous message, or need to send a message
+ * from within interrupt context, use usb_submit_urb() If a thread in your
+ * driver uses this call, make sure your disconnect() method can wait for it to
+ * complete.  Since you don't have a handle on the URB used, you can't cancel
+ * the request.
+ */
+int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
+		      void *data, int len, int *actual_length, int timeout)
+{
+	return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout);
+}
+EXPORT_SYMBOL_GPL(usb_interrupt_msg);
+
+/**
  *	usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
  *	@usb_dev: pointer to the usb device to send the message to
  *	@pipe: endpoint "pipe" to send the message to
@@ -1380,6 +1411,12 @@
 				return ret;
 			}
 		}
+
+		i = dev->bus_mA - cp->desc.bMaxPower * 2;
+		if (i < 0)
+			dev_warn(&dev->dev, "new config #%d exceeds power "
+					"limit by %dmA\n",
+					configuration, -i);
 	}
 
 	/* if it's already configured, clear out old state first.
@@ -1388,92 +1425,85 @@
 	if (dev->state != USB_STATE_ADDRESS)
 		usb_disable_device (dev, 1);	// Skip ep0
 
-	if (cp) {
-		i = dev->bus_mA - cp->desc.bMaxPower * 2;
-		if (i < 0)
-			dev_warn(&dev->dev, "new config #%d exceeds power "
-					"limit by %dmA\n",
-					configuration, -i);
-	}
-
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
-		goto free_interfaces;
+			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
+
+		/* All the old state is gone, so what else can we do?
+		 * The device is probably useless now anyway.
+		 */
+		cp = NULL;
+	}
 
 	dev->actconfig = cp;
-	if (!cp)
+	if (!cp) {
 		usb_set_device_state(dev, USB_STATE_ADDRESS);
-	else {
-		usb_set_device_state(dev, USB_STATE_CONFIGURED);
+		goto free_interfaces;
+	}
+	usb_set_device_state(dev, USB_STATE_CONFIGURED);
 
-		/* Initialize the new interface structures and the
-		 * hc/hcd/usbcore interface/endpoint state.
+	/* Initialize the new interface structures and the
+	 * hc/hcd/usbcore interface/endpoint state.
+	 */
+	for (i = 0; i < nintf; ++i) {
+		struct usb_interface_cache *intfc;
+		struct usb_interface *intf;
+		struct usb_host_interface *alt;
+
+		cp->interface[i] = intf = new_interfaces[i];
+		intfc = cp->intf_cache[i];
+		intf->altsetting = intfc->altsetting;
+		intf->num_altsetting = intfc->num_altsetting;
+		kref_get(&intfc->ref);
+
+		alt = usb_altnum_to_altsetting(intf, 0);
+
+		/* No altsetting 0?  We'll assume the first altsetting.
+		 * We could use a GetInterface call, but if a device is
+		 * so non-compliant that it doesn't have altsetting 0
+		 * then I wouldn't trust its reply anyway.
 		 */
-		for (i = 0; i < nintf; ++i) {
-			struct usb_interface_cache *intfc;
-			struct usb_interface *intf;
-			struct usb_host_interface *alt;
+		if (!alt)
+			alt = &intf->altsetting[0];
 
-			cp->interface[i] = intf = new_interfaces[i];
-			intfc = cp->intf_cache[i];
-			intf->altsetting = intfc->altsetting;
-			intf->num_altsetting = intfc->num_altsetting;
-			kref_get(&intfc->ref);
+		intf->cur_altsetting = alt;
+		usb_enable_interface(dev, intf);
+		intf->dev.parent = &dev->dev;
+		intf->dev.driver = NULL;
+		intf->dev.bus = &usb_bus_type;
+		intf->dev.dma_mask = dev->dev.dma_mask;
+		intf->dev.release = release_interface;
+		device_initialize (&intf->dev);
+		mark_quiesced(intf);
+		sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
+			 dev->bus->busnum, dev->devpath,
+			 configuration, alt->desc.bInterfaceNumber);
+	}
+	kfree(new_interfaces);
 
-			alt = usb_altnum_to_altsetting(intf, 0);
+	if (cp->string == NULL)
+		cp->string = usb_cache_string(dev, cp->desc.iConfiguration);
 
-			/* No altsetting 0?  We'll assume the first altsetting.
-			 * We could use a GetInterface call, but if a device is
-			 * so non-compliant that it doesn't have altsetting 0
-			 * then I wouldn't trust its reply anyway.
-			 */
-			if (!alt)
-				alt = &intf->altsetting[0];
+	/* Now that all the interfaces are set up, register them
+	 * to trigger binding of drivers to interfaces.  probe()
+	 * routines may install different altsettings and may
+	 * claim() any interfaces not yet bound.  Many class drivers
+	 * need that: CDC, audio, video, etc.
+	 */
+	for (i = 0; i < nintf; ++i) {
+		struct usb_interface *intf = cp->interface[i];
 
-			intf->cur_altsetting = alt;
-			usb_enable_interface(dev, intf);
-			intf->dev.parent = &dev->dev;
-			intf->dev.driver = NULL;
-			intf->dev.bus = &usb_bus_type;
-			intf->dev.dma_mask = dev->dev.dma_mask;
-			intf->dev.release = release_interface;
-			device_initialize (&intf->dev);
-			mark_quiesced(intf);
-			sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
-				 dev->bus->busnum, dev->devpath,
-				 configuration,
-				 alt->desc.bInterfaceNumber);
+		dev_dbg (&dev->dev,
+			"adding %s (config #%d, interface %d)\n",
+			intf->dev.bus_id, configuration,
+			intf->cur_altsetting->desc.bInterfaceNumber);
+		ret = device_add (&intf->dev);
+		if (ret != 0) {
+			dev_err(&dev->dev, "device_add(%s) --> %d\n",
+				intf->dev.bus_id, ret);
+			continue;
 		}
-		kfree(new_interfaces);
-
-		if (cp->string == NULL)
-			cp->string = usb_cache_string(dev,
-					cp->desc.iConfiguration);
-
-		/* Now that all the interfaces are set up, register them
-		 * to trigger binding of drivers to interfaces.  probe()
-		 * routines may install different altsettings and may
-		 * claim() any interfaces not yet bound.  Many class drivers
-		 * need that: CDC, audio, video, etc.
-		 */
-		for (i = 0; i < nintf; ++i) {
-			struct usb_interface *intf = cp->interface[i];
-
-			dev_dbg (&dev->dev,
-				"adding %s (config #%d, interface %d)\n",
-				intf->dev.bus_id, configuration,
-				intf->cur_altsetting->desc.bInterfaceNumber);
-			ret = device_add (&intf->dev);
-			if (ret != 0) {
-				dev_err(&dev->dev,
-					"device_add(%s) --> %d\n",
-					intf->dev.bus_id,
-					ret);
-				continue;
-			}
-			usb_create_sysfs_intf_files (intf);
-		}
+		usb_create_sysfs_intf_files (intf);
 	}
 
 	return 0;
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 71d8813..3f49bf5 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -15,203 +15,6 @@
 #include <linux/usb.h>
 #include "usb.h"
 
-/* endpoint stuff */
-struct ep_object {
-	struct usb_endpoint_descriptor *desc;
-	struct usb_device *udev;
-	struct kobject kobj;
-};
-#define to_ep_object(_kobj) \
-	container_of(_kobj, struct ep_object, kobj)
-
-struct ep_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct usb_device *,
-			struct usb_endpoint_descriptor *, char *);
-};
-#define to_ep_attribute(_attr) \
-	container_of(_attr, struct ep_attribute, attr)
-
-#define EP_ATTR(_name)						\
-struct ep_attribute ep_##_name = {				\
-	.attr = {.name = #_name, .owner = THIS_MODULE,		\
-			.mode = S_IRUGO},			\
-	.show = show_ep_##_name}
-
-#define usb_ep_attr(field, format_string)			\
-static ssize_t show_ep_##field(struct usb_device *udev,		\
-		struct usb_endpoint_descriptor *desc, 		\
-		char *buf)					\
-{								\
-	return sprintf(buf, format_string, desc->field);	\
-}								\
-static EP_ATTR(field);
-
-usb_ep_attr(bLength, "%02x\n")
-usb_ep_attr(bEndpointAddress, "%02x\n")
-usb_ep_attr(bmAttributes, "%02x\n")
-usb_ep_attr(bInterval, "%02x\n")
-
-static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
-		struct usb_endpoint_descriptor *desc, char *buf)
-{
-	return sprintf(buf, "%04x\n",
-			le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
-}
-static EP_ATTR(wMaxPacketSize);
-
-static ssize_t show_ep_type(struct usb_device *udev,
-		struct usb_endpoint_descriptor *desc, char *buf)
-{
-	char *type = "unknown";
-
-	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-	case USB_ENDPOINT_XFER_CONTROL:
-		type = "Control";
-		break;
-	case USB_ENDPOINT_XFER_ISOC:
-		type = "Isoc";
-		break;
-	case USB_ENDPOINT_XFER_BULK:
-		type = "Bulk";
-		break;
-	case USB_ENDPOINT_XFER_INT:
-		type = "Interrupt";
-		break;
-	}
-	return sprintf(buf, "%s\n", type);
-}
-static EP_ATTR(type);
-
-static ssize_t show_ep_interval(struct usb_device *udev,
-		struct usb_endpoint_descriptor *desc, char *buf)
-{
-	char unit;
-	unsigned interval = 0;
-	unsigned in;
-
-	in = (desc->bEndpointAddress & USB_DIR_IN);
-
-	switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
-	case USB_ENDPOINT_XFER_CONTROL:
-		if (udev->speed == USB_SPEED_HIGH) 	/* uframes per NAK */
-			interval = desc->bInterval;
-		break;
-	case USB_ENDPOINT_XFER_ISOC:
-		interval = 1 << (desc->bInterval - 1);
-		break;
-	case USB_ENDPOINT_XFER_BULK:
-		if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
-			interval = desc->bInterval;
-		break;
-	case USB_ENDPOINT_XFER_INT:
-		if (udev->speed == USB_SPEED_HIGH)
-			interval = 1 << (desc->bInterval - 1);
-		else
-			interval = desc->bInterval;
-		break;
-	}
-	interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
-	if (interval % 1000)
-		unit = 'u';
-	else {
-		unit = 'm';
-		interval /= 1000;
-	}
-
-	return sprintf(buf, "%d%cs\n", interval, unit);
-}
-static EP_ATTR(interval);
-
-static ssize_t show_ep_direction(struct usb_device *udev,
-		struct usb_endpoint_descriptor *desc, char *buf)
-{
-	char *direction;
-
-	if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-			USB_ENDPOINT_XFER_CONTROL)
-		direction = "both";
-	else if (desc->bEndpointAddress & USB_DIR_IN)
-		direction = "in";
-	else
-		direction = "out";
-	return sprintf(buf, "%s\n", direction);
-}
-static EP_ATTR(direction);
-
-static struct attribute *ep_attrs[] = {
-	&ep_bLength.attr,
-	&ep_bEndpointAddress.attr,
-	&ep_bmAttributes.attr,
-	&ep_bInterval.attr,
-	&ep_wMaxPacketSize.attr,
-	&ep_type.attr,
-	&ep_interval.attr,
-	&ep_direction.attr,
-	NULL,
-};
-
-static void ep_object_release(struct kobject *kobj)
-{
-	kfree(to_ep_object(kobj));
-}
-
-static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr,
-		char *buf)
-{
-	struct ep_object *ep_obj = to_ep_object(kobj);
-	struct ep_attribute *ep_attr = to_ep_attribute(attr);
-
-	return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf);
-}
-
-static struct sysfs_ops ep_object_sysfs_ops = {
-	.show =			ep_object_show,
-};
-
-static struct kobj_type ep_object_ktype = {
-	.release =		ep_object_release,
-	.sysfs_ops =		&ep_object_sysfs_ops,
-	.default_attrs =	ep_attrs,
-};
-
-static void usb_create_ep_files(struct kobject *parent,
-		struct usb_host_endpoint *endpoint,
-		struct usb_device *udev)
-{
-	struct ep_object *ep_obj;
-	struct kobject *kobj;
-
-	ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL);
-	if (!ep_obj)
-		return;
-
-	ep_obj->desc = &endpoint->desc;
-	ep_obj->udev = udev;
-
-	kobj = &ep_obj->kobj;
-	kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress);
-	kobj->parent = parent;
-	kobj->ktype = &ep_object_ktype;
-
-	/* Don't use kobject_register, because it generates a hotplug event */
-	kobject_init(kobj);
-	if (kobject_add(kobj) == 0)
-		endpoint->kobj = kobj;
-	else
-		kobject_put(kobj);
-}
-
-static void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
-{
-
-	if (endpoint->kobj) {
-		kobject_del(endpoint->kobj);
-		kobject_put(endpoint->kobj);
-		endpoint->kobj = NULL;
-	}
-}
-
 /* Active configuration fields */
 #define usb_actconfig_show(field, multiplier, format_string)		\
 static ssize_t  show_##field (struct device *dev,			\
@@ -420,7 +223,7 @@
 	if (udev->serial)
 		device_create_file (dev, &dev_attr_serial);
 	device_create_file (dev, &dev_attr_configuration);
-	usb_create_ep_files(&dev->kobj, &udev->ep0, udev);
+	usb_create_ep_files(dev, &udev->ep0, udev);
 }
 
 void usb_remove_sysfs_dev_files (struct usb_device *udev)
@@ -524,7 +327,7 @@
 
 	iface_desc = intf->cur_altsetting;
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
-		usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
+		usb_create_ep_files(&intf->dev, &iface_desc->endpoint[i],
 				udev);
 }
 
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index b7fdc1c..fb488c8 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -991,6 +991,8 @@
 
 static int verify_suspended(struct device *dev, void *unused)
 {
+	if (dev->driver == NULL)
+		return 0;
 	return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
 }
 
@@ -1207,6 +1209,7 @@
 EXPORT_SYMBOL(usb_altnum_to_altsetting);
 
 EXPORT_SYMBOL(usb_reset_device);
+EXPORT_SYMBOL(usb_reset_composite_device);
 
 EXPORT_SYMBOL(__usb_get_extra_descriptor);
 
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 4647e1e..7a650c7 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -4,6 +4,9 @@
 extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
 extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
 extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
+extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
+				struct usb_device *udev);
+extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
 
 extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr);
 extern void usb_disable_interface (struct usb_device *dev,
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
index 9c4422a..078daa0 100644
--- a/drivers/usb/gadget/ether.c
+++ b/drivers/usb/gadget/ether.c
@@ -49,7 +49,7 @@
 #include <asm/unaligned.h>
 
 #include <linux/usb_ch9.h>
-#include <linux/usb_cdc.h>
+#include <linux/usb/cdc.h>
 #include <linux/usb_gadget.h>
 
 #include <linux/random.h>
@@ -101,9 +101,9 @@
 
 /* CDC and RNDIS support the same host-chosen outgoing packet filters. */
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
- 			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
- 			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
- 			|USB_CDC_PACKET_TYPE_DIRECTED)
+			|USB_CDC_PACKET_TYPE_ALL_MULTICAST \
+			|USB_CDC_PACKET_TYPE_PROMISCUOUS \
+			|USB_CDC_PACKET_TYPE_DIRECTED)
 
 
 /*-------------------------------------------------------------------------*/
@@ -318,7 +318,7 @@
 #define DEFAULT_QLEN	2	/* double buffering by default */
 
 /* peak bulk transfer bits-per-second */
-#define	HS_BPS 		(13 * 512 * 8 * 1000 * 8)
+#define	HS_BPS		(13 * 512 * 8 * 1000 * 8)
 #define	FS_BPS		(19 *  64 * 1 * 1000 * 8)
 
 #ifdef CONFIG_USB_GADGET_DUALSPEED
@@ -466,7 +466,7 @@
 };
 
 #ifdef	CONFIG_USB_ETH_RNDIS
-static struct usb_config_descriptor 
+static struct usb_config_descriptor
 rndis_config = {
 	.bLength =              sizeof rndis_config,
 	.bDescriptorType =      USB_DT_CONFIG,
@@ -511,7 +511,7 @@
 rndis_control_intf = {
 	.bLength =              sizeof rndis_control_intf,
 	.bDescriptorType =      USB_DT_INTERFACE,
-	  
+
 	.bInterfaceNumber =     0,
 	.bNumEndpoints =        1,
 	.bInterfaceClass =      USB_CLASS_COMM,
@@ -545,20 +545,20 @@
 #ifdef	CONFIG_USB_ETH_RNDIS
 
 static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
-	.bLength =  		sizeof call_mgmt_descriptor,
-	.bDescriptorType = 	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType = 	USB_CDC_CALL_MANAGEMENT_TYPE,
+	.bLength =		sizeof call_mgmt_descriptor,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
 
-	.bmCapabilities = 	0x00,
-	.bDataInterface = 	0x01,
+	.bmCapabilities =	0x00,
+	.bDataInterface =	0x01,
 };
 
 static const struct usb_cdc_acm_descriptor acm_descriptor = {
-	.bLength =  		sizeof acm_descriptor,
-	.bDescriptorType = 	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType = 	USB_CDC_ACM_TYPE,
+	.bLength =		sizeof acm_descriptor,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
 
-	.bmCapabilities = 	0x00,
+	.bmCapabilities =	0x00,
 };
 
 #endif
@@ -595,7 +595,7 @@
  * RNDIS requires the status endpoint, since it uses that encapsulation
  * mechanism for its funky RPC scheme.
  */
- 
+
 #define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
 #define STATUS_BYTECOUNT		16	/* 8 byte header + data */
 
@@ -978,7 +978,7 @@
 
 		result = usb_ep_enable (dev->status_ep, dev->status);
 		if (result != 0) {
-			DEBUG (dev, "enable %s --> %d\n", 
+			DEBUG (dev, "enable %s --> %d\n",
 				dev->status_ep->name, result);
 			goto done;
 		}
@@ -1002,15 +1002,15 @@
 	if (!cdc_active(dev)) {
 		result = usb_ep_enable (dev->in_ep, dev->in);
 		if (result != 0) {
-			DEBUG(dev, "enable %s --> %d\n", 
+			DEBUG(dev, "enable %s --> %d\n",
 				dev->in_ep->name, result);
 			goto done;
 		}
 
 		result = usb_ep_enable (dev->out_ep, dev->out);
 		if (result != 0) {
-			DEBUG (dev, "enable %s --> %d\n", 
-				dev->in_ep->name, result);
+			DEBUG (dev, "enable %s --> %d\n",
+				dev->out_ep->name, result);
 			goto done;
 		}
 	}
@@ -1144,7 +1144,7 @@
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_SPEED_HIGH:	speed = "high"; break;
 #endif
-		default: 		speed = "?"; break;
+		default:		speed = "?"; break;
 		}
 
 		dev->config = number;
@@ -1206,7 +1206,7 @@
 	struct usb_request		*req = dev->stat_req;
 	struct usb_cdc_notification	*event;
 	int				value;
- 
+
 	DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
 
 	/* flush old status
@@ -1268,7 +1268,7 @@
 {
 	struct eth_dev          *dev = ep->driver_data;
 	int			status;
-	
+
 	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
 	spin_lock(&dev->lock);
 	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
@@ -1472,7 +1472,7 @@
 
 #endif /* DEV_CONFIG_CDC */
 
-#ifdef CONFIG_USB_ETH_RNDIS		
+#ifdef CONFIG_USB_ETH_RNDIS
 	/* RNDIS uses the CDC command encapsulation mechanism to implement
 	 * an RPC scheme, with much getting/setting of attributes by OID.
 	 */
@@ -1489,7 +1489,7 @@
 		req->complete = rndis_command_complete;
 		/* later, rndis_control_ack () sends a notification */
 		break;
-		
+
 	case USB_CDC_GET_ENCAPSULATED_RESPONSE:
 		if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
 					== ctrl->bRequestType
@@ -1641,7 +1641,7 @@
 		DEBUG (dev, "no rx skb\n");
 		goto enomem;
 	}
-	
+
 	/* Some platforms perform better when IP packets are aligned,
 	 * but on at least one, checksumming fails otherwise.  Note:
 	 * RNDIS headers involve variable numbers of LE32 values.
@@ -1720,7 +1720,7 @@
 	case -EOVERFLOW:
 		dev->stats.rx_over_errors++;
 		// FALLTHROUGH
-	    
+
 	default:
 		dev->stats.rx_errors++;
 		DEBUG (dev, "rx status %d\n", status);
@@ -1915,7 +1915,7 @@
 				sizeof (struct rndis_packet_msg_type));
 		if (!skb_rndis)
 			goto drop;
-	
+
 		dev_kfree_skb_any (skb);
 		skb = skb_rndis;
 		rndis_add_hdr (skb);
@@ -2001,7 +2001,7 @@
 	struct eth_dev          *dev = netdev_priv(net);
 	u32                     length;
 	struct usb_request      *resp = dev->stat_req;
-	
+
 	/* in case RNDIS calls this after disconnect */
 	if (!dev->status) {
 		DEBUG (dev, "status ENODEV\n");
@@ -2021,16 +2021,16 @@
 	resp->length = 8;
 	resp->complete = rndis_control_ack_complete;
 	resp->context = dev;
-	
+
 	*((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
 	*((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
-	
+
 	length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
 	if (length < 0) {
 		resp->status = 0;
 		rndis_control_ack_complete (dev->status_ep, resp);
 	}
-	
+
 	return 0;
 }
 
@@ -2047,7 +2047,7 @@
 	/* fill the rx queue */
 	rx_fill (dev, gfp_flags);
 
-	/* and open the tx floodgates */ 
+	/* and open the tx floodgates */
 	atomic_set (&dev->tx_qlen, 0);
 	netif_wake_queue (dev->net);
 	if (rndis_active(dev)) {
@@ -2076,7 +2076,7 @@
 	netif_stop_queue (net);
 
 	DEBUG (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n",
-		dev->stats.rx_packets, dev->stats.tx_packets, 
+		dev->stats.rx_packets, dev->stats.tx_packets,
 		dev->stats.rx_errors, dev->stats.tx_errors
 		);
 
@@ -2095,7 +2095,7 @@
 			usb_ep_enable (dev->status_ep, dev->status);
 		}
 	}
-	
+
 	if (rndis_active(dev)) {
 		rndis_set_param_medium (dev->rndis_config,
 					NDIS_MEDIUM_802_3, 0);
@@ -2301,7 +2301,7 @@
 		return -ENODEV;
 	}
 	in_ep->driver_data = in_ep;	/* claim */
-	
+
 	out_ep = usb_ep_autoconfig (gadget, &fs_sink_desc);
 	if (!out_ep)
 		goto autoconf_fail;
@@ -2374,8 +2374,8 @@
 #endif
 	}
 
- 	net = alloc_etherdev (sizeof *dev);
- 	if (!net)
+	net = alloc_etherdev (sizeof *dev);
+	if (!net)
 		return status;
 	dev = netdev_priv(net);
 	spin_lock_init (&dev->lock);
@@ -2454,7 +2454,7 @@
 	dev->gadget = gadget;
 	set_gadget_data (gadget, dev);
 	gadget->ep0->driver_data = dev;
-	
+
 	/* two kinds of host-initiated state changes:
 	 *  - iff DATA transfer is active, carrier is "on"
 	 *  - tx queueing enabled if open *and* carrier is "on"
@@ -2462,8 +2462,8 @@
 	netif_stop_queue (dev->net);
 	netif_carrier_off (dev->net);
 
- 	SET_NETDEV_DEV (dev->net, &gadget->dev);
- 	status = register_netdev (dev->net);
+	SET_NETDEV_DEV (dev->net, &gadget->dev);
+	status = register_netdev (dev->net);
 	if (status < 0)
 		goto fail1;
 
@@ -2488,7 +2488,7 @@
 		u32	vendorID = 0;
 
 		/* FIXME RNDIS vendor id == "vendor NIC code" == ? */
-		
+
 		dev->rndis_config = rndis_register (rndis_control_ack);
 		if (dev->rndis_config < 0) {
 fail0:
@@ -2496,7 +2496,7 @@
 			status = -ENODEV;
 			goto fail;
 		}
-		
+
 		/* these set up a lot of the OIDs that RNDIS needs */
 		rndis_set_host_mac (dev->rndis_config, dev->host_mac);
 		if (rndis_set_param_dev (dev->rndis_config, dev->net,
@@ -2556,7 +2556,7 @@
 	.suspend	= eth_suspend,
 	.resume		= eth_resume,
 
-	.driver 	= {
+	.driver	= {
 		.name		= (char *) shortname,
 		.owner		= THIS_MODULE,
 	},
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 6f88747..a43dc90 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1906,7 +1906,6 @@
 
 	inode = filp->f_dentry->d_inode;
 	mutex_lock(&inode->i_mutex);
-	current->flags |= PF_SYNCWRITE;
 	rc = filemap_fdatawrite(inode->i_mapping);
 	err = filp->f_op->fsync(filp, filp->f_dentry, 1);
 	if (!rc)
@@ -1914,7 +1913,6 @@
 	err = filemap_fdatawait(inode->i_mapping);
 	if (!rc)
 		rc = err;
-	current->flags &= ~PF_SYNCWRITE;
 	mutex_unlock(&inode->i_mutex);
 	VLDBG(curlun, "fdatasync -> %d\n", rc);
 	return rc;
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 66b81bb..5378c17 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1850,7 +1850,6 @@
 	unsigned long		resource, len;
 	void __iomem		*base = NULL;
 	int			retval;
-	char			buf [8], *bufp;
 
 	/* if you want to support more than one controller in a system,
 	 * usb_gadget_driver_{register,unregister}() must change.
@@ -1913,20 +1912,14 @@
 	pci_set_drvdata(pdev, dev);
 	INFO(dev, "%s\n", driver_desc);
 	INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr());
-#ifndef __sparc__
-	scnprintf(buf, sizeof buf, "%d", pdev->irq);
-	bufp = buf;
-#else
-	bufp = __irq_itoa(pdev->irq);
-#endif
-	INFO(dev, "irq %s, pci mem %p\n", bufp, base);
+	INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base);
 
 	/* init to known state, then setup irqs */
 	udc_reset(dev);
 	udc_reinit (dev);
 	if (request_irq(pdev->irq, goku_irq, SA_SHIRQ/*|SA_SAMPLE_RANDOM*/,
 			driver_name, dev) != 0) {
-		DBG(dev, "request interrupt %s failed\n", bufp);
+		DBG(dev, "request interrupt %d failed\n", pdev->irq);
 		retval = -EBUSY;
 		goto done;
 	}
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 0eb010a..3bdc5e3 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -528,7 +528,7 @@
 	struct usb_request	*req;
 	struct ep_data		*epdata;
 	void			*buf;
-	char __user		*ubuf;
+	char __user		*ubuf;		/* NULL for writes */
 	unsigned		actual;
 };
 
@@ -566,7 +566,6 @@
 		status = priv->actual;
 	kfree(priv->buf);
 	kfree(priv);
-	aio_put_req(iocb);
 	return status;
 }
 
@@ -580,8 +579,8 @@
 	spin_lock(&epdata->dev->lock);
 	priv->req = NULL;
 	priv->epdata = NULL;
-	if (NULL == iocb->ki_retry
-			|| unlikely(0 == req->actual)
+	if (priv->ubuf == NULL
+			|| unlikely(req->actual == 0)
 			|| unlikely(kiocbIsCancelled(iocb))) {
 		kfree(req->buf);
 		kfree(priv);
@@ -618,7 +617,7 @@
 	char __user	*ubuf
 )
 {
-	struct kiocb_priv	*priv = (void *) &iocb->private;
+	struct kiocb_priv	*priv;
 	struct usb_request	*req;
 	ssize_t			value;
 
@@ -670,7 +669,7 @@
 		kfree(priv);
 		put_ep(epdata);
 	} else
-		value = -EIOCBQUEUED;
+		value = (ubuf ? -EIOCBRETRY : -EIOCBQUEUED);
 	return value;
 }
 
@@ -1039,7 +1038,7 @@
 		/* ep0 can't deliver events when STATE_SETUP */
 		for (i = 0; i < n; i++) {
 			if (dev->event [i].type == GADGETFS_SETUP) {
-				len = n = i + 1;
+				len = i + 1;
 				len *= sizeof (struct usb_gadgetfs_event);
 				n = 0;
 				break;
@@ -1587,13 +1586,13 @@
 static int activate_ep_files (struct dev_data *dev)
 {
 	struct usb_ep	*ep;
+	struct ep_data	*data;
 
 	gadget_for_each_ep (ep, dev->gadget) {
-		struct ep_data	*data;
 
 		data = kzalloc(sizeof(*data), GFP_KERNEL);
 		if (!data)
-			goto enomem;
+			goto enomem0;
 		data->state = STATE_EP_DISABLED;
 		init_MUTEX (&data->lock);
 		init_waitqueue_head (&data->wait);
@@ -1608,21 +1607,23 @@
 
 		data->req = usb_ep_alloc_request (ep, GFP_KERNEL);
 		if (!data->req)
-			goto enomem;
+			goto enomem1;
 
 		data->inode = gadgetfs_create_file (dev->sb, data->name,
 				data, &ep_config_operations,
 				&data->dentry);
-		if (!data->inode) {
-			usb_ep_free_request(ep, data->req);
-			kfree (data);
-			goto enomem;
-		}
+		if (!data->inode)
+			goto enomem2;
 		list_add_tail (&data->epfiles, &dev->epfiles);
 	}
 	return 0;
 
-enomem:
+enomem2:
+	usb_ep_free_request (ep, data->req);
+enomem1:
+	put_dev (dev);
+	kfree (data);
+enomem0:
 	DBG (dev, "%s enomem\n", __FUNCTION__);
 	destroy_ep_files (dev);
 	return -ENOMEM;
@@ -1793,7 +1794,7 @@
  *
  * After initialization, the device stays active for as long as that
  * $CHIP file is open.  Events may then be read from that descriptor,
- * such configuration notifications.  More complex drivers will handle
+ * such as configuration notifications.  More complex drivers will handle
  * some control requests in user space.
  */
 
@@ -2033,12 +2034,10 @@
 			NULL, &simple_dir_operations,
 			S_IFDIR | S_IRUGO | S_IXUGO);
 	if (!inode)
-		return -ENOMEM;
+		goto enomem0;
 	inode->i_op = &simple_dir_inode_operations;
-	if (!(d = d_alloc_root (inode))) {
-		iput (inode);
-		return -ENOMEM;
-	}
+	if (!(d = d_alloc_root (inode)))
+		goto enomem1;
 	sb->s_root = d;
 
 	/* the ep0 file is named after the controller we expect;
@@ -2046,29 +2045,36 @@
 	 */
 	dev = dev_new ();
 	if (!dev)
-		return -ENOMEM;
+		goto enomem2;
 
 	dev->sb = sb;
-	if (!(inode = gadgetfs_create_file (sb, CHIP,
+	if (!gadgetfs_create_file (sb, CHIP,
 				dev, &dev_init_operations,
-				&dev->dentry))) {
-		put_dev(dev);
-		return -ENOMEM;
-	}
+				&dev->dentry))
+		goto enomem3;
 
 	/* other endpoint files are available after hardware setup,
 	 * from binding to a controller.
 	 */
 	the_device = dev;
 	return 0;
+
+enomem3:
+	put_dev (dev);
+enomem2:
+	dput (d);
+enomem1:
+	iput (inode);
+enomem0:
+	return -ENOMEM;
 }
 
 /* "mount -t gadgetfs path /dev/gadget" ends up here */
-static struct super_block *
+static int
 gadgetfs_get_sb (struct file_system_type *t, int flags,
-		const char *path, void *opts)
+		const char *path, void *opts, struct vfsmount *mnt)
 {
-	return get_sb_single (t, flags, opts, gadgetfs_fill_super);
+	return get_sb_single (t, flags, opts, gadgetfs_fill_super, mnt);
 }
 
 static void
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 0b92934..1facdea 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2822,7 +2822,6 @@
 	unsigned long		resource, len;
 	void			__iomem *base = NULL;
 	int			retval, i;
-	char			buf [8], *bufp;
 
 	/* if you want to support more than one controller in a system,
 	 * usb_gadget_driver_{register,unregister}() must change.
@@ -2896,15 +2895,10 @@
 		retval = -ENODEV;
 		goto done;
 	}
-#ifndef __sparc__
-	scnprintf (buf, sizeof buf, "%d", pdev->irq);
-	bufp = buf;
-#else
-	bufp = __irq_itoa(pdev->irq);
-#endif
+
 	if (request_irq (pdev->irq, net2280_irq, SA_SHIRQ, driver_name, dev)
 			!= 0) {
-		ERROR (dev, "request interrupt %s failed\n", bufp);
+		ERROR (dev, "request interrupt %d failed\n", pdev->irq);
 		retval = -EBUSY;
 		goto done;
 	}
@@ -2953,8 +2947,8 @@
 
 	/* done */
 	INFO (dev, "%s\n", driver_desc);
-	INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
-			bufp, base, dev->chiprev);
+	INFO (dev, "irq %d, pci mem %p, chip rev %04x\n",
+			pdev->irq, base, dev->chiprev);
 	INFO (dev, "version: " DRIVER_VERSION "; dma %s\n",
 			use_dma
 				? (use_dma_chaining ? "chaining" : "enabled")
@@ -2972,6 +2966,22 @@
 	return retval;
 }
 
+/* make sure the board is quiescent; otherwise it will continue
+ * generating IRQs across the upcoming reboot.
+ */
+
+static void net2280_shutdown (struct pci_dev *pdev)
+{
+	struct net2280		*dev = pci_get_drvdata (pdev);
+
+	/* disable IRQs */
+	writel (0, &dev->regs->pciirqenb0);
+	writel (0, &dev->regs->pciirqenb1);
+
+	/* disable the pullup so the host will think we're gone */
+	writel (0, &dev->usb->usbctl);
+}
+
 
 /*-------------------------------------------------------------------------*/
 
@@ -3001,6 +3011,7 @@
 
 	.probe =	net2280_probe,
 	.remove =	net2280_remove,
+	.shutdown =	net2280_shutdown,
 
 	/* FIXME add power management support */
 };
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 680f7fc..269ce7f 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -53,12 +53,14 @@
 #include <asm/mach-types.h>
 #include <asm/unaligned.h>
 #include <asm/hardware.h>
+#ifdef CONFIG_ARCH_PXA
 #include <asm/arch/pxa-regs.h>
+#endif
 
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 
-#include <asm/arch/udc.h>
+#include <asm/arch/hardware/intel_udc.h>
 
 
 /*
@@ -545,6 +547,7 @@
 		count = req->req.length;
 		done (ep, req, 0);
 		ep0_idle(ep->dev);
+#ifndef CONFIG_ARCH_IXP4XX
 #if 1
 		/* This seems to get rid of lost status irqs in some cases:
 		 * host responds quickly, or next request involves config
@@ -565,6 +568,7 @@
 			} while (count);
 		}
 #endif
+#endif
 	} else if (ep->dev->req_pending)
 		ep0start(ep->dev, 0, "IN");
 	return is_short;
@@ -1585,7 +1589,7 @@
 	int			retval;
 
 	if (!driver
-			|| driver->speed != USB_SPEED_FULL
+			|| driver->speed < USB_SPEED_FULL
 			|| !driver->bind
 			|| !driver->unbind
 			|| !driver->disconnect
@@ -2427,6 +2431,7 @@
 #define PXA210_B1		0x00000123
 #define PXA210_B0		0x00000122
 #define IXP425_A0		0x000001c1
+#define IXP465_AD		0x00000200
 
 /*
  * 	probe - binds to the platform device
@@ -2463,6 +2468,8 @@
 		break;
 #elif	defined(CONFIG_ARCH_IXP4XX)
 	case IXP425_A0:
+	case IXP465_AD:
+		dev->has_cfr = 1;
 		out_dma = 0;
 		break;
 #endif
@@ -2575,10 +2582,12 @@
 		free_irq(IRQ_USB, dev);
 		dev->got_irq = 0;
 	}
+#ifdef CONFIG_ARCH_LUBBOCK
 	if (machine_is_lubbock()) {
 		free_irq(LUBBOCK_USB_DISC_IRQ, dev);
 		free_irq(LUBBOCK_USB_IRQ, dev);
 	}
+#endif
 	platform_set_drvdata(pdev, NULL);
 	the_controller = NULL;
 	return 0;
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 6d6eaad..3ff6db7 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -1,23 +1,23 @@
-/* 
+/*
  * RNDIS MSG parser
- * 
+ *
  * Version:     $Id: rndis.c,v 1.19 2004/03/25 21:33:46 robert Exp $
- * 
+ *
  * Authors:	Benedikt Spranger, Pengutronix
- * 		Robert Schwebel, Pengutronix
- * 
+ *		Robert Schwebel, Pengutronix
+ *
  *              This program is free software; you can redistribute it and/or
  *              modify it under the terms of the GNU General Public License
- *              version 2, as published by the Free Software Foundation. 
- * 
+ *              version 2, as published by the Free Software Foundation.
+ *
  *		This software was originally developed in conformance with
  *		Microsoft's Remote NDIS Specification License Agreement.
- *              
+ *
  * 03/12/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
  *		Fixed message length bug in init_response
- * 
+ *
  * 03/25/2004 Kai-Uwe Bloem <linux-development@auerswald.de>
- * 		Fixed rndis_rm_hdr length bug.
+ *		Fixed rndis_rm_hdr length bug.
  *
  * Copyright (C) 2004 by David Brownell
  *		updates to merge with Linux 2.6, better match RNDIS spec
@@ -82,7 +82,7 @@
 
 
 /* supported OIDs */
-static const u32 oid_supported_list [] = 
+static const u32 oid_supported_list [] =
 {
 	/* the general stuff */
 	OID_GEN_SUPPORTED_LIST,
@@ -103,7 +103,7 @@
 #if 0
 	OID_GEN_RNDIS_CONFIG_PARAMETER,
 #endif
-	
+
 	/* the statistical stuff */
 	OID_GEN_XMIT_OK,
 	OID_GEN_RCV_OK,
@@ -127,14 +127,14 @@
 	OID_GEN_TRANSMIT_QUEUE_LENGTH,
 #endif	/* RNDIS_OPTIONAL_STATS */
 
-    	/* mandatory 802.3 */
+	/* mandatory 802.3 */
 	/* the general stuff */
 	OID_802_3_PERMANENT_ADDRESS,
 	OID_802_3_CURRENT_ADDRESS,
 	OID_802_3_MULTICAST_LIST,
 	OID_802_3_MAC_OPTIONS,
 	OID_802_3_MAXIMUM_LIST_SIZE,
-	
+
 	/* the statistical stuff */
 	OID_802_3_RCV_ERROR_ALIGNMENT,
 	OID_802_3_XMIT_ONE_COLLISION,
@@ -172,8 +172,8 @@
 gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
 		rndis_resp_t *r)
 {
-	int 			retval = -ENOTSUPP;
-	u32 			length = 4;	/* usually */
+	int			retval = -ENOTSUPP;
+	u32			length = 4;	/* usually */
 	__le32			*outbuf;
 	int			i, count;
 	rndis_query_cmplt_type	*resp;
@@ -211,27 +211,27 @@
 			outbuf[i] = cpu_to_le32 (oid_supported_list[i]);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_HARDWARE_STATUS:
 		DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__);
-		/* Bogus question! 
+		/* Bogus question!
 		 * Hardware must be ready to receive high level protocols.
-		 * BTW: 
+		 * BTW:
 		 * reddite ergo quae sunt Caesaris Caesari
 		 * et quae sunt Dei Deo!
 		 */
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_MEDIA_SUPPORTED:
 		DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__);
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_MEDIA_IN_USE:
 		DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__);
@@ -239,7 +239,7 @@
 		*outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_MAXIMUM_FRAME_SIZE:
 		DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__);
@@ -249,7 +249,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_LINK_SPEED:
 		if (rndis_debug > 1)
@@ -272,7 +272,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_RECEIVE_BLOCK_SIZE:
 		DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__);
@@ -282,7 +282,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_VENDOR_ID:
 		DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__);
@@ -290,7 +290,7 @@
 			rndis_per_dev_params [configNr].vendorID);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_VENDOR_DESCRIPTION:
 		DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__);
@@ -356,7 +356,7 @@
 			DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
-			    rndis_per_dev_params [configNr].stats->tx_packets - 
+			    rndis_per_dev_params [configNr].stats->tx_packets -
 			    rndis_per_dev_params [configNr].stats->tx_errors -
 			    rndis_per_dev_params [configNr].stats->tx_dropped);
 			retval = 0;
@@ -369,13 +369,13 @@
 			DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
-			    rndis_per_dev_params [configNr].stats->rx_packets - 
+			    rndis_per_dev_params [configNr].stats->rx_packets -
 			    rndis_per_dev_params [configNr].stats->rx_errors -
 			    rndis_per_dev_params [configNr].stats->rx_dropped);
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_XMIT_ERROR:
 		if (rndis_debug > 1)
@@ -386,7 +386,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_RCV_ERROR:
 		if (rndis_debug > 1)
@@ -397,7 +397,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_GEN_RCV_NO_BUFFER:
 		DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__);
@@ -411,7 +411,7 @@
 #ifdef	RNDIS_OPTIONAL_STATS
 	case OID_GEN_DIRECTED_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__);
-		/* 
+		/*
 		 * Aunt Tilly's size of shoes
 		 * minus antarctica count of penguins
 		 * divided by weight of Alpha Centauri
@@ -419,7 +419,7 @@
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
 				(rndis_per_dev_params [configNr]
-					.stats->tx_packets - 
+					.stats->tx_packets -
 				 rndis_per_dev_params [configNr]
 					 .stats->tx_errors -
 				 rndis_per_dev_params [configNr]
@@ -428,14 +428,14 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_DIRECTED_FRAMES_XMIT:
 		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__);
 		/* dito */
 		if (rndis_per_dev_params [configNr].stats) {
 			*outbuf = cpu_to_le32 (
 				(rndis_per_dev_params [configNr]
-					.stats->tx_packets - 
+					.stats->tx_packets -
 				 rndis_per_dev_params [configNr]
 					 .stats->tx_errors -
 				 rndis_per_dev_params [configNr]
@@ -444,7 +444,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_MULTICAST_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -453,7 +453,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_MULTICAST_FRAMES_XMIT:
 		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -462,7 +462,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_BROADCAST_BYTES_XMIT:
 		DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -471,7 +471,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_BROADCAST_FRAMES_XMIT:
 		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -480,19 +480,19 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_DIRECTED_BYTES_RCV:
 		DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
-		
+
 	case OID_GEN_DIRECTED_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
-		
+
 	case OID_GEN_MULTICAST_BYTES_RCV:
 		DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -501,7 +501,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_MULTICAST_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -510,7 +510,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_BROADCAST_BYTES_RCV:
 		DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -519,7 +519,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_BROADCAST_FRAMES_RCV:
 		DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -528,7 +528,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_RCV_CRC_ERROR:
 		DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__);
 		if (rndis_per_dev_params [configNr].stats) {
@@ -537,7 +537,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
 		DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
@@ -558,7 +558,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_802_3_CURRENT_ADDRESS:
 		DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
@@ -570,7 +570,7 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_802_3_MULTICAST_LIST:
 		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
@@ -578,7 +578,7 @@
 		*outbuf = __constant_cpu_to_le32 (0xE0000000);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_802_3_MAXIMUM_LIST_SIZE:
 		DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__);
@@ -586,7 +586,7 @@
 		*outbuf = __constant_cpu_to_le32 (1);
 		retval = 0;
 		break;
-		
+
 	case OID_802_3_MAC_OPTIONS:
 		DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__);
 		break;
@@ -602,56 +602,56 @@
 			retval = 0;
 		}
 		break;
-		
+
 	/* mandatory */
 	case OID_802_3_XMIT_ONE_COLLISION:
 		DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
-		
+
 	/* mandatory */
 	case OID_802_3_XMIT_MORE_COLLISIONS:
 		DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__);
 		*outbuf = __constant_cpu_to_le32 (0);
 		retval = 0;
 		break;
-		
+
 #ifdef	RNDIS_OPTIONAL_STATS
 	case OID_802_3_XMIT_DEFERRED:
 		DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__);
 		/* TODO */
 		break;
-		
+
 	case OID_802_3_XMIT_MAX_COLLISIONS:
 		DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__);
 		/* TODO */
 		break;
-		
+
 	case OID_802_3_RCV_OVERRUN:
 		DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__);
 		/* TODO */
 		break;
-		
+
 	case OID_802_3_XMIT_UNDERRUN:
 		DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__);
 		/* TODO */
 		break;
-		
+
 	case OID_802_3_XMIT_HEARTBEAT_FAILURE:
 		DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__);
 		/* TODO */
 		break;
-		
+
 	case OID_802_3_XMIT_TIMES_CRS_LOST:
 		DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__);
 		/* TODO */
 		break;
-		
+
 	case OID_802_3_XMIT_LATE_COLLISIONS:
 		DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__);
 		/* TODO */
-		break;		
+		break;
 #endif	/* RNDIS_OPTIONAL_STATS */
 
 #ifdef	RNDIS_PM
@@ -676,23 +676,23 @@
 #endif
 
 	default:
-		printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", 
+		printk (KERN_WARNING "%s: query unknown OID 0x%08X\n",
 			 __FUNCTION__, OID);
 	}
 	if (retval < 0)
 		length = 0;
-	
+
 	resp->InformationBufferLength = cpu_to_le32 (length);
 	r->length = length + sizeof *resp;
 	resp->MessageLength = cpu_to_le32 (r->length);
 	return retval;
 }
 
-static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, 
-			      rndis_resp_t *r)
+static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
+			rndis_resp_t *r)
 {
 	rndis_set_cmplt_type		*resp;
-	int 				i, retval = -ENOTSUPP;
+	int				i, retval = -ENOTSUPP;
 	struct rndis_params		*params;
 
 	if (!r)
@@ -745,9 +745,9 @@
 			netif_stop_queue (params->dev);
 		}
 		break;
-		
+
 	case OID_802_3_MULTICAST_LIST:
-		/* I think we can ignore this */		
+		/* I think we can ignore this */
 		DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__);
 		retval = 0;
 		break;
@@ -796,29 +796,29 @@
 #endif	/* RNDIS_PM */
 
 	default:
-		printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", 
+		printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n",
 			 __FUNCTION__, OID, buf_len);
 	}
-	
+
 	return retval;
 }
 
-/* 
- * Response Functions 
+/*
+ * Response Functions
  */
 
 static int rndis_init_response (int configNr, rndis_init_msg_type *buf)
 {
-	rndis_init_cmplt_type	*resp; 
+	rndis_init_cmplt_type	*resp;
 	rndis_resp_t            *r;
-	
+
 	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
-	
+
 	r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type));
 	if (!r)
 		return -ENOMEM;
 	resp = (rndis_init_cmplt_type *) r->buf;
-	
+
 	resp->MessageType = __constant_cpu_to_le32 (
 			REMOTE_NDIS_INITIALIZE_CMPLT);
 	resp->MessageLength = __constant_cpu_to_le32 (52);
@@ -837,11 +837,11 @@
 	resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0);
 	resp->AFListOffset = __constant_cpu_to_le32 (0);
 	resp->AFListSize = __constant_cpu_to_le32 (0);
-	
+
 	if (rndis_per_dev_params [configNr].ack)
-	    rndis_per_dev_params [configNr].ack (
-	    		rndis_per_dev_params [configNr].dev);
-	
+		rndis_per_dev_params [configNr].ack (
+			rndis_per_dev_params [configNr].dev);
+
 	return 0;
 }
 
@@ -849,10 +849,10 @@
 {
 	rndis_query_cmplt_type *resp;
 	rndis_resp_t            *r;
-	
+
 	// DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID));
 	if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP;
-	
+
 	/*
 	 * we need more memory:
 	 * gen_ndis_query_resp expects enough space for
@@ -864,10 +864,10 @@
 	if (!r)
 		return -ENOMEM;
 	resp = (rndis_query_cmplt_type *) r->buf;
-	
+
 	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-  	
+
 	if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID),
 			le32_to_cpu(buf->InformationBufferOffset)
 					+ 8 + (u8 *) buf,
@@ -881,10 +881,10 @@
 		resp->InformationBufferOffset = __constant_cpu_to_le32 (0);
 	} else
 		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
-	
+
 	if (rndis_per_dev_params [configNr].ack)
-	    rndis_per_dev_params [configNr].ack (
-	    		rndis_per_dev_params [configNr].dev);
+		rndis_per_dev_params [configNr].ack (
+			rndis_per_dev_params [configNr].dev);
 	return 0;
 }
 
@@ -893,7 +893,7 @@
 	u32			BufLength, BufOffset;
 	rndis_set_cmplt_type	*resp;
 	rndis_resp_t		*r;
-	
+
 	r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type));
 	if (!r)
 		return -ENOMEM;
@@ -906,26 +906,27 @@
 	DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength);
 	DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset);
 	DEBUG("%s: InfoBuffer: ", __FUNCTION__);
-	
+
 	for (i = 0; i < BufLength; i++) {
 		DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset));
 	}
-	
+
 	DEBUG ("\n");
 #endif
-	
+
 	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT);
 	resp->MessageLength = __constant_cpu_to_le32 (16);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
-	if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), 
-			       ((u8 *) buf) + 8 + BufOffset, BufLength, r))
-	    resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
-	else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
-	
+	if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID),
+			((u8 *) buf) + 8 + BufOffset, BufLength, r))
+		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED);
+	else
+		resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
+
 	if (rndis_per_dev_params [configNr].ack)
-	    rndis_per_dev_params [configNr].ack (
-	    		rndis_per_dev_params [configNr].dev);
-	
+		rndis_per_dev_params [configNr].ack (
+			rndis_per_dev_params [configNr].dev);
+
 	return 0;
 }
 
@@ -933,27 +934,27 @@
 {
 	rndis_reset_cmplt_type	*resp;
 	rndis_resp_t		*r;
-	
+
 	r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type));
 	if (!r)
 		return -ENOMEM;
 	resp = (rndis_reset_cmplt_type *) r->buf;
-	
+
 	resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT);
 	resp->MessageLength = __constant_cpu_to_le32 (16);
 	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
 	/* resent information */
 	resp->AddressingReset = __constant_cpu_to_le32 (1);
-	
+
 	if (rndis_per_dev_params [configNr].ack)
-	    rndis_per_dev_params [configNr].ack (
-	    		rndis_per_dev_params [configNr].dev);
+		rndis_per_dev_params [configNr].ack (
+			rndis_per_dev_params [configNr].dev);
 
 	return 0;
 }
 
 static int rndis_keepalive_response (int configNr,
-				     rndis_keepalive_msg_type *buf)
+				rndis_keepalive_msg_type *buf)
 {
 	rndis_keepalive_cmplt_type	*resp;
 	rndis_resp_t			*r;
@@ -964,48 +965,48 @@
 	if (!r)
 		return -ENOMEM;
 	resp = (rndis_keepalive_cmplt_type *) r->buf;
-		
+
 	resp->MessageType = __constant_cpu_to_le32 (
 			REMOTE_NDIS_KEEPALIVE_CMPLT);
 	resp->MessageLength = __constant_cpu_to_le32 (16);
 	resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
 	resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS);
-	
+
 	if (rndis_per_dev_params [configNr].ack)
-	    rndis_per_dev_params [configNr].ack (
-	    		rndis_per_dev_params [configNr].dev);
-	
+		rndis_per_dev_params [configNr].ack (
+			rndis_per_dev_params [configNr].dev);
+
 	return 0;
 }
 
 
-/* 
- * Device to Host Comunication 
+/*
+ * Device to Host Comunication
  */
 static int rndis_indicate_status_msg (int configNr, u32 status)
 {
-	rndis_indicate_status_msg_type	*resp;	
+	rndis_indicate_status_msg_type	*resp;
 	rndis_resp_t			*r;
-	
+
 	if (rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED)
-	    return -ENOTSUPP;
-	
-	r = rndis_add_response (configNr, 
+		return -ENOTSUPP;
+
+	r = rndis_add_response (configNr,
 				sizeof (rndis_indicate_status_msg_type));
 	if (!r)
 		return -ENOMEM;
 	resp = (rndis_indicate_status_msg_type *) r->buf;
-	
+
 	resp->MessageType = __constant_cpu_to_le32 (
 			REMOTE_NDIS_INDICATE_STATUS_MSG);
 	resp->MessageLength = __constant_cpu_to_le32 (20);
 	resp->Status = cpu_to_le32 (status);
 	resp->StatusBufferLength = __constant_cpu_to_le32 (0);
 	resp->StatusBufferOffset = __constant_cpu_to_le32 (0);
-	
-	if (rndis_per_dev_params [configNr].ack) 
-	    rndis_per_dev_params [configNr].ack (
-	    		rndis_per_dev_params [configNr].dev);
+
+	if (rndis_per_dev_params [configNr].ack)
+		rndis_per_dev_params [configNr].ack (
+			rndis_per_dev_params [configNr].dev);
 	return 0;
 }
 
@@ -1013,7 +1014,7 @@
 {
 	rndis_per_dev_params [configNr].media_state
 			= NDIS_MEDIA_STATE_CONNECTED;
-	return rndis_indicate_status_msg (configNr, 
+	return rndis_indicate_status_msg (configNr,
 					  RNDIS_STATUS_MEDIA_CONNECT);
 }
 
@@ -1045,26 +1046,26 @@
 	rndis_per_dev_params [configNr].host_mac = addr;
 }
 
-/* 
- * Message Parser 
+/*
+ * Message Parser
  */
 int rndis_msg_parser (u8 configNr, u8 *buf)
 {
 	u32 MsgType, MsgLength;
 	__le32 *tmp;
 	struct rndis_params		*params;
-	
+
 	if (!buf)
 		return -ENOMEM;
-	
-	tmp = (__le32 *) buf; 
+
+	tmp = (__le32 *) buf;
 	MsgType   = le32_to_cpup(tmp++);
 	MsgLength = le32_to_cpup(tmp++);
-	
+
 	if (configNr >= RNDIS_MAX_CONFIGS)
 		return -ENOTSUPP;
 	params = &rndis_per_dev_params [configNr];
-	
+
 	/* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for
 	 * rx/tx statistics and link status, in addition to KEEPALIVE traffic
 	 * and normal HC level polling to see if there's any IN traffic.
@@ -1073,12 +1074,12 @@
 	/* For USB: responses may take up to 10 seconds */
 	switch (MsgType) {
 	case REMOTE_NDIS_INITIALIZE_MSG:
-		DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", 
+		DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n",
 			__FUNCTION__ );
 		params->state = RNDIS_INITIALIZED;
 		return  rndis_init_response (configNr,
-					     (rndis_init_msg_type *) buf);
-		
+					(rndis_init_msg_type *) buf);
+
 	case REMOTE_NDIS_HALT_MSG:
 		DEBUG("%s: REMOTE_NDIS_HALT_MSG\n",
 			__FUNCTION__ );
@@ -1088,37 +1089,37 @@
 			netif_stop_queue (params->dev);
 		}
 		return 0;
-		
+
 	case REMOTE_NDIS_QUERY_MSG:
-		return rndis_query_response (configNr, 
-					     (rndis_query_msg_type *) buf);
-		
+		return rndis_query_response (configNr,
+					(rndis_query_msg_type *) buf);
+
 	case REMOTE_NDIS_SET_MSG:
-		return rndis_set_response (configNr, 
-					   (rndis_set_msg_type *) buf);
-		
+		return rndis_set_response (configNr,
+					(rndis_set_msg_type *) buf);
+
 	case REMOTE_NDIS_RESET_MSG:
-		DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", 
+		DEBUG("%s: REMOTE_NDIS_RESET_MSG\n",
 			__FUNCTION__ );
 		return rndis_reset_response (configNr,
-					     (rndis_reset_msg_type *) buf);
+					(rndis_reset_msg_type *) buf);
 
 	case REMOTE_NDIS_KEEPALIVE_MSG:
 		/* For USB: host does this every 5 seconds */
 		if (rndis_debug > 1)
-			DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", 
+			DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
 				__FUNCTION__ );
 		return rndis_keepalive_response (configNr,
-						 (rndis_keepalive_msg_type *) 
+						 (rndis_keepalive_msg_type *)
 						 buf);
-		
-	default: 
+
+	default:
 		/* At least Windows XP emits some undefined RNDIS messages.
 		 * In one case those messages seemed to relate to the host
 		 * suspending itself.
 		 */
 		printk (KERN_WARNING
-			"%s: unknown RNDIS message 0x%08X len %d\n", 
+			"%s: unknown RNDIS message 0x%08X len %d\n",
 			__FUNCTION__ , MsgType, MsgLength);
 		{
 			unsigned i;
@@ -1142,14 +1143,14 @@
 		}
 		break;
 	}
-	
+
 	return -ENOTSUPP;
 }
 
 int rndis_register (int (* rndis_control_ack) (struct net_device *))
 {
 	u8 i;
-	
+
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
 		if (!rndis_per_dev_params [i].used) {
 			rndis_per_dev_params [i].used = 1;
@@ -1159,32 +1160,32 @@
 		}
 	}
 	DEBUG("failed\n");
-	
+
 	return -1;
 }
 
 void rndis_deregister (int configNr)
 {
 	DEBUG("%s: \n", __FUNCTION__ );
-	
+
 	if (configNr >= RNDIS_MAX_CONFIGS) return;
 	rndis_per_dev_params [configNr].used = 0;
-	
+
 	return;
 }
 
-int rndis_set_param_dev (u8 configNr, struct net_device *dev, 
+int rndis_set_param_dev (u8 configNr, struct net_device *dev,
 			 struct net_device_stats *stats,
 			 u16 *cdc_filter)
 {
 	DEBUG("%s:\n", __FUNCTION__ );
 	if (!dev || !stats) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
-	
+
 	rndis_per_dev_params [configNr].dev = dev;
 	rndis_per_dev_params [configNr].stats = stats;
 	rndis_per_dev_params [configNr].filter = cdc_filter;
-	
+
 	return 0;
 }
 
@@ -1193,10 +1194,10 @@
 	DEBUG("%s:\n", __FUNCTION__ );
 	if (!vendorDescr) return -1;
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
-	
+
 	rndis_per_dev_params [configNr].vendorID = vendorID;
 	rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
-	
+
 	return 0;
 }
 
@@ -1204,10 +1205,10 @@
 {
 	DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed);
 	if (configNr >= RNDIS_MAX_CONFIGS) return -1;
-	
+
 	rndis_per_dev_params [configNr].medium = medium;
 	rndis_per_dev_params [configNr].speed = speed;
-	
+
 	return 0;
 }
 
@@ -1229,9 +1230,9 @@
 {
 	rndis_resp_t		*r;
 	struct list_head	*act, *tmp;
-	
-	list_for_each_safe (act, tmp, 
-			    &(rndis_per_dev_params [configNr].resp_queue))
+
+	list_for_each_safe (act, tmp,
+			&(rndis_per_dev_params [configNr].resp_queue))
 	{
 		r = list_entry (act, rndis_resp_t, list);
 		if (r && r->buf == buf) {
@@ -1244,12 +1245,12 @@
 u8 *rndis_get_next_response (int configNr, u32 *length)
 {
 	rndis_resp_t		*r;
-	struct list_head 	*act, *tmp;
-	
+	struct list_head	*act, *tmp;
+
 	if (!length) return NULL;
-	
-	list_for_each_safe (act, tmp, 
-			    &(rndis_per_dev_params [configNr].resp_queue))
+
+	list_for_each_safe (act, tmp,
+			&(rndis_per_dev_params [configNr].resp_queue))
 	{
 		r = list_entry (act, rndis_resp_t, list);
 		if (!r->send) {
@@ -1258,24 +1259,24 @@
 			return r->buf;
 		}
 	}
-	
+
 	return NULL;
 }
 
 static rndis_resp_t *rndis_add_response (int configNr, u32 length)
 {
 	rndis_resp_t	*r;
-	
+
 	/* NOTE:  this gets copied into ether.c USB_BUFSIZ bytes ... */
 	r = kmalloc (sizeof (rndis_resp_t) + length, GFP_ATOMIC);
 	if (!r) return NULL;
-	
+
 	r->buf = (u8 *) (r + 1);
 	r->length = length;
 	r->send = 0;
-	
-	list_add_tail (&r->list, 
-		       &(rndis_per_dev_params [configNr].resp_queue));
+
+	list_add_tail (&r->list,
+		&(rndis_per_dev_params [configNr].resp_queue));
 	return r;
 }
 
@@ -1301,14 +1302,14 @@
 
 #ifdef	CONFIG_USB_GADGET_DEBUG_FILES
 
-static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof, 
-		     void *data)
+static int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
+		void *data)
 {
 	char *out = page;
 	int len;
 	rndis_params *param = (rndis_params *) data;
-	
-	out += snprintf (out, count, 
+
+	out += snprintf (out, count,
 			 "Config Nr. %d\n"
 			 "used      : %s\n"
 			 "state     : %s\n"
@@ -1316,8 +1317,8 @@
 			 "speed     : %d\n"
 			 "cable     : %s\n"
 			 "vendor ID : 0x%08X\n"
-			 "vendor    : %s\n", 
-			 param->confignr, (param->used) ? "y" : "n", 
+			 "vendor    : %s\n",
+			 param->confignr, (param->used) ? "y" : "n",
 			 ({ char *s = "?";
 			 switch (param->state) {
 			 case RNDIS_UNINITIALIZED:
@@ -1327,32 +1328,32 @@
 			 case RNDIS_DATA_INITIALIZED:
 				s = "RNDIS_DATA_INITIALIZED"; break;
 			}; s; }),
-			 param->medium, 
-			 (param->media_state) ? 0 : param->speed*100, 
+			 param->medium,
+			 (param->media_state) ? 0 : param->speed*100,
 			 (param->media_state) ? "disconnected" : "connected",
-			 param->vendorID, param->vendorDescr);      
-	
+			 param->vendorID, param->vendorDescr);
+
 	len = out - page;
 	len -= off;
-	
+
 	if (len < count) {
 		*eof = 1;
 		if (len <= 0)
 			return 0;
 	} else
 		len = count;
-	
+
 	*start = page + off;
 	return len;
 }
 
-static int rndis_proc_write (struct file *file, const char __user *buffer, 
-		      unsigned long count, void *data)
+static int rndis_proc_write (struct file *file, const char __user *buffer,
+		unsigned long count, void *data)
 {
 	rndis_params *p = data;
 	u32 speed = 0;
 	int i, fl_speed = 0;
-	
+
 	for (i = 0; i < count; i++) {
 		char c;
 		if (get_user(c, buffer))
@@ -1379,15 +1380,15 @@
 		case 'd':
 			rndis_signal_disconnect(p->confignr);
 			break;
-		default: 
+		default:
 			if (fl_speed) p->speed = speed;
 			else DEBUG ("%c is not valid\n", c);
 			break;
 		}
-		
+
 		buffer++;
 	}
-	
+
 	return count;
 }
 
@@ -1408,7 +1409,7 @@
 
 		sprintf (name, NAME_TEMPLATE, i);
 		if (!(rndis_connect_state [i]
-				= create_proc_entry (name, 0660, NULL))) 
+				= create_proc_entry (name, 0660, NULL)))
 		{
 			DEBUG ("%s :remove entries", __FUNCTION__);
 			while (i) {
@@ -1432,7 +1433,7 @@
 				= NDIS_MEDIA_STATE_DISCONNECTED;
 		INIT_LIST_HEAD (&(rndis_per_dev_params [i].resp_queue));
 	}
-	
+
 	return 0;
 }
 
@@ -1441,7 +1442,7 @@
 #ifdef	CONFIG_USB_GADGET_DEBUG_FILES
 	u8 i;
 	char name [20];
-	
+
 	for (i = 0; i < RNDIS_MAX_CONFIGS; i++) {
 		sprintf (name, NAME_TEMPLATE, i);
 		remove_proc_entry (name, NULL);
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 95b4c63..2956608 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -1,15 +1,15 @@
-/* 
+/*
  * RNDIS	Definitions for Remote NDIS
- * 
+ *
  * Version:	$Id: rndis.h,v 1.15 2004/03/25 21:33:46 robert Exp $
- * 
+ *
  * Authors:	Benedikt Spranger, Pengutronix
- * 		Robert Schwebel, Pengutronix
- * 
- * 		This program is free software; you can redistribute it and/or
+ *		Robert Schwebel, Pengutronix
+ *
+ *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
- *		version 2, as published by the Free Software Foundation. 
- * 
+ *		version 2, as published by the Free Software Foundation.
+ *
  *		This software was originally developed in conformance with
  *		Microsoft's Remote NDIS Specification License Agreement.
  */
@@ -34,7 +34,7 @@
 #define RNDIS_STATUS_MEDIA_CONNECT	0x4001000BU	/* Device connected  */
 #define RNDIS_STATUS_MEDIA_DISCONNECT	0x4001000CU	/* Device disconnected */
 /* For all not specified status messages:
- * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx 
+ * RNDIS_STATUS_Xxx -> NDIS_STATUS_Xxx
  */
 
 /* Message Set for Connectionless (802.3) Devices */
@@ -69,7 +69,7 @@
 #define OID_PNP_ENABLE_WAKE_UP			0xFD010106
 
 
-typedef struct rndis_init_msg_type 
+typedef struct rndis_init_msg_type
 {
 	__le32	MessageType;
 	__le32	MessageLength;
@@ -234,12 +234,12 @@
 
 	const u8		*host_mac;
 	u16			*filter;
-	struct net_device 	*dev;
+	struct net_device	*dev;
 	struct net_device_stats *stats;
 
 	u32			vendorID;
 	const char		*vendorDescr;
-	int 			(*ack) (struct net_device *);
+	int			(*ack) (struct net_device *);
 	struct list_head	resp_queue;
 } rndis_params;
 
@@ -250,7 +250,7 @@
 int  rndis_set_param_dev (u8 configNr, struct net_device *dev,
 			 struct net_device_stats *stats,
 			 u16 *cdc_filter);
-int  rndis_set_param_vendor (u8 configNr, u32 vendorID, 
+int  rndis_set_param_vendor (u8 configNr, u32 vendorID,
 			    const char *vendorDescr);
 int  rndis_set_param_medium (u8 configNr, u32 medium, u32 speed);
 void rndis_add_hdr (struct sk_buff *skb);
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index b992546..9d6e1d2 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -45,88 +45,16 @@
 #include <asm/uaccess.h>
 
 #include <linux/usb_ch9.h>
-#include <linux/usb_cdc.h>
+#include <linux/usb/cdc.h>
 #include <linux/usb_gadget.h>
 
 #include "gadget_chips.h"
 
 
-/* Wait Cond */
-
-#define __wait_cond_interruptible(wq, condition, lock, flags, ret)	\
-do {									\
-	wait_queue_t __wait;						\
-	init_waitqueue_entry(&__wait, current);				\
-									\
-	add_wait_queue(&wq, &__wait);					\
-	for (;;) {							\
-		set_current_state(TASK_INTERRUPTIBLE);			\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			spin_unlock_irqrestore(lock, flags);		\
-			schedule();					\
-			spin_lock_irqsave(lock, flags);			\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	current->state = TASK_RUNNING;					\
-	remove_wait_queue(&wq, &__wait);				\
-} while (0)
-	
-#define wait_cond_interruptible(wq, condition, lock, flags)		\
-({									\
-	int __ret = 0;							\
-	if (!(condition))						\
-		__wait_cond_interruptible(wq, condition, lock, flags,	\
-						__ret);			\
-	__ret;								\
-})
-
-#define __wait_cond_interruptible_timeout(wq, condition, lock, flags, 	\
-						timeout, ret)		\
-do {									\
-	signed long __timeout = timeout;				\
-	wait_queue_t __wait;						\
-	init_waitqueue_entry(&__wait, current);				\
-									\
-	add_wait_queue(&wq, &__wait);					\
-	for (;;) {							\
-		set_current_state(TASK_INTERRUPTIBLE);			\
-		if (__timeout == 0)					\
-			break;						\
-		if (condition)						\
-			break;						\
-		if (!signal_pending(current)) {				\
-			spin_unlock_irqrestore(lock, flags);		\
-			__timeout = schedule_timeout(__timeout);	\
-			spin_lock_irqsave(lock, flags);			\
-			continue;					\
-		}							\
-		ret = -ERESTARTSYS;					\
-		break;							\
-	}								\
-	current->state = TASK_RUNNING;					\
-	remove_wait_queue(&wq, &__wait);				\
-} while (0)
-	
-#define wait_cond_interruptible_timeout(wq, condition, lock, flags,	\
-						timeout)		\
-({									\
-	int __ret = 0;							\
-	if (!(condition))						\
-		__wait_cond_interruptible_timeout(wq, condition, lock,	\
-						flags, timeout, __ret);	\
-	__ret;								\
-})
-
-
 /* Defines */
 
-#define GS_VERSION_STR			"v2.0"
-#define GS_VERSION_NUM			0x0200
+#define GS_VERSION_STR			"v2.2"
+#define GS_VERSION_NUM			0x0202
 
 #define GS_LONG_NAME			"Gadget Serial"
 #define GS_SHORT_NAME			"g_serial"
@@ -843,9 +771,19 @@
 /*
  * gs_close
  */
+
+#define GS_WRITE_FINISHED_EVENT_SAFELY(p)			\
+({								\
+	int cond;						\
+								\
+	spin_lock_irq(&(p)->port_lock);				\
+	cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \
+	spin_unlock_irq(&(p)->port_lock);			\
+	cond;							\
+})
+
 static void gs_close(struct tty_struct *tty, struct file *file)
 {
-	unsigned long flags;
 	struct gs_port *port = tty->driver_data;
 	struct semaphore *sem;
 
@@ -859,7 +797,7 @@
 	sem = &gs_open_close_sem[port->port_num];
 	down(sem);
 
-	spin_lock_irqsave(&port->port_lock, flags);
+	spin_lock_irq(&port->port_lock);
 
 	if (port->port_open_count == 0) {
 		printk(KERN_ERR
@@ -887,12 +825,11 @@
 	/* wait for write buffer to drain, or */
 	/* at most GS_CLOSE_TIMEOUT seconds */
 	if (gs_buf_data_avail(port->port_write_buf) > 0) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		wait_cond_interruptible_timeout(port->port_write_wait,
-		port->port_dev == NULL
-		|| gs_buf_data_avail(port->port_write_buf) == 0,
-		&port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ);
-		spin_lock_irqsave(&port->port_lock, flags);
+		spin_unlock_irq(&port->port_lock);
+		wait_event_interruptible_timeout(port->port_write_wait,
+					GS_WRITE_FINISHED_EVENT_SAFELY(port),
+					GS_CLOSE_TIMEOUT * HZ);
+		spin_lock_irq(&port->port_lock);
 	}
 
 	/* free disconnected port on final close */
@@ -912,7 +849,7 @@
 		port->port_num, tty, file);
 
 exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	spin_unlock_irq(&port->port_lock);
 	up(sem);
 }
 
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index e27b79a3..b93d71d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -47,12 +47,29 @@
 	  controller is needed.  It's safe to say "y" even if your
 	  controller doesn't support this feature.
 
-	  This supports the EHCI implementation from TransDimension Inc.
+	  This supports the EHCI implementation that's originally
+	  from ARC, and has since changed hands a few times.
+
+config USB_EHCI_TT_NEWSCHED
+	bool "Improved Transaction Translator scheduling (EXPERIMENTAL)"
+	depends on USB_EHCI_HCD && EXPERIMENTAL
+	---help---
+	  This changes the periodic scheduling code to fill more of the low
+	  and full speed bandwidth available from the Transaction Translator
+	  (TT) in USB 2.0 hubs.  Without this, only one transfer will be
+	  issued in each microframe, significantly reducing the number of
+	  periodic low/fullspeed transfers possible.
+
+	  If you have multiple periodic low/fullspeed devices connected to a
+	  highspeed USB hub which is connected to a highspeed USB Host
+	  Controller, and some of those devices will not work correctly
+	  (possibly due to "ENOSPC" or "-28" errors), say Y.
+
+	  If unsure, say N.
 
 config USB_ISP116X_HCD
 	tristate "ISP116X HCD support"
 	depends on USB
-	default N
 	---help---
 	  The ISP1160 and ISP1161 chips are USB host controllers. Enable this
 	  option if your board has this chip. If unsure, say N.
@@ -127,7 +144,6 @@
 config USB_SL811_HCD
 	tristate "SL811HS HCD support"
 	depends on USB
-	default N
 	help
 	  The SL811HS is a single-port USB controller that supports either
 	  host side or peripheral side roles.  Enable this option if your
@@ -140,7 +156,6 @@
 config USB_SL811_CS
 	tristate "CF/PCMCIA support for SL811HS HCD"
 	depends on USB_SL811_HCD && PCMCIA
-	default N
 	help
 	  Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC
 	  REX-CFU1U CF card (often used with PDAs).  If unsure, say N.
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 63eadee..9b4697a 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -16,10 +16,6 @@
 #include <linux/platform_device.h>
 #include <asm/mach-au1x00/au1000.h>
 
-#ifndef CONFIG_SOC_AU1200
-#error "this Alchemy chip doesn't have EHCI"
-#else				/* Au1200 */
-
 #define USB_HOST_CONFIG   (USB_MSR_BASE + USB_MSR_MCFG)
 #define USB_MCFG_PFEN     (1<<31)
 #define USB_MCFG_RDCOMB   (1<<30)
@@ -272,6 +268,8 @@
 	return 0;
 }
 */
+MODULE_ALIAS("au1xxx-ehci");
+/* FIXME use "struct platform_driver" */
 static struct device_driver ehci_hcd_au1xxx_driver = {
 	.name = "au1xxx-ehci",
 	.bus = &platform_bus_type,
@@ -280,18 +278,3 @@
 	/*.suspend      = ehci_hcd_au1xxx_drv_suspend, */
 	/*.resume       = ehci_hcd_au1xxx_drv_resume, */
 };
-
-static int __init ehci_hcd_au1xxx_init(void)
-{
-	pr_debug(DRIVER_INFO " (Au1xxx)\n");
-
-	return driver_register(&ehci_hcd_au1xxx_driver);
-}
-
-static void __exit ehci_hcd_au1xxx_cleanup(void)
-{
-	driver_unregister(&ehci_hcd_au1xxx_driver);
-}
-
-module_init(ehci_hcd_au1xxx_init);
-module_exit(ehci_hcd_au1xxx_cleanup);
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index f985f121..a49a689 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -324,43 +324,12 @@
 	return 0;
 }
 
-static struct platform_driver ehci_fsl_dr_driver = {
+MODULE_ALIAS("fsl-ehci");
+
+static struct platform_driver ehci_fsl_driver = {
 	.probe = ehci_fsl_drv_probe,
 	.remove = ehci_fsl_drv_remove,
 	.driver = {
-		   .name = "fsl-usb2-dr",
+		   .name = "fsl-ehci",
 		   },
 };
-
-static struct platform_driver ehci_fsl_mph_driver = {
-	.probe = ehci_fsl_drv_probe,
-	.remove = ehci_fsl_drv_remove,
-	.driver = {
-		   .name = "fsl-usb2-mph",
-		   },
-};
-
-static int __init ehci_fsl_init(void)
-{
-	int retval;
-
-	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
-		 hcd_name,
-		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
-		 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
-
-	retval = platform_driver_register(&ehci_fsl_dr_driver);
-	if (retval)
-		return retval;
-
-	return platform_driver_register(&ehci_fsl_mph_driver);
-}
-
-static void __exit ehci_fsl_cleanup(void)
-{
-	platform_driver_unregister(&ehci_fsl_mph_driver);
-	platform_driver_unregister(&ehci_fsl_dr_driver);
-}
-
-module_init(ehci_fsl_init);
-module_exit(ehci_fsl_cleanup);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 79f2d8b..9b37e50 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -889,19 +889,59 @@
 
 #ifdef CONFIG_PCI
 #include "ehci-pci.c"
-#define	EHCI_BUS_GLUED
+#define	PCI_DRIVER		ehci_pci_driver
 #endif
 
 #ifdef CONFIG_PPC_83xx
 #include "ehci-fsl.c"
-#define	EHCI_BUS_GLUED
+#define	PLATFORM_DRIVER		ehci_fsl_driver
 #endif
 
-#ifdef CONFIG_SOC_AU1X00
+#ifdef CONFIG_SOC_AU1200
 #include "ehci-au1xxx.c"
-#define	EHCI_BUS_GLUED
+#define	PLATFORM_DRIVER		ehci_hcd_au1xxx_driver
 #endif
 
-#ifndef	EHCI_BUS_GLUED
+#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER)
 #error "missing bus glue for ehci-hcd"
 #endif
+
+static int __init ehci_hcd_init(void)
+{
+	int retval = 0;
+
+	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
+		 hcd_name,
+		 sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
+		 sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
+
+#ifdef PLATFORM_DRIVER
+	retval = platform_driver_register(&PLATFORM_DRIVER);
+	if (retval < 0)
+		return retval;
+#endif
+
+#ifdef PCI_DRIVER
+	retval = pci_register_driver(&PCI_DRIVER);
+	if (retval < 0) {
+#ifdef PLATFORM_DRIVER
+		platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+	}
+#endif
+
+	return retval;
+}
+module_init(ehci_hcd_init);
+
+static void __exit ehci_hcd_cleanup(void)
+{
+#ifdef PLATFORM_DRIVER
+	platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+#ifdef PCI_DRIVER
+	pci_unregister_driver(&PCI_DRIVER);
+#endif
+}
+module_exit(ehci_hcd_cleanup);
+
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index a1bd2be..cadffac 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -76,6 +76,30 @@
 	dbg_hcs_params(ehci, "reset");
 	dbg_hcc_params(ehci, "reset");
 
+        /* ehci_init() causes memory for DMA transfers to be
+         * allocated.  Thus, any vendor-specific workarounds based on
+         * limiting the type of memory used for DMA transfers must
+         * happen before ehci_init() is called. */
+	switch (pdev->vendor) {
+	case PCI_VENDOR_ID_NVIDIA:
+		/* NVidia reports that certain chips don't handle
+		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
+		 * data buffer, and periodic schedule are normal.)
+		 */
+		switch (pdev->device) {
+		case 0x003c:	/* MCP04 */
+		case 0x005b:	/* CK804 */
+		case 0x00d8:	/* CK8 */
+		case 0x00e8:	/* CK8S */
+			if (pci_set_consistent_dma_mask(pdev,
+						DMA_31BIT_MASK) < 0)
+				ehci_warn(ehci, "can't enable NVidia "
+					"workaround for >2GB RAM\n");
+			break;
+		}
+		break;
+	}
+
 	/* cache this readonly data; minimize chip reads */
 	ehci->hcs_params = readl(&ehci->caps->hcs_params);
 
@@ -88,8 +112,6 @@
 	if (retval)
 		return retval;
 
-	/* NOTE:  only the parts below this line are PCI-specific */
-
 	switch (pdev->vendor) {
 	case PCI_VENDOR_ID_TDI:
 		if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
@@ -107,19 +129,6 @@
 		break;
 	case PCI_VENDOR_ID_NVIDIA:
 		switch (pdev->device) {
-		/* NVidia reports that certain chips don't handle
-		 * QH, ITD, or SITD addresses above 2GB.  (But TD,
-		 * data buffer, and periodic schedule are normal.)
-		 */
-		case 0x003c:	/* MCP04 */
-		case 0x005b:	/* CK804 */
-		case 0x00d8:	/* CK8 */
-		case 0x00e8:	/* CK8S */
-			if (pci_set_consistent_dma_mask(pdev,
-						DMA_31BIT_MASK) < 0)
-				ehci_warn(ehci, "can't enable NVidia "
-					"workaround for >2GB RAM\n");
-			break;
 		/* Some NForce2 chips have problems with selective suspend;
 		 * fixed in newer silicon.
 		 */
@@ -370,23 +379,3 @@
 	.resume =	usb_hcd_pci_resume,
 #endif
 };
-
-static int __init ehci_hcd_pci_init(void)
-{
-	if (usb_disabled())
-		return -ENODEV;
-
-	pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n",
-		hcd_name,
-		sizeof(struct ehci_qh), sizeof(struct ehci_qtd),
-		sizeof(struct ehci_itd), sizeof(struct ehci_sitd));
-
-	return pci_register_driver(&ehci_pci_driver);
-}
-module_init(ehci_hcd_pci_init);
-
-static void __exit ehci_hcd_pci_cleanup(void)
-{
-	pci_unregister_driver(&ehci_pci_driver);
-}
-module_exit(ehci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 5871944..4859900 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -163,6 +163,190 @@
 		return 1;
 }
 
+#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+
+/* Which uframe does the low/fullspeed transfer start in?
+ *
+ * The parameter is the mask of ssplits in "H-frame" terms
+ * and this returns the transfer start uframe in "B-frame" terms,
+ * which allows both to match, e.g. a ssplit in "H-frame" uframe 0
+ * will cause a transfer in "B-frame" uframe 0.  "B-frames" lag
+ * "H-frames" by 1 uframe.  See the EHCI spec sec 4.5 and figure 4.7.
+ */
+static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask)
+{
+	unsigned char smask = QH_SMASK & le32_to_cpu(mask);
+	if (!smask) {
+		ehci_err(ehci, "invalid empty smask!\n");
+		/* uframe 7 can't have bw so this will indicate failure */
+		return 7;
+	}
+	return ffs(smask) - 1;
+}
+
+static const unsigned char
+max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 };
+
+/* carryover low/fullspeed bandwidth that crosses uframe boundries */
+static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8])
+{
+	int i;
+	for (i=0; i<7; i++) {
+		if (max_tt_usecs[i] < tt_usecs[i]) {
+			tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i];
+			tt_usecs[i] = max_tt_usecs[i];
+		}
+	}
+}
+
+/* How many of the tt's periodic downstream 1000 usecs are allocated?
+ *
+ * While this measures the bandwidth in terms of usecs/uframe,
+ * the low/fullspeed bus has no notion of uframes, so any particular
+ * low/fullspeed transfer can "carry over" from one uframe to the next,
+ * since the TT just performs downstream transfers in sequence.
+ *
+ * For example two seperate 100 usec transfers can start in the same uframe,
+ * and the second one would "carry over" 75 usecs into the next uframe.
+ */
+static void
+periodic_tt_usecs (
+	struct ehci_hcd *ehci,
+	struct usb_device *dev,
+	unsigned frame,
+	unsigned short tt_usecs[8]
+)
+{
+	__le32			*hw_p = &ehci->periodic [frame];
+	union ehci_shadow	*q = &ehci->pshadow [frame];
+	unsigned char		uf;
+
+	memset(tt_usecs, 0, 16);
+
+	while (q->ptr) {
+		switch (Q_NEXT_TYPE(*hw_p)) {
+		case Q_TYPE_ITD:
+			hw_p = &q->itd->hw_next;
+			q = &q->itd->itd_next;
+			continue;
+		case Q_TYPE_QH:
+			if (same_tt(dev, q->qh->dev)) {
+				uf = tt_start_uframe(ehci, q->qh->hw_info2);
+				tt_usecs[uf] += q->qh->tt_usecs;
+			}
+			hw_p = &q->qh->hw_next;
+			q = &q->qh->qh_next;
+			continue;
+		case Q_TYPE_SITD:
+			if (same_tt(dev, q->sitd->urb->dev)) {
+				uf = tt_start_uframe(ehci, q->sitd->hw_uframe);
+				tt_usecs[uf] += q->sitd->stream->tt_usecs;
+			}
+			hw_p = &q->sitd->hw_next;
+			q = &q->sitd->sitd_next;
+			continue;
+		// case Q_TYPE_FSTN:
+		default:
+			ehci_dbg(ehci,
+				  "ignoring periodic frame %d FSTN\n", frame);
+			hw_p = &q->fstn->hw_next;
+			q = &q->fstn->fstn_next;
+		}
+	}
+
+	carryover_tt_bandwidth(tt_usecs);
+
+	if (max_tt_usecs[7] < tt_usecs[7])
+		ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n",
+			frame, tt_usecs[7] - max_tt_usecs[7]);
+}
+
+/*
+ * Return true if the device's tt's downstream bus is available for a
+ * periodic transfer of the specified length (usecs), starting at the
+ * specified frame/uframe.  Note that (as summarized in section 11.19
+ * of the usb 2.0 spec) TTs can buffer multiple transactions for each
+ * uframe.
+ *
+ * The uframe parameter is when the fullspeed/lowspeed transfer
+ * should be executed in "B-frame" terms, which is the same as the
+ * highspeed ssplit's uframe (which is in "H-frame" terms).  For example
+ * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0.
+ * See the EHCI spec sec 4.5 and fig 4.7.
+ *
+ * This checks if the full/lowspeed bus, at the specified starting uframe,
+ * has the specified bandwidth available, according to rules listed
+ * in USB 2.0 spec section 11.18.1 fig 11-60.
+ *
+ * This does not check if the transfer would exceed the max ssplit
+ * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4,
+ * since proper scheduling limits ssplits to less than 16 per uframe.
+ */
+static int tt_available (
+	struct ehci_hcd		*ehci,
+	unsigned		period,
+	struct usb_device	*dev,
+	unsigned		frame,
+	unsigned		uframe,
+	u16			usecs
+)
+{
+	if ((period == 0) || (uframe >= 7))	/* error */
+		return 0;
+
+	for (; frame < ehci->periodic_size; frame += period) {
+		unsigned short tt_usecs[8];
+
+		periodic_tt_usecs (ehci, dev, frame, tt_usecs);
+
+		ehci_vdbg(ehci, "tt frame %d check %d usecs start uframe %d in"
+			" schedule %d/%d/%d/%d/%d/%d/%d/%d\n",
+			frame, usecs, uframe,
+			tt_usecs[0], tt_usecs[1], tt_usecs[2], tt_usecs[3],
+			tt_usecs[4], tt_usecs[5], tt_usecs[6], tt_usecs[7]);
+
+		if (max_tt_usecs[uframe] <= tt_usecs[uframe]) {
+			ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n",
+				frame, uframe);
+			return 0;
+		}
+
+		/* special case for isoc transfers larger than 125us:
+		 * the first and each subsequent fully used uframe
+		 * must be empty, so as to not illegally delay
+		 * already scheduled transactions
+		 */
+		if (125 < usecs) {
+			int ufs = (usecs / 125) - 1;
+			int i;
+			for (i = uframe; i < (uframe + ufs) && i < 8; i++)
+				if (0 < tt_usecs[i]) {
+					ehci_vdbg(ehci,
+						"multi-uframe xfer can't fit "
+						"in frame %d uframe %d\n",
+						frame, i);
+					return 0;
+				}
+		}
+
+		tt_usecs[uframe] += usecs;
+
+		carryover_tt_bandwidth(tt_usecs);
+
+		/* fail if the carryover pushed bw past the last uframe's limit */
+		if (max_tt_usecs[7] < tt_usecs[7]) {
+			ehci_vdbg(ehci,
+				"tt unavailable usecs %d frame %d uframe %d\n",
+				usecs, frame, uframe);
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+#else
+
 /* return true iff the device's transaction translator is available
  * for a periodic transfer starting at the specified frame, using
  * all the uframes in the mask.
@@ -237,6 +421,8 @@
 	return 1;
 }
 
+#endif /* CONFIG_USB_EHCI_TT_NEWSCHED */
+
 /*-------------------------------------------------------------------------*/
 
 static int enable_periodic (struct ehci_hcd *ehci)
@@ -481,7 +667,7 @@
 )
 {
     	int		retval = -ENOSPC;
-	u8		mask;
+	u8		mask = 0;
 
 	if (qh->c_usecs && uframe >= 6)		/* FSTN territory? */
 		goto done;
@@ -494,6 +680,24 @@
 		goto done;
 	}
 
+#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+	if (tt_available (ehci, qh->period, qh->dev, frame, uframe,
+				qh->tt_usecs)) {
+		unsigned i;
+
+		/* TODO : this may need FSTN for SSPLIT in uframe 5. */
+		for (i=uframe+1; i<8 && i<uframe+4; i++)
+			if (!check_period (ehci, frame, i,
+						qh->period, qh->c_usecs))
+				goto done;
+			else
+				mask |= 1 << i;
+
+		retval = 0;
+
+		*c_maskp = cpu_to_le32 (mask << 8);
+	}
+#else
 	/* Make sure this tt's buffer is also available for CSPLITs.
 	 * We pessimize a bit; probably the typical full speed case
 	 * doesn't need the second CSPLIT.
@@ -514,6 +718,7 @@
 			goto done;
 		retval = 0;
 	}
+#endif
 done:
 	return retval;
 }
@@ -1047,12 +1252,21 @@
 		frame = uframe >> 3;
 		uf = uframe & 7;
 
+#ifdef CONFIG_USB_EHCI_TT_NEWSCHED
+		/* The tt's fullspeed bus bandwidth must be available.
+		 * tt_available scheduling guarantees 10+% for control/bulk.
+		 */
+		if (!tt_available (ehci, period_uframes << 3,
+				stream->udev, frame, uf, stream->tt_usecs))
+			return 0;
+#else
 		/* tt must be idle for start(s), any gap, and csplit.
 		 * assume scheduling slop leaves 10+% for control/bulk.
 		 */
 		if (!tt_no_collision (ehci, period_uframes << 3,
 				stream->udev, frame, mask))
 			return 0;
+#endif
 
 		/* check starts (OUT uses more than one) */
 		max_used = 100 - stream->usecs;
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 2fe7fd1..4a22909 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -411,8 +411,7 @@
 	urb_entry_t *urb_entry = __urb_list_entry(urb, epid);
 	assert(urb_entry);
 
-	list_del(&urb_entry->list);
-	list_add_tail(&urb_entry->list, &urb_list[epid]);
+	list_move_tail(&urb_entry->list, &urb_list[epid]);
 }
 
 /* Get the next urb in the list. */
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index e99210b..1438625 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -63,7 +63,7 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/usb.h>
-#include <linux/usb_isp116x.h>
+#include <linux/usb/isp116x.h>
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
@@ -781,7 +781,7 @@
 		if (ep->branch < PERIODIC_SIZE)
 			break;
 
-		ret = ep->branch = balance(isp116x, ep->period, ep->load);
+		ep->branch = ret = balance(isp116x, ep->period, ep->load);
 		if (ret < 0)
 			goto fail;
 		ret = 0;
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index a923430..6b4bc3f 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -46,7 +46,7 @@
 #include <linux/list.h>
 #include <linux/interrupt.h>
 #include <linux/usb.h>
-#include <linux/usb_sl811.h>
+#include <linux/usb/sl811.h>
 #include <linux/platform_device.h>
 
 #include <asm/io.h>
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
index 302aa1e..54f554e 100644
--- a/drivers/usb/host/sl811_cs.c
+++ b/drivers/usb/host/sl811_cs.c
@@ -27,7 +27,7 @@
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
 
-#include <linux/usb_sl811.h>
+#include <linux/usb/sl811.h>
 
 MODULE_AUTHOR("Botond Botyanszki");
 MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6");
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index e123931..6637a0e 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -98,6 +98,7 @@
 	char *out = buf;
 	struct uhci_td *td;
 	int i, nactive, ninactive;
+	char *ptype;
 
 	if (len < 200)
 		return 0;
@@ -110,13 +111,15 @@
 			(usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
 
 	switch (usb_pipetype(urbp->urb->pipe)) {
-	case PIPE_ISOCHRONOUS: out += sprintf(out, "ISO"); break;
-	case PIPE_INTERRUPT: out += sprintf(out, "INT"); break;
-	case PIPE_BULK: out += sprintf(out, "BLK"); break;
-	case PIPE_CONTROL: out += sprintf(out, "CTL"); break;
+	case PIPE_ISOCHRONOUS: ptype = "ISO"; break;
+	case PIPE_INTERRUPT: ptype = "INT"; break;
+	case PIPE_BULK: ptype = "BLK"; break;
+	default:
+	case PIPE_CONTROL: ptype = "CTL"; break;
 	}
 
-	out += sprintf(out, "%s", (urbp->fsbr ? " FSBR" : ""));
+	out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : ""));
+	out += sprintf(out, " Actlen=%d", urbp->urb->actual_length);
 
 	if (urbp->urb->status != -EINPROGRESS)
 		out += sprintf(out, " Status=%d", urbp->urb->status);
@@ -124,7 +127,8 @@
 
 	i = nactive = ninactive = 0;
 	list_for_each_entry(td, &urbp->td_list, list) {
-		if (++i <= 10 || debug > 2) {
+		if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC &&
+				(++i <= 10 || debug > 2)) {
 			out += sprintf(out, "%*s%d: ", space + 2, "", i);
 			out += uhci_show_td(td, out, len - (out - buf), 0);
 		} else {
@@ -147,13 +151,27 @@
 	char *out = buf;
 	int i, nurbs;
 	__le32 element = qh_element(qh);
+	char *qtype;
 
 	/* Try to make sure there's enough memory */
-	if (len < 80 * 6)
+	if (len < 80 * 7)
 		return 0;
 
-	out += sprintf(out, "%*s[%p] link (%08x) element (%08x)\n", space, "",
-			qh, le32_to_cpu(qh->link), le32_to_cpu(element));
+	switch (qh->type) {
+	case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break;
+	case USB_ENDPOINT_XFER_INT: qtype = "INT"; break;
+	case USB_ENDPOINT_XFER_BULK: qtype = "BLK"; break;
+	case USB_ENDPOINT_XFER_CONTROL: qtype = "CTL"; break;
+	default: qtype = "Skel" ; break;
+	}
+
+	out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n",
+			space, "", qh, qtype,
+			le32_to_cpu(qh->link), le32_to_cpu(element));
+	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+		out += sprintf(out, "%*s    period %d frame %x desc [%p]\n",
+				space, "", qh->period, qh->iso_frame,
+				qh->iso_packet_desc);
 
 	if (element & UHCI_PTR_QH)
 		out += sprintf(out, "%*s  Element points to QH (bug?)\n", space, "");
@@ -261,7 +279,8 @@
 	    default:
 		rh_state = "?";			break;
 	}
-	out += sprintf(out, "Root-hub state: %s\n", rh_state);
+	out += sprintf(out, "Root-hub state: %s   FSBR: %d\n",
+			rh_state, uhci->fsbr_is_on);
 	return out - buf;
 }
 
@@ -275,7 +294,7 @@
 	unsigned short portsc1, portsc2;
 
 	/* Try to make sure there's enough memory */
-	if (len < 80 * 6)
+	if (len < 80 * 9)
 		return 0;
 
 	usbcmd    = inw(io_addr + 0);
@@ -314,6 +333,10 @@
 	out += sprintf(out, "  sof       =       %02x\n", sof);
 	out += uhci_show_sc(1, portsc1, out, len - (out - buf));
 	out += uhci_show_sc(2, portsc2, out, len - (out - buf));
+	out += sprintf(out, "Most recent frame: %x (%d)   "
+			"Last ISO frame: %x (%d)\n",
+			uhci->frame_number, uhci->frame_number & 1023,
+			uhci->last_iso_frame, uhci->last_iso_frame & 1023);
 
 	return out - buf;
 }
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index d225e11..7b48567 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -13,7 +13,7 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
  *
  * Intel documents this fairly well, and as far as I know there
  * are no royalties or anything like that, but even so there are
@@ -31,7 +31,6 @@
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
 #include <linux/interrupt.h>
@@ -88,15 +87,6 @@
 static void wakeup_rh(struct uhci_hcd *uhci);
 static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 
-/* If a transfer is still active after this much time, turn off FSBR */
-#define IDLE_TIMEOUT	msecs_to_jiffies(50)
-#define FSBR_DELAY	msecs_to_jiffies(50)
-
-/* When we timeout an idle transfer for FSBR, we'll switch it over to */
-/* depth first traversal. We'll do it in groups of this number of TDs */
-/* to make sure it doesn't hog all of the bandwidth */
-#define DEPTH_INTERVAL 5
-
 #include "uhci-debug.c"
 #include "uhci-q.c"
 #include "uhci-hub.c"
@@ -120,22 +110,29 @@
 	uhci->is_stopped = UHCI_IS_STOPPED;
 	uhci_to_hcd(uhci)->state = HC_STATE_HALT;
 	uhci_to_hcd(uhci)->poll_rh = 0;
+
+	uhci->dead = 0;		/* Full reset resurrects the controller */
 }
 
 /*
  * Last rites for a defunct/nonfunctional controller
  * or one we don't want to use any more.
  */
-static void hc_died(struct uhci_hcd *uhci)
+static void uhci_hc_died(struct uhci_hcd *uhci)
 {
+	uhci_get_current_frame_number(uhci);
 	uhci_reset_hc(to_pci_dev(uhci_dev(uhci)), uhci->io_addr);
 	finish_reset(uhci);
-	uhci->hc_inaccessible = 1;
+	uhci->dead = 1;
+
+	/* The current frame may already be partway finished */
+	++uhci->frame_number;
 }
 
 /*
- * Initialize a controller that was newly discovered or has just been
- * resumed.  In either case we can't be sure of its previous state.
+ * Initialize a controller that was newly discovered or has lost power
+ * or otherwise been reset while it was suspended.  In none of these cases
+ * can we be sure of its previous state.
  */
 static void check_and_reset_hc(struct uhci_hcd *uhci)
 {
@@ -155,7 +152,8 @@
 	outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
 
 	/* Set the current frame number */
-	outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
+	outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER,
+			uhci->io_addr + USBFRNUM);
 
 	/* Mark controller as not halted before we enable interrupts */
 	uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;
@@ -207,7 +205,8 @@
 	int int_enable;
 
 	auto_stop = (new_state == UHCI_RH_AUTO_STOPPED);
-	dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
+	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+			"%s%s\n", __FUNCTION__,
 			(auto_stop ? " (auto-stop)" : ""));
 
 	/* If we get a suspend request when we're already auto-stopped
@@ -241,27 +240,27 @@
 		spin_unlock_irq(&uhci->lock);
 		msleep(1);
 		spin_lock_irq(&uhci->lock);
-		if (uhci->hc_inaccessible)	/* Died */
+		if (uhci->dead)
 			return;
 	}
 	if (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH))
-		dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n");
+		dev_warn(&uhci_to_hcd(uhci)->self.root_hub->dev,
+			"Controller not stopped yet!\n");
 
 	uhci_get_current_frame_number(uhci);
-	smp_wmb();
 
 	uhci->rh_state = new_state;
 	uhci->is_stopped = UHCI_IS_STOPPED;
 	uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
 	uhci_scan_schedule(uhci, NULL);
+	uhci_fsbr_off(uhci);
 }
 
 static void start_rh(struct uhci_hcd *uhci)
 {
 	uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;
 	uhci->is_stopped = 0;
-	smp_wmb();
 
 	/* Mark it configured and running with a 64-byte max packet.
 	 * All interrupts are enabled, even though RESUME won't do anything.
@@ -278,7 +277,8 @@
 __releases(uhci->lock)
 __acquires(uhci->lock)
 {
-	dev_dbg(uhci_dev(uhci), "%s%s\n", __FUNCTION__,
+	dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev,
+			"%s%s\n", __FUNCTION__,
 			uhci->rh_state == UHCI_RH_AUTO_STOPPED ?
 				" (auto-start)" : "");
 
@@ -293,7 +293,7 @@
 		spin_unlock_irq(&uhci->lock);
 		msleep(20);
 		spin_lock_irq(&uhci->lock);
-		if (uhci->hc_inaccessible)	/* Died */
+		if (uhci->dead)
 			return;
 
 		/* End Global Resume and wait for EOP to be sent */
@@ -345,7 +345,7 @@
 							errbuf, ERRBUF_LEN);
 					lprintk(errbuf);
 				}
-				hc_died(uhci);
+				uhci_hc_died(uhci);
 
 				/* Force a callback in case there are
 				 * pending unlinks */
@@ -368,12 +368,21 @@
 
 /*
  * Store the current frame number in uhci->frame_number if the controller
- * is runnning
+ * is runnning.  Expand from 11 bits (of which we use only 10) to a
+ * full-sized integer.
+ *
+ * Like many other parts of the driver, this code relies on being polled
+ * more than once per second as long as the controller is running.
  */
 static void uhci_get_current_frame_number(struct uhci_hcd *uhci)
 {
-	if (!uhci->is_stopped)
-		uhci->frame_number = inw(uhci->io_addr + USBFRNUM);
+	if (!uhci->is_stopped) {
+		unsigned delta;
+
+		delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) &
+				(UHCI_NUMFRAMES - 1);
+		uhci->frame_number += delta;
+	}
 }
 
 /*
@@ -407,7 +416,7 @@
 			uhci->frame, uhci->frame_dma_handle);
 }
 
-static int uhci_reset(struct usb_hcd *hcd)
+static int uhci_init(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned io_size = (unsigned) hcd->rsrc_len;
@@ -459,7 +468,7 @@
 {
 	struct usb_hcd *hcd = (struct usb_hcd *) pci_get_drvdata(pdev);
 
-	hc_died(hcd_to_uhci(hcd));
+	uhci_hc_died(hcd_to_uhci(hcd));
 }
 
 /*
@@ -487,14 +496,10 @@
 
 	hcd->uses_new_polling = 1;
 
-	uhci->fsbr = 0;
-	uhci->fsbrtimeout = 0;
-
 	spin_lock_init(&uhci->lock);
-
-	INIT_LIST_HEAD(&uhci->td_remove_list);
+	setup_timer(&uhci->fsbr_timer, uhci_fsbr_timeout,
+			(unsigned long) uhci);
 	INIT_LIST_HEAD(&uhci->idle_qh_list);
-
 	init_waitqueue_head(&uhci->waitqh);
 
 	if (DEBUG_CONFIGURED) {
@@ -665,11 +670,12 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
 	spin_lock_irq(&uhci->lock);
-	if (!uhci->hc_inaccessible)
-		hc_died(uhci);
+	if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead)
+		uhci_hc_died(uhci);
 	uhci_scan_schedule(uhci, NULL);
 	spin_unlock_irq(&uhci->lock);
 
+	del_timer_sync(&uhci->fsbr_timer);
 	release_uhci(uhci);
 }
 
@@ -677,12 +683,15 @@
 static int uhci_rh_suspend(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+	int rc = 0;
 
 	spin_lock_irq(&uhci->lock);
-	if (!uhci->hc_inaccessible)		/* Not dead */
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))
+		rc = -ESHUTDOWN;
+	else if (!uhci->dead)
 		suspend_rh(uhci, UHCI_RH_SUSPENDED);
 	spin_unlock_irq(&uhci->lock);
-	return 0;
+	return rc;
 }
 
 static int uhci_rh_resume(struct usb_hcd *hcd)
@@ -691,13 +700,10 @@
 	int rc = 0;
 
 	spin_lock_irq(&uhci->lock);
-	if (uhci->hc_inaccessible) {
-		if (uhci->rh_state == UHCI_RH_SUSPENDED) {
-			dev_warn(uhci_dev(uhci), "HC isn't running!\n");
-			rc = -ENODEV;
-		}
-		/* Otherwise the HC is dead */
-	} else
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
+		dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n");
+		rc = -ESHUTDOWN;
+	} else if (!uhci->dead)
 		wakeup_rh(uhci);
 	spin_unlock_irq(&uhci->lock);
 	return rc;
@@ -711,8 +717,8 @@
 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 
 	spin_lock_irq(&uhci->lock);
-	if (uhci->hc_inaccessible)	/* Dead or already suspended */
-		goto done;
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
+		goto done_okay;		/* Already suspended or dead */
 
 	if (uhci->rh_state > UHCI_RH_SUSPENDED) {
 		dev_warn(uhci_dev(uhci), "Root hub isn't suspended!\n");
@@ -725,12 +731,12 @@
 	 */
 	pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0);
 	mb();
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	uhci->hc_inaccessible = 1;
 	hcd->poll_rh = 0;
 
 	/* FIXME: Enable non-PME# remote wakeup? */
 
+done_okay:
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 done:
 	spin_unlock_irq(&uhci->lock);
 	return rc;
@@ -743,24 +749,22 @@
 	dev_dbg(uhci_dev(uhci), "%s\n", __FUNCTION__);
 
 	/* Since we aren't in D3 any more, it's safe to set this flag
-	 * even if the controller was dead.  It might not even be dead
-	 * any more, if the firmware or quirks code has reset it.
+	 * even if the controller was dead.
 	 */
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	mb();
 
-	if (uhci->rh_state == UHCI_RH_RESET)	/* Dead */
-		return 0;
 	spin_lock_irq(&uhci->lock);
 
 	/* FIXME: Disable non-PME# remote wakeup? */
 
-	uhci->hc_inaccessible = 0;
-
-	/* The BIOS may have changed the controller settings during a
-	 * system wakeup.  Check it and reconfigure to avoid problems.
+	/* The firmware or a boot kernel may have changed the controller
+	 * settings during a system wakeup.  Check it and reconfigure
+	 * to avoid problems.
 	 */
 	check_and_reset_hc(uhci);
+
+	/* If the controller was dead before, it's back alive now */
 	configure_hc(uhci);
 
 	if (uhci->rh_state == UHCI_RH_RESET) {
@@ -810,18 +814,15 @@
 static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	unsigned long flags;
-	int is_stopped;
-	int frame_number;
+	unsigned frame_number;
+	unsigned delta;
 
 	/* Minimize latency by avoiding the spinlock */
-	local_irq_save(flags);
-	is_stopped = uhci->is_stopped;
-	smp_rmb();
-	frame_number = (is_stopped ? uhci->frame_number :
-			inw(uhci->io_addr + USBFRNUM));
-	local_irq_restore(flags);
-	return frame_number;
+	frame_number = uhci->frame_number;
+	barrier();
+	delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) &
+			(UHCI_NUMFRAMES - 1);
+	return frame_number + delta;
 }
 
 static const char hcd_name[] = "uhci_hcd";
@@ -836,7 +837,7 @@
 	.flags =		HCD_USB11,
 
 	/* Basic lifecycle operations */
-	.reset =		uhci_reset,
+	.reset =		uhci_init,
 	.start =		uhci_start,
 #ifdef CONFIG_PM
 	.suspend =		uhci_suspend,
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index d5c8f4d..108e3de 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -84,6 +84,13 @@
 #define CAN_SCHEDULE_FRAMES	1000	/* how far in the future frames
 					 * can be scheduled */
 
+/* When no queues need Full-Speed Bandwidth Reclamation,
+ * delay this long before turning FSBR off */
+#define FSBR_OFF_DELAY		msecs_to_jiffies(10)
+
+/* If a queue hasn't advanced after this much time, assume it is stuck */
+#define QH_WAIT_TIMEOUT		msecs_to_jiffies(200)
+
 
 /*
  *	Queue Headers
@@ -121,21 +128,31 @@
 	__le32 element;			/* Queue element (TD) pointer */
 
 	/* Software fields */
-	dma_addr_t dma_handle;
-
 	struct list_head node;		/* Node in the list of QHs */
 	struct usb_host_endpoint *hep;	/* Endpoint information */
 	struct usb_device *udev;
 	struct list_head queue;		/* Queue of urbps for this QH */
 	struct uhci_qh *skel;		/* Skeleton for this QH */
 	struct uhci_td *dummy_td;	/* Dummy TD to end the queue */
+	struct uhci_td *post_td;	/* Last TD completed */
 
+	struct usb_iso_packet_descriptor *iso_packet_desc;
+					/* Next urb->iso_frame_desc entry */
+	unsigned long advance_jiffies;	/* Time of last queue advance */
 	unsigned int unlink_frame;	/* When the QH was unlinked */
+	unsigned int period;		/* For Interrupt and Isochronous QHs */
+	unsigned int iso_frame;		/* Frame # for iso_packet_desc */
+	int iso_status;			/* Status for Isochronous URBs */
+
 	int state;			/* QH_STATE_xxx; see above */
+	int type;			/* Queue type (control, bulk, etc) */
+
+	dma_addr_t dma_handle;
 
 	unsigned int initial_toggle:1;	/* Endpoint's current toggle value */
 	unsigned int needs_fixup:1;	/* Must fix the TD toggle values */
-	unsigned int is_stopped:1;	/* Queue was stopped by an error */
+	unsigned int is_stopped:1;	/* Queue was stopped by error/unlink */
+	unsigned int wait_expired:1;	/* QH_WAIT_TIMEOUT has expired */
 } __attribute__((aligned(16)));
 
 /*
@@ -226,7 +243,6 @@
 	dma_addr_t dma_handle;
 
 	struct list_head list;
-	struct list_head remove_list;
 
 	int frame;			/* for iso: what frame? */
 	struct list_head fl_list;
@@ -305,38 +321,8 @@
 #define skel_bulk_qh		skelqh[12]
 #define skel_term_qh		skelqh[13]
 
-/*
- * Search tree for determining where <interval> fits in the skelqh[]
- * skeleton.
- *
- * An interrupt request should be placed into the slowest skelqh[]
- * which meets the interval/period/frequency requirement.
- * An interrupt request is allowed to be faster than <interval> but not slower.
- *
- * For a given <interval>, this function returns the appropriate/matching
- * skelqh[] index value.
- */
-static inline int __interval_to_skel(int interval)
-{
-	if (interval < 16) {
-		if (interval < 4) {
-			if (interval < 2)
-				return 9;	/* int1 for 0-1 ms */
-			return 8;		/* int2 for 2-3 ms */
-		}
-		if (interval < 8)
-			return 7;		/* int4 for 4-7 ms */
-		return 6;			/* int8 for 8-15 ms */
-	}
-	if (interval < 64) {
-		if (interval < 32)
-			return 5;		/* int16 for 16-31 ms */
-		return 4;			/* int32 for 32-63 ms */
-	}
-	if (interval < 128)
-		return 3;			/* int64 for 64-127 ms */
-	return 2;				/* int128 for 128-255 ms (Max.) */
-}
+/* Find the skelqh entry corresponding to an interval exponent */
+#define UHCI_SKEL_INDEX(exponent)	(9 - exponent)
 
 
 /*
@@ -396,32 +382,32 @@
 	__le32 *frame;
 	void **frame_cpu;		/* CPU's frame list */
 
-	int fsbr;			/* Full-speed bandwidth reclamation */
-	unsigned long fsbrtimeout;	/* FSBR delay */
-
 	enum uhci_rh_state rh_state;
 	unsigned long auto_stop_time;		/* When to AUTO_STOP */
 
 	unsigned int frame_number;		/* As of last check */
 	unsigned int is_stopped;
 #define UHCI_IS_STOPPED		9999		/* Larger than a frame # */
+	unsigned int last_iso_frame;		/* Frame of last scan */
+	unsigned int cur_iso_frame;		/* Frame for current scan */
 
 	unsigned int scan_in_progress:1;	/* Schedule scan is running */
 	unsigned int need_rescan:1;		/* Redo the schedule scan */
-	unsigned int hc_inaccessible:1;		/* HC is suspended or dead */
+	unsigned int dead:1;			/* Controller has died */
 	unsigned int working_RD:1;		/* Suspended root hub doesn't
 						   need to be polled */
 	unsigned int is_initialized:1;		/* Data structure is usable */
+	unsigned int fsbr_is_on:1;		/* FSBR is turned on */
+	unsigned int fsbr_is_wanted:1;		/* Does any URB want FSBR? */
+	unsigned int fsbr_expiring:1;		/* FSBR is timing out */
+
+	struct timer_list fsbr_timer;		/* For turning off FBSR */
 
 	/* Support for port suspend/resume/reset */
 	unsigned long port_c_suspend;		/* Bit-arrays of ports */
 	unsigned long resuming_ports;
 	unsigned long ports_timeout;		/* Time to stop signalling */
 
-	/* List of TDs that are done, but waiting to be freed (race) */
-	struct list_head td_remove_list;
-	unsigned int td_remove_age;		/* Age in frames */
-
 	struct list_head idle_qh_list;		/* Where the idle QHs live */
 
 	int rh_numports;			/* Number of root-hub ports */
@@ -442,6 +428,9 @@
 
 #define uhci_dev(u)	(uhci_to_hcd(u)->self.controller)
 
+/* Utility macro for comparing frame numbers */
+#define uhci_frame_before_eq(f1, f2)	(0 <= (int) ((f2) - (f1)))
+
 
 /*
  *	Private per-URB data
@@ -454,9 +443,7 @@
 	struct uhci_qh *qh;		/* QH for this URB */
 	struct list_head td_list;
 
-	unsigned fsbr : 1;		/* URB turned on FSBR */
-	unsigned short_transfer : 1;	/* URB got a short transfer, no
-					 * need to rescan */
+	unsigned fsbr:1;		/* URB wants FSBR */
 };
 
 
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index c8451d9..c545ef9 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -171,9 +171,8 @@
 	spin_lock_irqsave(&uhci->lock, flags);
 
 	uhci_scan_schedule(uhci, NULL);
-	if (uhci->hc_inaccessible)
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
 		goto done;
-	check_fsbr(uhci);
 	uhci_check_ports(uhci);
 
 	status = get_hub_status_data(uhci, buf);
@@ -228,7 +227,7 @@
 	u16 wPortChange, wPortStatus;
 	unsigned long flags;
 
-	if (uhci->hc_inaccessible)
+	if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead)
 		return -ETIMEDOUT;
 
 	spin_lock_irqsave(&uhci->lock, flags);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index a06d84c..c9d72ac 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -13,10 +13,9 @@
  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu
+ * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu
  */
 
-static void uhci_free_pending_tds(struct uhci_hcd *uhci);
 
 /*
  * Technically, updating td->status here is a race, but it's not really a
@@ -38,6 +37,60 @@
 	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
 }
 
+
+/*
+ * Full-Speed Bandwidth Reclamation (FSBR).
+ * We turn on FSBR whenever a queue that wants it is advancing,
+ * and leave it on for a short time thereafter.
+ */
+static void uhci_fsbr_on(struct uhci_hcd *uhci)
+{
+	uhci->fsbr_is_on = 1;
+	uhci->skel_term_qh->link = cpu_to_le32(
+			uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+}
+
+static void uhci_fsbr_off(struct uhci_hcd *uhci)
+{
+	uhci->fsbr_is_on = 0;
+	uhci->skel_term_qh->link = UHCI_PTR_TERM;
+}
+
+static void uhci_add_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = urb->hcpriv;
+
+	if (!(urb->transfer_flags & URB_NO_FSBR))
+		urbp->fsbr = 1;
+}
+
+static void uhci_urbp_wants_fsbr(struct uhci_hcd *uhci, struct urb_priv *urbp)
+{
+	if (urbp->fsbr) {
+		uhci->fsbr_is_wanted = 1;
+		if (!uhci->fsbr_is_on)
+			uhci_fsbr_on(uhci);
+		else if (uhci->fsbr_expiring) {
+			uhci->fsbr_expiring = 0;
+			del_timer(&uhci->fsbr_timer);
+		}
+	}
+}
+
+static void uhci_fsbr_timeout(unsigned long _uhci)
+{
+	struct uhci_hcd *uhci = (struct uhci_hcd *) _uhci;
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->lock, flags);
+	if (uhci->fsbr_expiring) {
+		uhci->fsbr_expiring = 0;
+		uhci_fsbr_off(uhci);
+	}
+	spin_unlock_irqrestore(&uhci->lock, flags);
+}
+
+
 static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci)
 {
 	dma_addr_t dma_handle;
@@ -51,7 +104,6 @@
 	td->frame = -1;
 
 	INIT_LIST_HEAD(&td->list);
-	INIT_LIST_HEAD(&td->remove_list);
 	INIT_LIST_HEAD(&td->fl_list);
 
 	return td;
@@ -61,8 +113,6 @@
 {
 	if (!list_empty(&td->list))
 		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
-	if (!list_empty(&td->remove_list))
-		dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
 	if (!list_empty(&td->fl_list))
 		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
 
@@ -77,6 +127,16 @@
 	td->buffer = cpu_to_le32(buffer);
 }
 
+static void uhci_add_td_to_urbp(struct uhci_td *td, struct urb_priv *urbp)
+{
+	list_add_tail(&td->list, &urbp->td_list);
+}
+
+static void uhci_remove_td_from_urbp(struct uhci_td *td)
+{
+	list_del_init(&td->list);
+}
+
 /*
  * We insert Isochronous URBs directly into the frame list at the beginning
  */
@@ -138,6 +198,24 @@
 	td->frame = -1;
 }
 
+static inline void uhci_remove_tds_from_frame(struct uhci_hcd *uhci,
+		unsigned int framenum)
+{
+	struct uhci_td *ftd, *ltd;
+
+	framenum &= (UHCI_NUMFRAMES - 1);
+
+	ftd = uhci->frame_cpu[framenum];
+	if (ftd) {
+		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
+		uhci->frame[framenum] = ltd->link;
+		uhci->frame_cpu[framenum] = NULL;
+
+		while (!list_empty(&ftd->fl_list))
+			list_del_init(ftd->fl_list.prev);
+	}
+}
+
 /*
  * Remove all the TDs for an Isochronous URB from the frame list
  */
@@ -148,7 +226,6 @@
 
 	list_for_each_entry(td, &urbp->td_list, list)
 		uhci_remove_td_from_frame_list(uhci, td);
-	wmb();
 }
 
 static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci,
@@ -161,6 +238,7 @@
 	if (!qh)
 		return NULL;
 
+	memset(qh, 0, sizeof(*qh));
 	qh->dma_handle = dma_handle;
 
 	qh->element = UHCI_PTR_TERM;
@@ -179,10 +257,11 @@
 		qh->hep = hep;
 		qh->udev = udev;
 		hep->hcpriv = qh;
+		qh->type = hep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 
 	} else {		/* Skeleton QH */
 		qh->state = QH_STATE_ACTIVE;
-		qh->udev = NULL;
+		qh->type = -1;
 	}
 	return qh;
 }
@@ -202,35 +281,64 @@
 }
 
 /*
- * When the currently executing URB is dequeued, save its current toggle value
+ * When a queue is stopped and a dequeued URB is given back, adjust
+ * the previous TD link (if the URB isn't first on the queue) or
+ * save its toggle value (if it is first and is currently executing).
+ *
+ * Returns 0 if the URB should not yet be given back, 1 otherwise.
  */
-static void uhci_save_toggle(struct uhci_qh *qh, struct urb *urb)
+static int uhci_cleanup_queue(struct uhci_hcd *uhci, struct uhci_qh *qh,
+		struct urb *urb)
 {
-	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
+	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
+	int ret = 1;
+
+	/* Isochronous pipes don't use toggles and their TD link pointers
+	 * get adjusted during uhci_urb_dequeue().  But since their queues
+	 * cannot truly be stopped, we have to watch out for dequeues
+	 * occurring after the nominal unlink frame. */
+	if (qh->type == USB_ENDPOINT_XFER_ISOC) {
+		ret = (uhci->frame_number + uhci->is_stopped !=
+				qh->unlink_frame);
+		goto done;
+	}
+
+	/* If the URB isn't first on its queue, adjust the link pointer
+	 * of the last TD in the previous URB.  The toggle doesn't need
+	 * to be saved since this URB can't be executing yet. */
+	if (qh->queue.next != &urbp->node) {
+		struct urb_priv *purbp;
+		struct uhci_td *ptd;
+
+		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
+		WARN_ON(list_empty(&purbp->td_list));
+		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
+				list);
+		td = list_entry(urbp->td_list.prev, struct uhci_td,
+				list);
+		ptd->link = td->link;
+		goto done;
+	}
 
 	/* If the QH element pointer is UHCI_PTR_TERM then then currently
 	 * executing URB has already been unlinked, so this one isn't it. */
-	if (qh_element(qh) == UHCI_PTR_TERM ||
-				qh->queue.next != &urbp->node)
-		return;
+	if (qh_element(qh) == UHCI_PTR_TERM)
+		goto done;
 	qh->element = UHCI_PTR_TERM;
 
-	/* Only bulk and interrupt pipes have to worry about toggles */
-	if (!(usb_pipetype(urb->pipe) == PIPE_BULK ||
-			usb_pipetype(urb->pipe) == PIPE_INTERRUPT))
-		return;
+	/* Control pipes have to worry about toggles */
+	if (qh->type == USB_ENDPOINT_XFER_CONTROL)
+		goto done;
 
-	/* Find the first active TD; that's the device's toggle state */
-	list_for_each_entry(td, &urbp->td_list, list) {
-		if (td_status(td) & TD_CTRL_ACTIVE) {
-			qh->needs_fixup = 1;
-			qh->initial_toggle = uhci_toggle(td_token(td));
-			return;
-		}
-	}
+	/* Save the next toggle value */
+	WARN_ON(list_empty(&urbp->td_list));
+	td = list_entry(urbp->td_list.next, struct uhci_td, list);
+	qh->needs_fixup = 1;
+	qh->initial_toggle = uhci_toggle(td_token(td));
 
-	WARN_ON(1);
+done:
+	return ret;
 }
 
 /*
@@ -305,6 +413,10 @@
 		qh->element = cpu_to_le32(td->dma_handle);
 	}
 
+	/* Treat the queue as if it has just advanced */
+	qh->wait_expired = 0;
+	qh->advance_jiffies = jiffies;
+
 	if (qh->state == QH_STATE_ACTIVE)
 		return;
 	qh->state = QH_STATE_ACTIVE;
@@ -370,6 +482,12 @@
 	list_move(&qh->node, &uhci->idle_qh_list);
 	qh->state = QH_STATE_IDLE;
 
+	/* Now that the QH is idle, its post_td isn't being used */
+	if (qh->post_td) {
+		uhci_free_td(uhci, qh->post_td);
+		qh->post_td = NULL;
+	}
+
 	/* If anyone is waiting for a QH to become idle, wake them up */
 	if (uhci->num_waiting)
 		wake_up_all(&uhci->waitqh);
@@ -395,21 +513,6 @@
 	return urbp;
 }
 
-static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	list_add_tail(&td->list, &urbp->td_list);
-}
-
-static void uhci_remove_td_from_urb(struct uhci_td *td)
-{
-	if (list_empty(&td->list))
-		return;
-
-	list_del_init(&td->list);
-}
-
 static void uhci_free_urb_priv(struct uhci_hcd *uhci,
 		struct urb_priv *urbp)
 {
@@ -419,48 +522,15 @@
 		dev_warn(uhci_dev(uhci), "urb %p still on QH's list!\n",
 				urbp->urb);
 
-	uhci_get_current_frame_number(uhci);
-	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age) {
-		uhci_free_pending_tds(uhci);
-		uhci->td_remove_age = uhci->frame_number;
-	}
-
-	/* Check to see if the remove list is empty. Set the IOC bit */
-	/* to force an interrupt so we can remove the TDs. */
-	if (list_empty(&uhci->td_remove_list))
-		uhci_set_next_interrupt(uhci);
-
 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
-		uhci_remove_td_from_urb(td);
-		list_add(&td->remove_list, &uhci->td_remove_list);
+		uhci_remove_td_from_urbp(td);
+		uhci_free_td(uhci, td);
 	}
 
 	urbp->urb->hcpriv = NULL;
 	kmem_cache_free(uhci_up_cachep, urbp);
 }
 
-static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) {
-		urbp->fsbr = 1;
-		if (!uhci->fsbr++ && !uhci->fsbrtimeout)
-			uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
-	}
-}
-
-static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) {
-		urbp->fsbr = 0;
-		if (!--uhci->fsbr)
-			uhci->fsbrtimeout = jiffies + FSBR_DELAY;
-	}
-}
-
 /*
  * Map status to standard result codes
  *
@@ -487,7 +557,6 @@
 		return -ENOSR;
 	if (status & TD_CTRL_STALLED)			/* Stalled */
 		return -EPIPE;
-	WARN_ON(status & TD_CTRL_ACTIVE);		/* Active */
 	return 0;
 }
 
@@ -503,6 +572,7 @@
 	int len = urb->transfer_buffer_length;
 	dma_addr_t data = urb->transfer_dma;
 	__le32 *plink;
+	struct urb_priv *urbp = urb->hcpriv;
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
@@ -516,7 +586,7 @@
 	 * Build the TD for the control request setup packet
 	 */
 	td = qh->dummy_td;
-	uhci_add_td_to_urb(urb, td);
+	uhci_add_td_to_urbp(td, urbp);
 	uhci_fill_td(td, status, destination | uhci_explen(8),
 			urb->setup_dma);
 	plink = &td->link;
@@ -548,7 +618,7 @@
 		/* Alternate Data0/1 (start with Data1) */
 		destination ^= TD_TOKEN_TOGGLE;
 	
-		uhci_add_td_to_urb(urb, td);
+		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status, destination | uhci_explen(pktsze),
 				data);
 		plink = &td->link;
@@ -579,7 +649,7 @@
 
 	status &= ~TD_CTRL_SPD;
 
-	uhci_add_td_to_urb(urb, td);
+	uhci_add_td_to_urbp(td, urbp);
 	uhci_fill_td(td, status | TD_CTRL_IOC,
 			destination | uhci_explen(0), 0);
 	plink = &td->link;
@@ -606,145 +676,19 @@
 		qh->skel = uhci->skel_ls_control_qh;
 	else {
 		qh->skel = uhci->skel_fs_control_qh;
-		uhci_inc_fsbr(uhci, urb);
+		uhci_add_fsbr(uhci, urb);
 	}
+
+	urb->actual_length = -8;	/* Account for the SETUP packet */
 	return 0;
 
 nomem:
 	/* Remove the dummy TD from the td_list so it doesn't get freed */
-	uhci_remove_td_from_urb(qh->dummy_td);
+	uhci_remove_td_from_urbp(qh->dummy_td);
 	return -ENOMEM;
 }
 
 /*
- * If control-IN transfer was short, the status packet wasn't sent.
- * This routine changes the element pointer in the QH to point at the
- * status TD.  It's safe to do this even while the QH is live, because
- * the hardware only updates the element pointer following a successful
- * transfer.  The inactive TD for the short packet won't cause an update,
- * so the pointer won't get overwritten.  The next time the controller
- * sees this QH, it will send the status packet.
- */
-static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-
-	urbp->short_transfer = 1;
-
-	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
-	urbp->qh->element = cpu_to_le32(td->dma_handle);
-
-	return -EINPROGRESS;
-}
-
-
-static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct list_head *tmp, *head;
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status;
-	int ret = 0;
-
-	head = &urbp->td_list;
-	if (urbp->short_transfer) {
-		tmp = head->prev;
-		goto status_stage;
-	}
-
-	urb->actual_length = 0;
-
-	tmp = head->next;
-	td = list_entry(tmp, struct uhci_td, list);
-
-	/* The first TD is the SETUP stage, check the status, but skip */
-	/*  the count */
-	status = uhci_status_bits(td_status(td));
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
-
-	if (status)
-		goto td_error;
-
-	/* The rest of the TDs (but the last) are data */
-	tmp = tmp->next;
-	while (tmp != head && tmp->next != head) {
-		unsigned int ctrlstat;
-
-		td = list_entry(tmp, struct uhci_td, list);
-		tmp = tmp->next;
-
-		ctrlstat = td_status(td);
-		status = uhci_status_bits(ctrlstat);
-		if (status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		urb->actual_length += uhci_actual_length(ctrlstat);
-
-		if (status)
-			goto td_error;
-
-		/* Check to see if we received a short packet */
-		if (uhci_actual_length(ctrlstat) <
-				uhci_expected_length(td_token(td))) {
-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-				ret = -EREMOTEIO;
-				goto err;
-			}
-
-			return usb_control_retrigger_status(uhci, urb);
-		}
-	}
-
-status_stage:
-	td = list_entry(tmp, struct uhci_td, list);
-
-	/* Control status stage */
-	status = td_status(td);
-
-#ifdef I_HAVE_BUGGY_APC_BACKUPS
-	/* APC BackUPS Pro kludge */
-	/* It tries to send all of the descriptor instead of the amount */
-	/*  we requested */
-	if (status & TD_CTRL_IOC &&	/* IOC is masked out by uhci_status_bits */
-	    status & TD_CTRL_ACTIVE &&
-	    status & TD_CTRL_NAK)
-		return 0;
-#endif
-
-	status = uhci_status_bits(status);
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
-
-	if (status)
-		goto td_error;
-
-	return 0;
-
-td_error:
-	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-
-err:
-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
-		/* Some debugging code */
-		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
-				__FUNCTION__, status);
-
-		if (errbuf) {
-			/* Print the chain for debugging purposes */
-			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-			lprintk(errbuf);
-		}
-	}
-
-	/* Note that the queue has stopped */
-	urbp->qh->element = UHCI_PTR_TERM;
-	urbp->qh->is_stopped = 1;
-	return ret;
-}
-
-/*
  * Common submit for bulk and interrupt
  */
 static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
@@ -756,6 +700,7 @@
 	int len = urb->transfer_buffer_length;
 	dma_addr_t data = urb->transfer_dma;
 	__le32 *plink;
+	struct urb_priv *urbp = urb->hcpriv;
 	unsigned int toggle;
 
 	if (len < 0)
@@ -793,7 +738,7 @@
 				goto nomem;
 			*plink = cpu_to_le32(td->dma_handle);
 		}
-		uhci_add_td_to_urb(urb, td);
+		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status,
 				destination | uhci_explen(pktsze) |
 					(toggle << TD_TOKEN_TOGGLE_SHIFT),
@@ -821,7 +766,7 @@
 			goto nomem;
 		*plink = cpu_to_le32(td->dma_handle);
 
-		uhci_add_td_to_urb(urb, td);
+		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status,
 				destination | uhci_explen(0) |
 					(toggle << TD_TOKEN_TOGGLE_SHIFT),
@@ -851,6 +796,7 @@
 	wmb();
 	qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE);
 	qh->dummy_td = td;
+	qh->period = urb->interval;
 
 	usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			usb_pipeout(urb->pipe), toggle);
@@ -858,90 +804,10 @@
 
 nomem:
 	/* Remove the dummy TD from the td_list so it doesn't get freed */
-	uhci_remove_td_from_urb(qh->dummy_td);
+	uhci_remove_td_from_urbp(qh->dummy_td);
 	return -ENOMEM;
 }
 
-/*
- * Common result for bulk and interrupt
- */
-static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status = 0;
-	int ret = 0;
-
-	urb->actual_length = 0;
-
-	list_for_each_entry(td, &urbp->td_list, list) {
-		unsigned int ctrlstat = td_status(td);
-
-		status = uhci_status_bits(ctrlstat);
-		if (status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		urb->actual_length += uhci_actual_length(ctrlstat);
-
-		if (status)
-			goto td_error;
-
-		if (uhci_actual_length(ctrlstat) <
-				uhci_expected_length(td_token(td))) {
-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-				ret = -EREMOTEIO;
-				goto err;
-			}
-
-			/*
-			 * This URB stopped short of its end.  We have to
-			 * fix up the toggles of the following URBs on the
-			 * queue and restart the queue.
-			 *
-			 * Do this only the first time we encounter the
-			 * short URB.
-			 */
-			if (!urbp->short_transfer) {
-				urbp->short_transfer = 1;
-				urbp->qh->initial_toggle =
-						uhci_toggle(td_token(td)) ^ 1;
-				uhci_fixup_toggles(urbp->qh, 1);
-
-				td = list_entry(urbp->td_list.prev,
-						struct uhci_td, list);
-				urbp->qh->element = td->link;
-			}
-			break;
-		}
-	}
-
-	return 0;
-
-td_error:
-	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-
-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
-		/* Some debugging code */
-		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
-				__FUNCTION__, status);
-
-		if (debug > 1 && errbuf) {
-			/* Print the chain for debugging purposes */
-			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-			lprintk(errbuf);
-		}
-	}
-err:
-
-	/* Note that the queue has stopped and save the next toggle value */
-	urbp->qh->element = UHCI_PTR_TERM;
-	urbp->qh->is_stopped = 1;
-	urbp->qh->needs_fixup = 1;
-	urbp->qh->initial_toggle = uhci_toggle(td_token(td)) ^
-			(ret == -EREMOTEIO);
-	return ret;
-}
-
 static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb,
 		struct uhci_qh *qh)
 {
@@ -954,22 +820,163 @@
 	qh->skel = uhci->skel_bulk_qh;
 	ret = uhci_submit_common(uhci, urb, qh);
 	if (ret == 0)
-		uhci_inc_fsbr(uhci, urb);
+		uhci_add_fsbr(uhci, urb);
 	return ret;
 }
 
-static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
+static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
 		struct uhci_qh *qh)
 {
+	int exponent;
+
 	/* USB 1.1 interrupt transfers only involve one packet per interval.
 	 * Drivers can submit URBs of any length, but longer ones will need
 	 * multiple intervals to complete.
 	 */
-	qh->skel = uhci->skelqh[__interval_to_skel(urb->interval)];
+
+	/* Figure out which power-of-two queue to use */
+	for (exponent = 7; exponent >= 0; --exponent) {
+		if ((1 << exponent) <= urb->interval)
+			break;
+	}
+	if (exponent < 0)
+		return -EINVAL;
+	urb->interval = 1 << exponent;
+
+	if (qh->period == 0)
+		qh->skel = uhci->skelqh[UHCI_SKEL_INDEX(exponent)];
+	else if (qh->period != urb->interval)
+		return -EINVAL;		/* Can't change the period */
+
 	return uhci_submit_common(uhci, urb, qh);
 }
 
 /*
+ * Fix up the data structures following a short transfer
+ */
+static int uhci_fixup_short_transfer(struct uhci_hcd *uhci,
+		struct uhci_qh *qh, struct urb_priv *urbp)
+{
+	struct uhci_td *td;
+	struct list_head *tmp;
+	int ret;
+
+	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
+	if (qh->type == USB_ENDPOINT_XFER_CONTROL) {
+
+		/* When a control transfer is short, we have to restart
+		 * the queue at the status stage transaction, which is
+		 * the last TD. */
+		WARN_ON(list_empty(&urbp->td_list));
+		qh->element = cpu_to_le32(td->dma_handle);
+		tmp = td->list.prev;
+		ret = -EINPROGRESS;
+
+	} else {
+
+		/* When a bulk/interrupt transfer is short, we have to
+		 * fix up the toggles of the following URBs on the queue
+		 * before restarting the queue at the next URB. */
+		qh->initial_toggle = uhci_toggle(td_token(qh->post_td)) ^ 1;
+		uhci_fixup_toggles(qh, 1);
+
+		if (list_empty(&urbp->td_list))
+			td = qh->post_td;
+		qh->element = td->link;
+		tmp = urbp->td_list.prev;
+		ret = 0;
+	}
+
+	/* Remove all the TDs we skipped over, from tmp back to the start */
+	while (tmp != &urbp->td_list) {
+		td = list_entry(tmp, struct uhci_td, list);
+		tmp = tmp->prev;
+
+		uhci_remove_td_from_urbp(td);
+		uhci_free_td(uhci, td);
+	}
+	return ret;
+}
+
+/*
+ * Common result for control, bulk, and interrupt
+ */
+static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = urb->hcpriv;
+	struct uhci_qh *qh = urbp->qh;
+	struct uhci_td *td, *tmp;
+	unsigned status;
+	int ret = 0;
+
+	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+		unsigned int ctrlstat;
+		int len;
+
+		ctrlstat = td_status(td);
+		status = uhci_status_bits(ctrlstat);
+		if (status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
+		len = uhci_actual_length(ctrlstat);
+		urb->actual_length += len;
+
+		if (status) {
+			ret = uhci_map_status(status,
+					uhci_packetout(td_token(td)));
+			if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+				/* Some debugging code */
+				dev_dbg(&urb->dev->dev,
+						"%s: failed with status %x\n",
+						__FUNCTION__, status);
+
+				if (debug > 1 && errbuf) {
+					/* Print the chain for debugging */
+					uhci_show_qh(urbp->qh, errbuf,
+							ERRBUF_LEN, 0);
+					lprintk(errbuf);
+				}
+			}
+
+		} else if (len < uhci_expected_length(td_token(td))) {
+
+			/* We received a short packet */
+			if (urb->transfer_flags & URB_SHORT_NOT_OK)
+				ret = -EREMOTEIO;
+			else if (ctrlstat & TD_CTRL_SPD)
+				ret = 1;
+		}
+
+		uhci_remove_td_from_urbp(td);
+		if (qh->post_td)
+			uhci_free_td(uhci, qh->post_td);
+		qh->post_td = td;
+
+		if (ret != 0)
+			goto err;
+	}
+	return ret;
+
+err:
+	if (ret < 0) {
+		/* In case a control transfer gets an error
+		 * during the setup stage */
+		urb->actual_length = max(urb->actual_length, 0);
+
+		/* Note that the queue has stopped and save
+		 * the next toggle value */
+		qh->element = UHCI_PTR_TERM;
+		qh->is_stopped = 1;
+		qh->needs_fixup = (qh->type != USB_ENDPOINT_XFER_CONTROL);
+		qh->initial_toggle = uhci_toggle(td_token(td)) ^
+				(ret == -EREMOTEIO);
+
+	} else		/* Short packet received */
+		ret = uhci_fixup_short_transfer(uhci, qh, urbp);
+	return ret;
+}
+
+/*
  * Isochronous transfers
  */
 static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb,
@@ -980,38 +987,57 @@
 	unsigned long destination, status;
 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
-	if (urb->number_of_packets > 900)	/* 900? Why? */
+	/* Values must not be too big (could overflow below) */
+	if (urb->interval >= UHCI_NUMFRAMES ||
+			urb->number_of_packets >= UHCI_NUMFRAMES)
+		return -EFBIG;
+
+	/* Check the period and figure out the starting frame number */
+	if (qh->period == 0) {
+		if (urb->transfer_flags & URB_ISO_ASAP) {
+			uhci_get_current_frame_number(uhci);
+			urb->start_frame = uhci->frame_number + 10;
+		} else {
+			i = urb->start_frame - uhci->last_iso_frame;
+			if (i <= 0 || i >= UHCI_NUMFRAMES)
+				return -EINVAL;
+		}
+	} else if (qh->period != urb->interval) {
+		return -EINVAL;		/* Can't change the period */
+
+	} else {	/* Pick up where the last URB leaves off */
+		if (list_empty(&qh->queue)) {
+			frame = qh->iso_frame;
+		} else {
+			struct urb *lurb;
+
+			lurb = list_entry(qh->queue.prev,
+					struct urb_priv, node)->urb;
+			frame = lurb->start_frame +
+					lurb->number_of_packets *
+					lurb->interval;
+		}
+		if (urb->transfer_flags & URB_ISO_ASAP)
+			urb->start_frame = frame;
+		else if (urb->start_frame != frame)
+			return -EINVAL;
+	}
+
+	/* Make sure we won't have to go too far into the future */
+	if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES,
+			urb->start_frame + urb->number_of_packets *
+				urb->interval))
 		return -EFBIG;
 
 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
 
-	/* Figure out the starting frame number */
-	if (urb->transfer_flags & URB_ISO_ASAP) {
-		if (list_empty(&qh->queue)) {
-			uhci_get_current_frame_number(uhci);
-			urb->start_frame = (uhci->frame_number + 10);
-
-		} else {		/* Go right after the last one */
-			struct urb *last_urb;
-
-			last_urb = list_entry(qh->queue.prev,
-					struct urb_priv, node)->urb;
-			urb->start_frame = (last_urb->start_frame +
-					last_urb->number_of_packets *
-					last_urb->interval);
-		}
-	} else {
-		/* FIXME: Sanity check */
-	}
-	urb->start_frame &= (UHCI_NUMFRAMES - 1);
-
 	for (i = 0; i < urb->number_of_packets; i++) {
 		td = uhci_alloc_td(uhci);
 		if (!td)
 			return -ENOMEM;
 
-		uhci_add_td_to_urb(urb, td);
+		uhci_add_td_to_urbp(td, urbp);
 		uhci_fill_td(td, status, destination |
 				uhci_explen(urb->iso_frame_desc[i].length),
 				urb->transfer_dma +
@@ -1022,12 +1048,19 @@
 	td->status |= __constant_cpu_to_le32(TD_CTRL_IOC);
 
 	qh->skel = uhci->skel_iso_qh;
+	qh->period = urb->interval;
 
 	/* Add the TDs to the frame list */
 	frame = urb->start_frame;
 	list_for_each_entry(td, &urbp->td_list, list) {
 		uhci_insert_td_in_frame_list(uhci, td, frame);
-		frame += urb->interval;
+		frame += qh->period;
+	}
+
+	if (list_empty(&qh->queue)) {
+		qh->iso_packet_desc = &urb->iso_frame_desc[0];
+		qh->iso_frame = urb->start_frame;
+		qh->iso_status = 0;
 	}
 
 	return 0;
@@ -1035,37 +1068,44 @@
 
 static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 {
-	struct uhci_td *td;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	int status;
-	int i, ret = 0;
+	struct uhci_td *td, *tmp;
+	struct urb_priv *urbp = urb->hcpriv;
+	struct uhci_qh *qh = urbp->qh;
 
-	urb->actual_length = urb->error_count = 0;
-
-	i = 0;
-	list_for_each_entry(td, &urbp->td_list, list) {
+	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+		unsigned int ctrlstat;
+		int status;
 		int actlength;
-		unsigned int ctrlstat = td_status(td);
 
-		if (ctrlstat & TD_CTRL_ACTIVE)
+		if (uhci_frame_before_eq(uhci->cur_iso_frame, qh->iso_frame))
 			return -EINPROGRESS;
 
-		actlength = uhci_actual_length(ctrlstat);
-		urb->iso_frame_desc[i].actual_length = actlength;
-		urb->actual_length += actlength;
+		uhci_remove_tds_from_frame(uhci, qh->iso_frame);
 
-		status = uhci_map_status(uhci_status_bits(ctrlstat),
-				usb_pipeout(urb->pipe));
-		urb->iso_frame_desc[i].status = status;
-		if (status) {
-			urb->error_count++;
-			ret = status;
+		ctrlstat = td_status(td);
+		if (ctrlstat & TD_CTRL_ACTIVE) {
+			status = -EXDEV;	/* TD was added too late? */
+		} else {
+			status = uhci_map_status(uhci_status_bits(ctrlstat),
+					usb_pipeout(urb->pipe));
+			actlength = uhci_actual_length(ctrlstat);
+
+			urb->actual_length += actlength;
+			qh->iso_packet_desc->actual_length = actlength;
+			qh->iso_packet_desc->status = status;
 		}
 
-		i++;
-	}
+		if (status) {
+			urb->error_count++;
+			qh->iso_status = status;
+		}
 
-	return ret;
+		uhci_remove_td_from_urbp(td);
+		uhci_free_td(uhci, td);
+		qh->iso_frame += qh->period;
+		++qh->iso_packet_desc;
+	}
+	return qh->iso_status;
 }
 
 static int uhci_urb_enqueue(struct usb_hcd *hcd,
@@ -1099,14 +1139,14 @@
 	}
 	urbp->qh = qh;
 
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_CONTROL:
+	switch (qh->type) {
+	case USB_ENDPOINT_XFER_CONTROL:
 		ret = uhci_submit_control(uhci, urb, qh);
 		break;
-	case PIPE_BULK:
+	case USB_ENDPOINT_XFER_BULK:
 		ret = uhci_submit_bulk(uhci, urb, qh);
 		break;
-	case PIPE_INTERRUPT:
+	case USB_ENDPOINT_XFER_INT:
 		if (list_empty(&qh->queue)) {
 			bustime = usb_check_bandwidth(urb->dev, urb);
 			if (bustime < 0)
@@ -1125,7 +1165,8 @@
 			ret = uhci_submit_interrupt(uhci, urb, qh);
 		}
 		break;
-	case PIPE_ISOCHRONOUS:
+	case USB_ENDPOINT_XFER_ISOC:
+		urb->error_count = 0;
 		bustime = usb_check_bandwidth(urb->dev, urb);
 		if (bustime < 0) {
 			ret = bustime;
@@ -1146,9 +1187,12 @@
 
 	/* If the new URB is the first and only one on this QH then either
 	 * the QH is new and idle or else it's unlinked and waiting to
-	 * become idle, so we can activate it right away. */
-	if (qh->queue.next == &urbp->node)
+	 * become idle, so we can activate it right away.  But only if the
+	 * queue isn't stopped. */
+	if (qh->queue.next == &urbp->node && !qh->is_stopped) {
 		uhci_activate_qh(uhci, qh);
+		uhci_urbp_wants_fsbr(uhci, urbp);
+	}
 	goto done;
 
 err_submit_failed:
@@ -1168,16 +1212,26 @@
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 	unsigned long flags;
 	struct urb_priv *urbp;
+	struct uhci_qh *qh;
 
 	spin_lock_irqsave(&uhci->lock, flags);
 	urbp = urb->hcpriv;
 	if (!urbp)			/* URB was never linked! */
 		goto done;
+	qh = urbp->qh;
 
 	/* Remove Isochronous TDs from the frame list ASAP */
-	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+	if (qh->type == USB_ENDPOINT_XFER_ISOC) {
 		uhci_unlink_isochronous_tds(uhci, urb);
-	uhci_unlink_qh(uhci, urbp->qh);
+		mb();
+
+		/* If the URB has already started, update the QH unlink time */
+		uhci_get_current_frame_number(uhci);
+		if (uhci_frame_before_eq(urb->start_frame, uhci->frame_number))
+			qh->unlink_frame = uhci->frame_number;
+	}
+
+	uhci_unlink_qh(uhci, qh);
 
 done:
 	spin_unlock_irqrestore(&uhci->lock, flags);
@@ -1194,22 +1248,17 @@
 {
 	struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv;
 
-	/* Isochronous TDs get unlinked directly from the frame list */
-	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
-		uhci_unlink_isochronous_tds(uhci, urb);
+	/* When giving back the first URB in an Isochronous queue,
+	 * reinitialize the QH's iso-related members for the next URB. */
+	if (qh->type == USB_ENDPOINT_XFER_ISOC &&
+			urbp->node.prev == &qh->queue &&
+			urbp->node.next != &qh->queue) {
+		struct urb *nurb = list_entry(urbp->node.next,
+				struct urb_priv, node)->urb;
 
-	/* If the URB isn't first on its queue, adjust the link pointer
-	 * of the last TD in the previous URB. */
-	else if (qh->queue.next != &urbp->node) {
-		struct urb_priv *purbp;
-		struct uhci_td *ptd, *ltd;
-
-		purbp = list_entry(urbp->node.prev, struct urb_priv, node);
-		ptd = list_entry(purbp->td_list.prev, struct uhci_td,
-				list);
-		ltd = list_entry(urbp->td_list.prev, struct uhci_td,
-				list);
-		ptd->link = ltd->link;
+		qh->iso_packet_desc = &nurb->iso_frame_desc[0];
+		qh->iso_frame = nurb->start_frame;
+		qh->iso_status = 0;
 	}
 
 	/* Take the URB off the QH's queue.  If the queue is now empty,
@@ -1221,16 +1270,15 @@
 		qh->needs_fixup = 0;
 	}
 
-	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
 	uhci_free_urb_priv(uhci, urbp);
 
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_ISOCHRONOUS:
+	switch (qh->type) {
+	case USB_ENDPOINT_XFER_ISOC:
 		/* Release bandwidth for Interrupt or Isoc. transfers */
 		if (urb->bandwidth)
 			usb_release_bandwidth(urb->dev, urb, 1);
 		break;
-	case PIPE_INTERRUPT:
+	case USB_ENDPOINT_XFER_INT:
 		/* Release bandwidth for Interrupt or Isoc. transfers */
 		/* Make sure we don't release if we have a queued URB */
 		if (list_empty(&qh->queue) && urb->bandwidth)
@@ -1252,6 +1300,7 @@
 		uhci_unlink_qh(uhci, qh);
 
 		/* Bandwidth stuff not yet implemented */
+		qh->period = 0;
 	}
 }
 
@@ -1273,17 +1322,10 @@
 		urbp = list_entry(qh->queue.next, struct urb_priv, node);
 		urb = urbp->urb;
 
-		switch (usb_pipetype(urb->pipe)) {
-		case PIPE_CONTROL:
-			status = uhci_result_control(uhci, urb);
-			break;
-		case PIPE_ISOCHRONOUS:
+		if (qh->type == USB_ENDPOINT_XFER_ISOC)
 			status = uhci_result_isochronous(uhci, urb);
-			break;
-		default:	/* PIPE_BULK or PIPE_INTERRUPT */
+		else
 			status = uhci_result_common(uhci, urb);
-			break;
-		}
 		if (status == -EINPROGRESS)
 			break;
 
@@ -1291,31 +1333,43 @@
 		if (urb->status == -EINPROGRESS)	/* Not dequeued */
 			urb->status = status;
 		else
-			status = -ECONNRESET;
+			status = ECONNRESET;		/* Not -ECONNRESET */
 		spin_unlock(&urb->lock);
 
 		/* Dequeued but completed URBs can't be given back unless
 		 * the QH is stopped or has finished unlinking. */
-		if (status == -ECONNRESET &&
-				!(qh->is_stopped || QH_FINISHED_UNLINKING(qh)))
-			return;
+		if (status == ECONNRESET) {
+			if (QH_FINISHED_UNLINKING(qh))
+				qh->is_stopped = 1;
+			else if (!qh->is_stopped)
+				return;
+		}
 
 		uhci_giveback_urb(uhci, qh, urb, regs);
-		if (qh->is_stopped)
+		if (status < 0)
 			break;
 	}
 
 	/* If the QH is neither stopped nor finished unlinking (normal case),
 	 * our work here is done. */
- restart:
-	if (!(qh->is_stopped || QH_FINISHED_UNLINKING(qh)))
+	if (QH_FINISHED_UNLINKING(qh))
+		qh->is_stopped = 1;
+	else if (!qh->is_stopped)
 		return;
 
 	/* Otherwise give back each of the dequeued URBs */
+restart:
 	list_for_each_entry(urbp, &qh->queue, node) {
 		urb = urbp->urb;
 		if (urb->status != -EINPROGRESS) {
-			uhci_save_toggle(qh, urb);
+
+			/* Fix up the TD links and save the toggles for
+			 * non-Isochronous queues.  For Isochronous queues,
+			 * test for too-recent dequeues. */
+			if (!uhci_cleanup_queue(uhci, qh, urb)) {
+				qh->is_stopped = 0;
+				return;
+			}
 			uhci_giveback_urb(uhci, qh, urb, regs);
 			goto restart;
 		}
@@ -1327,6 +1381,18 @@
 	if (!list_empty(&qh->queue)) {
 		if (qh->needs_fixup)
 			uhci_fixup_toggles(qh, 0);
+
+		/* If the first URB on the queue wants FSBR but its time
+		 * limit has expired, set the next TD to interrupt on
+		 * completion before reactivating the QH. */
+		urbp = list_entry(qh->queue.next, struct urb_priv, node);
+		if (urbp->fsbr && qh->wait_expired) {
+			struct uhci_td *td = list_entry(urbp->td_list.next,
+					struct uhci_td, list);
+
+			td->status |= __cpu_to_le32(TD_CTRL_IOC);
+		}
+
 		uhci_activate_qh(uhci, qh);
 	}
 
@@ -1336,15 +1402,84 @@
 		uhci_make_qh_idle(uhci, qh);
 }
 
-static void uhci_free_pending_tds(struct uhci_hcd *uhci)
+/*
+ * Check for queues that have made some forward progress.
+ * Returns 0 if the queue is not Isochronous, is ACTIVE, and
+ * has not advanced since last examined; 1 otherwise.
+ *
+ * Early Intel controllers have a bug which causes qh->element sometimes
+ * not to advance when a TD completes successfully.  The queue remains
+ * stuck on the inactive completed TD.  We detect such cases and advance
+ * the element pointer by hand.
+ */
+static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh)
 {
-	struct uhci_td *td, *tmp;
+	struct urb_priv *urbp = NULL;
+	struct uhci_td *td;
+	int ret = 1;
+	unsigned status;
 
-	list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) {
-		list_del_init(&td->remove_list);
+	if (qh->type == USB_ENDPOINT_XFER_ISOC)
+		goto done;
 
-		uhci_free_td(uhci, td);
+	/* Treat an UNLINKING queue as though it hasn't advanced.
+	 * This is okay because reactivation will treat it as though
+	 * it has advanced, and if it is going to become IDLE then
+	 * this doesn't matter anyway.  Furthermore it's possible
+	 * for an UNLINKING queue not to have any URBs at all, or
+	 * for its first URB not to have any TDs (if it was dequeued
+	 * just as it completed).  So it's not easy in any case to
+	 * test whether such queues have advanced. */
+	if (qh->state != QH_STATE_ACTIVE) {
+		urbp = NULL;
+		status = 0;
+
+	} else {
+		urbp = list_entry(qh->queue.next, struct urb_priv, node);
+		td = list_entry(urbp->td_list.next, struct uhci_td, list);
+		status = td_status(td);
+		if (!(status & TD_CTRL_ACTIVE)) {
+
+			/* We're okay, the queue has advanced */
+			qh->wait_expired = 0;
+			qh->advance_jiffies = jiffies;
+			goto done;
+		}
+		ret = 0;
 	}
+
+	/* The queue hasn't advanced; check for timeout */
+	if (qh->wait_expired)
+		goto done;
+
+	if (time_after(jiffies, qh->advance_jiffies + QH_WAIT_TIMEOUT)) {
+
+		/* Detect the Intel bug and work around it */
+		if (qh->post_td && qh_element(qh) ==
+				cpu_to_le32(qh->post_td->dma_handle)) {
+			qh->element = qh->post_td->link;
+			qh->advance_jiffies = jiffies;
+			ret = 1;
+			goto done;
+		}
+
+		qh->wait_expired = 1;
+
+		/* If the current URB wants FSBR, unlink it temporarily
+		 * so that we can safely set the next TD to interrupt on
+		 * completion.  That way we'll know as soon as the queue
+		 * starts moving again. */
+		if (urbp && urbp->fsbr && !(status & TD_CTRL_IOC))
+			uhci_unlink_qh(uhci, qh);
+
+	} else {
+		/* Unmoving but not-yet-expired queues keep FSBR alive */
+		if (urbp)
+			uhci_urbp_wants_fsbr(uhci, urbp);
+	}
+
+done:
+	return ret;
 }
 
 /*
@@ -1361,14 +1496,13 @@
 		return;
 	}
 	uhci->scan_in_progress = 1;
- rescan:
+rescan:
 	uhci->need_rescan = 0;
+	uhci->fsbr_is_wanted = 0;
 
 	uhci_clear_next_interrupt(uhci);
 	uhci_get_current_frame_number(uhci);
-
-	if (uhci->frame_number + uhci->is_stopped != uhci->td_remove_age)
-		uhci_free_pending_tds(uhci);
+	uhci->cur_iso_frame = uhci->frame_number;
 
 	/* Go through all the QH queues and process the URBs in each one */
 	for (i = 0; i < UHCI_NUM_SKELQH - 1; ++i) {
@@ -1377,33 +1511,30 @@
 		while ((qh = uhci->next_qh) != uhci->skelqh[i]) {
 			uhci->next_qh = list_entry(qh->node.next,
 					struct uhci_qh, node);
-			uhci_scan_qh(uhci, qh, regs);
+
+			if (uhci_advance_check(uhci, qh)) {
+				uhci_scan_qh(uhci, qh, regs);
+				if (qh->state == QH_STATE_ACTIVE) {
+					uhci_urbp_wants_fsbr(uhci,
+	list_entry(qh->queue.next, struct urb_priv, node));
+				}
+			}
 		}
 	}
 
+	uhci->last_iso_frame = uhci->cur_iso_frame;
 	if (uhci->need_rescan)
 		goto rescan;
 	uhci->scan_in_progress = 0;
 
-	/* If the controller is stopped, we can finish these off right now */
-	if (uhci->is_stopped)
-		uhci_free_pending_tds(uhci);
+	if (uhci->fsbr_is_on && !uhci->fsbr_is_wanted &&
+			!uhci->fsbr_expiring) {
+		uhci->fsbr_expiring = 1;
+		mod_timer(&uhci->fsbr_timer, jiffies + FSBR_OFF_DELAY);
+	}
 
-	if (list_empty(&uhci->td_remove_list) &&
-			list_empty(&uhci->skel_unlink_qh->node))
+	if (list_empty(&uhci->skel_unlink_qh->node))
 		uhci_clear_next_interrupt(uhci);
 	else
 		uhci_set_next_interrupt(uhci);
 }
-
-static void check_fsbr(struct uhci_hcd *uhci)
-{
-	/* For now, don't scan URBs for FSBR timeouts.
-	 * Add it back in later... */
-
-	/* Really disable FSBR */
-	if (!uhci->fsbr && uhci->fsbrtimeout && time_after_eq(jiffies, uhci->fsbrtimeout)) {
-		uhci->fsbrtimeout = 0;
-		uhci->skel_term_qh->link = UHCI_PTR_TERM;
-	}
-}
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 2a0e18a..b2bafc3 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -513,7 +513,7 @@
 		mts_transfer_cleanup(transfer);
         }
 
-	sg = context->srb->buffer;
+	sg = context->srb->request_buffer;
 	context->fragment++;
 	mts_int_submit_urb(transfer,
 			   context->data_pipe,
@@ -549,19 +549,19 @@
 	desc->context.fragment = 0;
 
 	if (!srb->use_sg) {
-		if ( !srb->bufflen ){
+		if ( !srb->request_bufflen ){
 			desc->context.data = NULL;
 			desc->context.data_length = 0;
 			return;
 		} else {
-			desc->context.data = srb->buffer;
-			desc->context.data_length = srb->bufflen;
+			desc->context.data = srb->request_buffer;
+			desc->context.data_length = srb->request_bufflen;
 			MTS_DEBUG("length = %d or %d\n",
 				  srb->request_bufflen, srb->bufflen);
 		}
 	} else {
 		MTS_DEBUG("Using scatter/gather\n");
-		sg = srb->buffer;
+		sg = srb->request_buffer;
 		desc->context.data = page_address(sg[0].page) + sg[0].offset;
 		desc->context.data_length = sg[0].length;
 	}
diff --git a/drivers/usb/input/acecad.c b/drivers/usb/input/acecad.c
index df29b80..18c10e1 100644
--- a/drivers/usb/input/acecad.c
+++ b/drivers/usb/input/acecad.c
@@ -27,11 +27,9 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 /*
  * Version Information
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index a6693b0..b138dae 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -73,11 +73,9 @@
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 #include <linux/sched.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
diff --git a/drivers/usb/input/appletouch.c b/drivers/usb/input/appletouch.c
index c222ed1..3685506 100644
--- a/drivers/usb/input/appletouch.c
+++ b/drivers/usb/input/appletouch.c
@@ -1,5 +1,5 @@
 /*
- * Apple USB Touchpad (for post-February 2005 PowerBooks) driver
+ * Apple USB Touchpad (for post-February 2005 PowerBooks and MacBooks) driver
  *
  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2005      Johannes Berg (johannes@sipsolutions.net)
@@ -7,6 +7,7 @@
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
  * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
+ * Copyright (C) 2006      Nicolas Boichat (nicolas@boichat.ch)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
@@ -32,9 +33,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/input.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
@@ -44,6 +43,11 @@
 #define GEYSER_ISO_PRODUCT_ID	0x0215
 #define GEYSER_JIS_PRODUCT_ID	0x0216
 
+/* MacBook devices */
+#define GEYSER3_ANSI_PRODUCT_ID	0x0217
+#define GEYSER3_ISO_PRODUCT_ID	0x0218
+#define GEYSER3_JIS_PRODUCT_ID	0x0219
+
 #define ATP_DEVICE(prod)					\
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
 		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
@@ -65,6 +69,10 @@
 	{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
 	{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
 
+	{ ATP_DEVICE(GEYSER3_ANSI_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER3_ISO_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER3_JIS_PRODUCT_ID) },
+
 	/* Terminating entry */
 	{ }
 };
@@ -101,6 +109,13 @@
  */
 #define ATP_THRESHOLD	 5
 
+/* MacBook Pro (Geyser 3) initialization constants */
+#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1
+#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9
+#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300
+#define ATP_GEYSER3_MODE_REQUEST_INDEX 0
+#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04
+
 /* Structure to hold all of our device specific stuff */
 struct atp {
 	char			phys[64];
@@ -147,13 +162,22 @@
 /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
 static inline int atp_is_geyser_2(struct atp *dev)
 {
-	int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+	u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
 
 	return (productId == GEYSER_ANSI_PRODUCT_ID) ||
 		(productId == GEYSER_ISO_PRODUCT_ID) ||
 		(productId == GEYSER_JIS_PRODUCT_ID);
 }
 
+static inline int atp_is_geyser_3(struct atp *dev)
+{
+	u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+	return (productId == GEYSER3_ANSI_PRODUCT_ID) ||
+		(productId == GEYSER3_ISO_PRODUCT_ID) ||
+		(productId == GEYSER3_JIS_PRODUCT_ID);
+}
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -219,12 +243,33 @@
 
 	/* drop incomplete datasets */
 	if (dev->urb->actual_length != dev->datalen) {
-		dprintk("appletouch: incomplete data package.\n");
+		dprintk("appletouch: incomplete data package"
+			" (first byte: %d, length: %d).\n",
+			dev->data[0], dev->urb->actual_length);
 		goto exit;
 	}
 
 	/* reorder the sensors values */
-	if (atp_is_geyser_2(dev)) {
+	if (atp_is_geyser_3(dev)) {
+		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+		/*
+		 * The values are laid out like this:
+		 * -, Y1, Y2, -, Y3, Y4, -, ..., -, X1, X2, -, X3, X4, ...
+		 * '-' is an unused value.
+		 */
+
+		/* read X values */
+		for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+			dev->xy_cur[i] = dev->data[j + 1];
+			dev->xy_cur[i + 1] = dev->data[j + 2];
+		}
+		/* read Y values */
+		for (i = 0, j = 1; i < 9; i += 2, j += 3) {
+			dev->xy_cur[ATP_XSENSORS + i] = dev->data[j + 1];
+			dev->xy_cur[ATP_XSENSORS + i + 1] = dev->data[j + 2];
+		}
+	} else if (atp_is_geyser_2(dev)) {
 		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
 
 		/*
@@ -267,6 +312,9 @@
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
+		if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
+			goto exit;
+
 		/* 17" Powerbooks have extra X sensors */
 		for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
 			if (!dev->xy_cur[i]) continue;
@@ -414,7 +462,50 @@
 	dev->udev = udev;
 	dev->input = input_dev;
 	dev->overflowwarn = 0;
-	dev->datalen = (atp_is_geyser_2(dev)?64:81);
+	if (atp_is_geyser_3(dev))
+		dev->datalen = 64;
+	else if (atp_is_geyser_2(dev))
+		dev->datalen = 64;
+	else
+		dev->datalen = 81;
+
+	if (atp_is_geyser_3(dev)) {
+		/*
+		 * By default Geyser 3 device sends standard USB HID mouse
+		 * packets (Report ID 2). This code changes device mode, so it
+		 * sends raw sensor reports (Report ID 5).
+		 */
+		char data[8];
+		int size;
+
+		size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+			ATP_GEYSER3_MODE_READ_REQUEST_ID,
+			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			ATP_GEYSER3_MODE_REQUEST_VALUE,
+			ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+
+		if (size != 8) {
+			err("Could not do mode read request from device"
+							" (Geyser 3 mode)");
+			goto err_free_devs;
+		}
+
+		/* Apply the mode switch */
+		data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE;
+
+		size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			ATP_GEYSER3_MODE_WRITE_REQUEST_ID,
+			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			ATP_GEYSER3_MODE_REQUEST_VALUE,
+			ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000);
+
+		if (size != 8) {
+			err("Could not do mode write request to device"
+							" (Geyser 3 mode)");
+			goto err_free_devs;
+		}
+		printk("appletouch Geyser 3 inited.\n");
+	}
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
@@ -447,7 +538,15 @@
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	if (atp_is_geyser_2(dev)) {
+	if (atp_is_geyser_3(dev)) {
+		/*
+		 * MacBook have 20 X sensors, 10 Y sensors
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     ((20 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     ((10 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+	} else if (atp_is_geyser_2(dev)) {
 		/*
 		 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
 		 * later.
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index 99f986c..07c8c0e 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -92,9 +92,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 #include <linux/wait.h>
 #include <linux/jiffies.h>
 
diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c
index ab1a1ae..ea71de8 100644
--- a/drivers/usb/input/ati_remote2.c
+++ b/drivers/usb/input/ati_remote2.c
@@ -8,7 +8,7 @@
  * as published by the Free Software Foundation.
  */
 
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #define DRIVER_DESC    "ATI/Philips USB RF remote driver"
 #define DRIVER_VERSION "0.1"
diff --git a/drivers/usb/input/fixp-arith.h b/drivers/usb/input/fixp-arith.h
index b44d398..ed3d2da 100644
--- a/drivers/usb/input/fixp-arith.h
+++ b/drivers/usb/input/fixp-arith.h
@@ -2,8 +2,6 @@
 #define _FIXP_ARITH_H
 
 /*
- * $$
- *
  * Simplistic fixed-point arithmetics.
  * Hmm, I'm probably duplicating some code :(
  *
@@ -31,20 +29,20 @@
 
 #include <linux/types.h>
 
-// The type representing fixed-point values
+/* The type representing fixed-point values */
 typedef s16 fixp_t;
 
 #define FRAC_N 8
 #define FRAC_MASK ((1<<FRAC_N)-1)
 
-// Not to be used directly. Use fixp_{cos,sin}
-static const fixp_t cos_table[45] = {
+/* Not to be used directly. Use fixp_{cos,sin} */
+static const fixp_t cos_table[46] = {
 	0x0100,	0x00FF,	0x00FF,	0x00FE,	0x00FD,	0x00FC,	0x00FA,	0x00F8,
 	0x00F6,	0x00F3,	0x00F0,	0x00ED,	0x00E9,	0x00E6,	0x00E2,	0x00DD,
 	0x00D9,	0x00D4,	0x00CF,	0x00C9,	0x00C4,	0x00BE,	0x00B8,	0x00B1,
 	0x00AB,	0x00A4,	0x009D,	0x0096,	0x008F,	0x0087,	0x0080,	0x0078,
 	0x0070,	0x0068,	0x005F,	0x0057,	0x004F,	0x0046,	0x003D,	0x0035,
-	0x002C,	0x0023,	0x001A,	0x0011,	0x0008
+	0x002C,	0x0023,	0x001A,	0x0011,	0x0008, 0x0000
 };
 
 
@@ -68,9 +66,8 @@
 	int quadrant = (degrees / 90) & 3;
 	unsigned int i = degrees % 90;
 
-	if (quadrant == 1 || quadrant == 3) {
-		i = 89 - i;
-	}
+	if (quadrant == 1 || quadrant == 3)
+		i = 90 - i;
 
 	i >>= 1;
 
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 435273e..b9fb968 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -944,21 +944,28 @@
 	dev_dbg(&hid->intf->dev, "resetting device\n");
 	rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
 	if (rc_lock >= 0) {
-		rc = usb_reset_device(hid->dev);
+		rc = usb_reset_composite_device(hid->dev, hid->intf);
 		if (rc_lock)
 			usb_unlock_device(hid->dev);
 	}
 	clear_bit(HID_RESET_PENDING, &hid->iofl);
 
-	if (rc == 0) {
-		hid->retry_delay = 0;
-		if (hid_start_in(hid))
+	switch (rc) {
+	case 0:
+		if (!test_bit(HID_IN_RUNNING, &hid->iofl))
 			hid_io_error(hid);
-	} else if (!(rc == -ENODEV || rc == -EHOSTUNREACH || rc == -EINTR))
+		break;
+	default:
 		err("can't reset device, %s-%s/input%d, status %d",
 				hid->dev->bus->bus_name,
 				hid->dev->devpath,
 				hid->ifnum, rc);
+		/* FALLTHROUGH */
+	case -EHOSTUNREACH:
+	case -ENODEV:
+	case -EINTR:
+		break;
+	}
 }
 
 /* Main I/O error handler */
@@ -1374,9 +1381,6 @@
 
 #define USB_VENDOR_ID_PANJIT		0x134c
 
-#define USB_VENDOR_ID_SILVERCREST	0x062a
-#define USB_DEVICE_ID_SILVERCREST_KB	0x0201
-
 /*
  * Initialize all reports
  */
@@ -1461,9 +1465,6 @@
 #define USB_VENDOR_ID_ONTRAK		0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
-#define USB_VENDOR_ID_TANGTOP		0x0d3d
-#define USB_DEVICE_ID_TANGTOP_USBPS2	0x0001
-
 #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
 #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
@@ -1520,12 +1521,6 @@
 #define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
 
-#define USB_VENDOR_ID_CHICONY		0x04f2
-#define USB_DEVICE_ID_CHICONY_USBHUB_KB	0x0100
-
-#define USB_VENDOR_ID_BTC		0x046e
-#define USB_DEVICE_ID_BTC_KEYBOARD	0x5303
-
 #define USB_VENDOR_ID_VERNIER		0x08f7
 #define USB_DEVICE_ID_VERNIER_LABPRO	0x0001
 #define USB_DEVICE_ID_VERNIER_GOTEMP	0x0002
@@ -1549,20 +1544,13 @@
 #define USB_DEVICE_ID_LD_MACHINETEST	0x2040
 
 #define USB_VENDOR_ID_APPLE		0x05ac
-#define USB_DEVICE_ID_APPLE_POWERMOUSE	0x0304
+#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE	0x0304
 
 #define USB_VENDOR_ID_CHERRY		0x046a
 #define USB_DEVICE_ID_CHERRY_CYMOTION	0x0023
 
-#define USB_VENDOR_ID_HP		0x03f0
-#define USB_DEVICE_ID_HP_USBHUB_KB	0x020c
-
-#define USB_VENDOR_ID_IBM		0x04b3
-#define USB_DEVICE_ID_IBM_USBHUB_KB	0x3005
-
-#define USB_VENDOR_ID_CREATIVELABS	0x062a
-#define USB_DEVICE_ID_CREATIVELABS_SILVERCREST	0x0201
-
+#define USB_VENDOR_ID_YEALINK		0x6993
+#define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K	0xb001
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -1671,6 +1659,7 @@
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_DTF + 3, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
 
 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
@@ -1680,16 +1669,9 @@
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET},
-	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
-	{ USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVELABS_SILVERCREST, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_HP, USB_DEVICE_ID_HP_USBHUB_KB, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_IBM, USB_DEVICE_ID_IBM_USBHUB_KB, HID_QUIRK_NOGET },
-	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-	{ USB_VENDOR_ID_SILVERCREST, USB_DEVICE_ID_SILVERCREST_KB, HID_QUIRK_NOGET },
 
-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_POWERMOUSE, HID_QUIRK_2WHEEL_POWERMOUSE },
+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
 	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
 
@@ -1711,6 +1693,9 @@
 	{ USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
 	{ USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN },
 	{ USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN },
+	{ USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN },
 	{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
 	{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
 
@@ -1794,6 +1779,14 @@
 			(hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct)))
 				quirks = hid_blacklist[n].quirks;
 
+	/* Many keyboards and mice don't like to be polled for reports,
+	 * so we will always set the HID_QUIRK_NOGET flag for them. */
+	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
+		if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD ||
+			interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
+				quirks |= HID_QUIRK_NOGET;
+	}
+
 	if (quirks & HID_QUIRK_IGNORE)
 		return NULL;
 
@@ -2080,11 +2073,29 @@
 	int status;
 
 	clear_bit(HID_SUSPENDED, &hid->iofl);
+	hid->retry_delay = 0;
 	status = hid_start_in(hid);
 	dev_dbg(&intf->dev, "resume status %d\n", status);
 	return status;
 }
 
+/* Treat USB reset pretty much the same as suspend/resume */
+static void hid_pre_reset(struct usb_interface *intf)
+{
+	/* FIXME: What if the interface is already suspended? */
+	hid_suspend(intf, PMSG_ON);
+}
+
+static void hid_post_reset(struct usb_interface *intf)
+{
+	struct usb_device *dev = interface_to_usbdev (intf);
+
+	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);
+	/* FIXME: Any more reinitialization needed? */
+
+	hid_resume(intf);
+}
+
 static struct usb_device_id hid_usb_ids [] = {
 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
 		.bInterfaceClass = USB_INTERFACE_CLASS_HID },
@@ -2099,6 +2110,8 @@
 	.disconnect =	hid_disconnect,
 	.suspend =	hid_suspend,
 	.resume =	hid_resume,
+	.pre_reset =	hid_pre_reset,
+	.post_reset =	hid_post_reset,
 	.id_table =	hid_usb_ids,
 };
 
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
index 702c48c..f04d6d7 100644
--- a/drivers/usb/input/hid-debug.h
+++ b/drivers/usb/input/hid-debug.h
@@ -563,7 +563,7 @@
 	[KEY_VOLUMEUP] = "VolumeUp",		[KEY_POWER] = "Power",
 	[KEY_KPEQUAL] = "KPEqual",		[KEY_KPPLUSMINUS] = "KPPlusMinus",
 	[KEY_PAUSE] = "Pause",			[KEY_KPCOMMA] = "KPComma",
-	[KEY_HANGUEL] = "Hanguel",		[KEY_HANJA] = "Hanja",
+	[KEY_HANGUEL] = "Hangeul",		[KEY_HANJA] = "Hanja",
 	[KEY_YEN] = "Yen",			[KEY_LEFTMETA] = "LeftMeta",
 	[KEY_RIGHTMETA] = "RightMeta",		[KEY_COMPOSE] = "Compose",
 	[KEY_STOP] = "Stop",			[KEY_AGAIN] = "Again",
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 25bc85f..028e1ad 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -29,9 +29,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/kernel.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #undef DEBUG
 
@@ -567,16 +565,14 @@
 			break;
 	}
 
-	set_bit(usage->type, input->evbit);
-
-	while (usage->code <= max && test_and_set_bit(usage->code, bit))
-		usage->code = find_next_zero_bit(bit, max + 1, usage->code);
-
-	if (usage->code > max)
-		goto ignore;
-
-	if (((device->quirks & (HID_QUIRK_2WHEEL_POWERMOUSE)) && (usage->hid == 0x00010032)))
-		map_rel(REL_HWHEEL);
+	if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
+		if (usage->hid == HID_GD_Z)
+			map_rel(REL_HWHEEL);
+		else if (usage->code == BTN_1)
+			map_key(BTN_2);
+		else if (usage->code == BTN_2)
+			map_key(BTN_1);
+	}
 
 	if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
 		 (usage->type == EV_REL) && (usage->code == REL_WHEEL))
@@ -586,6 +582,15 @@
 		|| ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
 		goto ignore;
 
+	set_bit(usage->type, input->evbit);
+
+	while (usage->code <= max && test_and_set_bit(usage->code, bit))
+		usage->code = find_next_zero_bit(bit, max + 1, usage->code);
+
+	if (usage->code > max)
+		goto ignore;
+
+
 	if (usage->type == EV_ABS) {
 
 		int a = field->logical_minimum;
@@ -647,6 +652,11 @@
 		return;
 	}
 
+	if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
+		input_event(input, usage->type, usage->code, -value);
+		return;
+	}
+
 	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
 		input_event(input, usage->type, REL_HWHEEL, value);
 		return;
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 9c62837..778e575 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -41,6 +41,14 @@
 #define USB_INTERFACE_CLASS_HID		3
 
 /*
+ * USB HID interface subclass and protocol codes
+ */
+
+#define USB_INTERFACE_SUBCLASS_BOOT	1
+#define USB_INTERFACE_PROTOCOL_KEYBOARD	1
+#define USB_INTERFACE_PROTOCOL_MOUSE	2
+
+/*
  * HID class requests
  */
 
@@ -247,10 +255,11 @@
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_7		0x00000080
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_5		0x00000100
 #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON		0x00000200
-#define HID_QUIRK_2WHEEL_POWERMOUSE		0x00000400
+#define HID_QUIRK_MIGHTYMOUSE			0x00000400
 #define HID_QUIRK_CYMOTION			0x00000800
 #define HID_QUIRK_POWERBOOK_HAS_FN		0x00001000
 #define HID_QUIRK_POWERBOOK_FN_ON		0x00002000
+#define HID_QUIRK_INVERT_HWHEEL			0x00004000
 
 /*
  * This is the global environment of the parser. This information is
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c
index 7618ae5..5c570cc 100644
--- a/drivers/usb/input/itmtouch.c
+++ b/drivers/usb/input/itmtouch.c
@@ -42,11 +42,9 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 /* only an 8 byte buffer necessary for a single packet */
 #define ITM_BUFSIZE			8
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index f6d5cea..604ade3 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -1,12 +1,9 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 #include <asm/unaligned.h>
-#include <asm/byteorder.h>
 
 /*
  * Version Information
diff --git a/drivers/usb/input/keyspan_remote.c b/drivers/usb/input/keyspan_remote.c
index 3d91197..70af985 100644
--- a/drivers/usb/input/keyspan_remote.c
+++ b/drivers/usb/input/keyspan_remote.c
@@ -18,9 +18,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #define DRIVER_VERSION	"v0.1"
 #define DRIVER_AUTHOR	"Michael Downey <downey@zymeta.com>"
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index f018953..4fdee4d 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -42,11 +42,9 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #define MTOUCHUSB_MIN_XC                0x0
 #define MTOUCHUSB_MAX_RAW_XC            0x4000
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index fdf0f78..b3c0d0c 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -30,12 +30,10 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #define POWERMATE_VENDOR	0x077d	/* Griffin Technology, Inc. */
 #define POWERMATE_PRODUCT_NEW	0x0410	/* Griffin PowerMate */
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 697c5e5..da7b0bf 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -27,11 +27,9 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #define TOUCHKIT_MIN_XC			0x0
 #define TOUCHKIT_MAX_XC			0x07ff
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 2f3edc2..5067a6a 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -29,10 +29,8 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/input.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 /*
  * Version Information
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index af52613..446935b 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -28,11 +28,9 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 /*
  * Version Information
diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c
index e9a07c1..3b175aa 100644
--- a/drivers/usb/input/usbtouchscreen.c
+++ b/drivers/usb/input/usbtouchscreen.c
@@ -39,7 +39,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 
 #define DRIVER_VERSION		"v0.3"
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index cf84c60..369461a 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -69,13 +69,10 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 #include <asm/unaligned.h>
-#include <asm/byteorder.h>
 
 /*
  * Version Information
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index e278489..cfd4a4e 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -56,13 +56,11 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/input.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #define DRIVER_VERSION "v0.0.5"
 #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>"
diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c
index 37d2f0b..24aedbb 100644
--- a/drivers/usb/input/yealink.c
+++ b/drivers/usb/input/yealink.c
@@ -48,13 +48,11 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/input.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/rwsem.h>
-#include <linux/usb.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 
 #include "map_to_7segment.h"
 #include "yealink.h"
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 8ba6a70..daa486d 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -88,6 +88,20 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbled.
 
+config USB_CY7C63
+	tristate "Cypress CY7C63xxx USB driver support"
+	depends on USB
+	help
+	  Say Y here if you want to connect a Cypress CY7C63xxx
+	  micro controller to your computer's USB port. This driver
+	  supports the pre-programmed devices (incl. firmware) by
+	  AK Modul-Bus Computer GmbH.
+
+	  Please see: http://www.ak-modul-bus.de/stat/mikrocontroller.html
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called cy7c63.
+
 config USB_CYTHERM
 	tristate "Cypress USB thermometer driver support"
 	depends on USB
@@ -137,6 +151,15 @@
 
 	  See also <http://www.fs.tum.de/~echtler/idmouse/>.
 
+config USB_APPLEDISPLAY
+	tristate "Apple Cinema Display support"
+	depends on USB
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	help
+	  Say Y here if you want to control the backlight of Apple Cinema
+	  Displays over USB. This driver provides a sysfs interface.
+
 source "drivers/usb/misc/sisusbvga/Kconfig"
 
 config USB_LD
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 6c693bc..f25a972 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_USB_AUERSWALD)	+= auerswald.o
+obj-$(CONFIG_USB_CY7C63)	+= cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)	+= cytherm.o
 obj-$(CONFIG_USB_EMI26)		+= emi26.o
 obj-$(CONFIG_USB_EMI62)		+= emi62.o
@@ -17,6 +18,7 @@
 obj-$(CONFIG_USB_RIO500)	+= rio500.o
 obj-$(CONFIG_USB_TEST)		+= usbtest.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
+obj-$(CONFIG_USB_APPLEDISPLAY)	+= appledisplay.o
 
 obj-$(CONFIG_USB_SISUSBVGA)	+= sisusbvga/
 
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c
new file mode 100644
index 0000000..bfde82f
--- /dev/null
+++ b/drivers/usb/misc/appledisplay.c
@@ -0,0 +1,383 @@
+/*
+ * Apple Cinema Display driver
+ *
+ * Copyright (C) 2006  Michael Hanselmann (linux-kernel@hansmi.ch)
+ *
+ * Thanks to Caskey L. Dickson for his work with acdctl.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/backlight.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+#define APPLE_VENDOR_ID		0x05AC
+
+#define USB_REQ_GET_REPORT	0x01
+#define USB_REQ_SET_REPORT	0x09
+
+#define ACD_USB_TIMEOUT		250
+
+#define ACD_USB_EDID		0x0302
+#define ACD_USB_BRIGHTNESS	0x0310
+
+#define ACD_BTN_NONE		0
+#define ACD_BTN_BRIGHT_UP	3
+#define ACD_BTN_BRIGHT_DOWN	4
+
+#define ACD_URB_BUFFER_LEN	2
+#define ACD_MSG_BUFFER_LEN	2
+
+#define APPLEDISPLAY_DEVICE(prod)				\
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
+		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
+		       USB_DEVICE_ID_MATCH_INT_PROTOCOL,	\
+	.idVendor = APPLE_VENDOR_ID,				\
+	.idProduct = (prod),					\
+	.bInterfaceClass = USB_CLASS_HID,			\
+	.bInterfaceProtocol = 0x00
+
+/* table of devices that work with this driver */
+static struct usb_device_id appledisplay_table [] = {
+	{ APPLEDISPLAY_DEVICE(0x9218) },
+	{ APPLEDISPLAY_DEVICE(0x9219) },
+	{ APPLEDISPLAY_DEVICE(0x921d) },
+
+	/* Terminating entry */
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, appledisplay_table);
+
+/* Structure to hold all of our device specific stuff */
+struct appledisplay {
+	struct usb_device *udev;	/* usb device */
+	struct urb *urb;		/* usb request block */
+	struct backlight_device *bd;	/* backlight device */
+	char *urbdata;			/* interrupt URB data buffer */
+	char *msgdata;			/* control message data buffer */
+
+	struct work_struct work;
+	int button_pressed;
+	spinlock_t lock;
+};
+
+static atomic_t count_displays = ATOMIC_INIT(0);
+static struct workqueue_struct *wq;
+
+static void appledisplay_complete(struct urb *urb, struct pt_regs *regs)
+{
+	struct appledisplay *pdata = urb->context;
+	unsigned long flags;
+	int retval;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -EOVERFLOW:
+		printk(KERN_ERR "appletouch: OVERFLOW with data "
+			"length %d, actual length is %d\n",
+			ACD_URB_BUFFER_LEN, pdata->urb->actual_length);
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* This urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d",
+			__FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d",
+			__FUNCTION__, urb->status);
+		goto exit;
+	}
+
+	spin_lock_irqsave(&pdata->lock, flags);
+
+	switch(pdata->urbdata[1]) {
+	case ACD_BTN_BRIGHT_UP:
+	case ACD_BTN_BRIGHT_DOWN:
+		pdata->button_pressed = 1;
+		queue_work(wq, &pdata->work);
+		break;
+	case ACD_BTN_NONE:
+	default:
+		pdata->button_pressed = 0;
+		break;
+	}
+
+	spin_unlock_irqrestore(&pdata->lock, flags);
+
+exit:
+	retval = usb_submit_urb(pdata->urb, GFP_ATOMIC);
+	if (retval) {
+		err("%s - usb_submit_urb failed with result %d",
+			__FUNCTION__, retval);
+	}
+}
+
+static int appledisplay_bl_update_status(struct backlight_device *bd)
+{
+	struct appledisplay *pdata = class_get_devdata(&bd->class_dev);
+	int retval;
+
+	pdata->msgdata[0] = 0x10;
+	pdata->msgdata[1] = bd->props->brightness;
+
+	retval = usb_control_msg(
+		pdata->udev,
+		usb_sndctrlpipe(pdata->udev, 0),
+		USB_REQ_SET_REPORT,
+		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		ACD_USB_BRIGHTNESS,
+		0,
+		pdata->msgdata, 2,
+		ACD_USB_TIMEOUT);
+
+	return retval;
+}
+
+static int appledisplay_bl_get_brightness(struct backlight_device *bd)
+{
+	struct appledisplay *pdata = class_get_devdata(&bd->class_dev);
+	int retval;
+
+	retval = usb_control_msg(
+		pdata->udev,
+		usb_rcvctrlpipe(pdata->udev, 0),
+		USB_REQ_GET_REPORT,
+		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		ACD_USB_BRIGHTNESS,
+		0,
+		pdata->msgdata, 2,
+		ACD_USB_TIMEOUT);
+
+	if (retval < 0)
+		return retval;
+	else
+		return pdata->msgdata[1];
+}
+
+static struct backlight_properties appledisplay_bl_data = {
+	.owner		= THIS_MODULE,
+	.get_brightness	= appledisplay_bl_get_brightness,
+	.update_status	= appledisplay_bl_update_status,
+	.max_brightness	= 0xFF
+};
+
+static void appledisplay_work(void *private)
+{
+	struct appledisplay *pdata = private;
+	int retval;
+
+	up(&pdata->bd->sem);
+	retval = appledisplay_bl_get_brightness(pdata->bd);
+	if (retval >= 0)
+		pdata->bd->props->brightness = retval;
+	down(&pdata->bd->sem);
+
+	/* Poll again in about 125ms if there's still a button pressed */
+	if (pdata->button_pressed)
+		schedule_delayed_work(&pdata->work, HZ / 8);
+}
+
+static int appledisplay_probe(struct usb_interface *iface,
+	const struct usb_device_id *id)
+{
+	struct appledisplay *pdata;
+	struct usb_device *udev = interface_to_usbdev(iface);
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	int int_in_endpointAddr = 0;
+	int i, retval = -ENOMEM, brightness;
+	char bl_name[20];
+
+	/* set up the endpoint information */
+	/* use only the first interrupt-in endpoint */
+	iface_desc = iface->cur_altsetting;
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+		endpoint = &iface_desc->endpoint[i].desc;
+		if (!int_in_endpointAddr &&
+		    (endpoint->bEndpointAddress & USB_DIR_IN) &&
+		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+		     USB_ENDPOINT_XFER_INT)) {
+			/* we found an interrupt in endpoint */
+			int_in_endpointAddr = endpoint->bEndpointAddress;
+			break;
+		}
+	}
+	if (!int_in_endpointAddr) {
+		err("Could not find int-in endpoint");
+		return -EIO;
+	}
+
+	/* allocate memory for our device state and initialize it */
+	pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL);
+	if (!pdata) {
+		retval = -ENOMEM;
+		err("Out of memory");
+		goto error;
+	}
+
+	pdata->udev = udev;
+
+	spin_lock_init(&pdata->lock);
+	INIT_WORK(&pdata->work, appledisplay_work, pdata);
+
+	/* Allocate buffer for control messages */
+	pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL);
+	if (!pdata->msgdata) {
+		retval = -ENOMEM;
+		err("appledisplay: Allocating buffer for control messages "
+			"failed");
+		goto error;
+	}
+
+	/* Allocate interrupt URB */
+	pdata->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!pdata->urb) {
+		retval = -ENOMEM;
+		err("appledisplay: Allocating URB failed");
+		goto error;
+	}
+
+	/* Allocate buffer for interrupt data */
+	pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN,
+		GFP_KERNEL, &pdata->urb->transfer_dma);
+	if (!pdata->urbdata) {
+		retval = -ENOMEM;
+		err("appledisplay: Allocating URB buffer failed");
+		goto error;
+	}
+
+	/* Configure interrupt URB */
+	usb_fill_int_urb(pdata->urb, udev,
+		usb_rcvintpipe(udev, int_in_endpointAddr),
+		pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete,
+		pdata, 1);
+	if (usb_submit_urb(pdata->urb, GFP_KERNEL)) {
+		retval = -EIO;
+		err("appledisplay: Submitting URB failed");
+		goto error;
+	}
+
+	/* Register backlight device */
+	snprintf(bl_name, sizeof(bl_name), "appledisplay%d",
+		atomic_inc_return(&count_displays) - 1);
+	pdata->bd = backlight_device_register(bl_name, pdata,
+						&appledisplay_bl_data);
+	if (IS_ERR(pdata->bd)) {
+		err("appledisplay: Backlight registration failed");
+		goto error;
+	}
+
+	/* Try to get brightness */
+	up(&pdata->bd->sem);
+	brightness = appledisplay_bl_get_brightness(pdata->bd);
+	down(&pdata->bd->sem);
+
+	if (brightness < 0) {
+		retval = brightness;
+		err("appledisplay: Error while getting initial brightness: %d", retval);
+		goto error;
+	}
+
+	/* Set brightness in backlight device */
+	up(&pdata->bd->sem);
+	pdata->bd->props->brightness = brightness;
+	down(&pdata->bd->sem);
+
+	/* save our data pointer in the interface device */
+	usb_set_intfdata(iface, pdata);
+
+	printk(KERN_INFO "appledisplay: Apple Cinema Display connected\n");
+
+	return 0;
+
+error:
+	if (pdata) {
+		if (pdata->urb) {
+			usb_kill_urb(pdata->urb);
+			if (pdata->urbdata)
+				usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN,
+					pdata->urbdata, pdata->urb->transfer_dma);
+			usb_free_urb(pdata->urb);
+		}
+		if (pdata->bd)
+			backlight_device_unregister(pdata->bd);
+		kfree(pdata->msgdata);
+	}
+	usb_set_intfdata(iface, NULL);
+	kfree(pdata);
+	return retval;
+}
+
+static void appledisplay_disconnect(struct usb_interface *iface)
+{
+	struct appledisplay *pdata = usb_get_intfdata(iface);
+
+	if (pdata) {
+		usb_kill_urb(pdata->urb);
+		cancel_delayed_work(&pdata->work);
+		backlight_device_unregister(pdata->bd);
+		usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN,
+			pdata->urbdata, pdata->urb->transfer_dma);
+		usb_free_urb(pdata->urb);
+		kfree(pdata->msgdata);
+		kfree(pdata);
+	}
+
+	printk(KERN_INFO "appledisplay: Apple Cinema Display disconnected\n");
+}
+
+static struct usb_driver appledisplay_driver = {
+	.name		= "appledisplay",
+	.probe		= appledisplay_probe,
+	.disconnect	= appledisplay_disconnect,
+	.id_table	= appledisplay_table,
+};
+
+static int __init appledisplay_init(void)
+{
+	wq = create_singlethread_workqueue("appledisplay");
+	if (!wq) {
+		err("Could not create work queue\n");
+		return -ENOMEM;
+	}
+
+	return usb_register(&appledisplay_driver);
+}
+
+static void __exit appledisplay_exit(void)
+{
+	flush_workqueue(wq);
+	destroy_workqueue(wq);
+	usb_deregister(&appledisplay_driver);
+}
+
+MODULE_AUTHOR("Michael Hanselmann");
+MODULE_DESCRIPTION("Apple Cinema Display driver");
+MODULE_LICENSE("GPL");
+
+module_init(appledisplay_init);
+module_exit(appledisplay_exit);
diff --git a/drivers/usb/misc/cy7c63.c b/drivers/usb/misc/cy7c63.c
new file mode 100644
index 0000000..8a1c10b
--- /dev/null
+++ b/drivers/usb/misc/cy7c63.c
@@ -0,0 +1,244 @@
+/*
+* cy7c63.c
+*
+* Copyright (c) 2006 Oliver Bock (bock@fh-wolfenbuettel.de)
+*
+*	This driver is based on the Cypress Thermometer USB Driver by
+*	Marcus Maul and the 2.0 version of Greg Kroah-Hartman's
+*	USB Skeleton driver.
+*
+*	Is is a generic driver for the Cypress CY7C63000 family.
+*	For the time being it enables you to toggle the single I/O ports
+*	of the device.
+*
+*	Supported vendors:	AK Modul-Bus Computer GmbH
+*	Supported devices:	CY7C63001A-PC (to be continued...)
+*	Supported functions:	Read/Write Ports (to be continued...)
+*
+*	Chipsets families:	CY7C63000, CY7C63001, CY7C63100, CY7C63101
+*
+*
+*	This program is free software; you can redistribute it and/or
+*	modify it under the terms of the GNU General Public License as
+*	published by the Free Software Foundation, version 2.
+*/
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/usb.h>
+
+#define DRIVER_AUTHOR		"Oliver Bock (bock@fh-wolfenbuettel.de)"
+#define DRIVER_DESC		"Cypress CY7C63xxx USB driver"
+
+#define CY7C63_VENDOR_ID	0xa2c
+#define CY7C63_PRODUCT_ID	0x8
+
+#define CY7C63_READ_PORT	0x4
+#define CY7C63_WRITE_PORT	0x5
+#define CY7C63_READ_RAM		0x2
+#define CY7C63_WRITE_RAM	0x3
+#define CY7C63_READ_ROM		0x1
+
+#define CY7C63_READ_PORT_ID0	0
+#define CY7C63_WRITE_PORT_ID0	0
+#define CY7C63_READ_PORT_ID1	0x2
+#define CY7C63_WRITE_PORT_ID1	1
+
+#define CY7C63_MAX_REQSIZE	8
+
+
+/* table of devices that work with this driver */
+static struct usb_device_id cy7c63_table [] = {
+	{ USB_DEVICE(CY7C63_VENDOR_ID, CY7C63_PRODUCT_ID) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, cy7c63_table);
+
+/* structure to hold all of our device specific stuff */
+struct cy7c63 {
+	struct usb_device *	udev;
+	char 			port0;
+	char			port1;
+};
+
+/* used to send usb control messages to device */
+int vendor_command(struct cy7c63 *dev, unsigned char request,
+			 unsigned char address, unsigned char data) {
+
+	int retval = 0;
+	unsigned int pipe;
+	unsigned char *iobuf;
+
+	/* allocate some memory for the i/o buffer*/
+	iobuf = kzalloc(CY7C63_MAX_REQSIZE, GFP_KERNEL);
+	if (!iobuf) {
+		dev_err(&dev->udev->dev, "Out of memory!\n");
+		retval = -ENOMEM;
+		goto error;
+	}
+
+	dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data);
+
+	/* prepare usb control message and send it upstream */
+	pipe = usb_rcvctrlpipe(dev->udev, 0);
+	retval = usb_control_msg(dev->udev, pipe, request,
+				USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+				address, data, iobuf, CY7C63_MAX_REQSIZE,
+				USB_CTRL_GET_TIMEOUT);
+
+	/* store returned data (more READs to be added!) */
+	switch (request) {
+		case CY7C63_READ_PORT:
+			if (address == CY7C63_READ_PORT_ID0) {
+				dev->port0 = iobuf[1];
+				dev_dbg(&dev->udev->dev,
+					"READ_PORT0 returned: %d\n",dev->port0);
+			}
+			else if (address == CY7C63_READ_PORT_ID1) {
+				dev->port1 = iobuf[1];
+				dev_dbg(&dev->udev->dev,
+					"READ_PORT1 returned: %d\n",dev->port1);
+			}
+			break;
+	}
+
+	kfree(iobuf);
+error:
+	return retval;
+}
+
+#define get_set_port(num,read_id,write_id) \
+static ssize_t set_port##num(struct device *dev, struct device_attribute *attr,	\
+					const char *buf, size_t count) {	\
+										\
+	int value;								\
+	int result = 0;								\
+										\
+	struct usb_interface *intf = to_usb_interface(dev);			\
+	struct cy7c63 *cyp = usb_get_intfdata(intf);				\
+										\
+	dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", num);			\
+										\
+	/* validate input data */						\
+	if (sscanf(buf, "%d", &value) < 1) {					\
+		result = -EINVAL;						\
+		goto error;							\
+	}									\
+	if (value>255 || value<0) {						\
+		result = -EINVAL;						\
+		goto error;							\
+	}									\
+										\
+	result = vendor_command(cyp, CY7C63_WRITE_PORT, write_id,		\
+					 (unsigned char)value);			\
+										\
+	dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n",result);	\
+error:										\
+	return result < 0 ? result : count;					\
+}										\
+										\
+static ssize_t get_port##num(struct device *dev,				\
+				 struct device_attribute *attr, char *buf) {	\
+										\
+	int result = 0;								\
+										\
+	struct usb_interface *intf = to_usb_interface(dev);			\
+	struct cy7c63 *cyp = usb_get_intfdata(intf);				\
+										\
+	dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", num);			\
+										\
+	result = vendor_command(cyp, CY7C63_READ_PORT, read_id, 0);		\
+										\
+	dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);	\
+										\
+	return sprintf(buf, "%d", cyp->port##num);				\
+}										\
+static DEVICE_ATTR(port##num, S_IWUGO | S_IRUGO, get_port##num, set_port##num);
+
+get_set_port(0, CY7C63_READ_PORT_ID0, CY7C63_WRITE_PORT_ID0);
+get_set_port(1, CY7C63_READ_PORT_ID1, CY7C63_WRITE_PORT_ID1);
+
+static int cy7c63_probe(struct usb_interface *interface,
+			const struct usb_device_id *id) {
+
+	struct cy7c63 *dev = NULL;
+	int retval = -ENOMEM;
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&dev->udev->dev, "Out of memory!\n");
+		goto error;
+	}
+
+	dev->udev = usb_get_dev(interface_to_usbdev(interface));
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	/* create device attribute files */
+	device_create_file(&interface->dev, &dev_attr_port0);
+	device_create_file(&interface->dev, &dev_attr_port1);
+
+	/* let the user know what node this device is now attached to */
+	dev_info(&interface->dev,
+		"Cypress CY7C63xxx device now attached\n");
+
+	retval = 0;
+error:
+	return retval;
+}
+
+static void cy7c63_disconnect(struct usb_interface *interface) {
+
+	struct cy7c63 *dev;
+
+	dev = usb_get_intfdata(interface);
+	usb_set_intfdata(interface, NULL);
+
+	/* remove device attribute files */
+	device_remove_file(&interface->dev, &dev_attr_port0);
+	device_remove_file(&interface->dev, &dev_attr_port1);
+
+	usb_put_dev(dev->udev);
+
+	dev_info(&interface->dev,
+		"Cypress CY7C63xxx device now disconnected\n");
+
+	kfree(dev);
+}
+
+static struct usb_driver cy7c63_driver = {
+	.name = "cy7c63",
+	.probe = cy7c63_probe,
+	.disconnect = cy7c63_disconnect,
+	.id_table = cy7c63_table,
+};
+
+static int __init cy7c63_init(void) {
+
+	int result;
+
+	/* register this driver with the USB subsystem */
+	result = usb_register(&cy7c63_driver);
+	if (result) {
+		err("Function usb_register failed! Error number: %d\n", result);
+	}
+
+	return result;
+}
+
+static void __exit cy7c63_exit(void) {
+
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&cy7c63_driver);
+}
+
+module_init(cy7c63_init);
+module_exit(cy7c63_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index 997db5d..13aeea2 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -1,7 +1,8 @@
 /*
  * USB PhidgetInterfaceKit driver 1.0
  *
- * Copyright (C) 2004 Sean Young <sean@mess.org>
+ * Copyright (C) 2004, 2006 Sean Young <sean@mess.org>
+ * Copyright (C) 2005 Daniel Saakes <daniel@saakes.net>
  * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,6 +26,7 @@
 
 #define USB_VENDOR_ID_GLAB		0x06c2
 #define USB_DEVICE_ID_INTERFACEKIT004	0x0040
+#define USB_DEVICE_ID_INTERFACEKIT01616	0x0044
 #define USB_DEVICE_ID_INTERFACEKIT888	0x0045
 #define USB_DEVICE_ID_INTERFACEKIT047	0x0051
 #define USB_DEVICE_ID_INTERFACEKIT088	0x0053
@@ -32,7 +34,9 @@
 #define USB_VENDOR_ID_WISEGROUP		0x0925
 #define USB_DEVICE_ID_INTERFACEKIT884	0x8201
 
-#define MAX_INTERFACES			8
+#define MAX_INTERFACES			16
+
+#define URB_INT_SIZE			8
 
 struct driver_interfacekit {
 	int sensors;
@@ -52,19 +56,24 @@
 ifkit(0, 4, 7, 1);
 ifkit(8, 8, 4, 0);
 ifkit(0, 8, 8, 1);
+ifkit(0, 16, 16, 0);
 
-struct phidget_interfacekit {
+struct interfacekit {
 	struct usb_device *udev;
 	struct usb_interface *intf;
 	struct driver_interfacekit *ifkit;
-	int outputs[MAX_INTERFACES];
-	int inputs[MAX_INTERFACES];
-	int sensors[MAX_INTERFACES];
+	unsigned long outputs;
+	u8 inputs[MAX_INTERFACES];
+	u16 sensors[MAX_INTERFACES];
 	u8 lcd_files_on;
 
 	struct urb *irq;
 	unsigned char *data;
 	dma_addr_t data_dma;
+
+	struct work_struct do_notify;
+	unsigned long input_events;
+	unsigned long sensor_events;
 };
 
 static struct usb_device_id id_table[] = {
@@ -76,33 +85,33 @@
 		.driver_info = (kernel_ulong_t)&ph_047},
 	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088),
 		.driver_info = (kernel_ulong_t)&ph_088},
+	{USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616),
+		.driver_info = (kernel_ulong_t)&ph_01616},
 	{USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884),
 		.driver_info = (kernel_ulong_t)&ph_884},
 	{}
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-static int change_outputs(struct phidget_interfacekit *kit, int output_num, int enable)
+static int change_outputs(struct interfacekit *kit, int output_num, int enable)
 {
-	unsigned char *buffer;
+	u8 *buffer;
 	int retval;
-	int n;
+
+	if (enable)
+		set_bit(output_num, &kit->outputs);
+	else
+		clear_bit(output_num, &kit->outputs);
 
 	buffer = kzalloc(4, GFP_KERNEL);
 	if (!buffer) {
-		dev_err(&kit->udev->dev, "%s - out of memory\n",
-			__FUNCTION__);
+		dev_err(&kit->udev->dev, "%s - out of memory\n", __FUNCTION__);
 		return -ENOMEM;
 	}
+	buffer[0] = (u8)kit->outputs;
+	buffer[1] = (u8)(kit->outputs >> 8);
 
-	kit->outputs[output_num] = enable;
-	for (n=0; n<8; n++) {
-		if (kit->outputs[n]) {
-			buffer[0] |= 1 << n;
-		}
-	}
-
-	dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]);
+	dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs);
 
 	retval = usb_control_msg(kit->udev,
 			 usb_sndctrlpipe(kit->udev, 0),
@@ -116,10 +125,10 @@
 	return retval < 0 ? retval : 0;
 }
 
-static int change_string(struct phidget_interfacekit *kit, const char *display, unsigned char row)
+static int change_string(struct interfacekit *kit, const char *display, unsigned char row)
 {
 	unsigned char *buffer;
-        unsigned char *form_buffer;
+	unsigned char *form_buffer;
 	int retval = -ENOMEM;
 	int i,j, len, buf_ptr;
 	
@@ -175,7 +184,7 @@
 static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
 {											\
 	struct usb_interface *intf = to_usb_interface(dev);				\
-	struct phidget_interfacekit *kit = usb_get_intfdata(intf);			\
+	struct interfacekit *kit = usb_get_intfdata(intf);				\
 	change_string(kit, buf, number - 1);						\
 	return count;									\
 }											\
@@ -186,7 +195,7 @@
 static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
-	struct phidget_interfacekit *kit = usb_get_intfdata(intf);
+	struct interfacekit *kit = usb_get_intfdata(intf);
 	int enabled;
 	unsigned char *buffer;
 	int retval = -ENOMEM;
@@ -220,7 +229,7 @@
 }
 static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
 
-static void remove_lcd_files(struct phidget_interfacekit *kit)
+static void remove_lcd_files(struct interfacekit *kit)
 {
 	if (kit->lcd_files_on) {
 		dev_dbg(&kit->udev->dev, "Removing lcd files\n");
@@ -233,7 +242,7 @@
 static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
-	struct phidget_interfacekit *kit = usb_get_intfdata(intf);
+	struct interfacekit *kit = usb_get_intfdata(intf);
 	int enable;
 	
 	if (kit->ifkit->has_lcd == 0)
@@ -263,10 +272,10 @@
 
 static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
 {
-	struct phidget_interfacekit *kit = urb->context;
+	struct interfacekit *kit = urb->context;
 	unsigned char *buffer = kit->data;
+	int i, level, sensor;
 	int status;
-	int n;
 
 	switch (urb->status) {
 	case 0:			/* success */
@@ -280,22 +289,63 @@
 		goto resubmit;
 	}
 
-	for (n=0; n<8; n++) {
-		kit->inputs[n] = buffer[1] & (1 << n) ? 1 : 0;
+	/* digital inputs */
+	if (kit->ifkit->inputs == 16) {
+		for (i=0; i < 8; i++) {
+			level = (buffer[0] >> i) & 1;
+			if (kit->inputs[i] != level) {
+				kit->inputs[i] = level;
+				set_bit(i, &kit->input_events);
+			}
+			level = (buffer[1] >> i) & 1;
+			if (kit->inputs[8 + i] != level) {
+				kit->inputs[8 + i] = level;
+				set_bit(8 + i, &kit->input_events);
+			}
+		}
+	}
+	else if (kit->ifkit->inputs == 8) {
+		for (i=0; i < 8; i++) {
+			level = (buffer[1] >> i) & 1;
+			if (kit->inputs[i] != level) {
+				kit->inputs[i] = level;
+				set_bit(i, &kit->input_events);
+			}
+		}
 	}
 
-	if (buffer[0] & 1) {
-		kit->sensors[4] = buffer[2] + (buffer[3] & 0x0f) * 256;
-		kit->sensors[5] = buffer[4] + (buffer[3] & 0xf0) * 16;
-		kit->sensors[6] = buffer[5] + (buffer[6] & 0x0f) * 256;
-		kit->sensors[7] = buffer[7] + (buffer[6] & 0xf0) * 16;
-	} else {
-		kit->sensors[0] = buffer[2] + (buffer[3] & 0x0f) * 256;
-		kit->sensors[1] = buffer[4] + (buffer[3] & 0xf0) * 16;
-		kit->sensors[2] = buffer[5] + (buffer[6] & 0x0f) * 256;
-		kit->sensors[3] = buffer[7] + (buffer[6] & 0xf0) * 16;
+	/* analog inputs */
+	if (kit->ifkit->sensors) {
+		sensor = (buffer[0] & 1) ? 4 : 0;
+
+		level = buffer[2] + (buffer[3] & 0x0f) * 256;
+		if (level != kit->sensors[sensor]) {
+			kit->sensors[sensor] = level;
+			set_bit(sensor, &kit->sensor_events);
+		}
+		sensor++;
+		level = buffer[4] + (buffer[3] & 0xf0) * 16;
+		if (level != kit->sensors[sensor]) {
+			kit->sensors[sensor] = level;
+			set_bit(sensor, &kit->sensor_events);
+		}
+		sensor++;
+		level = buffer[5] + (buffer[6] & 0x0f) * 256;
+		if (level != kit->sensors[sensor]) {
+			kit->sensors[sensor] = level;
+			set_bit(sensor, &kit->sensor_events);
+		}
+		sensor++;
+		level = buffer[7] + (buffer[6] & 0xf0) * 16;
+		if (level != kit->sensors[sensor]) {
+			kit->sensors[sensor] = level;
+			set_bit(sensor, &kit->sensor_events);
+		}
 	}
 
+	if (kit->input_events || kit->sensor_events)
+		schedule_work(&kit->do_notify);
+
 resubmit:
 	status = usb_submit_urb(urb, SLAB_ATOMIC);
 	if (status)
@@ -304,20 +354,40 @@
 			kit->udev->devpath, status);
 }
 
+static void do_notify(void *data)
+{
+	struct interfacekit *kit = data;
+	int i;
+	char sysfs_file[8];
+
+	for (i=0; i<kit->ifkit->inputs; i++) {
+		if (test_and_clear_bit(i, &kit->input_events)) {
+			sprintf(sysfs_file, "input%d", i + 1);
+			sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+		}
+	}
+
+	for (i=0; i<kit->ifkit->sensors; i++) {
+		if (test_and_clear_bit(i, &kit->sensor_events)) {
+			sprintf(sysfs_file, "sensor%d", i + 1);
+			sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+		}
+	}
+}
+
 #define show_set_output(value)		\
-static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, 	\
+static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf,	\
 							size_t count)	\
 {									\
 	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+	struct interfacekit *kit = usb_get_intfdata(intf);		\
 	int enabled;							\
 	int retval;							\
 									\
-	if (sscanf(buf, "%d", &enabled) < 1) {				\
+	if (sscanf(buf, "%d", &enabled) < 1)				\
 		return -EINVAL;						\
-	}								\
 									\
-	retval = change_outputs(kit, value - 1, enabled ? 1 : 0);	\
+	retval = change_outputs(kit, value - 1, enabled);		\
 									\
 	return retval ? retval : count;					\
 }									\
@@ -325,9 +395,9 @@
 static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+	struct interfacekit *kit = usb_get_intfdata(intf);		\
 									\
-	return sprintf(buf, "%d\n", kit->outputs[value - 1]);		\
+	return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\
 }									\
 static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO,			\
 		show_output##value, set_output##value);
@@ -338,15 +408,23 @@
 show_set_output(5);
 show_set_output(6);
 show_set_output(7);
-show_set_output(8);	/* should be MAX_INTERFACES - 1 */
+show_set_output(8);
+show_set_output(9);
+show_set_output(10);
+show_set_output(11);
+show_set_output(12);
+show_set_output(13);
+show_set_output(14);
+show_set_output(15);
+show_set_output(16);
 
 #define show_input(value)	\
 static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+	struct interfacekit *kit = usb_get_intfdata(intf);		\
 									\
-	return sprintf(buf, "%d\n", kit->inputs[value - 1]);		\
+	return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]);	\
 }									\
 static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
 
@@ -357,15 +435,23 @@
 show_input(5);
 show_input(6);
 show_input(7);
-show_input(8);		/* should be MAX_INTERFACES - 1 */
+show_input(8);
+show_input(9);
+show_input(10);
+show_input(11);
+show_input(12);
+show_input(13);
+show_input(14);
+show_input(15);
+show_input(16);
 
 #define show_sensor(value)	\
 static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	struct usb_interface *intf = to_usb_interface(dev);		\
-	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
+	struct interfacekit *kit = usb_get_intfdata(intf);		\
 									\
-	return sprintf(buf, "%d\n", kit->sensors[value - 1]);		\
+	return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]);	\
 }									\
 static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
 
@@ -376,16 +462,16 @@
 show_sensor(5);
 show_sensor(6);
 show_sensor(7);
-show_sensor(8);		/* should be MAX_INTERFACES - 1 */
+show_sensor(8);
 
 static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_device *dev = interface_to_usbdev(intf);
 	struct usb_host_interface *interface;
 	struct usb_endpoint_descriptor *endpoint;
-	struct phidget_interfacekit *kit;
+	struct interfacekit *kit;
 	struct driver_interfacekit *ifkit;
-	int pipe, maxp;
+	int pipe, maxp, rc = -ENOMEM;
 
 	ifkit = (struct driver_interfacekit *)id->driver_info;
 	if (!ifkit)
@@ -405,29 +491,23 @@
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 	
 	kit = kzalloc(sizeof(*kit), GFP_KERNEL);
-	if (kit  == NULL) {
-		dev_err(&intf->dev, "%s - out of memory\n", __FUNCTION__);
-		return -ENOMEM;
-	}
-	kit->ifkit = ifkit;
+	if (!kit)
+		goto out;
 
-	kit->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kit->data_dma);
-	if (!kit->data) {
-		kfree(kit);
-		return -ENOMEM;
-	}
+	kit->ifkit = ifkit;
+	kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);
+	if (!kit->data)
+		goto out;
 
 	kit->irq = usb_alloc_urb(0, GFP_KERNEL);
-	if (!kit->irq) {
-		usb_buffer_free(dev, 8, kit->data, kit->data_dma);
-		kfree(kit);
-		return -ENOMEM;
-	}
+	if (!kit->irq)
+		goto out;
 
 	kit->udev = usb_get_dev(dev);
 	kit->intf = intf;
+	INIT_WORK(&kit->do_notify, do_notify, kit);
 	usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data,
-			(maxp > 8 ? 8 : maxp),
+			maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
 			interfacekit_irq, kit, endpoint->bInterval);
 	kit->irq->transfer_dma = kit->data_dma;
 	kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
@@ -435,7 +515,8 @@
 	usb_set_intfdata(intf, kit);
 
 	if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
-		return -EIO;
+		rc = -EIO;
+		goto out;
 	}
 
 	if (ifkit->outputs >= 4) {
@@ -444,12 +525,22 @@
 		device_create_file(&intf->dev, &dev_attr_output3);
 		device_create_file(&intf->dev, &dev_attr_output4);
 	}
-	if (ifkit->outputs == 8) {
+	if (ifkit->outputs >= 8) {
 		device_create_file(&intf->dev, &dev_attr_output5);
 		device_create_file(&intf->dev, &dev_attr_output6);
 		device_create_file(&intf->dev, &dev_attr_output7);
 		device_create_file(&intf->dev, &dev_attr_output8);
 	} 
+	if (ifkit->outputs == 16) {
+		device_create_file(&intf->dev, &dev_attr_output9);
+		device_create_file(&intf->dev, &dev_attr_output10);
+		device_create_file(&intf->dev, &dev_attr_output11);
+		device_create_file(&intf->dev, &dev_attr_output12);
+		device_create_file(&intf->dev, &dev_attr_output13);
+		device_create_file(&intf->dev, &dev_attr_output14);
+		device_create_file(&intf->dev, &dev_attr_output15);
+		device_create_file(&intf->dev, &dev_attr_output16);
+	}
 
 	if (ifkit->inputs >= 4) {
 		device_create_file(&intf->dev, &dev_attr_input1);
@@ -457,12 +548,22 @@
 		device_create_file(&intf->dev, &dev_attr_input3);
 		device_create_file(&intf->dev, &dev_attr_input4);
 	}
-	if (ifkit->inputs == 8) {
+	if (ifkit->inputs >= 8) {
 		device_create_file(&intf->dev, &dev_attr_input5);
 		device_create_file(&intf->dev, &dev_attr_input6);
 		device_create_file(&intf->dev, &dev_attr_input7);
 		device_create_file(&intf->dev, &dev_attr_input8);
 	}
+	if (ifkit->inputs == 16) {
+		device_create_file(&intf->dev, &dev_attr_input9);
+		device_create_file(&intf->dev, &dev_attr_input10);
+		device_create_file(&intf->dev, &dev_attr_input11);
+		device_create_file(&intf->dev, &dev_attr_input12);
+		device_create_file(&intf->dev, &dev_attr_input13);
+		device_create_file(&intf->dev, &dev_attr_input14);
+		device_create_file(&intf->dev, &dev_attr_input15);
+		device_create_file(&intf->dev, &dev_attr_input16);
+	}
 
 	if (ifkit->sensors >= 4) {
 		device_create_file(&intf->dev, &dev_attr_sensor1);
@@ -475,9 +576,8 @@
 		device_create_file(&intf->dev, &dev_attr_sensor6);
 		device_create_file(&intf->dev, &dev_attr_sensor7);
 	}
-	if (ifkit->sensors == 8) {
+	if (ifkit->sensors == 8)
 		device_create_file(&intf->dev, &dev_attr_sensor8);
-	}
 
 	if (ifkit->has_lcd)
 		device_create_file(&intf->dev, &dev_attr_lcd);
@@ -486,29 +586,56 @@
 			ifkit->sensors, ifkit->inputs, ifkit->outputs);
 
 	return 0;
+
+out:
+	if (kit) {
+		if (kit->irq)
+			usb_free_urb(kit->irq);
+		if (kit->data)
+			usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
+		kfree(kit);
+	}
+
+	return rc;
 }
 
 static void interfacekit_disconnect(struct usb_interface *interface)
 {
-	struct phidget_interfacekit *kit;
+	struct interfacekit *kit;
 
 	kit = usb_get_intfdata(interface);
 	usb_set_intfdata(interface, NULL);
 	if (!kit)
 		return;
 
+	usb_kill_urb(kit->irq);
+	usb_free_urb(kit->irq);
+	usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma);
+
+	cancel_delayed_work(&kit->do_notify);
+
 	if (kit->ifkit->outputs >= 4) {
 		device_remove_file(&interface->dev, &dev_attr_output1);
 		device_remove_file(&interface->dev, &dev_attr_output2);
 		device_remove_file(&interface->dev, &dev_attr_output3);
 		device_remove_file(&interface->dev, &dev_attr_output4);
 	}
-	if (kit->ifkit->outputs == 8) {
+	if (kit->ifkit->outputs >= 8) {
 		device_remove_file(&interface->dev, &dev_attr_output5);
 		device_remove_file(&interface->dev, &dev_attr_output6);
 		device_remove_file(&interface->dev, &dev_attr_output7);
 		device_remove_file(&interface->dev, &dev_attr_output8);
 	}
+	if (kit->ifkit->outputs == 16) {
+		device_remove_file(&interface->dev, &dev_attr_output9);
+		device_remove_file(&interface->dev, &dev_attr_output10);
+		device_remove_file(&interface->dev, &dev_attr_output11);
+		device_remove_file(&interface->dev, &dev_attr_output12);
+		device_remove_file(&interface->dev, &dev_attr_output13);
+		device_remove_file(&interface->dev, &dev_attr_output14);
+		device_remove_file(&interface->dev, &dev_attr_output15);
+		device_remove_file(&interface->dev, &dev_attr_output16);
+	}
 
 	if (kit->ifkit->inputs >= 4) {
 		device_remove_file(&interface->dev, &dev_attr_input1);
@@ -516,12 +643,22 @@
 		device_remove_file(&interface->dev, &dev_attr_input3);
 		device_remove_file(&interface->dev, &dev_attr_input4);
 	}
-	if (kit->ifkit->inputs == 8) {
+	if (kit->ifkit->inputs >= 8) {
 		device_remove_file(&interface->dev, &dev_attr_input5);
 		device_remove_file(&interface->dev, &dev_attr_input6);
 		device_remove_file(&interface->dev, &dev_attr_input7);
 		device_remove_file(&interface->dev, &dev_attr_input8);
 	}
+	if (kit->ifkit->inputs == 16) {
+		device_remove_file(&interface->dev, &dev_attr_input9);
+		device_remove_file(&interface->dev, &dev_attr_input10);
+		device_remove_file(&interface->dev, &dev_attr_input11);
+		device_remove_file(&interface->dev, &dev_attr_input12);
+		device_remove_file(&interface->dev, &dev_attr_input13);
+		device_remove_file(&interface->dev, &dev_attr_input14);
+		device_remove_file(&interface->dev, &dev_attr_input15);
+		device_remove_file(&interface->dev, &dev_attr_input16);
+	}
 
 	if (kit->ifkit->sensors >= 4) {
 		device_remove_file(&interface->dev, &dev_attr_sensor1);
@@ -534,19 +671,15 @@
 		device_remove_file(&interface->dev, &dev_attr_sensor6);
 		device_remove_file(&interface->dev, &dev_attr_sensor7);
 	}
-	if (kit->ifkit->sensors == 8) {
+	if (kit->ifkit->sensors == 8)
 		device_remove_file(&interface->dev, &dev_attr_sensor8);
-	}
+
 	if (kit->ifkit->has_lcd)
 		device_remove_file(&interface->dev, &dev_attr_lcd);
 
 	dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
 		kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
 
-	usb_kill_urb(kit->irq);
-	usb_free_urb(kit->irq);
-	usb_buffer_free(kit->udev, 8, kit->data, kit->data_dma);
-
 	usb_put_dev(kit->udev);
 	kfree(kit);
 }
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
index 196c879..738bd7c 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -37,6 +37,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -52,6 +53,7 @@
 #include <linux/vmalloc.h>
 
 #include "sisusb.h"
+#include "sisusb_init.h"
 
 #ifdef INCL_SISUSB_CON
 #include <linux/font.h>
@@ -62,36 +64,6 @@
 /* Forward declarations / clean-up routines */
 
 #ifdef INCL_SISUSB_CON
-int	sisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data);
-int	sisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data);
-int	sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data);
-int	sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data);
-int	sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,	u8 myand, u8 myor);
-int	sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor);
-int	sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand);
-
-int	sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
-int	sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
-int	sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
-int	sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
-int	sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
-			u32 dest, int length, size_t *bytes_written);
-
-int	sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
-
-extern int  SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
-extern int  SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
-
-extern void sisusb_init_concode(void);
-extern int  sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
-extern void sisusb_console_exit(struct sisusb_usb_data *sisusb);
-
-extern void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
-
-extern int  sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
-		u8 *arg, int cmapsz, int ch512, int dorecalc,
-		struct vc_data *c, int fh, int uplock);
-
 static int sisusb_first_vc = 0;
 static int sisusb_last_vc = 0;
 module_param_named(first, sisusb_first_vc, int, 0);
@@ -102,7 +74,7 @@
 
 static struct usb_driver sisusb_driver;
 
-DECLARE_MUTEX(disconnect_sem);
+DEFINE_MUTEX(disconnect_mutex);
 
 static void
 sisusb_free_buffers(struct sisusb_usb_data *sisusb)
@@ -1359,9 +1331,6 @@
 }
 #endif
 
-#ifndef INCL_SISUSB_CON
-static
-#endif
 int
 sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
 {
@@ -1371,9 +1340,6 @@
 	return ret;
 }
 
-#ifndef INCL_SISUSB_CON
-static
-#endif
 int
 sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
 {
@@ -1383,9 +1349,6 @@
 	return ret;
 }
 
-#ifndef INCL_SISUSB_CON
-static
-#endif
 int
 sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
 							u8 myand, u8 myor)
@@ -1415,18 +1378,12 @@
 	return ret;
 }
 
-#ifndef INCL_SISUSB_CON
-static
-#endif
 int
 sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
 {
 	return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
 }
 
-#ifndef INCL_SISUSB_CON
-static
-#endif
 int
 sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
 {
@@ -1448,6 +1405,8 @@
 	return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));
 }
 
+#if 0
+
 int
 sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data)
 {
@@ -1460,6 +1419,8 @@
 	return(sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));
 }
 
+#endif  /*  0  */
+
 int
 sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
 			u32 dest, int length, size_t *bytes_written)
@@ -2552,39 +2513,39 @@
 	struct usb_interface *interface;
 	int subminor = iminor(inode);
 
-	down(&disconnect_sem);
+	mutex_lock(&disconnect_mutex);
 
 	if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
 		printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
 				subminor);
-		up(&disconnect_sem);
+		mutex_unlock(&disconnect_mutex);
 		return -ENODEV;
 	}
 
 	if (!(sisusb = usb_get_intfdata(interface))) {
-		up(&disconnect_sem);
+		mutex_unlock(&disconnect_mutex);
 		return -ENODEV;
 	}
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	if (!sisusb->present || !sisusb->ready) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		return -ENODEV;
 	}
 
 	if (sisusb->isopen) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		return -EBUSY;
 	}
 
 	if (!sisusb->devinit) {
 		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
 			if (sisusb_init_gfxdevice(sisusb, 0)) {
-				up(&sisusb->lock);
-				up(&disconnect_sem);
+				mutex_unlock(&sisusb->lock);
+				mutex_unlock(&disconnect_mutex);
 				printk(KERN_ERR
 					"sisusbvga[%d]: Failed to initialize "
 					"device\n",
@@ -2592,8 +2553,8 @@
 				return -EIO;
 			}
 		} else {
-			up(&sisusb->lock);
-			up(&disconnect_sem);
+			mutex_unlock(&sisusb->lock);
+			mutex_unlock(&disconnect_mutex);
 			printk(KERN_ERR
 				"sisusbvga[%d]: Device not attached to "
 				"USB 2.0 hub\n",
@@ -2609,9 +2570,9 @@
 
 	file->private_data = sisusb;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
-	up(&disconnect_sem);
+	mutex_unlock(&disconnect_mutex);
 
 	return 0;
 }
@@ -2642,14 +2603,14 @@
 	struct sisusb_usb_data *sisusb;
 	int myminor;
 
-	down(&disconnect_sem);
+	mutex_lock(&disconnect_mutex);
 
 	if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
-		up(&disconnect_sem);
+		mutex_unlock(&disconnect_mutex);
 		return -ENODEV;
 	}
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	if (sisusb->present) {
 		/* Wait for all URBs to finish if device still present */
@@ -2662,12 +2623,12 @@
 	sisusb->isopen = 0;
 	file->private_data = NULL;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	/* decrement the usage count on our device */
 	kref_put(&sisusb->kref, sisusb_delete);
 
-	up(&disconnect_sem);
+	mutex_unlock(&disconnect_mutex);
 
 	return 0;
 }
@@ -2685,11 +2646,11 @@
 	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
 		return -ENODEV;
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	/* Sanity check */
 	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return -ENODEV;
 	}
 
@@ -2784,7 +2745,7 @@
 		    (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
 
 		if (count != 4) {
-			up(&sisusb->lock);
+			mutex_unlock(&sisusb->lock);
 			return -EINVAL;
 		}
 
@@ -2808,7 +2769,7 @@
 
 	(*ppos) += bytes_read;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return errno ? errno : bytes_read;
 }
@@ -2827,11 +2788,11 @@
 	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
 		return -ENODEV;
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	/* Sanity check */
 	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return -ENODEV;
 	}
 
@@ -2930,7 +2891,7 @@
 		    (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
 
 		if (count != 4) {
-			up(&sisusb->lock);
+			mutex_unlock(&sisusb->lock);
 			return -EINVAL;
 		}
 
@@ -2956,7 +2917,7 @@
 
 	(*ppos) += bytes_written;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return errno ? errno : bytes_written;
 }
@@ -2970,11 +2931,11 @@
 	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
 		return -ENODEV;
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	/* Sanity check */
 	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return -ENODEV;
 	}
 
@@ -2994,7 +2955,7 @@
 			ret = -EINVAL;
 	}
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 	return ret;
 }
 
@@ -3136,7 +3097,7 @@
 	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
 		return -ENODEV;
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	/* Sanity check */
 	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
@@ -3193,7 +3154,7 @@
 	}
 
 err_out:
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 	return retval;
 }
 
@@ -3258,7 +3219,7 @@
 	}
 	kref_init(&sisusb->kref);
 
-	init_MUTEX(&(sisusb->lock));
+	mutex_init(&(sisusb->lock));
 
 	/* Register device */
 	if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
@@ -3429,9 +3390,9 @@
 	 * protect all other routines from the disconnect
 	 * case, not the other way round.
 	 */
-	down(&disconnect_sem);
+	mutex_lock(&disconnect_mutex);
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	/* Wait for all URBs to complete and kill them in case (MUST do) */
 	if (!sisusb_wait_all_out_complete(sisusb))
@@ -3462,12 +3423,12 @@
 	sisusb->present = 0;
 	sisusb->ready = 0;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	/* decrement our usage count */
 	kref_put(&sisusb->kref, sisusb_delete);
 
-	up(&disconnect_sem);
+	mutex_unlock(&disconnect_mutex);
 
 	printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
 }
diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
index a716825..8e1120a 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.h
+++ b/drivers/usb/misc/sisusbvga/sisusb.h
@@ -41,6 +41,8 @@
 #define SISUSB_NEW_CONFIG_COMPAT
 #endif
 
+#include <linux/mutex.h>
+
 /* For older kernels, support for text consoles is by default
  * off. To ensable text console support, change the following:
  */
@@ -60,11 +62,9 @@
 #define INCL_SISUSB_CON		1
 #endif
 
-#ifdef INCL_SISUSB_CON
 #include <linux/console.h>
 #include <linux/vt_kern.h>
 #include "sisusb_struct.h"
-#endif
 
 /* USB related */
 
@@ -116,7 +116,7 @@
 	struct usb_interface *interface;
 	struct kref kref;
 	wait_queue_head_t wait_q;	/* for syncind and timeouts */
-	struct semaphore lock;		/* general race avoidance */
+	struct mutex lock;		/* general race avoidance */
 	unsigned int ifnum;		/* interface number of the USB device */
 	int minor;			/* minor (for logging clarity) */
 	int isopen;			/* !=0 if open */
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index be5c1a2..fb48fec 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -48,6 +48,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
@@ -69,27 +70,9 @@
 #include <linux/vmalloc.h>
 
 #include "sisusb.h"
+#include "sisusb_init.h"
 
 #ifdef INCL_SISUSB_CON
-extern int sisusb_setreg(struct sisusb_usb_data *, int, u8);
-extern int sisusb_getreg(struct sisusb_usb_data *, int, u8 *);
-extern int sisusb_setidxreg(struct sisusb_usb_data *, int, u8, u8);
-extern int sisusb_getidxreg(struct sisusb_usb_data *, int, u8, u8 *);
-extern int sisusb_setidxregor(struct sisusb_usb_data *, int, u8, u8);
-extern int sisusb_setidxregand(struct sisusb_usb_data *, int, u8, u8);
-extern int sisusb_setidxregandor(struct sisusb_usb_data *, int, u8, u8, u8);
-
-extern int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
-extern int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
-extern int sisusb_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data);
-extern int sisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data);
-extern int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
-			u32 dest, int length, size_t *bytes_written);
-
-extern void sisusb_delete(struct kref *kref);
-extern int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
-
-extern int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 
 #define sisusbcon_writew(val, addr)	(*(addr) = (val))
 #define sisusbcon_readw(addr)		(*(addr))
@@ -102,8 +85,6 @@
 /* Forward declaration */
 static const struct consw sisusb_con;
 
-extern struct semaphore disconnect_sem;
-
 static inline void
 sisusbcon_memsetw(u16 *s, u16 c, unsigned int count)
 {
@@ -194,11 +175,11 @@
 	if (!(sisusb = sisusb_get_sisusb(console)))
 		return NULL;
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	if (!sisusb_sisusb_valid(sisusb) ||
 	    !sisusb->havethisconsole[console]) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return NULL;
 	}
 
@@ -236,18 +217,18 @@
 	 * are set up/restored.
 	 */
 
-	down(&disconnect_sem);
+	mutex_lock(&disconnect_mutex);
 
 	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
-		up(&disconnect_sem);
+		mutex_unlock(&disconnect_mutex);
 		return;
 	}
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	if (!sisusb_sisusb_valid(sisusb)) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		return;
 	}
 
@@ -284,9 +265,9 @@
 	if (!*c->vc_uni_pagedir_loc)
 		con_set_default_unimap(c);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
-	up(&disconnect_sem);
+	mutex_unlock(&disconnect_mutex);
 
 	if (init) {
 		c->vc_cols = cols;
@@ -306,14 +287,14 @@
 	 * and others, ie not under our control.
 	 */
 
-	down(&disconnect_sem);
+	mutex_lock(&disconnect_mutex);
 
 	if (!(sisusb = sisusb_get_sisusb(c->vc_num))) {
-		up(&disconnect_sem);
+		mutex_unlock(&disconnect_mutex);
 		return;
 	}
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	/* Clear ourselves in mysisusbs */
 	mysisusbs[c->vc_num] = NULL;
@@ -332,12 +313,12 @@
 		}
 	}
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	/* decrement the usage count on our sisusb */
 	kref_put(&sisusb->kref, sisusb_delete);
 
-	up(&disconnect_sem);
+	mutex_unlock(&disconnect_mutex);
 }
 
 /* interface routine */
@@ -417,7 +398,7 @@
 #endif
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return;
 	}
 
@@ -425,7 +406,7 @@
 	sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
 				(u32)SISUSB_HADDR(x, y), 2, &written);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 }
 
 /* Interface routine */
@@ -453,14 +434,14 @@
 		sisusbcon_writew(sisusbcon_readw(s++), dest++);
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return;
 	}
 
 	sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(x, y),
 				(u32)SISUSB_HADDR(x, y), count * 2, &written);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 }
 
 /* Interface routine */
@@ -504,7 +485,7 @@
 	}
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return;
 	}
 
@@ -514,7 +495,7 @@
 	sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(x, y),
 				(u32)SISUSB_HADDR(x, y), length, &written);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 }
 
 /* Interface routine */
@@ -576,7 +557,7 @@
 #endif
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return;
 	}
 
@@ -586,7 +567,7 @@
 	sisusb_copy_memory(sisusb, (unsigned char *)SISUSB_VADDR(dx, dy),
 				(u32)SISUSB_HADDR(dx, dy), length, &written);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 }
 
 /* interface routine */
@@ -609,7 +590,7 @@
 
 	/* Don't write to screen if in gfx mode */
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return 0;
 	}
 
@@ -618,7 +599,7 @@
 	 * as origin.
 	 */
 	if (c->vc_origin == (unsigned long)c->vc_screenbuf) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		printk(KERN_DEBUG "sisusb: ASSERT ORIGIN != SCREENBUF!\n");
 		return 0;
 	}
@@ -635,7 +616,7 @@
 				(u32)SISUSB_HADDR(0, 0),
 				length, &written);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return 0;
 }
@@ -657,7 +638,7 @@
 	/* sisusb->lock is down */
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return;
 	}
 
@@ -669,7 +650,7 @@
 	sisusbcon_memcpyw((u16 *)c->vc_screenbuf, (u16 *)c->vc_origin,
 								length);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 }
 
 /* interface routine */
@@ -690,7 +671,7 @@
 	/* sisusb->lock is down */
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return -EINVAL;
 	}
 
@@ -705,7 +686,7 @@
 			break;
 	}
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return 0;
 }
@@ -728,7 +709,7 @@
 		sisusb->is_gfx = blank ? 1 : 0;
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return 0;
 	}
 
@@ -777,7 +758,7 @@
 			cr63  = 0x40;
 			break;
 		default:
-			up(&sisusb->lock);
+			mutex_unlock(&sisusb->lock);
 			return -EINVAL;
 		}
 
@@ -788,7 +769,7 @@
 
 	}
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return ret;
 }
@@ -809,7 +790,7 @@
 	/* sisusb->lock is down */
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return 0;
 	}
 
@@ -849,7 +830,7 @@
 
 	sisusbcon_set_start_address(sisusb, c);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return 1;
 }
@@ -867,7 +848,7 @@
 	/* sisusb->lock is down */
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return;
 	}
 
@@ -879,7 +860,7 @@
 	if (mode == CM_ERASE) {
 		sisusb_setidxregor(sisusb, SISCR, 0x0a, 0x20);
 		sisusb->sisusb_cursor_size_to = -1;
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return;
 	}
 
@@ -919,7 +900,7 @@
 		sisusb->sisusb_cursor_size_to   = to;
 	}
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 }
 
 static int
@@ -961,7 +942,7 @@
 	sisusb_copy_memory(sisusb, (char *)SISUSB_VADDR(0, t),
 				(u32)SISUSB_HADDR(0, t), length, &written);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return 1;
 }
@@ -994,7 +975,7 @@
 	/* sisusb->lock is down */
 
 	if (sisusb_is_inactive(c, sisusb)) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return 0;
 	}
 
@@ -1084,7 +1065,7 @@
 
 	c->vc_pos = c->vc_pos - oldorigin + c->vc_origin;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return 1;
 }
@@ -1106,7 +1087,7 @@
 	/* sisusb->lock is down */
 
 	if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return 0;
 	}
 
@@ -1116,7 +1097,7 @@
 
 	sisusb->con_rolled_over = 0;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return 1;
 }
@@ -1133,7 +1114,7 @@
 
 	fh = sisusb->current_font_height;
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	/* We are quite unflexible as regards resizing. The vt code
 	 * handles sizes where the line length isn't equal the pitch
@@ -1167,7 +1148,7 @@
 
 	if ((slot != 0 && slot != 2) || !fh) {
 		if (uplock)
-			up(&sisusb->lock);
+			mutex_unlock(&sisusb->lock);
 		return -EINVAL;
 	}
 
@@ -1327,7 +1308,7 @@
 	}
 
 	if (uplock)
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 
 	if (dorecalc && c) {
 		int i, rows = c->vc_scan_lines / fh;
@@ -1351,7 +1332,7 @@
 
 font_op_error:
 	if (uplock)
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 
 	return -EIO;
 }
@@ -1417,19 +1398,19 @@
 	font->charcount = 256;
 
 	if (!font->data) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return 0;
 	}
 
 	if (!sisusb->font_backup) {
-		up(&sisusb->lock);
+		mutex_unlock(&sisusb->lock);
 		return -ENODEV;
 	}
 
 	/* Copy 256 chars only, like vgacon */
 	memcpy(font->data, sisusb->font_backup, 256 * 32);
 
-	up(&sisusb->lock);
+	mutex_unlock(&sisusb->lock);
 
 	return 0;
 }
@@ -1486,7 +1467,7 @@
 
 #define SISUSBCONDUMMY	(void *)sisusbdummycon_dummy
 
-const struct consw sisusb_dummy_con = {
+static const struct consw sisusb_dummy_con = {
 	.owner =		THIS_MODULE,
 	.con_startup =		sisusbdummycon_startup,
 	.con_init =		sisusbdummycon_init,
@@ -1512,14 +1493,14 @@
 {
 	int i, ret, minor = sisusb->minor;
 
-	down(&disconnect_sem);
+	mutex_lock(&disconnect_mutex);
 
-	down(&sisusb->lock);
+	mutex_lock(&sisusb->lock);
 
 	/* Erm.. that should not happen */
 	if (sisusb->haveconsole || !sisusb->SiS_Pr) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		return 1;
 	}
 
@@ -1529,15 +1510,15 @@
 	if (first > last ||
 	    first > MAX_NR_CONSOLES ||
 	    last > MAX_NR_CONSOLES) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		return 1;
 	}
 
 	/* If gfxcore not initialized or no consoles given, quit graciously */
 	if (!sisusb->gfxinit || first < 1 || last < 1) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		return 0;
 	}
 
@@ -1547,8 +1528,8 @@
 
 	/* Set up text mode (and upload  default font) */
 	if (sisusb_reset_text_mode(sisusb, 1)) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		printk(KERN_ERR
 			"sisusbvga[%d]: Failed to set up text mode\n",
 			minor);
@@ -1571,16 +1552,16 @@
 
 	/* Allocate screen buffer */
 	if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {
-		up(&sisusb->lock);
-		up(&disconnect_sem);
+		mutex_unlock(&sisusb->lock);
+		mutex_unlock(&disconnect_mutex);
 		printk(KERN_ERR
 			"sisusbvga[%d]: Failed to allocate screen buffer\n",
 			minor);
 		return 1;
 	}
 
-	up(&sisusb->lock);
-	up(&disconnect_sem);
+	mutex_unlock(&sisusb->lock);
+	mutex_unlock(&disconnect_mutex);
 
 	/* Now grab the desired console(s) */
 	ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c
index 044fa44..968f0d3 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_init.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.c
@@ -74,6 +74,7 @@
 /*            HELPER: Get ModeID             */
 /*********************************************/
 
+#if 0
 unsigned short
 SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth)
 {
@@ -157,6 +158,7 @@
 
 	return ModeIndex;
 }
+#endif  /*  0  */
 
 /*********************************************/
 /*          HELPER: SetReg, GetReg           */
@@ -233,7 +235,7 @@
 /*        HELPER: Init Port Addresses        */
 /*********************************************/
 
-void
+static void
 SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr)
 {
 	SiS_Pr->SiS_P3c4 = BaseAddr + 0x14;
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h
index 5b11577..f05f832 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_init.h
+++ b/drivers/usb/misc/sisusbvga/sisusb_init.h
@@ -690,7 +690,7 @@
    0x41}}   /* 0x54 */
 };
 
-static struct SiS_VCLKData SiSUSB_VCLKData[] =
+static const struct SiS_VCLKData SiSUSB_VCLKData[] =
 {
 	{ 0x1b,0xe1, 25}, /* 0x00 */
 	{ 0x4e,0xe4, 28}, /* 0x01 */
@@ -808,8 +808,8 @@
 	{ 0x2b,0xc2, 35}  /* 0x71 768@576@60 */
 };
 
-void		SiSUSBRegInit(struct SiS_Private *SiS_Pr, unsigned long BaseAddr);
-unsigned short	SiSUSB_GetModeID(int HDisplay, int VDisplay, int Depth);
+extern struct mutex disconnect_mutex;
+
 int		SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo);
 int		SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo);
 
@@ -826,5 +826,19 @@
 extern int	sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port,
 					u8 idx, u8 myand);
 
+void sisusb_delete(struct kref *kref);
+int sisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data);
+int sisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data);
+int sisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src,
+		       u32 dest, int length, size_t *bytes_written);
+int sisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init);
+int sisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,
+			 u8 *arg, int cmapsz, int ch512, int dorecalc,
+			 struct vc_data *c, int fh, int uplock);
+void sisusb_set_cursor(struct sisusb_usb_data *sisusb, unsigned int location);
+int sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last);
+void sisusb_console_exit(struct sisusb_usb_data *sisusb);
+void sisusb_init_concode(void);
+
 #endif
 
diff --git a/drivers/usb/misc/sisusbvga/sisusb_struct.h b/drivers/usb/misc/sisusbvga/sisusb_struct.h
index 94edd47..f325ecb 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_struct.h
+++ b/drivers/usb/misc/sisusbvga/sisusb_struct.h
@@ -161,7 +161,7 @@
 	const struct SiS_Ext		*SiS_EModeIDTable;
 	const struct SiS_Ext2		*SiS_RefIndex;
 	const struct SiS_CRT1Table	*SiS_CRT1Table;
-	struct SiS_VCLKData		*SiS_VCLKData;
+	const struct SiS_VCLKData	*SiS_VCLKData;
 	const struct SiS_ModeResInfo	*SiS_ModeResInfo;
 };
 
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index ccc5e82..81ba14c 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -802,7 +802,9 @@
 
 				if (u == urb || !u->dev)
 					continue;
+				spin_unlock(&ctx->lock);
 				status = usb_unlink_urb (u);
+				spin_lock(&ctx->lock);
 				switch (status) {
 				case -EINPROGRESS:
 				case -EBUSY:
@@ -1335,7 +1337,9 @@
 	unsigned		pending;
 	spinlock_t		lock;
 	struct completion	done;
+	int			submit_error;
 	unsigned long		errors;
+	unsigned long		packet_count;
 	struct usbtest_dev	*dev;
 };
 
@@ -1346,10 +1350,14 @@
 	spin_lock(&ctx->lock);
 	ctx->count--;
 
+	ctx->packet_count += urb->number_of_packets;
 	if (urb->error_count > 0)
 		ctx->errors += urb->error_count;
+	else if (urb->status != 0)
+		ctx->errors += urb->number_of_packets;
 
-	if (urb->status == 0 && ctx->count > (ctx->pending - 1)) {
+	if (urb->status == 0 && ctx->count > (ctx->pending - 1)
+			&& !ctx->submit_error) {
 		int status = usb_submit_urb (urb, GFP_ATOMIC);
 		switch (status) {
 		case 0:
@@ -1360,6 +1368,8 @@
 					status);
 			/* FALLTHROUGH */
 		case -ENODEV:			/* disconnected */
+		case -ESHUTDOWN:		/* endpoint disabled */
+			ctx->submit_error = 1;
 			break;
 		}
 	}
@@ -1369,8 +1379,8 @@
 	if (ctx->pending == 0) {
 		if (ctx->errors)
 			dev_dbg (&ctx->dev->intf->dev,
-				"iso test, %lu errors\n",
-				ctx->errors);
+				"iso test, %lu errors out of %lu\n",
+				ctx->errors, ctx->packet_count);
 		complete (&ctx->done);
 	}
 done:
@@ -1431,15 +1441,14 @@
 	struct usb_device	*udev;
 	unsigned		i;
 	unsigned long		packets = 0;
-	int			status;
+	int			status = 0;
 	struct urb		*urbs[10];	/* FIXME no limit */
 
 	if (param->sglen > 10)
 		return -EDOM;
 
+	memset(&context, 0, sizeof context);
 	context.count = param->iterations * param->sglen;
-	context.pending = param->sglen;
-	context.errors = 0;
 	context.dev = dev;
 	init_completion (&context.done);
 	spin_lock_init (&context.lock);
@@ -1471,6 +1480,7 @@
 
 	spin_lock_irq (&context.lock);
 	for (i = 0; i < param->sglen; i++) {
+		++context.pending;
 		status = usb_submit_urb (urbs [i], SLAB_ATOMIC);
 		if (status < 0) {
 			ERROR (dev, "submit iso[%d], error %d\n", i, status);
@@ -1481,12 +1491,26 @@
 
 			simple_free_urb (urbs [i]);
 			context.pending--;
+			context.submit_error = 1;
+			break;
 		}
 	}
 	spin_unlock_irq (&context.lock);
 
 	wait_for_completion (&context.done);
-	return 0;
+
+	/*
+	 * Isochronous transfers are expected to fail sometimes.  As an
+	 * arbitrary limit, we will report an error if any submissions
+	 * fail or if the transfer failure rate is > 10%.
+	 */
+	if (status != 0)
+		;
+	else if (context.submit_error)
+		status = -EACCES;
+	else if (context.errors > context.packet_count / 10)
+		status = -EIO;
+	return status;
 
 fail:
 	for (i = 0; i < param->sglen; i++) {
diff --git a/drivers/usb/mon/mon_dma.c b/drivers/usb/mon/mon_dma.c
index 0a1367b..ddcfc01 100644
--- a/drivers/usb/mon/mon_dma.c
+++ b/drivers/usb/mon/mon_dma.c
@@ -13,7 +13,10 @@
 #include <linux/usb.h>	/* Only needed for declarations in usb_mon.h */
 #include "usb_mon.h"
 
-#ifdef __i386__		/* CONFIG_ARCH_I386 does not exit */
+/*
+ * PC-compatibles, are, fortunately, sufficiently cache-coherent for this.
+ */
+#if defined(__i386__) || defined(__x86_64__) /* CONFIG_ARCH_I386 doesn't exit */
 #define MON_HAS_UNMAP 1
 
 #define phys_to_page(phys)	pfn_to_page((phys) >> PAGE_SHIFT)
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 6ecc273..275a66f 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -97,6 +97,7 @@
 	if (mbus->nreaders == 0)
 		goto out_locked;
 
+	mbus->cnt_events++;
 	list_for_each (pos, &mbus->r_list) {
 		r = list_entry(pos, struct mon_reader, r_link);
 		r->rnf_submit(r->r_data, urb);
@@ -113,20 +114,32 @@
 
 /*
  */
-static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err)
+static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
 {
 	struct mon_bus *mbus;
+	unsigned long flags;
+	struct list_head *pos;
+	struct mon_reader *r;
 
 	mbus = ubus->mon_bus;
 	if (mbus == NULL)
 		goto out_unlocked;
 
-	/*
-	 * XXX Capture the error code and the 'E' event.
-	 */
+	spin_lock_irqsave(&mbus->lock, flags);
+	if (mbus->nreaders == 0)
+		goto out_locked;
 
+	mbus->cnt_events++;
+	list_for_each (pos, &mbus->r_list) {
+		r = list_entry(pos, struct mon_reader, r_link);
+		r->rnf_error(r->r_data, urb, error);
+	}
+
+	spin_unlock_irqrestore(&mbus->lock, flags);
 	return;
 
+out_locked:
+	spin_unlock_irqrestore(&mbus->lock, flags);
 out_unlocked:
 	return;
 }
@@ -152,6 +165,7 @@
 	}
 
 	spin_lock_irqsave(&mbus->lock, flags);
+	mbus->cnt_events++;
 	list_for_each (pos, &mbus->r_list) {
 		r = list_entry(pos, struct mon_reader, r_link);
 		r->rnf_complete(r->r_data, urb);
@@ -163,7 +177,6 @@
 
 /*
  * Stop monitoring.
- * Obviously this must be well locked, so no need to play with mb's.
  */
 static void mon_stop(struct mon_bus *mbus)
 {
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
index 6e4b165..1fe01d9 100644
--- a/drivers/usb/mon/mon_stat.c
+++ b/drivers/usb/mon/mon_stat.c
@@ -31,8 +31,8 @@
 	mbus = inode->u.generic_ip;
 
 	sp->slen = snprintf(sp->str, STAT_BUF_SIZE,
-	    "nreaders %d text_lost %u\n",
-	    mbus->nreaders, mbus->cnt_text_lost);
+	    "nreaders %d events %u text_lost %u\n",
+	    mbus->nreaders, mbus->cnt_events, mbus->cnt_text_lost);
 
 	file->private_data = sp;
 	return 0;
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index ac043ec..e02c1a3 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -26,10 +26,13 @@
 
 /*
  * This limit exists to prevent OOMs when the user process stops reading.
+ * If usbmon were available to unprivileged processes, it might be open
+ * to a local DoS. But we have to keep to root in order to prevent
+ * password sniffing from HID devices.
  */
-#define EVENT_MAX  25
+#define EVENT_MAX  (2*PAGE_SIZE / sizeof(struct mon_event_text))
 
-#define PRINTF_DFL  130
+#define PRINTF_DFL  160
 
 struct mon_event_text {
 	struct list_head e_link;
@@ -111,7 +114,7 @@
 	 * number of corner cases, but it seems that the following is
 	 * more or less safe.
 	 *
-	 * We do not even try to look transfer_buffer, because it can
+	 * We do not even try to look at transfer_buffer, because it can
 	 * contain non-NULL garbage in case the upper level promised to
 	 * set DMA for the HCD.
 	 */
@@ -179,6 +182,32 @@
 	mon_text_event(rp, urb, 'C');
 }
 
+static void mon_text_error(void *data, struct urb *urb, int error)
+{
+	struct mon_reader_text *rp = data;
+	struct mon_event_text *ep;
+
+	if (rp->nevents >= EVENT_MAX ||
+	    (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+		rp->r.m_bus->cnt_text_lost++;
+		return;
+	}
+
+	ep->type = 'E';
+	ep->pipe = urb->pipe;
+	ep->id = (unsigned long) urb;
+	ep->tstamp = 0;
+	ep->length = 0;
+	ep->status = error;
+
+	ep->setup_flag = '-';
+	ep->data_flag = 'E';
+
+	rp->nevents++;
+	list_add_tail(&ep->e_link, &rp->e_list);
+	wake_up(&rp->wait);
+}
+
 /*
  * Fetch next event from the circular buffer.
  */
@@ -232,6 +261,7 @@
 	rp->r.m_bus = mbus;
 	rp->r.r_data = rp;
 	rp->r.rnf_submit = mon_text_submit;
+	rp->r.rnf_error = mon_text_error;
 	rp->r.rnf_complete = mon_text_complete;
 
 	snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum,
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
index 8e0613c..33678c2 100644
--- a/drivers/usb/mon/usb_mon.h
+++ b/drivers/usb/mon/usb_mon.h
@@ -27,6 +27,7 @@
 	struct kref ref;		/* Under mon_lock */
 
 	/* Stats */
+	unsigned int cnt_events;
 	unsigned int cnt_text_lost;
 };
 
@@ -39,6 +40,7 @@
 	void *r_data;		/* Use container_of instead? */
 
 	void (*rnf_submit)(void *data, struct urb *urb);
+	void (*rnf_error)(void *data, struct urb *urb, int error);
 	void (*rnf_complete)(void *data, struct urb *urb);
 };
 
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index efd6ca7..0540596 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -301,21 +301,4 @@
 	  some cases CDC MDLM) protocol, not "g_ether".
 
 
-config USB_ZD1201
-	tristate "USB ZD1201 based Wireless device support"
-	depends on NET_RADIO
-	select FW_LOADER
-	---help---
-	  Say Y if you want to use wireless LAN adapters based on the ZyDAS
-	  ZD1201 chip.
-
-	  This driver makes the adapter appear as a normal Ethernet interface,
-	  typically on wlan0.
-	  
-	  The zd1201 device requires external firmware to be loaded.
-	  This can be found at http://linux-lc100020.sourceforge.net/
-	  
-	  To compile this driver as a module, choose M here: the
-	  module will be called zd1201.
-
 endmenu
diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
index a21e6ea..160f19d 100644
--- a/drivers/usb/net/Makefile
+++ b/drivers/usb/net/Makefile
@@ -15,7 +15,6 @@
 obj-$(CONFIG_USB_NET_CDC_SUBSET)	+= cdc_subset.o
 obj-$(CONFIG_USB_NET_ZAURUS)	+= zaurus.o
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
-obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c
index 12b599a0..37111ac 100644
--- a/drivers/usb/net/asix.c
+++ b/drivers/usb/net/asix.c
@@ -912,6 +912,10 @@
         USB_DEVICE (0x0b95, 0x7720),
         .driver_info = (unsigned long) &ax88772_info,
 }, {
+	// ASIX AX88178 10/100/1000
+	USB_DEVICE (0x0b95, 0x1780),
+	.driver_info = (unsigned long) &ax88772_info,
+}, {
 	// Linksys USB200M Rev 2
 	USB_DEVICE (0x13b1, 0x0018),
 	.driver_info = (unsigned long) &ax88772_info,
diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c
index 63f1f3b..efd195b 100644
--- a/drivers/usb/net/cdc_ether.c
+++ b/drivers/usb/net/cdc_ether.c
@@ -31,7 +31,7 @@
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
-#include <linux/usb_cdc.h>
+#include <linux/usb/cdc.h>
 
 #include "usbnet.h"
 
@@ -455,6 +455,18 @@
 	.driver_info		= 0,
 },
 
+/* Olympus has some models with a Zaurus-compatible option.
+ * R-1000 uses a FreeScale i.MXL cpu (ARMv4T)
+ */
+{
+	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+		 | USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor               = 0x07B4,
+	.idProduct              = 0x0F02,	/* R-1000 */
+	ZAURUS_MASTER_INTERFACE,
+	.driver_info		= 0,
+},
+
 /*
  * WHITELIST!!!
  *
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 7683926..ab21f96 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -163,6 +163,8 @@
 
 	/* using ATOMIC, we'd never wake up if we slept */
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+		if (ret == -ENODEV)
+			netif_device_detach(pegasus->net);
 		if (netif_msg_drv(pegasus))
 			dev_err(&pegasus->intf->dev, "%s, status %d\n",
 					__FUNCTION__, ret);
@@ -217,6 +219,8 @@
 	set_current_state(TASK_UNINTERRUPTIBLE);
 
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+		if (ret == -ENODEV)
+			netif_device_detach(pegasus->net);
 		if (netif_msg_drv(pegasus))
 			dev_err(&pegasus->intf->dev, "%s, status %d\n",
 					__FUNCTION__, ret);
@@ -268,6 +272,8 @@
 	set_current_state(TASK_UNINTERRUPTIBLE);
 
 	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+		if (ret == -ENODEV)
+			netif_device_detach(pegasus->net);
 		if (netif_msg_drv(pegasus))
 			dev_err(&pegasus->intf->dev, "%s, status %d\n",
 					__FUNCTION__, ret);
@@ -298,10 +304,13 @@
 			     (char *) &pegasus->dr,
 			     pegasus->eth_regs, 3, ctrl_callback, pegasus);
 
-	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC)))
+	if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
+		if (ret == -ENODEV)
+			netif_device_detach(pegasus->net);
 		if (netif_msg_drv(pegasus))
 			dev_err(&pegasus->intf->dev, "%s, status %d\n",
 					__FUNCTION__, ret);
+	}
 
 	return ret;
 }
@@ -692,7 +701,10 @@
 			  usb_rcvbulkpipe(pegasus->usb, 1),
 			  pegasus->rx_skb->data, PEGASUS_MTU + 8,
 			  read_bulk_callback, pegasus);
-	if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) {
+	rx_status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
+	if (rx_status == -ENODEV)
+		netif_device_detach(pegasus->net);
+	else if (rx_status) {
 		pegasus->flags |= PEGASUS_RX_URB_FAIL;
 		goto tl_sched;
 	} else {
@@ -709,6 +721,7 @@
 {
 	pegasus_t *pegasus;
 	unsigned long flags;
+	int status;
 
 	pegasus = (pegasus_t *) data;
 	if (pegasus->flags & PEGASUS_UNPLUG)
@@ -734,7 +747,10 @@
 			  pegasus->rx_skb->data, PEGASUS_MTU + 8,
 			  read_bulk_callback, pegasus);
 try_again:
-	if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) {
+	status = usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC);
+	if (status == -ENODEV)
+		netif_device_detach(pegasus->net);
+	else if (status) {
 		pegasus->flags |= PEGASUS_RX_URB_FAIL;
 		tasklet_schedule(&pegasus->rx_tl);
 	} else {
@@ -836,6 +852,8 @@
 	}
 
 	status = usb_submit_urb(urb, SLAB_ATOMIC);
+	if (status == -ENODEV)
+		netif_device_detach(pegasus->net);
 	if (status && netif_msg_timer(pegasus))
 		printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n",
 				net->name, status);
@@ -874,6 +892,7 @@
 			/* cleanup should already have been scheduled */
 			break;
 		case -ENODEV:		/* disconnect() upcoming */
+			netif_device_detach(pegasus->net);
 			break;
 		default:
 			pegasus->stats.tx_errors++;
@@ -999,6 +1018,8 @@
 			  pegasus->rx_skb->data, PEGASUS_MTU + 8,
 			  read_bulk_callback, pegasus);
 	if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) {
+		if (res == -ENODEV)
+			netif_device_detach(pegasus->net);
 		if (netif_msg_ifup(pegasus))
 			pr_debug("%s: failed rx_urb, %d", net->name, res);
 		goto exit;
@@ -1009,6 +1030,8 @@
 			 pegasus->intr_buff, sizeof (pegasus->intr_buff),
 			 intr_callback, pegasus, pegasus->intr_interval);
 	if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) {
+		if (res == -ENODEV)
+			netif_device_detach(pegasus->net);
 		if (netif_msg_ifup(pegasus))
 			pr_debug("%s: failed intr_urb, %d\n", net->name, res);
 		usb_kill_urb(pegasus->rx_urb);
diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c
index 94ddfe1..f551546 100644
--- a/drivers/usb/net/rndis_host.c
+++ b/drivers/usb/net/rndis_host.c
@@ -30,7 +30,7 @@
 #include <linux/workqueue.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
-#include <linux/usb_cdc.h>
+#include <linux/usb/cdc.h>
 
 #include "usbnet.h"
 
diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c
index f7ac9d6..813e470 100644
--- a/drivers/usb/net/zaurus.c
+++ b/drivers/usb/net/zaurus.c
@@ -30,7 +30,7 @@
 #include <linux/mii.h>
 #include <linux/crc32.h>
 #include <linux/usb.h>
-#include <linux/usb_cdc.h>
+#include <linux/usb/cdc.h>
 
 #include "usbnet.h"
 
@@ -109,7 +109,7 @@
 	.check_connect = always_connected,
 	.bind =		zaurus_bind,
 	.unbind =	usbnet_cdc_unbind,
-	.tx_fixup = 	zaurus_tx_fixup,
+	.tx_fixup =	zaurus_tx_fixup,
 };
 #define	ZAURUS_STRONGARM_INFO	((unsigned long)&zaurus_sl5x00_info)
 
@@ -119,7 +119,7 @@
 	.check_connect = always_connected,
 	.bind =		zaurus_bind,
 	.unbind =	usbnet_cdc_unbind,
-	.tx_fixup = 	zaurus_tx_fixup,
+	.tx_fixup =	zaurus_tx_fixup,
 };
 #define	ZAURUS_PXA_INFO		((unsigned long)&zaurus_pxa_info)
 
@@ -129,7 +129,7 @@
 	.check_connect = always_connected,
 	.bind =		zaurus_bind,
 	.unbind =	usbnet_cdc_unbind,
-	.tx_fixup = 	zaurus_tx_fixup,
+	.tx_fixup =	zaurus_tx_fixup,
 };
 #define	OLYMPUS_MXL_INFO	((unsigned long)&olympus_mxl_info)
 
@@ -228,6 +228,11 @@
 						detail->bDetailData[2]);
 				goto bad_desc;
 			}
+
+			/* same extra framing as for non-BLAN mode */
+			dev->net->hard_header_len += 6;
+			dev->rx_urb_size = dev->net->hard_header_len
+					+ dev->net->mtu;
 			break;
 		}
 next_desc:
@@ -258,7 +263,7 @@
 	.description =	"pseudo-MDLM (BLAN) device",
 	.flags =	FLAG_FRAMING_Z,
 	.check_connect = always_connected,
-	.tx_fixup = 	zaurus_tx_fixup,
+	.tx_fixup =	zaurus_tx_fixup,
 	.bind =		blan_mdlm_bind,
 };
 
@@ -367,13 +372,13 @@
 
 static int __init zaurus_init(void)
 {
- 	return usb_register(&zaurus_driver);
+	return usb_register(&zaurus_driver);
 }
 module_init(zaurus_init);
 
 static void __exit zaurus_exit(void)
 {
- 	usb_deregister(&zaurus_driver);
+	usb_deregister(&zaurus_driver);
 }
 module_exit(zaurus_exit);
 
diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
deleted file mode 100644
index 9b1e4ed..0000000
--- a/drivers/usb/net/zd1201.c
+++ /dev/null
@@ -1,1944 +0,0 @@
-/*
- *	Driver for ZyDAS zd1201 based wireless USB devices.
- *
- *	Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	version 2 as published by the Free Software Foundation.
- *
- *	Parts of this driver have been derived from a wlan-ng version
- *	modified by ZyDAS. They also made documentation available, thanks!
- *	Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
- */
-
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/wireless.h>
-#include <net/iw_handler.h>
-#include <linux/string.h>
-#include <linux/if_arp.h>
-#include <linux/firmware.h>
-#include <net/ieee80211.h>
-#include "zd1201.h"
-
-static struct usb_device_id zd1201_table[] = {
-	{USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
-	{USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
-	{USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb  adapter */
-	{USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb  adapter */
-	{USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */
-	{}
-};
-
-static int ap = 0;	/* Are we an AP or a normal station? */
-
-#define ZD1201_VERSION	"0.15"
-
-MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
-MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters");
-MODULE_VERSION(ZD1201_VERSION);
-MODULE_LICENSE("GPL");
-module_param(ap, int, 0);
-MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded");
-MODULE_DEVICE_TABLE(usb, zd1201_table);
-
-
-static int zd1201_fw_upload(struct usb_device *dev, int apfw)
-{
-	const struct firmware *fw_entry;
-	char* data;
-	unsigned long len;
-	int err;
-	unsigned char ret;
-	char *buf;
-	char *fwfile;
-
-	if (apfw)
-		fwfile = "zd1201-ap.fw";
-	else
-		fwfile = "zd1201.fw";
-
-	err = request_firmware(&fw_entry, fwfile, &dev->dev);
-	if (err) {
-		dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
-		dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
-		dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n");
-		return err;
-	}
-
-	data = fw_entry->data;
-        len = fw_entry->size;
-
-	buf = kmalloc(1024, GFP_ATOMIC);
-	if (!buf)
-		goto exit;
-	
-	while (len > 0) {
-		int translen = (len > 1024) ? 1024 : len;
-		memcpy(buf, data, translen);
-
-		err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0,
-		    USB_DIR_OUT | 0x40, 0, 0, buf, translen,
-		    ZD1201_FW_TIMEOUT);
-		if (err < 0)
-			goto exit;
-
-		len -= translen;
-		data += translen;
-	}
-                                        
-	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2,
-	    USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
-	if (err < 0)
-		goto exit;
-                                                                                                                                                                
-	err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
-	    USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
-	if (err < 0)
-		goto exit;
-                                                                                                                                                                                                                                                                                        
-	if (ret & 0x80) {
-		err = -EIO;
-		goto exit;
-	}
-
-	err = 0;
-exit:
-	kfree(buf);
-	release_firmware(fw_entry);
-	return err;
-}
-
-static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
-{
-	struct zd1201 *zd = urb->context;
-
-	switch(urb->status) {
-		case -EILSEQ:
-		case -ENODEV:
-		case -ETIMEDOUT:
-		case -ENOENT:
-		case -EPIPE:
-		case -EOVERFLOW:
-		case -ESHUTDOWN:
-			dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", 
-			    zd->dev->name, urb->status);
-	}
-
-	kfree(urb->transfer_buffer);
-	usb_free_urb(urb);
-	return;
-}
-
-/* cmdreq message: 
-	u32 type
-	u16 cmd
-	u16 parm0
-	u16 parm1
-	u16 parm2
-	u8  pad[4]
-
-	total: 4 + 2 + 2 + 2 + 2 + 4 = 16
-*/
-static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0,
-			int parm1, int parm2)
-{
-	unsigned char *command;
-	int ret;
-	struct urb *urb;
-
-	command = kmalloc(16, GFP_ATOMIC);
-	if (!command)
-		return -ENOMEM;
-
-	*((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ);
-	*((__le16*)&command[4]) = cpu_to_le16(cmd);
-	*((__le16*)&command[6]) = cpu_to_le16(parm0);
-	*((__le16*)&command[8]) = cpu_to_le16(parm1);
-	*((__le16*)&command[10])= cpu_to_le16(parm2);
-
-	urb = usb_alloc_urb(0, GFP_ATOMIC);
-	if (!urb) {
-		kfree(command);
-		return -ENOMEM;
-	}
-	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
-	     command, 16, zd1201_usbfree, zd);
-	ret = usb_submit_urb(urb, GFP_ATOMIC);
-	if (ret) {
-		kfree(command);
-		usb_free_urb(urb);
-	}
-	
-	return ret;
-}
-
-/* Callback after sending out a packet */
-static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
-{
-	struct zd1201 *zd = urb->context;
-	netif_wake_queue(zd->dev);
-	return;
-}
-
-/* Incoming data */
-static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
-{
-	struct zd1201 *zd = urb->context;
-	int free = 0;
-	unsigned char *data = urb->transfer_buffer;
-	struct sk_buff *skb;
-	unsigned char type;
-
-	if (!zd) {
-		free = 1;
-		goto exit;
-	}
-
-	switch(urb->status) {
-		case -EILSEQ:
-		case -ENODEV:
-		case -ETIMEDOUT:
-		case -ENOENT:
-		case -EPIPE:
-		case -EOVERFLOW:
-		case -ESHUTDOWN:
-			dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n",
-			    zd->dev->name, urb->status);
-			free = 1;
-			goto exit;
-	}
-	
-	if (urb->status != 0 || urb->actual_length == 0)
-		goto resubmit;
-
-	type = data[0];
-	if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) {
-		memcpy(zd->rxdata, data, urb->actual_length);
-		zd->rxlen = urb->actual_length;
-		zd->rxdatas = 1;
-		wake_up(&zd->rxdataq);
-	}
-	/* Info frame */
-	if (type == ZD1201_PACKET_INQUIRE) {
-		int i = 0;
-		unsigned short infotype, framelen, copylen;
-		framelen = le16_to_cpu(*(__le16*)&data[4]);
-		infotype = le16_to_cpu(*(__le16*)&data[6]);
-
-		if (infotype == ZD1201_INF_LINKSTATUS) {
-			short linkstatus;
-
-			linkstatus = le16_to_cpu(*(__le16*)&data[8]);
-			switch(linkstatus) {
-				case 1:
-					netif_carrier_on(zd->dev);
-					break;
-				case 2:
-					netif_carrier_off(zd->dev);
-					break;
-				case 3:
-					netif_carrier_off(zd->dev);
-					break;
-				case 4:
-					netif_carrier_on(zd->dev);
-					break;
-				default:
-					netif_carrier_off(zd->dev);
-			}
-			goto resubmit;
-		}
-		if (infotype == ZD1201_INF_ASSOCSTATUS) {
-			short status = le16_to_cpu(*(__le16*)(data+8));
-			int event;
-			union iwreq_data wrqu;
-
-			switch (status) {
-				case ZD1201_ASSOCSTATUS_STAASSOC:
-				case ZD1201_ASSOCSTATUS_REASSOC:
-					event = IWEVREGISTERED;
-					break;
-				case ZD1201_ASSOCSTATUS_DISASSOC:
-				case ZD1201_ASSOCSTATUS_ASSOCFAIL:
-				case ZD1201_ASSOCSTATUS_AUTHFAIL:
-				default:
-					event = IWEVEXPIRED;
-			}
-			memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN);
-			wrqu.addr.sa_family = ARPHRD_ETHER;
-
-			/* Send event to user space */
-			wireless_send_event(zd->dev, event, &wrqu, NULL);
-
-			goto resubmit;
-		}
-		if (infotype == ZD1201_INF_AUTHREQ) {
-			union iwreq_data wrqu;
-
-			memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN);
-			wrqu.addr.sa_family = ARPHRD_ETHER;
-			/* There isn't a event that trully fits this request.
-			   We assume that userspace will be smart enough to
-			   see a new station being expired and sends back a
-			   authstation ioctl to authorize it. */
-			wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL);
-			goto resubmit;
-		}
-		/* Other infotypes are handled outside this handler */
-		zd->rxlen = 0;
-		while (i < urb->actual_length) {
-			copylen = le16_to_cpu(*(__le16*)&data[i+2]);
-			/* Sanity check, sometimes we get junk */
-			if (copylen+zd->rxlen > sizeof(zd->rxdata))
-				break;
-			memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen);
-			zd->rxlen += copylen;
-			i += 64;
-		}
-		if (i >= urb->actual_length) {
-			zd->rxdatas = 1;
-			wake_up(&zd->rxdataq);
-		}
-		goto  resubmit;
-	}
-	/* Actual data */
-	if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) {
-		int datalen = urb->actual_length-1;
-		unsigned short len, fc, seq;
-		struct hlist_node *node;
-
-		len = ntohs(*(__be16 *)&data[datalen-2]);
-		if (len>datalen)
-			len=datalen;
-		fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
-		seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
-
-		if(zd->monitor) {
-			if (datalen < 24)
-				goto resubmit;
-			if (!(skb = dev_alloc_skb(datalen+24)))
-				goto resubmit;
-			
-			memcpy(skb_put(skb, 2), &data[datalen-16], 2);
-			memcpy(skb_put(skb, 2), &data[datalen-2], 2);
-			memcpy(skb_put(skb, 6), &data[datalen-14], 6);
-			memcpy(skb_put(skb, 6), &data[datalen-22], 6);
-			memcpy(skb_put(skb, 6), &data[datalen-8], 6);
-			memcpy(skb_put(skb, 2), &data[datalen-24], 2);
-			memcpy(skb_put(skb, len), data, len);
-			skb->dev = zd->dev;
-			skb->dev->last_rx = jiffies;
-			skb->protocol = eth_type_trans(skb, zd->dev);
-			zd->stats.rx_packets++;
-			zd->stats.rx_bytes += skb->len;
-			netif_rx(skb);
-			goto resubmit;
-		}
-			
-		if ((seq & IEEE80211_SCTL_FRAG) ||
-		    (fc & IEEE80211_FCTL_MOREFRAGS)) {
-			struct zd1201_frag *frag = NULL;
-			char *ptr;
-
-			if (datalen<14)
-				goto resubmit;
-			if ((seq & IEEE80211_SCTL_FRAG) == 0) {
-				frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
-				if (!frag)
-					goto resubmit;
-				skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
-				if (!skb) {
-					kfree(frag);
-					goto resubmit;
-				}
-				frag->skb = skb;
-				frag->seq = seq & IEEE80211_SCTL_SEQ;
-				skb_reserve(skb, 2);
-				memcpy(skb_put(skb, 12), &data[datalen-14], 12);
-				memcpy(skb_put(skb, 2), &data[6], 2);
-				memcpy(skb_put(skb, len), data+8, len);
-				hlist_add_head(&frag->fnode, &zd->fraglist);
-				goto resubmit;
-			}
-			hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
-				if(frag->seq == (seq&IEEE80211_SCTL_SEQ))
-					break;
-			if (!frag)
-				goto resubmit;
-			skb = frag->skb;
-			ptr = skb_put(skb, len);
-			if (ptr)
-				memcpy(ptr, data+8, len);
-			if (fc & IEEE80211_FCTL_MOREFRAGS)
-				goto resubmit;
-			hlist_del_init(&frag->fnode);
-			kfree(frag);
-			/* Fallthrough */
-		} else {
-			if (datalen<14)
-				goto resubmit;
-			skb = dev_alloc_skb(len + 14 + 2);
-			if (!skb)
-				goto resubmit;
-			skb_reserve(skb, 2);
-			memcpy(skb_put(skb, 12), &data[datalen-14], 12);
-			memcpy(skb_put(skb, 2), &data[6], 2);
-			memcpy(skb_put(skb, len), data+8, len);
-		}
-		skb->dev = zd->dev;
-		skb->dev->last_rx = jiffies;
-		skb->protocol = eth_type_trans(skb, zd->dev);
-		zd->stats.rx_packets++;
-		zd->stats.rx_bytes += skb->len;
-		netif_rx(skb);
-	}
-resubmit:
-	memset(data, 0, ZD1201_RXSIZE);
-
-	urb->status = 0;
-	urb->dev = zd->usb;
-	if(usb_submit_urb(urb, GFP_ATOMIC))
-		free = 1;
-
-exit:
-	if (free) {
-		zd->rxlen = 0;
-		zd->rxdatas = 1;
-		wake_up(&zd->rxdataq);
-		kfree(urb->transfer_buffer);
-	}
-	return;
-}
-
-static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
-	unsigned int riddatalen)
-{
-	int err;
-	int i = 0;
-	int code;
-	int rid_fid;
-	int length;
-	unsigned char *pdata;
-	
-	zd->rxdatas = 0;
-	err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
-	if (err)
-		return err;
-
-	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
-	if (!zd->rxlen)
-		return -EIO;
-
-	code = le16_to_cpu(*(__le16*)(&zd->rxdata[4]));
-	rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6]));
-	length = le16_to_cpu(*(__le16*)(&zd->rxdata[8]));
-	if (length > zd->rxlen)
-		length = zd->rxlen-6;
-
-	/* If access bit is not on, then error */
-	if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid )
-		return -EINVAL;
-
-	/* Not enough buffer for allocating data */
-	if (riddatalen != (length - 4)) {
-		dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n",
-		    riddatalen, zd->rxlen, length, rid, rid_fid);
-		return -ENODATA;
-	}
-
-	zd->rxdatas = 0;
-	/* Issue SetRxRid commnd */			
-	err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length);
-	if (err)
-		return err;
-
-	/* Receive RID record from resource packets */
-	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
-	if (!zd->rxlen)
-		return -EIO;
-
-	if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) {
-		dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n",
-		    zd->rxdata[zd->rxlen-1]);
-		return -EINVAL;
-	}
-
-	/* Set the data pointer and received data length */
-	pdata = zd->rxdata;
-	length = zd->rxlen;
-
-	do {
-		int  actual_length;
-
-		actual_length = (length > 64) ? 64 : length;
-
-		if(pdata[0] != 0x3) {
-			dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
-			    pdata[0]);
-			return -EINVAL;
-		}
-
-		if (actual_length != 64) {
-			/* Trim the last packet type byte */
-			actual_length--;
-		}
-
-		/* Skip the 4 bytes header (RID length and RID) */
-		if(i == 0) {
-			pdata += 8;
-			actual_length -= 8;
-		}
-		else {
-			pdata += 4;
-			actual_length -= 4;
-		}
-		
-		memcpy(riddata, pdata, actual_length);
-		riddata += actual_length;
-		pdata += actual_length;
-		length -= 64;
-		i++;
-	} while (length > 0);
-
-	return 0;
-}
-
-/*
- *	resreq:
- *		byte	type
- *		byte	sequence
- *		u16	reserved
- *		byte	data[12]
- *	total: 16
- */
-static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait)
-{
-	int err;
-	unsigned char *request;
-	int reqlen;
-	char seq=0;
-	struct urb *urb;
-	gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
-
-	len += 4;			/* first 4 are for header */
-
-	zd->rxdatas = 0;
-	zd->rxlen = 0;
-	for (seq=0; len > 0; seq++) {
-		request = kmalloc(16, gfp_mask);
-		if (!request)
-			return -ENOMEM;
-		urb = usb_alloc_urb(0, gfp_mask);
-		if (!urb) {
-			kfree(request);
-			return -ENOMEM;
-		}
-		memset(request, 0, 16);
-		reqlen = len>12 ? 12 : len;
-		request[0] = ZD1201_USB_RESREQ;
-		request[1] = seq;
-		request[2] = 0;
-		request[3] = 0;
-		if (request[1] == 0) {
-			/* add header */
-			*(__le16*)&request[4] = cpu_to_le16((len-2+1)/2);
-			*(__le16*)&request[6] = cpu_to_le16(rid);
-			memcpy(request+8, buf, reqlen-4);
-			buf += reqlen-4;
-		} else {
-			memcpy(request+4, buf, reqlen);
-			buf += reqlen;
-		}
-
-		len -= reqlen;
-
-		usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb,
-		    zd->endp_out2), request, 16, zd1201_usbfree, zd);
-		err = usb_submit_urb(urb, gfp_mask);
-		if (err)
-			goto err;
-	}
-
-	request = kmalloc(16, gfp_mask);
-	if (!request)
-		return -ENOMEM;
-	urb = usb_alloc_urb(0, gfp_mask);
-	if (!urb) {
-		kfree(request);
-		return -ENOMEM;
-	}
-	*((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ);
-	*((__le16*)&request[4]) = 
-	    cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT);
-	*((__le16*)&request[6]) = cpu_to_le16(rid);
-	*((__le16*)&request[8]) = cpu_to_le16(0);
-	*((__le16*)&request[10]) = cpu_to_le16(0);
-	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
-	     request, 16, zd1201_usbfree, zd);
-	err = usb_submit_urb(urb, gfp_mask);
-	if (err)
-		goto err;
-	
-	if (wait) {
-		wait_event_interruptible(zd->rxdataq, zd->rxdatas);
-		if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) {
-			dev_dbg(&zd->usb->dev, "wrong or no RID received\n");
-		}
-	}
-
-	return 0;
-err:
-	kfree(request);
-	usb_free_urb(urb);
-	return err;
-}
-
-static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val)
-{
-	int err;
-	__le16 zdval;
-
-	err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16));
-	if (err)
-		return err;
-	*val = le16_to_cpu(zdval);
-	return 0;
-}
-
-static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val)
-{
-	__le16 zdval = cpu_to_le16(val);
-	return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1));
-}
-
-static int zd1201_drvr_start(struct zd1201 *zd)
-{
-	int err, i;
-	short max;
-	__le16 zdmax;
-	unsigned char *buffer;
-	
-	buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL);
-	if (!buffer)
-		return -ENOMEM;
-
-	usb_fill_bulk_urb(zd->rx_urb, zd->usb, 
-	    usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE,
-	    zd1201_usbrx, zd);
-
-	err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
-	if (err)
-		goto err_buffer;
-	
-	err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
-	if (err)
-		goto err_urb;
-
-	err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax,
-	    sizeof(__le16));
-	if (err)
-		goto err_urb;
-
-	max = le16_to_cpu(zdmax);
-	for (i=0; i<max; i++) {
-		err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0);
-		if (err)
-			goto err_urb;
-	}
-
-	return 0;
-
-err_urb:
-	usb_kill_urb(zd->rx_urb);
-	return err;
-err_buffer:
-	kfree(buffer);
-	return err;
-}
-
-/*	Magic alert: The firmware doesn't seem to like the MAC state being
- *	toggled in promisc (aka monitor) mode.
- *	(It works a number of times, but will halt eventually)
- *	So we turn it of before disabling and on after enabling if needed.
- */
-static int zd1201_enable(struct zd1201 *zd)
-{
-	int err;
-
-	if (zd->mac_enabled)
-		return 0;
-
-	err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0);
-	if (!err)
-		zd->mac_enabled = 1;
-
-	if (zd->monitor)
-		err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1);
-
-	return err;
-}
-
-static int zd1201_disable(struct zd1201 *zd)
-{
-	int err;
-	
-	if (!zd->mac_enabled)
-		return 0;
-	if (zd->monitor) {
-		err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
-		if (err)
-			return err;
-	}
-
-	err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0);
-	if (!err)
-		zd->mac_enabled = 0;
-	return err;
-}
-
-static int zd1201_mac_reset(struct zd1201 *zd)
-{
-	if (!zd->mac_enabled)
-		return 0;
-	zd1201_disable(zd);
-	return zd1201_enable(zd);
-}
-
-static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen)
-{
-	int err, val;
-	char buf[IW_ESSID_MAX_SIZE+2];
-
-	err = zd1201_disable(zd);
-	if (err)
-		return err;
-
-	val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
-	val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY;
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val);
-	if (err)
-		return err;
-
-	*(__le16 *)buf = cpu_to_le16(essidlen);
-	memcpy(buf+2, essid, essidlen);
-	if (!zd->ap) {	/* Normal station */
-		err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
-		    IW_ESSID_MAX_SIZE+2, 1);
-		if (err)
-			return err;
-	} else {	/* AP */
-		err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf,
-		    IW_ESSID_MAX_SIZE+2, 1);
-		if (err)
-			return err;
-	}
-
-	err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
-	    zd->dev->dev_addr, zd->dev->addr_len, 1);
-	if (err)
-		return err;
-
-	err = zd1201_enable(zd);
-	if (err)
-		return err;
-
-	msleep(100);
-	return 0;
-}
-
-static int zd1201_net_open(struct net_device *dev)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-
-	/* Start MAC with wildcard if no essid set */
-	if (!zd->mac_enabled)
-		zd1201_join(zd, zd->essid, zd->essidlen);
-	netif_start_queue(dev);
-
-	return 0;
-}
-
-static int zd1201_net_stop(struct net_device *dev)
-{
-	netif_stop_queue(dev);
-	
-	return 0;
-}
-
-/*
-	RFC 1042 encapsulates Ethernet frames in 802.11 frames
-	by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0
-	(0x00, 0x00, 0x00). Zd requires an additional padding, copy
-	of ethernet addresses, length of the standard RFC 1042 packet
-	and a command byte (which is nul for tx).
-	
-	tx frame (from Wlan NG):
-	RFC 1042:
-		llc		0xAA 0xAA 0x03 (802.2 LLC)
-		snap		0x00 0x00 0x00 (Ethernet encapsulated)
-		type		2 bytes, Ethernet type field
-		payload		(minus eth header)
-	Zydas specific:
-		padding		1B if (skb->len+8+1)%64==0
-		Eth MAC addr	12 bytes, Ethernet MAC addresses
-		length		2 bytes, RFC 1042 packet length 
-				(llc+snap+type+payload)
-		zd		1 null byte, zd1201 packet type
- */
-static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	unsigned char *txbuf = zd->txdata;
-	int txbuflen, pad = 0, err;
-	struct urb *urb = zd->tx_urb;
-
-	if (!zd->mac_enabled || zd->monitor) {
-		zd->stats.tx_dropped++;
-		kfree_skb(skb);
-		return 0;
-	}
-	netif_stop_queue(dev);
-
-	txbuflen = skb->len + 8 + 1;
-	if (txbuflen%64 == 0) {
-		pad = 1;
-		txbuflen++;
-	}
-	txbuf[0] = 0xAA;
-	txbuf[1] = 0xAA;
-	txbuf[2] = 0x03;
-	txbuf[3] = 0x00;	/* rfc1042 */
-	txbuf[4] = 0x00;
-	txbuf[5] = 0x00;
-
-	memcpy(txbuf+6, skb->data+12, skb->len-12);
-	if (pad)
-		txbuf[skb->len-12+6]=0;
-	memcpy(txbuf+skb->len-12+6+pad, skb->data, 12);
-	*(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6);
-	txbuf[txbuflen-1] = 0;
-
-	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out),
-	    txbuf, txbuflen, zd1201_usbtx, zd);
-
-	err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC);
-	if (err) {
-		zd->stats.tx_errors++;
-		netif_start_queue(dev);
-		return err;
-	}
-	zd->stats.tx_packets++;
-	zd->stats.tx_bytes += skb->len;
-	dev->trans_start = jiffies;
-	kfree_skb(skb);
-
-	return 0;
-}
-
-static void zd1201_tx_timeout(struct net_device *dev)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-
-	if (!zd)
-		return;
-	dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
-	    dev->name);
-	usb_unlink_urb(zd->tx_urb);
-	zd->stats.tx_errors++;
-	/* Restart the timeout to quiet the watchdog: */
-	dev->trans_start = jiffies;
-}
-
-static int zd1201_set_mac_address(struct net_device *dev, void *p)
-{
-	struct sockaddr *addr = p;
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	int err;
-
-	if (!zd)
-		return -ENODEV;
-
-	err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
-	    addr->sa_data, dev->addr_len, 1);
-	if (err)
-		return err;
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-
-	return zd1201_mac_reset(zd);
-}
-
-static struct net_device_stats *zd1201_get_stats(struct net_device *dev)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-
-	return &zd->stats;
-}
-
-static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-
-	return &zd->iwstats;
-}
-
-static void zd1201_set_multicast(struct net_device *dev)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	struct dev_mc_list *mc = dev->mc_list;
-	unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI];
-	int i;
-
-	if (dev->mc_count > ZD1201_MAXMULTI)
-		return;
-
-	for (i=0; i<dev->mc_count; i++) {
-		memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN);
-		mc = mc->next;
-	}
-	zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf,
-	    dev->mc_count*ETH_ALEN, 0);
-	
-}
-
-static int zd1201_config_commit(struct net_device *dev, 
-    struct iw_request_info *info, struct iw_point *data, char *essid)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-
-	return zd1201_mac_reset(zd);
-}
-
-static int zd1201_get_name(struct net_device *dev,
-    struct iw_request_info *info, char *name, char *extra)
-{
-	strcpy(name, "IEEE 802.11b");
-
-	return 0;
-}
-
-static int zd1201_set_freq(struct net_device *dev,
-    struct iw_request_info *info, struct iw_freq *freq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short channel = 0;
-	int err;
-
-	if (freq->e == 0)
-		channel = freq->m;
-	else {
-		if (freq->m >= 2482)
-			channel = 14;
-		if (freq->m >= 2407)
-			channel = (freq->m-2407)/5;
-	}
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
-	if (err)
-		return err;
-
-	zd1201_mac_reset(zd);
-
-	return 0;
-}
-
-static int zd1201_get_freq(struct net_device *dev,
-    struct iw_request_info *info, struct iw_freq *freq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short channel;
-	int err;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel);
-	if (err)
-		return err;
-	freq->e = 0;
-	freq->m = channel;
-
-	return 0;
-}
-
-static int zd1201_set_mode(struct net_device *dev,
-    struct iw_request_info *info, __u32 *mode, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short porttype, monitor = 0;
-	unsigned char buffer[IW_ESSID_MAX_SIZE+2];
-	int err;
-
-	if (zd->ap) {
-		if (*mode != IW_MODE_MASTER)
-			return -EINVAL;
-		return 0;
-	}
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
-	if (err)
-		return err;
-	zd->dev->type = ARPHRD_ETHER;
-	switch(*mode) {
-		case IW_MODE_MONITOR:
-			monitor = 1;
-			zd->dev->type = ARPHRD_IEEE80211;
-			/* Make sure we are no longer associated with by
-			   setting an 'impossible' essid.
-			   (otherwise we mess up firmware)
-			 */
-			zd1201_join(zd, "\0-*#\0", 5);
-			/* Put port in pIBSS */
-		case 8: /* No pseudo-IBSS in wireless extensions (yet) */
-			porttype = ZD1201_PORTTYPE_PSEUDOIBSS;
-			break;
-		case IW_MODE_ADHOC:
-			porttype = ZD1201_PORTTYPE_IBSS;
-			break;
-		case IW_MODE_INFRA:
-			porttype = ZD1201_PORTTYPE_BSS;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
-	if (err)
-		return err;
-	if (zd->monitor && !monitor) {
-			zd1201_disable(zd);
-			*(__le16 *)buffer = cpu_to_le16(zd->essidlen);
-			memcpy(buffer+2, zd->essid, zd->essidlen);
-			err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID,
-			    buffer, IW_ESSID_MAX_SIZE+2, 1);
-			if (err)
-				return err;
-	}
-	zd->monitor=monitor;
-	/* If monitor mode is set we don't actually turn it on here since it
-	 * is done during mac reset anyway (see zd1201_mac_enable).
-	 */
-
-	zd1201_mac_reset(zd);
-
-	return 0;
-}
-
-static int zd1201_get_mode(struct net_device *dev,
-    struct iw_request_info *info, __u32 *mode, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short porttype;
-	int err;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype);
-	if (err)
-		return err;
-	switch(porttype) {
-		case ZD1201_PORTTYPE_IBSS:
-			*mode = IW_MODE_ADHOC;
-			break;
-		case ZD1201_PORTTYPE_BSS:
-			*mode = IW_MODE_INFRA;
-			break;
-		case ZD1201_PORTTYPE_WDS:
-			*mode = IW_MODE_REPEAT;
-			break;
-		case ZD1201_PORTTYPE_PSEUDOIBSS:
-			*mode = 8;/* No Pseudo-IBSS... */
-			break;
-		case ZD1201_PORTTYPE_AP:
-			*mode = IW_MODE_MASTER;
-			break;
-		default:
-			dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n",
-			    porttype);
-			*mode = IW_MODE_AUTO;
-	}
-	if (zd->monitor)
-		*mode = IW_MODE_MONITOR;
-
-	return 0;
-}
-
-static int zd1201_get_range(struct net_device *dev,
-    struct iw_request_info *info, struct iw_point *wrq, char *extra)
-{
-	struct iw_range *range = (struct iw_range *)extra;
-
-	wrq->length = sizeof(struct iw_range);
-	memset(range, 0, sizeof(struct iw_range));
-	range->we_version_compiled = WIRELESS_EXT;
-	range->we_version_source = WIRELESS_EXT;
-
-	range->max_qual.qual = 128;
-	range->max_qual.level = 128;
-	range->max_qual.noise = 128;
-	range->max_qual.updated = 7;
-
-	range->encoding_size[0] = 5;
-	range->encoding_size[1] = 13;
-	range->num_encoding_sizes = 2;
-	range->max_encoding_tokens = ZD1201_NUMKEYS;
-
-	range->num_bitrates = 4;
-	range->bitrate[0] = 1000000;
-	range->bitrate[1] = 2000000;
-	range->bitrate[2] = 5500000;
-	range->bitrate[3] = 11000000;
-
-	range->min_rts = 0;
-	range->min_frag = ZD1201_FRAGMIN;
-	range->max_rts = ZD1201_RTSMAX;
-	range->min_frag = ZD1201_FRAGMAX;
-
-	return 0;
-}
-
-/*	Little bit of magic here: we only get the quality if we poll
- *	for it, and we never get an actual request to trigger such
- *	a poll. Therefore we 'assume' that the user will soon ask for
- *	the stats after asking the bssid.
- */
-static int zd1201_get_wap(struct net_device *dev,
-    struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	unsigned char buffer[6];
-
-	if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) {
-		/* Unfortunately the quality and noise reported is useless.
-		   they seem to be accumulators that increase until you
-		   read them, unless we poll on a fixed interval we can't
-		   use them
-		 */
-		/*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/
-		zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]);
-		/*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/
-		zd->iwstats.qual.updated = 2;
-	}
-
-	return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6);
-}
-
-static int zd1201_set_scan(struct net_device *dev,
-    struct iw_request_info *info, struct iw_point *srq, char *extra)
-{
-	/* We do everything in get_scan */
-	return 0;
-}
-
-static int zd1201_get_scan(struct net_device *dev,
-    struct iw_request_info *info, struct iw_point *srq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	int err, i, j, enabled_save;
-	struct iw_event iwe;
-	char *cev = extra;
-	char *end_buf = extra + IW_SCAN_MAX_DATA;
-
-	/* No scanning in AP mode */
-	if (zd->ap)
-		return -EOPNOTSUPP;
-
-	/* Scan doesn't seem to work if disabled */
-	enabled_save = zd->mac_enabled;
-	zd1201_enable(zd);
-
-	zd->rxdatas = 0;
-	err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, 
-	     ZD1201_INQ_SCANRESULTS, 0, 0);
-	if (err)
-		return err;
-
-	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
-	if (!zd->rxlen)
-		return -EIO;
-
-	if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS)
-		return -EIO;
-
-	for(i=8; i<zd->rxlen; i+=62) {
-		iwe.cmd = SIOCGIWAP;
-		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-		memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6);
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
-
-		iwe.cmd = SIOCGIWESSID;
-		iwe.u.data.length = zd->rxdata[i+16];
-		iwe.u.data.flags = 1;
-		cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18);
-
-		iwe.cmd = SIOCGIWMODE;
-		if (zd->rxdata[i+14]&0x01)
-			iwe.u.mode = IW_MODE_MASTER;
-		else
-			iwe.u.mode = IW_MODE_ADHOC;
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
-		
-		iwe.cmd = SIOCGIWFREQ;
-		iwe.u.freq.m = zd->rxdata[i+0];
-		iwe.u.freq.e = 0;
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
-		
-		iwe.cmd = SIOCGIWRATE;
-		iwe.u.bitrate.fixed = 0;
-		iwe.u.bitrate.disabled = 0;
-		for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) {
-			iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000;
-			cev=iwe_stream_add_event(cev, end_buf, &iwe,
-			    IW_EV_PARAM_LEN);
-		}
-		
-		iwe.cmd = SIOCGIWENCODE;
-		iwe.u.data.length = 0;
-		if (zd->rxdata[i+14]&0x10)
-			iwe.u.data.flags = IW_ENCODE_ENABLED;
-		else
-			iwe.u.data.flags = IW_ENCODE_DISABLED;
-		cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
-		
-		iwe.cmd = IWEVQUAL;
-		iwe.u.qual.qual = zd->rxdata[i+4];
-		iwe.u.qual.noise= zd->rxdata[i+2]/10-100;
-		iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100;
-		iwe.u.qual.updated = 7;
-		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
-	}
-
-	if (!enabled_save)
-		zd1201_disable(zd);
-
-	srq->length = cev - extra;
-	srq->flags = 0;
-
-	return 0;
-}
-
-static int zd1201_set_essid(struct net_device *dev,
-    struct iw_request_info *info, struct iw_point *data, char *essid)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-
-	if (data->length > IW_ESSID_MAX_SIZE)
-		return -EINVAL;
-	if (data->length < 1)
-		data->length = 1;
-	zd->essidlen = data->length-1;
-	memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
-	memcpy(zd->essid, essid, data->length);
-	return zd1201_join(zd, zd->essid, zd->essidlen);
-}
-
-static int zd1201_get_essid(struct net_device *dev,
-    struct iw_request_info *info, struct iw_point *data, char *essid)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-
-	memcpy(essid, zd->essid, zd->essidlen);
-	data->flags = 1;
-	data->length = zd->essidlen;
-
-	return 0;
-}
-
-static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info,
-    struct iw_point *data, char *nick)
-{
-	strcpy(nick, "zd1201");
-	data->flags = 1;
-	data->length = strlen(nick);
-	return 0;
-}
-
-static int zd1201_set_rate(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short rate;
-	int err;
-
-	switch (rrq->value) {
-		case 1000000:
-			rate = ZD1201_RATEB1;
-			break;
-		case 2000000:
-			rate = ZD1201_RATEB2;
-			break;
-		case 5500000:
-			rate = ZD1201_RATEB5;
-			break;
-		case 11000000:
-		default:
-			rate = ZD1201_RATEB11;
-			break;
-	}
-	if (!rrq->fixed) { /* Also enable all lower bitrates */
-		rate |= rate-1;
-	}
-	
-	err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
-	if (err)
-		return err;
-
-	return zd1201_mac_reset(zd);
-}
-
-static int zd1201_get_rate(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short rate;
-	int err;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate);
-	if (err)
-		return err;
-
-	switch(rate) {
-		case 1:
-			rrq->value = 1000000;
-			break;
-		case 2:
-			rrq->value = 2000000;
-			break;
-		case 5:
-			rrq->value = 5500000;
-			break;
-		case 11:
-			rrq->value = 11000000;
-			break;
-		default:
-			rrq->value = 0;
-	}
-	rrq->fixed = 0;
-	rrq->disabled = 0;
-
-	return 0;
-}
-
-static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info,
-    struct iw_param *rts, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	int err;
-	short val = rts->value;
-
-	if (rts->disabled || !rts->fixed)
-		val = ZD1201_RTSMAX;
-	if (val > ZD1201_RTSMAX)
-		return -EINVAL;
-	if (val < 0)
-		return -EINVAL;
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val);
-	if (err)
-		return err;
-	return zd1201_mac_reset(zd);
-}
-
-static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info,
-    struct iw_param *rts, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short rtst;
-	int err;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst);
-	if (err)
-		return err;
-	rts->value = rtst;
-	rts->disabled = (rts->value == ZD1201_RTSMAX);
-	rts->fixed = 1;
-
-	return 0;
-}
-
-static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info,
-    struct iw_param *frag, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	int err;
-	short val = frag->value;
-
-	if (frag->disabled || !frag->fixed)
-		val = ZD1201_FRAGMAX;
-	if (val > ZD1201_FRAGMAX)
-		return -EINVAL;
-	if (val < ZD1201_FRAGMIN)
-		return -EINVAL;
-	if (val & 1)
-		return -EINVAL;
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val);
-	if (err)
-		return err;
-	return zd1201_mac_reset(zd);
-}
-
-static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info,
-    struct iw_param *frag, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short fragt;
-	int err;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt);
-	if (err)
-		return err;
-	frag->value = fragt;
-	frag->disabled = (frag->value == ZD1201_FRAGMAX);
-	frag->fixed = 1;
-
-	return 0;
-}
-
-static int zd1201_set_retry(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	return 0;
-}
-
-static int zd1201_get_retry(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	return 0;
-}
-
-static int zd1201_set_encode(struct net_device *dev,
-    struct iw_request_info *info, struct iw_point *erq, char *key)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short i;
-	int err, rid;
-
-	if (erq->length > ZD1201_MAXKEYLEN)
-		return -EINVAL;
-
-	i = (erq->flags & IW_ENCODE_INDEX)-1;
-	if (i == -1) {
-		err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i);
-		if (err)
-			return err;
-	} else {
-		err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i);
-		if (err)
-			return err;
-	}
-
-	if (i < 0 || i >= ZD1201_NUMKEYS)
-		return -EINVAL;
-
-	rid = ZD1201_RID_CNFDEFAULTKEY0 + i;
-	err = zd1201_setconfig(zd, rid, key, erq->length, 1);
-	if (err)
-		return err;
-	zd->encode_keylen[i] = erq->length;
-	memcpy(zd->encode_keys[i], key, erq->length);
-
-	i=0;
-	if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) {
-		i |= 0x01;
-		zd->encode_enabled = 1;
-	} else
-		zd->encode_enabled = 0;
-	if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) {
-		i |= 0x02;
-		zd->encode_restricted = 1;
-	} else
-		zd->encode_restricted = 0;
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i);
-	if (err)
-		return err;
-
-	if (zd->encode_enabled)
-		i = ZD1201_CNFAUTHENTICATION_SHAREDKEY;
-	else
-		i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i);
-	if (err)
-		return err;
-
-	return zd1201_mac_reset(zd);
-}
-
-static int zd1201_get_encode(struct net_device *dev,
-    struct iw_request_info *info, struct iw_point *erq, char *key)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short i;
-	int err;
-
-	if (zd->encode_enabled)
-		erq->flags = IW_ENCODE_ENABLED;
-	else
-		erq->flags = IW_ENCODE_DISABLED;
-	if (zd->encode_restricted)
-		erq->flags |= IW_ENCODE_RESTRICTED;
-	else
-		erq->flags |= IW_ENCODE_OPEN;
-
-	i = (erq->flags & IW_ENCODE_INDEX) -1;
-	if (i == -1) {
-		err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i);
-		if (err)
-			return err;
-	}
-	if (i<0 || i>= ZD1201_NUMKEYS)
-		return -EINVAL;
-
-	erq->flags |= i+1;
-	
-	erq->length = zd->encode_keylen[i];
-	memcpy(key, zd->encode_keys[i], erq->length);
-
-	return 0;
-}
-
-static int zd1201_set_power(struct net_device *dev, 
-    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short enabled, duration, level;
-	int err;
-
-	enabled = vwrq->disabled ? 0 : 1;
-	if (enabled) {
-		if (vwrq->flags & IW_POWER_PERIOD) {
-			duration = vwrq->value;
-			err = zd1201_setconfig16(zd, 
-			    ZD1201_RID_CNFMAXSLEEPDURATION, duration);
-			if (err)
-				return err;
-			goto out;
-		}
-		if (vwrq->flags & IW_POWER_TIMEOUT) {
-			err = zd1201_getconfig16(zd, 
-			    ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
-			if (err)
-				return err;
-			level = vwrq->value * 4 / duration;
-			if (level > 4)
-				level = 4;
-			if (level < 0)
-				level = 0;
-			err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS,
-			    level);
-			if (err)
-				return err;
-			goto out;
-		}
-		return -EINVAL;
-	}
-out:
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
-	if (err)
-		return err;
-
-	return 0;
-}
-
-static int zd1201_get_power(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short enabled, level, duration;
-	int err;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled);
-	if (err)
-		return err;
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level);
-	if (err)
-		return err;
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
-	if (err)
-		return err;
-	vwrq->disabled = enabled ? 0 : 1;
-	if (vwrq->flags & IW_POWER_TYPE) {
-		if (vwrq->flags & IW_POWER_PERIOD) {
-			vwrq->value = duration;
-			vwrq->flags = IW_POWER_PERIOD;
-		} else {
-			vwrq->value = duration * level / 4;
-			vwrq->flags = IW_POWER_TIMEOUT;
-		}
-	}
-	if (vwrq->flags & IW_POWER_MODE) {
-		if (enabled && level)
-			vwrq->flags = IW_POWER_UNICAST_R;
-		else
-			vwrq->flags = IW_POWER_ALL_R;
-	}
-
-	return 0;
-}
-
-
-static const iw_handler zd1201_iw_handler[] =
-{
-	(iw_handler) zd1201_config_commit,	/* SIOCSIWCOMMIT */
-	(iw_handler) zd1201_get_name,    	/* SIOCGIWNAME */
-	(iw_handler) NULL,			/* SIOCSIWNWID */
-	(iw_handler) NULL,			/* SIOCGIWNWID */
-	(iw_handler) zd1201_set_freq,		/* SIOCSIWFREQ */
-	(iw_handler) zd1201_get_freq,		/* SIOCGIWFREQ */
-	(iw_handler) zd1201_set_mode,		/* SIOCSIWMODE */
-	(iw_handler) zd1201_get_mode,		/* SIOCGIWMODE */
-	(iw_handler) NULL,                  	/* SIOCSIWSENS */
-	(iw_handler) NULL,           		/* SIOCGIWSENS */
-	(iw_handler) NULL,			/* SIOCSIWRANGE */
-	(iw_handler) zd1201_get_range,           /* SIOCGIWRANGE */
-	(iw_handler) NULL,			/* SIOCSIWPRIV */
-	(iw_handler) NULL,			/* SIOCGIWPRIV */
-	(iw_handler) NULL,			/* SIOCSIWSTATS */
-	(iw_handler) NULL,			/* SIOCGIWSTATS */
-	(iw_handler) NULL,			/* SIOCSIWSPY */
-	(iw_handler) NULL,			/* SIOCGIWSPY */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL/*zd1201_set_wap*/,		/* SIOCSIWAP */
-	(iw_handler) zd1201_get_wap,		/* SIOCGIWAP */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL,       		/* SIOCGIWAPLIST */
-	(iw_handler) zd1201_set_scan,		/* SIOCSIWSCAN */
-	(iw_handler) zd1201_get_scan,		/* SIOCGIWSCAN */
-	(iw_handler) zd1201_set_essid,		/* SIOCSIWESSID */
-	(iw_handler) zd1201_get_essid,		/* SIOCGIWESSID */
-	(iw_handler) NULL,         		/* SIOCSIWNICKN */
-	(iw_handler) zd1201_get_nick, 		/* SIOCGIWNICKN */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) NULL,			/* -- hole -- */
-	(iw_handler) zd1201_set_rate,		/* SIOCSIWRATE */
-	(iw_handler) zd1201_get_rate,		/* SIOCGIWRATE */
-	(iw_handler) zd1201_set_rts,		/* SIOCSIWRTS */
-	(iw_handler) zd1201_get_rts,		/* SIOCGIWRTS */
-	(iw_handler) zd1201_set_frag,		/* SIOCSIWFRAG */
-	(iw_handler) zd1201_get_frag,		/* SIOCGIWFRAG */
-	(iw_handler) NULL,         		/* SIOCSIWTXPOW */
-	(iw_handler) NULL,          		/* SIOCGIWTXPOW */
-	(iw_handler) zd1201_set_retry,		/* SIOCSIWRETRY */
-	(iw_handler) zd1201_get_retry,		/* SIOCGIWRETRY */
-	(iw_handler) zd1201_set_encode,		/* SIOCSIWENCODE */
-	(iw_handler) zd1201_get_encode,		/* SIOCGIWENCODE */
-	(iw_handler) zd1201_set_power,		/* SIOCSIWPOWER */
-	(iw_handler) zd1201_get_power,		/* SIOCGIWPOWER */
-};
-
-static int zd1201_set_hostauth(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	int err;
-
-	if (!zd->ap)
-		return -EOPNOTSUPP;
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
-	if (err)
-		return err;
-	return 0;
-}
-
-static int zd1201_get_hostauth(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short hostauth;
-	int err;
-
-	if (!zd->ap)
-		return -EOPNOTSUPP;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth);
-	if (err)
-		return err;
-	rrq->value = hostauth;
-	rrq->fixed = 1;
-
-	return 0;
-}
-
-static int zd1201_auth_sta(struct net_device *dev,
-    struct iw_request_info *info, struct sockaddr *sta, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	unsigned char buffer[10];
-
-	if (!zd->ap)
-		return -EOPNOTSUPP;
-
-	memcpy(buffer, sta->sa_data, ETH_ALEN);
-	*(short*)(buffer+6) = 0;	/* 0==success, 1==failure */
-	*(short*)(buffer+8) = 0;
-
-	return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1);
-}
-
-static int zd1201_set_maxassoc(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	int err;
-
-	if (!zd->ap)
-		return -EOPNOTSUPP;
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value);
-	if (err)
-		return err;
-	return 0;
-}
-
-static int zd1201_get_maxassoc(struct net_device *dev,
-    struct iw_request_info *info, struct iw_param *rrq, char *extra)
-{
-	struct zd1201 *zd = (struct zd1201 *)dev->priv;
-	short maxassoc;
-	int err;
-
-	if (!zd->ap)
-		return -EOPNOTSUPP;
-
-	err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc);
-	if (err)
-		return err;
-	rrq->value = maxassoc;
-	rrq->fixed = 1;
-
-	return 0;
-}
-
-static const iw_handler zd1201_private_handler[] = {
-	(iw_handler) zd1201_set_hostauth,	/* ZD1201SIWHOSTAUTH */
-	(iw_handler) zd1201_get_hostauth,	/* ZD1201GIWHOSTAUTH */
-	(iw_handler) zd1201_auth_sta,		/* ZD1201SIWAUTHSTA */
-	(iw_handler) NULL,			/* nothing to get */
-	(iw_handler) zd1201_set_maxassoc,	/* ZD1201SIMAXASSOC */
-	(iw_handler) zd1201_get_maxassoc,	/* ZD1201GIMAXASSOC */
-};
-
-static const struct iw_priv_args zd1201_private_args[] = {
-	{ ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	    IW_PRIV_TYPE_NONE, "sethostauth" },
-	{ ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE,
-	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" },
-	{ ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1,
-	    IW_PRIV_TYPE_NONE, "authstation" },
-	{ ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-	    IW_PRIV_TYPE_NONE, "setmaxassoc" },
-	{ ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE,
-	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" },
-};
-
-static const struct iw_handler_def zd1201_iw_handlers = {
-	.num_standard 		= ARRAY_SIZE(zd1201_iw_handler),
-	.num_private 		= ARRAY_SIZE(zd1201_private_handler),
-	.num_private_args 	= ARRAY_SIZE(zd1201_private_args),
-	.standard 		= (iw_handler *)zd1201_iw_handler,
-	.private 		= (iw_handler *)zd1201_private_handler,
-	.private_args 		= (struct iw_priv_args *) zd1201_private_args,
-	.get_wireless_stats	= zd1201_get_wireless_stats,
-};
-
-static int zd1201_probe(struct usb_interface *interface,
-			const struct usb_device_id *id)
-{
-	struct zd1201 *zd;
-	struct usb_device *usb;
-	int i, err;
-	short porttype;
-	char buf[IW_ESSID_MAX_SIZE+2];
-
-	usb = interface_to_usbdev(interface);
-
-	zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL);
-	if (!zd)
-		return -ENOMEM;
-	zd->ap = ap;
-	zd->usb = usb;
-	zd->removed = 0;
-	init_waitqueue_head(&zd->rxdataq);
-	INIT_HLIST_HEAD(&zd->fraglist);
-	
-	err = zd1201_fw_upload(usb, zd->ap);
-	if (err) {
-		dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err);
-		goto err_zd;
-	}
-	
-	zd->endp_in = 1;
-	zd->endp_out = 1;
-	zd->endp_out2 = 2;
-	zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!zd->rx_urb || !zd->tx_urb)
-		goto err_zd;
-
-	for(i = 0; i<100; i++)
-		udelay(1000);
-
-	err = zd1201_drvr_start(zd);
-	if (err)
-		goto err_zd;
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312);
-	if (err)
-		goto err_start;
-
-	err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL,
-	    ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11);
-	if (err)
-		goto err_start;
-
-	zd->dev = alloc_etherdev(0);
-	if (!zd->dev)
-		goto err_start;
-
-	zd->dev->priv = zd;
-	zd->dev->open = zd1201_net_open;
-	zd->dev->stop = zd1201_net_stop;
-	zd->dev->get_stats = zd1201_get_stats;
-	zd->dev->wireless_handlers =
-	    (struct iw_handler_def *)&zd1201_iw_handlers;
-	zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
-	zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT;
-	zd->dev->tx_timeout = zd1201_tx_timeout;
-	zd->dev->set_multicast_list = zd1201_set_multicast;
-	zd->dev->set_mac_address = zd1201_set_mac_address;
-	strcpy(zd->dev->name, "wlan%d");
-
-	err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
-	    zd->dev->dev_addr, zd->dev->addr_len);
-	if (err)
-		goto err_net;
-
-	/* Set wildcard essid to match zd->essid */
-	*(__le16 *)buf = cpu_to_le16(0);
-	err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
-	    IW_ESSID_MAX_SIZE+2, 1);
-	if (err)
-		goto err_net;
-
-	if (zd->ap)
-		porttype = ZD1201_PORTTYPE_AP;
-	else
-		porttype = ZD1201_PORTTYPE_BSS;
-	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
-	if (err)
-		goto err_net;
-
-	SET_NETDEV_DEV(zd->dev, &usb->dev);
-
-	err = register_netdev(zd->dev);
-	if (err)
-		goto err_net;
-	dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
-	    zd->dev->name);
-	
-	usb_set_intfdata(interface, zd);
-	return 0;
-
-err_net:
-	free_netdev(zd->dev);
-err_start:
-	/* Leave the device in reset state */
-	zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
-err_zd:
-	if (zd->tx_urb)
-		usb_free_urb(zd->tx_urb);
-	if (zd->rx_urb)
-		usb_free_urb(zd->rx_urb);
-	kfree(zd);
-	return err;
-}
-
-static void zd1201_disconnect(struct usb_interface *interface)
-{
-	struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface);
-	struct hlist_node *node, *node2;
-	struct zd1201_frag *frag;
-
-	if (!zd)
-		return;
-	usb_set_intfdata(interface, NULL);
-	if (zd->dev) {
-		unregister_netdev(zd->dev);
-		free_netdev(zd->dev);
-	}
-
-	hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) {
-		hlist_del_init(&frag->fnode);
-		kfree_skb(frag->skb);
-		kfree(frag);
-	}
-
-	if (zd->tx_urb) {
-		usb_kill_urb(zd->tx_urb);
-		usb_free_urb(zd->tx_urb);
-	}
-	if (zd->rx_urb) {
-		usb_kill_urb(zd->rx_urb);
-		usb_free_urb(zd->rx_urb);
-	}
-	kfree(zd);
-}
-
-#ifdef CONFIG_PM
-
-static int zd1201_suspend(struct usb_interface *interface,
-			   pm_message_t message)
-{
-	struct zd1201 *zd = usb_get_intfdata(interface);
-
-	netif_device_detach(zd->dev);
-
-	zd->was_enabled = zd->mac_enabled;
-
-	if (zd->was_enabled)
-		return zd1201_disable(zd);
-	else
-		return 0;
-}
-
-static int zd1201_resume(struct usb_interface *interface)
-{
-	struct zd1201 *zd = usb_get_intfdata(interface);
-
-	if (!zd || !zd->dev)
-		return -ENODEV;
-
-	netif_device_attach(zd->dev);
-
-	if (zd->was_enabled)
-		return zd1201_enable(zd);
-	else
-		return 0;
-}
-
-#else
-
-#define zd1201_suspend NULL
-#define zd1201_resume  NULL
-
-#endif
-
-static struct usb_driver zd1201_usb = {
-	.name = "zd1201",
-	.probe = zd1201_probe,
-	.disconnect = zd1201_disconnect,
-	.id_table = zd1201_table,
-	.suspend = zd1201_suspend,
-	.resume = zd1201_resume,
-};
-
-static int __init zd1201_init(void)
-{
-	return usb_register(&zd1201_usb);
-}
-
-static void __exit zd1201_cleanup(void)
-{
-	usb_deregister(&zd1201_usb);
-}
-
-module_init(zd1201_init);
-module_exit(zd1201_cleanup);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 5c60be5..8bd44fd 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -417,7 +417,7 @@
 	  Magic Control Technology Corp. (U232 is one of the model numbers).
 
 	  This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB
-	  BAY devices.
+	  BAY, Belkin F5U109, and Belkin F5U409 devices.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called mct_u232.
@@ -491,16 +491,22 @@
 	  module will be called keyspan_pda.
 
 config USB_SERIAL_OPTION
-	tristate "USB Option PCMCIA serial driver"
-	depends on USB_SERIAL && USB_OHCI_HCD && PCCARD
+	tristate "USB driver for GSM modems"
+	depends on USB_SERIAL
 	help
-	  Say Y here if you want to use an Option card. This is a
-	  GSM card, controlled by three serial ports which are connected
-	  via an OHCI adapter located on a PC card.
+	  Say Y here if you have an "Option" GSM PCMCIA card
+	  (or an OEM version: branded Huawei, Audiovox, or Novatel).
+
+	  These cards feature a built-in OHCI-USB adapter and an
+	  internally-connected GSM modem. The USB bus is not
+	  accessible externally.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called option.
 
+	  If this driver doesn't recognize your device,
+	  it might be accessible via the FTDI_SIO driver.
+
 config USB_SERIAL_OMNINET
 	tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
 	depends on USB_SERIAL && EXPERIMENTAL
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c
index 694b205..94b9ba0 100644
--- a/drivers/usb/serial/airprime.c
+++ b/drivers/usb/serial/airprime.c
@@ -16,9 +16,11 @@
 #include "usb-serial.h"
 
 static struct usb_device_id id_table [] = {
+	{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
 	{ USB_DEVICE(0xf3d, 0x0112) },  /* AirPrime CDMA Wireless PC Card */
 	{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
 	{ USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */
+	{ USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
 	{ },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 8023bb7..f3404e1 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -202,7 +202,7 @@
 	struct usb_serial *serial;
 	int retval = -ENODEV;
 
-	if (!port)
+	if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
 		return;
 	serial = port->serial;
 
@@ -213,17 +213,38 @@
 
 	if (!port->open_count) {
 		dbg ("%s - port not opened", __FUNCTION__);
-		goto exit;
+		return;
 	}
 
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->write)
-		retval = serial->type->write(port, buf, count);
-	else
-		retval = usb_serial_generic_write(port, buf, count);
-
-exit:
-	dbg("%s - return value (if we had one): %d", __FUNCTION__, retval);
+	while (count) {
+		unsigned int i;
+		unsigned int lf;
+		/* search for LF so we can insert CR if necessary */
+		for (i=0, lf=0 ; i < count ; i++) {
+			if (*(buf + i) == 10) {
+				lf = 1;
+				i++;
+				break;
+			}
+		}
+		/* pass on to the driver specific version of this function if it is available */
+		if (serial->type->write)
+			retval = serial->type->write(port, buf, i);
+		else
+			retval = usb_serial_generic_write(port, buf, i);
+		dbg("%s - return value : %d", __FUNCTION__, retval);
+		if (lf) {
+			/* append CR after LF */
+			unsigned char cr = 13;
+			if (serial->type->write)
+				retval = serial->type->write(port, &cr, 1);
+			else
+				retval = usb_serial_generic_write(port, &cr, 1);
+			dbg("%s - return value : %d", __FUNCTION__, retval);
+		}
+		buf += i;
+		count -= i;
+	}
 }
 
 static struct console usbcons = {
@@ -234,6 +255,14 @@
 	.index =	-1,
 };
 
+void usb_serial_console_disconnect(struct usb_serial *serial)
+{
+	if (serial && serial->port && serial->port[0] && serial->port[0] == usbcons_info.port) {
+		usb_serial_console_exit();
+		usb_serial_put(serial);
+	}
+}
+
 void usb_serial_console_init (int serial_debug, int minor)
 {
 	debug = serial_debug;
@@ -259,6 +288,11 @@
 
 void usb_serial_console_exit (void)
 {
-	unregister_console(&usbcons);
+	if (usbcons_info.port) {
+		unregister_console(&usbcons);
+		if (usbcons_info.port->open_count)
+			usbcons_info.port->open_count--;
+		usbcons_info.port = NULL;
+	}
 }
 
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index e0c2acd..f8c0cb2 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -59,6 +59,7 @@
 	{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
 	{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
 	{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
+	{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
 	{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
 	{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
 	{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index 2357b1d..1fd5c5a 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -469,7 +469,7 @@
 
 exit:
 	spin_unlock(&priv->lock);
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 static int __init cyberjack_init (void)
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index 7212fbe..5de76ef 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -824,7 +824,7 @@
 	priv->bytes_out += count; /* do not count the line control and size bytes */
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 } /* cypress_send */
 
 
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index 63f7c78..afca1eae 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -335,7 +335,7 @@
 		return;
 	}
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 986d762..b2bfea7 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -500,6 +500,7 @@
 	{ USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) },
 	{ USB_DEVICE(PAPOUCH_VID, PAPOUCH_TMU_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
@@ -1261,7 +1262,6 @@
 
 static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_open */
-	struct termios tmp_termios;
 	struct usb_device *dev = port->serial->dev;
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
 	unsigned long flags;
@@ -1271,8 +1271,8 @@
 
 	dbg("%s", __FUNCTION__);
 
-
-	port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	if (port->tty)
+		port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
 	/* No error checking for this (will get errors later anyway) */
 	/* See ftdi_sio.h for description of what is reset */
@@ -1286,7 +1286,8 @@
 	   This is same behaviour as serial.c/rs_open() - Kuba */
 
 	/* ftdi_set_termios  will send usb control messages */
-	ftdi_set_termios(port, &tmp_termios);
+	if (port->tty)
+		ftdi_set_termios(port, NULL);
 
 	/* FIXME: Flow control might be enabled, so it should be checked -
 	   we have no control of defaults! */
@@ -1472,7 +1473,7 @@
 		return;
 	}
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 } /* ftdi_write_bulk_callback */
 
 
@@ -1867,7 +1868,7 @@
 			err("%s urb failed to set baudrate", __FUNCTION__);
 		}
 		/* Ensure RTS and DTR are raised when baudrate changed from 0 */
-		if ((old_termios->c_cflag & CBAUD) == B0) {
+		if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
 			set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 		}
 	}
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index d69a917..6ab2ac8 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -436,6 +436,12 @@
  */
 #define FTDI_ACG_HFDUAL_PID		0xDD20	/* HF Dual ISO Reader (RFID) */
 
+/*
+ * Yost Engineering, Inc. products (www.yostengineering.com).
+ * PID 0xE050 submitted by Aaron Prose.
+ */
+#define FTDI_YEI_SERVOCENTER31_PID	0xE050	/* YEI ServoCenter3.1 USB */
+
 /* Commands */
 #define FTDI_SIO_RESET 		0 /* Reset the port */
 #define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 5ec9bf5..0476775 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -1012,7 +1012,7 @@
 		garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
 	}
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index c62cc28..07a478c 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -299,9 +299,7 @@
 		return;
 	}
 
-	usb_serial_port_softint((void *)port);
-
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
 
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index b606c59..b85d215 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -142,7 +142,7 @@
 
 /* This structure holds all of the individual device information */
 struct edgeport_serial {
-	char			name[MAX_NAME_LEN+1];		/* string name of this device */
+	char			name[MAX_NAME_LEN+2];		/* string name of this device */
 
 	struct edge_manuf_descriptor	manuf_descriptor;	/* the manufacturer descriptor */
 	struct edge_boot_descriptor	boot_descriptor;	/* the boot firmware descriptor */
@@ -270,7 +270,7 @@
 static void get_boot_desc		(struct edgeport_serial *edge_serial);
 static void load_application_firmware	(struct edgeport_serial *edge_serial);
 
-static void unicode_to_ascii		(char *string, __le16 *unicode, int unicode_size);
+static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size);
 
 
 // ************************************************************************
@@ -373,7 +373,7 @@
  *  Get string descriptor from device					*
  *									*
  ************************************************************************/
-static int get_string (struct usb_device *dev, int Id, char *string)
+static int get_string (struct usb_device *dev, int Id, char *string, int buflen)
 {
 	struct usb_string_descriptor StringDesc;
 	struct usb_string_descriptor *pStringDesc;
@@ -395,7 +395,7 @@
 		return 0;
 	}
 
-	unicode_to_ascii(string,  pStringDesc->wData,     pStringDesc->bLength/2-1);
+	unicode_to_ascii(string, buflen, pStringDesc->wData, pStringDesc->bLength/2);
 
 	kfree(pStringDesc);
 	return strlen(string);
@@ -2564,16 +2564,20 @@
  *	ASCII range, but it's only for debugging...
  *	NOTE: expects the unicode in LE format
  ****************************************************************************/
-static void unicode_to_ascii (char *string, __le16 *unicode, int unicode_size)
+static void unicode_to_ascii(char *string, int buflen, __le16 *unicode, int unicode_size)
 {
 	int i;
 
-	if (unicode_size <= 0)
+	if (buflen <= 0)	/* never happens, but... */
 		return;
+	--buflen;		/* space for nul */
 
-	for (i = 0; i < unicode_size; ++i)
+	for (i = 0; i < unicode_size; i++) {
+		if (i >= buflen)
+			break;
 		string[i] = (char)(le16_to_cpu(unicode[i]));
-	string[unicode_size] = 0x00;
+	}
+	string[i] = 0x00;
 }
 
 
@@ -2603,11 +2607,17 @@
 		dbg("  BoardRev:       %d", edge_serial->manuf_descriptor.BoardRev);
 		dbg("  NumPorts:       %d", edge_serial->manuf_descriptor.NumPorts);
 		dbg("  DescDate:       %d/%d/%d", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900);
-		unicode_to_ascii (string, edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2-1);
+		unicode_to_ascii(string, sizeof(string),
+		    edge_serial->manuf_descriptor.SerialNumber,
+		    edge_serial->manuf_descriptor.SerNumLength/2);
 		dbg("  SerialNumber: %s", string);
-		unicode_to_ascii (string, edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2-1);
+		unicode_to_ascii(string, sizeof(string),
+		    edge_serial->manuf_descriptor.AssemblyNumber,
+		    edge_serial->manuf_descriptor.AssemblyNumLength/2);
 		dbg("  AssemblyNumber: %s", string);
-		unicode_to_ascii (string, edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2-1);
+		unicode_to_ascii(string, sizeof(string),
+		    edge_serial->manuf_descriptor.OemAssyNumber,
+		    edge_serial->manuf_descriptor.OemAssyNumLength/2);
 		dbg("  OemAssyNumber:  %s", string);
 		dbg("  UartType:       %d", edge_serial->manuf_descriptor.UartType);
 		dbg("  IonPid:         %d", edge_serial->manuf_descriptor.IonPid);
@@ -2720,7 +2730,7 @@
 	struct edgeport_serial *edge_serial;
 	struct edgeport_port *edge_port;
 	struct usb_device *dev;
-	int i;
+	int i, j;
 
 	dev = serial->dev;
 
@@ -2735,11 +2745,11 @@
 	usb_set_serial_data(serial, edge_serial);
 
 	/* get the name for the device from the device */
-	if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) {
-		edge_serial->name[i-1] = ' ';
-	}
-
-	get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]);
+	i = get_string(dev, dev->descriptor.iManufacturer,
+	    &edge_serial->name[0], MAX_NAME_LEN+1);
+	edge_serial->name[i++] = ' ';
+	get_string(dev, dev->descriptor.iProduct,
+	    &edge_serial->name[i], MAX_NAME_LEN+2 - i);
 
 	dev_info(&serial->dev->dev, "%s detected\n", edge_serial->name);
 
@@ -2784,6 +2794,10 @@
 		edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
 		if (edge_port == NULL) {
 			dev_err(&serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
+			for (j = 0; j < i; ++j) {
+				kfree (usb_get_serial_port_data(serial->port[j]));
+				usb_set_serial_port_data(serial->port[j],  NULL);
+			}
 			usb_set_serial_data(serial, NULL);
 			kfree(edge_serial);
 			return -ENOMEM;
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index 9a5c9798..9da6d2a 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -870,7 +870,7 @@
 		spin_unlock_irqrestore(&write_list_lock, flags);
 	}
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 static int ipaq_write_room(struct usb_serial_port *port)
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
index e760a70..a4a0bfe 100644
--- a/drivers/usb/serial/ipw.c
+++ b/drivers/usb/serial/ipw.c
@@ -376,7 +376,7 @@
 	if (urb->status)
 		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int count)
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index 426182d..d7f3f73 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -408,7 +408,7 @@
 		urb->actual_length,
 		urb->transfer_buffer);
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
@@ -453,8 +453,7 @@
 			tty = port->tty;
 
 			/*
-			 *	FIXME: must not do this in IRQ context,
-			 *	must honour TTY_DONT_FLIP
+			 *	FIXME: must not do this in IRQ context
 			 */
 			tty->ldisc.receive_buf(
 				tty,
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 052b735..2cf6ade 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -481,7 +481,7 @@
 	dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]); 
 
 	if (port->open_count)
-		schedule_work(&port->work);
+		usb_serial_port_softint(port);
 }
 
 static void	usa26_inack_callback(struct urb *urb, struct pt_regs *regs)
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 78335a5..65d79f6 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -569,8 +569,7 @@
 		return;
 	}
 
-	/* from generic_write_bulk_callback */
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 } /* klsi_105_write_bulk_completion_callback */
 
 
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 238033a..6dcdb5f 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -320,7 +320,7 @@
 		return;
 	}
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5cf2b80..b0861b6 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1,5 +1,5 @@
 /*
-  Option Card (PCMCIA to) USB to Serial Driver
+  USB Driver for GSM modems
 
   Copyright (C) 2005  Matthias Urlichs <smurf@smurf.noris.de>
 
@@ -28,15 +28,34 @@
   2005-09-10  v0.4.3 added HUAWEI E600 card and Audiovox AirCard
   2005-09-20  v0.4.4 increased recv buffer size: the card sometimes
                      wants to send >2000 bytes.
-  2006-04-10  v0.4.2 fixed two array overrun errors :-/
+  2006-04-10  v0.5   fixed two array overrun errors :-/
+  2006-04-21  v0.5.1 added support for Sierra Wireless MC8755
+  2006-05-15  v0.6   re-enable multi-port support
+  2006-06-01  v0.6.1 add COBRA
+  2006-06-01  v0.6.2 add backwards-compatibility stuff
+  2006-06-01  v0.6.3 add Novatel Wireless
+  2006-06-01  v0.7   Option => GSM
 
   Work sponsored by: Sigos GmbH, Germany <info@sigos.de>
 
+  This driver exists because the "normal" serial driver doesn't work too well
+  with GSM modems. Issues:
+  - data loss -- one single Receive URB is not nearly enough
+  - nonstandard flow (Option devices) and multiplex (Sierra) control
+  - controlling the baud rate doesn't make sense
+
+  This driver is named "option" because the most common device it's
+  used for is a PC-Card (with an internal OHCI-USB interface, behind
+  which the GSM interface sits), made by Option Inc.
+
+  Some of the "one port" devices actually exhibit multiple USB instances
+  on the USB bus. This is not a bug, these ports are used for different
+  device features.
 */
 
-#define DRIVER_VERSION "v0.4"
+#define DRIVER_VERSION "v0.7.0"
 #define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
-#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
+#define DRIVER_DESC "USB Driver for GSM modems"
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -74,22 +93,45 @@
 static int  option_send_setup(struct usb_serial_port *port);
 
 /* Vendor and product IDs */
-#define OPTION_VENDOR_ID			0x0AF0
-#define HUAWEI_VENDOR_ID			0x12D1
-#define AUDIOVOX_VENDOR_ID			0x0F3D
+#define OPTION_VENDOR_ID                0x0AF0
+#define HUAWEI_VENDOR_ID                0x12D1
+#define AUDIOVOX_VENDOR_ID              0x0F3D
+#define SIERRAWIRELESS_VENDOR_ID        0x1199
+#define NOVATELWIRELESS_VENDOR_ID       0x1410
 
-#define OPTION_PRODUCT_OLD		0x5000
-#define OPTION_PRODUCT_FUSION	0x6000
-#define OPTION_PRODUCT_FUSION2	0x6300
-#define HUAWEI_PRODUCT_E600     0x1001
-#define AUDIOVOX_PRODUCT_AIRCARD 0x0112
+#define OPTION_PRODUCT_OLD              0x5000
+#define OPTION_PRODUCT_FUSION           0x6000
+#define OPTION_PRODUCT_FUSION2          0x6300
+#define OPTION_PRODUCT_COBRA            0x6500
+#define HUAWEI_PRODUCT_E600             0x1001
+#define AUDIOVOX_PRODUCT_AIRCARD        0x0112
+#define SIERRAWIRELESS_PRODUCT_MC8755   0x6802
+#define NOVATELWIRELESS_PRODUCT_U740    0x1400
 
 static struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
 	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
 	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
+	{ USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
+	{ } /* Terminating entry */
+};
+
+static struct usb_device_id option_ids1[] = {
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_FUSION2) },
+	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COBRA) },
+	{ USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600) },
+	{ USB_DEVICE(AUDIOVOX_VENDOR_ID, AUDIOVOX_PRODUCT_AIRCARD) },
+	{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID,NOVATELWIRELESS_PRODUCT_U740) },
+	{ } /* Terminating entry */
+};
+static struct usb_device_id option_ids3[] = {
+	{ USB_DEVICE(SIERRAWIRELESS_VENDOR_ID, SIERRAWIRELESS_PRODUCT_MC8755) },
 	{ } /* Terminating entry */
 };
 
@@ -111,12 +153,39 @@
 		.owner =	THIS_MODULE,
 		.name =		"option",
 	},
-	.description       = "Option 3G data card",
-	.id_table          = option_ids,
+	.description       = "GSM modem (3-port)",
+	.id_table          = option_ids3,
 	.num_interrupt_in  = NUM_DONT_CARE,
 	.num_bulk_in       = NUM_DONT_CARE,
 	.num_bulk_out      = NUM_DONT_CARE,
-	.num_ports         = 1, /* 3, but the card reports its ports separately */
+	.num_ports         = 3,
+	.open              = option_open,
+	.close             = option_close,
+	.write             = option_write,
+	.write_room        = option_write_room,
+	.chars_in_buffer   = option_chars_in_buffer,
+	.throttle          = option_rx_throttle,
+	.unthrottle        = option_rx_unthrottle,
+	.set_termios       = option_set_termios,
+	.break_ctl         = option_break_ctl,
+	.tiocmget          = option_tiocmget,
+	.tiocmset          = option_tiocmset,
+	.attach            = option_startup,
+	.shutdown          = option_shutdown,
+	.read_int_callback = option_instat_callback,
+};
+
+static struct usb_serial_driver option_1port_device = {
+	.driver = {
+		.owner =	THIS_MODULE,
+		.name =		"option",
+	},
+	.description       = "GSM modem (1-port)",
+	.id_table          = option_ids1,
+	.num_interrupt_in  = NUM_DONT_CARE,
+	.num_bulk_in       = NUM_DONT_CARE,
+	.num_bulk_out      = NUM_DONT_CARE,
+	.num_ports         = 1,
 	.open              = option_open,
 	.close             = option_close,
 	.write             = option_write,
@@ -170,6 +239,9 @@
 static int __init option_init(void)
 {
 	int retval;
+	retval = usb_serial_register(&option_1port_device);
+	if (retval)
+		goto failed_1port_device_register;
 	retval = usb_serial_register(&option_3port_device);
 	if (retval)
 		goto failed_3port_device_register;
@@ -184,6 +256,8 @@
 failed_driver_register:
 	usb_serial_deregister (&option_3port_device);
 failed_3port_device_register:
+	usb_serial_deregister (&option_1port_device);
+failed_1port_device_register:
 	return retval;
 }
 
@@ -191,6 +265,7 @@
 {
 	usb_deregister (&option_driver);
 	usb_serial_deregister (&option_3port_device);
+	usb_serial_deregister (&option_1port_device);
 }
 
 module_init(option_init);
@@ -365,8 +440,7 @@
 
 	port = (struct usb_serial_port *) urb->context;
 
-	if (port->open_count)
-		schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 static void option_instat_callback(struct urb *urb, struct pt_regs *regs)
@@ -573,27 +647,30 @@
 /* Setup urbs */
 static void option_setup_urbs(struct usb_serial *serial)
 {
-	int j;
+	int i,j;
 	struct usb_serial_port *port;
 	struct option_port_private *portdata;
 
 	dbg("%s", __FUNCTION__);
 
-	port = serial->port[0];
-	portdata = usb_get_serial_port_data(port);
+
+	for (i = 0; i < serial->num_ports; i++) {
+		port = serial->port[i];
+		portdata = usb_get_serial_port_data(port);
 
 	/* Do indat endpoints first */
-	for (j = 0; j < N_IN_URB; ++j) {
-		portdata->in_urbs[j] = option_setup_urb (serial,
-                  port->bulk_in_endpointAddress, USB_DIR_IN, port,
-                  portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
-	}
+		for (j = 0; j < N_IN_URB; ++j) {
+			portdata->in_urbs[j] = option_setup_urb (serial,
+                  	port->bulk_in_endpointAddress, USB_DIR_IN, port,
+                  	portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
+		}
 
-	/* outdat endpoints */
-	for (j = 0; j < N_OUT_URB; ++j) {
-		portdata->out_urbs[j] = option_setup_urb (serial,
-                  port->bulk_out_endpointAddress, USB_DIR_OUT, port,
-                  portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
+		/* outdat endpoints */
+		for (j = 0; j < N_OUT_URB; ++j) {
+			portdata->out_urbs[j] = option_setup_urb (serial,
+                  	port->bulk_out_endpointAddress, USB_DIR_OUT, port,
+                  	portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
+		}
 	}
 }
 
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index c96714b..d887043 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -314,7 +314,7 @@
 		// TODO: reschedule pl2303_send
 	}
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 static int pl2303_write_room(struct usb_serial_port *port)
@@ -600,7 +600,7 @@
 	unsigned int c_cflag;
 	int bps;
 	long timeout;
-	wait_queue_t wait;						\
+	wait_queue_t wait;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 9c36f0e..a30135c 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -162,12 +162,19 @@
 		}
 	}
 
+	flush_scheduled_work();		/* port->work */
+
 	usb_put_dev(serial->dev);
 
 	/* free up any memory that we allocated */
 	kfree (serial);
 }
 
+void usb_serial_put(struct usb_serial *serial)
+{
+	kref_put(&serial->kref, destroy_serial);
+}
+
 /*****************************************************************************
  * Driver tty interface functions
  *****************************************************************************/
@@ -201,12 +208,12 @@
 	 
 	++port->open_count;
 
-	if (port->open_count == 1) {
+	/* set up our port structure making the tty driver
+	 * remember our port object, and us it */
+	tty->driver_data = port;
+	port->tty = tty;
 
-		/* set up our port structure making the tty driver
-		 * remember our port object, and us it */
-		tty->driver_data = port;
-		port->tty = tty;
+	if (port->open_count == 1) {
 
 		/* lock this module before we call it
 		 * this may fail, which means we must bail out,
@@ -230,9 +237,11 @@
 	module_put(serial->type->driver.owner);
 bailout_mutex_unlock:
 	port->open_count = 0;
+	tty->driver_data = NULL;
+	port->tty = NULL;
 	mutex_unlock(&port->mutex);
 bailout_kref_put:
-	kref_put(&serial->kref, destroy_serial);
+	usb_serial_put(serial);
 	return retval;
 }
 
@@ -268,7 +277,7 @@
 	}
 
 	mutex_unlock(&port->mutex);
-	kref_put(&port->serial->kref, destroy_serial);
+	usb_serial_put(port->serial);
 }
 
 static int serial_write (struct tty_struct * tty, const unsigned char *buf, int count)
@@ -276,7 +285,7 @@
 	struct usb_serial_port *port = tty->driver_data;
 	int retval = -EINVAL;
 
-	if (!port)
+	if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
 		goto exit;
 
 	dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
@@ -296,7 +305,7 @@
 static int serial_write_room (struct tty_struct *tty) 
 {
 	struct usb_serial_port *port = tty->driver_data;
-	int retval = -EINVAL;
+	int retval = -ENODEV;
 
 	if (!port)
 		goto exit;
@@ -318,7 +327,7 @@
 static int serial_chars_in_buffer (struct tty_struct *tty) 
 {
 	struct usb_serial_port *port = tty->driver_data;
-	int retval = -EINVAL;
+	int retval = -ENODEV;
 
 	if (!port)
 		goto exit;
@@ -473,7 +482,7 @@
 			begin += length;
 			length = 0;
 		}
-		kref_put(&serial->kref, destroy_serial);
+		usb_serial_put(serial);
 	}
 	*eof = 1;
 done:
@@ -488,19 +497,18 @@
 	struct usb_serial_port *port = tty->driver_data;
 
 	if (!port)
-		goto exit;
+		return -ENODEV;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
 		dbg("%s - port not open", __FUNCTION__);
-		goto exit;
+		return -ENODEV;
 	}
 
 	if (port->serial->type->tiocmget)
 		return port->serial->type->tiocmget(port, file);
 
-exit:
 	return -EINVAL;
 }
 
@@ -510,23 +518,32 @@
 	struct usb_serial_port *port = tty->driver_data;
 
 	if (!port)
-		goto exit;
+		return -ENODEV;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	if (!port->open_count) {
 		dbg("%s - port not open", __FUNCTION__);
-		goto exit;
+		return -ENODEV;
 	}
 
 	if (port->serial->type->tiocmset)
 		return port->serial->type->tiocmset(port, file, set, clear);
 
-exit:
 	return -EINVAL;
 }
 
-void usb_serial_port_softint(void *private)
+/*
+ * We would be calling tty_wakeup here, but unfortunately some line
+ * disciplines have an annoying habit of calling tty->write from
+ * the write wakeup callback (e.g. n_hdlc.c).
+ */
+void usb_serial_port_softint(struct usb_serial_port *port)
+{
+	schedule_work(&port->work);
+}
+
+static void usb_serial_port_work(void *private)
 {
 	struct usb_serial_port *port = private;
 	struct tty_struct *tty;
@@ -789,7 +806,7 @@
 		port->serial = serial;
 		spin_lock_init(&port->lock);
 		mutex_init(&port->mutex);
-		INIT_WORK(&port->work, usb_serial_port_softint, port);
+		INIT_WORK(&port->work, usb_serial_port_work, port);
 		serial->port[i] = port;
 	}
 
@@ -985,6 +1002,7 @@
 	struct device *dev = &interface->dev;
 	struct usb_serial_port *port;
 
+	usb_serial_console_disconnect(serial);
 	dbg ("%s", __FUNCTION__);
 
 	usb_set_intfdata (interface, NULL);
@@ -996,7 +1014,7 @@
 		}
 		/* let the last holder of this object 
 		 * cause it to be cleaned up */
-		kref_put(&serial->kref, destroy_serial);
+		usb_serial_put(serial);
 	}
 	dev_info(dev, "device disconnected\n");
 }
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index dc89d87..d53ea9b 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -236,7 +236,7 @@
 
 extern int  usb_serial_register(struct usb_serial_driver *driver);
 extern void usb_serial_deregister(struct usb_serial_driver *driver);
-extern void usb_serial_port_softint(void *private);
+extern void usb_serial_port_softint(struct usb_serial_port *port);
 
 extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id);
 extern void usb_serial_disconnect(struct usb_interface *iface);
@@ -248,13 +248,16 @@
 #ifdef CONFIG_USB_SERIAL_CONSOLE
 extern void usb_serial_console_init (int debug, int minor);
 extern void usb_serial_console_exit (void);
+extern void usb_serial_console_disconnect(struct usb_serial *serial);
 #else
 static inline void usb_serial_console_init (int debug, int minor) { }
 static inline void usb_serial_console_exit (void) { }
+static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
 #endif
 
 /* Functions needed by other parts of the usbserial core */
 extern struct usb_serial *usb_serial_get_by_index (unsigned int minor);
+extern void usb_serial_put(struct usb_serial *serial);
 extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count);
 extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp);
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index f5c3841..9e89b8d 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -480,7 +480,7 @@
 	--priv->outstanding_urbs;
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index f806553..56ffc81 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -388,7 +388,7 @@
 	if (ret) {
 		err("%s: Couldn't send command [%d]", serial->type->description, ret);
 		goto no_firmware;
-	} else if (alen != sizeof(command)) {
+	} else if (alen != 2) {
 		err("%s: Send command incomplete [%d]", serial->type->description, alen);
 		goto no_firmware;
 	}
@@ -400,7 +400,7 @@
 	if (ret) {
 		err("%s: Couldn't get results [%d]", serial->type->description, ret);
 		goto no_firmware;
-	} else if (alen != sizeof(result)) {
+	} else if (alen != sizeof(*hw_info) + 1) {
 		err("%s: Get results incomplete [%d]", serial->type->description, alen);
 		goto no_firmware;
 	} else if (result[0] != command[0]) {
@@ -686,19 +686,16 @@
 		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 		urb = wrap->urb;
 		usb_kill_urb(urb);
-		list_del(tmp);
-		list_add(tmp, &info->rx_urbs_free);
+		list_move(tmp, &info->rx_urbs_free);
 	}
-	list_for_each_safe(tmp, tmp2, &info->rx_urb_q) {
-		list_del(tmp);
-		list_add(tmp, &info->rx_urbs_free);
-	}
+	list_for_each_safe(tmp, tmp2, &info->rx_urb_q)
+		list_move(tmp, &info->rx_urbs_free);
+
 	list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) {
 		wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 		urb = wrap->urb;
 		usb_kill_urb(urb);
-		list_del(tmp);
-		list_add(tmp, &info->tx_urbs_free);
+		list_move(tmp, &info->tx_urbs_free);
 	}
 	spin_unlock_irqrestore(&info->lock, flags);
 
@@ -1080,8 +1077,7 @@
 		err("%s - Not my urb!", __FUNCTION__);
 		return;
 	}
-	list_del(&wrap->list);
-	list_add(&wrap->list, &info->tx_urbs_free);
+	list_move(&wrap->list, &info->tx_urbs_free);
 	spin_unlock(&info->lock);
 
 	if (urb->status) {
@@ -1089,9 +1085,7 @@
 		return;
 	}
 
-	usb_serial_port_softint((void *)port);
-
-	schedule_work(&port->work);
+	usb_serial_port_softint(port);
 }
 
 
@@ -1373,8 +1367,7 @@
 				wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
 				urb = wrap->urb;
 				usb_kill_urb(urb);
-				list_del(tmp);
-				list_add(tmp, &info->rx_urbs_free);
+				list_move(tmp, &info->rx_urbs_free);
 			}
 			break;
 		}
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 55ee2d3..026a587 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -34,9 +34,8 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/usb.h>
 #include <linux/usb_ch9.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 #include "usb.h"
 #include "onetouch.h"
 #include "debug.h"
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 5f11e19..5715291 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -286,11 +286,7 @@
 	int result;
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
-
-	mutex_lock(&(us->dev_mutex));
 	result = usb_stor_port_reset(us);
-	mutex_unlock(&us->dev_mutex);
-
 	return result < 0 ? FAILED : SUCCESS;
 }
 
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index f2bc5c9..8fcec01 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -131,28 +131,30 @@
  * Convenience function to perform a bulk read
  */
 static int usbat_bulk_read(struct us_data *us,
-							 unsigned char *data,
-							 unsigned int len)
+			   unsigned char *data,
+			   unsigned int len,
+			   int use_sg)
 {
 	if (len == 0)
 		return USB_STOR_XFER_GOOD;
 
 	US_DEBUGP("usbat_bulk_read: len = %d\n", len);
-	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL);
+	return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, data, len, use_sg, NULL);
 }
 
 /*
  * Convenience function to perform a bulk write
  */
 static int usbat_bulk_write(struct us_data *us,
-							unsigned char *data,
-							unsigned int len)
+			    unsigned char *data,
+			    unsigned int len,
+			    int use_sg)
 {
 	if (len == 0)
 		return USB_STOR_XFER_GOOD;
 
 	US_DEBUGP("usbat_bulk_write:  len = %d\n", len);
-	return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL);
+	return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, data, len, use_sg, NULL);
 }
 
 /*
@@ -317,7 +319,8 @@
  */
 static int usbat_read_block(struct us_data *us,
 			    unsigned char *content,
-			    unsigned short len)
+			    unsigned short len,
+			    int use_sg)
 {
 	int result;
 	unsigned char *command = us->iobuf;
@@ -338,7 +341,7 @@
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	result = usbat_bulk_read(us, content, len);
+	result = usbat_bulk_read(us, content, len, use_sg);
 	return (result == USB_STOR_XFER_GOOD ?
 			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
 }
@@ -350,7 +353,8 @@
 			     unsigned char access,
 			     unsigned char *content,
 			     unsigned short len,
-			     int minutes)
+			     int minutes,
+			     int use_sg)
 {
 	int result;
 	unsigned char *command = us->iobuf;
@@ -372,7 +376,7 @@
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	result = usbat_bulk_write(us, content, len);
+	result = usbat_bulk_write(us, content, len, use_sg);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -465,7 +469,7 @@
 				data[1+(j<<1)] = data_out[j];
 			}
 
-			result = usbat_bulk_write(us, data, num_registers*2);
+			result = usbat_bulk_write(us, data, num_registers*2, 0);
 			if (result != USB_STOR_XFER_GOOD)
 				return USB_STOR_TRANSPORT_ERROR;
 
@@ -583,7 +587,7 @@
 	}
 
 	/* Send the data */
-	result = usbat_bulk_write(us, data, num_registers*2);
+	result = usbat_bulk_write(us, data, num_registers*2, 0);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
@@ -606,8 +610,9 @@
  * other related details) are defined beforehand with _set_shuttle_features().
  */
 static int usbat_read_blocks(struct us_data *us,
-							 unsigned char *buffer,
-							 int len)
+			     unsigned char *buffer,
+			     int len,
+			     int use_sg)
 {
 	int result;
 	unsigned char *command = us->iobuf;
@@ -627,7 +632,7 @@
 		return USB_STOR_TRANSPORT_FAILED;
 	
 	/* Read the blocks we just asked for */
-	result = usbat_bulk_read(us, buffer, len);
+	result = usbat_bulk_read(us, buffer, len, use_sg);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_FAILED;
 
@@ -648,7 +653,8 @@
  */
 static int usbat_write_blocks(struct us_data *us,
 							  unsigned char *buffer,
-							  int len)
+			      int len,
+			      int use_sg)
 {
 	int result;
 	unsigned char *command = us->iobuf;
@@ -668,7 +674,7 @@
 		return USB_STOR_TRANSPORT_FAILED;
 	
 	/* Write the data */
-	result = usbat_bulk_write(us, buffer, len);
+	result = usbat_bulk_write(us, buffer, len, use_sg);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_FAILED;
 
@@ -887,22 +893,28 @@
  * Set the transport function based on the device type
  */
 static int usbat_set_transport(struct us_data *us,
-			       struct usbat_info *info)
+			       struct usbat_info *info,
+			       int devicetype)
 {
-	int rc;
 
-	if (!info->devicetype) {
-		rc = usbat_identify_device(us, info);
-		if (rc != USB_STOR_TRANSPORT_GOOD) {
-			US_DEBUGP("usbat_set_transport: Could not identify device\n");
-			return 1;
-		}
-	}
+	if (!info->devicetype)
+		info->devicetype = devicetype;
 
-	if (usbat_get_device_type(us) == USBAT_DEV_HP8200)
+	if (!info->devicetype)
+		usbat_identify_device(us, info);
+
+	switch (info->devicetype) {
+	default:
+		return USB_STOR_TRANSPORT_ERROR;
+
+	case  USBAT_DEV_HP8200:
 		us->transport = usbat_hp8200e_transport;
-	else if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
+		break;
+
+	case USBAT_DEV_FLASH:
 		us->transport = usbat_flash_transport;
+		break;
+	}
 
 	return 0;
 }
@@ -947,7 +959,7 @@
 	msleep(100);
 
 	/* Read the device identification data */
-	rc = usbat_read_block(us, reply, 512);
+	rc = usbat_read_block(us, reply, 512, 0);
 	if (rc != USB_STOR_TRANSPORT_GOOD)
 		goto leave;
 
@@ -1031,7 +1043,7 @@
 			goto leave;
 
 		/* Read the data we just requested */
-		result = usbat_read_blocks(us, buffer, len);
+		result = usbat_read_blocks(us, buffer, len, 0);
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			goto leave;
   	 
@@ -1125,7 +1137,7 @@
 			goto leave;
 
 		/* Write the data */
-		result = usbat_write_blocks(us, buffer, len);
+		result = usbat_write_blocks(us, buffer, len, 0);
 		if (result != USB_STOR_TRANSPORT_GOOD)
 			goto leave;
 
@@ -1310,7 +1322,7 @@
 /*
  * Initialize the USBAT processor and the storage device
  */
-int init_usbat(struct us_data *us)
+static int init_usbat(struct us_data *us, int devicetype)
 {
 	int rc;
 	struct usbat_info *info;
@@ -1392,7 +1404,7 @@
 	US_DEBUGP("INIT 9\n");
 
 	/* At this point, we need to detect which device we are using */
-	if (usbat_set_transport(us, info))
+	if (usbat_set_transport(us, info, devicetype))
 		return USB_STOR_TRANSPORT_ERROR;
 
 	US_DEBUGP("INIT 10\n");
@@ -1503,10 +1515,10 @@
 	 * AT SPEED 4 IS UNRELIABLE!!!
 	 */
 
-	if ( (result = usbat_write_block(us, 
+	if ((result = usbat_write_block(us,
 			USBAT_ATA, srb->cmnd, 12,
-			srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
-				USB_STOR_TRANSPORT_GOOD) {
+				(srb->cmnd[0]==GPCMD_BLANK ? 75 : 10), 0) !=
+			     USB_STOR_TRANSPORT_GOOD)) {
 		return result;
 	}
 
@@ -1533,7 +1545,7 @@
 			len = *status;
 
 
-		result = usbat_read_block(us, srb->request_buffer, len);
+		result = usbat_read_block(us, srb->request_buffer, len, srb->use_sg);
 
 		/* Debug-print the first 32 bytes of the transfer */
 
@@ -1695,6 +1707,22 @@
 	return USB_STOR_TRANSPORT_FAILED;
 }
 
+int init_usbat_cd(struct us_data *us)
+{
+	return init_usbat(us, USBAT_DEV_HP8200);
+}
+
+
+int init_usbat_flash(struct us_data *us)
+{
+	return init_usbat(us, USBAT_DEV_FLASH);
+}
+
+int init_usbat_probe(struct us_data *us)
+{
+	return init_usbat(us, 0);
+}
+
 /*
  * Default transport function. Attempts to detect which transport function
  * should be called, makes it the new default, and calls it.
@@ -1708,9 +1736,8 @@
 {
 	struct usbat_info *info = (struct usbat_info*) (us->extra);
 
-	if (usbat_set_transport(us, info))
+	if (usbat_set_transport(us, info, 0))
 		return USB_STOR_TRANSPORT_ERROR;
 
 	return us->transport(srb, us);	
 }
-
diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
index 25e7d8b..3ddf143 100644
--- a/drivers/usb/storage/shuttle_usbat.h
+++ b/drivers/usb/storage/shuttle_usbat.h
@@ -106,7 +106,9 @@
 #define USBAT_FEAT_ET2	0x01
 
 extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int init_usbat(struct us_data *us);
+extern int init_usbat_cd(struct us_data *us);
+extern int init_usbat_flash(struct us_data *us);
+extern int init_usbat_probe(struct us_data *us);
 
 struct usbat_info {
 	int devicetype;
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 7ca896a..19b25c5 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -115,19 +115,6 @@
 
 	complete(urb_done_ptr);
 }
- 
-/* This is the timeout handler which will cancel an URB when its timeout
- * expires.
- */
-static void timeout_handler(unsigned long us_)
-{
-	struct us_data *us = (struct us_data *) us_;
-
-	if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
-		US_DEBUGP("Timeout -- cancelling URB\n");
-		usb_unlink_urb(us->current_urb);
-	}
-}
 
 /* This is the common part of the URB message submission code
  *
@@ -138,7 +125,7 @@
 static int usb_stor_msg_common(struct us_data *us, int timeout)
 {
 	struct completion urb_done;
-	struct timer_list to_timer;
+	long timeleft;
 	int status;
 
 	/* don't submit URBs during abort/disconnect processing */
@@ -185,22 +172,17 @@
 		}
 	}
  
-	/* submit the timeout timer, if a timeout was requested */
-	if (timeout > 0) {
-		init_timer(&to_timer);
-		to_timer.expires = jiffies + timeout;
-		to_timer.function = timeout_handler;
-		to_timer.data = (unsigned long) us;
-		add_timer(&to_timer);
-	}
-
 	/* wait for the completion of the URB */
-	wait_for_completion(&urb_done);
-	clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);
+	timeleft = wait_for_completion_interruptible_timeout(
+			&urb_done, timeout ? : MAX_SCHEDULE_TIMEOUT);
  
-	/* clean up the timeout timer */
-	if (timeout > 0)
-		del_timer_sync(&to_timer);
+	clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);
+
+	if (timeleft <= 0) {
+		US_DEBUGP("%s -- cancelling URB\n",
+			  timeleft == 0 ? "Timeout" : "Signal");
+		usb_unlink_urb(us->current_urb);
+	}
 
 	/* return the URB status */
 	return us->current_urb->status;
@@ -721,16 +703,19 @@
 	 * device reset. */
   Handle_Errors:
 
-	/* Let the SCSI layer know we are doing a reset, set the
-	 * RESETTING bit, and clear the ABORTING bit so that the reset
-	 * may proceed. */
+	/* Set the RESETTING bit, and clear the ABORTING bit so that
+	 * the reset may proceed. */
 	scsi_lock(us_to_host(us));
-	usb_stor_report_bus_reset(us);
 	set_bit(US_FLIDX_RESETTING, &us->flags);
 	clear_bit(US_FLIDX_ABORTING, &us->flags);
 	scsi_unlock(us_to_host(us));
 
+	/* We must release the device lock because the pre_reset routine
+	 * will want to acquire it. */
+	mutex_unlock(&us->dev_mutex);
 	result = usb_stor_port_reset(us);
+	mutex_lock(&us->dev_mutex);
+
 	if (result < 0) {
 		scsi_lock(us_to_host(us));
 		usb_stor_report_device_reset(us);
@@ -1214,31 +1199,30 @@
 				 0, us->ifnum, NULL, 0);
 }
 
-/* Issue a USB port reset to the device.  But don't do anything if
- * there's more than one interface in the device, so that other users
- * are not affected. */
+/* Issue a USB port reset to the device.  The caller must not hold
+ * us->dev_mutex.
+ */
 int usb_stor_port_reset(struct us_data *us)
 {
-	int result, rc;
+	int result, rc_lock;
 
-	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
-		result = -EIO;
-		US_DEBUGP("No reset during disconnect\n");
-	} else if (us->pusb_dev->actconfig->desc.bNumInterfaces != 1) {
-		result = -EBUSY;
-		US_DEBUGP("Refusing to reset a multi-interface device\n");
-	} else {
-		result = rc =
-			usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
-		if (result < 0) {
-			US_DEBUGP("unable to lock device for reset: %d\n",
-					result);
+	result = rc_lock =
+		usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
+	if (result < 0)
+		US_DEBUGP("unable to lock device for reset: %d\n", result);
+	else {
+		/* Were we disconnected while waiting for the lock? */
+		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
+			result = -EIO;
+			US_DEBUGP("No reset during disconnect\n");
 		} else {
-			result = usb_reset_device(us->pusb_dev);
-			if (rc)
-				usb_unlock_device(us->pusb_dev);
-			US_DEBUGP("usb_reset_device returns %d\n", result);
+			result = usb_reset_composite_device(
+					us->pusb_dev, us->pusb_intf);
+			US_DEBUGP("usb_reset_composite_device returns %d\n",
+					result);
 		}
+		if (rc_lock)
+			usb_unlock_device(us->pusb_dev);
 	}
 	return result;
 }
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index aec5ea8..543244d 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -78,12 +78,12 @@
 UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
 		"HP",
 		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_USBAT, init_usbat, 0),
+		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
 
 UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001, 
 		"HP",
 		"CD-Writer+ CD-4e",
-		US_SC_8070, US_PR_USBAT, init_usbat, 0),
+		US_SC_8070, US_PR_USBAT, init_usbat_cd, 0),
 #endif
 
 /* Reported by Sebastian Kapfer <sebastian_kapfer@gmx.net>
@@ -133,6 +133,14 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Jiri Slaby <jirislaby@gmail.com> and
+ * Rene C. Castberg <Rene@Castberg.org> */
+UNUSUAL_DEV(  0x0421, 0x0446, 0x0100, 0x0100,
+		"Nokia",
+		"N80",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ),
+
 /* Reported by Olaf Hering <olh@suse.de> from novell bug #105878 */
 UNUSUAL_DEV(  0x0424, 0x0fdc, 0x0210, 0x0210,
 		"SMSC",
@@ -216,13 +224,6 @@
 		"DVD-CAM DZ-MV100A Camcorder",
 		US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
 
-/* Reported by Andreas Bockhold <andreas@bockionline.de> */
-UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
-		"NIKON",
-		"NIKON DSC D70",
-		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY),
-
 /* Patch for Nikon coolpix 2000
  * Submitted by Fabien Cosse <fabien.cosse@wanadoo.fr>*/
 UNUSUAL_DEV(  0x04b0, 0x0301, 0x0010, 0x0010,
@@ -231,6 +232,20 @@
 		US_SC_DEVICE, US_PR_DEVICE,NULL,
 		US_FL_NOT_LOCKABLE ),
 
+/* Reported by Andreas Bockhold <andreas@bockionline.de> */
+UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
+		"NIKON",
+		"NIKON DSC D70",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY),
+
+/* Reported by Jamie Kitson <jamie@staberinde.fsnet.co.uk> */
+UNUSUAL_DEV(  0x04b0, 0x040d, 0x0100, 0x0100,
+		"NIKON",
+		"NIKON DSC D70s",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY),
+
 /* BENQ DC5330
  * Reported by Manuel Fombuena <mfombuena@ya.com> and
  * Frank Copeland <fjc@thingy.apana.org.au> */
@@ -393,7 +408,7 @@
 UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
 		"Shuttle/SCM",
 		"USBAT-02",
-		US_SC_SCSI, US_PR_USBAT, init_usbat,
+		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
 		US_FL_SINGLE_LUN),
 #endif
 
@@ -797,7 +812,7 @@
 UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
 		"Sandisk",
 		"ImageMate SDDR-05b",
-		US_SC_SCSI, US_PR_USBAT, init_usbat,
+		US_SC_SCSI, US_PR_USBAT, init_usbat_flash,
 		US_FL_SINGLE_LUN ),
 #endif
 
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index dd108634..e232c7c 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -221,6 +221,37 @@
 #endif /* CONFIG_PM */
 
 /*
+ * The next two routines get called just before and just after
+ * a USB port reset, whether from this driver or a different one.
+ */
+
+static void storage_pre_reset(struct usb_interface *iface)
+{
+	struct us_data *us = usb_get_intfdata(iface);
+
+	US_DEBUGP("%s\n", __FUNCTION__);
+
+	/* Make sure no command runs during the reset */
+	mutex_lock(&us->dev_mutex);
+}
+
+static void storage_post_reset(struct usb_interface *iface)
+{
+	struct us_data *us = usb_get_intfdata(iface);
+
+	US_DEBUGP("%s\n", __FUNCTION__);
+
+	/* Report the reset to the SCSI core */
+	scsi_lock(us_to_host(us));
+	usb_stor_report_bus_reset(us);
+	scsi_unlock(us_to_host(us));
+
+	/* FIXME: Notify the subdrivers that they need to reinitialize
+	 * the device */
+	mutex_unlock(&us->dev_mutex);
+}
+
+/*
  * fill_inquiry_response takes an unsigned char array (which must
  * be at least 36 characters) and populates the vendor name,
  * product name, and revision fields. Then the array is copied
@@ -593,6 +624,15 @@
 		break;
 #endif
 
+#ifdef CONFIG_USB_STORAGE_ALAUDA
+	case US_PR_ALAUDA:
+		us->transport_name  = "Alauda Control/Bulk";
+		us->transport = alauda_transport;
+		us->transport_reset = usb_stor_Bulk_reset;
+		us->max_lun = 1;
+		break;
+#endif
+
 	default:
 		return -EIO;
 	}
@@ -648,15 +688,6 @@
 		break;
 #endif
 
-#ifdef CONFIG_USB_STORAGE_ALAUDA
-	case US_PR_ALAUDA:
-		us->transport_name  = "Alauda Control/Bulk";
-		us->transport = alauda_transport;
-		us->transport_reset = usb_stor_Bulk_reset;
-		us->max_lun = 1;
-		break;
-#endif
-
 	default:
 		return -EIO;
 	}
@@ -1002,6 +1033,8 @@
 	.suspend =	storage_suspend,
 	.resume =	storage_resume,
 #endif
+	.pre_reset =	storage_pre_reset,
+	.post_reset =	storage_post_reset,
 	.id_table =	storage_usb_ids,
 };
 
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 009fb095..5284abe 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -160,10 +160,10 @@
 };
 
 /* Convert between us_data and the corresponding Scsi_Host */
-static struct Scsi_Host inline *us_to_host(struct us_data *us) {
+static inline struct Scsi_Host *us_to_host(struct us_data *us) {
 	return container_of((void *) us, struct Scsi_Host, hostdata);
 }
-static struct us_data inline *host_to_us(struct Scsi_Host *host) {
+static inline struct us_data *host_to_us(struct Scsi_Host *host) {
 	return (struct us_data *) host->hostdata;
 }
 
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4587087..17de4c84 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -4,6 +4,21 @@
 
 menu "Graphics support"
 
+config FIRMWARE_EDID
+       bool "Enable firmware EDID"
+       default y
+       ---help---
+         This enables access to the EDID transferred from the firmware.
+	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
+	 transfers do not work for your driver and if you are using
+	 nvidiafb, i810fb or savagefb.
+
+	 In general, choosing Y for this option is safe.  If you
+	 experience extremely long delays while booting before you get
+	 something on your display, try setting this to N.  Matrox cards in
+	 combination with certain motherboards and monitors are known to
+	 suffer from this problem.
+
 config FB
 	tristate "Support for frame buffer devices"
 	---help---
@@ -70,21 +85,10 @@
        depends on FB
        default n
 
-config FB_FIRMWARE_EDID
-       bool "Enable firmware EDID"
+config FB_BACKLIGHT
+       bool
        depends on FB
-       default y
-       ---help---
-         This enables access to the EDID transferred from the firmware.
-	 On the i386, this is from the Video BIOS. Enable this if DDC/I2C
-	 transfers do not work for your driver and if you are using
-	 nvidiafb, i810fb or savagefb.
-
-	 In general, choosing Y for this option is safe.  If you
-	 experience extremely long delays while booting before you get
-	 something on your display, try setting this to N.  Matrox cards in
-	 combination with certain motherboards and monitors are known to
-	 suffer from this problem.
+       default n
 
 config FB_MODE_HELPERS
         bool "Enable Video Mode Handling Helpers"
@@ -167,6 +171,69 @@
 	  here and read <file:Documentation/modules.txt>.  The module
 	  will be called amba-clcd.
 
+choice
+
+	depends on FB_ARMCLCD && (ARCH_LH7A40X || ARCH_LH7952X)
+	prompt "LCD Panel"
+	default FB_ARMCLCD_SHARP_LQ035Q7DB02
+
+config FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
+	bool "LogicPD LCD 3.5\" QVGA w/HRTFT IC"
+	help
+	  This is an implementation of the Sharp LQ035Q7DB02, a 3.5"
+	  color QVGA, HRTFT panel.  The LogicPD device includes an
+	  an integrated HRTFT controller IC.
+	  The native resolution is 240x320.
+
+config FB_ARMCLCD_SHARP_LQ057Q3DC02
+	bool "LogicPD LCD 5.7\" QVGA"
+	help
+	  This is an implementation of the Sharp LQ057Q3DC02, a 5.7"
+	  color QVGA, TFT panel.  The LogicPD device includes an
+	  The native resolution is 320x240.
+
+config FB_ARMCLCD_SHARP_LQ64D343
+	bool "LogicPD LCD 6.4\" VGA"
+	help
+	  This is an implementation of the Sharp LQ64D343, a 6.4"
+	  color VGA, TFT panel.  The LogicPD device includes an
+	  The native resolution is 640x480.
+
+config FB_ARMCLCD_SHARP_LQ10D368
+	bool "LogicPD LCD 10.4\" VGA"
+	help
+	  This is an implementation of the Sharp LQ10D368, a 10.4"
+	  color VGA, TFT panel.  The LogicPD device includes an
+	  The native resolution is 640x480.
+
+
+config FB_ARMCLCD_SHARP_LQ121S1DG41
+	bool "LogicPD LCD 12.1\" SVGA"
+	help
+	  This is an implementation of the Sharp LQ121S1DG41, a 12.1"
+	  color SVGA, TFT panel.  The LogicPD device includes an
+	  The native resolution is 800x600.
+
+	  This panel requires a clock rate may be an integer fraction
+	  of the base LCDCLK frequency.  The driver will select the
+	  highest frequency available that is lower than the maximum
+	  allowed.  The panel may flicker if the clock rate is
+	  slower than the recommended minimum.
+
+config FB_ARMCLCD_AUO_A070VW01_WIDE
+	bool "AU Optronics A070VW01 LCD 7.0\" WIDE"
+	help
+	  This is an implementation of the AU Optronics, a 7.0"
+	  WIDE Color.  The native resolution is 234x480.
+
+config FB_ARMCLCD_HITACHI
+	bool "Hitachi Wide Screen 800x480"
+	help
+	  This is an implementation of the Hitachi 800x480.
+
+endchoice
+
+
 config FB_ACORN
 	bool "Acorn VIDC support"
 	depends on (FB = y) && ARM && (ARCH_ACORN || ARCH_CLPS7500)
@@ -483,10 +550,14 @@
 	  You will get a boot time penguin logo at no additional cost. Please
 	  read <file:Documentation/fb/vesafb.txt>. If unsure, say Y.
 
-config VIDEO_SELECT
-	bool
-	depends on FB_VESA
-	default y
+config FB_IMAC
+	bool "Intel-based Macintosh Framebuffer Support"
+	depends on (FB = y) && X86
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This is the frame buffer device driver for the Intel-based Macintosh
 
 config FB_HGA
 	tristate "Hercules mono graphics support"
@@ -510,12 +581,6 @@
 	This will compile the Hercules mono graphics with
 	acceleration functions.
 
-
-config VIDEO_SELECT
-	bool
-	depends on (FB = y) && X86
-	default y
-
 config FB_SGIVW
 	tristate "SGI Visual Workstation framebuffer support"
 	depends on FB && X86_VISWS
@@ -654,6 +719,16 @@
 	  independently validate video mode parameters, you should say Y
 	  here.
 
+config FB_NVIDIA_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_NVIDIA && PPC_PMAC
+	select FB_BACKLIGHT
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
 config FB_RIVA
 	tristate "nVidia Riva support"
 	depends on FB && PCI
@@ -692,6 +767,16 @@
 	  of debugging informations to provide to the maintainer when
 	  something goes wrong.
 
+config FB_RIVA_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_RIVA && PPC_PMAC
+	select FB_BACKLIGHT
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
 config FB_I810
 	tristate "Intel 810/815 support (EXPERIMENTAL)"
 	depends on FB && EXPERIMENTAL && PCI && X86_32
@@ -743,7 +828,7 @@
 
 config FB_INTEL
 	tristate "Intel 830M/845G/852GM/855GM/865G support (EXPERIMENTAL)"
-	depends on FB && EXPERIMENTAL && PCI && X86_32
+	depends on FB && EXPERIMENTAL && PCI && X86
 	select AGP
 	select AGP_INTEL
 	select FB_MODE_HELPERS
@@ -930,6 +1015,7 @@
 
 	  There is a product page at
 	  http://apps.ati.com/ATIcompare/
+
 config FB_RADEON_I2C
 	bool "DDC/I2C for ATI Radeon support"
 	depends on FB_RADEON
@@ -937,6 +1023,16 @@
 	help
 	  Say Y here if you want DDC/I2C support for your Radeon board. 
 
+config FB_RADEON_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_RADEON && PPC_PMAC
+	select FB_BACKLIGHT
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
 config FB_RADEON_DEBUG
 	bool "Lots of debug output from Radeon driver"
 	depends on FB_RADEON
@@ -961,6 +1057,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called aty128fb.
 
+config FB_ATY128_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_ATY128 && PPC_PMAC
+	select FB_BACKLIGHT
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
 config FB_ATY
 	tristate "ATI Mach64 display support" if PCI || ATARI
 	depends on FB && !SPARC32
@@ -1003,6 +1109,16 @@
 	  is at
 	  <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
 
+config FB_ATY_BACKLIGHT
+	bool "Support for backlight control"
+	depends on FB_ATY && PPC_PMAC
+	select FB_BACKLIGHT
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_CLASS_DEVICE
+	default y
+	help
+	  Say Y here if you want to control the backlight of your display.
+
 config FB_S3TRIO
 	bool "S3 Trio display support"
 	depends on (FB = y) && PPC && BROKEN
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 23de3b2..c335e9b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -4,15 +4,15 @@
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_VT)		  += console/
-obj-$(CONFIG_LOGO)		  += logo/
-obj-$(CONFIG_SYSFS)		  += backlight/
-
 obj-$(CONFIG_FB)                  += fb.o
 fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o \
                                      modedb.o fbcvt.o
 fb-objs                           := $(fb-y)
 
+obj-$(CONFIG_VT)		  += console/
+obj-$(CONFIG_LOGO)		  += logo/
+obj-$(CONFIG_SYSFS)		  += backlight/
+
 obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
 obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
 obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
@@ -97,6 +97,7 @@
 
 # Platform or fallback drivers go here
 obj-$(CONFIG_FB_VESA)             += vesafb.o
+obj-$(CONFIG_FB_IMAC)             += imacfb.o
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
 obj-$(CONFIG_FB_OF)               += offb.o
 
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
index 1852139..a6cc0e9 100644
--- a/drivers/video/aty/Makefile
+++ b/drivers/video/aty/Makefile
@@ -10,5 +10,6 @@
 
 radeonfb-y			:= radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o
 radeonfb-$(CONFIG_FB_RADEON_I2C)	+= radeon_i2c.o
+radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT)	+= radeon_backlight.o
 radeonfb-objs			:= $(radeonfb-y)
 
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index f7bbff4..11cf7fc 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -64,6 +64,7 @@
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/console.h>
+#include <linux/backlight.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_PPC_PMAC
@@ -99,7 +100,7 @@
 
 #ifndef CONFIG_PPC_PMAC
 /* default mode */
-static struct fb_var_screeninfo default_var __initdata = {
+static struct fb_var_screeninfo default_var __devinitdata = {
 	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
 	640, 480, 640, 480, 0, 0, 8, 0,
 	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
@@ -122,7 +123,7 @@
 
 /* default modedb mode */
 /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
-static struct fb_videomode defaultmode __initdata = {
+static struct fb_videomode defaultmode __devinitdata = {
 	.refresh =	60,
 	.xres =		640,
 	.yres =		480,
@@ -334,7 +335,7 @@
 static const struct aty128_meminfo ddr_sgram =
 	{ 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
 
-static struct fb_fix_screeninfo aty128fb_fix __initdata = {
+static struct fb_fix_screeninfo aty128fb_fix __devinitdata = {
 	.id		= "ATY Rage128",
 	.type		= FB_TYPE_PACKED_PIXELS,
 	.visual		= FB_VISUAL_PSEUDOCOLOR,
@@ -344,15 +345,15 @@
 	.accel		= FB_ACCEL_ATI_RAGE128,
 };
 
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 #ifdef CONFIG_PPC_PMAC
-static int default_vmode __initdata = VMODE_1024_768_60;
-static int default_cmode __initdata = CMODE_8;
+static int default_vmode __devinitdata = VMODE_1024_768_60;
+static int default_cmode __devinitdata = CMODE_8;
 #endif
 
-static int default_crt_on __initdata = 0;
-static int default_lcd_on __initdata = 1;
+static int default_crt_on __devinitdata = 0;
+static int default_lcd_on __devinitdata = 1;
 
 #ifdef CONFIG_MTRR
 static int mtrr = 1;
@@ -444,9 +445,9 @@
 static int aty128_decode_var(struct fb_var_screeninfo *var,
                              struct aty128fb_par *par);
 #if 0
-static void __init aty128_get_pllinfo(struct aty128fb_par *par,
+static void __devinit aty128_get_pllinfo(struct aty128fb_par *par,
 				      void __iomem *bios);
-static void __init __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par);
+static void __devinit __iomem *aty128_map_ROM(struct pci_dev *pdev, const struct aty128fb_par *par);
 #endif
 static void aty128_timings(struct aty128fb_par *par);
 static void aty128_init_engine(struct aty128fb_par *par);
@@ -480,16 +481,6 @@
 	.fb_imageblit	= cfb_imageblit,
 };
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int aty128_set_backlight_enable(int on, int level, void* data);
-static int aty128_set_backlight_level(int level, void* data);
-
-static struct backlight_controller aty128_backlight_controller = {
-	aty128_set_backlight_enable,
-	aty128_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
     /*
      * Functions to read from/write to the mmio registers
      *	- endian conversions may possibly be avoided by
@@ -582,7 +573,7 @@
 
 
 /* write to the scratch register to test r/w functionality */
-static int __init register_test(const struct aty128fb_par *par)
+static int __devinit register_test(const struct aty128fb_par *par)
 {
 	u32 val;
 	int flag = 0;
@@ -781,7 +772,7 @@
 
 
 #ifndef __sparc__
-static void __iomem * __init aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev)
+static void __iomem * __devinit aty128_map_ROM(const struct aty128fb_par *par, struct pci_dev *dev)
 {
 	u16 dptr;
 	u8 rom_type;
@@ -865,7 +856,7 @@
 	return NULL;
 }
 
-static void __init aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios)
+static void __devinit aty128_get_pllinfo(struct aty128fb_par *par, unsigned char __iomem *bios)
 {
 	unsigned int bios_hdr;
 	unsigned int bios_pll;
@@ -912,7 +903,7 @@
 #endif /* ndef(__sparc__) */
 
 /* fill in known card constants if pll_block is not available */
-static void __init aty128_timings(struct aty128fb_par *par)
+static void __devinit aty128_timings(struct aty128fb_par *par)
 {
 #ifdef CONFIG_PPC_OF
 	/* instead of a table lookup, assume OF has properly
@@ -1258,19 +1249,35 @@
 static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
 {
 	u32 reg;
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+#endif
 
 	if (on) {
 		reg = aty_ld_le32(LVDS_GEN_CNTL);
 		reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
 		reg &= ~LVDS_DISPLAY_DIS;
 		aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef CONFIG_PMAC_BACKLIGHT
-		aty128_set_backlight_enable(get_backlight_enable(),
-					    get_backlight_level(), par);
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+		mutex_lock(&info->bl_mutex);
+		if (info->bl_dev) {
+			down(&info->bl_dev->sem);
+			info->bl_dev->props->update_status(info->bl_dev);
+			up(&info->bl_dev->sem);
+		}
+		mutex_unlock(&info->bl_mutex);
 #endif	
 	} else {
-#ifdef CONFIG_PMAC_BACKLIGHT
-		aty128_set_backlight_enable(0, 0, par);
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+		mutex_lock(&info->bl_mutex);
+		if (info->bl_dev) {
+			down(&info->bl_dev->sem);
+			info->bl_dev->props->brightness = 0;
+			info->bl_dev->props->power = FB_BLANK_POWERDOWN;
+			info->bl_dev->props->update_status(info->bl_dev);
+			up(&info->bl_dev->sem);
+		}
+		mutex_unlock(&info->bl_mutex);
 #endif	
 		reg = aty_ld_le32(LVDS_GEN_CNTL);
 		reg |= LVDS_DISPLAY_DIS;
@@ -1638,7 +1645,7 @@
 }
 
 #ifndef MODULE
-static int __init aty128fb_setup(char *options)
+static int __devinit aty128fb_setup(char *options)
 {
 	char *this_opt;
 
@@ -1691,6 +1698,184 @@
 }
 #endif  /*  MODULE  */
 
+/* Backlight */
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+#define MAX_LEVEL 0xFF
+
+static struct backlight_properties aty128_bl_data;
+
+static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
+		int level)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	int atylevel;
+
+	/* Get and convert the value */
+	mutex_lock(&info->bl_mutex);
+	atylevel = MAX_LEVEL -
+		(info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
+	mutex_unlock(&info->bl_mutex);
+
+	if (atylevel < 0)
+		atylevel = 0;
+	else if (atylevel > MAX_LEVEL)
+		atylevel = MAX_LEVEL;
+
+	return atylevel;
+}
+
+/* We turn off the LCD completely instead of just dimming the backlight.
+ * This provides greater power saving and the display is useless without
+ * backlight anyway
+ */
+#define BACKLIGHT_LVDS_OFF
+/* That one prevents proper CRT output with LCD off */
+#undef BACKLIGHT_DAC_OFF
+
+static int aty128_bl_update_status(struct backlight_device *bd)
+{
+	struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
+	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
+	int level;
+
+	if (bd->props->power != FB_BLANK_UNBLANK ||
+	    bd->props->fb_blank != FB_BLANK_UNBLANK ||
+	    !par->lcd_on)
+		level = 0;
+	else
+		level = bd->props->brightness;
+
+	reg |= LVDS_BL_MOD_EN | LVDS_BLON;
+	if (level > 0) {
+		reg |= LVDS_DIGION;
+		if (!(reg & LVDS_ON)) {
+			reg &= ~LVDS_BLON;
+			aty_st_le32(LVDS_GEN_CNTL, reg);
+			aty_ld_le32(LVDS_GEN_CNTL);
+			mdelay(10);
+			reg |= LVDS_BLON;
+			aty_st_le32(LVDS_GEN_CNTL, reg);
+		}
+		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+		reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+		reg |= LVDS_ON | LVDS_EN;
+		reg &= ~LVDS_DISPLAY_DIS;
+#endif
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
+#endif
+	} else {
+		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+		reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+		reg |= LVDS_DISPLAY_DIS;
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+		aty_ld_le32(LVDS_GEN_CNTL);
+		udelay(10);
+		reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
+#endif
+		aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
+#endif
+	}
+
+	return 0;
+}
+
+static int aty128_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props->brightness;
+}
+
+static struct backlight_properties aty128_bl_data = {
+	.owner		= THIS_MODULE,
+	.get_brightness	= aty128_bl_get_brightness,
+	.update_status	= aty128_bl_update_status,
+	.max_brightness	= (FB_BACKLIGHT_LEVELS - 1),
+};
+
+static void aty128_bl_init(struct aty128fb_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd;
+	char name[12];
+
+	/* Could be extended to Rage128Pro LVDS output too */
+	if (par->chip_gen != rage_M3)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati"))
+		return;
+#endif
+
+	snprintf(name, sizeof(name), "aty128bl%d", info->node);
+
+	bd = backlight_device_register(name, par, &aty128_bl_data);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk("aty128: Backlight registration failed\n");
+		goto error;
+	}
+
+	mutex_lock(&info->bl_mutex);
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+		 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+		219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+	mutex_unlock(&info->bl_mutex);
+
+	up(&bd->sem);
+	bd->props->brightness = aty128_bl_data.max_brightness;
+	bd->props->power = FB_BLANK_UNBLANK;
+	bd->props->update_status(bd);
+	down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = bd;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+	printk("aty128: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+static void aty128_bl_exit(struct aty128fb_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+#endif
+
+	mutex_lock(&info->bl_mutex);
+	if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+		if (pmac_backlight == info->bl_dev)
+			pmac_backlight = NULL;
+#endif
+
+		backlight_device_unregister(info->bl_dev);
+		info->bl_dev = NULL;
+
+		printk("aty128: Backlight unloaded\n");
+	}
+	mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
+#endif /* CONFIG_FB_ATY128_BACKLIGHT */
 
 /*
  *  Initialisation
@@ -1708,7 +1893,7 @@
 }
 #endif /* CONFIG_PPC_PMAC */
 
-static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct fb_info *info = pci_get_drvdata(pdev);
 	struct aty128fb_par *par = info->par;
@@ -1835,17 +2020,15 @@
 	if (register_framebuffer(info) < 0)
 		return 0;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	/* Could be extended to Rage128Pro LVDS output too */
-	if (par->chip_gen == rage_M3)
-		register_backlight_controller(&aty128_backlight_controller, par, "ati");
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
 	par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
 	par->pdev = pdev;
 	par->asleep = 0;
 	par->lock_blank = 0;
-	
+
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	aty128_bl_init(par);
+#endif
+
 	printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
 	       info->node, info->fix.id, video_card);
 
@@ -1854,7 +2037,7 @@
 
 #ifdef CONFIG_PCI
 /* register a card    ++ajoshi */
-static int __init aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int __devinit aty128_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	unsigned long fb_addr, reg_addr;
 	struct aty128fb_par *par;
@@ -1981,6 +2164,10 @@
 
 	par = info->par;
 
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	aty128_bl_exit(par);
+#endif
+
 	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
@@ -2011,10 +2198,14 @@
 	if (par->lock_blank || par->asleep)
 		return 0;
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (machine_is(powermac) && blank)
-		set_backlight_enable(0);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	if (machine_is(powermac) && blank) {
+		down(&fb->bl_dev->sem);
+		fb->bl_dev->props->power = FB_BLANK_POWERDOWN;
+		fb->bl_dev->props->update_status(fb->bl_dev);
+		up(&fb->bl_dev->sem);
+	}
+#endif
 
 	if (blank & FB_BLANK_VSYNC_SUSPEND)
 		state |= 2;
@@ -2029,10 +2220,14 @@
 		aty128_set_crt_enable(par, par->crt_on && !blank);
 		aty128_set_lcd_enable(par, par->lcd_on && !blank);
 	}
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (machine_is(powermac) && !blank)
-		set_backlight_enable(1);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+	if (machine_is(powermac) && !blank) {
+		down(&fb->bl_dev->sem);
+		fb->bl_dev->props->power = FB_BLANK_UNBLANK;
+		fb->bl_dev->props->update_status(fb->bl_dev);
+		up(&fb->bl_dev->sem);
+	}
+#endif
 	return 0;
 }
 
@@ -2138,73 +2333,6 @@
 	return -EINVAL;
 }
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight_conv[] = {
-	0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
-	0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
-};
-
-/* We turn off the LCD completely instead of just dimming the backlight.
- * This provides greater power saving and the display is useless without
- * backlight anyway
- */
-#define BACKLIGHT_LVDS_OFF
-/* That one prevents proper CRT output with LCD off */
-#undef BACKLIGHT_DAC_OFF
-
-static int aty128_set_backlight_enable(int on, int level, void *data)
-{
-	struct aty128fb_par *par = data;
-	unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
-
-	if (!par->lcd_on)
-		on = 0;
-	reg |= LVDS_BL_MOD_EN | LVDS_BLON;
-	if (on && level > BACKLIGHT_OFF) {
-		reg |= LVDS_DIGION;
-		if (!(reg & LVDS_ON)) {
-			reg &= ~LVDS_BLON;
-			aty_st_le32(LVDS_GEN_CNTL, reg);
-			(void)aty_ld_le32(LVDS_GEN_CNTL);
-			mdelay(10);
-			reg |= LVDS_BLON;
-			aty_st_le32(LVDS_GEN_CNTL, reg);
-		}
-		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
-		reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT);
-#ifdef BACKLIGHT_LVDS_OFF
-		reg |= LVDS_ON | LVDS_EN;
-		reg &= ~LVDS_DISPLAY_DIS;
-#endif
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef BACKLIGHT_DAC_OFF
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
-#endif		
-	} else {
-		reg &= ~LVDS_BL_MOD_LEVEL_MASK;
-		reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT);
-#ifdef BACKLIGHT_LVDS_OFF
-		reg |= LVDS_DISPLAY_DIS;
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-		(void)aty_ld_le32(LVDS_GEN_CNTL);
-		udelay(10);
-		reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
-#endif		
-		aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef BACKLIGHT_DAC_OFF
-		aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
-#endif		
-	}
-
-	return 0;
-}
-
-static int aty128_set_backlight_level(int level, void* data)
-{
-	return aty128_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
 #if 0
     /*
      *  Accelerated functions
@@ -2428,7 +2556,7 @@
 }
 
 
-static int __init aty128fb_init(void)
+static int __devinit aty128fb_init(void)
 {
 #ifndef MODULE
 	char *option = NULL;
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index e9b7a64..43d2cb5 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -151,6 +151,7 @@
 	int lock_blank;
 	unsigned long res_start;
 	unsigned long res_size;
+	struct pci_dev *pdev;
 #ifdef __sparc__
 	struct pci_mmap_map *mmap_map;
 	u8 mmaped;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index d9d7d3c..22e7206 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -66,6 +66,7 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
+#include <linux/backlight.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -315,12 +316,12 @@
 static int pll;
 static int mclk;
 static int xclk;
-static int comp_sync __initdata = -1;
+static int comp_sync __devinitdata = -1;
 static char *mode;
 
 #ifdef CONFIG_PPC
-static int default_vmode __initdata = VMODE_CHOOSE;
-static int default_cmode __initdata = CMODE_CHOOSE;
+static int default_vmode __devinitdata = VMODE_CHOOSE;
+static int default_cmode __devinitdata = CMODE_CHOOSE;
 
 module_param_named(vmode, default_vmode, int, 0);
 MODULE_PARM_DESC(vmode, "int: video mode for mac");
@@ -329,10 +330,10 @@
 #endif
 
 #ifdef CONFIG_ATARI
-static unsigned int mach64_count __initdata = 0;
-static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };
-static unsigned long phys_size[FB_MAX] __initdata = { 0, };
-static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };
+static unsigned int mach64_count __devinitdata = 0;
+static unsigned long phys_vmembase[FB_MAX] __devinitdata = { 0, };
+static unsigned long phys_size[FB_MAX] __devinitdata = { 0, };
+static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, };
 #endif
 
 /* top -> down is an evolution of mach64 chipset, any corrections? */
@@ -582,7 +583,7 @@
  *  Apple monitor sense
  */
 
-static int __init read_aty_sense(const struct atyfb_par *par)
+static int __devinit read_aty_sense(const struct atyfb_par *par)
 {
 	int sense, i;
 
@@ -1280,6 +1281,14 @@
 
 	par->accel_flags = var->accel_flags; /* hack */
 
+	if (var->accel_flags) {
+		info->fbops->fb_sync = atyfb_sync;
+		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+	} else {
+		info->fbops->fb_sync = NULL;
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+
 	if (par->blitter_may_be_busy)
 		wait_for_idle(par);
 
@@ -2115,47 +2124,144 @@
 
 #endif /*  defined(CONFIG_PM) && defined(CONFIG_PCI) */
 
-#ifdef CONFIG_PMAC_BACKLIGHT
+/* Backlight */
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+#define MAX_LEVEL 0xFF
 
-    /*
-     *   LCD backlight control
-     */
+static struct backlight_properties aty_bl_data;
 
-static int backlight_conv[] = {
-	0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
-	0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
-};
-
-static int aty_set_backlight_enable(int on, int level, void *data)
+static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
 {
-	struct fb_info *info = (struct fb_info *) data;
-	struct atyfb_par *par = (struct atyfb_par *) info->par;
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	int atylevel;
+
+	/* Get and convert the value */
+	mutex_lock(&info->bl_mutex);
+	atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
+	mutex_unlock(&info->bl_mutex);
+
+	if (atylevel < 0)
+		atylevel = 0;
+	else if (atylevel > MAX_LEVEL)
+		atylevel = MAX_LEVEL;
+
+	return atylevel;
+}
+
+static int aty_bl_update_status(struct backlight_device *bd)
+{
+	struct atyfb_par *par = class_get_devdata(&bd->class_dev);
 	unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
+	int level;
+
+	if (bd->props->power != FB_BLANK_UNBLANK ||
+	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props->brightness;
 
 	reg |= (BLMOD_EN | BIASMOD_EN);
-	if (on && level > BACKLIGHT_OFF) {
+	if (level > 0) {
 		reg &= ~BIAS_MOD_LEVEL_MASK;
-		reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
+		reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
 	} else {
 		reg &= ~BIAS_MOD_LEVEL_MASK;
-		reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
+		reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
 	}
 	aty_st_lcd(LCD_MISC_CNTL, reg, par);
+
 	return 0;
 }
 
-static int aty_set_backlight_level(int level, void *data)
+static int aty_bl_get_brightness(struct backlight_device *bd)
 {
-	return aty_set_backlight_enable(1, level, data);
+	return bd->props->brightness;
 }
 
-static struct backlight_controller aty_backlight_controller = {
-	aty_set_backlight_enable,
-	aty_set_backlight_level
+static struct backlight_properties aty_bl_data = {
+	.owner	  = THIS_MODULE,
+	.get_brightness = aty_bl_get_brightness,
+	.update_status	= aty_bl_update_status,
+	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
 };
-#endif /* CONFIG_PMAC_BACKLIGHT */
 
-static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
+static void aty_bl_init(struct atyfb_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd;
+	char name[12];
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati"))
+		return;
+#endif
+
+	snprintf(name, sizeof(name), "atybl%d", info->node);
+
+	bd = backlight_device_register(name, par, &aty_bl_data);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk("aty: Backlight registration failed\n");
+		goto error;
+	}
+
+	mutex_lock(&info->bl_mutex);
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+		0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
+		0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
+	mutex_unlock(&info->bl_mutex);
+
+	up(&bd->sem);
+	bd->props->brightness = aty_bl_data.max_brightness;
+	bd->props->power = FB_BLANK_UNBLANK;
+	bd->props->update_status(bd);
+	down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = bd;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+	printk("aty: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+static void aty_bl_exit(struct atyfb_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+#endif
+
+	mutex_lock(&info->bl_mutex);
+	if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+		if (pmac_backlight == info->bl_dev)
+			pmac_backlight = NULL;
+#endif
+
+		backlight_device_unregister(info->bl_dev);
+
+		printk("aty: Backlight unloaded\n");
+	}
+	mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
+
+#endif /* CONFIG_FB_ATY_BACKLIGHT */
+
+static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
 {
 	const int ragepro_tbl[] = {
 		44, 50, 55, 66, 75, 80, 100
@@ -2215,7 +2321,7 @@
 }
 #endif /* defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) */
 
-static int __init aty_init(struct fb_info *info, const char *name)
+static int __devinit aty_init(struct fb_info *info, const char *name)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	const char *ramname = NULL, *xtal;
@@ -2296,12 +2402,15 @@
 			break;
 		}
 		switch (clk_type) {
+#ifdef CONFIG_ATARI
 		case CLK_ATI18818_1:
 			par->pll_ops = &aty_pll_ati18818_1;
 			break;
+#else
 		case CLK_IBMRGB514:
 			par->pll_ops = &aty_pll_ibm514;
 			break;
+#endif
 #if 0 /* dead code */
 		case CLK_STG1703:
 			par->pll_ops = &aty_pll_stg1703;
@@ -2506,16 +2615,24 @@
 
 	info->fbops = &atyfb_ops;
 	info->pseudo_palette = pseudo_palette;
-	info->flags = FBINFO_FLAG_DEFAULT;
+	info->flags = FBINFO_DEFAULT           |
+	              FBINFO_HWACCEL_IMAGEBLIT |
+	              FBINFO_HWACCEL_FILLRECT  |
+	              FBINFO_HWACCEL_COPYAREA  |
+	              FBINFO_HWACCEL_YPAN;
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) {
 		/* these bits let the 101 powerbook wake up from sleep -- paulus */
 		aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
 			   | (USE_F32KHZ | TRISTATE_MEM_EN), par);
-	} else if (M64_HAS(MOBIL_BUS))
-		register_backlight_controller(&aty_backlight_controller, info, "ati");
-#endif /* CONFIG_PMAC_BACKLIGHT */
+	} else
+#endif
+	if (M64_HAS(MOBIL_BUS)) {
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+		aty_bl_init (par);
+#endif
+	}
 
 	memset(&var, 0, sizeof(var));
 #ifdef CONFIG_PPC
@@ -2631,7 +2748,7 @@
 }
 
 #ifdef CONFIG_ATARI
-static int __init store_video_par(char *video_str, unsigned char m64_num)
+static int __devinit store_video_par(char *video_str, unsigned char m64_num)
 {
 	char *p;
 	unsigned long vmembase, size, guiregbase;
@@ -2674,8 +2791,16 @@
 		return 0;
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
-		set_backlight_enable(0);
+	if (machine_is(powermac) && blank > FB_BLANK_NORMAL) {
+		mutex_lock(&info->bl_mutex);
+		if (info->bl_dev) {
+			down(&info->bl_dev->sem);
+			info->bl_dev->props->power = FB_BLANK_POWERDOWN;
+			info->bl_dev->props->update_status(info->bl_dev);
+			up(&info->bl_dev->sem);
+		}
+		mutex_unlock(&info->bl_mutex);
+	}
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank > FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2706,8 +2831,16 @@
 	aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
 
 #ifdef CONFIG_PMAC_BACKLIGHT
-	if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
-		set_backlight_enable(1);
+	if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) {
+		mutex_lock(&info->bl_mutex);
+		if (info->bl_dev) {
+			down(&info->bl_dev->sem);
+			info->bl_dev->props->power = FB_BLANK_UNBLANK;
+			info->bl_dev->props->update_status(info->bl_dev);
+			up(&info->bl_dev->sem);
+		}
+		mutex_unlock(&info->bl_mutex);
+	}
 #elif defined(CONFIG_FB_ATY_GENERIC_LCD)
 	if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
 	    (aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2966,7 +3099,7 @@
 	}
 
 	pcp = pdev->sysdata;
-	if (node == pcp->prom_node) {
+	if (node == pcp->prom_node->node) {
 		struct fb_var_screeninfo *var = &default_var;
 		unsigned int N, P, Q, M, T, R;
 		u32 v_total, h_total;
@@ -3440,6 +3573,7 @@
 	par->res_start = res_start;
 	par->res_size = res_size;
 	par->irq = pdev->irq;
+	par->pdev = pdev;
 
 	/* Setup "info" structure */
 #ifdef __sparc__
@@ -3571,6 +3705,11 @@
 	aty_set_crtc(par, &saved_crtc);
 	par->pll_ops->set_pll(info, &saved_pll);
 
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+	if (M64_HAS(MOBIL_BUS))
+		aty_bl_exit(par);
+#endif
+
 	unregister_framebuffer(info);
 
 #ifdef CONFIG_MTRR
@@ -3640,7 +3779,7 @@
 #endif /* CONFIG_PCI */
 
 #ifndef MODULE
-static int __init atyfb_setup(char *options)
+static int __devinit atyfb_setup(char *options)
 {
 	char *this_opt;
 
@@ -3712,7 +3851,7 @@
 }
 #endif  /*  MODULE  */
 
-static int __init atyfb_init(void)
+static int __devinit atyfb_init(void)
 {
 #ifndef MODULE
     char *option = NULL;
@@ -3722,7 +3861,9 @@
     atyfb_setup(option);
 #endif
 
+#ifdef CONFIG_PCI
     pci_register_driver(&atyfb_driver);
+#endif
 #ifdef CONFIG_ATARI
     atyfb_atari_probe();
 #endif
@@ -3731,7 +3872,9 @@
 
 static void __exit atyfb_exit(void)
 {
+#ifdef CONFIG_PCI
 	pci_unregister_driver(&atyfb_driver);
+#endif
 }
 
 module_init(atyfb_init);
diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/aty/mach64_accel.c
index c98f4a4..1490e5e 100644
--- a/drivers/video/aty/mach64_accel.c
+++ b/drivers/video/aty/mach64_accel.c
@@ -200,8 +200,6 @@
 	if (!area->width || !area->height)
 		return;
 	if (!par->accel_flags) {
-		if (par->blitter_may_be_busy)
-			wait_for_idle(par);
 		cfb_copyarea(info, area);
 		return;
 	}
@@ -248,8 +246,6 @@
 	if (!rect->width || !rect->height)
 		return;
 	if (!par->accel_flags) {
-		if (par->blitter_may_be_busy)
-			wait_for_idle(par);
 		cfb_fillrect(info, rect);
 		return;
 	}
@@ -288,14 +284,10 @@
 		return;
 	if (!par->accel_flags ||
 	    (image->depth != 1 && info->var.bits_per_pixel != image->depth)) {
-		if (par->blitter_may_be_busy)
-			wait_for_idle(par);
-
 		cfb_imageblit(info, image);
 		return;
 	}
 
-	wait_for_idle(par);
 	pix_width = pix_width_save = aty_ld_le32(DP_PIX_WIDTH, par);
 	host_cntl = aty_ld_le32(HOST_CNTL, par) | HOST_BYTE_ALIGN;
 
@@ -425,8 +417,6 @@
 		}
 	}
 
-	wait_for_idle(par);
-
 	/* restore pix_width */
 	wait_for_fifo(1, par);
 	aty_st_le32(DP_PIX_WIDTH, pix_width_save, par);
diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
index ad8b749..2a7f381 100644
--- a/drivers/video/aty/mach64_cursor.c
+++ b/drivers/video/aty/mach64_cursor.c
@@ -66,11 +66,6 @@
 	0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55
 };
 
-static const u8 cursor_mask_lookup[16] = {
-	0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
-	0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
-};
-
 static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
@@ -130,13 +125,13 @@
 		fg_idx = cursor->image.fg_color;
 		bg_idx = cursor->image.bg_color;
 
-		fg = (info->cmap.red[fg_idx] << 24) |
-		     (info->cmap.green[fg_idx] << 16) |
-		     (info->cmap.blue[fg_idx] << 8) | 15;
+		fg = ((info->cmap.red[fg_idx] & 0xff) << 24) |
+		     ((info->cmap.green[fg_idx] & 0xff) << 16) |
+		     ((info->cmap.blue[fg_idx] & 0xff) << 8) | 0xff;
 
-		bg = (info->cmap.red[bg_idx] << 24) |
-		     (info->cmap.green[bg_idx] << 16) |
-		     (info->cmap.blue[bg_idx] << 8);
+		bg = ((info->cmap.red[bg_idx] & 0xff) << 24) |
+		     ((info->cmap.green[bg_idx] & 0xff) << 16) |
+		     ((info->cmap.blue[bg_idx] & 0xff) << 8);
 
 		wait_for_fifo(2, par);
 		aty_st_le32(CUR_CLR0, bg, par);
@@ -166,19 +161,17 @@
 			switch (cursor->rop) {
 			case ROP_XOR:
 			    // Upper 4 bits of mask data
-			    fb_writeb(cursor_mask_lookup[m >> 4 ] |
-				cursor_bits_lookup[(b ^ m) >> 4], dst++);
+			    fb_writeb(cursor_bits_lookup[(b ^ m) >> 4], dst++);
 			    // Lower 4 bits of mask
-			    fb_writeb(cursor_mask_lookup[m & 0x0f ] |
-				cursor_bits_lookup[(b ^ m) & 0x0f], dst++);
+			    fb_writeb(cursor_bits_lookup[(b ^ m) & 0x0f],
+				      dst++);
 			    break;
 			case ROP_COPY:
 			    // Upper 4 bits of mask data
-			    fb_writeb(cursor_mask_lookup[m >> 4 ] |
-				cursor_bits_lookup[(b & m) >> 4], dst++);
+			    fb_writeb(cursor_bits_lookup[(b & m) >> 4], dst++);
 			    // Lower 4 bits of mask
-			    fb_writeb(cursor_mask_lookup[m & 0x0f ] |
-				cursor_bits_lookup[(b & m) & 0x0f], dst++);
+			    fb_writeb(cursor_bits_lookup[(b & m) & 0x0f],
+				      dst++);
 			    break;
 			}
 		}
@@ -194,7 +187,7 @@
 	return 0;
 }
 
-int __init aty_init_cursor(struct fb_info *info)
+int __devinit aty_init_cursor(struct fb_info *info)
 {
 	unsigned long addr;
 
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
new file mode 100644
index 0000000..1755ddd
--- /dev/null
+++ b/drivers/video/aty/radeon_backlight.c
@@ -0,0 +1,247 @@
+/*
+ * Backlight code for ATI Radeon based graphic cards
+ *
+ * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org>
+ * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "radeonfb.h"
+#include <linux/backlight.h>
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#define MAX_RADEON_LEVEL 0xFF
+
+static struct backlight_properties radeon_bl_data;
+
+struct radeon_bl_privdata {
+	struct radeonfb_info *rinfo;
+	uint8_t negative;
+};
+
+static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
+		int level)
+{
+	struct fb_info *info = pdata->rinfo->info;
+	int rlevel;
+
+	mutex_lock(&info->bl_mutex);
+
+	/* Get and convert the value */
+	rlevel = pdata->rinfo->info->bl_curve[level] *
+		 FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
+
+	mutex_unlock(&info->bl_mutex);
+
+	if (rlevel < 0)
+		rlevel = 0;
+	else if (rlevel > MAX_RADEON_LEVEL)
+		rlevel = MAX_RADEON_LEVEL;
+
+	if (pdata->negative)
+		rlevel = MAX_RADEON_LEVEL - rlevel;
+
+	return rlevel;
+}
+
+static int radeon_bl_update_status(struct backlight_device *bd)
+{
+	struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev);
+	struct radeonfb_info *rinfo = pdata->rinfo;
+	u32 lvds_gen_cntl, tmpPixclksCntl;
+	int level;
+
+	if (rinfo->mon1_type != MT_LCD)
+		return 0;
+
+	/* We turn off the LCD completely instead of just dimming the
+	 * backlight. This provides some greater power saving and the display
+	 * is useless without backlight anyway.
+	 */
+        if (bd->props->power != FB_BLANK_UNBLANK ||
+	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props->brightness;
+
+	del_timer_sync(&rinfo->lvds_timer);
+	radeon_engine_idle();
+
+	lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+	if (level > 0) {
+		lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
+		if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
+			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
+			lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
+			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+			lvds_gen_cntl |=
+				(radeon_bl_get_level_brightness(pdata, level) <<
+				 LVDS_BL_MOD_LEVEL_SHIFT);
+			lvds_gen_cntl |= LVDS_ON;
+			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
+			rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+			mod_timer(&rinfo->lvds_timer,
+				  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+		} else {
+			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+			lvds_gen_cntl |=
+				(radeon_bl_get_level_brightness(pdata, level) <<
+				 LVDS_BL_MOD_LEVEL_SHIFT);
+			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+		}
+		rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+		rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
+			& LVDS_STATE_MASK;
+	} else {
+		/* Asic bug, when turning off LVDS_ON, we have to make sure
+		   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+		*/
+		tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
+		if (rinfo->is_mobility || rinfo->is_IGP)
+			OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+		lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
+		lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
+				  LVDS_BL_MOD_LEVEL_SHIFT);
+		lvds_gen_cntl |= LVDS_DISPLAY_DIS;
+		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+		udelay(100);
+		lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
+		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+		lvds_gen_cntl &= ~(LVDS_DIGON);
+		rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+		mod_timer(&rinfo->lvds_timer,
+			  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+		if (rinfo->is_mobility || rinfo->is_IGP)
+			OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
+	}
+	rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+	rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
+
+	return 0;
+}
+
+static int radeon_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props->brightness;
+}
+
+static struct backlight_properties radeon_bl_data = {
+	.owner		= THIS_MODULE,
+	.get_brightness = radeon_bl_get_brightness,
+	.update_status	= radeon_bl_update_status,
+	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void radeonfb_bl_init(struct radeonfb_info *rinfo)
+{
+	struct backlight_device *bd;
+	struct radeon_bl_privdata *pdata;
+	char name[12];
+
+	if (rinfo->mon1_type != MT_LCD)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati") &&
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL);
+	if (!pdata) {
+		printk("radeonfb: Memory allocation failed\n");
+		goto error;
+	}
+
+	snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
+
+	bd = backlight_device_register(name, pdata, &radeon_bl_data);
+	if (IS_ERR(bd)) {
+		rinfo->info->bl_dev = NULL;
+		printk("radeonfb: Backlight registration failed\n");
+		goto error;
+	}
+
+	pdata->rinfo = rinfo;
+
+	/* Pardon me for that hack... maybe some day we can figure out in what
+	 * direction backlight should work on a given panel?
+	 */
+	pdata->negative =
+		(rinfo->family != CHIP_FAMILY_RV200 &&
+		 rinfo->family != CHIP_FAMILY_RV250 &&
+		 rinfo->family != CHIP_FAMILY_RV280 &&
+		 rinfo->family != CHIP_FAMILY_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	pdata->negative = pdata->negative ||
+		machine_is_compatible("PowerBook4,3") ||
+		machine_is_compatible("PowerBook6,3") ||
+		machine_is_compatible("PowerBook6,5");
+#endif
+
+	mutex_lock(&rinfo->info->bl_mutex);
+	rinfo->info->bl_dev = bd;
+	fb_bl_default_curve(rinfo->info, 0,
+		 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
+		217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
+	mutex_unlock(&rinfo->info->bl_mutex);
+
+	up(&bd->sem);
+	bd->props->brightness = radeon_bl_data.max_brightness;
+	bd->props->power = FB_BLANK_UNBLANK;
+	bd->props->update_status(bd);
+	down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = bd;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+	printk("radeonfb: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	kfree(pdata);
+	return;
+}
+
+void radeonfb_bl_exit(struct radeonfb_info *rinfo)
+{
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+#endif
+
+	mutex_lock(&rinfo->info->bl_mutex);
+	if (rinfo->info->bl_dev) {
+		struct radeon_bl_privdata *pdata;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+		if (pmac_backlight == rinfo->info->bl_dev)
+			pmac_backlight = NULL;
+#endif
+
+		pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
+		backlight_device_unregister(rinfo->info->bl_dev);
+		kfree(pdata);
+		rinfo->info->bl_dev = NULL;
+
+		printk("radeonfb: Backlight unloaded\n");
+	}
+	mutex_unlock(&rinfo->info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 387a18a..68b1564 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -78,10 +78,6 @@
 #include <asm/pci-bridge.h>
 #include "../macmodes.h"
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
 #ifdef CONFIG_BOOTX_TEXT
 #include <asm/btext.h>
 #endif
@@ -277,20 +273,6 @@
  * prototypes
  */
 
-
-#ifdef CONFIG_PPC_OF
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int radeon_set_backlight_enable(int on, int level, void *data);
-static int radeon_set_backlight_level(int level, void *data);
-static struct backlight_controller radeon_backlight_controller = {
-	radeon_set_backlight_enable,
-	radeon_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-#endif /* CONFIG_PPC_OF */
-
 static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
 {
 	if (!rinfo->bios_seg)
@@ -1913,116 +1895,6 @@
         return 0;
 }
 
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-
-/* TODO: Dbl check these tables, we don't go up to full ON backlight
- * in these, possibly because we noticed MacOS doesn't, but I'd prefer
- * having some more official numbers from ATI
- */
-static int backlight_conv_m6[] = {
-	0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
-	0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
-};
-static int backlight_conv_m7[] = {
-	0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81,
-	0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9
-};
-
-#define BACKLIGHT_LVDS_OFF
-#undef BACKLIGHT_DAC_OFF
-
-/* We turn off the LCD completely instead of just dimming the backlight.
- * This provides some greater power saving and the display is useless
- * without backlight anyway.
- */
-static int radeon_set_backlight_enable(int on, int level, void *data)
-{
-	struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
-	u32 lvds_gen_cntl, tmpPixclksCntl;
-	int* conv_table;
-
-	if (rinfo->mon1_type != MT_LCD)
-		return 0;
-
-	/* Pardon me for that hack... maybe some day we can figure
-	 * out in what direction backlight should work on a given
-	 * panel ?
-	 */
-	if ((rinfo->family == CHIP_FAMILY_RV200 ||
-	     rinfo->family == CHIP_FAMILY_RV250 ||
-	     rinfo->family == CHIP_FAMILY_RV280 ||
-	     rinfo->family == CHIP_FAMILY_RV350) &&
-	    !machine_is_compatible("PowerBook4,3") &&
-	    !machine_is_compatible("PowerBook6,3") &&
-	    !machine_is_compatible("PowerBook6,5"))
-		conv_table = backlight_conv_m7;
-	else
-		conv_table = backlight_conv_m6;
-
-	del_timer_sync(&rinfo->lvds_timer);
-	radeon_engine_idle();
-
-	lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
-	if (on && (level > BACKLIGHT_OFF)) {
-		lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
-		if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
-			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
-			lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
-			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-			lvds_gen_cntl |= (conv_table[level] <<
-					  LVDS_BL_MOD_LEVEL_SHIFT);
-			lvds_gen_cntl |= LVDS_ON;
-			lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
-			rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
-			mod_timer(&rinfo->lvds_timer,
-				  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-		} else {
-			lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
-			lvds_gen_cntl |= (conv_table[level] <<
-					  LVDS_BL_MOD_LEVEL_SHIFT);
-			OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-		}
-		rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-		rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
-			& LVDS_STATE_MASK;
-	} else {
-		/* Asic bug, when turning off LVDS_ON, we have to make sure
-		   RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
-		*/
-		tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
-		if (rinfo->is_mobility || rinfo->is_IGP)
-			OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
-		lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
-		lvds_gen_cntl |= (conv_table[0] <<
-				  LVDS_BL_MOD_LEVEL_SHIFT);
-		lvds_gen_cntl |= LVDS_DISPLAY_DIS;
-		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-		udelay(100);
-		lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
-		OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
-		lvds_gen_cntl &= ~(LVDS_DIGON);
-		rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
-		mod_timer(&rinfo->lvds_timer,
-			  jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
-		if (rinfo->is_mobility || rinfo->is_IGP)
-			OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
-	}
-	rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
-	rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
-
-	return 0;
-}
-
-
-static int radeon_set_backlight_level(int level, void *data)
-{
-	return radeon_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-
 /*
  * This reconfigure the card's internal memory map. In theory, we'd like
  * to setup the card's memory at the same address as it's PCI bus address,
@@ -2477,14 +2349,7 @@
 						 MTRR_TYPE_WRCOMB, 1);
 #endif
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (rinfo->mon1_type == MT_LCD) {
-		register_backlight_controller(&radeon_backlight_controller,
-					      rinfo, "ati");
-		register_backlight_controller(&radeon_backlight_controller,
-					      rinfo, "mnca");
-	}
-#endif
+	radeonfb_bl_init(rinfo);
 
 	printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
 
@@ -2514,7 +2379,6 @@
 err_release_fb:
         framebuffer_release(info);
 err_disable:
-	pci_disable_device(pdev);
 err_out:
 	return ret;
 }
@@ -2528,7 +2392,8 @@
  
         if (!rinfo)
                 return;
- 
+
+	radeonfb_bl_exit(rinfo);
 	radeonfb_pm_exit(rinfo);
 
 	if (rinfo->mon1_EDID)
@@ -2570,7 +2435,6 @@
 #endif        
 	fb_dealloc_cmap(&info->cmap);
         framebuffer_release(info);
-	pci_disable_device(pdev);
 }
 
 
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 217e00a..1645943 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -625,4 +625,13 @@
 extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
 			       int reg_only);
 
+/* Backlight functions */
+#ifdef CONFIG_FB_RADEON_BACKLIGHT
+extern void radeonfb_bl_init(struct radeonfb_info *rinfo);
+extern void radeonfb_bl_exit(struct radeonfb_info *rinfo);
+#else
+static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {}
+static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {}
+#endif
+
 #endif /* __RADEONFB_H__ */
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index 789450b..9ef68cd 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -7,6 +7,8 @@
  *  	Karl Lessard <klessard@sunrisetelecom.com>
  *  	<c.pellegrin@exadron.com>
  *
+ * PM support added by Rodolfo Giometti <giometti@linux.it>
+ *
  * Copyright 2002 MontaVista Software
  * Author: MontaVista Software, Inc.
  *		ppopov@mvista.com or source@mvista.com
@@ -602,17 +604,52 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static u32 sys_clksrc;
+static struct au1100fb_regs fbregs;
+
 int au1100fb_drv_suspend(struct device *dev, pm_message_t state)
 {
-	/* TODO */
+	struct au1100fb_device *fbdev = dev_get_drvdata(dev);
+
+	if (!fbdev)
+		return 0;
+
+	/* Save the clock source state */
+	sys_clksrc = au_readl(SYS_CLKSRC);
+
+	/* Blank the LCD */
+	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
+
+	/* Stop LCD clocking */
+	au_writel(sys_clksrc & ~SYS_CS_ML_MASK, SYS_CLKSRC);
+
+	memcpy(&fbregs, fbdev->regs, sizeof(struct au1100fb_regs));
+
 	return 0;
 }
 
 int au1100fb_drv_resume(struct device *dev)
 {
-	/* TODO */
+	struct au1100fb_device *fbdev = dev_get_drvdata(dev);
+
+	if (!fbdev)
+		return 0;
+
+	memcpy(fbdev->regs, &fbregs, sizeof(struct au1100fb_regs));
+
+	/* Restart LCD clocking */
+	au_writel(sys_clksrc, SYS_CLKSRC);
+
+	/* Unblank the LCD */
+	au1100fb_fb_blank(VESA_NO_BLANKING, &fbdev->info);
+
 	return 0;
 }
+#else
+#define au1100fb_drv_suspend NULL
+#define au1100fb_drv_resume NULL
+#endif
 
 static struct device_driver au1100fb_driver = {
 	.name		= "au1100-lcd",
@@ -706,8 +743,7 @@
 {
 	driver_unregister(&au1100fb_driver);
 
-	if (drv_info.opt_mode)
-		kfree(drv_info.opt_mode);
+	kfree(drv_info.opt_mode);
 }
 
 module_init(au1100fb_init);
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index b895eaa..022f9d3 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -10,7 +10,7 @@
 
 config BACKLIGHT_CLASS_DEVICE
         tristate "Lowlevel Backlight controls"
-	depends on BACKLIGHT_LCD_SUPPORT
+	depends on BACKLIGHT_LCD_SUPPORT && FB
 	default m
 	help
 	  This framework adds support for low-level control of the LCD
@@ -26,7 +26,7 @@
 
 config LCD_CLASS_DEVICE
         tristate "Lowlevel LCD controls"
-	depends on BACKLIGHT_LCD_SUPPORT
+	depends on BACKLIGHT_LCD_SUPPORT && FB
 	default m
 	help
 	  This framework adds support for low-level control of LCD.
@@ -50,6 +50,14 @@
 	  If you have a Sharp Zaurus SL-C7xx, SL-Cxx00 or SL-6000x say y to enable the
 	  backlight driver.
 
+config BACKLIGHT_LOCOMO
+	tristate "Sharp LOCOMO LCD/Backlight Driver"
+	depends on BACKLIGHT_DEVICE && SHARP_LOCOMO
+	default y
+	help
+	  If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to
+	  enable the LCD/backlight driver.
+
 config BACKLIGHT_HP680
 	tristate "HP Jornada 680 Backlight Driver"
 	depends on BACKLIGHT_DEVICE && SH_HP6XX
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 744210c..65e5553 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -4,4 +4,4 @@
 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
 obj-$(CONFIG_BACKLIGHT_CORGI)	+= corgi_bl.o
 obj-$(CONFIG_BACKLIGHT_HP680)	+= hp680_bl.o
-obj-$(CONFIG_SHARP_LOCOMO)	+= locomolcd.o
+obj-$(CONFIG_BACKLIGHT_LOCOMO)	+= locomolcd.o
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index a71e984..ffc72ae 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -27,7 +27,7 @@
 
 static int hp680bl_suspended;
 static int current_intensity = 0;
-static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(bl_lock);
 static struct backlight_device *hp680_backlight_device;
 
 static void hp680bl_send_intensity(struct backlight_device *bd)
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index 60831bb..bd879b7 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -17,6 +17,8 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
 
 #include <asm/hardware/locomo.h>
 #include <asm/irq.h>
@@ -25,7 +27,10 @@
 
 #include "../../../arch/arm/mach-sa1100/generic.h"
 
+static struct backlight_device *locomolcd_bl_device;
 static struct locomo_dev *locomolcd_dev;
+static unsigned long locomolcd_flags;
+#define LOCOMOLCD_SUSPENDED     0x01
 
 static void locomolcd_on(int comadj)
 {
@@ -89,12 +94,10 @@
 	}
 
 	/* read comadj */
-	if (comadj == -1) {
-		if (machine_is_poodle())
-			comadj = 118;
-		if (machine_is_collie())
-			comadj = 128;
-	}
+	if (comadj == -1 && machine_is_collie())
+		comadj = 128;
+	if (comadj == -1 && machine_is_poodle())
+		comadj = 118;
 
 	if (on)
 		locomolcd_on(comadj);
@@ -105,26 +108,100 @@
 }
 EXPORT_SYMBOL(locomolcd_power);
 
-static int poodle_lcd_probe(struct locomo_dev *dev)
+
+static int current_intensity;
+
+static int locomolcd_set_intensity(struct backlight_device *bd)
+{
+	int intensity = bd->props->brightness;
+
+	if (bd->props->power != FB_BLANK_UNBLANK)
+		intensity = 0;
+	if (bd->props->fb_blank != FB_BLANK_UNBLANK)
+		intensity = 0;
+	if (locomolcd_flags & LOCOMOLCD_SUSPENDED)
+		intensity = 0;
+
+	switch (intensity) {
+	/* AC and non-AC are handled differently, but produce same results in sharp code? */
+	case 0: locomo_frontlight_set(locomolcd_dev, 0, 0, 161); break;
+	case 1: locomo_frontlight_set(locomolcd_dev, 117, 0, 161); break;
+	case 2: locomo_frontlight_set(locomolcd_dev, 163, 0, 148); break;
+	case 3: locomo_frontlight_set(locomolcd_dev, 194, 0, 161); break;
+	case 4: locomo_frontlight_set(locomolcd_dev, 194, 1, 161); break;
+
+	default:
+		return -ENODEV;
+	}
+	current_intensity = intensity;
+	return 0;
+}
+
+static int locomolcd_get_intensity(struct backlight_device *bd)
+{
+	return current_intensity;
+}
+
+static struct backlight_properties locomobl_data = {
+	.owner		= THIS_MODULE,
+	.get_brightness = locomolcd_get_intensity,
+	.update_status  = locomolcd_set_intensity,
+	.max_brightness = 4,
+};
+
+#ifdef CONFIG_PM
+static int locomolcd_suspend(struct locomo_dev *dev, pm_message_t state)
+{
+	locomolcd_flags |= LOCOMOLCD_SUSPENDED;
+	locomolcd_set_intensity(locomolcd_bl_device);
+	return 0;
+}
+
+static int locomolcd_resume(struct locomo_dev *dev)
+{
+	locomolcd_flags &= ~LOCOMOLCD_SUSPENDED;
+	locomolcd_set_intensity(locomolcd_bl_device);
+	return 0;
+}
+#else
+#define locomolcd_suspend	NULL
+#define locomolcd_resume	NULL
+#endif
+
+static int locomolcd_probe(struct locomo_dev *dev)
 {
 	unsigned long flags;
 
 	local_irq_save(flags);
 	locomolcd_dev = dev;
 
+	locomo_gpio_set_dir(dev, LOCOMO_GPIO_FL_VR, 0);
+
 	/* the poodle_lcd_power function is called for the first time
 	 * from fs_initcall, which is before locomo is activated.
 	 * We need to recall poodle_lcd_power here*/
-#ifdef CONFIG_MACH_POODLE
-	locomolcd_power(1);
-#endif
+	if (machine_is_poodle())
+		locomolcd_power(1);
+
 	local_irq_restore(flags);
+
+	locomolcd_bl_device = backlight_device_register("locomo-bl", NULL, &locomobl_data);
+
+	if (IS_ERR (locomolcd_bl_device))
+		return PTR_ERR (locomolcd_bl_device);
+
+	/* Set up frontlight so that screen is readable */
+	locomobl_data.brightness = 2;
+	locomolcd_set_intensity(locomolcd_bl_device);
+
 	return 0;
 }
 
-static int poodle_lcd_remove(struct locomo_dev *dev)
+static int locomolcd_remove(struct locomo_dev *dev)
 {
 	unsigned long flags;
+
+	backlight_device_unregister(locomolcd_bl_device);
 	local_irq_save(flags);
 	locomolcd_dev = NULL;
 	local_irq_restore(flags);
@@ -136,19 +213,33 @@
 		.name = "locomo-backlight",
 	},
 	.devid	= LOCOMO_DEVID_BACKLIGHT,
-	.probe	= poodle_lcd_probe,
-	.remove	= poodle_lcd_remove,
+	.probe	= locomolcd_probe,
+	.remove	= locomolcd_remove,
+	.suspend = locomolcd_suspend,
+	.resume = locomolcd_resume,
 };
 
-static int __init poodle_lcd_init(void)
+
+static int __init locomolcd_init(void)
 {
 	int ret = locomo_driver_register(&poodle_lcd_driver);
-	if (ret) return ret;
+	if (ret)
+		return ret;
 
 #ifdef CONFIG_SA1100_COLLIE
 	sa1100fb_lcd_power = locomolcd_power;
 #endif
 	return 0;
 }
-device_initcall(poodle_lcd_init);
 
+static void __exit locomolcd_exit(void)
+{
+	locomo_driver_unregister(&poodle_lcd_driver);
+}
+
+module_init(locomolcd_init);
+module_exit(locomolcd_exit);
+
+MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>, Pavel Machek <pavel@suse.cz>");
+MODULE_DESCRIPTION("Collie LCD driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 8ba6152..ad8a89b 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -230,6 +230,7 @@
 		tab = cfb_tab16;
 		break;
 	case 32:
+	default:
 		tab = cfb_tab32;
 		break;
 	}
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 72ff6bf..d76bbfac 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -148,9 +148,24 @@
 static int chipsfb_blank(int blank, struct fb_info *info)
 {
 #ifdef CONFIG_PMAC_BACKLIGHT
-	// used to disable backlight only for blank > 1, but it seems
-	// useful at blank = 1 too (saves battery, extends backlight life)
-	set_backlight_enable(!blank);
+	mutex_lock(&pmac_backlight_mutex);
+
+	if (pmac_backlight) {
+		down(&pmac_backlight->sem);
+
+		/* used to disable backlight only for blank > 1, but it seems
+		 * useful at blank = 1 too (saves battery, extends backlight
+		 * life)
+	 	 */
+		if (blank)
+			pmac_backlight->props->power = FB_BLANK_POWERDOWN;
+		else
+			pmac_backlight->props->power = FB_BLANK_UNBLANK;
+		pmac_backlight->props->update_status(pmac_backlight);
+		up(&pmac_backlight->sem);
+	}
+
+	mutex_unlock(&pmac_backlight_mutex);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
 	return 1;	/* get fb_blank to set the colormap to all black */
@@ -401,7 +416,14 @@
 
 #ifdef CONFIG_PMAC_BACKLIGHT
 	/* turn on the backlight */
-	set_backlight_enable(1);
+	mutex_lock(&pmac_backlight_mutex);
+	if (pmac_backlight) {
+		down(&pmac_backlight->sem);
+		pmac_backlight->props->power = FB_BLANK_UNBLANK;
+		pmac_backlight->props->update_status(pmac_backlight);
+		up(&pmac_backlight->sem);
+	}
+	mutex_unlock(&pmac_backlight_mutex);
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
 #ifdef CONFIG_PPC
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 1103010..dda240e 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -2227,7 +2227,6 @@
 		release_region(0x3C0, 32);
 	pci_release_regions(pdev);
 	framebuffer_release(cinfo->info);
-	pci_disable_device(pdev);
 }
 #endif /* CONFIG_PCI */
 
@@ -2458,7 +2457,6 @@
 err_release_fb:
 	framebuffer_release(info);
 err_disable:
-	pci_disable_device(pdev);
 err_out:
 	return ret;
 }
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 47ba1a7..5dc4083 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -125,6 +125,8 @@
 static int first_fb_vc;
 static int last_fb_vc = MAX_NR_CONSOLES - 1;
 static int fbcon_is_default = 1; 
+static int fbcon_has_exited;
+
 /* font data */
 static char fontname[40];
 
@@ -140,7 +142,6 @@
 
 #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row)
 
-static void fbcon_free_font(struct display *);
 static int fbcon_set_origin(struct vc_data *);
 
 #define CURSOR_DRAW_DELAY		(1)
@@ -194,6 +195,9 @@
 			      int line, int count, int dy);
 static void fbcon_modechanged(struct fb_info *info);
 static void fbcon_set_all_vcs(struct fb_info *info);
+static void fbcon_start(void);
+static void fbcon_exit(void);
+static struct class_device *fbcon_class_device;
 
 #ifdef CONFIG_MAC
 /*
@@ -252,7 +256,7 @@
 	if (!ops || ops->currcon < 0 || rotate > 3)
 		return;
 
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		vc = vc_cons[i].d;
 		if (!vc || vc->vc_mode != KD_TEXT ||
 		    registered_fb[con2fb_map[i]] != info)
@@ -389,15 +393,18 @@
 	int c;
 	int mode;
 
-	if (ops->currcon != -1)
+	acquire_console_sem();
+	if (ops && ops->currcon != -1)
 		vc = vc_cons[ops->currcon].d;
 
 	if (!vc || !CON_IS_VISIBLE(vc) ||
 	    fbcon_is_inactive(vc, info) ||
  	    registered_fb[con2fb_map[vc->vc_num]] != info ||
-	    vc_cons[ops->currcon].d->vc_deccm != 1)
+	    vc_cons[ops->currcon].d->vc_deccm != 1) {
+		release_console_sem();
 		return;
-	acquire_console_sem();
+	}
+
 	p = &fb_display[vc->vc_num];
 	c = scr_readw((u16 *) vc->vc_pos);
 	mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
@@ -528,7 +535,7 @@
 {
 	int i, retval = 0;
 
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (con2fb_map[i] == idx)
 			retval = 1;
 	}
@@ -539,7 +546,7 @@
 {
 	int i, retval = 0;
 
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (con2fb_map[i] != -1)
 			retval = 1;
 	}
@@ -561,6 +568,7 @@
 
 	err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,
 				fbcon_is_default);
+
 	if (err) {
 		for (i = first_fb_vc; i <= last_fb_vc; i++) {
 			con2fb_map[i] = -1;
@@ -795,8 +803,8 @@
 	if (oldidx == newidx)
 		return 0;
 
-	if (!info)
- 		err =  -EINVAL;
+	if (!info || fbcon_has_exited)
+		return -EINVAL;
 
  	if (!err && !search_for_mapped_con()) {
 		info_idx = newidx;
@@ -832,6 +840,9 @@
  		con2fb_init_display(vc, info, unit, show_logo);
 	}
 
+	if (!search_fb_in_map(info_idx))
+		info_idx = newidx;
+
 	release_console_sem();
  	return err;
 }
@@ -1034,6 +1045,7 @@
 #endif				/* CONFIG_MAC */
 
 	fbcon_add_cursor_timer(info);
+	fbcon_has_exited = 0;
 	return display_desc;
 }
 
@@ -1061,17 +1073,36 @@
 
 	/* If we are not the first console on this
 	   fb, copy the font from that console */
-	t = &fb_display[svc->vc_num];
-	if (!vc->vc_font.data) {
-		vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
-		vc->vc_font.width = (*default_mode)->vc_font.width;
-		vc->vc_font.height = (*default_mode)->vc_font.height;
-		p->userfont = t->userfont;
-		if (p->userfont)
-			REFCOUNT(p->fontdata)++;
+	t = &fb_display[fg_console];
+	if (!p->fontdata) {
+		if (t->fontdata) {
+			struct vc_data *fvc = vc_cons[fg_console].d;
+
+			vc->vc_font.data = (void *)(p->fontdata =
+						    fvc->vc_font.data);
+			vc->vc_font.width = fvc->vc_font.width;
+			vc->vc_font.height = fvc->vc_font.height;
+			p->userfont = t->userfont;
+
+			if (p->userfont)
+				REFCOUNT(p->fontdata)++;
+		} else {
+			const struct font_desc *font = NULL;
+
+			if (!fontname[0] || !(font = find_font(fontname)))
+				font = get_default_font(info->var.xres,
+							info->var.yres);
+			vc->vc_font.width = font->width;
+			vc->vc_font.height = font->height;
+			vc->vc_font.data = (void *)(p->fontdata = font->data);
+			vc->vc_font.charcount = 256; /* FIXME  Need to
+							support more fonts */
+		}
 	}
+
 	if (p->userfont)
 		charcnt = FNTCHARCNT(p->fontdata);
+
 	vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	if (charcnt == 256) {
@@ -1145,13 +1176,47 @@
 	ops->p = &fb_display[fg_console];
 }
 
+static void fbcon_free_font(struct display *p)
+{
+	if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
+		kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
+	p->fontdata = NULL;
+	p->userfont = 0;
+}
+
 static void fbcon_deinit(struct vc_data *vc)
 {
 	struct display *p = &fb_display[vc->vc_num];
+	struct fb_info *info;
+	struct fbcon_ops *ops;
+	int idx;
 
-	if (info_idx != -1)
-	    return;
 	fbcon_free_font(p);
+	idx = con2fb_map[vc->vc_num];
+
+	if (idx == -1)
+		goto finished;
+
+	info = registered_fb[idx];
+
+	if (!info)
+		goto finished;
+
+	ops = info->fbcon_par;
+
+	if (!ops)
+		goto finished;
+
+	if (CON_IS_VISIBLE(vc))
+		fbcon_del_cursor_timer(info);
+
+	ops->flags &= ~FBCON_FLAGS_INIT;
+finished:
+
+	if (!con_is_bound(&fb_con))
+		fbcon_exit();
+
+	return;
 }
 
 /* ====================================================================== */
@@ -2099,12 +2164,11 @@
 		if (info->fbops->fb_set_par)
 			info->fbops->fb_set_par(info);
 
-		if (old_info != info) {
+		if (old_info != info)
 			fbcon_del_cursor_timer(old_info);
-			fbcon_add_cursor_timer(info);
-		}
 	}
 
+	fbcon_add_cursor_timer(info);
 	set_blitting_type(vc, info);
 	ops->cursor_reset = 1;
 
@@ -2222,14 +2286,6 @@
 	return 0;
 }
 
-static void fbcon_free_font(struct display *p)
-{
-	if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
-		kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
-	p->fontdata = NULL;
-	p->userfont = 0;
-}
-
 static int fbcon_get_font(struct vc_data *vc, struct console_font *font)
 {
 	u8 *fontdata = vc->vc_font.data;
@@ -2443,7 +2499,7 @@
 
 	FNTSUM(new_data) = csum;
 	/* Check if the same font is on some other console already */
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		struct vc_data *tmp = vc_cons[i].d;
 		
 		if (fb_display[i].userfont &&
@@ -2768,7 +2824,7 @@
 	if (!ops || ops->currcon < 0)
 		return;
 
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		vc = vc_cons[i].d;
 		if (!vc || vc->vc_mode != KD_TEXT ||
 		    registered_fb[con2fb_map[i]] != info)
@@ -2830,22 +2886,57 @@
 	return found;
 }
 
+static int fbcon_fb_unregistered(int idx)
+{
+	int i;
+
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
+		if (con2fb_map[i] == idx)
+			con2fb_map[i] = -1;
+	}
+
+	if (idx == info_idx) {
+		info_idx = -1;
+
+		for (i = 0; i < FB_MAX; i++) {
+			if (registered_fb[i] != NULL) {
+				info_idx = i;
+				break;
+			}
+		}
+	}
+
+	if (info_idx != -1) {
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
+			if (con2fb_map[i] == -1)
+				con2fb_map[i] = info_idx;
+		}
+	}
+
+	if (!num_registered_fb)
+		unregister_con_driver(&fb_con);
+
+	return 0;
+}
+
 static int fbcon_fb_registered(int idx)
 {
 	int ret = 0, i;
 
 	if (info_idx == -1) {
-		for (i = 0; i < MAX_NR_CONSOLES; i++) {
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
 			if (con2fb_map_boot[i] == idx) {
 				info_idx = idx;
 				break;
 			}
 		}
+
 		if (info_idx != -1)
 			ret = fbcon_takeover(1);
 	} else {
-		for (i = 0; i < MAX_NR_CONSOLES; i++) {
-			if (con2fb_map_boot[i] == idx)
+		for (i = first_fb_vc; i <= last_fb_vc; i++) {
+			if (con2fb_map_boot[i] == idx &&
+			    con2fb_map[i] == -1)
 				set_con2fb_map(i, idx, 0);
 		}
 	}
@@ -2882,7 +2973,7 @@
 	struct fb_var_screeninfo var;
 	struct fb_videomode *mode;
 
-	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+	for (i = first_fb_vc; i <= last_fb_vc; i++) {
 		if (registered_fb[con2fb_map[i]] != info)
 			continue;
 		if (!fb_display[i].mode)
@@ -2910,6 +3001,14 @@
 	struct fb_con2fbmap *con2fb;
 	int ret = 0;
 
+	/*
+	 * ignore all events except driver registration and deregistration
+	 * if fbcon is not active
+	 */
+	if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED ||
+				  action == FB_EVENT_FB_UNREGISTERED))
+		goto done;
+
 	switch(action) {
 	case FB_EVENT_SUSPEND:
 		fbcon_suspended(info);
@@ -2930,6 +3029,9 @@
 	case FB_EVENT_FB_REGISTERED:
 		ret = fbcon_fb_registered(info->node);
 		break;
+	case FB_EVENT_FB_UNREGISTERED:
+		ret = fbcon_fb_unregistered(info->node);
+		break;
 	case FB_EVENT_SET_CONSOLE_MAP:
 		con2fb = event->data;
 		ret = set_con2fb_map(con2fb->console - 1,
@@ -2945,16 +3047,9 @@
 	case FB_EVENT_NEW_MODELIST:
 		fbcon_new_modelist(info);
 		break;
-	case FB_EVENT_SET_CON_ROTATE:
-		fbcon_rotate(info, *(int *)event->data);
-		break;
-	case FB_EVENT_GET_CON_ROTATE:
-		ret = fbcon_get_rotate(info);
-		break;
-	case FB_EVENT_SET_CON_ROTATE_ALL:
-		fbcon_rotate_all(info, *(int *)event->data);
 	}
 
+done:
 	return ret;
 }
 
@@ -2992,27 +3087,181 @@
 	.notifier_call	= fbcon_event_notify,
 };
 
-static int __init fb_console_init(void)
+static ssize_t store_rotate(struct class_device *class_device,
+			    const char *buf, size_t count)
+{
+	struct fb_info *info;
+	int rotate, idx;
+	char **last = NULL;
+
+	if (fbcon_has_exited)
+		return count;
+
+	acquire_console_sem();
+	idx = con2fb_map[fg_console];
+
+	if (idx == -1 || registered_fb[idx] == NULL)
+		goto err;
+
+	info = registered_fb[idx];
+	rotate = simple_strtoul(buf, last, 0);
+	fbcon_rotate(info, rotate);
+err:
+	release_console_sem();
+	return count;
+}
+
+static ssize_t store_rotate_all(struct class_device *class_device,
+				const char *buf, size_t count)
+{
+	struct fb_info *info;
+	int rotate, idx;
+	char **last = NULL;
+
+	if (fbcon_has_exited)
+		return count;
+
+	acquire_console_sem();
+	idx = con2fb_map[fg_console];
+
+	if (idx == -1 || registered_fb[idx] == NULL)
+		goto err;
+
+	info = registered_fb[idx];
+	rotate = simple_strtoul(buf, last, 0);
+	fbcon_rotate_all(info, rotate);
+err:
+	release_console_sem();
+	return count;
+}
+
+static ssize_t show_rotate(struct class_device *class_device, char *buf)
+{
+	struct fb_info *info;
+	int rotate = 0, idx;
+
+	if (fbcon_has_exited)
+		return 0;
+
+	acquire_console_sem();
+	idx = con2fb_map[fg_console];
+
+	if (idx == -1 || registered_fb[idx] == NULL)
+		goto err;
+
+	info = registered_fb[idx];
+	rotate = fbcon_get_rotate(info);
+err:
+	release_console_sem();
+	return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
+}
+
+static struct class_device_attribute class_device_attrs[] = {
+	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
+	__ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all),
+};
+
+static int fbcon_init_class_device(void)
 {
 	int i;
 
-	acquire_console_sem();
-	fb_register_client(&fbcon_event_notifier);
-	release_console_sem();
+	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+		class_device_create_file(fbcon_class_device,
+					 &class_device_attrs[i]);
+	return 0;
+}
 
-	for (i = 0; i < MAX_NR_CONSOLES; i++)
-		con2fb_map[i] = -1;
-
+static void fbcon_start(void)
+{
 	if (num_registered_fb) {
+		int i;
+
+		acquire_console_sem();
+
 		for (i = 0; i < FB_MAX; i++) {
 			if (registered_fb[i] != NULL) {
 				info_idx = i;
 				break;
 			}
 		}
+
+		release_console_sem();
 		fbcon_takeover(0);
 	}
+}
 
+static void fbcon_exit(void)
+{
+	struct fb_info *info;
+	int i, j, mapped;
+
+	if (fbcon_has_exited)
+		return;
+
+#ifdef CONFIG_ATARI
+	free_irq(IRQ_AUTO_4, fbcon_vbl_handler);
+#endif
+#ifdef CONFIG_MAC
+	if (MACH_IS_MAC && vbl_detected)
+		free_irq(IRQ_MAC_VBL, fbcon_vbl_handler);
+#endif
+
+	kfree((void *)softback_buf);
+	softback_buf = 0UL;
+
+	for (i = 0; i < FB_MAX; i++) {
+		mapped = 0;
+		info = registered_fb[i];
+
+		if (info == NULL)
+			continue;
+
+		for (j = first_fb_vc; j <= last_fb_vc; j++) {
+			if (con2fb_map[j] == i)
+				mapped = 1;
+		}
+
+		if (mapped) {
+			if (info->fbops->fb_release)
+				info->fbops->fb_release(info, 0);
+			module_put(info->fbops->owner);
+
+			if (info->fbcon_par) {
+				fbcon_del_cursor_timer(info);
+				kfree(info->fbcon_par);
+				info->fbcon_par = NULL;
+			}
+
+			if (info->queue.func == fb_flashcursor)
+				info->queue.func = NULL;
+		}
+	}
+
+	fbcon_has_exited = 1;
+}
+
+static int __init fb_console_init(void)
+{
+	int i;
+
+	acquire_console_sem();
+	fb_register_client(&fbcon_event_notifier);
+	fbcon_class_device =
+	    class_device_create(fb_class, NULL, MKDEV(0, 0), NULL, "fbcon");
+
+	if (IS_ERR(fbcon_class_device)) {
+		printk(KERN_WARNING "Unable to create class_device "
+		       "for fbcon; errno = %ld\n",
+		       PTR_ERR(fbcon_class_device));
+		fbcon_class_device = NULL;
+	} else
+		fbcon_init_class_device();
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++)
+		con2fb_map[i] = -1;
+
+	release_console_sem();
+	fbcon_start();
 	return 0;
 }
 
@@ -3020,12 +3269,24 @@
 
 #ifdef MODULE
 
+static void __exit fbcon_deinit_class_device(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+		class_device_remove_file(fbcon_class_device,
+					 &class_device_attrs[i]);
+}
+
 static void __exit fb_console_exit(void)
 {
 	acquire_console_sem();
 	fb_unregister_client(&fbcon_event_notifier);
+	fbcon_deinit_class_device();
+	class_device_destroy(fb_class, MKDEV(0, 0));
+	fbcon_exit();
 	release_console_sem();
-	give_up_console(&fb_con);
+	unregister_con_driver(&fb_con);
 }	
 
 module_exit(fb_console_exit);
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index c38c3d8..3487a636 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -175,6 +175,7 @@
 #endif
 extern void fbcon_set_bitops(struct fbcon_ops *ops);
 extern int  soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
+extern struct class *fb_class;
 
 #define FBCON_ATTRIBUTE_UNDERLINE 1
 #define FBCON_ATTRIBUTE_REVERSE   2
diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
index 989e4d4..c89f90ed 100644
--- a/drivers/video/console/mdacon.c
+++ b/drivers/video/console/mdacon.c
@@ -308,13 +308,13 @@
 	outb_p(0x00, mda_gfx_port);
 }
 
-static const char __init *mdacon_startup(void)
+static const char *mdacon_startup(void)
 {
 	mda_num_columns = 80;
 	mda_num_lines   = 25;
 
-	mda_vram_base = VGA_MAP_MEM(0xb0000);
 	mda_vram_len  = 0x01000;
+	mda_vram_base = VGA_MAP_MEM(0xb0000, mda_vram_len);
 
 	mda_index_port  = 0x3b4;
 	mda_value_port  = 0x3b5;
diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c
index e99fe30..0304131 100644
--- a/drivers/video/console/newport_con.c
+++ b/drivers/video/console/newport_con.c
@@ -51,6 +51,7 @@
 static int xcurs_correction = 29;
 static int newport_xsize;
 static int newport_ysize;
+static int newport_has_init;
 
 static int newport_set_def_font(int unit, struct console_font *op);
 
@@ -283,6 +284,15 @@
 		xcurs_correction = 21;
 }
 
+static void newport_exit(void)
+{
+	int i;
+
+	/* free memory used by user font */
+	for (i = 0; i < MAX_NR_CONSOLES; i++)
+		newport_set_def_font(i, NULL);
+}
+
 /* Can't be __init, take_over_console may call it later */
 static const char *newport_startup(void)
 {
@@ -290,8 +300,10 @@
 
 	if (!sgi_gfxaddr)
 		return NULL;
-	npregs = (struct newport_regs *)	/* ioremap cannot fail */
-		 ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
+
+	if (!npregs)
+		npregs = (struct newport_regs *)/* ioremap cannot fail */
+			ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
 	npregs->cset.config = NPORT_CFG_GD0;
 
 	if (newport_wait(npregs))
@@ -307,11 +319,11 @@
 	newport_reset();
 	newport_get_revisions();
 	newport_get_screensize();
+	newport_has_init = 1;
 
 	return "SGI Newport";
 
 out_unmap:
-	iounmap((void *)npregs);
 	return NULL;
 }
 
@@ -324,11 +336,10 @@
 
 static void newport_deinit(struct vc_data *c)
 {
-	int i;
-
-	/* free memory used by user font */
-	for (i = 0; i < MAX_NR_CONSOLES; i++)
-		newport_set_def_font(i, NULL);
+	if (!con_is_bound(&newport_con) && newport_has_init) {
+		newport_exit();
+		newport_has_init = 0;
+	}
 }
 
 static void newport_clear(struct vc_data *vc, int sy, int sx, int height,
@@ -728,16 +739,23 @@
 #ifdef MODULE
 static int __init newport_console_init(void)
 {
+
+	if (!sgi_gfxaddr)
+		return NULL;
+
+	if (!npregs)
+		npregs = (struct newport_regs *)/* ioremap cannot fail */
+			ioremap(sgi_gfxaddr, sizeof(struct newport_regs));
+
 	return take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1);
 }
+module_init(newport_console_init);
 
 static void __exit newport_console_exit(void)
 {
 	give_up_console(&newport_con);
 	iounmap((void *)npregs);
 }
-
-module_init(newport_console_init);
 module_exit(newport_console_exit);
 #endif
 
diff --git a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c
index 04f42fc..d6e6ad5 100644
--- a/drivers/video/console/promcon.c
+++ b/drivers/video/console/promcon.c
@@ -109,7 +109,7 @@
 	return b - p;
 }
 
-const char __init *promcon_startup(void)
+const char *promcon_startup(void)
 {
 	const char *display_desc = "PROM";
 	int node;
@@ -133,7 +133,7 @@
 	return display_desc;
 }
 
-static void __init 
+static void
 promcon_init_unimap(struct vc_data *conp)
 {
 	mm_segment_t old_fs = get_fs();
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
index fd5940f..45c4f22 100644
--- a/drivers/video/console/sticon.c
+++ b/drivers/video/console/sticon.c
@@ -75,7 +75,7 @@
     cursor_drawn = 0;
 }
 
-static const char *__init sticon_startup(void)
+static const char *sticon_startup(void)
 {
     return "STI console";
 }
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index d5a04b6..f32b590 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -114,6 +114,7 @@
 static int 		vga_video_font_height;
 static int 		vga_scan_lines;
 static unsigned int 	vga_rolled_over = 0;
+static int              vga_init_done;
 
 static int __init no_scroll(char *str)
 {
@@ -190,7 +191,7 @@
 	}
 }
 
-static void __init vgacon_scrollback_startup(void)
+static void vgacon_scrollback_startup(void)
 {
 	vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
 					  * 1024);
@@ -355,7 +356,7 @@
 }
 #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
 
-static const char __init *vgacon_startup(void)
+static const char *vgacon_startup(void)
 {
 	const char *display_desc = NULL;
 	u16 saved1, saved2;
@@ -391,7 +392,7 @@
 			static struct resource ega_console_resource =
 			    { "ega", 0x3B0, 0x3BF };
 			vga_video_type = VIDEO_TYPE_EGAM;
-			vga_vram_end = 0xb8000;
+			vga_vram_size = 0x8000;
 			display_desc = "EGA+";
 			request_resource(&ioport_resource,
 					 &ega_console_resource);
@@ -401,7 +402,7 @@
 			static struct resource mda2_console_resource =
 			    { "mda", 0x3BF, 0x3BF };
 			vga_video_type = VIDEO_TYPE_MDA;
-			vga_vram_end = 0xb2000;
+			vga_vram_size = 0x2000;
 			display_desc = "*MDA";
 			request_resource(&ioport_resource,
 					 &mda1_console_resource);
@@ -418,7 +419,7 @@
 		if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
 			int i;
 
-			vga_vram_end = 0xc0000;
+			vga_vram_size = 0x8000;
 
 			if (!ORIG_VIDEO_ISVGA) {
 				static struct resource ega_console_resource
@@ -443,7 +444,7 @@
 				 * and COE=1 isn't necessarily a good idea)
 				 */
 				vga_vram_base = 0xa0000;
-				vga_vram_end = 0xb0000;
+				vga_vram_size = 0x10000;
 				outb_p(6, VGA_GFX_I);
 				outb_p(6, VGA_GFX_D);
 #endif
@@ -475,7 +476,7 @@
 			static struct resource cga_console_resource =
 			    { "cga", 0x3D4, 0x3D5 };
 			vga_video_type = VIDEO_TYPE_CGA;
-			vga_vram_end = 0xba000;
+			vga_vram_size = 0x2000;
 			display_desc = "*CGA";
 			request_resource(&ioport_resource,
 					 &cga_console_resource);
@@ -483,9 +484,8 @@
 		}
 	}
 
-	vga_vram_base = VGA_MAP_MEM(vga_vram_base);
-	vga_vram_end = VGA_MAP_MEM(vga_vram_end);
-	vga_vram_size = vga_vram_end - vga_vram_base;
+	vga_vram_base = VGA_MAP_MEM(vga_vram_base, vga_vram_size);
+	vga_vram_end = vga_vram_base + vga_vram_size;
 
 	/*
 	 *      Find out if there is a graphics card present.
@@ -524,7 +524,12 @@
 
 	vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
 	vgacon_yres = vga_scan_lines;
-	vgacon_scrollback_startup();
+
+	if (!vga_init_done) {
+		vgacon_scrollback_startup();
+		vga_init_done = 1;
+	}
+
 	return display_desc;
 }
 
@@ -532,10 +537,20 @@
 {
 	unsigned long p;
 
-	/* We cannot be loaded as a module, therefore init is always 1 */
+	/*
+	 * We cannot be loaded as a module, therefore init is always 1,
+	 * but vgacon_init can be called more than once, and init will
+	 * not be 1.
+	 */
 	c->vc_can_do_color = vga_can_do_color;
-	c->vc_cols = vga_video_num_columns;
-	c->vc_rows = vga_video_num_lines;
+
+	/* set dimensions manually if init != 0 since vc_resize() will fail */
+	if (init) {
+		c->vc_cols = vga_video_num_columns;
+		c->vc_rows = vga_video_num_lines;
+	} else
+		vc_resize(c, vga_video_num_columns, vga_video_num_lines);
+
 	c->vc_scan_lines = vga_scan_lines;
 	c->vc_font.height = vga_video_font_height;
 	c->vc_complement_mask = 0x7700;
@@ -1020,14 +1035,14 @@
 	char *charmap;
 	
 	if (vga_video_type != VIDEO_TYPE_EGAM) {
-		charmap = (char *) VGA_MAP_MEM(colourmap);
+		charmap = (char *) VGA_MAP_MEM(colourmap, 0);
 		beg = 0x0e;
 #ifdef VGA_CAN_DO_64KB
 		if (vga_video_type == VIDEO_TYPE_VGAC)
 			beg = 0x06;
 #endif
 	} else {
-		charmap = (char *) VGA_MAP_MEM(blackwmap);
+		charmap = (char *) VGA_MAP_MEM(blackwmap, 0);
 		beg = 0x0a;
 	}
 
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 0827594..f0a621e 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -605,11 +605,6 @@
 		fb_writeb(0, dst);
 }
 
-static void epson1355fb_platform_release(struct device *device)
-{
-	dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n");
-}
-
 static int epson1355fb_remove(struct platform_device *dev)
 {
 	struct fb_info *info = platform_get_drvdata(dev);
@@ -733,13 +728,7 @@
 	},
 };
 
-static struct platform_device epson1355fb_device = {
-	.name	= "epson1355fb",
-	.id	= 0,
-	.dev	= {
-		.release = epson1355fb_platform_release,
-	}
-};
+static struct platform_device *epson1355fb_device;
 
 int __init epson1355fb_init(void)
 {
@@ -749,11 +738,21 @@
 		return -ENODEV;
 
 	ret = platform_driver_register(&epson1355fb_driver);
+
 	if (!ret) {
-		ret = platform_device_register(&epson1355fb_device);
-		if (ret)
+		epson1355fb_device = platform_device_alloc("epson1355fb", 0);
+
+		if (epson1355fb_device)
+			ret = platform_device_add(epson1355fb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(epson1355fb_device);
 			platform_driver_unregister(&epson1355fb_driver);
+		}
 	}
+
 	return ret;
 }
 
@@ -762,7 +761,7 @@
 #ifdef MODULE
 static void __exit epson1355fb_exit(void)
 {
-	platform_device_unregister(&epson1355fb_device);
+	platform_device_unregister(epson1355fb_device);
 	platform_driver_unregister(&epson1355fb_driver);
 }
 
diff --git a/drivers/video/fbcvt.c b/drivers/video/fbcvt.c
index ac90883..b549899 100644
--- a/drivers/video/fbcvt.c
+++ b/drivers/video/fbcvt.c
@@ -376,4 +376,3 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(fb_find_mode_cvt);
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 372aa17..31143af 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -34,7 +34,6 @@
 #endif
 #include <linux/devfs_fs_kernel.h>
 #include <linux/err.h>
-#include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/efi.h>
 
@@ -162,7 +161,6 @@
 }
 
 #ifdef CONFIG_LOGO
-#include <linux/linux_logo.h>
 
 static inline unsigned safe_shift(unsigned d, int n)
 {
@@ -336,11 +334,11 @@
 
 static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
 {
-	int i, j, w = width - 1;
+	int i, j, h = height - 1;
 
 	for (i = 0; i < height; i++)
 		for (j = 0; j < width; j++)
-			out[height * j + w - i] = *in++;
+				out[height * j + h - i] = *in++;
 }
 
 static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
@@ -358,24 +356,24 @@
 	u32 tmp;
 
 	if (rotate == FB_ROTATE_UD) {
-		image->dx = info->var.xres - image->width;
-		image->dy = info->var.yres - image->height;
 		fb_rotate_logo_ud(image->data, dst, image->width,
 				  image->height);
+		image->dx = info->var.xres - image->width;
+		image->dy = info->var.yres - image->height;
 	} else if (rotate == FB_ROTATE_CW) {
-		tmp = image->width;
-		image->width = image->height;
-		image->height = tmp;
-		image->dx = info->var.xres - image->height;
 		fb_rotate_logo_cw(image->data, dst, image->width,
 				  image->height);
-	} else if (rotate == FB_ROTATE_CCW) {
 		tmp = image->width;
 		image->width = image->height;
 		image->height = tmp;
-		image->dy = info->var.yres - image->width;
+		image->dx = info->var.xres - image->width;
+	} else if (rotate == FB_ROTATE_CCW) {
 		fb_rotate_logo_ccw(image->data, dst, image->width,
 				   image->height);
+		tmp = image->width;
+		image->width = image->height;
+		image->height = tmp;
+		image->dy = info->var.yres - image->height;
 	}
 
 	image->data = dst;
@@ -435,7 +433,7 @@
 			depth = info->var.green.length;
 	}
 
-	if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
+	if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {
 		/* assume console colormap */
 		depth = 4;
 	}
@@ -1278,8 +1276,8 @@
 #endif
 };
 
-static struct class *fb_class;
-
+struct class *fb_class;
+EXPORT_SYMBOL(fb_class);
 /**
  *	register_framebuffer - registers a frame buffer device
  *	@fb_info: frame buffer info structure
@@ -1355,6 +1353,7 @@
 int
 unregister_framebuffer(struct fb_info *fb_info)
 {
+	struct fb_event event;
 	int i;
 
 	i = fb_info->node;
@@ -1362,13 +1361,17 @@
 		return -EINVAL;
 	devfs_remove("fb/%d", i);
 
-	if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
+	if (fb_info->pixmap.addr &&
+	    (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
 		kfree(fb_info->pixmap.addr);
 	fb_destroy_modelist(&fb_info->modelist);
 	registered_fb[i]=NULL;
 	num_registered_fb--;
 	fb_cleanup_class_device(fb_info);
 	class_device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+	event.info = fb_info;
+	blocking_notifier_call_chain(&fb_notifier_list,
+				     FB_EVENT_FB_UNREGISTERED, &event);
 	return 0;
 }
 
@@ -1491,28 +1494,6 @@
 	return err;
 }
 
-/**
- * fb_con_duit - user<->fbcon passthrough
- * @info: struct fb_info
- * @event: notification event to be passed to fbcon
- * @data: private data
- *
- * DESCRIPTION
- * This function is an fbcon-user event passing channel
- * which bypasses fbdev.  This is hopefully temporary
- * until a user interface for fbcon is created
- */
-int fb_con_duit(struct fb_info *info, int event, void *data)
-{
-	struct fb_event evnt;
-
-	evnt.info = info;
-	evnt.data = data;
-
-	return blocking_notifier_call_chain(&fb_notifier_list, event, &evnt);
-}
-EXPORT_SYMBOL(fb_con_duit);
-
 static char *video_options[FB_MAX];
 static int ofonly;
 
@@ -1622,6 +1603,5 @@
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
 EXPORT_SYMBOL(fb_get_options);
-EXPORT_SYMBOL(fb_new_modelist);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 53beeb4..3ccfff7 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -29,9 +29,9 @@
 #include <linux/tty.h>
 #include <linux/fb.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <video/edid.h>
 #ifdef CONFIG_PPC_OF
-#include <linux/pci.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #endif
@@ -605,6 +605,7 @@
 	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
 
 	DPRINTK("      Monitor Operating Limits: ");
+
 	for (i = 0; i < 4; i++, block += DETAILED_TIMING_DESCRIPTION_SIZE) {
 		if (edid_is_limits_block(block)) {
 			specs->hfmin = H_MIN_RATE * 1000;
@@ -618,11 +619,12 @@
 			break;
 		}
 	}
-	
+
 	/* estimate monitor limits based on modes supported */
 	if (retval) {
-		struct fb_videomode *modes;
+		struct fb_videomode *modes, *mode;
 		int num_modes, i, hz, hscan, pixclock;
+		int vtotal, htotal;
 
 		modes = fb_create_modedb(edid, &num_modes);
 		if (!modes) {
@@ -632,20 +634,38 @@
 
 		retval = 0;
 		for (i = 0; i < num_modes; i++) {
-			hz = modes[i].refresh;
+			mode = &modes[i];
 			pixclock = PICOS2KHZ(modes[i].pixclock) * 1000;
-			hscan = (modes[i].yres * 105 * hz + 5000)/100;
+			htotal = mode->xres + mode->right_margin + mode->hsync_len
+				+ mode->left_margin;
+			vtotal = mode->yres + mode->lower_margin + mode->vsync_len
+				+ mode->upper_margin;
+
+			if (mode->vmode & FB_VMODE_INTERLACED)
+				vtotal /= 2;
+
+			if (mode->vmode & FB_VMODE_DOUBLE)
+				vtotal *= 2;
+
+			hscan = (pixclock + htotal / 2) / htotal;
+			hscan = (hscan + 500) / 1000 * 1000;
+			hz = (hscan + vtotal / 2) / vtotal;
 			
 			if (specs->dclkmax == 0 || specs->dclkmax < pixclock)
 				specs->dclkmax = pixclock;
+
 			if (specs->dclkmin == 0 || specs->dclkmin > pixclock)
 				specs->dclkmin = pixclock;
+
 			if (specs->hfmax == 0 || specs->hfmax < hscan)
 				specs->hfmax = hscan;
+
 			if (specs->hfmin == 0 || specs->hfmin > hscan)
 				specs->hfmin = hscan;
+
 			if (specs->vfmax == 0 || specs->vfmax < hz)
 				specs->vfmax = hz;
+
 			if (specs->vfmin == 0 || specs->vfmin > hz)
 				specs->vfmin = hz;
 		}
@@ -1281,8 +1301,7 @@
 		-EINVAL : 0;
 }
 
-#if defined(CONFIG_FB_FIRMWARE_EDID) && defined(__i386__)
-#include <linux/pci.h>
+#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86)
 
 /*
  * We need to ensure that the EDID block is only returned for
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 34e0739..4f78f23 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -18,6 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/fb.h>
 #include <linux/console.h>
+#include <linux/module.h>
 
 /**
  * framebuffer_alloc - creates a new frame buffer info structure
@@ -55,6 +56,10 @@
 
 	info->device = dev;
 
+#ifdef CONFIG_FB_BACKLIGHT
+	mutex_init(&info->bl_mutex);
+#endif
+
 	return info;
 #undef PADDING
 #undef BYTES_PER_LONG
@@ -95,13 +100,22 @@
 		       const struct fb_videomode *mode)
 {
 	char m = 'U';
+	char v = 'p';
+
 	if (mode->flag & FB_MODE_IS_DETAILED)
 		m = 'D';
 	if (mode->flag & FB_MODE_IS_VESA)
 		m = 'V';
 	if (mode->flag & FB_MODE_IS_STANDARD)
 		m = 'S';
-	return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d-%d\n", m, mode->xres, mode->yres, mode->refresh);
+
+	if (mode->vmode & FB_VMODE_INTERLACED)
+		v = 'i';
+	if (mode->vmode & FB_VMODE_DOUBLE)
+		v = 'd';
+
+	return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d%c-%d\n",
+	                m, mode->xres, mode->yres, v, mode->refresh);
 }
 
 static ssize_t store_mode(struct class_device *class_device, const char * buf,
@@ -233,45 +247,6 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate);
 }
 
-static ssize_t store_con_rotate(struct class_device *class_device,
-				const char *buf, size_t count)
-{
-	struct fb_info *fb_info = class_get_devdata(class_device);
-	int rotate;
-	char **last = NULL;
-
-	acquire_console_sem();
-	rotate = simple_strtoul(buf, last, 0);
-	fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE, &rotate);
-	release_console_sem();
-	return count;
-}
-
-static ssize_t store_con_rotate_all(struct class_device *class_device,
-				const char *buf, size_t count)
-{
-	struct fb_info *fb_info = class_get_devdata(class_device);
-	int rotate;
-	char **last = NULL;
-
-	acquire_console_sem();
-	rotate = simple_strtoul(buf, last, 0);
-	fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE_ALL, &rotate);
-	release_console_sem();
-	return count;
-}
-
-static ssize_t show_con_rotate(struct class_device *class_device, char *buf)
-{
-	struct fb_info *fb_info = class_get_devdata(class_device);
-	int rotate;
-
-	acquire_console_sem();
-	rotate = fb_con_duit(fb_info, FB_EVENT_GET_CON_ROTATE, NULL);
-	release_console_sem();
-	return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
-}
-
 static ssize_t store_virtual(struct class_device *class_device,
 			     const char * buf, size_t count)
 {
@@ -414,6 +389,65 @@
 	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
 }
 
+#ifdef CONFIG_FB_BACKLIGHT
+static ssize_t store_bl_curve(struct class_device *class_device,
+		const char *buf, size_t count)
+{
+	struct fb_info *fb_info = class_get_devdata(class_device);
+	u8 tmp_curve[FB_BACKLIGHT_LEVELS];
+	unsigned int i;
+
+	if (count != (FB_BACKLIGHT_LEVELS / 8 * 24))
+		return -EINVAL;
+
+	for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i)
+		if (sscanf(&buf[i * 24],
+			"%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx\n",
+			&tmp_curve[i * 8 + 0],
+			&tmp_curve[i * 8 + 1],
+			&tmp_curve[i * 8 + 2],
+			&tmp_curve[i * 8 + 3],
+			&tmp_curve[i * 8 + 4],
+			&tmp_curve[i * 8 + 5],
+			&tmp_curve[i * 8 + 6],
+			&tmp_curve[i * 8 + 7]) != 8)
+			return -EINVAL;
+
+	/* If there has been an error in the input data, we won't
+	 * reach this loop.
+	 */
+	mutex_lock(&fb_info->bl_mutex);
+	for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
+		fb_info->bl_curve[i] = tmp_curve[i];
+	mutex_unlock(&fb_info->bl_mutex);
+
+	return count;
+}
+
+static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info = class_get_devdata(class_device);
+	ssize_t len = 0;
+	unsigned int i;
+
+	mutex_lock(&fb_info->bl_mutex);
+	for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
+		len += snprintf(&buf[len], PAGE_SIZE,
+				"%02x %02x %02x %02x %02x %02x %02x %02x\n",
+				fb_info->bl_curve[i + 0],
+				fb_info->bl_curve[i + 1],
+				fb_info->bl_curve[i + 2],
+				fb_info->bl_curve[i + 3],
+				fb_info->bl_curve[i + 4],
+				fb_info->bl_curve[i + 5],
+				fb_info->bl_curve[i + 6],
+				fb_info->bl_curve[i + 7]);
+	mutex_unlock(&fb_info->bl_mutex);
+
+	return len;
+}
+#endif
+
 /* When cmap is added back in it should be a binary attribute
  * not a text one. Consideration should also be given to converting
  * fbdev to use configfs instead of sysfs */
@@ -429,9 +463,10 @@
 	__ATTR(name, S_IRUGO, show_name, NULL),
 	__ATTR(stride, S_IRUGO, show_stride, NULL),
 	__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
-	__ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate),
-	__ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all),
 	__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
+#ifdef CONFIG_FB_BACKLIGHT
+	__ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
+#endif
 };
 
 int fb_init_class_device(struct fb_info *fb_info)
@@ -454,4 +489,25 @@
 					 &class_device_attrs[i]);
 }
 
+#ifdef CONFIG_FB_BACKLIGHT
+/* This function generates a linear backlight curve
+ *
+ *     0: off
+ *   1-7: min
+ * 8-127: linear from min to max
+ */
+void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
+{
+	unsigned int i, flat, count, range = (max - min);
 
+	fb_info->bl_curve[0] = off;
+
+	for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
+		fb_info->bl_curve[flat] = min;
+
+	count = FB_BACKLIGHT_LEVELS * 15 / 16;
+	for (i = 0; i < count; ++i)
+		fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
+}
+EXPORT_SYMBOL_GPL(fb_bl_default_curve);
+#endif
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
index 20e6915..4d3a887 100644
--- a/drivers/video/geode/gx1fb_core.c
+++ b/drivers/video/geode/gx1fb_core.c
@@ -376,8 +376,6 @@
 		release_mem_region(gx1_gx_base() + 0x8300, 0x100);
 	}
 
-	pci_disable_device(pdev);
-
 	if (info)
 		framebuffer_release(info);
 	return ret;
@@ -399,7 +397,6 @@
 	iounmap(par->dc_regs);
 	release_mem_region(gx1_gx_base() + 0x8300, 0x100);
 
-	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 
 	framebuffer_release(info);
diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/geode/gxfb_core.c
index 89c34b1..5ef12a3 100644
--- a/drivers/video/geode/gxfb_core.c
+++ b/drivers/video/geode/gxfb_core.c
@@ -354,8 +354,6 @@
 		pci_release_region(pdev, 2);
 	}
 
-	pci_disable_device(pdev);
-
 	if (info)
 		framebuffer_release(info);
 	return ret;
@@ -377,7 +375,6 @@
 	iounmap(par->dc_regs);
 	pci_release_region(pdev, 2);
 
-	pci_disable_device(pdev);
 	pci_set_drvdata(pdev, NULL);
 
 	framebuffer_release(info);
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 44aa2ff..a1f7d80 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -2110,9 +2110,6 @@
 	if (par->res_flags & MMIO_REQ)
 		release_mem_region(par->mmio_start_phys, MMIO_SIZE);
 
-	if (par->res_flags & PCI_DEVICE_ENABLED)
-		pci_disable_device(par->dev);
-
 	framebuffer_release(info);
 
 }
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 6b88050..8a0c2d3 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -232,9 +232,6 @@
 
 	size = vma->vm_end - vma->vm_start;
 
-	/* To stop the swapper from even considering these pages. */
-	vma->vm_flags |= (VM_SHM | VM_LOCKED);
-
 	/* Each page, see which map applies */
 	for (page = 0; page < size; ) {
 		map_size = 0;
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
new file mode 100644
index 0000000..7b1c168
--- /dev/null
+++ b/drivers/video/imacfb.c
@@ -0,0 +1,345 @@
+/*
+ * framebuffer driver for Intel Based Mac's
+ *
+ * (c) 2006 Edgar Hucek <gimli@dark-green.com>
+ * Original imac driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fb.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tty.h>
+
+#include <asm/io.h>
+
+#include <video/vga.h>
+
+typedef enum _MAC_TYPE {
+	M_I17,
+	M_I20,
+	M_MINI,
+	M_MACBOOK,
+	M_NEW
+} MAC_TYPE;
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo imacfb_defined __initdata = {
+	.activate		= FB_ACTIVATE_NOW,
+	.height			= -1,
+	.width			= -1,
+	.right_margin		= 32,
+	.upper_margin		= 16,
+	.lower_margin		= 4,
+	.vsync_len		= 4,
+	.vmode			= FB_VMODE_NONINTERLACED,
+};
+
+static struct fb_fix_screeninfo imacfb_fix __initdata = {
+	.id			= "IMAC VGA",
+	.type			= FB_TYPE_PACKED_PIXELS,
+	.accel			= FB_ACCEL_NONE,
+	.visual			= FB_VISUAL_TRUECOLOR,
+};
+
+static int inverse;
+static int model		= M_NEW;
+static int manual_height;
+static int manual_width;
+
+#define	DEFAULT_FB_MEM	1024*1024*16
+
+/* --------------------------------------------------------------------- */
+
+static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			    unsigned blue, unsigned transp,
+			    struct fb_info *info)
+{
+	/*
+	 *  Set a single color register. The values supplied are
+	 *  already rounded down to the hardware's capabilities
+	 *  (according to the entries in the `var' structure). Return
+	 *  != 0 for invalid regno.
+	 */
+
+	if (regno >= info->cmap.len)
+		return 1;
+
+	if (regno < 16) {
+		red   >>= 8;
+		green >>= 8;
+		blue  >>= 8;
+		((u32 *)(info->pseudo_palette))[regno] =
+			(red   << info->var.red.offset)   |
+			(green << info->var.green.offset) |
+			(blue  << info->var.blue.offset);
+	}
+	return 0;
+}
+
+static struct fb_ops imacfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= imacfb_setcolreg,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static int __init imacfb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt) continue;
+
+		if (!strcmp(this_opt, "inverse"))
+			inverse = 1;
+		else if (!strcmp(this_opt, "i17"))
+			model = M_I17;
+		else if (!strcmp(this_opt, "i20"))
+			model = M_I20;
+		else if (!strcmp(this_opt, "mini"))
+			model = M_MINI;
+		else if (!strcmp(this_opt, "macbook"))
+			model = M_MACBOOK;
+		else if (!strncmp(this_opt, "height:", 7))
+			manual_height = simple_strtoul(this_opt+7, NULL, 0);
+		else if (!strncmp(this_opt, "width:", 6))
+			manual_width = simple_strtoul(this_opt+6, NULL, 0);
+	}
+	return 0;
+}
+
+static int __init imacfb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int err;
+	unsigned int size_vmode;
+	unsigned int size_remap;
+	unsigned int size_total;
+
+	screen_info.lfb_depth = 32;
+	screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000;
+	screen_info.pages=1;
+	screen_info.blue_size = 8;
+	screen_info.blue_pos = 0;
+	screen_info.green_size = 8;
+	screen_info.green_pos = 8;
+	screen_info.red_size = 8;
+	screen_info.red_pos = 16;
+	screen_info.rsvd_size = 8;
+	screen_info.rsvd_pos = 24;
+
+	switch (model) {
+	case M_I17:
+		screen_info.lfb_width = 1440;
+		screen_info.lfb_height = 900;
+		screen_info.lfb_linelength = 1472 * 4;
+		screen_info.lfb_base = 0x80010000;
+		break;
+	case M_NEW:
+	case M_I20:
+		screen_info.lfb_width = 1680;
+		screen_info.lfb_height = 1050;
+		screen_info.lfb_linelength = 1728 * 4;
+		screen_info.lfb_base = 0x80010000;
+		break;
+	case M_MINI:
+		screen_info.lfb_width = 1024;
+		screen_info.lfb_height = 768;
+		screen_info.lfb_linelength = 2048 * 4;
+		screen_info.lfb_base = 0x80000000;
+		break;
+	case M_MACBOOK:
+		screen_info.lfb_width = 1280;
+		screen_info.lfb_height = 800;
+		screen_info.lfb_linelength = 2048 * 4;
+		screen_info.lfb_base = 0x80000000;
+		break;
+ 	}
+
+	/* if the user wants to manually specify height/width,
+	   we will override the defaults */
+	/* TODO: eventually get auto-detection working */
+	if (manual_height > 0)
+		screen_info.lfb_height = manual_height;
+	if (manual_width > 0)
+		screen_info.lfb_width = manual_width;
+
+	imacfb_fix.smem_start = screen_info.lfb_base;
+	imacfb_defined.bits_per_pixel = screen_info.lfb_depth;
+	imacfb_defined.xres = screen_info.lfb_width;
+	imacfb_defined.yres = screen_info.lfb_height;
+	imacfb_fix.line_length = screen_info.lfb_linelength;
+
+	/*   size_vmode -- that is the amount of memory needed for the
+	 *                 used video mode, i.e. the minimum amount of
+	 *                 memory we need. */
+	size_vmode = imacfb_defined.yres * imacfb_fix.line_length;
+
+	/*   size_total -- all video memory we have. Used for
+	 *                 entries, ressource allocation and bounds
+	 *                 checking. */
+	size_total = screen_info.lfb_size * 65536;
+	if (size_total < size_vmode)
+		size_total = size_vmode;
+
+	/*   size_remap -- the amount of video memory we are going to
+	 *                 use for imacfb.  With modern cards it is no
+	 *                 option to simply use size_total as that
+	 *                 wastes plenty of kernel address space. */
+	size_remap  = size_vmode * 2;
+	if (size_remap < size_vmode)
+		size_remap = size_vmode;
+	if (size_remap > size_total)
+		size_remap = size_total;
+	imacfb_fix.smem_len = size_remap;
+
+#ifndef __i386__
+	screen_info.imacpm_seg = 0;
+#endif
+
+	if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) {
+		printk(KERN_WARNING
+		       "imacfb: cannot reserve video memory at 0x%lx\n",
+			imacfb_fix.smem_start);
+		/* We cannot make this fatal. Sometimes this comes from magic
+		   spaces our resource handlers simply don't know about */
+	}
+
+	info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev);
+	if (!info) {
+		err = -ENOMEM;
+		goto err_release_mem;
+	}
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+
+	info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_ERR "imacfb: abort, cannot ioremap video memory "
+				"0x%x @ 0x%lx\n",
+			imacfb_fix.smem_len, imacfb_fix.smem_start);
+		err = -EIO;
+		goto err_unmap;
+	}
+
+	printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, "
+	       "using %dk, total %dk\n",
+	       imacfb_fix.smem_start, info->screen_base,
+	       size_remap/1024, size_total/1024);
+	printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+	       imacfb_defined.xres, imacfb_defined.yres,
+	       imacfb_defined.bits_per_pixel, imacfb_fix.line_length,
+	       screen_info.pages);
+
+	imacfb_defined.xres_virtual = imacfb_defined.xres;
+	imacfb_defined.yres_virtual = imacfb_fix.smem_len /
+					imacfb_fix.line_length;
+	printk(KERN_INFO "imacfb: scrolling: redraw\n");
+	imacfb_defined.yres_virtual = imacfb_defined.yres;
+
+	/* some dummy values for timing to make fbset happy */
+	imacfb_defined.pixclock     = 10000000 / imacfb_defined.xres *
+					1000 / imacfb_defined.yres;
+	imacfb_defined.left_margin  = (imacfb_defined.xres / 8) & 0xf8;
+	imacfb_defined.hsync_len    = (imacfb_defined.xres / 8) & 0xf8;
+
+	imacfb_defined.red.offset    = screen_info.red_pos;
+	imacfb_defined.red.length    = screen_info.red_size;
+	imacfb_defined.green.offset  = screen_info.green_pos;
+	imacfb_defined.green.length  = screen_info.green_size;
+	imacfb_defined.blue.offset   = screen_info.blue_pos;
+	imacfb_defined.blue.length   = screen_info.blue_size;
+	imacfb_defined.transp.offset = screen_info.rsvd_pos;
+	imacfb_defined.transp.length = screen_info.rsvd_size;
+
+	printk(KERN_INFO "imacfb: %s: "
+	       "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
+	       "Truecolor",
+	       screen_info.rsvd_size,
+	       screen_info.red_size,
+	       screen_info.green_size,
+	       screen_info.blue_size,
+	       screen_info.rsvd_pos,
+	       screen_info.red_pos,
+	       screen_info.green_pos,
+	       screen_info.blue_pos);
+
+	imacfb_fix.ypanstep  = 0;
+	imacfb_fix.ywrapstep = 0;
+
+	/* request failure does not faze us, as vgacon probably has this
+	 * region already (FIXME) */
+	request_region(0x3c0, 32, "imacfb");
+
+	info->fbops = &imacfb_ops;
+	info->var = imacfb_defined;
+	info->fix = imacfb_fix;
+	info->flags = FBINFO_FLAG_DEFAULT;
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		err = -ENOMEM;
+		goto err_unmap;
+	}
+	if (register_framebuffer(info)<0) {
+		err = -EINVAL;
+		goto err_fb_dealoc;
+	}
+	printk(KERN_INFO "fb%d: %s frame buffer device\n",
+	       info->node, info->fix.id);
+	return 0;
+
+err_fb_dealoc:
+	fb_dealloc_cmap(&info->cmap);
+err_unmap:
+	iounmap(info->screen_base);
+	framebuffer_release(info);
+err_release_mem:
+	release_mem_region(imacfb_fix.smem_start, size_total);
+	return err;
+}
+
+static struct platform_driver imacfb_driver = {
+	.probe	= imacfb_probe,
+	.driver	= {
+		.name	= "imacfb",
+	},
+};
+
+static struct platform_device imacfb_device = {
+	.name	= "imacfb",
+};
+
+static int __init imacfb_init(void)
+{
+	int ret;
+	char *option = NULL;
+
+	/* ignore error return of fb_get_options */
+	fb_get_options("imacfb", &option);
+	imacfb_setup(option);
+	ret = platform_driver_register(&imacfb_driver);
+
+	if (!ret) {
+		ret = platform_device_register(&imacfb_device);
+		if (ret)
+			platform_driver_unregister(&imacfb_driver);
+	}
+	return ret;
+}
+module_init(imacfb_init);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
index da29d00..e290d74 100644
--- a/drivers/video/intelfb/intelfb.h
+++ b/drivers/video/intelfb/intelfb.h
@@ -8,9 +8,9 @@
 
 
 /*** Version/name ***/
-#define INTELFB_VERSION			"0.9.2"
+#define INTELFB_VERSION			"0.9.4"
 #define INTELFB_MODULE_NAME		"intelfb"
-#define SUPPORTED_CHIPSETS		"830M/845G/852GM/855GM/865G/915G/915GM"
+#define SUPPORTED_CHIPSETS		"830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM"
 
 
 /*** Debug/feature defines ***/
@@ -52,11 +52,14 @@
 #define PCI_DEVICE_ID_INTEL_865G	0x2572
 #define PCI_DEVICE_ID_INTEL_915G	0x2582
 #define PCI_DEVICE_ID_INTEL_915GM	0x2592
+#define PCI_DEVICE_ID_INTEL_945G	0x2772
+#define PCI_DEVICE_ID_INTEL_945GM	0x27A2
 
 /* Size of MMIO region */
 #define INTEL_REG_SIZE			0x80000
 
 #define STRIDE_ALIGNMENT		16
+#define STRIDE_ALIGNMENT_I9XX		64
 
 #define PALETTE_8_ENTRIES		256
 
@@ -125,7 +128,9 @@
 	INTEL_855GME,
 	INTEL_865G,
 	INTEL_915G,
-	INTEL_915GM
+	INTEL_915GM,
+	INTEL_945G,
+	INTEL_945GM,
 };
 
 struct intelfb_hwstate {
@@ -232,7 +237,7 @@
 	u32 fb_start;
 
 	/* ring buffer */
-	u8 __iomem *ring_head;
+	u32 ring_head;
 	u32 ring_tail;
 	u32 ring_tail_mask;
 	u32 ring_space;
@@ -277,8 +282,13 @@
 
 	/* driver registered */
 	int registered;
+	
+	/* index into plls */
+	int pll_index;
 };
 
+#define IS_I9XX(dinfo) (((dinfo)->chipset == INTEL_915G)||(dinfo->chipset == INTEL_915GM)||((dinfo)->chipset == INTEL_945G)||(dinfo->chipset==INTEL_945GM))
+
 /*** function prototypes ***/
 
 extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 995b47c..0a0a8b1 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -1,11 +1,12 @@
 /*
  * intelfb
  *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM
- * integrated graphics chips.
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G/915GM/
+ * 945G/945GM integrated graphics chips.
  *
  * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
  *                   2004 Sylvain Meyer
+ *                   2006 David Airlie
  *
  * This driver consists of two parts.  The first part (intelfbdrv.c) provides
  * the basic fbdev interfaces, is derived in part from the radeonfb and
@@ -131,6 +132,7 @@
 
 #include "intelfb.h"
 #include "intelfbhw.h"
+#include "../edid.h"
 
 static void __devinit get_initial_mode(struct intelfb_info *dinfo);
 static void update_dinfo(struct intelfb_info *dinfo,
@@ -182,6 +184,8 @@
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915GM },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_945GM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_945GM },
 	{ 0, }
 };
 
@@ -261,7 +265,7 @@
 
 #ifndef MODULE
 #define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
-#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), NULL, 0)
+#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name) + 1, NULL, 0)
 #define OPT_STRVAL(opt, name) (opt + strlen(name))
 
 static __inline__ char *
@@ -546,11 +550,11 @@
 
 	/* Set base addresses. */
 	if ((ent->device == PCI_DEVICE_ID_INTEL_915G) ||
-			(ent->device == PCI_DEVICE_ID_INTEL_915GM)) {
+	    (ent->device == PCI_DEVICE_ID_INTEL_915GM) ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_945G)  ||
+	    (ent->device == PCI_DEVICE_ID_INTEL_945GM)) {
 		aperture_bar = 2;
 		mmio_bar = 0;
-		/* Disable HW cursor on 915G/M (not implemented yet) */
-		hwcursor = 0;
 	}
 	dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
 	dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);
@@ -584,8 +588,7 @@
 	/* Get the chipset info. */
 	dinfo->pci_chipset = pdev->device;
 
-	if (intelfbhw_get_chipset(pdev, &dinfo->name, &dinfo->chipset,
-				  &dinfo->mobile)) {
+	if (intelfbhw_get_chipset(pdev, dinfo)) {
 		cleanup(dinfo);
 		return -ENODEV;
 	}
@@ -704,7 +707,7 @@
 			+ (dinfo->ring.offset << 12);
 		dinfo->ring.virtual  = dinfo->aperture.virtual
 			+ (dinfo->ring.offset << 12);
-		dinfo->ring_head = dinfo->ring.virtual;
+		dinfo->ring_head = 0;
 	}
 	if (dinfo->hwcursor) {
 		agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
@@ -763,18 +766,18 @@
 	if (mtrr)
 		set_mtrr(dinfo);
 
-	DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%x)\n",
+	DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%p)\n",
 		dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
-		(u32 __iomem ) dinfo->fb.virtual);
-	DBG_MSG("MMIO: 0x%x/0x%x (0x%x)\n",
+		dinfo->fb.virtual);
+	DBG_MSG("MMIO: 0x%x/0x%x (0x%p)\n",
 		dinfo->mmio_base_phys, INTEL_REG_SIZE,
-		(u32 __iomem) dinfo->mmio_base);
-	DBG_MSG("ring buffer: 0x%x/0x%x (0x%x)\n",
+		dinfo->mmio_base);
+	DBG_MSG("ring buffer: 0x%x/0x%x (0x%p)\n",
 		dinfo->ring.physical, dinfo->ring.size,
-		(u32 __iomem ) dinfo->ring.virtual);
-	DBG_MSG("HW cursor: 0x%x/0x%x (0x%x) (offset 0x%x) (phys 0x%x)\n",
+		dinfo->ring.virtual);
+	DBG_MSG("HW cursor: 0x%x/0x%x (0x%p) (offset 0x%x) (phys 0x%x)\n",
 		dinfo->cursor.physical, dinfo->cursor.size,
-		(u32 __iomem ) dinfo->cursor.virtual, dinfo->cursor.offset,
+		dinfo->cursor.virtual, dinfo->cursor.offset,
 		dinfo->cursor.physical);
 
 	DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
@@ -1029,17 +1032,44 @@
 		       sizeof(struct fb_var_screeninfo));
 		msrc = 5;
 	} else {
-		if (mode) {
-			msrc = fb_find_mode(var, dinfo->info, mode,
-					    vesa_modes, VESA_MODEDB_SIZE,
-					    NULL, 0);
-			if (msrc)
-				msrc |= 8;
+		const u8 *edid_s = fb_firmware_edid(&dinfo->pdev->dev);
+		u8 *edid_d = NULL;
+
+		if (edid_s) {
+			edid_d = kmalloc(EDID_LENGTH, GFP_KERNEL);
+
+			if (edid_d) {
+				memcpy(edid_d, edid_s, EDID_LENGTH);
+				fb_edid_to_monspecs(edid_d,
+						    &dinfo->info->monspecs);
+				kfree(edid_d);
+			}
 		}
+
+		if (mode) {
+			printk("intelfb: Looking for mode in private "
+			       "database\n");
+			msrc = fb_find_mode(var, dinfo->info, mode,
+					    dinfo->info->monspecs.modedb,
+					    dinfo->info->monspecs.modedb_len,
+					    NULL, 0);
+
+			if (msrc && msrc > 1) {
+				printk("intelfb: No mode in private database, "
+				       "intelfb: looking for mode in global "
+				       "database ");
+				msrc = fb_find_mode(var, dinfo->info, mode,
+						    NULL, 0, NULL, 0);
+
+				if (msrc)
+					msrc |= 8;
+			}
+
+		}
+
 		if (!msrc) {
 			msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
-					    vesa_modes, VESA_MODEDB_SIZE,
-					    NULL, 0);
+					    NULL, 0, NULL, 0);
 		}
 	}
 
@@ -1139,7 +1169,10 @@
 	}
 
 	/* Make sure the line length is a aligned correctly. */
-	dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
+	if (IS_I9XX(dinfo))
+		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT_I9XX);
+	else
+		dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
 
 	if (FIXED_MODE(dinfo))
 		dinfo->pitch = dinfo->initial_pitch;
@@ -1162,16 +1195,33 @@
 	struct fb_var_screeninfo v;
 	struct intelfb_info *dinfo;
 	static int first = 1;
+	int i;
+	/* Good pitches to allow tiling.  Don't care about pitches < 1024. */
+	static const int pitches[] = {
+		128 * 8,
+		128 * 16,
+		128 * 32,
+		128 * 64,
+		0
+	};
 
 	DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
 
 	dinfo = GET_DINFO(info);
 
+	/* update the pitch */
 	if (intelfbhw_validate_mode(dinfo, var) != 0)
 		return -EINVAL;
 
 	v = *var;
 
+	for (i = 0; pitches[i] != 0; i++) {
+		if (pitches[i] >= v.xres_virtual) {
+			v.xres_virtual = pitches[i];
+			break;
+		}
+	}
+
 	/* Check for a supported bpp. */
 	if (v.bits_per_pixel <= 8) {
 		v.bits_per_pixel = 8;
@@ -1467,7 +1517,7 @@
 intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
         struct intelfb_info *dinfo = GET_DINFO(info);
-
+	u32 physical;
 #if VERBOSE > 0
 	DBG_MSG("intelfb_cursor\n");
 #endif
@@ -1478,7 +1528,10 @@
 	intelfbhw_cursor_hide(dinfo);
 
 	/* If XFree killed the cursor - restore it */
-	if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.offset << 12) {
+	physical = (dinfo->mobile || IS_I9XX(dinfo)) ? dinfo->cursor.physical :
+		   (dinfo->cursor.offset << 12);
+
+	if (INREG(CURSOR_A_BASEADDR) != physical) {
 		u32 fg, bg;
 
 		DBG_MSG("the cursor was killed - restore it !!\n");
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
index 624c4bc..7533b3d 100644
--- a/drivers/video/intelfb/intelfbhw.c
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -40,68 +40,110 @@
 #include "intelfb.h"
 #include "intelfbhw.h"
 
+struct pll_min_max {
+	int min_m, max_m, min_m1, max_m1;
+	int min_m2, max_m2, min_n, max_n;
+	int min_p, max_p, min_p1, max_p1;
+	int min_vco, max_vco, p_transition_clk, ref_clk;
+	int p_inc_lo, p_inc_hi;
+};
+
+#define PLLS_I8xx 0
+#define PLLS_I9xx 1
+#define PLLS_MAX 2
+
+static struct pll_min_max plls[PLLS_MAX] = {
+	{ 108, 140, 18, 26,
+	  6, 16, 3, 16,
+	  4, 128, 0, 31,
+	  930000, 1400000, 165000, 48000,
+	  4, 2 }, //I8xx
+
+	{ 75, 120, 10, 20,
+	  5, 9, 4, 7,
+	  5, 80, 1, 8,
+	  1400000, 2800000, 200000, 96000,
+	  10, 5 }  //I9xx
+};
+
 int
-intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,
-		      int *mobile)
+intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo)
 {
 	u32 tmp;
-
-	if (!pdev || !name || !chipset || !mobile)
+	if (!pdev || !dinfo)
 		return 1;
 
 	switch (pdev->device) {
 	case PCI_DEVICE_ID_INTEL_830M:
-		*name = "Intel(R) 830M";
-		*chipset = INTEL_830M;
-		*mobile = 1;
+		dinfo->name = "Intel(R) 830M";
+		dinfo->chipset = INTEL_830M;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I8xx;
 		return 0;
 	case PCI_DEVICE_ID_INTEL_845G:
-		*name = "Intel(R) 845G";
-		*chipset = INTEL_845G;
-		*mobile = 0;
+		dinfo->name = "Intel(R) 845G";
+		dinfo->chipset = INTEL_845G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I8xx;
 		return 0;
 	case PCI_DEVICE_ID_INTEL_85XGM:
 		tmp = 0;
-		*mobile = 1;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I8xx;
 		pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
 		switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
 			INTEL_85X_VARIANT_MASK) {
 		case INTEL_VAR_855GME:
-			*name = "Intel(R) 855GME";
-			*chipset = INTEL_855GME;
+			dinfo->name = "Intel(R) 855GME";
+			dinfo->chipset = INTEL_855GME;
 			return 0;
 		case INTEL_VAR_855GM:
-			*name = "Intel(R) 855GM";
-			*chipset = INTEL_855GM;
+			dinfo->name = "Intel(R) 855GM";
+			dinfo->chipset = INTEL_855GM;
 			return 0;
 		case INTEL_VAR_852GME:
-			*name = "Intel(R) 852GME";
-			*chipset = INTEL_852GME;
+			dinfo->name = "Intel(R) 852GME";
+			dinfo->chipset = INTEL_852GME;
 			return 0;
 		case INTEL_VAR_852GM:
-			*name = "Intel(R) 852GM";
-			*chipset = INTEL_852GM;
+			dinfo->name = "Intel(R) 852GM";
+			dinfo->chipset = INTEL_852GM;
 			return 0;
 		default:
-			*name = "Intel(R) 852GM/855GM";
-			*chipset = INTEL_85XGM;
+			dinfo->name = "Intel(R) 852GM/855GM";
+			dinfo->chipset = INTEL_85XGM;
 			return 0;
 		}
 		break;
 	case PCI_DEVICE_ID_INTEL_865G:
-		*name = "Intel(R) 865G";
-		*chipset = INTEL_865G;
-		*mobile = 0;
+		dinfo->name = "Intel(R) 865G";
+		dinfo->chipset = INTEL_865G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I8xx;
 		return 0;
 	case PCI_DEVICE_ID_INTEL_915G:
-		*name = "Intel(R) 915G";
-		*chipset = INTEL_915G;
-		*mobile = 0;
+		dinfo->name = "Intel(R) 915G";
+		dinfo->chipset = INTEL_915G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I9xx;
 		return 0;
 	case PCI_DEVICE_ID_INTEL_915GM:
-		*name = "Intel(R) 915GM";
-		*chipset = INTEL_915GM;
-		*mobile = 1;
+		dinfo->name = "Intel(R) 915GM";
+		dinfo->chipset = INTEL_915GM;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_945G:
+		dinfo->name = "Intel(R) 945G";
+		dinfo->chipset = INTEL_945G;
+		dinfo->mobile = 0;
+		dinfo->pll_index = PLLS_I9xx;
+		return 0;
+	case PCI_DEVICE_ID_INTEL_945GM:
+		dinfo->name = "Intel(R) 945GM";
+		dinfo->chipset = INTEL_945GM;
+		dinfo->mobile = 1;
+		dinfo->pll_index = PLLS_I9xx;
 		return 0;
 	default:
 		return 1;
@@ -114,6 +156,7 @@
 {
 	struct pci_dev *bridge_dev;
 	u16 tmp;
+	int stolen_overhead;
 
 	if (!pdev || !aperture_size || !stolen_size)
 		return 1;
@@ -128,21 +171,41 @@
 	tmp = 0;
 	pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
 	switch (pdev->device) {
-	case PCI_DEVICE_ID_INTEL_830M:
-	case PCI_DEVICE_ID_INTEL_845G:
+	case PCI_DEVICE_ID_INTEL_915G:
+	case PCI_DEVICE_ID_INTEL_915GM:
+	case PCI_DEVICE_ID_INTEL_945G:
+	case PCI_DEVICE_ID_INTEL_945GM:
+		/* 915 and 945 chipsets support a 256MB aperture.
+		   Aperture size is determined by inspected the
+		   base address of the aperture. */
+		if (pci_resource_start(pdev, 2) & 0x08000000)
+			*aperture_size = MB(128);
+		else
+			*aperture_size = MB(256);
+		break;
+	default:
 		if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
 			*aperture_size = MB(64);
 		else
 			*aperture_size = MB(128);
+		break;
+	}
+
+	/* Stolen memory size is reduced by the GTT and the popup.
+	   GTT is 1K per MB of aperture size, and popup is 4K. */
+	stolen_overhead = (*aperture_size / MB(1)) + 4;
+	switch(pdev->device) {
+	case PCI_DEVICE_ID_INTEL_830M:
+	case PCI_DEVICE_ID_INTEL_845G:
 		switch (tmp & INTEL_830_GMCH_GMS_MASK) {
 		case INTEL_830_GMCH_GMS_STOLEN_512:
-			*stolen_size = KB(512) - KB(132);
+			*stolen_size = KB(512) - KB(stolen_overhead);
 			return 0;
 		case INTEL_830_GMCH_GMS_STOLEN_1024:
-			*stolen_size = MB(1) - KB(132);
+			*stolen_size = MB(1) - KB(stolen_overhead);
 			return 0;
 		case INTEL_830_GMCH_GMS_STOLEN_8192:
-			*stolen_size = MB(8) - KB(132);
+			*stolen_size = MB(8) - KB(stolen_overhead);
 			return 0;
 		case INTEL_830_GMCH_GMS_LOCAL:
 			ERR_MSG("only local memory found\n");
@@ -157,28 +220,27 @@
 		}
 		break;
 	default:
-		*aperture_size = MB(128);
 		switch (tmp & INTEL_855_GMCH_GMS_MASK) {
 		case INTEL_855_GMCH_GMS_STOLEN_1M:
-			*stolen_size = MB(1) - KB(132);
+			*stolen_size = MB(1) - KB(stolen_overhead);
 			return 0;
 		case INTEL_855_GMCH_GMS_STOLEN_4M:
-			*stolen_size = MB(4) - KB(132);
+			*stolen_size = MB(4) - KB(stolen_overhead);
 			return 0;
 		case INTEL_855_GMCH_GMS_STOLEN_8M:
-			*stolen_size = MB(8) - KB(132);
+			*stolen_size = MB(8) - KB(stolen_overhead);
 			return 0;
 		case INTEL_855_GMCH_GMS_STOLEN_16M:
-			*stolen_size = MB(16) - KB(132);
+			*stolen_size = MB(16) - KB(stolen_overhead);
 			return 0;
 		case INTEL_855_GMCH_GMS_STOLEN_32M:
-			*stolen_size = MB(32) - KB(132);
+			*stolen_size = MB(32) - KB(stolen_overhead);
 			return 0;
 		case INTEL_915G_GMCH_GMS_STOLEN_48M:
-			*stolen_size = MB(48) - KB(132);
+			*stolen_size = MB(48) - KB(stolen_overhead);
 			return 0;
 		case INTEL_915G_GMCH_GMS_STOLEN_64M:
-			*stolen_size = MB(64) - KB(132);
+			*stolen_size = MB(64) - KB(stolen_overhead);
 			return 0;
 		case INTEL_855_GMCH_GMS_DISABLED:
 			ERR_MSG("video memory is disabled\n");
@@ -529,12 +591,63 @@
 }
 
 
+static int calc_vclock3(int index, int m, int n, int p)
+{
+	if (p == 0 || n == 0)
+		return 0;
+	return plls[index].ref_clk * m / n / p;
+}
+
+static int calc_vclock(int index, int m1, int m2, int n, int p1, int p2, int lvds)
+{
+	struct pll_min_max *pll = &plls[index];
+	u32 m, vco, p;
+
+	m = (5 * (m1 + 2)) + (m2 + 2);
+	n += 2;
+	vco = pll->ref_clk * m / n;
+
+	if (index == PLLS_I8xx) {
+		p = ((p1 + 2) * (1 << (p2 + 1)));
+	} else {
+		p = ((p1) * (p2 ? 5 : 10));
+	}
+	return vco / p;
+}
+
+static void
+intelfbhw_get_p1p2(struct intelfb_info *dinfo, int dpll, int *o_p1, int *o_p2)
+{
+	int p1, p2;
+
+	if (IS_I9XX(dinfo)) {
+		if (dpll & DPLL_P1_FORCE_DIV2)
+			p1 = 1;
+		else
+			p1 = (dpll >> DPLL_P1_SHIFT) & 0xff;
+		
+		p1 = ffs(p1);
+
+		p2 = (dpll >> DPLL_I9XX_P2_SHIFT) & DPLL_P2_MASK;
+	} else {
+		if (dpll & DPLL_P1_FORCE_DIV2)
+			p1 = 0;
+		else
+			p1 = (dpll >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
+		p2 = (dpll >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+	}
+
+	*o_p1 = p1;
+	*o_p2 = p2;
+}
+
+
 void
 intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
 {
 #if REGDUMP
 	int i, m1, m2, n, p1, p2;
-
+	int index = dinfo->pll_index;
 	DBG_MSG("intelfbhw_print_hw_state\n");
 
 	if (!hw || !dinfo)
@@ -547,26 +660,22 @@
 	n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2)
-		p1 = 0;
-	else
-		p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK;
-	p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
+
 	printk("	VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-		m1, m2, n, p1, p2);
-	printk("	VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+	       m1, m2, n, p1, p2);
+	printk("	VGA0: clock is %d\n",
+	       calc_vclock(index, m1, m2, n, p1, p2, 0));
 
 	n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2)
-		p1 = 0;
-	else
-		p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK;
-	p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->vga_pd, &p1, &p2);
 	printk("	VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-		m1, m2, n, p1, p2);
-	printk("	VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+	       m1, m2, n, p1, p2);
+	printk("	VGA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
 
 	printk("	DPLL_A:			0x%08x\n", hw->dpll_a);
 	printk("	DPLL_B:			0x%08x\n", hw->dpll_b);
@@ -578,34 +687,30 @@
 	n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
-		p1 = 0;
-	else
-		p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
-	p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
+
 	printk("	PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-		m1, m2, n, p1, p2);
-	printk("	PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+	       m1, m2, n, p1, p2);
+	printk("	PLLA0: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
 
 	n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
 	m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
-	if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
-		p1 = 0;
-	else
-		p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
-	p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
+
+	intelfbhw_get_p1p2(dinfo, hw->dpll_a, &p1, &p2);
+
 	printk("	PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
-		m1, m2, n, p1, p2);
-	printk("	PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
+	       m1, m2, n, p1, p2);
+	printk("	PLLA1: clock is %d\n", calc_vclock(index, m1, m2, n, p1, p2, 0));
 
 #if 0
 	printk("	PALETTE_A:\n");
 	for (i = 0; i < PALETTE_8_ENTRIES)
-		printk("	%3d:	0x%08x\n", i, hw->palette_a[i];
+		printk("	%3d:	0x%08x\n", i, hw->palette_a[i]);
 	printk("	PALETTE_B:\n");
 	for (i = 0; i < PALETTE_8_ENTRIES)
-		printk("	%3d:	0x%08x\n", i, hw->palette_b[i];
+		printk("	%3d:	0x%08x\n", i, hw->palette_b[i]);
 #endif
 
 	printk("	HTOTAL_A:		0x%08x\n", hw->htotal_a);
@@ -680,11 +785,11 @@
 	}
 	for (i = 0; i < 3; i++) {
 		printk("	SWF3%d			0x%08x\n", i,
-			hw->swf3x[i]);
+		       hw->swf3x[i]);
 	}
 	for (i = 0; i < 8; i++)
 		printk("	FENCE%d			0x%08x\n", i,
-			hw->fence[i]);
+		       hw->fence[i]);
 
 	printk("	INSTPM			0x%08x\n", hw->instpm);
 	printk("	MEM_MODE		0x%08x\n", hw->mem_mode);
@@ -695,43 +800,58 @@
 #endif
 }
 
+
+
 /* Split the M parameter into M1 and M2. */
 static int
-splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2)
+splitm(int index, unsigned int m, unsigned int *retm1, unsigned int *retm2)
 {
 	int m1, m2;
+	int testm;
+	struct pll_min_max *pll = &plls[index];
 
-	m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2;
-	if (m1 < MIN_M1)
-		m1 = MIN_M1;
-	if (m1 > MAX_M1)
-		m1 = MAX_M1;
-	m2 = m - 5 * (m1 + 2) - 2;
-	if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) {
-		return 1;
-	} else {
-		*retm1 = (unsigned int)m1;
-		*retm2 = (unsigned int)m2;
-		return 0;
+	/* no point optimising too much - brute force m */
+	for (m1 = pll->min_m1; m1 < pll->max_m1 + 1; m1++) {
+		for (m2 = pll->min_m2; m2 < pll->max_m2 + 1; m2++) {
+			testm = (5 * (m1 + 2)) + (m2 + 2);
+			if (testm == m) {
+				*retm1 = (unsigned int)m1;
+				*retm2 = (unsigned int)m2;
+				return 0;
+			}
+		}
 	}
+	return 1;
 }
 
 /* Split the P parameter into P1 and P2. */
 static int
-splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2)
+splitp(int index, unsigned int p, unsigned int *retp1, unsigned int *retp2)
 {
 	int p1, p2;
+	struct pll_min_max *pll = &plls[index];
+
+	if (index == PLLS_I9xx) {
+		p2 = (p % 10) ? 1 : 0;
+
+		p1 = p / (p2 ? 5 : 10);
+
+		*retp1 = (unsigned int)p1;
+		*retp2 = (unsigned int)p2;
+		return 0;
+	}
 
 	if (p % 4 == 0)
 		p2 = 1;
 	else
 		p2 = 0;
 	p1 = (p / (1 << (p2 + 1))) - 2;
-	if (p % 4 == 0 && p1 < MIN_P1) {
+	if (p % 4 == 0 && p1 < pll->min_p1) {
 		p2 = 0;
 		p1 = (p / (1 << (p2 + 1))) - 2;
 	}
-	if (p1  < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) {
+	if (p1 < pll->min_p1 || p1 > pll->max_p1 ||
+	    (p1 + 2) * (1 << (p2 + 1)) != p) {
 		return 1;
 	} else {
 		*retp1 = (unsigned int)p1;
@@ -741,14 +861,15 @@
 }
 
 static int
-calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
+calc_pll_params(int index, int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
 		u32 *retp2, u32 *retclock)
 {
-	u32 m1, m2, n, p1, p2, n1;
-	u32 f_vco, p, p_best = 0, m, f_out;
+	u32 m1, m2, n, p1, p2, n1, testm;
+	u32 f_vco, p, p_best = 0, m, f_out = 0;
 	u32 err_max, err_target, err_best = 10000000;
 	u32 n_best = 0, m_best = 0, f_best, f_err;
-	u32 p_min, p_max, p_inc, div_min, div_max;
+	u32 p_min, p_max, p_inc, div_max;
+	struct pll_min_max *pll = &plls[index];
 
 	/* Accept 0.5% difference, but aim for 0.1% */
 	err_max = 5 * clock / 1000;
@@ -756,58 +877,56 @@
 
 	DBG_MSG("Clock is %d\n", clock);
 
-	div_max = MAX_VCO_FREQ / clock;
-	div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock;
+	div_max = pll->max_vco / clock;
 
-	if (clock <= P_TRANSITION_CLOCK)
-		p_inc = 4;
-	else
-		p_inc = 2;
-	p_min = ROUND_UP_TO(div_min, p_inc);
+	p_inc = (clock <= pll->p_transition_clk) ? pll->p_inc_lo : pll->p_inc_hi;
+	p_min = p_inc;
 	p_max = ROUND_DOWN_TO(div_max, p_inc);
-	if (p_min < MIN_P)
-		p_min = 4;
-	if (p_max > MAX_P)
-		p_max = 128;
+	if (p_min < pll->min_p)
+		p_min = pll->min_p;
+	if (p_max > pll->max_p)
+		p_max = pll->max_p;
 
 	DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
 
 	p = p_min;
 	do {
-		if (splitp(p, &p1, &p2)) {
+		if (splitp(index, p, &p1, &p2)) {
 			WRN_MSG("cannot split p = %d\n", p);
 			p += p_inc;
 			continue;
 		}
-		n = MIN_N;
+		n = pll->min_n;
 		f_vco = clock * p;
 
 		do {
-			m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK;
-			if (m < MIN_M)
-				m = MIN_M;
-			if (m > MAX_M)
-				m = MAX_M;
-			f_out = CALC_VCLOCK3(m, n, p);
-			if (splitm(m, &m1, &m2)) {
-				WRN_MSG("cannot split m = %d\n", m);
-				n++;
-				continue;
-			}
-			if (clock > f_out)
-				f_err = clock - f_out;
-			else
-				f_err = f_out - clock;
+			m = ROUND_UP_TO(f_vco * n, pll->ref_clk) / pll->ref_clk;
+			if (m < pll->min_m)
+				m = pll->min_m + 1;
+			if (m > pll->max_m)
+				m = pll->max_m - 1;
+			for (testm = m - 1; testm <= m; testm++) {
+				f_out = calc_vclock3(index, m, n, p);
+				if (splitm(index, testm, &m1, &m2)) {
+					WRN_MSG("cannot split m = %d\n", m);
+					n++;
+					continue;
+				}
+				if (clock > f_out)
+					f_err = clock - f_out;
+				else/* slightly bias the error for bigger clocks */
+					f_err = f_out - clock + 1;
 
-			if (f_err < err_best) {
-				m_best = m;
-				n_best = n;
-				p_best = p;
-				f_best = f_out;
-				err_best = f_err;
+				if (f_err < err_best) {
+					m_best = testm;
+					n_best = n;
+					p_best = p;
+					f_best = f_out;
+					err_best = f_err;
+				}
 			}
 			n++;
-		} while ((n <= MAX_N) && (f_out >= clock));
+		} while ((n <= pll->max_n) && (f_out >= clock));
 		p += p_inc;
 	} while ((p <= p_max));
 
@@ -818,21 +937,22 @@
 	m = m_best;
 	n = n_best;
 	p = p_best;
-	splitm(m, &m1, &m2);
-	splitp(p, &p1, &p2);
+	splitm(index, m, &m1, &m2);
+	splitp(index, p, &p1, &p2);
 	n1 = n - 2;
 
 	DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
 		"f: %d (%d), VCO: %d\n",
 		m, m1, m2, n, n1, p, p1, p2,
-		CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2),
-		CALC_VCLOCK3(m, n, p) * p);
+		calc_vclock3(index, m, n, p),
+		calc_vclock(index, m1, m2, n1, p1, p2, 0),
+		calc_vclock3(index, m, n, p) * p);
 	*retm1 = m1;
 	*retm2 = m2;
 	*retn = n1;
 	*retp1 = p1;
 	*retp2 = p2;
-	*retclock = CALC_VCLOCK(m1, m2, n1, p1, p2);
+	*retclock = calc_vclock(index, m1, m2, n1, p1, p2, 0);
 
 	return 0;
 }
@@ -860,6 +980,7 @@
 	u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
 	u32 vsync_pol, hsync_pol;
 	u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
+	u32 stride_alignment;
 
 	DBG_MSG("intelfbhw_mode_to_hw\n");
 
@@ -929,7 +1050,8 @@
 	/* Desired clock in kHz */
 	clock_target = 1000000000 / var->pixclock;
 
-	if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) {
+	if (calc_pll_params(dinfo->pll_index, clock_target, &m1, &m2,
+			    &n, &p1, &p2, &clock)) {
 		WRN_MSG("calc_pll_params failed\n");
 		return 1;
 	}
@@ -949,7 +1071,14 @@
 	*dpll &= ~DPLL_P1_FORCE_DIV2;
 	*dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
 		   (DPLL_P1_MASK << DPLL_P1_SHIFT));
-	*dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
+
+	if (IS_I9XX(dinfo)) {
+		*dpll |= (p2 << DPLL_I9XX_P2_SHIFT);
+		*dpll |= (1 << (p1 - 1)) << DPLL_P1_SHIFT;
+	} else {
+		*dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
+	}
+
 	*fp0 = (n << FP_N_DIVISOR_SHIFT) |
 	       (m1 << FP_M1_DIVISOR_SHIFT) |
 	       (m2 << FP_M2_DIVISOR_SHIFT);
@@ -1054,7 +1183,7 @@
 	*ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
 	      (vactive << SRC_SIZE_VERT_SHIFT);
 
-	hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8;
+	hw->disp_a_stride = dinfo->pitch;
 	DBG_MSG("pitch is %d\n", hw->disp_a_stride);
 
 	hw->disp_a_base = hw->disp_a_stride * var->yoffset +
@@ -1063,9 +1192,11 @@
 	hw->disp_a_base += dinfo->fb.offset << 12;
 
 	/* Check stride alignment. */
-	if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) {
+	stride_alignment = IS_I9XX(dinfo) ? STRIDE_ALIGNMENT_I9XX :
+					    STRIDE_ALIGNMENT;
+	if (hw->disp_a_stride % stride_alignment != 0) {
 		WRN_MSG("display stride %d has bad alignment %d\n",
-			hw->disp_a_stride, STRIDE_ALIGNMENT);
+			hw->disp_a_stride, stride_alignment);
 		return 1;
 	}
 
@@ -1087,6 +1218,7 @@
 	u32 hsync_reg, htotal_reg, hblank_reg;
 	u32 vsync_reg, vtotal_reg, vblank_reg;
 	u32 src_size_reg;
+	u32 count, tmp_val[3];
 
 	/* Assume single pipe, display plane A, analog CRT. */
 
@@ -1155,6 +1287,27 @@
 		src_size_reg = SRC_SIZE_A;
 	}
 
+	/* turn off pipe */
+	tmp = INREG(pipe_conf_reg);
+	tmp &= ~PIPECONF_ENABLE;
+	OUTREG(pipe_conf_reg, tmp);
+
+	count = 0;
+	do {
+		tmp_val[count%3] = INREG(0x70000);
+		if ((tmp_val[0] == tmp_val[1]) && (tmp_val[1]==tmp_val[2]))
+			break;
+		count++;
+		udelay(1);
+		if (count % 200 == 0) {
+			tmp = INREG(pipe_conf_reg);
+			tmp &= ~PIPECONF_ENABLE;
+			OUTREG(pipe_conf_reg, tmp);
+		}
+	} while(count < 2000);
+
+	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
+
 	/* Disable planes A and B. */
 	tmp = INREG(DSPACNTR);
 	tmp &= ~DISPPLANE_PLANE_ENABLE;
@@ -1163,19 +1316,21 @@
 	tmp &= ~DISPPLANE_PLANE_ENABLE;
 	OUTREG(DSPBCNTR, tmp);
 
-	/* Wait for vblank.  For now, just wait for a 50Hz cycle (20ms)) */
+	/* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
 	mdelay(20);
 
+	OUTREG(DVOB, INREG(DVOB) & ~PORT_ENABLE);
+	OUTREG(DVOC, INREG(DVOC) & ~PORT_ENABLE);
+	OUTREG(ADPA, INREG(ADPA) & ~ADPA_DAC_ENABLE);
+
 	/* Disable Sync */
 	tmp = INREG(ADPA);
 	tmp &= ~ADPA_DPMS_CONTROL_MASK;
 	tmp |= ADPA_DPMS_D3;
 	OUTREG(ADPA, tmp);
 
-	/* turn off pipe */
-	tmp = INREG(pipe_conf_reg);
-	tmp &= ~PIPECONF_ENABLE;
-	OUTREG(pipe_conf_reg, tmp);
+	/* do some funky magic - xyzzy */
+	OUTREG(0x61204, 0xabcd0000);
 
 	/* turn off PLL */
 	tmp = INREG(dpll_reg);
@@ -1183,10 +1338,23 @@
 	OUTREG(dpll_reg, tmp);
 
 	/* Set PLL parameters */
-	OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE);
 	OUTREG(fp0_reg, *fp0);
 	OUTREG(fp1_reg, *fp1);
 
+	/* Enable PLL */
+	OUTREG(dpll_reg, *dpll);
+
+	/* Set DVOs B/C */
+	OUTREG(DVOB, hw->dvob);
+	OUTREG(DVOC, hw->dvoc);
+
+	/* undo funky magic */
+	OUTREG(0x61204, 0x00000000);
+
+	/* Set ADPA */
+	OUTREG(ADPA, INREG(ADPA) | ADPA_DAC_ENABLE);
+	OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
+
 	/* Set pipe parameters */
 	OUTREG(hsync_reg, *hs);
 	OUTREG(hblank_reg, *hb);
@@ -1196,18 +1364,6 @@
 	OUTREG(vtotal_reg, *vt);
 	OUTREG(src_size_reg, *ss);
 
-	/* Set DVOs B/C */
-	OUTREG(DVOB, hw->dvob);
-	OUTREG(DVOC, hw->dvoc);
-
-	/* Set ADPA */
-	OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
-
-	/* Enable PLL */
-	tmp = INREG(dpll_reg);
-	tmp |= DPLL_VCO_ENABLE;
-	OUTREG(dpll_reg, tmp);
-
 	/* Enable pipe */
 	OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
 
@@ -1231,7 +1387,7 @@
 			OUTREG(DSPACNTR,
 			       hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
 			mdelay(1);
-              }
+		}
 	}
 
 	OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
@@ -1267,19 +1423,17 @@
 
 	end = jiffies + (HZ * 3);
 	while (dinfo->ring_space < n) {
-		dinfo->ring_head = (u8 __iomem *)(INREG(PRI_RING_HEAD) &
-						   RING_HEAD_MASK);
-		if (dinfo->ring_tail + RING_MIN_FREE <
-		    (u32 __iomem) dinfo->ring_head)
-			dinfo->ring_space = (u32 __iomem) dinfo->ring_head
+		dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
+		if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head)
+			dinfo->ring_space = dinfo->ring_head
 				- (dinfo->ring_tail + RING_MIN_FREE);
 		else
 			dinfo->ring_space = (dinfo->ring.size +
-					     (u32 __iomem) dinfo->ring_head)
+					     dinfo->ring_head)
 				- (dinfo->ring_tail + RING_MIN_FREE);
-		if ((u32 __iomem) dinfo->ring_head != last_head) {
+		if (dinfo->ring_head != last_head) {
 			end = jiffies + (HZ * 3);
-			last_head = (u32 __iomem) dinfo->ring_head;
+			last_head = dinfo->ring_head;
 		}
 		i++;
 		if (time_before(end, jiffies)) {
@@ -1339,15 +1493,13 @@
 	DBG_MSG("refresh_ring\n");
 #endif
 
-	dinfo->ring_head = (u8 __iomem *) (INREG(PRI_RING_HEAD) &
-					   RING_HEAD_MASK);
+	dinfo->ring_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
 	dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
-	if (dinfo->ring_tail + RING_MIN_FREE < (u32 __iomem)dinfo->ring_head)
-		dinfo->ring_space = (u32 __iomem) dinfo->ring_head
+	if (dinfo->ring_tail + RING_MIN_FREE < dinfo->ring_head)
+		dinfo->ring_space = dinfo->ring_head
 			- (dinfo->ring_tail + RING_MIN_FREE);
 	else
-		dinfo->ring_space = (dinfo->ring.size +
-				     (u32 __iomem) dinfo->ring_head)
+		dinfo->ring_space = (dinfo->ring.size + dinfo->ring_head)
 			- (dinfo->ring_tail + RING_MIN_FREE);
 }
 
@@ -1616,7 +1768,7 @@
 	DBG_MSG("intelfbhw_cursor_init\n");
 #endif
 
-	if (dinfo->mobile) {
+	if (dinfo->mobile || IS_I9XX(dinfo)) {
 		if (!dinfo->cursor.physical)
 			return;
 		tmp = INREG(CURSOR_A_CONTROL);
@@ -1649,7 +1801,7 @@
 #endif
 
 	dinfo->cursor_on = 0;
-	if (dinfo->mobile) {
+	if (dinfo->mobile || IS_I9XX(dinfo)) {
 		if (!dinfo->cursor.physical)
 			return;
 		tmp = INREG(CURSOR_A_CONTROL);
@@ -1679,7 +1831,7 @@
 	if (dinfo->cursor_blanked)
 		return;
 
-	if (dinfo->mobile) {
+	if (dinfo->mobile || IS_I9XX(dinfo)) {
 		if (!dinfo->cursor.physical)
 			return;
 		tmp = INREG(CURSOR_A_CONTROL);
@@ -1705,14 +1857,18 @@
 #endif
 
 	/*
-	 * Sets the position.  The coordinates are assumed to already
-	 * have any offset adjusted.  Assume that the cursor is never
+	 * Sets the position. The coordinates are assumed to already
+	 * have any offset adjusted. Assume that the cursor is never
 	 * completely off-screen, and that x, y are always >= 0.
 	 */
 
 	tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
 	      ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
 	OUTREG(CURSOR_A_POSITION, tmp);
+
+	if (IS_I9XX(dinfo)) {
+		OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
+	}
 }
 
 void
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
index ba19201..10acda0 100644
--- a/drivers/video/intelfb/intelfbhw.h
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -133,6 +133,7 @@
 #define DPLL_VGA_MODE_DISABLE		(1 << 28)
 #define DPLL_P2_MASK			1
 #define DPLL_P2_SHIFT			23
+#define DPLL_I9XX_P2_SHIFT              24
 #define DPLL_P1_FORCE_DIV2		(1 << 21)
 #define DPLL_P1_MASK			0x1f
 #define DPLL_P1_SHIFT			16
@@ -155,29 +156,8 @@
 /* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
 /* Clock values are in units of kHz */
 #define PLL_REFCLK		48000
-#define MIN_VCO_FREQ		930000
-#define MAX_VCO_FREQ		1400000
 #define MIN_CLOCK		25000
 #define MAX_CLOCK		350000
-#define P_TRANSITION_CLOCK	165000
-#define MIN_M			108
-#define MAX_M			140
-#define MIN_M1			18
-#define MAX_M1			26
-#define MIN_M2			6
-#define MAX_M2			16
-#define MIN_P			4
-#define MAX_P			128
-#define MIN_P1			0
-#define MAX_P1			31
-#define MIN_N			3
-#define MAX_N			16
-
-#define CALC_VCLOCK(m1, m2, n, p1, p2) \
-        ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \
-        (((p1) + 2) * (1 << (p2 + 1))))
-
-#define CALC_VCLOCK3(m, n, p)	((PLL_REFCLK * (m) / (n)) / (p))
 
 /* Two pipes */
 #define PIPE_A			0
@@ -522,8 +502,7 @@
 
 
 /* function protoypes */
-extern int intelfbhw_get_chipset(struct pci_dev *pdev, const char **name,
-				 int *chipset, int *mobile);
+extern int intelfbhw_get_chipset(struct pci_dev *pdev, struct intelfb_info *dinfo);
 extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
 				int *stolen_size);
 extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index c0385c6..d21321c 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -327,7 +327,6 @@
     }
     return -EINVAL;
 }
-EXPORT_SYMBOL(mac_var_to_vmode);
 
 /**
  *	mac_map_monitor_sense - Convert monitor sense to vmode
@@ -371,8 +370,9 @@
  *
  */
 
-int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
-			 const char *mode_option, unsigned int default_bpp)
+int __devinit mac_find_mode(struct fb_var_screeninfo *var,
+			    struct fb_info *info, const char *mode_option,
+			    unsigned int default_bpp)
 {
     const struct fb_videomode *db = NULL;
     unsigned int dbsize = 0;
diff --git a/drivers/video/macmodes.h b/drivers/video/macmodes.h
index 232f5a09..babeb81 100644
--- a/drivers/video/macmodes.h
+++ b/drivers/video/macmodes.h
@@ -55,9 +55,10 @@
 extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
 			    int *cmode);
 extern int mac_map_monitor_sense(int sense);
-extern int __init mac_find_mode(struct fb_var_screeninfo *var,
-				struct fb_info *info, const char *mode_option,
-				unsigned int default_bpp);
+extern int __devinit mac_find_mode(struct fb_var_screeninfo *var,
+				   struct fb_info *info,
+				   const char *mode_option,
+				   unsigned int default_bpp);
 
 
     /*
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 23c1827..f4ddd34 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -102,6 +102,8 @@
 #include <linux/config.h>
 #include <linux/version.h>
 
+#define __OLD_VIDIOC_
+
 #include "matroxfb_base.h"
 #include "matroxfb_misc.h"
 #include "matroxfb_accel.h"
@@ -158,9 +160,9 @@
 
 	/* Make sure that displays are compatible */
 	if (info && (info->fbcon.var.bits_per_pixel == ACCESS_FBINFO(fbcon).var.bits_per_pixel)
-	         && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
-	         && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
-	         ) {
+		 && (info->fbcon.var.xres_virtual == ACCESS_FBINFO(fbcon).var.xres_virtual)
+		 && (info->fbcon.var.green.length == ACCESS_FBINFO(fbcon).var.green.length)
+		 ) {
 		switch (ACCESS_FBINFO(fbcon).var.bits_per_pixel) {
 			case 16:
 			case 32:
@@ -224,7 +226,7 @@
 
 int matroxfb_enable_irq(WPMINFO int reenable) {
 	u_int32_t bm;
-	
+
 	if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400)
 		bm = 0x220;
 	else
@@ -241,7 +243,7 @@
 		mga_outl(M_IEN, mga_inl(M_IEN) | bm);
 	} else if (reenable) {
 		u_int32_t ien;
-		
+
 		ien = mga_inl(M_IEN);
 		if ((ien & bm) != bm) {
 			printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
@@ -347,7 +349,7 @@
 		mga_setr(M_EXTVGA_INDEX, 0x00, p2);
 	}
 	matroxfb_DAC_unlock_irqrestore(flags);
-	
+
 	update_crtc2(PMINFO pos);
 
 	CRITEND
@@ -390,7 +392,7 @@
 static int matroxfb_open(struct fb_info *info, int user)
 {
 	MINFO_FROM_INFO(info);
-	
+
 	DBG_LOOP(__FUNCTION__)
 
 	if (ACCESS_FBINFO(dead)) {
@@ -406,7 +408,7 @@
 static int matroxfb_release(struct fb_info *info, int user)
 {
 	MINFO_FROM_INFO(info);
-	
+
 	DBG_LOOP(__FUNCTION__)
 
 	if (user) {
@@ -854,7 +856,7 @@
 		vblank->flags |= FB_VBLANK_VBLANKING;
 	if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {
 		vblank->flags |= FB_VBLANK_HAVE_COUNT;
-		/* Only one writer, aligned int value... 
+		/* Only one writer, aligned int value...
 		   it should work without lock and without atomic_t */
 		vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt;
 	}
@@ -870,7 +872,7 @@
 {
 	void __user *argp = (void __user *)arg;
 	MINFO_FROM_INFO(info);
-	
+
 	DBG(__FUNCTION__)
 
 	if (ACCESS_FBINFO(dead)) {
@@ -1081,7 +1083,7 @@
 		case VIDIOC_QUERYCAP:
 			{
 				struct v4l2_capability r;
-				
+
 				memset(&r, 0, sizeof(r));
 				strcpy(r.driver, "matroxfb");
 				strcpy(r.card, "Matrox");
@@ -1091,7 +1093,7 @@
 				if (copy_to_user(argp, &r, sizeof(r)))
 					return -EFAULT;
 				return 0;
-				
+
 			}
 		case VIDIOC_QUERYCTRL:
 			{
@@ -1690,8 +1692,8 @@
 		pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, &cmd);
 		mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
 		mga_option |= MX_OPTION_BSWAP;
-                /* disable palette snooping */
-                cmd &= ~PCI_COMMAND_VGA_PALETTE;
+		/* disable palette snooping */
+		cmd &= ~PCI_COMMAND_VGA_PALETTE;
 		if (pci_dev_present(intel_82437)) {
 			if (!(mga_option & 0x20000000) && !ACCESS_FBINFO(devflags.nopciretry)) {
 				printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
@@ -1809,12 +1811,12 @@
 
 		if (fv) {
 			tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
-			          + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
+				  + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
 			if ((tmp < fh) || (fh == 0)) fh = tmp;
 		}
 		if (fh) {
 			tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
-			          + vesafb_defined.right_margin + vesafb_defined.hsync_len);
+				  + vesafb_defined.right_margin + vesafb_defined.hsync_len);
 			if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
 		}
 		tmp = (maxclk + 499) / 500;
@@ -1890,14 +1892,14 @@
 
 	/* there is no console on this fb... but we have to initialize hardware
 	 * until someone tells me what is proper thing to do */
- 	if (!ACCESS_FBINFO(initialized)) {
- 		printk(KERN_INFO "fb%d: initializing hardware\n",
- 		       ACCESS_FBINFO(fbcon.node));
- 		/* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
- 		 * already before, so register_framebuffer works correctly. */
- 		vesafb_defined.activate |= FB_ACTIVATE_FORCE;
- 		fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
- 	}
+	if (!ACCESS_FBINFO(initialized)) {
+		printk(KERN_INFO "fb%d: initializing hardware\n",
+		       ACCESS_FBINFO(fbcon.node));
+		/* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
+		 * already before, so register_framebuffer works correctly. */
+		vesafb_defined.activate |= FB_ACTIVATE_FORCE;
+		fb_set_var(&ACCESS_FBINFO(fbcon), &vesafb_defined);
+	}
 
 	return 0;
 failVideoIO:;
@@ -2356,7 +2358,7 @@
 		else if (!strncmp(this_opt, "dfp:", 4)) {
 			dfp_type = simple_strtoul(this_opt+4, NULL, 0);
 			dfp = 1;
-		}	
+		}
 #ifdef CONFIG_PPC_PMAC
 		else if (!strncmp(this_opt, "vmode:", 6)) {
 			unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index 26a1c61..ff54546 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -259,6 +259,10 @@
 	/* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */
 	NULL, 60, 1152, 768, 15386, 158, 26, 29, 3, 136, 6,
 	FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+    }, {
+	/* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */
+	NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5,
+	0, FB_VMODE_NONINTERLACED
     },
 };
 
@@ -787,8 +791,9 @@
 			if (diff > d) {
 				diff = d;
 				best = mode;
-			} else if (diff == d && mode->refresh > best->refresh)
-			    best = mode;
+			} else if (diff == d && best &&
+				   mode->refresh > best->refresh)
+				best = mode;
 		}
 	}
 	return best;
@@ -1016,8 +1021,6 @@
 EXPORT_SYMBOL(fb_var_to_videomode);
 EXPORT_SYMBOL(fb_mode_is_equal);
 EXPORT_SYMBOL(fb_add_videomode);
-EXPORT_SYMBOL(fb_delete_videomode);
-EXPORT_SYMBOL(fb_destroy_modelist);
 EXPORT_SYMBOL(fb_match_mode);
 EXPORT_SYMBOL(fb_find_best_mode);
 EXPORT_SYMBOL(fb_find_nearest_mode);
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c
index 24b12f7..2f156b7 100644
--- a/drivers/video/neofb.c
+++ b/drivers/video/neofb.c
@@ -1333,17 +1333,22 @@
 	 *  run "setterm -powersave powerdown" to take advantage
 	 */
 	struct neofb_par *par = info->par;
-	int seqflags, lcdflags, dpmsflags, reg;
-
+	int seqflags, lcdflags, dpmsflags, reg, tmpdisp;
 
 	/*
-	 * Reload the value stored in the register, if sensible. It might have
-	 * been changed via FN keystroke.
+	 * Read back the register bits related to display configuration. They might
+	 * have been changed underneath the driver via Fn key stroke.
+	 */
+	neoUnlock();
+	tmpdisp = vga_rgfx(NULL, 0x20) & 0x03;
+	neoLock(&par->state);
+
+	/* In case we blank the screen, we want to store the possibly new
+	 * configuration in the driver. During un-blank, we re-apply this setting,
+	 * since the LCD bit will be cleared in order to switch off the backlight.
 	 */
 	if (par->PanelDispCntlRegRead) {
-		neoUnlock();
-		par->PanelDispCntlReg1 = vga_rgfx(NULL, 0x20) & 0x03;
-		neoLock(&par->state);
+		par->PanelDispCntlReg1 = tmpdisp;
 	}
 	par->PanelDispCntlRegRead = !blank_mode;
 
@@ -1378,12 +1383,21 @@
 		break;
 	case FB_BLANK_NORMAL:		/* just blank screen (backlight stays on) */
 		seqflags = VGA_SR01_SCREEN_OFF;	/* Disable sequencer */
-		lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
+		/*
+		 * During a blank operation with the LID shut, we might store "LCD off"
+		 * by mistake. Due to timing issues, the BIOS may switch the lights
+		 * back on, and we turn it back off once we "unblank".
+		 *
+		 * So here is an attempt to implement ">=" - if we are in the process
+		 * of unblanking, and the LCD bit is unset in the driver but set in the
+		 * register, we must keep it.
+		 */
+		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
 		dpmsflags = 0x00;	/* no hsync/vsync suppression */
 		break;
 	case FB_BLANK_UNBLANK:		/* unblank */
 		seqflags = 0;			/* Enable sequencer */
-		lcdflags = par->PanelDispCntlReg1 & 0x02; /* LCD normal */
+		lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02); /* LCD normal */
 		dpmsflags = 0x00;	/* no hsync/vsync suppression */
 #ifdef CONFIG_TOSHIBA
 		/* Do we still need this ? */
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile
index 690d37e..ca47432 100644
--- a/drivers/video/nvidia/Makefile
+++ b/drivers/video/nvidia/Makefile
@@ -7,6 +7,7 @@
 nvidiafb-y                       := nvidia.o nv_hw.o nv_setup.o \
 			            nv_accel.o
 nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
+nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT)  += nv_backlight.o
 nvidiafb-$(CONFIG_PPC_OF)	 += nv_of.o
 
-nvidiafb-objs                    := $(nvidiafb-y)
\ No newline at end of file
+nvidiafb-objs                    := $(nvidiafb-y)
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
new file mode 100644
index 0000000..1c1c10c
--- /dev/null
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -0,0 +1,175 @@
+/*
+ * Backlight code for nVidia based graphic cards
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#include <asm/machdep.h>
+#endif
+
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
+
+static struct backlight_properties nvidia_bl_data;
+
+static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
+		int level)
+{
+	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+	int nlevel;
+
+	/* Get and convert the value */
+	mutex_lock(&info->bl_mutex);
+	nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
+	mutex_unlock(&info->bl_mutex);
+
+	if (nlevel < 0)
+		nlevel = 0;
+	else if (nlevel < MIN_LEVEL)
+		nlevel = MIN_LEVEL;
+	else if (nlevel > MAX_LEVEL)
+		nlevel = MAX_LEVEL;
+
+	return nlevel;
+}
+
+static int nvidia_bl_update_status(struct backlight_device *bd)
+{
+	struct nvidia_par *par = class_get_devdata(&bd->class_dev);
+	u32 tmp_pcrt, tmp_pmc, fpcontrol;
+	int level;
+
+	if (!par->FlatPanel)
+		return 0;
+
+	if (bd->props->power != FB_BLANK_UNBLANK ||
+	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props->brightness;
+
+	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
+	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
+	fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
+
+	if (level > 0) {
+		tmp_pcrt |= 0x1;
+		tmp_pmc |= (1 << 31); /* backlight bit */
+		tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
+		fpcontrol |= par->fpSyncs;
+	} else
+		fpcontrol |= 0x20000022;
+
+	NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
+	NV_WR32(par->PMC, 0x10F0, tmp_pmc);
+	NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
+
+	return 0;
+}
+
+static int nvidia_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props->brightness;
+}
+
+static struct backlight_properties nvidia_bl_data = {
+	.owner		= THIS_MODULE,
+	.get_brightness = nvidia_bl_get_brightness,
+	.update_status	= nvidia_bl_update_status,
+	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void nvidia_bl_init(struct nvidia_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+	struct backlight_device *bd;
+	char name[12];
+
+	if (!par->FlatPanel)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!machine_is(powermac) ||
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	snprintf(name, sizeof(name), "nvidiabl%d", info->node);
+
+	bd = backlight_device_register(name, par, &nvidia_bl_data);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk("nvidia: Backlight registration failed\n");
+		goto error;
+	}
+
+	mutex_lock(&info->bl_mutex);
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+		0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+	mutex_unlock(&info->bl_mutex);
+
+	up(&bd->sem);
+	bd->props->brightness = nvidia_bl_data.max_brightness;
+	bd->props->power = FB_BLANK_UNBLANK;
+	bd->props->update_status(bd);
+	down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = bd;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+	printk("nvidia: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+void nvidia_bl_exit(struct nvidia_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pci_dev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+#endif
+
+	mutex_lock(&info->bl_mutex);
+	if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+		if (pmac_backlight == info->bl_dev)
+			pmac_backlight = NULL;
+#endif
+
+		backlight_device_unregister(info->bl_dev);
+
+		printk("nvidia: Backlight unloaded\n");
+	}
+	mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index 99c3a8e..9ed640d 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -886,7 +886,10 @@
 	case NV_ARCH_20:
 	case NV_ARCH_30:
 	default:
-		if (((par->Chipset & 0xffff) == 0x01A0) ||
+		if ((par->Chipset & 0xfff0) == 0x0240) {
+			state->arbitration0 = 256;
+			state->arbitration1 = 0x0480;
+		} else if (((par->Chipset & 0xffff) == 0x01A0) ||
 		    ((par->Chipset & 0xffff) == 0x01f0)) {
 			nForceUpdateArbitrationSettings(VClk,
 							pixelDepth * 8,
@@ -1235,6 +1238,7 @@
 					break;
 				case 0x0160:
 				case 0x01D0:
+				case 0x0240:
 					NV_WR32(par->PMC, 0x1700,
 						NV_RD32(par->PFB, 0x020C));
 					NV_WR32(par->PMC, 0x1704, 0);
@@ -1359,7 +1363,9 @@
 						if(((par->Chipset & 0xfff0)
 						    != 0x0160) &&
 						   ((par->Chipset & 0xfff0)
-						    != 0x0220))
+						    != 0x0220) &&
+						   ((par->Chipset & 0xfff0)
+						    != 0x240))
 							NV_WR32(par->PGRAPH,
 								0x6900 + i*4,
 								NV_RD32(par->PFB,
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index b149a69..6fba656 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -63,4 +63,14 @@
 			       const struct fb_image *image);
 extern int nvidiafb_sync(struct fb_info *info);
 extern u8 byte_rev[256];
+
+/* in nv_backlight.h */
+#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
+extern void nvidia_bl_init(struct nvidia_par *par);
+extern void nvidia_bl_exit(struct nvidia_par *par);
+#else
+static inline void nvidia_bl_init(struct nvidia_par *par) {}
+static inline void nvidia_bl_exit(struct nvidia_par *par) {}
+#endif
+
 #endif				/* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 093ab99..7b5cffb 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/console.h>
+#include <linux/backlight.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
@@ -29,10 +30,6 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/machdep.h>
-#include <asm/backlight.h>
-#endif
 
 #include "nv_local.h"
 #include "nv_type.h"
@@ -70,359 +67,10 @@
 #define MAX_CURS		32
 
 static struct pci_device_id nvidiafb_pci_tbl[] = {
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0252,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0313,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0316,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0317,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x031D,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x031E,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x031F,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0329,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x032F,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0345,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0349,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x034B,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x034F,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x00c0,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A_LE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_GO1400,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x00cd,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_1400,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0142,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0143,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0144,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0145,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0146,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0147,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0148,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0149,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x014b,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x14c,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x014d,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0160,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0162,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0163,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0165,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0169,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x016b,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x016c,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x016d,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x016e,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0210,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x021d,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x021e,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0220,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0221,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0222,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{PCI_VENDOR_ID_NVIDIA, 0x0228,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0,}			/* terminate list */
+	{PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+	 PCI_BASE_CLASS_DISPLAY << 16, 0xff0000, 0},
+	{ 0, }
 };
-
 MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
 
 /* command line data, set in nvidiafb_setup() */
@@ -470,75 +118,6 @@
 	.vmode = FB_VMODE_NONINTERLACED
 };
 
-/*
- * Backlight control
- */
-#ifdef CONFIG_PMAC_BACKLIGHT
-
-static int nvidia_backlight_levels[] = {
-	0x158,
-	0x192,
-	0x1c6,
-	0x200,
-	0x234,
-	0x268,
-	0x2a2,
-	0x2d6,
-	0x310,
-	0x344,
-	0x378,
-	0x3b2,
-	0x3e6,
-	0x41a,
-	0x454,
-	0x534,
-};
-
-/* ------------------------------------------------------------------------- *
- *
- * Backlight operations
- *
- * ------------------------------------------------------------------------- */
-
-static int nvidia_set_backlight_enable(int on, int level, void *data)
-{
-	struct nvidia_par *par = data;
-	u32 tmp_pcrt, tmp_pmc, fpcontrol;
-
-	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
-	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
-	fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
-
-	if (on && (level > BACKLIGHT_OFF)) {
-		tmp_pcrt |= 0x1;
-		tmp_pmc |= (1 << 31);	// backlight bit
-		tmp_pmc |= nvidia_backlight_levels[level - 1] << 16;
-	}
-
-	if (on)
-		fpcontrol |= par->fpSyncs;
-	else
-		fpcontrol |= 0x20000022;
-
-	NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
-	NV_WR32(par->PMC, 0x10F0, tmp_pmc);
-	NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
-
-	return 0;
-}
-
-static int nvidia_set_backlight_level(int level, void *data)
-{
-	return nvidia_set_backlight_enable(1, level, data);
-}
-
-static struct backlight_controller nvidia_backlight_controller = {
-	nvidia_set_backlight_enable,
-	nvidia_set_backlight_level
-};
-
-#endif				/* CONFIG_PMAC_BACKLIGHT */
-
 static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
 				       u16 bg, u16 fg, u32 w, u32 h)
 {
@@ -1355,10 +934,15 @@
 	NVWriteSeq(par, 0x01, tmp);
 	NVWriteCrtc(par, 0x1a, vesa);
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (par->FlatPanel && machine_is(powermac)) {
-		set_backlight_enable(!blank);
+#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
+	mutex_lock(&info->bl_mutex);
+	if (info->bl_dev) {
+		down(&info->bl_dev->sem);
+		info->bl_dev->props->power = blank;
+		info->bl_dev->props->update_status(info->bl_dev);
+		up(&info->bl_dev->sem);
 	}
+	mutex_unlock(&info->bl_mutex);
 #endif
 
 	NVTRACE_LEAVE();
@@ -1532,10 +1116,10 @@
 	struct nvidia_par *par = info->par;
 	u32 id = (par->pci_dev->vendor << 16) | par->pci_dev->device;
 
-	printk("nvidiafb: PCI id - %x\n", id);
+	printk(KERN_INFO PFX "Device ID: %x \n", id);
+
 	if ((id & 0xfff0) == 0x00f0) {
 		/* pci-e */
-		printk("nvidiafb: PCI-E card\n");
 		id = NV_RD32(par->REGS, 0x1800);
 
 		if ((id & 0x0000ffff) == 0x000010DE)
@@ -1543,9 +1127,9 @@
 		else if ((id & 0xffff0000) == 0xDE100000) /* wrong endian */
 			id = 0x10DE0000 | ((id << 8) & 0x0000ff00) |
                             ((id >> 8) & 0x000000ff);
+		printk(KERN_INFO PFX "Subsystem ID: %x \n", id);
 	}
 
-	printk("nvidiafb: Actual id - %x\n", id);
 	return id;
 }
 
@@ -1587,6 +1171,7 @@
 	case 0x0210:
 	case 0x0220:
 	case 0x0230:
+	case 0x0240:
 	case 0x0290:
 	case 0x0390:
 		arch = NV_ARCH_40;
@@ -1634,7 +1219,7 @@
 
 	if (pci_request_regions(pd, "nvidiafb")) {
 		printk(KERN_ERR PFX "cannot request PCI regions\n");
-		goto err_out_request;
+		goto err_out_enable;
 	}
 
 	par->FlatPanel = flatpanel;
@@ -1663,7 +1248,6 @@
 	}
 
 	par->Chipset = nvidia_get_chipset(info);
-	printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
 	par->Architecture = nvidia_get_arch(info);
 
 	if (par->Architecture == 0) {
@@ -1741,11 +1325,9 @@
 	       "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
 	       info->fix.id,
 	       par->FbMapSize / (1024 * 1024), info->fix.smem_start);
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (par->FlatPanel && machine_is(powermac))
-		register_backlight_controller(&nvidia_backlight_controller,
-					      par, "mnca");
-#endif
+
+	nvidia_bl_init(par);
+
 	NVTRACE_LEAVE();
 	return 0;
 
@@ -1756,10 +1338,8 @@
 	nvidia_delete_i2c_busses(par);
 err_out_arch:
 	iounmap(par->REGS);
-err_out_free_base0:
+ err_out_free_base0:
 	pci_release_regions(pd);
-err_out_request:
-	pci_disable_device(pd);
 err_out_enable:
 	kfree(info->pixmap.addr);
 err_out_kfree:
@@ -1775,6 +1355,8 @@
 
 	NVTRACE_ENTER();
 
+	nvidia_bl_exit(par);
+
 	unregister_framebuffer(info);
 #ifdef CONFIG_MTRR
 	if (par->mtrr.vram_valid)
@@ -1787,7 +1369,6 @@
 	nvidia_delete_i2c_busses(par);
 	iounmap(par->REGS);
 	pci_release_regions(pd);
-	pci_disable_device(pd);
 	kfree(info->pixmap.addr);
 	framebuffer_release(info);
 	pci_set_drvdata(pd, NULL);
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 3e9308f..12af58c 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -41,6 +41,7 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/backlight.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
@@ -272,34 +273,154 @@
 /*
  * Backlight control
  */
+#ifdef CONFIG_FB_RIVA_BACKLIGHT
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
+
+static struct backlight_properties riva_bl_data;
+
+static int riva_bl_get_level_brightness(struct riva_par *par,
+		int level)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	int nlevel;
+
+	/* Get and convert the value */
+	mutex_lock(&info->bl_mutex);
+	nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
+	mutex_unlock(&info->bl_mutex);
+
+	if (nlevel < 0)
+		nlevel = 0;
+	else if (nlevel < MIN_LEVEL)
+		nlevel = MIN_LEVEL;
+	else if (nlevel > MAX_LEVEL)
+		nlevel = MAX_LEVEL;
+
+	return nlevel;
+}
+
+static int riva_bl_update_status(struct backlight_device *bd)
+{
+	struct riva_par *par = class_get_devdata(&bd->class_dev);
+	U032 tmp_pcrt, tmp_pmc;
+	int level;
+
+	if (bd->props->power != FB_BLANK_UNBLANK ||
+	    bd->props->fb_blank != FB_BLANK_UNBLANK)
+		level = 0;
+	else
+		level = bd->props->brightness;
+
+	tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
+	tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
+	if(level > 0) {
+		tmp_pcrt |= 0x1;
+		tmp_pmc |= (1 << 31); /* backlight bit */
+		tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
+	}
+	par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
+	par->riva.PMC[0x10F0/4] = tmp_pmc;
+
+	return 0;
+}
+
+static int riva_bl_get_brightness(struct backlight_device *bd)
+{
+	return bd->props->brightness;
+}
+
+static struct backlight_properties riva_bl_data = {
+	.owner    = THIS_MODULE,
+	.get_brightness = riva_bl_get_brightness,
+	.update_status	= riva_bl_update_status,
+	.max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+static void riva_bl_init(struct riva_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+	struct backlight_device *bd;
+	char name[12];
+
+	if (!par->FlatPanel)
+		return;
+
 #ifdef CONFIG_PMAC_BACKLIGHT
+	if (!machine_is(powermac) ||
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
 
-static int riva_backlight_levels[] = {
-    0x158,
-    0x192,
-    0x1c6,
-    0x200,
-    0x234,
-    0x268,
-    0x2a2,
-    0x2d6,
-    0x310,
-    0x344,
-    0x378,
-    0x3b2,
-    0x3e6,
-    0x41a,
-    0x454,
-    0x534,
-};
+	snprintf(name, sizeof(name), "rivabl%d", info->node);
 
-static int riva_set_backlight_enable(int on, int level, void *data);
-static int riva_set_backlight_level(int level, void *data);
-static struct backlight_controller riva_backlight_controller = {
-	riva_set_backlight_enable,
-	riva_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
+	bd = backlight_device_register(name, par, &riva_bl_data);
+	if (IS_ERR(bd)) {
+		info->bl_dev = NULL;
+		printk("riva: Backlight registration failed\n");
+		goto error;
+	}
+
+	mutex_lock(&info->bl_mutex);
+	info->bl_dev = bd;
+	fb_bl_default_curve(info, 0,
+		0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+		0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+	mutex_unlock(&info->bl_mutex);
+
+	up(&bd->sem);
+	bd->props->brightness = riva_bl_data.max_brightness;
+	bd->props->power = FB_BLANK_UNBLANK;
+	bd->props->update_status(bd);
+	down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+	if (!pmac_backlight)
+		pmac_backlight = bd;
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+	printk("riva: Backlight initialized (%s)\n", name);
+
+	return;
+
+error:
+	return;
+}
+
+static void riva_bl_exit(struct riva_par *par)
+{
+	struct fb_info *info = pci_get_drvdata(par->pdev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_lock(&pmac_backlight_mutex);
+#endif
+
+	mutex_lock(&info->bl_mutex);
+	if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+		if (pmac_backlight == info->bl_dev)
+			pmac_backlight = NULL;
+#endif
+
+		backlight_device_unregister(info->bl_dev);
+
+		printk("riva: Backlight unloaded\n");
+	}
+	mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
+#else
+static inline void riva_bl_init(struct riva_par *par) {}
+static inline void riva_bl_exit(struct riva_par *par) {}
+#endif /* CONFIG_FB_RIVA_BACKLIGHT */
 
 /* ------------------------------------------------------------------------- *
  *
@@ -973,36 +1094,6 @@
 
 /* ------------------------------------------------------------------------- *
  *
- * Backlight operations
- *
- * ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int riva_set_backlight_enable(int on, int level, void *data)
-{
-	struct riva_par *par = data;
-	U032 tmp_pcrt, tmp_pmc;
-
-	tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
-	tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
-	if(on && (level > BACKLIGHT_OFF)) {
-		tmp_pcrt |= 0x1;
-		tmp_pmc |= (1 << 31); // backlight bit
-		tmp_pmc |= riva_backlight_levels[level-1] << 16; // level
-	}
-	par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
-	par->riva.PMC[0x10F0/4] = tmp_pmc;
-	return 0;
-}
-
-static int riva_set_backlight_level(int level, void *data)
-{
-	return riva_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-/* ------------------------------------------------------------------------- *
- *
  * framebuffer operations
  *
  * ------------------------------------------------------------------------- */
@@ -1247,10 +1338,15 @@
 	SEQout(par, 0x01, tmp);
 	CRTCout(par, 0x1a, vesa);
 
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if ( par->FlatPanel && machine_is(powermac)) {
-		set_backlight_enable(!blank);
+#ifdef CONFIG_FB_RIVA_BACKLIGHT
+	mutex_lock(&info->bl_mutex);
+	if (info->bl_dev) {
+		down(&info->bl_dev->sem);
+		info->bl_dev->props->power = blank;
+		info->bl_dev->props->update_status(info->bl_dev);
+		up(&info->bl_dev->sem);
 	}
+	mutex_unlock(&info->bl_mutex);
 #endif
 
 	NVTRACE_LEAVE();
@@ -2037,11 +2133,9 @@
 		RIVAFB_VERSION,
 		info->fix.smem_len / (1024 * 1024),
 		info->fix.smem_start);
-#ifdef CONFIG_PMAC_BACKLIGHT
-	if (default_par->FlatPanel && machine_is(powermac))
-		register_backlight_controller(&riva_backlight_controller,
-					      default_par, "mnca");
-#endif
+
+	riva_bl_init(info->par);
+
 	NVTRACE_LEAVE();
 	return 0;
 
@@ -2058,7 +2152,6 @@
 err_release_region:
 	pci_release_regions(pd);
 err_disable_device:
-	pci_disable_device(pd);
 err_free_pixmap:
 	kfree(info->pixmap.addr);
 err_framebuffer_release:
@@ -2074,6 +2167,8 @@
 	
 	NVTRACE_ENTER();
 
+	riva_bl_exit(par);
+
 #ifdef CONFIG_FB_RIVA_I2C
 	riva_delete_i2c_busses(par);
 	kfree(par->EDID);
@@ -2091,7 +2186,6 @@
 	if (par->riva.Architecture == NV_ARCH_03)
 		iounmap(par->riva.PRAMIN);
 	pci_release_regions(pd);
-	pci_disable_device(pd);
 	kfree(info->pixmap.addr);
 	framebuffer_release(info);
 	pci_set_drvdata(pd, NULL);
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index 9451932..fbc4118 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -641,6 +641,7 @@
 	int ret;
 	int irq;
 	int i;
+	u32 lcdcon1;
 
 	mach_info = pdev->dev.platform_data;
 	if (mach_info == NULL) {
@@ -672,6 +673,11 @@
 
 	memcpy(&info->regs, &mach_info->regs, sizeof(info->regs));
 
+	/* Stop the video and unset ENVID if set */
+	info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
+	lcdcon1 = readl(S3C2410_LCDCON1);
+	writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+
 	info->mach_info		    = pdev->dev.platform_data;
 
 	fbinfo->fix.type	    = FB_TYPE_PACKED_PIXELS;
@@ -794,15 +800,14 @@
  * shutdown the lcd controller
 */
 
-static void s3c2410fb_stop_lcd(void)
+static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi)
 {
 	unsigned long flags;
-	unsigned long tmp;
 
 	local_irq_save(flags);
 
-	tmp = readl(S3C2410_LCDCON1);
-	writel(tmp & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1);
+	fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;
+	writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);
 
 	local_irq_restore(flags);
 }
@@ -816,7 +821,7 @@
 	struct s3c2410fb_info *info = fbinfo->par;
 	int irq;
 
-	s3c2410fb_stop_lcd();
+	s3c2410fb_stop_lcd(info);
 	msleep(1);
 
 	s3c2410fb_unmap_video_memory(info);
@@ -844,7 +849,7 @@
 	struct fb_info	   *fbinfo = platform_get_drvdata(dev);
 	struct s3c2410fb_info *info = fbinfo->par;
 
-	s3c2410fb_stop_lcd();
+	s3c2410fb_stop_lcd(info);
 
 	/* sleep before disabling the clock, we need to ensure
 	 * the LCD DMA engine is not going to get back on the bus
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index 58cfdfb..e648a6c 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -147,77 +147,7 @@
 	int	       interlaced;
 };
 
-
-/* --------------------------------------------------------------------- */
-
-#define NR_PALETTE	256
-
-
-struct savagefb_par;
-
-struct savagefb_i2c_chan {
-	struct savagefb_par *par;
-	struct i2c_adapter adapter;
-	struct i2c_algo_bit_data algo;
-	volatile u8 __iomem *ioaddr;
-	u32   reg;
-};
-
-struct savagefb_par {
-	struct pci_dev *pcidev;
-	savage_chipset  chip;
-	struct savagefb_i2c_chan chan;
-	unsigned char   *edid;
-	u32 pseudo_palette[16];
-	int paletteEnabled;
-	int pm_state;
-	int display_type;
-	int dvi;
-	int crtonly;
-	int dacSpeedBpp;
-	int maxClock;
-	int minClock;
-	int numClocks;
-	int clock[4];
-	struct {
-		u8   __iomem *vbase;
-		u32    pbase;
-		u32    len;
-#ifdef CONFIG_MTRR
-		int    mtrr;
-#endif
-	} video;
-
-	struct {
-		volatile u8  __iomem *vbase;
-		u32           pbase;
-		u32           len;
-	} mmio;
-
-	volatile u32  __iomem *bci_base;
-	unsigned int  bci_ptr;
-
-	u32           cob_offset;
-	u32           cob_size;
-	int           cob_index;
-
-	void (*SavageWaitIdle) (struct savagefb_par *par);
-	void (*SavageWaitFifo) (struct savagefb_par *par, int space);
-
-	int MCLK, REFCLK, LCDclk;
-	int HorizScaleFactor;
-
-	/* Panels size */
-	int SavagePanelWidth;
-	int SavagePanelHeight;
-
-	struct {
-		u16 red, green, blue, transp;
-	} palette[NR_PALETTE];
-
-	int depth;
-	int vwidth;
-
+struct savage_reg {
 	unsigned char MiscOutReg;     /* Misc */
 	unsigned char CRTC[25];       /* Crtc Controller */
 	unsigned char Sequencer[5];   /* Video Sequencer */
@@ -238,6 +168,77 @@
 	unsigned int  STREAMS[22];	/* yuck, streams regs */
 	unsigned int  MMPR0, MMPR1, MMPR2, MMPR3;
 };
+/* --------------------------------------------------------------------- */
+
+#define NR_PALETTE	256
+
+
+struct savagefb_par;
+
+struct savagefb_i2c_chan {
+	struct savagefb_par *par;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+	volatile u8 __iomem *ioaddr;
+	u32   reg;
+};
+
+struct savagefb_par {
+	struct pci_dev *pcidev;
+	savage_chipset  chip;
+	struct savagefb_i2c_chan chan;
+	struct savage_reg state;
+	struct savage_reg save;
+	unsigned char   *edid;
+	u32 pseudo_palette[16];
+	int paletteEnabled;
+	int pm_state;
+	int display_type;
+	int dvi;
+	int crtonly;
+	int dacSpeedBpp;
+	int maxClock;
+	int minClock;
+	int numClocks;
+	int clock[4];
+	int MCLK, REFCLK, LCDclk;
+	struct {
+		u8   __iomem *vbase;
+		u32    pbase;
+		u32    len;
+#ifdef CONFIG_MTRR
+		int    mtrr;
+#endif
+	} video;
+
+	struct {
+		volatile u8  __iomem *vbase;
+		u32           pbase;
+		u32           len;
+	} mmio;
+
+	volatile u32  __iomem *bci_base;
+	unsigned int  bci_ptr;
+	u32           cob_offset;
+	u32           cob_size;
+	int           cob_index;
+
+	void (*SavageWaitIdle) (struct savagefb_par *par);
+	void (*SavageWaitFifo) (struct savagefb_par *par, int space);
+
+	int HorizScaleFactor;
+
+	/* Panels size */
+	int SavagePanelWidth;
+	int SavagePanelHeight;
+
+	struct {
+		u16 red, green, blue, transp;
+	} palette[NR_PALETTE];
+
+	int depth;
+	int vwidth;
+};
 
 #define BCI_BD_BW_DISABLE            0x10000000
 #define BCI_BD_SET_BPP(bd, bpp)      ((bd) |= (((bpp) & 0xFF) << 16))
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 0da624e..78883cf 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -86,15 +86,15 @@
 
 /* --------------------------------------------------------------------- */
 
-static void vgaHWSeqReset (struct savagefb_par *par, int start)
+static void vgaHWSeqReset(struct savagefb_par *par, int start)
 {
 	if (start)
-		VGAwSEQ (0x00, 0x01, par);	/* Synchronous Reset */
+		VGAwSEQ(0x00, 0x01, par);	/* Synchronous Reset */
 	else
-		VGAwSEQ (0x00, 0x03, par);	/* End Reset */
+		VGAwSEQ(0x00, 0x03, par);	/* End Reset */
 }
 
-static void vgaHWProtect (struct savagefb_par *par, int on)
+static void vgaHWProtect(struct savagefb_par *par, int on)
 {
 	unsigned char tmp;
 
@@ -102,10 +102,10 @@
 		/*
 		 * Turn off screen and disable sequencer.
 		 */
-		tmp = VGArSEQ (0x01, par);
+		tmp = VGArSEQ(0x01, par);
 
-		vgaHWSeqReset (par, 1);	        /* start synchronous reset */
-		VGAwSEQ (0x01, tmp | 0x20, par);/* disable the display */
+		vgaHWSeqReset(par, 1);	        /* start synchronous reset */
+		VGAwSEQ(0x01, tmp | 0x20, par);/* disable the display */
 
 		VGAenablePalette(par);
 	} else {
@@ -113,75 +113,76 @@
 		 * Reenable sequencer, then turn on screen.
 		 */
 
-		tmp = VGArSEQ (0x01, par);
+		tmp = VGArSEQ(0x01, par);
 
-		VGAwSEQ (0x01, tmp & ~0x20, par);/* reenable display */
-		vgaHWSeqReset (par, 0);	        /* clear synchronous reset */
+		VGAwSEQ(0x01, tmp & ~0x20, par);/* reenable display */
+		vgaHWSeqReset(par, 0);	        /* clear synchronous reset */
 
 		VGAdisablePalette(par);
 	}
 }
 
-static void vgaHWRestore (struct savagefb_par  *par)
+static void vgaHWRestore(struct savagefb_par  *par, struct savage_reg *reg)
 {
 	int i;
 
-	VGAwMISC (par->MiscOutReg, par);
+	VGAwMISC(reg->MiscOutReg, par);
 
 	for (i = 1; i < 5; i++)
-		VGAwSEQ (i, par->Sequencer[i], par);
+		VGAwSEQ(i, reg->Sequencer[i], par);
 
 	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
 	   CRTC[17] */
-	VGAwCR (17, par->CRTC[17] & ~0x80, par);
+	VGAwCR(17, reg->CRTC[17] & ~0x80, par);
 
 	for (i = 0; i < 25; i++)
-		VGAwCR (i, par->CRTC[i], par);
+		VGAwCR(i, reg->CRTC[i], par);
 
 	for (i = 0; i < 9; i++)
-		VGAwGR (i, par->Graphics[i], par);
+		VGAwGR(i, reg->Graphics[i], par);
 
 	VGAenablePalette(par);
 
 	for (i = 0; i < 21; i++)
-		VGAwATTR (i, par->Attribute[i], par);
+		VGAwATTR(i, reg->Attribute[i], par);
 
 	VGAdisablePalette(par);
 }
 
-static void vgaHWInit (struct fb_var_screeninfo *var,
-		       struct savagefb_par            *par,
-		       struct xtimings                *timings)
+static void vgaHWInit(struct fb_var_screeninfo *var,
+		      struct savagefb_par            *par,
+		      struct xtimings                *timings,
+		      struct savage_reg              *reg)
 {
-	par->MiscOutReg = 0x23;
+	reg->MiscOutReg = 0x23;
 
 	if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
-		par->MiscOutReg |= 0x40;
+		reg->MiscOutReg |= 0x40;
 
 	if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
-		par->MiscOutReg |= 0x80;
+		reg->MiscOutReg |= 0x80;
 
 	/*
 	 * Time Sequencer
 	 */
-	par->Sequencer[0x00] = 0x00;
-	par->Sequencer[0x01] = 0x01;
-	par->Sequencer[0x02] = 0x0F;
-	par->Sequencer[0x03] = 0x00;          /* Font select */
-	par->Sequencer[0x04] = 0x0E;          /* Misc */
+	reg->Sequencer[0x00] = 0x00;
+	reg->Sequencer[0x01] = 0x01;
+	reg->Sequencer[0x02] = 0x0F;
+	reg->Sequencer[0x03] = 0x00;          /* Font select */
+	reg->Sequencer[0x04] = 0x0E;          /* Misc */
 
 	/*
 	 * CRTC Controller
 	 */
-	par->CRTC[0x00] = (timings->HTotal >> 3) - 5;
-	par->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
-	par->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
-	par->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
-	par->CRTC[0x04] = (timings->HSyncStart >> 3);
-	par->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
+	reg->CRTC[0x00] = (timings->HTotal >> 3) - 5;
+	reg->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
+	reg->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
+	reg->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
+	reg->CRTC[0x04] = (timings->HSyncStart >> 3);
+	reg->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
 		(((timings->HSyncEnd >> 3)) & 0x1f);
-	par->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
-	par->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
+	reg->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
+	reg->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
 		(((timings->VDisplay - 1) & 0x100) >> 7) |
 		((timings->VSyncStart & 0x100) >> 6) |
 		(((timings->VSyncStart - 1) & 0x100) >> 5) |
@@ -189,27 +190,27 @@
 		(((timings->VTotal - 2) & 0x200) >> 4) |
 		(((timings->VDisplay - 1) & 0x200) >> 3) |
 		((timings->VSyncStart & 0x200) >> 2);
-	par->CRTC[0x08] = 0x00;
-	par->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
+	reg->CRTC[0x08] = 0x00;
+	reg->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
 
 	if (timings->dblscan)
-		par->CRTC[0x09] |= 0x80;
+		reg->CRTC[0x09] |= 0x80;
 
-	par->CRTC[0x0a] = 0x00;
-	par->CRTC[0x0b] = 0x00;
-	par->CRTC[0x0c] = 0x00;
-	par->CRTC[0x0d] = 0x00;
-	par->CRTC[0x0e] = 0x00;
-	par->CRTC[0x0f] = 0x00;
-	par->CRTC[0x10] = timings->VSyncStart & 0xff;
-	par->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
-	par->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
-	par->CRTC[0x13] = var->xres_virtual >> 4;
-	par->CRTC[0x14] = 0x00;
-	par->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
-	par->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
-	par->CRTC[0x17] = 0xc3;
-	par->CRTC[0x18] = 0xff;
+	reg->CRTC[0x0a] = 0x00;
+	reg->CRTC[0x0b] = 0x00;
+	reg->CRTC[0x0c] = 0x00;
+	reg->CRTC[0x0d] = 0x00;
+	reg->CRTC[0x0e] = 0x00;
+	reg->CRTC[0x0f] = 0x00;
+	reg->CRTC[0x10] = timings->VSyncStart & 0xff;
+	reg->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
+	reg->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
+	reg->CRTC[0x13] = var->xres_virtual >> 4;
+	reg->CRTC[0x14] = 0x00;
+	reg->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
+	reg->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
+	reg->CRTC[0x17] = 0xc3;
+	reg->CRTC[0x18] = 0xff;
 
 	/*
 	 * are these unnecessary?
@@ -220,38 +221,38 @@
 	/*
 	 * Graphics Display Controller
 	 */
-	par->Graphics[0x00] = 0x00;
-	par->Graphics[0x01] = 0x00;
-	par->Graphics[0x02] = 0x00;
-	par->Graphics[0x03] = 0x00;
-	par->Graphics[0x04] = 0x00;
-	par->Graphics[0x05] = 0x40;
-	par->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
-	par->Graphics[0x07] = 0x0F;
-	par->Graphics[0x08] = 0xFF;
+	reg->Graphics[0x00] = 0x00;
+	reg->Graphics[0x01] = 0x00;
+	reg->Graphics[0x02] = 0x00;
+	reg->Graphics[0x03] = 0x00;
+	reg->Graphics[0x04] = 0x00;
+	reg->Graphics[0x05] = 0x40;
+	reg->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
+	reg->Graphics[0x07] = 0x0F;
+	reg->Graphics[0x08] = 0xFF;
 
 
-	par->Attribute[0x00]  = 0x00; /* standard colormap translation */
-	par->Attribute[0x01]  = 0x01;
-	par->Attribute[0x02]  = 0x02;
-	par->Attribute[0x03]  = 0x03;
-	par->Attribute[0x04]  = 0x04;
-	par->Attribute[0x05]  = 0x05;
-	par->Attribute[0x06]  = 0x06;
-	par->Attribute[0x07]  = 0x07;
-	par->Attribute[0x08]  = 0x08;
-	par->Attribute[0x09]  = 0x09;
-	par->Attribute[0x0a] = 0x0A;
-	par->Attribute[0x0b] = 0x0B;
-	par->Attribute[0x0c] = 0x0C;
-	par->Attribute[0x0d] = 0x0D;
-	par->Attribute[0x0e] = 0x0E;
-	par->Attribute[0x0f] = 0x0F;
-	par->Attribute[0x10] = 0x41;
-	par->Attribute[0x11] = 0xFF;
-	par->Attribute[0x12] = 0x0F;
-	par->Attribute[0x13] = 0x00;
-	par->Attribute[0x14] = 0x00;
+	reg->Attribute[0x00]  = 0x00; /* standard colormap translation */
+	reg->Attribute[0x01]  = 0x01;
+	reg->Attribute[0x02]  = 0x02;
+	reg->Attribute[0x03]  = 0x03;
+	reg->Attribute[0x04]  = 0x04;
+	reg->Attribute[0x05]  = 0x05;
+	reg->Attribute[0x06]  = 0x06;
+	reg->Attribute[0x07]  = 0x07;
+	reg->Attribute[0x08]  = 0x08;
+	reg->Attribute[0x09]  = 0x09;
+	reg->Attribute[0x0a] = 0x0A;
+	reg->Attribute[0x0b] = 0x0B;
+	reg->Attribute[0x0c] = 0x0C;
+	reg->Attribute[0x0d] = 0x0D;
+	reg->Attribute[0x0e] = 0x0E;
+	reg->Attribute[0x0f] = 0x0F;
+	reg->Attribute[0x10] = 0x41;
+	reg->Attribute[0x11] = 0xFF;
+	reg->Attribute[0x12] = 0x0F;
+	reg->Attribute[0x13] = 0x00;
+	reg->Attribute[0x14] = 0x00;
 }
 
 /* -------------------- Hardware specific routines ------------------------- */
@@ -304,15 +305,15 @@
 	while ((savage_in32(0x48C60, par) & 0x009fffff));
 }
 
-
+#ifdef CONFIG_FB_SAVAGE_ACCEL
 static void
-SavageSetup2DEngine (struct savagefb_par  *par)
+SavageSetup2DEngine(struct savagefb_par  *par)
 {
 	unsigned long GlobalBitmapDescriptor;
 
 	GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;
-	BCI_BD_SET_BPP (GlobalBitmapDescriptor, par->depth);
-	BCI_BD_SET_STRIDE (GlobalBitmapDescriptor, par->vwidth);
+	BCI_BD_SET_BPP(GlobalBitmapDescriptor, par->depth);
+	BCI_BD_SET_STRIDE(GlobalBitmapDescriptor, par->vwidth);
 
 	switch(par->chip) {
 	case S3_SAVAGE3D:
@@ -361,32 +362,48 @@
 	vga_out8(0x3d5, 0x0c, par);
 
 	/* Set stride to use GBD. */
-	vga_out8 (0x3d4, 0x50, par);
-	vga_out8 (0x3d5, vga_in8(0x3d5, par) | 0xC1, par);
+	vga_out8(0x3d4, 0x50, par);
+	vga_out8(0x3d5, vga_in8(0x3d5, par) | 0xC1, par);
 
 	/* Enable 2D engine. */
-	vga_out8 (0x3d4, 0x40, par);
-	vga_out8 (0x3d5, 0x01, par);
+	vga_out8(0x3d4, 0x40, par);
+	vga_out8(0x3d5, 0x01, par);
 
-	savage_out32 (MONO_PAT_0, ~0, par);
-	savage_out32 (MONO_PAT_1, ~0, par);
+	savage_out32(MONO_PAT_0, ~0, par);
+	savage_out32(MONO_PAT_1, ~0, par);
 
 	/* Setup plane masks */
-	savage_out32 (0x8128, ~0, par); /* enable all write planes */
-	savage_out32 (0x812C, ~0, par); /* enable all read planes */
-	savage_out16 (0x8134, 0x27, par);
-	savage_out16 (0x8136, 0x07, par);
+	savage_out32(0x8128, ~0, par); /* enable all write planes */
+	savage_out32(0x812C, ~0, par); /* enable all read planes */
+	savage_out16(0x8134, 0x27, par);
+	savage_out16(0x8136, 0x07, par);
 
 	/* Now set the GBD */
 	par->bci_ptr = 0;
-	par->SavageWaitFifo (par, 4);
+	par->SavageWaitFifo(par, 4);
 
-	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD1 );
-	BCI_SEND( 0 );
-	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD2 );
-	BCI_SEND( GlobalBitmapDescriptor );
+	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD1);
+	BCI_SEND(0);
+	BCI_SEND(BCI_CMD_SETREG | (1 << 16) | BCI_GBD2);
+	BCI_SEND(GlobalBitmapDescriptor);
 }
 
+static void savagefb_set_clip(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+	int cmd;
+
+	cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
+	par->bci_ptr = 0;
+	par->SavageWaitFifo(par,3);
+	BCI_SEND(cmd);
+	BCI_SEND(BCI_CLIP_TL(0, 0));
+	BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
+}
+#else
+static void SavageSetup2DEngine(struct savagefb_par  *par) {}
+
+#endif
 
 static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
 			    int min_n2, int max_n2, long freq_min,
@@ -398,11 +415,11 @@
 	unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
 
 	if (freq < freq_min / (1 << max_n2)) {
-		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
+		printk(KERN_ERR "invalid frequency %ld Khz\n", freq);
 		freq = freq_min / (1 << max_n2);
 	}
 	if (freq > freq_max / (1 << min_n2)) {
-		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
+		printk(KERN_ERR "invalid frequency %ld Khz\n", freq);
 		freq = freq_max / (1 << min_n2);
 	}
 
@@ -453,12 +470,12 @@
 				BASE_FREQ;
 			if (m < min_m + 2 || m > 127+2)
 				continue;
-			if((m * BASE_FREQ >= freq_min * n1) &&
-			   (m * BASE_FREQ <= freq_max * n1)) {
+			if ((m * BASE_FREQ >= freq_min * n1) &&
+			    (m * BASE_FREQ <= freq_max * n1)) {
 				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
-				if(diff < 0)
+				if (diff < 0)
 					diff = -diff;
-				if(diff < best_diff) {
+				if (diff < best_diff) {
 					best_diff = diff;
 					best_m = m;
 					best_n1 = n1;
@@ -468,7 +485,7 @@
 		}
 	}
 
-	if(max_n1 == 63)
+	if (max_n1 == 63)
 		*ndiv = (best_n1 - 2) | (best_n2 << 6);
 	else
 		*ndiv = (best_n1 - 2) | (best_n2 << 5);
@@ -488,23 +505,23 @@
 	int vgaCRReg = 0x3d5;
 
 	printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "
-	       "xF" );
+	       "xF");
 
-	for( i = 0; i < 0x70; i++ ) {
-		if( !(i % 16) )
-			printk(KERN_DEBUG "\nSR%xx ", i >> 4 );
-		vga_out8( 0x3c4, i, par);
-		printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par) );
+	for (i = 0; i < 0x70; i++) {
+		if (!(i % 16))
+			printk(KERN_DEBUG "\nSR%xx ", i >> 4);
+		vga_out8(0x3c4, i, par);
+		printk(KERN_DEBUG " %02x", vga_in8(0x3c5, par));
 	}
 
 	printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
-	       "xD xE xF" );
+	       "xD xE xF");
 
-	for( i = 0; i < 0xB7; i++ ) {
-		if( !(i % 16) )
-			printk(KERN_DEBUG "\nCR%xx ", i >> 4 );
-		vga_out8( vgaCRIndex, i, par);
-		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par) );
+	for (i = 0; i < 0xB7; i++) {
+		if (!(i % 16))
+			printk(KERN_DEBUG "\nCR%xx ", i >> 4);
+		vga_out8(vgaCRIndex, i, par);
+		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg, par));
 	}
 
 	printk(KERN_DEBUG "\n\n");
@@ -513,156 +530,309 @@
 
 /* --------------------------------------------------------------------- */
 
-static void savage_get_default_par(struct savagefb_par *par)
+static void savage_get_default_par(struct savagefb_par *par, struct savage_reg *reg)
 {
 	unsigned char cr3a, cr53, cr66;
 
-	vga_out16 (0x3d4, 0x4838, par);
-	vga_out16 (0x3d4, 0xa039, par);
-	vga_out16 (0x3c4, 0x0608, par);
+	vga_out16(0x3d4, 0x4838, par);
+	vga_out16(0x3d4, 0xa039, par);
+	vga_out16(0x3c4, 0x0608, par);
 
-	vga_out8 (0x3d4, 0x66, par);
-	cr66 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr66 | 0x80, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	cr3a = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr3a | 0x80, par);
-	vga_out8 (0x3d4, 0x53, par);
-	cr53 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr53 & 0x7f, par);
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+	vga_out8(0x3d4, 0x53, par);
+	cr53 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr53 & 0x7f, par);
 
-	vga_out8 (0x3d4, 0x66, par);
-	vga_out8 (0x3d5, cr66, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	vga_out8 (0x3d5, cr3a, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
 
-	vga_out8 (0x3d4, 0x66, par);
-	vga_out8 (0x3d5, cr66, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	vga_out8 (0x3d5, cr3a, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
 
 	/* unlock extended seq regs */
-	vga_out8 (0x3c4, 0x08, par);
-	par->SR08 = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c5, 0x06, par);
+	vga_out8(0x3c4, 0x08, par);
+	reg->SR08 = vga_in8(0x3c5, par);
+	vga_out8(0x3c5, 0x06, par);
 
 	/* now save all the extended regs we need */
-	vga_out8 (0x3d4, 0x31, par);
-	par->CR31 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x32, par);
-	par->CR32 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x34, par);
-	par->CR34 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x36, par);
-	par->CR36 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	par->CR3A = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x40, par);
-	par->CR40 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x42, par);
-	par->CR42 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x45, par);
-	par->CR45 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x50, par);
-	par->CR50 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x51, par);
-	par->CR51 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x53, par);
-	par->CR53 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x58, par);
-	par->CR58 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x60, par);
-	par->CR60 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x66, par);
-	par->CR66 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x67, par);
-	par->CR67 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x68, par);
-	par->CR68 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x69, par);
-	par->CR69 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x6f, par);
-	par->CR6F = vga_in8 (0x3d5, par);
+	vga_out8(0x3d4, 0x31, par);
+	reg->CR31 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x32, par);
+	reg->CR32 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x34, par);
+	reg->CR34 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x36, par);
+	reg->CR36 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x3a, par);
+	reg->CR3A = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x40, par);
+	reg->CR40 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x42, par);
+	reg->CR42 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x45, par);
+	reg->CR45 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x50, par);
+	reg->CR50 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x51, par);
+	reg->CR51 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x53, par);
+	reg->CR53 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x58, par);
+	reg->CR58 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x60, par);
+	reg->CR60 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x66, par);
+	reg->CR66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x67, par);
+	reg->CR67 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x68, par);
+	reg->CR68 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x69, par);
+	reg->CR69 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x6f, par);
+	reg->CR6F = vga_in8(0x3d5, par);
 
-	vga_out8 (0x3d4, 0x33, par);
-	par->CR33 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x86, par);
-	par->CR86 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x88, par);
-	par->CR88 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x90, par);
-	par->CR90 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x91, par);
-	par->CR91 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0xb0, par);
-	par->CRB0 = vga_in8 (0x3d5, par) | 0x80;
+	vga_out8(0x3d4, 0x33, par);
+	reg->CR33 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x86, par);
+	reg->CR86 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x88, par);
+	reg->CR88 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x90, par);
+	reg->CR90 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x91, par);
+	reg->CR91 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0xb0, par);
+	reg->CRB0 = vga_in8(0x3d5, par) | 0x80;
 
 	/* extended mode timing regs */
-	vga_out8 (0x3d4, 0x3b, par);
-	par->CR3B = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x3c, par);
-	par->CR3C = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x43, par);
-	par->CR43 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x5d, par);
-	par->CR5D = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x5e, par);
-	par->CR5E = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x65, par);
-	par->CR65 = vga_in8 (0x3d5, par);
+	vga_out8(0x3d4, 0x3b, par);
+	reg->CR3B = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x3c, par);
+	reg->CR3C = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x43, par);
+	reg->CR43 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x5d, par);
+	reg->CR5D = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x5e, par);
+	reg->CR5E = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x65, par);
+	reg->CR65 = vga_in8(0x3d5, par);
 
 	/* save seq extended regs for DCLK PLL programming */
-	vga_out8 (0x3c4, 0x0e, par);
-	par->SR0E = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x0f, par);
-	par->SR0F = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x10, par);
-	par->SR10 = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x11, par);
-	par->SR11 = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x12, par);
-	par->SR12 = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x13, par);
-	par->SR13 = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x29, par);
-	par->SR29 = vga_in8 (0x3c5, par);
+	vga_out8(0x3c4, 0x0e, par);
+	reg->SR0E = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x0f, par);
+	reg->SR0F = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x10, par);
+	reg->SR10 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x11, par);
+	reg->SR11 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x12, par);
+	reg->SR12 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x13, par);
+	reg->SR13 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x29, par);
+	reg->SR29 = vga_in8(0x3c5, par);
 
-	vga_out8 (0x3c4, 0x15, par);
-	par->SR15 = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x30, par);
-	par->SR30 = vga_in8 (0x3c5, par);
-	vga_out8 (0x3c4, 0x18, par);
-	par->SR18 = vga_in8 (0x3c5, par);
+	vga_out8(0x3c4, 0x15, par);
+	reg->SR15 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x30, par);
+	reg->SR30 = vga_in8(0x3c5, par);
+	vga_out8(0x3c4, 0x18, par);
+	reg->SR18 = vga_in8(0x3c5, par);
 
 	/* Save flat panel expansion regsters. */
 	if (par->chip == S3_SAVAGE_MX) {
 		int i;
 
 		for (i = 0; i < 8; i++) {
-			vga_out8 (0x3c4, 0x54+i, par);
-			par->SR54[i] = vga_in8 (0x3c5, par);
+			vga_out8(0x3c4, 0x54+i, par);
+			reg->SR54[i] = vga_in8(0x3c5, par);
 		}
 	}
 
-	vga_out8 (0x3d4, 0x66, par);
-	cr66 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr66 | 0x80, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	cr3a = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr3a | 0x80, par);
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
 
 	/* now save MIU regs */
 	if (par->chip != S3_SAVAGE_MX) {
-		par->MMPR0 = savage_in32(FIFO_CONTROL_REG, par);
-		par->MMPR1 = savage_in32(MIU_CONTROL_REG, par);
-		par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par);
-		par->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par);
+		reg->MMPR0 = savage_in32(FIFO_CONTROL_REG, par);
+		reg->MMPR1 = savage_in32(MIU_CONTROL_REG, par);
+		reg->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG, par);
+		reg->MMPR3 = savage_in32(MISC_TIMEOUT_REG, par);
 	}
 
-	vga_out8 (0x3d4, 0x3a, par);
-	vga_out8 (0x3d5, cr3a, par);
-	vga_out8 (0x3d4, 0x66, par);
-	vga_out8 (0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+}
+
+static void savage_set_default_par(struct savagefb_par *par,
+				struct savage_reg *reg)
+{
+	unsigned char cr3a, cr53, cr66;
+
+	vga_out16(0x3d4, 0x4838, par);
+	vga_out16(0x3d4, 0xa039, par);
+	vga_out16(0x3c4, 0x0608, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+	vga_out8(0x3d4, 0x53, par);
+	cr53 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr53 & 0x7f, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+
+	/* unlock extended seq regs */
+	vga_out8(0x3c4, 0x08, par);
+	vga_out8(0x3c5, reg->SR08, par);
+	vga_out8(0x3c5, 0x06, par);
+
+	/* now restore all the extended regs we need */
+	vga_out8(0x3d4, 0x31, par);
+	vga_out8(0x3d5, reg->CR31, par);
+	vga_out8(0x3d4, 0x32, par);
+	vga_out8(0x3d5, reg->CR32, par);
+	vga_out8(0x3d4, 0x34, par);
+	vga_out8(0x3d5, reg->CR34, par);
+	vga_out8(0x3d4, 0x36, par);
+	vga_out8(0x3d5,reg->CR36, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, reg->CR3A, par);
+	vga_out8(0x3d4, 0x40, par);
+	vga_out8(0x3d5, reg->CR40, par);
+	vga_out8(0x3d4, 0x42, par);
+	vga_out8(0x3d5, reg->CR42, par);
+	vga_out8(0x3d4, 0x45, par);
+	vga_out8(0x3d5, reg->CR45, par);
+	vga_out8(0x3d4, 0x50, par);
+	vga_out8(0x3d5, reg->CR50, par);
+	vga_out8(0x3d4, 0x51, par);
+	vga_out8(0x3d5, reg->CR51, par);
+	vga_out8(0x3d4, 0x53, par);
+	vga_out8(0x3d5, reg->CR53, par);
+	vga_out8(0x3d4, 0x58, par);
+	vga_out8(0x3d5, reg->CR58, par);
+	vga_out8(0x3d4, 0x60, par);
+	vga_out8(0x3d5, reg->CR60, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, reg->CR66, par);
+	vga_out8(0x3d4, 0x67, par);
+	vga_out8(0x3d5, reg->CR67, par);
+	vga_out8(0x3d4, 0x68, par);
+	vga_out8(0x3d5, reg->CR68, par);
+	vga_out8(0x3d4, 0x69, par);
+	vga_out8(0x3d5, reg->CR69, par);
+	vga_out8(0x3d4, 0x6f, par);
+	vga_out8(0x3d5, reg->CR6F, par);
+
+	vga_out8(0x3d4, 0x33, par);
+	vga_out8(0x3d5, reg->CR33, par);
+	vga_out8(0x3d4, 0x86, par);
+	vga_out8(0x3d5, reg->CR86, par);
+	vga_out8(0x3d4, 0x88, par);
+	vga_out8(0x3d5, reg->CR88, par);
+	vga_out8(0x3d4, 0x90, par);
+	vga_out8(0x3d5, reg->CR90, par);
+	vga_out8(0x3d4, 0x91, par);
+	vga_out8(0x3d5, reg->CR91, par);
+	vga_out8(0x3d4, 0xb0, par);
+	vga_out8(0x3d5, reg->CRB0, par);
+
+	/* extended mode timing regs */
+	vga_out8(0x3d4, 0x3b, par);
+	vga_out8(0x3d5, reg->CR3B, par);
+	vga_out8(0x3d4, 0x3c, par);
+	vga_out8(0x3d5, reg->CR3C, par);
+	vga_out8(0x3d4, 0x43, par);
+	vga_out8(0x3d5, reg->CR43, par);
+	vga_out8(0x3d4, 0x5d, par);
+	vga_out8(0x3d5, reg->CR5D, par);
+	vga_out8(0x3d4, 0x5e, par);
+	vga_out8(0x3d5, reg->CR5E, par);
+	vga_out8(0x3d4, 0x65, par);
+	vga_out8(0x3d5, reg->CR65, par);
+
+	/* save seq extended regs for DCLK PLL programming */
+	vga_out8(0x3c4, 0x0e, par);
+	vga_out8(0x3c5, reg->SR0E, par);
+	vga_out8(0x3c4, 0x0f, par);
+	vga_out8(0x3c5, reg->SR0F, par);
+	vga_out8(0x3c4, 0x10, par);
+	vga_out8(0x3c5, reg->SR10, par);
+	vga_out8(0x3c4, 0x11, par);
+	vga_out8(0x3c5, reg->SR11, par);
+	vga_out8(0x3c4, 0x12, par);
+	vga_out8(0x3c5, reg->SR12, par);
+	vga_out8(0x3c4, 0x13, par);
+	vga_out8(0x3c5, reg->SR13, par);
+	vga_out8(0x3c4, 0x29, par);
+	vga_out8(0x3c5, reg->SR29, par);
+
+	vga_out8(0x3c4, 0x15, par);
+	vga_out8(0x3c5, reg->SR15, par);
+	vga_out8(0x3c4, 0x30, par);
+	vga_out8(0x3c5, reg->SR30, par);
+	vga_out8(0x3c4, 0x18, par);
+	vga_out8(0x3c5, reg->SR18, par);
+
+	/* Save flat panel expansion regsters. */
+	if (par->chip == S3_SAVAGE_MX) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			vga_out8(0x3c4, 0x54+i, par);
+			vga_out8(0x3c5, reg->SR54[i], par);
+		}
+	}
+
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
+
+	/* now save MIU regs */
+	if (par->chip != S3_SAVAGE_MX) {
+		savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par);
+		savage_out32(MIU_CONTROL_REG, reg->MMPR1, par);
+		savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par);
+		savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par);
+	}
+
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
 }
 
 static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
@@ -683,8 +853,8 @@
         var->vmode = modedb->vmode;
 }
 
-static int savagefb_check_var (struct fb_var_screeninfo   *var,
-			       struct fb_info *info)
+static int savagefb_check_var(struct fb_var_screeninfo   *var,
+			      struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
 	int memlen, vramlen, mode_valid = 0;
@@ -750,10 +920,10 @@
 	if (par->SavagePanelWidth &&
 	    (var->xres > par->SavagePanelWidth ||
 	     var->yres > par->SavagePanelHeight)) {
-		printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel "
-			"(%dx%d)\n", var->xres,  var->yres,
-			par->SavagePanelWidth,
-			par->SavagePanelHeight);
+		printk(KERN_INFO "Mode (%dx%d) larger than the LCD panel "
+		       "(%dx%d)\n", var->xres,  var->yres,
+		       par->SavagePanelWidth,
+		       par->SavagePanelHeight);
 		return -1;
 	}
 
@@ -788,8 +958,9 @@
 }
 
 
-static int savagefb_decode_var (struct fb_var_screeninfo   *var,
-				struct savagefb_par        *par)
+static int savagefb_decode_var(struct fb_var_screeninfo   *var,
+			       struct savagefb_par        *par,
+			       struct savage_reg          *reg)
 {
 	struct xtimings timings;
 	int width, dclk, i, j; /*, refresh; */
@@ -799,7 +970,7 @@
 
 	DBG("savagefb_decode_var");
 
-	memset (&timings, 0, sizeof(timings));
+	memset(&timings, 0, sizeof(timings));
 
 	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
 	timings.Clock = 1000000000 / pixclock;
@@ -831,39 +1002,39 @@
 	 * This will allocate the datastructure and initialize all of the
 	 * generic VGA registers.
 	 */
-	vgaHWInit (var, par, &timings);
+	vgaHWInit(var, par, &timings, reg);
 
 	/* We need to set CR67 whether or not we use the BIOS. */
 
 	dclk = timings.Clock;
-	par->CR67 = 0x00;
+	reg->CR67 = 0x00;
 
-	switch( var->bits_per_pixel ) {
+	switch(var->bits_per_pixel) {
 	case 8:
-		if( (par->chip == S3_SAVAGE2000) && (dclk >= 230000) )
-			par->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
+		if ((par->chip == S3_SAVAGE2000) && (dclk >= 230000))
+			reg->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
 		else
-			par->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
+			reg->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
 		break;
 	case 15:
-		if ( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-		     ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
-			par->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
+		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))
+			reg->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
 		else
-			par->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
+			reg->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
 		break;
 	case 16:
-		if( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
-			par->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
+		if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		   ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)))
+			reg->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
 		else
-			par->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
+			reg->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
 		break;
 	case 24:
-		par->CR67 = 0x70;
+		reg->CR67 = 0x70;
 		break;
 	case 32:
-		par->CR67 = 0xd0;
+		reg->CR67 = 0xd0;
 		break;
 	}
 
@@ -872,61 +1043,61 @@
 	 * match.  Fall back to traditional register-crunching.
 	 */
 
-	vga_out8 (0x3d4, 0x3a, par);
-	tmp = vga_in8 (0x3d5, par);
+	vga_out8(0x3d4, 0x3a, par);
+	tmp = vga_in8(0x3d5, par);
 	if (1 /*FIXME:psav->pci_burst*/)
-		par->CR3A = (tmp & 0x7f) | 0x15;
+		reg->CR3A = (tmp & 0x7f) | 0x15;
 	else
-		par->CR3A = tmp | 0x95;
+		reg->CR3A = tmp | 0x95;
 
-	par->CR53 = 0x00;
-	par->CR31 = 0x8c;
-	par->CR66 = 0x89;
+	reg->CR53 = 0x00;
+	reg->CR31 = 0x8c;
+	reg->CR66 = 0x89;
 
-	vga_out8 (0x3d4, 0x58, par);
-	par->CR58 = vga_in8 (0x3d5, par) & 0x80;
-	par->CR58 |= 0x13;
+	vga_out8(0x3d4, 0x58, par);
+	reg->CR58 = vga_in8(0x3d5, par) & 0x80;
+	reg->CR58 |= 0x13;
 
-	par->SR15 = 0x03 | 0x80;
-	par->SR18 = 0x00;
-	par->CR43 = par->CR45 = par->CR65 = 0x00;
+	reg->SR15 = 0x03 | 0x80;
+	reg->SR18 = 0x00;
+	reg->CR43 = reg->CR45 = reg->CR65 = 0x00;
 
-	vga_out8 (0x3d4, 0x40, par);
-	par->CR40 = vga_in8 (0x3d5, par) & ~0x01;
+	vga_out8(0x3d4, 0x40, par);
+	reg->CR40 = vga_in8(0x3d5, par) & ~0x01;
 
-	par->MMPR0 = 0x010400;
-	par->MMPR1 = 0x00;
-	par->MMPR2 = 0x0808;
-	par->MMPR3 = 0x08080810;
+	reg->MMPR0 = 0x010400;
+	reg->MMPR1 = 0x00;
+	reg->MMPR2 = 0x0808;
+	reg->MMPR3 = 0x08080810;
 
-	SavageCalcClock (dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
+	SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
 	/* m = 107; n = 4; r = 2; */
 
 	if (par->MCLK <= 0) {
-		par->SR10 = 255;
-		par->SR11 = 255;
+		reg->SR10 = 255;
+		reg->SR11 = 255;
 	} else {
-		common_calc_clock (par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
-				   &par->SR11, &par->SR10);
-		/*      par->SR10 = 80; // MCLK == 286000 */
-		/*      par->SR11 = 125; */
+		common_calc_clock(par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
+				   &reg->SR11, &reg->SR10);
+		/*      reg->SR10 = 80; // MCLK == 286000 */
+		/*      reg->SR11 = 125; */
 	}
 
-	par->SR12 = (r << 6) | (n & 0x3f);
-	par->SR13 = m & 0xff;
-	par->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
+	reg->SR12 = (r << 6) | (n & 0x3f);
+	reg->SR13 = m & 0xff;
+	reg->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
 
 	if (var->bits_per_pixel < 24)
-		par->MMPR0 -= 0x8000;
+		reg->MMPR0 -= 0x8000;
 	else
-		par->MMPR0 -= 0x4000;
+		reg->MMPR0 -= 0x4000;
 
 	if (timings.interlaced)
-		par->CR42 = 0x20;
+		reg->CR42 = 0x20;
 	else
-		par->CR42 = 0x00;
+		reg->CR42 = 0x00;
 
-	par->CR34 = 0x10; /* display fifo */
+	reg->CR34 = 0x10; /* display fifo */
 
 	i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |
 		((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |
@@ -938,77 +1109,77 @@
 	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)
 		i |= 0x20;
 
-	j = (par->CRTC[0] + ((i & 0x01) << 8) +
-	     par->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
+	j = (reg->CRTC[0] + ((i & 0x01) << 8) +
+	     reg->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
 
-	if (j - (par->CRTC[4] + ((i & 0x10) << 4)) < 4) {
-		if (par->CRTC[4] + ((i & 0x10) << 4) + 4 <=
-		    par->CRTC[0] + ((i & 0x01) << 8))
-			j = par->CRTC[4] + ((i & 0x10) << 4) + 4;
+	if (j - (reg->CRTC[4] + ((i & 0x10) << 4)) < 4) {
+		if (reg->CRTC[4] + ((i & 0x10) << 4) + 4 <=
+		    reg->CRTC[0] + ((i & 0x01) << 8))
+			j = reg->CRTC[4] + ((i & 0x10) << 4) + 4;
 		else
-			j = par->CRTC[0] + ((i & 0x01) << 8) + 1;
+			j = reg->CRTC[0] + ((i & 0x01) << 8) + 1;
 	}
 
-	par->CR3B = j & 0xff;
+	reg->CR3B = j & 0xff;
 	i |= (j & 0x100) >> 2;
-	par->CR3C = (par->CRTC[0] + ((i & 0x01) << 8)) / 2;
-	par->CR5D = i;
-	par->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
+	reg->CR3C = (reg->CRTC[0] + ((i & 0x01) << 8)) / 2;
+	reg->CR5D = i;
+	reg->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
 		(((timings.VDisplay - 1) & 0x400) >> 9) |
 		(((timings.VSyncStart) & 0x400) >> 8) |
 		(((timings.VSyncStart) & 0x400) >> 6) | 0x40;
 	width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;
-	par->CR91 = par->CRTC[19] = 0xff & width;
-	par->CR51 = (0x300 & width) >> 4;
-	par->CR90 = 0x80 | (width >> 8);
-	par->MiscOutReg |= 0x0c;
+	reg->CR91 = reg->CRTC[19] = 0xff & width;
+	reg->CR51 = (0x300 & width) >> 4;
+	reg->CR90 = 0x80 | (width >> 8);
+	reg->MiscOutReg |= 0x0c;
 
 	/* Set frame buffer description. */
 
 	if (var->bits_per_pixel <= 8)
-		par->CR50 = 0;
+		reg->CR50 = 0;
 	else if (var->bits_per_pixel <= 16)
-		par->CR50 = 0x10;
+		reg->CR50 = 0x10;
 	else
-		par->CR50 = 0x30;
+		reg->CR50 = 0x30;
 
 	if (var->xres_virtual <= 640)
-		par->CR50 |= 0x40;
+		reg->CR50 |= 0x40;
 	else if (var->xres_virtual == 800)
-		par->CR50 |= 0x80;
+		reg->CR50 |= 0x80;
 	else if (var->xres_virtual == 1024)
-		par->CR50 |= 0x00;
+		reg->CR50 |= 0x00;
 	else if (var->xres_virtual == 1152)
-		par->CR50 |= 0x01;
+		reg->CR50 |= 0x01;
 	else if (var->xres_virtual == 1280)
-		par->CR50 |= 0xc0;
+		reg->CR50 |= 0xc0;
 	else if (var->xres_virtual == 1600)
-		par->CR50 |= 0x81;
+		reg->CR50 |= 0x81;
 	else
-		par->CR50 |= 0xc1;	/* Use GBD */
+		reg->CR50 |= 0xc1;	/* Use GBD */
 
-	if( par->chip == S3_SAVAGE2000 )
-		par->CR33 = 0x08;
+	if (par->chip == S3_SAVAGE2000)
+		reg->CR33 = 0x08;
 	else
-		par->CR33 = 0x20;
+		reg->CR33 = 0x20;
 
-	par->CRTC[0x17] = 0xeb;
+	reg->CRTC[0x17] = 0xeb;
 
-	par->CR67 |= 1;
+	reg->CR67 |= 1;
 
 	vga_out8(0x3d4, 0x36, par);
-	par->CR36 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x68, par);
-	par->CR68 = vga_in8 (0x3d5, par);
-	par->CR69 = 0;
-	vga_out8 (0x3d4, 0x6f, par);
-	par->CR6F = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x86, par);
-	par->CR86 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d4, 0x88, par);
-	par->CR88 = vga_in8 (0x3d5, par) | 0x08;
-	vga_out8 (0x3d4, 0xb0, par);
-	par->CRB0 = vga_in8 (0x3d5, par) | 0x80;
+	reg->CR36 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x68, par);
+	reg->CR68 = vga_in8(0x3d5, par);
+	reg->CR69 = 0;
+	vga_out8(0x3d4, 0x6f, par);
+	reg->CR6F = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x86, par);
+	reg->CR86 = vga_in8(0x3d5, par);
+	vga_out8(0x3d4, 0x88, par);
+	reg->CR88 = vga_in8(0x3d5, par) | 0x08;
+	vga_out8(0x3d4, 0xb0, par);
+	reg->CRB0 = vga_in8(0x3d5, par) | 0x80;
 
 	return 0;
 }
@@ -1037,11 +1208,11 @@
 
 	switch (info->var.bits_per_pixel) {
 	case 8:
-		vga_out8 (0x3c8, regno, par);
+		vga_out8(0x3c8, regno, par);
 
-		vga_out8 (0x3c9, red   >> 10, par);
-		vga_out8 (0x3c9, green >> 10, par);
-		vga_out8 (0x3c9, blue  >> 10, par);
+		vga_out8(0x3c9, red   >> 10, par);
+		vga_out8(0x3c9, green >> 10, par);
+		vga_out8(0x3c9, blue  >> 10, par);
 		break;
 
 	case 16:
@@ -1075,21 +1246,21 @@
 	return 0;
 }
 
-static void savagefb_set_par_int (struct savagefb_par  *par)
+static void savagefb_set_par_int(struct savagefb_par  *par, struct savage_reg *reg)
 {
 	unsigned char tmp, cr3a, cr66, cr67;
 
-	DBG ("savagefb_set_par_int");
+	DBG("savagefb_set_par_int");
 
-	par->SavageWaitIdle (par);
+	par->SavageWaitIdle(par);
 
-	vga_out8 (0x3c2, 0x23, par);
+	vga_out8(0x3c2, 0x23, par);
 
-	vga_out16 (0x3d4, 0x4838, par);
-	vga_out16 (0x3d4, 0xa539, par);
-	vga_out16 (0x3c4, 0x0608, par);
+	vga_out16(0x3d4, 0x4838, par);
+	vga_out16(0x3d4, 0xa539, par);
+	vga_out16(0x3c4, 0x0608, par);
 
-	vgaHWProtect (par, 1);
+	vgaHWProtect(par, 1);
 
 	/*
 	 * Some Savage/MX and /IX systems go nuts when trying to exit the
@@ -1099,203 +1270,202 @@
 	 */
 
 	VerticalRetraceWait(par);
-	vga_out8 (0x3d4, 0x67, par);
-	cr67 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */
+	vga_out8(0x3d4, 0x67, par);
+	cr67 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr67/*par->CR67*/ & ~0x0c, par); /* no STREAMS yet */
 
-	vga_out8 (0x3d4, 0x23, par);
-	vga_out8 (0x3d5, 0x00, par);
-	vga_out8 (0x3d4, 0x26, par);
-	vga_out8 (0x3d5, 0x00, par);
+	vga_out8(0x3d4, 0x23, par);
+	vga_out8(0x3d5, 0x00, par);
+	vga_out8(0x3d4, 0x26, par);
+	vga_out8(0x3d5, 0x00, par);
 
 	/* restore extended regs */
-	vga_out8 (0x3d4, 0x66, par);
-	vga_out8 (0x3d5, par->CR66, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	vga_out8 (0x3d5, par->CR3A, par);
-	vga_out8 (0x3d4, 0x31, par);
-	vga_out8 (0x3d5, par->CR31, par);
-	vga_out8 (0x3d4, 0x32, par);
-	vga_out8 (0x3d5, par->CR32, par);
-	vga_out8 (0x3d4, 0x58, par);
-	vga_out8 (0x3d5, par->CR58, par);
-	vga_out8 (0x3d4, 0x53, par);
-	vga_out8 (0x3d5, par->CR53 & 0x7f, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, reg->CR66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, reg->CR3A, par);
+	vga_out8(0x3d4, 0x31, par);
+	vga_out8(0x3d5, reg->CR31, par);
+	vga_out8(0x3d4, 0x32, par);
+	vga_out8(0x3d5, reg->CR32, par);
+	vga_out8(0x3d4, 0x58, par);
+	vga_out8(0x3d5, reg->CR58, par);
+	vga_out8(0x3d4, 0x53, par);
+	vga_out8(0x3d5, reg->CR53 & 0x7f, par);
 
-	vga_out16 (0x3c4, 0x0608, par);
+	vga_out16(0x3c4, 0x0608, par);
 
 	/* Restore DCLK registers. */
 
-	vga_out8 (0x3c4, 0x0e, par);
-	vga_out8 (0x3c5, par->SR0E, par);
-	vga_out8 (0x3c4, 0x0f, par);
-	vga_out8 (0x3c5, par->SR0F, par);
-	vga_out8 (0x3c4, 0x29, par);
-	vga_out8 (0x3c5, par->SR29, par);
-	vga_out8 (0x3c4, 0x15, par);
-	vga_out8 (0x3c5, par->SR15, par);
+	vga_out8(0x3c4, 0x0e, par);
+	vga_out8(0x3c5, reg->SR0E, par);
+	vga_out8(0x3c4, 0x0f, par);
+	vga_out8(0x3c5, reg->SR0F, par);
+	vga_out8(0x3c4, 0x29, par);
+	vga_out8(0x3c5, reg->SR29, par);
+	vga_out8(0x3c4, 0x15, par);
+	vga_out8(0x3c5, reg->SR15, par);
 
 	/* Restore flat panel expansion regsters. */
-	if( par->chip == S3_SAVAGE_MX ) {
+	if (par->chip == S3_SAVAGE_MX) {
 		int i;
 
-		for( i = 0; i < 8; i++ ) {
-			vga_out8 (0x3c4, 0x54+i, par);
-			vga_out8 (0x3c5, par->SR54[i], par);
+		for (i = 0; i < 8; i++) {
+			vga_out8(0x3c4, 0x54+i, par);
+			vga_out8(0x3c5, reg->SR54[i], par);
 		}
 	}
 
-	vgaHWRestore (par);
+	vgaHWRestore (par, reg);
 
 	/* extended mode timing registers */
-	vga_out8 (0x3d4, 0x53, par);
-	vga_out8 (0x3d5, par->CR53, par);
-	vga_out8 (0x3d4, 0x5d, par);
-	vga_out8 (0x3d5, par->CR5D, par);
-	vga_out8 (0x3d4, 0x5e, par);
-	vga_out8 (0x3d5, par->CR5E, par);
-	vga_out8 (0x3d4, 0x3b, par);
-	vga_out8 (0x3d5, par->CR3B, par);
-	vga_out8 (0x3d4, 0x3c, par);
-	vga_out8 (0x3d5, par->CR3C, par);
-	vga_out8 (0x3d4, 0x43, par);
-	vga_out8 (0x3d5, par->CR43, par);
-	vga_out8 (0x3d4, 0x65, par);
-	vga_out8 (0x3d5, par->CR65, par);
+	vga_out8(0x3d4, 0x53, par);
+	vga_out8(0x3d5, reg->CR53, par);
+	vga_out8(0x3d4, 0x5d, par);
+	vga_out8(0x3d5, reg->CR5D, par);
+	vga_out8(0x3d4, 0x5e, par);
+	vga_out8(0x3d5, reg->CR5E, par);
+	vga_out8(0x3d4, 0x3b, par);
+	vga_out8(0x3d5, reg->CR3B, par);
+	vga_out8(0x3d4, 0x3c, par);
+	vga_out8(0x3d5, reg->CR3C, par);
+	vga_out8(0x3d4, 0x43, par);
+	vga_out8(0x3d5, reg->CR43, par);
+	vga_out8(0x3d4, 0x65, par);
+	vga_out8(0x3d5, reg->CR65, par);
 
 	/* restore the desired video mode with cr67 */
-	vga_out8 (0x3d4, 0x67, par);
+	vga_out8(0x3d4, 0x67, par);
 	/* following part not present in X11 driver */
-	cr67 = vga_in8 (0x3d5, par) & 0xf;
-	vga_out8 (0x3d5, 0x50 | cr67, par);
-	udelay (10000);
-	vga_out8 (0x3d4, 0x67, par);
+	cr67 = vga_in8(0x3d5, par) & 0xf;
+	vga_out8(0x3d5, 0x50 | cr67, par);
+	udelay(10000);
+	vga_out8(0x3d4, 0x67, par);
 	/* end of part */
-	vga_out8 (0x3d5, par->CR67 & ~0x0c, par);
+	vga_out8(0x3d5, reg->CR67 & ~0x0c, par);
 
 	/* other mode timing and extended regs */
-	vga_out8 (0x3d4, 0x34, par);
-	vga_out8 (0x3d5, par->CR34, par);
-	vga_out8 (0x3d4, 0x40, par);
-	vga_out8 (0x3d5, par->CR40, par);
-	vga_out8 (0x3d4, 0x42, par);
-	vga_out8 (0x3d5, par->CR42, par);
-	vga_out8 (0x3d4, 0x45, par);
-	vga_out8 (0x3d5, par->CR45, par);
-	vga_out8 (0x3d4, 0x50, par);
-	vga_out8 (0x3d5, par->CR50, par);
-	vga_out8 (0x3d4, 0x51, par);
-	vga_out8 (0x3d5, par->CR51, par);
+	vga_out8(0x3d4, 0x34, par);
+	vga_out8(0x3d5, reg->CR34, par);
+	vga_out8(0x3d4, 0x40, par);
+	vga_out8(0x3d5, reg->CR40, par);
+	vga_out8(0x3d4, 0x42, par);
+	vga_out8(0x3d5, reg->CR42, par);
+	vga_out8(0x3d4, 0x45, par);
+	vga_out8(0x3d5, reg->CR45, par);
+	vga_out8(0x3d4, 0x50, par);
+	vga_out8(0x3d5, reg->CR50, par);
+	vga_out8(0x3d4, 0x51, par);
+	vga_out8(0x3d5, reg->CR51, par);
 
 	/* memory timings */
-	vga_out8 (0x3d4, 0x36, par);
-	vga_out8 (0x3d5, par->CR36, par);
-	vga_out8 (0x3d4, 0x60, par);
-	vga_out8 (0x3d5, par->CR60, par);
-	vga_out8 (0x3d4, 0x68, par);
-	vga_out8 (0x3d5, par->CR68, par);
-	vga_out8 (0x3d4, 0x69, par);
-	vga_out8 (0x3d5, par->CR69, par);
-	vga_out8 (0x3d4, 0x6f, par);
-	vga_out8 (0x3d5, par->CR6F, par);
+	vga_out8(0x3d4, 0x36, par);
+	vga_out8(0x3d5, reg->CR36, par);
+	vga_out8(0x3d4, 0x60, par);
+	vga_out8(0x3d5, reg->CR60, par);
+	vga_out8(0x3d4, 0x68, par);
+	vga_out8(0x3d5, reg->CR68, par);
+	vga_out8(0x3d4, 0x69, par);
+	vga_out8(0x3d5, reg->CR69, par);
+	vga_out8(0x3d4, 0x6f, par);
+	vga_out8(0x3d5, reg->CR6F, par);
 
-	vga_out8 (0x3d4, 0x33, par);
-	vga_out8 (0x3d5, par->CR33, par);
-	vga_out8 (0x3d4, 0x86, par);
-	vga_out8 (0x3d5, par->CR86, par);
-	vga_out8 (0x3d4, 0x88, par);
-	vga_out8 (0x3d5, par->CR88, par);
-	vga_out8 (0x3d4, 0x90, par);
-	vga_out8 (0x3d5, par->CR90, par);
-	vga_out8 (0x3d4, 0x91, par);
-	vga_out8 (0x3d5, par->CR91, par);
+	vga_out8(0x3d4, 0x33, par);
+	vga_out8(0x3d5, reg->CR33, par);
+	vga_out8(0x3d4, 0x86, par);
+	vga_out8(0x3d5, reg->CR86, par);
+	vga_out8(0x3d4, 0x88, par);
+	vga_out8(0x3d5, reg->CR88, par);
+	vga_out8(0x3d4, 0x90, par);
+	vga_out8(0x3d5, reg->CR90, par);
+	vga_out8(0x3d4, 0x91, par);
+	vga_out8(0x3d5, reg->CR91, par);
 
 	if (par->chip == S3_SAVAGE4) {
-		vga_out8 (0x3d4, 0xb0, par);
-		vga_out8 (0x3d5, par->CRB0, par);
+		vga_out8(0x3d4, 0xb0, par);
+		vga_out8(0x3d5, reg->CRB0, par);
 	}
 
-	vga_out8 (0x3d4, 0x32, par);
-	vga_out8 (0x3d5, par->CR32, par);
+	vga_out8(0x3d4, 0x32, par);
+	vga_out8(0x3d5, reg->CR32, par);
 
 	/* unlock extended seq regs */
-	vga_out8 (0x3c4, 0x08, par);
-	vga_out8 (0x3c5, 0x06, par);
+	vga_out8(0x3c4, 0x08, par);
+	vga_out8(0x3c5, 0x06, par);
 
 	/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
 	 * that we should leave the default SR10 and SR11 values there.
 	 */
-	if (par->SR10 != 255) {
-		vga_out8 (0x3c4, 0x10, par);
-		vga_out8 (0x3c5, par->SR10, par);
-		vga_out8 (0x3c4, 0x11, par);
-		vga_out8 (0x3c5, par->SR11, par);
+	if (reg->SR10 != 255) {
+		vga_out8(0x3c4, 0x10, par);
+		vga_out8(0x3c5, reg->SR10, par);
+		vga_out8(0x3c4, 0x11, par);
+		vga_out8(0x3c5, reg->SR11, par);
 	}
 
 	/* restore extended seq regs for dclk */
-	vga_out8 (0x3c4, 0x0e, par);
-	vga_out8 (0x3c5, par->SR0E, par);
-	vga_out8 (0x3c4, 0x0f, par);
-	vga_out8 (0x3c5, par->SR0F, par);
-	vga_out8 (0x3c4, 0x12, par);
-	vga_out8 (0x3c5, par->SR12, par);
-	vga_out8 (0x3c4, 0x13, par);
-	vga_out8 (0x3c5, par->SR13, par);
-	vga_out8 (0x3c4, 0x29, par);
-	vga_out8 (0x3c5, par->SR29, par);
-
-	vga_out8 (0x3c4, 0x18, par);
-	vga_out8 (0x3c5, par->SR18, par);
+	vga_out8(0x3c4, 0x0e, par);
+	vga_out8(0x3c5, reg->SR0E, par);
+	vga_out8(0x3c4, 0x0f, par);
+	vga_out8(0x3c5, reg->SR0F, par);
+	vga_out8(0x3c4, 0x12, par);
+	vga_out8(0x3c5, reg->SR12, par);
+	vga_out8(0x3c4, 0x13, par);
+	vga_out8(0x3c5, reg->SR13, par);
+	vga_out8(0x3c4, 0x29, par);
+	vga_out8(0x3c5, reg->SR29, par);
+	vga_out8(0x3c4, 0x18, par);
+	vga_out8(0x3c5, reg->SR18, par);
 
 	/* load new m, n pll values for dclk & mclk */
-	vga_out8 (0x3c4, 0x15, par);
-	tmp = vga_in8 (0x3c5, par) & ~0x21;
+	vga_out8(0x3c4, 0x15, par);
+	tmp = vga_in8(0x3c5, par) & ~0x21;
 
-	vga_out8 (0x3c5, tmp | 0x03, par);
-	vga_out8 (0x3c5, tmp | 0x23, par);
-	vga_out8 (0x3c5, tmp | 0x03, par);
-	vga_out8 (0x3c5, par->SR15, par);
-	udelay (100);
+	vga_out8(0x3c5, tmp | 0x03, par);
+	vga_out8(0x3c5, tmp | 0x23, par);
+	vga_out8(0x3c5, tmp | 0x03, par);
+	vga_out8(0x3c5, reg->SR15, par);
+	udelay(100);
 
-	vga_out8 (0x3c4, 0x30, par);
-	vga_out8 (0x3c5, par->SR30, par);
-	vga_out8 (0x3c4, 0x08, par);
-	vga_out8 (0x3c5, par->SR08, par);
+	vga_out8(0x3c4, 0x30, par);
+	vga_out8(0x3c5, reg->SR30, par);
+	vga_out8(0x3c4, 0x08, par);
+	vga_out8(0x3c5, reg->SR08, par);
 
 	/* now write out cr67 in full, possibly starting STREAMS */
 	VerticalRetraceWait(par);
-	vga_out8 (0x3d4, 0x67, par);
-	vga_out8 (0x3d5, par->CR67, par);
+	vga_out8(0x3d4, 0x67, par);
+	vga_out8(0x3d5, reg->CR67, par);
 
-	vga_out8 (0x3d4, 0x66, par);
-	cr66 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr66 | 0x80, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	cr3a = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr3a | 0x80, par);
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x80, par);
+	vga_out8(0x3d4, 0x3a, par);
+	cr3a = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3a | 0x80, par);
 
 	if (par->chip != S3_SAVAGE_MX) {
 		VerticalRetraceWait(par);
-		savage_out32 (FIFO_CONTROL_REG, par->MMPR0, par);
-		par->SavageWaitIdle (par);
-		savage_out32 (MIU_CONTROL_REG, par->MMPR1, par);
-		par->SavageWaitIdle (par);
-		savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2, par);
-		par->SavageWaitIdle (par);
-		savage_out32 (MISC_TIMEOUT_REG, par->MMPR3, par);
+		savage_out32(FIFO_CONTROL_REG, reg->MMPR0, par);
+		par->SavageWaitIdle(par);
+		savage_out32(MIU_CONTROL_REG, reg->MMPR1, par);
+		par->SavageWaitIdle(par);
+		savage_out32(STREAMS_TIMEOUT_REG, reg->MMPR2, par);
+		par->SavageWaitIdle(par);
+		savage_out32(MISC_TIMEOUT_REG, reg->MMPR3, par);
 	}
 
-	vga_out8 (0x3d4, 0x66, par);
-	vga_out8 (0x3d5, cr66, par);
-	vga_out8 (0x3d4, 0x3a, par);
-	vga_out8 (0x3d5, cr3a, par);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66, par);
+	vga_out8(0x3d4, 0x3a, par);
+	vga_out8(0x3d5, cr3a, par);
 
-	SavageSetup2DEngine (par);
-	vgaHWProtect (par, 0);
+	SavageSetup2DEngine(par);
+	vgaHWProtect(par, 0);
 }
 
-static void savagefb_update_start (struct savagefb_par      *par,
-				   struct fb_var_screeninfo *var)
+static void savagefb_update_start(struct savagefb_par      *par,
+				  struct fb_var_screeninfo *var)
 {
 	int base;
 
@@ -1305,8 +1475,8 @@
 	/* now program the start address registers */
 	vga_out16(0x3d4, (base & 0x00ff00) | 0x0c, par);
 	vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d, par);
-	vga_out8 (0x3d4, 0x69, par);
-	vga_out8 (0x3d5, (base & 0x7f0000) >> 16, par);
+	vga_out8(0x3d4, 0x69, par);
+	vga_out8(0x3d5, (base & 0x7f0000) >> 16, par);
 }
 
 
@@ -1325,29 +1495,14 @@
 
 }
 
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-static void savagefb_set_clip(struct fb_info *info)
-{
-    struct savagefb_par *par = info->par;
-    int cmd;
-
-    cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
-    par->bci_ptr = 0;
-    par->SavageWaitFifo(par,3);
-    BCI_SEND(cmd);
-    BCI_SEND(BCI_CLIP_TL(0, 0));
-    BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
-}
-#endif
-
-static int savagefb_set_par (struct fb_info *info)
+static int savagefb_set_par(struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
 	struct fb_var_screeninfo *var = &info->var;
 	int err;
 
 	DBG("savagefb_set_par");
-	err = savagefb_decode_var (var, par);
+	err = savagefb_decode_var(var, par, &par->state);
 	if (err)
 		return err;
 
@@ -1366,8 +1521,8 @@
 	par->maxClock = par->dacSpeedBpp;
 	par->minClock = 10000;
 
-	savagefb_set_par_int (par);
-	fb_set_cmap (&info->cmap, info);
+	savagefb_set_par_int(par, &par->state);
+	fb_set_cmap(&info->cmap, info);
 	savagefb_set_fix(info);
 	savagefb_set_clip(info);
 
@@ -1378,12 +1533,12 @@
 /*
  *    Pan or Wrap the Display
  */
-static int savagefb_pan_display (struct fb_var_screeninfo *var,
-				 struct fb_info           *info)
+static int savagefb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info           *info)
 {
 	struct savagefb_par *par = info->par;
 
-	savagefb_update_start (par, var);
+	savagefb_update_start(par, var);
 	return 0;
 }
 
@@ -1440,6 +1595,22 @@
 	return (blank == FB_BLANK_NORMAL) ? 1 : 0;
 }
 
+static void savagefb_save_state(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+
+	savage_get_default_par(par, &par->save);
+}
+
+static void savagefb_restore_state(struct fb_info *info)
+{
+	struct savagefb_par *par = info->par;
+
+	savagefb_blank(FB_BLANK_POWERDOWN, info);
+	savage_set_default_par(par, &par->save);
+	savagefb_blank(FB_BLANK_UNBLANK, info);
+}
+
 static struct fb_ops savagefb_ops = {
 	.owner          = THIS_MODULE,
 	.fb_check_var   = savagefb_check_var,
@@ -1447,6 +1618,8 @@
 	.fb_setcolreg   = savagefb_setcolreg,
 	.fb_pan_display = savagefb_pan_display,
 	.fb_blank       = savagefb_blank,
+	.fb_save_state  = savagefb_save_state,
+	.fb_restore_state = savagefb_restore_state,
 #if defined(CONFIG_FB_SAVAGE_ACCEL)
 	.fb_fillrect    = savagefb_fillrect,
 	.fb_copyarea    = savagefb_copyarea,
@@ -1479,59 +1652,59 @@
 	.vmode =	FB_VMODE_NONINTERLACED
 };
 
-static void savage_enable_mmio (struct savagefb_par *par)
+static void savage_enable_mmio(struct savagefb_par *par)
 {
 	unsigned char val;
 
-	DBG ("savage_enable_mmio\n");
+	DBG("savage_enable_mmio\n");
 
-	val = vga_in8 (0x3c3, par);
-	vga_out8 (0x3c3, val | 0x01, par);
-	val = vga_in8 (0x3cc, par);
-	vga_out8 (0x3c2, val | 0x01, par);
+	val = vga_in8(0x3c3, par);
+	vga_out8(0x3c3, val | 0x01, par);
+	val = vga_in8(0x3cc, par);
+	vga_out8(0x3c2, val | 0x01, par);
 
 	if (par->chip >= S3_SAVAGE4) {
-		vga_out8 (0x3d4, 0x40, par);
-		val = vga_in8 (0x3d5, par);
-		vga_out8 (0x3d5, val | 1, par);
+		vga_out8(0x3d4, 0x40, par);
+		val = vga_in8(0x3d5, par);
+		vga_out8(0x3d5, val | 1, par);
 	}
 }
 
 
-static void savage_disable_mmio (struct savagefb_par *par)
+static void savage_disable_mmio(struct savagefb_par *par)
 {
 	unsigned char val;
 
-	DBG ("savage_disable_mmio\n");
+	DBG("savage_disable_mmio\n");
 
-	if(par->chip >= S3_SAVAGE4 ) {
-		vga_out8 (0x3d4, 0x40, par);
-		val = vga_in8 (0x3d5, par);
-		vga_out8 (0x3d5, val | 1, par);
+	if (par->chip >= S3_SAVAGE4) {
+		vga_out8(0x3d4, 0x40, par);
+		val = vga_in8(0x3d5, par);
+		vga_out8(0x3d5, val | 1, par);
 	}
 }
 
 
-static int __devinit savage_map_mmio (struct fb_info *info)
+static int __devinit savage_map_mmio(struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
-	DBG ("savage_map_mmio");
+	DBG("savage_map_mmio");
 
-	if (S3_SAVAGE3D_SERIES (par->chip))
-		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
+	if (S3_SAVAGE3D_SERIES(par->chip))
+		par->mmio.pbase = pci_resource_start(par->pcidev, 0) +
 			SAVAGE_NEWMMIO_REGBASE_S3;
 	else
-		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
+		par->mmio.pbase = pci_resource_start(par->pcidev, 0) +
 			SAVAGE_NEWMMIO_REGBASE_S4;
 
 	par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
 
-	par->mmio.vbase = ioremap (par->mmio.pbase, par->mmio.len);
+	par->mmio.vbase = ioremap(par->mmio.pbase, par->mmio.len);
 	if (!par->mmio.vbase) {
-		printk ("savagefb: unable to map memory mapped IO\n");
+		printk("savagefb: unable to map memory mapped IO\n");
 		return -ENOMEM;
 	} else
-		printk (KERN_INFO "savagefb: mapped io at %p\n",
+		printk(KERN_INFO "savagefb: mapped io at %p\n",
 			par->mmio.vbase);
 
 	info->fix.mmio_start = par->mmio.pbase;
@@ -1540,15 +1713,15 @@
 	par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
 	par->bci_ptr  = 0;
 
-	savage_enable_mmio (par);
+	savage_enable_mmio(par);
 
 	return 0;
 }
 
-static void savage_unmap_mmio (struct fb_info *info)
+static void savage_unmap_mmio(struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
-	DBG ("savage_unmap_mmio");
+	DBG("savage_unmap_mmio");
 
 	savage_disable_mmio(par);
 
@@ -1558,46 +1731,46 @@
 	}
 }
 
-static int __devinit savage_map_video (struct fb_info *info,
-				       int video_len)
+static int __devinit savage_map_video(struct fb_info *info,
+				      int video_len)
 {
 	struct savagefb_par *par = info->par;
 	int resource;
 
 	DBG("savage_map_video");
 
-	if (S3_SAVAGE3D_SERIES (par->chip))
+	if (S3_SAVAGE3D_SERIES(par->chip))
 		resource = 0;
 	else
 		resource = 1;
 
-	par->video.pbase = pci_resource_start (par->pcidev, resource);
+	par->video.pbase = pci_resource_start(par->pcidev, resource);
 	par->video.len   = video_len;
-	par->video.vbase = ioremap (par->video.pbase, par->video.len);
+	par->video.vbase = ioremap(par->video.pbase, par->video.len);
 
 	if (!par->video.vbase) {
-		printk ("savagefb: unable to map screen memory\n");
+		printk("savagefb: unable to map screen memory\n");
 		return -ENOMEM;
 	} else
-		printk (KERN_INFO "savagefb: mapped framebuffer at %p, "
-			"pbase == %x\n", par->video.vbase, par->video.pbase);
+		printk(KERN_INFO "savagefb: mapped framebuffer at %p, "
+		       "pbase == %x\n", par->video.vbase, par->video.pbase);
 
 	info->fix.smem_start = par->video.pbase;
 	info->fix.smem_len   = par->video.len - par->cob_size;
 	info->screen_base    = par->video.vbase;
 
 #ifdef CONFIG_MTRR
-	par->video.mtrr = mtrr_add (par->video.pbase, video_len,
-				     MTRR_TYPE_WRCOMB, 1);
+	par->video.mtrr = mtrr_add(par->video.pbase, video_len,
+				   MTRR_TYPE_WRCOMB, 1);
 #endif
 
 	/* Clear framebuffer, it's all white in memory after boot */
-	memset_io (par->video.vbase, 0, par->video.len);
+	memset_io(par->video.vbase, 0, par->video.len);
 
 	return 0;
 }
 
-static void savage_unmap_video (struct fb_info *info)
+static void savage_unmap_video(struct fb_info *info)
 {
 	struct savagefb_par *par = info->par;
 
@@ -1605,16 +1778,16 @@
 
 	if (par->video.vbase) {
 #ifdef CONFIG_MTRR
-		mtrr_del (par->video.mtrr, par->video.pbase, par->video.len);
+		mtrr_del(par->video.mtrr, par->video.pbase, par->video.len);
 #endif
 
-		iounmap (par->video.vbase);
+		iounmap(par->video.vbase);
 		par->video.vbase = NULL;
 		info->screen_base = NULL;
 	}
 }
 
-static int savage_init_hw (struct savagefb_par *par)
+static int savage_init_hw(struct savagefb_par *par)
 {
 	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
 
@@ -1656,7 +1829,7 @@
 
 	switch  (par->chip) {
 	case S3_SAVAGE3D:
-		videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024;
+		videoRam = RamSavage3D[(config1 & 0xC0) >> 6 ] * 1024;
 		break;
 
 	case S3_SAVAGE4:
@@ -1667,22 +1840,22 @@
 		 * can do it different...
 		 */
 		vga_out8(0x3d4, 0x68, par);	/* memory control 1 */
-		if( (vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6) )
+		if ((vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6))
 			RamSavage4[1] = 8;
 
 		/*FALLTHROUGH*/
 
 	case S3_SAVAGE2000:
-		videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024;
+		videoRam = RamSavage4[(config1 & 0xE0) >> 5] * 1024;
 		break;
 
 	case S3_SAVAGE_MX:
 	case S3_SUPERSAVAGE:
-		videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024;
+		videoRam = RamSavageMX[(config1 & 0x0E) >> 1] * 1024;
 		break;
 
 	case S3_PROSAVAGE:
-		videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024;
+		videoRam = RamSavageNB[(config1 & 0xE0) >> 5] * 1024;
 		break;
 
 	default:
@@ -1693,31 +1866,31 @@
 
 	videoRambytes = videoRam * 1024;
 
-	printk (KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
+	printk(KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
 
 	/* reset graphics engine to avoid memory corruption */
-	vga_out8 (0x3d4, 0x66, par);
-	cr66 = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr66 | 0x02, par);
-	udelay (10000);
+	vga_out8(0x3d4, 0x66, par);
+	cr66 = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr66 | 0x02, par);
+	udelay(10000);
 
-	vga_out8 (0x3d4, 0x66, par);
-	vga_out8 (0x3d5, cr66 & ~0x02, par);	/* clear reset flag */
-	udelay (10000);
+	vga_out8(0x3d4, 0x66, par);
+	vga_out8(0x3d5, cr66 & ~0x02, par);	/* clear reset flag */
+	udelay(10000);
 
 
 	/*
 	 * reset memory interface, 3D engine, AGP master, PCI master,
 	 * master engine unit, motion compensation/LPB
 	 */
-	vga_out8 (0x3d4, 0x3f, par);
-	cr3f = vga_in8 (0x3d5, par);
-	vga_out8 (0x3d5, cr3f | 0x08, par);
-	udelay (10000);
+	vga_out8(0x3d4, 0x3f, par);
+	cr3f = vga_in8(0x3d5, par);
+	vga_out8(0x3d5, cr3f | 0x08, par);
+	udelay(10000);
 
-	vga_out8 (0x3d4, 0x3f, par);
-	vga_out8 (0x3d5, cr3f & ~0x08, par);	/* clear reset flags */
-	udelay (10000);
+	vga_out8(0x3d4, 0x3f, par);
+	vga_out8(0x3d5, cr3f & ~0x08, par);	/* clear reset flags */
+	udelay(10000);
 
 	/* Savage ramdac speeds */
 	par->numClocks = 4;
@@ -1740,7 +1913,7 @@
 	n1 = n & 0x1f;
 	n2 = (n >> 5) & 0x03;
 	par->MCLK = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
-	printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
+	printk(KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
 		par->MCLK);
 
 	/* check for DVI/flat panel */
@@ -1769,12 +1942,12 @@
 	/* Check LCD panel parrmation */
 
 	if (par->display_type == DISP_LCD) {
-		unsigned char cr6b = VGArCR( 0x6b, par);
+		unsigned char cr6b = VGArCR(0x6b, par);
 
-		int panelX = (VGArSEQ (0x61, par) +
-			      ((VGArSEQ (0x66, par) & 0x02) << 7) + 1) * 8;
-		int panelY = (VGArSEQ (0x69, par) +
-			      ((VGArSEQ (0x6e, par) & 0x70) << 4) + 1);
+		int panelX = (VGArSEQ(0x61, par) +
+			      ((VGArSEQ(0x66, par) & 0x02) << 7) + 1) * 8;
+		int panelY = (VGArSEQ(0x69, par) +
+			      ((VGArSEQ(0x6e, par) & 0x70) << 4) + 1);
 
 		char * sTechnology = "Unknown";
 
@@ -1796,26 +1969,26 @@
 			ActiveDUO = 0x80
 		};
 
-		if ((VGArSEQ (0x39, par) & 0x03) == 0) {
+		if ((VGArSEQ(0x39, par) & 0x03) == 0) {
 			sTechnology = "TFT";
-		} else if ((VGArSEQ (0x30, par) & 0x01) == 0) {
+		} else if ((VGArSEQ(0x30, par) & 0x01) == 0) {
 			sTechnology = "DSTN";
 		} else 	{
 			sTechnology = "STN";
 		}
 
-		printk (KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
-			panelX, panelY, sTechnology,
-			cr6b & ActiveLCD ? "and active" : "but not active");
+		printk(KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
+		       panelX, panelY, sTechnology,
+		       cr6b & ActiveLCD ? "and active" : "but not active");
 
-		if( cr6b & ActiveLCD ) 	{
+		if (cr6b & ActiveLCD) 	{
 			/*
 			 * If the LCD is active and panel expansion is enabled,
 			 * we probably want to kill the HW cursor.
 			 */
 
-			printk (KERN_INFO "savagefb: Limiting video mode to "
-				"%dx%d\n", panelX, panelY );
+			printk(KERN_INFO "savagefb: Limiting video mode to "
+				"%dx%d\n", panelX, panelY);
 
 			par->SavagePanelWidth = panelX;
 			par->SavagePanelHeight = panelY;
@@ -1824,9 +1997,10 @@
 			par->display_type = DISP_CRT;
 	}
 
-	savage_get_default_par (par);
+	savage_get_default_par(par, &par->state);
+	par->save = par->state;
 
-	if( S3_SAVAGE4_SERIES(par->chip) ) {
+	if (S3_SAVAGE4_SERIES(par->chip)) {
 		/*
 		 * The Savage4 and ProSavage have COB coherency bugs which
 		 * render the buffer useless.  We disable it.
@@ -1845,9 +2019,9 @@
 	return videoRambytes;
 }
 
-static int __devinit savage_init_fb_info (struct fb_info *info,
-					  struct pci_dev *dev,
-					  const struct pci_device_id *id)
+static int __devinit savage_init_fb_info(struct fb_info *info,
+					 struct pci_dev *dev,
+					 const struct pci_device_id *id)
 {
 	struct savagefb_par *par = info->par;
 	int err = 0;
@@ -1863,63 +2037,63 @@
 	switch (info->fix.accel) {
 	case FB_ACCEL_SUPERSAVAGE:
 		par->chip = S3_SUPERSAVAGE;
-		snprintf (info->fix.id, 16, "SuperSavage");
+		snprintf(info->fix.id, 16, "SuperSavage");
 		break;
 	case FB_ACCEL_SAVAGE4:
 		par->chip = S3_SAVAGE4;
-		snprintf (info->fix.id, 16, "Savage4");
+		snprintf(info->fix.id, 16, "Savage4");
 		break;
 	case FB_ACCEL_SAVAGE3D:
 		par->chip = S3_SAVAGE3D;
-		snprintf (info->fix.id, 16, "Savage3D");
+		snprintf(info->fix.id, 16, "Savage3D");
 		break;
 	case FB_ACCEL_SAVAGE3D_MV:
 		par->chip = S3_SAVAGE3D;
-		snprintf (info->fix.id, 16, "Savage3D-MV");
+		snprintf(info->fix.id, 16, "Savage3D-MV");
 		break;
 	case FB_ACCEL_SAVAGE2000:
 		par->chip = S3_SAVAGE2000;
-		snprintf (info->fix.id, 16, "Savage2000");
+		snprintf(info->fix.id, 16, "Savage2000");
 		break;
 	case FB_ACCEL_SAVAGE_MX_MV:
 		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/MX-MV");
+		snprintf(info->fix.id, 16, "Savage/MX-MV");
 		break;
 	case FB_ACCEL_SAVAGE_MX:
 		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/MX");
+		snprintf(info->fix.id, 16, "Savage/MX");
 		break;
 	case FB_ACCEL_SAVAGE_IX_MV:
 		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/IX-MV");
+		snprintf(info->fix.id, 16, "Savage/IX-MV");
 		break;
 	case FB_ACCEL_SAVAGE_IX:
 		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/IX");
+		snprintf(info->fix.id, 16, "Savage/IX");
 		break;
 	case FB_ACCEL_PROSAVAGE_PM:
 		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavagePM");
+		snprintf(info->fix.id, 16, "ProSavagePM");
 		break;
 	case FB_ACCEL_PROSAVAGE_KM:
 		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavageKM");
+		snprintf(info->fix.id, 16, "ProSavageKM");
 		break;
 	case FB_ACCEL_S3TWISTER_P:
 		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "TwisterP");
+		snprintf(info->fix.id, 16, "TwisterP");
 		break;
 	case FB_ACCEL_S3TWISTER_K:
 		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "TwisterK");
+		snprintf(info->fix.id, 16, "TwisterK");
 		break;
 	case FB_ACCEL_PROSAVAGE_DDR:
 		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavageDDR");
+		snprintf(info->fix.id, 16, "ProSavageDDR");
 		break;
 	case FB_ACCEL_PROSAVAGE_DDRK:
 		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavage8");
+		snprintf(info->fix.id, 16, "ProSavage8");
 		break;
 	}
 
@@ -1960,7 +2134,7 @@
 		info->pixmap.buf_align = 4;
 		info->pixmap.access_align = 32;
 
-		err = fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+		err = fb_alloc_cmap(&info->cmap, NR_PALETTE, 0);
 		if (!err)
 		info->flags |= FBINFO_HWACCEL_COPYAREA |
 	                       FBINFO_HWACCEL_FILLRECT |
@@ -1972,8 +2146,8 @@
 
 /* --------------------------------------------------------------------- */
 
-static int __devinit savagefb_probe (struct pci_dev* dev,
-				     const struct pci_device_id* id)
+static int __devinit savagefb_probe(struct pci_dev* dev,
+				    const struct pci_device_id* id)
 {
 	struct fb_info *info;
 	struct savagefb_par *par;
@@ -2085,12 +2259,12 @@
 	fb_destroy_modedb(info->monspecs.modedb);
 	info->monspecs.modedb = NULL;
 
-	err = register_framebuffer (info);
+	err = register_framebuffer(info);
 	if (err < 0)
 		goto failed;
 
-	printk (KERN_INFO "fb: S3 %s frame buffer device\n",
-		info->fix.id);
+	printk(KERN_INFO "fb: S3 %s frame buffer device\n",
+	       info->fix.id);
 
 	/*
 	 * Our driver data
@@ -2103,10 +2277,10 @@
 #ifdef CONFIG_FB_SAVAGE_I2C
 	savagefb_delete_i2c_busses(info);
 #endif
-	fb_alloc_cmap (&info->cmap, 0, 0);
+	fb_alloc_cmap(&info->cmap, 0, 0);
 	savage_unmap_video(info);
  failed_video:
-	savage_unmap_mmio (info);
+	savage_unmap_mmio(info);
  failed_mmio:
 	kfree(info->pixmap.addr);
  failed_init:
@@ -2117,7 +2291,7 @@
 	return err;
 }
 
-static void __devexit savagefb_remove (struct pci_dev *dev)
+static void __devexit savagefb_remove(struct pci_dev *dev)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
 
@@ -2129,16 +2303,16 @@
 		 * we will be leaving hooks that could cause
 		 * oopsen laying around.
 		 */
-		if (unregister_framebuffer (info))
-			printk (KERN_WARNING "savagefb: danger danger! "
-				"Oopsen imminent!\n");
+		if (unregister_framebuffer(info))
+			printk(KERN_WARNING "savagefb: danger danger! "
+			       "Oopsen imminent!\n");
 
 #ifdef CONFIG_FB_SAVAGE_I2C
 		savagefb_delete_i2c_busses(info);
 #endif
-		fb_alloc_cmap (&info->cmap, 0, 0);
-		savage_unmap_video (info);
-		savage_unmap_mmio (info);
+		fb_alloc_cmap(&info->cmap, 0, 0);
+		savage_unmap_video(info);
+		savage_unmap_mmio(info);
 		kfree(info->pixmap.addr);
 		pci_release_regions(dev);
 		framebuffer_release(info);
@@ -2151,7 +2325,7 @@
 	}
 }
 
-static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
+static int savagefb_suspend(struct pci_dev* dev, pm_message_t state)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
 	struct savagefb_par *par = info->par;
@@ -2177,6 +2351,7 @@
 		info->fbops->fb_sync(info);
 
 	savagefb_blank(FB_BLANK_POWERDOWN, info);
+	savage_set_default_par(par, &par->save);
 	savage_disable_mmio(par);
 	pci_save_state(dev);
 	pci_disable_device(dev);
@@ -2186,7 +2361,7 @@
 	return 0;
 }
 
-static int savagefb_resume (struct pci_dev* dev)
+static int savagefb_resume(struct pci_dev* dev)
 {
 	struct fb_info *info = pci_get_drvdata(dev);
 	struct savagefb_par *par = info->par;
@@ -2210,15 +2385,15 @@
 	pci_set_power_state(dev, PCI_D0);
 	pci_restore_state(dev);
 
-	if(pci_enable_device(dev))
+	if (pci_enable_device(dev))
 		DBG("err");
 
 	pci_set_master(dev);
 	savage_enable_mmio(par);
 	savage_init_hw(par);
-	savagefb_set_par (info);
+	savagefb_set_par(info);
+	fb_set_suspend(info, 0);
 	savagefb_blank(FB_BLANK_UNBLANK, info);
-	fb_set_suspend (info, 0);
 	release_console_sem();
 
 	return 0;
@@ -2311,10 +2486,10 @@
 
 /* **************************** exit-time only **************************** */
 
-static void __exit savage_done (void)
+static void __exit savage_done(void)
 {
 	DBG("savage_done");
-	pci_unregister_driver (&savagefb_driver);
+	pci_unregister_driver(&savagefb_driver);
 }
 
 
@@ -2345,7 +2520,7 @@
 		return -ENODEV;
 
 	savagefb_setup(option);
-	return pci_register_driver (&savagefb_driver);
+	return pci_register_driver(&savagefb_driver);
 
 }
 
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
index 8adf5bf..c63c0e7 100644
--- a/drivers/video/sis/sis_main.c
+++ b/drivers/video/sis/sis_main.c
@@ -275,7 +275,7 @@
 static void __devinit
 sisfb_get_vga_mode_from_kernel(void)
 {
-#if (defined(__i386__) || defined(__x86_64__)) && defined(CONFIG_VIDEO_SELECT)
+#ifdef CONFIG_X86
 	char mymode[32];
 	int  mydepth = screen_info.lfb_depth;
 
diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
index 9b70777..67f429e 100644
--- a/drivers/video/skeletonfb.c
+++ b/drivers/video/skeletonfb.c
@@ -906,11 +906,6 @@
 }
 #endif
 
-MODULE_LICENSE("GPL");
-module_init(xxxfb_init);
-module_exit(xxxfb_exit);
-
-
     /*
      *  Setup
      */
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 7398bd4..6c2c78a 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -26,7 +26,6 @@
 #include <linux/selection.h>
 #include <asm/io.h>
 #include <video/tgafb.h>
-#include <linux/selection.h>
 
 /*
  * Local functions.
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 9ac2d31..41f8c2d 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -551,7 +551,7 @@
 #define crtc_unlock()	write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
 
 /*  Return flat panel's maximum x resolution */
-static int __init get_nativex(void)
+static int __devinit get_nativex(void)
 {
 	int x,y,tmp;
 
@@ -658,7 +658,7 @@
  * If we see that FP is active we assume we have one.
  * Otherwise we have a CRT display.User can override.
  */
-static unsigned int __init get_displaytype(void)
+static unsigned int __devinit get_displaytype(void)
 {
 	if (fp)
 		return DISPLAY_FP;
@@ -668,7 +668,7 @@
 }
 
 /* Try detecting the video memory size */
-static unsigned int __init get_memsize(void)
+static unsigned int __devinit get_memsize(void)
 {
 	unsigned char tmp, tmp2;
 	unsigned int k;
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index b0b9acf..5718924 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -51,7 +51,7 @@
 static int             mtrr      = 0; /* disable mtrr */
 static int	       vram_remap __initdata = 0; /* Set amount of memory to be used */
 static int	       vram_total __initdata = 0; /* Set total amount of memory */
-static int             pmi_setpal = 0;	/* pmi for palette changes ??? */
+static int             pmi_setpal = 1;	/* pmi for palette changes ??? */
 static int             ypan       = 0;  /* 0..nothing, 1..ypan, 2..ywrap */
 static unsigned short  *pmi_base  = NULL;
 static void            (*pmi_start)(void);
@@ -80,15 +80,30 @@
 	return 0;
 }
 
-static void vesa_setpalette(int regno, unsigned red, unsigned green,
+static int vesa_setpalette(int regno, unsigned red, unsigned green,
 			    unsigned blue)
 {
 	int shift = 16 - depth;
+	int err = -EINVAL;
+
+/*
+ * Try VGA registers first...
+ */
+	if (vga_compat) {
+		outb_p(regno,       dac_reg);
+		outb_p(red   >> shift, dac_val);
+		outb_p(green >> shift, dac_val);
+		outb_p(blue  >> shift, dac_val);
+		err = 0;
+	}
 
 #ifdef __i386__
-	struct { u_char blue, green, red, pad; } entry;
+/*
+ * Fallback to the PMI....
+ */
+	if (err && pmi_setpal) {
+		struct { u_char blue, green, red, pad; } entry;
 
-	if (pmi_setpal) {
 		entry.red   = red   >> shift;
 		entry.green = green >> shift;
 		entry.blue  = blue  >> shift;
@@ -102,26 +117,19 @@
                   "d" (regno),          /* EDX */
                   "D" (&entry),         /* EDI */
                   "S" (&pmi_pal));      /* ESI */
-		return;
+		err = 0;
 	}
 #endif
 
-/*
- * without protected mode interface and if VGA compatible,
- * try VGA registers...
- */
-	if (vga_compat) {
-		outb_p(regno,       dac_reg);
-		outb_p(red   >> shift, dac_val);
-		outb_p(green >> shift, dac_val);
-		outb_p(blue  >> shift, dac_val);
-	}
+	return err;
 }
 
 static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 			    unsigned blue, unsigned transp,
 			    struct fb_info *info)
 {
+	int err = 0;
+
 	/*
 	 *  Set a single color register. The values supplied are
 	 *  already rounded down to the hardware's capabilities
@@ -133,7 +141,7 @@
 		return 1;
 
 	if (info->var.bits_per_pixel == 8)
-		vesa_setpalette(regno,red,green,blue);
+		err = vesa_setpalette(regno,red,green,blue);
 	else if (regno < 16) {
 		switch (info->var.bits_per_pixel) {
 		case 16:
@@ -164,7 +172,7 @@
 		}
 	}
 
-	return 0;
+	return err;
 }
 
 static struct fb_ops vesafb_ops = {
@@ -460,9 +468,7 @@
 	},
 };
 
-static struct platform_device vesafb_device = {
-	.name	= "vesafb",
-};
+static struct platform_device *vesafb_device;
 
 static int __init vesafb_init(void)
 {
@@ -475,10 +481,19 @@
 	ret = platform_driver_register(&vesafb_driver);
 
 	if (!ret) {
-		ret = platform_device_register(&vesafb_device);
-		if (ret)
+		vesafb_device = platform_device_alloc("vesafb", 0);
+
+		if (vesafb_device)
+			ret = platform_device_add(vesafb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(vesafb_device);
 			platform_driver_unregister(&vesafb_driver);
+		}
 	}
+
 	return ret;
 }
 module_init(vesafb_init);
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 77eed1f..d073ffb 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -398,12 +398,6 @@
      *  Initialisation
      */
 
-static void vfb_platform_release(struct device *device)
-{
-	// This is called when the reference count goes to zero.
-	dev_err(device, "This driver is broken, please bug the authors so they will fix it.\n");
-}
-
 static int __init vfb_probe(struct platform_device *dev)
 {
 	struct fb_info *info;
@@ -482,13 +476,7 @@
 	},
 };
 
-static struct platform_device vfb_device = {
-	.name	= "vfb",
-	.id	= 0,
-	.dev	= {
-		.release = vfb_platform_release,
-	}
-};
+static struct platform_device *vfb_device;
 
 static int __init vfb_init(void)
 {
@@ -508,10 +496,19 @@
 	ret = platform_driver_register(&vfb_driver);
 
 	if (!ret) {
-		ret = platform_device_register(&vfb_device);
-		if (ret)
+		vfb_device = platform_device_alloc("vfb", 0);
+
+		if (vfb_device)
+			ret = platform_device_add(vfb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(vfb_device);
 			platform_driver_unregister(&vfb_driver);
+		}
 	}
+
 	return ret;
 }
 
@@ -520,7 +517,7 @@
 #ifdef MODULE
 static void __exit vfb_exit(void)
 {
-	platform_device_unregister(&vfb_device);
+	platform_device_unregister(vfb_device);
 	platform_driver_unregister(&vfb_driver);
 }
 
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index f3f16fd..3c404c9 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1334,9 +1334,8 @@
 }
 #endif
 
-static int __init vga16fb_probe(struct device *device)
+static int __init vga16fb_probe(struct platform_device *dev)
 {
-	struct platform_device *dev = to_platform_device(device);
 	struct fb_info *info;
 	struct vga16fb_par *par;
 	int i;
@@ -1351,7 +1350,7 @@
 	}
 
 	/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
-	info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS);
+	info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
 
 	if (!info->screen_base) {
 		printk(KERN_ERR "vga16fb: unable to map device\n");
@@ -1403,7 +1402,7 @@
 
 	printk(KERN_INFO "fb%d: %s frame buffer device\n",
 	       info->node, info->fix.id);
-	dev_set_drvdata(device, info);
+	platform_set_drvdata(dev, info);
 
 	return 0;
 
@@ -1417,9 +1416,9 @@
 	return ret;
 }
 
-static int vga16fb_remove(struct device *device)
+static int vga16fb_remove(struct platform_device *dev)
 {
-	struct fb_info *info = dev_get_drvdata(device);
+	struct fb_info *info = platform_get_drvdata(dev);
 
 	if (info) {
 		unregister_framebuffer(info);
@@ -1432,16 +1431,15 @@
 	return 0;
 }
 
-static struct device_driver vga16fb_driver = {
-	.name = "vga16fb",
-	.bus  = &platform_bus_type,
+static struct platform_driver vga16fb_driver = {
 	.probe = vga16fb_probe,
 	.remove = vga16fb_remove,
+	.driver = {
+		.name = "vga16fb",
+	},
 };
 
-static struct platform_device vga16fb_device = {
-	.name = "vga16fb",
-};
+static struct platform_device *vga16fb_device;
 
 static int __init vga16fb_init(void)
 {
@@ -1454,12 +1452,20 @@
 
 	vga16fb_setup(option);
 #endif
-	ret = driver_register(&vga16fb_driver);
+	ret = platform_driver_register(&vga16fb_driver);
 
 	if (!ret) {
-		ret = platform_device_register(&vga16fb_device);
-		if (ret)
-			driver_unregister(&vga16fb_driver);
+		vga16fb_device = platform_device_alloc("vga16fb", 0);
+
+		if (vga16fb_device)
+			ret = platform_device_add(vga16fb_device);
+		else
+			ret = -ENOMEM;
+
+		if (ret) {
+			platform_device_put(vga16fb_device);
+			platform_driver_unregister(&vga16fb_driver);
+		}
 	}
 
 	return ret;
@@ -1467,8 +1473,8 @@
 
 static void __exit vga16fb_exit(void)
 {
-	platform_device_unregister(&vga16fb_device);
-	driver_unregister(&vga16fb_driver);
+	platform_device_unregister(vga16fb_device);
+	platform_driver_unregister(&vga16fb_driver);
 }
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 5e61ed5..8b3d0f0 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -2,8 +2,9 @@
 
 config W1
 	tristate "Dallas's 1-wire support"
+	depends on CONNECTOR
 	---help---
-	  Dallas's 1-wire bus is useful to connect slow 1-pin devices
+	  Dallas' 1-wire bus is useful to connect slow 1-pin devices
 	  such as iButtons and thermal sensors.
 
 	  If you want W1 support, you should say Y here.
@@ -11,6 +12,18 @@
 	  This W1 support can also be built as a module.  If so, the module
 	  will be called wire.ko.
 
+config W1_CON
+	depends on CONNECTOR && W1
+	bool "Userspace communication over connector"
+	default y
+	--- help ---
+	  This allows to communicate with userspace using connector [Documentation/connector].
+	  There are three types of messages between w1 core and userspace:
+	  1. Events. They are generated each time new master or slave device found
+		either due to automatic or requested search.
+	  2. Userspace commands. Includes read/write and search/alarm search comamnds.
+	  3. Replies to userspace commands.
+
 source drivers/w1/masters/Kconfig
 source drivers/w1/slaves/Kconfig
 
diff --git a/drivers/w1/Makefile b/drivers/w1/Makefile
index 0c2aa22d..93845a2 100644
--- a/drivers/w1/Makefile
+++ b/drivers/w1/Makefile
@@ -2,10 +2,6 @@
 # Makefile for the Dallas's 1-wire bus.
 #
 
-ifneq ($(CONFIG_NET), y)
-EXTRA_CFLAGS	+= -DNETLINK_DISABLED
-endif
-
 ifeq ($(CONFIG_W1_DS2433_CRC), y)
 EXTRA_CFLAGS	+= -DCONFIG_W1_F23_CRC
 endif
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index c6bad4d..2fb4255 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -15,24 +15,15 @@
 	  This support is also available as a module.  If so, the module
 	  will be called matrox_w1.ko.
 
-config W1_MASTER_DS9490
-	tristate "DS9490R transport layer driver"
-	depends on W1 && USB
-	help
-	  Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
+config W1_MASTER_DS2490
+	tristate "DS2490 USB <-> W1 transport layer for 1-wire"
+  	depends on W1 && USB
+  	help
+	  Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges,
+	  for example DS9490*.
 
-	  This support is also available as a module.  If so, the module
-	  will be called ds9490r.ko.
-
-config W1_MASTER_DS9490_BRIDGE
-	tristate "DS9490R USB <-> W1 transport layer for 1-wire"
-	depends on W1_MASTER_DS9490
-	help
-	  Say Y here if you want to communicate with your 1-wire devices
-	  using DS9490R USB bridge.
-
-	  This support is also available as a module.  If so, the module
-	  will be called ds_w1_bridge.ko.
+  	  This support is also available as a module.  If so, the module
+	  will be called ds2490.ko.
 
 config W1_MASTER_DS2482
 	tristate "Maxim DS2482 I2C to 1-Wire bridge"
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index 1f3c8b9..4cee256 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -3,11 +3,6 @@
 #
 
 obj-$(CONFIG_W1_MASTER_MATROX)		+= matrox_w1.o
-
-obj-$(CONFIG_W1_MASTER_DS9490)		+= ds9490r.o
-ds9490r-objs    := dscore.o
-
-obj-$(CONFIG_W1_MASTER_DS9490_BRIDGE)	+= ds_w1_bridge.o
-
+obj-$(CONFIG_W1_MASTER_DS2490)		+= ds2490.o
 obj-$(CONFIG_W1_MASTER_DS2482)		+= ds2482.o
 
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index d1cacd2..af492cc 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -125,7 +125,7 @@
 
 struct ds2482_data {
 	struct i2c_client	client;
-	struct semaphore	access_lock;
+	struct mutex		access_lock;
 
 	/* 1-wire interface(s) */
 	int			w1_count;	/* 1 or 8 */
@@ -265,7 +265,7 @@
 	struct ds2482_data    *pdev = pchan->pdev;
 	int status = -1;
 
-	down(&pdev->access_lock);
+	mutex_lock(&pdev->access_lock);
 
 	/* Select the channel */
 	ds2482_wait_1wire_idle(pdev);
@@ -277,7 +277,7 @@
 				  bit ? 0xFF : 0))
 		status = ds2482_wait_1wire_idle(pdev);
 
-	up(&pdev->access_lock);
+	mutex_unlock(&pdev->access_lock);
 
 	return (status & DS2482_REG_STS_SBR) ? 1 : 0;
 }
@@ -297,7 +297,7 @@
 	struct ds2482_data    *pdev = pchan->pdev;
 	int status = (3 << 5);
 
-	down(&pdev->access_lock);
+	mutex_lock(&pdev->access_lock);
 
 	/* Select the channel */
 	ds2482_wait_1wire_idle(pdev);
@@ -309,7 +309,7 @@
 				  dbit ? 0xFF : 0))
 		status = ds2482_wait_1wire_idle(pdev);
 
-	up(&pdev->access_lock);
+	mutex_unlock(&pdev->access_lock);
 
 	/* Decode the status */
 	return (status >> 5);
@@ -326,7 +326,7 @@
 	struct ds2482_w1_chan *pchan = data;
 	struct ds2482_data    *pdev = pchan->pdev;
 
-	down(&pdev->access_lock);
+	mutex_lock(&pdev->access_lock);
 
 	/* Select the channel */
 	ds2482_wait_1wire_idle(pdev);
@@ -336,7 +336,7 @@
 	/* Send the write byte command */
 	ds2482_send_cmd_data(pdev, DS2482_CMD_1WIRE_WRITE_BYTE, byte);
 
-	up(&pdev->access_lock);
+	mutex_unlock(&pdev->access_lock);
 }
 
 /**
@@ -351,7 +351,7 @@
 	struct ds2482_data    *pdev = pchan->pdev;
 	int result;
 
-	down(&pdev->access_lock);
+	mutex_lock(&pdev->access_lock);
 
 	/* Select the channel */
 	ds2482_wait_1wire_idle(pdev);
@@ -370,7 +370,7 @@
 	/* Read the data byte */
 	result = i2c_smbus_read_byte(&pdev->client);
 
-	up(&pdev->access_lock);
+	mutex_unlock(&pdev->access_lock);
 
 	return result;
 }
@@ -389,7 +389,7 @@
 	int err;
 	u8 retval = 1;
 
-	down(&pdev->access_lock);
+	mutex_lock(&pdev->access_lock);
 
 	/* Select the channel */
 	ds2482_wait_1wire_idle(pdev);
@@ -409,7 +409,7 @@
 					     0xF0);
 	}
 
-	up(&pdev->access_lock);
+	mutex_unlock(&pdev->access_lock);
 
 	return retval;
 }
@@ -482,7 +482,7 @@
 	snprintf(new_client->name, sizeof(new_client->name), "ds2482-%d00",
 		 data->w1_count);
 
-	init_MUTEX(&data->access_lock);
+	mutex_init(&data->access_lock);
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
new file mode 100644
index 0000000..299e274
--- /dev/null
+++ b/drivers/w1/masters/ds2490.c
@@ -0,0 +1,947 @@
+/*
+ *	dscore.c
+ *
+ * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/usb.h>
+
+#include "../w1_int.h"
+#include "../w1.h"
+
+/* COMMAND TYPE CODES */
+#define CONTROL_CMD			0x00
+#define COMM_CMD			0x01
+#define MODE_CMD			0x02
+
+/* CONTROL COMMAND CODES */
+#define CTL_RESET_DEVICE		0x0000
+#define CTL_START_EXE			0x0001
+#define CTL_RESUME_EXE			0x0002
+#define CTL_HALT_EXE_IDLE		0x0003
+#define CTL_HALT_EXE_DONE		0x0004
+#define CTL_FLUSH_COMM_CMDS		0x0007
+#define CTL_FLUSH_RCV_BUFFER		0x0008
+#define CTL_FLUSH_XMT_BUFFER		0x0009
+#define CTL_GET_COMM_CMDS		0x000A
+
+/* MODE COMMAND CODES */
+#define MOD_PULSE_EN			0x0000
+#define MOD_SPEED_CHANGE_EN		0x0001
+#define MOD_1WIRE_SPEED			0x0002
+#define MOD_STRONG_PU_DURATION		0x0003
+#define MOD_PULLDOWN_SLEWRATE		0x0004
+#define MOD_PROG_PULSE_DURATION		0x0005
+#define MOD_WRITE1_LOWTIME		0x0006
+#define MOD_DSOW0_TREC			0x0007
+
+/* COMMUNICATION COMMAND CODES */
+#define COMM_ERROR_ESCAPE		0x0601
+#define COMM_SET_DURATION		0x0012
+#define COMM_BIT_IO			0x0020
+#define COMM_PULSE			0x0030
+#define COMM_1_WIRE_RESET		0x0042
+#define COMM_BYTE_IO			0x0052
+#define COMM_MATCH_ACCESS		0x0064
+#define COMM_BLOCK_IO			0x0074
+#define COMM_READ_STRAIGHT		0x0080
+#define COMM_DO_RELEASE			0x6092
+#define COMM_SET_PATH			0x00A2
+#define COMM_WRITE_SRAM_PAGE		0x00B2
+#define COMM_WRITE_EPROM		0x00C4
+#define COMM_READ_CRC_PROT_PAGE		0x00D4
+#define COMM_READ_REDIRECT_PAGE_CRC	0x21E4
+#define COMM_SEARCH_ACCESS		0x00F4
+
+/* Communication command bits */
+#define COMM_TYPE			0x0008
+#define COMM_SE				0x0008
+#define COMM_D				0x0008
+#define COMM_Z				0x0008
+#define COMM_CH				0x0008
+#define COMM_SM				0x0008
+#define COMM_R				0x0008
+#define COMM_IM				0x0001
+
+#define COMM_PS				0x4000
+#define COMM_PST			0x4000
+#define COMM_CIB			0x4000
+#define COMM_RTS			0x4000
+#define COMM_DT				0x2000
+#define COMM_SPU			0x1000
+#define COMM_F				0x0800
+#define COMM_NTP			0x0400
+#define COMM_ICP			0x0200
+#define COMM_RST			0x0100
+
+#define PULSE_PROG			0x01
+#define PULSE_SPUE			0x02
+
+#define BRANCH_MAIN			0xCC
+#define BRANCH_AUX			0x33
+
+/*
+ * Duration of the strong pull-up pulse in milliseconds.
+ */
+#define PULLUP_PULSE_DURATION		750
+
+/* Status flags */
+#define ST_SPUA				0x01  /* Strong Pull-up is active */
+#define ST_PRGA				0x02  /* 12V programming pulse is being generated */
+#define ST_12VP				0x04  /* external 12V programming voltage is present */
+#define ST_PMOD				0x08  /* DS2490 powered from USB and external sources */
+#define ST_HALT				0x10  /* DS2490 is currently halted */
+#define ST_IDLE				0x20  /* DS2490 is currently idle */
+#define ST_EPOF				0x80
+
+#define SPEED_NORMAL			0x00
+#define SPEED_FLEXIBLE			0x01
+#define SPEED_OVERDRIVE			0x02
+
+#define NUM_EP				4
+#define EP_CONTROL			0
+#define EP_STATUS			1
+#define EP_DATA_OUT			2
+#define EP_DATA_IN			3
+
+struct ds_device
+{
+	struct list_head	ds_entry;
+
+	struct usb_device	*udev;
+	struct usb_interface	*intf;
+
+	int			ep[NUM_EP];
+
+	struct w1_bus_master	master;
+};
+
+struct ds_status
+{
+	u8			enable;
+	u8			speed;
+	u8			pullup_dur;
+	u8			ppuls_dur;
+	u8			pulldown_slew;
+	u8			write1_time;
+	u8			write0_time;
+	u8			reserved0;
+	u8			status;
+	u8			command0;
+	u8			command1;
+	u8			command_buffer_status;
+	u8			data_out_buffer_status;
+	u8			data_in_buffer_status;
+	u8			reserved1;
+	u8			reserved2;
+
+};
+
+static struct usb_device_id ds_id_table [] = {
+	{ USB_DEVICE(0x04fa, 0x2490) },
+	{ },
+};
+MODULE_DEVICE_TABLE(usb, ds_id_table);
+
+static int ds_probe(struct usb_interface *, const struct usb_device_id *);
+static void ds_disconnect(struct usb_interface *);
+
+static inline void ds_dump_status(unsigned char *, unsigned char *, int);
+static int ds_send_control(struct ds_device *, u16, u16);
+static int ds_send_control_cmd(struct ds_device *, u16, u16);
+
+static LIST_HEAD(ds_devices);
+static DEFINE_MUTEX(ds_mutex);
+
+static struct usb_driver ds_driver = {
+	.name =		"DS9490R",
+	.probe =	ds_probe,
+	.disconnect =	ds_disconnect,
+	.id_table =	ds_id_table,
+};
+
+static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
+{
+	int err;
+
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+			CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
+				value, index, err);
+		return err;
+	}
+
+	return err;
+}
+#if 0
+static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
+{
+	int err;
+
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+			MODE_CMD, 0x40, value, index, NULL, 0, 1000);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
+				value, index, err);
+		return err;
+	}
+
+	return err;
+}
+#endif
+static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
+{
+	int err;
+
+	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
+			COMM_CMD, 0x40, value, index, NULL, 0, 1000);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
+				value, index, err);
+		return err;
+	}
+
+	return err;
+}
+
+static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
+{
+	printk("%45s: %8x\n", str, buf[off]);
+}
+
+static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
+				 unsigned char *buf, int size)
+{
+	int count, err;
+
+	memset(st, 0, sizeof(st));
+
+	count = 0;
+	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
+		return err;
+	}
+
+	if (count >= sizeof(*st))
+		memcpy(st, buf, sizeof(*st));
+
+	return count;
+}
+
+static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+{
+	unsigned char buf[64];
+	int count, err = 0, i;
+
+	memcpy(st, buf, sizeof(*st));
+
+	count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+	if (count < 0)
+		return err;
+
+	printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
+	for (i=0; i<count; ++i)
+		printk("%02x ", buf[i]);
+	printk("\n");
+
+	if (count >= 16) {
+		ds_dump_status(buf, "enable flag", 0);
+		ds_dump_status(buf, "1-wire speed", 1);
+		ds_dump_status(buf, "strong pullup duration", 2);
+		ds_dump_status(buf, "programming pulse duration", 3);
+		ds_dump_status(buf, "pulldown slew rate control", 4);
+		ds_dump_status(buf, "write-1 low time", 5);
+		ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
+		ds_dump_status(buf, "reserved (test register)", 7);
+		ds_dump_status(buf, "device status flags", 8);
+		ds_dump_status(buf, "communication command byte 1", 9);
+		ds_dump_status(buf, "communication command byte 2", 10);
+		ds_dump_status(buf, "communication command buffer status", 11);
+		ds_dump_status(buf, "1-wire data output buffer status", 12);
+		ds_dump_status(buf, "1-wire data input buffer status", 13);
+		ds_dump_status(buf, "reserved", 14);
+		ds_dump_status(buf, "reserved", 15);
+	}
+
+	memcpy(st, buf, sizeof(*st));
+
+	if (st->status & ST_EPOF) {
+		printk(KERN_INFO "Resetting device after ST_EPOF.\n");
+		err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+		if (err)
+			return err;
+		count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+		if (count < 0)
+			return err;
+	}
+#if 0
+	if (st->status & ST_IDLE) {
+		printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
+		err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+		if (err)
+			return err;
+	}
+#endif
+
+	return err;
+}
+
+static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+{
+	int count, err;
+	struct ds_status st;
+
+	count = 0;
+	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
+				buf, size, &count, 1000);
+	if (err < 0) {
+		printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
+		usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
+		ds_recv_status(dev, &st);
+		return err;
+	}
+
+#if 0
+	{
+		int i;
+
+		printk("%s: count=%d: ", __func__, count);
+		for (i=0; i<count; ++i)
+			printk("%02x ", buf[i]);
+		printk("\n");
+	}
+#endif
+	return count;
+}
+
+static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+{
+	int count, err;
+
+	count = 0;
+	err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
+	if (err < 0) {
+		printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
+		return err;
+	}
+
+	return err;
+}
+
+#if 0
+
+int ds_stop_pulse(struct ds_device *dev, int limit)
+{
+	struct ds_status st;
+	int count = 0, err = 0;
+	u8 buf[0x20];
+
+	do {
+		err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
+		if (err)
+			break;
+		err = ds_send_control(dev, CTL_RESUME_EXE, 0);
+		if (err)
+			break;
+		err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
+		if (err)
+			break;
+
+		if ((st.status & ST_SPUA) == 0) {
+			err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
+			if (err)
+				break;
+		}
+	} while(++count < limit);
+
+	return err;
+}
+
+int ds_detect(struct ds_device *dev, struct ds_status *st)
+{
+	int err;
+
+	err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
+	if (err)
+		return err;
+
+	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
+	if (err)
+		return err;
+
+	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
+	if (err)
+		return err;
+
+	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
+	if (err)
+		return err;
+
+	err = ds_recv_status(dev, st);
+
+	return err;
+}
+
+#endif  /*  0  */
+
+static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
+{
+	u8 buf[0x20];
+	int err, count = 0;
+
+	do {
+		err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
+#if 0
+		if (err >= 0) {
+			int i;
+			printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
+			for (i=0; i<err; ++i)
+				printk("%02x ", buf[i]);
+			printk("\n");
+		}
+#endif
+	} while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
+
+
+	if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
+		ds_recv_status(dev, st);
+		return -1;
+	} else
+		return 0;
+}
+
+static int ds_reset(struct ds_device *dev, struct ds_status *st)
+{
+	int err;
+
+	//err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
+	err = ds_send_control(dev, 0x43, SPEED_NORMAL);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, st);
+#if 0
+	if (st->command_buffer_status) {
+		printk(KERN_INFO "Short circuit.\n");
+		return -EIO;
+	}
+#endif
+
+	return 0;
+}
+
+#if 0
+static int ds_set_speed(struct ds_device *dev, int speed)
+{
+	int err;
+
+	if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
+		return -EINVAL;
+
+	if (speed != SPEED_OVERDRIVE)
+		speed = SPEED_FLEXIBLE;
+
+	speed &= 0xff;
+
+	err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
+	if (err)
+		return err;
+
+	return err;
+}
+#endif  /*  0  */
+
+static int ds_start_pulse(struct ds_device *dev, int delay)
+{
+	int err;
+	u8 del = 1 + (u8)(delay >> 4);
+	struct ds_status st;
+
+#if 0
+	err = ds_stop_pulse(dev, 10);
+	if (err)
+		return err;
+
+	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
+	if (err)
+		return err;
+#endif
+	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
+	if (err)
+		return err;
+
+	err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
+	if (err)
+		return err;
+
+	mdelay(delay);
+
+	ds_wait_status(dev, &st);
+
+	return err;
+}
+
+static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
+{
+	int err, count;
+	struct ds_status st;
+	u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
+	u16 cmd;
+
+	err = ds_send_control(dev, value, 0);
+	if (err)
+		return err;
+
+	count = 0;
+	do {
+		err = ds_wait_status(dev, &st);
+		if (err)
+			return err;
+
+		cmd = st.command0 | (st.command1 << 8);
+	} while (cmd != value && ++count < 10);
+
+	if (err < 0 || count >= 10) {
+		printk(KERN_ERR "Failed to obtain status.\n");
+		return -EINVAL;
+	}
+
+	err = ds_recv_data(dev, tbit, sizeof(*tbit));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int ds_write_bit(struct ds_device *dev, u8 bit)
+{
+	int err;
+	struct ds_status st;
+
+	err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	return 0;
+}
+
+static int ds_write_byte(struct ds_device *dev, u8 byte)
+{
+	int err;
+	struct ds_status st;
+	u8 rbyte;
+
+	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
+	if (err)
+		return err;
+
+	err = ds_wait_status(dev, &st);
+	if (err)
+		return err;
+
+	err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
+	if (err < 0)
+		return err;
+
+	ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+
+	return !(byte == rbyte);
+}
+
+static int ds_read_byte(struct ds_device *dev, u8 *byte)
+{
+	int err;
+	struct ds_status st;
+
+	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	err = ds_recv_data(dev, byte, sizeof(*byte));
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+{
+	struct ds_status st;
+	int err;
+
+	if (len > 64*1024)
+		return -E2BIG;
+
+	memset(buf, 0xFF, len);
+
+	err = ds_send_data(dev, buf, len);
+	if (err < 0)
+		return err;
+
+	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	memset(buf, 0x00, len);
+	err = ds_recv_data(dev, buf, len);
+
+	return err;
+}
+
+static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
+{
+	int err;
+	struct ds_status st;
+
+	err = ds_send_data(dev, buf, len);
+	if (err < 0)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	err = ds_recv_data(dev, buf, len);
+	if (err < 0)
+		return err;
+
+	ds_start_pulse(dev, PULLUP_PULSE_DURATION);
+
+	return !(err == len);
+}
+
+#if 0
+
+static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
+{
+	int err;
+	u16 value, index;
+	struct ds_status st;
+
+	memset(buf, 0, sizeof(buf));
+
+	err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
+	if (err)
+		return err;
+
+	ds_wait_status(ds_dev, &st);
+
+	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
+	index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
+	err = ds_send_control(ds_dev, value, index);
+	if (err)
+		return err;
+
+	ds_wait_status(ds_dev, &st);
+
+	err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
+	if (err < 0)
+		return err;
+
+	return err/8;
+}
+
+static int ds_match_access(struct ds_device *dev, u64 init)
+{
+	int err;
+	struct ds_status st;
+
+	err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	return 0;
+}
+
+static int ds_set_path(struct ds_device *dev, u64 init)
+{
+	int err;
+	struct ds_status st;
+	u8 buf[9];
+
+	memcpy(buf, &init, 8);
+	buf[8] = BRANCH_MAIN;
+
+	err = ds_send_data(dev, buf, sizeof(buf));
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
+	if (err)
+		return err;
+
+	ds_wait_status(dev, &st);
+
+	return 0;
+}
+
+#endif  /*  0  */
+
+static u8 ds9490r_touch_bit(void *data, u8 bit)
+{
+	u8 ret;
+	struct ds_device *dev = data;
+
+	if (ds_touch_bit(dev, bit, &ret))
+		return 0;
+
+	return ret;
+}
+
+static void ds9490r_write_bit(void *data, u8 bit)
+{
+	struct ds_device *dev = data;
+
+	ds_write_bit(dev, bit);
+}
+
+static void ds9490r_write_byte(void *data, u8 byte)
+{
+	struct ds_device *dev = data;
+
+	ds_write_byte(dev, byte);
+}
+
+static u8 ds9490r_read_bit(void *data)
+{
+	struct ds_device *dev = data;
+	int err;
+	u8 bit = 0;
+
+	err = ds_touch_bit(dev, 1, &bit);
+	if (err)
+		return 0;
+
+	return bit & 1;
+}
+
+static u8 ds9490r_read_byte(void *data)
+{
+	struct ds_device *dev = data;
+	int err;
+	u8 byte = 0;
+
+	err = ds_read_byte(dev, &byte);
+	if (err)
+		return 0;
+
+	return byte;
+}
+
+static void ds9490r_write_block(void *data, const u8 *buf, int len)
+{
+	struct ds_device *dev = data;
+
+	ds_write_block(dev, (u8 *)buf, len);
+}
+
+static u8 ds9490r_read_block(void *data, u8 *buf, int len)
+{
+	struct ds_device *dev = data;
+	int err;
+
+	err = ds_read_block(dev, buf, len);
+	if (err < 0)
+		return 0;
+
+	return len;
+}
+
+static u8 ds9490r_reset(void *data)
+{
+	struct ds_device *dev = data;
+	struct ds_status st;
+	int err;
+
+	memset(&st, 0, sizeof(st));
+
+	err = ds_reset(dev, &st);
+	if (err)
+		return 1;
+
+	return 0;
+}
+
+static int ds_w1_init(struct ds_device *dev)
+{
+	memset(&dev->master, 0, sizeof(struct w1_bus_master));
+
+	dev->master.data	= dev;
+	dev->master.touch_bit	= &ds9490r_touch_bit;
+	dev->master.read_bit	= &ds9490r_read_bit;
+	dev->master.write_bit	= &ds9490r_write_bit;
+	dev->master.read_byte	= &ds9490r_read_byte;
+	dev->master.write_byte	= &ds9490r_write_byte;
+	dev->master.read_block	= &ds9490r_read_block;
+	dev->master.write_block	= &ds9490r_write_block;
+	dev->master.reset_bus	= &ds9490r_reset;
+
+	return w1_add_master_device(&dev->master);
+}
+
+static void ds_w1_fini(struct ds_device *dev)
+{
+	w1_remove_master_device(&dev->master);
+}
+
+static int ds_probe(struct usb_interface *intf,
+		    const struct usb_device_id *udev_id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct usb_endpoint_descriptor *endpoint;
+	struct usb_host_interface *iface_desc;
+	struct ds_device *dev;
+	int i, err;
+
+	dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
+	if (!dev) {
+		printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
+		return -ENOMEM;
+	}
+	dev->udev = usb_get_dev(udev);
+	if (!dev->udev) {
+		err = -ENOMEM;
+		goto err_out_free;
+	}
+	memset(dev->ep, 0, sizeof(dev->ep));
+
+	usb_set_intfdata(intf, dev);
+
+	err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
+	if (err) {
+		printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
+				intf->altsetting[0].desc.bInterfaceNumber, err);
+		goto err_out_clear;
+	}
+
+	err = usb_reset_configuration(dev->udev);
+	if (err) {
+		printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
+		goto err_out_clear;
+	}
+
+	iface_desc = &intf->altsetting[0];
+	if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
+		printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
+		err = -EINVAL;
+		goto err_out_clear;
+	}
+
+	/*
+	 * This loop doesn'd show control 0 endpoint,
+	 * so we will fill only 1-3 endpoints entry.
+	 */
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+
+		dev->ep[i+1] = endpoint->bEndpointAddress;
+#if 0
+		printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
+			i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
+			(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
+			endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+#endif
+	}
+
+	err = ds_w1_init(dev);
+	if (err)
+		goto err_out_clear;
+
+	mutex_lock(&ds_mutex);
+	list_add_tail(&dev->ds_entry, &ds_devices);
+	mutex_unlock(&ds_mutex);
+
+	return 0;
+
+err_out_clear:
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(dev->udev);
+err_out_free:
+	kfree(dev);
+	return err;
+}
+
+static void ds_disconnect(struct usb_interface *intf)
+{
+	struct ds_device *dev;
+
+	dev = usb_get_intfdata(intf);
+	if (!dev)
+		return;
+
+	mutex_lock(&ds_mutex);
+	list_del(&dev->ds_entry);
+	mutex_unlock(&ds_mutex);
+
+	ds_w1_fini(dev);
+
+	usb_set_intfdata(intf, NULL);
+
+	usb_put_dev(dev->udev);
+	kfree(dev);
+}
+
+static int ds_init(void)
+{
+	int err;
+
+	err = usb_register(&ds_driver);
+	if (err) {
+		printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void ds_fini(void)
+{
+	usb_deregister(&ds_driver);
+}
+
+module_init(ds_init);
+module_exit(ds_fini);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
+MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)");
diff --git a/drivers/w1/masters/ds_w1_bridge.c b/drivers/w1/masters/ds_w1_bridge.c
deleted file mode 100644
index 5d30783..0000000
--- a/drivers/w1/masters/ds_w1_bridge.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- *	ds_w1_bridge.c
- *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-
-#include "../w1.h"
-#include "../w1_int.h"
-#include "dscore.h"
-
-static struct ds_device *ds_dev;
-static struct w1_bus_master *ds_bus_master;
-
-static u8 ds9490r_touch_bit(void *data, u8 bit)
-{
-	u8 ret;
-	struct ds_device *dev = data;
-
-	if (ds_touch_bit(dev, bit, &ret))
-		return 0;
-
-	return ret;
-}
-
-static void ds9490r_write_bit(void *data, u8 bit)
-{
-	struct ds_device *dev = data;
-
-	ds_write_bit(dev, bit);
-}
-
-static void ds9490r_write_byte(void *data, u8 byte)
-{
-	struct ds_device *dev = data;
-
-	ds_write_byte(dev, byte);
-}
-
-static u8 ds9490r_read_bit(void *data)
-{
-	struct ds_device *dev = data;
-	int err;
-	u8 bit = 0;
-
-	err = ds_touch_bit(dev, 1, &bit);
-	if (err)
-		return 0;
-	//err = ds_read_bit(dev, &bit);
-	//if (err)
-	//	return 0;
-
-	return bit & 1;
-}
-
-static u8 ds9490r_read_byte(void *data)
-{
-	struct ds_device *dev = data;
-	int err;
-	u8 byte = 0;
-
-	err = ds_read_byte(dev, &byte);
-	if (err)
-		return 0;
-
-	return byte;
-}
-
-static void ds9490r_write_block(void *data, const u8 *buf, int len)
-{
-	struct ds_device *dev = data;
-
-	ds_write_block(dev, (u8 *)buf, len);
-}
-
-static u8 ds9490r_read_block(void *data, u8 *buf, int len)
-{
-	struct ds_device *dev = data;
-	int err;
-
-	err = ds_read_block(dev, buf, len);
-	if (err < 0)
-		return 0;
-
-	return len;
-}
-
-static u8 ds9490r_reset(void *data)
-{
-	struct ds_device *dev = data;
-	struct ds_status st;
-	int err;
-
-	memset(&st, 0, sizeof(st));
-
-	err = ds_reset(dev, &st);
-	if (err)
-		return 1;
-
-	return 0;
-}
-
-static int __devinit ds_w1_init(void)
-{
-	int err;
-
-	ds_bus_master = kmalloc(sizeof(*ds_bus_master), GFP_KERNEL);
-	if (!ds_bus_master) {
-		printk(KERN_ERR "Failed to allocate DS9490R USB<->W1 bus_master structure.\n");
-		return -ENOMEM;
-	}
-
-	ds_dev = ds_get_device();
-	if (!ds_dev) {
-		printk(KERN_ERR "DS9490R is not registered.\n");
-		err =  -ENODEV;
-		goto err_out_free_bus_master;
-	}
-
-	memset(ds_bus_master, 0, sizeof(*ds_bus_master));
-
-	ds_bus_master->data		= ds_dev;
-	ds_bus_master->touch_bit	= &ds9490r_touch_bit;
-	ds_bus_master->read_bit		= &ds9490r_read_bit;
-	ds_bus_master->write_bit	= &ds9490r_write_bit;
-	ds_bus_master->read_byte	= &ds9490r_read_byte;
-	ds_bus_master->write_byte	= &ds9490r_write_byte;
-	ds_bus_master->read_block	= &ds9490r_read_block;
-	ds_bus_master->write_block	= &ds9490r_write_block;
-	ds_bus_master->reset_bus	= &ds9490r_reset;
-
-	err = w1_add_master_device(ds_bus_master);
-	if (err)
-		goto err_out_put_device;
-
-	return 0;
-
-err_out_put_device:
-	ds_put_device(ds_dev);
-err_out_free_bus_master:
-	kfree(ds_bus_master);
-
-	return err;
-}
-
-static void __devexit ds_w1_fini(void)
-{
-	w1_remove_master_device(ds_bus_master);
-	ds_put_device(ds_dev);
-	kfree(ds_bus_master);
-}
-
-module_init(ds_w1_init);
-module_exit(ds_w1_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
diff --git a/drivers/w1/masters/dscore.c b/drivers/w1/masters/dscore.c
deleted file mode 100644
index 2cf7776..0000000
--- a/drivers/w1/masters/dscore.c
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- *	dscore.c
- *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
-#include <linux/usb.h>
-
-#include "dscore.h"
-
-static struct usb_device_id ds_id_table [] = {
-	{ USB_DEVICE(0x04fa, 0x2490) },
-	{ },
-};
-MODULE_DEVICE_TABLE(usb, ds_id_table);
-
-static int ds_probe(struct usb_interface *, const struct usb_device_id *);
-static void ds_disconnect(struct usb_interface *);
-
-int ds_touch_bit(struct ds_device *, u8, u8 *);
-int ds_read_byte(struct ds_device *, u8 *);
-int ds_read_bit(struct ds_device *, u8 *);
-int ds_write_byte(struct ds_device *, u8);
-int ds_write_bit(struct ds_device *, u8);
-static int ds_start_pulse(struct ds_device *, int);
-int ds_reset(struct ds_device *, struct ds_status *);
-struct ds_device * ds_get_device(void);
-void ds_put_device(struct ds_device *);
-
-static inline void ds_dump_status(unsigned char *, unsigned char *, int);
-static int ds_send_control(struct ds_device *, u16, u16);
-static int ds_send_control_mode(struct ds_device *, u16, u16);
-static int ds_send_control_cmd(struct ds_device *, u16, u16);
-
-
-static struct usb_driver ds_driver = {
-	.name =		"DS9490R",
-	.probe =	ds_probe,
-	.disconnect =	ds_disconnect,
-	.id_table =	ds_id_table,
-};
-
-static struct ds_device *ds_dev;
-
-struct ds_device * ds_get_device(void)
-{
-	if (ds_dev)
-		atomic_inc(&ds_dev->refcnt);
-	return ds_dev;
-}
-
-void ds_put_device(struct ds_device *dev)
-{
-	atomic_dec(&dev->refcnt);
-}
-
-static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index)
-{
-	int err;
-
-	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
-			CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
-	if (err < 0) {
-		printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n",
-				value, index, err);
-		return err;
-	}
-
-	return err;
-}
-
-static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index)
-{
-	int err;
-
-	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
-			MODE_CMD, 0x40, value, index, NULL, 0, 1000);
-	if (err < 0) {
-		printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n",
-				value, index, err);
-		return err;
-	}
-
-	return err;
-}
-
-static int ds_send_control(struct ds_device *dev, u16 value, u16 index)
-{
-	int err;
-
-	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]),
-			COMM_CMD, 0x40, value, index, NULL, 0, 1000);
-	if (err < 0) {
-		printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n",
-				value, index, err);
-		return err;
-	}
-
-	return err;
-}
-
-static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off)
-{
-	printk("%45s: %8x\n", str, buf[off]);
-}
-
-static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st,
-				 unsigned char *buf, int size)
-{
-	int count, err;
-
-	memset(st, 0, sizeof(st));
-
-	count = 0;
-	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100);
-	if (err < 0) {
-		printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err);
-		return err;
-	}
-
-	if (count >= sizeof(*st))
-		memcpy(st, buf, sizeof(*st));
-
-	return count;
-}
-
-static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
-{
-	unsigned char buf[64];
-	int count, err = 0, i;
-
-	memcpy(st, buf, sizeof(*st));
-
-	count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
-	if (count < 0)
-		return err;
-
-	printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count);
-	for (i=0; i<count; ++i)
-		printk("%02x ", buf[i]);
-	printk("\n");
-
-	if (count >= 16) {
-		ds_dump_status(buf, "enable flag", 0);
-		ds_dump_status(buf, "1-wire speed", 1);
-		ds_dump_status(buf, "strong pullup duration", 2);
-		ds_dump_status(buf, "programming pulse duration", 3);
-		ds_dump_status(buf, "pulldown slew rate control", 4);
-		ds_dump_status(buf, "write-1 low time", 5);
-		ds_dump_status(buf, "data sample offset/write-0 recovery time", 6);
-		ds_dump_status(buf, "reserved (test register)", 7);
-		ds_dump_status(buf, "device status flags", 8);
-		ds_dump_status(buf, "communication command byte 1", 9);
-		ds_dump_status(buf, "communication command byte 2", 10);
-		ds_dump_status(buf, "communication command buffer status", 11);
-		ds_dump_status(buf, "1-wire data output buffer status", 12);
-		ds_dump_status(buf, "1-wire data input buffer status", 13);
-		ds_dump_status(buf, "reserved", 14);
-		ds_dump_status(buf, "reserved", 15);
-	}
-
-	memcpy(st, buf, sizeof(*st));
-
-	if (st->status & ST_EPOF) {
-		printk(KERN_INFO "Resetting device after ST_EPOF.\n");
-		err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
-		if (err)
-			return err;
-		count = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
-		if (count < 0)
-			return err;
-	}
-#if 0
-	if (st->status & ST_IDLE) {
-		printk(KERN_INFO "Resetting pulse after ST_IDLE.\n");
-		err = ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-		if (err)
-			return err;
-	}
-#endif
-
-	return err;
-}
-
-static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
-{
-	int count, err;
-	struct ds_status st;
-
-	count = 0;
-	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]),
-				buf, size, &count, 1000);
-	if (err < 0) {
-		printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
-		usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
-		ds_recv_status(dev, &st);
-		return err;
-	}
-
-#if 0
-	{
-		int i;
-
-		printk("%s: count=%d: ", __func__, count);
-		for (i=0; i<count; ++i)
-			printk("%02x ", buf[i]);
-		printk("\n");
-	}
-#endif
-	return count;
-}
-
-static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
-{
-	int count, err;
-
-	count = 0;
-	err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
-	if (err < 0) {
-		printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
-		return err;
-	}
-
-	return err;
-}
-
-#if 0
-
-int ds_stop_pulse(struct ds_device *dev, int limit)
-{
-	struct ds_status st;
-	int count = 0, err = 0;
-	u8 buf[0x20];
-
-	do {
-		err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0);
-		if (err)
-			break;
-		err = ds_send_control(dev, CTL_RESUME_EXE, 0);
-		if (err)
-			break;
-		err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf));
-		if (err)
-			break;
-
-		if ((st.status & ST_SPUA) == 0) {
-			err = ds_send_control_mode(dev, MOD_PULSE_EN, 0);
-			if (err)
-				break;
-		}
-	} while(++count < limit);
-
-	return err;
-}
-
-int ds_detect(struct ds_device *dev, struct ds_status *st)
-{
-	int err;
-
-	err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0);
-	if (err)
-		return err;
-
-	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0);
-	if (err)
-		return err;
-
-	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40);
-	if (err)
-		return err;
-
-	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG);
-	if (err)
-		return err;
-
-	err = ds_recv_status(dev, st);
-
-	return err;
-}
-
-#endif  /*  0  */
-
-static int ds_wait_status(struct ds_device *dev, struct ds_status *st)
-{
-	u8 buf[0x20];
-	int err, count = 0;
-
-	do {
-		err = ds_recv_status_nodump(dev, st, buf, sizeof(buf));
-#if 0
-		if (err >= 0) {
-			int i;
-			printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err);
-			for (i=0; i<err; ++i)
-				printk("%02x ", buf[i]);
-			printk("\n");
-		}
-#endif
-	} while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100);
-
-
-	if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) {
-		ds_recv_status(dev, st);
-		return -1;
-	} else
-		return 0;
-}
-
-int ds_reset(struct ds_device *dev, struct ds_status *st)
-{
-	int err;
-
-	//err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE);
-	err = ds_send_control(dev, 0x43, SPEED_NORMAL);
-	if (err)
-		return err;
-
-	ds_wait_status(dev, st);
-#if 0
-	if (st->command_buffer_status) {
-		printk(KERN_INFO "Short circuit.\n");
-		return -EIO;
-	}
-#endif
-
-	return 0;
-}
-
-#if 0
-int ds_set_speed(struct ds_device *dev, int speed)
-{
-	int err;
-
-	if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE)
-		return -EINVAL;
-
-	if (speed != SPEED_OVERDRIVE)
-		speed = SPEED_FLEXIBLE;
-
-	speed &= 0xff;
-
-	err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed);
-	if (err)
-		return err;
-
-	return err;
-}
-#endif  /*  0  */
-
-static int ds_start_pulse(struct ds_device *dev, int delay)
-{
-	int err;
-	u8 del = 1 + (u8)(delay >> 4);
-	struct ds_status st;
-
-#if 0
-	err = ds_stop_pulse(dev, 10);
-	if (err)
-		return err;
-
-	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
-	if (err)
-		return err;
-#endif
-	err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del);
-	if (err)
-		return err;
-
-	err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0);
-	if (err)
-		return err;
-
-	mdelay(delay);
-
-	ds_wait_status(dev, &st);
-
-	return err;
-}
-
-int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit)
-{
-	int err, count;
-	struct ds_status st;
-	u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0);
-	u16 cmd;
-
-	err = ds_send_control(dev, value, 0);
-	if (err)
-		return err;
-
-	count = 0;
-	do {
-		err = ds_wait_status(dev, &st);
-		if (err)
-			return err;
-
-		cmd = st.command0 | (st.command1 << 8);
-	} while (cmd != value && ++count < 10);
-
-	if (err < 0 || count >= 10) {
-		printk(KERN_ERR "Failed to obtain status.\n");
-		return -EINVAL;
-	}
-
-	err = ds_recv_data(dev, tbit, sizeof(*tbit));
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-int ds_write_bit(struct ds_device *dev, u8 bit)
-{
-	int err;
-	struct ds_status st;
-
-	err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0);
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	return 0;
-}
-
-int ds_write_byte(struct ds_device *dev, u8 byte)
-{
-	int err;
-	struct ds_status st;
-	u8 rbyte;
-
-	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte);
-	if (err)
-		return err;
-
-	err = ds_wait_status(dev, &st);
-	if (err)
-		return err;
-
-	err = ds_recv_data(dev, &rbyte, sizeof(rbyte));
-	if (err < 0)
-		return err;
-
-	ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-
-	return !(byte == rbyte);
-}
-
-int ds_read_bit(struct ds_device *dev, u8 *bit)
-{
-	int err;
-
-	err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE);
-	if (err)
-		return err;
-
-	err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_SPU | COMM_D, 0);
-	if (err)
-		return err;
-
-	err = ds_recv_data(dev, bit, sizeof(*bit));
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-int ds_read_byte(struct ds_device *dev, u8 *byte)
-{
-	int err;
-	struct ds_status st;
-
-	err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff);
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	err = ds_recv_data(dev, byte, sizeof(*byte));
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-int ds_read_block(struct ds_device *dev, u8 *buf, int len)
-{
-	struct ds_status st;
-	int err;
-
-	if (len > 64*1024)
-		return -E2BIG;
-
-	memset(buf, 0xFF, len);
-
-	err = ds_send_data(dev, buf, len);
-	if (err < 0)
-		return err;
-
-	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	memset(buf, 0x00, len);
-	err = ds_recv_data(dev, buf, len);
-
-	return err;
-}
-
-int ds_write_block(struct ds_device *dev, u8 *buf, int len)
-{
-	int err;
-	struct ds_status st;
-
-	err = ds_send_data(dev, buf, len);
-	if (err < 0)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len);
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	err = ds_recv_data(dev, buf, len);
-	if (err < 0)
-		return err;
-
-	ds_start_pulse(dev, PULLUP_PULSE_DURATION);
-
-	return !(err == len);
-}
-
-#if 0
-
-int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search)
-{
-	int err;
-	u16 value, index;
-	struct ds_status st;
-
-	memset(buf, 0, sizeof(buf));
-
-	err = ds_send_data(ds_dev, (unsigned char *)&init, 8);
-	if (err)
-		return err;
-
-	ds_wait_status(ds_dev, &st);
-
-	value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS;
-	index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8);
-	err = ds_send_control(ds_dev, value, index);
-	if (err)
-		return err;
-
-	ds_wait_status(ds_dev, &st);
-
-	err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number);
-	if (err < 0)
-		return err;
-
-	return err/8;
-}
-
-int ds_match_access(struct ds_device *dev, u64 init)
-{
-	int err;
-	struct ds_status st;
-
-	err = ds_send_data(dev, (unsigned char *)&init, sizeof(init));
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055);
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	return 0;
-}
-
-int ds_set_path(struct ds_device *dev, u64 init)
-{
-	int err;
-	struct ds_status st;
-	u8 buf[9];
-
-	memcpy(buf, &init, 8);
-	buf[8] = BRANCH_MAIN;
-
-	err = ds_send_data(dev, buf, sizeof(buf));
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0);
-	if (err)
-		return err;
-
-	ds_wait_status(dev, &st);
-
-	return 0;
-}
-
-#endif  /*  0  */
-
-static int ds_probe(struct usb_interface *intf,
-		    const struct usb_device_id *udev_id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_endpoint_descriptor *endpoint;
-	struct usb_host_interface *iface_desc;
-	int i, err;
-
-	ds_dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL);
-	if (!ds_dev) {
-		printk(KERN_INFO "Failed to allocate new DS9490R structure.\n");
-		return -ENOMEM;
-	}
-
-	ds_dev->udev = usb_get_dev(udev);
-	usb_set_intfdata(intf, ds_dev);
-
-	err = usb_set_interface(ds_dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3);
-	if (err) {
-		printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n",
-				intf->altsetting[0].desc.bInterfaceNumber, err);
-		return err;
-	}
-
-	err = usb_reset_configuration(ds_dev->udev);
-	if (err) {
-		printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err);
-		return err;
-	}
-
-	iface_desc = &intf->altsetting[0];
-	if (iface_desc->desc.bNumEndpoints != NUM_EP-1) {
-		printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints);
-		return -ENODEV;
-	}
-
-	atomic_set(&ds_dev->refcnt, 0);
-	memset(ds_dev->ep, 0, sizeof(ds_dev->ep));
-
-	/*
-	 * This loop doesn'd show control 0 endpoint,
-	 * so we will fill only 1-3 endpoints entry.
-	 */
-	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
-		endpoint = &iface_desc->endpoint[i].desc;
-
-		ds_dev->ep[i+1] = endpoint->bEndpointAddress;
-
-		printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
-			i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
-			(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
-			endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
-	}
-
-#if 0
-	{
-		int err, i;
-		u64 buf[3];
-		u64 init=0xb30000002078ee81ull;
-		struct ds_status st;
-
-		ds_reset(ds_dev, &st);
-		err = ds_search(ds_dev, init, buf, 3, 0);
-		if (err < 0)
-			return err;
-		for (i=0; i<err; ++i)
-			printk("%d: %llx\n", i, buf[i]);
-
-		printk("Resetting...\n");
-		ds_reset(ds_dev, &st);
-		printk("Setting path for %llx.\n", init);
-		err = ds_set_path(ds_dev, init);
-		if (err)
-			return err;
-		printk("Calling MATCH_ACCESS.\n");
-		err = ds_match_access(ds_dev, init);
-		if (err)
-			return err;
-
-		printk("Searching the bus...\n");
-		err = ds_search(ds_dev, init, buf, 3, 0);
-
-		printk("ds_search() returned %d\n", err);
-
-		if (err < 0)
-			return err;
-		for (i=0; i<err; ++i)
-			printk("%d: %llx\n", i, buf[i]);
-
-		return 0;
-	}
-#endif
-
-	return 0;
-}
-
-static void ds_disconnect(struct usb_interface *intf)
-{
-	struct ds_device *dev;
-
-	dev = usb_get_intfdata(intf);
-	usb_set_intfdata(intf, NULL);
-
-	while (atomic_read(&dev->refcnt)) {
-		printk(KERN_INFO "Waiting for DS to become free: refcnt=%d.\n",
-				atomic_read(&dev->refcnt));
-
-		if (msleep_interruptible(1000))
-			flush_signals(current);
-	}
-
-	usb_put_dev(dev->udev);
-	kfree(dev);
-	ds_dev = NULL;
-}
-
-static int ds_init(void)
-{
-	int err;
-
-	err = usb_register(&ds_driver);
-	if (err) {
-		printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err);
-		return err;
-	}
-
-	return 0;
-}
-
-static void ds_fini(void)
-{
-	usb_deregister(&ds_driver);
-}
-
-module_init(ds_init);
-module_exit(ds_fini);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
-
-EXPORT_SYMBOL(ds_touch_bit);
-EXPORT_SYMBOL(ds_read_byte);
-EXPORT_SYMBOL(ds_read_bit);
-EXPORT_SYMBOL(ds_read_block);
-EXPORT_SYMBOL(ds_write_byte);
-EXPORT_SYMBOL(ds_write_bit);
-EXPORT_SYMBOL(ds_write_block);
-EXPORT_SYMBOL(ds_reset);
-EXPORT_SYMBOL(ds_get_device);
-EXPORT_SYMBOL(ds_put_device);
-
-/*
- * This functions can be used for EEPROM programming,
- * when driver will be included into mainline this will
- * require uncommenting.
- */
-#if 0
-EXPORT_SYMBOL(ds_start_pulse);
-EXPORT_SYMBOL(ds_set_speed);
-EXPORT_SYMBOL(ds_detect);
-EXPORT_SYMBOL(ds_stop_pulse);
-EXPORT_SYMBOL(ds_search);
-#endif
diff --git a/drivers/w1/masters/dscore.h b/drivers/w1/masters/dscore.h
deleted file mode 100644
index 6cf5671..0000000
--- a/drivers/w1/masters/dscore.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- *	dscore.h
- *
- * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __DSCORE_H
-#define __DSCORE_H
-
-#include <linux/usb.h>
-#include <asm/atomic.h>
-
-/* COMMAND TYPE CODES */
-#define CONTROL_CMD			0x00
-#define COMM_CMD			0x01
-#define MODE_CMD			0x02
-
-/* CONTROL COMMAND CODES */
-#define CTL_RESET_DEVICE		0x0000
-#define CTL_START_EXE			0x0001
-#define CTL_RESUME_EXE			0x0002
-#define CTL_HALT_EXE_IDLE		0x0003
-#define CTL_HALT_EXE_DONE		0x0004
-#define CTL_FLUSH_COMM_CMDS		0x0007
-#define CTL_FLUSH_RCV_BUFFER		0x0008
-#define CTL_FLUSH_XMT_BUFFER		0x0009
-#define CTL_GET_COMM_CMDS		0x000A
-
-/* MODE COMMAND CODES */
-#define MOD_PULSE_EN			0x0000
-#define MOD_SPEED_CHANGE_EN		0x0001
-#define MOD_1WIRE_SPEED			0x0002
-#define MOD_STRONG_PU_DURATION		0x0003
-#define MOD_PULLDOWN_SLEWRATE		0x0004
-#define MOD_PROG_PULSE_DURATION		0x0005
-#define MOD_WRITE1_LOWTIME		0x0006
-#define MOD_DSOW0_TREC			0x0007
-
-/* COMMUNICATION COMMAND CODES */
-#define COMM_ERROR_ESCAPE		0x0601
-#define COMM_SET_DURATION		0x0012
-#define COMM_BIT_IO			0x0020
-#define COMM_PULSE			0x0030
-#define COMM_1_WIRE_RESET		0x0042
-#define COMM_BYTE_IO			0x0052
-#define COMM_MATCH_ACCESS		0x0064
-#define COMM_BLOCK_IO			0x0074
-#define COMM_READ_STRAIGHT		0x0080
-#define COMM_DO_RELEASE			0x6092
-#define COMM_SET_PATH			0x00A2
-#define COMM_WRITE_SRAM_PAGE		0x00B2
-#define COMM_WRITE_EPROM		0x00C4
-#define COMM_READ_CRC_PROT_PAGE		0x00D4
-#define COMM_READ_REDIRECT_PAGE_CRC	0x21E4
-#define COMM_SEARCH_ACCESS		0x00F4
-
-/* Communication command bits */
-#define COMM_TYPE			0x0008
-#define COMM_SE				0x0008
-#define COMM_D				0x0008
-#define COMM_Z				0x0008
-#define COMM_CH				0x0008
-#define COMM_SM				0x0008
-#define COMM_R				0x0008
-#define COMM_IM				0x0001
-
-#define COMM_PS				0x4000
-#define COMM_PST			0x4000
-#define COMM_CIB			0x4000
-#define COMM_RTS			0x4000
-#define COMM_DT				0x2000
-#define COMM_SPU			0x1000
-#define COMM_F				0x0800
-#define COMM_NTP			0x0400
-#define COMM_ICP			0x0200
-#define COMM_RST			0x0100
-
-#define PULSE_PROG			0x01
-#define PULSE_SPUE			0x02
-
-#define BRANCH_MAIN			0xCC
-#define BRANCH_AUX			0x33
-
-/*
- * Duration of the strong pull-up pulse in milliseconds.
- */
-#define PULLUP_PULSE_DURATION		750
-
-/* Status flags */
-#define ST_SPUA				0x01  /* Strong Pull-up is active */
-#define ST_PRGA				0x02  /* 12V programming pulse is being generated */
-#define ST_12VP				0x04  /* external 12V programming voltage is present */
-#define ST_PMOD				0x08  /* DS2490 powered from USB and external sources */
-#define ST_HALT				0x10  /* DS2490 is currently halted */
-#define ST_IDLE				0x20  /* DS2490 is currently idle */
-#define ST_EPOF				0x80
-
-#define SPEED_NORMAL			0x00
-#define SPEED_FLEXIBLE			0x01
-#define SPEED_OVERDRIVE			0x02
-
-#define NUM_EP				4
-#define EP_CONTROL			0
-#define EP_STATUS			1
-#define EP_DATA_OUT			2
-#define EP_DATA_IN			3
-
-struct ds_device
-{
-	struct usb_device	*udev;
-	struct usb_interface	*intf;
-
-	int			ep[NUM_EP];
-
-	atomic_t		refcnt;
-};
-
-struct ds_status
-{
-	u8			enable;
-	u8			speed;
-	u8			pullup_dur;
-	u8			ppuls_dur;
-	u8			pulldown_slew;
-	u8			write1_time;
-	u8			write0_time;
-	u8			reserved0;
-	u8			status;
-	u8			command0;
-	u8			command1;
-	u8			command_buffer_status;
-	u8			data_out_buffer_status;
-	u8			data_in_buffer_status;
-	u8			reserved1;
-	u8			reserved2;
-
-};
-
-int ds_touch_bit(struct ds_device *, u8, u8 *);
-int ds_read_byte(struct ds_device *, u8 *);
-int ds_read_bit(struct ds_device *, u8 *);
-int ds_write_byte(struct ds_device *, u8);
-int ds_write_bit(struct ds_device *, u8);
-int ds_reset(struct ds_device *, struct ds_status *);
-struct ds_device * ds_get_device(void);
-void ds_put_device(struct ds_device *);
-int ds_write_block(struct ds_device *, u8 *, int);
-int ds_read_block(struct ds_device *, u8 *, int);
-
-#endif /* __DSCORE_H */
-
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index f9d4c91..d18d642 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -28,7 +28,7 @@
 
 config W1_SLAVE_DS2433_CRC
 	bool "Protect DS2433 data with a CRC16"
-	depends on W1_DS2433
+	depends on W1_SLAVE_DS2433
 	select CRC16
 	help
 	  Say Y here to protect DS2433 data with a CRC16.
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index fb118be..2ac238f 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -22,7 +22,6 @@
 #endif
 
 #include "../w1.h"
-#include "../w1_io.h"
 #include "../w1_int.h"
 #include "../w1_family.h"
 
@@ -106,11 +105,7 @@
 	if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
 		return 0;
 
-	atomic_inc(&sl->refcnt);
-	if (down_interruptible(&sl->master->mutex)) {
-		count = 0;
-		goto out_dec;
-	}
+	mutex_lock(&sl->master->mutex);
 
 #ifdef CONFIG_W1_F23_CRC
 
@@ -141,9 +136,7 @@
 #endif	/* CONFIG_W1_F23_CRC */
 
 out_up:
-	up(&sl->master->mutex);
-out_dec:
-	atomic_dec(&sl->refcnt);
+	mutex_unlock(&sl->master->mutex);
 
 	return count;
 }
@@ -232,11 +225,7 @@
 	}
 #endif	/* CONFIG_W1_F23_CRC */
 
-	atomic_inc(&sl->refcnt);
-	if (down_interruptible(&sl->master->mutex)) {
-		count = 0;
-		goto out_dec;
-	}
+	mutex_lock(&sl->master->mutex);
 
 	/* Can only write data to one page at a time */
 	idx = 0;
@@ -254,9 +243,7 @@
 	}
 
 out_up:
-	up(&sl->master->mutex);
-out_dec:
-	atomic_dec(&sl->refcnt);
+	mutex_unlock(&sl->master->mutex);
 
 	return count;
 }
diff --git a/drivers/w1/slaves/w1_smem.c b/drivers/w1/slaves/w1_smem.c
index c6d3be5..cc8c02e 100644
--- a/drivers/w1/slaves/w1_smem.c
+++ b/drivers/w1/slaves/w1_smem.c
@@ -28,7 +28,6 @@
 #include <linux/types.h>
 
 #include "../w1.h"
-#include "../w1_io.h"
 #include "../w1_int.h"
 #include "../w1_family.h"
 
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 536d16d..5372cfc 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -29,7 +29,6 @@
 #include <linux/delay.h>
 
 #include "../w1.h"
-#include "../w1_io.h"
 #include "../w1_int.h"
 #include "../w1_family.h"
 
@@ -166,12 +165,7 @@
 	u8 rom[9], crc, verdict;
 	int i, max_trying = 10;
 
-	atomic_inc(&sl->refcnt);
-	smp_mb__after_atomic_inc();
-	if (down_interruptible(&sl->master->mutex)) {
-		count = 0;
-		goto out_dec;
-	}
+	mutex_lock(&sl->master->mutex);
 
 	if (off > W1_SLAVE_DATA_SIZE) {
 		count = 0;
@@ -234,10 +228,7 @@
 
 	count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
 out:
-	up(&dev->mutex);
-out_dec:
-	smp_mb__before_atomic_inc();
-	atomic_dec(&sl->refcnt);
+	mutex_unlock(&dev->mutex);
 
 	return count;
 }
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index a698b51..de3e979 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -35,7 +35,6 @@
 #include <asm/atomic.h>
 
 #include "w1.h"
-#include "w1_io.h"
 #include "w1_log.h"
 #include "w1_int.h"
 #include "w1_family.h"
@@ -55,7 +54,7 @@
 module_param_named(max_slave_count, w1_max_slave_count, int, 0);
 module_param_named(slave_ttl, w1_max_slave_ttl, int, 0);
 
-DEFINE_SPINLOCK(w1_mlock);
+DEFINE_MUTEX(w1_mlock);
 LIST_HEAD(w1_masters);
 
 static struct task_struct *w1_control_thread;
@@ -75,8 +74,6 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 
 	dev_dbg(dev, "%s: Releasing %s.\n", __func__, md->name);
-
-	dev_fini_netlink(md);
 	memset(md, 0, sizeof(struct w1_master) + sizeof(struct w1_bus_master));
 	kfree(md);
 }
@@ -85,10 +82,10 @@
 {
 	struct w1_slave *sl = dev_to_w1_slave(dev);
 
-	dev_dbg(dev, "%s: Releasing %s.\n", __func__, sl->name);
+	printk("%s: Releasing %s.\n", __func__, sl->name);
 
 	while (atomic_read(&sl->refcnt)) {
-		dev_dbg(dev, "Waiting for %s to become free: refcnt=%d.\n",
+		printk("Waiting for %s to become free: refcnt=%d.\n",
 				sl->name, atomic_read(&sl->refcnt));
 		if (msleep_interruptible(1000))
 			flush_signals(current);
@@ -111,7 +108,6 @@
 {
 	struct w1_slave *sl = kobj_to_w1_slave(kobj);
 
-	atomic_inc(&sl->refcnt);
 	if (off > 8) {
 		count = 0;
 	} else {
@@ -120,7 +116,6 @@
 
 		memcpy(buf, (u8 *)&sl->reg_num, count);
 	}
-	atomic_dec(&sl->refcnt);
 
 	return count;
 }
@@ -139,7 +134,63 @@
 };
 
 /* Default family */
-static struct w1_family w1_default_family;
+
+static ssize_t w1_default_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct w1_slave *sl = kobj_to_w1_slave(kobj);
+
+	mutex_lock(&sl->master->mutex);
+	if (w1_reset_select_slave(sl)) {
+		count = 0;
+		goto out_up;
+	}
+
+	w1_write_block(sl->master, buf, count);
+
+out_up:
+	mutex_unlock(&sl->master->mutex);
+	return count;
+}
+
+static ssize_t w1_default_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	struct w1_slave *sl = kobj_to_w1_slave(kobj);
+
+	mutex_lock(&sl->master->mutex);
+	w1_read_block(sl->master, buf, count);
+	mutex_unlock(&sl->master->mutex);
+	return count;
+}
+
+static struct bin_attribute w1_default_attr = {
+      .attr = {
+              .name = "rw",
+              .mode = S_IRUGO | S_IWUSR,
+              .owner = THIS_MODULE,
+      },
+      .size = PAGE_SIZE,
+      .read = w1_default_read,
+      .write = w1_default_write,
+};
+
+static int w1_default_add_slave(struct w1_slave *sl)
+{
+	return sysfs_create_bin_file(&sl->dev.kobj, &w1_default_attr);
+}
+
+static void w1_default_remove_slave(struct w1_slave *sl)
+{
+	sysfs_remove_bin_file(&sl->dev.kobj, &w1_default_attr);
+}
+
+static struct w1_family_ops w1_default_fops = {
+	.add_slave	= w1_default_add_slave,
+	.remove_slave	= w1_default_remove_slave,
+};
+
+static struct w1_family w1_default_family = {
+	.fops = &w1_default_fops,
+};
 
 static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
 
@@ -183,12 +234,9 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 	ssize_t count;
 
-	if (down_interruptible (&md->mutex))
-		return -EBUSY;
-
+	mutex_lock(&md->mutex);
 	count = sprintf(buf, "%s\n", md->name);
-
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 
 	return count;
 }
@@ -199,12 +247,9 @@
 {
 	struct w1_master *md = dev_to_w1_master(dev);
 
-	if (down_interruptible (&md->mutex))
-		return -EBUSY;
-
+	mutex_lock(&md->mutex);
 	md->search_count = simple_strtol(buf, NULL, 0);
-
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 
 	return count;
 }
@@ -216,12 +261,9 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 	ssize_t count;
 
-	if (down_interruptible (&md->mutex))
-		return -EBUSY;
-
+	mutex_lock(&md->mutex);
 	count = sprintf(buf, "%d\n", md->search_count);
-
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 
 	return count;
 }
@@ -231,12 +273,9 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 	ssize_t count;
 
-	if (down_interruptible(&md->mutex))
-		return -EBUSY;
-
+	mutex_lock(&md->mutex);
 	count = sprintf(buf, "0x%p\n", md->bus_master);
-
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 	return count;
 }
 
@@ -252,12 +291,9 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 	ssize_t count;
 
-	if (down_interruptible(&md->mutex))
-		return -EBUSY;
-
+	mutex_lock(&md->mutex);
 	count = sprintf(buf, "%d\n", md->max_slave_count);
-
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 	return count;
 }
 
@@ -266,12 +302,9 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 	ssize_t count;
 
-	if (down_interruptible(&md->mutex))
-		return -EBUSY;
-
+	mutex_lock(&md->mutex);
 	count = sprintf(buf, "%lu\n", md->attempts);
-
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 	return count;
 }
 
@@ -280,12 +313,9 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 	ssize_t count;
 
-	if (down_interruptible(&md->mutex))
-		return -EBUSY;
-
+	mutex_lock(&md->mutex);
 	count = sprintf(buf, "%d\n", md->slave_count);
-
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 	return count;
 }
 
@@ -294,8 +324,7 @@
 	struct w1_master *md = dev_to_w1_master(dev);
 	int c = PAGE_SIZE;
 
-	if (down_interruptible(&md->mutex))
-		return -EBUSY;
+	mutex_lock(&md->mutex);
 
 	if (md->slave_count == 0)
 		c -= snprintf(buf + PAGE_SIZE - c, c, "not found.\n");
@@ -310,7 +339,7 @@
 		}
 	}
 
-	up(&md->mutex);
+	mutex_unlock(&md->mutex);
 
 	return PAGE_SIZE - c;
 }
@@ -362,7 +391,8 @@
 }
 
 #ifdef CONFIG_HOTPLUG
-static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int w1_uevent(struct device *dev, char **envp, int num_envp,
+			char *buffer, int buffer_size)
 {
 	struct w1_master *md = NULL;
 	struct w1_slave *sl = NULL;
@@ -382,7 +412,8 @@
 		return -EINVAL;
 	}
 
-	dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n", event_owner, name, dev->bus_id);
+	dev_dbg(dev, "Hotplug event for %s %s, bus_id=%s.\n",
+			event_owner, name, dev->bus_id);
 
 	if (dev->driver != &w1_slave_driver || !sl)
 		return 0;
@@ -401,7 +432,8 @@
 	return 0;
 };
 #else
-static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+static int w1_uevent(struct device *dev, char **envp, int num_envp,
+			char *buffer, int buffer_size)
 {
 	return 0;
 }
@@ -425,7 +457,8 @@
 		 (unsigned int) sl->reg_num.family,
 		 (unsigned long long) sl->reg_num.id);
 
-	dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, &sl->dev.bus_id[0]);
+	dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__,
+		&sl->dev.bus_id[0]);
 
 	err = device_register(&sl->dev);
 	if (err < 0) {
@@ -496,6 +529,7 @@
 	sl->master = dev;
 	set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 
+	memset(&msg, 0, sizeof(msg));
 	memcpy(&sl->reg_num, rn, sizeof(sl->reg_num));
 	atomic_set(&sl->refcnt, 0);
 	init_completion(&sl->released);
@@ -526,7 +560,7 @@
 	sl->ttl = dev->slave_ttl;
 	dev->slave_count++;
 
-	memcpy(&msg.id.id, rn, sizeof(msg.id.id));
+	memcpy(msg.id.id, rn, sizeof(msg.id));
 	msg.type = W1_SLAVE_ADD;
 	w1_netlink_send(dev, &msg);
 
@@ -544,7 +578,8 @@
 	if (sl->family->fops && sl->family->fops->remove_slave)
 		sl->family->fops->remove_slave(sl);
 
-	memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
+	memset(&msg, 0, sizeof(msg));
+	memcpy(msg.id.id, &sl->reg_num, sizeof(msg.id));
 	msg.type = W1_SLAVE_REMOVE;
 	w1_netlink_send(sl->master, &msg);
 
@@ -561,7 +596,7 @@
 	struct w1_master *dev;
 	int found = 0;
 
-	spin_lock_bh(&w1_mlock);
+	mutex_lock(&w1_mlock);
 	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
 		if (dev->bus_master->data == data) {
 			found = 1;
@@ -569,22 +604,69 @@
 			break;
 		}
 	}
-	spin_unlock_bh(&w1_mlock);
+	mutex_unlock(&w1_mlock);
 
 	return (found)?dev:NULL;
 }
 
+struct w1_master *w1_search_master_id(u32 id)
+{
+	struct w1_master *dev;
+	int found = 0;
+
+	mutex_lock(&w1_mlock);
+	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+		if (dev->id == id) {
+			found = 1;
+			atomic_inc(&dev->refcnt);
+			break;
+		}
+	}
+	mutex_unlock(&w1_mlock);
+
+	return (found)?dev:NULL;
+}
+
+struct w1_slave *w1_search_slave(struct w1_reg_num *id)
+{
+	struct w1_master *dev;
+	struct w1_slave *sl = NULL;
+	int found = 0;
+
+	mutex_lock(&w1_mlock);
+	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+		mutex_lock(&dev->mutex);
+		list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+			if (sl->reg_num.family == id->family &&
+					sl->reg_num.id == id->id &&
+					sl->reg_num.crc == id->crc) {
+				found = 1;
+				atomic_inc(&dev->refcnt);
+				atomic_inc(&sl->refcnt);
+				break;
+			}
+		}
+		mutex_unlock(&dev->mutex);
+
+		if (found)
+			break;
+	}
+	mutex_unlock(&w1_mlock);
+
+	return (found)?sl:NULL;
+}
+
 void w1_reconnect_slaves(struct w1_family *f)
 {
 	struct w1_master *dev;
 
-	spin_lock_bh(&w1_mlock);
+	mutex_lock(&w1_mlock);
 	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
 		dev_dbg(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
 				dev->name, f->fid);
 		set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
 	}
-	spin_unlock_bh(&w1_mlock);
+	mutex_unlock(&w1_mlock);
 }
 
 static void w1_slave_found(void *data, u64 rn)
@@ -646,7 +728,7 @@
  * @dev        The master device to search
  * @cb         Function to call when a device is found
  */
-void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
+void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
 {
 	u64 last_rn, rn, tmp64;
 	int i, slave_count = 0;
@@ -677,7 +759,7 @@
 		}
 
 		/* Start the search */
-		w1_write_8(dev, W1_SEARCH);
+		w1_write_8(dev, search_type);
 		for (i = 0; i < 64; ++i) {
 			/* Determine the direction/search bit */
 			if (i == desc_bit)
@@ -739,23 +821,23 @@
 			if (kthread_should_stop() || test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
 				set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
 
-				spin_lock(&w1_mlock);
+				mutex_lock(&w1_mlock);
 				list_del(&dev->w1_master_entry);
-				spin_unlock(&w1_mlock);
+				mutex_unlock(&w1_mlock);
 
-				down(&dev->mutex);
+				mutex_lock(&dev->mutex);
 				list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
 					w1_slave_detach(sl);
 				}
 				w1_destroy_master_attributes(dev);
-				up(&dev->mutex);
+				mutex_unlock(&dev->mutex);
 				atomic_dec(&dev->refcnt);
 				continue;
 			}
 
 			if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
 				dev_dbg(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
-				down(&dev->mutex);
+				mutex_lock(&dev->mutex);
 				list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
 					if (sl->family->fid == W1_FAMILY_DEFAULT) {
 						struct w1_reg_num rn;
@@ -768,7 +850,7 @@
 				}
 				dev_dbg(&dev->dev, "Reconnecting slaves in device %s has been finished.\n", dev->name);
 				clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
-				up(&dev->mutex);
+				mutex_unlock(&dev->mutex);
 			}
 		}
 	}
@@ -776,10 +858,31 @@
 	return 0;
 }
 
+void w1_search_process(struct w1_master *dev, u8 search_type)
+{
+	struct w1_slave *sl, *sln;
+
+	list_for_each_entry(sl, &dev->slist, w1_slave_entry)
+		clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
+
+	w1_search_devices(dev, search_type, w1_slave_found);
+
+	list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+		if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
+			w1_slave_detach(sl);
+
+			dev->slave_count--;
+		} else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
+			sl->ttl = dev->slave_ttl;
+	}
+
+	if (dev->search_count > 0)
+		dev->search_count--;
+}
+
 int w1_process(void *data)
 {
 	struct w1_master *dev = (struct w1_master *) data;
-	struct w1_slave *sl, *sln;
 
 	while (!kthread_should_stop() && !test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
 		try_to_freeze();
@@ -794,27 +897,9 @@
 		if (dev->search_count == 0)
 			continue;
 
-		if (down_interruptible(&dev->mutex))
-			continue;
-
-		list_for_each_entry(sl, &dev->slist, w1_slave_entry)
-			clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
-
-		w1_search_devices(dev, w1_slave_found);
-
-		list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
-			if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
-				w1_slave_detach(sl);
-
-				dev->slave_count--;
-			} else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
-				sl->ttl = dev->slave_ttl;
-		}
-
-		if (dev->search_count > 0)
-			dev->search_count--;
-
-		up(&dev->mutex);
+		mutex_lock(&dev->mutex);
+		w1_search_process(dev, W1_SEARCH);
+		mutex_unlock(&dev->mutex);
 	}
 
 	atomic_dec(&dev->refcnt);
@@ -828,6 +913,8 @@
 
 	printk(KERN_INFO "Driver for 1-wire Dallas network protocol.\n");
 
+	w1_init_netlink();
+
 	retval = bus_register(&w1_bus_type);
 	if (retval) {
 		printk(KERN_ERR "Failed to register bus. err=%d.\n", retval);
@@ -880,6 +967,8 @@
 	list_for_each_entry(dev, &w1_masters, w1_master_entry)
 		__w1_remove_master_device(dev);
 
+	w1_fini_netlink();
+
 	kthread_stop(w1_control_thread);
 
 	driver_unregister(&w1_slave_driver);
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index 5698050..f1df534 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -41,10 +41,7 @@
 
 #include <linux/completion.h>
 #include <linux/device.h>
-
-#include <net/sock.h>
-
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 #include "w1_family.h"
 
@@ -52,7 +49,7 @@
 #define W1_SLAVE_DATA_SIZE	128
 
 #define W1_SEARCH		0xF0
-#define W1_CONDITIONAL_SEARCH	0xEC
+#define W1_ALARM_SEARCH		0xEC
 #define W1_CONVERT_TEMP		0x44
 #define W1_SKIP_ROM		0xCC
 #define W1_READ_SCRATCHPAD	0xBE
@@ -60,7 +57,7 @@
 #define W1_READ_PSUPPLY		0xB4
 #define W1_MATCH_ROM		0x55
 
-#define W1_SLAVE_ACTIVE		(1<<0)
+#define W1_SLAVE_ACTIVE		0
 
 struct w1_slave
 {
@@ -145,8 +142,8 @@
 	 */
 	u8		(*reset_bus)(void *);
 
-	/** Really nice hardware can handles the ROM searches */
-	void		(*search)(void *, w1_slave_found_callback);
+	/** Really nice hardware can handles the different types of ROM search */
+	void		(*search)(void *, u8, w1_slave_found_callback);
 };
 
 #define W1_MASTER_NEED_EXIT		0
@@ -173,19 +170,30 @@
 	long			flags;
 
 	struct task_struct	*thread;
-	struct semaphore	mutex;
+	struct mutex		mutex;
 
 	struct device_driver	*driver;
 	struct device		dev;
 
 	struct w1_bus_master	*bus_master;
 
-	u32			seq, groups;
-	struct sock		*nls;
+	u32			seq;
 };
 
 int w1_create_master_attributes(struct w1_master *);
-void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
+void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
+void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb);
+struct w1_slave *w1_search_slave(struct w1_reg_num *id);
+void w1_search_process(struct w1_master *dev, u8 search_type);
+struct w1_master *w1_search_master_id(u32 id);
+
+u8 w1_triplet(struct w1_master *dev, int bdir);
+void w1_write_8(struct w1_master *, u8);
+int w1_reset_bus(struct w1_master *);
+u8 w1_calc_crc8(u8 *, int);
+void w1_write_block(struct w1_master *, const u8 *, int);
+u8 w1_read_block(struct w1_master *, u8 *, int);
+int w1_reset_select_slave(struct w1_slave *sl);
 
 static inline struct w1_slave* dev_to_w1_slave(struct device *dev)
 {
@@ -202,15 +210,14 @@
 	return container_of(dev, struct w1_master, dev);
 }
 
-extern int w1_max_slave_count;
-extern int w1_max_slave_ttl;
-extern spinlock_t w1_mlock;
-extern struct list_head w1_masters;
 extern struct device_driver w1_master_driver;
 extern struct device w1_master_device;
+extern int w1_max_slave_count;
+extern int w1_max_slave_ttl;
+extern struct list_head w1_masters;
+extern struct mutex w1_mlock;
 
-int w1_process(void *data);
-void w1_reconnect_slaves(struct w1_family *f);
+extern int w1_process(void *);
 
 #endif /* __KERNEL__ */
 
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index 0e32c11..a3c95bd 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -107,6 +107,12 @@
 	return (ret) ? f : NULL;
 }
 
+static void __w1_family_put(struct w1_family *f)
+{
+	if (atomic_dec_and_test(&f->refcnt))
+		f->need_exit = 1;
+}
+
 void w1_family_put(struct w1_family *f)
 {
 	spin_lock(&w1_flock);
@@ -114,19 +120,14 @@
 	spin_unlock(&w1_flock);
 }
 
-void __w1_family_put(struct w1_family *f)
-{
-	if (atomic_dec_and_test(&f->refcnt))
-		f->need_exit = 1;
-}
-
+#if 0
 void w1_family_get(struct w1_family *f)
 {
 	spin_lock(&w1_flock);
 	__w1_family_get(f);
 	spin_unlock(&w1_flock);
-
 }
+#endif  /*  0  */
 
 void __w1_family_get(struct w1_family *f)
 {
@@ -135,8 +136,5 @@
 	smp_mb__after_atomic_inc();
 }
 
-EXPORT_SYMBOL(w1_family_get);
-EXPORT_SYMBOL(w1_family_put);
-EXPORT_SYMBOL(w1_family_registered);
 EXPORT_SYMBOL(w1_unregister_family);
 EXPORT_SYMBOL(w1_register_family);
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 2ca0489..1e2ac40 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -57,12 +57,11 @@
 
 extern spinlock_t w1_flock;
 
-void w1_family_get(struct w1_family *);
 void w1_family_put(struct w1_family *);
 void __w1_family_get(struct w1_family *);
-void __w1_family_put(struct w1_family *);
 struct w1_family * w1_family_registered(u8);
 void w1_unregister_family(struct w1_family *);
 int w1_register_family(struct w1_family *);
+void w1_reconnect_slaves(struct w1_family *f);
 
 #endif /* __W1_FAMILY_H */
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 68565aa..357a2e0 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -65,7 +65,7 @@
 	atomic_set(&dev->refcnt, 2);
 
 	INIT_LIST_HEAD(&dev->slist);
-	init_MUTEX(&dev->mutex);
+	mutex_init(&dev->mutex);
 
 	memcpy(&dev->dev, device, sizeof(struct device));
 	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
@@ -74,16 +74,11 @@
 
 	dev->driver = driver;
 
-	dev->groups = 1;
 	dev->seq = 1;
-	dev_init_netlink(dev);
 
 	err = device_register(&dev->dev);
 	if (err) {
 		printk(KERN_ERR "Failed to register master device. err=%d\n", err);
-
-		dev_fini_netlink(dev);
-
 		memset(dev, 0, sizeof(struct w1_master));
 		kfree(dev);
 		dev = NULL;
@@ -131,12 +126,12 @@
 
 	dev->initialized = 1;
 
-	spin_lock(&w1_mlock);
+	mutex_lock(&w1_mlock);
 	list_add(&dev->w1_master_entry, &w1_masters);
-	spin_unlock(&w1_mlock);
+	mutex_unlock(&w1_mlock);
 
+	memset(&msg, 0, sizeof(msg));
 	msg.id.mst.id = dev->id;
-	msg.id.mst.pid = dev->thread->pid;
 	msg.type = W1_MASTER_ADD;
 	w1_netlink_send(dev, &msg);
 
@@ -153,7 +148,6 @@
 void __w1_remove_master_device(struct w1_master *dev)
 {
 	struct w1_netlink_msg msg;
-	pid_t pid = dev->thread->pid;
 
 	set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
 	kthread_stop(dev->thread);
@@ -166,8 +160,8 @@
 			flush_signals(current);
 	}
 
+	memset(&msg, 0, sizeof(msg));
 	msg.id.mst.id = dev->id;
-	msg.id.mst.pid = pid;
 	msg.type = W1_MASTER_REMOVE;
 	w1_netlink_send(dev, &msg);
 
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index f7f7e8b..30b6fbf 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -23,10 +23,10 @@
 
 #include <linux/delay.h>
 #include <linux/moduleparam.h>
+#include <linux/module.h>
 
 #include "w1.h"
 #include "w1_log.h"
-#include "w1_io.h"
 
 static int w1_delay_parm = 1;
 module_param_named(delay_coef, w1_delay_parm, int, 0);
@@ -50,7 +50,7 @@
 	116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53
 };
 
-void w1_delay(unsigned long tm)
+static void w1_delay(unsigned long tm)
 {
 	udelay(tm * w1_delay_parm);
 }
@@ -61,7 +61,7 @@
 /**
  * Generates a write-0 or write-1 cycle and samples the level.
  */
-u8 w1_touch_bit(struct w1_master *dev, int bit)
+static u8 w1_touch_bit(struct w1_master *dev, int bit)
 {
 	if (dev->bus_master->touch_bit)
 		return dev->bus_master->touch_bit(dev->bus_master->data, bit);
@@ -108,6 +108,7 @@
 		for (i = 0; i < 8; ++i)
 			w1_touch_bit(dev, (byte >> i) & 0x1);
 }
+EXPORT_SYMBOL_GPL(w1_write_8);
 
 
 /**
@@ -176,7 +177,7 @@
  * @param dev     the master device
  * @return        the byte read
  */
-u8 w1_read_8(struct w1_master * dev)
+static u8 w1_read_8(struct w1_master * dev)
 {
 	int i;
 	u8 res = 0;
@@ -208,6 +209,7 @@
 		for (i = 0; i < len; ++i)
 			w1_write_8(dev, buf[i]);
 }
+EXPORT_SYMBOL_GPL(w1_write_block);
 
 /**
  * Reads a series of bytes.
@@ -232,6 +234,7 @@
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(w1_read_block);
 
 /**
  * Issues a reset bus sequence.
@@ -257,6 +260,7 @@
 
 	return result;
 }
+EXPORT_SYMBOL_GPL(w1_reset_bus);
 
 u8 w1_calc_crc8(u8 * data, int len)
 {
@@ -267,14 +271,15 @@
 
 	return crc;
 }
+EXPORT_SYMBOL_GPL(w1_calc_crc8);
 
-void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
+void w1_search_devices(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb)
 {
 	dev->attempts++;
 	if (dev->bus_master->search)
-		dev->bus_master->search(dev->bus_master->data, cb);
+		dev->bus_master->search(dev->bus_master->data, search_type, cb);
 	else
-		w1_search(dev, cb);
+		w1_search(dev, search_type, cb);
 }
 
 /**
@@ -299,14 +304,4 @@
 	}
 	return 0;
 }
-
-EXPORT_SYMBOL(w1_touch_bit);
-EXPORT_SYMBOL(w1_write_8);
-EXPORT_SYMBOL(w1_read_8);
-EXPORT_SYMBOL(w1_reset_bus);
-EXPORT_SYMBOL(w1_calc_crc8);
-EXPORT_SYMBOL(w1_delay);
-EXPORT_SYMBOL(w1_read_block);
-EXPORT_SYMBOL(w1_write_block);
-EXPORT_SYMBOL(w1_search_devices);
-EXPORT_SYMBOL(w1_reset_select_slave);
+EXPORT_SYMBOL_GPL(w1_reset_select_slave);
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
index 2328601..9a76d2a 100644
--- a/drivers/w1/w1_io.h
+++ b/drivers/w1/w1_io.h
@@ -24,11 +24,8 @@
 
 #include "w1.h"
 
-void w1_delay(unsigned long);
-u8 w1_touch_bit(struct w1_master *, int);
 u8 w1_triplet(struct w1_master *dev, int bdir);
 void w1_write_8(struct w1_master *, u8);
-u8 w1_read_8(struct w1_master *);
 int w1_reset_bus(struct w1_master *);
 u8 w1_calc_crc8(u8 *, int);
 void w1_write_block(struct w1_master *, const u8 *, int);
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index 328645d..65c5ebd 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -21,72 +21,225 @@
 
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
+#include <linux/connector.h>
 
 #include "w1.h"
 #include "w1_log.h"
 #include "w1_netlink.h"
 
-#ifndef NETLINK_DISABLED
+#if defined(CONFIG_W1_CON) && (defined(CONFIG_CONNECTOR) || (defined(CONFIG_CONNECTOR_MODULE) && defined(CONFIG_W1_MODULE)))
 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
 {
-	unsigned int size;
-	struct sk_buff *skb;
-	struct w1_netlink_msg *data;
-	struct nlmsghdr *nlh;
+	char buf[sizeof(struct cn_msg) + sizeof(struct w1_netlink_msg)];
+	struct cn_msg *m = (struct cn_msg *)buf;
+	struct w1_netlink_msg *w = (struct w1_netlink_msg *)(m+1);
 
-	if (!dev->nls)
-		return;
+	memset(buf, 0, sizeof(buf));
 
-	size = NLMSG_SPACE(sizeof(struct w1_netlink_msg));
+	m->id.idx = CN_W1_IDX;
+	m->id.val = CN_W1_VAL;
 
-	skb = alloc_skb(size, GFP_ATOMIC);
-	if (!skb) {
-		dev_err(&dev->dev, "skb_alloc() failed.\n");
-		return;
-	}
+	m->seq = dev->seq++;
+	m->len = sizeof(struct w1_netlink_msg);
 
-	nlh = NLMSG_PUT(skb, 0, dev->seq++, NLMSG_DONE, size - sizeof(*nlh));
+	memcpy(w, msg, sizeof(struct w1_netlink_msg));
 
-	data = (struct w1_netlink_msg *)NLMSG_DATA(nlh);
-
-	memcpy(data, msg, sizeof(struct w1_netlink_msg));
-
-	NETLINK_CB(skb).dst_group = dev->groups;
-	netlink_broadcast(dev->nls, skb, 0, dev->groups, GFP_ATOMIC);
-
-nlmsg_failure:
-	return;
+	cn_netlink_send(m, 0, GFP_KERNEL);
 }
 
-int dev_init_netlink(struct w1_master *dev)
+static int w1_process_command_master(struct w1_master *dev, struct cn_msg *msg,
+		struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
 {
-	dev->nls = netlink_kernel_create(NETLINK_W1, 1, NULL, THIS_MODULE);
-	if (!dev->nls) {
-		printk(KERN_ERR "Failed to create new netlink socket(%u) for w1 master %s.\n",
-			NETLINK_W1, dev->dev.bus_id);
-	}
+	dev_dbg(&dev->dev, "%s: %s: cmd=%02x, len=%u.\n",
+		__func__, dev->name, cmd->cmd, cmd->len);
 
+	if (cmd->cmd != W1_CMD_SEARCH && cmd->cmd != W1_CMD_ALARM_SEARCH)
+		return -EINVAL;
+
+	w1_search_process(dev, (cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH);
 	return 0;
 }
 
-void dev_fini_netlink(struct w1_master *dev)
+static int w1_send_read_reply(struct w1_slave *sl, struct cn_msg *msg,
+		struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
 {
-	if (dev->nls && dev->nls->sk_socket)
-		sock_release(dev->nls->sk_socket);
+	void *data;
+	struct w1_netlink_msg *h;
+	struct w1_netlink_cmd *c;
+	struct cn_msg *cm;
+	int err;
+
+	data = kzalloc(sizeof(struct cn_msg) +
+			sizeof(struct w1_netlink_msg) +
+			sizeof(struct w1_netlink_cmd) +
+			cmd->len, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	cm = (struct cn_msg *)(data);
+	h = (struct w1_netlink_msg *)(cm + 1);
+	c = (struct w1_netlink_cmd *)(h + 1);
+
+	memcpy(cm, msg, sizeof(struct cn_msg));
+	memcpy(h, hdr, sizeof(struct w1_netlink_msg));
+	memcpy(c, cmd, sizeof(struct w1_netlink_cmd));
+
+	cm->ack = msg->seq+1;
+	cm->len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len;
+
+	h->len = sizeof(struct w1_netlink_cmd) + cmd->len;
+
+	memcpy(c->data, cmd->data, c->len);
+
+	err = cn_netlink_send(cm, 0, GFP_KERNEL);
+
+	kfree(data);
+
+	return err;
+}
+
+static int w1_process_command_slave(struct w1_slave *sl, struct cn_msg *msg,
+		struct w1_netlink_msg *hdr, struct w1_netlink_cmd *cmd)
+{
+	int err = 0;
+
+	dev_dbg(&sl->master->dev, "%s: %02x.%012llx.%02x: cmd=%02x, len=%u.\n",
+		__func__, sl->reg_num.family, (unsigned long long)sl->reg_num.id, sl->reg_num.crc,
+		cmd->cmd, cmd->len);
+
+	switch (cmd->cmd) {
+		case W1_CMD_READ:
+			w1_read_block(sl->master, cmd->data, cmd->len);
+			w1_send_read_reply(sl, msg, hdr, cmd);
+			break;
+		case W1_CMD_WRITE:
+			w1_write_block(sl->master, cmd->data, cmd->len);
+			break;
+		case W1_CMD_SEARCH:
+		case W1_CMD_ALARM_SEARCH:
+			w1_search_process(sl->master,
+					(cmd->cmd == W1_CMD_ALARM_SEARCH)?W1_ALARM_SEARCH:W1_SEARCH);
+			break;
+		default:
+			err = -1;
+			break;
+	}
+
+	return err;
+}
+
+static void w1_cn_callback(void *data)
+{
+	struct cn_msg *msg = data;
+	struct w1_netlink_msg *m = (struct w1_netlink_msg *)(msg + 1);
+	struct w1_netlink_cmd *cmd;
+	struct w1_slave *sl;
+	struct w1_master *dev;
+	int err = 0;
+
+	while (msg->len && !err) {
+		struct w1_reg_num id;
+		u16 mlen = m->len;
+		u8 *cmd_data = m->data;
+
+		dev = NULL;
+		sl = NULL;
+
+		memcpy(&id, m->id.id, sizeof(id));
+#if 0
+		printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n",
+				__func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len);
+#endif
+		if (m->len + sizeof(struct w1_netlink_msg) > msg->len) {
+			err = -E2BIG;
+			break;
+		}
+
+		if (!mlen)
+			goto out_cont;
+
+		if (m->type == W1_MASTER_CMD) {
+			dev = w1_search_master_id(m->id.mst.id);
+		} else if (m->type == W1_SLAVE_CMD) {
+			sl = w1_search_slave(&id);
+			if (sl)
+				dev = sl->master;
+		}
+
+		if (!dev) {
+			err = -ENODEV;
+			goto out_cont;
+		}
+
+		mutex_lock(&dev->mutex);
+
+		if (sl && w1_reset_select_slave(sl)) {
+			err = -ENODEV;
+			goto out_up;
+		}
+
+		while (mlen) {
+			cmd = (struct w1_netlink_cmd *)cmd_data;
+
+			if (cmd->len + sizeof(struct w1_netlink_cmd) > mlen) {
+				err = -E2BIG;
+				break;
+			}
+
+			if (sl)
+				w1_process_command_slave(sl, msg, m, cmd);
+			else
+				w1_process_command_master(dev, msg, m, cmd);
+
+			cmd_data += cmd->len + sizeof(struct w1_netlink_cmd);
+			mlen -= cmd->len + sizeof(struct w1_netlink_cmd);
+		}
+out_up:
+		atomic_dec(&dev->refcnt);
+		if (sl)
+			atomic_dec(&sl->refcnt);
+		mutex_unlock(&dev->mutex);
+out_cont:
+		msg->len -= sizeof(struct w1_netlink_msg) + m->len;
+		m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len);
+
+		/*
+		 * Let's allow requests for nonexisting devices.
+		 */
+		if (err == -ENODEV)
+			err = 0;
+	}
+#if 0
+	if (err) {
+		printk("%s: malformed message. Dropping.\n", __func__);
+	}
+#endif
+}
+
+int w1_init_netlink(void)
+{
+	struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
+
+	return cn_add_callback(&w1_id, "w1", &w1_cn_callback);
+}
+
+void w1_fini_netlink(void)
+{
+	struct cb_id w1_id = {.idx = CN_W1_IDX, .val = CN_W1_VAL};
+
+	cn_del_callback(&w1_id);
 }
 #else
-#warning Netlink support is disabled. Please compile with NET support enabled.
-
 void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
 {
 }
 
-int dev_init_netlink(struct w1_master *dev)
+int w1_init_netlink(void)
 {
 	return 0;
 }
 
-void dev_fini_netlink(struct w1_master *dev)
+void w1_fini_netlink(void)
 {
 }
 #endif
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index eb0c8b3..56122b9 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -23,6 +23,7 @@
 #define __W1_NETLINK_H
 
 #include <asm/types.h>
+#include <linux/connector.h>
 
 #include "w1.h"
 
@@ -31,29 +32,43 @@
 	W1_SLAVE_REMOVE,
 	W1_MASTER_ADD,
 	W1_MASTER_REMOVE,
+	W1_MASTER_CMD,
+	W1_SLAVE_CMD,
 };
 
 struct w1_netlink_msg
 {
 	__u8				type;
-	__u8				reserved[3];
-	union
-	{
-		struct w1_reg_num	id;
-		__u64			w1_id;
-		struct
-		{
+	__u8				reserved;
+	__u16				len;
+	union {
+		__u8			id[8];
+		struct w1_mst {
 			__u32		id;
-			__u32		pid;
+			__u32		res;
 		} mst;
 	} id;
+	__u8				data[0];
+};
+
+#define W1_CMD_READ		0x0
+#define W1_CMD_WRITE		0x1
+#define W1_CMD_SEARCH		0x2
+#define W1_CMD_ALARM_SEARCH	0x3
+
+struct w1_netlink_cmd
+{
+	__u8				cmd;
+	__u8				res;
+	__u16				len;
+	__u8				data[0];
 };
 
 #ifdef __KERNEL__
 
 void w1_netlink_send(struct w1_master *, struct w1_netlink_msg *);
-int dev_init_netlink(struct w1_master *dev);
-void dev_fini_netlink(struct w1_master *dev);
+int w1_init_netlink(void);
+void w1_fini_netlink(void);
 
 #endif /* __KERNEL__ */
 #endif /* __W1_NETLINK_H */
diff --git a/fs/9p/mux.c b/fs/9p/mux.c
index f4407eb..8d45ed6 100644
--- a/fs/9p/mux.c
+++ b/fs/9p/mux.c
@@ -712,7 +712,7 @@
  * v9fs_send_request - send 9P request
  * The function can sleep until the request is scheduled for sending.
  * The function can be interrupted. Return from the function is not
- * a guarantee that the request is sent succesfully. Can return errors
+ * a guarantee that the request is sent successfully. Can return errors
  * that can be retrieved by PTR_ERR macros.
  *
  * @m: mux data
@@ -932,6 +932,8 @@
 					r.rcall || r.err);
 			} while (!r.rcall && !r.err && err==-ERESTARTSYS &&
 				m->trans->status==Connected && !m->err);
+
+			err = -ERESTARTSYS;
 		}
 		sigpending = 1;
 	}
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index f867b8d..450b0c1 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -38,7 +38,7 @@
  */
 
 extern struct file_system_type v9fs_fs_type;
-extern struct address_space_operations v9fs_addr_operations;
+extern const struct address_space_operations v9fs_addr_operations;
 extern const struct file_operations v9fs_file_operations;
 extern const struct file_operations v9fs_dir_operations;
 extern struct dentry_operations v9fs_dentry_operations;
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index efda46f..d4f0aa3 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -103,6 +103,6 @@
 	return retval;
 }
 
-struct address_space_operations v9fs_addr_operations = {
+const struct address_space_operations v9fs_addr_operations = {
       .readpage = v9fs_vfs_readpage,
 };
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 2cb87ba..2f580a1 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -300,7 +300,7 @@
 	fid = V9FS_NOFID;
 
 put_fid:
-	if (fid >= 0)
+	if (fid != V9FS_NOFID)
 		v9fs_put_idpool(fid, &v9ses->fidpool);
 
 	kfree(fcall);
@@ -530,9 +530,6 @@
 	if (vfid)
 		v9fs_fid_destroy(vfid);
 
-	if (inode)
-		iput(inode);
-
 	return err;
 }
 
@@ -1054,6 +1051,9 @@
 	int ret;
 	char *link = __getname();
 
+	if (unlikely(!link))
+		return -ENOMEM;
+
 	if (buflen > PATH_MAX)
 		buflen = PATH_MAX;
 
@@ -1171,9 +1171,6 @@
 	if (vfid)
 		v9fs_fid_destroy(vfid);
 
-	if (inode)
-		iput(inode);
-
 	return err;
 
 }
@@ -1227,6 +1224,9 @@
 	}
 
 	name = __getname();
+	if (unlikely(!name))
+		return -ENOMEM;
+
 	sprintf(name, "%d\n", oldfid->fid);
 	retval = v9fs_vfs_mkspecial(dir, dentry, V9FS_DMLINK, name);
 	__putname(name);
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
index 61c599b..8b15bb2 100644
--- a/fs/9p/vfs_super.c
+++ b/fs/9p/vfs_super.c
@@ -99,12 +99,13 @@
  * @flags: mount flags
  * @dev_name: device name that was mounted
  * @data: mount options
+ * @mnt: mountpoint record to be instantiated
  *
  */
 
-static struct super_block *v9fs_get_sb(struct file_system_type
-				       *fs_type, int flags,
-				       const char *dev_name, void *data)
+static int v9fs_get_sb(struct file_system_type *fs_type, int flags,
+		       const char *dev_name, void *data,
+		       struct vfsmount *mnt)
 {
 	struct super_block *sb = NULL;
 	struct v9fs_fcall *fcall = NULL;
@@ -123,17 +124,19 @@
 
 	v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL);
 	if (!v9ses)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 
 	if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) {
 		dprintk(DEBUG_ERROR, "problem initiating session\n");
-		sb = ERR_PTR(newfid);
+		retval = newfid;
 		goto out_free_session;
 	}
 
 	sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
-	if (IS_ERR(sb))
+	if (IS_ERR(sb)) {
+		retval = PTR_ERR(sb);
 		goto out_close_session;
+	}
 	v9fs_fill_super(sb, v9ses, flags);
 
 	inode = v9fs_get_inode(sb, S_IFDIR | mode);
@@ -184,19 +187,19 @@
 		goto put_back_sb;
 	}
 
-	return sb;
+	return simple_set_mnt(mnt, sb);
 
 out_close_session:
 	v9fs_session_close(v9ses);
 out_free_session:
 	kfree(v9ses);
-	return sb;
+	return retval;
 
 put_back_sb:
 	/* deactivate_super calls v9fs_kill_super which will frees the rest */
 	up_write(&sb->s_umount);
 	deactivate_super(sb);
-	return ERR_PTR(retval);
+	return retval;
 }
 
 /**
@@ -253,11 +256,12 @@
 }
 
 static void
-v9fs_umount_begin(struct super_block *sb)
+v9fs_umount_begin(struct vfsmount *vfsmnt, int flags)
 {
-	struct v9fs_session_info *v9ses = sb->s_fs_info;
+	struct v9fs_session_info *v9ses = vfsmnt->mnt_sb->s_fs_info;
 
-	v9fs_session_cancel(v9ses);
+	if (flags & MNT_FORCE)
+		v9fs_session_cancel(v9ses);
 }
 
 static struct super_operations v9fs_super_ops = {
diff --git a/fs/Kconfig b/fs/Kconfig
index f9b5842..6dc8cfd 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -53,7 +53,7 @@
 
 config EXT2_FS_XIP
 	bool "Ext2 execute in place support"
-	depends on EXT2_FS
+	depends on EXT2_FS && MMU
 	help
 	  Execute in place can be used on memory-backed block devices. If you
 	  enable this option, you can select to mount block devices which are
@@ -393,18 +393,30 @@
 	bool "Inotify file change notification support"
 	default y
 	---help---
-	  Say Y here to enable inotify support and the associated system
-	  calls.  Inotify is a file change notification system and a
-	  replacement for dnotify.  Inotify fixes numerous shortcomings in
-	  dnotify and introduces several new features.  It allows monitoring
-	  of both files and directories via a single open fd.  Other features
-	  include multiple file events, one-shot support, and unmount
+	  Say Y here to enable inotify support.  Inotify is a file change
+	  notification system and a replacement for dnotify.  Inotify fixes
+	  numerous shortcomings in dnotify and introduces several new features
+	  including multiple file events, one-shot support, and unmount
 	  notification.
 
 	  For more information, see Documentation/filesystems/inotify.txt
 
 	  If unsure, say Y.
 
+config INOTIFY_USER
+	bool "Inotify support for userspace"
+	depends on INOTIFY
+	default y
+	---help---
+	  Say Y here to enable inotify support for userspace, including the
+	  associated system calls.  Inotify allows monitoring of both files and
+	  directories via a single open fd.  Events are read from the file
+	  descriptor, which is also select()- and poll()-able.
+
+	  For more information, see Documentation/filesystems/inotify.txt
+
+	  If unsure, say Y.
+
 config QUOTA
 	bool "Quota support"
 	help
@@ -764,7 +776,8 @@
 menu "Pseudo filesystems"
 
 config PROC_FS
-	bool "/proc file system support"
+	bool "/proc file system support" if EMBEDDED
+	default y
 	help
 	  This is a virtual file system providing information about the status
 	  of the system. "Virtual" means that it doesn't take up any space on
@@ -1101,6 +1114,44 @@
 
 	  If unsure, say 'N'.
 
+config JFFS2_FS_XATTR
+	bool "JFFS2 XATTR support (EXPERIMENTAL)"
+	depends on JFFS2_FS && EXPERIMENTAL
+	default n
+	help
+	  Extended attributes are name:value pairs associated with inodes by
+	  the kernel or by users (see the attr(5) manual page, or visit
+	  <http://acl.bestbits.at/> for details).
+	  
+	  If unsure, say N.
+
+config JFFS2_FS_POSIX_ACL
+	bool "JFFS2 POSIX Access Control Lists"
+	depends on JFFS2_FS_XATTR
+	default y
+	select FS_POSIX_ACL
+	help
+	  Posix Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
+	  
+	  To learn more about Access Control Lists, visit the Posix ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+	  
+	  If you don't know what Access Control Lists are, say N
+
+config JFFS2_FS_SECURITY
+	bool "JFFS2 Security Labels"
+	depends on JFFS2_FS_XATTR
+	default y
+	help
+	  Security labels support alternative access control models
+	  implemented by security modules like SELinux.  This option
+	  enables an extended attribute handler for file security
+	  labels in the jffs2 filesystem.
+	  
+	  If you are not using a security module that requires using
+	  extended attributes for file security labels, say N.
+
 config JFFS2_COMPRESSION_OPTIONS
 	bool "Advanced compression options for JFFS2"
 	depends on JFFS2_FS
@@ -1320,11 +1371,19 @@
 
 config UFS_FS_WRITE
 	bool "UFS file system write support (DANGEROUS)"
-	depends on UFS_FS && EXPERIMENTAL && BROKEN
+	depends on UFS_FS && EXPERIMENTAL
 	help
 	  Say Y here if you want to try writing to UFS partitions. This is
 	  experimental, so you should back up your UFS partitions beforehand.
 
+config UFS_DEBUG
+	bool "UFS debugging"
+	depends on UFS_FS
+	help
+	  If you are experiencing any problems with the UFS filesystem, say
+	  Y here.  This will result in _many_ additional debugging messages to be
+	  written to the system log.
+
 endmenu
 
 menu "Network File Systems"
@@ -1431,7 +1490,12 @@
 	select LOCKD
 	select SUNRPC
 	select EXPORTFS
-	select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL
+	select NFSD_V2_ACL if NFSD_V3_ACL
+	select NFS_ACL_SUPPORT if NFSD_V2_ACL
+	select NFSD_TCP if NFSD_V4
+	select CRYPTO_MD5 if NFSD_V4
+	select CRYPTO if NFSD_V4
+	select FS_POSIX_ACL if NFSD_V4
 	help
 	  If you want your Linux box to act as an NFS *server*, so that other
 	  computers on your local network which support NFS can access certain
@@ -1469,7 +1533,6 @@
 config NFSD_V3_ACL
 	bool "Provide server support for the NFSv3 ACL protocol extension"
 	depends on NFSD_V3
-	select NFSD_V2_ACL
 	help
 	  Implement the NFSv3 ACL protocol extension for manipulating POSIX
 	  Access Control Lists on exported file systems. NFS clients should
@@ -1479,10 +1542,6 @@
 config NFSD_V4
 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
 	depends on NFSD_V3 && EXPERIMENTAL
-	select NFSD_TCP
-	select CRYPTO_MD5
-	select CRYPTO
-	select FS_POSIX_ACL
 	help
 	  If you would like to include the NFSv4 server as well as the NFSv2
 	  and NFSv3 servers, say Y here.  This feature is experimental, and
@@ -1663,7 +1722,7 @@
 	  mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
 
 config CIFS_STATS2
-	bool "CIFS extended statistics"
+	bool "Extended statistics"
 	depends on CIFS_STATS
 	help
 	  Enabling this option will allow more detailed statistics on SMB
@@ -1676,6 +1735,32 @@
 	  Unless you are a developer or are doing network performance analysis
 	  or tuning, say N.
 
+config CIFS_WEAK_PW_HASH
+	bool "Support legacy servers which use weaker LANMAN security"
+	depends on CIFS
+	help
+	  Modern CIFS servers including Samba and most Windows versions
+	  (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
+	  security mechanisms. These hash the password more securely
+	  than the mechanisms used in the older LANMAN version of the
+          SMB protocol needed to establish sessions with old SMB servers.
+
+	  Enabling this option allows the cifs module to mount to older
+	  LANMAN based servers such as OS/2 and Windows 95, but such
+	  mounts may be less secure than mounts using NTLM or more recent
+	  security mechanisms if you are on a public network.  Unless you
+	  have a need to access old SMB servers (and are on a private 
+	  network) you probably want to say N.  Even if this support
+	  is enabled in the kernel build, they will not be used
+	  automatically. At runtime LANMAN mounts are disabled but
+	  can be set to required (or optional) either in
+	  /proc/fs/cifs (see fs/cifs/README for more detail) or via an
+	  option on the mount command. This support is disabled by 
+	  default in order to reduce the possibility of a downgrade
+	  attack.
+ 
+	  If unsure, say N.
+
 config CIFS_XATTR
         bool "CIFS extended attributes"
         depends on CIFS
@@ -1704,6 +1789,16 @@
 	  (such as Samba 3.10 and later) which can negotiate
 	  CIFS POSIX ACL support.  If unsure, say N.
 
+config CIFS_DEBUG2
+	bool "Enable additional CIFS debugging routines"
+	help
+	   Enabling this option adds a few more debugging routines
+	   to the cifs code which slightly increases the size of
+	   the cifs module and can cause additional logging of debug
+	   messages in some error paths, slowing performance. This
+	   option can be turned off unless you are debugging
+	   cifs problems.  If unsure, say N.
+	   
 config CIFS_EXPERIMENTAL
 	  bool "CIFS Experimental Features (EXPERIMENTAL)"
 	  depends on CIFS && EXPERIMENTAL
@@ -1719,7 +1814,7 @@
 	    If unsure, say N.
 
 config CIFS_UPCALL
-	  bool "CIFS Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
+	  bool "Kerberos/SPNEGO advanced session setup (EXPERIMENTAL)"
 	  depends on CIFS_EXPERIMENTAL
 	  select CONNECTOR
 	  help
diff --git a/fs/Makefile b/fs/Makefile
index 078d3d1..d0ea6bf 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -13,6 +13,7 @@
 		ioprio.o pnode.o drop_caches.o splice.o sync.o
 
 obj-$(CONFIG_INOTIFY)		+= inotify.o
+obj-$(CONFIG_INOTIFY_USER)	+= inotify_user.o
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
 obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
 
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index a02802a..534f3ee 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -72,7 +72,7 @@
 	return generic_block_bmap(mapping, block, adfs_get_block);
 }
 
-static struct address_space_operations adfs_aops = {
+static const struct address_space_operations adfs_aops = {
 	.readpage	= adfs_readpage,
 	.writepage	= adfs_writepage,
 	.sync_page	= block_sync_page,
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index 252abda..ba1c88a 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -196,17 +196,17 @@
 	return parse_options(sb, data);
 }
 
-static int adfs_statfs(struct super_block *sb, struct kstatfs *buf)
+static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct adfs_sb_info *asb = ADFS_SB(sb);
+	struct adfs_sb_info *asb = ADFS_SB(dentry->d_sb);
 
 	buf->f_type    = ADFS_SUPER_MAGIC;
 	buf->f_namelen = asb->s_namelen;
-	buf->f_bsize   = sb->s_blocksize;
+	buf->f_bsize   = dentry->d_sb->s_blocksize;
 	buf->f_blocks  = asb->s_size;
 	buf->f_files   = asb->s_ids_per_zone * asb->s_map_size;
 	buf->f_bavail  =
-	buf->f_bfree   = adfs_map_free(sb);
+	buf->f_bfree   = adfs_map_free(dentry->d_sb);
 	buf->f_ffree   = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks;
 
 	return 0;
@@ -470,10 +470,11 @@
 	return -EINVAL;
 }
 
-static struct super_block *adfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int adfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type adfs_fs_type = {
diff --git a/fs/affs/affs.h b/fs/affs/affs.h
index a43a876..0ddd4cc 100644
--- a/fs/affs/affs.h
+++ b/fs/affs/affs.h
@@ -195,9 +195,9 @@
 extern const struct file_operations	 affs_file_operations;
 extern const struct file_operations	 affs_file_operations_ofs;
 extern const struct file_operations	 affs_dir_operations;
-extern struct address_space_operations	 affs_symlink_aops;
-extern struct address_space_operations	 affs_aops;
-extern struct address_space_operations	 affs_aops_ofs;
+extern const struct address_space_operations	 affs_symlink_aops;
+extern const struct address_space_operations	 affs_aops;
+extern const struct address_space_operations	 affs_aops_ofs;
 
 extern struct dentry_operations	 affs_dentry_operations;
 extern struct dentry_operations	 affs_dentry_operations_intl;
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 7076262..3de8590 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -406,7 +406,7 @@
 {
 	return generic_block_bmap(mapping,block,affs_get_block);
 }
-struct address_space_operations affs_aops = {
+const struct address_space_operations affs_aops = {
 	.readpage = affs_readpage,
 	.writepage = affs_writepage,
 	.sync_page = block_sync_page,
@@ -759,7 +759,7 @@
 	goto done;
 }
 
-struct address_space_operations affs_aops_ofs = {
+const struct address_space_operations affs_aops_ofs = {
 	.readpage = affs_readpage_ofs,
 	//.writepage = affs_writepage_ofs,
 	//.sync_page = affs_sync_page_ofs,
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 4d7e5b1..5200f49 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -18,7 +18,7 @@
 
 extern struct timezone sys_tz;
 
-static int affs_statfs(struct super_block *sb, struct kstatfs *buf);
+static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int affs_remount (struct super_block *sb, int *flags, char *data);
 
 static void
@@ -271,6 +271,7 @@
 	int			 reserved;
 	unsigned long		 mount_flags;
 	int			 tmp_flags;	/* fix remount prototype... */
+	u8			 sig[4];
 
 	pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
 
@@ -370,8 +371,9 @@
 		printk(KERN_ERR "AFFS: Cannot read boot block\n");
 		goto out_error;
 	}
-	chksum = be32_to_cpu(*(__be32 *)boot_bh->b_data);
+	memcpy(sig, boot_bh->b_data, 4);
 	brelse(boot_bh);
+	chksum = be32_to_cpu(*(__be32 *)sig);
 
 	/* Dircache filesystems are compatible with non-dircache ones
 	 * when reading. As long as they aren't supported, writing is
@@ -420,11 +422,11 @@
 	}
 
 	if (mount_flags & SF_VERBOSE) {
-		chksum = cpu_to_be32(chksum);
-		printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n",
-			AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0],
+		u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0];
+		printk(KERN_NOTICE "AFFS: Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n",
+			len > 31 ? 31 : len,
 			AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1,
-			(char *)&chksum,((char *)&chksum)[3] + '0',blocksize);
+			sig, sig[3] + '0', blocksize);
 	}
 
 	sb->s_flags |= MS_NODEV | MS_NOSUID;
@@ -508,8 +510,9 @@
 }
 
 static int
-affs_statfs(struct super_block *sb, struct kstatfs *buf)
+affs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
 	int		 free;
 
 	pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size,
@@ -524,10 +527,11 @@
 	return 0;
 }
 
-static struct super_block *affs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int affs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type affs_fs_type = {
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index 426f0f0..f802256 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -66,7 +66,7 @@
 	return err;
 }
 
-struct address_space_operations affs_symlink_aops = {
+const struct address_space_operations affs_symlink_aops = {
 	.readpage	= affs_symlink_readpage,
 };
 
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index 009a9ae..bfc1fd2 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -413,8 +413,7 @@
 
 	/* we found it in the graveyard - resurrect it */
  found_dead_server:
-	list_del(&server->link);
-	list_add_tail(&server->link, &cell->sv_list);
+	list_move_tail(&server->link, &cell->sv_list);
 	afs_get_server(server);
 	afs_kafstimod_del_timer(&server->timeout);
 	spin_unlock(&cell->sv_gylock);
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index a6dff6a..2fc9987 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -185,9 +185,7 @@
 
 	_enter("{%lu},%lu", dir->i_ino, index);
 
-	page = read_cache_page(dir->i_mapping,index,
-			       (filler_t *) dir->i_mapping->a_ops->readpage,
-			       NULL);
+	page = read_mapping_page(dir->i_mapping, index, NULL);
 	if (!IS_ERR(page)) {
 		wait_on_page_locked(page);
 		kmap(page);
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 7bb7168..67d6634 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -35,7 +35,7 @@
 	.getattr	= afs_inode_getattr,
 };
 
-struct address_space_operations afs_fs_aops = {
+const struct address_space_operations afs_fs_aops = {
 	.readpage	= afs_file_readpage,
 	.sync_page	= block_sync_page,
 	.set_page_dirty	= __set_page_dirty_nobuffers,
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 72febdf..e88b3b6 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -69,7 +69,7 @@
 /*
  * file.c
  */
-extern struct address_space_operations afs_fs_aops;
+extern const struct address_space_operations afs_fs_aops;
 extern struct inode_operations afs_file_inode_operations;
 
 #ifdef AFS_CACHING_SUPPORT
diff --git a/fs/afs/kafsasyncd.c b/fs/afs/kafsasyncd.c
index 7ac07d0..f09a794 100644
--- a/fs/afs/kafsasyncd.c
+++ b/fs/afs/kafsasyncd.c
@@ -136,8 +136,7 @@
 			if (!list_empty(&kafsasyncd_async_attnq)) {
 				op = list_entry(kafsasyncd_async_attnq.next,
 						struct afs_async_op, link);
-				list_del(&op->link);
-				list_add_tail(&op->link,
+				list_move_tail(&op->link,
 					      &kafsasyncd_async_busyq);
 			}
 
@@ -204,8 +203,7 @@
 	init_waitqueue_entry(&op->waiter, kafsasyncd_task);
 	add_wait_queue(&op->call->waitq, &op->waiter);
 
-	list_del(&op->link);
-	list_add_tail(&op->link, &kafsasyncd_async_busyq);
+	list_move_tail(&op->link, &kafsasyncd_async_busyq);
 
 	spin_unlock(&kafsasyncd_async_lock);
 
@@ -223,8 +221,7 @@
 
 	spin_lock(&kafsasyncd_async_lock);
 
-	list_del(&op->link);
-	list_add_tail(&op->link, &kafsasyncd_async_attnq);
+	list_move_tail(&op->link, &kafsasyncd_async_attnq);
 
 	spin_unlock(&kafsasyncd_async_lock);
 
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 4e6eeb5..99785a7 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -63,7 +63,6 @@
 int afs_mntpt_check_symlink(struct afs_vnode *vnode)
 {
 	struct page *page;
-	filler_t *filler;
 	size_t size;
 	char *buf;
 	int ret;
@@ -71,10 +70,7 @@
 	_enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique);
 
 	/* read the contents of the symlink into the pagecache */
-	filler = (filler_t *) AFS_VNODE_TO_I(vnode)->i_mapping->a_ops->readpage;
-
-	page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0,
-			       filler, NULL);
+	page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, NULL);
 	if (IS_ERR(page)) {
 		ret = PTR_ERR(page);
 		goto out;
@@ -160,7 +156,6 @@
 	struct page *page = NULL;
 	size_t size;
 	char *buf, *devname = NULL, *options = NULL;
-	filler_t *filler;
 	int ret;
 
 	kenter("{%s}", mntpt->d_name.name);
@@ -182,9 +177,7 @@
 		goto error;
 
 	/* read the contents of the AFS special symlink */
-	filler = (filler_t *)mntpt->d_inode->i_mapping->a_ops->readpage;
-
-	page = read_cache_page(mntpt->d_inode->i_mapping, 0, filler, NULL);
+	page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL);
 	if (IS_ERR(page)) {
 		ret = PTR_ERR(page);
 		goto error;
@@ -210,7 +203,7 @@
 
 	/* try and do the mount */
 	kdebug("--- attempting mount %s -o %s ---", devname, options);
-	mnt = do_kern_mount("afs", 0, devname, options);
+	mnt = vfs_kern_mount(&afs_fs_type, 0, devname, options);
 	kdebug("--- mount result %p ---", mnt);
 
 	free_page((unsigned long) devname);
diff --git a/fs/afs/server.c b/fs/afs/server.c
index 62b093a..22afaae 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -123,8 +123,7 @@
  resurrect_server:
 	_debug("resurrecting server");
 
-	list_del(&zombie->link);
-	list_add_tail(&zombie->link, &cell->sv_list);
+	list_move_tail(&zombie->link, &cell->sv_list);
 	afs_get_server(zombie);
 	afs_kafstimod_del_timer(&zombie->timeout);
 	spin_unlock(&cell->sv_gylock);
@@ -168,8 +167,7 @@
 	}
 
 	spin_lock(&cell->sv_gylock);
-	list_del(&server->link);
-	list_add_tail(&server->link, &cell->sv_graveyard);
+	list_move_tail(&server->link, &cell->sv_graveyard);
 
 	/* time out in 10 secs */
 	afs_kafstimod_add_timer(&server->timeout, 10 * HZ);
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 53c56e7..67d1f5c 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -38,9 +38,9 @@
 static void afs_i_init_once(void *foo, kmem_cache_t *cachep,
 			    unsigned long flags);
 
-static struct super_block *afs_get_sb(struct file_system_type *fs_type,
-				      int flags, const char *dev_name,
-				      void *data);
+static int afs_get_sb(struct file_system_type *fs_type,
+		      int flags, const char *dev_name,
+		      void *data, struct vfsmount *mnt);
 
 static struct inode *afs_alloc_inode(struct super_block *sb);
 
@@ -48,7 +48,7 @@
 
 static void afs_destroy_inode(struct inode *inode);
 
-static struct file_system_type afs_fs_type = {
+struct file_system_type afs_fs_type = {
 	.owner		= THIS_MODULE,
 	.name		= "afs",
 	.get_sb		= afs_get_sb,
@@ -294,10 +294,11 @@
  * get an AFS superblock
  * - TODO: don't use get_sb_nodev(), but rather call sget() directly
  */
-static struct super_block *afs_get_sb(struct file_system_type *fs_type,
-				      int flags,
-				      const char *dev_name,
-				      void *options)
+static int afs_get_sb(struct file_system_type *fs_type,
+		      int flags,
+		      const char *dev_name,
+		      void *options,
+		      struct vfsmount *mnt)
 {
 	struct afs_mount_params params;
 	struct super_block *sb;
@@ -311,7 +312,7 @@
 	ret = afscm_start();
 	if (ret < 0) {
 		_leave(" = %d", ret);
-		return ERR_PTR(ret);
+		return ret;
 	}
 
 	/* parse the options */
@@ -348,18 +349,19 @@
 		goto error;
 	}
 	sb->s_flags |= MS_ACTIVE;
+	simple_set_mnt(mnt, sb);
 
 	afs_put_volume(params.volume);
 	afs_put_cell(params.default_cell);
-	_leave(" = %p", sb);
-	return sb;
+	_leave(" = 0 [%p]", 0, sb);
+	return 0;
 
  error:
 	afs_put_volume(params.volume);
 	afs_put_cell(params.default_cell);
 	afscm_stop();
 	_leave(" = %d", ret);
-	return ERR_PTR(ret);
+	return ret;
 } /* end afs_get_sb() */
 
 /*****************************************************************************/
diff --git a/fs/afs/super.h b/fs/afs/super.h
index ac11362..32de8cc 100644
--- a/fs/afs/super.h
+++ b/fs/afs/super.h
@@ -38,6 +38,8 @@
 	return sb->s_fs_info;
 }
 
+extern struct file_system_type afs_fs_type;
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_AFS_SUPER_H */
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index eced206..331f730 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -326,8 +326,7 @@
 	/* found in the graveyard - resurrect */
 	_debug("found in graveyard");
 	atomic_inc(&vlocation->usage);
-	list_del(&vlocation->link);
-	list_add_tail(&vlocation->link, &cell->vl_list);
+	list_move_tail(&vlocation->link, &cell->vl_list);
 	spin_unlock(&cell->vl_gylock);
 
 	afs_kafstimod_del_timer(&vlocation->timeout);
@@ -478,8 +477,7 @@
 	}
 
 	/* move to graveyard queue */
-	list_del(&vlocation->link);
-	list_add_tail(&vlocation->link,&cell->vl_graveyard);
+	list_move_tail(&vlocation->link,&cell->vl_graveyard);
 
 	/* remove from pending timeout queue (refcounted if actually being
 	 * updated) */
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index 9867fef..cf62da5 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -104,8 +104,7 @@
 					vnode->cb_expiry * HZ);
 
 		spin_lock(&afs_cb_hash_lock);
-		list_del(&vnode->cb_hash_link);
-		list_add_tail(&vnode->cb_hash_link,
+		list_move_tail(&vnode->cb_hash_link,
 			      &afs_cb_hash(server, &vnode->fid));
 		spin_unlock(&afs_cb_hash_lock);
 
diff --git a/fs/aio.c b/fs/aio.c
index e41e932..9506301 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -641,7 +641,7 @@
  *	invoked both for initial i/o submission and
  *	subsequent retries via the aio_kick_handler.
  *	Expects to be invoked with iocb->ki_ctx->lock
- *	already held. The lock is released and reaquired
+ *	already held. The lock is released and reacquired
  *	as needed during processing.
  *
  * Calls the iocb retry method (already setup for the
@@ -777,11 +777,11 @@
 static int __aio_run_iocbs(struct kioctx *ctx)
 {
 	struct kiocb *iocb;
-	LIST_HEAD(run_list);
+	struct list_head run_list;
 
 	assert_spin_locked(&ctx->ctx_lock);
 
-	list_splice_init(&ctx->run_list, &run_list);
+	list_replace_init(&ctx->run_list, &run_list);
 	while (!list_empty(&run_list)) {
 		iocb = list_entry(run_list.next, struct kiocb,
 			ki_run_list);
diff --git a/fs/autofs/init.c b/fs/autofs/init.c
index b977ece..aca1237 100644
--- a/fs/autofs/init.c
+++ b/fs/autofs/init.c
@@ -14,10 +14,10 @@
 #include <linux/init.h>
 #include "autofs_i.h"
 
-static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int autofs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, autofs_fill_super);
+	return get_sb_nodev(fs_type, flags, data, autofs_fill_super, mnt);
 }
 
 static struct file_system_type autofs_fs_type = {
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index b8ce026..8dbd44f 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -174,6 +174,12 @@
 			struct autofs_info *ino = autofs4_dentry_ino(p);
 			unsigned int ino_count = atomic_read(&ino->count);
 
+			/*
+			 * Clean stale dentries below that have not been
+			 * invalidated after a mount fail during lookup
+			 */
+			d_invalidate(p);
+
 			/* allow for dget above and top is already dgot */
 			if (p == top)
 				ino_count += 2;
@@ -370,8 +376,7 @@
 		DPRINTK("returning %p %.*s",
 			expired, (int)expired->d_name.len, expired->d_name.name);
 		spin_lock(&dcache_lock);
-		list_del(&expired->d_parent->d_subdirs);
-		list_add(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
+		list_move(&expired->d_parent->d_subdirs, &expired->d_u.d_child);
 		spin_unlock(&dcache_lock);
 		return expired;
 	}
diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c
index acecec8..5d91933 100644
--- a/fs/autofs4/init.c
+++ b/fs/autofs4/init.c
@@ -14,10 +14,10 @@
 #include <linux/init.h>
 #include "autofs_i.h"
 
-static struct super_block *autofs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int autofs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, autofs4_fill_super);
+	return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt);
 }
 
 static struct file_system_type autofs_fs_type = {
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 68ebd10..a83e889 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -49,7 +49,7 @@
 			char **out, int *out_len);
 static void befs_put_super(struct super_block *);
 static int befs_remount(struct super_block *, int *, char *);
-static int befs_statfs(struct super_block *, struct kstatfs *);
+static int befs_statfs(struct dentry *, struct kstatfs *);
 static int parse_options(char *, befs_mount_options *);
 
 static const struct super_operations befs_sops = {
@@ -73,7 +73,7 @@
 	.lookup		= befs_lookup,
 };
 
-static struct address_space_operations befs_aops = {
+static const struct address_space_operations befs_aops = {
 	.readpage	= befs_readpage,
 	.sync_page	= block_sync_page,
 	.bmap		= befs_bmap,
@@ -880,8 +880,9 @@
 }
 
 static int
-befs_statfs(struct super_block *sb, struct kstatfs *buf)
+befs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
 
 	befs_debug(sb, "---> befs_statfs()");
 
@@ -899,11 +900,12 @@
 	return 0;
 }
 
-static struct super_block *
+static int
 befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name,
-	    void *data)
+	    void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type befs_fs_type = {
diff --git a/fs/bfs/bfs.h b/fs/bfs/bfs.h
index 9d79100..31973bb 100644
--- a/fs/bfs/bfs.h
+++ b/fs/bfs/bfs.h
@@ -50,7 +50,7 @@
 /* file.c */
 extern struct inode_operations bfs_file_inops;
 extern const struct file_operations bfs_file_operations;
-extern struct address_space_operations bfs_aops;
+extern const struct address_space_operations bfs_aops;
 
 /* dir.c */
 extern struct inode_operations bfs_dir_inops;
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index d83cd74..3d5aca2 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -153,7 +153,7 @@
 	return generic_block_bmap(mapping, block, bfs_get_block);
 }
 
-struct address_space_operations bfs_aops = {
+const struct address_space_operations bfs_aops = {
 	.readpage	= bfs_readpage,
 	.writepage	= bfs_writepage,
 	.sync_page	= block_sync_page,
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
index 55a7a78..cf74f3d 100644
--- a/fs/bfs/inode.c
+++ b/fs/bfs/inode.c
@@ -203,8 +203,9 @@
 	s->s_fs_info = NULL;
 }
 
-static int bfs_statfs(struct super_block *s, struct kstatfs *buf)
+static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *s = dentry->d_sb;
 	struct bfs_sb_info *info = BFS_SB(s);
 	u64 id = huge_encode_dev(s->s_bdev->bd_dev);
 	buf->f_type = BFS_MAGIC;
@@ -410,10 +411,10 @@
 	return -EINVAL;
 }
 
-static struct super_block *bfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int bfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super, mnt);
 }
 
 static struct file_system_type bfs_fs_type = {
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 537893a..d043440 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -38,15 +38,13 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/random.h>
-
+#include <linux/elf.h>
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
 
-#include <linux/elf.h>
-
-static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
-static int load_elf_library(struct file*);
+static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
+static int load_elf_library(struct file *);
 static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
 extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
 
@@ -59,15 +57,15 @@
  * don't even try.
  */
 #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)
-static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file);
+static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file);
 #else
 #define elf_core_dump	NULL
 #endif
 
 #if ELF_EXEC_PAGESIZE > PAGE_SIZE
-# define ELF_MIN_ALIGN	ELF_EXEC_PAGESIZE
+#define ELF_MIN_ALIGN	ELF_EXEC_PAGESIZE
 #else
-# define ELF_MIN_ALIGN	PAGE_SIZE
+#define ELF_MIN_ALIGN	PAGE_SIZE
 #endif
 
 #ifndef ELF_CORE_EFLAGS
@@ -86,7 +84,7 @@
 		.min_coredump	= ELF_EXEC_PAGESIZE
 };
 
-#define BAD_ADDR(x)	((unsigned long)(x) > TASK_SIZE)
+#define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
 
 static int set_brk(unsigned long start, unsigned long end)
 {
@@ -104,13 +102,11 @@
 	return 0;
 }
 
-
 /* We need to explicitly zero any fractional pages
    after the data section (i.e. bss).  This would
    contain the junk from the file that should not
-   be in memory */
-
-
+   be in memory
+ */
 static int padzero(unsigned long elf_bss)
 {
 	unsigned long nbyte;
@@ -129,7 +125,9 @@
 #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))
 #define STACK_ROUND(sp, items) \
 	((15 + (unsigned long) ((sp) + (items))) &~ 15UL)
-#define STACK_ALLOC(sp, len) ({ elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; old_sp; })
+#define STACK_ALLOC(sp, len) ({ \
+	elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; \
+	old_sp; })
 #else
 #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items))
 #define STACK_ROUND(sp, items) \
@@ -138,7 +136,7 @@
 #endif
 
 static int
-create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
+create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
 		int interp_aout, unsigned long load_addr,
 		unsigned long interp_load_addr)
 {
@@ -161,7 +159,6 @@
 	 * for userspace to get any other way, in others (i386) it is
 	 * merely difficult.
 	 */
-
 	u_platform = NULL;
 	if (k_platform) {
 		size_t len = strlen(k_platform) + 1;
@@ -171,7 +168,7 @@
 		 * evictions by the processes running on the same package. One
 		 * thing we can do is to shuffle the initial stack for them.
 		 */
-	 
+
 		p = arch_align_stack(p);
 
 		u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
@@ -180,9 +177,12 @@
 	}
 
 	/* Create the ELF interpreter info */
-	elf_info = (elf_addr_t *) current->mm->saved_auxv;
+	elf_info = (elf_addr_t *)current->mm->saved_auxv;
 #define NEW_AUX_ENT(id, val) \
-	do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0)
+	do { \
+		elf_info[ei_index++] = id; \
+		elf_info[ei_index++] = val; \
+	} while (0)
 
 #ifdef ARCH_DLINFO
 	/* 
@@ -195,21 +195,22 @@
 	NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE);
 	NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC);
 	NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff);
-	NEW_AUX_ENT(AT_PHENT, sizeof (struct elf_phdr));
+	NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr));
 	NEW_AUX_ENT(AT_PHNUM, exec->e_phnum);
 	NEW_AUX_ENT(AT_BASE, interp_load_addr);
 	NEW_AUX_ENT(AT_FLAGS, 0);
 	NEW_AUX_ENT(AT_ENTRY, exec->e_entry);
-	NEW_AUX_ENT(AT_UID, (elf_addr_t) tsk->uid);
-	NEW_AUX_ENT(AT_EUID, (elf_addr_t) tsk->euid);
-	NEW_AUX_ENT(AT_GID, (elf_addr_t) tsk->gid);
-	NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid);
- 	NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm));
+	NEW_AUX_ENT(AT_UID, tsk->uid);
+	NEW_AUX_ENT(AT_EUID, tsk->euid);
+	NEW_AUX_ENT(AT_GID, tsk->gid);
+	NEW_AUX_ENT(AT_EGID, tsk->egid);
+ 	NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm));
 	if (k_platform) {
-		NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform);
+		NEW_AUX_ENT(AT_PLATFORM,
+			    (elf_addr_t)(unsigned long)u_platform);
 	}
 	if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
-		NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data);
+		NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
 	}
 #undef NEW_AUX_ENT
 	/* AT_NULL is zero; clear the rest too */
@@ -232,7 +233,7 @@
 	/* Point sp at the lowest address on the stack */
 #ifdef CONFIG_STACK_GROWSUP
 	sp = (elf_addr_t __user *)bprm->p - items - ei_index;
-	bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */
+	bprm->exec = (unsigned long)sp; /* XXX: PARISC HACK */
 #else
 	sp = (elf_addr_t __user *)bprm->p;
 #endif
@@ -285,7 +286,7 @@
 #ifndef elf_map
 
 static unsigned long elf_map(struct file *filep, unsigned long addr,
-			struct elf_phdr *eppnt, int prot, int type)
+		struct elf_phdr *eppnt, int prot, int type)
 {
 	unsigned long map_addr;
 	unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr);
@@ -310,9 +311,8 @@
    is only provided so that we can read a.out libraries that have
    an ELF header */
 
-static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
-				     struct file * interpreter,
-				     unsigned long *interp_load_addr)
+static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex,
+		struct file *interpreter, unsigned long *interp_load_addr)
 {
 	struct elf_phdr *elf_phdata;
 	struct elf_phdr *eppnt;
@@ -342,15 +342,15 @@
 		goto out;
 
 	/* Now read in all of the header information */
-
 	size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;
 	if (size > ELF_MIN_ALIGN)
 		goto out;
-	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
+	elf_phdata = kmalloc(size, GFP_KERNEL);
 	if (!elf_phdata)
 		goto out;
 
-	retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size);
+	retval = kernel_read(interpreter, interp_elf_ex->e_phoff,
+			     (char *)elf_phdata,size);
 	error = -EIO;
 	if (retval != size) {
 		if (retval < 0)
@@ -359,58 +359,65 @@
 	}
 
 	eppnt = elf_phdata;
-	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
-	  if (eppnt->p_type == PT_LOAD) {
-	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
-	    int elf_prot = 0;
-	    unsigned long vaddr = 0;
-	    unsigned long k, map_addr;
+	for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) {
+		if (eppnt->p_type == PT_LOAD) {
+			int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
+			int elf_prot = 0;
+			unsigned long vaddr = 0;
+			unsigned long k, map_addr;
 
-	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
-	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-	    vaddr = eppnt->p_vaddr;
-	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
-	    	elf_type |= MAP_FIXED;
+			if (eppnt->p_flags & PF_R)
+		    		elf_prot = PROT_READ;
+			if (eppnt->p_flags & PF_W)
+				elf_prot |= PROT_WRITE;
+			if (eppnt->p_flags & PF_X)
+				elf_prot |= PROT_EXEC;
+			vaddr = eppnt->p_vaddr;
+			if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
+				elf_type |= MAP_FIXED;
 
-	    map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
-	    error = map_addr;
-	    if (BAD_ADDR(map_addr))
-	    	goto out_close;
+			map_addr = elf_map(interpreter, load_addr + vaddr,
+					   eppnt, elf_prot, elf_type);
+			error = map_addr;
+			if (BAD_ADDR(map_addr))
+				goto out_close;
 
-	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
-		load_addr = map_addr - ELF_PAGESTART(vaddr);
-		load_addr_set = 1;
-	    }
+			if (!load_addr_set &&
+			    interp_elf_ex->e_type == ET_DYN) {
+				load_addr = map_addr - ELF_PAGESTART(vaddr);
+				load_addr_set = 1;
+			}
 
-	    /*
-	     * Check to see if the section's size will overflow the
-	     * allowed task size. Note that p_filesz must always be
-	     * <= p_memsize so it is only necessary to check p_memsz.
-	     */
-	    k = load_addr + eppnt->p_vaddr;
-	    if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz ||
-		eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) {
-	        error = -ENOMEM;
-		goto out_close;
-	    }
+			/*
+			 * Check to see if the section's size will overflow the
+			 * allowed task size. Note that p_filesz must always be
+			 * <= p_memsize so it's only necessary to check p_memsz.
+			 */
+			k = load_addr + eppnt->p_vaddr;
+			if (k > TASK_SIZE ||
+			    eppnt->p_filesz > eppnt->p_memsz ||
+			    eppnt->p_memsz > TASK_SIZE ||
+			    TASK_SIZE - eppnt->p_memsz < k) {
+				error = -ENOMEM;
+				goto out_close;
+			}
 
-	    /*
-	     * Find the end of the file mapping for this phdr, and keep
-	     * track of the largest address we see for this.
-	     */
-	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
-	    if (k > elf_bss)
-		elf_bss = k;
+			/*
+			 * Find the end of the file mapping for this phdr, and
+			 * keep track of the largest address we see for this.
+			 */
+			k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
+			if (k > elf_bss)
+				elf_bss = k;
 
-	    /*
-	     * Do the same thing for the memory mapping - between
-	     * elf_bss and last_bss is the bss section.
-	     */
-	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
-	    if (k > last_bss)
-		last_bss = k;
-	  }
+			/*
+			 * Do the same thing for the memory mapping - between
+			 * elf_bss and last_bss is the bss section.
+			 */
+			k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
+			if (k > last_bss)
+				last_bss = k;
+		}
 	}
 
 	/*
@@ -424,7 +431,8 @@
 		goto out_close;
 	}
 
-	elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);	/* What we have mapped so far */
+	/* What we have mapped so far */
+	elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
 
 	/* Map the last of the bss segment */
 	if (last_bss > elf_bss) {
@@ -436,7 +444,7 @@
 	}
 
 	*interp_load_addr = load_addr;
-	error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;
+	error = ((unsigned long)interp_elf_ex->e_entry) + load_addr;
 
 out_close:
 	kfree(elf_phdata);
@@ -444,8 +452,8 @@
 	return error;
 }
 
-static unsigned long load_aout_interp(struct exec * interp_ex,
-			     struct file * interpreter)
+static unsigned long load_aout_interp(struct exec *interp_ex,
+		struct file *interpreter)
 {
 	unsigned long text_data, elf_entry = ~0UL;
 	char __user * addr;
@@ -464,7 +472,7 @@
 	case ZMAGIC:
 	case QMAGIC:
 		offset = N_TXTOFF(*interp_ex);
-		addr = (char __user *) N_TXTADDR(*interp_ex);
+		addr = (char __user *)N_TXTADDR(*interp_ex);
 		break;
 	default:
 		goto out;
@@ -480,7 +488,6 @@
 	flush_icache_range((unsigned long)addr,
 	                   (unsigned long)addr + text_data);
 
-
 	down_write(&current->mm->mmap_sem);	
 	do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1),
 		interp_ex->a_bss);
@@ -519,7 +526,7 @@
 #endif
 }
 
-static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 {
 	struct file *interpreter = NULL; /* to shut gcc up */
  	unsigned long load_addr = 0, load_bias = 0;
@@ -528,7 +535,7 @@
 	unsigned int interpreter_type = INTERPRETER_NONE;
 	unsigned char ibcs2_interpreter = 0;
 	unsigned long error;
-	struct elf_phdr * elf_ppnt, *elf_phdata;
+	struct elf_phdr *elf_ppnt, *elf_phdata;
 	unsigned long elf_bss, elf_brk;
 	int elf_exec_fileno;
 	int retval, i;
@@ -553,7 +560,7 @@
 	}
 	
 	/* Get the exec-header */
-	loc->elf_ex = *((struct elfhdr *) bprm->buf);
+	loc->elf_ex = *((struct elfhdr *)bprm->buf);
 
 	retval = -ENOEXEC;
 	/* First of all, some simple consistency checks */
@@ -568,7 +575,6 @@
 		goto out;
 
 	/* Now read in all of the header information */
-
 	if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
 		goto out;
 	if (loc->elf_ex.e_phnum < 1 ||
@@ -576,18 +582,19 @@
 		goto out;
 	size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
 	retval = -ENOMEM;
-	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
+	elf_phdata = kmalloc(size, GFP_KERNEL);
 	if (!elf_phdata)
 		goto out;
 
-	retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size);
+	retval = kernel_read(bprm->file, loc->elf_ex.e_phoff,
+			     (char *)elf_phdata, size);
 	if (retval != size) {
 		if (retval >= 0)
 			retval = -EIO;
 		goto out_free_ph;
 	}
 
-	files = current->files;		/* Refcounted so ok */
+	files = current->files;	/* Refcounted so ok */
 	retval = unshare_files();
 	if (retval < 0)
 		goto out_free_ph;
@@ -598,7 +605,6 @@
 
 	/* exec will make our files private anyway, but for the a.out
 	   loader stuff we need to do it earlier */
-
 	retval = get_unused_fd();
 	if (retval < 0)
 		goto out_free_fh;
@@ -620,7 +626,6 @@
 			 * shared libraries - for now assume that this
 			 * is an a.out format binary
 			 */
-
 			retval = -ENOEXEC;
 			if (elf_ppnt->p_filesz > PATH_MAX || 
 			    elf_ppnt->p_filesz < 2)
@@ -628,13 +633,13 @@
 
 			retval = -ENOMEM;
 			elf_interpreter = kmalloc(elf_ppnt->p_filesz,
-							   GFP_KERNEL);
+						  GFP_KERNEL);
 			if (!elf_interpreter)
 				goto out_free_file;
 
 			retval = kernel_read(bprm->file, elf_ppnt->p_offset,
-					   elf_interpreter,
-					   elf_ppnt->p_filesz);
+					     elf_interpreter,
+					     elf_ppnt->p_filesz);
 			if (retval != elf_ppnt->p_filesz) {
 				if (retval >= 0)
 					retval = -EIO;
@@ -678,7 +683,8 @@
 			retval = PTR_ERR(interpreter);
 			if (IS_ERR(interpreter))
 				goto out_free_interp;
-			retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE);
+			retval = kernel_read(interpreter, 0, bprm->buf,
+					     BINPRM_BUF_SIZE);
 			if (retval != BINPRM_BUF_SIZE) {
 				if (retval >= 0)
 					retval = -EIO;
@@ -686,8 +692,8 @@
 			}
 
 			/* Get the exec headers */
-			loc->interp_ex = *((struct exec *) bprm->buf);
-			loc->interp_elf_ex = *((struct elfhdr *) bprm->buf);
+			loc->interp_ex = *((struct exec *)bprm->buf);
+			loc->interp_elf_ex = *((struct elfhdr *)bprm->buf);
 			break;
 		}
 		elf_ppnt++;
@@ -739,7 +745,6 @@
 
 	/* OK, we are done with that, now set up the arg stuff,
 	   and then start this sucker up */
-
 	if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) {
 		char *passed_p = passed_fileno;
 		sprintf(passed_fileno, "%d", elf_exec_fileno);
@@ -759,7 +764,6 @@
 
 	/* Discard our unneeded old files struct */
 	if (files) {
-		steal_locks(files);
 		put_files_struct(files);
 		files = NULL;
 	}
@@ -778,7 +782,7 @@
 	if (elf_read_implies_exec(loc->elf_ex, executable_stack))
 		current->personality |= READ_IMPLIES_EXEC;
 
-	if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+	if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
 		current->flags |= PF_RANDOMIZE;
 	arch_pick_mmap_layout(current->mm);
 
@@ -799,8 +803,8 @@
 	   the correct location in memory.  At this point, we assume that
 	   the image should be loaded at fixed address, not at a variable
 	   address. */
-
-	for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
+	for(i = 0, elf_ppnt = elf_phdata;
+	    i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
 		int elf_prot = 0, elf_flags;
 		unsigned long k, vaddr;
 
@@ -828,30 +832,35 @@
 							load_bias, nbyte)) {
 					/*
 					 * This bss-zeroing can fail if the ELF
-					 * file specifies odd protections.  So
+					 * file specifies odd protections. So
 					 * we don't check the return value
 					 */
 				}
 			}
 		}
 
-		if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
-		if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
-		if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+		if (elf_ppnt->p_flags & PF_R)
+			elf_prot |= PROT_READ;
+		if (elf_ppnt->p_flags & PF_W)
+			elf_prot |= PROT_WRITE;
+		if (elf_ppnt->p_flags & PF_X)
+			elf_prot |= PROT_EXEC;
 
-		elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
+		elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE;
 
 		vaddr = elf_ppnt->p_vaddr;
 		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
 			elf_flags |= MAP_FIXED;
 		} else if (loc->elf_ex.e_type == ET_DYN) {
-			/* Try and get dynamic programs out of the way of the default mmap
-			   base, as well as whatever program they might try to exec.  This
-			   is because the brk will follow the loader, and is not movable.  */
+			/* Try and get dynamic programs out of the way of the
+			 * default mmap base, as well as whatever program they
+			 * might try to exec.  This is because the brk will
+			 * follow the loader, and is not movable.  */
 			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
 		}
 
-		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
+		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
+				elf_prot, elf_flags);
 		if (BAD_ADDR(error)) {
 			send_sig(SIGKILL, current, 0);
 			goto out_free_dentry;
@@ -868,8 +877,10 @@
 			}
 		}
 		k = elf_ppnt->p_vaddr;
-		if (k < start_code) start_code = k;
-		if (start_data < k) start_data = k;
+		if (k < start_code)
+			start_code = k;
+		if (start_data < k)
+			start_data = k;
 
 		/*
 		 * Check to see if the section's size will overflow the
@@ -879,7 +890,7 @@
 		if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
 		    elf_ppnt->p_memsz > TASK_SIZE ||
 		    TASK_SIZE - elf_ppnt->p_memsz < k) {
-			/* set_brk can never work.  Avoid overflows.  */
+			/* set_brk can never work. Avoid overflows. */
 			send_sig(SIGKILL, current, 0);
 			goto out_free_dentry;
 		}
@@ -967,8 +978,9 @@
 
 	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
-	create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT),
-			load_addr, interp_load_addr);
+	create_elf_tables(bprm, &loc->elf_ex,
+			  (interpreter_type == INTERPRETER_AOUT),
+			  load_addr, interp_load_addr);
 	/* N.B. passed_fileno might not be initialized? */
 	if (interpreter_type == INTERPRETER_AOUT)
 		current->mm->arg_start += strlen(passed_fileno) + 1;
@@ -982,7 +994,7 @@
 		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
 		   and some applications "depend" upon this behavior.
 		   Since we do not have the power to recompile these, we
-		   emulate the SVr4 behavior.  Sigh.  */
+		   emulate the SVr4 behavior. Sigh. */
 		down_write(&current->mm->mmap_sem);
 		error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
 				MAP_FIXED | MAP_PRIVATE, 0);
@@ -1037,7 +1049,6 @@
 
 /* This is really simpleminded and specialized - we are loading an
    a.out library that is given an ELF header. */
-
 static int load_elf_library(struct file *file)
 {
 	struct elf_phdr *elf_phdata;
@@ -1047,7 +1058,7 @@
 	struct elfhdr elf_ex;
 
 	error = -ENOEXEC;
-	retval = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex));
+	retval = kernel_read(file, 0, (char *)&elf_ex, sizeof(elf_ex));
 	if (retval != sizeof(elf_ex))
 		goto out;
 
@@ -1056,7 +1067,7 @@
 
 	/* First of all, some simple consistency checks */
 	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
-	   !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
+	    !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap)
 		goto out;
 
 	/* Now read in all of the header information */
@@ -1104,7 +1115,8 @@
 		goto out_free_ph;
 	}
 
-	len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1);
+	len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
+			    ELF_MIN_ALIGN - 1);
 	bss = eppnt->p_memsz + eppnt->p_vaddr;
 	if (bss > len) {
 		down_write(&current->mm->mmap_sem);
@@ -1163,7 +1175,7 @@
 	if (vma->vm_flags & (VM_IO | VM_RESERVED))
 		return 0;
 
-	/* Dump shared memory only if mapped from an anonymous file.  */
+	/* Dump shared memory only if mapped from an anonymous file. */
 	if (vma->vm_flags & VM_SHARED)
 		return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
 
@@ -1174,7 +1186,7 @@
 	return 1;
 }
 
-#define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
+#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
 
 /* An ELF note in memory */
 struct memelfnote
@@ -1277,11 +1289,11 @@
 }
 
 /*
- * fill up all the fields in prstatus from the given task struct, except registers
- * which need to be filled up separately.
+ * fill up all the fields in prstatus from the given task struct, except
+ * registers which need to be filled up separately.
  */
 static void fill_prstatus(struct elf_prstatus *prstatus,
-			struct task_struct *p, long signr) 
+		struct task_struct *p, long signr)
 {
 	prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
 	prstatus->pr_sigpend = p->pending.signal.sig[0];
@@ -1366,8 +1378,8 @@
 
 /*
  * In order to add the specific thread information for the elf file format,
- * we need to keep a linked list of every threads pr_status and then
- * create a single section for them in the final core file.
+ * we need to keep a linked list of every threads pr_status and then create
+ * a single section for them in the final core file.
  */
 static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
 {
@@ -1378,19 +1390,23 @@
 	fill_prstatus(&t->prstatus, p, signr);
 	elf_core_copy_task_regs(p, &t->prstatus.pr_reg);	
 	
-	fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), &(t->prstatus));
+	fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
+		  &(t->prstatus));
 	t->num_notes++;
 	sz += notesize(&t->notes[0]);
 
-	if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu))) {
-		fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), &(t->fpu));
+	if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL,
+								&t->fpu))) {
+		fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu),
+			  &(t->fpu));
 		t->num_notes++;
 		sz += notesize(&t->notes[1]);
 	}
 
 #ifdef ELF_CORE_COPY_XFPREGS
 	if (elf_core_copy_task_xfpregs(p, &t->xfpu)) {
-		fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu), &t->xfpu);
+		fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu),
+			  &t->xfpu);
 		t->num_notes++;
 		sz += notesize(&t->notes[2]);
 	}
@@ -1405,7 +1421,7 @@
  * and then they are actually written out.  If we run out of core limit
  * we just truncate.
  */
-static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
+static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
 {
 #define	NUM_NOTES	6
 	int has_dumped = 0;
@@ -1434,12 +1450,12 @@
 	/*
 	 * We no longer stop all VM operations.
 	 * 
-	 * This is because those proceses that could possibly change map_count or
-	 * the mmap / vma pages are now blocked in do_exit on current finishing
-	 * this core dump.
+	 * This is because those proceses that could possibly change map_count
+	 * or the mmap / vma pages are now blocked in do_exit on current
+	 * finishing this core dump.
 	 *
 	 * Only ptrace can touch these memory addresses, but it doesn't change
-	 * the map_count or the pages allocated.  So no possibility of crashing
+	 * the map_count or the pages allocated. So no possibility of crashing
 	 * exists while dumping the mm->vm_next areas to the core file.
 	 */
   
@@ -1501,7 +1517,7 @@
 #endif
 
 	/* Set up header */
-	fill_elf_header(elf, segs+1);	/* including notes section */
+	fill_elf_header(elf, segs + 1);	/* including notes section */
 
 	has_dumped = 1;
 	current->flags |= PF_DUMPCORE;
@@ -1511,24 +1527,24 @@
 	 * with info from their /proc.
 	 */
 
-	fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
-	
+	fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus);
 	fill_psinfo(psinfo, current->group_leader, current->mm);
-	fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
+	fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo);
 	
 	numnote = 2;
 
-	auxv = (elf_addr_t *) current->mm->saved_auxv;
+	auxv = (elf_addr_t *)current->mm->saved_auxv;
 
 	i = 0;
 	do
 		i += 2;
 	while (auxv[i - 2] != AT_NULL);
 	fill_note(&notes[numnote++], "CORE", NT_AUXV,
-		  i * sizeof (elf_addr_t), auxv);
+		  i * sizeof(elf_addr_t), auxv);
 
   	/* Try to dump the FPU. */
-	if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu)))
+	if ((prstatus->pr_fpvalid =
+	     elf_core_copy_task_fpregs(current, regs, fpu)))
 		fill_note(notes + numnote++,
 			  "CORE", NT_PRFPREG, sizeof(*fpu), fpu);
 #ifdef ELF_CORE_COPY_XFPREGS
@@ -1577,8 +1593,10 @@
 		phdr.p_memsz = sz;
 		offset += phdr.p_filesz;
 		phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
-		if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;
-		if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
+		if (vma->vm_flags & VM_WRITE)
+			phdr.p_flags |= PF_W;
+		if (vma->vm_flags & VM_EXEC)
+			phdr.p_flags |= PF_X;
 		phdr.p_align = ELF_EXEC_PAGESIZE;
 
 		DUMP_WRITE(&phdr, sizeof(phdr));
@@ -1595,7 +1613,9 @@
 
 	/* write out the thread status notes section */
 	list_for_each(t, &thread_list) {
-		struct elf_thread_status *tmp = list_entry(t, struct elf_thread_status, list);
+		struct elf_thread_status *tmp =
+				list_entry(t, struct elf_thread_status, list);
+
 		for (i = 0; i < tmp->num_notes; i++)
 			if (!writenote(&tmp->notes[i], file))
 				goto end_coredump;
@@ -1612,18 +1632,19 @@
 		for (addr = vma->vm_start;
 		     addr < vma->vm_end;
 		     addr += PAGE_SIZE) {
-			struct page* page;
+			struct page *page;
 			struct vm_area_struct *vma;
 
 			if (get_user_pages(current, current->mm, addr, 1, 0, 1,
 						&page, &vma) <= 0) {
-				DUMP_SEEK (file->f_pos + PAGE_SIZE);
+				DUMP_SEEK(file->f_pos + PAGE_SIZE);
 			} else {
 				if (page == ZERO_PAGE(addr)) {
-					DUMP_SEEK (file->f_pos + PAGE_SIZE);
+					DUMP_SEEK(file->f_pos + PAGE_SIZE);
 				} else {
 					void *kaddr;
-					flush_cache_page(vma, addr, page_to_pfn(page));
+					flush_cache_page(vma, addr,
+							 page_to_pfn(page));
 					kaddr = kmap(page);
 					if ((size += PAGE_SIZE) > limit ||
 					    !dump_write(file, kaddr,
@@ -1645,7 +1666,8 @@
 
 	if ((off_t)file->f_pos != offset) {
 		/* Sanity check */
-		printk(KERN_WARNING "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
+		printk(KERN_WARNING
+		       "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n",
 		       (off_t)file->f_pos, offset);
 	}
 
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index a2e48c9..eba4e23 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -435,9 +435,10 @@
 				   struct elf_fdpic_params *interp_params)
 {
 	unsigned long sp, csp, nitems;
-	elf_caddr_t *argv, *envp;
+	elf_caddr_t __user *argv, *envp;
 	size_t platform_len = 0, len;
-	char *k_platform, *u_platform, *p;
+	char *k_platform;
+	char __user *u_platform, *p;
 	long hwcap;
 	int loop;
 
@@ -462,12 +463,11 @@
 	if (k_platform) {
 		platform_len = strlen(k_platform) + 1;
 		sp -= platform_len;
+		u_platform = (char __user *) sp;
 		if (__copy_to_user(u_platform, k_platform, platform_len) != 0)
 			return -EFAULT;
 	}
 
-	u_platform = (char *) sp;
-
 #if defined(__i386__) && defined(CONFIG_SMP)
 	/* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
 	 * by the processes running on the same package. One thing we can do
@@ -490,7 +490,7 @@
 	sp = (sp - len) & ~7UL;
 	exec_params->map_addr = sp;
 
-	if (copy_to_user((void *) sp, exec_params->loadmap, len) != 0)
+	if (copy_to_user((void __user *) sp, exec_params->loadmap, len) != 0)
 		return -EFAULT;
 
 	current->mm->context.exec_fdpic_loadmap = (unsigned long) sp;
@@ -501,7 +501,7 @@
 		sp = (sp - len) & ~7UL;
 		interp_params->map_addr = sp;
 
-		if (copy_to_user((void *) sp, interp_params->loadmap, len) != 0)
+		if (copy_to_user((void __user *) sp, interp_params->loadmap, len) != 0)
 			return -EFAULT;
 
 		current->mm->context.interp_fdpic_loadmap = (unsigned long) sp;
@@ -527,7 +527,7 @@
 	/* put the ELF interpreter info on the stack */
 #define NEW_AUX_ENT(nr, id, val)						\
 	do {									\
-		struct { unsigned long _id, _val; } *ent = (void *) csp;	\
+		struct { unsigned long _id, _val; } __user *ent = (void __user *) csp;	\
 		__put_user((id), &ent[nr]._id);					\
 		__put_user((val), &ent[nr]._val);				\
 	} while (0)
@@ -564,13 +564,13 @@
 
 	/* allocate room for argv[] and envv[] */
 	csp -= (bprm->envc + 1) * sizeof(elf_caddr_t);
-	envp = (elf_caddr_t *) csp;
+	envp = (elf_caddr_t __user *) csp;
 	csp -= (bprm->argc + 1) * sizeof(elf_caddr_t);
-	argv = (elf_caddr_t *) csp;
+	argv = (elf_caddr_t __user *) csp;
 
 	/* stack argc */
 	csp -= sizeof(unsigned long);
-	__put_user(bprm->argc, (unsigned long *) csp);
+	__put_user(bprm->argc, (unsigned long __user *) csp);
 
 	BUG_ON(csp != sp);
 
@@ -581,7 +581,7 @@
 	current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p);
 #endif
 
-	p = (char *) current->mm->arg_start;
+	p = (char __user *) current->mm->arg_start;
 	for (loop = bprm->argc; loop > 0; loop--) {
 		__put_user((elf_caddr_t) p, argv++);
 		len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES);
@@ -1025,7 +1025,7 @@
 		/* clear the bit between beginning of mapping and beginning of PT_LOAD */
 		if (prot & PROT_WRITE && disp > 0) {
 			kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp);
-			clear_user((void *) maddr, disp);
+			clear_user((void __user *) maddr, disp);
 			maddr += disp;
 		}
 
@@ -1059,7 +1059,7 @@
 		if (prot & PROT_WRITE && excess1 > 0) {
 			kdebug("clear[%d] ad=%lx sz=%lx",
 			       loop, maddr + phdr->p_filesz, excess1);
-			clear_user((void *) maddr + phdr->p_filesz, excess1);
+			clear_user((void __user *) maddr + phdr->p_filesz, excess1);
 		}
 
 #else
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index b1c902e..c94d52e 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -510,7 +510,7 @@
 		}
 
 		/* OK, This is the point of no return */
-		set_personality(PER_LINUX);
+		set_personality(PER_LINUX_32BIT);
 	}
 
 	/*
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index d73d755..34ebbc1 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -55,6 +55,7 @@
 } Node;
 
 static DEFINE_RWLOCK(entries_lock);
+static struct file_system_type bm_fs_type;
 static struct vfsmount *bm_mnt;
 static int entry_count;
 
@@ -203,7 +204,6 @@
 		goto _error;
 
 	if (files) {
-		steal_locks(files);
 		put_files_struct(files);
 		files = NULL;
 	}
@@ -638,7 +638,7 @@
 	if (!inode)
 		goto out2;
 
-	err = simple_pin_fs("binfmt_misc", &bm_mnt, &entry_count);
+	err = simple_pin_fs(&bm_fs_type, &bm_mnt, &entry_count);
 	if (err) {
 		iput(inode);
 		inode = NULL;
@@ -740,10 +740,10 @@
 	return err;
 }
 
-static struct super_block *bm_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int bm_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, bm_fill_super);
+	return get_sb_single(fs_type, flags, data, bm_fill_super, mnt);
 }
 
 static struct linux_binfmt misc_format = {
diff --git a/fs/block_dev.c b/fs/block_dev.c
index f5958f4..7f7600e2 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -300,10 +300,10 @@
 	.clear_inode = bdev_clear_inode,
 };
 
-static struct super_block *bd_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int bd_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576);
+	return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576, mnt);
 }
 
 static struct file_system_type bd_type = {
@@ -414,21 +414,31 @@
 static struct block_device *bd_acquire(struct inode *inode)
 {
 	struct block_device *bdev;
+
 	spin_lock(&bdev_lock);
 	bdev = inode->i_bdev;
-	if (bdev && igrab(bdev->bd_inode)) {
+	if (bdev) {
+		atomic_inc(&bdev->bd_inode->i_count);
 		spin_unlock(&bdev_lock);
 		return bdev;
 	}
 	spin_unlock(&bdev_lock);
+
 	bdev = bdget(inode->i_rdev);
 	if (bdev) {
 		spin_lock(&bdev_lock);
-		if (inode->i_bdev)
-			__bd_forget(inode);
-		inode->i_bdev = bdev;
-		inode->i_mapping = bdev->bd_inode->i_mapping;
-		list_add(&inode->i_devices, &bdev->bd_inodes);
+		if (!inode->i_bdev) {
+			/*
+			 * We take an additional bd_inode->i_count for inode,
+			 * and it's released in clear_inode() of inode.
+			 * So, we can access it via ->i_mapping always
+			 * without igrab().
+			 */
+			atomic_inc(&bdev->bd_inode->i_count);
+			inode->i_bdev = bdev;
+			inode->i_mapping = bdev->bd_inode->i_mapping;
+			list_add(&inode->i_devices, &bdev->bd_inodes);
+		}
 		spin_unlock(&bdev_lock);
 	}
 	return bdev;
@@ -438,10 +448,18 @@
 
 void bd_forget(struct inode *inode)
 {
+	struct block_device *bdev = NULL;
+
 	spin_lock(&bdev_lock);
-	if (inode->i_bdev)
+	if (inode->i_bdev) {
+		if (inode->i_sb != blockdev_superblock)
+			bdev = inode->i_bdev;
 		__bd_forget(inode);
+	}
 	spin_unlock(&bdev_lock);
+
+	if (bdev)
+		iput(bdev->bd_inode);
 }
 
 int bd_claim(struct block_device *bdev, void *holder)
@@ -1077,7 +1095,7 @@
 	return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
 }
 
-struct address_space_operations def_blk_aops = {
+const struct address_space_operations def_blk_aops = {
 	.readpage	= blkdev_readpage,
 	.writepage	= blkdev_writepage,
 	.sync_page	= block_sync_page,
diff --git a/fs/buffer.c b/fs/buffer.c
index 23f1f3a..e999472 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -331,7 +331,6 @@
 		goto out;
 	}
 
-	current->flags |= PF_SYNCWRITE;
 	ret = filemap_fdatawrite(mapping);
 
 	/*
@@ -346,7 +345,6 @@
 	err = filemap_fdatawait(mapping);
 	if (!ret)
 		ret = err;
-	current->flags &= ~PF_SYNCWRITE;
 out:
 	return ret;
 }
@@ -566,7 +564,7 @@
  * Completion handler for block_write_full_page() - pages which are unlocked
  * during I/O, and which have PageWriteback cleared upon I/O completion.
  */
-void end_buffer_async_write(struct buffer_head *bh, int uptodate)
+static void end_buffer_async_write(struct buffer_head *bh, int uptodate)
 {
 	char b[BDEVNAME_SIZE];
 	unsigned long flags;
@@ -2600,7 +2598,7 @@
 	unsigned offset = from & (PAGE_CACHE_SIZE-1);
 	unsigned to;
 	struct page *page;
-	struct address_space_operations *a_ops = mapping->a_ops;
+	const struct address_space_operations *a_ops = mapping->a_ops;
 	char *kaddr;
 	int ret = 0;
 
@@ -3168,7 +3166,6 @@
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(block_write_full_page);
 EXPORT_SYMBOL(cont_prepare_write);
-EXPORT_SYMBOL(end_buffer_async_write);
 EXPORT_SYMBOL(end_buffer_read_sync);
 EXPORT_SYMBOL(end_buffer_write_sync);
 EXPORT_SYMBOL(file_fsync);
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 7271bb0..a61d17e 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,9 +1,24 @@
+Version 1.44
+------------
+Rewritten sessionsetup support, including support for legacy SMB
+session setup needed for OS/2 and older servers such as Windows 95 and 98.
+Fix oops on ls to OS/2 servers.  Add support for level 1 FindFirst
+so we can do search (ls etc.) to OS/2.  Do not send NTCreateX
+or recent levels of FindFirst unless server says it supports NT SMBs
+(instead use legacy equivalents from LANMAN dialect). Fix to allow
+NTLMv2 authentication support (now can use stronger password hashing
+on mount if corresponding /proc/fs/cifs/SecurityFlags is set (0x4004).
+Allow override of global cifs security flags on mount via "sec=" option(s).
+
 Version 1.43
 ------------
 POSIX locking to servers which support CIFS POSIX Extensions
 (disabled by default controlled by proc/fs/cifs/Experimental).
 Handle conversion of long share names (especially Asian languages)
-to Unicode during mount. 
+to Unicode during mount. Fix memory leak in sess struct on reconnect.
+Fix rare oops after acpi suspend.  Fix O_TRUNC opens to overwrite on
+cifs open which helps rare case when setpathinfo fails or server does
+not support it. 
 
 Version 1.42
 ------------
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 58c7725..a26f26e 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
 #
 obj-$(CONFIG_CIFS) += cifs.o
 
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o ntlmssp.o
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o fcntl.o readdir.o ioctl.o sess.o
diff --git a/fs/cifs/README b/fs/cifs/README
index 0355003..7986d0d 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -443,7 +443,10 @@
 		SFU does).  In the future the bottom 9 bits of the mode
 		mode also will be emulated using queries of the security
 		descriptor (ACL).
-sec		Security mode.  Allowed values are:
+ sign           Must use packet signing (helps avoid unwanted data modification
+		by intermediate systems in the route).  Note that signing
+		does not work with lanman or plaintext authentication.
+ sec            Security mode.  Allowed values are:
 			none	attempt to connection as a null user (no name)
 			krb5    Use Kerberos version 5 authentication
 			krb5i   Use Kerberos authentication and packet signing
@@ -453,6 +456,8 @@
 				server requires signing also can be the default) 
 			ntlmv2  Use NTLMv2 password hashing      
 			ntlmv2i Use NTLMv2 password hashing with packet signing
+			lanman  (if configured in kernel config) use older
+				lanman hash
 
 The mount.cifs mount helper also accepts a few mount options before -o
 including:
@@ -485,14 +490,34 @@
 			it.  If set to two, cifs packet signing is
 			required even if the server considers packet
 			signing optional. (default 1)
+SecurityFlags		Flags which control security negotiation and
+			also packet signing. Authentication (may/must)
+			flags (e.g. for NTLM and/or NTLMv2) may be combined with
+			the signing flags.  Specifying two different password
+			hashing mechanisms (as "must use") on the other hand 
+			does not make much sense. Default flags are 
+				0x07007 
+			(NTLM, NTLMv2 and packet signing allowed).  Maximum 
+			allowable flags if you want to allow mounts to servers
+			using weaker password hashes is 0x37037 (lanman,
+			plaintext, ntlm, ntlmv2, signing allowed):
+ 
+			may use packet signing 				0x00001
+			must use packet signing				0x01001
+			may use NTLM (most common password hash)	0x00002
+			must use NTLM					0x02002
+			may use NTLMv2					0x00004
+			must use NTLMv2					0x04004
+			may use Kerberos security (not implemented yet) 0x00008
+			must use Kerberos (not implemented yet)         0x08008
+			may use lanman (weak) password hash  		0x00010
+			must use lanman password hash			0x10010
+			may use plaintext passwords    			0x00020
+			must use plaintext passwords			0x20020
+			(reserved for future packet encryption)		0x00040
+
 cifsFYI			If set to one, additional debug information is
 			logged to the system error log. (default 0)
-ExtendedSecurity	If set to one, SPNEGO session establishment
-			is allowed which enables more advanced 
-			secure CIFS session establishment (default 0)
-NTLMV2Enabled		If set to one, more secure password hashes
-			are used when the server supports them and
-			when kerberos is not negotiated (default 0)
 traceSMB		If set to one, debug information is logged to the
 			system error log with the start of smb requests
 			and responses (default 0)
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index 086ae8f..031cdf2 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -467,7 +467,7 @@
 	asn1_open(&ctx, security_blob, length);
 
 	if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-		cFYI(1, ("Error decoding negTokenInit header "));
+		cFYI(1, ("Error decoding negTokenInit header"));
 		return 0;
 	} else if ((cls != ASN1_APL) || (con != ASN1_CON)
 		   || (tag != ASN1_EOC)) {
@@ -495,7 +495,7 @@
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("Error decoding negTokenInit "));
+			cFYI(1, ("Error decoding negTokenInit"));
 			return 0;
 		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 			   || (tag != ASN1_EOC)) {
@@ -505,7 +505,7 @@
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("Error decoding negTokenInit "));
+			cFYI(1, ("Error decoding negTokenInit"));
 			return 0;
 		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 			   || (tag != ASN1_SEQ)) {
@@ -515,7 +515,7 @@
 		}
 
 		if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("Error decoding 2nd part of negTokenInit "));
+			cFYI(1, ("Error decoding 2nd part of negTokenInit"));
 			return 0;
 		} else if ((cls != ASN1_CTX) || (con != ASN1_CON)
 			   || (tag != ASN1_EOC)) {
@@ -527,7 +527,7 @@
 
 		if (asn1_header_decode
 		    (&ctx, &sequence_end, &cls, &con, &tag) == 0) {
-			cFYI(1, ("Error decoding 2nd part of negTokenInit "));
+			cFYI(1, ("Error decoding 2nd part of negTokenInit"));
 			return 0;
 		} else if ((cls != ASN1_UNI) || (con != ASN1_CON)
 			   || (tag != ASN1_SEQ)) {
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index f4124a3..96abeb7 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -39,7 +39,7 @@
 	char *charptr = data;
 	char buf[10], line[80];
 
-	printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n\n", 
+	printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n", 
 		label, length, data);
 	for (i = 0; i < length; i += 16) {
 		line[0] = 0;
@@ -57,6 +57,57 @@
 	}
 }
 
+#ifdef CONFIG_CIFS_DEBUG2
+void cifs_dump_detail(struct smb_hdr * smb)
+{
+	cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
+		  smb->Command, smb->Status.CifsError,
+		  smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
+	cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
+}
+
+
+void cifs_dump_mids(struct TCP_Server_Info * server)
+{
+	struct list_head *tmp;
+	struct mid_q_entry * mid_entry;
+
+	if(server == NULL)
+		return;
+
+	cERROR(1,("Dump pending requests:"));
+	spin_lock(&GlobalMid_Lock);
+	list_for_each(tmp, &server->pending_mid_q) {
+		mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
+		if(mid_entry) {
+			cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
+				mid_entry->midState,
+				(int)mid_entry->command,
+				mid_entry->pid,
+				mid_entry->tsk,
+				mid_entry->mid));
+#ifdef CONFIG_CIFS_STATS2
+			cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld",
+				mid_entry->largeBuf,
+				mid_entry->resp_buf,
+				mid_entry->when_received,
+				jiffies));
+#endif /* STATS2 */
+			cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
+				  mid_entry->multiEnd));
+			if(mid_entry->resp_buf) {
+				cifs_dump_detail(mid_entry->resp_buf);
+				cifs_dump_mem("existing buf: ",
+					mid_entry->resp_buf,
+					62 /* fixme */);
+			}
+			
+		}
+	}
+	spin_unlock(&GlobalMid_Lock);
+}
+#endif /* CONFIG_CIFS_DEBUG2 */
+
 #ifdef CONFIG_PROC_FS
 static int
 cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
@@ -73,7 +124,6 @@
 
 	*beginBuffer = buf + offset;
 
-	
 	length =
 	    sprintf(buf,
 		    "Display Internal CIFS Data Structures for Debugging\n"
@@ -395,12 +445,12 @@
 static write_proc_t traceSMB_write;
 static read_proc_t multiuser_mount_read;
 static write_proc_t multiuser_mount_write;
-static read_proc_t extended_security_read;
-static write_proc_t extended_security_write;
-static read_proc_t ntlmv2_enabled_read;
+static read_proc_t security_flags_read;
+static write_proc_t security_flags_write;
+/* static read_proc_t ntlmv2_enabled_read;
 static write_proc_t ntlmv2_enabled_write;
 static read_proc_t packet_signing_enabled_read;
-static write_proc_t packet_signing_enabled_write;
+static write_proc_t packet_signing_enabled_write;*/
 static read_proc_t experimEnabled_read;
 static write_proc_t experimEnabled_write;
 static read_proc_t linuxExtensionsEnabled_read;
@@ -458,10 +508,10 @@
 		pde->write_proc = multiuser_mount_write;
 
 	pde =
-	    create_proc_read_entry("ExtendedSecurity", 0, proc_fs_cifs,
-				extended_security_read, NULL);
+	    create_proc_read_entry("SecurityFlags", 0, proc_fs_cifs,
+				security_flags_read, NULL);
 	if (pde)
-		pde->write_proc = extended_security_write;
+		pde->write_proc = security_flags_write;
 
 	pde =
 	create_proc_read_entry("LookupCacheEnabled", 0, proc_fs_cifs,
@@ -469,7 +519,7 @@
 	if (pde)
 		pde->write_proc = lookupFlag_write;
 
-	pde =
+/*	pde =
 	    create_proc_read_entry("NTLMV2Enabled", 0, proc_fs_cifs,
 				ntlmv2_enabled_read, NULL);
 	if (pde)
@@ -479,7 +529,7 @@
 	    create_proc_read_entry("PacketSigningEnabled", 0, proc_fs_cifs,
 				packet_signing_enabled_read, NULL);
 	if (pde)
-		pde->write_proc = packet_signing_enabled_write;
+		pde->write_proc = packet_signing_enabled_write;*/
 }
 
 void
@@ -496,9 +546,9 @@
 #endif
 	remove_proc_entry("MultiuserMount", proc_fs_cifs);
 	remove_proc_entry("OplockEnabled", proc_fs_cifs);
-	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs);
-	remove_proc_entry("ExtendedSecurity",proc_fs_cifs);
-	remove_proc_entry("PacketSigningEnabled",proc_fs_cifs);
+/*	remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
+	remove_proc_entry("SecurityFlags",proc_fs_cifs);
+/*	remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */
 	remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs);
 	remove_proc_entry("Experimental",proc_fs_cifs);
 	remove_proc_entry("LookupCacheEnabled",proc_fs_cifs);
@@ -782,12 +832,12 @@
 }
 
 static int
-extended_security_read(char *page, char **start, off_t off,
+security_flags_read(char *page, char **start, off_t off,
 		       int count, int *eof, void *data)
 {
 	int len;
 
-	len = sprintf(page, "%d\n", extended_security);
+	len = sprintf(page, "0x%x\n", extended_security);
 
 	len -= off;
 	*start = page + off;
@@ -803,24 +853,52 @@
 	return len;
 }
 static int
-extended_security_write(struct file *file, const char __user *buffer,
+security_flags_write(struct file *file, const char __user *buffer,
 			unsigned long count, void *data)
 {
+	unsigned int flags;
+	char flags_string[12];
 	char c;
-	int rc;
 
-	rc = get_user(c, buffer);
-	if (rc)
-		return rc;
-	if (c == '0' || c == 'n' || c == 'N')
-		extended_security = 0;
-	else if (c == '1' || c == 'y' || c == 'Y')
-		extended_security = 1;
+	if((count < 1) || (count > 11))
+		return -EINVAL;
 
+	memset(flags_string, 0, 12);
+
+	if(copy_from_user(flags_string, buffer, count))
+		return -EFAULT;
+
+	if(count < 3) {
+		/* single char or single char followed by null */
+		c = flags_string[0];
+		if (c == '0' || c == 'n' || c == 'N')
+			extended_security = CIFSSEC_DEF; /* default */
+		else if (c == '1' || c == 'y' || c == 'Y')
+			extended_security = CIFSSEC_MAX;
+		return count;
+	}
+	/* else we have a number */
+
+	flags = simple_strtoul(flags_string, NULL, 0);
+
+	cFYI(1,("sec flags 0x%x", flags));
+
+	if(flags <= 0)  {
+		cERROR(1,("invalid security flags %s",flags_string));
+		return -EINVAL;
+	}
+
+	if(flags & ~CIFSSEC_MASK) {
+		cERROR(1,("attempt to set unsupported security flags 0x%x",
+			flags & ~CIFSSEC_MASK));
+		return -EINVAL;
+	}
+	/* flags look ok - update the global security flags for cifs module */
+	extended_security = flags;
 	return count;
 }
 
-static int
+/* static int
 ntlmv2_enabled_read(char *page, char **start, off_t off,
 		       int count, int *eof, void *data)
 {
@@ -855,6 +933,8 @@
 		ntlmv2_support = 0;
 	else if (c == '1' || c == 'y' || c == 'Y')
 		ntlmv2_support = 1;
+	else if (c == '2')
+		ntlmv2_support = 2;
 
 	return count;
 }
@@ -898,7 +978,7 @@
 		sign_CIFS_PDUs = 2;
 
 	return count;
-}
+} */
 
 
 #endif
diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h
index 4304d9d..c26cd0d 100644
--- a/fs/cifs/cifs_debug.h
+++ b/fs/cifs/cifs_debug.h
@@ -24,6 +24,10 @@
 #define _H_CIFS_DEBUG
 
 void cifs_dump_mem(char *label, void *data, int length);
+#ifdef CONFIG_CIFS_DEBUG2
+void cifs_dump_detail(struct smb_hdr *);
+void cifs_dump_mids(struct TCP_Server_Info *);
+#endif
 extern int traceSMB;		/* flag which enables the function below */
 void dump_smb(struct smb_hdr *, int);
 #define CIFS_INFO	0x01
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index d2b1282..d2a8b29 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -22,6 +22,7 @@
 #include "cifs_unicode.h"
 #include "cifs_uniupr.h"
 #include "cifspdu.h"
+#include "cifsglob.h"
 #include "cifs_debug.h"
 
 /*
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index e7d6373..a89efaf 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -26,6 +26,8 @@
 #include "md5.h"
 #include "cifs_unicode.h"
 #include "cifsproto.h"
+#include <linux/ctype.h>
+#include <linux/random.h>
 
 /* Calculate and return the CIFS signature based on the mac key and the smb pdu */
 /* the 16 byte signature must be allocated by the caller  */
@@ -35,6 +37,8 @@
 
 extern void mdfour(unsigned char *out, unsigned char *in, int n);
 extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
+                       unsigned char *p24);
 	
 static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, 
 				    const char * key, char * signature)
@@ -45,7 +49,7 @@
 		return -EINVAL;
 
 	MD5Init(&context);
-	MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+	MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
 	MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
 	MD5Final(signature,&context);
 	return 0;
@@ -90,7 +94,7 @@
 		return -EINVAL;
 
 	MD5Init(&context);
-	MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+	MD5Update(&context,key,CIFS_SESS_KEY_SIZE+16);
 	for(i=0;i<n_vec;i++) {
 		if(iov[i].iov_base == NULL) {
 			cERROR(1,("null iovec entry"));
@@ -204,11 +208,12 @@
 
 	E_md4hash(password, temp_key);
 	mdfour(key,temp_key,16);
-	memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
+	memcpy(key+16,rn, CIFS_SESS_KEY_SIZE);
 	return 0;
 }
 
-int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_info)
+int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, 
+				const struct nls_table * nls_info)
 {
 	char temp_hash[16];
 	struct HMACMD5Context ctx;
@@ -225,6 +230,8 @@
 	user_name_len = strlen(ses->userName);
 	if(user_name_len > MAX_USERNAME_SIZE)
 		return -EINVAL;
+	if(ses->domainName == NULL)
+		return -EINVAL; /* BB should we use CIFS_LINUX_DOM */
 	dom_name_len = strlen(ses->domainName);
 	if(dom_name_len > MAX_USERNAME_SIZE)
 		return -EINVAL;
@@ -259,16 +266,131 @@
 	kfree(unicode_buf);
 	return 0;
 }
-void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_response)
+
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key)
+{
+	int i;
+	char password_with_pad[CIFS_ENCPWD_SIZE];
+
+	if(ses->server == NULL)
+		return;
+
+	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
+	strncpy(password_with_pad, ses->password, CIFS_ENCPWD_SIZE);
+
+	if((ses->server->secMode & SECMODE_PW_ENCRYPT) == 0)
+		if(extended_security & CIFSSEC_MAY_PLNTXT) {
+			memcpy(lnm_session_key, password_with_pad, CIFS_ENCPWD_SIZE); 
+			return;
+		}
+
+	/* calculate old style session key */
+	/* calling toupper is less broken than repeatedly
+	calling nls_toupper would be since that will never
+	work for UTF8, but neither handles multibyte code pages
+	but the only alternative would be converting to UCS-16 (Unicode)
+	(using a routine something like UniStrupr) then
+	uppercasing and then converting back from Unicode - which
+	would only worth doing it if we knew it were utf8. Basically
+	utf8 and other multibyte codepages each need their own strupper
+	function since a byte at a time will ont work. */
+
+	for(i = 0; i < CIFS_ENCPWD_SIZE; i++) {
+		password_with_pad[i] = toupper(password_with_pad[i]);
+	}
+
+	SMBencrypt(password_with_pad, ses->server->cryptKey, lnm_session_key);
+	/* clear password before we return/free memory */
+	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
+}
+#endif /* CIFS_WEAK_PW_HASH */
+
+static int calc_ntlmv2_hash(struct cifsSesInfo *ses, 
+			    const struct nls_table * nls_cp)
+{
+	int rc = 0;
+	int len;
+	char nt_hash[16];
+	struct HMACMD5Context * pctxt;
+	wchar_t * user;
+	wchar_t * domain;
+
+	pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
+
+	if(pctxt == NULL)
+		return -ENOMEM;
+
+	/* calculate md4 hash of password */
+	E_md4hash(ses->password, nt_hash);
+
+	/* convert Domainname to unicode and uppercase */
+	hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
+
+	/* convert ses->userName to unicode and uppercase */
+	len = strlen(ses->userName);
+	user = kmalloc(2 + (len * 2), GFP_KERNEL);
+	if(user == NULL)
+		goto calc_exit_2;
+	len = cifs_strtoUCS(user, ses->userName, len, nls_cp);
+	UniStrupr(user);
+	hmac_md5_update((char *)user, 2*len, pctxt);
+
+	/* convert ses->domainName to unicode and uppercase */
+	if(ses->domainName) {
+		len = strlen(ses->domainName);
+
+        	domain = kmalloc(2 + (len * 2), GFP_KERNEL);
+		if(domain == NULL)
+			goto calc_exit_1;
+		len = cifs_strtoUCS(domain, ses->domainName, len, nls_cp);
+		UniStrupr(domain);
+
+		hmac_md5_update((char *)domain, 2*len, pctxt);
+	
+		kfree(domain);
+	}
+calc_exit_1:
+	kfree(user);
+calc_exit_2:
+	/* BB FIXME what about bytes 24 through 40 of the signing key? 
+	   compare with the NTLM example */
+	hmac_md5_final(ses->server->mac_signing_key, pctxt);
+
+	return rc;
+}
+
+void setup_ntlmv2_rsp(struct cifsSesInfo * ses, char * resp_buf, 
+		      const struct nls_table * nls_cp)
+{
+	int rc;
+	struct ntlmv2_resp * buf = (struct ntlmv2_resp *)resp_buf;
+
+	buf->blob_signature = cpu_to_le32(0x00000101);
+	buf->reserved = 0;
+	buf->time = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+	get_random_bytes(&buf->client_chal, sizeof(buf->client_chal));
+	buf->reserved2 = 0;
+	buf->names[0].type = 0;
+	buf->names[0].length = 0;
+
+	/* calculate buf->ntlmv2_hash */
+	rc = calc_ntlmv2_hash(ses, nls_cp);
+	if(rc)
+		cERROR(1,("could not get v2 hash rc %d",rc));
+	CalcNTLMv2_response(ses, resp_buf);
+}
+
+void CalcNTLMv2_response(const struct cifsSesInfo * ses, char * v2_session_response)
 {
 	struct HMACMD5Context context;
+	/* rest of v2 struct already generated */
 	memcpy(v2_session_response + 8, ses->server->cryptKey,8);
-	/* gen_blob(v2_session_response + 16); */
 	hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context);
 
-	hmac_md5_update(ses->server->cryptKey,8,&context);
-/*	hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */
+	hmac_md5_update(v2_session_response+8, 
+			sizeof(struct ntlmv2_resp) - 8, &context);
 
 	hmac_md5_final(v2_session_response,&context);
-	cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); /* BB removeme BB */
+/*	cifs_dump_mem("v2_sess_rsp: ", v2_session_response, 32); */
 }
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index c262d88..c28ede5 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -56,8 +56,8 @@
 unsigned int linuxExtEnabled = 1;
 unsigned int lookupCacheEnabled = 1;
 unsigned int multiuser_mount = 0;
-unsigned int extended_security = 0;
-unsigned int ntlmv2_support = 0;
+unsigned int extended_security = CIFSSEC_DEF;
+/* unsigned int ntlmv2_support = 0; */
 unsigned int sign_CIFS_PDUs = 1;
 extern struct task_struct * oplockThread; /* remove sparse warning */
 struct task_struct * oplockThread = NULL;
@@ -166,8 +166,9 @@
 }
 
 static int
-cifs_statfs(struct super_block *sb, struct kstatfs *buf)
+cifs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
 	int xid; 
 	int rc = -EOPNOTSUPP;
 	struct cifs_sb_info *cifs_sb;
@@ -402,12 +403,14 @@
 #endif
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
-static void cifs_umount_begin(struct super_block * sblock)
+static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 {
 	struct cifs_sb_info *cifs_sb;
 	struct cifsTconInfo * tcon;
 
-	cifs_sb = CIFS_SB(sblock);
+	if (!(flags & MNT_FORCE))
+		return;
+	cifs_sb = CIFS_SB(vfsmnt->mnt_sb);
 	if(cifs_sb == NULL)
 		return;
 
@@ -460,9 +463,9 @@
 	.remount_fs = cifs_remount,
 };
 
-static struct super_block *
+static int
 cifs_get_sb(struct file_system_type *fs_type,
-	    int flags, const char *dev_name, void *data)
+	    int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
 	int rc;
 	struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL);
@@ -470,7 +473,7 @@
 	cFYI(1, ("Devname: %s flags: %d ", dev_name, flags));
 
 	if (IS_ERR(sb))
-		return sb;
+		return PTR_ERR(sb);
 
 	sb->s_flags = flags;
 
@@ -478,10 +481,10 @@
 	if (rc) {
 		up_write(&sb->s_umount);
 		deactivate_super(sb);
-		return ERR_PTR(rc);
+		return rc;
 	}
 	sb->s_flags |= MS_ACTIVE;
-	return sb;
+	return simple_set_mnt(mnt, sb);
 }
 
 static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov,
@@ -905,7 +908,7 @@
 	struct cifsSesInfo *ses;
 
 	do {
-		if(try_to_freeze())
+		if (try_to_freeze())
 			continue;
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(15*HZ);
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index c98755d..8f75c6f 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -32,7 +32,8 @@
 #define TRUE 1
 #endif
 
-extern struct address_space_operations cifs_addr_ops;
+extern const struct address_space_operations cifs_addr_ops;
+extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
 /* Functions related to super block operations */
 extern struct super_operations cifs_super_ops;
@@ -74,7 +75,7 @@
 			 size_t write_size, loff_t * poffset);
 extern int cifs_lock(struct file *, int, struct file_lock *);
 extern int cifs_fsync(struct file *, struct dentry *, int);
-extern int cifs_flush(struct file *);
+extern int cifs_flush(struct file *, fl_owner_t id);
 extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
 extern const struct file_operations cifs_dir_ops;
 extern int cifs_dir_open(struct inode *inode, struct file *file);
@@ -99,5 +100,5 @@
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 		       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.43"
+#define CIFS_VERSION   "1.44"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 006eb33..6d7cf5f 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -88,7 +88,8 @@
 };
 
 enum securityEnum {
-	NTLM = 0,		/* Legacy NTLM012 auth with NTLM hash */
+	LANMAN = 0,             /* Legacy LANMAN auth */
+	NTLM,			/* Legacy NTLM012 auth with NTLM hash */
 	NTLMv2,			/* Legacy NTLM auth with NTLMv2 hash */
 	RawNTLMSSP,		/* NTLMSSP without SPNEGO */
 	NTLMSSP,		/* NTLMSSP via SPNEGO */
@@ -157,7 +158,7 @@
 	/* 16th byte of RFC1001 workstation name is always null */
 	char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
 	__u32 sequence_number; /* needed for CIFS PDU signature */
-	char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; 
+	char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; 
 };
 
 /*
@@ -179,10 +180,13 @@
 struct cifsSesInfo {
 	struct list_head cifsSessionList;
 	struct semaphore sesSem;
+#if 0
 	struct cifsUidInfo *uidInfo;	/* pointer to user info */
+#endif
 	struct TCP_Server_Info *server;	/* pointer to server info */
 	atomic_t inUse; /* # of mounts (tree connections) on this ses */
 	enum statusEnum status;
+	unsigned overrideSecFlg;  /* if non-zero override global sec flags */
 	__u16 ipc_tid;		/* special tid for connection to IPC share */
 	__u16 flags;
 	char *serverOS;		/* name of operating system underlying server */
@@ -194,7 +198,7 @@
 	char serverName[SERVER_NAME_LEN_WITH_NULL * 2];	/* BB make bigger for 
 				TCP names - will ipv6 and sctp addresses fit? */
 	char userName[MAX_USERNAME_SIZE + 1];
-	char domainName[MAX_USERNAME_SIZE + 1];
+	char * domainName;
 	char * password;
 };
 /* session flags */
@@ -209,12 +213,12 @@
 	struct list_head openFileList;
 	struct semaphore tconSem;
 	struct cifsSesInfo *ses;	/* pointer to session associated with */
-	char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource (in ASCII not UTF) */
+	char treeName[MAX_TREE_SIZE + 1]; /* UNC name of resource in ASCII */
 	char *nativeFileSystem;
 	__u16 tid;		/* The 2 byte tree id */
 	__u16 Flags;		/* optional support bits */
 	enum statusEnum tidStatus;
-	atomic_t useCount;	/* how many mounts (explicit or implicit) to this share */
+	atomic_t useCount;	/* how many explicit/implicit mounts to share */
 #ifdef CONFIG_CIFS_STATS
 	atomic_t num_smbs_sent;
 	atomic_t num_writes;
@@ -254,7 +258,7 @@
 	spinlock_t stat_lock;
 #endif /* CONFIG_CIFS_STATS */
 	FILE_SYSTEM_DEVICE_INFO fsDevInfo;
-	FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo;	/* ok if file system name truncated */
+	FILE_SYSTEM_ATTRIBUTE_INFO fsAttrInfo; /* ok if fs name truncated */
 	FILE_SYSTEM_UNIX_INFO fsUnixInfo;
 	unsigned retry:1;
 	unsigned nocase:1;
@@ -305,7 +309,6 @@
 	atomic_t wrtPending;   /* handle in use - defer close */
 	struct semaphore fh_sem; /* prevents reopen race after dead ses*/
 	char * search_resume_name; /* BB removeme BB */
-	unsigned int resume_name_length; /* BB removeme - field renamed and moved BB */
 	struct cifs_search_info srch_inf;
 };
 
@@ -391,9 +394,9 @@
 	struct smb_hdr *resp_buf;	/* response buffer */
 	int midState;	/* wish this were enum but can not pass to wait_event */
 	__u8 command;	/* smb command code */
-	unsigned multiPart:1;	/* multiple responses to one SMB request */
 	unsigned largeBuf:1;    /* if valid response, is pointer to large buf */
-	unsigned multiResp:1;   /* multiple trans2 responses for one request  */
+	unsigned multiRsp:1;   /* multiple trans2 responses for one request  */
+	unsigned multiEnd:1; /* both received */
 };
 
 struct oplock_q_entry {
@@ -430,15 +433,35 @@
 #define   CIFS_LARGE_BUFFER     2
 #define   CIFS_IOVEC            4    /* array of response buffers */
 
-/* Type of session setup needed */
-#define   CIFS_PLAINTEXT	0
-#define   CIFS_LANMAN		1
-#define   CIFS_NTLM		2
-#define   CIFS_NTLMSSP_NEG	3
-#define   CIFS_NTLMSSP_AUTH	4
-#define   CIFS_SPNEGO_INIT	5
-#define   CIFS_SPNEGO_TARG	6
+/* Security Flags: indicate type of session setup needed */
+#define   CIFSSEC_MAY_SIGN	0x00001
+#define   CIFSSEC_MAY_NTLM	0x00002
+#define   CIFSSEC_MAY_NTLMV2	0x00004
+#define   CIFSSEC_MAY_KRB5	0x00008
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+#define   CIFSSEC_MAY_LANMAN	0x00010
+#define   CIFSSEC_MAY_PLNTXT	0x00020
+#endif /* weak passwords */
+#define   CIFSSEC_MAY_SEAL	0x00040 /* not supported yet */
 
+#define   CIFSSEC_MUST_SIGN	0x01001
+/* note that only one of the following can be set so the
+result of setting MUST flags more than once will be to
+require use of the stronger protocol */
+#define   CIFSSEC_MUST_NTLM	0x02002
+#define   CIFSSEC_MUST_NTLMV2	0x04004
+#define   CIFSSEC_MUST_KRB5	0x08008
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+#define   CIFSSEC_MUST_LANMAN	0x10010
+#define   CIFSSEC_MUST_PLNTXT	0x20020
+#define   CIFSSEC_MASK          0x37037 /* current flags supported if weak */
+#else	  
+#define	  CIFSSEC_MASK          0x07007 /* flags supported if no weak config */
+#endif /* WEAK_PW_HASH */
+#define   CIFSSEC_MUST_SEAL	0x40040 /* not supported yet */
+
+#define   CIFSSEC_DEF  CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2
+#define   CIFSSEC_MAX  CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2
 /*
  *****************************************************************
  * All constants go here
@@ -500,16 +523,16 @@
 GLOBAL_EXTERN struct list_head GlobalOplock_Q;
 
 GLOBAL_EXTERN struct list_head GlobalDnotifyReqList; /* Outstanding dir notify requests */
-GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q; /* Dir notify response queue */
+GLOBAL_EXTERN struct list_head GlobalDnotifyRsp_Q;/* DirNotify response queue */
 
 /*
  * Global transaction id (XID) information
  */
 GLOBAL_EXTERN unsigned int GlobalCurrentXid;	/* protected by GlobalMid_Sem */
-GLOBAL_EXTERN unsigned int GlobalTotalActiveXid;	/* prot by GlobalMid_Sem */
+GLOBAL_EXTERN unsigned int GlobalTotalActiveXid; /* prot by GlobalMid_Sem */
 GLOBAL_EXTERN unsigned int GlobalMaxActiveXid;	/* prot by GlobalMid_Sem */
-GLOBAL_EXTERN spinlock_t GlobalMid_Lock;  /* protects above and list operations */
-					/* on midQ entries */
+GLOBAL_EXTERN spinlock_t GlobalMid_Lock;  /* protects above & list operations */
+					  /* on midQ entries */
 GLOBAL_EXTERN char Local_System_Name[15];
 
 /*
@@ -531,7 +554,7 @@
 GLOBAL_EXTERN atomic_t midCount;
 
 /* Misc globals */
-GLOBAL_EXTERN unsigned int multiuser_mount;	/* if enabled allows new sessions
+GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
 				to be established on existing mount if we
 				have the uid/password or Kerberos credential 
 				or equivalent for current user */
@@ -540,8 +563,8 @@
 GLOBAL_EXTERN unsigned int lookupCacheEnabled;
 GLOBAL_EXTERN unsigned int extended_security;	/* if on, session setup sent 
 				with more secure ntlmssp2 challenge/resp */
-GLOBAL_EXTERN unsigned int ntlmv2_support;  /* better optional password hash */
 GLOBAL_EXTERN unsigned int sign_CIFS_PDUs;  /* enable smb packet signing */
+GLOBAL_EXTERN unsigned int secFlags;
 GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/
 GLOBAL_EXTERN unsigned int CIFSMaxBufSize;  /* max size not including hdr */
 GLOBAL_EXTERN unsigned int cifs_min_rcv;    /* min size of big ntwrk buf pool */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index b2233ac..8623902 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -16,7 +16,7 @@
  *
  *   You should have received a copy of the GNU Lesser General Public License
  *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #ifndef _CIFSPDU_H
@@ -24,8 +24,14 @@
 
 #include <net/sock.h>
 
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+#define LANMAN_PROT 0
+#define CIFS_PROT   1
+#else
 #define CIFS_PROT   0
-#define BAD_PROT    CIFS_PROT+1
+#endif
+#define POSIX_PROT  CIFS_PROT+1
+#define BAD_PROT 0xFFFF
 
 /* SMB command codes */
 /* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
@@ -110,7 +116,7 @@
 /*
  * Size of the session key (crypto key encrypted with the password
  */
-#define CIFS_SESSION_KEY_SIZE (24)
+#define CIFS_SESS_KEY_SIZE (24)
 
 /*
  * Maximum user name length
@@ -400,6 +406,29 @@
 	unsigned char DialectsArray[1];
 } __attribute__((packed)) NEGOTIATE_REQ;
 
+/* Dialect index is 13 for LANMAN */
+
+typedef struct lanman_neg_rsp {
+	struct smb_hdr hdr;	/* wct = 13 */
+	__le16 DialectIndex;
+	__le16 SecurityMode;
+	__le16 MaxBufSize;
+	__le16 MaxMpxCount;
+	__le16 MaxNumberVcs;
+	__le16 RawMode;
+	__le32 SessionKey;
+	__le32 ServerTime;
+	__le16 ServerTimeZone;
+	__le16 EncryptionKeyLength;
+	__le16 Reserved;
+	__u16  ByteCount;
+	unsigned char EncryptionKey[1];
+} __attribute__((packed)) LANMAN_NEG_RSP;
+
+#define READ_RAW_ENABLE 1
+#define WRITE_RAW_ENABLE 2
+#define RAW_ENABLE (READ_RAW_ENABLE | WRITE_RAW_ENABLE)
+
 typedef struct negotiate_rsp {
 	struct smb_hdr hdr;	/* wct = 17 */
 	__le16 DialectIndex;
@@ -509,7 +538,7 @@
 /*      unsigned char  * NativeOS;      */
 /*	unsigned char  * NativeLanMan;  */
 /*      unsigned char  * PrimaryDomain; */
-	} __attribute__((packed)) resp;			/* NTLM response format (with or without extended security */
+	} __attribute__((packed)) resp;	/* NTLM response with or without extended sec*/
 
 	struct {		/* request format */
 		struct smb_hdr hdr;	/* wct = 10 */
@@ -520,8 +549,8 @@
 		__le16 MaxMpxCount;
 		__le16 VcNumber;
 		__u32 SessionKey;
-		__le16 PassswordLength;
-		__u32 Reserved;
+		__le16 PasswordLength;
+		__u32 Reserved; /* encrypt key len and offset */
 		__le16 ByteCount;
 		unsigned char AccountPassword[1];	/* followed by */
 		/* STRING AccountName */
@@ -543,6 +572,26 @@
 	} __attribute__((packed)) old_resp; /* pre-NTLM (LANMAN2.1) response */
 } __attribute__((packed)) SESSION_SETUP_ANDX;
 
+/* format of NLTMv2 Response ie "case sensitive password" hash when NTLMv2 */
+
+struct ntlmssp2_name {
+	__le16 type;
+	__le16 length;
+/*	char   name[length]; */
+} __attribute__((packed));
+
+struct ntlmv2_resp {
+	char ntlmv2_hash[CIFS_ENCPWD_SIZE];
+	__le32 blob_signature;
+	__u32  reserved;
+	__le64  time;
+	__u64  client_chal; /* random */
+	__u32  reserved2;
+	struct ntlmssp2_name names[1];
+	/* array of name entries could follow ending in minimum 4 byte struct */
+} __attribute__((packed));
+
+
 #define CIFS_NETWORK_OPSYS "CIFS VFS Client for Linux"
 
 /* Capabilities bits (for NTLM SessSetup request) */
@@ -573,7 +622,9 @@
 } __attribute__((packed)) TCONX_REQ;
 
 typedef struct smb_com_tconx_rsp {
-	struct smb_hdr hdr;	/* wct = 3 *//* note that Win2000 has sent wct=7 in some cases on responses. Four unspecified words followed OptionalSupport */
+	struct smb_hdr hdr;	/* wct = 3 note that Win2000 has sent wct = 7
+				 in some cases on responses. Four unspecified
+				 words followed OptionalSupport */
 	__u8 AndXCommand;
 	__u8 AndXReserved;
 	__le16 AndXOffset;
@@ -1323,6 +1374,9 @@
 #define SMB_FILE_MAXIMUM_INFO           0x40d
 
 /* Find File infolevels */
+#define SMB_FIND_FILE_INFO_STANDARD       0x001
+#define SMB_FIND_FILE_QUERY_EA_SIZE       0x002
+#define SMB_FIND_FILE_QUERY_EAS_FROM_LIST 0x003
 #define SMB_FIND_FILE_DIRECTORY_INFO      0x101
 #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102
 #define SMB_FIND_FILE_NAMES_INFO          0x103
@@ -1844,13 +1898,13 @@
 typedef struct {
 	__le32 DeviceType;
 	__le32 DeviceCharacteristics;
-} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO;	/* device info, level 0x104 */
+} __attribute__((packed)) FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
 
 typedef struct {
 	__le32 Attributes;
 	__le32 MaxPathNameComponentLength;
 	__le32 FileSystemNameLen;
-	char FileSystemName[52]; /* do not really need to save this - so potentially get only subset of name */
+	char FileSystemName[52]; /* do not have to save this - get subset? */
 } __attribute__((packed)) FILE_SYSTEM_ATTRIBUTE_INFO;
 
 /******************************************************************************/
@@ -1947,7 +2001,8 @@
 
 struct file_allocation_info {
 	__le64 AllocationSize; /* Note old Samba srvr rounds this up too much */
-} __attribute__((packed));	/* size used on disk, level 0x103 for set, 0x105 for query */
+} __attribute__((packed));	/* size used on disk, for level 0x103 for set,
+				   0x105 for query */
 
 struct file_end_of_file_info {
 	__le64 FileSize;		/* offset to end of file */
@@ -2054,7 +2109,7 @@
 	__le32 ExtFileAttributes;
 	__le32 FileNameLength;
 	char FileName[1];
-} __attribute__((packed)) FILE_DIRECTORY_INFO;   /* level 0x101 FF response data area */
+} __attribute__((packed)) FILE_DIRECTORY_INFO;   /* level 0x101 FF resp data */
 
 typedef struct {
 	__le32 NextEntryOffset;
@@ -2069,7 +2124,7 @@
 	__le32 FileNameLength;
 	__le32 EaSize; /* length of the xattrs */
 	char FileName[1];
-} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO;   /* level 0x102 FF response data area */
+} __attribute__((packed)) FILE_FULL_DIRECTORY_INFO; /* level 0x102 rsp data */
 
 typedef struct {
 	__le32 NextEntryOffset;
@@ -2086,7 +2141,7 @@
 	__le32 Reserved;
 	__u64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
 	char FileName[1];
-} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO;   /* level 0x105 FF response data area */
+} __attribute__((packed)) SEARCH_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
 
 typedef struct {
 	__le32 NextEntryOffset;
@@ -2104,7 +2159,22 @@
 	__u8   Reserved;
 	__u8   ShortName[12];
 	char FileName[1];
-} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO;   /* level 0x104 FF response data area */
+} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */
+
+typedef struct {
+	__u32  ResumeKey;
+	__le16 CreationDate; /* SMB Date */
+	__le16 CreationTime; /* SMB Time */
+	__le16 LastAccessDate;
+	__le16 LastAccessTime;
+	__le16 LastWriteDate;
+	__le16 LastWriteTime;
+	__le32 DataSize; /* File Size (EOF) */
+	__le32 AllocationSize;
+	__le16 Attributes; /* verify not u32 */
+	__u8   FileNameLength;
+	char FileName[1];
+} __attribute__((packed)) FIND_FILE_STANDARD_INFO; /* level 0x1 FF resp data */
 
 
 struct win_dev {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 310ea2f..a5ddc62 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -64,14 +64,12 @@
 extern void header_assemble(struct smb_hdr *, char /* command */ ,
 			    const struct cifsTconInfo *, int /* length of
 			    fixed section (word count) in two byte units */);
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
 				struct cifsSesInfo *ses,
 				void ** request_buf);
 extern int CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses,
-			     const int stage, int * pNTLMv2_flg,
+			     const int stage, 
 			     const struct nls_table *nls_cp);
-#endif
 extern __u16 GetNextMid(struct TCP_Server_Info *server);
 extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, 
 						 struct cifsTconInfo *);
@@ -285,8 +283,14 @@
 extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key,
 	__u32 expected_sequence_number);
 extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
-extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, struct nls_table *);
-extern void CalcNTLMv2_response(const struct cifsSesInfo *,char * );
+extern int CalcNTLMv2_partial_mac_key(struct cifsSesInfo *, 
+			const struct nls_table *);
+extern void CalcNTLMv2_response(const struct cifsSesInfo *, char * );
+extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *, 
+			     const struct nls_table *);
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+extern void calc_lanman_hash(struct cifsSesInfo * ses, char * lnm_session_key);
+#endif /* CIFS_WEAK_PW_HASH */
 extern int CIFSSMBCopy(int xid,
 			struct cifsTconInfo *source_tcon,
 			const char *fromName,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 925881e..19678c5 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -44,8 +44,11 @@
 	int index;
 	char *name;
 } protocols[] = {
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+	{LANMAN_PROT, "\2LM1.2X002"},
+#endif /* weak password hashing for legacy clients */
 	{CIFS_PROT, "\2NT LM 0.12"}, 
-	{CIFS_PROT, "\2POSIX 2"},
+	{POSIX_PROT, "\2POSIX 2"},
 	{BAD_PROT, "\2"}
 };
 #else
@@ -53,11 +56,29 @@
 	int index;
 	char *name;
 } protocols[] = {
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+	{LANMAN_PROT, "\2LM1.2X002"},
+#endif /* weak password hashing for legacy clients */
 	{CIFS_PROT, "\2NT LM 0.12"}, 
 	{BAD_PROT, "\2"}
 };
 #endif
 
+/* define the number of elements in the cifs dialect array */
+#ifdef CONFIG_CIFS_POSIX
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+#define CIFS_NUM_PROT 3
+#else
+#define CIFS_NUM_PROT 2
+#endif /* CIFS_WEAK_PW_HASH */
+#else /* not posix */
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+#define CIFS_NUM_PROT 2
+#else
+#define CIFS_NUM_PROT 1
+#endif /* CONFIG_CIFS_WEAK_PW_HASH */
+#endif /* CIFS_POSIX */
+
 
 /* Mark as invalid, all open files on tree connections since they
    were closed when session to server was lost */
@@ -188,7 +209,6 @@
 	return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL  
 int
 small_smb_init_no_tc(const int smb_command, const int wct, 
 		     struct cifsSesInfo *ses, void **request_buf)
@@ -214,7 +234,6 @@
 
 	return rc;
 }
-#endif  /* CONFIG_CIFS_EXPERIMENTAL */
 
 /* If the return code is zero, this function must fill in request_buf pointer */
 static int
@@ -322,7 +341,8 @@
     /* potential retries of smb operations it turns out we can determine */
     /* from the mid flags when the request buffer can be resent without  */
     /* having to use a second distinct buffer for the response */
-	*response_buf = *request_buf; 
+	if(response_buf)
+		*response_buf = *request_buf; 
 
 	header_assemble((struct smb_hdr *) *request_buf, smb_command, tcon,
 			wct /*wct */ );
@@ -373,8 +393,10 @@
 	NEGOTIATE_RSP *pSMBr;
 	int rc = 0;
 	int bytes_returned;
+	int i;
 	struct TCP_Server_Info * server;
 	u16 count;
+	unsigned int secFlags;
 
 	if(ses->server)
 		server = ses->server;
@@ -386,101 +408,200 @@
 		      (void **) &pSMB, (void **) &pSMBr);
 	if (rc)
 		return rc;
+
+	/* if any of auth flags (ie not sign or seal) are overriden use them */
+	if(ses->overrideSecFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL)))
+		secFlags = ses->overrideSecFlg;
+	else /* if override flags set only sign/seal OR them with global auth */
+		secFlags = extended_security | ses->overrideSecFlg;
+
+	cFYI(1,("secFlags 0x%x",secFlags));
+
 	pSMB->hdr.Mid = GetNextMid(server);
 	pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
-	if (extended_security)
+	if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
 		pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
-
-	count = strlen(protocols[0].name) + 1;
-	strncpy(pSMB->DialectsArray, protocols[0].name, 30);	
-    /* null guaranteed to be at end of source and target buffers anyway */
-
+	
+	count = 0;
+	for(i=0;i<CIFS_NUM_PROT;i++) {
+		strncpy(pSMB->DialectsArray+count, protocols[i].name, 16);
+		count += strlen(protocols[i].name) + 1;
+		/* null at end of source and target buffers anyway */
+	}
 	pSMB->hdr.smb_buf_length += count;
 	pSMB->ByteCount = cpu_to_le16(count);
 
 	rc = SendReceive(xid, ses, (struct smb_hdr *) pSMB,
 			 (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-	if (rc == 0) {
-		server->secMode = pSMBr->SecurityMode;
-		if((server->secMode & SECMODE_USER) == 0)
-			cFYI(1,("share mode security"));
-		server->secType = NTLM; /* BB override default for
-					   NTLMv2 or kerberos v5 */
-		/* one byte - no need to convert this or EncryptionKeyLen
-		   from little endian */
-		server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
-		/* probably no need to store and check maxvcs */
-		server->maxBuf =
-			min(le32_to_cpu(pSMBr->MaxBufferSize),
-			(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
-		server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
-		cFYI(0, ("Max buf = %d", ses->server->maxBuf));
-		GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
-		server->capabilities = le32_to_cpu(pSMBr->Capabilities);
-		server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);	
-        /* BB with UTC do we ever need to be using srvr timezone? */
-		if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
-			memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
-			       CIFS_CRYPTO_KEY_SIZE);
-		} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
-			   && (pSMBr->EncryptionKeyLength == 0)) {
-			/* decode security blob */
-		} else
-			rc = -EIO;
+	if (rc != 0) 
+		goto neg_err_exit;
 
-		/* BB might be helpful to save off the domain of server here */
+	cFYI(1,("Dialect: %d", pSMBr->DialectIndex));
+	/* Check wct = 1 error case */
+	if((pSMBr->hdr.WordCount < 13) || (pSMBr->DialectIndex == BAD_PROT)) {
+		/* core returns wct = 1, but we do not ask for core - otherwise
+		small wct just comes when dialect index is -1 indicating we 
+		could not negotiate a common dialect */
+		rc = -EOPNOTSUPP;
+		goto neg_err_exit;
+#ifdef CONFIG_CIFS_WEAK_PW_HASH 
+	} else if((pSMBr->hdr.WordCount == 13)
+			&& (pSMBr->DialectIndex == LANMAN_PROT)) {
+		struct lanman_neg_rsp * rsp = (struct lanman_neg_rsp *)pSMBr;
 
-		if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
-			(server->capabilities & CAP_EXTENDED_SECURITY)) {
-			count = pSMBr->ByteCount;
-			if (count < 16)
-				rc = -EIO;
-			else if (count == 16) {
-				server->secType = RawNTLMSSP;
-				if (server->socketUseCount.counter > 1) {
-					if (memcmp
-						(server->server_GUID,
-						pSMBr->u.extended_response.
-						GUID, 16) != 0) {
-						cFYI(1, ("server UID changed"));
-						memcpy(server->
-							server_GUID,
-							pSMBr->u.
-							extended_response.
-							GUID, 16);
-					}
-				} else
-					memcpy(server->server_GUID,
-					       pSMBr->u.extended_response.
-					       GUID, 16);
-			} else {
-				rc = decode_negTokenInit(pSMBr->u.
-							 extended_response.
-							 SecurityBlob,
-							 count - 16,
-							 &server->secType);
-				if(rc == 1) {
-				/* BB Need to fill struct for sessetup here */
-					rc = -EOPNOTSUPP;
-				} else {
-					rc = -EINVAL;
-				}
-			}
-		} else
-			server->capabilities &= ~CAP_EXTENDED_SECURITY;
-		if(sign_CIFS_PDUs == FALSE) {        
-			if(server->secMode & SECMODE_SIGN_REQUIRED)
-				cERROR(1,
-				 ("Server requires /proc/fs/cifs/PacketSigningEnabled"));
-			server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
-		} else if(sign_CIFS_PDUs == 1) {
-			if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
-				server->secMode &= ~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+		if((secFlags & CIFSSEC_MAY_LANMAN) || 
+			(secFlags & CIFSSEC_MAY_PLNTXT))
+			server->secType = LANMAN;
+		else {
+			cERROR(1, ("mount failed weak security disabled"
+				   " in /proc/fs/cifs/SecurityFlags"));
+			rc = -EOPNOTSUPP;
+			goto neg_err_exit;
+		}	
+		server->secMode = (__u8)le16_to_cpu(rsp->SecurityMode);
+		server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
+		server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
+				(__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
+		GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
+		/* even though we do not use raw we might as well set this
+		accurately, in case we ever find a need for it */
+		if((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
+			server->maxRw = 0xFF00;
+			server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
+		} else {
+			server->maxRw = 0;/* we do not need to use raw anyway */
+			server->capabilities = CAP_MPX_MODE;
 		}
-				
+		server->timeZone = le16_to_cpu(rsp->ServerTimeZone);
+
+		/* BB get server time for time conversions and add
+		code to use it and timezone since this is not UTC */	
+
+		if (rsp->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+			memcpy(server->cryptKey, rsp->EncryptionKey,
+				CIFS_CRYPTO_KEY_SIZE);
+		} else if (server->secMode & SECMODE_PW_ENCRYPT) {
+			rc = -EIO; /* need cryptkey unless plain text */
+			goto neg_err_exit;
+		}
+
+		cFYI(1,("LANMAN negotiated"));
+		/* we will not end up setting signing flags - as no signing
+		was in LANMAN and server did not return the flags on */
+		goto signing_check;
+#else /* weak security disabled */
+	} else if(pSMBr->hdr.WordCount == 13) {
+		cERROR(1,("mount failed, cifs module not built "
+			  "with CIFS_WEAK_PW_HASH support"));
+			rc = -EOPNOTSUPP;
+#endif /* WEAK_PW_HASH */
+		goto neg_err_exit;
+	} else if(pSMBr->hdr.WordCount != 17) {
+		/* unknown wct */
+		rc = -EOPNOTSUPP;
+		goto neg_err_exit;
 	}
-	
+	/* else wct == 17 NTLM */
+	server->secMode = pSMBr->SecurityMode;
+	if((server->secMode & SECMODE_USER) == 0)
+		cFYI(1,("share mode security"));
+
+	if((server->secMode & SECMODE_PW_ENCRYPT) == 0)
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+		if ((secFlags & CIFSSEC_MAY_PLNTXT) == 0)
+#endif /* CIFS_WEAK_PW_HASH */
+			cERROR(1,("Server requests plain text password"
+				  " but client support disabled"));
+
+	if((secFlags & CIFSSEC_MUST_NTLMV2) == CIFSSEC_MUST_NTLMV2)
+		server->secType = NTLMv2;
+	else if(secFlags & CIFSSEC_MAY_NTLM)
+		server->secType = NTLM;
+	else if(secFlags & CIFSSEC_MAY_NTLMV2)
+		server->secType = NTLMv2;
+	/* else krb5 ... any others ... */
+
+	/* one byte, so no need to convert this or EncryptionKeyLen from
+	   little endian */
+	server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount);
+	/* probably no need to store and check maxvcs */
+	server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
+			(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
+	server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
+	cFYI(0, ("Max buf = %d", ses->server->maxBuf));
+	GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
+	server->capabilities = le32_to_cpu(pSMBr->Capabilities);
+	server->timeZone = le16_to_cpu(pSMBr->ServerTimeZone);	
+	if (pSMBr->EncryptionKeyLength == CIFS_CRYPTO_KEY_SIZE) {
+		memcpy(server->cryptKey, pSMBr->u.EncryptionKey,
+		       CIFS_CRYPTO_KEY_SIZE);
+	} else if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC)
+			&& (pSMBr->EncryptionKeyLength == 0)) {
+		/* decode security blob */
+	} else if (server->secMode & SECMODE_PW_ENCRYPT) {
+		rc = -EIO; /* no crypt key only if plain text pwd */
+		goto neg_err_exit;
+	}
+
+	/* BB might be helpful to save off the domain of server here */
+
+	if ((pSMBr->hdr.Flags2 & SMBFLG2_EXT_SEC) && 
+		(server->capabilities & CAP_EXTENDED_SECURITY)) {
+		count = pSMBr->ByteCount;
+		if (count < 16)
+			rc = -EIO;
+		else if (count == 16) {
+			server->secType = RawNTLMSSP;
+			if (server->socketUseCount.counter > 1) {
+				if (memcmp(server->server_GUID,
+					   pSMBr->u.extended_response.
+					   GUID, 16) != 0) {
+					cFYI(1, ("server UID changed"));
+					memcpy(server->server_GUID,
+						pSMBr->u.extended_response.GUID,
+						16);
+				}
+			} else
+				memcpy(server->server_GUID,
+				       pSMBr->u.extended_response.GUID, 16);
+		} else {
+			rc = decode_negTokenInit(pSMBr->u.extended_response.
+						 SecurityBlob,
+						 count - 16,
+						 &server->secType);
+			if(rc == 1) {
+			/* BB Need to fill struct for sessetup here */
+				rc = -EOPNOTSUPP;
+			} else {
+				rc = -EINVAL;
+			}
+		}
+	} else
+		server->capabilities &= ~CAP_EXTENDED_SECURITY;
+
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+signing_check:
+#endif
+	if(sign_CIFS_PDUs == FALSE) {        
+		if(server->secMode & SECMODE_SIGN_REQUIRED)
+			cERROR(1,("Server requires "
+				 "/proc/fs/cifs/PacketSigningEnabled to be on"));
+		server->secMode &= 
+			~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+	} else if(sign_CIFS_PDUs == 1) {
+		if((server->secMode & SECMODE_SIGN_REQUIRED) == 0)
+			server->secMode &= 
+				~(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED);
+	} else if(sign_CIFS_PDUs == 2) {
+		if((server->secMode & 
+			(SECMODE_SIGN_ENABLED | SECMODE_SIGN_REQUIRED)) == 0) {
+			cERROR(1,("signing required but server lacks support"));
+		}
+	}
+neg_err_exit:	
 	cifs_buf_release(pSMB);
+
+	cFYI(1,("negprot rc %d",rc));
 	return rc;
 }
 
@@ -2239,7 +2360,7 @@
 			}
 			symlinkinfo[buflen] = 0; /* just in case so the caller
 					does not go off the end of the buffer */
-			cFYI(1,("readlink result - %s ",symlinkinfo));
+			cFYI(1,("readlink result - %s",symlinkinfo));
 		}
 	}
 qreparse_out:
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index bae1479..876eb9e 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -49,8 +49,6 @@
 
 static DECLARE_COMPLETION(cifsd_complete);
 
-extern void SMBencrypt(unsigned char *passwd, unsigned char *c8,
-		       unsigned char *p24);
 extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
 			 unsigned char *p24);
 
@@ -70,6 +68,7 @@
 	gid_t linux_gid;
 	mode_t file_mode;
 	mode_t dir_mode;
+	unsigned secFlg;
 	unsigned rw:1;
 	unsigned retry:1;
 	unsigned intr:1;
@@ -83,12 +82,7 @@
 	unsigned remap:1;   /* set to remap seven reserved chars in filenames */
 	unsigned posix_paths:1;   /* unset to not ask for posix pathnames. */
 	unsigned sfu_emul:1;
-	unsigned krb5:1;
-	unsigned ntlm:1;
-	unsigned ntlmv2:1;
 	unsigned nullauth:1; /* attempt to authenticate with null user */
-	unsigned sign:1;
-	unsigned seal:1;     /* encrypt */
 	unsigned nocase;     /* request case insensitive filenames */
 	unsigned nobrl;      /* disable sending byte range locks to srv */
 	unsigned int rsize;
@@ -369,21 +363,21 @@
 			continue;
 		if (bigbuf == NULL) {
 			bigbuf = cifs_buf_get();
-			if(bigbuf == NULL) {
-				cERROR(1,("No memory for large SMB response"));
+			if (!bigbuf) {
+				cERROR(1, ("No memory for large SMB response"));
 				msleep(3000);
 				/* retry will check if exiting */
 				continue;
 			}
-		} else if(isLargeBuf) {
-			/* we are reusing a dirtry large buf, clear its start */
+		} else if (isLargeBuf) {
+			/* we are reusing a dirty large buf, clear its start */
 			memset(bigbuf, 0, sizeof (struct smb_hdr));
 		}
 
 		if (smallbuf == NULL) {
 			smallbuf = cifs_small_buf_get();
-			if(smallbuf == NULL) {
-				cERROR(1,("No memory for SMB response"));
+			if (!smallbuf) {
+				cERROR(1, ("No memory for SMB response"));
 				msleep(1000);
 				/* retry will check if exiting */
 				continue;
@@ -403,12 +397,12 @@
 		    kernel_recvmsg(csocket, &smb_msg,
 				 &iov, 1, 4, 0 /* BB see socket.h flags */);
 
-		if(server->tcpStatus == CifsExiting) {
+		if (server->tcpStatus == CifsExiting) {
 			break;
 		} else if (server->tcpStatus == CifsNeedReconnect) {
-			cFYI(1,("Reconnect after server stopped responding"));
+			cFYI(1, ("Reconnect after server stopped responding"));
 			cifs_reconnect(server);
-			cFYI(1,("call to reconnect done"));
+			cFYI(1, ("call to reconnect done"));
 			csocket = server->ssocket;
 			continue;
 		} else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) {
@@ -417,15 +411,15 @@
 				tcpStatus CifsNeedReconnect if server hung */
 			continue;
 		} else if (length <= 0) {
-			if(server->tcpStatus == CifsNew) {
-				cFYI(1,("tcp session abend after SMBnegprot"));
+			if (server->tcpStatus == CifsNew) {
+				cFYI(1, ("tcp session abend after SMBnegprot"));
 				/* some servers kill the TCP session rather than
 				   returning an SMB negprot error, in which
 				   case reconnecting here is not going to help,
 				   and so simply return error to mount */
 				break;
 			}
-			if(length == -EINTR) { 
+			if (!try_to_freeze() && (length == -EINTR)) {
 				cFYI(1,("cifsd thread killed"));
 				break;
 			}
@@ -585,9 +579,11 @@
 						/* merge response - fix up 1st*/
 						if(coalesce_t2(smb_buffer, 
 							mid_entry->resp_buf)) {
+							mid_entry->multiRsp = 1;
 							break;
 						} else {
 							/* all parts received */
+							mid_entry->multiEnd = 1;
 							goto multi_t2_fnd; 
 						}
 					} else {
@@ -632,9 +628,14 @@
 			wake_up_process(task_to_wake);
 		} else if ((is_valid_oplock_break(smb_buffer, server) == FALSE)
 		    && (isMultiRsp == FALSE)) {                          
-			cERROR(1, ("No task to wake, unknown frame rcvd!"));
+			cERROR(1, ("No task to wake, unknown frame rcvd! NumMids %d", midCount.counter));
 			cifs_dump_mem("Received Data is: ",(char *)smb_buffer,
 				      sizeof(struct smb_hdr));
+#ifdef CONFIG_CIFS_DEBUG2
+			cifs_dump_detail(smb_buffer);
+			cifs_dump_mids(server);
+#endif /* CIFS_DEBUG2 */
+			
 		}
 	} /* end while !EXITING */
 
@@ -784,7 +785,6 @@
 
 	/* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */
 	vol->rw = TRUE;
-	vol->ntlm = TRUE;
 	/* default is always to request posix paths. */
 	vol->posix_paths = 1;
 
@@ -915,30 +915,35 @@
 				cERROR(1,("no security value specified"));
                                 continue;
                         } else if (strnicmp(value, "krb5i", 5) == 0) {
-				vol->sign = 1;
-				vol->krb5 = 1;
+				vol->secFlg |= CIFSSEC_MAY_KRB5 | 
+					CIFSSEC_MUST_SIGN;
 			} else if (strnicmp(value, "krb5p", 5) == 0) {
-				/* vol->seal = 1; 
-				   vol->krb5 = 1; */
+				/* vol->secFlg |= CIFSSEC_MUST_SEAL | 
+					CIFSSEC_MAY_KRB5; */ 
 				cERROR(1,("Krb5 cifs privacy not supported"));
 				return 1;
 			} else if (strnicmp(value, "krb5", 4) == 0) {
-				vol->krb5 = 1;
+				vol->secFlg |= CIFSSEC_MAY_KRB5;
 			} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
-				vol->ntlmv2 = 1;
-				vol->sign = 1;
+				vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
+					CIFSSEC_MUST_SIGN;
 			} else if (strnicmp(value, "ntlmv2", 6) == 0) {
-				vol->ntlmv2 = 1;
+				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
 			} else if (strnicmp(value, "ntlmi", 5) == 0) {
-				vol->ntlm = 1;
-				vol->sign = 1;
+				vol->secFlg |= CIFSSEC_MAY_NTLM |
+					CIFSSEC_MUST_SIGN;
 			} else if (strnicmp(value, "ntlm", 4) == 0) {
 				/* ntlm is default so can be turned off too */
-				vol->ntlm = 1;
+				vol->secFlg |= CIFSSEC_MAY_NTLM;
 			} else if (strnicmp(value, "nontlm", 6) == 0) {
-				vol->ntlm = 0;
+				/* BB is there a better way to do this? */
+				vol->secFlg |= CIFSSEC_MAY_NTLMV2;
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+			} else if (strnicmp(value, "lanman", 6) == 0) {
+                                vol->secFlg |= CIFSSEC_MAY_LANMAN;
+#endif
 			} else if (strnicmp(value, "none", 4) == 0) {
-				vol->nullauth = 1; 
+				vol->nullauth = 1;
                         } else {
                                 cERROR(1,("bad security option: %s", value));
                                 return 1;
@@ -976,7 +981,7 @@
 			}
 			/* BB are there cases in which a comma can be valid in
 			a domain name and need special handling? */
-			if (strnlen(value, 65) < 65) {
+			if (strnlen(value, 256) < 256) {
 				vol->domainname = value;
 				cFYI(1, ("Domain name set"));
 			} else {
@@ -1168,6 +1173,10 @@
 			vol->no_psx_acl = 0;
 		} else if (strnicmp(data, "noacl",5) == 0) {
 			vol->no_psx_acl = 1;
+		} else if (strnicmp(data, "sign",4) == 0) {
+			vol->secFlg |= CIFSSEC_MUST_SIGN;
+/*		} else if (strnicmp(data, "seal",4) == 0) {
+			vol->secFlg |= CIFSSEC_MUST_SEAL; */
 		} else if (strnicmp(data, "direct",6) == 0) {
 			vol->direct_io = 1;
 		} else if (strnicmp(data, "forcedirectio",13) == 0) {
@@ -1762,11 +1771,18 @@
 			if (volume_info.username)
 				strncpy(pSesInfo->userName,
 					volume_info.username,MAX_USERNAME_SIZE);
-			if (volume_info.domainname)
-				strncpy(pSesInfo->domainName,
-					volume_info.domainname,MAX_USERNAME_SIZE);
+			if (volume_info.domainname) {
+				int len = strlen(volume_info.domainname);
+				pSesInfo->domainName = 
+					kmalloc(len + 1, GFP_KERNEL);
+				if(pSesInfo->domainName)
+					strcpy(pSesInfo->domainName,
+						volume_info.domainname);
+			}
 			pSesInfo->linux_uid = volume_info.linux_uid;
+			pSesInfo->overrideSecFlg = volume_info.secFlg;
 			down(&pSesInfo->sesSem);
+			/* BB FIXME need to pass vol->secFlgs BB */
 			rc = cifs_setup_session(xid,pSesInfo, cifs_sb->local_nls);
 			up(&pSesInfo->sesSem);
 			if(!rc)
@@ -1980,7 +1996,7 @@
 
 static int
 CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-	      char session_key[CIFS_SESSION_KEY_SIZE],
+	      char session_key[CIFS_SESS_KEY_SIZE],
 	      const struct nls_table *nls_codepage)
 {
 	struct smb_hdr *smb_buffer;
@@ -2038,15 +2054,15 @@
 	pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
 
 	pSMB->req_no_secext.CaseInsensitivePasswordLength = 
-		cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+		cpu_to_le16(CIFS_SESS_KEY_SIZE);
 
 	pSMB->req_no_secext.CaseSensitivePasswordLength =
-	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+	    cpu_to_le16(CIFS_SESS_KEY_SIZE);
 	bcc_ptr = pByteArea(smb_buffer);
-	memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
-	bcc_ptr += CIFS_SESSION_KEY_SIZE;
-	memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
-	bcc_ptr += CIFS_SESSION_KEY_SIZE;
+	memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
+	bcc_ptr += CIFS_SESS_KEY_SIZE;
+	memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
+	bcc_ptr += CIFS_SESS_KEY_SIZE;
 
 	if (ses->capabilities & CAP_UNICODE) {
 		if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
@@ -2054,7 +2070,7 @@
 			bcc_ptr++;
 		}
 		if(user == NULL)
-			bytes_returned = 0; /* skill null user */
+			bytes_returned = 0; /* skip null user */
 	        else
 			bytes_returned =
 			        cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
@@ -2162,8 +2178,7 @@
 				if (remaining_words > 0) {
 					len = UniStrnlen((wchar_t *)bcc_ptr,
 							 remaining_words-1);
-					if(ses->serverNOS)
-						kfree(ses->serverNOS);
+					kfree(ses->serverNOS);
 					ses->serverNOS = kzalloc(2 * (len + 1),GFP_KERNEL);
 					if(ses->serverNOS == NULL)
 						goto sesssetup_nomem;
@@ -2203,12 +2218,10 @@
 					/* if these kcallocs fail not much we
 					   can do, but better to not fail the
 					   sesssetup itself */
-					if(ses->serverDomain)
-						kfree(ses->serverDomain);
+					kfree(ses->serverDomain);
 					ses->serverDomain =
 					    kzalloc(2, GFP_KERNEL);
-					if(ses->serverNOS)
-						kfree(ses->serverNOS);
+					kfree(ses->serverNOS);
 					ses->serverNOS =
 					    kzalloc(2, GFP_KERNEL);
 				}
@@ -2217,8 +2230,7 @@
 				if (((long) bcc_ptr + len) - (long)
 				    pByteArea(smb_buffer_response)
 					    <= BCC(smb_buffer_response)) {
-					if(ses->serverOS)
-						kfree(ses->serverOS);
+					kfree(ses->serverOS);
 					ses->serverOS = kzalloc(len + 1,GFP_KERNEL);
 					if(ses->serverOS == NULL)
 						goto sesssetup_nomem;
@@ -2229,8 +2241,7 @@
 					bcc_ptr++;
 
 					len = strnlen(bcc_ptr, 1024);
-					if(ses->serverNOS)
-						kfree(ses->serverNOS);
+					kfree(ses->serverNOS);
 					ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
 					if(ses->serverNOS == NULL)
 						goto sesssetup_nomem;
@@ -2274,292 +2285,6 @@
 }
 
 static int
-CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
-		char *SecurityBlob,int SecurityBlobLength,
-		const struct nls_table *nls_codepage)
-{
-	struct smb_hdr *smb_buffer;
-	struct smb_hdr *smb_buffer_response;
-	SESSION_SETUP_ANDX *pSMB;
-	SESSION_SETUP_ANDX *pSMBr;
-	char *bcc_ptr;
-	char *user;
-	char *domain;
-	int rc = 0;
-	int remaining_words = 0;
-	int bytes_returned = 0;
-	int len;
-	__u32 capabilities;
-	__u16 count;
-
-	cFYI(1, ("In spnego sesssetup "));
-	if(ses == NULL)
-		return -EINVAL;
-	user = ses->userName;
-	domain = ses->domainName;
-
-	smb_buffer = cifs_buf_get();
-	if (smb_buffer == NULL) {
-		return -ENOMEM;
-	}
-	smb_buffer_response = smb_buffer;
-	pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
-
-	/* send SMBsessionSetup here */
-	header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
-			NULL /* no tCon exists yet */ , 12 /* wct */ );
-
-	smb_buffer->Mid = GetNextMid(ses->server);
-	pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
-	pSMB->req.AndXCommand = 0xFF;
-	if(ses->server->maxBuf > 64*1024)
-		ses->server->maxBuf = (64*1023);
-	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
-	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
-	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
-	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
-	    CAP_EXTENDED_SECURITY;
-	if (ses->capabilities & CAP_UNICODE) {
-		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
-		capabilities |= CAP_UNICODE;
-	}
-	if (ses->capabilities & CAP_STATUS32) {
-		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
-		capabilities |= CAP_STATUS32;
-	}
-	if (ses->capabilities & CAP_DFS) {
-		smb_buffer->Flags2 |= SMBFLG2_DFS;
-		capabilities |= CAP_DFS;
-	}
-	pSMB->req.Capabilities = cpu_to_le32(capabilities);
-
-	pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
-	bcc_ptr = pByteArea(smb_buffer);
-	memcpy(bcc_ptr, SecurityBlob, SecurityBlobLength);
-	bcc_ptr += SecurityBlobLength;
-
-	if (ses->capabilities & CAP_UNICODE) {
-		if ((long) bcc_ptr % 2) {	/* must be word aligned for Unicode strings */
-			*bcc_ptr = 0;
-			bcc_ptr++;
-		}
-		bytes_returned =
-		    cifs_strtoUCS((__le16 *) bcc_ptr, user, 100, nls_codepage);
-		bcc_ptr += 2 * bytes_returned;	/* convert num of 16 bit words to bytes */
-		bcc_ptr += 2;	/* trailing null */
-		if (domain == NULL)
-			bytes_returned =
-			    cifs_strtoUCS((__le16 *) bcc_ptr,
-					  "CIFS_LINUX_DOM", 32, nls_codepage);
-		else
-			bytes_returned =
-			    cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
-					  nls_codepage);
-		bcc_ptr += 2 * bytes_returned;
-		bcc_ptr += 2;
-		bytes_returned =
-		    cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
-				  32, nls_codepage);
-		bcc_ptr += 2 * bytes_returned;
-		bytes_returned =
-		    cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, 32,
-				  nls_codepage);
-		bcc_ptr += 2 * bytes_returned;
-		bcc_ptr += 2;
-		bytes_returned =
-		    cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
-				  64, nls_codepage);
-		bcc_ptr += 2 * bytes_returned;
-		bcc_ptr += 2;
-	} else {
-		strncpy(bcc_ptr, user, 200);
-		bcc_ptr += strnlen(user, 200);
-		*bcc_ptr = 0;
-		bcc_ptr++;
-		if (domain == NULL) {
-			strcpy(bcc_ptr, "CIFS_LINUX_DOM");
-			bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
-		} else {
-			strncpy(bcc_ptr, domain, 64);
-			bcc_ptr += strnlen(domain, 64);
-			*bcc_ptr = 0;
-			bcc_ptr++;
-		}
-		strcpy(bcc_ptr, "Linux version ");
-		bcc_ptr += strlen("Linux version ");
-		strcpy(bcc_ptr, system_utsname.release);
-		bcc_ptr += strlen(system_utsname.release) + 1;
-		strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
-		bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
-	}
-	count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
-	smb_buffer->smb_buf_length += count;
-	pSMB->req.ByteCount = cpu_to_le16(count);
-
-	rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
-			 &bytes_returned, 1);
-	if (rc) {
-/*    rc = map_smb_to_linux_error(smb_buffer_response);  *//* done in SendReceive now */
-	} else if ((smb_buffer_response->WordCount == 3)
-		   || (smb_buffer_response->WordCount == 4)) {
-		__u16 action = le16_to_cpu(pSMBr->resp.Action);
-		__u16 blob_len =
-		    le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-		if (action & GUEST_LOGIN)
-			cFYI(1, (" Guest login"));	/* BB do we want to set anything in SesInfo struct ? */
-		if (ses) {
-			ses->Suid = smb_buffer_response->Uid;	/* UID left in wire format (le) */
-			cFYI(1, ("UID = %d ", ses->Suid));
-			bcc_ptr = pByteArea(smb_buffer_response);	/* response can have either 3 or 4 word count - Samba sends 3 */
-
-			/* BB Fix below to make endian neutral !! */
-
-			if ((pSMBr->resp.hdr.WordCount == 3)
-			    || ((pSMBr->resp.hdr.WordCount == 4)
-				&& (blob_len <
-				    pSMBr->resp.ByteCount))) {
-				if (pSMBr->resp.hdr.WordCount == 4) {
-					bcc_ptr +=
-					    blob_len;
-					cFYI(1,
-					     ("Security Blob Length %d ",
-					      blob_len));
-				}
-
-				if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
-					if ((long) (bcc_ptr) % 2) {
-						remaining_words =
-						    (BCC(smb_buffer_response)
-						     - 1) / 2;
-						bcc_ptr++;	/* Unicode strings must be word aligned */
-					} else {
-						remaining_words =
-						    BCC
-						    (smb_buffer_response) / 2;
-					}
-					len =
-					    UniStrnlen((wchar_t *) bcc_ptr,
-						       remaining_words - 1);
-/* We look for obvious messed up bcc or strings in response so we do not go off
-   the end since (at least) WIN2K and Windows XP have a major bug in not null
-   terminating last Unicode string in response  */
-					if(ses->serverOS)
-						kfree(ses->serverOS);
-					ses->serverOS =
-					    kzalloc(2 * (len + 1), GFP_KERNEL);
-					cifs_strfromUCS_le(ses->serverOS,
-							   (__le16 *)
-							   bcc_ptr, len,
-							   nls_codepage);
-					bcc_ptr += 2 * (len + 1);
-					remaining_words -= len + 1;
-					ses->serverOS[2 * len] = 0;
-					ses->serverOS[1 + (2 * len)] = 0;
-					if (remaining_words > 0) {
-						len = UniStrnlen((wchar_t *)bcc_ptr,
-								 remaining_words
-								 - 1);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
-						ses->serverNOS =
-						    kzalloc(2 * (len + 1),
-							    GFP_KERNEL);
-						cifs_strfromUCS_le(ses->serverNOS,
-								   (__le16 *)bcc_ptr,
-								   len,
-								   nls_codepage);
-						bcc_ptr += 2 * (len + 1);
-						ses->serverNOS[2 * len] = 0;
-						ses->serverNOS[1 + (2 * len)] = 0;
-						remaining_words -= len + 1;
-						if (remaining_words > 0) {
-							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
-                     /* last string not null terminated (e.g.Windows XP/2000) */
-							if(ses->serverDomain)
-								kfree(ses->serverDomain);
-							ses->serverDomain = kzalloc(2*(len+1),GFP_KERNEL);
-							cifs_strfromUCS_le(ses->serverDomain,
-							     (__le16 *)bcc_ptr, 
-							     len, nls_codepage);
-							bcc_ptr += 2*(len+1);
-							ses->serverDomain[2*len] = 0;
-							ses->serverDomain[1+(2*len)] = 0;
-						} /* else no more room so create dummy domain string */
-						else {
-							if(ses->serverDomain)
-								kfree(ses->serverDomain);
-							ses->serverDomain =
-							    kzalloc(2,GFP_KERNEL);
-						}
-					} else {/* no room use dummy domain&NOS */
-						if(ses->serverDomain)
-							kfree(ses->serverDomain);
-						ses->serverDomain = kzalloc(2, GFP_KERNEL);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
-						ses->serverNOS = kzalloc(2, GFP_KERNEL);
-					}
-				} else {	/* ASCII */
-
-					len = strnlen(bcc_ptr, 1024);
-					if (((long) bcc_ptr + len) - (long)
-					    pByteArea(smb_buffer_response)
-					    <= BCC(smb_buffer_response)) {
-						if(ses->serverOS)
-							kfree(ses->serverOS);
-						ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
-						strncpy(ses->serverOS, bcc_ptr, len);
-
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;	/* null terminate the string */
-						bcc_ptr++;
-
-						len = strnlen(bcc_ptr, 1024);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
-						ses->serverNOS = kzalloc(len + 1,GFP_KERNEL);
-						strncpy(ses->serverNOS, bcc_ptr, len);
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;
-						bcc_ptr++;
-
-						len = strnlen(bcc_ptr, 1024);
-						if(ses->serverDomain)
-							kfree(ses->serverDomain);
-						ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
-						strncpy(ses->serverDomain, bcc_ptr, len);
-						bcc_ptr += len;
-						bcc_ptr[0] = 0;
-						bcc_ptr++;
-					} else
-						cFYI(1,
-						     ("Variable field of length %d extends beyond end of smb ",
-						      len));
-				}
-			} else {
-				cERROR(1,
-				       (" Security Blob Length extends beyond end of SMB"));
-			}
-		} else {
-			cERROR(1, ("No session structure passed in."));
-		}
-	} else {
-		cERROR(1,
-		       (" Invalid Word count %d: ",
-			smb_buffer_response->WordCount));
-		rc = -EIO;
-	}
-
-	if (smb_buffer)
-		cifs_buf_release(smb_buffer);
-
-	return rc;
-}
-
-static int
 CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
 			      struct cifsSesInfo *ses, int * pNTLMv2_flag,
 			      const struct nls_table *nls_codepage)
@@ -2635,8 +2360,8 @@
 	    /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
 	if(sign_CIFS_PDUs)
 		negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
-	if(ntlmv2_support)
-		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
+/*	if(ntlmv2_support)
+		negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
 	/* setup pointers to domain name and workstation name */
 	bcc_ptr += SecurityBlobLength;
 
@@ -2783,8 +2508,7 @@
 								 bcc_ptr,
 								 remaining_words
 								 - 1);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
+						kfree(ses->serverNOS);
 						ses->serverNOS =
 						    kzalloc(2 * (len + 1),
 							    GFP_KERNEL);
@@ -2802,8 +2526,7 @@
 						if (remaining_words > 0) {
 							len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);	
            /* last string is not always null terminated (for e.g. for Windows XP & 2000) */
-							if(ses->serverDomain)
-								kfree(ses->serverDomain);
+							kfree(ses->serverDomain);
 							ses->serverDomain =
 							    kzalloc(2 *
 								    (len +
@@ -2822,19 +2545,16 @@
 							    = 0;
 						} /* else no more room so create dummy domain string */
 						else {
-							if(ses->serverDomain)
-								kfree(ses->serverDomain);
+							kfree(ses->serverDomain);
 							ses->serverDomain =
 							    kzalloc(2,
 								    GFP_KERNEL);
 						}
 					} else {	/* no room so create dummy domain and NOS string */
-						if(ses->serverDomain);
-							kfree(ses->serverDomain);
+						kfree(ses->serverDomain);
 						ses->serverDomain =
 						    kzalloc(2, GFP_KERNEL);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
+						kfree(ses->serverNOS);
 						ses->serverNOS =
 						    kzalloc(2, GFP_KERNEL);
 					}
@@ -2856,8 +2576,7 @@
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
+						kfree(ses->serverNOS);
 						ses->serverNOS =
 						    kzalloc(len + 1,
 							    GFP_KERNEL);
@@ -2867,8 +2586,7 @@
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
-						if(ses->serverDomain)
-							kfree(ses->serverDomain);
+						kfree(ses->serverDomain);
 						ses->serverDomain =
 						    kzalloc(len + 1,
 							    GFP_KERNEL);
@@ -2994,14 +2712,14 @@
 	SecurityBlob->LmChallengeResponse.Buffer = 0;
 
 	SecurityBlob->NtChallengeResponse.Length =
-	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+	    cpu_to_le16(CIFS_SESS_KEY_SIZE);
 	SecurityBlob->NtChallengeResponse.MaximumLength =
-	    cpu_to_le16(CIFS_SESSION_KEY_SIZE);
-	memcpy(bcc_ptr, ntlm_session_key, CIFS_SESSION_KEY_SIZE);
+	    cpu_to_le16(CIFS_SESS_KEY_SIZE);
+	memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
 	SecurityBlob->NtChallengeResponse.Buffer =
 	    cpu_to_le32(SecurityBlobLength);
-	SecurityBlobLength += CIFS_SESSION_KEY_SIZE;
-	bcc_ptr += CIFS_SESSION_KEY_SIZE;
+	SecurityBlobLength += CIFS_SESS_KEY_SIZE;
+	bcc_ptr += CIFS_SESS_KEY_SIZE;
 
 	if (ses->capabilities & CAP_UNICODE) {
 		if (domain == NULL) {
@@ -3190,8 +2908,7 @@
 								 bcc_ptr,
 								 remaining_words
 								 - 1);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
+						kfree(ses->serverNOS);
 						ses->serverNOS =
 						    kzalloc(2 * (len + 1),
 							    GFP_KERNEL);
@@ -3244,8 +2961,7 @@
 						if(ses->serverDomain)
 							kfree(ses->serverDomain);
 						ses->serverDomain = kzalloc(2, GFP_KERNEL);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
+						kfree(ses->serverNOS);
 						ses->serverNOS = kzalloc(2, GFP_KERNEL);
 					}
 				} else {	/* ASCII */
@@ -3263,8 +2979,7 @@
 						bcc_ptr++;
 
 						len = strnlen(bcc_ptr, 1024);
-						if(ses->serverNOS)
-							kfree(ses->serverNOS);
+						kfree(ses->serverNOS);
 						ses->serverNOS = kzalloc(len+1,GFP_KERNEL);
 						strncpy(ses->serverNOS, bcc_ptr, len);	
 						bcc_ptr += len;
@@ -3340,22 +3055,33 @@
 	bcc_ptr = &pSMB->Password[0];
 	if((ses->server->secMode) & SECMODE_USER) {
 		pSMB->PasswordLength = cpu_to_le16(1);	/* minimum */
+		*bcc_ptr = 0; /* password is null byte */
 		bcc_ptr++;              /* skip password */
+		/* already aligned so no need to do it below */
 	} else {
-		pSMB->PasswordLength = cpu_to_le16(CIFS_SESSION_KEY_SIZE);
+		pSMB->PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
 		/* BB FIXME add code to fail this if NTLMv2 or Kerberos
 		   specified as required (when that support is added to
 		   the vfs in the future) as only NTLM or the much
-		   weaker LANMAN (which we do not send) is accepted
+		   weaker LANMAN (which we do not send by default) is accepted
 		   by Samba (not sure whether other servers allow
 		   NTLMv2 password here) */
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+		if((extended_security & CIFSSEC_MAY_LANMAN) && 
+			(ses->server->secType == LANMAN))
+			calc_lanman_hash(ses, bcc_ptr);
+		else
+#endif /* CIFS_WEAK_PW_HASH */
 		SMBNTencrypt(ses->password,
 			     ses->server->cryptKey,
 			     bcc_ptr);
 
-		bcc_ptr += CIFS_SESSION_KEY_SIZE;
-		*bcc_ptr = 0;
-		bcc_ptr++; /* align */
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
+		if(ses->capabilities & CAP_UNICODE) {
+			/* must align unicode strings */
+			*bcc_ptr = 0; /* null byte password */
+			bcc_ptr++;
+		}
 	}
 
 	if(ses->server->secMode & 
@@ -3429,7 +3155,10 @@
 			}
 			/* else do not bother copying these informational fields */
 		}
-		tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
+		if(smb_buffer_response->WordCount == 3)
+			tcon->Flags = le16_to_cpu(pSMBr->OptionalSupport);
+		else
+			tcon->Flags = 0;
 		cFYI(1, ("Tcon flags: 0x%x ", tcon->Flags));
 	} else if ((rc == 0) && tcon == NULL) {
         /* all we need to save for IPC$ connection */
@@ -3494,7 +3223,7 @@
 					   struct nls_table * nls_info)
 {
 	int rc = 0;
-	char ntlm_session_key[CIFS_SESSION_KEY_SIZE];
+	char ntlm_session_key[CIFS_SESS_KEY_SIZE];
 	int ntlmv2_flag = FALSE;
 	int first_time = 0;
 
@@ -3526,20 +3255,13 @@
 			pSesInfo->server->secMode,
 			pSesInfo->server->capabilities,
 			pSesInfo->server->timeZone));
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-		if(experimEnabled > 1)
-			rc = CIFS_SessSetup(xid, pSesInfo, CIFS_NTLM /* type */,
-					    &ntlmv2_flag, nls_info);	
-		else
-#endif
-		if (extended_security
+		if(experimEnabled < 2)
+			rc = CIFS_SessSetup(xid, pSesInfo,
+					    first_time, nls_info);
+		else if (extended_security
 				&& (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
 				&& (pSesInfo->server->secType == NTLMSSP)) {
-			cFYI(1, ("New style sesssetup"));
-			rc = CIFSSpnegoSessSetup(xid, pSesInfo,
-				NULL /* security blob */, 
-				0 /* blob length */,
-				nls_info);
+			rc = -EOPNOTSUPP;
 		} else if (extended_security
 			   && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
 			   && (pSesInfo->server->secType == RawNTLMSSP)) {
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 82315ed..ba4cbe9 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -113,7 +113,7 @@
 	full_path[namelen+2] = 0;
 BB remove above eight lines BB */
 
-/* Inode operations in similar order to how they appear in the Linux file fs.h */
+/* Inode operations in similar order to how they appear in Linux file fs.h */
 
 int
 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
@@ -178,11 +178,14 @@
 		FreeXid(xid);
 		return -ENOMEM;
 	}
-
-	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
+	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 
+		rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
 			 desiredAccess, CREATE_NOT_DIR,
 			 &fileHandle, &oplock, buf, cifs_sb->local_nls,
 			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+	else
+		rc = -EIO; /* no NT SMB support fall into legacy open below */
+
 	if(rc == -EIO) {
 		/* old server, retry the open legacy style */
 		rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -191,7 +194,7 @@
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	} 
 	if (rc) {
-		cFYI(1, ("cifs_create returned 0x%x ", rc));
+		cFYI(1, ("cifs_create returned 0x%x", rc));
 	} else {
 		/* If Open reported that we actually created a file
 		then we now have to set the mode if possible */
@@ -369,6 +372,10 @@
 					 cifs_sb->mnt_cifs_flags & 
 					    CIFS_MOUNT_MAP_SPECIAL_CHR);
 
+			/* BB FIXME - add handling for backlevel servers
+			   which need legacy open and check for all
+			   calls to SMBOpen for fallback to 
+			   SMBLeagcyOpen */
 			if(!rc) {
 				/* BB Do not bother to decode buf since no
 				   local inode yet to put timestamps in,
diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c
index 633a938..d91a3d4 100644
--- a/fs/cifs/fcntl.c
+++ b/fs/cifs/fcntl.c
@@ -91,14 +91,14 @@
 	if(full_path == NULL) {
 		rc = -ENOMEM;
 	} else {
-		cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */
+		cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg));
 		rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, 
 			GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
 			&netfid, &oplock,NULL, cifs_sb->local_nls,
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 		/* BB fixme - add this handle to a notify handle list */
 		if(rc) {
-			cERROR(1,("Could not open directory for notify"));  /* BB remove BB */
+			cFYI(1,("Could not open directory for notify"));
 		} else {
 			filter = convert_to_cifs_notify_flags(arg);
 			if(filter != 0) {
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index e2b4ce1..5861eb4 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -110,7 +110,6 @@
 			 &pCifsInode->openFileList);
 	}
 	write_unlock(&GlobalSMBSeslock);
-	write_unlock(&file->f_owner.lock);
 	if (pCifsInode->clientCanCacheRead) {
 		/* we have the inode open somewhere else
 		   no need to discard cache data */
@@ -201,7 +200,7 @@
 		} else {
 			if (file->f_flags & O_EXCL)
 				cERROR(1, ("could not find file instance for "
-					   "new file %p ", file));
+					   "new file %p", file));
 		}
 	}
 
@@ -260,10 +259,15 @@
 		rc = -ENOMEM;
 		goto out;
 	}
-	rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess,
-			 CREATE_NOT_DIR, &netfid, &oplock, buf,
+
+	if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
+		rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, 
+			 desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf,
 			 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags
 				 & CIFS_MOUNT_MAP_SPECIAL_CHR);
+	else
+		rc = -EIO; /* no NT SMB support fall into legacy open below */
+
 	if (rc == -EIO) {
 		/* Old server, try legacy style OpenX */
 		rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -272,7 +276,7 @@
 				& CIFS_MOUNT_MAP_SPECIAL_CHR);
 	}
 	if (rc) {
-		cFYI(1, ("cifs_open returned 0x%x ", rc));
+		cFYI(1, ("cifs_open returned 0x%x", rc));
 		goto out;
 	}
 	file->private_data =
@@ -282,7 +286,6 @@
 		goto out;
 	}
 	pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
-	write_lock(&file->f_owner.lock);
 	write_lock(&GlobalSMBSeslock);
 	list_add(&pCifsFile->tlist, &pTcon->openFileList);
 
@@ -293,7 +296,6 @@
 					    &oplock, buf, full_path, xid);
 	} else {
 		write_unlock(&GlobalSMBSeslock);
-		write_unlock(&file->f_owner.lock);
 	}
 
 	if (oplock & CIFS_CREATE_ACTION) {           
@@ -409,8 +411,8 @@
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
 		up(&pCifsFile->fh_sem);
-		cFYI(1, ("cifs_open returned 0x%x ", rc));
-		cFYI(1, ("oplock: %d ", oplock));
+		cFYI(1, ("cifs_open returned 0x%x", rc));
+		cFYI(1, ("oplock: %d", oplock));
 	} else {
 		pCifsFile->netfid = netfid;
 		pCifsFile->invalidHandle = FALSE;
@@ -472,7 +474,6 @@
 	pTcon = cifs_sb->tcon;
 	if (pSMBFile) {
 		pSMBFile->closePend = TRUE;
-		write_lock(&file->f_owner.lock);
 		if (pTcon) {
 			/* no sense reconnecting to close a file that is
 			   already closed */
@@ -487,23 +488,18 @@
 					the struct would be in each open file,
 					but this should give enough time to 
 					clear the socket */
-					write_unlock(&file->f_owner.lock);
 					cERROR(1,("close with pending writes"));
 					msleep(timeout);
-					write_lock(&file->f_owner.lock);
 					timeout *= 4;
 				} 
-				write_unlock(&file->f_owner.lock);
 				rc = CIFSSMBClose(xid, pTcon,
 						  pSMBFile->netfid);
-				write_lock(&file->f_owner.lock);
 			}
 		}
 		write_lock(&GlobalSMBSeslock);
 		list_del(&pSMBFile->flist);
 		list_del(&pSMBFile->tlist);
 		write_unlock(&GlobalSMBSeslock);
-		write_unlock(&file->f_owner.lock);
 		kfree(pSMBFile->search_resume_name);
 		kfree(file->private_data);
 		file->private_data = NULL;
@@ -531,7 +527,7 @@
 	    (struct cifsFileInfo *)file->private_data;
 	char *ptmp;
 
-	cFYI(1, ("Closedir inode = 0x%p with ", inode));
+	cFYI(1, ("Closedir inode = 0x%p", inode));
 
 	xid = GetXid();
 
@@ -605,7 +601,7 @@
 	}
 	if (pfLock->fl_flags & FL_ACCESS)
 		cFYI(1, ("Process suspended by mandatory locking - "
-			 "not implemented yet "));
+			 "not implemented yet"));
 	if (pfLock->fl_flags & FL_LEASE)
 		cFYI(1, ("Lease on file - not implemented yet"));
 	if (pfLock->fl_flags & 
@@ -1079,9 +1075,9 @@
 	unsigned int bytes_written;
 	struct cifs_sb_info *cifs_sb;
 	int done = 0;
-	pgoff_t end = -1;
+	pgoff_t end;
 	pgoff_t index;
-	int is_range = 0;
+ 	int range_whole = 0;
 	struct kvec iov[32];
 	int len;
 	int n_iov = 0;
@@ -1122,16 +1118,14 @@
 	xid = GetXid();
 
 	pagevec_init(&pvec, 0);
-	if (wbc->sync_mode == WB_SYNC_NONE)
+	if (wbc->range_cyclic) {
 		index = mapping->writeback_index; /* Start from prev offset */
-	else {
-		index = 0;
-		scanned = 1;
-	}
-	if (wbc->start || wbc->end) {
-		index = wbc->start >> PAGE_CACHE_SHIFT;
-		end = wbc->end >> PAGE_CACHE_SHIFT;
-		is_range = 1;
+		end = -1;
+	} else {
+		index = wbc->range_start >> PAGE_CACHE_SHIFT;
+		end = wbc->range_end >> PAGE_CACHE_SHIFT;
+		if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+			range_whole = 1;
 		scanned = 1;
 	}
 retry:
@@ -1167,7 +1161,7 @@
 				break;
 			}
 
-			if (unlikely(is_range) && (page->index > end)) {
+			if (!wbc->range_cyclic && page->index > end) {
 				done = 1;
 				unlock_page(page);
 				break;
@@ -1271,7 +1265,7 @@
 		index = 0;
 		goto retry;
 	}
-	if (!is_range)
+	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
 		mapping->writeback_index = index;
 
 	FreeXid(xid);
@@ -1377,7 +1371,7 @@
 
 	xid = GetXid();
 
-	cFYI(1, ("Sync file - name: %s datasync: 0x%x ", 
+	cFYI(1, ("Sync file - name: %s datasync: 0x%x", 
 		dentry->d_name.name, datasync));
 	
 	rc = filemap_fdatawrite(inode->i_mapping);
@@ -1406,7 +1400,7 @@
 /*	fill in rpages then 
 	result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */
 
-/*	cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index));
+/*	cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index));
 
 #if 0
 	if (rc < 0)
@@ -1419,7 +1413,7 @@
  * As file closes, flush all cached write data for this inode checking
  * for write behind errors.
  */
-int cifs_flush(struct file *file)
+int cifs_flush(struct file *file, fl_owner_t id)
 {
 	struct inode * inode = file->f_dentry->d_inode;
 	int rc = 0;
@@ -1838,7 +1832,7 @@
 	if (rc < 0)
 		goto io_error;
 	else
-		cFYI(1, ("Bytes read %d ",rc));
+		cFYI(1, ("Bytes read %d",rc));
                                                                                                                            
 	file->f_dentry->d_inode->i_atime =
 		current_fs_time(file->f_dentry->d_inode->i_sb);
@@ -1948,7 +1942,7 @@
 	return 0;
 }
 
-struct address_space_operations cifs_addr_ops = {
+const struct address_space_operations cifs_addr_ops = {
 	.readpage = cifs_readpage,
 	.readpages = cifs_readpages,
 	.writepage = cifs_writepage,
@@ -1959,3 +1953,19 @@
 	/* .sync_page = cifs_sync_page, */
 	/* .direct_IO = */
 };
+
+/*
+ * cifs_readpages requires the server to support a buffer large enough to
+ * contain the header plus one complete page of data.  Otherwise, we need
+ * to leave cifs_readpages out of the address space operations.
+ */
+const struct address_space_operations cifs_addr_ops_smallbuf = {
+	.readpage = cifs_readpage,
+	.writepage = cifs_writepage,
+	.writepages = cifs_writepages,
+	.prepare_write = cifs_prepare_write,
+	.commit_write = cifs_commit_write,
+	.set_page_dirty = __set_page_dirty_nobuffers,
+	/* .sync_page = cifs_sync_page, */
+	/* .direct_IO = */
+};
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 4093764..b88147c 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -41,7 +41,7 @@
 	char *tmp_path;
 
 	pTcon = cifs_sb->tcon;
-	cFYI(1, ("Getting info on %s ", search_path));
+	cFYI(1, ("Getting info on %s", search_path));
 	/* could have done a find first instead but this returns more info */
 	rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
 				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -97,9 +97,9 @@
 		inode = *pinode;
 		cifsInfo = CIFS_I(inode);
 
-		cFYI(1, ("Old time %ld ", cifsInfo->time));
+		cFYI(1, ("Old time %ld", cifsInfo->time));
 		cifsInfo->time = jiffies;
-		cFYI(1, ("New time %ld ", cifsInfo->time));
+		cFYI(1, ("New time %ld", cifsInfo->time));
 		/* this is ok to set on every inode revalidate */
 		atomic_set(&cifsInfo->inUse,1);
 
@@ -180,11 +180,12 @@
 			else /* not direct, send byte range locks */ 
 				inode->i_fop = &cifs_file_ops;
 
-			inode->i_data.a_ops = &cifs_addr_ops;
 			/* check if server can support readpages */
 			if(pTcon->ses->server->maxBuf < 
-			    4096 + MAX_CIFS_HDR_SIZE)
-				inode->i_data.a_ops->readpages = NULL;
+			    PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
+				inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
+			else
+				inode->i_data.a_ops = &cifs_addr_ops;
 		} else if (S_ISDIR(inode->i_mode)) {
 			cFYI(1, ("Directory inode"));
 			inode->i_op = &cifs_dir_inode_ops;
@@ -421,23 +422,23 @@
 		inode = *pinode;
 		cifsInfo = CIFS_I(inode);
 		cifsInfo->cifsAttrs = attr;
-		cFYI(1, ("Old time %ld ", cifsInfo->time));
+		cFYI(1, ("Old time %ld", cifsInfo->time));
 		cifsInfo->time = jiffies;
-		cFYI(1, ("New time %ld ", cifsInfo->time));
+		cFYI(1, ("New time %ld", cifsInfo->time));
 
 		/* blksize needs to be multiple of two. So safer to default to
 		blksize and blkbits set in superblock so 2**blkbits and blksize
 		will match rather than setting to:
 		(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFE00;*/
 
-		/* Linux can not store file creation time unfortunately so we ignore it */
+		/* Linux can not store file creation time so ignore it */
 		inode->i_atime =
 		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
 		inode->i_mtime =
 		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
 		inode->i_ctime =
 		    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
-		cFYI(0, ("Attributes came in as 0x%x ", attr));
+		cFYI(0, ("Attributes came in as 0x%x", attr));
 
 		/* set default mode. will override for dirs below */
 		if (atomic_read(&cifsInfo->inUse) == 0)
@@ -519,10 +520,11 @@
 			else /* not direct, send byte range locks */
 				inode->i_fop = &cifs_file_ops;
 
-			inode->i_data.a_ops = &cifs_addr_ops;
 			if(pTcon->ses->server->maxBuf < 
-			     4096 + MAX_CIFS_HDR_SIZE)
-				inode->i_data.a_ops->readpages = NULL;
+			     PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
+				inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
+			else
+				inode->i_data.a_ops = &cifs_addr_ops;
 		} else if (S_ISDIR(inode->i_mode)) {
 			cFYI(1, ("Directory inode"));
 			inode->i_op = &cifs_dir_inode_ops;
@@ -731,7 +733,7 @@
 	rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
 			  cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 	if (rc) {
-		cFYI(1, ("cifs_mkdir returned 0x%x ", rc));
+		cFYI(1, ("cifs_mkdir returned 0x%x", rc));
 		d_drop(direntry);
 	} else {
 		inode->i_nlink++;
@@ -798,7 +800,7 @@
 	char *full_path = NULL;
 	struct cifsInodeInfo *cifsInode;
 
-	cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode));
+	cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
 
 	xid = GetXid();
 
@@ -1121,7 +1123,7 @@
 
 	xid = GetXid();
 
-	cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ",
+	cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
 		 direntry->d_name.name, attrs->ia_valid));
 
 	cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
@@ -1157,6 +1159,7 @@
 		   when the local oplock break takes longer to flush
 		   writebehind data than the SMB timeout for the SetPathInfo
 		   request would allow */
+
 		open_file = find_writable_file(cifsInode);
 		if (open_file) {
 			__u16 nfid = open_file->netfid;
@@ -1289,7 +1292,7 @@
 		it may be useful to Windows - but we do
 		not want to set ctime unless some other
 		timestamp is changing */
-		cFYI(1, ("CIFS - CTIME changed "));
+		cFYI(1, ("CIFS - CTIME changed"));
 		time_buf.ChangeTime =
 		    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
 	} else
@@ -1356,7 +1359,7 @@
 
 void cifs_delete_inode(struct inode *inode)
 {
-	cFYI(1, ("In cifs_delete_inode, inode = 0x%p ", inode));
+	cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
 	/* may have to add back in if and when safe distributed caching of
 	   directories added e.g. via FindNotify */
 }
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 2ec99f8..a57f5d6 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -167,7 +167,7 @@
 		return -ENOMEM;
 	}
 
-	cFYI(1, ("Full path: %s ", full_path));
+	cFYI(1, ("Full path: %s", full_path));
 	cFYI(1, ("symname is %s", symname));
 
 	/* BB what if DFS and this volume is on different share? BB */
@@ -186,8 +186,7 @@
 						 inode->i_sb,xid);
 
 		if (rc != 0) {
-			cFYI(1,
-			     ("Create symlink worked but get_inode_info failed with rc = %d ",
+			cFYI(1, ("Create symlink ok, getinodeinfo fail rc = %d",
 			      rc));
 		} else {
 			if (pTcon->nocase)
@@ -289,7 +288,7 @@
 					else {
 						cFYI(1,("num referral: %d",num_referrals));
 						if(referrals) {
-							cFYI(1,("referral string: %s ",referrals));
+							cFYI(1,("referral string: %s",referrals));
 							strncpy(tmpbuffer, referrals, len-1);                            
 						}
 					}
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index fafd056..22c937e 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -101,6 +101,7 @@
 	kfree(buf_to_free->serverDomain);
 	kfree(buf_to_free->serverNOS);
 	kfree(buf_to_free->password);
+	kfree(buf_to_free->domainName);
 	kfree(buf_to_free);
 }
 
@@ -499,11 +500,12 @@
 		if(pSMBr->ByteCount > sizeof(struct file_notify_information)) {
 			data_offset = le32_to_cpu(pSMBr->DataOffset);
 
-			pnotify = (struct file_notify_information *)((char *)&pSMBr->hdr.Protocol
-				+ data_offset);
-			cFYI(1,("dnotify on %s with action: 0x%x",pnotify->FileName,
+			pnotify = (struct file_notify_information *)
+				((char *)&pSMBr->hdr.Protocol + data_offset);
+			cFYI(1,("dnotify on %s Action: 0x%x",pnotify->FileName,
 				pnotify->Action));  /* BB removeme BB */
-	             /*   cifs_dump_mem("Received notify Data is: ",buf,sizeof(struct smb_hdr)+60); */
+	             /*   cifs_dump_mem("Rcvd notify Data: ",buf,
+				sizeof(struct smb_hdr)+60); */
 			return TRUE;
 		}
 		if(pSMBr->hdr.Status.CifsError) {
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index 5de74d2..b66eff5 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -84,11 +84,11 @@
 
 static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
 	{ERRerror, -EIO},
-	{ERRbadpw, -EPERM},
+	{ERRbadpw, -EACCES},  /* was EPERM */
 	{ERRbadtype, -EREMOTE},
 	{ERRaccess, -EACCES},
 	{ERRinvtid, -ENXIO},
-	{ERRinvnetname, -ENODEV},
+	{ERRinvnetname, -ENXIO},
 	{ERRinvdevice, -ENXIO},
 	{ERRqfull, -ENOSPC},
 	{ERRqtoobig, -ENOSPC},
diff --git a/fs/cifs/ntlmssp.c b/fs/cifs/ntlmssp.c
deleted file mode 100644
index 115359cc..0000000
--- a/fs/cifs/ntlmssp.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *   fs/cifs/ntlmssp.h
- *
- *   Copyright (c) International Business Machines  Corp., 2006
- *   Author(s): Steve French (sfrench@us.ibm.com)
- *
- *   This library is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU Lesser General Public License as published
- *   by the Free Software Foundation; either version 2.1 of the License, or
- *   (at your option) any later version.
- *
- *   This library is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU Lesser General Public License for more details.
- *
- *   You should have received a copy of the GNU Lesser General Public License
- *   along with this library; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "cifspdu.h"
-#include "cifsglob.h"
-#include "cifsproto.h"
-#include "cifs_unicode.h"
-#include "cifs_debug.h"
-#include "ntlmssp.h"
-#include "nterr.h"
-
-#ifdef CONFIG_CIFS_EXPERIMENTAL
-static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
-{
-	__u32 capabilities = 0;
-
-	/* init fields common to all four types of SessSetup */
-	/* note that header is initialized to zero in header_assemble */
-	pSMB->req.AndXCommand = 0xFF;
-	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
-	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
-	/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
-
-	/* BB verify whether signing required on neg or just on auth frame 
-	   (and NTLM case) */
-
-	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
-			CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
-
-	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-		pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
-	if (ses->capabilities & CAP_UNICODE) {
-		pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
-		capabilities |= CAP_UNICODE;
-	}
-	if (ses->capabilities & CAP_STATUS32) {
-		pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
-		capabilities |= CAP_STATUS32;
-	}
-	if (ses->capabilities & CAP_DFS) {
-		pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
-		capabilities |= CAP_DFS;
-	}
-
-	/* BB check whether to init vcnum BB */
-	return capabilities;
-}
-int 
-CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, const int type,
-		  int * pNTLMv2_flg, const struct nls_table *nls_cp)
-{
-	int rc = 0;
-	int wct;
-	struct smb_hdr *smb_buffer;
-	char *bcc_ptr;
-	SESSION_SETUP_ANDX *pSMB;
-	__u32 capabilities;
-
-	if(ses == NULL)
-		return -EINVAL;
-
-	cFYI(1,("SStp type: %d",type));
-	if(type < CIFS_NTLM) {
-#ifndef CONFIG_CIFS_WEAK_PW_HASH
-		/* LANMAN and plaintext are less secure and off by default.
-		So we make this explicitly be turned on in kconfig (in the
-		build) and turned on at runtime (changed from the default)
-		in proc/fs/cifs or via mount parm.  Unfortunately this is
-		needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
-		return -EOPNOTSUPP;
-#endif
-		wct = 10; /* lanman 2 style sessionsetup */
-	} else if(type < CIFS_NTLMSSP_NEG)
-		wct = 13; /* old style NTLM sessionsetup */
-	else /* same size for negotiate or auth, NTLMSSP or extended security */
-		wct = 12;
-
-	rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
-			    (void **)&smb_buffer);
-	if(rc)
-		return rc;
-
-	pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
-
-	capabilities = cifs_ssetup_hdr(ses, pSMB);
-	bcc_ptr = pByteArea(smb_buffer);
-	if(type > CIFS_NTLM) {
-		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
-		capabilities |= CAP_EXTENDED_SECURITY;
-		pSMB->req.Capabilities = cpu_to_le32(capabilities);
-		/* BB set password lengths */
-	} else if(type < CIFS_NTLM) /* lanman */ {
-		/* no capabilities flags in old lanman negotiation */
-		/* pSMB->old_req.PasswordLength = */ /* BB fixme BB */
-	} else /* type CIFS_NTLM */ {
-		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
-		pSMB->req_no_secext.CaseInsensitivePasswordLength =
-			cpu_to_le16(CIFS_SESSION_KEY_SIZE);
-		pSMB->req_no_secext.CaseSensitivePasswordLength =
-			cpu_to_le16(CIFS_SESSION_KEY_SIZE);
-	}
-
-
-	/* copy session key */
-
-	/* if Unicode, align strings to two byte boundary */
-
-	/* copy user name */ /* BB Do we need to special case null user name? */
-
-	/* copy domain name */
-
-	/* copy Linux version */
-
-	/* copy network operating system name */
-
-	/* update bcc and smb buffer length */
-
-/*	rc = SendReceive2(xid, ses, iov, num_iovecs, &resp_buf_type, 0); */
-	/* SMB request buf freed in SendReceive2 */
-
-	return rc;
-}
-#endif /* CONFIG_CIFS_EXPERIMENTAL */
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index b689c50..03bbcb3 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -21,6 +21,7 @@
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 #include <linux/fs.h>
+#include <linux/pagemap.h>
 #include <linux/stat.h>
 #include <linux/smp_lock.h>
 #include "cifspdu.h"
@@ -31,8 +32,8 @@
 #include "cifs_fs_sb.h"
 #include "cifsfs.h"
 
-/* BB fixme - add debug wrappers around this function to disable it fixme BB */
-/* static void dump_cifs_file_struct(struct file *file, char *label)
+#ifdef CONFIG_CIFS_DEBUG2
+static void dump_cifs_file_struct(struct file *file, char *label)
 {
 	struct cifsFileInfo * cf;
 
@@ -53,7 +54,8 @@
 		}
 		
 	}
-} */
+}
+#endif /* DEBUG2 */
 
 /* Returns one if new inode created (which therefore needs to be hashed) */
 /* Might check in the future if inode number changed so we can rehash inode */
@@ -107,32 +109,52 @@
 	return rc;
 }
 
-static void fill_in_inode(struct inode *tmp_inode,
-	FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode)
+static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
+		char * buf, int *pobject_type, int isNewInode)
 {
 	loff_t local_size;
 	struct timespec local_mtime;
 
 	struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
 	struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb);
-	__u32 attr = le32_to_cpu(pfindData->ExtFileAttributes);
-	__u64 allocation_size = le64_to_cpu(pfindData->AllocationSize);
-	__u64 end_of_file = le64_to_cpu(pfindData->EndOfFile);
-
-	cifsInfo->cifsAttrs = attr;
-	cifsInfo->time = jiffies;
+	__u32 attr;
+	__u64 allocation_size;
+	__u64 end_of_file;
 
 	/* save mtime and size */
 	local_mtime = tmp_inode->i_mtime;
 	local_size  = tmp_inode->i_size;
 
+	if(new_buf_type) {
+		FILE_DIRECTORY_INFO *pfindData = (FILE_DIRECTORY_INFO *)buf;
+
+		attr = le32_to_cpu(pfindData->ExtFileAttributes);
+		allocation_size = le64_to_cpu(pfindData->AllocationSize);
+		end_of_file = le64_to_cpu(pfindData->EndOfFile);
+		tmp_inode->i_atime =
+		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
+		tmp_inode->i_mtime =
+		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
+		tmp_inode->i_ctime =
+		      cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+	} else { /* legacy, OS2 and DOS style */
+		FIND_FILE_STANDARD_INFO * pfindData = 
+			(FIND_FILE_STANDARD_INFO *)buf;
+
+		attr = le16_to_cpu(pfindData->Attributes);
+		allocation_size = le32_to_cpu(pfindData->AllocationSize);
+		end_of_file = le32_to_cpu(pfindData->DataSize);
+		tmp_inode->i_atime = CURRENT_TIME;
+		/* tmp_inode->i_mtime =  BB FIXME - add dos time handling
+		tmp_inode->i_ctime = 0;   BB FIXME */
+
+	}
+
 	/* Linux can not store file creation time unfortunately so ignore it */
-	tmp_inode->i_atime =
-	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime));
-	tmp_inode->i_mtime =
-	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
-	tmp_inode->i_ctime =
-	    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
+
+	cifsInfo->cifsAttrs = attr;
+	cifsInfo->time = jiffies;
+
 	/* treat dos attribute of read-only as read-only mode bit e.g. 555? */
 	/* 2767 perms - indicate mandatory locking */
 		/* BB fill in uid and gid here? with help from winbind? 
@@ -215,11 +237,13 @@
 		else
 			tmp_inode->i_fop = &cifs_file_ops;
 
-		tmp_inode->i_data.a_ops = &cifs_addr_ops;
 		if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
 		   (cifs_sb->tcon->ses->server->maxBuf <
-			4096 + MAX_CIFS_HDR_SIZE))
-			tmp_inode->i_data.a_ops->readpages = NULL;
+			PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
+			tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
+		else
+			tmp_inode->i_data.a_ops = &cifs_addr_ops;
+
 		if(isNewInode)
 			return; /* No sense invalidating pages for new inode
 				   since have not started caching readahead file
@@ -338,11 +362,12 @@
 		else
 			tmp_inode->i_fop = &cifs_file_ops;
 
-		tmp_inode->i_data.a_ops = &cifs_addr_ops;
 		if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
 		   (cifs_sb->tcon->ses->server->maxBuf < 
-			4096 + MAX_CIFS_HDR_SIZE))
-			tmp_inode->i_data.a_ops->readpages = NULL;
+			PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE))
+			tmp_inode->i_data.a_ops = &cifs_addr_ops_smallbuf;
+		else
+			tmp_inode->i_data.a_ops = &cifs_addr_ops;
 
 		if(isNewInode)
 			return; /* No sense invalidating pages for new inode since we
@@ -415,7 +440,10 @@
 ffirst_retry:
 	/* test for Unix extensions */
 	if (pTcon->ses->capabilities & CAP_UNIX) {
-		cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 
+		cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
+	} else if ((pTcon->ses->capabilities & 
+			(CAP_NT_SMBS | CAP_NT_FIND)) == 0) {
+		cifsFile->srch_inf.info_level = SMB_FIND_FILE_INFO_STANDARD;
 	} else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
 		cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
 	} else /* not srvinos - BB fixme add check for backlevel? */ {
@@ -451,12 +479,19 @@
 	return len << 1;
 }
 
-static char *nxt_dir_entry(char *old_entry, char *end_of_smb)
+static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
 {
 	char * new_entry;
 	FILE_DIRECTORY_INFO * pDirInfo = (FILE_DIRECTORY_INFO *)old_entry;
 
-	new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
+	if(level == SMB_FIND_FILE_INFO_STANDARD) {
+		FIND_FILE_STANDARD_INFO * pfData;
+		pfData = (FIND_FILE_STANDARD_INFO *)pDirInfo;
+
+		new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
+				pfData->FileNameLength;
+	} else
+		new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
 	cFYI(1,("new entry %p old entry %p",new_entry,old_entry));
 	/* validate that new_entry is not past end of SMB */
 	if(new_entry >= end_of_smb) {
@@ -464,7 +499,10 @@
 		      ("search entry %p began after end of SMB %p old entry %p",
 			new_entry, end_of_smb, old_entry)); 
 		return NULL;
-	} else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) {
+	} else if(((level == SMB_FIND_FILE_INFO_STANDARD) &&
+		   (new_entry + sizeof(FIND_FILE_STANDARD_INFO) > end_of_smb)) ||
+		  ((level != SMB_FIND_FILE_INFO_STANDARD) &&
+		   (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb)))  {
 		cERROR(1,("search entry %p extends after end of SMB %p",
 			new_entry, end_of_smb));
 		return NULL;
@@ -482,7 +520,7 @@
 	char * filename = NULL;
 	int len = 0; 
 
-	if(cfile->srch_inf.info_level == 0x202) {
+	if(cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
 		FILE_UNIX_INFO * pFindData = (FILE_UNIX_INFO *)current_entry;
 		filename = &pFindData->FileName[0];
 		if(cfile->srch_inf.unicode) {
@@ -491,26 +529,34 @@
 			/* BB should we make this strnlen of PATH_MAX? */
 			len = strnlen(filename, 5);
 		}
-	} else if(cfile->srch_inf.info_level == 0x101) {
+	} else if(cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) {
 		FILE_DIRECTORY_INFO * pFindData = 
 			(FILE_DIRECTORY_INFO *)current_entry;
 		filename = &pFindData->FileName[0];
 		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if(cfile->srch_inf.info_level == 0x102) {
+	} else if(cfile->srch_inf.info_level == 
+			SMB_FIND_FILE_FULL_DIRECTORY_INFO) {
 		FILE_FULL_DIRECTORY_INFO * pFindData = 
 			(FILE_FULL_DIRECTORY_INFO *)current_entry;
 		filename = &pFindData->FileName[0];
 		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if(cfile->srch_inf.info_level == 0x105) {
+	} else if(cfile->srch_inf.info_level ==
+			SMB_FIND_FILE_ID_FULL_DIR_INFO) {
 		SEARCH_ID_FULL_DIR_INFO * pFindData = 
 			(SEARCH_ID_FULL_DIR_INFO *)current_entry;
 		filename = &pFindData->FileName[0];
 		len = le32_to_cpu(pFindData->FileNameLength);
-	} else if(cfile->srch_inf.info_level == 0x104) {
+	} else if(cfile->srch_inf.info_level == 
+			SMB_FIND_FILE_BOTH_DIRECTORY_INFO) {
 		FILE_BOTH_DIRECTORY_INFO * pFindData = 
 			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
 		filename = &pFindData->FileName[0];
 		len = le32_to_cpu(pFindData->FileNameLength);
+	} else if(cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) {
+		FIND_FILE_STANDARD_INFO * pFindData =
+			(FIND_FILE_STANDARD_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		len = le32_to_cpu(pFindData->FileNameLength);
 	} else {
 		cFYI(1,("Unknown findfirst level %d",cfile->srch_inf.info_level));
 	}
@@ -597,7 +643,9 @@
 	. and .. for the root of a drive and for those we need
 	to start two entries earlier */
 
-/*	dump_cifs_file_struct(file, "In fce ");*/
+#ifdef CONFIG_CIFS_DEBUG2
+	dump_cifs_file_struct(file, "In fce ");
+#endif
 	if(((index_to_find < cifsFile->srch_inf.index_of_last_entry) && 
 	     is_dir_changed(file)) || 
 	   (index_to_find < first_entry_in_buffer)) {
@@ -644,10 +692,12 @@
 		first_entry_in_buffer = cifsFile->srch_inf.index_of_last_entry
 					- cifsFile->srch_inf.entries_in_buffer;
 		pos_in_buf = index_to_find - first_entry_in_buffer;
-		cFYI(1,("found entry - pos_in_buf %d",pos_in_buf)); 
+		cFYI(1,("found entry - pos_in_buf %d",pos_in_buf));
+
 		for(i=0;(i<(pos_in_buf)) && (current_entry != NULL);i++) {
 			/* go entry by entry figuring out which is first */
-			current_entry = nxt_dir_entry(current_entry,end_of_smb);
+			current_entry = nxt_dir_entry(current_entry,end_of_smb,
+						cifsFile->srch_inf.info_level);
 		}
 		if((current_entry == NULL) && (i < pos_in_buf)) {
 			/* BB fixme - check if we should flag this error */
@@ -674,7 +724,7 @@
 /* inode num, inode type and filename returned */
 static int cifs_get_name_from_search_buf(struct qstr *pqst,
 	char *current_entry, __u16 level, unsigned int unicode,
-	struct cifs_sb_info * cifs_sb, ino_t *pinum)
+	struct cifs_sb_info * cifs_sb, int max_len, ino_t *pinum)
 {
 	int rc = 0;
 	unsigned int len = 0;
@@ -718,10 +768,22 @@
 			(FILE_BOTH_DIRECTORY_INFO *)current_entry;
 		filename = &pFindData->FileName[0];
 		len = le32_to_cpu(pFindData->FileNameLength);
+	} else if(level == SMB_FIND_FILE_INFO_STANDARD) {
+		FIND_FILE_STANDARD_INFO * pFindData =
+			(FIND_FILE_STANDARD_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		/* one byte length, no name conversion */
+		len = (unsigned int)pFindData->FileNameLength;
 	} else {
 		cFYI(1,("Unknown findfirst level %d",level));
 		return -EINVAL;
 	}
+
+	if(len > max_len) {
+		cERROR(1,("bad search response length %d past smb end", len));
+		return -EINVAL;
+	}
+
 	if(unicode) {
 		/* BB fixme - test with long names */
 		/* Note converted filename can be longer than in unicode */
@@ -741,7 +803,7 @@
 }
 
 static int cifs_filldir(char *pfindEntry, struct file *file,
-	filldir_t filldir, void *direntry, char *scratch_buf)
+	filldir_t filldir, void *direntry, char *scratch_buf, int max_len)
 {
 	int rc = 0;
 	struct qstr qstring;
@@ -777,6 +839,7 @@
 	rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
 			pCifsF->srch_inf.info_level,
 			pCifsF->srch_inf.unicode,cifs_sb,
+			max_len,
 			&inum /* returned */);
 
 	if(rc)
@@ -798,13 +861,16 @@
 	/* we pass in rc below, indicating whether it is a new inode,
 	   so we can figure out whether to invalidate the inode cached
 	   data if the file has changed */
-	if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) {
+	if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX)
 		unix_fill_in_inode(tmp_inode,
-				   (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc);
-	} else {
-		fill_in_inode(tmp_inode,
-			      (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc);
-	}
+				   (FILE_UNIX_INFO *)pfindEntry,
+				   &obj_type, rc);
+	else if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD)
+		fill_in_inode(tmp_inode, 0 /* old level 1 buffer type */,
+				pfindEntry, &obj_type, rc);
+	else
+		fill_in_inode(tmp_inode, 1 /* NT */, pfindEntry, &obj_type, rc);
+	
 	
 	rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,
 		     tmp_inode->i_ino,obj_type);
@@ -864,6 +930,12 @@
 		filename = &pFindData->FileName[0];
 		len = le32_to_cpu(pFindData->FileNameLength);
 		cifsFile->srch_inf.resume_key = pFindData->FileIndex;
+	} else if(level == SMB_FIND_FILE_INFO_STANDARD) {
+		FIND_FILE_STANDARD_INFO * pFindData =
+			(FIND_FILE_STANDARD_INFO *)current_entry;
+		filename = &pFindData->FileName[0];
+		/* one byte length, no name conversion */
+		len = (unsigned int)pFindData->FileNameLength;
 	} else {
 		cFYI(1,("Unknown findfirst level %d",level));
 		return -EINVAL;
@@ -884,6 +956,7 @@
 	int num_to_fill = 0;
 	char * tmp_buf = NULL;
 	char * end_of_smb;
+	int max_len;
 
 	xid = GetXid();
 
@@ -909,7 +982,7 @@
 	case 1:
 		if (filldir(direntry, "..", 2, file->f_pos,
 		     file->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {
-			cERROR(1, ("Filldir for parent dir failed "));
+			cERROR(1, ("Filldir for parent dir failed"));
 			rc = -ENOMEM;
 			break;
 		}
@@ -959,10 +1032,11 @@
 			goto rddir2_exit;
 		}
 		cFYI(1,("loop through %d times filling dir for net buf %p",
-			num_to_fill,cifsFile->srch_inf.ntwrk_buf_start)); 
-		end_of_smb = cifsFile->srch_inf.ntwrk_buf_start +
-			smbCalcSize((struct smb_hdr *)
-				    cifsFile->srch_inf.ntwrk_buf_start);
+			num_to_fill,cifsFile->srch_inf.ntwrk_buf_start));
+		max_len = smbCalcSize((struct smb_hdr *)
+				cifsFile->srch_inf.ntwrk_buf_start);
+		end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
+
 		/* To be safe - for UCS to UTF-8 with strings loaded
 		with the rare long characters alloc more to account for
 		such multibyte target UTF-8 characters. cifs_unicode.c,
@@ -977,17 +1051,19 @@
 			}
 			/* if buggy server returns . and .. late do
 			we want to check for that here? */
-			rc = cifs_filldir(current_entry, file, 
-					filldir, direntry,tmp_buf);
+			rc = cifs_filldir(current_entry, file,
+					filldir, direntry, tmp_buf, max_len);
 			file->f_pos++;
-			if(file->f_pos == cifsFile->srch_inf.index_of_last_entry) {
+			if(file->f_pos == 
+				cifsFile->srch_inf.index_of_last_entry) {
 				cFYI(1,("last entry in buf at pos %lld %s",
-					file->f_pos,tmp_buf)); /* BB removeme BB */
+					file->f_pos,tmp_buf));
 				cifs_save_resume_key(current_entry,cifsFile);
 				break;
 			} else 
-				current_entry = nxt_dir_entry(current_entry,
-							      end_of_smb);
+				current_entry = 
+					nxt_dir_entry(current_entry, end_of_smb,
+						cifsFile->srch_inf.info_level);
 		}
 		kfree(tmp_buf);
 		break;
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
new file mode 100644
index 0000000..7202d53
--- /dev/null
+++ b/fs/cifs/sess.c
@@ -0,0 +1,538 @@
+/*
+ *   fs/cifs/sess.c
+ *
+ *   SMB/CIFS session setup handling routines
+ *
+ *   Copyright (c) International Business Machines  Corp., 2006
+ *   Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ *   This library is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU Lesser General Public License as published
+ *   by the Free Software Foundation; either version 2.1 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This library is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+ *   the GNU Lesser General Public License for more details.
+ *
+ *   You should have received a copy of the GNU Lesser General Public License
+ *   along with this library; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifsproto.h"
+#include "cifs_unicode.h"
+#include "cifs_debug.h"
+#include "ntlmssp.h"
+#include "nterr.h"
+#include <linux/utsname.h>
+
+extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
+                         unsigned char *p24);
+
+static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
+{
+	__u32 capabilities = 0;
+
+	/* init fields common to all four types of SessSetup */
+	/* note that header is initialized to zero in header_assemble */
+	pSMB->req.AndXCommand = 0xFF;
+	pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
+	pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+
+	/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
+
+	/* BB verify whether signing required on neg or just on auth frame 
+	   (and NTLM case) */
+
+	capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
+			CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
+
+	if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+		pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
+	if (ses->capabilities & CAP_UNICODE) {
+		pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE;
+		capabilities |= CAP_UNICODE;
+	}
+	if (ses->capabilities & CAP_STATUS32) {
+		pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS;
+		capabilities |= CAP_STATUS32;
+	}
+	if (ses->capabilities & CAP_DFS) {
+		pSMB->req.hdr.Flags2 |= SMBFLG2_DFS;
+		capabilities |= CAP_DFS;
+	}
+	if (ses->capabilities & CAP_UNIX) {
+		capabilities |= CAP_UNIX;
+	}
+
+	/* BB check whether to init vcnum BB */
+	return capabilities;
+}
+
+static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
+			    const struct nls_table * nls_cp)
+{
+	char * bcc_ptr = *pbcc_area;
+	int bytes_ret = 0;
+
+	/* BB FIXME add check that strings total less
+	than 335 or will need to send them as arrays */
+
+	/* unicode strings, must be word aligned before the call */
+/*	if ((long) bcc_ptr % 2)	{
+		*bcc_ptr = 0;
+		bcc_ptr++;
+	} */
+	/* copy user */
+	if(ses->userName == NULL) {
+		/* BB what about null user mounts - check that we do this BB */
+	} else { /* 300 should be long enough for any conceivable user name */
+		bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
+					  300, nls_cp);
+	}
+	bcc_ptr += 2 * bytes_ret;
+	bcc_ptr += 2; /* account for null termination */
+	/* copy domain */
+	if(ses->domainName == NULL)
+		bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr,
+					  "CIFS_LINUX_DOM", 32, nls_cp);
+	else
+		bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, 
+					  256, nls_cp);
+	bcc_ptr += 2 * bytes_ret;
+	bcc_ptr += 2;  /* account for null terminator */
+
+	/* Copy OS version */
+	bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32,
+				  nls_cp);
+	bcc_ptr += 2 * bytes_ret;
+	bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release,
+				  32, nls_cp);
+	bcc_ptr += 2 * bytes_ret;
+	bcc_ptr += 2; /* trailing null */
+
+	bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
+                                  32, nls_cp);
+	bcc_ptr += 2 * bytes_ret;
+	bcc_ptr += 2; /* trailing null */
+
+	*pbcc_area = bcc_ptr;
+}
+
+static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses,
+			  const struct nls_table * nls_cp)
+{
+	char * bcc_ptr = *pbcc_area;
+
+	/* copy user */
+	/* BB what about null user mounts - check that we do this BB */
+        /* copy user */
+        if(ses->userName == NULL) {
+                /* BB what about null user mounts - check that we do this BB */
+        } else { /* 300 should be long enough for any conceivable user name */
+                strncpy(bcc_ptr, ses->userName, 300);
+        }
+	/* BB improve check for overflow */
+        bcc_ptr += strnlen(ses->userName, 300);
+	*bcc_ptr = 0;
+        bcc_ptr++; /* account for null termination */
+
+        /* copy domain */
+	
+        if(ses->domainName == NULL) {
+                strcpy(bcc_ptr, "CIFS_LINUX_DOM");
+		bcc_ptr += 14;  /* strlen(CIFS_LINUX_DOM) */
+ 	} else {
+                strncpy(bcc_ptr, ses->domainName, 256); 
+		bcc_ptr += strnlen(ses->domainName, 256);
+	}
+	*bcc_ptr = 0;
+	bcc_ptr++;
+
+	/* BB check for overflow here */
+
+	strcpy(bcc_ptr, "Linux version ");
+	bcc_ptr += strlen("Linux version ");
+	strcpy(bcc_ptr, system_utsname.release);
+	bcc_ptr += strlen(system_utsname.release) + 1;
+
+	strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
+	bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
+
+        *pbcc_area = bcc_ptr;
+}
+
+static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
+                            const struct nls_table * nls_cp)
+{
+	int rc = 0;
+	int words_left, len;
+	char * data = *pbcc_area;
+
+
+
+	cFYI(1,("bleft %d",bleft));
+
+
+	/* word align, if bytes remaining is not even */
+	if(bleft % 2) {
+		bleft--;
+		data++;
+	}
+	words_left = bleft / 2;
+
+	/* save off server operating system */
+	len = UniStrnlen((wchar_t *) data, words_left);
+
+/* We look for obvious messed up bcc or strings in response so we do not go off
+   the end since (at least) WIN2K and Windows XP have a major bug in not null
+   terminating last Unicode string in response  */
+	if(len >= words_left)
+		return rc;
+
+	if(ses->serverOS)
+		kfree(ses->serverOS);
+	/* UTF-8 string will not grow more than four times as big as UCS-16 */
+	ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
+	if(ses->serverOS != NULL) {
+		cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len,
+				   nls_cp);
+	}
+	data += 2 * (len + 1);
+	words_left -= len + 1;
+
+	/* save off server network operating system */
+	len = UniStrnlen((wchar_t *) data, words_left);
+
+	if(len >= words_left)
+		return rc;
+
+	if(ses->serverNOS)
+		kfree(ses->serverNOS);
+	ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
+	if(ses->serverNOS != NULL) {
+		cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
+				   nls_cp);
+		if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) {
+			cFYI(1,("NT4 server"));
+			ses->flags |= CIFS_SES_NT4;
+		}
+	}
+	data += 2 * (len + 1);
+	words_left -= len + 1;
+
+        /* save off server domain */
+        len = UniStrnlen((wchar_t *) data, words_left);
+
+        if(len > words_left)
+                return rc;
+
+        if(ses->serverDomain)
+                kfree(ses->serverDomain);
+        ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */
+        if(ses->serverDomain != NULL) {
+                cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
+                                   nls_cp);
+                ses->serverDomain[2*len] = 0;
+                ses->serverDomain[(2*len) + 1] = 0;
+        }
+        data += 2 * (len + 1);
+        words_left -= len + 1;
+	
+	cFYI(1,("words left: %d",words_left));
+
+	return rc;
+}
+
+static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses,
+                            const struct nls_table * nls_cp)
+{
+	int rc = 0;
+	int len;
+	char * bcc_ptr = *pbcc_area;
+
+	cFYI(1,("decode sessetup ascii. bleft %d", bleft));
+	
+	len = strnlen(bcc_ptr, bleft);
+	if(len >= bleft)
+		return rc;
+	
+	if(ses->serverOS)
+		kfree(ses->serverOS);
+
+	ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
+	if(ses->serverOS)
+		strncpy(ses->serverOS, bcc_ptr, len);
+
+	bcc_ptr += len + 1;
+	bleft -= len + 1;
+
+	len = strnlen(bcc_ptr, bleft);
+	if(len >= bleft)
+		return rc;
+
+	if(ses->serverNOS)
+		kfree(ses->serverNOS);
+
+	ses->serverNOS = kzalloc(len + 1, GFP_KERNEL);
+	if(ses->serverNOS)
+		strncpy(ses->serverNOS, bcc_ptr, len);
+
+	bcc_ptr += len + 1;
+	bleft -= len + 1;
+
+        len = strnlen(bcc_ptr, bleft);
+        if(len > bleft)
+                return rc;
+
+        if(ses->serverDomain)
+                kfree(ses->serverDomain);
+
+        ses->serverDomain = kzalloc(len + 1, GFP_KERNEL);
+        if(ses->serverOS)
+                strncpy(ses->serverOS, bcc_ptr, len);
+
+        bcc_ptr += len + 1;
+	bleft -= len + 1;
+
+	cFYI(1,("ascii: bytes left %d",bleft));
+
+	return rc;
+}
+
+int 
+CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
+		const struct nls_table *nls_cp)
+{
+	int rc = 0;
+	int wct;
+	struct smb_hdr *smb_buf;
+	char *bcc_ptr;
+	char *str_area;
+	SESSION_SETUP_ANDX *pSMB;
+	__u32 capabilities;
+	int count;
+	int resp_buf_type = 0;
+	struct kvec iov[2];
+	enum securityEnum type;
+	__u16 action;
+	int bytes_remaining;
+
+	if(ses == NULL)
+		return -EINVAL;
+
+	type = ses->server->secType;
+
+	cFYI(1,("sess setup type %d",type));
+	if(type == LANMAN) {
+#ifndef CONFIG_CIFS_WEAK_PW_HASH
+		/* LANMAN and plaintext are less secure and off by default.
+		So we make this explicitly be turned on in kconfig (in the
+		build) and turned on at runtime (changed from the default)
+		in proc/fs/cifs or via mount parm.  Unfortunately this is
+		needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
+		return -EOPNOTSUPP;
+#endif
+		wct = 10; /* lanman 2 style sessionsetup */
+	} else if((type == NTLM) || (type == NTLMv2)) { 
+		/* For NTLMv2 failures eventually may need to retry NTLM */
+		wct = 13; /* old style NTLM sessionsetup */
+	} else /* same size for negotiate or auth, NTLMSSP or extended security */
+		wct = 12;
+
+	rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
+			    (void **)&smb_buf);
+	if(rc)
+		return rc;
+
+	pSMB = (SESSION_SETUP_ANDX *)smb_buf;
+
+	capabilities = cifs_ssetup_hdr(ses, pSMB);
+
+	/* we will send the SMB in two pieces,
+	a fixed length beginning part, and a
+	second part which will include the strings
+	and rest of bcc area, in order to avoid having
+	to do a large buffer 17K allocation */
+        iov[0].iov_base = (char *)pSMB;
+        iov[0].iov_len = smb_buf->smb_buf_length + 4;
+
+	/* 2000 big enough to fit max user, domain, NOS name etc. */
+	str_area = kmalloc(2000, GFP_KERNEL);
+	bcc_ptr = str_area;
+
+	if(type == LANMAN) {
+#ifdef CONFIG_CIFS_WEAK_PW_HASH
+		char lnm_session_key[CIFS_SESS_KEY_SIZE];
+
+		/* no capabilities flags in old lanman negotiation */
+
+		pSMB->old_req.PasswordLength = CIFS_SESS_KEY_SIZE; 
+		/* BB calculate hash with password */
+		/* and copy into bcc */
+
+		calc_lanman_hash(ses, lnm_session_key);
+
+/* #ifdef CONFIG_CIFS_DEBUG2
+		cifs_dump_mem("cryptkey: ",ses->server->cryptKey,
+			CIFS_SESS_KEY_SIZE);
+#endif */
+		memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
+
+		/* can not sign if LANMAN negotiated so no need
+		to calculate signing key? but what if server
+		changed to do higher than lanman dialect and
+		we reconnected would we ever calc signing_key? */
+
+		cFYI(1,("Negotiating LANMAN setting up strings"));
+		/* Unicode not allowed for LANMAN dialects */
+		ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+#endif    
+	} else if (type == NTLM) {
+		char ntlm_session_key[CIFS_SESS_KEY_SIZE];
+
+		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+		pSMB->req_no_secext.CaseInsensitivePasswordLength =
+			cpu_to_le16(CIFS_SESS_KEY_SIZE);
+		pSMB->req_no_secext.CaseSensitivePasswordLength =
+			cpu_to_le16(CIFS_SESS_KEY_SIZE);
+	
+		/* calculate session key */
+		SMBNTencrypt(ses->password, ses->server->cryptKey,
+			     ntlm_session_key);
+
+		if(first_time) /* should this be moved into common code 
+				  with similar ntlmv2 path? */
+			cifs_calculate_mac_key(ses->server->mac_signing_key,
+				ntlm_session_key, ses->password);
+		/* copy session key */
+
+		memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
+		memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE);
+		bcc_ptr += CIFS_SESS_KEY_SIZE;
+		if(ses->capabilities & CAP_UNICODE) {
+			/* unicode strings must be word aligned */
+			if (iov[0].iov_len % 2) {
+				*bcc_ptr = 0;
+				bcc_ptr++;		
+			}	
+			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
+		} else
+			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+	} else if (type == NTLMv2) {
+		char * v2_sess_key = 
+			kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);
+
+		/* BB FIXME change all users of v2_sess_key to
+		   struct ntlmv2_resp */
+
+		if(v2_sess_key == NULL) {
+			cifs_small_buf_release(smb_buf);
+			return -ENOMEM;
+		}
+
+		pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
+
+		/* LM2 password would be here if we supported it */
+		pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+		/*	cpu_to_le16(LM2_SESS_KEY_SIZE); */
+
+		pSMB->req_no_secext.CaseSensitivePasswordLength =
+			cpu_to_le16(sizeof(struct ntlmv2_resp));
+
+		/* calculate session key */
+		setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
+		if(first_time) /* should this be moved into common code
+			          with similar ntlmv2 path? */
+		/*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
+				response BB FIXME, v2_sess_key); */
+
+		/* copy session key */
+
+	/*	memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
+		bcc_ptr += LM2_SESS_KEY_SIZE; */
+		memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp));
+		bcc_ptr += sizeof(struct ntlmv2_resp);
+		kfree(v2_sess_key);
+		if(ses->capabilities & CAP_UNICODE) {
+			if(iov[0].iov_len % 2) {
+				*bcc_ptr = 0;
+			}	bcc_ptr++;
+			unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
+		} else
+			ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
+	} else /* NTLMSSP or SPNEGO */ {
+		pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+		capabilities |= CAP_EXTENDED_SECURITY;
+		pSMB->req.Capabilities = cpu_to_le32(capabilities);
+		/* BB set password lengths */
+	}
+
+	count = (long) bcc_ptr - (long) str_area;
+	smb_buf->smb_buf_length += count;
+
+	BCC_LE(smb_buf) = cpu_to_le16(count);
+
+	iov[1].iov_base = str_area;
+	iov[1].iov_len = count; 
+	rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0);
+	/* SMB request buf freed in SendReceive2 */
+
+	cFYI(1,("ssetup rc from sendrecv2 is %d",rc));
+	if(rc)
+		goto ssetup_exit;
+
+	pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
+	smb_buf = (struct smb_hdr *)iov[0].iov_base;
+
+	if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
+		rc = -EIO;
+		cERROR(1,("bad word count %d", smb_buf->WordCount));
+		goto ssetup_exit;
+	}
+	action = le16_to_cpu(pSMB->resp.Action);
+	if (action & GUEST_LOGIN)
+		cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
+	ses->Suid = smb_buf->Uid;   /* UID left in wire format (le) */
+	cFYI(1, ("UID = %d ", ses->Suid));
+	/* response can have either 3 or 4 word count - Samba sends 3 */
+	/* and lanman response is 3 */
+	bytes_remaining = BCC(smb_buf);
+	bcc_ptr = pByteArea(smb_buf);
+
+	if(smb_buf->WordCount == 4) {
+		__u16 blob_len;
+		blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
+		bcc_ptr += blob_len;
+		if(blob_len > bytes_remaining) {
+			cERROR(1,("bad security blob length %d", blob_len));
+			rc = -EINVAL;
+			goto ssetup_exit;
+		}
+		bytes_remaining -= blob_len;
+	}	
+
+	/* BB check if Unicode and decode strings */
+	if(smb_buf->Flags2 & SMBFLG2_UNICODE)
+		rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
+						   ses, nls_cp);
+	else
+		rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp);
+	
+ssetup_exit:
+	kfree(str_area);
+	if(resp_buf_type == CIFS_SMALL_BUFFER) {
+		cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base));
+		cifs_small_buf_release(iov[0].iov_base);
+	} else if(resp_buf_type == CIFS_LARGE_BUFFER)
+		cifs_buf_release(iov[0].iov_base);
+
+	return rc;
+}
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 6103bcd..f518c5e 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -30,6 +30,7 @@
 #include <linux/random.h>
 #include "cifs_unicode.h"
 #include "cifspdu.h"
+#include "cifsglob.h"
 #include "md5.h"
 #include "cifs_debug.h"
 #include "cifsencrypt.h"
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 3da8040..17ba329 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -654,8 +654,7 @@
 
 	if (in_buf->smb_buf_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) {
 		up(&ses->server->tcpSem);
-		cERROR(1,
-		       ("Illegal length, greater than maximum frame, %d ",
+		cERROR(1, ("Illegal length, greater than maximum frame, %d",
 			in_buf->smb_buf_length));
 		DeleteMidQEntry(midQ);
 		/* If not lock req, update # of requests on wire to server */
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 7c26424..cc66c68 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -164,7 +164,7 @@
 	return 0;
 }
 
-int coda_flush(struct file *coda_file)
+int coda_flush(struct file *coda_file, fl_owner_t id)
 {
 	unsigned short flags = coda_file->f_flags & ~O_EXCL;
 	unsigned short coda_flags = coda_flags_to_cflags(flags);
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index ada1a81..87f1dc8 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -36,7 +36,7 @@
 /* VFS super_block ops */
 static void coda_clear_inode(struct inode *);
 static void coda_put_super(struct super_block *);
-static int coda_statfs(struct super_block *sb, struct kstatfs *buf);
+static int coda_statfs(struct dentry *dentry, struct kstatfs *buf);
 
 static kmem_cache_t * coda_inode_cachep;
 
@@ -278,13 +278,13 @@
 	.setattr	= coda_setattr,
 };
 
-static int coda_statfs(struct super_block *sb, struct kstatfs *buf)
+static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	int error;
 	
 	lock_kernel();
 
-	error = venus_statfs(sb, buf);
+	error = venus_statfs(dentry, buf);
 
 	unlock_kernel();
 
@@ -307,10 +307,10 @@
 
 /* init_coda: used by filesystems.c to register coda */
 
-static struct super_block *coda_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int coda_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, coda_fill_super);
+	return get_sb_nodev(fs_type, flags, data, coda_fill_super, mnt);
 }
 
 struct file_system_type coda_fs_type = {
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 6c6771d..7caee8d 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -259,7 +259,7 @@
 	/* If request was not a signal, enqueue and don't free */
 	if (!(req->uc_flags & REQ_ASYNC)) {
 		req->uc_flags |= REQ_READ;
-		list_add(&(req->uc_chain), vcp->vc_processing.prev);
+		list_add_tail(&(req->uc_chain), &vcp->vc_processing);
 		goto out;
 	}
 
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index b35e5bb..76e00a6 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -50,6 +50,6 @@
 	return error;
 }
 
-struct address_space_operations coda_symlink_aops = {
+const struct address_space_operations coda_symlink_aops = {
 	.readpage	= coda_symlink_filler,
 };
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index 1bae996..a5b5e63 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -611,7 +611,7 @@
 	return error;
 }
 
-int venus_statfs(struct super_block *sb, struct kstatfs *sfs) 
+int venus_statfs(struct dentry *dentry, struct kstatfs *sfs)
 { 
         union inputArgs *inp;
         union outputArgs *outp;
@@ -620,7 +620,7 @@
 	insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs));
 	UPARG(CODA_STATFS);
 
-        error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
+        error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp);
 	
         if (!error) {
 		sfs->f_blocks = outp->coda_statfs.stat.f_blocks;
@@ -725,7 +725,7 @@
 	((union inputArgs *)buffer)->ih.unique = req->uc_unique;
 
 	/* Append msg to pending queue and poke Venus. */
-	list_add(&(req->uc_chain), vcommp->vc_pending.prev);
+	list_add_tail(&(req->uc_chain), &vcommp->vc_pending);
         
 	wake_up_interruptible(&vcommp->vc_waitq);
 	/* We can be interrupted while we wait for Venus to process
diff --git a/fs/compat.c b/fs/compat.c
index b1f6478..e31e9cf 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -55,6 +55,20 @@
 
 extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
 
+int compat_log = 1;
+
+int compat_printk(const char *fmt, ...)
+{
+	va_list ap;
+	int ret;
+	if (!compat_log)
+		return 0;
+	va_start(ap, fmt);
+	ret = vprintk(fmt, ap);
+	va_end(ap);
+	return ret;
+}
+
 /*
  * Not all architectures have sys_utime, so implement this in terms
  * of sys_utimes.
@@ -197,7 +211,7 @@
 	error = user_path_walk(path, &nd);
 	if (!error) {
 		struct kstatfs tmp;
-		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
+		error = vfs_statfs(nd.dentry, &tmp);
 		if (!error)
 			error = put_compat_statfs(buf, &tmp);
 		path_release(&nd);
@@ -215,7 +229,7 @@
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+	error = vfs_statfs(file->f_dentry, &tmp);
 	if (!error)
 		error = put_compat_statfs(buf, &tmp);
 	fput(file);
@@ -265,7 +279,7 @@
 	error = user_path_walk(path, &nd);
 	if (!error) {
 		struct kstatfs tmp;
-		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
+		error = vfs_statfs(nd.dentry, &tmp);
 		if (!error)
 			error = put_compat_statfs64(buf, &tmp);
 		path_release(&nd);
@@ -286,7 +300,7 @@
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+	error = vfs_statfs(file->f_dentry, &tmp);
 	if (!error)
 		error = put_compat_statfs64(buf, &tmp);
 	fput(file);
@@ -359,7 +373,7 @@
 	sprintf(buf,"'%c'", (cmd>>24) & 0x3f);
 	if (!isprint(buf[1]))
 		sprintf(buf, "%02x", buf[1]);
-	printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
+	compat_printk("ioctl32(%s:%d): Unknown cmd fd(%d) "
 			"cmd(%08x){%s} arg(%08x) on %s\n",
 			current->comm, current->pid,
 			(int)fd, (unsigned int)cmd, buf,
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index d2c3887..d8ecfed 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -80,6 +80,7 @@
 #include <net/bluetooth/rfcomm.h>
 
 #include <linux/capi.h>
+#include <linux/gigaset_dev.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_ioctl.h>
@@ -205,38 +206,6 @@
 	return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg));
 }
 
-struct compat_dmx_event {
-	dmx_event_t	event;
-	compat_time_t	timeStamp;
-	union
-	{
-		dmx_scrambling_status_t scrambling;
-	} u;
-};
-
-static int do_dmx_get_event(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct dmx_event kevent;
-	mm_segment_t old_fs = get_fs();
-	int err;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long) &kevent);
-	set_fs(old_fs);
-
-	if (!err) {
-		struct compat_dmx_event __user *up = compat_ptr(arg);
-
-		err  = put_user(kevent.event, &up->event);
-		err |= put_user(kevent.timeStamp, &up->timeStamp);
-		err |= put_user(kevent.u.scrambling, &up->u.scrambling);
-		if (err)
-			err = -EFAULT;
-	}
-
-	return err;
-}
-
 struct compat_video_event {
 	int32_t		type;
 	compat_time_t	timestamp;
@@ -2964,7 +2933,6 @@
 #endif
 
 /* dvb */
-HANDLE_IOCTL(DMX_GET_EVENT, do_dmx_get_event)
 HANDLE_IOCTL(VIDEO_GET_EVENT, do_video_get_event)
 HANDLE_IOCTL(VIDEO_STILLPICTURE, do_video_stillpicture)
 HANDLE_IOCTL(VIDEO_SET_SPU_PALETTE, do_video_set_spu_palette)
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
index 5f95218..207f800 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -1009,8 +1009,7 @@
 			/* fallthrough */
 		default:
 			if (filp->f_pos == 2) {
-				list_del(q);
-				list_add(q, &parent_sd->s_children);
+				list_move(q, &parent_sd->s_children);
 			}
 			for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
 				struct configfs_dirent *next;
@@ -1033,8 +1032,7 @@
 						 dt_type(next)) < 0)
 					return 0;
 
-				list_del(q);
-				list_add(q, p);
+				list_move(q, p);
 				p = q;
 				filp->f_pos++;
 			}
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index c153bd9..e14488c 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -38,7 +38,7 @@
 
 extern struct super_block * configfs_sb;
 
-static struct address_space_operations configfs_aops = {
+static const struct address_space_operations configfs_aops = {
 	.readpage	= simple_readpage,
 	.prepare_write	= simple_prepare_write,
 	.commit_write	= simple_commit_write
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c
index f920d30..3e5fe84 100644
--- a/fs/configfs/mount.c
+++ b/fs/configfs/mount.c
@@ -103,10 +103,10 @@
 	return 0;
 }
 
-static struct super_block *configfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int configfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, configfs_fill_super);
+	return get_sb_single(fs_type, flags, data, configfs_fill_super, mnt);
 }
 
 static struct file_system_type configfs_fs_type = {
@@ -118,7 +118,7 @@
 
 int configfs_pin_fs(void)
 {
-	return simple_pin_fs("configfs", &configfs_mount,
+	return simple_pin_fs(&configfs_fs_type, &configfs_mount,
 			     &configfs_mnt_count);
 }
 
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 9efcc3a..223c043 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -30,7 +30,7 @@
 static struct super_operations cramfs_ops;
 static struct inode_operations cramfs_dir_inode_operations;
 static const struct file_operations cramfs_directory_operations;
-static struct address_space_operations cramfs_aops;
+static const struct address_space_operations cramfs_aops;
 
 static DEFINE_MUTEX(read_mutex);
 
@@ -181,9 +181,7 @@
 		struct page *page = NULL;
 
 		if (blocknr + i < devsize) {
-			page = read_cache_page(mapping, blocknr + i,
-				(filler_t *)mapping->a_ops->readpage,
-				NULL);
+			page = read_mapping_page(mapping, blocknr + i, NULL);
 			/* synchronous error? */
 			if (IS_ERR(page))
 				page = NULL;
@@ -322,8 +320,10 @@
 	return -EINVAL;
 }
 
-static int cramfs_statfs(struct super_block *sb, struct kstatfs *buf)
+static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
+
 	buf->f_type = CRAMFS_MAGIC;
 	buf->f_bsize = PAGE_CACHE_SIZE;
 	buf->f_blocks = CRAMFS_SB(sb)->blocks;
@@ -501,7 +501,7 @@
 	return 0;
 }
 
-static struct address_space_operations cramfs_aops = {
+static const struct address_space_operations cramfs_aops = {
 	.readpage = cramfs_readpage
 };
 
@@ -528,10 +528,11 @@
 	.statfs		= cramfs_statfs,
 };
 
-static struct super_block *cramfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int cramfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type cramfs_fs_type = {
diff --git a/fs/dcache.c b/fs/dcache.c
index 940d188..48b44a7 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -359,12 +359,13 @@
 }
 
 /*
- * Throw away a dentry - free the inode, dput the parent.
- * This requires that the LRU list has already been
- * removed.
+ * Throw away a dentry - free the inode, dput the parent.  This requires that
+ * the LRU list has already been removed.
+ *
  * Called with dcache_lock, drops it and then regains.
+ * Called with dentry->d_lock held, drops it.
  */
-static inline void prune_one_dentry(struct dentry * dentry)
+static void prune_one_dentry(struct dentry * dentry)
 {
 	struct dentry * parent;
 
@@ -382,6 +383,8 @@
 /**
  * prune_dcache - shrink the dcache
  * @count: number of entries to try and free
+ * @sb: if given, ignore dentries for other superblocks
+ *         which are being unmounted.
  *
  * Shrink the dcache. This is done when we need
  * more memory, or simply when we need to unmount
@@ -392,16 +395,29 @@
  * all the dentries are in use.
  */
  
-static void prune_dcache(int count)
+static void prune_dcache(int count, struct super_block *sb)
 {
 	spin_lock(&dcache_lock);
 	for (; count ; count--) {
 		struct dentry *dentry;
 		struct list_head *tmp;
+		struct rw_semaphore *s_umount;
 
 		cond_resched_lock(&dcache_lock);
 
 		tmp = dentry_unused.prev;
+		if (sb) {
+			/* Try to find a dentry for this sb, but don't try
+			 * too hard, if they aren't near the tail they will
+			 * be moved down again soon
+			 */
+			int skip = count;
+			while (skip && tmp != &dentry_unused &&
+			    list_entry(tmp, struct dentry, d_lru)->d_sb != sb) {
+				skip--;
+				tmp = tmp->prev;
+			}
+		}
 		if (tmp == &dentry_unused)
 			break;
 		list_del_init(tmp);
@@ -427,7 +443,45 @@
  			spin_unlock(&dentry->d_lock);
 			continue;
 		}
-		prune_one_dentry(dentry);
+		/*
+		 * If the dentry is not DCACHED_REFERENCED, it is time
+		 * to remove it from the dcache, provided the super block is
+		 * NULL (which means we are trying to reclaim memory)
+		 * or this dentry belongs to the same super block that
+		 * we want to shrink.
+		 */
+		/*
+		 * If this dentry is for "my" filesystem, then I can prune it
+		 * without taking the s_umount lock (I already hold it).
+		 */
+		if (sb && dentry->d_sb == sb) {
+			prune_one_dentry(dentry);
+			continue;
+		}
+		/*
+		 * ...otherwise we need to be sure this filesystem isn't being
+		 * unmounted, otherwise we could race with
+		 * generic_shutdown_super(), and end up holding a reference to
+		 * an inode while the filesystem is unmounted.
+		 * So we try to get s_umount, and make sure s_root isn't NULL.
+		 * (Take a local copy of s_umount to avoid a use-after-free of
+		 * `dentry').
+		 */
+		s_umount = &dentry->d_sb->s_umount;
+		if (down_read_trylock(s_umount)) {
+			if (dentry->d_sb->s_root != NULL) {
+				prune_one_dentry(dentry);
+				up_read(s_umount);
+				continue;
+			}
+			up_read(s_umount);
+		}
+		spin_unlock(&dentry->d_lock);
+		/* Cannot remove the first dentry, and it isn't appropriate
+		 * to move it to the head of the list, so give up, and try
+		 * later
+		 */
+		break;
 	}
 	spin_unlock(&dcache_lock);
 }
@@ -468,8 +522,7 @@
 		dentry = list_entry(tmp, struct dentry, d_lru);
 		if (dentry->d_sb != sb)
 			continue;
-		list_del(tmp);
-		list_add(tmp, &dentry_unused);
+		list_move(tmp, &dentry_unused);
 	}
 
 	/*
@@ -584,7 +637,7 @@
 		 * of the unused list for prune_dcache
 		 */
 		if (!atomic_read(&dentry->d_count)) {
-			list_add(&dentry->d_lru, dentry_unused.prev);
+			list_add_tail(&dentry->d_lru, &dentry_unused);
 			dentry_stat.nr_unused++;
 			found++;
 		}
@@ -630,46 +683,7 @@
 	int found;
 
 	while ((found = select_parent(parent)) != 0)
-		prune_dcache(found);
-}
-
-/**
- * shrink_dcache_anon - further prune the cache
- * @head: head of d_hash list of dentries to prune
- *
- * Prune the dentries that are anonymous
- *
- * parsing d_hash list does not hlist_for_each_entry_rcu() as it
- * done under dcache_lock.
- *
- */
-void shrink_dcache_anon(struct hlist_head *head)
-{
-	struct hlist_node *lp;
-	int found;
-	do {
-		found = 0;
-		spin_lock(&dcache_lock);
-		hlist_for_each(lp, head) {
-			struct dentry *this = hlist_entry(lp, struct dentry, d_hash);
-			if (!list_empty(&this->d_lru)) {
-				dentry_stat.nr_unused--;
-				list_del_init(&this->d_lru);
-			}
-
-			/* 
-			 * move only zero ref count dentries to the end 
-			 * of the unused list for prune_dcache
-			 */
-			if (!atomic_read(&this->d_count)) {
-				list_add_tail(&this->d_lru, &dentry_unused);
-				dentry_stat.nr_unused++;
-				found++;
-			}
-		}
-		spin_unlock(&dcache_lock);
-		prune_dcache(found);
-	} while(found);
+		prune_dcache(found, parent->d_sb);
 }
 
 /*
@@ -689,7 +703,7 @@
 	if (nr) {
 		if (!(gfp_mask & __GFP_FS))
 			return -1;
-		prune_dcache(nr);
+		prune_dcache(nr, NULL);
 	}
 	return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure;
 }
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index b55b4ea..6fa1e04 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -111,11 +111,11 @@
 	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
 }
 
-static struct super_block *debug_get_sb(struct file_system_type *fs_type,
-				        int flags, const char *dev_name,
-					void *data)
+static int debug_get_sb(struct file_system_type *fs_type,
+			int flags, const char *dev_name,
+			void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, debug_fill_super);
+	return get_sb_single(fs_type, flags, data, debug_fill_super, mnt);
 }
 
 static struct file_system_type debug_fs_type = {
@@ -199,7 +199,7 @@
 
 	pr_debug("debugfs: creating file '%s'\n",name);
 
-	error = simple_pin_fs("debugfs", &debugfs_mount, &debugfs_mount_count);
+	error = simple_pin_fs(&debug_fs_type, &debugfs_mount, &debugfs_mount_count);
 	if (error)
 		goto exit;
 
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index 52f5059..51a97f1 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -2549,11 +2549,11 @@
 	return -EINVAL;
 }				/*  End Function devfs_fill_super  */
 
-static struct super_block *devfs_get_sb(struct file_system_type *fs_type,
-					int flags, const char *dev_name,
-					void *data)
+static int devfs_get_sb(struct file_system_type *fs_type,
+			int flags, const char *dev_name,
+			void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, devfs_fill_super);
+	return get_sb_single(fs_type, flags, data, devfs_fill_super, mnt);
 }
 
 static struct file_system_type devfs_fs_type = {
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 14c5620..f7aef5b 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -130,10 +130,10 @@
 	return -ENOMEM;
 }
 
-static struct super_block *devpts_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int devpts_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, devpts_fill_super);
+	return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
 }
 
 static struct file_system_type devpts_fs_type = {
diff --git a/fs/direct-io.c b/fs/direct-io.c
index b05d1b2..538fb04 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -162,7 +162,7 @@
 		NULL);				/* vmas */
 	up_read(&current->mm->mmap_sem);
 
-	if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) {
+	if (ret < 0 && dio->blocks_available && (dio->rw & WRITE)) {
 		struct page *page = ZERO_PAGE(dio->curr_user_address);
 		/*
 		 * A memory fault, but the filesystem has some outstanding
@@ -535,7 +535,7 @@
 		map_bh->b_state = 0;
 		map_bh->b_size = fs_count << dio->inode->i_blkbits;
 
-		create = dio->rw == WRITE;
+		create = dio->rw & WRITE;
 		if (dio->lock_type == DIO_LOCKING) {
 			if (dio->block_in_file < (i_size_read(dio->inode) >>
 							dio->blkbits))
@@ -867,7 +867,7 @@
 				loff_t i_size_aligned;
 
 				/* AKPM: eargh, -ENOTBLK is a hack */
-				if (dio->rw == WRITE) {
+				if (dio->rw & WRITE) {
 					page_cache_release(page);
 					return -ENOTBLK;
 				}
@@ -1045,7 +1045,7 @@
 		}
 	} /* end iovec loop */
 
-	if (ret == -ENOTBLK && rw == WRITE) {
+	if (ret == -ENOTBLK && (rw & WRITE)) {
 		/*
 		 * The remaining part of the request will be
 		 * be handled by buffered I/O when we return
@@ -1089,7 +1089,7 @@
 	if (dio->is_async) {
 		int should_wait = 0;
 
-		if (dio->result < dio->size && rw == WRITE) {
+		if (dio->result < dio->size && (rw & WRITE)) {
 			dio->waiter = current;
 			should_wait = 1;
 		}
@@ -1142,7 +1142,7 @@
 			ret = transferred;
 
 		/* We could have also come here on an AIO file extend */
-		if (!is_sync_kiocb(iocb) && rw == WRITE &&
+		if (!is_sync_kiocb(iocb) && (rw & WRITE) &&
 		    ret >= 0 && dio->result == dio->size)
 			/*
 			 * For AIO writes where we have completed the
@@ -1194,7 +1194,7 @@
 	int acquire_i_mutex = 0;
 
 	if (rw & WRITE)
-		current->flags |= PF_SYNCWRITE;
+		rw = WRITE_SYNC;
 
 	if (bdev)
 		bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev));
@@ -1270,7 +1270,7 @@
 	 * even for AIO, we need to wait for i/o to complete before
 	 * returning in this case.
 	 */
-	dio->is_async = !is_sync_kiocb(iocb) && !((rw == WRITE) &&
+	dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) &&
 		(end > i_size_read(inode)));
 
 	retval = direct_io_worker(rw, iocb, inode, iov, offset,
@@ -1284,8 +1284,6 @@
 		mutex_unlock(&inode->i_mutex);
 	else if (acquire_i_mutex)
 		mutex_lock(&inode->i_mutex);
-	if (rw & WRITE)
-		current->flags &= ~PF_SYNCWRITE;
 	return retval;
 }
 EXPORT_SYMBOL(__blockdev_direct_IO);
diff --git a/fs/dquot.c b/fs/dquot.c
index 81d87a4..0122a27 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -250,7 +250,7 @@
 /* Add a dquot to the tail of the free list */
 static inline void put_dquot_last(struct dquot *dquot)
 {
-	list_add(&dquot->dq_free, free_dquots.prev);
+	list_add_tail(&dquot->dq_free, &free_dquots);
 	dqstats.free_dquots++;
 }
 
@@ -266,7 +266,7 @@
 {
 	/* We add to the back of inuse list so we don't have to restart
 	 * when traversing this list and we block */
-	list_add(&dquot->dq_inuse, inuse_list.prev);
+	list_add_tail(&dquot->dq_inuse, &inuse_list);
 	dqstats.allocated_dquots++;
 }
 
diff --git a/fs/efs/inode.c b/fs/efs/inode.c
index 180607f..174696f 100644
--- a/fs/efs/inode.c
+++ b/fs/efs/inode.c
@@ -21,7 +21,7 @@
 {
 	return generic_block_bmap(mapping,block,efs_get_block);
 }
-static struct address_space_operations efs_aops = {
+static const struct address_space_operations efs_aops = {
 	.readpage = efs_readpage,
 	.sync_page = block_sync_page,
 	.bmap = _efs_bmap
diff --git a/fs/efs/super.c b/fs/efs/super.c
index dff623e..8ac2462 100644
--- a/fs/efs/super.c
+++ b/fs/efs/super.c
@@ -15,13 +15,13 @@
 #include <linux/buffer_head.h>
 #include <linux/vfs.h>
 
-static int efs_statfs(struct super_block *s, struct kstatfs *buf);
+static int efs_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int efs_fill_super(struct super_block *s, void *d, int silent);
 
-static struct super_block *efs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int efs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super, mnt);
 }
 
 static struct file_system_type efs_fs_type = {
@@ -322,8 +322,8 @@
 	return -EINVAL;
 }
 
-static int efs_statfs(struct super_block *s, struct kstatfs *buf) {
-	struct efs_sb_info *sb = SUPER_INFO(s);
+static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) {
+	struct efs_sb_info *sb = SUPER_INFO(dentry->d_sb);
 
 	buf->f_type    = EFS_SUPER_MAGIC;	/* efs magic number */
 	buf->f_bsize   = EFS_BLOCKSIZE;		/* blocksize */
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
index 3d9a350..e249cf7 100644
--- a/fs/efs/symlink.c
+++ b/fs/efs/symlink.c
@@ -53,6 +53,6 @@
 	return err;
 }
 
-struct address_space_operations efs_symlink_aops = {
+const struct address_space_operations efs_symlink_aops = {
 	.readpage	= efs_symlink_readpage
 };
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 1b4491c..9c677bb 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1,6 +1,6 @@
 /*
  *  fs/eventpoll.c ( Efficent event polling implementation )
- *  Copyright (C) 2001,...,2003	 Davide Libenzi
+ *  Copyright (C) 2001,...,2006	 Davide Libenzi
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -268,9 +268,9 @@
 		   int maxevents, long timeout);
 static int eventpollfs_delete_dentry(struct dentry *dentry);
 static struct inode *ep_eventpoll_inode(void);
-static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
-					      int flags, const char *dev_name,
-					      void *data);
+static int eventpollfs_get_sb(struct file_system_type *fs_type,
+			      int flags, const char *dev_name,
+			      void *data, struct vfsmount *mnt);
 
 /*
  * This semaphore is used to serialize ep_free() and eventpoll_release_file().
@@ -337,20 +337,20 @@
 /* Special initialization for the rb-tree node to detect linkage */
 static inline void ep_rb_initnode(struct rb_node *n)
 {
-	n->rb_parent = n;
+	rb_set_parent(n, n);
 }
 
 /* Removes a node from the rb-tree and marks it for a fast is-linked check */
 static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
 {
 	rb_erase(n, r);
-	n->rb_parent = n;
+	rb_set_parent(n, n);
 }
 
 /* Fast check to verify that the item is linked to the main rb-tree */
 static inline int ep_rb_linked(struct rb_node *n)
 {
-	return n->rb_parent != n;
+	return rb_parent(n) != n;
 }
 
 /*
@@ -1004,7 +1004,7 @@
 
 		/* Notify waiting tasks that events are available */
 		if (waitqueue_active(&ep->wq))
-			wake_up(&ep->wq);
+			__wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE);
 		if (waitqueue_active(&ep->poll_wait))
 			pwake++;
 	}
@@ -1083,7 +1083,8 @@
 
 				/* Notify waiting tasks that events are available */
 				if (waitqueue_active(&ep->wq))
-					wake_up(&ep->wq);
+					__wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+							 TASK_INTERRUPTIBLE);
 				if (waitqueue_active(&ep->poll_wait))
 					pwake++;
 			}
@@ -1260,7 +1261,8 @@
 	 * wait list.
 	 */
 	if (waitqueue_active(&ep->wq))
-		wake_up(&ep->wq);
+		__wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+				 TASK_INTERRUPTIBLE);
 	if (waitqueue_active(&ep->poll_wait))
 		pwake++;
 
@@ -1444,7 +1446,8 @@
 		 * wait list.
 		 */
 		if (waitqueue_active(&ep->wq))
-			wake_up(&ep->wq);
+			__wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+					 TASK_INTERRUPTIBLE);
 		if (waitqueue_active(&ep->poll_wait))
 			pwake++;
 	}
@@ -1516,7 +1519,7 @@
 		 * ep_poll_callback() when events will become available.
 		 */
 		init_waitqueue_entry(&wait, current);
-		add_wait_queue(&ep->wq, &wait);
+		__add_wait_queue(&ep->wq, &wait);
 
 		for (;;) {
 			/*
@@ -1536,7 +1539,7 @@
 			jtimeout = schedule_timeout(jtimeout);
 			write_lock_irqsave(&ep->lock, flags);
 		}
-		remove_wait_queue(&ep->wq, &wait);
+		__remove_wait_queue(&ep->wq, &wait);
 
 		set_current_state(TASK_RUNNING);
 	}
@@ -1595,11 +1598,12 @@
 }
 
 
-static struct super_block *
+static int
 eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
-		   const char *dev_name, void *data)
+		   const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC);
+	return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC,
+			     mnt);
 }
 
 
diff --git a/fs/exec.c b/fs/exec.c
index 3a79d97..c8494f5 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -49,6 +49,7 @@
 #include <linux/rmap.h>
 #include <linux/acct.h>
 #include <linux/cn_proc.h>
+#include <linux/audit.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -665,8 +666,6 @@
 	 * and to assume its PID:
 	 */
 	if (!thread_group_leader(current)) {
-		struct dentry *proc_dentry1, *proc_dentry2;
-
 		/*
 		 * Wait for the thread group leader to be a zombie.
 		 * It should already be zombie at this point, most
@@ -688,10 +687,6 @@
 		 */
 		current->start_time = leader->start_time;
 
-		spin_lock(&leader->proc_lock);
-		spin_lock(&current->proc_lock);
-		proc_dentry1 = proc_pid_unhash(current);
-		proc_dentry2 = proc_pid_unhash(leader);
 		write_lock_irq(&tasklist_lock);
 
 		BUG_ON(leader->tgid != current->tgid);
@@ -712,7 +707,7 @@
 		attach_pid(current, PIDTYPE_PID,  current->pid);
 		attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
 		attach_pid(current, PIDTYPE_SID,  current->signal->session);
-		list_add_tail_rcu(&current->tasks, &init_task.tasks);
+		list_replace_rcu(&leader->tasks, &current->tasks);
 
 		current->group_leader = current;
 		leader->group_leader = current;
@@ -720,7 +715,6 @@
 		/* Reduce leader to a thread */
 		detach_pid(leader, PIDTYPE_PGID);
 		detach_pid(leader, PIDTYPE_SID);
-		list_del_init(&leader->tasks);
 
 		current->exit_signal = SIGCHLD;
 
@@ -728,10 +722,6 @@
 		leader->exit_state = EXIT_DEAD;
 
 		write_unlock_irq(&tasklist_lock);
-		spin_unlock(&leader->proc_lock);
-		spin_unlock(&current->proc_lock);
-		proc_pid_flush(proc_dentry1);
-		proc_pid_flush(proc_dentry2);
         }
 
 	/*
@@ -865,7 +855,6 @@
 	bprm->mm = NULL;		/* We're using it now */
 
 	/* This is the point of no return */
-	steal_locks(files);
 	put_files_struct(files);
 
 	current->sas_ss_sp = current->sas_ss_size = 0;
@@ -1085,6 +1074,11 @@
 	/* kernel module loader fixup */
 	/* so we don't try to load run modprobe in kernel space. */
 	set_fs(USER_DS);
+
+	retval = audit_bprm(bprm);
+	if (retval)
+		return retval;
+
 	retval = -ENOENT;
 	for (try=0; try<2; try++) {
 		read_lock(&binfmt_lock);
@@ -1374,67 +1368,102 @@
 	*out_ptr = 0;
 }
 
-static void zap_threads (struct mm_struct *mm)
+static void zap_process(struct task_struct *start)
+{
+	struct task_struct *t;
+
+	start->signal->flags = SIGNAL_GROUP_EXIT;
+	start->signal->group_stop_count = 0;
+
+	t = start;
+	do {
+		if (t != current && t->mm) {
+			t->mm->core_waiters++;
+			sigaddset(&t->pending.signal, SIGKILL);
+			signal_wake_up(t, 1);
+		}
+	} while ((t = next_thread(t)) != start);
+}
+
+static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
+				int exit_code)
 {
 	struct task_struct *g, *p;
+	unsigned long flags;
+	int err = -EAGAIN;
+
+	spin_lock_irq(&tsk->sighand->siglock);
+	if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) {
+		tsk->signal->group_exit_code = exit_code;
+		zap_process(tsk);
+		err = 0;
+	}
+	spin_unlock_irq(&tsk->sighand->siglock);
+	if (err)
+		return err;
+
+	if (atomic_read(&mm->mm_users) == mm->core_waiters + 1)
+		goto done;
+
+	rcu_read_lock();
+	for_each_process(g) {
+		if (g == tsk->group_leader)
+			continue;
+
+		p = g;
+		do {
+			if (p->mm) {
+				if (p->mm == mm) {
+					/*
+					 * p->sighand can't disappear, but
+					 * may be changed by de_thread()
+					 */
+					lock_task_sighand(p, &flags);
+					zap_process(p);
+					unlock_task_sighand(p, &flags);
+				}
+				break;
+			}
+		} while ((p = next_thread(p)) != g);
+	}
+	rcu_read_unlock();
+done:
+	return mm->core_waiters;
+}
+
+static int coredump_wait(int exit_code)
+{
 	struct task_struct *tsk = current;
-	struct completion *vfork_done = tsk->vfork_done;
-	int traced = 0;
+	struct mm_struct *mm = tsk->mm;
+	struct completion startup_done;
+	struct completion *vfork_done;
+	int core_waiters;
+
+	init_completion(&mm->core_done);
+	init_completion(&startup_done);
+	mm->core_startup_done = &startup_done;
+
+	core_waiters = zap_threads(tsk, mm, exit_code);
+	up_write(&mm->mmap_sem);
+
+	if (unlikely(core_waiters < 0))
+		goto fail;
 
 	/*
 	 * Make sure nobody is waiting for us to release the VM,
 	 * otherwise we can deadlock when we wait on each other
 	 */
+	vfork_done = tsk->vfork_done;
 	if (vfork_done) {
 		tsk->vfork_done = NULL;
 		complete(vfork_done);
 	}
 
-	read_lock(&tasklist_lock);
-	do_each_thread(g,p)
-		if (mm == p->mm && p != tsk) {
-			force_sig_specific(SIGKILL, p);
-			mm->core_waiters++;
-			if (unlikely(p->ptrace) &&
-			    unlikely(p->parent->mm == mm))
-				traced = 1;
-		}
-	while_each_thread(g,p);
-
-	read_unlock(&tasklist_lock);
-
-	if (unlikely(traced)) {
-		/*
-		 * We are zapping a thread and the thread it ptraces.
-		 * If the tracee went into a ptrace stop for exit tracing,
-		 * we could deadlock since the tracer is waiting for this
-		 * coredump to finish.  Detach them so they can both die.
-		 */
-		write_lock_irq(&tasklist_lock);
-		do_each_thread(g,p) {
-			if (mm == p->mm && p != tsk &&
-			    p->ptrace && p->parent->mm == mm) {
-				__ptrace_detach(p, 0);
-			}
-		} while_each_thread(g,p);
-		write_unlock_irq(&tasklist_lock);
-	}
-}
-
-static void coredump_wait(struct mm_struct *mm)
-{
-	DECLARE_COMPLETION(startup_done);
-	int core_waiters;
-
-	mm->core_startup_done = &startup_done;
-
-	zap_threads(mm);
-	core_waiters = mm->core_waiters;
-	up_write(&mm->mmap_sem);
-
 	if (core_waiters)
 		wait_for_completion(&startup_done);
+fail:
 	BUG_ON(mm->core_waiters);
+	return core_waiters;
 }
 
 int do_coredump(long signr, int exit_code, struct pt_regs * regs)
@@ -1468,22 +1497,9 @@
 	}
 	mm->dumpable = 0;
 
-	retval = -EAGAIN;
-	spin_lock_irq(&current->sighand->siglock);
-	if (!(current->signal->flags & SIGNAL_GROUP_EXIT)) {
-		current->signal->flags = SIGNAL_GROUP_EXIT;
-		current->signal->group_exit_code = exit_code;
-		current->signal->group_stop_count = 0;
-		retval = 0;
-	}
-	spin_unlock_irq(&current->sighand->siglock);
-	if (retval) {
-		up_write(&mm->mmap_sem);
+	retval = coredump_wait(exit_code);
+	if (retval < 0)
 		goto fail;
-	}
-
-	init_completion(&mm->core_done);
-	coredump_wait(mm);
 
 	/*
 	 * Clear any false indication of pending signals that might
diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile
index c5d02da..e0b2b43 100644
--- a/fs/ext2/Makefile
+++ b/fs/ext2/Makefile
@@ -4,7 +4,7 @@
 
 obj-$(CONFIG_EXT2_FS) += ext2.o
 
-ext2-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
+ext2-y := balloc.o dir.o file.o fsync.o ialloc.o inode.o \
 	  ioctl.o namei.o super.o symlink.o
 
 ext2-$(CONFIG_EXT2_FS_XATTR)	 += xattr.o xattr_user.o xattr_trusted.o
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index 2c00953..433a213 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -521,6 +521,26 @@
 	goto out_release;
 }
 
+#ifdef EXT2FS_DEBUG
+
+static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
+
+unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
+{
+	unsigned int i;
+	unsigned long sum = 0;
+
+	if (!map)
+		return (0);
+	for (i = 0; i < numchars; i++)
+		sum += nibblemap[map->b_data[i] & 0xf] +
+			nibblemap[(map->b_data[i] >> 4) & 0xf];
+	return (sum);
+}
+
+#endif  /*  EXT2FS_DEBUG  */
+
+/* Superblock must be locked */
 unsigned long ext2_count_free_blocks (struct super_block * sb)
 {
 	struct ext2_group_desc * desc;
@@ -530,7 +550,6 @@
 	unsigned long bitmap_count, x;
 	struct ext2_super_block *es;
 
-	lock_super (sb);
 	es = EXT2_SB(sb)->s_es;
 	desc_count = 0;
 	bitmap_count = 0;
@@ -554,7 +573,6 @@
 	printk("ext2_count_free_blocks: stored = %lu, computed = %lu, %lu\n",
 		(long)le32_to_cpu(es->s_free_blocks_count),
 		desc_count, bitmap_count);
-	unlock_super (sb);
 	return bitmap_count;
 #else
         for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {
diff --git a/fs/ext2/bitmap.c b/fs/ext2/bitmap.c
deleted file mode 100644
index e9983a0..0000000
--- a/fs/ext2/bitmap.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  linux/fs/ext2/bitmap.c
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- */
-
-#ifdef EXT2FS_DEBUG
-
-#include <linux/buffer_head.h>
-
-#include "ext2.h"
-
-static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
-
-unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars)
-{
-	unsigned int i;
-	unsigned long sum = 0;
-	
-	if (!map) 
-		return (0);
-	for (i = 0; i < numchars; i++)
-		sum += nibblemap[map->b_data[i] & 0xf] +
-			nibblemap[(map->b_data[i] >> 4) & 0xf];
-	return (sum);
-}
-
-#endif  /*  EXT2FS_DEBUG  */
-
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index d672aa9..92ea826 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -159,8 +159,7 @@
 static struct page * ext2_get_page(struct inode *dir, unsigned long n)
 {
 	struct address_space *mapping = dir->i_mapping;
-	struct page *page = read_cache_page(mapping, n,
-				(filler_t*)mapping->a_ops->readpage, NULL);
+	struct page *page = read_mapping_page(mapping, n, NULL);
 	if (!IS_ERR(page)) {
 		wait_on_page_locked(page);
 		kmap(page);
@@ -400,8 +399,7 @@
 	de = ext2_find_entry (dir, dentry, &page);
 	if (de) {
 		res = le32_to_cpu(de->inode);
-		kunmap(page);
-		page_cache_release(page);
+		ext2_put_page(page);
 	}
 	return res;
 }
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 9f74a62..e65a019 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -162,9 +162,9 @@
 extern const struct file_operations ext2_xip_file_operations;
 
 /* inode.c */
-extern struct address_space_operations ext2_aops;
-extern struct address_space_operations ext2_aops_xip;
-extern struct address_space_operations ext2_nobh_aops;
+extern const struct address_space_operations ext2_aops;
+extern const struct address_space_operations ext2_aops_xip;
+extern const struct address_space_operations ext2_nobh_aops;
 
 /* namei.c */
 extern struct inode_operations ext2_dir_inode_operations;
diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c
index c9c2e5f..7806b9e 100644
--- a/fs/ext2/fsync.c
+++ b/fs/ext2/fsync.c
@@ -24,7 +24,7 @@
 
 #include "ext2.h"
 #include <linux/smp_lock.h>
-#include <linux/buffer_head.h>		/* for fsync_inode_buffers() */
+#include <linux/buffer_head.h>		/* for sync_mapping_buffers() */
 
 
 /*
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index e527652..308c252 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -638,6 +638,7 @@
 	return ERR_PTR(err);
 }
 
+/* Superblock must be locked */
 unsigned long ext2_count_free_inodes (struct super_block * sb)
 {
 	struct ext2_group_desc *desc;
@@ -649,7 +650,6 @@
 	unsigned long bitmap_count = 0;
 	struct buffer_head *bitmap_bh = NULL;
 
-	lock_super (sb);
 	es = EXT2_SB(sb)->s_es;
 	for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {
 		unsigned x;
@@ -672,7 +672,6 @@
 	printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
 		percpu_counter_read(&EXT2_SB(sb)->s_freeinodes_counter),
 		desc_count, bitmap_count);
-	unlock_super(sb);
 	return desc_count;
 #else
 	for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 04af9c4..fb4d322 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -684,7 +684,7 @@
 	return mpage_writepages(mapping, wbc, ext2_get_block);
 }
 
-struct address_space_operations ext2_aops = {
+const struct address_space_operations ext2_aops = {
 	.readpage		= ext2_readpage,
 	.readpages		= ext2_readpages,
 	.writepage		= ext2_writepage,
@@ -697,12 +697,12 @@
 	.migratepage		= buffer_migrate_page,
 };
 
-struct address_space_operations ext2_aops_xip = {
+const struct address_space_operations ext2_aops_xip = {
 	.bmap			= ext2_bmap,
 	.get_xip_page		= ext2_get_xip_page,
 };
 
-struct address_space_operations ext2_nobh_aops = {
+const struct address_space_operations ext2_nobh_aops = {
 	.readpage		= ext2_readpage,
 	.readpages		= ext2_readpages,
 	.writepage		= ext2_nobh_writepage,
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 7e30bae..d4233b2 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -39,7 +39,7 @@
 static void ext2_sync_super(struct super_block *sb,
 			    struct ext2_super_block *es);
 static int ext2_remount (struct super_block * sb, int * flags, char * data);
-static int ext2_statfs (struct super_block * sb, struct kstatfs * buf);
+static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf);
 
 void ext2_error (struct super_block * sb, const char * function,
 		 const char * fmt, ...)
@@ -834,9 +834,6 @@
 		printk ("EXT2-fs: not enough memory\n");
 		goto failed_mount;
 	}
-	percpu_counter_init(&sbi->s_freeblocks_counter);
-	percpu_counter_init(&sbi->s_freeinodes_counter);
-	percpu_counter_init(&sbi->s_dirs_counter);
 	bgl_lock_init(&sbi->s_blockgroup_lock);
 	sbi->s_debts = kmalloc(sbi->s_groups_count * sizeof(*sbi->s_debts),
 			       GFP_KERNEL);
@@ -857,12 +854,18 @@
 	}
 	if (!ext2_check_descriptors (sb)) {
 		printk ("EXT2-fs: group descriptors corrupted!\n");
-		db_count = i;
 		goto failed_mount2;
 	}
 	sbi->s_gdb_count = db_count;
 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
 	spin_lock_init(&sbi->s_next_gen_lock);
+
+	percpu_counter_init(&sbi->s_freeblocks_counter,
+				ext2_count_free_blocks(sb));
+	percpu_counter_init(&sbi->s_freeinodes_counter,
+				ext2_count_free_inodes(sb));
+	percpu_counter_init(&sbi->s_dirs_counter,
+				ext2_count_dirs(sb));
 	/*
 	 * set up enough so that it can read an inode
 	 */
@@ -874,24 +877,18 @@
 	if (!sb->s_root) {
 		iput(root);
 		printk(KERN_ERR "EXT2-fs: get root inode failed\n");
-		goto failed_mount2;
+		goto failed_mount3;
 	}
 	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
 		dput(sb->s_root);
 		sb->s_root = NULL;
 		printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n");
-		goto failed_mount2;
+		goto failed_mount3;
 	}
 	if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
 		ext2_warning(sb, __FUNCTION__,
 			"mounting ext3 filesystem as ext2");
 	ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
-	percpu_counter_mod(&sbi->s_freeblocks_counter,
-				ext2_count_free_blocks(sb));
-	percpu_counter_mod(&sbi->s_freeinodes_counter,
-				ext2_count_free_inodes(sb));
-	percpu_counter_mod(&sbi->s_dirs_counter,
-				ext2_count_dirs(sb));
 	return 0;
 
 cantfind_ext2:
@@ -899,7 +896,10 @@
 		printk("VFS: Can't find an ext2 filesystem on dev %s.\n",
 		       sb->s_id);
 	goto failed_mount;
-
+failed_mount3:
+	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+	percpu_counter_destroy(&sbi->s_dirs_counter);
 failed_mount2:
 	for (i = 0; i < db_count; i++)
 		brelse(sbi->s_group_desc[i]);
@@ -1038,12 +1038,14 @@
 	return err;
 }
 
-static int ext2_statfs (struct super_block * sb, struct kstatfs * buf)
+static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
 {
+	struct super_block *sb = dentry->d_sb;
 	struct ext2_sb_info *sbi = EXT2_SB(sb);
 	unsigned long overhead;
 	int i;
 
+	lock_super(sb);
 	if (test_opt (sb, MINIX_DF))
 		overhead = 0;
 	else {
@@ -1084,13 +1086,14 @@
 	buf->f_files = le32_to_cpu(sbi->s_es->s_inodes_count);
 	buf->f_ffree = ext2_count_free_inodes (sb);
 	buf->f_namelen = EXT2_NAME_LEN;
+	unlock_super(sb);
 	return 0;
 }
 
-static struct super_block *ext2_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int ext2_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt);
 }
 
 #ifdef CONFIG_QUOTA
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 77927d6..96172e8 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -163,20 +163,19 @@
 #endif
 
 static int
-goal_in_my_reservation(struct ext3_reserve_window *rsv, int goal,
+goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal,
 			unsigned int group, struct super_block * sb)
 {
-	unsigned long group_first_block, group_last_block;
+	ext3_fsblk_t group_first_block, group_last_block;
 
-	group_first_block = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-				group * EXT3_BLOCKS_PER_GROUP(sb);
+	group_first_block = ext3_group_first_block_no(sb, group);
 	group_last_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1;
 
 	if ((rsv->_rsv_start > group_last_block) ||
 	    (rsv->_rsv_end < group_first_block))
 		return 0;
-	if ((goal >= 0) && ((goal + group_first_block < rsv->_rsv_start)
-		|| (goal + group_first_block > rsv->_rsv_end)))
+	if ((grp_goal >= 0) && ((grp_goal + group_first_block < rsv->_rsv_start)
+		|| (grp_goal + group_first_block > rsv->_rsv_end)))
 		return 0;
 	return 1;
 }
@@ -187,7 +186,7 @@
  * Returns NULL if there are no windows or if all windows start after the goal.
  */
 static struct ext3_reserve_window_node *
-search_reserve_window(struct rb_root *root, unsigned long goal)
+search_reserve_window(struct rb_root *root, ext3_fsblk_t goal)
 {
 	struct rb_node *n = root->rb_node;
 	struct ext3_reserve_window_node *rsv;
@@ -223,7 +222,7 @@
 {
 	struct rb_root *root = &EXT3_SB(sb)->s_rsv_window_root;
 	struct rb_node *node = &rsv->rsv_node;
-	unsigned int start = rsv->rsv_start;
+	ext3_fsblk_t start = rsv->rsv_start;
 
 	struct rb_node ** p = &root->rb_node;
 	struct rb_node * parent = NULL;
@@ -310,20 +309,20 @@
 
 /* Free given blocks, update quota and i_blocks field */
 void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
-			 unsigned long block, unsigned long count,
-			 int *pdquot_freed_blocks)
+			 ext3_fsblk_t block, unsigned long count,
+			 unsigned long *pdquot_freed_blocks)
 {
 	struct buffer_head *bitmap_bh = NULL;
 	struct buffer_head *gd_bh;
 	unsigned long block_group;
-	unsigned long bit;
+	ext3_grpblk_t bit;
 	unsigned long i;
 	unsigned long overflow;
 	struct ext3_group_desc * desc;
 	struct ext3_super_block * es;
 	struct ext3_sb_info *sbi;
 	int err = 0, ret;
-	unsigned group_freed;
+	ext3_grpblk_t group_freed;
 
 	*pdquot_freed_blocks = 0;
 	sbi = EXT3_SB(sb);
@@ -333,7 +332,7 @@
 	    block + count > le32_to_cpu(es->s_blocks_count)) {
 		ext3_error (sb, "ext3_free_blocks",
 			    "Freeing blocks not in datazone - "
-			    "block = %lu, count = %lu", block, count);
+			    "block = "E3FSBLK", count = %lu", block, count);
 		goto error_return;
 	}
 
@@ -369,7 +368,7 @@
 		      sbi->s_itb_per_group))
 		ext3_error (sb, "ext3_free_blocks",
 			    "Freeing blocks in system zones - "
-			    "Block = %lu, count = %lu",
+			    "Block = "E3FSBLK", count = %lu",
 			    block, count);
 
 	/*
@@ -453,7 +452,8 @@
 						bit + i, bitmap_bh->b_data)) {
 			jbd_unlock_bh_state(bitmap_bh);
 			ext3_error(sb, __FUNCTION__,
-				"bit already cleared for block %lu", block + i);
+				"bit already cleared for block "E3FSBLK,
+				 block + i);
 			jbd_lock_bh_state(bitmap_bh);
 			BUFFER_TRACE(bitmap_bh, "bit already cleared");
 		} else {
@@ -493,10 +493,10 @@
 
 /* Free given blocks, update quota and i_blocks field */
 void ext3_free_blocks(handle_t *handle, struct inode *inode,
-			unsigned long block, unsigned long count)
+			ext3_fsblk_t block, unsigned long count)
 {
 	struct super_block * sb;
-	int dquot_freed_blocks;
+	unsigned long dquot_freed_blocks;
 
 	sb = inode->i_sb;
 	if (!sb) {
@@ -525,7 +525,7 @@
  * data-writes at some point, and disable it for metadata allocations or
  * sync-data inodes.
  */
-static int ext3_test_allocatable(int nr, struct buffer_head *bh)
+static int ext3_test_allocatable(ext3_grpblk_t nr, struct buffer_head *bh)
 {
 	int ret;
 	struct journal_head *jh = bh2jh(bh);
@@ -542,11 +542,11 @@
 	return ret;
 }
 
-static int
-bitmap_search_next_usable_block(int start, struct buffer_head *bh,
-					int maxblocks)
+static ext3_grpblk_t
+bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
+					ext3_grpblk_t maxblocks)
 {
-	int next;
+	ext3_grpblk_t next;
 	struct journal_head *jh = bh2jh(bh);
 
 	/*
@@ -576,10 +576,11 @@
  * the initial goal; then for a free byte somewhere in the bitmap; then
  * for any free bit in the bitmap.
  */
-static int
-find_next_usable_block(int start, struct buffer_head *bh, int maxblocks)
+static ext3_grpblk_t
+find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
+			ext3_grpblk_t maxblocks)
 {
-	int here, next;
+	ext3_grpblk_t here, next;
 	char *p, *r;
 
 	if (start > 0) {
@@ -591,7 +592,7 @@
 		 * less than EXT3_BLOCKS_PER_GROUP. Aligning up to the
 		 * next 64-bit boundary is simple..
 		 */
-		int end_goal = (start + 63) & ~63;
+		ext3_grpblk_t end_goal = (start + 63) & ~63;
 		if (end_goal > maxblocks)
 			end_goal = maxblocks;
 		here = ext3_find_next_zero_bit(bh->b_data, end_goal, start);
@@ -628,7 +629,7 @@
  * zero (failure).
  */
 static inline int
-claim_block(spinlock_t *lock, int block, struct buffer_head *bh)
+claim_block(spinlock_t *lock, ext3_grpblk_t block, struct buffer_head *bh)
 {
 	struct journal_head *jh = bh2jh(bh);
 	int ret;
@@ -651,19 +652,18 @@
  * new bitmap.  In that case we must release write access to the old one via
  * ext3_journal_release_buffer(), else we'll run out of credits.
  */
-static int
+static ext3_grpblk_t
 ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
-			struct buffer_head *bitmap_bh, int goal,
+			struct buffer_head *bitmap_bh, ext3_grpblk_t grp_goal,
 			unsigned long *count, struct ext3_reserve_window *my_rsv)
 {
-	int group_first_block, start, end;
+	ext3_fsblk_t group_first_block;
+	ext3_grpblk_t start, end;
 	unsigned long num = 0;
 
 	/* we do allocation within the reservation window if we have a window */
 	if (my_rsv) {
-		group_first_block =
-			le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-			group * EXT3_BLOCKS_PER_GROUP(sb);
+		group_first_block = ext3_group_first_block_no(sb, group);
 		if (my_rsv->_rsv_start >= group_first_block)
 			start = my_rsv->_rsv_start - group_first_block;
 		else
@@ -673,13 +673,13 @@
 		if (end > EXT3_BLOCKS_PER_GROUP(sb))
 			/* reservation window crosses group boundary */
 			end = EXT3_BLOCKS_PER_GROUP(sb);
-		if ((start <= goal) && (goal < end))
-			start = goal;
+		if ((start <= grp_goal) && (grp_goal < end))
+			start = grp_goal;
 		else
-			goal = -1;
+			grp_goal = -1;
 	} else {
-		if (goal > 0)
-			start = goal;
+		if (grp_goal > 0)
+			start = grp_goal;
 		else
 			start = 0;
 		end = EXT3_BLOCKS_PER_GROUP(sb);
@@ -688,43 +688,43 @@
 	BUG_ON(start > EXT3_BLOCKS_PER_GROUP(sb));
 
 repeat:
-	if (goal < 0 || !ext3_test_allocatable(goal, bitmap_bh)) {
-		goal = find_next_usable_block(start, bitmap_bh, end);
-		if (goal < 0)
+	if (grp_goal < 0 || !ext3_test_allocatable(grp_goal, bitmap_bh)) {
+		grp_goal = find_next_usable_block(start, bitmap_bh, end);
+		if (grp_goal < 0)
 			goto fail_access;
 		if (!my_rsv) {
 			int i;
 
-			for (i = 0; i < 7 && goal > start &&
-					ext3_test_allocatable(goal - 1,
+			for (i = 0; i < 7 && grp_goal > start &&
+					ext3_test_allocatable(grp_goal - 1,
 								bitmap_bh);
-					i++, goal--)
+					i++, grp_goal--)
 				;
 		}
 	}
-	start = goal;
+	start = grp_goal;
 
-	if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, bitmap_bh)) {
+	if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) {
 		/*
 		 * The block was allocated by another thread, or it was
 		 * allocated and then freed by another thread
 		 */
 		start++;
-		goal++;
+		grp_goal++;
 		if (start >= end)
 			goto fail_access;
 		goto repeat;
 	}
 	num++;
-	goal++;
-	while (num < *count && goal < end
-		&& ext3_test_allocatable(goal, bitmap_bh)
-		&& claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, bitmap_bh)) {
+	grp_goal++;
+	while (num < *count && grp_goal < end
+		&& ext3_test_allocatable(grp_goal, bitmap_bh)
+		&& claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) {
 		num++;
-		goal++;
+		grp_goal++;
 	}
 	*count = num;
-	return goal - num;
+	return grp_goal - num;
 fail_access:
 	*count = num;
 	return -1;
@@ -766,12 +766,13 @@
 static int find_next_reservable_window(
 				struct ext3_reserve_window_node *search_head,
 				struct ext3_reserve_window_node *my_rsv,
-				struct super_block * sb, int start_block,
-				int last_block)
+				struct super_block * sb,
+				ext3_fsblk_t start_block,
+				ext3_fsblk_t last_block)
 {
 	struct rb_node *next;
 	struct ext3_reserve_window_node *rsv, *prev;
-	int cur;
+	ext3_fsblk_t cur;
 	int size = my_rsv->rsv_goal_size;
 
 	/* TODO: make the start of the reservation window byte-aligned */
@@ -873,10 +874,10 @@
  *
  *	@rsv: the reservation
  *
- *	@goal: The goal (group-relative).  It is where the search for a
+ *	@grp_goal: The goal (group-relative).  It is where the search for a
  *		free reservable space should start from.
- *		if we have a goal(goal >0 ), then start from there,
- *		no goal(goal = -1), we start from the first block
+ *		if we have a grp_goal(grp_goal >0 ), then start from there,
+ *		no grp_goal(grp_goal = -1), we start from the first block
  *		of the group.
  *
  *	@sb: the super block
@@ -885,25 +886,24 @@
  *
  */
 static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
-		int goal, struct super_block *sb,
+		ext3_grpblk_t grp_goal, struct super_block *sb,
 		unsigned int group, struct buffer_head *bitmap_bh)
 {
 	struct ext3_reserve_window_node *search_head;
-	int group_first_block, group_end_block, start_block;
-	int first_free_block;
+	ext3_fsblk_t group_first_block, group_end_block, start_block;
+	ext3_grpblk_t first_free_block;
 	struct rb_root *fs_rsv_root = &EXT3_SB(sb)->s_rsv_window_root;
 	unsigned long size;
 	int ret;
 	spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
 
-	group_first_block = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-				group * EXT3_BLOCKS_PER_GROUP(sb);
+	group_first_block = ext3_group_first_block_no(sb, group);
 	group_end_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1;
 
-	if (goal < 0)
+	if (grp_goal < 0)
 		start_block = group_first_block;
 	else
-		start_block = goal + group_first_block;
+		start_block = grp_goal + group_first_block;
 
 	size = my_rsv->rsv_goal_size;
 
@@ -1057,14 +1057,15 @@
  * sorted double linked list should be fast.
  *
  */
-static int
+static ext3_grpblk_t
 ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
 			unsigned int group, struct buffer_head *bitmap_bh,
-			int goal, struct ext3_reserve_window_node * my_rsv,
+			ext3_grpblk_t grp_goal,
+			struct ext3_reserve_window_node * my_rsv,
 			unsigned long *count, int *errp)
 {
-	unsigned long group_first_block;
-	int ret = 0;
+	ext3_fsblk_t group_first_block;
+	ext3_grpblk_t ret = 0;
 	int fatal;
 	unsigned long num = *count;
 
@@ -1090,17 +1091,16 @@
 	 */
 	if (my_rsv == NULL ) {
 		ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh,
-						goal, count, NULL);
+						grp_goal, count, NULL);
 		goto out;
 	}
 	/*
-	 * goal is a group relative block number (if there is a goal)
-	 * 0 < goal < EXT3_BLOCKS_PER_GROUP(sb)
+	 * grp_goal is a group relative block number (if there is a goal)
+	 * 0 < grp_goal < EXT3_BLOCKS_PER_GROUP(sb)
 	 * first block is a filesystem wide block number
 	 * first block is the block number of the first block in this group
 	 */
-	group_first_block = le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block) +
-			group * EXT3_BLOCKS_PER_GROUP(sb);
+	group_first_block = ext3_group_first_block_no(sb, group);
 
 	/*
 	 * Basically we will allocate a new block from inode's reservation
@@ -1119,24 +1119,24 @@
 	 */
 	while (1) {
 		if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
-			!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) {
+			!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) {
 			if (my_rsv->rsv_goal_size < *count)
 				my_rsv->rsv_goal_size = *count;
-			ret = alloc_new_reservation(my_rsv, goal, sb,
+			ret = alloc_new_reservation(my_rsv, grp_goal, sb,
 							group, bitmap_bh);
 			if (ret < 0)
 				break;			/* failed */
 
-			if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb))
-				goal = -1;
-		} else if (goal > 0 && (my_rsv->rsv_end-goal+1) < *count)
+			if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb))
+				grp_goal = -1;
+		} else if (grp_goal > 0 && (my_rsv->rsv_end-grp_goal+1) < *count)
 			try_to_extend_reservation(my_rsv, sb,
-					*count-my_rsv->rsv_end + goal - 1);
+					*count-my_rsv->rsv_end + grp_goal - 1);
 
 		if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb))
 		    || (my_rsv->rsv_end < group_first_block))
 			BUG();
-		ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal,
+		ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, grp_goal,
 					   &num, &my_rsv->rsv_window);
 		if (ret >= 0) {
 			my_rsv->rsv_alloc_hit += num;
@@ -1164,7 +1164,7 @@
 
 static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
 {
-	int free_blocks, root_blocks;
+	ext3_fsblk_t free_blocks, root_blocks;
 
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
 	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
@@ -1200,19 +1200,20 @@
  * bitmap, and then for any free bit if that fails.
  * This function also updates quota and i_blocks field.
  */
-int ext3_new_blocks(handle_t *handle, struct inode *inode,
-			unsigned long goal, unsigned long *count, int *errp)
+ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
+			ext3_fsblk_t goal, unsigned long *count, int *errp)
 {
 	struct buffer_head *bitmap_bh = NULL;
 	struct buffer_head *gdp_bh;
 	int group_no;
 	int goal_group;
-	int ret_block;
+	ext3_grpblk_t grp_target_blk;	/* blockgroup relative goal block */
+	ext3_grpblk_t grp_alloc_blk;	/* blockgroup-relative allocated block*/
+	ext3_fsblk_t ret_block;		/* filesyetem-wide allocated block */
 	int bgi;			/* blockgroup iteration index */
-	int target_block;
 	int fatal = 0, err;
 	int performed_allocation = 0;
-	int free_blocks;
+	ext3_grpblk_t free_blocks;	/* number of free blocks in a group */
 	struct super_block *sb;
 	struct ext3_group_desc *gdp;
 	struct ext3_super_block *es;
@@ -1285,16 +1286,17 @@
 		my_rsv = NULL;
 
 	if (free_blocks > 0) {
-		ret_block = ((goal - le32_to_cpu(es->s_first_data_block)) %
+		grp_target_blk = ((goal - le32_to_cpu(es->s_first_data_block)) %
 				EXT3_BLOCKS_PER_GROUP(sb));
 		bitmap_bh = read_block_bitmap(sb, group_no);
 		if (!bitmap_bh)
 			goto io_error;
-		ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
-					bitmap_bh, ret_block, my_rsv, &num, &fatal);
+		grp_alloc_blk = ext3_try_to_allocate_with_rsv(sb, handle,
+					group_no, bitmap_bh, grp_target_blk,
+					my_rsv,	&num, &fatal);
 		if (fatal)
 			goto out;
-		if (ret_block >= 0)
+		if (grp_alloc_blk >= 0)
 			goto allocated;
 	}
 
@@ -1327,11 +1329,15 @@
 		bitmap_bh = read_block_bitmap(sb, group_no);
 		if (!bitmap_bh)
 			goto io_error;
-		ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
-					bitmap_bh, -1, my_rsv, &num, &fatal);
+		/*
+		 * try to allocate block(s) from this group, without a goal(-1).
+		 */
+		grp_alloc_blk = ext3_try_to_allocate_with_rsv(sb, handle,
+					group_no, bitmap_bh, -1, my_rsv,
+					&num, &fatal);
 		if (fatal)
 			goto out;
-		if (ret_block >= 0) 
+		if (grp_alloc_blk >= 0)
 			goto allocated;
 	}
 	/*
@@ -1360,18 +1366,18 @@
 	if (fatal)
 		goto out;
 
-	target_block = ret_block + group_no * EXT3_BLOCKS_PER_GROUP(sb)
-				+ le32_to_cpu(es->s_first_data_block);
+	ret_block = grp_alloc_blk + ext3_group_first_block_no(sb, group_no);
 
-	if (in_range(le32_to_cpu(gdp->bg_block_bitmap), target_block, num) ||
-	    in_range(le32_to_cpu(gdp->bg_inode_bitmap), target_block, num) ||
-	    in_range(target_block, le32_to_cpu(gdp->bg_inode_table),
+	if (in_range(le32_to_cpu(gdp->bg_block_bitmap), ret_block, num) ||
+	    in_range(le32_to_cpu(gdp->bg_inode_bitmap), ret_block, num) ||
+	    in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
 		      EXT3_SB(sb)->s_itb_per_group) ||
-	    in_range(target_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
+	    in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
 		      EXT3_SB(sb)->s_itb_per_group))
 		ext3_error(sb, "ext3_new_block",
 			    "Allocating block in system zone - "
-			    "blocks from %u, length %lu", target_block, num);
+			    "blocks from "E3FSBLK", length %lu",
+			     ret_block, num);
 
 	performed_allocation = 1;
 
@@ -1380,7 +1386,7 @@
 		struct buffer_head *debug_bh;
 
 		/* Record bitmap buffer state in the newly allocated block */
-		debug_bh = sb_find_get_block(sb, target_block);
+		debug_bh = sb_find_get_block(sb, ret_block);
 		if (debug_bh) {
 			BUFFER_TRACE(debug_bh, "state when allocated");
 			BUFFER_TRACE2(debug_bh, bitmap_bh, "bitmap state");
@@ -1393,24 +1399,21 @@
 		int i;
 
 		for (i = 0; i < num; i++) {
-			if (ext3_test_bit(ret_block,
+			if (ext3_test_bit(grp_alloc_blk+i,
 					bh2jh(bitmap_bh)->b_committed_data)) {
 				printk("%s: block was unexpectedly set in "
 					"b_committed_data\n", __FUNCTION__);
 			}
 		}
 	}
-	ext3_debug("found bit %d\n", ret_block);
+	ext3_debug("found bit %d\n", grp_alloc_blk);
 	spin_unlock(sb_bgl_lock(sbi, group_no));
 	jbd_unlock_bh_state(bitmap_bh);
 #endif
 
-	/* ret_block was blockgroup-relative.  Now it becomes fs-relative */
-	ret_block = target_block;
-
 	if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
 		ext3_error(sb, "ext3_new_block",
-			    "block(%d) >= blocks count(%d) - "
+			    "block("E3FSBLK") >= blocks count(%d) - "
 			    "block_group = %d, es == %p ", ret_block,
 			le32_to_cpu(es->s_blocks_count), group_no, es);
 		goto out;
@@ -1421,7 +1424,7 @@
 	 * list of some description.  We don't know in advance whether
 	 * the caller wants to use it as metadata or data.
 	 */
-	ext3_debug("allocating block %d. Goal hits %d of %d.\n",
+	ext3_debug("allocating block %lu. Goal hits %d of %d.\n",
 			ret_block, goal_hits, goal_attempts);
 
 	spin_lock(sb_bgl_lock(sbi, group_no));
@@ -1461,23 +1464,24 @@
 	return 0;
 }
 
-int ext3_new_block(handle_t *handle, struct inode *inode,
-			unsigned long goal, int *errp)
+ext3_fsblk_t ext3_new_block(handle_t *handle, struct inode *inode,
+			ext3_fsblk_t goal, int *errp)
 {
 	unsigned long count = 1;
 
 	return ext3_new_blocks(handle, inode, goal, &count, errp);
 }
 
-unsigned long ext3_count_free_blocks(struct super_block *sb)
+ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb)
 {
-	unsigned long desc_count;
+	ext3_fsblk_t desc_count;
 	struct ext3_group_desc *gdp;
 	int i;
 	unsigned long ngroups = EXT3_SB(sb)->s_groups_count;
 #ifdef EXT3FS_DEBUG
 	struct ext3_super_block *es;
-	unsigned long bitmap_count, x;
+	ext3_fsblk_t bitmap_count;
+	unsigned long x;
 	struct buffer_head *bitmap_bh = NULL;
 
 	es = EXT3_SB(sb)->s_es;
@@ -1502,8 +1506,10 @@
 		bitmap_count += x;
 	}
 	brelse(bitmap_bh);
-	printk("ext3_count_free_blocks: stored = %u, computed = %lu, %lu\n",
-	       le32_to_cpu(es->s_free_blocks_count), desc_count, bitmap_count);
+	printk("ext3_count_free_blocks: stored = "E3FSBLK
+		", computed = "E3FSBLK", "E3FSBLK"\n",
+	       le32_to_cpu(es->s_free_blocks_count),
+		desc_count, bitmap_count);
 	return bitmap_count;
 #else
 	desc_count = 0;
@@ -1520,7 +1526,7 @@
 }
 
 static inline int
-block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
+block_in_use(ext3_fsblk_t block, struct super_block *sb, unsigned char *map)
 {
 	return ext3_test_bit ((block -
 		le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c
index f37528e..fbb0d4e 100644
--- a/fs/ext3/dir.c
+++ b/fs/ext3/dir.c
@@ -284,7 +284,7 @@
 		 * beginning of the loop and try to free the parent
 		 * node.
 		 */
-		parent = n->rb_parent;
+		parent = rb_parent(n);
 		fname = rb_entry(n, struct fname, rb_hash);
 		while (fname) {
 			struct fname * old = fname;
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index dc82646..36546ed 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -262,9 +262,11 @@
 	int ngroups = sbi->s_groups_count;
 	int inodes_per_group = EXT3_INODES_PER_GROUP(sb);
 	int freei, avefreei;
-	int freeb, avefreeb;
-	int blocks_per_dir, ndirs;
-	int max_debt, max_dirs, min_blocks, min_inodes;
+	ext3_fsblk_t freeb, avefreeb;
+	ext3_fsblk_t blocks_per_dir;
+	int ndirs;
+	int max_debt, max_dirs, min_inodes;
+	ext3_grpblk_t min_blocks;
 	int group = -1, i;
 	struct ext3_group_desc *desc;
 	struct buffer_head *bh;
@@ -307,7 +309,7 @@
 	min_inodes = avefreei - inodes_per_group / 4;
 	min_blocks = avefreeb - EXT3_BLOCKS_PER_GROUP(sb) / 4;
 
-	max_debt = EXT3_BLOCKS_PER_GROUP(sb) / max(blocks_per_dir, BLOCK_COST);
+	max_debt = EXT3_BLOCKS_PER_GROUP(sb) / max(blocks_per_dir, (ext3_fsblk_t)BLOCK_COST);
 	if (max_debt * INODE_COST > inodes_per_group)
 		max_debt = inodes_per_group / INODE_COST;
 	if (max_debt > 255)
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 2edd7ee..f804d5e 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -62,7 +62,7 @@
  * still needs to be revoked.
  */
 int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
-			struct buffer_head *bh, int blocknr)
+			struct buffer_head *bh, ext3_fsblk_t blocknr)
 {
 	int err;
 
@@ -407,13 +407,13 @@
  *
  *	Caller must make sure that @ind is valid and will stay that way.
  */
-static unsigned long ext3_find_near(struct inode *inode, Indirect *ind)
+static ext3_fsblk_t ext3_find_near(struct inode *inode, Indirect *ind)
 {
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	__le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data;
 	__le32 *p;
-	unsigned long bg_start;
-	unsigned long colour;
+	ext3_fsblk_t bg_start;
+	ext3_grpblk_t colour;
 
 	/* Try to find previous block */
 	for (p = ind->p - 1; p >= start; p--) {
@@ -429,8 +429,7 @@
 	 * It is going to be referred to from the inode itself? OK, just put it
 	 * into the same cylinder group then.
 	 */
-	bg_start = (ei->i_block_group * EXT3_BLOCKS_PER_GROUP(inode->i_sb)) +
-		le32_to_cpu(EXT3_SB(inode->i_sb)->s_es->s_first_data_block);
+	bg_start = ext3_group_first_block_no(inode->i_sb, ei->i_block_group);
 	colour = (current->pid % 16) *
 			(EXT3_BLOCKS_PER_GROUP(inode->i_sb) / 16);
 	return bg_start + colour;
@@ -448,7 +447,7 @@
  *	stores it in *@goal and returns zero.
  */
 
-static unsigned long ext3_find_goal(struct inode *inode, long block,
+static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block,
 		Indirect chain[4], Indirect *partial)
 {
 	struct ext3_block_alloc_info *block_i;
@@ -516,13 +515,13 @@
  *		direct blocks
  */
 static int ext3_alloc_blocks(handle_t *handle, struct inode *inode,
-			unsigned long goal, int indirect_blks, int blks,
-			unsigned long long new_blocks[4], int *err)
+			ext3_fsblk_t goal, int indirect_blks, int blks,
+			ext3_fsblk_t new_blocks[4], int *err)
 {
 	int target, i;
 	unsigned long count = 0;
 	int index = 0;
-	unsigned long current_block = 0;
+	ext3_fsblk_t current_block = 0;
 	int ret = 0;
 
 	/*
@@ -592,7 +591,7 @@
  *	as described above and return 0.
  */
 static int ext3_alloc_branch(handle_t *handle, struct inode *inode,
-			int indirect_blks, int *blks, unsigned long goal,
+			int indirect_blks, int *blks, ext3_fsblk_t goal,
 			int *offsets, Indirect *branch)
 {
 	int blocksize = inode->i_sb->s_blocksize;
@@ -600,8 +599,8 @@
 	int err = 0;
 	struct buffer_head *bh;
 	int num;
-	unsigned long long new_blocks[4];
-	unsigned long long current_block;
+	ext3_fsblk_t new_blocks[4];
+	ext3_fsblk_t current_block;
 
 	num = ext3_alloc_blocks(handle, inode, goal, indirect_blks,
 				*blks, new_blocks, &err);
@@ -688,7 +687,7 @@
 	int i;
 	int err = 0;
 	struct ext3_block_alloc_info *block_i;
-	unsigned long current_block;
+	ext3_fsblk_t current_block;
 
 	block_i = EXT3_I(inode)->i_block_alloc_info;
 	/*
@@ -795,13 +794,13 @@
 	int offsets[4];
 	Indirect chain[4];
 	Indirect *partial;
-	unsigned long goal;
+	ext3_fsblk_t goal;
 	int indirect_blks;
 	int blocks_to_boundary = 0;
 	int depth;
 	struct ext3_inode_info *ei = EXT3_I(inode);
 	int count = 0;
-	unsigned long first_block = 0;
+	ext3_fsblk_t first_block = 0;
 
 
 	J_ASSERT(handle != NULL || create == 0);
@@ -819,7 +818,7 @@
 		count++;
 		/*map more blocks*/
 		while (count < maxblocks && count <= blocks_to_boundary) {
-			unsigned long blk;
+			ext3_fsblk_t blk;
 
 			if (!verify_chain(chain, partial)) {
 				/*
@@ -1699,7 +1698,7 @@
 	return __set_page_dirty_nobuffers(page);
 }
 
-static struct address_space_operations ext3_ordered_aops = {
+static const struct address_space_operations ext3_ordered_aops = {
 	.readpage	= ext3_readpage,
 	.readpages	= ext3_readpages,
 	.writepage	= ext3_ordered_writepage,
@@ -1713,7 +1712,7 @@
 	.migratepage	= buffer_migrate_page,
 };
 
-static struct address_space_operations ext3_writeback_aops = {
+static const struct address_space_operations ext3_writeback_aops = {
 	.readpage	= ext3_readpage,
 	.readpages	= ext3_readpages,
 	.writepage	= ext3_writeback_writepage,
@@ -1727,7 +1726,7 @@
 	.migratepage	= buffer_migrate_page,
 };
 
-static struct address_space_operations ext3_journalled_aops = {
+static const struct address_space_operations ext3_journalled_aops = {
 	.readpage	= ext3_readpage,
 	.readpages	= ext3_readpages,
 	.writepage	= ext3_journalled_writepage,
@@ -1759,7 +1758,7 @@
 static int ext3_block_truncate_page(handle_t *handle, struct page *page,
 		struct address_space *mapping, loff_t from)
 {
-	unsigned long index = from >> PAGE_CACHE_SHIFT;
+	ext3_fsblk_t index = from >> PAGE_CACHE_SHIFT;
 	unsigned offset = from & (PAGE_CACHE_SIZE-1);
 	unsigned blocksize, iblock, length, pos;
 	struct inode *inode = mapping->host;
@@ -1960,7 +1959,7 @@
  * than `count' because there can be holes in there.
  */
 static void ext3_clear_blocks(handle_t *handle, struct inode *inode,
-		struct buffer_head *bh, unsigned long block_to_free,
+		struct buffer_head *bh, ext3_fsblk_t block_to_free,
 		unsigned long count, __le32 *first, __le32 *last)
 {
 	__le32 *p;
@@ -2022,12 +2021,12 @@
 			   struct buffer_head *this_bh,
 			   __le32 *first, __le32 *last)
 {
-	unsigned long block_to_free = 0;    /* Starting block # of a run */
+	ext3_fsblk_t block_to_free = 0;    /* Starting block # of a run */
 	unsigned long count = 0;	    /* Number of blocks in the run */ 
 	__le32 *block_to_free_p = NULL;	    /* Pointer into inode/ind
 					       corresponding to
 					       block_to_free */
-	unsigned long nr;		    /* Current block # */
+	ext3_fsblk_t nr;		    /* Current block # */
 	__le32 *p;			    /* Pointer into inode/ind
 					       for current block */
 	int err;
@@ -2089,7 +2088,7 @@
 			       struct buffer_head *parent_bh,
 			       __le32 *first, __le32 *last, int depth)
 {
-	unsigned long nr;
+	ext3_fsblk_t nr;
 	__le32 *p;
 
 	if (is_handle_aborted(handle))
@@ -2113,7 +2112,7 @@
 			 */
 			if (!bh) {
 				ext3_error(inode->i_sb, "ext3_free_branches",
-					   "Read failure, inode=%ld, block=%ld",
+					   "Read failure, inode=%ld, block="E3FSBLK,
 					   inode->i_ino, nr);
 				continue;
 			}
@@ -2394,11 +2393,12 @@
 	ext3_journal_stop(handle);
 }
 
-static unsigned long ext3_get_inode_block(struct super_block *sb,
+static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb,
 		unsigned long ino, struct ext3_iloc *iloc)
 {
 	unsigned long desc, group_desc, block_group;
-	unsigned long offset, block;
+	unsigned long offset;
+	ext3_fsblk_t block;
 	struct buffer_head *bh;
 	struct ext3_group_desc * gdp;
 
@@ -2448,7 +2448,7 @@
 static int __ext3_get_inode_loc(struct inode *inode,
 				struct ext3_iloc *iloc, int in_mem)
 {
-	unsigned long block;
+	ext3_fsblk_t block;
 	struct buffer_head *bh;
 
 	block = ext3_get_inode_block(inode->i_sb, inode->i_ino, iloc);
@@ -2459,7 +2459,8 @@
 	if (!bh) {
 		ext3_error (inode->i_sb, "ext3_get_inode_loc",
 				"unable to read inode block - "
-				"inode=%lu, block=%lu", inode->i_ino, block);
+				"inode=%lu, block="E3FSBLK,
+				 inode->i_ino, block);
 		return -EIO;
 	}
 	if (!buffer_uptodate(bh)) {
@@ -2540,7 +2541,7 @@
 		if (!buffer_uptodate(bh)) {
 			ext3_error(inode->i_sb, "ext3_get_inode_loc",
 					"unable to read inode block - "
-					"inode=%lu, block=%lu",
+					"inode=%lu, block="E3FSBLK,
 					inode->i_ino, block);
 			brelse(bh);
 			return -EIO;
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 8c22aa9a..3a6b012 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -204,7 +204,7 @@
 		return 0;
 	}
 	case EXT3_IOC_GROUP_EXTEND: {
-		unsigned long n_blocks_count;
+		ext3_fsblk_t n_blocks_count;
 		struct super_block *sb = inode->i_sb;
 		int err;
 
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index b8f5cd1..d9176db 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -1379,7 +1379,6 @@
 	int	dx_fallback=0;
 #endif
 	unsigned blocksize;
-	unsigned nlen, rlen;
 	u32 block, blocks;
 
 	sb = dir->i_sb;
@@ -1417,8 +1416,7 @@
 		return retval;
 	de = (struct ext3_dir_entry_2 *) bh->b_data;
 	de->inode = 0;
-	de->rec_len = cpu_to_le16(rlen = blocksize);
-	nlen = 0;
+	de->rec_len = cpu_to_le16(blocksize);
 	return add_dirent_to_buf(handle, dentry, inode, de, bh);
 }
 
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c
index 34b39e9..dfd8118 100644
--- a/fs/ext3/resize.c
+++ b/fs/ext3/resize.c
@@ -28,16 +28,16 @@
 {
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	struct ext3_super_block *es = sbi->s_es;
-	unsigned start = le32_to_cpu(es->s_blocks_count);
-	unsigned end = start + input->blocks_count;
+	ext3_fsblk_t start = le32_to_cpu(es->s_blocks_count);
+	ext3_fsblk_t end = start + input->blocks_count;
 	unsigned group = input->group;
-	unsigned itend = input->inode_table + sbi->s_itb_per_group;
+	ext3_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
 	unsigned overhead = ext3_bg_has_super(sb, group) ?
 		(1 + ext3_bg_num_gdb(sb, group) +
 		 le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;
-	unsigned metaend = start + overhead;
+	ext3_fsblk_t metaend = start + overhead;
 	struct buffer_head *bh = NULL;
-	int free_blocks_count;
+	ext3_grpblk_t free_blocks_count;
 	int err = -EINVAL;
 
 	input->free_blocks_count = free_blocks_count =
@@ -64,7 +64,8 @@
 		ext3_warning(sb, __FUNCTION__, "Bad blocks count %u",
 			     input->blocks_count);
 	else if (!(bh = sb_bread(sb, end - 1)))
-		ext3_warning(sb, __FUNCTION__, "Cannot read last block (%u)",
+		ext3_warning(sb, __FUNCTION__,
+			     "Cannot read last block ("E3FSBLK")",
 			     end - 1);
 	else if (outside(input->block_bitmap, start, end))
 		ext3_warning(sb, __FUNCTION__,
@@ -77,7 +78,7 @@
 	else if (outside(input->inode_table, start, end) ||
 	         outside(itend - 1, start, end))
 		ext3_warning(sb, __FUNCTION__,
-			     "Inode table not in group (blocks %u-%u)",
+			     "Inode table not in group (blocks %u-"E3FSBLK")",
 			     input->inode_table, itend - 1);
 	else if (input->inode_bitmap == input->block_bitmap)
 		ext3_warning(sb, __FUNCTION__,
@@ -85,24 +86,27 @@
 			     input->block_bitmap);
 	else if (inside(input->block_bitmap, input->inode_table, itend))
 		ext3_warning(sb, __FUNCTION__,
-			     "Block bitmap (%u) in inode table (%u-%u)",
+			     "Block bitmap (%u) in inode table (%u-"E3FSBLK")",
 			     input->block_bitmap, input->inode_table, itend-1);
 	else if (inside(input->inode_bitmap, input->inode_table, itend))
 		ext3_warning(sb, __FUNCTION__,
-			     "Inode bitmap (%u) in inode table (%u-%u)",
+			     "Inode bitmap (%u) in inode table (%u-"E3FSBLK")",
 			     input->inode_bitmap, input->inode_table, itend-1);
 	else if (inside(input->block_bitmap, start, metaend))
 		ext3_warning(sb, __FUNCTION__,
-			     "Block bitmap (%u) in GDT table (%u-%u)",
+			     "Block bitmap (%u) in GDT table"
+			     " ("E3FSBLK"-"E3FSBLK")",
 			     input->block_bitmap, start, metaend - 1);
 	else if (inside(input->inode_bitmap, start, metaend))
 		ext3_warning(sb, __FUNCTION__,
-			     "Inode bitmap (%u) in GDT table (%u-%u)",
+			     "Inode bitmap (%u) in GDT table"
+			     " ("E3FSBLK"-"E3FSBLK")",
 			     input->inode_bitmap, start, metaend - 1);
 	else if (inside(input->inode_table, start, metaend) ||
 	         inside(itend - 1, start, metaend))
 		ext3_warning(sb, __FUNCTION__,
-			     "Inode table (%u-%u) overlaps GDT table (%u-%u)",
+			     "Inode table (%u-"E3FSBLK") overlaps"
+			     "GDT table ("E3FSBLK"-"E3FSBLK")",
 			     input->inode_table, itend - 1, start, metaend - 1);
 	else
 		err = 0;
@@ -112,7 +116,7 @@
 }
 
 static struct buffer_head *bclean(handle_t *handle, struct super_block *sb,
-				  unsigned long blk)
+				  ext3_fsblk_t blk)
 {
 	struct buffer_head *bh;
 	int err;
@@ -163,15 +167,14 @@
 				  struct ext3_new_group_data *input)
 {
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
-	unsigned long start = input->group * sbi->s_blocks_per_group +
-		le32_to_cpu(sbi->s_es->s_first_data_block);
+	ext3_fsblk_t start = ext3_group_first_block_no(sb, input->group);
 	int reserved_gdb = ext3_bg_has_super(sb, input->group) ?
 		le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) : 0;
 	unsigned long gdblocks = ext3_bg_num_gdb(sb, input->group);
 	struct buffer_head *bh;
 	handle_t *handle;
-	unsigned long block;
-	int bit;
+	ext3_fsblk_t block;
+	ext3_grpblk_t bit;
 	int i;
 	int err = 0, err2;
 
@@ -328,7 +331,7 @@
 static int verify_reserved_gdb(struct super_block *sb,
 			       struct buffer_head *primary)
 {
-	const unsigned long blk = primary->b_blocknr;
+	const ext3_fsblk_t blk = primary->b_blocknr;
 	const unsigned long end = EXT3_SB(sb)->s_groups_count;
 	unsigned three = 1;
 	unsigned five = 5;
@@ -340,7 +343,8 @@
 	while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) {
 		if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){
 			ext3_warning(sb, __FUNCTION__,
-				     "reserved GDT %ld missing grp %d (%ld)",
+				     "reserved GDT "E3FSBLK
+				     " missing grp %d ("E3FSBLK")",
 				     blk, grp,
 				     grp * EXT3_BLOCKS_PER_GROUP(sb) + blk);
 			return -EINVAL;
@@ -372,7 +376,7 @@
 	struct super_block *sb = inode->i_sb;
 	struct ext3_super_block *es = EXT3_SB(sb)->s_es;
 	unsigned long gdb_num = input->group / EXT3_DESC_PER_BLOCK(sb);
-	unsigned long gdblock = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
+	ext3_fsblk_t gdblock = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + gdb_num;
 	struct buffer_head **o_group_desc, **n_group_desc;
 	struct buffer_head *dind;
 	int gdbackups;
@@ -417,7 +421,7 @@
 	data = (__u32 *)dind->b_data;
 	if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) {
 		ext3_warning(sb, __FUNCTION__,
-			     "new group %u GDT block %lu not reserved",
+			     "new group %u GDT block "E3FSBLK" not reserved",
 			     input->group, gdblock);
 		err = -EINVAL;
 		goto exit_dind;
@@ -515,7 +519,7 @@
 	struct buffer_head **primary;
 	struct buffer_head *dind;
 	struct ext3_iloc iloc;
-	unsigned long blk;
+	ext3_fsblk_t blk;
 	__u32 *data, *end;
 	int gdbackups = 0;
 	int res, i;
@@ -540,7 +544,8 @@
 	for (res = 0; res < reserved_gdb; res++, blk++) {
 		if (le32_to_cpu(*data) != blk) {
 			ext3_warning(sb, __FUNCTION__,
-				     "reserved block %lu not at offset %ld",
+				     "reserved block "E3FSBLK
+				     " not at offset %ld",
 				     blk, (long)(data - (__u32 *)dind->b_data));
 			err = -EINVAL;
 			goto exit_bh;
@@ -902,15 +907,16 @@
  * GDT blocks are reserved to grow to the desired size.
  */
 int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
-		      unsigned long n_blocks_count)
+		      ext3_fsblk_t n_blocks_count)
 {
-	unsigned long o_blocks_count;
+	ext3_fsblk_t o_blocks_count;
 	unsigned long o_groups_count;
-	unsigned long last;
-	int add;
+	ext3_grpblk_t last;
+	ext3_grpblk_t add;
 	struct buffer_head * bh;
 	handle_t *handle;
-	int err, freed_blocks;
+	int err;
+	unsigned long freed_blocks;
 
 	/* We don't need to worry about locking wrt other resizers just
 	 * yet: we're going to revalidate es->s_blocks_count after
@@ -919,12 +925,22 @@
 	o_groups_count = EXT3_SB(sb)->s_groups_count;
 
 	if (test_opt(sb, DEBUG))
-		printk(KERN_DEBUG "EXT3-fs: extending last group from %lu to %lu blocks\n",
+		printk(KERN_DEBUG "EXT3-fs: extending last group from "E3FSBLK" uto "E3FSBLK" blocks\n",
 		       o_blocks_count, n_blocks_count);
 
 	if (n_blocks_count == 0 || n_blocks_count == o_blocks_count)
 		return 0;
 
+	if (n_blocks_count > (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+		printk(KERN_ERR "EXT3-fs: filesystem on %s:"
+			" too large to resize to %lu blocks safely\n",
+			sb->s_id, n_blocks_count);
+		if (sizeof(sector_t) < 8)
+			ext3_warning(sb, __FUNCTION__,
+			"CONFIG_LBD not enabled\n");
+		return -EINVAL;
+	}
+
 	if (n_blocks_count < o_blocks_count) {
 		ext3_warning(sb, __FUNCTION__,
 			     "can't shrink FS - resize aborted");
@@ -948,7 +964,8 @@
 
 	if (o_blocks_count + add < n_blocks_count)
 		ext3_warning(sb, __FUNCTION__,
-			     "will only finish group (%lu blocks, %u new)",
+			     "will only finish group ("E3FSBLK
+			     " blocks, %u new)",
 			     o_blocks_count + add, add);
 
 	/* See if the device is actually as big as what was requested */
@@ -991,10 +1008,10 @@
 	ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
 	sb->s_dirt = 1;
 	unlock_super(sb);
-	ext3_debug("freeing blocks %ld through %ld\n", o_blocks_count,
+	ext3_debug("freeing blocks %lu through "E3FSBLK"\n", o_blocks_count,
 		   o_blocks_count + add);
 	ext3_free_blocks_sb(handle, sb, o_blocks_count, add, &freed_blocks);
-	ext3_debug("freed blocks %ld through %ld\n", o_blocks_count,
+	ext3_debug("freed blocks "E3FSBLK" through "E3FSBLK"\n", o_blocks_count,
 		   o_blocks_count + add);
 	if ((err = ext3_journal_stop(handle)))
 		goto exit_put;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index f8a5266..b748336 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -58,7 +58,7 @@
 static const char *ext3_decode_error(struct super_block * sb, int errno,
 				     char nbuf[16]);
 static int ext3_remount (struct super_block * sb, int * flags, char * data);
-static int ext3_statfs (struct super_block * sb, struct kstatfs * buf);
+static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf);
 static void ext3_unlockfs(struct super_block *sb);
 static void ext3_write_super (struct super_block * sb);
 static void ext3_write_super_lockfs(struct super_block *sb);
@@ -499,20 +499,21 @@
 {
 	struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
-       if (EXT3_I(inode)->i_acl &&
-           EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) {
-               posix_acl_release(EXT3_I(inode)->i_acl);
-               EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED;
-       }
-       if (EXT3_I(inode)->i_default_acl &&
-           EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) {
-               posix_acl_release(EXT3_I(inode)->i_default_acl);
-               EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED;
-       }
+	if (EXT3_I(inode)->i_acl &&
+			EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) {
+		posix_acl_release(EXT3_I(inode)->i_acl);
+		EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED;
+	}
+	if (EXT3_I(inode)->i_default_acl &&
+			EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) {
+		posix_acl_release(EXT3_I(inode)->i_default_acl);
+		EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED;
+	}
 #endif
 	ext3_discard_reservation(inode);
 	EXT3_I(inode)->i_block_alloc_info = NULL;
-	kfree(rsv);
+	if (unlikely(rsv))
+		kfree(rsv);
 }
 
 static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb)
@@ -629,7 +630,7 @@
 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
 	Opt_nouid32, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov,
 	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
-	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh,
+	Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
 	Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
@@ -665,6 +666,7 @@
 	{Opt_noreservation, "noreservation"},
 	{Opt_noload, "noload"},
 	{Opt_nobh, "nobh"},
+	{Opt_bh, "bh"},
 	{Opt_commit, "commit=%u"},
 	{Opt_journal_update, "journal=update"},
 	{Opt_journal_inum, "journal=%u"},
@@ -688,14 +690,15 @@
 	{Opt_resize, "resize"},
 };
 
-static unsigned long get_sb_block(void **data)
+static ext3_fsblk_t get_sb_block(void **data)
 {
-	unsigned long 	sb_block;
+	ext3_fsblk_t 	sb_block;
 	char 		*options = (char *) *data;
 
 	if (!options || strncmp(options, "sb=", 3) != 0)
 		return 1;	/* Default location */
 	options += 3;
+	/*todo: use simple_strtoll with >32bit ext3 */
 	sb_block = simple_strtoul(options, &options, 0);
 	if (*options && *options != ',') {
 		printk("EXT3-fs: Invalid sb specification: %s\n",
@@ -710,7 +713,7 @@
 
 static int parse_options (char *options, struct super_block *sb,
 			  unsigned long *inum, unsigned long *journal_devnum,
-			  unsigned long *n_blocks_count, int is_remount)
+			  ext3_fsblk_t *n_blocks_count, int is_remount)
 {
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	char * p;
@@ -1012,6 +1015,9 @@
 		case Opt_nobh:
 			set_opt(sbi->s_mount_opt, NOBH);
 			break;
+		case Opt_bh:
+			clear_opt(sbi->s_mount_opt, NOBH);
+			break;
 		default:
 			printk (KERN_ERR
 				"EXT3-fs: Unrecognized mount option \"%s\" "
@@ -1127,7 +1133,7 @@
 static int ext3_check_descriptors (struct super_block * sb)
 {
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
-	unsigned long block = le32_to_cpu(sbi->s_es->s_first_data_block);
+	ext3_fsblk_t block = le32_to_cpu(sbi->s_es->s_first_data_block);
 	struct ext3_group_desc * gdp = NULL;
 	int desc_block = 0;
 	int i;
@@ -1314,15 +1320,14 @@
 	return res;
 }
 
-static unsigned long descriptor_loc(struct super_block *sb,
-				    unsigned long logic_sb_block,
+static ext3_fsblk_t descriptor_loc(struct super_block *sb,
+				    ext3_fsblk_t logic_sb_block,
 				    int nr)
 {
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
-	unsigned long bg, first_data_block, first_meta_bg;
+	unsigned long bg, first_meta_bg;
 	int has_super = 0;
 
-	first_data_block = le32_to_cpu(sbi->s_es->s_first_data_block);
 	first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg);
 
 	if (!EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_META_BG) ||
@@ -1331,7 +1336,7 @@
 	bg = sbi->s_desc_per_block * nr;
 	if (ext3_bg_has_super(sb, bg))
 		has_super = 1;
-	return (first_data_block + has_super + (bg * sbi->s_blocks_per_group));
+	return (has_super + ext3_group_first_block_no(sb, bg));
 }
 
 
@@ -1340,9 +1345,9 @@
 	struct buffer_head * bh;
 	struct ext3_super_block *es = NULL;
 	struct ext3_sb_info *sbi;
-	unsigned long block;
-	unsigned long sb_block = get_sb_block(&data);
-	unsigned long logic_sb_block;
+	ext3_fsblk_t block;
+	ext3_fsblk_t sb_block = get_sb_block(&data);
+	ext3_fsblk_t logic_sb_block;
 	unsigned long offset = 0;
 	unsigned long journal_inum = 0;
 	unsigned long journal_devnum = 0;
@@ -1564,6 +1569,16 @@
 		goto failed_mount;
 	}
 
+	if (le32_to_cpu(es->s_blocks_count) >
+		    (sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
+		printk(KERN_ERR "EXT3-fs: filesystem on %s:"
+			" too large to mount safely\n", sb->s_id);
+		if (sizeof(sector_t) < 8)
+			printk(KERN_WARNING "EXT3-fs: CONFIG_LBD not "
+					"enabled\n");
+		goto failed_mount;
+	}
+
 	if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
 		goto cantfind_ext3;
 	sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
@@ -1579,9 +1594,6 @@
 		goto failed_mount;
 	}
 
-	percpu_counter_init(&sbi->s_freeblocks_counter);
-	percpu_counter_init(&sbi->s_freeinodes_counter);
-	percpu_counter_init(&sbi->s_dirs_counter);
 	bgl_lock_init(&sbi->s_blockgroup_lock);
 
 	for (i = 0; i < db_count; i++) {
@@ -1595,12 +1607,20 @@
 		}
 	}
 	if (!ext3_check_descriptors (sb)) {
-		printk (KERN_ERR "EXT3-fs: group descriptors corrupted !\n");
+		printk(KERN_ERR "EXT3-fs: group descriptors corrupted!\n");
 		goto failed_mount2;
 	}
 	sbi->s_gdb_count = db_count;
 	get_random_bytes(&sbi->s_next_generation, sizeof(u32));
 	spin_lock_init(&sbi->s_next_gen_lock);
+
+	percpu_counter_init(&sbi->s_freeblocks_counter,
+		ext3_count_free_blocks(sb));
+	percpu_counter_init(&sbi->s_freeinodes_counter,
+		ext3_count_free_inodes(sb));
+	percpu_counter_init(&sbi->s_dirs_counter,
+		ext3_count_dirs(sb));
+
 	/* per fileystem reservation list head & lock */
 	spin_lock_init(&sbi->s_rsv_window_lock);
 	sbi->s_rsv_window_root = RB_ROOT;
@@ -1639,16 +1659,16 @@
 	if (!test_opt(sb, NOLOAD) &&
 	    EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
 		if (ext3_load_journal(sb, es, journal_devnum))
-			goto failed_mount2;
+			goto failed_mount3;
 	} else if (journal_inum) {
 		if (ext3_create_journal(sb, es, journal_inum))
-			goto failed_mount2;
+			goto failed_mount3;
 	} else {
 		if (!silent)
 			printk (KERN_ERR
 				"ext3: No journal on filesystem on %s\n",
 				sb->s_id);
-		goto failed_mount2;
+		goto failed_mount3;
 	}
 
 	/* We have now updated the journal if required, so we can
@@ -1671,7 +1691,7 @@
 		    (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) {
 			printk(KERN_ERR "EXT3-fs: Journal does not support "
 			       "requested data journaling mode\n");
-			goto failed_mount3;
+			goto failed_mount4;
 		}
 	default:
 		break;
@@ -1694,13 +1714,13 @@
 	if (!sb->s_root) {
 		printk(KERN_ERR "EXT3-fs: get root inode failed\n");
 		iput(root);
-		goto failed_mount3;
+		goto failed_mount4;
 	}
 	if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
 		dput(sb->s_root);
 		sb->s_root = NULL;
 		printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n");
-		goto failed_mount3;
+		goto failed_mount4;
 	}
 
 	ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY);
@@ -1723,13 +1743,6 @@
 		test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered":
 		"writeback");
 
-	percpu_counter_mod(&sbi->s_freeblocks_counter,
-		ext3_count_free_blocks(sb));
-	percpu_counter_mod(&sbi->s_freeinodes_counter,
-		ext3_count_free_inodes(sb));
-	percpu_counter_mod(&sbi->s_dirs_counter,
-		ext3_count_dirs(sb));
-
 	lock_kernel();
 	return 0;
 
@@ -1739,8 +1752,12 @@
 		       sb->s_id);
 	goto failed_mount;
 
-failed_mount3:
+failed_mount4:
 	journal_destroy(sbi->s_journal);
+failed_mount3:
+	percpu_counter_destroy(&sbi->s_freeblocks_counter);
+	percpu_counter_destroy(&sbi->s_freeinodes_counter);
+	percpu_counter_destroy(&sbi->s_dirs_counter);
 failed_mount2:
 	for (i = 0; i < db_count; i++)
 		brelse(sbi->s_group_desc[i]);
@@ -1827,10 +1844,10 @@
 {
 	struct buffer_head * bh;
 	journal_t *journal;
-	int start;
-	int len;
+	ext3_fsblk_t start;
+	ext3_fsblk_t len;
 	int hblock, blocksize;
-	unsigned long sb_block;
+	ext3_fsblk_t sb_block;
 	unsigned long offset;
 	struct ext3_super_block * es;
 	struct block_device *bdev;
@@ -2203,7 +2220,7 @@
 {
 	struct ext3_super_block * es;
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
-	unsigned long n_blocks_count = 0;
+	ext3_fsblk_t n_blocks_count = 0;
 	unsigned long old_sb_flags;
 	struct ext3_mount_options old_opts;
 	int err;
@@ -2318,11 +2335,12 @@
 	return err;
 }
 
-static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
+static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
 {
+	struct super_block *sb = dentry->d_sb;
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	struct ext3_super_block *es = sbi->s_es;
-	unsigned long overhead;
+	ext3_fsblk_t overhead;
 	int i;
 
 	if (test_opt (sb, MINIX_DF))
@@ -2646,10 +2664,10 @@
 
 #endif
 
-static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int ext3_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt);
 }
 
 static struct file_system_type ext3_fs_type = {
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index e8d60bf..a44a056 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -225,7 +225,7 @@
 	error = -ENODATA;
 	if (!EXT3_I(inode)->i_file_acl)
 		goto cleanup;
-	ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
+	ea_idebug(inode, "reading block %u", EXT3_I(inode)->i_file_acl);
 	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
 	if (!bh)
 		goto cleanup;
@@ -233,7 +233,7 @@
 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
 	if (ext3_xattr_check_block(bh)) {
 bad_block:	ext3_error(inode->i_sb, __FUNCTION__,
-			   "inode %ld: bad block %d", inode->i_ino,
+			   "inode %ld: bad block "E3FSBLK, inode->i_ino,
 			   EXT3_I(inode)->i_file_acl);
 		error = -EIO;
 		goto cleanup;
@@ -366,7 +366,7 @@
 	error = 0;
 	if (!EXT3_I(inode)->i_file_acl)
 		goto cleanup;
-	ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
+	ea_idebug(inode, "reading block %u", EXT3_I(inode)->i_file_acl);
 	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
 	error = -EIO;
 	if (!bh)
@@ -375,7 +375,7 @@
 		atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
 	if (ext3_xattr_check_block(bh)) {
 		ext3_error(inode->i_sb, __FUNCTION__,
-			   "inode %ld: bad block %d", inode->i_ino,
+			   "inode %ld: bad block "E3FSBLK, inode->i_ino,
 			   EXT3_I(inode)->i_file_acl);
 		error = -EIO;
 		goto cleanup;
@@ -647,7 +647,7 @@
 			le32_to_cpu(BHDR(bs->bh)->h_refcount));
 		if (ext3_xattr_check_block(bs->bh)) {
 			ext3_error(sb, __FUNCTION__,
-				"inode %ld: bad block %d", inode->i_ino,
+				"inode %ld: bad block "E3FSBLK, inode->i_ino,
 				EXT3_I(inode)->i_file_acl);
 			error = -EIO;
 			goto cleanup;
@@ -792,11 +792,12 @@
 			get_bh(new_bh);
 		} else {
 			/* We need to allocate a new block */
-			int goal = le32_to_cpu(
+			ext3_fsblk_t goal = le32_to_cpu(
 					EXT3_SB(sb)->s_es->s_first_data_block) +
-				EXT3_I(inode)->i_block_group *
+				(ext3_fsblk_t)EXT3_I(inode)->i_block_group *
 				EXT3_BLOCKS_PER_GROUP(sb);
-			int block = ext3_new_block(handle, inode, goal, &error);
+			ext3_fsblk_t block = ext3_new_block(handle, inode,
+							goal, &error);
 			if (error)
 				goto cleanup;
 			ea_idebug(inode, "creating block %d", block);
@@ -847,7 +848,7 @@
 
 bad_block:
 	ext3_error(inode->i_sb, __FUNCTION__,
-		   "inode %ld: bad block %d", inode->i_ino,
+		   "inode %ld: bad block "E3FSBLK, inode->i_ino,
 		   EXT3_I(inode)->i_file_acl);
 	goto cleanup;
 
@@ -1076,14 +1077,14 @@
 	bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
 	if (!bh) {
 		ext3_error(inode->i_sb, __FUNCTION__,
-			"inode %ld: block %d read error", inode->i_ino,
+			"inode %ld: block "E3FSBLK" read error", inode->i_ino,
 			EXT3_I(inode)->i_file_acl);
 		goto cleanup;
 	}
 	if (BHDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
 	    BHDR(bh)->h_blocks != cpu_to_le32(1)) {
 		ext3_error(inode->i_sb, __FUNCTION__,
-			"inode %ld: bad block %d", inode->i_ino,
+			"inode %ld: bad block "E3FSBLK, inode->i_ino,
 			EXT3_I(inode)->i_file_acl);
 		goto cleanup;
 	}
@@ -1210,11 +1211,11 @@
 		bh = sb_bread(inode->i_sb, ce->e_block);
 		if (!bh) {
 			ext3_error(inode->i_sb, __FUNCTION__,
-				"inode %ld: block %ld read error",
+				"inode %ld: block %lu read error",
 				inode->i_ino, (unsigned long) ce->e_block);
 		} else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
 				EXT3_XATTR_REFCOUNT_MAX) {
-			ea_idebug(inode, "block %ld refcount %d>=%d",
+			ea_idebug(inode, "block %lu refcount %d>=%d",
 				  (unsigned long) ce->e_block,
 				  le32_to_cpu(BHDR(bh)->h_refcount),
 					  EXT3_XATTR_REFCOUNT_MAX);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index c1ce284..31b7174 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -196,7 +196,7 @@
 	return generic_block_bmap(mapping, block, fat_get_block);
 }
 
-static struct address_space_operations fat_aops = {
+static const struct address_space_operations fat_aops = {
 	.readpage	= fat_readpage,
 	.readpages	= fat_readpages,
 	.writepage	= fat_writepage,
@@ -539,18 +539,18 @@
 	return 0;
 }
 
-static int fat_statfs(struct super_block *sb, struct kstatfs *buf)
+static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb);
 
 	/* If the count of free cluster is still unknown, counts it here. */
 	if (sbi->free_clusters == -1) {
-		int err = fat_count_free_clusters(sb);
+		int err = fat_count_free_clusters(dentry->d_sb);
 		if (err)
 			return err;
 	}
 
-	buf->f_type = sb->s_magic;
+	buf->f_type = dentry->d_sb->s_magic;
 	buf->f_bsize = sbi->cluster_size;
 	buf->f_blocks = sbi->max_cluster - FAT_START_ENT;
 	buf->f_bfree = sbi->free_clusters;
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index 944652e..308f2b6 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -210,4 +210,3 @@
 	return err;
 }
 
-EXPORT_SYMBOL_GPL(fat_sync_bhs);
diff --git a/fs/file_table.c b/fs/file_table.c
index bcea199..506d530 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -300,5 +300,5 @@
 	if (files_stat.max_files < NR_FILE)
 		files_stat.max_files = NR_FILE;
 	files_defer_init();
-	percpu_counter_init(&nr_files);
+	percpu_counter_init(&nr_files, 0);
 } 
diff --git a/fs/freevxfs/vxfs.h b/fs/freevxfs/vxfs.h
index 583bd78..d35979a 100644
--- a/fs/freevxfs/vxfs.h
+++ b/fs/freevxfs/vxfs.h
@@ -159,11 +159,11 @@
  * In core superblock filesystem private data for VxFS.
  */
 struct vxfs_sb_info {
-	struct vxfs_sb		*vsi_raw;	/* raw (on disk) supeblock */
+	struct vxfs_sb		*vsi_raw;	/* raw (on disk) superblock */
 	struct buffer_head	*vsi_bp;	/* buffer for raw superblock*/
 	struct inode		*vsi_fship;	/* fileset header inode */
 	struct inode		*vsi_ilist;	/* inode list inode */
-	struct inode		*vsi_stilist;	/* structual inode list inode */
+	struct inode		*vsi_stilist;	/* structural inode list inode */
 	u_long			vsi_iext;	/* initial inode list */
 	ino_t			vsi_fshino;	/* fileset header inode */
 	daddr_t			vsi_oltext;	/* OLT extent */
diff --git a/fs/freevxfs/vxfs_fshead.c b/fs/freevxfs/vxfs_fshead.c
index 6dee109..78948b4 100644
--- a/fs/freevxfs/vxfs_fshead.c
+++ b/fs/freevxfs/vxfs_fshead.c
@@ -112,7 +112,7 @@
 
 	vip = vxfs_blkiget(sbp, infp->vsi_iext, infp->vsi_fshino);
 	if (!vip) {
-		printk(KERN_ERR "vxfs: unabled to read fsh inode\n");
+		printk(KERN_ERR "vxfs: unable to read fsh inode\n");
 		return -EINVAL;
 	}
 	if (!VXFS_ISFSH(vip)) {
@@ -129,13 +129,13 @@
 
 	infp->vsi_fship = vxfs_get_fake_inode(sbp, vip);
 	if (!infp->vsi_fship) {
-		printk(KERN_ERR "vxfs: unabled to get fsh inode\n");
+		printk(KERN_ERR "vxfs: unable to get fsh inode\n");
 		goto out_free_fship;
 	}
 
 	sfp = vxfs_getfsh(infp->vsi_fship, 0);
 	if (!sfp) {
-		printk(KERN_ERR "vxfs: unabled to get structural fsh\n");
+		printk(KERN_ERR "vxfs: unable to get structural fsh\n");
 		goto out_iput_fship;
 	} 
 
@@ -145,7 +145,7 @@
 
 	pfp = vxfs_getfsh(infp->vsi_fship, 1);
 	if (!pfp) {
-		printk(KERN_ERR "vxfs: unabled to get primary fsh\n");
+		printk(KERN_ERR "vxfs: unable to get primary fsh\n");
 		goto out_free_sfp;
 	}
 
@@ -159,7 +159,7 @@
 
 	infp->vsi_stilist = vxfs_get_fake_inode(sbp, tip);
 	if (!infp->vsi_stilist) {
-		printk(KERN_ERR "vxfs: unabled to get structual list inode\n");
+		printk(KERN_ERR "vxfs: unable to get structural list inode\n");
 		kfree(tip);
 		goto out_free_pfp;
 	}
@@ -174,7 +174,7 @@
 		goto out_iput_stilist;
 	infp->vsi_ilist = vxfs_get_fake_inode(sbp, tip);
 	if (!infp->vsi_ilist) {
-		printk(KERN_ERR "vxfs: unabled to get inode list inode\n");
+		printk(KERN_ERR "vxfs: unable to get inode list inode\n");
 		kfree(tip);
 		goto out_iput_stilist;
 	}
diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
index 6f5df17..4e25f3f 100644
--- a/fs/freevxfs/vxfs_immed.c
+++ b/fs/freevxfs/vxfs_immed.c
@@ -56,7 +56,7 @@
 /*
  * Adress space operations for immed files and directories.
  */
-struct address_space_operations vxfs_immed_aops = {
+const struct address_space_operations vxfs_immed_aops = {
 	.readpage =		vxfs_immed_readpage,
 };
 
diff --git a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
index f544aae..ca6a397 100644
--- a/fs/freevxfs/vxfs_inode.c
+++ b/fs/freevxfs/vxfs_inode.c
@@ -41,8 +41,8 @@
 #include "vxfs_extern.h"
 
 
-extern struct address_space_operations vxfs_aops;
-extern struct address_space_operations vxfs_immed_aops;
+extern const struct address_space_operations vxfs_aops;
+extern const struct address_space_operations vxfs_immed_aops;
 
 extern struct inode_operations vxfs_immed_symlink_iops;
 
@@ -295,7 +295,7 @@
 {
 	struct super_block		*sbp = ip->i_sb;
 	struct vxfs_inode_info		*vip;
-	struct address_space_operations	*aops;
+	const struct address_space_operations	*aops;
 	ino_t				ino = ip->i_ino;
 
 	if (!(vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist)))
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c
index 50aae77..decac62 100644
--- a/fs/freevxfs/vxfs_subr.c
+++ b/fs/freevxfs/vxfs_subr.c
@@ -42,7 +42,7 @@
 static int		vxfs_readpage(struct file *, struct page *);
 static sector_t		vxfs_bmap(struct address_space *, sector_t);
 
-struct address_space_operations vxfs_aops = {
+const struct address_space_operations vxfs_aops = {
 	.readpage =		vxfs_readpage,
 	.bmap =			vxfs_bmap,
 	.sync_page =		block_sync_page,
@@ -71,8 +71,7 @@
 {
 	struct page *			pp;
 
-	pp = read_cache_page(mapping, n,
-			(filler_t*)mapping->a_ops->readpage, NULL);
+	pp = read_mapping_page(mapping, n, NULL);
 
 	if (!IS_ERR(pp)) {
 		wait_on_page_locked(pp);
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c
index b44c916..b74b791 100644
--- a/fs/freevxfs/vxfs_super.c
+++ b/fs/freevxfs/vxfs_super.c
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/vfs.h>
+#include <linux/mount.h>
 
 #include "vxfs.h"
 #include "vxfs_extern.h"
@@ -55,7 +56,7 @@
 
 
 static void		vxfs_put_super(struct super_block *);
-static int		vxfs_statfs(struct super_block *, struct kstatfs *);
+static int		vxfs_statfs(struct dentry *, struct kstatfs *);
 static int		vxfs_remount(struct super_block *, int *, char *);
 
 static struct super_operations vxfs_super_ops = {
@@ -90,12 +91,12 @@
 
 /**
  * vxfs_statfs - get filesystem information
- * @sbp:	VFS superblock
+ * @dentry:	VFS dentry to locate superblock
  * @bufp:	output buffer
  *
  * Description:
  *   vxfs_statfs fills the statfs buffer @bufp with information
- *   about the filesystem described by @sbp.
+ *   about the filesystem described by @dentry.
  *
  * Returns:
  *   Zero.
@@ -107,12 +108,12 @@
  *   This is everything but complete...
  */
 static int
-vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp)
+vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
 {
-	struct vxfs_sb_info		*infp = VXFS_SBI(sbp);
+	struct vxfs_sb_info		*infp = VXFS_SBI(dentry->d_sb);
 
 	bufp->f_type = VXFS_SUPER_MAGIC;
-	bufp->f_bsize = sbp->s_blocksize;
+	bufp->f_bsize = dentry->d_sb->s_blocksize;
 	bufp->f_blocks = infp->vsi_raw->vs_dsize;
 	bufp->f_bfree = infp->vsi_raw->vs_free;
 	bufp->f_bavail = 0;
@@ -241,10 +242,11 @@
 /*
  * The usual module blurb.
  */
-static struct super_block *vxfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int vxfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type vxfs_fs_type = {
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index f3fbe2d..031b27a 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -461,6 +461,8 @@
 {
 	struct writeback_control wbc = {
 		.sync_mode	= wait ? WB_SYNC_ALL : WB_SYNC_HOLD,
+		.range_start	= 0,
+		.range_end	= LLONG_MAX,
 	};
 	unsigned long nr_dirty = read_page_state(nr_dirty);
 	unsigned long nr_unstable = read_page_state(nr_unstable);
@@ -559,6 +561,8 @@
 	struct writeback_control wbc = {
 		.nr_to_write = LONG_MAX,
 		.sync_mode = WB_SYNC_ALL,
+		.range_start = 0,
+		.range_end = LLONG_MAX,
 	};
 
 	if (!mapping_cap_writeback_dirty(inode->i_mapping))
@@ -619,7 +623,6 @@
 	int need_write_inode_now = 0;
 	int err2;
 
-	current->flags |= PF_SYNCWRITE;
 	if (what & OSYNC_DATA)
 		err = filemap_fdatawrite(mapping);
 	if (what & (OSYNC_METADATA|OSYNC_DATA)) {
@@ -632,7 +635,6 @@
 		if (!err)
 			err = err2;
 	}
-	current->flags &= ~PF_SYNCWRITE;
 
 	spin_lock(&inode_lock);
 	if ((inode->i_state & I_DIRTY) &&
diff --git a/fs/fuse/Makefile b/fs/fuse/Makefile
index c3e1f76..7243706 100644
--- a/fs/fuse/Makefile
+++ b/fs/fuse/Makefile
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_FUSE_FS) += fuse.o
 
-fuse-objs := dev.o dir.o file.o inode.o
+fuse-objs := dev.o dir.o file.o inode.o control.o
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
new file mode 100644
index 0000000..a3bce3a
--- /dev/null
+++ b/fs/fuse/control.c
@@ -0,0 +1,218 @@
+/*
+  FUSE: Filesystem in Userspace
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
+
+  This program can be distributed under the terms of the GNU GPL.
+  See the file COPYING.
+*/
+
+#include "fuse_i.h"
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+#define FUSE_CTL_SUPER_MAGIC 0x65735543
+
+/*
+ * This is non-NULL when the single instance of the control filesystem
+ * exists.  Protected by fuse_mutex
+ */
+static struct super_block *fuse_control_sb;
+
+static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
+{
+	struct fuse_conn *fc;
+	mutex_lock(&fuse_mutex);
+	fc = file->f_dentry->d_inode->u.generic_ip;
+	if (fc)
+		fc = fuse_conn_get(fc);
+	mutex_unlock(&fuse_mutex);
+	return fc;
+}
+
+static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
+	if (fc) {
+		fuse_abort_conn(fc);
+		fuse_conn_put(fc);
+	}
+	return count;
+}
+
+static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf,
+				      size_t len, loff_t *ppos)
+{
+	char tmp[32];
+	size_t size;
+
+	if (!*ppos) {
+		struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
+		if (!fc)
+			return 0;
+
+		file->private_data=(void *)(long)atomic_read(&fc->num_waiting);
+		fuse_conn_put(fc);
+	}
+	size = sprintf(tmp, "%ld\n", (long)file->private_data);
+	return simple_read_from_buffer(buf, len, ppos, tmp, size);
+}
+
+static const struct file_operations fuse_ctl_abort_ops = {
+	.open = nonseekable_open,
+	.write = fuse_conn_abort_write,
+};
+
+static const struct file_operations fuse_ctl_waiting_ops = {
+	.open = nonseekable_open,
+	.read = fuse_conn_waiting_read,
+};
+
+static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
+					  struct fuse_conn *fc,
+					  const char *name,
+					  int mode, int nlink,
+					  struct inode_operations *iop,
+					  const struct file_operations *fop)
+{
+	struct dentry *dentry;
+	struct inode *inode;
+
+	BUG_ON(fc->ctl_ndents >= FUSE_CTL_NUM_DENTRIES);
+	dentry = d_alloc_name(parent, name);
+	if (!dentry)
+		return NULL;
+
+	fc->ctl_dentry[fc->ctl_ndents++] = dentry;
+	inode = new_inode(fuse_control_sb);
+	if (!inode)
+		return NULL;
+
+	inode->i_mode = mode;
+	inode->i_uid = fc->user_id;
+	inode->i_gid = fc->group_id;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	/* setting ->i_op to NULL is not allowed */
+	if (iop)
+		inode->i_op = iop;
+	inode->i_fop = fop;
+	inode->i_nlink = nlink;
+	inode->u.generic_ip = fc;
+	d_add(dentry, inode);
+	return dentry;
+}
+
+/*
+ * Add a connection to the control filesystem (if it exists).  Caller
+ * must host fuse_mutex
+ */
+int fuse_ctl_add_conn(struct fuse_conn *fc)
+{
+	struct dentry *parent;
+	char name[32];
+
+	if (!fuse_control_sb)
+		return 0;
+
+	parent = fuse_control_sb->s_root;
+	parent->d_inode->i_nlink++;
+	sprintf(name, "%llu", (unsigned long long) fc->id);
+	parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2,
+				     &simple_dir_inode_operations,
+				     &simple_dir_operations);
+	if (!parent)
+		goto err;
+
+	if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400, 1,
+				NULL, &fuse_ctl_waiting_ops) ||
+	    !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200, 1,
+				 NULL, &fuse_ctl_abort_ops))
+		goto err;
+
+	return 0;
+
+ err:
+	fuse_ctl_remove_conn(fc);
+	return -ENOMEM;
+}
+
+/*
+ * Remove a connection from the control filesystem (if it exists).
+ * Caller must host fuse_mutex
+ */
+void fuse_ctl_remove_conn(struct fuse_conn *fc)
+{
+	int i;
+
+	if (!fuse_control_sb)
+		return;
+
+	for (i = fc->ctl_ndents - 1; i >= 0; i--) {
+		struct dentry *dentry = fc->ctl_dentry[i];
+		dentry->d_inode->u.generic_ip = NULL;
+		d_drop(dentry);
+		dput(dentry);
+	}
+	fuse_control_sb->s_root->d_inode->i_nlink--;
+}
+
+static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
+{
+	struct tree_descr empty_descr = {""};
+	struct fuse_conn *fc;
+	int err;
+
+	err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr);
+	if (err)
+		return err;
+
+	mutex_lock(&fuse_mutex);
+	BUG_ON(fuse_control_sb);
+	fuse_control_sb = sb;
+	list_for_each_entry(fc, &fuse_conn_list, entry) {
+		err = fuse_ctl_add_conn(fc);
+		if (err) {
+			fuse_control_sb = NULL;
+			mutex_unlock(&fuse_mutex);
+			return err;
+		}
+	}
+	mutex_unlock(&fuse_mutex);
+
+	return 0;
+}
+
+static int fuse_ctl_get_sb(struct file_system_type *fs_type, int flags,
+			const char *dev_name, void *raw_data,
+			struct vfsmount *mnt)
+{
+	return get_sb_single(fs_type, flags, raw_data,
+				fuse_ctl_fill_super, mnt);
+}
+
+static void fuse_ctl_kill_sb(struct super_block *sb)
+{
+	mutex_lock(&fuse_mutex);
+	fuse_control_sb = NULL;
+	mutex_unlock(&fuse_mutex);
+
+	kill_litter_super(sb);
+}
+
+static struct file_system_type fuse_ctl_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "fusectl",
+	.get_sb		= fuse_ctl_get_sb,
+	.kill_sb	= fuse_ctl_kill_sb,
+};
+
+int __init fuse_ctl_init(void)
+{
+	return register_filesystem(&fuse_ctl_fs_type);
+}
+
+void fuse_ctl_cleanup(void)
+{
+	unregister_filesystem(&fuse_ctl_fs_type);
+}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 104a62d..1e2006c 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -34,6 +34,7 @@
 {
 	memset(req, 0, sizeof(*req));
 	INIT_LIST_HEAD(&req->list);
+	INIT_LIST_HEAD(&req->intr_entry);
 	init_waitqueue_head(&req->waitq);
 	atomic_set(&req->count, 1);
 }
@@ -64,18 +65,6 @@
 	sigprocmask(SIG_SETMASK, oldset, NULL);
 }
 
-/*
- * Reset request, so that it can be reused
- *
- * The caller must be _very_ careful to make sure, that it is holding
- * the only reference to req
- */
-void fuse_reset_request(struct fuse_req *req)
-{
-	BUG_ON(atomic_read(&req->count) != 1);
-	fuse_request_init(req);
-}
-
 static void __fuse_get_request(struct fuse_req *req)
 {
 	atomic_inc(&req->count);
@@ -88,6 +77,13 @@
 	atomic_dec(&req->count);
 }
 
+static void fuse_req_init_context(struct fuse_req *req)
+{
+	req->in.h.uid = current->fsuid;
+	req->in.h.gid = current->fsgid;
+	req->in.h.pid = current->pid;
+}
+
 struct fuse_req *fuse_get_req(struct fuse_conn *fc)
 {
 	struct fuse_req *req;
@@ -103,14 +99,16 @@
 	if (intr)
 		goto out;
 
+	err = -ENOTCONN;
+	if (!fc->connected)
+		goto out;
+
 	req = fuse_request_alloc();
 	err = -ENOMEM;
 	if (!req)
 		goto out;
 
-	req->in.h.uid = current->fsuid;
-	req->in.h.gid = current->fsgid;
-	req->in.h.pid = current->pid;
+	fuse_req_init_context(req);
 	req->waiting = 1;
 	return req;
 
@@ -119,142 +117,183 @@
 	return ERR_PTR(err);
 }
 
+/*
+ * Return request in fuse_file->reserved_req.  However that may
+ * currently be in use.  If that is the case, wait for it to become
+ * available.
+ */
+static struct fuse_req *get_reserved_req(struct fuse_conn *fc,
+					 struct file *file)
+{
+	struct fuse_req *req = NULL;
+	struct fuse_file *ff = file->private_data;
+
+	do {
+		wait_event(fc->blocked_waitq, ff->reserved_req);
+		spin_lock(&fc->lock);
+		if (ff->reserved_req) {
+			req = ff->reserved_req;
+			ff->reserved_req = NULL;
+			get_file(file);
+			req->stolen_file = file;
+		}
+		spin_unlock(&fc->lock);
+	} while (!req);
+
+	return req;
+}
+
+/*
+ * Put stolen request back into fuse_file->reserved_req
+ */
+static void put_reserved_req(struct fuse_conn *fc, struct fuse_req *req)
+{
+	struct file *file = req->stolen_file;
+	struct fuse_file *ff = file->private_data;
+
+	spin_lock(&fc->lock);
+	fuse_request_init(req);
+	BUG_ON(ff->reserved_req);
+	ff->reserved_req = req;
+	wake_up(&fc->blocked_waitq);
+	spin_unlock(&fc->lock);
+	fput(file);
+}
+
+/*
+ * Gets a requests for a file operation, always succeeds
+ *
+ * This is used for sending the FLUSH request, which must get to
+ * userspace, due to POSIX locks which may need to be unlocked.
+ *
+ * If allocation fails due to OOM, use the reserved request in
+ * fuse_file.
+ *
+ * This is very unlikely to deadlock accidentally, since the
+ * filesystem should not have it's own file open.  If deadlock is
+ * intentional, it can still be broken by "aborting" the filesystem.
+ */
+struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file)
+{
+	struct fuse_req *req;
+
+	atomic_inc(&fc->num_waiting);
+	wait_event(fc->blocked_waitq, !fc->blocked);
+	req = fuse_request_alloc();
+	if (!req)
+		req = get_reserved_req(fc, file);
+
+	fuse_req_init_context(req);
+	req->waiting = 1;
+	return req;
+}
+
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
 	if (atomic_dec_and_test(&req->count)) {
 		if (req->waiting)
 			atomic_dec(&fc->num_waiting);
-		fuse_request_free(req);
-	}
-}
 
-/*
- * Called with sbput_sem held for read (request_end) or write
- * (fuse_put_super).  By the time fuse_put_super() is finished, all
- * inodes belonging to background requests must be released, so the
- * iputs have to be done within the locked region.
- */
-void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req)
-{
-	iput(req->inode);
-	iput(req->inode2);
-	spin_lock(&fc->lock);
-	list_del(&req->bg_entry);
-	if (fc->num_background == FUSE_MAX_BACKGROUND) {
-		fc->blocked = 0;
-		wake_up_all(&fc->blocked_waitq);
+		if (req->stolen_file)
+			put_reserved_req(fc, req);
+		else
+			fuse_request_free(req);
 	}
-	fc->num_background--;
-	spin_unlock(&fc->lock);
 }
 
 /*
  * This function is called when a request is finished.  Either a reply
- * has arrived or it was interrupted (and not yet sent) or some error
+ * has arrived or it was aborted (and not yet sent) or some error
  * occurred during communication with userspace, or the device file
- * was closed.  In case of a background request the reference to the
- * stored objects are released.  The requester thread is woken up (if
- * still waiting), the 'end' callback is called if given, else the
- * reference to the request is released
- *
- * Releasing extra reference for foreground requests must be done
- * within the same locked region as setting state to finished.  This
- * is because fuse_reset_request() may be called after request is
- * finished and it must be the sole possessor.  If request is
- * interrupted and put in the background, it will return with an error
- * and hence never be reset and reused.
+ * was closed.  The requester thread is woken up (if still waiting),
+ * the 'end' callback is called if given, else the reference to the
+ * request is released
  *
  * Called with fc->lock, unlocks it
  */
 static void request_end(struct fuse_conn *fc, struct fuse_req *req)
 {
+	void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
+	req->end = NULL;
 	list_del(&req->list);
+	list_del(&req->intr_entry);
 	req->state = FUSE_REQ_FINISHED;
-	if (!req->background) {
-		spin_unlock(&fc->lock);
-		wake_up(&req->waitq);
-		fuse_put_request(fc, req);
-	} else {
-		void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
-		req->end = NULL;
-		spin_unlock(&fc->lock);
-		down_read(&fc->sbput_sem);
-		if (fc->mounted)
-			fuse_release_background(fc, req);
-		up_read(&fc->sbput_sem);
-
-		/* fput must go outside sbput_sem, otherwise it can deadlock */
-		if (req->file)
-			fput(req->file);
-
-		if (end)
-			end(fc, req);
-		else
-			fuse_put_request(fc, req);
+	if (req->background) {
+		if (fc->num_background == FUSE_MAX_BACKGROUND) {
+			fc->blocked = 0;
+			wake_up_all(&fc->blocked_waitq);
+		}
+		fc->num_background--;
 	}
+	spin_unlock(&fc->lock);
+	dput(req->dentry);
+	mntput(req->vfsmount);
+	if (req->file)
+		fput(req->file);
+	wake_up(&req->waitq);
+	if (end)
+		end(fc, req);
+	else
+		fuse_put_request(fc, req);
 }
 
-/*
- * Unfortunately request interruption not just solves the deadlock
- * problem, it causes problems too.  These stem from the fact, that an
- * interrupted request is continued to be processed in userspace,
- * while all the locks and object references (inode and file) held
- * during the operation are released.
- *
- * To release the locks is exactly why there's a need to interrupt the
- * request, so there's not a lot that can be done about this, except
- * introduce additional locking in userspace.
- *
- * More important is to keep inode and file references until userspace
- * has replied, otherwise FORGET and RELEASE could be sent while the
- * inode/file is still used by the filesystem.
- *
- * For this reason the concept of "background" request is introduced.
- * An interrupted request is backgrounded if it has been already sent
- * to userspace.  Backgrounding involves getting an extra reference to
- * inode(s) or file used in the request, and adding the request to
- * fc->background list.  When a reply is received for a background
- * request, the object references are released, and the request is
- * removed from the list.  If the filesystem is unmounted while there
- * are still background requests, the list is walked and references
- * are released as if a reply was received.
- *
- * There's one more use for a background request.  The RELEASE message is
- * always sent as background, since it doesn't return an error or
- * data.
- */
-static void background_request(struct fuse_conn *fc, struct fuse_req *req)
+static void wait_answer_interruptible(struct fuse_conn *fc,
+				      struct fuse_req *req)
 {
-	req->background = 1;
-	list_add(&req->bg_entry, &fc->background);
-	fc->num_background++;
-	if (fc->num_background == FUSE_MAX_BACKGROUND)
-		fc->blocked = 1;
-	if (req->inode)
-		req->inode = igrab(req->inode);
-	if (req->inode2)
-		req->inode2 = igrab(req->inode2);
-	if (req->file)
-		get_file(req->file);
+	if (signal_pending(current))
+		return;
+
+	spin_unlock(&fc->lock);
+	wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
+	spin_lock(&fc->lock);
+}
+
+static void queue_interrupt(struct fuse_conn *fc, struct fuse_req *req)
+{
+	list_add_tail(&req->intr_entry, &fc->interrupts);
+	wake_up(&fc->waitq);
+	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 }
 
 /* Called with fc->lock held.  Releases, and then reacquires it. */
 static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
 {
-	sigset_t oldset;
+	if (!fc->no_interrupt) {
+		/* Any signal may interrupt this */
+		wait_answer_interruptible(fc, req);
 
-	spin_unlock(&fc->lock);
-	block_sigs(&oldset);
-	wait_event_interruptible(req->waitq, req->state == FUSE_REQ_FINISHED);
-	restore_sigs(&oldset);
-	spin_lock(&fc->lock);
-	if (req->state == FUSE_REQ_FINISHED && !req->interrupted)
-		return;
+		if (req->aborted)
+			goto aborted;
+		if (req->state == FUSE_REQ_FINISHED)
+			return;
 
-	if (!req->interrupted) {
-		req->out.h.error = -EINTR;
 		req->interrupted = 1;
+		if (req->state == FUSE_REQ_SENT)
+			queue_interrupt(fc, req);
 	}
+
+	if (req->force) {
+		spin_unlock(&fc->lock);
+		wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
+		spin_lock(&fc->lock);
+	} else {
+		sigset_t oldset;
+
+		/* Only fatal signals may interrupt this */
+		block_sigs(&oldset);
+		wait_answer_interruptible(fc, req);
+		restore_sigs(&oldset);
+	}
+
+	if (req->aborted)
+		goto aborted;
+	if (req->state == FUSE_REQ_FINISHED)
+ 		return;
+
+	req->out.h.error = -EINTR;
+	req->aborted = 1;
+
+ aborted:
 	if (req->locked) {
 		/* This is uninterruptible sleep, because data is
 		   being copied to/from the buffers of req.  During
@@ -268,8 +307,11 @@
 	if (req->state == FUSE_REQ_PENDING) {
 		list_del(&req->list);
 		__fuse_put_request(req);
-	} else if (req->state == FUSE_REQ_SENT)
-		background_request(fc, req);
+	} else if (req->state == FUSE_REQ_SENT) {
+		spin_unlock(&fc->lock);
+		wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
+		spin_lock(&fc->lock);
+	}
 }
 
 static unsigned len_args(unsigned numargs, struct fuse_arg *args)
@@ -283,13 +325,19 @@
 	return nbytes;
 }
 
+static u64 fuse_get_unique(struct fuse_conn *fc)
+ {
+ 	fc->reqctr++;
+ 	/* zero is special */
+ 	if (fc->reqctr == 0)
+ 		fc->reqctr = 1;
+
+	return fc->reqctr;
+}
+
 static void queue_request(struct fuse_conn *fc, struct fuse_req *req)
 {
-	fc->reqctr++;
-	/* zero is special */
-	if (fc->reqctr == 0)
-		fc->reqctr = 1;
-	req->in.h.unique = fc->reqctr;
+	req->in.h.unique = fuse_get_unique(fc);
 	req->in.h.len = sizeof(struct fuse_in_header) +
 		len_args(req->in.numargs, (struct fuse_arg *) req->in.args);
 	list_add_tail(&req->list, &fc->pending);
@@ -302,9 +350,6 @@
 	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 }
 
-/*
- * This can only be interrupted by a SIGKILL
- */
 void request_send(struct fuse_conn *fc, struct fuse_req *req)
 {
 	req->isreply = 1;
@@ -327,8 +372,12 @@
 static void request_send_nowait(struct fuse_conn *fc, struct fuse_req *req)
 {
 	spin_lock(&fc->lock);
-	background_request(fc, req);
 	if (fc->connected) {
+		req->background = 1;
+		fc->num_background++;
+		if (fc->num_background == FUSE_MAX_BACKGROUND)
+			fc->blocked = 1;
+
 		queue_request(fc, req);
 		spin_unlock(&fc->lock);
 	} else {
@@ -352,14 +401,14 @@
 /*
  * Lock the request.  Up to the next unlock_request() there mustn't be
  * anything that could cause a page-fault.  If the request was already
- * interrupted bail out.
+ * aborted bail out.
  */
 static int lock_request(struct fuse_conn *fc, struct fuse_req *req)
 {
 	int err = 0;
 	if (req) {
 		spin_lock(&fc->lock);
-		if (req->interrupted)
+		if (req->aborted)
 			err = -ENOENT;
 		else
 			req->locked = 1;
@@ -369,7 +418,7 @@
 }
 
 /*
- * Unlock request.  If it was interrupted during being locked, the
+ * Unlock request.  If it was aborted during being locked, the
  * requester thread is currently waiting for it to be unlocked, so
  * wake it up.
  */
@@ -378,7 +427,7 @@
 	if (req) {
 		spin_lock(&fc->lock);
 		req->locked = 0;
-		if (req->interrupted)
+		if (req->aborted)
 			wake_up(&req->waitq);
 		spin_unlock(&fc->lock);
 	}
@@ -557,13 +606,18 @@
 	return err;
 }
 
+static int request_pending(struct fuse_conn *fc)
+{
+	return !list_empty(&fc->pending) || !list_empty(&fc->interrupts);
+}
+
 /* Wait until a request is available on the pending list */
 static void request_wait(struct fuse_conn *fc)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
 	add_wait_queue_exclusive(&fc->waitq, &wait);
-	while (fc->connected && list_empty(&fc->pending)) {
+	while (fc->connected && !request_pending(fc)) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (signal_pending(current))
 			break;
@@ -577,11 +631,50 @@
 }
 
 /*
+ * Transfer an interrupt request to userspace
+ *
+ * Unlike other requests this is assembled on demand, without a need
+ * to allocate a separate fuse_req structure.
+ *
+ * Called with fc->lock held, releases it
+ */
+static int fuse_read_interrupt(struct fuse_conn *fc, struct fuse_req *req,
+			       const struct iovec *iov, unsigned long nr_segs)
+{
+	struct fuse_copy_state cs;
+	struct fuse_in_header ih;
+	struct fuse_interrupt_in arg;
+	unsigned reqsize = sizeof(ih) + sizeof(arg);
+	int err;
+
+	list_del_init(&req->intr_entry);
+	req->intr_unique = fuse_get_unique(fc);
+	memset(&ih, 0, sizeof(ih));
+	memset(&arg, 0, sizeof(arg));
+	ih.len = reqsize;
+	ih.opcode = FUSE_INTERRUPT;
+	ih.unique = req->intr_unique;
+	arg.unique = req->in.h.unique;
+
+	spin_unlock(&fc->lock);
+	if (iov_length(iov, nr_segs) < reqsize)
+		return -EINVAL;
+
+	fuse_copy_init(&cs, fc, 1, NULL, iov, nr_segs);
+	err = fuse_copy_one(&cs, &ih, sizeof(ih));
+	if (!err)
+		err = fuse_copy_one(&cs, &arg, sizeof(arg));
+	fuse_copy_finish(&cs);
+
+	return err ? err : reqsize;
+}
+
+/*
  * Read a single request into the userspace filesystem's buffer.  This
  * function waits until a request is available, then removes it from
  * the pending list and copies request data to userspace buffer.  If
- * no reply is needed (FORGET) or request has been interrupted or
- * there was an error during the copying then it's finished by calling
+ * no reply is needed (FORGET) or request has been aborted or there
+ * was an error during the copying then it's finished by calling
  * request_end().  Otherwise add it to the processing list, and set
  * the 'sent' flag.
  */
@@ -601,7 +694,7 @@
 	spin_lock(&fc->lock);
 	err = -EAGAIN;
 	if ((file->f_flags & O_NONBLOCK) && fc->connected &&
-	    list_empty(&fc->pending))
+	    !request_pending(fc))
 		goto err_unlock;
 
 	request_wait(fc);
@@ -609,9 +702,15 @@
 	if (!fc->connected)
 		goto err_unlock;
 	err = -ERESTARTSYS;
-	if (list_empty(&fc->pending))
+	if (!request_pending(fc))
 		goto err_unlock;
 
+	if (!list_empty(&fc->interrupts)) {
+		req = list_entry(fc->interrupts.next, struct fuse_req,
+				 intr_entry);
+		return fuse_read_interrupt(fc, req, iov, nr_segs);
+	}
+
 	req = list_entry(fc->pending.next, struct fuse_req, list);
 	req->state = FUSE_REQ_READING;
 	list_move(&req->list, &fc->io);
@@ -636,10 +735,10 @@
 	fuse_copy_finish(&cs);
 	spin_lock(&fc->lock);
 	req->locked = 0;
-	if (!err && req->interrupted)
+	if (!err && req->aborted)
 		err = -ENOENT;
 	if (err) {
-		if (!req->interrupted)
+		if (!req->aborted)
 			req->out.h.error = -EIO;
 		request_end(fc, req);
 		return err;
@@ -649,6 +748,8 @@
 	else {
 		req->state = FUSE_REQ_SENT;
 		list_move_tail(&req->list, &fc->processing);
+		if (req->interrupted)
+			queue_interrupt(fc, req);
 		spin_unlock(&fc->lock);
 	}
 	return reqsize;
@@ -675,7 +776,7 @@
 	list_for_each(entry, &fc->processing) {
 		struct fuse_req *req;
 		req = list_entry(entry, struct fuse_req, list);
-		if (req->in.h.unique == unique)
+		if (req->in.h.unique == unique || req->intr_unique == unique)
 			return req;
 	}
 	return NULL;
@@ -741,17 +842,33 @@
 		goto err_unlock;
 
 	req = request_find(fc, oh.unique);
-	err = -EINVAL;
 	if (!req)
 		goto err_unlock;
 
-	if (req->interrupted) {
+	if (req->aborted) {
 		spin_unlock(&fc->lock);
 		fuse_copy_finish(&cs);
 		spin_lock(&fc->lock);
 		request_end(fc, req);
 		return -ENOENT;
 	}
+	/* Is it an interrupt reply? */
+	if (req->intr_unique == oh.unique) {
+		err = -EINVAL;
+		if (nbytes != sizeof(struct fuse_out_header))
+			goto err_unlock;
+
+		if (oh.error == -ENOSYS)
+			fc->no_interrupt = 1;
+		else if (oh.error == -EAGAIN)
+			queue_interrupt(fc, req);
+
+		spin_unlock(&fc->lock);
+		fuse_copy_finish(&cs);
+		return nbytes;
+	}
+
+	req->state = FUSE_REQ_WRITING;
 	list_move(&req->list, &fc->io);
 	req->out.h = oh;
 	req->locked = 1;
@@ -764,9 +881,9 @@
 	spin_lock(&fc->lock);
 	req->locked = 0;
 	if (!err) {
-		if (req->interrupted)
+		if (req->aborted)
 			err = -ENOENT;
-	} else if (!req->interrupted)
+	} else if (!req->aborted)
 		req->out.h.error = -EIO;
 	request_end(fc, req);
 
@@ -800,7 +917,7 @@
 	spin_lock(&fc->lock);
 	if (!fc->connected)
 		mask = POLLERR;
-	else if (!list_empty(&fc->pending))
+	else if (request_pending(fc))
 		mask |= POLLIN | POLLRDNORM;
 	spin_unlock(&fc->lock);
 
@@ -826,7 +943,7 @@
 /*
  * Abort requests under I/O
  *
- * The requests are set to interrupted and finished, and the request
+ * The requests are set to aborted and finished, and the request
  * waiter is woken up.  This will make request_wait_answer() wait
  * until the request is unlocked and then return.
  *
@@ -841,7 +958,7 @@
 			list_entry(fc->io.next, struct fuse_req, list);
 		void (*end) (struct fuse_conn *, struct fuse_req *) = req->end;
 
-		req->interrupted = 1;
+		req->aborted = 1;
 		req->out.h.error = -ECONNABORTED;
 		req->state = FUSE_REQ_FINISHED;
 		list_del_init(&req->list);
@@ -874,19 +991,20 @@
  * onto the pending list is prevented by req->connected being false.
  *
  * Progression of requests under I/O to the processing list is
- * prevented by the req->interrupted flag being true for these
- * requests.  For this reason requests on the io list must be aborted
- * first.
+ * prevented by the req->aborted flag being true for these requests.
+ * For this reason requests on the io list must be aborted first.
  */
 void fuse_abort_conn(struct fuse_conn *fc)
 {
 	spin_lock(&fc->lock);
 	if (fc->connected) {
 		fc->connected = 0;
+		fc->blocked = 0;
 		end_io_requests(fc);
 		end_requests(fc, &fc->pending);
 		end_requests(fc, &fc->processing);
 		wake_up_all(&fc->waitq);
+		wake_up_all(&fc->blocked_waitq);
 		kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 	}
 	spin_unlock(&fc->lock);
@@ -902,7 +1020,7 @@
 		end_requests(fc, &fc->processing);
 		spin_unlock(&fc->lock);
 		fasync_helper(-1, file, 0, &fc->fasync);
-		kobject_put(&fc->kobj);
+		fuse_conn_put(fc);
 	}
 
 	return 0;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 8d7546e..72a74cd 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1,6 +1,6 @@
 /*
   FUSE: Filesystem in Userspace
-  Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+  Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
   This program can be distributed under the terms of the GNU GPL.
   See the file COPYING.
@@ -79,7 +79,6 @@
 {
 	req->in.h.opcode = FUSE_LOOKUP;
 	req->in.h.nodeid = get_node_id(dir);
-	req->inode = dir;
 	req->in.numargs = 1;
 	req->in.args[0].size = entry->d_name.len + 1;
 	req->in.args[0].value = entry->d_name.name;
@@ -225,6 +224,20 @@
 }
 
 /*
+ * Synchronous release for the case when something goes wrong in CREATE_OPEN
+ */
+static void fuse_sync_release(struct fuse_conn *fc, struct fuse_file *ff,
+			      u64 nodeid, int flags)
+{
+	struct fuse_req *req;
+
+	req = fuse_release_fill(ff, nodeid, flags, FUSE_RELEASE);
+	req->force = 1;
+	request_send(fc, req);
+	fuse_put_request(fc, req);
+}
+
+/*
  * Atomic create+open operation
  *
  * If the filesystem doesn't support this, then fall back to separate
@@ -237,6 +250,7 @@
 	struct inode *inode;
 	struct fuse_conn *fc = get_fuse_conn(dir);
 	struct fuse_req *req;
+	struct fuse_req *forget_req;
 	struct fuse_open_in inarg;
 	struct fuse_open_out outopen;
 	struct fuse_entry_out outentry;
@@ -247,9 +261,14 @@
 	if (fc->no_create)
 		return -ENOSYS;
 
+	forget_req = fuse_get_req(fc);
+	if (IS_ERR(forget_req))
+		return PTR_ERR(forget_req);
+
 	req = fuse_get_req(fc);
+	err = PTR_ERR(req);
 	if (IS_ERR(req))
-		return PTR_ERR(req);
+		goto out_put_forget_req;
 
 	err = -ENOMEM;
 	ff = fuse_file_alloc();
@@ -262,7 +281,6 @@
 	inarg.mode = mode;
 	req->in.h.opcode = FUSE_CREATE;
 	req->in.h.nodeid = get_node_id(dir);
-	req->inode = dir;
 	req->in.numargs = 2;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -285,25 +303,23 @@
 	if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
 		goto out_free_ff;
 
+	fuse_put_request(fc, req);
 	inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
 			  &outentry.attr);
-	err = -ENOMEM;
 	if (!inode) {
 		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
 		ff->fh = outopen.fh;
-		/* Special release, with inode = NULL, this will
-		   trigger a 'forget' request when the release is
-		   complete */
-		fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0);
-		goto out_put_request;
+		fuse_sync_release(fc, ff, outentry.nodeid, flags);
+		fuse_send_forget(fc, forget_req, outentry.nodeid, 1);
+		return -ENOMEM;
 	}
-	fuse_put_request(fc, req);
+	fuse_put_request(fc, forget_req);
 	d_instantiate(entry, inode);
 	fuse_change_timeout(entry, &outentry);
 	file = lookup_instantiate_filp(nd, entry, generic_file_open);
 	if (IS_ERR(file)) {
 		ff->fh = outopen.fh;
-		fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0);
+		fuse_sync_release(fc, ff, outentry.nodeid, flags);
 		return PTR_ERR(file);
 	}
 	fuse_finish_open(inode, file, ff, &outopen);
@@ -313,6 +329,8 @@
 	fuse_file_free(ff);
  out_put_request:
 	fuse_put_request(fc, req);
+ out_put_forget_req:
+	fuse_put_request(fc, forget_req);
 	return err;
 }
 
@@ -328,7 +346,6 @@
 	int err;
 
 	req->in.h.nodeid = get_node_id(dir);
-	req->inode = dir;
 	req->out.numargs = 1;
 	req->out.args[0].size = sizeof(outarg);
 	req->out.args[0].value = &outarg;
@@ -448,7 +465,6 @@
 
 	req->in.h.opcode = FUSE_UNLINK;
 	req->in.h.nodeid = get_node_id(dir);
-	req->inode = dir;
 	req->in.numargs = 1;
 	req->in.args[0].size = entry->d_name.len + 1;
 	req->in.args[0].value = entry->d_name.name;
@@ -480,7 +496,6 @@
 
 	req->in.h.opcode = FUSE_RMDIR;
 	req->in.h.nodeid = get_node_id(dir);
-	req->inode = dir;
 	req->in.numargs = 1;
 	req->in.args[0].size = entry->d_name.len + 1;
 	req->in.args[0].value = entry->d_name.name;
@@ -510,8 +525,6 @@
 	inarg.newdir = get_node_id(newdir);
 	req->in.h.opcode = FUSE_RENAME;
 	req->in.h.nodeid = get_node_id(olddir);
-	req->inode = olddir;
-	req->inode2 = newdir;
 	req->in.numargs = 3;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -558,7 +571,6 @@
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.oldnodeid = get_node_id(inode);
 	req->in.h.opcode = FUSE_LINK;
-	req->inode2 = inode;
 	req->in.numargs = 2;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -587,7 +599,6 @@
 
 	req->in.h.opcode = FUSE_GETATTR;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->out.numargs = 1;
 	req->out.args[0].size = sizeof(arg);
 	req->out.args[0].value = &arg;
@@ -679,7 +690,6 @@
 	inarg.mask = mask;
 	req->in.h.opcode = FUSE_ACCESS;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -820,7 +830,6 @@
 	}
 	req->in.h.opcode = FUSE_READLINK;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->out.argvar = 1;
 	req->out.numargs = 1;
 	req->out.args[0].size = PAGE_SIZE - 1;
@@ -939,7 +948,6 @@
 	iattr_to_fattr(attr, &inarg);
 	req->in.h.opcode = FUSE_SETATTR;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -1002,7 +1010,6 @@
 	inarg.flags = flags;
 	req->in.h.opcode = FUSE_SETXATTR;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->in.numargs = 3;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -1041,7 +1048,6 @@
 	inarg.size = size;
 	req->in.h.opcode = FUSE_GETXATTR;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->in.numargs = 2;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -1091,7 +1097,6 @@
 	inarg.size = size;
 	req->in.h.opcode = FUSE_LISTXATTR;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -1135,7 +1140,6 @@
 
 	req->in.h.opcode = FUSE_REMOVEXATTR;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->in.numargs = 1;
 	req->in.args[0].size = strlen(name) + 1;
 	req->in.args[0].value = name;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index fc342cf..63614ed 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -30,7 +30,6 @@
 	inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 	req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -49,8 +48,8 @@
 	struct fuse_file *ff;
 	ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
 	if (ff) {
-		ff->release_req = fuse_request_alloc();
-		if (!ff->release_req) {
+		ff->reserved_req = fuse_request_alloc();
+		if (!ff->reserved_req) {
 			kfree(ff);
 			ff = NULL;
 		}
@@ -60,7 +59,7 @@
 
 void fuse_file_free(struct fuse_file *ff)
 {
-	fuse_request_free(ff->release_req);
+	fuse_request_free(ff->reserved_req);
 	kfree(ff);
 }
 
@@ -113,37 +112,22 @@
 	return err;
 }
 
-/* Special case for failed iget in CREATE */
-static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
+struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
+				   int opcode)
 {
-	/* If called from end_io_requests(), req has more than one
-	   reference and fuse_reset_request() cannot work */
-	if (fc->connected) {
-		u64 nodeid = req->in.h.nodeid;
-		fuse_reset_request(req);
-		fuse_send_forget(fc, req, nodeid, 1);
-	} else
-		fuse_put_request(fc, req);
-}
-
-void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
-		       u64 nodeid, struct inode *inode, int flags, int isdir)
-{
-	struct fuse_req * req = ff->release_req;
+	struct fuse_req *req = ff->reserved_req;
 	struct fuse_release_in *inarg = &req->misc.release_in;
 
 	inarg->fh = ff->fh;
 	inarg->flags = flags;
-	req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
+	req->in.h.opcode = opcode;
 	req->in.h.nodeid = nodeid;
-	req->inode = inode;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(struct fuse_release_in);
 	req->in.args[0].value = inarg;
-	request_send_background(fc, req);
-	if (!inode)
-		req->end = fuse_release_end;
 	kfree(ff);
+
+	return req;
 }
 
 int fuse_release_common(struct inode *inode, struct file *file, int isdir)
@@ -151,8 +135,15 @@
 	struct fuse_file *ff = file->private_data;
 	if (ff) {
 		struct fuse_conn *fc = get_fuse_conn(inode);
-		u64 nodeid = get_node_id(inode);
-		fuse_send_release(fc, ff, nodeid, inode, file->f_flags, isdir);
+		struct fuse_req *req;
+
+		req = fuse_release_fill(ff, get_node_id(inode), file->f_flags,
+					isdir ? FUSE_RELEASEDIR : FUSE_RELEASE);
+
+		/* Hold vfsmount and dentry until release is finished */
+		req->vfsmount = mntget(file->f_vfsmnt);
+		req->dentry = dget(file->f_dentry);
+		request_send_background(fc, req);
 	}
 
 	/* Return value is ignored by VFS */
@@ -169,7 +160,29 @@
 	return fuse_release_common(inode, file, 0);
 }
 
-static int fuse_flush(struct file *file)
+/*
+ * Scramble the ID space with XTEA, so that the value of the files_struct
+ * pointer is not exposed to userspace.
+ */
+static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
+{
+	u32 *k = fc->scramble_key;
+	u64 v = (unsigned long) id;
+	u32 v0 = v;
+	u32 v1 = v >> 32;
+	u32 sum = 0;
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
+		sum += 0x9E3779B9;
+		v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
+	}
+
+	return (u64) v0 + ((u64) v1 << 32);
+}
+
+static int fuse_flush(struct file *file, fl_owner_t id)
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct fuse_conn *fc = get_fuse_conn(inode);
@@ -184,19 +197,16 @@
 	if (fc->no_flush)
 		return 0;
 
-	req = fuse_get_req(fc);
-	if (IS_ERR(req))
-		return PTR_ERR(req);
-
+	req = fuse_get_req_nofail(fc, file);
 	memset(&inarg, 0, sizeof(inarg));
 	inarg.fh = ff->fh;
+	inarg.lock_owner = fuse_lock_owner_id(fc, id);
 	req->in.h.opcode = FUSE_FLUSH;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
-	req->file = file;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
+	req->force = 1;
 	request_send(fc, req);
 	err = req->out.h.error;
 	fuse_put_request(fc, req);
@@ -232,8 +242,6 @@
 	inarg.fsync_flags = datasync ? 1 : 0;
 	req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
-	req->file = file;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(inarg);
 	req->in.args[0].value = &inarg;
@@ -266,8 +274,6 @@
 	inarg->size = count;
 	req->in.h.opcode = opcode;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
-	req->file = file;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(struct fuse_read_in);
 	req->in.args[0].value = inarg;
@@ -342,6 +348,8 @@
 	req->out.page_zeroing = 1;
 	fuse_read_fill(req, file, inode, pos, count, FUSE_READ);
 	if (fc->async_read) {
+		get_file(file);
+		req->file = file;
 		req->end = fuse_readpages_end;
 		request_send_background(fc, req);
 	} else {
@@ -420,8 +428,6 @@
 	inarg.size = count;
 	req->in.h.opcode = FUSE_WRITE;
 	req->in.h.nodeid = get_node_id(inode);
-	req->inode = inode;
-	req->file = file;
 	req->in.argpages = 1;
 	req->in.numargs = 2;
 	req->in.args[0].size = sizeof(struct fuse_write_in);
@@ -619,6 +625,126 @@
 	return 0;
 }
 
+static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
+				  struct file_lock *fl)
+{
+	switch (ffl->type) {
+	case F_UNLCK:
+		break;
+
+	case F_RDLCK:
+	case F_WRLCK:
+		if (ffl->start > OFFSET_MAX || ffl->end > OFFSET_MAX ||
+		    ffl->end < ffl->start)
+			return -EIO;
+
+		fl->fl_start = ffl->start;
+		fl->fl_end = ffl->end;
+		fl->fl_pid = ffl->pid;
+		break;
+
+	default:
+		return -EIO;
+	}
+	fl->fl_type = ffl->type;
+	return 0;
+}
+
+static void fuse_lk_fill(struct fuse_req *req, struct file *file,
+			 const struct file_lock *fl, int opcode, pid_t pid)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_file *ff = file->private_data;
+	struct fuse_lk_in *arg = &req->misc.lk_in;
+
+	arg->fh = ff->fh;
+	arg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
+	arg->lk.start = fl->fl_start;
+	arg->lk.end = fl->fl_end;
+	arg->lk.type = fl->fl_type;
+	arg->lk.pid = pid;
+	req->in.h.opcode = opcode;
+	req->in.h.nodeid = get_node_id(inode);
+	req->in.numargs = 1;
+	req->in.args[0].size = sizeof(*arg);
+	req->in.args[0].value = arg;
+}
+
+static int fuse_getlk(struct file *file, struct file_lock *fl)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_req *req;
+	struct fuse_lk_out outarg;
+	int err;
+
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
+
+	fuse_lk_fill(req, file, fl, FUSE_GETLK, 0);
+	req->out.numargs = 1;
+	req->out.args[0].size = sizeof(outarg);
+	req->out.args[0].value = &outarg;
+	request_send(fc, req);
+	err = req->out.h.error;
+	fuse_put_request(fc, req);
+	if (!err)
+		err = convert_fuse_file_lock(&outarg.lk, fl);
+
+	return err;
+}
+
+static int fuse_setlk(struct file *file, struct file_lock *fl)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	struct fuse_req *req;
+	int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
+	pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
+	int err;
+
+	/* Unlock on close is handled by the flush method */
+	if (fl->fl_flags & FL_CLOSE)
+		return 0;
+
+	req = fuse_get_req(fc);
+	if (IS_ERR(req))
+		return PTR_ERR(req);
+
+	fuse_lk_fill(req, file, fl, opcode, pid);
+	request_send(fc, req);
+	err = req->out.h.error;
+	/* locking is restartable */
+	if (err == -EINTR)
+		err = -ERESTARTSYS;
+	fuse_put_request(fc, req);
+	return err;
+}
+
+static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct fuse_conn *fc = get_fuse_conn(inode);
+	int err;
+
+	if (cmd == F_GETLK) {
+		if (fc->no_lock) {
+			if (!posix_test_lock(file, fl, fl))
+				fl->fl_type = F_UNLCK;
+			err = 0;
+		} else
+			err = fuse_getlk(file, fl);
+	} else {
+		if (fc->no_lock)
+			err = posix_lock_file_wait(file, fl);
+		else
+			err = fuse_setlk(file, fl);
+	}
+	return err;
+}
+
 static const struct file_operations fuse_file_operations = {
 	.llseek		= generic_file_llseek,
 	.read		= generic_file_read,
@@ -628,6 +754,7 @@
 	.flush		= fuse_flush,
 	.release	= fuse_release,
 	.fsync		= fuse_fsync,
+	.lock		= fuse_file_lock,
 	.sendfile	= generic_file_sendfile,
 };
 
@@ -639,10 +766,11 @@
 	.flush		= fuse_flush,
 	.release	= fuse_release,
 	.fsync		= fuse_fsync,
+	.lock		= fuse_file_lock,
 	/* no mmap and sendfile */
 };
 
-static struct address_space_operations fuse_file_aops  = {
+static const struct address_space_operations fuse_file_aops  = {
 	.readpage	= fuse_readpage,
 	.prepare_write	= fuse_prepare_write,
 	.commit_write	= fuse_commit_write,
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0474202..0dbf966 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -8,12 +8,13 @@
 
 #include <linux/fuse.h>
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/wait.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/backing-dev.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 /** Max number of pages that can be used in a single read request */
 #define FUSE_MAX_PAGES_PER_REQ 32
@@ -24,6 +25,9 @@
 /** It could be as large as PATH_MAX, but would that have any uses? */
 #define FUSE_NAME_MAX 1024
 
+/** Number of dentries for each connection in the control filesystem */
+#define FUSE_CTL_NUM_DENTRIES 3
+
 /** If the FUSE_DEFAULT_PERMISSIONS flag is given, the filesystem
     module will check permissions based on the file mode.  Otherwise no
     permission checking is done in the kernel */
@@ -33,6 +37,11 @@
     doing the mount will be allowed to access the filesystem */
 #define FUSE_ALLOW_OTHER         (1 << 1)
 
+/** List of active connections */
+extern struct list_head fuse_conn_list;
+
+/** Global mutex protecting fuse_conn_list and the control filesystem */
+extern struct mutex fuse_mutex;
 
 /** FUSE inode */
 struct fuse_inode {
@@ -56,7 +65,7 @@
 /** FUSE specific file data */
 struct fuse_file {
 	/** Request reserved for flush and release */
-	struct fuse_req *release_req;
+	struct fuse_req *reserved_req;
 
 	/** File handle used by userspace */
 	u64 fh;
@@ -122,6 +131,7 @@
 	FUSE_REQ_PENDING,
 	FUSE_REQ_READING,
 	FUSE_REQ_SENT,
+	FUSE_REQ_WRITING,
 	FUSE_REQ_FINISHED
 };
 
@@ -135,12 +145,15 @@
 	    fuse_conn */
 	struct list_head list;
 
-	/** Entry on the background list */
-	struct list_head bg_entry;
+	/** Entry on the interrupts list  */
+	struct list_head intr_entry;
 
 	/** refcount */
 	atomic_t count;
 
+	/** Unique ID for the interrupt request */
+	u64 intr_unique;
+
 	/*
 	 * The following bitfields are either set once before the
 	 * request is queued or setting/clearing them is protected by
@@ -150,12 +163,18 @@
 	/** True if the request has reply */
 	unsigned isreply:1;
 
-	/** The request was interrupted */
-	unsigned interrupted:1;
+	/** Force sending of the request even if interrupted */
+	unsigned force:1;
+
+	/** The request was aborted */
+	unsigned aborted:1;
 
 	/** Request is sent in the background */
 	unsigned background:1;
 
+	/** The request has been interrupted */
+	unsigned interrupted:1;
+
 	/** Data is being copied to/from the request */
 	unsigned locked:1;
 
@@ -181,6 +200,7 @@
 		struct fuse_init_in init_in;
 		struct fuse_init_out init_out;
 		struct fuse_read_in read_in;
+		struct fuse_lk_in lk_in;
 	} misc;
 
 	/** page vector */
@@ -192,17 +212,20 @@
 	/** offset of data on first page */
 	unsigned page_offset;
 
-	/** Inode used in the request */
-	struct inode *inode;
-
-	/** Second inode used in the request (or NULL) */
-	struct inode *inode2;
-
 	/** File used in the request (or NULL) */
 	struct file *file;
 
+	/** vfsmount used in release */
+	struct vfsmount *vfsmount;
+
+	/** dentry used in release */
+	struct dentry *dentry;
+
 	/** Request completion callback */
 	void (*end)(struct fuse_conn *, struct fuse_req *);
+
+	/** Request is stolen from fuse_file->reserved_req */
+	struct file *stolen_file;
 };
 
 /**
@@ -216,6 +239,9 @@
 	/** Lock protecting accessess to  members of this structure */
 	spinlock_t lock;
 
+	/** Refcount */
+	atomic_t count;
+
 	/** The user id for this mount */
 	uid_t user_id;
 
@@ -243,13 +269,12 @@
 	/** The list of requests under I/O */
 	struct list_head io;
 
-	/** Requests put in the background (RELEASE or any other
-	    interrupted request) */
-	struct list_head background;
-
 	/** Number of requests currently in the background */
 	unsigned num_background;
 
+	/** Pending interrupts */
+	struct list_head interrupts;
+
 	/** Flag indicating if connection is blocked.  This will be
 	    the case before the INIT reply is received, and if there
 	    are too many outstading backgrounds requests */
@@ -258,15 +283,9 @@
 	/** waitq for blocked connection */
 	wait_queue_head_t blocked_waitq;
 
-	/** RW semaphore for exclusion with fuse_put_super() */
-	struct rw_semaphore sbput_sem;
-
 	/** The next unique request id */
 	u64 reqctr;
 
-	/** Mount is active */
-	unsigned mounted;
-
 	/** Connection established, cleared on umount, connection
 	    abort and device release */
 	unsigned connected;
@@ -305,12 +324,18 @@
 	/** Is removexattr not implemented by fs? */
 	unsigned no_removexattr : 1;
 
+	/** Are file locking primitives not implemented by fs? */
+	unsigned no_lock : 1;
+
 	/** Is access not implemented by fs? */
 	unsigned no_access : 1;
 
 	/** Is create not implemented by fs? */
 	unsigned no_create : 1;
 
+	/** Is interrupt not implemented by fs? */
+	unsigned no_interrupt : 1;
+
 	/** The number of requests waiting for completion */
 	atomic_t num_waiting;
 
@@ -320,11 +345,23 @@
 	/** Backing dev info */
 	struct backing_dev_info bdi;
 
-	/** kobject */
-	struct kobject kobj;
+	/** Entry on the fuse_conn_list */
+	struct list_head entry;
+
+	/** Unique ID */
+	u64 id;
+
+	/** Dentries in the control filesystem */
+	struct dentry *ctl_dentry[FUSE_CTL_NUM_DENTRIES];
+
+	/** number of dentries used in the above array */
+	int ctl_ndents;
 
 	/** O_ASYNC requests */
 	struct fasync_struct *fasync;
+
+	/** Key for lock owner ID scrambling */
+	u32 scramble_key[4];
 };
 
 static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
@@ -337,11 +374,6 @@
 	return get_fuse_conn_super(inode->i_sb);
 }
 
-static inline struct fuse_conn *get_fuse_conn_kobj(struct kobject *obj)
-{
-	return container_of(obj, struct fuse_conn, kobj);
-}
-
 static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
 {
 	return container_of(inode, struct fuse_inode, inode);
@@ -383,12 +415,9 @@
 void fuse_finish_open(struct inode *inode, struct file *file,
 		      struct fuse_file *ff, struct fuse_open_out *outarg);
 
-/**
- * Send a RELEASE request
- */
-void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff,
-		       u64 nodeid, struct inode *inode, int flags, int isdir);
-
+/** */
+struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
+				   int opcode);
 /**
  * Send RELEASE or RELEASEDIR request
  */
@@ -435,6 +464,9 @@
  */
 void fuse_dev_cleanup(void);
 
+int fuse_ctl_init(void);
+void fuse_ctl_cleanup(void);
+
 /**
  * Allocate a request
  */
@@ -446,16 +478,16 @@
 void fuse_request_free(struct fuse_req *req);
 
 /**
- * Reinitialize a request, the preallocated flag is left unmodified
- */
-void fuse_reset_request(struct fuse_req *req);
-
-/**
- * Reserve a preallocated request
+ * Get a request, may fail with -ENOMEM
  */
 struct fuse_req *fuse_get_req(struct fuse_conn *fc);
 
 /**
+ * Gets a requests for a file operation, always succeeds
+ */
+struct fuse_req *fuse_get_req_nofail(struct fuse_conn *fc, struct file *file);
+
+/**
  * Decrement reference count of a request.  If count goes to zero free
  * the request.
  */
@@ -476,11 +508,6 @@
  */
 void request_send_background(struct fuse_conn *fc, struct fuse_req *req);
 
-/**
- * Release inodes and file associated with background request
- */
-void fuse_release_background(struct fuse_conn *fc, struct fuse_req *req);
-
 /* Abort all requests */
 void fuse_abort_conn(struct fuse_conn *fc);
 
@@ -493,3 +520,23 @@
  * Invalidate inode attributes
  */
 void fuse_invalidate_attr(struct inode *inode);
+
+/**
+ * Acquire reference to fuse_conn
+ */
+struct fuse_conn *fuse_conn_get(struct fuse_conn *fc);
+
+/**
+ * Release reference to fuse_conn
+ */
+void fuse_conn_put(struct fuse_conn *fc);
+
+/**
+ * Add connection to control filesystem
+ */
+int fuse_ctl_add_conn(struct fuse_conn *fc);
+
+/**
+ * Remove connection from control filesystem
+ */
+void fuse_ctl_remove_conn(struct fuse_conn *fc);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 7627022..dcaaabd 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -11,25 +11,20 @@
 #include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/file.h>
-#include <linux/mount.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/parser.h>
 #include <linux/statfs.h>
+#include <linux/random.h>
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
 MODULE_LICENSE("GPL");
 
 static kmem_cache_t *fuse_inode_cachep;
-static struct subsystem connections_subsys;
-
-struct fuse_conn_attr {
-	struct attribute attr;
-	ssize_t (*show)(struct fuse_conn *, char *);
-	ssize_t (*store)(struct fuse_conn *, const char *, size_t);
-};
+struct list_head fuse_conn_list;
+DEFINE_MUTEX(fuse_mutex);
 
 #define FUSE_SUPER_MAGIC 0x65735546
 
@@ -104,6 +99,14 @@
 	}
 }
 
+static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
+{
+	if (*flags & MS_MANDLOCK)
+		return -EINVAL;
+
+	return 0;
+}
+
 void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
 {
 	if (S_ISREG(inode->i_mode) && i_size_read(inode) != attr->size)
@@ -195,31 +198,29 @@
 	return inode;
 }
 
-static void fuse_umount_begin(struct super_block *sb)
+static void fuse_umount_begin(struct vfsmount *vfsmnt, int flags)
 {
-	fuse_abort_conn(get_fuse_conn_super(sb));
+	if (flags & MNT_FORCE)
+		fuse_abort_conn(get_fuse_conn_super(vfsmnt->mnt_sb));
 }
 
 static void fuse_put_super(struct super_block *sb)
 {
 	struct fuse_conn *fc = get_fuse_conn_super(sb);
 
-	down_write(&fc->sbput_sem);
-	while (!list_empty(&fc->background))
-		fuse_release_background(fc,
-					list_entry(fc->background.next,
-						   struct fuse_req, bg_entry));
-
 	spin_lock(&fc->lock);
-	fc->mounted = 0;
 	fc->connected = 0;
+	fc->blocked = 0;
 	spin_unlock(&fc->lock);
-	up_write(&fc->sbput_sem);
 	/* Flush all readers on this fs */
 	kill_fasync(&fc->fasync, SIGIO, POLL_IN);
 	wake_up_all(&fc->waitq);
-	kobject_del(&fc->kobj);
-	kobject_put(&fc->kobj);
+	wake_up_all(&fc->blocked_waitq);
+	mutex_lock(&fuse_mutex);
+	list_del(&fc->entry);
+	fuse_ctl_remove_conn(fc);
+	mutex_unlock(&fuse_mutex);
+	fuse_conn_put(fc);
 }
 
 static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr)
@@ -236,8 +237,9 @@
 	/* fsid is left zero */
 }
 
-static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
+static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
 	struct fuse_conn *fc = get_fuse_conn_super(sb);
 	struct fuse_req *req;
 	struct fuse_statfs_out outarg;
@@ -368,11 +370,6 @@
 	return 0;
 }
 
-static void fuse_conn_release(struct kobject *kobj)
-{
-	kfree(get_fuse_conn_kobj(kobj));
-}
-
 static struct fuse_conn *new_conn(void)
 {
 	struct fuse_conn *fc;
@@ -380,24 +377,35 @@
 	fc = kzalloc(sizeof(*fc), GFP_KERNEL);
 	if (fc) {
 		spin_lock_init(&fc->lock);
+		atomic_set(&fc->count, 1);
 		init_waitqueue_head(&fc->waitq);
 		init_waitqueue_head(&fc->blocked_waitq);
 		INIT_LIST_HEAD(&fc->pending);
 		INIT_LIST_HEAD(&fc->processing);
 		INIT_LIST_HEAD(&fc->io);
-		INIT_LIST_HEAD(&fc->background);
-		init_rwsem(&fc->sbput_sem);
-		kobj_set_kset_s(fc, connections_subsys);
-		kobject_init(&fc->kobj);
+		INIT_LIST_HEAD(&fc->interrupts);
 		atomic_set(&fc->num_waiting, 0);
 		fc->bdi.ra_pages = (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE;
 		fc->bdi.unplug_io_fn = default_unplug_io_fn;
 		fc->reqctr = 0;
 		fc->blocked = 1;
+		get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
 	}
 	return fc;
 }
 
+void fuse_conn_put(struct fuse_conn *fc)
+{
+	if (atomic_dec_and_test(&fc->count))
+		kfree(fc);
+}
+
+struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
+{
+	atomic_inc(&fc->count);
+	return fc;
+}
+
 static struct inode *get_root_inode(struct super_block *sb, unsigned mode)
 {
 	struct fuse_attr attr;
@@ -413,6 +421,7 @@
 	.destroy_inode  = fuse_destroy_inode,
 	.read_inode	= fuse_read_inode,
 	.clear_inode	= fuse_clear_inode,
+	.remount_fs	= fuse_remount_fs,
 	.put_super	= fuse_put_super,
 	.umount_begin	= fuse_umount_begin,
 	.statfs		= fuse_statfs,
@@ -432,8 +441,12 @@
 			ra_pages = arg->max_readahead / PAGE_CACHE_SIZE;
 			if (arg->flags & FUSE_ASYNC_READ)
 				fc->async_read = 1;
-		} else
+			if (!(arg->flags & FUSE_POSIX_LOCKS))
+				fc->no_lock = 1;
+		} else {
 			ra_pages = fc->max_read / PAGE_CACHE_SIZE;
+			fc->no_lock = 1;
+		}
 
 		fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages);
 		fc->minor = arg->minor;
@@ -451,7 +464,7 @@
 	arg->major = FUSE_KERNEL_VERSION;
 	arg->minor = FUSE_KERNEL_MINOR_VERSION;
 	arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
-	arg->flags |= FUSE_ASYNC_READ;
+	arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS;
 	req->in.h.opcode = FUSE_INIT;
 	req->in.numargs = 1;
 	req->in.args[0].size = sizeof(*arg);
@@ -467,10 +480,9 @@
 	request_send_background(fc, req);
 }
 
-static unsigned long long conn_id(void)
+static u64 conn_id(void)
 {
-	/* BKL is held for ->get_sb() */
-	static unsigned long long ctr = 1;
+	static u64 ctr = 1;
 	return ctr++;
 }
 
@@ -484,6 +496,9 @@
 	struct fuse_req *init_req;
 	int err;
 
+	if (sb->s_flags & MS_MANDLOCK)
+		return -EINVAL;
+
 	if (!parse_fuse_opt((char *) data, &d))
 		return -EINVAL;
 
@@ -527,25 +542,21 @@
 	if (!init_req)
 		goto err_put_root;
 
-	err = kobject_set_name(&fc->kobj, "%llu", conn_id());
-	if (err)
-		goto err_free_req;
-
-	err = kobject_add(&fc->kobj);
-	if (err)
-		goto err_free_req;
-
-	/* Setting file->private_data can't race with other mount()
-	   instances, since BKL is held for ->get_sb() */
+	mutex_lock(&fuse_mutex);
 	err = -EINVAL;
 	if (file->private_data)
-		goto err_kobject_del;
+		goto err_unlock;
 
+	fc->id = conn_id();
+	err = fuse_ctl_add_conn(fc);
+	if (err)
+		goto err_unlock;
+
+	list_add_tail(&fc->entry, &fuse_conn_list);
 	sb->s_root = root_dentry;
-	fc->mounted = 1;
 	fc->connected = 1;
-	kobject_get(&fc->kobj);
-	file->private_data = fc;
+	file->private_data = fuse_conn_get(fc);
+	mutex_unlock(&fuse_mutex);
 	/*
 	 * atomic_dec_and_test() in fput() provides the necessary
 	 * memory barrier for file->private_data to be visible on all
@@ -557,23 +568,22 @@
 
 	return 0;
 
- err_kobject_del:
-	kobject_del(&fc->kobj);
- err_free_req:
+ err_unlock:
+	mutex_unlock(&fuse_mutex);
 	fuse_request_free(init_req);
  err_put_root:
 	dput(root_dentry);
  err:
 	fput(file);
-	kobject_put(&fc->kobj);
+	fuse_conn_put(fc);
 	return err;
 }
 
-static struct super_block *fuse_get_sb(struct file_system_type *fs_type,
-				       int flags, const char *dev_name,
-				       void *raw_data)
+static int fuse_get_sb(struct file_system_type *fs_type,
+		       int flags, const char *dev_name,
+		       void *raw_data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super);
+	return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt);
 }
 
 static struct file_system_type fuse_fs_type = {
@@ -583,68 +593,8 @@
 	.kill_sb	= kill_anon_super,
 };
 
-static ssize_t fuse_conn_waiting_show(struct fuse_conn *fc, char *page)
-{
-	return sprintf(page, "%i\n", atomic_read(&fc->num_waiting));
-}
-
-static ssize_t fuse_conn_abort_store(struct fuse_conn *fc, const char *page,
-				     size_t count)
-{
-	fuse_abort_conn(fc);
-	return count;
-}
-
-static struct fuse_conn_attr fuse_conn_waiting =
-	__ATTR(waiting, 0400, fuse_conn_waiting_show, NULL);
-static struct fuse_conn_attr fuse_conn_abort =
-	__ATTR(abort, 0600, NULL, fuse_conn_abort_store);
-
-static struct attribute *fuse_conn_attrs[] = {
-	&fuse_conn_waiting.attr,
-	&fuse_conn_abort.attr,
-	NULL,
-};
-
-static ssize_t fuse_conn_attr_show(struct kobject *kobj,
-				   struct attribute *attr,
-				   char *page)
-{
-	struct fuse_conn_attr *fca =
-		container_of(attr, struct fuse_conn_attr, attr);
-
-	if (fca->show)
-		return fca->show(get_fuse_conn_kobj(kobj), page);
-	else
-		return -EACCES;
-}
-
-static ssize_t fuse_conn_attr_store(struct kobject *kobj,
-				    struct attribute *attr,
-				    const char *page, size_t count)
-{
-	struct fuse_conn_attr *fca =
-		container_of(attr, struct fuse_conn_attr, attr);
-
-	if (fca->store)
-		return fca->store(get_fuse_conn_kobj(kobj), page, count);
-	else
-		return -EACCES;
-}
-
-static struct sysfs_ops fuse_conn_sysfs_ops = {
-	.show	= &fuse_conn_attr_show,
-	.store	= &fuse_conn_attr_store,
-};
-
-static struct kobj_type ktype_fuse_conn = {
-	.release	= fuse_conn_release,
-	.sysfs_ops	= &fuse_conn_sysfs_ops,
-	.default_attrs	= fuse_conn_attrs,
-};
-
 static decl_subsys(fuse, NULL, NULL);
-static decl_subsys(connections, &ktype_fuse_conn, NULL);
+static decl_subsys(connections, NULL, NULL);
 
 static void fuse_inode_init_once(void *foo, kmem_cache_t *cachep,
 				 unsigned long flags)
@@ -718,6 +668,7 @@
 	printk("fuse init (API version %i.%i)\n",
 	       FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
 
+	INIT_LIST_HEAD(&fuse_conn_list);
 	res = fuse_fs_init();
 	if (res)
 		goto err;
@@ -730,8 +681,14 @@
 	if (res)
 		goto err_dev_cleanup;
 
+	res = fuse_ctl_init();
+	if (res)
+		goto err_sysfs_cleanup;
+
 	return 0;
 
+ err_sysfs_cleanup:
+	fuse_sysfs_cleanup();
  err_dev_cleanup:
 	fuse_dev_cleanup();
  err_fs_cleanup:
@@ -744,6 +701,7 @@
 {
 	printk(KERN_DEBUG "fuse exit\n");
 
+	fuse_ctl_cleanup();
 	fuse_sysfs_cleanup();
 	fuse_fs_cleanup();
 	fuse_dev_cleanup();
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
index 1e44dcf..13231dd 100644
--- a/fs/hfs/bnode.c
+++ b/fs/hfs/bnode.c
@@ -280,7 +280,7 @@
 	block = off >> PAGE_CACHE_SHIFT;
 	node->page_offset = off & ~PAGE_CACHE_MASK;
 	for (i = 0; i < tree->pages_per_bnode; i++) {
-		page = read_cache_page(mapping, block++, (filler_t *)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, block++, NULL);
 		if (IS_ERR(page))
 			goto fail;
 		if (PageError(page)) {
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c
index d20131c..4003579 100644
--- a/fs/hfs/btree.c
+++ b/fs/hfs/btree.c
@@ -59,7 +59,7 @@
 	unlock_new_inode(tree->inode);
 
 	mapping = tree->inode->i_mapping;
-	page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL);
+	page = read_mapping_page(mapping, 0, NULL);
 	if (IS_ERR(page))
 		goto free_tree;
 
diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h
index 3ed8663..735332d 100644
--- a/fs/hfs/hfs_fs.h
+++ b/fs/hfs/hfs_fs.h
@@ -182,8 +182,8 @@
 extern int hfs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 /* inode.c */
-extern struct address_space_operations hfs_aops;
-extern struct address_space_operations hfs_btree_aops;
+extern const struct address_space_operations hfs_aops;
+extern const struct address_space_operations hfs_btree_aops;
 
 extern struct inode *hfs_new_inode(struct inode *, struct qstr *, int);
 extern void hfs_inode_write_fork(struct inode *, struct hfs_extent *, __be32 *, __be32 *);
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index 2d4ced2..315cf44 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -114,7 +114,7 @@
 	return mpage_writepages(mapping, wbc, hfs_get_block);
 }
 
-struct address_space_operations hfs_btree_aops = {
+const struct address_space_operations hfs_btree_aops = {
 	.readpage	= hfs_readpage,
 	.writepage	= hfs_writepage,
 	.sync_page	= block_sync_page,
@@ -124,7 +124,7 @@
 	.releasepage	= hfs_releasepage,
 };
 
-struct address_space_operations hfs_aops = {
+const struct address_space_operations hfs_aops = {
 	.readpage	= hfs_readpage,
 	.writepage	= hfs_writepage,
 	.sync_page	= block_sync_page,
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 1181d11..d9227bf 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -80,8 +80,10 @@
  *
  * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
  */
-static int hfs_statfs(struct super_block *sb, struct kstatfs *buf)
+static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
+
 	buf->f_type = HFS_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div;
@@ -413,10 +415,11 @@
 	return res;
 }
 
-static struct super_block *hfs_get_sb(struct file_system_type *fs_type,
-				      int flags, const char *dev_name, void *data)
+static int hfs_get_sb(struct file_system_type *fs_type,
+		      int flags, const char *dev_name, void *data,
+		      struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super, mnt);
 }
 
 static struct file_system_type hfs_fs_type = {
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c
index 9fb5163..d128a25b 100644
--- a/fs/hfsplus/bitmap.c
+++ b/fs/hfsplus/bitmap.c
@@ -31,8 +31,7 @@
 	dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len);
 	mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
 	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
-	page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
-			       (filler_t *)mapping->a_ops->readpage, NULL);
+	page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL);
 	pptr = kmap(page);
 	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
 	i = offset % 32;
@@ -72,8 +71,8 @@
 		offset += PAGE_CACHE_BITS;
 		if (offset >= size)
 			break;
-		page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
-				       (filler_t *)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
+					 NULL);
 		curr = pptr = kmap(page);
 		if ((size ^ offset) / PAGE_CACHE_BITS)
 			end = pptr + PAGE_CACHE_BITS / 32;
@@ -119,8 +118,8 @@
 		set_page_dirty(page);
 		kunmap(page);
 		offset += PAGE_CACHE_BITS;
-		page = read_cache_page(mapping, offset / PAGE_CACHE_BITS,
-				       (filler_t *)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS,
+					 NULL);
 		pptr = kmap(page);
 		curr = pptr;
 		end = pptr + PAGE_CACHE_BITS / 32;
@@ -167,7 +166,7 @@
 	mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex);
 	mapping = HFSPLUS_SB(sb).alloc_file->i_mapping;
 	pnr = offset / PAGE_CACHE_BITS;
-	page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL);
+	page = read_mapping_page(mapping, pnr, NULL);
 	pptr = kmap(page);
 	curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32;
 	end = pptr + PAGE_CACHE_BITS / 32;
@@ -199,7 +198,7 @@
 			break;
 		set_page_dirty(page);
 		kunmap(page);
-		page = read_cache_page(mapping, ++pnr, (filler_t *)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, ++pnr, NULL);
 		pptr = kmap(page);
 		curr = pptr;
 		end = pptr + PAGE_CACHE_BITS / 32;
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 746abc9..77bf434 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -440,7 +440,7 @@
 	block = off >> PAGE_CACHE_SHIFT;
 	node->page_offset = off & ~PAGE_CACHE_MASK;
 	for (i = 0; i < tree->pages_per_bnode; block++, i++) {
-		page = read_cache_page(mapping, block, (filler_t *)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, block, NULL);
 		if (IS_ERR(page))
 			goto fail;
 		if (PageError(page)) {
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c
index effa899..cfc852f 100644
--- a/fs/hfsplus/btree.c
+++ b/fs/hfsplus/btree.c
@@ -38,7 +38,7 @@
 		goto free_tree;
 
 	mapping = tree->inode->i_mapping;
-	page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL);
+	page = read_mapping_page(mapping, 0, NULL);
 	if (IS_ERR(page))
 		goto free_tree;
 
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index 7ae3936..8a1ca5e 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -323,8 +323,8 @@
 void hfsplus_file_truncate(struct inode *);
 
 /* inode.c */
-extern struct address_space_operations hfsplus_aops;
-extern struct address_space_operations hfsplus_btree_aops;
+extern const struct address_space_operations hfsplus_aops;
+extern const struct address_space_operations hfsplus_btree_aops;
 
 void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *);
 void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *);
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index acf66db..924ecde 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -109,7 +109,7 @@
 	return mpage_writepages(mapping, wbc, hfsplus_get_block);
 }
 
-struct address_space_operations hfsplus_btree_aops = {
+const struct address_space_operations hfsplus_btree_aops = {
 	.readpage	= hfsplus_readpage,
 	.writepage	= hfsplus_writepage,
 	.sync_page	= block_sync_page,
@@ -119,7 +119,7 @@
 	.releasepage	= hfsplus_releasepage,
 };
 
-struct address_space_operations hfsplus_aops = {
+const struct address_space_operations hfsplus_aops = {
 	.readpage	= hfsplus_readpage,
 	.writepage	= hfsplus_writepage,
 	.sync_page	= block_sync_page,
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 7843f79..0a92fa2 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -212,8 +212,10 @@
 	sb->s_fs_info = NULL;
 }
 
-static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf)
+static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
+
 	buf->f_type = HFSPLUS_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift;
@@ -450,10 +452,12 @@
 
 #define HFSPLUS_INODE_SIZE	sizeof(struct hfsplus_inode_info)
 
-static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type,
-					  int flags, const char *dev_name, void *data)
+static int hfsplus_get_sb(struct file_system_type *fs_type,
+			  int flags, const char *dev_name, void *data,
+			  struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super,
+			   mnt);
 }
 
 static struct file_system_type hfsplus_fs_type = {
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index bf0f8e1..b82e3d9 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -54,7 +54,7 @@
 
 static struct inode_operations hostfs_iops;
 static struct inode_operations hostfs_dir_iops;
-static struct address_space_operations hostfs_link_aops;
+static const struct address_space_operations hostfs_link_aops;
 
 #ifndef MODULE
 static int __init hostfs_args(char *options, int *add)
@@ -239,7 +239,7 @@
 	return(err);
 }
 
-int hostfs_statfs(struct super_block *sb, struct kstatfs *sf)
+int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf)
 {
 	/* do_statfs uses struct statfs64 internally, but the linux kernel
 	 * struct statfs still has 32-bit versions for most of these fields,
@@ -252,7 +252,7 @@
 	long long f_files;
 	long long f_ffree;
 
-	err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename,
+	err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename,
 			&sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files,
 			&f_ffree, &sf->f_fsid, sizeof(sf->f_fsid),
 			&sf->f_namelen, sf->f_spare);
@@ -518,7 +518,7 @@
 	return(err);
 }
 
-static struct address_space_operations hostfs_aops = {
+static const struct address_space_operations hostfs_aops = {
 	.writepage 	= hostfs_writepage,
 	.readpage	= hostfs_readpage,
 	.set_page_dirty = __set_page_dirty_nobuffers,
@@ -935,7 +935,7 @@
 	return(err);
 }
 
-static struct address_space_operations hostfs_link_aops = {
+static const struct address_space_operations hostfs_link_aops = {
 	.readpage	= hostfs_link_readpage,
 };
 
@@ -993,11 +993,11 @@
 	return(err);
 }
 
-static struct super_block *hostfs_read_sb(struct file_system_type *type,
-					     int flags, const char *dev_name,
-					     void *data)
+static int hostfs_read_sb(struct file_system_type *type,
+			  int flags, const char *dev_name,
+			  void *data, struct vfsmount *mnt)
 {
-	return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common));
+	return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt);
 }
 
 static struct file_system_type hostfs_type = {
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index d3b9fff..d9eb19b 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -99,7 +99,7 @@
 {
 	return generic_block_bmap(mapping,block,hpfs_get_block);
 }
-struct address_space_operations hpfs_aops = {
+const struct address_space_operations hpfs_aops = {
 	.readpage = hpfs_readpage,
 	.writepage = hpfs_writepage,
 	.sync_page = block_sync_page,
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 29b7a3e..f687d54 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -268,7 +268,7 @@
 int hpfs_file_fsync(struct file *, struct dentry *, int);
 extern const struct file_operations hpfs_file_ops;
 extern struct inode_operations hpfs_file_iops;
-extern struct address_space_operations hpfs_aops;
+extern const struct address_space_operations hpfs_aops;
 
 /* inode.c */
 
@@ -304,7 +304,7 @@
 /* namei.c */
 
 extern struct inode_operations hpfs_dir_iops;
-extern struct address_space_operations hpfs_symlink_aops;
+extern const struct address_space_operations hpfs_symlink_aops;
 
 static inline struct hpfs_inode_info *hpfs_i(struct inode *inode)
 {
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index a03abb1..59e7dc1 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -538,7 +538,7 @@
 	return err;
 }
 
-struct address_space_operations hpfs_symlink_aops = {
+const struct address_space_operations hpfs_symlink_aops = {
 	.readpage	= hpfs_symlink_readpage
 };
 	
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index d72d8c8..f798480 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -135,8 +135,9 @@
 	return count;
 }
 
-static int hpfs_statfs(struct super_block *s, struct kstatfs *buf)
+static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *s = dentry->d_sb;
 	struct hpfs_sb_info *sbi = hpfs_sb(s);
 	lock_kernel();
 
@@ -662,10 +663,11 @@
 	return -EINVAL;
 }
 
-static struct super_block *hpfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int hpfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type hpfs_fs_type = {
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index 5e6363b..3a9bdf58 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -616,7 +616,7 @@
 	.fsync		= hppfs_fsync,
 };
 
-static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf)
+static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf)
 {
 	sf->f_blocks = 0;
 	sf->f_bfree = 0;
@@ -769,11 +769,11 @@
 	return(err);
 }
 
-static struct super_block *hppfs_read_super(struct file_system_type *type,
-					     int flags, const char *dev_name,
-					     void *data)
+static int hppfs_read_super(struct file_system_type *type,
+			    int flags, const char *dev_name,
+			    void *data, struct vfsmount *mnt)
 {
-	return(get_sb_nodev(type, flags, data, hppfs_fill_super));
+	return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt);
 }
 
 static struct file_system_type hppfs_type = {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 3a5b4e9..6449cb6 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -34,7 +34,7 @@
 #define HUGETLBFS_MAGIC	0x958458f6
 
 static struct super_operations hugetlbfs_ops;
-static struct address_space_operations hugetlbfs_aops;
+static const struct address_space_operations hugetlbfs_aops;
 const struct file_operations hugetlbfs_file_operations;
 static struct inode_operations hugetlbfs_dir_inode_operations;
 static struct inode_operations hugetlbfs_inode_operations;
@@ -59,7 +59,6 @@
 static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct inode *inode = file->f_dentry->d_inode;
-	struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode);
 	loff_t len, vma_len;
 	int ret;
 
@@ -87,9 +86,10 @@
 	if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size)
 		goto out;
 
-	if (vma->vm_flags & VM_MAYSHARE)
-		if (hugetlb_extend_reservation(info, len >> HPAGE_SHIFT) != 0)
-			goto out;
+	if (vma->vm_flags & VM_MAYSHARE &&
+	    hugetlb_reserve_pages(inode, vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT),
+				  len >> HPAGE_SHIFT))
+		goto out;
 
 	ret = 0;
 	hugetlb_prefault_arch_hook(vma->vm_mm);
@@ -195,12 +195,8 @@
 	const pgoff_t start = lstart >> HPAGE_SHIFT;
 	struct pagevec pvec;
 	pgoff_t next;
-	int i;
+	int i, freed = 0;
 
-	hugetlb_truncate_reservation(HUGETLBFS_I(inode),
-				     lstart >> HPAGE_SHIFT);
-	if (!mapping->nrpages)
-		return;
 	pagevec_init(&pvec, 0);
 	next = start;
 	while (1) {
@@ -221,10 +217,12 @@
 			truncate_huge_page(page);
 			unlock_page(page);
 			hugetlb_put_quota(mapping);
+			freed++;
 		}
 		huge_pagevec_release(&pvec);
 	}
 	BUG_ON(!lstart && mapping->nrpages);
+	hugetlb_unreserve_pages(inode, start, freed);
 }
 
 static void hugetlbfs_delete_inode(struct inode *inode)
@@ -366,6 +364,7 @@
 		inode->i_mapping->a_ops = &hugetlbfs_aops;
 		inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		INIT_LIST_HEAD(&inode->i_mapping->private_list);
 		info = HUGETLBFS_I(inode);
 		mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL);
 		switch (mode & S_IFMT) {
@@ -467,9 +466,9 @@
 	return 0;
 }
 
-static int hugetlbfs_statfs(struct super_block *sb, struct kstatfs *buf)
+static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb);
+	struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
 
 	buf->f_type = HUGETLBFS_MAGIC;
 	buf->f_bsize = HPAGE_SIZE;
@@ -538,7 +537,6 @@
 		hugetlbfs_inc_free_inodes(sbinfo);
 		return NULL;
 	}
-	p->prereserved_hpages = 0;
 	return &p->vfs_inode;
 }
 
@@ -549,7 +547,7 @@
 	kmem_cache_free(hugetlbfs_inode_cachep, HUGETLBFS_I(inode));
 }
 
-static struct address_space_operations hugetlbfs_aops = {
+static const struct address_space_operations hugetlbfs_aops = {
 	.readpage	= hugetlbfs_readpage,
 	.prepare_write	= hugetlbfs_prepare_write,
 	.commit_write	= hugetlbfs_commit_write,
@@ -723,10 +721,10 @@
 	}
 }
 
-static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int hugetlbfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super);
+	return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super, mnt);
 }
 
 static struct file_system_type hugetlbfs_fs_type = {
@@ -781,8 +779,7 @@
 		goto out_file;
 
 	error = -ENOMEM;
-	if (hugetlb_extend_reservation(HUGETLBFS_I(inode),
-				       size >> HPAGE_SHIFT) != 0)
+	if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT))
 		goto out_inode;
 
 	d_instantiate(dentry, inode);
diff --git a/fs/inode.c b/fs/inode.c
index 3a2446a..f42961e 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -102,7 +102,7 @@
 
 static struct inode *alloc_inode(struct super_block *sb)
 {
-	static struct address_space_operations empty_aops;
+	static const struct address_space_operations empty_aops;
 	static struct inode_operations empty_iops;
 	static const struct file_operations empty_fops;
 	struct inode *inode;
diff --git a/fs/inotify.c b/fs/inotify.c
index 732ec4b..723836a 100644
--- a/fs/inotify.c
+++ b/fs/inotify.c
@@ -5,7 +5,10 @@
  *	John McCutchan	<ttb@tentacle.dhs.org>
  *	Robert Love	<rml@novell.com>
  *
+ * Kernel API added by: Amy Griffis <amy.griffis@hp.com>
+ *
  * Copyright (C) 2005 John McCutchan
+ * Copyright 2006 Hewlett-Packard Development Company, L.P.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -20,35 +23,17 @@
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/idr.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
-#include <linux/file.h>
-#include <linux/mount.h>
-#include <linux/namei.h>
-#include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/writeback.h>
 #include <linux/inotify.h>
-#include <linux/syscalls.h>
-
-#include <asm/ioctls.h>
 
 static atomic_t inotify_cookie;
 
-static kmem_cache_t *watch_cachep __read_mostly;
-static kmem_cache_t *event_cachep __read_mostly;
-
-static struct vfsmount *inotify_mnt __read_mostly;
-
-/* these are configurable via /proc/sys/fs/inotify/ */
-int inotify_max_user_instances __read_mostly;
-int inotify_max_user_watches __read_mostly;
-int inotify_max_queued_events __read_mostly;
-
 /*
  * Lock ordering:
  *
@@ -56,330 +41,111 @@
  * iprune_mutex (synchronize shrink_icache_memory())
  * 	inode_lock (protects the super_block->s_inodes list)
  * 	inode->inotify_mutex (protects inode->inotify_watches and watches->i_list)
- * 		inotify_dev->mutex (protects inotify_device and watches->d_list)
+ * 		inotify_handle->mutex (protects inotify_handle and watches->h_list)
+ *
+ * The inode->inotify_mutex and inotify_handle->mutex and held during execution
+ * of a caller's event handler.  Thus, the caller must not hold any locks
+ * taken in their event handler while calling any of the published inotify
+ * interfaces.
  */
 
 /*
- * Lifetimes of the three main data structures--inotify_device, inode, and
+ * Lifetimes of the three main data structures--inotify_handle, inode, and
  * inotify_watch--are managed by reference count.
  *
- * inotify_device: Lifetime is from inotify_init() until release.  Additional
- * references can bump the count via get_inotify_dev() and drop the count via
- * put_inotify_dev().
+ * inotify_handle: Lifetime is from inotify_init() to inotify_destroy().
+ * Additional references can bump the count via get_inotify_handle() and drop
+ * the count via put_inotify_handle().
  *
- * inotify_watch: Lifetime is from create_watch() to destory_watch().
- * Additional references can bump the count via get_inotify_watch() and drop
- * the count via put_inotify_watch().
+ * inotify_watch: for inotify's purposes, lifetime is from inotify_add_watch()
+ * to remove_watch_no_event().  Additional references can bump the count via
+ * get_inotify_watch() and drop the count via put_inotify_watch().  The caller
+ * is reponsible for the final put after receiving IN_IGNORED, or when using
+ * IN_ONESHOT after receiving the first event.  Inotify does the final put if
+ * inotify_destroy() is called.
  *
  * inode: Pinned so long as the inode is associated with a watch, from
- * create_watch() to put_inotify_watch().
+ * inotify_add_watch() to the final put_inotify_watch().
  */
 
 /*
- * struct inotify_device - represents an inotify instance
+ * struct inotify_handle - represents an inotify instance
  *
  * This structure is protected by the mutex 'mutex'.
  */
-struct inotify_device {
-	wait_queue_head_t 	wq;		/* wait queue for i/o */
+struct inotify_handle {
 	struct idr		idr;		/* idr mapping wd -> watch */
 	struct mutex		mutex;		/* protects this bad boy */
-	struct list_head 	events;		/* list of queued events */
 	struct list_head	watches;	/* list of watches */
 	atomic_t		count;		/* reference count */
-	struct user_struct	*user;		/* user who opened this dev */
-	unsigned int		queue_size;	/* size of the queue (bytes) */
-	unsigned int		event_count;	/* number of pending events */
-	unsigned int		max_events;	/* maximum number of events */
 	u32			last_wd;	/* the last wd allocated */
+	const struct inotify_operations *in_ops; /* inotify caller operations */
 };
 
-/*
- * struct inotify_kernel_event - An inotify event, originating from a watch and
- * queued for user-space.  A list of these is attached to each instance of the
- * device.  In read(), this list is walked and all events that can fit in the
- * buffer are returned.
- *
- * Protected by dev->mutex of the device in which we are queued.
- */
-struct inotify_kernel_event {
-	struct inotify_event	event;	/* the user-space event */
-	struct list_head        list;	/* entry in inotify_device's list */
-	char			*name;	/* filename, if any */
-};
-
-/*
- * struct inotify_watch - represents a watch request on a specific inode
- *
- * d_list is protected by dev->mutex of the associated watch->dev.
- * i_list and mask are protected by inode->inotify_mutex of the associated inode.
- * dev, inode, and wd are never written to once the watch is created.
- */
-struct inotify_watch {
-	struct list_head	d_list;	/* entry in inotify_device's list */
-	struct list_head	i_list;	/* entry in inode's list */
-	atomic_t		count;	/* reference count */
-	struct inotify_device	*dev;	/* associated device */
-	struct inode		*inode;	/* associated inode */
-	s32 			wd;	/* watch descriptor */
-	u32			mask;	/* event mask for this watch */
-};
-
-#ifdef CONFIG_SYSCTL
-
-#include <linux/sysctl.h>
-
-static int zero;
-
-ctl_table inotify_table[] = {
-	{
-		.ctl_name	= INOTIFY_MAX_USER_INSTANCES,
-		.procname	= "max_user_instances",
-		.data		= &inotify_max_user_instances,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
-		.extra1		= &zero,
-	},
-	{
-		.ctl_name	= INOTIFY_MAX_USER_WATCHES,
-		.procname	= "max_user_watches",
-		.data		= &inotify_max_user_watches,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec,
-		.extra1		= &zero, 
-	},
-	{
-		.ctl_name	= INOTIFY_MAX_QUEUED_EVENTS,
-		.procname	= "max_queued_events",
-		.data		= &inotify_max_queued_events,
-		.maxlen		= sizeof(int),
-		.mode		= 0644, 
-		.proc_handler	= &proc_dointvec_minmax,
-		.strategy	= &sysctl_intvec, 
-		.extra1		= &zero
-	},
-	{ .ctl_name = 0 }
-};
-#endif /* CONFIG_SYSCTL */
-
-static inline void get_inotify_dev(struct inotify_device *dev)
+static inline void get_inotify_handle(struct inotify_handle *ih)
 {
-	atomic_inc(&dev->count);
+	atomic_inc(&ih->count);
 }
 
-static inline void put_inotify_dev(struct inotify_device *dev)
+static inline void put_inotify_handle(struct inotify_handle *ih)
 {
-	if (atomic_dec_and_test(&dev->count)) {
-		atomic_dec(&dev->user->inotify_devs);
-		free_uid(dev->user);
-		idr_destroy(&dev->idr);
-		kfree(dev);
+	if (atomic_dec_and_test(&ih->count)) {
+		idr_destroy(&ih->idr);
+		kfree(ih);
 	}
 }
 
-static inline void get_inotify_watch(struct inotify_watch *watch)
+/**
+ * get_inotify_watch - grab a reference to an inotify_watch
+ * @watch: watch to grab
+ */
+void get_inotify_watch(struct inotify_watch *watch)
 {
 	atomic_inc(&watch->count);
 }
+EXPORT_SYMBOL_GPL(get_inotify_watch);
 
-/*
+/**
  * put_inotify_watch - decrements the ref count on a given watch.  cleans up
- * the watch and its references if the count reaches zero.
+ * watch references if the count reaches zero.  inotify_watch is freed by
+ * inotify callers via the destroy_watch() op.
+ * @watch: watch to release
  */
-static inline void put_inotify_watch(struct inotify_watch *watch)
+void put_inotify_watch(struct inotify_watch *watch)
 {
 	if (atomic_dec_and_test(&watch->count)) {
-		put_inotify_dev(watch->dev);
+		struct inotify_handle *ih = watch->ih;
+
 		iput(watch->inode);
-		kmem_cache_free(watch_cachep, watch);
+		ih->in_ops->destroy_watch(watch);
+		put_inotify_handle(ih);
 	}
 }
+EXPORT_SYMBOL_GPL(put_inotify_watch);
 
 /*
- * kernel_event - create a new kernel event with the given parameters
+ * inotify_handle_get_wd - returns the next WD for use by the given handle
  *
- * This function can sleep.
+ * Callers must hold ih->mutex.  This function can sleep.
  */
-static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
-						  const char *name)
-{
-	struct inotify_kernel_event *kevent;
-
-	kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
-	if (unlikely(!kevent))
-		return NULL;
-
-	/* we hand this out to user-space, so zero it just in case */
-	memset(&kevent->event, 0, sizeof(struct inotify_event));
-
-	kevent->event.wd = wd;
-	kevent->event.mask = mask;
-	kevent->event.cookie = cookie;
-
-	INIT_LIST_HEAD(&kevent->list);
-
-	if (name) {
-		size_t len, rem, event_size = sizeof(struct inotify_event);
-
-		/*
-		 * We need to pad the filename so as to properly align an
-		 * array of inotify_event structures.  Because the structure is
-		 * small and the common case is a small filename, we just round
-		 * up to the next multiple of the structure's sizeof.  This is
-		 * simple and safe for all architectures.
-		 */
-		len = strlen(name) + 1;
-		rem = event_size - len;
-		if (len > event_size) {
-			rem = event_size - (len % event_size);
-			if (len % event_size == 0)
-				rem = 0;
-		}
-
-		kevent->name = kmalloc(len + rem, GFP_KERNEL);
-		if (unlikely(!kevent->name)) {
-			kmem_cache_free(event_cachep, kevent);
-			return NULL;
-		}
-		memcpy(kevent->name, name, len);
-		if (rem)
-			memset(kevent->name + len, 0, rem);		
-		kevent->event.len = len + rem;
-	} else {
-		kevent->event.len = 0;
-		kevent->name = NULL;
-	}
-
-	return kevent;
-}
-
-/*
- * inotify_dev_get_event - return the next event in the given dev's queue
- *
- * Caller must hold dev->mutex.
- */
-static inline struct inotify_kernel_event *
-inotify_dev_get_event(struct inotify_device *dev)
-{
-	return list_entry(dev->events.next, struct inotify_kernel_event, list);
-}
-
-/*
- * inotify_dev_queue_event - add a new event to the given device
- *
- * Caller must hold dev->mutex.  Can sleep (calls kernel_event()).
- */
-static void inotify_dev_queue_event(struct inotify_device *dev,
-				    struct inotify_watch *watch, u32 mask,
-				    u32 cookie, const char *name)
-{
-	struct inotify_kernel_event *kevent, *last;
-
-	/* coalescing: drop this event if it is a dupe of the previous */
-	last = inotify_dev_get_event(dev);
-	if (last && last->event.mask == mask && last->event.wd == watch->wd &&
-			last->event.cookie == cookie) {
-		const char *lastname = last->name;
-
-		if (!name && !lastname)
-			return;
-		if (name && lastname && !strcmp(lastname, name))
-			return;
-	}
-
-	/* the queue overflowed and we already sent the Q_OVERFLOW event */
-	if (unlikely(dev->event_count > dev->max_events))
-		return;
-
-	/* if the queue overflows, we need to notify user space */
-	if (unlikely(dev->event_count == dev->max_events))
-		kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
-	else
-		kevent = kernel_event(watch->wd, mask, cookie, name);
-
-	if (unlikely(!kevent))
-		return;
-
-	/* queue the event and wake up anyone waiting */
-	dev->event_count++;
-	dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
-	list_add_tail(&kevent->list, &dev->events);
-	wake_up_interruptible(&dev->wq);
-}
-
-/*
- * remove_kevent - cleans up and ultimately frees the given kevent
- *
- * Caller must hold dev->mutex.
- */
-static void remove_kevent(struct inotify_device *dev,
-			  struct inotify_kernel_event *kevent)
-{
-	list_del(&kevent->list);
-
-	dev->event_count--;
-	dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
-
-	kfree(kevent->name);
-	kmem_cache_free(event_cachep, kevent);
-}
-
-/*
- * inotify_dev_event_dequeue - destroy an event on the given device
- *
- * Caller must hold dev->mutex.
- */
-static void inotify_dev_event_dequeue(struct inotify_device *dev)
-{
-	if (!list_empty(&dev->events)) {
-		struct inotify_kernel_event *kevent;
-		kevent = inotify_dev_get_event(dev);
-		remove_kevent(dev, kevent);
-	}
-}
-
-/*
- * inotify_dev_get_wd - returns the next WD for use by the given dev
- *
- * Callers must hold dev->mutex.  This function can sleep.
- */
-static int inotify_dev_get_wd(struct inotify_device *dev,
-			      struct inotify_watch *watch)
+static int inotify_handle_get_wd(struct inotify_handle *ih,
+				 struct inotify_watch *watch)
 {
 	int ret;
 
 	do {
-		if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL)))
+		if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL)))
 			return -ENOSPC;
-		ret = idr_get_new_above(&dev->idr, watch, dev->last_wd+1, &watch->wd);
+		ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd);
 	} while (ret == -EAGAIN);
 
+	if (likely(!ret))
+		ih->last_wd = watch->wd;
+
 	return ret;
 }
 
 /*
- * find_inode - resolve a user-given path to a specific inode and return a nd
- */
-static int find_inode(const char __user *dirname, struct nameidata *nd,
-		      unsigned flags)
-{
-	int error;
-
-	error = __user_walk(dirname, flags, nd);
-	if (error)
-		return error;
-	/* you can only watch an inode if you have read permissions on it */
-	error = vfs_permission(nd, MAY_READ);
-	if (error) 
-		path_release(nd);
-	return error;
-}
-
-/*
  * inotify_inode_watched - returns nonzero if there are watches on this inode
  * and zero otherwise.  We call this lockless, we do not care if we race.
  */
@@ -422,67 +188,18 @@
 }
 
 /*
- * create_watch - creates a watch on the given device.
- *
- * Callers must hold dev->mutex.  Calls inotify_dev_get_wd() so may sleep.
- * Both 'dev' and 'inode' (by way of nameidata) need to be pinned.
- */
-static struct inotify_watch *create_watch(struct inotify_device *dev,
-					  u32 mask, struct inode *inode)
-{
-	struct inotify_watch *watch;
-	int ret;
-
-	if (atomic_read(&dev->user->inotify_watches) >=
-			inotify_max_user_watches)
-		return ERR_PTR(-ENOSPC);
-
-	watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
-	if (unlikely(!watch))
-		return ERR_PTR(-ENOMEM);
-
-	ret = inotify_dev_get_wd(dev, watch);
-	if (unlikely(ret)) {
-		kmem_cache_free(watch_cachep, watch);
-		return ERR_PTR(ret);
-	}
-
-	dev->last_wd = watch->wd;
-	watch->mask = mask;
-	atomic_set(&watch->count, 0);
-	INIT_LIST_HEAD(&watch->d_list);
-	INIT_LIST_HEAD(&watch->i_list);
-
-	/* save a reference to device and bump the count to make it official */
-	get_inotify_dev(dev);
-	watch->dev = dev;
-
-	/*
-	 * Save a reference to the inode and bump the ref count to make it
-	 * official.  We hold a reference to nameidata, which makes this safe.
-	 */
-	watch->inode = igrab(inode);
-
-	/* bump our own count, corresponding to our entry in dev->watches */
-	get_inotify_watch(watch);
-
-	atomic_inc(&dev->user->inotify_watches);
-
-	return watch;
-}
-
-/*
- * inotify_find_dev - find the watch associated with the given inode and dev
+ * inotify_find_handle - find the watch associated with the given inode and
+ * handle
  *
  * Callers must hold inode->inotify_mutex.
  */
-static struct inotify_watch *inode_find_dev(struct inode *inode,
-					    struct inotify_device *dev)
+static struct inotify_watch *inode_find_handle(struct inode *inode,
+					       struct inotify_handle *ih)
 {
 	struct inotify_watch *watch;
 
 	list_for_each_entry(watch, &inode->inotify_watches, i_list) {
-		if (watch->dev == dev)
+		if (watch->ih == ih)
 			return watch;
 	}
 
@@ -490,40 +207,40 @@
 }
 
 /*
- * remove_watch_no_event - remove_watch() without the IN_IGNORED event.
+ * remove_watch_no_event - remove watch without the IN_IGNORED event.
+ *
+ * Callers must hold both inode->inotify_mutex and ih->mutex.
  */
 static void remove_watch_no_event(struct inotify_watch *watch,
-				  struct inotify_device *dev)
+				  struct inotify_handle *ih)
 {
 	list_del(&watch->i_list);
-	list_del(&watch->d_list);
+	list_del(&watch->h_list);
 
 	if (!inotify_inode_watched(watch->inode))
 		set_dentry_child_flags(watch->inode, 0);
 
-	atomic_dec(&dev->user->inotify_watches);
-	idr_remove(&dev->idr, watch->wd);
-	put_inotify_watch(watch);
+	idr_remove(&ih->idr, watch->wd);
 }
 
-/*
- * remove_watch - Remove a watch from both the device and the inode.  Sends
- * the IN_IGNORED event to the given device signifying that the inode is no
- * longer watched.
+/**
+ * inotify_remove_watch_locked - Remove a watch from both the handle and the
+ * inode.  Sends the IN_IGNORED event signifying that the inode is no longer
+ * watched.  May be invoked from a caller's event handler.
+ * @ih: inotify handle associated with watch
+ * @watch: watch to remove
  *
- * Callers must hold both inode->inotify_mutex and dev->mutex.  We drop a
- * reference to the inode before returning.
- *
- * The inode is not iput() so as to remain atomic.  If the inode needs to be
- * iput(), the call returns one.  Otherwise, it returns zero.
+ * Callers must hold both inode->inotify_mutex and ih->mutex.
  */
-static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev)
+void inotify_remove_watch_locked(struct inotify_handle *ih,
+				 struct inotify_watch *watch)
 {
-	inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL);
-	remove_watch_no_event(watch, dev);
+	remove_watch_no_event(watch, ih);
+	ih->in_ops->handle_event(watch, watch->wd, IN_IGNORED, 0, NULL, NULL);
 }
+EXPORT_SYMBOL_GPL(inotify_remove_watch_locked);
 
-/* Kernel API */
+/* Kernel API for producing events */
 
 /*
  * inotify_d_instantiate - instantiate dcache entry for inode
@@ -563,9 +280,10 @@
  * @mask: event mask describing this event
  * @cookie: cookie for synchronization, or zero
  * @name: filename, if any
+ * @n_inode: inode associated with name
  */
 void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie,
-			       const char *name)
+			       const char *name, struct inode *n_inode)
 {
 	struct inotify_watch *watch, *next;
 
@@ -576,14 +294,13 @@
 	list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
 		u32 watch_mask = watch->mask;
 		if (watch_mask & mask) {
-			struct inotify_device *dev = watch->dev;
-			get_inotify_watch(watch);
-			mutex_lock(&dev->mutex);
-			inotify_dev_queue_event(dev, watch, mask, cookie, name);
+			struct inotify_handle *ih= watch->ih;
+			mutex_lock(&ih->mutex);
 			if (watch_mask & IN_ONESHOT)
-				remove_watch_no_event(watch, dev);
-			mutex_unlock(&dev->mutex);
-			put_inotify_watch(watch);
+				remove_watch_no_event(watch, ih);
+			ih->in_ops->handle_event(watch, watch->wd, mask, cookie,
+						 name, n_inode);
+			mutex_unlock(&ih->mutex);
 		}
 	}
 	mutex_unlock(&inode->inotify_mutex);
@@ -613,7 +330,8 @@
 	if (inotify_inode_watched(inode)) {
 		dget(parent);
 		spin_unlock(&dentry->d_lock);
-		inotify_inode_queue_event(inode, mask, cookie, name);
+		inotify_inode_queue_event(inode, mask, cookie, name,
+					  dentry->d_inode);
 		dput(parent);
 	} else
 		spin_unlock(&dentry->d_lock);
@@ -665,7 +383,7 @@
 
 		need_iput_tmp = need_iput;
 		need_iput = NULL;
-		/* In case the remove_watch() drops a reference. */
+		/* In case inotify_remove_watch_locked() drops a reference. */
 		if (inode != need_iput_tmp)
 			__iget(inode);
 		else
@@ -694,11 +412,12 @@
 		mutex_lock(&inode->inotify_mutex);
 		watches = &inode->inotify_watches;
 		list_for_each_entry_safe(watch, next_w, watches, i_list) {
-			struct inotify_device *dev = watch->dev;
-			mutex_lock(&dev->mutex);
-			inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL);
-			remove_watch(watch, dev);
-			mutex_unlock(&dev->mutex);
+			struct inotify_handle *ih= watch->ih;
+			mutex_lock(&ih->mutex);
+			ih->in_ops->handle_event(watch, watch->wd, IN_UNMOUNT, 0,
+						 NULL, NULL);
+			inotify_remove_watch_locked(ih, watch);
+			mutex_unlock(&ih->mutex);
 		}
 		mutex_unlock(&inode->inotify_mutex);
 		iput(inode);		
@@ -718,432 +437,292 @@
 
 	mutex_lock(&inode->inotify_mutex);
 	list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) {
-		struct inotify_device *dev = watch->dev;
-		mutex_lock(&dev->mutex);
-		remove_watch(watch, dev);
-		mutex_unlock(&dev->mutex);
+		struct inotify_handle *ih = watch->ih;
+		mutex_lock(&ih->mutex);
+		inotify_remove_watch_locked(ih, watch);
+		mutex_unlock(&ih->mutex);
 	}
 	mutex_unlock(&inode->inotify_mutex);
 }
 EXPORT_SYMBOL_GPL(inotify_inode_is_dead);
 
-/* Device Interface */
+/* Kernel Consumer API */
 
-static unsigned int inotify_poll(struct file *file, poll_table *wait)
+/**
+ * inotify_init - allocate and initialize an inotify instance
+ * @ops: caller's inotify operations
+ */
+struct inotify_handle *inotify_init(const struct inotify_operations *ops)
 {
-	struct inotify_device *dev = file->private_data;
-	int ret = 0;
+	struct inotify_handle *ih;
 
-	poll_wait(file, &dev->wq, wait);
-	mutex_lock(&dev->mutex);
-	if (!list_empty(&dev->events))
-		ret = POLLIN | POLLRDNORM;
-	mutex_unlock(&dev->mutex);
+	ih = kmalloc(sizeof(struct inotify_handle), GFP_KERNEL);
+	if (unlikely(!ih))
+		return ERR_PTR(-ENOMEM);
 
-	return ret;
+	idr_init(&ih->idr);
+	INIT_LIST_HEAD(&ih->watches);
+	mutex_init(&ih->mutex);
+	ih->last_wd = 0;
+	ih->in_ops = ops;
+	atomic_set(&ih->count, 0);
+	get_inotify_handle(ih);
+
+	return ih;
 }
+EXPORT_SYMBOL_GPL(inotify_init);
 
-static ssize_t inotify_read(struct file *file, char __user *buf,
-			    size_t count, loff_t *pos)
+/**
+ * inotify_init_watch - initialize an inotify watch
+ * @watch: watch to initialize
+ */
+void inotify_init_watch(struct inotify_watch *watch)
 {
-	size_t event_size = sizeof (struct inotify_event);
-	struct inotify_device *dev;
-	char __user *start;
-	int ret;
-	DEFINE_WAIT(wait);
-
-	start = buf;
-	dev = file->private_data;
-
-	while (1) {
-		int events;
-
-		prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
-
-		mutex_lock(&dev->mutex);
-		events = !list_empty(&dev->events);
-		mutex_unlock(&dev->mutex);
-		if (events) {
-			ret = 0;
-			break;
-		}
-
-		if (file->f_flags & O_NONBLOCK) {
-			ret = -EAGAIN;
-			break;
-		}
-
-		if (signal_pending(current)) {
-			ret = -EINTR;
-			break;
-		}
-
-		schedule();
-	}
-
-	finish_wait(&dev->wq, &wait);
-	if (ret)
-		return ret;
-
-	mutex_lock(&dev->mutex);
-	while (1) {
-		struct inotify_kernel_event *kevent;
-
-		ret = buf - start;
-		if (list_empty(&dev->events))
-			break;
-
-		kevent = inotify_dev_get_event(dev);
-		if (event_size + kevent->event.len > count)
-			break;
-
-		if (copy_to_user(buf, &kevent->event, event_size)) {
-			ret = -EFAULT;
-			break;
-		}
-		buf += event_size;
-		count -= event_size;
-
-		if (kevent->name) {
-			if (copy_to_user(buf, kevent->name, kevent->event.len)){
-				ret = -EFAULT;
-				break;
-			}
-			buf += kevent->event.len;
-			count -= kevent->event.len;
-		}
-
-		remove_kevent(dev, kevent);
-	}
-	mutex_unlock(&dev->mutex);
-
-	return ret;
+	INIT_LIST_HEAD(&watch->h_list);
+	INIT_LIST_HEAD(&watch->i_list);
+	atomic_set(&watch->count, 0);
+	get_inotify_watch(watch); /* initial get */
 }
+EXPORT_SYMBOL_GPL(inotify_init_watch);
 
-static int inotify_release(struct inode *ignored, struct file *file)
+/**
+ * inotify_destroy - clean up and destroy an inotify instance
+ * @ih: inotify handle
+ */
+void inotify_destroy(struct inotify_handle *ih)
 {
-	struct inotify_device *dev = file->private_data;
-
 	/*
-	 * Destroy all of the watches on this device.  Unfortunately, not very
+	 * Destroy all of the watches for this handle. Unfortunately, not very
 	 * pretty.  We cannot do a simple iteration over the list, because we
 	 * do not know the inode until we iterate to the watch.  But we need to
-	 * hold inode->inotify_mutex before dev->mutex.  The following works.
+	 * hold inode->inotify_mutex before ih->mutex.  The following works.
 	 */
 	while (1) {
 		struct inotify_watch *watch;
 		struct list_head *watches;
 		struct inode *inode;
 
-		mutex_lock(&dev->mutex);
-		watches = &dev->watches;
+		mutex_lock(&ih->mutex);
+		watches = &ih->watches;
 		if (list_empty(watches)) {
-			mutex_unlock(&dev->mutex);
+			mutex_unlock(&ih->mutex);
 			break;
 		}
-		watch = list_entry(watches->next, struct inotify_watch, d_list);
+		watch = list_entry(watches->next, struct inotify_watch, h_list);
 		get_inotify_watch(watch);
-		mutex_unlock(&dev->mutex);
+		mutex_unlock(&ih->mutex);
 
 		inode = watch->inode;
 		mutex_lock(&inode->inotify_mutex);
-		mutex_lock(&dev->mutex);
+		mutex_lock(&ih->mutex);
 
 		/* make sure we didn't race with another list removal */
-		if (likely(idr_find(&dev->idr, watch->wd)))
-			remove_watch_no_event(watch, dev);
+		if (likely(idr_find(&ih->idr, watch->wd))) {
+			remove_watch_no_event(watch, ih);
+			put_inotify_watch(watch);
+		}
 
-		mutex_unlock(&dev->mutex);
+		mutex_unlock(&ih->mutex);
 		mutex_unlock(&inode->inotify_mutex);
 		put_inotify_watch(watch);
 	}
 
-	/* destroy all of the events on this device */
-	mutex_lock(&dev->mutex);
-	while (!list_empty(&dev->events))
-		inotify_dev_event_dequeue(dev);
-	mutex_unlock(&dev->mutex);
-
-	/* free this device: the put matching the get in inotify_init() */
-	put_inotify_dev(dev);
-
-	return 0;
+	/* free this handle: the put matching the get in inotify_init() */
+	put_inotify_handle(ih);
 }
+EXPORT_SYMBOL_GPL(inotify_destroy);
 
-/*
- * inotify_ignore - remove a given wd from this inotify instance.
+/**
+ * inotify_find_watch - find an existing watch for an (ih,inode) pair
+ * @ih: inotify handle
+ * @inode: inode to watch
+ * @watchp: pointer to existing inotify_watch
+ *
+ * Caller must pin given inode (via nameidata).
+ */
+s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode,
+		       struct inotify_watch **watchp)
+{
+	struct inotify_watch *old;
+	int ret = -ENOENT;
+
+	mutex_lock(&inode->inotify_mutex);
+	mutex_lock(&ih->mutex);
+
+	old = inode_find_handle(inode, ih);
+	if (unlikely(old)) {
+		get_inotify_watch(old); /* caller must put watch */
+		*watchp = old;
+		ret = old->wd;
+	}
+
+	mutex_unlock(&ih->mutex);
+	mutex_unlock(&inode->inotify_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(inotify_find_watch);
+
+/**
+ * inotify_find_update_watch - find and update the mask of an existing watch
+ * @ih: inotify handle
+ * @inode: inode's watch to update
+ * @mask: mask of events to watch
+ *
+ * Caller must pin given inode (via nameidata).
+ */
+s32 inotify_find_update_watch(struct inotify_handle *ih, struct inode *inode,
+			      u32 mask)
+{
+	struct inotify_watch *old;
+	int mask_add = 0;
+	int ret;
+
+	if (mask & IN_MASK_ADD)
+		mask_add = 1;
+
+	/* don't allow invalid bits: we don't want flags set */
+	mask &= IN_ALL_EVENTS | IN_ONESHOT;
+	if (unlikely(!mask))
+		return -EINVAL;
+
+	mutex_lock(&inode->inotify_mutex);
+	mutex_lock(&ih->mutex);
+
+	/*
+	 * Handle the case of re-adding a watch on an (inode,ih) pair that we
+	 * are already watching.  We just update the mask and return its wd.
+	 */
+	old = inode_find_handle(inode, ih);
+	if (unlikely(!old)) {
+		ret = -ENOENT;
+		goto out;
+	}
+
+	if (mask_add)
+		old->mask |= mask;
+	else
+		old->mask = mask;
+	ret = old->wd;
+out:
+	mutex_unlock(&ih->mutex);
+	mutex_unlock(&inode->inotify_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(inotify_find_update_watch);
+
+/**
+ * inotify_add_watch - add a watch to an inotify instance
+ * @ih: inotify handle
+ * @watch: caller allocated watch structure
+ * @inode: inode to watch
+ * @mask: mask of events to watch
+ *
+ * Caller must pin given inode (via nameidata).
+ * Caller must ensure it only calls inotify_add_watch() once per watch.
+ * Calls inotify_handle_get_wd() so may sleep.
+ */
+s32 inotify_add_watch(struct inotify_handle *ih, struct inotify_watch *watch,
+		      struct inode *inode, u32 mask)
+{
+	int ret = 0;
+
+	/* don't allow invalid bits: we don't want flags set */
+	mask &= IN_ALL_EVENTS | IN_ONESHOT;
+	if (unlikely(!mask))
+		return -EINVAL;
+	watch->mask = mask;
+
+	mutex_lock(&inode->inotify_mutex);
+	mutex_lock(&ih->mutex);
+
+	/* Initialize a new watch */
+	ret = inotify_handle_get_wd(ih, watch);
+	if (unlikely(ret))
+		goto out;
+	ret = watch->wd;
+
+	/* save a reference to handle and bump the count to make it official */
+	get_inotify_handle(ih);
+	watch->ih = ih;
+
+	/*
+	 * Save a reference to the inode and bump the ref count to make it
+	 * official.  We hold a reference to nameidata, which makes this safe.
+	 */
+	watch->inode = igrab(inode);
+
+	if (!inotify_inode_watched(inode))
+		set_dentry_child_flags(inode, 1);
+
+	/* Add the watch to the handle's and the inode's list */
+	list_add(&watch->h_list, &ih->watches);
+	list_add(&watch->i_list, &inode->inotify_watches);
+out:
+	mutex_unlock(&ih->mutex);
+	mutex_unlock(&inode->inotify_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(inotify_add_watch);
+
+/**
+ * inotify_rm_wd - remove a watch from an inotify instance
+ * @ih: inotify handle
+ * @wd: watch descriptor to remove
  *
  * Can sleep.
  */
-static int inotify_ignore(struct inotify_device *dev, s32 wd)
+int inotify_rm_wd(struct inotify_handle *ih, u32 wd)
 {
 	struct inotify_watch *watch;
 	struct inode *inode;
 
-	mutex_lock(&dev->mutex);
-	watch = idr_find(&dev->idr, wd);
+	mutex_lock(&ih->mutex);
+	watch = idr_find(&ih->idr, wd);
 	if (unlikely(!watch)) {
-		mutex_unlock(&dev->mutex);
+		mutex_unlock(&ih->mutex);
 		return -EINVAL;
 	}
 	get_inotify_watch(watch);
 	inode = watch->inode;
-	mutex_unlock(&dev->mutex);
+	mutex_unlock(&ih->mutex);
 
 	mutex_lock(&inode->inotify_mutex);
-	mutex_lock(&dev->mutex);
+	mutex_lock(&ih->mutex);
 
 	/* make sure that we did not race */
-	if (likely(idr_find(&dev->idr, wd) == watch))
-		remove_watch(watch, dev);
+	if (likely(idr_find(&ih->idr, wd) == watch))
+		inotify_remove_watch_locked(ih, watch);
 
-	mutex_unlock(&dev->mutex);
+	mutex_unlock(&ih->mutex);
 	mutex_unlock(&inode->inotify_mutex);
 	put_inotify_watch(watch);
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(inotify_rm_wd);
 
-static long inotify_ioctl(struct file *file, unsigned int cmd,
-			  unsigned long arg)
+/**
+ * inotify_rm_watch - remove a watch from an inotify instance
+ * @ih: inotify handle
+ * @watch: watch to remove
+ *
+ * Can sleep.
+ */
+int inotify_rm_watch(struct inotify_handle *ih,
+		     struct inotify_watch *watch)
 {
-	struct inotify_device *dev;
-	void __user *p;
-	int ret = -ENOTTY;
-
-	dev = file->private_data;
-	p = (void __user *) arg;
-
-	switch (cmd) {
-	case FIONREAD:
-		ret = put_user(dev->queue_size, (int __user *) p);
-		break;
-	}
-
-	return ret;
+	return inotify_rm_wd(ih, watch->wd);
 }
-
-static const struct file_operations inotify_fops = {
-	.poll           = inotify_poll,
-	.read           = inotify_read,
-	.release        = inotify_release,
-	.unlocked_ioctl = inotify_ioctl,
-	.compat_ioctl	= inotify_ioctl,
-};
-
-asmlinkage long sys_inotify_init(void)
-{
-	struct inotify_device *dev;
-	struct user_struct *user;
-	struct file *filp;	
-	int fd, ret;
-
-	fd = get_unused_fd();
-	if (fd < 0)
-		return fd;
-
-	filp = get_empty_filp();
-	if (!filp) {
-		ret = -ENFILE;
-		goto out_put_fd;
-	}
-
-	user = get_uid(current->user);
-	if (unlikely(atomic_read(&user->inotify_devs) >=
-			inotify_max_user_instances)) {
-		ret = -EMFILE;
-		goto out_free_uid;
-	}
-
-	dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
-	if (unlikely(!dev)) {
-		ret = -ENOMEM;
-		goto out_free_uid;
-	}
-
-	filp->f_op = &inotify_fops;
-	filp->f_vfsmnt = mntget(inotify_mnt);
-	filp->f_dentry = dget(inotify_mnt->mnt_root);
-	filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
-	filp->f_mode = FMODE_READ;
-	filp->f_flags = O_RDONLY;
-	filp->private_data = dev;
-
-	idr_init(&dev->idr);
-	INIT_LIST_HEAD(&dev->events);
-	INIT_LIST_HEAD(&dev->watches);
-	init_waitqueue_head(&dev->wq);
-	mutex_init(&dev->mutex);
-	dev->event_count = 0;
-	dev->queue_size = 0;
-	dev->max_events = inotify_max_queued_events;
-	dev->user = user;
-	dev->last_wd = 0;
-	atomic_set(&dev->count, 0);
-
-	get_inotify_dev(dev);
-	atomic_inc(&user->inotify_devs);
-	fd_install(fd, filp);
-
-	return fd;
-out_free_uid:
-	free_uid(user);
-	put_filp(filp);
-out_put_fd:
-	put_unused_fd(fd);
-	return ret;
-}
-
-asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
-{
-	struct inotify_watch *watch, *old;
-	struct inode *inode;
-	struct inotify_device *dev;
-	struct nameidata nd;
-	struct file *filp;
-	int ret, fput_needed;
-	int mask_add = 0;
-	unsigned flags = 0;
-
-	filp = fget_light(fd, &fput_needed);
-	if (unlikely(!filp))
-		return -EBADF;
-
-	/* verify that this is indeed an inotify instance */
-	if (unlikely(filp->f_op != &inotify_fops)) {
-		ret = -EINVAL;
-		goto fput_and_out;
-	}
-
-	if (!(mask & IN_DONT_FOLLOW))
-		flags |= LOOKUP_FOLLOW;
-	if (mask & IN_ONLYDIR)
-		flags |= LOOKUP_DIRECTORY;
-
-	ret = find_inode(path, &nd, flags);
-	if (unlikely(ret))
-		goto fput_and_out;
-
-	/* inode held in place by reference to nd; dev by fget on fd */
-	inode = nd.dentry->d_inode;
-	dev = filp->private_data;
-
-	mutex_lock(&inode->inotify_mutex);
-	mutex_lock(&dev->mutex);
-
-	if (mask & IN_MASK_ADD)
-		mask_add = 1;
-
-	/* don't let user-space set invalid bits: we don't want flags set */
-	mask &= IN_ALL_EVENTS | IN_ONESHOT;
-	if (unlikely(!mask)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Handle the case of re-adding a watch on an (inode,dev) pair that we
-	 * are already watching.  We just update the mask and return its wd.
-	 */
-	old = inode_find_dev(inode, dev);
-	if (unlikely(old)) {
-		if (mask_add)
-			old->mask |= mask;
-		else
-			old->mask = mask;
-		ret = old->wd;
-		goto out;
-	}
-
-	watch = create_watch(dev, mask, inode);
-	if (unlikely(IS_ERR(watch))) {
-		ret = PTR_ERR(watch);
-		goto out;
-	}
-
-	if (!inotify_inode_watched(inode))
-		set_dentry_child_flags(inode, 1);
-
-	/* Add the watch to the device's and the inode's list */
-	list_add(&watch->d_list, &dev->watches);
-	list_add(&watch->i_list, &inode->inotify_watches);
-	ret = watch->wd;
-out:
-	mutex_unlock(&dev->mutex);
-	mutex_unlock(&inode->inotify_mutex);
-	path_release(&nd);
-fput_and_out:
-	fput_light(filp, fput_needed);
-	return ret;
-}
-
-asmlinkage long sys_inotify_rm_watch(int fd, u32 wd)
-{
-	struct file *filp;
-	struct inotify_device *dev;
-	int ret, fput_needed;
-
-	filp = fget_light(fd, &fput_needed);
-	if (unlikely(!filp))
-		return -EBADF;
-
-	/* verify that this is indeed an inotify instance */
-	if (unlikely(filp->f_op != &inotify_fops)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	dev = filp->private_data;
-	ret = inotify_ignore(dev, wd);
-
-out:
-	fput_light(filp, fput_needed);
-	return ret;
-}
-
-static struct super_block *
-inotify_get_sb(struct file_system_type *fs_type, int flags,
-	       const char *dev_name, void *data)
-{
-    return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA);
-}
-
-static struct file_system_type inotify_fs_type = {
-    .name           = "inotifyfs",
-    .get_sb         = inotify_get_sb,
-    .kill_sb        = kill_anon_super,
-};
+EXPORT_SYMBOL_GPL(inotify_rm_watch);
 
 /*
- * inotify_setup - Our initialization function.  Note that we cannnot return
- * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
- * must result in panic().
+ * inotify_setup - core initialization function
  */
 static int __init inotify_setup(void)
 {
-	int ret;
-
-	ret = register_filesystem(&inotify_fs_type);
-	if (unlikely(ret))
-		panic("inotify: register_filesystem returned %d!\n", ret);
-
-	inotify_mnt = kern_mount(&inotify_fs_type);
-	if (IS_ERR(inotify_mnt))
-		panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
-
-	inotify_max_queued_events = 16384;
-	inotify_max_user_instances = 128;
-	inotify_max_user_watches = 8192;
-
 	atomic_set(&inotify_cookie, 0);
 
-	watch_cachep = kmem_cache_create("inotify_watch_cache",
-					 sizeof(struct inotify_watch),
-					 0, SLAB_PANIC, NULL, NULL);
-	event_cachep = kmem_cache_create("inotify_event_cache",
-					 sizeof(struct inotify_kernel_event),
-					 0, SLAB_PANIC, NULL, NULL);
-
 	return 0;
 }
 
diff --git a/fs/inotify_user.c b/fs/inotify_user.c
new file mode 100644
index 0000000..f238644
--- /dev/null
+++ b/fs/inotify_user.c
@@ -0,0 +1,719 @@
+/*
+ * fs/inotify_user.c - inotify support for userspace
+ *
+ * Authors:
+ *	John McCutchan	<ttb@tentacle.dhs.org>
+ *	Robert Love	<rml@novell.com>
+ *
+ * Copyright (C) 2005 John McCutchan
+ * Copyright 2006 Hewlett-Packard Development Company, L.P.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/inotify.h>
+#include <linux/syscalls.h>
+
+#include <asm/ioctls.h>
+
+static kmem_cache_t *watch_cachep __read_mostly;
+static kmem_cache_t *event_cachep __read_mostly;
+
+static struct vfsmount *inotify_mnt __read_mostly;
+
+/* these are configurable via /proc/sys/fs/inotify/ */
+int inotify_max_user_instances __read_mostly;
+int inotify_max_user_watches __read_mostly;
+int inotify_max_queued_events __read_mostly;
+
+/*
+ * Lock ordering:
+ *
+ * inotify_dev->up_mutex (ensures we don't re-add the same watch)
+ * 	inode->inotify_mutex (protects inode's watch list)
+ * 		inotify_handle->mutex (protects inotify_handle's watch list)
+ * 			inotify_dev->ev_mutex (protects device's event queue)
+ */
+
+/*
+ * Lifetimes of the main data structures:
+ *
+ * inotify_device: Lifetime is managed by reference count, from
+ * sys_inotify_init() until release.  Additional references can bump the count
+ * via get_inotify_dev() and drop the count via put_inotify_dev().
+ *
+ * inotify_user_watch: Lifetime is from create_watch() to the receipt of an
+ * IN_IGNORED event from inotify, or when using IN_ONESHOT, to receipt of the
+ * first event, or to inotify_destroy().
+ */
+
+/*
+ * struct inotify_device - represents an inotify instance
+ *
+ * This structure is protected by the mutex 'mutex'.
+ */
+struct inotify_device {
+	wait_queue_head_t 	wq;		/* wait queue for i/o */
+	struct mutex		ev_mutex;	/* protects event queue */
+	struct mutex		up_mutex;	/* synchronizes watch updates */
+	struct list_head 	events;		/* list of queued events */
+	atomic_t		count;		/* reference count */
+	struct user_struct	*user;		/* user who opened this dev */
+	struct inotify_handle	*ih;		/* inotify handle */
+	unsigned int		queue_size;	/* size of the queue (bytes) */
+	unsigned int		event_count;	/* number of pending events */
+	unsigned int		max_events;	/* maximum number of events */
+};
+
+/*
+ * struct inotify_kernel_event - An inotify event, originating from a watch and
+ * queued for user-space.  A list of these is attached to each instance of the
+ * device.  In read(), this list is walked and all events that can fit in the
+ * buffer are returned.
+ *
+ * Protected by dev->ev_mutex of the device in which we are queued.
+ */
+struct inotify_kernel_event {
+	struct inotify_event	event;	/* the user-space event */
+	struct list_head        list;	/* entry in inotify_device's list */
+	char			*name;	/* filename, if any */
+};
+
+/*
+ * struct inotify_user_watch - our version of an inotify_watch, we add
+ * a reference to the associated inotify_device.
+ */
+struct inotify_user_watch {
+	struct inotify_device	*dev;	/* associated device */
+	struct inotify_watch	wdata;	/* inotify watch data */
+};
+
+#ifdef CONFIG_SYSCTL
+
+#include <linux/sysctl.h>
+
+static int zero;
+
+ctl_table inotify_table[] = {
+	{
+		.ctl_name	= INOTIFY_MAX_USER_INSTANCES,
+		.procname	= "max_user_instances",
+		.data		= &inotify_max_user_instances,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+	{
+		.ctl_name	= INOTIFY_MAX_USER_WATCHES,
+		.procname	= "max_user_watches",
+		.data		= &inotify_max_user_watches,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+	{
+		.ctl_name	= INOTIFY_MAX_QUEUED_EVENTS,
+		.procname	= "max_queued_events",
+		.data		= &inotify_max_queued_events,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_minmax,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero
+	},
+	{ .ctl_name = 0 }
+};
+#endif /* CONFIG_SYSCTL */
+
+static inline void get_inotify_dev(struct inotify_device *dev)
+{
+	atomic_inc(&dev->count);
+}
+
+static inline void put_inotify_dev(struct inotify_device *dev)
+{
+	if (atomic_dec_and_test(&dev->count)) {
+		atomic_dec(&dev->user->inotify_devs);
+		free_uid(dev->user);
+		kfree(dev);
+	}
+}
+
+/*
+ * free_inotify_user_watch - cleans up the watch and its references
+ */
+static void free_inotify_user_watch(struct inotify_watch *w)
+{
+	struct inotify_user_watch *watch;
+	struct inotify_device *dev;
+
+	watch = container_of(w, struct inotify_user_watch, wdata);
+	dev = watch->dev;
+
+	atomic_dec(&dev->user->inotify_watches);
+	put_inotify_dev(dev);
+	kmem_cache_free(watch_cachep, watch);
+}
+
+/*
+ * kernel_event - create a new kernel event with the given parameters
+ *
+ * This function can sleep.
+ */
+static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie,
+						  const char *name)
+{
+	struct inotify_kernel_event *kevent;
+
+	kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL);
+	if (unlikely(!kevent))
+		return NULL;
+
+	/* we hand this out to user-space, so zero it just in case */
+	memset(&kevent->event, 0, sizeof(struct inotify_event));
+
+	kevent->event.wd = wd;
+	kevent->event.mask = mask;
+	kevent->event.cookie = cookie;
+
+	INIT_LIST_HEAD(&kevent->list);
+
+	if (name) {
+		size_t len, rem, event_size = sizeof(struct inotify_event);
+
+		/*
+		 * We need to pad the filename so as to properly align an
+		 * array of inotify_event structures.  Because the structure is
+		 * small and the common case is a small filename, we just round
+		 * up to the next multiple of the structure's sizeof.  This is
+		 * simple and safe for all architectures.
+		 */
+		len = strlen(name) + 1;
+		rem = event_size - len;
+		if (len > event_size) {
+			rem = event_size - (len % event_size);
+			if (len % event_size == 0)
+				rem = 0;
+		}
+
+		kevent->name = kmalloc(len + rem, GFP_KERNEL);
+		if (unlikely(!kevent->name)) {
+			kmem_cache_free(event_cachep, kevent);
+			return NULL;
+		}
+		memcpy(kevent->name, name, len);
+		if (rem)
+			memset(kevent->name + len, 0, rem);
+		kevent->event.len = len + rem;
+	} else {
+		kevent->event.len = 0;
+		kevent->name = NULL;
+	}
+
+	return kevent;
+}
+
+/*
+ * inotify_dev_get_event - return the next event in the given dev's queue
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static inline struct inotify_kernel_event *
+inotify_dev_get_event(struct inotify_device *dev)
+{
+	return list_entry(dev->events.next, struct inotify_kernel_event, list);
+}
+
+/*
+ * inotify_dev_queue_event - event handler registered with core inotify, adds
+ * a new event to the given device
+ *
+ * Can sleep (calls kernel_event()).
+ */
+static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask,
+				    u32 cookie, const char *name,
+				    struct inode *ignored)
+{
+	struct inotify_user_watch *watch;
+	struct inotify_device *dev;
+	struct inotify_kernel_event *kevent, *last;
+
+	watch = container_of(w, struct inotify_user_watch, wdata);
+	dev = watch->dev;
+
+	mutex_lock(&dev->ev_mutex);
+
+	/* we can safely put the watch as we don't reference it while
+	 * generating the event
+	 */
+	if (mask & IN_IGNORED || mask & IN_ONESHOT)
+		put_inotify_watch(w); /* final put */
+
+	/* coalescing: drop this event if it is a dupe of the previous */
+	last = inotify_dev_get_event(dev);
+	if (last && last->event.mask == mask && last->event.wd == wd &&
+			last->event.cookie == cookie) {
+		const char *lastname = last->name;
+
+		if (!name && !lastname)
+			goto out;
+		if (name && lastname && !strcmp(lastname, name))
+			goto out;
+	}
+
+	/* the queue overflowed and we already sent the Q_OVERFLOW event */
+	if (unlikely(dev->event_count > dev->max_events))
+		goto out;
+
+	/* if the queue overflows, we need to notify user space */
+	if (unlikely(dev->event_count == dev->max_events))
+		kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL);
+	else
+		kevent = kernel_event(wd, mask, cookie, name);
+
+	if (unlikely(!kevent))
+		goto out;
+
+	/* queue the event and wake up anyone waiting */
+	dev->event_count++;
+	dev->queue_size += sizeof(struct inotify_event) + kevent->event.len;
+	list_add_tail(&kevent->list, &dev->events);
+	wake_up_interruptible(&dev->wq);
+
+out:
+	mutex_unlock(&dev->ev_mutex);
+}
+
+/*
+ * remove_kevent - cleans up and ultimately frees the given kevent
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static void remove_kevent(struct inotify_device *dev,
+			  struct inotify_kernel_event *kevent)
+{
+	list_del(&kevent->list);
+
+	dev->event_count--;
+	dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len;
+
+	kfree(kevent->name);
+	kmem_cache_free(event_cachep, kevent);
+}
+
+/*
+ * inotify_dev_event_dequeue - destroy an event on the given device
+ *
+ * Caller must hold dev->ev_mutex.
+ */
+static void inotify_dev_event_dequeue(struct inotify_device *dev)
+{
+	if (!list_empty(&dev->events)) {
+		struct inotify_kernel_event *kevent;
+		kevent = inotify_dev_get_event(dev);
+		remove_kevent(dev, kevent);
+	}
+}
+
+/*
+ * find_inode - resolve a user-given path to a specific inode and return a nd
+ */
+static int find_inode(const char __user *dirname, struct nameidata *nd,
+		      unsigned flags)
+{
+	int error;
+
+	error = __user_walk(dirname, flags, nd);
+	if (error)
+		return error;
+	/* you can only watch an inode if you have read permissions on it */
+	error = vfs_permission(nd, MAY_READ);
+	if (error)
+		path_release(nd);
+	return error;
+}
+
+/*
+ * create_watch - creates a watch on the given device.
+ *
+ * Callers must hold dev->up_mutex.
+ */
+static int create_watch(struct inotify_device *dev, struct inode *inode,
+			u32 mask)
+{
+	struct inotify_user_watch *watch;
+	int ret;
+
+	if (atomic_read(&dev->user->inotify_watches) >=
+			inotify_max_user_watches)
+		return -ENOSPC;
+
+	watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL);
+	if (unlikely(!watch))
+		return -ENOMEM;
+
+	/* save a reference to device and bump the count to make it official */
+	get_inotify_dev(dev);
+	watch->dev = dev;
+
+	atomic_inc(&dev->user->inotify_watches);
+
+	inotify_init_watch(&watch->wdata);
+	ret = inotify_add_watch(dev->ih, &watch->wdata, inode, mask);
+	if (ret < 0)
+		free_inotify_user_watch(&watch->wdata);
+
+	return ret;
+}
+
+/* Device Interface */
+
+static unsigned int inotify_poll(struct file *file, poll_table *wait)
+{
+	struct inotify_device *dev = file->private_data;
+	int ret = 0;
+
+	poll_wait(file, &dev->wq, wait);
+	mutex_lock(&dev->ev_mutex);
+	if (!list_empty(&dev->events))
+		ret = POLLIN | POLLRDNORM;
+	mutex_unlock(&dev->ev_mutex);
+
+	return ret;
+}
+
+static ssize_t inotify_read(struct file *file, char __user *buf,
+			    size_t count, loff_t *pos)
+{
+	size_t event_size = sizeof (struct inotify_event);
+	struct inotify_device *dev;
+	char __user *start;
+	int ret;
+	DEFINE_WAIT(wait);
+
+	start = buf;
+	dev = file->private_data;
+
+	while (1) {
+		int events;
+
+		prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE);
+
+		mutex_lock(&dev->ev_mutex);
+		events = !list_empty(&dev->events);
+		mutex_unlock(&dev->ev_mutex);
+		if (events) {
+			ret = 0;
+			break;
+		}
+
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			break;
+		}
+
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+
+		schedule();
+	}
+
+	finish_wait(&dev->wq, &wait);
+	if (ret)
+		return ret;
+
+	mutex_lock(&dev->ev_mutex);
+	while (1) {
+		struct inotify_kernel_event *kevent;
+
+		ret = buf - start;
+		if (list_empty(&dev->events))
+			break;
+
+		kevent = inotify_dev_get_event(dev);
+		if (event_size + kevent->event.len > count)
+			break;
+
+		if (copy_to_user(buf, &kevent->event, event_size)) {
+			ret = -EFAULT;
+			break;
+		}
+		buf += event_size;
+		count -= event_size;
+
+		if (kevent->name) {
+			if (copy_to_user(buf, kevent->name, kevent->event.len)){
+				ret = -EFAULT;
+				break;
+			}
+			buf += kevent->event.len;
+			count -= kevent->event.len;
+		}
+
+		remove_kevent(dev, kevent);
+	}
+	mutex_unlock(&dev->ev_mutex);
+
+	return ret;
+}
+
+static int inotify_release(struct inode *ignored, struct file *file)
+{
+	struct inotify_device *dev = file->private_data;
+
+	inotify_destroy(dev->ih);
+
+	/* destroy all of the events on this device */
+	mutex_lock(&dev->ev_mutex);
+	while (!list_empty(&dev->events))
+		inotify_dev_event_dequeue(dev);
+	mutex_unlock(&dev->ev_mutex);
+
+	/* free this device: the put matching the get in inotify_init() */
+	put_inotify_dev(dev);
+
+	return 0;
+}
+
+static long inotify_ioctl(struct file *file, unsigned int cmd,
+			  unsigned long arg)
+{
+	struct inotify_device *dev;
+	void __user *p;
+	int ret = -ENOTTY;
+
+	dev = file->private_data;
+	p = (void __user *) arg;
+
+	switch (cmd) {
+	case FIONREAD:
+		ret = put_user(dev->queue_size, (int __user *) p);
+		break;
+	}
+
+	return ret;
+}
+
+static const struct file_operations inotify_fops = {
+	.poll           = inotify_poll,
+	.read           = inotify_read,
+	.release        = inotify_release,
+	.unlocked_ioctl = inotify_ioctl,
+	.compat_ioctl	= inotify_ioctl,
+};
+
+static const struct inotify_operations inotify_user_ops = {
+	.handle_event	= inotify_dev_queue_event,
+	.destroy_watch	= free_inotify_user_watch,
+};
+
+asmlinkage long sys_inotify_init(void)
+{
+	struct inotify_device *dev;
+	struct inotify_handle *ih;
+	struct user_struct *user;
+	struct file *filp;
+	int fd, ret;
+
+	fd = get_unused_fd();
+	if (fd < 0)
+		return fd;
+
+	filp = get_empty_filp();
+	if (!filp) {
+		ret = -ENFILE;
+		goto out_put_fd;
+	}
+
+	user = get_uid(current->user);
+	if (unlikely(atomic_read(&user->inotify_devs) >=
+			inotify_max_user_instances)) {
+		ret = -EMFILE;
+		goto out_free_uid;
+	}
+
+	dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL);
+	if (unlikely(!dev)) {
+		ret = -ENOMEM;
+		goto out_free_uid;
+	}
+
+	ih = inotify_init(&inotify_user_ops);
+	if (unlikely(IS_ERR(ih))) {
+		ret = PTR_ERR(ih);
+		goto out_free_dev;
+	}
+	dev->ih = ih;
+
+	filp->f_op = &inotify_fops;
+	filp->f_vfsmnt = mntget(inotify_mnt);
+	filp->f_dentry = dget(inotify_mnt->mnt_root);
+	filp->f_mapping = filp->f_dentry->d_inode->i_mapping;
+	filp->f_mode = FMODE_READ;
+	filp->f_flags = O_RDONLY;
+	filp->private_data = dev;
+
+	INIT_LIST_HEAD(&dev->events);
+	init_waitqueue_head(&dev->wq);
+	mutex_init(&dev->ev_mutex);
+	mutex_init(&dev->up_mutex);
+	dev->event_count = 0;
+	dev->queue_size = 0;
+	dev->max_events = inotify_max_queued_events;
+	dev->user = user;
+	atomic_set(&dev->count, 0);
+
+	get_inotify_dev(dev);
+	atomic_inc(&user->inotify_devs);
+	fd_install(fd, filp);
+
+	return fd;
+out_free_dev:
+	kfree(dev);
+out_free_uid:
+	free_uid(user);
+	put_filp(filp);
+out_put_fd:
+	put_unused_fd(fd);
+	return ret;
+}
+
+asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask)
+{
+	struct inode *inode;
+	struct inotify_device *dev;
+	struct nameidata nd;
+	struct file *filp;
+	int ret, fput_needed;
+	unsigned flags = 0;
+
+	filp = fget_light(fd, &fput_needed);
+	if (unlikely(!filp))
+		return -EBADF;
+
+	/* verify that this is indeed an inotify instance */
+	if (unlikely(filp->f_op != &inotify_fops)) {
+		ret = -EINVAL;
+		goto fput_and_out;
+	}
+
+	if (!(mask & IN_DONT_FOLLOW))
+		flags |= LOOKUP_FOLLOW;
+	if (mask & IN_ONLYDIR)
+		flags |= LOOKUP_DIRECTORY;
+
+	ret = find_inode(path, &nd, flags);
+	if (unlikely(ret))
+		goto fput_and_out;
+
+	/* inode held in place by reference to nd; dev by fget on fd */
+	inode = nd.dentry->d_inode;
+	dev = filp->private_data;
+
+	mutex_lock(&dev->up_mutex);
+	ret = inotify_find_update_watch(dev->ih, inode, mask);
+	if (ret == -ENOENT)
+		ret = create_watch(dev, inode, mask);
+	mutex_unlock(&dev->up_mutex);
+
+	path_release(&nd);
+fput_and_out:
+	fput_light(filp, fput_needed);
+	return ret;
+}
+
+asmlinkage long sys_inotify_rm_watch(int fd, u32 wd)
+{
+	struct file *filp;
+	struct inotify_device *dev;
+	int ret, fput_needed;
+
+	filp = fget_light(fd, &fput_needed);
+	if (unlikely(!filp))
+		return -EBADF;
+
+	/* verify that this is indeed an inotify instance */
+	if (unlikely(filp->f_op != &inotify_fops)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	dev = filp->private_data;
+
+	/* we free our watch data when we get IN_IGNORED */
+	ret = inotify_rm_wd(dev->ih, wd);
+
+out:
+	fput_light(filp, fput_needed);
+	return ret;
+}
+
+static int
+inotify_get_sb(struct file_system_type *fs_type, int flags,
+	       const char *dev_name, void *data, struct vfsmount *mnt)
+{
+	return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt);
+}
+
+static struct file_system_type inotify_fs_type = {
+    .name           = "inotifyfs",
+    .get_sb         = inotify_get_sb,
+    .kill_sb        = kill_anon_super,
+};
+
+/*
+ * inotify_user_setup - Our initialization function.  Note that we cannnot return
+ * error because we have compiled-in VFS hooks.  So an (unlikely) failure here
+ * must result in panic().
+ */
+static int __init inotify_user_setup(void)
+{
+	int ret;
+
+	ret = register_filesystem(&inotify_fs_type);
+	if (unlikely(ret))
+		panic("inotify: register_filesystem returned %d!\n", ret);
+
+	inotify_mnt = kern_mount(&inotify_fs_type);
+	if (IS_ERR(inotify_mnt))
+		panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt));
+
+	inotify_max_queued_events = 16384;
+	inotify_max_user_instances = 128;
+	inotify_max_user_watches = 8192;
+
+	watch_cachep = kmem_cache_create("inotify_watch_cache",
+					 sizeof(struct inotify_user_watch),
+					 0, SLAB_PANIC, NULL, NULL);
+	event_cachep = kmem_cache_create("inotify_event_cache",
+					 sizeof(struct inotify_kernel_event),
+					 0, SLAB_PANIC, NULL, NULL);
+
+	return 0;
+}
+
+module_init(inotify_user_setup);
diff --git a/fs/ioprio.c b/fs/ioprio.c
index ca77008..7fa76ed 100644
--- a/fs/ioprio.c
+++ b/fs/ioprio.c
@@ -24,15 +24,21 @@
 #include <linux/blkdev.h>
 #include <linux/capability.h>
 #include <linux/syscalls.h>
+#include <linux/security.h>
 
 static int set_task_ioprio(struct task_struct *task, int ioprio)
 {
+	int err;
 	struct io_context *ioc;
 
 	if (task->uid != current->euid &&
 	    task->uid != current->uid && !capable(CAP_SYS_NICE))
 		return -EPERM;
 
+	err = security_task_setioprio(task, ioprio);
+	if (err)
+		return err;
+
 	task_lock(task);
 
 	task->ioprio = ioprio;
diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c
index 4917315..3a39158 100644
--- a/fs/isofs/compress.c
+++ b/fs/isofs/compress.c
@@ -312,7 +312,7 @@
 	return err;
 }
 
-struct address_space_operations zisofs_aops = {
+const struct address_space_operations zisofs_aops = {
 	.readpage = zisofs_readpage,
 	/* No sync_page operation supported? */
 	/* No bmap operation supported */
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 70adbb9..bb11c7f 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -56,7 +56,7 @@
 }
 
 static void isofs_read_inode(struct inode *);
-static int isofs_statfs (struct super_block *, struct kstatfs *);
+static int isofs_statfs (struct dentry *, struct kstatfs *);
 
 static kmem_cache_t *isofs_inode_cachep;
 
@@ -901,8 +901,10 @@
 	return -EINVAL;
 }
 
-static int isofs_statfs (struct super_block *sb, struct kstatfs *buf)
+static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
+
 	buf->f_type = ISOFS_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = (ISOFS_SB(sb)->s_nzones
@@ -1052,7 +1054,7 @@
 	return generic_block_bmap(mapping,block,isofs_get_block);
 }
 
-static struct address_space_operations isofs_aops = {
+static const struct address_space_operations isofs_aops = {
 	.readpage = isofs_readpage,
 	.sync_page = block_sync_page,
 	.bmap = _isofs_bmap
@@ -1399,10 +1401,11 @@
 	return inode;
 }
 
-static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int isofs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type iso9660_fs_type = {
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index b87ba06..e6308c8 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -176,5 +176,5 @@
 
 extern struct inode_operations isofs_dir_inode_operations;
 extern const struct file_operations isofs_dir_operations;
-extern struct address_space_operations isofs_symlink_aops;
+extern const struct address_space_operations isofs_symlink_aops;
 extern struct export_operations isofs_export_ops;
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 4326cb4..f3a1db3 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -754,6 +754,6 @@
 	return -EIO;
 }
 
-struct address_space_operations isofs_symlink_aops = {
+const struct address_space_operations isofs_symlink_aops = {
 	.readpage = rock_ridge_symlink_readpage
 };
diff --git a/fs/isofs/zisofs.h b/fs/isofs/zisofs.h
index d78485d..2737957 100644
--- a/fs/isofs/zisofs.h
+++ b/fs/isofs/zisofs.h
@@ -15,7 +15,7 @@
  */
 
 #ifdef CONFIG_ZISOFS
-extern struct address_space_operations zisofs_aops;
+extern const struct address_space_operations zisofs_aops;
 extern int __init zisofs_init(void);
 extern void zisofs_cleanup(void);
 #endif
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 3f5102b..47678a2 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -24,29 +24,67 @@
 #include <linux/slab.h>
 
 /*
- * Unlink a buffer from a transaction.
+ * Unlink a buffer from a transaction checkpoint list.
  *
  * Called with j_list_lock held.
  */
-
-static inline void __buffer_unlink(struct journal_head *jh)
+static inline void __buffer_unlink_first(struct journal_head *jh)
 {
-	transaction_t *transaction;
-
-	transaction = jh->b_cp_transaction;
-	jh->b_cp_transaction = NULL;
+	transaction_t *transaction = jh->b_cp_transaction;
 
 	jh->b_cpnext->b_cpprev = jh->b_cpprev;
 	jh->b_cpprev->b_cpnext = jh->b_cpnext;
-	if (transaction->t_checkpoint_list == jh)
+	if (transaction->t_checkpoint_list == jh) {
 		transaction->t_checkpoint_list = jh->b_cpnext;
-	if (transaction->t_checkpoint_list == jh)
-		transaction->t_checkpoint_list = NULL;
+		if (transaction->t_checkpoint_list == jh)
+			transaction->t_checkpoint_list = NULL;
+	}
+}
+
+/*
+ * Unlink a buffer from a transaction checkpoint(io) list.
+ *
+ * Called with j_list_lock held.
+ */
+static inline void __buffer_unlink(struct journal_head *jh)
+{
+	transaction_t *transaction = jh->b_cp_transaction;
+
+	__buffer_unlink_first(jh);
+	if (transaction->t_checkpoint_io_list == jh) {
+		transaction->t_checkpoint_io_list = jh->b_cpnext;
+		if (transaction->t_checkpoint_io_list == jh)
+			transaction->t_checkpoint_io_list = NULL;
+	}
+}
+
+/*
+ * Move a buffer from the checkpoint list to the checkpoint io list
+ *
+ * Called with j_list_lock held
+ */
+static inline void __buffer_relink_io(struct journal_head *jh)
+{
+	transaction_t *transaction = jh->b_cp_transaction;
+
+	__buffer_unlink_first(jh);
+
+	if (!transaction->t_checkpoint_io_list) {
+		jh->b_cpnext = jh->b_cpprev = jh;
+	} else {
+		jh->b_cpnext = transaction->t_checkpoint_io_list;
+		jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
+		jh->b_cpprev->b_cpnext = jh;
+		jh->b_cpnext->b_cpprev = jh;
+	}
+	transaction->t_checkpoint_io_list = jh;
 }
 
 /*
  * Try to release a checkpointed buffer from its transaction.
- * Returns 1 if we released it.
+ * Returns 1 if we released it and 2 if we also released the
+ * whole transaction.
+ *
  * Requires j_list_lock
  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
  */
@@ -57,12 +95,11 @@
 
 	if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) {
 		JBUFFER_TRACE(jh, "remove from checkpoint list");
-		__journal_remove_checkpoint(jh);
+		ret = __journal_remove_checkpoint(jh) + 1;
 		jbd_unlock_bh_state(bh);
 		journal_remove_journal_head(bh);
 		BUFFER_TRACE(bh, "release");
 		__brelse(bh);
-		ret = 1;
 	} else {
 		jbd_unlock_bh_state(bh);
 	}
@@ -117,83 +154,54 @@
 }
 
 /*
- * Clean up a transaction's checkpoint list.
- *
- * We wait for any pending IO to complete and make sure any clean
- * buffers are removed from the transaction.
- *
- * Return 1 if we performed any actions which might have destroyed the
- * checkpoint.  (journal_remove_checkpoint() deletes the transaction when
- * the last checkpoint buffer is cleansed)
+ * Clean up transaction's list of buffers submitted for io.
+ * We wait for any pending IO to complete and remove any clean
+ * buffers. Note that we take the buffers in the opposite ordering
+ * from the one in which they were submitted for IO.
  *
  * Called with j_list_lock held.
  */
-static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
+static void __wait_cp_io(journal_t *journal, transaction_t *transaction)
 {
-	struct journal_head *jh, *next_jh, *last_jh;
+	struct journal_head *jh;
 	struct buffer_head *bh;
-	int ret = 0;
+	tid_t this_tid;
+	int released = 0;
 
-	assert_spin_locked(&journal->j_list_lock);
-	jh = transaction->t_checkpoint_list;
-	if (!jh)
-		return 0;
-
-	last_jh = jh->b_cpprev;
-	next_jh = jh;
-	do {
-		jh = next_jh;
+	this_tid = transaction->t_tid;
+restart:
+	/* Did somebody clean up the transaction in the meanwhile? */
+	if (journal->j_checkpoint_transactions != transaction ||
+			transaction->t_tid != this_tid)
+		return;
+	while (!released && transaction->t_checkpoint_io_list) {
+		jh = transaction->t_checkpoint_io_list;
 		bh = jh2bh(jh);
+		if (!jbd_trylock_bh_state(bh)) {
+			jbd_sync_bh(journal, bh);
+			spin_lock(&journal->j_list_lock);
+			goto restart;
+		}
 		if (buffer_locked(bh)) {
 			atomic_inc(&bh->b_count);
 			spin_unlock(&journal->j_list_lock);
+			jbd_unlock_bh_state(bh);
 			wait_on_buffer(bh);
 			/* the journal_head may have gone by now */
 			BUFFER_TRACE(bh, "brelse");
 			__brelse(bh);
-			goto out_return_1;
+			spin_lock(&journal->j_list_lock);
+			goto restart;
 		}
-
 		/*
-		 * This is foul
+		 * Now in whatever state the buffer currently is, we know that
+		 * it has been written out and so we can drop it from the list
 		 */
-		if (!jbd_trylock_bh_state(bh)) {
-			jbd_sync_bh(journal, bh);
-			goto out_return_1;
-		}
-
-		if (jh->b_transaction != NULL) {
-			transaction_t *t = jh->b_transaction;
-			tid_t tid = t->t_tid;
-
-			spin_unlock(&journal->j_list_lock);
-			jbd_unlock_bh_state(bh);
-			log_start_commit(journal, tid);
-			log_wait_commit(journal, tid);
-			goto out_return_1;
-		}
-
-		/*
-		 * AKPM: I think the buffer_jbddirty test is redundant - it
-		 * shouldn't have NULL b_transaction?
-		 */
-		next_jh = jh->b_cpnext;
-		if (!buffer_dirty(bh) && !buffer_jbddirty(bh)) {
-			BUFFER_TRACE(bh, "remove from checkpoint");
-			__journal_remove_checkpoint(jh);
-			jbd_unlock_bh_state(bh);
-			journal_remove_journal_head(bh);
-			__brelse(bh);
-			ret = 1;
-		} else {
-			jbd_unlock_bh_state(bh);
-		}
-	} while (jh != last_jh);
-
-	return ret;
-out_return_1:
-	spin_lock(&journal->j_list_lock);
-	return 1;
+		released = __journal_remove_checkpoint(jh);
+		jbd_unlock_bh_state(bh);
+		journal_remove_journal_head(bh);
+		__brelse(bh);
+	}
 }
 
 #define NR_BATCH	64
@@ -203,9 +211,7 @@
 {
 	int i;
 
-	spin_unlock(&journal->j_list_lock);
 	ll_rw_block(SWRITE, *batch_count, bhs);
-	spin_lock(&journal->j_list_lock);
 	for (i = 0; i < *batch_count; i++) {
 		struct buffer_head *bh = bhs[i];
 		clear_buffer_jwrite(bh);
@@ -221,19 +227,43 @@
  * Return 1 if something happened which requires us to abort the current
  * scan of the checkpoint list.  
  *
- * Called with j_list_lock held.
+ * Called with j_list_lock held and drops it if 1 is returned
  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
  */
-static int __flush_buffer(journal_t *journal, struct journal_head *jh,
-			struct buffer_head **bhs, int *batch_count,
-			int *drop_count)
+static int __process_buffer(journal_t *journal, struct journal_head *jh,
+			struct buffer_head **bhs, int *batch_count)
 {
 	struct buffer_head *bh = jh2bh(jh);
 	int ret = 0;
 
-	if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) {
-		J_ASSERT_JH(jh, jh->b_transaction == NULL);
+	if (buffer_locked(bh)) {
+		atomic_inc(&bh->b_count);
+		spin_unlock(&journal->j_list_lock);
+		jbd_unlock_bh_state(bh);
+		wait_on_buffer(bh);
+		/* the journal_head may have gone by now */
+		BUFFER_TRACE(bh, "brelse");
+		__brelse(bh);
+		ret = 1;
+	} else if (jh->b_transaction != NULL) {
+		transaction_t *t = jh->b_transaction;
+		tid_t tid = t->t_tid;
 
+		spin_unlock(&journal->j_list_lock);
+		jbd_unlock_bh_state(bh);
+		log_start_commit(journal, tid);
+		log_wait_commit(journal, tid);
+		ret = 1;
+	} else if (!buffer_dirty(bh)) {
+		J_ASSERT_JH(jh, !buffer_jbddirty(bh));
+		BUFFER_TRACE(bh, "remove from checkpoint");
+		__journal_remove_checkpoint(jh);
+		spin_unlock(&journal->j_list_lock);
+		jbd_unlock_bh_state(bh);
+		journal_remove_journal_head(bh);
+		__brelse(bh);
+		ret = 1;
+	} else {
 		/*
 		 * Important: we are about to write the buffer, and
 		 * possibly block, while still holding the journal lock.
@@ -246,45 +276,30 @@
 		J_ASSERT_BH(bh, !buffer_jwrite(bh));
 		set_buffer_jwrite(bh);
 		bhs[*batch_count] = bh;
+		__buffer_relink_io(jh);
 		jbd_unlock_bh_state(bh);
 		(*batch_count)++;
 		if (*batch_count == NR_BATCH) {
+			spin_unlock(&journal->j_list_lock);
 			__flush_batch(journal, bhs, batch_count);
 			ret = 1;
 		}
-	} else {
-		int last_buffer = 0;
-		if (jh->b_cpnext == jh) {
-			/* We may be about to drop the transaction.  Tell the
-			 * caller that the lists have changed.
-			 */
-			last_buffer = 1;
-		}
-		if (__try_to_free_cp_buf(jh)) {
-			(*drop_count)++;
-			ret = last_buffer;
-		}
 	}
 	return ret;
 }
 
 /*
- * Perform an actual checkpoint.  We don't write out only enough to
- * satisfy the current blocked requests: rather we submit a reasonably
- * sized chunk of the outstanding data to disk at once for
- * efficiency.  __log_wait_for_space() will retry if we didn't free enough.
+ * Perform an actual checkpoint. We take the first transaction on the
+ * list of transactions to be checkpointed and send all its buffers
+ * to disk. We submit larger chunks of data at once.
  * 
- * However, we _do_ take into account the amount requested so that once
- * the IO has been queued, we can return as soon as enough of it has
- * completed to disk.
- *
  * The journal should be locked before calling this function.
  */
 int log_do_checkpoint(journal_t *journal)
 {
+	transaction_t *transaction;
+	tid_t this_tid;
 	int result;
-	int batch_count = 0;
-	struct buffer_head *bhs[NR_BATCH];
 
 	jbd_debug(1, "Start checkpoint\n");
 
@@ -299,79 +314,68 @@
 		return result;
 
 	/*
-	 * OK, we need to start writing disk blocks.  Try to free up a
-	 * quarter of the log in a single checkpoint if we can.
-	 */
-	/*
-	 * AKPM: check this code.  I had a feeling a while back that it
-	 * degenerates into a busy loop at unmount time.
+	 * OK, we need to start writing disk blocks.  Take one transaction
+	 * and write it.
 	 */
 	spin_lock(&journal->j_list_lock);
-	while (journal->j_checkpoint_transactions) {
-		transaction_t *transaction;
-		struct journal_head *jh, *last_jh, *next_jh;
-		int drop_count = 0;
-		int cleanup_ret, retry = 0;
-		tid_t this_tid;
+	if (!journal->j_checkpoint_transactions)
+		goto out;
+	transaction = journal->j_checkpoint_transactions;
+	this_tid = transaction->t_tid;
+restart:
+	/*
+	 * If someone cleaned up this transaction while we slept, we're
+	 * done (maybe it's a new transaction, but it fell at the same
+	 * address).
+	 */
+	if (journal->j_checkpoint_transactions == transaction &&
+			transaction->t_tid == this_tid) {
+		int batch_count = 0;
+		struct buffer_head *bhs[NR_BATCH];
+		struct journal_head *jh;
+		int retry = 0;
 
-		transaction = journal->j_checkpoint_transactions;
-		this_tid = transaction->t_tid;
-		jh = transaction->t_checkpoint_list;
-		last_jh = jh->b_cpprev;
-		next_jh = jh;
-		do {
+		while (!retry && transaction->t_checkpoint_list) {
 			struct buffer_head *bh;
 
-			jh = next_jh;
-			next_jh = jh->b_cpnext;
+			jh = transaction->t_checkpoint_list;
 			bh = jh2bh(jh);
 			if (!jbd_trylock_bh_state(bh)) {
 				jbd_sync_bh(journal, bh);
-				spin_lock(&journal->j_list_lock);
 				retry = 1;
 				break;
 			}
-			retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count);
-			if (cond_resched_lock(&journal->j_list_lock)) {
+			retry = __process_buffer(journal, jh, bhs,&batch_count);
+			if (!retry && lock_need_resched(&journal->j_list_lock)){
+				spin_unlock(&journal->j_list_lock);
 				retry = 1;
 				break;
 			}
-		} while (jh != last_jh && !retry);
-
-		if (batch_count) {
-			__flush_batch(journal, bhs, &batch_count);
-			retry = 1;
 		}
 
+		if (batch_count) {
+			if (!retry) {
+				spin_unlock(&journal->j_list_lock);
+				retry = 1;
+			}
+			__flush_batch(journal, bhs, &batch_count);
+		}
+
+		if (retry) {
+			spin_lock(&journal->j_list_lock);
+			goto restart;
+		}
 		/*
-		 * If someone cleaned up this transaction while we slept, we're
-		 * done
+		 * Now we have cleaned up the first transaction's checkpoint
+		 * list. Let's clean up the second one
 		 */
-		if (journal->j_checkpoint_transactions != transaction)
-			break;
-		if (retry)
-			continue;
-		/*
-		 * Maybe it's a new transaction, but it fell at the same
-		 * address
-		 */
-		if (transaction->t_tid != this_tid)
-			continue;
-		/*
-		 * We have walked the whole transaction list without
-		 * finding anything to write to disk.  We had better be
-		 * able to make some progress or we are in trouble.
-		 */
-		cleanup_ret = __cleanup_transaction(journal, transaction);
-		J_ASSERT(drop_count != 0 || cleanup_ret != 0);
-		if (journal->j_checkpoint_transactions != transaction)
-			break;
+		__wait_cp_io(journal, transaction);
 	}
+out:
 	spin_unlock(&journal->j_list_lock);
 	result = cleanup_journal_tail(journal);
 	if (result < 0)
 		return result;
-
 	return 0;
 }
 
@@ -456,52 +460,98 @@
 /* Checkpoint list management */
 
 /*
- * journal_clean_checkpoint_list
+ * journal_clean_one_cp_list
  *
- * Find all the written-back checkpoint buffers in the journal and release them.
+ * Find all the written-back checkpoint buffers in the given list and release them.
  *
  * Called with the journal locked.
  * Called with j_list_lock held.
  * Returns number of bufers reaped (for debug)
  */
 
+static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
+{
+	struct journal_head *last_jh;
+	struct journal_head *next_jh = jh;
+	int ret, freed = 0;
+
+	*released = 0;
+	if (!jh)
+		return 0;
+
+ 	last_jh = jh->b_cpprev;
+	do {
+		jh = next_jh;
+		next_jh = jh->b_cpnext;
+		/* Use trylock because of the ranking */
+		if (jbd_trylock_bh_state(jh2bh(jh))) {
+			ret = __try_to_free_cp_buf(jh);
+			if (ret) {
+				freed++;
+				if (ret == 2) {
+					*released = 1;
+					return freed;
+				}
+			}
+		}
+		/*
+		 * This function only frees up some memory
+		 * if possible so we dont have an obligation
+		 * to finish processing. Bail out if preemption
+		 * requested:
+		 */
+		if (need_resched())
+			return freed;
+	} while (jh != last_jh);
+
+	return freed;
+}
+
+/*
+ * journal_clean_checkpoint_list
+ *
+ * Find all the written-back checkpoint buffers in the journal and release them.
+ *
+ * Called with the journal locked.
+ * Called with j_list_lock held.
+ * Returns number of buffers reaped (for debug)
+ */
+
 int __journal_clean_checkpoint_list(journal_t *journal)
 {
 	transaction_t *transaction, *last_transaction, *next_transaction;
 	int ret = 0;
+	int released;
 
 	transaction = journal->j_checkpoint_transactions;
-	if (transaction == 0)
+	if (!transaction)
 		goto out;
 
 	last_transaction = transaction->t_cpprev;
 	next_transaction = transaction;
 	do {
-		struct journal_head *jh;
-
 		transaction = next_transaction;
 		next_transaction = transaction->t_cpnext;
-		jh = transaction->t_checkpoint_list;
-		if (jh) {
-			struct journal_head *last_jh = jh->b_cpprev;
-			struct journal_head *next_jh = jh;
-
-			do {
-				jh = next_jh;
-				next_jh = jh->b_cpnext;
-				/* Use trylock because of the ranknig */
-				if (jbd_trylock_bh_state(jh2bh(jh)))
-					ret += __try_to_free_cp_buf(jh);
-				/*
-				 * This function only frees up some memory
-				 * if possible so we dont have an obligation
-				 * to finish processing. Bail out if preemption
-				 * requested:
-				 */
-				if (need_resched())
-					goto out;
-			} while (jh != last_jh);
-		}
+		ret += journal_clean_one_cp_list(transaction->
+				t_checkpoint_list, &released);
+		/*
+		 * This function only frees up some memory if possible so we
+		 * dont have an obligation to finish processing. Bail out if
+		 * preemption requested:
+		 */
+		if (need_resched())
+			goto out;
+		if (released)
+			continue;
+		/*
+		 * It is essential that we are as careful as in the case of
+		 * t_checkpoint_list with removing the buffer from the list as
+		 * we can possibly see not yet submitted buffers on io_list
+		 */
+		ret += journal_clean_one_cp_list(transaction->
+				t_checkpoint_io_list, &released);
+		if (need_resched())
+			goto out;
 	} while (transaction != last_transaction);
 out:
 	return ret;
@@ -516,18 +566,22 @@
  * buffer updates committed in that transaction have safely been stored
  * elsewhere on disk.  To achieve this, all of the buffers in a
  * transaction need to be maintained on the transaction's checkpoint
- * list until they have been rewritten, at which point this function is
+ * lists until they have been rewritten, at which point this function is
  * called to remove the buffer from the existing transaction's
- * checkpoint list.
+ * checkpoint lists.
+ *
+ * The function returns 1 if it frees the transaction, 0 otherwise.
  *
  * This function is called with the journal locked.
  * This function is called with j_list_lock held.
+ * This function is called with jbd_lock_bh_state(jh2bh(jh))
  */
 
-void __journal_remove_checkpoint(struct journal_head *jh)
+int __journal_remove_checkpoint(struct journal_head *jh)
 {
 	transaction_t *transaction;
 	journal_t *journal;
+	int ret = 0;
 
 	JBUFFER_TRACE(jh, "entry");
 
@@ -538,8 +592,10 @@
 	journal = transaction->t_journal;
 
 	__buffer_unlink(jh);
+	jh->b_cp_transaction = NULL;
 
-	if (transaction->t_checkpoint_list != NULL)
+	if (transaction->t_checkpoint_list != NULL ||
+	    transaction->t_checkpoint_io_list != NULL)
 		goto out;
 	JBUFFER_TRACE(jh, "transaction has no more buffers");
 
@@ -565,8 +621,10 @@
 	/* Just in case anybody was waiting for more transactions to be
            checkpointed... */
 	wake_up(&journal->j_wait_logspace);
+	ret = 1;
 out:
 	JBUFFER_TRACE(jh, "exit");
+	return ret;
 }
 
 /*
@@ -628,6 +686,7 @@
 	J_ASSERT(transaction->t_shadow_list == NULL);
 	J_ASSERT(transaction->t_log_list == NULL);
 	J_ASSERT(transaction->t_checkpoint_list == NULL);
+	J_ASSERT(transaction->t_checkpoint_io_list == NULL);
 	J_ASSERT(transaction->t_updates == 0);
 	J_ASSERT(journal->j_committing_transaction != transaction);
 	J_ASSERT(journal->j_running_transaction != transaction);
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 002ad2b..0971814 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -790,11 +790,22 @@
 			jbd_unlock_bh_state(bh);
 		} else {
 			J_ASSERT_BH(bh, !buffer_dirty(bh));
-			J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
-			__journal_unfile_buffer(jh);
-			jbd_unlock_bh_state(bh);
-			journal_remove_journal_head(bh);  /* needs a brelse */
-			release_buffer_page(bh);
+			/* The buffer on BJ_Forget list and not jbddirty means
+			 * it has been freed by this transaction and hence it
+			 * could not have been reallocated until this
+			 * transaction has committed. *BUT* it could be
+			 * reallocated once we have written all the data to
+			 * disk and before we process the buffer on BJ_Forget
+			 * list. */
+			JBUFFER_TRACE(jh, "refile or unfile freed buffer");
+			__journal_refile_buffer(jh);
+			if (!jh->b_transaction) {
+				jbd_unlock_bh_state(bh);
+				 /* needs a brelse */
+				journal_remove_journal_head(bh);
+				release_buffer_page(bh);
+			} else
+				jbd_unlock_bh_state(bh);
 		}
 		cond_resched_lock(&journal->j_list_lock);
 	}
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 7f96b5c..8c9b28d 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -34,6 +34,7 @@
 #include <linux/suspend.h>
 #include <linux/pagemap.h>
 #include <linux/kthread.h>
+#include <linux/poison.h>
 #include <linux/proc_fs.h>
 
 #include <asm/uaccess.h>
@@ -1675,7 +1676,7 @@
 {
 #ifdef CONFIG_JBD_DEBUG
 	atomic_dec(&nr_journal_heads);
-	memset(jh, 0x5b, sizeof(*jh));
+	memset(jh, JBD_POISON_FREE, sizeof(*jh));
 #endif
 	kmem_cache_free(journal_head_cache, jh);
 }
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c
index 80d7f53..de5bafb4e 100644
--- a/fs/jbd/recovery.c
+++ b/fs/jbd/recovery.c
@@ -531,6 +531,7 @@
 		default:
 			jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
 				  blocktype);
+			brelse(bh);
 			goto done;
 		}
 	}
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index c609f50..508b2ea 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -227,7 +227,8 @@
 	spin_unlock(&transaction->t_handle_lock);
 	spin_unlock(&journal->j_state_lock);
 out:
-	kfree(new_transaction);
+	if (unlikely(new_transaction))		/* It's usually NULL */
+		kfree(new_transaction);
 	return ret;
 }
 
@@ -724,7 +725,8 @@
 	journal_cancel_revoke(handle, jh);
 
 out:
-	kfree(frozen_buffer);
+	if (unlikely(frozen_buffer))	/* It's usually NULL */
+		kfree(frozen_buffer);
 
 	JBUFFER_TRACE(jh, "exit");
 	return error;
@@ -903,7 +905,8 @@
 	jbd_unlock_bh_state(bh);
 out:
 	journal_put_journal_head(jh);
-	kfree(committed_data);
+	if (unlikely(committed_data))
+		kfree(committed_data);
 	return err;
 }
 
@@ -2038,7 +2041,8 @@
 	__journal_temp_unlink_buffer(jh);
 	jh->b_transaction = jh->b_next_transaction;
 	jh->b_next_transaction = NULL;
-	__journal_file_buffer(jh, jh->b_transaction, BJ_Metadata);
+	__journal_file_buffer(jh, jh->b_transaction,
+				was_dirty ? BJ_Metadata : BJ_Reserved);
 	J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING);
 
 	if (was_dirty)
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index 020cc09..9306869 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -59,7 +59,7 @@
 static struct inode_operations jffs_file_inode_operations;
 static const struct file_operations jffs_dir_operations;
 static struct inode_operations jffs_dir_inode_operations;
-static struct address_space_operations jffs_address_operations;
+static const struct address_space_operations jffs_address_operations;
 
 kmem_cache_t     *node_cache = NULL;
 kmem_cache_t     *fm_cache = NULL;
@@ -377,9 +377,9 @@
 
 /* Get statistics of the file system.  */
 static int
-jffs_statfs(struct super_block *sb, struct kstatfs *buf)
+jffs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct jffs_control *c = (struct jffs_control *) sb->s_fs_info;
+	struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info;
 	struct jffs_fmcontrol *fmc;
 
 	lock_kernel();
@@ -1614,7 +1614,7 @@
 } /* jffs_ioctl()  */
 
 
-static struct address_space_operations jffs_address_operations = {
+static const struct address_space_operations jffs_address_operations = {
 	.readpage	= jffs_readpage,
 	.prepare_write	= jffs_prepare_write,
 	.commit_write	= jffs_commit_write,
@@ -1785,10 +1785,11 @@
 	.remount_fs	= jffs_remount,
 };
 
-static struct super_block *jffs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int jffs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type jffs_fs_type = {
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 0ef207d..5371a40 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -247,7 +247,7 @@
 	D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n",
 		  mtd, (unsigned int) from, buf, count));
 
-	res = MTD_READ(mtd, from, count, &retlen, buf);
+	res = mtd->read(mtd, from, count, &retlen, buf);
 	if (retlen != count) {
 		panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res);
 	}
@@ -262,7 +262,7 @@
 	__u32 ret;
 	int res;
 
-	res = MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret);
+	res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret);
 	if (retlen != 4) {
 		printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res);
 		return 0;
@@ -282,7 +282,7 @@
 	D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n",
 		  mtd, (unsigned int) to, buf, count));
 
-	res = MTD_WRITE(mtd, to, count, &retlen, buf);
+	res = mtd->write(mtd, to, count, &retlen, buf);
 	if (retlen != count) {
 		printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res);
 	}
@@ -300,9 +300,9 @@
 
 	D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n",
 		  mtd, (unsigned int) to, vecs));
-	
+
 	if (mtd->writev) {
-		res = MTD_WRITEV(mtd, vecs, iovec_cnt, to, &retlen);
+		res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen);
 		return res ? res : retlen;
 	}
 	/* Not implemented writev. Repeatedly use write - on the not so
@@ -312,7 +312,8 @@
 	retlen=0;
 
 	for (i=0; !res && i<iovec_cnt; i++) {
-		res = MTD_WRITE(mtd, to, vecs[i].iov_len, &retlen_a, vecs[i].iov_base);
+		res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a,
+				 vecs[i].iov_base);
 		if (retlen_a != vecs[i].iov_len) {
 			printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res);
 			if (i != iovec_cnt-1)
@@ -393,7 +394,7 @@
 	set_current_state(TASK_UNINTERRUPTIBLE);
 	add_wait_queue(&wait_q, &wait);
 
-	if (MTD_ERASE(mtd, erase) < 0) {
+	if (mtd->erase(mtd, erase) < 0) {
 		set_current_state(TASK_RUNNING);
 		remove_wait_queue(&wait_q, &wait);
 		kfree(erase);
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile
index 77dc556..7f28ee0 100644
--- a/fs/jffs2/Makefile
+++ b/fs/jffs2/Makefile
@@ -12,6 +12,9 @@
 jffs2-y	+= super.o debug.o
 
 jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER)	+= wbuf.o
+jffs2-$(CONFIG_JFFS2_FS_XATTR)		+= xattr.o xattr_trusted.o xattr_user.o
+jffs2-$(CONFIG_JFFS2_FS_SECURITY)	+= security.o
+jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL)	+= acl.o
 jffs2-$(CONFIG_JFFS2_RUBIN)	+= compr_rubin.o
 jffs2-$(CONFIG_JFFS2_RTIME)	+= compr_rtime.o
 jffs2-$(CONFIG_JFFS2_ZLIB)	+= compr_zlib.o
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
index b794343..c8f0bd6 100644
--- a/fs/jffs2/README.Locking
+++ b/fs/jffs2/README.Locking
@@ -150,3 +150,24 @@
 
 Ordering constraints:
 	Lock wbuf_sem last, after the alloc_sem or and f->sem.
+
+
+	c->xattr_sem
+	------------
+
+This read/write semaphore protects against concurrent access to the
+xattr related objects which include stuff in superblock and ic->xref.
+In read-only path, write-semaphore is too much exclusion. It's enough
+by read-semaphore. But you must hold write-semaphore when updating,
+creating or deleting any xattr related object.
+
+Once xattr_sem released, there would be no assurance for the existence
+of those objects. Thus, a series of processes is often required to retry,
+when updating such a object is necessary under holding read semaphore.
+For example, do_jffs2_getxattr() holds read-semaphore to scan xref and
+xdatum at first. But it retries this process with holding write-semaphore
+after release read-semaphore, if it's necessary to load name/value pair
+from medium.
+
+Ordering constraints:
+	Lock xattr_sem last, after the alloc_sem.
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
new file mode 100644
index 0000000..9c2077e
--- /dev/null
+++ b/fs/jffs2/acl.c
@@ -0,0 +1,487 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static size_t jffs2_acl_size(int count)
+{
+	if (count <= 4) {
+		return sizeof(struct jffs2_acl_header)
+		       + count * sizeof(struct jffs2_acl_entry_short);
+	} else {
+		return sizeof(struct jffs2_acl_header)
+		       + 4 * sizeof(struct jffs2_acl_entry_short)
+		       + (count - 4) * sizeof(struct jffs2_acl_entry);
+	}
+}
+
+static int jffs2_acl_count(size_t size)
+{
+	size_t s;
+
+	size -= sizeof(struct jffs2_acl_header);
+	s = size - 4 * sizeof(struct jffs2_acl_entry_short);
+	if (s < 0) {
+		if (size % sizeof(struct jffs2_acl_entry_short))
+			return -1;
+		return size / sizeof(struct jffs2_acl_entry_short);
+	} else {
+		if (s % sizeof(struct jffs2_acl_entry))
+			return -1;
+		return s / sizeof(struct jffs2_acl_entry) + 4;
+	}
+}
+
+static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size)
+{
+	void *end = value + size;
+	struct jffs2_acl_header *header = value;
+	struct jffs2_acl_entry *entry;
+	struct posix_acl *acl;
+	uint32_t ver;
+	int i, count;
+
+	if (!value)
+		return NULL;
+	if (size < sizeof(struct jffs2_acl_header))
+		return ERR_PTR(-EINVAL);
+	ver = je32_to_cpu(header->a_version);
+	if (ver != JFFS2_ACL_VERSION) {
+		JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver);
+		return ERR_PTR(-EINVAL);
+	}
+
+	value += sizeof(struct jffs2_acl_header);
+	count = jffs2_acl_count(size);
+	if (count < 0)
+		return ERR_PTR(-EINVAL);
+	if (count == 0)
+		return NULL;
+
+	acl = posix_acl_alloc(count, GFP_KERNEL);
+	if (!acl)
+		return ERR_PTR(-ENOMEM);
+
+	for (i=0; i < count; i++) {
+		entry = value;
+		if (value + sizeof(struct jffs2_acl_entry_short) > end)
+			goto fail;
+		acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag);
+		acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm);
+		switch (acl->a_entries[i].e_tag) {
+			case ACL_USER_OBJ:
+			case ACL_GROUP_OBJ:
+			case ACL_MASK:
+			case ACL_OTHER:
+				value += sizeof(struct jffs2_acl_entry_short);
+				acl->a_entries[i].e_id = ACL_UNDEFINED_ID;
+				break;
+
+			case ACL_USER:
+			case ACL_GROUP:
+				value += sizeof(struct jffs2_acl_entry);
+				if (value > end)
+					goto fail;
+				acl->a_entries[i].e_id = je32_to_cpu(entry->e_id);
+				break;
+
+			default:
+				goto fail;
+		}
+	}
+	if (value != end)
+		goto fail;
+	return acl;
+ fail:
+	posix_acl_release(acl);
+	return ERR_PTR(-EINVAL);
+}
+
+static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
+{
+	struct jffs2_acl_header *header;
+	struct jffs2_acl_entry *entry;
+	void *e;
+	size_t i;
+
+	*size = jffs2_acl_size(acl->a_count);
+	header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL);
+	if (!header)
+		return ERR_PTR(-ENOMEM);
+	header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
+	e = header + 1;
+	for (i=0; i < acl->a_count; i++) {
+		entry = e;
+		entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag);
+		entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm);
+		switch(acl->a_entries[i].e_tag) {
+			case ACL_USER:
+			case ACL_GROUP:
+				entry->e_id = cpu_to_je32(acl->a_entries[i].e_id);
+				e += sizeof(struct jffs2_acl_entry);
+				break;
+
+			case ACL_USER_OBJ:
+			case ACL_GROUP_OBJ:
+			case ACL_MASK:
+			case ACL_OTHER:
+				e += sizeof(struct jffs2_acl_entry_short);
+				break;
+
+			default:
+				goto fail;
+		}
+	}
+	return header;
+ fail:
+	kfree(header);
+	return ERR_PTR(-EINVAL);
+}
+
+static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+	struct posix_acl *acl = JFFS2_ACL_NOT_CACHED;
+
+	spin_lock(&inode->i_lock);
+	if (*i_acl != JFFS2_ACL_NOT_CACHED)
+		acl = posix_acl_dup(*i_acl);
+	spin_unlock(&inode->i_lock);
+	return acl;
+}
+
+static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl)
+{
+	spin_lock(&inode->i_lock);
+	if (*i_acl != JFFS2_ACL_NOT_CACHED)
+		posix_acl_release(*i_acl);
+	*i_acl = posix_acl_dup(acl);
+	spin_unlock(&inode->i_lock);
+}
+
+static struct posix_acl *jffs2_get_acl(struct inode *inode, int type)
+{
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+	struct posix_acl *acl;
+	char *value = NULL;
+	int rc, xprefix;
+
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		acl = jffs2_iget_acl(inode, &f->i_acl_access);
+		if (acl != JFFS2_ACL_NOT_CACHED)
+			return acl;
+		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
+		break;
+	case ACL_TYPE_DEFAULT:
+		acl = jffs2_iget_acl(inode, &f->i_acl_default);
+		if (acl != JFFS2_ACL_NOT_CACHED)
+			return acl;
+		xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
+		break;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+	rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0);
+	if (rc > 0) {
+		value = kmalloc(rc, GFP_KERNEL);
+		if (!value)
+			return ERR_PTR(-ENOMEM);
+		rc = do_jffs2_getxattr(inode, xprefix, "", value, rc);
+	}
+	if (rc > 0) {
+		acl = jffs2_acl_from_medium(value, rc);
+	} else if (rc == -ENODATA || rc == -ENOSYS) {
+		acl = NULL;
+	} else {
+		acl = ERR_PTR(rc);
+	}
+	if (value)
+		kfree(value);
+	if (!IS_ERR(acl)) {
+		switch (type) {
+		case ACL_TYPE_ACCESS:
+			jffs2_iset_acl(inode, &f->i_acl_access, acl);
+			break;
+		case ACL_TYPE_DEFAULT:
+			jffs2_iset_acl(inode, &f->i_acl_default, acl);
+			break;
+		}
+	}
+	return acl;
+}
+
+static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+	size_t size = 0;
+	char *value = NULL;
+	int rc, xprefix;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+
+	switch (type) {
+	case ACL_TYPE_ACCESS:
+		xprefix = JFFS2_XPREFIX_ACL_ACCESS;
+		if (acl) {
+			mode_t mode = inode->i_mode;
+			rc = posix_acl_equiv_mode(acl, &mode);
+			if (rc < 0)
+				return rc;
+			if (inode->i_mode != mode) {
+				inode->i_mode = mode;
+				jffs2_dirty_inode(inode);
+			}
+			if (rc == 0)
+				acl = NULL;
+		}
+		break;
+	case ACL_TYPE_DEFAULT:
+		xprefix = JFFS2_XPREFIX_ACL_DEFAULT;
+		if (!S_ISDIR(inode->i_mode))
+			return acl ? -EACCES : 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (acl) {
+		value = jffs2_acl_to_medium(acl, &size);
+		if (IS_ERR(value))
+			return PTR_ERR(value);
+	}
+
+	rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0);
+	if (!value && rc == -ENODATA)
+		rc = 0;
+	if (value)
+		kfree(value);
+	if (!rc) {
+		switch(type) {
+		case ACL_TYPE_ACCESS:
+			jffs2_iset_acl(inode, &f->i_acl_access, acl);
+			break;
+		case ACL_TYPE_DEFAULT:
+			jffs2_iset_acl(inode, &f->i_acl_default, acl);
+			break;
+		}
+	}
+	return rc;
+}
+
+static int jffs2_check_acl(struct inode *inode, int mask)
+{
+	struct posix_acl *acl;
+	int rc;
+
+	acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	if (acl) {
+		rc = posix_acl_permission(inode, acl, mask);
+		posix_acl_release(acl);
+		return rc;
+	}
+	return -EAGAIN;
+}
+
+int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	return generic_permission(inode, mask, jffs2_check_acl);
+}
+
+int jffs2_init_acl(struct inode *inode, struct inode *dir)
+{
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+	struct posix_acl *acl = NULL, *clone;
+	mode_t mode;
+	int rc = 0;
+
+	f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+	f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+	if (!S_ISLNK(inode->i_mode)) {
+		acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		if (!acl)
+			inode->i_mode &= ~current->fs->umask;
+	}
+	if (acl) {
+		if (S_ISDIR(inode->i_mode)) {
+			rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl);
+			if (rc)
+				goto cleanup;
+		}
+		clone = posix_acl_clone(acl, GFP_KERNEL);
+		rc = -ENOMEM;
+		if (!clone)
+			goto cleanup;
+		mode = inode->i_mode;
+		rc = posix_acl_create_masq(clone, &mode);
+		if (rc >= 0) {
+			inode->i_mode = mode;
+			if (rc > 0)
+				rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
+		}
+		posix_acl_release(clone);
+	}
+ cleanup:
+	posix_acl_release(acl);
+	return rc;
+}
+
+void jffs2_clear_acl(struct inode *inode)
+{
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+
+	if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) {
+		posix_acl_release(f->i_acl_access);
+		f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+	}
+	if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) {
+		posix_acl_release(f->i_acl_default);
+		f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+	}
+}
+
+int jffs2_acl_chmod(struct inode *inode)
+{
+	struct posix_acl *acl, *clone;
+	int rc;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+	acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS);
+	if (IS_ERR(acl) || !acl)
+		return PTR_ERR(acl);
+	clone = posix_acl_clone(acl, GFP_KERNEL);
+	posix_acl_release(acl);
+	if (!clone)
+		return -ENOMEM;
+	rc = posix_acl_chmod_masq(clone, inode->i_mode);
+	if (!rc)
+		rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone);
+	posix_acl_release(clone);
+	return rc;
+}
+
+static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size,
+					 const char *name, size_t name_len)
+{
+	const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS);
+
+	if (list && retlen <= list_size)
+		strcpy(list, POSIX_ACL_XATTR_ACCESS);
+	return retlen;
+}
+
+static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size,
+					  const char *name, size_t name_len)
+{
+	const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT);
+
+	if (list && retlen <= list_size)
+		strcpy(list, POSIX_ACL_XATTR_DEFAULT);
+	return retlen;
+}
+
+static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size)
+{
+	struct posix_acl *acl;
+	int rc;
+
+	acl = jffs2_get_acl(inode, type);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	if (!acl)
+		return -ENODATA;
+	rc = posix_acl_to_xattr(acl, buffer, size);
+	posix_acl_release(acl);
+
+	return rc;
+}
+
+static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
+{
+	if (name[0] != '\0')
+		return -EINVAL;
+	return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size)
+{
+	if (name[0] != '\0')
+		return -EINVAL;
+	return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size)
+{
+	struct posix_acl *acl;
+	int rc;
+
+	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		return -EPERM;
+
+	if (value) {
+		acl = posix_acl_from_xattr(value, size);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		if (acl) {
+			rc = posix_acl_valid(acl);
+			if (rc)
+				goto out;
+		}
+	} else {
+		acl = NULL;
+	}
+	rc = jffs2_set_acl(inode, type, acl);
+ out:
+	posix_acl_release(acl);
+	return rc;
+}
+
+static int jffs2_acl_access_setxattr(struct inode *inode, const char *name,
+				     const void *buffer, size_t size, int flags)
+{
+	if (name[0] != '\0')
+		return -EINVAL;
+	return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size);
+}
+
+static int jffs2_acl_default_setxattr(struct inode *inode, const char *name,
+				      const void *buffer, size_t size, int flags)
+{
+	if (name[0] != '\0')
+		return -EINVAL;
+	return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size);
+}
+
+struct xattr_handler jffs2_acl_access_xattr_handler = {
+	.prefix	= POSIX_ACL_XATTR_ACCESS,
+	.list	= jffs2_acl_access_listxattr,
+	.get	= jffs2_acl_access_getxattr,
+	.set	= jffs2_acl_access_setxattr,
+};
+
+struct xattr_handler jffs2_acl_default_xattr_handler = {
+	.prefix	= POSIX_ACL_XATTR_DEFAULT,
+	.list	= jffs2_acl_default_listxattr,
+	.get	= jffs2_acl_default_getxattr,
+	.set	= jffs2_acl_default_setxattr,
+};
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
new file mode 100644
index 0000000..8893bd1
--- /dev/null
+++ b/fs/jffs2/acl.h
@@ -0,0 +1,45 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+struct jffs2_acl_entry {
+	jint16_t	e_tag;
+	jint16_t	e_perm;
+	jint32_t	e_id;
+};
+
+struct jffs2_acl_entry_short {
+	jint16_t	e_tag;
+	jint16_t	e_perm;
+};
+
+struct jffs2_acl_header {
+	jint32_t	a_version;
+};
+
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+
+#define JFFS2_ACL_NOT_CACHED ((void *)-1)
+
+extern int jffs2_permission(struct inode *, int, struct nameidata *);
+extern int jffs2_acl_chmod(struct inode *);
+extern int jffs2_init_acl(struct inode *, struct inode *);
+extern void jffs2_clear_acl(struct inode *);
+
+extern struct xattr_handler jffs2_acl_access_xattr_handler;
+extern struct xattr_handler jffs2_acl_default_xattr_handler;
+
+#else
+
+#define jffs2_permission NULL
+#define jffs2_acl_chmod(inode)		(0)
+#define jffs2_init_acl(inode,dir)	(0)
+#define jffs2_clear_acl(inode)
+
+#endif	/* CONFIG_JFFS2_FS_POSIX_ACL */
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
index 70f7a89..0282696 100644
--- a/fs/jffs2/build.c
+++ b/fs/jffs2/build.c
@@ -160,6 +160,7 @@
 		ic->scan_dents = NULL;
 		cond_resched();
 	}
+	jffs2_build_xattr_subsystem(c);
 	c->flags &= ~JFFS2_SB_FLAG_BUILDING;
 
 	dbg_fsbuild("FS build complete\n");
@@ -178,6 +179,7 @@
 				jffs2_free_full_dirent(fd);
 			}
 		}
+		jffs2_clear_xattr_subsystem(c);
 	}
 
 	return ret;
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c
index e7944e6..7001ba2 100644
--- a/fs/jffs2/compr.c
+++ b/fs/jffs2/compr.c
@@ -412,7 +412,7 @@
                 kfree(comprbuf);
 }
 
-int jffs2_compressors_init(void)
+int __init jffs2_compressors_init(void)
 {
 /* Registering compressors */
 #ifdef CONFIG_JFFS2_ZLIB
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h
index a77e830..509b8b1 100644
--- a/fs/jffs2/compr.h
+++ b/fs/jffs2/compr.h
@@ -23,8 +23,8 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/jffs2.h>
-#include <linux/jffs2_fs_i.h>
-#include <linux/jffs2_fs_sb.h>
+#include "jffs2_fs_i.h"
+#include "jffs2_fs_sb.h"
 #include "nodelist.h"
 
 #define JFFS2_RUBINMIPS_PRIORITY 10
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 1fe17de..72b4fc1 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -192,13 +192,13 @@
 		else
 			my_dirty_size += totlen;
 
-		if ((!ref2->next_phys) != (ref2 == jeb->last_node)) {
-			JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
-				ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys,
-				ref_offset(jeb->last_node), jeb->last_node);
+		if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) {
+			JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n",
+				    ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2),
+				    ref_offset(jeb->last_node), jeb->last_node);
 			goto error;
 		}
-		ref2 = ref2->next_phys;
+		ref2 = ref_next(ref2);
 	}
 
 	if (my_used_size != jeb->used_size) {
@@ -268,9 +268,9 @@
 	}
 
 	printk(JFFS2_DBG);
-	for (ref = jeb->first_node; ; ref = ref->next_phys) {
+	for (ref = jeb->first_node; ; ref = ref_next(ref)) {
 		printk("%#08x(%#x)", ref_offset(ref), ref->__totlen);
-		if (ref->next_phys)
+		if (ref_next(ref))
 			printk("->");
 		else
 			break;
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h
index 162af6d..5fa494a 100644
--- a/fs/jffs2/debug.h
+++ b/fs/jffs2/debug.h
@@ -171,6 +171,12 @@
 #define dbg_memalloc(fmt, ...)
 #endif
 
+/* Watch the XATTR subsystem */
+#ifdef JFFS2_DBG_XATTR_MESSAGES
+#define dbg_xattr(fmt, ...)  JFFS2_DEBUG(fmt, ##__VA_ARGS__)
+#else
+#define dbg_xattr(fmt, ...)
+#endif 
 
 /* "Sanity" checks */
 void
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 8bc7a50..edd8371 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -17,8 +17,8 @@
 #include <linux/fs.h>
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
-#include <linux/jffs2_fs_i.h>
-#include <linux/jffs2_fs_sb.h>
+#include "jffs2_fs_i.h"
+#include "jffs2_fs_sb.h"
 #include <linux/time.h>
 #include "nodelist.h"
 
@@ -57,7 +57,12 @@
 	.rmdir =	jffs2_rmdir,
 	.mknod =	jffs2_mknod,
 	.rename =	jffs2_rename,
+	.permission =	jffs2_permission,
 	.setattr =	jffs2_setattr,
+	.setxattr =	jffs2_setxattr,
+	.getxattr =	jffs2_getxattr,
+	.listxattr =	jffs2_listxattr,
+	.removexattr =	jffs2_removexattr
 };
 
 /***********************************************************************/
@@ -78,6 +83,9 @@
 
 	D1(printk(KERN_DEBUG "jffs2_lookup()\n"));
 
+	if (target->d_name.len > JFFS2_MAX_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
 	dir_f = JFFS2_INODE_INFO(dir_i);
 	c = JFFS2_SB_INFO(dir_i->i_sb);
 
@@ -206,12 +214,15 @@
 	ret = jffs2_do_create(c, dir_f, f, ri,
 			      dentry->d_name.name, dentry->d_name.len);
 
-	if (ret) {
-		make_bad_inode(inode);
-		iput(inode);
-		jffs2_free_raw_inode(ri);
-		return ret;
-	}
+	if (ret)
+		goto fail;
+
+	ret = jffs2_init_security(inode, dir_i);
+	if (ret)
+		goto fail;
+	ret = jffs2_init_acl(inode, dir_i);
+	if (ret)
+		goto fail;
 
 	dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
 
@@ -221,6 +232,12 @@
 	D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n",
 		  inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages));
 	return 0;
+
+ fail:
+	make_bad_inode(inode);
+	iput(inode);
+	jffs2_free_raw_inode(ri);
+	return ret;
 }
 
 /***********************************************************************/
@@ -291,7 +308,7 @@
 	struct jffs2_full_dnode *fn;
 	struct jffs2_full_dirent *fd;
 	int namelen;
-	uint32_t alloclen, phys_ofs;
+	uint32_t alloclen;
 	int ret, targetlen = strlen(target);
 
 	/* FIXME: If you care. We'd need to use frags for the target
@@ -310,8 +327,8 @@
 	 * Just the node will do for now, though
 	 */
 	namelen = dentry->d_name.len;
-	ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+	ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen,
+				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 
 	if (ret) {
 		jffs2_free_raw_inode(ri);
@@ -339,7 +356,7 @@
 	ri->data_crc = cpu_to_je32(crc32(0, target, targetlen));
 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-	fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL);
+	fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL);
 
 	jffs2_free_raw_inode(ri);
 
@@ -371,8 +388,20 @@
 	up(&f->sem);
 
 	jffs2_complete_reservation(c);
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+
+	ret = jffs2_init_security(inode, dir_i);
+	if (ret) {
+		jffs2_clear_inode(inode);
+		return ret;
+	}
+	ret = jffs2_init_acl(inode, dir_i);
+	if (ret) {
+		jffs2_clear_inode(inode);
+		return ret;
+	}
+
+	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
+				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 	if (ret) {
 		/* Eep. */
 		jffs2_clear_inode(inode);
@@ -404,7 +433,7 @@
 	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
 	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
 
-	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL);
+	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
 
 	if (IS_ERR(fd)) {
 		/* dirent failed to write. Delete the inode normally
@@ -442,7 +471,7 @@
 	struct jffs2_full_dnode *fn;
 	struct jffs2_full_dirent *fd;
 	int namelen;
-	uint32_t alloclen, phys_ofs;
+	uint32_t alloclen;
 	int ret;
 
 	mode |= S_IFDIR;
@@ -457,8 +486,8 @@
 	 * Just the node will do for now, though
 	 */
 	namelen = dentry->d_name.len;
-	ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL,
-				JFFS2_SUMMARY_INODE_SIZE);
+	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
+				  JFFS2_SUMMARY_INODE_SIZE);
 
 	if (ret) {
 		jffs2_free_raw_inode(ri);
@@ -483,7 +512,7 @@
 	ri->data_crc = cpu_to_je32(0);
 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-	fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
+	fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
 
 	jffs2_free_raw_inode(ri);
 
@@ -501,8 +530,20 @@
 	up(&f->sem);
 
 	jffs2_complete_reservation(c);
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+
+	ret = jffs2_init_security(inode, dir_i);
+	if (ret) {
+		jffs2_clear_inode(inode);
+		return ret;
+	}
+	ret = jffs2_init_acl(inode, dir_i);
+	if (ret) {
+		jffs2_clear_inode(inode);
+		return ret;
+	}
+
+	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
+				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 	if (ret) {
 		/* Eep. */
 		jffs2_clear_inode(inode);
@@ -534,7 +575,7 @@
 	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
 	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
 
-	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL);
+	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
 
 	if (IS_ERR(fd)) {
 		/* dirent failed to write. Delete the inode normally
@@ -588,12 +629,12 @@
 	struct jffs2_full_dnode *fn;
 	struct jffs2_full_dirent *fd;
 	int namelen;
-	jint16_t dev;
+	union jffs2_device_node dev;
 	int devlen = 0;
-	uint32_t alloclen, phys_ofs;
+	uint32_t alloclen;
 	int ret;
 
-	if (!old_valid_dev(rdev))
+	if (!new_valid_dev(rdev))
 		return -EINVAL;
 
 	ri = jffs2_alloc_raw_inode();
@@ -602,17 +643,15 @@
 
 	c = JFFS2_SB_INFO(dir_i->i_sb);
 
-	if (S_ISBLK(mode) || S_ISCHR(mode)) {
-		dev = cpu_to_je16(old_encode_dev(rdev));
-		devlen = sizeof(dev);
-	}
+	if (S_ISBLK(mode) || S_ISCHR(mode))
+		devlen = jffs2_encode_dev(&dev, rdev);
 
 	/* Try to reserve enough space for both node and dirent.
 	 * Just the node will do for now, though
 	 */
 	namelen = dentry->d_name.len;
-	ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+	ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen,
+				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 
 	if (ret) {
 		jffs2_free_raw_inode(ri);
@@ -639,7 +678,7 @@
 	ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen));
 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-	fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL);
+	fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL);
 
 	jffs2_free_raw_inode(ri);
 
@@ -657,8 +696,20 @@
 	up(&f->sem);
 
 	jffs2_complete_reservation(c);
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+
+	ret = jffs2_init_security(inode, dir_i);
+	if (ret) {
+		jffs2_clear_inode(inode);
+		return ret;
+	}
+	ret = jffs2_init_acl(inode, dir_i);
+	if (ret) {
+		jffs2_clear_inode(inode);
+		return ret;
+	}
+
+	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
+				  ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 	if (ret) {
 		/* Eep. */
 		jffs2_clear_inode(inode);
@@ -693,7 +744,7 @@
 	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
 	rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
 
-	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL);
+	fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL);
 
 	if (IS_ERR(fd)) {
 		/* dirent failed to write. Delete the inode normally
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index dad68fd..ad01210 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -30,7 +30,6 @@
 #endif
 static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset);
 static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
-static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 
 static void jffs2_erase_block(struct jffs2_sb_info *c,
@@ -54,8 +53,7 @@
 	if (!instr) {
 		printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n");
 		spin_lock(&c->erase_completion_lock);
-		list_del(&jeb->list);
-		list_add(&jeb->list, &c->erase_pending_list);
+		list_move(&jeb->list, &c->erase_pending_list);
 		c->erasing_size -= c->sector_size;
 		c->dirty_size += c->sector_size;
 		jeb->dirty_size = c->sector_size;
@@ -87,8 +85,7 @@
 		/* Erase failed immediately. Refile it on the list */
 		D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret));
 		spin_lock(&c->erase_completion_lock);
-		list_del(&jeb->list);
-		list_add(&jeb->list, &c->erase_pending_list);
+		list_move(&jeb->list, &c->erase_pending_list);
 		c->erasing_size -= c->sector_size;
 		c->dirty_size += c->sector_size;
 		jeb->dirty_size = c->sector_size;
@@ -136,7 +133,7 @@
 			c->used_size -= jeb->used_size;
 			c->dirty_size -= jeb->dirty_size;
 			jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0;
-			jffs2_free_all_node_refs(c, jeb);
+			jffs2_free_jeb_node_refs(c, jeb);
 			list_add(&jeb->list, &c->erasing_list);
 			spin_unlock(&c->erase_completion_lock);
 
@@ -162,8 +159,7 @@
 {
 	D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
 	spin_lock(&c->erase_completion_lock);
-	list_del(&jeb->list);
-	list_add_tail(&jeb->list, &c->erase_complete_list);
+	list_move_tail(&jeb->list, &c->erase_complete_list);
 	spin_unlock(&c->erase_completion_lock);
 	/* Ensure that kupdated calls us again to mark them clean */
 	jffs2_erase_pending_trigger(c);
@@ -179,8 +175,7 @@
 		if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
 			/* We'd like to give this block another try. */
 			spin_lock(&c->erase_completion_lock);
-			list_del(&jeb->list);
-			list_add(&jeb->list, &c->erase_pending_list);
+			list_move(&jeb->list, &c->erase_pending_list);
 			c->erasing_size -= c->sector_size;
 			c->dirty_size += c->sector_size;
 			jeb->dirty_size = c->sector_size;
@@ -192,8 +187,7 @@
 	spin_lock(&c->erase_completion_lock);
 	c->erasing_size -= c->sector_size;
 	c->bad_size += c->sector_size;
-	list_del(&jeb->list);
-	list_add(&jeb->list, &c->bad_list);
+	list_move(&jeb->list, &c->bad_list);
 	c->nr_erasing_blocks--;
 	spin_unlock(&c->erase_completion_lock);
 	wake_up(&c->erase_wait);
@@ -254,7 +248,8 @@
 
 	/* PARANOIA */
 	if (!ic) {
-		printk(KERN_WARNING "inode_cache not found in remove_node_refs()!!\n");
+		JFFS2_WARNING("inode_cache/xattr_datum/xattr_ref"
+			      " not found in remove_node_refs()!!\n");
 		return;
 	}
 
@@ -279,26 +274,42 @@
 		printk("\n");
 	});
 
-	if (ic->nodes == (void *)ic && ic->nlink == 0)
-		jffs2_del_ino_cache(c, ic);
+	switch (ic->class) {
+#ifdef CONFIG_JFFS2_FS_XATTR
+		case RAWNODE_CLASS_XATTR_DATUM:
+			jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
+			break;
+		case RAWNODE_CLASS_XATTR_REF:
+			jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
+			break;
+#endif
+		default:
+			if (ic->nodes == (void *)ic && ic->nlink == 0)
+				jffs2_del_ino_cache(c, ic);
+	}
 }
 
-static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
-	struct jffs2_raw_node_ref *ref;
+	struct jffs2_raw_node_ref *block, *ref;
 	D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset));
-	while(jeb->first_node) {
-		ref = jeb->first_node;
-		jeb->first_node = ref->next_phys;
 
-		/* Remove from the inode-list */
-		if (ref->next_in_ino)
+	block = ref = jeb->first_node;
+
+	while (ref) {
+		if (ref->flash_offset == REF_LINK_NODE) {
+			ref = ref->next_in_ino;
+			jffs2_free_refblock(block);
+			block = ref;
+			continue;
+		}
+		if (ref->flash_offset != REF_EMPTY_NODE && ref->next_in_ino)
 			jffs2_remove_node_refs_from_ino_list(c, ref, jeb);
 		/* else it was a non-inode node or already removed, so don't bother */
 
-		jffs2_free_raw_node_ref(ref);
+		ref++;
 	}
-	jeb->last_node = NULL;
+	jeb->first_node = jeb->last_node = NULL;
 }
 
 static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset)
@@ -351,7 +362,6 @@
 
 static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
-	struct jffs2_raw_node_ref *marker_ref = NULL;
 	size_t retlen;
 	int ret;
 	uint32_t bad_offset;
@@ -373,12 +383,8 @@
 				goto filebad;
 		}
 
-		jeb->first_node = jeb->last_node = NULL;
+		/* Everything else got zeroed before the erase */
 		jeb->free_size = c->sector_size;
-		jeb->used_size = 0;
-		jeb->dirty_size = 0;
-		jeb->wasted_size = 0;
-
 	} else {
 
 		struct kvec vecs[1];
@@ -388,11 +394,7 @@
 			.totlen =	cpu_to_je32(c->cleanmarker_size)
 		};
 
-		marker_ref = jffs2_alloc_raw_node_ref();
-		if (!marker_ref) {
-			printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n");
-			goto refile;
-		}
+		jffs2_prealloc_raw_node_refs(c, jeb, 1);
 
 		marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4));
 
@@ -408,21 +410,13 @@
 				printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n",
 				       jeb->offset, sizeof(marker), retlen);
 
-			jffs2_free_raw_node_ref(marker_ref);
 			goto filebad;
 		}
 
-		marker_ref->next_in_ino = NULL;
-		marker_ref->next_phys = NULL;
-		marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-		marker_ref->__totlen = c->cleanmarker_size;
-
-		jeb->first_node = jeb->last_node = marker_ref;
-
-		jeb->free_size = c->sector_size - c->cleanmarker_size;
-		jeb->used_size = c->cleanmarker_size;
-		jeb->dirty_size = 0;
-		jeb->wasted_size = 0;
+		/* Everything else got zeroed before the erase */
+		jeb->free_size = c->sector_size;
+		/* FIXME Special case for cleanmarker in empty block */
+		jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL);
 	}
 
 	spin_lock(&c->erase_completion_lock);
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 9f41712..3ed6e3e 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -54,10 +54,15 @@
 
 struct inode_operations jffs2_file_inode_operations =
 {
-	.setattr =	jffs2_setattr
+	.permission =	jffs2_permission,
+	.setattr =	jffs2_setattr,
+	.setxattr =	jffs2_setxattr,
+	.getxattr =	jffs2_getxattr,
+	.listxattr =	jffs2_listxattr,
+	.removexattr =	jffs2_removexattr
 };
 
-struct address_space_operations jffs2_file_address_operations =
+const struct address_space_operations jffs2_file_address_operations =
 {
 	.readpage =	jffs2_readpage,
 	.prepare_write =jffs2_prepare_write,
@@ -129,13 +134,13 @@
 		struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
 		struct jffs2_raw_inode ri;
 		struct jffs2_full_dnode *fn;
-		uint32_t phys_ofs, alloc_len;
+		uint32_t alloc_len;
 
 		D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
 			  (unsigned int)inode->i_size, pageofs));
 
-		ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len,
-					ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+		ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+					  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 		if (ret)
 			return ret;
 
@@ -161,7 +166,7 @@
 		ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
 		ri.data_crc = cpu_to_je32(0);
 
-		fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
+		fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_NORMAL);
 
 		if (IS_ERR(fn)) {
 			ret = PTR_ERR(fn);
@@ -215,12 +220,20 @@
 	D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
 		  inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags));
 
-	if (!start && end == PAGE_CACHE_SIZE) {
-		/* We need to avoid deadlock with page_cache_read() in
-		   jffs2_garbage_collect_pass(). So we have to mark the
-		   page up to date, to prevent page_cache_read() from
-		   trying to re-lock it. */
-		SetPageUptodate(pg);
+	if (end == PAGE_CACHE_SIZE) {
+		if (!start) {
+			/* We need to avoid deadlock with page_cache_read() in
+			   jffs2_garbage_collect_pass(). So we have to mark the
+			   page up to date, to prevent page_cache_read() from
+			   trying to re-lock it. */
+			SetPageUptodate(pg);
+		} else {
+			/* When writing out the end of a page, write out the 
+			   _whole_ page. This helps to reduce the number of
+			   nodes in files which have many short writes, like
+			   syslog files. */
+			start = aligned_start = 0;
+		}
 	}
 
 	ri = jffs2_alloc_raw_inode();
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index 09e5d10..97caa77 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -33,11 +33,11 @@
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
 	struct jffs2_raw_inode *ri;
-	unsigned short dev;
+	union jffs2_device_node dev;
 	unsigned char *mdata = NULL;
 	int mdatalen = 0;
 	unsigned int ivalid;
-	uint32_t phys_ofs, alloclen;
+	uint32_t alloclen;
 	int ret;
 	D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
 	ret = inode_change_ok(inode, iattr);
@@ -51,20 +51,24 @@
 	   it out again with the appropriate data attached */
 	if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
 		/* For these, we don't actually need to read the old node */
-		dev = old_encode_dev(inode->i_rdev);
+		mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
 		mdata = (char *)&dev;
-		mdatalen = sizeof(dev);
 		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen));
 	} else if (S_ISLNK(inode->i_mode)) {
+		down(&f->sem);
 		mdatalen = f->metadata->size;
 		mdata = kmalloc(f->metadata->size, GFP_USER);
-		if (!mdata)
+		if (!mdata) {
+			up(&f->sem);
 			return -ENOMEM;
+		}
 		ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
 		if (ret) {
+			up(&f->sem);
 			kfree(mdata);
 			return ret;
 		}
+		up(&f->sem);
 		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
 	}
 
@@ -75,8 +79,8 @@
 		return -ENOMEM;
 	}
 
-	ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen,
-				ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+	ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
+				  ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 	if (ret) {
 		jffs2_free_raw_inode(ri);
 		if (S_ISLNK(inode->i_mode & S_IFMT))
@@ -127,7 +131,7 @@
 	else
 		ri->data_crc = cpu_to_je32(0);
 
-	new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL);
+	new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL);
 	if (S_ISLNK(inode->i_mode))
 		kfree(mdata);
 
@@ -180,12 +184,17 @@
 
 int jffs2_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-	return jffs2_do_setattr(dentry->d_inode, iattr);
+	int rc;
+
+	rc = jffs2_do_setattr(dentry->d_inode, iattr);
+	if (!rc && (iattr->ia_valid & ATTR_MODE))
+		rc = jffs2_acl_chmod(dentry->d_inode);
+	return rc;
 }
 
-int jffs2_statfs(struct super_block *sb, struct kstatfs *buf)
+int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb);
 	unsigned long avail;
 
 	buf->f_type = JFFS2_SUPER_MAGIC;
@@ -218,7 +227,6 @@
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
 
 	D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode));
-
 	jffs2_do_clear_inode(c, f);
 }
 
@@ -227,6 +235,8 @@
 	struct jffs2_inode_info *f;
 	struct jffs2_sb_info *c;
 	struct jffs2_raw_inode latest_node;
+	union jffs2_device_node jdev;
+	dev_t rdev = 0;
 	int ret;
 
 	D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
@@ -258,7 +268,6 @@
 	inode->i_blocks = (inode->i_size + 511) >> 9;
 
 	switch (inode->i_mode & S_IFMT) {
-		jint16_t rdev;
 
 	case S_IFLNK:
 		inode->i_op = &jffs2_symlink_inode_operations;
@@ -292,8 +301,16 @@
 	case S_IFBLK:
 	case S_IFCHR:
 		/* Read the device numbers from the media */
+		if (f->metadata->size != sizeof(jdev.old) &&
+		    f->metadata->size != sizeof(jdev.new)) {
+			printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
+			up(&f->sem);
+			jffs2_do_clear_inode(c, f);
+			make_bad_inode(inode);
+			return;
+		}
 		D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
-		if (jffs2_read_dnode(c, f, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
+		if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {
 			/* Eep */
 			printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
 			up(&f->sem);
@@ -301,12 +318,15 @@
 			make_bad_inode(inode);
 			return;
 		}
+		if (f->metadata->size == sizeof(jdev.old))
+			rdev = old_decode_dev(je16_to_cpu(jdev.old));
+		else
+			rdev = new_decode_dev(je32_to_cpu(jdev.new));
 
 	case S_IFSOCK:
 	case S_IFIFO:
 		inode->i_op = &jffs2_file_inode_operations;
-		init_special_inode(inode, inode->i_mode,
-				   old_decode_dev((je16_to_cpu(rdev))));
+		init_special_inode(inode, inode->i_mode, rdev);
 		break;
 
 	default:
@@ -492,6 +512,8 @@
 	}
 	memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
 
+	jffs2_init_xattr_subsystem(c);
+
 	if ((ret = jffs2_do_mount_fs(c)))
 		goto out_inohash;
 
@@ -526,6 +548,7 @@
 	else
 		kfree(c->blocks);
  out_inohash:
+	jffs2_clear_xattr_subsystem(c);
 	kfree(c->inocache_list);
  out_wbuf:
 	jffs2_flash_cleanup(c);
@@ -639,13 +662,6 @@
 			return ret;
 	}
 
-	/* add setups for other bizarre flashes here... */
-	if (jffs2_nor_ecc(c)) {
-		ret = jffs2_nor_ecc_flash_setup(c);
-		if (ret)
-			return ret;
-	}
-
 	/* and Dataflash */
 	if (jffs2_dataflash(c)) {
 		ret = jffs2_dataflash_setup(c);
@@ -669,11 +685,6 @@
 		jffs2_nand_flash_cleanup(c);
 	}
 
-	/* add cleanups for other bizarre flashes here... */
-	if (jffs2_nor_ecc(c)) {
-		jffs2_nor_ecc_flash_cleanup(c);
-	}
-
 	/* and DataFlash */
 	if (jffs2_dataflash(c)) {
 		jffs2_dataflash_cleanup(c);
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index f9ffece..daff334 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -125,6 +125,7 @@
 	struct jffs2_eraseblock *jeb;
 	struct jffs2_raw_node_ref *raw;
 	int ret = 0, inum, nlink;
+	int xattr = 0;
 
 	if (down_interruptible(&c->alloc_sem))
 		return -EINTR;
@@ -138,7 +139,7 @@
 		   the node CRCs etc. Do it now. */
 
 		/* checked_ino is protected by the alloc_sem */
-		if (c->checked_ino > c->highest_ino) {
+		if (c->checked_ino > c->highest_ino && xattr) {
 			printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n",
 			       c->unchecked_size);
 			jffs2_dbg_dump_block_lists_nolock(c);
@@ -148,6 +149,9 @@
 
 		spin_unlock(&c->erase_completion_lock);
 
+		if (!xattr)
+			xattr = jffs2_verify_xattr(c);
+
 		spin_lock(&c->inocache_lock);
 
 		ic = jffs2_get_ino_cache(c, c->checked_ino++);
@@ -161,6 +165,7 @@
 			D1(printk(KERN_DEBUG "Skipping check of ino #%d with nlink zero\n",
 				  ic->ino));
 			spin_unlock(&c->inocache_lock);
+			jffs2_xattr_delete_inode(c, ic);
 			continue;
 		}
 		switch(ic->state) {
@@ -181,6 +186,10 @@
 			   and trigger the BUG() above while we haven't yet
 			   finished checking all its nodes */
 			D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino));
+			/* We need to come back again for the _same_ inode. We've
+			 made no progress in this case, but that should be OK */
+			c->checked_ino--;
+
 			up(&c->alloc_sem);
 			sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
 			return 0;
@@ -231,7 +240,7 @@
 
 	while(ref_obsolete(raw)) {
 		D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw)));
-		raw = raw->next_phys;
+		raw = ref_next(raw);
 		if (unlikely(!raw)) {
 			printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n");
 			printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n",
@@ -248,16 +257,36 @@
 
 	if (!raw->next_in_ino) {
 		/* Inode-less node. Clean marker, snapshot or something like that */
-		/* FIXME: If it's something that needs to be copied, including something
-		   we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */
 		spin_unlock(&c->erase_completion_lock);
-		jffs2_mark_node_obsolete(c, raw);
+		if (ref_flags(raw) == REF_PRISTINE) {
+			/* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */
+			jffs2_garbage_collect_pristine(c, NULL, raw);
+		} else {
+			/* Just mark it obsolete */
+			jffs2_mark_node_obsolete(c, raw);
+		}
 		up(&c->alloc_sem);
 		goto eraseit_lock;
 	}
 
 	ic = jffs2_raw_ref_to_ic(raw);
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+	/* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr.
+	 * We can decide whether this node is inode or xattr by ic->class.     */
+	if (ic->class == RAWNODE_CLASS_XATTR_DATUM
+	    || ic->class == RAWNODE_CLASS_XATTR_REF) {
+		spin_unlock(&c->erase_completion_lock);
+
+		if (ic->class == RAWNODE_CLASS_XATTR_DATUM) {
+			ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic, raw);
+		} else {
+			ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic, raw);
+		}
+		goto release_sem;
+	}
+#endif
+
 	/* We need to hold the inocache. Either the erase_completion_lock or
 	   the inocache_lock are sufficient; we trade down since the inocache_lock
 	   causes less contention. */
@@ -499,7 +528,6 @@
 					  struct jffs2_raw_node_ref *raw)
 {
 	union jffs2_node_union *node;
-	struct jffs2_raw_node_ref *nraw;
 	size_t retlen;
 	int ret;
 	uint32_t phys_ofs, alloclen;
@@ -508,15 +536,16 @@
 
 	D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw)));
 
-	rawlen = ref_totlen(c, c->gcblock, raw);
+	alloclen = rawlen = ref_totlen(c, c->gcblock, raw);
 
 	/* Ask for a small amount of space (or the totlen if smaller) because we
 	   don't want to force wastage of the end of a block if splitting would
 	   work. */
-	ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) +
-				JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen);
-				/* this is not the exact summary size of it,
-					it is only an upper estimation */
+	if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
+		alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN;
+
+	ret = jffs2_reserve_space_gc(c, alloclen, &alloclen, rawlen);
+	/* 'rawlen' is not the exact summary size; it is only an upper estimation */
 
 	if (ret)
 		return ret;
@@ -580,22 +609,17 @@
 		}
 		break;
 	default:
-		printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
-		       ref_offset(raw), je16_to_cpu(node->u.nodetype));
-		goto bail;
-	}
-
-	nraw = jffs2_alloc_raw_node_ref();
-	if (!nraw) {
-		ret = -ENOMEM;
-		goto out_node;
+		/* If it's inode-less, we don't _know_ what it is. Just copy it intact */
+		if (ic) {
+			printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n",
+			       ref_offset(raw), je16_to_cpu(node->u.nodetype));
+			goto bail;
+		}
 	}
 
 	/* OK, all the CRCs are good; this node can just be copied as-is. */
  retry:
-	nraw->flash_offset = phys_ofs;
-	nraw->__totlen = rawlen;
-	nraw->next_phys = NULL;
+	phys_ofs = write_ofs(c);
 
 	ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node);
 
@@ -603,17 +627,11 @@
 		printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n",
                        rawlen, phys_ofs, ret, retlen);
 		if (retlen) {
-                        /* Doesn't belong to any inode */
-			nraw->next_in_ino = NULL;
-
-			nraw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, nraw);
-			jffs2_mark_node_obsolete(c, nraw);
+			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL);
 		} else {
-			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset);
-                        jffs2_free_raw_node_ref(nraw);
+			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs);
 		}
-		if (!retried && (nraw = jffs2_alloc_raw_node_ref())) {
+		if (!retried) {
 			/* Try to reallocate space and retry */
 			uint32_t dummy;
 			struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size];
@@ -625,7 +643,7 @@
 			jffs2_dbg_acct_sanity_check(c,jeb);
 			jffs2_dbg_acct_paranoia_check(c, jeb);
 
-			ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen);
+			ret = jffs2_reserve_space_gc(c, rawlen, &dummy, rawlen);
 						/* this is not the exact summary size of it,
 							it is only an upper estimation */
 
@@ -638,25 +656,13 @@
 				goto retry;
 			}
 			D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-			jffs2_free_raw_node_ref(nraw);
 		}
 
-		jffs2_free_raw_node_ref(nraw);
 		if (!ret)
 			ret = -EIO;
 		goto out_node;
 	}
-	nraw->flash_offset |= REF_PRISTINE;
-	jffs2_add_physical_node_ref(c, nraw);
-
-	/* Link into per-inode list. This is safe because of the ic
-	   state being INO_STATE_GC. Note that if we're doing this
-	   for an inode which is in-core, the 'nraw' pointer is then
-	   going to be fetched from ic->nodes by our caller. */
-	spin_lock(&c->erase_completion_lock);
-        nraw->next_in_ino = ic->nodes;
-        ic->nodes = nraw;
-	spin_unlock(&c->erase_completion_lock);
+	jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic);
 
 	jffs2_mark_node_obsolete(c, raw);
 	D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw)));
@@ -675,19 +681,16 @@
 	struct jffs2_full_dnode *new_fn;
 	struct jffs2_raw_inode ri;
 	struct jffs2_node_frag *last_frag;
-	jint16_t dev;
+	union jffs2_device_node dev;
 	char *mdata = NULL, mdatalen = 0;
-	uint32_t alloclen, phys_ofs, ilen;
+	uint32_t alloclen, ilen;
 	int ret;
 
 	if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
 	    S_ISCHR(JFFS2_F_I_MODE(f)) ) {
 		/* For these, we don't actually need to read the old node */
-		/* FIXME: for minor or major > 255. */
-		dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) |
-			JFFS2_F_I_RDEV_MIN(f)));
+		mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
 		mdata = (char *)&dev;
-		mdatalen = sizeof(dev);
 		D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
 	} else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
 		mdatalen = fn->size;
@@ -706,7 +709,7 @@
 
 	}
 
-	ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen,
+	ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &alloclen,
 				JFFS2_SUMMARY_INODE_SIZE);
 	if (ret) {
 		printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n",
@@ -744,7 +747,7 @@
 	ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
 	ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
 
-	new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, ALLOC_GC);
+	new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, ALLOC_GC);
 
 	if (IS_ERR(new_fn)) {
 		printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn));
@@ -765,7 +768,7 @@
 {
 	struct jffs2_full_dirent *new_fd;
 	struct jffs2_raw_dirent rd;
-	uint32_t alloclen, phys_ofs;
+	uint32_t alloclen;
 	int ret;
 
 	rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -787,14 +790,14 @@
 	rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8));
 	rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize));
 
-	ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen,
+	ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &alloclen,
 				JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize));
 	if (ret) {
 		printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n",
 		       sizeof(rd)+rd.nsize, ret);
 		return ret;
 	}
-	new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC);
+	new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, ALLOC_GC);
 
 	if (IS_ERR(new_fd)) {
 		printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd));
@@ -922,7 +925,7 @@
 	struct jffs2_raw_inode ri;
 	struct jffs2_node_frag *frag;
 	struct jffs2_full_dnode *new_fn;
-	uint32_t alloclen, phys_ofs, ilen;
+	uint32_t alloclen, ilen;
 	int ret;
 
 	D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n",
@@ -1001,14 +1004,14 @@
 	ri.data_crc = cpu_to_je32(0);
 	ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
 
-	ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen,
-				JFFS2_SUMMARY_INODE_SIZE);
+	ret = jffs2_reserve_space_gc(c, sizeof(ri), &alloclen,
+				     JFFS2_SUMMARY_INODE_SIZE);
 	if (ret) {
 		printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n",
 		       sizeof(ri), ret);
 		return ret;
 	}
-	new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC);
+	new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_GC);
 
 	if (IS_ERR(new_fn)) {
 		printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn));
@@ -1070,7 +1073,7 @@
 {
 	struct jffs2_full_dnode *new_fn;
 	struct jffs2_raw_inode ri;
-	uint32_t alloclen, phys_ofs, offset, orig_end, orig_start;
+	uint32_t alloclen, offset, orig_end, orig_start;
 	int ret = 0;
 	unsigned char *comprbuf = NULL, *writebuf;
 	unsigned long pg;
@@ -1227,7 +1230,7 @@
 		uint32_t cdatalen;
 		uint16_t comprtype = JFFS2_COMPR_NONE;
 
-		ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs,
+		ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN,
 					&alloclen, JFFS2_SUMMARY_INODE_SIZE);
 
 		if (ret) {
@@ -1264,7 +1267,7 @@
 		ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
 		ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
 
-		new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC);
+		new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, ALLOC_GC);
 
 		jffs2_free_comprbuf(comprbuf, writebuf);
 
diff --git a/fs/jffs2/histo.h b/fs/jffs2/histo.h
deleted file mode 100644
index 22a93a0..0000000
--- a/fs/jffs2/histo.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* This file provides the bit-probabilities for the input file */
-#define BIT_DIVIDER 629
-static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h
new file mode 100644
index 0000000..2e0cc8e
--- /dev/null
+++ b/fs/jffs2/jffs2_fs_i.h
@@ -0,0 +1,55 @@
+/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */
+
+#ifndef _JFFS2_FS_I
+#define _JFFS2_FS_I
+
+#include <linux/version.h>
+#include <linux/rbtree.h>
+#include <linux/posix_acl.h>
+#include <asm/semaphore.h>
+
+struct jffs2_inode_info {
+	/* We need an internal mutex similar to inode->i_mutex.
+	   Unfortunately, we can't used the existing one, because
+	   either the GC would deadlock, or we'd have to release it
+	   before letting GC proceed. Or we'd have to put ugliness
+	   into the GC code so it didn't attempt to obtain the i_mutex
+	   for the inode(s) which are already locked */
+	struct semaphore sem;
+
+	/* The highest (datanode) version number used for this ino */
+	uint32_t highest_version;
+
+	/* List of data fragments which make up the file */
+	struct rb_root fragtree;
+
+	/* There may be one datanode which isn't referenced by any of the
+	   above fragments, if it contains a metadata update but no actual
+	   data - or if this is a directory inode */
+	/* This also holds the _only_ dnode for symlinks/device nodes,
+	   etc. */
+	struct jffs2_full_dnode *metadata;
+
+	/* Directory entries */
+	struct jffs2_full_dirent *dents;
+
+	/* The target path if this is the inode of a symlink */
+	unsigned char *target;
+
+	/* Some stuff we just have to keep in-core at all times, for each inode. */
+	struct jffs2_inode_cache *inocache;
+
+	uint16_t flags;
+	uint8_t usercompr;
+#if !defined (__ECOS)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2)
+	struct inode vfs_inode;
+#endif
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+	struct posix_acl *i_acl_access;
+	struct posix_acl *i_acl_default;
+#endif
+};
+
+#endif /* _JFFS2_FS_I */
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
new file mode 100644
index 0000000..b985949
--- /dev/null
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -0,0 +1,136 @@
+/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */
+
+#ifndef _JFFS2_FS_SB
+#define _JFFS2_FS_SB
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <asm/semaphore.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/rwsem.h>
+
+#define JFFS2_SB_FLAG_RO 1
+#define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */
+#define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */
+
+struct jffs2_inodirty;
+
+/* A struct for the overall file system control.  Pointers to
+   jffs2_sb_info structs are named `c' in the source code.
+   Nee jffs_control
+*/
+struct jffs2_sb_info {
+	struct mtd_info *mtd;
+
+	uint32_t highest_ino;
+	uint32_t checked_ino;
+
+	unsigned int flags;
+
+	struct task_struct *gc_task;	/* GC task struct */
+	struct completion gc_thread_start; /* GC thread start completion */
+	struct completion gc_thread_exit; /* GC thread exit completion port */
+
+	struct semaphore alloc_sem;	/* Used to protect all the following
+					   fields, and also to protect against
+					   out-of-order writing of nodes. And GC. */
+	uint32_t cleanmarker_size;	/* Size of an _inline_ CLEANMARKER
+					 (i.e. zero for OOB CLEANMARKER */
+
+	uint32_t flash_size;
+	uint32_t used_size;
+	uint32_t dirty_size;
+	uint32_t wasted_size;
+	uint32_t free_size;
+	uint32_t erasing_size;
+	uint32_t bad_size;
+	uint32_t sector_size;
+	uint32_t unchecked_size;
+
+	uint32_t nr_free_blocks;
+	uint32_t nr_erasing_blocks;
+
+	/* Number of free blocks there must be before we... */
+	uint8_t resv_blocks_write;	/* ... allow a normal filesystem write */
+	uint8_t resv_blocks_deletion;	/* ... allow a normal filesystem deletion */
+	uint8_t resv_blocks_gctrigger;	/* ... wake up the GC thread */
+	uint8_t resv_blocks_gcbad;	/* ... pick a block from the bad_list to GC */
+	uint8_t resv_blocks_gcmerge;	/* ... merge pages when garbage collecting */
+
+	uint32_t nospc_dirty_size;
+
+	uint32_t nr_blocks;
+	struct jffs2_eraseblock *blocks;	/* The whole array of blocks. Used for getting blocks
+						 * from the offset (blocks[ofs / sector_size]) */
+	struct jffs2_eraseblock *nextblock;	/* The block we're currently filling */
+
+	struct jffs2_eraseblock *gcblock;	/* The block we're currently garbage-collecting */
+
+	struct list_head clean_list;		/* Blocks 100% full of clean data */
+	struct list_head very_dirty_list;	/* Blocks with lots of dirty space */
+	struct list_head dirty_list;		/* Blocks with some dirty space */
+	struct list_head erasable_list;		/* Blocks which are completely dirty, and need erasing */
+	struct list_head erasable_pending_wbuf_list;	/* Blocks which need erasing but only after the current wbuf is flushed */
+	struct list_head erasing_list;		/* Blocks which are currently erasing */
+	struct list_head erase_pending_list;	/* Blocks which need erasing now */
+	struct list_head erase_complete_list;	/* Blocks which are erased and need the clean marker written to them */
+	struct list_head free_list;		/* Blocks which are free and ready to be used */
+	struct list_head bad_list;		/* Bad blocks. */
+	struct list_head bad_used_list;		/* Bad blocks with valid data in. */
+
+	spinlock_t erase_completion_lock;	/* Protect free_list and erasing_list
+						   against erase completion handler */
+	wait_queue_head_t erase_wait;		/* For waiting for erases to complete */
+
+	wait_queue_head_t inocache_wq;
+	struct jffs2_inode_cache **inocache_list;
+	spinlock_t inocache_lock;
+
+	/* Sem to allow jffs2_garbage_collect_deletion_dirent to
+	   drop the erase_completion_lock while it's holding a pointer
+	   to an obsoleted node. I don't like this. Alternatives welcomed. */
+	struct semaphore erase_free_sem;
+
+	uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
+
+#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
+	/* Write-behind buffer for NAND flash */
+	unsigned char *wbuf;
+	unsigned char *oobbuf;
+	uint32_t wbuf_ofs;
+	uint32_t wbuf_len;
+	struct jffs2_inodirty *wbuf_inodes;
+
+	struct rw_semaphore wbuf_sem;	/* Protects the write buffer */
+
+	/* Information about out-of-band area usage... */
+	struct nand_ecclayout *ecclayout;
+	uint32_t badblock_pos;
+	uint32_t fsdata_pos;
+	uint32_t fsdata_len;
+#endif
+
+	struct jffs2_summary *summary;		/* Summary information */
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+#define XATTRINDEX_HASHSIZE	(57)
+	uint32_t highest_xid;
+	uint32_t highest_xseqno;
+	struct list_head xattrindex[XATTRINDEX_HASHSIZE];
+	struct list_head xattr_unchecked;
+	struct list_head xattr_dead_list;
+	struct jffs2_xattr_ref *xref_dead_list;
+	struct jffs2_xattr_ref *xref_temp;
+	struct rw_semaphore xattr_sem;
+	uint32_t xdatum_mem_usage;
+	uint32_t xdatum_mem_threshold;
+#endif
+	/* OS-private pointer for getting back to master superblock info */
+	void *os_priv;
+};
+
+#endif /* _JFFS2_FB_SB */
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
index 036cbd1..8310c95 100644
--- a/fs/jffs2/malloc.c
+++ b/fs/jffs2/malloc.c
@@ -26,6 +26,10 @@
 static kmem_cache_t *raw_node_ref_slab;
 static kmem_cache_t *node_frag_slab;
 static kmem_cache_t *inode_cache_slab;
+#ifdef CONFIG_JFFS2_FS_XATTR
+static kmem_cache_t *xattr_datum_cache;
+static kmem_cache_t *xattr_ref_cache;
+#endif
 
 int __init jffs2_create_slab_caches(void)
 {
@@ -53,8 +57,8 @@
 	if (!tmp_dnode_info_slab)
 		goto err;
 
-	raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref",
-					      sizeof(struct jffs2_raw_node_ref),
+	raw_node_ref_slab = kmem_cache_create("jffs2_refblock",
+					      sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1),
 					      0, 0, NULL, NULL);
 	if (!raw_node_ref_slab)
 		goto err;
@@ -68,8 +72,24 @@
 	inode_cache_slab = kmem_cache_create("jffs2_inode_cache",
 					     sizeof(struct jffs2_inode_cache),
 					     0, 0, NULL, NULL);
-	if (inode_cache_slab)
-		return 0;
+	if (!inode_cache_slab)
+		goto err;
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+	xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum",
+					     sizeof(struct jffs2_xattr_datum),
+					     0, 0, NULL, NULL);
+	if (!xattr_datum_cache)
+		goto err;
+
+	xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref",
+					   sizeof(struct jffs2_xattr_ref),
+					   0, 0, NULL, NULL);
+	if (!xattr_ref_cache)
+		goto err;
+#endif
+
+	return 0;
  err:
 	jffs2_destroy_slab_caches();
 	return -ENOMEM;
@@ -91,6 +111,12 @@
 		kmem_cache_destroy(node_frag_slab);
 	if(inode_cache_slab)
 		kmem_cache_destroy(inode_cache_slab);
+#ifdef CONFIG_JFFS2_FS_XATTR
+	if (xattr_datum_cache)
+		kmem_cache_destroy(xattr_datum_cache);
+	if (xattr_ref_cache)
+		kmem_cache_destroy(xattr_ref_cache);
+#endif
 }
 
 struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
@@ -164,15 +190,65 @@
 	kmem_cache_free(tmp_dnode_info_slab, x);
 }
 
-struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
+struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
 {
 	struct jffs2_raw_node_ref *ret;
+
 	ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL);
-	dbg_memalloc("%p\n", ret);
+	if (ret) {
+		int i = 0;
+		for (i=0; i < REFS_PER_BLOCK; i++) {
+			ret[i].flash_offset = REF_EMPTY_NODE;
+			ret[i].next_in_ino = NULL;
+		}
+		ret[i].flash_offset = REF_LINK_NODE;
+		ret[i].next_in_ino = NULL;
+	}
 	return ret;
 }
 
-void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
+int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
+				 struct jffs2_eraseblock *jeb, int nr)
+{
+	struct jffs2_raw_node_ref **p, *ref;
+	int i = nr;
+
+	dbg_memalloc("%d\n", nr);
+
+	p = &jeb->last_node;
+	ref = *p;
+
+	dbg_memalloc("Reserving %d refs for block @0x%08x\n", nr, jeb->offset);
+
+	/* If jeb->last_node is really a valid node then skip over it */
+	if (ref && ref->flash_offset != REF_EMPTY_NODE)
+		ref++;
+
+	while (i) {
+		if (!ref) {
+			dbg_memalloc("Allocating new refblock linked from %p\n", p);
+			ref = *p = jffs2_alloc_refblock();
+			if (!ref)
+				return -ENOMEM;
+		}
+		if (ref->flash_offset == REF_LINK_NODE) {
+			p = &ref->next_in_ino;
+			ref = *p;
+			continue;
+		}
+		i--;
+		ref++;
+	}
+	jeb->allocated_refs = nr;
+
+	dbg_memalloc("Reserved %d refs for block @0x%08x, last_node is %p (%08x,%p)\n",
+		  nr, jeb->offset, jeb->last_node, jeb->last_node->flash_offset,
+		  jeb->last_node->next_in_ino);
+
+	return 0;
+}
+
+void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
 {
 	dbg_memalloc("%p\n", x);
 	kmem_cache_free(raw_node_ref_slab, x);
@@ -205,3 +281,42 @@
 	dbg_memalloc("%p\n", x);
 	kmem_cache_free(inode_cache_slab, x);
 }
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void)
+{
+	struct jffs2_xattr_datum *xd;
+	xd = kmem_cache_alloc(xattr_datum_cache, GFP_KERNEL);
+	dbg_memalloc("%p\n", xd);
+
+	memset(xd, 0, sizeof(struct jffs2_xattr_datum));
+	xd->class = RAWNODE_CLASS_XATTR_DATUM;
+	xd->node = (void *)xd;
+	INIT_LIST_HEAD(&xd->xindex);
+	return xd;
+}
+
+void jffs2_free_xattr_datum(struct jffs2_xattr_datum *xd)
+{
+	dbg_memalloc("%p\n", xd);
+	kmem_cache_free(xattr_datum_cache, xd);
+}
+
+struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void)
+{
+	struct jffs2_xattr_ref *ref;
+	ref = kmem_cache_alloc(xattr_ref_cache, GFP_KERNEL);
+	dbg_memalloc("%p\n", ref);
+
+	memset(ref, 0, sizeof(struct jffs2_xattr_ref));
+	ref->class = RAWNODE_CLASS_XATTR_REF;
+	ref->node = (void *)ref;
+	return ref;
+}
+
+void jffs2_free_xattr_ref(struct jffs2_xattr_ref *ref)
+{
+	dbg_memalloc("%p\n", ref);
+	kmem_cache_free(xattr_ref_cache, ref);
+}
+#endif
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
index 1d46677..7675b33 100644
--- a/fs/jffs2/nodelist.c
+++ b/fs/jffs2/nodelist.c
@@ -438,8 +438,7 @@
 	if (c->mtd->point) {
 		err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
 		if (!err && retlen < tn->csize) {
-			JFFS2_WARNING("MTD point returned len too short: %zu "
-					"instead of %u.\n", retlen, tn->csize);
+			JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
 			c->mtd->unpoint(c->mtd, buffer, ofs, len);
 		} else if (err)
 			JFFS2_WARNING("MTD point failed: error code %d.\n", err);
@@ -462,8 +461,7 @@
 		}
 
 		if (retlen != len) {
-			JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n",
-					ofs, retlen, len);
+			JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len);
 			err = -EIO;
 			goto free_out;
 		}
@@ -908,6 +906,9 @@
 {
 	struct jffs2_inode_cache **prev;
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+	BUG_ON(old->xref);
+#endif
 	dbg_inocache("del %p (ino #%u)\n", old, old->ino);
 	spin_lock(&c->inocache_lock);
 
@@ -940,6 +941,7 @@
 		this = c->inocache_list[i];
 		while (this) {
 			next = this->next;
+			jffs2_xattr_free_inode(c, this);
 			jffs2_free_inode_cache(this);
 			this = next;
 		}
@@ -954,9 +956,13 @@
 
 	for (i=0; i<c->nr_blocks; i++) {
 		this = c->blocks[i].first_node;
-		while(this) {
-			next = this->next_phys;
-			jffs2_free_raw_node_ref(this);
+		while (this) {
+			if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE)
+				next = this[REFS_PER_BLOCK].next_in_ino;
+			else
+				next = NULL;
+
+			jffs2_free_refblock(this);
 			this = next;
 		}
 		c->blocks[i].first_node = c->blocks[i].last_node = NULL;
@@ -1047,3 +1053,169 @@
 		cond_resched();
 	}
 }
+
+struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
+					       struct jffs2_eraseblock *jeb,
+					       uint32_t ofs, uint32_t len,
+					       struct jffs2_inode_cache *ic)
+{
+	struct jffs2_raw_node_ref *ref;
+
+	BUG_ON(!jeb->allocated_refs);
+	jeb->allocated_refs--;
+
+	ref = jeb->last_node;
+
+	dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset,
+		    ref->next_in_ino);
+
+	while (ref->flash_offset != REF_EMPTY_NODE) {
+		if (ref->flash_offset == REF_LINK_NODE)
+			ref = ref->next_in_ino;
+		else
+			ref++;
+	}
+
+	dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref, 
+		    ref->flash_offset, ofs, ref->next_in_ino, len);
+
+	ref->flash_offset = ofs;
+
+	if (!jeb->first_node) {
+		jeb->first_node = ref;
+		BUG_ON(ref_offset(ref) != jeb->offset);
+	} else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) {
+		uint32_t last_len = ref_totlen(c, jeb, jeb->last_node);
+
+		JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n",
+			    ref, ref_offset(ref), ref_offset(ref)+len,
+			    ref_offset(jeb->last_node), 
+			    ref_offset(jeb->last_node)+last_len);
+		BUG();
+	}
+	jeb->last_node = ref;
+
+	if (ic) {
+		ref->next_in_ino = ic->nodes;
+		ic->nodes = ref;
+	} else {
+		ref->next_in_ino = NULL;
+	}
+
+	switch(ref_flags(ref)) {
+	case REF_UNCHECKED:
+		c->unchecked_size += len;
+		jeb->unchecked_size += len;
+		break;
+
+	case REF_NORMAL:
+	case REF_PRISTINE:
+		c->used_size += len;
+		jeb->used_size += len;
+		break;
+
+	case REF_OBSOLETE:
+		c->dirty_size += len;
+		jeb->dirty_size += len;
+		break;
+	}
+	c->free_size -= len;
+	jeb->free_size -= len;
+
+#ifdef TEST_TOTLEN
+	/* Set (and test) __totlen field... for now */
+	ref->__totlen = len;
+	ref_totlen(c, jeb, ref);
+#endif
+	return ref;
+}
+
+/* No locking, no reservation of 'ref'. Do not use on a live file system */
+int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+			   uint32_t size)
+{
+	if (!size)
+		return 0;
+	if (unlikely(size > jeb->free_size)) {
+		printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n",
+		       size, jeb->free_size, jeb->wasted_size);
+		BUG();
+	}
+	/* REF_EMPTY_NODE is !obsolete, so that works OK */
+	if (jeb->last_node && ref_obsolete(jeb->last_node)) {
+#ifdef TEST_TOTLEN
+		jeb->last_node->__totlen += size;
+#endif
+		c->dirty_size += size;
+		c->free_size -= size;
+		jeb->dirty_size += size;
+		jeb->free_size -= size;
+	} else {
+		uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size;
+		ofs |= REF_OBSOLETE;
+
+		jffs2_link_node_ref(c, jeb, ofs, size, NULL);
+	}
+
+	return 0;
+}
+
+/* Calculate totlen from surrounding nodes or eraseblock */
+static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
+				    struct jffs2_eraseblock *jeb,
+				    struct jffs2_raw_node_ref *ref)
+{
+	uint32_t ref_end;
+	struct jffs2_raw_node_ref *next_ref = ref_next(ref);
+
+	if (next_ref)
+		ref_end = ref_offset(next_ref);
+	else {
+		if (!jeb)
+			jeb = &c->blocks[ref->flash_offset / c->sector_size];
+
+		/* Last node in block. Use free_space */
+		if (unlikely(ref != jeb->last_node)) {
+			printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n",
+			       ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0);
+			BUG();
+		}
+		ref_end = jeb->offset + c->sector_size - jeb->free_size;
+	}
+	return ref_end - ref_offset(ref);
+}
+
+uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+			    struct jffs2_raw_node_ref *ref)
+{
+	uint32_t ret;
+
+	ret = __ref_totlen(c, jeb, ref);
+
+#ifdef TEST_TOTLEN
+	if (unlikely(ret != ref->__totlen)) {
+		if (!jeb)
+			jeb = &c->blocks[ref->flash_offset / c->sector_size];
+
+		printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
+		       ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
+		       ret, ref->__totlen);
+		if (ref_next(ref)) {
+			printk(KERN_CRIT "next %p (0x%08x-0x%08x)\n", ref_next(ref), ref_offset(ref_next(ref)),
+			       ref_offset(ref_next(ref))+ref->__totlen);
+		} else 
+			printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node);
+
+		printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size);
+
+#if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS)
+		__jffs2_dbg_dump_node_refs_nolock(c, jeb);
+#endif
+
+		WARN_ON(1);
+
+		ret = ref->__totlen;
+	}
+#endif /* TEST_TOTLEN */
+	return ret;
+}
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 23a67bb..b16c60b 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -18,8 +18,10 @@
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/jffs2.h>
-#include <linux/jffs2_fs_sb.h>
-#include <linux/jffs2_fs_i.h>
+#include "jffs2_fs_sb.h"
+#include "jffs2_fs_i.h"
+#include "xattr.h"
+#include "acl.h"
 #include "summary.h"
 
 #ifdef __ECOS
@@ -75,14 +77,50 @@
 struct jffs2_raw_node_ref
 {
 	struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref
-		for this inode. If this is the last, it points to the inode_cache
-		for this inode instead. The inode_cache will have NULL in the first
-		word so you know when you've got there :) */
-	struct jffs2_raw_node_ref *next_phys;
+		for this object. If this _is_ the last, it points to the inode_cache,
+		xattr_ref or xattr_datum instead. The common part of those structures
+		has NULL in the first word. See jffs2_raw_ref_to_ic() below */
 	uint32_t flash_offset;
+#define TEST_TOTLEN
+#ifdef TEST_TOTLEN
 	uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */
+#endif
 };
 
+#define REF_LINK_NODE ((int32_t)-1)
+#define REF_EMPTY_NODE ((int32_t)-2)
+
+/* Use blocks of about 256 bytes */
+#define REFS_PER_BLOCK ((255/sizeof(struct jffs2_raw_node_ref))-1)
+
+static inline struct jffs2_raw_node_ref *ref_next(struct jffs2_raw_node_ref *ref)
+{
+	ref++;
+
+	/* Link to another block of refs */
+	if (ref->flash_offset == REF_LINK_NODE) {
+		ref = ref->next_in_ino;
+		if (!ref)
+			return ref;
+	}
+
+	/* End of chain */
+	if (ref->flash_offset == REF_EMPTY_NODE)
+		return NULL;
+
+	return ref;
+}
+
+static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
+{
+	while(raw->next_in_ino)
+		raw = raw->next_in_ino;
+
+	/* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and
+	   not actually a jffs2_inode_cache. Check ->class */
+	return ((struct jffs2_inode_cache *)raw);
+}
+
         /* flash_offset & 3 always has to be zero, because nodes are
 	   always aligned at 4 bytes. So we have a couple of extra bits
 	   to play with, which indicate the node's status; see below: */
@@ -95,6 +133,11 @@
 #define ref_obsolete(ref)	(((ref)->flash_offset & 3) == REF_OBSOLETE)
 #define mark_ref_normal(ref)    do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
 
+/* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates
+   it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get
+   copied. If you need to do anything different to GC inode-less nodes, then
+   you need to modify gc.c accordingly. */
+
 /* For each inode in the filesystem, we need to keep a record of
    nlink, because it would be a PITA to scan the whole directory tree
    at read_inode() time to calculate it, and to keep sufficient information
@@ -103,15 +146,27 @@
    a pointer to the first physical node which is part of this inode, too.
 */
 struct jffs2_inode_cache {
+	/* First part of structure is shared with other objects which
+	   can terminate the raw node refs' next_in_ino list -- which
+	   currently struct jffs2_xattr_datum and struct jffs2_xattr_ref. */
+
 	struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
 		temporary lists of dirents, and later must be set to
 		NULL to mark the end of the raw_node_ref->next_in_ino
 		chain. */
-	struct jffs2_inode_cache *next;
 	struct jffs2_raw_node_ref *nodes;
+	uint8_t class;	/* It's used for identification */
+
+	/* end of shared structure */
+
+	uint8_t flags;
+	uint16_t state;
 	uint32_t ino;
+	struct jffs2_inode_cache *next;
+#ifdef CONFIG_JFFS2_FS_XATTR
+	struct jffs2_xattr_ref *xref;
+#endif
 	int nlink;
-	int state;
 };
 
 /* Inode states for 'state' above. We need the 'GC' state to prevent
@@ -125,8 +180,16 @@
 #define INO_STATE_READING	5	/* In read_inode() */
 #define INO_STATE_CLEARING	6	/* In clear_inode() */
 
+#define INO_FLAGS_XATTR_CHECKED	0x01	/* has no duplicate xattr_ref */
+
+#define RAWNODE_CLASS_INODE_CACHE	0
+#define RAWNODE_CLASS_XATTR_DATUM	1
+#define RAWNODE_CLASS_XATTR_REF		2
+
 #define INOCACHE_HASHSIZE 128
 
+#define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size)
+
 /*
   Larger representation of a raw node, kept in-core only when the
   struct inode for this particular ino is instantiated.
@@ -192,6 +255,7 @@
 	uint32_t wasted_size;
 	uint32_t free_size;	/* Note that sector_size - free_size
 				   is the address of the first free space */
+	uint32_t allocated_refs;
 	struct jffs2_raw_node_ref *first_node;
 	struct jffs2_raw_node_ref *last_node;
 
@@ -203,57 +267,7 @@
 	return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024);
 }
 
-/* Calculate totlen from surrounding nodes or eraseblock */
-static inline uint32_t __ref_totlen(struct jffs2_sb_info *c,
-				    struct jffs2_eraseblock *jeb,
-				    struct jffs2_raw_node_ref *ref)
-{
-	uint32_t ref_end;
-
-	if (ref->next_phys)
-		ref_end = ref_offset(ref->next_phys);
-	else {
-		if (!jeb)
-			jeb = &c->blocks[ref->flash_offset / c->sector_size];
-
-		/* Last node in block. Use free_space */
-		BUG_ON(ref != jeb->last_node);
-		ref_end = jeb->offset + c->sector_size - jeb->free_size;
-	}
-	return ref_end - ref_offset(ref);
-}
-
-static inline uint32_t ref_totlen(struct jffs2_sb_info *c,
-				  struct jffs2_eraseblock *jeb,
-				  struct jffs2_raw_node_ref *ref)
-{
-	uint32_t ret;
-
-#if CONFIG_JFFS2_FS_DEBUG > 0
-	if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) {
-		printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n",
-		       jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref));
-		BUG();
-	}
-#endif
-
-#if 1
-	ret = ref->__totlen;
-#else
-	/* This doesn't actually work yet */
-	ret = __ref_totlen(c, jeb, ref);
-	if (ret != ref->__totlen) {
-		printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n",
-		       ref, ref_offset(ref), ref_offset(ref)+ref->__totlen,
-		       ret, ref->__totlen);
-		if (!jeb)
-			jeb = &c->blocks[ref->flash_offset / c->sector_size];
-		jffs2_dbg_dump_node_refs_nolock(c, jeb);
-		BUG();
-	}
-#endif
-	return ret;
-}
+#define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c))
 
 #define ALLOC_NORMAL	0	/* Normal allocation */
 #define ALLOC_DELETION	1	/* Deletion node. Best to allow it */
@@ -268,13 +282,15 @@
 
 #define PAD(x) (((x)+3)&~3)
 
-static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw)
+static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
 {
-	while(raw->next_in_ino) {
-		raw = raw->next_in_ino;
+	if (old_valid_dev(rdev)) {
+		jdev->old = cpu_to_je16(old_encode_dev(rdev));
+		return sizeof(jdev->old);
+	} else {
+		jdev->new = cpu_to_je32(new_encode_dev(rdev));
+		return sizeof(jdev->new);
 	}
-
-	return ((struct jffs2_inode_cache *)raw);
 }
 
 static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
@@ -299,7 +315,6 @@
 	return rb_entry(node, struct jffs2_node_frag, rb);
 }
 
-#define rb_parent(rb) ((rb)->rb_parent)
 #define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
 #define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
 #define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
@@ -324,28 +339,44 @@
 int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
 void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
 int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn);
+struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c,
+					       struct jffs2_eraseblock *jeb,
+					       uint32_t ofs, uint32_t len,
+					       struct jffs2_inode_cache *ic);
+extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c,
+				   struct jffs2_eraseblock *jeb,
+				   struct jffs2_raw_node_ref *ref);
 
 /* nodemgmt.c */
 int jffs2_thread_should_wake(struct jffs2_sb_info *c);
-int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
 			uint32_t *len, int prio, uint32_t sumsize);
-int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
 			uint32_t *len, uint32_t sumsize);
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new);
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, 
+						       uint32_t ofs, uint32_t len,
+						       struct jffs2_inode_cache *ic);
 void jffs2_complete_reservation(struct jffs2_sb_info *c);
 void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
 
 /* write.c */
 int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri);
 
-struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode);
-struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode);
+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+					   struct jffs2_raw_inode *ri, const unsigned char *data,
+					   uint32_t datalen, int alloc_mode);
+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+					     struct jffs2_raw_dirent *rd, const unsigned char *name,
+					     uint32_t namelen, int alloc_mode);
 int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 			    struct jffs2_raw_inode *ri, unsigned char *buf,
 			    uint32_t offset, uint32_t writelen, uint32_t *retlen);
-int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen);
-int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
-int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time);
+int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f,
+		    struct jffs2_raw_inode *ri, const char *name, int namelen);
+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name,
+		    int namelen, struct jffs2_inode_info *dead_f, uint32_t time);
+int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino,
+		   uint8_t type, const char *name, int namelen, uint32_t time);
 
 
 /* readinode.c */
@@ -368,12 +399,19 @@
 void jffs2_free_raw_inode(struct jffs2_raw_inode *);
 struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void);
 void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *);
-struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void);
-void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *);
+int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
+				 struct jffs2_eraseblock *jeb, int nr);
+void jffs2_free_refblock(struct jffs2_raw_node_ref *);
 struct jffs2_node_frag *jffs2_alloc_node_frag(void);
 void jffs2_free_node_frag(struct jffs2_node_frag *);
 struct jffs2_inode_cache *jffs2_alloc_inode_cache(void);
 void jffs2_free_inode_cache(struct jffs2_inode_cache *);
+#ifdef CONFIG_JFFS2_FS_XATTR
+struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void);
+void jffs2_free_xattr_datum(struct jffs2_xattr_datum *);
+struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void);
+void jffs2_free_xattr_ref(struct jffs2_xattr_ref *);
+#endif
 
 /* gc.c */
 int jffs2_garbage_collect_pass(struct jffs2_sb_info *c);
@@ -393,12 +431,14 @@
 				uint32_t ofs, uint32_t len);
 struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino);
 int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
+int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size);
 
 /* build.c */
 int jffs2_do_mount_fs(struct jffs2_sb_info *c);
 
 /* erase.c */
 void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count);
+void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 /* wbuf.c */
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index 49127a1..d883769 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -23,13 +23,12 @@
  *	jffs2_reserve_space - request physical space to write nodes to flash
  *	@c: superblock info
  *	@minsize: Minimum acceptable size of allocation
- *	@ofs: Returned value of node offset
  *	@len: Returned value of allocation length
  *	@prio: Allocation type - ALLOC_{NORMAL,DELETION}
  *
  *	Requests a block of physical space on the flash. Returns zero for success
- *	and puts 'ofs' and 'len' into the appriopriate place, or returns -ENOSPC
- *	or other error if appropriate.
+ *	and puts 'len' into the appropriate place, or returns -ENOSPC or other 
+ *	error if appropriate. Doesn't return len since that's 
  *
  *	If it returns zero, jffs2_reserve_space() also downs the per-filesystem
  *	allocation semaphore, to prevent more than one allocation from being
@@ -40,9 +39,9 @@
  */
 
 static int jffs2_do_reserve_space(struct jffs2_sb_info *c,  uint32_t minsize,
-					uint32_t *ofs, uint32_t *len, uint32_t sumsize);
+				  uint32_t *len, uint32_t sumsize);
 
-int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
+int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
 			uint32_t *len, int prio, uint32_t sumsize)
 {
 	int ret = -EAGAIN;
@@ -132,19 +131,21 @@
 			spin_lock(&c->erase_completion_lock);
 		}
 
-		ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize);
+		ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
 		if (ret) {
 			D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret));
 		}
 	}
 	spin_unlock(&c->erase_completion_lock);
+	if (!ret)
+		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
 	if (ret)
 		up(&c->alloc_sem);
 	return ret;
 }
 
-int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs,
-			uint32_t *len, uint32_t sumsize)
+int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize,
+			   uint32_t *len, uint32_t sumsize)
 {
 	int ret = -EAGAIN;
 	minsize = PAD(minsize);
@@ -153,12 +154,15 @@
 
 	spin_lock(&c->erase_completion_lock);
 	while(ret == -EAGAIN) {
-		ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize);
+		ret = jffs2_do_reserve_space(c, minsize, len, sumsize);
 		if (ret) {
 		        D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret));
 		}
 	}
 	spin_unlock(&c->erase_completion_lock);
+	if (!ret)
+		ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+
 	return ret;
 }
 
@@ -207,8 +211,7 @@
 			struct jffs2_eraseblock *ejeb;
 
 			ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list);
-			list_del(&ejeb->list);
-			list_add_tail(&ejeb->list, &c->erase_pending_list);
+			list_move_tail(&ejeb->list, &c->erase_pending_list);
 			c->nr_erasing_blocks++;
 			jffs2_erase_pending_trigger(c);
 			D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n",
@@ -259,10 +262,11 @@
 }
 
 /* Called with alloc sem _and_ erase_completion_lock */
-static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize)
+static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize,
+				  uint32_t *len, uint32_t sumsize)
 {
 	struct jffs2_eraseblock *jeb = c->nextblock;
-	uint32_t reserved_size; 			/* for summary information at the end of the jeb */
+	uint32_t reserved_size;				/* for summary information at the end of the jeb */
 	int ret;
 
  restart:
@@ -312,6 +316,8 @@
 		}
 	} else {
 		if (jeb && minsize > jeb->free_size) {
+			uint32_t waste;
+
 			/* Skip the end of this block and file it as having some dirty space */
 			/* If there's a pending write to it, flush now */
 
@@ -324,10 +330,26 @@
 				goto restart;
 			}
 
-			c->wasted_size += jeb->free_size;
-			c->free_size -= jeb->free_size;
-			jeb->wasted_size += jeb->free_size;
-			jeb->free_size = 0;
+			spin_unlock(&c->erase_completion_lock);
+
+			ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+			if (ret)
+				return ret;
+			/* Just lock it again and continue. Nothing much can change because
+			   we hold c->alloc_sem anyway. In fact, it's not entirely clear why
+			   we hold c->erase_completion_lock in the majority of this function...
+			   but that's a question for another (more caffeine-rich) day. */
+			spin_lock(&c->erase_completion_lock);
+
+			waste = jeb->free_size;
+			jffs2_link_node_ref(c, jeb,
+					    (jeb->offset + c->sector_size - waste) | REF_OBSOLETE,
+					    waste, NULL);
+			/* FIXME: that made it count as dirty. Convert to wasted */
+			jeb->dirty_size -= waste;
+			c->dirty_size -= waste;
+			jeb->wasted_size += waste;
+			c->wasted_size += waste;
 
 			jffs2_close_nextblock(c, jeb);
 			jeb = NULL;
@@ -349,7 +371,6 @@
 	}
 	/* OK, jeb (==c->nextblock) is now pointing at a block which definitely has
 	   enough space */
-	*ofs = jeb->offset + (c->sector_size - jeb->free_size);
 	*len = jeb->free_size - reserved_size;
 
 	if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size &&
@@ -365,7 +386,8 @@
 		spin_lock(&c->erase_completion_lock);
 	}
 
-	D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs));
+	D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n",
+		  *len, jeb->offset + (c->sector_size - jeb->free_size)));
 	return 0;
 }
 
@@ -374,7 +396,6 @@
  *	@c: superblock info
  *	@new: new node reference to add
  *	@len: length of this physical node
- *	@dirty: dirty flag for new node
  *
  *	Should only be used to report nodes for which space has been allocated
  *	by jffs2_reserve_space.
@@ -382,42 +403,30 @@
  *	Must be called with the alloc_sem held.
  */
 
-int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new)
+struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c,
+						       uint32_t ofs, uint32_t len,
+						       struct jffs2_inode_cache *ic)
 {
 	struct jffs2_eraseblock *jeb;
-	uint32_t len;
+	struct jffs2_raw_node_ref *new;
 
-	jeb = &c->blocks[new->flash_offset / c->sector_size];
-	len = ref_totlen(c, jeb, new);
+	jeb = &c->blocks[ofs / c->sector_size];
 
-	D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len));
+	D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n",
+		  ofs & ~3, ofs & 3, len));
 #if 1
-	/* we could get some obsolete nodes after nextblock was refiled
-	   in wbuf.c */
-	if ((c->nextblock || !ref_obsolete(new))
-	    &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) {
+	/* Allow non-obsolete nodes only to be added at the end of c->nextblock, 
+	   if c->nextblock is set. Note that wbuf.c will file obsolete nodes
+	   even after refiling c->nextblock */
+	if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE))
+	    && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) {
 		printk(KERN_WARNING "argh. node added in wrong place\n");
-		jffs2_free_raw_node_ref(new);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 #endif
 	spin_lock(&c->erase_completion_lock);
 
-	if (!jeb->first_node)
-		jeb->first_node = new;
-	if (jeb->last_node)
-		jeb->last_node->next_phys = new;
-	jeb->last_node = new;
-
-	jeb->free_size -= len;
-	c->free_size -= len;
-	if (ref_obsolete(new)) {
-		jeb->dirty_size += len;
-		c->dirty_size += len;
-	} else {
-		jeb->used_size += len;
-		c->used_size += len;
-	}
+	new = jffs2_link_node_ref(c, jeb, ofs, len, ic);
 
 	if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) {
 		/* If it lives on the dirty_list, jffs2_reserve_space will put it there */
@@ -438,7 +447,7 @@
 
 	spin_unlock(&c->erase_completion_lock);
 
-	return 0;
+	return new;
 }
 
 
@@ -470,8 +479,9 @@
 	struct jffs2_unknown_node n;
 	int ret, addedsize;
 	size_t retlen;
+	uint32_t freed_len;
 
-	if(!ref) {
+	if(unlikely(!ref)) {
 		printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n");
 		return;
 	}
@@ -499,32 +509,34 @@
 
 	spin_lock(&c->erase_completion_lock);
 
+	freed_len = ref_totlen(c, jeb, ref);
+
 	if (ref_flags(ref) == REF_UNCHECKED) {
-		D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) {
+		D1(if (unlikely(jeb->unchecked_size < freed_len)) {
 			printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n",
-			       ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size);
+			       freed_len, blocknr, ref->flash_offset, jeb->used_size);
 			BUG();
 		})
-		D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref)));
-		jeb->unchecked_size -= ref_totlen(c, jeb, ref);
-		c->unchecked_size -= ref_totlen(c, jeb, ref);
+		D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), freed_len));
+		jeb->unchecked_size -= freed_len;
+		c->unchecked_size -= freed_len;
 	} else {
-		D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) {
+		D1(if (unlikely(jeb->used_size < freed_len)) {
 			printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n",
-			       ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size);
+			       freed_len, blocknr, ref->flash_offset, jeb->used_size);
 			BUG();
 		})
-		D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref)));
-		jeb->used_size -= ref_totlen(c, jeb, ref);
-		c->used_size -= ref_totlen(c, jeb, ref);
+		D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), freed_len));
+		jeb->used_size -= freed_len;
+		c->used_size -= freed_len;
 	}
 
 	// Take care, that wasted size is taken into concern
-	if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) {
-		D1(printk(KERN_DEBUG "Dirtying\n"));
-		addedsize = ref_totlen(c, jeb, ref);
-		jeb->dirty_size += ref_totlen(c, jeb, ref);
-		c->dirty_size += ref_totlen(c, jeb, ref);
+	if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) {
+		D1(printk("Dirtying\n"));
+		addedsize = freed_len;
+		jeb->dirty_size += freed_len;
+		c->dirty_size += freed_len;
 
 		/* Convert wasted space to dirty, if not a bad block */
 		if (jeb->wasted_size) {
@@ -543,10 +555,10 @@
 			}
 		}
 	} else {
-		D1(printk(KERN_DEBUG "Wasting\n"));
+		D1(printk("Wasting\n"));
 		addedsize = 0;
-		jeb->wasted_size += ref_totlen(c, jeb, ref);
-		c->wasted_size += ref_totlen(c, jeb, ref);
+		jeb->wasted_size += freed_len;
+		c->wasted_size += freed_len;
 	}
 	ref->flash_offset = ref_offset(ref) | REF_OBSOLETE;
 
@@ -622,7 +634,7 @@
 	/* The erase_free_sem is locked, and has been since before we marked the node obsolete
 	   and potentially put its eraseblock onto the erase_pending_list. Thus, we know that
 	   the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet
-	   by jffs2_free_all_node_refs() in erase.c. Which is nice. */
+	   by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */
 
 	D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref)));
 	ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n);
@@ -634,8 +646,8 @@
 		printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen);
 		goto out_erase_sem;
 	}
-	if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) {
-		printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref));
+	if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) {
+		printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), freed_len);
 		goto out_erase_sem;
 	}
 	if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) {
@@ -677,57 +689,23 @@
 		*p = ref->next_in_ino;
 		ref->next_in_ino = NULL;
 
-		if (ic->nodes == (void *)ic && ic->nlink == 0)
-			jffs2_del_ino_cache(c, ic);
-
-		spin_unlock(&c->erase_completion_lock);
-	}
-
-
-	/* Merge with the next node in the physical list, if there is one
-	   and if it's also obsolete and if it doesn't belong to any inode */
-	if (ref->next_phys && ref_obsolete(ref->next_phys) &&
-	    !ref->next_phys->next_in_ino) {
-		struct jffs2_raw_node_ref *n = ref->next_phys;
-
-		spin_lock(&c->erase_completion_lock);
-
-		ref->__totlen += n->__totlen;
-		ref->next_phys = n->next_phys;
-                if (jeb->last_node == n) jeb->last_node = ref;
-		if (jeb->gc_node == n) {
-			/* gc will be happy continuing gc on this node */
-			jeb->gc_node=ref;
-		}
-		spin_unlock(&c->erase_completion_lock);
-
-		jffs2_free_raw_node_ref(n);
-	}
-
-	/* Also merge with the previous node in the list, if there is one
-	   and that one is obsolete */
-	if (ref != jeb->first_node ) {
-		struct jffs2_raw_node_ref *p = jeb->first_node;
-
-		spin_lock(&c->erase_completion_lock);
-
-		while (p->next_phys != ref)
-			p = p->next_phys;
-
-		if (ref_obsolete(p) && !ref->next_in_ino) {
-			p->__totlen += ref->__totlen;
-			if (jeb->last_node == ref) {
-				jeb->last_node = p;
-			}
-			if (jeb->gc_node == ref) {
-				/* gc will be happy continuing gc on this node */
-				jeb->gc_node=p;
-			}
-			p->next_phys = ref->next_phys;
-			jffs2_free_raw_node_ref(ref);
+		switch (ic->class) {
+#ifdef CONFIG_JFFS2_FS_XATTR
+			case RAWNODE_CLASS_XATTR_DATUM:
+				jffs2_release_xattr_datum(c, (struct jffs2_xattr_datum *)ic);
+				break;
+			case RAWNODE_CLASS_XATTR_REF:
+				jffs2_release_xattr_ref(c, (struct jffs2_xattr_ref *)ic);
+				break;
+#endif
+			default:
+				if (ic->nodes == (void *)ic && ic->nlink == 0)
+					jffs2_del_ino_cache(c, ic);
+				break;
 		}
 		spin_unlock(&c->erase_completion_lock);
 	}
+
  out_erase_sem:
 	up(&c->erase_free_sem);
 }
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index d307cf5..9f41fc0 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -31,9 +31,7 @@
 #define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
 #define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid)
 #define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid)
-
-#define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f)))
-#define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f)))
+#define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev)
 
 #define ITIME(sec) ((struct timespec){sec, 0})
 #define I_SEC(tv) ((tv).tv_sec)
@@ -60,6 +58,10 @@
 	f->target = NULL;
 	f->flags = 0;
 	f->usercompr = 0;
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+	f->i_acl_access = JFFS2_ACL_NOT_CACHED;
+	f->i_acl_default = JFFS2_ACL_NOT_CACHED;
+#endif
 }
 
 
@@ -90,13 +92,10 @@
 #define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e)
 #define jffs2_wbuf_timeout NULL
 #define jffs2_wbuf_process NULL
-#define jffs2_nor_ecc(c) (0)
 #define jffs2_dataflash(c) (0)
-#define jffs2_nor_wbuf_flash(c) (0)
-#define jffs2_nor_ecc_flash_setup(c) (0)
-#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0)
 #define jffs2_dataflash_setup(c) (0)
 #define jffs2_dataflash_cleanup(c) do {} while (0)
+#define jffs2_nor_wbuf_flash(c) (0)
 #define jffs2_nor_wbuf_flash_setup(c) (0)
 #define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0)
 
@@ -107,9 +106,7 @@
 #ifdef CONFIG_JFFS2_SUMMARY
 #define jffs2_can_mark_obsolete(c) (0)
 #else
-#define jffs2_can_mark_obsolete(c) \
-  ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \
-   c->mtd->type == MTD_RAM)
+#define jffs2_can_mark_obsolete(c) (c->mtd->flags & (MTD_BIT_WRITEABLE))
 #endif
 
 #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH)
@@ -133,15 +130,11 @@
 int jffs2_nand_flash_setup(struct jffs2_sb_info *c);
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c);
 
-#define jffs2_nor_ecc(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_ECC))
-int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c);
-void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c);
-
 #define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH)
 int jffs2_dataflash_setup(struct jffs2_sb_info *c);
 void jffs2_dataflash_cleanup(struct jffs2_sb_info *c);
 
-#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_PROGRAM_REGIONS))
+#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE))
 int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
 void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
 
@@ -165,7 +158,7 @@
 /* file.c */
 extern const struct file_operations jffs2_file_operations;
 extern struct inode_operations jffs2_file_inode_operations;
-extern struct address_space_operations jffs2_file_address_operations;
+extern const struct address_space_operations jffs2_file_address_operations;
 int jffs2_fsync(struct file *, struct dentry *, int);
 int jffs2_do_readpage_unlock (struct inode *inode, struct page *pg);
 
@@ -182,7 +175,7 @@
 void jffs2_dirty_inode(struct inode *inode);
 struct inode *jffs2_new_inode (struct inode *dir_i, int mode,
 			       struct jffs2_raw_inode *ri);
-int jffs2_statfs (struct super_block *, struct kstatfs *);
+int jffs2_statfs (struct dentry *, struct kstatfs *);
 void jffs2_write_super (struct super_block *);
 int jffs2_remount_fs (struct super_block *, int *, char *);
 int jffs2_do_fill_super(struct super_block *sb, void *data, int silent);
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index f169564..cc18992 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -66,7 +66,7 @@
 			jffs2_free_full_dnode(tn->fn);
 			jffs2_free_tmp_dnode_info(tn);
 
-			this = this->rb_parent;
+			this = rb_parent(this);
 			if (!this)
 				break;
 
@@ -116,19 +116,42 @@
 				uint32_t *latest_mctime, uint32_t *mctime_ver)
 {
 	struct jffs2_full_dirent *fd;
+	uint32_t crc;
 
-	/* The direntry nodes are checked during the flash scanning */
-	BUG_ON(ref_flags(ref) == REF_UNCHECKED);
 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
 	BUG_ON(ref_obsolete(ref));
 
-	/* Sanity check */
-	if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
-		JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
-		       ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
+	crc = crc32(0, rd, sizeof(*rd) - 8);
+	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
+		JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n",
+			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
 		return 1;
 	}
 
+	/* If we've never checked the CRCs on this node, check them now */
+	if (ref_flags(ref) == REF_UNCHECKED) {
+		struct jffs2_eraseblock *jeb;
+		int len;
+
+		/* Sanity check */
+		if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) {
+			JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n",
+				    ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen));
+			return 1;
+		}
+
+		jeb = &c->blocks[ref->flash_offset / c->sector_size];
+		len = ref_totlen(c, jeb, ref);
+
+		spin_lock(&c->erase_completion_lock);
+		jeb->used_size += len;
+		jeb->unchecked_size -= len;
+		c->used_size += len;
+		c->unchecked_size -= len;
+		ref->flash_offset = ref_offset(ref) | REF_PRISTINE;
+		spin_unlock(&c->erase_completion_lock);
+	}
+
 	fd = jffs2_alloc_full_dirent(rd->nsize + 1);
 	if (unlikely(!fd))
 		return -ENOMEM;
@@ -198,13 +221,21 @@
 	struct jffs2_tmp_dnode_info *tn;
 	uint32_t len, csize;
 	int ret = 1;
+	uint32_t crc;
 
 	/* Obsoleted. This cannot happen, surely? dwmw2 20020308 */
 	BUG_ON(ref_obsolete(ref));
 
+	crc = crc32(0, rd, sizeof(*rd) - 8);
+	if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
+		JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n",
+			     ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
+		return 1;
+	}
+
 	tn = jffs2_alloc_tmp_dnode_info();
 	if (!tn) {
-		JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn));
+		JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn));
 		return -ENOMEM;
 	}
 
@@ -213,14 +244,6 @@
 
 	/* If we've never checked the CRCs on this node, check them now */
 	if (ref_flags(ref) == REF_UNCHECKED) {
-		uint32_t crc;
-
-		crc = crc32(0, rd, sizeof(*rd) - 8);
-		if (unlikely(crc != je32_to_cpu(rd->node_crc))) {
-			JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n",
-					ref_offset(ref), je32_to_cpu(rd->node_crc), crc);
-			goto free_out;
-		}
 
 		/* Sanity checks */
 		if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) ||
@@ -343,7 +366,7 @@
  * Helper function for jffs2_get_inode_nodes().
  * It is called every time an unknown node is found.
  *
- * Returns: 0 on succes;
+ * Returns: 0 on success;
  * 	    1 if the node should be marked obsolete;
  * 	    negative error code on failure.
  */
@@ -354,37 +377,30 @@
 
 	un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype));
 
-	if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) {
-		/* Hmmm. This should have been caught at scan time. */
-		JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref));
-		jffs2_dbg_dump_node(c, ref_offset(ref));
+	switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
+
+	case JFFS2_FEATURE_INCOMPAT:
+		JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
+			    je16_to_cpu(un->nodetype), ref_offset(ref));
+		/* EEP */
+		BUG();
+		break;
+
+	case JFFS2_FEATURE_ROCOMPAT:
+		JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
+			    je16_to_cpu(un->nodetype), ref_offset(ref));
+		BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
+		break;
+
+	case JFFS2_FEATURE_RWCOMPAT_COPY:
+		JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
+			     je16_to_cpu(un->nodetype), ref_offset(ref));
+		break;
+
+	case JFFS2_FEATURE_RWCOMPAT_DELETE:
+		JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
+			     je16_to_cpu(un->nodetype), ref_offset(ref));
 		return 1;
-	} else {
-		switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) {
-
-		case JFFS2_FEATURE_INCOMPAT:
-			JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n",
-				je16_to_cpu(un->nodetype), ref_offset(ref));
-			/* EEP */
-			BUG();
-			break;
-
-		case JFFS2_FEATURE_ROCOMPAT:
-			JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n",
-					je16_to_cpu(un->nodetype), ref_offset(ref));
-			BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO));
-			break;
-
-		case JFFS2_FEATURE_RWCOMPAT_COPY:
-			JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n",
-					je16_to_cpu(un->nodetype), ref_offset(ref));
-			break;
-
-		case JFFS2_FEATURE_RWCOMPAT_DELETE:
-			JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n",
-					je16_to_cpu(un->nodetype), ref_offset(ref));
-			return 1;
-		}
 	}
 
 	return 0;
@@ -434,7 +450,7 @@
 	}
 
 	if (retlen < len) {
-		JFFS2_ERROR("short read at %#08x: %d instead of %d.\n",
+		JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n",
 				offs, retlen, len);
 		return -EIO;
 	}
@@ -542,13 +558,25 @@
 		}
 
 		if (retlen < len) {
-			JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len);
+			JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len);
 			err = -EIO;
 			goto free_out;
 		}
 
 		node = (union jffs2_node_union *)bufstart;
 
+		/* No need to mask in the valid bit; it shouldn't be invalid */
+		if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) {
+			JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n",
+				     ref_offset(ref), je16_to_cpu(node->u.magic),
+				     je16_to_cpu(node->u.nodetype),
+				     je32_to_cpu(node->u.totlen),
+				     je32_to_cpu(node->u.hdr_crc));
+			jffs2_dbg_dump_node(c, ref_offset(ref));
+			jffs2_mark_node_obsolete(c, ref);
+			goto cont;
+		}
+
 		switch (je16_to_cpu(node->u.nodetype)) {
 
 		case JFFS2_NODETYPE_DIRENT:
@@ -606,6 +634,7 @@
 				goto free_out;
 
 		}
+	cont:
 		spin_lock(&c->erase_completion_lock);
 	}
 
@@ -679,12 +708,12 @@
 			jffs2_mark_node_obsolete(c, fn->raw);
 
 		BUG_ON(rb->rb_left);
-		if (rb->rb_parent && rb->rb_parent->rb_left == rb) {
+		if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) {
 			/* We were then left-hand child of our parent. We need
 			 * to move our own right-hand child into our place. */
 			repl_rb = rb->rb_right;
 			if (repl_rb)
-				repl_rb->rb_parent = rb->rb_parent;
+				rb_set_parent(repl_rb, rb_parent(rb));
 		} else
 			repl_rb = NULL;
 
@@ -692,14 +721,14 @@
 
 		/* Remove the spent tn from the tree; don't bother rebalancing
 		 * but put our right-hand child in our own place. */
-		if (tn->rb.rb_parent) {
-			if (tn->rb.rb_parent->rb_left == &tn->rb)
-				tn->rb.rb_parent->rb_left = repl_rb;
-			else if (tn->rb.rb_parent->rb_right == &tn->rb)
-				tn->rb.rb_parent->rb_right = repl_rb;
+		if (rb_parent(&tn->rb)) {
+			if (rb_parent(&tn->rb)->rb_left == &tn->rb)
+				rb_parent(&tn->rb)->rb_left = repl_rb;
+			else if (rb_parent(&tn->rb)->rb_right == &tn->rb)
+				rb_parent(&tn->rb)->rb_right = repl_rb;
 			else BUG();
 		} else if (tn->rb.rb_right)
-			tn->rb.rb_right->rb_parent = NULL;
+			rb_set_parent(tn->rb.rb_right, NULL);
 
 		jffs2_free_tmp_dnode_info(tn);
 		if (ret) {
@@ -939,6 +968,7 @@
 	struct jffs2_full_dirent *fd, *fds;
 	int deleted;
 
+	jffs2_xattr_delete_inode(c, f->inocache);
 	down(&f->sem);
 	deleted = f->inocache && !f->inocache->nlink;
 
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index cf55b22..2bfdc33 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -65,6 +65,28 @@
 		return DEFAULT_EMPTY_SCAN_SIZE;
 }
 
+static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+{
+	int ret;
+
+	if ((ret = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
+		return ret;
+	if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
+		return ret;
+	/* Turned wasted size into dirty, since we apparently 
+	   think it's recoverable now. */
+	jeb->dirty_size += jeb->wasted_size;
+	c->dirty_size += jeb->wasted_size;
+	c->wasted_size -= jeb->wasted_size;
+	jeb->wasted_size = 0;
+	if (VERYDIRTY(c, jeb->dirty_size)) {
+		list_add(&jeb->list, &c->very_dirty_list);
+	} else {
+		list_add(&jeb->list, &c->dirty_list);
+	}
+	return 0;
+}
+
 int jffs2_scan_medium(struct jffs2_sb_info *c)
 {
 	int i, ret;
@@ -170,34 +192,20 @@
 					(!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
 				/* Better candidate for the next writes to go to */
 				if (c->nextblock) {
-					c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
-					c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size;
-					c->free_size -= c->nextblock->free_size;
-					c->wasted_size -= c->nextblock->wasted_size;
-					c->nextblock->free_size = c->nextblock->wasted_size = 0;
-					if (VERYDIRTY(c, c->nextblock->dirty_size)) {
-						list_add(&c->nextblock->list, &c->very_dirty_list);
-					} else {
-						list_add(&c->nextblock->list, &c->dirty_list);
-					}
+					ret = file_dirty(c, c->nextblock);
+					if (ret)
+						return ret;
 					/* deleting summary information of the old nextblock */
 					jffs2_sum_reset_collected(c->summary);
 				}
-				/* update collected summary infromation for the current nextblock */
+				/* update collected summary information for the current nextblock */
 				jffs2_sum_move_collected(c, s);
 				D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset));
 				c->nextblock = jeb;
 			} else {
-				jeb->dirty_size += jeb->free_size + jeb->wasted_size;
-				c->dirty_size += jeb->free_size + jeb->wasted_size;
-				c->free_size -= jeb->free_size;
-				c->wasted_size -= jeb->wasted_size;
-				jeb->free_size = jeb->wasted_size = 0;
-				if (VERYDIRTY(c, jeb->dirty_size)) {
-					list_add(&jeb->list, &c->very_dirty_list);
-				} else {
-					list_add(&jeb->list, &c->dirty_list);
-				}
+				ret = file_dirty(c, jeb);
+				if (ret)
+					return ret;
 			}
 			break;
 
@@ -222,9 +230,6 @@
 		}
 	}
 
-	if (jffs2_sum_active() && s)
-		kfree(s);
-
 	/* Nextblock dirty is always seen as wasted, because we cannot recycle it now */
 	if (c->nextblock && (c->nextblock->dirty_size)) {
 		c->nextblock->wasted_size += c->nextblock->dirty_size;
@@ -242,11 +247,8 @@
 
 		D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
 			  skip));
-		c->nextblock->wasted_size += skip;
-		c->wasted_size += skip;
-
-		c->nextblock->free_size -= skip;
-		c->free_size -= skip;
+		jffs2_prealloc_raw_node_refs(c, c->nextblock, 1);
+		jffs2_scan_dirty_space(c, c->nextblock, skip);
 	}
 #endif
 	if (c->nr_erasing_blocks) {
@@ -266,6 +268,9 @@
 	else
 		c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size);
 #endif
+	if (s)
+		kfree(s);
+
 	return ret;
 }
 
@@ -290,7 +295,7 @@
 int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
 {
 	if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size
-		&& (!jeb->first_node || !jeb->first_node->next_phys) )
+	    && (!jeb->first_node || !ref_next(jeb->first_node)) )
 		return BLK_STATE_CLEANMARKER;
 
 	/* move blocks with max 4 byte dirty space to cleanlist */
@@ -306,11 +311,126 @@
 		return BLK_STATE_ALLDIRTY;
 }
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+				 struct jffs2_raw_xattr *rx, uint32_t ofs,
+				 struct jffs2_summary *s)
+{
+	struct jffs2_xattr_datum *xd;
+	uint32_t xid, version, totlen, crc;
+	int err;
+
+	crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4);
+	if (crc != je32_to_cpu(rx->node_crc)) {
+		JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+			      ofs, je32_to_cpu(rx->node_crc), crc);
+		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
+			return err;
+		return 0;
+	}
+
+	xid = je32_to_cpu(rx->xid);
+	version = je32_to_cpu(rx->version);
+
+	totlen = PAD(sizeof(struct jffs2_raw_xattr)
+			+ rx->name_len + 1 + je16_to_cpu(rx->value_len));
+	if (totlen != je32_to_cpu(rx->totlen)) {
+		JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n",
+			      ofs, je32_to_cpu(rx->totlen), totlen);
+		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen))))
+			return err;
+		return 0;
+	}
+
+	xd = jffs2_setup_xattr_datum(c, xid, version);
+	if (IS_ERR(xd))
+		return PTR_ERR(xd);
+
+	if (xd->version > version) {
+		struct jffs2_raw_node_ref *raw
+			= jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL);
+		raw->next_in_ino = xd->node->next_in_ino;
+		xd->node->next_in_ino = raw;
+	} else {
+		xd->version = version;
+		xd->xprefix = rx->xprefix;
+		xd->name_len = rx->name_len;
+		xd->value_len = je16_to_cpu(rx->value_len);
+		xd->data_crc = je32_to_cpu(rx->data_crc);
+
+		jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, (void *)xd);
+	}
+
+	if (jffs2_sum_active())
+		jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset);
+	dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n",
+		  ofs, xd->xid, xd->version);
+	return 0;
+}
+
+static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
+				struct jffs2_raw_xref *rr, uint32_t ofs,
+				struct jffs2_summary *s)
+{
+	struct jffs2_xattr_ref *ref;
+	uint32_t crc;
+	int err;
+
+	crc = crc32(0, rr, sizeof(*rr) - 4);
+	if (crc != je32_to_cpu(rr->node_crc)) {
+		JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+			      ofs, je32_to_cpu(rr->node_crc), crc);
+		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen)))))
+			return err;
+		return 0;
+	}
+
+	if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) {
+		JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd\n",
+			      ofs, je32_to_cpu(rr->totlen),
+			      PAD(sizeof(struct jffs2_raw_xref)));
+		if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen))))
+			return err;
+		return 0;
+	}
+
+	ref = jffs2_alloc_xattr_ref();
+	if (!ref)
+		return -ENOMEM;
+
+	/* BEFORE jffs2_build_xattr_subsystem() called, 
+	 * and AFTER xattr_ref is marked as a dead xref,
+	 * ref->xid is used to store 32bit xid, xd is not used
+	 * ref->ino is used to store 32bit inode-number, ic is not used
+	 * Thoes variables are declared as union, thus using those
+	 * are exclusive. In a similar way, ref->next is temporarily
+	 * used to chain all xattr_ref object. It's re-chained to
+	 * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly.
+	 */
+	ref->ino = je32_to_cpu(rr->ino);
+	ref->xid = je32_to_cpu(rr->xid);
+	ref->xseqno = je32_to_cpu(rr->xseqno);
+	if (ref->xseqno > c->highest_xseqno)
+		c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
+	ref->next = c->xref_temp;
+	c->xref_temp = ref;
+
+	jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), (void *)ref);
+
+	if (jffs2_sum_active())
+		jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset);
+	dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n",
+		  ofs, ref->xid, ref->ino);
+	return 0;
+}
+#endif
+
+/* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into
+   the flash, XIP-style */
 static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-				unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
+				  unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) {
 	struct jffs2_unknown_node *node;
 	struct jffs2_unknown_node crcnode;
-	struct jffs2_sum_marker *sm;
 	uint32_t ofs, prevofs;
 	uint32_t hdr_crc, buf_ofs, buf_len;
 	int err;
@@ -344,44 +464,75 @@
 #endif
 
 	if (jffs2_sum_active()) {
-		sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL);
-		if (!sm) {
-			return -ENOMEM;
-		}
-
-		err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size -
-					sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker));
-		if (err) {
-			kfree(sm);
-			return err;
-		}
-
-		if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) {
-			err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random);
-			if (err) {
-				kfree(sm);
-				return err;
+		struct jffs2_sum_marker *sm;
+		void *sumptr = NULL;
+		uint32_t sumlen;
+	      
+		if (!buf_size) {
+			/* XIP case. Just look, point at the summary if it's there */
+			sm = (void *)buf + c->sector_size - sizeof(*sm);
+			if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
+				sumptr = buf + je32_to_cpu(sm->offset);
+				sumlen = c->sector_size - je32_to_cpu(sm->offset);
 			}
+		} else {
+			/* If NAND flash, read a whole page of it. Else just the end */
+			if (c->wbuf_pagesize)
+				buf_len = c->wbuf_pagesize;
+			else
+				buf_len = sizeof(*sm);
+
+			/* Read as much as we want into the _end_ of the preallocated buffer */
+			err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, 
+						  jeb->offset + c->sector_size - buf_len,
+						  buf_len);				
+			if (err)
+				return err;
+
+			sm = (void *)buf + buf_size - sizeof(*sm);
+			if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) {
+				sumlen = c->sector_size - je32_to_cpu(sm->offset);
+				sumptr = buf + buf_size - sumlen;
+
+				/* Now, make sure the summary itself is available */
+				if (sumlen > buf_size) {
+					/* Need to kmalloc for this. */
+					sumptr = kmalloc(sumlen, GFP_KERNEL);
+					if (!sumptr)
+						return -ENOMEM;
+					memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len);
+				}
+				if (buf_len < sumlen) {
+					/* Need to read more so that the entire summary node is present */
+					err = jffs2_fill_scan_buf(c, sumptr, 
+								  jeb->offset + c->sector_size - sumlen,
+								  sumlen - buf_len);				
+					if (err)
+						return err;
+				}
+			}
+
 		}
 
-		kfree(sm);
+		if (sumptr) {
+			err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random);
 
-		ofs = jeb->offset;
-		prevofs = jeb->offset - 1;
+			if (buf_size && sumlen > buf_size)
+				kfree(sumptr);
+			/* If it returns with a real error, bail. 
+			   If it returns positive, that's a block classification
+			   (i.e. BLK_STATE_xxx) so return that too.
+			   If it returns zero, fall through to full scan. */
+			if (err)
+				return err;
+		}
 	}
 
 	buf_ofs = jeb->offset;
 
 	if (!buf_size) {
+		/* This is the XIP case -- we're reading _directly_ from the flash chip */
 		buf_len = c->sector_size;
-
-		if (jffs2_sum_active()) {
-			/* must reread because of summary test */
-			err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
-			if (err)
-				return err;
-		}
-
 	} else {
 		buf_len = EMPTY_SCAN_SIZE(c->sector_size);
 		err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len);
@@ -418,7 +569,10 @@
 	if (ofs) {
 		D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset,
 			  jeb->offset + ofs));
-		DIRTY_SPACE(ofs);
+		if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1)))
+			return err;
+		if ((err = jffs2_scan_dirty_space(c, jeb, ofs)))
+			return err;
 	}
 
 	/* Now ofs is a complete physical flash offset as it always was... */
@@ -433,6 +587,11 @@
 
 		jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 
+		/* Make sure there are node refs available for use */
+		err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
+		if (err)
+			return err;
+
 		cond_resched();
 
 		if (ofs & 3) {
@@ -442,7 +601,8 @@
 		}
 		if (ofs == prevofs) {
 			printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs);
-			DIRTY_SPACE(4);
+			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+				return err;
 			ofs += 4;
 			continue;
 		}
@@ -451,7 +611,8 @@
 		if (jeb->offset + c->sector_size < ofs + sizeof(*node)) {
 			D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node),
 				  jeb->offset, c->sector_size, ofs, sizeof(*node)));
-			DIRTY_SPACE((jeb->offset + c->sector_size)-ofs);
+			if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs)))
+				return err;
 			break;
 		}
 
@@ -481,7 +642,8 @@
 				if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) {
 					printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n",
 					       empty_start, ofs);
-					DIRTY_SPACE(ofs-empty_start);
+					if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start)))
+						return err;
 					goto scan_more;
 				}
 
@@ -494,7 +656,7 @@
 			/* If we're only checking the beginning of a block with a cleanmarker,
 			   bail now */
 			if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) &&
-			    c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) {
+			    c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) {
 				D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size)));
 				return BLK_STATE_CLEANMARKER;
 			}
@@ -518,20 +680,23 @@
 
 		if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) {
 			printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs);
-			DIRTY_SPACE(4);
+			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+				return err;
 			ofs += 4;
 			continue;
 		}
 		if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) {
 			D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs));
-			DIRTY_SPACE(4);
+			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+				return err;
 			ofs += 4;
 			continue;
 		}
 		if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) {
 			printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs);
 			printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n");
-			DIRTY_SPACE(4);
+			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+				return err;
 			ofs += 4;
 			continue;
 		}
@@ -540,7 +705,8 @@
 			noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n",
 				     JFFS2_MAGIC_BITMASK, ofs,
 				     je16_to_cpu(node->magic));
-			DIRTY_SPACE(4);
+			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+				return err;
 			ofs += 4;
 			continue;
 		}
@@ -557,7 +723,8 @@
 				     je32_to_cpu(node->totlen),
 				     je32_to_cpu(node->hdr_crc),
 				     hdr_crc);
-			DIRTY_SPACE(4);
+			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+				return err;
 			ofs += 4;
 			continue;
 		}
@@ -568,7 +735,8 @@
 			printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
 			       ofs, je32_to_cpu(node->totlen));
 			printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
-			DIRTY_SPACE(4);
+			if ((err = jffs2_scan_dirty_space(c, jeb, 4)))
+				return err;
 			ofs += 4;
 			continue;
 		}
@@ -576,7 +744,8 @@
 		if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) {
 			/* Wheee. This is an obsoleted node */
 			D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
-			DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+				return err;
 			ofs += PAD(je32_to_cpu(node->totlen));
 			continue;
 		}
@@ -614,30 +783,59 @@
 			ofs += PAD(je32_to_cpu(node->totlen));
 			break;
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+		case JFFS2_NODETYPE_XATTR:
+			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
+				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
+				D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)"
+					  " left to end of buf. Reading 0x%x at 0x%08x\n",
+					  je32_to_cpu(node->totlen), buf_len, ofs));
+				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
+				if (err)
+					return err;
+				buf_ofs = ofs;
+				node = (void *)buf;
+			}
+			err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s);
+			if (err)
+				return err;
+			ofs += PAD(je32_to_cpu(node->totlen));
+			break;
+		case JFFS2_NODETYPE_XREF:
+			if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) {
+				buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
+				D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)"
+					  " left to end of buf. Reading 0x%x at 0x%08x\n",
+					  je32_to_cpu(node->totlen), buf_len, ofs));
+				err = jffs2_fill_scan_buf(c, buf, ofs, buf_len);
+				if (err)
+					return err;
+				buf_ofs = ofs;
+				node = (void *)buf;
+			}
+			err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s);
+			if (err)
+				return err;
+			ofs += PAD(je32_to_cpu(node->totlen));
+			break;
+#endif	/* CONFIG_JFFS2_FS_XATTR */
+
 		case JFFS2_NODETYPE_CLEANMARKER:
 			D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs));
 			if (je32_to_cpu(node->totlen) != c->cleanmarker_size) {
 				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",
 				       ofs, je32_to_cpu(node->totlen), c->cleanmarker_size);
-				DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
+				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
+					return err;
 				ofs += PAD(sizeof(struct jffs2_unknown_node));
 			} else if (jeb->first_node) {
 				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
-				DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
+				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node)))))
+					return err;
 				ofs += PAD(sizeof(struct jffs2_unknown_node));
 			} else {
-				struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
-				if (!marker_ref) {
-					printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n");
-					return -ENOMEM;
-				}
-				marker_ref->next_in_ino = NULL;
-				marker_ref->next_phys = NULL;
-				marker_ref->flash_offset = ofs | REF_NORMAL;
-				marker_ref->__totlen = c->cleanmarker_size;
-				jeb->first_node = jeb->last_node = marker_ref;
+				jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL);
 
-				USED_SPACE(PAD(c->cleanmarker_size));
 				ofs += PAD(c->cleanmarker_size);
 			}
 			break;
@@ -645,7 +843,8 @@
 		case JFFS2_NODETYPE_PADDING:
 			if (jffs2_sum_active())
 				jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen));
-			DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+				return err;
 			ofs += PAD(je32_to_cpu(node->totlen));
 			break;
 
@@ -656,7 +855,8 @@
 			        c->flags |= JFFS2_SB_FLAG_RO;
 				if (!(jffs2_is_readonly(c)))
 					return -EROFS;
-				DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+					return err;
 				ofs += PAD(je32_to_cpu(node->totlen));
 				break;
 
@@ -666,15 +866,21 @@
 
 			case JFFS2_FEATURE_RWCOMPAT_DELETE:
 				D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
-				DIRTY_SPACE(PAD(je32_to_cpu(node->totlen)));
+				if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen)))))
+					return err;
 				ofs += PAD(je32_to_cpu(node->totlen));
 				break;
 
-			case JFFS2_FEATURE_RWCOMPAT_COPY:
+			case JFFS2_FEATURE_RWCOMPAT_COPY: {
 				D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs));
-				USED_SPACE(PAD(je32_to_cpu(node->totlen)));
+
+				jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL);
+
+				/* We can't summarise nodes we don't grok */
+				jffs2_sum_disable_collecting(s);
 				ofs += PAD(je32_to_cpu(node->totlen));
 				break;
+				}
 			}
 		}
 	}
@@ -687,9 +893,9 @@
 		}
 	}
 
-	D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset,
-		  jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size));
-
+	D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
+		  jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
+	
 	/* mark_node_obsolete can add to wasted !! */
 	if (jeb->wasted_size) {
 		jeb->dirty_size += jeb->wasted_size;
@@ -730,9 +936,9 @@
 static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 				 struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_inode_cache *ic;
 	uint32_t ino = je32_to_cpu(ri->ino);
+	int err;
 
 	D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs));
 
@@ -745,12 +951,6 @@
 	   Which means that the _full_ amount of time to get to proper write mode with GC
 	   operational may actually be _longer_ than before. Sucks to be me. */
 
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw) {
-		printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n");
-		return -ENOMEM;
-	}
-
 	ic = jffs2_get_ino_cache(c, ino);
 	if (!ic) {
 		/* Inocache get failed. Either we read a bogus ino# or it's just genuinely the
@@ -762,30 +962,17 @@
 			printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
 			       ofs, je32_to_cpu(ri->node_crc), crc);
 			/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
-			DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen)));
-			jffs2_free_raw_node_ref(raw);
+			if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen)))))
+				return err;
 			return 0;
 		}
 		ic = jffs2_scan_make_ino_cache(c, ino);
-		if (!ic) {
-			jffs2_free_raw_node_ref(raw);
+		if (!ic)
 			return -ENOMEM;
-		}
 	}
 
 	/* Wheee. It worked */
-
-	raw->flash_offset = ofs | REF_UNCHECKED;
-	raw->__totlen = PAD(je32_to_cpu(ri->totlen));
-	raw->next_phys = NULL;
-	raw->next_in_ino = ic->nodes;
-
-	ic->nodes = raw;
-	if (!jeb->first_node)
-		jeb->first_node = raw;
-	if (jeb->last_node)
-		jeb->last_node->next_phys = raw;
-	jeb->last_node = raw;
+	jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic);
 
 	D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n",
 		  je32_to_cpu(ri->ino), je32_to_cpu(ri->version),
@@ -794,8 +981,6 @@
 
 	pseudo_random += je32_to_cpu(ri->version);
 
-	UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen)));
-
 	if (jffs2_sum_active()) {
 		jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset);
 	}
@@ -806,10 +991,10 @@
 static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 				  struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_full_dirent *fd;
 	struct jffs2_inode_cache *ic;
 	uint32_t crc;
+	int err;
 
 	D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs));
 
@@ -821,7 +1006,8 @@
 		printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n",
 		       ofs, je32_to_cpu(rd->node_crc), crc);
 		/* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */
-		DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
+		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
+			return err;
 		return 0;
 	}
 
@@ -842,40 +1028,23 @@
 		jffs2_free_full_dirent(fd);
 		/* FIXME: Why do we believe totlen? */
 		/* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */
-		DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen)));
+		if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen)))))
+			return err;
 		return 0;
 	}
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw) {
-		jffs2_free_full_dirent(fd);
-		printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n");
-		return -ENOMEM;
-	}
 	ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino));
 	if (!ic) {
 		jffs2_free_full_dirent(fd);
-		jffs2_free_raw_node_ref(raw);
 		return -ENOMEM;
 	}
 
-	raw->__totlen = PAD(je32_to_cpu(rd->totlen));
-	raw->flash_offset = ofs | REF_PRISTINE;
-	raw->next_phys = NULL;
-	raw->next_in_ino = ic->nodes;
-	ic->nodes = raw;
-	if (!jeb->first_node)
-		jeb->first_node = raw;
-	if (jeb->last_node)
-		jeb->last_node->next_phys = raw;
-	jeb->last_node = raw;
+	fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic);
 
-	fd->raw = raw;
 	fd->next = NULL;
 	fd->version = je32_to_cpu(rd->version);
 	fd->ino = je32_to_cpu(rd->ino);
 	fd->nhash = full_name_hash(fd->name, rd->nsize);
 	fd->type = rd->type;
-	USED_SPACE(PAD(je32_to_cpu(rd->totlen)));
 	jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
 	if (jffs2_sum_active()) {
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
new file mode 100644
index 0000000..52a9894
--- /dev/null
+++ b/fs/jffs2/security.c
@@ -0,0 +1,82 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include <linux/security.h>
+#include "nodelist.h"
+
+/* ---- Initial Security Label Attachment -------------- */
+int jffs2_init_security(struct inode *inode, struct inode *dir)
+{
+	int rc;
+	size_t len;
+	void *value;
+	char *name;
+
+	rc = security_inode_init_security(inode, dir, &name, &value, &len);
+	if (rc) {
+		if (rc == -EOPNOTSUPP)
+			return 0;
+		return rc;
+	}
+	rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
+
+        kfree(name);
+        kfree(value);
+        return rc;
+}
+
+/* ---- XATTR Handler for "security.*" ----------------- */
+static int jffs2_security_getxattr(struct inode *inode, const char *name,
+				   void *buffer, size_t size)
+{
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size);
+}
+
+static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer,
+				   size_t size, int flags)
+{
+	if (!strcmp(name, ""))
+		return -EINVAL;
+
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags);
+}
+
+static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size,
+				       const char *name, size_t name_len)
+{
+	size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1;
+
+	if (list && retlen <= list_size) {
+		strcpy(list, XATTR_SECURITY_PREFIX);
+		strcpy(list + XATTR_SECURITY_PREFIX_LEN, name);
+	}
+
+	return retlen;
+}
+
+struct xattr_handler jffs2_security_xattr_handler = {
+	.prefix = XATTR_SECURITY_PREFIX,
+	.list = jffs2_security_listxattr,
+	.set = jffs2_security_setxattr,
+	.get = jffs2_security_getxattr
+};
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c
index fb9cec6..c19bd47 100644
--- a/fs/jffs2/summary.c
+++ b/fs/jffs2/summary.c
@@ -5,6 +5,7 @@
  *                     Zoltan Sogor <weth@inf.u-szeged.hu>,
  *                     Patrik Kluba <pajko@halom.u-szeged.hu>,
  *                     University of Szeged, Hungary
+ *               2006  KaiGai Kohei <kaigai@ak.jp.nec.com>
  *
  * For licensing information, see the file 'LICENCE' in this directory.
  *
@@ -42,7 +43,7 @@
 		return -ENOMEM;
 	}
 
-	dbg_summary("returned succesfully\n");
+	dbg_summary("returned successfully\n");
 
 	return 0;
 }
@@ -81,6 +82,19 @@
 			dbg_summary("dirent (%u) added to summary\n",
 						je32_to_cpu(item->d.ino));
 			break;
+#ifdef CONFIG_JFFS2_FS_XATTR
+		case JFFS2_NODETYPE_XATTR:
+			s->sum_size += JFFS2_SUMMARY_XATTR_SIZE;
+			s->sum_num++;
+			dbg_summary("xattr (xid=%u, version=%u) added to summary\n",
+				    je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version));
+			break;
+		case JFFS2_NODETYPE_XREF:
+			s->sum_size += JFFS2_SUMMARY_XREF_SIZE;
+			s->sum_num++;
+			dbg_summary("xref added to summary\n");
+			break;
+#endif
 		default:
 			JFFS2_WARNING("UNKNOWN node type %u\n",
 					    je16_to_cpu(item->u.nodetype));
@@ -141,6 +155,40 @@
 	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
 }
 
+#ifdef CONFIG_JFFS2_FS_XATTR
+int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs)
+{
+	struct jffs2_sum_xattr_mem *temp;
+
+	temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
+	if (!temp)
+		return -ENOMEM;
+
+	temp->nodetype = rx->nodetype;
+	temp->xid = rx->xid;
+	temp->version = rx->version;
+	temp->offset = cpu_to_je32(ofs);
+	temp->totlen = rx->totlen;
+	temp->next = NULL;
+
+	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
+}
+
+int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs)
+{
+	struct jffs2_sum_xref_mem *temp;
+
+	temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
+	if (!temp)
+		return -ENOMEM;
+
+	temp->nodetype = rr->nodetype;
+	temp->offset = cpu_to_je32(ofs);
+	temp->next = NULL;
+
+	return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp);
+}
+#endif
 /* Cleanup every collected summary information */
 
 static void jffs2_sum_clean_collected(struct jffs2_summary *s)
@@ -259,7 +307,34 @@
 
 			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
 		}
+#ifdef CONFIG_JFFS2_FS_XATTR
+		case JFFS2_NODETYPE_XATTR: {
+			struct jffs2_sum_xattr_mem *temp;
+			temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL);
+			if (!temp)
+				goto no_mem;
 
+			temp->nodetype = node->x.nodetype;
+			temp->xid = node->x.xid;
+			temp->version = node->x.version;
+			temp->totlen = node->x.totlen;
+			temp->offset = cpu_to_je32(ofs);
+			temp->next = NULL;
+
+			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
+		}
+		case JFFS2_NODETYPE_XREF: {
+			struct jffs2_sum_xref_mem *temp;
+			temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL);
+			if (!temp)
+				goto no_mem;
+			temp->nodetype = node->r.nodetype;
+			temp->offset = cpu_to_je32(ofs);
+			temp->next = NULL;
+
+			return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp);
+		}
+#endif
 		case JFFS2_NODETYPE_PADDING:
 			dbg_summary("node PADDING\n");
 			c->summary->sum_padded += je32_to_cpu(node->u.totlen);
@@ -288,23 +363,41 @@
 	return -ENOMEM;
 }
 
+static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c,
+						    struct jffs2_eraseblock *jeb,
+						    uint32_t ofs, uint32_t len,
+						    struct jffs2_inode_cache *ic)
+{
+	/* If there was a gap, mark it dirty */
+	if ((ofs & ~3) > c->sector_size - jeb->free_size) {
+		/* Ew. Summary doesn't actually tell us explicitly about dirty space */
+		jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size));
+	}
+
+	return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic);
+}
 
 /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */
 
 static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
 				struct jffs2_raw_summary *summary, uint32_t *pseudo_random)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_inode_cache *ic;
 	struct jffs2_full_dirent *fd;
 	void *sp;
 	int i, ino;
+	int err;
 
 	sp = summary->sum;
 
 	for (i=0; i<je32_to_cpu(summary->sum_num); i++) {
 		dbg_summary("processing summary index %d\n", i);
 
+		/* Make sure there's a spare ref for dirty space */
+		err = jffs2_prealloc_raw_node_refs(c, jeb, 2);
+		if (err)
+			return err;
+
 		switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
 			case JFFS2_NODETYPE_INODE: {
 				struct jffs2_sum_inode_flash *spi;
@@ -312,39 +405,21 @@
 
 				ino = je32_to_cpu(spi->inode);
 
-				dbg_summary("Inode at 0x%08x\n",
-							jeb->offset + je32_to_cpu(spi->offset));
-
-				raw = jffs2_alloc_raw_node_ref();
-				if (!raw) {
-					JFFS2_NOTICE("allocation of node reference failed\n");
-					kfree(summary);
-					return -ENOMEM;
-				}
+				dbg_summary("Inode at 0x%08x-0x%08x\n",
+					    jeb->offset + je32_to_cpu(spi->offset),
+					    jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen));
 
 				ic = jffs2_scan_make_ino_cache(c, ino);
 				if (!ic) {
 					JFFS2_NOTICE("scan_make_ino_cache failed\n");
-					jffs2_free_raw_node_ref(raw);
-					kfree(summary);
 					return -ENOMEM;
 				}
 
-				raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED;
-				raw->__totlen = PAD(je32_to_cpu(spi->totlen));
-				raw->next_phys = NULL;
-				raw->next_in_ino = ic->nodes;
+				sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED,
+						  PAD(je32_to_cpu(spi->totlen)), ic);
 
-				ic->nodes = raw;
-				if (!jeb->first_node)
-					jeb->first_node = raw;
-				if (jeb->last_node)
-					jeb->last_node->next_phys = raw;
-				jeb->last_node = raw;
 				*pseudo_random += je32_to_cpu(spi->version);
 
-				UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen)));
-
 				sp += JFFS2_SUMMARY_INODE_SIZE;
 
 				break;
@@ -354,52 +429,33 @@
 				struct jffs2_sum_dirent_flash *spd;
 				spd = sp;
 
-				dbg_summary("Dirent at 0x%08x\n",
-							jeb->offset + je32_to_cpu(spd->offset));
+				dbg_summary("Dirent at 0x%08x-0x%08x\n",
+					    jeb->offset + je32_to_cpu(spd->offset),
+					    jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen));
+
 
 				fd = jffs2_alloc_full_dirent(spd->nsize+1);
-				if (!fd) {
-					kfree(summary);
+				if (!fd)
 					return -ENOMEM;
-				}
 
 				memcpy(&fd->name, spd->name, spd->nsize);
 				fd->name[spd->nsize] = 0;
 
-				raw = jffs2_alloc_raw_node_ref();
-				if (!raw) {
-					jffs2_free_full_dirent(fd);
-					JFFS2_NOTICE("allocation of node reference failed\n");
-					kfree(summary);
-					return -ENOMEM;
-				}
-
 				ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino));
 				if (!ic) {
 					jffs2_free_full_dirent(fd);
-					jffs2_free_raw_node_ref(raw);
-					kfree(summary);
 					return -ENOMEM;
 				}
 
-				raw->__totlen = PAD(je32_to_cpu(spd->totlen));
-				raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE;
-				raw->next_phys = NULL;
-				raw->next_in_ino = ic->nodes;
-				ic->nodes = raw;
-				if (!jeb->first_node)
-					jeb->first_node = raw;
-				if (jeb->last_node)
-					jeb->last_node->next_phys = raw;
-				jeb->last_node = raw;
+				fd->raw = sum_link_node_ref(c, jeb,  je32_to_cpu(spd->offset) | REF_UNCHECKED,
+							    PAD(je32_to_cpu(spd->totlen)), ic);
 
-				fd->raw = raw;
 				fd->next = NULL;
 				fd->version = je32_to_cpu(spd->version);
 				fd->ino = je32_to_cpu(spd->ino);
 				fd->nhash = full_name_hash(fd->name, spd->nsize);
 				fd->type = spd->type;
-				USED_SPACE(PAD(je32_to_cpu(spd->totlen)));
+
 				jffs2_add_fd_to_list(c, fd, &ic->scan_dents);
 
 				*pseudo_random += je32_to_cpu(spd->version);
@@ -408,48 +464,100 @@
 
 				break;
 			}
+#ifdef CONFIG_JFFS2_FS_XATTR
+			case JFFS2_NODETYPE_XATTR: {
+				struct jffs2_xattr_datum *xd;
+				struct jffs2_sum_xattr_flash *spx;
 
+				spx = (struct jffs2_sum_xattr_flash *)sp;
+				dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)\n", 
+					    jeb->offset + je32_to_cpu(spx->offset),
+					    jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen),
+					    je32_to_cpu(spx->xid), je32_to_cpu(spx->version));
+
+				xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid),
+								je32_to_cpu(spx->version));
+				if (IS_ERR(xd))
+					return PTR_ERR(xd);
+				if (xd->version > je32_to_cpu(spx->version)) {
+					/* node is not the newest one */
+					struct jffs2_raw_node_ref *raw
+						= sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
+								    PAD(je32_to_cpu(spx->totlen)), NULL);
+					raw->next_in_ino = xd->node->next_in_ino;
+					xd->node->next_in_ino = raw;
+				} else {
+					xd->version = je32_to_cpu(spx->version);
+					sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED,
+							  PAD(je32_to_cpu(spx->totlen)), (void *)xd);
+				}
+				*pseudo_random += je32_to_cpu(spx->xid);
+				sp += JFFS2_SUMMARY_XATTR_SIZE;
+
+				break;
+			}
+			case JFFS2_NODETYPE_XREF: {
+				struct jffs2_xattr_ref *ref;
+				struct jffs2_sum_xref_flash *spr;
+
+				spr = (struct jffs2_sum_xref_flash *)sp;
+				dbg_summary("xref at %#08x-%#08x\n",
+					    jeb->offset + je32_to_cpu(spr->offset),
+					    jeb->offset + je32_to_cpu(spr->offset) + 
+					    (uint32_t)PAD(sizeof(struct jffs2_raw_xref)));
+
+				ref = jffs2_alloc_xattr_ref();
+				if (!ref) {
+					JFFS2_NOTICE("allocation of xattr_datum failed\n");
+					return -ENOMEM;
+				}
+				ref->next = c->xref_temp;
+				c->xref_temp = ref;
+
+				sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED,
+						  PAD(sizeof(struct jffs2_raw_xref)), (void *)ref);
+
+				*pseudo_random += ref->node->flash_offset;
+				sp += JFFS2_SUMMARY_XREF_SIZE;
+
+				break;
+			}
+#endif
 			default : {
-				JFFS2_WARNING("Unsupported node type found in summary! Exiting...");
-				kfree(summary);
-				return -EIO;
+				uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype);
+				JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype);
+				if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT)
+					return -EIO;
+
+				/* For compatible node types, just fall back to the full scan */
+				c->wasted_size -= jeb->wasted_size;
+				c->free_size += c->sector_size - jeb->free_size;
+				c->used_size -= jeb->used_size;
+				c->dirty_size -= jeb->dirty_size;
+				jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0;
+				jeb->free_size = c->sector_size;
+
+				jffs2_free_jeb_node_refs(c, jeb);
+				return -ENOTRECOVERABLE;
 			}
 		}
 	}
-
-	kfree(summary);
 	return 0;
 }
 
 /* Process the summary node - called from jffs2_scan_eraseblock() */
-
 int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-				uint32_t ofs, uint32_t *pseudo_random)
+			   struct jffs2_raw_summary *summary, uint32_t sumsize,
+			   uint32_t *pseudo_random)
 {
 	struct jffs2_unknown_node crcnode;
-	struct jffs2_raw_node_ref *cache_ref;
-	struct jffs2_raw_summary *summary;
-	int ret, sumsize;
+	int ret, ofs;
 	uint32_t crc;
 
-	sumsize = c->sector_size - ofs;
-	ofs += jeb->offset;
+	ofs = c->sector_size - sumsize;
 
 	dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n",
-				jeb->offset, ofs, sumsize);
-
-	summary = kmalloc(sumsize, GFP_KERNEL);
-
-	if (!summary) {
-		return -ENOMEM;
-	}
-
-	ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize);
-
-	if (ret) {
-		kfree(summary);
-		return ret;
-	}
+		    jeb->offset, jeb->offset + ofs, sumsize);
 
 	/* OK, now check for node validity and CRC */
 	crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -486,67 +594,50 @@
 
 		dbg_summary("Summary : CLEANMARKER node \n");
 
+		ret = jffs2_prealloc_raw_node_refs(c, jeb, 1);
+		if (ret)
+			return ret;
+
 		if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) {
 			dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n",
 				je32_to_cpu(summary->cln_mkr), c->cleanmarker_size);
-			UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
+			if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
+				return ret;
 		} else if (jeb->first_node) {
 			dbg_summary("CLEANMARKER node not first node in block "
 					"(0x%08x)\n", jeb->offset);
-			UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr)));
+			if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr)))))
+				return ret;
 		} else {
-			struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref();
-
-			if (!marker_ref) {
-				JFFS2_NOTICE("Failed to allocate node ref for clean marker\n");
-				kfree(summary);
-				return -ENOMEM;
-			}
-
-			marker_ref->next_in_ino = NULL;
-			marker_ref->next_phys = NULL;
-			marker_ref->flash_offset = jeb->offset | REF_NORMAL;
-			marker_ref->__totlen = je32_to_cpu(summary->cln_mkr);
-			jeb->first_node = jeb->last_node = marker_ref;
-
-			USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) );
+			jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL,
+					    je32_to_cpu(summary->cln_mkr), NULL);
 		}
 	}
 
-	if (je32_to_cpu(summary->padded)) {
-		DIRTY_SPACE(je32_to_cpu(summary->padded));
-	}
-
 	ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random);
+	/* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full
+	   scan of this eraseblock. So return zero */
+	if (ret == -ENOTRECOVERABLE)
+		return 0;
+	if (ret)
+		return ret;		/* real error */
+
+	/* for PARANOIA_CHECK */
+	ret = jffs2_prealloc_raw_node_refs(c, jeb, 2);
 	if (ret)
 		return ret;
 
-	/* for PARANOIA_CHECK */
-	cache_ref = jffs2_alloc_raw_node_ref();
+	sum_link_node_ref(c, jeb, ofs | REF_NORMAL, sumsize, NULL);
 
-	if (!cache_ref) {
-		JFFS2_NOTICE("Failed to allocate node ref for cache\n");
-		return -ENOMEM;
+	if (unlikely(jeb->free_size)) {
+		JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n",
+			      jeb->free_size, jeb->offset);
+		jeb->wasted_size += jeb->free_size;
+		c->wasted_size += jeb->free_size;
+		c->free_size -= jeb->free_size;
+		jeb->free_size = 0;
 	}
 
-	cache_ref->next_in_ino = NULL;
-	cache_ref->next_phys = NULL;
-	cache_ref->flash_offset = ofs | REF_NORMAL;
-	cache_ref->__totlen = sumsize;
-
-	if (!jeb->first_node)
-		jeb->first_node = cache_ref;
-	if (jeb->last_node)
-		jeb->last_node->next_phys = cache_ref;
-	jeb->last_node = cache_ref;
-
-	USED_SPACE(sumsize);
-
-	jeb->wasted_size += jeb->free_size;
-	c->wasted_size += jeb->free_size;
-	c->free_size -= jeb->free_size;
-	jeb->free_size = 0;
-
 	return jffs2_scan_classify_jeb(c, jeb);
 
 crc_err:
@@ -564,6 +655,7 @@
 	union jffs2_sum_mem *temp;
 	struct jffs2_sum_marker *sm;
 	struct kvec vecs[2];
+	uint32_t sum_ofs;
 	void *wpage;
 	int ret;
 	size_t retlen;
@@ -581,16 +673,17 @@
 	wpage = c->summary->sum_buf;
 
 	while (c->summary->sum_num) {
+		temp = c->summary->sum_list_head;
 
-		switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) {
+		switch (je16_to_cpu(temp->u.nodetype)) {
 			case JFFS2_NODETYPE_INODE: {
 				struct jffs2_sum_inode_flash *sino_ptr = wpage;
 
-				sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype;
-				sino_ptr->inode = c->summary->sum_list_head->i.inode;
-				sino_ptr->version = c->summary->sum_list_head->i.version;
-				sino_ptr->offset = c->summary->sum_list_head->i.offset;
-				sino_ptr->totlen = c->summary->sum_list_head->i.totlen;
+				sino_ptr->nodetype = temp->i.nodetype;
+				sino_ptr->inode = temp->i.inode;
+				sino_ptr->version = temp->i.version;
+				sino_ptr->offset = temp->i.offset;
+				sino_ptr->totlen = temp->i.totlen;
 
 				wpage += JFFS2_SUMMARY_INODE_SIZE;
 
@@ -600,30 +693,60 @@
 			case JFFS2_NODETYPE_DIRENT: {
 				struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage;
 
-				sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype;
-				sdrnt_ptr->totlen = c->summary->sum_list_head->d.totlen;
-				sdrnt_ptr->offset = c->summary->sum_list_head->d.offset;
-				sdrnt_ptr->pino = c->summary->sum_list_head->d.pino;
-				sdrnt_ptr->version = c->summary->sum_list_head->d.version;
-				sdrnt_ptr->ino = c->summary->sum_list_head->d.ino;
-				sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize;
-				sdrnt_ptr->type = c->summary->sum_list_head->d.type;
+				sdrnt_ptr->nodetype = temp->d.nodetype;
+				sdrnt_ptr->totlen = temp->d.totlen;
+				sdrnt_ptr->offset = temp->d.offset;
+				sdrnt_ptr->pino = temp->d.pino;
+				sdrnt_ptr->version = temp->d.version;
+				sdrnt_ptr->ino = temp->d.ino;
+				sdrnt_ptr->nsize = temp->d.nsize;
+				sdrnt_ptr->type = temp->d.type;
 
-				memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name,
-							c->summary->sum_list_head->d.nsize);
+				memcpy(sdrnt_ptr->name, temp->d.name,
+							temp->d.nsize);
 
-				wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize);
+				wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize);
 
 				break;
 			}
+#ifdef CONFIG_JFFS2_FS_XATTR
+			case JFFS2_NODETYPE_XATTR: {
+				struct jffs2_sum_xattr_flash *sxattr_ptr = wpage;
 
+				temp = c->summary->sum_list_head;
+				sxattr_ptr->nodetype = temp->x.nodetype;
+				sxattr_ptr->xid = temp->x.xid;
+				sxattr_ptr->version = temp->x.version;
+				sxattr_ptr->offset = temp->x.offset;
+				sxattr_ptr->totlen = temp->x.totlen;
+
+				wpage += JFFS2_SUMMARY_XATTR_SIZE;
+				break;
+			}
+			case JFFS2_NODETYPE_XREF: {
+				struct jffs2_sum_xref_flash *sxref_ptr = wpage;
+
+				temp = c->summary->sum_list_head;
+				sxref_ptr->nodetype = temp->r.nodetype;
+				sxref_ptr->offset = temp->r.offset;
+
+				wpage += JFFS2_SUMMARY_XREF_SIZE;
+				break;
+			}
+#endif
 			default : {
-				BUG();	/* unknown node in summary information */
+				if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK)
+				    == JFFS2_FEATURE_RWCOMPAT_COPY) {
+					dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n",
+						    je16_to_cpu(temp->u.nodetype));
+					jffs2_sum_disable_collecting(c->summary);
+				} else {
+					BUG();	/* unknown node in summary information */
+				}
 			}
 		}
 
-		temp = c->summary->sum_list_head;
-		c->summary->sum_list_head = c->summary->sum_list_head->u.next;
+		c->summary->sum_list_head = temp->u.next;
 		kfree(temp);
 
 		c->summary->sum_num--;
@@ -645,25 +768,34 @@
 	vecs[1].iov_base = c->summary->sum_buf;
 	vecs[1].iov_len = datasize;
 
+	sum_ofs = jeb->offset + c->sector_size - jeb->free_size;
+
 	dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n",
-			jeb->offset + c->sector_size - jeb->free_size);
+		    sum_ofs);
 
-	spin_unlock(&c->erase_completion_lock);
-	ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size -
-				jeb->free_size, &retlen, 0);
-	spin_lock(&c->erase_completion_lock);
-
+	ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0);
 
 	if (ret || (retlen != infosize)) {
-		JFFS2_WARNING("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
-			infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen);
+
+		JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n",
+			      infosize, sum_ofs, ret, retlen);
+
+		if (retlen) {
+			/* Waste remaining space */
+			spin_lock(&c->erase_completion_lock);
+			jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL);
+			spin_unlock(&c->erase_completion_lock);
+		}
 
 		c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE;
-		WASTED_SPACE(infosize);
 
-		return 1;
+		return 0;
 	}
 
+	spin_lock(&c->erase_completion_lock);
+	jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL);
+	spin_unlock(&c->erase_completion_lock);
+
 	return 0;
 }
 
@@ -671,13 +803,16 @@
 
 int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
 {
-	struct jffs2_raw_node_ref *summary_ref;
-	int datasize, infosize, padsize, ret;
+	int datasize, infosize, padsize;
 	struct jffs2_eraseblock *jeb;
+	int ret;
 
 	dbg_summary("called\n");
 
+	spin_unlock(&c->erase_completion_lock);
+
 	jeb = c->nextblock;
+	jffs2_prealloc_raw_node_refs(c, jeb, 1);
 
 	if (!c->summary->sum_num || !c->summary->sum_list_head) {
 		JFFS2_WARNING("Empty summary info!!!\n");
@@ -696,35 +831,11 @@
 		jffs2_sum_disable_collecting(c->summary);
 
 		JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
+		spin_lock(&c->erase_completion_lock);
 		return 0;
 	}
 
 	ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
-	if (ret)
-		return 0; /* can't write out summary, block is marked as NOSUM_SIZE */
-
-	/* for ACCT_PARANOIA_CHECK */
-	spin_unlock(&c->erase_completion_lock);
-	summary_ref = jffs2_alloc_raw_node_ref();
 	spin_lock(&c->erase_completion_lock);
-
-	if (!summary_ref) {
-		JFFS2_NOTICE("Failed to allocate node ref for summary\n");
-		return -ENOMEM;
-	}
-
-	summary_ref->next_in_ino = NULL;
-	summary_ref->next_phys = NULL;
-	summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL;
-	summary_ref->__totlen = infosize;
-
-	if (!jeb->first_node)
-		jeb->first_node = summary_ref;
-	if (jeb->last_node)
-		jeb->last_node->next_phys = summary_ref;
-	jeb->last_node = summary_ref;
-
-	USED_SPACE(infosize);
-
-	return 0;
+	return ret;
 }
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h
index b7a678be1..6bf1f6a 100644
--- a/fs/jffs2/summary.h
+++ b/fs/jffs2/summary.h
@@ -18,23 +18,6 @@
 #include <linux/uio.h>
 #include <linux/jffs2.h>
 
-#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \
-		c->free_size -= _x; c->dirty_size += _x; \
-		jeb->free_size -= _x ; jeb->dirty_size += _x; \
-		}while(0)
-#define USED_SPACE(x) do { typeof(x) _x = (x); \
-		c->free_size -= _x; c->used_size += _x; \
-		jeb->free_size -= _x ; jeb->used_size += _x; \
-		}while(0)
-#define WASTED_SPACE(x) do { typeof(x) _x = (x); \
-		c->free_size -= _x; c->wasted_size += _x; \
-		jeb->free_size -= _x ; jeb->wasted_size += _x; \
-		}while(0)
-#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \
-		c->free_size -= _x; c->unchecked_size += _x; \
-		jeb->free_size -= _x ; jeb->unchecked_size += _x; \
-		}while(0)
-
 #define BLK_STATE_ALLFF		0
 #define BLK_STATE_CLEAN		1
 #define BLK_STATE_PARTDIRTY	2
@@ -45,6 +28,8 @@
 #define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff
 #define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash))
 #define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x))
+#define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash))
+#define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash))
 
 /* Summary structures used on flash */
 
@@ -75,11 +60,28 @@
 	uint8_t name[0];	/* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_flash
+{
+	jint16_t nodetype;	/* == JFFS2_NODETYPE_XATR */
+	jint32_t xid;		/* xattr identifier */
+	jint32_t version;	/* version number */
+	jint32_t offset;	/* offset on jeb */
+	jint32_t totlen;	/* node length */
+} __attribute__((packed));
+
+struct jffs2_sum_xref_flash
+{
+	jint16_t nodetype;	/* == JFFS2_NODETYPE_XREF */
+	jint32_t offset;	/* offset on jeb */
+} __attribute__((packed));
+
 union jffs2_sum_flash
 {
 	struct jffs2_sum_unknown_flash u;
 	struct jffs2_sum_inode_flash i;
 	struct jffs2_sum_dirent_flash d;
+	struct jffs2_sum_xattr_flash x;
+	struct jffs2_sum_xref_flash r;
 };
 
 /* Summary structures used in the memory */
@@ -114,11 +116,30 @@
 	uint8_t name[0];	/* dirent name */
 } __attribute__((packed));
 
+struct jffs2_sum_xattr_mem
+{
+	union jffs2_sum_mem *next;
+	jint16_t nodetype;
+	jint32_t xid;
+	jint32_t version;
+	jint32_t offset;
+	jint32_t totlen;
+} __attribute__((packed));
+
+struct jffs2_sum_xref_mem
+{
+	union jffs2_sum_mem *next;
+	jint16_t nodetype;
+	jint32_t offset;
+} __attribute__((packed));
+
 union jffs2_sum_mem
 {
 	struct jffs2_sum_unknown_mem u;
 	struct jffs2_sum_inode_mem i;
 	struct jffs2_sum_dirent_mem d;
+	struct jffs2_sum_xattr_mem x;
+	struct jffs2_sum_xref_mem r;
 };
 
 /* Summary related information stored in superblock */
@@ -159,8 +180,11 @@
 int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size);
 int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs);
 int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs);
+int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs);
+int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs);
 int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
-			uint32_t ofs, uint32_t *pseudo_random);
+			   struct jffs2_raw_summary *summary, uint32_t sumlen,
+			   uint32_t *pseudo_random);
 
 #else				/* SUMMARY DISABLED */
 
@@ -176,7 +200,9 @@
 #define jffs2_sum_add_padding_mem(a,b)
 #define jffs2_sum_add_inode_mem(a,b,c)
 #define jffs2_sum_add_dirent_mem(a,b,c)
-#define jffs2_sum_scan_sumnode(a,b,c,d) (0)
+#define jffs2_sum_add_xattr_mem(a,b,c)
+#define jffs2_sum_add_xref_mem(a,b,c)
+#define jffs2_sum_scan_sumnode(a,b,c,d,e) (0)
 
 #endif /* CONFIG_JFFS2_SUMMARY */
 
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c
index ffd8e84..2378a66 100644
--- a/fs/jffs2/super.c
+++ b/fs/jffs2/super.c
@@ -111,9 +111,10 @@
 	return 0;
 }
 
-static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type,
-					      int flags, const char *dev_name,
-					      void *data, struct mtd_info *mtd)
+static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
+			    int flags, const char *dev_name,
+			    void *data, struct mtd_info *mtd,
+			    struct vfsmount *mnt)
 {
 	struct super_block *sb;
 	struct jffs2_sb_info *c;
@@ -121,19 +122,20 @@
 
 	c = kmalloc(sizeof(*c), GFP_KERNEL);
 	if (!c)
-		return ERR_PTR(-ENOMEM);
+		return -ENOMEM;
 	memset(c, 0, sizeof(*c));
 	c->mtd = mtd;
 
 	sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
 
 	if (IS_ERR(sb))
-		goto out_put;
+		goto out_error;
 
 	if (sb->s_root) {
 		/* New mountpoint for JFFS2 which is already mounted */
 		D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n",
 			  mtd->index, mtd->name));
+		ret = simple_set_mnt(mnt, sb);
 		goto out_put;
 	}
 
@@ -151,51 +153,57 @@
 
 	sb->s_op = &jffs2_super_operations;
 	sb->s_flags = flags | MS_NOATIME;
-
+	sb->s_xattr = jffs2_xattr_handlers;
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+	sb->s_flags |= MS_POSIXACL;
+#endif
 	ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
 
 	if (ret) {
 		/* Failure case... */
 		up_write(&sb->s_umount);
 		deactivate_super(sb);
-		return ERR_PTR(ret);
+		return ret;
 	}
 
 	sb->s_flags |= MS_ACTIVE;
-	return sb;
+	return simple_set_mnt(mnt, sb);
 
+out_error:
+	ret = PTR_ERR(sb);
  out_put:
 	kfree(c);
 	put_mtd_device(mtd);
 
-	return sb;
+	return ret;
 }
 
-static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
-					      int flags, const char *dev_name,
-					      void *data, int mtdnr)
+static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type,
+			      int flags, const char *dev_name,
+			      void *data, int mtdnr,
+			      struct vfsmount *mnt)
 {
 	struct mtd_info *mtd;
 
 	mtd = get_mtd_device(NULL, mtdnr);
 	if (!mtd) {
 		D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr));
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 	}
 
-	return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd);
+	return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
 }
 
-static struct super_block *jffs2_get_sb(struct file_system_type *fs_type,
-					int flags, const char *dev_name,
-					void *data)
+static int jffs2_get_sb(struct file_system_type *fs_type,
+			int flags, const char *dev_name,
+			void *data, struct vfsmount *mnt)
 {
 	int err;
 	struct nameidata nd;
 	int mtdnr;
 
 	if (!dev_name)
-		return ERR_PTR(-EINVAL);
+		return -EINVAL;
 
 	D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name));
 
@@ -217,7 +225,7 @@
 				mtd = get_mtd_device(NULL, mtdnr);
 				if (mtd) {
 					if (!strcmp(mtd->name, dev_name+4))
-						return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd);
+						return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt);
 					put_mtd_device(mtd);
 				}
 			}
@@ -230,7 +238,7 @@
 			if (!*endptr) {
 				/* It was a valid number */
 				D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr));
-				return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr);
+				return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
 			}
 		}
 	}
@@ -244,7 +252,7 @@
 		  err, nd.dentry->d_inode));
 
 	if (err)
-		return ERR_PTR(err);
+		return err;
 
 	err = -EINVAL;
 
@@ -266,11 +274,11 @@
 	mtdnr = iminor(nd.dentry->d_inode);
 	path_release(&nd);
 
-	return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr);
+	return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt);
 
 out:
 	path_release(&nd);
-	return ERR_PTR(err);
+	return err;
 }
 
 static void jffs2_put_super (struct super_block *sb)
@@ -293,6 +301,7 @@
 		kfree(c->blocks);
 	jffs2_flash_cleanup(c);
 	kfree(c->inocache_list);
+	jffs2_clear_xattr_subsystem(c);
 	if (c->mtd->sync)
 		c->mtd->sync(c->mtd);
 
@@ -320,6 +329,18 @@
 {
 	int ret;
 
+	/* Paranoia checks for on-medium structures. If we ask GCC
+	   to pack them with __attribute__((packed)) then it _also_
+	   assumes that they're not aligned -- so it emits crappy
+	   code on some architectures. Ideally we want an attribute
+	   which means just 'no padding', without the alignment
+	   thing. But GCC doesn't have that -- we have to just
+	   hope the structs are the right sizes, instead. */
+	BUG_ON(sizeof(struct jffs2_unknown_node) != 12);
+	BUG_ON(sizeof(struct jffs2_raw_dirent) != 40);
+	BUG_ON(sizeof(struct jffs2_raw_inode) != 68);
+	BUG_ON(sizeof(struct jffs2_raw_summary) != 32);
+
 	printk(KERN_INFO "JFFS2 version 2.2."
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
 	       " (NAND)"
@@ -327,7 +348,7 @@
 #ifdef CONFIG_JFFS2_SUMMARY
 	       " (SUMMARY) "
 #endif
-	       " (C) 2001-2003 Red Hat, Inc.\n");
+	       " (C) 2001-2006 Red Hat, Inc.\n");
 
 	jffs2_inode_cachep = kmem_cache_create("jffs2_i",
 					     sizeof(struct jffs2_inode_info),
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
index d55754f..fc211b6 100644
--- a/fs/jffs2/symlink.c
+++ b/fs/jffs2/symlink.c
@@ -24,7 +24,12 @@
 {
 	.readlink =	generic_readlink,
 	.follow_link =	jffs2_follow_link,
-	.setattr =	jffs2_setattr
+	.permission =	jffs2_permission,
+	.setattr =	jffs2_setattr,
+	.setxattr =	jffs2_setxattr,
+	.getxattr =	jffs2_getxattr,
+	.listxattr =	jffs2_listxattr,
+	.removexattr =	jffs2_removexattr
 };
 
 static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 4cebf0e..b9b7007 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -156,69 +156,130 @@
 		jffs2_erase_pending_trigger(c);
 	}
 
-	/* Adjust its size counts accordingly */
-	c->wasted_size += jeb->free_size;
-	c->free_size -= jeb->free_size;
-	jeb->wasted_size += jeb->free_size;
-	jeb->free_size = 0;
+	if (!jffs2_prealloc_raw_node_refs(c, jeb, 1)) {
+		uint32_t oldfree = jeb->free_size;
+
+		jffs2_link_node_ref(c, jeb, 
+				    (jeb->offset+c->sector_size-oldfree) | REF_OBSOLETE,
+				    oldfree, NULL);
+		/* convert to wasted */
+		c->wasted_size += oldfree;
+		jeb->wasted_size += oldfree;
+		c->dirty_size -= oldfree;
+		jeb->dirty_size -= oldfree;
+	}
 
 	jffs2_dbg_dump_block_lists_nolock(c);
 	jffs2_dbg_acct_sanity_check_nolock(c,jeb);
 	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 }
 
+static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info *c,
+							    struct jffs2_inode_info *f,
+							    struct jffs2_raw_node_ref *raw,
+							    union jffs2_node_union *node)
+{
+	struct jffs2_node_frag *frag;
+	struct jffs2_full_dirent *fd;
+
+	dbg_noderef("incore_replace_raw: node at %p is {%04x,%04x}\n",
+		    node, je16_to_cpu(node->u.magic), je16_to_cpu(node->u.nodetype));
+
+	BUG_ON(je16_to_cpu(node->u.magic) != 0x1985 &&
+	       je16_to_cpu(node->u.magic) != 0);
+
+	switch (je16_to_cpu(node->u.nodetype)) {
+	case JFFS2_NODETYPE_INODE:
+		if (f->metadata && f->metadata->raw == raw) {
+			dbg_noderef("Will replace ->raw in f->metadata at %p\n", f->metadata);
+			return &f->metadata->raw;
+		}
+		frag = jffs2_lookup_node_frag(&f->fragtree, je32_to_cpu(node->i.offset));
+		BUG_ON(!frag);
+		/* Find a frag which refers to the full_dnode we want to modify */
+		while (!frag->node || frag->node->raw != raw) {
+			frag = frag_next(frag);
+			BUG_ON(!frag);
+		}
+		dbg_noderef("Will replace ->raw in full_dnode at %p\n", frag->node);
+		return &frag->node->raw;
+
+	case JFFS2_NODETYPE_DIRENT:
+		for (fd = f->dents; fd; fd = fd->next) {
+			if (fd->raw == raw) {
+				dbg_noderef("Will replace ->raw in full_dirent at %p\n", fd);
+				return &fd->raw;
+			}
+		}
+		BUG();
+
+	default:
+		dbg_noderef("Don't care about replacing raw for nodetype %x\n",
+			    je16_to_cpu(node->u.nodetype));
+		break;
+	}
+	return NULL;
+}
+
 /* Recover from failure to write wbuf. Recover the nodes up to the
  * wbuf, not the one which we were starting to try to write. */
 
 static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
 {
 	struct jffs2_eraseblock *jeb, *new_jeb;
-	struct jffs2_raw_node_ref **first_raw, **raw;
+	struct jffs2_raw_node_ref *raw, *next, *first_raw = NULL;
 	size_t retlen;
 	int ret;
+	int nr_refile = 0;
 	unsigned char *buf;
 	uint32_t start, end, ofs, len;
 
-	spin_lock(&c->erase_completion_lock);
-
 	jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
 
+	spin_lock(&c->erase_completion_lock);
 	jffs2_block_refile(c, jeb, REFILE_NOTEMPTY);
+	spin_unlock(&c->erase_completion_lock);
+
+	BUG_ON(!ref_obsolete(jeb->last_node));
 
 	/* Find the first node to be recovered, by skipping over every
 	   node which ends before the wbuf starts, or which is obsolete. */
-	first_raw = &jeb->first_node;
-	while (*first_raw &&
-	       (ref_obsolete(*first_raw) ||
-		(ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) {
-		D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n",
-			  ref_offset(*first_raw), ref_flags(*first_raw),
-			  (ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw)),
-			  c->wbuf_ofs));
-		first_raw = &(*first_raw)->next_phys;
+	for (next = raw = jeb->first_node; next; raw = next) {
+		next = ref_next(raw);
+
+		if (ref_obsolete(raw) || 
+		    (next && ref_offset(next) <= c->wbuf_ofs)) {
+			dbg_noderef("Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n",
+				    ref_offset(raw), ref_flags(raw),
+				    (ref_offset(raw) + ref_totlen(c, jeb, raw)),
+				    c->wbuf_ofs);
+			continue;
+		}
+		dbg_noderef("First node to be recovered is at 0x%08x(%d)-0x%08x\n",
+			    ref_offset(raw), ref_flags(raw),
+			    (ref_offset(raw) + ref_totlen(c, jeb, raw)));
+
+		first_raw = raw;
+		break;
 	}
 
-	if (!*first_raw) {
+	if (!first_raw) {
 		/* All nodes were obsolete. Nothing to recover. */
 		D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n"));
-		spin_unlock(&c->erase_completion_lock);
+		c->wbuf_len = 0;
 		return;
 	}
 
-	start = ref_offset(*first_raw);
-	end = ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw);
+	start = ref_offset(first_raw);
+	end = ref_offset(jeb->last_node);
+	nr_refile = 1;
 
-	/* Find the last node to be recovered */
-	raw = first_raw;
-	while ((*raw)) {
-		if (!ref_obsolete(*raw))
-			end = ref_offset(*raw) + ref_totlen(c, jeb, *raw);
+	/* Count the number of refs which need to be copied */
+	while ((raw = ref_next(raw)) != jeb->last_node)
+		nr_refile++;
 
-		raw = &(*raw)->next_phys;
-	}
-	spin_unlock(&c->erase_completion_lock);
-
-	D1(printk(KERN_DEBUG "wbuf recover %08x-%08x\n", start, end));
+	dbg_noderef("wbuf recover %08x-%08x (%d bytes in %d nodes)\n",
+		    start, end, end - start, nr_refile);
 
 	buf = NULL;
 	if (start < c->wbuf_ofs) {
@@ -233,28 +294,37 @@
 		}
 
 		/* Do the read... */
-		if (jffs2_cleanmarker_oob(c))
-			ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo);
-		else
-			ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf);
+		ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf);
 
-		if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) {
-			/* ECC recovered */
+		/* ECC recovered ? */
+		if ((ret == -EUCLEAN || ret == -EBADMSG) &&
+		    (retlen == c->wbuf_ofs - start))
 			ret = 0;
-		}
+
 		if (ret || retlen != c->wbuf_ofs - start) {
 			printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n");
 
 			kfree(buf);
 			buf = NULL;
 		read_failed:
-			first_raw = &(*first_raw)->next_phys;
+			first_raw = ref_next(first_raw);
+			nr_refile--;
+			while (first_raw && ref_obsolete(first_raw)) {
+				first_raw = ref_next(first_raw);
+				nr_refile--;
+			}
+
 			/* If this was the only node to be recovered, give up */
-			if (!(*first_raw))
+			if (!first_raw) {
+				c->wbuf_len = 0;
 				return;
+			}
 
 			/* It wasn't. Go on and try to recover nodes complete in the wbuf */
-			start = ref_offset(*first_raw);
+			start = ref_offset(first_raw);
+			dbg_noderef("wbuf now recover %08x-%08x (%d bytes in %d nodes)\n",
+				    start, end, end - start, nr_refile);
+
 		} else {
 			/* Read succeeded. Copy the remaining data from the wbuf */
 			memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs);
@@ -263,14 +333,23 @@
 	/* OK... we're to rewrite (end-start) bytes of data from first_raw onwards.
 	   Either 'buf' contains the data, or we find it in the wbuf */
 
-
 	/* ... and get an allocation of space from a shiny new block instead */
-	ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE);
+	ret = jffs2_reserve_space_gc(c, end-start, &len, JFFS2_SUMMARY_NOSUM_SIZE);
 	if (ret) {
 		printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n");
 		kfree(buf);
 		return;
 	}
+
+	ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile);
+	if (ret) {
+		printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n");
+		kfree(buf);
+		return;
+	}
+
+	ofs = write_ofs(c);
+
 	if (end-start >= c->wbuf_pagesize) {
 		/* Need to do another write immediately, but it's possible
 		   that this is just because the wbuf itself is completely
@@ -288,36 +367,22 @@
 		if (breakme++ == 20) {
 			printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs);
 			breakme = 0;
-			c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,
-					  brokenbuf, NULL, c->oobinfo);
+			c->mtd->write(c->mtd, ofs, towrite, &retlen,
+				      brokenbuf);
 			ret = -EIO;
 		} else
 #endif
-		if (jffs2_cleanmarker_oob(c))
-			ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen,
-						rewrite_buf, NULL, c->oobinfo);
-		else
-			ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, rewrite_buf);
+			ret = c->mtd->write(c->mtd, ofs, towrite, &retlen,
+					    rewrite_buf);
 
 		if (ret || retlen != towrite) {
 			/* Argh. We tried. Really we did. */
 			printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n");
 			kfree(buf);
 
-			if (retlen) {
-				struct jffs2_raw_node_ref *raw2;
+			if (retlen)
+				jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, first_raw), NULL);
 
-				raw2 = jffs2_alloc_raw_node_ref();
-				if (!raw2)
-					return;
-
-				raw2->flash_offset = ofs | REF_OBSOLETE;
-				raw2->__totlen = ref_totlen(c, jeb, *first_raw);
-				raw2->next_phys = NULL;
-				raw2->next_in_ino = NULL;
-
-				jffs2_add_physical_node_ref(c, raw2);
-			}
 			return;
 		}
 		printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs);
@@ -326,12 +391,10 @@
 		c->wbuf_ofs = ofs + towrite;
 		memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len);
 		/* Don't muck about with c->wbuf_inodes. False positives are harmless. */
-		kfree(buf);
 	} else {
 		/* OK, now we're left with the dregs in whichever buffer we're using */
 		if (buf) {
 			memcpy(c->wbuf, buf, end-start);
-			kfree(buf);
 		} else {
 			memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start);
 		}
@@ -343,62 +406,110 @@
 	new_jeb = &c->blocks[ofs / c->sector_size];
 
 	spin_lock(&c->erase_completion_lock);
-	if (new_jeb->first_node) {
-		/* Odd, but possible with ST flash later maybe */
-		new_jeb->last_node->next_phys = *first_raw;
-	} else {
-		new_jeb->first_node = *first_raw;
-	}
-
-	raw = first_raw;
-	while (*raw) {
-		uint32_t rawlen = ref_totlen(c, jeb, *raw);
+	for (raw = first_raw; raw != jeb->last_node; raw = ref_next(raw)) {
+		uint32_t rawlen = ref_totlen(c, jeb, raw);
+		struct jffs2_inode_cache *ic;
+		struct jffs2_raw_node_ref *new_ref;
+		struct jffs2_raw_node_ref **adjust_ref = NULL;
+		struct jffs2_inode_info *f = NULL;
 
 		D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n",
-			  rawlen, ref_offset(*raw), ref_flags(*raw), ofs));
+			  rawlen, ref_offset(raw), ref_flags(raw), ofs));
 
-		if (ref_obsolete(*raw)) {
-			/* Shouldn't really happen much */
-			new_jeb->dirty_size += rawlen;
-			new_jeb->free_size -= rawlen;
-			c->dirty_size += rawlen;
-		} else {
-			new_jeb->used_size += rawlen;
-			new_jeb->free_size -= rawlen;
+		ic = jffs2_raw_ref_to_ic(raw);
+
+		/* Ick. This XATTR mess should be fixed shortly... */
+		if (ic && ic->class == RAWNODE_CLASS_XATTR_DATUM) {
+			struct jffs2_xattr_datum *xd = (void *)ic;
+			BUG_ON(xd->node != raw);
+			adjust_ref = &xd->node;
+			raw->next_in_ino = NULL;
+			ic = NULL;
+		} else if (ic && ic->class == RAWNODE_CLASS_XATTR_REF) {
+			struct jffs2_xattr_datum *xr = (void *)ic;
+			BUG_ON(xr->node != raw);
+			adjust_ref = &xr->node;
+			raw->next_in_ino = NULL;
+			ic = NULL;
+		} else if (ic && ic->class == RAWNODE_CLASS_INODE_CACHE) {
+			struct jffs2_raw_node_ref **p = &ic->nodes;
+
+			/* Remove the old node from the per-inode list */
+			while (*p && *p != (void *)ic) {
+				if (*p == raw) {
+					(*p) = (raw->next_in_ino);
+					raw->next_in_ino = NULL;
+					break;
+				}
+				p = &((*p)->next_in_ino);
+			}
+
+			if (ic->state == INO_STATE_PRESENT && !ref_obsolete(raw)) {
+				/* If it's an in-core inode, then we have to adjust any
+				   full_dirent or full_dnode structure to point to the
+				   new version instead of the old */
+				f = jffs2_gc_fetch_inode(c, ic->ino, ic->nlink);
+				if (IS_ERR(f)) {
+					/* Should never happen; it _must_ be present */
+					JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n",
+						    ic->ino, PTR_ERR(f));
+					BUG();
+				}
+				/* We don't lock f->sem. There's a number of ways we could
+				   end up in here with it already being locked, and nobody's
+				   going to modify it on us anyway because we hold the
+				   alloc_sem. We're only changing one ->raw pointer too,
+				   which we can get away with without upsetting readers. */
+				adjust_ref = jffs2_incore_replace_raw(c, f, raw,
+								      (void *)(buf?:c->wbuf) + (ref_offset(raw) - start));
+			} else if (unlikely(ic->state != INO_STATE_PRESENT &&
+					    ic->state != INO_STATE_CHECKEDABSENT &&
+					    ic->state != INO_STATE_GC)) {
+				JFFS2_ERROR("Inode #%u is in strange state %d!\n", ic->ino, ic->state);
+				BUG();
+			}
+		}
+
+		new_ref = jffs2_link_node_ref(c, new_jeb, ofs | ref_flags(raw), rawlen, ic);
+
+		if (adjust_ref) {
+			BUG_ON(*adjust_ref != raw);
+			*adjust_ref = new_ref;
+		}
+		if (f)
+			jffs2_gc_release_inode(c, f);
+
+		if (!ref_obsolete(raw)) {
 			jeb->dirty_size += rawlen;
 			jeb->used_size  -= rawlen;
 			c->dirty_size += rawlen;
+			c->used_size -= rawlen;
+			raw->flash_offset = ref_offset(raw) | REF_OBSOLETE;
+			BUG_ON(raw->next_in_ino);
 		}
-		c->free_size -= rawlen;
-		(*raw)->flash_offset = ofs | ref_flags(*raw);
 		ofs += rawlen;
-		new_jeb->last_node = *raw;
-
-		raw = &(*raw)->next_phys;
 	}
 
+	kfree(buf);
+
 	/* Fix up the original jeb now it's on the bad_list */
-	*first_raw = NULL;
-	if (first_raw == &jeb->first_node) {
-		jeb->last_node = NULL;
+	if (first_raw == jeb->first_node) {
 		D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset));
-		list_del(&jeb->list);
-		list_add(&jeb->list, &c->erase_pending_list);
+		list_move(&jeb->list, &c->erase_pending_list);
 		c->nr_erasing_blocks++;
 		jffs2_erase_pending_trigger(c);
 	}
-	else
-		jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys);
 
 	jffs2_dbg_acct_sanity_check_nolock(c, jeb);
-        jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
+	jffs2_dbg_acct_paranoia_check_nolock(c, jeb);
 
 	jffs2_dbg_acct_sanity_check_nolock(c, new_jeb);
-        jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb);
+	jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb);
 
 	spin_unlock(&c->erase_completion_lock);
 
-	D1(printk(KERN_DEBUG "wbuf recovery completed OK\n"));
+	D1(printk(KERN_DEBUG "wbuf recovery completed OK. wbuf_ofs 0x%08x, len 0x%x\n", c->wbuf_ofs, c->wbuf_len));
+
 }
 
 /* Meaning of pad argument:
@@ -412,6 +523,7 @@
 
 static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 {
+	struct jffs2_eraseblock *wbuf_jeb;
 	int ret;
 	size_t retlen;
 
@@ -429,6 +541,10 @@
 	if (!c->wbuf_len)	/* already checked c->wbuf above */
 		return 0;
 
+	wbuf_jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
+	if (jffs2_prealloc_raw_node_refs(c, wbuf_jeb, c->nextblock->allocated_refs + 1))
+		return -ENOMEM;
+
 	/* claim remaining space on the page
 	   this happens, if we have a change to a new block,
 	   or if fsync forces us to flush the writebuffer.
@@ -458,15 +574,12 @@
 	if (breakme++ == 20) {
 		printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs);
 		breakme = 0;
-		c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize,
-					&retlen, brokenbuf, NULL, c->oobinfo);
+		c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen,
+			      brokenbuf);
 		ret = -EIO;
 	} else
 #endif
 
-	if (jffs2_cleanmarker_oob(c))
-		ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo);
-	else
 		ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf);
 
 	if (ret || retlen != c->wbuf_pagesize) {
@@ -483,32 +596,34 @@
 		return ret;
 	}
 
-	spin_lock(&c->erase_completion_lock);
-
 	/* Adjust free size of the block if we padded. */
 	if (pad) {
-		struct jffs2_eraseblock *jeb;
-
-		jeb = &c->blocks[c->wbuf_ofs / c->sector_size];
+		uint32_t waste = c->wbuf_pagesize - c->wbuf_len;
 
 		D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n",
-			  (jeb==c->nextblock)?"next":"", jeb->offset));
+			  (wbuf_jeb==c->nextblock)?"next":"", wbuf_jeb->offset));
 
 		/* wbuf_pagesize - wbuf_len is the amount of space that's to be
 		   padded. If there is less free space in the block than that,
 		   something screwed up */
-		if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) {
+		if (wbuf_jeb->free_size < waste) {
 			printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n",
-			       c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len);
+			       c->wbuf_ofs, c->wbuf_len, waste);
 			printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n",
-			       jeb->offset, jeb->free_size);
+			       wbuf_jeb->offset, wbuf_jeb->free_size);
 			BUG();
 		}
-		jeb->free_size -= (c->wbuf_pagesize - c->wbuf_len);
-		c->free_size -= (c->wbuf_pagesize - c->wbuf_len);
-		jeb->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
-		c->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
-	}
+
+		spin_lock(&c->erase_completion_lock);
+
+		jffs2_link_node_ref(c, wbuf_jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL);
+		/* FIXME: that made it count as dirty. Convert to wasted */
+		wbuf_jeb->dirty_size -= waste;
+		c->dirty_size -= waste;
+		wbuf_jeb->wasted_size += waste;
+		c->wasted_size += waste;
+	} else
+		spin_lock(&c->erase_completion_lock);
 
 	/* Stick any now-obsoleted blocks on the erase_pending_list */
 	jffs2_refile_wbuf_blocks(c);
@@ -603,20 +718,30 @@
 
 	return ret;
 }
-int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino)
-{
-	struct kvec outvecs[3];
-	uint32_t totlen = 0;
-	uint32_t split_ofs = 0;
-	uint32_t old_totlen;
-	int ret, splitvec = -1;
-	int invec, outvec;
-	size_t wbuf_retlen;
-	unsigned char *wbuf_ptr;
-	size_t donelen = 0;
-	uint32_t outvec_to = to;
 
-	/* If not NAND flash, don't bother */
+static size_t jffs2_fill_wbuf(struct jffs2_sb_info *c, const uint8_t *buf,
+			      size_t len)
+{
+	if (len && !c->wbuf_len && (len >= c->wbuf_pagesize))
+		return 0;
+
+	if (len > (c->wbuf_pagesize - c->wbuf_len))
+		len = c->wbuf_pagesize - c->wbuf_len;
+	memcpy(c->wbuf + c->wbuf_len, buf, len);
+	c->wbuf_len += (uint32_t) len;
+	return len;
+}
+
+int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs,
+		       unsigned long count, loff_t to, size_t *retlen,
+		       uint32_t ino)
+{
+	struct jffs2_eraseblock *jeb;
+	size_t wbuf_retlen, donelen = 0;
+	uint32_t outvec_to = to;
+	int ret, invec;
+
+	/* If not writebuffered flash, don't bother */
 	if (!jffs2_is_writebuffered(c))
 		return jffs2_flash_direct_writev(c, invecs, count, to, retlen);
 
@@ -629,34 +754,22 @@
 		memset(c->wbuf,0xff,c->wbuf_pagesize);
 	}
 
-	/* Fixup the wbuf if we are moving to a new eraseblock.  The checks below
-	   fail for ECC'd NOR because cleanmarker == 16, so a block starts at
-	   xxx0010.  */
-	if (jffs2_nor_ecc(c)) {
-		if (((c->wbuf_ofs % c->sector_size) == 0) && !c->wbuf_len) {
-			c->wbuf_ofs = PAGE_DIV(to);
-			c->wbuf_len = PAGE_MOD(to);
-			memset(c->wbuf,0xff,c->wbuf_pagesize);
-		}
-	}
-
-	/* Sanity checks on target address.
-	   It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs),
-	   and it's permitted to write at the beginning of a new
-	   erase block. Anything else, and you die.
-	   New block starts at xxx000c (0-b = block header)
-	*/
+	/*
+	 * Sanity checks on target address.  It's permitted to write
+	 * at PAD(c->wbuf_len+c->wbuf_ofs), and it's permitted to
+	 * write at the beginning of a new erase block. Anything else,
+	 * and you die.  New block starts at xxx000c (0-b = block
+	 * header)
+	 */
 	if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) {
 		/* It's a write to a new block */
 		if (c->wbuf_len) {
-			D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs));
+			D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx "
+				  "causes flush of wbuf at 0x%08x\n",
+				  (unsigned long)to, c->wbuf_ofs));
 			ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT);
-			if (ret) {
-				/* the underlying layer has to check wbuf_len to do the cleanup */
-				D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));
-				*retlen = 0;
-				goto exit;
-			}
+			if (ret)
+				goto outerr;
 		}
 		/* set pointer to new block */
 		c->wbuf_ofs = PAGE_DIV(to);
@@ -665,165 +778,70 @@
 
 	if (to != PAD(c->wbuf_ofs + c->wbuf_len)) {
 		/* We're not writing immediately after the writebuffer. Bad. */
-		printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write to %08lx\n", (unsigned long)to);
+		printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write "
+		       "to %08lx\n", (unsigned long)to);
 		if (c->wbuf_len)
 			printk(KERN_CRIT "wbuf was previously %08x-%08x\n",
-					  c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len);
+			       c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len);
 		BUG();
 	}
 
-	/* Note outvecs[3] above. We know count is never greater than 2 */
-	if (count > 2) {
-		printk(KERN_CRIT "jffs2_flash_writev(): count is %ld\n", count);
-		BUG();
-	}
-
-	invec = 0;
-	outvec = 0;
-
-	/* Fill writebuffer first, if already in use */
-	if (c->wbuf_len) {
-		uint32_t invec_ofs = 0;
-
-		/* adjust alignment offset */
-		if (c->wbuf_len != PAGE_MOD(to)) {
-			c->wbuf_len = PAGE_MOD(to);
-			/* take care of alignment to next page */
-			if (!c->wbuf_len)
-				c->wbuf_len = c->wbuf_pagesize;
-		}
-
-		while(c->wbuf_len < c->wbuf_pagesize) {
-			uint32_t thislen;
-
-			if (invec == count)
-				goto alldone;
-
-			thislen = c->wbuf_pagesize - c->wbuf_len;
-
-			if (thislen >= invecs[invec].iov_len)
-				thislen = invecs[invec].iov_len;
-
-			invec_ofs = thislen;
-
-			memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen);
-			c->wbuf_len += thislen;
-			donelen += thislen;
-			/* Get next invec, if actual did not fill the buffer */
-			if (c->wbuf_len < c->wbuf_pagesize)
-				invec++;
-		}
-
-		/* write buffer is full, flush buffer */
-		ret = __jffs2_flush_wbuf(c, NOPAD);
-		if (ret) {
-			/* the underlying layer has to check wbuf_len to do the cleanup */
-			D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret));
-			/* Retlen zero to make sure our caller doesn't mark the space dirty.
-			   We've already done everything that's necessary */
-			*retlen = 0;
-			goto exit;
-		}
-		outvec_to += donelen;
-		c->wbuf_ofs = outvec_to;
-
-		/* All invecs done ? */
-		if (invec == count)
-			goto alldone;
-
-		/* Set up the first outvec, containing the remainder of the
-		   invec we partially used */
-		if (invecs[invec].iov_len > invec_ofs) {
-			outvecs[0].iov_base = invecs[invec].iov_base+invec_ofs;
-			totlen = outvecs[0].iov_len = invecs[invec].iov_len-invec_ofs;
-			if (totlen > c->wbuf_pagesize) {
-				splitvec = outvec;
-				split_ofs = outvecs[0].iov_len - PAGE_MOD(totlen);
-			}
-			outvec++;
-		}
-		invec++;
-	}
-
-	/* OK, now we've flushed the wbuf and the start of the bits
-	   we have been asked to write, now to write the rest.... */
-
-	/* totlen holds the amount of data still to be written */
-	old_totlen = totlen;
-	for ( ; invec < count; invec++,outvec++ ) {
-		outvecs[outvec].iov_base = invecs[invec].iov_base;
-		totlen += outvecs[outvec].iov_len = invecs[invec].iov_len;
-		if (PAGE_DIV(totlen) != PAGE_DIV(old_totlen)) {
-			splitvec = outvec;
-			split_ofs = outvecs[outvec].iov_len - PAGE_MOD(totlen);
-			old_totlen = totlen;
+	/* adjust alignment offset */
+	if (c->wbuf_len != PAGE_MOD(to)) {
+		c->wbuf_len = PAGE_MOD(to);
+		/* take care of alignment to next page */
+		if (!c->wbuf_len) {
+			c->wbuf_len = c->wbuf_pagesize;
+			ret = __jffs2_flush_wbuf(c, NOPAD);
+			if (ret)
+				goto outerr;
 		}
 	}
 
-	/* Now the outvecs array holds all the remaining data to write */
-	/* Up to splitvec,split_ofs is to be written immediately. The rest
-	   goes into the (now-empty) wbuf */
+	for (invec = 0; invec < count; invec++) {
+		int vlen = invecs[invec].iov_len;
+		uint8_t *v = invecs[invec].iov_base;
 
-	if (splitvec != -1) {
-		uint32_t remainder;
+		wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
 
-		remainder = outvecs[splitvec].iov_len - split_ofs;
-		outvecs[splitvec].iov_len = split_ofs;
-
-		/* We did cross a page boundary, so we write some now */
-		if (jffs2_cleanmarker_oob(c))
-			ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo);
-		else
-			ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen);
-
-		if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) {
-			/* At this point we have no problem,
-			   c->wbuf is empty. However refile nextblock to avoid
-			   writing again to same address.
-			*/
-			struct jffs2_eraseblock *jeb;
-
-			spin_lock(&c->erase_completion_lock);
-
-			jeb = &c->blocks[outvec_to / c->sector_size];
-			jffs2_block_refile(c, jeb, REFILE_ANYWAY);
-
-			*retlen = 0;
-			spin_unlock(&c->erase_completion_lock);
-			goto exit;
+		if (c->wbuf_len == c->wbuf_pagesize) {
+			ret = __jffs2_flush_wbuf(c, NOPAD);
+			if (ret)
+				goto outerr;
 		}
-
+		vlen -= wbuf_retlen;
+		outvec_to += wbuf_retlen;
 		donelen += wbuf_retlen;
-		c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen);
+		v += wbuf_retlen;
 
-		if (remainder) {
-			outvecs[splitvec].iov_base += split_ofs;
-			outvecs[splitvec].iov_len = remainder;
-		} else {
-			splitvec++;
+		if (vlen >= c->wbuf_pagesize) {
+			ret = c->mtd->write(c->mtd, outvec_to, PAGE_DIV(vlen),
+					    &wbuf_retlen, v);
+			if (ret < 0 || wbuf_retlen != PAGE_DIV(vlen))
+				goto outfile;
+
+			vlen -= wbuf_retlen;
+			outvec_to += wbuf_retlen;
+			c->wbuf_ofs = outvec_to;
+			donelen += wbuf_retlen;
+			v += wbuf_retlen;
 		}
 
-	} else {
-		splitvec = 0;
+		wbuf_retlen = jffs2_fill_wbuf(c, v, vlen);
+		if (c->wbuf_len == c->wbuf_pagesize) {
+			ret = __jffs2_flush_wbuf(c, NOPAD);
+			if (ret)
+				goto outerr;
+		}
+
+		outvec_to += wbuf_retlen;
+		donelen += wbuf_retlen;
 	}
 
-	/* Now splitvec points to the start of the bits we have to copy
-	   into the wbuf */
-	wbuf_ptr = c->wbuf;
-
-	for ( ; splitvec < outvec; splitvec++) {
-		/* Don't copy the wbuf into itself */
-		if (outvecs[splitvec].iov_base == c->wbuf)
-			continue;
-		memcpy(wbuf_ptr, outvecs[splitvec].iov_base, outvecs[splitvec].iov_len);
-		wbuf_ptr += outvecs[splitvec].iov_len;
-		donelen += outvecs[splitvec].iov_len;
-	}
-	c->wbuf_len = wbuf_ptr - c->wbuf;
-
-	/* If there's a remainder in the wbuf and it's a non-GC write,
-	   remember that the wbuf affects this ino */
-alldone:
+	/*
+	 * If there's a remainder in the wbuf and it's a non-GC write,
+	 * remember that the wbuf affects this ino
+	 */
 	*retlen = donelen;
 
 	if (jffs2_sum_active()) {
@@ -836,8 +854,24 @@
 		jffs2_wbuf_dirties_inode(c, ino);
 
 	ret = 0;
+	up_write(&c->wbuf_sem);
+	return ret;
 
-exit:
+outfile:
+	/*
+	 * At this point we have no problem, c->wbuf is empty. However
+	 * refile nextblock to avoid writing again to same address.
+	 */
+
+	spin_lock(&c->erase_completion_lock);
+
+	jeb = &c->blocks[outvec_to / c->sector_size];
+	jffs2_block_refile(c, jeb, REFILE_ANYWAY);
+
+	spin_unlock(&c->erase_completion_lock);
+
+outerr:
+	*retlen = 0;
 	up_write(&c->wbuf_sem);
 	return ret;
 }
@@ -846,7 +880,8 @@
  *	This is the entry for flash write.
  *	Check, if we work on NAND FLASH, if so build an kvec and write it via vritev
 */
-int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf)
+int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
+		      size_t *retlen, const u_char *buf)
 {
 	struct kvec vecs[1];
 
@@ -871,25 +906,23 @@
 
 	/* Read flash */
 	down_read(&c->wbuf_sem);
-	if (jffs2_cleanmarker_oob(c))
-		ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo);
-	else
-		ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
+	ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
 
-	if ( (ret == -EBADMSG) && (*retlen == len) ) {
-		printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n",
-		       len, ofs);
+	if ( (ret == -EBADMSG || ret == -EUCLEAN) && (*retlen == len) ) {
+		if (ret == -EBADMSG)
+			printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx)"
+			       " returned ECC error\n", len, ofs);
 		/*
-		 * We have the raw data without ECC correction in the buffer, maybe
-		 * we are lucky and all data or parts are correct. We check the node.
-		 * If data are corrupted node check will sort it out.
-		 * We keep this block, it will fail on write or erase and the we
-		 * mark it bad. Or should we do that now? But we should give him a chance.
-		 * Maybe we had a system crash or power loss before the ecc write or
-		 * a erase was completed.
+		 * We have the raw data without ECC correction in the buffer,
+		 * maybe we are lucky and all data or parts are correct. We
+		 * check the node.  If data are corrupted node check will sort
+		 * it out.  We keep this block, it will fail on write or erase
+		 * and the we mark it bad. Or should we do that now? But we
+		 * should give him a chance.  Maybe we had a system crash or
+		 * power loss before the ecc write or a erase was completed.
 		 * So we return success. :)
 		 */
-	 	ret = 0;
+		ret = 0;
 	}
 
 	/* if no writebuffer available or write buffer empty, return */
@@ -911,7 +944,7 @@
 		orbf = (c->wbuf_ofs - ofs);	/* offset in read buffer */
 		if (orbf > len)			/* is write beyond write buffer ? */
 			goto exit;
-		lwbf = len - orbf; 		/* number of bytes to copy */
+		lwbf = len - orbf;		/* number of bytes to copy */
 		if (lwbf > c->wbuf_len)
 			lwbf = c->wbuf_len;
 	}
@@ -923,158 +956,159 @@
 	return ret;
 }
 
+#define NR_OOB_SCAN_PAGES	4
+
 /*
- *	Check, if the out of band area is empty
+ * Check, if the out of band area is empty
  */
-int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode)
+int jffs2_check_oob_empty(struct jffs2_sb_info *c,
+			  struct jffs2_eraseblock *jeb, int mode)
 {
-	unsigned char *buf;
-	int 	ret = 0;
-	int	i,len,page;
-	size_t  retlen;
-	int	oob_size;
+	int i, page, ret;
+	int oobsize = c->mtd->oobsize;
+	struct mtd_oob_ops ops;
 
-	/* allocate a buffer for all oob data in this sector */
-	oob_size = c->mtd->oobsize;
-	len = 4 * oob_size;
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n");
-		return -ENOMEM;
-	}
-	/*
-	 * if mode = 0, we scan for a total empty oob area, else we have
-	 * to take care of the cleanmarker in the first page of the block
-	*/
-	ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf);
+	ops.len = NR_OOB_SCAN_PAGES * oobsize;
+	ops.ooblen = oobsize;
+	ops.oobbuf = c->oobbuf;
+	ops.ooboffs = 0;
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_PLACE;
+
+	ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops);
 	if (ret) {
-		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
-		goto out;
+		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
+			  "failed %d for block at %08x\n", ret, jeb->offset));
+		return ret;
 	}
 
-	if (retlen < len) {
-		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read "
-			  "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset));
-		ret = -EIO;
-		goto out;
+	if (ops.retlen < ops.len) {
+		D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB "
+			  "returned short read (%zd bytes not %d) for block "
+			  "at %08x\n", ops.retlen, ops.len, jeb->offset));
+		return -EIO;
 	}
 
 	/* Special check for first page */
-	for(i = 0; i < oob_size ; i++) {
+	for(i = 0; i < oobsize ; i++) {
 		/* Yeah, we know about the cleanmarker. */
 		if (mode && i >= c->fsdata_pos &&
 		    i < c->fsdata_pos + c->fsdata_len)
 			continue;
 
-		if (buf[i] != 0xFF) {
-			D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n",
-				  buf[i], i, jeb->offset));
-			ret = 1;
-			goto out;
+		if (ops.oobbuf[i] != 0xFF) {
+			D2(printk(KERN_DEBUG "Found %02x at %x in OOB for "
+				  "%08x\n", ops.oobbuf[i], i, jeb->offset));
+			return 1;
 		}
 	}
 
 	/* we know, we are aligned :) */
-	for (page = oob_size; page < len; page += sizeof(long)) {
-		unsigned long dat = *(unsigned long *)(&buf[page]);
-		if(dat != -1) {
-			ret = 1;
-			goto out;
-		}
+	for (page = oobsize; page < ops.len; page += sizeof(long)) {
+		long dat = *(long *)(&ops.oobbuf[page]);
+		if(dat != -1)
+			return 1;
 	}
-
-out:
-	kfree(buf);
-
-	return ret;
+	return 0;
 }
 
 /*
-*	Scan for a valid cleanmarker and for bad blocks
-*	For virtual blocks (concatenated physical blocks) check the cleanmarker
-*	only in the first page of the first physical block, but scan for bad blocks in all
-*	physical blocks
-*/
-int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+ * Scan for a valid cleanmarker and for bad blocks
+ */
+int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c,
+				  struct jffs2_eraseblock *jeb)
 {
 	struct jffs2_unknown_node n;
-	unsigned char buf[2 * NAND_MAX_OOBSIZE];
-	unsigned char *p;
-	int ret, i, cnt, retval = 0;
-	size_t retlen, offset;
-	int oob_size;
+	struct mtd_oob_ops ops;
+	int oobsize = c->mtd->oobsize;
+	unsigned char *p,*b;
+	int i, ret;
+	size_t offset = jeb->offset;
 
-	offset = jeb->offset;
-	oob_size = c->mtd->oobsize;
-
-	/* Loop through the physical blocks */
-	for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) {
-		/* Check first if the block is bad. */
-		if (c->mtd->block_isbad (c->mtd, offset)) {
-			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset));
-			return 2;
-		}
-		/*
-		   *    We read oob data from page 0 and 1 of the block.
-		   *    page 0 contains cleanmarker and badblock info
-		   *    page 1 contains failure count of this block
-		 */
-		ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf);
-
-		if (ret) {
-			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset));
-			return ret;
-		}
-		if (retlen < (oob_size << 1)) {
-			D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset));
-			return -EIO;
-		}
-
-		/* Check cleanmarker only on the first physical block */
-		if (!cnt) {
-			n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
-			n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
-			n.totlen = cpu_to_je32 (8);
-			p = (unsigned char *) &n;
-
-			for (i = 0; i < c->fsdata_len; i++) {
-				if (buf[c->fsdata_pos + i] != p[i]) {
-					retval = 1;
-				}
-			}
-			D1(if (retval == 1) {
-				printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset);
-				printk(KERN_WARNING "OOB at %08x was ", offset);
-				for (i=0; i < oob_size; i++) {
-					printk("%02x ", buf[i]);
-				}
-				printk("\n");
-			})
-		}
-		offset += c->mtd->erasesize;
+	/* Check first if the block is bad. */
+	if (c->mtd->block_isbad(c->mtd, offset)) {
+		D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()"
+			   ": Bad block at %08x\n", jeb->offset));
+		return 2;
 	}
-	return retval;
+
+	ops.len = oobsize;
+	ops.ooblen = oobsize;
+	ops.oobbuf = c->oobbuf;
+	ops.ooboffs = 0;
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_PLACE;
+
+	ret = c->mtd->read_oob(c->mtd, offset, &ops);
+	if (ret) {
+		D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
+			   "Read OOB failed %d for block at %08x\n",
+			   ret, jeb->offset));
+		return ret;
+	}
+
+	if (ops.retlen < ops.len) {
+		D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): "
+			    "Read OOB return short read (%zd bytes not %d) "
+			    "for block at %08x\n", ops.retlen, ops.len,
+			    jeb->offset));
+		return -EIO;
+	}
+
+	n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
+	n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
+	n.totlen = cpu_to_je32 (8);
+	p = (unsigned char *) &n;
+	b = c->oobbuf + c->fsdata_pos;
+
+	for (i = c->fsdata_len; i; i--) {
+		if (*b++ != *p++)
+			ret = 1;
+	}
+
+	D1(if (ret == 1) {
+		printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): "
+		       "Cleanmarker node not detected in block at %08x\n",
+		       offset);
+		printk(KERN_WARNING "OOB at %08zx was ", offset);
+		for (i=0; i < oobsize; i++)
+			printk("%02x ", c->oobbuf[i]);
+		printk("\n");
+	});
+	return ret;
 }
 
-int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
+int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c,
+				 struct jffs2_eraseblock *jeb)
 {
-	struct 	jffs2_unknown_node n;
-	int 	ret;
-	size_t 	retlen;
+	struct jffs2_unknown_node n;
+	int	ret;
+	struct mtd_oob_ops ops;
 
 	n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
 	n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
 	n.totlen = cpu_to_je32(8);
 
-	ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n);
+	ops.len = c->fsdata_len;
+	ops.ooblen = c->fsdata_len;;
+	ops.oobbuf = (uint8_t *)&n;
+	ops.ooboffs = c->fsdata_pos;
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_PLACE;
+
+	ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops);
 
 	if (ret) {
-		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret));
+		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
+			  "Write failed for block at %08x: error %d\n",
+			  jeb->offset, ret));
 		return ret;
 	}
-	if (retlen != c->fsdata_len) {
-		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len));
-		return ret;
+	if (ops.retlen != ops.len) {
+		D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): "
+			  "Short write for block at %08x: %zd not %d\n",
+			  jeb->offset, ops.retlen, ops.len));
+		return -EIO;
 	}
 	return 0;
 }
@@ -1108,18 +1142,9 @@
 	return 1;
 }
 
-#define NAND_JFFS2_OOB16_FSDALEN	8
-
-static struct nand_oobinfo jffs2_oobinfo_docecc = {
-	.useecc = MTD_NANDECC_PLACE,
-	.eccbytes = 6,
-	.eccpos = {0,1,2,3,4,5}
-};
-
-
 static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c)
 {
-	struct nand_oobinfo *oinfo = &c->mtd->oobinfo;
+	struct nand_ecclayout *oinfo = c->mtd->ecclayout;
 
 	/* Do this only, if we have an oob buffer */
 	if (!c->mtd->oobsize)
@@ -1129,33 +1154,23 @@
 	c->cleanmarker_size = 0;
 
 	/* Should we use autoplacement ? */
-	if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) {
-		D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
-		/* Get the position of the free bytes */
-		if (!oinfo->oobfree[0][1]) {
-			printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n");
-			return -ENOSPC;
-		}
-		c->fsdata_pos = oinfo->oobfree[0][0];
-		c->fsdata_len = oinfo->oobfree[0][1];
-		if (c->fsdata_len > 8)
-			c->fsdata_len = 8;
-	} else {
-		/* This is just a legacy fallback and should go away soon */
-		switch(c->mtd->ecctype) {
-		case MTD_ECC_RS_DiskOnChip:
-			printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n");
-			c->oobinfo = &jffs2_oobinfo_docecc;
-			c->fsdata_pos = 6;
-			c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN;
-			c->badblock_pos = 15;
-			break;
-
-		default:
-			D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
-			return -EINVAL;
-		}
+	if (!oinfo) {
+		D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n"));
+		return -EINVAL;
 	}
+
+	D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n"));
+	/* Get the position of the free bytes */
+	if (!oinfo->oobfree[0].length) {
+		printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep."
+			" Autoplacement selected and no empty space in oob\n");
+		return -ENOSPC;
+	}
+	c->fsdata_pos = oinfo->oobfree[0].offset;
+	c->fsdata_len = oinfo->oobfree[0].length;
+	if (c->fsdata_len > 8)
+		c->fsdata_len = 8;
+
 	return 0;
 }
 
@@ -1165,13 +1180,17 @@
 
 	/* Initialise write buffer */
 	init_rwsem(&c->wbuf_sem);
-	c->wbuf_pagesize = c->mtd->oobblock;
+	c->wbuf_pagesize = c->mtd->writesize;
 	c->wbuf_ofs = 0xFFFFFFFF;
 
 	c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
 	if (!c->wbuf)
 		return -ENOMEM;
 
+	c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL);
+	if (!c->oobbuf)
+		return -ENOMEM;
+
 	res = jffs2_nand_set_oobinfo(c);
 
 #ifdef BREAKME
@@ -1189,6 +1208,7 @@
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
 {
 	kfree(c->wbuf);
+	kfree(c->oobbuf);
 }
 
 int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
@@ -1236,33 +1256,14 @@
 	kfree(c->wbuf);
 }
 
-int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) {
-	/* Cleanmarker is actually larger on the flashes */
-	c->cleanmarker_size = 16;
-
-	/* Initialize write buffer */
-	init_rwsem(&c->wbuf_sem);
-	c->wbuf_pagesize = c->mtd->eccsize;
-	c->wbuf_ofs = 0xFFFFFFFF;
-
-	c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-	if (!c->wbuf)
-		return -ENOMEM;
-
-	return 0;
-}
-
-void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) {
-	kfree(c->wbuf);
-}
-
 int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
-	/* Cleanmarker currently occupies a whole programming region */
-	c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd);
+	/* Cleanmarker currently occupies whole programming regions,
+	 * either one or 2 for 8Byte STMicro flashes. */
+	c->cleanmarker_size = max(16u, c->mtd->writesize);
 
 	/* Initialize write buffer */
 	init_rwsem(&c->wbuf_sem);
-	c->wbuf_pagesize = MTD_PROGREGION_SIZE(c->mtd);
+	c->wbuf_pagesize = c->mtd->writesize;
 	c->wbuf_ofs = 0xFFFFFFFF;
 
 	c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index 1342f01..6717679 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -37,7 +37,6 @@
 	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
 	f->inocache->state = INO_STATE_PRESENT;
 
-
 	jffs2_add_ino_cache(c, f->inocache);
 	D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
 	ri->ino = cpu_to_je32(f->inocache->ino);
@@ -57,12 +56,14 @@
 /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
    write it to the flash, link it into the existing inode/fragment list */
 
-struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode)
+struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+					   struct jffs2_raw_inode *ri, const unsigned char *data,
+					   uint32_t datalen, int alloc_mode)
 
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_full_dnode *fn;
 	size_t retlen;
+	uint32_t flash_ofs;
 	struct kvec vecs[2];
 	int ret;
 	int retried = 0;
@@ -78,34 +79,21 @@
 	vecs[1].iov_base = (unsigned char *)data;
 	vecs[1].iov_len = datalen;
 
-	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
-
 	if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
 		printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen);
 	}
-	raw = jffs2_alloc_raw_node_ref();
-	if (!raw)
-		return ERR_PTR(-ENOMEM);
 
 	fn = jffs2_alloc_full_dnode();
-	if (!fn) {
-		jffs2_free_raw_node_ref(raw);
+	if (!fn)
 		return ERR_PTR(-ENOMEM);
-	}
-
-	fn->ofs = je32_to_cpu(ri->offset);
-	fn->size = je32_to_cpu(ri->dsize);
-	fn->frags = 0;
 
 	/* check number of valid vecs */
 	if (!datalen || !data)
 		cnt = 1;
  retry:
-	fn->raw = raw;
+	flash_ofs = write_ofs(c);
 
-	raw->flash_offset = flash_ofs;
-	raw->__totlen = PAD(sizeof(*ri)+datalen);
-	raw->next_phys = NULL;
+	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
 
 	if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
 		BUG_ON(!retried);
@@ -125,22 +113,16 @@
 
 		/* Mark the space as dirtied */
 		if (retlen) {
-			/* Doesn't belong to any inode */
-			raw->next_in_ino = NULL;
-
 			/* Don't change raw->size to match retlen. We may have
 			   written the node header already, and only the data will
 			   seem corrupted, in which case the scan would skip over
 			   any node we write before the original intended end of
 			   this node */
-			raw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, raw);
-			jffs2_mark_node_obsolete(c, raw);
+			jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL);
 		} else {
-			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
-			jffs2_free_raw_node_ref(raw);
+			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
 		}
-		if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) {
+		if (!retried && alloc_mode != ALLOC_NORETRY) {
 			/* Try to reallocate space and retry */
 			uint32_t dummy;
 			struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -153,19 +135,20 @@
 			jffs2_dbg_acct_paranoia_check(c, jeb);
 
 			if (alloc_mode == ALLOC_GC) {
-				ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs,
-							&dummy, JFFS2_SUMMARY_INODE_SIZE);
+				ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy,
+							     JFFS2_SUMMARY_INODE_SIZE);
 			} else {
 				/* Locking pain */
 				up(&f->sem);
 				jffs2_complete_reservation(c);
 
-				ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs,
-							&dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
+				ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy,
+							  alloc_mode, JFFS2_SUMMARY_INODE_SIZE);
 				down(&f->sem);
 			}
 
 			if (!ret) {
+				flash_ofs = write_ofs(c);
 				D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
 
 				jffs2_dbg_acct_sanity_check(c,jeb);
@@ -174,7 +157,6 @@
 				goto retry;
 			}
 			D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-			jffs2_free_raw_node_ref(raw);
 		}
 		/* Release the full_dnode which is now useless, and return */
 		jffs2_free_full_dnode(fn);
@@ -188,20 +170,17 @@
 	if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
 	    ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
 	      (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) ==  je32_to_cpu(ri->isize)))) {
-		raw->flash_offset |= REF_PRISTINE;
+		flash_ofs |= REF_PRISTINE;
 	} else {
-		raw->flash_offset |= REF_NORMAL;
+		flash_ofs |= REF_NORMAL;
 	}
-	jffs2_add_physical_node_ref(c, raw);
-
-	/* Link into per-inode list */
-	spin_lock(&c->erase_completion_lock);
-	raw->next_in_ino = f->inocache->nodes;
-	f->inocache->nodes = raw;
-	spin_unlock(&c->erase_completion_lock);
+	fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache);
+	fn->ofs = je32_to_cpu(ri->offset);
+	fn->size = je32_to_cpu(ri->dsize);
+	fn->frags = 0;
 
 	D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
-		  flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize),
+		  flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize),
 		  je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
 		  je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
 
@@ -212,12 +191,14 @@
 	return fn;
 }
 
-struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode)
+struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
+					     struct jffs2_raw_dirent *rd, const unsigned char *name,
+					     uint32_t namelen, int alloc_mode)
 {
-	struct jffs2_raw_node_ref *raw;
 	struct jffs2_full_dirent *fd;
 	size_t retlen;
 	struct kvec vecs[2];
+	uint32_t flash_ofs;
 	int retried = 0;
 	int ret;
 
@@ -228,26 +209,16 @@
 	D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
 		printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
 		BUG();
-	}
-	   );
+	   });
 
 	vecs[0].iov_base = rd;
 	vecs[0].iov_len = sizeof(*rd);
 	vecs[1].iov_base = (unsigned char *)name;
 	vecs[1].iov_len = namelen;
 
-	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
-
-	raw = jffs2_alloc_raw_node_ref();
-
-	if (!raw)
-		return ERR_PTR(-ENOMEM);
-
 	fd = jffs2_alloc_full_dirent(namelen+1);
-	if (!fd) {
-		jffs2_free_raw_node_ref(raw);
+	if (!fd)
 		return ERR_PTR(-ENOMEM);
-	}
 
 	fd->version = je32_to_cpu(rd->version);
 	fd->ino = je32_to_cpu(rd->ino);
@@ -257,11 +228,9 @@
 	fd->name[namelen]=0;
 
  retry:
-	fd->raw = raw;
+	flash_ofs = write_ofs(c);
 
-	raw->flash_offset = flash_ofs;
-	raw->__totlen = PAD(sizeof(*rd)+namelen);
-	raw->next_phys = NULL;
+	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
 
 	if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
 		BUG_ON(!retried);
@@ -280,15 +249,11 @@
 			       sizeof(*rd)+namelen, flash_ofs, ret, retlen);
 		/* Mark the space as dirtied */
 		if (retlen) {
-			raw->next_in_ino = NULL;
-			raw->flash_offset |= REF_OBSOLETE;
-			jffs2_add_physical_node_ref(c, raw);
-			jffs2_mark_node_obsolete(c, raw);
+			jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL);
 		} else {
-			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
-			jffs2_free_raw_node_ref(raw);
+			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs);
 		}
-		if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
+		if (!retried) {
 			/* Try to reallocate space and retry */
 			uint32_t dummy;
 			struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
@@ -301,39 +266,33 @@
 			jffs2_dbg_acct_paranoia_check(c, jeb);
 
 			if (alloc_mode == ALLOC_GC) {
-				ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs,
-							&dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+				ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy,
+							     JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 			} else {
 				/* Locking pain */
 				up(&f->sem);
 				jffs2_complete_reservation(c);
 
-				ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs,
-							&dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
+				ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy,
+							  alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 				down(&f->sem);
 			}
 
 			if (!ret) {
+				flash_ofs = write_ofs(c);
 				D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
 				jffs2_dbg_acct_sanity_check(c,jeb);
 				jffs2_dbg_acct_paranoia_check(c, jeb);
 				goto retry;
 			}
 			D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
-			jffs2_free_raw_node_ref(raw);
 		}
 		/* Release the full_dnode which is now useless, and return */
 		jffs2_free_full_dirent(fd);
 		return ERR_PTR(ret?ret:-EIO);
 	}
 	/* Mark the space used */
-	raw->flash_offset |= REF_PRISTINE;
-	jffs2_add_physical_node_ref(c, raw);
-
-	spin_lock(&c->erase_completion_lock);
-	raw->next_in_ino = f->inocache->nodes;
-	f->inocache->nodes = raw;
-	spin_unlock(&c->erase_completion_lock);
+	fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache);
 
 	if (retried) {
 		jffs2_dbg_acct_sanity_check(c,NULL);
@@ -359,14 +318,14 @@
 		struct jffs2_full_dnode *fn;
 		unsigned char *comprbuf = NULL;
 		uint16_t comprtype = JFFS2_COMPR_NONE;
-		uint32_t phys_ofs, alloclen;
+		uint32_t alloclen;
 		uint32_t datalen, cdatalen;
 		int retried = 0;
 
 	retry:
 		D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset));
 
-		ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs,
+		ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN,
 					&alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
 		if (ret) {
 			D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
@@ -394,7 +353,7 @@
 		ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 		ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
 
-		fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY);
+		fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY);
 
 		jffs2_free_comprbuf(comprbuf, buf);
 
@@ -448,13 +407,13 @@
 	struct jffs2_raw_dirent *rd;
 	struct jffs2_full_dnode *fn;
 	struct jffs2_full_dirent *fd;
-	uint32_t alloclen, phys_ofs;
+	uint32_t alloclen;
 	int ret;
 
 	/* Try to reserve enough space for both node and dirent.
 	 * Just the node will do for now, though
 	 */
-	ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL,
+	ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL,
 				JFFS2_SUMMARY_INODE_SIZE);
 	D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
 	if (ret) {
@@ -465,7 +424,7 @@
 	ri->data_crc = cpu_to_je32(0);
 	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
 
-	fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
+	fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL);
 
 	D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n",
 		  jemode_to_cpu(ri->mode)));
@@ -484,7 +443,7 @@
 
 	up(&f->sem);
 	jffs2_complete_reservation(c);
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
+	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
 				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 
 	if (ret) {
@@ -516,7 +475,7 @@
 	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
 	rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
 
-	fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
+	fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
 
 	jffs2_free_raw_dirent(rd);
 
@@ -545,7 +504,7 @@
 {
 	struct jffs2_raw_dirent *rd;
 	struct jffs2_full_dirent *fd;
-	uint32_t alloclen, phys_ofs;
+	uint32_t alloclen;
 	int ret;
 
 	if (1 /* alternative branch needs testing */ ||
@@ -556,7 +515,7 @@
 		if (!rd)
 			return -ENOMEM;
 
-		ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
+		ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
 					ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 		if (ret) {
 			jffs2_free_raw_dirent(rd);
@@ -580,7 +539,7 @@
 		rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
 		rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
 
-		fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION);
+		fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION);
 
 		jffs2_free_raw_dirent(rd);
 
@@ -659,14 +618,14 @@
 {
 	struct jffs2_raw_dirent *rd;
 	struct jffs2_full_dirent *fd;
-	uint32_t alloclen, phys_ofs;
+	uint32_t alloclen;
 	int ret;
 
 	rd = jffs2_alloc_raw_dirent();
 	if (!rd)
 		return -ENOMEM;
 
-	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen,
+	ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen,
 				ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen));
 	if (ret) {
 		jffs2_free_raw_dirent(rd);
@@ -692,7 +651,7 @@
 	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
 	rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
 
-	fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
+	fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL);
 
 	jffs2_free_raw_dirent(rd);
 
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
new file mode 100644
index 0000000..18e66db
--- /dev/null
+++ b/fs/jffs2/xattr.c
@@ -0,0 +1,1326 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/time.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/crc32.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+/* -------- xdatum related functions ----------------
+ * xattr_datum_hashkey(xprefix, xname, xvalue, xsize)
+ *   is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is
+ *   the index of the xattr name/value pair cache (c->xattrindex).
+ * is_xattr_datum_unchecked(c, xd)
+ *   returns 1, if xdatum contains any unchecked raw nodes. if all raw nodes are not
+ *   unchecked, it returns 0.
+ * unload_xattr_datum(c, xd)
+ *   is used to release xattr name/value pair and detach from c->xattrindex.
+ * reclaim_xattr_datum(c)
+ *   is used to reclaim xattr name/value pairs on the xattr name/value pair cache when
+ *   memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold 
+ *   is hard coded as 32KiB.
+ * do_verify_xattr_datum(c, xd)
+ *   is used to load the xdatum informations without name/value pair from the medium.
+ *   It's necessary once, because those informations are not collected during mounting
+ *   process when EBS is enabled.
+ *   0 will be returned, if success. An negative return value means recoverable error, and
+ *   positive return value means unrecoverable error. Thus, caller must remove this xdatum
+ *   and xref when it returned positive value.
+ * do_load_xattr_datum(c, xd)
+ *   is used to load name/value pair from the medium.
+ *   The meanings of return value is same as do_verify_xattr_datum().
+ * load_xattr_datum(c, xd)
+ *   is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum().
+ *   If xd need to call do_verify_xattr_datum() at first, it's called before calling
+ *   do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum().
+ * save_xattr_datum(c, xd)
+ *   is used to write xdatum to medium. xd->version will be incremented.
+ * create_xattr_datum(c, xprefix, xname, xvalue, xsize)
+ *   is used to create new xdatum and write to medium.
+ * delete_xattr_datum(c, xd)
+ *   is used to delete a xdatum. It marks xd JFFS2_XFLAGS_DEAD, and allows
+ *   GC to reclaim those physical nodes.
+ * -------------------------------------------------- */
+static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize)
+{
+	int name_len = strlen(xname);
+
+	return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize);
+}
+
+static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	struct jffs2_raw_node_ref *raw;
+	int rc = 0;
+
+	spin_lock(&c->erase_completion_lock);
+	for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
+		if (ref_flags(raw) == REF_UNCHECKED) {
+			rc = 1;
+			break;
+		}
+	}
+	spin_unlock(&c->erase_completion_lock);
+	return rc;
+}
+
+static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	/* must be called under down_write(xattr_sem) */
+	D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version));
+	if (xd->xname) {
+		c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len);
+		kfree(xd->xname);
+	}
+
+	list_del_init(&xd->xindex);
+	xd->hashkey = 0;
+	xd->xname = NULL;
+	xd->xvalue = NULL;
+}
+
+static void reclaim_xattr_datum(struct jffs2_sb_info *c)
+{
+	/* must be called under down_write(xattr_sem) */
+	struct jffs2_xattr_datum *xd, *_xd;
+	uint32_t target, before;
+	static int index = 0;
+	int count;
+
+	if (c->xdatum_mem_threshold > c->xdatum_mem_usage)
+		return;
+
+	before = c->xdatum_mem_usage;
+	target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */
+	for (count = 0; count < XATTRINDEX_HASHSIZE; count++) {
+		list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) {
+			if (xd->flags & JFFS2_XFLAGS_HOT) {
+				xd->flags &= ~JFFS2_XFLAGS_HOT;
+			} else if (!(xd->flags & JFFS2_XFLAGS_BIND)) {
+				unload_xattr_datum(c, xd);
+			}
+			if (c->xdatum_mem_usage <= target)
+				goto out;
+		}
+		index = (index+1) % XATTRINDEX_HASHSIZE;
+	}
+ out:
+	JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n",
+		     before, c->xdatum_mem_usage, before - c->xdatum_mem_usage);
+}
+
+static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	/* must be called under down_write(xattr_sem) */
+	struct jffs2_eraseblock *jeb;
+	struct jffs2_raw_node_ref *raw;
+	struct jffs2_raw_xattr rx;
+	size_t readlen;
+	uint32_t crc, offset, totlen;
+	int rc;
+
+	spin_lock(&c->erase_completion_lock);
+	offset = ref_offset(xd->node);
+	if (ref_flags(xd->node) == REF_PRISTINE)
+		goto complete;
+	spin_unlock(&c->erase_completion_lock);
+
+	rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx);
+	if (rc || readlen != sizeof(rx)) {
+		JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n",
+			      rc, sizeof(rx), readlen, offset);
+		return rc ? rc : -EIO;
+	}
+	crc = crc32(0, &rx, sizeof(rx) - 4);
+	if (crc != je32_to_cpu(rx.node_crc)) {
+		JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+			    offset, je32_to_cpu(rx.hdr_crc), crc);
+		xd->flags |= JFFS2_XFLAGS_INVALID;
+		return EIO;
+	}
+	totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
+	if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
+	    || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR
+	    || je32_to_cpu(rx.totlen) != totlen
+	    || je32_to_cpu(rx.xid) != xd->xid
+	    || je32_to_cpu(rx.version) != xd->version) {
+		JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, "
+			    "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n",
+			    offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK,
+			    je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR,
+			    je32_to_cpu(rx.totlen), totlen,
+			    je32_to_cpu(rx.xid), xd->xid,
+			    je32_to_cpu(rx.version), xd->version);
+		xd->flags |= JFFS2_XFLAGS_INVALID;
+		return EIO;
+	}
+	xd->xprefix = rx.xprefix;
+	xd->name_len = rx.name_len;
+	xd->value_len = je16_to_cpu(rx.value_len);
+	xd->data_crc = je32_to_cpu(rx.data_crc);
+
+	spin_lock(&c->erase_completion_lock);
+ complete:
+	for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
+		jeb = &c->blocks[ref_offset(raw) / c->sector_size];
+		totlen = PAD(ref_totlen(c, jeb, raw));
+		if (ref_flags(raw) == REF_UNCHECKED) {
+			c->unchecked_size -= totlen; c->used_size += totlen;
+			jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+		}
+		raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL);
+	}
+	spin_unlock(&c->erase_completion_lock);
+
+	/* unchecked xdatum is chained with c->xattr_unchecked */
+	list_del_init(&xd->xindex);
+
+	dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n",
+		  xd->xid, xd->version);
+
+	return 0;
+}
+
+static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	/* must be called under down_write(xattr_sem) */
+	char *data;
+	size_t readlen;
+	uint32_t crc, length;
+	int i, ret, retry = 0;
+
+	BUG_ON(ref_flags(xd->node) != REF_PRISTINE);
+	BUG_ON(!list_empty(&xd->xindex));
+ retry:
+	length = xd->name_len + 1 + xd->value_len;
+	data = kmalloc(length, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr),
+			       length, &readlen, data);
+
+	if (ret || length!=readlen) {
+		JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n",
+			      ret, length, readlen, ref_offset(xd->node));
+		kfree(data);
+		return ret ? ret : -EIO;
+	}
+
+	data[xd->name_len] = '\0';
+	crc = crc32(0, data, length);
+	if (crc != xd->data_crc) {
+		JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)"
+			      " at %#08x, read: 0x%08x calculated: 0x%08x\n",
+			      ref_offset(xd->node), xd->data_crc, crc);
+		kfree(data);
+		xd->flags |= JFFS2_XFLAGS_INVALID;
+		return EIO;
+	}
+
+	xd->flags |= JFFS2_XFLAGS_HOT;
+	xd->xname = data;
+	xd->xvalue = data + xd->name_len+1;
+
+	c->xdatum_mem_usage += length;
+
+	xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len);
+	i = xd->hashkey % XATTRINDEX_HASHSIZE;
+	list_add(&xd->xindex, &c->xattrindex[i]);
+	if (!retry) {
+		retry = 1;
+		reclaim_xattr_datum(c);
+		if (!xd->xname)
+			goto retry;
+	}
+
+	dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n",
+		  xd->xid, xd->xprefix, xd->xname);
+
+	return 0;
+}
+
+static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	/* must be called under down_write(xattr_sem);
+	 * rc < 0 : recoverable error, try again
+	 * rc = 0 : success
+	 * rc > 0 : Unrecoverable error, this node should be deleted.
+	 */
+	int rc = 0;
+
+	BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD);
+	if (xd->xname)
+		return 0;
+	if (xd->flags & JFFS2_XFLAGS_INVALID)
+		return EIO;
+	if (unlikely(is_xattr_datum_unchecked(c, xd)))
+		rc = do_verify_xattr_datum(c, xd);
+	if (!rc)
+		rc = do_load_xattr_datum(c, xd);
+	return rc;
+}
+
+static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	/* must be called under down_write(xattr_sem) */
+	struct jffs2_raw_xattr rx;
+	struct kvec vecs[2];
+	size_t length;
+	int rc, totlen;
+	uint32_t phys_ofs = write_ofs(c);
+
+	BUG_ON(!xd->xname);
+	BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID));
+
+	vecs[0].iov_base = &rx;
+	vecs[0].iov_len = sizeof(rx);
+	vecs[1].iov_base = xd->xname;
+	vecs[1].iov_len = xd->name_len + 1 + xd->value_len;
+	totlen = vecs[0].iov_len + vecs[1].iov_len;
+
+	/* Setup raw-xattr */
+	memset(&rx, 0, sizeof(rx));
+	rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+	rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR);
+	rx.totlen = cpu_to_je32(PAD(totlen));
+	rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4));
+
+	rx.xid = cpu_to_je32(xd->xid);
+	rx.version = cpu_to_je32(++xd->version);
+	rx.xprefix = xd->xprefix;
+	rx.name_len = xd->name_len;
+	rx.value_len = cpu_to_je16(xd->value_len);
+	rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len));
+	rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4));
+
+	rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0);
+	if (rc || totlen != length) {
+		JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n",
+			      rc, totlen, length, phys_ofs);
+		rc = rc ? rc : -EIO;
+		if (length)
+			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL);
+
+		return rc;
+	}
+	/* success */
+	jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd);
+
+	dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n",
+		  xd->xid, xd->version, xd->xprefix, xd->xname);
+
+	return 0;
+}
+
+static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c,
+						    int xprefix, const char *xname,
+						    const char *xvalue, int xsize)
+{
+	/* must be called under down_write(xattr_sem) */
+	struct jffs2_xattr_datum *xd;
+	uint32_t hashkey, name_len;
+	char *data;
+	int i, rc;
+
+	/* Search xattr_datum has same xname/xvalue by index */
+	hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize);
+	i = hashkey % XATTRINDEX_HASHSIZE;
+	list_for_each_entry(xd, &c->xattrindex[i], xindex) {
+		if (xd->hashkey==hashkey
+		    && xd->xprefix==xprefix
+		    && xd->value_len==xsize
+		    && !strcmp(xd->xname, xname)
+		    && !memcmp(xd->xvalue, xvalue, xsize)) {
+			atomic_inc(&xd->refcnt);
+			return xd;
+		}
+	}
+
+	/* Not found, Create NEW XATTR-Cache */
+	name_len = strlen(xname);
+
+	xd = jffs2_alloc_xattr_datum();
+	if (!xd)
+		return ERR_PTR(-ENOMEM);
+
+	data = kmalloc(name_len + 1 + xsize, GFP_KERNEL);
+	if (!data) {
+		jffs2_free_xattr_datum(xd);
+		return ERR_PTR(-ENOMEM);
+	}
+	strcpy(data, xname);
+	memcpy(data + name_len + 1, xvalue, xsize);
+
+	atomic_set(&xd->refcnt, 1);
+	xd->xid = ++c->highest_xid;
+	xd->flags |= JFFS2_XFLAGS_HOT;
+	xd->xprefix = xprefix;
+
+	xd->hashkey = hashkey;
+	xd->xname = data;
+	xd->xvalue = data + name_len + 1;
+	xd->name_len = name_len;
+	xd->value_len = xsize;
+	xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len);
+
+	rc = save_xattr_datum(c, xd);
+	if (rc) {
+		kfree(xd->xname);
+		jffs2_free_xattr_datum(xd);
+		return ERR_PTR(rc);
+	}
+
+	/* Insert Hash Index */
+	i = hashkey % XATTRINDEX_HASHSIZE;
+	list_add(&xd->xindex, &c->xattrindex[i]);
+
+	c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len);
+	reclaim_xattr_datum(c);
+
+	return xd;
+}
+
+static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	/* must be called under down_write(xattr_sem) */
+	BUG_ON(atomic_read(&xd->refcnt));
+
+	unload_xattr_datum(c, xd);
+	xd->flags |= JFFS2_XFLAGS_DEAD;
+	spin_lock(&c->erase_completion_lock);
+	if (xd->node == (void *)xd) {
+		BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID));
+		jffs2_free_xattr_datum(xd);
+	} else {
+		list_add(&xd->xindex, &c->xattr_dead_list);
+	}
+	spin_unlock(&c->erase_completion_lock);
+	dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xd->xid, xd->version);
+}
+
+/* -------- xref related functions ------------------
+ * verify_xattr_ref(c, ref)
+ *   is used to load xref information from medium. Because summary data does not
+ *   contain xid/ino, it's necessary to verify once while mounting process.
+ * save_xattr_ref(c, ref)
+ *   is used to write xref to medium. If delete marker is marked, it write
+ *   a delete marker of xref into medium.
+ * create_xattr_ref(c, ic, xd)
+ *   is used to create a new xref and write to medium.
+ * delete_xattr_ref(c, ref)
+ *   is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER,
+ *   and allows GC to reclaim those physical nodes.
+ * jffs2_xattr_delete_inode(c, ic)
+ *   is called to remove xrefs related to obsolete inode when inode is unlinked.
+ * jffs2_xattr_free_inode(c, ic)
+ *   is called to release xattr related objects when unmounting. 
+ * check_xattr_ref_inode(c, ic)
+ *   is used to confirm inode does not have duplicate xattr name/value pair.
+ * -------------------------------------------------- */
+static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+	struct jffs2_eraseblock *jeb;
+	struct jffs2_raw_node_ref *raw;
+	struct jffs2_raw_xref rr;
+	size_t readlen;
+	uint32_t crc, offset, totlen;
+	int rc;
+
+	spin_lock(&c->erase_completion_lock);
+	if (ref_flags(ref->node) != REF_UNCHECKED)
+		goto complete;
+	offset = ref_offset(ref->node);
+	spin_unlock(&c->erase_completion_lock);
+
+	rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr);
+	if (rc || sizeof(rr) != readlen) {
+		JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n",
+			      rc, sizeof(rr), readlen, offset);
+		return rc ? rc : -EIO;
+	}
+	/* obsolete node */
+	crc = crc32(0, &rr, sizeof(rr) - 4);
+	if (crc != je32_to_cpu(rr.node_crc)) {
+		JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
+			    offset, je32_to_cpu(rr.node_crc), crc);
+		return EIO;
+	}
+	if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
+	    || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
+	    || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) {
+		JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, "
+			    "nodetype=%#04x/%#04x, totlen=%u/%zu\n",
+			    offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
+			    je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
+			    je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
+		return EIO;
+	}
+	ref->ino = je32_to_cpu(rr.ino);
+	ref->xid = je32_to_cpu(rr.xid);
+	ref->xseqno = je32_to_cpu(rr.xseqno);
+	if (ref->xseqno > c->highest_xseqno)
+		c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER);
+
+	spin_lock(&c->erase_completion_lock);
+ complete:
+	for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) {
+		jeb = &c->blocks[ref_offset(raw) / c->sector_size];
+		totlen = PAD(ref_totlen(c, jeb, raw));
+		if (ref_flags(raw) == REF_UNCHECKED) {
+			c->unchecked_size -= totlen; c->used_size += totlen;
+			jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+		}
+		raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL);
+	}
+	spin_unlock(&c->erase_completion_lock);
+
+	dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n",
+		  ref->ino, ref->xid, ref_offset(ref->node));
+	return 0;
+}
+
+static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+	/* must be called under down_write(xattr_sem) */
+	struct jffs2_raw_xref rr;
+	size_t length;
+	uint32_t xseqno, phys_ofs = write_ofs(c);
+	int ret;
+
+	rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+	rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF);
+	rr.totlen = cpu_to_je32(PAD(sizeof(rr)));
+	rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4));
+
+	xseqno = (c->highest_xseqno += 2);
+	if (is_xattr_ref_dead(ref)) {
+		xseqno |= XREF_DELETE_MARKER;
+		rr.ino = cpu_to_je32(ref->ino);
+		rr.xid = cpu_to_je32(ref->xid);
+	} else {
+		rr.ino = cpu_to_je32(ref->ic->ino);
+		rr.xid = cpu_to_je32(ref->xd->xid);
+	}
+	rr.xseqno = cpu_to_je32(xseqno);
+	rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4));
+
+	ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr);
+	if (ret || sizeof(rr) != length) {
+		JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n",
+			      ret, sizeof(rr), length, phys_ofs);
+		ret = ret ? ret : -EIO;
+		if (length)
+			jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL);
+
+		return ret;
+	}
+	/* success */
+	ref->xseqno = xseqno;
+	jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref);
+
+	dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid);
+
+	return 0;
+}
+
+static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic,
+						struct jffs2_xattr_datum *xd)
+{
+	/* must be called under down_write(xattr_sem) */
+	struct jffs2_xattr_ref *ref;
+	int ret;
+
+	ref = jffs2_alloc_xattr_ref();
+	if (!ref)
+		return ERR_PTR(-ENOMEM);
+	ref->ic = ic;
+	ref->xd = xd;
+
+	ret = save_xattr_ref(c, ref);
+	if (ret) {
+		jffs2_free_xattr_ref(ref);
+		return ERR_PTR(ret);
+	}
+
+	/* Chain to inode */
+	ref->next = ic->xref;
+	ic->xref = ref;
+
+	return ref; /* success */
+}
+
+static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+	/* must be called under down_write(xattr_sem) */
+	struct jffs2_xattr_datum *xd;
+
+	xd = ref->xd;
+	ref->xseqno |= XREF_DELETE_MARKER;
+	ref->ino = ref->ic->ino;
+	ref->xid = ref->xd->xid;
+	spin_lock(&c->erase_completion_lock);
+	ref->next = c->xref_dead_list;
+	c->xref_dead_list = ref;
+	spin_unlock(&c->erase_completion_lock);
+
+	dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n",
+		  ref->ino, ref->xid, ref->xseqno);
+
+	if (atomic_dec_and_test(&xd->refcnt))
+		delete_xattr_datum(c, xd);
+}
+
+void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+	/* It's called from jffs2_clear_inode() on inode removing.
+	   When an inode with XATTR is removed, those XATTRs must be removed. */
+	struct jffs2_xattr_ref *ref, *_ref;
+
+	if (!ic || ic->nlink > 0)
+		return;
+
+	down_write(&c->xattr_sem);
+	for (ref = ic->xref; ref; ref = _ref) {
+		_ref = ref->next;
+		delete_xattr_ref(c, ref);
+	}
+	ic->xref = NULL;
+	up_write(&c->xattr_sem);
+}
+
+void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+	/* It's called from jffs2_free_ino_caches() until unmounting FS. */
+	struct jffs2_xattr_datum *xd;
+	struct jffs2_xattr_ref *ref, *_ref;
+
+	down_write(&c->xattr_sem);
+	for (ref = ic->xref; ref; ref = _ref) {
+		_ref = ref->next;
+		xd = ref->xd;
+		if (atomic_dec_and_test(&xd->refcnt)) {
+			unload_xattr_datum(c, xd);
+			jffs2_free_xattr_datum(xd);
+		}
+		jffs2_free_xattr_ref(ref);
+	}
+	ic->xref = NULL;
+	up_write(&c->xattr_sem);
+}
+
+static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
+{
+	/* success of check_xattr_ref_inode() means taht inode (ic) dose not have
+	 * duplicate name/value pairs. If duplicate name/value pair would be found,
+	 * one will be removed.
+	 */
+	struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp;
+	int rc = 0;
+
+	if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED))
+		return 0;
+	down_write(&c->xattr_sem);
+ retry:
+	rc = 0;
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+		if (!ref->xd->xname) {
+			rc = load_xattr_datum(c, ref->xd);
+			if (unlikely(rc > 0)) {
+				*pref = ref->next;
+				delete_xattr_ref(c, ref);
+				goto retry;
+			} else if (unlikely(rc < 0))
+				goto out;
+		}
+		for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) {
+			if (!cmp->xd->xname) {
+				ref->xd->flags |= JFFS2_XFLAGS_BIND;
+				rc = load_xattr_datum(c, cmp->xd);
+				ref->xd->flags &= ~JFFS2_XFLAGS_BIND;
+				if (unlikely(rc > 0)) {
+					*pcmp = cmp->next;
+					delete_xattr_ref(c, cmp);
+					goto retry;
+				} else if (unlikely(rc < 0))
+					goto out;
+			}
+			if (ref->xd->xprefix == cmp->xd->xprefix
+			    && !strcmp(ref->xd->xname, cmp->xd->xname)) {
+				if (ref->xseqno > cmp->xseqno) {
+					*pcmp = cmp->next;
+					delete_xattr_ref(c, cmp);
+				} else {
+					*pref = ref->next;
+					delete_xattr_ref(c, ref);
+				}
+				goto retry;
+			}
+		}
+	}
+	ic->flags |= INO_FLAGS_XATTR_CHECKED;
+ out:
+	up_write(&c->xattr_sem);
+
+	return rc;
+}
+
+/* -------- xattr subsystem functions ---------------
+ * jffs2_init_xattr_subsystem(c)
+ *   is used to initialize semaphore and list_head, and some variables.
+ * jffs2_find_xattr_datum(c, xid)
+ *   is used to lookup xdatum while scanning process.
+ * jffs2_clear_xattr_subsystem(c)
+ *   is used to release any xattr related objects.
+ * jffs2_build_xattr_subsystem(c)
+ *   is used to associate xdatum and xref while super block building process.
+ * jffs2_setup_xattr_datum(c, xid, version)
+ *   is used to insert xdatum while scanning process.
+ * -------------------------------------------------- */
+void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c)
+{
+	int i;
+
+	for (i=0; i < XATTRINDEX_HASHSIZE; i++)
+		INIT_LIST_HEAD(&c->xattrindex[i]);
+	INIT_LIST_HEAD(&c->xattr_unchecked);
+	INIT_LIST_HEAD(&c->xattr_dead_list);
+	c->xref_dead_list = NULL;
+	c->xref_temp = NULL;
+
+	init_rwsem(&c->xattr_sem);
+	c->highest_xid = 0;
+	c->highest_xseqno = 0;
+	c->xdatum_mem_usage = 0;
+	c->xdatum_mem_threshold = 32 * 1024;	/* Default 32KB */
+}
+
+static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid)
+{
+	struct jffs2_xattr_datum *xd;
+	int i = xid % XATTRINDEX_HASHSIZE;
+
+	/* It's only used in scanning/building process. */
+	BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING)));
+
+	list_for_each_entry(xd, &c->xattrindex[i], xindex) {
+		if (xd->xid==xid)
+			return xd;
+	}
+	return NULL;
+}
+
+void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c)
+{
+	struct jffs2_xattr_datum *xd, *_xd;
+	struct jffs2_xattr_ref *ref, *_ref;
+	int i;
+
+	for (ref=c->xref_temp; ref; ref = _ref) {
+		_ref = ref->next;
+		jffs2_free_xattr_ref(ref);
+	}
+
+	for (ref=c->xref_dead_list; ref; ref = _ref) {
+		_ref = ref->next;
+		jffs2_free_xattr_ref(ref);
+	}
+
+	for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
+		list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
+			list_del(&xd->xindex);
+			if (xd->xname)
+				kfree(xd->xname);
+			jffs2_free_xattr_datum(xd);
+		}
+	}
+
+	list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) {
+		list_del(&xd->xindex);
+		jffs2_free_xattr_datum(xd);
+	}
+}
+
+#define XREF_TMPHASH_SIZE	(128)
+void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c)
+{
+	struct jffs2_xattr_ref *ref, *_ref;
+	struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE];
+	struct jffs2_xattr_datum *xd, *_xd;
+	struct jffs2_inode_cache *ic;
+	struct jffs2_raw_node_ref *raw;
+	int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0;
+	int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0;
+
+	BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING));
+
+	/* Phase.1 : Merge same xref */
+	for (i=0; i < XREF_TMPHASH_SIZE; i++)
+		xref_tmphash[i] = NULL;
+	for (ref=c->xref_temp; ref; ref=_ref) {
+		struct jffs2_xattr_ref *tmp;
+
+		_ref = ref->next;
+		if (ref_flags(ref->node) != REF_PRISTINE) {
+			if (verify_xattr_ref(c, ref)) {
+				BUG_ON(ref->node->next_in_ino != (void *)ref);
+				ref->node->next_in_ino = NULL;
+				jffs2_mark_node_obsolete(c, ref->node);
+				jffs2_free_xattr_ref(ref);
+				continue;
+			}
+		}
+
+		i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE;
+		for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) {
+			if (tmp->ino == ref->ino && tmp->xid == ref->xid)
+				break;
+		}
+		if (tmp) {
+			raw = ref->node;
+			if (ref->xseqno > tmp->xseqno) {
+				tmp->xseqno = ref->xseqno;
+				raw->next_in_ino = tmp->node;
+				tmp->node = raw;
+			} else {
+				raw->next_in_ino = tmp->node->next_in_ino;
+				tmp->node->next_in_ino = raw;
+			}
+			jffs2_free_xattr_ref(ref);
+			continue;
+		} else {
+			ref->next = xref_tmphash[i];
+			xref_tmphash[i] = ref;
+		}
+	}
+	c->xref_temp = NULL;
+
+	/* Phase.2 : Bind xref with inode_cache and xattr_datum */
+	for (i=0; i < XREF_TMPHASH_SIZE; i++) {
+		for (ref=xref_tmphash[i]; ref; ref=_ref) {
+			xref_count++;
+			_ref = ref->next;
+			if (is_xattr_ref_dead(ref)) {
+				ref->next = c->xref_dead_list;
+				c->xref_dead_list = ref;
+				xref_dead_count++;
+				continue;
+			}
+			/* At this point, ref->xid and ref->ino contain XID and inode number.
+			   ref->xd and ref->ic are not valid yet. */
+			xd = jffs2_find_xattr_datum(c, ref->xid);
+			ic = jffs2_get_ino_cache(c, ref->ino);
+			if (!xd || !ic) {
+				dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n",
+					  ref->ino, ref->xid, ref->xseqno);
+				ref->xseqno |= XREF_DELETE_MARKER;
+				ref->next = c->xref_dead_list;
+				c->xref_dead_list = ref;
+				xref_orphan_count++;
+				continue;
+			}
+			ref->xd = xd;
+			ref->ic = ic;
+			atomic_inc(&xd->refcnt);
+			ref->next = ic->xref;
+			ic->xref = ref;
+		}
+	}
+
+	/* Phase.3 : Link unchecked xdatum to xattr_unchecked list */
+	for (i=0; i < XATTRINDEX_HASHSIZE; i++) {
+		list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) {
+			xdatum_count++;
+			list_del_init(&xd->xindex);
+			if (!atomic_read(&xd->refcnt)) {
+				dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n",
+					  xd->xid, xd->version);
+				xd->flags |= JFFS2_XFLAGS_DEAD;
+				list_add(&xd->xindex, &c->xattr_unchecked);
+				xdatum_orphan_count++;
+				continue;
+			}
+			if (is_xattr_datum_unchecked(c, xd)) {
+				dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n",
+					  xd->xid, xd->version);
+				list_add(&xd->xindex, &c->xattr_unchecked);
+				xdatum_unchecked_count++;
+			}
+		}
+	}
+	/* build complete */
+	JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum"
+		     " (%u unchecked, %u orphan) and "
+		     "%u of xref (%u dead, %u orphan) found.\n",
+		     xdatum_count, xdatum_unchecked_count, xdatum_orphan_count,
+		     xref_count, xref_dead_count, xref_orphan_count);
+}
+
+struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+						  uint32_t xid, uint32_t version)
+{
+	struct jffs2_xattr_datum *xd;
+
+	xd = jffs2_find_xattr_datum(c, xid);
+	if (!xd) {
+		xd = jffs2_alloc_xattr_datum();
+		if (!xd)
+			return ERR_PTR(-ENOMEM);
+		xd->xid = xid;
+		xd->version = version;
+		if (xd->xid > c->highest_xid)
+			c->highest_xid = xd->xid;
+		list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]);
+	}
+	return xd;
+}
+
+/* -------- xattr subsystem functions ---------------
+ * xprefix_to_handler(xprefix)
+ *   is used to translate xprefix into xattr_handler.
+ * jffs2_listxattr(dentry, buffer, size)
+ *   is an implementation of listxattr handler on jffs2.
+ * do_jffs2_getxattr(inode, xprefix, xname, buffer, size)
+ *   is an implementation of getxattr handler on jffs2.
+ * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags)
+ *   is an implementation of setxattr handler on jffs2.
+ * -------------------------------------------------- */
+struct xattr_handler *jffs2_xattr_handlers[] = {
+	&jffs2_user_xattr_handler,
+#ifdef CONFIG_JFFS2_FS_SECURITY
+	&jffs2_security_xattr_handler,
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+	&jffs2_acl_access_xattr_handler,
+	&jffs2_acl_default_xattr_handler,
+#endif
+	&jffs2_trusted_xattr_handler,
+	NULL
+};
+
+static struct xattr_handler *xprefix_to_handler(int xprefix) {
+	struct xattr_handler *ret;
+
+	switch (xprefix) {
+	case JFFS2_XPREFIX_USER:
+		ret = &jffs2_user_xattr_handler;
+		break;
+#ifdef CONFIG_JFFS2_FS_SECURITY
+	case JFFS2_XPREFIX_SECURITY:
+		ret = &jffs2_security_xattr_handler;
+		break;
+#endif
+#ifdef CONFIG_JFFS2_FS_POSIX_ACL
+	case JFFS2_XPREFIX_ACL_ACCESS:
+		ret = &jffs2_acl_access_xattr_handler;
+		break;
+	case JFFS2_XPREFIX_ACL_DEFAULT:
+		ret = &jffs2_acl_default_xattr_handler;
+		break;
+#endif
+	case JFFS2_XPREFIX_TRUSTED:
+		ret = &jffs2_trusted_xattr_handler;
+		break;
+	default:
+		ret = NULL;
+		break;
+	}
+	return ret;
+}
+
+ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+	struct jffs2_inode_cache *ic = f->inocache;
+	struct jffs2_xattr_ref *ref, **pref;
+	struct jffs2_xattr_datum *xd;
+	struct xattr_handler *xhandle;
+	ssize_t len, rc;
+	int retry = 0;
+
+	rc = check_xattr_ref_inode(c, ic);
+	if (unlikely(rc))
+		return rc;
+
+	down_read(&c->xattr_sem);
+ retry:
+	len = 0;
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+		BUG_ON(ref->ic != ic);
+		xd = ref->xd;
+		if (!xd->xname) {
+			/* xdatum is unchached */
+			if (!retry) {
+				retry = 1;
+				up_read(&c->xattr_sem);
+				down_write(&c->xattr_sem);
+				goto retry;
+			} else {
+				rc = load_xattr_datum(c, xd);
+				if (unlikely(rc > 0)) {
+					*pref = ref->next;
+					delete_xattr_ref(c, ref);
+					goto retry;
+				} else if (unlikely(rc < 0))
+					goto out;
+			}
+		}
+		xhandle = xprefix_to_handler(xd->xprefix);
+		if (!xhandle)
+			continue;
+		if (buffer) {
+			rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len);
+		} else {
+			rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len);
+		}
+		if (rc < 0)
+			goto out;
+		len += rc;
+	}
+	rc = len;
+ out:
+	if (!retry) {
+		up_read(&c->xattr_sem);
+	} else {
+		up_write(&c->xattr_sem);
+	}
+	return rc;
+}
+
+int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
+		      char *buffer, size_t size)
+{
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+	struct jffs2_inode_cache *ic = f->inocache;
+	struct jffs2_xattr_datum *xd;
+	struct jffs2_xattr_ref *ref, **pref;
+	int rc, retry = 0;
+
+	rc = check_xattr_ref_inode(c, ic);
+	if (unlikely(rc))
+		return rc;
+
+	down_read(&c->xattr_sem);
+ retry:
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+		BUG_ON(ref->ic!=ic);
+
+		xd = ref->xd;
+		if (xd->xprefix != xprefix)
+			continue;
+		if (!xd->xname) {
+			/* xdatum is unchached */
+			if (!retry) {
+				retry = 1;
+				up_read(&c->xattr_sem);
+				down_write(&c->xattr_sem);
+				goto retry;
+			} else {
+				rc = load_xattr_datum(c, xd);
+				if (unlikely(rc > 0)) {
+					*pref = ref->next;
+					delete_xattr_ref(c, ref);
+					goto retry;
+				} else if (unlikely(rc < 0)) {
+					goto out;
+				}
+			}
+		}
+		if (!strcmp(xname, xd->xname)) {
+			rc = xd->value_len;
+			if (buffer) {
+				if (size < rc) {
+					rc = -ERANGE;
+				} else {
+					memcpy(buffer, xd->xvalue, rc);
+				}
+			}
+			goto out;
+		}
+	}
+	rc = -ENODATA;
+ out:
+	if (!retry) {
+		up_read(&c->xattr_sem);
+	} else {
+		up_write(&c->xattr_sem);
+	}
+	return rc;
+}
+
+int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
+		      const char *buffer, size_t size, int flags)
+{
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+	struct jffs2_inode_cache *ic = f->inocache;
+	struct jffs2_xattr_datum *xd;
+	struct jffs2_xattr_ref *ref, *newref, **pref;
+	uint32_t length, request;
+	int rc;
+
+	rc = check_xattr_ref_inode(c, ic);
+	if (unlikely(rc))
+		return rc;
+
+	request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
+	rc = jffs2_reserve_space(c, request, &length,
+				 ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
+	if (rc) {
+		JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
+		return rc;
+	}
+
+	/* Find existing xattr */
+	down_write(&c->xattr_sem);
+ retry:
+	for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) {
+		xd = ref->xd;
+		if (xd->xprefix != xprefix)
+			continue;
+		if (!xd->xname) {
+			rc = load_xattr_datum(c, xd);
+			if (unlikely(rc > 0)) {
+				*pref = ref->next;
+				delete_xattr_ref(c, ref);
+				goto retry;
+			} else if (unlikely(rc < 0))
+				goto out;
+		}
+		if (!strcmp(xd->xname, xname)) {
+			if (flags & XATTR_CREATE) {
+				rc = -EEXIST;
+				goto out;
+			}
+			if (!buffer) {
+				ref->ino = ic->ino;
+				ref->xid = xd->xid;
+				ref->xseqno |= XREF_DELETE_MARKER;
+				rc = save_xattr_ref(c, ref);
+				if (!rc) {
+					*pref = ref->next;
+					spin_lock(&c->erase_completion_lock);
+					ref->next = c->xref_dead_list;
+					c->xref_dead_list = ref;
+					spin_unlock(&c->erase_completion_lock);
+					if (atomic_dec_and_test(&xd->refcnt))
+						delete_xattr_datum(c, xd);
+				} else {
+					ref->ic = ic;
+					ref->xd = xd;
+					ref->xseqno &= ~XREF_DELETE_MARKER;
+				}
+				goto out;
+			}
+			goto found;
+		}
+	}
+	/* not found */
+	if (flags & XATTR_REPLACE) {
+		rc = -ENODATA;
+		goto out;
+	}
+	if (!buffer) {
+		rc = -ENODATA;
+		goto out;
+	}
+ found:
+	xd = create_xattr_datum(c, xprefix, xname, buffer, size);
+	if (IS_ERR(xd)) {
+		rc = PTR_ERR(xd);
+		goto out;
+	}
+	up_write(&c->xattr_sem);
+	jffs2_complete_reservation(c);
+
+	/* create xattr_ref */
+	request = PAD(sizeof(struct jffs2_raw_xref));
+	rc = jffs2_reserve_space(c, request, &length,
+				 ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE);
+	down_write(&c->xattr_sem);
+	if (rc) {
+		JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request);
+		if (atomic_dec_and_test(&xd->refcnt))
+			delete_xattr_datum(c, xd);
+		up_write(&c->xattr_sem);
+		return rc;
+	}
+	if (ref)
+		*pref = ref->next;
+	newref = create_xattr_ref(c, ic, xd);
+	if (IS_ERR(newref)) {
+		if (ref) {
+			ref->next = ic->xref;
+			ic->xref = ref;
+		}
+		rc = PTR_ERR(newref);
+		if (atomic_dec_and_test(&xd->refcnt))
+			delete_xattr_datum(c, xd);
+	} else if (ref) {
+		delete_xattr_ref(c, ref);
+	}
+ out:
+	up_write(&c->xattr_sem);
+	jffs2_complete_reservation(c);
+	return rc;
+}
+
+/* -------- garbage collector functions -------------
+ * jffs2_garbage_collect_xattr_datum(c, xd, raw)
+ *   is used to move xdatum into new node.
+ * jffs2_garbage_collect_xattr_ref(c, ref, raw)
+ *   is used to move xref into new node.
+ * jffs2_verify_xattr(c)
+ *   is used to call do_verify_xattr_datum() before garbage collecting.
+ * jffs2_release_xattr_datum(c, xd)
+ *   is used to release an in-memory object of xdatum.
+ * jffs2_release_xattr_ref(c, ref)
+ *   is used to release an in-memory object of xref.
+ * -------------------------------------------------- */
+int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
+				      struct jffs2_raw_node_ref *raw)
+{
+	uint32_t totlen, length, old_ofs;
+	int rc = 0;
+
+	down_write(&c->xattr_sem);
+	if (xd->node != raw)
+		goto out;
+	if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID))
+		goto out;
+
+	rc = load_xattr_datum(c, xd);
+	if (unlikely(rc)) {
+		rc = (rc > 0) ? 0 : rc;
+		goto out;
+	}
+	old_ofs = ref_offset(xd->node);
+	totlen = PAD(sizeof(struct jffs2_raw_xattr)
+			+ xd->name_len + 1 + xd->value_len);
+	rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE);
+	if (rc) {
+		JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen);
+		rc = rc ? rc : -EBADFD;
+		goto out;
+	}
+	rc = save_xattr_datum(c, xd);
+	if (!rc)
+		dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n",
+			  xd->xid, xd->version, old_ofs, ref_offset(xd->node));
+ out:
+	if (!rc)
+		jffs2_mark_node_obsolete(c, raw);
+	up_write(&c->xattr_sem);
+	return rc;
+}
+
+int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
+				    struct jffs2_raw_node_ref *raw)
+{
+	uint32_t totlen, length, old_ofs;
+	int rc = 0;
+
+	down_write(&c->xattr_sem);
+	BUG_ON(!ref->node);
+
+	if (ref->node != raw)
+		goto out;
+	if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref))
+		goto out;
+
+	old_ofs = ref_offset(ref->node);
+	totlen = ref_totlen(c, c->gcblock, ref->node);
+
+	rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE);
+	if (rc) {
+		JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n",
+			      __FUNCTION__, rc, totlen);
+		rc = rc ? rc : -EBADFD;
+		goto out;
+	}
+	rc = save_xattr_ref(c, ref);
+	if (!rc)
+		dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n",
+			  ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node));
+ out:
+	if (!rc)
+		jffs2_mark_node_obsolete(c, raw);
+	up_write(&c->xattr_sem);
+	return rc;
+}
+
+int jffs2_verify_xattr(struct jffs2_sb_info *c)
+{
+	struct jffs2_xattr_datum *xd, *_xd;
+	struct jffs2_eraseblock *jeb;
+	struct jffs2_raw_node_ref *raw;
+	uint32_t totlen;
+	int rc;
+
+	down_write(&c->xattr_sem);
+	list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) {
+		rc = do_verify_xattr_datum(c, xd);
+		if (rc < 0)
+			continue;
+		list_del_init(&xd->xindex);
+		spin_lock(&c->erase_completion_lock);
+		for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) {
+			if (ref_flags(raw) != REF_UNCHECKED)
+				continue;
+			jeb = &c->blocks[ref_offset(raw) / c->sector_size];
+			totlen = PAD(ref_totlen(c, jeb, raw));
+			c->unchecked_size -= totlen; c->used_size += totlen;
+			jeb->unchecked_size -= totlen; jeb->used_size += totlen;
+			raw->flash_offset = ref_offset(raw)
+				| ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL);
+		}
+		if (xd->flags & JFFS2_XFLAGS_DEAD)
+			list_add(&xd->xindex, &c->xattr_dead_list);
+		spin_unlock(&c->erase_completion_lock);
+	}
+	up_write(&c->xattr_sem);
+	return list_empty(&c->xattr_unchecked) ? 1 : 0;
+}
+
+void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd)
+{
+	/* must be called under spin_lock(&c->erase_completion_lock) */
+	if (atomic_read(&xd->refcnt) || xd->node != (void *)xd)
+		return;
+
+	list_del(&xd->xindex);
+	jffs2_free_xattr_datum(xd);
+}
+
+void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref)
+{
+	/* must be called under spin_lock(&c->erase_completion_lock) */
+	struct jffs2_xattr_ref *tmp, **ptmp;
+
+	if (ref->node != (void *)ref)
+		return;
+
+	for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) {
+		if (ref == tmp) {
+			*ptmp = tmp->next;
+			break;
+		}
+	}
+	jffs2_free_xattr_ref(ref);
+}
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h
new file mode 100644
index 0000000..06a5c69
--- /dev/null
+++ b/fs/jffs2/xattr.h
@@ -0,0 +1,129 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#ifndef _JFFS2_FS_XATTR_H_
+#define _JFFS2_FS_XATTR_H_
+
+#include <linux/xattr.h>
+#include <linux/list.h>
+
+#define JFFS2_XFLAGS_HOT	(0x01)	/* This datum is HOT */
+#define JFFS2_XFLAGS_BIND	(0x02)	/* This datum is not reclaimed */
+#define JFFS2_XFLAGS_DEAD	(0x40)	/* This datum is already dead */
+#define JFFS2_XFLAGS_INVALID	(0x80)	/* This datum contains crc error */
+
+struct jffs2_xattr_datum
+{
+	void *always_null;
+	struct jffs2_raw_node_ref *node;
+	uint8_t class;
+	uint8_t flags;
+	uint16_t xprefix;		/* see JFFS2_XATTR_PREFIX_* */
+
+	struct list_head xindex;	/* chained from c->xattrindex[n] */
+	atomic_t refcnt;		/* # of xattr_ref refers this */
+	uint32_t xid;
+	uint32_t version;
+
+	uint32_t data_crc;
+	uint32_t hashkey;
+	char *xname;		/* XATTR name without prefix */
+	uint32_t name_len;	/* length of xname */
+	char *xvalue;		/* XATTR value */
+	uint32_t value_len;	/* length of xvalue */
+};
+
+struct jffs2_inode_cache;
+struct jffs2_xattr_ref
+{
+	void *always_null;
+	struct jffs2_raw_node_ref *node;
+	uint8_t class;
+	uint8_t flags;		/* Currently unused */
+	u16 unused;
+
+	uint32_t xseqno;
+	union {
+		struct jffs2_inode_cache *ic;	/* reference to jffs2_inode_cache */
+		uint32_t ino;			/* only used in scanning/building  */
+	};
+	union {
+		struct jffs2_xattr_datum *xd;	/* reference to jffs2_xattr_datum */
+		uint32_t xid;			/* only used in sccanning/building */
+	};
+	struct jffs2_xattr_ref *next;		/* chained from ic->xref_list */
+};
+
+#define XREF_DELETE_MARKER	(0x00000001)
+static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref)
+{
+	return ((ref->xseqno & XREF_DELETE_MARKER) != 0);
+}
+
+#ifdef CONFIG_JFFS2_FS_XATTR
+
+extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c);
+extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c);
+extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c);
+
+extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c,
+                                                  uint32_t xid, uint32_t version);
+
+extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
+extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic);
+
+extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd,
+					     struct jffs2_raw_node_ref *raw);
+extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref,
+					   struct jffs2_raw_node_ref *raw);
+extern int jffs2_verify_xattr(struct jffs2_sb_info *c);
+extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd);
+extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref);
+
+extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname,
+			     char *buffer, size_t size);
+extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
+			     const char *buffer, size_t size, int flags);
+
+extern struct xattr_handler *jffs2_xattr_handlers[];
+extern struct xattr_handler jffs2_user_xattr_handler;
+extern struct xattr_handler jffs2_trusted_xattr_handler;
+
+extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t);
+#define jffs2_getxattr		generic_getxattr
+#define jffs2_setxattr		generic_setxattr
+#define jffs2_removexattr	generic_removexattr
+
+#else
+
+#define jffs2_init_xattr_subsystem(c)
+#define jffs2_build_xattr_subsystem(c)
+#define jffs2_clear_xattr_subsystem(c)
+
+#define jffs2_xattr_delete_inode(c, ic)
+#define jffs2_xattr_free_inode(c, ic)
+#define jffs2_verify_xattr(c)			(1)
+
+#define jffs2_xattr_handlers	NULL
+#define jffs2_listxattr		NULL
+#define jffs2_getxattr		NULL
+#define jffs2_setxattr		NULL
+#define jffs2_removexattr	NULL
+
+#endif /* CONFIG_JFFS2_FS_XATTR */
+
+#ifdef CONFIG_JFFS2_FS_SECURITY
+extern int jffs2_init_security(struct inode *inode, struct inode *dir);
+extern struct xattr_handler jffs2_security_xattr_handler;
+#else
+#define jffs2_init_security(inode,dir)	(0)
+#endif /* CONFIG_JFFS2_FS_SECURITY */
+
+#endif /* _JFFS2_FS_XATTR_H_ */
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
new file mode 100644
index 0000000..ed046e1
--- /dev/null
+++ b/fs/jffs2/xattr_trusted.c
@@ -0,0 +1,52 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static int jffs2_trusted_getxattr(struct inode *inode, const char *name,
+				  void *buffer, size_t size)
+{
+	if (!strcmp(name, ""))
+		return -EINVAL;
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size);
+}
+
+static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer,
+				  size_t size, int flags)
+{
+	if (!strcmp(name, ""))
+		return -EINVAL;
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags);
+}
+
+static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size,
+				      const char *name, size_t name_len)
+{
+	size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1;
+
+	if (list && retlen<=list_size) {
+		strcpy(list, XATTR_TRUSTED_PREFIX);
+		strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name);
+	}
+
+	return retlen;
+}
+
+struct xattr_handler jffs2_trusted_xattr_handler = {
+	.prefix = XATTR_TRUSTED_PREFIX,
+	.list = jffs2_trusted_listxattr,
+	.set = jffs2_trusted_setxattr,
+	.get = jffs2_trusted_getxattr
+};
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
new file mode 100644
index 0000000..2f8e9aa
--- /dev/null
+++ b/fs/jffs2/xattr_user.c
@@ -0,0 +1,52 @@
+/*
+ * JFFS2 -- Journalling Flash File System, Version 2.
+ *
+ * Copyright (C) 2006  NEC Corporation
+ *
+ * Created by KaiGai Kohei <kaigai@ak.jp.nec.com>
+ *
+ * For licensing information, see the file 'LICENCE' in this directory.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/jffs2.h>
+#include <linux/xattr.h>
+#include <linux/mtd/mtd.h>
+#include "nodelist.h"
+
+static int jffs2_user_getxattr(struct inode *inode, const char *name,
+                               void *buffer, size_t size)
+{
+	if (!strcmp(name, ""))
+		return -EINVAL;
+	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size);
+}
+
+static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer,
+                               size_t size, int flags)
+{
+	if (!strcmp(name, ""))
+		return -EINVAL;
+	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags);
+}
+
+static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size,
+				   const char *name, size_t name_len)
+{
+	size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1;
+
+	if (list && retlen <= list_size) {
+		strcpy(list, XATTR_USER_PREFIX);
+		strcpy(list + XATTR_USER_PREFIX_LEN, name);
+	}
+
+	return retlen;
+}
+
+struct xattr_handler jffs2_user_xattr_handler = {
+	.prefix = XATTR_USER_PREFIX,
+	.list = jffs2_user_listxattr,
+	.set = jffs2_user_setxattr,
+	.get = jffs2_user_getxattr
+};
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 04eb78f..43e3f56 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -305,7 +305,7 @@
 				offset, nr_segs, jfs_get_block, NULL);
 }
 
-struct address_space_operations jfs_aops = {
+const struct address_space_operations jfs_aops = {
 	.readpage	= jfs_readpage,
 	.readpages	= jfs_readpages,
 	.writepage	= jfs_writepage,
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 5549378..4d52593 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -126,7 +126,7 @@
 
 	/* allocate the disk blocks for the extent.  initially, extBalloc()
 	 * will try to allocate disk blocks for the requested size (xlen). 
-	 * if this fails (xlen contigious free blocks not avaliable), it'll
+	 * if this fails (xlen contiguous free blocks not avaliable), it'll
 	 * try to allocate a smaller number of blocks (producing a smaller
 	 * extent), with this smaller number of blocks consisting of the
 	 * requested number of blocks rounded down to the next smaller
@@ -493,7 +493,7 @@
  *
  *		initially, we will try to allocate disk blocks for the
  *		requested size (nblocks).  if this fails (nblocks 
- *		contigious free blocks not avaliable), we'll try to allocate
+ *		contiguous free blocks not avaliable), we'll try to allocate
  *		a smaller number of blocks (producing a smaller extent), with
  *		this smaller number of blocks consisting of the requested
  *		number of blocks rounded down to the next smaller power of 2
@@ -529,7 +529,7 @@
 
 	/* get the number of blocks to initially attempt to allocate.
 	 * we'll first try the number of blocks requested unless this
-	 * number is greater than the maximum number of contigious free
+	 * number is greater than the maximum number of contiguous free
 	 * blocks in the map. in that case, we'll start off with the 
 	 * maximum free.
 	 */
@@ -586,7 +586,7 @@
  *		in place.  if this fails, we'll try to move the extent
  *		to a new set of blocks. if moving the extent, we initially
  *		will try to allocate disk blocks for the requested size
- *		(nnew).  if this fails 	(nnew contigious free blocks not
+ *		(nnew).  if this fails 	(new contiguous free blocks not
  *		avaliable), we'll try  to allocate a smaller number of
  *		blocks (producing a smaller extent), with this smaller
  *		number of blocks consisting of the requested number of
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index c300726..b5c7da6 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -33,7 +33,7 @@
 extern struct dentry *jfs_get_parent(struct dentry *dentry);
 extern void jfs_set_inode_flags(struct inode *);
 
-extern struct address_space_operations jfs_aops;
+extern const struct address_space_operations jfs_aops;
 extern struct inode_operations jfs_dir_inode_operations;
 extern const struct file_operations jfs_dir_operations;
 extern struct inode_operations jfs_file_inode_operations;
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 2b220dd..e1e0a6e 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -577,7 +577,7 @@
 	metapage_releasepage(page, 0);
 }
 
-struct address_space_operations jfs_metapage_aops = {
+const struct address_space_operations jfs_metapage_aops = {
 	.readpage	= metapage_readpage,
 	.writepage	= metapage_writepage,
 	.sync_page	= block_sync_page,
@@ -632,10 +632,9 @@
 		}
 		SetPageUptodate(page);
 	} else {
-		page = read_cache_page(mapping, page_index,
-			    (filler_t *)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, page_index, NULL);
 		if (IS_ERR(page) || !PageUptodate(page)) {
-			jfs_err("read_cache_page failed!");
+			jfs_err("read_mapping_page failed!");
 			return NULL;
 		}
 		lock_page(page);
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index f0b7d32..d17a329 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -139,7 +139,7 @@
 	put_metapage(mp);
 }
 
-extern struct address_space_operations jfs_metapage_aops;
+extern const struct address_space_operations jfs_metapage_aops;
 
 /*
  * This routines invalidate all pages for an extent.
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index db6f41d..73d2aba 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -139,9 +139,9 @@
 	kmem_cache_free(jfs_inode_cachep, ji);
 }
 
-static int jfs_statfs(struct super_block *sb, struct kstatfs *buf)
+static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct jfs_sb_info *sbi = JFS_SBI(sb);
+	struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb);
 	s64 maxinodes;
 	struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap;
 
@@ -565,10 +565,11 @@
 	}
 }
 
-static struct super_block *jfs_get_sb(struct file_system_type *fs_type, 
-	int flags, const char *dev_name, void *data)
+static int jfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super,
+			   mnt);
 }
 
 static int jfs_sync_fs(struct super_block *sb, int wait)
diff --git a/fs/libfs.c b/fs/libfs.c
index 7145ba7..ac02ea6 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -20,9 +20,9 @@
 	return 0;
 }
 
-int simple_statfs(struct super_block *sb, struct kstatfs *buf)
+int simple_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	buf->f_type = sb->s_magic;
+	buf->f_type = dentry->d_sb->s_magic;
 	buf->f_bsize = PAGE_CACHE_SIZE;
 	buf->f_namelen = NAME_MAX;
 	return 0;
@@ -149,10 +149,9 @@
 			/* fallthrough */
 		default:
 			spin_lock(&dcache_lock);
-			if (filp->f_pos == 2) {
-				list_del(q);
-				list_add(q, &dentry->d_subdirs);
-			}
+			if (filp->f_pos == 2)
+				list_move(q, &dentry->d_subdirs);
+
 			for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
 				struct dentry *next;
 				next = list_entry(p, struct dentry, d_u.d_child);
@@ -164,8 +163,7 @@
 					return 0;
 				spin_lock(&dcache_lock);
 				/* next is still alive */
-				list_del(q);
-				list_add(q, p);
+				list_move(q, p);
 				p = q;
 				filp->f_pos++;
 			}
@@ -196,9 +194,9 @@
  * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
  * will never be mountable)
  */
-struct super_block *
-get_sb_pseudo(struct file_system_type *fs_type, char *name,
-	struct super_operations *ops, unsigned long magic)
+int get_sb_pseudo(struct file_system_type *fs_type, char *name,
+	struct super_operations *ops, unsigned long magic,
+	struct vfsmount *mnt)
 {
 	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
 	static struct super_operations default_ops = {.statfs = simple_statfs};
@@ -207,7 +205,7 @@
 	struct qstr d_name = {.name = name, .len = strlen(name)};
 
 	if (IS_ERR(s))
-		return s;
+		return PTR_ERR(s);
 
 	s->s_flags = MS_NOUSER;
 	s->s_maxbytes = ~0ULL;
@@ -232,12 +230,12 @@
 	d_instantiate(dentry, root);
 	s->s_root = dentry;
 	s->s_flags |= MS_ACTIVE;
-	return s;
+	return simple_set_mnt(mnt, s);
 
 Enomem:
 	up_write(&s->s_umount);
 	deactivate_super(s);
-	return ERR_PTR(-ENOMEM);
+	return -ENOMEM;
 }
 
 int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
@@ -424,13 +422,13 @@
 
 static DEFINE_SPINLOCK(pin_fs_lock);
 
-int simple_pin_fs(char *name, struct vfsmount **mount, int *count)
+int simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
 {
 	struct vfsmount *mnt = NULL;
 	spin_lock(&pin_fs_lock);
 	if (unlikely(!*mount)) {
 		spin_unlock(&pin_fs_lock);
-		mnt = do_kern_mount(name, 0, name, NULL);
+		mnt = vfs_kern_mount(type, 0, type->name, NULL);
 		if (IS_ERR(mnt))
 			return PTR_ERR(mnt);
 		spin_lock(&pin_fs_lock);
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index bce7444..52774fe 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -147,11 +147,10 @@
  * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number,
  * that we mark locks for reclaiming, and that we bump the pseudo NSM state.
  */
-static inline
-void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate)
+static void nlmclnt_prepare_reclaim(struct nlm_host *host)
 {
+	down_write(&host->h_rwsem);
 	host->h_monitored = 0;
-	host->h_nsmstate = newstate;
 	host->h_state++;
 	host->h_nextrebind = 0;
 	nlm_rebind_host(host);
@@ -164,6 +163,13 @@
 	dprintk("NLM: reclaiming locks for host %s", host->h_name);
 }
 
+static void nlmclnt_finish_reclaim(struct nlm_host *host)
+{
+	host->h_reclaiming = 0;
+	up_write(&host->h_rwsem);
+	dprintk("NLM: done reclaiming locks for host %s", host->h_name);
+}
+
 /*
  * Reclaim all locks on server host. We do this by spawning a separate
  * reclaimer thread.
@@ -171,12 +177,10 @@
 void
 nlmclnt_recovery(struct nlm_host *host, u32 newstate)
 {
-	if (host->h_reclaiming++) {
-		if (host->h_nsmstate == newstate)
-			return;
-		nlmclnt_prepare_reclaim(host, newstate);
-	} else {
-		nlmclnt_prepare_reclaim(host, newstate);
+	if (host->h_nsmstate == newstate)
+		return;
+	host->h_nsmstate = newstate;
+	if (!host->h_reclaiming++) {
 		nlm_get_host(host);
 		__module_get(THIS_MODULE);
 		if (kernel_thread(reclaimer, host, CLONE_KERNEL) < 0)
@@ -190,6 +194,7 @@
 	struct nlm_host	  *host = (struct nlm_host *) ptr;
 	struct nlm_wait	  *block;
 	struct file_lock *fl, *next;
+	u32 nsmstate;
 
 	daemonize("%s-reclaim", host->h_name);
 	allow_signal(SIGKILL);
@@ -199,19 +204,25 @@
 	lock_kernel();
 	lockd_up();
 
+	nlmclnt_prepare_reclaim(host);
 	/* First, reclaim all locks that have been marked. */
 restart:
+	nsmstate = host->h_nsmstate;
 	list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) {
 		list_del_init(&fl->fl_u.nfs_fl.list);
 
 		if (signalled())
 			continue;
-		if (nlmclnt_reclaim(host, fl) == 0)
-			list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
-		goto restart;
+		if (nlmclnt_reclaim(host, fl) != 0)
+			continue;
+		list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted);
+		if (host->h_nsmstate != nsmstate) {
+			/* Argh! The server rebooted again! */
+			list_splice_init(&host->h_granted, &host->h_reclaim);
+			goto restart;
+		}
 	}
-
-	host->h_reclaiming = 0;
+	nlmclnt_finish_reclaim(host);
 
 	/* Now, wake up all processes that sleep on a blocked lock */
 	list_for_each_entry(block, &nlm_blocked, b_list) {
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index f96e381..4db6209 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -508,7 +508,10 @@
 	}
 
 	block = nlmclnt_prepare_block(host, fl);
+again:
 	for(;;) {
+		/* Reboot protection */
+		fl->fl_u.nfs_fl.state = host->h_state;
 		status = nlmclnt_call(req, NLMPROC_LOCK);
 		if (status < 0)
 			goto out_unblock;
@@ -531,10 +534,16 @@
 	}
 
 	if (resp->status == NLM_LCK_GRANTED) {
-		fl->fl_u.nfs_fl.state = host->h_state;
+		down_read(&host->h_rwsem);
+		/* Check whether or not the server has rebooted */
+		if (fl->fl_u.nfs_fl.state != host->h_state) {
+			up_read(&host->h_rwsem);
+			goto again;
+		}
 		fl->fl_flags |= FL_SLEEP;
 		/* Ensure the resulting lock will get added to granted list */
 		do_vfs_lock(fl);
+		up_read(&host->h_rwsem);
 	}
 	status = nlm_stat_to_errno(resp->status);
 out_unblock:
@@ -596,6 +605,7 @@
 static int
 nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
 {
+	struct nlm_host	*host = req->a_host;
 	struct nlm_res	*resp = &req->a_res;
 	int		status;
 
@@ -604,7 +614,9 @@
 	 * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either
 	 * case, we want to unlock.
 	 */
+	down_read(&host->h_rwsem);
 	do_vfs_lock(fl);
+	up_read(&host->h_rwsem);
 
 	if (req->a_flags & RPC_TASK_ASYNC)
 		return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops);
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 729ac42..38b0e8a 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -112,11 +112,12 @@
 	host->h_version    = version;
 	host->h_proto      = proto;
 	host->h_rpcclnt    = NULL;
-	init_MUTEX(&host->h_sema);
+	mutex_init(&host->h_mutex);
 	host->h_nextrebind = jiffies + NLM_HOST_REBIND;
 	host->h_expires    = jiffies + NLM_HOST_EXPIRE;
 	atomic_set(&host->h_count, 1);
 	init_waitqueue_head(&host->h_gracewait);
+	init_rwsem(&host->h_rwsem);
 	host->h_state      = 0;			/* pseudo NSM state */
 	host->h_nsmstate   = 0;			/* real NSM state */
 	host->h_server	   = server;
@@ -172,7 +173,7 @@
 			(unsigned)ntohl(host->h_addr.sin_addr.s_addr));
 
 	/* Lock host handle */
-	down(&host->h_sema);
+	mutex_lock(&host->h_mutex);
 
 	/* If we've already created an RPC client, check whether
 	 * RPC rebind is required
@@ -204,12 +205,12 @@
 		host->h_rpcclnt = clnt;
 	}
 
-	up(&host->h_sema);
+	mutex_unlock(&host->h_mutex);
 	return clnt;
 
 forgetit:
 	printk("lockd: couldn't create RPC handle for %s\n", host->h_name);
-	up(&host->h_sema);
+	mutex_unlock(&host->h_mutex);
 	return NULL;
 }
 
diff --git a/fs/locks.c b/fs/locks.c
index ab61a8b..1ad29c9 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -703,7 +703,7 @@
  * from a broken NFS client. But broken NFS clients have a lot more to
  * worry about than proper deadlock detection anyway... --okir
  */
-int posix_locks_deadlock(struct file_lock *caller_fl,
+static int posix_locks_deadlock(struct file_lock *caller_fl,
 				struct file_lock *block_fl)
 {
 	struct list_head *tmp;
@@ -722,8 +722,6 @@
 	return 0;
 }
 
-EXPORT_SYMBOL(posix_locks_deadlock);
-
 /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks
  * at the head of the list, but that's secret knowledge known only to
  * flock_lock_file and posix_lock_file.
@@ -794,7 +792,8 @@
 static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock)
 {
 	struct file_lock *fl;
-	struct file_lock *new_fl, *new_fl2;
+	struct file_lock *new_fl = NULL;
+	struct file_lock *new_fl2 = NULL;
 	struct file_lock *left = NULL;
 	struct file_lock *right = NULL;
 	struct file_lock **before;
@@ -803,9 +802,15 @@
 	/*
 	 * We may need two file_lock structures for this operation,
 	 * so we get them in advance to avoid races.
+	 *
+	 * In some cases we can be sure, that no new locks will be needed
 	 */
-	new_fl = locks_alloc_lock();
-	new_fl2 = locks_alloc_lock();
+	if (!(request->fl_flags & FL_ACCESS) &&
+	    (request->fl_type != F_UNLCK ||
+	     request->fl_start != 0 || request->fl_end != OFFSET_MAX)) {
+		new_fl = locks_alloc_lock();
+		new_fl2 = locks_alloc_lock();
+	}
 
 	lock_kernel();
 	if (request->fl_type != F_UNLCK) {
@@ -834,14 +839,7 @@
 	if (request->fl_flags & FL_ACCESS)
 		goto out;
 
-	error = -ENOLCK; /* "no luck" */
-	if (!(new_fl && new_fl2))
-		goto out;
-
 	/*
-	 * We've allocated the new locks in advance, so there are no
-	 * errors possible (and no blocking operations) from here on.
-	 * 
 	 * Find the first old lock with the same owner as the new lock.
 	 */
 	
@@ -938,10 +936,25 @@
 		before = &fl->fl_next;
 	}
 
+	/*
+	 * The above code only modifies existing locks in case of
+	 * merging or replacing.  If new lock(s) need to be inserted
+	 * all modifications are done bellow this, so it's safe yet to
+	 * bail out.
+	 */
+	error = -ENOLCK; /* "no luck" */
+	if (right && left == right && !new_fl2)
+		goto out;
+
 	error = 0;
 	if (!added) {
 		if (request->fl_type == F_UNLCK)
 			goto out;
+
+		if (!new_fl) {
+			error = -ENOLCK;
+			goto out;
+		}
 		locks_copy_lock(new_fl, request);
 		locks_insert_lock(before, new_fl);
 		new_fl = NULL;
@@ -1881,19 +1894,18 @@
  */
 void locks_remove_posix(struct file *filp, fl_owner_t owner)
 {
-	struct file_lock lock, **before;
+	struct file_lock lock;
 
 	/*
 	 * If there are no locks held on this file, we don't need to call
 	 * posix_lock_file().  Another process could be setting a lock on this
 	 * file at the same time, but we wouldn't remove that lock anyway.
 	 */
-	before = &filp->f_dentry->d_inode->i_flock;
-	if (*before == NULL)
+	if (!filp->f_dentry->d_inode->i_flock)
 		return;
 
 	lock.fl_type = F_UNLCK;
-	lock.fl_flags = FL_POSIX;
+	lock.fl_flags = FL_POSIX | FL_CLOSE;
 	lock.fl_start = 0;
 	lock.fl_end = OFFSET_MAX;
 	lock.fl_owner = owner;
@@ -1902,25 +1914,11 @@
 	lock.fl_ops = NULL;
 	lock.fl_lmops = NULL;
 
-	if (filp->f_op && filp->f_op->lock != NULL) {
+	if (filp->f_op && filp->f_op->lock != NULL)
 		filp->f_op->lock(filp, F_SETLK, &lock);
-		goto out;
-	}
+	else
+		posix_lock_file(filp, &lock);
 
-	/* Can't use posix_lock_file here; we need to remove it no matter
-	 * which pid we have.
-	 */
-	lock_kernel();
-	while (*before != NULL) {
-		struct file_lock *fl = *before;
-		if (IS_POSIX(fl) && posix_same_owner(fl, &lock)) {
-			locks_delete_lock(before);
-			continue;
-		}
-		before = &fl->fl_next;
-	}
-	unlock_kernel();
-out:
 	if (lock.fl_ops && lock.fl_ops->fl_release_private)
 		lock.fl_ops->fl_release_private(&lock);
 }
@@ -2206,63 +2204,6 @@
 
 EXPORT_SYMBOL(lock_may_write);
 
-static inline void __steal_locks(struct file *file, fl_owner_t from)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	struct file_lock *fl = inode->i_flock;
-
-	while (fl) {
-		if (fl->fl_file == file && fl->fl_owner == from)
-			fl->fl_owner = current->files;
-		fl = fl->fl_next;
-	}
-}
-
-/* When getting ready for executing a binary, we make sure that current
- * has a files_struct on its own. Before dropping the old files_struct,
- * we take over ownership of all locks for all file descriptors we own.
- * Note that we may accidentally steal a lock for a file that a sibling
- * has created since the unshare_files() call.
- */
-void steal_locks(fl_owner_t from)
-{
-	struct files_struct *files = current->files;
-	int i, j;
-	struct fdtable *fdt;
-
-	if (from == files)
-		return;
-
-	lock_kernel();
-	j = 0;
-
-	/*
-	 * We are not taking a ref to the file structures, so
-	 * we need to acquire ->file_lock.
-	 */
-	spin_lock(&files->file_lock);
-	fdt = files_fdtable(files);
-	for (;;) {
-		unsigned long set;
-		i = j * __NFDBITS;
-		if (i >= fdt->max_fdset || i >= fdt->max_fds)
-			break;
-		set = fdt->open_fds->fds_bits[j++];
-		while (set) {
-			if (set & 1) {
-				struct file *file = fdt->fd[i];
-				if (file)
-					__steal_locks(file, from);
-			}
-			i++;
-			set >>= 1;
-		}
-	}
-	spin_unlock(&files->file_lock);
-	unlock_kernel();
-}
-EXPORT_SYMBOL(steal_locks);
-
 static int __init filelock_init(void)
 {
 	filelock_cache = kmem_cache_create("file_lock_cache",
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index 69224d1..2b0a389 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -60,8 +60,7 @@
 static struct page * dir_get_page(struct inode *dir, unsigned long n)
 {
 	struct address_space *mapping = dir->i_mapping;
-	struct page *page = read_cache_page(mapping, n,
-				(filler_t*)mapping->a_ops->readpage, NULL);
+	struct page *page = read_mapping_page(mapping, n, NULL);
 	if (!IS_ERR(page)) {
 		wait_on_page_locked(page);
 		kmap(page);
diff --git a/fs/minix/inode.c b/fs/minix/inode.c
index 2dcccf1..9ea91c5 100644
--- a/fs/minix/inode.c
+++ b/fs/minix/inode.c
@@ -19,7 +19,7 @@
 
 static void minix_read_inode(struct inode * inode);
 static int minix_write_inode(struct inode * inode, int wait);
-static int minix_statfs(struct super_block *sb, struct kstatfs *buf);
+static int minix_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int minix_remount (struct super_block * sb, int * flags, char * data);
 
 static void minix_delete_inode(struct inode *inode)
@@ -296,11 +296,11 @@
 	return -EINVAL;
 }
 
-static int minix_statfs(struct super_block *sb, struct kstatfs *buf)
+static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct minix_sb_info *sbi = minix_sb(sb);
-	buf->f_type = sb->s_magic;
-	buf->f_bsize = sb->s_blocksize;
+	struct minix_sb_info *sbi = minix_sb(dentry->d_sb);
+	buf->f_type = dentry->d_sb->s_magic;
+	buf->f_bsize = dentry->d_sb->s_blocksize;
 	buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
 	buf->f_bfree = minix_count_free_blocks(sbi);
 	buf->f_bavail = buf->f_bfree;
@@ -335,7 +335,7 @@
 {
 	return generic_block_bmap(mapping,block,minix_get_block);
 }
-static struct address_space_operations minix_aops = {
+static const struct address_space_operations minix_aops = {
 	.readpage = minix_readpage,
 	.writepage = minix_writepage,
 	.sync_page = block_sync_page,
@@ -559,10 +559,11 @@
 		V2_minix_truncate(inode);
 }
 
-static struct super_block *minix_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int minix_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super,
+			   mnt);
 }
 
 static struct file_system_type minix_fs_type = {
diff --git a/fs/mpage.c b/fs/mpage.c
index 9bf2eb3..1e45982 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -707,9 +707,9 @@
 	struct pagevec pvec;
 	int nr_pages;
 	pgoff_t index;
-	pgoff_t end = -1;		/* Inclusive */
+	pgoff_t end;		/* Inclusive */
 	int scanned = 0;
-	int is_range = 0;
+	int range_whole = 0;
 
 	if (wbc->nonblocking && bdi_write_congested(bdi)) {
 		wbc->encountered_congestion = 1;
@@ -721,16 +721,14 @@
 		writepage = mapping->a_ops->writepage;
 
 	pagevec_init(&pvec, 0);
-	if (wbc->sync_mode == WB_SYNC_NONE) {
+	if (wbc->range_cyclic) {
 		index = mapping->writeback_index; /* Start from prev offset */
+		end = -1;
 	} else {
-		index = 0;			  /* whole-file sweep */
-		scanned = 1;
-	}
-	if (wbc->start || wbc->end) {
-		index = wbc->start >> PAGE_CACHE_SHIFT;
-		end = wbc->end >> PAGE_CACHE_SHIFT;
-		is_range = 1;
+		index = wbc->range_start >> PAGE_CACHE_SHIFT;
+		end = wbc->range_end >> PAGE_CACHE_SHIFT;
+		if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
+			range_whole = 1;
 		scanned = 1;
 	}
 retry:
@@ -759,7 +757,7 @@
 				continue;
 			}
 
-			if (unlikely(is_range) && page->index > end) {
+			if (!wbc->range_cyclic && page->index > end) {
 				done = 1;
 				unlock_page(page);
 				continue;
@@ -810,7 +808,7 @@
 		index = 0;
 		goto retry;
 	}
-	if (!is_range)
+	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
 		mapping->writeback_index = index;
 	if (bio)
 		mpage_bio_submit(WRITE, bio);
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 5b76ccd..9e44158 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -661,11 +661,12 @@
 	return 0;
 }
 
-static struct super_block *msdos_get_sb(struct file_system_type *fs_type,
-					int flags, const char *dev_name,
-					void *data)
+static int msdos_get_sb(struct file_system_type *fs_type,
+			int flags, const char *dev_name,
+			void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super,
+			   mnt);
 }
 
 static struct file_system_type msdos_fs_type = {
diff --git a/fs/namei.c b/fs/namei.c
index d6e2ee2..c784e8b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1127,7 +1127,7 @@
 	if (likely(retval == 0)) {
 		if (unlikely(current->audit_context && nd && nd->dentry &&
 				nd->dentry->d_inode))
-		audit_inode(name, nd->dentry->d_inode, flags);
+		audit_inode(name, nd->dentry->d_inode);
 	}
 out_fail:
 	return retval;
@@ -2243,14 +2243,16 @@
 	int error;
 	char * to;
 
-	if (flags != 0)
+	if ((flags & ~AT_SYMLINK_FOLLOW) != 0)
 		return -EINVAL;
 
 	to = getname(newname);
 	if (IS_ERR(to))
 		return PTR_ERR(to);
 
-	error = __user_walk_fd(olddfd, oldname, 0, &old_nd);
+	error = __user_walk_fd(olddfd, oldname,
+			       flags & AT_SYMLINK_FOLLOW ? LOOKUP_FOLLOW : 0,
+			       &old_nd);
 	if (error)
 		goto exit;
 	error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
@@ -2577,8 +2579,7 @@
 {
 	struct page * page;
 	struct address_space *mapping = dentry->d_inode->i_mapping;
-	page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage,
-				NULL);
+	page = read_mapping_page(mapping, 0, NULL);
 	if (IS_ERR(page))
 		goto sync_fail;
 	wait_on_page_locked(page);
diff --git a/fs/namespace.c b/fs/namespace.c
index bf478ad..b3ed212 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -86,6 +86,15 @@
 	return mnt;
 }
 
+int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)
+{
+	mnt->mnt_sb = sb;
+	mnt->mnt_root = dget(sb->s_root);
+	return 0;
+}
+
+EXPORT_SYMBOL(simple_set_mnt);
+
 void free_vfsmnt(struct vfsmount *mnt)
 {
 	kfree(mnt->mnt_devname);
@@ -517,10 +526,8 @@
 {
 	struct vfsmount *p;
 
-	for (p = mnt; p; p = next_mnt(p, mnt)) {
-		list_del(&p->mnt_hash);
-		list_add(&p->mnt_hash, kill);
-	}
+	for (p = mnt; p; p = next_mnt(p, mnt))
+		list_move(&p->mnt_hash, kill);
 
 	if (propagate)
 		propagate_umount(kill);
@@ -576,8 +583,8 @@
 	 */
 
 	lock_kernel();
-	if ((flags & MNT_FORCE) && sb->s_op->umount_begin)
-		sb->s_op->umount_begin(sb);
+	if (sb->s_op->umount_begin)
+		sb->s_op->umount_begin(mnt, flags);
 	unlock_kernel();
 
 	/*
@@ -1163,13 +1170,46 @@
 }
 
 /*
+ * go through the vfsmounts we've just consigned to the graveyard to
+ * - check that they're still dead
+ * - delete the vfsmount from the appropriate namespace under lock
+ * - dispose of the corpse
+ */
+static void expire_mount_list(struct list_head *graveyard, struct list_head *mounts)
+{
+	struct namespace *namespace;
+	struct vfsmount *mnt;
+
+	while (!list_empty(graveyard)) {
+		LIST_HEAD(umounts);
+		mnt = list_entry(graveyard->next, struct vfsmount, mnt_expire);
+		list_del_init(&mnt->mnt_expire);
+
+		/* don't do anything if the namespace is dead - all the
+		 * vfsmounts from it are going away anyway */
+		namespace = mnt->mnt_namespace;
+		if (!namespace || !namespace->root)
+			continue;
+		get_namespace(namespace);
+
+		spin_unlock(&vfsmount_lock);
+		down_write(&namespace_sem);
+		expire_mount(mnt, mounts, &umounts);
+		up_write(&namespace_sem);
+		release_mounts(&umounts);
+		mntput(mnt);
+		put_namespace(namespace);
+		spin_lock(&vfsmount_lock);
+	}
+}
+
+/*
  * process a list of expirable mountpoints with the intent of discarding any
  * mountpoints that aren't in use and haven't been touched since last we came
  * here
  */
 void mark_mounts_for_expiry(struct list_head *mounts)
 {
-	struct namespace *namespace;
 	struct vfsmount *mnt, *next;
 	LIST_HEAD(graveyard);
 
@@ -1193,33 +1233,7 @@
 		list_move(&mnt->mnt_expire, &graveyard);
 	}
 
-	/*
-	 * go through the vfsmounts we've just consigned to the graveyard to
-	 * - check that they're still dead
-	 * - delete the vfsmount from the appropriate namespace under lock
-	 * - dispose of the corpse
-	 */
-	while (!list_empty(&graveyard)) {
-		LIST_HEAD(umounts);
-		mnt = list_entry(graveyard.next, struct vfsmount, mnt_expire);
-		list_del_init(&mnt->mnt_expire);
-
-		/* don't do anything if the namespace is dead - all the
-		 * vfsmounts from it are going away anyway */
-		namespace = mnt->mnt_namespace;
-		if (!namespace || !namespace->root)
-			continue;
-		get_namespace(namespace);
-
-		spin_unlock(&vfsmount_lock);
-		down_write(&namespace_sem);
-		expire_mount(mnt, mounts, &umounts);
-		up_write(&namespace_sem);
-		release_mounts(&umounts);
-		mntput(mnt);
-		put_namespace(namespace);
-		spin_lock(&vfsmount_lock);
-	}
+	expire_mount_list(&graveyard, mounts);
 
 	spin_unlock(&vfsmount_lock);
 }
@@ -1227,6 +1241,73 @@
 EXPORT_SYMBOL_GPL(mark_mounts_for_expiry);
 
 /*
+ * Ripoff of 'select_parent()'
+ *
+ * search the list of submounts for a given mountpoint, and move any
+ * shrinkable submounts to the 'graveyard' list.
+ */
+static int select_submounts(struct vfsmount *parent, struct list_head *graveyard)
+{
+	struct vfsmount *this_parent = parent;
+	struct list_head *next;
+	int found = 0;
+
+repeat:
+	next = this_parent->mnt_mounts.next;
+resume:
+	while (next != &this_parent->mnt_mounts) {
+		struct list_head *tmp = next;
+		struct vfsmount *mnt = list_entry(tmp, struct vfsmount, mnt_child);
+
+		next = tmp->next;
+		if (!(mnt->mnt_flags & MNT_SHRINKABLE))
+			continue;
+		/*
+		 * Descend a level if the d_mounts list is non-empty.
+		 */
+		if (!list_empty(&mnt->mnt_mounts)) {
+			this_parent = mnt;
+			goto repeat;
+		}
+
+		if (!propagate_mount_busy(mnt, 1)) {
+			mntget(mnt);
+			list_move_tail(&mnt->mnt_expire, graveyard);
+			found++;
+		}
+	}
+	/*
+	 * All done at this level ... ascend and resume the search
+	 */
+	if (this_parent != parent) {
+		next = this_parent->mnt_child.next;
+		this_parent = this_parent->mnt_parent;
+		goto resume;
+	}
+	return found;
+}
+
+/*
+ * process a list of expirable mountpoints with the intent of discarding any
+ * submounts of a specific parent mountpoint
+ */
+void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts)
+{
+	LIST_HEAD(graveyard);
+	int found;
+
+	spin_lock(&vfsmount_lock);
+
+	/* extract submounts of 'mountpoint' from the expiration list */
+	while ((found = select_submounts(mountpoint, &graveyard)) != 0)
+		expire_mount_list(&graveyard, mounts);
+
+	spin_unlock(&vfsmount_lock);
+}
+
+EXPORT_SYMBOL_GPL(shrink_submounts);
+
+/*
  * Some copy_from_user() implementations do not return the exact number of
  * bytes remaining to copy on a fault.  But copy_mount_options() requires that.
  * Note that this function differs from copy_from_user() in that it will oops
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index a1f3e97..6c51c11 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -39,7 +39,7 @@
 
 static void ncp_delete_inode(struct inode *);
 static void ncp_put_super(struct super_block *);
-static int  ncp_statfs(struct super_block *, struct kstatfs *);
+static int  ncp_statfs(struct dentry *, struct kstatfs *);
 
 static kmem_cache_t * ncp_inode_cachep;
 
@@ -105,7 +105,7 @@
 
 extern struct dentry_operations ncp_root_dentry_operations;
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
-extern struct address_space_operations ncp_symlink_aops;
+extern const struct address_space_operations ncp_symlink_aops;
 extern int ncp_symlink(struct inode*, struct dentry*, const char*);
 #endif
 
@@ -724,13 +724,14 @@
 	kfree(server);
 }
 
-static int ncp_statfs(struct super_block *sb, struct kstatfs *buf)
+static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct dentry* d;
 	struct inode* i;
 	struct ncp_inode_info* ni;
 	struct ncp_server* s;
 	struct ncp_volume_info vi;
+	struct super_block *sb = dentry->d_sb;
 	int err;
 	__u8 dh;
 	
@@ -957,10 +958,10 @@
 	return result;
 }
 
-static struct super_block *ncp_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int ncp_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, ncp_fill_super);
+	return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt);
 }
 
 static struct file_system_type ncp_fs_type = {
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
index e935f1b..f76b139 100644
--- a/fs/ncpfs/symlink.c
+++ b/fs/ncpfs/symlink.c
@@ -99,7 +99,7 @@
 /*
  * symlinks can't do much...
  */
-struct address_space_operations ncp_symlink_aops = {
+const struct address_space_operations ncp_symlink_aops = {
 	.readpage	= ncp_symlink_readpage,
 };
 	
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index ec61fd5..0b572a0 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -4,14 +4,16 @@
 
 obj-$(CONFIG_NFS_FS) += nfs.o
 
-nfs-y 			:= dir.o file.o inode.o nfs2xdr.o pagelist.o \
-			   proc.o read.o symlink.o unlink.o write.o
+nfs-y 			:= dir.o file.o inode.o super.o nfs2xdr.o pagelist.o \
+			   proc.o read.o symlink.o unlink.o write.o \
+			   namespace.o
 nfs-$(CONFIG_ROOT_NFS)	+= nfsroot.o mount_clnt.o      
 nfs-$(CONFIG_NFS_V3)	+= nfs3proc.o nfs3xdr.o
 nfs-$(CONFIG_NFS_V3_ACL)	+= nfs3acl.o
 nfs-$(CONFIG_NFS_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
 			   delegation.o idmap.o \
-			   callback.o callback_xdr.o callback_proc.o
+			   callback.o callback_xdr.o callback_proc.o \
+			   nfs4namespace.o
 nfs-$(CONFIG_NFS_DIRECTIO) += direct.o
 nfs-$(CONFIG_SYSCTL) += sysctl.o
 nfs-objs		:= $(nfs-y)
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 90c95ad..d53f8c6 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -182,8 +182,6 @@
 /*
  * Define NFS4 callback program
  */
-extern struct svc_version nfs4_callback_version1;
-
 static struct svc_version *nfs4_callback_version[] = {
 	[1] = &nfs4_callback_version1,
 };
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 05c38cf..c929913 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -202,7 +202,7 @@
 	status = decode_fh(xdr, &args->fh);
 out:
 	dprintk("%s: exit with status = %d\n", __FUNCTION__, status);
-	return 0;
+	return status;
 }
 
 static unsigned encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index cae74dd..3ddda6f 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -528,7 +528,7 @@
 
 	lock_kernel();
 
-	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	res = nfs_revalidate_mapping(inode, filp->f_mapping);
 	if (res < 0) {
 		unlock_kernel();
 		return res;
@@ -868,6 +868,17 @@
 	return (nd->intent.open.flags & O_EXCL) != 0;
 }
 
+static inline int nfs_reval_fsid(struct inode *dir,
+		struct nfs_fh *fh, struct nfs_fattr *fattr)
+{
+	struct nfs_server *server = NFS_SERVER(dir);
+
+	if (!nfs_fsid_equal(&server->fsid, &fattr->fsid))
+		/* Revalidate fsid on root dir */
+		return __nfs_revalidate_inode(server, dir->i_sb->s_root->d_inode);
+	return 0;
+}
+
 static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
 	struct dentry *res;
@@ -900,6 +911,11 @@
 		res = ERR_PTR(error);
 		goto out_unlock;
 	}
+	error = nfs_reval_fsid(dir, &fhandle, &fattr);
+	if (error < 0) {
+		res = ERR_PTR(error);
+		goto out_unlock;
+	}
 	inode = nfs_fhget(dentry->d_sb, &fhandle, &fattr);
 	res = (struct dentry *)inode;
 	if (IS_ERR(res))
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 3c72b0c..8ca9707 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -892,7 +892,7 @@
  * nfs_init_directcache - create a slab cache for nfs_direct_req structures
  *
  */
-int nfs_init_directcache(void)
+int __init nfs_init_directcache(void)
 {
 	nfs_direct_cachep = kmem_cache_create("nfs_direct_cache",
 						sizeof(struct nfs_direct_req),
@@ -906,7 +906,7 @@
 }
 
 /**
- * nfs_init_directcache - destroy the slab cache for nfs_direct_req structures
+ * nfs_destroy_directcache - destroy the slab cache for nfs_direct_req structures
  *
  */
 void nfs_destroy_directcache(void)
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index fade02c..cc2b874 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -43,7 +43,7 @@
 static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
 static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
 static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t);
-static int  nfs_file_flush(struct file *);
+static int  nfs_file_flush(struct file *, fl_owner_t id);
 static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
 static int nfs_check_flags(int flags);
 static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
@@ -127,23 +127,6 @@
 }
 
 /**
- * nfs_revalidate_file - Revalidate the page cache & related metadata
- * @inode - pointer to inode struct
- * @file - pointer to file
- */
-static int nfs_revalidate_file(struct inode *inode, struct file *filp)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-	int retval = 0;
-
-	if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR))
-			|| nfs_attribute_timeout(inode))
-		retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
-	nfs_revalidate_mapping(inode, filp->f_mapping);
-	return 0;
-}
-
-/**
  * nfs_revalidate_size - Revalidate the file size
  * @inode - pointer to inode struct
  * @file - pointer to struct file
@@ -188,7 +171,7 @@
  *
  */
 static int
-nfs_file_flush(struct file *file)
+nfs_file_flush(struct file *file, fl_owner_t id)
 {
 	struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data;
 	struct inode	*inode = file->f_dentry->d_inode;
@@ -228,7 +211,7 @@
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long) pos);
 
-	result = nfs_revalidate_file(inode, iocb->ki_filp);
+	result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
 	nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, count);
 	if (!result)
 		result = generic_file_aio_read(iocb, buf, count, pos);
@@ -247,7 +230,7 @@
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long long) *ppos);
 
-	res = nfs_revalidate_file(inode, filp);
+	res = nfs_revalidate_mapping(inode, filp->f_mapping);
 	if (!res)
 		res = generic_file_sendfile(filp, ppos, count, actor, target);
 	return res;
@@ -263,7 +246,7 @@
 	dfprintk(VFS, "nfs: mmap(%s/%s)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	status = nfs_revalidate_file(inode, file);
+	status = nfs_revalidate_mapping(inode, file->f_mapping);
 	if (!status)
 		status = generic_file_mmap(file, vma);
 	return status;
@@ -320,7 +303,11 @@
 
 static void nfs_invalidate_page(struct page *page, unsigned long offset)
 {
-	/* FIXME: we really should cancel any unstarted writes on this page */
+	struct inode *inode = page->mapping->host;
+
+	/* Cancel any unstarted writes on this page */
+	if (offset == 0)
+		nfs_sync_inode_wait(inode, page->index, 1, FLUSH_INVALIDATE);
 }
 
 static int nfs_release_page(struct page *page, gfp_t gfp)
@@ -328,7 +315,7 @@
 	return !nfs_wb_page(page->mapping->host, page);
 }
 
-struct address_space_operations nfs_file_aops = {
+const struct address_space_operations nfs_file_aops = {
 	.readpage = nfs_readpage,
 	.readpages = nfs_readpages,
 	.set_page_dirty = __set_page_dirty_nobuffers,
@@ -373,7 +360,6 @@
 		if (result)
 			goto out;
 	}
-	nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
 
 	result = count;
 	if (!count)
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 3fab5b0..b81e7ed 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -47,7 +47,6 @@
 #include <linux/workqueue.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
 
-#include <linux/nfs_fs_sb.h>
 #include <linux/nfs_fs.h>
 
 #include <linux/nfs_idmap.h>
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index d0b991a..c5b9166 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -36,6 +36,8 @@
 #include <linux/mount.h>
 #include <linux/nfs_idmap.h>
 #include <linux/vfs.h>
+#include <linux/inet.h>
+#include <linux/nfs_xdr.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -44,89 +46,17 @@
 #include "callback.h"
 #include "delegation.h"
 #include "iostat.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
 #define NFS_PARANOIA 1
 
-/* Maximum number of readahead requests
- * FIXME: this should really be a sysctl so that users may tune it to suit
- *        their needs. People that do NFS over a slow network, might for
- *        instance want to reduce it to something closer to 1 for improved
- *        interactive response.
- */
-#define NFS_MAX_READAHEAD	(RPC_DEF_SLOT_TABLE - 1)
-
 static void nfs_invalidate_inode(struct inode *);
 static int nfs_update_inode(struct inode *, struct nfs_fattr *);
 
-static struct inode *nfs_alloc_inode(struct super_block *sb);
-static void nfs_destroy_inode(struct inode *);
-static int nfs_write_inode(struct inode *,int);
-static void nfs_delete_inode(struct inode *);
-static void nfs_clear_inode(struct inode *);
-static void nfs_umount_begin(struct super_block *);
-static int  nfs_statfs(struct super_block *, struct kstatfs *);
-static int  nfs_show_options(struct seq_file *, struct vfsmount *);
-static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
 static void nfs_zap_acl_cache(struct inode *);
 
-static struct rpc_program	nfs_program;
-
-static struct super_operations nfs_sops = { 
-	.alloc_inode	= nfs_alloc_inode,
-	.destroy_inode	= nfs_destroy_inode,
-	.write_inode	= nfs_write_inode,
-	.delete_inode	= nfs_delete_inode,
-	.statfs		= nfs_statfs,
-	.clear_inode	= nfs_clear_inode,
-	.umount_begin	= nfs_umount_begin,
-	.show_options	= nfs_show_options,
-	.show_stats	= nfs_show_stats,
-};
-
-/*
- * RPC cruft for NFS
- */
-static struct rpc_stat		nfs_rpcstat = {
-	.program		= &nfs_program
-};
-static struct rpc_version *	nfs_version[] = {
-	NULL,
-	NULL,
-	&nfs_version2,
-#if defined(CONFIG_NFS_V3)
-	&nfs_version3,
-#elif defined(CONFIG_NFS_V4)
-	NULL,
-#endif
-#if defined(CONFIG_NFS_V4)
-	&nfs_version4,
-#endif
-};
-
-static struct rpc_program	nfs_program = {
-	.name			= "nfs",
-	.number			= NFS_PROGRAM,
-	.nrvers			= ARRAY_SIZE(nfs_version),
-	.version		= nfs_version,
-	.stats			= &nfs_rpcstat,
-	.pipe_dir_name		= "/nfs",
-};
-
-#ifdef CONFIG_NFS_V3_ACL
-static struct rpc_stat		nfsacl_rpcstat = { &nfsacl_program };
-static struct rpc_version *	nfsacl_version[] = {
-	[3]			= &nfsacl_version3,
-};
-
-struct rpc_program		nfsacl_program = {
-	.name =			"nfsacl",
-	.number =		NFS_ACL_PROGRAM,
-	.nrvers =		ARRAY_SIZE(nfsacl_version),
-	.version =		nfsacl_version,
-	.stats =		&nfsacl_rpcstat,
-};
-#endif  /* CONFIG_NFS_V3_ACL */
+static kmem_cache_t * nfs_inode_cachep;
 
 static inline unsigned long
 nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
@@ -134,8 +64,7 @@
 	return nfs_fileid_to_ino_t(fattr->fileid);
 }
 
-static int
-nfs_write_inode(struct inode *inode, int sync)
+int nfs_write_inode(struct inode *inode, int sync)
 {
 	int flags = sync ? FLUSH_SYNC : 0;
 	int ret;
@@ -146,31 +75,15 @@
 	return 0;
 }
 
-static void
-nfs_delete_inode(struct inode * inode)
-{
-	dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
-
-	truncate_inode_pages(&inode->i_data, 0);
-
-	nfs_wb_all(inode);
-	/*
-	 * The following should never happen...
-	 */
-	if (nfs_have_writebacks(inode)) {
-		printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);
-	}
-
-	clear_inode(inode);
-}
-
-static void
-nfs_clear_inode(struct inode *inode)
+void nfs_clear_inode(struct inode *inode)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	struct rpc_cred *cred;
 
-	nfs_wb_all(inode);
+	/*
+	 * The following should never happen...
+	 */
+	BUG_ON(nfs_have_writebacks(inode));
 	BUG_ON (!list_empty(&nfsi->open_files));
 	nfs_zap_acl_cache(inode);
 	cred = nfsi->cache_access.cred;
@@ -179,554 +92,6 @@
 	BUG_ON(atomic_read(&nfsi->data_updates) != 0);
 }
 
-void
-nfs_umount_begin(struct super_block *sb)
-{
-	struct rpc_clnt	*rpc = NFS_SB(sb)->client;
-
-	/* -EIO all pending I/O */
-	if (!IS_ERR(rpc))
-		rpc_killall_tasks(rpc);
-	rpc = NFS_SB(sb)->client_acl;
-	if (!IS_ERR(rpc))
-		rpc_killall_tasks(rpc);
-}
-
-
-static inline unsigned long
-nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
-{
-	/* make sure blocksize is a power of two */
-	if ((bsize & (bsize - 1)) || nrbitsp) {
-		unsigned char	nrbits;
-
-		for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--)
-			;
-		bsize = 1 << nrbits;
-		if (nrbitsp)
-			*nrbitsp = nrbits;
-	}
-
-	return bsize;
-}
-
-/*
- * Calculate the number of 512byte blocks used.
- */
-static inline unsigned long
-nfs_calc_block_size(u64 tsize)
-{
-	loff_t used = (tsize + 511) >> 9;
-	return (used > ULONG_MAX) ? ULONG_MAX : used;
-}
-
-/*
- * Compute and set NFS server blocksize
- */
-static inline unsigned long
-nfs_block_size(unsigned long bsize, unsigned char *nrbitsp)
-{
-	if (bsize < NFS_MIN_FILE_IO_SIZE)
-		bsize = NFS_DEF_FILE_IO_SIZE;
-	else if (bsize >= NFS_MAX_FILE_IO_SIZE)
-		bsize = NFS_MAX_FILE_IO_SIZE;
-
-	return nfs_block_bits(bsize, nrbitsp);
-}
-
-/*
- * Obtain the root inode of the file system.
- */
-static struct inode *
-nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
-{
-	struct nfs_server	*server = NFS_SB(sb);
-	int			error;
-
-	error = server->rpc_ops->getroot(server, rootfh, fsinfo);
-	if (error < 0) {
-		dprintk("nfs_get_root: getattr error = %d\n", -error);
-		return ERR_PTR(error);
-	}
-
-	return nfs_fhget(sb, rootfh, fsinfo->fattr);
-}
-
-/*
- * Do NFS version-independent mount processing, and sanity checking
- */
-static int
-nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
-{
-	struct nfs_server	*server;
-	struct inode		*root_inode;
-	struct nfs_fattr	fattr;
-	struct nfs_fsinfo	fsinfo = {
-					.fattr = &fattr,
-				};
-	struct nfs_pathconf pathinfo = {
-			.fattr = &fattr,
-	};
-	int no_root_error = 0;
-	unsigned long max_rpc_payload;
-
-	/* We probably want something more informative here */
-	snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
-
-	server = NFS_SB(sb);
-
-	sb->s_magic      = NFS_SUPER_MAGIC;
-
-	server->io_stats = nfs_alloc_iostats();
-	if (server->io_stats == NULL)
-		return -ENOMEM;
-
-	root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
-	/* Did getting the root inode fail? */
-	if (IS_ERR(root_inode)) {
-		no_root_error = PTR_ERR(root_inode);
-		goto out_no_root;
-	}
-	sb->s_root = d_alloc_root(root_inode);
-	if (!sb->s_root) {
-		no_root_error = -ENOMEM;
-		goto out_no_root;
-	}
-	sb->s_root->d_op = server->rpc_ops->dentry_ops;
-
-	/* mount time stamp, in seconds */
-	server->mount_time = jiffies;
-
-	/* Get some general file system info */
-	if (server->namelen == 0 &&
-	    server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
-		server->namelen = pathinfo.max_namelen;
-	/* Work out a lot of parameters */
-	if (server->rsize == 0)
-		server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
-	if (server->wsize == 0)
-		server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
-
-	if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
-		server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
-	if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
-		server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
-
-	max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
-	if (server->rsize > max_rpc_payload)
-		server->rsize = max_rpc_payload;
-	if (server->rsize > NFS_MAX_FILE_IO_SIZE)
-		server->rsize = NFS_MAX_FILE_IO_SIZE;
-	server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-
-	if (server->wsize > max_rpc_payload)
-		server->wsize = max_rpc_payload;
-	if (server->wsize > NFS_MAX_FILE_IO_SIZE)
-		server->wsize = NFS_MAX_FILE_IO_SIZE;
-	server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-
-	if (sb->s_blocksize == 0)
-		sb->s_blocksize = nfs_block_bits(server->wsize,
-							 &sb->s_blocksize_bits);
-	server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);
-
-	server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
-	if (server->dtsize > PAGE_CACHE_SIZE)
-		server->dtsize = PAGE_CACHE_SIZE;
-	if (server->dtsize > server->rsize)
-		server->dtsize = server->rsize;
-
-	if (server->flags & NFS_MOUNT_NOAC) {
-		server->acregmin = server->acregmax = 0;
-		server->acdirmin = server->acdirmax = 0;
-		sb->s_flags |= MS_SYNCHRONOUS;
-	}
-	server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
-
-	sb->s_maxbytes = fsinfo.maxfilesize;
-	if (sb->s_maxbytes > MAX_LFS_FILESIZE) 
-		sb->s_maxbytes = MAX_LFS_FILESIZE; 
-
-	server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
-	server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
-
-	/* We're airborne Set socket buffersize */
-	rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
-	return 0;
-	/* Yargs. It didn't work out. */
-out_no_root:
-	dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error);
-	if (!IS_ERR(root_inode))
-		iput(root_inode);
-	return no_root_error;
-}
-
-static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
-{
-	to->to_initval = timeo * HZ / 10;
-	to->to_retries = retrans;
-	if (!to->to_retries)
-		to->to_retries = 2;
-
-	switch (proto) {
-	case IPPROTO_TCP:
-		if (!to->to_initval)
-			to->to_initval = 60 * HZ;
-		if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
-			to->to_initval = NFS_MAX_TCP_TIMEOUT;
-		to->to_increment = to->to_initval;
-		to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
-		to->to_exponential = 0;
-		break;
-	case IPPROTO_UDP:
-	default:
-		if (!to->to_initval)
-			to->to_initval = 11 * HZ / 10;
-		if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
-			to->to_initval = NFS_MAX_UDP_TIMEOUT;
-		to->to_maxval = NFS_MAX_UDP_TIMEOUT;
-		to->to_exponential = 1;
-		break;
-	}
-}
-
-/*
- * Create an RPC client handle.
- */
-static struct rpc_clnt *
-nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
-{
-	struct rpc_timeout	timeparms;
-	struct rpc_xprt		*xprt = NULL;
-	struct rpc_clnt		*clnt = NULL;
-	int			proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
-
-	nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
-
-	server->retrans_timeo = timeparms.to_initval;
-	server->retrans_count = timeparms.to_retries;
-
-	/* create transport and client */
-	xprt = xprt_create_proto(proto, &server->addr, &timeparms);
-	if (IS_ERR(xprt)) {
-		dprintk("%s: cannot create RPC transport. Error = %ld\n",
-				__FUNCTION__, PTR_ERR(xprt));
-		return (struct rpc_clnt *)xprt;
-	}
-	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
-				 server->rpc_ops->version, data->pseudoflavor);
-	if (IS_ERR(clnt)) {
-		dprintk("%s: cannot create RPC client. Error = %ld\n",
-				__FUNCTION__, PTR_ERR(xprt));
-		goto out_fail;
-	}
-
-	clnt->cl_intr     = 1;
-	clnt->cl_softrtry = 1;
-
-	return clnt;
-
-out_fail:
-	return clnt;
-}
-
-/*
- * The way this works is that the mount process passes a structure
- * in the data argument which contains the server's IP address
- * and the root file handle obtained from the server's mount
- * daemon. We stash these away in the private superblock fields.
- */
-static int
-nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
-{
-	struct nfs_server	*server;
-	rpc_authflavor_t	authflavor;
-
-	server           = NFS_SB(sb);
-	sb->s_blocksize_bits = 0;
-	sb->s_blocksize = 0;
-	if (data->bsize)
-		sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
-	if (data->rsize)
-		server->rsize = nfs_block_size(data->rsize, NULL);
-	if (data->wsize)
-		server->wsize = nfs_block_size(data->wsize, NULL);
-	server->flags    = data->flags & NFS_MOUNT_FLAGMASK;
-
-	server->acregmin = data->acregmin*HZ;
-	server->acregmax = data->acregmax*HZ;
-	server->acdirmin = data->acdirmin*HZ;
-	server->acdirmax = data->acdirmax*HZ;
-
-	/* Start lockd here, before we might error out */
-	if (!(server->flags & NFS_MOUNT_NONLM))
-		lockd_up();
-
-	server->namelen  = data->namlen;
-	server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
-	if (!server->hostname)
-		return -ENOMEM;
-	strcpy(server->hostname, data->hostname);
-
-	/* Check NFS protocol revision and initialize RPC op vector
-	 * and file handle pool. */
-#ifdef CONFIG_NFS_V3
-	if (server->flags & NFS_MOUNT_VER3) {
-		server->rpc_ops = &nfs_v3_clientops;
-		server->caps |= NFS_CAP_READDIRPLUS;
-	} else {
-		server->rpc_ops = &nfs_v2_clientops;
-	}
-#else
-	server->rpc_ops = &nfs_v2_clientops;
-#endif
-
-	/* Fill in pseudoflavor for mount version < 5 */
-	if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
-		data->pseudoflavor = RPC_AUTH_UNIX;
-	authflavor = data->pseudoflavor;	/* save for sb_init() */
-	/* XXX maybe we want to add a server->pseudoflavor field */
-
-	/* Create RPC client handles */
-	server->client = nfs_create_client(server, data);
-	if (IS_ERR(server->client))
-		return PTR_ERR(server->client);
-	/* RFC 2623, sec 2.3.2 */
-	if (authflavor != RPC_AUTH_UNIX) {
-		struct rpc_auth *auth;
-
-		server->client_sys = rpc_clone_client(server->client);
-		if (IS_ERR(server->client_sys))
-			return PTR_ERR(server->client_sys);
-		auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
-		if (IS_ERR(auth))
-			return PTR_ERR(auth);
-	} else {
-		atomic_inc(&server->client->cl_count);
-		server->client_sys = server->client;
-	}
-	if (server->flags & NFS_MOUNT_VER3) {
-#ifdef CONFIG_NFS_V3_ACL
-		if (!(server->flags & NFS_MOUNT_NOACL)) {
-			server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
-			/* No errors! Assume that Sun nfsacls are supported */
-			if (!IS_ERR(server->client_acl))
-				server->caps |= NFS_CAP_ACLS;
-		}
-#else
-		server->flags &= ~NFS_MOUNT_NOACL;
-#endif /* CONFIG_NFS_V3_ACL */
-		/*
-		 * The VFS shouldn't apply the umask to mode bits. We will
-		 * do so ourselves when necessary.
-		 */
-		sb->s_flags |= MS_POSIXACL;
-		if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
-			server->namelen = NFS3_MAXNAMLEN;
-		sb->s_time_gran = 1;
-	} else {
-		if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
-			server->namelen = NFS2_MAXNAMLEN;
-	}
-
-	sb->s_op = &nfs_sops;
-	return nfs_sb_init(sb, authflavor);
-}
-
-static int
-nfs_statfs(struct super_block *sb, struct kstatfs *buf)
-{
-	struct nfs_server *server = NFS_SB(sb);
-	unsigned char blockbits;
-	unsigned long blockres;
-	struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode);
-	struct nfs_fattr fattr;
-	struct nfs_fsstat res = {
-			.fattr = &fattr,
-	};
-	int error;
-
-	lock_kernel();
-
-	error = server->rpc_ops->statfs(server, rootfh, &res);
-	buf->f_type = NFS_SUPER_MAGIC;
-	if (error < 0)
-		goto out_err;
-
-	/*
-	 * Current versions of glibc do not correctly handle the
-	 * case where f_frsize != f_bsize.  Eventually we want to
-	 * report the value of wtmult in this field.
-	 */
-	buf->f_frsize = sb->s_blocksize;
-
-	/*
-	 * On most *nix systems, f_blocks, f_bfree, and f_bavail
-	 * are reported in units of f_frsize.  Linux hasn't had
-	 * an f_frsize field in its statfs struct until recently,
-	 * thus historically Linux's sys_statfs reports these
-	 * fields in units of f_bsize.
-	 */
-	buf->f_bsize = sb->s_blocksize;
-	blockbits = sb->s_blocksize_bits;
-	blockres = (1 << blockbits) - 1;
-	buf->f_blocks = (res.tbytes + blockres) >> blockbits;
-	buf->f_bfree = (res.fbytes + blockres) >> blockbits;
-	buf->f_bavail = (res.abytes + blockres) >> blockbits;
-
-	buf->f_files = res.tfiles;
-	buf->f_ffree = res.afiles;
-
-	buf->f_namelen = server->namelen;
- out:
-	unlock_kernel();
-	return 0;
-
- out_err:
-	dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
-	buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
-	goto out;
-
-}
-
-static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
-{
-	static struct proc_nfs_info {
-		int flag;
-		char *str;
-		char *nostr;
-	} nfs_info[] = {
-		{ NFS_MOUNT_SOFT, ",soft", ",hard" },
-		{ NFS_MOUNT_INTR, ",intr", "" },
-		{ NFS_MOUNT_NOCTO, ",nocto", "" },
-		{ NFS_MOUNT_NOAC, ",noac", "" },
-		{ NFS_MOUNT_NONLM, ",nolock", "" },
-		{ NFS_MOUNT_NOACL, ",noacl", "" },
-		{ 0, NULL, NULL }
-	};
-	struct proc_nfs_info *nfs_infop;
-	char buf[12];
-	char *proto;
-
-	seq_printf(m, ",vers=%d", nfss->rpc_ops->version);
-	seq_printf(m, ",rsize=%d", nfss->rsize);
-	seq_printf(m, ",wsize=%d", nfss->wsize);
-	if (nfss->acregmin != 3*HZ || showdefaults)
-		seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
-	if (nfss->acregmax != 60*HZ || showdefaults)
-		seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
-	if (nfss->acdirmin != 30*HZ || showdefaults)
-		seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
-	if (nfss->acdirmax != 60*HZ || showdefaults)
-		seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
-	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
-		if (nfss->flags & nfs_infop->flag)
-			seq_puts(m, nfs_infop->str);
-		else
-			seq_puts(m, nfs_infop->nostr);
-	}
-	switch (nfss->client->cl_xprt->prot) {
-		case IPPROTO_TCP:
-			proto = "tcp";
-			break;
-		case IPPROTO_UDP:
-			proto = "udp";
-			break;
-		default:
-			snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
-			proto = buf;
-	}
-	seq_printf(m, ",proto=%s", proto);
-	seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ);
-	seq_printf(m, ",retrans=%u", nfss->retrans_count);
-}
-
-static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
-{
-	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
-
-	nfs_show_mount_options(m, nfss, 0);
-
-	seq_puts(m, ",addr=");
-	seq_escape(m, nfss->hostname, " \t\n\\");
-
-	return 0;
-}
-
-static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
-{
-	int i, cpu;
-	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
-	struct rpc_auth *auth = nfss->client->cl_auth;
-	struct nfs_iostats totals = { };
-
-	seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
-
-	/*
-	 * Display all mount option settings
-	 */
-	seq_printf(m, "\n\topts:\t");
-	seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
-	seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
-	seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
-	seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
-	nfs_show_mount_options(m, nfss, 1);
-
-	seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
-
-	seq_printf(m, "\n\tcaps:\t");
-	seq_printf(m, "caps=0x%x", nfss->caps);
-	seq_printf(m, ",wtmult=%d", nfss->wtmult);
-	seq_printf(m, ",dtsize=%d", nfss->dtsize);
-	seq_printf(m, ",bsize=%d", nfss->bsize);
-	seq_printf(m, ",namelen=%d", nfss->namelen);
-
-#ifdef CONFIG_NFS_V4
-	if (nfss->rpc_ops->version == 4) {
-		seq_printf(m, "\n\tnfsv4:\t");
-		seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
-		seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
-		seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
-	}
-#endif
-
-	/*
-	 * Display security flavor in effect for this mount
-	 */
-	seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
-	if (auth->au_flavor)
-		seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
-
-	/*
-	 * Display superblock I/O counters
-	 */
-	for_each_possible_cpu(cpu) {
-		struct nfs_iostats *stats;
-
-		preempt_disable();
-		stats = per_cpu_ptr(nfss->io_stats, cpu);
-
-		for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
-			totals.events[i] += stats->events[i];
-		for (i = 0; i < __NFSIOS_BYTESMAX; i++)
-			totals.bytes[i] += stats->bytes[i];
-
-		preempt_enable();
-	}
-
-	seq_printf(m, "\n\tevents:\t");
-	for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
-		seq_printf(m, "%lu ", totals.events[i]);
-	seq_printf(m, "\n\tbytes:\t");
-	for (i = 0; i < __NFSIOS_BYTESMAX; i++)
-		seq_printf(m, "%Lu ", totals.bytes[i]);
-	seq_printf(m, "\n");
-
-	rpc_print_iostats(m, nfss->client);
-
-	return 0;
-}
-
 /**
  * nfs_sync_mapping - helper to flush all mmapped dirty data to disk
  */
@@ -889,6 +254,14 @@
 			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)
 			    && fattr->size <= NFS_LIMIT_READDIRPLUS)
 				set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode));
+			/* Deal with crossing mountpoints */
+			if (!nfs_fsid_equal(&NFS_SB(sb)->fsid, &fattr->fsid)) {
+				if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
+					inode->i_op = &nfs_referral_inode_operations;
+				else
+					inode->i_op = &nfs_mountpoint_inode_operations;
+				inode->i_fop = NULL;
+			}
 		} else if (S_ISLNK(inode->i_mode))
 			inode->i_op = &nfs_symlink_inode_operations;
 		else
@@ -1207,6 +580,7 @@
 	dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",
 		inode->i_sb->s_id, (long long)NFS_FILEID(inode));
 
+	nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
 	lock_kernel();
 	if (!inode || is_bad_inode(inode))
  		goto out_nowait;
@@ -1220,7 +594,7 @@
 		status = -ESTALE;
 		/* Do we trust the cached ESTALE? */
 		if (NFS_ATTRTIMEO(inode) != 0) {
-			if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) {
+			if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME)) {
 				/* no */
 			} else
 				goto out;
@@ -1251,8 +625,6 @@
 	}
 	spin_unlock(&inode->i_lock);
 
-	nfs_revalidate_mapping(inode, inode->i_mapping);
-
 	if (nfsi->cache_validity & NFS_INO_INVALID_ACL)
 		nfs_zap_acl_cache(inode);
 
@@ -1286,8 +658,7 @@
  */
 int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
 {
-	nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);
-	if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))
+	if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR)
 			&& !nfs_attribute_timeout(inode))
 		return NFS_STALE(inode) ? -ESTALE : 0;
 	return __nfs_revalidate_inode(server, inode);
@@ -1298,9 +669,16 @@
  * @inode - pointer to host inode
  * @mapping - pointer to mapping
  */
-void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
+	int ret = 0;
+
+	if (NFS_STALE(inode))
+		ret = -ESTALE;
+	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)
+			|| nfs_attribute_timeout(inode))
+		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
 
 	if (nfsi->cache_validity & NFS_INO_INVALID_DATA) {
 		nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
@@ -1321,6 +699,7 @@
 				inode->i_sb->s_id,
 				(long long)NFS_FILEID(inode));
 	}
+	return ret;
 }
 
 /**
@@ -1360,12 +739,6 @@
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
-	if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
-			&& nfsi->change_attr == fattr->pre_change_attr) {
-		nfsi->change_attr = fattr->change_attr;
-		nfsi->cache_change_attribute = jiffies;
-	}
-
 	/* If we have atomic WCC data, we may update some attributes */
 	if ((fattr->valid & NFS_ATTR_WCC) != 0) {
 		if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
@@ -1399,9 +772,6 @@
 	int data_unstable;
 
 
-	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
-		return 0;
-
 	/* Has the inode gone and changed behind our back? */
 	if (nfsi->fileid != fattr->fileid
 			|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {
@@ -1414,20 +784,13 @@
 	/* Do atomic weak cache consistency updates */
 	nfs_wcc_update_inode(inode, fattr);
 
-	if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0) {
-		if (nfsi->change_attr == fattr->change_attr)
-			goto out;
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
-		if (!data_unstable)
-			nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
-	}
+	if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
+			nfsi->change_attr != fattr->change_attr)
+		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
 
 	/* Verify a few of the more important attributes */
-	if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
-		if (!data_unstable)
-			nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
-	}
+	if (!timespec_equal(&inode->i_mtime, &fattr->mtime))
+		nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
 
 	cur_size = i_size_read(inode);
  	new_isize = nfs_size_to_loff_t(fattr->size);
@@ -1444,7 +807,6 @@
 	if (inode->i_nlink != fattr->nlink)
 		nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
 
-out:
 	if (!timespec_equal(&inode->i_atime, &fattr->atime))
 		nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
 
@@ -1470,7 +832,6 @@
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
 		return 0;
 	spin_lock(&inode->i_lock);
-	nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE;
 	if (time_after(fattr->time_start, nfsi->last_updated))
 		status = nfs_update_inode(inode, fattr);
 	else
@@ -1495,7 +856,7 @@
 
 	spin_lock(&inode->i_lock);
 	if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) {
-		nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+		nfsi->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
 		goto out;
 	}
 	status = nfs_update_inode(inode, fattr);
@@ -1518,6 +879,7 @@
  */
 static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
 {
+	struct nfs_server *server;
 	struct nfs_inode *nfsi = NFS_I(inode);
 	loff_t cur_isize, new_isize;
 	unsigned int	invalid = 0;
@@ -1527,9 +889,6 @@
 			__FUNCTION__, inode->i_sb->s_id, inode->i_ino,
 			atomic_read(&inode->i_count), fattr->valid);
 
-	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
-		return 0;
-
 	if (nfsi->fileid != fattr->fileid)
 		goto out_fileid;
 
@@ -1539,6 +898,12 @@
 	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
 		goto out_changed;
 
+	server = NFS_SERVER(inode);
+	/* Update the fsid if and only if this is the root directory */
+	if (inode == inode->i_sb->s_root->d_inode
+			&& !nfs_fsid_equal(&server->fsid, &fattr->fsid))
+		server->fsid = fattr->fsid;
+
 	/*
 	 * Update the read time so we don't revalidate too often.
 	 */
@@ -1548,7 +913,7 @@
 	/* Are we racing with known updates of the metadata on the server? */
 	data_stable = nfs_verify_change_attribute(inode, fattr->time_start);
 	if (data_stable)
-		nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
+		nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATIME);
 
 	/* Do atomic weak cache consistency updates */
 	nfs_wcc_update_inode(inode, fattr);
@@ -1612,15 +977,13 @@
  		inode->i_blksize = fattr->du.nfs2.blocksize;
  	}
 
-	if ((fattr->valid & NFS_ATTR_FATTR_V4)) {
-		if (nfsi->change_attr != fattr->change_attr) {
-			dprintk("NFS: change_attr change on server for file %s/%ld\n",
-					inode->i_sb->s_id, inode->i_ino);
-			nfsi->change_attr = fattr->change_attr;
-			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
-			nfsi->cache_change_attribute = jiffies;
-		} else
-			invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA);
+	if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
+			nfsi->change_attr != fattr->change_attr) {
+		dprintk("NFS: change_attr change on server for file %s/%ld\n",
+				inode->i_sb->s_id, inode->i_ino);
+		nfsi->change_attr = fattr->change_attr;
+		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+		nfsi->cache_change_attribute = jiffies;
 	}
 
 	/* Update attrtimeo value if we're out of the unstable period */
@@ -1668,190 +1031,15 @@
 	goto out_err;
 }
 
-/*
- * File system information
- */
-
-static int nfs_set_super(struct super_block *s, void *data)
-{
-	s->s_fs_info = data;
-	return set_anon_super(s, data);
-}
- 
-static int nfs_compare_super(struct super_block *sb, void *data)
-{
-	struct nfs_server *server = data;
-	struct nfs_server *old = NFS_SB(sb);
-
-	if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)
-		return 0;
-	if (old->addr.sin_port != server->addr.sin_port)
-		return 0;
-	return !nfs_compare_fh(&old->fh, &server->fh);
-}
-
-static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data)
-{
-	int error;
-	struct nfs_server *server = NULL;
-	struct super_block *s;
-	struct nfs_fh *root;
-	struct nfs_mount_data *data = raw_data;
-
-	s = ERR_PTR(-EINVAL);
-	if (data == NULL) {
-		dprintk("%s: missing data argument\n", __FUNCTION__);
-		goto out_err;
-	}
-	if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
-		dprintk("%s: bad mount version\n", __FUNCTION__);
-		goto out_err;
-	}
-	switch (data->version) {
-		case 1:
-			data->namlen = 0;
-		case 2:
-			data->bsize  = 0;
-		case 3:
-			if (data->flags & NFS_MOUNT_VER3) {
-				dprintk("%s: mount structure version %d does not support NFSv3\n",
-						__FUNCTION__,
-						data->version);
-				goto out_err;
-			}
-			data->root.size = NFS2_FHSIZE;
-			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
-		case 4:
-			if (data->flags & NFS_MOUNT_SECFLAVOUR) {
-				dprintk("%s: mount structure version %d does not support strong security\n",
-						__FUNCTION__,
-						data->version);
-				goto out_err;
-			}
-		case 5:
-			memset(data->context, 0, sizeof(data->context));
-	}
-#ifndef CONFIG_NFS_V3
-	/* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
-	s = ERR_PTR(-EPROTONOSUPPORT);
-	if (data->flags & NFS_MOUNT_VER3) {
-		dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
-		goto out_err;
-	}
-#endif /* CONFIG_NFS_V3 */
-
-	s = ERR_PTR(-ENOMEM);
-	server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
-	if (!server)
-		goto out_err;
-	/* Zero out the NFS state stuff */
-	init_nfsv4_state(server);
-	server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
-
-	root = &server->fh;
-	if (data->flags & NFS_MOUNT_VER3)
-		root->size = data->root.size;
-	else
-		root->size = NFS2_FHSIZE;
-	s = ERR_PTR(-EINVAL);
-	if (root->size > sizeof(root->data)) {
-		dprintk("%s: invalid root filehandle\n", __FUNCTION__);
-		goto out_err;
-	}
-	memcpy(root->data, data->root.data, root->size);
-
-	/* We now require that the mount process passes the remote address */
-	memcpy(&server->addr, &data->addr, sizeof(server->addr));
-	if (server->addr.sin_addr.s_addr == INADDR_ANY) {
-		dprintk("%s: mount program didn't pass remote address!\n",
-				__FUNCTION__);
-		goto out_err;
-	}
-
-	/* Fire up rpciod if not yet running */
-	s = ERR_PTR(rpciod_up());
-	if (IS_ERR(s)) {
-		dprintk("%s: couldn't start rpciod! Error = %ld\n",
-				__FUNCTION__, PTR_ERR(s));
-		goto out_err;
-	}
-
-	s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
-	if (IS_ERR(s) || s->s_root)
-		goto out_rpciod_down;
-
-	s->s_flags = flags;
-
-	error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
-	if (error) {
-		up_write(&s->s_umount);
-		deactivate_super(s);
-		return ERR_PTR(error);
-	}
-	s->s_flags |= MS_ACTIVE;
-	return s;
-out_rpciod_down:
-	rpciod_down();
-out_err:
-	kfree(server);
-	return s;
-}
-
-static void nfs_kill_super(struct super_block *s)
-{
-	struct nfs_server *server = NFS_SB(s);
-
-	kill_anon_super(s);
-
-	if (!IS_ERR(server->client))
-		rpc_shutdown_client(server->client);
-	if (!IS_ERR(server->client_sys))
-		rpc_shutdown_client(server->client_sys);
-	if (!IS_ERR(server->client_acl))
-		rpc_shutdown_client(server->client_acl);
-
-	if (!(server->flags & NFS_MOUNT_NONLM))
-		lockd_down();	/* release rpc.lockd */
-
-	rpciod_down();		/* release rpciod */
-
-	nfs_free_iostats(server->io_stats);
-	kfree(server->hostname);
-	kfree(server);
-}
-
-static struct file_system_type nfs_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "nfs",
-	.get_sb		= nfs_get_sb,
-	.kill_sb	= nfs_kill_super,
-	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
 
 #ifdef CONFIG_NFS_V4
 
-static void nfs4_clear_inode(struct inode *);
-
-
-static struct super_operations nfs4_sops = { 
-	.alloc_inode	= nfs_alloc_inode,
-	.destroy_inode	= nfs_destroy_inode,
-	.write_inode	= nfs_write_inode,
-	.delete_inode	= nfs_delete_inode,
-	.statfs		= nfs_statfs,
-	.clear_inode	= nfs4_clear_inode,
-	.umount_begin	= nfs_umount_begin,
-	.show_options	= nfs_show_options,
-	.show_stats	= nfs_show_stats,
-};
-
 /*
  * Clean out any remaining NFSv4 state that might be left over due
  * to open() calls that passed nfs_atomic_lookup, but failed to call
  * nfs_open().
  */
-static void nfs4_clear_inode(struct inode *inode)
+void nfs4_clear_inode(struct inode *inode)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 
@@ -1875,357 +1063,9 @@
 		nfs4_close_state(state, state->state);
 	}
 }
-
-
-static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
-{
-	struct nfs_server *server;
-	struct nfs4_client *clp = NULL;
-	struct rpc_xprt *xprt = NULL;
-	struct rpc_clnt *clnt = NULL;
-	struct rpc_timeout timeparms;
-	rpc_authflavor_t authflavour;
-	int err = -EIO;
-
-	sb->s_blocksize_bits = 0;
-	sb->s_blocksize = 0;
-	server = NFS_SB(sb);
-	if (data->rsize != 0)
-		server->rsize = nfs_block_size(data->rsize, NULL);
-	if (data->wsize != 0)
-		server->wsize = nfs_block_size(data->wsize, NULL);
-	server->flags = data->flags & NFS_MOUNT_FLAGMASK;
-	server->caps = NFS_CAP_ATOMIC_OPEN;
-
-	server->acregmin = data->acregmin*HZ;
-	server->acregmax = data->acregmax*HZ;
-	server->acdirmin = data->acdirmin*HZ;
-	server->acdirmax = data->acdirmax*HZ;
-
-	server->rpc_ops = &nfs_v4_clientops;
-
-	nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
-
-	server->retrans_timeo = timeparms.to_initval;
-	server->retrans_count = timeparms.to_retries;
-
-	clp = nfs4_get_client(&server->addr.sin_addr);
-	if (!clp) {
-		dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
-		return -EIO;
-	}
-
-	/* Now create transport and client */
-	authflavour = RPC_AUTH_UNIX;
-	if (data->auth_flavourlen != 0) {
-		if (data->auth_flavourlen != 1) {
-			dprintk("%s: Invalid number of RPC auth flavours %d.\n",
-					__FUNCTION__, data->auth_flavourlen);
-			err = -EINVAL;
-			goto out_fail;
-		}
-		if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
-			err = -EFAULT;
-			goto out_fail;
-		}
-	}
-
-	down_write(&clp->cl_sem);
-	if (IS_ERR(clp->cl_rpcclient)) {
-		xprt = xprt_create_proto(data->proto, &server->addr, &timeparms);
-		if (IS_ERR(xprt)) {
-			up_write(&clp->cl_sem);
-			err = PTR_ERR(xprt);
-			dprintk("%s: cannot create RPC transport. Error = %d\n",
-					__FUNCTION__, err);
-			goto out_fail;
-		}
-		clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
-				server->rpc_ops->version, authflavour);
-		if (IS_ERR(clnt)) {
-			up_write(&clp->cl_sem);
-			err = PTR_ERR(clnt);
-			dprintk("%s: cannot create RPC client. Error = %d\n",
-					__FUNCTION__, err);
-			goto out_fail;
-		}
-		clnt->cl_intr     = 1;
-		clnt->cl_softrtry = 1;
-		clp->cl_rpcclient = clnt;
-		memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
-		nfs_idmap_new(clp);
-	}
-	list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
-	clnt = rpc_clone_client(clp->cl_rpcclient);
-	if (!IS_ERR(clnt))
-			server->nfs4_state = clp;
-	up_write(&clp->cl_sem);
-	clp = NULL;
-
-	if (IS_ERR(clnt)) {
-		err = PTR_ERR(clnt);
-		dprintk("%s: cannot create RPC client. Error = %d\n",
-				__FUNCTION__, err);
-		return err;
-	}
-
-	server->client    = clnt;
-
-	if (server->nfs4_state->cl_idmap == NULL) {
-		dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
-		return -ENOMEM;
-	}
-
-	if (clnt->cl_auth->au_flavor != authflavour) {
-		struct rpc_auth *auth;
-
-		auth = rpcauth_create(authflavour, clnt);
-		if (IS_ERR(auth)) {
-			dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
-			return PTR_ERR(auth);
-		}
-	}
-
-	sb->s_time_gran = 1;
-
-	sb->s_op = &nfs4_sops;
-	err = nfs_sb_init(sb, authflavour);
-	if (err == 0)
-		return 0;
-out_fail:
-	if (clp)
-		nfs4_put_client(clp);
-	return err;
-}
-
-static int nfs4_compare_super(struct super_block *sb, void *data)
-{
-	struct nfs_server *server = data;
-	struct nfs_server *old = NFS_SB(sb);
-
-	if (strcmp(server->hostname, old->hostname) != 0)
-		return 0;
-	if (strcmp(server->mnt_path, old->mnt_path) != 0)
-		return 0;
-	return 1;
-}
-
-static void *
-nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
-{
-	void *p = NULL;
-
-	if (!src->len)
-		return ERR_PTR(-EINVAL);
-	if (src->len < maxlen)
-		maxlen = src->len;
-	if (dst == NULL) {
-		p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
-		if (p == NULL)
-			return ERR_PTR(-ENOMEM);
-	}
-	if (copy_from_user(dst, src->data, maxlen)) {
-		kfree(p);
-		return ERR_PTR(-EFAULT);
-	}
-	dst[maxlen] = '\0';
-	return dst;
-}
-
-static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *raw_data)
-{
-	int error;
-	struct nfs_server *server;
-	struct super_block *s;
-	struct nfs4_mount_data *data = raw_data;
-	void *p;
-
-	if (data == NULL) {
-		dprintk("%s: missing data argument\n", __FUNCTION__);
-		return ERR_PTR(-EINVAL);
-	}
-	if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
-		dprintk("%s: bad mount version\n", __FUNCTION__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
-	if (!server)
-		return ERR_PTR(-ENOMEM);
-	/* Zero out the NFS state stuff */
-	init_nfsv4_state(server);
-	server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
-
-	p = nfs_copy_user_string(NULL, &data->hostname, 256);
-	if (IS_ERR(p))
-		goto out_err;
-	server->hostname = p;
-
-	p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
-	if (IS_ERR(p))
-		goto out_err;
-	server->mnt_path = p;
-
-	p = nfs_copy_user_string(server->ip_addr, &data->client_addr,
-			sizeof(server->ip_addr) - 1);
-	if (IS_ERR(p))
-		goto out_err;
-
-	/* We now require that the mount process passes the remote address */
-	if (data->host_addrlen != sizeof(server->addr)) {
-		s = ERR_PTR(-EINVAL);
-		goto out_free;
-	}
-	if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
-		s = ERR_PTR(-EFAULT);
-		goto out_free;
-	}
-	if (server->addr.sin_family != AF_INET ||
-	    server->addr.sin_addr.s_addr == INADDR_ANY) {
-		dprintk("%s: mount program didn't pass remote IP address!\n",
-				__FUNCTION__);
-		s = ERR_PTR(-EINVAL);
-		goto out_free;
-	}
-
-	/* Fire up rpciod if not yet running */
-	s = ERR_PTR(rpciod_up());
-	if (IS_ERR(s)) {
-		dprintk("%s: couldn't start rpciod! Error = %ld\n",
-				__FUNCTION__, PTR_ERR(s));
-		goto out_free;
-	}
-
-	s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
-
-	if (IS_ERR(s) || s->s_root)
-		goto out_free;
-
-	s->s_flags = flags;
-
-	error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
-	if (error) {
-		up_write(&s->s_umount);
-		deactivate_super(s);
-		return ERR_PTR(error);
-	}
-	s->s_flags |= MS_ACTIVE;
-	return s;
-out_err:
-	s = (struct super_block *)p;
-out_free:
-	kfree(server->mnt_path);
-	kfree(server->hostname);
-	kfree(server);
-	return s;
-}
-
-static void nfs4_kill_super(struct super_block *sb)
-{
-	struct nfs_server *server = NFS_SB(sb);
-
-	nfs_return_all_delegations(sb);
-	kill_anon_super(sb);
-
-	nfs4_renewd_prepare_shutdown(server);
-
-	if (server->client != NULL && !IS_ERR(server->client))
-		rpc_shutdown_client(server->client);
-
-	destroy_nfsv4_state(server);
-
-	rpciod_down();
-
-	nfs_free_iostats(server->io_stats);
-	kfree(server->hostname);
-	kfree(server);
-}
-
-static struct file_system_type nfs4_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "nfs4",
-	.get_sb		= nfs4_get_sb,
-	.kill_sb	= nfs4_kill_super,
-	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
-};
-
-static const int nfs_set_port_min = 0;
-static const int nfs_set_port_max = 65535;
-static int param_set_port(const char *val, struct kernel_param *kp)
-{
-	char *endp;
-	int num = simple_strtol(val, &endp, 0);
-	if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max)
-		return -EINVAL;
-	*((int *)kp->arg) = num;
-	return 0;
-}
-
-module_param_call(callback_tcpport, param_set_port, param_get_int,
-		 &nfs_callback_set_tcpport, 0644);
-
-static int param_set_idmap_timeout(const char *val, struct kernel_param *kp)
-{
-	char *endp;
-	int num = simple_strtol(val, &endp, 0);
-	int jif = num * HZ;
-	if (endp == val || *endp || num < 0 || jif < num)
-		return -EINVAL;
-	*((int *)kp->arg) = jif;
-	return 0;
-}
-
-module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int,
-		 &nfs_idmap_cache_timeout, 0644);
-
-#define nfs4_init_once(nfsi) \
-	do { \
-		INIT_LIST_HEAD(&(nfsi)->open_states); \
-		nfsi->delegation = NULL; \
-		nfsi->delegation_state = 0; \
-		init_rwsem(&nfsi->rwsem); \
-	} while(0)
-
-static inline int register_nfs4fs(void)
-{
-	int ret;
-
-	ret = nfs_register_sysctl();
-	if (ret != 0)
-		return ret;
-	ret = register_filesystem(&nfs4_fs_type);
-	if (ret != 0)
-		nfs_unregister_sysctl();
-	return ret;
-}
-
-static inline void unregister_nfs4fs(void)
-{
-	unregister_filesystem(&nfs4_fs_type);
-	nfs_unregister_sysctl();
-}
-#else
-#define nfs4_init_once(nfsi) \
-	do { } while (0)
-#define register_nfs4fs() (0)
-#define unregister_nfs4fs()
 #endif
 
-extern int nfs_init_nfspagecache(void);
-extern void nfs_destroy_nfspagecache(void);
-extern int nfs_init_readpagecache(void);
-extern void nfs_destroy_readpagecache(void);
-extern int nfs_init_writepagecache(void);
-extern void nfs_destroy_writepagecache(void);
-#ifdef CONFIG_NFS_DIRECTIO
-extern int nfs_init_directcache(void);
-extern void nfs_destroy_directcache(void);
-#endif
-
-static kmem_cache_t * nfs_inode_cachep;
-
-static struct inode *nfs_alloc_inode(struct super_block *sb)
+struct inode *nfs_alloc_inode(struct super_block *sb)
 {
 	struct nfs_inode *nfsi;
 	nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL);
@@ -2244,11 +1084,21 @@
 	return &nfsi->vfs_inode;
 }
 
-static void nfs_destroy_inode(struct inode *inode)
+void nfs_destroy_inode(struct inode *inode)
 {
 	kmem_cache_free(nfs_inode_cachep, NFS_I(inode));
 }
 
+static inline void nfs4_init_once(struct nfs_inode *nfsi)
+{
+#ifdef CONFIG_NFS_V4
+	INIT_LIST_HEAD(&nfsi->open_states);
+	nfsi->delegation = NULL;
+	nfsi->delegation_state = 0;
+	init_rwsem(&nfsi->rwsem);
+#endif
+}
+
 static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
 {
 	struct nfs_inode *nfsi = (struct nfs_inode *) foo;
@@ -2269,7 +1119,7 @@
 	}
 }
  
-static int nfs_init_inodecache(void)
+static int __init nfs_init_inodecache(void)
 {
 	nfs_inode_cachep = kmem_cache_create("nfs_inode_cache",
 					     sizeof(struct nfs_inode),
@@ -2311,29 +1161,22 @@
 	if (err)
 		goto out1;
 
-#ifdef CONFIG_NFS_DIRECTIO
 	err = nfs_init_directcache();
 	if (err)
 		goto out0;
-#endif
 
 #ifdef CONFIG_PROC_FS
 	rpc_proc_register(&nfs_rpcstat);
 #endif
-        err = register_filesystem(&nfs_fs_type);
-	if (err)
-		goto out;
-	if ((err = register_nfs4fs()) != 0)
+	if ((err = register_nfs_fs()) != 0)
 		goto out;
 	return 0;
 out:
 #ifdef CONFIG_PROC_FS
 	rpc_proc_unregister("nfs");
 #endif
-#ifdef CONFIG_NFS_DIRECTIO
 	nfs_destroy_directcache();
 out0:
-#endif
 	nfs_destroy_writepagecache();
 out1:
 	nfs_destroy_readpagecache();
@@ -2347,9 +1190,7 @@
 
 static void __exit exit_nfs_fs(void)
 {
-#ifdef CONFIG_NFS_DIRECTIO
 	nfs_destroy_directcache();
-#endif
 	nfs_destroy_writepagecache();
 	nfs_destroy_readpagecache();
 	nfs_destroy_inodecache();
@@ -2357,8 +1198,7 @@
 #ifdef CONFIG_PROC_FS
 	rpc_proc_unregister("nfs");
 #endif
-	unregister_filesystem(&nfs_fs_type);
-	unregister_nfs4fs();
+	unregister_nfs_fs();
 }
 
 /* Not quite true; I just maintain it */
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
new file mode 100644
index 0000000..4fe51c1
--- /dev/null
+++ b/fs/nfs/internal.h
@@ -0,0 +1,186 @@
+/*
+ * NFS internal definitions
+ */
+
+#include <linux/mount.h>
+
+struct nfs_clone_mount {
+	const struct super_block *sb;
+	const struct dentry *dentry;
+	struct nfs_fh *fh;
+	struct nfs_fattr *fattr;
+	char *hostname;
+	char *mnt_path;
+	struct sockaddr_in *addr;
+	rpc_authflavor_t authflavor;
+};
+
+/* namespace-nfs4.c */
+#ifdef CONFIG_NFS_V4
+extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry);
+#else
+static inline
+struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+{
+	return ERR_PTR(-ENOENT);
+}
+#endif
+
+/* callback_xdr.c */
+extern struct svc_version nfs4_callback_version1;
+
+/* pagelist.c */
+extern int __init nfs_init_nfspagecache(void);
+extern void nfs_destroy_nfspagecache(void);
+extern int __init nfs_init_readpagecache(void);
+extern void nfs_destroy_readpagecache(void);
+extern int __init nfs_init_writepagecache(void);
+extern void nfs_destroy_writepagecache(void);
+
+#ifdef CONFIG_NFS_DIRECTIO
+extern int __init nfs_init_directcache(void);
+extern void nfs_destroy_directcache(void);
+#else
+#define nfs_init_directcache() (0)
+#define nfs_destroy_directcache() do {} while(0)
+#endif
+
+/* nfs2xdr.c */
+extern struct rpc_procinfo nfs_procedures[];
+extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
+
+/* nfs3xdr.c */
+extern struct rpc_procinfo nfs3_procedures[];
+extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
+
+/* nfs4xdr.c */
+extern int nfs_stat_to_errno(int);
+extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
+
+/* nfs4proc.c */
+#ifdef CONFIG_NFS_V4
+extern struct rpc_procinfo nfs4_procedures[];
+
+extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
+				  struct nfs4_fs_locations *fs_locations,
+				  struct page *page);
+#endif
+
+/* inode.c */
+extern struct inode *nfs_alloc_inode(struct super_block *sb);
+extern void nfs_destroy_inode(struct inode *);
+extern int nfs_write_inode(struct inode *,int);
+extern void nfs_clear_inode(struct inode *);
+#ifdef CONFIG_NFS_V4
+extern void nfs4_clear_inode(struct inode *);
+#endif
+
+/* super.c */
+extern struct file_system_type nfs_referral_nfs4_fs_type;
+extern struct file_system_type clone_nfs_fs_type;
+#ifdef CONFIG_NFS_V4
+extern struct file_system_type clone_nfs4_fs_type;
+#endif
+#ifdef CONFIG_PROC_FS
+extern struct rpc_stat nfs_rpcstat;
+#endif
+extern int __init register_nfs_fs(void);
+extern void __exit unregister_nfs_fs(void);
+
+/* namespace.c */
+extern char *nfs_path(const char *base, const struct dentry *dentry,
+		      char *buffer, ssize_t buflen);
+
+/*
+ * Determine the mount path as a string
+ */
+static inline char *
+nfs4_path(const struct dentry *dentry, char *buffer, ssize_t buflen)
+{
+#ifdef CONFIG_NFS_V4
+	return nfs_path(NFS_SB(dentry->d_sb)->mnt_path, dentry, buffer, buflen);
+#else
+	return NULL;
+#endif
+}
+
+/*
+ * Determine the device name as a string
+ */
+static inline char *nfs_devname(const struct vfsmount *mnt_parent,
+			 const struct dentry *dentry,
+			 char *buffer, ssize_t buflen)
+{
+	return nfs_path(mnt_parent->mnt_devname, dentry, buffer, buflen);
+}
+
+/*
+ * Determine the actual block size (and log2 thereof)
+ */
+static inline
+unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp)
+{
+	/* make sure blocksize is a power of two */
+	if ((bsize & (bsize - 1)) || nrbitsp) {
+		unsigned char	nrbits;
+
+		for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--)
+			;
+		bsize = 1 << nrbits;
+		if (nrbitsp)
+			*nrbitsp = nrbits;
+	}
+
+	return bsize;
+}
+
+/*
+ * Calculate the number of 512byte blocks used.
+ */
+static inline unsigned long nfs_calc_block_size(u64 tsize)
+{
+	loff_t used = (tsize + 511) >> 9;
+	return (used > ULONG_MAX) ? ULONG_MAX : used;
+}
+
+/*
+ * Compute and set NFS server blocksize
+ */
+static inline
+unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp)
+{
+	if (bsize < NFS_MIN_FILE_IO_SIZE)
+		bsize = NFS_DEF_FILE_IO_SIZE;
+	else if (bsize >= NFS_MAX_FILE_IO_SIZE)
+		bsize = NFS_MAX_FILE_IO_SIZE;
+
+	return nfs_block_bits(bsize, nrbitsp);
+}
+
+/*
+ * Determine the maximum file size for a superblock
+ */
+static inline
+void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize)
+{
+	sb->s_maxbytes = (loff_t)maxfilesize;
+	if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0)
+		sb->s_maxbytes = MAX_LFS_FILESIZE;
+}
+
+/*
+ * Check if the string represents a "valid" IPv4 address
+ */
+static inline int valid_ipaddr4(const char *buf)
+{
+	int rc, count, in[4];
+
+	rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]);
+	if (rc != 4)
+		return -EINVAL;
+	for (count = 0; count < 4; count++) {
+		if (in[count] > 255)
+			return -EINVAL;
+	}
+	return 0;
+}
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
new file mode 100644
index 0000000..19b98ca
--- /dev/null
+++ b/fs/nfs/namespace.c
@@ -0,0 +1,229 @@
+/*
+ * linux/fs/nfs/namespace.c
+ *
+ * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
+ *
+ * NFS namespace
+ */
+
+#include <linux/config.h>
+
+#include <linux/dcache.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/nfs_fs.h>
+#include <linux/string.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/vfs.h>
+#include "internal.h"
+
+#define NFSDBG_FACILITY		NFSDBG_VFS
+
+static void nfs_expire_automounts(void *list);
+
+LIST_HEAD(nfs_automount_list);
+static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list);
+int nfs_mountpoint_expiry_timeout = 500 * HZ;
+
+/*
+ * nfs_path - reconstruct the path given an arbitrary dentry
+ * @base - arbitrary string to prepend to the path
+ * @dentry - pointer to dentry
+ * @buffer - result buffer
+ * @buflen - length of buffer
+ *
+ * Helper function for constructing the path from the
+ * root dentry to an arbitrary hashed dentry.
+ *
+ * This is mainly for use in figuring out the path on the
+ * server side when automounting on top of an existing partition.
+ */
+char *nfs_path(const char *base, const struct dentry *dentry,
+	       char *buffer, ssize_t buflen)
+{
+	char *end = buffer+buflen;
+	int namelen;
+
+	*--end = '\0';
+	buflen--;
+	spin_lock(&dcache_lock);
+	while (!IS_ROOT(dentry)) {
+		namelen = dentry->d_name.len;
+		buflen -= namelen + 1;
+		if (buflen < 0)
+			goto Elong;
+		end -= namelen;
+		memcpy(end, dentry->d_name.name, namelen);
+		*--end = '/';
+		dentry = dentry->d_parent;
+	}
+	spin_unlock(&dcache_lock);
+	namelen = strlen(base);
+	/* Strip off excess slashes in base string */
+	while (namelen > 0 && base[namelen - 1] == '/')
+		namelen--;
+	buflen -= namelen;
+	if (buflen < 0)
+		goto Elong;
+	end -= namelen;
+	memcpy(end, base, namelen);
+	return end;
+Elong:
+	return ERR_PTR(-ENAMETOOLONG);
+}
+
+/*
+ * nfs_follow_mountpoint - handle crossing a mountpoint on the server
+ * @dentry - dentry of mountpoint
+ * @nd - nameidata info
+ *
+ * When we encounter a mountpoint on the server, we want to set up
+ * a mountpoint on the client too, to prevent inode numbers from
+ * colliding, and to allow "df" to work properly.
+ * On NFSv4, we also want to allow for the fact that different
+ * filesystems may be migrated to different servers in a failover
+ * situation, and that different filesystems may want to use
+ * different security flavours.
+ */
+static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd)
+{
+	struct vfsmount *mnt;
+	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+	struct dentry *parent;
+	struct nfs_fh fh;
+	struct nfs_fattr fattr;
+	int err;
+
+	BUG_ON(IS_ROOT(dentry));
+	dprintk("%s: enter\n", __FUNCTION__);
+	dput(nd->dentry);
+	nd->dentry = dget(dentry);
+	if (d_mountpoint(nd->dentry))
+		goto out_follow;
+	/* Look it up again */
+	parent = dget_parent(nd->dentry);
+	err = server->rpc_ops->lookup(parent->d_inode, &nd->dentry->d_name, &fh, &fattr);
+	dput(parent);
+	if (err != 0)
+		goto out_err;
+
+	if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL)
+		mnt = nfs_do_refmount(nd->mnt, nd->dentry);
+	else
+		mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr);
+	err = PTR_ERR(mnt);
+	if (IS_ERR(mnt))
+		goto out_err;
+
+	mntget(mnt);
+	err = do_add_mount(mnt, nd, nd->mnt->mnt_flags|MNT_SHRINKABLE, &nfs_automount_list);
+	if (err < 0) {
+		mntput(mnt);
+		if (err == -EBUSY)
+			goto out_follow;
+		goto out_err;
+	}
+	mntput(nd->mnt);
+	dput(nd->dentry);
+	nd->mnt = mnt;
+	nd->dentry = dget(mnt->mnt_root);
+	schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
+out:
+	dprintk("%s: done, returned %d\n", __FUNCTION__, err);
+	return ERR_PTR(err);
+out_err:
+	path_release(nd);
+	goto out;
+out_follow:
+	while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
+		;
+	err = 0;
+	goto out;
+}
+
+struct inode_operations nfs_mountpoint_inode_operations = {
+	.follow_link	= nfs_follow_mountpoint,
+	.getattr	= nfs_getattr,
+};
+
+struct inode_operations nfs_referral_inode_operations = {
+	.follow_link	= nfs_follow_mountpoint,
+};
+
+static void nfs_expire_automounts(void *data)
+{
+	struct list_head *list = (struct list_head *)data;
+
+	mark_mounts_for_expiry(list);
+	if (!list_empty(list))
+		schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
+}
+
+void nfs_release_automount_timer(void)
+{
+	if (list_empty(&nfs_automount_list)) {
+		cancel_delayed_work(&nfs_automount_task);
+		flush_scheduled_work();
+	}
+}
+
+/*
+ * Clone a mountpoint of the appropriate type
+ */
+static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, char *devname,
+					   struct nfs_clone_mount *mountdata)
+{
+#ifdef CONFIG_NFS_V4
+	struct vfsmount *mnt = NULL;
+	switch (server->rpc_ops->version) {
+		case 2:
+		case 3:
+			mnt = vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
+			break;
+		case 4:
+			mnt = vfs_kern_mount(&clone_nfs4_fs_type, 0, devname, mountdata);
+	}
+	return mnt;
+#else
+	return vfs_kern_mount(&clone_nfs_fs_type, 0, devname, mountdata);
+#endif
+}
+
+/**
+ * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
+ * @mnt_parent - mountpoint of parent directory
+ * @dentry - parent directory
+ * @fh - filehandle for new root dentry
+ * @fattr - attributes for new root inode
+ *
+ */
+struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+		const struct dentry *dentry, struct nfs_fh *fh,
+		struct nfs_fattr *fattr)
+{
+	struct nfs_clone_mount mountdata = {
+		.sb = mnt_parent->mnt_sb,
+		.dentry = dentry,
+		.fh = fh,
+		.fattr = fattr,
+	};
+	struct vfsmount *mnt = ERR_PTR(-ENOMEM);
+	char *page = (char *) __get_free_page(GFP_USER);
+	char *devname;
+
+	dprintk("%s: submounting on %s/%s\n", __FUNCTION__,
+			dentry->d_parent->d_name.name,
+			dentry->d_name.name);
+	if (page == NULL)
+		goto out;
+	devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
+	mnt = (struct vfsmount *)devname;
+	if (IS_ERR(devname))
+		goto free_page;
+	mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata);
+free_page:
+	free_page((unsigned long)page);
+out:
+	dprintk("%s: done\n", __FUNCTION__);
+	return mnt;
+}
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index f0015fa..67391ee 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -23,12 +23,11 @@
 #include <linux/nfs.h>
 #include <linux/nfs2.h>
 #include <linux/nfs_fs.h>
+#include "internal.h"
 
 #define NFSDBG_FACILITY		NFSDBG_XDR
 /* #define NFS_PARANOIA 1 */
 
-extern int			nfs_stat_to_errno(int stat);
-
 /* Mapping from NFS error code to "errno" error code. */
 #define errno_NFSERR_IO		EIO
 
@@ -131,7 +130,8 @@
 	fattr->du.nfs2.blocksize = ntohl(*p++);
 	rdev = ntohl(*p++);
 	fattr->du.nfs2.blocks = ntohl(*p++);
-	fattr->fsid_u.nfs3 = ntohl(*p++);
+	fattr->fsid.major = ntohl(*p++);
+	fattr->fsid.minor = 0;
 	fattr->fileid = ntohl(*p++);
 	p = xdr_decode_time(p, &fattr->atime);
 	p = xdr_decode_time(p, &fattr->mtime);
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 3328787..7322da4 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -172,8 +172,10 @@
 		inode->i_ino, acl, dfacl);
 	spin_lock(&inode->i_lock);
 	__nfs3_forget_cached_acls(NFS_I(inode));
-	nfsi->acl_access = posix_acl_dup(acl);
-	nfsi->acl_default = posix_acl_dup(dfacl);
+	if (!IS_ERR(acl))
+		nfsi->acl_access = posix_acl_dup(acl);
+	if (!IS_ERR(dfacl))
+		nfsi->acl_default = posix_acl_dup(dfacl);
 	spin_unlock(&inode->i_lock);
 }
 
@@ -254,7 +256,9 @@
 			res.acl_access = NULL;
 		}
 	}
-	nfs3_cache_acls(inode, res.acl_access, res.acl_default);
+	nfs3_cache_acls(inode,
+		(res.mask & NFS_ACL)   ? res.acl_access  : ERR_PTR(-EINVAL),
+		(res.mask & NFS_DFACL) ? res.acl_default : ERR_PTR(-EINVAL));
 
 	switch(type) {
 		case ACL_TYPE_ACCESS:
@@ -329,6 +333,7 @@
 	switch (status) {
 		case 0:
 			status = nfs_refresh_inode(inode, &fattr);
+			nfs3_cache_acls(inode, acl, dfacl);
 			break;
 		case -EPFNOSUPPORT:
 		case -EPROTONOSUPPORT:
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index cf186f0..7143b1f 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -20,11 +20,10 @@
 #include <linux/nfs_mount.h>
 
 #include "iostat.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
-extern struct rpc_procinfo nfs3_procedures[];
-
 /* A wrapper to handle the EJUKEBOX error message */
 static int
 nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
@@ -809,8 +808,6 @@
 	return status;
 }
 
-extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int);
-
 static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data)
 {
 	if (nfs3_async_handle_jukebox(task, data->inode))
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index ec23361..0250269 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -22,14 +22,13 @@
 #include <linux/nfs3.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfsacl.h>
+#include "internal.h"
 
 #define NFSDBG_FACILITY		NFSDBG_XDR
 
 /* Mapping from NFS error code to "errno" error code. */
 #define errno_NFSERR_IO		EIO
 
-extern int			nfs_stat_to_errno(int);
-
 /*
  * Declare the space requirements for NFS arguments and replies as
  * number of 32bit-words
@@ -166,7 +165,8 @@
 	if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
 		fattr->rdev = 0;
 
-	p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3);
+	p = xdr_decode_hyper(p, &fattr->fsid.major);
+	fattr->fsid.minor = 0;
 	p = xdr_decode_hyper(p, &fattr->fileid);
 	p = xdr_decode_time3(p, &fattr->atime);
 	p = xdr_decode_time3(p, &fattr->mtime);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 0f5e4e7..9a10286 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -217,6 +217,9 @@
 extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state);
 extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
+extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
+extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
+		struct nfs4_fs_locations *fs_locations, struct page *page);
 
 extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
 extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
@@ -225,6 +228,7 @@
 extern const u32 nfs4_statfs_bitmap[2];
 extern const u32 nfs4_pathconf_bitmap[2];
 extern const u32 nfs4_fsinfo_bitmap[2];
+extern const u32 nfs4_fs_locations_bitmap[2];
 
 /* nfs4renewd.c */
 extern void nfs4_schedule_state_renewal(struct nfs4_client *);
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
new file mode 100644
index 0000000..ea38d27
--- /dev/null
+++ b/fs/nfs/nfs4namespace.c
@@ -0,0 +1,201 @@
+/*
+ * linux/fs/nfs/nfs4namespace.c
+ *
+ * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
+ *
+ * NFSv4 namespace
+ */
+
+#include <linux/config.h>
+
+#include <linux/dcache.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/nfs_fs.h>
+#include <linux/string.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/vfs.h>
+#include <linux/inet.h>
+#include "internal.h"
+
+#define NFSDBG_FACILITY		NFSDBG_VFS
+
+/*
+ * Check if fs_root is valid
+ */
+static inline char *nfs4_pathname_string(struct nfs4_pathname *pathname,
+					 char *buffer, ssize_t buflen)
+{
+	char *end = buffer + buflen;
+	int n;
+
+	*--end = '\0';
+	buflen--;
+
+	n = pathname->ncomponents;
+	while (--n >= 0) {
+		struct nfs4_string *component = &pathname->components[n];
+		buflen -= component->len + 1;
+		if (buflen < 0)
+			goto Elong;
+		end -= component->len;
+		memcpy(end, component->data, component->len);
+		*--end = '/';
+	}
+	return end;
+Elong:
+	return ERR_PTR(-ENAMETOOLONG);
+}
+
+
+/**
+ * nfs_follow_referral - set up mountpoint when hitting a referral on moved error
+ * @mnt_parent - mountpoint of parent directory
+ * @dentry - parent directory
+ * @fspath - fs path returned in fs_locations
+ * @mntpath - mount path to new server
+ * @hostname - hostname of new server
+ * @addr - host addr of new server
+ *
+ */
+static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent,
+					    const struct dentry *dentry,
+					    struct nfs4_fs_locations *locations)
+{
+	struct vfsmount *mnt = ERR_PTR(-ENOENT);
+	struct nfs_clone_mount mountdata = {
+		.sb = mnt_parent->mnt_sb,
+		.dentry = dentry,
+		.authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor,
+	};
+	char *page, *page2;
+	char *path, *fs_path;
+	char *devname;
+	int loc, s;
+
+	if (locations == NULL || locations->nlocations <= 0)
+		goto out;
+
+	dprintk("%s: referral at %s/%s\n", __FUNCTION__,
+		dentry->d_parent->d_name.name, dentry->d_name.name);
+
+	/* Ensure fs path is a prefix of current dentry path */
+	page = (char *) __get_free_page(GFP_USER);
+	if (page == NULL)
+		goto out;
+	page2 = (char *) __get_free_page(GFP_USER);
+	if (page2 == NULL)
+		goto out;
+
+	path = nfs4_path(dentry, page, PAGE_SIZE);
+	if (IS_ERR(path))
+		goto out_free;
+
+	fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE);
+	if (IS_ERR(fs_path))
+		goto out_free;
+
+	if (strncmp(path, fs_path, strlen(fs_path)) != 0) {
+		dprintk("%s: path %s does not begin with fsroot %s\n", __FUNCTION__, path, fs_path);
+		goto out_free;
+	}
+
+	devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE);
+	if (IS_ERR(devname)) {
+		mnt = (struct vfsmount *)devname;
+		goto out_free;
+	}
+
+	loc = 0;
+	while (loc < locations->nlocations && IS_ERR(mnt)) {
+		struct nfs4_fs_location *location = &locations->locations[loc];
+		char *mnt_path;
+
+		if (location == NULL || location->nservers <= 0 ||
+		    location->rootpath.ncomponents == 0) {
+			loc++;
+			continue;
+		}
+
+		mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE);
+		if (IS_ERR(mnt_path)) {
+			loc++;
+			continue;
+		}
+		mountdata.mnt_path = mnt_path;
+
+		s = 0;
+		while (s < location->nservers) {
+			struct sockaddr_in addr = {};
+
+			if (location->servers[s].len <= 0 ||
+			    valid_ipaddr4(location->servers[s].data) < 0) {
+				s++;
+				continue;
+			}
+
+			mountdata.hostname = location->servers[s].data;
+			addr.sin_addr.s_addr = in_aton(mountdata.hostname);
+			addr.sin_family = AF_INET;
+			addr.sin_port = htons(NFS_PORT);
+			mountdata.addr = &addr;
+
+			mnt = vfs_kern_mount(&nfs_referral_nfs4_fs_type, 0, devname, &mountdata);
+			if (!IS_ERR(mnt)) {
+				break;
+			}
+			s++;
+		}
+		loc++;
+	}
+
+out_free:
+	free_page((unsigned long)page);
+	free_page((unsigned long)page2);
+out:
+	dprintk("%s: done\n", __FUNCTION__);
+	return mnt;
+}
+
+/*
+ * nfs_do_refmount - handle crossing a referral on server
+ * @dentry - dentry of referral
+ * @nd - nameidata info
+ *
+ */
+struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry)
+{
+	struct vfsmount *mnt = ERR_PTR(-ENOENT);
+	struct dentry *parent;
+	struct nfs4_fs_locations *fs_locations = NULL;
+	struct page *page;
+	int err;
+
+	/* BUG_ON(IS_ROOT(dentry)); */
+	dprintk("%s: enter\n", __FUNCTION__);
+
+	page = alloc_page(GFP_KERNEL);
+	if (page == NULL)
+		goto out;
+
+	fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
+	if (fs_locations == NULL)
+		goto out_free;
+
+	/* Get locations */
+	parent = dget_parent(dentry);
+	dprintk("%s: getting locations for %s/%s\n", __FUNCTION__, parent->d_name.name, dentry->d_name.name);
+	err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page);
+	dput(parent);
+	if (err != 0 || fs_locations->nlocations <= 0 ||
+	    fs_locations->fs_path.ncomponents <= 0)
+		goto out_free;
+
+	mnt = nfs_follow_referral(mnt_parent, dentry, fs_locations);
+out_free:
+	__free_page(page);
+	kfree(fs_locations);
+out:
+	dprintk("%s: done\n", __FUNCTION__);
+	return mnt;
+}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index d86c0db..b4916b0 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -65,8 +65,6 @@
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
 static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
 static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp);
-extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
-extern struct rpc_procinfo nfs4_procedures[];
 
 /* Prevent leaks of NFSv4 errors into userland */
 int nfs4_map_errors(int err)
@@ -121,6 +119,25 @@
 			0
 };
 
+const u32 nfs4_fs_locations_bitmap[2] = {
+	FATTR4_WORD0_TYPE
+	| FATTR4_WORD0_CHANGE
+	| FATTR4_WORD0_SIZE
+	| FATTR4_WORD0_FSID
+	| FATTR4_WORD0_FILEID
+	| FATTR4_WORD0_FS_LOCATIONS,
+	FATTR4_WORD1_MODE
+	| FATTR4_WORD1_NUMLINKS
+	| FATTR4_WORD1_OWNER
+	| FATTR4_WORD1_OWNER_GROUP
+	| FATTR4_WORD1_RAWDEV
+	| FATTR4_WORD1_SPACE_USED
+	| FATTR4_WORD1_TIME_ACCESS
+	| FATTR4_WORD1_TIME_METADATA
+	| FATTR4_WORD1_TIME_MODIFY
+	| FATTR4_WORD1_MOUNTED_ON_FILEID
+};
+
 static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
 		struct nfs4_readdir_arg *readdir)
 {
@@ -185,15 +202,15 @@
 	spin_unlock(&clp->cl_lock);
 }
 
-static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinfo)
+static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo)
 {
-	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs_inode *nfsi = NFS_I(dir);
 
-	spin_lock(&inode->i_lock);
-	nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
+	spin_lock(&dir->i_lock);
+	nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA;
 	if (cinfo->before == nfsi->change_attr && cinfo->atomic)
 		nfsi->change_attr = cinfo->after;
-	spin_unlock(&inode->i_lock);
+	spin_unlock(&dir->i_lock);
 }
 
 struct nfs4_opendata {
@@ -1331,7 +1348,7 @@
 	return status;
 }
 
-static int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
+int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
 {
 	struct nfs4_exception exception = { };
 	int err;
@@ -1443,6 +1460,50 @@
 	return nfs4_map_errors(status);
 }
 
+/*
+ * Get locations and (maybe) other attributes of a referral.
+ * Note that we'll actually follow the referral later when
+ * we detect fsid mismatch in inode revalidation
+ */
+static int nfs4_get_referral(struct inode *dir, struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+{
+	int status = -ENOMEM;
+	struct page *page = NULL;
+	struct nfs4_fs_locations *locations = NULL;
+	struct dentry dentry = {};
+
+	page = alloc_page(GFP_KERNEL);
+	if (page == NULL)
+		goto out;
+	locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
+	if (locations == NULL)
+		goto out;
+
+	dentry.d_name.name = name->name;
+	dentry.d_name.len = name->len;
+	status = nfs4_proc_fs_locations(dir, &dentry, locations, page);
+	if (status != 0)
+		goto out;
+	/* Make sure server returned a different fsid for the referral */
+	if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
+		dprintk("%s: server did not return a different fsid for a referral at %s\n", __FUNCTION__, name->name);
+		status = -EIO;
+		goto out;
+	}
+
+	memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
+	fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL;
+	if (!fattr->mode)
+		fattr->mode = S_IFDIR;
+	memset(fhandle, 0, sizeof(struct nfs_fh));
+out:
+	if (page)
+		__free_page(page);
+	if (locations)
+		kfree(locations);
+	return status;
+}
+
 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
 {
 	struct nfs4_getattr_arg args = {
@@ -1547,6 +1608,8 @@
 	
 	dprintk("NFS call  lookup %s\n", name->name);
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+	if (status == -NFS4ERR_MOVED)
+		status = nfs4_get_referral(dir, name, fattr, fhandle);
 	dprintk("NFS reply lookup: %d\n", status);
 	return status;
 }
@@ -2008,7 +2071,7 @@
 	if (!status) {
 		update_changeattr(dir, &res.cinfo);
 		nfs_post_op_update_inode(dir, res.dir_attr);
-		nfs_refresh_inode(inode, res.fattr);
+		nfs_post_op_update_inode(inode, res.fattr);
 	}
 
 	return status;
@@ -3570,6 +3633,36 @@
 	return len;
 }
 
+int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry,
+		struct nfs4_fs_locations *fs_locations, struct page *page)
+{
+	struct nfs_server *server = NFS_SERVER(dir);
+	u32 bitmask[2] = {
+		[0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
+		[1] = FATTR4_WORD1_MOUNTED_ON_FILEID,
+	};
+	struct nfs4_fs_locations_arg args = {
+		.dir_fh = NFS_FH(dir),
+		.name = &dentry->d_name,
+		.page = page,
+		.bitmask = bitmask,
+	};
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_FS_LOCATIONS],
+		.rpc_argp = &args,
+		.rpc_resp = fs_locations,
+	};
+	int status;
+
+	dprintk("%s: start\n", __FUNCTION__);
+	fs_locations->fattr.valid = 0;
+	fs_locations->server = server;
+	fs_locations->nlocations = 0;
+	status = rpc_call_sync(server->client, &msg, 0);
+	dprintk("%s: returned status = %d\n", __FUNCTION__, status);
+	return status;
+}
+
 struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
 	.recover_open	= nfs4_open_reclaim,
 	.recover_lock	= nfs4_lock_reclaim,
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 7c5d70e..1750d99 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -411,6 +411,15 @@
 #define NFS4_dec_setacl_sz	(compound_decode_hdr_maxsz + \
 				decode_putfh_maxsz + \
 				op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
+#define NFS4_enc_fs_locations_sz \
+				(compound_encode_hdr_maxsz + \
+				 encode_putfh_maxsz + \
+				 encode_getattr_maxsz)
+#define NFS4_dec_fs_locations_sz \
+				(compound_decode_hdr_maxsz + \
+				 decode_putfh_maxsz + \
+				 op_decode_hdr_maxsz + \
+				 nfs4_fattr_bitmap_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -722,6 +731,13 @@
 			bitmask[1] & nfs4_fsinfo_bitmap[1]);
 }
 
+static int encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask)
+{
+	return encode_getattr_two(xdr,
+				  bitmask[0] & nfs4_fs_locations_bitmap[0],
+				  bitmask[1] & nfs4_fs_locations_bitmap[1]);
+}
+
 static int encode_getfh(struct xdr_stream *xdr)
 {
 	uint32_t *p;
@@ -2003,6 +2019,38 @@
 }
 
 /*
+ * Encode FS_LOCATIONS request
+ */
+static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations_arg *args)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr = {
+		.nops = 3,
+	};
+	struct rpc_auth *auth = req->rq_task->tk_auth;
+	int replen;
+	int status;
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, &hdr);
+	if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
+		goto out;
+	if ((status = encode_lookup(&xdr, args->name)) != 0)
+		goto out;
+	if ((status = encode_fs_locations(&xdr, args->bitmask)) != 0)
+		goto out;
+	/* set up reply
+	 *   toplevel_status + OP_PUTFH + status
+	 *   + OP_LOOKUP + status + OP_GETATTR + status = 7
+	 */
+	replen = (RPC_REPHDRSIZE + auth->au_rslack + 7) << 2;
+	xdr_inline_pages(&req->rq_rcv_buf, replen, &args->page,
+			0, PAGE_SIZE);
+out:
+	return status;
+}
+
+/*
  * START OF "GENERIC" DECODE ROUTINES.
  *   These may look a little ugly since they are imported from a "generic"
  * set of XDR encode/decode routines which are intended to be shared by
@@ -2036,7 +2084,7 @@
 	} \
 } while (0)
 
-static int decode_opaque_inline(struct xdr_stream *xdr, uint32_t *len, char **string)
+static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
 {
 	uint32_t *p;
 
@@ -2087,7 +2135,7 @@
 static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp)
 {
 	uint32_t *p;
-	uint32_t strlen;
+	unsigned int strlen;
 	char *str;
 
 	READ_BUF(12);
@@ -2217,7 +2265,7 @@
 	return 0;
 }
 
-static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fsid *fsid)
+static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
 {
 	uint32_t *p;
 
@@ -2285,6 +2333,22 @@
 	return 0;
 }
 
+static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
+{
+	uint32_t *p;
+
+	*fileid = 0;
+	if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
+		return -EIO;
+	if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
+		READ_BUF(8);
+		READ64(*fileid);
+		bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+	}
+	dprintk("%s: fileid=%Lu\n", __FUNCTION__, (unsigned long long)*fileid);
+	return 0;
+}
+
 static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
 	uint32_t *p;
@@ -2336,6 +2400,116 @@
 	return status;
 }
 
+static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
+{
+	int n;
+	uint32_t *p;
+	int status = 0;
+
+	READ_BUF(4);
+	READ32(n);
+	if (n < 0)
+		goto out_eio;
+	if (n == 0)
+		goto root_path;
+	dprintk("path ");
+	path->ncomponents = 0;
+	while (path->ncomponents < n) {
+		struct nfs4_string *component = &path->components[path->ncomponents];
+		status = decode_opaque_inline(xdr, &component->len, &component->data);
+		if (unlikely(status != 0))
+			goto out_eio;
+		if (path->ncomponents != n)
+			dprintk("/");
+		dprintk("%s", component->data);
+		if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS)
+			path->ncomponents++;
+		else {
+			dprintk("cannot parse %d components in path\n", n);
+			goto out_eio;
+		}
+	}
+out:
+	dprintk("\n");
+	return status;
+root_path:
+/* a root pathname is sent as a zero component4 */
+	path->ncomponents = 1;
+	path->components[0].len=0;
+	path->components[0].data=NULL;
+	dprintk("path /\n");
+	goto out;
+out_eio:
+	dprintk(" status %d", status);
+	status = -EIO;
+	goto out;
+}
+
+static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
+{
+	int n;
+	uint32_t *p;
+	int status = -EIO;
+
+	if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
+		goto out;
+	status = 0;
+	if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
+		goto out;
+	dprintk("%s: fsroot ", __FUNCTION__);
+	status = decode_pathname(xdr, &res->fs_path);
+	if (unlikely(status != 0))
+		goto out;
+	READ_BUF(4);
+	READ32(n);
+	if (n <= 0)
+		goto out_eio;
+	res->nlocations = 0;
+	while (res->nlocations < n) {
+		int m;
+		struct nfs4_fs_location *loc = &res->locations[res->nlocations];
+
+		READ_BUF(4);
+		READ32(m);
+		if (m <= 0)
+			goto out_eio;
+
+		loc->nservers = 0;
+		dprintk("%s: servers ", __FUNCTION__);
+		while (loc->nservers < m) {
+			struct nfs4_string *server = &loc->servers[loc->nservers];
+			status = decode_opaque_inline(xdr, &server->len, &server->data);
+			if (unlikely(status != 0))
+				goto out_eio;
+			dprintk("%s ", server->data);
+			if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS)
+				loc->nservers++;
+			else {
+				int i;
+				dprintk("%s: using first %d of %d servers returned for location %d\n", __FUNCTION__, NFS4_FS_LOCATION_MAXSERVERS, m, res->nlocations);
+				for (i = loc->nservers; i < m; i++) {
+					int len;
+					char *data;
+					status = decode_opaque_inline(xdr, &len, &data);
+					if (unlikely(status != 0))
+						goto out_eio;
+				}
+			}
+		}
+		status = decode_pathname(xdr, &loc->rootpath);
+		if (unlikely(status != 0))
+			goto out_eio;
+		if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES)
+			res->nlocations++;
+	}
+out:
+	dprintk("%s: fs_locations done, error = %d\n", __FUNCTION__, status);
+	return status;
+out_eio:
+	status = -EIO;
+	goto out;
+}
+
 static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
 {
 	uint32_t *p;
@@ -2841,6 +3015,7 @@
 		 bitmap[2] = {0},
 		 type;
 	int status, fmode = 0;
+	uint64_t fileid;
 
 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
 		goto xdr_error;
@@ -2863,10 +3038,14 @@
 		goto xdr_error;
 	if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0)
 		goto xdr_error;
-	if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid_u.nfs4)) != 0)
+	if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid)) != 0)
 		goto xdr_error;
 	if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0)
 		goto xdr_error;
+	if ((status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr,
+						struct nfs4_fs_locations,
+						fattr))) != 0)
+		goto xdr_error;
 	if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0)
 		goto xdr_error;
 	fattr->mode |= fmode;
@@ -2886,6 +3065,10 @@
 		goto xdr_error;
 	if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0)
 		goto xdr_error;
+	if ((status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid)) != 0)
+		goto xdr_error;
+	if (fattr->fileid == 0 && fileid != 0)
+		fattr->fileid = fileid;
 	if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
 		fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4;
 xdr_error:
@@ -3350,8 +3533,7 @@
 					attrlen, recvd);
 			return -EINVAL;
 		}
-		if (attrlen <= *acl_len)
-			xdr_read_pages(xdr, attrlen);
+		xdr_read_pages(xdr, attrlen);
 		*acl_len = attrlen;
 	} else
 		status = -EOPNOTSUPP;
@@ -4211,6 +4393,29 @@
 	return status;
 }
 
+/*
+ * FS_LOCATIONS request
+ */
+static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs_locations *res)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status != 0)
+		goto out;
+	if ((status = decode_putfh(&xdr)) != 0)
+		goto out;
+	if ((status = decode_lookup(&xdr)) != 0)
+		goto out;
+	xdr_enter_page(&xdr, PAGE_SIZE);
+	status = decode_getfattr(&xdr, &res->fattr, res->server);
+out:
+	return status;
+}
+
 uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 {
 	uint32_t bitmap[2] = {0};
@@ -4382,6 +4587,7 @@
   PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
   PROC(GETACL,		enc_getacl,	dec_getacl),
   PROC(SETACL,		enc_setacl,	dec_setacl),
+  PROC(FS_LOCATIONS,	enc_fs_locations, dec_fs_locations),
 };
 
 struct rpc_version		nfs_version4 = {
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 106aca3..d89f6fb 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -325,6 +325,7 @@
 
 /**
  * nfs_scan_list - Scan a list for matching requests
+ * @nfsi: NFS inode
  * @head: One of the NFS inode request lists
  * @dst: Destination list
  * @idx_start: lower bound of page->index to scan
@@ -336,14 +337,15 @@
  * The requests are *not* checked to ensure that they form a contiguous set.
  * You must be holding the inode's req_lock when calling this function
  */
-int
-nfs_scan_list(struct list_head *head, struct list_head *dst,
-	      unsigned long idx_start, unsigned int npages)
+int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head,
+		struct list_head *dst, unsigned long idx_start,
+		unsigned int npages)
 {
-	struct list_head	*pos, *tmp;
-	struct nfs_page		*req;
-	unsigned long		idx_end;
-	int			res;
+	struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
+	struct nfs_page *req;
+	unsigned long idx_end;
+	int found, i;
+	int res;
 
 	res = 0;
 	if (npages == 0)
@@ -351,25 +353,32 @@
 	else
 		idx_end = idx_start + npages - 1;
 
-	list_for_each_safe(pos, tmp, head) {
-
-		req = nfs_list_entry(pos);
-
-		if (req->wb_index < idx_start)
-			continue;
-		if (req->wb_index > idx_end)
+	for (;;) {
+		found = radix_tree_gang_lookup(&nfsi->nfs_page_tree,
+				(void **)&pgvec[0], idx_start,
+				NFS_SCAN_MAXENTRIES);
+		if (found <= 0)
 			break;
+		for (i = 0; i < found; i++) {
+			req = pgvec[i];
+			if (req->wb_index > idx_end)
+				goto out;
+			idx_start = req->wb_index + 1;
+			if (req->wb_list_head != head)
+				continue;
+			if (nfs_set_page_writeback_locked(req)) {
+				nfs_list_remove_request(req);
+				nfs_list_add_request(req, dst);
+				res++;
+			}
+		}
 
-		if (!nfs_set_page_writeback_locked(req))
-			continue;
-		nfs_list_remove_request(req);
-		nfs_list_add_request(req, dst);
-		res++;
 	}
+out:
 	return res;
 }
 
-int nfs_init_nfspagecache(void)
+int __init nfs_init_nfspagecache(void)
 {
 	nfs_page_cachep = kmem_cache_create("nfs_page",
 					    sizeof(struct nfs_page),
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 9dd85ca..b3899ea 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -44,11 +44,10 @@
 #include <linux/nfs_page.h>
 #include <linux/lockd/bind.h>
 #include <linux/smp_lock.h>
+#include "internal.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
-extern struct rpc_procinfo nfs_procedures[];
-
 /*
  * Bare-bones access to getattr: this is for nfs_read_super.
  */
@@ -611,8 +610,6 @@
 	return 0;
 }
 
-extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int);
-
 static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
 {
 	if (task->tk_status >= 0) {
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 624ca71..32cf377 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -51,14 +51,11 @@
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
-		if (pagecount < NFS_PAGEVEC_SIZE)
-			p->pagevec = &p->page_array[0];
+		if (pagecount <= ARRAY_SIZE(p->page_array))
+			p->pagevec = p->page_array;
 		else {
-			size_t size = ++pagecount * sizeof(struct page *);
-			p->pagevec = kmalloc(size, GFP_NOFS);
-			if (p->pagevec) {
-				memset(p->pagevec, 0, size);
-			} else {
+			p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS);
+			if (!p->pagevec) {
 				mempool_free(p, nfs_rdata_mempool);
 				p = NULL;
 			}
@@ -104,6 +101,28 @@
 	return 0;
 }
 
+static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
+{
+	unsigned int remainder = data->args.count - data->res.count;
+	unsigned int base = data->args.pgbase + data->res.count;
+	unsigned int pglen;
+	struct page **pages;
+
+	if (data->res.eof == 0 || remainder == 0)
+		return;
+	/*
+	 * Note: "remainder" can never be negative, since we check for
+	 * 	this in the XDR code.
+	 */
+	pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
+	base &= ~PAGE_CACHE_MASK;
+	pglen = PAGE_CACHE_SIZE - base;
+	if (pglen < remainder)
+		memclear_highpage_flush(*pages, base, pglen);
+	else
+		memclear_highpage_flush(*pages, base, remainder);
+}
+
 /*
  * Read a page synchronously.
  */
@@ -177,11 +196,9 @@
 	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
 	spin_unlock(&inode->i_lock);
 
-	if (count)
-		memclear_highpage_flush(page, rdata->args.pgbase, count);
-	SetPageUptodate(page);
-	if (PageError(page))
-		ClearPageError(page);
+	nfs_readpage_truncate_uninitialised_page(rdata);
+	if (rdata->res.eof || rdata->res.count == rdata->args.count)
+		SetPageUptodate(page);
 	result = 0;
 
 io_error:
@@ -436,20 +453,12 @@
 	struct nfs_page *req = data->req;
 	struct page *page = req->wb_page;
  
+	if (likely(task->tk_status >= 0))
+		nfs_readpage_truncate_uninitialised_page(data);
+	else
+		SetPageError(page);
 	if (nfs_readpage_result(task, data) != 0)
 		return;
-	if (task->tk_status >= 0) {
-		unsigned int request = data->args.count;
-		unsigned int result = data->res.count;
-
-		if (result < request) {
-			memclear_highpage_flush(page,
-						data->args.pgbase + result,
-						request - result);
-		}
-	} else
-		SetPageError(page);
-
 	if (atomic_dec_and_test(&req->wb_complete)) {
 		if (!PageError(page))
 			SetPageUptodate(page);
@@ -462,6 +471,40 @@
 	.rpc_release = nfs_readdata_release,
 };
 
+static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data)
+{
+	unsigned int count = data->res.count;
+	unsigned int base = data->args.pgbase;
+	struct page **pages;
+
+	if (unlikely(count == 0))
+		return;
+	pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
+	base &= ~PAGE_CACHE_MASK;
+	count += base;
+	for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
+		SetPageUptodate(*pages);
+	/*
+	 * Was this an eof or a short read? If the latter, don't mark the page
+	 * as uptodate yet.
+	 */
+	if (count > 0 && (data->res.eof || data->args.count == data->res.count))
+		SetPageUptodate(*pages);
+}
+
+static void nfs_readpage_set_pages_error(struct nfs_read_data *data)
+{
+	unsigned int count = data->args.count;
+	unsigned int base = data->args.pgbase;
+	struct page **pages;
+
+	pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];
+	base &= ~PAGE_CACHE_MASK;
+	count += base;
+	for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)
+		SetPageError(*pages);
+}
+
 /*
  * This is the callback from RPC telling us whether a reply was
  * received or some error occurred (timeout or socket shutdown).
@@ -469,27 +512,24 @@
 static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
 {
 	struct nfs_read_data *data = calldata;
-	unsigned int count = data->res.count;
 
+	/*
+	 * Note: nfs_readpage_result may change the values of
+	 * data->args. In the multi-page case, we therefore need
+	 * to ensure that we call the next nfs_readpage_set_page_uptodate()
+	 * first in the multi-page case.
+	 */
+	if (likely(task->tk_status >= 0)) {
+		nfs_readpage_truncate_uninitialised_page(data);
+		nfs_readpage_set_pages_uptodate(data);
+	} else
+		nfs_readpage_set_pages_error(data);
 	if (nfs_readpage_result(task, data) != 0)
 		return;
 	while (!list_empty(&data->pages)) {
 		struct nfs_page *req = nfs_list_entry(data->pages.next);
-		struct page *page = req->wb_page;
-		nfs_list_remove_request(req);
 
-		if (task->tk_status >= 0) {
-			if (count < PAGE_CACHE_SIZE) {
-				if (count < req->wb_bytes)
-					memclear_highpage_flush(page,
-							req->wb_pgbase + count,
-							req->wb_bytes - count);
-				count = 0;
-			} else
-				count -= PAGE_CACHE_SIZE;
-			SetPageUptodate(page);
-		} else
-			SetPageError(page);
+		nfs_list_remove_request(req);
 		nfs_readpage_release(req);
 	}
 }
@@ -654,7 +694,7 @@
 	return ret;
 }
 
-int nfs_init_readpagecache(void)
+int __init nfs_init_readpagecache(void)
 {
 	nfs_rdata_cachep = kmem_cache_create("nfs_read_data",
 					     sizeof(struct nfs_read_data),
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
new file mode 100644
index 0000000..e8a9bee
--- /dev/null
+++ b/fs/nfs/super.c
@@ -0,0 +1,1537 @@
+/*
+ *  linux/fs/nfs/super.c
+ *
+ *  Copyright (C) 1992  Rick Sladkey
+ *
+ *  nfs superblock handling functions
+ *
+ *  Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some
+ *  experimental NFS changes. Modularisation taken straight from SYS5 fs.
+ *
+ *  Change to nfs_read_super() to permit NFS mounts to multi-homed hosts.
+ *  J.S.Peatfield@damtp.cam.ac.uk
+ *
+ *  Split from inode.c by David Howells <dhowells@redhat.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/time.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/stats.h>
+#include <linux/sunrpc/metrics.h>
+#include <linux/nfs_fs.h>
+#include <linux/nfs_mount.h>
+#include <linux/nfs4_mount.h>
+#include <linux/lockd/bind.h>
+#include <linux/smp_lock.h>
+#include <linux/seq_file.h>
+#include <linux/mount.h>
+#include <linux/nfs_idmap.h>
+#include <linux/vfs.h>
+#include <linux/inet.h>
+#include <linux/nfs_xdr.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "nfs4_fs.h"
+#include "callback.h"
+#include "delegation.h"
+#include "iostat.h"
+#include "internal.h"
+
+#define NFSDBG_FACILITY		NFSDBG_VFS
+
+/* Maximum number of readahead requests
+ * FIXME: this should really be a sysctl so that users may tune it to suit
+ *        their needs. People that do NFS over a slow network, might for
+ *        instance want to reduce it to something closer to 1 for improved
+ *        interactive response.
+ */
+#define NFS_MAX_READAHEAD	(RPC_DEF_SLOT_TABLE - 1)
+
+/*
+ * RPC cruft for NFS
+ */
+static struct rpc_version * nfs_version[] = {
+	NULL,
+	NULL,
+	&nfs_version2,
+#if defined(CONFIG_NFS_V3)
+	&nfs_version3,
+#elif defined(CONFIG_NFS_V4)
+	NULL,
+#endif
+#if defined(CONFIG_NFS_V4)
+	&nfs_version4,
+#endif
+};
+
+static struct rpc_program nfs_program = {
+	.name			= "nfs",
+	.number			= NFS_PROGRAM,
+	.nrvers			= ARRAY_SIZE(nfs_version),
+	.version		= nfs_version,
+	.stats			= &nfs_rpcstat,
+	.pipe_dir_name		= "/nfs",
+};
+
+struct rpc_stat nfs_rpcstat = {
+	.program		= &nfs_program
+};
+
+
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_stat		nfsacl_rpcstat = { &nfsacl_program };
+static struct rpc_version *	nfsacl_version[] = {
+	[3]			= &nfsacl_version3,
+};
+
+struct rpc_program		nfsacl_program = {
+	.name =			"nfsacl",
+	.number =		NFS_ACL_PROGRAM,
+	.nrvers =		ARRAY_SIZE(nfsacl_version),
+	.version =		nfsacl_version,
+	.stats =		&nfsacl_rpcstat,
+};
+#endif  /* CONFIG_NFS_V3_ACL */
+
+static void nfs_umount_begin(struct vfsmount *, int);
+static int  nfs_statfs(struct dentry *, struct kstatfs *);
+static int  nfs_show_options(struct seq_file *, struct vfsmount *);
+static int  nfs_show_stats(struct seq_file *, struct vfsmount *);
+static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);
+static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
+		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static void nfs_kill_super(struct super_block *);
+
+static struct file_system_type nfs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "nfs",
+	.get_sb		= nfs_get_sb,
+	.kill_sb	= nfs_kill_super,
+	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type clone_nfs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "nfs",
+	.get_sb		= nfs_clone_nfs_sb,
+	.kill_sb	= nfs_kill_super,
+	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct super_operations nfs_sops = {
+	.alloc_inode	= nfs_alloc_inode,
+	.destroy_inode	= nfs_destroy_inode,
+	.write_inode	= nfs_write_inode,
+	.statfs		= nfs_statfs,
+	.clear_inode	= nfs_clear_inode,
+	.umount_begin	= nfs_umount_begin,
+	.show_options	= nfs_show_options,
+	.show_stats	= nfs_show_stats,
+};
+
+#ifdef CONFIG_NFS_V4
+static int nfs4_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
+		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
+		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);
+static void nfs4_kill_super(struct super_block *sb);
+
+static struct file_system_type nfs4_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "nfs4",
+	.get_sb		= nfs4_get_sb,
+	.kill_sb	= nfs4_kill_super,
+	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type clone_nfs4_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "nfs4",
+	.get_sb		= nfs_clone_nfs4_sb,
+	.kill_sb	= nfs4_kill_super,
+	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+struct file_system_type nfs_referral_nfs4_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= "nfs4",
+	.get_sb		= nfs_referral_nfs4_sb,
+	.kill_sb	= nfs4_kill_super,
+	.fs_flags	= FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,
+};
+
+static struct super_operations nfs4_sops = {
+	.alloc_inode	= nfs_alloc_inode,
+	.destroy_inode	= nfs_destroy_inode,
+	.write_inode	= nfs_write_inode,
+	.statfs		= nfs_statfs,
+	.clear_inode	= nfs4_clear_inode,
+	.umount_begin	= nfs_umount_begin,
+	.show_options	= nfs_show_options,
+	.show_stats	= nfs_show_stats,
+};
+#endif
+
+#ifdef CONFIG_NFS_V4
+static const int nfs_set_port_min = 0;
+static const int nfs_set_port_max = 65535;
+
+static int param_set_port(const char *val, struct kernel_param *kp)
+{
+	char *endp;
+	int num = simple_strtol(val, &endp, 0);
+	if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max)
+		return -EINVAL;
+	*((int *)kp->arg) = num;
+	return 0;
+}
+
+module_param_call(callback_tcpport, param_set_port, param_get_int,
+		 &nfs_callback_set_tcpport, 0644);
+#endif
+
+#ifdef CONFIG_NFS_V4
+static int param_set_idmap_timeout(const char *val, struct kernel_param *kp)
+{
+	char *endp;
+	int num = simple_strtol(val, &endp, 0);
+	int jif = num * HZ;
+	if (endp == val || *endp || num < 0 || jif < num)
+		return -EINVAL;
+	*((int *)kp->arg) = jif;
+	return 0;
+}
+
+module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int,
+		 &nfs_idmap_cache_timeout, 0644);
+#endif
+
+/*
+ * Register the NFS filesystems
+ */
+int __init register_nfs_fs(void)
+{
+	int ret;
+
+        ret = register_filesystem(&nfs_fs_type);
+	if (ret < 0)
+		goto error_0;
+
+#ifdef CONFIG_NFS_V4
+	ret = nfs_register_sysctl();
+	if (ret < 0)
+		goto error_1;
+	ret = register_filesystem(&nfs4_fs_type);
+	if (ret < 0)
+		goto error_2;
+#endif
+	return 0;
+
+#ifdef CONFIG_NFS_V4
+error_2:
+	nfs_unregister_sysctl();
+error_1:
+	unregister_filesystem(&nfs_fs_type);
+#endif
+error_0:
+	return ret;
+}
+
+/*
+ * Unregister the NFS filesystems
+ */
+void __exit unregister_nfs_fs(void)
+{
+#ifdef CONFIG_NFS_V4
+	unregister_filesystem(&nfs4_fs_type);
+	nfs_unregister_sysctl();
+#endif
+	unregister_filesystem(&nfs_fs_type);
+}
+
+/*
+ * Deliver file system statistics to userspace
+ */
+static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	struct super_block *sb = dentry->d_sb;
+	struct nfs_server *server = NFS_SB(sb);
+	unsigned char blockbits;
+	unsigned long blockres;
+	struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode);
+	struct nfs_fattr fattr;
+	struct nfs_fsstat res = {
+			.fattr = &fattr,
+	};
+	int error;
+
+	lock_kernel();
+
+	error = server->rpc_ops->statfs(server, rootfh, &res);
+	buf->f_type = NFS_SUPER_MAGIC;
+	if (error < 0)
+		goto out_err;
+
+	/*
+	 * Current versions of glibc do not correctly handle the
+	 * case where f_frsize != f_bsize.  Eventually we want to
+	 * report the value of wtmult in this field.
+	 */
+	buf->f_frsize = sb->s_blocksize;
+
+	/*
+	 * On most *nix systems, f_blocks, f_bfree, and f_bavail
+	 * are reported in units of f_frsize.  Linux hasn't had
+	 * an f_frsize field in its statfs struct until recently,
+	 * thus historically Linux's sys_statfs reports these
+	 * fields in units of f_bsize.
+	 */
+	buf->f_bsize = sb->s_blocksize;
+	blockbits = sb->s_blocksize_bits;
+	blockres = (1 << blockbits) - 1;
+	buf->f_blocks = (res.tbytes + blockres) >> blockbits;
+	buf->f_bfree = (res.fbytes + blockres) >> blockbits;
+	buf->f_bavail = (res.abytes + blockres) >> blockbits;
+
+	buf->f_files = res.tfiles;
+	buf->f_ffree = res.afiles;
+
+	buf->f_namelen = server->namelen;
+ out:
+	unlock_kernel();
+	return 0;
+
+ out_err:
+	dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);
+	buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
+	goto out;
+
+}
+
+static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour)
+{
+	static struct {
+		rpc_authflavor_t flavour;
+		const char *str;
+	} sec_flavours[] = {
+		{ RPC_AUTH_NULL, "null" },
+		{ RPC_AUTH_UNIX, "sys" },
+		{ RPC_AUTH_GSS_KRB5, "krb5" },
+		{ RPC_AUTH_GSS_KRB5I, "krb5i" },
+		{ RPC_AUTH_GSS_KRB5P, "krb5p" },
+		{ RPC_AUTH_GSS_LKEY, "lkey" },
+		{ RPC_AUTH_GSS_LKEYI, "lkeyi" },
+		{ RPC_AUTH_GSS_LKEYP, "lkeyp" },
+		{ RPC_AUTH_GSS_SPKM, "spkm" },
+		{ RPC_AUTH_GSS_SPKMI, "spkmi" },
+		{ RPC_AUTH_GSS_SPKMP, "spkmp" },
+		{ -1, "unknown" }
+	};
+	int i;
+
+	for (i=0; sec_flavours[i].flavour != -1; i++) {
+		if (sec_flavours[i].flavour == flavour)
+			break;
+	}
+	return sec_flavours[i].str;
+}
+
+/*
+ * Describe the mount options in force on this server representation
+ */
+static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults)
+{
+	static struct proc_nfs_info {
+		int flag;
+		char *str;
+		char *nostr;
+	} nfs_info[] = {
+		{ NFS_MOUNT_SOFT, ",soft", ",hard" },
+		{ NFS_MOUNT_INTR, ",intr", "" },
+		{ NFS_MOUNT_NOCTO, ",nocto", "" },
+		{ NFS_MOUNT_NOAC, ",noac", "" },
+		{ NFS_MOUNT_NONLM, ",nolock", "" },
+		{ NFS_MOUNT_NOACL, ",noacl", "" },
+		{ 0, NULL, NULL }
+	};
+	struct proc_nfs_info *nfs_infop;
+	char buf[12];
+	char *proto;
+
+	seq_printf(m, ",vers=%d", nfss->rpc_ops->version);
+	seq_printf(m, ",rsize=%d", nfss->rsize);
+	seq_printf(m, ",wsize=%d", nfss->wsize);
+	if (nfss->acregmin != 3*HZ || showdefaults)
+		seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
+	if (nfss->acregmax != 60*HZ || showdefaults)
+		seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
+	if (nfss->acdirmin != 30*HZ || showdefaults)
+		seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
+	if (nfss->acdirmax != 60*HZ || showdefaults)
+		seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
+	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
+		if (nfss->flags & nfs_infop->flag)
+			seq_puts(m, nfs_infop->str);
+		else
+			seq_puts(m, nfs_infop->nostr);
+	}
+	switch (nfss->client->cl_xprt->prot) {
+		case IPPROTO_TCP:
+			proto = "tcp";
+			break;
+		case IPPROTO_UDP:
+			proto = "udp";
+			break;
+		default:
+			snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot);
+			proto = buf;
+	}
+	seq_printf(m, ",proto=%s", proto);
+	seq_printf(m, ",timeo=%lu", 10U * nfss->retrans_timeo / HZ);
+	seq_printf(m, ",retrans=%u", nfss->retrans_count);
+	seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));
+}
+
+/*
+ * Describe the mount options on this VFS mountpoint
+ */
+static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+
+	nfs_show_mount_options(m, nfss, 0);
+
+	seq_puts(m, ",addr=");
+	seq_escape(m, nfss->hostname, " \t\n\\");
+
+	return 0;
+}
+
+/*
+ * Present statistical information for this VFS mountpoint
+ */
+static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
+{
+	int i, cpu;
+	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);
+	struct rpc_auth *auth = nfss->client->cl_auth;
+	struct nfs_iostats totals = { };
+
+	seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS);
+
+	/*
+	 * Display all mount option settings
+	 */
+	seq_printf(m, "\n\topts:\t");
+	seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw");
+	seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : "");
+	seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : "");
+	seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : "");
+	nfs_show_mount_options(m, nfss, 1);
+
+	seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ);
+
+	seq_printf(m, "\n\tcaps:\t");
+	seq_printf(m, "caps=0x%x", nfss->caps);
+	seq_printf(m, ",wtmult=%d", nfss->wtmult);
+	seq_printf(m, ",dtsize=%d", nfss->dtsize);
+	seq_printf(m, ",bsize=%d", nfss->bsize);
+	seq_printf(m, ",namelen=%d", nfss->namelen);
+
+#ifdef CONFIG_NFS_V4
+	if (nfss->rpc_ops->version == 4) {
+		seq_printf(m, "\n\tnfsv4:\t");
+		seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]);
+		seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]);
+		seq_printf(m, ",acl=0x%x", nfss->acl_bitmask);
+	}
+#endif
+
+	/*
+	 * Display security flavor in effect for this mount
+	 */
+	seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor);
+	if (auth->au_flavor)
+		seq_printf(m, ",pseudoflavor=%d", auth->au_flavor);
+
+	/*
+	 * Display superblock I/O counters
+	 */
+	for_each_possible_cpu(cpu) {
+		struct nfs_iostats *stats;
+
+		preempt_disable();
+		stats = per_cpu_ptr(nfss->io_stats, cpu);
+
+		for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
+			totals.events[i] += stats->events[i];
+		for (i = 0; i < __NFSIOS_BYTESMAX; i++)
+			totals.bytes[i] += stats->bytes[i];
+
+		preempt_enable();
+	}
+
+	seq_printf(m, "\n\tevents:\t");
+	for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
+		seq_printf(m, "%lu ", totals.events[i]);
+	seq_printf(m, "\n\tbytes:\t");
+	for (i = 0; i < __NFSIOS_BYTESMAX; i++)
+		seq_printf(m, "%Lu ", totals.bytes[i]);
+	seq_printf(m, "\n");
+
+	rpc_print_iostats(m, nfss->client);
+
+	return 0;
+}
+
+/*
+ * Begin unmount by attempting to remove all automounted mountpoints we added
+ * in response to traversals
+ */
+static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
+{
+	struct nfs_server *server;
+	struct rpc_clnt	*rpc;
+
+	shrink_submounts(vfsmnt, &nfs_automount_list);
+	if (!(flags & MNT_FORCE))
+		return;
+	/* -EIO all pending I/O */
+	server = NFS_SB(vfsmnt->mnt_sb);
+	rpc = server->client;
+	if (!IS_ERR(rpc))
+		rpc_killall_tasks(rpc);
+	rpc = server->client_acl;
+	if (!IS_ERR(rpc))
+		rpc_killall_tasks(rpc);
+}
+
+/*
+ * Obtain the root inode of the file system.
+ */
+static struct inode *
+nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo)
+{
+	struct nfs_server	*server = NFS_SB(sb);
+	int			error;
+
+	error = server->rpc_ops->getroot(server, rootfh, fsinfo);
+	if (error < 0) {
+		dprintk("nfs_get_root: getattr error = %d\n", -error);
+		return ERR_PTR(error);
+	}
+
+	server->fsid = fsinfo->fattr->fsid;
+	return nfs_fhget(sb, rootfh, fsinfo->fattr);
+}
+
+/*
+ * Do NFS version-independent mount processing, and sanity checking
+ */
+static int
+nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor)
+{
+	struct nfs_server	*server;
+	struct inode		*root_inode;
+	struct nfs_fattr	fattr;
+	struct nfs_fsinfo	fsinfo = {
+					.fattr = &fattr,
+				};
+	struct nfs_pathconf pathinfo = {
+			.fattr = &fattr,
+	};
+	int no_root_error = 0;
+	unsigned long max_rpc_payload;
+
+	/* We probably want something more informative here */
+	snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
+
+	server = NFS_SB(sb);
+
+	sb->s_magic      = NFS_SUPER_MAGIC;
+
+	server->io_stats = nfs_alloc_iostats();
+	if (server->io_stats == NULL)
+		return -ENOMEM;
+
+	root_inode = nfs_get_root(sb, &server->fh, &fsinfo);
+	/* Did getting the root inode fail? */
+	if (IS_ERR(root_inode)) {
+		no_root_error = PTR_ERR(root_inode);
+		goto out_no_root;
+	}
+	sb->s_root = d_alloc_root(root_inode);
+	if (!sb->s_root) {
+		no_root_error = -ENOMEM;
+		goto out_no_root;
+	}
+	sb->s_root->d_op = server->rpc_ops->dentry_ops;
+
+	/* mount time stamp, in seconds */
+	server->mount_time = jiffies;
+
+	/* Get some general file system info */
+	if (server->namelen == 0 &&
+	    server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)
+		server->namelen = pathinfo.max_namelen;
+	/* Work out a lot of parameters */
+	if (server->rsize == 0)
+		server->rsize = nfs_block_size(fsinfo.rtpref, NULL);
+	if (server->wsize == 0)
+		server->wsize = nfs_block_size(fsinfo.wtpref, NULL);
+
+	if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)
+		server->rsize = nfs_block_size(fsinfo.rtmax, NULL);
+	if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
+		server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
+
+	max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
+	if (server->rsize > max_rpc_payload)
+		server->rsize = max_rpc_payload;
+	if (server->rsize > NFS_MAX_FILE_IO_SIZE)
+		server->rsize = NFS_MAX_FILE_IO_SIZE;
+	server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+	if (server->wsize > max_rpc_payload)
+		server->wsize = max_rpc_payload;
+	if (server->wsize > NFS_MAX_FILE_IO_SIZE)
+		server->wsize = NFS_MAX_FILE_IO_SIZE;
+	server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+
+	if (sb->s_blocksize == 0)
+		sb->s_blocksize = nfs_block_bits(server->wsize,
+							 &sb->s_blocksize_bits);
+	server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);
+
+	server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);
+	if (server->dtsize > PAGE_CACHE_SIZE)
+		server->dtsize = PAGE_CACHE_SIZE;
+	if (server->dtsize > server->rsize)
+		server->dtsize = server->rsize;
+
+	if (server->flags & NFS_MOUNT_NOAC) {
+		server->acregmin = server->acregmax = 0;
+		server->acdirmin = server->acdirmax = 0;
+		sb->s_flags |= MS_SYNCHRONOUS;
+	}
+	server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;
+
+	nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
+
+	server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
+	server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
+
+	/* We're airborne Set socket buffersize */
+	rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
+	return 0;
+	/* Yargs. It didn't work out. */
+out_no_root:
+	dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error);
+	if (!IS_ERR(root_inode))
+		iput(root_inode);
+	return no_root_error;
+}
+
+/*
+ * Initialise the timeout values for a connection
+ */
+static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans)
+{
+	to->to_initval = timeo * HZ / 10;
+	to->to_retries = retrans;
+	if (!to->to_retries)
+		to->to_retries = 2;
+
+	switch (proto) {
+	case IPPROTO_TCP:
+		if (!to->to_initval)
+			to->to_initval = 60 * HZ;
+		if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
+			to->to_initval = NFS_MAX_TCP_TIMEOUT;
+		to->to_increment = to->to_initval;
+		to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
+		to->to_exponential = 0;
+		break;
+	case IPPROTO_UDP:
+	default:
+		if (!to->to_initval)
+			to->to_initval = 11 * HZ / 10;
+		if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
+			to->to_initval = NFS_MAX_UDP_TIMEOUT;
+		to->to_maxval = NFS_MAX_UDP_TIMEOUT;
+		to->to_exponential = 1;
+		break;
+	}
+}
+
+/*
+ * Create an RPC client handle.
+ */
+static struct rpc_clnt *
+nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
+{
+	struct rpc_timeout	timeparms;
+	struct rpc_xprt		*xprt = NULL;
+	struct rpc_clnt		*clnt = NULL;
+	int			proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
+
+	nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans);
+
+	server->retrans_timeo = timeparms.to_initval;
+	server->retrans_count = timeparms.to_retries;
+
+	/* create transport and client */
+	xprt = xprt_create_proto(proto, &server->addr, &timeparms);
+	if (IS_ERR(xprt)) {
+		dprintk("%s: cannot create RPC transport. Error = %ld\n",
+				__FUNCTION__, PTR_ERR(xprt));
+		return (struct rpc_clnt *)xprt;
+	}
+	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
+				 server->rpc_ops->version, data->pseudoflavor);
+	if (IS_ERR(clnt)) {
+		dprintk("%s: cannot create RPC client. Error = %ld\n",
+				__FUNCTION__, PTR_ERR(xprt));
+		goto out_fail;
+	}
+
+	clnt->cl_intr     = 1;
+	clnt->cl_softrtry = 1;
+
+	return clnt;
+
+out_fail:
+	return clnt;
+}
+
+/*
+ * Clone a server record
+ */
+static struct nfs_server *nfs_clone_server(struct super_block *sb, struct nfs_clone_mount *data)
+{
+	struct nfs_server *server = NFS_SB(sb);
+	struct nfs_server *parent = NFS_SB(data->sb);
+	struct inode *root_inode;
+	struct nfs_fsinfo fsinfo;
+	void *err = ERR_PTR(-ENOMEM);
+
+	sb->s_op = data->sb->s_op;
+	sb->s_blocksize = data->sb->s_blocksize;
+	sb->s_blocksize_bits = data->sb->s_blocksize_bits;
+	sb->s_maxbytes = data->sb->s_maxbytes;
+
+	server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
+	server->io_stats = nfs_alloc_iostats();
+	if (server->io_stats == NULL)
+		goto out;
+
+	server->client = rpc_clone_client(parent->client);
+	if (IS_ERR((err = server->client)))
+		goto out;
+
+	if (!IS_ERR(parent->client_sys)) {
+		server->client_sys = rpc_clone_client(parent->client_sys);
+		if (IS_ERR((err = server->client_sys)))
+			goto out;
+	}
+	if (!IS_ERR(parent->client_acl)) {
+		server->client_acl = rpc_clone_client(parent->client_acl);
+		if (IS_ERR((err = server->client_acl)))
+			goto out;
+	}
+	root_inode = nfs_fhget(sb, data->fh, data->fattr);
+	if (!root_inode)
+		goto out;
+	sb->s_root = d_alloc_root(root_inode);
+	if (!sb->s_root)
+		goto out_put_root;
+	fsinfo.fattr = data->fattr;
+	if (NFS_PROTO(root_inode)->fsinfo(server, data->fh, &fsinfo) == 0)
+		nfs_super_set_maxbytes(sb, fsinfo.maxfilesize);
+	sb->s_root->d_op = server->rpc_ops->dentry_ops;
+	sb->s_flags |= MS_ACTIVE;
+	return server;
+out_put_root:
+	iput(root_inode);
+out:
+	return err;
+}
+
+/*
+ * Copy an existing superblock and attach revised data
+ */
+static int nfs_clone_generic_sb(struct nfs_clone_mount *data,
+		struct super_block *(*fill_sb)(struct nfs_server *, struct nfs_clone_mount *),
+		struct nfs_server *(*fill_server)(struct super_block *, struct nfs_clone_mount *),
+		struct vfsmount *mnt)
+{
+	struct nfs_server *server;
+	struct nfs_server *parent = NFS_SB(data->sb);
+	struct super_block *sb = ERR_PTR(-EINVAL);
+	char *hostname;
+	int error = -ENOMEM;
+	int len;
+
+	server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
+	if (server == NULL)
+		goto out_err;
+	memcpy(server, parent, sizeof(*server));
+	hostname = (data->hostname != NULL) ? data->hostname : parent->hostname;
+	len = strlen(hostname) + 1;
+	server->hostname = kmalloc(len, GFP_KERNEL);
+	if (server->hostname == NULL)
+		goto free_server;
+	memcpy(server->hostname, hostname, len);
+	error = rpciod_up();
+	if (error != 0)
+		goto free_hostname;
+
+	sb = fill_sb(server, data);
+	if (IS_ERR(sb)) {
+		error = PTR_ERR(sb);
+		goto kill_rpciod;
+	}
+		
+	if (sb->s_root)
+		goto out_rpciod_down;
+
+	server = fill_server(sb, data);
+	if (IS_ERR(server)) {
+		error = PTR_ERR(server);
+		goto out_deactivate;
+	}
+	return simple_set_mnt(mnt, sb);
+out_deactivate:
+	up_write(&sb->s_umount);
+	deactivate_super(sb);
+	return error;
+out_rpciod_down:
+	rpciod_down();
+	kfree(server->hostname);
+	kfree(server);
+	return simple_set_mnt(mnt, sb);
+kill_rpciod:
+	rpciod_down();
+free_hostname:
+	kfree(server->hostname);
+free_server:
+	kfree(server);
+out_err:
+	return error;
+}
+
+/*
+ * Set up an NFS2/3 superblock
+ *
+ * The way this works is that the mount process passes a structure
+ * in the data argument which contains the server's IP address
+ * and the root file handle obtained from the server's mount
+ * daemon. We stash these away in the private superblock fields.
+ */
+static int
+nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
+{
+	struct nfs_server	*server;
+	rpc_authflavor_t	authflavor;
+
+	server           = NFS_SB(sb);
+	sb->s_blocksize_bits = 0;
+	sb->s_blocksize = 0;
+	if (data->bsize)
+		sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);
+	if (data->rsize)
+		server->rsize = nfs_block_size(data->rsize, NULL);
+	if (data->wsize)
+		server->wsize = nfs_block_size(data->wsize, NULL);
+	server->flags    = data->flags & NFS_MOUNT_FLAGMASK;
+
+	server->acregmin = data->acregmin*HZ;
+	server->acregmax = data->acregmax*HZ;
+	server->acdirmin = data->acdirmin*HZ;
+	server->acdirmax = data->acdirmax*HZ;
+
+	/* Start lockd here, before we might error out */
+	if (!(server->flags & NFS_MOUNT_NONLM))
+		lockd_up();
+
+	server->namelen  = data->namlen;
+	server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);
+	if (!server->hostname)
+		return -ENOMEM;
+	strcpy(server->hostname, data->hostname);
+
+	/* Check NFS protocol revision and initialize RPC op vector
+	 * and file handle pool. */
+#ifdef CONFIG_NFS_V3
+	if (server->flags & NFS_MOUNT_VER3) {
+		server->rpc_ops = &nfs_v3_clientops;
+		server->caps |= NFS_CAP_READDIRPLUS;
+	} else {
+		server->rpc_ops = &nfs_v2_clientops;
+	}
+#else
+	server->rpc_ops = &nfs_v2_clientops;
+#endif
+
+	/* Fill in pseudoflavor for mount version < 5 */
+	if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
+		data->pseudoflavor = RPC_AUTH_UNIX;
+	authflavor = data->pseudoflavor;	/* save for sb_init() */
+	/* XXX maybe we want to add a server->pseudoflavor field */
+
+	/* Create RPC client handles */
+	server->client = nfs_create_client(server, data);
+	if (IS_ERR(server->client))
+		return PTR_ERR(server->client);
+	/* RFC 2623, sec 2.3.2 */
+	if (authflavor != RPC_AUTH_UNIX) {
+		struct rpc_auth *auth;
+
+		server->client_sys = rpc_clone_client(server->client);
+		if (IS_ERR(server->client_sys))
+			return PTR_ERR(server->client_sys);
+		auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
+		if (IS_ERR(auth))
+			return PTR_ERR(auth);
+	} else {
+		atomic_inc(&server->client->cl_count);
+		server->client_sys = server->client;
+	}
+	if (server->flags & NFS_MOUNT_VER3) {
+#ifdef CONFIG_NFS_V3_ACL
+		if (!(server->flags & NFS_MOUNT_NOACL)) {
+			server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+			/* No errors! Assume that Sun nfsacls are supported */
+			if (!IS_ERR(server->client_acl))
+				server->caps |= NFS_CAP_ACLS;
+		}
+#else
+		server->flags &= ~NFS_MOUNT_NOACL;
+#endif /* CONFIG_NFS_V3_ACL */
+		/*
+		 * The VFS shouldn't apply the umask to mode bits. We will
+		 * do so ourselves when necessary.
+		 */
+		sb->s_flags |= MS_POSIXACL;
+		if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
+			server->namelen = NFS3_MAXNAMLEN;
+		sb->s_time_gran = 1;
+	} else {
+		if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
+			server->namelen = NFS2_MAXNAMLEN;
+	}
+
+	sb->s_op = &nfs_sops;
+	return nfs_sb_init(sb, authflavor);
+}
+
+static int nfs_set_super(struct super_block *s, void *data)
+{
+	s->s_fs_info = data;
+	return set_anon_super(s, data);
+}
+
+static int nfs_compare_super(struct super_block *sb, void *data)
+{
+	struct nfs_server *server = data;
+	struct nfs_server *old = NFS_SB(sb);
+
+	if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr)
+		return 0;
+	if (old->addr.sin_port != server->addr.sin_port)
+		return 0;
+	return !nfs_compare_fh(&old->fh, &server->fh);
+}
+
+static int nfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+{
+	int error;
+	struct nfs_server *server = NULL;
+	struct super_block *s;
+	struct nfs_fh *root;
+	struct nfs_mount_data *data = raw_data;
+
+	error = -EINVAL;
+	if (data == NULL) {
+		dprintk("%s: missing data argument\n", __FUNCTION__);
+		goto out_err_noserver;
+	}
+	if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
+		dprintk("%s: bad mount version\n", __FUNCTION__);
+		goto out_err_noserver;
+	}
+	switch (data->version) {
+		case 1:
+			data->namlen = 0;
+		case 2:
+			data->bsize  = 0;
+		case 3:
+			if (data->flags & NFS_MOUNT_VER3) {
+				dprintk("%s: mount structure version %d does not support NFSv3\n",
+						__FUNCTION__,
+						data->version);
+				goto out_err_noserver;
+			}
+			data->root.size = NFS2_FHSIZE;
+			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
+		case 4:
+			if (data->flags & NFS_MOUNT_SECFLAVOUR) {
+				dprintk("%s: mount structure version %d does not support strong security\n",
+						__FUNCTION__,
+						data->version);
+				goto out_err_noserver;
+			}
+		case 5:
+			memset(data->context, 0, sizeof(data->context));
+	}
+#ifndef CONFIG_NFS_V3
+	/* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
+	error = -EPROTONOSUPPORT;
+	if (data->flags & NFS_MOUNT_VER3) {
+		dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
+		goto out_err_noserver;
+	}
+#endif /* CONFIG_NFS_V3 */
+
+	error = -ENOMEM;
+	server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
+	if (!server)
+		goto out_err_noserver;
+	/* Zero out the NFS state stuff */
+	init_nfsv4_state(server);
+	server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
+
+	root = &server->fh;
+	if (data->flags & NFS_MOUNT_VER3)
+		root->size = data->root.size;
+	else
+		root->size = NFS2_FHSIZE;
+	error = -EINVAL;
+	if (root->size > sizeof(root->data)) {
+		dprintk("%s: invalid root filehandle\n", __FUNCTION__);
+		goto out_err;
+	}
+	memcpy(root->data, data->root.data, root->size);
+
+	/* We now require that the mount process passes the remote address */
+	memcpy(&server->addr, &data->addr, sizeof(server->addr));
+	if (server->addr.sin_addr.s_addr == INADDR_ANY) {
+		dprintk("%s: mount program didn't pass remote address!\n",
+				__FUNCTION__);
+		goto out_err;
+	}
+
+	/* Fire up rpciod if not yet running */
+	error = rpciod_up();
+	if (error < 0) {
+		dprintk("%s: couldn't start rpciod! Error = %d\n",
+				__FUNCTION__, error);
+		goto out_err;
+	}
+
+	s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+	if (IS_ERR(s)) {
+		error = PTR_ERR(s);
+		goto out_err_rpciod;
+	}
+
+	if (s->s_root)
+		goto out_rpciod_down;
+
+	s->s_flags = flags;
+
+	error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+	if (error) {
+		up_write(&s->s_umount);
+		deactivate_super(s);
+		return error;
+	}
+	s->s_flags |= MS_ACTIVE;
+	return simple_set_mnt(mnt, s);
+
+out_rpciod_down:
+	rpciod_down();
+	kfree(server);
+	return simple_set_mnt(mnt, s);
+
+out_err_rpciod:
+	rpciod_down();
+out_err:
+	kfree(server);
+out_err_noserver:
+	return error;
+}
+
+static void nfs_kill_super(struct super_block *s)
+{
+	struct nfs_server *server = NFS_SB(s);
+
+	kill_anon_super(s);
+
+	if (!IS_ERR(server->client))
+		rpc_shutdown_client(server->client);
+	if (!IS_ERR(server->client_sys))
+		rpc_shutdown_client(server->client_sys);
+	if (!IS_ERR(server->client_acl))
+		rpc_shutdown_client(server->client_acl);
+
+	if (!(server->flags & NFS_MOUNT_NONLM))
+		lockd_down();	/* release rpc.lockd */
+
+	rpciod_down();		/* release rpciod */
+
+	nfs_free_iostats(server->io_stats);
+	kfree(server->hostname);
+	kfree(server);
+	nfs_release_automount_timer();
+}
+
+static struct super_block *nfs_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
+{
+	struct super_block *sb;
+
+	server->fsid = data->fattr->fsid;
+	nfs_copy_fh(&server->fh, data->fh);
+	sb = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server);
+	if (!IS_ERR(sb) && sb->s_root == NULL && !(server->flags & NFS_MOUNT_NONLM))
+		lockd_up();
+	return sb;
+}
+
+static int nfs_clone_nfs_sb(struct file_system_type *fs_type,
+		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+{
+	struct nfs_clone_mount *data = raw_data;
+	return nfs_clone_generic_sb(data, nfs_clone_sb, nfs_clone_server, mnt);
+}
+
+#ifdef CONFIG_NFS_V4
+static struct rpc_clnt *nfs4_create_client(struct nfs_server *server,
+	struct rpc_timeout *timeparms, int proto, rpc_authflavor_t flavor)
+{
+	struct nfs4_client *clp;
+	struct rpc_xprt *xprt = NULL;
+	struct rpc_clnt *clnt = NULL;
+	int err = -EIO;
+
+	clp = nfs4_get_client(&server->addr.sin_addr);
+	if (!clp) {
+		dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
+		return ERR_PTR(err);
+	}
+
+	/* Now create transport and client */
+	down_write(&clp->cl_sem);
+	if (IS_ERR(clp->cl_rpcclient)) {
+		xprt = xprt_create_proto(proto, &server->addr, timeparms);
+		if (IS_ERR(xprt)) {
+			up_write(&clp->cl_sem);
+			err = PTR_ERR(xprt);
+			dprintk("%s: cannot create RPC transport. Error = %d\n",
+					__FUNCTION__, err);
+			goto out_fail;
+		}
+		/* Bind to a reserved port! */
+		xprt->resvport = 1;
+		clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
+				server->rpc_ops->version, flavor);
+		if (IS_ERR(clnt)) {
+			up_write(&clp->cl_sem);
+			err = PTR_ERR(clnt);
+			dprintk("%s: cannot create RPC client. Error = %d\n",
+					__FUNCTION__, err);
+			goto out_fail;
+		}
+		clnt->cl_intr     = 1;
+		clnt->cl_softrtry = 1;
+		clp->cl_rpcclient = clnt;
+		memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
+		nfs_idmap_new(clp);
+	}
+	list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
+	clnt = rpc_clone_client(clp->cl_rpcclient);
+	if (!IS_ERR(clnt))
+		server->nfs4_state = clp;
+	up_write(&clp->cl_sem);
+	clp = NULL;
+
+	if (IS_ERR(clnt)) {
+		dprintk("%s: cannot create RPC client. Error = %d\n",
+				__FUNCTION__, err);
+		return clnt;
+	}
+
+	if (server->nfs4_state->cl_idmap == NULL) {
+		dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	if (clnt->cl_auth->au_flavor != flavor) {
+		struct rpc_auth *auth;
+
+		auth = rpcauth_create(flavor, clnt);
+		if (IS_ERR(auth)) {
+			dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
+			return (struct rpc_clnt *)auth;
+		}
+	}
+	return clnt;
+
+ out_fail:
+	if (clp)
+		nfs4_put_client(clp);
+	return ERR_PTR(err);
+}
+
+/*
+ * Set up an NFS4 superblock
+ */
+static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent)
+{
+	struct nfs_server *server;
+	struct rpc_timeout timeparms;
+	rpc_authflavor_t authflavour;
+	int err = -EIO;
+
+	sb->s_blocksize_bits = 0;
+	sb->s_blocksize = 0;
+	server = NFS_SB(sb);
+	if (data->rsize != 0)
+		server->rsize = nfs_block_size(data->rsize, NULL);
+	if (data->wsize != 0)
+		server->wsize = nfs_block_size(data->wsize, NULL);
+	server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+	server->caps = NFS_CAP_ATOMIC_OPEN;
+
+	server->acregmin = data->acregmin*HZ;
+	server->acregmax = data->acregmax*HZ;
+	server->acdirmin = data->acdirmin*HZ;
+	server->acdirmax = data->acdirmax*HZ;
+
+	server->rpc_ops = &nfs_v4_clientops;
+
+	nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans);
+
+	server->retrans_timeo = timeparms.to_initval;
+	server->retrans_count = timeparms.to_retries;
+
+	/* Now create transport and client */
+	authflavour = RPC_AUTH_UNIX;
+	if (data->auth_flavourlen != 0) {
+		if (data->auth_flavourlen != 1) {
+			dprintk("%s: Invalid number of RPC auth flavours %d.\n",
+					__FUNCTION__, data->auth_flavourlen);
+			err = -EINVAL;
+			goto out_fail;
+		}
+		if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
+			err = -EFAULT;
+			goto out_fail;
+		}
+	}
+
+	server->client = nfs4_create_client(server, &timeparms, data->proto, authflavour);
+	if (IS_ERR(server->client)) {
+		err = PTR_ERR(server->client);
+			dprintk("%s: cannot create RPC client. Error = %d\n",
+					__FUNCTION__, err);
+			goto out_fail;
+	}
+
+	sb->s_time_gran = 1;
+
+	sb->s_op = &nfs4_sops;
+	err = nfs_sb_init(sb, authflavour);
+
+ out_fail:
+	return err;
+}
+
+static int nfs4_compare_super(struct super_block *sb, void *data)
+{
+	struct nfs_server *server = data;
+	struct nfs_server *old = NFS_SB(sb);
+
+	if (strcmp(server->hostname, old->hostname) != 0)
+		return 0;
+	if (strcmp(server->mnt_path, old->mnt_path) != 0)
+		return 0;
+	return 1;
+}
+
+static void *
+nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen)
+{
+	void *p = NULL;
+
+	if (!src->len)
+		return ERR_PTR(-EINVAL);
+	if (src->len < maxlen)
+		maxlen = src->len;
+	if (dst == NULL) {
+		p = dst = kmalloc(maxlen + 1, GFP_KERNEL);
+		if (p == NULL)
+			return ERR_PTR(-ENOMEM);
+	}
+	if (copy_from_user(dst, src->data, maxlen)) {
+		kfree(p);
+		return ERR_PTR(-EFAULT);
+	}
+	dst[maxlen] = '\0';
+	return dst;
+}
+
+static int nfs4_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+{
+	int error;
+	struct nfs_server *server;
+	struct super_block *s;
+	struct nfs4_mount_data *data = raw_data;
+	void *p;
+
+	if (data == NULL) {
+		dprintk("%s: missing data argument\n", __FUNCTION__);
+		return -EINVAL;
+	}
+	if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
+		dprintk("%s: bad mount version\n", __FUNCTION__);
+		return -EINVAL;
+	}
+
+	server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
+	if (!server)
+		return -ENOMEM;
+	/* Zero out the NFS state stuff */
+	init_nfsv4_state(server);
+	server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
+
+	p = nfs_copy_user_string(NULL, &data->hostname, 256);
+	if (IS_ERR(p))
+		goto out_err;
+	server->hostname = p;
+
+	p = nfs_copy_user_string(NULL, &data->mnt_path, 1024);
+	if (IS_ERR(p))
+		goto out_err;
+	server->mnt_path = p;
+
+	p = nfs_copy_user_string(server->ip_addr, &data->client_addr,
+			sizeof(server->ip_addr) - 1);
+	if (IS_ERR(p))
+		goto out_err;
+
+	/* We now require that the mount process passes the remote address */
+	if (data->host_addrlen != sizeof(server->addr)) {
+		error = -EINVAL;
+		goto out_free;
+	}
+	if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) {
+		error = -EFAULT;
+		goto out_free;
+	}
+	if (server->addr.sin_family != AF_INET ||
+	    server->addr.sin_addr.s_addr == INADDR_ANY) {
+		dprintk("%s: mount program didn't pass remote IP address!\n",
+				__FUNCTION__);
+		error = -EINVAL;
+		goto out_free;
+	}
+
+	/* Fire up rpciod if not yet running */
+	error = rpciod_up();
+	if (error < 0) {
+		dprintk("%s: couldn't start rpciod! Error = %d\n",
+				__FUNCTION__, error);
+		goto out_free;
+	}
+
+	s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
+
+	if (IS_ERR(s)) {
+		error = PTR_ERR(s);
+		goto out_free;
+	}
+
+	if (s->s_root) {
+		kfree(server->mnt_path);
+		kfree(server->hostname);
+		kfree(server);
+		return simple_set_mnt(mnt, s);
+	}
+
+	s->s_flags = flags;
+
+	error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
+	if (error) {
+		up_write(&s->s_umount);
+		deactivate_super(s);
+		return error;
+	}
+	s->s_flags |= MS_ACTIVE;
+	return simple_set_mnt(mnt, s);
+out_err:
+	error = PTR_ERR(p);
+out_free:
+	kfree(server->mnt_path);
+	kfree(server->hostname);
+	kfree(server);
+	return error;
+}
+
+static void nfs4_kill_super(struct super_block *sb)
+{
+	struct nfs_server *server = NFS_SB(sb);
+
+	nfs_return_all_delegations(sb);
+	kill_anon_super(sb);
+
+	nfs4_renewd_prepare_shutdown(server);
+
+	if (server->client != NULL && !IS_ERR(server->client))
+		rpc_shutdown_client(server->client);
+
+	destroy_nfsv4_state(server);
+
+	rpciod_down();
+
+	nfs_free_iostats(server->io_stats);
+	kfree(server->hostname);
+	kfree(server);
+	nfs_release_automount_timer();
+}
+
+/*
+ * Constructs the SERVER-side path
+ */
+static inline char *nfs4_dup_path(const struct dentry *dentry)
+{
+	char *page = (char *) __get_free_page(GFP_USER);
+	char *path;
+
+	path = nfs4_path(dentry, page, PAGE_SIZE);
+	if (!IS_ERR(path)) {
+		int len = PAGE_SIZE + page - path;
+		char *tmp = path;
+
+		path = kmalloc(len, GFP_KERNEL);
+		if (path)
+			memcpy(path, tmp, len);
+		else
+			path = ERR_PTR(-ENOMEM);
+	}
+	free_page((unsigned long)page);
+	return path;
+}
+
+static struct super_block *nfs4_clone_sb(struct nfs_server *server, struct nfs_clone_mount *data)
+{
+	const struct dentry *dentry = data->dentry;
+	struct nfs4_client *clp = server->nfs4_state;
+	struct super_block *sb;
+
+	server->fsid = data->fattr->fsid;
+	nfs_copy_fh(&server->fh, data->fh);
+	server->mnt_path = nfs4_dup_path(dentry);
+	if (IS_ERR(server->mnt_path)) {
+		sb = (struct super_block *)server->mnt_path;
+		goto err;
+	}
+	sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
+	if (IS_ERR(sb) || sb->s_root)
+		goto free_path;
+	nfs4_server_capabilities(server, &server->fh);
+
+	down_write(&clp->cl_sem);
+	atomic_inc(&clp->cl_count);
+	list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks);
+	up_write(&clp->cl_sem);
+	return sb;
+free_path:
+	kfree(server->mnt_path);
+err:
+	server->mnt_path = NULL;
+	return sb;
+}
+
+static int nfs_clone_nfs4_sb(struct file_system_type *fs_type,
+		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+{
+	struct nfs_clone_mount *data = raw_data;
+	return nfs_clone_generic_sb(data, nfs4_clone_sb, nfs_clone_server, mnt);
+}
+
+static struct super_block *nfs4_referral_sb(struct nfs_server *server, struct nfs_clone_mount *data)
+{
+	struct super_block *sb = ERR_PTR(-ENOMEM);
+	int len;
+
+	len = strlen(data->mnt_path) + 1;
+	server->mnt_path = kmalloc(len, GFP_KERNEL);
+	if (server->mnt_path == NULL)
+		goto err;
+	memcpy(server->mnt_path, data->mnt_path, len);
+	memcpy(&server->addr, data->addr, sizeof(struct sockaddr_in));
+
+	sb = sget(&nfs4_fs_type, nfs4_compare_super, nfs_set_super, server);
+	if (IS_ERR(sb) || sb->s_root)
+		goto free_path;
+	return sb;
+free_path:
+	kfree(server->mnt_path);
+err:
+	server->mnt_path = NULL;
+	return sb;
+}
+
+static struct nfs_server *nfs4_referral_server(struct super_block *sb, struct nfs_clone_mount *data)
+{
+	struct nfs_server *server = NFS_SB(sb);
+	struct rpc_timeout timeparms;
+	int proto, timeo, retrans;
+	void *err;
+
+	proto = IPPROTO_TCP;
+	/* Since we are following a referral and there may be alternatives,
+	   set the timeouts and retries to low values */
+	timeo = 2;
+	retrans = 1;
+	nfs_init_timeout_values(&timeparms, proto, timeo, retrans);
+
+	server->client = nfs4_create_client(server, &timeparms, proto, data->authflavor);
+	if (IS_ERR((err = server->client)))
+		goto out_err;
+
+	sb->s_time_gran = 1;
+	sb->s_op = &nfs4_sops;
+	err = ERR_PTR(nfs_sb_init(sb, data->authflavor));
+	if (!IS_ERR(err))
+		return server;
+out_err:
+	return (struct nfs_server *)err;
+}
+
+static int nfs_referral_nfs4_sb(struct file_system_type *fs_type,
+		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt)
+{
+	struct nfs_clone_mount *data = raw_data;
+	return nfs_clone_generic_sb(data, nfs4_referral_sb, nfs4_referral_server, mnt);
+}
+
+#endif
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 18dc95b..600bbe6 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -52,7 +52,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	struct page *page;
-	void *err = ERR_PTR(nfs_revalidate_inode(NFS_SERVER(inode), inode));
+	void *err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
 	if (err)
 		goto read_failed;
 	page = read_cache_page(&inode->i_data, 0,
@@ -75,22 +75,13 @@
 	return NULL;
 }
 
-static void nfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
-{
-	if (cookie) {
-		struct page *page = cookie;
-		kunmap(page);
-		page_cache_release(page);
-	}
-}
-
 /*
  * symlinks can't do much...
  */
 struct inode_operations nfs_symlink_inode_operations = {
 	.readlink	= generic_readlink,
 	.follow_link	= nfs_follow_link,
-	.put_link	= nfs_put_link,
+	.put_link	= page_put_link,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
 };
diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c
index 4c486eb..db61e51 100644
--- a/fs/nfs/sysctl.c
+++ b/fs/nfs/sysctl.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_idmap.h>
+#include <linux/nfs_fs.h>
 
 #include "callback.h"
 
@@ -46,6 +47,15 @@
 		.strategy = &sysctl_jiffies,
 	},
 #endif
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "nfs_mountpoint_timeout",
+		.data		= &nfs_mountpoint_expiry_timeout,
+		.maxlen		= sizeof(nfs_mountpoint_expiry_timeout),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec_jiffies,
+		.strategy	= &sysctl_jiffies,
+	},
 	{ .ctl_name = 0 }
 };
 
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 4cfada2..8fccb9c 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -98,11 +98,10 @@
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
-		if (pagecount < NFS_PAGEVEC_SIZE)
-			p->pagevec = &p->page_array[0];
+		if (pagecount <= ARRAY_SIZE(p->page_array))
+			p->pagevec = p->page_array;
 		else {
-			size_t size = ++pagecount * sizeof(struct page *);
-			p->pagevec = kzalloc(size, GFP_NOFS);
+			p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS);
 			if (!p->pagevec) {
 				mempool_free(p, nfs_commit_mempool);
 				p = NULL;
@@ -126,14 +125,11 @@
 	if (p) {
 		memset(p, 0, sizeof(*p));
 		INIT_LIST_HEAD(&p->pages);
-		if (pagecount < NFS_PAGEVEC_SIZE)
-			p->pagevec = &p->page_array[0];
+		if (pagecount <= ARRAY_SIZE(p->page_array))
+			p->pagevec = p->page_array;
 		else {
-			size_t size = ++pagecount * sizeof(struct page *);
-			p->pagevec = kmalloc(size, GFP_NOFS);
-			if (p->pagevec) {
-				memset(p->pagevec, 0, size);
-			} else {
+			p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_NOFS);
+			if (!p->pagevec) {
 				mempool_free(p, nfs_wdata_mempool);
 				p = NULL;
 			}
@@ -583,6 +579,17 @@
 	return ret;
 }
 
+static void nfs_cancel_requests(struct list_head *head)
+{
+	struct nfs_page *req;
+	while(!list_empty(head)) {
+		req = nfs_list_entry(head->next);
+		nfs_list_remove_request(req);
+		nfs_inode_remove_request(req);
+		nfs_clear_page_writeback(req);
+	}
+}
+
 /*
  * nfs_scan_dirty - Scan an inode for dirty requests
  * @inode: NFS inode to scan
@@ -627,7 +634,7 @@
 	int res = 0;
 
 	if (nfsi->ncommit != 0) {
-		res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);
+		res = nfs_scan_list(nfsi, &nfsi->commit, dst, idx_start, npages);
 		nfsi->ncommit -= res;
 		if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
 			printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
@@ -1495,15 +1502,25 @@
 		pages = nfs_scan_dirty(inode, &head, idx_start, npages);
 		if (pages != 0) {
 			spin_unlock(&nfsi->req_lock);
-			ret = nfs_flush_list(inode, &head, pages, how);
+			if (how & FLUSH_INVALIDATE)
+				nfs_cancel_requests(&head);
+			else
+				ret = nfs_flush_list(inode, &head, pages, how);
 			spin_lock(&nfsi->req_lock);
 			continue;
 		}
 		if (nocommit)
 			break;
-		pages = nfs_scan_commit(inode, &head, 0, 0);
+		pages = nfs_scan_commit(inode, &head, idx_start, npages);
 		if (pages == 0)
 			break;
+		if (how & FLUSH_INVALIDATE) {
+			spin_unlock(&nfsi->req_lock);
+			nfs_cancel_requests(&head);
+			spin_lock(&nfsi->req_lock);
+			continue;
+		}
+		pages += nfs_scan_commit(inode, &head, 0, 0);
 		spin_unlock(&nfsi->req_lock);
 		ret = nfs_commit_list(inode, &head, how);
 		spin_lock(&nfsi->req_lock);
@@ -1512,7 +1529,7 @@
 	return ret;
 }
 
-int nfs_init_writepagecache(void)
+int __init nfs_init_writepagecache(void)
 {
 	nfs_wdata_cachep = kmem_cache_create("nfs_write_data",
 					     sizeof(struct nfs_write_data),
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 96c7578..7c7d016 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -123,7 +123,7 @@
  */
 
 /* recall_lock protects the del_recall_lru */
-static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(recall_lock);
 static struct list_head del_recall_lru;
 
 static void
@@ -529,8 +529,7 @@
 
 	dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
 	list_del_init(&clp->cl_strhash);
-	list_del_init(&clp->cl_idhash);
-	list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
+	list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
 	strhashval = clientstr_hashval(clp->cl_recdir);
 	list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
 	renew_client(clp);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index de3998f..5446a08 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1310,7 +1310,7 @@
 	if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
 	    (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
 		       FATTR4_WORD1_SPACE_TOTAL))) {
-		status = vfs_statfs(dentry->d_inode->i_sb, &statfs);
+		status = vfs_statfs(dentry, &statfs);
 		if (status)
 			goto out_nfserr;
 	}
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index d852ebb..fdf7cf3 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -103,8 +103,7 @@
 static void
 lru_put_end(struct svc_cacherep *rp)
 {
-	list_del(&rp->c_lru);
-	list_add_tail(&rp->c_lru, &lru_head);
+	list_move_tail(&rp->c_lru, &lru_head);
 }
 
 /*
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 3ef017b..a1810e6 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -494,10 +494,10 @@
 	return simple_fill_super(sb, 0x6e667364, nfsd_files);
 }
 
-static struct super_block *nfsd_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int nfsd_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, nfsd_fill_super);
+	return get_sb_single(fs_type, flags, data, nfsd_fill_super, mnt);
 }
 
 static struct file_system_type nfsd_fs_type = {
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 1d65f13..245eaa1 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1737,7 +1737,7 @@
 nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat)
 {
 	int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
-	if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat))
+	if (!err && vfs_statfs(fhp->fh_dentry,stat))
 		err = nfserr_io;
 	return err;
 }
diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
index 580412d..bc579bf 100644
--- a/fs/ntfs/aops.c
+++ b/fs/ntfs/aops.c
@@ -1544,7 +1544,7 @@
 /**
  * ntfs_aops - general address space operations for inodes and attributes
  */
-struct address_space_operations ntfs_aops = {
+const struct address_space_operations ntfs_aops = {
 	.readpage	= ntfs_readpage,	/* Fill page with data. */
 	.sync_page	= block_sync_page,	/* Currently, just unplugs the
 						   disk request queue. */
@@ -1560,7 +1560,7 @@
  * ntfs_mst_aops - general address space operations for mst protecteed inodes
  *		   and attributes
  */
-struct address_space_operations ntfs_mst_aops = {
+const struct address_space_operations ntfs_mst_aops = {
 	.readpage	= ntfs_readpage,	/* Fill page with data. */
 	.sync_page	= block_sync_page,	/* Currently, just unplugs the
 						   disk request queue. */
diff --git a/fs/ntfs/aops.h b/fs/ntfs/aops.h
index 3b74e66..325ce26 100644
--- a/fs/ntfs/aops.h
+++ b/fs/ntfs/aops.h
@@ -86,8 +86,7 @@
 static inline struct page *ntfs_map_page(struct address_space *mapping,
 		unsigned long index)
 {
-	struct page *page = read_cache_page(mapping, index,
-			(filler_t*)mapping->a_ops->readpage, NULL);
+	struct page *page = read_mapping_page(mapping, index, NULL);
 
 	if (!IS_ERR(page)) {
 		wait_on_page_locked(page);
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c
index 1663f5c..6708e1d 100644
--- a/fs/ntfs/attrib.c
+++ b/fs/ntfs/attrib.c
@@ -2529,8 +2529,7 @@
 	end >>= PAGE_CACHE_SHIFT;
 	/* If there is a first partial page, need to do it the slow way. */
 	if (start_ofs) {
-		page = read_cache_page(mapping, idx,
-				(filler_t*)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, idx, NULL);
 		if (IS_ERR(page)) {
 			ntfs_error(vol->sb, "Failed to read first partial "
 					"page (sync error, index 0x%lx).", idx);
@@ -2600,8 +2599,7 @@
 	}
 	/* If there is a last partial page, need to do it the slow way. */
 	if (end_ofs) {
-		page = read_cache_page(mapping, idx,
-				(filler_t*)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, idx, NULL);
 		if (IS_ERR(page)) {
 			ntfs_error(vol->sb, "Failed to read last partial page "
 					"(sync error, index 0x%lx).", idx);
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
index c63a83e..2e42c2d 100644
--- a/fs/ntfs/file.c
+++ b/fs/ntfs/file.c
@@ -231,8 +231,7 @@
 		 * Read the page.  If the page is not present, this will zero
 		 * the uninitialized regions for us.
 		 */
-		page = read_cache_page(mapping, index,
-				(filler_t*)mapping->a_ops->readpage, NULL);
+		page = read_mapping_page(mapping, index, NULL);
 		if (IS_ERR(page)) {
 			err = PTR_ERR(page);
 			goto init_err_out;
@@ -1359,7 +1358,7 @@
 	goto out;
 }
 
-static size_t __ntfs_copy_from_user_iovec(char *vaddr,
+static size_t __ntfs_copy_from_user_iovec_inatomic(char *vaddr,
 		const struct iovec *iov, size_t iov_ofs, size_t bytes)
 {
 	size_t total = 0;
@@ -1377,10 +1376,6 @@
 		bytes -= len;
 		vaddr += len;
 		if (unlikely(left)) {
-			/*
-			 * Zero the rest of the target like __copy_from_user().
-			 */
-			memset(vaddr, 0, bytes);
 			total -= left;
 			break;
 		}
@@ -1421,11 +1416,13 @@
  * pages (out to offset + bytes), to emulate ntfs_copy_from_user()'s
  * single-segment behaviour.
  *
- * We call the same helper (__ntfs_copy_from_user_iovec()) both when atomic and
- * when not atomic.  This is ok because __ntfs_copy_from_user_iovec() calls
- * __copy_from_user_inatomic() and it is ok to call this when non-atomic.  In
- * fact, the only difference between __copy_from_user_inatomic() and
- * __copy_from_user() is that the latter calls might_sleep().  And on many
+ * We call the same helper (__ntfs_copy_from_user_iovec_inatomic()) both
+ * when atomic and when not atomic.  This is ok because
+ * __ntfs_copy_from_user_iovec_inatomic() calls __copy_from_user_inatomic()
+ * and it is ok to call this when non-atomic.
+ * Infact, the only difference between __copy_from_user_inatomic() and
+ * __copy_from_user() is that the latter calls might_sleep() and the former
+ * should not zero the tail of the buffer on error.  And on many
  * architectures __copy_from_user_inatomic() is just defined to
  * __copy_from_user() so it makes no difference at all on those architectures.
  */
@@ -1442,14 +1439,18 @@
 		if (len > bytes)
 			len = bytes;
 		kaddr = kmap_atomic(*pages, KM_USER0);
-		copied = __ntfs_copy_from_user_iovec(kaddr + ofs,
+		copied = __ntfs_copy_from_user_iovec_inatomic(kaddr + ofs,
 				*iov, *iov_ofs, len);
 		kunmap_atomic(kaddr, KM_USER0);
 		if (unlikely(copied != len)) {
 			/* Do it the slow way. */
 			kaddr = kmap(*pages);
-			copied = __ntfs_copy_from_user_iovec(kaddr + ofs,
+			copied = __ntfs_copy_from_user_iovec_inatomic(kaddr + ofs,
 					*iov, *iov_ofs, len);
+			/*
+			 * Zero the rest of the target like __copy_from_user().
+			 */
+			memset(kaddr + ofs + copied, 0, len - copied);
 			kunmap(*pages);
 			if (unlikely(copied != len))
 				goto err_out;
@@ -1484,14 +1485,15 @@
 		unsigned nr_pages)
 {
 	BUG_ON(!nr_pages);
+	/*
+	 * Warning: Do not do the decrement at the same time as the call to
+	 * flush_dcache_page() because it is a NULL macro on i386 and hence the
+	 * decrement never happens so the loop never terminates.
+	 */
 	do {
-		/*
-		 * Warning: Do not do the decrement at the same time as the
-		 * call because flush_dcache_page() is a NULL macro on i386
-		 * and hence the decrement never happens.
-		 */
+		--nr_pages;
 		flush_dcache_page(pages[nr_pages]);
-	} while (--nr_pages > 0);
+	} while (nr_pages > 0);
 }
 
 /**
diff --git a/fs/ntfs/ntfs.h b/fs/ntfs/ntfs.h
index bf7b3d7..ddd3d50 100644
--- a/fs/ntfs/ntfs.h
+++ b/fs/ntfs/ntfs.h
@@ -57,8 +57,8 @@
 extern struct kmem_cache *ntfs_index_ctx_cache;
 
 /* The various operations structs defined throughout the driver files. */
-extern struct address_space_operations ntfs_aops;
-extern struct address_space_operations ntfs_mst_aops;
+extern const struct address_space_operations ntfs_aops;
+extern const struct address_space_operations ntfs_mst_aops;
 
 extern const struct  file_operations ntfs_file_ops;
 extern struct inode_operations ntfs_file_inode_ops;
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 27833f6..0e14ace 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2601,10 +2601,10 @@
 
 /**
  * ntfs_statfs - return information about mounted NTFS volume
- * @sb:		super block of mounted volume
+ * @dentry:	dentry from mounted volume
  * @sfs:	statfs structure in which to return the information
  *
- * Return information about the mounted NTFS volume @sb in the statfs structure
+ * Return information about the mounted NTFS volume @dentry in the statfs structure
  * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is
  * called). We interpret the values to be correct of the moment in time at
  * which we are called. Most values are variable otherwise and this isn't just
@@ -2617,8 +2617,9 @@
  *
  * Return 0 on success or -errno on error.
  */
-static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs)
+static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)
 {
+	struct super_block *sb = dentry->d_sb;
 	s64 size;
 	ntfs_volume *vol = NTFS_SB(sb);
 	ntfs_inode *mft_ni = NTFS_I(vol->mft_ino);
@@ -3093,10 +3094,11 @@
 /* Driver wide mutex. */
 DEFINE_MUTEX(ntfs_lock);
 
-static struct super_block *ntfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int ntfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type ntfs_fs_type = {
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 47152bf..cca7131 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -666,7 +666,7 @@
 	return ret;
 }
 
-struct address_space_operations ocfs2_aops = {
+const struct address_space_operations ocfs2_aops = {
 	.readpage	= ocfs2_readpage,
 	.writepage	= ocfs2_writepage,
 	.prepare_write	= ocfs2_prepare_write,
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 21f38ac..1d26cfc 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -54,7 +54,7 @@
  * multiple hb threads are watching multiple regions.  A node is live
  * whenever any of the threads sees activity from the node in its region.
  */
-static spinlock_t o2hb_live_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(o2hb_live_lock);
 static struct list_head o2hb_live_slots[O2NM_MAX_NODES];
 static unsigned long o2hb_live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
 static LIST_HEAD(o2hb_node_events);
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 0f60cc0..1591eb3 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -108,7 +108,7 @@
 	    ##args);							\
 } while (0)
 
-static rwlock_t o2net_handler_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(o2net_handler_lock);
 static struct rb_root o2net_handler_tree = RB_ROOT;
 
 static struct o2net_node o2net_nodes[O2NM_MAX_NODES];
diff --git a/fs/ocfs2/dlm/dlmast.c b/fs/ocfs2/dlm/dlmast.c
index 355593dd8..42775e2 100644
--- a/fs/ocfs2/dlm/dlmast.c
+++ b/fs/ocfs2/dlm/dlmast.c
@@ -197,12 +197,14 @@
 				  lock->ml.node == dlm->node_num ? "master" :
 				  "remote");
 			memcpy(lksb->lvb, res->lvb, DLM_LVB_LEN);
-		} else if (lksb->flags & DLM_LKSB_PUT_LVB) {
-			mlog(0, "setting lvb from lockres for %s node\n",
-				  lock->ml.node == dlm->node_num ? "master" :
-				  "remote");
-			memcpy(res->lvb, lksb->lvb, DLM_LVB_LEN);
 		}
+		/* Do nothing for lvb put requests - they should be done in
+ 		 * place when the lock is downconverted - otherwise we risk
+ 		 * racing gets and puts which could result in old lvb data
+ 		 * being propagated. We leave the put flag set and clear it
+ 		 * here. In the future we might want to clear it at the time
+ 		 * the put is actually done.
+		 */
 		spin_unlock(&res->spinlock);
 	}
 
@@ -381,8 +383,7 @@
 	ret = DLM_NORMAL;
 	if (past->type == DLM_AST) {
 		/* do not alter lock refcount.  switching lists. */
-		list_del_init(&lock->list);
-		list_add_tail(&lock->list, &res->granted);
+		list_move_tail(&lock->list, &res->granted);
 		mlog(0, "ast: adding to granted list... type=%d, "
 			  "convert_type=%d\n", lock->ml.type, lock->ml.convert_type);
 		if (lock->ml.convert_type != LKM_IVMODE) {
diff --git a/fs/ocfs2/dlm/dlmcommon.h b/fs/ocfs2/dlm/dlmcommon.h
index 88cc43d..9bdc9cf 100644
--- a/fs/ocfs2/dlm/dlmcommon.h
+++ b/fs/ocfs2/dlm/dlmcommon.h
@@ -37,7 +37,17 @@
 #define DLM_THREAD_SHUFFLE_INTERVAL    5     // flush everything every 5 passes
 #define DLM_THREAD_MS                  200   // flush at least every 200 ms
 
-#define DLM_HASH_BUCKETS     (PAGE_SIZE / sizeof(struct hlist_head))
+#define DLM_HASH_SIZE_DEFAULT	(1 << 14)
+#if DLM_HASH_SIZE_DEFAULT < PAGE_SIZE
+# define DLM_HASH_PAGES		1
+#else
+# define DLM_HASH_PAGES		(DLM_HASH_SIZE_DEFAULT / PAGE_SIZE)
+#endif
+#define DLM_BUCKETS_PER_PAGE	(PAGE_SIZE / sizeof(struct hlist_head))
+#define DLM_HASH_BUCKETS	(DLM_HASH_PAGES * DLM_BUCKETS_PER_PAGE)
+
+/* Intended to make it easier for us to switch out hash functions */
+#define dlm_lockid_hash(_n, _l) full_name_hash(_n, _l)
 
 enum dlm_ast_type {
 	DLM_AST = 0,
@@ -61,7 +71,8 @@
 	return 0;
 }
 
-#define DLM_RECO_STATE_ACTIVE  0x0001
+#define DLM_RECO_STATE_ACTIVE    0x0001
+#define DLM_RECO_STATE_FINALIZE  0x0002
 
 struct dlm_recovery_ctxt
 {
@@ -85,7 +96,7 @@
 struct dlm_ctxt
 {
 	struct list_head list;
-	struct hlist_head *lockres_hash;
+	struct hlist_head **lockres_hash;
 	struct list_head dirty_list;
 	struct list_head purge_list;
 	struct list_head pending_asts;
@@ -120,6 +131,7 @@
 	struct o2hb_callback_func dlm_hb_down;
 	struct task_struct *dlm_thread_task;
 	struct task_struct *dlm_reco_thread_task;
+	struct workqueue_struct *dlm_worker;
 	wait_queue_head_t dlm_thread_wq;
 	wait_queue_head_t dlm_reco_thread_wq;
 	wait_queue_head_t ast_wq;
@@ -132,6 +144,11 @@
 	struct list_head	dlm_eviction_callbacks;
 };
 
+static inline struct hlist_head *dlm_lockres_hash(struct dlm_ctxt *dlm, unsigned i)
+{
+	return dlm->lockres_hash[(i / DLM_BUCKETS_PER_PAGE) % DLM_HASH_PAGES] + (i % DLM_BUCKETS_PER_PAGE);
+}
+
 /* these keventd work queue items are for less-frequently
  * called functions that cannot be directly called from the
  * net message handlers for some reason, usually because
@@ -216,20 +233,29 @@
 	/* WARNING: Please see the comment in dlm_init_lockres before
 	 * adding fields here. */
 	struct hlist_node hash_node;
+	struct qstr lockname;
 	struct kref      refs;
 
-	/* please keep these next 3 in this order
-	 * some funcs want to iterate over all lists */
+	/*
+	 * Please keep granted, converting, and blocked in this order,
+	 * as some funcs want to iterate over all lists.
+	 *
+	 * All four lists are protected by the hash's reference.
+	 */
 	struct list_head granted;
 	struct list_head converting;
 	struct list_head blocked;
+	struct list_head purge;
 
+	/*
+	 * These two lists require you to hold an additional reference
+	 * while they are on the list.
+	 */
 	struct list_head dirty;
 	struct list_head recovering; // dlm_recovery_ctxt.resources list
 
 	/* unused lock resources have their last_used stamped and are
 	 * put on a list for the dlm thread to run. */
-	struct list_head purge;
 	unsigned long    last_used;
 
 	unsigned migration_pending:1;
@@ -238,7 +264,6 @@
 	wait_queue_head_t wq;
 	u8  owner;              //node which owns the lock resource, or unknown
 	u16 state;
-	struct qstr lockname;
 	char lvb[DLM_LVB_LEN];
 };
 
@@ -300,6 +325,15 @@
 	DLM_BLOCKED_LIST
 };
 
+static inline int dlm_lvb_is_empty(char *lvb)
+{
+	int i;
+	for (i=0; i<DLM_LVB_LEN; i++)
+		if (lvb[i])
+			return 0;
+	return 1;
+}
+
 static inline struct list_head *
 dlm_list_idx_to_ptr(struct dlm_lock_resource *res, enum dlm_lockres_list idx)
 {
@@ -609,7 +643,8 @@
 {
 	u8 node_idx;
 	u8 dead_node;
-	__be16 pad1;
+	u8 flags;
+	u8 pad1;
 	__be32 pad2;
 };
 
@@ -676,6 +711,7 @@
 void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
 int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node);
 int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout);
+int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout);
 
 void dlm_put(struct dlm_ctxt *dlm);
 struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm);
@@ -687,14 +723,20 @@
 			    struct dlm_lock_resource *res);
 void dlm_purge_lockres(struct dlm_ctxt *dlm,
 		       struct dlm_lock_resource *lockres);
-void dlm_lockres_get(struct dlm_lock_resource *res);
+static inline void dlm_lockres_get(struct dlm_lock_resource *res)
+{
+	/* This is called on every lookup, so it might be worth
+	 * inlining. */
+	kref_get(&res->refs);
+}
 void dlm_lockres_put(struct dlm_lock_resource *res);
 void __dlm_unhash_lockres(struct dlm_lock_resource *res);
 void __dlm_insert_lockres(struct dlm_ctxt *dlm,
 			  struct dlm_lock_resource *res);
 struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
 						const char *name,
-						unsigned int len);
+						unsigned int len,
+						unsigned int hash);
 struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
 					      const char *name,
 					      unsigned int len);
@@ -819,6 +861,7 @@
 			   u8 dead_node);
 int dlm_lock_basts_flushed(struct dlm_ctxt *dlm, struct dlm_lock *lock);
 
+int __dlm_lockres_unused(struct dlm_lock_resource *res);
 
 static inline const char * dlm_lock_mode_name(int mode)
 {
diff --git a/fs/ocfs2/dlm/dlmconvert.c b/fs/ocfs2/dlm/dlmconvert.c
index 8285228..c764dc8 100644
--- a/fs/ocfs2/dlm/dlmconvert.c
+++ b/fs/ocfs2/dlm/dlmconvert.c
@@ -214,6 +214,9 @@
 	if (lock->ml.node == dlm->node_num)
 		mlog(0, "doing in-place convert for nonlocal lock\n");
 	lock->ml.type = type;
+	if (lock->lksb->flags & DLM_LKSB_PUT_LVB)
+		memcpy(res->lvb, lock->lksb->lvb, DLM_LVB_LEN);
+
 	status = DLM_NORMAL;
 	*call_ast = 1;
 	goto unlock_exit;
@@ -231,8 +234,7 @@
 
 	lock->ml.convert_type = type;
 	/* do not alter lock refcount.  switching lists. */
-	list_del_init(&lock->list);
-	list_add_tail(&lock->list, &res->converting);
+	list_move_tail(&lock->list, &res->converting);
 
 unlock_exit:
 	spin_unlock(&lock->spinlock);
@@ -248,8 +250,7 @@
 				struct dlm_lock *lock)
 {
 	/* do not alter lock refcount.  switching lists. */
-	list_del_init(&lock->list);
-	list_add_tail(&lock->list, &res->granted);
+	list_move_tail(&lock->list, &res->granted);
 	lock->ml.convert_type = LKM_IVMODE;
 	lock->lksb->flags &= ~(DLM_LKSB_GET_LVB|DLM_LKSB_PUT_LVB);
 }
@@ -294,8 +295,7 @@
 	res->state |= DLM_LOCK_RES_IN_PROGRESS;
 	/* move lock to local convert queue */
 	/* do not alter lock refcount.  switching lists. */
-	list_del_init(&lock->list);
-	list_add_tail(&lock->list, &res->converting);
+	list_move_tail(&lock->list, &res->converting);
 	lock->convert_pending = 1;
 	lock->ml.convert_type = type;
 
@@ -464,6 +464,12 @@
 	}
 
 	spin_lock(&res->spinlock);
+	status = __dlm_lockres_state_to_status(res);
+	if (status != DLM_NORMAL) {
+		spin_unlock(&res->spinlock);
+		dlm_error(status);
+		goto leave;
+	}
 	list_for_each(iter, &res->granted) {
 		lock = list_entry(iter, struct dlm_lock, list);
 		if (lock->ml.cookie == cnv->cookie &&
@@ -473,6 +479,21 @@
 		}
 		lock = NULL;
 	}
+	if (!lock) {
+		__dlm_print_one_lock_resource(res);
+		list_for_each(iter, &res->granted) {
+			lock = list_entry(iter, struct dlm_lock, list);
+			if (lock->ml.node == cnv->node_idx) {
+				mlog(ML_ERROR, "There is something here "
+				     "for node %u, lock->ml.cookie=%llu, "
+				     "cnv->cookie=%llu\n", cnv->node_idx,
+				     (unsigned long long)lock->ml.cookie,
+				     (unsigned long long)cnv->cookie);
+				break;
+			}
+		}
+		lock = NULL;
+	}
 	spin_unlock(&res->spinlock);
 	if (!lock) {
 		status = DLM_IVLOCKID;
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c
index c7eae5d..3f6c8d8 100644
--- a/fs/ocfs2/dlm/dlmdebug.c
+++ b/fs/ocfs2/dlm/dlmdebug.c
@@ -37,10 +37,8 @@
 
 #include "dlmapi.h"
 #include "dlmcommon.h"
-#include "dlmdebug.h"
 
 #include "dlmdomain.h"
-#include "dlmdebug.h"
 
 #define MLOG_MASK_PREFIX ML_DLM
 #include "cluster/masklog.h"
@@ -120,6 +118,7 @@
 }
 EXPORT_SYMBOL_GPL(dlm_print_one_lock);
 
+#if 0
 void dlm_dump_lock_resources(struct dlm_ctxt *dlm)
 {
 	struct dlm_lock_resource *res;
@@ -136,12 +135,13 @@
 
 	spin_lock(&dlm->spinlock);
 	for (i=0; i<DLM_HASH_BUCKETS; i++) {
-		bucket = &(dlm->lockres_hash[i]);
+		bucket = dlm_lockres_hash(dlm, i);
 		hlist_for_each_entry(res, iter, bucket, hash_node)
 			dlm_print_one_lock_resource(res);
 	}
 	spin_unlock(&dlm->spinlock);
 }
+#endif  /*  0  */
 
 static const char *dlm_errnames[] = {
 	[DLM_NORMAL] =			"DLM_NORMAL",
diff --git a/fs/ocfs2/dlm/dlmdebug.h b/fs/ocfs2/dlm/dlmdebug.h
deleted file mode 100644
index 6858510..0000000
--- a/fs/ocfs2/dlm/dlmdebug.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8; -*-
- * vim: noexpandtab sw=8 ts=8 sts=0:
- *
- * dlmdebug.h
- *
- * Copyright (C) 2004 Oracle.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 021110-1307, USA.
- *
- */
-
-#ifndef DLMDEBUG_H
-#define DLMDEBUG_H
-
-void dlm_dump_lock_resources(struct dlm_ctxt *dlm);
-
-#endif
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 8f3a9e3..b8c23f7 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -41,7 +41,6 @@
 #include "dlmapi.h"
 #include "dlmcommon.h"
 
-#include "dlmdebug.h"
 #include "dlmdomain.h"
 
 #include "dlmver.h"
@@ -49,6 +48,33 @@
 #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_DOMAIN)
 #include "cluster/masklog.h"
 
+static void dlm_free_pagevec(void **vec, int pages)
+{
+	while (pages--)
+		free_page((unsigned long)vec[pages]);
+	kfree(vec);
+}
+
+static void **dlm_alloc_pagevec(int pages)
+{
+	void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL);
+	int i;
+
+	if (!vec)
+		return NULL;
+
+	for (i = 0; i < pages; i++)
+		if (!(vec[i] = (void *)__get_free_page(GFP_KERNEL)))
+			goto out_free;
+
+	mlog(0, "Allocated DLM hash pagevec; %d pages (%lu expected), %lu buckets per page\n",
+	     pages, DLM_HASH_PAGES, (unsigned long)DLM_BUCKETS_PER_PAGE);
+	return vec;
+out_free:
+	dlm_free_pagevec(vec, i);
+	return NULL;
+}
+
 /*
  *
  * spinlock lock ordering: if multiple locks are needed, obey this ordering:
@@ -62,7 +88,7 @@
  *
  */
 
-spinlock_t dlm_domain_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(dlm_domain_lock);
 LIST_HEAD(dlm_domains);
 static DECLARE_WAIT_QUEUE_HEAD(dlm_domain_events);
 
@@ -90,8 +116,7 @@
 	assert_spin_locked(&dlm->spinlock);
 
 	q = &res->lockname;
-	q->hash = full_name_hash(q->name, q->len);
-	bucket = &(dlm->lockres_hash[q->hash % DLM_HASH_BUCKETS]);
+	bucket = dlm_lockres_hash(dlm, q->hash);
 
 	/* get a reference for our hashtable */
 	dlm_lockres_get(res);
@@ -100,34 +125,32 @@
 }
 
 struct dlm_lock_resource * __dlm_lookup_lockres(struct dlm_ctxt *dlm,
-					 const char *name,
-					 unsigned int len)
+						const char *name,
+						unsigned int len,
+						unsigned int hash)
 {
-	unsigned int hash;
-	struct hlist_node *iter;
-	struct dlm_lock_resource *tmpres=NULL;
 	struct hlist_head *bucket;
+	struct hlist_node *list;
 
 	mlog_entry("%.*s\n", len, name);
 
 	assert_spin_locked(&dlm->spinlock);
 
-	hash = full_name_hash(name, len);
+	bucket = dlm_lockres_hash(dlm, hash);
 
-	bucket = &(dlm->lockres_hash[hash % DLM_HASH_BUCKETS]);
-
-	/* check for pre-existing lock */
-	hlist_for_each(iter, bucket) {
-		tmpres = hlist_entry(iter, struct dlm_lock_resource, hash_node);
-		if (tmpres->lockname.len == len &&
-		    memcmp(tmpres->lockname.name, name, len) == 0) {
-			dlm_lockres_get(tmpres);
-			break;
-		}
-
-		tmpres = NULL;
+	hlist_for_each(list, bucket) {
+		struct dlm_lock_resource *res = hlist_entry(list,
+			struct dlm_lock_resource, hash_node);
+		if (res->lockname.name[0] != name[0])
+			continue;
+		if (unlikely(res->lockname.len != len))
+			continue;
+		if (memcmp(res->lockname.name + 1, name + 1, len - 1))
+			continue;
+		dlm_lockres_get(res);
+		return res;
 	}
-	return tmpres;
+	return NULL;
 }
 
 struct dlm_lock_resource * dlm_lookup_lockres(struct dlm_ctxt *dlm,
@@ -135,9 +158,10 @@
 				    unsigned int len)
 {
 	struct dlm_lock_resource *res;
+	unsigned int hash = dlm_lockid_hash(name, len);
 
 	spin_lock(&dlm->spinlock);
-	res = __dlm_lookup_lockres(dlm, name, len);
+	res = __dlm_lookup_lockres(dlm, name, len, hash);
 	spin_unlock(&dlm->spinlock);
 	return res;
 }
@@ -194,7 +218,7 @@
 static void dlm_free_ctxt_mem(struct dlm_ctxt *dlm)
 {
 	if (dlm->lockres_hash)
-		free_page((unsigned long) dlm->lockres_hash);
+		dlm_free_pagevec((void **)dlm->lockres_hash, DLM_HASH_PAGES);
 
 	if (dlm->name)
 		kfree(dlm->name);
@@ -278,11 +302,21 @@
 	return ret;
 }
 
+static void dlm_destroy_dlm_worker(struct dlm_ctxt *dlm)
+{
+	if (dlm->dlm_worker) {
+		flush_workqueue(dlm->dlm_worker);
+		destroy_workqueue(dlm->dlm_worker);
+		dlm->dlm_worker = NULL;
+	}
+}
+
 static void dlm_complete_dlm_shutdown(struct dlm_ctxt *dlm)
 {
 	dlm_unregister_domain_handlers(dlm);
 	dlm_complete_thread(dlm);
 	dlm_complete_recovery_thread(dlm);
+	dlm_destroy_dlm_worker(dlm);
 
 	/* We've left the domain. Now we can take ourselves out of the
 	 * list and allow the kref stuff to help us free the
@@ -304,8 +338,8 @@
 restart:
 	spin_lock(&dlm->spinlock);
 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
-		while (!hlist_empty(&dlm->lockres_hash[i])) {
-			res = hlist_entry(dlm->lockres_hash[i].first,
+		while (!hlist_empty(dlm_lockres_hash(dlm, i))) {
+			res = hlist_entry(dlm_lockres_hash(dlm, i)->first,
 					  struct dlm_lock_resource, hash_node);
 			/* need reference when manually grabbing lockres */
 			dlm_lockres_get(res);
@@ -1126,6 +1160,13 @@
 		goto bail;
 	}
 
+	dlm->dlm_worker = create_singlethread_workqueue("dlm_wq");
+	if (!dlm->dlm_worker) {
+		status = -ENOMEM;
+		mlog_errno(status);
+		goto bail;
+	}
+
 	do {
 		unsigned int backoff;
 		status = dlm_try_to_join_domain(dlm);
@@ -1166,6 +1207,7 @@
 		dlm_unregister_domain_handlers(dlm);
 		dlm_complete_thread(dlm);
 		dlm_complete_recovery_thread(dlm);
+		dlm_destroy_dlm_worker(dlm);
 	}
 
 	return status;
@@ -1191,7 +1233,7 @@
 		goto leave;
 	}
 
-	dlm->lockres_hash = (struct hlist_head *) __get_free_page(GFP_KERNEL);
+	dlm->lockres_hash = (struct hlist_head **)dlm_alloc_pagevec(DLM_HASH_PAGES);
 	if (!dlm->lockres_hash) {
 		mlog_errno(-ENOMEM);
 		kfree(dlm->name);
@@ -1200,8 +1242,8 @@
 		goto leave;
 	}
 
-	for (i=0; i<DLM_HASH_BUCKETS; i++)
-		INIT_HLIST_HEAD(&dlm->lockres_hash[i]);
+	for (i = 0; i < DLM_HASH_BUCKETS; i++)
+		INIT_HLIST_HEAD(dlm_lockres_hash(dlm, i));
 
 	strcpy(dlm->name, domain);
 	dlm->key = key;
@@ -1231,6 +1273,7 @@
 
 	dlm->dlm_thread_task = NULL;
 	dlm->dlm_reco_thread_task = NULL;
+	dlm->dlm_worker = NULL;
 	init_waitqueue_head(&dlm->dlm_thread_wq);
 	init_waitqueue_head(&dlm->dlm_reco_thread_wq);
 	init_waitqueue_head(&dlm->reco.event);
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c
index 7e88e24..033ad17 100644
--- a/fs/ocfs2/dlm/dlmfs.c
+++ b/fs/ocfs2/dlm/dlmfs.c
@@ -116,7 +116,7 @@
 	 * doesn't make sense for LVB writes. */
 	file->f_flags &= ~O_APPEND;
 
-	fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+	fp = kmalloc(sizeof(*fp), GFP_NOFS);
 	if (!fp) {
 		status = -ENOMEM;
 		goto bail;
@@ -196,7 +196,7 @@
 	else
 		readlen = count - *ppos;
 
-	lvb_buf = kmalloc(readlen, GFP_KERNEL);
+	lvb_buf = kmalloc(readlen, GFP_NOFS);
 	if (!lvb_buf)
 		return -ENOMEM;
 
@@ -240,7 +240,7 @@
 	else
 		writelen = count - *ppos;
 
-	lvb_buf = kmalloc(writelen, GFP_KERNEL);
+	lvb_buf = kmalloc(writelen, GFP_NOFS);
 	if (!lvb_buf)
 		return -ENOMEM;
 
@@ -574,10 +574,10 @@
 	.getattr	= simple_getattr,
 };
 
-static struct super_block *dlmfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int dlmfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super);
+	return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super, mnt);
 }
 
 static struct file_system_type dlmfs_fs_type = {
diff --git a/fs/ocfs2/dlm/dlmlock.c b/fs/ocfs2/dlm/dlmlock.c
index 6fea283..5ca57ec 100644
--- a/fs/ocfs2/dlm/dlmlock.c
+++ b/fs/ocfs2/dlm/dlmlock.c
@@ -53,7 +53,7 @@
 #define MLOG_MASK_PREFIX ML_DLM
 #include "cluster/masklog.h"
 
-static spinlock_t dlm_cookie_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dlm_cookie_lock);
 static u64 dlm_next_cookie = 1;
 
 static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm,
@@ -201,6 +201,7 @@
 				      struct dlm_lock *lock, int flags)
 {
 	enum dlm_status status = DLM_DENIED;
+	int lockres_changed = 1;
 
 	mlog_entry("type=%d\n", lock->ml.type);
 	mlog(0, "lockres %.*s, flags = 0x%x\n", res->lockname.len,
@@ -226,8 +227,25 @@
 	res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
 	lock->lock_pending = 0;
 	if (status != DLM_NORMAL) {
-		if (status != DLM_NOTQUEUED)
+		if (status == DLM_RECOVERING &&
+		    dlm_is_recovery_lock(res->lockname.name,
+					 res->lockname.len)) {
+			/* recovery lock was mastered by dead node.
+			 * we need to have calc_usage shoot down this
+			 * lockres and completely remaster it. */
+			mlog(0, "%s: recovery lock was owned by "
+			     "dead node %u, remaster it now.\n",
+			     dlm->name, res->owner);
+		} else if (status != DLM_NOTQUEUED) {
+			/*
+			 * DO NOT call calc_usage, as this would unhash
+			 * the remote lockres before we ever get to use
+			 * it.  treat as if we never made any change to
+			 * the lockres.
+			 */
+			lockres_changed = 0;
 			dlm_error(status);
+		}
 		dlm_revert_pending_lock(res, lock);
 		dlm_lock_put(lock);
 	} else if (dlm_is_recovery_lock(res->lockname.name, 
@@ -239,12 +257,12 @@
 		mlog(0, "%s: $RECOVERY lock for this node (%u) is "
 		     "mastered by %u; got lock, manually granting (no ast)\n",
 		     dlm->name, dlm->node_num, res->owner);
-		list_del_init(&lock->list);
-		list_add_tail(&lock->list, &res->granted);
+		list_move_tail(&lock->list, &res->granted);
 	}
 	spin_unlock(&res->spinlock);
 
-	dlm_lockres_calc_usage(dlm, res);
+	if (lockres_changed)
+		dlm_lockres_calc_usage(dlm, res);
 
 	wake_up(&res->wq);
 	return status;
@@ -281,6 +299,14 @@
 	if (tmpret >= 0) {
 		// successfully sent and received
 		ret = status;  // this is already a dlm_status
+		if (ret == DLM_REJECTED) {
+			mlog(ML_ERROR, "%s:%.*s: BUG.  this is a stale lockres "
+			     "no longer owned by %u.  that node is coming back "
+			     "up currently.\n", dlm->name, create.namelen,
+			     create.name, res->owner);
+			dlm_print_one_lock_resource(res);
+			BUG();
+		}
 	} else {
 		mlog_errno(tmpret);
 		if (dlm_is_host_down(tmpret)) {
@@ -382,13 +408,13 @@
 	struct dlm_lock *lock;
 	int kernel_allocated = 0;
 
-	lock = kcalloc(1, sizeof(*lock), GFP_KERNEL);
+	lock = kcalloc(1, sizeof(*lock), GFP_NOFS);
 	if (!lock)
 		return NULL;
 
 	if (!lksb) {
 		/* zero memory only if kernel-allocated */
-		lksb = kcalloc(1, sizeof(*lksb), GFP_KERNEL);
+		lksb = kcalloc(1, sizeof(*lksb), GFP_NOFS);
 		if (!lksb) {
 			kfree(lock);
 			return NULL;
@@ -429,11 +455,16 @@
 	if (!dlm_grab(dlm))
 		return DLM_REJECTED;
 
-	mlog_bug_on_msg(!dlm_domain_fully_joined(dlm),
-			"Domain %s not fully joined!\n", dlm->name);
-
 	name = create->name;
 	namelen = create->namelen;
+	status = DLM_REJECTED;
+	if (!dlm_domain_fully_joined(dlm)) {
+		mlog(ML_ERROR, "Domain %s not fully joined, but node %u is "
+		     "sending a create_lock message for lock %.*s!\n",
+		     dlm->name, create->node_idx, namelen, name);
+		dlm_error(status);
+		goto leave;
+	}
 
 	status = DLM_IVBUFLEN;
 	if (namelen > DLM_LOCKID_NAME_MAX) {
@@ -669,18 +700,22 @@
 			msleep(100);
 			/* no waiting for dlm_reco_thread */
 			if (recovery) {
-				if (status == DLM_RECOVERING) {
-					mlog(0, "%s: got RECOVERING "
-					     "for $REOCVERY lock, master "
-					     "was %u\n", dlm->name, 
-					     res->owner);
-					dlm_wait_for_node_death(dlm, res->owner, 
-							DLM_NODE_DEATH_WAIT_MAX);
-				}
+				if (status != DLM_RECOVERING)
+					goto retry_lock;
+
+				mlog(0, "%s: got RECOVERING "
+				     "for $RECOVERY lock, master "
+				     "was %u\n", dlm->name,
+				     res->owner);
+				/* wait to see the node go down, then
+				 * drop down and allow the lockres to
+				 * get cleaned up.  need to remaster. */
+				dlm_wait_for_node_death(dlm, res->owner,
+						DLM_NODE_DEATH_WAIT_MAX);
 			} else {
 				dlm_wait_for_recovery(dlm);
+				goto retry_lock;
 			}
-			goto retry_lock;
 		}
 
 		if (status != DLM_NORMAL) {
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 940be4c..1b8346d 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -47,7 +47,6 @@
 
 #include "dlmapi.h"
 #include "dlmcommon.h"
-#include "dlmdebug.h"
 #include "dlmdomain.h"
 
 #define MLOG_MASK_PREFIX (ML_DLM|ML_DLM_MASTER)
@@ -74,6 +73,7 @@
 	wait_queue_head_t wq;
 	atomic_t woken;
 	struct kref mle_refs;
+	int inuse;
 	unsigned long maybe_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
 	unsigned long vote_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
 	unsigned long response_map[BITS_TO_LONGS(O2NM_MAX_NODES)];
@@ -127,18 +127,30 @@
 	return 1;
 }
 
-#if 0
-/* Code here is included but defined out as it aids debugging */
-
-void dlm_print_one_mle(struct dlm_master_list_entry *mle)
+#define dlm_print_nodemap(m)  _dlm_print_nodemap(m,#m)
+static void _dlm_print_nodemap(unsigned long *map, const char *mapname)
 {
-	int i = 0, refs;
+	int i;
+	printk("%s=[ ", mapname);
+	for (i=0; i<O2NM_MAX_NODES; i++)
+		if (test_bit(i, map))
+			printk("%d ", i);
+	printk("]");
+}
+
+static void dlm_print_one_mle(struct dlm_master_list_entry *mle)
+{
+	int refs;
 	char *type;
 	char attached;
 	u8 master;
 	unsigned int namelen;
 	const char *name;
 	struct kref *k;
+	unsigned long *maybe = mle->maybe_map,
+		      *vote = mle->vote_map,
+		      *resp = mle->response_map,
+		      *node = mle->node_map;
 
 	k = &mle->mle_refs;
 	if (mle->type == DLM_MLE_BLOCK)
@@ -159,18 +171,29 @@
 		name = mle->u.res->lockname.name;
 	}
 
-	mlog(ML_NOTICE, "  #%3d: %3s  %3d  %3u   %3u %c    (%d)%.*s\n",
-		  i, type, refs, master, mle->new_master, attached,
-		  namelen, namelen, name);
+	mlog(ML_NOTICE, "%.*s: %3s refs=%3d mas=%3u new=%3u evt=%c inuse=%d ",
+		  namelen, name, type, refs, master, mle->new_master, attached,
+		  mle->inuse);
+	dlm_print_nodemap(maybe);
+	printk(", ");
+	dlm_print_nodemap(vote);
+	printk(", ");
+	dlm_print_nodemap(resp);
+	printk(", ");
+	dlm_print_nodemap(node);
+	printk(", ");
+	printk("\n");
 }
 
+#if 0
+/* Code here is included but defined out as it aids debugging */
+
 static void dlm_dump_mles(struct dlm_ctxt *dlm)
 {
 	struct dlm_master_list_entry *mle;
 	struct list_head *iter;
 	
 	mlog(ML_NOTICE, "dumping all mles for domain %s:\n", dlm->name);
-	mlog(ML_NOTICE, "  ####: type refs owner new events? lockname nodemap votemap respmap maybemap\n");
 	spin_lock(&dlm->master_lock);
 	list_for_each(iter, &dlm->master_list) {
 		mle = list_entry(iter, struct dlm_master_list_entry, list);
@@ -314,6 +337,31 @@
 	spin_unlock(&dlm->spinlock);
 }
 
+static void dlm_get_mle_inuse(struct dlm_master_list_entry *mle)
+{
+	struct dlm_ctxt *dlm;
+	dlm = mle->dlm;
+
+	assert_spin_locked(&dlm->spinlock);
+	assert_spin_locked(&dlm->master_lock);
+	mle->inuse++;
+	kref_get(&mle->mle_refs);
+}
+
+static void dlm_put_mle_inuse(struct dlm_master_list_entry *mle)
+{
+	struct dlm_ctxt *dlm;
+	dlm = mle->dlm;
+
+	spin_lock(&dlm->spinlock);
+	spin_lock(&dlm->master_lock);
+	mle->inuse--;
+	__dlm_put_mle(mle);
+	spin_unlock(&dlm->master_lock);
+	spin_unlock(&dlm->spinlock);
+
+}
+
 /* remove from list and free */
 static void __dlm_put_mle(struct dlm_master_list_entry *mle)
 {
@@ -322,9 +370,14 @@
 
 	assert_spin_locked(&dlm->spinlock);
 	assert_spin_locked(&dlm->master_lock);
-	BUG_ON(!atomic_read(&mle->mle_refs.refcount));
-
-	kref_put(&mle->mle_refs, dlm_mle_release);
+	if (!atomic_read(&mle->mle_refs.refcount)) {
+		/* this may or may not crash, but who cares.
+		 * it's a BUG. */
+		mlog(ML_ERROR, "bad mle: %p\n", mle);
+		dlm_print_one_mle(mle);
+		BUG();
+	} else
+		kref_put(&mle->mle_refs, dlm_mle_release);
 }
 
 
@@ -367,6 +420,7 @@
 	memset(mle->response_map, 0, sizeof(mle->response_map));
 	mle->master = O2NM_MAX_NODES;
 	mle->new_master = O2NM_MAX_NODES;
+	mle->inuse = 0;
 
 	if (mle->type == DLM_MLE_MASTER) {
 		BUG_ON(!res);
@@ -564,6 +618,28 @@
 	mlog(0, "destroying lockres %.*s\n", res->lockname.len,
 	     res->lockname.name);
 
+	if (!hlist_unhashed(&res->hash_node) ||
+	    !list_empty(&res->granted) ||
+	    !list_empty(&res->converting) ||
+	    !list_empty(&res->blocked) ||
+	    !list_empty(&res->dirty) ||
+	    !list_empty(&res->recovering) ||
+	    !list_empty(&res->purge)) {
+		mlog(ML_ERROR,
+		     "Going to BUG for resource %.*s."
+		     "  We're on a list! [%c%c%c%c%c%c%c]\n",
+		     res->lockname.len, res->lockname.name,
+		     !hlist_unhashed(&res->hash_node) ? 'H' : ' ',
+		     !list_empty(&res->granted) ? 'G' : ' ',
+		     !list_empty(&res->converting) ? 'C' : ' ',
+		     !list_empty(&res->blocked) ? 'B' : ' ',
+		     !list_empty(&res->dirty) ? 'D' : ' ',
+		     !list_empty(&res->recovering) ? 'R' : ' ',
+		     !list_empty(&res->purge) ? 'P' : ' ');
+
+		dlm_print_one_lock_resource(res);
+	}
+
 	/* By the time we're ready to blow this guy away, we shouldn't
 	 * be on any lists. */
 	BUG_ON(!hlist_unhashed(&res->hash_node));
@@ -579,11 +655,6 @@
 	kfree(res);
 }
 
-void dlm_lockres_get(struct dlm_lock_resource *res)
-{
-	kref_get(&res->refs);
-}
-
 void dlm_lockres_put(struct dlm_lock_resource *res)
 {
 	kref_put(&res->refs, dlm_lockres_release);
@@ -603,7 +674,7 @@
 	memcpy(qname, name, namelen);
 
 	res->lockname.len = namelen;
-	res->lockname.hash = full_name_hash(name, namelen);
+	res->lockname.hash = dlm_lockid_hash(name, namelen);
 
 	init_waitqueue_head(&res->wq);
 	spin_lock_init(&res->spinlock);
@@ -637,11 +708,11 @@
 {
 	struct dlm_lock_resource *res;
 
-	res = kmalloc(sizeof(struct dlm_lock_resource), GFP_KERNEL);
+	res = kmalloc(sizeof(struct dlm_lock_resource), GFP_NOFS);
 	if (!res)
 		return NULL;
 
-	res->lockname.name = kmalloc(namelen, GFP_KERNEL);
+	res->lockname.name = kmalloc(namelen, GFP_NOFS);
 	if (!res->lockname.name) {
 		kfree(res);
 		return NULL;
@@ -677,19 +748,20 @@
 	int blocked = 0;
 	int ret, nodenum;
 	struct dlm_node_iter iter;
-	unsigned int namelen;
+	unsigned int namelen, hash;
 	int tries = 0;
 	int bit, wait_on_recovery = 0;
 
 	BUG_ON(!lockid);
 
 	namelen = strlen(lockid);
+	hash = dlm_lockid_hash(lockid, namelen);
 
 	mlog(0, "get lockres %s (len %d)\n", lockid, namelen);
 
 lookup:
 	spin_lock(&dlm->spinlock);
-	tmpres = __dlm_lookup_lockres(dlm, lockid, namelen);
+	tmpres = __dlm_lookup_lockres(dlm, lockid, namelen, hash);
 	if (tmpres) {
 		spin_unlock(&dlm->spinlock);
 		mlog(0, "found in hash!\n");
@@ -704,7 +776,7 @@
 		mlog(0, "allocating a new resource\n");
 		/* nothing found and we need to allocate one. */
 		alloc_mle = (struct dlm_master_list_entry *)
-			kmem_cache_alloc(dlm_mle_cache, GFP_KERNEL);
+			kmem_cache_alloc(dlm_mle_cache, GFP_NOFS);
 		if (!alloc_mle)
 			goto leave;
 		res = dlm_new_lockres(dlm, lockid, namelen);
@@ -790,10 +862,11 @@
 	 * if so, the creator of the BLOCK may try to put the last
 	 * ref at this time in the assert master handler, so we
 	 * need an extra one to keep from a bad ptr deref. */
-	dlm_get_mle(mle);
+	dlm_get_mle_inuse(mle);
 	spin_unlock(&dlm->master_lock);
 	spin_unlock(&dlm->spinlock);
 
+redo_request:
 	while (wait_on_recovery) {
 		/* any cluster changes that occurred after dropping the
 		 * dlm spinlock would be detectable be a change on the mle,
@@ -812,7 +885,7 @@
 		} 
 
 		dlm_kick_recovery_thread(dlm);
-		msleep(100);
+		msleep(1000);
 		dlm_wait_for_recovery(dlm);
 
 		spin_lock(&dlm->spinlock);
@@ -825,13 +898,15 @@
 		} else
 			wait_on_recovery = 0;
 		spin_unlock(&dlm->spinlock);
+
+		if (wait_on_recovery)
+			dlm_wait_for_node_recovery(dlm, bit, 10000);
 	}
 
 	/* must wait for lock to be mastered elsewhere */
 	if (blocked)
 		goto wait;
 
-redo_request:
 	ret = -EINVAL;
 	dlm_node_iter_init(mle->vote_map, &iter);
 	while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
@@ -856,6 +931,7 @@
 	/* keep going until the response map includes all nodes */
 	ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked);
 	if (ret < 0) {
+		wait_on_recovery = 1;
 		mlog(0, "%s:%.*s: node map changed, redo the "
 		     "master request now, blocked=%d\n",
 		     dlm->name, res->lockname.len,
@@ -866,7 +942,7 @@
 			     dlm->name, res->lockname.len, 
 			     res->lockname.name, blocked);
 			dlm_print_one_lock_resource(res);
-			/* dlm_print_one_mle(mle); */
+			dlm_print_one_mle(mle);
 			tries = 0;
 		}
 		goto redo_request;
@@ -880,7 +956,7 @@
 	dlm_mle_detach_hb_events(dlm, mle);
 	dlm_put_mle(mle);
 	/* put the extra ref */
-	dlm_put_mle(mle);
+	dlm_put_mle_inuse(mle);
 
 wake_waiters:
 	spin_lock(&res->spinlock);
@@ -921,12 +997,14 @@
 		spin_unlock(&res->spinlock);
 		/* this will cause the master to re-assert across
 		 * the whole cluster, freeing up mles */
-		ret = dlm_do_master_request(mle, res->owner);
-		if (ret < 0) {
-			/* give recovery a chance to run */
-			mlog(ML_ERROR, "link to %u went down?: %d\n", res->owner, ret);
-			msleep(500);
-			goto recheck;
+		if (res->owner != dlm->node_num) {
+			ret = dlm_do_master_request(mle, res->owner);
+			if (ret < 0) {
+				/* give recovery a chance to run */
+				mlog(ML_ERROR, "link to %u went down?: %d\n", res->owner, ret);
+				msleep(500);
+				goto recheck;
+			}
 		}
 		ret = 0;
 		goto leave;
@@ -962,6 +1040,12 @@
 		     "rechecking now\n", dlm->name, res->lockname.len,
 		     res->lockname.name);
 		goto recheck;
+	} else {
+		if (!voting_done) {
+			mlog(0, "map not changed and voting not done "
+			     "for %s:%.*s\n", dlm->name, res->lockname.len,
+			     res->lockname.name);
+		}
 	}
 
 	if (m != O2NM_MAX_NODES) {
@@ -1129,18 +1213,6 @@
 			set_bit(node, mle->vote_map);
 		} else {
 			mlog(ML_ERROR, "node down! %d\n", node);
-
-			/* if the node wasn't involved in mastery skip it,
-			 * but clear it out from the maps so that it will
-			 * not affect mastery of this lockres */
-			clear_bit(node, mle->response_map);
-			clear_bit(node, mle->vote_map);
-			if (!test_bit(node, mle->maybe_map))
-				goto next;
-
-			/* if we're already blocked on lock mastery, and the
-			 * dead node wasn't the expected master, or there is
-			 * another node in the maybe_map, keep waiting */
 			if (blocked) {
 				int lowest = find_next_bit(mle->maybe_map,
 						       O2NM_MAX_NODES, 0);
@@ -1148,54 +1220,53 @@
 				/* act like it was never there */
 				clear_bit(node, mle->maybe_map);
 
-			       	if (node != lowest)
-					goto next;
-
-				mlog(ML_ERROR, "expected master %u died while "
-				     "this node was blocked waiting on it!\n",
-				     node);
-				lowest = find_next_bit(mle->maybe_map,
-						       O2NM_MAX_NODES,
-						       lowest+1);
-				if (lowest < O2NM_MAX_NODES) {
-					mlog(0, "still blocked. waiting "
-					     "on %u now\n", lowest);
-					goto next;
+			       	if (node == lowest) {
+					mlog(0, "expected master %u died"
+					    " while this node was blocked "
+					    "waiting on it!\n", node);
+					lowest = find_next_bit(mle->maybe_map,
+						       	O2NM_MAX_NODES,
+						       	lowest+1);
+					if (lowest < O2NM_MAX_NODES) {
+						mlog(0, "%s:%.*s:still "
+						     "blocked. waiting on %u "
+						     "now\n", dlm->name,
+						     res->lockname.len,
+						     res->lockname.name,
+						     lowest);
+					} else {
+						/* mle is an MLE_BLOCK, but
+						 * there is now nothing left to
+						 * block on.  we need to return
+						 * all the way back out and try
+						 * again with an MLE_MASTER.
+						 * dlm_do_local_recovery_cleanup
+						 * has already run, so the mle
+						 * refcount is ok */
+						mlog(0, "%s:%.*s: no "
+						     "longer blocking. try to "
+						     "master this here\n",
+						     dlm->name,
+						     res->lockname.len,
+						     res->lockname.name);
+						mle->type = DLM_MLE_MASTER;
+						mle->u.res = res;
+					}
 				}
-
-				/* mle is an MLE_BLOCK, but there is now
-				 * nothing left to block on.  we need to return
-				 * all the way back out and try again with
-				 * an MLE_MASTER. dlm_do_local_recovery_cleanup
-				 * has already run, so the mle refcount is ok */
-				mlog(0, "no longer blocking. we can "
-				     "try to master this here\n");
-				mle->type = DLM_MLE_MASTER;
-				memset(mle->maybe_map, 0,
-				       sizeof(mle->maybe_map));
-				memset(mle->response_map, 0,
-				       sizeof(mle->maybe_map));
-				memcpy(mle->vote_map, mle->node_map,
-				       sizeof(mle->node_map));
-				mle->u.res = res;
-				set_bit(dlm->node_num, mle->maybe_map);
-
-				ret = -EAGAIN;
-				goto next;
 			}
 
-			clear_bit(node, mle->maybe_map);
-			if (node > dlm->node_num)
-				goto next;
-
-			mlog(0, "dead node in map!\n");
-			/* yuck. go back and re-contact all nodes
-			 * in the vote_map, removing this node. */
-			memset(mle->response_map, 0,
-			       sizeof(mle->response_map));
+			/* now blank out everything, as if we had never
+			 * contacted anyone */
+			memset(mle->maybe_map, 0, sizeof(mle->maybe_map));
+			memset(mle->response_map, 0, sizeof(mle->response_map));
+			/* reset the vote_map to the current node_map */
+			memcpy(mle->vote_map, mle->node_map,
+			       sizeof(mle->node_map));
+			/* put myself into the maybe map */
+			if (mle->type != DLM_MLE_BLOCK)
+				set_bit(dlm->node_num, mle->maybe_map);
 		}
 		ret = -EAGAIN;
-next:
 		node = dlm_bitmap_diff_iter_next(&bdi, &sc);
 	}
 	return ret;
@@ -1316,7 +1387,7 @@
 	struct dlm_master_request *request = (struct dlm_master_request *) msg->buf;
 	struct dlm_master_list_entry *mle = NULL, *tmpmle = NULL;
 	char *name;
-	unsigned int namelen;
+	unsigned int namelen, hash;
 	int found, ret;
 	int set_maybe;
 	int dispatch_assert = 0;
@@ -1331,6 +1402,7 @@
 
 	name = request->name;
 	namelen = request->namelen;
+	hash = dlm_lockid_hash(name, namelen);
 
 	if (namelen > DLM_LOCKID_NAME_MAX) {
 		response = DLM_IVBUFLEN;
@@ -1339,7 +1411,7 @@
 
 way_up_top:
 	spin_lock(&dlm->spinlock);
-	res = __dlm_lookup_lockres(dlm, name, namelen);
+	res = __dlm_lookup_lockres(dlm, name, namelen, hash);
 	if (res) {
 		spin_unlock(&dlm->spinlock);
 
@@ -1459,21 +1531,18 @@
 			spin_unlock(&dlm->spinlock);
 
 			mle = (struct dlm_master_list_entry *)
-				kmem_cache_alloc(dlm_mle_cache, GFP_KERNEL);
+				kmem_cache_alloc(dlm_mle_cache, GFP_NOFS);
 			if (!mle) {
 				response = DLM_MASTER_RESP_ERROR;
 				mlog_errno(-ENOMEM);
 				goto send_response;
 			}
-			spin_lock(&dlm->spinlock);
-			dlm_init_mle(mle, DLM_MLE_BLOCK, dlm, NULL,
-					 name, namelen);
-			spin_unlock(&dlm->spinlock);
 			goto way_up_top;
 		}
 
 		// mlog(0, "this is second time thru, already allocated, "
 		// "add the block.\n");
+		dlm_init_mle(mle, DLM_MLE_BLOCK, dlm, NULL, name, namelen);
 		set_bit(request->node_idx, mle->maybe_map);
 		list_add(&mle->list, &dlm->master_list);
 		response = DLM_MASTER_RESP_NO;
@@ -1556,6 +1625,8 @@
 	dlm_node_iter_init(nodemap, &iter);
 	while ((to = dlm_node_iter_next(&iter)) >= 0) {
 		int r = 0;
+		struct dlm_master_list_entry *mle = NULL;
+
 		mlog(0, "sending assert master to %d (%.*s)\n", to,
 		     namelen, lockname);
 		memset(&assert, 0, sizeof(assert));
@@ -1567,20 +1638,28 @@
 		tmpret = o2net_send_message(DLM_ASSERT_MASTER_MSG, dlm->key,
 					    &assert, sizeof(assert), to, &r);
 		if (tmpret < 0) {
-			mlog(ML_ERROR, "assert_master returned %d!\n", tmpret);
+			mlog(0, "assert_master returned %d!\n", tmpret);
 			if (!dlm_is_host_down(tmpret)) {
-				mlog(ML_ERROR, "unhandled error!\n");
+				mlog(ML_ERROR, "unhandled error=%d!\n", tmpret);
 				BUG();
 			}
 			/* a node died.  finish out the rest of the nodes. */
-			mlog(ML_ERROR, "link to %d went down!\n", to);
+			mlog(0, "link to %d went down!\n", to);
 			/* any nonzero status return will do */
 			ret = tmpret;
 		} else if (r < 0) {
 			/* ok, something horribly messed.  kill thyself. */
 			mlog(ML_ERROR,"during assert master of %.*s to %u, "
 			     "got %d.\n", namelen, lockname, to, r);
-			dlm_dump_lock_resources(dlm);
+			spin_lock(&dlm->spinlock);
+			spin_lock(&dlm->master_lock);
+			if (dlm_find_mle(dlm, &mle, (char *)lockname,
+					 namelen)) {
+				dlm_print_one_mle(mle);
+				__dlm_put_mle(mle);
+			}
+			spin_unlock(&dlm->master_lock);
+			spin_unlock(&dlm->spinlock);
 			BUG();
 		} else if (r == EAGAIN) {
 			mlog(0, "%.*s: node %u create mles on other "
@@ -1612,7 +1691,7 @@
 	struct dlm_assert_master *assert = (struct dlm_assert_master *)msg->buf;
 	struct dlm_lock_resource *res = NULL;
 	char *name;
-	unsigned int namelen;
+	unsigned int namelen, hash;
 	u32 flags;
 	int master_request = 0;
 	int ret = 0;
@@ -1622,6 +1701,7 @@
 
 	name = assert->name;
 	namelen = assert->namelen;
+	hash = dlm_lockid_hash(name, namelen);
 	flags = be32_to_cpu(assert->flags);
 
 	if (namelen > DLM_LOCKID_NAME_MAX) {
@@ -1646,7 +1726,7 @@
 		if (bit >= O2NM_MAX_NODES) {
 			/* not necessarily an error, though less likely.
 			 * could be master just re-asserting. */
-			mlog(ML_ERROR, "no bits set in the maybe_map, but %u "
+			mlog(0, "no bits set in the maybe_map, but %u "
 			     "is asserting! (%.*s)\n", assert->node_idx,
 			     namelen, name);
 		} else if (bit != assert->node_idx) {
@@ -1658,19 +1738,36 @@
 				 * number winning the mastery will respond
 				 * YES to mastery requests, but this node
 				 * had no way of knowing.  let it pass. */
-				mlog(ML_ERROR, "%u is the lowest node, "
+				mlog(0, "%u is the lowest node, "
 				     "%u is asserting. (%.*s)  %u must "
 				     "have begun after %u won.\n", bit,
 				     assert->node_idx, namelen, name, bit,
 				     assert->node_idx);
 			}
 		}
+		if (mle->type == DLM_MLE_MIGRATION) {
+			if (flags & DLM_ASSERT_MASTER_MLE_CLEANUP) {
+				mlog(0, "%s:%.*s: got cleanup assert"
+				     " from %u for migration\n",
+				     dlm->name, namelen, name,
+				     assert->node_idx);
+			} else if (!(flags & DLM_ASSERT_MASTER_FINISH_MIGRATION)) {
+				mlog(0, "%s:%.*s: got unrelated assert"
+				     " from %u for migration, ignoring\n",
+				     dlm->name, namelen, name,
+				     assert->node_idx);
+				__dlm_put_mle(mle);
+				spin_unlock(&dlm->master_lock);
+				spin_unlock(&dlm->spinlock);
+				goto done;
+			}	
+		}
 	}
 	spin_unlock(&dlm->master_lock);
 
 	/* ok everything checks out with the MLE
 	 * now check to see if there is a lockres */
-	res = __dlm_lookup_lockres(dlm, name, namelen);
+	res = __dlm_lookup_lockres(dlm, name, namelen, hash);
 	if (res) {
 		spin_lock(&res->spinlock);
 		if (res->state & DLM_LOCK_RES_RECOVERING)  {
@@ -1679,7 +1776,8 @@
 			goto kill;
 		}
 		if (!mle) {
-			if (res->owner != assert->node_idx) {
+			if (res->owner != DLM_LOCK_RES_OWNER_UNKNOWN &&
+			    res->owner != assert->node_idx) {
 				mlog(ML_ERROR, "assert_master from "
 					  "%u, but current owner is "
 					  "%u! (%.*s)\n",
@@ -1732,6 +1830,7 @@
 	if (mle) {
 		int extra_ref = 0;
 		int nn = -1;
+		int rr, err = 0;
 		
 		spin_lock(&mle->spinlock);
 		if (mle->type == DLM_MLE_BLOCK || mle->type == DLM_MLE_MIGRATION)
@@ -1751,27 +1850,64 @@
 		wake_up(&mle->wq);
 		spin_unlock(&mle->spinlock);
 
-		if (mle->type == DLM_MLE_MIGRATION && res) {
-			mlog(0, "finishing off migration of lockres %.*s, "
-			     "from %u to %u\n",
-			       res->lockname.len, res->lockname.name,
-			       dlm->node_num, mle->new_master);
+		if (res) {
 			spin_lock(&res->spinlock);
-			res->state &= ~DLM_LOCK_RES_MIGRATING;
-			dlm_change_lockres_owner(dlm, res, mle->new_master);
-			BUG_ON(res->state & DLM_LOCK_RES_DIRTY);
+			if (mle->type == DLM_MLE_MIGRATION) {
+				mlog(0, "finishing off migration of lockres %.*s, "
+			     		"from %u to %u\n",
+			       		res->lockname.len, res->lockname.name,
+			       		dlm->node_num, mle->new_master);
+				res->state &= ~DLM_LOCK_RES_MIGRATING;
+				dlm_change_lockres_owner(dlm, res, mle->new_master);
+				BUG_ON(res->state & DLM_LOCK_RES_DIRTY);
+			} else {
+				dlm_change_lockres_owner(dlm, res, mle->master);
+			}
 			spin_unlock(&res->spinlock);
 		}
-		/* master is known, detach if not already detached */
-		dlm_mle_detach_hb_events(dlm, mle);
-		dlm_put_mle(mle);
-		
+
+		/* master is known, detach if not already detached.
+		 * ensures that only one assert_master call will happen
+		 * on this mle. */
+		spin_lock(&dlm->spinlock);
+		spin_lock(&dlm->master_lock);
+
+		rr = atomic_read(&mle->mle_refs.refcount);
+		if (mle->inuse > 0) {
+			if (extra_ref && rr < 3)
+				err = 1;
+			else if (!extra_ref && rr < 2)
+				err = 1;
+		} else {
+			if (extra_ref && rr < 2)
+				err = 1;
+			else if (!extra_ref && rr < 1)
+				err = 1;
+		}
+		if (err) {
+			mlog(ML_ERROR, "%s:%.*s: got assert master from %u "
+			     "that will mess up this node, refs=%d, extra=%d, "
+			     "inuse=%d\n", dlm->name, namelen, name,
+			     assert->node_idx, rr, extra_ref, mle->inuse);
+			dlm_print_one_mle(mle);
+		}
+		list_del_init(&mle->list);
+		__dlm_mle_detach_hb_events(dlm, mle);
+		__dlm_put_mle(mle);
 		if (extra_ref) {
 			/* the assert master message now balances the extra
 		 	 * ref given by the master / migration request message.
 		 	 * if this is the last put, it will be removed
 		 	 * from the list. */
-			dlm_put_mle(mle);
+			__dlm_put_mle(mle);
+		}
+		spin_unlock(&dlm->master_lock);
+		spin_unlock(&dlm->spinlock);
+	} else if (res) {
+		if (res->owner != assert->node_idx) {
+			mlog(0, "assert_master from %u, but current "
+			     "owner is %u (%.*s), no mle\n", assert->node_idx,
+			     res->owner, namelen, name);
 		}
 	}
 
@@ -1788,12 +1924,12 @@
 
 kill:
 	/* kill the caller! */
+	mlog(ML_ERROR, "Bad message received from another node.  Dumping state "
+	     "and killing the other node now!  This node is OK and can continue.\n");
+	__dlm_print_one_lock_resource(res);
 	spin_unlock(&res->spinlock);
 	spin_unlock(&dlm->spinlock);
 	dlm_lockres_put(res);
-	mlog(ML_ERROR, "Bad message received from another node.  Dumping state "
-	     "and killing the other node now!  This node is OK and can continue.\n");
-	dlm_dump_lock_resources(dlm);
 	dlm_put(dlm);
 	return -EINVAL;
 }
@@ -1803,7 +1939,7 @@
 			       int ignore_higher, u8 request_from, u32 flags)
 {
 	struct dlm_work_item *item;
-	item = kcalloc(1, sizeof(*item), GFP_KERNEL);
+	item = kcalloc(1, sizeof(*item), GFP_NOFS);
 	if (!item)
 		return -ENOMEM;
 
@@ -1825,7 +1961,7 @@
 	list_add_tail(&item->list, &dlm->work_list);
 	spin_unlock(&dlm->work_lock);
 
-	schedule_work(&dlm->dispatched_work);
+	queue_work(dlm->dlm_worker, &dlm->dispatched_work);
 	return 0;
 }
 
@@ -1866,6 +2002,23 @@
 		}
 	}
 
+	/*
+	 * If we're migrating this lock to someone else, we are no
+	 * longer allowed to assert out own mastery.  OTOH, we need to
+	 * prevent migration from starting while we're still asserting
+	 * our dominance.  The reserved ast delays migration.
+	 */
+	spin_lock(&res->spinlock);
+	if (res->state & DLM_LOCK_RES_MIGRATING) {
+		mlog(0, "Someone asked us to assert mastery, but we're "
+		     "in the middle of migration.  Skipping assert, "
+		     "the new master will handle that.\n");
+		spin_unlock(&res->spinlock);
+		goto put;
+	} else
+		__dlm_lockres_reserve_ast(res);
+	spin_unlock(&res->spinlock);
+
 	/* this call now finishes out the nodemap
 	 * even if one or more nodes die */
 	mlog(0, "worker about to master %.*s here, this=%u\n",
@@ -1875,9 +2028,14 @@
 				   nodemap, flags);
 	if (ret < 0) {
 		/* no need to restart, we are done */
-		mlog_errno(ret);
+		if (!dlm_is_host_down(ret))
+			mlog_errno(ret);
 	}
 
+	/* Ok, we've asserted ourselves.  Let's let migration start. */
+	dlm_lockres_release_ast(dlm, res);
+
+put:
 	dlm_lockres_put(res);
 
 	mlog(0, "finished with dlm_assert_master_worker\n");
@@ -1916,6 +2074,7 @@
 				BUG();
 			/* host is down, so answer for that node would be
 			 * DLM_LOCK_RES_OWNER_UNKNOWN.  continue. */
+			ret = 0;
 		}
 
 		if (master != DLM_LOCK_RES_OWNER_UNKNOWN) {
@@ -2016,14 +2175,14 @@
 	 */
 
 	ret = -ENOMEM;
-	mres = (struct dlm_migratable_lockres *) __get_free_page(GFP_KERNEL);
+	mres = (struct dlm_migratable_lockres *) __get_free_page(GFP_NOFS);
 	if (!mres) {
 		mlog_errno(ret);
 		goto leave;
 	}
 
 	mle = (struct dlm_master_list_entry *) kmem_cache_alloc(dlm_mle_cache,
-								GFP_KERNEL);
+								GFP_NOFS);
 	if (!mle) {
 		mlog_errno(ret);
 		goto leave;
@@ -2117,7 +2276,7 @@
 	 * take both dlm->spinlock and dlm->master_lock */
 	spin_lock(&dlm->spinlock);
 	spin_lock(&dlm->master_lock);
-	dlm_get_mle(mle);
+	dlm_get_mle_inuse(mle);
 	spin_unlock(&dlm->master_lock);
 	spin_unlock(&dlm->spinlock);
 
@@ -2134,7 +2293,10 @@
 		/* migration failed, detach and clean up mle */
 		dlm_mle_detach_hb_events(dlm, mle);
 		dlm_put_mle(mle);
-		dlm_put_mle(mle);
+		dlm_put_mle_inuse(mle);
+		spin_lock(&res->spinlock);
+		res->state &= ~DLM_LOCK_RES_MIGRATING;
+		spin_unlock(&res->spinlock);
 		goto leave;
 	}
 
@@ -2164,8 +2326,8 @@
 			/* avoid hang during shutdown when migrating lockres 
 			 * to a node which also goes down */
 			if (dlm_is_node_dead(dlm, target)) {
-				mlog(0, "%s:%.*s: expected migration target %u "
-				     "is no longer up.  restarting.\n",
+				mlog(0, "%s:%.*s: expected migration "
+				     "target %u is no longer up, restarting\n",
 				     dlm->name, res->lockname.len,
 				     res->lockname.name, target);
 				ret = -ERESTARTSYS;
@@ -2175,7 +2337,10 @@
 			/* migration failed, detach and clean up mle */
 			dlm_mle_detach_hb_events(dlm, mle);
 			dlm_put_mle(mle);
-			dlm_put_mle(mle);
+			dlm_put_mle_inuse(mle);
+			spin_lock(&res->spinlock);
+			res->state &= ~DLM_LOCK_RES_MIGRATING;
+			spin_unlock(&res->spinlock);
 			goto leave;
 		}
 		/* TODO: if node died: stop, clean up, return error */
@@ -2191,7 +2356,7 @@
 
 	/* master is known, detach if not already detached */
 	dlm_mle_detach_hb_events(dlm, mle);
-	dlm_put_mle(mle);
+	dlm_put_mle_inuse(mle);
 	ret = 0;
 
 	dlm_lockres_calc_usage(dlm, res);
@@ -2462,7 +2627,7 @@
 	struct dlm_migrate_request *migrate = (struct dlm_migrate_request *) msg->buf;
 	struct dlm_master_list_entry *mle = NULL, *oldmle = NULL;
 	const char *name;
-	unsigned int namelen;
+	unsigned int namelen, hash;
 	int ret = 0;
 
 	if (!dlm_grab(dlm))
@@ -2470,10 +2635,11 @@
 
 	name = migrate->name;
 	namelen = migrate->namelen;
+	hash = dlm_lockid_hash(name, namelen);
 
 	/* preallocate.. if this fails, abort */
 	mle = (struct dlm_master_list_entry *) kmem_cache_alloc(dlm_mle_cache,
-							 GFP_KERNEL);
+							 GFP_NOFS);
 
 	if (!mle) {
 		ret = -ENOMEM;
@@ -2482,7 +2648,7 @@
 
 	/* check for pre-existing lock */
 	spin_lock(&dlm->spinlock);
-	res = __dlm_lookup_lockres(dlm, name, namelen);
+	res = __dlm_lookup_lockres(dlm, name, namelen, hash);
 	spin_lock(&dlm->master_lock);
 
 	if (res) {
@@ -2580,6 +2746,7 @@
 			/* remove it from the list so that only one
 			 * mle will be found */
 			list_del_init(&tmp->list);
+			__dlm_mle_detach_hb_events(dlm, mle);
 		}
 		spin_unlock(&tmp->spinlock);
 	}
@@ -2601,6 +2768,7 @@
 	struct list_head *iter, *iter2;
 	struct dlm_master_list_entry *mle;
 	struct dlm_lock_resource *res;
+	unsigned int hash;
 
 	mlog_entry("dlm=%s, dead node=%u\n", dlm->name, dead_node);
 top:
@@ -2640,7 +2808,7 @@
 				 * may result in the mle being unlinked and
 				 * freed, but there may still be a process
 				 * waiting in the dlmlock path which is fine. */
-				mlog(ML_ERROR, "node %u was expected master\n",
+				mlog(0, "node %u was expected master\n",
 				     dead_node);
 				atomic_set(&mle->woken, 1);
 				spin_unlock(&mle->spinlock);
@@ -2673,19 +2841,21 @@
 
 		/* remove from the list early.  NOTE: unlinking
 		 * list_head while in list_for_each_safe */
+		__dlm_mle_detach_hb_events(dlm, mle);
 		spin_lock(&mle->spinlock);
 		list_del_init(&mle->list);
 		atomic_set(&mle->woken, 1);
 		spin_unlock(&mle->spinlock);
 		wake_up(&mle->wq);
 
-		mlog(0, "node %u died during migration from "
-		     "%u to %u!\n", dead_node,
+		mlog(0, "%s: node %u died during migration from "
+		     "%u to %u!\n", dlm->name, dead_node,
 		     mle->master, mle->new_master);
 		/* if there is a lockres associated with this
 	 	 * mle, find it and set its owner to UNKNOWN */
+		hash = dlm_lockid_hash(mle->u.name.name, mle->u.name.len);
 		res = __dlm_lookup_lockres(dlm, mle->u.name.name,
-					mle->u.name.len);
+					   mle->u.name.len, hash);
 		if (res) {
 			/* unfortunately if we hit this rare case, our
 		 	 * lock ordering is messed.  we need to drop
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 805cbab..29b2845 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -98,8 +98,8 @@
 
 static u64 dlm_get_next_mig_cookie(void);
 
-static spinlock_t dlm_reco_state_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t dlm_mig_cookie_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(dlm_reco_state_lock);
+static DEFINE_SPINLOCK(dlm_mig_cookie_lock);
 static u64 dlm_mig_cookie = 1;
 
 static u64 dlm_get_next_mig_cookie(void)
@@ -115,12 +115,37 @@
 	return c;
 }
 
+static inline void dlm_set_reco_dead_node(struct dlm_ctxt *dlm,
+					  u8 dead_node)
+{
+	assert_spin_locked(&dlm->spinlock);
+	if (dlm->reco.dead_node != dead_node)
+		mlog(0, "%s: changing dead_node from %u to %u\n",
+		     dlm->name, dlm->reco.dead_node, dead_node);
+	dlm->reco.dead_node = dead_node;
+}
+
+static inline void dlm_set_reco_master(struct dlm_ctxt *dlm,
+				       u8 master)
+{
+	assert_spin_locked(&dlm->spinlock);
+	mlog(0, "%s: changing new_master from %u to %u\n",
+	     dlm->name, dlm->reco.new_master, master);
+	dlm->reco.new_master = master;
+}
+
+static inline void __dlm_reset_recovery(struct dlm_ctxt *dlm)
+{
+	assert_spin_locked(&dlm->spinlock);
+	clear_bit(dlm->reco.dead_node, dlm->recovery_map);
+	dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM);
+	dlm_set_reco_master(dlm, O2NM_INVALID_NODE_NUM);
+}
+
 static inline void dlm_reset_recovery(struct dlm_ctxt *dlm)
 {
 	spin_lock(&dlm->spinlock);
-	clear_bit(dlm->reco.dead_node, dlm->recovery_map);
-	dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
-	dlm->reco.new_master = O2NM_INVALID_NODE_NUM;
+	__dlm_reset_recovery(dlm);
 	spin_unlock(&dlm->spinlock);
 }
 
@@ -132,12 +157,21 @@
 	struct list_head *iter, *iter2;
 	struct dlm_work_item *item;
 	dlm_workfunc_t *workfunc;
+	int tot=0;
+
+	if (!dlm_joined(dlm))
+		return;
 
 	spin_lock(&dlm->work_lock);
 	list_splice_init(&dlm->work_list, &tmp_list);
 	spin_unlock(&dlm->work_lock);
 
 	list_for_each_safe(iter, iter2, &tmp_list) {
+		tot++;
+	}
+	mlog(0, "%s: work thread has %d work items\n", dlm->name, tot);
+
+	list_for_each_safe(iter, iter2, &tmp_list) {
 		item = list_entry(iter, struct dlm_work_item, list);
 		workfunc = item->func;
 		list_del_init(&item->list);
@@ -220,6 +254,52 @@
  *
  */
 
+static void dlm_print_reco_node_status(struct dlm_ctxt *dlm)
+{
+	struct dlm_reco_node_data *ndata;
+	struct dlm_lock_resource *res;
+
+	mlog(ML_NOTICE, "%s(%d): recovery info, state=%s, dead=%u, master=%u\n",
+	     dlm->name, dlm->dlm_reco_thread_task->pid,
+	     dlm->reco.state & DLM_RECO_STATE_ACTIVE ? "ACTIVE" : "inactive",
+	     dlm->reco.dead_node, dlm->reco.new_master);
+
+	list_for_each_entry(ndata, &dlm->reco.node_data, list) {
+		char *st = "unknown";
+		switch (ndata->state) {
+			case DLM_RECO_NODE_DATA_INIT:
+				st = "init";
+				break;
+			case DLM_RECO_NODE_DATA_REQUESTING:
+				st = "requesting";
+				break;
+			case DLM_RECO_NODE_DATA_DEAD:
+				st = "dead";
+				break;
+			case DLM_RECO_NODE_DATA_RECEIVING:
+				st = "receiving";
+				break;
+			case DLM_RECO_NODE_DATA_REQUESTED:
+				st = "requested";
+				break;
+			case DLM_RECO_NODE_DATA_DONE:
+				st = "done";
+				break;
+			case DLM_RECO_NODE_DATA_FINALIZE_SENT:
+				st = "finalize-sent";
+				break;
+			default:
+				st = "bad";
+				break;
+		}
+		mlog(ML_NOTICE, "%s: reco state, node %u, state=%s\n",
+		     dlm->name, ndata->node_num, st);
+	}
+	list_for_each_entry(res, &dlm->reco.resources, recovering) {
+		mlog(ML_NOTICE, "%s: lockres %.*s on recovering list\n",
+		     dlm->name, res->lockname.len, res->lockname.name);
+	}
+}
 
 #define DLM_RECO_THREAD_TIMEOUT_MS (5 * 1000)
 
@@ -267,11 +347,23 @@
 {
 	int dead;
 	spin_lock(&dlm->spinlock);
-	dead = test_bit(node, dlm->domain_map);
+	dead = !test_bit(node, dlm->domain_map);
 	spin_unlock(&dlm->spinlock);
 	return dead;
 }
 
+/* returns true if node is no longer in the domain
+ * could be dead or just not joined */
+static int dlm_is_node_recovered(struct dlm_ctxt *dlm, u8 node)
+{
+	int recovered;
+	spin_lock(&dlm->spinlock);
+	recovered = !test_bit(node, dlm->recovery_map);
+	spin_unlock(&dlm->spinlock);
+	return recovered;
+}
+
+
 int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout)
 {
 	if (timeout) {
@@ -290,6 +382,24 @@
 	return 0;
 }
 
+int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout)
+{
+	if (timeout) {
+		mlog(0, "%s: waiting %dms for notification of "
+		     "recovery of node %u\n", dlm->name, timeout, node);
+		wait_event_timeout(dlm->dlm_reco_thread_wq,
+			   dlm_is_node_recovered(dlm, node),
+			   msecs_to_jiffies(timeout));
+	} else {
+		mlog(0, "%s: waiting indefinitely for notification "
+		     "of recovery of node %u\n", dlm->name, node);
+		wait_event(dlm->dlm_reco_thread_wq,
+			   dlm_is_node_recovered(dlm, node));
+	}
+	/* for now, return 0 */
+	return 0;
+}
+
 /* callers of the top-level api calls (dlmlock/dlmunlock) should
  * block on the dlm->reco.event when recovery is in progress.
  * the dlm recovery thread will set this state when it begins
@@ -308,6 +418,13 @@
 
 void dlm_wait_for_recovery(struct dlm_ctxt *dlm)
 {
+	if (dlm_in_recovery(dlm)) {
+		mlog(0, "%s: reco thread %d in recovery: "
+		     "state=%d, master=%u, dead=%u\n",
+		     dlm->name, dlm->dlm_reco_thread_task->pid,
+		     dlm->reco.state, dlm->reco.new_master,
+		     dlm->reco.dead_node);
+	}
 	wait_event(dlm->reco.event, !dlm_in_recovery(dlm));
 }
 
@@ -341,7 +458,7 @@
 		mlog(0, "new master %u died while recovering %u!\n",
 		     dlm->reco.new_master, dlm->reco.dead_node);
 		/* unset the new_master, leave dead_node */
-		dlm->reco.new_master = O2NM_INVALID_NODE_NUM;
+		dlm_set_reco_master(dlm, O2NM_INVALID_NODE_NUM);
 	}
 
 	/* select a target to recover */
@@ -350,14 +467,14 @@
 
 		bit = find_next_bit (dlm->recovery_map, O2NM_MAX_NODES+1, 0);
 		if (bit >= O2NM_MAX_NODES || bit < 0)
-			dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
+			dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM);
 		else
-			dlm->reco.dead_node = bit;
+			dlm_set_reco_dead_node(dlm, bit);
 	} else if (!test_bit(dlm->reco.dead_node, dlm->recovery_map)) {
 		/* BUG? */
 		mlog(ML_ERROR, "dead_node %u no longer in recovery map!\n",
 		     dlm->reco.dead_node);
-		dlm->reco.dead_node = O2NM_INVALID_NODE_NUM;
+		dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM);
 	}
 
 	if (dlm->reco.dead_node == O2NM_INVALID_NODE_NUM) {
@@ -366,7 +483,8 @@
 		/* return to main thread loop and sleep. */
 		return 0;
 	}
-	mlog(0, "recovery thread found node %u in the recovery map!\n",
+	mlog(0, "%s(%d):recovery thread found node %u in the recovery map!\n",
+	     dlm->name, dlm->dlm_reco_thread_task->pid,
 	     dlm->reco.dead_node);
 	spin_unlock(&dlm->spinlock);
 
@@ -389,8 +507,8 @@
 		}
 		mlog(0, "another node will master this recovery session.\n");
 	}
-	mlog(0, "dlm=%s, new_master=%u, this node=%u, dead_node=%u\n",
-	     dlm->name, dlm->reco.new_master,
+	mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n",
+	     dlm->name, dlm->dlm_reco_thread_task->pid, dlm->reco.new_master,
 	     dlm->node_num, dlm->reco.dead_node);
 
 	/* it is safe to start everything back up here
@@ -402,11 +520,13 @@
 	return 0;
 
 master_here:
-	mlog(0, "mastering recovery of %s:%u here(this=%u)!\n",
+	mlog(0, "(%d) mastering recovery of %s:%u here(this=%u)!\n",
+	     dlm->dlm_reco_thread_task->pid,
 	     dlm->name, dlm->reco.dead_node, dlm->node_num);
 
 	status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
 	if (status < 0) {
+		/* we should never hit this anymore */
 		mlog(ML_ERROR, "error %d remastering locks for node %u, "
 		     "retrying.\n", status, dlm->reco.dead_node);
 		/* yield a bit to allow any final network messages
@@ -433,9 +553,16 @@
 	int destroy = 0;
 	int pass = 0;
 
-	status = dlm_init_recovery_area(dlm, dead_node);
-	if (status < 0)
-		goto leave;
+	do {
+		/* we have become recovery master.  there is no escaping
+		 * this, so just keep trying until we get it. */
+		status = dlm_init_recovery_area(dlm, dead_node);
+		if (status < 0) {
+			mlog(ML_ERROR, "%s: failed to alloc recovery area, "
+			     "retrying\n", dlm->name);
+			msleep(1000);
+		}
+	} while (status != 0);
 
 	/* safe to access the node data list without a lock, since this
 	 * process is the only one to change the list */
@@ -452,16 +579,36 @@
 			continue;
 		}
 
-		status = dlm_request_all_locks(dlm, ndata->node_num, dead_node);
-		if (status < 0) {
-			mlog_errno(status);
-			if (dlm_is_host_down(status))
-				ndata->state = DLM_RECO_NODE_DATA_DEAD;
-			else {
-				destroy = 1;
-				goto leave;
+		do {
+			status = dlm_request_all_locks(dlm, ndata->node_num,
+						       dead_node);
+			if (status < 0) {
+				mlog_errno(status);
+				if (dlm_is_host_down(status)) {
+					/* node died, ignore it for recovery */
+					status = 0;
+					ndata->state = DLM_RECO_NODE_DATA_DEAD;
+					/* wait for the domain map to catch up
+					 * with the network state. */
+					wait_event_timeout(dlm->dlm_reco_thread_wq,
+							   dlm_is_node_dead(dlm,
+								ndata->node_num),
+							   msecs_to_jiffies(1000));
+					mlog(0, "waited 1 sec for %u, "
+					     "dead? %s\n", ndata->node_num,
+					     dlm_is_node_dead(dlm, ndata->node_num) ?
+					     "yes" : "no");
+				} else {
+					/* -ENOMEM on the other node */
+					mlog(0, "%s: node %u returned "
+					     "%d during recovery, retrying "
+					     "after a short wait\n",
+					     dlm->name, ndata->node_num,
+					     status);
+					msleep(100);
+				}
 			}
-		}
+		} while (status != 0);
 
 		switch (ndata->state) {
 			case DLM_RECO_NODE_DATA_INIT:
@@ -473,10 +620,9 @@
 				mlog(0, "node %u died after requesting "
 				     "recovery info for node %u\n",
 				     ndata->node_num, dead_node);
-				// start all over
-				destroy = 1;
-				status = -EAGAIN;
-				goto leave;
+				/* fine.  don't need this node's info.
+				 * continue without it. */
+				break;
 			case DLM_RECO_NODE_DATA_REQUESTING:
 				ndata->state = DLM_RECO_NODE_DATA_REQUESTED;
 				mlog(0, "now receiving recovery data from "
@@ -520,35 +666,26 @@
 					BUG();
 					break;
 				case DLM_RECO_NODE_DATA_DEAD:
-					mlog(ML_NOTICE, "node %u died after "
+					mlog(0, "node %u died after "
 					     "requesting recovery info for "
 					     "node %u\n", ndata->node_num,
 					     dead_node);
-					spin_unlock(&dlm_reco_state_lock);
-					// start all over
-					destroy = 1;
-					status = -EAGAIN;
-					/* instead of spinning like crazy here,
-					 * wait for the domain map to catch up
-					 * with the network state.  otherwise this
-					 * can be hit hundreds of times before
-					 * the node is really seen as dead. */
-					wait_event_timeout(dlm->dlm_reco_thread_wq,
-							   dlm_is_node_dead(dlm,
-								ndata->node_num),
-							   msecs_to_jiffies(1000));
-					mlog(0, "waited 1 sec for %u, "
-					     "dead? %s\n", ndata->node_num,
-					     dlm_is_node_dead(dlm, ndata->node_num) ?
-					     "yes" : "no");
-					goto leave;
+					break;
 				case DLM_RECO_NODE_DATA_RECEIVING:
 				case DLM_RECO_NODE_DATA_REQUESTED:
+					mlog(0, "%s: node %u still in state %s\n",
+					     dlm->name, ndata->node_num,
+					     ndata->state==DLM_RECO_NODE_DATA_RECEIVING ?
+					     "receiving" : "requested");
 					all_nodes_done = 0;
 					break;
 				case DLM_RECO_NODE_DATA_DONE:
+					mlog(0, "%s: node %u state is done\n",
+					     dlm->name, ndata->node_num);
 					break;
 				case DLM_RECO_NODE_DATA_FINALIZE_SENT:
+					mlog(0, "%s: node %u state is finalize\n",
+					     dlm->name, ndata->node_num);
 					break;
 			}
 		}
@@ -578,7 +715,7 @@
 			     jiffies, dlm->reco.dead_node,
 			     dlm->node_num, dlm->reco.new_master);
 			destroy = 1;
-			status = ret;
+			status = 0;
 			/* rescan everything marked dirty along the way */
 			dlm_kick_thread(dlm, NULL);
 			break;
@@ -591,7 +728,6 @@
 
 	}
 
-leave:
 	if (destroy)
 		dlm_destroy_recovery_area(dlm, dead_node);
 
@@ -617,7 +753,7 @@
 		}
 		BUG_ON(num == dead_node);
 
-		ndata = kcalloc(1, sizeof(*ndata), GFP_KERNEL);
+		ndata = kcalloc(1, sizeof(*ndata), GFP_NOFS);
 		if (!ndata) {
 			dlm_destroy_recovery_area(dlm, dead_node);
 			return -ENOMEM;
@@ -691,16 +827,25 @@
 	if (!dlm_grab(dlm))
 		return -EINVAL;
 
+	if (lr->dead_node != dlm->reco.dead_node) {
+		mlog(ML_ERROR, "%s: node %u sent dead_node=%u, but local "
+		     "dead_node is %u\n", dlm->name, lr->node_idx,
+		     lr->dead_node, dlm->reco.dead_node);
+		dlm_print_reco_node_status(dlm);
+		/* this is a hack */
+		dlm_put(dlm);
+		return -ENOMEM;
+	}
 	BUG_ON(lr->dead_node != dlm->reco.dead_node);
 
-	item = kcalloc(1, sizeof(*item), GFP_KERNEL);
+	item = kcalloc(1, sizeof(*item), GFP_NOFS);
 	if (!item) {
 		dlm_put(dlm);
 		return -ENOMEM;
 	}
 
 	/* this will get freed by dlm_request_all_locks_worker */
-	buf = (char *) __get_free_page(GFP_KERNEL);
+	buf = (char *) __get_free_page(GFP_NOFS);
 	if (!buf) {
 		kfree(item);
 		dlm_put(dlm);
@@ -715,7 +860,7 @@
 	spin_lock(&dlm->work_lock);
 	list_add_tail(&item->list, &dlm->work_list);
 	spin_unlock(&dlm->work_lock);
-	schedule_work(&dlm->dispatched_work);
+	queue_work(dlm->dlm_worker, &dlm->dispatched_work);
 
 	dlm_put(dlm);
 	return 0;
@@ -730,32 +875,34 @@
 	struct list_head *iter;
 	int ret;
 	u8 dead_node, reco_master;
+	int skip_all_done = 0;
 
 	dlm = item->dlm;
 	dead_node = item->u.ral.dead_node;
 	reco_master = item->u.ral.reco_master;
 	mres = (struct dlm_migratable_lockres *)data;
 
+	mlog(0, "%s: recovery worker started, dead=%u, master=%u\n",
+	     dlm->name, dead_node, reco_master);
+
 	if (dead_node != dlm->reco.dead_node ||
 	    reco_master != dlm->reco.new_master) {
-		/* show extra debug info if the recovery state is messed */
-		mlog(ML_ERROR, "%s: bad reco state: reco(dead=%u, master=%u), "
-		     "request(dead=%u, master=%u)\n",
-		     dlm->name, dlm->reco.dead_node, dlm->reco.new_master,
-		     dead_node, reco_master);
-		mlog(ML_ERROR, "%s: name=%.*s master=%u locks=%u/%u flags=%u "
-		     "entry[0]={c=%u:%llu,l=%u,f=%u,t=%d,ct=%d,hb=%d,n=%u}\n",
-		     dlm->name, mres->lockname_len, mres->lockname, mres->master,
-		     mres->num_locks, mres->total_locks, mres->flags,
-		     dlm_get_lock_cookie_node(mres->ml[0].cookie),
-		     dlm_get_lock_cookie_seq(mres->ml[0].cookie),
-		     mres->ml[0].list, mres->ml[0].flags,
-		     mres->ml[0].type, mres->ml[0].convert_type,
-		     mres->ml[0].highest_blocked, mres->ml[0].node);
-		BUG();
+		/* worker could have been created before the recovery master
+		 * died.  if so, do not continue, but do not error. */
+		if (dlm->reco.new_master == O2NM_INVALID_NODE_NUM) {
+			mlog(ML_NOTICE, "%s: will not send recovery state, "
+			     "recovery master %u died, thread=(dead=%u,mas=%u)"
+			     " current=(dead=%u,mas=%u)\n", dlm->name,
+			     reco_master, dead_node, reco_master,
+			     dlm->reco.dead_node, dlm->reco.new_master);
+		} else {
+			mlog(ML_NOTICE, "%s: reco state invalid: reco(dead=%u, "
+			     "master=%u), request(dead=%u, master=%u)\n",
+			     dlm->name, dlm->reco.dead_node,
+			     dlm->reco.new_master, dead_node, reco_master);
+		}
+		goto leave;
 	}
-	BUG_ON(dead_node != dlm->reco.dead_node);
-	BUG_ON(reco_master != dlm->reco.new_master);
 
 	/* lock resources should have already been moved to the
  	 * dlm->reco.resources list.  now move items from that list
@@ -766,12 +913,20 @@
 	dlm_move_reco_locks_to_list(dlm, &resources, dead_node);
 
 	/* now we can begin blasting lockreses without the dlm lock */
+
+	/* any errors returned will be due to the new_master dying,
+	 * the dlm_reco_thread should detect this */
 	list_for_each(iter, &resources) {
 		res = list_entry (iter, struct dlm_lock_resource, recovering);
 		ret = dlm_send_one_lockres(dlm, res, mres, reco_master,
 				   	DLM_MRES_RECOVERY);
-		if (ret < 0)
-			mlog_errno(ret);
+		if (ret < 0) {
+			mlog(ML_ERROR, "%s: node %u went down while sending "
+			     "recovery state for dead node %u, ret=%d\n", dlm->name,
+			     reco_master, dead_node, ret);
+			skip_all_done = 1;
+			break;
+		}
 	}
 
 	/* move the resources back to the list */
@@ -779,10 +934,15 @@
 	list_splice_init(&resources, &dlm->reco.resources);
 	spin_unlock(&dlm->spinlock);
 
-	ret = dlm_send_all_done_msg(dlm, dead_node, reco_master);
-	if (ret < 0)
-		mlog_errno(ret);
-
+	if (!skip_all_done) {
+		ret = dlm_send_all_done_msg(dlm, dead_node, reco_master);
+		if (ret < 0) {
+			mlog(ML_ERROR, "%s: node %u went down while sending "
+			     "recovery all-done for dead node %u, ret=%d\n",
+			     dlm->name, reco_master, dead_node, ret);
+		}
+	}
+leave:
 	free_page((unsigned long)data);
 }
 
@@ -801,8 +961,14 @@
 
 	ret = o2net_send_message(DLM_RECO_DATA_DONE_MSG, dlm->key, &done_msg,
 				 sizeof(done_msg), send_to, &tmpret);
-	/* negative status is ignored by the caller */
-	if (ret >= 0)
+	if (ret < 0) {
+		if (!dlm_is_host_down(ret)) {
+			mlog_errno(ret);
+			mlog(ML_ERROR, "%s: unknown error sending data-done "
+			     "to %u\n", dlm->name, send_to);
+			BUG();
+		}
+	} else
 		ret = tmpret;
 	return ret;
 }
@@ -822,7 +988,11 @@
 	mlog(0, "got DATA DONE: dead_node=%u, reco.dead_node=%u, "
 	     "node_idx=%u, this node=%u\n", done->dead_node,
 	     dlm->reco.dead_node, done->node_idx, dlm->node_num);
-	BUG_ON(done->dead_node != dlm->reco.dead_node);
+
+	mlog_bug_on_msg((done->dead_node != dlm->reco.dead_node),
+			"Got DATA DONE: dead_node=%u, reco.dead_node=%u, "
+			"node_idx=%u, this node=%u\n", done->dead_node,
+			dlm->reco.dead_node, done->node_idx, dlm->node_num);
 
 	spin_lock(&dlm_reco_state_lock);
 	list_for_each(iter, &dlm->reco.node_data) {
@@ -905,13 +1075,11 @@
 			mlog(0, "found lockres owned by dead node while "
 				  "doing recovery for node %u. sending it.\n",
 				  dead_node);
-			list_del_init(&res->recovering);
-			list_add_tail(&res->recovering, list);
+			list_move_tail(&res->recovering, list);
 		} else if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
 			mlog(0, "found UNKNOWN owner while doing recovery "
 				  "for node %u. sending it.\n", dead_node);
-			list_del_init(&res->recovering);
-			list_add_tail(&res->recovering, list);
+			list_move_tail(&res->recovering, list);
 		}
 	}
 	spin_unlock(&dlm->spinlock);
@@ -1023,8 +1191,9 @@
 		    ml->type == LKM_PRMODE) {
 			/* if it is already set, this had better be a PR
 			 * and it has to match */
-			if (mres->lvb[0] && (ml->type == LKM_EXMODE ||
-			    memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) {
+			if (!dlm_lvb_is_empty(mres->lvb) &&
+			    (ml->type == LKM_EXMODE ||
+			     memcmp(mres->lvb, lock->lksb->lvb, DLM_LVB_LEN))) {
 				mlog(ML_ERROR, "mismatched lvbs!\n");
 				__dlm_print_one_lock_resource(lock->lockres);
 				BUG();
@@ -1083,22 +1252,25 @@
 			 * we must send it immediately. */
 			ret = dlm_send_mig_lockres_msg(dlm, mres, send_to,
 						       res, total_locks);
-			if (ret < 0) {
-				// TODO
-				mlog(ML_ERROR, "dlm_send_mig_lockres_msg "
-				     "returned %d, TODO\n", ret);
-				BUG();
-			}
+			if (ret < 0)
+				goto error;
 		}
 	}
 	/* flush any remaining locks */
 	ret = dlm_send_mig_lockres_msg(dlm, mres, send_to, res, total_locks);
-	if (ret < 0) {
-		// TODO
-		mlog(ML_ERROR, "dlm_send_mig_lockres_msg returned %d, "
-		     "TODO\n", ret);
+	if (ret < 0)
+		goto error;
+	return ret;
+
+error:
+	mlog(ML_ERROR, "%s: dlm_send_mig_lockres_msg returned %d\n",
+	     dlm->name, ret);
+	if (!dlm_is_host_down(ret))
 		BUG();
-	}
+	mlog(0, "%s: node %u went down while sending %s "
+	     "lockres %.*s\n", dlm->name, send_to,
+	     flags & DLM_MRES_RECOVERY ?  "recovery" : "migration",
+	     res->lockname.len, res->lockname.name);
 	return ret;
 }
 
@@ -1146,8 +1318,8 @@
 		mlog(0, "all done flag.  all lockres data received!\n");
 
 	ret = -ENOMEM;
-	buf = kmalloc(be16_to_cpu(msg->data_len), GFP_KERNEL);
-	item = kcalloc(1, sizeof(*item), GFP_KERNEL);
+	buf = kmalloc(be16_to_cpu(msg->data_len), GFP_NOFS);
+	item = kcalloc(1, sizeof(*item), GFP_NOFS);
 	if (!buf || !item)
 		goto leave;
 
@@ -1238,7 +1410,7 @@
 	spin_lock(&dlm->work_lock);
 	list_add_tail(&item->list, &dlm->work_list);
 	spin_unlock(&dlm->work_lock);
-	schedule_work(&dlm->dispatched_work);
+	queue_work(dlm->dlm_worker, &dlm->dispatched_work);
 
 leave:
 	dlm_put(dlm);
@@ -1406,6 +1578,7 @@
 	struct dlm_ctxt *dlm = data;
 	struct dlm_master_requery *req = (struct dlm_master_requery *)msg->buf;
 	struct dlm_lock_resource *res = NULL;
+	unsigned int hash;
 	int master = DLM_LOCK_RES_OWNER_UNKNOWN;
 	u32 flags = DLM_ASSERT_MASTER_REQUERY;
 
@@ -1415,8 +1588,10 @@
 		return master;
 	}
 
+	hash = dlm_lockid_hash(req->name, req->namelen);
+
 	spin_lock(&dlm->spinlock);
-	res = __dlm_lookup_lockres(dlm, req->name, req->namelen);
+	res = __dlm_lookup_lockres(dlm, req->name, req->namelen, hash);
 	if (res) {
 		spin_lock(&res->spinlock);
 		master = res->owner;
@@ -1483,7 +1658,7 @@
 	struct dlm_lock *newlock = NULL;
 	struct dlm_lockstatus *lksb = NULL;
 	int ret = 0;
-	int i;
+	int i, bad;
 	struct list_head *iter;
 	struct dlm_lock *lock = NULL;
 
@@ -1529,8 +1704,7 @@
 
 			/* move the lock to its proper place */
 			/* do not alter lock refcount.  switching lists. */
-			list_del_init(&lock->list);
-			list_add_tail(&lock->list, queue);
+			list_move_tail(&lock->list, queue);
 			spin_unlock(&res->spinlock);
 
 			mlog(0, "just reordered a local lock!\n");
@@ -1553,28 +1727,48 @@
 		}
 		lksb->flags |= (ml->flags &
 				(DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB));
-			
-		if (mres->lvb[0]) {
+
+		if (ml->type == LKM_NLMODE)
+			goto skip_lvb;
+
+		if (!dlm_lvb_is_empty(mres->lvb)) {
 			if (lksb->flags & DLM_LKSB_PUT_LVB) {
 				/* other node was trying to update
 				 * lvb when node died.  recreate the
 				 * lksb with the updated lvb. */
 				memcpy(lksb->lvb, mres->lvb, DLM_LVB_LEN);
+				/* the lock resource lvb update must happen
+				 * NOW, before the spinlock is dropped.
+				 * we no longer wait for the AST to update
+				 * the lvb. */
+				memcpy(res->lvb, mres->lvb, DLM_LVB_LEN);
 			} else {
 				/* otherwise, the node is sending its 
 				 * most recent valid lvb info */
 				BUG_ON(ml->type != LKM_EXMODE &&
 				       ml->type != LKM_PRMODE);
-				if (res->lvb[0] && (ml->type == LKM_EXMODE ||
-				    memcmp(res->lvb, mres->lvb, DLM_LVB_LEN))) {
-					mlog(ML_ERROR, "received bad lvb!\n");
-					__dlm_print_one_lock_resource(res);
-					BUG();
+				if (!dlm_lvb_is_empty(res->lvb) &&
+ 				    (ml->type == LKM_EXMODE ||
+ 				     memcmp(res->lvb, mres->lvb, DLM_LVB_LEN))) {
+ 					int i;
+ 					mlog(ML_ERROR, "%s:%.*s: received bad "
+ 					     "lvb! type=%d\n", dlm->name,
+ 					     res->lockname.len,
+ 					     res->lockname.name, ml->type);
+ 					printk("lockres lvb=[");
+ 					for (i=0; i<DLM_LVB_LEN; i++)
+ 						printk("%02x", res->lvb[i]);
+ 					printk("]\nmigrated lvb=[");
+ 					for (i=0; i<DLM_LVB_LEN; i++)
+ 						printk("%02x", mres->lvb[i]);
+ 					printk("]\n");
+ 					dlm_print_one_lock_resource(res);
+ 					BUG();
 				}
 				memcpy(res->lvb, mres->lvb, DLM_LVB_LEN);
 			}
 		}
-
+skip_lvb:
 
 		/* NOTE:
 		 * wrt lock queue ordering and recovery:
@@ -1592,9 +1786,33 @@
 		 * relative to each other, but clearly *not*
 		 * preserved relative to locks from other nodes.
 		 */
+		bad = 0;
 		spin_lock(&res->spinlock);
-		dlm_lock_get(newlock);
-		list_add_tail(&newlock->list, queue);
+		list_for_each_entry(lock, queue, list) {
+			if (lock->ml.cookie == ml->cookie) {
+				u64 c = lock->ml.cookie;
+				mlog(ML_ERROR, "%s:%.*s: %u:%llu: lock already "
+				     "exists on this lockres!\n", dlm->name,
+				     res->lockname.len, res->lockname.name,
+				     dlm_get_lock_cookie_node(c),
+				     dlm_get_lock_cookie_seq(c));
+
+				mlog(ML_NOTICE, "sent lock: type=%d, conv=%d, "
+				     "node=%u, cookie=%u:%llu, queue=%d\n",
+	      			     ml->type, ml->convert_type, ml->node,
+				     dlm_get_lock_cookie_node(ml->cookie),
+				     dlm_get_lock_cookie_seq(ml->cookie),
+				     ml->list);
+
+				__dlm_print_one_lock_resource(res);
+				bad = 1;
+				break;
+			}
+		}
+		if (!bad) {
+			dlm_lock_get(newlock);
+			list_add_tail(&newlock->list, queue);
+		}
 		spin_unlock(&res->spinlock);
 	}
 	mlog(0, "done running all the locks\n");
@@ -1618,8 +1836,14 @@
 	struct dlm_lock *lock;
 
 	res->state |= DLM_LOCK_RES_RECOVERING;
-	if (!list_empty(&res->recovering))
+	if (!list_empty(&res->recovering)) {
+		mlog(0,
+		     "Recovering res %s:%.*s, is already on recovery list!\n",
+		     dlm->name, res->lockname.len, res->lockname.name);
 		list_del_init(&res->recovering);
+	}
+	/* We need to hold a reference while on the recovery list */
+	dlm_lockres_get(res);
 	list_add_tail(&res->recovering, &dlm->reco.resources);
 
 	/* find any pending locks and put them back on proper list */
@@ -1708,9 +1932,11 @@
 			spin_lock(&res->spinlock);
 			dlm_change_lockres_owner(dlm, res, new_master);
 			res->state &= ~DLM_LOCK_RES_RECOVERING;
-			__dlm_dirty_lockres(dlm, res);
+			if (!__dlm_lockres_unused(res))
+				__dlm_dirty_lockres(dlm, res);
 			spin_unlock(&res->spinlock);
 			wake_up(&res->wq);
+			dlm_lockres_put(res);
 		}
 	}
 
@@ -1719,7 +1945,7 @@
 	 * the RECOVERING state and set the owner
 	 * if necessary */
 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
-		bucket = &(dlm->lockres_hash[i]);
+		bucket = dlm_lockres_hash(dlm, i);
 		hlist_for_each_entry(res, hash_iter, bucket, hash_node) {
 			if (res->state & DLM_LOCK_RES_RECOVERING) {
 				if (res->owner == dead_node) {
@@ -1743,11 +1969,13 @@
 					     dlm->name, res->lockname.len,
 					     res->lockname.name, res->owner);
 					list_del_init(&res->recovering);
+					dlm_lockres_put(res);
 				}
 				spin_lock(&res->spinlock);
 				dlm_change_lockres_owner(dlm, res, new_master);
 				res->state &= ~DLM_LOCK_RES_RECOVERING;
-				__dlm_dirty_lockres(dlm, res);
+				if (!__dlm_lockres_unused(res))
+					__dlm_dirty_lockres(dlm, res);
 				spin_unlock(&res->spinlock);
 				wake_up(&res->wq);
 			}
@@ -1884,7 +2112,7 @@
 	 *    need to be fired as a result.
 	 */
 	for (i = 0; i < DLM_HASH_BUCKETS; i++) {
-		bucket = &(dlm->lockres_hash[i]);
+		bucket = dlm_lockres_hash(dlm, i);
 		hlist_for_each_entry(res, iter, bucket, hash_node) {
  			/* always prune any $RECOVERY entries for dead nodes,
  			 * otherwise hangs can occur during later recovery */
@@ -1924,6 +2152,20 @@
 {
 	assert_spin_locked(&dlm->spinlock);
 
+	if (dlm->reco.new_master == idx) {
+		mlog(0, "%s: recovery master %d just died\n",
+		     dlm->name, idx);
+		if (dlm->reco.state & DLM_RECO_STATE_FINALIZE) {
+			/* finalize1 was reached, so it is safe to clear
+			 * the new_master and dead_node.  that recovery
+			 * is complete. */
+			mlog(0, "%s: dead master %d had reached "
+			     "finalize1 state, clearing\n", dlm->name, idx);
+			dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE;
+			__dlm_reset_recovery(dlm);
+		}
+	}
+
 	/* check to see if the node is already considered dead */
 	if (!test_bit(idx, dlm->live_nodes_map)) {
 		mlog(0, "for domain %s, node %d is already dead. "
@@ -2087,7 +2329,7 @@
 
 			/* set the new_master to this node */
 			spin_lock(&dlm->spinlock);
-			dlm->reco.new_master = dlm->node_num;
+			dlm_set_reco_master(dlm, dlm->node_num);
 			spin_unlock(&dlm->spinlock);
 		}
 
@@ -2125,6 +2367,10 @@
 		mlog(0, "%s: reco master %u is ready to recover %u\n",
 		     dlm->name, dlm->reco.new_master, dlm->reco.dead_node);
 		status = -EEXIST;
+	} else if (ret == DLM_RECOVERING) {
+		mlog(0, "dlm=%s dlmlock says master node died (this=%u)\n",
+		     dlm->name, dlm->node_num);
+		goto again;
 	} else {
 		struct dlm_lock_resource *res;
 
@@ -2156,7 +2402,7 @@
 
 	mlog_entry("%u\n", dead_node);
 
-	mlog(0, "dead node is %u\n", dead_node);
+	mlog(0, "%s: dead node is %u\n", dlm->name, dead_node);
 
 	spin_lock(&dlm->spinlock);
 	dlm_node_iter_init(dlm->domain_map, &iter);
@@ -2214,6 +2460,14 @@
 			 * another ENOMEM */
 			msleep(100);
 			goto retry;
+		} else if (ret == EAGAIN) {
+			mlog(0, "%s: trying to start recovery of node "
+			     "%u, but node %u is waiting for last recovery "
+			     "to complete, backoff for a bit\n", dlm->name,
+			     dead_node, nodenum);
+			/* TODO Look into replacing msleep with cond_resched() */
+			msleep(100);
+			goto retry;
 		}
 	}
 
@@ -2229,8 +2483,20 @@
 	if (!dlm_grab(dlm))
 		return 0;
 
-	mlog(0, "node %u wants to recover node %u\n",
-		  br->node_idx, br->dead_node);
+	spin_lock(&dlm->spinlock);
+	if (dlm->reco.state & DLM_RECO_STATE_FINALIZE) {
+		mlog(0, "%s: node %u wants to recover node %u (%u:%u) "
+		     "but this node is in finalize state, waiting on finalize2\n",
+		     dlm->name, br->node_idx, br->dead_node,
+		     dlm->reco.dead_node, dlm->reco.new_master);
+		spin_unlock(&dlm->spinlock);
+		return EAGAIN;
+	}
+	spin_unlock(&dlm->spinlock);
+
+	mlog(0, "%s: node %u wants to recover node %u (%u:%u)\n",
+	     dlm->name, br->node_idx, br->dead_node,
+	     dlm->reco.dead_node, dlm->reco.new_master);
 
 	dlm_fire_domain_eviction_callbacks(dlm, br->dead_node);
 
@@ -2252,8 +2518,8 @@
 		     "node %u changing it to %u\n", dlm->name, 
 		     dlm->reco.dead_node, br->node_idx, br->dead_node);
 	}
-	dlm->reco.new_master = br->node_idx;
-	dlm->reco.dead_node = br->dead_node;
+	dlm_set_reco_master(dlm, br->node_idx);
+	dlm_set_reco_dead_node(dlm, br->dead_node);
 	if (!test_bit(br->dead_node, dlm->recovery_map)) {
 		mlog(0, "recovery master %u sees %u as dead, but this "
 		     "node has not yet.  marking %u as dead\n",
@@ -2272,10 +2538,16 @@
 	spin_unlock(&dlm->spinlock);
 
 	dlm_kick_recovery_thread(dlm);
+
+	mlog(0, "%s: recovery started by node %u, for %u (%u:%u)\n",
+	     dlm->name, br->node_idx, br->dead_node,
+	     dlm->reco.dead_node, dlm->reco.new_master);
+
 	dlm_put(dlm);
 	return 0;
 }
 
+#define DLM_FINALIZE_STAGE2  0x01
 static int dlm_send_finalize_reco_message(struct dlm_ctxt *dlm)
 {
 	int ret = 0;
@@ -2283,25 +2555,31 @@
 	struct dlm_node_iter iter;
 	int nodenum;
 	int status;
+	int stage = 1;
 
-	mlog(0, "finishing recovery for node %s:%u\n",
-	     dlm->name, dlm->reco.dead_node);
+	mlog(0, "finishing recovery for node %s:%u, "
+	     "stage %d\n", dlm->name, dlm->reco.dead_node, stage);
 
 	spin_lock(&dlm->spinlock);
 	dlm_node_iter_init(dlm->domain_map, &iter);
 	spin_unlock(&dlm->spinlock);
 
+stage2:
 	memset(&fr, 0, sizeof(fr));
 	fr.node_idx = dlm->node_num;
 	fr.dead_node = dlm->reco.dead_node;
+	if (stage == 2)
+		fr.flags |= DLM_FINALIZE_STAGE2;
 
 	while ((nodenum = dlm_node_iter_next(&iter)) >= 0) {
 		if (nodenum == dlm->node_num)
 			continue;
 		ret = o2net_send_message(DLM_FINALIZE_RECO_MSG, dlm->key,
 					 &fr, sizeof(fr), nodenum, &status);
-		if (ret >= 0) {
+		if (ret >= 0)
 			ret = status;
+		if (ret < 0) {
+			mlog_errno(ret);
 			if (dlm_is_host_down(ret)) {
 				/* this has no effect on this recovery 
 				 * session, so set the status to zero to 
@@ -2309,13 +2587,17 @@
 				mlog(ML_ERROR, "node %u went down after this "
 				     "node finished recovery.\n", nodenum);
 				ret = 0;
+				continue;
 			}
-		}
-		if (ret < 0) {
-			mlog_errno(ret);
 			break;
 		}
 	}
+	if (stage == 1) {
+		/* reset the node_iter back to the top and send finalize2 */
+		iter.curnode = -1;
+		stage = 2;
+		goto stage2;
+	}
 
 	return ret;
 }
@@ -2324,14 +2606,19 @@
 {
 	struct dlm_ctxt *dlm = data;
 	struct dlm_finalize_reco *fr = (struct dlm_finalize_reco *)msg->buf;
+	int stage = 1;
 
 	/* ok to return 0, domain has gone away */
 	if (!dlm_grab(dlm))
 		return 0;
 
-	mlog(0, "node %u finalizing recovery of node %u\n",
-	     fr->node_idx, fr->dead_node);
+	if (fr->flags & DLM_FINALIZE_STAGE2)
+		stage = 2;
 
+	mlog(0, "%s: node %u finalizing recovery stage%d of "
+	     "node %u (%u:%u)\n", dlm->name, fr->node_idx, stage,
+	     fr->dead_node, dlm->reco.dead_node, dlm->reco.new_master);
+ 
 	spin_lock(&dlm->spinlock);
 
 	if (dlm->reco.new_master != fr->node_idx) {
@@ -2347,13 +2634,41 @@
 		BUG();
 	}
 
-	dlm_finish_local_lockres_recovery(dlm, fr->dead_node, fr->node_idx);
+	switch (stage) {
+		case 1:
+			dlm_finish_local_lockres_recovery(dlm, fr->dead_node, fr->node_idx);
+			if (dlm->reco.state & DLM_RECO_STATE_FINALIZE) {
+				mlog(ML_ERROR, "%s: received finalize1 from "
+				     "new master %u for dead node %u, but "
+				     "this node has already received it!\n",
+				     dlm->name, fr->node_idx, fr->dead_node);
+				dlm_print_reco_node_status(dlm);
+				BUG();
+			}
+			dlm->reco.state |= DLM_RECO_STATE_FINALIZE;
+			spin_unlock(&dlm->spinlock);
+			break;
+		case 2:
+			if (!(dlm->reco.state & DLM_RECO_STATE_FINALIZE)) {
+				mlog(ML_ERROR, "%s: received finalize2 from "
+				     "new master %u for dead node %u, but "
+				     "this node did not have finalize1!\n",
+				     dlm->name, fr->node_idx, fr->dead_node);
+				dlm_print_reco_node_status(dlm);
+				BUG();
+			}
+			dlm->reco.state &= ~DLM_RECO_STATE_FINALIZE;
+			spin_unlock(&dlm->spinlock);
+			dlm_reset_recovery(dlm);
+			dlm_kick_recovery_thread(dlm);
+			break;
+		default:
+			BUG();
+	}
 
-	spin_unlock(&dlm->spinlock);
+	mlog(0, "%s: recovery done, reco master was %u, dead now %u, master now %u\n",
+	     dlm->name, fr->node_idx, dlm->reco.dead_node, dlm->reco.new_master);
 
-	dlm_reset_recovery(dlm);
-
-	dlm_kick_recovery_thread(dlm);
 	dlm_put(dlm);
 	return 0;
 }
diff --git a/fs/ocfs2/dlm/dlmthread.c b/fs/ocfs2/dlm/dlmthread.c
index 5be9d14..0c822f3 100644
--- a/fs/ocfs2/dlm/dlmthread.c
+++ b/fs/ocfs2/dlm/dlmthread.c
@@ -39,6 +39,7 @@
 #include <linux/inet.h>
 #include <linux/timer.h>
 #include <linux/kthread.h>
+#include <linux/delay.h>
 
 
 #include "cluster/heartbeat.h"
@@ -53,6 +54,8 @@
 #include "cluster/masklog.h"
 
 static int dlm_thread(void *data);
+static void dlm_purge_lockres_now(struct dlm_ctxt *dlm,
+				  struct dlm_lock_resource *lockres);
 
 static void dlm_flush_asts(struct dlm_ctxt *dlm);
 
@@ -80,7 +83,7 @@
 }
 
 
-static int __dlm_lockres_unused(struct dlm_lock_resource *res)
+int __dlm_lockres_unused(struct dlm_lock_resource *res)
 {
 	if (list_empty(&res->granted) &&
 	    list_empty(&res->converting) &&
@@ -103,6 +106,20 @@
 	assert_spin_locked(&res->spinlock);
 
 	if (__dlm_lockres_unused(res)){
+		/* For now, just keep any resource we master */
+		if (res->owner == dlm->node_num)
+		{
+			if (!list_empty(&res->purge)) {
+				mlog(0, "we master %s:%.*s, but it is on "
+				     "the purge list.  Removing\n",
+				     dlm->name, res->lockname.len,
+				     res->lockname.name);
+				list_del_init(&res->purge);
+				dlm->purge_count--;
+			}
+			return;
+		}
+
 		if (list_empty(&res->purge)) {
 			mlog(0, "putting lockres %.*s from purge list\n",
 			     res->lockname.len, res->lockname.name);
@@ -110,10 +127,23 @@
 			res->last_used = jiffies;
 			list_add_tail(&res->purge, &dlm->purge_list);
 			dlm->purge_count++;
+
+			/* if this node is not the owner, there is
+			 * no way to keep track of who the owner could be.
+			 * unhash it to avoid serious problems. */
+			if (res->owner != dlm->node_num) {
+				mlog(0, "%s:%.*s: doing immediate "
+				     "purge of lockres owned by %u\n",
+				     dlm->name, res->lockname.len,
+				     res->lockname.name, res->owner);
+
+				dlm_purge_lockres_now(dlm, res);
+			}
 		}
 	} else if (!list_empty(&res->purge)) {
-		mlog(0, "removing lockres %.*s from purge list\n",
-		     res->lockname.len, res->lockname.name);
+		mlog(0, "removing lockres %.*s from purge list, "
+		     "owner=%u\n", res->lockname.len, res->lockname.name,
+		     res->owner);
 
 		list_del_init(&res->purge);
 		dlm->purge_count--;
@@ -165,6 +195,7 @@
 	} else if (ret < 0) {
 		mlog(ML_NOTICE, "lockres %.*s: migrate failed, retrying\n",
 		     lockres->lockname.len, lockres->lockname.name);
+		msleep(100);
 		goto again;
 	}
 
@@ -178,6 +209,24 @@
 	__dlm_unhash_lockres(lockres);
 }
 
+/* make an unused lockres go away immediately.
+ * as soon as the dlm spinlock is dropped, this lockres
+ * will not be found. kfree still happens on last put. */
+static void dlm_purge_lockres_now(struct dlm_ctxt *dlm,
+				  struct dlm_lock_resource *lockres)
+{
+	assert_spin_locked(&dlm->spinlock);
+	assert_spin_locked(&lockres->spinlock);
+
+	BUG_ON(!__dlm_lockres_unused(lockres));
+
+	if (!list_empty(&lockres->purge)) {
+		list_del_init(&lockres->purge);
+		dlm->purge_count--;
+	}
+	__dlm_unhash_lockres(lockres);
+}
+
 static void dlm_run_purge_list(struct dlm_ctxt *dlm,
 			       int purge_now)
 {
@@ -318,8 +367,7 @@
 
 		target->ml.type = target->ml.convert_type;
 		target->ml.convert_type = LKM_IVMODE;
-		list_del_init(&target->list);
-		list_add_tail(&target->list, &res->granted);
+		list_move_tail(&target->list, &res->granted);
 
 		BUG_ON(!target->lksb);
 		target->lksb->status = DLM_NORMAL;
@@ -380,8 +428,7 @@
 		     target->ml.type, target->ml.node);
 
 		// target->ml.type is already correct
-		list_del_init(&target->list);
-		list_add_tail(&target->list, &res->granted);
+		list_move_tail(&target->list, &res->granted);
 
 		BUG_ON(!target->lksb);
 		target->lksb->status = DLM_NORMAL;
@@ -422,6 +469,8 @@
 	/* don't shuffle secondary queues */
 	if ((res->owner == dlm->node_num) &&
 	    !(res->state & DLM_LOCK_RES_DIRTY)) {
+		/* ref for dirty_list */
+		dlm_lockres_get(res);
 		list_add_tail(&res->dirty, &dlm->dirty_list);
 		res->state |= DLM_LOCK_RES_DIRTY;
 	}
@@ -606,6 +655,8 @@
 			list_del_init(&res->dirty);
 			spin_unlock(&res->spinlock);
 			spin_unlock(&dlm->spinlock);
+			/* Drop dirty_list ref */
+			dlm_lockres_put(res);
 
 		 	/* lockres can be re-dirtied/re-added to the
 			 * dirty_list in this gap, but that is ok */
@@ -642,8 +693,9 @@
 			 * spinlock and do NOT have the dlm lock.
 			 * safe to reserve/queue asts and run the lists. */
 
-			mlog(0, "calling dlm_shuffle_lists with dlm=%p, "
-			     "res=%p\n", dlm, res);
+			mlog(0, "calling dlm_shuffle_lists with dlm=%s, "
+			     "res=%.*s\n", dlm->name,
+			     res->lockname.len, res->lockname.name);
 
 			/* called while holding lockres lock */
 			dlm_shuffle_lists(dlm, res);
@@ -657,6 +709,8 @@
 			/* if the lock was in-progress, stick
 			 * it on the back of the list */
 			if (delay) {
+				/* ref for dirty_list */
+				dlm_lockres_get(res);
 				spin_lock(&res->spinlock);
 				list_add_tail(&res->dirty, &dlm->dirty_list);
 				res->state |= DLM_LOCK_RES_DIRTY;
@@ -677,7 +731,7 @@
 
 		/* yield and continue right away if there is more work to do */
 		if (!n) {
-			yield();
+			cond_resched();
 			continue;
 		}
 
diff --git a/fs/ocfs2/dlm/dlmunlock.c b/fs/ocfs2/dlm/dlmunlock.c
index 7b1a275..b0c3134 100644
--- a/fs/ocfs2/dlm/dlmunlock.c
+++ b/fs/ocfs2/dlm/dlmunlock.c
@@ -271,8 +271,7 @@
 void dlm_commit_pending_cancel(struct dlm_lock_resource *res,
 			       struct dlm_lock *lock)
 {
-	list_del_init(&lock->list);
-	list_add_tail(&lock->list, &res->granted);
+	list_move_tail(&lock->list, &res->granted);
 	lock->ml.convert_type = LKM_IVMODE;
 }
 
@@ -319,6 +318,16 @@
 
 	mlog_entry("%.*s\n", res->lockname.len, res->lockname.name);
 
+	if (owner == dlm->node_num) {
+		/* ended up trying to contact ourself.  this means
+		 * that the lockres had been remote but became local
+		 * via a migration.  just retry it, now as local */
+		mlog(0, "%s:%.*s: this node became the master due to a "
+		     "migration, re-evaluate now\n", dlm->name,
+		     res->lockname.len, res->lockname.name);
+		return DLM_FORWARD;
+	}
+
 	memset(&unlock, 0, sizeof(unlock));
 	unlock.node_idx = dlm->node_num;
 	unlock.flags = cpu_to_be32(flags);
diff --git a/fs/ocfs2/dlm/userdlm.c b/fs/ocfs2/dlm/userdlm.c
index 74ca4e5f..e641b08 100644
--- a/fs/ocfs2/dlm/userdlm.c
+++ b/fs/ocfs2/dlm/userdlm.c
@@ -672,7 +672,7 @@
 	u32 dlm_key;
 	char *domain;
 
-	domain = kmalloc(name->len + 1, GFP_KERNEL);
+	domain = kmalloc(name->len + 1, GFP_NOFS);
 	if (!domain) {
 		mlog_errno(-ENOMEM);
 		return ERR_PTR(-ENOMEM);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 64cd528..4acd372 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -242,7 +242,7 @@
 	mlog_exit_void();
 }
 
-static spinlock_t ocfs2_dlm_tracking_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(ocfs2_dlm_tracking_lock);
 
 static void ocfs2_add_lockres_tracking(struct ocfs2_lock_res *res,
 				       struct ocfs2_dlm_debug *dlm_debug)
diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
index 84c5079..35140f6 100644
--- a/fs/ocfs2/inode.h
+++ b/fs/ocfs2/inode.h
@@ -114,7 +114,7 @@
 
 extern kmem_cache_t *ocfs2_inode_cache;
 
-extern struct address_space_operations ocfs2_aops;
+extern const struct address_space_operations ocfs2_aops;
 
 struct buffer_head *ocfs2_bread(struct inode *inode, int block,
 				int *err, int reada);
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index eebc3cf..910a601 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -49,7 +49,7 @@
 
 #include "buffer_head_io.h"
 
-spinlock_t trans_inc_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(trans_inc_lock);
 
 static int ocfs2_force_read_journal(struct inode *inode);
 static int ocfs2_recover_node(struct ocfs2_super *osb,
@@ -222,8 +222,7 @@
 	BUG_ON(!list_empty(&OCFS2_I(inode)->ip_handle_list));
 
 	OCFS2_I(inode)->ip_handle = handle;
-	list_del(&(OCFS2_I(inode)->ip_handle_list));
-	list_add_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list));
+	list_move_tail(&(OCFS2_I(inode)->ip_handle_list), &(handle->inode_list));
 }
 
 static void ocfs2_handle_unlock_inodes(struct ocfs2_journal_handle *handle)
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 949b3da..cdf7339 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -100,7 +100,7 @@
 static void ocfs2_free_mem_caches(void);
 static void ocfs2_delete_osb(struct ocfs2_super *osb);
 
-static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf);
+static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf);
 
 static int ocfs2_sync_fs(struct super_block *sb, int wait);
 
@@ -672,12 +672,14 @@
 	return status;
 }
 
-static struct super_block *ocfs2_get_sb(struct file_system_type *fs_type,
-					int flags,
-					const char *dev_name,
-					void *data)
+static int ocfs2_get_sb(struct file_system_type *fs_type,
+			int flags,
+			const char *dev_name,
+			void *data,
+			struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super,
+			   mnt);
 }
 
 static struct file_system_type ocfs2_fs_type = {
@@ -855,7 +857,7 @@
 	mlog_exit_void();
 }
 
-static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf)
+static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	struct ocfs2_super *osb;
 	u32 numbits, freebits;
@@ -864,9 +866,9 @@
 	struct buffer_head *bh = NULL;
 	struct inode *inode = NULL;
 
-	mlog_entry("(%p, %p)\n", sb, buf);
+	mlog_entry("(%p, %p)\n", dentry->d_sb, buf);
 
-	osb = OCFS2_SB(sb);
+	osb = OCFS2_SB(dentry->d_sb);
 
 	inode = ocfs2_get_system_file_inode(osb,
 					    GLOBAL_BITMAP_SYSTEM_INODE,
@@ -889,7 +891,7 @@
 	freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used);
 
 	buf->f_type = OCFS2_SUPER_MAGIC;
-	buf->f_bsize = sb->s_blocksize;
+	buf->f_bsize = dentry->d_sb->s_blocksize;
 	buf->f_namelen = OCFS2_MAX_FILENAME_LEN;
 	buf->f_blocks = ((sector_t) numbits) *
 			(osb->s_clustersize >> osb->sb->s_blocksize_bits);
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c
index f6986bd..0c8a129 100644
--- a/fs/ocfs2/symlink.c
+++ b/fs/ocfs2/symlink.c
@@ -64,8 +64,7 @@
 {
 	struct page * page;
 	struct address_space *mapping = dentry->d_inode->i_mapping;
-	page = read_cache_page(mapping, 0,
-			       (filler_t *)mapping->a_ops->readpage, NULL);
+	page = read_mapping_page(mapping, 0, NULL);
 	if (IS_ERR(page))
 		goto sync_fail;
 	wait_on_page_locked(page);
diff --git a/fs/ocfs2/vote.c b/fs/ocfs2/vote.c
index ee42765..cf70fe2 100644
--- a/fs/ocfs2/vote.c
+++ b/fs/ocfs2/vote.c
@@ -988,9 +988,7 @@
 	}
 
 bail:
-	if (request)
-		kfree(request);
-
+	kfree(request);
 	return status;
 }
 
@@ -1021,9 +1019,7 @@
 	}
 
 bail:
-	if (request)
-		kfree(request);
-
+	kfree(request);
 	return status;
 }
 
diff --git a/fs/open.c b/fs/open.c
index 317b7c7..303f06d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -31,18 +31,18 @@
 
 #include <asm/unistd.h>
 
-int vfs_statfs(struct super_block *sb, struct kstatfs *buf)
+int vfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	int retval = -ENODEV;
 
-	if (sb) {
+	if (dentry) {
 		retval = -ENOSYS;
-		if (sb->s_op->statfs) {
+		if (dentry->d_sb->s_op->statfs) {
 			memset(buf, 0, sizeof(*buf));
-			retval = security_sb_statfs(sb);
+			retval = security_sb_statfs(dentry);
 			if (retval)
 				return retval;
-			retval = sb->s_op->statfs(sb, buf);
+			retval = dentry->d_sb->s_op->statfs(dentry, buf);
 			if (retval == 0 && buf->f_frsize == 0)
 				buf->f_frsize = buf->f_bsize;
 		}
@@ -52,12 +52,12 @@
 
 EXPORT_SYMBOL(vfs_statfs);
 
-static int vfs_statfs_native(struct super_block *sb, struct statfs *buf)
+static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf)
 {
 	struct kstatfs st;
 	int retval;
 
-	retval = vfs_statfs(sb, &st);
+	retval = vfs_statfs(dentry, &st);
 	if (retval)
 		return retval;
 
@@ -95,12 +95,12 @@
 	return 0;
 }
 
-static int vfs_statfs64(struct super_block *sb, struct statfs64 *buf)
+static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
 {
 	struct kstatfs st;
 	int retval;
 
-	retval = vfs_statfs(sb, &st);
+	retval = vfs_statfs(dentry, &st);
 	if (retval)
 		return retval;
 
@@ -130,7 +130,7 @@
 	error = user_path_walk(path, &nd);
 	if (!error) {
 		struct statfs tmp;
-		error = vfs_statfs_native(nd.dentry->d_inode->i_sb, &tmp);
+		error = vfs_statfs_native(nd.dentry, &tmp);
 		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 			error = -EFAULT;
 		path_release(&nd);
@@ -149,7 +149,7 @@
 	error = user_path_walk(path, &nd);
 	if (!error) {
 		struct statfs64 tmp;
-		error = vfs_statfs64(nd.dentry->d_inode->i_sb, &tmp);
+		error = vfs_statfs64(nd.dentry, &tmp);
 		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 			error = -EFAULT;
 		path_release(&nd);
@@ -168,7 +168,7 @@
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = vfs_statfs_native(file->f_dentry->d_inode->i_sb, &tmp);
+	error = vfs_statfs_native(file->f_dentry, &tmp);
 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 		error = -EFAULT;
 	fput(file);
@@ -189,7 +189,7 @@
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = vfs_statfs64(file->f_dentry->d_inode->i_sb, &tmp);
+	error = vfs_statfs64(file->f_dentry, &tmp);
 	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 		error = -EFAULT;
 	fput(file);
@@ -322,7 +322,7 @@
 
 	error = locks_verify_truncate(inode, file, length);
 	if (!error)
-		error = do_truncate(dentry, length, 0, file);
+		error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
 out_putf:
 	fput(file);
 out:
@@ -633,7 +633,7 @@
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 
-	audit_inode(NULL, inode, 0);
+	audit_inode(NULL, inode);
 
 	err = -EROFS;
 	if (IS_RDONLY(inode))
@@ -786,7 +786,7 @@
 	if (file) {
 		struct dentry * dentry;
 		dentry = file->f_dentry;
-		audit_inode(NULL, dentry->d_inode, 0);
+		audit_inode(NULL, dentry->d_inode);
 		error = chown_common(dentry, user, group);
 		fput(file);
 	}
@@ -1152,7 +1152,7 @@
 	}
 
 	if (filp->f_op && filp->f_op->flush)
-		retval = filp->f_op->flush(filp);
+		retval = filp->f_op->flush(filp, id);
 
 	dnotify_flush(filp, id);
 	locks_remove_posix(filp, id);
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 0f14276..93a56bd 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -1,5 +1,4 @@
-/* $Id: inode.c,v 1.15 2001/11/12 09:43:39 davem Exp $
- * openpromfs.c: /proc/openprom handling routines
+/* inode.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
  * Copyright (C) 1998      Eddie C. Dost  (ecd@skynet.be)
@@ -12,756 +11,245 @@
 #include <linux/openprom_fs.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/seq_file.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/uaccess.h>
 
-#define ALIASES_NNODES 64
+static DEFINE_MUTEX(op_mutex);
 
-typedef struct {
-	u16	parent;
-	u16	next;
-	u16	child;
-	u16	first_prop;
-	u32	node;
-} openpromfs_node;
+#define OPENPROM_ROOT_INO	0
 
-typedef struct {
-#define OPP_STRING	0x10
-#define OPP_STRINGLIST	0x20
-#define OPP_BINARY	0x40
-#define OPP_HEXSTRING	0x80
-#define OPP_DIRTY	0x01
-#define OPP_QUOTED	0x02
-#define OPP_NOTQUOTED	0x04
-#define OPP_ASCIIZ	0x08
-	u32	flag;
-	u32	alloclen;
-	u32	len;
-	char	*value;
-	char	name[8];
-} openprom_property;
+enum op_inode_type {
+	op_inode_node,
+	op_inode_prop,
+};
 
-static openpromfs_node *nodes;
-static int alloced;
-static u16 last_node;
-static u16 first_prop;
-static u16 options = 0xffff;
-static u16 aliases = 0xffff;
-static int aliases_nodes;
-static char *alias_names [ALIASES_NNODES];
+union op_inode_data {
+	struct device_node	*node;
+	struct property		*prop;
+};
 
-#define OPENPROM_ROOT_INO	16
-#define OPENPROM_FIRST_INO	OPENPROM_ROOT_INO
-#define NODE(ino) nodes[ino - OPENPROM_FIRST_INO]
-#define NODE2INO(node) (node + OPENPROM_FIRST_INO)
-#define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
+struct op_inode_info {
+	struct inode		vfs_inode;
+	enum op_inode_type	type;
+	union op_inode_data	u;
+};
 
-static int openpromfs_create (struct inode *, struct dentry *, int, struct nameidata *);
-static int openpromfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry, struct nameidata *nd);
-static int openpromfs_unlink (struct inode *, struct dentry *dentry);
-
-static ssize_t nodenum_read(struct file *file, char __user *buf,
-			    size_t count, loff_t *ppos)
+static inline struct op_inode_info *OP_I(struct inode *inode)
 {
-	struct inode *inode = file->f_dentry->d_inode;
-	char buffer[10];
-	
-	if (count < 0 || !inode->u.generic_ip)
-		return -EINVAL;
-	sprintf (buffer, "%8.8x\n", (u32)(long)(inode->u.generic_ip));
-	if (file->f_pos >= 9)
-		return 0;
-	if (count > 9 - file->f_pos)
-		count = 9 - file->f_pos;
-	if (copy_to_user(buf, buffer + file->f_pos, count))
-		return -EFAULT;
-	*ppos += count;
-	return count;
+	return container_of(inode, struct op_inode_info, vfs_inode);
 }
 
-static ssize_t property_read(struct file *filp, char __user *buf,
-			     size_t count, loff_t *ppos)
+static int is_string(unsigned char *p, int len)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
-	int i, j, k;
-	u32 node;
-	char *p, *s;
-	u32 *q;
-	openprom_property *op;
-	char buffer[64];
-	
-	if (!filp->private_data) {
-		node = nodes[(u16)((long)inode->u.generic_ip)].node;
-		i = ((u32)(long)inode->u.generic_ip) >> 16;
-		if ((u16)((long)inode->u.generic_ip) == aliases) {
-			if (i >= aliases_nodes)
-				p = NULL;
-			else
-				p = alias_names [i];
-		} else
-			for (p = prom_firstprop (node, buffer);
-			     i && p && *p;
-			     p = prom_nextprop (node, p, buffer), i--)
-				/* nothing */ ;
-		if (!p || !*p)
-			return -EIO;
-		i = prom_getproplen (node, p);
-		if (i < 0) {
-			if ((u16)((long)inode->u.generic_ip) == aliases)
-				i = 0;
-			else
-				return -EIO;
-		}
-		k = i;
-		if (i < 64) i = 64;
-		filp->private_data = kmalloc (sizeof (openprom_property)
-					      + (j = strlen (p)) + 2 * i,
-					      GFP_KERNEL);
-		if (!filp->private_data)
-			return -ENOMEM;
-		op = (openprom_property *)filp->private_data;
-		op->flag = 0;
-		op->alloclen = 2 * i;
-		strcpy (op->name, p);
-		op->value = (char *)(((unsigned long)(op->name + j + 4)) & ~3);
-		op->len = k;
-		if (k && prom_getproperty (node, p, op->value, i) < 0)
-			return -EIO;
-		op->value [k] = 0;
-		if (k) {
-			for (s = NULL, p = op->value; p < op->value + k; p++) {
-				if ((*p >= ' ' && *p <= '~') || *p == '\n') {
-					op->flag |= OPP_STRING;
-					s = p;
-					continue;
-				}
-				if (p > op->value && !*p && s == p - 1) {
-					if (p < op->value + k - 1)
-						op->flag |= OPP_STRINGLIST;
-					else
-						op->flag |= OPP_ASCIIZ;
-					continue;
-				}
-				if (k == 1 && !*p) {
-					op->flag |= (OPP_STRING|OPP_ASCIIZ);
-					break;
-				}
-				op->flag &= ~(OPP_STRING|OPP_STRINGLIST);
-				if (k & 3)
-					op->flag |= OPP_HEXSTRING;
-				else
-					op->flag |= OPP_BINARY;
-				break;
-			}
-			if (op->flag & OPP_STRINGLIST)
-				op->flag &= ~(OPP_STRING);
-			if (op->flag & OPP_ASCIIZ)
-				op->len--;
-		}
-	} else
-		op = (openprom_property *)filp->private_data;
-	if (!count || !(op->len || (op->flag & OPP_ASCIIZ)))
+	int i;
+
+	for (i = 0; i < len; i++) {
+		unsigned char val = p[i];
+
+		if ((i && !val) ||
+		    (val >= ' ' && val <= '~'))
+			continue;
+
 		return 0;
-	if (*ppos >= 0xffffff || count >= 0xffffff)
-		return -EINVAL;
-	if (op->flag & OPP_STRINGLIST) {
-		for (k = 0, p = op->value; p < op->value + op->len; p++)
-			if (!*p)
-				k++;
-		i = op->len + 4 * k + 3;
-	} else if (op->flag & OPP_STRING) {
-		i = op->len + 3;
-	} else if (op->flag & OPP_BINARY) {
-		i = (op->len * 9) >> 2;
+	}
+
+	return 1;
+}
+
+static int property_show(struct seq_file *f, void *v)
+{
+	struct property *prop = f->private;
+	void *pval;
+	int len;
+
+	len = prop->length;
+	pval = prop->value;
+
+	if (is_string(pval, len)) {
+		while (len > 0) {
+			int n = strlen(pval);
+
+			seq_printf(f, "%s", (char *) pval);
+
+			/* Skip over the NULL byte too.  */
+			pval += n + 1;
+			len -= n + 1;
+
+			if (len > 0)
+				seq_printf(f, " + ");
+		}
 	} else {
-		i = (op->len << 1) + 1;
-	}
-	k = *ppos;
-	if (k >= i) return 0;
-	if (count > i - k) count = i - k;
-	if (op->flag & OPP_STRING) {
-		if (!k) {
-			if (put_user('\'', buf))
-				return -EFAULT;
-			k++;
-			count--;
-		}
-
-		if (k + count >= i - 2)
-			j = i - 2 - k;
-		else
-			j = count;
-
-		if (j >= 0) {
-			if (copy_to_user(buf + k - *ppos,
-					 op->value + k - 1, j))
-				return -EFAULT;
-			count -= j;
-			k += j;
-		}
-
-		if (count) {
-			if (put_user('\'', &buf [k++ - *ppos]))
-				return -EFAULT;
-		}
-		if (count > 1) {
-			if (put_user('\n', &buf [k++ - *ppos]))
-				return -EFAULT;
-		}
-	} else if (op->flag & OPP_STRINGLIST) {
-		char *tmp;
-
-		tmp = kmalloc (i, GFP_KERNEL);
-		if (!tmp)
-			return -ENOMEM;
-
-		s = tmp;
-		*s++ = '\'';
-		for (p = op->value; p < op->value + op->len; p++) {
-			if (!*p) {
-				strcpy(s, "' + '");
-				s += 5;
-				continue;
-			}
-			*s++ = *p;
-		}
-		strcpy(s, "'\n");
-
-		if (copy_to_user(buf, tmp + k, count))
-			return -EFAULT;
-
-		kfree(tmp);
-		k += count;
-
-	} else if (op->flag & OPP_BINARY) {
-		char buffer[10];
-		u32 *first, *last;
-		int first_off, last_cnt;
-
-		first = ((u32 *)op->value) + k / 9;
-		first_off = k % 9;
-		last = ((u32 *)op->value) + (k + count - 1) / 9;
-		last_cnt = (k + count) % 9;
-		if (!last_cnt) last_cnt = 9;
-
-		if (first == last) {
-			sprintf (buffer, "%08x.", *first);
-			if (copy_to_user(buf, buffer + first_off,
-					 last_cnt - first_off))
-				return -EFAULT;
-			buf += last_cnt - first_off;
-		} else {		
-			for (q = first; q <= last; q++) {
-				sprintf (buffer, "%08x.", *q);
-				if (q == first) {
-					if (copy_to_user(buf, buffer + first_off,
-							 9 - first_off))
-						return -EFAULT;
-					buf += 9 - first_off;
-				} else if (q == last) {
-					if (copy_to_user(buf, buffer, last_cnt))
-						return -EFAULT;
-					buf += last_cnt;
-				} else {
-					if (copy_to_user(buf, buffer, 9))
-						return -EFAULT;
-					buf += 9;
-				}
-			}
-		}
-
-		if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9) {
-			if (put_user('\n', (buf - 1)))
-				return -EFAULT;
-		}
-
-		k += count;
-
-	} else if (op->flag & OPP_HEXSTRING) {
-		char buffer[3];
-
-		if ((k < i - 1) && (k & 1)) {
-			sprintf (buffer, "%02x",
-				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (put_user(buffer[1], &buf[k++ - *ppos]))
-				return -EFAULT;
-			count--;
-		}
-
-		for (; (count > 1) && (k < i - 1); k += 2) {
-			sprintf (buffer, "%02x",
-				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (copy_to_user(buf + k - *ppos, buffer, 2))
-				return -EFAULT;
-			count -= 2;
-		}
-
-		if (count && (k < i - 1)) {
-			sprintf (buffer, "%02x",
-				 (unsigned char) *(op->value + (k >> 1)) & 0xff);
-			if (put_user(buffer[0], &buf[k++ - *ppos]))
-				return -EFAULT;
-			count--;
-		}
-
-		if (count) {
-			if (put_user('\n', &buf [k++ - *ppos]))
-				return -EFAULT;
-		}
-	}
-	count = k - *ppos;
-	*ppos = k;
-	return count;
-}
-
-static ssize_t property_write(struct file *filp, const char __user *buf,
-			      size_t count, loff_t *ppos)
-{
-	int i, j, k;
-	char *p;
-	u32 *q;
-	void *b;
-	openprom_property *op;
-	
-	if (*ppos >= 0xffffff || count >= 0xffffff)
-		return -EINVAL;
-	if (!filp->private_data) {
-		i = property_read (filp, NULL, 0, NULL);
-		if (i)
-			return i;
-	}
-	k = *ppos;
-	op = (openprom_property *)filp->private_data;
-	if (!(op->flag & OPP_STRING)) {
-		u32 *first, *last;
-		int first_off, last_cnt;
-		u32 mask, mask2;
-		char tmp [9];
-		int forcelen = 0;
-		
-		j = k % 9;
-		for (i = 0; i < count; i++, j++) {
-			if (j == 9) j = 0;
-			if (!j) {
-				char ctmp;
-				if (get_user(ctmp, &buf[i]))
-					return -EFAULT;
-				if (ctmp != '.') {
-					if (ctmp != '\n') {
-						if (op->flag & OPP_BINARY)
-							return -EINVAL;
-						else
-							goto write_try_string;
-					} else {
-						count = i + 1;
-						forcelen = 1;
-						break;
-					}
-				}
-			} else {
-				char ctmp;
-				if (get_user(ctmp, &buf[i]))
-					return -EFAULT;
-				if (ctmp < '0' || 
-				    (ctmp > '9' && ctmp < 'A') ||
-				    (ctmp > 'F' && ctmp < 'a') ||
-				    ctmp > 'f') {
-					if (op->flag & OPP_BINARY)
-						return -EINVAL;
-					else
-						goto write_try_string;
-				}
-			}
-		}
-		op->flag |= OPP_BINARY;
-		tmp [8] = 0;
-		i = ((count + k + 8) / 9) << 2;
-		if (op->alloclen <= i) {
-			b = kmalloc (sizeof (openprom_property) + 2 * i,
-				     GFP_KERNEL);
-			if (!b)
-				return -ENOMEM;
-			memcpy (b, filp->private_data,
-				sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen);
-			memset (((char *)b) + sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen, 
-				0, 2 * i - op->alloclen);
-			op = (openprom_property *)b;
-			op->alloclen = 2*i;
-			b = filp->private_data;
-			filp->private_data = (void *)op;
-			kfree (b);
-		}
-		first = ((u32 *)op->value) + (k / 9);
-		first_off = k % 9;
-		last = (u32 *)(op->value + i);
-		last_cnt = (k + count) % 9;
-		if (first + 1 == last) {
-			memset (tmp, '0', 8);
-			if (copy_from_user(tmp + first_off, buf,
-					   (count + first_off > 8) ?
-					   8 - first_off : count))
-				return -EFAULT;
-			mask = 0xffffffff;
-			mask2 = 0xffffffff;
-			for (j = 0; j < first_off; j++)
-				mask >>= 1;
-			for (j = 8 - count - first_off; j > 0; j--)
-				mask2 <<= 1;
-			mask &= mask2;
-			if (mask) {
-				*first &= ~mask;
-				*first |= simple_strtoul (tmp, NULL, 16);
-				op->flag |= OPP_DIRTY;
+		if (len & 3) {
+			while (len) {
+				len--;
+				if (len)
+					seq_printf(f, "%02x.",
+						   *(unsigned char *) pval);
+				else
+					seq_printf(f, "%02x",
+						   *(unsigned char *) pval);
+				pval++;
 			}
 		} else {
-			op->flag |= OPP_DIRTY;
-			for (q = first; q < last; q++) {
-				if (q == first) {
-					if (first_off < 8) {
-						memset (tmp, '0', 8);
-						if (copy_from_user(tmp + first_off,
-								   buf,
-								   8 - first_off))
-							return -EFAULT;
-						mask = 0xffffffff;
-						for (j = 0; j < first_off; j++)
-							mask >>= 1;
-						*q &= ~mask;
-						*q |= simple_strtoul (tmp,NULL,16);
-					}
-					buf += 9;
-				} else if ((q == last - 1) && last_cnt
-					   && (last_cnt < 8)) {
-					memset (tmp, '0', 8);
-					if (copy_from_user(tmp, buf, last_cnt))
-						return -EFAULT;
-					mask = 0xffffffff;
-					for (j = 0; j < 8 - last_cnt; j++)
-						mask <<= 1;
-					*q &= ~mask;
-					*q |= simple_strtoul (tmp, NULL, 16);
-					buf += last_cnt;
-				} else {
-					char tchars[17]; /* XXX yuck... */
+			while (len >= 4) {
+				len -= 4;
 
-					if (copy_from_user(tchars, buf, 16))
-						return -EFAULT;
-					*q = simple_strtoul (tchars, NULL, 16);
-					buf += 9;
-				}
+				if (len)
+					seq_printf(f, "%08x.",
+						   *(unsigned int *) pval);
+				else
+					seq_printf(f, "%08x",
+						   *(unsigned int *) pval);
+				pval += 4;
 			}
 		}
-		if (!forcelen) {
-			if (op->len < i)
-				op->len = i;
-		} else
-			op->len = i;
-		*ppos += count;
 	}
-write_try_string:
-	if (!(op->flag & OPP_BINARY)) {
-		if (!(op->flag & (OPP_QUOTED | OPP_NOTQUOTED))) {
-			char ctmp;
+	seq_printf(f, "\n");
 
-			/* No way, if somebody starts writing from the middle, 
-			 * we don't know whether he uses quotes around or not 
-			 */
-			if (k > 0)
-				return -EINVAL;
-			if (get_user(ctmp, buf))
-				return -EFAULT;
-			if (ctmp == '\'') {
-				op->flag |= OPP_QUOTED;
-				buf++;
-				count--;
-				(*ppos)++;
-				if (!count) {
-					op->flag |= OPP_STRING;
-					return 1;
-				}
-			} else
-				op->flag |= OPP_NOTQUOTED;
-		}
-		op->flag |= OPP_STRING;
-		if (op->alloclen <= count + *ppos) {
-			b = kmalloc (sizeof (openprom_property)
-				     + 2 * (count + *ppos), GFP_KERNEL);
-			if (!b)
-				return -ENOMEM;
-			memcpy (b, filp->private_data,
-				sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen);
-			memset (((char *)b) + sizeof (openprom_property)
-				+ strlen (op->name) + op->alloclen, 
-				0, 2*(count - *ppos) - op->alloclen);
-			op = (openprom_property *)b;
-			op->alloclen = 2*(count + *ppos);
-			b = filp->private_data;
-			filp->private_data = (void *)op;
-			kfree (b);
-		}
-		p = op->value + *ppos - ((op->flag & OPP_QUOTED) ? 1 : 0);
-		if (copy_from_user(p, buf, count))
-			return -EFAULT;
-		op->flag |= OPP_DIRTY;
-		for (i = 0; i < count; i++, p++)
-			if (*p == '\n') {
-				*p = 0;
-				break;
-			}
-		if (i < count) {
-			op->len = p - op->value;
-			*ppos += i + 1;
-			if ((p > op->value) && (op->flag & OPP_QUOTED)
-			    && (*(p - 1) == '\''))
-				op->len--;
-		} else {
-			if (p - op->value > op->len)
-				op->len = p - op->value;
-			*ppos += count;
-		}
-	}
-	return *ppos - k;
-}
-
-int property_release (struct inode *inode, struct file *filp)
-{
-	openprom_property *op = (openprom_property *)filp->private_data;
-	int error;
-	u32 node;
-	
-	if (!op)
-		return 0;
-	lock_kernel();
-	node = nodes[(u16)((long)inode->u.generic_ip)].node;
-	if ((u16)((long)inode->u.generic_ip) == aliases) {
-		if ((op->flag & OPP_DIRTY) && (op->flag & OPP_STRING)) {
-			char *p = op->name;
-			int i = (op->value - op->name) - strlen (op->name) - 1;
-			op->value [op->len] = 0;
-			*(op->value - 1) = ' ';
-			if (i) {
-				for (p = op->value - i - 2; p >= op->name; p--)
-					p[i] = *p;
-				p = op->name + i;
-			}
-			memcpy (p - 8, "nvalias ", 8);
-			prom_feval (p - 8);
-		}
-	} else if (op->flag & OPP_DIRTY) {
-		if (op->flag & OPP_STRING) {
-			op->value [op->len] = 0;
-			error = prom_setprop (node, op->name,
-					      op->value, op->len + 1);
-			if (error <= 0)
-				printk (KERN_WARNING "openpromfs: "
-					"Couldn't write property %s\n",
-					op->name);
-		} else if ((op->flag & OPP_BINARY) || !op->len) {
-			error = prom_setprop (node, op->name,
-					      op->value, op->len);
-			if (error <= 0)
-				printk (KERN_WARNING "openpromfs: "
-					"Couldn't write property %s\n",
-					op->name);
-		} else {
-			printk (KERN_WARNING "openpromfs: "
-				"Unknown property type of %s\n",
-				op->name);
-		}
-	}
-	unlock_kernel();
-	kfree (filp->private_data);
 	return 0;
 }
 
-static const struct file_operations openpromfs_prop_ops = {
-	.read		= property_read,
-	.write		= property_write,
-	.release	= property_release,
+static void *property_start(struct seq_file *f, loff_t *pos)
+{
+	if (*pos == 0)
+		return pos;
+	return NULL;
+}
+
+static void *property_next(struct seq_file *f, void *v, loff_t *pos)
+{
+	(*pos)++;
+	return NULL;
+}
+
+static void property_stop(struct seq_file *f, void *v)
+{
+	/* Nothing to do */
+}
+
+static struct seq_operations property_op = {
+	.start		= property_start,
+	.next		= property_next,
+	.stop		= property_stop,
+	.show		= property_show
 };
 
-static const struct file_operations openpromfs_nodenum_ops = {
-	.read		= nodenum_read,
+static int property_open(struct inode *inode, struct file *file)
+{
+	struct op_inode_info *oi = OP_I(inode);
+	int ret;
+
+	BUG_ON(oi->type != op_inode_prop);
+
+	ret = seq_open(file, &property_op);
+	if (!ret) {
+		struct seq_file *m = file->private_data;
+		m->private = oi->u.prop;
+	}
+	return ret;
+}
+
+static const struct file_operations openpromfs_prop_ops = {
+	.open		= property_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
 };
 
+static int openpromfs_readdir(struct file *, void *, filldir_t);
+
 static const struct file_operations openprom_operations = {
 	.read		= generic_read_dir,
 	.readdir	= openpromfs_readdir,
 };
 
-static struct inode_operations openprom_alias_inode_operations = {
-	.create		= openpromfs_create,
-	.lookup		= openpromfs_lookup,
-	.unlink		= openpromfs_unlink,
-};
+static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *);
 
 static struct inode_operations openprom_inode_operations = {
 	.lookup		= openpromfs_lookup,
 };
 
-static int lookup_children(u16 n, const char * name, int len)
+static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
-	int ret;
-	u16 node;
-	for (; n != 0xffff; n = nodes[n].next) {
-		node = nodes[n].child;
-		if (node != 0xffff) {
-			char buffer[128];
-			int i;
-			char *p;
-			
-			while (node != 0xffff) {
-				if (prom_getname (nodes[node].node,
-						  buffer, 128) >= 0) {
-					i = strlen (buffer);
-					if ((len == i)
-					    && !strncmp (buffer, name, len))
-						return NODE2INO(node);
-					p = strchr (buffer, '@');
-					if (p && (len == p - buffer)
-					    && !strncmp (buffer, name, len))
-						return NODE2INO(node);
-				}
-				node = nodes[node].next;
-			}
-		} else
-			continue;
-		ret = lookup_children (nodes[n].child, name, len);
-		if (ret) return ret;
-	}
-	return 0;
-}
-
-static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
-{
-	int ino = 0;
-#define OPFSL_DIR	0
-#define OPFSL_PROPERTY	1
-#define OPFSL_NODENUM	2
-	int type = 0;
-	char buffer[128];
-	char *p;
+	struct op_inode_info *ent_oi, *oi = OP_I(dir);
+	struct device_node *dp, *child;
+	struct property *prop;
+	enum op_inode_type ent_type;
+	union op_inode_data ent_data;
 	const char *name;
-	u32 n;
-	u16 dirnode;
-	unsigned int len;
-	int i;
 	struct inode *inode;
-	char buffer2[64];
+	unsigned int ino;
+	int len;
 	
-	inode = NULL;
+	BUG_ON(oi->type != op_inode_node);
+
+	dp = oi->u.node;
+
 	name = dentry->d_name.name;
 	len = dentry->d_name.len;
-	lock_kernel();
-	if (name [0] == '.' && len == 5 && !strncmp (name + 1, "node", 4)) {
-		ino = NODEP2INO(NODE(dir->i_ino).first_prop);
-		type = OPFSL_NODENUM;
-	}
-	if (!ino) {
-		u16 node = NODE(dir->i_ino).child;
-		while (node != 0xffff) {
-			if (prom_getname (nodes[node].node, buffer, 128) >= 0) {
-				i = strlen (buffer);
-				if (len == i && !strncmp (buffer, name, len)) {
-					ino = NODE2INO(node);
-					type = OPFSL_DIR;
-					break;
-				}
-				p = strchr (buffer, '@');
-				if (p && (len == p - buffer)
-				    && !strncmp (buffer, name, len)) {
-					ino = NODE2INO(node);
-					type = OPFSL_DIR;
-					break;
-				}
-			}
-			node = nodes[node].next;
+
+	mutex_lock(&op_mutex);
+
+	child = dp->child;
+	while (child) {
+		int n = strlen(child->path_component_name);
+
+		if (len == n &&
+		    !strncmp(child->path_component_name, name, len)) {
+			ent_type = op_inode_node;
+			ent_data.node = child;
+			ino = child->unique_id;
+			goto found;
 		}
+		child = child->sibling;
 	}
-	n = NODE(dir->i_ino).node;
-	dirnode = dir->i_ino - OPENPROM_FIRST_INO;
-	if (!ino) {
-		int j = NODEP2INO(NODE(dir->i_ino).first_prop);
-		if (dirnode != aliases) {
-			for (p = prom_firstprop (n, buffer2);
-			     p && *p;
-			     p = prom_nextprop (n, p, buffer2)) {
-				j++;
-				if ((len == strlen (p))
-				    && !strncmp (p, name, len)) {
-					ino = j;
-					type = OPFSL_PROPERTY;
-					break;
-				}
-			}
-		} else {
-			int k;
-			for (k = 0; k < aliases_nodes; k++) {
-				j++;
-				if (alias_names [k]
-				    && (len == strlen (alias_names [k]))
-				    && !strncmp (alias_names [k], name, len)) {
-					ino = j;
-					type = OPFSL_PROPERTY;
-					break;
-				}
-			}
+
+	prop = dp->properties;
+	while (prop) {
+		int n = strlen(prop->name);
+
+		if (len == n && !strncmp(prop->name, name, len)) {
+			ent_type = op_inode_prop;
+			ent_data.prop = prop;
+			ino = prop->unique_id;
+			goto found;
 		}
+
+		prop = prop->next;
 	}
-	if (!ino) {
-		ino = lookup_children (NODE(dir->i_ino).child, name, len);
-		if (ino)
-			type = OPFSL_DIR;
-		else {
-			unlock_kernel();
-			return ERR_PTR(-ENOENT);
-		}
-	}
-	inode = iget (dir->i_sb, ino);
-	unlock_kernel();
+
+	mutex_unlock(&op_mutex);
+	return ERR_PTR(-ENOENT);
+
+found:
+	inode = iget(dir->i_sb, ino);
+	mutex_unlock(&op_mutex);
 	if (!inode)
 		return ERR_PTR(-EINVAL);
-	switch (type) {
-	case OPFSL_DIR:
+	ent_oi = OP_I(inode);
+	ent_oi->type = ent_type;
+	ent_oi->u = ent_data;
+
+	switch (ent_type) {
+	case op_inode_node:
 		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
-		if (ino == OPENPROM_FIRST_INO + aliases) {
-			inode->i_mode |= S_IWUSR;
-			inode->i_op = &openprom_alias_inode_operations;
-		} else
-			inode->i_op = &openprom_inode_operations;
+		inode->i_op = &openprom_inode_operations;
 		inode->i_fop = &openprom_operations;
 		inode->i_nlink = 2;
 		break;
-	case OPFSL_NODENUM:
-		inode->i_mode = S_IFREG | S_IRUGO;
-		inode->i_fop = &openpromfs_nodenum_ops;
-		inode->i_nlink = 1;
-		inode->u.generic_ip = (void *)(long)(n);
-		break;
-	case OPFSL_PROPERTY:
-		if ((dirnode == options) && (len == 17)
-		    && !strncmp (name, "security-password", 17))
+	case op_inode_prop:
+		if (!strcmp(dp->name, "options") && (len == 17) &&
+		    !strncmp (name, "security-password", 17))
 			inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
-		else {
+		else
 			inode->i_mode = S_IFREG | S_IRUGO;
-			if (dirnode == options || dirnode == aliases) {
-				if (len != 4 || strncmp (name, "name", 4))
-					inode->i_mode |= S_IWUSR;
-			}
-		}
 		inode->i_fop = &openpromfs_prop_ops;
 		inode->i_nlink = 1;
-		if (inode->i_size < 0)
-			inode->i_size = 0;
-		inode->u.generic_ip = (void *)(long)(((u16)dirnode) | 
-			(((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));
+		inode->i_size = ent_oi->u.prop->length;
 		break;
 	}
 
@@ -775,237 +263,89 @@
 static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
+	struct op_inode_info *oi = OP_I(inode);
+	struct device_node *dp = oi->u.node;
+	struct device_node *child;
+	struct property *prop;
 	unsigned int ino;
-	u32 n;
-	int i, j;
-	char buffer[128];
-	u16 node;
-	char *p;
-	char buffer2[64];
+	int i;
 
-	lock_kernel();
+	mutex_lock(&op_mutex);
 	
 	ino = inode->i_ino;
 	i = filp->f_pos;
 	switch (i) {
 	case 0:
-		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0) goto out;
+		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+			goto out;
 		i++;
 		filp->f_pos++;
 		/* fall thru */
 	case 1:
-		if (filldir(dirent, "..", 2, i, 
-			(NODE(ino).parent == 0xffff) ? 
-			OPENPROM_ROOT_INO : NODE2INO(NODE(ino).parent), DT_DIR) < 0) 
+		if (filldir(dirent, "..", 2, i,
+			    (dp->parent == NULL ?
+			     OPENPROM_ROOT_INO :
+			     dp->parent->unique_id), DT_DIR) < 0) 
 			goto out;
 		i++;
 		filp->f_pos++;
 		/* fall thru */
 	default:
 		i -= 2;
-		node = NODE(ino).child;
-		while (i && node != 0xffff) {
-			node = nodes[node].next;
+
+		/* First, the children nodes as directories.  */
+		child = dp->child;
+		while (i && child) {
+			child = child->sibling;
 			i--;
 		}
-		while (node != 0xffff) {
-			if (prom_getname (nodes[node].node, buffer, 128) < 0)
+		while (child) {
+			if (filldir(dirent,
+				    child->path_component_name,
+				    strlen(child->path_component_name),
+				    filp->f_pos, child->unique_id, DT_DIR) < 0)
 				goto out;
-			if (filldir(dirent, buffer, strlen(buffer),
-				    filp->f_pos, NODE2INO(node), DT_DIR) < 0)
-				goto out;
+
 			filp->f_pos++;
-			node = nodes[node].next;
+			child = child->sibling;
 		}
-		j = NODEP2INO(NODE(ino).first_prop);
-		if (!i) {
-			if (filldir(dirent, ".node", 5, filp->f_pos, j, DT_REG) < 0)
-				goto out;
-			filp->f_pos++;
-		} else
+
+		/* Next, the properties as files.  */
+		prop = dp->properties;
+		while (i && prop) {
+			prop = prop->next;
 			i--;
-		n = NODE(ino).node;
-		if (ino == OPENPROM_FIRST_INO + aliases) {
-			for (j++; i < aliases_nodes; i++, j++) {
-				if (alias_names [i]) {
-					if (filldir (dirent, alias_names [i], 
-						strlen (alias_names [i]), 
-						filp->f_pos, j, DT_REG) < 0) goto out; 
-					filp->f_pos++;
-				}
-			}
-		} else {
-			for (p = prom_firstprop (n, buffer2);
-			     p && *p;
-			     p = prom_nextprop (n, p, buffer2)) {
-				j++;
-				if (i) i--;
-				else {
-					if (filldir(dirent, p, strlen(p),
-						    filp->f_pos, j, DT_REG) < 0)
-						goto out;
-					filp->f_pos++;
-				}
-			}
+		}
+		while (prop) {
+			if (filldir(dirent, prop->name, strlen(prop->name),
+				    filp->f_pos, prop->unique_id, DT_REG) < 0)
+				goto out;
+
+			filp->f_pos++;
+			prop = prop->next;
 		}
 	}
 out:
-	unlock_kernel();
+	mutex_unlock(&op_mutex);
 	return 0;
 }
 
-static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode,
-		struct nameidata *nd)
+static kmem_cache_t *op_inode_cachep;
+
+static struct inode *openprom_alloc_inode(struct super_block *sb)
 {
-	char *p;
-	struct inode *inode;
-	
-	if (!dir)
-		return -ENOENT;
-	if (dentry->d_name.len > 256)
-		return -EINVAL;
-	p = kmalloc (dentry->d_name.len + 1, GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-	strncpy (p, dentry->d_name.name, dentry->d_name.len);
-	p [dentry->d_name.len] = 0;
-	lock_kernel();
-	if (aliases_nodes == ALIASES_NNODES) {
-		kfree(p);
-		unlock_kernel();
-		return -EIO;
-	}
-	alias_names [aliases_nodes++] = p;
-	inode = iget (dir->i_sb,
-			NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes);
-	if (!inode) {
-		unlock_kernel();
-		return -EINVAL;
-	}
-	inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;
-	inode->i_fop = &openpromfs_prop_ops;
-	inode->i_nlink = 1;
-	if (inode->i_size < 0) inode->i_size = 0;
-	inode->u.generic_ip = (void *)(long)(((u16)aliases) | 
-			(((u16)(aliases_nodes - 1)) << 16));
-	unlock_kernel();
-	d_instantiate(dentry, inode);
-	return 0;
+	struct op_inode_info *oi;
+
+	oi = kmem_cache_alloc(op_inode_cachep, SLAB_KERNEL);
+	if (!oi)
+		return NULL;
+
+	return &oi->vfs_inode;
 }
 
-static int openpromfs_unlink (struct inode *dir, struct dentry *dentry)
+static void openprom_destroy_inode(struct inode *inode)
 {
-	unsigned int len;
-	char *p;
-	const char *name;
-	int i;
-	
-	name = dentry->d_name.name;
-	len = dentry->d_name.len;
-	lock_kernel();
-	for (i = 0; i < aliases_nodes; i++)
-		if ((strlen (alias_names [i]) == len)
-		    && !strncmp (name, alias_names[i], len)) {
-			char buffer[512];
-			
-			p = alias_names [i];
-			alias_names [i] = NULL;
-			kfree (p);
-			strcpy (buffer, "nvunalias ");
-			memcpy (buffer + 10, name, len);
-			buffer [10 + len] = 0;
-			prom_feval (buffer);
-		}
-	unlock_kernel();
-	return 0;
-}
-
-/* {{{ init section */
-static int __init check_space (u16 n)
-{
-	unsigned long pages;
-
-	if ((1 << alloced) * PAGE_SIZE < (n + 2) * sizeof(openpromfs_node)) {
-		pages = __get_free_pages (GFP_KERNEL, alloced + 1);
-		if (!pages)
-			return -1;
-
-		if (nodes) {
-			memcpy ((char *)pages, (char *)nodes,
-				(1 << alloced) * PAGE_SIZE);
-			free_pages ((unsigned long)nodes, alloced);
-		}
-		alloced++;
-		nodes = (openpromfs_node *)pages;
-	}
-	return 0;
-}
-
-static u16 __init get_nodes (u16 parent, u32 node)
-{
-	char *p;
-	u16 n = last_node++, i;
-	char buffer[64];
-
-	if (check_space (n) < 0)
-		return 0xffff;
-	nodes[n].parent = parent;
-	nodes[n].node = node;
-	nodes[n].next = 0xffff;
-	nodes[n].child = 0xffff;
-	nodes[n].first_prop = first_prop++;
-	if (!parent) {
-		char buffer[8];
-		int j;
-		
-		if ((j = prom_getproperty (node, "name", buffer, 8)) >= 0) {
-		    buffer[j] = 0;
-		    if (!strcmp (buffer, "options"))
-			options = n;
-		    else if (!strcmp (buffer, "aliases"))
-		        aliases = n;
-		}
-	}
-	if (n != aliases)
-		for (p = prom_firstprop (node, buffer);
-		     p && p != (char *)-1 && *p;
-		     p = prom_nextprop (node, p, buffer))
-			first_prop++;
-	else {
-		char *q;
-		for (p = prom_firstprop (node, buffer);
-		     p && p != (char *)-1 && *p;
-		     p = prom_nextprop (node, p, buffer)) {
-			if (aliases_nodes == ALIASES_NNODES)
-				break;
-			for (i = 0; i < aliases_nodes; i++)
-				if (!strcmp (p, alias_names [i]))
-					break;
-			if (i < aliases_nodes)
-				continue;
-			q = kmalloc (strlen (p) + 1, GFP_KERNEL);
-			if (!q)
-				return 0xffff;
-			strcpy (q, p);
-			alias_names [aliases_nodes++] = q;
-		}
-		first_prop += ALIASES_NNODES;
-	}
-	node = prom_getchild (node);
-	if (node) {
-		parent = get_nodes (n, node);
-		if (parent == 0xffff)
-			return 0xffff;
-		nodes[n].child = parent;
-		while ((node = prom_getsibling (node)) != 0) {
-			i = get_nodes (n, node);
-			if (i == 0xffff)
-				return 0xffff;
-			nodes[parent].next = i;
-			parent = i;
-		}
-	}
-	return n;
+	kmem_cache_free(op_inode_cachep, OP_I(inode));
 }
 
 static void openprom_read_inode(struct inode * inode)
@@ -1025,6 +365,8 @@
 }
 
 static struct super_operations openprom_sops = { 
+	.alloc_inode	= openprom_alloc_inode,
+	.destroy_inode	= openprom_destroy_inode,
 	.read_inode	= openprom_read_inode,
 	.statfs		= simple_statfs,
 	.remount_fs	= openprom_remount,
@@ -1032,7 +374,8 @@
 
 static int openprom_fill_super(struct super_block *s, void *data, int silent)
 {
-	struct inode * root_inode;
+	struct inode *root_inode;
+	struct op_inode_info *oi;
 
 	s->s_flags |= MS_NOATIME;
 	s->s_blocksize = 1024;
@@ -1043,6 +386,11 @@
 	root_inode = iget(s, OPENPROM_ROOT_INO);
 	if (!root_inode)
 		goto out_no_root;
+
+	oi = OP_I(root_inode);
+	oi->type = op_inode_node;
+	oi->u.node = of_find_node_by_path("/");
+
 	s->s_root = d_alloc_root(root_inode);
 	if (!s->s_root)
 		goto out_no_root;
@@ -1054,10 +402,10 @@
 	return -ENOMEM;
 }
 
-static struct super_block *openprom_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int openprom_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, openprom_fill_super);
+	return get_sb_single(fs_type, flags, data, openprom_fill_super, mnt);
 }
 
 static struct file_system_type openprom_fs_type = {
@@ -1067,29 +415,39 @@
 	.kill_sb	= kill_anon_super,
 };
 
+static void op_inode_init_once(void *data, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct op_inode_info *oi = (struct op_inode_info *) data;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&oi->vfs_inode);
+}
+
 static int __init init_openprom_fs(void)
 {
-	nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
-	if (!nodes) {
-		printk (KERN_WARNING "openpromfs: can't get free page\n");
-		return -EIO;
-	}
-	if (get_nodes (0xffff, prom_root_node) == 0xffff) {
-		printk (KERN_WARNING "openpromfs: couldn't setup tree\n");
-		return -EIO;
-	}
-	nodes[last_node].first_prop = first_prop;
-	return register_filesystem(&openprom_fs_type);
+	int err;
+
+	op_inode_cachep = kmem_cache_create("op_inode_cache",
+					    sizeof(struct op_inode_info),
+					    0,
+					    (SLAB_RECLAIM_ACCOUNT |
+					     SLAB_MEM_SPREAD),
+					    op_inode_init_once, NULL);
+	if (!op_inode_cachep)
+		return -ENOMEM;
+
+	err = register_filesystem(&openprom_fs_type);
+	if (err)
+		kmem_cache_destroy(op_inode_cachep);
+
+	return err;
 }
 
 static void __exit exit_openprom_fs(void)
 {
-	int i;
 	unregister_filesystem(&openprom_fs_type);
-	free_pages ((unsigned long)nodes, alloced);
-	for (i = 0; i < aliases_nodes; i++)
-		kfree (alias_names [i]);
-	nodes = NULL;
+	kmem_cache_destroy(op_inode_cachep);
 }
 
 module_init(init_openprom_fs)
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 7ef1f09..2ef313a 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -329,6 +329,7 @@
 	p->ios[0] = p->ios[1] = 0;
 	p->sectors[0] = p->sectors[1] = 0;
 	devfs_remove("%s/part%d", disk->devfs_name, part);
+	sysfs_remove_link(&p->kobj, "subsystem");
 	if (p->holder_dir)
 		kobject_unregister(p->holder_dir);
 	kobject_uevent(&p->kobj, KOBJ_REMOVE);
@@ -363,6 +364,7 @@
 	kobject_add(&p->kobj);
 	if (!disk->part_uevent_suppress)
 		kobject_uevent(&p->kobj, KOBJ_ADD);
+	sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem");
 	partition_sysfs_add_subdir(p);
 	disk->part[part-1] = p;
 }
@@ -398,6 +400,7 @@
 			kfree(disk_name);
 		}
 	}
+	sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem");
 }
 
 /* Not exported, helper to add_disk(). */
@@ -481,6 +484,10 @@
 		sector_t from = state->parts[p].from;
 		if (!size)
 			continue;
+		if (from + size > get_capacity(disk)) {
+			printk(" %s: p%d exceeds device capacity\n",
+				disk->disk_name, p);
+		}
 		add_partition(disk, p, from, size);
 #ifdef CONFIG_BLK_DEV_MD
 		if (state->parts[p].flags)
@@ -496,8 +503,8 @@
 	struct address_space *mapping = bdev->bd_inode->i_mapping;
 	struct page *page;
 
-	page = read_cache_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
-			(filler_t *)mapping->a_ops->readpage, NULL);
+	page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)),
+				 NULL);
 	if (!IS_ERR(page)) {
 		wait_on_page_locked(page);
 		if (!PageUptodate(page))
@@ -548,5 +555,6 @@
 		put_device(disk->driverfs_dev);
 		disk->driverfs_dev = NULL;
 	}
+	sysfs_remove_link(&disk->kobj, "subsystem");
 	kobject_del(&disk->kobj);
 }
diff --git a/fs/pipe.c b/fs/pipe.c
index 5acd895..2035257 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -979,12 +979,11 @@
  * any operations on the root directory. However, we need a non-trivial
  * d_name - pipe: will go nicely and kill the special-casing in procfs.
  */
-
-static struct super_block *
-pipefs_get_sb(struct file_system_type *fs_type, int flags,
-	      const char *dev_name, void *data)
+static int pipefs_get_sb(struct file_system_type *fs_type,
+			 int flags, const char *dev_name, void *data,
+			 struct vfsmount *mnt)
 {
-	return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC);
+	return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt);
 }
 
 static struct file_system_type pipe_fs_type = {
diff --git a/fs/pnode.c b/fs/pnode.c
index 37b568e..da42ee6 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -53,8 +53,7 @@
 	if (master) {
 		list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave)
 			slave_mnt->mnt_master = master;
-		list_del(&mnt->mnt_slave);
-		list_add(&mnt->mnt_slave, &master->mnt_slave_list);
+		list_move(&mnt->mnt_slave, &master->mnt_slave_list);
 		list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev);
 		INIT_LIST_HEAD(&mnt->mnt_slave_list);
 	} else {
@@ -283,10 +282,8 @@
 		 * umount the child only if the child has no
 		 * other children
 		 */
-		if (child && list_empty(&child->mnt_mounts)) {
-			list_del(&child->mnt_hash);
-			list_add_tail(&child->mnt_hash, &mnt->mnt_hash);
-		}
+		if (child && list_empty(&child->mnt_mounts))
+			list_move_tail(&child->mnt_hash, &mnt->mnt_hash);
 	}
 }
 
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6cc77dc..6ba7785 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -74,6 +74,16 @@
 #include <linux/poll.h>
 #include "internal.h"
 
+/* NOTE:
+ *	Implementing inode permission operations in /proc is almost
+ *	certainly an error.  Permission checks need to happen during
+ *	each system call not at open time.  The reason is that most of
+ *	what we wish to check for permissions in /proc varies at runtime.
+ *
+ *	The classic example of a problem is opening file descriptors
+ *	in /proc for a task before it execs a suid executable.
+ */
+
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
  * Feel free to change the macro below - just keep the range distinct from
@@ -121,6 +131,8 @@
 	PROC_TGID_ATTR_PREV,
 	PROC_TGID_ATTR_EXEC,
 	PROC_TGID_ATTR_FSCREATE,
+	PROC_TGID_ATTR_KEYCREATE,
+	PROC_TGID_ATTR_SOCKCREATE,
 #endif
 #ifdef CONFIG_AUDITSYSCALL
 	PROC_TGID_LOGINUID,
@@ -162,6 +174,8 @@
 	PROC_TID_ATTR_PREV,
 	PROC_TID_ATTR_EXEC,
 	PROC_TID_ATTR_FSCREATE,
+	PROC_TID_ATTR_KEYCREATE,
+	PROC_TID_ATTR_SOCKCREATE,
 #endif
 #ifdef CONFIG_AUDITSYSCALL
 	PROC_TID_LOGINUID,
@@ -173,6 +187,9 @@
 	PROC_TID_FD_DIR = 0x8000,	/* 0x8000-0xffff */
 };
 
+/* Worst case buffer size needed for holding an integer. */
+#define PROC_NUMBUF 10
+
 struct pid_entry {
 	int type;
 	int len;
@@ -275,6 +292,8 @@
 	E(PROC_TGID_ATTR_PREV,     "prev",     S_IFREG|S_IRUGO),
 	E(PROC_TGID_ATTR_EXEC,     "exec",     S_IFREG|S_IRUGO|S_IWUGO),
 	E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
+	E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
+	E(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
 	{0,0,NULL,0}
 };
 static struct pid_entry tid_attr_stuff[] = {
@@ -282,6 +301,8 @@
 	E(PROC_TID_ATTR_PREV,      "prev",     S_IFREG|S_IRUGO),
 	E(PROC_TID_ATTR_EXEC,      "exec",     S_IFREG|S_IRUGO|S_IWUGO),
 	E(PROC_TID_ATTR_FSCREATE,  "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
+	E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
+	E(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
 	{0,0,NULL,0}
 };
 #endif
@@ -290,12 +311,15 @@
 
 static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-	struct task_struct *task = proc_task(inode);
-	struct files_struct *files;
+	struct task_struct *task = get_proc_task(inode);
+	struct files_struct *files = NULL;
 	struct file *file;
-	int fd = proc_type(inode) - PROC_TID_FD_DIR;
+	int fd = proc_fd(inode);
 
-	files = get_files_struct(task);
+	if (task) {
+		files = get_files_struct(task);
+		put_task_struct(task);
+	}
 	if (files) {
 		/*
 		 * We are not taking a ref to the file structure, so we must
@@ -327,10 +351,29 @@
 	return fs;
 }
 
+static int get_nr_threads(struct task_struct *tsk)
+{
+	/* Must be called with the rcu_read_lock held */
+	unsigned long flags;
+	int count = 0;
+
+	if (lock_task_sighand(tsk, &flags)) {
+		count = atomic_read(&tsk->signal->count);
+		unlock_task_sighand(tsk, &flags);
+	}
+	return count;
+}
+
 static int proc_cwd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-	struct fs_struct *fs = get_fs_struct(proc_task(inode));
+	struct task_struct *task = get_proc_task(inode);
+	struct fs_struct *fs = NULL;
 	int result = -ENOENT;
+
+	if (task) {
+		fs = get_fs_struct(task);
+		put_task_struct(task);
+	}
 	if (fs) {
 		read_lock(&fs->lock);
 		*mnt = mntget(fs->pwdmnt);
@@ -344,8 +387,14 @@
 
 static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
 {
-	struct fs_struct *fs = get_fs_struct(proc_task(inode));
+	struct task_struct *task = get_proc_task(inode);
+	struct fs_struct *fs = NULL;
 	int result = -ENOENT;
+
+	if (task) {
+		fs = get_fs_struct(task);
+		put_task_struct(task);
+	}
 	if (fs) {
 		read_lock(&fs->lock);
 		*mnt = mntget(fs->rootmnt);
@@ -357,54 +406,6 @@
 	return result;
 }
 
-
-/* Same as proc_root_link, but this addionally tries to get fs from other
- * threads in the group */
-static int proc_task_root_link(struct inode *inode, struct dentry **dentry,
-				struct vfsmount **mnt)
-{
-	struct fs_struct *fs;
-	int result = -ENOENT;
-	struct task_struct *leader = proc_task(inode);
-
-	task_lock(leader);
-	fs = leader->fs;
-	if (fs) {
-		atomic_inc(&fs->count);
-		task_unlock(leader);
-	} else {
-		/* Try to get fs from other threads */
-		task_unlock(leader);
-		read_lock(&tasklist_lock);
-		if (pid_alive(leader)) {
-			struct task_struct *task = leader;
-
-			while ((task = next_thread(task)) != leader) {
-				task_lock(task);
-				fs = task->fs;
-				if (fs) {
-					atomic_inc(&fs->count);
-					task_unlock(task);
-					break;
-				}
-				task_unlock(task);
-			}
-		}
-		read_unlock(&tasklist_lock);
-	}
-
-	if (fs) {
-		read_lock(&fs->lock);
-		*mnt = mntget(fs->rootmnt);
-		*dentry = dget(fs->root);
-		read_unlock(&fs->lock);
-		result = 0;
-		put_fs_struct(fs);
-	}
-	return result;
-}
-
-
 #define MAY_PTRACE(task) \
 	(task == current || \
 	(task->parent == current && \
@@ -535,142 +536,22 @@
 /************************************************************************/
 
 /* permission checks */
-
-/* If the process being read is separated by chroot from the reading process,
- * don't let the reader access the threads.
- *
- * note: this does dput(root) and mntput(vfsmnt) on exit.
- */
-static int proc_check_chroot(struct dentry *root, struct vfsmount *vfsmnt)
+static int proc_fd_access_allowed(struct inode *inode)
 {
-	struct dentry *de, *base;
-	struct vfsmount *our_vfsmnt, *mnt;
-	int res = 0;
-
-	read_lock(&current->fs->lock);
-	our_vfsmnt = mntget(current->fs->rootmnt);
-	base = dget(current->fs->root);
-	read_unlock(&current->fs->lock);
-
-	spin_lock(&vfsmount_lock);
-	de = root;
-	mnt = vfsmnt;
-
-	while (mnt != our_vfsmnt) {
-		if (mnt == mnt->mnt_parent)
-			goto out;
-		de = mnt->mnt_mountpoint;
-		mnt = mnt->mnt_parent;
+	struct task_struct *task;
+	int allowed = 0;
+	/* Allow access to a task's file descriptors if it is us or we
+	 * may use ptrace attach to the process and find out that
+	 * information.
+	 */
+	task = get_proc_task(inode);
+	if (task) {
+		allowed = ptrace_may_attach(task);
+		put_task_struct(task);
 	}
-
-	if (!is_subdir(de, base))
-		goto out;
-	spin_unlock(&vfsmount_lock);
-
-exit:
-	dput(base);
-	mntput(our_vfsmnt);
-	dput(root);
-	mntput(vfsmnt);
-	return res;
-out:
-	spin_unlock(&vfsmount_lock);
-	res = -EACCES;
-	goto exit;
+	return allowed;
 }
 
-static int proc_check_root(struct inode *inode)
-{
-	struct dentry *root;
-	struct vfsmount *vfsmnt;
-
-	if (proc_root_link(inode, &root, &vfsmnt)) /* Ewww... */
-		return -ENOENT;
-	return proc_check_chroot(root, vfsmnt);
-}
-
-static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
-	if (generic_permission(inode, mask, NULL) != 0)
-		return -EACCES;
-	return proc_check_root(inode);
-}
-
-static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
-	struct dentry *root;
-	struct vfsmount *vfsmnt;
-
-	if (generic_permission(inode, mask, NULL) != 0)
-		return -EACCES;
-
-	if (proc_task_root_link(inode, &root, &vfsmnt))
-		return -ENOENT;
-
-	return proc_check_chroot(root, vfsmnt);
-}
-
-extern struct seq_operations proc_pid_maps_op;
-static int maps_open(struct inode *inode, struct file *file)
-{
-	struct task_struct *task = proc_task(inode);
-	int ret = seq_open(file, &proc_pid_maps_op);
-	if (!ret) {
-		struct seq_file *m = file->private_data;
-		m->private = task;
-	}
-	return ret;
-}
-
-static struct file_operations proc_maps_operations = {
-	.open		= maps_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-
-#ifdef CONFIG_NUMA
-extern struct seq_operations proc_pid_numa_maps_op;
-static int numa_maps_open(struct inode *inode, struct file *file)
-{
-	struct task_struct *task = proc_task(inode);
-	int ret = seq_open(file, &proc_pid_numa_maps_op);
-	if (!ret) {
-		struct seq_file *m = file->private_data;
-		m->private = task;
-	}
-	return ret;
-}
-
-static struct file_operations proc_numa_maps_operations = {
-	.open		= numa_maps_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-#endif
-
-#ifdef CONFIG_MMU
-extern struct seq_operations proc_pid_smaps_op;
-static int smaps_open(struct inode *inode, struct file *file)
-{
-	struct task_struct *task = proc_task(inode);
-	int ret = seq_open(file, &proc_pid_smaps_op);
-	if (!ret) {
-		struct seq_file *m = file->private_data;
-		m->private = task;
-	}
-	return ret;
-}
-
-static struct file_operations proc_smaps_operations = {
-	.open		= smaps_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= seq_release,
-};
-#endif
-
 extern struct seq_operations mounts_op;
 struct proc_mounts {
 	struct seq_file m;
@@ -679,16 +560,19 @@
 
 static int mounts_open(struct inode *inode, struct file *file)
 {
-	struct task_struct *task = proc_task(inode);
-	struct namespace *namespace;
+	struct task_struct *task = get_proc_task(inode);
+	struct namespace *namespace = NULL;
 	struct proc_mounts *p;
 	int ret = -EINVAL;
 
-	task_lock(task);
-	namespace = task->namespace;
-	if (namespace)
-		get_namespace(namespace);
-	task_unlock(task);
+	if (task) {
+		task_lock(task);
+		namespace = task->namespace;
+		if (namespace)
+			get_namespace(namespace);
+		task_unlock(task);
+		put_task_struct(task);
+	}
 
 	if (namespace) {
 		ret = -ENOMEM;
@@ -745,17 +629,21 @@
 extern struct seq_operations mountstats_op;
 static int mountstats_open(struct inode *inode, struct file *file)
 {
-	struct task_struct *task = proc_task(inode);
 	int ret = seq_open(file, &mountstats_op);
 
 	if (!ret) {
 		struct seq_file *m = file->private_data;
-		struct namespace *namespace;
-		task_lock(task);
-		namespace = task->namespace;
-		if (namespace)
-			get_namespace(namespace);
-		task_unlock(task);
+		struct namespace *namespace = NULL;
+		struct task_struct *task = get_proc_task(inode);
+
+		if (task) {
+			task_lock(task);
+			namespace = task->namespace;
+			if (namespace)
+				get_namespace(namespace);
+			task_unlock(task);
+			put_task_struct(task);
+		}
 
 		if (namespace)
 			m->private = namespace;
@@ -782,18 +670,27 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	unsigned long page;
 	ssize_t length;
-	struct task_struct *task = proc_task(inode);
+	struct task_struct *task = get_proc_task(inode);
+
+	length = -ESRCH;
+	if (!task)
+		goto out_no_task;
 
 	if (count > PROC_BLOCK_SIZE)
 		count = PROC_BLOCK_SIZE;
+
+	length = -ENOMEM;
 	if (!(page = __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
+		goto out;
 
 	length = PROC_I(inode)->op.proc_read(task, (char*)page);
 
 	if (length >= 0)
 		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
 	free_page(page);
+out:
+	put_task_struct(task);
+out_no_task:
 	return length;
 }
 
@@ -810,12 +707,15 @@
 static ssize_t mem_read(struct file * file, char __user * buf,
 			size_t count, loff_t *ppos)
 {
-	struct task_struct *task = proc_task(file->f_dentry->d_inode);
+	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
 	char *page;
 	unsigned long src = *ppos;
 	int ret = -ESRCH;
 	struct mm_struct *mm;
 
+	if (!task)
+		goto out_no_task;
+
 	if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
 		goto out;
 
@@ -865,6 +765,8 @@
 out_free:
 	free_page((unsigned long) page);
 out:
+	put_task_struct(task);
+out_no_task:
 	return ret;
 }
 
@@ -877,15 +779,20 @@
 {
 	int copied = 0;
 	char *page;
-	struct task_struct *task = proc_task(file->f_dentry->d_inode);
+	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
 	unsigned long dst = *ppos;
 
-	if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
-		return -ESRCH;
+	copied = -ESRCH;
+	if (!task)
+		goto out_no_task;
 
+	if (!MAY_PTRACE(task) || !ptrace_may_attach(task))
+		goto out;
+
+	copied = -ENOMEM;
 	page = (char *)__get_free_page(GFP_USER);
 	if (!page)
-		return -ENOMEM;
+		goto out;
 
 	while (count > 0) {
 		int this_len, retval;
@@ -908,6 +815,9 @@
 	}
 	*ppos = dst;
 	free_page((unsigned long) page);
+out:
+	put_task_struct(task);
+out_no_task:
 	return copied;
 }
 #endif
@@ -938,13 +848,18 @@
 static ssize_t oom_adjust_read(struct file *file, char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	struct task_struct *task = proc_task(file->f_dentry->d_inode);
-	char buffer[8];
+	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);
+	char buffer[PROC_NUMBUF];
 	size_t len;
-	int oom_adjust = task->oomkilladj;
+	int oom_adjust;
 	loff_t __ppos = *ppos;
 
-	len = sprintf(buffer, "%i\n", oom_adjust);
+	if (!task)
+		return -ESRCH;
+	oom_adjust = task->oomkilladj;
+	put_task_struct(task);
+
+	len = snprintf(buffer, sizeof(buffer), "%i\n", oom_adjust);
 	if (__ppos >= len)
 		return 0;
 	if (count > len-__ppos)
@@ -958,15 +873,15 @@
 static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
 				size_t count, loff_t *ppos)
 {
-	struct task_struct *task = proc_task(file->f_dentry->d_inode);
-	char buffer[8], *end;
+	struct task_struct *task;
+	char buffer[PROC_NUMBUF], *end;
 	int oom_adjust;
 
 	if (!capable(CAP_SYS_RESOURCE))
 		return -EPERM;
-	memset(buffer, 0, 8);
-	if (count > 6)
-		count = 6;
+	memset(buffer, 0, sizeof(buffer));
+	if (count > sizeof(buffer) - 1)
+		count = sizeof(buffer) - 1;
 	if (copy_from_user(buffer, buf, count))
 		return -EFAULT;
 	oom_adjust = simple_strtol(buffer, &end, 0);
@@ -974,7 +889,11 @@
 		return -EINVAL;
 	if (*end == '\n')
 		end++;
+	task = get_proc_task(file->f_dentry->d_inode);
+	if (!task)
+		return -ESRCH;
 	task->oomkilladj = oom_adjust;
+	put_task_struct(task);
 	if (end - buffer == 0)
 		return -EIO;
 	return end - buffer;
@@ -985,22 +904,21 @@
 	.write		= oom_adjust_write,
 };
 
-static struct inode_operations proc_mem_inode_operations = {
-	.permission	= proc_permission,
-};
-
 #ifdef CONFIG_AUDITSYSCALL
 #define TMPBUFLEN 21
 static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
 				  size_t count, loff_t *ppos)
 {
 	struct inode * inode = file->f_dentry->d_inode;
-	struct task_struct *task = proc_task(inode);
+	struct task_struct *task = get_proc_task(inode);
 	ssize_t length;
 	char tmpbuf[TMPBUFLEN];
 
+	if (!task)
+		return -ESRCH;
 	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
 				audit_get_loginuid(task->audit_context));
+	put_task_struct(task);
 	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
 }
 
@@ -1010,17 +928,16 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	char *page, *tmp;
 	ssize_t length;
-	struct task_struct *task = proc_task(inode);
 	uid_t loginuid;
 
 	if (!capable(CAP_AUDIT_CONTROL))
 		return -EPERM;
 
-	if (current != task)
+	if (current != pid_task(proc_pid(inode), PIDTYPE_PID))
 		return -EPERM;
 
-	if (count > PAGE_SIZE)
-		count = PAGE_SIZE;
+	if (count >= PAGE_SIZE)
+		count = PAGE_SIZE - 1;
 
 	if (*ppos != 0) {
 		/* No partial writes. */
@@ -1033,13 +950,14 @@
 	if (copy_from_user(page, buf, count))
 		goto out_free_page;
 
+	page[count] = '\0';
 	loginuid = simple_strtoul(page, &tmp, 10);
 	if (tmp == page) {
 		length = -EINVAL;
 		goto out_free_page;
 
 	}
-	length = audit_set_loginuid(task, loginuid);
+	length = audit_set_loginuid(current, loginuid);
 	if (likely(length == 0))
 		length = count;
 
@@ -1058,13 +976,16 @@
 static ssize_t seccomp_read(struct file *file, char __user *buf,
 			    size_t count, loff_t *ppos)
 {
-	struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
+	struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
 	char __buf[20];
 	loff_t __ppos = *ppos;
 	size_t len;
 
+	if (!tsk)
+		return -ESRCH;
 	/* no need to print the trailing zero, so use only len */
 	len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
+	put_task_struct(tsk);
 	if (__ppos >= len)
 		return 0;
 	if (count > len - __ppos)
@@ -1078,29 +999,43 @@
 static ssize_t seccomp_write(struct file *file, const char __user *buf,
 			     size_t count, loff_t *ppos)
 {
-	struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
+	struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
 	char __buf[20], *end;
 	unsigned int seccomp_mode;
+	ssize_t result;
+
+	result = -ESRCH;
+	if (!tsk)
+		goto out_no_task;
 
 	/* can set it only once to be even more secure */
+	result = -EPERM;
 	if (unlikely(tsk->seccomp.mode))
-		return -EPERM;
+		goto out;
 
+	result = -EFAULT;
 	memset(__buf, 0, sizeof(__buf));
 	count = min(count, sizeof(__buf) - 1);
 	if (copy_from_user(__buf, buf, count))
-		return -EFAULT;
+		goto out;
+
 	seccomp_mode = simple_strtoul(__buf, &end, 0);
 	if (*end == '\n')
 		end++;
+	result = -EINVAL;
 	if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
 		tsk->seccomp.mode = seccomp_mode;
 		set_tsk_thread_flag(tsk, TIF_SECCOMP);
 	} else
-		return -EINVAL;
+		goto out;
+	result = -EIO;
 	if (unlikely(!(end - __buf)))
-		return -EIO;
-	return end - __buf;
+		goto out;
+	result = end - __buf;
+out:
+	put_task_struct(tsk);
+out_no_task:
+	return result;
 }
 
 static struct file_operations proc_seccomp_operations = {
@@ -1117,10 +1052,8 @@
 	/* We don't need a base pointer in the /proc filesystem */
 	path_release(nd);
 
-	if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE))
-		goto out;
-	error = proc_check_root(inode);
-	if (error)
+	/* Are we allowed to snoop on the tasks file descriptors? */
+	if (!proc_fd_access_allowed(inode))
 		goto out;
 
 	error = PROC_I(inode)->op.proc_get_link(inode, &nd->dentry, &nd->mnt);
@@ -1162,12 +1095,8 @@
 	struct dentry *de;
 	struct vfsmount *mnt = NULL;
 
-	lock_kernel();
-
-	if (current->fsuid != inode->i_uid && !capable(CAP_DAC_OVERRIDE))
-		goto out;
-	error = proc_check_root(inode);
-	if (error)
+	/* Are we allowed to snoop on the tasks file descriptors? */
+	if (!proc_fd_access_allowed(inode))
 		goto out;
 
 	error = PROC_I(inode)->op.proc_get_link(inode, &de, &mnt);
@@ -1178,7 +1107,6 @@
 	dput(de);
 	mntput(mnt);
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -1187,21 +1115,20 @@
 	.follow_link	= proc_pid_follow_link
 };
 
-#define NUMBUF 10
-
 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
-	struct task_struct *p = proc_task(inode);
+	struct dentry *dentry = filp->f_dentry;
+	struct inode *inode = dentry->d_inode;
+	struct task_struct *p = get_proc_task(inode);
 	unsigned int fd, tid, ino;
 	int retval;
-	char buf[NUMBUF];
+	char buf[PROC_NUMBUF];
 	struct files_struct * files;
 	struct fdtable *fdt;
 
 	retval = -ENOENT;
-	if (!pid_alive(p))
-		goto out;
+	if (!p)
+		goto out_no_task;
 	retval = 0;
 	tid = p->pid;
 
@@ -1212,7 +1139,7 @@
 				goto out;
 			filp->f_pos++;
 		case 1:
-			ino = fake_ino(tid, PROC_TID_INO);
+			ino = parent_ino(dentry);
 			if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
 				goto out;
 			filp->f_pos++;
@@ -1231,7 +1158,7 @@
 					continue;
 				rcu_read_unlock();
 
-				j = NUMBUF;
+				j = PROC_NUMBUF;
 				i = fd;
 				do {
 					j--;
@@ -1240,7 +1167,7 @@
 				} while (i);
 
 				ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
-				if (filldir(dirent, buf+j, NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
+				if (filldir(dirent, buf+j, PROC_NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
 					rcu_read_lock();
 					break;
 				}
@@ -1250,6 +1177,8 @@
 			put_files_struct(files);
 	}
 out:
+	put_task_struct(p);
+out_no_task:
 	return retval;
 }
 
@@ -1261,16 +1190,18 @@
 	int pid;
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
+	struct task_struct *task = get_proc_task(inode);
 	struct pid_entry *p;
 	ino_t ino;
 	int ret;
 
 	ret = -ENOENT;
-	if (!pid_alive(proc_task(inode)))
+	if (!task)
 		goto out;
 
 	ret = 0;
-	pid = proc_task(inode)->pid;
+	pid = task->pid;
+	put_task_struct(task);
 	i = filp->f_pos;
 	switch (i) {
 	case 0:
@@ -1353,22 +1284,19 @@
 
 	/* Common stuff */
 	ei = PROC_I(inode);
-	ei->task = NULL;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_ino = fake_ino(task->pid, ino);
 
-	if (!pid_alive(task))
-		goto out_unlock;
-
 	/*
 	 * grab the reference to task.
 	 */
-	get_task_struct(task);
-	ei->task = task;
-	ei->type = ino;
+	ei->pid = get_pid(task->pids[PIDTYPE_PID].pid);
+	if (!ei->pid)
+		goto out_unlock;
+
 	inode->i_uid = 0;
 	inode->i_gid = 0;
-	if (ino == PROC_TGID_INO || ino == PROC_TID_INO || task_dumpable(task)) {
+	if (task_dumpable(task)) {
 		inode->i_uid = task->euid;
 		inode->i_gid = task->egid;
 	}
@@ -1378,7 +1306,6 @@
 	return inode;
 
 out_unlock:
-	ei->pde = NULL;
 	iput(inode);
 	return NULL;
 }
@@ -1392,13 +1319,21 @@
  *
  * Rewrite the inode's ownerships here because the owning task may have
  * performed a setuid(), etc.
+ *
+ * Before the /proc/pid/status file was created the only way to read
+ * the effective uid of a /process was to stat /proc/pid.  Reading
+ * /proc/pid/status is slow enough that procps and other packages
+ * kept stating /proc/pid.  To keep the rules in /proc simple I have
+ * made this apply to all per process world readable and executable
+ * directories.
  */
 static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
-	struct task_struct *task = proc_task(inode);
-	if (pid_alive(task)) {
-		if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) {
+	struct task_struct *task = get_proc_task(inode);
+	if (task) {
+		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
+		    task_dumpable(task)) {
 			inode->i_uid = task->euid;
 			inode->i_gid = task->egid;
 		} else {
@@ -1406,50 +1341,66 @@
 			inode->i_gid = 0;
 		}
 		security_task_to_inode(task, inode);
+		put_task_struct(task);
 		return 1;
 	}
 	d_drop(dentry);
 	return 0;
 }
 
-static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
 {
 	struct inode *inode = dentry->d_inode;
-	struct task_struct *task = proc_task(inode);
-	int fd = proc_type(inode) - PROC_TID_FD_DIR;
-	struct files_struct *files;
+	struct task_struct *task;
+	generic_fillattr(inode, stat);
 
-	files = get_files_struct(task);
-	if (files) {
-		rcu_read_lock();
-		if (fcheck_files(files, fd)) {
-			rcu_read_unlock();
-			put_files_struct(files);
-			if (task_dumpable(task)) {
-				inode->i_uid = task->euid;
-				inode->i_gid = task->egid;
-			} else {
-				inode->i_uid = 0;
-				inode->i_gid = 0;
-			}
-			security_task_to_inode(task, inode);
-			return 1;
+	rcu_read_lock();
+	stat->uid = 0;
+	stat->gid = 0;
+	task = pid_task(proc_pid(inode), PIDTYPE_PID);
+	if (task) {
+		if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
+		    task_dumpable(task)) {
+			stat->uid = task->euid;
+			stat->gid = task->egid;
 		}
-		rcu_read_unlock();
-		put_files_struct(files);
 	}
-	d_drop(dentry);
+	rcu_read_unlock();
 	return 0;
 }
 
-static void pid_base_iput(struct dentry *dentry, struct inode *inode)
+static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
 {
-	struct task_struct *task = proc_task(inode);
-	spin_lock(&task->proc_lock);
-	if (task->proc_dentry == dentry)
-		task->proc_dentry = NULL;
-	spin_unlock(&task->proc_lock);
-	iput(inode);
+	struct inode *inode = dentry->d_inode;
+	struct task_struct *task = get_proc_task(inode);
+	int fd = proc_fd(inode);
+	struct files_struct *files;
+
+	if (task) {
+		files = get_files_struct(task);
+		if (files) {
+			rcu_read_lock();
+			if (fcheck_files(files, fd)) {
+				rcu_read_unlock();
+				put_files_struct(files);
+				if (task_dumpable(task)) {
+					inode->i_uid = task->euid;
+					inode->i_gid = task->egid;
+				} else {
+					inode->i_uid = 0;
+					inode->i_gid = 0;
+				}
+				security_task_to_inode(task, inode);
+				put_task_struct(task);
+				return 1;
+			}
+			rcu_read_unlock();
+			put_files_struct(files);
+		}
+		put_task_struct(task);
+	}
+	d_drop(dentry);
+	return 0;
 }
 
 static int pid_delete_dentry(struct dentry * dentry)
@@ -1458,7 +1409,7 @@
 	 * If so, then don't put the dentry on the lru list,
 	 * kill it immediately.
 	 */
-	return !pid_alive(proc_task(dentry->d_inode));
+	return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
 }
 
 static struct dentry_operations tid_fd_dentry_operations =
@@ -1473,13 +1424,6 @@
 	.d_delete	= pid_delete_dentry,
 };
 
-static struct dentry_operations pid_base_dentry_operations =
-{
-	.d_revalidate	= pid_revalidate,
-	.d_iput		= pid_base_iput,
-	.d_delete	= pid_delete_dentry,
-};
-
 /* Lookups */
 
 static unsigned name_to_int(struct dentry *dentry)
@@ -1507,22 +1451,24 @@
 /* SMP-safe */
 static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
 {
-	struct task_struct *task = proc_task(dir);
+	struct task_struct *task = get_proc_task(dir);
 	unsigned fd = name_to_int(dentry);
+	struct dentry *result = ERR_PTR(-ENOENT);
 	struct file * file;
 	struct files_struct * files;
 	struct inode *inode;
 	struct proc_inode *ei;
 
+	if (!task)
+		goto out_no_task;
 	if (fd == ~0U)
 		goto out;
-	if (!pid_alive(task))
-		goto out;
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd);
 	if (!inode)
 		goto out;
 	ei = PROC_I(inode);
+	ei->fd = fd;
 	files = get_files_struct(task);
 	if (!files)
 		goto out_unlock;
@@ -1547,19 +1493,25 @@
 	ei->op.proc_get_link = proc_fd_link;
 	dentry->d_op = &tid_fd_dentry_operations;
 	d_add(dentry, inode);
-	return NULL;
+	/* Close the race of the process dying before we return the dentry */
+	if (tid_fd_revalidate(dentry, NULL))
+		result = NULL;
+out:
+	put_task_struct(task);
+out_no_task:
+	return result;
 
 out_unlock2:
 	spin_unlock(&files->file_lock);
 	put_files_struct(files);
 out_unlock:
 	iput(inode);
-out:
-	return ERR_PTR(-ENOENT);
+	goto out;
 }
 
 static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir);
 static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd);
+static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
 
 static struct file_operations proc_fd_operations = {
 	.read		= generic_read_dir,
@@ -1576,12 +1528,11 @@
  */
 static struct inode_operations proc_fd_inode_operations = {
 	.lookup		= proc_lookupfd,
-	.permission	= proc_permission,
 };
 
 static struct inode_operations proc_task_inode_operations = {
 	.lookup		= proc_task_lookup,
-	.permission	= proc_task_permission,
+	.getattr	= proc_task_getattr,
 };
 
 #ifdef CONFIG_SECURITY
@@ -1591,12 +1542,17 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	unsigned long page;
 	ssize_t length;
-	struct task_struct *task = proc_task(inode);
+	struct task_struct *task = get_proc_task(inode);
+
+	length = -ESRCH;
+	if (!task)
+		goto out_no_task;
 
 	if (count > PAGE_SIZE)
 		count = PAGE_SIZE;
+	length = -ENOMEM;
 	if (!(page = __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
+		goto out;
 
 	length = security_getprocattr(task, 
 				      (char*)file->f_dentry->d_name.name, 
@@ -1604,6 +1560,9 @@
 	if (length >= 0)
 		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
 	free_page(page);
+out:
+	put_task_struct(task);
+out_no_task:
 	return length;
 }
 
@@ -1613,26 +1572,36 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	char *page; 
 	ssize_t length; 
-	struct task_struct *task = proc_task(inode); 
+	struct task_struct *task = get_proc_task(inode);
 
+	length = -ESRCH;
+	if (!task)
+		goto out_no_task;
 	if (count > PAGE_SIZE) 
 		count = PAGE_SIZE; 
-	if (*ppos != 0) {
-		/* No partial writes. */
-		return -EINVAL;
-	}
+
+	/* No partial writes. */
+	length = -EINVAL;
+	if (*ppos != 0)
+		goto out;
+
+	length = -ENOMEM;
 	page = (char*)__get_free_page(GFP_USER); 
 	if (!page) 
-		return -ENOMEM;
+		goto out;
+
 	length = -EFAULT; 
 	if (copy_from_user(page, buf, count)) 
-		goto out;
+		goto out_free;
 
 	length = security_setprocattr(task, 
 				      (char*)file->f_dentry->d_name.name, 
 				      (void*)page, count);
-out:
+out_free:
 	free_page((unsigned long) page);
+out:
+	put_task_struct(task);
+out_no_task:
 	return length;
 } 
 
@@ -1647,24 +1616,22 @@
 static struct inode_operations proc_tgid_attr_inode_operations;
 #endif
 
-static int get_tid_list(int index, unsigned int *tids, struct inode *dir);
-
 /* SMP-safe */
 static struct dentry *proc_pident_lookup(struct inode *dir, 
 					 struct dentry *dentry,
 					 struct pid_entry *ents)
 {
 	struct inode *inode;
-	int error;
-	struct task_struct *task = proc_task(dir);
+	struct dentry *error;
+	struct task_struct *task = get_proc_task(dir);
 	struct pid_entry *p;
 	struct proc_inode *ei;
 
-	error = -ENOENT;
+	error = ERR_PTR(-ENOENT);
 	inode = NULL;
 
-	if (!pid_alive(task))
-		goto out;
+	if (!task)
+		goto out_no_task;
 
 	for (p = ents; p->name; p++) {
 		if (p->len != dentry->d_name.len)
@@ -1675,7 +1642,7 @@
 	if (!p->name)
 		goto out;
 
-	error = -EINVAL;
+	error = ERR_PTR(-EINVAL);
 	inode = proc_pid_make_inode(dir->i_sb, task, p->type);
 	if (!inode)
 		goto out;
@@ -1688,7 +1655,7 @@
 	 */
 	switch(p->type) {
 		case PROC_TGID_TASK:
-			inode->i_nlink = 2 + get_tid_list(2, NULL, dir);
+			inode->i_nlink = 2;
 			inode->i_op = &proc_task_inode_operations;
 			inode->i_fop = &proc_task_operations;
 			break;
@@ -1758,7 +1725,6 @@
 #endif
 		case PROC_TID_MEM:
 		case PROC_TGID_MEM:
-			inode->i_op = &proc_mem_inode_operations;
 			inode->i_fop = &proc_mem_operations;
 			break;
 #ifdef CONFIG_SECCOMP
@@ -1800,6 +1766,10 @@
 		case PROC_TGID_ATTR_EXEC:
 		case PROC_TID_ATTR_FSCREATE:
 		case PROC_TGID_ATTR_FSCREATE:
+		case PROC_TID_ATTR_KEYCREATE:
+		case PROC_TGID_ATTR_KEYCREATE:
+		case PROC_TID_ATTR_SOCKCREATE:
+		case PROC_TGID_ATTR_SOCKCREATE:
 			inode->i_fop = &proc_pid_attr_operations;
 			break;
 #endif
@@ -1841,14 +1811,18 @@
 		default:
 			printk("procfs: impossible type (%d)",p->type);
 			iput(inode);
-			return ERR_PTR(-EINVAL);
+			error = ERR_PTR(-EINVAL);
+			goto out;
 	}
 	dentry->d_op = &pid_dentry_operations;
 	d_add(dentry, inode);
-	return NULL;
-
+	/* Close the race of the process dying before we return the dentry */
+	if (pid_revalidate(dentry, NULL))
+		error = NULL;
 out:
-	return ERR_PTR(error);
+	put_task_struct(task);
+out_no_task:
+	return error;
 }
 
 static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
@@ -1871,10 +1845,12 @@
 
 static struct inode_operations proc_tgid_base_inode_operations = {
 	.lookup		= proc_tgid_base_lookup,
+	.getattr	= pid_getattr,
 };
 
 static struct inode_operations proc_tid_base_inode_operations = {
 	.lookup		= proc_tid_base_lookup,
+	.getattr	= pid_getattr,
 };
 
 #ifdef CONFIG_SECURITY
@@ -1916,10 +1892,12 @@
 
 static struct inode_operations proc_tgid_attr_inode_operations = {
 	.lookup		= proc_tgid_attr_lookup,
+	.getattr	= pid_getattr,
 };
 
 static struct inode_operations proc_tid_attr_inode_operations = {
 	.lookup		= proc_tid_attr_lookup,
+	.getattr	= pid_getattr,
 };
 #endif
 
@@ -1929,14 +1907,14 @@
 static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
 			      int buflen)
 {
-	char tmp[30];
+	char tmp[PROC_NUMBUF];
 	sprintf(tmp, "%d", current->tgid);
 	return vfs_readlink(dentry,buffer,buflen,tmp);
 }
 
 static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-	char tmp[30];
+	char tmp[PROC_NUMBUF];
 	sprintf(tmp, "%d", current->tgid);
 	return ERR_PTR(vfs_follow_link(nd,tmp));
 }	
@@ -1947,67 +1925,80 @@
 };
 
 /**
- * proc_pid_unhash -  Unhash /proc/@pid entry from the dcache.
- * @p: task that should be flushed.
+ * proc_flush_task -  Remove dcache entries for @task from the /proc dcache.
  *
- * Drops the /proc/@pid dcache entry from the hash chains.
+ * @task: task that should be flushed.
  *
- * Dropping /proc/@pid entries and detach_pid must be synchroneous,
- * otherwise e.g. /proc/@pid/exe might point to the wrong executable,
- * if the pid value is immediately reused. This is enforced by
- * - caller must acquire spin_lock(p->proc_lock)
- * - must be called before detach_pid()
- * - proc_pid_lookup acquires proc_lock, and checks that
- *   the target is not dead by looking at the attach count
- *   of PIDTYPE_PID.
+ * Looks in the dcache for
+ * /proc/@pid
+ * /proc/@tgid/task/@pid
+ * if either directory is present flushes it and all of it'ts children
+ * from the dcache.
+ *
+ * It is safe and reasonable to cache /proc entries for a task until
+ * that task exits.  After that they just clog up the dcache with
+ * useless entries, possibly causing useful dcache entries to be
+ * flushed instead.  This routine is proved to flush those useless
+ * dcache entries at process exit time.
+ *
+ * NOTE: This routine is just an optimization so it does not guarantee
+ *       that no dcache entries will exist at process exit time it
+ *       just makes it very unlikely that any will persist.
  */
-
-struct dentry *proc_pid_unhash(struct task_struct *p)
+void proc_flush_task(struct task_struct *task)
 {
-	struct dentry *proc_dentry;
+	struct dentry *dentry, *leader, *dir;
+	char buf[PROC_NUMBUF];
+	struct qstr name;
 
-	proc_dentry = p->proc_dentry;
-	if (proc_dentry != NULL) {
-
-		spin_lock(&dcache_lock);
-		spin_lock(&proc_dentry->d_lock);
-		if (!d_unhashed(proc_dentry)) {
-			dget_locked(proc_dentry);
-			__d_drop(proc_dentry);
-			spin_unlock(&proc_dentry->d_lock);
-		} else {
-			spin_unlock(&proc_dentry->d_lock);
-			proc_dentry = NULL;
-		}
-		spin_unlock(&dcache_lock);
+	name.name = buf;
+	name.len = snprintf(buf, sizeof(buf), "%d", task->pid);
+	dentry = d_hash_and_lookup(proc_mnt->mnt_root, &name);
+	if (dentry) {
+		shrink_dcache_parent(dentry);
+		d_drop(dentry);
+		dput(dentry);
 	}
-	return proc_dentry;
-}
 
-/**
- * proc_pid_flush - recover memory used by stale /proc/@pid/x entries
- * @proc_dentry: directoy to prune.
- *
- * Shrink the /proc directory that was used by the just killed thread.
- */
-	
-void proc_pid_flush(struct dentry *proc_dentry)
-{
-	might_sleep();
-	if(proc_dentry != NULL) {
-		shrink_dcache_parent(proc_dentry);
-		dput(proc_dentry);
+	if (thread_group_leader(task))
+		goto out;
+
+	name.name = buf;
+	name.len = snprintf(buf, sizeof(buf), "%d", task->tgid);
+	leader = d_hash_and_lookup(proc_mnt->mnt_root, &name);
+	if (!leader)
+		goto out;
+
+	name.name = "task";
+	name.len = strlen(name.name);
+	dir = d_hash_and_lookup(leader, &name);
+	if (!dir)
+		goto out_put_leader;
+
+	name.name = buf;
+	name.len = snprintf(buf, sizeof(buf), "%d", task->pid);
+	dentry = d_hash_and_lookup(dir, &name);
+	if (dentry) {
+		shrink_dcache_parent(dentry);
+		d_drop(dentry);
+		dput(dentry);
 	}
+
+	dput(dir);
+out_put_leader:
+	dput(leader);
+out:
+	return;
 }
 
 /* SMP-safe */
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
+	struct dentry *result = ERR_PTR(-ENOENT);
 	struct task_struct *task;
 	struct inode *inode;
 	struct proc_inode *ei;
 	unsigned tgid;
-	int died;
 
 	if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) {
 		inode = new_inode(dir->i_sb);
@@ -2028,21 +2019,18 @@
 	if (tgid == ~0U)
 		goto out;
 
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	task = find_task_by_pid(tgid);
 	if (task)
 		get_task_struct(task);
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 	if (!task)
 		goto out;
 
 	inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
+	if (!inode)
+		goto out_put_task;
 
-
-	if (!inode) {
-		put_task_struct(task);
-		goto out;
-	}
 	inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
 	inode->i_op = &proc_tgid_base_inode_operations;
 	inode->i_fop = &proc_tgid_base_operations;
@@ -2053,45 +2041,40 @@
 	inode->i_nlink = 4;
 #endif
 
-	dentry->d_op = &pid_base_dentry_operations;
+	dentry->d_op = &pid_dentry_operations;
 
-	died = 0;
 	d_add(dentry, inode);
-	spin_lock(&task->proc_lock);
-	task->proc_dentry = dentry;
-	if (!pid_alive(task)) {
-		dentry = proc_pid_unhash(task);
-		died = 1;
-	}
-	spin_unlock(&task->proc_lock);
+	/* Close the race of the process dying before we return the dentry */
+	if (pid_revalidate(dentry, NULL))
+		result = NULL;
 
+out_put_task:
 	put_task_struct(task);
-	if (died) {
-		proc_pid_flush(dentry);
-		goto out;
-	}
-	return NULL;
 out:
-	return ERR_PTR(-ENOENT);
+	return result;
 }
 
 /* SMP-safe */
 static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
 {
+	struct dentry *result = ERR_PTR(-ENOENT);
 	struct task_struct *task;
-	struct task_struct *leader = proc_task(dir);
+	struct task_struct *leader = get_proc_task(dir);
 	struct inode *inode;
 	unsigned tid;
 
+	if (!leader)
+		goto out_no_task;
+
 	tid = name_to_int(dentry);
 	if (tid == ~0U)
 		goto out;
 
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	task = find_task_by_pid(tid);
 	if (task)
 		get_task_struct(task);
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 	if (!task)
 		goto out;
 	if (leader->tgid != task->tgid)
@@ -2112,101 +2095,95 @@
 	inode->i_nlink = 3;
 #endif
 
-	dentry->d_op = &pid_base_dentry_operations;
+	dentry->d_op = &pid_dentry_operations;
 
 	d_add(dentry, inode);
+	/* Close the race of the process dying before we return the dentry */
+	if (pid_revalidate(dentry, NULL))
+		result = NULL;
 
-	put_task_struct(task);
-	return NULL;
 out_drop_task:
 	put_task_struct(task);
 out:
-	return ERR_PTR(-ENOENT);
-}
-
-#define PROC_NUMBUF 10
-#define PROC_MAXPIDS 20
-
-/*
- * Get a few tgid's to return for filldir - we need to hold the
- * tasklist lock while doing this, and we must release it before
- * we actually do the filldir itself, so we use a temp buffer..
- */
-static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
-{
-	struct task_struct *p;
-	int nr_tgids = 0;
-
-	index--;
-	read_lock(&tasklist_lock);
-	p = NULL;
-	if (version) {
-		p = find_task_by_pid(version);
-		if (p && !thread_group_leader(p))
-			p = NULL;
-	}
-
-	if (p)
-		index = 0;
-	else
-		p = next_task(&init_task);
-
-	for ( ; p != &init_task; p = next_task(p)) {
-		int tgid = p->pid;
-		if (!pid_alive(p))
-			continue;
-		if (--index >= 0)
-			continue;
-		tgids[nr_tgids] = tgid;
-		nr_tgids++;
-		if (nr_tgids >= PROC_MAXPIDS)
-			break;
-	}
-	read_unlock(&tasklist_lock);
-	return nr_tgids;
+	put_task_struct(leader);
+out_no_task:
+	return result;
 }
 
 /*
- * Get a few tid's to return for filldir - we need to hold the
- * tasklist lock while doing this, and we must release it before
- * we actually do the filldir itself, so we use a temp buffer..
+ * Find the first tgid to return to user space.
+ *
+ * Usually this is just whatever follows &init_task, but if the users
+ * buffer was too small to hold the full list or there was a seek into
+ * the middle of the directory we have more work to do.
+ *
+ * In the case of a short read we start with find_task_by_pid.
+ *
+ * In the case of a seek we start with &init_task and walk nr
+ * threads past it.
  */
-static int get_tid_list(int index, unsigned int *tids, struct inode *dir)
+static struct task_struct *first_tgid(int tgid, unsigned int nr)
 {
-	struct task_struct *leader_task = proc_task(dir);
-	struct task_struct *task = leader_task;
-	int nr_tids = 0;
+	struct task_struct *pos;
+	rcu_read_lock();
+	if (tgid && nr) {
+		pos = find_task_by_pid(tgid);
+		if (pos && thread_group_leader(pos))
+			goto found;
+	}
+	/* If nr exceeds the number of processes get out quickly */
+	pos = NULL;
+	if (nr && nr >= nr_processes())
+		goto done;
 
-	index -= 2;
-	read_lock(&tasklist_lock);
-	/*
-	 * The starting point task (leader_task) might be an already
-	 * unlinked task, which cannot be used to access the task-list
-	 * via next_thread().
+	/* If we haven't found our starting place yet start with
+	 * the init_task and walk nr tasks forward.
 	 */
-	if (pid_alive(task)) do {
-		int tid = task->pid;
+	for (pos = next_task(&init_task); nr > 0; --nr) {
+		pos = next_task(pos);
+		if (pos == &init_task) {
+			pos = NULL;
+			goto done;
+		}
+	}
+found:
+	get_task_struct(pos);
+done:
+	rcu_read_unlock();
+	return pos;
+}
 
-		if (--index >= 0)
-			continue;
-		if (tids != NULL)
-			tids[nr_tids] = tid;
-		nr_tids++;
-		if (nr_tids >= PROC_MAXPIDS)
-			break;
-	} while ((task = next_thread(task)) != leader_task);
-	read_unlock(&tasklist_lock);
-	return nr_tids;
+/*
+ * Find the next task in the task list.
+ * Return NULL if we loop or there is any error.
+ *
+ * The reference to the input task_struct is released.
+ */
+static struct task_struct *next_tgid(struct task_struct *start)
+{
+	struct task_struct *pos;
+	rcu_read_lock();
+	pos = start;
+	if (pid_alive(start))
+		pos = next_task(start);
+	if (pid_alive(pos) && (pos != &init_task)) {
+		get_task_struct(pos);
+		goto done;
+	}
+	pos = NULL;
+done:
+	rcu_read_unlock();
+	put_task_struct(start);
+	return pos;
 }
 
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-	unsigned int tgid_array[PROC_MAXPIDS];
 	char buf[PROC_NUMBUF];
 	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
-	unsigned int nr_tgids, i;
-	int next_tgid;
+	struct task_struct *task;
+	int tgid;
 
 	if (!nr) {
 		ino_t ino = fake_ino(0,PROC_TGID_INO);
@@ -2215,63 +2192,116 @@
 		filp->f_pos++;
 		nr++;
 	}
+	nr -= 1;
 
 	/* f_version caches the tgid value that the last readdir call couldn't
 	 * return. lseek aka telldir automagically resets f_version to 0.
 	 */
-	next_tgid = filp->f_version;
+	tgid = filp->f_version;
 	filp->f_version = 0;
-	for (;;) {
-		nr_tgids = get_tgid_list(nr, next_tgid, tgid_array);
-		if (!nr_tgids) {
-			/* no more entries ! */
+	for (task = first_tgid(tgid, nr);
+	     task;
+	     task = next_tgid(task), filp->f_pos++) {
+		int len;
+		ino_t ino;
+		tgid = task->pid;
+		len = snprintf(buf, sizeof(buf), "%d", tgid);
+		ino = fake_ino(tgid, PROC_TGID_INO);
+		if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) {
+			/* returning this tgid failed, save it as the first
+			 * pid for the next readir call */
+			filp->f_version = tgid;
+			put_task_struct(task);
 			break;
 		}
-		next_tgid = 0;
+	}
+	return 0;
+}
 
-		/* do not use the last found pid, reserve it for next_tgid */
-		if (nr_tgids == PROC_MAXPIDS) {
-			nr_tgids--;
-			next_tgid = tgid_array[nr_tgids];
-		}
+/*
+ * Find the first tid of a thread group to return to user space.
+ *
+ * Usually this is just the thread group leader, but if the users
+ * buffer was too small or there was a seek into the middle of the
+ * directory we have more work todo.
+ *
+ * In the case of a short read we start with find_task_by_pid.
+ *
+ * In the case of a seek we start with the leader and walk nr
+ * threads past it.
+ */
+static struct task_struct *first_tid(struct task_struct *leader,
+					int tid, int nr)
+{
+	struct task_struct *pos;
 
-		for (i=0;i<nr_tgids;i++) {
-			int tgid = tgid_array[i];
-			ino_t ino = fake_ino(tgid,PROC_TGID_INO);
-			unsigned long j = PROC_NUMBUF;
+	rcu_read_lock();
+	/* Attempt to start with the pid of a thread */
+	if (tid && (nr > 0)) {
+		pos = find_task_by_pid(tid);
+		if (pos && (pos->group_leader == leader))
+			goto found;
+	}
 
-			do
-				buf[--j] = '0' + (tgid % 10);
-			while ((tgid /= 10) != 0);
+	/* If nr exceeds the number of threads there is nothing todo */
+	pos = NULL;
+	if (nr && nr >= get_nr_threads(leader))
+		goto out;
 
-			if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino, DT_DIR) < 0) {
-				/* returning this tgid failed, save it as the first
-				 * pid for the next readir call */
-				filp->f_version = tgid_array[i];
-				goto out;
-			}
-			filp->f_pos++;
-			nr++;
+	/* If we haven't found our starting place yet start
+	 * with the leader and walk nr threads forward.
+	 */
+	for (pos = leader; nr > 0; --nr) {
+		pos = next_thread(pos);
+		if (pos == leader) {
+			pos = NULL;
+			goto out;
 		}
 	}
+found:
+	get_task_struct(pos);
 out:
-	return 0;
+	rcu_read_unlock();
+	return pos;
+}
+
+/*
+ * Find the next thread in the thread list.
+ * Return NULL if there is an error or no next thread.
+ *
+ * The reference to the input task_struct is released.
+ */
+static struct task_struct *next_tid(struct task_struct *start)
+{
+	struct task_struct *pos = NULL;
+	rcu_read_lock();
+	if (pid_alive(start)) {
+		pos = next_thread(start);
+		if (thread_group_leader(pos))
+			pos = NULL;
+		else
+			get_task_struct(pos);
+	}
+	rcu_read_unlock();
+	put_task_struct(start);
+	return pos;
 }
 
 /* for the /proc/TGID/task/ directories */
 static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-	unsigned int tid_array[PROC_MAXPIDS];
 	char buf[PROC_NUMBUF];
-	unsigned int nr_tids, i;
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *inode = dentry->d_inode;
+	struct task_struct *leader = get_proc_task(inode);
+	struct task_struct *task;
 	int retval = -ENOENT;
 	ino_t ino;
+	int tid;
 	unsigned long pos = filp->f_pos;  /* avoiding "long long" filp->f_pos */
 
-	if (!pid_alive(proc_task(inode)))
-		goto out;
+	if (!leader)
+		goto out_no_task;
 	retval = 0;
 
 	switch (pos) {
@@ -2289,24 +2319,45 @@
 		/* fall through */
 	}
 
-	nr_tids = get_tid_list(pos, tid_array, inode);
-	inode->i_nlink = pos + nr_tids;
-
-	for (i = 0; i < nr_tids; i++) {
-		unsigned long j = PROC_NUMBUF;
-		int tid = tid_array[i];
-
-		ino = fake_ino(tid,PROC_TID_INO);
-
-		do
-			buf[--j] = '0' + (tid % 10);
-		while ((tid /= 10) != 0);
-
-		if (filldir(dirent, buf+j, PROC_NUMBUF-j, pos, ino, DT_DIR) < 0)
+	/* f_version caches the tgid value that the last readdir call couldn't
+	 * return. lseek aka telldir automagically resets f_version to 0.
+	 */
+	tid = filp->f_version;
+	filp->f_version = 0;
+	for (task = first_tid(leader, tid, pos - 2);
+	     task;
+	     task = next_tid(task), pos++) {
+		int len;
+		tid = task->pid;
+		len = snprintf(buf, sizeof(buf), "%d", tid);
+		ino = fake_ino(tid, PROC_TID_INO);
+		if (filldir(dirent, buf, len, pos, ino, DT_DIR < 0)) {
+			/* returning this tgid failed, save it as the first
+			 * pid for the next readir call */
+			filp->f_version = tid;
+			put_task_struct(task);
 			break;
-		pos++;
+		}
 	}
 out:
 	filp->f_pos = pos;
+	put_task_struct(leader);
+out_no_task:
 	return retval;
 }
+
+static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+	struct inode *inode = dentry->d_inode;
+	struct task_struct *p = get_proc_task(inode);
+	generic_fillattr(inode, stat);
+
+	if (p) {
+		rcu_read_lock();
+		stat->nlink += get_nr_threads(p);
+		rcu_read_unlock();
+		put_task_struct(p);
+	}
+
+	return 0;
+}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 722b9c4..6dcef08 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -58,14 +58,11 @@
 static void proc_delete_inode(struct inode *inode)
 {
 	struct proc_dir_entry *de;
-	struct task_struct *tsk;
 
 	truncate_inode_pages(&inode->i_data, 0);
 
-	/* Let go of any associated process */
-	tsk = PROC_I(inode)->task;
-	if (tsk)
-		put_task_struct(tsk);
+	/* Stop tracking associated processes */
+	put_pid(PROC_I(inode)->pid);
 
 	/* Let go of any associated proc directory entry */
 	de = PROC_I(inode)->pde;
@@ -94,8 +91,8 @@
 	ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, SLAB_KERNEL);
 	if (!ei)
 		return NULL;
-	ei->task = NULL;
-	ei->type = 0;
+	ei->pid = NULL;
+	ei->fd = 0;
 	ei->op.proc_get_link = NULL;
 	ei->pde = NULL;
 	inode = &ei->vfs_inode;
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 0502f17..146a434 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -37,16 +37,30 @@
 extern int proc_pid_status(struct task_struct *, char *);
 extern int proc_pid_statm(struct task_struct *, char *);
 
+extern struct file_operations proc_maps_operations;
+extern struct file_operations proc_numa_maps_operations;
+extern struct file_operations proc_smaps_operations;
+
+extern struct file_operations proc_maps_operations;
+extern struct file_operations proc_numa_maps_operations;
+extern struct file_operations proc_smaps_operations;
+
+
 void free_proc_entry(struct proc_dir_entry *de);
 
 int proc_init_inodecache(void);
 
-static inline struct task_struct *proc_task(struct inode *inode)
+static inline struct pid *proc_pid(struct inode *inode)
 {
-	return PROC_I(inode)->task;
+	return PROC_I(inode)->pid;
 }
 
-static inline int proc_type(struct inode *inode)
+static inline struct task_struct *get_proc_task(struct inode *inode)
 {
-	return PROC_I(inode)->type;
+	return get_pid_task(proc_pid(inode), PIDTYPE_PID);
+}
+
+static inline int proc_fd(struct inode *inode)
+{
+	return PROC_I(inode)->fd;
 }
diff --git a/fs/proc/root.c b/fs/proc/root.c
index c3fd361..9995356 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -26,10 +26,10 @@
 struct proc_dir_entry *proc_sys_root;
 #endif
 
-static struct super_block *proc_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int proc_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, proc_fill_super);
+	return get_sb_single(fs_type, flags, data, proc_fill_super, mnt);
 }
 
 static struct file_system_type proc_fs_type = {
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 91b7c15..0a163a4 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -75,9 +75,13 @@
 {
 	struct vm_area_struct * vma;
 	int result = -ENOENT;
-	struct task_struct *task = proc_task(inode);
-	struct mm_struct * mm = get_task_mm(task);
+	struct task_struct *task = get_proc_task(inode);
+	struct mm_struct * mm = NULL;
 
+	if (task) {
+		mm = get_task_mm(task);
+		put_task_struct(task);
+	}
 	if (!mm)
 		goto out;
 	down_read(&mm->mmap_sem);
@@ -118,9 +122,15 @@
 	unsigned long private_dirty;
 };
 
+__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	return NULL;
+}
+
 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
 {
-	struct task_struct *task = m->private;
+	struct proc_maps_private *priv = m->private;
+	struct task_struct *task = priv->task;
 	struct vm_area_struct *vma = v;
 	struct mm_struct *mm = vma->vm_mm;
 	struct file *file = vma->vm_file;
@@ -153,22 +163,23 @@
 		pad_len_spaces(m, len);
 		seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
 	} else {
-		if (mm) {
-			if (vma->vm_start <= mm->start_brk &&
+		const char *name = arch_vma_name(vma);
+		if (!name) {
+			if (mm) {
+				if (vma->vm_start <= mm->start_brk &&
 						vma->vm_end >= mm->brk) {
-				pad_len_spaces(m, len);
-				seq_puts(m, "[heap]");
-			} else {
-				if (vma->vm_start <= mm->start_stack &&
-					vma->vm_end >= mm->start_stack) {
-
-					pad_len_spaces(m, len);
-					seq_puts(m, "[stack]");
+					name = "[heap]";
+				} else if (vma->vm_start <= mm->start_stack &&
+					   vma->vm_end >= mm->start_stack) {
+					name = "[stack]";
 				}
+			} else {
+				name = "[vdso]";
 			}
-		} else {
+		}
+		if (name) {
 			pad_len_spaces(m, len);
-			seq_puts(m, "[vdso]");
+			seq_puts(m, name);
 		}
 	}
 	seq_putc(m, '\n');
@@ -295,12 +306,16 @@
 
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
-	struct task_struct *task = m->private;
+	struct proc_maps_private *priv = m->private;
 	unsigned long last_addr = m->version;
 	struct mm_struct *mm;
-	struct vm_area_struct *vma, *tail_vma;
+	struct vm_area_struct *vma, *tail_vma = NULL;
 	loff_t l = *pos;
 
+	/* Clear the per syscall fields in priv */
+	priv->task = NULL;
+	priv->tail_vma = NULL;
+
 	/*
 	 * We remember last_addr rather than next_addr to hit with
 	 * mmap_cache most of the time. We have zero last_addr at
@@ -311,11 +326,15 @@
 	if (last_addr == -1UL)
 		return NULL;
 
-	mm = get_task_mm(task);
+	priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
+	if (!priv->task)
+		return NULL;
+
+	mm = get_task_mm(priv->task);
 	if (!mm)
 		return NULL;
 
-	tail_vma = get_gate_vma(task);
+	priv->tail_vma = tail_vma = get_gate_vma(priv->task);
 	down_read(&mm->mmap_sem);
 
 	/* Start with last addr hint */
@@ -350,11 +369,9 @@
 	return tail_vma;
 }
 
-static void m_stop(struct seq_file *m, void *v)
+static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
 {
-	struct task_struct *task = m->private;
-	struct vm_area_struct *vma = v;
-	if (vma && vma != get_gate_vma(task)) {
+	if (vma && vma != priv->tail_vma) {
 		struct mm_struct *mm = vma->vm_mm;
 		up_read(&mm->mmap_sem);
 		mmput(mm);
@@ -363,38 +380,103 @@
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
-	struct task_struct *task = m->private;
+	struct proc_maps_private *priv = m->private;
 	struct vm_area_struct *vma = v;
-	struct vm_area_struct *tail_vma = get_gate_vma(task);
+	struct vm_area_struct *tail_vma = priv->tail_vma;
 
 	(*pos)++;
 	if (vma && (vma != tail_vma) && vma->vm_next)
 		return vma->vm_next;
-	m_stop(m, v);
+	vma_stop(priv, vma);
 	return (vma != tail_vma)? tail_vma: NULL;
 }
 
-struct seq_operations proc_pid_maps_op = {
+static void m_stop(struct seq_file *m, void *v)
+{
+	struct proc_maps_private *priv = m->private;
+	struct vm_area_struct *vma = v;
+
+	vma_stop(priv, vma);
+	if (priv->task)
+		put_task_struct(priv->task);
+}
+
+static struct seq_operations proc_pid_maps_op = {
 	.start	= m_start,
 	.next	= m_next,
 	.stop	= m_stop,
 	.show	= show_map
 };
 
-struct seq_operations proc_pid_smaps_op = {
+static struct seq_operations proc_pid_smaps_op = {
 	.start	= m_start,
 	.next	= m_next,
 	.stop	= m_stop,
 	.show	= show_smap
 };
 
+static int do_maps_open(struct inode *inode, struct file *file,
+			struct seq_operations *ops)
+{
+	struct proc_maps_private *priv;
+	int ret = -ENOMEM;
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (priv) {
+		priv->pid = proc_pid(inode);
+		ret = seq_open(file, ops);
+		if (!ret) {
+			struct seq_file *m = file->private_data;
+			m->private = priv;
+		} else {
+			kfree(priv);
+		}
+	}
+	return ret;
+}
+
+static int maps_open(struct inode *inode, struct file *file)
+{
+	return do_maps_open(inode, file, &proc_pid_maps_op);
+}
+
+struct file_operations proc_maps_operations = {
+	.open		= maps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
+
 #ifdef CONFIG_NUMA
 extern int show_numa_map(struct seq_file *m, void *v);
 
-struct seq_operations proc_pid_numa_maps_op = {
+static struct seq_operations proc_pid_numa_maps_op = {
         .start  = m_start,
         .next   = m_next,
         .stop   = m_stop,
         .show   = show_numa_map
 };
+
+static int numa_maps_open(struct inode *inode, struct file *file)
+{
+	return do_maps_open(inode, file, &proc_pid_numa_maps_op);
+}
+
+struct file_operations proc_numa_maps_operations = {
+	.open		= numa_maps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
 #endif
+
+static int smaps_open(struct inode *inode, struct file *file)
+{
+	return do_maps_open(inode, file, &proc_pid_smaps_op);
+}
+
+struct file_operations proc_smaps_operations = {
+	.open		= smaps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release_private,
+};
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 8f68827..af69f28 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -156,9 +156,28 @@
 {
 	return NULL;
 }
-struct seq_operations proc_pid_maps_op = {
+static struct seq_operations proc_pid_maps_op = {
 	.start	= m_start,
 	.next	= m_next,
 	.stop	= m_stop,
 	.show	= show_map
 };
+
+static int maps_open(struct inode *inode, struct file *file)
+{
+	int ret;
+	ret = seq_open(file, &proc_pid_maps_op);
+	if (!ret) {
+		struct seq_file *m = file->private_data;
+		m->private = NULL;
+	}
+	return ret;
+}
+
+struct file_operations proc_maps_operations = {
+	.open		= maps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 2ecd46f..8bc182a 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -128,7 +128,7 @@
 static void qnx4_destroy_inode(struct inode *inode);
 static void qnx4_read_inode(struct inode *);
 static int qnx4_remount(struct super_block *sb, int *flags, char *data);
-static int qnx4_statfs(struct super_block *, struct kstatfs *);
+static int qnx4_statfs(struct dentry *, struct kstatfs *);
 
 static struct super_operations qnx4_sops =
 {
@@ -282,8 +282,10 @@
 	return block;
 }
 
-static int qnx4_statfs(struct super_block *sb, struct kstatfs *buf)
+static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
+
 	lock_kernel();
 
 	buf->f_type    = sb->s_magic;
@@ -448,7 +450,7 @@
 {
 	return generic_block_bmap(mapping,block,qnx4_get_block);
 }
-static struct address_space_operations qnx4_aops = {
+static const struct address_space_operations qnx4_aops = {
 	.readpage	= qnx4_readpage,
 	.writepage	= qnx4_writepage,
 	.sync_page	= block_sync_page,
@@ -561,10 +563,11 @@
 		       "qnx4_inode_cache: not all structures were freed\n");
 }
 
-static struct super_block *qnx4_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int qnx4_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super,
+			   mnt);
 }
 
 static struct file_system_type qnx4_fs_type = {
diff --git a/fs/ramfs/file-mmu.c b/fs/ramfs/file-mmu.c
index 00a933e..86f14ca 100644
--- a/fs/ramfs/file-mmu.c
+++ b/fs/ramfs/file-mmu.c
@@ -26,7 +26,7 @@
 
 #include <linux/fs.h>
 
-struct address_space_operations ramfs_aops = {
+const struct address_space_operations ramfs_aops = {
 	.readpage	= simple_readpage,
 	.prepare_write	= simple_prepare_write,
 	.commit_write	= simple_commit_write
diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
index f443a84..99fffc9 100644
--- a/fs/ramfs/file-nommu.c
+++ b/fs/ramfs/file-nommu.c
@@ -27,7 +27,7 @@
 
 static int ramfs_nommu_setattr(struct dentry *, struct iattr *);
 
-struct address_space_operations ramfs_aops = {
+const struct address_space_operations ramfs_aops = {
 	.readpage		= simple_readpage,
 	.prepare_write		= simple_prepare_write,
 	.commit_write		= simple_commit_write
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 14bd224..b967733 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -185,16 +185,17 @@
 	return 0;
 }
 
-struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+int ramfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super);
+	return get_sb_nodev(fs_type, flags, data, ramfs_fill_super, mnt);
 }
 
-static struct super_block *rootfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int rootfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super);
+	return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,
+			    mnt);
 }
 
 static struct file_system_type ramfs_fs_type = {
diff --git a/fs/ramfs/internal.h b/fs/ramfs/internal.h
index 3132376..c2bb58e 100644
--- a/fs/ramfs/internal.h
+++ b/fs/ramfs/internal.h
@@ -10,6 +10,6 @@
  */
 
 
-extern struct address_space_operations ramfs_aops;
+extern const struct address_space_operations ramfs_aops;
 extern const struct file_operations ramfs_file_operations;
 extern struct inode_operations ramfs_file_inode_operations;
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index cf6e1cf..752cea1 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -1560,12 +1560,6 @@
 	return res;
 }
 
-static ssize_t reiserfs_aio_write(struct kiocb *iocb, const char __user * buf,
-				  size_t count, loff_t pos)
-{
-	return generic_file_aio_write(iocb, buf, count, pos);
-}
-
 const struct file_operations reiserfs_file_operations = {
 	.read = generic_file_read,
 	.write = reiserfs_file_write,
@@ -1575,7 +1569,7 @@
 	.fsync = reiserfs_sync_file,
 	.sendfile = generic_file_sendfile,
 	.aio_read = generic_file_aio_read,
-	.aio_write = reiserfs_aio_write,
+	.aio_write = generic_file_aio_write,
 	.splice_read = generic_file_splice_read,
 	.splice_write = generic_file_splice_write,
 };
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 9857e50..a24858a 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -2996,7 +2996,7 @@
 	return error;
 }
 
-struct address_space_operations reiserfs_address_space_operations = {
+const struct address_space_operations reiserfs_address_space_operations = {
 	.writepage = reiserfs_writepage,
 	.readpage = reiserfs_readpage,
 	.readpages = reiserfs_readpages,
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 1b73529..49d1a53 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -834,8 +834,7 @@
 		get_bh(bh);
 		if (test_set_buffer_locked(bh)) {
 			if (!buffer_dirty(bh)) {
-				list_del_init(&jh->list);
-				list_add(&jh->list, &tmp);
+				list_move(&jh->list, &tmp);
 				goto loop_next;
 			}
 			spin_unlock(lock);
@@ -855,8 +854,7 @@
 			ret = -EIO;
 		}
 		if (buffer_dirty(bh)) {
-			list_del_init(&jh->list);
-			list_add(&jh->list, &tmp);
+			list_move(&jh->list, &tmp);
 			add_to_chunk(&chunk, bh, lock, write_ordered_chunk);
 		} else {
 			reiserfs_free_jh(bh);
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index cae2abb..00f1321 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -60,7 +60,7 @@
 }
 
 static int reiserfs_remount(struct super_block *s, int *flags, char *data);
-static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf);
+static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf);
 
 static int reiserfs_sync_fs(struct super_block *s, int wait)
 {
@@ -1938,15 +1938,15 @@
 	return errval;
 }
 
-static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf)
+static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
+	struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(dentry->d_sb);
 
 	buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize));
 	buf->f_bfree = sb_free_blocks(rs);
 	buf->f_bavail = buf->f_bfree;
 	buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1;
-	buf->f_bsize = s->s_blocksize;
+	buf->f_bsize = dentry->d_sb->s_blocksize;
 	/* changed to accommodate gcc folks. */
 	buf->f_type = REISERFS_SUPER_MAGIC;
 	return 0;
@@ -2249,11 +2249,12 @@
 
 #endif
 
-static struct super_block *get_super_block(struct file_system_type *fs_type,
-					   int flags, const char *dev_name,
-					   void *data)
+static int get_super_block(struct file_system_type *fs_type,
+			   int flags, const char *dev_name,
+			   void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super,
+			   mnt);
 }
 
 static int __init init_reiserfs_fs(void)
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index ffb79c4..39fedaa 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -452,8 +452,7 @@
 	/* We can deadlock if we try to free dentries,
 	   and an unlink/rmdir has just occured - GFP_NOFS avoids this */
 	mapping_set_gfp_mask(mapping, GFP_NOFS);
-	page = read_cache_page(mapping, n,
-			       (filler_t *) mapping->a_ops->readpage, NULL);
+	page = read_mapping_page(mapping, n, NULL);
 	if (!IS_ERR(page)) {
 		wait_on_page_locked(page);
 		kmap(page);
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 9b9eda7..22eed61 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -179,12 +179,12 @@
 /* That's simple too. */
 
 static int
-romfs_statfs(struct super_block *sb, struct kstatfs *buf)
+romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	buf->f_type = ROMFS_MAGIC;
 	buf->f_bsize = ROMBSIZE;
 	buf->f_bfree = buf->f_bavail = buf->f_ffree;
-	buf->f_blocks = (romfs_maxsize(sb)+ROMBSIZE-1)>>ROMBSBITS;
+	buf->f_blocks = (romfs_maxsize(dentry->d_sb)+ROMBSIZE-1)>>ROMBSBITS;
 	buf->f_namelen = ROMFS_MAXFN;
 	return 0;
 }
@@ -459,7 +459,7 @@
 
 /* Mapping from our types to the kernel */
 
-static struct address_space_operations romfs_aops = {
+static const struct address_space_operations romfs_aops = {
 	.readpage = romfs_readpage
 };
 
@@ -607,10 +607,11 @@
 	.remount_fs	= romfs_remount,
 };
 
-static struct super_block *romfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int romfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super,
+			   mnt);
 }
 
 static struct file_system_type romfs_fs_type = {
diff --git a/fs/select.c b/fs/select.c
index a8109ba..33b72ba 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -546,37 +546,38 @@
 
 #define POLLFD_PER_PAGE  ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd))
 
-static void do_pollfd(unsigned int num, struct pollfd * fdpage,
-	poll_table ** pwait, int *count)
+/*
+ * Fish for pollable events on the pollfd->fd file descriptor. We're only
+ * interested in events matching the pollfd->events mask, and the result
+ * matching that mask is both recorded in pollfd->revents and returned. The
+ * pwait poll_table will be used by the fd-provided poll handler for waiting,
+ * if non-NULL.
+ */
+static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait)
 {
-	int i;
+	unsigned int mask;
+	int fd;
 
-	for (i = 0; i < num; i++) {
-		int fd;
-		unsigned int mask;
-		struct pollfd *fdp;
+	mask = 0;
+	fd = pollfd->fd;
+	if (fd >= 0) {
+		int fput_needed;
+		struct file * file;
 
-		mask = 0;
-		fdp = fdpage+i;
-		fd = fdp->fd;
-		if (fd >= 0) {
-			int fput_needed;
-			struct file * file = fget_light(fd, &fput_needed);
-			mask = POLLNVAL;
-			if (file != NULL) {
-				mask = DEFAULT_POLLMASK;
-				if (file->f_op && file->f_op->poll)
-					mask = file->f_op->poll(file, *pwait);
-				mask &= fdp->events | POLLERR | POLLHUP;
-				fput_light(file, fput_needed);
-			}
-			if (mask) {
-				*pwait = NULL;
-				(*count)++;
-			}
+		file = fget_light(fd, &fput_needed);
+		mask = POLLNVAL;
+		if (file != NULL) {
+			mask = DEFAULT_POLLMASK;
+			if (file->f_op && file->f_op->poll)
+				mask = file->f_op->poll(file, pwait);
+			/* Mask out unneeded events. */
+			mask &= pollfd->events | POLLERR | POLLHUP;
+			fput_light(file, fput_needed);
 		}
-		fdp->revents = mask;
 	}
+	pollfd->revents = mask;
+
+	return mask;
 }
 
 static int do_poll(unsigned int nfds,  struct poll_list *list,
@@ -594,11 +595,29 @@
 		long __timeout;
 
 		set_current_state(TASK_INTERRUPTIBLE);
-		walk = list;
-		while(walk != NULL) {
-			do_pollfd( walk->len, walk->entries, &pt, &count);
-			walk = walk->next;
+		for (walk = list; walk != NULL; walk = walk->next) {
+			struct pollfd * pfd, * pfd_end;
+
+			pfd = walk->entries;
+			pfd_end = pfd + walk->len;
+			for (; pfd != pfd_end; pfd++) {
+				/*
+				 * Fish for events. If we found one, record it
+				 * and kill the poll_table, so we don't
+				 * needlessly register any other waiters after
+				 * this. They'll get immediately deregistered
+				 * when we break out and return.
+				 */
+				if (do_pollfd(pfd, pt)) {
+					count++;
+					pt = NULL;
+				}
+			}
 		}
+		/*
+		 * All waiters have already been registered, so don't provide
+		 * a poll_table to them on the next loop iteration.
+		 */
 		pt = NULL;
 		if (count || !*timeout || signal_pending(current))
 			break;
@@ -727,9 +746,9 @@
 asmlinkage long sys_poll(struct pollfd __user *ufds, unsigned int nfds,
 			long timeout_msecs)
 {
-	s64 timeout_jiffies = 0;
+	s64 timeout_jiffies;
 
-	if (timeout_msecs) {
+	if (timeout_msecs > 0) {
 #if HZ > 1000
 		/* We can only overflow if HZ > 1000 */
 		if (timeout_msecs / 1000 > (s64)0x7fffffffffffffffULL / (s64)HZ)
@@ -737,6 +756,9 @@
 		else
 #endif
 			timeout_jiffies = msecs_to_jiffies(timeout_msecs);
+	} else {
+		/* Infinite (< 0) or no (0) timeout */
+		timeout_jiffies = timeout_msecs;
 	}
 
 	return do_sys_poll(ufds, nfds, &timeout_jiffies);
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index ed9a24d..dae6704 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -306,7 +306,7 @@
 	return status;
 }
 
-struct address_space_operations smb_file_aops = {
+const struct address_space_operations smb_file_aops = {
 	.readpage = smb_readpage,
 	.writepage = smb_writepage,
 	.prepare_write = smb_prepare_write,
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
index fdeabc0..506ff87 100644
--- a/fs/smbfs/inode.c
+++ b/fs/smbfs/inode.c
@@ -48,7 +48,7 @@
 
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
-static int  smb_statfs(struct super_block *, struct kstatfs *);
+static int  smb_statfs(struct dentry *, struct kstatfs *);
 static int  smb_show_options(struct seq_file *, struct vfsmount *);
 
 static kmem_cache_t *smb_inode_cachep;
@@ -641,13 +641,13 @@
 }
 
 static int
-smb_statfs(struct super_block *sb, struct kstatfs *buf)
+smb_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
 	int result;
 	
 	lock_kernel();
 
-	result = smb_proc_dskattr(sb, buf);
+	result = smb_proc_dskattr(dentry, buf);
 
 	unlock_kernel();
 
@@ -782,10 +782,10 @@
 	return error;
 }
 
-static struct super_block *smb_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int smb_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, smb_fill_super);
+	return get_sb_nodev(fs_type, flags, data, smb_fill_super, mnt);
 }
 
 static struct file_system_type smb_fs_type = {
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c
index b1b878b..c349505 100644
--- a/fs/smbfs/proc.c
+++ b/fs/smbfs/proc.c
@@ -3226,9 +3226,9 @@
 }
 
 int
-smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr)
+smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr)
 {
-	struct smb_sb_info *server = SMB_SB(sb);
+	struct smb_sb_info *server = SMB_SB(dentry->d_sb);
 	int result;
 	char *p;
 	long unit;
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h
index 4766459..34fb462 100644
--- a/fs/smbfs/proto.h
+++ b/fs/smbfs/proto.h
@@ -29,7 +29,7 @@
 extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr);
 extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor);
 extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr);
-extern int smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr);
+extern int smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr);
 extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len);
 extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath);
 extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry);
@@ -63,7 +63,7 @@
 extern int smb_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
 extern int smb_notify_change(struct dentry *dentry, struct iattr *attr);
 /* file.c */
-extern struct address_space_operations smb_file_aops;
+extern const struct address_space_operations smb_file_aops;
 extern const struct file_operations smb_file_operations;
 extern struct inode_operations smb_file_inode_operations;
 /* ioctl.c */
diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
index c71dd27..c8e9619 100644
--- a/fs/smbfs/request.c
+++ b/fs/smbfs/request.c
@@ -400,8 +400,7 @@
 	if (!(req->rq_flags & SMB_REQ_TRANSMITTED))
 		goto out;
 
-	list_del_init(&req->rq_queue);
-	list_add_tail(&req->rq_queue, &server->recvq);
+	list_move_tail(&req->rq_queue, &server->recvq);
 	result = 1;
 out:
 	return result;
@@ -435,8 +434,7 @@
 	result = smb_request_send_req(req);
 	if (result < 0) {
 		server->conn_error = result;
-		list_del_init(&req->rq_queue);
-		list_add(&req->rq_queue, &server->xmitq);
+		list_move(&req->rq_queue, &server->xmitq);
 		result = -EIO;
 		goto out;
 	}
diff --git a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c
index 481a97a42..24577e2 100644
--- a/fs/smbfs/smbiod.c
+++ b/fs/smbfs/smbiod.c
@@ -20,6 +20,7 @@
 #include <linux/smp_lock.h>
 #include <linux/module.h>
 #include <linux/net.h>
+#include <linux/kthread.h>
 #include <net/ip.h>
 
 #include <linux/smb_fs.h>
@@ -40,7 +41,7 @@
 };
 
 static enum smbiod_state smbiod_state = SMBIOD_DEAD;
-static pid_t smbiod_pid;
+static struct task_struct *smbiod_thread;
 static DECLARE_WAIT_QUEUE_HEAD(smbiod_wait);
 static LIST_HEAD(smb_servers);
 static DEFINE_SPINLOCK(servers_lock);
@@ -67,20 +68,29 @@
  */
 static int smbiod_start(void)
 {
-	pid_t pid;
+	struct task_struct *tsk;
+	int err = 0;
+
 	if (smbiod_state != SMBIOD_DEAD)
 		return 0;
 	smbiod_state = SMBIOD_STARTING;
 	__module_get(THIS_MODULE);
 	spin_unlock(&servers_lock);
-	pid = kernel_thread(smbiod, NULL, 0);
-	if (pid < 0)
+	tsk = kthread_run(smbiod, NULL, "smbiod");
+	if (IS_ERR(tsk)) {
+		err = PTR_ERR(tsk);
 		module_put(THIS_MODULE);
+	}
 
 	spin_lock(&servers_lock);
-	smbiod_state = pid < 0 ? SMBIOD_DEAD : SMBIOD_RUNNING;
-	smbiod_pid = pid;
-	return pid;
+	if (err < 0) {
+		smbiod_state = SMBIOD_DEAD;
+		smbiod_thread = NULL;
+	} else {
+		smbiod_state = SMBIOD_RUNNING;
+		smbiod_thread = tsk;
+	}
+	return err;
 }
 
 /*
@@ -183,8 +193,7 @@
 		if (req->rq_flags & SMB_REQ_RETRY) {
 			/* must move the request to the xmitq */
 			VERBOSE("retrying request %p on recvq\n", req);
-			list_del(&req->rq_queue);
-			list_add(&req->rq_queue, &server->xmitq);
+			list_move(&req->rq_queue, &server->xmitq);
 			continue;
 		}
 #endif
@@ -290,8 +299,6 @@
  */
 static int smbiod(void *unused)
 {
-	daemonize("smbiod");
-
 	allow_signal(SIGKILL);
 
 	VERBOSE("SMB Kernel thread starting (%d) ...\n", current->pid);
diff --git a/fs/splice.c b/fs/splice.c
index a285fd7..05fd278 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -55,31 +55,43 @@
 				     struct pipe_buffer *buf)
 {
 	struct page *page = buf->page;
-	struct address_space *mapping = page_mapping(page);
+	struct address_space *mapping;
 
 	lock_page(page);
 
-	WARN_ON(!PageUptodate(page));
+	mapping = page_mapping(page);
+	if (mapping) {
+		WARN_ON(!PageUptodate(page));
 
-	/*
-	 * At least for ext2 with nobh option, we need to wait on writeback
-	 * completing on this page, since we'll remove it from the pagecache.
-	 * Otherwise truncate wont wait on the page, allowing the disk
-	 * blocks to be reused by someone else before we actually wrote our
-	 * data to them. fs corruption ensues.
-	 */
-	wait_on_page_writeback(page);
+		/*
+		 * At least for ext2 with nobh option, we need to wait on
+		 * writeback completing on this page, since we'll remove it
+		 * from the pagecache.  Otherwise truncate wont wait on the
+		 * page, allowing the disk blocks to be reused by someone else
+		 * before we actually wrote our data to them. fs corruption
+		 * ensues.
+		 */
+		wait_on_page_writeback(page);
 
-	if (PagePrivate(page))
-		try_to_release_page(page, mapping_gfp_mask(mapping));
+		if (PagePrivate(page))
+			try_to_release_page(page, mapping_gfp_mask(mapping));
 
-	if (!remove_mapping(mapping, page)) {
-		unlock_page(page);
-		return 1;
+		/*
+		 * If we succeeded in removing the mapping, set LRU flag
+		 * and return good.
+		 */
+		if (remove_mapping(mapping, page)) {
+			buf->flags |= PIPE_BUF_FLAG_LRU;
+			return 0;
+		}
 	}
 
-	buf->flags |= PIPE_BUF_FLAG_LRU;
-	return 0;
+	/*
+	 * Raced with truncate or failed to remove page from current
+	 * address space, unlock and return failure.
+	 */
+	unlock_page(page);
+	return 1;
 }
 
 static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe,
diff --git a/fs/super.c b/fs/super.c
index a66f66b..8a669f6 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -231,7 +231,7 @@
 	if (root) {
 		sb->s_root = NULL;
 		shrink_dcache_parent(root);
-		shrink_dcache_anon(&sb->s_anon);
+		shrink_dcache_sb(sb);
 		dput(root);
 		fsync_super(sb);
 		lock_super(sb);
@@ -486,7 +486,7 @@
         s = user_get_super(new_decode_dev(dev));
         if (s == NULL)
                 goto out;
-	err = vfs_statfs(s, &sbuf);
+	err = vfs_statfs(s->s_root, &sbuf);
 	drop_super(s);
 	if (err)
 		goto out;
@@ -676,9 +676,10 @@
 	}
 }
 
-struct super_block *get_sb_bdev(struct file_system_type *fs_type,
+int get_sb_bdev(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data,
-	int (*fill_super)(struct super_block *, void *, int))
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt)
 {
 	struct block_device *bdev;
 	struct super_block *s;
@@ -686,7 +687,7 @@
 
 	bdev = open_bdev_excl(dev_name, flags, fs_type);
 	if (IS_ERR(bdev))
-		return (struct super_block *)bdev;
+		return PTR_ERR(bdev);
 
 	/*
 	 * once the super is inserted into the list by sget, s_umount
@@ -697,15 +698,17 @@
 	s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
 	mutex_unlock(&bdev->bd_mount_mutex);
 	if (IS_ERR(s))
-		goto out;
+		goto error_s;
 
 	if (s->s_root) {
 		if ((flags ^ s->s_flags) & MS_RDONLY) {
 			up_write(&s->s_umount);
 			deactivate_super(s);
-			s = ERR_PTR(-EBUSY);
+			error = -EBUSY;
+			goto error_bdev;
 		}
-		goto out;
+
+		close_bdev_excl(bdev);
 	} else {
 		char b[BDEVNAME_SIZE];
 
@@ -716,18 +719,21 @@
 		if (error) {
 			up_write(&s->s_umount);
 			deactivate_super(s);
-			s = ERR_PTR(error);
-		} else {
-			s->s_flags |= MS_ACTIVE;
-			bdev_uevent(bdev, KOBJ_MOUNT);
+			goto error;
 		}
+
+		s->s_flags |= MS_ACTIVE;
+		bdev_uevent(bdev, KOBJ_MOUNT);
 	}
 
-	return s;
+	return simple_set_mnt(mnt, s);
 
-out:
+error_s:
+	error = PTR_ERR(s);
+error_bdev:
 	close_bdev_excl(bdev);
-	return s;
+error:
+	return error;
 }
 
 EXPORT_SYMBOL(get_sb_bdev);
@@ -744,15 +750,16 @@
 
 EXPORT_SYMBOL(kill_block_super);
 
-struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+int get_sb_nodev(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int))
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt)
 {
 	int error;
 	struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
 
 	if (IS_ERR(s))
-		return s;
+		return PTR_ERR(s);
 
 	s->s_flags = flags;
 
@@ -760,10 +767,10 @@
 	if (error) {
 		up_write(&s->s_umount);
 		deactivate_super(s);
-		return ERR_PTR(error);
+		return error;
 	}
 	s->s_flags |= MS_ACTIVE;
-	return s;
+	return simple_set_mnt(mnt, s);
 }
 
 EXPORT_SYMBOL(get_sb_nodev);
@@ -773,94 +780,100 @@
 	return 1;
 }
 
-struct super_block *get_sb_single(struct file_system_type *fs_type,
+int get_sb_single(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int))
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt)
 {
 	struct super_block *s;
 	int error;
 
 	s = sget(fs_type, compare_single, set_anon_super, NULL);
 	if (IS_ERR(s))
-		return s;
+		return PTR_ERR(s);
 	if (!s->s_root) {
 		s->s_flags = flags;
 		error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
 		if (error) {
 			up_write(&s->s_umount);
 			deactivate_super(s);
-			return ERR_PTR(error);
+			return error;
 		}
 		s->s_flags |= MS_ACTIVE;
 	}
 	do_remount_sb(s, flags, data, 0);
-	return s;
+	return simple_set_mnt(mnt, s);
 }
 
 EXPORT_SYMBOL(get_sb_single);
 
 struct vfsmount *
-do_kern_mount(const char *fstype, int flags, const char *name, void *data)
+vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
 {
-	struct file_system_type *type = get_fs_type(fstype);
-	struct super_block *sb = ERR_PTR(-ENOMEM);
 	struct vfsmount *mnt;
-	int error;
 	char *secdata = NULL;
+	int error;
 
 	if (!type)
 		return ERR_PTR(-ENODEV);
 
+	error = -ENOMEM;
 	mnt = alloc_vfsmnt(name);
 	if (!mnt)
 		goto out;
 
 	if (data) {
 		secdata = alloc_secdata();
-		if (!secdata) {
-			sb = ERR_PTR(-ENOMEM);
+		if (!secdata)
 			goto out_mnt;
-		}
 
 		error = security_sb_copy_data(type, data, secdata);
-		if (error) {
-			sb = ERR_PTR(error);
+		if (error)
 			goto out_free_secdata;
-		}
 	}
 
-	sb = type->get_sb(type, flags, name, data);
-	if (IS_ERR(sb))
+	error = type->get_sb(type, flags, name, data, mnt);
+	if (error < 0)
 		goto out_free_secdata;
- 	error = security_sb_kern_mount(sb, secdata);
+
+ 	error = security_sb_kern_mount(mnt->mnt_sb, secdata);
  	if (error)
  		goto out_sb;
-	mnt->mnt_sb = sb;
-	mnt->mnt_root = dget(sb->s_root);
-	mnt->mnt_mountpoint = sb->s_root;
+
+	mnt->mnt_mountpoint = mnt->mnt_root;
 	mnt->mnt_parent = mnt;
-	up_write(&sb->s_umount);
+	up_write(&mnt->mnt_sb->s_umount);
 	free_secdata(secdata);
-	put_filesystem(type);
 	return mnt;
 out_sb:
-	up_write(&sb->s_umount);
-	deactivate_super(sb);
-	sb = ERR_PTR(error);
+	dput(mnt->mnt_root);
+	up_write(&mnt->mnt_sb->s_umount);
+	deactivate_super(mnt->mnt_sb);
 out_free_secdata:
 	free_secdata(secdata);
 out_mnt:
 	free_vfsmnt(mnt);
 out:
-	put_filesystem(type);
-	return (struct vfsmount *)sb;
+	return ERR_PTR(error);
 }
 
-EXPORT_SYMBOL_GPL(do_kern_mount);
+EXPORT_SYMBOL_GPL(vfs_kern_mount);
+
+struct vfsmount *
+do_kern_mount(const char *fstype, int flags, const char *name, void *data)
+{
+	struct file_system_type *type = get_fs_type(fstype);
+	struct vfsmount *mnt;
+	if (!type)
+		return ERR_PTR(-ENODEV);
+	mnt = vfs_kern_mount(type, flags, name, data);
+	put_filesystem(type);
+	return mnt;
+}
 
 struct vfsmount *kern_mount(struct file_system_type *type)
 {
-	return do_kern_mount(type->name, 0, type->name, NULL);
+	return vfs_kern_mount(type, 0, type->name, NULL);
 }
 
 EXPORT_SYMBOL(kern_mount);
diff --git a/fs/sync.c b/fs/sync.c
index aab5ffe..955aef0 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -100,7 +100,7 @@
 	}
 
 	if (nbytes == 0)
-		endbyte = -1;
+		endbyte = LLONG_MAX;
 	else
 		endbyte--;		/* inclusive */
 
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 610b5bd..61c4243 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -430,10 +430,9 @@
 			i++;
 			/* fallthrough */
 		default:
-			if (filp->f_pos == 2) {
-				list_del(q);
-				list_add(q, &parent_sd->s_children);
-			}
+			if (filp->f_pos == 2)
+				list_move(q, &parent_sd->s_children);
+
 			for (p=q->next; p!= &parent_sd->s_children; p=p->next) {
 				struct sysfs_dirent *next;
 				const char * name;
@@ -455,8 +454,7 @@
 						 dt_type(next)) < 0)
 					return 0;
 
-				list_del(q);
-				list_add(q, p);
+				list_move(q, p);
 				p = q;
 				filp->f_pos++;
 			}
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index f0b347b..5e0e31c 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -16,7 +16,7 @@
 
 extern struct super_block * sysfs_sb;
 
-static struct address_space_operations sysfs_aops = {
+static const struct address_space_operations sysfs_aops = {
 	.readpage	= simple_readpage,
 	.prepare_write	= simple_prepare_write,
 	.commit_write	= simple_commit_write
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index f1117e8..40190c4 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -66,10 +66,10 @@
 	return 0;
 }
 
-static struct super_block *sysfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int sysfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, sysfs_fill_super);
+	return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);
 }
 
 static struct file_system_type sysfs_fs_type = {
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index d707434..f2bef96 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -53,8 +53,7 @@
 static struct page * dir_get_page(struct inode *dir, unsigned long n)
 {
 	struct address_space *mapping = dir->i_mapping;
-	struct page *page = read_cache_page(mapping, n,
-				(filler_t*)mapping->a_ops->readpage, NULL);
+	struct page *page = read_mapping_page(mapping, n, NULL);
 	if (!IS_ERR(page)) {
 		wait_on_page_locked(page);
 		kmap(page);
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 3ff89cc..58b2d22 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -85,8 +85,9 @@
 	kfree(sbi);
 }
 
-static int sysv_statfs(struct super_block *sb, struct kstatfs *buf)
+static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
 	struct sysv_sb_info *sbi = SYSV_SB(sb);
 
 	buf->f_type = sb->s_magic;
diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
index 86f5f8d..f2bcccd 100644
--- a/fs/sysv/itree.c
+++ b/fs/sysv/itree.c
@@ -465,7 +465,7 @@
 {
 	return generic_block_bmap(mapping,block,get_block);
 }
-struct address_space_operations sysv_aops = {
+const struct address_space_operations sysv_aops = {
 	.readpage = sysv_readpage,
 	.writepage = sysv_writepage,
 	.sync_page = block_sync_page,
diff --git a/fs/sysv/super.c b/fs/sysv/super.c
index e92b991..876639b 100644
--- a/fs/sysv/super.c
+++ b/fs/sysv/super.c
@@ -506,16 +506,17 @@
 
 /* Every kernel module contains stuff like this. */
 
-static struct super_block *sysv_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int sysv_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super,
+			   mnt);
 }
 
-static struct super_block *v7_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int v7_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super, mnt);
 }
 
 static struct file_system_type sysv_fs_type = {
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 393a480..9dcc821 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -161,7 +161,7 @@
 extern struct inode_operations sysv_fast_symlink_inode_operations;
 extern const struct file_operations sysv_file_operations;
 extern const struct file_operations sysv_dir_operations;
-extern struct address_space_operations sysv_aops;
+extern const struct address_space_operations sysv_aops;
 extern struct super_operations sysv_sops;
 extern struct dentry_operations sysv_dentry_operations;
 
diff --git a/fs/udf/file.c b/fs/udf/file.c
index e34b00e..a59e5f3 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -95,7 +95,7 @@
 	return 0;
 }
 
-struct address_space_operations udf_adinicb_aops = {
+const struct address_space_operations udf_adinicb_aops = {
 	.readpage		= udf_adinicb_readpage,
 	.writepage		= udf_adinicb_writepage,
 	.sync_page		= block_sync_page,
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 2983afd..605f511 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -132,7 +132,7 @@
 	return generic_block_bmap(mapping,block,udf_get_block);
 }
 
-struct address_space_operations udf_aops = {
+const struct address_space_operations udf_aops = {
 	.readpage		= udf_readpage,
 	.writepage		= udf_writepage,
 	.sync_page		= block_sync_page,
diff --git a/fs/udf/super.c b/fs/udf/super.c
index e45789f..44fe2cb 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -91,13 +91,13 @@
 static void udf_open_lvid(struct super_block *);
 static void udf_close_lvid(struct super_block *);
 static unsigned int udf_count_free(struct super_block *);
-static int udf_statfs(struct super_block *, struct kstatfs *);
+static int udf_statfs(struct dentry *, struct kstatfs *);
 
 /* UDF filesystem type */
-static struct super_block *udf_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int udf_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super, mnt);
 }
 
 static struct file_system_type udf_fstype = {
@@ -1779,8 +1779,10 @@
  *	Written, tested, and released.
  */
 static int
-udf_statfs(struct super_block *sb, struct kstatfs *buf)
+udf_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
+	struct super_block *sb = dentry->d_sb;
+
 	buf->f_type = UDF_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 674bb40..ba068a7 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -113,6 +113,6 @@
 /*
  * symlinks can't do much...
  */
-struct address_space_operations udf_symlink_aops = {
+const struct address_space_operations udf_symlink_aops = {
 	.readpage		= udf_symlink_filler,
 };
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 023e19b..2f99238 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -47,9 +47,9 @@
 extern const struct file_operations udf_dir_operations;
 extern struct inode_operations udf_file_inode_operations;
 extern const struct file_operations udf_file_operations;
-extern struct address_space_operations udf_aops;
-extern struct address_space_operations udf_adinicb_aops;
-extern struct address_space_operations udf_symlink_aops;
+extern const struct address_space_operations udf_aops;
+extern const struct address_space_operations udf_adinicb_aops;
+extern const struct address_space_operations udf_symlink_aops;
 
 struct udf_fileident_bh
 {
diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c
index 3ada9dc..95b878e 100644
--- a/fs/ufs/balloc.c
+++ b/fs/ufs/balloc.c
@@ -21,14 +21,6 @@
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_BALLOC_DEBUG
-
-#ifdef UFS_BALLOC_DEBUG
-#define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
 static unsigned ufs_add_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
 static unsigned ufs_alloc_fragments (struct inode *, unsigned, unsigned, unsigned, int *);
 static unsigned ufs_alloccg_block (struct inode *, struct ufs_cg_private_info *, unsigned, int *);
@@ -39,7 +31,8 @@
 /*
  * Free 'count' fragments from fragment number 'fragment'
  */
-void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count) {
+void ufs_free_fragments(struct inode *inode, unsigned fragment, unsigned count)
+{
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
@@ -51,7 +44,7 @@
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
 	
-	UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
+	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
 	
 	if (ufs_fragnum(fragment) + count > uspi->s_fpg)
 		ufs_error (sb, "ufs_free_fragments", "internal error");
@@ -68,7 +61,7 @@
 	ucpi = ufs_load_cylinder (sb, cgno);
 	if (!ucpi) 
 		goto failed;
-	ucg = ubh_get_ucg (UCPI_UBH);
+	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg)) {
 		ufs_panic (sb, "ufs_free_fragments", "internal error, bad magic number on cg %u", cgno);
 		goto failed;
@@ -76,11 +69,11 @@
 
 	end_bit = bit + count;
 	bbase = ufs_blknum (bit);
-	blkmap = ubh_blkmap (UCPI_UBH, ucpi->c_freeoff, bbase);
+	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
 	ufs_fragacct (sb, blkmap, ucg->cg_frsum, -1);
 	for (i = bit; i < end_bit; i++) {
-		if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, i))
-			ubh_setbit (UCPI_UBH, ucpi->c_freeoff, i);
+		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, i))
+			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, i);
 		else 
 			ufs_error (sb, "ufs_free_fragments",
 				   "bit already cleared for fragment %u", i);
@@ -90,51 +83,52 @@
 
 	
 	fs32_add(sb, &ucg->cg_cs.cs_nffree, count);
-	fs32_add(sb, &usb1->fs_cstotal.cs_nffree, count);
+	uspi->cs_total.cs_nffree += count;
 	fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
-	blkmap = ubh_blkmap (UCPI_UBH, ucpi->c_freeoff, bbase);
+	blkmap = ubh_blkmap (UCPI_UBH(ucpi), ucpi->c_freeoff, bbase);
 	ufs_fragacct(sb, blkmap, ucg->cg_frsum, 1);
 
 	/*
 	 * Trying to reassemble free fragments into block
 	 */
 	blkno = ufs_fragstoblks (bbase);
-	if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, blkno)) {
+	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
 		fs32_sub(sb, &ucg->cg_cs.cs_nffree, uspi->s_fpb);
-		fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, uspi->s_fpb);
+		uspi->cs_total.cs_nffree -= uspi->s_fpb;
 		fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, uspi->s_fpb);
 		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
 			ufs_clusteracct (sb, ucpi, blkno, 1);
 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
-		fs32_add(sb, &usb1->fs_cstotal.cs_nbfree, 1);
+		uspi->cs_total.cs_nbfree++;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
 		cylno = ufs_cbtocylno (bbase);
 		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(bbase)), 1);
 		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
 	}
 	
-	ubh_mark_buffer_dirty (USPI_UBH);
-	ubh_mark_buffer_dirty (UCPI_UBH);
+	ubh_mark_buffer_dirty (USPI_UBH(uspi));
+	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
-		ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
-		ubh_wait_on_buffer (UCPI_UBH);
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer (UCPI_UBH(ucpi));
 	}
 	sb->s_dirt = 1;
 	
 	unlock_super (sb);
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return;
 
 failed:
 	unlock_super (sb);
-	UFSD(("EXIT (FAILED)\n"))
+	UFSD("EXIT (FAILED)\n");
 	return;
 }
 
 /*
  * Free 'count' fragments from fragment number 'fragment' (free whole blocks)
  */
-void ufs_free_blocks (struct inode * inode, unsigned fragment, unsigned count) {
+void ufs_free_blocks(struct inode *inode, unsigned fragment, unsigned count)
+{
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
@@ -146,7 +140,7 @@
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
 
-	UFSD(("ENTER, fragment %u, count %u\n", fragment, count))
+	UFSD("ENTER, fragment %u, count %u\n", fragment, count);
 	
 	if ((fragment & uspi->s_fpbmask) || (count & uspi->s_fpbmask)) {
 		ufs_error (sb, "ufs_free_blocks", "internal error, "
@@ -162,7 +156,7 @@
 	bit = ufs_dtogd (fragment);
 	if (cgno >= uspi->s_ncg) {
 		ufs_panic (sb, "ufs_free_blocks", "freeing blocks are outside device");
-		goto failed;
+		goto failed_unlock;
 	}
 	end_bit = bit + count;
 	if (end_bit > uspi->s_fpg) {
@@ -173,36 +167,36 @@
 
 	ucpi = ufs_load_cylinder (sb, cgno);
 	if (!ucpi) 
-		goto failed;
-	ucg = ubh_get_ucg (UCPI_UBH);
+		goto failed_unlock;
+	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg)) {
 		ufs_panic (sb, "ufs_free_blocks", "internal error, bad magic number on cg %u", cgno);
-		goto failed;
+		goto failed_unlock;
 	}
 
 	for (i = bit; i < end_bit; i += uspi->s_fpb) {
 		blkno = ufs_fragstoblks(i);
-		if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, blkno)) {
+		if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno)) {
 			ufs_error(sb, "ufs_free_blocks", "freeing free fragment");
 		}
-		ubh_setblock(UCPI_UBH, ucpi->c_freeoff, blkno);
+		ubh_setblock(UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
 		if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
 			ufs_clusteracct (sb, ucpi, blkno, 1);
 		DQUOT_FREE_BLOCK(inode, uspi->s_fpb);
 
 		fs32_add(sb, &ucg->cg_cs.cs_nbfree, 1);
-		fs32_add(sb, &usb1->fs_cstotal.cs_nbfree, 1);
+		uspi->cs_total.cs_nbfree++;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nbfree, 1);
 		cylno = ufs_cbtocylno(i);
 		fs16_add(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(i)), 1);
 		fs32_add(sb, &ubh_cg_blktot(ucpi, cylno), 1);
 	}
 
-	ubh_mark_buffer_dirty (USPI_UBH);
-	ubh_mark_buffer_dirty (UCPI_UBH);
+	ubh_mark_buffer_dirty (USPI_UBH(uspi));
+	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
-		ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
-		ubh_wait_on_buffer (UCPI_UBH);
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer (UCPI_UBH(ucpi));
 	}
 
 	if (overflow) {
@@ -213,38 +207,127 @@
 
 	sb->s_dirt = 1;
 	unlock_super (sb);
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return;
 
-failed:
+failed_unlock:
 	unlock_super (sb);
-	UFSD(("EXIT (FAILED)\n"))
+failed:
+	UFSD("EXIT (FAILED)\n");
 	return;
 }
 
+static struct page *ufs_get_locked_page(struct address_space *mapping,
+				  unsigned long index)
+{
+	struct page *page;
 
+try_again:
+	page = find_lock_page(mapping, index);
+	if (!page) {
+		page = read_cache_page(mapping, index,
+				       (filler_t*)mapping->a_ops->readpage,
+				       NULL);
+		if (IS_ERR(page)) {
+			printk(KERN_ERR "ufs_change_blocknr: "
+			       "read_cache_page error: ino %lu, index: %lu\n",
+			       mapping->host->i_ino, index);
+			goto out;
+		}
 
-#define NULLIFY_FRAGMENTS \
-	for (i = oldcount; i < newcount; i++) { \
-		bh = sb_getblk(sb, result + i); \
-		memset (bh->b_data, 0, sb->s_blocksize); \
-		set_buffer_uptodate(bh); \
-		mark_buffer_dirty (bh); \
-		if (IS_SYNC(inode)) \
-			sync_dirty_buffer(bh); \
-		brelse (bh); \
+		lock_page(page);
+
+		if (!PageUptodate(page) || PageError(page)) {
+			unlock_page(page);
+			page_cache_release(page);
+
+			printk(KERN_ERR "ufs_change_blocknr: "
+			       "can not read page: ino %lu, index: %lu\n",
+			       mapping->host->i_ino, index);
+
+			page = ERR_PTR(-EIO);
+			goto out;
+		}
 	}
 
-unsigned ufs_new_fragments (struct inode * inode, __fs32 * p, unsigned fragment,
-	unsigned goal, unsigned count, int * err )
+	if (unlikely(!page->mapping || !page_has_buffers(page))) {
+		unlock_page(page);
+		page_cache_release(page);
+		goto try_again;/*we really need these buffers*/
+	}
+out:
+	return page;
+}
+
+/*
+ * Modify inode page cache in such way:
+ * have - blocks with b_blocknr equal to oldb...oldb+count-1
+ * get - blocks with b_blocknr equal to newb...newb+count-1
+ * also we suppose that oldb...oldb+count-1 blocks
+ * situated at the end of file.
+ *
+ * We can come here from ufs_writepage or ufs_prepare_write,
+ * locked_page is argument of these functions, so we already lock it.
+ */
+static void ufs_change_blocknr(struct inode *inode, unsigned int baseblk,
+			       unsigned int count, unsigned int oldb,
+			       unsigned int newb, struct page *locked_page)
+{
+	unsigned int blk_per_page = 1 << (PAGE_CACHE_SHIFT - inode->i_blkbits);
+	struct address_space *mapping = inode->i_mapping;
+	pgoff_t index, cur_index = locked_page->index;
+	unsigned int i, j;
+	struct page *page;
+	struct buffer_head *head, *bh;
+
+	UFSD("ENTER, ino %lu, count %u, oldb %u, newb %u\n",
+	      inode->i_ino, count, oldb, newb);
+
+	BUG_ON(!PageLocked(locked_page));
+
+	for (i = 0; i < count; i += blk_per_page) {
+		index = (baseblk+i) >> (PAGE_CACHE_SHIFT - inode->i_blkbits);
+
+		if (likely(cur_index != index)) {
+			page = ufs_get_locked_page(mapping, index);
+			if (IS_ERR(page))
+				continue;
+		} else
+			page = locked_page;
+
+		j = i;
+		head = page_buffers(page);
+		bh = head;
+		do {
+			if (likely(bh->b_blocknr == j + oldb && j < count)) {
+				unmap_underlying_metadata(bh->b_bdev,
+							  bh->b_blocknr);
+				bh->b_blocknr = newb + j++;
+				mark_buffer_dirty(bh);
+			}
+
+			bh = bh->b_this_page;
+		} while (bh != head);
+
+		set_page_dirty(page);
+
+		if (likely(cur_index != index)) {
+			unlock_page(page);
+			page_cache_release(page);
+		}
+ 	}
+	UFSD("EXIT\n");
+}
+
+unsigned ufs_new_fragments(struct inode * inode, __fs32 * p, unsigned fragment,
+			   unsigned goal, unsigned count, int * err, struct page *locked_page)
 {
 	struct super_block * sb;
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
-	struct buffer_head * bh;
-	unsigned cgno, oldcount, newcount, tmp, request, i, result;
+	unsigned cgno, oldcount, newcount, tmp, request, result;
 	
-	UFSD(("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count))
+	UFSD("ENTER, ino %lu, fragment %u, goal %u, count %u\n", inode->i_ino, fragment, goal, count);
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -273,14 +356,14 @@
 			return (unsigned)-1;
 		}
 		if (fragment < UFS_I(inode)->i_lastfrag) {
-			UFSD(("EXIT (ALREADY ALLOCATED)\n"))
+			UFSD("EXIT (ALREADY ALLOCATED)\n");
 			unlock_super (sb);
 			return 0;
 		}
 	}
 	else {
 		if (tmp) {
-			UFSD(("EXIT (ALREADY ALLOCATED)\n"))
+			UFSD("EXIT (ALREADY ALLOCATED)\n");
 			unlock_super(sb);
 			return 0;
 		}
@@ -289,9 +372,9 @@
 	/*
 	 * There is not enough space for user on the device
 	 */
-	if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(usb1, UFS_MINFREE) <= 0) {
+	if (!capable(CAP_SYS_RESOURCE) && ufs_freespace(uspi, UFS_MINFREE) <= 0) {
 		unlock_super (sb);
-		UFSD(("EXIT (FAILED)\n"))
+		UFSD("EXIT (FAILED)\n");
 		return 0;
 	}
 
@@ -310,12 +393,10 @@
 		if (result) {
 			*p = cpu_to_fs32(sb, result);
 			*err = 0;
-			inode->i_blocks += count << uspi->s_nspfshift;
 			UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
-			NULLIFY_FRAGMENTS
 		}
 		unlock_super(sb);
-		UFSD(("EXIT, result %u\n", result))
+		UFSD("EXIT, result %u\n", result);
 		return result;
 	}
 
@@ -325,11 +406,9 @@
 	result = ufs_add_fragments (inode, tmp, oldcount, newcount, err);
 	if (result) {
 		*err = 0;
-		inode->i_blocks += count << uspi->s_nspfshift;
 		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
-		NULLIFY_FRAGMENTS
 		unlock_super(sb);
-		UFSD(("EXIT, result %u\n", result))
+		UFSD("EXIT, result %u\n", result);
 		return result;
 	}
 
@@ -339,8 +418,8 @@
 	switch (fs32_to_cpu(sb, usb1->fs_optim)) {
 	    case UFS_OPTSPACE:
 		request = newcount;
-		if (uspi->s_minfree < 5 || fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree) 
-		    > uspi->s_dsize * uspi->s_minfree / (2 * 100) )
+		if (uspi->s_minfree < 5 || uspi->cs_total.cs_nffree
+		    > uspi->s_dsize * uspi->s_minfree / (2 * 100))
 			break;
 		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
 		break;
@@ -349,7 +428,7 @@
 	
 	    case UFS_OPTTIME:
 		request = uspi->s_fpb;
-		if (fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree) < uspi->s_dsize *
+		if (uspi->cs_total.cs_nffree < uspi->s_dsize *
 		    (uspi->s_minfree - 2) / 100)
 			break;
 		usb1->fs_optim = cpu_to_fs32(sb, UFS_OPTTIME);
@@ -357,39 +436,22 @@
 	}
 	result = ufs_alloc_fragments (inode, cgno, goal, request, err);
 	if (result) {
-		for (i = 0; i < oldcount; i++) {
-			bh = sb_bread(sb, tmp + i);
-			if(bh)
-			{
-				clear_buffer_dirty(bh);
-				bh->b_blocknr = result + i;
-				mark_buffer_dirty (bh);
-				if (IS_SYNC(inode))
-					sync_dirty_buffer(bh);
-				brelse (bh);
-			}
-			else
-			{
-				printk(KERN_ERR "ufs_new_fragments: bread fail\n");
-				unlock_super(sb);
-				return 0;
-			}
-		}
+		ufs_change_blocknr(inode, fragment - oldcount, oldcount, tmp,
+				   result, locked_page);
+
 		*p = cpu_to_fs32(sb, result);
 		*err = 0;
-		inode->i_blocks += count << uspi->s_nspfshift;
 		UFS_I(inode)->i_lastfrag = max_t(u32, UFS_I(inode)->i_lastfrag, fragment + count);
-		NULLIFY_FRAGMENTS
 		unlock_super(sb);
 		if (newcount < request)
 			ufs_free_fragments (inode, result + newcount, request - newcount);
 		ufs_free_fragments (inode, tmp, oldcount);
-		UFSD(("EXIT, result %u\n", result))
+		UFSD("EXIT, result %u\n", result);
 		return result;
 	}
 
 	unlock_super(sb);
-	UFSD(("EXIT (FAILED)\n"))
+	UFSD("EXIT (FAILED)\n");
 	return 0;
 }		
 
@@ -404,7 +466,7 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned cgno, fragno, fragoff, count, fragsize, i;
 	
-	UFSD(("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount))
+	UFSD("ENTER, fragment %u, oldcount %u, newcount %u\n", fragment, oldcount, newcount);
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -419,7 +481,7 @@
 	ucpi = ufs_load_cylinder (sb, cgno);
 	if (!ucpi)
 		return 0;
-	ucg = ubh_get_ucg (UCPI_UBH);
+	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg)) {
 		ufs_panic (sb, "ufs_add_fragments",
 			"internal error, bad magic number on cg %u", cgno);
@@ -429,14 +491,14 @@
 	fragno = ufs_dtogd (fragment);
 	fragoff = ufs_fragnum (fragno);
 	for (i = oldcount; i < newcount; i++)
-		if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, fragno + i))
+		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
 			return 0;
 	/*
 	 * Block can be extended
 	 */
 	ucg->cg_time = cpu_to_fs32(sb, get_seconds());
 	for (i = newcount; i < (uspi->s_fpb - fragoff); i++)
-		if (ubh_isclr (UCPI_UBH, ucpi->c_freeoff, fragno + i))
+		if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i))
 			break;
 	fragsize = i - oldcount;
 	if (!fs32_to_cpu(sb, ucg->cg_frsum[fragsize]))
@@ -446,7 +508,7 @@
 	if (fragsize != count)
 		fs32_add(sb, &ucg->cg_frsum[fragsize - count], 1);
 	for (i = oldcount; i < newcount; i++)
-		ubh_clrbit (UCPI_UBH, ucpi->c_freeoff, fragno + i);
+		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, fragno + i);
 	if(DQUOT_ALLOC_BLOCK(inode, count)) {
 		*err = -EDQUOT;
 		return 0;
@@ -454,17 +516,17 @@
 
 	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
-	fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, count);
+	uspi->cs_total.cs_nffree -= count;
 	
-	ubh_mark_buffer_dirty (USPI_UBH);
-	ubh_mark_buffer_dirty (UCPI_UBH);
+	ubh_mark_buffer_dirty (USPI_UBH(uspi));
+	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
-		ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
-		ubh_wait_on_buffer (UCPI_UBH);
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer (UCPI_UBH(ucpi));
 	}
 	sb->s_dirt = 1;
 
-	UFSD(("EXIT, fragment %u\n", fragment))
+	UFSD("EXIT, fragment %u\n", fragment);
 	
 	return fragment;
 }
@@ -487,7 +549,7 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned oldcg, i, j, k, result, allocsize;
 	
-	UFSD(("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count))
+	UFSD("ENTER, ino %lu, cgno %u, goal %u, count %u\n", inode->i_ino, cgno, goal, count);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -521,14 +583,14 @@
 		UFS_TEST_FREE_SPACE_CG
 	}
 	
-	UFSD(("EXIT (FAILED)\n"))
+	UFSD("EXIT (FAILED)\n");
 	return 0;
 
 cg_found:
 	ucpi = ufs_load_cylinder (sb, cgno);
 	if (!ucpi)
 		return 0;
-	ucg = ubh_get_ucg (UCPI_UBH);
+	ucg = ubh_get_ucg (UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg)) 
 		ufs_panic (sb, "ufs_alloc_fragments",
 			"internal error, bad magic number on cg %u", cgno);
@@ -551,12 +613,12 @@
 			return 0;
 		goal = ufs_dtogd (result);
 		for (i = count; i < uspi->s_fpb; i++)
-			ubh_setbit (UCPI_UBH, ucpi->c_freeoff, goal + i);
+			ubh_setbit (UCPI_UBH(ucpi), ucpi->c_freeoff, goal + i);
 		i = uspi->s_fpb - count;
 		DQUOT_FREE_BLOCK(inode, i);
 
 		fs32_add(sb, &ucg->cg_cs.cs_nffree, i);
-		fs32_add(sb, &usb1->fs_cstotal.cs_nffree, i);
+		uspi->cs_total.cs_nffree += i;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, i);
 		fs32_add(sb, &ucg->cg_frsum[i], 1);
 		goto succed;
@@ -570,10 +632,10 @@
 		return 0;
 	}
 	for (i = 0; i < count; i++)
-		ubh_clrbit (UCPI_UBH, ucpi->c_freeoff, result + i);
+		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_freeoff, result + i);
 	
 	fs32_sub(sb, &ucg->cg_cs.cs_nffree, count);
-	fs32_sub(sb, &usb1->fs_cstotal.cs_nffree, count);
+	uspi->cs_total.cs_nffree -= count;
 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(cgno).cs_nffree, count);
 	fs32_sub(sb, &ucg->cg_frsum[allocsize], 1);
 
@@ -581,16 +643,16 @@
 		fs32_add(sb, &ucg->cg_frsum[allocsize - count], 1);
 
 succed:
-	ubh_mark_buffer_dirty (USPI_UBH);
-	ubh_mark_buffer_dirty (UCPI_UBH);
+	ubh_mark_buffer_dirty (USPI_UBH(uspi));
+	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
-		ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **)&ucpi);
-		ubh_wait_on_buffer (UCPI_UBH);
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer (UCPI_UBH(ucpi));
 	}
 	sb->s_dirt = 1;
 
 	result += cgno * uspi->s_fpg;
-	UFSD(("EXIT3, result %u\n", result))
+	UFSD("EXIT3, result %u\n", result);
 	return result;
 }
 
@@ -603,12 +665,12 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned result, cylno, blkno;
 
-	UFSD(("ENTER, goal %u\n", goal))
+	UFSD("ENTER, goal %u\n", goal);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
-	ucg = ubh_get_ucg(UCPI_UBH);
+	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 
 	if (goal == 0) {
 		goal = ucpi->c_rotor;
@@ -620,7 +682,7 @@
 	/*
 	 * If the requested block is available, use it.
 	 */
-	if (ubh_isblockset(UCPI_UBH, ucpi->c_freeoff, ufs_fragstoblks(goal))) {
+	if (ubh_isblockset(UCPI_UBH(ucpi), ucpi->c_freeoff, ufs_fragstoblks(goal))) {
 		result = goal;
 		goto gotit;
 	}
@@ -632,7 +694,7 @@
 	ucpi->c_rotor = result;
 gotit:
 	blkno = ufs_fragstoblks(result);
-	ubh_clrblock (UCPI_UBH, ucpi->c_freeoff, blkno);
+	ubh_clrblock (UCPI_UBH(ucpi), ucpi->c_freeoff, blkno);
 	if ((UFS_SB(sb)->s_flags & UFS_CG_MASK) == UFS_CG_44BSD)
 		ufs_clusteracct (sb, ucpi, blkno, -1);
 	if(DQUOT_ALLOC_BLOCK(inode, uspi->s_fpb)) {
@@ -641,31 +703,76 @@
 	}
 
 	fs32_sub(sb, &ucg->cg_cs.cs_nbfree, 1);
-	fs32_sub(sb, &usb1->fs_cstotal.cs_nbfree, 1);
+	uspi->cs_total.cs_nbfree--;
 	fs32_sub(sb, &UFS_SB(sb)->fs_cs(ucpi->c_cgx).cs_nbfree, 1);
 	cylno = ufs_cbtocylno(result);
 	fs16_sub(sb, &ubh_cg_blks(ucpi, cylno, ufs_cbtorpos(result)), 1);
 	fs32_sub(sb, &ubh_cg_blktot(ucpi, cylno), 1);
 	
-	UFSD(("EXIT, result %u\n", result))
+	UFSD("EXIT, result %u\n", result);
 
 	return result;
 }
 
-static unsigned ufs_bitmap_search (struct super_block * sb,
-	struct ufs_cg_private_info * ucpi, unsigned goal, unsigned count)
+static unsigned ubh_scanc(struct ufs_sb_private_info *uspi,
+			  struct ufs_buffer_head *ubh,
+			  unsigned begin, unsigned size,
+			  unsigned char *table, unsigned char mask)
 {
-	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
-	struct ufs_cylinder_group * ucg;
-	unsigned start, length, location, result;
-	unsigned possition, fragsize, blockmap, mask;
+	unsigned rest, offset;
+	unsigned char *cp;
 	
-	UFSD(("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count))
 
-	uspi = UFS_SB(sb)->s_uspi;
+	offset = begin & ~uspi->s_fmask;
+	begin >>= uspi->s_fshift;
+	for (;;) {
+		if ((offset + size) < uspi->s_fsize)
+			rest = size;
+		else
+			rest = uspi->s_fsize - offset;
+		size -= rest;
+		cp = ubh->bh[begin]->b_data + offset;
+		while ((table[*cp++] & mask) == 0 && --rest)
+			;
+		if (rest || !size)
+			break;
+		begin++;
+		offset = 0;
+	}
+	return (size + rest);
+}
+
+/*
+ * Find a block of the specified size in the specified cylinder group.
+ * @sp: pointer to super block
+ * @ucpi: pointer to cylinder group info
+ * @goal: near which block we want find new one
+ * @count: specified size
+ */
+static unsigned ufs_bitmap_search(struct super_block *sb,
+				  struct ufs_cg_private_info *ucpi,
+				  unsigned goal, unsigned count)
+{
+	/*
+	 * Bit patterns for identifying fragments in the block map
+	 * used as ((map & mask_arr) == want_arr)
+	 */
+	static const int mask_arr[9] = {
+		0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff
+	};
+	static const int want_arr[9] = {
+		0x0, 0x2, 0x6, 0xe, 0x1e, 0x3e, 0x7e, 0xfe, 0x1fe
+	};
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	struct ufs_super_block_first *usb1;
+	struct ufs_cylinder_group *ucg;
+	unsigned start, length, loc, result;
+	unsigned pos, want, blockmap, mask, end;
+
+	UFSD("ENTER, cg %u, goal %u, count %u\n", ucpi->c_cgx, goal, count);
+
 	usb1 = ubh_get_usb_first (uspi);
-	ucg = ubh_get_ucg(UCPI_UBH);
+	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 
 	if (goal)
 		start = ufs_dtogd(goal) >> 3;
@@ -673,53 +780,50 @@
 		start = ucpi->c_frotor >> 3;
 		
 	length = ((uspi->s_fpg + 7) >> 3) - start;
-	location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff + start, length,
+	loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff + start, length,
 		(uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
 		1 << (count - 1 + (uspi->s_fpb & 7))); 
-	if (location == 0) {
+	if (loc == 0) {
 		length = start + 1;
-		location = ubh_scanc(UCPI_UBH, ucpi->c_freeoff, length, 
-			(uspi->s_fpb == 8) ? ufs_fragtable_8fpb : ufs_fragtable_other,
-			1 << (count - 1 + (uspi->s_fpb & 7)));
-		if (location == 0) {
-			ufs_error (sb, "ufs_bitmap_search",
-			"bitmap corrupted on cg %u, start %u, length %u, count %u, freeoff %u\n",
-			ucpi->c_cgx, start, length, count, ucpi->c_freeoff);
+		loc = ubh_scanc(uspi, UCPI_UBH(ucpi), ucpi->c_freeoff, length,
+				(uspi->s_fpb == 8) ? ufs_fragtable_8fpb :
+				ufs_fragtable_other,
+				1 << (count - 1 + (uspi->s_fpb & 7)));
+		if (loc == 0) {
+			ufs_error(sb, "ufs_bitmap_search",
+				  "bitmap corrupted on cg %u, start %u,"
+				  " length %u, count %u, freeoff %u\n",
+				  ucpi->c_cgx, start, length, count,
+				  ucpi->c_freeoff);
 			return (unsigned)-1;
 		}
 		start = 0;
 	}
-	result = (start + length - location) << 3;
+	result = (start + length - loc) << 3;
 	ucpi->c_frotor = result;
 
 	/*
 	 * found the byte in the map
 	 */
-	blockmap = ubh_blkmap(UCPI_UBH, ucpi->c_freeoff, result);
-	fragsize = 0;
-	for (possition = 0, mask = 1; possition < 8; possition++, mask <<= 1) {
-		if (blockmap & mask) {
-			if (!(possition & uspi->s_fpbmask))
-				fragsize = 1;
-			else 
-				fragsize++;
-		}
-		else {
-			if (fragsize == count) {
-				result += possition - count;
-				UFSD(("EXIT, result %u\n", result))
-				return result;
-			}
-			fragsize = 0;
-		}
-	}
-	if (fragsize == count) {
-		result += possition - count;
-		UFSD(("EXIT, result %u\n", result))
-		return result;
-	}
-	ufs_error (sb, "ufs_bitmap_search", "block not in map on cg %u\n", ucpi->c_cgx);
-	UFSD(("EXIT (FAILED)\n"))
+
+	for (end = result + 8; result < end; result += uspi->s_fpb) {
+		blockmap = ubh_blkmap(UCPI_UBH(ucpi), ucpi->c_freeoff, result);
+		blockmap <<= 1;
+		mask = mask_arr[count];
+		want = want_arr[count];
+		for (pos = 0; pos <= uspi->s_fpb - count; pos++) {
+			if ((blockmap & mask) == want) {
+				UFSD("EXIT, result %u\n", result);
+				return result + pos;
+ 			}
+			mask <<= 1;
+			want <<= 1;
+ 		}
+ 	}
+
+	ufs_error(sb, "ufs_bitmap_search", "block not in map on cg %u\n",
+		  ucpi->c_cgx);
+	UFSD("EXIT (FAILED)\n");
 	return (unsigned)-1;
 }
 
@@ -734,9 +838,9 @@
 		return;
 
 	if (cnt > 0)
-		ubh_setbit(UCPI_UBH, ucpi->c_clusteroff, blkno);
+		ubh_setbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
 	else
-		ubh_clrbit(UCPI_UBH, ucpi->c_clusteroff, blkno);
+		ubh_clrbit(UCPI_UBH(ucpi), ucpi->c_clusteroff, blkno);
 
 	/*
 	 * Find the size of the cluster going forward.
@@ -745,7 +849,7 @@
 	end = start + uspi->s_contigsumsize;
 	if ( end >= ucpi->c_nclusterblks)
 		end = ucpi->c_nclusterblks;
-	i = ubh_find_next_zero_bit (UCPI_UBH, ucpi->c_clusteroff, end, start);
+	i = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, end, start);
 	if (i > end)
 		i = end;
 	forw = i - start;
@@ -757,7 +861,7 @@
 	end = start - uspi->s_contigsumsize;
 	if (end < 0 ) 
 		end = -1;
-	i = ubh_find_last_zero_bit (UCPI_UBH, ucpi->c_clusteroff, start, end);
+	i = ubh_find_last_zero_bit (UCPI_UBH(ucpi), ucpi->c_clusteroff, start, end);
 	if ( i < end) 
 		i = end;
 	back = start - i;
@@ -769,11 +873,11 @@
 	i = back + forw + 1;
 	if (i > uspi->s_contigsumsize)
 		i = uspi->s_contigsumsize;
-	fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (i << 2)), cnt);
+	fs32_add(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (i << 2)), cnt);
 	if (back > 0)
-		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (back << 2)), cnt);
+		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (back << 2)), cnt);
 	if (forw > 0)
-		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH, ucpi->c_clustersumoff + (forw << 2)), cnt);
+		fs32_sub(sb, (__fs32*)ubh_get_addr(UCPI_UBH(ucpi), ucpi->c_clustersumoff + (forw << 2)), cnt);
 }
 
 
diff --git a/fs/ufs/cylinder.c b/fs/ufs/cylinder.c
index 14abb8b..09c39e5 100644
--- a/fs/ufs/cylinder.c
+++ b/fs/ufs/cylinder.c
@@ -20,15 +20,6 @@
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_CYLINDER_DEBUG
-
-#ifdef UFS_CYLINDER_DEBUG
-#define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
-
 /*
  * Read cylinder group into cache. The memory space for ufs_cg_private_info
  * structure is already allocated during ufs_read_super.
@@ -42,19 +33,19 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned i, j;
 
-	UFSD(("ENTER, cgno %u, bitmap_nr %u\n", cgno, bitmap_nr))
+	UFSD("ENTER, cgno %u, bitmap_nr %u\n", cgno, bitmap_nr);
 	uspi = sbi->s_uspi;
 	ucpi = sbi->s_ucpi[bitmap_nr];
 	ucg = (struct ufs_cylinder_group *)sbi->s_ucg[cgno]->b_data;
 
-	UCPI_UBH->fragment = ufs_cgcmin(cgno);
-	UCPI_UBH->count = uspi->s_cgsize >> sb->s_blocksize_bits;
+	UCPI_UBH(ucpi)->fragment = ufs_cgcmin(cgno);
+	UCPI_UBH(ucpi)->count = uspi->s_cgsize >> sb->s_blocksize_bits;
 	/*
 	 * We have already the first fragment of cylinder group block in buffer
 	 */
-	UCPI_UBH->bh[0] = sbi->s_ucg[cgno];
-	for (i = 1; i < UCPI_UBH->count; i++)
-		if (!(UCPI_UBH->bh[i] = sb_bread(sb, UCPI_UBH->fragment + i)))
+	UCPI_UBH(ucpi)->bh[0] = sbi->s_ucg[cgno];
+	for (i = 1; i < UCPI_UBH(ucpi)->count; i++)
+		if (!(UCPI_UBH(ucpi)->bh[i] = sb_bread(sb, UCPI_UBH(ucpi)->fragment + i)))
 			goto failed;
 	sbi->s_cgno[bitmap_nr] = cgno;
 			
@@ -73,7 +64,7 @@
 	ucpi->c_clustersumoff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clustersumoff);
 	ucpi->c_clusteroff = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_clusteroff);
 	ucpi->c_nclusterblks = fs32_to_cpu(sb, ucg->cg_u.cg_44.cg_nclusterblks);
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return;	
 	
 failed:
@@ -95,15 +86,15 @@
 	struct ufs_cylinder_group * ucg;
 	unsigned i;
 
-	UFSD(("ENTER, bitmap_nr %u\n", bitmap_nr))
+	UFSD("ENTER, bitmap_nr %u\n", bitmap_nr);
 
 	uspi = sbi->s_uspi;
 	if (sbi->s_cgno[bitmap_nr] == UFS_CGNO_EMPTY) {
-		UFSD(("EXIT\n"))
+		UFSD("EXIT\n");
 		return;
 	}
 	ucpi = sbi->s_ucpi[bitmap_nr];
-	ucg = ubh_get_ucg(UCPI_UBH);
+	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 
 	if (uspi->s_ncg > UFS_MAX_GROUP_LOADED && bitmap_nr >= sbi->s_cg_loaded) {
 		ufs_panic (sb, "ufs_put_cylinder", "internal error");
@@ -116,13 +107,13 @@
 	ucg->cg_rotor = cpu_to_fs32(sb, ucpi->c_rotor);
 	ucg->cg_frotor = cpu_to_fs32(sb, ucpi->c_frotor);
 	ucg->cg_irotor = cpu_to_fs32(sb, ucpi->c_irotor);
-	ubh_mark_buffer_dirty (UCPI_UBH);
-	for (i = 1; i < UCPI_UBH->count; i++) {
-		brelse (UCPI_UBH->bh[i]);
+	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
+	for (i = 1; i < UCPI_UBH(ucpi)->count; i++) {
+		brelse (UCPI_UBH(ucpi)->bh[i]);
 	}
 
 	sbi->s_cgno[bitmap_nr] = UFS_CGNO_EMPTY;
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 }
 
 /*
@@ -139,7 +130,7 @@
 	struct ufs_cg_private_info * ucpi;
 	unsigned cg, i, j;
 
-	UFSD(("ENTER, cgno %u\n", cgno))
+	UFSD("ENTER, cgno %u\n", cgno);
 
 	uspi = sbi->s_uspi;
 	if (cgno >= uspi->s_ncg) {
@@ -150,7 +141,7 @@
 	 * Cylinder group number cg it in cache and it was last used
 	 */
 	if (sbi->s_cgno[0] == cgno) {
-		UFSD(("EXIT\n"))
+		UFSD("EXIT\n");
 		return sbi->s_ucpi[0];
 	}
 	/*
@@ -160,16 +151,16 @@
 		if (sbi->s_cgno[cgno] != UFS_CGNO_EMPTY) {
 			if (sbi->s_cgno[cgno] != cgno) {
 				ufs_panic (sb, "ufs_load_cylinder", "internal error, wrong number of cg in cache");
-				UFSD(("EXIT (FAILED)\n"))
+				UFSD("EXIT (FAILED)\n");
 				return NULL;
 			}
 			else {
-				UFSD(("EXIT\n"))
+				UFSD("EXIT\n");
 				return sbi->s_ucpi[cgno];
 			}
 		} else {
 			ufs_read_cylinder (sb, cgno, cgno);
-			UFSD(("EXIT\n"))
+			UFSD("EXIT\n");
 			return sbi->s_ucpi[cgno];
 		}
 	}
@@ -204,6 +195,6 @@
 		sbi->s_ucpi[0] = ucpi;
 		ufs_read_cylinder (sb, cgno, 0);
 	}
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return sbi->s_ucpi[0];
 }
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 1a56120..7f0a0aa 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -11,31 +11,20 @@
  * 4.4BSD (FreeBSD) support added on February 1st 1998 by
  * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
  * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
+ *
+ * Migration to usage of "page cache" on May 2006 by
+ * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
  */
 
 #include <linux/time.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/smp_lock.h>
-#include <linux/buffer_head.h>
 #include <linux/sched.h>
 
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_DIR_DEBUG
-
-#ifdef UFS_DIR_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
-static int
-ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *,
-		     struct buffer_head *, unsigned long);
-
-
 /*
  * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
  *
@@ -51,495 +40,541 @@
 	return !memcmp(name, de->d_name, len);
 }
 
-/*
- * This is blatantly stolen from ext2fs
- */
-static int
-ufs_readdir (struct file * filp, void * dirent, filldir_t filldir)
+static int ufs_commit_chunk(struct page *page, unsigned from, unsigned to)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
-	int error = 0;
-	unsigned long offset, lblk;
-	int i, stored;
-	struct buffer_head * bh;
-	struct ufs_dir_entry * de;
-	struct super_block * sb;
-	int de_reclen;
-	unsigned flags;
-	u64     blk= 0L;
+	struct inode *dir = page->mapping->host;
+	int err = 0;
+	dir->i_version++;
+	page->mapping->a_ops->commit_write(NULL, page, from, to);
+	if (IS_DIRSYNC(dir))
+		err = write_one_page(page, 1);
+	else
+		unlock_page(page);
+	return err;
+}
 
-	lock_kernel();
+static inline void ufs_put_page(struct page *page)
+{
+	kunmap(page);
+	page_cache_release(page);
+}
 
-	sb = inode->i_sb;
-	flags = UFS_SB(sb)->s_flags;
+static inline unsigned long ufs_dir_pages(struct inode *inode)
+{
+	return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
+}
 
-	UFSD(("ENTER, ino %lu  f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos))
-
-	stored = 0;
-	bh = NULL;
-	offset = filp->f_pos & (sb->s_blocksize - 1);
-
-	while (!error && !stored && filp->f_pos < inode->i_size) {
-		lblk = (filp->f_pos) >> sb->s_blocksize_bits;
-		blk = ufs_frag_map(inode, lblk);
-		if (!blk || !(bh = sb_bread(sb, blk))) {
-			/* XXX - error - skip to the next block */
-			printk("ufs_readdir: "
-			       "dir inode %lu has a hole at offset %lu\n",
-			       inode->i_ino, (unsigned long int)filp->f_pos);
-			filp->f_pos += sb->s_blocksize - offset;
-			continue;
-		}
-
-revalidate:
-		/* If the dir block has changed since the last call to
-		 * readdir(2), then we might be pointing to an invalid
-		 * dirent right now.  Scan from the start of the block
-		 * to make sure. */
-		if (filp->f_version != inode->i_version) {
-			for (i = 0; i < sb->s_blocksize && i < offset; ) {
-				de = (struct ufs_dir_entry *)(bh->b_data + i);
-				/* It's too expensive to do a full
-				 * dirent test each time round this
-				 * loop, but we do have to test at
-				 * least that it is non-zero.  A
-				 * failure will be detected in the
-				 * dirent test below. */
-				de_reclen = fs16_to_cpu(sb, de->d_reclen);
-				if (de_reclen < 1)
-					break;
-				i += de_reclen;
-			}
-			offset = i;
-			filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
-				| offset;
-			filp->f_version = inode->i_version;
-		}
-
-		while (!error && filp->f_pos < inode->i_size
-		       && offset < sb->s_blocksize) {
-			de = (struct ufs_dir_entry *) (bh->b_data + offset);
-			/* XXX - put in a real ufs_check_dir_entry() */
-			if ((de->d_reclen == 0) || (ufs_get_de_namlen(sb, de) == 0)) {
-				filp->f_pos = (filp->f_pos &
-				              (sb->s_blocksize - 1)) +
-				               sb->s_blocksize;
-				brelse(bh);
-				unlock_kernel();
-				return stored;
-			}
-			if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
-						   bh, offset)) {
-				/* On error, skip the f_pos to the
-				   next block. */
-				filp->f_pos = (filp->f_pos |
-				              (sb->s_blocksize - 1)) +
-					       1;
-				brelse (bh);
-				unlock_kernel();
-				return stored;
-			}
-			offset += fs16_to_cpu(sb, de->d_reclen);
-			if (de->d_ino) {
-				/* We might block in the next section
-				 * if the data destination is
-				 * currently swapped out.  So, use a
-				 * version stamp to detect whether or
-				 * not the directory has been modified
-				 * during the copy operation. */
-				unsigned long version = filp->f_version;
-				unsigned char d_type = DT_UNKNOWN;
-
-				UFSD(("filldir(%s,%u)\n", de->d_name,
-							fs32_to_cpu(sb, de->d_ino)))
-				UFSD(("namlen %u\n", ufs_get_de_namlen(sb, de)))
-
-				if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
-					d_type = de->d_u.d_44.d_type;
-				error = filldir(dirent, de->d_name,
-						ufs_get_de_namlen(sb, de), filp->f_pos,
-						fs32_to_cpu(sb, de->d_ino), d_type);
-				if (error)
-					break;
-				if (version != filp->f_version)
-					goto revalidate;
-				stored ++;
-			}
-			filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
-		}
-		offset = 0;
-		brelse (bh);
+ino_t ufs_inode_by_name(struct inode *dir, struct dentry *dentry)
+{
+	ino_t res = 0;
+	struct ufs_dir_entry *de;
+	struct page *page;
+	
+	de = ufs_find_entry(dir, dentry, &page);
+	if (de) {
+		res = fs32_to_cpu(dir->i_sb, de->d_ino);
+		ufs_put_page(page);
 	}
-	unlock_kernel();
-	return 0;
+	return res;
+}
+
+
+/* Releases the page */
+void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
+		  struct page *page, struct inode *inode)
+{
+	unsigned from = (char *) de - (char *) page_address(page);
+	unsigned to = from + fs16_to_cpu(dir->i_sb, de->d_reclen);
+	int err;
+
+	lock_page(page);
+	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+	BUG_ON(err);
+	de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
+	ufs_set_de_type(dir->i_sb, de, inode->i_mode);
+	err = ufs_commit_chunk(page, from, to);
+	ufs_put_page(page);
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+	mark_inode_dirty(dir);
+}
+
+
+static void ufs_check_page(struct page *page)
+{
+	struct inode *dir = page->mapping->host;
+	struct super_block *sb = dir->i_sb;
+	char *kaddr = page_address(page);
+	unsigned offs, rec_len;
+	unsigned limit = PAGE_CACHE_SIZE;
+	struct ufs_dir_entry *p;
+	char *error;
+
+	if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
+		limit = dir->i_size & ~PAGE_CACHE_MASK;
+		if (limit & (UFS_SECTOR_SIZE - 1))
+			goto Ebadsize;
+		if (!limit)
+			goto out;
+	}
+	for (offs = 0; offs <= limit - UFS_DIR_REC_LEN(1); offs += rec_len) {
+		p = (struct ufs_dir_entry *)(kaddr + offs);
+		rec_len = fs16_to_cpu(sb, p->d_reclen);
+
+		if (rec_len < UFS_DIR_REC_LEN(1))
+			goto Eshort;
+		if (rec_len & 3)
+			goto Ealign;
+		if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p)))
+			goto Enamelen;
+		if (((offs + rec_len - 1) ^ offs) & ~(UFS_SECTOR_SIZE-1))
+			goto Espan;
+		if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg *
+						  UFS_SB(sb)->s_uspi->s_ncg))
+			goto Einumber;
+	}
+	if (offs != limit)
+		goto Eend;
+out:
+	SetPageChecked(page);
+	return;
+
+	/* Too bad, we had an error */
+
+Ebadsize:
+	ufs_error(sb, "ufs_check_page",
+		  "size of directory #%lu is not a multiple of chunk size",
+		  dir->i_ino
+	);
+	goto fail;
+Eshort:
+	error = "rec_len is smaller than minimal";
+	goto bad_entry;
+Ealign:
+	error = "unaligned directory entry";
+	goto bad_entry;
+Enamelen:
+	error = "rec_len is too small for name_len";
+	goto bad_entry;
+Espan:
+	error = "directory entry across blocks";
+	goto bad_entry;
+Einumber:
+	error = "inode out of bounds";
+bad_entry:
+	ufs_error (sb, "ufs_check_page", "bad entry in directory #%lu: %s - "
+		   "offset=%lu, rec_len=%d, name_len=%d",
+		   dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs,
+		   rec_len, ufs_get_de_namlen(sb, p));
+	goto fail;
+Eend:
+	p = (struct ufs_dir_entry *)(kaddr + offs);
+	ufs_error (sb, "ext2_check_page",
+		   "entry in directory #%lu spans the page boundary"
+		   "offset=%lu",
+		   dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs);
+fail:
+	SetPageChecked(page);
+	SetPageError(page);
+}
+
+static struct page *ufs_get_page(struct inode *dir, unsigned long n)
+{
+	struct address_space *mapping = dir->i_mapping;
+	struct page *page = read_cache_page(mapping, n,
+				(filler_t*)mapping->a_ops->readpage, NULL);
+	if (!IS_ERR(page)) {
+		wait_on_page_locked(page);
+		kmap(page);
+		if (!PageUptodate(page))
+			goto fail;
+		if (!PageChecked(page))
+			ufs_check_page(page);
+		if (PageError(page))
+			goto fail;
+	}
+	return page;
+
+fail:
+	ufs_put_page(page);
+	return ERR_PTR(-EIO);
 }
 
 /*
- * define how far ahead to read directories while searching them.
+ * Return the offset into page `page_nr' of the last valid
+ * byte in that page, plus one.
  */
-#define NAMEI_RA_CHUNKS  2
-#define NAMEI_RA_BLOCKS  4
-#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
-#define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
+static unsigned
+ufs_last_byte(struct inode *inode, unsigned long page_nr)
+{
+	unsigned last_byte = inode->i_size;
+
+	last_byte -= page_nr << PAGE_CACHE_SHIFT;
+	if (last_byte > PAGE_CACHE_SIZE)
+		last_byte = PAGE_CACHE_SIZE;
+	return last_byte;
+}
+
+static inline struct ufs_dir_entry *
+ufs_next_entry(struct super_block *sb, struct ufs_dir_entry *p)
+{
+	return (struct ufs_dir_entry *)((char *)p +
+					fs16_to_cpu(sb, p->d_reclen));
+}
+
+struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct page **p)
+{
+	struct page *page = ufs_get_page(dir, 0);
+	struct ufs_dir_entry *de = NULL;
+
+	if (!IS_ERR(page)) {
+		de = ufs_next_entry(dir->i_sb,
+				    (struct ufs_dir_entry *)page_address(page));
+		*p = page;
+	}
+	return de;
+}
 
 /*
  *	ufs_find_entry()
  *
  * finds an entry in the specified directory with the wanted name. It
- * returns the cache buffer in which the entry was found, and the entry
- * itself (as a parameter - res_bh). It does NOT read the inode of the
- * entry - you'll have to do that yourself if you want to.
+ * returns the page in which the entry was found, and the entry itself
+ * (as a parameter - res_dir). Page is returned mapped and unlocked.
+ * Entry is guaranteed to be valid.
  */
-struct ufs_dir_entry * ufs_find_entry (struct dentry *dentry,
-	struct buffer_head ** res_bh)
-{
-	struct super_block * sb;
-	struct buffer_head * bh_use[NAMEI_RA_SIZE];
-	struct buffer_head * bh_read[NAMEI_RA_SIZE];
-	unsigned long offset;
-	int block, toread, i, err;
-	struct inode *dir = dentry->d_parent->d_inode;
-	const char *name = dentry->d_name.name;
-	int namelen = dentry->d_name.len;
-
-	UFSD(("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen))
-	
-	*res_bh = NULL;
-	
-	sb = dir->i_sb;
-	
-	if (namelen > UFS_MAXNAMLEN)
-		return NULL;
-
-	memset (bh_use, 0, sizeof (bh_use));
-	toread = 0;
-	for (block = 0; block < NAMEI_RA_SIZE; ++block) {
-		struct buffer_head * bh;
-
-		if ((block << sb->s_blocksize_bits) >= dir->i_size)
-			break;
-		bh = ufs_getfrag (dir, block, 0, &err);
-		bh_use[block] = bh;
-		if (bh && !buffer_uptodate(bh))
-			bh_read[toread++] = bh;
-	}
-
-	for (block = 0, offset = 0; offset < dir->i_size; block++) {
-		struct buffer_head * bh;
-		struct ufs_dir_entry * de;
-		char * dlimit;
-
-		if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
-			ll_rw_block (READ, toread, bh_read);
-			toread = 0;
-		}
-		bh = bh_use[block % NAMEI_RA_SIZE];
-		if (!bh) {
-			ufs_error (sb, "ufs_find_entry", 
-				"directory #%lu contains a hole at offset %lu",
-				dir->i_ino, offset);
-			offset += sb->s_blocksize;
-			continue;
-		}
-		wait_on_buffer (bh);
-		if (!buffer_uptodate(bh)) {
-			/*
-			 * read error: all bets are off
-			 */
-			break;
-		}
-
-		de = (struct ufs_dir_entry *) bh->b_data;
-		dlimit = bh->b_data + sb->s_blocksize;
-		while ((char *) de < dlimit && offset < dir->i_size) {
-			/* this code is executed quadratically often */
-			/* do minimal checking by hand */
-			int de_len;
-
-			if ((char *) de + namelen <= dlimit &&
-			    ufs_match(sb, namelen, name, de)) {
-				/* found a match -
-				just to be sure, do a full check */
-				if (!ufs_check_dir_entry("ufs_find_entry",
-				    dir, de, bh, offset))
-					goto failed;
-				for (i = 0; i < NAMEI_RA_SIZE; ++i) {
-					if (bh_use[i] != bh)
-						brelse (bh_use[i]);
-				}
-				*res_bh = bh;
-				return de;
-			}
-                        /* prevent looping on a bad block */
-			de_len = fs16_to_cpu(sb, de->d_reclen);
-			if (de_len <= 0)
-				goto failed;
-			offset += de_len;
-			de = (struct ufs_dir_entry *) ((char *) de + de_len);
-		}
-
-		brelse (bh);
-		if (((block + NAMEI_RA_SIZE) << sb->s_blocksize_bits ) >=
-		    dir->i_size)
-			bh = NULL;
-		else
-			bh = ufs_getfrag (dir, block + NAMEI_RA_SIZE, 0, &err);
-		bh_use[block % NAMEI_RA_SIZE] = bh;
-		if (bh && !buffer_uptodate(bh))
-			bh_read[toread++] = bh;
-	}
-
-failed:
-	for (i = 0; i < NAMEI_RA_SIZE; ++i) brelse (bh_use[i]);
-	UFSD(("EXIT\n"))
-	return NULL;
-}
-
-static int
-ufs_check_dir_entry (const char *function, struct inode *dir,
-		     struct ufs_dir_entry *de, struct buffer_head *bh,
-		     unsigned long offset)
+struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct dentry *dentry,
+				     struct page **res_page)
 {
 	struct super_block *sb = dir->i_sb;
-	const char *error_msg = NULL;
-	int rlen = fs16_to_cpu(sb, de->d_reclen);
+	const char *name = dentry->d_name.name;
+	int namelen = dentry->d_name.len;
+	unsigned reclen = UFS_DIR_REC_LEN(namelen);
+	unsigned long start, n;
+	unsigned long npages = ufs_dir_pages(dir);
+	struct page *page = NULL;
+	struct ufs_inode_info *ui = UFS_I(dir);
+	struct ufs_dir_entry *de;
 
-	if (rlen < UFS_DIR_REC_LEN(1))
-		error_msg = "reclen is smaller than minimal";
-	else if (rlen % 4 != 0)
-		error_msg = "reclen % 4 != 0";
-	else if (rlen < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)))
-		error_msg = "reclen is too small for namlen";
-	else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
-		error_msg = "directory entry across blocks";
-	else if (fs32_to_cpu(sb, de->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg *
-				      UFS_SB(sb)->s_uspi->s_ncg))
-		error_msg = "inode out of bounds";
+	UFSD("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen);
 
-	if (error_msg != NULL)
-		ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - "
-			    "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
-			    dir->i_ino, dir->i_size, error_msg, offset,
-			    (unsigned long)fs32_to_cpu(sb, de->d_ino),
-			    rlen, ufs_get_de_namlen(sb, de));
-	
-	return (error_msg == NULL ? 1 : 0);
-}
+	if (npages == 0 || namelen > UFS_MAXNAMLEN)
+		goto out;
 
-struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct buffer_head **p)
-{
-	int err;
-	struct buffer_head *bh = ufs_bread (dir, 0, 0, &err);
-	struct ufs_dir_entry *res = NULL;
+	/* OFFSET_CACHE */
+	*res_page = NULL;
 
-	if (bh) {
-		res = (struct ufs_dir_entry *) bh->b_data;
-		res = (struct ufs_dir_entry *)((char *)res +
-			fs16_to_cpu(dir->i_sb, res->d_reclen));
-	}
-	*p = bh;
-	return res;
-}
-ino_t ufs_inode_by_name(struct inode * dir, struct dentry *dentry)
-{
-	ino_t res = 0;
-	struct ufs_dir_entry * de;
-	struct buffer_head *bh;
+	start = ui->i_dir_start_lookup;
 
-	de = ufs_find_entry (dentry, &bh);
-	if (de) {
-		res = fs32_to_cpu(dir->i_sb, de->d_ino);
-		brelse(bh);
-	}
-	return res;
-}
+	if (start >= npages)
+		start = 0;
+	n = start;
+	do {
+		char *kaddr;
+		page = ufs_get_page(dir, n);
+		if (!IS_ERR(page)) {
+			kaddr = page_address(page);
+			de = (struct ufs_dir_entry *) kaddr;
+			kaddr += ufs_last_byte(dir, n) - reclen;
+			while ((char *) de <= kaddr) {
+				if (de->d_reclen == 0) {
+					ufs_error(dir->i_sb, __FUNCTION__,
+						  "zero-length directory entry");
+					ufs_put_page(page);
+					goto out;
+				}
+				if (ufs_match(sb, namelen, name, de))
+					goto found;
+				de = ufs_next_entry(sb, de);
+			}
+			ufs_put_page(page);
+		}
+		if (++n >= npages)
+			n = 0;
+	} while (n != start);
+out:
+	return NULL;
 
-void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
-		struct buffer_head *bh, struct inode *inode)
-{
-	dir->i_version++;
-	de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
-	mark_buffer_dirty(bh);
-	if (IS_DIRSYNC(dir))
-		sync_dirty_buffer(bh);
-	brelse (bh);
+found:
+	*res_page = page;
+	ui->i_dir_start_lookup = n;
+	return de;
 }
 
 /*
- *	ufs_add_entry()
- *
- * adds a file entry to the specified directory, using the same
- * semantics as ufs_find_entry(). It returns NULL if it failed.
+ *	Parent is locked.
  */
 int ufs_add_link(struct dentry *dentry, struct inode *inode)
 {
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
-	unsigned long offset;
-	unsigned fragoff;
-	unsigned short rec_len;
-	struct buffer_head * bh;
-	struct ufs_dir_entry * de, * de1;
 	struct inode *dir = dentry->d_parent->d_inode;
 	const char *name = dentry->d_name.name;
 	int namelen = dentry->d_name.len;
+	struct super_block *sb = dir->i_sb;
+	unsigned reclen = UFS_DIR_REC_LEN(namelen);
+	unsigned short rec_len, name_len;
+	struct page *page = NULL;
+	struct ufs_dir_entry *de;
+	unsigned long npages = ufs_dir_pages(dir);
+	unsigned long n;
+	char *kaddr;
+	unsigned from, to;
 	int err;
 
-	UFSD(("ENTER, name %s, namelen %u\n", name, namelen))
-	
-	sb = dir->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
+	UFSD("ENTER, name %s, namelen %u\n", name, namelen);
 
-	if (!namelen)
-		return -EINVAL;
-	bh = ufs_bread (dir, 0, 0, &err);
-	if (!bh)
-		return err;
-	rec_len = UFS_DIR_REC_LEN(namelen);
-	offset = 0;
-	de = (struct ufs_dir_entry *) bh->b_data;
-	while (1) {
-		if ((char *)de >= UFS_SECTOR_SIZE + bh->b_data) {
-			fragoff = offset & ~uspi->s_fmask;
-			if (fragoff != 0 && fragoff != UFS_SECTOR_SIZE)
-				ufs_error (sb, "ufs_add_entry", "internal error"
-					" fragoff %u", fragoff);
-			if (!fragoff) {
-				brelse (bh);
-				bh = ufs_bread (dir, offset >> sb->s_blocksize_bits, 1, &err);
-				if (!bh)
-					return err;
-			}
-			if (dir->i_size <= offset) {
-				if (dir->i_size == 0) {
-					brelse(bh);
-					return -ENOENT;
-				}
-				de = (struct ufs_dir_entry *) (bh->b_data + fragoff);
-				de->d_ino = 0;
+	/*
+	 * We take care of directory expansion in the same loop.
+	 * This code plays outside i_size, so it locks the page
+	 * to protect that region.
+	 */
+	for (n = 0; n <= npages; n++) {
+		char *dir_end;
+
+		page = ufs_get_page(dir, n);
+		err = PTR_ERR(page);
+		if (IS_ERR(page))
+			goto out;
+		lock_page(page);
+		kaddr = page_address(page);
+		dir_end = kaddr + ufs_last_byte(dir, n);
+		de = (struct ufs_dir_entry *)kaddr;
+		kaddr += PAGE_CACHE_SIZE - reclen;
+		while ((char *)de <= kaddr) {
+			if ((char *)de == dir_end) {
+				/* We hit i_size */
+				name_len = 0;
+				rec_len = UFS_SECTOR_SIZE;
 				de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
-				ufs_set_de_namlen(sb, de, 0);
-				dir->i_size = offset + UFS_SECTOR_SIZE;
-				mark_inode_dirty(dir);
-			} else {
-				de = (struct ufs_dir_entry *) bh->b_data;
+				de->d_ino = 0;
+				goto got_it;
 			}
+			if (de->d_reclen == 0) {
+				ufs_error(dir->i_sb, __FUNCTION__,
+					  "zero-length directory entry");
+				err = -EIO;
+				goto out_unlock;
+			}
+			err = -EEXIST;
+			if (ufs_match(sb, namelen, name, de))
+				goto out_unlock;
+			name_len = UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de));
+			rec_len = fs16_to_cpu(sb, de->d_reclen);
+			if (!de->d_ino && rec_len >= reclen)
+				goto got_it;
+			if (rec_len >= name_len + reclen)
+				goto got_it;
+			de = (struct ufs_dir_entry *) ((char *) de + rec_len);
 		}
-		if (!ufs_check_dir_entry ("ufs_add_entry", dir, de, bh, offset)) {
-			brelse (bh);
-			return -ENOENT;
-		}
-		if (ufs_match(sb, namelen, name, de)) {
-			brelse (bh);
-			return -EEXIST;
-		}
-		if (de->d_ino == 0 && fs16_to_cpu(sb, de->d_reclen) >= rec_len)
-			break;
-			
-		if (fs16_to_cpu(sb, de->d_reclen) >=
-		     UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)) + rec_len)
-			break;
-		offset += fs16_to_cpu(sb, de->d_reclen);
-		de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen));
+		unlock_page(page);
+		ufs_put_page(page);
 	}
+	BUG();
+	return -EINVAL;
 
+got_it:
+	from = (char*)de - (char*)page_address(page);
+	to = from + rec_len;
+	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
+	if (err)
+		goto out_unlock;
 	if (de->d_ino) {
-		de1 = (struct ufs_dir_entry *) ((char *) de +
-			UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
-		de1->d_reclen =
-			cpu_to_fs16(sb, fs16_to_cpu(sb, de->d_reclen) -
-				UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
-		de->d_reclen =
-			cpu_to_fs16(sb, UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
+		struct ufs_dir_entry *de1 =
+			(struct ufs_dir_entry *) ((char *) de + name_len);
+		de1->d_reclen = cpu_to_fs16(sb, rec_len - name_len);
+		de->d_reclen = cpu_to_fs16(sb, name_len);
+
 		de = de1;
 	}
-	de->d_ino = 0;
+
 	ufs_set_de_namlen(sb, de, namelen);
-	memcpy (de->d_name, name, namelen + 1);
+	memcpy(de->d_name, name, namelen + 1);
 	de->d_ino = cpu_to_fs32(sb, inode->i_ino);
 	ufs_set_de_type(sb, de, inode->i_mode);
-	mark_buffer_dirty(bh);
-	if (IS_DIRSYNC(dir))
-		sync_dirty_buffer(bh);
-	brelse (bh);
-	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
-	dir->i_version++;
-	mark_inode_dirty(dir);
 
-	UFSD(("EXIT\n"))
+	err = ufs_commit_chunk(page, from, to);
+	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
+
+	mark_inode_dirty(dir);
+	/* OFFSET_CACHE */
+out_put:
+	ufs_put_page(page);
+out:
+	return err;
+out_unlock:
+	unlock_page(page);
+	goto out_put;
+}
+
+static inline unsigned
+ufs_validate_entry(struct super_block *sb, char *base,
+		   unsigned offset, unsigned mask)
+{
+	struct ufs_dir_entry *de = (struct ufs_dir_entry*)(base + offset);
+	struct ufs_dir_entry *p = (struct ufs_dir_entry*)(base + (offset&mask));
+	while ((char*)p < (char*)de) {
+		if (p->d_reclen == 0)
+			break;
+		p = ufs_next_entry(sb, p);
+	}
+	return (char *)p - base;
+}
+
+
+/*
+ * This is blatantly stolen from ext2fs
+ */
+static int
+ufs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+	loff_t pos = filp->f_pos;
+	struct inode *inode = filp->f_dentry->d_inode;
+	struct super_block *sb = inode->i_sb;
+	unsigned int offset = pos & ~PAGE_CACHE_MASK;
+	unsigned long n = pos >> PAGE_CACHE_SHIFT;
+	unsigned long npages = ufs_dir_pages(inode);
+	unsigned chunk_mask = ~(UFS_SECTOR_SIZE - 1);
+	int need_revalidate = filp->f_version != inode->i_version;
+	unsigned flags = UFS_SB(sb)->s_flags;
+
+	UFSD("BEGIN\n");
+
+	if (pos > inode->i_size - UFS_DIR_REC_LEN(1))
+		return 0;
+
+	for ( ; n < npages; n++, offset = 0) {
+		char *kaddr, *limit;
+		struct ufs_dir_entry *de;
+
+		struct page *page = ufs_get_page(inode, n);
+
+		if (IS_ERR(page)) {
+			ufs_error(sb, __FUNCTION__,
+				  "bad page in #%lu",
+				  inode->i_ino);
+			filp->f_pos += PAGE_CACHE_SIZE - offset;
+			return -EIO;
+		}
+		kaddr = page_address(page);
+		if (unlikely(need_revalidate)) {
+			if (offset) {
+				offset = ufs_validate_entry(sb, kaddr, offset, chunk_mask);
+				filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset;
+			}
+			filp->f_version = inode->i_version;
+			need_revalidate = 0;
+		}
+		de = (struct ufs_dir_entry *)(kaddr+offset);
+		limit = kaddr + ufs_last_byte(inode, n) - UFS_DIR_REC_LEN(1);
+		for ( ;(char*)de <= limit; de = ufs_next_entry(sb, de)) {
+			if (de->d_reclen == 0) {
+				ufs_error(sb, __FUNCTION__,
+					"zero-length directory entry");
+				ufs_put_page(page);
+				return -EIO;
+			}
+			if (de->d_ino) {
+				int over;
+				unsigned char d_type = DT_UNKNOWN;
+
+				offset = (char *)de - kaddr;
+
+				UFSD("filldir(%s,%u)\n", de->d_name,
+				      fs32_to_cpu(sb, de->d_ino));
+				UFSD("namlen %u\n", ufs_get_de_namlen(sb, de));
+
+				if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
+					d_type = de->d_u.d_44.d_type;
+
+				over = filldir(dirent, de->d_name,
+					       ufs_get_de_namlen(sb, de),
+						(n<<PAGE_CACHE_SHIFT) | offset,
+					       fs32_to_cpu(sb, de->d_ino), d_type);
+				if (over) {
+					ufs_put_page(page);
+					return 0;
+				}
+			}
+			filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
+		}
+		ufs_put_page(page);
+	}
 	return 0;
 }
 
+
 /*
  * ufs_delete_entry deletes a directory entry by merging it with the
  * previous entry.
  */
-int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir,
-	struct buffer_head * bh )
-	
+int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
+		     struct page * page)
 {
-	struct super_block * sb;
-	struct ufs_dir_entry * de, * pde;
-	unsigned i;
-	
-	UFSD(("ENTER\n"))
+	struct super_block *sb = inode->i_sb;
+	struct address_space *mapping = page->mapping;
+	char *kaddr = page_address(page);
+	unsigned from = ((char*)dir - kaddr) & ~(UFS_SECTOR_SIZE - 1);
+	unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen);
+	struct ufs_dir_entry *pde = NULL;
+	struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from);
+	int err;
 
-	sb = inode->i_sb;
-	i = 0;
-	pde = NULL;
-	de = (struct ufs_dir_entry *) bh->b_data;
-	
-	UFSD(("ino %u, reclen %u, namlen %u, name %s\n",
-		fs32_to_cpu(sb, de->d_ino),
-		fs16_to_cpu(sb, de->d_reclen),
-		ufs_get_de_namlen(sb, de), de->d_name))
+	UFSD("ENTER\n");
 
-	while (i < bh->b_size) {
-		if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) {
-			brelse(bh);
-			return -EIO;
+	UFSD("ino %u, reclen %u, namlen %u, name %s\n",
+	      fs32_to_cpu(sb, de->d_ino),
+	      fs16_to_cpu(sb, de->d_reclen),
+	      ufs_get_de_namlen(sb, de), de->d_name);
+
+	while ((char*)de < (char*)dir) {
+		if (de->d_reclen == 0) {
+			ufs_error(inode->i_sb, __FUNCTION__,
+				  "zero-length directory entry");
+			err = -EIO;
+			goto out;
 		}
-		if (de == dir)  {
-			if (pde)
-				fs16_add(sb, &pde->d_reclen,
-					fs16_to_cpu(sb, dir->d_reclen));
-			dir->d_ino = 0;
-			inode->i_version++;
-			inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
-			mark_inode_dirty(inode);
-			mark_buffer_dirty(bh);
-			if (IS_DIRSYNC(inode))
-				sync_dirty_buffer(bh);
-			brelse(bh);
-			UFSD(("EXIT\n"))
-			return 0;
-		}
-		i += fs16_to_cpu(sb, de->d_reclen);
-		if (i == UFS_SECTOR_SIZE) pde = NULL;
-		else pde = de;
-		de = (struct ufs_dir_entry *)
-		    ((char *) de + fs16_to_cpu(sb, de->d_reclen));
-		if (i == UFS_SECTOR_SIZE && de->d_reclen == 0)
-			break;
+		pde = de;
+		de = ufs_next_entry(sb, de);
 	}
-	UFSD(("EXIT\n"))
-	brelse(bh);
-	return -ENOENT;
+	if (pde)
+		from = (char*)pde - (char*)page_address(page);
+	lock_page(page);
+	err = mapping->a_ops->prepare_write(NULL, page, from, to);
+	BUG_ON(err);
+	if (pde)
+		pde->d_reclen = cpu_to_fs16(sb, to-from);
+	dir->d_ino = 0;
+	err = ufs_commit_chunk(page, from, to);
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+	mark_inode_dirty(inode);
+out:
+	ufs_put_page(page);
+	UFSD("EXIT\n");
+	return err;
 }
 
 int ufs_make_empty(struct inode * inode, struct inode *dir)
 {
 	struct super_block * sb = dir->i_sb;
-	struct buffer_head * dir_block;
+	struct address_space *mapping = inode->i_mapping;
+	struct page *page = grab_cache_page(mapping, 0);
 	struct ufs_dir_entry * de;
+	char *base;
 	int err;
 
-	dir_block = ufs_bread (inode, 0, 1, &err);
-	if (!dir_block)
-		return err;
+	if (!page)
+		return -ENOMEM;
+	kmap(page);
+	err = mapping->a_ops->prepare_write(NULL, page, 0, UFS_SECTOR_SIZE);
+	if (err) {
+		unlock_page(page);
+		goto fail;
+	}
 
-	inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;
-	de = (struct ufs_dir_entry *) dir_block->b_data;
+
+	base = (char*)page_address(page);
+	memset(base, 0, PAGE_CACHE_SIZE);
+
+	de = (struct ufs_dir_entry *) base;
+
 	de->d_ino = cpu_to_fs32(sb, inode->i_ino);
 	ufs_set_de_type(sb, de, inode->i_mode);
 	ufs_set_de_namlen(sb, de, 1);
@@ -552,72 +587,65 @@
 	de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
 	ufs_set_de_namlen(sb, de, 2);
 	strcpy (de->d_name, "..");
-	mark_buffer_dirty(dir_block);
-	brelse (dir_block);
-	mark_inode_dirty(inode);
-	return 0;
+
+	err = ufs_commit_chunk(page, 0, UFS_SECTOR_SIZE);
+fail:
+	kunmap(page);
+	page_cache_release(page);
+	return err;
 }
 
 /*
  * routine to check that the specified directory is empty (for rmdir)
  */
-int ufs_empty_dir (struct inode * inode)
+int ufs_empty_dir(struct inode * inode)
 {
-	struct super_block * sb;
-	unsigned long offset;
-	struct buffer_head * bh;
-	struct ufs_dir_entry * de, * de1;
-	int err;
-	
-	sb = inode->i_sb;
+	struct super_block *sb = inode->i_sb;
+	struct page *page = NULL;
+	unsigned long i, npages = ufs_dir_pages(inode);
 
-	if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||
-	    !(bh = ufs_bread (inode, 0, 0, &err))) {
-	    	ufs_warning (inode->i_sb, "empty_dir",
-			      "bad directory (dir #%lu) - no data block",
-			      inode->i_ino);
-		return 1;
-	}
-	de = (struct ufs_dir_entry *) bh->b_data;
-	de1 = (struct ufs_dir_entry *)
-		((char *)de + fs16_to_cpu(sb, de->d_reclen));
-	if (fs32_to_cpu(sb, de->d_ino) != inode->i_ino || de1->d_ino == 0 ||
-	     strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
-	    	ufs_warning (inode->i_sb, "empty_dir",
-			      "bad directory (dir #%lu) - no `.' or `..'",
-			      inode->i_ino);
-		return 1;
-	}
-	offset = fs16_to_cpu(sb, de->d_reclen) + fs16_to_cpu(sb, de1->d_reclen);
-	de = (struct ufs_dir_entry *)
-		((char *)de1 + fs16_to_cpu(sb, de1->d_reclen));
-	while (offset < inode->i_size ) {
-		if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
-			brelse (bh);
-			bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err);
-	 		if (!bh) {
-				ufs_error (sb, "empty_dir",
-					    "directory #%lu contains a hole at offset %lu",
-					    inode->i_ino, offset);
-				offset += sb->s_blocksize;
-				continue;
+	for (i = 0; i < npages; i++) {
+		char *kaddr;
+		struct ufs_dir_entry *de;
+		page = ufs_get_page(inode, i);
+
+		if (IS_ERR(page))
+			continue;
+
+		kaddr = page_address(page);
+		de = (struct ufs_dir_entry *)kaddr;
+		kaddr += ufs_last_byte(inode, i) - UFS_DIR_REC_LEN(1);
+
+		while ((char *)de <= kaddr) {
+			if (de->d_reclen == 0) {
+				ufs_error(inode->i_sb, __FUNCTION__,
+					"zero-length directory entry: "
+					"kaddr=%p, de=%p\n", kaddr, de);
+				goto not_empty;
 			}
-			de = (struct ufs_dir_entry *) bh->b_data;
+			if (de->d_ino) {
+				u16 namelen=ufs_get_de_namlen(sb, de);
+				/* check for . and .. */
+				if (de->d_name[0] != '.')
+					goto not_empty;
+				if (namelen > 2)
+					goto not_empty;
+				if (namelen < 2) {
+					if (inode->i_ino !=
+					    fs32_to_cpu(sb, de->d_ino))
+						goto not_empty;
+				} else if (de->d_name[1] != '.')
+					goto not_empty;
+			}
+			de = ufs_next_entry(sb, de);
 		}
-		if (!ufs_check_dir_entry ("empty_dir", inode, de, bh, offset)) {
-			brelse (bh);
-			return 1;
-		}
-		if (de->d_ino) {
-			brelse (bh);
-			return 0;
-		}
-		offset += fs16_to_cpu(sb, de->d_reclen);
-		de = (struct ufs_dir_entry *)
-			((char *)de + fs16_to_cpu(sb, de->d_reclen));
+		ufs_put_page(page);
 	}
-	brelse (bh);
 	return 1;
+
+not_empty:
+	ufs_put_page(page);
+	return 0;
 }
 
 const struct file_operations ufs_dir_operations = {
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 312fd3f..0e50015 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -25,6 +25,26 @@
 
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
+#include <linux/buffer_head.h>	/* for sync_mapping_buffers() */
+
+static int ufs_sync_file(struct file *file, struct dentry *dentry, int datasync)
+{
+	struct inode *inode = dentry->d_inode;
+	int err;
+	int ret;
+
+	ret = sync_mapping_buffers(inode->i_mapping);
+	if (!(inode->i_state & I_DIRTY))
+		return ret;
+	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
+		return ret;
+
+	err = ufs_sync_inode(inode);
+	if (ret == 0)
+		ret = err;
+	return ret;
+}
+
 
 /*
  * We have mostly NULL's here: the current defaults are ok for
@@ -37,6 +57,7 @@
 	.write		= generic_file_write,
 	.mmap		= generic_file_mmap,
 	.open           = generic_file_open,
+	.fsync		= ufs_sync_file,
 	.sendfile	= generic_file_sendfile,
 };
 
diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c
index c7a47ed..9501dcd 100644
--- a/fs/ufs/ialloc.c
+++ b/fs/ufs/ialloc.c
@@ -34,14 +34,6 @@
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_IALLOC_DEBUG
-
-#ifdef UFS_IALLOC_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
 /*
  * NOTE! When we get the inode, we're the only people
  * that have access to it, and as such there are no
@@ -68,7 +60,7 @@
 	int is_directory;
 	unsigned ino, cg, bit;
 	
-	UFSD(("ENTER, ino %lu\n", inode->i_ino))
+	UFSD("ENTER, ino %lu\n", inode->i_ino);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -91,7 +83,7 @@
 		unlock_super (sb);
 		return;
 	}
-	ucg = ubh_get_ucg(UCPI_UBH);
+	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg))
 		ufs_panic (sb, "ufs_free_fragments", "internal error, bad cg magic number");
 
@@ -104,33 +96,33 @@
 
 	clear_inode (inode);
 
-	if (ubh_isclr (UCPI_UBH, ucpi->c_iusedoff, bit))
+	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
 		ufs_error(sb, "ufs_free_inode", "bit already cleared for inode %u", ino);
 	else {
-		ubh_clrbit (UCPI_UBH, ucpi->c_iusedoff, bit);
+		ubh_clrbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
 		if (ino < ucpi->c_irotor)
 			ucpi->c_irotor = ino;
 		fs32_add(sb, &ucg->cg_cs.cs_nifree, 1);
-		fs32_add(sb, &usb1->fs_cstotal.cs_nifree, 1);
+		uspi->cs_total.cs_nifree++;
 		fs32_add(sb, &UFS_SB(sb)->fs_cs(cg).cs_nifree, 1);
 
 		if (is_directory) {
 			fs32_sub(sb, &ucg->cg_cs.cs_ndir, 1);
-			fs32_sub(sb, &usb1->fs_cstotal.cs_ndir, 1);
+			uspi->cs_total.cs_ndir--;
 			fs32_sub(sb, &UFS_SB(sb)->fs_cs(cg).cs_ndir, 1);
 		}
 	}
 
-	ubh_mark_buffer_dirty (USPI_UBH);
-	ubh_mark_buffer_dirty (UCPI_UBH);
+	ubh_mark_buffer_dirty (USPI_UBH(uspi));
+	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
-		ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **) &ucpi);
-		ubh_wait_on_buffer (UCPI_UBH);
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer (UCPI_UBH(ucpi));
 	}
 	
 	sb->s_dirt = 1;
 	unlock_super (sb);
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 }
 
 /*
@@ -155,7 +147,7 @@
 	unsigned cg, bit, i, j, start;
 	struct ufs_inode_info *ufsi;
 
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 	
 	/* Cannot create files in a deleted directory */
 	if (!dir || !dir->i_nlink)
@@ -213,43 +205,43 @@
 	ucpi = ufs_load_cylinder (sb, cg);
 	if (!ucpi)
 		goto failed;
-	ucg = ubh_get_ucg(UCPI_UBH);
+	ucg = ubh_get_ucg(UCPI_UBH(ucpi));
 	if (!ufs_cg_chkmagic(sb, ucg)) 
 		ufs_panic (sb, "ufs_new_inode", "internal error, bad cg magic number");
 
 	start = ucpi->c_irotor;
-	bit = ubh_find_next_zero_bit (UCPI_UBH, ucpi->c_iusedoff, uspi->s_ipg, start);
+	bit = ubh_find_next_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, uspi->s_ipg, start);
 	if (!(bit < uspi->s_ipg)) {
-		bit = ubh_find_first_zero_bit (UCPI_UBH, ucpi->c_iusedoff, start);
+		bit = ubh_find_first_zero_bit (UCPI_UBH(ucpi), ucpi->c_iusedoff, start);
 		if (!(bit < start)) {
 			ufs_error (sb, "ufs_new_inode",
 			    "cylinder group %u corrupted - error in inode bitmap\n", cg);
 			goto failed;
 		}
 	}
-	UFSD(("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg))
-	if (ubh_isclr (UCPI_UBH, ucpi->c_iusedoff, bit))
-		ubh_setbit (UCPI_UBH, ucpi->c_iusedoff, bit);
+	UFSD("start = %u, bit = %u, ipg = %u\n", start, bit, uspi->s_ipg);
+	if (ubh_isclr (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit))
+		ubh_setbit (UCPI_UBH(ucpi), ucpi->c_iusedoff, bit);
 	else {
 		ufs_panic (sb, "ufs_new_inode", "internal error");
 		goto failed;
 	}
 	
 	fs32_sub(sb, &ucg->cg_cs.cs_nifree, 1);
-	fs32_sub(sb, &usb1->fs_cstotal.cs_nifree, 1);
+	uspi->cs_total.cs_nifree--;
 	fs32_sub(sb, &sbi->fs_cs(cg).cs_nifree, 1);
 	
 	if (S_ISDIR(mode)) {
 		fs32_add(sb, &ucg->cg_cs.cs_ndir, 1);
-		fs32_add(sb, &usb1->fs_cstotal.cs_ndir, 1);
+		uspi->cs_total.cs_ndir++;
 		fs32_add(sb, &sbi->fs_cs(cg).cs_ndir, 1);
 	}
 
-	ubh_mark_buffer_dirty (USPI_UBH);
-	ubh_mark_buffer_dirty (UCPI_UBH);
+	ubh_mark_buffer_dirty (USPI_UBH(uspi));
+	ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
 	if (sb->s_flags & MS_SYNCHRONOUS) {
-		ubh_ll_rw_block (SWRITE, 1, (struct ufs_buffer_head **) &ucpi);
-		ubh_wait_on_buffer (UCPI_UBH);
+		ubh_ll_rw_block(SWRITE, UCPI_UBH(ucpi));
+		ubh_wait_on_buffer (UCPI_UBH(ucpi));
 	}
 	sb->s_dirt = 1;
 
@@ -272,6 +264,7 @@
 	ufsi->i_shadow = 0;
 	ufsi->i_osync = 0;
 	ufsi->i_oeftflag = 0;
+	ufsi->i_dir_start_lookup = 0;
 	memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1));
 
 	insert_inode_hash(inode);
@@ -287,14 +280,14 @@
 		return ERR_PTR(-EDQUOT);
 	}
 
-	UFSD(("allocating inode %lu\n", inode->i_ino))
-	UFSD(("EXIT\n"))
+	UFSD("allocating inode %lu\n", inode->i_ino);
+	UFSD("EXIT\n");
 	return inode;
 
 failed:
 	unlock_super (sb);
 	make_bad_inode(inode);
 	iput (inode);
-	UFSD(("EXIT (FAILED)\n"))
+	UFSD("EXIT (FAILED)\n");
 	return ERR_PTR(-ENOSPC);
 }
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index 3c3f62c..8e1f90e 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -41,14 +41,7 @@
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_INODE_DEBUG
-#undef UFS_INODE_DEBUG_MORE
-
-#ifdef UFS_INODE_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
+static u64 ufs_frag_map(struct inode *inode, sector_t frag);
 
 static int ufs_block_to_path(struct inode *inode, sector_t i_block, sector_t offsets[4])
 {
@@ -61,7 +54,7 @@
 	int n = 0;
 
 
-	UFSD(("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks));
+	UFSD("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks);
 	if (i_block < 0) {
 		ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0");
 	} else if (i_block < direct_blocks) {
@@ -89,7 +82,7 @@
  * the begining of the filesystem.
  */
 
-u64  ufs_frag_map(struct inode *inode, sector_t frag)
+static u64 ufs_frag_map(struct inode *inode, sector_t frag)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
 	struct super_block *sb = inode->i_sb;
@@ -104,8 +97,8 @@
 	unsigned flags = UFS_SB(sb)->s_flags;
 	u64 temp = 0L;
 
-	UFSD((": frag = %llu  depth = %d\n", (unsigned long long)frag, depth));
-	UFSD((": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask));
+	UFSD(": frag = %llu  depth = %d\n", (unsigned long long)frag, depth);
+	UFSD(": uspi->s_fpbshift = %d ,uspi->s_apbmask = %x, mask=%llx\n",uspi->s_fpbshift,uspi->s_apbmask,mask);
 
 	if (depth == 0)
 		return 0;
@@ -161,26 +154,64 @@
 	return ret;
 }
 
-static struct buffer_head * ufs_inode_getfrag (struct inode *inode,
-	unsigned int fragment, unsigned int new_fragment,
-	unsigned int required, int *err, int metadata, long *phys, int *new)
+static void ufs_clear_frag(struct inode *inode, struct buffer_head *bh)
+{
+	lock_buffer(bh);
+	memset(bh->b_data, 0, inode->i_sb->s_blocksize);
+	set_buffer_uptodate(bh);
+	mark_buffer_dirty(bh);
+	unlock_buffer(bh);
+	if (IS_SYNC(inode))
+		sync_dirty_buffer(bh);
+}
+
+static struct buffer_head *
+ufs_clear_frags(struct inode *inode, sector_t beg,
+		unsigned int n)
+{
+	struct buffer_head *res, *bh;
+	sector_t end = beg + n;
+
+	res = sb_getblk(inode->i_sb, beg);
+	ufs_clear_frag(inode, res);
+	for (++beg; beg < end; ++beg) {
+		bh = sb_getblk(inode->i_sb, beg);
+		ufs_clear_frag(inode, bh);
+		brelse(bh);
+	}
+	return res;
+}
+
+/**
+ * ufs_inode_getfrag() - allocate new fragment(s)
+ * @inode - pointer to inode
+ * @fragment - number of `fragment' which hold pointer
+ *   to new allocated fragment(s)
+ * @new_fragment - number of new allocated fragment(s)
+ * @required - how many fragment(s) we require
+ * @err - we set it if something wrong
+ * @phys - pointer to where we save physical number of new allocated fragments,
+ *   NULL if we allocate not data(indirect blocks for example).
+ * @new - we set it if we allocate new block
+ * @locked_page - for ufs_new_fragments()
+ */
+static struct buffer_head *
+ufs_inode_getfrag(struct inode *inode, unsigned int fragment,
+		  sector_t new_fragment, unsigned int required, int *err,
+		  long *phys, int *new, struct page *locked_page)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
+	struct super_block *sb = inode->i_sb;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct buffer_head * result;
 	unsigned block, blockoff, lastfrag, lastblock, lastblockoff;
 	unsigned tmp, goal;
 	__fs32 * p, * p2;
-	unsigned flags = 0;
 
-	UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u, required %u\n",
-		inode->i_ino, fragment, new_fragment, required))         
+	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, required %u, "
+	     "metadata %d\n", inode->i_ino, fragment,
+	     (unsigned long long)new_fragment, required, !phys);
 
-	sb = inode->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
-
-	flags = UFS_SB(sb)->s_flags;
         /* TODO : to be done for write support
         if ( (flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
              goto ufs2;
@@ -195,16 +226,16 @@
 	tmp = fs32_to_cpu(sb, *p);
 	lastfrag = ufsi->i_lastfrag;
 	if (tmp && fragment < lastfrag) {
-		if (metadata) {
+		if (!phys) {
 			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
 			if (tmp == fs32_to_cpu(sb, *p)) {
-				UFSD(("EXIT, result %u\n", tmp + blockoff))
+				UFSD("EXIT, result %u\n", tmp + blockoff);
 				return result;
 			}
 			brelse (result);
 			goto repeat;
 		} else {
-			*phys = tmp;
+			*phys = tmp + blockoff;
 			return NULL;
 		}
 	}
@@ -221,7 +252,8 @@
 		if (lastblockoff) {
 			p2 = ufsi->i_u1.i_data + lastblock;
 			tmp = ufs_new_fragments (inode, p2, lastfrag, 
-				fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff, err);
+						 fs32_to_cpu(sb, *p2), uspi->s_fpb - lastblockoff,
+						 err, locked_page);
 			if (!tmp) {
 				if (lastfrag != ufsi->i_lastfrag)
 					goto repeat;
@@ -233,14 +265,16 @@
 		}
 		goal = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock]) + uspi->s_fpb;
 		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
-			goal, required + blockoff, err);
+					 goal, required + blockoff,
+					 err, locked_page);
 	}
 	/*
 	 * We will extend last allocated block
 	 */
 	else if (lastblock == block) {
-		tmp = ufs_new_fragments (inode, p, fragment - (blockoff - lastblockoff),
-			fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff), err);
+		tmp = ufs_new_fragments(inode, p, fragment - (blockoff - lastblockoff),
+					fs32_to_cpu(sb, *p), required +  (blockoff - lastblockoff),
+					err, locked_page);
 	}
 	/*
 	 * We will allocate new block before last allocated block
@@ -248,8 +282,8 @@
 	else /* (lastblock > block) */ {
 		if (lastblock && (tmp = fs32_to_cpu(sb, ufsi->i_u1.i_data[lastblock-1])))
 			goal = tmp + uspi->s_fpb;
-		tmp = ufs_new_fragments (inode, p, fragment - blockoff, 
-			goal, uspi->s_fpb, err);
+		tmp = ufs_new_fragments(inode, p, fragment - blockoff,
+					goal, uspi->s_fpb, err, locked_page);
 	}
 	if (!tmp) {
 		if ((!blockoff && *p) || 
@@ -259,14 +293,10 @@
 		return NULL;
 	}
 
-	/* The nullification of framgents done in ufs/balloc.c is
-	 * something I don't have the stomache to move into here right
-	 * now. -DaveM
-	 */
-	if (metadata) {
-		result = sb_getblk(inode->i_sb, tmp + blockoff);
+	if (!phys) {
+		result = ufs_clear_frags(inode, tmp + blockoff, required);
 	} else {
-		*phys = tmp;
+		*phys = tmp + blockoff;
 		result = NULL;
 		*err = 0;
 		*new = 1;
@@ -276,7 +306,7 @@
 	if (IS_SYNC(inode))
 		ufs_sync_inode (inode);
 	mark_inode_dirty(inode);
-	UFSD(("EXIT, result %u\n", tmp + blockoff))
+	UFSD("EXIT, result %u\n", tmp + blockoff);
 	return result;
 
      /* This part : To be implemented ....
@@ -295,22 +325,35 @@
      */
 }
 
-static struct buffer_head * ufs_block_getfrag (struct inode *inode,
-	struct buffer_head *bh, unsigned int fragment, unsigned int new_fragment, 
-	unsigned int blocksize, int * err, int metadata, long *phys, int *new)
+/**
+ * ufs_inode_getblock() - allocate new block
+ * @inode - pointer to inode
+ * @bh - pointer to block which hold "pointer" to new allocated block
+ * @fragment - number of `fragment' which hold pointer
+ *   to new allocated block
+ * @new_fragment - number of new allocated fragment
+ *  (block will hold this fragment and also uspi->s_fpb-1)
+ * @err - see ufs_inode_getfrag()
+ * @phys - see ufs_inode_getfrag()
+ * @new - see ufs_inode_getfrag()
+ * @locked_page - see ufs_inode_getfrag()
+ */
+static struct buffer_head *
+ufs_inode_getblock(struct inode *inode, struct buffer_head *bh,
+		  unsigned int fragment, sector_t new_fragment, int *err,
+		  long *phys, int *new, struct page *locked_page)
 {
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
+	struct super_block *sb = inode->i_sb;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
 	struct buffer_head * result;
 	unsigned tmp, goal, block, blockoff;
 	__fs32 * p;
 
-	sb = inode->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
 	block = ufs_fragstoblks (fragment);
 	blockoff = ufs_fragnum (fragment);
 
-	UFSD(("ENTER, ino %lu, fragment %u, new_fragment %u\n", inode->i_ino, fragment, new_fragment))	
+	UFSD("ENTER, ino %lu, fragment %u, new_fragment %llu, metadata %d\n",
+	     inode->i_ino, fragment, (unsigned long long)new_fragment, !phys);
 
 	result = NULL;
 	if (!bh)
@@ -326,14 +369,14 @@
 repeat:
 	tmp = fs32_to_cpu(sb, *p);
 	if (tmp) {
-		if (metadata) {
+		if (!phys) {
 			result = sb_getblk(sb, uspi->s_sbbase + tmp + blockoff);
 			if (tmp == fs32_to_cpu(sb, *p))
 				goto out;
 			brelse (result);
 			goto repeat;
 		} else {
-			*phys = tmp;
+			*phys = tmp + blockoff;
 			goto out;
 		}
 	}
@@ -342,21 +385,19 @@
 		goal = tmp + uspi->s_fpb;
 	else
 		goal = bh->b_blocknr + uspi->s_fpb;
-	tmp = ufs_new_fragments (inode, p, ufs_blknum(new_fragment), goal, uspi->s_fpb, err);
+	tmp = ufs_new_fragments(inode, p, ufs_blknum(new_fragment), goal,
+				uspi->s_fpb, err, locked_page);
 	if (!tmp) {
 		if (fs32_to_cpu(sb, *p))
 			goto repeat;
 		goto out;
 	}		
 
-	/* The nullification of framgents done in ufs/balloc.c is
-	 * something I don't have the stomache to move into here right
-	 * now. -DaveM
-	 */
-	if (metadata) {
-		result = sb_getblk(sb, tmp + blockoff);
+
+	if (!phys) {
+		result = ufs_clear_frags(inode, tmp + blockoff, uspi->s_fpb);
 	} else {
-		*phys = tmp;
+		*phys = tmp + blockoff;
 		*new = 1;
 	}
 
@@ -365,18 +406,19 @@
 		sync_dirty_buffer(bh);
 	inode->i_ctime = CURRENT_TIME_SEC;
 	mark_inode_dirty(inode);
-	UFSD(("result %u\n", tmp + blockoff));
+	UFSD("result %u\n", tmp + blockoff);
 out:
 	brelse (bh);
-	UFSD(("EXIT\n"));
+	UFSD("EXIT\n");
 	return result;
 }
 
-/*
- * This function gets the block which contains the fragment.
+/**
+ * ufs_getfrag_bloc() - `get_block_t' function, interface between UFS and
+ * readpage, writepage and so on
  */
 
-int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
+int ufs_getfrag_block(struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create)
 {
 	struct super_block * sb = inode->i_sb;
 	struct ufs_sb_private_info * uspi = UFS_SB(sb)->s_uspi;
@@ -387,7 +429,7 @@
 	
 	if (!create) {
 		phys64 = ufs_frag_map(inode, fragment);
-		UFSD(("phys64 = %llu \n",phys64));
+		UFSD("phys64 = %llu \n",phys64);
 		if (phys64)
 			map_bh(bh_result, sb, phys64);
 		return 0;
@@ -402,7 +444,7 @@
 
 	lock_kernel();
 
-	UFSD(("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment))
+	UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment);
 	if (fragment < 0)
 		goto abort_negative;
 	if (fragment >
@@ -418,15 +460,15 @@
 	 * it much more readable:
 	 */
 #define GET_INODE_DATABLOCK(x) \
-		ufs_inode_getfrag(inode, x, fragment, 1, &err, 0, &phys, &new)
+	ufs_inode_getfrag(inode, x, fragment, 1, &err, &phys, &new, bh_result->b_page)
 #define GET_INODE_PTR(x) \
-		ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, 1, NULL, NULL)
+	ufs_inode_getfrag(inode, x, fragment, uspi->s_fpb, &err, NULL, NULL, bh_result->b_page)
 #define GET_INDIRECT_DATABLOCK(x) \
-		ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
-				  &err, 0, &phys, &new);
+	ufs_inode_getblock(inode, bh, x, fragment,	\
+			  &err, &phys, &new, bh_result->b_page);
 #define GET_INDIRECT_PTR(x) \
-		ufs_block_getfrag(inode, bh, x, fragment, sb->s_blocksize, \
-				  &err, 1, NULL, NULL);
+	ufs_inode_getblock(inode, bh, x, fragment,	\
+			  &err, NULL, NULL, bh_result->b_page);
 
 	if (ptr < UFS_NDIR_FRAGMENT) {
 		bh = GET_INODE_DATABLOCK(ptr);
@@ -474,8 +516,9 @@
 	goto abort;
 }
 
-struct buffer_head *ufs_getfrag(struct inode *inode, unsigned int fragment,
-				int create, int *err)
+static struct buffer_head *ufs_getfrag(struct inode *inode,
+				       unsigned int fragment,
+				       int create, int *err)
 {
 	struct buffer_head dummy;
 	int error;
@@ -502,7 +545,7 @@
 {
 	struct buffer_head * bh;
 
-	UFSD(("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment))
+	UFSD("ENTER, ino %lu, fragment %u\n", inode->i_ino, fragment);
 	bh = ufs_getfrag (inode, fragment, create, err);
 	if (!bh || buffer_uptodate(bh)) 		
 		return bh;
@@ -531,7 +574,7 @@
 {
 	return generic_block_bmap(mapping,block,ufs_getfrag_block);
 }
-struct address_space_operations ufs_aops = {
+const struct address_space_operations ufs_aops = {
 	.readpage = ufs_readpage,
 	.writepage = ufs_writepage,
 	.sync_page = block_sync_page,
@@ -540,39 +583,34 @@
 	.bmap = ufs_bmap
 };
 
-void ufs_read_inode (struct inode * inode)
+static void ufs_set_inode_ops(struct inode *inode)
+{
+	if (S_ISREG(inode->i_mode)) {
+		inode->i_op = &ufs_file_inode_operations;
+		inode->i_fop = &ufs_file_operations;
+		inode->i_mapping->a_ops = &ufs_aops;
+	} else if (S_ISDIR(inode->i_mode)) {
+		inode->i_op = &ufs_dir_inode_operations;
+		inode->i_fop = &ufs_dir_operations;
+		inode->i_mapping->a_ops = &ufs_aops;
+	} else if (S_ISLNK(inode->i_mode)) {
+		if (!inode->i_blocks)
+			inode->i_op = &ufs_fast_symlink_inode_operations;
+		else {
+			inode->i_op = &page_symlink_inode_operations;
+			inode->i_mapping->a_ops = &ufs_aops;
+		}
+	} else
+		init_special_inode(inode, inode->i_mode,
+				   ufs_get_inode_dev(inode->i_sb, UFS_I(inode)));
+}
+
+static void ufs1_read_inode(struct inode *inode, struct ufs_inode *ufs_inode)
 {
 	struct ufs_inode_info *ufsi = UFS_I(inode);
-	struct super_block * sb;
-	struct ufs_sb_private_info * uspi;
-	struct ufs_inode * ufs_inode;	
-	struct ufs2_inode *ufs2_inode;
-	struct buffer_head * bh;
+	struct super_block *sb = inode->i_sb;
 	mode_t mode;
 	unsigned i;
-	unsigned flags;
-	
-	UFSD(("ENTER, ino %lu\n", inode->i_ino))
-	
-	sb = inode->i_sb;
-	uspi = UFS_SB(sb)->s_uspi;
-	flags = UFS_SB(sb)->s_flags;
-
-	if (inode->i_ino < UFS_ROOTINO || 
-	    inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
-		ufs_warning (sb, "ufs_read_inode", "bad inode number (%lu)\n", inode->i_ino);
-		goto bad_inode;
-	}
-	
-	bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
-	if (!bh) {
-		ufs_warning (sb, "ufs_read_inode", "unable to read inode %lu\n", inode->i_ino);
-		goto bad_inode;
-	}
-	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
-		goto ufs2_inode;
-
-	ufs_inode = (struct ufs_inode *) (bh->b_data + sizeof(struct ufs_inode) * ufs_inotofsbo(inode->i_ino));
 
 	/*
 	 * Copy data to the in-core inode.
@@ -596,56 +634,29 @@
 	inode->i_atime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = fs32_to_cpu(sb, ufs_inode->ui_blocks);
-	inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat) */
-	inode->i_version++;
 	ufsi->i_flags = fs32_to_cpu(sb, ufs_inode->ui_flags);
 	ufsi->i_gen = fs32_to_cpu(sb, ufs_inode->ui_gen);
 	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
 	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
-	ufsi->i_lastfrag = (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
+
 	
 	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
 		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
 			ufsi->i_u1.i_data[i] = ufs_inode->ui_u2.ui_addr.ui_db[i];
-	}
-	else {
+	} else {
 		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
 			ufsi->i_u1.i_symlink[i] = ufs_inode->ui_u2.ui_symlink[i];
 	}
-	ufsi->i_osync = 0;
+}
 
-	if (S_ISREG(inode->i_mode)) {
-		inode->i_op = &ufs_file_inode_operations;
-		inode->i_fop = &ufs_file_operations;
-		inode->i_mapping->a_ops = &ufs_aops;
-	} else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &ufs_dir_inode_operations;
-		inode->i_fop = &ufs_dir_operations;
-	} else if (S_ISLNK(inode->i_mode)) {
-		if (!inode->i_blocks)
-			inode->i_op = &ufs_fast_symlink_inode_operations;
-		else {
-			inode->i_op = &page_symlink_inode_operations;
-			inode->i_mapping->a_ops = &ufs_aops;
-		}
-	} else
-		init_special_inode(inode, inode->i_mode,
-			ufs_get_inode_dev(sb, ufsi));
+static void ufs2_read_inode(struct inode *inode, struct ufs2_inode *ufs2_inode)
+{
+	struct ufs_inode_info *ufsi = UFS_I(inode);
+	struct super_block *sb = inode->i_sb;
+	mode_t mode;
+	unsigned i;
 
-	brelse (bh);
-
-	UFSD(("EXIT\n"))
-	return;
-
-bad_inode:
-	make_bad_inode(inode);
-	return;
-
-ufs2_inode :
-	UFSD(("Reading ufs2 inode, ino %lu\n", inode->i_ino))
-
-	ufs2_inode = (struct ufs2_inode *)(bh->b_data + sizeof(struct ufs2_inode) * ufs_inotofsbo(inode->i_ino));
-
+	UFSD("Reading ufs2 inode, ino %lu\n", inode->i_ino);
 	/*
 	 * Copy data to the in-core inode.
 	 */
@@ -668,50 +679,75 @@
 	inode->i_atime.tv_nsec = 0;
 	inode->i_ctime.tv_nsec = 0;
 	inode->i_blocks = fs64_to_cpu(sb, ufs2_inode->ui_blocks);
-	inode->i_blksize = PAGE_SIZE; /*This is the optimal IO size(for stat)*/
-
-	inode->i_version++;
 	ufsi->i_flags = fs32_to_cpu(sb, ufs2_inode->ui_flags);
 	ufsi->i_gen = fs32_to_cpu(sb, ufs2_inode->ui_gen);
 	/*
 	ufsi->i_shadow = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_shadow);
 	ufsi->i_oeftflag = fs32_to_cpu(sb, ufs_inode->ui_u3.ui_sun.ui_oeftflag);
 	*/
-	ufsi->i_lastfrag= (inode->i_size + uspi->s_fsize- 1) >> uspi->s_fshift;
 
 	if (S_ISCHR(mode) || S_ISBLK(mode) || inode->i_blocks) {
 		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR); i++)
 			ufsi->i_u1.u2_i_data[i] =
 				ufs2_inode->ui_u2.ui_addr.ui_db[i];
-	}
-	else {
+	} else {
 		for (i = 0; i < (UFS_NDADDR + UFS_NINDIR) * 4; i++)
 			ufsi->i_u1.i_symlink[i] = ufs2_inode->ui_u2.ui_symlink[i];
 	}
+}
+
+void ufs_read_inode(struct inode * inode)
+{
+	struct ufs_inode_info *ufsi = UFS_I(inode);
+	struct super_block * sb;
+	struct ufs_sb_private_info * uspi;
+	struct buffer_head * bh;
+
+	UFSD("ENTER, ino %lu\n", inode->i_ino);
+
+	sb = inode->i_sb;
+	uspi = UFS_SB(sb)->s_uspi;
+
+	if (inode->i_ino < UFS_ROOTINO ||
+	    inode->i_ino > (uspi->s_ncg * uspi->s_ipg)) {
+		ufs_warning(sb, "ufs_read_inode", "bad inode number (%lu)\n",
+			    inode->i_ino);
+		goto bad_inode;
+	}
+
+	bh = sb_bread(sb, uspi->s_sbbase + ufs_inotofsba(inode->i_ino));
+	if (!bh) {
+		ufs_warning(sb, "ufs_read_inode", "unable to read inode %lu\n",
+			    inode->i_ino);
+		goto bad_inode;
+	}
+	if ((UFS_SB(sb)->s_flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+		struct ufs2_inode *ufs2_inode = (struct ufs2_inode *)bh->b_data;
+
+		ufs2_read_inode(inode,
+				ufs2_inode + ufs_inotofsbo(inode->i_ino));
+	} else {
+		struct ufs_inode *ufs_inode = (struct ufs_inode *)bh->b_data;
+
+		ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
+	}
+
+	inode->i_blksize = PAGE_SIZE;/*This is the optimal IO size (for stat)*/
+	inode->i_version++;
+	ufsi->i_lastfrag =
+		(inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
+	ufsi->i_dir_start_lookup = 0;
 	ufsi->i_osync = 0;
 
-	if (S_ISREG(inode->i_mode)) {
-		inode->i_op = &ufs_file_inode_operations;
-		inode->i_fop = &ufs_file_operations;
-		inode->i_mapping->a_ops = &ufs_aops;
-	} else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &ufs_dir_inode_operations;
-		inode->i_fop = &ufs_dir_operations;
-	} else if (S_ISLNK(inode->i_mode)) {
-		if (!inode->i_blocks)
-			inode->i_op = &ufs_fast_symlink_inode_operations;
-		else {
-			inode->i_op = &page_symlink_inode_operations;
-			inode->i_mapping->a_ops = &ufs_aops;
-		}
-	} else   /* TODO  : here ...*/
-		init_special_inode(inode, inode->i_mode,
-			ufs_get_inode_dev(sb, ufsi));
+	ufs_set_inode_ops(inode);
 
 	brelse(bh);
 
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return;
+
+bad_inode:
+	make_bad_inode(inode);
 }
 
 static int ufs_update_inode(struct inode * inode, int do_sync)
@@ -724,7 +760,7 @@
 	unsigned i;
 	unsigned flags;
 
-	UFSD(("ENTER, ino %lu\n", inode->i_ino))
+	UFSD("ENTER, ino %lu\n", inode->i_ino);
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -785,7 +821,7 @@
 		sync_dirty_buffer(bh);
 	brelse (bh);
 	
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return 0;
 }
 
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 8d5f98a..abd5f23 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -1,6 +1,9 @@
 /*
  * linux/fs/ufs/namei.c
  *
+ * Migration to usage of "page cache" on May 2006 by
+ * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
+ *
  * Copyright (C) 1998
  * Daniel Pirkl <daniel.pirkl@email.cz>
  * Charles University, Faculty of Mathematics and Physics
@@ -28,21 +31,9 @@
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
 #include <linux/smp_lock.h>
-#include <linux/buffer_head.h>
 #include "swab.h"	/* will go away - see comment in mknod() */
 #include "util.h"
 
-/*
-#undef UFS_NAMEI_DEBUG
-*/
-#define UFS_NAMEI_DEBUG
-
-#ifdef UFS_NAMEI_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
 static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
 {
 	int err = ufs_add_link(dentry, inode);
@@ -88,8 +79,13 @@
 static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
 		struct nameidata *nd)
 {
-	struct inode * inode = ufs_new_inode(dir, mode);
-	int err = PTR_ERR(inode);
+	struct inode *inode;
+	int err;
+
+	UFSD("BEGIN\n");
+	inode = ufs_new_inode(dir, mode);
+	err = PTR_ERR(inode);
+
 	if (!IS_ERR(inode)) {
 		inode->i_op = &ufs_file_inode_operations;
 		inode->i_fop = &ufs_file_operations;
@@ -99,6 +95,7 @@
 		err = ufs_add_nondir(dentry, inode);
 		unlock_kernel();
 	}
+	UFSD("END: err=%d\n", err);
 	return err;
 }
 
@@ -205,6 +202,7 @@
 
 	inode->i_op = &ufs_dir_inode_operations;
 	inode->i_fop = &ufs_dir_operations;
+	inode->i_mapping->a_ops = &ufs_aops;
 
 	inode_inc_link_count(inode);
 
@@ -231,19 +229,18 @@
 	goto out;
 }
 
-static int ufs_unlink(struct inode * dir, struct dentry *dentry)
+static int ufs_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct inode * inode = dentry->d_inode;
-	struct buffer_head * bh;
-	struct ufs_dir_entry * de;
+	struct ufs_dir_entry *de;
+	struct page *page;
 	int err = -ENOENT;
 
-	lock_kernel();
-	de = ufs_find_entry (dentry, &bh);
+	de = ufs_find_entry(dir, dentry, &page);
 	if (!de)
 		goto out;
 
-	err = ufs_delete_entry (dir, de, bh);
+	err = ufs_delete_entry(dir, de, page);
 	if (err)
 		goto out;
 
@@ -251,7 +248,6 @@
 	inode_dec_link_count(inode);
 	err = 0;
 out:
-	unlock_kernel();
 	return err;
 }
 
@@ -273,42 +269,42 @@
 	return err;
 }
 
-static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
-	struct inode * new_dir,	struct dentry * new_dentry )
+static int ufs_rename(struct inode *old_dir, struct dentry *old_dentry,
+		      struct inode *new_dir, struct dentry *new_dentry)
 {
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
-	struct buffer_head *dir_bh = NULL;
-	struct ufs_dir_entry *dir_de = NULL;
-	struct buffer_head *old_bh;
+	struct page *dir_page = NULL;
+	struct ufs_dir_entry * dir_de = NULL;
+	struct page *old_page;
 	struct ufs_dir_entry *old_de;
 	int err = -ENOENT;
 
-	lock_kernel();
-	old_de = ufs_find_entry (old_dentry, &old_bh);
+	old_de = ufs_find_entry(old_dir, old_dentry, &old_page);
 	if (!old_de)
 		goto out;
 
 	if (S_ISDIR(old_inode->i_mode)) {
 		err = -EIO;
-		dir_de = ufs_dotdot(old_inode, &dir_bh);
+		dir_de = ufs_dotdot(old_inode, &dir_page);
 		if (!dir_de)
 			goto out_old;
 	}
 
 	if (new_inode) {
-		struct buffer_head *new_bh;
+		struct page *new_page;
 		struct ufs_dir_entry *new_de;
 
 		err = -ENOTEMPTY;
-		if (dir_de && !ufs_empty_dir (new_inode))
+		if (dir_de && !ufs_empty_dir(new_inode))
 			goto out_dir;
+
 		err = -ENOENT;
-		new_de = ufs_find_entry (new_dentry, &new_bh);
+		new_de = ufs_find_entry(new_dir, new_dentry, &new_page);
 		if (!new_de)
 			goto out_dir;
 		inode_inc_link_count(old_inode);
-		ufs_set_link(new_dir, new_de, new_bh, old_inode);
+		ufs_set_link(new_dir, new_de, new_page, old_inode);
 		new_inode->i_ctime = CURRENT_TIME_SEC;
 		if (dir_de)
 			new_inode->i_nlink--;
@@ -329,24 +325,32 @@
 			inode_inc_link_count(new_dir);
 	}
 
-	ufs_delete_entry (old_dir, old_de, old_bh);
+	/*
+	 * Like most other Unix systems, set the ctime for inodes on a
+ 	 * rename.
+	 * inode_dec_link_count() will mark the inode dirty.
+	 */
+	old_inode->i_ctime = CURRENT_TIME_SEC;
 
+	ufs_delete_entry(old_dir, old_de, old_page);
 	inode_dec_link_count(old_inode);
 
 	if (dir_de) {
-		ufs_set_link(old_inode, dir_de, dir_bh, new_dir);
+		ufs_set_link(old_inode, dir_de, dir_page, new_dir);
 		inode_dec_link_count(old_dir);
 	}
-	unlock_kernel();
 	return 0;
 
+
 out_dir:
-	if (dir_de)
-		brelse(dir_bh);
+	if (dir_de) {
+		kunmap(dir_page);
+		page_cache_release(dir_page);
+	}
 out_old:
-	brelse (old_bh);
+	kunmap(old_page);
+	page_cache_release(old_page);
 out:
-	unlock_kernel();
 	return err;
 }
 
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index db98a4c..74ef5e9 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -90,95 +90,84 @@
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_SUPER_DEBUG
-#undef UFS_SUPER_DEBUG_MORE
-
-
-#undef UFS_SUPER_DEBUG_MORE
-#ifdef UFS_SUPER_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
-#ifdef UFS_SUPER_DEBUG_MORE
+#ifdef CONFIG_UFS_DEBUG
 /*
  * Print contents of ufs_super_block, useful for debugging
  */
-void ufs_print_super_stuff(struct super_block *sb,
-	struct ufs_super_block_first * usb1,
-	struct ufs_super_block_second * usb2, 
-	struct ufs_super_block_third * usb3)
+static void ufs_print_super_stuff(struct super_block *sb, unsigned flags,
+				  struct ufs_super_block_first *usb1,
+				  struct ufs_super_block_second *usb2,
+				  struct ufs_super_block_third *usb3)
 {
 	printk("ufs_print_super_stuff\n");
-	printk("size of usb:     %u\n", sizeof(struct ufs_super_block));
-	printk("  magic:         0x%x\n", fs32_to_cpu(sb, usb3->fs_magic));
-	printk("  sblkno:        %u\n", fs32_to_cpu(sb, usb1->fs_sblkno));
-	printk("  cblkno:        %u\n", fs32_to_cpu(sb, usb1->fs_cblkno));
-	printk("  iblkno:        %u\n", fs32_to_cpu(sb, usb1->fs_iblkno));
-	printk("  dblkno:        %u\n", fs32_to_cpu(sb, usb1->fs_dblkno));
-	printk("  cgoffset:      %u\n", fs32_to_cpu(sb, usb1->fs_cgoffset));
-	printk("  ~cgmask:       0x%x\n", ~fs32_to_cpu(sb, usb1->fs_cgmask));
-	printk("  size:          %u\n", fs32_to_cpu(sb, usb1->fs_size));
-	printk("  dsize:         %u\n", fs32_to_cpu(sb, usb1->fs_dsize));
-	printk("  ncg:           %u\n", fs32_to_cpu(sb, usb1->fs_ncg));
-	printk("  bsize:         %u\n", fs32_to_cpu(sb, usb1->fs_bsize));
-	printk("  fsize:         %u\n", fs32_to_cpu(sb, usb1->fs_fsize));
-	printk("  frag:          %u\n", fs32_to_cpu(sb, usb1->fs_frag));
-	printk("  fragshift:     %u\n", fs32_to_cpu(sb, usb1->fs_fragshift));
-	printk("  ~fmask:        %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask));
-	printk("  fshift:        %u\n", fs32_to_cpu(sb, usb1->fs_fshift));
-	printk("  sbsize:        %u\n", fs32_to_cpu(sb, usb1->fs_sbsize));
-	printk("  spc:           %u\n", fs32_to_cpu(sb, usb1->fs_spc));
-	printk("  cpg:           %u\n", fs32_to_cpu(sb, usb1->fs_cpg));
-	printk("  ipg:           %u\n", fs32_to_cpu(sb, usb1->fs_ipg));
-	printk("  fpg:           %u\n", fs32_to_cpu(sb, usb1->fs_fpg));
-	printk("  csaddr:        %u\n", fs32_to_cpu(sb, usb1->fs_csaddr));
-	printk("  cssize:        %u\n", fs32_to_cpu(sb, usb1->fs_cssize));
-	printk("  cgsize:        %u\n", fs32_to_cpu(sb, usb1->fs_cgsize));
-	printk("  fstodb:        %u\n", fs32_to_cpu(sb, usb1->fs_fsbtodb));
-	printk("  contigsumsize: %d\n", fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_contigsumsize));
-	printk("  postblformat:  %u\n", fs32_to_cpu(sb, usb3->fs_postblformat));
-	printk("  nrpos:         %u\n", fs32_to_cpu(sb, usb3->fs_nrpos));
-	printk("  ndir           %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir));
-	printk("  nifree         %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree));
-	printk("  nbfree         %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree));
-	printk("  nffree         %u\n", fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree));
-	printk("\n");
-}
-
-/*
- * Print contents of ufs2 ufs_super_block, useful for debugging
- */
-void ufs2_print_super_stuff(
-     struct super_block *sb,
-      struct ufs_super_block *usb)
-{
-	printk("ufs_print_super_stuff\n");
-	printk("size of usb:     %u\n", sizeof(struct ufs_super_block));
-	printk("  magic:         0x%x\n", fs32_to_cpu(sb, usb->fs_magic));
-	printk("  fs_size:   %u\n",fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_size));
-	printk("  fs_dsize:  %u\n",fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize));
-	printk("  bsize:         %u\n", fs32_to_cpu(usb, usb->fs_bsize));
-	printk("  fsize:         %u\n", fs32_to_cpu(usb, usb->fs_fsize));
-	printk("  fs_volname:  %s\n", usb->fs_u11.fs_u2.fs_volname);
-	printk("  fs_fsmnt:  %s\n", usb->fs_u11.fs_u2.fs_fsmnt);
-	printk("  fs_sblockloc: %u\n",fs64_to_cpu(sb,
-			usb->fs_u11.fs_u2.fs_sblockloc));
-	printk("  cs_ndir(No of dirs):  %u\n",fs64_to_cpu(sb,
-			usb->fs_u11.fs_u2.fs_cstotal.cs_ndir));
-	printk("  cs_nbfree(No of free blocks):  %u\n",fs64_to_cpu(sb,
-			usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree));
+	printk("  magic:     0x%x\n", fs32_to_cpu(sb, usb3->fs_magic));
+	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+		printk("  fs_size:   %llu\n", (unsigned long long)
+		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size));
+		printk("  fs_dsize:  %llu\n", (unsigned long long)
+		       fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize));
+		printk("  bsize:         %u\n",
+		       fs32_to_cpu(sb, usb1->fs_bsize));
+		printk("  fsize:         %u\n",
+		       fs32_to_cpu(sb, usb1->fs_fsize));
+		printk("  fs_volname:  %s\n", usb2->fs_un.fs_u2.fs_volname);
+		printk("  fs_sblockloc: %llu\n", (unsigned long long)
+		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.fs_sblockloc));
+		printk("  cs_ndir(No of dirs):  %llu\n", (unsigned long long)
+		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir));
+		printk("  cs_nbfree(No of free blocks):  %llu\n",
+		       (unsigned long long)
+		       fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree));
+	} else {
+		printk(" sblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_sblkno));
+		printk(" cblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_cblkno));
+		printk(" iblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_iblkno));
+		printk(" dblkno:      %u\n", fs32_to_cpu(sb, usb1->fs_dblkno));
+		printk(" cgoffset:    %u\n",
+		       fs32_to_cpu(sb, usb1->fs_cgoffset));
+		printk(" ~cgmask:     0x%x\n",
+		       ~fs32_to_cpu(sb, usb1->fs_cgmask));
+		printk(" size:        %u\n", fs32_to_cpu(sb, usb1->fs_size));
+		printk(" dsize:       %u\n", fs32_to_cpu(sb, usb1->fs_dsize));
+		printk(" ncg:         %u\n", fs32_to_cpu(sb, usb1->fs_ncg));
+		printk(" bsize:       %u\n", fs32_to_cpu(sb, usb1->fs_bsize));
+		printk(" fsize:       %u\n", fs32_to_cpu(sb, usb1->fs_fsize));
+		printk(" frag:        %u\n", fs32_to_cpu(sb, usb1->fs_frag));
+		printk(" fragshift:   %u\n",
+		       fs32_to_cpu(sb, usb1->fs_fragshift));
+		printk(" ~fmask:      %u\n", ~fs32_to_cpu(sb, usb1->fs_fmask));
+		printk(" fshift:      %u\n", fs32_to_cpu(sb, usb1->fs_fshift));
+		printk(" sbsize:      %u\n", fs32_to_cpu(sb, usb1->fs_sbsize));
+		printk(" spc:         %u\n", fs32_to_cpu(sb, usb1->fs_spc));
+		printk(" cpg:         %u\n", fs32_to_cpu(sb, usb1->fs_cpg));
+		printk(" ipg:         %u\n", fs32_to_cpu(sb, usb1->fs_ipg));
+		printk(" fpg:         %u\n", fs32_to_cpu(sb, usb1->fs_fpg));
+		printk(" csaddr:      %u\n", fs32_to_cpu(sb, usb1->fs_csaddr));
+		printk(" cssize:      %u\n", fs32_to_cpu(sb, usb1->fs_cssize));
+		printk(" cgsize:      %u\n", fs32_to_cpu(sb, usb1->fs_cgsize));
+		printk(" fstodb:      %u\n",
+		       fs32_to_cpu(sb, usb1->fs_fsbtodb));
+		printk(" nrpos:       %u\n", fs32_to_cpu(sb, usb3->fs_nrpos));
+		printk(" ndir         %u\n",
+		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir));
+		printk(" nifree       %u\n",
+		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree));
+		printk(" nbfree       %u\n",
+		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree));
+		printk(" nffree       %u\n",
+		       fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree));
+	}
 	printk("\n");
 }
 
 /*
  * Print contents of ufs_cylinder_group, useful for debugging
  */
-void ufs_print_cylinder_stuff(struct super_block *sb, struct ufs_cylinder_group *cg)
+static void ufs_print_cylinder_stuff(struct super_block *sb,
+				     struct ufs_cylinder_group *cg)
 {
 	printk("\nufs_print_cylinder_stuff\n");
-	printk("size of ucg: %u\n", sizeof(struct ufs_cylinder_group));
+	printk("size of ucg: %zu\n", sizeof(struct ufs_cylinder_group));
 	printk("  magic:        %x\n", fs32_to_cpu(sb, cg->cg_magic));
 	printk("  time:         %u\n", fs32_to_cpu(sb, cg->cg_time));
 	printk("  cgx:          %u\n", fs32_to_cpu(sb, cg->cg_cgx));
@@ -202,12 +191,18 @@
 	printk("  iuseoff:      %u\n", fs32_to_cpu(sb, cg->cg_iusedoff));
 	printk("  freeoff:      %u\n", fs32_to_cpu(sb, cg->cg_freeoff));
 	printk("  nextfreeoff:  %u\n", fs32_to_cpu(sb, cg->cg_nextfreeoff));
-	printk("  clustersumoff %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff));
-	printk("  clusteroff    %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff));
-	printk("  nclusterblks  %u\n", fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks));
+	printk("  clustersumoff %u\n",
+	       fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clustersumoff));
+	printk("  clusteroff    %u\n",
+	       fs32_to_cpu(sb, cg->cg_u.cg_44.cg_clusteroff));
+	printk("  nclusterblks  %u\n",
+	       fs32_to_cpu(sb, cg->cg_u.cg_44.cg_nclusterblks));
 	printk("\n");
 }
-#endif /* UFS_SUPER_DEBUG_MORE */
+#else
+#  define ufs_print_super_stuff(sb, flags, usb1, usb2, usb3) /**/
+#  define ufs_print_cylinder_stuff(sb, cg) /**/
+#endif /* CONFIG_UFS_DEBUG */
 
 static struct super_operations ufs_super_ops;
 
@@ -225,7 +220,7 @@
 	
 	if (!(sb->s_flags & MS_RDONLY)) {
 		usb1->fs_clean = UFS_FSBAD;
-		ubh_mark_buffer_dirty(USPI_UBH);
+		ubh_mark_buffer_dirty(USPI_UBH(uspi));
 		sb->s_dirt = 1;
 		sb->s_flags |= MS_RDONLY;
 	}
@@ -257,7 +252,7 @@
 	
 	if (!(sb->s_flags & MS_RDONLY)) {
 		usb1->fs_clean = UFS_FSBAD;
-		ubh_mark_buffer_dirty(USPI_UBH);
+		ubh_mark_buffer_dirty(USPI_UBH(uspi));
 		sb->s_dirt = 1;
 	}
 	va_start (args, fmt);
@@ -309,7 +304,7 @@
 {
 	char * p;
 	
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 	
 	if (!options)
 		return 1;
@@ -386,27 +381,57 @@
 }
 
 /*
+ * Diffrent types of UFS hold fs_cstotal in different
+ * places, and use diffrent data structure for it.
+ * To make things simplier we just copy fs_cstotal to ufs_sb_private_info
+ */
+static void ufs_setup_cstotal(struct super_block *sb)
+{
+	struct ufs_sb_info *sbi = UFS_SB(sb);
+	struct ufs_sb_private_info *uspi = sbi->s_uspi;
+	struct ufs_super_block_first *usb1;
+	struct ufs_super_block_second *usb2;
+	struct ufs_super_block_third *usb3;
+	unsigned mtype = sbi->s_mount_opt & UFS_MOUNT_UFSTYPE;
+
+	UFSD("ENTER, mtype=%u\n", mtype);
+	usb1 = ubh_get_usb_first(uspi);
+	usb2 = ubh_get_usb_second(uspi);
+	usb3 = ubh_get_usb_third(uspi);
+
+	if ((mtype == UFS_MOUNT_UFSTYPE_44BSD &&
+	     (usb1->fs_flags & UFS_FLAGS_UPDATED)) ||
+	    mtype == UFS_MOUNT_UFSTYPE_UFS2) {
+		/*we have statistic in different place, then usual*/
+		uspi->cs_total.cs_ndir = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_ndir);
+		uspi->cs_total.cs_nbfree = fs64_to_cpu(sb, usb2->fs_un.fs_u2.cs_nbfree);
+		uspi->cs_total.cs_nifree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nifree);
+		uspi->cs_total.cs_nffree = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.cs_nffree);
+	} else {
+		uspi->cs_total.cs_ndir = fs32_to_cpu(sb, usb1->fs_cstotal.cs_ndir);
+		uspi->cs_total.cs_nbfree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree);
+		uspi->cs_total.cs_nifree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
+		uspi->cs_total.cs_nffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
+	}
+	UFSD("EXIT\n");
+}
+
+/*
  * Read on-disk structures associated with cylinder groups
  */
-static int ufs_read_cylinder_structures (struct super_block *sb)
+static int ufs_read_cylinder_structures(struct super_block *sb)
 {
-	struct ufs_sb_info * sbi = UFS_SB(sb);
-	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block *usb;
+	struct ufs_sb_info *sbi = UFS_SB(sb);
+	struct ufs_sb_private_info *uspi = sbi->s_uspi;
+	unsigned flags = sbi->s_flags;
 	struct ufs_buffer_head * ubh;
 	unsigned char * base, * space;
 	unsigned size, blks, i;
-	unsigned flags = 0;
-	
-	UFSD(("ENTER\n"))
-	
-	uspi = sbi->s_uspi;
+	struct ufs_super_block_third *usb3;
 
-	usb  = (struct ufs_super_block *)
-		((struct ufs_buffer_head *)uspi)->bh[0]->b_data;
+	UFSD("ENTER\n");
 
-        flags = UFS_SB(sb)->s_flags;
-	
+	usb3 = ubh_get_usb_third(uspi);
 	/*
 	 * Read cs structures from (usually) first data block
 	 * on the device. 
@@ -424,7 +449,7 @@
 
 		if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) 
 			ubh = ubh_bread(sb,
-				fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_csaddr) + i, size);
+				fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_csaddr) + i, size);
 		else 
 			ubh = ubh_bread(sb, uspi->s_csaddr + i, size);
 		
@@ -451,14 +476,13 @@
 		sbi->s_cgno[i] = UFS_CGNO_EMPTY;
 	}
 	for (i = 0; i < uspi->s_ncg; i++) {
-		UFSD(("read cg %u\n", i))
+		UFSD("read cg %u\n", i);
 		if (!(sbi->s_ucg[i] = sb_bread(sb, ufs_cgcmin(i))))
 			goto failed;
 		if (!ufs_cg_chkmagic (sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data))
 			goto failed;
-#ifdef UFS_SUPER_DEBUG_MORE
+
 		ufs_print_cylinder_stuff(sb, (struct ufs_cylinder_group *) sbi->s_ucg[i]->b_data);
-#endif
 	}
 	for (i = 0; i < UFS_MAX_GROUP_LOADED; i++) {
 		if (!(sbi->s_ucpi[i] = kmalloc (sizeof(struct ufs_cg_private_info), GFP_KERNEL)))
@@ -466,7 +490,7 @@
 		sbi->s_cgno[i] = UFS_CGNO_EMPTY;
 	}
 	sbi->s_cg_loaded = 0;
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return 1;
 
 failed:
@@ -479,26 +503,69 @@
 		for (i = 0; i < UFS_MAX_GROUP_LOADED; i++)
 			kfree (sbi->s_ucpi[i]);
 	}
-	UFSD(("EXIT (FAILED)\n"))
+	UFSD("EXIT (FAILED)\n");
 	return 0;
 }
 
 /*
- * Put on-disk structures associated with cylinder groups and 
- * write them back to disk
+ * Sync our internal copy of fs_cstotal with disk
  */
-static void ufs_put_cylinder_structures (struct super_block *sb)
+static void ufs_put_cstotal(struct super_block *sb)
 {
-	struct ufs_sb_info * sbi = UFS_SB(sb);
-	struct ufs_sb_private_info * uspi;
+	unsigned mtype = UFS_SB(sb)->s_mount_opt & UFS_MOUNT_UFSTYPE;
+	struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi;
+	struct ufs_super_block_first *usb1;
+	struct ufs_super_block_second *usb2;
+	struct ufs_super_block_third *usb3;
+
+	UFSD("ENTER\n");
+	usb1 = ubh_get_usb_first(uspi);
+	usb2 = ubh_get_usb_second(uspi);
+	usb3 = ubh_get_usb_third(uspi);
+
+	if ((mtype == UFS_MOUNT_UFSTYPE_44BSD &&
+	     (usb1->fs_flags & UFS_FLAGS_UPDATED)) ||
+	    mtype == UFS_MOUNT_UFSTYPE_UFS2) {
+		/*we have statistic in different place, then usual*/
+		usb2->fs_un.fs_u2.cs_ndir =
+			cpu_to_fs64(sb, uspi->cs_total.cs_ndir);
+		usb2->fs_un.fs_u2.cs_nbfree =
+			cpu_to_fs64(sb, uspi->cs_total.cs_nbfree);
+		usb3->fs_un1.fs_u2.cs_nifree =
+			cpu_to_fs64(sb, uspi->cs_total.cs_nifree);
+		usb3->fs_un1.fs_u2.cs_nffree =
+			cpu_to_fs64(sb, uspi->cs_total.cs_nffree);
+	} else {
+		usb1->fs_cstotal.cs_ndir =
+			cpu_to_fs32(sb, uspi->cs_total.cs_ndir);
+		usb1->fs_cstotal.cs_nbfree =
+			cpu_to_fs32(sb, uspi->cs_total.cs_nbfree);
+		usb1->fs_cstotal.cs_nifree =
+			cpu_to_fs32(sb, uspi->cs_total.cs_nifree);
+		usb1->fs_cstotal.cs_nffree =
+			cpu_to_fs32(sb, uspi->cs_total.cs_nffree);
+	}
+	ubh_mark_buffer_dirty(USPI_UBH(uspi));
+	UFSD("EXIT\n");
+}
+
+/**
+ * ufs_put_super_internal() - put on-disk intrenal structures
+ * @sb: pointer to super_block structure
+ * Put on-disk structures associated with cylinder groups
+ * and write them back to disk, also update cs_total on disk
+ */
+static void ufs_put_super_internal(struct super_block *sb)
+{
+	struct ufs_sb_info *sbi = UFS_SB(sb);
+	struct ufs_sb_private_info *uspi = sbi->s_uspi;
 	struct ufs_buffer_head * ubh;
 	unsigned char * base, * space;
 	unsigned blks, size, i;
-	
-	UFSD(("ENTER\n"))
-	
-	uspi = sbi->s_uspi;
 
+	
+	UFSD("ENTER\n");
+	ufs_put_cstotal(sb);
 	size = uspi->s_cssize;
 	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
 	base = space = (char*) sbi->s_csp;
@@ -523,7 +590,7 @@
 		brelse (sbi->s_ucg[i]);
 	kfree (sbi->s_ucg);
 	kfree (base);
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 }
 
 static int ufs_fill_super(struct super_block *sb, void *data, int silent)
@@ -533,7 +600,6 @@
 	struct ufs_super_block_first * usb1;
 	struct ufs_super_block_second * usb2;
 	struct ufs_super_block_third * usb3;
-	struct ufs_super_block *usb;
 	struct ufs_buffer_head * ubh;	
 	struct inode *inode;
 	unsigned block_size, super_block_size;
@@ -544,7 +610,7 @@
 	ubh = NULL;
 	flags = 0;
 	
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 		
 	sbi = kmalloc(sizeof(struct ufs_sb_info), GFP_KERNEL);
 	if (!sbi)
@@ -552,7 +618,7 @@
 	sb->s_fs_info = sbi;
 	memset(sbi, 0, sizeof(struct ufs_sb_info));
 
-	UFSD(("flag %u\n", (int)(sb->s_flags & MS_RDONLY)))
+	UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY));
 	
 #ifndef CONFIG_UFS_FS_WRITE
 	if (!(sb->s_flags & MS_RDONLY)) {
@@ -593,7 +659,7 @@
 	   the rules */
 	switch (sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) {
 	case UFS_MOUNT_UFSTYPE_44BSD:
-		UFSD(("ufstype=44bsd\n"))
+		UFSD("ufstype=44bsd\n");
 		uspi->s_fsize = block_size = 512;
 		uspi->s_fmask = ~(512 - 1);
 		uspi->s_fshift = 9;
@@ -602,7 +668,7 @@
 		flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
 		break;
 	case UFS_MOUNT_UFSTYPE_UFS2:
-		UFSD(("ufstype=ufs2\n"));
+		UFSD("ufstype=ufs2\n");
 		super_block_offset=SBLOCK_UFS2;
 		uspi->s_fsize = block_size = 512;
 		uspi->s_fmask = ~(512 - 1);
@@ -617,7 +683,7 @@
 		break;
 		
 	case UFS_MOUNT_UFSTYPE_SUN:
-		UFSD(("ufstype=sun\n"))
+		UFSD("ufstype=sun\n");
 		uspi->s_fsize = block_size = 1024;
 		uspi->s_fmask = ~(1024 - 1);
 		uspi->s_fshift = 10;
@@ -628,7 +694,7 @@
 		break;
 
 	case UFS_MOUNT_UFSTYPE_SUNx86:
-		UFSD(("ufstype=sunx86\n"))
+		UFSD("ufstype=sunx86\n");
 		uspi->s_fsize = block_size = 1024;
 		uspi->s_fmask = ~(1024 - 1);
 		uspi->s_fshift = 10;
@@ -639,7 +705,7 @@
 		break;
 
 	case UFS_MOUNT_UFSTYPE_OLD:
-		UFSD(("ufstype=old\n"))
+		UFSD("ufstype=old\n");
 		uspi->s_fsize = block_size = 1024;
 		uspi->s_fmask = ~(1024 - 1);
 		uspi->s_fshift = 10;
@@ -654,7 +720,7 @@
 		break;
 	
 	case UFS_MOUNT_UFSTYPE_NEXTSTEP:
-		UFSD(("ufstype=nextstep\n"))
+		UFSD("ufstype=nextstep\n");
 		uspi->s_fsize = block_size = 1024;
 		uspi->s_fmask = ~(1024 - 1);
 		uspi->s_fshift = 10;
@@ -669,7 +735,7 @@
 		break;
 	
 	case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD:
-		UFSD(("ufstype=nextstep-cd\n"))
+		UFSD("ufstype=nextstep-cd\n");
 		uspi->s_fsize = block_size = 2048;
 		uspi->s_fmask = ~(2048 - 1);
 		uspi->s_fshift = 11;
@@ -684,7 +750,7 @@
 		break;
 	
 	case UFS_MOUNT_UFSTYPE_OPENSTEP:
-		UFSD(("ufstype=openstep\n"))
+		UFSD("ufstype=openstep\n");
 		uspi->s_fsize = block_size = 1024;
 		uspi->s_fmask = ~(1024 - 1);
 		uspi->s_fshift = 10;
@@ -699,7 +765,7 @@
 		break;
 	
 	case UFS_MOUNT_UFSTYPE_HP:
-		UFSD(("ufstype=hp\n"))
+		UFSD("ufstype=hp\n");
 		uspi->s_fsize = block_size = 1024;
 		uspi->s_fmask = ~(1024 - 1);
 		uspi->s_fshift = 10;
@@ -737,8 +803,6 @@
 	usb1 = ubh_get_usb_first(uspi);
 	usb2 = ubh_get_usb_second(uspi);
 	usb3 = ubh_get_usb_third(uspi);
-	usb  = (struct ufs_super_block *)
-		((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
 
 	/*
 	 * Check ufs magic number
@@ -820,16 +884,12 @@
 		ubh = NULL;
 		block_size = uspi->s_fsize;
 		super_block_size = uspi->s_sbsize;
-		UFSD(("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size))
+		UFSD("another value of block_size or super_block_size %u, %u\n", block_size, super_block_size);
 		goto again;
 	}
 
-#ifdef UFS_SUPER_DEBUG_MORE
-        if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
-		ufs2_print_super_stuff(sb,usb);
-        else
-		ufs_print_super_stuff(sb, usb1, usb2, usb3);
-#endif
+
+	ufs_print_super_stuff(sb, flags, usb1, usb2, usb3);
 
 	/*
 	 * Check, if file system was correctly unmounted.
@@ -842,13 +902,13 @@
 	  (ufs_get_fs_state(sb, usb1, usb3) == (UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time))))) {
 		switch(usb1->fs_clean) {
 		case UFS_FSCLEAN:
-			UFSD(("fs is clean\n"))
+			UFSD("fs is clean\n");
 			break;
 		case UFS_FSSTABLE:
-			UFSD(("fs is stable\n"))
+			UFSD("fs is stable\n");
 			break;
 		case UFS_FSOSF1:
-			UFSD(("fs is DEC OSF/1\n"))
+			UFSD("fs is DEC OSF/1\n");
 			break;
 		case UFS_FSACTIVE:
 			printk("ufs_read_super: fs is active\n");
@@ -863,8 +923,7 @@
 			sb->s_flags |= MS_RDONLY;
 			break;
 		}
-	}
-	else {
+	} else {
 		printk("ufs_read_super: fs needs fsck\n");
 		sb->s_flags |= MS_RDONLY;
 	}
@@ -884,10 +943,9 @@
 	uspi->s_cgmask = fs32_to_cpu(sb, usb1->fs_cgmask);
 
 	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
-		uspi->s_u2_size  = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_size);
-		uspi->s_u2_dsize = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize);
-	}
-	else {
+		uspi->s_u2_size  = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_size);
+		uspi->s_u2_dsize = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize);
+	} else {
 		uspi->s_size  =  fs32_to_cpu(sb, usb1->fs_size);
 		uspi->s_dsize =  fs32_to_cpu(sb, usb1->fs_dsize);
 	}
@@ -901,8 +959,8 @@
 	uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask);
 	uspi->s_bshift = fs32_to_cpu(sb, usb1->fs_bshift);
 	uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift);
-	UFSD(("uspi->s_bshift = %d,uspi->s_fshift = %d", uspi->s_bshift,
-		uspi->s_fshift));
+	UFSD("uspi->s_bshift = %d,uspi->s_fshift = %d", uspi->s_bshift,
+		uspi->s_fshift);
 	uspi->s_fpbshift = fs32_to_cpu(sb, usb1->fs_fragshift);
 	uspi->s_fsbtodb = fs32_to_cpu(sb, usb1->fs_fsbtodb);
 	/* s_sbsize already set */
@@ -922,8 +980,8 @@
 	uspi->s_spc = fs32_to_cpu(sb, usb1->fs_spc);
 	uspi->s_ipg = fs32_to_cpu(sb, usb1->fs_ipg);
 	uspi->s_fpg = fs32_to_cpu(sb, usb1->fs_fpg);
-	uspi->s_cpc = fs32_to_cpu(sb, usb2->fs_cpc);
-	uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_contigsumsize);
+	uspi->s_cpc = fs32_to_cpu(sb, usb2->fs_un.fs_u1.fs_cpc);
+	uspi->s_contigsumsize = fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_contigsumsize);
 	uspi->s_qbmask = ufs_get_fs_qbmask(sb, usb3);
 	uspi->s_qfmask = ufs_get_fs_qfmask(sb, usb3);
 	uspi->s_postblformat = fs32_to_cpu(sb, usb3->fs_postblformat);
@@ -935,12 +993,11 @@
 	 * Compute another frequently used values
 	 */
 	uspi->s_fpbmask = uspi->s_fpb - 1;
-	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
+	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2)
 		uspi->s_apbshift = uspi->s_bshift - 3;
-	}
-	else {
+	else
 		uspi->s_apbshift = uspi->s_bshift - 2;
-	}
+
 	uspi->s_2apbshift = uspi->s_apbshift * 2;
 	uspi->s_3apbshift = uspi->s_apbshift * 3;
 	uspi->s_apb = 1 << uspi->s_apbshift;
@@ -956,7 +1013,7 @@
 	if ((sbi->s_mount_opt & UFS_MOUNT_UFSTYPE) ==
 	    UFS_MOUNT_UFSTYPE_44BSD)
 		uspi->s_maxsymlinklen =
-		    fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_maxsymlinklen);
+		    fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_maxsymlinklen);
 	
 	sbi->s_flags = flags;
 
@@ -967,7 +1024,7 @@
 	if (!sb->s_root)
 		goto dalloc_failed;
 
-
+	ufs_setup_cstotal(sb);
 	/*
 	 * Read cylinder group structures
 	 */
@@ -975,7 +1032,7 @@
 		if (!ufs_read_cylinder_structures(sb))
 			goto failed;
 
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return 0;
 
 dalloc_failed:
@@ -986,15 +1043,16 @@
 	kfree (uspi);
 	kfree(sbi);
 	sb->s_fs_info = NULL;
-	UFSD(("EXIT (FAILED)\n"))
+	UFSD("EXIT (FAILED)\n");
 	return -EINVAL;
 
 failed_nomem:
-	UFSD(("EXIT (NOMEM)\n"))
+	UFSD("EXIT (NOMEM)\n");
 	return -ENOMEM;
 }
 
-static void ufs_write_super (struct super_block *sb) {
+static void ufs_write_super(struct super_block *sb)
+{
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
 	struct ufs_super_block_third * usb3;
@@ -1002,7 +1060,7 @@
 
 	lock_kernel();
 
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 	flags = UFS_SB(sb)->s_flags;
 	uspi = UFS_SB(sb)->s_uspi;
 	usb1 = ubh_get_usb_first(uspi);
@@ -1014,26 +1072,27 @@
 		  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
 			ufs_set_fs_state(sb, usb1, usb3,
 					UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
-		ubh_mark_buffer_dirty (USPI_UBH);
+		ufs_put_cstotal(sb);
 	}
 	sb->s_dirt = 0;
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	unlock_kernel();
 }
 
-static void ufs_put_super (struct super_block *sb)
+static void ufs_put_super(struct super_block *sb)
 {
 	struct ufs_sb_info * sbi = UFS_SB(sb);
 		
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 
 	if (!(sb->s_flags & MS_RDONLY))
-		ufs_put_cylinder_structures (sb);
+		ufs_put_super_internal(sb);
 	
 	ubh_brelse_uspi (sbi->s_uspi);
 	kfree (sbi->s_uspi);
 	kfree (sbi);
 	sb->s_fs_info = NULL;
+	UFSD("EXIT\n");
 	return;
 }
 
@@ -1062,8 +1121,7 @@
 		return -EINVAL;
 	if (!(new_mount_opt & UFS_MOUNT_UFSTYPE)) {
 		new_mount_opt |= ufstype;
-	}
-	else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
+	} else if ((new_mount_opt & UFS_MOUNT_UFSTYPE) != ufstype) {
 		printk("ufstype can't be changed during remount\n");
 		return -EINVAL;
 	}
@@ -1077,20 +1135,19 @@
 	 * fs was mouted as rw, remounting ro
 	 */
 	if (*mount_flags & MS_RDONLY) {
-		ufs_put_cylinder_structures(sb);
+		ufs_put_super_internal(sb);
 		usb1->fs_time = cpu_to_fs32(sb, get_seconds());
 		if ((flags & UFS_ST_MASK) == UFS_ST_SUN
 		  || (flags & UFS_ST_MASK) == UFS_ST_SUNx86) 
 			ufs_set_fs_state(sb, usb1, usb3,
 				UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
-		ubh_mark_buffer_dirty (USPI_UBH);
+		ubh_mark_buffer_dirty (USPI_UBH(uspi));
 		sb->s_dirt = 0;
 		sb->s_flags |= MS_RDONLY;
-	}
+	} else {
 	/*
 	 * fs was mounted as ro, remounting rw
 	 */
-	else {
 #ifndef CONFIG_UFS_FS_WRITE
 		printk("ufs was compiled with read-only support, "
 		"can't be mounted as read-write\n");
@@ -1102,7 +1159,7 @@
 			printk("this ufstype is read-only supported\n");
 			return -EINVAL;
 		}
-		if (!ufs_read_cylinder_structures (sb)) {
+		if (!ufs_read_cylinder_structures(sb)) {
 			printk("failed during remounting\n");
 			return -EPERM;
 		}
@@ -1113,36 +1170,31 @@
 	return 0;
 }
 
-static int ufs_statfs (struct super_block *sb, struct kstatfs *buf)
+static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct ufs_sb_private_info * uspi;
-	struct ufs_super_block_first * usb1;
-	struct ufs_super_block * usb;
-	unsigned  flags = 0;
+	struct super_block *sb = dentry->d_sb;
+	struct ufs_sb_private_info *uspi= UFS_SB(sb)->s_uspi;
+	unsigned  flags = UFS_SB(sb)->s_flags;
+	struct ufs_super_block_first *usb1;
+	struct ufs_super_block_second *usb2;
+	struct ufs_super_block_third *usb3;
 
 	lock_kernel();
 
-	uspi = UFS_SB(sb)->s_uspi;
-	usb1 = ubh_get_usb_first (uspi);
-	usb  = (struct ufs_super_block *)
-		((struct ufs_buffer_head *)uspi)->bh[0]->b_data ;
+	usb1 = ubh_get_usb_first(uspi);
+	usb2 = ubh_get_usb_second(uspi);
+	usb3 = ubh_get_usb_third(uspi);
 	
-	flags = UFS_SB(sb)->s_flags;
 	if ((flags & UFS_TYPE_MASK) == UFS_TYPE_UFS2) {
 		buf->f_type = UFS2_MAGIC;
-		buf->f_blocks = fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_dsize);
-		buf->f_bfree = ufs_blkstofrags(fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nbfree)) +
-			fs64_to_cpu(sb, usb->fs_u11.fs_u2.fs_cstotal.cs_nffree);
-		buf->f_ffree = fs64_to_cpu(sb,
-        		usb->fs_u11.fs_u2.fs_cstotal.cs_nifree);
-	}
-	else {
+		buf->f_blocks = fs64_to_cpu(sb, usb3->fs_un1.fs_u2.fs_dsize);
+	} else {
 		buf->f_type = UFS_MAGIC;
 		buf->f_blocks = uspi->s_dsize;
-		buf->f_bfree = ufs_blkstofrags(fs32_to_cpu(sb, usb1->fs_cstotal.cs_nbfree)) +
-			fs32_to_cpu(sb, usb1->fs_cstotal.cs_nffree);
-		buf->f_ffree = fs32_to_cpu(sb, usb1->fs_cstotal.cs_nifree);
 	}
+	buf->f_bfree = ufs_blkstofrags(uspi->cs_total.cs_nbfree) +
+		uspi->cs_total.cs_nffree;
+	buf->f_ffree = uspi->cs_total.cs_nifree;
 	buf->f_bsize = sb->s_blocksize;
 	buf->f_bavail = (buf->f_bfree > (((long)buf->f_blocks / 100) * uspi->s_minfree))
 		? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0;
@@ -1311,10 +1363,10 @@
 
 #endif
 
-static struct super_block *ufs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int ufs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super, mnt);
 }
 
 static struct file_system_type ufs_fs_type = {
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 02e8629..3c3b301 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -49,14 +49,6 @@
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_TRUNCATE_DEBUG
-
-#ifdef UFS_TRUNCATE_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
- 
 /*
  * Secure deletion currently doesn't work. It interacts very badly
  * with buffers shared with memory mappings, and for that reason
@@ -82,7 +74,7 @@
 	unsigned i, tmp;
 	int retry;
 	
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -105,7 +97,7 @@
 		block2 = ufs_fragstoblks (frag3);
 	}
 
-	UFSD(("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4))
+	UFSD("frag1 %u, frag2 %u, block1 %u, block2 %u, frag3 %u, frag4 %u\n", frag1, frag2, block1, block2, frag3, frag4);
 
 	if (frag1 >= frag2)
 		goto next1;		
@@ -120,9 +112,8 @@
 	frag1 = ufs_fragnum (frag1);
 	frag2 = ufs_fragnum (frag2);
 
-	inode->i_blocks -= (frag2-frag1) << uspi->s_nspfshift;
-	mark_inode_dirty(inode);
 	ufs_free_fragments (inode, tmp + frag1, frag2 - frag1);
+	mark_inode_dirty(inode);
 	frag_to_free = tmp + frag1;
 
 next1:
@@ -136,8 +127,7 @@
 			continue;
 
 		*p = 0;
-		inode->i_blocks -= uspi->s_nspb;
-		mark_inode_dirty(inode);
+
 		if (free_count == 0) {
 			frag_to_free = tmp;
 			free_count = uspi->s_fpb;
@@ -148,6 +138,7 @@
 			frag_to_free = tmp;
 			free_count = uspi->s_fpb;
 		}
+		mark_inode_dirty(inode);
 	}
 	
 	if (free_count > 0)
@@ -166,12 +157,12 @@
 	frag4 = ufs_fragnum (frag4);
 
 	*p = 0;
-	inode->i_blocks -= frag4 << uspi->s_nspfshift;
-	mark_inode_dirty(inode);
+
 	ufs_free_fragments (inode, tmp, frag4);
+	mark_inode_dirty(inode);
  next3:
 
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return retry;
 }
 
@@ -186,7 +177,7 @@
 	unsigned frag_to_free, free_count;
 	int retry;
 
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 		
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -227,7 +218,7 @@
 			frag_to_free = tmp;
 			free_count = uspi->s_fpb;
 		}
-		inode->i_blocks -= uspi->s_nspb;
+
 		mark_inode_dirty(inode);
 	}
 
@@ -238,26 +229,21 @@
 		if (*ubh_get_addr32(ind_ubh,i))
 			break;
 	if (i >= uspi->s_apb) {
-		if (ubh_max_bcount(ind_ubh) != 1) {
-			retry = 1;
-		}
-		else {
-			tmp = fs32_to_cpu(sb, *p);
-			*p = 0;
-			inode->i_blocks -= uspi->s_nspb;
-			mark_inode_dirty(inode);
-			ufs_free_blocks (inode, tmp, uspi->s_fpb);
-			ubh_bforget(ind_ubh);
-			ind_ubh = NULL;
-		}
+		tmp = fs32_to_cpu(sb, *p);
+		*p = 0;
+
+		ufs_free_blocks (inode, tmp, uspi->s_fpb);
+		mark_inode_dirty(inode);
+		ubh_bforget(ind_ubh);
+		ind_ubh = NULL;
 	}
 	if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) {
-		ubh_ll_rw_block (SWRITE, 1, &ind_ubh);
+		ubh_ll_rw_block(SWRITE, ind_ubh);
 		ubh_wait_on_buffer (ind_ubh);
 	}
 	ubh_brelse (ind_ubh);
 	
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	
 	return retry;
 }
@@ -271,7 +257,7 @@
 	__fs32 * dind;
 	int retry = 0;
 	
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 	
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -306,25 +292,21 @@
 		if (*ubh_get_addr32 (dind_bh, i))
 			break;
 	if (i >= uspi->s_apb) {
-		if (ubh_max_bcount(dind_bh) != 1)
-			retry = 1;
-		else {
-			tmp = fs32_to_cpu(sb, *p);
-			*p = 0;
-			inode->i_blocks -= uspi->s_nspb;
-			mark_inode_dirty(inode);
-			ufs_free_blocks (inode, tmp, uspi->s_fpb);
-			ubh_bforget(dind_bh);
-			dind_bh = NULL;
-		}
+		tmp = fs32_to_cpu(sb, *p);
+		*p = 0;
+
+		ufs_free_blocks(inode, tmp, uspi->s_fpb);
+		mark_inode_dirty(inode);
+		ubh_bforget(dind_bh);
+		dind_bh = NULL;
 	}
 	if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) {
-		ubh_ll_rw_block (SWRITE, 1, &dind_bh);
+		ubh_ll_rw_block(SWRITE, dind_bh);
 		ubh_wait_on_buffer (dind_bh);
 	}
 	ubh_brelse (dind_bh);
 	
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	
 	return retry;
 }
@@ -339,7 +321,7 @@
 	__fs32 * tind, * p;
 	int retry;
 	
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
@@ -370,25 +352,21 @@
 		if (*ubh_get_addr32 (tind_bh, i))
 			break;
 	if (i >= uspi->s_apb) {
-		if (ubh_max_bcount(tind_bh) != 1)
-			retry = 1;
-		else {
-			tmp = fs32_to_cpu(sb, *p);
-			*p = 0;
-			inode->i_blocks -= uspi->s_nspb;
-			mark_inode_dirty(inode);
-			ufs_free_blocks (inode, tmp, uspi->s_fpb);
-			ubh_bforget(tind_bh);
-			tind_bh = NULL;
-		}
+		tmp = fs32_to_cpu(sb, *p);
+		*p = 0;
+
+		ufs_free_blocks(inode, tmp, uspi->s_fpb);
+		mark_inode_dirty(inode);
+		ubh_bforget(tind_bh);
+		tind_bh = NULL;
 	}
 	if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) {
-		ubh_ll_rw_block (SWRITE, 1, &tind_bh);
+		ubh_ll_rw_block(SWRITE, tind_bh);
 		ubh_wait_on_buffer (tind_bh);
 	}
 	ubh_brelse (tind_bh);
 	
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 	return retry;
 }
 		
@@ -399,7 +377,7 @@
 	struct ufs_sb_private_info * uspi;
 	int retry;
 	
-	UFSD(("ENTER\n"))
+	UFSD("ENTER\n");
 	sb = inode->i_sb;
 	uspi = UFS_SB(sb)->s_uspi;
 
@@ -430,5 +408,5 @@
 	ufsi->i_lastfrag = DIRECT_FRAGMENT;
 	unlock_kernel();
 	mark_inode_dirty(inode);
-	UFSD(("EXIT\n"))
+	UFSD("EXIT\n");
 }
diff --git a/fs/ufs/util.c b/fs/ufs/util.c
index 59acc8f..a2f13f4 100644
--- a/fs/ufs/util.c
+++ b/fs/ufs/util.c
@@ -14,15 +14,6 @@
 #include "swab.h"
 #include "util.h"
 
-#undef UFS_UTILS_DEBUG
-
-#ifdef UFS_UTILS_DEBUG
-#define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
-
 struct ufs_buffer_head * _ubh_bread_ (struct ufs_sb_private_info * uspi,
 	struct super_block *sb, u64 fragment, u64 size)
 {
@@ -63,17 +54,17 @@
 	count = size >> uspi->s_fshift;
 	if (count <= 0 || count > UFS_MAXFRAG)
 		return NULL;
-	USPI_UBH->fragment = fragment;
-	USPI_UBH->count = count;
+	USPI_UBH(uspi)->fragment = fragment;
+	USPI_UBH(uspi)->count = count;
 	for (i = 0; i < count; i++)
-		if (!(USPI_UBH->bh[i] = sb_bread(sb, fragment + i)))
+		if (!(USPI_UBH(uspi)->bh[i] = sb_bread(sb, fragment + i)))
 			goto failed;
 	for (; i < UFS_MAXFRAG; i++)
-		USPI_UBH->bh[i] = NULL;
-	return USPI_UBH;
+		USPI_UBH(uspi)->bh[i] = NULL;
+	return USPI_UBH(uspi);
 failed:
 	for (j = 0; j < i; j++)
-		brelse (USPI_UBH->bh[j]);
+		brelse (USPI_UBH(uspi)->bh[j]);
 	return NULL;
 }
 
@@ -90,11 +81,11 @@
 void ubh_brelse_uspi (struct ufs_sb_private_info * uspi)
 {
 	unsigned i;
-	if (!USPI_UBH)
+	if (!USPI_UBH(uspi))
 		return;
-	for ( i = 0; i < USPI_UBH->count; i++ ) {
-		brelse (USPI_UBH->bh[i]);
-		USPI_UBH->bh[i] = NULL;
+	for ( i = 0; i < USPI_UBH(uspi)->count; i++ ) {
+		brelse (USPI_UBH(uspi)->bh[i]);
+		USPI_UBH(uspi)->bh[i] = NULL;
 	}
 }
 
@@ -121,13 +112,12 @@
 	}
 }
 
-void ubh_ll_rw_block (int rw, unsigned nr, struct ufs_buffer_head * ubh[])
+void ubh_ll_rw_block(int rw, struct ufs_buffer_head *ubh)
 {
-	unsigned i;
 	if (!ubh)
 		return;
-	for ( i = 0; i < nr; i++ )
-		ll_rw_block (rw, ubh[i]->count, ubh[i]->bh);
+
+	ll_rw_block(rw, ubh->count, ubh->bh);
 }
 
 void ubh_wait_on_buffer (struct ufs_buffer_head * ubh)
@@ -139,18 +129,6 @@
 		wait_on_buffer (ubh->bh[i]);
 }
 
-unsigned ubh_max_bcount (struct ufs_buffer_head * ubh)
-{
-	unsigned i;
-	unsigned max = 0;
-	if (!ubh)
-		return 0;
-	for ( i = 0; i < ubh->count; i++ ) 
-		if ( atomic_read(&ubh->bh[i]->b_count) > max )
-			max = atomic_read(&ubh->bh[i]->b_count);
-	return max;
-}
-
 void ubh_bforget (struct ufs_buffer_head * ubh)
 {
 	unsigned i;
diff --git a/fs/ufs/util.h b/fs/ufs/util.h
index 48d6d9b..406981f 100644
--- a/fs/ufs/util.h
+++ b/fs/ufs/util.h
@@ -17,10 +17,16 @@
 #define in_range(b,first,len)	((b)>=(first)&&(b)<(first)+(len))
 
 /*
- * macros used for retyping
+ * functions used for retyping
  */
-#define UCPI_UBH ((struct ufs_buffer_head *)ucpi)
-#define USPI_UBH ((struct ufs_buffer_head *)uspi)
+static inline struct ufs_buffer_head *UCPI_UBH(struct ufs_cg_private_info *cpi)
+{
+	return &cpi->c_ubh;
+}
+static inline struct ufs_buffer_head *USPI_UBH(struct ufs_sb_private_info *spi)
+{
+	return &spi->s_ubh;
+}
 
 
 
@@ -33,12 +39,12 @@
 {
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		return fs32_to_cpu(sb, usb3->fs_u2.fs_sun.fs_state);
+		return fs32_to_cpu(sb, usb3->fs_un2.fs_sun.fs_state);
 	case UFS_ST_SUNx86:
 		return fs32_to_cpu(sb, usb1->fs_u1.fs_sunx86.fs_state);
 	case UFS_ST_44BSD:
 	default:
-		return fs32_to_cpu(sb, usb3->fs_u2.fs_44.fs_state);
+		return fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_state);
 	}
 }
 
@@ -48,13 +54,13 @@
 {
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		usb3->fs_u2.fs_sun.fs_state = cpu_to_fs32(sb, value);
+		usb3->fs_un2.fs_sun.fs_state = cpu_to_fs32(sb, value);
 		break;
 	case UFS_ST_SUNx86:
 		usb1->fs_u1.fs_sunx86.fs_state = cpu_to_fs32(sb, value);
 		break;
 	case UFS_ST_44BSD:
-		usb3->fs_u2.fs_44.fs_state = cpu_to_fs32(sb, value);
+		usb3->fs_un2.fs_44.fs_state = cpu_to_fs32(sb, value);
 		break;
 	}
 }
@@ -64,7 +70,7 @@
 		  struct ufs_super_block_third *usb3)
 {
 	if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
-		return fs32_to_cpu(sb, usb3->fs_u2.fs_sunx86.fs_npsect);
+		return fs32_to_cpu(sb, usb3->fs_un2.fs_sunx86.fs_npsect);
 	else
 		return fs32_to_cpu(sb, usb1->fs_u1.fs_sun.fs_npsect);
 }
@@ -76,16 +82,16 @@
 
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qbmask[0];
-		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qbmask[1];
 		break;
 	case UFS_ST_SUNx86:
-		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qbmask[0];
-		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sunx86.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sunx86.fs_qbmask[1];
 		break;
 	case UFS_ST_44BSD:
-		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qbmask[0];
-		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qbmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_44.fs_qbmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_44.fs_qbmask[1];
 		break;
 	}
 
@@ -99,16 +105,16 @@
 
 	switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
 	case UFS_ST_SUN:
-		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sun.fs_qfmask[0];
-		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sun.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qfmask[1];
 		break;
 	case UFS_ST_SUNx86:
-		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_sunx86.fs_qfmask[0];
-		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_sunx86.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sunx86.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sunx86.fs_qfmask[1];
 		break;
 	case UFS_ST_44BSD:
-		((__fs32 *)&tmp)[0] = usb3->fs_u2.fs_44.fs_qfmask[0];
-		((__fs32 *)&tmp)[1] = usb3->fs_u2.fs_44.fs_qfmask[1];
+		((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_44.fs_qfmask[0];
+		((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_44.fs_qfmask[1];
 		break;
 	}
 
@@ -236,9 +242,8 @@
 extern void ubh_brelse_uspi (struct ufs_sb_private_info *);
 extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *);
 extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int);
-extern void ubh_ll_rw_block (int, unsigned, struct ufs_buffer_head **);
+extern void ubh_ll_rw_block(int, struct ufs_buffer_head *);
 extern void ubh_wait_on_buffer (struct ufs_buffer_head *);
-extern unsigned ubh_max_bcount (struct ufs_buffer_head *);
 extern void ubh_bforget (struct ufs_buffer_head *);
 extern int  ubh_buffer_dirty (struct ufs_buffer_head *);
 #define ubh_ubhcpymem(mem,ubh,size) _ubh_ubhcpymem_(uspi,mem,ubh,size)
@@ -297,40 +302,26 @@
 #define ubh_blkmap(ubh,begin,bit) \
 	((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))
 
-
-/*
- * Macros for access to superblock array structures
- */
-#define ubh_postbl(ubh,cylno,i) \
-	((uspi->s_postblformat != UFS_DYNAMICPOSTBLFMT) \
-	? (*(__s16*)(ubh_get_addr(ubh, \
-	(unsigned)(&((struct ufs_super_block *)0)->fs_opostbl) \
-	+ (((cylno) * 16 + (i)) << 1) ) )) \
-	: (*(__s16*)(ubh_get_addr(ubh, \
-	uspi->s_postbloff + (((cylno) * uspi->s_nrpos + (i)) << 1) ))))
-
-#define ubh_rotbl(ubh,i) \
-	((uspi->s_postblformat != UFS_DYNAMICPOSTBLFMT) \
-	? (*(__u8*)(ubh_get_addr(ubh, \
-	(unsigned)(&((struct ufs_super_block *)0)->fs_space) + (i)))) \
-	: (*(__u8*)(ubh_get_addr(ubh, uspi->s_rotbloff + (i)))))
-
 /*
  * Determine the number of available frags given a
  * percentage to hold in reserve.
  */
-#define ufs_freespace(usb, percentreserved) \
-	(ufs_blkstofrags(fs32_to_cpu(sb, (usb)->fs_cstotal.cs_nbfree)) + \
-	fs32_to_cpu(sb, (usb)->fs_cstotal.cs_nffree) - (uspi->s_dsize * (percentreserved) / 100))
+static inline u64
+ufs_freespace(struct ufs_sb_private_info *uspi, int percentreserved)
+{
+	return ufs_blkstofrags(uspi->cs_total.cs_nbfree) +
+		uspi->cs_total.cs_nffree -
+		(uspi->s_dsize * (percentreserved) / 100);
+}
 
 /*
  * Macros to access cylinder group array structures
  */
 #define ubh_cg_blktot(ucpi,cylno) \
-	(*((__fs32*)ubh_get_addr(UCPI_UBH, (ucpi)->c_btotoff + ((cylno) << 2))))
+	(*((__fs32*)ubh_get_addr(UCPI_UBH(ucpi), (ucpi)->c_btotoff + ((cylno) << 2))))
 
 #define ubh_cg_blks(ucpi,cylno,rpos) \
-	(*((__fs16*)ubh_get_addr(UCPI_UBH, \
+	(*((__fs16*)ubh_get_addr(UCPI_UBH(ucpi), \
 	(ucpi)->c_boff + (((cylno) * uspi->s_nrpos + (rpos)) << 1 ))))
 
 /*
@@ -508,29 +499,3 @@
 	if (fragsize > 0 && fragsize < uspi->s_fpb)
 		fs32_add(sb, &fraglist[fragsize], cnt);
 }
-
-#define ubh_scanc(ubh,begin,size,table,mask) _ubh_scanc_(uspi,ubh,begin,size,table,mask)
-static inline unsigned _ubh_scanc_(struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh, 
-	unsigned begin, unsigned size, unsigned char * table, unsigned char mask)
-{
-	unsigned rest, offset;
-	unsigned char * cp;
-	
-
-	offset = begin & ~uspi->s_fmask;
-	begin >>= uspi->s_fshift;
-	for (;;) {
-		if ((offset + size) < uspi->s_fsize)
-			rest = size;
-		else
-			rest = uspi->s_fsize - offset;
-		size -= rest;
-		cp = ubh->bh[begin]->b_data + offset;
-		while ((table[*cp++] & mask) == 0 && --rest);
-		if (rest || !size)
-			break;
-		begin++;
-		offset = 0;
-	}
-	return (size + rest);
-}
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index a56cec3..9a8f48b 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -1023,11 +1023,12 @@
 	return 0;
 }
 
-static struct super_block *vfat_get_sb(struct file_system_type *fs_type,
-				       int flags, const char *dev_name,
-				       void *data)
+static int vfat_get_sb(struct file_system_type *fs_type,
+		       int flags, const char *dev_name,
+		       void *data, struct vfsmount *mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super,
+			   mnt);
 }
 
 static struct file_system_type vfat_fs_type = {
diff --git a/fs/xattr.c b/fs/xattr.c
index e416190..c32f15b 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -242,7 +242,7 @@
 	if (!f)
 		return error;
 	dentry = f->f_dentry;
-	audit_inode(NULL, dentry->d_inode, 0);
+	audit_inode(NULL, dentry->d_inode);
 	error = setxattr(dentry, name, value, size, flags);
 	fput(f);
 	return error;
@@ -469,7 +469,7 @@
 	if (!f)
 		return error;
 	dentry = f->f_dentry;
-	audit_inode(NULL, dentry->d_inode, 0);
+	audit_inode(NULL, dentry->d_inode);
 	error = removexattr(dentry, name);
 	fput(f);
 	return error;
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig
index bac27d6..26b364c 100644
--- a/fs/xfs/Kconfig
+++ b/fs/xfs/Kconfig
@@ -1,6 +1,5 @@
 config XFS_FS
 	tristate "XFS filesystem support"
-	select EXPORTFS if NFSD!=n
 	help
 	  XFS is a high performance journaling filesystem which originated
 	  on the SGI IRIX platform.  It is completely multi-threaded, can
@@ -18,11 +17,6 @@
 	  system of your root partition is compiled as a module, you'll need
 	  to use an initial ramdisk (initrd) to boot.
 
-config XFS_EXPORT
-	bool
-	depends on XFS_FS && EXPORTFS
-	default y
-
 config XFS_QUOTA
 	bool "XFS Quota support"
 	depends on XFS_FS
@@ -65,18 +59,19 @@
 	  If you don't know what Access Control Lists are, say N.
 
 config XFS_RT
-	bool "XFS Realtime support (EXPERIMENTAL)"
-	depends on XFS_FS && EXPERIMENTAL
+	bool "XFS Realtime subvolume support"
+	depends on XFS_FS
 	help
 	  If you say Y here you will be able to mount and use XFS filesystems
-	  which contain a realtime subvolume. The realtime subvolume is a
-	  separate area of disk space where only file data is stored. The
-	  realtime subvolume is designed to provide very deterministic
-	  data rates suitable for media streaming applications.
+	  which contain a realtime subvolume.  The realtime subvolume is a
+	  separate area of disk space where only file data is stored.  It was
+	  originally designed to provide deterministic data rates suitable
+	  for media streaming applications, but is also useful as a generic
+	  mechanism for ensuring data and metadata/log I/Os are completely
+	  separated.  Regular file I/Os are isolated to a separate device
+	  from all other requests, and this can be done quite transparently
+	  to applications via the inherit-realtime directory inode flag.
 
-	  See the xfs man page in section 5 for a bit more information.
-
-	  This feature is unsupported at this time, is not yet fully
-	  functional, and may cause serious problems.
+	  See the xfs man page in section 5 for additional information.
 
 	  If unsure, say N.
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6
index 5d73eaa..9e7f859 100644
--- a/fs/xfs/Makefile-linux-2.6
+++ b/fs/xfs/Makefile-linux-2.6
@@ -59,7 +59,6 @@
 xfs-$(CONFIG_PROC_FS)		+= $(XFS_LINUX)/xfs_stats.o
 xfs-$(CONFIG_SYSCTL)		+= $(XFS_LINUX)/xfs_sysctl.o
 xfs-$(CONFIG_COMPAT)		+= $(XFS_LINUX)/xfs_ioctl32.o
-xfs-$(CONFIG_XFS_EXPORT)	+= $(XFS_LINUX)/xfs_export.o
 
 
 xfs-y				+= xfs_alloc.o \
@@ -73,14 +72,12 @@
 				   xfs_btree.o \
 				   xfs_buf_item.o \
 				   xfs_da_btree.o \
-				   xfs_dir.o \
 				   xfs_dir2.o \
 				   xfs_dir2_block.o \
 				   xfs_dir2_data.o \
 				   xfs_dir2_leaf.o \
 				   xfs_dir2_node.o \
 				   xfs_dir2_sf.o \
-				   xfs_dir_leaf.o \
 				   xfs_error.o \
 				   xfs_extfree_item.o \
 				   xfs_fsops.o \
@@ -117,6 +114,7 @@
 				   kmem.o \
 				   xfs_aops.o \
 				   xfs_buf.o \
+				   xfs_export.o \
 				   xfs_file.o \
 				   xfs_fs_subr.o \
 				   xfs_globals.o \
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h
index 2cfd33d..939bd84 100644
--- a/fs/xfs/linux-2.6/kmem.h
+++ b/fs/xfs/linux-2.6/kmem.h
@@ -23,42 +23,6 @@
 #include <linux/mm.h>
 
 /*
- * Process flags handling
- */
-
-#define PFLAGS_TEST_NOIO()              (current->flags & PF_NOIO)
-#define PFLAGS_TEST_FSTRANS()           (current->flags & PF_FSTRANS)
-
-#define PFLAGS_SET_NOIO() do {		\
-	current->flags |= PF_NOIO;	\
-} while (0)
-
-#define PFLAGS_CLEAR_NOIO() do {	\
-	current->flags &= ~PF_NOIO;	\
-} while (0)
-
-/* these could be nested, so we save state */
-#define PFLAGS_SET_FSTRANS(STATEP) do {	\
-	*(STATEP) = current->flags;	\
-	current->flags |= PF_FSTRANS;	\
-} while (0)
-
-#define PFLAGS_CLEAR_FSTRANS(STATEP) do { \
-	*(STATEP) = current->flags;	\
-	current->flags &= ~PF_FSTRANS;	\
-} while (0)
-
-/* Restore the PF_FSTRANS state to what was saved in STATEP */
-#define PFLAGS_RESTORE_FSTRANS(STATEP) do {     		\
-	current->flags = ((current->flags & ~PF_FSTRANS) |	\
-			  (*(STATEP) & PF_FSTRANS));		\
-} while (0)
-
-#define PFLAGS_DUP(OSTATEP, NSTATEP) do { \
-	*(NSTATEP) = *(OSTATEP);	\
-} while (0)
-
-/*
  * General memory allocation interfaces
  */
 
@@ -83,7 +47,7 @@
 		lflags = GFP_ATOMIC | __GFP_NOWARN;
 	} else {
 		lflags = GFP_KERNEL | __GFP_NOWARN;
-		if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS))
+		if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS))
 			lflags &= ~__GFP_FS;
 	}
 	return lflags;
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h
index 1b262b7..32e1ce0 100644
--- a/fs/xfs/linux-2.6/mrlock.h
+++ b/fs/xfs/linux-2.6/mrlock.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
 } mrlock_t;
 
 #define mrinit(mrp, name)	\
-	( (mrp)->mr_writer = 0, init_rwsem(&(mrp)->mr_lock) )
+	do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0)
 #define mrlock_init(mrp, t,n,s)	mrinit(mrp, n)
 #define mrfree(mrp)		do { } while (0)
 #define mraccess(mrp)		mraccessf(mrp, 0)
diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h
index 194a844..b250900 100644
--- a/fs/xfs/linux-2.6/sema.h
+++ b/fs/xfs/linux-2.6/sema.h
@@ -34,20 +34,21 @@
 #define initnsema(sp, val, name)	sema_init(sp, val)
 #define psema(sp, b)			down(sp)
 #define vsema(sp)			up(sp)
-#define valusema(sp)			(atomic_read(&(sp)->count))
-#define freesema(sema)
+#define freesema(sema)			do { } while (0)
+
+static inline int issemalocked(sema_t *sp)
+{
+	return down_trylock(sp) || (up(sp), 0);
+}
 
 /*
  * Map cpsema (try to get the sema) to down_trylock. We need to switch
  * the return values since cpsema returns 1 (acquired) 0 (failed) and
  * down_trylock returns the reverse 0 (acquired) 1 (failed).
  */
-
-#define cpsema(sp)			(down_trylock(sp) ? 0 : 1)
-
-/*
- * Didn't do cvsema(sp). Not sure how to map this to up/down/...
- * It does a vsema if the values is < 0 other wise nothing.
- */
+static inline int cpsema(sema_t *sp)
+{
+	return down_trylock(sp) ? 0 : 1;
+}
 
 #endif /* __XFS_SUPPORT_SEMA_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 4d191ef..c40f81b 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -21,7 +21,6 @@
 #include "xfs_inum.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_trans.h"
 #include "xfs_dmapi.h"
@@ -29,7 +28,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -76,7 +74,7 @@
 	int		mask)
 {
 	xfs_inode_t	*ip;
-	vnode_t		*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 	loff_t		isize = i_size_read(inode);
 	loff_t		offset = page_offset(page);
 	int		delalloc = -1, unmapped = -1, unwritten = -1;
@@ -136,9 +134,10 @@
 
 	for (bh = ioend->io_buffer_head; bh; bh = next) {
 		next = bh->b_private;
-		bh->b_end_io(bh, ioend->io_uptodate);
+		bh->b_end_io(bh, !ioend->io_error);
 	}
-
+	if (unlikely(ioend->io_error))
+		vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__);
 	vn_iowake(ioend->io_vnode);
 	mempool_free(ioend, xfs_ioend_pool);
 }
@@ -180,13 +179,12 @@
 	void			*data)
 {
 	xfs_ioend_t		*ioend = data;
-	vnode_t			*vp = ioend->io_vnode;
+	bhv_vnode_t		*vp = ioend->io_vnode;
 	xfs_off_t		offset = ioend->io_offset;
 	size_t			size = ioend->io_size;
-	int			error;
 
-	if (ioend->io_uptodate)
-		VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error);
+	if (likely(!ioend->io_error))
+		bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL);
 	xfs_destroy_ioend(ioend);
 }
 
@@ -211,7 +209,7 @@
 	 * all the I/O from calling the completion routine too early.
 	 */
 	atomic_set(&ioend->io_remaining, 1);
-	ioend->io_uptodate = 1; /* cleared if any I/O fails */
+	ioend->io_error = 0;
 	ioend->io_list = NULL;
 	ioend->io_type = type;
 	ioend->io_vnode = vn_from_inode(inode);
@@ -239,10 +237,10 @@
 	xfs_iomap_t		*mapp,
 	int			flags)
 {
-	vnode_t			*vp = vn_from_inode(inode);
+	bhv_vnode_t		*vp = vn_from_inode(inode);
 	int			error, nmaps = 1;
 
-	VOP_BMAP(vp, offset, count, flags, mapp, &nmaps, error);
+	error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps);
 	if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE)))
 		VMODIFY(vp);
 	return -error;
@@ -271,16 +269,14 @@
 	if (bio->bi_size)
 		return 1;
 
-	ASSERT(ioend);
 	ASSERT(atomic_read(&bio->bi_cnt) >= 1);
+	ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error;
 
 	/* Toss bio and pass work off to an xfsdatad thread */
-	if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
-		ioend->io_uptodate = 0;
 	bio->bi_private = NULL;
 	bio->bi_end_io = NULL;
-
 	bio_put(bio);
+
 	xfs_finish_ioend(ioend);
 	return 0;
 }
@@ -1127,7 +1123,7 @@
 	 * then mark the page dirty again and leave the page
 	 * as is.
 	 */
-	if (PFLAGS_TEST_FSTRANS() && need_trans)
+	if (current_test_flags(PF_FSTRANS) && need_trans)
 		goto out_fail;
 
 	/*
@@ -1158,6 +1154,18 @@
 	return error;
 }
 
+STATIC int
+xfs_vm_writepages(
+	struct address_space	*mapping,
+	struct writeback_control *wbc)
+{
+	struct bhv_vnode	*vp = vn_from_inode(mapping->host);
+
+	if (VN_TRUNC(vp))
+		VUNTRUNCATE(vp);
+	return generic_writepages(mapping, wbc);
+}
+
 /*
  * Called to move a page into cleanable state - and from there
  * to be released. Possibly the page is already clean. We always
@@ -1204,7 +1212,7 @@
 	/* If we are already inside a transaction or the thread cannot
 	 * do I/O, we cannot release this page.
 	 */
-	if (PFLAGS_TEST_FSTRANS())
+	if (current_test_flags(PF_FSTRANS))
 		return 0;
 
 	/*
@@ -1231,7 +1239,7 @@
 	int			direct,
 	bmapi_flags_t		flags)
 {
-	vnode_t			*vp = vn_from_inode(inode);
+	bhv_vnode_t		*vp = vn_from_inode(inode);
 	xfs_iomap_t		iomap;
 	xfs_off_t		offset;
 	ssize_t			size;
@@ -1241,8 +1249,8 @@
 	offset = (xfs_off_t)iblock << inode->i_blkbits;
 	ASSERT(bh_result->b_size >= (1 << inode->i_blkbits));
 	size = bh_result->b_size;
-	VOP_BMAP(vp, offset, size,
-		create ? flags : BMAPI_READ, &iomap, &niomap, error);
+	error = bhv_vop_bmap(vp, offset, size,
+			     create ? flags : BMAPI_READ, &iomap, &niomap);
 	if (error)
 		return -error;
 	if (niomap == 0)
@@ -1370,13 +1378,13 @@
 {
 	struct file	*file = iocb->ki_filp;
 	struct inode	*inode = file->f_mapping->host;
-	vnode_t		*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 	xfs_iomap_t	iomap;
 	int		maps = 1;
 	int		error;
 	ssize_t		ret;
 
-	VOP_BMAP(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps, error);
+	error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps);
 	if (error)
 		return -error;
 
@@ -1409,14 +1417,12 @@
 	sector_t		block)
 {
 	struct inode		*inode = (struct inode *)mapping->host;
-	vnode_t			*vp = vn_from_inode(inode);
-	int			error;
+	bhv_vnode_t		*vp = vn_from_inode(inode);
 
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
-
-	VOP_RWLOCK(vp, VRWLOCK_READ);
-	VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error);
-	VOP_RWUNLOCK(vp, VRWLOCK_READ);
+	bhv_vop_rwlock(vp, VRWLOCK_READ);
+	bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
+	bhv_vop_rwunlock(vp, VRWLOCK_READ);
 	return generic_block_bmap(mapping, block, xfs_get_blocks);
 }
 
@@ -1448,10 +1454,11 @@
 	block_invalidatepage(page, offset);
 }
 
-struct address_space_operations xfs_address_space_operations = {
+const struct address_space_operations xfs_address_space_operations = {
 	.readpage		= xfs_vm_readpage,
 	.readpages		= xfs_vm_readpages,
 	.writepage		= xfs_vm_writepage,
+	.writepages		= xfs_vm_writepages,
 	.sync_page		= block_sync_page,
 	.releasepage		= xfs_vm_releasepage,
 	.invalidatepage		= xfs_vm_invalidatepage,
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h
index 6071654..2244e51 100644
--- a/fs/xfs/linux-2.6/xfs_aops.h
+++ b/fs/xfs/linux-2.6/xfs_aops.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005 Silicon Graphics, Inc.
+ * Copyright (c) 2005-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -30,9 +30,9 @@
 typedef struct xfs_ioend {
 	struct xfs_ioend	*io_list;	/* next ioend in chain */
 	unsigned int		io_type;	/* delalloc / unwritten */
-	unsigned int		io_uptodate;	/* I/O status register */
+	int			io_error;	/* I/O error code */
 	atomic_t		io_remaining;	/* hold count */
-	struct vnode		*io_vnode;	/* file being written to */
+	struct bhv_vnode	*io_vnode;	/* file being written to */
 	struct buffer_head	*io_buffer_head;/* buffer linked list head */
 	struct buffer_head	*io_buffer_tail;/* buffer linked list tail */
 	size_t			io_size;	/* size of the extent */
@@ -40,7 +40,7 @@
 	struct work_struct	io_work;	/* xfsdatad work queue */
 } xfs_ioend_t;
 
-extern struct address_space_operations xfs_address_space_operations;
+extern const struct address_space_operations xfs_address_space_operations;
 extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int);
 
-#endif /* __XFS_IOPS_H__ */
+#endif /* __XFS_AOPS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 26fed07..2af528d 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -1520,7 +1520,7 @@
 	struct backing_dev_info	*bdi;
 	struct inode		*inode;
 	struct address_space	*mapping;
-	static struct address_space_operations mapping_aops = {
+	static const struct address_space_operations mapping_aops = {
 		.sync_page = block_sync_page,
 		.migratepage = fail_migrate_page,
 	};
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index b768ea9..5fb75d9 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -21,7 +21,6 @@
 #include "xfs_log.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_mount.h"
 #include "xfs_export.h"
 
@@ -97,7 +96,7 @@
 	int			len;
 	int			is64 = 0;
 #if XFS_BIG_INUMS
-	vfs_t			*vfs = vfs_from_sb(inode->i_sb);
+	bhv_vfs_t		*vfs = vfs_from_sb(inode->i_sb);
 
 	if (!(vfs->vfs_flag & VFS_32BITINODES)) {
 		/* filesystem may contain 64bit inode numbers */
@@ -136,13 +135,13 @@
 	struct super_block	*sb,
 	void			*data)
 {
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	struct inode		*inode;
 	struct dentry		*result;
-	vfs_t			*vfsp = vfs_from_sb(sb);
+	bhv_vfs_t		*vfsp = vfs_from_sb(sb);
 	int			error;
 
-	VFS_VGET(vfsp, &vp, (fid_t *)data, error);
+	error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data);
 	if (error || vp == NULL)
 		return ERR_PTR(-ESTALE) ;
 
@@ -160,12 +159,12 @@
 	struct dentry		*child)
 {
 	int			error;
-	vnode_t			*vp, *cvp;
+	bhv_vnode_t		*vp, *cvp;
 	struct dentry		*parent;
 
 	cvp = NULL;
 	vp = vn_from_inode(child->d_inode);
-	VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error);
+	error = bhv_vop_lookup(vp, &dotdot, &cvp, 0, NULL, NULL);
 	if (unlikely(error))
 		return ERR_PTR(-error);
 
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index c847416..3d4f6df 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -21,7 +21,6 @@
 #include "xfs_inum.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_trans.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_alloc.h"
 #include "xfs_btree.h"
 #include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
@@ -58,15 +56,12 @@
 {
 	struct iovec		iov = {buf, count};
 	struct file		*file = iocb->ki_filp;
-	vnode_t			*vp = vn_from_inode(file->f_dentry->d_inode);
-	ssize_t			rval;
+	bhv_vnode_t		*vp = vn_from_inode(file->f_dentry->d_inode);
 
 	BUG_ON(iocb->ki_pos != pos);
-
 	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
-	VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
-	return rval;
+	return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
 }
 
 STATIC ssize_t
@@ -100,15 +95,12 @@
 	struct iovec	iov = {(void __user *)buf, count};
 	struct file	*file = iocb->ki_filp;
 	struct inode	*inode = file->f_mapping->host;
-	vnode_t		*vp = vn_from_inode(inode);
-	ssize_t		rval;
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 
 	BUG_ON(iocb->ki_pos != pos);
 	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
-
-	VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval);
-	return rval;
+	return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL);
 }
 
 STATIC ssize_t
@@ -140,7 +132,7 @@
 	loff_t			*ppos)
 {
 	struct inode	*inode = file->f_mapping->host;
-	vnode_t		*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 	struct kiocb	kiocb;
 	ssize_t		rval;
 
@@ -149,7 +141,8 @@
 
 	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
-	VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
+	rval = bhv_vop_read(vp, &kiocb, iov, nr_segs,
+				&kiocb.ki_pos, ioflags, NULL);
 
 	*ppos = kiocb.ki_pos;
 	return rval;
@@ -184,7 +177,7 @@
 	loff_t			*ppos)
 {
 	struct inode	*inode = file->f_mapping->host;
-	vnode_t		*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 	struct kiocb	kiocb;
 	ssize_t		rval;
 
@@ -193,7 +186,8 @@
 	if (unlikely(file->f_flags & O_DIRECT))
 		ioflags |= IO_ISDIRECT;
 
-	VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval);
+	rval = bhv_vop_write(vp, &kiocb, iov, nr_segs,
+				 &kiocb.ki_pos, ioflags, NULL);
 
 	*ppos = kiocb.ki_pos;
 	return rval;
@@ -227,11 +221,8 @@
 	read_actor_t		actor,
 	void			*target)
 {
-	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
-	ssize_t			rval;
-
-	VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval);
-	return rval;
+	return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
+				filp, pos, 0, count, actor, target, NULL);
 }
 
 STATIC ssize_t
@@ -242,11 +233,8 @@
 	read_actor_t		actor,
 	void			*target)
 {
-	vnode_t			*vp = vn_from_inode(filp->f_dentry->d_inode);
-	ssize_t			rval;
-
-	VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval);
-	return rval;
+	return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode),
+				filp, pos, IO_INVIS, count, actor, target, NULL);
 }
 
 STATIC ssize_t
@@ -257,11 +245,8 @@
 	size_t			len,
 	unsigned int		flags)
 {
-	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
-	ssize_t			rval;
-
-	VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval);
-	return rval;
+	return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
+				   infilp, ppos, pipe, len, flags, 0, NULL);
 }
 
 STATIC ssize_t
@@ -272,11 +257,9 @@
 	size_t			len,
 	unsigned int		flags)
 {
-	vnode_t			*vp = vn_from_inode(infilp->f_dentry->d_inode);
-	ssize_t			rval;
-
-	VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval);
-	return rval;
+	return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode),
+				   infilp, ppos, pipe, len, flags, IO_INVIS,
+				   NULL);
 }
 
 STATIC ssize_t
@@ -287,11 +270,8 @@
 	size_t			len,
 	unsigned int		flags)
 {
-	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
-	ssize_t			rval;
-
-	VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval);
-	return rval;
+	return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
+				    pipe, outfilp, ppos, len, flags, 0, NULL);
 }
 
 STATIC ssize_t
@@ -302,11 +282,9 @@
 	size_t			len,
 	unsigned int		flags)
 {
-	vnode_t			*vp = vn_from_inode(outfilp->f_dentry->d_inode);
-	ssize_t			rval;
-
-	VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval);
-	return rval;
+	return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode),
+				    pipe, outfilp, ppos, len, flags, IO_INVIS,
+				    NULL);
 }
 
 STATIC int
@@ -314,13 +292,18 @@
 	struct inode	*inode,
 	struct file	*filp)
 {
-	vnode_t		*vp = vn_from_inode(inode);
-	int		error;
-
 	if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
 		return -EFBIG;
-	VOP_OPEN(vp, NULL, error);
-	return -error;
+	return -bhv_vop_open(vn_from_inode(inode), NULL);
+}
+
+STATIC int
+xfs_file_close(
+	struct file	*filp,
+	fl_owner_t	id)
+{
+	return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0,
+				file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL);
 }
 
 STATIC int
@@ -328,12 +311,11 @@
 	struct inode	*inode,
 	struct file	*filp)
 {
-	vnode_t		*vp = vn_from_inode(inode);
-	int		error = 0;
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 
 	if (vp)
-		VOP_RELEASE(vp, error);
-	return -error;
+		return -bhv_vop_release(vp);
+	return 0;
 }
 
 STATIC int
@@ -342,15 +324,14 @@
 	struct dentry	*dentry,
 	int		datasync)
 {
-	struct inode	*inode = dentry->d_inode;
-	vnode_t		*vp = vn_from_inode(inode);
-	int		error;
+	bhv_vnode_t	*vp = vn_from_inode(dentry->d_inode);
 	int		flags = FSYNC_WAIT;
 
 	if (datasync)
 		flags |= FSYNC_DATA;
-	VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error);
-	return -error;
+	if (VN_TRUNC(vp))
+		VUNTRUNCATE(vp);
+	return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1);
 }
 
 #ifdef CONFIG_XFS_DMAPI
@@ -361,16 +342,11 @@
 	int			*type)
 {
 	struct inode	*inode = area->vm_file->f_dentry->d_inode;
-	vnode_t		*vp = vn_from_inode(inode);
-	xfs_mount_t	*mp = XFS_VFSTOM(vp->v_vfsp);
-	int		error;
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 
 	ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI);
-
-	error = XFS_SEND_MMAP(mp, area, 0);
-	if (error)
+	if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0))
 		return NULL;
-
 	return filemap_nopage(area, address, type);
 }
 #endif /* CONFIG_XFS_DMAPI */
@@ -382,7 +358,7 @@
 	filldir_t	filldir)
 {
 	int		error = 0;
-	vnode_t		*vp = vn_from_inode(filp->f_dentry->d_inode);
+	bhv_vnode_t	*vp = vn_from_inode(filp->f_dentry->d_inode);
 	uio_t		uio;
 	iovec_t		iov;
 	int		eof = 0;
@@ -417,7 +393,7 @@
 
 		start_offset = uio.uio_offset;
 
-		VOP_READDIR(vp, &uio, NULL, &eof, error);
+		error = bhv_vop_readdir(vp, &uio, NULL, &eof);
 		if ((uio.uio_offset == start_offset) || error) {
 			size = 0;
 			break;
@@ -456,38 +432,28 @@
 	struct file	*filp,
 	struct vm_area_struct *vma)
 {
-	struct inode	*ip = filp->f_dentry->d_inode;
-	vnode_t		*vp = vn_from_inode(ip);
-	vattr_t		vattr;
-	int		error;
-
 	vma->vm_ops = &xfs_file_vm_ops;
 
 #ifdef CONFIG_XFS_DMAPI
-	if (vp->v_vfsp->vfs_flag & VFS_DMI) {
+	if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI)
 		vma->vm_ops = &xfs_dmapi_file_vm_ops;
-	}
 #endif /* CONFIG_XFS_DMAPI */
 
-	vattr.va_mask = XFS_AT_UPDATIME;
-	VOP_SETATTR(vp, &vattr, XFS_AT_UPDATIME, NULL, error);
-	if (likely(!error))
-		__vn_revalidate(vp, &vattr);	/* update flags */
+	file_accessed(filp);
 	return 0;
 }
 
-
 STATIC long
 xfs_file_ioctl(
 	struct file	*filp,
 	unsigned int	cmd,
-	unsigned long	arg)
+	unsigned long	p)
 {
 	int		error;
 	struct inode	*inode = filp->f_dentry->d_inode;
-	vnode_t		*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 
-	VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error);
+	error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p);
 	VMODIFY(vp);
 
 	/* NOTE:  some of the ioctl's return positive #'s as a
@@ -503,13 +469,13 @@
 xfs_file_ioctl_invis(
 	struct file	*filp,
 	unsigned int	cmd,
-	unsigned long	arg)
+	unsigned long	p)
 {
-	struct inode	*inode = filp->f_dentry->d_inode;
-	vnode_t		*vp = vn_from_inode(inode);
 	int		error;
+	struct inode	*inode = filp->f_dentry->d_inode;
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 
-	VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error);
+	error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p);
 	VMODIFY(vp);
 
 	/* NOTE:  some of the ioctl's return positive #'s as a
@@ -528,7 +494,7 @@
 	struct vm_area_struct *vma,
 	unsigned int	newflags)
 {
-	vnode_t		*vp = vn_from_inode(vma->vm_file->f_dentry->d_inode);
+	bhv_vnode_t	*vp = vn_from_inode(vma->vm_file->f_dentry->d_inode);
 	int		error = 0;
 
 	if (vp->v_vfsp->vfs_flag & VFS_DMI) {
@@ -554,24 +520,19 @@
 xfs_file_open_exec(
 	struct inode	*inode)
 {
-	vnode_t		*vp = vn_from_inode(inode);
-	xfs_mount_t	*mp = XFS_VFSTOM(vp->v_vfsp);
-	int		error = 0;
-	xfs_inode_t	*ip;
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 
-	if (vp->v_vfsp->vfs_flag & VFS_DMI) {
-		ip = xfs_vtoi(vp);
-		if (!ip) {
-			error = -EINVAL;
-			goto open_exec_out;
-		}
-		if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) {
-			error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
+	if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) {
+		xfs_mount_t	*mp = XFS_VFSTOM(vp->v_vfsp);
+		xfs_inode_t	*ip = xfs_vtoi(vp);
+
+		if (!ip)
+			return -EINVAL;
+		if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ))
+			return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp,
 					       0, 0, 0, NULL);
-		}
 	}
-open_exec_out:
-	return error;
+	return 0;
 }
 #endif /* HAVE_FOP_OPEN_EXEC */
 
@@ -592,6 +553,7 @@
 #endif
 	.mmap		= xfs_file_mmap,
 	.open		= xfs_file_open,
+	.flush		= xfs_file_close,
 	.release	= xfs_file_release,
 	.fsync		= xfs_file_fsync,
 #ifdef HAVE_FOP_OPEN_EXEC
@@ -616,6 +578,7 @@
 #endif
 	.mmap		= xfs_file_mmap,
 	.open		= xfs_file_open,
+	.flush		= xfs_file_close,
 	.release	= xfs_file_release,
 	.fsync		= xfs_file_fsync,
 };
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c
index 575f2a7..dc05628 100644
--- a/fs/xfs/linux-2.6/xfs_fs_subr.c
+++ b/fs/xfs/linux-2.6/xfs_fs_subr.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2002,2005-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -15,40 +15,12 @@
  * along with this program; if not, write the Free Software Foundation,
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-
 #include "xfs.h"
 
-/*
- * Stub for no-op vnode operations that return error status.
- */
-int
-fs_noerr(void)
-{
-	return 0;
-}
+int  fs_noerr(void) { return 0; }
+int  fs_nosys(void) { return ENOSYS; }
+void fs_noval(void) { return; }
 
-/*
- * Operation unsupported under this file system.
- */
-int
-fs_nosys(void)
-{
-	return ENOSYS;
-}
-
-/*
- * Stub for inactive, strategy, and read/write lock/unlock.  Does nothing.
- */
-/* ARGSUSED */
-void
-fs_noval(void)
-{
-}
-
-/*
- * vnode pcache layer for vnode_tosspages.
- * 'last' parameter unused but left in for IRIX compatibility
- */
 void
 fs_tosspages(
 	bhv_desc_t	*bdp,
@@ -56,18 +28,13 @@
 	xfs_off_t	last,
 	int		fiopt)
 {
-	vnode_t		*vp = BHV_TO_VNODE(bdp);
+	bhv_vnode_t	*vp = BHV_TO_VNODE(bdp);
 	struct inode	*ip = vn_to_inode(vp);
 
 	if (VN_CACHED(vp))
 		truncate_inode_pages(ip->i_mapping, first);
 }
 
-
-/*
- * vnode pcache layer for vnode_flushinval_pages.
- * 'last' parameter unused but left in for IRIX compatibility
- */
 void
 fs_flushinval_pages(
 	bhv_desc_t	*bdp,
@@ -75,20 +42,17 @@
 	xfs_off_t	last,
 	int		fiopt)
 {
-	vnode_t		*vp = BHV_TO_VNODE(bdp);
+	bhv_vnode_t	*vp = BHV_TO_VNODE(bdp);
 	struct inode	*ip = vn_to_inode(vp);
 
 	if (VN_CACHED(vp)) {
+		if (VN_TRUNC(vp))
+			VUNTRUNCATE(vp);
 		filemap_write_and_wait(ip->i_mapping);
-
 		truncate_inode_pages(ip->i_mapping, first);
 	}
 }
 
-/*
- * vnode pcache layer for vnode_flush_pages.
- * 'last' parameter unused but left in for IRIX compatibility
- */
 int
 fs_flush_pages(
 	bhv_desc_t	*bdp,
@@ -97,15 +61,16 @@
 	uint64_t	flags,
 	int		fiopt)
 {
-	vnode_t		*vp = BHV_TO_VNODE(bdp);
+	bhv_vnode_t	*vp = BHV_TO_VNODE(bdp);
 	struct inode	*ip = vn_to_inode(vp);
 
-	if (VN_CACHED(vp)) {
+	if (VN_DIRTY(vp)) {
+		if (VN_TRUNC(vp))
+			VUNTRUNCATE(vp);
 		filemap_fdatawrite(ip->i_mapping);
 		if (flags & XFS_B_ASYNC)
 			return 0;
 		filemap_fdatawait(ip->i_mapping);
 	}
-
 	return 0;
 }
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c
index 6e8085f..6c162c3 100644
--- a/fs/xfs/linux-2.6/xfs_globals.c
+++ b/fs/xfs/linux-2.6/xfs_globals.c
@@ -45,6 +45,7 @@
 	.xfs_buf_age	= {	1*100,		15*100,		7200*100},
 	.inherit_nosym	= {	0,		0,		1	},
 	.rotorstep	= {	1,		1,		255	},
+	.inherit_nodfrg	= {	0,		1,		1	},
 };
 
 /*
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 8447849..6e52a5d 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -31,7 +30,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
@@ -78,7 +76,7 @@
 	xfs_handle_t		handle;
 	xfs_fsop_handlereq_t	hreq;
 	struct inode		*inode;
-	struct vnode		*vp;
+	bhv_vnode_t		*vp;
 
 	if (copy_from_user(&hreq, arg, sizeof(hreq)))
 		return -XFS_ERROR(EFAULT);
@@ -192,7 +190,7 @@
 	xfs_mount_t		*mp,
 	struct inode		*parinode,	/* parent inode pointer    */
 	xfs_fsop_handlereq_t	*hreq,
-	vnode_t			**vp,
+	bhv_vnode_t		**vp,
 	struct inode		**inode)
 {
 	void			__user *hanp;
@@ -202,7 +200,7 @@
 	xfs_handle_t		handle;
 	xfs_inode_t		*ip;
 	struct inode		*inodep;
-	vnode_t			*vpp;
+	bhv_vnode_t		*vpp;
 	xfs_ino_t		ino;
 	__u32			igen;
 	int			error;
@@ -277,7 +275,7 @@
 	struct file		*filp;
 	struct inode		*inode;
 	struct dentry		*dentry;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	xfs_fsop_handlereq_t	hreq;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -362,7 +360,7 @@
 	struct uio		auio;
 	struct inode		*inode;
 	xfs_fsop_handlereq_t	hreq;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	__u32			olen;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -393,9 +391,11 @@
 	auio.uio_segflg	= UIO_USERSPACE;
 	auio.uio_resid	= olen;
 
-	VOP_READLINK(vp, &auio, IO_INVIS, NULL, error);
-
+	error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL);
 	VN_RELE(vp);
+	if (error)
+		return -error;
+
 	return (olen - auio.uio_resid);
 }
 
@@ -411,7 +411,7 @@
 	xfs_fsop_setdm_handlereq_t dmhreq;
 	struct inode		*inode;
 	bhv_desc_t		*bdp;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 
 	if (!capable(CAP_MKNOD))
 		return -XFS_ERROR(EPERM);
@@ -452,7 +452,7 @@
 	attrlist_cursor_kern_t	*cursor;
 	xfs_fsop_attrlist_handlereq_t al_hreq;
 	struct inode		*inode;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	char			*kbuf;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -472,8 +472,8 @@
 		goto out_vn_rele;
 
 	cursor = (attrlist_cursor_kern_t *)&al_hreq.pos;
-	VOP_ATTR_LIST(vp, kbuf, al_hreq.buflen, al_hreq.flags,
-			cursor, NULL, error);
+	error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags,
+					cursor, NULL);
 	if (error)
 		goto out_kfree;
 
@@ -490,7 +490,7 @@
 
 STATIC int
 xfs_attrmulti_attr_get(
-	struct vnode		*vp,
+	bhv_vnode_t		*vp,
 	char			*name,
 	char			__user *ubuf,
 	__uint32_t		*len,
@@ -505,7 +505,7 @@
 	if (!kbuf)
 		return ENOMEM;
 
-	VOP_ATTR_GET(vp, name, kbuf, len, flags, NULL, error);
+	error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL);
 	if (error)
 		goto out_kfree;
 
@@ -519,7 +519,7 @@
 
 STATIC int
 xfs_attrmulti_attr_set(
-	struct vnode		*vp,
+	bhv_vnode_t		*vp,
 	char			*name,
 	const char		__user *ubuf,
 	__uint32_t		len,
@@ -542,7 +542,7 @@
 	if (copy_from_user(kbuf, ubuf, len))
 		goto out_kfree;
 			
-	VOP_ATTR_SET(vp, name, kbuf, len, flags, NULL, error);
+	error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL);
 
  out_kfree:
 	kfree(kbuf);
@@ -551,20 +551,15 @@
 
 STATIC int
 xfs_attrmulti_attr_remove(
-	struct vnode		*vp,
+	bhv_vnode_t		*vp,
 	char			*name,
 	__uint32_t		flags)
 {
-	int			error;
-
-
 	if (IS_RDONLY(&vp->v_inode))
 		return -EROFS;
 	if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode))
 		return EPERM;
-
-	VOP_ATTR_REMOVE(vp, name, flags, NULL, error);
-	return error;
+	return bhv_vop_attr_remove(vp, name, flags, NULL);
 }
 
 STATIC int
@@ -578,7 +573,7 @@
 	xfs_attr_multiop_t	*ops;
 	xfs_fsop_attrmulti_handlereq_t am_hreq;
 	struct inode		*inode;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	unsigned int		i, size;
 	char			*attr_name;
 
@@ -658,7 +653,7 @@
 STATIC int
 xfs_ioc_space(
 	bhv_desc_t		*bdp,
-	vnode_t			*vp,
+	bhv_vnode_t		*vp,
 	struct file		*filp,
 	int			flags,
 	unsigned int		cmd,
@@ -682,7 +677,7 @@
 
 STATIC int
 xfs_ioc_xattr(
-	vnode_t			*vp,
+	bhv_vnode_t		*vp,
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
@@ -711,7 +706,7 @@
 	void			__user *arg)
 {
 	int			error;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	xfs_inode_t		*ip;
 	xfs_mount_t		*mp;
 
@@ -962,7 +957,7 @@
 STATIC int
 xfs_ioc_space(
 	bhv_desc_t		*bdp,
-	vnode_t			*vp,
+	bhv_vnode_t		*vp,
 	struct file		*filp,
 	int			ioflags,
 	unsigned int		cmd,
@@ -1153,14 +1148,14 @@
 
 STATIC int
 xfs_ioc_xattr(
-	vnode_t			*vp,
+	bhv_vnode_t		*vp,
 	xfs_inode_t		*ip,
 	struct file		*filp,
 	unsigned int		cmd,
 	void			__user *arg)
 {
 	struct fsxattr		fa;
-	struct vattr		*vattr;
+	struct bhv_vattr	*vattr;
 	int			error = 0;
 	int			attr_flags;
 	unsigned int		flags;
@@ -1173,7 +1168,7 @@
 	case XFS_IOC_FSGETXATTR: {
 		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
 				 XFS_AT_NEXTENTS | XFS_AT_PROJID;
-		VOP_GETATTR(vp, vattr, 0, NULL, error);
+		error = bhv_vop_getattr(vp, vattr, 0, NULL);
 		if (unlikely(error)) {
 			error = -error;
 			break;
@@ -1206,7 +1201,7 @@
 		vattr->va_extsize = fa.fsx_extsize;
 		vattr->va_projid  = fa.fsx_projid;
 
-		VOP_SETATTR(vp, vattr, attr_flags, NULL, error);
+		error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
 		if (likely(!error))
 			__vn_revalidate(vp, vattr);	/* update flags */
 		error = -error;
@@ -1216,7 +1211,7 @@
 	case XFS_IOC_FSGETXATTRA: {
 		vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
 				 XFS_AT_ANEXTENTS | XFS_AT_PROJID;
-		VOP_GETATTR(vp, vattr, 0, NULL, error);
+		error = bhv_vop_getattr(vp, vattr, 0, NULL);
 		if (unlikely(error)) {
 			error = -error;
 			break;
@@ -1262,7 +1257,7 @@
 		vattr->va_xflags = xfs_merge_ioc_xflags(flags,
 							xfs_ip2xflags(ip));
 
-		VOP_SETATTR(vp, vattr, attr_flags, NULL, error);
+		error = bhv_vop_setattr(vp, vattr, attr_flags, NULL);
 		if (likely(!error))
 			__vn_revalidate(vp, vattr);	/* update flags */
 		error = -error;
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 251bfe4..601f01c 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -114,7 +114,7 @@
 	unsigned long	arg)
 {
 	struct inode	*inode = file->f_dentry->d_inode;
-	vnode_t		*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 	int		error;
 
 	switch (cmd) {
@@ -193,7 +193,7 @@
 		return -ENOIOCTLCMD;
 	}
 
-	VOP_IOCTL(vp, inode, file, mode, cmd, (void __user *)arg, error);
+	error = bhv_vop_ioctl(vp, inode, file, mode, cmd, (void __user *)arg);
 	VMODIFY(vp);
 
 	return error;
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index 2e2e275..d918002 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -61,7 +59,7 @@
  */
 xfs_inode_t *
 xfs_vtoi(
-	struct vnode	*vp)
+	bhv_vnode_t	*vp)
 {
 	bhv_desc_t      *bdp;
 
@@ -80,7 +78,7 @@
 xfs_synchronize_atime(
 	xfs_inode_t	*ip)
 {
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	vp = XFS_ITOV_NULL(ip);
 	if (vp) {
@@ -200,14 +198,10 @@
 STATIC void
 xfs_validate_fields(
 	struct inode	*ip,
-	struct vattr	*vattr)
+	bhv_vattr_t	*vattr)
 {
-	vnode_t		*vp = vn_from_inode(ip);
-	int		error;
-
 	vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS;
-	VOP_GETATTR(vp, vattr, ATTR_LAZY, NULL, error);
-  	if (likely(!error)) {
+	if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) {
 		ip->i_nlink = vattr->va_nlink;
 		ip->i_blocks = vattr->va_nblocks;
 
@@ -225,7 +219,7 @@
  */
 STATIC int
 xfs_init_security(
-	struct vnode	*vp,
+	bhv_vnode_t	*vp,
 	struct inode	*dir)
 {
 	struct inode	*ip = vn_to_inode(vp);
@@ -241,7 +235,7 @@
 		return -error;
 	}
 
-	VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error);
+	error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL);
 	if (!error)
 		VMODIFY(vp);
 
@@ -264,13 +258,12 @@
 
 STATIC inline void
 xfs_cleanup_inode(
-	vnode_t		*dvp,
-	vnode_t		*vp,
+	bhv_vnode_t	*dvp,
+	bhv_vnode_t	*vp,
 	struct dentry	*dentry,
 	int		mode)
 {
 	struct dentry   teardown = {};
-	int             error;
 
 	/* Oh, the horror.
 	 * If we can't add the ACL or we fail in
@@ -281,9 +274,9 @@
 	teardown.d_name = dentry->d_name;
 
 	if (S_ISDIR(mode))
-	  	VOP_RMDIR(dvp, &teardown, NULL, error);
+	  	bhv_vop_rmdir(dvp, &teardown, NULL);
 	else
-		VOP_REMOVE(dvp, &teardown, NULL, error);
+		bhv_vop_remove(dvp, &teardown, NULL);
 	VN_RELE(vp);
 }
 
@@ -295,8 +288,8 @@
 	dev_t		rdev)
 {
 	struct inode	*ip;
-	vattr_t		vattr = { 0 };
-	vnode_t		*vp = NULL, *dvp = vn_from_inode(dir);
+	bhv_vattr_t	vattr = { 0 };
+	bhv_vnode_t	*vp = NULL, *dvp = vn_from_inode(dir);
 	xfs_acl_t	*default_acl = NULL;
 	attrexists_t	test_default_acl = _ACL_DEFAULT_EXISTS;
 	int		error;
@@ -330,10 +323,10 @@
 		vattr.va_mask |= XFS_AT_RDEV;
 		/*FALLTHROUGH*/
 	case S_IFREG:
-		VOP_CREATE(dvp, dentry, &vattr, &vp, NULL, error);
+		error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL);
 		break;
 	case S_IFDIR:
-		VOP_MKDIR(dvp, dentry, &vattr, &vp, NULL, error);
+		error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL);
 		break;
 	default:
 		error = EINVAL;
@@ -396,14 +389,14 @@
 	struct dentry	*dentry,
 	struct nameidata *nd)
 {
-	struct vnode	*vp = vn_from_inode(dir), *cvp;
+	bhv_vnode_t	*vp = vn_from_inode(dir), *cvp;
 	int		error;
 
 	if (dentry->d_name.len >= MAXNAMELEN)
 		return ERR_PTR(-ENAMETOOLONG);
 
-	VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error);
-	if (error) {
+	error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL);
+	if (unlikely(error)) {
 		if (unlikely(error != ENOENT))
 			return ERR_PTR(-error);
 		d_add(dentry, NULL);
@@ -420,22 +413,21 @@
 	struct dentry	*dentry)
 {
 	struct inode	*ip;	/* inode of guy being linked to */
-	vnode_t		*tdvp;	/* target directory for new name/link */
-	vnode_t		*vp;	/* vp of name being linked */
-	vattr_t		vattr;
+	bhv_vnode_t	*tdvp;	/* target directory for new name/link */
+	bhv_vnode_t	*vp;	/* vp of name being linked */
+	bhv_vattr_t	vattr;
 	int		error;
 
 	ip = old_dentry->d_inode;	/* inode being linked to */
-	if (S_ISDIR(ip->i_mode))
-		return -EPERM;
-
 	tdvp = vn_from_inode(dir);
 	vp = vn_from_inode(ip);
 
-	VOP_LINK(tdvp, vp, dentry, NULL, error);
-	if (likely(!error)) {
+	VN_HOLD(vp);
+	error = bhv_vop_link(tdvp, vp, dentry, NULL);
+	if (unlikely(error)) {
+		VN_RELE(vp);
+	} else {
 		VMODIFY(tdvp);
-		VN_HOLD(vp);
 		xfs_validate_fields(ip, &vattr);
 		d_instantiate(dentry, ip);
 	}
@@ -448,14 +440,14 @@
 	struct dentry	*dentry)
 {
 	struct inode	*inode;
-	vnode_t		*dvp;	/* directory containing name to remove */
-	vattr_t		vattr;
+	bhv_vnode_t	*dvp;	/* directory containing name to remove */
+	bhv_vattr_t	vattr;
 	int		error;
 
 	inode = dentry->d_inode;
 	dvp = vn_from_inode(dir);
 
-	VOP_REMOVE(dvp, dentry, NULL, error);
+	error = bhv_vop_remove(dvp, dentry, NULL);
 	if (likely(!error)) {
 		xfs_validate_fields(dir, &vattr);	/* size needs update */
 		xfs_validate_fields(inode, &vattr);
@@ -470,27 +462,26 @@
 	const char	*symname)
 {
 	struct inode	*ip;
-	vattr_t		vattr = { 0 };
-	vnode_t		*dvp;	/* directory containing name of symlink */
-	vnode_t		*cvp;	/* used to lookup symlink to put in dentry */
+	bhv_vattr_t	va = { 0 };
+	bhv_vnode_t	*dvp;	/* directory containing name of symlink */
+	bhv_vnode_t	*cvp;	/* used to lookup symlink to put in dentry */
 	int		error;
 
 	dvp = vn_from_inode(dir);
 	cvp = NULL;
 
-	vattr.va_mode = S_IFLNK |
+	va.va_mode = S_IFLNK |
 		(irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO);
-	vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
+	va.va_mask = XFS_AT_TYPE|XFS_AT_MODE;
 
-	error = 0;
-	VOP_SYMLINK(dvp, dentry, &vattr, (char *)symname, &cvp, NULL, error);
+	error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL);
 	if (likely(!error && cvp)) {
 		error = xfs_init_security(cvp, dir);
 		if (likely(!error)) {
 			ip = vn_to_inode(cvp);
 			d_instantiate(dentry, ip);
-			xfs_validate_fields(dir, &vattr);
-			xfs_validate_fields(ip, &vattr);
+			xfs_validate_fields(dir, &va);
+			xfs_validate_fields(ip, &va);
 		} else {
 			xfs_cleanup_inode(dvp, cvp, dentry, 0);
 		}
@@ -504,11 +495,11 @@
 	struct dentry	*dentry)
 {
 	struct inode	*inode = dentry->d_inode;
-	vnode_t		*dvp = vn_from_inode(dir);
-	vattr_t		vattr;
+	bhv_vnode_t	*dvp = vn_from_inode(dir);
+	bhv_vattr_t	vattr;
 	int		error;
 
-	VOP_RMDIR(dvp, dentry, NULL, error);
+	error = bhv_vop_rmdir(dvp, dentry, NULL);
 	if (likely(!error)) {
 		xfs_validate_fields(inode, &vattr);
 		xfs_validate_fields(dir, &vattr);
@@ -524,15 +515,15 @@
 	struct dentry	*ndentry)
 {
 	struct inode	*new_inode = ndentry->d_inode;
-	vnode_t		*fvp;	/* from directory */
-	vnode_t		*tvp;	/* target directory */
-	vattr_t		vattr;
+	bhv_vnode_t	*fvp;	/* from directory */
+	bhv_vnode_t	*tvp;	/* target directory */
+	bhv_vattr_t	vattr;
 	int		error;
 
 	fvp = vn_from_inode(odir);
 	tvp = vn_from_inode(ndir);
 
-	VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error);
+	error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL);
 	if (likely(!error)) {
 		if (new_inode)
 			xfs_validate_fields(new_inode, &vattr);
@@ -553,7 +544,7 @@
 	struct dentry		*dentry,
 	struct nameidata	*nd)
 {
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	uio_t			*uio;
 	iovec_t			iov;
 	int			error;
@@ -586,8 +577,8 @@
 	uio->uio_resid = MAXPATHLEN;
 	uio->uio_iovcnt = 1;
 
-	VOP_READLINK(vp, uio, 0, NULL, error);
-	if (error) {
+	error = bhv_vop_readlink(vp, uio, 0, NULL);
+	if (unlikely(error)) {
 		kfree(link);
 		link = ERR_PTR(-error);
 	} else {
@@ -618,12 +609,7 @@
 	int		mode,
 	struct nameidata *nd)
 {
-	vnode_t		*vp = vn_from_inode(inode);
-	int		error;
-
-	mode <<= 6;		/* convert from linux to vnode access bits */
-	VOP_ACCESS(vp, mode, NULL, error);
-	return -error;
+	return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL);
 }
 #else
 #define xfs_vn_permission NULL
@@ -636,14 +622,14 @@
 	struct kstat	*stat)
 {
 	struct inode	*inode = dentry->d_inode;
-	vnode_t		*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 	int		error = 0;
 
 	if (unlikely(vp->v_flag & VMODIFIED))
 		error = vn_revalidate(vp);
 	if (!error)
 		generic_fillattr(inode, stat);
-	return 0;
+	return -error;
 }
 
 STATIC int
@@ -653,8 +639,8 @@
 {
 	struct inode	*inode = dentry->d_inode;
 	unsigned int	ia_valid = attr->ia_valid;
-	vnode_t		*vp = vn_from_inode(inode);
-	vattr_t		vattr = { 0 };
+	bhv_vnode_t	*vp = vn_from_inode(inode);
+	bhv_vattr_t	vattr = { 0 };
 	int		flags = 0;
 	int		error;
 
@@ -697,7 +683,7 @@
 		flags |= ATTR_NONBLOCK;
 #endif
 
-	VOP_SETATTR(vp, &vattr, flags, NULL, error);
+	error = bhv_vop_setattr(vp, &vattr, flags, NULL);
 	if (likely(!error))
 		__vn_revalidate(vp, &vattr);
 	return -error;
@@ -718,7 +704,7 @@
 	size_t		size,
 	int		flags)
 {
-	vnode_t		*vp = vn_from_inode(dentry->d_inode);
+	bhv_vnode_t	*vp = vn_from_inode(dentry->d_inode);
 	char		*attr = (char *)name;
 	attrnames_t	*namesp;
 	int		xflags = 0;
@@ -748,7 +734,7 @@
 	void		*data,
 	size_t		size)
 {
-	vnode_t		*vp = vn_from_inode(dentry->d_inode);
+	bhv_vnode_t	*vp = vn_from_inode(dentry->d_inode);
 	char		*attr = (char *)name;
 	attrnames_t	*namesp;
 	int		xflags = 0;
@@ -777,7 +763,7 @@
 	char			*data,
 	size_t			size)
 {
-	vnode_t			*vp = vn_from_inode(dentry->d_inode);
+	bhv_vnode_t		*vp = vn_from_inode(dentry->d_inode);
 	int			error, xflags = ATTR_KERNAMELS;
 	ssize_t			result;
 
@@ -796,7 +782,7 @@
 	struct dentry	*dentry,
 	const char	*name)
 {
-	vnode_t		*vp = vn_from_inode(dentry->d_inode);
+	bhv_vnode_t	*vp = vn_from_inode(dentry->d_inode);
 	char		*attr = (char *)name;
 	attrnames_t	*namesp;
 	int		xflags = 0;
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index e9fe43d..028eb17 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -134,14 +134,19 @@
 #define xfs_buf_age_centisecs	xfs_params.xfs_buf_age.val
 #define xfs_inherit_nosymlinks	xfs_params.inherit_nosym.val
 #define xfs_rotorstep		xfs_params.rotorstep.val
+#define xfs_inherit_nodefrag	xfs_params.inherit_nodfrg.val
 
-#ifndef raw_smp_processor_id
-#define raw_smp_processor_id()	smp_processor_id()
-#endif
-#define current_cpu()		raw_smp_processor_id()
+#define current_cpu()		(raw_smp_processor_id())
 #define current_pid()		(current->pid)
 #define current_fsuid(cred)	(current->fsuid)
 #define current_fsgid(cred)	(current->fsgid)
+#define current_test_flags(f)	(current->flags & (f))
+#define current_set_flags_nested(sp, f)		\
+		(*(sp) = current->flags, current->flags |= (f))
+#define current_clear_flags_nested(sp, f)	\
+		(*(sp) = current->flags, current->flags &= ~(f))
+#define current_restore_flags_nested(sp, f)	\
+		(current->flags = ((current->flags & ~(f)) | (*(sp) & (f))))
 
 #define NBPP		PAGE_SIZE
 #define DPPSHFT		(PAGE_SHIFT - 9)
@@ -187,25 +192,9 @@
 /* bytes to clicks */
 #define btoc(x)         (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT)
 
-#ifndef ENOATTR
 #define ENOATTR		ENODATA		/* Attribute not found */
-#endif
-
-/* Note: EWRONGFS never visible outside the kernel */
-#define	EWRONGFS	EINVAL		/* Mount with wrong filesystem type */
-
-/*
- * XXX EFSCORRUPTED needs a real value in errno.h. asm-i386/errno.h won't
- *     return codes out of its known range in errno.
- * XXX Also note: needs to be < 1000 and fairly unique on Linux (mustn't
- *     conflict with any code we use already or any code a driver may use)
- * XXX Some options (currently we do #2):
- *	1/ New error code ["Filesystem is corrupted", _after_ glibc updated]
- *	2/ 990 ["Unknown error 990"]
- *	3/ EUCLEAN ["Structure needs cleaning"]
- *	4/ Convert EFSCORRUPTED to EIO [just prior to return into userspace]
- */
-#define EFSCORRUPTED    990		/* Filesystem is corrupted */
+#define EWRONGFS	EINVAL		/* Mount with wrong filesystem type */
+#define EFSCORRUPTED	EUCLEAN		/* Filesystem is corrupted */
 
 #define SYNCHRONIZE()	barrier()
 #define __return_address __builtin_return_address(0)
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index 67efe33..5d9cfd9 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -206,7 +204,7 @@
 	xfs_fsize_t		n;
 	xfs_inode_t		*ip;
 	xfs_mount_t		*mp;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	unsigned long		seg;
 
 	ip = XFS_BHVTOI(bdp);
@@ -258,7 +256,7 @@
 
 	if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
 	    !(ioflags & IO_INVIS)) {
-		vrwlock_t locktype = VRWLOCK_READ;
+		bhv_vrwlock_t locktype = VRWLOCK_READ;
 		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
 
 		ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
@@ -271,7 +269,7 @@
 	}
 
 	if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp)))
-		VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(*offset)),
+		bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)),
 						-1, FI_REMAPF_LOCKED);
 
 	xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore,
@@ -313,7 +311,7 @@
 
 	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
 	    (!(ioflags & IO_INVIS))) {
-		vrwlock_t locktype = VRWLOCK_READ;
+		bhv_vrwlock_t locktype = VRWLOCK_READ;
 		int error;
 
 		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
@@ -357,7 +355,7 @@
 
 	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) &&
 	    (!(ioflags & IO_INVIS))) {
-		vrwlock_t locktype = VRWLOCK_READ;
+		bhv_vrwlock_t locktype = VRWLOCK_READ;
 		int error;
 
 		error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp),
@@ -401,7 +399,7 @@
 
 	if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) &&
 	    (!(ioflags & IO_INVIS))) {
-		vrwlock_t locktype = VRWLOCK_WRITE;
+		bhv_vrwlock_t locktype = VRWLOCK_WRITE;
 		int error;
 
 		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp),
@@ -458,7 +456,7 @@
 	last_fsb = XFS_B_TO_FSBT(mp, isize);
 	nimaps = 1;
 	error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap,
-			  &nimaps, NULL);
+			  &nimaps, NULL, NULL);
 	if (error) {
 		return error;
 	}
@@ -499,7 +497,7 @@
 
 int					/* error (positive) */
 xfs_zero_eof(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	xfs_iocore_t	*io,
 	xfs_off_t	offset,		/* starting I/O offset */
 	xfs_fsize_t	isize,		/* current inode size */
@@ -510,7 +508,6 @@
 	xfs_fileoff_t	end_zero_fsb;
 	xfs_fileoff_t	zero_count_fsb;
 	xfs_fileoff_t	last_fsb;
-	xfs_extlen_t	buf_len_fsb;
 	xfs_mount_t	*mp = io->io_mount;
 	int		nimaps;
 	int		error = 0;
@@ -556,7 +553,7 @@
 		nimaps = 1;
 		zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
 		error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb,
-				  0, NULL, 0, &imap, &nimaps, NULL);
+				  0, NULL, 0, &imap, &nimaps, NULL, NULL);
 		if (error) {
 			ASSERT(ismrlocked(io->io_lock, MR_UPDATE));
 			ASSERT(ismrlocked(io->io_iolock, MR_UPDATE));
@@ -579,16 +576,7 @@
 		}
 
 		/*
-		 * There are blocks in the range requested.
-		 * Zero them a single write at a time.  We actually
-		 * don't zero the entire range returned if it is
-		 * too big and simply loop around to get the rest.
-		 * That is not the most efficient thing to do, but it
-		 * is simple and this path should not be exercised often.
-		 */
-		buf_len_fsb = XFS_FILBLKS_MIN(imap.br_blockcount,
-					      mp->m_writeio_blocks << 8);
-		/*
+		 * There are blocks we need to zero.
 		 * Drop the inode lock while we're doing the I/O.
 		 * We'll still have the iolock to protect us.
 		 */
@@ -596,14 +584,13 @@
 
 		error = xfs_iozero(ip,
 				   XFS_FSB_TO_B(mp, start_zero_fsb),
-				   XFS_FSB_TO_B(mp, buf_len_fsb),
+				   XFS_FSB_TO_B(mp, imap.br_blockcount),
 				   end_size);
-
 		if (error) {
 			goto out_lock;
 		}
 
-		start_zero_fsb = imap.br_startoff + buf_len_fsb;
+		start_zero_fsb = imap.br_startoff + imap.br_blockcount;
 		ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
 
 		XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD);
@@ -637,11 +624,11 @@
 	ssize_t			ret = 0, error = 0;
 	xfs_fsize_t		isize, new_size;
 	xfs_iocore_t		*io;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	unsigned long		seg;
 	int			iolock;
 	int			eventsent = 0;
-	vrwlock_t		locktype;
+	bhv_vrwlock_t		locktype;
 	size_t			ocount = 0, count;
 	loff_t			pos;
 	int			need_i_mutex = 1, need_flush = 0;
@@ -679,11 +666,11 @@
 	io = &xip->i_iocore;
 	mp = io->io_mount;
 
+	vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE);
+
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return -EIO;
 
-	fs_check_frozen(vp->v_vfsp, SB_FREEZE_WRITE);
-
 	if (ioflags & IO_ISDIRECT) {
 		xfs_buftarg_t	*target =
 			(xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ?
@@ -814,7 +801,7 @@
 		if (need_flush) {
 			xfs_inval_cached_trace(io, pos, -1,
 					ctooff(offtoct(pos)), -1);
-			VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(pos)),
+			bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)),
 					-1, FI_REMAPF_LOCKED);
 		}
 
@@ -903,79 +890,9 @@
 
 	/* Handle various SYNC-type writes */
 	if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
-		/*
-		 * If we're treating this as O_DSYNC and we have not updated the
-		 * size, force the log.
-		 */
-		if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
-		    !(xip->i_update_size)) {
-			xfs_inode_log_item_t	*iip = xip->i_itemp;
-
-			/*
-			 * If an allocation transaction occurred
-			 * without extending the size, then we have to force
-			 * the log up the proper point to ensure that the
-			 * allocation is permanent.  We can't count on
-			 * the fact that buffered writes lock out direct I/O
-			 * writes - the direct I/O write could have extended
-			 * the size nontransactionally, then finished before
-			 * we started.  xfs_write_file will think that the file
-			 * didn't grow but the update isn't safe unless the
-			 * size change is logged.
-			 *
-			 * Force the log if we've committed a transaction
-			 * against the inode or if someone else has and
-			 * the commit record hasn't gone to disk (e.g.
-			 * the inode is pinned).  This guarantees that
-			 * all changes affecting the inode are permanent
-			 * when we return.
-			 */
-			if (iip && iip->ili_last_lsn) {
-				xfs_log_force(mp, iip->ili_last_lsn,
-						XFS_LOG_FORCE | XFS_LOG_SYNC);
-			} else if (xfs_ipincount(xip) > 0) {
-				xfs_log_force(mp, (xfs_lsn_t)0,
-						XFS_LOG_FORCE | XFS_LOG_SYNC);
-			}
-
-		} else {
-			xfs_trans_t	*tp;
-
-			/*
-			 * O_SYNC or O_DSYNC _with_ a size update are handled
-			 * the same way.
-			 *
-			 * If the write was synchronous then we need to make
-			 * sure that the inode modification time is permanent.
-			 * We'll have updated the timestamp above, so here
-			 * we use a synchronous transaction to log the inode.
-			 * It's not fast, but it's necessary.
-			 *
-			 * If this a dsync write and the size got changed
-			 * non-transactionally, then we need to ensure that
-			 * the size change gets logged in a synchronous
-			 * transaction.
-			 */
-
-			tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC);
-			if ((error = xfs_trans_reserve(tp, 0,
-						      XFS_SWRITE_LOG_RES(mp),
-						      0, 0, 0))) {
-				/* Transaction reserve failed */
-				xfs_trans_cancel(tp, 0);
-			} else {
-				/* Transaction reserve successful */
-				xfs_ilock(xip, XFS_ILOCK_EXCL);
-				xfs_trans_ijoin(tp, xip, XFS_ILOCK_EXCL);
-				xfs_trans_ihold(tp, xip);
-				xfs_trans_log_inode(tp, xip, XFS_ILOG_CORE);
-				xfs_trans_set_sync(tp);
-				error = xfs_trans_commit(tp, 0, NULL);
-				xfs_iunlock(xip, XFS_ILOCK_EXCL);
-			}
-			if (error)
-				goto out_unlock_internal;
-		}
+		error = xfs_write_sync_logforce(mp, xip);
+		if (error)
+			goto out_unlock_internal;
 
 		xfs_rwunlock(bdp, locktype);
 		if (need_i_mutex)
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index 8f45399..c77e62e 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -18,8 +18,8 @@
 #ifndef __XFS_LRW_H__
 #define __XFS_LRW_H__
 
-struct vnode;
 struct bhv_desc;
+struct bhv_vnode;
 struct xfs_mount;
 struct xfs_iocore;
 struct xfs_inode;
@@ -49,7 +49,7 @@
 #define	XFS_CTRUNC4		14
 #define	XFS_CTRUNC5		15
 #define	XFS_CTRUNC6		16
-#define	XFS_BUNMAPI		17
+#define	XFS_BUNMAP		17
 #define	XFS_INVAL_CACHED	18
 #define	XFS_DIORD_ENTER		19
 #define	XFS_DIOWR_ENTER		20
@@ -82,7 +82,7 @@
 extern int xfs_bdstrat_cb(struct xfs_buf *);
 extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
 
-extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
+extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t,
 				xfs_fsize_t, xfs_fsize_t);
 extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
 				const struct iovec *, unsigned int,
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c
index 1f0589a..e480b61 100644
--- a/fs/xfs/linux-2.6/xfs_stats.c
+++ b/fs/xfs/linux-2.6/xfs_stats.c
@@ -62,7 +62,7 @@
 		while (j < xstats[i].endpoint) {
 			val = 0;
 			/* sum over all cpus */
-			for_each_cpu(c)
+			for_each_possible_cpu(c)
 				val += *(((__u32*)&per_cpu(xfsstats, c) + j));
 			len += sprintf(buffer + len, " %u", val);
 			j++;
@@ -70,7 +70,7 @@
 		buffer[len++] = '\n';
 	}
 	/* extra precision counters */
-	for_each_cpu(i) {
+	for_each_possible_cpu(i) {
 		xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes;
 		xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes;
 		xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes;
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 68f4793..9bdef9d 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -151,7 +149,7 @@
 STATIC __inline__ void
 xfs_revalidate_inode(
 	xfs_mount_t		*mp,
-	vnode_t			*vp,
+	bhv_vnode_t		*vp,
 	xfs_inode_t		*ip)
 {
 	struct inode		*inode = vn_to_inode(vp);
@@ -206,7 +204,7 @@
 void
 xfs_initialize_vnode(
 	bhv_desc_t		*bdp,
-	vnode_t			*vp,
+	bhv_vnode_t		*vp,
 	bhv_desc_t		*inode_bhv,
 	int			unlock)
 {
@@ -336,7 +334,7 @@
 xfs_fs_alloc_inode(
 	struct super_block	*sb)
 {
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 
 	vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP);
 	if (unlikely(!vp))
@@ -359,13 +357,13 @@
 {
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 		      SLAB_CTOR_CONSTRUCTOR)
-		inode_init_once(vn_to_inode((vnode_t *)vnode));
+		inode_init_once(vn_to_inode((bhv_vnode_t *)vnode));
 }
 
 STATIC int
 xfs_init_zones(void)
 {
-	xfs_vnode_zone = kmem_zone_init_flags(sizeof(vnode_t), "xfs_vnode_t",
+	xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode",
 					KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
 					KM_ZONE_SPREAD,
 					xfs_fs_inode_init_once);
@@ -409,22 +407,17 @@
 	struct inode		*inode,
 	int			sync)
 {
-	vnode_t			*vp = vn_from_inode(inode);
+	bhv_vnode_t		*vp = vn_from_inode(inode);
 	int			error = 0, flags = FLUSH_INODE;
 
 	if (vp) {
 		vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
 		if (sync)
 			flags |= FLUSH_SYNC;
-		VOP_IFLUSH(vp, flags, error);
-		if (error == EAGAIN) {
-			if (sync)
-				VOP_IFLUSH(vp, flags | FLUSH_LOG, error);
-			else
-				error = 0;
-		}
+		error = bhv_vop_iflush(vp, flags);
+		if (error == EAGAIN)
+			error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0;
 	}
-
 	return -error;
 }
 
@@ -432,8 +425,7 @@
 xfs_fs_clear_inode(
 	struct inode		*inode)
 {
-	vnode_t			*vp = vn_from_inode(inode);
-	int			error, cache;
+	bhv_vnode_t		*vp = vn_from_inode(inode);
 
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
 
@@ -446,20 +438,18 @@
 	 * This can happen because xfs_iget_core calls xfs_idestroy if we
 	 * find an inode with di_mode == 0 but without IGET_CREATE set.
 	 */
-	if (vp->v_fbhv)
-		VOP_INACTIVE(vp, NULL, cache);
+	if (VNHEAD(vp))
+		bhv_vop_inactive(vp, NULL);
 
 	VN_LOCK(vp);
 	vp->v_flag &= ~VMODIFIED;
 	VN_UNLOCK(vp, 0);
 
-	if (vp->v_fbhv) {
-		VOP_RECLAIM(vp, error);
-		if (error)
-			panic("vn_purge: cannot reclaim");
-	}
+	if (VNHEAD(vp))
+		if (bhv_vop_reclaim(vp))
+			panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp);
 
-	ASSERT(vp->v_fbhv == NULL);
+	ASSERT(VNHEAD(vp) == NULL);
 
 #ifdef XFS_VNODE_TRACE
 	ktrace_free(vp->v_trace);
@@ -475,13 +465,13 @@
  */
 STATIC void
 xfs_syncd_queue_work(
-	struct vfs	*vfs,
+	struct bhv_vfs	*vfs,
 	void		*data,
-	void		(*syncer)(vfs_t *, void *))
+	void		(*syncer)(bhv_vfs_t *, void *))
 {
-	vfs_sync_work_t	*work;
+	struct bhv_vfs_sync_work *work;
 
-	work = kmem_alloc(sizeof(struct vfs_sync_work), KM_SLEEP);
+	work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP);
 	INIT_LIST_HEAD(&work->w_list);
 	work->w_syncer = syncer;
 	work->w_data = data;
@@ -500,7 +490,7 @@
  */
 STATIC void
 xfs_flush_inode_work(
-	vfs_t		*vfs,
+	bhv_vfs_t	*vfs,
 	void		*inode)
 {
 	filemap_flush(((struct inode *)inode)->i_mapping);
@@ -512,7 +502,7 @@
 	xfs_inode_t	*ip)
 {
 	struct inode	*inode = vn_to_inode(XFS_ITOV(ip));
-	struct vfs	*vfs = XFS_MTOVFS(ip->i_mount);
+	struct bhv_vfs	*vfs = XFS_MTOVFS(ip->i_mount);
 
 	igrab(inode);
 	xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work);
@@ -525,7 +515,7 @@
  */
 STATIC void
 xfs_flush_device_work(
-	vfs_t		*vfs,
+	bhv_vfs_t	*vfs,
 	void		*inode)
 {
 	sync_blockdev(vfs->vfs_super->s_bdev);
@@ -537,7 +527,7 @@
 	xfs_inode_t	*ip)
 {
 	struct inode	*inode = vn_to_inode(XFS_ITOV(ip));
-	struct vfs	*vfs = XFS_MTOVFS(ip->i_mount);
+	struct bhv_vfs	*vfs = XFS_MTOVFS(ip->i_mount);
 
 	igrab(inode);
 	xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work);
@@ -545,16 +535,16 @@
 	xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
 }
 
-#define SYNCD_FLAGS	(SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR|SYNC_REFCACHE)
 STATIC void
 vfs_sync_worker(
-	vfs_t		*vfsp,
+	bhv_vfs_t	*vfsp,
 	void		*unused)
 {
 	int		error;
 
 	if (!(vfsp->vfs_flag & VFS_RDONLY))
-		VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error);
+		error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \
+					SYNC_ATTR | SYNC_REFCACHE, NULL);
 	vfsp->vfs_sync_seq++;
 	wmb();
 	wake_up(&vfsp->vfs_wait_single_sync_task);
@@ -565,8 +555,8 @@
 	void			*arg)
 {
 	long			timeleft;
-	vfs_t			*vfsp = (vfs_t *) arg;
-	struct vfs_sync_work	*work, *n;
+	bhv_vfs_t		*vfsp = (bhv_vfs_t *) arg;
+	bhv_vfs_sync_work_t	*work, *n;
 	LIST_HEAD		(tmp);
 
 	timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
@@ -600,7 +590,7 @@
 			list_del(&work->w_list);
 			if (work == &vfsp->vfs_sync_work)
 				continue;
-			kmem_free(work, sizeof(struct vfs_sync_work));
+			kmem_free(work, sizeof(struct bhv_vfs_sync_work));
 		}
 	}
 
@@ -609,7 +599,7 @@
 
 STATIC int
 xfs_fs_start_syncd(
-	vfs_t			*vfsp)
+	bhv_vfs_t		*vfsp)
 {
 	vfsp->vfs_sync_work.w_syncer = vfs_sync_worker;
 	vfsp->vfs_sync_work.w_vfs = vfsp;
@@ -621,7 +611,7 @@
 
 STATIC void
 xfs_fs_stop_syncd(
-	vfs_t			*vfsp)
+	bhv_vfs_t		*vfsp)
 {
 	kthread_stop(vfsp->vfs_sync_task);
 }
@@ -630,35 +620,26 @@
 xfs_fs_put_super(
 	struct super_block	*sb)
 {
-	vfs_t			*vfsp = vfs_from_sb(sb);
+	bhv_vfs_t		*vfsp = vfs_from_sb(sb);
 	int			error;
 
 	xfs_fs_stop_syncd(vfsp);
-	VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error);
-	if (!error)
-		VFS_UNMOUNT(vfsp, 0, NULL, error);
+	bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL);
+	error = bhv_vfs_unmount(vfsp, 0, NULL);
 	if (error) {
-		printk("XFS unmount got error %d\n", error);
-		printk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp);
-		return;
+		printk("XFS: unmount got error=%d\n", error);
+		printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp);
+	} else {
+		vfs_deallocate(vfsp);
 	}
-
-	vfs_deallocate(vfsp);
 }
 
 STATIC void
 xfs_fs_write_super(
 	struct super_block	*sb)
 {
-	vfs_t			*vfsp = vfs_from_sb(sb);
-	int			error;
-
-	if (sb->s_flags & MS_RDONLY) {
-		sb->s_dirt = 0; /* paranoia */
-		return;
-	}
-	/* Push the log and superblock a little */
-	VFS_SYNC(vfsp, SYNC_FSDATA, NULL, error);
+	if (!(sb->s_flags & MS_RDONLY))
+		bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL);
 	sb->s_dirt = 0;
 }
 
@@ -667,16 +648,16 @@
 	struct super_block	*sb,
 	int			wait)
 {
-	vfs_t		*vfsp = vfs_from_sb(sb);
-	int		error;
-	int		flags = SYNC_FSDATA;
+	bhv_vfs_t		*vfsp = vfs_from_sb(sb);
+	int			error;
+	int			flags;
 
 	if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
 		flags = SYNC_QUIESCE;
 	else
 		flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
 
-	VFS_SYNC(vfsp, flags, NULL, error);
+	error = bhv_vfs_sync(vfsp, flags, NULL);
 	sb->s_dirt = 0;
 
 	if (unlikely(laptop_mode)) {
@@ -703,14 +684,11 @@
 
 STATIC int
 xfs_fs_statfs(
-	struct super_block	*sb,
+	struct dentry		*dentry,
 	struct kstatfs		*statp)
 {
-	vfs_t			*vfsp = vfs_from_sb(sb);
-	int			error;
-
-	VFS_STATVFS(vfsp, statp, NULL, error);
-	return -error;
+	return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp,
+				vn_from_inode(dentry->d_inode));
 }
 
 STATIC int
@@ -719,13 +697,13 @@
 	int			*flags,
 	char			*options)
 {
-	vfs_t			*vfsp = vfs_from_sb(sb);
+	bhv_vfs_t		*vfsp = vfs_from_sb(sb);
 	struct xfs_mount_args	*args = xfs_args_allocate(sb, 0);
 	int			error;
 
-	VFS_PARSEARGS(vfsp, options, args, 1, error);
+	error = bhv_vfs_parseargs(vfsp, options, args, 1);
 	if (!error)
-		VFS_MNTUPDATE(vfsp, flags, args, error);
+		error = bhv_vfs_mntupdate(vfsp, flags, args);
 	kmem_free(args, sizeof(*args));
 	return -error;
 }
@@ -734,7 +712,7 @@
 xfs_fs_lockfs(
 	struct super_block	*sb)
 {
-	VFS_FREEZE(vfs_from_sb(sb));
+	bhv_vfs_freeze(vfs_from_sb(sb));
 }
 
 STATIC int
@@ -742,11 +720,7 @@
 	struct seq_file		*m,
 	struct vfsmount		*mnt)
 {
-	struct vfs		*vfsp = vfs_from_sb(mnt->mnt_sb);
-	int			error;
-
-	VFS_SHOWARGS(vfsp, m, error);
-	return error;
+	return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m);
 }
 
 STATIC int
@@ -754,11 +728,7 @@
 	struct super_block	*sb,
 	int			type)
 {
-	struct vfs		*vfsp = vfs_from_sb(sb);
-	int			error;
-
-	VFS_QUOTACTL(vfsp, Q_XQUOTASYNC, 0, (caddr_t)NULL, error);
-	return -error;
+	return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL);
 }
 
 STATIC int
@@ -766,11 +736,7 @@
 	struct super_block	*sb,
 	struct fs_quota_stat	*fqs)
 {
-	struct vfs		*vfsp = vfs_from_sb(sb);
-	int			error;
-
-	VFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (caddr_t)fqs, error);
-	return -error;
+	return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs);
 }
 
 STATIC int
@@ -779,11 +745,7 @@
 	unsigned int		flags,
 	int			op)
 {
-	struct vfs		*vfsp = vfs_from_sb(sb);
-	int			error;
-
-	VFS_QUOTACTL(vfsp, op, 0, (caddr_t)&flags, error);
-	return -error;
+	return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags);
 }
 
 STATIC int
@@ -793,13 +755,10 @@
 	qid_t			id,
 	struct fs_disk_quota	*fdq)
 {
-	struct vfs		*vfsp = vfs_from_sb(sb);
-	int			error, getmode;
-
-	getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
-		 ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
-	VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
-	return -error;
+	return -bhv_vfs_quotactl(vfs_from_sb(sb),
+				 (type == USRQUOTA) ? Q_XGETQUOTA :
+				  ((type == GRPQUOTA) ? Q_XGETGQUOTA :
+				   Q_XGETPQUOTA), id, (caddr_t)fdq);
 }
 
 STATIC int
@@ -809,13 +768,10 @@
 	qid_t			id,
 	struct fs_disk_quota	*fdq)
 {
-	struct vfs		*vfsp = vfs_from_sb(sb);
-	int			error, setmode;
-
-	setmode = (type == USRQUOTA) ? Q_XSETQLIM :
-		 ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
-	VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
-	return -error;
+	return -bhv_vfs_quotactl(vfs_from_sb(sb),
+				 (type == USRQUOTA) ? Q_XSETQLIM :
+				  ((type == GRPQUOTA) ? Q_XSETGQLIM :
+				   Q_XSETPQLIM), id, (caddr_t)fdq);
 }
 
 STATIC int
@@ -824,34 +780,32 @@
 	void			*data,
 	int			silent)
 {
-	vnode_t			*rootvp;
-	struct vfs		*vfsp = vfs_allocate(sb);
+	struct bhv_vnode	*rootvp;
+	struct bhv_vfs		*vfsp = vfs_allocate(sb);
 	struct xfs_mount_args	*args = xfs_args_allocate(sb, silent);
 	struct kstatfs		statvfs;
-	int			error, error2;
+	int			error;
 
 	bhv_insert_all_vfsops(vfsp);
 
-	VFS_PARSEARGS(vfsp, (char *)data, args, 0, error);
+	error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0);
 	if (error) {
 		bhv_remove_all_vfsops(vfsp, 1);
 		goto fail_vfsop;
 	}
 
 	sb_min_blocksize(sb, BBSIZE);
-#ifdef CONFIG_XFS_EXPORT
 	sb->s_export_op = &xfs_export_operations;
-#endif
 	sb->s_qcop = &xfs_quotactl_operations;
 	sb->s_op = &xfs_super_operations;
 
-	VFS_MOUNT(vfsp, args, NULL, error);
+	error = bhv_vfs_mount(vfsp, args, NULL);
 	if (error) {
 		bhv_remove_all_vfsops(vfsp, 1);
 		goto fail_vfsop;
 	}
 
-	VFS_STATVFS(vfsp, &statvfs, NULL, error);
+	error = bhv_vfs_statvfs(vfsp, &statvfs, NULL);
 	if (error)
 		goto fail_unmount;
 
@@ -863,7 +817,7 @@
 	sb->s_time_gran = 1;
 	set_posix_acl_flag(sb);
 
-	VFS_ROOT(vfsp, &rootvp, error);
+	error = bhv_vfs_root(vfsp, &rootvp);
 	if (error)
 		goto fail_unmount;
 
@@ -892,7 +846,7 @@
 	}
 
 fail_unmount:
-	VFS_UNMOUNT(vfsp, 0, NULL, error2);
+	bhv_vfs_unmount(vfsp, 0, NULL);
 
 fail_vfsop:
 	vfs_deallocate(vfsp);
@@ -900,14 +854,16 @@
 	return -error;
 }
 
-STATIC struct super_block *
+STATIC int
 xfs_fs_get_sb(
 	struct file_system_type	*fs_type,
 	int			flags,
 	const char		*dev_name,
-	void			*data)
+	void			*data,
+	struct vfsmount		*mnt)
 {
-	return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super);
+	return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super,
+			   mnt);
 }
 
 STATIC struct super_operations xfs_super_operations = {
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h
index 376b96c..33dd1ca 100644
--- a/fs/xfs/linux-2.6/xfs_super.h
+++ b/fs/xfs/linux-2.6/xfs_super.h
@@ -105,7 +105,7 @@
 
 extern __uint64_t xfs_max_file_offset(unsigned int);
 
-extern void xfs_initialize_vnode(bhv_desc_t *, vnode_t *, bhv_desc_t *, int);
+extern void xfs_initialize_vnode(bhv_desc_t *, bhv_vnode_t *, bhv_desc_t *, int);
 
 extern void xfs_flush_inode(struct xfs_inode *);
 extern void xfs_flush_device(struct xfs_inode *);
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c
index 7079cc8..af24653 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.c
+++ b/fs/xfs/linux-2.6/xfs_sysctl.c
@@ -38,7 +38,7 @@
 
 	if (!ret && write && *valp) {
 		printk("XFS Clearing xfsstats\n");
-		for_each_cpu(c) {
+		for_each_possible_cpu(c) {
 			preempt_disable();
 			/* save vn_active, it's a universal truth! */
 			vn_active = per_cpu(xfsstats, c).vn_active;
@@ -120,6 +120,11 @@
 	&sysctl_intvec, NULL,
 	&xfs_params.rotorstep.min, &xfs_params.rotorstep.max},
 
+	{XFS_INHERIT_NODFRG, "inherit_nodefrag", &xfs_params.inherit_nodfrg.val,
+	sizeof(int), 0644, NULL, &proc_dointvec_minmax,
+	&sysctl_intvec, NULL,
+	&xfs_params.inherit_nodfrg.min, &xfs_params.inherit_nodfrg.max},
+
 	/* please keep this the last entry */
 #ifdef CONFIG_PROC_FS
 	{XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val,
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h
index bc8c11f..a631fb8 100644
--- a/fs/xfs/linux-2.6/xfs_sysctl.h
+++ b/fs/xfs/linux-2.6/xfs_sysctl.h
@@ -46,6 +46,7 @@
 	xfs_sysctl_val_t xfs_buf_age;	/* Metadata buffer age before flush. */
 	xfs_sysctl_val_t inherit_nosym;	/* Inherit the "nosymlinks" flag. */
 	xfs_sysctl_val_t rotorstep;	/* inode32 AG rotoring control knob */
+	xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */
 } xfs_param_t;
 
 /*
@@ -84,6 +85,7 @@
 	/* XFS_IO_BYPASS = 18 */
 	XFS_INHERIT_NOSYM = 19,
 	XFS_ROTORSTEP = 20,
+	XFS_INHERIT_NODFRG = 21,
 };
 
 extern xfs_param_t	xfs_params;
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c
index 6f7c9f7..6145e8b 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.c
+++ b/fs/xfs/linux-2.6/xfs_vfs.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_imap.h"
 #include "xfs_alloc.h"
@@ -104,7 +103,7 @@
 int
 vfs_root(
 	struct bhv_desc		*bdp,
-	struct vnode		**vpp)
+	struct bhv_vnode	**vpp)
 {
 	struct bhv_desc		*next = bdp;
 
@@ -117,15 +116,15 @@
 int
 vfs_statvfs(
 	struct bhv_desc		*bdp,
-	xfs_statfs_t		*sp,
-	struct vnode		*vp)
+	bhv_statvfs_t		*statp,
+	struct bhv_vnode	*vp)
 {
 	struct bhv_desc		*next = bdp;
 
 	ASSERT(next);
 	while (! (bhvtovfsops(next))->vfs_statvfs)
 		next = BHV_NEXT(next);
-	return ((*bhvtovfsops(next)->vfs_statvfs)(next, sp, vp));
+	return ((*bhvtovfsops(next)->vfs_statvfs)(next, statp, vp));
 }
 
 int
@@ -145,7 +144,7 @@
 int
 vfs_vget(
 	struct bhv_desc		*bdp,
-	struct vnode		**vpp,
+	struct bhv_vnode	**vpp,
 	struct fid		*fidp)
 {
 	struct bhv_desc		*next = bdp;
@@ -187,7 +186,7 @@
 void
 vfs_init_vnode(
 	struct bhv_desc		*bdp,
-	struct vnode		*vp,
+	struct bhv_vnode	*vp,
 	struct bhv_desc		*bp,
 	int			unlock)
 {
@@ -226,13 +225,13 @@
 	((*bhvtovfsops(next)->vfs_freeze)(next));
 }
 
-vfs_t *
+bhv_vfs_t *
 vfs_allocate(
 	struct super_block	*sb)
 {
-	struct vfs		*vfsp;
+	struct bhv_vfs		*vfsp;
 
-	vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP);
+	vfsp = kmem_zalloc(sizeof(bhv_vfs_t), KM_SLEEP);
 	bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
 	INIT_LIST_HEAD(&vfsp->vfs_sync_list);
 	spin_lock_init(&vfsp->vfs_sync_lock);
@@ -247,25 +246,25 @@
 	return vfsp;
 }
 
-vfs_t *
+bhv_vfs_t *
 vfs_from_sb(
 	struct super_block	*sb)
 {
-	return (vfs_t *)sb->s_fs_info;
+	return (bhv_vfs_t *)sb->s_fs_info;
 }
 
 void
 vfs_deallocate(
-	struct vfs		*vfsp)
+	struct bhv_vfs		*vfsp)
 {
 	bhv_head_destroy(VFS_BHVHEAD(vfsp));
-	kmem_free(vfsp, sizeof(vfs_t));
+	kmem_free(vfsp, sizeof(bhv_vfs_t));
 }
 
 void
 vfs_insertops(
-	struct vfs		*vfsp,
-	struct bhv_vfsops	*vfsops)
+	struct bhv_vfs		*vfsp,
+	struct bhv_module_vfsops *vfsops)
 {
 	struct bhv_desc		*bdp;
 
@@ -276,9 +275,9 @@
 
 void
 vfs_insertbhv(
-	struct vfs		*vfsp,
+	struct bhv_vfs		*vfsp,
 	struct bhv_desc		*bdp,
-	struct vfsops		*vfsops,
+	struct bhv_vfsops	*vfsops,
 	void			*mount)
 {
 	bhv_desc_init(bdp, mount, vfsp, vfsops);
@@ -287,7 +286,7 @@
 
 void
 bhv_remove_vfsops(
-	struct vfs		*vfsp,
+	struct bhv_vfs		*vfsp,
 	int			pos)
 {
 	struct bhv_desc		*bhv;
@@ -301,7 +300,7 @@
 
 void
 bhv_remove_all_vfsops(
-	struct vfs		*vfsp,
+	struct bhv_vfs		*vfsp,
 	int			freebase)
 {
 	struct xfs_mount	*mp;
@@ -317,7 +316,7 @@
 
 void
 bhv_insert_all_vfsops(
-	struct vfs		*vfsp)
+	struct bhv_vfs		*vfsp)
 {
 	struct xfs_mount	*mp;
 
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 841200c..91fc2c4 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -21,42 +21,40 @@
 #include <linux/vfs.h>
 #include "xfs_fs.h"
 
+struct bhv_vfs;
+struct bhv_vnode;
+
 struct fid;
-struct vfs;
 struct cred;
-struct vnode;
-struct kstatfs;
 struct seq_file;
 struct super_block;
 struct xfs_mount_args;
 
-typedef struct kstatfs xfs_statfs_t;
+typedef struct kstatfs	bhv_statvfs_t;
 
-typedef struct vfs_sync_work {
+typedef struct bhv_vfs_sync_work {
 	struct list_head	w_list;
-	struct vfs		*w_vfs;
+	struct bhv_vfs		*w_vfs;
 	void			*w_data;	/* syncer routine argument */
-	void			(*w_syncer)(struct vfs *, void *);
-} vfs_sync_work_t;
+	void			(*w_syncer)(struct bhv_vfs *, void *);
+} bhv_vfs_sync_work_t;
 
-typedef struct vfs {
+typedef struct bhv_vfs {
 	u_int			vfs_flag;	/* flags */
 	xfs_fsid_t		vfs_fsid;	/* file system ID */
 	xfs_fsid_t		*vfs_altfsid;	/* An ID fixed for life of FS */
 	bhv_head_t		vfs_bh;		/* head of vfs behavior chain */
 	struct super_block	*vfs_super;	/* generic superblock pointer */
 	struct task_struct	*vfs_sync_task;	/* generalised sync thread */
-	vfs_sync_work_t		vfs_sync_work;	/* work item for VFS_SYNC */
+	bhv_vfs_sync_work_t	vfs_sync_work;	/* work item for VFS_SYNC */
 	struct list_head	vfs_sync_list;	/* sync thread work item list */
 	spinlock_t		vfs_sync_lock;	/* work item list lock */
-	int 			vfs_sync_seq;	/* sync thread generation no. */
+	int			vfs_sync_seq;	/* sync thread generation no. */
 	wait_queue_head_t	vfs_wait_single_sync_task;
-} vfs_t;
+} bhv_vfs_t;
 
-#define vfs_fbhv		vfs_bh.bh_first	/* 1st on vfs behavior chain */
-
-#define bhvtovfs(bdp)		( (struct vfs *)BHV_VOBJ(bdp) )
-#define bhvtovfsops(bdp)	( (struct vfsops *)BHV_OPS(bdp) )
+#define bhvtovfs(bdp)		( (struct bhv_vfs *)BHV_VOBJ(bdp) )
+#define bhvtovfsops(bdp)	( (struct bhv_vfsops *)BHV_OPS(bdp) )
 #define VFS_BHVHEAD(vfs)	( &(vfs)->vfs_bh )
 #define VFS_REMOVEBHV(vfs, bdp)	( bhv_remove(VFS_BHVHEAD(vfs), bdp) )
 
@@ -71,7 +69,7 @@
 	VFS_BHV_QM,		/* quota manager */
 	VFS_BHV_IO,		/* IO path */
 	VFS_BHV_END		/* housekeeping end-of-range */
-} vfs_bhv_t;
+} bhv_vfs_type_t;
 
 #define VFS_POSITION_XFS	(BHV_POSITION_BASE)
 #define VFS_POSITION_DM		(VFS_POSITION_BASE+10)
@@ -81,8 +79,9 @@
 #define VFS_RDONLY		0x0001	/* read-only vfs */
 #define VFS_GRPID		0x0002	/* group-ID assigned from directory */
 #define VFS_DMI			0x0004	/* filesystem has the DMI enabled */
-#define VFS_32BITINODES		0x0008	/* do not use inums above 32 bits */
-#define VFS_END			0x0008	/* max flag */
+#define VFS_UMOUNT		0x0008	/* unmount in progress */
+#define VFS_32BITINODES		0x0010	/* do not use inums above 32 bits */
+#define VFS_END			0x0010	/* max flag */
 
 #define SYNC_ATTR		0x0001	/* sync attributes */
 #define SYNC_CLOSE		0x0002	/* close file system down */
@@ -92,7 +91,14 @@
 #define SYNC_FSDATA		0x0020	/* flush fs data (e.g. superblocks) */
 #define SYNC_REFCACHE		0x0040  /* prune some of the nfs ref cache */
 #define SYNC_REMOUNT		0x0080  /* remount readonly, no dummy LRs */
-#define SYNC_QUIESCE		0x0100  /* quiesce filesystem for a snapshot */
+#define SYNC_QUIESCE		0x0100  /* quiesce fileystem for a snapshot */
+
+#define SHUTDOWN_META_IO_ERROR	0x0001	/* write attempt to metadata failed */
+#define SHUTDOWN_LOG_IO_ERROR	0x0002	/* write attempt to the log failed */
+#define SHUTDOWN_FORCE_UMOUNT	0x0004	/* shutdown from a forced unmount */
+#define SHUTDOWN_CORRUPT_INCORE	0x0008	/* corrupt in-memory data structures */
+#define SHUTDOWN_REMOTE_REQ	0x0010	/* shutdown came from remote cell */
+#define SHUTDOWN_DEVICE_REQ	0x0020	/* failed all paths to the device */
 
 typedef int	(*vfs_mount_t)(bhv_desc_t *,
 				struct xfs_mount_args *, struct cred *);
@@ -102,18 +108,19 @@
 typedef int	(*vfs_unmount_t)(bhv_desc_t *, int, struct cred *);
 typedef int	(*vfs_mntupdate_t)(bhv_desc_t *, int *,
 				struct xfs_mount_args *);
-typedef int	(*vfs_root_t)(bhv_desc_t *, struct vnode **);
-typedef int	(*vfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, struct vnode *);
+typedef int	(*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **);
+typedef int	(*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *,
+				struct bhv_vnode *);
 typedef int	(*vfs_sync_t)(bhv_desc_t *, int, struct cred *);
-typedef int	(*vfs_vget_t)(bhv_desc_t *, struct vnode **, struct fid *);
+typedef int	(*vfs_vget_t)(bhv_desc_t *, struct bhv_vnode **, struct fid *);
 typedef int	(*vfs_dmapiops_t)(bhv_desc_t *, caddr_t);
 typedef int	(*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t);
 typedef void	(*vfs_init_vnode_t)(bhv_desc_t *,
-				struct vnode *, bhv_desc_t *, int);
+				struct bhv_vnode *, bhv_desc_t *, int);
 typedef void	(*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int);
 typedef void	(*vfs_freeze_t)(bhv_desc_t *);
 
-typedef struct vfsops {
+typedef struct bhv_vfsops {
 	bhv_position_t		vf_position;	/* behavior chain position */
 	vfs_mount_t		vfs_mount;	/* mount file system */
 	vfs_parseargs_t		vfs_parseargs;	/* parse mount options */
@@ -129,82 +136,82 @@
 	vfs_init_vnode_t	vfs_init_vnode;	/* initialize a new vnode */
 	vfs_force_shutdown_t	vfs_force_shutdown;	/* crash and burn */
 	vfs_freeze_t		vfs_freeze;	/* freeze fs for snapshot */
-} vfsops_t;
+} bhv_vfsops_t;
 
 /*
- * VFS's.  Operates on vfs structure pointers (starts at bhv head).
+ * Virtual filesystem operations, operating from head bhv.
  */
-#define VHEAD(v)			((v)->vfs_fbhv)
-#define VFS_MOUNT(v, ma,cr, rv)		((rv) = vfs_mount(VHEAD(v), ma,cr))
-#define VFS_PARSEARGS(v, o,ma,f, rv)	((rv) = vfs_parseargs(VHEAD(v), o,ma,f))
-#define VFS_SHOWARGS(v, m, rv)		((rv) = vfs_showargs(VHEAD(v), m))
-#define VFS_UNMOUNT(v, f, cr, rv)	((rv) = vfs_unmount(VHEAD(v), f,cr))
-#define VFS_MNTUPDATE(v, fl, args, rv)	((rv) = vfs_mntupdate(VHEAD(v), fl, args))
-#define VFS_ROOT(v, vpp, rv)		((rv) = vfs_root(VHEAD(v), vpp))
-#define VFS_STATVFS(v, sp,vp, rv)	((rv) = vfs_statvfs(VHEAD(v), sp,vp))
-#define VFS_SYNC(v, flag,cr, rv)	((rv) = vfs_sync(VHEAD(v), flag,cr))
-#define VFS_VGET(v, vpp,fidp, rv)	((rv) = vfs_vget(VHEAD(v), vpp,fidp))
-#define VFS_DMAPIOPS(v, p, rv)		((rv) = vfs_dmapiops(VHEAD(v), p))
-#define VFS_QUOTACTL(v, c,id,p, rv)	((rv) = vfs_quotactl(VHEAD(v), c,id,p))
-#define VFS_INIT_VNODE(v, vp,b,ul)	( vfs_init_vnode(VHEAD(v), vp,b,ul) )
-#define VFS_FORCE_SHUTDOWN(v, fl,f,l)	( vfs_force_shutdown(VHEAD(v), fl,f,l) )
-#define VFS_FREEZE(v)			( vfs_freeze(VHEAD(v)) )
+#define VFSHEAD(v)			((v)->vfs_bh.bh_first)
+#define bhv_vfs_mount(v, ma,cr)		vfs_mount(VFSHEAD(v), ma,cr)
+#define bhv_vfs_parseargs(v, o,ma,f)	vfs_parseargs(VFSHEAD(v), o,ma,f)
+#define bhv_vfs_showargs(v, m)		vfs_showargs(VFSHEAD(v), m)
+#define bhv_vfs_unmount(v, f,cr)	vfs_unmount(VFSHEAD(v), f,cr)
+#define bhv_vfs_mntupdate(v, fl,args)	vfs_mntupdate(VFSHEAD(v), fl,args)
+#define bhv_vfs_root(v, vpp)		vfs_root(VFSHEAD(v), vpp)
+#define bhv_vfs_statvfs(v, sp,vp)	vfs_statvfs(VFSHEAD(v), sp,vp)
+#define bhv_vfs_sync(v, flag,cr)	vfs_sync(VFSHEAD(v), flag,cr)
+#define bhv_vfs_vget(v, vpp,fidp)	vfs_vget(VFSHEAD(v), vpp,fidp)
+#define bhv_vfs_dmapiops(v, p)		vfs_dmapiops(VFSHEAD(v), p)
+#define bhv_vfs_quotactl(v, c,id,p)	vfs_quotactl(VFSHEAD(v), c,id,p)
+#define bhv_vfs_init_vnode(v, vp,b,ul)	vfs_init_vnode(VFSHEAD(v), vp,b,ul)
+#define bhv_vfs_force_shutdown(v,u,f,l)	vfs_force_shutdown(VFSHEAD(v), u,f,l)
+#define bhv_vfs_freeze(v)		vfs_freeze(VFSHEAD(v))
 
 /*
- * PVFS's.  Operates on behavior descriptor pointers.
+ * Virtual filesystem operations, operating from next bhv.
  */
-#define PVFS_MOUNT(b, ma,cr, rv)	((rv) = vfs_mount(b, ma,cr))
-#define PVFS_PARSEARGS(b, o,ma,f, rv)	((rv) = vfs_parseargs(b, o,ma,f))
-#define PVFS_SHOWARGS(b, m, rv)		((rv) = vfs_showargs(b, m))
-#define PVFS_UNMOUNT(b, f,cr, rv)	((rv) = vfs_unmount(b, f,cr))
-#define PVFS_MNTUPDATE(b, fl, args, rv)	((rv) = vfs_mntupdate(b, fl, args))
-#define PVFS_ROOT(b, vpp, rv)		((rv) = vfs_root(b, vpp))
-#define PVFS_STATVFS(b, sp,vp, rv)	((rv) = vfs_statvfs(b, sp,vp))
-#define PVFS_SYNC(b, flag,cr, rv)	((rv) = vfs_sync(b, flag,cr))
-#define PVFS_VGET(b, vpp,fidp, rv)	((rv) = vfs_vget(b, vpp,fidp))
-#define PVFS_DMAPIOPS(b, p, rv)		((rv) = vfs_dmapiops(b, p))
-#define PVFS_QUOTACTL(b, c,id,p, rv)	((rv) = vfs_quotactl(b, c,id,p))
-#define PVFS_INIT_VNODE(b, vp,b2,ul)	( vfs_init_vnode(b, vp,b2,ul) )
-#define PVFS_FORCE_SHUTDOWN(b, fl,f,l)	( vfs_force_shutdown(b, fl,f,l) )
-#define PVFS_FREEZE(b)			( vfs_freeze(b) )
+#define bhv_next_vfs_mount(b, ma,cr)		vfs_mount(b, ma,cr)
+#define bhv_next_vfs_parseargs(b, o,ma,f)	vfs_parseargs(b, o,ma,f)
+#define bhv_next_vfs_showargs(b, m)		vfs_showargs(b, m)
+#define bhv_next_vfs_unmount(b, f,cr)		vfs_unmount(b, f,cr)
+#define bhv_next_vfs_mntupdate(b, fl,args)	vfs_mntupdate(b, fl, args)
+#define bhv_next_vfs_root(b, vpp)		vfs_root(b, vpp)
+#define bhv_next_vfs_statvfs(b, sp,vp)		vfs_statvfs(b, sp,vp)
+#define bhv_next_vfs_sync(b, flag,cr)		vfs_sync(b, flag,cr)
+#define bhv_next_vfs_vget(b, vpp,fidp)		vfs_vget(b, vpp,fidp)
+#define bhv_next_vfs_dmapiops(b, p)		vfs_dmapiops(b, p)
+#define bhv_next_vfs_quotactl(b, c,id,p)	vfs_quotactl(b, c,id,p)
+#define bhv_next_vfs_init_vnode(b, vp,b2,ul)	vfs_init_vnode(b, vp,b2,ul)
+#define bhv_next_force_shutdown(b, fl,f,l)	vfs_force_shutdown(b, fl,f,l)
+#define bhv_next_vfs_freeze(b)			vfs_freeze(b)
 
 extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *);
 extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int);
 extern int vfs_showargs(bhv_desc_t *, struct seq_file *);
 extern int vfs_unmount(bhv_desc_t *, int, struct cred *);
 extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *);
-extern int vfs_root(bhv_desc_t *, struct vnode **);
-extern int vfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct vnode *);
+extern int vfs_root(bhv_desc_t *, struct bhv_vnode **);
+extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *);
 extern int vfs_sync(bhv_desc_t *, int, struct cred *);
-extern int vfs_vget(bhv_desc_t *, struct vnode **, struct fid *);
+extern int vfs_vget(bhv_desc_t *, struct bhv_vnode **, struct fid *);
 extern int vfs_dmapiops(bhv_desc_t *, caddr_t);
 extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t);
-extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int);
+extern void vfs_init_vnode(bhv_desc_t *, struct bhv_vnode *, bhv_desc_t *, int);
 extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int);
 extern void vfs_freeze(bhv_desc_t *);
 
-typedef struct bhv_vfsops {
-	struct vfsops		bhv_common;
+#define vfs_test_for_freeze(vfs)	((vfs)->vfs_super->s_frozen)
+#define vfs_wait_for_freeze(vfs,l)	vfs_check_frozen((vfs)->vfs_super, (l))
+ 
+typedef struct bhv_module_vfsops {
+	struct bhv_vfsops	bhv_common;
 	void *			bhv_custom;
-} bhv_vfsops_t;
+} bhv_module_vfsops_t;
 
-#define vfs_bhv_lookup(v, id)	( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) )
-#define vfs_bhv_custom(b)	( ((bhv_vfsops_t *)BHV_OPS(b))->bhv_custom )
-#define vfs_bhv_set_custom(b,o)	( (b)->bhv_custom = (void *)(o))
-#define vfs_bhv_clr_custom(b)	( (b)->bhv_custom = NULL )
+#define vfs_bhv_lookup(v, id)	(bhv_lookup_range(&(v)->vfs_bh, (id), (id)))
+#define vfs_bhv_custom(b)	(((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom)
+#define vfs_bhv_set_custom(b,o)	((b)->bhv_custom = (void *)(o))
+#define vfs_bhv_clr_custom(b)	((b)->bhv_custom = NULL)
 
-extern vfs_t *vfs_allocate(struct super_block *);
-extern vfs_t *vfs_from_sb(struct super_block *);
-extern void vfs_deallocate(vfs_t *);
-extern void vfs_insertops(vfs_t *, bhv_vfsops_t *);
-extern void vfs_insertbhv(vfs_t *, bhv_desc_t *, vfsops_t *, void *);
+extern bhv_vfs_t *vfs_allocate(struct super_block *);
+extern bhv_vfs_t *vfs_from_sb(struct super_block *);
+extern void vfs_deallocate(bhv_vfs_t *);
+extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *);
 
-extern void bhv_insert_all_vfsops(struct vfs *);
-extern void bhv_remove_all_vfsops(struct vfs *, int);
-extern void bhv_remove_vfsops(struct vfs *, int);
+extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *);
 
-#define fs_frozen(vfsp)		((vfsp)->vfs_super->s_frozen)
-#define fs_check_frozen(vfsp, level) \
-	vfs_check_frozen(vfsp->vfs_super, level);
+extern void bhv_insert_all_vfsops(struct bhv_vfs *);
+extern void bhv_remove_all_vfsops(struct bhv_vfs *, int);
+extern void bhv_remove_vfsops(struct bhv_vfs *, int);
 
 #endif	/* __XFS_VFS_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index d27c25b..6628d96 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -39,7 +39,7 @@
 
 void
 vn_iowait(
-	struct vnode	*vp)
+	bhv_vnode_t	*vp)
 {
 	wait_queue_head_t *wq = vptosync(vp);
 
@@ -48,17 +48,33 @@
 
 void
 vn_iowake(
-	struct vnode	*vp)
+	bhv_vnode_t	*vp)
 {
 	if (atomic_dec_and_test(&vp->v_iocount))
 		wake_up(vptosync(vp));
 }
 
-struct vnode *
+/*
+ * Volume managers supporting multiple paths can send back ENODEV when the
+ * final path disappears.  In this case continuing to fill the page cache
+ * with dirty data which cannot be written out is evil, so prevent that.
+ */
+void
+vn_ioerror(
+	bhv_vnode_t	*vp,
+	int		error,
+	char		*f,
+	int		l)
+{
+	if (unlikely(error == -ENODEV))
+		bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l);
+}
+
+bhv_vnode_t *
 vn_initialize(
 	struct inode	*inode)
 {
-	struct vnode	*vp = vn_from_inode(inode);
+	bhv_vnode_t	*vp = vn_from_inode(inode);
 
 	XFS_STATS_INC(vn_active);
 	XFS_STATS_INC(vn_alloc);
@@ -94,8 +110,8 @@
  */
 void
 vn_revalidate_core(
-	struct vnode	*vp,
-	vattr_t		*vap)
+	bhv_vnode_t	*vp,
+	bhv_vattr_t	*vap)
 {
 	struct inode	*inode = vn_to_inode(vp);
 
@@ -130,14 +146,14 @@
  */
 int
 __vn_revalidate(
-	struct vnode	*vp,
-	struct vattr	*vattr)
+	bhv_vnode_t	*vp,
+	bhv_vattr_t	*vattr)
 {
 	int		error;
 
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
 	vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS;
-	VOP_GETATTR(vp, vattr, 0, NULL, error);
+	error = bhv_vop_getattr(vp, vattr, 0, NULL);
 	if (likely(!error)) {
 		vn_revalidate_core(vp, vattr);
 		VUNMODIFY(vp);
@@ -147,9 +163,9 @@
 
 int
 vn_revalidate(
-	struct vnode	*vp)
+	bhv_vnode_t	*vp)
 {
-	vattr_t		vattr;
+	bhv_vattr_t	vattr;
 
 	return __vn_revalidate(vp, &vattr);
 }
@@ -157,9 +173,9 @@
 /*
  * Add a reference to a referenced vnode.
  */
-struct vnode *
+bhv_vnode_t *
 vn_hold(
-	struct vnode	*vp)
+	bhv_vnode_t	*vp)
 {
 	struct inode	*inode;
 
@@ -192,31 +208,31 @@
  * Vnode tracing code.
  */
 void
-vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra)
+vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra)
 {
 	KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra);
 }
 
 void
-vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra)
+vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra)
 {
 	KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra);
 }
 
 void
-vn_trace_hold(vnode_t *vp, char *file, int line, inst_t *ra)
+vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
 {
 	KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra);
 }
 
 void
-vn_trace_ref(vnode_t *vp, char *file, int line, inst_t *ra)
+vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
 {
 	KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra);
 }
 
 void
-vn_trace_rele(vnode_t *vp, char *file, int line, inst_t *ra)
+vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra)
 {
 	KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra);
 }
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 2a8e16c..c42b322 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -14,57 +14,35 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write the Free Software Foundation,
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Portions Copyright (c) 1989, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
  */
 #ifndef __XFS_VNODE_H__
 #define __XFS_VNODE_H__
 
 struct uio;
 struct file;
-struct vattr;
+struct bhv_vfs;
+struct bhv_vattr;
 struct xfs_iomap;
 struct attrlist_cursor_kern;
 
+typedef struct dentry	bhv_vname_t;
+typedef __u64		bhv_vnumber_t;
 
-typedef xfs_ino_t vnumber_t;
-typedef struct dentry vname_t;
-typedef bhv_head_t vn_bhv_head_t;
+typedef enum bhv_vflags {
+	VMODIFIED	= 0x08,	/* XFS inode state possibly differs */
+				/* to the Linux inode state. */
+	VTRUNCATED	= 0x40,	/* truncated down so flush-on-close */
+} bhv_vflags_t;
 
 /*
  * MP locking protocols:
  *	v_flag, v_vfsp				VN_LOCK/VN_UNLOCK
  */
-typedef struct vnode {
-	__u32		v_flag;			/* vnode flags (see below) */
-	struct vfs	*v_vfsp;		/* ptr to containing VFS */
-	vnumber_t	v_number;		/* in-core vnode number */
-	vn_bhv_head_t	v_bh;			/* behavior head */
+typedef struct bhv_vnode {
+	bhv_vflags_t	v_flag;			/* vnode flags (see above) */
+	bhv_vfs_t	*v_vfsp;		/* ptr to containing VFS */
+	bhv_vnumber_t	v_number;		/* in-core vnode number */
+	bhv_head_t	v_bh;			/* behavior head */
 	spinlock_t	v_lock;			/* VN_LOCK/VN_UNLOCK */
 	atomic_t	v_iocount;		/* outstanding I/O count */
 #ifdef XFS_VNODE_TRACE
@@ -72,7 +50,7 @@
 #endif
 	struct inode	v_inode;		/* Linux inode */
 	/* inode MUST be last */
-} vnode_t;
+} bhv_vnode_t;
 
 #define VN_ISLNK(vp)	S_ISLNK((vp)->v_inode.i_mode)
 #define VN_ISREG(vp)	S_ISREG((vp)->v_inode.i_mode)
@@ -80,9 +58,6 @@
 #define VN_ISCHR(vp)	S_ISCHR((vp)->v_inode.i_mode)
 #define VN_ISBLK(vp)	S_ISBLK((vp)->v_inode.i_mode)
 
-#define v_fbhv			v_bh.bh_first	       /* first behavior */
-#define v_fops			v_bh.bh_first->bd_ops  /* first behavior ops */
-
 #define VNODE_POSITION_BASE	BHV_POSITION_BASE	/* chain bottom */
 #define VNODE_POSITION_TOP	BHV_POSITION_TOP	/* chain top */
 #define VNODE_POSITION_INVALID	BHV_POSITION_INVALID	/* invalid pos. num */
@@ -104,8 +79,8 @@
 /*
  * Macros for dealing with the behavior descriptor inside of the vnode.
  */
-#define BHV_TO_VNODE(bdp)	((vnode_t *)BHV_VOBJ(bdp))
-#define BHV_TO_VNODE_NULL(bdp)	((vnode_t *)BHV_VOBJNULL(bdp))
+#define BHV_TO_VNODE(bdp)	((bhv_vnode_t *)BHV_VOBJ(bdp))
+#define BHV_TO_VNODE_NULL(bdp)	((bhv_vnode_t *)BHV_VOBJNULL(bdp))
 
 #define VN_BHV_HEAD(vp)			((bhv_head_t *)(&((vp)->v_bh)))
 #define vn_bhv_head_init(bhp,name)	bhv_head_init(bhp,name)
@@ -116,35 +91,29 @@
 /*
  * Vnode to Linux inode mapping.
  */
-static inline struct vnode *vn_from_inode(struct inode *inode)
+static inline struct bhv_vnode *vn_from_inode(struct inode *inode)
 {
-	return (vnode_t *)list_entry(inode, vnode_t, v_inode);
+	return container_of(inode, bhv_vnode_t, v_inode);
 }
-static inline struct inode *vn_to_inode(struct vnode *vnode)
+static inline struct inode *vn_to_inode(struct bhv_vnode *vnode)
 {
 	return &vnode->v_inode;
 }
 
 /*
- * Vnode flags.
+ * Values for the vop_rwlock/rwunlock flags parameter.
  */
-#define VMODIFIED	       0x8	/* XFS inode state possibly differs */
-					/* to the Linux inode state.	*/
-
-/*
- * Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter.
- */
-typedef enum vrwlock {
+typedef enum bhv_vrwlock {
 	VRWLOCK_NONE,
 	VRWLOCK_READ,
 	VRWLOCK_WRITE,
 	VRWLOCK_WRITE_DIRECT,
 	VRWLOCK_TRY_READ,
 	VRWLOCK_TRY_WRITE
-} vrwlock_t;
+} bhv_vrwlock_t;
 
 /*
- * Return values for VOP_INACTIVE.  A return value of
+ * Return values for bhv_vop_inactive.  A return value of
  * VN_INACTIVE_NOCACHE implies that the file system behavior
  * has disassociated its state and bhv_desc_t from the vnode.
  */
@@ -152,18 +121,20 @@
 #define	VN_INACTIVE_NOCACHE	1
 
 /*
- * Values for the cmd code given to VOP_VNODE_CHANGE.
+ * Values for the cmd code given to vop_vnode_change.
  */
-typedef enum vchange {
+typedef enum bhv_vchange {
 	VCHANGE_FLAGS_FRLOCKS		= 0,
 	VCHANGE_FLAGS_ENF_LOCKING	= 1,
 	VCHANGE_FLAGS_TRUNCATED		= 2,
 	VCHANGE_FLAGS_PAGE_DIRTY	= 3,
 	VCHANGE_FLAGS_IOEXCL_COUNT	= 4
-} vchange_t;
+} bhv_vchange_t;
 
+typedef enum { L_FALSE, L_TRUE } lastclose_t;
 
 typedef int	(*vop_open_t)(bhv_desc_t *, struct cred *);
+typedef int	(*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *);
 typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
@@ -181,27 +152,27 @@
 				struct cred *);
 typedef int	(*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *,
 				int, unsigned int, void __user *);
-typedef int	(*vop_getattr_t)(bhv_desc_t *, struct vattr *, int,
+typedef int	(*vop_getattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
 				struct cred *);
-typedef int	(*vop_setattr_t)(bhv_desc_t *, struct vattr *, int,
+typedef int	(*vop_setattr_t)(bhv_desc_t *, struct bhv_vattr *, int,
 				struct cred *);
 typedef int	(*vop_access_t)(bhv_desc_t *, int, struct cred *);
-typedef int	(*vop_lookup_t)(bhv_desc_t *, vname_t *, vnode_t **,
-				int, vnode_t *, struct cred *);
-typedef int	(*vop_create_t)(bhv_desc_t *, vname_t *, struct vattr *,
-				vnode_t **, struct cred *);
-typedef int	(*vop_remove_t)(bhv_desc_t *, vname_t *, struct cred *);
-typedef int	(*vop_link_t)(bhv_desc_t *, vnode_t *, vname_t *,
+typedef int	(*vop_lookup_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t **,
+				int, bhv_vnode_t *, struct cred *);
+typedef int	(*vop_create_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
+				bhv_vnode_t **, struct cred *);
+typedef int	(*vop_remove_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
+typedef int	(*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, bhv_vname_t *,
 				struct cred *);
-typedef int	(*vop_rename_t)(bhv_desc_t *, vname_t *, vnode_t *, vname_t *,
-				struct cred *);
-typedef int	(*vop_mkdir_t)(bhv_desc_t *, vname_t *, struct vattr *,
-				vnode_t **, struct cred *);
-typedef int	(*vop_rmdir_t)(bhv_desc_t *, vname_t *, struct cred *);
+typedef int	(*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
+				bhv_vname_t *, struct cred *);
+typedef int	(*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
+				bhv_vnode_t **, struct cred *);
+typedef int	(*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
 typedef int	(*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
 				int *);
-typedef int	(*vop_symlink_t)(bhv_desc_t *, vname_t *, struct vattr *,
-				char *, vnode_t **, struct cred *);
+typedef int	(*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
+				char *, bhv_vnode_t **, struct cred *);
 typedef int	(*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
 				struct cred *);
 typedef int	(*vop_fsync_t)(bhv_desc_t *, int, struct cred *,
@@ -209,8 +180,8 @@
 typedef int	(*vop_inactive_t)(bhv_desc_t *, struct cred *);
 typedef int	(*vop_fid2_t)(bhv_desc_t *, struct fid *);
 typedef int	(*vop_release_t)(bhv_desc_t *);
-typedef int	(*vop_rwlock_t)(bhv_desc_t *, vrwlock_t);
-typedef void	(*vop_rwunlock_t)(bhv_desc_t *, vrwlock_t);
+typedef int	(*vop_rwlock_t)(bhv_desc_t *, bhv_vrwlock_t);
+typedef void	(*vop_rwunlock_t)(bhv_desc_t *, bhv_vrwlock_t);
 typedef int	(*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int,
 				struct xfs_iomap *, int *);
 typedef int	(*vop_reclaim_t)(bhv_desc_t *);
@@ -222,8 +193,8 @@
 				int, struct cred *);
 typedef	int	(*vop_attr_list_t)(bhv_desc_t *, char *, int, int,
 				struct attrlist_cursor_kern *, struct cred *);
-typedef void	(*vop_link_removed_t)(bhv_desc_t *, vnode_t *, int);
-typedef void	(*vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t);
+typedef void	(*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int);
+typedef void	(*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t);
 typedef void	(*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 typedef void	(*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int);
 typedef int	(*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t,
@@ -231,9 +202,10 @@
 typedef int	(*vop_iflush_t)(bhv_desc_t *, int);
 
 
-typedef struct vnodeops {
+typedef struct bhv_vnodeops {
 	bhv_position_t  vn_position;    /* position within behavior chain */
 	vop_open_t		vop_open;
+	vop_close_t		vop_close;
 	vop_read_t		vop_read;
 	vop_write_t		vop_write;
 	vop_sendfile_t		vop_sendfile;
@@ -271,103 +243,80 @@
 	vop_pflushvp_t		vop_flush_pages;
 	vop_release_t		vop_release;
 	vop_iflush_t		vop_iflush;
-} vnodeops_t;
+} bhv_vnodeops_t;
 
 /*
- * VOP's.
+ * Virtual node operations, operating from head bhv.
  */
-#define _VOP_(op, vp)	(*((vnodeops_t *)(vp)->v_fops)->op)
-
-#define VOP_READ(vp,file,iov,segs,offset,ioflags,cr,rv)			\
-	rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
-#define VOP_WRITE(vp,file,iov,segs,offset,ioflags,cr,rv)		\
-	rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr)
-#define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv)		\
-	rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr)
-#define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv)			\
-	rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
-#define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv)			\
-	rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr)
-#define VOP_BMAP(vp,of,sz,rw,b,n,rv)					\
-	rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n)
-#define VOP_OPEN(vp, cr, rv)						\
-	rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr)
-#define VOP_GETATTR(vp, vap, f, cr, rv)					\
-	rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr)
-#define	VOP_SETATTR(vp, vap, f, cr, rv)					\
-	rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr)
-#define	VOP_ACCESS(vp, mode, cr, rv)					\
-	rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr)
-#define	VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv)				\
-	rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr)
-#define VOP_CREATE(dvp,d,vap,vpp,cr,rv)					\
-	rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr)
-#define VOP_REMOVE(dvp,d,cr,rv)						\
-	rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr)
-#define	VOP_LINK(tdvp,fvp,d,cr,rv)					\
-	rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr)
-#define	VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv)				\
-	rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr)
-#define	VOP_MKDIR(dp,d,vap,vpp,cr,rv)					\
-	rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr)
-#define	VOP_RMDIR(dp,d,cr,rv)	 					\
-	rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr)
-#define	VOP_READDIR(vp,uiop,cr,eofp,rv)					\
-	rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp)
-#define	VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv)				\
-	rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr)
-#define	VOP_READLINK(vp,uiop,fl,cr,rv)					\
-	rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,fl,cr)
-#define	VOP_FSYNC(vp,f,cr,b,e,rv)					\
-	rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e)
-#define VOP_INACTIVE(vp, cr, rv)					\
-	rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr)
-#define VOP_RELEASE(vp, rv)						\
-	rv = _VOP_(vop_release, vp)((vp)->v_fbhv)
-#define VOP_FID2(vp, fidp, rv)						\
-	rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp)
-#define VOP_RWLOCK(vp,i)						\
-	(void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
-#define VOP_RWLOCK_TRY(vp,i)						\
-	_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i)
-#define VOP_RWUNLOCK(vp,i)						\
-	(void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i)
-#define VOP_FRLOCK(vp,c,fl,flags,offset,fr,rv)				\
-	rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr)
-#define VOP_RECLAIM(vp, rv)						\
-	rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv)
-#define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv)		\
-	rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred)
-#define	VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv)		\
-	rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred)
-#define	VOP_ATTR_REMOVE(vp, name, flags, cred, rv)			\
-	rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred)
-#define	VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv)		\
-	rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred)
-#define VOP_LINK_REMOVED(vp, dvp, linkzero)				\
-	(void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero)
-#define VOP_VNODE_CHANGE(vp, cmd, val)					\
-	(void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val)
-/*
- * These are page cache functions that now go thru VOPs.
- * 'last' parameter is unused and left in for IRIX compatibility
- */
-#define VOP_TOSS_PAGES(vp, first, last, fiopt)				\
-	_VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt)
-/*
- * 'last' parameter is unused and left in for IRIX compatibility
- */
-#define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt)			\
-	_VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt)
-/*
- * 'last' parameter is unused and left in for IRIX compatibility
- */
-#define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv)		\
-	rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt)
-#define VOP_IOCTL(vp, inode, filp, fl, cmd, arg, rv)			\
-	rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg)
-#define VOP_IFLUSH(vp, flags, rv)					\
-	rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags)
+#define VNHEAD(vp)	((vp)->v_bh.bh_first)
+#define VOP(op, vp)	(*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op)
+#define bhv_vop_open(vp, cr)		VOP(vop_open, vp)(VNHEAD(vp),cr)
+#define bhv_vop_close(vp, f,last,cr)	VOP(vop_close, vp)(VNHEAD(vp),f,last,cr)
+#define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr)		\
+		VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
+#define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr)		\
+		VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr)
+#define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr)		\
+		VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr)
+#define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr)			\
+		VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
+#define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr)		\
+		VOP(vop_splice_write, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr)
+#define bhv_vop_bmap(vp,of,sz,rw,b,n)					\
+		VOP(vop_bmap, vp)(VNHEAD(vp),of,sz,rw,b,n)
+#define bhv_vop_getattr(vp, vap,f,cr)					\
+		VOP(vop_getattr, vp)(VNHEAD(vp), vap,f,cr)
+#define	bhv_vop_setattr(vp, vap,f,cr)					\
+		VOP(vop_setattr, vp)(VNHEAD(vp), vap,f,cr)
+#define	bhv_vop_access(vp, mode,cr)	VOP(vop_access, vp)(VNHEAD(vp), mode,cr)
+#define	bhv_vop_lookup(vp,d,vpp,f,rdir,cr)				\
+		VOP(vop_lookup, vp)(VNHEAD(vp),d,vpp,f,rdir,cr)
+#define bhv_vop_create(dvp,d,vap,vpp,cr)				\
+		VOP(vop_create, dvp)(VNHEAD(dvp),d,vap,vpp,cr)
+#define bhv_vop_remove(dvp,d,cr)	VOP(vop_remove, dvp)(VNHEAD(dvp),d,cr)
+#define	bhv_vop_link(dvp,fvp,d,cr)	VOP(vop_link, dvp)(VNHEAD(dvp),fvp,d,cr)
+#define	bhv_vop_rename(fvp,fnm,tdvp,tnm,cr)				\
+		VOP(vop_rename, fvp)(VNHEAD(fvp),fnm,tdvp,tnm,cr)
+#define	bhv_vop_mkdir(dp,d,vap,vpp,cr)					\
+		VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr)
+#define	bhv_vop_rmdir(dp,d,cr)	 	VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr)
+#define	bhv_vop_readdir(vp,uiop,cr,eofp)				\
+		VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp)
+#define	bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr)				\
+		VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
+#define	bhv_vop_readlink(vp,uiop,fl,cr)					\
+		VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr)
+#define	bhv_vop_fsync(vp,f,cr,b,e)	VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e)
+#define bhv_vop_inactive(vp,cr)		VOP(vop_inactive, vp)(VNHEAD(vp),cr)
+#define bhv_vop_release(vp)		VOP(vop_release, vp)(VNHEAD(vp))
+#define bhv_vop_fid2(vp,fidp)		VOP(vop_fid2, vp)(VNHEAD(vp),fidp)
+#define bhv_vop_rwlock(vp,i)		VOP(vop_rwlock, vp)(VNHEAD(vp),i)
+#define bhv_vop_rwlock_try(vp,i)	VOP(vop_rwlock, vp)(VNHEAD(vp),i)
+#define bhv_vop_rwunlock(vp,i)		VOP(vop_rwunlock, vp)(VNHEAD(vp),i)
+#define bhv_vop_frlock(vp,c,fl,flags,offset,fr)				\
+		VOP(vop_frlock, vp)(VNHEAD(vp),c,fl,flags,offset,fr)
+#define bhv_vop_reclaim(vp)		VOP(vop_reclaim, vp)(VNHEAD(vp))
+#define bhv_vop_attr_get(vp, name, val, vallenp, fl, cred)		\
+		VOP(vop_attr_get, vp)(VNHEAD(vp),name,val,vallenp,fl,cred)
+#define	bhv_vop_attr_set(vp, name, val, vallen, fl, cred)		\
+		VOP(vop_attr_set, vp)(VNHEAD(vp),name,val,vallen,fl,cred)
+#define	bhv_vop_attr_remove(vp, name, flags, cred)			\
+		VOP(vop_attr_remove, vp)(VNHEAD(vp),name,flags,cred)
+#define	bhv_vop_attr_list(vp, buf, buflen, fl, cursor, cred)		\
+		VOP(vop_attr_list, vp)(VNHEAD(vp),buf,buflen,fl,cursor,cred)
+#define bhv_vop_link_removed(vp, dvp, linkzero)				\
+		VOP(vop_link_removed, vp)(VNHEAD(vp), dvp, linkzero)
+#define bhv_vop_vnode_change(vp, cmd, val)				\
+		VOP(vop_vnode_change, vp)(VNHEAD(vp), cmd, val)
+#define bhv_vop_toss_pages(vp, first, last, fiopt)			\
+		VOP(vop_tosspages, vp)(VNHEAD(vp), first, last, fiopt)
+#define bhv_vop_flushinval_pages(vp, first, last, fiopt)		\
+		VOP(vop_flushinval_pages, vp)(VNHEAD(vp),first,last,fiopt)
+#define bhv_vop_flush_pages(vp, first, last, flags, fiopt)		\
+		VOP(vop_flush_pages, vp)(VNHEAD(vp),first,last,flags,fiopt)
+#define bhv_vop_ioctl(vp, inode, filp, fl, cmd, arg)			\
+		VOP(vop_ioctl, vp)(VNHEAD(vp),inode,filp,fl,cmd,arg)
+#define bhv_vop_iflush(vp, flags)	VOP(vop_iflush, vp)(VNHEAD(vp), flags)
 
 /*
  * Flags for read/write calls - same values as IRIX
@@ -377,7 +326,7 @@
 #define IO_INVIS	0x00020		/* don't update inode timestamps */
 
 /*
- * Flags for VOP_IFLUSH call
+ * Flags for vop_iflush call
  */
 #define FLUSH_SYNC		1	/* wait for flush to complete	*/
 #define FLUSH_INODE		2	/* flush the inode itself	*/
@@ -385,8 +334,7 @@
 					 * this inode out to disk	*/
 
 /*
- * Flush/Invalidate options for VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and
- *	VOP_FLUSH_PAGES.
+ * Flush/Invalidate options for vop_toss/flush/flushinval_pages.
  */
 #define FI_NONE			0	/* none */
 #define FI_REMAPF		1	/* Do a remapf prior to the operation */
@@ -398,7 +346,7 @@
  * Vnode attributes.  va_mask indicates those attributes the caller
  * wants to set or extract.
  */
-typedef struct vattr {
+typedef struct bhv_vattr {
 	int		va_mask;	/* bit-mask of attributes present */
 	mode_t		va_mode;	/* file access mode and type */
 	xfs_nlink_t	va_nlink;	/* number of references to file */
@@ -418,7 +366,7 @@
 	u_long		va_nextents;	/* number of extents in file */
 	u_long		va_anextents;	/* number of attr extents in file */
 	prid_t		va_projid;	/* project id */
-} vattr_t;
+} bhv_vattr_t;
 
 /*
  * setattr or getattr attributes
@@ -492,29 +440,17 @@
 	(VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID)
 
 extern void	vn_init(void);
-extern vnode_t	*vn_initialize(struct inode *);
+extern bhv_vnode_t	*vn_initialize(struct inode *);
+extern int	vn_revalidate(struct bhv_vnode *);
+extern int	__vn_revalidate(struct bhv_vnode *, bhv_vattr_t *);
+extern void	vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *);
 
-/*
- * vnode_map structures _must_ match vn_epoch and vnode structure sizes.
- */
-typedef struct vnode_map {
-	vfs_t		*v_vfsp;
-	vnumber_t	v_number;		/* in-core vnode number */
-	xfs_ino_t	v_ino;			/* inode #	*/
-} vmap_t;
+extern void	vn_iowait(struct bhv_vnode *vp);
+extern void	vn_iowake(struct bhv_vnode *vp);
 
-#define VMAP(vp, vmap)	{(vmap).v_vfsp	 = (vp)->v_vfsp,	\
-			 (vmap).v_number = (vp)->v_number,	\
-			 (vmap).v_ino	 = (vp)->v_inode.i_ino; }
+extern void	vn_ioerror(struct bhv_vnode *vp, int error, char *f, int l);
 
-extern int	vn_revalidate(struct vnode *);
-extern int	__vn_revalidate(struct vnode *, vattr_t *);
-extern void	vn_revalidate_core(struct vnode *, vattr_t *);
-
-extern void	vn_iowait(struct vnode *vp);
-extern void	vn_iowake(struct vnode *vp);
-
-static inline int vn_count(struct vnode *vp)
+static inline int vn_count(struct bhv_vnode *vp)
 {
 	return atomic_read(&vn_to_inode(vp)->i_count);
 }
@@ -522,7 +458,7 @@
 /*
  * Vnode reference counting functions (and macros for compatibility).
  */
-extern vnode_t	*vn_hold(struct vnode *);
+extern bhv_vnode_t	*vn_hold(struct bhv_vnode *);
 
 #if defined(XFS_VNODE_TRACE)
 #define VN_HOLD(vp)		\
@@ -536,7 +472,7 @@
 #define VN_RELE(vp)		(iput(vn_to_inode(vp)))
 #endif
 
-static inline struct vnode *vn_grab(struct vnode *vp)
+static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp)
 {
 	struct inode *inode = igrab(vn_to_inode(vp));
 	return inode ? vn_from_inode(inode) : NULL;
@@ -554,32 +490,39 @@
  */
 #define VN_LOCK(vp)		mutex_spinlock(&(vp)->v_lock)
 #define VN_UNLOCK(vp, s)	mutex_spinunlock(&(vp)->v_lock, s)
-#define VN_FLAGSET(vp,b)	vn_flagset(vp,b)
-#define VN_FLAGCLR(vp,b)	vn_flagclr(vp,b)
 
-static __inline__ void vn_flagset(struct vnode *vp, uint flag)
+static __inline__ void vn_flagset(struct bhv_vnode *vp, uint flag)
 {
 	spin_lock(&vp->v_lock);
 	vp->v_flag |= flag;
 	spin_unlock(&vp->v_lock);
 }
 
-static __inline__ void vn_flagclr(struct vnode *vp, uint flag)
+static __inline__ uint vn_flagclr(struct bhv_vnode *vp, uint flag)
 {
+	uint	cleared;
+
 	spin_lock(&vp->v_lock);
+	cleared = (vp->v_flag & flag);
 	vp->v_flag &= ~flag;
 	spin_unlock(&vp->v_lock);
+	return cleared;
 }
 
+#define VMODIFY(vp)	vn_flagset(vp, VMODIFIED)
+#define VUNMODIFY(vp)	vn_flagclr(vp, VMODIFIED)
+#define VTRUNCATE(vp)	vn_flagset(vp, VTRUNCATED)
+#define VUNTRUNCATE(vp)	vn_flagclr(vp, VTRUNCATED)
+
 /*
  * Dealing with bad inodes
  */
-static inline void vn_mark_bad(struct vnode *vp)
+static inline void vn_mark_bad(struct bhv_vnode *vp)
 {
 	make_bad_inode(vn_to_inode(vp));
 }
 
-static inline int VN_BAD(struct vnode *vp)
+static inline int VN_BAD(struct bhv_vnode *vp)
 {
 	return is_bad_inode(vn_to_inode(vp));
 }
@@ -587,18 +530,18 @@
 /*
  * Extracting atime values in various formats
  */
-static inline void vn_atime_to_bstime(struct vnode *vp, xfs_bstime_t *bs_atime)
+static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime)
 {
 	bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec;
 	bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec;
 }
 
-static inline void vn_atime_to_timespec(struct vnode *vp, struct timespec *ts)
+static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts)
 {
 	*ts = vp->v_inode.i_atime;
 }
 
-static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt)
+static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt)
 {
 	*tt = vp->v_inode.i_atime.tv_sec;
 }
@@ -610,11 +553,10 @@
 #define VN_CACHED(vp)	(vn_to_inode(vp)->i_mapping->nrpages)
 #define VN_DIRTY(vp)	mapping_tagged(vn_to_inode(vp)->i_mapping, \
 					PAGECACHE_TAG_DIRTY)
-#define VMODIFY(vp)	VN_FLAGSET(vp, VMODIFIED)
-#define VUNMODIFY(vp)	VN_FLAGCLR(vp, VMODIFIED)
+#define VN_TRUNC(vp)	((vp)->v_flag & VTRUNCATED)
 
 /*
- * Flags to VOP_SETATTR/VOP_GETATTR.
+ * Flags to vop_setattr/getattr.
  */
 #define	ATTR_UTIME	0x01	/* non-default utime(2) request */
 #define	ATTR_DMI	0x08	/* invocation from a DMI function */
@@ -624,7 +566,7 @@
 #define ATTR_NOSIZETOK	0x400	/* Don't get the SIZE token */
 
 /*
- * Flags to VOP_FSYNC and VOP_RECLAIM.
+ * Flags to vop_fsync/reclaim.
  */
 #define FSYNC_NOWAIT	0	/* asynchronous flush */
 #define FSYNC_WAIT	0x1	/* synchronous fsync or forced reclaim */
@@ -643,11 +585,11 @@
 #define	VNODE_KTRACE_REF	4
 #define	VNODE_KTRACE_RELE	5
 
-extern void vn_trace_entry(struct vnode *, const char *, inst_t *);
-extern void vn_trace_exit(struct vnode *, const char *, inst_t *);
-extern void vn_trace_hold(struct vnode *, char *, int, inst_t *);
-extern void vn_trace_ref(struct vnode *, char *, int, inst_t *);
-extern void vn_trace_rele(struct vnode *, char *, int, inst_t *);
+extern void vn_trace_entry(struct bhv_vnode *, const char *, inst_t *);
+extern void vn_trace_exit(struct bhv_vnode *, const char *, inst_t *);
+extern void vn_trace_hold(struct bhv_vnode *, char *, int, inst_t *);
+extern void vn_trace_ref(struct bhv_vnode *, char *, int, inst_t *);
+extern void vn_trace_rele(struct bhv_vnode *, char *, int, inst_t *);
 
 #define	VN_TRACE(vp)		\
 	vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address)
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 772ac48..3aa7715 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -444,7 +442,7 @@
 			      XFS_BMAPI_METADATA | XFS_BMAPI_WRITE,
 			      &firstblock,
 			      XFS_QM_DQALLOC_SPACE_RES(mp),
-			      &map, &nmaps, &flist))) {
+			      &map, &nmaps, &flist, NULL))) {
 		goto error0;
 	}
 	ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB);
@@ -559,7 +557,7 @@
 		error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset,
 				  XFS_DQUOT_CLUSTER_SIZE_FSB,
 				  XFS_BMAPI_METADATA,
-				  NULL, 0, &map, &nmaps, NULL);
+				  NULL, 0, &map, &nmaps, NULL, NULL);
 
 		xfs_iunlock(quotip, XFS_ILOCK_SHARED);
 		if (error)
@@ -1261,7 +1259,7 @@
 
 	if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id),
 			   0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
-		xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
+		xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE);
 		return XFS_ERROR(EIO);
 	}
 
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index c0c6296..78d3ab9 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -119,7 +119,7 @@
  */
 #define xfs_dqflock(dqp)	 { psema(&((dqp)->q_flock), PINOD | PRECALC);\
 				   (dqp)->dq_flags |= XFS_DQ_FLOCKED; }
-#define xfs_dqfunlock(dqp)	 { ASSERT(valusema(&((dqp)->q_flock)) <= 0); \
+#define xfs_dqfunlock(dqp)	 { ASSERT(issemalocked(&((dqp)->q_flock))); \
 				   vsema(&((dqp)->q_flock)); \
 				   (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); }
 
@@ -128,7 +128,7 @@
 #define XFS_DQ_PINUNLOCK(dqp, s)   mutex_spinunlock( \
 				     &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s)
 
-#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (valusema(&((dqp)->q_flock)) <= 0)
+#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock)))
 #define XFS_DQ_IS_ON_FREELIST(dqp)  ((dqp)->dq_flnext != (dqp))
 #define XFS_DQ_IS_DIRTY(dqp)	((dqp)->dq_flags & XFS_DQ_DIRTY)
 #define XFS_QM_ISUDQ(dqp)	((dqp)->dq_flags & XFS_DQ_USER)
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index 546f48a..5b2dcc5 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -248,7 +246,7 @@
 	 * inode flush completed and the inode was taken off the AIL.
 	 * So, just get out.
 	 */
-	if ((valusema(&(dqp->q_flock)) > 0)  ||
+	if (!issemalocked(&(dqp->q_flock))  ||
 	    ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) {
 		qip->qli_pushbuf_flag = 0;
 		xfs_dqunlock(dqp);
@@ -261,7 +259,7 @@
 	if (bp != NULL) {
 		if (XFS_BUF_ISDELAYWRITE(bp)) {
 			dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) &&
-				  (valusema(&(dqp->q_flock)) <= 0));
+				  issemalocked(&(dqp->q_flock)));
 			qip->qli_pushbuf_flag = 0;
 			xfs_dqunlock(dqp);
 
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 7fb5eca..e23e455 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -1603,7 +1601,7 @@
 				  maxlblkcnt - lblkno,
 				  XFS_BMAPI_METADATA,
 				  NULL,
-				  0, map, &nmaps, NULL);
+				  0, map, &nmaps, NULL, NULL);
 		xfs_iunlock(qip, XFS_ILOCK_SHARED);
 		if (error)
 			break;
@@ -1905,9 +1903,7 @@
 		 */
 		if ((error = xfs_bulkstat(mp, &lastino, &count,
 				     xfs_qm_dqusage_adjust, NULL,
-				     structsz, NULL,
-				     BULKSTAT_FG_IGET|BULKSTAT_FG_VFSLOCKED,
-				     &done)))
+				     structsz, NULL, BULKSTAT_FG_IGET, &done)))
 			break;
 
 	} while (! done);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index 6838b36..e95e99f 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -129,7 +127,7 @@
 		return XFS_ERROR(EINVAL);
 	}
 
-	PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
+	error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update);
 	if (!error && !referenced)
 		bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
 	return error;
@@ -140,9 +138,8 @@
 	struct bhv_desc		*bhv,
 	struct seq_file		*m)
 {
-	struct vfs		*vfsp = bhvtovfs(bhv);
+	struct bhv_vfs		*vfsp = bhvtovfs(bhv);
 	struct xfs_mount	*mp = XFS_VFSTOM(vfsp);
-	int			error;
 
 	if (mp->m_qflags & XFS_UQUOTA_ACCT) {
 		(mp->m_qflags & XFS_UQUOTA_ENFD) ?
@@ -165,8 +162,7 @@
 	if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
 		seq_puts(m, "," MNTOPT_NOQUOTA);
 
-	PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
-	return error;
+	return bhv_next_vfs_showargs(BHV_NEXT(bhv), m);
 }
 
 STATIC int
@@ -175,14 +171,67 @@
 	struct xfs_mount_args	*args,
 	struct cred		*cr)
 {
-	struct vfs		*vfsp = bhvtovfs(bhv);
+	struct bhv_vfs		*vfsp = bhvtovfs(bhv);
 	struct xfs_mount	*mp = XFS_VFSTOM(vfsp);
-	int			error;
 
 	if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
 		xfs_qm_mount_quotainit(mp, args->flags);
-	PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
-	return error;
+	return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr);
+}
+
+/*
+ * Directory tree accounting is implemented using project quotas, where
+ * the project identifier is inherited from parent directories.
+ * A statvfs (df, etc.) of a directory that is using project quota should
+ * return a statvfs of the project, not the entire filesystem.
+ * This makes such trees appear as if they are filesystems in themselves.
+ */
+STATIC int
+xfs_qm_statvfs(
+	struct bhv_desc		*bhv,
+	bhv_statvfs_t		*statp,
+	struct bhv_vnode	*vnode)
+{
+	xfs_mount_t		*mp;
+	xfs_inode_t		*ip;
+	xfs_dquot_t		*dqp;
+	xfs_disk_dquot_t	*dp;
+	__uint64_t		limit;
+	int			error;
+
+	error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode);
+	if (error || !vnode)
+		return error;
+
+	mp = XFS_BHVTOM(bhv);
+	ip = xfs_vtoi(vnode);
+
+	if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT))
+		return 0;
+	if (!(mp->m_qflags & XFS_PQUOTA_ACCT))
+		return 0;
+	if (!(mp->m_qflags & XFS_OQUOTA_ENFD))
+		return 0;
+
+	if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp))
+		return 0;
+	dp = &dqp->q_core;
+
+	limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit;
+	if (limit && statp->f_blocks > limit) {
+		statp->f_blocks = limit;
+		statp->f_bfree = (statp->f_blocks > dp->d_bcount) ?
+					(statp->f_blocks - dp->d_bcount) : 0;
+	}
+	limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit;
+	if (limit && statp->f_files > limit) {
+		statp->f_files = limit;
+		statp->f_ffree = (statp->f_files > dp->d_icount) ?
+					(statp->f_ffree - dp->d_icount) : 0;
+	}
+
+	xfs_qm_dqput(dqp);
+	return 0;
 }
 
 STATIC int
@@ -191,7 +240,7 @@
 	int			flags,
 	cred_t			*credp)
 {
-	struct vfs		*vfsp = bhvtovfs(bhv);
+	struct bhv_vfs		*vfsp = bhvtovfs(bhv);
 	struct xfs_mount	*mp = XFS_VFSTOM(vfsp);
 	int			error;
 
@@ -210,8 +259,7 @@
 			}
 		}
 	}
-	PVFS_SYNC(BHV_NEXT(bhv), flags, credp, error);
-	return error;
+	return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp);
 }
 
 STATIC int
@@ -346,11 +394,12 @@
 	.xfs_dqtrxops		= &xfs_trans_dquot_ops,
 };
 
-struct bhv_vfsops xfs_qmops = { {
+struct bhv_module_vfsops xfs_qmops = { {
 	BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM),
 	.vfs_parseargs		= xfs_qm_parseargs,
 	.vfs_showargs		= xfs_qm_showargs,
 	.vfs_mount		= xfs_qm_mount,
+	.vfs_statvfs		= xfs_qm_statvfs,
 	.vfs_sync		= xfs_qm_syncall,
 	.vfs_quotactl		= xfs_qm_quotactl, },
 };
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c
index 0570f77..6f858fb 100644
--- a/fs/xfs/quota/xfs_qm_stats.c
+++ b/fs/xfs/quota/xfs_qm_stats.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index c55db46..ed620c4 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -26,7 +26,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -35,7 +34,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -91,8 +89,8 @@
 	xfs_caddr_t	addr)
 {
 	xfs_mount_t	*mp;
+	bhv_vfs_t	*vfsp;
 	int		error;
-	struct vfs	*vfsp;
 
 	vfsp = bhvtovfs(bdp);
 	mp = XFS_VFSTOM(vfsp);
@@ -1035,7 +1033,7 @@
 {
 	xfs_inode_t	*ip, *topino;
 	uint		ireclaims;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 	boolean_t	vnode_refd;
 
 	ASSERT(mp->m_quotainfo);
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 9168918..0242e96 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -33,7 +32,6 @@
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
 #include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index b08b3d9..36fbecc 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -47,7 +47,7 @@
 	va_start(ap, fmt);
 	if (*fmt == '!') fp++;
 	len = vsprintf(message, fp, ap);
-	if (message[len-1] != '\n')
+	if (level != CE_DEBUG && message[len-1] != '\n')
 		strcat(message, "\n");
 	printk("%s%s", err_level[level], message);
 	va_end(ap);
@@ -68,7 +68,7 @@
 		level = XFS_MAX_ERR_LEVEL;
 	spin_lock_irqsave(&xfs_err_lock,flags);
 	len = vsprintf(message, fmt, ap);
-	if (message[len-1] != '\n')
+	if (level != CE_DEBUG && message[len-1] != '\n')
 		strcat(message, "\n");
 	spin_unlock_irqrestore(&xfs_err_lock,flags);
 	printk("%s%s", err_level[level], message);
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index e3bf581..4f54dca 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -33,9 +33,6 @@
 	__attribute__ ((format (printf, 2, 3)));
 extern void assfail(char *expr, char *f, int l);
 
-#define prdev(fmt,targ,args...) \
-	printk("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args)
-
 #define ASSERT_ALWAYS(expr)	\
 	(unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
 
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 2539af3..4b0cb47 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -21,12 +21,10 @@
 #include "xfs_bit.h"
 #include "xfs_inum.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -39,15 +37,15 @@
 #include <linux/capability.h>
 #include <linux/posix_acl_xattr.h>
 
-STATIC int	xfs_acl_setmode(vnode_t *, xfs_acl_t *, int *);
+STATIC int	xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *);
 STATIC void     xfs_acl_filter_mode(mode_t, xfs_acl_t *);
 STATIC void	xfs_acl_get_endian(xfs_acl_t *);
 STATIC int	xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *);
 STATIC int	xfs_acl_invalid(xfs_acl_t *);
 STATIC void	xfs_acl_sync_mode(mode_t, xfs_acl_t *);
-STATIC void	xfs_acl_get_attr(vnode_t *, xfs_acl_t *, int, int, int *);
-STATIC void	xfs_acl_set_attr(vnode_t *, xfs_acl_t *, int, int *);
-STATIC int	xfs_acl_allow_set(vnode_t *, int);
+STATIC void	xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *);
+STATIC void	xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *);
+STATIC int	xfs_acl_allow_set(bhv_vnode_t *, int);
 
 kmem_zone_t *xfs_acl_zone;
 
@@ -57,7 +55,7 @@
  */
 int
 xfs_acl_vhasacl_access(
-	vnode_t		*vp)
+	bhv_vnode_t	*vp)
 {
 	int		error;
 
@@ -70,7 +68,7 @@
  */
 int
 xfs_acl_vhasacl_default(
-	vnode_t		*vp)
+	bhv_vnode_t	*vp)
 {
 	int		error;
 
@@ -209,7 +207,7 @@
 
 int
 xfs_acl_vget(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	void		*acl,
 	size_t		size,
 	int		kind)
@@ -241,10 +239,10 @@
 			goto out;
 		}
 		if (kind == _ACL_TYPE_ACCESS) {
-			vattr_t	va;
+			bhv_vattr_t	va;
 
 			va.va_mask = XFS_AT_MODE;
-			VOP_GETATTR(vp, &va, 0, sys_cred, error);
+			error = bhv_vop_getattr(vp, &va, 0, sys_cred);
 			if (error)
 				goto out;
 			xfs_acl_sync_mode(va.va_mode, xfs_acl);
@@ -260,7 +258,7 @@
 
 int
 xfs_acl_vremove(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	int		kind)
 {
 	int		error;
@@ -268,9 +266,9 @@
 	VN_HOLD(vp);
 	error = xfs_acl_allow_set(vp, kind);
 	if (!error) {
-		VOP_ATTR_REMOVE(vp, kind == _ACL_TYPE_DEFAULT?
-				SGI_ACL_DEFAULT: SGI_ACL_FILE,
-				ATTR_ROOT, sys_cred, error);
+		error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT?
+						SGI_ACL_DEFAULT: SGI_ACL_FILE,
+						ATTR_ROOT, sys_cred);
 		if (error == ENOATTR)
 			error = 0;	/* 'scool */
 	}
@@ -280,7 +278,7 @@
 
 int
 xfs_acl_vset(
-	vnode_t			*vp,
+	bhv_vnode_t		*vp,
 	void			*acl,
 	size_t			size,
 	int			kind)
@@ -370,10 +368,10 @@
 
 STATIC int
 xfs_acl_allow_set(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	int		kind)
 {
-	vattr_t		va;
+	bhv_vattr_t	va;
 	int		error;
 
 	if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND))
@@ -383,7 +381,7 @@
 	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
 		return EROFS;
 	va.va_mask = XFS_AT_UID;
-	VOP_GETATTR(vp, &va, 0, NULL, error);
+	error = bhv_vop_getattr(vp, &va, 0, NULL);
 	if (error)
 		return error;
 	if (va.va_uid != current->fsuid && !capable(CAP_FOWNER))
@@ -606,7 +604,7 @@
  */
 STATIC void
 xfs_acl_get_attr(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	xfs_acl_t	*aclp,
 	int		kind,
 	int		flags,
@@ -616,9 +614,9 @@
 
 	ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1);
 	flags |= ATTR_ROOT;
-	VOP_ATTR_GET(vp,
-		kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT,
-		(char *)aclp, &len, flags, sys_cred, *error);
+	*error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ?
+					SGI_ACL_FILE : SGI_ACL_DEFAULT,
+					(char *)aclp, &len, flags, sys_cred);
 	if (*error || (flags & ATTR_KERNOVAL))
 		return;
 	xfs_acl_get_endian(aclp);
@@ -629,7 +627,7 @@
  */
 STATIC void
 xfs_acl_set_attr(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	xfs_acl_t	*aclp,
 	int		kind,
 	int		*error)
@@ -654,19 +652,19 @@
 		INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm);
 	}
 	INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt);
-	VOP_ATTR_SET(vp,
-		kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT,
-		(char *)newacl, len, ATTR_ROOT, sys_cred, *error);
+	*error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ?
+				SGI_ACL_FILE: SGI_ACL_DEFAULT,
+				(char *)newacl, len, ATTR_ROOT, sys_cred);
 	_ACL_FREE(newacl);
 }
 
 int
 xfs_acl_vtoacl(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	xfs_acl_t	*access_acl,
 	xfs_acl_t	*default_acl)
 {
-	vattr_t		va;
+	bhv_vattr_t	va;
 	int		error = 0;
 
 	if (access_acl) {
@@ -678,7 +676,7 @@
 		if (!error) {
 			/* Got the ACL, need the mode... */
 			va.va_mask = XFS_AT_MODE;
-			VOP_GETATTR(vp, &va, 0, sys_cred, error);
+			error = bhv_vop_getattr(vp, &va, 0, sys_cred);
 		}
 
 		if (error)
@@ -701,8 +699,8 @@
  */
 int
 xfs_acl_inherit(
-	vnode_t		*vp,
-	vattr_t		*vap,
+	bhv_vnode_t	*vp,
+	bhv_vattr_t	*vap,
 	xfs_acl_t	*pdaclp)
 {
 	xfs_acl_t	*cacl;
@@ -757,11 +755,11 @@
  */
 STATIC int
 xfs_acl_setmode(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	xfs_acl_t	*acl,
 	int		*basicperms)
 {
-	vattr_t		va;
+	bhv_vattr_t	va;
 	xfs_acl_entry_t	*ap;
 	xfs_acl_entry_t	*gap = NULL;
 	int		i, error, nomask = 1;
@@ -776,7 +774,7 @@
 	 * mode.  The m:: bits take precedence over the g:: bits.
 	 */
 	va.va_mask = XFS_AT_MODE;
-	VOP_GETATTR(vp, &va, 0, sys_cred, error);
+	error = bhv_vop_getattr(vp, &va, 0, sys_cred);
 	if (error)
 		return error;
 
@@ -810,8 +808,7 @@
 	if (gap && nomask)
 		va.va_mode |= gap->ae_perm << 3;
 
-	VOP_SETATTR(vp, &va, 0, sys_cred, error);
-	return error;
+	return bhv_vop_setattr(vp, &va, 0, sys_cred);
 }
 
 /*
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 538d0d6..f853cf1 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -50,7 +50,7 @@
 #ifdef CONFIG_XFS_POSIX_ACL
 
 struct vattr;
-struct vnode;
+struct bhv_vnode;
 struct xfs_inode;
 
 extern struct kmem_zone *xfs_acl_zone;
@@ -58,14 +58,14 @@
 		(zone) = kmem_zone_init(sizeof(xfs_acl_t), (name))
 #define xfs_acl_zone_destroy(zone)	kmem_zone_destroy(zone)
 
-extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *);
+extern int xfs_acl_inherit(struct bhv_vnode *, struct bhv_vattr *, xfs_acl_t *);
 extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *);
-extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *);
-extern int xfs_acl_vhasacl_access(struct vnode *);
-extern int xfs_acl_vhasacl_default(struct vnode *);
-extern int xfs_acl_vset(struct vnode *, void *, size_t, int);
-extern int xfs_acl_vget(struct vnode *, void *, size_t, int);
-extern int xfs_acl_vremove(struct vnode *vp, int);
+extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *);
+extern int xfs_acl_vhasacl_access(struct bhv_vnode *);
+extern int xfs_acl_vhasacl_default(struct bhv_vnode *);
+extern int xfs_acl_vset(struct bhv_vnode *, void *, size_t, int);
+extern int xfs_acl_vget(struct bhv_vnode *, void *, size_t, int);
+extern int xfs_acl_vremove(struct bhv_vnode *, int);
 
 #define _ACL_TYPE_ACCESS	1
 #define _ACL_TYPE_DEFAULT	2
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 8558226..eef6763 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -1862,7 +1860,7 @@
 		(pag->pagf_longest - delta) :
 		(pag->pagf_flcount > 0 || pag->pagf_longest > 0);
 	if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-	    (args->minleft &&
+	    (!(flags & XFS_ALLOC_FLAG_FREEING) &&
 	     (int)(pag->pagf_freeblks + pag->pagf_flcount -
 		   need - args->total) <
 	     (int)args->minleft)) {
@@ -1898,7 +1896,7 @@
 	longest = (longest > delta) ? (longest - delta) :
 		(be32_to_cpu(agf->agf_flcount) > 0 || longest > 0);
 	if (args->minlen + args->alignment + args->minalignslop - 1 > longest ||
-	     (args->minleft &&
+	     (!(flags & XFS_ALLOC_FLAG_FREEING) &&
 		(int)(be32_to_cpu(agf->agf_freeblks) +
 		   be32_to_cpu(agf->agf_flcount) - need - args->total) <
 	     (int)args->minleft)) {
@@ -1951,8 +1949,14 @@
 		 * the restrictions correctly.  Can happen for free calls
 		 * on a completely full ag.
 		 */
-		if (targs.agbno == NULLAGBLOCK)
+		if (targs.agbno == NULLAGBLOCK) {
+			if (!(flags & XFS_ALLOC_FLAG_FREEING)) {
+				xfs_trans_brelse(tp, agflbp);
+				args->agbp = NULL;
+				return 0;
+			}
 			break;
+		}
 		/*
 		 * Put each allocated block on the list.
 		 */
@@ -2360,8 +2364,19 @@
 			if (args->agno == sagno &&
 			    type == XFS_ALLOCTYPE_START_BNO)
 				args->type = XFS_ALLOCTYPE_THIS_AG;
-			if (++(args->agno) == mp->m_sb.sb_agcount)
-				args->agno = 0;
+			/*
+			* For the first allocation, we can try any AG to get
+			* space.  However, if we already have allocated a
+			* block, we don't want to try AGs whose number is below
+			* sagno. Otherwise, we may end up with out-of-order
+			* locking of AGF, which might cause deadlock.
+			*/
+			if (++(args->agno) == mp->m_sb.sb_agcount) {
+				if (args->firstblock != NULLFSBLOCK)
+					args->agno = sagno;
+				else
+					args->agno = 0;
+			}
 			/*
 			 * Reached the starting a.g., must either be done
 			 * or switch to non-trylock mode.
@@ -2443,7 +2458,7 @@
 	args.minlen = args.minleft = args.minalignslop = 0;
 	down_read(&args.mp->m_peraglock);
 	args.pag = &args.mp->m_perag[args.agno];
-	if ((error = xfs_alloc_fix_freelist(&args, 0)))
+	if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
 		goto error0;
 #ifdef DEBUG
 	ASSERT(args.agbp != NULL);
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h
index 2d1f892..650591f 100644
--- a/fs/xfs/xfs_alloc.h
+++ b/fs/xfs/xfs_alloc.h
@@ -41,6 +41,7 @@
  * Flags for xfs_alloc_fix_freelist.
  */
 #define	XFS_ALLOC_FLAG_TRYLOCK	0x00000001  /* use trylock for buffer locking */
+#define	XFS_ALLOC_FLAG_FREEING	0x00000002  /* indicate caller is freeing extents*/
 
 /*
  * Argument structure for xfs_alloc routines.
@@ -70,6 +71,7 @@
 	char		wasfromfl;	/* set if allocation is from freelist */
 	char		isfl;		/* set if is freelist blocks - !acctg */
 	char		userdata;	/* set if this is user data */
+	xfs_fsblock_t	firstblock;	/* io first block allocated */
 } xfs_alloc_arg_t;
 
 /*
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index a1d92da..7446556 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index b6e1e02..1a210104 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -27,7 +27,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -35,7 +34,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -1910,7 +1908,7 @@
 		error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno,
 				  args->rmtblkcnt,
 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-				  NULL, 0, map, &nmap, NULL);
+				  NULL, 0, map, &nmap, NULL, NULL);
 		if (error)
 			return(error);
 		ASSERT(nmap >= 1);
@@ -1988,7 +1986,7 @@
 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA |
 							XFS_BMAPI_WRITE,
 				  args->firstblock, args->total, &map, &nmap,
-				  args->flist);
+				  args->flist, NULL);
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
 						*args->firstblock, &committed);
@@ -2039,7 +2037,8 @@
 		error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno,
 				  args->rmtblkcnt,
 				  XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-				  args->firstblock, 0, &map, &nmap, NULL);
+				  args->firstblock, 0, &map, &nmap,
+				  NULL, NULL);
 		if (error) {
 			return(error);
 		}
@@ -2104,7 +2103,7 @@
 					args->rmtblkcnt,
 					XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
 					args->firstblock, 0, &map, &nmap,
-					args->flist);
+					args->flist, NULL);
 		if (error) {
 			return(error);
 		}
@@ -2142,7 +2141,8 @@
 		XFS_BMAP_INIT(args->flist, args->firstblock);
 		error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt,
 				    XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-				    1, args->firstblock, args->flist, &done);
+				    1, args->firstblock, args->flist,
+				    NULL, &done);
 		if (!error) {
 			error = xfs_bmap_finish(&args->trans, args->flist,
 						*args->firstblock, &committed);
@@ -2322,56 +2322,56 @@
 
 STATIC int
 posix_acl_access_set(
-	vnode_t	*vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
 	return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS);
 }
 
 STATIC int
 posix_acl_access_remove(
-	struct vnode *vp, char *name, int xflags)
+	bhv_vnode_t *vp, char *name, int xflags)
 {
 	return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS);
 }
 
 STATIC int
 posix_acl_access_get(
-	vnode_t *vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
 	return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS);
 }
 
 STATIC int
 posix_acl_access_exists(
-	vnode_t *vp)
+	bhv_vnode_t *vp)
 {
 	return xfs_acl_vhasacl_access(vp);
 }
 
 STATIC int
 posix_acl_default_set(
-	vnode_t	*vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
 	return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT);
 }
 
 STATIC int
 posix_acl_default_get(
-	vnode_t *vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
 	return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT);
 }
 
 STATIC int
 posix_acl_default_remove(
-	struct vnode *vp, char *name, int xflags)
+	bhv_vnode_t *vp, char *name, int xflags)
 {
 	return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT);
 }
 
 STATIC int
 posix_acl_default_exists(
-	vnode_t *vp)
+	bhv_vnode_t *vp)
 {
 	return xfs_acl_vhasacl_default(vp);
 }
@@ -2404,21 +2404,18 @@
 
 STATIC int
 attr_generic_set(
-	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
-	int 	error;
-
-	VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error);
-	return -error;
+	return -bhv_vop_attr_set(vp, name, data, size, xflags, NULL);
 }
 
 STATIC int
 attr_generic_get(
-	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
 	int	error, asize = size;
 
-	VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error);
+	error = bhv_vop_attr_get(vp, name, data, &asize, xflags, NULL);
 	if (!error)
 		return asize;
 	return -error;
@@ -2426,12 +2423,9 @@
 
 STATIC int
 attr_generic_remove(
-	struct vnode *vp, char *name, int xflags)
+	bhv_vnode_t *vp, char *name, int xflags)
 {
-	int	error;
-
-	VOP_ATTR_REMOVE(vp, name, xflags, NULL, error);
-	return -error;
+	return -bhv_vop_attr_remove(vp, name, xflags, NULL);
 }
 
 STATIC int
@@ -2459,7 +2453,7 @@
 
 STATIC int
 attr_system_list(
-	struct vnode		*vp,
+	bhv_vnode_t		*vp,
 	void			*data,
 	size_t			size,
 	ssize_t			*result)
@@ -2481,12 +2475,12 @@
 
 int
 attr_generic_list(
-	struct vnode *vp, void *data, size_t size, int xflags, ssize_t *result)
+	bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result)
 {
 	attrlist_cursor_kern_t	cursor = { 0 };
 	int			error;
 
-	VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error);
+	error = bhv_vop_attr_list(vp, data, size, xflags, &cursor, NULL);
 	if (error > 0)
 		return -error;
 	*result = -error;
@@ -2514,7 +2508,7 @@
  */
 STATIC int
 attr_user_capable(
-	struct vnode	*vp,
+	bhv_vnode_t	*vp,
 	cred_t		*cred)
 {
 	struct inode	*inode = vn_to_inode(vp);
@@ -2532,7 +2526,7 @@
 
 STATIC int
 attr_trusted_capable(
-	struct vnode	*vp,
+	bhv_vnode_t	*vp,
 	cred_t		*cred)
 {
 	struct inode	*inode = vn_to_inode(vp);
@@ -2546,7 +2540,7 @@
 
 STATIC int
 attr_secure_capable(
-	struct vnode	*vp,
+	bhv_vnode_t	*vp,
 	cred_t		*cred)
 {
 	return -ENOSECURITY;
@@ -2554,7 +2548,7 @@
 
 STATIC int
 attr_system_set(
-	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
 	attrnames_t	*namesp;
 	int		error;
@@ -2573,7 +2567,7 @@
 
 STATIC int
 attr_system_get(
-	struct vnode *vp, char *name, void *data, size_t size, int xflags)
+	bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags)
 {
 	attrnames_t	*namesp;
 
@@ -2585,7 +2579,7 @@
 
 STATIC int
 attr_system_remove(
-	struct vnode *vp, char *name, int xflags)
+	bhv_vnode_t *vp, char *name, int xflags)
 {
 	attrnames_t	*namesp;
 
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index b2c7b9f..981633f 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -36,13 +36,13 @@
  *========================================================================*/
 
 struct cred;
-struct vnode;
+struct bhv_vnode;
 
-typedef int (*attrset_t)(struct vnode *, char *, void *, size_t, int);
-typedef int (*attrget_t)(struct vnode *, char *, void *, size_t, int);
-typedef int (*attrremove_t)(struct vnode *, char *, int);
-typedef int (*attrexists_t)(struct vnode *);
-typedef int (*attrcapable_t)(struct vnode *, struct cred *);
+typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int);
+typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int);
+typedef int (*attrremove_t)(struct bhv_vnode *, char *, int);
+typedef int (*attrexists_t)(struct bhv_vnode *);
+typedef int (*attrcapable_t)(struct bhv_vnode *, struct cred *);
 
 typedef struct attrnames {
 	char *		attr_name;
@@ -63,7 +63,7 @@
 extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
 
 extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
-extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
+extern int attr_generic_list(struct bhv_vnode *, void *, size_t, int, ssize_t *);
 
 #define ATTR_DONTFOLLOW	0x0001	/* -- unused, from IRIX -- */
 #define ATTR_ROOT	0x0002	/* use attrs in root (trusted) namespace */
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index 9462be8..9455051 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -34,7 +33,6 @@
 #include "xfs_ialloc_btree.h"
 #include "xfs_alloc.h"
 #include "xfs_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -2990,7 +2988,7 @@
 		nmap = 1;
 		error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt,
 					XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
-					NULL, 0, &map, &nmap, NULL);
+					NULL, 0, &map, &nmap, NULL, NULL);
 		if (error) {
 			return(error);
 		}
diff --git a/fs/xfs/xfs_behavior.h b/fs/xfs/xfs_behavior.h
index 1d8ff10..6e6e56f 100644
--- a/fs/xfs/xfs_behavior.h
+++ b/fs/xfs/xfs_behavior.h
@@ -78,15 +78,12 @@
  *
  */
 
-struct bhv_head_lock;
-
 /*
  * Behavior head.  Head of the chain of behaviors.
  * Contained within each virtualized object data structure.
  */
 typedef struct bhv_head {
 	struct bhv_desc *bh_first;	/* first behavior in chain */
-	struct bhv_head_lock *bh_lockp;	/* pointer to lock info struct */
 } bhv_head_t;
 
 /*
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 26939d3..3a61375 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -24,13 +24,11 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -40,13 +38,15 @@
 #include "xfs_mount.h"
 #include "xfs_ialloc.h"
 #include "xfs_itable.h"
+#include "xfs_dir2_data.h"
+#include "xfs_dir2_leaf.h"
+#include "xfs_dir2_block.h"
 #include "xfs_inode_item.h"
 #include "xfs_extfree_item.h"
 #include "xfs_alloc.h"
 #include "xfs_bmap.h"
 #include "xfs_rtalloc.h"
 #include "xfs_error.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_attr_leaf.h"
 #include "xfs_rw.h"
 #include "xfs_quota.h"
@@ -101,6 +101,7 @@
 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			whichfork, /* data or attr fork */
 	int			rsvd);	/* OK to allocate reserved blocks */
 
@@ -118,6 +119,7 @@
 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			rsvd);	/* OK to allocate reserved blocks */
 
 /*
@@ -131,6 +133,7 @@
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
 	int			*logflagsp,/* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			rsvd);	/* OK to allocate reserved blocks */
 
 /*
@@ -144,6 +147,7 @@
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			whichfork); /* data or attr fork */
 
 /*
@@ -156,7 +160,8 @@
 	xfs_extnum_t		idx,	/* extent number to update/insert */
 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
-	int			*logflagsp); /* inode logging flags */
+	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta); /* Change made to incore extents */
 
 /*
  * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
@@ -203,6 +208,7 @@
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
 	int			*logflagsp,/* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			whichfork, /* data or attr fork */
 	int			rsvd);	 /* OK to allocate reserved blocks */
 
@@ -510,7 +516,7 @@
 		dargs.total = mp->m_dirblkfsbs;
 		dargs.whichfork = XFS_DATA_FORK;
 		dargs.trans = tp;
-		error = XFS_DIR_SHORTFORM_TO_SINGLE(mp, &dargs);
+		error = xfs_dir2_sf_to_block(&dargs);
 	} else
 		error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags,
 			XFS_DATA_FORK);
@@ -530,6 +536,7 @@
 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			whichfork, /* data or attr fork */
 	int			rsvd)	/* OK to use reserved data blocks */
 {
@@ -567,6 +574,15 @@
 			logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
 		} else
 			logflags = 0;
+		/* DELTA: single new extent */
+		if (delta) {
+			if (delta->xed_startoff > new->br_startoff)
+				delta->xed_startoff = new->br_startoff;
+			if (delta->xed_blockcount <
+					new->br_startoff + new->br_blockcount)
+				delta->xed_blockcount = new->br_startoff +
+						new->br_blockcount;
+		}
 	}
 	/*
 	 * Any kind of new delayed allocation goes here.
@@ -576,7 +592,7 @@
 			ASSERT((cur->bc_private.b.flags &
 				XFS_BTCUR_BPRV_WASDEL) == 0);
 		if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new,
-				&logflags, rsvd)))
+				&logflags, delta, rsvd)))
 			goto done;
 	}
 	/*
@@ -587,7 +603,7 @@
 			ASSERT((cur->bc_private.b.flags &
 				XFS_BTCUR_BPRV_WASDEL) == 0);
 		if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
-				&logflags, whichfork)))
+				&logflags, delta, whichfork)))
 			goto done;
 	} else {
 		xfs_bmbt_irec_t	prev;	/* old extent at offset idx */
@@ -612,17 +628,17 @@
 						XFS_BTCUR_BPRV_WASDEL);
 				if ((error = xfs_bmap_add_extent_delay_real(ip,
 					idx, &cur, new, &da_new, first, flist,
-					&logflags, rsvd)))
+					&logflags, delta, rsvd)))
 					goto done;
 			} else if (new->br_state == XFS_EXT_NORM) {
 				ASSERT(new->br_state == XFS_EXT_NORM);
 				if ((error = xfs_bmap_add_extent_unwritten_real(
-					ip, idx, &cur, new, &logflags)))
+					ip, idx, &cur, new, &logflags, delta)))
 					goto done;
 			} else {
 				ASSERT(new->br_state == XFS_EXT_UNWRITTEN);
 				if ((error = xfs_bmap_add_extent_unwritten_real(
-					ip, idx, &cur, new, &logflags)))
+					ip, idx, &cur, new, &logflags, delta)))
 					goto done;
 			}
 			ASSERT(*curp == cur || *curp == NULL);
@@ -635,7 +651,7 @@
 				ASSERT((cur->bc_private.b.flags &
 					XFS_BTCUR_BPRV_WASDEL) == 0);
 			if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
-					new, &logflags, whichfork)))
+					new, &logflags, delta, whichfork)))
 				goto done;
 		}
 	}
@@ -700,6 +716,7 @@
 	xfs_fsblock_t		*first,	/* pointer to firstblock variable */
 	xfs_bmap_free_t		*flist,	/* list of extents to be freed */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			rsvd)	/* OK to use reserved data block allocation */
 {
 	xfs_btree_cur_t		*cur;	/* btree cursor */
@@ -716,8 +733,8 @@
 					/* left is 0, right is 1, prev is 2 */
 	int			rval=0;	/* return value (logging flags) */
 	int			state = 0;/* state bits, accessed thru macros */
-	xfs_filblks_t		temp;	/* value for dnew calculations */
-	xfs_filblks_t		temp2;	/* value for dnew calculations */
+	xfs_filblks_t		temp=0;	/* value for dnew calculations */
+	xfs_filblks_t		temp2=0;/* value for dnew calculations */
 	int			tmp_rval;	/* partial logging flags */
 	enum {				/* bit number definitions for state */
 		LEFT_CONTIG,	RIGHT_CONTIG,
@@ -839,6 +856,11 @@
 				goto done;
 		}
 		*dnew = 0;
+		/* DELTA: Three in-core extents are replaced by one. */
+		temp = LEFT.br_startoff;
+		temp2 = LEFT.br_blockcount +
+			PREV.br_blockcount +
+			RIGHT.br_blockcount;
 		break;
 
 	case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
@@ -872,6 +894,10 @@
 				goto done;
 		}
 		*dnew = 0;
+		/* DELTA: Two in-core extents are replaced by one. */
+		temp = LEFT.br_startoff;
+		temp2 = LEFT.br_blockcount +
+			PREV.br_blockcount;
 		break;
 
 	case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
@@ -906,6 +932,10 @@
 				goto done;
 		}
 		*dnew = 0;
+		/* DELTA: Two in-core extents are replaced by one. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount +
+			RIGHT.br_blockcount;
 		break;
 
 	case MASK2(LEFT_FILLING, RIGHT_FILLING):
@@ -936,6 +966,9 @@
 			ASSERT(i == 1);
 		}
 		*dnew = 0;
+		/* DELTA: The in-core extent described by new changed type. */
+		temp = new->br_startoff;
+		temp2 = new->br_blockcount;
 		break;
 
 	case MASK2(LEFT_FILLING, LEFT_CONTIG):
@@ -978,6 +1011,10 @@
 		xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx,
 			XFS_DATA_FORK);
 		*dnew = temp;
+		/* DELTA: The boundary between two in-core extents moved. */
+		temp = LEFT.br_startoff;
+		temp2 = LEFT.br_blockcount +
+			PREV.br_blockcount;
 		break;
 
 	case MASK(LEFT_FILLING):
@@ -1025,6 +1062,9 @@
 		xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1,
 			XFS_DATA_FORK);
 		*dnew = temp;
+		/* DELTA: One in-core extent is split in two. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount;
 		break;
 
 	case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
@@ -1067,6 +1107,10 @@
 		xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx,
 			XFS_DATA_FORK);
 		*dnew = temp;
+		/* DELTA: The boundary between two in-core extents moved. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount +
+			RIGHT.br_blockcount;
 		break;
 
 	case MASK(RIGHT_FILLING):
@@ -1112,6 +1156,9 @@
 		xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp));
 		xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK);
 		*dnew = temp;
+		/* DELTA: One in-core extent is split in two. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount;
 		break;
 
 	case 0:
@@ -1194,6 +1241,9 @@
 		xfs_bmap_trace_post_update(fname, "0", ip, idx + 2,
 			XFS_DATA_FORK);
 		*dnew = temp + temp2;
+		/* DELTA: One in-core extent is split in three. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount;
 		break;
 
 	case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
@@ -1209,6 +1259,13 @@
 		ASSERT(0);
 	}
 	*curp = cur;
+	if (delta) {
+		temp2 += temp;
+		if (delta->xed_startoff > temp)
+			delta->xed_startoff = temp;
+		if (delta->xed_blockcount < temp2)
+			delta->xed_blockcount = temp2;
+	}
 done:
 	*logflagsp = rval;
 	return error;
@@ -1235,7 +1292,8 @@
 	xfs_extnum_t		idx,	/* extent number to update/insert */
 	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
-	int			*logflagsp) /* inode logging flags */
+	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta) /* Change made to incore extents */
 {
 	xfs_btree_cur_t		*cur;	/* btree cursor */
 	xfs_bmbt_rec_t		*ep;	/* extent entry for idx */
@@ -1252,6 +1310,8 @@
 					/* left is 0, right is 1, prev is 2 */
 	int			rval=0;	/* return value (logging flags) */
 	int			state = 0;/* state bits, accessed thru macros */
+	xfs_filblks_t		temp=0;
+	xfs_filblks_t		temp2=0;
 	enum {				/* bit number definitions for state */
 		LEFT_CONTIG,	RIGHT_CONTIG,
 		LEFT_FILLING,	RIGHT_FILLING,
@@ -1380,6 +1440,11 @@
 				RIGHT.br_blockcount, LEFT.br_state)))
 				goto done;
 		}
+		/* DELTA: Three in-core extents are replaced by one. */
+		temp = LEFT.br_startoff;
+		temp2 = LEFT.br_blockcount +
+			PREV.br_blockcount +
+			RIGHT.br_blockcount;
 		break;
 
 	case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):
@@ -1419,6 +1484,10 @@
 				LEFT.br_state)))
 				goto done;
 		}
+		/* DELTA: Two in-core extents are replaced by one. */
+		temp = LEFT.br_startoff;
+		temp2 = LEFT.br_blockcount +
+			PREV.br_blockcount;
 		break;
 
 	case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):
@@ -1459,6 +1528,10 @@
 				newext)))
 				goto done;
 		}
+		/* DELTA: Two in-core extents are replaced by one. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount +
+			RIGHT.br_blockcount;
 		break;
 
 	case MASK2(LEFT_FILLING, RIGHT_FILLING):
@@ -1487,6 +1560,9 @@
 				newext)))
 				goto done;
 		}
+		/* DELTA: The in-core extent described by new changed type. */
+		temp = new->br_startoff;
+		temp2 = new->br_blockcount;
 		break;
 
 	case MASK2(LEFT_FILLING, LEFT_CONTIG):
@@ -1534,6 +1610,10 @@
 				LEFT.br_state))
 				goto done;
 		}
+		/* DELTA: The boundary between two in-core extents moved. */
+		temp = LEFT.br_startoff;
+		temp2 = LEFT.br_blockcount +
+			PREV.br_blockcount;
 		break;
 
 	case MASK(LEFT_FILLING):
@@ -1574,6 +1654,9 @@
 				goto done;
 			ASSERT(i == 1);
 		}
+		/* DELTA: One in-core extent is split in two. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount;
 		break;
 
 	case MASK2(RIGHT_FILLING, RIGHT_CONTIG):
@@ -1617,6 +1700,10 @@
 				newext)))
 				goto done;
 		}
+		/* DELTA: The boundary between two in-core extents moved. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount +
+			RIGHT.br_blockcount;
 		break;
 
 	case MASK(RIGHT_FILLING):
@@ -1657,6 +1744,9 @@
 				goto done;
 			ASSERT(i == 1);
 		}
+		/* DELTA: One in-core extent is split in two. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount;
 		break;
 
 	case 0:
@@ -1710,6 +1800,9 @@
 				goto done;
 			ASSERT(i == 1);
 		}
+		/* DELTA: One in-core extent is split in three. */
+		temp = PREV.br_startoff;
+		temp2 = PREV.br_blockcount;
 		break;
 
 	case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):
@@ -1725,6 +1818,13 @@
 		ASSERT(0);
 	}
 	*curp = cur;
+	if (delta) {
+		temp2 += temp;
+		if (delta->xed_startoff > temp)
+			delta->xed_startoff = temp;
+		if (delta->xed_blockcount < temp2)
+			delta->xed_blockcount = temp2;
+	}
 done:
 	*logflagsp = rval;
 	return error;
@@ -1753,6 +1853,7 @@
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			rsvd)		/* OK to allocate reserved blocks */
 {
 	xfs_bmbt_rec_t		*ep;	/* extent record for idx */
@@ -1765,7 +1866,8 @@
 	xfs_filblks_t		oldlen=0;	/* old indirect size */
 	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
 	int			state;  /* state bits, accessed thru macros */
-	xfs_filblks_t		temp;	/* temp for indirect calculations */
+	xfs_filblks_t		temp=0;	/* temp for indirect calculations */
+	xfs_filblks_t		temp2=0;
 	enum {				/* bit number definitions for state */
 		LEFT_CONTIG,	RIGHT_CONTIG,
 		LEFT_DELAY,	RIGHT_DELAY,
@@ -1844,6 +1946,9 @@
 			XFS_DATA_FORK);
 		xfs_iext_remove(ifp, idx, 1);
 		ip->i_df.if_lastex = idx - 1;
+		/* DELTA: Two in-core extents were replaced by one. */
+		temp2 = temp;
+		temp = left.br_startoff;
 		break;
 
 	case MASK(LEFT_CONTIG):
@@ -1864,6 +1969,9 @@
 		xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1,
 			XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx - 1;
+		/* DELTA: One in-core extent grew into a hole. */
+		temp2 = temp;
+		temp = left.br_startoff;
 		break;
 
 	case MASK(RIGHT_CONTIG):
@@ -1881,6 +1989,9 @@
 			NULLSTARTBLOCK((int)newlen), temp, right.br_state);
 		xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK);
 		ip->i_df.if_lastex = idx;
+		/* DELTA: One in-core extent grew into a hole. */
+		temp2 = temp;
+		temp = new->br_startoff;
 		break;
 
 	case 0:
@@ -1894,6 +2005,9 @@
 			XFS_DATA_FORK);
 		xfs_iext_insert(ifp, idx, 1, new);
 		ip->i_df.if_lastex = idx;
+		/* DELTA: A new in-core extent was added in a hole. */
+		temp2 = new->br_blockcount;
+		temp = new->br_startoff;
 		break;
 	}
 	if (oldlen != newlen) {
@@ -1904,6 +2018,13 @@
 		 * Nothing to do for disk quota accounting here.
 		 */
 	}
+	if (delta) {
+		temp2 += temp;
+		if (delta->xed_startoff > temp)
+			delta->xed_startoff = temp;
+		if (delta->xed_blockcount < temp2)
+			delta->xed_blockcount = temp2;
+	}
 	*logflagsp = 0;
 	return 0;
 #undef	MASK
@@ -1925,6 +2046,7 @@
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			whichfork) /* data or attr fork */
 {
 	xfs_bmbt_rec_t		*ep;	/* pointer to extent entry ins. point */
@@ -1936,7 +2058,10 @@
 	xfs_ifork_t		*ifp;	/* inode fork pointer */
 	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */
 	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */
+	int			rval=0;	/* return value (logging flags) */
 	int			state;	/* state bits, accessed thru macros */
+	xfs_filblks_t		temp=0;
+	xfs_filblks_t		temp2=0;
 	enum {				/* bit number definitions for state */
 		LEFT_CONTIG,	RIGHT_CONTIG,
 		LEFT_DELAY,	RIGHT_DELAY,
@@ -1993,6 +2118,7 @@
 		 left.br_blockcount + new->br_blockcount +
 		     right.br_blockcount <= MAXEXTLEN));
 
+	error = 0;
 	/*
 	 * Select which case we're in here, and implement it.
 	 */
@@ -2018,25 +2144,35 @@
 		XFS_IFORK_NEXT_SET(ip, whichfork,
 			XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
 		if (cur == NULL) {
-			*logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
-			return 0;
+			rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
+		} else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur,
+					right.br_startoff,
+					right.br_startblock,
+					right.br_blockcount, &i)))
+				goto done;
+			ASSERT(i == 1);
+			if ((error = xfs_bmbt_delete(cur, &i)))
+				goto done;
+			ASSERT(i == 1);
+			if ((error = xfs_bmbt_decrement(cur, 0, &i)))
+				goto done;
+			ASSERT(i == 1);
+			if ((error = xfs_bmbt_update(cur, left.br_startoff,
+					left.br_startblock,
+					left.br_blockcount +
+						new->br_blockcount +
+						right.br_blockcount,
+					left.br_state)))
+				goto done;
 		}
-		*logflagsp = XFS_ILOG_CORE;
-		if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff,
-				right.br_startblock, right.br_blockcount, &i)))
-			return error;
-		ASSERT(i == 1);
-		if ((error = xfs_bmbt_delete(cur, &i)))
-			return error;
-		ASSERT(i == 1);
-		if ((error = xfs_bmbt_decrement(cur, 0, &i)))
-			return error;
-		ASSERT(i == 1);
-		error = xfs_bmbt_update(cur, left.br_startoff,
-				left.br_startblock,
-				left.br_blockcount + new->br_blockcount +
-				right.br_blockcount, left.br_state);
-		return error;
+		/* DELTA: Two in-core extents were replaced by one. */
+		temp = left.br_startoff;
+		temp2 = left.br_blockcount +
+			new->br_blockcount +
+			right.br_blockcount;
+		break;
 
 	case MASK(LEFT_CONTIG):
 		/*
@@ -2050,19 +2186,27 @@
 		xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork);
 		ifp->if_lastex = idx - 1;
 		if (cur == NULL) {
-			*logflagsp = XFS_ILOG_FEXT(whichfork);
-			return 0;
+			rval = XFS_ILOG_FEXT(whichfork);
+		} else {
+			rval = 0;
+			if ((error = xfs_bmbt_lookup_eq(cur,
+					left.br_startoff,
+					left.br_startblock,
+					left.br_blockcount, &i)))
+				goto done;
+			ASSERT(i == 1);
+			if ((error = xfs_bmbt_update(cur, left.br_startoff,
+					left.br_startblock,
+					left.br_blockcount +
+						new->br_blockcount,
+					left.br_state)))
+				goto done;
 		}
-		*logflagsp = 0;
-		if ((error = xfs_bmbt_lookup_eq(cur, left.br_startoff,
-				left.br_startblock, left.br_blockcount, &i)))
-			return error;
-		ASSERT(i == 1);
-		error = xfs_bmbt_update(cur, left.br_startoff,
-				left.br_startblock,
-				left.br_blockcount + new->br_blockcount,
-				left.br_state);
-		return error;
+		/* DELTA: One in-core extent grew. */
+		temp = left.br_startoff;
+		temp2 = left.br_blockcount +
+			new->br_blockcount;
+		break;
 
 	case MASK(RIGHT_CONTIG):
 		/*
@@ -2077,19 +2221,27 @@
 		xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork);
 		ifp->if_lastex = idx;
 		if (cur == NULL) {
-			*logflagsp = XFS_ILOG_FEXT(whichfork);
-			return 0;
+			rval = XFS_ILOG_FEXT(whichfork);
+		} else {
+			rval = 0;
+			if ((error = xfs_bmbt_lookup_eq(cur,
+					right.br_startoff,
+					right.br_startblock,
+					right.br_blockcount, &i)))
+				goto done;
+			ASSERT(i == 1);
+			if ((error = xfs_bmbt_update(cur, new->br_startoff,
+					new->br_startblock,
+					new->br_blockcount +
+						right.br_blockcount,
+					right.br_state)))
+				goto done;
 		}
-		*logflagsp = 0;
-		if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff,
-				right.br_startblock, right.br_blockcount, &i)))
-			return error;
-		ASSERT(i == 1);
-		error = xfs_bmbt_update(cur, new->br_startoff,
-				new->br_startblock,
-				new->br_blockcount + right.br_blockcount,
-				right.br_state);
-		return error;
+		/* DELTA: One in-core extent grew. */
+		temp = new->br_startoff;
+		temp2 = new->br_blockcount +
+			right.br_blockcount;
+		break;
 
 	case 0:
 		/*
@@ -2104,29 +2256,41 @@
 		XFS_IFORK_NEXT_SET(ip, whichfork,
 			XFS_IFORK_NEXTENTS(ip, whichfork) + 1);
 		if (cur == NULL) {
-			*logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
-			return 0;
+			rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork);
+		} else {
+			rval = XFS_ILOG_CORE;
+			if ((error = xfs_bmbt_lookup_eq(cur,
+					new->br_startoff,
+					new->br_startblock,
+					new->br_blockcount, &i)))
+				goto done;
+			ASSERT(i == 0);
+			cur->bc_rec.b.br_state = new->br_state;
+			if ((error = xfs_bmbt_insert(cur, &i)))
+				goto done;
+			ASSERT(i == 1);
 		}
-		*logflagsp = XFS_ILOG_CORE;
-		if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,
-				new->br_startblock, new->br_blockcount, &i)))
-			return error;
-		ASSERT(i == 0);
-		cur->bc_rec.b.br_state = new->br_state;
-		if ((error = xfs_bmbt_insert(cur, &i)))
-			return error;
-		ASSERT(i == 1);
-		return 0;
+		/* DELTA: A new extent was added in a hole. */
+		temp = new->br_startoff;
+		temp2 = new->br_blockcount;
+		break;
 	}
+	if (delta) {
+		temp2 += temp;
+		if (delta->xed_startoff > temp)
+			delta->xed_startoff = temp;
+		if (delta->xed_blockcount < temp2)
+			delta->xed_blockcount = temp2;
+	}
+done:
+	*logflagsp = rval;
+	return error;
 #undef	MASK
 #undef	MASK2
 #undef	STATE_SET
 #undef	STATE_TEST
 #undef	STATE_SET_TEST
 #undef	SWITCH_STATE
-	/* NOTREACHED */
-	ASSERT(0);
-	return 0; /* keep gcc quite */
 }
 
 /*
@@ -2598,6 +2762,7 @@
 	args.mp = mp;
 	args.fsbno = ap->rval;
 	args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks);
+	args.firstblock = ap->firstblock;
 	blen = 0;
 	if (nullfb) {
 		args.type = XFS_ALLOCTYPE_START_BNO;
@@ -2657,7 +2822,7 @@
 		else
 			args.minlen = ap->alen;
 	} else if (ap->low) {
-		args.type = XFS_ALLOCTYPE_FIRST_AG;
+		args.type = XFS_ALLOCTYPE_START_BNO;
 		args.total = args.minlen = ap->minlen;
 	} else {
 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
@@ -2669,7 +2834,7 @@
 		args.prod = ap->ip->i_d.di_extsize;
 		if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod)))
 			args.mod = (xfs_extlen_t)(args.prod - args.mod);
-	} else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) {
+	} else if (mp->m_sb.sb_blocksize >= NBPP) {
 		args.prod = 1;
 		args.mod = 0;
 	} else {
@@ -2885,6 +3050,7 @@
 	xfs_btree_cur_t		*cur,	/* if null, not a btree */
 	xfs_bmbt_irec_t		*del,	/* data to remove from extents */
 	int			*logflagsp, /* inode logging flags */
+	xfs_extdelta_t		*delta, /* Change made to incore extents */
 	int			whichfork, /* data or attr fork */
 	int			rsvd)	/* OK to allocate reserved blocks */
 {
@@ -3193,6 +3359,14 @@
 	if (da_old > da_new)
 		xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new),
 			rsvd);
+	if (delta) {
+		/* DELTA: report the original extent. */
+		if (delta->xed_startoff > got.br_startoff)
+			delta->xed_startoff = got.br_startoff;
+		if (delta->xed_blockcount < got.br_startoff+got.br_blockcount)
+			delta->xed_blockcount = got.br_startoff +
+							got.br_blockcount;
+	}
 done:
 	*logflagsp = flags;
 	return error;
@@ -3279,6 +3453,7 @@
 	XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
 	args.tp = tp;
 	args.mp = mp;
+	args.firstblock = *firstblock;
 	if (*firstblock == NULLFSBLOCK) {
 		args.type = XFS_ALLOCTYPE_START_BNO;
 		args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino);
@@ -3414,6 +3589,7 @@
 
 		args.tp = tp;
 		args.mp = ip->i_mount;
+		args.firstblock = *firstblock;
 		ASSERT((ifp->if_flags &
 			(XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE);
 		/*
@@ -3753,7 +3929,7 @@
 	if (ip->i_rwtrace == NULL)
 		return;
 	ktrace_enter(ip->i_rwtrace,
-		(void *)(__psint_t)XFS_BUNMAPI,
+		(void *)(__psint_t)XFS_BUNMAP,
 		(void *)ip,
 		(void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff),
 		(void *)(__psint_t)(ip->i_d.di_size & 0xffffffff),
@@ -4087,8 +4263,8 @@
 			if (!XFS_FORCED_SHUTDOWN(mp))
 				xfs_force_shutdown(mp,
 						   (error == EFSCORRUPTED) ?
-						   XFS_CORRUPT_INCORE :
-						   XFS_METADATA_IO_ERROR);
+						   SHUTDOWN_CORRUPT_INCORE :
+						   SHUTDOWN_META_IO_ERROR);
 			return error;
 		}
 		xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock,
@@ -4538,7 +4714,8 @@
 	xfs_extlen_t	total,		/* total blocks needed */
 	xfs_bmbt_irec_t	*mval,		/* output: map values */
 	int		*nmap,		/* i/o: mval size/count */
-	xfs_bmap_free_t	*flist)		/* i/o: list extents to free */
+	xfs_bmap_free_t	*flist,		/* i/o: list extents to free */
+	xfs_extdelta_t	*delta)		/* o: change made to incore extents */
 {
 	xfs_fsblock_t	abno;		/* allocated block number */
 	xfs_extlen_t	alen;		/* allocated extent length */
@@ -4650,6 +4827,10 @@
 	end = bno + len;
 	obno = bno;
 	bma.ip = NULL;
+	if (delta) {
+		delta->xed_startoff = NULLFILEOFF;
+		delta->xed_blockcount = 0;
+	}
 	while (bno < end && n < *nmap) {
 		/*
 		 * Reading past eof, act as though there's a hole
@@ -4886,8 +5067,8 @@
 					got.br_state = XFS_EXT_UNWRITTEN;
 			}
 			error = xfs_bmap_add_extent(ip, lastx, &cur, &got,
-				firstblock, flist, &tmp_logflags, whichfork,
-				(flags & XFS_BMAPI_RSVBLOCKS));
+				firstblock, flist, &tmp_logflags, delta,
+				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
 			logflags |= tmp_logflags;
 			if (error)
 				goto error0;
@@ -4983,8 +5164,8 @@
 			}
 			mval->br_state = XFS_EXT_NORM;
 			error = xfs_bmap_add_extent(ip, lastx, &cur, mval,
-				firstblock, flist, &tmp_logflags, whichfork,
-				(flags & XFS_BMAPI_RSVBLOCKS));
+				firstblock, flist, &tmp_logflags, delta,
+				whichfork, (flags & XFS_BMAPI_RSVBLOCKS));
 			logflags |= tmp_logflags;
 			if (error)
 				goto error0;
@@ -5073,7 +5254,14 @@
 	ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE ||
 	       XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max);
 	error = 0;
-
+	if (delta && delta->xed_startoff != NULLFILEOFF) {
+		/* A change was actually made.
+		 * Note that delta->xed_blockount is an offset at this
+		 * point and needs to be converted to a block count.
+		 */
+		ASSERT(delta->xed_blockcount > delta->xed_startoff);
+		delta->xed_blockcount -= delta->xed_startoff;
+	}
 error0:
 	/*
 	 * Log everything.  Do this after conversion, there's no point in
@@ -5185,6 +5373,8 @@
 	xfs_fsblock_t		*firstblock,	/* first allocated block
 						   controls a.g. for allocs */
 	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
+	xfs_extdelta_t		*delta,		/* o: change made to incore
+						   extents */
 	int			*done)		/* set if not done yet */
 {
 	xfs_btree_cur_t		*cur;		/* bmap btree cursor */
@@ -5242,6 +5432,10 @@
 	bno = start + len - 1;
 	ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got,
 		&prev);
+	if (delta) {
+		delta->xed_startoff = NULLFILEOFF;
+		delta->xed_blockcount = 0;
+	}
 	/*
 	 * Check to see if the given block number is past the end of the
 	 * file, back up to the last block if so...
@@ -5340,7 +5534,8 @@
 			}
 			del.br_state = XFS_EXT_UNWRITTEN;
 			error = xfs_bmap_add_extent(ip, lastx, &cur, &del,
-				firstblock, flist, &logflags, XFS_DATA_FORK, 0);
+				firstblock, flist, &logflags, delta,
+				XFS_DATA_FORK, 0);
 			if (error)
 				goto error0;
 			goto nodelete;
@@ -5394,7 +5589,7 @@
 				prev.br_state = XFS_EXT_UNWRITTEN;
 				error = xfs_bmap_add_extent(ip, lastx - 1, &cur,
 					&prev, firstblock, flist, &logflags,
-					XFS_DATA_FORK, 0);
+					delta, XFS_DATA_FORK, 0);
 				if (error)
 					goto error0;
 				goto nodelete;
@@ -5403,7 +5598,7 @@
 				del.br_state = XFS_EXT_UNWRITTEN;
 				error = xfs_bmap_add_extent(ip, lastx, &cur,
 					&del, firstblock, flist, &logflags,
-					XFS_DATA_FORK, 0);
+					delta, XFS_DATA_FORK, 0);
 				if (error)
 					goto error0;
 				goto nodelete;
@@ -5456,7 +5651,7 @@
 			goto error0;
 		}
 		error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del,
-			&tmp_logflags, whichfork, rsvd);
+				&tmp_logflags, delta, whichfork, rsvd);
 		logflags |= tmp_logflags;
 		if (error)
 			goto error0;
@@ -5513,6 +5708,14 @@
 	ASSERT(ifp->if_ext_max ==
 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
 	error = 0;
+	if (delta && delta->xed_startoff != NULLFILEOFF) {
+		/* A change was actually made.
+		 * Note that delta->xed_blockount is an offset at this
+		 * point and needs to be converted to a block count.
+		 */
+		ASSERT(delta->xed_blockcount > delta->xed_startoff);
+		delta->xed_blockcount -= delta->xed_startoff;
+	}
 error0:
 	/*
 	 * Log everything.  Do this after conversion, there's no point in
@@ -5556,7 +5759,7 @@
 	__int64_t		fixlen;		/* length for -1 case */
 	int			i;		/* extent number */
 	xfs_inode_t		*ip;		/* xfs incore inode pointer */
-	vnode_t			*vp;		/* corresponding vnode */
+	bhv_vnode_t		*vp;		/* corresponding vnode */
 	int			lock;		/* lock state */
 	xfs_bmbt_irec_t		*map;		/* buffer for user's data */
 	xfs_mount_t		*mp;		/* file system mount point */
@@ -5653,7 +5856,7 @@
 
 	if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) {
 		/* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
-		VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error);
+		error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF);
 	}
 
 	ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0);
@@ -5689,7 +5892,8 @@
 		nmap = (nexleft > subnex) ? subnex : nexleft;
 		error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
 				  XFS_BB_TO_FSB(mp, bmv->bmv_length),
-				  bmapi_flags, NULL, 0, map, &nmap, NULL);
+				  bmapi_flags, NULL, 0, map, &nmap,
+				  NULL, NULL);
 		if (error)
 			goto unlock_and_return;
 		ASSERT(nmap <= subnex);
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index 8e0d73d..80e9340 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -26,6 +26,20 @@
 struct xfs_trans;
 
 /*
+ * DELTA: describe a change to the in-core extent list.
+ *
+ * Internally the use of xed_blockount is somewhat funky.
+ * xed_blockcount contains an offset much of the time because this
+ * makes merging changes easier.  (xfs_fileoff_t and xfs_filblks_t are
+ * the same underlying type).
+ */
+typedef struct xfs_extdelta
+{
+	xfs_fileoff_t		xed_startoff;	/* offset of range */
+	xfs_filblks_t		xed_blockcount;	/* blocks in range */
+} xfs_extdelta_t;
+
+/*
  * List of extents to be free "later".
  * The list is kept sorted on xbf_startblock.
  */
@@ -275,7 +289,9 @@
 	xfs_extlen_t		total,		/* total blocks needed */
 	struct xfs_bmbt_irec	*mval,		/* output: map values */
 	int			*nmap,		/* i/o: mval size/count */
-	xfs_bmap_free_t		*flist);	/* i/o: list extents to free */
+	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
+	xfs_extdelta_t		*delta);	/* o: change made to incore
+						   extents */
 
 /*
  * Map file blocks to filesystem blocks, simple version.
@@ -309,6 +325,8 @@
 	xfs_fsblock_t		*firstblock,	/* first allocated block
 						   controls a.g. for allocs */
 	xfs_bmap_free_t		*flist,		/* i/o: list extents to free */
+	xfs_extdelta_t		*delta,		/* o: change made to incore
+						   extents */
 	int			*done);		/* set if not done yet */
 
 /*
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index bea44709..18fb738 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -1569,12 +1567,11 @@
 	lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));
 	left = XFS_BUF_TO_BMBT_BLOCK(lbp);
 	args.fsbno = cur->bc_private.b.firstblock;
+	args.firstblock = args.fsbno;
 	if (args.fsbno == NULLFSBLOCK) {
 		args.fsbno = lbno;
 		args.type = XFS_ALLOCTYPE_START_BNO;
-	} else if (cur->bc_private.b.flist->xbf_low)
-		args.type = XFS_ALLOCTYPE_FIRST_AG;
-	else
+	} else
 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
 	args.mod = args.minleft = args.alignment = args.total = args.isfl =
 		args.userdata = args.minalignslop = 0;
@@ -2356,6 +2353,7 @@
 		args.userdata = args.minalignslop = 0;
 	args.minlen = args.maxlen = args.prod = 1;
 	args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
+	args.firstblock = args.fsbno;
 	if (args.fsbno == NULLFSBLOCK) {
 #ifdef DEBUG
 		if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
@@ -2365,9 +2363,7 @@
 #endif
 		args.fsbno = INT_GET(*pp, ARCH_CONVERT);
 		args.type = XFS_ALLOCTYPE_START_BNO;
-	} else if (args.wasdel)
-		args.type = XFS_ALLOCTYPE_FIRST_AG;
-	else
+	} else
 		args.type = XFS_ALLOCTYPE_NEAR_BNO;
 	if ((error = xfs_alloc_vextent(&args))) {
 		XFS_BMBT_TRACE_CURSOR(cur, ERROR);
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 52d5d09..ee2255b 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 5fed156..a4aa539 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -23,7 +23,6 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_buf_item.h"
@@ -1030,9 +1029,9 @@
 		if ((XFS_BUF_TARGET(bp) != lasttarg) ||
 		    (time_after(jiffies, (lasttime + 5*HZ)))) {
 			lasttime = jiffies;
-			prdev("XFS write error in file system meta-data "
-			      "block 0x%llx in %s",
-			      XFS_BUF_TARGET(bp),
+			cmn_err(CE_ALERT, "Device %s, XFS metadata write error"
+					" block 0x%llx in %s",
+				XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
 			      (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname);
 		}
 		lasttarg = XFS_BUF_TARGET(bp);
@@ -1108,7 +1107,7 @@
 	XFS_BUF_ERROR(bp,0);
 	xfs_buftrace("BUF_ERROR_RELSE", bp);
 	if (! XFS_FORCED_SHUTDOWN(mp))
-		xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
+		xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
 	/*
 	 * We have to unpin the pinned buffers so do the
 	 * callbacks.
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h
index d0035c6e..7a0e482 100644
--- a/fs/xfs/xfs_cap.h
+++ b/fs/xfs/xfs_cap.h
@@ -49,12 +49,12 @@
 
 #include <linux/posix_cap_xattr.h>
 
-struct vnode;
+struct bhv_vnode;
 
-extern int xfs_cap_vhascap(struct vnode *);
-extern int xfs_cap_vset(struct vnode *, void *, size_t);
-extern int xfs_cap_vget(struct vnode *, void *, size_t);
-extern int xfs_cap_vremove(struct vnode *vp);
+extern int xfs_cap_vhascap(struct bhv_vnode *);
+extern int xfs_cap_vset(struct bhv_vnode *, void *, size_t);
+extern int xfs_cap_vget(struct bhv_vnode *, void *, size_t);
+extern int xfs_cap_vremove(struct bhv_vnode *);
 
 #define _CAP_EXISTS		xfs_cap_vhascap
 
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 8988b90..32ab61d 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -43,7 +41,6 @@
 #include "xfs_bmap.h"
 #include "xfs_attr.h"
 #include "xfs_attr_leaf.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_dir2_data.h"
 #include "xfs_dir2_leaf.h"
 #include "xfs_dir2_block.h"
@@ -159,7 +156,7 @@
 	max = state->path.active - 1;
 	ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH));
 	ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC ||
-	       state->path.blk[max].magic == XFS_DIRX_LEAF_MAGIC(state->mp));
+	       state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC);
 
 	addblk = &state->path.blk[max];		/* initial dummy value */
 	for (i = max; (i >= 0) && addblk; state->path.active--, i--) {
@@ -199,38 +196,7 @@
 				return(error);	/* GROT: attr inconsistent */
 			addblk = newblk;
 			break;
-		case XFS_DIR_LEAF_MAGIC:
-			ASSERT(XFS_DIR_IS_V1(state->mp));
-			error = xfs_dir_leaf_split(state, oldblk, newblk);
-			if ((error != 0) && (error != ENOSPC)) {
-				return(error);	/* GROT: dir is inconsistent */
-			}
-			if (!error) {
-				addblk = newblk;
-				break;
-			}
-			/*
-			 * Entry wouldn't fit, split the leaf again.
-			 */
-			state->extravalid = 1;
-			if (state->inleaf) {
-				state->extraafter = 0;	/* before newblk */
-				error = xfs_dir_leaf_split(state, oldblk,
-							   &state->extrablk);
-				if (error)
-					return(error);	/* GROT: dir incon. */
-				addblk = newblk;
-			} else {
-				state->extraafter = 1;	/* after newblk */
-				error = xfs_dir_leaf_split(state, newblk,
-							   &state->extrablk);
-				if (error)
-					return(error);	/* GROT: dir incon. */
-				addblk = newblk;
-			}
-			break;
 		case XFS_DIR2_LEAFN_MAGIC:
-			ASSERT(XFS_DIR_IS_V2(state->mp));
 			error = xfs_dir2_leafn_split(state, oldblk, newblk);
 			if (error)
 				return error;
@@ -363,7 +329,6 @@
 		size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] -
 			     (char *)oldroot);
 	} else {
-		ASSERT(XFS_DIR_IS_V2(mp));
 		ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
 		leaf = (xfs_dir2_leaf_t *)oldroot;
 		size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] -
@@ -379,8 +344,7 @@
 	 * Set up the new root node.
 	 */
 	error = xfs_da_node_create(args,
-		args->whichfork == XFS_DATA_FORK &&
-		XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0,
+		(args->whichfork == XFS_DATA_FORK) ? mp->m_dirleafblk : 0,
 		be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork);
 	if (error)
 		return(error);
@@ -427,10 +391,9 @@
 	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
 
 	/*
-	 * With V2 the extra block is data or freespace.
+	 * With V2 dirs the extra block is data or freespace.
 	 */
-	useextra = state->extravalid && (XFS_DIR_IS_V1(state->mp) ||
-			state->args->whichfork == XFS_ATTR_FORK);
+	useextra = state->extravalid && state->args->whichfork == XFS_ATTR_FORK;
 	newcount = 1 + useextra;
 	/*
 	 * Do we have to split the node?
@@ -624,7 +587,7 @@
 	ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC);
 	ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count)));
 	ASSERT(newblk->blkno != 0);
-	if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
+	if (state->args->whichfork == XFS_DATA_FORK)
 		ASSERT(newblk->blkno >= mp->m_dirleafblk &&
 		       newblk->blkno < mp->m_dirfreeblk);
 
@@ -670,7 +633,7 @@
 	save_blk = &state->altpath.blk[ state->path.active-1 ];
 	ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC);
 	ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC ||
-	       drop_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp));
+	       drop_blk->magic == XFS_DIR2_LEAFN_MAGIC);
 
 	/*
 	 * Walk back up the tree joining/deallocating as necessary.
@@ -693,17 +656,7 @@
 				return(0);
 			xfs_attr_leaf_unbalance(state, drop_blk, save_blk);
 			break;
-		case XFS_DIR_LEAF_MAGIC:
-			ASSERT(XFS_DIR_IS_V1(state->mp));
-			error = xfs_dir_leaf_toosmall(state, &action);
-			if (error)
-				return(error);
-			if (action == 0)
-				return(0);
-			xfs_dir_leaf_unbalance(state, drop_blk, save_blk);
-			break;
 		case XFS_DIR2_LEAFN_MAGIC:
-			ASSERT(XFS_DIR_IS_V2(state->mp));
 			error = xfs_dir2_leafn_toosmall(state, &action);
 			if (error)
 				return error;
@@ -790,7 +743,7 @@
 	ASSERT(bp != NULL);
 	blkinfo = bp->data;
 	if (be16_to_cpu(oldroot->hdr.level) == 1) {
-		ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
+		ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIR2_LEAFN_MAGIC ||
 		       be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC);
 	} else {
 		ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC);
@@ -951,14 +904,7 @@
 		if (count == 0)
 			return;
 		break;
-	case XFS_DIR_LEAF_MAGIC:
-		ASSERT(XFS_DIR_IS_V1(state->mp));
-		lasthash = xfs_dir_leaf_lasthash(blk->bp, &count);
-		if (count == 0)
-			return;
-		break;
 	case XFS_DIR2_LEAFN_MAGIC:
-		ASSERT(XFS_DIR_IS_V2(state->mp));
 		lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count);
 		if (count == 0)
 			return;
@@ -1117,10 +1063,7 @@
 	 * Descend thru the B-tree searching each level for the right
 	 * node to use, until the right hashval is found.
 	 */
-	if (args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(state->mp))
-		blkno = state->mp->m_dirleafblk;
-	else
-		blkno = 0;
+	blkno = (args->whichfork == XFS_DATA_FORK)? state->mp->m_dirleafblk : 0;
 	for (blk = &state->path.blk[0], state->path.active = 1;
 			 state->path.active <= XFS_DA_NODE_MAXDEPTH;
 			 blk++, state->path.active++) {
@@ -1137,7 +1080,7 @@
 		}
 		curr = blk->bp->data;
 		ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC ||
-		       be16_to_cpu(curr->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
+		       be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC ||
 		       be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC);
 
 		/*
@@ -1190,16 +1133,10 @@
 				blk->index = probe;
 				blkno = be32_to_cpu(btree->before);
 			}
-		}
-		else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
+		} else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) {
 			blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
 			break;
-		}
-		else if (be16_to_cpu(curr->magic) == XFS_DIR_LEAF_MAGIC) {
-			blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL);
-			break;
-		}
-		else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
+		} else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) {
 			blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
 			break;
 		}
@@ -1212,12 +1149,7 @@
 	 * next leaf and keep searching.
 	 */
 	for (;;) {
-		if (blk->magic == XFS_DIR_LEAF_MAGIC) {
-			ASSERT(XFS_DIR_IS_V1(state->mp));
-			retval = xfs_dir_leaf_lookup_int(blk->bp, args,
-								  &blk->index);
-		} else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
-			ASSERT(XFS_DIR_IS_V2(state->mp));
+		if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
 			retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
 							&blk->index, state);
 		}
@@ -1270,7 +1202,7 @@
 	old_info = old_blk->bp->data;
 	new_info = new_blk->bp->data;
 	ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC ||
-	       old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) ||
+	       old_blk->magic == XFS_DIR2_LEAFN_MAGIC ||
 	       old_blk->magic == XFS_ATTR_LEAF_MAGIC);
 	ASSERT(old_blk->magic == be16_to_cpu(old_info->magic));
 	ASSERT(new_blk->magic == be16_to_cpu(new_info->magic));
@@ -1280,12 +1212,7 @@
 	case XFS_ATTR_LEAF_MAGIC:
 		before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp);
 		break;
-	case XFS_DIR_LEAF_MAGIC:
-		ASSERT(XFS_DIR_IS_V1(state->mp));
-		before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp);
-		break;
 	case XFS_DIR2_LEAFN_MAGIC:
-		ASSERT(XFS_DIR_IS_V2(state->mp));
 		before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp);
 		break;
 	case XFS_DA_NODE_MAGIC:
@@ -1404,7 +1331,7 @@
 	save_info = save_blk->bp->data;
 	drop_info = drop_blk->bp->data;
 	ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC ||
-	       save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) ||
+	       save_blk->magic == XFS_DIR2_LEAFN_MAGIC ||
 	       save_blk->magic == XFS_ATTR_LEAF_MAGIC);
 	ASSERT(save_blk->magic == be16_to_cpu(save_info->magic));
 	ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic));
@@ -1529,7 +1456,7 @@
 		ASSERT(blk->bp != NULL);
 		info = blk->bp->data;
 		ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC ||
-		       be16_to_cpu(info->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) ||
+		       be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC ||
 		       be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC);
 		blk->magic = be16_to_cpu(info->magic);
 		if (blk->magic == XFS_DA_NODE_MAGIC) {
@@ -1548,20 +1475,13 @@
 				blk->hashval = xfs_attr_leaf_lasthash(blk->bp,
 								      NULL);
 				break;
-			case XFS_DIR_LEAF_MAGIC:
-				ASSERT(XFS_DIR_IS_V1(state->mp));
-				blk->hashval = xfs_dir_leaf_lasthash(blk->bp,
-								     NULL);
-				break;
 			case XFS_DIR2_LEAFN_MAGIC:
-				ASSERT(XFS_DIR_IS_V2(state->mp));
 				blk->hashval = xfs_dir2_leafn_lasthash(blk->bp,
 								       NULL);
 				break;
 			default:
 				ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC ||
-				       blk->magic ==
-				       XFS_DIRX_LEAF_MAGIC(state->mp));
+				       blk->magic == XFS_DIR2_LEAFN_MAGIC);
 				break;
 			}
 		}
@@ -1620,7 +1540,6 @@
 	xfs_bmbt_irec_t	*mapp;
 	xfs_inode_t *dp;
 	int nmap, error, w, count, c, got, i, mapi;
-	xfs_fsize_t size;
 	xfs_trans_t *tp;
 	xfs_mount_t *mp;
 
@@ -1631,7 +1550,7 @@
 	/*
 	 * For new directories adjust the file offset and block count.
 	 */
-	if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) {
+	if (w == XFS_DATA_FORK) {
 		bno = mp->m_dirleafblk;
 		count = mp->m_dirblkfsbs;
 	} else {
@@ -1641,10 +1560,9 @@
 	/*
 	 * Find a spot in the file space to put the new block.
 	 */
-	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) {
+	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w)))
 		return error;
-	}
-	if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
+	if (w == XFS_DATA_FORK)
 		ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk);
 	/*
 	 * Try mapping it in one filesystem block.
@@ -1655,7 +1573,7 @@
 			XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|
 			XFS_BMAPI_CONTIG,
 			args->firstblock, args->total, &map, &nmap,
-			args->flist))) {
+			args->flist, NULL))) {
 		return error;
 	}
 	ASSERT(nmap <= 1);
@@ -1676,7 +1594,8 @@
 					XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|
 					XFS_BMAPI_METADATA,
 					args->firstblock, args->total,
-					&mapp[mapi], &nmap, args->flist))) {
+					&mapp[mapi], &nmap, args->flist,
+					NULL))) {
 				kmem_free(mapp, sizeof(*mapp) * count);
 				return error;
 			}
@@ -1705,19 +1624,6 @@
 	if (mapp != &map)
 		kmem_free(mapp, sizeof(*mapp) * count);
 	*new_blkno = (xfs_dablk_t)bno;
-	/*
-	 * For version 1 directories, adjust the file size if it changed.
-	 */
-	if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
-		ASSERT(mapi == 1);
-		if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
-			return error;
-		size = XFS_FSB_TO_B(mp, bno);
-		if (size != dp->i_d.di_size) {
-			dp->i_d.di_size = size;
-			xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
-		}
-	}
 	return 0;
 }
 
@@ -1742,7 +1648,6 @@
 	int error, w, entno, level, dead_level;
 	xfs_da_blkinfo_t *dead_info, *sib_info;
 	xfs_da_intnode_t *par_node, *dead_node;
-	xfs_dir_leafblock_t *dead_leaf;
 	xfs_dir2_leaf_t *dead_leaf2;
 	xfs_dahash_t dead_hash;
 
@@ -1753,11 +1658,8 @@
 	w = args->whichfork;
 	ASSERT(w == XFS_DATA_FORK);
 	mp = ip->i_mount;
-	if (XFS_DIR_IS_V2(mp)) {
-		lastoff = mp->m_dirfreeblk;
-		error = xfs_bmap_last_before(tp, ip, &lastoff, w);
-	} else
-		error = xfs_bmap_last_offset(tp, ip, &lastoff, w);
+	lastoff = mp->m_dirfreeblk;
+	error = xfs_bmap_last_before(tp, ip, &lastoff, w);
 	if (error)
 		return error;
 	if (unlikely(lastoff == 0)) {
@@ -1780,14 +1682,7 @@
 	/*
 	 * Get values from the moved block.
 	 */
-	if (be16_to_cpu(dead_info->magic) == XFS_DIR_LEAF_MAGIC) {
-		ASSERT(XFS_DIR_IS_V1(mp));
-		dead_leaf = (xfs_dir_leafblock_t *)dead_info;
-		dead_level = 0;
-		dead_hash =
-			INT_GET(dead_leaf->entries[INT_GET(dead_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT);
-	} else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
-		ASSERT(XFS_DIR_IS_V2(mp));
+	if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) {
 		dead_leaf2 = (xfs_dir2_leaf_t *)dead_info;
 		dead_level = 0;
 		dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval);
@@ -1842,7 +1737,7 @@
 		xfs_da_buf_done(sib_buf);
 		sib_buf = NULL;
 	}
-	par_blkno = XFS_DIR_IS_V1(mp) ? 0 : mp->m_dirleafblk;
+	par_blkno = mp->m_dirleafblk;
 	level = -1;
 	/*
 	 * Walk down the tree looking for the parent of the moved block.
@@ -1941,8 +1836,6 @@
 {
 	xfs_inode_t *dp;
 	int done, error, w, count;
-	xfs_fileoff_t bno;
-	xfs_fsize_t size;
 	xfs_trans_t *tp;
 	xfs_mount_t *mp;
 
@@ -1950,7 +1843,7 @@
 	w = args->whichfork;
 	tp = args->trans;
 	mp = dp->i_mount;
-	if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
+	if (w == XFS_DATA_FORK)
 		count = mp->m_dirblkfsbs;
 	else
 		count = 1;
@@ -1961,34 +1854,17 @@
 		 */
 		if ((error = xfs_bunmapi(tp, dp, dead_blkno, count,
 				XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA,
-				0, args->firstblock, args->flist,
+				0, args->firstblock, args->flist, NULL,
 				&done)) == ENOSPC) {
 			if (w != XFS_DATA_FORK)
-				goto done;
+				break;
 			if ((error = xfs_da_swap_lastblock(args, &dead_blkno,
 					&dead_buf)))
-				goto done;
-		} else if (error)
-			goto done;
-		else
+				break;
+		} else {
 			break;
-	}
-	ASSERT(done);
-	xfs_da_binval(tp, dead_buf);
-	/*
-	 * Adjust the directory size for version 1.
-	 */
-	if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) {
-		if ((error = xfs_bmap_last_offset(tp, dp, &bno, w)))
-			return error;
-		size = XFS_FSB_TO_B(dp->i_mount, bno);
-		if (size != dp->i_d.di_size) {
-			dp->i_d.di_size = size;
-			xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 		}
 	}
-	return 0;
-done:
 	xfs_da_binval(tp, dead_buf);
 	return error;
 }
@@ -2049,10 +1925,7 @@
 	xfs_dabuf_t	*rbp;
 
 	mp = dp->i_mount;
-	if (whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp))
-		nfsb = mp->m_dirblkfsbs;
-	else
-		nfsb = 1;
+	nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1;
 	mappedbno = *mappedbnop;
 	/*
 	 * Caller doesn't have a mapping.  -2 means don't complain
@@ -2086,7 +1959,7 @@
 					nfsb,
 					XFS_BMAPI_METADATA |
 						XFS_BMAPI_AFLAG(whichfork),
-					NULL, 0, mapp, &nmap, NULL)))
+					NULL, 0, mapp, &nmap, NULL, NULL)))
 				goto exit0;
 		}
 	} else {
@@ -2198,7 +2071,6 @@
 		magic1 = be32_to_cpu(data->hdr.magic);
 		if (unlikely(
 		    XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) &&
-				   (magic != XFS_DIR_LEAF_MAGIC) &&
 				   (magic != XFS_ATTR_LEAF_MAGIC) &&
 				   (magic != XFS_DIR2_LEAF1_MAGIC) &&
 				   (magic != XFS_DIR2_LEAFN_MAGIC) &&
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 243a730..4ab865e 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -36,14 +36,10 @@
  * level in the Btree, and to identify which type of block this is.
  */
 #define XFS_DA_NODE_MAGIC	0xfebe	/* magic number: non-leaf blocks */
-#define XFS_DIR_LEAF_MAGIC	0xfeeb	/* magic number: directory leaf blks */
 #define XFS_ATTR_LEAF_MAGIC	0xfbee	/* magic number: attribute leaf blks */
 #define	XFS_DIR2_LEAF1_MAGIC	0xd2f1	/* magic number: v2 dirlf single blks */
 #define	XFS_DIR2_LEAFN_MAGIC	0xd2ff	/* magic number: v2 dirlf multi blks */
 
-#define	XFS_DIRX_LEAF_MAGIC(mp)	\
-	(XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC)
-
 typedef struct xfs_da_blkinfo {
 	__be32		forw;			/* previous block in list */
 	__be32		back;			/* following block in list */
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 4968a63..80562b6 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -54,24 +52,14 @@
 	xfs_swapext_t	__user *sxu)
 {
 	xfs_swapext_t	*sxp;
-	xfs_inode_t     *ip=NULL, *tip=NULL, *ips[2];
-	xfs_trans_t     *tp;
+	xfs_inode_t     *ip=NULL, *tip=NULL;
 	xfs_mount_t     *mp;
-	xfs_bstat_t	*sbp;
 	struct file	*fp = NULL, *tfp = NULL;
-	vnode_t		*vp, *tvp;
-	static uint	lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
-	int		ilf_fields, tilf_fields;
+	bhv_vnode_t	*vp, *tvp;
 	int		error = 0;
-	xfs_ifork_t	*tempifp, *ifp, *tifp;
-	__uint64_t	tmp;
-	int		aforkblks = 0;
-	int		taforkblks = 0;
-	char		locked = 0;
 
 	sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL);
-	tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
-	if (!sxp || !tempifp) {
+	if (!sxp) {
 		error = XFS_ERROR(ENOMEM);
 		goto error0;
 	}
@@ -118,14 +106,56 @@
 
 	mp = ip->i_mount;
 
-	sbp = &sxp->sx_stat;
-
 	if (XFS_FORCED_SHUTDOWN(mp)) {
 		error =  XFS_ERROR(EIO);
 		goto error0;
 	}
 
-	locked = 1;
+	error = XFS_SWAP_EXTENTS(mp, &ip->i_iocore, &tip->i_iocore, sxp);
+
+ error0:
+	if (fp != NULL)
+		fput(fp);
+	if (tfp != NULL)
+		fput(tfp);
+
+	if (sxp != NULL)
+		kmem_free(sxp, sizeof(xfs_swapext_t));
+
+	return error;
+}
+
+int
+xfs_swap_extents(
+	xfs_inode_t	*ip,
+	xfs_inode_t	*tip,
+	xfs_swapext_t	*sxp)
+{
+	xfs_mount_t	*mp;
+	xfs_inode_t	*ips[2];
+	xfs_trans_t	*tp;
+	xfs_bstat_t	*sbp = &sxp->sx_stat;
+	bhv_vnode_t	*vp, *tvp;
+	xfs_ifork_t	*tempifp, *ifp, *tifp;
+	int		ilf_fields, tilf_fields;
+	static uint	lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL;
+	int		error = 0;
+	int		aforkblks = 0;
+	int		taforkblks = 0;
+	__uint64_t	tmp;
+	char		locked = 0;
+
+	mp = ip->i_mount;
+
+	tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL);
+	if (!tempifp) {
+		error = XFS_ERROR(ENOMEM);
+		goto error0;
+	}
+
+	sbp = &sxp->sx_stat;
+	vp = XFS_ITOV(ip);
+	tvp = XFS_ITOV(tip);
 
 	/* Lock in i_ino order */
 	if (ip->i_ino < tip->i_ino) {
@@ -137,6 +167,7 @@
 	}
 
 	xfs_lock_inodes(ips, 2, 0, lock_flags);
+	locked = 1;
 
 	/* Check permissions */
 	error = xfs_iaccess(ip, S_IWUSR, NULL);
@@ -169,7 +200,7 @@
 
 	if (VN_CACHED(tvp) != 0) {
 		xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
-		VOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED);
+		bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED);
 	}
 
 	/* Verify O_DIRECT for ftmp */
@@ -214,7 +245,7 @@
 	/* We need to fail if the file is memory mapped.  Once we have tossed
 	 * all existing pages, the page fault will have no option
 	 * but to go to the filesystem for pages. By making the page fault call
-	 * VOP_READ (or write in the case of autogrow) they block on the iolock
+	 * vop_read (or write in the case of autogrow) they block on the iolock
 	 * until we have switched the extents.
 	 */
 	if (VN_MAPPED(vp)) {
@@ -233,7 +264,7 @@
 	 * fields change.
 	 */
 
-	VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF);
+	bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT);
 	if ((error = xfs_trans_reserve(tp, 0,
@@ -360,16 +391,7 @@
 		xfs_iunlock(ip,  lock_flags);
 		xfs_iunlock(tip, lock_flags);
 	}
-
-	if (fp != NULL)
-		fput(fp);
-	if (tfp != NULL)
-		fput(tfp);
-
-	if (sxp != NULL)
-		kmem_free(sxp, sizeof(xfs_swapext_t));
 	if (tempifp != NULL)
 		kmem_free(tempifp, sizeof(xfs_ifork_t));
-
 	return error;
 }
diff --git a/fs/xfs/xfs_dfrag.h b/fs/xfs/xfs_dfrag.h
index f678559..da17820 100644
--- a/fs/xfs/xfs_dfrag.h
+++ b/fs/xfs/xfs_dfrag.h
@@ -48,6 +48,9 @@
  */
 int	xfs_swapext(struct xfs_swapext __user *sx);
 
+int	xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip,
+		struct xfs_swapext *sxp);
+
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_DFRAG_H__ */
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h
index 79d0d9e..b338269 100644
--- a/fs/xfs/xfs_dinode.h
+++ b/fs/xfs/xfs_dinode.h
@@ -85,7 +85,6 @@
 	union {
 		xfs_bmdr_block_t di_bmbt;	/* btree root block */
 		xfs_bmbt_rec_32_t di_bmx[1];	/* extent list */
-		xfs_dir_shortform_t di_dirsf;	/* shortform directory */
 		xfs_dir2_sf_t	di_dir2sf;	/* shortform directory v2 */
 		char		di_c[1];	/* local contents */
 		xfs_dev_t	di_dev;		/* device for S_IFCHR/S_IFBLK */
@@ -257,6 +256,7 @@
 #define XFS_DIFLAG_NOSYMLINKS_BIT   10	/* disallow symlink creation */
 #define XFS_DIFLAG_EXTSIZE_BIT      11	/* inode extent size allocator hint */
 #define XFS_DIFLAG_EXTSZINHERIT_BIT 12	/* inherit inode extent size */
+#define XFS_DIFLAG_NODEFRAG_BIT     13	/* do not reorganize/defragment */
 #define XFS_DIFLAG_REALTIME      (1 << XFS_DIFLAG_REALTIME_BIT)
 #define XFS_DIFLAG_PREALLOC      (1 << XFS_DIFLAG_PREALLOC_BIT)
 #define XFS_DIFLAG_NEWRTBM       (1 << XFS_DIFLAG_NEWRTBM_BIT)
@@ -270,12 +270,13 @@
 #define XFS_DIFLAG_NOSYMLINKS    (1 << XFS_DIFLAG_NOSYMLINKS_BIT)
 #define XFS_DIFLAG_EXTSIZE       (1 << XFS_DIFLAG_EXTSIZE_BIT)
 #define XFS_DIFLAG_EXTSZINHERIT  (1 << XFS_DIFLAG_EXTSZINHERIT_BIT)
+#define XFS_DIFLAG_NODEFRAG      (1 << XFS_DIFLAG_NODEFRAG_BIT)
 
 #define XFS_DIFLAG_ANY \
 	(XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \
 	 XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \
 	 XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \
 	 XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
-	 XFS_DIFLAG_EXTSZINHERIT)
+	 XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG)
 
 #endif	/* __XFS_DINODE_H__ */
diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c
deleted file mode 100644
index 9cc702a..0000000
--- a/fs/xfs/xfs_dir.c
+++ /dev/null
@@ -1,1217 +0,0 @@
-/*
- * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_types.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_dmapi.h"
-#include "xfs_mount.h"
-#include "xfs_da_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_alloc.h"
-#include "xfs_btree.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_bmap.h"
-#include "xfs_dir_leaf.h"
-#include "xfs_error.h"
-
-/*
- * xfs_dir.c
- *
- * Provide the external interfaces to manage directories.
- */
-
-/*========================================================================
- * Function prototypes for the kernel.
- *========================================================================*/
-
-/*
- * Functions for the dirops interfaces.
- */
-static void	xfs_dir_mount(struct xfs_mount *mp);
-
-static int	xfs_dir_isempty(struct xfs_inode *dp);
-
-static int	xfs_dir_init(struct xfs_trans *trans,
-			     struct xfs_inode *dir,
-			     struct xfs_inode *parent_dir);
-
-static int	xfs_dir_createname(struct xfs_trans *trans,
-				   struct xfs_inode *dp,
-				   char *name_string,
-				   int name_len,
-				   xfs_ino_t inode_number,
-				   xfs_fsblock_t *firstblock,
-				   xfs_bmap_free_t *flist,
-				   xfs_extlen_t total);
-
-static int	xfs_dir_lookup(struct xfs_trans *tp,
-			       struct xfs_inode *dp,
-			       char *name_string,
-			       int name_length,
-			       xfs_ino_t *inode_number);
-
-static int	xfs_dir_removename(struct xfs_trans *trans,
-				   struct xfs_inode *dp,
-				   char *name_string,
-				   int name_length,
-				   xfs_ino_t ino,
-				   xfs_fsblock_t *firstblock,
-				   xfs_bmap_free_t *flist,
-				   xfs_extlen_t total);
-
-static int	xfs_dir_getdents(struct xfs_trans *tp,
-				 struct xfs_inode *dp,
-				 struct uio *uiop,
-				 int *eofp);
-
-static int	xfs_dir_replace(struct xfs_trans *tp,
-				struct xfs_inode *dp,
-				char *name_string,
-				int name_length,
-				xfs_ino_t inode_number,
-				xfs_fsblock_t *firstblock,
-				xfs_bmap_free_t *flist,
-				xfs_extlen_t total);
-
-static int	xfs_dir_canenter(struct xfs_trans *tp,
-				 struct xfs_inode *dp,
-				 char *name_string,
-				 int name_length);
-
-static int	xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp,
-						  xfs_dinode_t *dip);
-
-xfs_dirops_t xfsv1_dirops = {
-	.xd_mount			= xfs_dir_mount,
-	.xd_isempty			= xfs_dir_isempty,
-	.xd_init			= xfs_dir_init,
-	.xd_createname			= xfs_dir_createname,
-	.xd_lookup			= xfs_dir_lookup,
-	.xd_removename			= xfs_dir_removename,
-	.xd_getdents			= xfs_dir_getdents,
-	.xd_replace			= xfs_dir_replace,
-	.xd_canenter			= xfs_dir_canenter,
-	.xd_shortform_validate_ondisk	= xfs_dir_shortform_validate_ondisk,
-	.xd_shortform_to_single		= xfs_dir_shortform_to_leaf,
-};
-
-/*
- * Internal routines when dirsize == XFS_LBSIZE(mp).
- */
-STATIC int xfs_dir_leaf_lookup(xfs_da_args_t *args);
-STATIC int xfs_dir_leaf_removename(xfs_da_args_t *args, int *number_entries,
-						 int *total_namebytes);
-STATIC int xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
-					     uio_t *uio, int *eofp,
-					     xfs_dirent_t *dbp,
-					     xfs_dir_put_t put);
-STATIC int xfs_dir_leaf_replace(xfs_da_args_t *args);
-
-/*
- * Internal routines when dirsize > XFS_LBSIZE(mp).
- */
-STATIC int xfs_dir_node_addname(xfs_da_args_t *args);
-STATIC int xfs_dir_node_lookup(xfs_da_args_t *args);
-STATIC int xfs_dir_node_removename(xfs_da_args_t *args);
-STATIC int xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp,
-					     uio_t *uio, int *eofp,
-					     xfs_dirent_t *dbp,
-					     xfs_dir_put_t put);
-STATIC int xfs_dir_node_replace(xfs_da_args_t *args);
-
-#if defined(XFS_DIR_TRACE)
-ktrace_t *xfs_dir_trace_buf;
-#endif
-
-
-/*========================================================================
- * Overall external interface routines.
- *========================================================================*/
-
-xfs_dahash_t	xfs_dir_hash_dot, xfs_dir_hash_dotdot;
-
-/*
- * One-time startup routine called from xfs_init().
- */
-void
-xfs_dir_startup(void)
-{
-	xfs_dir_hash_dot = xfs_da_hashname(".", 1);
-	xfs_dir_hash_dotdot = xfs_da_hashname("..", 2);
-}
-
-/*
- * Initialize directory-related fields in the mount structure.
- */
-static void
-xfs_dir_mount(xfs_mount_t *mp)
-{
-	uint shortcount, leafcount, count;
-
-	mp->m_dirversion = 1;
-	if (!(mp->m_flags & XFS_MOUNT_ATTR2)) {
-		shortcount = (mp->m_attroffset -
-				(uint)sizeof(xfs_dir_sf_hdr_t)) /
-				 (uint)sizeof(xfs_dir_sf_entry_t);
-		leafcount = (XFS_LBSIZE(mp) -
-				(uint)sizeof(xfs_dir_leaf_hdr_t)) /
-				 ((uint)sizeof(xfs_dir_leaf_entry_t) +
-				  (uint)sizeof(xfs_dir_leaf_name_t));
-	} else {
-		shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) -
-			      (uint)sizeof(xfs_dir_sf_hdr_t)) /
-			       (uint)sizeof(xfs_dir_sf_entry_t);
-		leafcount = (XFS_LBSIZE(mp) -
-			    (uint)sizeof(xfs_dir_leaf_hdr_t)) /
-			     ((uint)sizeof(xfs_dir_leaf_entry_t) +
-			      (uint)sizeof(xfs_dir_leaf_name_t));
-	}
-	count = shortcount > leafcount ? shortcount : leafcount;
-	mp->m_dircook_elog = xfs_da_log2_roundup(count + 1);
-	ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog);
-	mp->m_dir_node_ents = mp->m_attr_node_ents =
-		(XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) /
-		(uint)sizeof(xfs_da_node_entry_t);
-	mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100;
-	mp->m_dirblksize = mp->m_sb.sb_blocksize;
-	mp->m_dirblkfsbs = 1;
-}
-
-/*
- * Return 1 if directory contains only "." and "..".
- */
-static int
-xfs_dir_isempty(xfs_inode_t *dp)
-{
-	xfs_dir_sf_hdr_t *hdr;
-
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-	if (dp->i_d.di_size == 0)
-		return(1);
-	if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
-		return(0);
-	hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
-	return(hdr->count == 0);
-}
-
-/*
- * Initialize a directory with its "." and ".." entries.
- */
-static int
-xfs_dir_init(xfs_trans_t *trans, xfs_inode_t *dir, xfs_inode_t *parent_dir)
-{
-	xfs_da_args_t args;
-	int error;
-
-	memset((char *)&args, 0, sizeof(args));
-	args.dp = dir;
-	args.trans = trans;
-
-	ASSERT((dir->i_d.di_mode & S_IFMT) == S_IFDIR);
-	if ((error = xfs_dir_ino_validate(trans->t_mountp, parent_dir->i_ino)))
-		return error;
-
-	return(xfs_dir_shortform_create(&args, parent_dir->i_ino));
-}
-
-/*
- * Generic handler routine to add a name to a directory.
- * Transitions directory from shortform to Btree as necessary.
- */
-static int							/* error */
-xfs_dir_createname(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
-		   int namelen, xfs_ino_t inum, xfs_fsblock_t *firstblock,
-		   xfs_bmap_free_t *flist, xfs_extlen_t total)
-{
-	xfs_da_args_t args;
-	int retval, newsize, done;
-
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-
-	if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
-		return (retval);
-
-	XFS_STATS_INC(xs_dir_create);
-	/*
-	 * Fill in the arg structure for this request.
-	 */
-	args.name = name;
-	args.namelen = namelen;
-	args.hashval = xfs_da_hashname(name, namelen);
-	args.inumber = inum;
-	args.dp = dp;
-	args.firstblock = firstblock;
-	args.flist = flist;
-	args.total = total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = trans;
-	args.justcheck = 0;
-	args.addname = args.oknoent = 1;
-
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
-	done = 0;
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
-		newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
-		if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) {
-			retval = xfs_dir_shortform_addname(&args);
-			done = 1;
-		} else {
-			if (total == 0)
-				return XFS_ERROR(ENOSPC);
-			retval = xfs_dir_shortform_to_leaf(&args);
-			done = retval != 0;
-		}
-	}
-	if (!done && xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
-		retval = xfs_dir_leaf_addname(&args);
-		done = retval != ENOSPC;
-		if (!done) {
-			if (total == 0)
-				return XFS_ERROR(ENOSPC);
-			retval = xfs_dir_leaf_to_node(&args);
-			done = retval != 0;
-		}
-	}
-	if (!done) {
-		retval = xfs_dir_node_addname(&args);
-	}
-	return(retval);
-}
-
-/*
- * Generic handler routine to check if a name can be added to a directory,
- * without adding any blocks to the directory.
- */
-static int							/* error */
-xfs_dir_canenter(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen)
-{
-	xfs_da_args_t args;
-	int retval, newsize;
-
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-	/*
-	 * Fill in the arg structure for this request.
-	 */
-	args.name = name;
-	args.namelen = namelen;
-	args.hashval = xfs_da_hashname(name, namelen);
-	args.inumber = 0;
-	args.dp = dp;
-	args.firstblock = NULL;
-	args.flist = NULL;
-	args.total = 0;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = trans;
-	args.justcheck = args.addname = args.oknoent = 1;
-
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
-		newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen);
-		if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp))
-			retval = 0;
-		else
-			retval = XFS_ERROR(ENOSPC);
-	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
-		retval = xfs_dir_leaf_addname(&args);
-	} else {
-		retval = xfs_dir_node_addname(&args);
-	}
-	return(retval);
-}
-
-/*
- * Generic handler routine to remove a name from a directory.
- * Transitions directory from Btree to shortform as necessary.
- */
-static int							/* error */
-xfs_dir_removename(xfs_trans_t *trans, xfs_inode_t *dp, char *name,
-		   int namelen, xfs_ino_t ino, xfs_fsblock_t *firstblock,
-		   xfs_bmap_free_t *flist, xfs_extlen_t total)
-{
-	xfs_da_args_t args;
-	int count, totallen, newsize, retval;
-
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-	XFS_STATS_INC(xs_dir_remove);
-	/*
-	 * Fill in the arg structure for this request.
-	 */
-	args.name = name;
-	args.namelen = namelen;
-	args.hashval = xfs_da_hashname(name, namelen);
-	args.inumber = ino;
-	args.dp = dp;
-	args.firstblock = firstblock;
-	args.flist = flist;
-	args.total = total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = trans;
-	args.justcheck = args.addname = args.oknoent = 0;
-
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
-		retval = xfs_dir_shortform_removename(&args);
-	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
-		retval = xfs_dir_leaf_removename(&args, &count, &totallen);
-		if (retval == 0) {
-			newsize = XFS_DIR_SF_ALLFIT(count, totallen);
-			if (newsize <= XFS_IFORK_DSIZE(dp)) {
-				retval = xfs_dir_leaf_to_shortform(&args);
-			}
-		}
-	} else {
-		retval = xfs_dir_node_removename(&args);
-	}
-	return(retval);
-}
-
-static int							/* error */
-xfs_dir_lookup(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
-				   xfs_ino_t *inum)
-{
-	xfs_da_args_t args;
-	int retval;
-
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-
-	XFS_STATS_INC(xs_dir_lookup);
-	/*
-	 * Fill in the arg structure for this request.
-	 */
-	args.name = name;
-	args.namelen = namelen;
-	args.hashval = xfs_da_hashname(name, namelen);
-	args.inumber = 0;
-	args.dp = dp;
-	args.firstblock = NULL;
-	args.flist = NULL;
-	args.total = 0;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = trans;
-	args.justcheck = args.addname = 0;
-	args.oknoent = 1;
-
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
-		retval = xfs_dir_shortform_lookup(&args);
-	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
-		retval = xfs_dir_leaf_lookup(&args);
-	} else {
-		retval = xfs_dir_node_lookup(&args);
-	}
-	if (retval == EEXIST)
-		retval = 0;
-	*inum = args.inumber;
-	return(retval);
-}
-
-/*
- * Implement readdir.
- */
-static int							/* error */
-xfs_dir_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, int *eofp)
-{
-	xfs_dirent_t *dbp;
-	int  alignment, retval;
-	xfs_dir_put_t put;
-
-	XFS_STATS_INC(xs_dir_getdents);
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-
-	/*
-	 * If our caller has given us a single contiguous memory buffer,
-	 * just work directly within that buffer.  If it's in user memory,
-	 * lock it down first.
-	 */
-	alignment = sizeof(xfs_off_t) - 1;
-	if ((uio->uio_iovcnt == 1) &&
-	    (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
-	    ((uio->uio_iov[0].iov_len & alignment) == 0)) {
-		dbp = NULL;
-		put = xfs_dir_put_dirent64_direct;
-	} else {
-		dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
-		put = xfs_dir_put_dirent64_uio;
-	}
-
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
-	*eofp = 0;
-
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
-		retval = xfs_dir_shortform_getdents(dp, uio, eofp, dbp, put);
-	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
-		retval = xfs_dir_leaf_getdents(trans, dp, uio, eofp, dbp, put);
-	} else {
-		retval = xfs_dir_node_getdents(trans, dp, uio, eofp, dbp, put);
-	}
-	if (dbp != NULL)
-		kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
-
-	return(retval);
-}
-
-static int							/* error */
-xfs_dir_replace(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen,
-				    xfs_ino_t inum, xfs_fsblock_t *firstblock,
-				    xfs_bmap_free_t *flist, xfs_extlen_t total)
-{
-	xfs_da_args_t args;
-	int retval;
-
-	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-
-	if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum)))
-		return retval;
-
-	/*
-	 * Fill in the arg structure for this request.
-	 */
-	args.name = name;
-	args.namelen = namelen;
-	args.hashval = xfs_da_hashname(name, namelen);
-	args.inumber = inum;
-	args.dp = dp;
-	args.firstblock = firstblock;
-	args.flist = flist;
-	args.total = total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = trans;
-	args.justcheck = args.addname = args.oknoent = 0;
-
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
-	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) {
-		retval = xfs_dir_shortform_replace(&args);
-	} else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) {
-		retval = xfs_dir_leaf_replace(&args);
-	} else {
-		retval = xfs_dir_node_replace(&args);
-	}
-
-	return(retval);
-}
-
-static int
-xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp)
-{
-	xfs_ino_t		ino;
-	int			namelen_sum;
-	int			count;
-	xfs_dir_shortform_t	*sf;
-	xfs_dir_sf_entry_t	*sfe;
-	int			i;
-
-
-
-	if ((INT_GET(dp->di_core.di_mode, ARCH_CONVERT) & S_IFMT) != S_IFDIR) {
-		return 0;
-	}
-	if (INT_GET(dp->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_LOCAL) {
-		return 0;
-	}
-	if (INT_GET(dp->di_core.di_size, ARCH_CONVERT) < sizeof(sf->hdr)) {
-		xfs_fs_cmn_err(CE_WARN, mp, "Invalid shortform size: dp 0x%p",
-			dp);
-		return 1;
-	}
-	sf = (xfs_dir_shortform_t *)(&dp->di_u.di_dirsf);
-	ino = XFS_GET_DIR_INO8(sf->hdr.parent);
-	if (xfs_dir_ino_validate(mp, ino))
-		return 1;
-
-	count =	sf->hdr.count;
-	if ((count < 0) || ((count * 10) > XFS_LITINO(mp))) {
-		xfs_fs_cmn_err(CE_WARN, mp,
-			"Invalid shortform count: dp 0x%p", dp);
-		return(1);
-	}
-
-	if (count == 0) {
-		return 0;
-	}
-
-	namelen_sum = 0;
-	sfe = &sf->list[0];
-	for (i = sf->hdr.count - 1; i >= 0; i--) {
-		ino = XFS_GET_DIR_INO8(sfe->inumber);
-		xfs_dir_ino_validate(mp, ino);
-		if (sfe->namelen >= XFS_LITINO(mp)) {
-			xfs_fs_cmn_err(CE_WARN, mp,
-				"Invalid shortform namelen: dp 0x%p", dp);
-			return 1;
-		}
-		namelen_sum += sfe->namelen;
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-	}
-	if (namelen_sum >= XFS_LITINO(mp)) {
-		xfs_fs_cmn_err(CE_WARN, mp,
-			"Invalid shortform namelen: dp 0x%p", dp);
-		return 1;
-	}
-
-	return 0;
-}
-
-/*========================================================================
- * External routines when dirsize == XFS_LBSIZE(dp->i_mount).
- *========================================================================*/
-
-/*
- * Add a name to the leaf directory structure
- * This is the external routine.
- */
-int
-xfs_dir_leaf_addname(xfs_da_args_t *args)
-{
-	int index, retval;
-	xfs_dabuf_t *bp;
-
-	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
-					      XFS_DATA_FORK);
-	if (retval)
-		return(retval);
-	ASSERT(bp != NULL);
-
-	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
-	if (retval == ENOENT)
-		retval = xfs_dir_leaf_add(bp, args, index);
-	xfs_da_buf_done(bp);
-	return(retval);
-}
-
-/*
- * Remove a name from the leaf directory structure
- * This is the external routine.
- */
-STATIC int
-xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen)
-{
-	xfs_dir_leafblock_t *leaf;
-	int index, retval;
-	xfs_dabuf_t *bp;
-
-	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
-					      XFS_DATA_FORK);
-	if (retval)
-		return(retval);
-	ASSERT(bp != NULL);
-	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
-	if (retval == EEXIST) {
-		(void)xfs_dir_leaf_remove(args->trans, bp, index);
-		*count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
-		*totallen = INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
-		retval = 0;
-	}
-	xfs_da_buf_done(bp);
-	return(retval);
-}
-
-/*
- * Look up a name in a leaf directory structure.
- * This is the external routine.
- */
-STATIC int
-xfs_dir_leaf_lookup(xfs_da_args_t *args)
-{
-	int index, retval;
-	xfs_dabuf_t *bp;
-
-	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
-					      XFS_DATA_FORK);
-	if (retval)
-		return(retval);
-	ASSERT(bp != NULL);
-	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
-	xfs_da_brelse(args->trans, bp);
-	return(retval);
-}
-
-/*
- * Copy out directory entries for getdents(), for leaf directories.
- */
-STATIC int
-xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
-				  int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
-{
-	xfs_dabuf_t *bp;
-	int retval, eob;
-
-	retval = xfs_da_read_buf(dp->i_transp, dp, 0, -1, &bp, XFS_DATA_FORK);
-	if (retval)
-		return(retval);
-	ASSERT(bp != NULL);
-	retval = xfs_dir_leaf_getdents_int(bp, dp, 0, uio, &eob, dbp, put, -1);
-	xfs_da_brelse(trans, bp);
-	*eofp = (eob == 0);
-	return(retval);
-}
-
-/*
- * Look up a name in a leaf directory structure, replace the inode number.
- * This is the external routine.
- */
-STATIC int
-xfs_dir_leaf_replace(xfs_da_args_t *args)
-{
-	int index, retval;
-	xfs_dabuf_t *bp;
-	xfs_ino_t inum;
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_entry_t *entry;
-	xfs_dir_leaf_name_t *namest;
-
-	inum = args->inumber;
-	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp,
-					      XFS_DATA_FORK);
-	if (retval)
-		return(retval);
-	ASSERT(bp != NULL);
-	retval = xfs_dir_leaf_lookup_int(bp, args, &index);
-	if (retval == EEXIST) {
-		leaf = bp->data;
-		entry = &leaf->entries[index];
-		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
-		/* XXX - replace assert? */
-		XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
-		xfs_da_log_buf(args->trans, bp,
-		    XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
-		xfs_da_buf_done(bp);
-		retval = 0;
-	} else
-		xfs_da_brelse(args->trans, bp);
-	return(retval);
-}
-
-
-/*========================================================================
- * External routines when dirsize > XFS_LBSIZE(mp).
- *========================================================================*/
-
-/*
- * Add a name to a Btree-format directory.
- *
- * This will involve walking down the Btree, and may involve splitting
- * leaf nodes and even splitting intermediate nodes up to and including
- * the root node (a special case of an intermediate node).
- */
-STATIC int
-xfs_dir_node_addname(xfs_da_args_t *args)
-{
-	xfs_da_state_t *state;
-	xfs_da_state_blk_t *blk;
-	int retval, error;
-
-	/*
-	 * Fill in bucket of arguments/results/context to carry around.
-	 */
-	state = xfs_da_state_alloc();
-	state->args = args;
-	state->mp = args->dp->i_mount;
-	state->blocksize = state->mp->m_sb.sb_blocksize;
-	state->node_ents = state->mp->m_dir_node_ents;
-
-	/*
-	 * Search to see if name already exists, and get back a pointer
-	 * to where it should go.
-	 */
-	error = xfs_da_node_lookup_int(state, &retval);
-	if (error)
-		retval = error;
-	if (retval != ENOENT)
-		goto error;
-	blk = &state->path.blk[ state->path.active-1 ];
-	ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
-	retval = xfs_dir_leaf_add(blk->bp, args, blk->index);
-	if (retval == 0) {
-		/*
-		 * Addition succeeded, update Btree hashvals.
-		 */
-		if (!args->justcheck)
-			xfs_da_fixhashpath(state, &state->path);
-	} else {
-		/*
-		 * Addition failed, split as many Btree elements as required.
-		 */
-		if (args->total == 0) {
-			ASSERT(retval == ENOSPC);
-			goto error;
-		}
-		retval = xfs_da_split(state);
-	}
-error:
-	xfs_da_state_free(state);
-
-	return(retval);
-}
-
-/*
- * Remove a name from a B-tree directory.
- *
- * This will involve walking down the Btree, and may involve joining
- * leaf nodes and even joining intermediate nodes up to and including
- * the root node (a special case of an intermediate node).
- */
-STATIC int
-xfs_dir_node_removename(xfs_da_args_t *args)
-{
-	xfs_da_state_t *state;
-	xfs_da_state_blk_t *blk;
-	int retval, error;
-
-	state = xfs_da_state_alloc();
-	state->args = args;
-	state->mp = args->dp->i_mount;
-	state->blocksize = state->mp->m_sb.sb_blocksize;
-	state->node_ents = state->mp->m_dir_node_ents;
-
-	/*
-	 * Search to see if name exists, and get back a pointer to it.
-	 */
-	error = xfs_da_node_lookup_int(state, &retval);
-	if (error)
-		retval = error;
-	if (retval != EEXIST) {
-		xfs_da_state_free(state);
-		return(retval);
-	}
-
-	/*
-	 * Remove the name and update the hashvals in the tree.
-	 */
-	blk = &state->path.blk[ state->path.active-1 ];
-	ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
-	retval = xfs_dir_leaf_remove(args->trans, blk->bp, blk->index);
-	xfs_da_fixhashpath(state, &state->path);
-
-	/*
-	 * Check to see if the tree needs to be collapsed.
-	 */
-	error = 0;
-	if (retval) {
-		error = xfs_da_join(state);
-	}
-
-	xfs_da_state_free(state);
-	if (error)
-		return(error);
-	return(0);
-}
-
-/*
- * Look up a filename in a int directory.
- * Use an internal routine to actually do all the work.
- */
-STATIC int
-xfs_dir_node_lookup(xfs_da_args_t *args)
-{
-	xfs_da_state_t *state;
-	int retval, error, i;
-
-	state = xfs_da_state_alloc();
-	state->args = args;
-	state->mp = args->dp->i_mount;
-	state->blocksize = state->mp->m_sb.sb_blocksize;
-	state->node_ents = state->mp->m_dir_node_ents;
-
-	/*
-	 * Search to see if name exists,
-	 * and get back a pointer to it.
-	 */
-	error = xfs_da_node_lookup_int(state, &retval);
-	if (error) {
-		retval = error;
-	}
-
-	/*
-	 * If not in a transaction, we have to release all the buffers.
-	 */
-	for (i = 0; i < state->path.active; i++) {
-		xfs_da_brelse(args->trans, state->path.blk[i].bp);
-		state->path.blk[i].bp = NULL;
-	}
-
-	xfs_da_state_free(state);
-	return(retval);
-}
-
-STATIC int
-xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio,
-				  int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put)
-{
-	xfs_da_intnode_t *node;
-	xfs_da_node_entry_t *btree;
-	xfs_dir_leafblock_t *leaf = NULL;
-	xfs_dablk_t bno, nextbno;
-	xfs_dahash_t cookhash;
-	xfs_mount_t *mp;
-	int error, eob, i;
-	xfs_dabuf_t *bp;
-	xfs_daddr_t nextda;
-
-	/*
-	 * Pick up our context.
-	 */
-	mp = dp->i_mount;
-	bp = NULL;
-	bno = XFS_DA_COOKIE_BNO(mp, uio->uio_offset);
-	cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
-
-	xfs_dir_trace_g_du("node: start", dp, uio);
-
-	/*
-	 * Re-find our place, even if we're confused about what our place is.
-	 *
-	 * First we check the block number from the magic cookie, it is a
-	 * cache of where we ended last time.  If we find a leaf block, and
-	 * the starting hashval in that block is less than our desired
-	 * hashval, then we run with it.
-	 */
-	if (bno > 0) {
-		error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK);
-		if ((error != 0) && (error != EFSCORRUPTED))
-			return(error);
-		if (bp)
-			leaf = bp->data;
-		if (bp && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
-			xfs_dir_trace_g_dub("node: block not a leaf",
-						   dp, uio, bno);
-			xfs_da_brelse(trans, bp);
-			bp = NULL;
-		}
-		if (bp && INT_GET(leaf->entries[0].hashval, ARCH_CONVERT) > cookhash) {
-			xfs_dir_trace_g_dub("node: leaf hash too large",
-						   dp, uio, bno);
-			xfs_da_brelse(trans, bp);
-			bp = NULL;
-		}
-		if (bp &&
-		    cookhash > INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT)) {
-			xfs_dir_trace_g_dub("node: leaf hash too small",
-						   dp, uio, bno);
-			xfs_da_brelse(trans, bp);
-			bp = NULL;
-		}
-	}
-
-	/*
-	 * If we did not find a leaf block from the blockno in the cookie,
-	 * or we there was no blockno in the cookie (eg: first time thru),
-	 * the we start at the top of the Btree and re-find our hashval.
-	 */
-	if (bp == NULL) {
-		xfs_dir_trace_g_du("node: start at root" , dp, uio);
-		bno = 0;
-		for (;;) {
-			error = xfs_da_read_buf(trans, dp, bno, -1, &bp,
-						       XFS_DATA_FORK);
-			if (error)
-				return(error);
-			if (bp == NULL)
-				return(XFS_ERROR(EFSCORRUPTED));
-			node = bp->data;
-			if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC)
-				break;
-			btree = &node->btree[0];
-			xfs_dir_trace_g_dun("node: node detail", dp, uio, node);
-			for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) {
-				if (be32_to_cpu(btree->hashval) >= cookhash) {
-					bno = be32_to_cpu(btree->before);
-					break;
-				}
-			}
-			if (i == be16_to_cpu(node->hdr.count)) {
-				xfs_da_brelse(trans, bp);
-				xfs_dir_trace_g_du("node: hash beyond EOF",
-							  dp, uio);
-				uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0,
-							     XFS_DA_MAXHASH);
-				*eofp = 1;
-				return(0);
-			}
-			xfs_dir_trace_g_dub("node: going to block",
-						   dp, uio, bno);
-			xfs_da_brelse(trans, bp);
-		}
-	}
-	ASSERT(cookhash != XFS_DA_MAXHASH);
-
-	/*
-	 * We've dropped down to the (first) leaf block that contains the
-	 * hashval we are interested in.  Continue rolling upward thru the
-	 * leaf blocks until we fill up our buffer.
-	 */
-	for (;;) {
-		leaf = bp->data;
-		if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC)) {
-			xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf);
-			xfs_da_brelse(trans, bp);
-			XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)",
-					     XFS_ERRLEVEL_LOW, mp, leaf);
-			return XFS_ERROR(EFSCORRUPTED);
-		}
-		xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf);
-		if ((nextbno = be32_to_cpu(leaf->hdr.info.forw))) {
-			nextda = xfs_da_reada_buf(trans, dp, nextbno,
-						  XFS_DATA_FORK);
-		} else
-			nextda = -1;
-		error = xfs_dir_leaf_getdents_int(bp, dp, bno, uio, &eob, dbp,
-						  put, nextda);
-		xfs_da_brelse(trans, bp);
-		bno = nextbno;
-		if (eob) {
-			xfs_dir_trace_g_dub("node: E-O-B", dp, uio, bno);
-			*eofp = 0;
-			return(error);
-		}
-		if (bno == 0)
-			break;
-		error = xfs_da_read_buf(trans, dp, bno, nextda, &bp,
-					XFS_DATA_FORK);
-		if (error)
-			return(error);
-		if (unlikely(bp == NULL)) {
-			XFS_ERROR_REPORT("xfs_dir_node_getdents(2)",
-					 XFS_ERRLEVEL_LOW, mp);
-			return(XFS_ERROR(EFSCORRUPTED));
-		}
-	}
-	*eofp = 1;
-	xfs_dir_trace_g_du("node: E-O-F", dp, uio);
-	return(0);
-}
-
-/*
- * Look up a filename in an int directory, replace the inode number.
- * Use an internal routine to actually do the lookup.
- */
-STATIC int
-xfs_dir_node_replace(xfs_da_args_t *args)
-{
-	xfs_da_state_t *state;
-	xfs_da_state_blk_t *blk;
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_entry_t *entry;
-	xfs_dir_leaf_name_t *namest;
-	xfs_ino_t inum;
-	int retval, error, i;
-	xfs_dabuf_t *bp;
-
-	state = xfs_da_state_alloc();
-	state->args = args;
-	state->mp = args->dp->i_mount;
-	state->blocksize = state->mp->m_sb.sb_blocksize;
-	state->node_ents = state->mp->m_dir_node_ents;
-	inum = args->inumber;
-
-	/*
-	 * Search to see if name exists,
-	 * and get back a pointer to it.
-	 */
-	error = xfs_da_node_lookup_int(state, &retval);
-	if (error) {
-		retval = error;
-	}
-
-	if (retval == EEXIST) {
-		blk = &state->path.blk[state->path.active - 1];
-		ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC);
-		bp = blk->bp;
-		leaf = bp->data;
-		entry = &leaf->entries[blk->index];
-		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
-		/* XXX - replace assert ? */
-		XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber);
-		xfs_da_log_buf(args->trans, bp,
-		    XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber)));
-		xfs_da_buf_done(bp);
-		blk->bp = NULL;
-		retval = 0;
-	} else {
-		i = state->path.active - 1;
-		xfs_da_brelse(args->trans, state->path.blk[i].bp);
-		state->path.blk[i].bp = NULL;
-	}
-	for (i = 0; i < state->path.active - 1; i++) {
-		xfs_da_brelse(args->trans, state->path.blk[i].bp);
-		state->path.blk[i].bp = NULL;
-	}
-
-	xfs_da_state_free(state);
-	return(retval);
-}
-
-#if defined(XFS_DIR_TRACE)
-/*
- * Add a trace buffer entry for an inode and a uio.
- */
-void
-xfs_dir_trace_g_du(char *where, xfs_inode_t *dp, uio_t *uio)
-{
-	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DU, where,
-		     (void *)dp, (void *)dp->i_mount,
-		     (void *)((unsigned long)(uio->uio_offset >> 32)),
-		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
-		     (void *)(unsigned long)uio->uio_resid,
-		     NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-}
-
-/*
- * Add a trace buffer entry for an inode and a uio.
- */
-void
-xfs_dir_trace_g_dub(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dablk_t bno)
-{
-	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUB, where,
-		     (void *)dp, (void *)dp->i_mount,
-		     (void *)((unsigned long)(uio->uio_offset >> 32)),
-		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
-		     (void *)(unsigned long)uio->uio_resid,
-		     (void *)(unsigned long)bno,
-		     NULL, NULL, NULL, NULL, NULL, NULL);
-}
-
-/*
- * Add a trace buffer entry for an inode and a uio.
- */
-void
-xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio,
-			xfs_da_intnode_t *node)
-{
-	int	last = be16_to_cpu(node->hdr.count) - 1;
-
-	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where,
-		     (void *)dp, (void *)dp->i_mount,
-		     (void *)((unsigned long)(uio->uio_offset >> 32)),
-		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
-		     (void *)(unsigned long)uio->uio_resid,
-		     (void *)(unsigned long)be32_to_cpu(node->hdr.info.forw),
-		     (void *)(unsigned long)
-			be16_to_cpu(node->hdr.count),
-		     (void *)(unsigned long)
-			be32_to_cpu(node->btree[0].hashval),
-		     (void *)(unsigned long)
-			be32_to_cpu(node->btree[last].hashval),
-		     NULL, NULL, NULL);
-}
-
-/*
- * Add a trace buffer entry for an inode and a uio.
- */
-void
-xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio,
-			xfs_dir_leafblock_t *leaf)
-{
-	int	last = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1;
-
-	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where,
-		     (void *)dp, (void *)dp->i_mount,
-		     (void *)((unsigned long)(uio->uio_offset >> 32)),
-		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
-		     (void *)(unsigned long)uio->uio_resid,
-		     (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw),
-		     (void *)(unsigned long)
-			INT_GET(leaf->hdr.count, ARCH_CONVERT),
-		     (void *)(unsigned long)
-			INT_GET(leaf->entries[0].hashval, ARCH_CONVERT),
-		     (void *)(unsigned long)
-			INT_GET(leaf->entries[last].hashval, ARCH_CONVERT),
-		     NULL, NULL, NULL);
-}
-
-/*
- * Add a trace buffer entry for an inode and a uio.
- */
-void
-xfs_dir_trace_g_due(char *where, xfs_inode_t *dp, uio_t *uio,
-			xfs_dir_leaf_entry_t *entry)
-{
-	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUE, where,
-		     (void *)dp, (void *)dp->i_mount,
-		     (void *)((unsigned long)(uio->uio_offset >> 32)),
-		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
-		     (void *)(unsigned long)uio->uio_resid,
-		     (void *)(unsigned long)
-			INT_GET(entry->hashval, ARCH_CONVERT),
-		     NULL, NULL, NULL, NULL, NULL, NULL);
-}
-
-/*
- * Add a trace buffer entry for an inode and a uio.
- */
-void
-xfs_dir_trace_g_duc(char *where, xfs_inode_t *dp, uio_t *uio, xfs_off_t cookie)
-{
-	xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUC, where,
-		     (void *)dp, (void *)dp->i_mount,
-		     (void *)((unsigned long)(uio->uio_offset >> 32)),
-		     (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)),
-		     (void *)(unsigned long)uio->uio_resid,
-		     (void *)((unsigned long)(cookie >> 32)),
-		     (void *)((unsigned long)(cookie & 0xFFFFFFFF)),
-		     NULL, NULL, NULL, NULL, NULL);
-}
-
-/*
- * Add a trace buffer entry for the arguments given to the routine,
- * generic form.
- */
-void
-xfs_dir_trace_enter(int type, char *where,
-			void * a0, void * a1,
-			void * a2, void * a3,
-			void * a4, void * a5,
-			void * a6, void * a7,
-			void * a8, void * a9,
-			void * a10, void * a11)
-{
-	ASSERT(xfs_dir_trace_buf);
-	ktrace_enter(xfs_dir_trace_buf, (void *)(unsigned long)type,
-					(void *)where,
-					(void *)a0, (void *)a1, (void *)a2,
-					(void *)a3, (void *)a4, (void *)a5,
-					(void *)a6, (void *)a7, (void *)a8,
-					(void *)a9, (void *)a10, (void *)a11,
-					NULL, NULL);
-}
-#endif	/* XFS_DIR_TRACE */
diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h
deleted file mode 100644
index 8cc8afb..0000000
--- a/fs/xfs/xfs_dir.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (c) 2000,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR_H__
-#define	__XFS_DIR_H__
-
-/*
- * Large directories are structured around Btrees where all the data
- * elements are in the leaf nodes.  Filenames are hashed into an int,
- * then that int is used as the index into the Btree.  Since the hashval
- * of a filename may not be unique, we may have duplicate keys.  The
- * internal links in the Btree are logical block offsets into the file.
- *
- * Small directories use a different format and are packed as tightly
- * as possible so as to fit into the literal area of the inode.
- */
-
-/*========================================================================
- * Function prototypes for the kernel.
- *========================================================================*/
-
-struct uio;
-struct xfs_bmap_free;
-struct xfs_da_args;
-struct xfs_dinode;
-struct xfs_inode;
-struct xfs_mount;
-struct xfs_trans;
-
-/*
- * Directory function types.
- * Put in structures (xfs_dirops_t) for v1 and v2 directories.
- */
-typedef void	(*xfs_dir_mount_t)(struct xfs_mount *mp);
-typedef int	(*xfs_dir_isempty_t)(struct xfs_inode *dp);
-typedef int	(*xfs_dir_init_t)(struct xfs_trans *tp,
-				  struct xfs_inode *dp,
-				  struct xfs_inode *pdp);
-typedef int	(*xfs_dir_createname_t)(struct xfs_trans *tp,
-					struct xfs_inode *dp,
-					char *name,
-					int namelen,
-					xfs_ino_t inum,
-					xfs_fsblock_t *first,
-					struct xfs_bmap_free *flist,
-					xfs_extlen_t total);
-typedef int	(*xfs_dir_lookup_t)(struct xfs_trans *tp,
-				    struct xfs_inode *dp,
-				    char *name,
-				    int namelen,
-				    xfs_ino_t *inum);
-typedef int	(*xfs_dir_removename_t)(struct xfs_trans *tp,
-					struct xfs_inode *dp,
-					char *name,
-					int namelen,
-					xfs_ino_t ino,
-					xfs_fsblock_t *first,
-					struct xfs_bmap_free *flist,
-					xfs_extlen_t total);
-typedef int	(*xfs_dir_getdents_t)(struct xfs_trans *tp,
-				      struct xfs_inode *dp,
-				      struct uio *uio,
-				      int *eofp);
-typedef int	(*xfs_dir_replace_t)(struct xfs_trans *tp,
-				     struct xfs_inode *dp,
-				     char *name,
-				     int namelen,
-				     xfs_ino_t inum,
-				     xfs_fsblock_t *first,
-				     struct xfs_bmap_free *flist,
-				     xfs_extlen_t total);
-typedef int	(*xfs_dir_canenter_t)(struct xfs_trans *tp,
-				      struct xfs_inode *dp,
-				      char *name,
-				      int namelen);
-typedef int	(*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp,
-						       struct xfs_dinode *dip);
-typedef int	(*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args);
-
-typedef struct xfs_dirops {
-	xfs_dir_mount_t				xd_mount;
-	xfs_dir_isempty_t			xd_isempty;
-	xfs_dir_init_t				xd_init;
-	xfs_dir_createname_t			xd_createname;
-	xfs_dir_lookup_t			xd_lookup;
-	xfs_dir_removename_t			xd_removename;
-	xfs_dir_getdents_t			xd_getdents;
-	xfs_dir_replace_t			xd_replace;
-	xfs_dir_canenter_t			xd_canenter;
-	xfs_dir_shortform_validate_ondisk_t	xd_shortform_validate_ondisk;
-	xfs_dir_shortform_to_single_t		xd_shortform_to_single;
-} xfs_dirops_t;
-
-/*
- * Overall external interface routines.
- */
-void	xfs_dir_startup(void);	/* called exactly once */
-
-#define	XFS_DIR_MOUNT(mp)	\
-	((mp)->m_dirops.xd_mount(mp))
-#define	XFS_DIR_ISEMPTY(mp,dp)	\
-	((mp)->m_dirops.xd_isempty(dp))
-#define	XFS_DIR_INIT(mp,tp,dp,pdp)	\
-	((mp)->m_dirops.xd_init(tp,dp,pdp))
-#define	XFS_DIR_CREATENAME(mp,tp,dp,name,namelen,inum,first,flist,total) \
-	((mp)->m_dirops.xd_createname(tp,dp,name,namelen,inum,first,flist,\
-				      total))
-#define	XFS_DIR_LOOKUP(mp,tp,dp,name,namelen,inum)	\
-	((mp)->m_dirops.xd_lookup(tp,dp,name,namelen,inum))
-#define	XFS_DIR_REMOVENAME(mp,tp,dp,name,namelen,ino,first,flist,total)	\
-	((mp)->m_dirops.xd_removename(tp,dp,name,namelen,ino,first,flist,total))
-#define	XFS_DIR_GETDENTS(mp,tp,dp,uio,eofp)	\
-	((mp)->m_dirops.xd_getdents(tp,dp,uio,eofp))
-#define	XFS_DIR_REPLACE(mp,tp,dp,name,namelen,inum,first,flist,total)	\
-	((mp)->m_dirops.xd_replace(tp,dp,name,namelen,inum,first,flist,total))
-#define	XFS_DIR_CANENTER(mp,tp,dp,name,namelen)	\
-	((mp)->m_dirops.xd_canenter(tp,dp,name,namelen))
-#define	XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp,dip)	\
-	((mp)->m_dirops.xd_shortform_validate_ondisk(mp,dip))
-#define	XFS_DIR_SHORTFORM_TO_SINGLE(mp,args)	\
-	((mp)->m_dirops.xd_shortform_to_single(args))
-
-#define	XFS_DIR_IS_V1(mp)	((mp)->m_dirversion == 1)
-#define	XFS_DIR_IS_V2(mp)	((mp)->m_dirversion == 2)
-extern xfs_dirops_t xfsv1_dirops;
-extern xfs_dirops_t xfsv2_dirops;
-
-#endif	/* __XFS_DIR_H__ */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 022c839..8edbe1a 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -24,21 +24,18 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
 #include "xfs_bmap.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_dir2_data.h"
 #include "xfs_dir2_leaf.h"
 #include "xfs_dir2_block.h"
@@ -46,69 +43,14 @@
 #include "xfs_dir2_trace.h"
 #include "xfs_error.h"
 
-/*
- * Declarations for interface routines.
- */
-static void	xfs_dir2_mount(xfs_mount_t *mp);
-static int	xfs_dir2_isempty(xfs_inode_t *dp);
-static int	xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp,
-			      xfs_inode_t *pdp);
-static int	xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp,
-				    char *name, int namelen, xfs_ino_t inum,
-				    xfs_fsblock_t *first,
-				    xfs_bmap_free_t *flist, xfs_extlen_t total);
-static int	xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
-				int namelen, xfs_ino_t *inum);
-static int	xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp,
-				    char *name, int namelen, xfs_ino_t ino,
-				    xfs_fsblock_t *first,
-				    xfs_bmap_free_t *flist, xfs_extlen_t total);
-static int	xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio,
-				  int *eofp);
-static int	xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
-				 int namelen, xfs_ino_t inum,
-				 xfs_fsblock_t *first, xfs_bmap_free_t *flist,
-				 xfs_extlen_t total);
-static int	xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
-				  int namelen);
-static int	xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp,
-						   xfs_dinode_t *dip);
-
-/*
- * Utility routine declarations.
- */
 static int	xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
 static int	xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
 
-/*
- * Directory operations vector.
- */
-xfs_dirops_t	xfsv2_dirops = {
-	.xd_mount			= xfs_dir2_mount,
-	.xd_isempty			= xfs_dir2_isempty,
-	.xd_init			= xfs_dir2_init,
-	.xd_createname			= xfs_dir2_createname,
-	.xd_lookup			= xfs_dir2_lookup,
-	.xd_removename			= xfs_dir2_removename,
-	.xd_getdents			= xfs_dir2_getdents,
-	.xd_replace			= xfs_dir2_replace,
-	.xd_canenter			= xfs_dir2_canenter,
-	.xd_shortform_validate_ondisk	= xfs_dir2_shortform_validate_ondisk,
-	.xd_shortform_to_single		= xfs_dir2_sf_to_block,
-};
-
-/*
- * Interface routines.
- */
-
-/*
- * Initialize directory-related fields in the mount structure.
- */
-static void
-xfs_dir2_mount(
-	xfs_mount_t	*mp)		/* filesystem mount point */
+void
+xfs_dir_mount(
+	xfs_mount_t	*mp)
 {
-	mp->m_dirversion = 2;
+	ASSERT(XFS_SB_VERSION_HASDIRV2(&mp->m_sb));
 	ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
 	       XFS_MAX_BLOCKSIZE);
 	mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
@@ -128,19 +70,15 @@
 /*
  * Return 1 if directory contains only "." and "..".
  */
-static int				/* return code */
-xfs_dir2_isempty(
-	xfs_inode_t	*dp)		/* incore inode structure */
+int
+xfs_dir_isempty(
+	xfs_inode_t	*dp)
 {
-	xfs_dir2_sf_t	*sfp;		/* shortform directory structure */
+	xfs_dir2_sf_t	*sfp;
 
 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-	/*
-	 * Might happen during shutdown.
-	 */
-	if (dp->i_d.di_size == 0) {
+	if (dp->i_d.di_size == 0)	/* might happen during shutdown. */
 		return 1;
-	}
 	if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
 		return 0;
 	sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
@@ -148,53 +86,83 @@
 }
 
 /*
+ * Validate a given inode number.
+ */
+int
+xfs_dir_ino_validate(
+	xfs_mount_t	*mp,
+	xfs_ino_t	ino)
+{
+	xfs_agblock_t	agblkno;
+	xfs_agino_t	agino;
+	xfs_agnumber_t	agno;
+	int		ino_ok;
+	int		ioff;
+
+	agno = XFS_INO_TO_AGNO(mp, ino);
+	agblkno = XFS_INO_TO_AGBNO(mp, ino);
+	ioff = XFS_INO_TO_OFFSET(mp, ino);
+	agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
+	ino_ok =
+		agno < mp->m_sb.sb_agcount &&
+		agblkno < mp->m_sb.sb_agblocks &&
+		agblkno != 0 &&
+		ioff < (1 << mp->m_sb.sb_inopblog) &&
+		XFS_AGINO_TO_INO(mp, agno, agino) == ino;
+	if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
+			XFS_RANDOM_DIR_INO_VALIDATE))) {
+		xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
+				(unsigned long long) ino);
+		XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
+		return XFS_ERROR(EFSCORRUPTED);
+	}
+	return 0;
+}
+
+/*
  * Initialize a directory with its "." and ".." entries.
  */
-static int				/* error */
-xfs_dir2_init(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
-	xfs_inode_t	*pdp)		/* incore parent directory inode */
+int
+xfs_dir_init(
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
+	xfs_inode_t	*pdp)
 {
-	xfs_da_args_t	args;		/* operation arguments */
-	int		error;		/* error return value */
+	xfs_da_args_t	args;
+	int		error;
 
 	memset((char *)&args, 0, sizeof(args));
 	args.dp = dp;
 	args.trans = tp;
 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-	if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) {
+	if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
 		return error;
-	}
 	return xfs_dir2_sf_create(&args, pdp->i_ino);
 }
 
 /*
   Enter a name in a directory.
  */
-static int					/* error */
-xfs_dir2_createname(
-	xfs_trans_t		*tp,		/* transaction pointer */
-	xfs_inode_t		*dp,		/* incore directory inode */
-	char			*name,		/* new entry name */
-	int			namelen,	/* new entry name length */
+int
+xfs_dir_createname(
+	xfs_trans_t		*tp,
+	xfs_inode_t		*dp,
+	char			*name,
+	int			namelen,
 	xfs_ino_t		inum,		/* new entry inode number */
 	xfs_fsblock_t		*first,		/* bmap's firstblock */
 	xfs_bmap_free_t		*flist,		/* bmap's freeblock list */
 	xfs_extlen_t		total)		/* bmap's total block count */
 {
-	xfs_da_args_t		args;		/* operation arguments */
-	int			rval;		/* return value */
+	xfs_da_args_t		args;
+	int			rval;
 	int			v;		/* type-checking value */
 
 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
+	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
 		return rval;
-	}
 	XFS_STATS_INC(xs_dir_create);
-	/*
-	 * Fill in the arg structure for this request.
-	 */
+
 	args.name = name;
 	args.namelen = namelen;
 	args.hashval = xfs_da_hashname(name, namelen);
@@ -207,18 +175,16 @@
 	args.trans = tp;
 	args.justcheck = 0;
 	args.addname = args.oknoent = 1;
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
+
 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
 		rval = xfs_dir2_sf_addname(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_block_addname(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_leaf_addname(&args);
 	else
 		rval = xfs_dir2_node_addname(&args);
@@ -228,24 +194,21 @@
 /*
  * Lookup a name in a directory, give back the inode number.
  */
-static int				/* error */
-xfs_dir2_lookup(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
-	char		*name,		/* lookup name */
-	int		namelen,	/* lookup name length */
+int
+xfs_dir_lookup(
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
+	char		*name,
+	int		namelen,
 	xfs_ino_t	*inum)		/* out: inode number */
 {
-	xfs_da_args_t	args;		/* operation arguments */
-	int		rval;		/* return value */
+	xfs_da_args_t	args;
+	int		rval;
 	int		v;		/* type-checking value */
 
 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
 	XFS_STATS_INC(xs_dir_lookup);
 
-	/*
-	 * Fill in the arg structure for this request.
-	 */
 	args.name = name;
 	args.namelen = namelen;
 	args.hashval = xfs_da_hashname(name, namelen);
@@ -258,18 +221,16 @@
 	args.trans = tp;
 	args.justcheck = args.addname = 0;
 	args.oknoent = 1;
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
+
 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
 		rval = xfs_dir2_sf_lookup(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_block_lookup(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_leaf_lookup(&args);
 	else
 		rval = xfs_dir2_node_lookup(&args);
@@ -283,26 +244,24 @@
 /*
  * Remove an entry from a directory.
  */
-static int				/* error */
-xfs_dir2_removename(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
-	char		*name,		/* name of entry to remove */
-	int		namelen,	/* name length of entry to remove */
-	xfs_ino_t	ino,		/* inode number of entry to remove */
+int
+xfs_dir_removename(
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
+	char		*name,
+	int		namelen,
+	xfs_ino_t	ino,
 	xfs_fsblock_t	*first,		/* bmap's firstblock */
 	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
 	xfs_extlen_t	total)		/* bmap's total block count */
 {
-	xfs_da_args_t	args;		/* operation arguments */
-	int		rval;		/* return value */
+	xfs_da_args_t	args;
+	int		rval;
 	int		v;		/* type-checking value */
 
 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
 	XFS_STATS_INC(xs_dir_remove);
-	/*
-	 * Fill in the arg structure for this request.
-	 */
+
 	args.name = name;
 	args.namelen = namelen;
 	args.hashval = xfs_da_hashname(name, namelen);
@@ -314,18 +273,16 @@
 	args.whichfork = XFS_DATA_FORK;
 	args.trans = tp;
 	args.justcheck = args.addname = args.oknoent = 0;
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
+
 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
 		rval = xfs_dir2_sf_removename(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_block_removename(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_leaf_removename(&args);
 	else
 		rval = xfs_dir2_node_removename(&args);
@@ -335,10 +292,10 @@
 /*
  * Read a directory.
  */
-static int				/* error */
-xfs_dir2_getdents(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
+int
+xfs_dir_getdents(
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
 	uio_t		*uio,		/* caller's buffer control */
 	int		*eofp)		/* out: eof reached */
 {
@@ -367,14 +324,11 @@
 	}
 
 	*eofp = 0;
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
 		rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
 		;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
 	else
 		rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
@@ -386,29 +340,26 @@
 /*
  * Replace the inode number of a directory entry.
  */
-static int				/* error */
-xfs_dir2_replace(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
+int
+xfs_dir_replace(
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
 	char		*name,		/* name of entry to replace */
-	int		namelen,	/* name length of entry to replace */
+	int		namelen,
 	xfs_ino_t	inum,		/* new inode number */
 	xfs_fsblock_t	*first,		/* bmap's firstblock */
 	xfs_bmap_free_t	*flist,		/* bmap's freeblock list */
 	xfs_extlen_t	total)		/* bmap's total block count */
 {
-	xfs_da_args_t	args;		/* operation arguments */
-	int		rval;		/* return value */
+	xfs_da_args_t	args;
+	int		rval;
 	int		v;		/* type-checking value */
 
 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
 
-	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) {
+	if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
 		return rval;
-	}
-	/*
-	 * Fill in the arg structure for this request.
-	 */
+
 	args.name = name;
 	args.namelen = namelen;
 	args.hashval = xfs_da_hashname(name, namelen);
@@ -420,18 +371,16 @@
 	args.whichfork = XFS_DATA_FORK;
 	args.trans = tp;
 	args.justcheck = args.addname = args.oknoent = 0;
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
+
 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
 		rval = xfs_dir2_sf_replace(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_block_replace(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_leaf_replace(&args);
 	else
 		rval = xfs_dir2_node_replace(&args);
@@ -441,21 +390,19 @@
 /*
  * See if this entry can be added to the directory without allocating space.
  */
-static int				/* error */
-xfs_dir2_canenter(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
+int
+xfs_dir_canenter(
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
 	char		*name,		/* name of entry to add */
-	int		namelen)	/* name length of entry to add */
+	int		namelen)
 {
-	xfs_da_args_t	args;		/* operation arguments */
-	int		rval;		/* return value */
+	xfs_da_args_t	args;
+	int		rval;
 	int		v;		/* type-checking value */
 
 	ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
-	/*
-	 * Fill in the arg structure for this request.
-	 */
+
 	args.name = name;
 	args.namelen = namelen;
 	args.hashval = xfs_da_hashname(name, namelen);
@@ -467,18 +414,16 @@
 	args.whichfork = XFS_DATA_FORK;
 	args.trans = tp;
 	args.justcheck = args.addname = args.oknoent = 1;
-	/*
-	 * Decide on what work routines to call based on the inode size.
-	 */
+
 	if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
 		rval = xfs_dir2_sf_addname(&args);
-	else if ((rval = xfs_dir2_isblock(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_block_addname(&args);
-	else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) {
+	else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
 		return rval;
-	} else if (v)
+	else if (v)
 		rval = xfs_dir2_leaf_addname(&args);
 	else
 		rval = xfs_dir2_node_addname(&args);
@@ -486,19 +431,6 @@
 }
 
 /*
- * Dummy routine for shortform inode validation.
- * Can't really do this.
- */
-/* ARGSUSED */
-static int				/* error */
-xfs_dir2_shortform_validate_ondisk(
-	xfs_mount_t	*mp,		/* filesystem mount point */
-	xfs_dinode_t	*dip)		/* ondisk inode */
-{
-	return 0;
-}
-
-/*
  * Utility routines.
  */
 
@@ -507,24 +439,24 @@
  * This routine is for data and free blocks, not leaf/node blocks
  * which are handled by xfs_da_grow_inode.
  */
-int					/* error */
+int
 xfs_dir2_grow_inode(
-	xfs_da_args_t	*args,		/* operation arguments */
+	xfs_da_args_t	*args,
 	int		space,		/* v2 dir's space XFS_DIR2_xxx_SPACE */
 	xfs_dir2_db_t	*dbp)		/* out: block number added */
 {
 	xfs_fileoff_t	bno;		/* directory offset of new block */
 	int		count;		/* count of filesystem blocks */
 	xfs_inode_t	*dp;		/* incore directory inode */
-	int		error;		/* error return value */
+	int		error;
 	int		got;		/* blocks actually mapped */
-	int		i;		/* temp mapping index */
+	int		i;
 	xfs_bmbt_irec_t	map;		/* single structure for bmap */
 	int		mapi;		/* mapping index */
 	xfs_bmbt_irec_t	*mapp;		/* bmap mapping structure(s) */
-	xfs_mount_t	*mp;		/* filesystem mount point */
+	xfs_mount_t	*mp;
 	int		nmap;		/* number of bmap entries */
-	xfs_trans_t	*tp;		/* transaction pointer */
+	xfs_trans_t	*tp;
 
 	xfs_dir2_trace_args_s("grow_inode", args, space);
 	dp = args->dp;
@@ -538,9 +470,8 @@
 	/*
 	 * Find the first hole for our block.
 	 */
-	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) {
+	if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
 		return error;
-	}
 	nmap = 1;
 	ASSERT(args->firstblock != NULL);
 	/*
@@ -549,13 +480,9 @@
 	if ((error = xfs_bmapi(tp, dp, bno, count,
 			XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
 			args->firstblock, args->total, &map, &nmap,
-			args->flist))) {
+			args->flist, NULL)))
 		return error;
-	}
 	ASSERT(nmap <= 1);
-	/*
-	 * Got it in 1.
-	 */
 	if (nmap == 1) {
 		mapp = &map;
 		mapi = 1;
@@ -585,7 +512,8 @@
 			if ((error = xfs_bmapi(tp, dp, b, c,
 					XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
 					args->firstblock, args->total,
-					&mapp[mapi], &nmap, args->flist))) {
+					&mapp[mapi], &nmap, args->flist,
+					NULL))) {
 				kmem_free(mapp, sizeof(*mapp) * count);
 				return error;
 			}
@@ -645,20 +573,19 @@
 /*
  * See if the directory is a single-block form directory.
  */
-int					/* error */
+int
 xfs_dir2_isblock(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
 	int		*vp)		/* out: 1 is block, 0 is not block */
 {
 	xfs_fileoff_t	last;		/* last file offset */
-	xfs_mount_t	*mp;		/* filesystem mount point */
-	int		rval;		/* return value */
+	xfs_mount_t	*mp;
+	int		rval;
 
 	mp = dp->i_mount;
-	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
+	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
 		return rval;
-	}
 	rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
 	ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
 	*vp = rval;
@@ -668,20 +595,19 @@
 /*
  * See if the directory is a single-leaf form directory.
  */
-int					/* error */
+int
 xfs_dir2_isleaf(
-	xfs_trans_t	*tp,		/* transaction pointer */
-	xfs_inode_t	*dp,		/* incore directory inode */
+	xfs_trans_t	*tp,
+	xfs_inode_t	*dp,
 	int		*vp)		/* out: 1 is leaf, 0 is not leaf */
 {
 	xfs_fileoff_t	last;		/* last file offset */
-	xfs_mount_t	*mp;		/* filesystem mount point */
-	int		rval;		/* return value */
+	xfs_mount_t	*mp;
+	int		rval;
 
 	mp = dp->i_mount;
-	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) {
+	if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
 		return rval;
-	}
 	*vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
 	return 0;
 }
@@ -689,9 +615,9 @@
 /*
  * Getdents put routine for 64-bit ABI, direct form.
  */
-static int					/* error */
+static int
 xfs_dir2_put_dirent64_direct(
-	xfs_dir2_put_args_t	*pa)		/* argument bundle */
+	xfs_dir2_put_args_t	*pa)
 {
 	xfs_dirent_t		*idbp;		/* dirent pointer */
 	iovec_t			*iovp;		/* io vector */
@@ -726,9 +652,9 @@
 /*
  * Getdents put routine for 64-bit ABI, uio form.
  */
-static int					/* error */
+static int
 xfs_dir2_put_dirent64_uio(
-	xfs_dir2_put_args_t	*pa)		/* argument bundle */
+	xfs_dir2_put_args_t	*pa)
 {
 	xfs_dirent_t		*idbp;		/* dirent pointer */
 	int			namelen;	/* entry name length */
@@ -764,17 +690,17 @@
  */
 int
 xfs_dir2_shrink_inode(
-	xfs_da_args_t	*args,		/* operation arguments */
-	xfs_dir2_db_t	db,		/* directory block number */
-	xfs_dabuf_t	*bp)		/* block's buffer */
+	xfs_da_args_t	*args,
+	xfs_dir2_db_t	db,
+	xfs_dabuf_t	*bp)
 {
 	xfs_fileoff_t	bno;		/* directory file offset */
 	xfs_dablk_t	da;		/* directory file offset */
 	int		done;		/* bunmap is finished */
-	xfs_inode_t	*dp;		/* incore directory inode */
-	int		error;		/* error return value */
-	xfs_mount_t	*mp;		/* filesystem mount point */
-	xfs_trans_t	*tp;		/* transaction pointer */
+	xfs_inode_t	*dp;
+	int		error;
+	xfs_mount_t	*mp;
+	xfs_trans_t	*tp;
 
 	xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
 	dp = args->dp;
@@ -786,7 +712,7 @@
 	 */
 	if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
 			XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
-			&done))) {
+			NULL, &done))) {
 		/*
 		 * ENOSPC actually can happen if we're in a removename with
 		 * no space reservation, and the resulting block removal
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 7dd364b..86560b6 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -22,7 +22,9 @@
 struct xfs_dabuf;
 struct xfs_da_args;
 struct xfs_dir2_put_args;
+struct xfs_bmap_free;
 struct xfs_inode;
+struct xfs_mount;
 struct xfs_trans;
 
 /*
@@ -73,7 +75,35 @@
 } xfs_dir2_put_args_t;
 
 /*
- * Other interfaces used by the rest of the dir v2 code.
+ * Generic directory interface routines
+ */
+extern void xfs_dir_startup(void);
+extern void xfs_dir_mount(struct xfs_mount *mp);
+extern int xfs_dir_isempty(struct xfs_inode *dp);
+extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp,
+				struct xfs_inode *pdp);
+extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp,
+				char *name, int namelen, xfs_ino_t inum,
+				xfs_fsblock_t *first,
+				struct xfs_bmap_free *flist, xfs_extlen_t tot);
+extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp,
+				char *name, int namelen, xfs_ino_t *inum);
+extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
+				char *name, int namelen, xfs_ino_t ino,
+				xfs_fsblock_t *first,
+				struct xfs_bmap_free *flist, xfs_extlen_t tot);
+extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
+				uio_t *uio, int *eofp);
+extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
+				char *name, int namelen, xfs_ino_t inum,
+				xfs_fsblock_t *first,
+				struct xfs_bmap_free *flist, xfs_extlen_t tot);
+extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
+				char *name, int namelen);
+extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
+
+/*
+ * Utility routines for v2 directories.
  */
 extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
 				xfs_dir2_db_t *dbp);
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 972ded5..9d7438b 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -22,19 +22,16 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_dir2_data.h"
 #include "xfs_dir2_leaf.h"
 #include "xfs_dir2_block.h"
@@ -51,6 +48,18 @@
 				     int *entno);
 static int xfs_dir2_block_sort(const void *a, const void *b);
 
+static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
+
+/*
+ * One-time startup routine called from xfs_init().
+ */
+void
+xfs_dir_startup(void)
+{
+	xfs_dir_hash_dot = xfs_da_hashname(".", 1);
+	xfs_dir_hash_dotdot = xfs_da_hashname("..", 2);
+}
+
 /*
  * Add an entry to a block directory.
  */
@@ -400,7 +409,7 @@
 	/*
 	 * Create the new data entry.
 	 */
-	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
+	dep->inumber = cpu_to_be64(args->inumber);
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, args->namelen);
 	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -508,7 +517,7 @@
 
 		p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk,
 						    ptr - (char *)block);
-		p.ino = INT_GET(dep->inumber, ARCH_CONVERT);
+		p.ino = be64_to_cpu(dep->inumber);
 #if XFS_BIG_INUMS
 		p.ino += mp->m_inoadd;
 #endif
@@ -626,7 +635,7 @@
 	/*
 	 * Fill in inode number, release the block.
 	 */
-	args->inumber = INT_GET(dep->inumber, ARCH_CONVERT);
+	args->inumber = be64_to_cpu(dep->inumber);
 	xfs_da_brelse(args->trans, bp);
 	return XFS_ERROR(EEXIST);
 }
@@ -844,11 +853,11 @@
 	 */
 	dep = (xfs_dir2_data_entry_t *)
 	      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address)));
-	ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) != args->inumber);
+	ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
 	/*
 	 * Change the inode number to the new value.
 	 */
-	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
+	dep->inumber = cpu_to_be64(args->inumber);
 	xfs_dir2_data_log_entry(args->trans, bp, dep);
 	xfs_dir2_data_check(dp, bp);
 	xfs_da_buf_done(bp);
@@ -1130,7 +1139,7 @@
 	 */
 	dep = (xfs_dir2_data_entry_t *)
 	      ((char *)block + XFS_DIR2_DATA_DOT_OFFSET);
-	INT_SET(dep->inumber, ARCH_CONVERT, dp->i_ino);
+	dep->inumber = cpu_to_be64(dp->i_ino);
 	dep->namelen = 1;
 	dep->name[0] = '.';
 	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -1144,7 +1153,7 @@
 	 */
 	dep = (xfs_dir2_data_entry_t *)
 		((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET);
-	INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
+	dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
 	dep->namelen = 2;
 	dep->name[0] = dep->name[1] = '.';
 	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -1193,7 +1202,7 @@
 		 * Copy a real entry.
 		 */
 		dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset);
-		INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp,
+		dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp,
 				XFS_DIR2_SF_INUMBERP(sfep)));
 		dep->namelen = sfep->namelen;
 		memcpy(dep->name, sfep->name, dep->namelen);
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index bb3d03f..f7c7992 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -22,18 +22,15 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_dir2_data.h"
 #include "xfs_dir2_leaf.h"
 #include "xfs_dir2_block.h"
@@ -133,7 +130,7 @@
 		 */
 		dep = (xfs_dir2_data_entry_t *)p;
 		ASSERT(dep->namelen != 0);
-		ASSERT(xfs_dir_ino_validate(mp, INT_GET(dep->inumber, ARCH_CONVERT)) == 0);
+		ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0);
 		ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) ==
 		       (char *)dep - (char *)d);
 		count++;
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index 0847cbb..a6ae2d2 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -85,11 +85,11 @@
  * Tag appears as the last 2 bytes.
  */
 typedef struct xfs_dir2_data_entry {
-	xfs_ino_t		inumber;	/* inode number */
-	__uint8_t		namelen;	/* name length */
-	__uint8_t		name[1];	/* name bytes, no null */
+	__be64			inumber;	/* inode number */
+	__u8			namelen;	/* name length */
+	__u8			name[1];	/* name bytes, no null */
 						/* variable offset */
-	xfs_dir2_data_off_t	tag;		/* starting offset of us */
+	__be16			tag;		/* starting offset of us */
 } xfs_dir2_data_entry_t;
 
 /*
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 0f5e2f2..b1cf1fb 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_attr_sf.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
@@ -407,7 +405,7 @@
 	 * Initialize our new entry (at last).
 	 */
 	dep = (xfs_dir2_data_entry_t *)dup;
-	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
+	dep->inumber = cpu_to_be64(args->inumber);
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, dep->namelen);
 	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -884,7 +882,7 @@
 					XFS_DIR2_BYTE_TO_DA(mp,
 						XFS_DIR2_LEAF_OFFSET) - map_off,
 					XFS_BMAPI_METADATA, NULL, 0,
-					&map[map_valid], &nmap, NULL);
+					&map[map_valid], &nmap, NULL, NULL);
 				/*
 				 * Don't know if we should ignore this or
 				 * try to return an error.
@@ -1098,7 +1096,7 @@
 
 		p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length);
 
-		p->ino = INT_GET(dep->inumber, ARCH_CONVERT);
+		p->ino = be64_to_cpu(dep->inumber);
 #if XFS_BIG_INUMS
 		p->ino += mp->m_inoadd;
 #endif
@@ -1319,7 +1317,7 @@
 	/*
 	 * Return the found inode number.
 	 */
-	args->inumber = INT_GET(dep->inumber, ARCH_CONVERT);
+	args->inumber = be64_to_cpu(dep->inumber);
 	xfs_da_brelse(tp, dbp);
 	xfs_da_brelse(tp, lbp);
 	return XFS_ERROR(EEXIST);
@@ -1606,11 +1604,11 @@
 	dep = (xfs_dir2_data_entry_t *)
 	      ((char *)dbp->data +
 	       XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address)));
-	ASSERT(args->inumber != INT_GET(dep->inumber, ARCH_CONVERT));
+	ASSERT(args->inumber != be64_to_cpu(dep->inumber));
 	/*
 	 * Put the new inode number in, log it.
 	 */
-	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
+	dep->inumber = cpu_to_be64(args->inumber);
 	tp = args->trans;
 	xfs_dir2_data_log_entry(tp, dbp, dep);
 	xfs_da_buf_done(dbp);
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index ac511ab..9ca7171 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -22,13 +22,11 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -505,7 +503,6 @@
 							XFS_DATA_FORK))) {
 						return error;
 					}
-					curfdb = newfdb;
 					free = curbp->data;
 					ASSERT(be32_to_cpu(free->hdr.magic) ==
 					       XFS_DIR2_FREE_MAGIC);
@@ -527,8 +524,11 @@
 				if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) {
 					XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
 							 XFS_ERRLEVEL_LOW, mp);
+					if (curfdb != newfdb)
+						xfs_da_brelse(tp, curbp);
 					return XFS_ERROR(EFSCORRUPTED);
 				}
+				curfdb = newfdb;
 				if (be16_to_cpu(free->bests[fi]) >= length) {
 					*indexp = index;
 					state->extravalid = 1;
@@ -580,7 +580,7 @@
 			if (dep->namelen == args->namelen &&
 			    dep->name[0] == args->name[0] &&
 			    memcmp(dep->name, args->name, args->namelen) == 0) {
-				args->inumber = INT_GET(dep->inumber, ARCH_CONVERT);
+				args->inumber = be64_to_cpu(dep->inumber);
 				*indexp = index;
 				state->extravalid = 1;
 				state->extrablk.bp = curbp;
@@ -970,7 +970,7 @@
 			/*
 			 * One less used entry in the free table.
 			 */
-			free->hdr.nused = cpu_to_be32(-1);
+			be32_add(&free->hdr.nused, -1);
 			xfs_dir2_free_log_header(tp, fbp);
 			/*
 			 * If this was the last entry in the table, we can
@@ -1695,7 +1695,7 @@
 	 * Fill in the new entry and log it.
 	 */
 	dep = (xfs_dir2_data_entry_t *)dup;
-	INT_SET(dep->inumber, ARCH_CONVERT, args->inumber);
+	dep->inumber = cpu_to_be64(args->inumber);
 	dep->namelen = args->namelen;
 	memcpy(dep->name, args->name, dep->namelen);
 	tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep);
@@ -1905,11 +1905,11 @@
 		dep = (xfs_dir2_data_entry_t *)
 		      ((char *)data +
 		       XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address)));
-		ASSERT(inum != INT_GET(dep->inumber, ARCH_CONVERT));
+		ASSERT(inum != be64_to_cpu(dep->inumber));
 		/*
 		 * Fill in the new inode number and log the entry.
 		 */
-		INT_SET(dep->inumber, ARCH_CONVERT, inum);
+		dep->inumber = cpu_to_be64(inum);
 		xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep);
 		rval = 0;
 	}
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index d98a41d..0cd77b1 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -22,19 +22,16 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_error.h"
 #include "xfs_dir2_data.h"
 #include "xfs_dir2_leaf.h"
@@ -117,13 +114,13 @@
 			dep->name[0] == '.' && dep->name[1] == '.';
 #if XFS_BIG_INUMS
 		if (!isdot)
-			i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM;
+			i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM;
 #endif
 		if (!isdot && !isdotdot) {
 			count++;
 			namelen += dep->namelen;
 		} else if (isdotdot)
-			parent = INT_GET(dep->inumber, ARCH_CONVERT);
+			parent = be64_to_cpu(dep->inumber);
 		/*
 		 * Calculate the new size, see if we should give up yet.
 		 */
@@ -229,13 +226,13 @@
 		 * Skip .
 		 */
 		if (dep->namelen == 1 && dep->name[0] == '.')
-			ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == dp->i_ino);
+			ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino);
 		/*
 		 * Skip .., but make sure the inode number is right.
 		 */
 		else if (dep->namelen == 2 &&
 			 dep->name[0] == '.' && dep->name[1] == '.')
-			ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) ==
+			ASSERT(be64_to_cpu(dep->inumber) ==
 			       XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent));
 		/*
 		 * Normal entry, copy it into shortform.
@@ -246,7 +243,7 @@
 				(xfs_dir2_data_aoff_t)
 				((char *)dep - (char *)block));
 			memcpy(sfep->name, dep->name, dep->namelen);
-			temp=INT_GET(dep->inumber, ARCH_CONVERT);
+			temp = be64_to_cpu(dep->inumber);
 			XFS_DIR2_SF_PUT_INUMBER(sfp, &temp,
 				XFS_DIR2_SF_INUMBERP(sfep));
 			sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep);
diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c
index c626943..f3fb2ff 100644
--- a/fs/xfs/xfs_dir2_trace.c
+++ b/fs/xfs/xfs_dir2_trace.c
@@ -19,11 +19,9 @@
 #include "xfs_fs.h"
 #include "xfs_types.h"
 #include "xfs_inum.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
deleted file mode 100644
index 6d71186..0000000
--- a/fs/xfs/xfs_dir_leaf.c
+++ /dev/null
@@ -1,2213 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_types.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_dir.h"
-#include "xfs_dir2.h"
-#include "xfs_dmapi.h"
-#include "xfs_mount.h"
-#include "xfs_da_btree.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_inode_item.h"
-#include "xfs_alloc.h"
-#include "xfs_btree.h"
-#include "xfs_bmap.h"
-#include "xfs_dir_leaf.h"
-#include "xfs_error.h"
-
-/*
- * xfs_dir_leaf.c
- *
- * Routines to implement leaf blocks of directories as Btrees of hashed names.
- */
-
-/*========================================================================
- * Function prototypes for the kernel.
- *========================================================================*/
-
-/*
- * Routines used for growing the Btree.
- */
-STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
-					      int insertion_index,
-					      int freemap_index);
-STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer,
-					    int musthave, int justcheck);
-STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state,
-						  xfs_da_state_blk_t *blk1,
-						  xfs_da_state_blk_t *blk2);
-STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
-					  xfs_da_state_blk_t *leaf_blk_1,
-					  xfs_da_state_blk_t *leaf_blk_2,
-					  int *number_entries_in_blk1,
-					  int *number_namebytes_in_blk1);
-
-STATIC int xfs_dir_leaf_create(struct xfs_da_args *args,
-				xfs_dablk_t which_block,
-				struct xfs_dabuf **bpp);
-
-/*
- * Utility routines.
- */
-STATIC void xfs_dir_leaf_moveents(xfs_dir_leafblock_t *src_leaf,
-					      int src_start,
-					      xfs_dir_leafblock_t *dst_leaf,
-					      int dst_start, int move_count,
-					      xfs_mount_t *mp);
-
-
-/*========================================================================
- * External routines when dirsize < XFS_IFORK_DSIZE(dp).
- *========================================================================*/
-
-
-/*
- * Validate a given inode number.
- */
-int
-xfs_dir_ino_validate(xfs_mount_t *mp, xfs_ino_t ino)
-{
-	xfs_agblock_t	agblkno;
-	xfs_agino_t	agino;
-	xfs_agnumber_t	agno;
-	int		ino_ok;
-	int		ioff;
-
-	agno = XFS_INO_TO_AGNO(mp, ino);
-	agblkno = XFS_INO_TO_AGBNO(mp, ino);
-	ioff = XFS_INO_TO_OFFSET(mp, ino);
-	agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
-	ino_ok =
-		agno < mp->m_sb.sb_agcount &&
-		agblkno < mp->m_sb.sb_agblocks &&
-		agblkno != 0 &&
-		ioff < (1 << mp->m_sb.sb_inopblog) &&
-		XFS_AGINO_TO_INO(mp, agno, agino) == ino;
-	if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
-			XFS_RANDOM_DIR_INO_VALIDATE))) {
-		xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
-				(unsigned long long) ino);
-		XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
-		return XFS_ERROR(EFSCORRUPTED);
-	}
-	return 0;
-}
-
-/*
- * Create the initial contents of a shortform directory.
- */
-int
-xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent)
-{
-	xfs_dir_sf_hdr_t *hdr;
-	xfs_inode_t *dp;
-
-	dp = args->dp;
-	ASSERT(dp != NULL);
-	ASSERT(dp->i_d.di_size == 0);
-	if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) {
-		dp->i_df.if_flags &= ~XFS_IFEXTENTS;	/* just in case */
-		dp->i_d.di_format = XFS_DINODE_FMT_LOCAL;
-		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
-		dp->i_df.if_flags |= XFS_IFINLINE;
-	}
-	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
-	ASSERT(dp->i_df.if_bytes == 0);
-	xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK);
-	hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data;
-	XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent);
-
-	hdr->count = 0;
-	dp->i_d.di_size = sizeof(*hdr);
-	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
-	return 0;
-}
-
-/*
- * Add a name to the shortform directory structure.
- * Overflow from the inode has already been checked for.
- */
-int
-xfs_dir_shortform_addname(xfs_da_args_t *args)
-{
-	xfs_dir_shortform_t *sf;
-	xfs_dir_sf_entry_t *sfe;
-	int i, offset, size;
-	xfs_inode_t *dp;
-
-	dp = args->dp;
-	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
-	/*
-	 * Catch the case where the conversion from shortform to leaf
-	 * failed part way through.
-	 */
-	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
-		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
-		return XFS_ERROR(EIO);
-	}
-	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
-	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
-	sfe = &sf->list[0];
-	for (i = sf->hdr.count-1; i >= 0; i--) {
-		if (sfe->namelen == args->namelen &&
-		    args->name[0] == sfe->name[0] &&
-		    memcmp(args->name, sfe->name, args->namelen) == 0)
-			return XFS_ERROR(EEXIST);
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-	}
-
-	offset = (int)((char *)sfe - (char *)sf);
-	size = XFS_DIR_SF_ENTSIZE_BYNAME(args->namelen);
-	xfs_idata_realloc(dp, size, XFS_DATA_FORK);
-	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
-	sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset);
-
-	XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
-	sfe->namelen = args->namelen;
-	memcpy(sfe->name, args->name, sfe->namelen);
-	sf->hdr.count++;
-
-	dp->i_d.di_size += size;
-	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
-
-	return 0;
-}
-
-/*
- * Remove a name from the shortform directory structure.
- */
-int
-xfs_dir_shortform_removename(xfs_da_args_t *args)
-{
-	xfs_dir_shortform_t *sf;
-	xfs_dir_sf_entry_t *sfe;
-	int base, size = 0, i;
-	xfs_inode_t *dp;
-
-	dp = args->dp;
-	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
-	/*
-	 * Catch the case where the conversion from shortform to leaf
-	 * failed part way through.
-	 */
-	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
-		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
-		return XFS_ERROR(EIO);
-	}
-	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
-	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	base = sizeof(xfs_dir_sf_hdr_t);
-	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
-	sfe = &sf->list[0];
-	for (i = sf->hdr.count-1; i >= 0; i--) {
-		size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe);
-		if (sfe->namelen == args->namelen &&
-		    sfe->name[0] == args->name[0] &&
-		    memcmp(sfe->name, args->name, args->namelen) == 0)
-			break;
-		base += size;
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-	}
-	if (i < 0) {
-		ASSERT(args->oknoent);
-		return XFS_ERROR(ENOENT);
-	}
-
-	if ((base + size) != dp->i_d.di_size) {
-		memmove(&((char *)sf)[base], &((char *)sf)[base+size],
-					      dp->i_d.di_size - (base+size));
-	}
-	sf->hdr.count--;
-
-	xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
-	dp->i_d.di_size -= size;
-	xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA);
-
-	return 0;
-}
-
-/*
- * Look up a name in a shortform directory structure.
- */
-int
-xfs_dir_shortform_lookup(xfs_da_args_t *args)
-{
-	xfs_dir_shortform_t *sf;
-	xfs_dir_sf_entry_t *sfe;
-	int i;
-	xfs_inode_t *dp;
-
-	dp = args->dp;
-	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
-	/*
-	 * Catch the case where the conversion from shortform to leaf
-	 * failed part way through.
-	 */
-	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
-		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
-		return XFS_ERROR(EIO);
-	}
-	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
-	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
-	if (args->namelen == 2 &&
-	    args->name[0] == '.' && args->name[1] == '.') {
-		XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber);
-		return(XFS_ERROR(EEXIST));
-	}
-	if (args->namelen == 1 && args->name[0] == '.') {
-		args->inumber = dp->i_ino;
-		return(XFS_ERROR(EEXIST));
-	}
-	sfe = &sf->list[0];
-	for (i = sf->hdr.count-1; i >= 0; i--) {
-		if (sfe->namelen == args->namelen &&
-		    sfe->name[0] == args->name[0] &&
-		    memcmp(args->name, sfe->name, args->namelen) == 0) {
-			XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber);
-			return(XFS_ERROR(EEXIST));
-		}
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-	}
-	ASSERT(args->oknoent);
-	return(XFS_ERROR(ENOENT));
-}
-
-/*
- * Convert from using the shortform to the leaf.
- */
-int
-xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs)
-{
-	xfs_inode_t *dp;
-	xfs_dir_shortform_t *sf;
-	xfs_dir_sf_entry_t *sfe;
-	xfs_da_args_t args;
-	xfs_ino_t inumber;
-	char *tmpbuffer;
-	int retval, i, size;
-	xfs_dablk_t blkno;
-	xfs_dabuf_t *bp;
-
-	dp = iargs->dp;
-	/*
-	 * Catch the case where the conversion from shortform to leaf
-	 * failed part way through.
-	 */
-	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
-		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
-		return XFS_ERROR(EIO);
-	}
-	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
-	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	size = dp->i_df.if_bytes;
-	tmpbuffer = kmem_alloc(size, KM_SLEEP);
-	ASSERT(tmpbuffer != NULL);
-
-	memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size);
-
-	sf = (xfs_dir_shortform_t *)tmpbuffer;
-	XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber);
-
-	xfs_idata_realloc(dp, -size, XFS_DATA_FORK);
-	dp->i_d.di_size = 0;
-	xfs_trans_log_inode(iargs->trans, dp, XFS_ILOG_CORE);
-	retval = xfs_da_grow_inode(iargs, &blkno);
-	if (retval)
-		goto out;
-
-	ASSERT(blkno == 0);
-	retval = xfs_dir_leaf_create(iargs, blkno, &bp);
-	if (retval)
-		goto out;
-	xfs_da_buf_done(bp);
-
-	args.name = ".";
-	args.namelen = 1;
-	args.hashval = xfs_dir_hash_dot;
-	args.inumber = dp->i_ino;
-	args.dp = dp;
-	args.firstblock = iargs->firstblock;
-	args.flist = iargs->flist;
-	args.total = iargs->total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = iargs->trans;
-	args.justcheck = 0;
-	args.addname = args.oknoent = 1;
-	retval = xfs_dir_leaf_addname(&args);
-	if (retval)
-		goto out;
-
-	args.name = "..";
-	args.namelen = 2;
-	args.hashval = xfs_dir_hash_dotdot;
-	args.inumber = inumber;
-	retval = xfs_dir_leaf_addname(&args);
-	if (retval)
-		goto out;
-
-	sfe = &sf->list[0];
-	for (i = 0; i < sf->hdr.count; i++) {
-		args.name = (char *)(sfe->name);
-		args.namelen = sfe->namelen;
-		args.hashval = xfs_da_hashname((char *)(sfe->name),
-					       sfe->namelen);
-		XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber);
-		retval = xfs_dir_leaf_addname(&args);
-		if (retval)
-			goto out;
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-	}
-	retval = 0;
-
-out:
-	kmem_free(tmpbuffer, size);
-	return retval;
-}
-
-STATIC int
-xfs_dir_shortform_compare(const void *a, const void *b)
-{
-	xfs_dir_sf_sort_t *sa, *sb;
-
-	sa = (xfs_dir_sf_sort_t *)a;
-	sb = (xfs_dir_sf_sort_t *)b;
-	if (sa->hash < sb->hash)
-		return -1;
-	else if (sa->hash > sb->hash)
-		return 1;
-	else
-		return sa->entno - sb->entno;
-}
-
-/*
- * Copy out directory entries for getdents(), for shortform directories.
- */
-/*ARGSUSED*/
-int
-xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp,
-				       xfs_dirent_t *dbp, xfs_dir_put_t put)
-{
-	xfs_dir_shortform_t *sf;
-	xfs_dir_sf_entry_t *sfe;
-	int retval, i, sbsize, nsbuf, lastresid=0, want_entno;
-	xfs_mount_t *mp;
-	xfs_dahash_t cookhash, hash;
-	xfs_dir_put_args_t p;
-	xfs_dir_sf_sort_t *sbuf, *sbp;
-
-	mp = dp->i_mount;
-	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
-	cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
-	want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
-	nsbuf = sf->hdr.count + 2;
-	sbsize = (nsbuf + 1) * sizeof(*sbuf);
-	sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP);
-
-	xfs_dir_trace_g_du("sf: start", dp, uio);
-
-	/*
-	 * Collect all the entries into the buffer.
-	 * Entry 0 is .
-	 */
-	sbp->entno = 0;
-	sbp->seqno = 0;
-	sbp->hash = xfs_dir_hash_dot;
-	sbp->ino = dp->i_ino;
-	sbp->name = ".";
-	sbp->namelen = 1;
-	sbp++;
-
-	/*
-	 * Entry 1 is ..
-	 */
-	sbp->entno = 1;
-	sbp->seqno = 0;
-	sbp->hash = xfs_dir_hash_dotdot;
-	sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent);
-	sbp->name = "..";
-	sbp->namelen = 2;
-	sbp++;
-
-	/*
-	 * Scan the directory data for the rest of the entries.
-	 */
-	for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) {
-
-		if (unlikely(
-		    ((char *)sfe < (char *)sf) ||
-		    ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)))) {
-			xfs_dir_trace_g_du("sf: corrupted", dp, uio);
-			XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents",
-					     XFS_ERRLEVEL_LOW, mp, sfe);
-			kmem_free(sbuf, sbsize);
-			return XFS_ERROR(EFSCORRUPTED);
-		}
-
-		sbp->entno = i + 2;
-		sbp->seqno = 0;
-		sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen);
-		sbp->ino = XFS_GET_DIR_INO8(sfe->inumber);
-		sbp->name = (char *)sfe->name;
-		sbp->namelen = sfe->namelen;
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-		sbp++;
-	}
-
-	/*
-	 * Sort the entries on hash then entno.
-	 */
-	xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_dir_shortform_compare);
-	/*
-	 * Stuff in last entry.
-	 */
-	sbp->entno = nsbuf;
-	sbp->hash = XFS_DA_MAXHASH;
-	sbp->seqno = 0;
-	/*
-	 * Figure out the sequence numbers in case there's a hash duplicate.
-	 */
-	for (hash = sbuf->hash, sbp = sbuf + 1;
-				sbp < &sbuf[nsbuf + 1]; sbp++) {
-		if (sbp->hash == hash)
-			sbp->seqno = sbp[-1].seqno + 1;
-		else
-			hash = sbp->hash;
-	}
-
-	/*
-	 * Set up put routine.
-	 */
-	p.dbp = dbp;
-	p.put = put;
-	p.uio = uio;
-
-	/*
-	 * Find our place.
-	 */
-	for (sbp = sbuf; sbp < &sbuf[nsbuf + 1]; sbp++) {
-		if (sbp->hash > cookhash ||
-		    (sbp->hash == cookhash && sbp->seqno >= want_entno))
-			break;
-	}
-
-	/*
-	 * Did we fail to find anything?  We stop at the last entry,
-	 * the one we put maxhash into.
-	 */
-	if (sbp == &sbuf[nsbuf]) {
-		kmem_free(sbuf, sbsize);
-		xfs_dir_trace_g_du("sf: hash beyond end", dp, uio);
-		uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
-		*eofp = 1;
-		return 0;
-	}
-
-	/*
-	 * Loop putting entries into the user buffer.
-	 */
-	while (sbp < &sbuf[nsbuf]) {
-		/*
-		 * Save the first resid in a run of equal-hashval entries
-		 * so that we can back them out if they don't all fit.
-		 */
-		if (sbp->seqno == 0 || sbp == sbuf)
-			lastresid = uio->uio_resid;
-		XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash);
-		p.ino = sbp->ino;
-#if XFS_BIG_INUMS
-		p.ino += mp->m_inoadd;
-#endif
-		p.name = sbp->name;
-		p.namelen = sbp->namelen;
-		retval = p.put(&p);
-		if (!p.done) {
-			uio->uio_offset =
-				XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash);
-			kmem_free(sbuf, sbsize);
-			uio->uio_resid = lastresid;
-			xfs_dir_trace_g_du("sf: E-O-B", dp, uio);
-			return retval;
-		}
-		sbp++;
-	}
-	kmem_free(sbuf, sbsize);
-	uio->uio_offset = p.cook.o;
-	*eofp = 1;
-	xfs_dir_trace_g_du("sf: E-O-F", dp, uio);
-	return 0;
-}
-
-/*
- * Look up a name in a shortform directory structure, replace the inode number.
- */
-int
-xfs_dir_shortform_replace(xfs_da_args_t *args)
-{
-	xfs_dir_shortform_t *sf;
-	xfs_dir_sf_entry_t *sfe;
-	xfs_inode_t *dp;
-	int i;
-
-	dp = args->dp;
-	ASSERT(dp->i_df.if_flags & XFS_IFINLINE);
-	/*
-	 * Catch the case where the conversion from shortform to leaf
-	 * failed part way through.
-	 */
-	if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) {
-		ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount));
-		return XFS_ERROR(EIO);
-	}
-	ASSERT(dp->i_df.if_bytes == dp->i_d.di_size);
-	ASSERT(dp->i_df.if_u1.if_data != NULL);
-	sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data;
-	if (args->namelen == 2 &&
-	    args->name[0] == '.' && args->name[1] == '.') {
-		/* XXX - replace assert? */
-		XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent);
-		xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
-		return 0;
-	}
-	ASSERT(args->namelen != 1 || args->name[0] != '.');
-	sfe = &sf->list[0];
-	for (i = sf->hdr.count-1; i >= 0; i--) {
-		if (sfe->namelen == args->namelen &&
-		    sfe->name[0] == args->name[0] &&
-		    memcmp(args->name, sfe->name, args->namelen) == 0) {
-			ASSERT(memcmp((char *)&args->inumber,
-				(char *)&sfe->inumber, sizeof(xfs_ino_t)));
-			XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber);
-			xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA);
-			return 0;
-		}
-		sfe = XFS_DIR_SF_NEXTENTRY(sfe);
-	}
-	ASSERT(args->oknoent);
-	return XFS_ERROR(ENOENT);
-}
-
-/*
- * Convert a leaf directory to shortform structure
- */
-int
-xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_hdr_t *hdr;
-	xfs_dir_leaf_entry_t *entry;
-	xfs_dir_leaf_name_t *namest;
-	xfs_da_args_t args;
-	xfs_inode_t *dp;
-	xfs_ino_t parent = 0;
-	char *tmpbuffer;
-	int retval, i;
-	xfs_dabuf_t *bp;
-
-	dp = iargs->dp;
-	tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP);
-	ASSERT(tmpbuffer != NULL);
-
-	retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp,
-					       XFS_DATA_FORK);
-	if (retval)
-		goto out;
-	ASSERT(bp != NULL);
-	memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount));
-	leaf = (xfs_dir_leafblock_t *)tmpbuffer;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	memset(bp->data, 0, XFS_LBSIZE(dp->i_mount));
-
-	/*
-	 * Find and special case the parent inode number
-	 */
-	hdr = &leaf->hdr;
-	entry = &leaf->entries[0];
-	for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) {
-		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
-		if ((entry->namelen == 2) &&
-		    (namest->name[0] == '.') &&
-		    (namest->name[1] == '.')) {
-			XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent);
-			entry->nameidx = 0;
-		} else if ((entry->namelen == 1) && (namest->name[0] == '.')) {
-			entry->nameidx = 0;
-		}
-	}
-	retval = xfs_da_shrink_inode(iargs, 0, bp);
-	if (retval)
-		goto out;
-	retval = xfs_dir_shortform_create(iargs, parent);
-	if (retval)
-		goto out;
-
-	/*
-	 * Copy the rest of the filenames
-	 */
-	entry = &leaf->entries[0];
-	args.dp = dp;
-	args.firstblock = iargs->firstblock;
-	args.flist = iargs->flist;
-	args.total = iargs->total;
-	args.whichfork = XFS_DATA_FORK;
-	args.trans = iargs->trans;
-	args.justcheck = 0;
-	args.addname = args.oknoent = 1;
-	for (i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) {
-		if (!entry->nameidx)
-			continue;
-		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
-		args.name = (char *)(namest->name);
-		args.namelen = entry->namelen;
-		args.hashval = INT_GET(entry->hashval, ARCH_CONVERT);
-		XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber);
-		xfs_dir_shortform_addname(&args);
-	}
-
-out:
-	kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount));
-	return retval;
-}
-
-/*
- * Convert from using a single leaf to a root node and a leaf.
- */
-int
-xfs_dir_leaf_to_node(xfs_da_args_t *args)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_da_intnode_t *node;
-	xfs_inode_t *dp;
-	xfs_dabuf_t *bp1, *bp2;
-	xfs_dablk_t blkno;
-	int retval;
-
-	dp = args->dp;
-	retval = xfs_da_grow_inode(args, &blkno);
-	ASSERT(blkno == 1);
-	if (retval)
-		return retval;
-	retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1,
-					      XFS_DATA_FORK);
-	if (retval)
-		return retval;
-	ASSERT(bp1 != NULL);
-	retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2,
-					     XFS_DATA_FORK);
-	if (retval) {
-		xfs_da_buf_done(bp1);
-		return retval;
-	}
-	ASSERT(bp2 != NULL);
-	memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount));
-	xfs_da_buf_done(bp1);
-	xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1);
-
-	/*
-	 * Set up the new root node.
-	 */
-	retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK);
-	if (retval) {
-		xfs_da_buf_done(bp2);
-		return retval;
-	}
-	node = bp1->data;
-	leaf = bp2->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	node->btree[0].hashval = cpu_to_be32(
-		INT_GET(leaf->entries[
-			INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT));
-	xfs_da_buf_done(bp2);
-	node->btree[0].before = cpu_to_be32(blkno);
-	node->hdr.count = cpu_to_be16(1);
-	xfs_da_log_buf(args->trans, bp1,
-		XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0])));
-	xfs_da_buf_done(bp1);
-
-	return retval;
-}
-
-
-/*========================================================================
- * Routines used for growing the Btree.
- *========================================================================*/
-
-/*
- * Create the initial contents of a leaf directory
- * or a leaf in a node directory.
- */
-STATIC int
-xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_hdr_t *hdr;
-	xfs_inode_t *dp;
-	xfs_dabuf_t *bp;
-	int retval;
-
-	dp = args->dp;
-	ASSERT(dp != NULL);
-	retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK);
-	if (retval)
-		return retval;
-	ASSERT(bp != NULL);
-	leaf = bp->data;
-	memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount));
-	hdr = &leaf->hdr;
-	hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC);
-	INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount));
-	if (!hdr->firstused)
-		INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1);
-	INT_SET(hdr->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
-	INT_SET(hdr->freemap[0].size, ARCH_CONVERT, INT_GET(hdr->firstused, ARCH_CONVERT) - INT_GET(hdr->freemap[0].base, ARCH_CONVERT));
-
-	xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1);
-
-	*bpp = bp;
-	return 0;
-}
-
-/*
- * Split the leaf node, rebalance, then add the new entry.
- */
-int
-xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk,
-				  xfs_da_state_blk_t *newblk)
-{
-	xfs_dablk_t blkno;
-	xfs_da_args_t *args;
-	int error;
-
-	/*
-	 * Allocate space for a new leaf node.
-	 */
-	args = state->args;
-	ASSERT(args != NULL);
-	ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC);
-	error = xfs_da_grow_inode(args, &blkno);
-	if (error)
-		return error;
-	error = xfs_dir_leaf_create(args, blkno, &newblk->bp);
-	if (error)
-		return error;
-	newblk->blkno = blkno;
-	newblk->magic = XFS_DIR_LEAF_MAGIC;
-
-	/*
-	 * Rebalance the entries across the two leaves.
-	 */
-	xfs_dir_leaf_rebalance(state, oldblk, newblk);
-	error = xfs_da_blk_link(state, oldblk, newblk);
-	if (error)
-		return error;
-
-	/*
-	 * Insert the new entry in the correct block.
-	 */
-	if (state->inleaf) {
-		error = xfs_dir_leaf_add(oldblk->bp, args, oldblk->index);
-	} else {
-		error = xfs_dir_leaf_add(newblk->bp, args, newblk->index);
-	}
-
-	/*
-	 * Update last hashval in each block since we added the name.
-	 */
-	oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL);
-	newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL);
-	return error;
-}
-
-/*
- * Add a name to the leaf directory structure.
- *
- * Must take into account fragmented leaves and leaves where spacemap has
- * lost some freespace information (ie: holes).
- */
-int
-xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_hdr_t *hdr;
-	xfs_dir_leaf_map_t *map;
-	int tablesize, entsize, sum, i, tmp, error;
-
-	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	ASSERT((index >= 0) && (index <= INT_GET(leaf->hdr.count, ARCH_CONVERT)));
-	hdr = &leaf->hdr;
-	entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen);
-
-	/*
-	 * Search through freemap for first-fit on new name length.
-	 * (may need to figure in size of entry struct too)
-	 */
-	tablesize = (INT_GET(hdr->count, ARCH_CONVERT) + 1) * (uint)sizeof(xfs_dir_leaf_entry_t)
-			+ (uint)sizeof(xfs_dir_leaf_hdr_t);
-	map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1];
-	for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) {
-		if (tablesize > INT_GET(hdr->firstused, ARCH_CONVERT)) {
-			sum += INT_GET(map->size, ARCH_CONVERT);
-			continue;
-		}
-		if (!map->size)
-			continue;	/* no space in this map */
-		tmp = entsize;
-		if (INT_GET(map->base, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
-			tmp += (uint)sizeof(xfs_dir_leaf_entry_t);
-		if (INT_GET(map->size, ARCH_CONVERT) >= tmp) {
-			if (!args->justcheck)
-				xfs_dir_leaf_add_work(bp, args, index, i);
-			return 0;
-		}
-		sum += INT_GET(map->size, ARCH_CONVERT);
-	}
-
-	/*
-	 * If there are no holes in the address space of the block,
-	 * and we don't have enough freespace, then compaction will do us
-	 * no good and we should just give up.
-	 */
-	if (!hdr->holes && (sum < entsize))
-		return XFS_ERROR(ENOSPC);
-
-	/*
-	 * Compact the entries to coalesce free space.
-	 * Pass the justcheck flag so the checking pass can return
-	 * an error, without changing anything, if it won't fit.
-	 */
-	error = xfs_dir_leaf_compact(args->trans, bp,
-			args->total == 0 ?
-				entsize +
-				(uint)sizeof(xfs_dir_leaf_entry_t) : 0,
-			args->justcheck);
-	if (error)
-		return error;
-	/*
-	 * After compaction, the block is guaranteed to have only one
-	 * free region, in freemap[0].  If it is not big enough, give up.
-	 */
-	if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) <
-	    (entsize + (uint)sizeof(xfs_dir_leaf_entry_t)))
-		return XFS_ERROR(ENOSPC);
-
-	if (!args->justcheck)
-		xfs_dir_leaf_add_work(bp, args, index, 0);
-	return 0;
-}
-
-/*
- * Add a name to a leaf directory structure.
- */
-STATIC void
-xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index,
-		      int mapindex)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_hdr_t *hdr;
-	xfs_dir_leaf_entry_t *entry;
-	xfs_dir_leaf_name_t *namest;
-	xfs_dir_leaf_map_t *map;
-	/* REFERENCED */
-	xfs_mount_t *mp;
-	int tmp, i;
-
-	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	hdr = &leaf->hdr;
-	ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE));
-	ASSERT((index >= 0) && (index <= INT_GET(hdr->count, ARCH_CONVERT)));
-
-	/*
-	 * Force open some space in the entry array and fill it in.
-	 */
-	entry = &leaf->entries[index];
-	if (index < INT_GET(hdr->count, ARCH_CONVERT)) {
-		tmp  = INT_GET(hdr->count, ARCH_CONVERT) - index;
-		tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
-		memmove(entry + 1, entry, tmp);
-		xfs_da_log_buf(args->trans, bp,
-		    XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
-	}
-	INT_MOD(hdr->count, ARCH_CONVERT, +1);
-
-	/*
-	 * Allocate space for the new string (at the end of the run).
-	 */
-	map = &hdr->freemap[mapindex];
-	mp = args->trans->t_mountp;
-	ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
-	ASSERT(INT_GET(map->size, ARCH_CONVERT) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen));
-	ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
-	INT_MOD(map->size, ARCH_CONVERT, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)));
-	INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT));
-	INT_SET(entry->hashval, ARCH_CONVERT, args->hashval);
-	entry->namelen = args->namelen;
-	xfs_da_log_buf(args->trans, bp,
-	    XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry)));
-
-	/*
-	 * Copy the string and inode number into the new space.
-	 */
-	namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
-	XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber);
-	memcpy(namest->name, args->name, args->namelen);
-	xfs_da_log_buf(args->trans, bp,
-	    XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry)));
-
-	/*
-	 * Update the control info for this leaf node
-	 */
-	if (INT_GET(entry->nameidx, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT))
-		INT_COPY(hdr->firstused, entry->nameidx, ARCH_CONVERT);
-	ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr)));
-	tmp = (INT_GET(hdr->count, ARCH_CONVERT)-1) * (uint)sizeof(xfs_dir_leaf_entry_t)
-			+ (uint)sizeof(xfs_dir_leaf_hdr_t);
-	map = &hdr->freemap[0];
-	for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
-		if (INT_GET(map->base, ARCH_CONVERT) == tmp) {
-			INT_MOD(map->base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t));
-			INT_MOD(map->size, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t)));
-		}
-	}
-	INT_MOD(hdr->namebytes, ARCH_CONVERT, args->namelen);
-	xfs_da_log_buf(args->trans, bp,
-		XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
-}
-
-/*
- * Garbage collect a leaf directory block by copying it to a new buffer.
- */
-STATIC int
-xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave,
-		     int justcheck)
-{
-	xfs_dir_leafblock_t *leaf_s, *leaf_d;
-	xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
-	xfs_mount_t *mp;
-	char *tmpbuffer;
-	char *tmpbuffer2=NULL;
-	int rval;
-	int lbsize;
-
-	mp = trans->t_mountp;
-	lbsize = XFS_LBSIZE(mp);
-	tmpbuffer = kmem_alloc(lbsize, KM_SLEEP);
-	ASSERT(tmpbuffer != NULL);
-	memcpy(tmpbuffer, bp->data, lbsize);
-
-	/*
-	 * Make a second copy in case xfs_dir_leaf_moveents()
-	 * below destroys the original.
-	 */
-	if (musthave || justcheck) {
-		tmpbuffer2 = kmem_alloc(lbsize, KM_SLEEP);
-		memcpy(tmpbuffer2, bp->data, lbsize);
-	}
-	memset(bp->data, 0, lbsize);
-
-	/*
-	 * Copy basic information
-	 */
-	leaf_s = (xfs_dir_leafblock_t *)tmpbuffer;
-	leaf_d = bp->data;
-	hdr_s = &leaf_s->hdr;
-	hdr_d = &leaf_d->hdr;
-	hdr_d->info = hdr_s->info;	/* struct copy */
-	INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize);
-	if (!hdr_d->firstused)
-		INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize - 1);
-	hdr_d->namebytes = 0;
-	hdr_d->count = 0;
-	hdr_d->holes = 0;
-	INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t));
-	INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
-
-	/*
-	 * Copy all entry's in the same (sorted) order,
-	 * but allocate filenames packed and in sequence.
-	 * This changes the source (leaf_s) as well.
-	 */
-	xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, (int)INT_GET(hdr_s->count, ARCH_CONVERT), mp);
-
-	if (musthave && INT_GET(hdr_d->freemap[0].size, ARCH_CONVERT) < musthave)
-		rval = XFS_ERROR(ENOSPC);
-	else
-		rval = 0;
-
-	if (justcheck || rval == ENOSPC) {
-		ASSERT(tmpbuffer2);
-		memcpy(bp->data, tmpbuffer2, lbsize);
-	} else {
-		xfs_da_log_buf(trans, bp, 0, lbsize - 1);
-	}
-
-	kmem_free(tmpbuffer, lbsize);
-	if (musthave || justcheck)
-		kmem_free(tmpbuffer2, lbsize);
-	return rval;
-}
-
-/*
- * Redistribute the directory entries between two leaf nodes,
- * taking into account the size of the new entry.
- *
- * NOTE: if new block is empty, then it will get the upper half of old block.
- */
-STATIC void
-xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
-				      xfs_da_state_blk_t *blk2)
-{
-	xfs_da_state_blk_t *tmp_blk;
-	xfs_dir_leafblock_t *leaf1, *leaf2;
-	xfs_dir_leaf_hdr_t *hdr1, *hdr2;
-	int count, totallen, max, space, swap;
-
-	/*
-	 * Set up environment.
-	 */
-	ASSERT(blk1->magic == XFS_DIR_LEAF_MAGIC);
-	ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC);
-	leaf1 = blk1->bp->data;
-	leaf2 = blk2->bp->data;
-	ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-
-	/*
-	 * Check ordering of blocks, reverse if it makes things simpler.
-	 */
-	swap = 0;
-	if (xfs_dir_leaf_order(blk1->bp, blk2->bp)) {
-		tmp_blk = blk1;
-		blk1 = blk2;
-		blk2 = tmp_blk;
-		leaf1 = blk1->bp->data;
-		leaf2 = blk2->bp->data;
-		swap = 1;
-	}
-	hdr1 = &leaf1->hdr;
-	hdr2 = &leaf2->hdr;
-
-	/*
-	 * Examine entries until we reduce the absolute difference in
-	 * byte usage between the two blocks to a minimum.  Then get
-	 * the direction to copy and the number of elements to move.
-	 */
-	state->inleaf = xfs_dir_leaf_figure_balance(state, blk1, blk2,
-							   &count, &totallen);
-	if (swap)
-		state->inleaf = !state->inleaf;
-
-	/*
-	 * Move any entries required from leaf to leaf:
-	 */
-	if (count < INT_GET(hdr1->count, ARCH_CONVERT)) {
-		/*
-		 * Figure the total bytes to be added to the destination leaf.
-		 */
-		count = INT_GET(hdr1->count, ARCH_CONVERT) - count;	/* number entries being moved */
-		space  = INT_GET(hdr1->namebytes, ARCH_CONVERT) - totallen;
-		space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
-		space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
-
-		/*
-		 * leaf2 is the destination, compact it if it looks tight.
-		 */
-		max  = INT_GET(hdr2->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t);
-		max -= INT_GET(hdr2->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
-		if (space > max) {
-			xfs_dir_leaf_compact(state->args->trans, blk2->bp,
-								 0, 0);
-		}
-
-		/*
-		 * Move high entries from leaf1 to low end of leaf2.
-		 */
-		xfs_dir_leaf_moveents(leaf1, INT_GET(hdr1->count, ARCH_CONVERT) - count,
-					     leaf2, 0, count, state->mp);
-
-		xfs_da_log_buf(state->args->trans, blk1->bp, 0,
-						   state->blocksize-1);
-		xfs_da_log_buf(state->args->trans, blk2->bp, 0,
-						   state->blocksize-1);
-
-	} else if (count > INT_GET(hdr1->count, ARCH_CONVERT)) {
-		/*
-		 * Figure the total bytes to be added to the destination leaf.
-		 */
-		count -= INT_GET(hdr1->count, ARCH_CONVERT);		/* number entries being moved */
-		space  = totallen - INT_GET(hdr1->namebytes, ARCH_CONVERT);
-		space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1);
-		space += count * (uint)sizeof(xfs_dir_leaf_entry_t);
-
-		/*
-		 * leaf1 is the destination, compact it if it looks tight.
-		 */
-		max  = INT_GET(hdr1->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t);
-		max -= INT_GET(hdr1->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
-		if (space > max) {
-			xfs_dir_leaf_compact(state->args->trans, blk1->bp,
-								 0, 0);
-		}
-
-		/*
-		 * Move low entries from leaf2 to high end of leaf1.
-		 */
-		xfs_dir_leaf_moveents(leaf2, 0, leaf1, (int)INT_GET(hdr1->count, ARCH_CONVERT),
-					     count, state->mp);
-
-		xfs_da_log_buf(state->args->trans, blk1->bp, 0,
-						   state->blocksize-1);
-		xfs_da_log_buf(state->args->trans, blk2->bp, 0,
-						   state->blocksize-1);
-	}
-
-	/*
-	 * Copy out last hashval in each block for B-tree code.
-	 */
-	blk1->hashval = INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
-	blk2->hashval = INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
-
-	/*
-	 * Adjust the expected index for insertion.
-	 * GROT: this doesn't work unless blk2 was originally empty.
-	 */
-	if (!state->inleaf) {
-		blk2->index = blk1->index - INT_GET(leaf1->hdr.count, ARCH_CONVERT);
-	}
-}
-
-/*
- * Examine entries until we reduce the absolute difference in
- * byte usage between the two blocks to a minimum.
- * GROT: Is this really necessary?  With other than a 512 byte blocksize,
- * GROT: there will always be enough room in either block for a new entry.
- * GROT: Do a double-split for this case?
- */
-STATIC int
-xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
-					   xfs_da_state_blk_t *blk1,
-					   xfs_da_state_blk_t *blk2,
-					   int *countarg, int *namebytesarg)
-{
-	xfs_dir_leafblock_t *leaf1, *leaf2;
-	xfs_dir_leaf_hdr_t *hdr1, *hdr2;
-	xfs_dir_leaf_entry_t *entry;
-	int count, max, totallen, half;
-	int lastdelta, foundit, tmp;
-
-	/*
-	 * Set up environment.
-	 */
-	leaf1 = blk1->bp->data;
-	leaf2 = blk2->bp->data;
-	hdr1 = &leaf1->hdr;
-	hdr2 = &leaf2->hdr;
-	foundit = 0;
-	totallen = 0;
-
-	/*
-	 * Examine entries until we reduce the absolute difference in
-	 * byte usage between the two blocks to a minimum.
-	 */
-	max = INT_GET(hdr1->count, ARCH_CONVERT) + INT_GET(hdr2->count, ARCH_CONVERT);
-	half  = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
-	half += INT_GET(hdr1->namebytes, ARCH_CONVERT) + INT_GET(hdr2->namebytes, ARCH_CONVERT) + state->args->namelen;
-	half /= 2;
-	lastdelta = state->blocksize;
-	entry = &leaf1->entries[0];
-	for (count = 0; count < max; entry++, count++) {
-
-#define XFS_DIR_ABS(A)	(((A) < 0) ? -(A) : (A))
-		/*
-		 * The new entry is in the first block, account for it.
-		 */
-		if (count == blk1->index) {
-			tmp = totallen + (uint)sizeof(*entry)
-				+ XFS_DIR_LEAF_ENTSIZE_BYNAME(state->args->namelen);
-			if (XFS_DIR_ABS(half - tmp) > lastdelta)
-				break;
-			lastdelta = XFS_DIR_ABS(half - tmp);
-			totallen = tmp;
-			foundit = 1;
-		}
-
-		/*
-		 * Wrap around into the second block if necessary.
-		 */
-		if (count == INT_GET(hdr1->count, ARCH_CONVERT)) {
-			leaf1 = leaf2;
-			entry = &leaf1->entries[0];
-		}
-
-		/*
-		 * Figure out if next leaf entry would be too much.
-		 */
-		tmp = totallen + (uint)sizeof(*entry)
-				+ XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
-		if (XFS_DIR_ABS(half - tmp) > lastdelta)
-			break;
-		lastdelta = XFS_DIR_ABS(half - tmp);
-		totallen = tmp;
-#undef XFS_DIR_ABS
-	}
-
-	/*
-	 * Calculate the number of namebytes that will end up in lower block.
-	 * If new entry not in lower block, fix up the count.
-	 */
-	totallen -=
-		count * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1);
-	if (foundit) {
-		totallen -= (sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1) +
-			    state->args->namelen;
-	}
-
-	*countarg = count;
-	*namebytesarg = totallen;
-	return foundit;
-}
-
-/*========================================================================
- * Routines used for shrinking the Btree.
- *========================================================================*/
-
-/*
- * Check a leaf block and its neighbors to see if the block should be
- * collapsed into one or the other neighbor.  Always keep the block
- * with the smaller block number.
- * If the current block is over 50% full, don't try to join it, return 0.
- * If the block is empty, fill in the state structure and return 2.
- * If it can be collapsed, fill in the state structure and return 1.
- * If nothing can be done, return 0.
- */
-int
-xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_da_state_blk_t *blk;
-	xfs_da_blkinfo_t *info;
-	int count, bytes, forward, error, retval, i;
-	xfs_dablk_t blkno;
-	xfs_dabuf_t *bp;
-
-	/*
-	 * Check for the degenerate case of the block being over 50% full.
-	 * If so, it's not worth even looking to see if we might be able
-	 * to coalesce with a sibling.
-	 */
-	blk = &state->path.blk[ state->path.active-1 ];
-	info = blk->bp->data;
-	ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC);
-	leaf = (xfs_dir_leafblock_t *)info;
-	count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
-	bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) +
-		count * (uint)sizeof(xfs_dir_leaf_entry_t) +
-		count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) +
-		INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
-	if (bytes > (state->blocksize >> 1)) {
-		*action = 0;	/* blk over 50%, don't try to join */
-		return 0;
-	}
-
-	/*
-	 * Check for the degenerate case of the block being empty.
-	 * If the block is empty, we'll simply delete it, no need to
-	 * coalesce it with a sibling block.  We choose (arbitrarily)
-	 * to merge with the forward block unless it is NULL.
-	 */
-	if (count == 0) {
-		/*
-		 * Make altpath point to the block we want to keep and
-		 * path point to the block we want to drop (this one).
-		 */
-		forward = (info->forw != 0);
-		memcpy(&state->altpath, &state->path, sizeof(state->path));
-		error = xfs_da_path_shift(state, &state->altpath, forward,
-						 0, &retval);
-		if (error)
-			return error;
-		if (retval) {
-			*action = 0;
-		} else {
-			*action = 2;
-		}
-		return 0;
-	}
-
-	/*
-	 * Examine each sibling block to see if we can coalesce with
-	 * at least 25% free space to spare.  We need to figure out
-	 * whether to merge with the forward or the backward block.
-	 * We prefer coalescing with the lower numbered sibling so as
-	 * to shrink a directory over time.
-	 */
-	forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back));	/* start with smaller blk num */
-	for (i = 0; i < 2; forward = !forward, i++) {
-		if (forward)
-			blkno = be32_to_cpu(info->forw);
-		else
-			blkno = be32_to_cpu(info->back);
-		if (blkno == 0)
-			continue;
-		error = xfs_da_read_buf(state->args->trans, state->args->dp,
-							    blkno, -1, &bp,
-							    XFS_DATA_FORK);
-		if (error)
-			return error;
-		ASSERT(bp != NULL);
-
-		leaf = (xfs_dir_leafblock_t *)info;
-		count  = INT_GET(leaf->hdr.count, ARCH_CONVERT);
-		bytes  = state->blocksize - (state->blocksize>>2);
-		bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
-		leaf = bp->data;
-		ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-		count += INT_GET(leaf->hdr.count, ARCH_CONVERT);
-		bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
-		bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
-		bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t);
-		bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t);
-		if (bytes >= 0)
-			break;	/* fits with at least 25% to spare */
-
-		xfs_da_brelse(state->args->trans, bp);
-	}
-	if (i >= 2) {
-		*action = 0;
-		return 0;
-	}
-	xfs_da_buf_done(bp);
-
-	/*
-	 * Make altpath point to the block we want to keep (the lower
-	 * numbered block) and path point to the block we want to drop.
-	 */
-	memcpy(&state->altpath, &state->path, sizeof(state->path));
-	if (blkno < blk->blkno) {
-		error = xfs_da_path_shift(state, &state->altpath, forward,
-						 0, &retval);
-	} else {
-		error = xfs_da_path_shift(state, &state->path, forward,
-						 0, &retval);
-	}
-	if (error)
-		return error;
-	if (retval) {
-		*action = 0;
-	} else {
-		*action = 1;
-	}
-	return 0;
-}
-
-/*
- * Remove a name from the leaf directory structure.
- *
- * Return 1 if leaf is less than 37% full, 0 if >= 37% full.
- * If two leaves are 37% full, when combined they will leave 25% free.
- */
-int
-xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_hdr_t *hdr;
-	xfs_dir_leaf_map_t *map;
-	xfs_dir_leaf_entry_t *entry;
-	xfs_dir_leaf_name_t *namest;
-	int before, after, smallest, entsize;
-	int tablesize, tmp, i;
-	xfs_mount_t *mp;
-
-	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	hdr = &leaf->hdr;
-	mp = trans->t_mountp;
-	ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)));
-	ASSERT((index >= 0) && (index < INT_GET(hdr->count, ARCH_CONVERT)));
-	ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr)));
-	entry = &leaf->entries[index];
-	ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT));
-	ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp));
-
-	/*
-	 * Scan through free region table:
-	 *    check for adjacency of free'd entry with an existing one,
-	 *    find smallest free region in case we need to replace it,
-	 *    adjust any map that borders the entry table,
-	 */
-	tablesize = INT_GET(hdr->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)
-			+ (uint)sizeof(xfs_dir_leaf_hdr_t);
-	map = &hdr->freemap[0];
-	tmp = INT_GET(map->size, ARCH_CONVERT);
-	before = after = -1;
-	smallest = XFS_DIR_LEAF_MAPSIZE - 1;
-	entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry);
-	for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) {
-		ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp));
-		ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp));
-		if (INT_GET(map->base, ARCH_CONVERT) == tablesize) {
-			INT_MOD(map->base, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t)));
-			INT_MOD(map->size, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t));
-		}
-
-		if ((INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)) == INT_GET(entry->nameidx, ARCH_CONVERT)) {
-			before = i;
-		} else if (INT_GET(map->base, ARCH_CONVERT) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) {
-			after = i;
-		} else if (INT_GET(map->size, ARCH_CONVERT) < tmp) {
-			tmp = INT_GET(map->size, ARCH_CONVERT);
-			smallest = i;
-		}
-	}
-
-	/*
-	 * Coalesce adjacent freemap regions,
-	 * or replace the smallest region.
-	 */
-	if ((before >= 0) || (after >= 0)) {
-		if ((before >= 0) && (after >= 0)) {
-			map = &hdr->freemap[before];
-			INT_MOD(map->size, ARCH_CONVERT, entsize);
-			INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT));
-			hdr->freemap[after].base = 0;
-			hdr->freemap[after].size = 0;
-		} else if (before >= 0) {
-			map = &hdr->freemap[before];
-			INT_MOD(map->size, ARCH_CONVERT, entsize);
-		} else {
-			map = &hdr->freemap[after];
-			INT_COPY(map->base, entry->nameidx, ARCH_CONVERT);
-			INT_MOD(map->size, ARCH_CONVERT, entsize);
-		}
-	} else {
-		/*
-		 * Replace smallest region (if it is smaller than free'd entry)
-		 */
-		map = &hdr->freemap[smallest];
-		if (INT_GET(map->size, ARCH_CONVERT) < entsize) {
-			INT_COPY(map->base, entry->nameidx, ARCH_CONVERT);
-			INT_SET(map->size, ARCH_CONVERT, entsize);
-		}
-	}
-
-	/*
-	 * Did we remove the first entry?
-	 */
-	if (INT_GET(entry->nameidx, ARCH_CONVERT) == INT_GET(hdr->firstused, ARCH_CONVERT))
-		smallest = 1;
-	else
-		smallest = 0;
-
-	/*
-	 * Compress the remaining entries and zero out the removed stuff.
-	 */
-	namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
-	memset((char *)namest, 0, entsize);
-	xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize));
-
-	INT_MOD(hdr->namebytes, ARCH_CONVERT, -(entry->namelen));
-	tmp = (INT_GET(hdr->count, ARCH_CONVERT) - index) * (uint)sizeof(xfs_dir_leaf_entry_t);
-	memmove(entry, entry + 1, tmp);
-	INT_MOD(hdr->count, ARCH_CONVERT, -1);
-	xfs_da_log_buf(trans, bp,
-	    XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry)));
-	entry = &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)];
-	memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t));
-
-	/*
-	 * If we removed the first entry, re-find the first used byte
-	 * in the name area.  Note that if the entry was the "firstused",
-	 * then we don't have a "hole" in our block resulting from
-	 * removing the name.
-	 */
-	if (smallest) {
-		tmp = XFS_LBSIZE(mp);
-		entry = &leaf->entries[0];
-		for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) {
-			ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT));
-			ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp));
-			if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp)
-				tmp = INT_GET(entry->nameidx, ARCH_CONVERT);
-		}
-		INT_SET(hdr->firstused, ARCH_CONVERT, tmp);
-		if (!hdr->firstused)
-			INT_SET(hdr->firstused, ARCH_CONVERT, tmp - 1);
-	} else {
-		hdr->holes = 1;		/* mark as needing compaction */
-	}
-
-	xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr)));
-
-	/*
-	 * Check if leaf is less than 50% full, caller may want to
-	 * "join" the leaf with a sibling if so.
-	 */
-	tmp  = (uint)sizeof(xfs_dir_leaf_hdr_t);
-	tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t);
-	tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1);
-	tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT);
-	if (tmp < mp->m_dir_magicpct)
-		return 1;			/* leaf is < 37% full */
-	return 0;
-}
-
-/*
- * Move all the directory entries from drop_leaf into save_leaf.
- */
-void
-xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
-				      xfs_da_state_blk_t *save_blk)
-{
-	xfs_dir_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf;
-	xfs_dir_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr;
-	xfs_mount_t *mp;
-	char *tmpbuffer;
-
-	/*
-	 * Set up environment.
-	 */
-	mp = state->mp;
-	ASSERT(drop_blk->magic == XFS_DIR_LEAF_MAGIC);
-	ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC);
-	drop_leaf = drop_blk->bp->data;
-	save_leaf = save_blk->bp->data;
-	ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	drop_hdr = &drop_leaf->hdr;
-	save_hdr = &save_leaf->hdr;
-
-	/*
-	 * Save last hashval from dying block for later Btree fixup.
-	 */
-	drop_blk->hashval = INT_GET(drop_leaf->entries[ drop_leaf->hdr.count-1 ].hashval, ARCH_CONVERT);
-
-	/*
-	 * Check if we need a temp buffer, or can we do it in place.
-	 * Note that we don't check "leaf" for holes because we will
-	 * always be dropping it, toosmall() decided that for us already.
-	 */
-	if (save_hdr->holes == 0) {
-		/*
-		 * dest leaf has no holes, so we add there.  May need
-		 * to make some room in the entry array.
-		 */
-		if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
-			xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0,
-						 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
-		} else {
-			xfs_dir_leaf_moveents(drop_leaf, 0,
-					      save_leaf, INT_GET(save_hdr->count, ARCH_CONVERT),
-					      (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
-		}
-	} else {
-		/*
-		 * Destination has holes, so we make a temporary copy
-		 * of the leaf and add them both to that.
-		 */
-		tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP);
-		ASSERT(tmpbuffer != NULL);
-		memset(tmpbuffer, 0, state->blocksize);
-		tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer;
-		tmp_hdr = &tmp_leaf->hdr;
-		tmp_hdr->info = save_hdr->info;	/* struct copy */
-		tmp_hdr->count = 0;
-		INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize);
-		if (!tmp_hdr->firstused)
-			INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize - 1);
-		tmp_hdr->namebytes = 0;
-		if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) {
-			xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0,
-						 (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
-			xfs_dir_leaf_moveents(save_leaf, 0,
-					      tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT),
-					      (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp);
-		} else {
-			xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0,
-						 (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp);
-			xfs_dir_leaf_moveents(drop_leaf, 0,
-					      tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT),
-					      (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp);
-		}
-		memcpy(save_leaf, tmp_leaf, state->blocksize);
-		kmem_free(tmpbuffer, state->blocksize);
-	}
-
-	xfs_da_log_buf(state->args->trans, save_blk->bp, 0,
-					   state->blocksize - 1);
-
-	/*
-	 * Copy out last hashval in each block for B-tree code.
-	 */
-	save_blk->hashval = INT_GET(save_leaf->entries[ INT_GET(save_leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT);
-}
-
-/*========================================================================
- * Routines used for finding things in the Btree.
- *========================================================================*/
-
-/*
- * Look up a name in a leaf directory structure.
- * This is the internal routine, it uses the caller's buffer.
- *
- * Note that duplicate keys are allowed, but only check within the
- * current leaf node.  The Btree code must check in adjacent leaf nodes.
- *
- * Return in *index the index into the entry[] array of either the found
- * entry, or where the entry should have been (insert before that entry).
- *
- * Don't change the args->inumber unless we find the filename.
- */
-int
-xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index)
-{
-	xfs_dir_leafblock_t *leaf;
-	xfs_dir_leaf_entry_t *entry;
-	xfs_dir_leaf_name_t *namest;
-	int probe, span;
-	xfs_dahash_t hashval;
-
-	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) < (XFS_LBSIZE(args->dp->i_mount)/8));
-
-	/*
-	 * Binary search.  (note: small blocks will skip this loop)
-	 */
-	hashval = args->hashval;
-	probe = span = INT_GET(leaf->hdr.count, ARCH_CONVERT) / 2;
-	for (entry = &leaf->entries[probe]; span > 4;
-		   entry = &leaf->entries[probe]) {
-		span /= 2;
-		if (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)
-			probe += span;
-		else if (INT_GET(entry->hashval, ARCH_CONVERT) > hashval)
-			probe -= span;
-		else
-			break;
-	}
-	ASSERT((probe >= 0) && \
-	       ((!leaf->hdr.count) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT))));
-	ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval));
-
-	/*
-	 * Since we may have duplicate hashval's, find the first matching
-	 * hashval in the leaf.
-	 */
-	while ((probe > 0) && (INT_GET(entry->hashval, ARCH_CONVERT) >= hashval)) {
-		entry--;
-		probe--;
-	}
-	while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) {
-		entry++;
-		probe++;
-	}
-	if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) {
-		*index = probe;
-		ASSERT(args->oknoent);
-		return XFS_ERROR(ENOENT);
-	}
-
-	/*
-	 * Duplicate keys may be present, so search all of them for a match.
-	 */
-	while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) {
-		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT));
-		if (entry->namelen == args->namelen &&
-		    namest->name[0] == args->name[0] &&
-		    memcmp(args->name, namest->name, args->namelen) == 0) {
-			XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber);
-			*index = probe;
-			return XFS_ERROR(EEXIST);
-		}
-		entry++;
-		probe++;
-	}
-	*index = probe;
-	ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent);
-	return XFS_ERROR(ENOENT);
-}
-
-/*========================================================================
- * Utility routines.
- *========================================================================*/
-
-/*
- * Move the indicated entries from one leaf to another.
- * NOTE: this routine modifies both source and destination leaves.
- */
-/* ARGSUSED */
-STATIC void
-xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s,
-		      xfs_dir_leafblock_t *leaf_d, int start_d,
-		      int count, xfs_mount_t *mp)
-{
-	xfs_dir_leaf_hdr_t *hdr_s, *hdr_d;
-	xfs_dir_leaf_entry_t *entry_s, *entry_d;
-	int tmp, i;
-
-	/*
-	 * Check for nothing to do.
-	 */
-	if (count == 0)
-		return;
-
-	/*
-	 * Set up environment.
-	 */
-	ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	hdr_s = &leaf_s->hdr;
-	hdr_d = &leaf_d->hdr;
-	ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) && (INT_GET(hdr_s->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)));
-	ASSERT(INT_GET(hdr_s->firstused, ARCH_CONVERT) >=
-		((INT_GET(hdr_s->count, ARCH_CONVERT)*sizeof(*entry_s))+sizeof(*hdr_s)));
-	ASSERT(INT_GET(hdr_d->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8));
-	ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >=
-		((INT_GET(hdr_d->count, ARCH_CONVERT)*sizeof(*entry_d))+sizeof(*hdr_d)));
-
-	ASSERT(start_s < INT_GET(hdr_s->count, ARCH_CONVERT));
-	ASSERT(start_d <= INT_GET(hdr_d->count, ARCH_CONVERT));
-	ASSERT(count <= INT_GET(hdr_s->count, ARCH_CONVERT));
-
-	/*
-	 * Move the entries in the destination leaf up to make a hole?
-	 */
-	if (start_d < INT_GET(hdr_d->count, ARCH_CONVERT)) {
-		tmp  = INT_GET(hdr_d->count, ARCH_CONVERT) - start_d;
-		tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
-		entry_s = &leaf_d->entries[start_d];
-		entry_d = &leaf_d->entries[start_d + count];
-		memcpy(entry_d, entry_s, tmp);
-	}
-
-	/*
-	 * Copy all entry's in the same (sorted) order,
-	 * but allocate filenames packed and in sequence.
-	 */
-	entry_s = &leaf_s->entries[start_s];
-	entry_d = &leaf_d->entries[start_d];
-	for (i = 0; i < count; entry_s++, entry_d++, i++) {
-		ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= INT_GET(hdr_s->firstused, ARCH_CONVERT));
-		tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s);
-		INT_MOD(hdr_d->firstused, ARCH_CONVERT, -(tmp));
-		entry_d->hashval = entry_s->hashval; /* INT_: direct copy */
-		INT_COPY(entry_d->nameidx, hdr_d->firstused, ARCH_CONVERT);
-		entry_d->namelen = entry_s->namelen;
-		ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp));
-		memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, INT_GET(entry_d->nameidx, ARCH_CONVERT)),
-		       XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), tmp);
-		ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp));
-		memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)),
-		      0, tmp);
-		INT_MOD(hdr_s->namebytes, ARCH_CONVERT, -(entry_d->namelen));
-		INT_MOD(hdr_d->namebytes, ARCH_CONVERT, entry_d->namelen);
-		INT_MOD(hdr_s->count, ARCH_CONVERT, -1);
-		INT_MOD(hdr_d->count, ARCH_CONVERT, +1);
-		tmp  = INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)
-				+ (uint)sizeof(xfs_dir_leaf_hdr_t);
-		ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= tmp);
-
-	}
-
-	/*
-	 * Zero out the entries we just copied.
-	 */
-	if (start_s == INT_GET(hdr_s->count, ARCH_CONVERT)) {
-		tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
-		entry_s = &leaf_s->entries[start_s];
-		ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
-		memset((char *)entry_s, 0, tmp);
-	} else {
-		/*
-		 * Move the remaining entries down to fill the hole,
-		 * then zero the entries at the top.
-		 */
-		tmp  = INT_GET(hdr_s->count, ARCH_CONVERT) - count;
-		tmp *= (uint)sizeof(xfs_dir_leaf_entry_t);
-		entry_s = &leaf_s->entries[start_s + count];
-		entry_d = &leaf_s->entries[start_s];
-		memcpy(entry_d, entry_s, tmp);
-
-		tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t);
-		entry_s = &leaf_s->entries[INT_GET(hdr_s->count, ARCH_CONVERT)];
-		ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp));
-		memset((char *)entry_s, 0, tmp);
-	}
-
-	/*
-	 * Fill in the freemap information
-	 */
-	INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_hdr_t));
-	INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t));
-	INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT));
-	INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, (hdr_d->freemap[2].base = 0));
-	INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, (hdr_d->freemap[2].size = 0));
-	hdr_s->holes = 1;	/* leaf may not be compact */
-}
-
-/*
- * Compare two leaf blocks "order".
- */
-int
-xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp)
-{
-	xfs_dir_leafblock_t *leaf1, *leaf2;
-
-	leaf1 = leaf1_bp->data;
-	leaf2 = leaf2_bp->data;
-	ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) &&
-	       (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC));
-	if ((INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) &&
-	    ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) <
-	      INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) ||
-	     (INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) <
-	      INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) {
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Pick up the last hashvalue from a leaf block.
- */
-xfs_dahash_t
-xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count)
-{
-	xfs_dir_leafblock_t *leaf;
-
-	leaf = bp->data;
-	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC);
-	if (count)
-		*count = INT_GET(leaf->hdr.count, ARCH_CONVERT);
-	if (!leaf->hdr.count)
-		return(0);
-	return(INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT));
-}
-
-/*
- * Copy out directory entries for getdents(), for leaf directories.
- */
-int
-xfs_dir_leaf_getdents_int(
-	xfs_dabuf_t	*bp,
-	xfs_inode_t	*dp,
-	xfs_dablk_t	bno,
-	uio_t		*uio,
-	int		*eobp,
-	xfs_dirent_t	*dbp,
-	xfs_dir_put_t	put,
-	xfs_daddr_t		nextda)
-{
-	xfs_dir_leafblock_t	*leaf;
-	xfs_dir_leaf_entry_t	*entry;
-	xfs_dir_leaf_name_t	*namest;
-	int			entno, want_entno, i, nextentno;
-	xfs_mount_t		*mp;
-	xfs_dahash_t		cookhash;
-	xfs_dahash_t		nexthash = 0;
-#if (BITS_PER_LONG == 32)
-	xfs_dahash_t		lasthash = XFS_DA_MAXHASH;
-#endif
-	xfs_dir_put_args_t	p;
-
-	mp = dp->i_mount;
-	leaf = bp->data;
-	if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) {
-		*eobp = 1;
-		return XFS_ERROR(ENOENT);	/* XXX wrong code */
-	}
-
-	want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset);
-
-	cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset);
-
-	xfs_dir_trace_g_dul("leaf: start", dp, uio, leaf);
-
-	/*
-	 * Re-find our place.
-	 */
-	for (i = entno = 0, entry = &leaf->entries[0];
-		     i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
-			     entry++, i++) {
-
-		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
-				    INT_GET(entry->nameidx, ARCH_CONVERT));
-
-		if (unlikely(
-		    ((char *)namest < (char *)leaf) ||
-		    ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
-			XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)",
-					     XFS_ERRLEVEL_LOW, mp, leaf);
-			xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
-			return XFS_ERROR(EFSCORRUPTED);
-		}
-		if (INT_GET(entry->hashval, ARCH_CONVERT) >= cookhash) {
-			if (   entno < want_entno
-			    && INT_GET(entry->hashval, ARCH_CONVERT)
-							== cookhash) {
-				/*
-				 * Trying to get to a particular offset in a
-				 * run of equal-hashval entries.
-				 */
-				entno++;
-			} else if (   want_entno > 0
-				   && entno == want_entno
-				   && INT_GET(entry->hashval, ARCH_CONVERT)
-							== cookhash) {
-				break;
-			} else {
-				entno = 0;
-				break;
-			}
-		}
-	}
-
-	if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) {
-		xfs_dir_trace_g_du("leaf: hash not found", dp, uio);
-		if (!leaf->hdr.info.forw)
-			uio->uio_offset =
-				XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH);
-		/*
-		 * Don't set uio_offset if there's another block:
-		 * the node code will be setting uio_offset anyway.
-		 */
-		*eobp = 0;
-		return 0;
-	}
-	xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry);
-
-	p.dbp = dbp;
-	p.put = put;
-	p.uio = uio;
-
-	/*
-	 * We're synchronized, start copying entries out to the user.
-	 */
-	for (; entno >= 0 && i < INT_GET(leaf->hdr.count, ARCH_CONVERT);
-			     entry++, i++, (entno = nextentno)) {
-		int lastresid=0, retval;
-		xfs_dircook_t lastoffset;
-		xfs_dahash_t thishash;
-
-		/*
-		 * Check for a damaged directory leaf block and pick up
-		 * the inode number from this entry.
-		 */
-		namest = XFS_DIR_LEAF_NAMESTRUCT(leaf,
-				    INT_GET(entry->nameidx, ARCH_CONVERT));
-
-		if (unlikely(
-		    ((char *)namest < (char *)leaf) ||
-		    ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) {
-			XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)",
-					     XFS_ERRLEVEL_LOW, mp, leaf);
-			xfs_dir_trace_g_du("leaf: corrupted", dp, uio);
-			return XFS_ERROR(EFSCORRUPTED);
-		}
-
-		xfs_dir_trace_g_duc("leaf: middle cookie  ",
-						   dp, uio, p.cook.o);
-
-		if (i < (INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1)) {
-			nexthash = INT_GET(entry[1].hashval, ARCH_CONVERT);
-
-			if (nexthash == INT_GET(entry->hashval, ARCH_CONVERT))
-				nextentno = entno + 1;
-			else
-				nextentno = 0;
-			XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash);
-			xfs_dir_trace_g_duc("leaf: middle cookie  ",
-						   dp, uio, p.cook.o);
-
-		} else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) {
-			xfs_dabuf_t *bp2;
-			xfs_dir_leafblock_t *leaf2;
-
-			ASSERT(nextda != -1);
-
-			retval = xfs_da_read_buf(dp->i_transp, dp, thishash,
-						 nextda, &bp2, XFS_DATA_FORK);
-			if (retval)
-				return retval;
-
-			ASSERT(bp2 != NULL);
-
-			leaf2 = bp2->data;
-
-			if (unlikely(
-			       (be16_to_cpu(leaf2->hdr.info.magic)
-						!= XFS_DIR_LEAF_MAGIC)
-			    || (be32_to_cpu(leaf2->hdr.info.back)
-						!= bno))) {	/* GROT */
-				XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)",
-						     XFS_ERRLEVEL_LOW, mp,
-						     leaf2);
-				xfs_da_brelse(dp->i_transp, bp2);
-
-				return XFS_ERROR(EFSCORRUPTED);
-			}
-
-			nexthash = INT_GET(leaf2->entries[0].hashval,
-								ARCH_CONVERT);
-			nextentno = -1;
-			XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash);
-			xfs_da_brelse(dp->i_transp, bp2);
-			xfs_dir_trace_g_duc("leaf: next blk cookie",
-						   dp, uio, p.cook.o);
-		} else {
-			nextentno = -1;
-			XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH);
-		}
-
-		/*
-		 * Save off the cookie so we can fall back should the
-		 * 'put' into the outgoing buffer fails.  To handle a run
-		 * of equal-hashvals, the off_t structure on 64bit
-		 * builds has entno built into the cookie to ID the
-		 * entry.  On 32bit builds, we only have space for the
-		 * hashval so we can't ID specific entries within a group
-		 * of same hashval entries.   For this, lastoffset is set
-		 * to the first in the run of equal hashvals so we don't
-		 * include any entries unless we can include all entries
-		 * that share the same hashval.  Hopefully the buffer
-		 * provided is big enough to handle it (see pv763517).
-		 */
-#if (BITS_PER_LONG == 32)
-		if ((thishash = INT_GET(entry->hashval, ARCH_CONVERT))
-								!= lasthash) {
-			XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
-			lastresid = uio->uio_resid;
-			lasthash = thishash;
-		} else {
-			xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped",
-						   dp, uio, p.cook.o);
-		}
-#else
-		thishash = INT_GET(entry->hashval, ARCH_CONVERT);
-		XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash);
-		lastresid = uio->uio_resid;
-#endif /* BITS_PER_LONG == 32 */
-
-		/*
-		 * Put the current entry into the outgoing buffer.  If we fail
-		 * then restore the UIO to the first entry in the current
-		 * run of equal-hashval entries (probably one 1 entry long).
-		 */
-		p.ino = XFS_GET_DIR_INO8(namest->inumber);
-#if XFS_BIG_INUMS
-		p.ino += mp->m_inoadd;
-#endif
-		p.name = (char *)namest->name;
-		p.namelen = entry->namelen;
-
-		retval = p.put(&p);
-
-		if (!p.done) {
-			uio->uio_offset = lastoffset.o;
-			uio->uio_resid = lastresid;
-
-			*eobp = 1;
-
-			xfs_dir_trace_g_du("leaf: E-O-B", dp, uio);
-
-			return retval;
-		}
-	}
-
-	uio->uio_offset = p.cook.o;
-
-	*eobp = 0;
-
-	xfs_dir_trace_g_du("leaf: E-O-F", dp, uio);
-
-	return 0;
-}
-
-/*
- * Format a dirent64 structure and copy it out the the user's buffer.
- */
-int
-xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa)
-{
-	iovec_t *iovp;
-	int reclen, namelen;
-	xfs_dirent_t *idbp;
-	uio_t *uio;
-
-	namelen = pa->namelen;
-	reclen = DIRENTSIZE(namelen);
-	uio = pa->uio;
-	if (reclen > uio->uio_resid) {
-		pa->done = 0;
-		return 0;
-	}
-	iovp = uio->uio_iov;
-	idbp = (xfs_dirent_t *)iovp->iov_base;
-	iovp->iov_base = (char *)idbp + reclen;
-	iovp->iov_len -= reclen;
-	uio->uio_resid -= reclen;
-	idbp->d_reclen = reclen;
-	idbp->d_ino = pa->ino;
-	idbp->d_off = pa->cook.o;
-	idbp->d_name[namelen] = '\0';
-	pa->done = 1;
-	memcpy(idbp->d_name, pa->name, namelen);
-	return 0;
-}
-
-/*
- * Format a dirent64 structure and copy it out the the user's buffer.
- */
-int
-xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa)
-{
-	int		retval, reclen, namelen;
-	xfs_dirent_t	*idbp;
-	uio_t		*uio;
-
-	namelen = pa->namelen;
-	reclen = DIRENTSIZE(namelen);
-	uio = pa->uio;
-	if (reclen > uio->uio_resid) {
-		pa->done = 0;
-		return 0;
-	}
-	idbp = pa->dbp;
-	idbp->d_reclen = reclen;
-	idbp->d_ino = pa->ino;
-	idbp->d_off = pa->cook.o;
-	idbp->d_name[namelen] = '\0';
-	memcpy(idbp->d_name, pa->name, namelen);
-	retval = uio_read((caddr_t)idbp, reclen, uio);
-	pa->done = (retval == 0);
-	return retval;
-}
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
deleted file mode 100644
index eb8cd9a..0000000
--- a/fs/xfs/xfs_dir_leaf.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR_LEAF_H__
-#define	__XFS_DIR_LEAF_H__
-
-/*
- * Directory layout, internal structure, access macros, etc.
- *
- * Large directories are structured around Btrees where all the data
- * elements are in the leaf nodes.  Filenames are hashed into an int,
- * then that int is used as the index into the Btree.  Since the hashval
- * of a filename may not be unique, we may have duplicate keys.  The
- * internal links in the Btree are logical block offsets into the file.
- */
-
-struct uio;
-struct xfs_bmap_free;
-struct xfs_dabuf;
-struct xfs_da_args;
-struct xfs_da_state;
-struct xfs_da_state_blk;
-struct xfs_dir_put_args;
-struct xfs_inode;
-struct xfs_mount;
-struct xfs_trans;
-
-/*========================================================================
- * Directory Structure when equal to XFS_LBSIZE(mp) bytes.
- *========================================================================*/
-
-/*
- * This is the structure of the leaf nodes in the Btree.
- *
- * Struct leaf_entry's are packed from the top.  Names grow from the bottom
- * but are not packed.  The freemap contains run-length-encoded entries
- * for the free bytes after the leaf_entry's, but only the N largest such,
- * smaller runs are dropped.  When the freemap doesn't show enough space
- * for an allocation, we compact the namelist area and try again.  If we
- * still don't have enough space, then we have to split the block.
- *
- * Since we have duplicate hash keys, for each key that matches, compare
- * the actual string.  The root and intermediate node search always takes
- * the first-in-the-block key match found, so we should only have to work
- * "forw"ard.  If none matches, continue with the "forw"ard leaf nodes
- * until the hash key changes or the filename is found.
- *
- * The parent directory and the self-pointer are explicitly represented
- * (ie: there are entries for "." and "..").
- *
- * Note that the count being a __uint16_t limits us to something like a
- * blocksize of 1.3MB in the face of worst case (short) filenames.
- */
-#define XFS_DIR_LEAF_MAPSIZE	3	/* how many freespace slots */
-
-typedef struct xfs_dir_leaf_map {	/* RLE map of free bytes */
-	__uint16_t	base;	 	/* base of free region */
-	__uint16_t	size; 		/* run length of free region */
-} xfs_dir_leaf_map_t;
-
-typedef struct xfs_dir_leaf_hdr {	/* constant-structure header block */
-	xfs_da_blkinfo_t info;		/* block type, links, etc. */
-	__uint16_t	count;		/* count of active leaf_entry's */
-	__uint16_t	namebytes;	/* num bytes of name strings stored */
-	__uint16_t	firstused;	/* first used byte in name area */
-	__uint8_t	holes;		/* != 0 if blk needs compaction */
-	__uint8_t	pad1;
-	xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE];
-} xfs_dir_leaf_hdr_t;
-
-typedef struct xfs_dir_leaf_entry {	/* sorted on key, not name */
-	xfs_dahash_t	hashval;	/* hash value of name */
-	__uint16_t	nameidx;	/* index into buffer of name */
-	__uint8_t	namelen;	/* length of name string */
-	__uint8_t	pad2;
-} xfs_dir_leaf_entry_t;
-
-typedef struct xfs_dir_leaf_name {
-	xfs_dir_ino_t	inumber;	/* inode number for this key */
-	__uint8_t	name[1];	/* name string itself */
-} xfs_dir_leaf_name_t;
-
-typedef struct xfs_dir_leafblock {
-	xfs_dir_leaf_hdr_t	hdr;	/* constant-structure header block */
-	xfs_dir_leaf_entry_t	entries[1];	/* var sized array */
-	xfs_dir_leaf_name_t	namelist[1];	/* grows from bottom of buf */
-} xfs_dir_leafblock_t;
-
-/*
- * Length of name for which a 512-byte block filesystem
- * can get a double split.
- */
-#define	XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN	\
-	(512 - (uint)sizeof(xfs_dir_leaf_hdr_t) - \
-	 (uint)sizeof(xfs_dir_leaf_entry_t) * 2 - \
-	 (uint)sizeof(xfs_dir_leaf_name_t) * 2 - (MAXNAMELEN - 2) + 1 + 1)
-
-typedef int (*xfs_dir_put_t)(struct xfs_dir_put_args *pa);
-
-typedef union {
-	xfs_off_t		o;		/* offset (cookie) */
-	/*
-	 * Watch the order here (endian-ness dependent).
-	 */
-	struct {
-#ifndef XFS_NATIVE_HOST
-		xfs_dahash_t	h;	/* hash value */
-		__uint32_t	be;	/* block and entry */
-#else
-		__uint32_t	be;	/* block and entry */
-		xfs_dahash_t	h;	/* hash value */
-#endif /* XFS_NATIVE_HOST */
-	} s;
-} xfs_dircook_t;
-
-#define	XFS_PUT_COOKIE(c,mp,bno,entry,hash)	\
-	((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash))
-
-typedef struct xfs_dir_put_args {
-	xfs_dircook_t	cook;		/* cookie of (next) entry */
-	xfs_intino_t	ino;		/* inode number */
-	struct xfs_dirent *dbp;		/* buffer pointer */
-	char		*name;		/* directory entry name */
-	int		namelen;	/* length of name */
-	int		done;		/* output: set if value was stored */
-	xfs_dir_put_t	put;		/* put function ptr (i/o) */
-	struct uio	*uio;		/* uio control structure */
-} xfs_dir_put_args_t;
-
-#define XFS_DIR_LEAF_ENTSIZE_BYNAME(len)	\
-	xfs_dir_leaf_entsize_byname(len)
-static inline int xfs_dir_leaf_entsize_byname(int len)
-{
-	return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len;
-}
-
-#define XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry)	\
-	xfs_dir_leaf_entsize_byentry(entry)
-static inline int xfs_dir_leaf_entsize_byentry(xfs_dir_leaf_entry_t *entry)
-{
-	return (uint)sizeof(xfs_dir_leaf_name_t)-1 + (entry)->namelen;
-}
-
-#define XFS_DIR_LEAF_NAMESTRUCT(leafp,offset)	\
-	xfs_dir_leaf_namestruct(leafp,offset)
-static inline xfs_dir_leaf_name_t *
-xfs_dir_leaf_namestruct(xfs_dir_leafblock_t *leafp, int offset)
-{
-	return (xfs_dir_leaf_name_t *)&((char *)(leafp))[offset];
-}
-
-/*========================================================================
- * Function prototypes for the kernel.
- *========================================================================*/
-
-/*
- * Internal routines when dirsize < XFS_LITINO(mp).
- */
-int xfs_dir_shortform_create(struct xfs_da_args *args, xfs_ino_t parent);
-int xfs_dir_shortform_addname(struct xfs_da_args *args);
-int xfs_dir_shortform_lookup(struct xfs_da_args *args);
-int xfs_dir_shortform_to_leaf(struct xfs_da_args *args);
-int xfs_dir_shortform_removename(struct xfs_da_args *args);
-int xfs_dir_shortform_getdents(struct xfs_inode *dp, struct uio *uio, int *eofp,
-			       struct xfs_dirent *dbp, xfs_dir_put_t put);
-int xfs_dir_shortform_replace(struct xfs_da_args *args);
-
-/*
- * Internal routines when dirsize == XFS_LBSIZE(mp).
- */
-int xfs_dir_leaf_to_node(struct xfs_da_args *args);
-int xfs_dir_leaf_to_shortform(struct xfs_da_args *args);
-
-/*
- * Routines used for growing the Btree.
- */
-int	xfs_dir_leaf_split(struct xfs_da_state *state,
-				  struct xfs_da_state_blk *oldblk,
-				  struct xfs_da_state_blk *newblk);
-int	xfs_dir_leaf_add(struct xfs_dabuf *leaf_buffer,
-				struct xfs_da_args *args, int insertion_index);
-int	xfs_dir_leaf_addname(struct xfs_da_args *args);
-int	xfs_dir_leaf_lookup_int(struct xfs_dabuf *leaf_buffer,
-				       struct xfs_da_args *args,
-				       int *index_found_at);
-int	xfs_dir_leaf_remove(struct xfs_trans *trans,
-				   struct xfs_dabuf *leaf_buffer,
-				   int index_to_remove);
-int	xfs_dir_leaf_getdents_int(struct xfs_dabuf *bp, struct xfs_inode *dp,
-					 xfs_dablk_t bno, struct uio *uio,
-					 int *eobp, struct xfs_dirent *dbp,
-					 xfs_dir_put_t put, xfs_daddr_t nextda);
-
-/*
- * Routines used for shrinking the Btree.
- */
-int	xfs_dir_leaf_toosmall(struct xfs_da_state *state, int *retval);
-void	xfs_dir_leaf_unbalance(struct xfs_da_state *state,
-					     struct xfs_da_state_blk *drop_blk,
-					     struct xfs_da_state_blk *save_blk);
-
-/*
- * Utility routines.
- */
-uint	xfs_dir_leaf_lasthash(struct xfs_dabuf *bp, int *count);
-int	xfs_dir_leaf_order(struct xfs_dabuf *leaf1_bp,
-				  struct xfs_dabuf *leaf2_bp);
-int	xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa);
-int	xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa);
-int	xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
-
-/*
- * Global data.
- */
-extern xfs_dahash_t	xfs_dir_hash_dot, xfs_dir_hash_dotdot;
-
-#endif /* __XFS_DIR_LEAF_H__ */
diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h
deleted file mode 100644
index 5b20b4d..0000000
--- a/fs/xfs/xfs_dir_sf.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (c) 2000,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef __XFS_DIR_SF_H__
-#define	__XFS_DIR_SF_H__
-
-/*
- * Directory layout when stored internal to an inode.
- *
- * Small directories are packed as tightly as possible so as to
- * fit into the literal area of the inode.
- */
-
-typedef struct { __uint8_t i[sizeof(xfs_ino_t)]; } xfs_dir_ino_t;
-
-/*
- * The parent directory has a dedicated field, and the self-pointer must
- * be calculated on the fly.
- *
- * Entries are packed toward the top as tight as possible.  The header
- * and the elements much be memcpy'd out into a work area to get correct
- * alignment for the inode number fields.
- */
-typedef struct xfs_dir_sf_hdr {		/* constant-structure header block */
-	xfs_dir_ino_t	parent;		/* parent dir inode number */
-	__uint8_t	count;		/* count of active entries */
-} xfs_dir_sf_hdr_t;
-
-typedef struct xfs_dir_sf_entry {
-	xfs_dir_ino_t	inumber;	/* referenced inode number */
-	__uint8_t	namelen;	/* actual length of name (no NULL) */
-	__uint8_t	name[1];	/* name */
-} xfs_dir_sf_entry_t;
-
-typedef struct xfs_dir_shortform {
-	xfs_dir_sf_hdr_t	hdr;
-	xfs_dir_sf_entry_t	list[1];	/* variable sized array */
-} xfs_dir_shortform_t;
-
-/*
- * We generate this then sort it, so that readdirs are returned in
- * hash-order.  Else seekdir won't work.
- */
-typedef struct xfs_dir_sf_sort {
-	__uint8_t	entno;		/* .=0, ..=1, else entry# + 2 */
-	__uint8_t	seqno;		/* sequence # with same hash value */
-	__uint8_t	namelen;	/* length of name value (no null) */
-	xfs_dahash_t	hash;		/* this entry's hash value */
-	xfs_intino_t	ino;		/* this entry's inode number */
-	char		*name;		/* name value, pointer into buffer */
-} xfs_dir_sf_sort_t;
-
-#define	XFS_DIR_SF_GET_DIRINO(from,to)	xfs_dir_sf_get_dirino(from, to)
-static inline void xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to)
-{
-	*(to) = XFS_GET_DIR_INO8(*from);
-}
-
-#define	XFS_DIR_SF_PUT_DIRINO(from,to)	xfs_dir_sf_put_dirino(from, to)
-static inline void xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to)
-{
-	XFS_PUT_DIR_INO8(*(from), *(to));
-}
-
-#define XFS_DIR_SF_ENTSIZE_BYNAME(len)	xfs_dir_sf_entsize_byname(len)
-static inline int xfs_dir_sf_entsize_byname(int len)
-{
-	return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (len);
-}
-
-#define XFS_DIR_SF_ENTSIZE_BYENTRY(sfep)	xfs_dir_sf_entsize_byentry(sfep)
-static inline int xfs_dir_sf_entsize_byentry(xfs_dir_sf_entry_t *sfep)
-{
-	return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (sfep)->namelen;
-}
-
-#define XFS_DIR_SF_NEXTENTRY(sfep)		xfs_dir_sf_nextentry(sfep)
-static inline xfs_dir_sf_entry_t *xfs_dir_sf_nextentry(xfs_dir_sf_entry_t *sfep)
-{
-	return (xfs_dir_sf_entry_t *) \
-		((char *)(sfep) + XFS_DIR_SF_ENTSIZE_BYENTRY(sfep));
-}
-
-#define XFS_DIR_SF_ALLFIT(count,totallen)	\
-	xfs_dir_sf_allfit(count,totallen)
-static inline int xfs_dir_sf_allfit(int count, int totallen)
-{
-	return ((uint)sizeof(xfs_dir_sf_hdr_t) + \
-	       ((uint)sizeof(xfs_dir_sf_entry_t)-1)*(count) + (totallen));
-}
-
-#if defined(XFS_DIR_TRACE)
-
-/*
- * Kernel tracing support for directories.
- */
-struct uio;
-struct xfs_inode;
-struct xfs_da_intnode;
-struct xfs_dinode;
-struct xfs_dir_leafblock;
-struct xfs_dir_leaf_entry;
-
-#define	XFS_DIR_TRACE_SIZE	4096	/* size of global trace buffer */
-extern ktrace_t	*xfs_dir_trace_buf;
-
-/*
- * Trace record types.
- */
-#define	XFS_DIR_KTRACE_G_DU	1	/* dp, uio */
-#define	XFS_DIR_KTRACE_G_DUB	2	/* dp, uio, bno */
-#define	XFS_DIR_KTRACE_G_DUN	3	/* dp, uio, node */
-#define	XFS_DIR_KTRACE_G_DUL	4	/* dp, uio, leaf */
-#define	XFS_DIR_KTRACE_G_DUE	5	/* dp, uio, leaf entry */
-#define	XFS_DIR_KTRACE_G_DUC	6	/* dp, uio, cookie */
-
-void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio);
-void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio,
-			      xfs_dablk_t bno);
-void xfs_dir_trace_g_dun(char *where, struct xfs_inode *dp, struct uio *uio,
-			      struct xfs_da_intnode *node);
-void xfs_dir_trace_g_dul(char *where, struct xfs_inode *dp, struct uio *uio,
-			      struct xfs_dir_leafblock *leaf);
-void xfs_dir_trace_g_due(char *where, struct xfs_inode *dp, struct uio *uio,
-			      struct xfs_dir_leaf_entry *entry);
-void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio,
-			      xfs_off_t cookie);
-void xfs_dir_trace_enter(int type, char *where,
-			     void *a0, void *a1, void *a2, void *a3,
-			     void *a4, void *a5, void *a6, void *a7,
-			     void *a8, void *a9, void *a10, void *a11);
-#else
-#define	xfs_dir_trace_g_du(w,d,u)
-#define	xfs_dir_trace_g_dub(w,d,u,b)
-#define	xfs_dir_trace_g_dun(w,d,u,n)
-#define	xfs_dir_trace_g_dul(w,d,u,l)
-#define	xfs_dir_trace_g_due(w,d,u,e)
-#define	xfs_dir_trace_g_duc(w,d,u,c)
-#endif /* DEBUG */
-
-#endif	/* __XFS_DIR_SF_H__ */
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 00b1540..4e7865a 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -189,6 +189,6 @@
 #define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0)
 
 
-extern struct bhv_vfsops xfs_dmops;
+extern struct bhv_module_vfsops xfs_dmops;
 
 #endif  /* __XFS_DMAPI_H__ */
diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c
index 629795b..1e4a35d 100644
--- a/fs/xfs/xfs_dmops.c
+++ b/fs/xfs/xfs_dmops.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 2a21c50..b95681b 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -22,12 +22,10 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index f19282e..6cf6d87 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_buf_item.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_trans_priv.h"
@@ -294,6 +293,62 @@
 }
 
 /*
+ * Copy an EFI format buffer from the given buf, and into the destination
+ * EFI format structure.
+ * The given buffer can be in 32 bit or 64 bit form (which has different padding),
+ * one of which will be the native format for this kernel.
+ * It will handle the conversion of formats if necessary.
+ */
+int
+xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt)
+{
+	xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr;
+	uint i;
+	uint len = sizeof(xfs_efi_log_format_t) + 
+		(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t);  
+	uint len32 = sizeof(xfs_efi_log_format_32_t) + 
+		(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t);  
+	uint len64 = sizeof(xfs_efi_log_format_64_t) + 
+		(src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t);  
+
+	if (buf->i_len == len) {
+		memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len);
+		return 0;
+	} else if (buf->i_len == len32) {
+		xfs_efi_log_format_32_t *src_efi_fmt_32 =
+			(xfs_efi_log_format_32_t *)buf->i_addr;
+
+		dst_efi_fmt->efi_type     = src_efi_fmt_32->efi_type;
+		dst_efi_fmt->efi_size     = src_efi_fmt_32->efi_size;
+		dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents;
+		dst_efi_fmt->efi_id       = src_efi_fmt_32->efi_id;
+		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
+			dst_efi_fmt->efi_extents[i].ext_start =
+				src_efi_fmt_32->efi_extents[i].ext_start;
+			dst_efi_fmt->efi_extents[i].ext_len =
+				src_efi_fmt_32->efi_extents[i].ext_len;
+		}
+		return 0;
+	} else if (buf->i_len == len64) {
+		xfs_efi_log_format_64_t *src_efi_fmt_64 =
+			(xfs_efi_log_format_64_t *)buf->i_addr;
+
+		dst_efi_fmt->efi_type     = src_efi_fmt_64->efi_type;
+		dst_efi_fmt->efi_size     = src_efi_fmt_64->efi_size;
+		dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents;
+		dst_efi_fmt->efi_id       = src_efi_fmt_64->efi_id;
+		for (i = 0; i < dst_efi_fmt->efi_nextents; i++) {
+			dst_efi_fmt->efi_extents[i].ext_start =
+				src_efi_fmt_64->efi_extents[i].ext_start;
+			dst_efi_fmt->efi_extents[i].ext_len =
+				src_efi_fmt_64->efi_extents[i].ext_len;
+		}
+		return 0;
+	}
+	return EFSCORRUPTED;
+}
+
+/*
  * This is called by the efd item code below to release references to
  * the given efi item.  Each efd calls this with the number of
  * extents that it has logged, and when the sum of these reaches
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 5bf6817..0ea45ed 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -27,6 +27,24 @@
 } xfs_extent_t;
 
 /*
+ * Since an xfs_extent_t has types (start:64, len: 32)
+ * there are different alignments on 32 bit and 64 bit kernels.
+ * So we provide the different variants for use by a
+ * conversion routine.
+ */
+
+typedef struct xfs_extent_32 {
+	xfs_dfsbno_t	ext_start;
+	xfs_extlen_t	ext_len;
+} __attribute__((packed)) xfs_extent_32_t;
+
+typedef struct xfs_extent_64 {
+	xfs_dfsbno_t	ext_start;
+	xfs_extlen_t	ext_len;
+	__uint32_t	ext_pad;
+} xfs_extent_64_t;
+
+/*
  * This is the structure used to lay out an efi log item in the
  * log.  The efi_extents field is a variable size array whose
  * size is given by efi_nextents.
@@ -39,6 +57,22 @@
 	xfs_extent_t		efi_extents[1];	/* array of extents to free */
 } xfs_efi_log_format_t;
 
+typedef struct xfs_efi_log_format_32 {
+	unsigned short		efi_type;	/* efi log item type */
+	unsigned short		efi_size;	/* size of this item */
+	uint			efi_nextents;	/* # extents to free */
+	__uint64_t		efi_id;		/* efi identifier */
+	xfs_extent_32_t		efi_extents[1];	/* array of extents to free */
+} __attribute__((packed)) xfs_efi_log_format_32_t;
+
+typedef struct xfs_efi_log_format_64 {
+	unsigned short		efi_type;	/* efi log item type */
+	unsigned short		efi_size;	/* size of this item */
+	uint			efi_nextents;	/* # extents to free */
+	__uint64_t		efi_id;		/* efi identifier */
+	xfs_extent_64_t		efi_extents[1];	/* array of extents to free */
+} xfs_efi_log_format_64_t;
+
 /*
  * This is the structure used to lay out an efd log item in the
  * log.  The efd_extents array is a variable size array whose
@@ -52,6 +86,22 @@
 	xfs_extent_t		efd_extents[1];	/* array of extents freed */
 } xfs_efd_log_format_t;
 
+typedef struct xfs_efd_log_format_32 {
+	unsigned short		efd_type;	/* efd log item type */
+	unsigned short		efd_size;	/* size of this item */
+	uint			efd_nextents;	/* # of extents freed */
+	__uint64_t		efd_efi_id;	/* id of corresponding efi */
+	xfs_extent_32_t		efd_extents[1];	/* array of extents freed */
+} __attribute__((packed)) xfs_efd_log_format_32_t;
+
+typedef struct xfs_efd_log_format_64 {
+	unsigned short		efd_type;	/* efd log item type */
+	unsigned short		efd_size;	/* size of this item */
+	uint			efd_nextents;	/* # of extents freed */
+	__uint64_t		efd_efi_id;	/* id of corresponding efi */
+	xfs_extent_64_t		efd_extents[1];	/* array of extents freed */
+} xfs_efd_log_format_64_t;
+
 
 #ifdef __KERNEL__
 
@@ -103,7 +153,8 @@
 xfs_efi_log_item_t	*xfs_efi_init(struct xfs_mount *, uint);
 xfs_efd_log_item_t	*xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
 				      uint);
-
+int			xfs_efi_copy_format(xfs_log_iovec_t *buf,
+					    xfs_efi_log_format_t *dst_efi_fmt);
 void			xfs_efi_item_free(xfs_efi_log_item_t *);
 
 #endif	/* __KERNEL__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 14010f1..0f0ad15 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -67,14 +67,15 @@
 #define XFS_XFLAG_NOSYMLINKS	0x00000400	/* disallow symlink creation */
 #define XFS_XFLAG_EXTSIZE	0x00000800	/* extent size allocator hint */
 #define XFS_XFLAG_EXTSZINHERIT	0x00001000	/* inherit inode extent size */
+#define XFS_XFLAG_NODEFRAG	0x00002000  	/* do not defragment */
 #define XFS_XFLAG_HASATTR	0x80000000	/* no DIFLAG for this	*/
 
 /*
  * Structure for XFS_IOC_GETBMAP.
  * On input, fill in bmv_offset and bmv_length of the first structure
- * to indicate the area of interest in the file, and bmv_entry with the
- * number of array elements given.  The first structure is updated on
- * return to give the offset and length for the next call.
+ * to indicate the area of interest in the file, and bmv_entries with
+ * the number of array elements given back.  The first structure is
+ * updated on return to give the offset and length for the next call.
  */
 #ifndef HAVE_GETBMAP
 struct getbmap {
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index dfa3527..077629b 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -542,14 +540,13 @@
 }
 
 void
-xfs_fs_log_dummy(xfs_mount_t *mp)
+xfs_fs_log_dummy(
+	xfs_mount_t	*mp)
 {
-	xfs_trans_t *tp;
-	xfs_inode_t *ip;
-
+	xfs_trans_t	*tp;
+	xfs_inode_t	*ip;
 
 	tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
-	atomic_inc(&mp->m_active_trans);
 	if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
 		xfs_trans_cancel(tp, 0);
 		return;
@@ -574,21 +571,22 @@
 {
 	switch (inflags) {
 	case XFS_FSOP_GOING_FLAGS_DEFAULT: {
-		struct vfs *vfsp = XFS_MTOVFS(mp);
+		struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
 		struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev);
 
 		if (sb && !IS_ERR(sb)) {
-			xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+			xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
 			thaw_bdev(sb->s_bdev, sb);
 		}
 	
 		break;
 	}
 	case XFS_FSOP_GOING_FLAGS_LOGFLUSH:
-		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT);
+		xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT);
 		break;
 	case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH:
-		xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR);
+		xfs_force_shutdown(mp,
+				SHUTDOWN_FORCE_UMOUNT | SHUTDOWN_LOG_IO_ERROR);
 		break;
 	default:
 		return XFS_ERROR(EINVAL);
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index deddbd0..33164a8 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -1174,6 +1172,9 @@
 	if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||
 	    ino != XFS_AGINO_TO_INO(mp, agno, agino)) {
 #ifdef DEBUG
+		/* no diagnostics for bulkstat, ino comes from userspace */
+		if (flags & XFS_IMAP_BULKSTAT)
+			return XFS_ERROR(EINVAL);
 		if (agno >= mp->m_sb.sb_agcount) {
 			xfs_fs_cmn_err(CE_ALERT, mp,
 					"xfs_dilocate: agno (%d) >= "
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 60c65683..616eeeb 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index b538543..0724df7 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -186,7 +184,7 @@
  */
 STATIC int
 xfs_iget_core(
-	vnode_t		*vp,
+	bhv_vnode_t	*vp,
 	xfs_mount_t	*mp,
 	xfs_trans_t	*tp,
 	xfs_ino_t	ino,
@@ -198,7 +196,7 @@
 	xfs_ihash_t	*ih;
 	xfs_inode_t	*ip;
 	xfs_inode_t	*iq;
-	vnode_t		*inode_vp;
+	bhv_vnode_t	*inode_vp;
 	ulong		version;
 	int		error;
 	/* REFERENCED */
@@ -468,7 +466,7 @@
 	 * If we have a real type for an on-disk inode, we can set ops(&unlock)
 	 * now.	 If it's a new inode being created, xfs_ialloc will handle it.
 	 */
-	VFS_INIT_VNODE(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
+	bhv_vfs_init_vnode(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1);
 
 	return 0;
 }
@@ -489,7 +487,7 @@
 	xfs_daddr_t	bno)
 {
 	struct inode	*inode;
-	vnode_t		*vp = NULL;
+	bhv_vnode_t	*vp = NULL;
 	int		error;
 
 	XFS_STATS_INC(xs_ig_attempts);
@@ -543,7 +541,7 @@
 void
 xfs_inode_lock_init(
 	xfs_inode_t	*ip,
-	vnode_t		*vp)
+	bhv_vnode_t	*vp)
 {
 	mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
 		     "xfsino", (long)vp->v_number);
@@ -603,12 +601,10 @@
 xfs_iput(xfs_inode_t	*ip,
 	 uint		lock_flags)
 {
-	vnode_t	*vp = XFS_ITOV(ip);
+	bhv_vnode_t	*vp = XFS_ITOV(ip);
 
 	vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address);
-
 	xfs_iunlock(ip, lock_flags);
-
 	VN_RELE(vp);
 }
 
@@ -619,7 +615,7 @@
 xfs_iput_new(xfs_inode_t	*ip,
 	     uint		lock_flags)
 {
-	vnode_t		*vp = XFS_ITOV(ip);
+	bhv_vnode_t	*vp = XFS_ITOV(ip);
 	struct inode	*inode = vn_to_inode(vp);
 
 	vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address);
@@ -645,7 +641,7 @@
 void
 xfs_ireclaim(xfs_inode_t *ip)
 {
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	/*
 	 * Remove from old hash list and mount list.
@@ -1033,6 +1029,6 @@
 void
 xfs_ifunlock(xfs_inode_t *ip)
 {
-	ASSERT(valusema(&(ip->i_flock)) <= 0);
+	ASSERT(issemalocked(&(ip->i_flock)));
 	vsema(&(ip->i_flock));
 }
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 94b60dd0..86c1bf0 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -26,14 +26,12 @@
 #include "xfs_trans_priv.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -256,13 +254,11 @@
 	xfs_daddr_t	bno,
 	uint		imap_flags)
 {
+	xfs_imap_t	imap;
 	xfs_buf_t	*bp;
 	int		error;
-	xfs_imap_t	imap;
-#ifdef __KERNEL__
 	int		i;
 	int		ni;
-#endif
 
 	if (ip->i_blkno == (xfs_daddr_t)0) {
 		/*
@@ -319,7 +315,6 @@
 	 */
 	error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno,
 				   (int)imap.im_len, XFS_BUF_LOCK, &bp);
-
 	if (error) {
 #ifdef DEBUG
 		xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: "
@@ -330,17 +325,21 @@
 #endif /* DEBUG */
 		return error;
 	}
-#ifdef __KERNEL__
+
 	/*
 	 * Validate the magic number and version of every inode in the buffer
 	 * (if DEBUG kernel) or the first inode in the buffer, otherwise.
+	 * No validation is done here in userspace (xfs_repair).
 	 */
-#ifdef DEBUG
+#if !defined(__KERNEL__)
+	ni = 0;
+#elif defined(DEBUG)
 	ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 :
 		(BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog);
-#else
+#else	/* usual case */
 	ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1;
 #endif
+
 	for (i = 0; i < ni; i++) {
 		int		di_ok;
 		xfs_dinode_t	*dip;
@@ -352,8 +351,11 @@
 		if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP,
 				 XFS_RANDOM_ITOBP_INOTOBP))) {
 #ifdef DEBUG
-			prdev("bad inode magic/vsn daddr %lld #%d (magic=%x)",
-				mp->m_ddev_targp,
+			if (!(imap_flags & XFS_IMAP_BULKSTAT))
+				cmn_err(CE_ALERT,
+					"Device %s - bad inode magic/vsn "
+					"daddr %lld #%d (magic=%x)",
+				XFS_BUFTARG_NAME(mp->m_ddev_targp),
 				(unsigned long long)imap.im_blkno, i,
 				INT_GET(dip->di_core.di_magic, ARCH_CONVERT));
 #endif
@@ -363,7 +365,6 @@
 			return XFS_ERROR(EFSCORRUPTED);
 		}
 	}
-#endif	/* __KERNEL__ */
 
 	xfs_inobp_check(mp, bp);
 
@@ -782,7 +783,6 @@
 
 STATIC uint
 _xfs_dic2xflags(
-	xfs_dinode_core_t	*dic,
 	__uint16_t		di_flags)
 {
 	uint			flags = 0;
@@ -812,6 +812,8 @@
 			flags |= XFS_XFLAG_EXTSIZE;
 		if (di_flags & XFS_DIFLAG_EXTSZINHERIT)
 			flags |= XFS_XFLAG_EXTSZINHERIT;
+		if (di_flags & XFS_DIFLAG_NODEFRAG)
+			flags |= XFS_XFLAG_NODEFRAG;
 	}
 
 	return flags;
@@ -823,16 +825,16 @@
 {
 	xfs_dinode_core_t	*dic = &ip->i_d;
 
-	return _xfs_dic2xflags(dic, dic->di_flags) |
-		(XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
+	return _xfs_dic2xflags(dic->di_flags) |
+				(XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
 }
 
 uint
 xfs_dic2xflags(
 	xfs_dinode_core_t	*dic)
 {
-	return _xfs_dic2xflags(dic, INT_GET(dic->di_flags, ARCH_CONVERT)) |
-		(XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
+	return _xfs_dic2xflags(INT_GET(dic->di_flags, ARCH_CONVERT)) |
+				(XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
 }
 
 /*
@@ -1083,7 +1085,7 @@
 {
 	xfs_ino_t	ino;
 	xfs_inode_t	*ip;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 	uint		flags;
 	int		error;
 
@@ -1221,6 +1223,9 @@
 				di_flags |= XFS_DIFLAG_NOSYMLINKS;
 			if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
 				di_flags |= XFS_DIFLAG_PROJINHERIT;
+			if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) &&
+			    xfs_inherit_nodefrag)
+				di_flags |= XFS_DIFLAG_NODEFRAG;
 			ip->i_d.di_flags |= di_flags;
 		}
 		/* FALLTHROUGH */
@@ -1244,8 +1249,8 @@
 	 */
 	xfs_trans_log_inode(tp, ip, flags);
 
-	/* now that we have an i_mode  we can set Linux inode ops (& unlock) */
-	VFS_INIT_VNODE(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1);
+	/* now that we have an i_mode we can setup inode ops and unlock */
+	bhv_vfs_init_vnode(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1);
 
 	*ipp = ip;
 	return 0;
@@ -1285,7 +1290,7 @@
 				       (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) -
 			  map_first),
 			 XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps,
-			 NULL))
+			 NULL, NULL))
 	    return;
 	ASSERT(nimaps == 1);
 	ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK);
@@ -1421,7 +1426,7 @@
 	xfs_fsize_t	last_byte;
 	xfs_off_t	toss_start;
 	xfs_mount_t	*mp;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0);
 	ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size));
@@ -1434,9 +1439,9 @@
 	vn_iowait(vp);  /* wait for the completion of any pending DIOs */
 	
 	/*
-	 * Call VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES() to get rid of pages and buffers
+	 * Call toss_pages or flushinval_pages to get rid of pages
 	 * overlapping the region being removed.  We have to use
-	 * the less efficient VOP_FLUSHINVAL_PAGES() in the case that the
+	 * the less efficient flushinval_pages in the case that the
 	 * caller may not be able to finish the truncate without
 	 * dropping the inode's I/O lock.  Make sure
 	 * to catch any pages brought in by buffers overlapping
@@ -1445,10 +1450,10 @@
 	 * so that we don't toss things on the same block as
 	 * new_size but before it.
 	 *
-	 * Before calling VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES(), make sure to
+	 * Before calling toss_page or flushinval_pages, make sure to
 	 * call remapf() over the same region if the file is mapped.
 	 * This frees up mapped file references to the pages in the
-	 * given range and for the VOP_FLUSHINVAL_PAGES() case it ensures
+	 * given range and for the flushinval_pages case it ensures
 	 * that we get the latest mapped changes flushed out.
 	 */
 	toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size);
@@ -1466,9 +1471,9 @@
 			 last_byte);
 	if (last_byte > toss_start) {
 		if (flags & XFS_ITRUNC_DEFINITE) {
-			VOP_TOSS_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED);
+			bhv_vop_toss_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
 		} else {
-			VOP_FLUSHINVAL_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED);
+			bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED);
 		}
 	}
 
@@ -1666,12 +1671,13 @@
 		 * runs.
 		 */
 		XFS_BMAP_INIT(&free_list, &first_block);
-		error = xfs_bunmapi(ntp, ip, first_unmap_block,
-				    unmap_len,
+		error = XFS_BUNMAPI(mp, ntp, &ip->i_iocore,
+				    first_unmap_block, unmap_len,
 				    XFS_BMAPI_AFLAG(fork) |
 				      (sync ? 0 : XFS_BMAPI_ASYNC),
 				    XFS_ITRUNC_MAX_EXTENTS,
-				    &first_block, &free_list, &done);
+				    &first_block, &free_list,
+				    NULL, &done);
 		if (error) {
 			/*
 			 * If the bunmapi call encounters an error,
@@ -1955,9 +1961,9 @@
 	xfs_agino_t	agino;
 	xfs_agino_t	next_agino;
 	xfs_buf_t	*last_ibp;
-	xfs_dinode_t	*last_dip;
+	xfs_dinode_t	*last_dip = NULL;
 	short		bucket_index;
-	int		offset, last_offset;
+	int		offset, last_offset = 0;
 	int		error;
 	int		agi_ok;
 
@@ -2745,13 +2751,14 @@
 		 * the inode to become unpinned.
 		 */
 		if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) {
-			vnode_t	*vp = XFS_ITOV_NULL(ip);
+			bhv_vnode_t	*vp = XFS_ITOV_NULL(ip);
 
 			/* make sync come back and flush this inode */
 			if (vp) {
 				struct inode	*inode = vn_to_inode(vp);
 
-				if (!(inode->i_state & I_NEW))
+				if (!(inode->i_state &
+						(I_NEW|I_FREEING|I_CLEAR)))
 					mark_inode_dirty_sync(inode);
 			}
 		}
@@ -2916,13 +2923,6 @@
 			ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
 			memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
 		}
-		if (whichfork == XFS_DATA_FORK) {
-			if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) {
-				XFS_ERROR_REPORT("xfs_iflush_fork",
-						 XFS_ERRLEVEL_LOW, mp);
-				return XFS_ERROR(EFSCORRUPTED);
-			}
-		}
 		break;
 
 	case XFS_DINODE_FMT_EXTENTS:
@@ -3006,7 +3006,7 @@
 	XFS_STATS_INC(xs_iflush_count);
 
 	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
-	ASSERT(valusema(&ip->i_flock) <= 0);
+	ASSERT(issemalocked(&(ip->i_flock)));
 	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
 	       ip->i_d.di_nextents > ip->i_df.if_ext_max);
 
@@ -3199,7 +3199,7 @@
 
 corrupt_out:
 	xfs_buf_relse(bp);
-	xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
+	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 	xfs_iflush_abort(ip);
 	/*
 	 * Unlocks the flush lock
@@ -3221,7 +3221,7 @@
 		xfs_buf_relse(bp);
 	}
 
-	xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
+	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 
 	if(!bufwasdelwri)  {
 		/*
@@ -3264,7 +3264,7 @@
 	SPLDECL(s);
 
 	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS));
-	ASSERT(valusema(&ip->i_flock) <= 0);
+	ASSERT(issemalocked(&(ip->i_flock)));
 	ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE ||
 	       ip->i_d.di_nextents > ip->i_df.if_ext_max);
 
@@ -3504,7 +3504,7 @@
 	xfs_mount_t	*mp)
 {
 	xfs_inode_t	*ip;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
  again:
 	XFS_MOUNT_ILOCK(mp);
@@ -4180,7 +4180,7 @@
 	 */
 	memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents,
 		nextents * sizeof(xfs_bmbt_rec_t));
-	kmem_free(ifp->if_u1.if_extents, KM_SLEEP);
+	kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes);
 	ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext;
 	ifp->if_real_bytes = 0;
 }
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 3b544db..d10b76e 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -102,9 +102,9 @@
 
 #ifdef __KERNEL__
 struct bhv_desc;
+struct bhv_vnode;
 struct cred;
 struct ktrace;
-struct vnode;
 struct xfs_buf;
 struct xfs_bmap_free;
 struct xfs_bmbt_irec;
@@ -400,7 +400,7 @@
 void		xfs_chash_free(struct xfs_mount *);
 xfs_inode_t	*xfs_inode_incore(struct xfs_mount *, xfs_ino_t,
 				  struct xfs_trans *);
-void            xfs_inode_lock_init(xfs_inode_t *, struct vnode *);
+void            xfs_inode_lock_init(xfs_inode_t *, struct bhv_vnode *);
 int		xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
 			 uint, uint, xfs_inode_t **, xfs_daddr_t);
 void		xfs_iput(xfs_inode_t *, uint);
@@ -461,7 +461,7 @@
 xfs_fsize_t	xfs_file_last_byte(xfs_inode_t *);
 void		xfs_lock_inodes(xfs_inode_t **, int, int, uint);
 
-xfs_inode_t	*xfs_vtoi(struct vnode *vp);
+xfs_inode_t	*xfs_vtoi(struct bhv_vnode *vp);
 
 void		xfs_synchronize_atime(xfs_inode_t *);
 
@@ -509,7 +509,6 @@
 extern struct kmem_zone	*xfs_ifork_zone;
 extern struct kmem_zone	*xfs_inode_zone;
 extern struct kmem_zone	*xfs_ili_zone;
-extern struct vnodeops	xfs_vnodeops;
 
 #endif	/* __KERNEL__ */
 
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 7497a48..f8e80d8 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -25,7 +25,6 @@
 #include "xfs_buf_item.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -33,7 +32,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -794,7 +792,7 @@
 	 * inode flush completed and the inode was taken off the AIL.
 	 * So, just get out.
 	 */
-	if ((valusema(&(ip->i_flock)) > 0)  ||
+	if (!issemalocked(&(ip->i_flock)) ||
 	    ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) {
 		iip->ili_pushbuf_flag = 0;
 		xfs_iunlock(ip, XFS_ILOCK_SHARED);
@@ -816,7 +814,7 @@
 			 * If not, we can flush it async.
 			 */
 			dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) &&
-				  (valusema(&(ip->i_flock)) <= 0));
+				  issemalocked(&(ip->i_flock)));
 			iip->ili_pushbuf_flag = 0;
 			xfs_iunlock(ip, XFS_ILOCK_SHARED);
 			xfs_buftrace("INODE ITEM PUSH", bp);
@@ -864,7 +862,7 @@
 	ip = iip->ili_inode;
 
 	ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS));
-	ASSERT(valusema(&(ip->i_flock)) <= 0);
+	ASSERT(issemalocked(&(ip->i_flock)));
 	/*
 	 * Since we were able to lock the inode's flush lock and
 	 * we found it on the AIL, the inode must be dirty.  This
@@ -1084,3 +1082,52 @@
 {
 	xfs_iflush_abort(iip->ili_inode);
 }
+
+/*
+ * convert an xfs_inode_log_format struct from either 32 or 64 bit versions
+ * (which can have different field alignments) to the native version
+ */
+int
+xfs_inode_item_format_convert(
+	xfs_log_iovec_t		*buf,
+	xfs_inode_log_format_t	*in_f)
+{
+	if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) {
+		xfs_inode_log_format_32_t *in_f32;
+
+		in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr;
+		in_f->ilf_type = in_f32->ilf_type;
+		in_f->ilf_size = in_f32->ilf_size;
+		in_f->ilf_fields = in_f32->ilf_fields;
+		in_f->ilf_asize = in_f32->ilf_asize;
+		in_f->ilf_dsize = in_f32->ilf_dsize;
+		in_f->ilf_ino = in_f32->ilf_ino;
+		/* copy biggest field of ilf_u */
+		memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
+		       in_f32->ilf_u.ilfu_uuid.__u_bits,
+		       sizeof(uuid_t));
+		in_f->ilf_blkno = in_f32->ilf_blkno;
+		in_f->ilf_len = in_f32->ilf_len;
+		in_f->ilf_boffset = in_f32->ilf_boffset;
+		return 0;
+	} else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){
+		xfs_inode_log_format_64_t *in_f64;
+
+		in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr;
+		in_f->ilf_type = in_f64->ilf_type;
+		in_f->ilf_size = in_f64->ilf_size;
+		in_f->ilf_fields = in_f64->ilf_fields;
+		in_f->ilf_asize = in_f64->ilf_asize;
+		in_f->ilf_dsize = in_f64->ilf_dsize;
+		in_f->ilf_ino = in_f64->ilf_ino;
+		/* copy biggest field of ilf_u */
+		memcpy(in_f->ilf_u.ilfu_uuid.__u_bits,
+		       in_f64->ilf_u.ilfu_uuid.__u_bits,
+		       sizeof(uuid_t));
+		in_f->ilf_blkno = in_f64->ilf_blkno;
+		in_f->ilf_len = in_f64->ilf_len;
+		in_f->ilf_boffset = in_f64->ilf_boffset;
+		return 0;
+	}
+	return EFSCORRUPTED;
+}
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index c5dbf93..5db6cd1 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -23,25 +23,6 @@
  * log.  The size of the inline data/extents/b-tree root to be logged
  * (if any) is indicated in the ilf_dsize field.  Changes to this structure
  * must be added on to the end.
- *
- * Convention for naming inode log item versions :  The current version
- * is always named XFS_LI_INODE.  When an inode log item gets superseded,
- * add the latest version of IRIX that will generate logs with that item
- * to the version name.
- *
- * -Version 1 of this structure (XFS_LI_5_3_INODE) included up to the first
- *	union (ilf_u) field.  This was released with IRIX 5.3-XFS.
- * -Version 2 of this structure (XFS_LI_6_1_INODE) is currently the entire
- *	structure.  This was released with IRIX 6.0.1-XFS and IRIX 6.1.
- * -Version 3 of this structure (XFS_LI_INODE) is the same as version 2
- *	so a new structure definition wasn't necessary.  However, we had
- *	to add a new type because the inode cluster size changed from 4K
- *	to 8K and the version number had to be rev'ved to keep older kernels
- *	from trying to recover logs with the 8K buffers in them.  The logging
- *	code can handle recovery on different-sized clusters now so hopefully
- *	this'll be the last time we need to change the inode log item just
- *	for a change in the inode cluster size.  This new version was
- *	released with IRIX 6.2.
  */
 typedef struct xfs_inode_log_format {
 	unsigned short		ilf_type;	/* inode log item type */
@@ -59,18 +40,38 @@
 	int			ilf_boffset;	/* off of inode in buffer */
 } xfs_inode_log_format_t;
 
-/* Initial version shipped with IRIX 5.3-XFS */
-typedef struct xfs_inode_log_format_v1 {
-	unsigned short		ilf_type;	/* inode log item type */
-	unsigned short		ilf_size;	/* size of this item */
-	uint			ilf_fields;	/* flags for fields logged */
-	uint			ilf_dsize;	/* size of data/ext/root */
-	xfs_ino_t		ilf_ino;	/* inode number */
+typedef struct xfs_inode_log_format_32 {
+	unsigned short		ilf_type;	/* 16: inode log item type */
+	unsigned short		ilf_size;	/* 16: size of this item */
+	uint			ilf_fields;	/* 32: flags for fields logged */
+	ushort			ilf_asize;	/* 32: size of attr d/ext/root */
+	ushort			ilf_dsize;	/* 32: size of data/ext/root */
+	xfs_ino_t		ilf_ino;	/* 64: inode number */
 	union {
-		xfs_dev_t	ilfu_rdev;	/* rdev value for dev inode*/
-		uuid_t		ilfu_uuid;	/* mount point value */
+		xfs_dev_t	ilfu_rdev;	/* 32: rdev value for dev inode*/
+		uuid_t		ilfu_uuid;	/* 128: mount point value */
 	} ilf_u;
-} xfs_inode_log_format_t_v1;
+	__int64_t		ilf_blkno;	/* 64: blkno of inode buffer */
+	int			ilf_len;	/* 32: len of inode buffer */
+	int			ilf_boffset;	/* 32: off of inode in buffer */
+} __attribute__((packed)) xfs_inode_log_format_32_t;
+
+typedef struct xfs_inode_log_format_64 {
+	unsigned short		ilf_type;	/* 16: inode log item type */
+	unsigned short		ilf_size;	/* 16: size of this item */
+	uint			ilf_fields;	/* 32: flags for fields logged */
+	ushort			ilf_asize;	/* 32: size of attr d/ext/root */
+	ushort			ilf_dsize;	/* 32: size of data/ext/root */
+	__uint32_t		ilf_pad;	/* 32: pad for 64 bit boundary */
+	xfs_ino_t		ilf_ino;	/* 64: inode number */
+	union {
+		xfs_dev_t	ilfu_rdev;	/* 32: rdev value for dev inode*/
+		uuid_t		ilfu_uuid;	/* 128: mount point value */
+	} ilf_u;
+	__int64_t		ilf_blkno;	/* 64: blkno of inode buffer */
+	int			ilf_len;	/* 32: len of inode buffer */
+	int			ilf_boffset;	/* 32: off of inode in buffer */
+} xfs_inode_log_format_64_t;
 
 /*
  * Flags for xfs_trans_log_inode flags field.
@@ -172,6 +173,8 @@
 extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *);
 extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *);
 extern void xfs_iflush_abort(struct xfs_inode *);
+extern int xfs_inode_item_format_convert(xfs_log_iovec_t *,
+					 xfs_inode_log_format_t *);
 
 #endif	/* __KERNEL__ */
 
diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c
index a078156..06d710c 100644
--- a/fs/xfs/xfs_iocore.c
+++ b/fs/xfs/xfs_iocore.c
@@ -24,14 +24,13 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
+#include "xfs_dfrag.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -58,7 +57,7 @@
 
 STATIC int
 xfs_ioinit(
-	struct vfs		*vfsp,
+	struct bhv_vfs		*vfsp,
 	struct xfs_mount_args	*mntargs,
 	int			flags)
 {
@@ -68,6 +67,7 @@
 xfs_ioops_t	xfs_iocore_xfs = {
 	.xfs_ioinit		= (xfs_ioinit_t) xfs_ioinit,
 	.xfs_bmapi_func		= (xfs_bmapi_t) xfs_bmapi,
+	.xfs_bunmapi_func	= (xfs_bunmapi_t) xfs_bunmapi,
 	.xfs_bmap_eof_func	= (xfs_bmap_eof_t) xfs_bmap_eof,
 	.xfs_iomap_write_direct =
 			(xfs_iomap_write_direct_t) xfs_iomap_write_direct,
@@ -84,6 +84,7 @@
 	.xfs_unlock		= (xfs_unlk_t) xfs_iunlock,
 	.xfs_size_func		= (xfs_size_t) xfs_size_fn,
 	.xfs_iodone		= (xfs_iodone_t) fs_noerr,
+	.xfs_swap_extents_func	= (xfs_swap_extents_t) xfs_swap_extents,
 };
 
 void
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index d5dfedc..f1949c1 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -252,7 +250,7 @@
 	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
 			(xfs_filblks_t)(end_fsb - offset_fsb),
 			bmapi_flags,  NULL, 0, &imap,
-			&nimaps, NULL);
+			&nimaps, NULL, NULL);
 
 	if (error)
 		goto out;
@@ -519,8 +517,8 @@
 	 */
 	XFS_BMAP_INIT(&free_list, &firstfsb);
 	nimaps = 1;
-	error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
-		bmapi_flag, &firstfsb, 0, &imap, &nimaps, &free_list);
+	error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, bmapi_flag,
+		&firstfsb, 0, &imap, &nimaps, &free_list, NULL);
 	if (error)
 		goto error0;
 
@@ -610,8 +608,8 @@
 	while (count_fsb > 0) {
 		imaps = nimaps;
 		firstblock = NULLFSBLOCK;
-		error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb,
-				  0, &firstblock, 0, imap, &imaps, NULL);
+		error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 0,
+				  &firstblock, 0, imap, &imaps, NULL, NULL);
 		if (error)
 			return error;
 		for (n = 0; n < imaps; n++) {
@@ -695,11 +693,11 @@
 
 	nimaps = XFS_WRITE_IMAPS;
 	firstblock = NULLFSBLOCK;
-	error = xfs_bmapi(NULL, ip, offset_fsb,
+	error = XFS_BMAPI(mp, NULL, io, offset_fsb,
 			  (xfs_filblks_t)(last_fsb - offset_fsb),
 			  XFS_BMAPI_DELAY | XFS_BMAPI_WRITE |
 			  XFS_BMAPI_ENTIRE, &firstblock, 1, imap,
-			  &nimaps, NULL);
+			  &nimaps, NULL, NULL);
 	if (error && (error != ENOSPC))
 		return XFS_ERROR(error);
 
@@ -832,9 +830,9 @@
 			}
 
 			/* Go get the actual blocks */
-			error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb,
+			error = XFS_BMAPI(mp, tp, io, map_start_fsb, count_fsb,
 					XFS_BMAPI_WRITE, &first_block, 1,
-					imap, &nimaps, &free_list);
+					imap, &nimaps, &free_list, NULL);
 			if (error)
 				goto trans_cancel;
 
@@ -955,9 +953,9 @@
 		 */
 		XFS_BMAP_INIT(&free_list, &firstfsb);
 		nimaps = 1;
-		error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
+		error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb,
 				  XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb,
-				  1, &imap, &nimaps, &free_list);
+				  1, &imap, &nimaps, &free_list, NULL);
 		if (error)
 			goto error_on_bmapi_transaction;
 
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 94068d0..46249e4 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -41,11 +39,6 @@
 #include "xfs_error.h"
 #include "xfs_btree.h"
 
-#ifndef HAVE_USERACC
-#define useracc(ubuffer, size, flags, foo) (0)
-#define unuseracc(ubuffer, size, flags)
-#endif
-
 STATIC int
 xfs_bulkstat_one_iget(
 	xfs_mount_t	*mp,		/* mount point for filesystem */
@@ -56,7 +49,7 @@
 {
 	xfs_dinode_core_t *dic;		/* dinode core info pointer */
 	xfs_inode_t	*ip;		/* incore inode pointer */
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 	int		error;
 
 	error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno);
@@ -336,15 +329,6 @@
 	nimask = ~(nicluster - 1);
 	nbcluster = nicluster >> mp->m_sb.sb_inopblog;
 	/*
-	 * Lock down the user's buffer. If a buffer was not sent, as in the case
-	 * disk quota code calls here, we skip this.
-	 */
-	if (ubuffer &&
-	    (error = useracc(ubuffer, ubcount * statstruct_size,
-			(B_READ|B_PHYS), NULL))) {
-		return error;
-	}
-	/*
 	 * Allocate a page-sized buffer for inode btree records.
 	 * We could try allocating something smaller, but for normal
 	 * calls we'll always (potentially) need the whole page.
@@ -650,8 +634,6 @@
 	 * Done, we're either out of filesystem or space to put the data.
 	 */
 	kmem_free(irbuf, NBPC);
-	if (ubuffer)
-		unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS));
 	*ubcountp = ubelem;
 	if (agno >= mp->m_sb.sb_agcount) {
 		/*
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 11eb4e1..be5f12e 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -45,7 +45,6 @@
  */
 #define	BULKSTAT_FG_IGET	0x1	/* Go through the buffer cache */
 #define	BULKSTAT_FG_QUICK	0x2	/* No iget, walk the dinode cluster */
-#define BULKSTAT_FG_VFSLOCKED	0x4	/* Already have vfs lock */
 
 /*
  * Return stat information in bulk (by-inode) for the filesystem.
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 32e841d..e730328 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -36,7 +35,6 @@
 #include "xfs_ialloc_btree.h"
 #include "xfs_log_recover.h"
 #include "xfs_trans_priv.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -402,7 +400,7 @@
 	xlog_in_core_t	  *iclog = (xlog_in_core_t *)iclog_hndl;
 
 	if (xlog_state_release_iclog(log, iclog)) {
-		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
+		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
 		return EIO;
 	}
 
@@ -498,9 +496,8 @@
 	 * just worked.
 	 */
 	if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) {
-		int	error;
-		vfs_t	*vfsp = XFS_MTOVFS(mp);
-		int	readonly = (vfsp->vfs_flag & VFS_RDONLY);
+		bhv_vfs_t	*vfsp = XFS_MTOVFS(mp);
+		int		error, readonly = (vfsp->vfs_flag & VFS_RDONLY);
 
 		if (readonly)
 			vfsp->vfs_flag &= ~VFS_RDONLY;
@@ -726,7 +723,7 @@
 		return XFS_ERROR(EIO);
 
 	if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
-		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
+		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
 	}
 	return error;
 }	/* xfs_log_write */
@@ -816,9 +813,9 @@
 	SPLDECL(s);
 	int		needed = 0, gen;
 	xlog_t		*log = mp->m_log;
-	vfs_t		*vfsp = XFS_MTOVFS(mp);
+	bhv_vfs_t	*vfsp = XFS_MTOVFS(mp);
 
-	if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
+	if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
 	    (vfsp->vfs_flag & VFS_RDONLY))
 		return 0;
 
@@ -956,7 +953,7 @@
 			XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) {
 		xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp));
 		XFS_BUF_STALE(bp);
-		xfs_force_shutdown(l->l_mp, XFS_LOG_IO_ERROR);
+		xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR);
 		/*
 		 * This flag will be propagated to the trans-committed
 		 * callback routines to let them know that the log-commit
@@ -1261,7 +1258,7 @@
 	ASSERT_ALWAYS(iclog);
 	if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp,
 			       iclog, XLOG_COMMIT_TRANS))) {
-		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
+		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
 	}
 	return error;
 }	/* xlog_commit_record */
@@ -1743,10 +1740,10 @@
 	   xlog_in_core_t	**commit_iclog,
 	   uint			flags)
 {
-    xlog_t	     *log    = mp->m_log;
+    xlog_t	     *log = mp->m_log;
     xlog_ticket_t    *ticket = (xlog_ticket_t *)tic;
+    xlog_in_core_t   *iclog = NULL;  /* ptr to current in-core log */
     xlog_op_header_t *logop_head;    /* ptr to log operation header */
-    xlog_in_core_t   *iclog;	     /* ptr to current in-core log */
     __psint_t	     ptr;	     /* copy address into data region */
     int		     len;	     /* # xlog_write() bytes 2 still copy */
     int		     index;	     /* region index currently copying */
@@ -1790,7 +1787,7 @@
 	xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp,
 		"xfs_log_write: reservation ran out. Need to up reservation");
 	/* If we did not panic, shutdown the filesystem */
-	xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
+	xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 #endif
     } else
 	ticket->t_curr_res -= len;
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 1f0016b..3cb678e 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -193,14 +191,14 @@
 {
 	int			b;
 
-	printk("%s:  SB : uuid = ", __FUNCTION__);
+	cmn_err(CE_DEBUG, "%s:  SB : uuid = ", __FUNCTION__);
 	for (b = 0; b < 16; b++)
-		printk("%02x",((unsigned char *)&mp->m_sb.sb_uuid)[b]);
-	printk(", fmt = %d\n", XLOG_FMT);
-	printk("    log : uuid = ");
+		cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]);
+	cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT);
+	cmn_err(CE_DEBUG, "    log : uuid = ");
 	for (b = 0; b < 16; b++)
-		printk("%02x",((unsigned char *)&head->h_fs_uuid)[b]);
-	printk(", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT));
+		cmn_err(CE_DEBUG, "%02x",((uchar_t *)&head->h_fs_uuid)[b]);
+	cmn_err(CE_DEBUG, ", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT));
 }
 #else
 #define xlog_header_check_dump(mp, head)
@@ -282,7 +280,7 @@
 		mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *);
 		xfs_ioerror_alert("xlog_recover_iodone",
 				  mp, bp, XFS_BUF_ADDR(bp));
-		xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
+		xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
 	}
 	XFS_BUF_SET_FSPRIVATE(bp, NULL);
 	XFS_BUF_CLR_IODONE_FUNC(bp);
@@ -992,6 +990,8 @@
 	xfs_daddr_t     num_scan_bblks;
 	int	        error, log_bbnum = log->l_logBBsize;
 
+	*blk_no = 0;
+
 	/* check totally zeroed log */
 	bp = xlog_get_bp(log, 1);
 	if (!bp)
@@ -1889,7 +1889,7 @@
 
 		buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp,
 					      next_unlinked_offset);
-		INT_SET(*buffer_nextp, ARCH_CONVERT, *logged_nextp);
+		*buffer_nextp = *logged_nextp;
 	}
 
 	return 0;
@@ -2292,12 +2292,22 @@
 	int			attr_index;
 	uint			fields;
 	xfs_dinode_core_t	*dicp;
+	int			need_free = 0;
 
 	if (pass == XLOG_RECOVER_PASS1) {
 		return 0;
 	}
 
-	in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
+	if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) {
+		in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr;
+	} else {
+		in_f = (xfs_inode_log_format_t *)kmem_alloc(
+			sizeof(xfs_inode_log_format_t), KM_SLEEP);
+		need_free = 1;
+		error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f);
+		if (error)
+			goto error;
+	}
 	ino = in_f->ilf_ino;
 	mp = log->l_mp;
 	if (ITEM_TYPE(item) == XFS_LI_INODE) {
@@ -2323,8 +2333,10 @@
 	 * Inode buffers can be freed, look out for it,
 	 * and do not replay the inode.
 	 */
-	if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0))
-		return 0;
+	if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) {
+		error = 0;
+		goto error;
+	}
 
 	bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len,
 								XFS_BUF_LOCK);
@@ -2333,7 +2345,7 @@
 				  bp, imap.im_blkno);
 		error = XFS_BUF_GETERROR(bp);
 		xfs_buf_relse(bp);
-		return error;
+		goto error;
 	}
 	error = 0;
 	ASSERT(in_f->ilf_fields & XFS_ILOG_CORE);
@@ -2350,7 +2362,8 @@
 			dip, bp, ino);
 		XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)",
 				 XFS_ERRLEVEL_LOW, mp);
-		return XFS_ERROR(EFSCORRUPTED);
+		error = EFSCORRUPTED;
+		goto error;
 	}
 	dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr);
 	if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) {
@@ -2360,7 +2373,8 @@
 			item, ino);
 		XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)",
 				 XFS_ERRLEVEL_LOW, mp);
-		return XFS_ERROR(EFSCORRUPTED);
+		error = EFSCORRUPTED;
+		goto error;
 	}
 
 	/* Skip replay when the on disk inode is newer than the log one */
@@ -2376,7 +2390,8 @@
 			/* do nothing */
 		} else {
 			xfs_buf_relse(bp);
-			return 0;
+			error = 0;
+			goto error;
 		}
 	}
 	/* Take the opportunity to reset the flush iteration count */
@@ -2391,7 +2406,8 @@
 			xfs_fs_cmn_err(CE_ALERT, mp,
 				"xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
 				item, dip, bp, ino);
-			return XFS_ERROR(EFSCORRUPTED);
+			error = EFSCORRUPTED;
+			goto error;
 		}
 	} else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) {
 		if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) &&
@@ -2403,7 +2419,8 @@
 			xfs_fs_cmn_err(CE_ALERT, mp,
 				"xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld",
 				item, dip, bp, ino);
-			return XFS_ERROR(EFSCORRUPTED);
+			error = EFSCORRUPTED;
+			goto error;
 		}
 	}
 	if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){
@@ -2415,7 +2432,8 @@
 			item, dip, bp, ino,
 			dicp->di_nextents + dicp->di_anextents,
 			dicp->di_nblocks);
-		return XFS_ERROR(EFSCORRUPTED);
+		error = EFSCORRUPTED;
+		goto error;
 	}
 	if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) {
 		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)",
@@ -2424,7 +2442,8 @@
 		xfs_fs_cmn_err(CE_ALERT, mp,
 			"xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x",
 			item, dip, bp, ino, dicp->di_forkoff);
-		return XFS_ERROR(EFSCORRUPTED);
+		error = EFSCORRUPTED;
+		goto error;
 	}
 	if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) {
 		XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)",
@@ -2433,7 +2452,8 @@
 		xfs_fs_cmn_err(CE_ALERT, mp,
 			"xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p",
 			item->ri_buf[1].i_len, item);
-		return XFS_ERROR(EFSCORRUPTED);
+		error = EFSCORRUPTED;
+		goto error;
 	}
 
 	/* The core is in in-core format */
@@ -2521,7 +2541,8 @@
 			xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag");
 			ASSERT(0);
 			xfs_buf_relse(bp);
-			return XFS_ERROR(EIO);
+			error = EIO;
+			goto error;
 		}
 	}
 
@@ -2537,7 +2558,10 @@
 		error = xfs_bwrite(mp, bp);
 	}
 
-	return (error);
+error:
+	if (need_free)
+		kmem_free(in_f, sizeof(*in_f));
+	return XFS_ERROR(error);
 }
 
 /*
@@ -2674,32 +2698,32 @@
  * structure into it, and adds the efi to the AIL with the given
  * LSN.
  */
-STATIC void
+STATIC int
 xlog_recover_do_efi_trans(
 	xlog_t			*log,
 	xlog_recover_item_t	*item,
 	xfs_lsn_t		lsn,
 	int			pass)
 {
+	int			error;
 	xfs_mount_t		*mp;
 	xfs_efi_log_item_t	*efip;
 	xfs_efi_log_format_t	*efi_formatp;
 	SPLDECL(s);
 
 	if (pass == XLOG_RECOVER_PASS1) {
-		return;
+		return 0;
 	}
 
 	efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr;
-	ASSERT(item->ri_buf[0].i_len ==
-	       (sizeof(xfs_efi_log_format_t) +
-		((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))));
 
 	mp = log->l_mp;
 	efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
-	memcpy((char *)&(efip->efi_format), (char *)efi_formatp,
-	      sizeof(xfs_efi_log_format_t) +
-	      ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t)));
+	if ((error = xfs_efi_copy_format(&(item->ri_buf[0]),
+					 &(efip->efi_format)))) {
+		xfs_efi_item_free(efip);
+		return error;
+	}
 	efip->efi_next_extent = efi_formatp->efi_nextents;
 	efip->efi_flags |= XFS_EFI_COMMITTED;
 
@@ -2708,6 +2732,7 @@
 	 * xfs_trans_update_ail() drops the AIL lock.
 	 */
 	xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s);
+	return 0;
 }
 
 
@@ -2738,9 +2763,10 @@
 	}
 
 	efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr;
-	ASSERT(item->ri_buf[0].i_len ==
-	       (sizeof(xfs_efd_log_format_t) +
-		((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t))));
+	ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) +
+		((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) ||
+	       (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) +
+		((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t)))));
 	efi_id = efd_formatp->efd_efi_id;
 
 	/*
@@ -2810,15 +2836,14 @@
 			if  ((error = xlog_recover_do_buffer_trans(log, item,
 								 pass)))
 				break;
-		} else if ((ITEM_TYPE(item) == XFS_LI_INODE) ||
-			   (ITEM_TYPE(item) == XFS_LI_6_1_INODE) ||
-			   (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) {
+		} else if ((ITEM_TYPE(item) == XFS_LI_INODE)) {
 			if ((error = xlog_recover_do_inode_trans(log, item,
 								pass)))
 				break;
 		} else if (ITEM_TYPE(item) == XFS_LI_EFI) {
-			xlog_recover_do_efi_trans(log, item, trans->r_lsn,
-						  pass);
+			if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn,
+						  pass)))
+				break;
 		} else if (ITEM_TYPE(item) == XFS_LI_EFD) {
 			xlog_recover_do_efd_trans(log, item, pass);
 		} else if (ITEM_TYPE(item) == XFS_LI_DQUOT) {
@@ -3419,13 +3444,13 @@
 	    if (rhead->h_chksum ||
 		((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) {
 		    cmn_err(CE_DEBUG,
-			"XFS: LogR chksum mismatch: was (0x%x) is (0x%x)",
+			"XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n",
 			    INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum);
 		    cmn_err(CE_DEBUG,
 "XFS: Disregard message if filesystem was created with non-DEBUG kernel");
 		    if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) {
 			    cmn_err(CE_DEBUG,
-				"XFS: LogR this is a LogV2 filesystem");
+				"XFS: LogR this is a LogV2 filesystem\n");
 		    }
 		    log->l_flags |= XLOG_CHKSUM_MISMATCH;
 	    }
@@ -3798,7 +3823,7 @@
 	error = xlog_do_recovery_pass(log, head_blk, tail_blk,
 				      XLOG_RECOVER_PASS2);
 #ifdef DEBUG
-	{
+	if (!error) {
 		int	i;
 
 		for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
@@ -3974,7 +3999,7 @@
 		log->l_flags &= ~XLOG_RECOVERY_NEEDED;
 	} else {
 		cmn_err(CE_DEBUG,
-			"!Ending clean XFS mount for filesystem: %s",
+			"!Ending clean XFS mount for filesystem: %s\n",
 			log->l_mp->m_fsname);
 	}
 	return 0;
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index c0b1c29..4be5c0b 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -196,7 +194,7 @@
 		kmem_free(mp->m_logname, strlen(mp->m_logname) + 1);
 
 	if (remove_bhv) {
-		struct vfs	*vfsp = XFS_MTOVFS(mp);
+		struct bhv_vfs	*vfsp = XFS_MTOVFS(mp);
 
 		bhv_remove_all_vfsops(vfsp, 0);
 		VFS_REMOVEBHV(vfsp, &mp->m_bhv);
@@ -337,7 +335,7 @@
 
 xfs_agnumber_t
 xfs_initialize_perag(
-	struct vfs	*vfs,
+	bhv_vfs_t	*vfs,
 	xfs_mount_t	*mp,
 	xfs_agnumber_t	agcount)
 {
@@ -651,14 +649,14 @@
  */
 int
 xfs_mountfs(
-	vfs_t		*vfsp,
+	bhv_vfs_t	*vfsp,
 	xfs_mount_t	*mp,
 	int		mfsi_flags)
 {
 	xfs_buf_t	*bp;
 	xfs_sb_t	*sbp = &(mp->m_sb);
 	xfs_inode_t	*rip;
-	vnode_t		*rvp = NULL;
+	bhv_vnode_t	*rvp = NULL;
 	int		readio_log, writeio_log;
 	xfs_daddr_t	d;
 	__uint64_t	ret64;
@@ -934,18 +932,7 @@
 	vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
 	mp->m_dmevmask = 0;	/* not persistent; set after each mount */
 
-	/*
-	 * Select the right directory manager.
-	 */
-	mp->m_dirops =
-		XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ?
-			xfsv2_dirops :
-			xfsv1_dirops;
-
-	/*
-	 * Initialize directory manager's entries.
-	 */
-	XFS_DIR_MOUNT(mp);
+	xfs_dir_mount(mp);
 
 	/*
 	 * Initialize the attribute manager's entries.
@@ -1006,8 +993,9 @@
 
 	if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
 		cmn_err(CE_WARN, "XFS: corrupted root inode");
-		prdev("Root inode %llu is not a directory",
-		      mp->m_ddev_targp, (unsigned long long)rip->i_ino);
+		cmn_err(CE_WARN, "Device %s - root %llu is not a directory",
+			XFS_BUFTARG_NAME(mp->m_ddev_targp),
+			(unsigned long long)rip->i_ino);
 		xfs_iunlock(rip, XFS_ILOCK_EXCL);
 		XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
 				 mp);
@@ -1094,7 +1082,7 @@
 int
 xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
 {
-	struct vfs	*vfsp = XFS_MTOVFS(mp);
+	struct bhv_vfs	*vfsp = XFS_MTOVFS(mp);
 #if defined(DEBUG) || defined(INDUCE_IO_ERROR)
 	int64_t		fsid;
 #endif
@@ -1254,6 +1242,26 @@
 
 	xfs_trans_log_buf(tp, bp, first, last);
 }
+
+/*
+ * In order to avoid ENOSPC-related deadlock caused by
+ * out-of-order locking of AGF buffer (PV 947395), we place
+ * constraints on the relationship among actual allocations for
+ * data blocks, freelist blocks, and potential file data bmap
+ * btree blocks. However, these restrictions may result in no
+ * actual space allocated for a delayed extent, for example, a data
+ * block in a certain AG is allocated but there is no additional
+ * block for the additional bmap btree block due to a split of the
+ * bmap btree of the file. The result of this may lead to an
+ * infinite loop in xfssyncd when the file gets flushed to disk and
+ * all delayed extents need to be actually allocated. To get around
+ * this, we explicitly set aside a few blocks which will not be
+ * reserved in delayed allocation. Considering the minimum number of
+ * needed freelist blocks is 4 fsbs, a potential split of file's bmap
+ * btree requires 1 fsb, so we set the number of set-aside blocks to 8.
+*/
+#define SET_ASIDE_BLOCKS 8
+
 /*
  * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply
  * a delta to a specified field in the in-core superblock.  Simply
@@ -1298,7 +1306,7 @@
 		return 0;
 	case XFS_SBS_FDBLOCKS:
 
-		lcounter = (long long)mp->m_sb.sb_fdblocks;
+		lcounter = (long long)mp->m_sb.sb_fdblocks - SET_ASIDE_BLOCKS;
 		res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
 
 		if (delta > 0) {		/* Putting blocks back */
@@ -1332,7 +1340,7 @@
 			}
 		}
 
-		mp->m_sb.sb_fdblocks = lcounter;
+		mp->m_sb.sb_fdblocks = lcounter + SET_ASIDE_BLOCKS;
 		return 0;
 	case XFS_SBS_FREXTENTS:
 		lcounter = (long long)mp->m_sb.sb_frextents;
@@ -1713,15 +1721,14 @@
  * is present to prevent thrashing).
  */
 
+#ifdef CONFIG_HOTPLUG_CPU
 /*
  * hot-plug CPU notifier support.
  *
- * We cannot use the hotcpu_register() function because it does
- * not allow notifier instances. We need a notifier per filesystem
- * as we need to be able to identify the filesystem to balance
- * the counters out. This is achieved by having a notifier block
- * embedded in the xfs_mount_t and doing pointer magic to get the
- * mount pointer from the notifier block address.
+ * We need a notifier per filesystem as we need to be able to identify
+ * the filesystem to balance the counters out. This is achieved by
+ * having a notifier block embedded in the xfs_mount_t and doing pointer
+ * magic to get the mount pointer from the notifier block address.
  */
 STATIC int
 xfs_icsb_cpu_notify(
@@ -1771,6 +1778,7 @@
 
 	return NOTIFY_OK;
 }
+#endif /* CONFIG_HOTPLUG_CPU */
 
 int
 xfs_icsb_init_counters(
@@ -1783,9 +1791,11 @@
 	if (mp->m_sb_cnts == NULL)
 		return -ENOMEM;
 
+#ifdef CONFIG_HOTPLUG_CPU
 	mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
 	mp->m_icsb_notifier.priority = 0;
-	register_cpu_notifier(&mp->m_icsb_notifier);
+	register_hotcpu_notifier(&mp->m_icsb_notifier);
+#endif /* CONFIG_HOTPLUG_CPU */
 
 	for_each_online_cpu(i) {
 		cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
@@ -1804,7 +1814,7 @@
 	xfs_mount_t	*mp)
 {
 	if (mp->m_sb_cnts) {
-		unregister_cpu_notifier(&mp->m_icsb_notifier);
+		unregister_hotcpu_notifier(&mp->m_icsb_notifier);
 		free_percpu(mp->m_sb_cnts);
 	}
 }
@@ -2018,7 +2028,7 @@
 	xfs_sb_field_t  field,
 	int		flags)
 {
-	uint64_t	count, resid = 0;
+	uint64_t	count, resid;
 	int		weight = num_online_cpus();
 	int		s;
 
@@ -2050,6 +2060,7 @@
 		break;
 	default:
 		BUG();
+		count = resid = 0;	/* quiet, gcc */
 		break;
 	}
 
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 668ad23..b2bd4be 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -53,8 +53,8 @@
 #else
 struct cred;
 struct log;
-struct vfs;
-struct vnode;
+struct bhv_vfs;
+struct bhv_vnode;
 struct xfs_mount_args;
 struct xfs_ihash;
 struct xfs_chash;
@@ -63,9 +63,11 @@
 struct xfs_iocore;
 struct xfs_bmbt_irec;
 struct xfs_bmap_free;
+struct xfs_extdelta;
+struct xfs_swapext;
 
-extern struct vfsops xfs_vfsops;
-extern struct vnodeops xfs_vnodeops;
+extern struct bhv_vfsops xfs_vfsops;
+extern struct bhv_vnodeops xfs_vnodeops;
 
 #define	AIL_LOCK_T		lock_t
 #define	AIL_LOCKINIT(x,y)	spinlock_init(x,y)
@@ -78,15 +80,15 @@
  * Prototypes and functions for the Data Migration subsystem.
  */
 
-typedef int	(*xfs_send_data_t)(int, struct vnode *,
-			xfs_off_t, size_t, int, vrwlock_t *);
+typedef int	(*xfs_send_data_t)(int, struct bhv_vnode *,
+			xfs_off_t, size_t, int, bhv_vrwlock_t *);
 typedef int	(*xfs_send_mmap_t)(struct vm_area_struct *, uint);
-typedef int	(*xfs_send_destroy_t)(struct vnode *, dm_right_t);
-typedef int	(*xfs_send_namesp_t)(dm_eventtype_t, struct vfs *,
-			struct vnode *,
-			dm_right_t, struct vnode *, dm_right_t,
+typedef int	(*xfs_send_destroy_t)(struct bhv_vnode *, dm_right_t);
+typedef int	(*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *,
+			struct bhv_vnode *,
+			dm_right_t, struct bhv_vnode *, dm_right_t,
 			char *, char *, mode_t, int, int);
-typedef void	(*xfs_send_unmount_t)(struct vfs *, struct vnode *,
+typedef void	(*xfs_send_unmount_t)(struct bhv_vfs *, struct bhv_vnode *,
 			dm_right_t, mode_t, int, int);
 
 typedef struct xfs_dmops {
@@ -188,13 +190,18 @@
  * Prototypes and functions for I/O core modularization.
  */
 
-typedef int		(*xfs_ioinit_t)(struct vfs *,
+typedef int		(*xfs_ioinit_t)(struct bhv_vfs *,
 				struct xfs_mount_args *, int);
 typedef int		(*xfs_bmapi_t)(struct xfs_trans *, void *,
 				xfs_fileoff_t, xfs_filblks_t, int,
 				xfs_fsblock_t *, xfs_extlen_t,
 				struct xfs_bmbt_irec *, int *,
-				struct xfs_bmap_free *);
+				struct xfs_bmap_free *, struct xfs_extdelta *);
+typedef int		(*xfs_bunmapi_t)(struct xfs_trans *,
+				void *, xfs_fileoff_t,
+				xfs_filblks_t, int, xfs_extnum_t,
+				xfs_fsblock_t *, struct xfs_bmap_free *,
+				struct xfs_extdelta *, int *);
 typedef int		(*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *);
 typedef int		(*xfs_iomap_write_direct_t)(
 				void *, xfs_off_t, size_t, int,
@@ -213,11 +220,14 @@
 typedef int		(*xfs_lock_nowait_t)(void *, uint);
 typedef void		(*xfs_unlk_t)(void *, unsigned int);
 typedef xfs_fsize_t	(*xfs_size_t)(void *);
-typedef xfs_fsize_t	(*xfs_iodone_t)(struct vfs *);
+typedef xfs_fsize_t	(*xfs_iodone_t)(struct bhv_vfs *);
+typedef int		(*xfs_swap_extents_t)(void *, void *,
+				struct xfs_swapext*);
 
 typedef struct xfs_ioops {
 	xfs_ioinit_t			xfs_ioinit;
 	xfs_bmapi_t			xfs_bmapi_func;
+	xfs_bunmapi_t			xfs_bunmapi_func;
 	xfs_bmap_eof_t			xfs_bmap_eof_func;
 	xfs_iomap_write_direct_t	xfs_iomap_write_direct;
 	xfs_iomap_write_delay_t		xfs_iomap_write_delay;
@@ -230,13 +240,17 @@
 	xfs_unlk_t			xfs_unlock;
 	xfs_size_t			xfs_size_func;
 	xfs_iodone_t			xfs_iodone;
+	xfs_swap_extents_t		xfs_swap_extents_func;
 } xfs_ioops_t;
 
 #define XFS_IOINIT(vfsp, args, flags) \
 	(*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags)
-#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist)	\
+#define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \
 	(*(mp)->m_io_ops.xfs_bmapi_func) \
-		(trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist)
+		(trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta)
+#define XFS_BUNMAPI(mp, trans,io,bno,len,f,nexts,first,flist,delta,done) \
+	(*(mp)->m_io_ops.xfs_bunmapi_func) \
+		(trans,(io)->io_obj,bno,len,f,nexts,first,flist,delta,done)
 #define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \
 	(*(mp)->m_io_ops.xfs_bmap_eof_func) \
 		((io)->io_obj, endoff, whichfork, eof)
@@ -266,6 +280,9 @@
 	(*(mp)->m_io_ops.xfs_size_func)((io)->io_obj)
 #define XFS_IODONE(vfsp) \
 	(*(mp)->m_io_ops.xfs_iodone)(vfsp)
+#define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \
+	(*(mp)->m_io_ops.xfs_swap_extents_func) \
+		((io)->io_obj, (tio)->io_obj, sxp)
 
 #ifdef HAVE_PERCPU_SB
 
@@ -386,8 +403,6 @@
 	__uint8_t		m_inode_quiesce;/* call quiesce on new inodes.
 						   field governed by m_ilock */
 	__uint8_t		m_sectbb_log;	/* sectlog - BBSHIFT */
-	__uint8_t		m_dirversion;	/* 1 or 2 */
-	xfs_dirops_t		m_dirops;	/* table of dir funcs */
 	int			m_dirblksize;	/* directory block sz--bytes */
 	int			m_dirblkfsbs;	/* directory block sz--fsbs */
 	xfs_dablk_t		m_dirdatablk;	/* blockno of dir data v2 */
@@ -494,16 +509,7 @@
 
 #define XFS_FORCED_SHUTDOWN(mp)	((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN)
 #define xfs_force_shutdown(m,f)	\
-	VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
-
-/*
- * Flags sent to xfs_force_shutdown.
- */
-#define XFS_METADATA_IO_ERROR	0x1
-#define XFS_LOG_IO_ERROR	0x2
-#define XFS_FORCE_UMOUNT	0x4
-#define XFS_CORRUPT_INCORE	0x8	/* Corrupt in-memory data structures */
-#define XFS_SHUTDOWN_REMOTE_REQ 0x10	/* Shutdown came from remote cell */
+	bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__)
 
 /*
  * Flags for xfs_mountfs
@@ -521,7 +527,7 @@
  * Macros for getting from mount to vfs and back.
  */
 #define	XFS_MTOVFS(mp)		xfs_mtovfs(mp)
-static inline struct vfs *xfs_mtovfs(xfs_mount_t *mp)
+static inline struct bhv_vfs *xfs_mtovfs(xfs_mount_t *mp)
 {
 	return bhvtovfs(&mp->m_bhv);
 }
@@ -533,7 +539,7 @@
 }
 
 #define XFS_VFSTOM(vfs) xfs_vfstom(vfs)
-static inline xfs_mount_t *xfs_vfstom(vfs_t *vfs)
+static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs)
 {
 	return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops));
 }
@@ -571,7 +577,7 @@
 extern xfs_mount_t *xfs_mount_init(void);
 extern void	xfs_mod_sb(xfs_trans_t *, __int64_t);
 extern void	xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
-extern int	xfs_mountfs(struct vfs *, xfs_mount_t *mp, int);
+extern int	xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int);
 extern void	xfs_mountfs_check_barriers(xfs_mount_t *mp);
 
 extern int	xfs_unmountfs(xfs_mount_t *, struct cred *);
@@ -589,7 +595,7 @@
 extern void	xfs_do_force_shutdown(bhv_desc_t *, int, char *, int);
 extern int	xfs_syncsub(xfs_mount_t *, int, int, int *);
 extern int	xfs_sync_inodes(xfs_mount_t *, int, int, int *);
-extern xfs_agnumber_t	xfs_initialize_perag(struct vfs *, xfs_mount_t *,
+extern xfs_agnumber_t	xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *,
 						xfs_agnumber_t);
 extern void	xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t);
 
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c
index 1408a32..320d63f 100644
--- a/fs/xfs/xfs_qmops.c
+++ b/fs/xfs/xfs_qmops.c
@@ -23,7 +23,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 7fbef97..acb853b 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -365,7 +365,7 @@
 extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *);
 extern int xfs_mount_reset_sbqflags(struct xfs_mount *);
 
-extern struct bhv_vfsops xfs_qmops;
+extern struct bhv_module_vfsops xfs_qmops;
 
 #endif	/* __KERNEL__ */
 
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index 1f14876..d98171d 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -22,13 +22,11 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_da_btree.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -40,7 +38,6 @@
 #include "xfs_refcache.h"
 #include "xfs_utils.h"
 #include "xfs_trans_space.h"
-#include "xfs_dir_leaf.h"
 
 
 /*
@@ -87,8 +84,8 @@
 xfs_lock_for_rename(
 	xfs_inode_t	*dp1,	/* old (source) directory inode */
 	xfs_inode_t	*dp2,	/* new (target) directory inode */
-	vname_t		*vname1,/* old entry name */
-	vname_t		*vname2,/* new entry name */
+	bhv_vname_t	*vname1,/* old entry name */
+	bhv_vname_t	*vname2,/* new entry name */
 	xfs_inode_t	**ipp1,	/* inode of old entry */
 	xfs_inode_t	**ipp2,	/* inode of new entry, if it
 				   already exists, NULL otherwise. */
@@ -225,9 +222,9 @@
 int
 xfs_rename(
 	bhv_desc_t	*src_dir_bdp,
-	vname_t		*src_vname,
-	vnode_t		*target_dir_vp,
-	vname_t		*target_vname,
+	bhv_vname_t	*src_vname,
+	bhv_vnode_t	*target_dir_vp,
+	bhv_vname_t	*target_vname,
 	cred_t		*credp)
 {
 	xfs_trans_t	*tp;
@@ -242,7 +239,7 @@
 	int		committed;
 	xfs_inode_t	*inodes[4];
 	int		target_ip_dropped = 0;	/* dropped target_ip link? */
-	vnode_t		*src_dir_vp;
+	bhv_vnode_t	*src_dir_vp;
 	int		spaceres;
 	int		target_link_zero = 0;
 	int		num_inodes;
@@ -398,34 +395,29 @@
 		 * fit before actually inserting it.
 		 */
 		if (spaceres == 0 &&
-		    (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name,
-				target_namelen))) {
+		    (error = xfs_dir_canenter(tp, target_dp, target_name,
+						target_namelen)))
 			goto error_return;
-		}
 		/*
 		 * If target does not exist and the rename crosses
 		 * directories, adjust the target directory link count
 		 * to account for the ".." reference from the new entry.
 		 */
-		error = XFS_DIR_CREATENAME(mp, tp, target_dp, target_name,
+		error = xfs_dir_createname(tp, target_dp, target_name,
 					   target_namelen, src_ip->i_ino,
 					   &first_block, &free_list, spaceres);
-		if (error == ENOSPC) {
+		if (error == ENOSPC)
 			goto error_return;
-		}
-		if (error) {
+		if (error)
 			goto abort_return;
-		}
 		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 		if (new_parent && src_is_directory) {
 			error = xfs_bumplink(tp, target_dp);
-			if (error) {
+			if (error)
 				goto abort_return;
-			}
 		}
 	} else { /* target_ip != NULL */
-
 		/*
 		 * If target exists and it's a directory, check that both
 		 * target and source are directories and that target can be
@@ -435,7 +427,7 @@
 			/*
 			 * Make sure target dir is empty.
 			 */
-			if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) ||
+			if (!(xfs_dir_isempty(target_ip)) ||
 			    (target_ip->i_d.di_nlink > 2)) {
 				error = XFS_ERROR(EEXIST);
 				goto error_return;
@@ -451,12 +443,11 @@
 		 * In case there is already an entry with the same
 		 * name at the destination directory, remove it first.
 		 */
-		error = XFS_DIR_REPLACE(mp, tp, target_dp, target_name,
-			target_namelen, src_ip->i_ino, &first_block,
-			&free_list, spaceres);
-		if (error) {
+		error = xfs_dir_replace(tp, target_dp, target_name,
+					target_namelen, src_ip->i_ino,
+					&first_block, &free_list, spaceres);
+		if (error)
 			goto abort_return;
-		}
 		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 		/*
@@ -464,9 +455,8 @@
 		 * dir no longer points to it.
 		 */
 		error = xfs_droplink(tp, target_ip);
-		if (error) {
+		if (error)
 			goto abort_return;
-		}
 		target_ip_dropped = 1;
 
 		if (src_is_directory) {
@@ -474,9 +464,8 @@
 			 * Drop the link from the old "." entry.
 			 */
 			error = xfs_droplink(tp, target_ip);
-			if (error) {
+			if (error)
 				goto abort_return;
-			}
 		}
 
 		/* Do this test while we still hold the locks */
@@ -488,18 +477,15 @@
 	 * Remove the source.
 	 */
 	if (new_parent && src_is_directory) {
-
 		/*
 		 * Rewrite the ".." entry to point to the new
 		 * directory.
 		 */
-		error = XFS_DIR_REPLACE(mp, tp, src_ip, "..", 2,
-					target_dp->i_ino, &first_block,
-					&free_list, spaceres);
+		error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino,
+					&first_block, &free_list, spaceres);
 		ASSERT(error != EEXIST);
-		if (error) {
+		if (error)
 			goto abort_return;
-		}
 		xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 	} else {
@@ -527,16 +513,14 @@
 		 * entry that's moved no longer points to it.
 		 */
 		error = xfs_droplink(tp, src_dp);
-		if (error) {
+		if (error)
 			goto abort_return;
-		}
 	}
 
-	error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen,
+	error = xfs_dir_removename(tp, src_dp, src_name, src_namelen,
 			src_ip->i_ino, &first_block, &free_list, spaceres);
-	if (error) {
+	if (error)
 		goto abort_return;
-	}
 	xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
 	/*
@@ -609,7 +593,7 @@
 	 * Let interposed file systems know about removed links.
 	 */
 	if (target_ip_dropped) {
-		VOP_LINK_REMOVED(XFS_ITOV(target_ip), target_dir_vp,
+		bhv_vop_link_removed(XFS_ITOV(target_ip), target_dir_vp,
 					target_link_zero);
 		IRELE(target_ip);
 	}
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 5b41394..5a0b678 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -141,7 +139,7 @@
 		cancelflags |= XFS_TRANS_ABORT;
 		error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks,
 			XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock,
-			resblks, &map, &nmap, &flist);
+			resblks, &map, &nmap, &flist, NULL);
 		if (!error && nmap < 1)
 			error = XFS_ERROR(ENOSPC);
 		if (error)
@@ -1931,7 +1929,7 @@
 	/*
 	 * Initial error checking.
 	 */
-	if (mp->m_rtdev_targp || mp->m_rbmip == NULL ||
+	if (mp->m_rtdev_targp == NULL || mp->m_rbmip == NULL ||
 	    (nrblocks = in->newblocks) <= sbp->sb_rblocks ||
 	    (sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
 		return XFS_ERROR(EINVAL);
@@ -2404,10 +2402,10 @@
 {
 	xfs_extlen_t	i;		/* block number in the extent */
 
-	printk("%Ld: ", (long long)start);
+	cmn_err(CE_DEBUG, "%Ld: ", (long long)start);
 	for (i = 0; i < len; i++)
-		printk("%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
-	printk("\n");
+		cmn_err(CE_DEBUG, "%d", xfs_rtcheck_bit(mp, tp, start + i, 1));
+	cmn_err(CE_DEBUG, "\n");
 }
 
 /*
@@ -2431,17 +2429,17 @@
 			(void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c);
 			if (c) {
 				if (!p) {
-					printk("%Ld-%Ld:", 1LL << l,
+					cmn_err(CE_DEBUG, "%Ld-%Ld:", 1LL << l,
 						XFS_RTMIN((1LL << l) +
 							  ((1LL << l) - 1LL),
 							 mp->m_sb.sb_rextents));
 					p = 1;
 				}
-				printk(" %Ld:%d", (long long)i, c);
+				cmn_err(CE_DEBUG, " %Ld:%d", (long long)i, c);
 			}
 		}
 		if (p)
-			printk("\n");
+			cmn_err(CE_DEBUG, "\n");
 	}
 	if (sumbp)
 		xfs_trans_brelse(tp, sumbp);
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c
index a59c102..defb2fe 100644
--- a/fs/xfs/xfs_rw.c
+++ b/fs/xfs/xfs_rw.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -92,6 +90,90 @@
 }
 
 /*
+ * Handle logging requirements of various synchronous types of write.
+ */
+int
+xfs_write_sync_logforce(
+	xfs_mount_t	*mp,
+	xfs_inode_t	*ip)
+{
+	int		error = 0;
+
+	/*
+	 * If we're treating this as O_DSYNC and we have not updated the
+	 * size, force the log.
+	 */
+	if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) &&
+	    !(ip->i_update_size)) {
+		xfs_inode_log_item_t	*iip = ip->i_itemp;
+
+		/*
+		 * If an allocation transaction occurred
+		 * without extending the size, then we have to force
+		 * the log up the proper point to ensure that the
+		 * allocation is permanent.  We can't count on
+		 * the fact that buffered writes lock out direct I/O
+		 * writes - the direct I/O write could have extended
+		 * the size nontransactionally, then finished before
+		 * we started.  xfs_write_file will think that the file
+		 * didn't grow but the update isn't safe unless the
+		 * size change is logged.
+		 *
+		 * Force the log if we've committed a transaction
+		 * against the inode or if someone else has and
+		 * the commit record hasn't gone to disk (e.g.
+		 * the inode is pinned).  This guarantees that
+		 * all changes affecting the inode are permanent
+		 * when we return.
+		 */
+		if (iip && iip->ili_last_lsn) {
+			xfs_log_force(mp, iip->ili_last_lsn,
+					XFS_LOG_FORCE | XFS_LOG_SYNC);
+		} else if (xfs_ipincount(ip) > 0) {
+			xfs_log_force(mp, (xfs_lsn_t)0,
+					XFS_LOG_FORCE | XFS_LOG_SYNC);
+		}
+
+	} else {
+		xfs_trans_t	*tp;
+
+		/*
+		 * O_SYNC or O_DSYNC _with_ a size update are handled
+		 * the same way.
+		 *
+		 * If the write was synchronous then we need to make
+		 * sure that the inode modification time is permanent.
+		 * We'll have updated the timestamp above, so here
+		 * we use a synchronous transaction to log the inode.
+		 * It's not fast, but it's necessary.
+		 *
+		 * If this a dsync write and the size got changed
+		 * non-transactionally, then we need to ensure that
+		 * the size change gets logged in a synchronous
+		 * transaction.
+		 */
+		tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC);
+		if ((error = xfs_trans_reserve(tp, 0,
+						XFS_SWRITE_LOG_RES(mp),
+						0, 0, 0))) {
+			/* Transaction reserve failed */
+			xfs_trans_cancel(tp, 0);
+		} else {
+			/* Transaction reserve successful */
+			xfs_ilock(ip, XFS_ILOCK_EXCL);
+			xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+			xfs_trans_ihold(tp, ip);
+			xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+			xfs_trans_set_sync(tp);
+			error = xfs_trans_commit(tp, 0, NULL);
+			xfs_iunlock(ip, XFS_ILOCK_EXCL);
+		}
+	}
+
+	return error;
+}
+
+/*
  * Force a shutdown of the filesystem instantly while keeping
  * the filesystem consistent. We don't do an unmount here; just shutdown
  * the shop, make sure that absolutely nothing persistent happens to
@@ -109,12 +191,12 @@
 	xfs_mount_t	*mp;
 
 	mp = XFS_BHVTOM(bdp);
-	logerror = flags & XFS_LOG_IO_ERROR;
+	logerror = flags & SHUTDOWN_LOG_IO_ERROR;
 
-	if (!(flags & XFS_FORCE_UMOUNT)) {
-		cmn_err(CE_NOTE,
-		"xfs_force_shutdown(%s,0x%x) called from line %d of file %s.  Return address = 0x%p",
-			mp->m_fsname,flags,lnnum,fname,__return_address);
+	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
+		cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from "
+				 "line %d of file %s.  Return address = 0x%p",
+			mp->m_fsname, flags, lnnum, fname, __return_address);
 	}
 	/*
 	 * No need to duplicate efforts.
@@ -125,33 +207,37 @@
 	/*
 	 * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
 	 * queue up anybody new on the log reservations, and wakes up
-	 * everybody who's sleeping on log reservations and tells
-	 * them the bad news.
+	 * everybody who's sleeping on log reservations to tell them
+	 * the bad news.
 	 */
 	if (xfs_log_force_umount(mp, logerror))
 		return;
 
-	if (flags & XFS_CORRUPT_INCORE) {
+	if (flags & SHUTDOWN_CORRUPT_INCORE) {
 		xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
     "Corruption of in-memory data detected.  Shutting down filesystem: %s",
 			mp->m_fsname);
 		if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
 			xfs_stack_trace();
 		}
-	} else if (!(flags & XFS_FORCE_UMOUNT)) {
+	} else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
 		if (logerror) {
 			xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
-			"Log I/O Error Detected.  Shutting down filesystem: %s",
+		"Log I/O Error Detected.  Shutting down filesystem: %s",
 				mp->m_fsname);
-		} else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) {
+		} else if (flags & SHUTDOWN_DEVICE_REQ) {
 			xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
-				"I/O Error Detected.  Shutting down filesystem: %s",
+		"All device paths lost.  Shutting down filesystem: %s",
+				mp->m_fsname);
+		} else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
+			xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
+		"I/O Error Detected.  Shutting down filesystem: %s",
 				mp->m_fsname);
 		}
 	}
-	if (!(flags & XFS_FORCE_UMOUNT)) {
-		cmn_err(CE_ALERT,
-		"Please umount the filesystem, and rectify the problem(s)");
+	if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
+		cmn_err(CE_ALERT, "Please umount the filesystem, "
+				  "and rectify the problem(s)");
 	}
 }
 
@@ -335,7 +421,7 @@
 		 * from bwrite and we could be tracing a buffer that has
 		 * been reused.
 		 */
-		xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
+		xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
 	}
 	return (error);
 }
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h
index e637956..188b296 100644
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -75,6 +75,7 @@
  * Prototypes for functions in xfs_rw.c.
  */
 extern int xfs_write_clear_setuid(struct xfs_inode *ip);
+extern int xfs_write_sync_logforce(struct xfs_mount *mp, struct xfs_inode *ip);
 extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp);
 extern int xfs_bioerror(struct xfs_buf *bp);
 extern int xfs_bioerror_relse(struct xfs_buf *bp);
@@ -87,9 +88,10 @@
 /*
  * Prototypes for functions in xfs_vnodeops.c.
  */
-extern int xfs_rwlock(bhv_desc_t *bdp, vrwlock_t write_lock);
-extern void xfs_rwunlock(bhv_desc_t *bdp, vrwlock_t write_lock);
-extern int xfs_setattr(bhv_desc_t *bdp, vattr_t *vap, int flags, cred_t *credp);
+extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
+extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
+extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
+		       cred_t *credp);
 extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
 				 xfs_off_t offset, cred_t *credp, int flags);
 extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 8d056ce..ee2721e 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -33,7 +32,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -236,11 +234,8 @@
 	xfs_mount_t	*mp,
 	uint		type)
 {
-	fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
-	atomic_inc(&mp->m_active_trans);
-
-	return (_xfs_trans_alloc(mp, type));
-
+	vfs_wait_for_freeze(XFS_MTOVFS(mp), SB_FREEZE_TRANS);
+	return _xfs_trans_alloc(mp, type);
 }
 
 xfs_trans_t *
@@ -250,12 +245,9 @@
 {
 	xfs_trans_t	*tp;
 
-	ASSERT(xfs_trans_zone != NULL);
-	tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
+	atomic_inc(&mp->m_active_trans);
 
-	/*
-	 * Initialize the transaction structure.
-	 */
+	tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP);
 	tp->t_magic = XFS_TRANS_MAGIC;
 	tp->t_type = type;
 	tp->t_mountp = mp;
@@ -263,8 +255,7 @@
 	tp->t_busy_free = XFS_LBC_NUM_SLOTS;
 	XFS_LIC_INIT(&(tp->t_items));
 	XFS_LBC_INIT(&(tp->t_busy));
-
-	return (tp);
+	return tp;
 }
 
 /*
@@ -303,7 +294,7 @@
 	tp->t_blk_res = tp->t_blk_res_used;
 	ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used;
 	tp->t_rtx_res = tp->t_rtx_res_used;
-	PFLAGS_DUP(&tp->t_pflags, &ntp->t_pflags);
+	ntp->t_pflags = tp->t_pflags;
 
 	XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp);
 
@@ -335,14 +326,11 @@
 	uint		logcount)
 {
 	int		log_flags;
-	int		error;
-	int	rsvd;
-
-	error = 0;
-	rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
+	int		error = 0;
+	int		rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
 
 	/* Mark this thread as being in a transaction */
-        PFLAGS_SET_FSTRANS(&tp->t_pflags);
+	current_set_flags_nested(&tp->t_pflags, PF_FSTRANS);
 
 	/*
 	 * Attempt to reserve the needed disk blocks by decrementing
@@ -353,7 +341,7 @@
 		error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS,
 					  -blocks, rsvd);
 		if (error != 0) {
-                        PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
+			current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 			return (XFS_ERROR(ENOSPC));
 		}
 		tp->t_blk_res += blocks;
@@ -426,9 +414,9 @@
 		tp->t_blk_res = 0;
 	}
 
-        PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
+	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 
-	return (error);
+	return error;
 }
 
 
@@ -819,7 +807,7 @@
 			if (commit_lsn == -1 && !shutdown)
 				shutdown = XFS_ERROR(EIO);
 		}
-                PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
+		current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 		xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0);
 		xfs_trans_free_busy(tp);
 		xfs_trans_free(tp);
@@ -846,7 +834,7 @@
 	 */
 	nvec = xfs_trans_count_vecs(tp);
 	if (nvec == 0) {
-		xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
+		xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
 		goto shut_us_down;
 	} else if (nvec <= XFS_TRANS_LOGVEC_COUNT) {
 		log_vector = log_vector_fast;
@@ -884,7 +872,7 @@
 	 * had pinned, clean up, free trans structure, and return error.
 	 */
 	if (error || commit_lsn == -1) {
-                PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
+		current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 		xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT);
 		return XFS_ERROR(EIO);
 	}
@@ -926,7 +914,7 @@
 	/*
 	 * Mark this thread as no longer being in a transaction
 	 */
-	PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
+	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 
 	/*
 	 * Once all the items of the transaction have been copied
@@ -1148,7 +1136,7 @@
 	 */
 	if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) {
 		XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp);
-		xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
+		xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 	}
 #ifdef DEBUG
 	if (!(flags & XFS_TRANS_ABORT)) {
@@ -1182,7 +1170,7 @@
 	}
 
 	/* mark this thread as no longer being in a transaction */
-        PFLAGS_RESTORE_FSTRANS(&tp->t_pflags);
+	current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
 
 	xfs_trans_free_items(tp, flags);
 	xfs_trans_free_busy(tp);
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 100d9a4..9dc88b3 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -338,8 +338,6 @@
 typedef struct xfs_trans {
 	unsigned int		t_magic;	/* magic number */
 	xfs_log_callback_t	t_logcb;	/* log callback struct */
-	struct xfs_trans	*t_forw;	/* async list pointers */
-	struct xfs_trans	*t_back;	/* async list pointers */
 	unsigned int		t_type;		/* transaction type */
 	unsigned int		t_log_res;	/* amt of log space resvd */
 	unsigned int		t_log_count;	/* count for perm log res */
@@ -364,9 +362,11 @@
 	long			t_res_fdblocks_delta; /* on-disk only chg */
 	long			t_frextents_delta;/* superblock freextents chg*/
 	long			t_res_frextents_delta; /* on-disk only chg */
+#ifdef DEBUG
 	long			t_ag_freeblks_delta; /* debugging counter */
 	long			t_ag_flist_delta; /* debugging counter */
 	long			t_ag_btree_delta; /* debugging counter */
+#endif
 	long			t_dblocks_delta;/* superblock dblocks change */
 	long			t_agcount_delta;/* superblock agcount change */
 	long			t_imaxpct_delta;/* superblock imaxpct change */
@@ -805,12 +805,9 @@
 	((mp)->m_sb.sb_inodesize + \
 	 (mp)->m_sb.sb_sectsize * 2 + \
 	 (mp)->m_dirblksize + \
-	 (XFS_DIR_IS_V1(mp) ? 0 : \
-	    XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1))) + \
+	 XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \
 	 XFS_ALLOCFREE_LOG_RES(mp, 1) + \
-	 (128 * (4 + \
-		 (XFS_DIR_IS_V1(mp) ? 0 : \
-			 XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
+	 (128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \
 		 XFS_ALLOCFREE_LOG_COUNT(mp, 1))))
 
 #define	XFS_ADDAFORK_LOG_RES(mp)	((mp)->m_reservations.tr_addafork)
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 19ab24a..558c87f 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -22,7 +22,6 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_trans_priv.h"
@@ -363,9 +362,10 @@
 			AIL_UNLOCK(mp, s);
 		else {
 			xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp,
-				"xfs_trans_delete_ail: attempting to delete a log item that is not in the AIL");
+		"%s: attempting to delete a log item that is not in the AIL",
+					__FUNCTION__);
 			AIL_UNLOCK(mp, s);
-			xfs_force_shutdown(mp, XFS_CORRUPT_INCORE);
+			xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
 		}
 	}
 }
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index c74c31e..60b6b89 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -320,7 +318,7 @@
 			if (xfs_error_target == target) {
 				if (((xfs_req_num++) % xfs_error_mod) == 0) {
 					xfs_buf_relse(bp);
-					printk("Returning error!\n");
+					cmn_err(CE_DEBUG, "Returning error!\n");
 					return XFS_ERROR(EIO);
 				}
 			}
@@ -369,7 +367,7 @@
 				 */
 				if (tp->t_flags & XFS_TRANS_DIRTY)
 					xfs_force_shutdown(tp->t_mountp,
-							   XFS_METADATA_IO_ERROR);
+							SHUTDOWN_META_IO_ERROR);
 				return error;
 			}
 		}
@@ -414,7 +412,7 @@
 		xfs_ioerror_alert("xfs_trans_read_buf", mp,
 				  bp, blkno);
 		if (tp->t_flags & XFS_TRANS_DIRTY)
-			xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR);
+			xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR);
 		xfs_buf_relse(bp);
 		return error;
 	}
@@ -423,9 +421,9 @@
 		if (xfs_error_target == target) {
 			if (((xfs_req_num++) % xfs_error_mod) == 0) {
 				xfs_force_shutdown(tp->t_mountp,
-						   XFS_METADATA_IO_ERROR);
+						   SHUTDOWN_META_IO_ERROR);
 				xfs_buf_relse(bp);
-				printk("Returning error in trans!\n");
+				cmn_err(CE_DEBUG, "Returning trans error!\n");
 				return XFS_ERROR(EIO);
 			}
 		}
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index 7d7d627..b290270 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -22,7 +22,6 @@
 #include "xfs_inum.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
-#include "xfs_dir.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_trans_priv.h"
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index 7c5894d..b8db1d5 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -24,14 +24,12 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c
index 1117d60..2912aac 100644
--- a/fs/xfs/xfs_trans_item.c
+++ b/fs/xfs/xfs_trans_item.c
@@ -493,7 +493,7 @@
 				break;
 			} else {
 				/* out-of-order vacancy */
-				printk("OOO vacancy lbcp 0x%p\n", lbcp);
+				cmn_err(CE_DEBUG, "OOO vacancy lbcp 0x%p\n", lbcp);
 				ASSERT(0);
 			}
 		}
diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h
index 7fe3792..4ea2e50 100644
--- a/fs/xfs/xfs_trans_space.h
+++ b/fs/xfs/xfs_trans_space.h
@@ -30,8 +30,7 @@
 	  XFS_EXTENTADD_SPACE_RES(mp,w))
 #define	XFS_DAENTER_1B(mp,w)	((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1)
 #define	XFS_DAENTER_DBS(mp,w)	\
-	(XFS_DA_NODE_MAXDEPTH + \
-	 ((XFS_DIR_IS_V2(mp) && (w) == XFS_DATA_FORK) ? 2 : 0))
+	(XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0))
 #define	XFS_DAENTER_BLOCKS(mp,w)	\
 	(XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w))
 #define	XFS_DAENTER_BMAP1B(mp,w)	\
@@ -41,10 +40,7 @@
 #define	XFS_DAENTER_SPACE_RES(mp,w)	\
 	(XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w))
 #define	XFS_DAREMOVE_SPACE_RES(mp,w)	XFS_DAENTER_BMAPS(mp,w)
-#define	XFS_DIRENTER_MAX_SPLIT(mp,nl)	\
-	(((mp)->m_sb.sb_blocksize == 512 && \
-	  XFS_DIR_IS_V1(mp) && \
-	  (nl) >= XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN) ? 2 : 1)
+#define	XFS_DIRENTER_MAX_SPLIT(mp,nl)	1
 #define	XFS_DIRENTER_SPACE_RES(mp,nl)	\
 	(XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \
 	 XFS_DIRENTER_MAX_SPLIT(mp,nl))
@@ -57,8 +53,7 @@
  * Space reservation values for various transactions.
  */
 #define	XFS_ADDAFORK_SPACE_RES(mp)	\
-	((mp)->m_dirblkfsbs + \
-	 (XFS_DIR_IS_V1(mp) ? 0 : XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)))
+	((mp)->m_dirblkfsbs + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))
 #define	XFS_ATTRRM_SPACE_RES(mp)	\
 	XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK)
 /* This macro is not used - see inline code in xfs_attr_set */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index 34654ec..9014d7e 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -24,12 +24,10 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
 #include "xfs_bmap_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -51,10 +49,10 @@
  */
 int
 xfs_get_dir_entry(
-	vname_t		*dentry,
+	bhv_vname_t	*dentry,
 	xfs_inode_t	**ipp)
 {
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	vp = VNAME_TO_VNODE(dentry);
 
@@ -69,11 +67,11 @@
 xfs_dir_lookup_int(
 	bhv_desc_t	*dir_bdp,
 	uint		lock_mode,
-	vname_t		*dentry,
+	bhv_vname_t	*dentry,
 	xfs_ino_t	*inum,
 	xfs_inode_t	**ipp)
 {
-	vnode_t		*dir_vp;
+	bhv_vnode_t	*dir_vp;
 	xfs_inode_t	*dp;
 	int		error;
 
@@ -82,8 +80,7 @@
 
 	dp = XFS_BHVTOI(dir_bdp);
 
-	error = XFS_DIR_LOOKUP(dp->i_mount, NULL, dp,
-				VNAME(dentry), VNAMELEN(dentry), inum);
+	error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum);
 	if (!error) {
 		/*
 		 * Unlock the directory. We do this because we can't
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h
index 472661a..fe953e98 100644
--- a/fs/xfs/xfs_utils.h
+++ b/fs/xfs/xfs_utils.h
@@ -23,9 +23,10 @@
 #define	ITRACE(ip)	vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \
 				(inst_t *)__return_address)
 
-extern int xfs_rename (bhv_desc_t *, vname_t *, vnode_t *, vname_t *, cred_t *);
-extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **);
-extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *,
+extern int xfs_rename (bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
+			bhv_vname_t *, cred_t *);
+extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **);
+extern int xfs_dir_lookup_int (bhv_desc_t *, uint, bhv_vname_t *, xfs_ino_t *,
 				xfs_inode_t **);
 extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *);
 extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t,
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index 36ea1b2..6c96391 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -24,7 +24,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -32,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_ialloc_btree.h"
 #include "xfs_alloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -131,9 +129,6 @@
 #ifdef XFS_BMBT_TRACE
 	xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);
 #endif
-#ifdef XFS_DIR_TRACE
-	xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_TRACE_SIZE, KM_SLEEP);
-#endif
 #ifdef XFS_ATTR_TRACE
 	xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);
 #endif
@@ -177,9 +172,6 @@
 #ifdef XFS_ATTR_TRACE
 	ktrace_free(xfs_attr_trace_buf);
 #endif
-#ifdef XFS_DIR_TRACE
-	ktrace_free(xfs_dir_trace_buf);
-#endif
 #ifdef XFS_BMBT_TRACE
 	ktrace_free(xfs_bmbt_trace_buf);
 #endif
@@ -212,7 +204,7 @@
  */
 STATIC int
 xfs_start_flags(
-	struct vfs		*vfs,
+	struct bhv_vfs		*vfs,
 	struct xfs_mount_args	*ap,
 	struct xfs_mount	*mp)
 {
@@ -337,7 +329,7 @@
  */
 STATIC int
 xfs_finish_flags(
-	struct vfs		*vfs,
+	struct bhv_vfs		*vfs,
 	struct xfs_mount_args	*ap,
 	struct xfs_mount	*mp)
 {
@@ -423,7 +415,7 @@
 	struct xfs_mount_args	*args,
 	cred_t			*credp)
 {
-	struct vfs		*vfsp = bhvtovfs(bhvp);
+	struct bhv_vfs		*vfsp = bhvtovfs(bhvp);
 	struct bhv_desc		*p;
 	struct xfs_mount	*mp = XFS_BHVTOM(bhvp);
 	struct block_device	*ddev, *logdev, *rtdev;
@@ -552,10 +544,10 @@
 	int		flags,
 	cred_t		*credp)
 {
-	struct vfs	*vfsp = bhvtovfs(bdp);
+	bhv_vfs_t	*vfsp = bhvtovfs(bdp);
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
 	xfs_inode_t	*rip;
-	vnode_t		*rvp;
+	bhv_vnode_t	*rvp;
 	int		unmount_event_wanted = 0;
 	int		unmount_event_flags = 0;
 	int		xfs_unmountfs_needed = 0;
@@ -665,9 +657,8 @@
 	int				*flags,
 	struct xfs_mount_args		*args)
 {
-	struct vfs	*vfsp = bhvtovfs(bdp);
+	bhv_vfs_t	*vfsp = bhvtovfs(bdp);
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
-	int		error;
 
 	if (!(*flags & MS_RDONLY)) {			/* rw/ro -> rw */
 		if (vfsp->vfs_flag & VFS_RDONLY)
@@ -679,7 +670,7 @@
 			mp->m_flags &= ~XFS_MOUNT_BARRIER;
 		}
 	} else if (!(vfsp->vfs_flag & VFS_RDONLY)) {	/* rw -> ro */
-		VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error);
+		bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL);
 		xfs_quiesce_fs(mp);
 		xfs_log_unmount_write(mp);
 		xfs_unmountfs_writesb(mp);
@@ -702,7 +693,7 @@
 	xfs_inode_t	*rip = mp->m_rootip;
 	xfs_inode_t	*rbmip;
 	xfs_inode_t	*rsumip = NULL;
-	vnode_t		*rvp = XFS_ITOV(rip);
+	bhv_vnode_t	*rvp = XFS_ITOV(rip);
 	int		error;
 
 	xfs_ilock(rip, XFS_ILOCK_EXCL);
@@ -781,9 +772,9 @@
 STATIC int
 xfs_root(
 	bhv_desc_t	*bdp,
-	vnode_t		**vpp)
+	bhv_vnode_t	**vpp)
 {
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip);
 	VN_HOLD(vp);
@@ -801,8 +792,8 @@
 STATIC int
 xfs_statvfs(
 	bhv_desc_t	*bdp,
-	xfs_statfs_t	*statp,
-	vnode_t		*vp)
+	bhv_statvfs_t	*statp,
+	bhv_vnode_t	*vp)
 {
 	__uint64_t	fakeinos;
 	xfs_extlen_t	lsize;
@@ -900,7 +891,7 @@
 /*
  * xfs sync routine for internal use
  *
- * This routine supports all of the flags defined for the generic VFS_SYNC
+ * This routine supports all of the flags defined for the generic vfs_sync
  * interface as explained above under xfs_sync.  In the interests of not
  * changing interfaces within the 6.5 family, additional internally-
  * required functions are specified within a separate xflags parameter,
@@ -917,7 +908,7 @@
 	xfs_inode_t	*ip = NULL;
 	xfs_inode_t	*ip_next;
 	xfs_buf_t	*bp;
-	vnode_t		*vp = NULL;
+	bhv_vnode_t	*vp = NULL;
 	int		error;
 	int		last_error;
 	uint64_t	fflag;
@@ -1156,9 +1147,9 @@
 			xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
 			if (XFS_FORCED_SHUTDOWN(mp)) {
-				VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF);
+				bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF);
 			} else {
-				VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_REMAPF);
+				bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF);
 			}
 
 			xfs_ilock(ip, XFS_ILOCK_SHARED);
@@ -1178,8 +1169,8 @@
 				 * across calls to the buffer cache.
 				 */
 				xfs_iunlock(ip, XFS_ILOCK_SHARED);
-				VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1,
-							fflag, FI_NONE, error);
+				error = bhv_vop_flush_pages(vp, (xfs_off_t)0,
+							-1, fflag, FI_NONE);
 				xfs_ilock(ip, XFS_ILOCK_SHARED);
 			}
 
@@ -1231,9 +1222,7 @@
 						 * marker and free it.
 						 */
 						XFS_MOUNT_ILOCK(mp);
-
 						IPOINTER_REMOVE(ip, mp);
-
 						XFS_MOUNT_IUNLOCK(mp);
 
 						ASSERT(!(lock_flags &
@@ -1421,7 +1410,7 @@
 /*
  * xfs sync routine for internal use
  *
- * This routine supports all of the flags defined for the generic VFS_SYNC
+ * This routine supports all of the flags defined for the generic vfs_sync
  * interface as explained above under xfs_sync.  In the interests of not
  * changing interfaces within the 6.5 family, additional internally-
  * required functions are specified within a separate xflags parameter,
@@ -1574,7 +1563,7 @@
 STATIC int
 xfs_vget(
 	bhv_desc_t	*bdp,
-	vnode_t		**vpp,
+	bhv_vnode_t	**vpp,
 	fid_t		*fidp)
 {
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
@@ -1657,10 +1646,10 @@
 #define MNTOPT_NOATTR2	"noattr2"	/* do not use attr2 attribute format */
 
 STATIC unsigned long
-suffix_strtoul(const char *cp, char **endp, unsigned int base)
+suffix_strtoul(char *s, char **endp, unsigned int base)
 {
 	int	last, shift_left_factor = 0;
-	char	*value = (char *)cp;
+	char	*value = s;
 
 	last = strlen(value) - 1;
 	if (value[last] == 'K' || value[last] == 'k') {
@@ -1676,7 +1665,7 @@
 		value[last] = '\0';
 	}
 
-	return simple_strtoul(cp, endp, base) << shift_left_factor;
+	return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
 }
 
 STATIC int
@@ -1686,7 +1675,7 @@
 	struct xfs_mount_args	*args,
 	int			update)
 {
-	struct vfs		*vfsp = bhvtovfs(bhv);
+	bhv_vfs_t		*vfsp = bhvtovfs(bhv);
 	char			*this_char, *value, *eov;
 	int			dsunit, dswidth, vol_dsunit, vol_dswidth;
 	int			iosize;
@@ -1708,42 +1697,48 @@
 
 		if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			args->logbufs = simple_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			args->logbufsize = suffix_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			strncpy(args->logname, value, MAXNAMELEN);
 		} else if (!strcmp(this_char, MNTOPT_MTPT)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			strncpy(args->mtpt, value, MAXNAMELEN);
 		} else if (!strcmp(this_char, MNTOPT_RTDEV)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			strncpy(args->rtname, value, MAXNAMELEN);
 		} else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -1752,7 +1747,8 @@
 			args->iosizelog = (uint8_t) iosize;
 		} else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -1761,7 +1757,8 @@
 			args->iosizelog = ffs(iosize) - 1;
 		} else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -1782,7 +1779,8 @@
 		} else if (!strcmp(this_char, MNTOPT_INO64)) {
 			args->flags |= XFSMNT_INO64;
 #if !XFS_BIG_INUMS
-			printk("XFS: %s option not allowed on this system\n",
+			cmn_err(CE_WARN,
+				"XFS: %s option not allowed on this system",
 				this_char);
 			return EINVAL;
 #endif
@@ -1792,14 +1790,16 @@
 			args->flags |= XFSMNT_SWALLOC;
 		} else if (!strcmp(this_char, MNTOPT_SUNIT)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
 			dsunit = simple_strtoul(value, &eov, 10);
 		} else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
 			if (!value || !*value) {
-				printk("XFS: %s option requires an argument\n",
+				cmn_err(CE_WARN,
+					"XFS: %s option requires an argument",
 					this_char);
 				return EINVAL;
 			}
@@ -1807,7 +1807,8 @@
 		} else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
 			args->flags &= ~XFSMNT_32BITINODES;
 #if !XFS_BIG_INUMS
-			printk("XFS: %s option not allowed on this system\n",
+			cmn_err(CE_WARN,
+				"XFS: %s option not allowed on this system",
 				this_char);
 			return EINVAL;
 #endif
@@ -1831,36 +1832,41 @@
 			args->flags &= ~XFSMNT_ATTR2;
 		} else if (!strcmp(this_char, "osyncisdsync")) {
 			/* no-op, this is now the default */
-printk("XFS: osyncisdsync is now the default, option is deprecated.\n");
+			cmn_err(CE_WARN,
+	"XFS: osyncisdsync is now the default, option is deprecated.");
 		} else if (!strcmp(this_char, "irixsgid")) {
-printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
+			cmn_err(CE_WARN,
+	"XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
 		} else {
-			printk("XFS: unknown mount option [%s].\n", this_char);
+			cmn_err(CE_WARN,
+				"XFS: unknown mount option [%s].", this_char);
 			return EINVAL;
 		}
 	}
 
 	if (args->flags & XFSMNT_NORECOVERY) {
 		if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {
-			printk("XFS: no-recovery mounts must be read-only.\n");
+			cmn_err(CE_WARN,
+				"XFS: no-recovery mounts must be read-only.");
 			return EINVAL;
 		}
 	}
 
 	if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
-		printk(
-	"XFS: sunit and swidth options incompatible with the noalign option\n");
+		cmn_err(CE_WARN,
+	"XFS: sunit and swidth options incompatible with the noalign option");
 		return EINVAL;
 	}
 
 	if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
-		printk("XFS: sunit and swidth must be specified together\n");
+		cmn_err(CE_WARN,
+			"XFS: sunit and swidth must be specified together");
 		return EINVAL;
 	}
 
 	if (dsunit && (dswidth % dsunit != 0)) {
-		printk(
-	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n",
+		cmn_err(CE_WARN,
+	"XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
 			dswidth, dsunit);
 		return EINVAL;
 	}
@@ -1907,7 +1913,7 @@
 	};
 	struct proc_xfs_info	*xfs_infop;
 	struct xfs_mount	*mp = XFS_BHVTOM(bhv);
-	struct vfs		*vfsp = XFS_MTOVFS(mp);
+	struct bhv_vfs		*vfsp = XFS_MTOVFS(mp);
 
 	for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
 		if (mp->m_flags & xfs_infop->flag)
@@ -1967,7 +1973,7 @@
 }
 
 
-vfsops_t xfs_vfsops = {
+bhv_vfsops_t xfs_vfsops = {
 	BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
 	.vfs_parseargs		= xfs_parseargs,
 	.vfs_showargs		= xfs_showargs,
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 7027ae6..23cfa58 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -16,8 +16,6 @@
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <linux/capability.h>
-
 #include "xfs.h"
 #include "xfs_fs.h"
 #include "xfs_types.h"
@@ -27,7 +25,6 @@
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_dmapi.h"
 #include "xfs_mount.h"
@@ -35,13 +32,11 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
 #include "xfs_inode.h"
 #include "xfs_inode_item.h"
-#include "xfs_dir_leaf.h"
 #include "xfs_itable.h"
 #include "xfs_btree.h"
 #include "xfs_ialloc.h"
@@ -58,32 +53,14 @@
 #include "xfs_log_priv.h"
 #include "xfs_mac.h"
 
-
-/*
- * The maximum pathlen is 1024 bytes. Since the minimum file system
- * blocksize is 512 bytes, we can get a max of 2 extents back from
- * bmapi.
- */
-#define SYMLINK_MAPS 2
-
-/*
- * For xfs, we check that the file isn't too big to be opened by this kernel.
- * No other open action is required for regular files.  Devices are handled
- * through the specfs file system, pipes through fifofs.  Device and
- * fifo vnodes are "wrapped" by specfs and fifofs vnodes, respectively,
- * when a new vnode is first looked up or created.
- */
 STATIC int
 xfs_open(
 	bhv_desc_t	*bdp,
 	cred_t		*credp)
 {
 	int		mode;
-	vnode_t		*vp;
-	xfs_inode_t	*ip;
-
-	vp = BHV_TO_VNODE(bdp);
-	ip = XFS_BHVTOI(bdp);
+	bhv_vnode_t	*vp = BHV_TO_VNODE(bdp);
+	xfs_inode_t	*ip = XFS_BHVTOI(bdp);
 
 	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
 		return XFS_ERROR(EIO);
@@ -101,6 +78,35 @@
 	return 0;
 }
 
+STATIC int
+xfs_close(
+	bhv_desc_t	*bdp,
+	int		flags,
+	lastclose_t	lastclose,
+	cred_t		*credp)
+{
+	bhv_vnode_t	*vp = BHV_TO_VNODE(bdp);
+	xfs_inode_t	*ip = XFS_BHVTOI(bdp);
+
+	if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+		return XFS_ERROR(EIO);
+
+	if (lastclose != L_TRUE || !VN_ISREG(vp))
+		return 0;
+
+	/*
+	 * If we previously truncated this file and removed old data in
+	 * the process, we want to initiate "early" writeout on the last
+	 * close.  This is an attempt to combat the notorious NULL files
+	 * problem which is particularly noticable from a truncate down,
+	 * buffered (re-)write (delalloc), followed by a crash.  What we
+	 * are effectively doing here is significantly reducing the time
+	 * window where we'd otherwise be exposed to that problem.
+	 */
+	if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0)
+		return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE);
+	return 0;
+}
 
 /*
  * xfs_getattr
@@ -108,13 +114,13 @@
 STATIC int
 xfs_getattr(
 	bhv_desc_t	*bdp,
-	vattr_t		*vap,
+	bhv_vattr_t	*vap,
 	int		flags,
 	cred_t		*credp)
 {
 	xfs_inode_t	*ip;
 	xfs_mount_t	*mp;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	vp  = BHV_TO_VNODE(bdp);
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -241,7 +247,7 @@
 int
 xfs_setattr(
 	bhv_desc_t		*bdp,
-	vattr_t			*vap,
+	bhv_vattr_t		*vap,
 	int			flags,
 	cred_t			*credp)
 {
@@ -255,7 +261,7 @@
 	uid_t			uid=0, iuid=0;
 	gid_t			gid=0, igid=0;
 	int			timeflags = 0;
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	xfs_prid_t		projid=0, iprojid=0;
 	int			mandlock_before, mandlock_after;
 	struct xfs_dquot	*udqp, *gdqp, *olddquot1, *olddquot2;
@@ -347,7 +353,6 @@
 	 */
 	tp = NULL;
 	lock_flags = XFS_ILOCK_EXCL;
-	ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1);
 	if (flags & ATTR_NOLOCK)
 		need_iolock = 0;
 	if (!(mask & XFS_AT_SIZE)) {
@@ -666,9 +671,17 @@
 					    ((ip->i_d.di_nlink != 0 ||
 					      !(mp->m_flags & XFS_MOUNT_WSYNC))
 					     ? 1 : 0));
-			if (code) {
+			if (code)
 				goto abort_return;
-			}
+			/*
+			 * Truncated "down", so we're removing references
+			 * to old data here - if we now delay flushing for
+			 * a long time, we expose ourselves unduly to the
+			 * notorious NULL files problem.  So, we mark this
+			 * vnode and flush it when the file is closed, and
+			 * do not wait the usual (long) time for writeout.
+			 */
+			VTRUNCATE(vp);
 		}
 		/*
 		 * Have to do this even if the file's size doesn't change.
@@ -800,6 +813,8 @@
 				di_flags |= XFS_DIFLAG_NODUMP;
 			if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
 				di_flags |= XFS_DIFLAG_PROJINHERIT;
+			if (vap->va_xflags & XFS_XFLAG_NODEFRAG)
+				di_flags |= XFS_DIFLAG_NODEFRAG;
 			if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
 				if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
 					di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -869,7 +884,7 @@
 	 */
 	mandlock_after = MANDLOCK(vp, ip->i_d.di_mode);
 	if (mandlock_before != mandlock_after) {
-		VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_ENF_LOCKING,
+		bhv_vop_vnode_change(vp, VCHANGE_FLAGS_ENF_LOCKING,
 				 mandlock_after);
 	}
 
@@ -936,6 +951,13 @@
 
 
 /*
+ * The maximum pathlen is 1024 bytes. Since the minimum file system
+ * blocksize is 512 bytes, we can get a max of 2 extents back from
+ * bmapi.
+ */
+#define SYMLINK_MAPS 2
+
+/*
  * xfs_readlink
  *
  */
@@ -950,7 +972,7 @@
 	int		count;
 	xfs_off_t	offset;
 	int		pathlen;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 	int		error = 0;
 	xfs_mount_t	*mp;
 	int             nmaps;
@@ -1000,7 +1022,7 @@
 		nmaps = SYMLINK_MAPS;
 
 		error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen),
-				  0, NULL, 0, mval, &nmaps, NULL);
+				  0, NULL, 0, mval, &nmaps, NULL, NULL);
 
 		if (error) {
 			goto error_return;
@@ -1208,8 +1230,8 @@
 
 	nimaps = 1;
 	xfs_ilock(ip, XFS_ILOCK_SHARED);
-	error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0,
-			  NULL, 0, &imap, &nimaps, NULL);
+	error = XFS_BMAPI(mp, NULL, &ip->i_iocore, end_fsb, map_len, 0,
+			  NULL, 0, &imap, &nimaps, NULL, NULL);
 	xfs_iunlock(ip, XFS_ILOCK_SHARED);
 
 	if (!error && (nimaps != 0) &&
@@ -1338,7 +1360,7 @@
 	nmaps = ARRAY_SIZE(mval);
 	if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
 			XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
-			&free_list)))
+			&free_list, NULL)))
 		goto error0;
 	/*
 	 * Invalidate the block(s).
@@ -1353,7 +1375,7 @@
 	 * Unmap the dead block(s) to the free_list.
 	 */
 	if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps,
-			&first_block, &free_list, &done)))
+			&first_block, &free_list, NULL, &done)))
 		goto error1;
 	ASSERT(done);
 	/*
@@ -1469,9 +1491,6 @@
 	return 0;
 }
 
-/*
- *
- */
 STATIC int
 xfs_inactive_attrs(
 	xfs_inode_t	*ip,
@@ -1524,16 +1543,16 @@
 	bhv_desc_t	*bdp)
 {
 	xfs_inode_t	*ip;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 	xfs_mount_t	*mp;
 	int		error;
 
 	vp = BHV_TO_VNODE(bdp);
 	ip = XFS_BHVTOI(bdp);
+	mp = ip->i_mount;
 
-	if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) {
+	if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0))
 		return 0;
-	}
 
 	/* If this is a read-only mount, don't do this (would generate I/O) */
 	if (vp->v_vfsp->vfs_flag & VFS_RDONLY)
@@ -1545,8 +1564,6 @@
 		return 0;
 #endif
 
-	mp = ip->i_mount;
-
 	if (ip->i_d.di_nlink != 0) {
 		if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) &&
 		     ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 ||
@@ -1579,8 +1596,8 @@
 	cred_t		*credp)
 {
 	xfs_inode_t	*ip;
-	vnode_t		*vp;
-	xfs_bmap_free_t	free_list; 
+	bhv_vnode_t	*vp;
+	xfs_bmap_free_t	free_list;
 	xfs_fsblock_t	first_block;
 	int		committed;
 	xfs_trans_t	*tp;
@@ -1760,7 +1777,7 @@
 			cmn_err(CE_NOTE,
 		"xfs_inactive:	xfs_ifree() returned an error = %d on %s",
 				error, mp->m_fsname);
-			xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR);
+			xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);
 		}
 		xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT);
 	} else {
@@ -1795,17 +1812,17 @@
 STATIC int
 xfs_lookup(
 	bhv_desc_t		*dir_bdp,
-	vname_t			*dentry,
-	vnode_t			**vpp,
+	bhv_vname_t		*dentry,
+	bhv_vnode_t		**vpp,
 	int			flags,
-	vnode_t			*rdir,
+	bhv_vnode_t		*rdir,
 	cred_t			*credp)
 {
 	xfs_inode_t		*dp, *ip;
 	xfs_ino_t		e_inum;
 	int			error;
 	uint			lock_mode;
-	vnode_t			*dir_vp;
+	bhv_vnode_t		*dir_vp;
 
 	dir_vp = BHV_TO_VNODE(dir_bdp);
 	vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address);
@@ -1832,15 +1849,15 @@
 STATIC int
 xfs_create(
 	bhv_desc_t		*dir_bdp,
-	vname_t			*dentry,
-	vattr_t			*vap,
-	vnode_t			**vpp,
+	bhv_vname_t		*dentry,
+	bhv_vattr_t		*vap,
+	bhv_vnode_t		**vpp,
 	cred_t			*credp)
 {
 	char			*name = VNAME(dentry);
-	vnode_t			*dir_vp;
+	bhv_vnode_t		*dir_vp;
 	xfs_inode_t		*dp, *ip;
-	vnode_t		        *vp=NULL;
+	bhv_vnode_t	        *vp = NULL;
 	xfs_trans_t		*tp;
 	xfs_mount_t	        *mp;
 	xfs_dev_t		rdev;
@@ -1938,8 +1955,7 @@
 	if (error)
 		goto error_return;
 
-	if (resblks == 0 &&
-	    (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen)))
+	if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen)))
 		goto error_return;
 	rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0;
 	error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1,
@@ -1970,9 +1986,9 @@
 	xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
 	dp_joined_to_trans = B_TRUE;
 
-	error = XFS_DIR_CREATENAME(mp, tp, dp, name, namelen, ip->i_ino,
-		&first_block, &free_list,
-		resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+	error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino,
+					&first_block, &free_list, resblks ?
+					resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
 	if (error) {
 		ASSERT(error != ENOSPC);
 		goto abort_return;
@@ -2026,7 +2042,7 @@
 	 * Propagate the fact that the vnode changed after the
 	 * xfs_inode locks have been released.
 	 */
-	VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3);
+	bhv_vop_vnode_change(vp, VCHANGE_FLAGS_TRUNCATED, 3);
 
 	*vpp = vp;
 
@@ -2107,7 +2123,7 @@
 STATIC int
 xfs_lock_dir_and_entry(
 	xfs_inode_t	*dp,
-	vname_t		*dentry,
+	bhv_vname_t	*dentry,
 	xfs_inode_t	*ip)	/* inode of entry 'name' */
 {
 	int		attempts;
@@ -2321,10 +2337,10 @@
 STATIC int
 xfs_remove(
 	bhv_desc_t		*dir_bdp,
-	vname_t			*dentry,
+	bhv_vname_t		*dentry,
 	cred_t			*credp)
 {
-	vnode_t			*dir_vp;
+	bhv_vnode_t		*dir_vp;
 	char			*name = VNAME(dentry);
 	xfs_inode_t             *dp, *ip;
 	xfs_trans_t             *tp = NULL;
@@ -2448,8 +2464,8 @@
 	 * Entry must exist since we did a lookup in xfs_lock_dir_and_entry.
 	 */
 	XFS_BMAP_INIT(&free_list, &first_block);
-	error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, ip->i_ino,
-		&first_block, &free_list, 0);
+	error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino,
+					&first_block, &free_list, 0);
 	if (error) {
 		ASSERT(error != ENOENT);
 		REMOVE_DEBUG_TRACE(__LINE__);
@@ -2511,7 +2527,7 @@
 	/*
 	 * Let interposed file systems know about removed links.
 	 */
-	VOP_LINK_REMOVED(XFS_ITOV(ip), dir_vp, link_zero);
+	bhv_vop_link_removed(XFS_ITOV(ip), dir_vp, link_zero);
 
 	IRELE(ip);
 
@@ -2564,8 +2580,8 @@
 STATIC int
 xfs_link(
 	bhv_desc_t		*target_dir_bdp,
-	vnode_t			*src_vp,
-	vname_t			*dentry,
+	bhv_vnode_t		*src_vp,
+	bhv_vname_t		*dentry,
 	cred_t			*credp)
 {
 	xfs_inode_t		*tdp, *sip;
@@ -2577,7 +2593,7 @@
 	xfs_fsblock_t           first_block;
 	int			cancel_flags;
 	int			committed;
-	vnode_t			*target_dir_vp;
+	bhv_vnode_t		*target_dir_vp;
 	int			resblks;
 	char			*target_name = VNAME(dentry);
 	int			target_namelen;
@@ -2587,8 +2603,7 @@
 	vn_trace_entry(src_vp, __FUNCTION__, (inst_t *)__return_address);
 
 	target_namelen = VNAMELEN(dentry);
-	if (VN_ISDIR(src_vp))
-		return XFS_ERROR(EPERM);
+	ASSERT(!VN_ISDIR(src_vp));
 
 	sip = xfs_vtoi(src_vp);
 	tdp = XFS_BHVTOI(target_dir_bdp);
@@ -2668,13 +2683,12 @@
 	}
 
 	if (resblks == 0 &&
-	    (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name,
-			target_namelen)))
+	    (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen)))
 		goto error_return;
 
 	XFS_BMAP_INIT(&free_list, &first_block);
 
-	error = XFS_DIR_CREATENAME(mp, tp, tdp, target_name, target_namelen,
+	error = xfs_dir_createname(tp, tdp, target_name, target_namelen,
 				   sip->i_ino, &first_block, &free_list,
 				   resblks);
 	if (error)
@@ -2684,9 +2698,8 @@
 	xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
 
 	error = xfs_bumplink(tp, sip);
-	if (error) {
+	if (error)
 		goto abort_return;
-	}
 
 	/*
 	 * If this is a synchronous mount, make sure that the
@@ -2704,9 +2717,8 @@
 	}
 
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
-	if (error) {
+	if (error)
 		goto std_return;
-	}
 
 	/* Fall through to std_return with error = 0. */
 std_return:
@@ -2727,6 +2739,8 @@
 	xfs_trans_cancel(tp, cancel_flags);
 	goto std_return;
 }
+
+
 /*
  * xfs_mkdir
  *
@@ -2734,15 +2748,15 @@
 STATIC int
 xfs_mkdir(
 	bhv_desc_t		*dir_bdp,
-	vname_t			*dentry,
-	vattr_t			*vap,
-	vnode_t			**vpp,
+	bhv_vname_t		*dentry,
+	bhv_vattr_t		*vap,
+	bhv_vnode_t		**vpp,
 	cred_t			*credp)
 {
 	char			*dir_name = VNAME(dentry);
 	xfs_inode_t             *dp;
 	xfs_inode_t		*cdp;	/* inode of created dir */
-	vnode_t			*cvp;	/* vnode of created dir */
+	bhv_vnode_t		*cvp;	/* vnode of created dir */
 	xfs_trans_t		*tp;
 	xfs_mount_t		*mp;
 	int			cancel_flags;
@@ -2750,7 +2764,7 @@
 	int			committed;
 	xfs_bmap_free_t         free_list;
 	xfs_fsblock_t           first_block;
-	vnode_t			*dir_vp;
+	bhv_vnode_t		*dir_vp;
 	boolean_t		dp_joined_to_trans;
 	boolean_t		created = B_FALSE;
 	int			dm_event_sent = 0;
@@ -2840,7 +2854,7 @@
 		goto error_return;
 
 	if (resblks == 0 &&
-	    (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen)))
+	    (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen)))
 		goto error_return;
 	/*
 	 * create the directory inode.
@@ -2867,9 +2881,9 @@
 
 	XFS_BMAP_INIT(&free_list, &first_block);
 
-	error = XFS_DIR_CREATENAME(mp, tp, dp, dir_name, dir_namelen,
-			cdp->i_ino, &first_block, &free_list,
-			resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
+	error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino,
+				   &first_block, &free_list, resblks ?
+				   resblks - XFS_IALLOC_SPACE_RES(mp) : 0);
 	if (error) {
 		ASSERT(error != ENOSPC);
 		goto error1;
@@ -2883,16 +2897,14 @@
 	 */
 	dp->i_gen++;
 
-	error = XFS_DIR_INIT(mp, tp, cdp, dp);
-	if (error) {
+	error = xfs_dir_init(tp, cdp, dp);
+	if (error)
 		goto error2;
-	}
 
 	cdp->i_gen = 1;
 	error = xfs_bumplink(tp, dp);
-	if (error) {
+	if (error)
 		goto error2;
-	}
 
 	cvp = XFS_ITOV(cdp);
 
@@ -2969,7 +2981,7 @@
 STATIC int
 xfs_rmdir(
 	bhv_desc_t		*dir_bdp,
-	vname_t			*dentry,
+	bhv_vname_t		*dentry,
 	cred_t			*credp)
 {
 	char			*name = VNAME(dentry);
@@ -2982,7 +2994,7 @@
 	xfs_fsblock_t           first_block;
 	int			cancel_flags;
 	int			committed;
-	vnode_t			*dir_vp;
+	bhv_vnode_t		*dir_vp;
 	int			dm_di_mode = 0;
 	int			last_cdp_link;
 	int			namelen;
@@ -3101,16 +3113,15 @@
 		error = XFS_ERROR(ENOTEMPTY);
 		goto error_return;
 	}
-	if (!XFS_DIR_ISEMPTY(mp, cdp)) {
+	if (!xfs_dir_isempty(cdp)) {
 		error = XFS_ERROR(ENOTEMPTY);
 		goto error_return;
 	}
 
-	error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, cdp->i_ino,
-		&first_block, &free_list, resblks);
-	if (error) {
+	error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino,
+					&first_block, &free_list, resblks);
+	if (error)
 		goto error1;
-	}
 
 	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 
@@ -3181,7 +3192,7 @@
 	/*
 	 * Let interposed file systems know about removed links.
 	 */
-	VOP_LINK_REMOVED(XFS_ITOV(cdp), dir_vp, last_cdp_link);
+	bhv_vop_link_removed(XFS_ITOV(cdp), dir_vp, last_cdp_link);
 
 	IRELE(cdp);
 
@@ -3209,8 +3220,6 @@
 
 
 /*
- * xfs_readdir
- *
  * Read dp's entries starting at uiop->uio_offset and translate them into
  * bufsize bytes worth of struct dirents starting at bufbase.
  */
@@ -3230,28 +3239,23 @@
 					       (inst_t *)__return_address);
 	dp = XFS_BHVTOI(dir_bdp);
 
-	if (XFS_FORCED_SHUTDOWN(dp->i_mount)) {
+	if (XFS_FORCED_SHUTDOWN(dp->i_mount))
 		return XFS_ERROR(EIO);
-	}
 
 	lock_mode = xfs_ilock_map_shared(dp);
-	error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp);
+	error = xfs_dir_getdents(tp, dp, uiop, eofp);
 	xfs_iunlock_map_shared(dp, lock_mode);
 	return error;
 }
 
 
-/*
- * xfs_symlink
- *
- */
 STATIC int
 xfs_symlink(
 	bhv_desc_t		*dir_bdp,
-	vname_t			*dentry,
-	vattr_t			*vap,
+	bhv_vname_t		*dentry,
+	bhv_vattr_t		*vap,
 	char			*target_path,
-	vnode_t			**vpp,
+	bhv_vnode_t		**vpp,
 	cred_t			*credp)
 {
 	xfs_trans_t		*tp;
@@ -3263,7 +3267,7 @@
 	xfs_bmap_free_t		free_list;
 	xfs_fsblock_t		first_block;
 	boolean_t		dp_joined_to_trans;
-	vnode_t			*dir_vp;
+	bhv_vnode_t		*dir_vp;
 	uint			cancel_flags;
 	int			committed;
 	xfs_fileoff_t		first_fsb;
@@ -3308,7 +3312,7 @@
 		int len, total;
 		char *path;
 
-		for(total = 0, path = target_path; total < pathlen;) {
+		for (total = 0, path = target_path; total < pathlen;) {
 			/*
 			 * Skip any slashes.
 			 */
@@ -3402,7 +3406,7 @@
 	 * Check for ability to enter directory entry, if no space reserved.
 	 */
 	if (resblks == 0 &&
-	    (error = XFS_DIR_CANENTER(mp, tp, dp, link_name, link_namelen)))
+	    (error = xfs_dir_canenter(tp, dp, link_name, link_namelen)))
 		goto error_return;
 	/*
 	 * Initialize the bmap freelist prior to calling either
@@ -3457,7 +3461,7 @@
 		error = xfs_bmapi(tp, ip, first_fsb, fs_blocks,
 				  XFS_BMAPI_WRITE | XFS_BMAPI_METADATA,
 				  &first_block, resblks, mval, &nmaps,
-				  &free_list);
+				  &free_list, NULL);
 		if (error) {
 			goto error1;
 		}
@@ -3489,11 +3493,10 @@
 	/*
 	 * Create the directory entry for the symlink.
 	 */
-	error = XFS_DIR_CREATENAME(mp, tp, dp, link_name, link_namelen,
-			ip->i_ino, &first_block, &free_list, resblks);
-	if (error) {
+	error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino,
+				   &first_block, &free_list, resblks);
+	if (error)
 		goto error1;
-	}
 	xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
 	xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
 
@@ -3541,7 +3544,7 @@
 	}
 
 	if (!error) {
-		vnode_t *vp;
+		bhv_vnode_t *vp;
 
 		ASSERT(ip);
 		vp = XFS_ITOV(ip);
@@ -3606,10 +3609,10 @@
 int
 xfs_rwlock(
 	bhv_desc_t	*bdp,
-	vrwlock_t	locktype)
+	bhv_vrwlock_t	locktype)
 {
 	xfs_inode_t	*ip;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	vp = BHV_TO_VNODE(bdp);
 	if (VN_ISDIR(vp))
@@ -3637,10 +3640,10 @@
 void
 xfs_rwunlock(
 	bhv_desc_t	*bdp,
-	vrwlock_t	locktype)
+	bhv_vrwlock_t	locktype)
 {
 	xfs_inode_t     *ip;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	vp = BHV_TO_VNODE(bdp);
 	if (VN_ISDIR(vp))
@@ -3744,7 +3747,6 @@
 	return error;
 }
 
-
 int
 xfs_set_dmattrs (
 	bhv_desc_t	*bdp,
@@ -3785,16 +3787,12 @@
 	return error;
 }
 
-
-/*
- * xfs_reclaim
- */
 STATIC int
 xfs_reclaim(
 	bhv_desc_t	*bdp)
 {
 	xfs_inode_t	*ip;
-	vnode_t		*vp;
+	bhv_vnode_t	*vp;
 
 	vp = BHV_TO_VNODE(bdp);
 	ip = XFS_BHVTOI(bdp);
@@ -3849,7 +3847,7 @@
 	int		sync_mode)
 {
 	xfs_ihash_t	*ih = ip->i_hash;
-	vnode_t		*vp = XFS_ITOV_NULL(ip);
+	bhv_vnode_t	*vp = XFS_ITOV_NULL(ip);
 	int		error;
 
 	if (vp && VN_BAD(vp))
@@ -4116,10 +4114,10 @@
 		 * Issue the xfs_bmapi() call to allocate the blocks
 		 */
 		XFS_BMAP_INIT(&free_list, &firstfsb);
-		error = xfs_bmapi(tp, ip, startoffset_fsb,
+		error = XFS_BMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
 				  allocatesize_fsb, bmapi_flag,
 				  &firstfsb, 0, imapp, &nimaps,
-				  &free_list);
+				  &free_list, NULL);
 		if (error) {
 			goto error0;
 		}
@@ -4199,8 +4197,8 @@
 	for (offset = startoff; offset <= endoff; offset = lastoffset + 1) {
 		offset_fsb = XFS_B_TO_FSBT(mp, offset);
 		nimap = 1;
-		error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, NULL, 0, &imap,
-			&nimap, NULL);
+		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, offset_fsb, 1, 0,
+			NULL, 0, &imap, &nimap, NULL, NULL);
 		if (error || nimap < 1)
 			break;
 		ASSERT(imap.br_blockcount >= 1);
@@ -4259,7 +4257,7 @@
 	xfs_off_t		len,
 	int			attr_flags)
 {
-	vnode_t			*vp;
+	bhv_vnode_t		*vp;
 	int			committed;
 	int			done;
 	xfs_off_t		end_dmi_offset;
@@ -4308,7 +4306,6 @@
 			return error;
 	}
 
-	ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1);
 	if (attr_flags & ATTR_NOLOCK)
 		need_iolock = 0;
 	if (need_iolock) {
@@ -4326,7 +4323,7 @@
 	if (VN_CACHED(vp) != 0) {
 		xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
 				ctooff(offtoct(ioffset)), -1);
-		VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)),
+		bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)),
 				-1, FI_REMAPF_LOCKED);
 	}
 
@@ -4338,8 +4335,8 @@
 	 */
 	if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) {
 		nimap = 1;
-		error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0,
-			&imap, &nimap, NULL);
+		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, startoffset_fsb,
+			1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
 		if (error)
 			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
@@ -4353,8 +4350,8 @@
 				startoffset_fsb += mp->m_sb.sb_rextsize - mod;
 		}
 		nimap = 1;
-		error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0,
-			&imap, &nimap, NULL);
+		error = XFS_BMAPI(mp, NULL, &ip->i_iocore, endoffset_fsb - 1,
+			1, 0, NULL, 0, &imap, &nimap, NULL, NULL);
 		if (error)
 			goto out_unlock_iolock;
 		ASSERT(nimap == 0 || nimap == 1);
@@ -4426,9 +4423,9 @@
 		 * issue the bunmapi() call to free the blocks
 		 */
 		XFS_BMAP_INIT(&free_list, &firstfsb);
-		error = xfs_bunmapi(tp, ip, startoffset_fsb,
+		error = XFS_BUNMAPI(mp, tp, &ip->i_iocore, startoffset_fsb,
 				  endoffset_fsb - startoffset_fsb,
-				  0, 2, &firstfsb, &free_list, &done);
+				  0, 2, &firstfsb, &free_list, NULL, &done);
 		if (error) {
 			goto error0;
 		}
@@ -4488,8 +4485,8 @@
 	xfs_off_t	startoffset;
 	xfs_off_t	llen;
 	xfs_trans_t	*tp;
-	vattr_t		va;
-	vnode_t		*vp;
+	bhv_vattr_t	va;
+	bhv_vnode_t	*vp;
 
 	vp = BHV_TO_VNODE(bdp);
 	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
@@ -4642,9 +4639,10 @@
 	return error;
 }
 
-vnodeops_t xfs_vnodeops = {
+bhv_vnodeops_t xfs_vnodeops = {
 	BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS),
 	.vop_open		= xfs_open,
+	.vop_close		= xfs_close,
 	.vop_read		= xfs_read,
 #ifdef HAVE_SENDFILE
 	.vop_sendfile		= xfs_sendfile,
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index e27dc8f..b9beceb 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -63,7 +63,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20060127
+#define ACPI_CA_VERSION                 0x20060608
 
 /*
  * OS name, used for the _OS object.  The _OS object is essentially obsolete,
@@ -81,6 +81,7 @@
 #define ACPI_MAX_PARSE_CACHE_DEPTH      96	/* Parse tree objects */
 #define ACPI_MAX_EXTPARSE_CACHE_DEPTH   96	/* Parse tree objects */
 #define ACPI_MAX_OBJECT_CACHE_DEPTH     96	/* Interpreter operand objects */
+#define ACPI_MAX_NAMESPACE_CACHE_DEPTH  96	/* Namespace objects */
 
 /*
  * Should the subsystem abort the loading of an ACPI table if the
@@ -102,9 +103,9 @@
 
 #define ACPI_MAX_SEMAPHORE_COUNT        256
 
-/* Max reference count (for debug only) */
+/* Maximum object reference count (detects object deletion issues) */
 
-#define ACPI_MAX_REFERENCE_COUNT        0x400
+#define ACPI_MAX_REFERENCE_COUNT        0x800
 
 /* Size of cached memory mapping for system memory operation region */
 
@@ -171,12 +172,7 @@
 
 /* Array sizes.  Used for range checking also */
 
-#define ACPI_NUM_ACCESS_TYPES           6
-#define ACPI_NUM_UPDATE_RULES           3
-#define ACPI_NUM_LOCK_RULES             2
-#define ACPI_NUM_MATCH_OPS              6
-#define ACPI_NUM_OPCODES                256
-#define ACPI_NUM_FIELD_NAMES            2
+#define ACPI_MAX_MATCH_OPCODE           5
 
 /* RSDP checksums */
 
@@ -187,10 +183,6 @@
 
 #define ACPI_SMBUS_BUFFER_SIZE          34
 
-/* Number of strings associated with the _OSI reserved method */
-
-#define ACPI_NUM_OSI_STRINGS            10
-
 /******************************************************************************
  *
  * ACPI AML Debugger
diff --git a/include/acpi/acdisasm.h b/include/acpi/acdisasm.h
index 11a8fe3..9a7d692 100644
--- a/include/acpi/acdisasm.h
+++ b/include/acpi/acdisasm.h
@@ -50,26 +50,72 @@
 #define BLOCK_PAREN             1
 #define BLOCK_BRACE             2
 #define BLOCK_COMMA_LIST        4
+#define ACPI_DEFAULT_RESNAME    *(u32 *) "__RD"
 
 struct acpi_external_list {
 	char *path;
+	char *internal_path;
 	struct acpi_external_list *next;
+	u32 value;
+	u16 length;
+	u8 type;
 };
 
 extern struct acpi_external_list *acpi_gbl_external_list;
 
-/* Strings used for decoding flags to ASL keywords */
+typedef const struct acpi_dmtable_info {
+	u8 opcode;
+	u8 offset;
+	char *name;
 
-extern const char *acpi_gbl_word_decode[4];
-extern const char *acpi_gbl_irq_decode[2];
-extern const char *acpi_gbl_lock_rule[ACPI_NUM_LOCK_RULES];
-extern const char *acpi_gbl_access_types[ACPI_NUM_ACCESS_TYPES];
-extern const char *acpi_gbl_update_rules[ACPI_NUM_UPDATE_RULES];
-extern const char *acpi_gbl_match_ops[ACPI_NUM_MATCH_OPS];
+} acpi_dmtable_info;
+
+/*
+ * Values for Opcode above.
+ * Note: 0-7 must not change, used as a flag shift value
+ */
+#define ACPI_DMT_FLAG0                  0
+#define ACPI_DMT_FLAG1                  1
+#define ACPI_DMT_FLAG2                  2
+#define ACPI_DMT_FLAG3                  3
+#define ACPI_DMT_FLAG4                  4
+#define ACPI_DMT_FLAG5                  5
+#define ACPI_DMT_FLAG6                  6
+#define ACPI_DMT_FLAG7                  7
+#define ACPI_DMT_FLAGS0                 8
+#define ACPI_DMT_FLAGS2                 9
+#define ACPI_DMT_UINT8                  10
+#define ACPI_DMT_UINT16                 11
+#define ACPI_DMT_UINT24                 12
+#define ACPI_DMT_UINT32                 13
+#define ACPI_DMT_UINT56                 14
+#define ACPI_DMT_UINT64                 15
+#define ACPI_DMT_STRING                 16
+#define ACPI_DMT_NAME4                  17
+#define ACPI_DMT_NAME6                  18
+#define ACPI_DMT_NAME8                  19
+#define ACPI_DMT_CHKSUM                 20
+#define ACPI_DMT_SPACEID                21
+#define ACPI_DMT_GAS                    22
+#define ACPI_DMT_MADT                   23
+#define ACPI_DMT_SRAT                   24
+#define ACPI_DMT_EXIT                   25
+
+typedef
+void (*ACPI_TABLE_HANDLER) (struct acpi_table_header * table);
+
+struct acpi_dmtable_data {
+	char *signature;
+	struct acpi_dmtable_info *table_info;
+	ACPI_TABLE_HANDLER table_handler;
+};
 
 struct acpi_op_walk_info {
 	u32 level;
+	u32 last_level;
+	u32 count;
 	u32 bit_offset;
+	u32 flags;
 	struct acpi_walk_state *walk_state;
 };
 
@@ -77,6 +123,100 @@
 acpi_status(*asl_walk_callback) (union acpi_parse_object * op,
 				 u32 level, void *context);
 
+struct acpi_resource_tag {
+	u32 bit_index;
+	char *tag;
+};
+
+/* Strings used for decoding flags to ASL keywords */
+
+extern const char *acpi_gbl_word_decode[];
+extern const char *acpi_gbl_irq_decode[];
+extern const char *acpi_gbl_lock_rule[];
+extern const char *acpi_gbl_access_types[];
+extern const char *acpi_gbl_update_rules[];
+extern const char *acpi_gbl_match_ops[];
+
+extern struct acpi_dmtable_info acpi_dm_table_info_asf0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf3[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf4[];
+extern struct acpi_dmtable_info acpi_dm_table_info_asf_hdr[];
+extern struct acpi_dmtable_info acpi_dm_table_info_boot[];
+extern struct acpi_dmtable_info acpi_dm_table_info_cpep[];
+extern struct acpi_dmtable_info acpi_dm_table_info_cpep0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_dbgp[];
+extern struct acpi_dmtable_info acpi_dm_table_info_ecdt[];
+extern struct acpi_dmtable_info acpi_dm_table_info_facs[];
+extern struct acpi_dmtable_info acpi_dm_table_info_fadt1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_fadt2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_gas[];
+extern struct acpi_dmtable_info acpi_dm_table_info_header[];
+extern struct acpi_dmtable_info acpi_dm_table_info_hpet[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt3[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt4[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt5[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt6[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt7[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt8[];
+extern struct acpi_dmtable_info acpi_dm_table_info_madt_hdr[];
+extern struct acpi_dmtable_info acpi_dm_table_info_mcfg[];
+extern struct acpi_dmtable_info acpi_dm_table_info_mcfg0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_rsdp1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_rsdp2[];
+extern struct acpi_dmtable_info acpi_dm_table_info_sbst[];
+extern struct acpi_dmtable_info acpi_dm_table_info_slit[];
+extern struct acpi_dmtable_info acpi_dm_table_info_spcr[];
+extern struct acpi_dmtable_info acpi_dm_table_info_spmi[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat0[];
+extern struct acpi_dmtable_info acpi_dm_table_info_srat1[];
+extern struct acpi_dmtable_info acpi_dm_table_info_tcpa[];
+extern struct acpi_dmtable_info acpi_dm_table_info_wdrt[];
+
+/*
+ * dmtable
+ */
+void acpi_dm_dump_data_table(struct acpi_table_header *table);
+
+void
+acpi_dm_dump_table(u32 table_length,
+		   u32 table_offset,
+		   void *table,
+		   u32 sub_table_length, struct acpi_dmtable_info *info);
+
+void acpi_dm_line_header(u32 offset, u32 byte_length, char *name);
+
+void acpi_dm_line_header2(u32 offset, u32 byte_length, char *name, u32 value);
+
+/*
+ * dmtbdump
+ */
+void acpi_dm_dump_asf(struct acpi_table_header *table);
+
+void acpi_dm_dump_cpep(struct acpi_table_header *table);
+
+void acpi_dm_dump_fadt(struct acpi_table_header *table);
+
+void acpi_dm_dump_srat(struct acpi_table_header *table);
+
+void acpi_dm_dump_mcfg(struct acpi_table_header *table);
+
+void acpi_dm_dump_madt(struct acpi_table_header *table);
+
+u32 acpi_dm_dump_rsdp(struct acpi_table_header *table);
+
+void acpi_dm_dump_rsdt(struct acpi_table_header *table);
+
+void acpi_dm_dump_slit(struct acpi_table_header *table);
+
+void acpi_dm_dump_xsdt(struct acpi_table_header *table);
+
 /*
  * dmwalk
  */
@@ -84,6 +224,11 @@
 acpi_dm_disassemble(struct acpi_walk_state *walk_state,
 		    union acpi_parse_object *origin, u32 num_opcodes);
 
+void
+acpi_dm_walk_parse_tree(union acpi_parse_object *op,
+			asl_walk_callback descending_callback,
+			asl_walk_callback ascending_callback, void *context);
+
 /*
  * dmopcode
  */
@@ -166,6 +311,7 @@
 
 void
 acpi_dm_resource_template(struct acpi_op_walk_info *info,
+			  union acpi_parse_object *op,
 			  u8 * byte_data, u32 byte_count);
 
 u8 acpi_dm_is_resource_template(union acpi_parse_object *op);
@@ -176,6 +322,8 @@
 
 void acpi_dm_decode_attribute(u8 attribute);
 
+void acpi_dm_descriptor_name(void);
+
 /*
  * dmresrcl
  */
@@ -248,6 +396,15 @@
 /*
  * dmutils
  */
-void acpi_dm_add_to_external_list(char *path);
+void acpi_dm_add_to_external_list(char *path, u8 type, u32 value);
+
+/*
+ * dmrestag
+ */
+void acpi_dm_find_resources(union acpi_parse_object *root);
+
+void
+acpi_dm_check_resource_reference(union acpi_parse_object *op,
+				 struct acpi_walk_state *walk_state);
 
 #endif				/* __ACDISASM_H__ */
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index c41a926..288f849 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -194,7 +194,9 @@
 acpi_ds_restart_control_method(struct acpi_walk_state *walk_state,
 			       union acpi_operand_object *return_desc);
 
-void acpi_ds_terminate_control_method(struct acpi_walk_state *walk_state);
+void
+acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
+				 struct acpi_walk_state *walk_state);
 
 acpi_status
 acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node,
@@ -302,7 +304,7 @@
 		      struct acpi_namespace_node *method_node,
 		      u8 * aml_start,
 		      u32 aml_length,
-		      struct acpi_parameter_info *info, u8 pass_number);
+		      struct acpi_evaluate_info *info, u8 pass_number);
 
 acpi_status
 acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
diff --git a/include/acpi/acevents.h b/include/acpi/acevents.h
index f2717be..23414282 100644
--- a/include/acpi/acevents.h
+++ b/include/acpi/acevents.h
@@ -93,7 +93,7 @@
  */
 u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info);
 
-acpi_status acpi_ev_walk_gpe_list(ACPI_GPE_CALLBACK gpe_walk_callback);
+acpi_status acpi_ev_walk_gpe_list(acpi_gpe_callback gpe_walk_callback);
 
 acpi_status
 acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
@@ -138,7 +138,7 @@
 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 			       u32 function,
 			       acpi_physical_address address,
-			       u32 bit_width, void *value);
+			       u32 bit_width, acpi_integer * value);
 
 acpi_status
 acpi_ev_attach_region(union acpi_operand_object *handler_obj,
diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h
index dc768aa..797ca1e 100644
--- a/include/acpi/acexcep.h
+++ b/include/acpi/acexcep.h
@@ -160,8 +160,9 @@
 #define AE_AML_BAD_RESOURCE_VALUE       (acpi_status) (0x001F | AE_CODE_AML)
 #define AE_AML_CIRCULAR_REFERENCE       (acpi_status) (0x0020 | AE_CODE_AML)
 #define AE_AML_BAD_RESOURCE_LENGTH      (acpi_status) (0x0021 | AE_CODE_AML)
+#define AE_AML_ILLEGAL_ADDRESS          (acpi_status) (0x0022 | AE_CODE_AML)
 
-#define AE_CODE_AML_MAX                 0x0021
+#define AE_CODE_AML_MAX                 0x0022
 
 /*
  * Internal exceptions used for control
@@ -275,7 +276,8 @@
 	"AE_AML_NO_RESOURCE_END_TAG",
 	"AE_AML_BAD_RESOURCE_VALUE",
 	"AE_AML_CIRCULAR_REFERENCE",
-	"AE_AML_BAD_RESOURCE_LENGTH"
+	"AE_AML_BAD_RESOURCE_LENGTH",
+	"AE_AML_ILLEGAL_ADDRESS"
 };
 
 char const *acpi_gbl_exception_names_ctrl[] = {
diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
index 734cc77..14531d4 100644
--- a/include/acpi/acglobal.h
+++ b/include/acpi/acglobal.h
@@ -107,6 +107,7 @@
  * 3) Allow access to uninitialized locals/args (auto-init to integer 0)
  * 4) Allow ANY object type to be a source operand for the Store() operator
  * 5) Allow unresolved references (invalid target name) in package objects
+ * 6) Enable warning messages for behavior that is not ACPI spec compliant
  */
 ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
 
@@ -114,7 +115,7 @@
  * Automatically serialize ALL control methods? Default is FALSE, meaning
  * to use the Serialized/not_serialized method flags on a per method basis.
  * Only change this if the ASL code is poorly written and cannot handle
- * reentrancy even though methods are marked "not_serialized".
+ * reentrancy even though methods are marked "NotSerialized".
  */
 ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE);
 
@@ -149,10 +150,10 @@
 ACPI_EXTERN u32 acpi_gbl_table_flags;
 ACPI_EXTERN u32 acpi_gbl_rsdt_table_count;
 ACPI_EXTERN struct rsdp_descriptor *acpi_gbl_RSDP;
-ACPI_EXTERN XSDT_DESCRIPTOR *acpi_gbl_XSDT;
-ACPI_EXTERN FADT_DESCRIPTOR *acpi_gbl_FADT;
+ACPI_EXTERN struct xsdt_descriptor *acpi_gbl_XSDT;
+ACPI_EXTERN struct fadt_descriptor *acpi_gbl_FADT;
 ACPI_EXTERN struct acpi_table_header *acpi_gbl_DSDT;
-ACPI_EXTERN FACS_DESCRIPTOR *acpi_gbl_FACS;
+ACPI_EXTERN struct facs_descriptor *acpi_gbl_FACS;
 ACPI_EXTERN struct acpi_common_facs acpi_gbl_common_fACS;
 /*
  * Since there may be multiple SSDTs and PSDTs, a single pointer is not
@@ -177,15 +178,15 @@
 /*
  * ACPI Table info arrays
  */
-extern struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
-extern struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES];
+extern struct acpi_table_list acpi_gbl_table_lists[ACPI_TABLE_ID_MAX + 1];
+extern struct acpi_table_support acpi_gbl_table_data[ACPI_TABLE_ID_MAX + 1];
 
 /*
  * Predefined mutex objects.  This array contains the
  * actual OS mutex handles, indexed by the local ACPI_MUTEX_HANDLEs.
  * (The table maps local handles to the real OS handles)
  */
-ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[NUM_MUTEX];
+ACPI_EXTERN struct acpi_mutex_info acpi_gbl_mutex_info[ACPI_NUM_MUTEX];
 
 /*****************************************************************************
  *
@@ -203,6 +204,7 @@
 
 /* Object caches */
 
+ACPI_EXTERN acpi_cache_t *acpi_gbl_namespace_cache;
 ACPI_EXTERN acpi_cache_t *acpi_gbl_state_cache;
 ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_cache;
 ACPI_EXTERN acpi_cache_t *acpi_gbl_ps_node_ext_cache;
@@ -244,7 +246,6 @@
 extern const char *acpi_gbl_highest_dstate_names[4];
 extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
 extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
-extern const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS];
 
 /*****************************************************************************
  *
@@ -291,14 +292,6 @@
 
 /*****************************************************************************
  *
- * Parser globals
- *
- ****************************************************************************/
-
-ACPI_EXTERN union acpi_parse_object *acpi_gbl_parsed_namespace_root;
-
-/*****************************************************************************
- *
  * Hardware globals
  *
  ****************************************************************************/
@@ -321,7 +314,11 @@
 ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
 ACPI_EXTERN struct acpi_gpe_block_info
     *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
+
+/* Spinlocks */
+
 ACPI_EXTERN acpi_handle acpi_gbl_gpe_lock;
+ACPI_EXTERN acpi_handle acpi_gbl_hardware_lock;
 
 /*****************************************************************************
  *
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index 8361820..1eeca7a 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -44,7 +44,10 @@
 #ifndef __ACLOCAL_H__
 #define __ACLOCAL_H__
 
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
 #define ACPI_WAIT_FOREVER               0xFFFF	/* u16, as per ACPI spec */
+#define ACPI_INFINITE_CONCURRENCY       0xFF
 
 typedef void *acpi_mutex;
 typedef u32 acpi_mutex_handle;
@@ -69,52 +72,55 @@
  * Predefined handles for the mutex objects used within the subsystem
  * All mutex objects are automatically created by acpi_ut_mutex_initialize.
  *
- * The acquire/release ordering protocol is implied via this list.  Mutexes
+ * The acquire/release ordering protocol is implied via this list. Mutexes
  * with a lower value must be acquired before mutexes with a higher value.
  *
- * NOTE: any changes here must be reflected in the acpi_gbl_mutex_names table also!
+ * NOTE: any changes here must be reflected in the acpi_gbl_mutex_names
+ * table below also!
  */
-#define ACPI_MTX_EXECUTE                0
-#define ACPI_MTX_INTERPRETER            1
-#define ACPI_MTX_PARSER                 2
-#define ACPI_MTX_DISPATCHER             3
-#define ACPI_MTX_TABLES                 4
-#define ACPI_MTX_OP_REGIONS             5
-#define ACPI_MTX_NAMESPACE              6
-#define ACPI_MTX_EVENTS                 7
-#define ACPI_MTX_HARDWARE               8
-#define ACPI_MTX_CACHES                 9
-#define ACPI_MTX_MEMORY                 10
-#define ACPI_MTX_DEBUG_CMD_COMPLETE     11
-#define ACPI_MTX_DEBUG_CMD_READY        12
+#define ACPI_MTX_INTERPRETER            0	/* AML Interpreter, main lock */
+#define ACPI_MTX_CONTROL_METHOD         1	/* Control method termination [TBD: may no longer be necessary] */
+#define ACPI_MTX_TABLES                 2	/* Data for ACPI tables */
+#define ACPI_MTX_NAMESPACE              3	/* ACPI Namespace */
+#define ACPI_MTX_EVENTS                 4	/* Data for ACPI events */
+#define ACPI_MTX_CACHES                 5	/* Internal caches, general purposes */
+#define ACPI_MTX_MEMORY                 6	/* Debug memory tracking lists */
+#define ACPI_MTX_DEBUG_CMD_COMPLETE     7	/* AML debugger */
+#define ACPI_MTX_DEBUG_CMD_READY        8	/* AML debugger */
 
-#define MAX_MUTEX                       12
-#define NUM_MUTEX                       MAX_MUTEX+1
+#define ACPI_MAX_MUTEX                  8
+#define ACPI_NUM_MUTEX                  ACPI_MAX_MUTEX+1
 
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
 #ifdef DEFINE_ACPI_GLOBALS
 
-/* Names for the mutexes used in the subsystem */
+/* Debug names for the mutexes above */
 
-static char *acpi_gbl_mutex_names[] = {
-	"ACPI_MTX_Execute",
+static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
 	"ACPI_MTX_Interpreter",
-	"ACPI_MTX_Parser",
-	"ACPI_MTX_Dispatcher",
+	"ACPI_MTX_Method",
 	"ACPI_MTX_Tables",
-	"ACPI_MTX_op_regions",
 	"ACPI_MTX_Namespace",
 	"ACPI_MTX_Events",
-	"ACPI_MTX_Hardware",
 	"ACPI_MTX_Caches",
 	"ACPI_MTX_Memory",
-	"ACPI_MTX_debug_cmd_complete",
-	"ACPI_MTX_debug_cmd_ready",
+	"ACPI_MTX_DebugCmdComplete",
+	"ACPI_MTX_DebugCmdReady"
 };
 
 #endif
 #endif
 
+/*
+ * Predefined handles for spinlocks used within the subsystem.
+ * These spinlocks are created by acpi_ut_mutex_initialize
+ */
+#define ACPI_LOCK_GPES                  0
+#define ACPI_LOCK_HARDWARE              1
+
+#define ACPI_MAX_LOCK                   1
+#define ACPI_NUM_LOCK                   ACPI_MAX_LOCK+1
+
 /* Owner IDs are used to track namespace nodes for selective deletion */
 
 typedef u8 acpi_owner_id;
@@ -129,7 +135,7 @@
 struct acpi_mutex_info {
 	acpi_mutex mutex;
 	u32 use_count;
-	u32 thread_id;
+	acpi_thread_id thread_id;
 };
 
 /* Lock flag parameter for various interfaces */
@@ -144,6 +150,8 @@
 #define ACPI_FIELD_DWORD_GRANULARITY    4
 #define ACPI_FIELD_QWORD_GRANULARITY    8
 
+#define ACPI_ENTRY_NOT_FOUND            NULL
+
 /*****************************************************************************
  *
  * Namespace typedefs and structs
@@ -158,49 +166,55 @@
 	ACPI_IMODE_EXECUTE = 0x0E
 } acpi_interpreter_mode;
 
-/*
- * The Node describes a named object that appears in the AML
- * An acpi_node is used to store Nodes.
- *
- * data_type is used to differentiate between internal descriptors, and MUST
- * be the first byte in this structure.
- */
 union acpi_name_union {
 	u32 integer;
 	char ascii[4];
 };
 
+/*
+ * The Namespace Node describes a named object that appears in the AML.
+ * descriptor_type is used to differentiate between internal descriptors.
+ *
+ * The node is optimized for both 32-bit and 64-bit platforms:
+ * 20 bytes for the 32-bit case, 32 bytes for the 64-bit case.
+ *
+ * Note: The descriptor_type and Type fields must appear in the identical
+ * position in both the struct acpi_namespace_node and union acpi_operand_object
+ * structures.
+ */
 struct acpi_namespace_node {
-	u8 descriptor;		/* Used to differentiate object descriptor types */
-	u8 type;		/* Type associated with this name */
-	u16 reference_count;	/* Current count of references and children */
+	union acpi_operand_object *object;	/* Interpreter object */
+	u8 descriptor_type;	/* Differentiate object descriptor types */
+	u8 type;		/* ACPI Type associated with this name */
+	u8 flags;		/* Miscellaneous flags */
+	acpi_owner_id owner_id;	/* Node creator */
 	union acpi_name_union name;	/* ACPI Name, always 4 chars per ACPI spec */
-	union acpi_operand_object *object;	/* Pointer to attached ACPI object (optional) */
 	struct acpi_namespace_node *child;	/* First child */
-	struct acpi_namespace_node *peer;	/* Next peer */
-	u8 owner_id;		/* Who created this node */
-	u8 flags;
+	struct acpi_namespace_node *peer;	/* Peer. Parent if ANOBJ_END_OF_PEER_LIST set */
 
-	/* Fields used by the ASL compiler only */
-
-#ifdef ACPI_ASL_COMPILER
-	u32 value;
+	/*
+	 * The following fields are used by the ASL compiler and disassembler only
+	 */
+#ifdef ACPI_LARGE_NAMESPACE_NODE
 	union acpi_parse_object *op;
+	u32 value;
+	u32 length;
 #endif
 };
 
-#define ACPI_ENTRY_NOT_FOUND            NULL
+/* Namespace Node flags */
 
-/* Node flags */
+#define ANOBJ_END_OF_PEER_LIST          0x01	/* End-of-list, Peer field points to parent */
+#define ANOBJ_DATA_WIDTH_32             0x02	/* Parent table uses 32-bit math */
+#define ANOBJ_METHOD_ARG                0x04	/* Node is a method argument */
+#define ANOBJ_METHOD_LOCAL              0x08	/* Node is a method local */
+#define ANOBJ_SUBTREE_HAS_INI           0x10	/* Used to optimize device initialization */
 
-#define ANOBJ_RESERVED                  0x01
-#define ANOBJ_END_OF_PEER_LIST          0x02
-#define ANOBJ_DATA_WIDTH_32             0x04	/* Parent table is 64-bits */
-#define ANOBJ_METHOD_ARG                0x08
-#define ANOBJ_METHOD_LOCAL              0x10
-#define ANOBJ_METHOD_NO_RETVAL          0x20
-#define ANOBJ_METHOD_SOME_NO_RETVAL     0x40
-#define ANOBJ_IS_BIT_OFFSET             0x80
+#define ANOBJ_IS_EXTERNAL               0x08	/* i_aSL only: This object created via External() */
+#define ANOBJ_METHOD_NO_RETVAL          0x10	/* i_aSL only: Method has no return value */
+#define ANOBJ_METHOD_SOME_NO_RETVAL     0x20	/* i_aSL only: Method has at least one return value */
+#define ANOBJ_IS_BIT_OFFSET             0x40	/* i_aSL only: Reference is a bit offset */
+#define ANOBJ_IS_REFERENCED             0x80	/* i_aSL only: Object was referenced */
 
 /*
  * ACPI Table Descriptor.  One per ACPI table
@@ -212,8 +226,8 @@
 	struct acpi_table_header *pointer;
 	u8 *aml_start;
 	u64 physical_address;
-	u32 aml_length;
 	acpi_size length;
+	u32 aml_length;
 	acpi_owner_id owner_id;
 	u8 type;
 	u8 allocation;
@@ -276,6 +290,9 @@
 	u8 field_type;
 };
 
+typedef
+acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state);
+
 /*
  * Bitmapped ACPI types.  Used internally only
  */
@@ -377,7 +394,7 @@
 	struct acpi_gpe_block_info *gpe_block;
 };
 
-typedef acpi_status(*ACPI_GPE_CALLBACK) (struct acpi_gpe_xrupt_info *
+typedef acpi_status(*acpi_gpe_callback) (struct acpi_gpe_xrupt_info *
 					 gpe_xrupt_info,
 					 struct acpi_gpe_block_info *
 					 gpe_block);
@@ -416,13 +433,14 @@
 #define ACPI_CONTROL_PREDICATE_FALSE         0xC3
 #define ACPI_CONTROL_PREDICATE_TRUE          0xC4
 
-#define ACPI_STATE_COMMON   /* Two 32-bit fields and a pointer */\
-	u8                                  data_type;  /* To differentiate various internal objs */\
-	u8                                  flags;      \
-	u16                                 value;      \
-	u16                                 state;      \
-	u16                                 reserved;   \
-	void                                *next;
+#define ACPI_STATE_COMMON \
+	void                            *next; \
+	u8                              descriptor_type; /* To differentiate various internal objs */\
+	u8                              flags; \
+	u16                             value; \
+	u16                             state;
+
+	/* There are 2 bytes available here until the next natural alignment boundary */
 
 struct acpi_common_state {
 ACPI_STATE_COMMON};
@@ -438,12 +456,12 @@
  * Pkg state - used to traverse nested package structures
  */
 struct acpi_pkg_state {
-	ACPI_STATE_COMMON union acpi_operand_object *source_object;
+	ACPI_STATE_COMMON u16 index;
+	union acpi_operand_object *source_object;
 	union acpi_operand_object *dest_object;
 	struct acpi_walk_state *walk_state;
 	void *this_target_obj;
 	u32 num_packages;
-	u16 index;
 };
 
 /*
@@ -451,10 +469,10 @@
  * Allows nesting of these constructs
  */
 struct acpi_control_state {
-	ACPI_STATE_COMMON union acpi_parse_object *predicate_op;
+	ACPI_STATE_COMMON u16 opcode;
+	union acpi_parse_object *predicate_op;
 	u8 *aml_predicate_start;	/* Start of if/while predicate */
 	u8 *package_end;	/* End of if/while block */
-	u16 opcode;
 };
 
 /*
@@ -465,11 +483,11 @@
 };
 
 struct acpi_pscope_state {
-	ACPI_STATE_COMMON union acpi_parse_object *op;	/* Current op being parsed */
+	ACPI_STATE_COMMON u32 arg_count;	/* Number of fixed arguments */
+	union acpi_parse_object *op;	/* Current op being parsed */
 	u8 *arg_end;		/* Current argument end */
 	u8 *pkg_end;		/* Current package end */
 	u32 arg_list;		/* Next argument to parse */
-	u32 arg_count;		/* Number of fixed arguments */
 };
 
 /*
@@ -477,10 +495,10 @@
  * states are created when there are nested control methods executing.
  */
 struct acpi_thread_state {
-	ACPI_STATE_COMMON struct acpi_walk_state *walk_state_list;	/* Head of list of walk_states for this thread */
+	ACPI_STATE_COMMON u8 current_sync_level;	/* Mutex Sync (nested acquire) level */
+	struct acpi_walk_state *walk_state_list;	/* Head of list of walk_states for this thread */
 	union acpi_operand_object *acquired_mutex_list;	/* List of all currently acquired mutexes */
-	u32 thread_id;		/* Running thread ID */
-	u8 current_sync_level;	/* Mutex Sync (nested acquire) level */
+	acpi_thread_id thread_id;	/* Running thread ID */
 };
 
 /*
@@ -488,10 +506,9 @@
  * AML arguments
  */
 struct acpi_result_values {
-	ACPI_STATE_COMMON
-	    union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS];
-	u8 num_results;
+	ACPI_STATE_COMMON u8 num_results;
 	u8 last_insert;
+	union acpi_operand_object *obj_desc[ACPI_OBJ_NUM_OPERANDS];
 };
 
 typedef
@@ -546,7 +563,7 @@
 #endif
 	u32 parse_args;		/* Grammar/Parse time arguments */
 	u32 runtime_args;	/* Interpret time arguments */
-	u32 flags;		/* Misc flags */
+	u16 flags;		/* Misc flags */
 	u8 object_type;		/* Corresponding internal object type */
 	u8 class;		/* Opcode class */
 	u8 type;		/* Opcode type */
@@ -563,29 +580,31 @@
 };
 
 #define ACPI_PARSE_COMMON \
-	u8                                  data_type;      /* To differentiate various internal objs */\
-	u8                                  flags;          /* Type of Op */\
-	u16                                 aml_opcode;     /* AML opcode */\
-	u32                                 aml_offset;     /* Offset of declaration in AML */\
-	union acpi_parse_object             *parent;        /* Parent op */\
-	union acpi_parse_object             *next;          /* Next op */\
+	union acpi_parse_object         *parent;        /* Parent op */\
+	u8                              descriptor_type; /* To differentiate various internal objs */\
+	u8                              flags;          /* Type of Op */\
+	u16                             aml_opcode;     /* AML opcode */\
+	u32                             aml_offset;     /* Offset of declaration in AML */\
+	union acpi_parse_object         *next;          /* Next op */\
+	struct acpi_namespace_node      *node;          /* For use by interpreter */\
+	union acpi_parse_value          value;          /* Value or args associated with the opcode */\
 	ACPI_DISASM_ONLY_MEMBERS (\
-	u8                                  disasm_flags;   /* Used during AML disassembly */\
-	u8                                  disasm_opcode;  /* Subtype used for disassembly */\
-	char                                aml_op_name[16]) /* Op name (debug only) */\
-			   /* NON-DEBUG members below: */\
-	struct acpi_namespace_node          *node;          /* For use by interpreter */\
-	union acpi_parse_value              value;	/* Value or args associated with the opcode */
+	u8                              disasm_flags;   /* Used during AML disassembly */\
+	u8                              disasm_opcode;  /* Subtype used for disassembly */\
+	char                            aml_op_name[16])	/* Op name (debug only) */
 
-#define ACPI_DASM_BUFFER        0x00
-#define ACPI_DASM_RESOURCE      0x01
-#define ACPI_DASM_STRING        0x02
-#define ACPI_DASM_UNICODE       0x03
-#define ACPI_DASM_EISAID        0x04
-#define ACPI_DASM_MATCHOP       0x05
+#define ACPI_DASM_BUFFER                0x00
+#define ACPI_DASM_RESOURCE              0x01
+#define ACPI_DASM_STRING                0x02
+#define ACPI_DASM_UNICODE               0x03
+#define ACPI_DASM_EISAID                0x04
+#define ACPI_DASM_MATCHOP               0x05
+#define ACPI_DASM_LNOT_PREFIX           0x06
+#define ACPI_DASM_LNOT_SUFFIX           0x07
+#define ACPI_DASM_IGNORE                0x08
 
 /*
- * generic operation (for example:  If, While, Store)
+ * Generic operation (for example:  If, While, Store)
  */
 struct acpi_parse_obj_common {
 ACPI_PARSE_COMMON};
@@ -601,7 +620,7 @@
 	u32 name;		/* 4-byte name or zero if no name */
 };
 
-/* The parse node is the fundamental element of the parse tree */
+/* This version is used by the i_aSL compiler only */
 
 #define ACPI_MAX_PARSEOP_NAME   20
 
@@ -643,7 +662,6 @@
  * method.
  */
 struct acpi_parse_state {
-	u32 aml_size;
 	u8 *aml_start;		/* First AML byte */
 	u8 *aml;		/* Next AML byte */
 	u8 *aml_end;		/* (last + 1) AML byte */
@@ -653,22 +671,23 @@
 	struct acpi_namespace_node *start_node;
 	union acpi_generic_state *scope;	/* Current scope */
 	union acpi_parse_object *start_scope;
+	u32 aml_size;
 };
 
 /* Parse object flags */
 
-#define ACPI_PARSEOP_GENERIC                    0x01
-#define ACPI_PARSEOP_NAMED                      0x02
-#define ACPI_PARSEOP_DEFERRED                   0x04
-#define ACPI_PARSEOP_BYTELIST                   0x08
-#define ACPI_PARSEOP_IN_CACHE                   0x80
+#define ACPI_PARSEOP_GENERIC            0x01
+#define ACPI_PARSEOP_NAMED              0x02
+#define ACPI_PARSEOP_DEFERRED           0x04
+#define ACPI_PARSEOP_BYTELIST           0x08
+#define ACPI_PARSEOP_IN_CACHE           0x80
 
 /* Parse object disasm_flags */
 
-#define ACPI_PARSEOP_IGNORE                     0x01
-#define ACPI_PARSEOP_PARAMLIST                  0x02
-#define ACPI_PARSEOP_EMPTY_TERMLIST             0x04
-#define ACPI_PARSEOP_SPECIAL                    0x10
+#define ACPI_PARSEOP_IGNORE             0x01
+#define ACPI_PARSEOP_PARAMLIST          0x02
+#define ACPI_PARSEOP_EMPTY_TERMLIST     0x04
+#define ACPI_PARSEOP_SPECIAL            0x10
 
 /*****************************************************************************
  *
@@ -676,8 +695,8 @@
  *
  ****************************************************************************/
 
-#define PCI_ROOT_HID_STRING         "PNP0A03"
-#define PCI_EXPRESS_ROOT_HID_STRING "PNP0A08"
+#define PCI_ROOT_HID_STRING             "PNP0A03"
+#define PCI_EXPRESS_ROOT_HID_STRING     "PNP0A08"
 
 struct acpi_bit_register_info {
 	u8 parent_register;
@@ -710,13 +729,14 @@
 #define ACPI_BITMASK_PCIEXP_WAKE_STATUS         0x4000	/* ACPI 3.0 */
 #define ACPI_BITMASK_WAKE_STATUS                0x8000
 
-#define ACPI_BITMASK_ALL_FIXED_STATUS           (ACPI_BITMASK_TIMER_STATUS          | \
-			 ACPI_BITMASK_BUS_MASTER_STATUS     | \
-			 ACPI_BITMASK_GLOBAL_LOCK_STATUS    | \
-			 ACPI_BITMASK_POWER_BUTTON_STATUS   | \
-			 ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
-			 ACPI_BITMASK_RT_CLOCK_STATUS       | \
-			 ACPI_BITMASK_WAKE_STATUS)
+#define ACPI_BITMASK_ALL_FIXED_STATUS           (\
+	ACPI_BITMASK_TIMER_STATUS          | \
+	ACPI_BITMASK_BUS_MASTER_STATUS     | \
+	ACPI_BITMASK_GLOBAL_LOCK_STATUS    | \
+	ACPI_BITMASK_POWER_BUTTON_STATUS   | \
+	ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
+	ACPI_BITMASK_RT_CLOCK_STATUS       | \
+	ACPI_BITMASK_WAKE_STATUS)
 
 #define ACPI_BITMASK_TIMER_ENABLE               0x0001
 #define ACPI_BITMASK_GLOBAL_LOCK_ENABLE         0x0020
@@ -820,7 +840,7 @@
  *
  ****************************************************************************/
 
-#define ACPI_ASCII_ZERO                         0x30
+#define ACPI_ASCII_ZERO                 0x30
 
 /*****************************************************************************
  *
@@ -842,9 +862,9 @@
 	u32 objects;
 };
 
-#define ACPI_DB_REDIRECTABLE_OUTPUT  0x01
-#define ACPI_DB_CONSOLE_OUTPUT       0x02
-#define ACPI_DB_DUPLICATE_OUTPUT     0x03
+#define ACPI_DB_REDIRECTABLE_OUTPUT     0x01
+#define ACPI_DB_CONSOLE_OUTPUT          0x02
+#define ACPI_DB_DUPLICATE_OUTPUT        0x03
 
 /*****************************************************************************
  *
@@ -854,18 +874,18 @@
 
 /* Entry for a memory allocation (debug only) */
 
-#define ACPI_MEM_MALLOC                      0
-#define ACPI_MEM_CALLOC                      1
-#define ACPI_MAX_MODULE_NAME                 16
+#define ACPI_MEM_MALLOC                 0
+#define ACPI_MEM_CALLOC                 1
+#define ACPI_MAX_MODULE_NAME            16
 
 #define ACPI_COMMON_DEBUG_MEM_HEADER \
-	struct acpi_debug_mem_block         *previous; \
-	struct acpi_debug_mem_block         *next; \
-	u32                                 size; \
-	u32                                 component; \
-	u32                                 line; \
-	char                                module[ACPI_MAX_MODULE_NAME]; \
-	u8                                  alloc_type;
+	struct acpi_debug_mem_block     *previous; \
+	struct acpi_debug_mem_block     *next; \
+	u32                             size; \
+	u32                             component; \
+	u32                             line; \
+	char                            module[ACPI_MAX_MODULE_NAME]; \
+	u8                              alloc_type;
 
 struct acpi_debug_mem_header {
 ACPI_COMMON_DEBUG_MEM_HEADER};
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index f2be2a8..38f9aa4 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -56,6 +56,10 @@
 #define ACPI_CLEAR_BIT(target,bit)      ((target) &= ~(bit))
 #define ACPI_MIN(a,b)                   (((a)<(b))?(a):(b))
 
+/* Size calculation */
+
+#define ACPI_ARRAY_LENGTH(x)            (sizeof(x) / sizeof((x)[0]))
+
 #if ACPI_MACHINE_WIDTH == 16
 
 /*
@@ -99,7 +103,7 @@
  * printf() format helpers
  */
 
-/* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */
+/* Split 64-bit integer into two 32-bit values. Use with %8.8_x%8.8_x */
 
 #define ACPI_FORMAT_UINT64(i)           ACPI_HIDWORD(i),ACPI_LODWORD(i)
 
@@ -130,7 +134,6 @@
 #define ACPI_TO_POINTER(i)              ACPI_ADD_PTR (void,(void *) NULL,(acpi_native_uint) i)
 #define ACPI_TO_INTEGER(p)              ACPI_PTR_DIFF (p,(void *) NULL)
 #define ACPI_OFFSET(d,f)                (acpi_size) ACPI_PTR_DIFF (&(((d *)0)->f),(void *) NULL)
-#define ACPI_FADT_OFFSET(f)             ACPI_OFFSET (FADT_DESCRIPTOR, f)
 
 #if ACPI_MACHINE_WIDTH == 16
 #define ACPI_STORE_POINTER(d,s)         ACPI_MOVE_32_TO_32(d,s)
@@ -141,6 +144,12 @@
 #define ACPI_PTR_TO_PHYSADDR(i)         ACPI_TO_INTEGER(i)
 #endif
 
+#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
+#define ACPI_COMPARE_NAME(a,b)          (*ACPI_CAST_PTR (u32,(a)) == *ACPI_CAST_PTR (u32,(b)))
+#else
+#define ACPI_COMPARE_NAME(a,b)          (!ACPI_STRNCMP (ACPI_CAST_PTR (char,(a)), ACPI_CAST_PTR (char,(b)), ACPI_NAME_SIZE))
+#endif
+
 /*
  * Macros for moving data around to/from buffers that are possibly unaligned.
  * If the hardware supports the transfer of unaligned data, just do the store.
@@ -341,29 +350,33 @@
 /*
  * Rounding macros (Power of two boundaries only)
  */
-#define ACPI_ROUND_DOWN(value,boundary)      (((acpi_native_uint)(value)) & \
+#define ACPI_ROUND_DOWN(value,boundary)     (((acpi_native_uint)(value)) & \
 												(~(((acpi_native_uint) boundary)-1)))
 
-#define ACPI_ROUND_UP(value,boundary)        ((((acpi_native_uint)(value)) + \
+#define ACPI_ROUND_UP(value,boundary)       ((((acpi_native_uint)(value)) + \
 												(((acpi_native_uint) boundary)-1)) & \
 												(~(((acpi_native_uint) boundary)-1)))
 
-#define ACPI_ROUND_DOWN_TO_32_BITS(a)        ACPI_ROUND_DOWN(a,4)
-#define ACPI_ROUND_DOWN_TO_64_BITS(a)        ACPI_ROUND_DOWN(a,8)
-#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a)    ACPI_ROUND_DOWN(a,ALIGNED_ADDRESS_BOUNDARY)
+/* Note: sizeof(acpi_native_uint) evaluates to either 2, 4, or 8 */
 
-#define ACPI_ROUND_UP_to_32_bITS(a)          ACPI_ROUND_UP(a,4)
-#define ACPI_ROUND_UP_to_64_bITS(a)          ACPI_ROUND_UP(a,8)
-#define ACPI_ROUND_UP_TO_NATIVE_WORD(a)      ACPI_ROUND_UP(a,ALIGNED_ADDRESS_BOUNDARY)
+#define ACPI_ROUND_DOWN_TO_32BIT(a)         ACPI_ROUND_DOWN(a,4)
+#define ACPI_ROUND_DOWN_TO_64BIT(a)         ACPI_ROUND_DOWN(a,8)
+#define ACPI_ROUND_DOWN_TO_NATIVE_WORD(a)   ACPI_ROUND_DOWN(a,sizeof(acpi_native_uint))
 
-#define ACPI_ROUND_BITS_UP_TO_BYTES(a)       ACPI_DIV_8((a) + 7)
-#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a)     ACPI_DIV_8((a))
+#define ACPI_ROUND_UP_TO_32BIT(a)           ACPI_ROUND_UP(a,4)
+#define ACPI_ROUND_UP_TO_64BIT(a)           ACPI_ROUND_UP(a,8)
+#define ACPI_ROUND_UP_TO_NATIVE_WORD(a)     ACPI_ROUND_UP(a,sizeof(acpi_native_uint))
 
-#define ACPI_ROUND_UP_TO_1K(a)               (((a) + 1023) >> 10)
+#define ACPI_ROUND_BITS_UP_TO_BYTES(a)      ACPI_DIV_8((a) + 7)
+#define ACPI_ROUND_BITS_DOWN_TO_BYTES(a)    ACPI_DIV_8((a))
+
+#define ACPI_ROUND_UP_TO_1K(a)              (((a) + 1023) >> 10)
 
 /* Generic (non-power-of-two) rounding */
 
-#define ACPI_ROUND_UP_TO(value,boundary)     (((value) + ((boundary)-1)) / (boundary))
+#define ACPI_ROUND_UP_TO(value,boundary)    (((value) + ((boundary)-1)) / (boundary))
+
+#define ACPI_IS_MISALIGNED(value)           (((acpi_native_uint)value) & (sizeof(acpi_native_uint)-1))
 
 /*
  * Bitmask creation
@@ -371,10 +384,10 @@
  * MASK_BITS_ABOVE creates a mask starting AT the position and above
  * MASK_BITS_BELOW creates a mask starting one bit BELOW the position
  */
-#define ACPI_MASK_BITS_ABOVE(position)       (~((ACPI_INTEGER_MAX) << ((u32) (position))))
-#define ACPI_MASK_BITS_BELOW(position)       ((ACPI_INTEGER_MAX) << ((u32) (position)))
+#define ACPI_MASK_BITS_ABOVE(position)      (~((ACPI_INTEGER_MAX) << ((u32) (position))))
+#define ACPI_MASK_BITS_BELOW(position)      ((ACPI_INTEGER_MAX) << ((u32) (position)))
 
-#define ACPI_IS_OCTAL_DIGIT(d)               (((char)(d) >= '0') && ((char)(d) <= '7'))
+#define ACPI_IS_OCTAL_DIGIT(d)              (((char)(d) >= '0') && ((char)(d) <= '7'))
 
 /* Bitfields within ACPI registers */
 
@@ -396,8 +409,8 @@
  *
  * The "Descriptor" field is the first field in both structures.
  */
-#define ACPI_GET_DESCRIPTOR_TYPE(d)     (((union acpi_descriptor *)(void *)(d))->descriptor_id)
-#define ACPI_SET_DESCRIPTOR_TYPE(d,t)   (((union acpi_descriptor *)(void *)(d))->descriptor_id = t)
+#define ACPI_GET_DESCRIPTOR_TYPE(d)     (((union acpi_descriptor *)(void *)(d))->common.descriptor_type)
+#define ACPI_SET_DESCRIPTOR_TYPE(d,t)   (((union acpi_descriptor *)(void *)(d))->common.descriptor_type = t)
 
 /* Macro to test the object type */
 
@@ -486,7 +499,6 @@
 #define ACPI_ERROR(plist)
 #define ACPI_ERROR_NAMESPACE(s,e)
 #define ACPI_ERROR_METHOD(s,n,p,e)
-
 #endif
 
 /*
@@ -514,12 +526,12 @@
 #define ACPI_GET_FUNCTION_NAME          _acpi_function_name
 /*
  * The Name parameter should be the procedure name as a quoted string.
- * This is declared as a local string ("my_function_name") so that it can
+ * This is declared as a local string ("MyFunctionName") so that it can
  * be also used by the function exit macros below.
  * Note: (const char) is used to be compatible with the debug interfaces
  * and macros such as __FUNCTION__.
  */
-#define ACPI_FUNCTION_NAME(name)        const char *_acpi_function_name = name;
+#define ACPI_FUNCTION_NAME(name)        const char *_acpi_function_name = #name;
 
 #else
 /* Compiler supports __FUNCTION__ (or equivalent) -- Ignore this macro */
@@ -528,13 +540,13 @@
 #endif
 
 #define ACPI_FUNCTION_TRACE(a)          ACPI_FUNCTION_NAME(a) \
-									  acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
+			  acpi_ut_trace(ACPI_DEBUG_PARAMETERS)
 #define ACPI_FUNCTION_TRACE_PTR(a,b)    ACPI_FUNCTION_NAME(a) \
-											acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b)
+					   acpi_ut_trace_ptr(ACPI_DEBUG_PARAMETERS,(void *)b)
 #define ACPI_FUNCTION_TRACE_U32(a,b)    ACPI_FUNCTION_NAME(a) \
-											acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS,(u32)b)
+							 acpi_ut_trace_u32(ACPI_DEBUG_PARAMETERS,(u32)b)
 #define ACPI_FUNCTION_TRACE_STR(a,b)    ACPI_FUNCTION_NAME(a) \
-											acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS,(char *)b)
+									  acpi_ut_trace_str(ACPI_DEBUG_PARAMETERS,(char *)b)
 
 #define ACPI_FUNCTION_ENTRY()           acpi_ut_track_stack_ptr()
 
@@ -543,7 +555,7 @@
  * WARNING: These macros include a return statement.  This is usually considered
  * bad form, but having a separate exit macro is very ugly and difficult to maintain.
  * One of the FUNCTION_TRACE macros above must be used in conjunction with these macros
- * so that "_acpi_function_name" is defined.
+ * so that "_AcpiFunctionName" is defined.
  *
  * Note: the DO_WHILE0 macro is used to prevent some compilers from complaining
  * about these constructs.
@@ -654,6 +666,7 @@
 #define ACPI_DUMP_STACK_ENTRY(a)
 #define ACPI_DUMP_OPERANDS(a,b,c,d,e)
 #define ACPI_DUMP_ENTRY(a,b)
+#define ACPI_DUMP_TABLES(a,b)
 #define ACPI_DUMP_PATHNAME(a,b,c,d)
 #define ACPI_DUMP_RESOURCE_LIST(a)
 #define ACPI_DUMP_BUFFER(a,b)
@@ -709,19 +722,19 @@
 
 /* Memory allocation */
 
-#define ACPI_MEM_ALLOCATE(a)            acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_CALLOCATE(a)           acpi_ut_callocate((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_FREE(a)                acpi_os_free(a)
+#define ACPI_ALLOCATE(a)            acpi_ut_allocate((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_FREE(a)                acpi_os_free(a)
 #define ACPI_MEM_TRACKING(a)
 
 #else
 
 /* Memory allocation */
 
-#define ACPI_MEM_ALLOCATE(a)            acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_CALLOCATE(a)           acpi_ut_callocate_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_FREE(a)                acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__)
-#define ACPI_MEM_TRACKING(a)            a
+#define ACPI_ALLOCATE(a)            acpi_ut_allocate_and_track((acpi_size)(a),_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_ALLOCATE_ZEROED(a)     acpi_ut_allocate_zeroed_and_track((acpi_size)(a), _COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_FREE(a)                acpi_ut_free_and_track(a,_COMPONENT,_acpi_module_name,__LINE__)
+#define ACPI_MEM_TRACKING(a)        a
 
 #endif				/* ACPI_DBG_TRACK_ALLOCATIONS */
 
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index b667a80..83b52f9 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -63,6 +63,8 @@
 #define ACPI_NS_DONT_OPEN_SCOPE     0x02
 #define ACPI_NS_NO_PEER_SEARCH      0x04
 #define ACPI_NS_ERROR_IF_FOUND      0x08
+#define ACPI_NS_PREFIX_IS_SCOPE     0x10
+#define ACPI_NS_EXTERNAL            0x20
 
 #define ACPI_NS_WALK_UNLOCK         TRUE
 #define ACPI_NS_WALK_NO_UNLOCK      FALSE
@@ -171,19 +173,17 @@
 /*
  * nseval - Namespace evaluation functions
  */
-acpi_status acpi_ns_evaluate_by_handle(struct acpi_parameter_info *info);
-
-acpi_status
-acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info);
-
-acpi_status
-acpi_ns_evaluate_relative(char *pathname, struct acpi_parameter_info *info);
+acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
 
 /*
  * nsnames - Name and Scope manipulation
  */
 u32 acpi_ns_opens_scope(acpi_object_type type);
 
+void
+acpi_ns_build_external_path(struct acpi_namespace_node *node,
+			    acpi_size size, char *name_buffer);
+
 char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node);
 
 char *acpi_ns_name_of_current_scope(struct acpi_walk_state *walk_state);
@@ -196,9 +196,9 @@
 acpi_ns_pattern_match(struct acpi_namespace_node *obj_node, char *search_for);
 
 acpi_status
-acpi_ns_get_node_by_path(char *external_pathname,
-			 struct acpi_namespace_node *in_prefix_node,
-			 u32 flags, struct acpi_namespace_node **out_node);
+acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
+		 char *external_pathname,
+		 u32 flags, struct acpi_namespace_node **out_node);
 
 acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node);
 
@@ -241,10 +241,10 @@
 			 u32 flags, struct acpi_namespace_node **ret_node);
 
 acpi_status
-acpi_ns_search_node(u32 entry_name,
-		    struct acpi_namespace_node *node,
-		    acpi_object_type type,
-		    struct acpi_namespace_node **ret_node);
+acpi_ns_search_one_scope(u32 entry_name,
+			 struct acpi_namespace_node *node,
+			 acpi_object_type type,
+			 struct acpi_namespace_node **ret_node);
 
 void
 acpi_ns_install_node(struct acpi_walk_state *walk_state,
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index d130cfe..1747d94 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -1,7 +1,7 @@
 
 /******************************************************************************
  *
- * Name: acobject.h - Definition of union acpi_operand_object    (Internal object only)
+ * Name: acobject.h - Definition of union acpi_operand_object  (Internal object only)
  *
  *****************************************************************************/
 
@@ -45,10 +45,12 @@
 #ifndef _ACOBJECT_H
 #define _ACOBJECT_H
 
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
 /*
- * The union acpi_operand_object    is used to pass AML operands from the dispatcher
+ * The union acpi_operand_object is used to pass AML operands from the dispatcher
  * to the interpreter, and to keep track of the various handlers such as
- * address space handlers and notify handlers.  The object is a constant
+ * address space handlers and notify handlers. The object is a constant
  * size in order to allow it to be cached and reused.
  */
 
@@ -61,17 +63,25 @@
 /*
  * Common area for all objects.
  *
- * data_type is used to differentiate between internal descriptors, and MUST
- * be the first byte in this structure.
+ * descriptor_type is used to differentiate between internal descriptors, and
+ * must be in the same place across all descriptors
+ *
+ * Note: The descriptor_type and Type fields must appear in the identical
+ * position in both the struct acpi_namespace_node and union acpi_operand_object
+ * structures.
  */
-#define ACPI_OBJECT_COMMON_HEADER   /* SIZE/ALIGNMENT: 32 bits, one ptr plus trailing 8-bit flag */\
-	u8                                      descriptor;         /* To differentiate various internal objs */\
-	u8                                      type;               /* acpi_object_type */\
-	u16                                     reference_count;    /* For object deletion management */\
-	union acpi_operand_object               *next_object;       /* Objects linked to parent NS node */\
-	u8                                      flags;
+#define ACPI_OBJECT_COMMON_HEADER \
+	union acpi_operand_object       *next_object;       /* Objects linked to parent NS node */\
+	u8                              descriptor_type;    /* To differentiate various internal objs */\
+	u8                              type;               /* acpi_object_type */\
+	u16                             reference_count;    /* For object deletion management */\
+	u8                              flags;
+	/*
+	 * Note: There are 3 bytes available here before the
+	 * next natural alignment boundary (for both 32/64 cases)
+	 */
 
-/* Values for flag byte above */
+/* Values for Flag byte above */
 
 #define AOPOBJ_AML_CONSTANT         0x01
 #define AOPOBJ_STATIC_POINTER       0x02
@@ -79,36 +89,7 @@
 #define AOPOBJ_OBJECT_INITIALIZED   0x08
 #define AOPOBJ_SETUP_COMPLETE       0x10
 #define AOPOBJ_SINGLE_DATUM         0x20
-
-/*
- * Common bitfield for the field objects
- * "Field Datum"  -- a datum from the actual field object
- * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field
- */
-#define ACPI_COMMON_FIELD_INFO      /* SIZE/ALIGNMENT: 24 bits + three 32-bit values */\
-	u8                                      field_flags;        /* Access, update, and lock bits */\
-	u8                                      attribute;          /* From access_as keyword */\
-	u8                                      access_byte_width;  /* Read/Write size in bytes */\
-	u32                                     bit_length;         /* Length of field in bits */\
-	u32                                     base_byte_offset;   /* Byte offset within containing object */\
-	u8                                      start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
-	u8                                      access_bit_width;   /* Read/Write size in bits (8-64) */\
-	u32                                     value;              /* Value to store into the Bank or Index register */\
-	struct acpi_namespace_node              *node;	/* Link back to parent node */
-
-/*
- * Fields common to both Strings and Buffers
- */
-#define ACPI_COMMON_BUFFER_INFO \
-	u32                                     length;
-
-/*
- * Common fields for objects that support ASL notifications
- */
-#define ACPI_COMMON_NOTIFY_INFO \
-	union acpi_operand_object               *system_notify;     /* Handler for system notifies */\
-	union acpi_operand_object               *device_notify;     /* Handler for driver notifies */\
-	union acpi_operand_object               *handler;	/* Handler for Address space */
+#define AOPOBJ_INVALID              0x40	/* Used if host OS won't allow an op_region address */
 
 /******************************************************************************
  *
@@ -125,25 +106,31 @@
 
 /*
  * Note: The String and Buffer object must be identical through the Pointer
- * element.  There is code that depends on this.
+ * and length elements.  There is code that depends on this.
+ *
+ * Fields common to both Strings and Buffers
  */
+#define ACPI_COMMON_BUFFER_INFO(_type) \
+	_type                           *pointer; \
+	u32                             length;
+
 struct acpi_object_string {	/* Null terminated, ASCII characters only */
-	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO char *pointer;	/* String in AML stream or allocated string */
+	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(char)	/* String in AML stream or allocated string */
 };
 
 struct acpi_object_buffer {
-	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO u8 * pointer;	/* Buffer in AML stream or allocated buffer */
-	struct acpi_namespace_node *node;	/* Link back to parent node */
-	u8 *aml_start;
+	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(u8)	/* Buffer in AML stream or allocated buffer */
 	u32 aml_length;
+	u8 *aml_start;
+	struct acpi_namespace_node *node;	/* Link back to parent node */
 };
 
 struct acpi_object_package {
-	ACPI_OBJECT_COMMON_HEADER u32 count;	/* # of elements in package */
-	u32 aml_length;
-	u8 *aml_start;
-	struct acpi_namespace_node *node;	/* Link back to parent node */
+	ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node;	/* Link back to parent node */
 	union acpi_operand_object **elements;	/* Array of pointers to acpi_objects */
+	u8 *aml_start;
+	u32 aml_length;
+	u32 count;		/* # of elements in package */
 };
 
 /******************************************************************************
@@ -156,23 +143,6 @@
 	ACPI_OBJECT_COMMON_HEADER void *semaphore;
 };
 
-#define ACPI_INFINITE_CONCURRENCY   0xFF
-
-typedef
-acpi_status(*ACPI_INTERNAL_METHOD) (struct acpi_walk_state * walk_state);
-
-struct acpi_object_method {
-	ACPI_OBJECT_COMMON_HEADER u8 method_flags;
-	u8 param_count;
-	u32 aml_length;
-	void *semaphore;
-	u8 *aml_start;
-	ACPI_INTERNAL_METHOD implementation;
-	u8 concurrency;
-	u8 thread_count;
-	acpi_owner_id owner_id;
-};
-
 struct acpi_object_mutex {
 	ACPI_OBJECT_COMMON_HEADER u8 sync_level;	/* 0-15, specified in Mutex() call */
 	u16 acquisition_depth;	/* Allow multiple Acquires, same thread */
@@ -186,11 +156,23 @@
 
 struct acpi_object_region {
 	ACPI_OBJECT_COMMON_HEADER u8 space_id;
-	union acpi_operand_object *handler;	/* Handler for region access */
 	struct acpi_namespace_node *node;	/* Containing namespace node */
+	union acpi_operand_object *handler;	/* Handler for region access */
 	union acpi_operand_object *next;
-	u32 length;
 	acpi_physical_address address;
+	u32 length;
+};
+
+struct acpi_object_method {
+	ACPI_OBJECT_COMMON_HEADER u8 method_flags;
+	u8 param_count;
+	u8 concurrency;
+	void *semaphore;
+	u8 *aml_start;
+	ACPI_INTERNAL_METHOD implementation;
+	u32 aml_length;
+	u8 thread_count;
+	acpi_owner_id owner_id;
 };
 
 /******************************************************************************
@@ -199,6 +181,14 @@
  *
  *****************************************************************************/
 
+/*
+ * Common fields for objects that support ASL notifications
+ */
+#define ACPI_COMMON_NOTIFY_INFO \
+	union acpi_operand_object       *system_notify;     /* Handler for system notifies */\
+	union acpi_operand_object       *device_notify;     /* Handler for driver notifies */\
+	union acpi_operand_object       *handler;	/* Handler for Address space */
+
 struct acpi_object_notify_common {	/* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
 ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
 
@@ -213,9 +203,9 @@
 };
 
 struct acpi_object_processor {
-	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO u32 proc_id;
-	u32 length;
-	acpi_io_address address;
+	ACPI_OBJECT_COMMON_HEADER u8 proc_id;
+	u8 length;
+	 ACPI_COMMON_NOTIFY_INFO acpi_io_address address;
 };
 
 struct acpi_object_thermal_zone {
@@ -227,9 +217,24 @@
  *
  *****************************************************************************/
 
+/*
+ * Common bitfield for the field objects
+ * "Field Datum"  -- a datum from the actual field object
+ * "Buffer Datum" -- a datum from a user buffer, read from or to be written to the field
+ */
+#define ACPI_COMMON_FIELD_INFO \
+	u8                              field_flags;        /* Access, update, and lock bits */\
+	u8                              attribute;          /* From access_as keyword */\
+	u8                              access_byte_width;  /* Read/Write size in bytes */\
+	struct acpi_namespace_node      *node;              /* Link back to parent node */\
+	u32                             bit_length;         /* Length of field in bits */\
+	u32                             base_byte_offset;   /* Byte offset within containing object */\
+	u32                             value;              /* Value to store into the Bank or Index register */\
+	u8                              start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
+	u8                              access_bit_width;	/* Read/Write size in bits (8-64) */
+
 struct acpi_object_field_common {	/* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
-	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj;	/* Containing Operation Region object */
-	/* (REGION/BANK fields only) */
+	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj;	/* Parent Operation Region object (REGION/BANK fields only) */
 };
 
 struct acpi_object_region_field {
@@ -244,7 +249,7 @@
 struct acpi_object_index_field {
 	ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO
 	    /*
-	     * No "region_obj" pointer needed since the Index and Data registers
+	     * No "RegionObj" pointer needed since the Index and Data registers
 	     * are each field definitions unto themselves.
 	     */
 	union acpi_operand_object *index_obj;	/* Index register */
@@ -269,13 +274,9 @@
 	void *context;
 };
 
-/* Flags for address handler */
-
-#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED  0x1
-
 struct acpi_object_addr_handler {
 	ACPI_OBJECT_COMMON_HEADER u8 space_id;
-	u16 hflags;
+	u8 handler_flags;
 	acpi_adr_space_handler handler;
 	struct acpi_namespace_node *node;	/* Parent device */
 	void *context;
@@ -284,6 +285,10 @@
 	union acpi_operand_object *next;
 };
 
+/* Flags for address handler (handler_flags) */
+
+#define ACPI_ADDR_HANDLER_DEFAULT_INSTALLED  0x01
+
 /******************************************************************************
  *
  * Special internal objects
@@ -297,10 +302,10 @@
 struct acpi_object_reference {
 	ACPI_OBJECT_COMMON_HEADER u8 target_type;	/* Used for index_op */
 	u16 opcode;
-	u32 offset;		/* Used for arg_op, local_op, and index_op */
-	void *object;		/* name_op=>HANDLE to obj, index_op=>union acpi_operand_object  */
+	void *object;		/* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */
 	struct acpi_namespace_node *node;
 	union acpi_operand_object **where;
+	u32 offset;		/* Used for arg_op, local_op, and index_op */
 };
 
 /*
@@ -311,12 +316,10 @@
  * Currently: Region and field_unit types
  */
 struct acpi_object_extra {
-	ACPI_OBJECT_COMMON_HEADER u8 byte_fill1;
-	u16 word_fill1;
-	u32 aml_length;
-	u8 *aml_start;
-	struct acpi_namespace_node *method_REG;	/* _REG method for this region (if any) */
+	ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG;	/* _REG method for this region (if any) */
 	void *region_context;	/* Region-specific data */
+	u8 *aml_start;
+	u32 aml_length;
 };
 
 /* Additional data that can be attached to namespace nodes */
@@ -391,8 +394,13 @@
 #define ACPI_DESC_TYPE_NAMED            0x0F
 #define ACPI_DESC_TYPE_MAX              0x0F
 
+struct acpi_common_descriptor {
+	void *common_pointer;
+	u8 descriptor_type;	/* To differentiate various internal objs */
+};
+
 union acpi_descriptor {
-	u8 descriptor_id;	/* To differentiate various internal objs */
+	struct acpi_common_descriptor common;
 	union acpi_operand_object object;
 	struct acpi_namespace_node node;
 	union acpi_parse_object op;
diff --git a/include/acpi/acopcode.h b/include/acpi/acopcode.h
index e6d78bd..7659a46 100644
--- a/include/acpi/acopcode.h
+++ b/include/acpi/acopcode.h
@@ -94,7 +94,7 @@
 #define ARGP_CONCAT_RES_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_COND_REF_OF_OP             ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_SUPERNAME)
 #define ARGP_CONTINUE_OP                ARG_NONE
-#define ARGP_COPY_OP                    ARGP_LIST2 (ARGP_SUPERNAME,  ARGP_SIMPLENAME)
+#define ARGP_COPY_OP                    ARGP_LIST2 (ARGP_TERMARG,    ARGP_SIMPLENAME)
 #define ARGP_CREATE_BIT_FIELD_OP        ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME)
 #define ARGP_CREATE_BYTE_FIELD_OP       ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME)
 #define ARGP_CREATE_DWORD_FIELD_OP      ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_NAME)
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 7785d48..8d5039d 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -50,7 +50,7 @@
  * component basis and a per-exception-type basis.
  */
 
-/* Component IDs are used in the global "debug_layer" */
+/* Component IDs are used in the global "DebugLayer" */
 
 #define ACPI_UTILITIES              0x00000001
 #define ACPI_HARDWARE               0x00000002
@@ -121,7 +121,7 @@
 #define ACPI_LV_INTERRUPTS          0x08000000
 #define ACPI_LV_VERBOSITY3          0x0F000000 | ACPI_LV_VERBOSITY2
 
-/* Exceptionally verbose output -- also used in the global "debug_level" */
+/* Exceptionally verbose output -- also used in the global "DebugLevel"  */
 
 #define ACPI_LV_AML_DISASSEMBLE     0x10000000
 #define ACPI_LV_VERBOSE_INFO        0x20000000
@@ -135,7 +135,7 @@
  */
 #define ACPI_DEBUG_LEVEL(dl)        (u32) dl,ACPI_DEBUG_PARAMETERS
 
-/* Exception level -- used in the global "debug_level" */
+/* Exception level -- used in the global "DebugLevel" */
 
 #define ACPI_DB_INIT                ACPI_DEBUG_LEVEL (ACPI_LV_INIT)
 #define ACPI_DB_DEBUG_OBJECT        ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT)
@@ -144,13 +144,13 @@
 
 /*
  * These two levels are essentially obsolete, all instances in the
- * ACPICA core code have been replaced by REPORT_ERROR and REPORT_WARNING
+ * ACPICA core code have been replaced by ACPI_ERROR and ACPI_WARNING
  * (Kept here because some drivers may still use them)
  */
 #define ACPI_DB_ERROR               ACPI_DEBUG_LEVEL (ACPI_LV_ERROR)
 #define ACPI_DB_WARN                ACPI_DEBUG_LEVEL (ACPI_LV_WARN)
 
-/* Trace level -- also used in the global "debug_level" */
+/* Trace level -- also used in the global "DebugLevel" */
 
 #define ACPI_DB_INIT_NAMES          ACPI_DEBUG_LEVEL (ACPI_LV_INIT_NAMES)
 #define ACPI_DB_THREADS             ACPI_DEBUG_LEVEL (ACPI_LV_THREADS)
diff --git a/include/acpi/acparser.h b/include/acpi/acparser.h
index 5a1ff484..9d49d3c 100644
--- a/include/acpi/acparser.h
+++ b/include/acpi/acparser.h
@@ -46,7 +46,7 @@
 
 #define OP_HAS_RETURN_VALUE             1
 
-/* variable # arguments */
+/* Variable number of arguments. This field must be 32 bits */
 
 #define ACPI_VAR_ARGS                   ACPI_UINT32_MAX
 
@@ -71,7 +71,7 @@
 /*
  * psxface - Parser external interfaces
  */
-acpi_status acpi_ps_execute_method(struct acpi_parameter_info *info);
+acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info);
 
 /*
  * psargs - Parse AML opcode arguments
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 6dca3d5..a2b3e39 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -26,7 +26,7 @@
 #ifndef __ACPI_BUS_H__
 #define __ACPI_BUS_H__
 
-#include <linux/kobject.h>
+#include <linux/device.h>
 
 #include <acpi/acpi.h>
 
@@ -59,7 +59,7 @@
 
 #define ACPI_BUS_FILE_ROOT	"acpi"
 extern struct proc_dir_entry *acpi_root_dir;
-extern FADT_DESCRIPTOR acpi_fadt;
+extern struct fadt_descriptor acpi_fadt;
 
 enum acpi_bus_removal_type {
 	ACPI_BUS_REMOVAL_NORMAL = 0,
@@ -169,7 +169,8 @@
 	u32 power_manageable:1;
 	u32 performance_manageable:1;
 	u32 wake_capable:1;	/* Wakeup(_PRW) supported? */
-	u32 reserved:20;
+	u32 force_power_state:1;
+	u32 reserved:19;
 };
 
 /* File System */
@@ -296,6 +297,7 @@
 	struct acpi_driver *driver;
 	void *driver_data;
 	struct kobject kobj;
+	struct device dev;
 };
 
 #define acpi_driver_data(d)	((d)->driver_data)
@@ -327,7 +329,7 @@
 int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data);
 int acpi_bus_receive_event(struct acpi_bus_event *event);
 int acpi_bus_register_driver(struct acpi_driver *driver);
-int acpi_bus_unregister_driver(struct acpi_driver *driver);
+void acpi_bus_unregister_driver(struct acpi_driver *driver);
 int acpi_bus_add(struct acpi_device **child, struct acpi_device *parent,
 		 acpi_handle handle, int type);
 int acpi_bus_trim(struct acpi_device *start, int rmdevice);
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
new file mode 100644
index 0000000..1049f2a
--- /dev/null
+++ b/include/acpi/acpi_numa.h
@@ -0,0 +1,23 @@
+#ifndef __ACPI_NUMA_H
+#define __ACPI_NUMA_H
+
+#ifdef CONFIG_ACPI_NUMA
+#include <linux/kernel.h>
+
+/* Proximity bitmap length */
+#if MAX_NUMNODES > 256
+#define MAX_PXM_DOMAINS MAX_NUMNODES
+#else
+#define MAX_PXM_DOMAINS (256) /* Old pxm spec is defined 8 bit */
+#endif
+
+extern int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS];
+extern int __cpuinitdata node_to_pxm_map[MAX_NUMNODES];
+
+extern int __cpuinit pxm_to_node(int);
+extern int __cpuinit node_to_pxm(int);
+extern int __cpuinit acpi_map_pxm_to_node(int);
+extern void __cpuinit acpi_unmap_pxm_to_node(int);
+
+#endif				/* CONFIG_ACPI_NUMA */
+#endif				/* __ACP_NUMA_H */
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 970e9a6..8f473c8 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -50,12 +50,16 @@
 #include "platform/acenv.h"
 #include "actypes.h"
 
-/* Priorities for acpi_os_queue_for_execution */
+/* Types for acpi_os_execute */
 
-#define OSD_PRIORITY_GPE            1
-#define OSD_PRIORITY_HIGH           2
-#define OSD_PRIORITY_MED            3
-#define OSD_PRIORITY_LO             4
+typedef enum {
+	OSL_GLOBAL_LOCK_HANDLER,
+	OSL_NOTIFY_HANDLER,
+	OSL_GPE_HANDLER,
+	OSL_DEBUGGER_THREAD,
+	OSL_EC_POLL_HANDLER,
+	OSL_EC_BURST_HANDLER
+} acpi_execute_type;
 
 #define ACPI_NO_UNIT_LIMIT          ((u32) -1)
 #define ACPI_MUTEX_SEM              1
@@ -161,13 +165,11 @@
 /*
  * Threads and Scheduling
  */
-u32 acpi_os_get_thread_id(void);
+acpi_thread_id acpi_os_get_thread_id(void);
 
 acpi_status
-acpi_os_queue_for_execution(u32 priority,
-			    acpi_osd_exec_callback function, void *context);
-
-void acpi_os_wait_events_complete(void *context);
+acpi_os_execute(acpi_execute_type type,
+		acpi_osd_exec_callback function, void *context);
 
 void acpi_os_wait_events_complete(void *context);
 
@@ -214,6 +216,12 @@
 /*
  * Miscellaneous
  */
+acpi_status acpi_os_validate_interface(char *interface);
+
+acpi_status
+acpi_os_validate_address(u8 space_id,
+			 acpi_physical_address address, acpi_size length);
+
 u8 acpi_os_readable(void *pointer, acpi_size length);
 
 #ifdef ACPI_FUTURE_USAGE
@@ -255,11 +263,4 @@
 
 void acpi_os_close_directory(void *dir_handle);
 
-/*
- * Debug
- */
-void
-acpi_os_dbg_assert(void *failed_assertion,
-		   void *file_name, u32 line_number, char *message);
-
 #endif				/* __ACPIOSXF_H__ */
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 66cf2ec..049e9aa 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -268,7 +268,7 @@
  * Resource interfaces
  */
 typedef
-acpi_status(*ACPI_WALK_RESOURCE_CALLBACK) (struct acpi_resource * resource,
+acpi_status(*acpi_walk_resource_callback) (struct acpi_resource * resource,
 					   void *context);
 
 acpi_status
@@ -290,7 +290,7 @@
 acpi_status
 acpi_walk_resources(acpi_handle device_handle,
 		    char *name,
-		    ACPI_WALK_RESOURCE_CALLBACK user_function, void *context);
+		    acpi_walk_resource_callback user_function, void *context);
 
 acpi_status
 acpi_set_current_resources(acpi_handle device_handle,
diff --git a/include/acpi/acresrc.h b/include/acpi/acresrc.h
index fa02e80..ad11fc1 100644
--- a/include/acpi/acresrc.h
+++ b/include/acpi/acresrc.h
@@ -164,23 +164,26 @@
 /*
  * rsutils
  */
-acpi_status
-acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
 
 acpi_status
-acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
+acpi_rs_get_prt_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *ret_buffer);
 
-#ifdef	ACPI_FUTURE_USAGE
 acpi_status
-acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
-#endif				/* ACPI_FUTURE_USAGE */
+acpi_rs_get_crs_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *ret_buffer);
+
+acpi_status
+acpi_rs_get_prs_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *ret_buffer);
 
 acpi_status
 acpi_rs_get_method_data(acpi_handle handle,
 			char *path, struct acpi_buffer *ret_buffer);
 
 acpi_status
-acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer);
+acpi_rs_set_srs_method_data(struct acpi_namespace_node *node,
+			    struct acpi_buffer *ret_buffer);
 
 /*
  * rscalc
@@ -198,8 +201,9 @@
 				     acpi_size * buffer_size_needed);
 
 acpi_status
-acpi_rs_convert_aml_to_resources(u8 * aml_buffer,
-				 u32 aml_buffer_length, u8 * output_buffer);
+acpi_rs_convert_aml_to_resources(u8 * aml,
+				 u32 length,
+				 u32 offset, u8 resource_index, void **context);
 
 acpi_status
 acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
diff --git a/include/acpi/acstruct.h b/include/acpi/acstruct.h
index d8c1c2c..5e8095f 100644
--- a/include/acpi/acstruct.h
+++ b/include/acpi/acstruct.h
@@ -44,6 +44,8 @@
 #ifndef __ACSTRUCT_H__
 #define __ACSTRUCT_H__
 
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
 /*****************************************************************************
  *
  * Tree walking typedefs and structs
@@ -51,67 +53,76 @@
  ****************************************************************************/
 
 /*
- * Walk state - current state of a parse tree walk.  Used for both a leisurely stroll through
- * the tree (for whatever reason), and for control method execution.
+ * Walk state - current state of a parse tree walk.  Used for both a leisurely
+ * stroll through the tree (for whatever reason), and for control method
+ * execution.
  */
 #define ACPI_NEXT_OP_DOWNWARD       1
 #define ACPI_NEXT_OP_UPWARD         2
 
+/*
+ * Groups of definitions for walk_type used for different implementations of
+ * walkers (never simultaneously) - flags for interpreter:
+ */
 #define ACPI_WALK_NON_METHOD        0
-#define ACPI_WALK_METHOD            1
-#define ACPI_WALK_METHOD_RESTART    2
-#define ACPI_WALK_CONST_REQUIRED    3
-#define ACPI_WALK_CONST_OPTIONAL    4
+#define ACPI_WALK_METHOD            0x01
+#define ACPI_WALK_METHOD_RESTART    0x02
+
+/* Flags for i_aSL compiler only */
+
+#define ACPI_WALK_CONST_REQUIRED    0x10
+#define ACPI_WALK_CONST_OPTIONAL    0x20
 
 struct acpi_walk_state {
-	u8 data_type;		/* To differentiate various internal objs MUST BE FIRST! */
+	struct acpi_walk_state *next;	/* Next walk_state in list */
+	u8 descriptor_type;	/* To differentiate various internal objs */
 	u8 walk_type;
-	acpi_owner_id owner_id;	/* Owner of objects created during the walk */
-	u8 last_predicate;	/* Result of last predicate */
-	u8 current_result;	/* */
+	u16 opcode;		/* Current AML opcode */
 	u8 next_op_info;	/* Info about next_op */
 	u8 num_operands;	/* Stack pointer for Operands[] array */
+	acpi_owner_id owner_id;	/* Owner of objects created during the walk */
+	u8 last_predicate;	/* Result of last predicate */
+	u8 current_result;
 	u8 return_used;
-	u16 opcode;		/* Current AML opcode */
 	u8 scope_depth;
 	u8 pass_number;		/* Parse pass during table load */
-	u32 arg_count;		/* push for fixed or var args */
 	u32 aml_offset;
 	u32 arg_types;
 	u32 method_breakpoint;	/* For single stepping */
 	u32 user_breakpoint;	/* User AML breakpoint */
 	u32 parse_flags;
+
+	struct acpi_parse_state parser_state;	/* Current state of parser */
 	u32 prev_arg_types;
+	u32 arg_count;		/* push for fixed or var args */
+
+	struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS];	/* Control method arguments */
+	struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS];	/* Control method locals */
+	union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS + 1];	/* Operands passed to the interpreter (+1 for NULL terminator) */
+	union acpi_operand_object **params;
 
 	u8 *aml_last_while;
-	struct acpi_namespace_node arguments[ACPI_METHOD_NUM_ARGS];	/* Control method arguments */
 	union acpi_operand_object **caller_return_desc;
 	union acpi_generic_state *control_state;	/* List of control states (nested IFs) */
 	struct acpi_namespace_node *deferred_node;	/* Used when executing deferred opcodes */
 	struct acpi_gpe_event_info *gpe_event_info;	/* Info for GPE (_Lxx/_Exx methods only */
 	union acpi_operand_object *implicit_return_obj;
-	struct acpi_namespace_node local_variables[ACPI_METHOD_NUM_LOCALS];	/* Control method locals */
 	struct acpi_namespace_node *method_call_node;	/* Called method Node */
 	union acpi_parse_object *method_call_op;	/* method_call Op if running a method */
 	union acpi_operand_object *method_desc;	/* Method descriptor if running a method */
 	struct acpi_namespace_node *method_node;	/* Method node if running a method. */
 	union acpi_parse_object *op;	/* Current parser op */
-	union acpi_operand_object *operands[ACPI_OBJ_NUM_OPERANDS + 1];	/* Operands passed to the interpreter (+1 for NULL terminator) */
 	const struct acpi_opcode_info *op_info;	/* Info on current opcode */
 	union acpi_parse_object *origin;	/* Start of walk [Obsolete] */
-	union acpi_operand_object **params;
-	struct acpi_parse_state parser_state;	/* Current state of parser */
 	union acpi_operand_object *result_obj;
 	union acpi_generic_state *results;	/* Stack of accumulated results */
 	union acpi_operand_object *return_desc;	/* Return object, if any */
 	union acpi_generic_state *scope_info;	/* Stack of nested scopes */
-
 	union acpi_parse_object *prev_op;	/* Last op that was processed */
 	union acpi_parse_object *next_op;	/* next op to be processed */
+	struct acpi_thread_state *thread;
 	acpi_parse_downwards descending_callback;
 	acpi_parse_upwards ascending_callback;
-	struct acpi_thread_state *thread;
-	struct acpi_walk_state *next;	/* Next walk_state in list */
 };
 
 /* Info used by acpi_ps_init_objects */
@@ -131,32 +142,6 @@
 	struct acpi_table_desc *table_desc;
 };
 
-/* Info used by acpi_ns_initialize_devices */
-
-struct acpi_device_walk_info {
-	u16 device_count;
-	u16 num_STA;
-	u16 num_INI;
-	struct acpi_table_desc *table_desc;
-};
-
-/* TBD: [Restructure] Merge with struct above */
-
-struct acpi_walk_info {
-	u32 debug_level;
-	u32 count;
-	acpi_owner_id owner_id;
-	u8 display_type;
-};
-
-/* Display Types */
-
-#define ACPI_DISPLAY_SUMMARY    (u8) 0
-#define ACPI_DISPLAY_OBJECTS    (u8) 1
-#define ACPI_DISPLAY_MASK       (u8) 1
-
-#define ACPI_DISPLAY_SHORT      (u8) 2
-
 struct acpi_get_devices_info {
 	acpi_walk_callback user_function;
 	void *context;
@@ -189,16 +174,21 @@
 	} mid;
 };
 
-/* Internal method parameter list */
-
-struct acpi_parameter_info {
-	struct acpi_namespace_node *node;
+/*
+ * Structure used to pass object evaluation parameters.
+ * Purpose is to reduce CPU stack use.
+ */
+struct acpi_evaluate_info {
+	struct acpi_namespace_node *prefix_node;
+	char *pathname;
 	union acpi_operand_object *obj_desc;
 	union acpi_operand_object **parameters;
+	struct acpi_namespace_node *resolved_node;
 	union acpi_operand_object *return_object;
 	u8 pass_number;
 	u8 parameter_type;
 	u8 return_object_type;
+	u8 flags;
 };
 
 /* Types for parameter_type above */
@@ -206,4 +196,35 @@
 #define ACPI_PARAM_ARGS                 0
 #define ACPI_PARAM_GPE                  1
 
+/* Values for Flags above */
+
+#define ACPI_IGNORE_RETURN_VALUE        1
+
+/* Info used by acpi_ns_initialize_devices */
+
+struct acpi_device_walk_info {
+	u16 device_count;
+	u16 num_STA;
+	u16 num_INI;
+	struct acpi_table_desc *table_desc;
+	struct acpi_evaluate_info *evaluate_info;
+};
+
+/* TBD: [Restructure] Merge with struct above */
+
+struct acpi_walk_info {
+	u32 debug_level;
+	u32 count;
+	acpi_owner_id owner_id;
+	u8 display_type;
+};
+
+/* Display Types */
+
+#define ACPI_DISPLAY_SUMMARY        (u8) 0
+#define ACPI_DISPLAY_OBJECTS        (u8) 1
+#define ACPI_DISPLAY_MASK           (u8) 1
+
+#define ACPI_DISPLAY_SHORT          (u8) 2
+
 #endif
diff --git a/include/acpi/actables.h b/include/acpi/actables.h
index 30a4754..4dbaf02 100644
--- a/include/acpi/actables.h
+++ b/include/acpi/actables.h
@@ -136,7 +136,11 @@
 acpi_status
 acpi_tb_verify_table_checksum(struct acpi_table_header *table_header);
 
-u8 acpi_tb_generate_checksum(void *buffer, u32 length);
+u8 acpi_tb_sum_table(void *buffer, u32 length);
+
+u8 acpi_tb_generate_checksum(struct acpi_table_header *table);
+
+void acpi_tb_set_checksum(struct acpi_table_header *table);
 
 acpi_status
 acpi_tb_validate_table_header(struct acpi_table_header *table_header);
diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h
index ed53f84..b125cee 100644
--- a/include/acpi/actbl.h
+++ b/include/acpi/actbl.h
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Name: actbl.h - Table data structures defined in ACPI specification
+ * Name: actbl.h - Basic ACPI Table Definitions
  *
  *****************************************************************************/
 
@@ -45,66 +45,45 @@
 #define __ACTBL_H__
 
 /*
+ * Values for description table header signatures. Useful because they make
+ * it more difficult to inadvertently type in the wrong signature.
+ */
+#define DSDT_SIG                "DSDT"	/* Differentiated System Description Table */
+#define FADT_SIG                "FACP"	/* Fixed ACPI Description Table */
+#define FACS_SIG                "FACS"	/* Firmware ACPI Control Structure */
+#define PSDT_SIG                "PSDT"	/* Persistent System Description Table */
+#define RSDP_SIG                "RSD PTR "	/* Root System Description Pointer */
+#define RSDT_SIG                "RSDT"	/* Root System Description Table */
+#define XSDT_SIG                "XSDT"	/* Extended  System Description Table */
+#define SSDT_SIG                "SSDT"	/* Secondary System Description Table */
+#define RSDP_NAME               "RSDP"
+
+/*
+ * All tables and structures must be byte-packed to match the ACPI
+ * specification, since the tables are provided by the system BIOS
+ */
+#pragma pack(1)
+
+/*
+ * These are the ACPI tables that are directly consumed by the subsystem.
+ *
+ * The RSDP and FACS do not use the common ACPI table header. All other ACPI
+ * tables use the header.
+ *
  * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
  * This is the only type that is even remotely portable. Anything else is not
  * portable, so do not use any other bitfield types.
  */
 
-/*
- *  Values for description table header signatures
- */
-#define RSDP_NAME               "RSDP"
-#define RSDP_SIG                "RSD PTR "	/* RSDT Pointer signature */
-#define APIC_SIG                "APIC"	/* Multiple APIC Description Table */
-#define DSDT_SIG                "DSDT"	/* Differentiated System Description Table */
-#define FADT_SIG                "FACP"	/* Fixed ACPI Description Table */
-#define FACS_SIG                "FACS"	/* Firmware ACPI Control Structure */
-#define PSDT_SIG                "PSDT"	/* Persistent System Description Table */
-#define RSDT_SIG                "RSDT"	/* Root System Description Table */
-#define XSDT_SIG                "XSDT"	/* Extended  System Description Table */
-#define SSDT_SIG                "SSDT"	/* Secondary System Description Table */
-#define SBST_SIG                "SBST"	/* Smart Battery Specification Table */
-#define SPIC_SIG                "SPIC"	/* IOSAPIC table */
-#define BOOT_SIG                "BOOT"	/* Boot table */
-
-#define GL_OWNED                0x02	/* Ownership of global lock is bit 1 */
-
-/*
- * Common table types.  The base code can remain
- * constant if the underlying tables are changed
- */
-#define RSDT_DESCRIPTOR         struct rsdt_descriptor_rev2
-#define XSDT_DESCRIPTOR         struct xsdt_descriptor_rev2
-#define FACS_DESCRIPTOR         struct facs_descriptor_rev2
-#define FADT_DESCRIPTOR         struct fadt_descriptor_rev2
-
-#pragma pack(1)
-
-/*
- * ACPI Version-independent tables
+/*******************************************************************************
  *
- * NOTE: The tables that are specific to ACPI versions (1.0, 2.0, etc.)
- * are in separate files.
- */
-struct rsdp_descriptor {	/* Root System Descriptor Pointer */
-	char signature[8];	/* ACPI signature, contains "RSD PTR " */
-	u8 checksum;		/* ACPI 1.0 checksum */
-	char oem_id[6];		/* OEM identification */
-	u8 revision;		/* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
-	u32 rsdt_physical_address;	/* 32-bit physical address of the RSDT */
-	u32 length;		/* XSDT Length in bytes, including header */
-	u64 xsdt_physical_address;	/* 64-bit physical address of the XSDT */
-	u8 extended_checksum;	/* Checksum of entire table (ACPI 2.0) */
-	char reserved[3];	/* Reserved, must be zero */
-};
+ * ACPI Table Header. This common header is used by all tables except the
+ * RSDP and FACS. The define is used for direct inclusion of header into
+ * other ACPI tables
+ *
+ ******************************************************************************/
 
-struct acpi_common_facs {	/* Common FACS for internal use */
-	u32 *global_lock;
-	u64 *firmware_waking_vector;
-	u8 vector_width;
-};
-
-#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
+#define ACPI_TABLE_HEADER_DEF \
 	char                            signature[4];           /* ASCII table signature */\
 	u32                             length;                 /* Length of table in bytes, including this header */\
 	u8                              revision;               /* ACPI Specification minor version # */\
@@ -112,154 +91,239 @@
 	char                            oem_id[6];              /* ASCII OEM identification */\
 	char                            oem_table_id[8];        /* ASCII OEM table identification */\
 	u32                             oem_revision;           /* OEM revision number */\
-	char                            asl_compiler_id [4];    /* ASCII ASL compiler vendor ID */\
+	char                            asl_compiler_id[4];     /* ASCII ASL compiler vendor ID */\
 	u32                             asl_compiler_revision;	/* ASL compiler version */
 
-struct acpi_table_header {	/* ACPI common table header */
+struct acpi_table_header {
 ACPI_TABLE_HEADER_DEF};
 
 /*
- * MADT values and structures
+ * GAS - Generic Address Structure (ACPI 2.0+)
  */
+struct acpi_generic_address {
+	u8 address_space_id;	/* Address space where struct or register exists */
+	u8 register_bit_width;	/* Size in bits of given register */
+	u8 register_bit_offset;	/* Bit offset within the register */
+	u8 access_width;	/* Minimum Access size (ACPI 3.0) */
+	u64 address;		/* 64-bit address of struct or register */
+};
 
-/* Values for MADT PCATCompat */
+/*******************************************************************************
+ *
+ * RSDP - Root System Description Pointer (Signature is "RSD PTR ")
+ *
+ ******************************************************************************/
 
-#define DUAL_PIC                0
-#define MULTIPLE_APIC           1
+struct rsdp_descriptor {
+	char signature[8];	/* ACPI signature, contains "RSD PTR " */
+	u8 checksum;		/* ACPI 1.0 checksum */
+	char oem_id[6];		/* OEM identification */
+	u8 revision;		/* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
+	u32 rsdt_physical_address;	/* 32-bit physical address of the RSDT */
+	u32 length;		/* Table length in bytes, including header (ACPI 2.0+) */
+	u64 xsdt_physical_address;	/* 64-bit physical address of the XSDT (ACPI 2.0+) */
+	u8 extended_checksum;	/* Checksum of entire table (ACPI 2.0+) */
+	u8 reserved[3];		/* Reserved, must be zero */
+};
 
-/* Master MADT */
+#define ACPI_RSDP_REV0_SIZE     20	/* Size of original ACPI 1.0 RSDP */
 
-struct multiple_apic_table {
-	ACPI_TABLE_HEADER_DEF	/* ACPI common table header */
-	u32 local_apic_address;	/* Physical address of local APIC */
+/*******************************************************************************
+ *
+ * RSDT/XSDT - Root System Description Tables
+ *
+ ******************************************************************************/
+
+struct rsdt_descriptor {
+	ACPI_TABLE_HEADER_DEF u32 table_offset_entry[1];	/* Array of pointers to ACPI tables */
+};
+
+struct xsdt_descriptor {
+	ACPI_TABLE_HEADER_DEF u64 table_offset_entry[1];	/* Array of pointers to ACPI tables */
+};
+
+/*******************************************************************************
+ *
+ * FACS - Firmware ACPI Control Structure (FACS)
+ *
+ ******************************************************************************/
+
+struct facs_descriptor {
+	char signature[4];	/* ASCII table signature */
+	u32 length;		/* Length of structure, in bytes */
+	u32 hardware_signature;	/* Hardware configuration signature */
+	u32 firmware_waking_vector;	/* 32-bit physical address of the Firmware Waking Vector */
+	u32 global_lock;	/* Global Lock for shared hardware resources */
 
 	/* Flags (32 bits) */
 
-	u8 PCATcompat:1;	/* 00:    System also has dual 8259s */
+	u8 S4bios_f:1;		/* 00:    S4BIOS support is present */
 	 u8:7;			/* 01-07: Reserved, must be zero */
 	u8 reserved1[3];	/* 08-31: Reserved, must be zero */
+
+	u64 xfirmware_waking_vector;	/* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */
+	u8 version;		/* Version of this table (ACPI 2.0+) */
+	u8 reserved[31];	/* Reserved, must be zero */
 };
 
-/* Values for Type in APIC_HEADER_DEF */
-
-#define APIC_PROCESSOR          0
-#define APIC_IO                 1
-#define APIC_XRUPT_OVERRIDE     2
-#define APIC_NMI                3
-#define APIC_LOCAL_NMI          4
-#define APIC_ADDRESS_OVERRIDE   5
-#define APIC_IO_SAPIC           6
-#define APIC_LOCAL_SAPIC        7
-#define APIC_XRUPT_SOURCE       8
-#define APIC_RESERVED           9	/* 9 and greater are reserved */
+#define ACPI_GLOCK_PENDING      0x01	/* 00: Pending global lock ownership */
+#define ACPI_GLOCK_OWNED        0x02	/* 01: Global lock is owned */
 
 /*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
+ * Common FACS - This is a version-independent FACS structure used for internal use only
  */
-#define APIC_HEADER_DEF                     /* Common APIC sub-structure header */\
-	u8                              type; \
-	u8                              length;
-
-struct apic_header {
-APIC_HEADER_DEF};
-
-/* Values for MPS INTI flags */
-
-#define POLARITY_CONFORMS       0
-#define POLARITY_ACTIVE_HIGH    1
-#define POLARITY_RESERVED       2
-#define POLARITY_ACTIVE_LOW     3
-
-#define TRIGGER_CONFORMS        0
-#define TRIGGER_EDGE            1
-#define TRIGGER_RESERVED        2
-#define TRIGGER_LEVEL           3
-
-/* Common flag definitions (16 bits each) */
-
-#define MPS_INTI_FLAGS \
-	u8                              polarity        : 2;    /* 00-01: Polarity of APIC I/O input signals */\
-	u8                              trigger_mode    : 2;    /* 02-03: Trigger mode of APIC input signals */\
-	u8                                              : 4;    /* 04-07: Reserved, must be zero */\
-	u8                              reserved1;	/* 08-15: Reserved, must be zero */
-
-#define LOCAL_APIC_FLAGS \
-	u8                              processor_enabled: 1;   /* 00:    Processor is usable if set */\
-	u8                                              : 7;    /* 01-07: Reserved, must be zero */\
-	u8                              reserved2;	/* 08-15: Reserved, must be zero */
-
-/* Sub-structures for MADT */
-
-struct madt_processor_apic {
-	APIC_HEADER_DEF u8 processor_id;	/* ACPI processor id */
-	u8 local_apic_id;	/* Processor's local APIC id */
- LOCAL_APIC_FLAGS};
-
-struct madt_io_apic {
-	APIC_HEADER_DEF u8 io_apic_id;	/* I/O APIC ID */
-	u8 reserved;		/* Reserved - must be zero */
-	u32 address;		/* APIC physical address */
-	u32 interrupt;		/* Global system interrupt where INTI
-				 * lines start */
+struct acpi_common_facs {
+	u32 *global_lock;
+	u64 *firmware_waking_vector;
+	u8 vector_width;
 };
 
-struct madt_interrupt_override {
-	APIC_HEADER_DEF u8 bus;	/* 0 - ISA */
-	u8 source;		/* Interrupt source (IRQ) */
-	u32 interrupt;		/* Global system interrupt */
- MPS_INTI_FLAGS};
+/*******************************************************************************
+ *
+ * FADT - Fixed ACPI Description Table (Signature "FACP")
+ *
+ ******************************************************************************/
 
-struct madt_nmi_source {
-	APIC_HEADER_DEF MPS_INTI_FLAGS u32 interrupt;	/* Global system interrupt */
-};
+/* Fields common to all versions of the FADT */
 
-struct madt_local_apic_nmi {
-	APIC_HEADER_DEF u8 processor_id;	/* ACPI processor id */
-	MPS_INTI_FLAGS u8 lint;	/* LINTn to which NMI is connected */
-};
+#define ACPI_FADT_COMMON \
+	ACPI_TABLE_HEADER_DEF \
+	u32                             V1_firmware_ctrl;   /* 32-bit physical address of FACS */ \
+	u32                             V1_dsdt;            /* 32-bit physical address of DSDT */ \
+	u8                              reserved1;          /* System Interrupt Model isn't used in ACPI 2.0*/ \
+	u8                              prefer_PM_profile;  /* Conveys preferred power management profile to OSPM. */ \
+	u16                             sci_int;            /* System vector of SCI interrupt */ \
+	u32                             smi_cmd;            /* Port address of SMI command port */ \
+	u8                              acpi_enable;        /* Value to write to smi_cmd to enable ACPI */ \
+	u8                              acpi_disable;       /* Value to write to smi_cmd to disable ACPI */ \
+	u8                              S4bios_req;         /* Value to write to SMI CMD to enter S4BIOS state */ \
+	u8                              pstate_cnt;         /* Processor performance state control*/ \
+	u32                             V1_pm1a_evt_blk;    /* Port address of Power Mgt 1a Event Reg Blk */ \
+	u32                             V1_pm1b_evt_blk;    /* Port address of Power Mgt 1b Event Reg Blk */ \
+	u32                             V1_pm1a_cnt_blk;    /* Port address of Power Mgt 1a Control Reg Blk */ \
+	u32                             V1_pm1b_cnt_blk;    /* Port address of Power Mgt 1b Control Reg Blk */ \
+	u32                             V1_pm2_cnt_blk;     /* Port address of Power Mgt 2 Control Reg Blk */ \
+	u32                             V1_pm_tmr_blk;      /* Port address of Power Mgt Timer Ctrl Reg Blk */ \
+	u32                             V1_gpe0_blk;        /* Port addr of General Purpose acpi_event 0 Reg Blk */ \
+	u32                             V1_gpe1_blk;        /* Port addr of General Purpose acpi_event 1 Reg Blk */ \
+	u8                              pm1_evt_len;        /* Byte Length of ports at pm1_x_evt_blk */ \
+	u8                              pm1_cnt_len;        /* Byte Length of ports at pm1_x_cnt_blk */ \
+	u8                              pm2_cnt_len;        /* Byte Length of ports at pm2_cnt_blk */ \
+	u8                              pm_tm_len;          /* Byte Length of ports at pm_tm_blk */ \
+	u8                              gpe0_blk_len;       /* Byte Length of ports at gpe0_blk */ \
+	u8                              gpe1_blk_len;       /* Byte Length of ports at gpe1_blk */ \
+	u8                              gpe1_base;          /* Offset in gpe model where gpe1 events start */ \
+	u8                              cst_cnt;            /* Support for the _CST object and C States change notification.*/ \
+	u16                             plvl2_lat;          /* Worst case HW latency to enter/exit C2 state */ \
+	u16                             plvl3_lat;          /* Worst case HW latency to enter/exit C3 state */ \
+	u16                             flush_size;         /* Processor's memory cache line width, in bytes */ \
+	u16                             flush_stride;       /* Number of flush strides that need to be read */ \
+	u8                              duty_offset;        /* Processor's duty cycle index in processor's P_CNT reg*/ \
+	u8                              duty_width;         /* Processor's duty cycle value bit width in P_CNT register.*/ \
+	u8                              day_alrm;           /* Index to day-of-month alarm in RTC CMOS RAM */ \
+	u8                              mon_alrm;           /* Index to month-of-year alarm in RTC CMOS RAM */ \
+	u8                              century;            /* Index to century in RTC CMOS RAM */ \
+	u16                             iapc_boot_arch;     /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ \
+	u8                              reserved2;          /* Reserved, must be zero */
 
-struct madt_address_override {
-	APIC_HEADER_DEF u16 reserved;	/* Reserved, must be zero */
-	u64 address;		/* APIC physical address */
-};
+/*
+ * ACPI 2.0+ FADT
+ */
+struct fadt_descriptor {
+	ACPI_FADT_COMMON
+	    /* Flags (32 bits) */
+	u8 wb_invd:1;		/* 00:    The wbinvd instruction works properly */
+	u8 wb_invd_flush:1;	/* 01:    The wbinvd flushes but does not invalidate */
+	u8 proc_c1:1;		/* 02:    All processors support C1 state */
+	u8 plvl2_up:1;		/* 03:    C2 state works on MP system */
+	u8 pwr_button:1;	/* 04:    Power button is handled as a generic feature */
+	u8 sleep_button:1;	/* 05:    Sleep button is handled as a generic feature, or not present */
+	u8 fixed_rTC:1;		/* 06:    RTC wakeup stat not in fixed register space */
+	u8 rtcs4:1;		/* 07:    RTC wakeup stat not possible from S4 */
+	u8 tmr_val_ext:1;	/* 08:    tmr_val is 32 bits 0=24-bits */
+	u8 dock_cap:1;		/* 09:    Docking supported */
+	u8 reset_reg_sup:1;	/* 10:    System reset via the FADT RESET_REG supported */
+	u8 sealed_case:1;	/* 11:    No internal expansion capabilities and case is sealed */
+	u8 headless:1;		/* 12:    No local video capabilities or local input devices */
+	u8 cpu_sw_sleep:1;	/* 13:    Must execute native instruction after writing SLP_TYPx register */
 
-struct madt_io_sapic {
-	APIC_HEADER_DEF u8 io_sapic_id;	/* I/O SAPIC ID */
-	u8 reserved;		/* Reserved, must be zero */
-	u32 interrupt_base;	/* Glocal interrupt for SAPIC start */
-	u64 address;		/* SAPIC physical address */
-};
+	u8 pci_exp_wak:1;	/* 14:    System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */
+	u8 use_platform_clock:1;	/* 15:    OSPM should use platform-provided timer (ACPI 3.0) */
+	u8 S4rtc_sts_valid:1;	/* 16:    Contents of RTC_STS valid after S4 wake (ACPI 3.0) */
+	u8 remote_power_on_capable:1;	/* 17:    System is compatible with remote power on (ACPI 3.0) */
+	u8 force_apic_cluster_model:1;	/* 18:    All local APICs must use cluster model (ACPI 3.0) */
+	u8 force_apic_physical_destination_mode:1;	/* 19:   All local x_aPICs must use physical dest mode (ACPI 3.0) */
+	 u8:4;			/* 20-23: Reserved, must be zero */
+	u8 reserved3;		/* 24-31: Reserved, must be zero */
 
-struct madt_local_sapic {
-	APIC_HEADER_DEF u8 processor_id;	/* ACPI processor id */
-	u8 local_sapic_id;	/* SAPIC ID */
-	u8 local_sapic_eid;	/* SAPIC EID */
-	u8 reserved[3];		/* Reserved, must be zero */
-	 LOCAL_APIC_FLAGS u32 processor_uID;	/* Numeric UID - ACPI 3.0 */
-	char processor_uIDstring[1];	/* String UID  - ACPI 3.0 */
-};
-
-struct madt_interrupt_source {
-	APIC_HEADER_DEF MPS_INTI_FLAGS u8 interrupt_type;	/* 1=PMI, 2=INIT, 3=corrected */
-	u8 processor_id;	/* Processor ID */
-	u8 processor_eid;	/* Processor EID */
-	u8 io_sapic_vector;	/* Vector value for PMI interrupts */
-	u32 interrupt;		/* Global system interrupt */
-	u32 flags;		/* Interrupt Source Flags */
+	struct acpi_generic_address reset_register;	/* Reset register address in GAS format */
+	u8 reset_value;		/* Value to write to the reset_register port to reset the system */
+	u8 reserved4[3];	/* These three bytes must be zero */
+	u64 xfirmware_ctrl;	/* 64-bit physical address of FACS */
+	u64 Xdsdt;		/* 64-bit physical address of DSDT */
+	struct acpi_generic_address xpm1a_evt_blk;	/* Extended Power Mgt 1a acpi_event Reg Blk address */
+	struct acpi_generic_address xpm1b_evt_blk;	/* Extended Power Mgt 1b acpi_event Reg Blk address */
+	struct acpi_generic_address xpm1a_cnt_blk;	/* Extended Power Mgt 1a Control Reg Blk address */
+	struct acpi_generic_address xpm1b_cnt_blk;	/* Extended Power Mgt 1b Control Reg Blk address */
+	struct acpi_generic_address xpm2_cnt_blk;	/* Extended Power Mgt 2 Control Reg Blk address */
+	struct acpi_generic_address xpm_tmr_blk;	/* Extended Power Mgt Timer Ctrl Reg Blk address */
+	struct acpi_generic_address xgpe0_blk;	/* Extended General Purpose acpi_event 0 Reg Blk address */
+	struct acpi_generic_address xgpe1_blk;	/* Extended General Purpose acpi_event 1 Reg Blk address */
 };
 
 /*
- * Smart Battery
+ * "Down-revved" ACPI 2.0 FADT descriptor
+ * Defined here to allow compiler to generate the length of the struct
  */
-struct smart_battery_table {
-	ACPI_TABLE_HEADER_DEF u32 warning_level;
-	u32 low_level;
-	u32 critical_level;
+struct fadt_descriptor_rev2_minus {
+	ACPI_FADT_COMMON u32 flags;
+	struct acpi_generic_address reset_register;	/* Reset register address in GAS format */
+	u8 reset_value;		/* Value to write to the reset_register port to reset the system. */
+	u8 reserved7[3];	/* Reserved, must be zero */
 };
 
+/*
+ * ACPI 1.0 FADT
+ * Defined here to allow compiler to generate the length of the struct
+ */
+struct fadt_descriptor_rev1 {
+	ACPI_FADT_COMMON u32 flags;
+};
+
+/* FADT: Prefered Power Management Profiles */
+
+#define PM_UNSPECIFIED                  0
+#define PM_DESKTOP                      1
+#define PM_MOBILE                       2
+#define PM_WORKSTATION                  3
+#define PM_ENTERPRISE_SERVER            4
+#define PM_SOHO_SERVER                  5
+#define PM_APPLIANCE_PC                 6
+
+/* FADT: Boot Arch Flags */
+
+#define BAF_LEGACY_DEVICES              0x0001
+#define BAF_8042_KEYBOARD_CONTROLLER    0x0002
+
+#define FADT2_REVISION_ID               3
+#define FADT2_MINUS_REVISION_ID         2
+
+/* Reset to default packing */
+
 #pragma pack()
 
 /*
+ * This macro is temporary until the table bitfield flag definitions
+ * are removed and replaced by a Flags field.
+ */
+#define ACPI_FLAG_OFFSET(d,f,o)         (u8) (ACPI_OFFSET (d,f) + \
+			  sizeof(((d *)0)->f) + o)
+/*
+ * Get the remaining ACPI tables
+ */
+#include "actbl1.h"
+
+/*
  * ACPI Table information.  We save the table address, length,
  * and type of memory allocation (mapped or allocated) for each
  * table for 1) when we exit, and 2) if a new table is installed
@@ -290,27 +354,17 @@
 	u8 flags;
 };
 
-/*
- * Get the ACPI version-specific tables
- */
-#include "actbl1.h"		/* Acpi 1.0 table definitions */
-#include "actbl2.h"		/* Acpi 2.0 table definitions */
-
 extern u8 acpi_fadt_is_v1;	/* is set to 1 if FADT is revision 1,
 				 * needed for certain workarounds */
+/* Macros used to generate offsets to specific table fields */
 
-#pragma pack(1)
-/*
- * High performance timer
- */
-struct hpet_table {
-	ACPI_TABLE_HEADER_DEF u32 hardware_id;
-	struct acpi_generic_address base_address;
-	u8 hpet_number;
-	u16 clock_tick;
-	u8 attributes;
-};
+#define ACPI_FACS_OFFSET(f)             (u8) ACPI_OFFSET (struct facs_descriptor,f)
+#define ACPI_FADT_OFFSET(f)             (u8) ACPI_OFFSET (struct fadt_descriptor, f)
+#define ACPI_GAS_OFFSET(f)              (u8) ACPI_OFFSET (struct acpi_generic_address,f)
+#define ACPI_HDR_OFFSET(f)              (u8) ACPI_OFFSET (struct acpi_table_header,f)
+#define ACPI_RSDP_OFFSET(f)             (u8) ACPI_OFFSET (struct rsdp_descriptor,f)
 
-#pragma pack()
+#define ACPI_FADT_FLAG_OFFSET(f,o)      ACPI_FLAG_OFFSET (struct fadt_descriptor,f,o)
+#define ACPI_FACS_FLAG_OFFSET(f,o)      ACPI_FLAG_OFFSET (struct facs_descriptor,f,o)
 
 #endif				/* __ACTBL_H__ */
diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h
index cd428d5..745a644 100644
--- a/include/acpi/actbl1.h
+++ b/include/acpi/actbl1.h
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Name: actbl1.h - ACPI 1.0 tables
+ * Name: actbl1.h - Additional ACPI table definitions
  *
  *****************************************************************************/
 
@@ -44,92 +44,599 @@
 #ifndef __ACTBL1_H__
 #define __ACTBL1_H__
 
+/*******************************************************************************
+ *
+ * Additional ACPI Tables
+ *
+ * These tables are not consumed directly by the ACPICA subsystem, but are
+ * included here to support device drivers and the AML disassembler.
+ *
+ ******************************************************************************/
+
+/*
+ * Values for description table header signatures. Useful because they make
+ * it more difficult to inadvertently type in the wrong signature.
+ */
+#define ACPI_SIG_ASF            "ASF!"	/* Alert Standard Format table */
+#define ACPI_SIG_BOOT           "BOOT"	/* Simple Boot Flag Table */
+#define ACPI_SIG_CPEP           "CPEP"	/* Corrected Platform Error Polling table */
+#define ACPI_SIG_DBGP           "DBGP"	/* Debug Port table */
+#define ACPI_SIG_ECDT           "ECDT"	/* Embedded Controller Boot Resources Table */
+#define ACPI_SIG_HPET           "HPET"	/* High Precision Event Timer table */
+#define ACPI_SIG_MADT           "APIC"	/* Multiple APIC Description Table */
+#define ACPI_SIG_MCFG           "MCFG"	/* PCI Memory Mapped Configuration table */
+#define ACPI_SIG_SBST           "SBST"	/* Smart Battery Specification Table */
+#define ACPI_SIG_SLIT           "SLIT"	/* System Locality Distance Information Table */
+#define ACPI_SIG_SPCR           "SPCR"	/* Serial Port Console Redirection table */
+#define ACPI_SIG_SPMI           "SPMI"	/* Server Platform Management Interface table */
+#define ACPI_SIG_SRAT           "SRAT"	/* System Resource Affinity Table */
+#define ACPI_SIG_TCPA           "TCPA"	/* Trusted Computing Platform Alliance table */
+#define ACPI_SIG_WDRT           "WDRT"	/* Watchdog Resource Table */
+
+/* Legacy names */
+
+#define APIC_SIG                "APIC"	/* Multiple APIC Description Table */
+#define BOOT_SIG                "BOOT"	/* Simple Boot Flag Table */
+#define SBST_SIG                "SBST"	/* Smart Battery Specification Table */
+
+/*
+ * All tables must be byte-packed to match the ACPI specification, since
+ * the tables are provided by the system BIOS.
+ */
 #pragma pack(1)
 
 /*
- * ACPI 1.0 Root System Description Table (RSDT)
+ * Note about bitfields: The u8 type is used for bitfields in ACPI tables.
+ * This is the only type that is even remotely portable. Anything else is not
+ * portable, so do not use any other bitfield types.
  */
-struct rsdt_descriptor_rev1 {
-	ACPI_TABLE_HEADER_DEF	/* ACPI common table header */
-	u32 table_offset_entry[1];	/* Array of pointers to ACPI tables */
-};
+
+/*******************************************************************************
+ *
+ * ASF - Alert Standard Format table (Signature "ASF!")
+ *
+ ******************************************************************************/
+
+struct acpi_table_asf {
+ACPI_TABLE_HEADER_DEF};
+
+#define ACPI_ASF_HEADER_DEF \
+	u8                              type; \
+	u8                              reserved; \
+	u16                             length;
+
+struct acpi_asf_header {
+ACPI_ASF_HEADER_DEF};
+
+/* Values for Type field */
+
+#define ASF_INFO                0
+#define ASF_ALERT               1
+#define ASF_CONTROL             2
+#define ASF_BOOT                3
+#define ASF_ADDRESS             4
+#define ASF_RESERVED            5
 
 /*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
+ * ASF subtables
  */
-struct facs_descriptor_rev1 {
-	char signature[4];	/* ASCII table signature */
-	u32 length;		/* Length of structure in bytes */
-	u32 hardware_signature;	/* Hardware configuration signature */
-	u32 firmware_waking_vector;	/* ACPI OS waking vector */
-	u32 global_lock;	/* Global Lock */
+
+/* 0: ASF Information */
+
+struct acpi_asf_info {
+	ACPI_ASF_HEADER_DEF u8 min_reset_value;
+	u8 min_poll_interval;
+	u16 system_id;
+	u32 mfg_id;
+	u8 flags;
+	u8 reserved2[3];
+};
+
+/* 1: ASF Alerts */
+
+struct acpi_asf_alert {
+	ACPI_ASF_HEADER_DEF u8 assert_mask;
+	u8 deassert_mask;
+	u8 alerts;
+	u8 data_length;
+	u8 array[1];
+};
+
+/* 2: ASF Remote Control */
+
+struct acpi_asf_remote {
+	ACPI_ASF_HEADER_DEF u8 controls;
+	u8 data_length;
+	u16 reserved2;
+	u8 array[1];
+};
+
+/* 3: ASF RMCP Boot Options */
+
+struct acpi_asf_rmcp {
+	ACPI_ASF_HEADER_DEF u8 capabilities[7];
+	u8 completion_code;
+	u32 enterprise_id;
+	u8 command;
+	u16 parameter;
+	u16 boot_options;
+	u16 oem_parameters;
+};
+
+/* 4: ASF Address */
+
+struct acpi_asf_address {
+	ACPI_ASF_HEADER_DEF u8 eprom_address;
+	u8 devices;
+	u8 smbus_addresses[1];
+};
+
+/*******************************************************************************
+ *
+ * BOOT - Simple Boot Flag Table
+ *
+ ******************************************************************************/
+
+struct acpi_table_boot {
+	ACPI_TABLE_HEADER_DEF u8 cmos_index;	/* Index in CMOS RAM for the boot register */
+	u8 reserved[3];
+};
+
+/*******************************************************************************
+ *
+ * CPEP - Corrected Platform Error Polling table
+ *
+ ******************************************************************************/
+
+struct acpi_table_cpep {
+	ACPI_TABLE_HEADER_DEF u64 reserved;
+};
+
+/* Subtable */
+
+struct acpi_cpep_polling {
+	u8 type;
+	u8 length;
+	u8 processor_id;	/* Processor ID */
+	u8 processor_eid;	/* Processor EID */
+	u32 polling_interval;	/* Polling interval (msec) */
+};
+
+/*******************************************************************************
+ *
+ * DBGP - Debug Port table
+ *
+ ******************************************************************************/
+
+struct acpi_table_dbgp {
+	ACPI_TABLE_HEADER_DEF u8 interface_type;	/* 0=full 16550, 1=subset of 16550 */
+	u8 reserved[3];
+	struct acpi_generic_address debug_port;
+};
+
+/*******************************************************************************
+ *
+ * ECDT - Embedded Controller Boot Resources Table
+ *
+ ******************************************************************************/
+
+struct ec_boot_resources {
+	ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control;	/* Address of EC command/status register */
+	struct acpi_generic_address ec_data;	/* Address of EC data register */
+	u32 uid;		/* Unique ID - must be same as the EC _UID method */
+	u8 gpe_bit;		/* The GPE for the EC */
+	u8 ec_id[1];		/* Full namepath of the EC in the ACPI namespace */
+};
+
+/*******************************************************************************
+ *
+ * HPET - High Precision Event Timer table
+ *
+ ******************************************************************************/
+
+struct acpi_hpet_table {
+	ACPI_TABLE_HEADER_DEF u32 hardware_id;	/* Hardware ID of event timer block */
+	struct acpi_generic_address base_address;	/* Address of event timer block */
+	u8 hpet_number;		/* HPET sequence number */
+	u16 clock_tick;		/* Main counter min tick, periodic mode */
+	u8 attributes;
+};
+
+#if 0				/* HPET flags to be converted to macros */
+struct {			/* Flags (8 bits) */
+	u8 page_protect:1;	/* 00:    No page protection */
+	u8 page_protect4:1;	/* 01:    4_kB page protected */
+	u8 page_protect64:1;	/* 02:    64_kB page protected */
+	 u8:5;			/* 03-07: Reserved, must be zero */
+} flags;
+#endif
+
+/*******************************************************************************
+ *
+ * MADT - Multiple APIC Description Table
+ *
+ ******************************************************************************/
+
+struct multiple_apic_table {
+	ACPI_TABLE_HEADER_DEF u32 local_apic_address;	/* Physical address of local APIC */
 
 	/* Flags (32 bits) */
 
-	u8 S4bios_f:1;		/* 00:    S4BIOS support is present */
+	u8 PCATcompat:1;	/* 00:    System also has dual 8259s */
 	 u8:7;			/* 01-07: Reserved, must be zero */
 	u8 reserved1[3];	/* 08-31: Reserved, must be zero */
-
-	u8 reserved2[40];	/* Reserved, must be zero */
 };
 
+/* Values for MADT PCATCompat */
+
+#define DUAL_PIC                0
+#define MULTIPLE_APIC           1
+
+/* Common MADT Sub-table header */
+
+#define APIC_HEADER_DEF \
+	u8                              type; \
+	u8                              length;
+
+struct apic_header {
+APIC_HEADER_DEF};
+
+/* Values for Type in struct apic_header */
+
+#define APIC_PROCESSOR          0
+#define APIC_IO                 1
+#define APIC_XRUPT_OVERRIDE     2
+#define APIC_NMI                3
+#define APIC_LOCAL_NMI          4
+#define APIC_ADDRESS_OVERRIDE   5
+#define APIC_IO_SAPIC           6
+#define APIC_LOCAL_SAPIC        7
+#define APIC_XRUPT_SOURCE       8
+#define APIC_RESERVED           9	/* 9 and greater are reserved */
+
+/* Flag definitions for MADT sub-tables */
+
+#define ACPI_MADT_IFLAGS /* INTI flags (16 bits) */ \
+	u8                              polarity        : 2;    /* 00-01: Polarity of APIC I/O input signals */\
+	u8                              trigger_mode    : 2;    /* 02-03: Trigger mode of APIC input signals */\
+	u8                                              : 4;    /* 04-07: Reserved, must be zero */\
+	u8                              reserved1;	/* 08-15: Reserved, must be zero */
+
+#define ACPI_MADT_LFLAGS /* Local Sapic flags (32 bits) */ \
+	u8                              processor_enabled: 1;   /* 00:    Processor is usable if set */\
+	u8                                              : 7;    /* 01-07: Reserved, must be zero */\
+	u8                              reserved2[3];	/* 08-31: Reserved, must be zero */
+
+/* Values for MPS INTI flags */
+
+#define POLARITY_CONFORMS       0
+#define POLARITY_ACTIVE_HIGH    1
+#define POLARITY_RESERVED       2
+#define POLARITY_ACTIVE_LOW     3
+
+#define TRIGGER_CONFORMS        0
+#define TRIGGER_EDGE            1
+#define TRIGGER_RESERVED        2
+#define TRIGGER_LEVEL           3
+
 /*
- * ACPI 1.0 Fixed ACPI Description Table (FADT)
+ * MADT Sub-tables, correspond to Type in struct apic_header
  */
-struct fadt_descriptor_rev1 {
-	ACPI_TABLE_HEADER_DEF	/* ACPI common table header */
-	u32 firmware_ctrl;	/* Physical address of FACS */
-	u32 dsdt;		/* Physical address of DSDT */
-	u8 model;		/* System Interrupt Model */
-	u8 reserved1;		/* Reserved, must be zero */
-	u16 sci_int;		/* System vector of SCI interrupt */
-	u32 smi_cmd;		/* Port address of SMI command port */
-	u8 acpi_enable;		/* Value to write to smi_cmd to enable ACPI */
-	u8 acpi_disable;	/* Value to write to smi_cmd to disable ACPI */
-	u8 S4bios_req;		/* Value to write to SMI CMD to enter S4BIOS state */
-	u8 reserved2;		/* Reserved, must be zero */
-	u32 pm1a_evt_blk;	/* Port address of Power Mgt 1a acpi_event Reg Blk */
-	u32 pm1b_evt_blk;	/* Port address of Power Mgt 1b acpi_event Reg Blk */
-	u32 pm1a_cnt_blk;	/* Port address of Power Mgt 1a Control Reg Blk */
-	u32 pm1b_cnt_blk;	/* Port address of Power Mgt 1b Control Reg Blk */
-	u32 pm2_cnt_blk;	/* Port address of Power Mgt 2 Control Reg Blk */
-	u32 pm_tmr_blk;		/* Port address of Power Mgt Timer Ctrl Reg Blk */
-	u32 gpe0_blk;		/* Port addr of General Purpose acpi_event 0 Reg Blk */
-	u32 gpe1_blk;		/* Port addr of General Purpose acpi_event 1 Reg Blk */
-	u8 pm1_evt_len;		/* Byte length of ports at pm1_x_evt_blk */
-	u8 pm1_cnt_len;		/* Byte length of ports at pm1_x_cnt_blk */
-	u8 pm2_cnt_len;		/* Byte Length of ports at pm2_cnt_blk */
-	u8 pm_tm_len;		/* Byte Length of ports at pm_tm_blk */
-	u8 gpe0_blk_len;	/* Byte Length of ports at gpe0_blk */
-	u8 gpe1_blk_len;	/* Byte Length of ports at gpe1_blk */
-	u8 gpe1_base;		/* Offset in gpe model where gpe1 events start */
-	u8 reserved3;		/* Reserved, must be zero */
-	u16 plvl2_lat;		/* Worst case HW latency to enter/exit C2 state */
-	u16 plvl3_lat;		/* Worst case HW latency to enter/exit C3 state */
-	u16 flush_size;		/* Size of area read to flush caches */
-	u16 flush_stride;	/* Stride used in flushing caches */
-	u8 duty_offset;		/* Bit location of duty cycle field in p_cnt reg */
-	u8 duty_width;		/* Bit width of duty cycle field in p_cnt reg */
-	u8 day_alrm;		/* Index to day-of-month alarm in RTC CMOS RAM */
-	u8 mon_alrm;		/* Index to month-of-year alarm in RTC CMOS RAM */
-	u8 century;		/* Index to century in RTC CMOS RAM */
-	u8 reserved4[3];	/* Reserved, must be zero */
+
+/* 0: processor APIC */
+
+struct madt_processor_apic {
+	APIC_HEADER_DEF u8 processor_id;	/* ACPI processor id */
+	u8 local_apic_id;	/* Processor's local APIC id */
+ ACPI_MADT_LFLAGS};
+
+/* 1: IO APIC */
+
+struct madt_io_apic {
+	APIC_HEADER_DEF u8 io_apic_id;	/* I/O APIC ID */
+	u8 reserved;		/* Reserved - must be zero */
+	u32 address;		/* APIC physical address */
+	u32 interrupt;		/* Global system interrupt where INTI lines start */
+};
+
+/* 2: Interrupt Override */
+
+struct madt_interrupt_override {
+	APIC_HEADER_DEF u8 bus;	/* 0 - ISA */
+	u8 source;		/* Interrupt source (IRQ) */
+	u32 interrupt;		/* Global system interrupt */
+ ACPI_MADT_IFLAGS};
+
+/* 3: NMI Sources */
+
+struct madt_nmi_source {
+	APIC_HEADER_DEF ACPI_MADT_IFLAGS u32 interrupt;	/* Global system interrupt */
+};
+
+/* 4: Local APIC NMI */
+
+struct madt_local_apic_nmi {
+	APIC_HEADER_DEF u8 processor_id;	/* ACPI processor id */
+	ACPI_MADT_IFLAGS u8 lint;	/* LINTn to which NMI is connected */
+};
+
+/* 5: Address Override */
+
+struct madt_address_override {
+	APIC_HEADER_DEF u16 reserved;	/* Reserved, must be zero */
+	u64 address;		/* APIC physical address */
+};
+
+/* 6: I/O Sapic */
+
+struct madt_io_sapic {
+	APIC_HEADER_DEF u8 io_sapic_id;	/* I/O SAPIC ID */
+	u8 reserved;		/* Reserved, must be zero */
+	u32 interrupt_base;	/* Glocal interrupt for SAPIC start */
+	u64 address;		/* SAPIC physical address */
+};
+
+/* 7: Local Sapic */
+
+struct madt_local_sapic {
+	APIC_HEADER_DEF u8 processor_id;	/* ACPI processor id */
+	u8 local_sapic_id;	/* SAPIC ID */
+	u8 local_sapic_eid;	/* SAPIC EID */
+	u8 reserved[3];		/* Reserved, must be zero */
+	 ACPI_MADT_LFLAGS u32 processor_uID;	/* Numeric UID - ACPI 3.0 */
+	char processor_uIDstring[1];	/* String UID  - ACPI 3.0 */
+};
+
+/* 8: Platform Interrupt Source */
+
+struct madt_interrupt_source {
+	APIC_HEADER_DEF ACPI_MADT_IFLAGS u8 interrupt_type;	/* 1=PMI, 2=INIT, 3=corrected */
+	u8 processor_id;	/* Processor ID */
+	u8 processor_eid;	/* Processor EID */
+	u8 io_sapic_vector;	/* Vector value for PMI interrupts */
+	u32 interrupt;		/* Global system interrupt */
+	u32 flags;		/* Interrupt Source Flags */
+};
+
+#ifdef DUPLICATE_DEFINITION_WITH_LINUX_ACPI_H
+/*******************************************************************************
+ *
+ * MCFG - PCI Memory Mapped Configuration table and sub-table
+ *
+ ******************************************************************************/
+
+struct acpi_table_mcfg {
+	ACPI_TABLE_HEADER_DEF u8 reserved[8];
+};
+
+struct acpi_mcfg_allocation {
+	u64 base_address;	/* Base address, processor-relative */
+	u16 pci_segment;	/* PCI segment group number */
+	u8 start_bus_number;	/* Starting PCI Bus number */
+	u8 end_bus_number;	/* Final PCI Bus number */
+	u32 reserved;
+};
+#endif
+
+/*******************************************************************************
+ *
+ * SBST - Smart Battery Specification Table
+ *
+ ******************************************************************************/
+
+struct smart_battery_table {
+	ACPI_TABLE_HEADER_DEF u32 warning_level;
+	u32 low_level;
+	u32 critical_level;
+};
+
+/*******************************************************************************
+ *
+ * SLIT - System Locality Distance Information Table
+ *
+ ******************************************************************************/
+
+struct system_locality_info {
+	ACPI_TABLE_HEADER_DEF u64 locality_count;
+	u8 entry[1][1];
+};
+
+/*******************************************************************************
+ *
+ * SPCR - Serial Port Console Redirection table
+ *
+ ******************************************************************************/
+
+struct acpi_table_spcr {
+	ACPI_TABLE_HEADER_DEF u8 interface_type;	/* 0=full 16550, 1=subset of 16550 */
+	u8 reserved[3];
+	struct acpi_generic_address serial_port;
+	u8 interrupt_type;
+	u8 pc_interrupt;
+	u32 interrupt;
+	u8 baud_rate;
+	u8 parity;
+	u8 stop_bits;
+	u8 flow_control;
+	u8 terminal_type;
+	u8 reserved2;
+	u16 pci_device_id;
+	u16 pci_vendor_id;
+	u8 pci_bus;
+	u8 pci_device;
+	u8 pci_function;
+	u32 pci_flags;
+	u8 pci_segment;
+	u32 reserved3;
+};
+
+/*******************************************************************************
+ *
+ * SPMI - Server Platform Management Interface table
+ *
+ ******************************************************************************/
+
+struct acpi_table_spmi {
+	ACPI_TABLE_HEADER_DEF u8 reserved;
+	u8 interface_type;
+	u16 spec_revision;	/* Version of IPMI */
+	u8 interrupt_type;
+	u8 gpe_number;		/* GPE assigned */
+	u8 reserved2;
+	u8 pci_device_flag;
+	u32 interrupt;
+	struct acpi_generic_address ipmi_register;
+	u8 pci_segment;
+	u8 pci_bus;
+	u8 pci_device;
+	u8 pci_function;
+};
+
+/*******************************************************************************
+ *
+ * SRAT - System Resource Affinity Table
+ *
+ ******************************************************************************/
+
+struct system_resource_affinity {
+	ACPI_TABLE_HEADER_DEF u32 reserved1;	/* Must be value '1' */
+	u64 reserved2;		/* Reserved, must be zero */
+};
+
+/* SRAT common sub-table header */
+
+#define SRAT_SUBTABLE_HEADER \
+	u8                              type; \
+	u8                              length;
+
+/* Values for Type above */
+
+#define SRAT_CPU_AFFINITY       0
+#define SRAT_MEMORY_AFFINITY    1
+#define SRAT_RESERVED           2
+
+/* SRAT sub-tables */
+
+struct static_resource_alloc {
+	SRAT_SUBTABLE_HEADER u8 proximity_domain_lo;
+	u8 apic_id;
 
 	/* Flags (32 bits) */
 
-	u8 wb_invd:1;		/* 00:    The wbinvd instruction works properly */
-	u8 wb_invd_flush:1;	/* 01:    The wbinvd flushes but does not invalidate */
-	u8 proc_c1:1;		/* 02:    All processors support C1 state */
-	u8 plvl2_up:1;		/* 03:    C2 state works on MP system */
-	u8 pwr_button:1;	/* 04:    Power button is handled as a generic feature */
-	u8 sleep_button:1;	/* 05:    Sleep button is handled as a generic feature, or not present */
-	u8 fixed_rTC:1;		/* 06:    RTC wakeup stat not in fixed register space */
-	u8 rtcs4:1;		/* 07:    RTC wakeup stat not possible from S4 */
-	u8 tmr_val_ext:1;	/* 08:    tmr_val width is 32 bits (0 = 24 bits) */
-	 u8:7;			/* 09-15: Reserved, must be zero */
-	u8 reserved5[2];	/* 16-31: Reserved, must be zero */
+	u8 enabled:1;		/* 00:    Use affinity structure */
+	 u8:7;			/* 01-07: Reserved, must be zero */
+	u8 reserved3[3];	/* 08-31: Reserved, must be zero */
+
+	u8 local_sapic_eid;
+	u8 proximity_domain_hi[3];
+	u32 reserved4;		/* Reserved, must be zero */
 };
 
+struct memory_affinity {
+	SRAT_SUBTABLE_HEADER u32 proximity_domain;
+	u16 reserved3;
+	u64 base_address;
+	u64 address_length;
+	u32 reserved4;
+
+	/* Flags (32 bits) */
+
+	u8 enabled:1;		/* 00:    Use affinity structure */
+	u8 hot_pluggable:1;	/* 01:    Memory region is hot pluggable */
+	u8 non_volatile:1;	/* 02:    Memory is non-volatile */
+	 u8:5;			/* 03-07: Reserved, must be zero */
+	u8 reserved5[3];	/* 08-31: Reserved, must be zero */
+
+	u64 reserved6;		/* Reserved, must be zero */
+};
+
+/*******************************************************************************
+ *
+ * TCPA - Trusted Computing Platform Alliance table
+ *
+ ******************************************************************************/
+
+struct acpi_table_tcpa {
+	ACPI_TABLE_HEADER_DEF u16 reserved;
+	u32 max_log_length;	/* Maximum length for the event log area */
+	u64 log_address;	/* Address of the event log area */
+};
+
+/*******************************************************************************
+ *
+ * WDRT - Watchdog Resource Table
+ *
+ ******************************************************************************/
+
+struct acpi_table_wdrt {
+	ACPI_TABLE_HEADER_DEF u32 header_length;	/* Watchdog Header Length */
+	u8 pci_segment;		/* PCI Segment number */
+	u8 pci_bus;		/* PCI Bus number */
+	u8 pci_device;		/* PCI Device number */
+	u8 pci_function;	/* PCI Function number */
+	u32 timer_period;	/* Period of one timer count (msec) */
+	u32 max_count;		/* Maximum counter value supported */
+	u32 min_count;		/* Minimum counter value */
+	u8 flags;
+	u8 reserved[3];
+	u32 entries;		/* Number of watchdog entries that follow */
+};
+
+#if 0				/* Flags, will be converted to macros */
+u8 enabled:1;			/* 00:    Timer enabled */
+u8:6;				/* 01-06: Reserved */
+u8 sleep_stop:1;		/* 07:    Timer stopped in sleep state */
+#endif
+
+/* Macros used to generate offsets to specific table fields */
+
+#define ACPI_ASF0_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_asf_info,f)
+#define ACPI_ASF1_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_asf_alert,f)
+#define ACPI_ASF2_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_asf_remote,f)
+#define ACPI_ASF3_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_asf_rmcp,f)
+#define ACPI_ASF4_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_asf_address,f)
+#define ACPI_BOOT_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_boot,f)
+#define ACPI_CPEP_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_cpep,f)
+#define ACPI_CPEP0_OFFSET(f)            (u8) ACPI_OFFSET (struct acpi_cpep_polling,f)
+#define ACPI_DBGP_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_dbgp,f)
+#define ACPI_ECDT_OFFSET(f)             (u8) ACPI_OFFSET (struct ec_boot_resources,f)
+#define ACPI_HPET_OFFSET(f)             (u8) ACPI_OFFSET (struct hpet_table,f)
+#define ACPI_MADT_OFFSET(f)             (u8) ACPI_OFFSET (struct multiple_apic_table,f)
+#define ACPI_MADT0_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_processor_apic,f)
+#define ACPI_MADT1_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_io_apic,f)
+#define ACPI_MADT2_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_interrupt_override,f)
+#define ACPI_MADT3_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_nmi_source,f)
+#define ACPI_MADT4_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_local_apic_nmi,f)
+#define ACPI_MADT5_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_address_override,f)
+#define ACPI_MADT6_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_io_sapic,f)
+#define ACPI_MADT7_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_local_sapic,f)
+#define ACPI_MADT8_OFFSET(f)            (u8) ACPI_OFFSET (struct madt_interrupt_source,f)
+#define ACPI_MADTH_OFFSET(f)            (u8) ACPI_OFFSET (struct apic_header,f)
+#define ACPI_MCFG_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_mcfg,f)
+#define ACPI_MCFG0_OFFSET(f)            (u8) ACPI_OFFSET (struct acpi_mcfg_allocation,f)
+#define ACPI_SBST_OFFSET(f)             (u8) ACPI_OFFSET (struct smart_battery_table,f)
+#define ACPI_SLIT_OFFSET(f)             (u8) ACPI_OFFSET (struct system_locality_info,f)
+#define ACPI_SPCR_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_spcr,f)
+#define ACPI_SPMI_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_spmi,f)
+#define ACPI_SRAT_OFFSET(f)             (u8) ACPI_OFFSET (struct system_resource_affinity,f)
+#define ACPI_SRAT0_OFFSET(f)            (u8) ACPI_OFFSET (struct static_resource_alloc,f)
+#define ACPI_SRAT1_OFFSET(f)            (u8) ACPI_OFFSET (struct memory_affinity,f)
+#define ACPI_TCPA_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_tcpa,f)
+#define ACPI_WDRT_OFFSET(f)             (u8) ACPI_OFFSET (struct acpi_table_wdrt,f)
+
+#define ACPI_HPET_FLAG_OFFSET(f,o)      ACPI_FLAG_OFFSET (struct hpet_table,f,o)
+#define ACPI_SRAT0_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct static_resource_alloc,f,o)
+#define ACPI_SRAT1_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct memory_affinity,f,o)
+#define ACPI_MADT_FLAG_OFFSET(f,o)      ACPI_FLAG_OFFSET (struct multiple_apic_table,f,o)
+#define ACPI_MADT0_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct madt_processor_apic,f,o)
+#define ACPI_MADT2_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct madt_interrupt_override,f,o)
+#define ACPI_MADT3_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct madt_nmi_source,f,o)
+#define ACPI_MADT4_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct madt_local_apic_nmi,f,o)
+#define ACPI_MADT7_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct madt_local_sapic,f,o)
+#define ACPI_MADT8_FLAG_OFFSET(f,o)     ACPI_FLAG_OFFSET (struct madt_interrupt_source,f,o)
+
+/* Reset to default packing */
+
 #pragma pack()
 
 #endif				/* __ACTBL1_H__ */
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index dfc7ac1..67efe6c 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -44,234 +44,6 @@
 #ifndef __ACTBL2_H__
 #define __ACTBL2_H__
 
-/*
- * Prefered Power Management Profiles
- */
-#define PM_UNSPECIFIED                  0
-#define PM_DESKTOP                      1
-#define PM_MOBILE                       2
-#define PM_WORKSTATION                  3
-#define PM_ENTERPRISE_SERVER            4
-#define PM_SOHO_SERVER                  5
-#define PM_APPLIANCE_PC                 6
-
-/*
- * ACPI Boot Arch Flags
- */
-#define BAF_LEGACY_DEVICES              0x0001
-#define BAF_8042_KEYBOARD_CONTROLLER    0x0002
-
-#define FADT2_REVISION_ID               3
-#define FADT2_MINUS_REVISION_ID         2
-
-#pragma pack(1)
-
-/*
- * ACPI 2.0 Root System Description Table (RSDT)
- */
-struct rsdt_descriptor_rev2 {
-	ACPI_TABLE_HEADER_DEF	/* ACPI common table header */
-	u32 table_offset_entry[1];	/* Array of pointers to ACPI tables */
-};
-
-/*
- * ACPI 2.0 Extended System Description Table (XSDT)
- */
-struct xsdt_descriptor_rev2 {
-	ACPI_TABLE_HEADER_DEF	/* ACPI common table header */
-	u64 table_offset_entry[1];	/* Array of pointers to ACPI tables */
-};
-
-/*
- * ACPI 2.0 Firmware ACPI Control Structure (FACS)
- */
-struct facs_descriptor_rev2 {
-	char signature[4];	/* ASCII table signature */
-	u32 length;		/* Length of structure, in bytes */
-	u32 hardware_signature;	/* Hardware configuration signature */
-	u32 firmware_waking_vector;	/* 32-bit physical address of the Firmware Waking Vector. */
-	u32 global_lock;	/* Global Lock used to synchronize access to shared hardware resources */
-
-	/* Flags (32 bits) */
-
-	u8 S4bios_f:1;		/* 00:    S4BIOS support is present */
-	 u8:7;			/* 01-07: Reserved, must be zero */
-	u8 reserved1[3];	/* 08-31: Reserved, must be zero */
-
-	u64 xfirmware_waking_vector;	/* 64-bit physical address of the Firmware Waking Vector. */
-	u8 version;		/* Version of this table */
-	u8 reserved3[31];	/* Reserved, must be zero */
-};
-
-/*
- * ACPI 2.0+ Generic Address Structure (GAS)
- */
-struct acpi_generic_address {
-	u8 address_space_id;	/* Address space where struct or register exists. */
-	u8 register_bit_width;	/* Size in bits of given register */
-	u8 register_bit_offset;	/* Bit offset within the register */
-	u8 access_width;	/* Minimum Access size (ACPI 3.0) */
-	u64 address;		/* 64-bit address of struct or register */
-};
-
-#define FADT_REV2_COMMON \
-	u32                             V1_firmware_ctrl;   /* 32-bit physical address of FACS */ \
-	u32                             V1_dsdt;            /* 32-bit physical address of DSDT */ \
-	u8                              reserved1;          /* System Interrupt Model isn't used in ACPI 2.0*/ \
-	u8                              prefer_PM_profile;  /* Conveys preferred power management profile to OSPM. */ \
-	u16                             sci_int;            /* System vector of SCI interrupt */ \
-	u32                             smi_cmd;            /* Port address of SMI command port */ \
-	u8                              acpi_enable;        /* Value to write to smi_cmd to enable ACPI */ \
-	u8                              acpi_disable;       /* Value to write to smi_cmd to disable ACPI */ \
-	u8                              S4bios_req;         /* Value to write to SMI CMD to enter S4BIOS state */ \
-	u8                              pstate_cnt;         /* Processor performance state control*/ \
-	u32                             V1_pm1a_evt_blk;    /* Port address of Power Mgt 1a acpi_event Reg Blk */ \
-	u32                             V1_pm1b_evt_blk;    /* Port address of Power Mgt 1b acpi_event Reg Blk */ \
-	u32                             V1_pm1a_cnt_blk;    /* Port address of Power Mgt 1a Control Reg Blk */ \
-	u32                             V1_pm1b_cnt_blk;    /* Port address of Power Mgt 1b Control Reg Blk */ \
-	u32                             V1_pm2_cnt_blk;     /* Port address of Power Mgt 2 Control Reg Blk */ \
-	u32                             V1_pm_tmr_blk;      /* Port address of Power Mgt Timer Ctrl Reg Blk */ \
-	u32                             V1_gpe0_blk;        /* Port addr of General Purpose acpi_event 0 Reg Blk */ \
-	u32                             V1_gpe1_blk;        /* Port addr of General Purpose acpi_event 1 Reg Blk */ \
-	u8                              pm1_evt_len;        /* Byte length of ports at pm1_x_evt_blk */ \
-	u8                              pm1_cnt_len;        /* Byte length of ports at pm1_x_cnt_blk */ \
-	u8                              pm2_cnt_len;        /* Byte Length of ports at pm2_cnt_blk */ \
-	u8                              pm_tm_len;          /* Byte Length of ports at pm_tm_blk */ \
-	u8                              gpe0_blk_len;       /* Byte Length of ports at gpe0_blk */ \
-	u8                              gpe1_blk_len;       /* Byte Length of ports at gpe1_blk */ \
-	u8                              gpe1_base;          /* Offset in gpe model where gpe1 events start */ \
-	u8                              cst_cnt;            /* Support for the _CST object and C States change notification.*/ \
-	u16                             plvl2_lat;          /* Worst case HW latency to enter/exit C2 state */ \
-	u16                             plvl3_lat;          /* Worst case HW latency to enter/exit C3 state */ \
-	u16                             flush_size;         /* Number of flush strides that need to be read */ \
-	u16                             flush_stride;       /* Processor's memory cache line width, in bytes */ \
-	u8                              duty_offset;        /* Processor's duty cycle index in processor's P_CNT reg*/ \
-	u8                              duty_width;         /* Processor's duty cycle value bit width in P_CNT register.*/ \
-	u8                              day_alrm;           /* Index to day-of-month alarm in RTC CMOS RAM */ \
-	u8                              mon_alrm;           /* Index to month-of-year alarm in RTC CMOS RAM */ \
-	u8                              century;            /* Index to century in RTC CMOS RAM */ \
-	u16                             iapc_boot_arch;     /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/
-
-/*
- * ACPI 2.0+ Fixed ACPI Description Table (FADT)
- */
-struct fadt_descriptor_rev2 {
-	ACPI_TABLE_HEADER_DEF	/* ACPI common table header */
-	FADT_REV2_COMMON u8 reserved2;	/* Reserved, must be zero */
-
-	/* Flags (32 bits) */
-
-	u8 wb_invd:1;		/* 00:    The wbinvd instruction works properly */
-	u8 wb_invd_flush:1;	/* 01:    The wbinvd flushes but does not invalidate */
-	u8 proc_c1:1;		/* 02:    All processors support C1 state */
-	u8 plvl2_up:1;		/* 03:    C2 state works on MP system */
-	u8 pwr_button:1;	/* 04:    Power button is handled as a generic feature */
-	u8 sleep_button:1;	/* 05:    Sleep button is handled as a generic feature, or not present */
-	u8 fixed_rTC:1;		/* 06:    RTC wakeup stat not in fixed register space */
-	u8 rtcs4:1;		/* 07:    RTC wakeup stat not possible from S4 */
-	u8 tmr_val_ext:1;	/* 08:    tmr_val is 32 bits 0=24-bits */
-	u8 dock_cap:1;		/* 09:    Docking supported */
-	u8 reset_reg_sup:1;	/* 10:    System reset via the FADT RESET_REG supported */
-	u8 sealed_case:1;	/* 11:    No internal expansion capabilities and case is sealed */
-	u8 headless:1;		/* 12:    No local video capabilities or local input devices */
-	u8 cpu_sw_sleep:1;	/* 13:    Must execute native instruction after writing SLP_TYPx register */
-
-	u8 pci_exp_wak:1;	/* 14:    System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */
-	u8 use_platform_clock:1;	/* 15:    OSPM should use platform-provided timer (ACPI 3.0) */
-	u8 S4rtc_sts_valid:1;	/* 16:    Contents of RTC_STS valid after S4 wake (ACPI 3.0) */
-	u8 remote_power_on_capable:1;	/* 17:    System is compatible with remote power on (ACPI 3.0) */
-	u8 force_apic_cluster_model:1;	/* 18:    All local APICs must use cluster model (ACPI 3.0) */
-	u8 force_apic_physical_destination_mode:1;	/* 19:   all local x_aPICs must use physical dest mode (ACPI 3.0) */
-	 u8:4;			/* 20-23: Reserved, must be zero */
-	u8 reserved3;		/* 24-31: Reserved, must be zero */
-
-	struct acpi_generic_address reset_register;	/* Reset register address in GAS format */
-	u8 reset_value;		/* Value to write to the reset_register port to reset the system */
-	u8 reserved4[3];	/* These three bytes must be zero */
-	u64 xfirmware_ctrl;	/* 64-bit physical address of FACS */
-	u64 Xdsdt;		/* 64-bit physical address of DSDT */
-	struct acpi_generic_address xpm1a_evt_blk;	/* Extended Power Mgt 1a acpi_event Reg Blk address */
-	struct acpi_generic_address xpm1b_evt_blk;	/* Extended Power Mgt 1b acpi_event Reg Blk address */
-	struct acpi_generic_address xpm1a_cnt_blk;	/* Extended Power Mgt 1a Control Reg Blk address */
-	struct acpi_generic_address xpm1b_cnt_blk;	/* Extended Power Mgt 1b Control Reg Blk address */
-	struct acpi_generic_address xpm2_cnt_blk;	/* Extended Power Mgt 2 Control Reg Blk address */
-	struct acpi_generic_address xpm_tmr_blk;	/* Extended Power Mgt Timer Ctrl Reg Blk address */
-	struct acpi_generic_address xgpe0_blk;	/* Extended General Purpose acpi_event 0 Reg Blk address */
-	struct acpi_generic_address xgpe1_blk;	/* Extended General Purpose acpi_event 1 Reg Blk address */
-};
-
-/* "Down-revved" ACPI 2.0 FADT descriptor */
-
-struct fadt_descriptor_rev2_minus {
-	ACPI_TABLE_HEADER_DEF	/* ACPI common table header */
-	FADT_REV2_COMMON u8 reserved2;	/* Reserved, must be zero */
-	u32 flags;
-	struct acpi_generic_address reset_register;	/* Reset register address in GAS format */
-	u8 reset_value;		/* Value to write to the reset_register port to reset the system. */
-	u8 reserved7[3];	/* Reserved, must be zero */
-};
-
-/* ECDT - Embedded Controller Boot Resources Table */
-
-struct ec_boot_resources {
-	ACPI_TABLE_HEADER_DEF struct acpi_generic_address ec_control;	/* Address of EC command/status register */
-	struct acpi_generic_address ec_data;	/* Address of EC data register */
-	u32 uid;		/* Unique ID - must be same as the EC _UID method */
-	u8 gpe_bit;		/* The GPE for the EC */
-	u8 ec_id[1];		/* Full namepath of the EC in the ACPI namespace */
-};
-
-/* SRAT - System Resource Affinity Table */
-
-struct static_resource_alloc {
-	u8 type;
-	u8 length;
-	u8 proximity_domain_lo;
-	u8 apic_id;
-
-	/* Flags (32 bits) */
-
-	u8 enabled:1;		/* 00:    Use affinity structure */
-	 u8:7;			/* 01-07: Reserved, must be zero */
-	u8 reserved3[3];	/* 08-31: Reserved, must be zero */
-
-	u8 local_sapic_eid;
-	u8 proximity_domain_hi[3];
-	u32 reserved4;		/* Reserved, must be zero */
-};
-
-struct memory_affinity {
-	u8 type;
-	u8 length;
-	u32 proximity_domain;
-	u16 reserved3;
-	u64 base_address;
-	u64 address_length;
-	u32 reserved4;
-
-	/* Flags (32 bits) */
-
-	u8 enabled:1;		/* 00:    Use affinity structure */
-	u8 hot_pluggable:1;	/* 01:    Memory region is hot pluggable */
-	u8 non_volatile:1;	/* 02:    Memory is non-volatile */
-	 u8:5;			/* 03-07: Reserved, must be zero */
-	u8 reserved5[3];	/* 08-31: Reserved, must be zero */
-
-	u64 reserved6;		/* Reserved, must be zero */
-};
-
-struct system_resource_affinity {
-	ACPI_TABLE_HEADER_DEF u32 reserved1;	/* Must be value '1' */
-	u64 reserved2;		/* Reserved, must be zero */
-};
-
-/* SLIT - System Locality Distance Information Table */
-
-struct system_locality_info {
-	ACPI_TABLE_HEADER_DEF u64 locality_count;
-	u8 entry[1][1];
-};
-
-#pragma pack()
+/* Code moved to both actbl.h and actbl1.h */
 
 #endif				/* __ACTBL2_H__ */
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 7ca89cd..77cf123 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -44,6 +44,8 @@
 #ifndef __ACTYPES_H__
 #define __ACTYPES_H__
 
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
 /*
  * ACPI_MACHINE_WIDTH must be specified in an OS- or compiler-dependent header
  * and must be either 16, 32, or 64
@@ -154,7 +156,6 @@
 #define ACPI_MAX_PTR                    ACPI_UINT64_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT64_MAX
 
-#define ALIGNED_ADDRESS_BOUNDARY        0x00000008
 #define ACPI_USE_NATIVE_DIVIDE	/* Has native 64-bit integer support */
 
 /*
@@ -195,8 +196,6 @@
 #define ACPI_MAX_PTR                    ACPI_UINT32_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT32_MAX
 
-#define ALIGNED_ADDRESS_BOUNDARY        0x00000004
-
 /*******************************************************************************
  *
  * Types specific to 16-bit targets
@@ -223,7 +222,6 @@
 #define ACPI_MAX_PTR                    ACPI_UINT16_MAX
 #define ACPI_SIZE_MAX                   ACPI_UINT16_MAX
 
-#define ALIGNED_ADDRESS_BOUNDARY        0x00000002
 #define ACPI_USE_NATIVE_DIVIDE	/* No 64-bit integers, ok to use native divide */
 
 /* 64-bit integers cannot be supported */
@@ -254,7 +252,7 @@
 /* Use C99 uintptr_t for pointer casting if available, "void *" otherwise */
 
 #ifndef acpi_uintptr_t
-#define acpi_uintptr_t                          void *
+#define acpi_uintptr_t                  void *
 #endif
 
 /*
@@ -263,7 +261,7 @@
  * manager implementation is to be used (ACPI_USE_LOCAL_CACHE)
  */
 #ifndef acpi_cache_t
-#define acpi_cache_t                            struct acpi_memory_list
+#define acpi_cache_t                    struct acpi_memory_list
 #endif
 
 /*
@@ -271,7 +269,7 @@
  * lock and unlock OSL interfaces.
  */
 #ifndef acpi_cpu_flags
-#define acpi_cpu_flags                          acpi_native_uint
+#define acpi_cpu_flags                  acpi_native_uint
 #endif
 
 /*
@@ -292,6 +290,21 @@
 #define ACPI_UNUSED_VAR
 #endif
 
+/*
+ * All ACPICA functions that are available to the rest of the kernel are
+ * tagged with this macro which can be defined as appropriate for the host.
+ */
+#ifndef ACPI_EXPORT_SYMBOL
+#define ACPI_EXPORT_SYMBOL(symbol)
+#endif
+
+/*
+ * thread_id is returned by acpi_os_get_thread_id.
+ */
+#ifndef acpi_thread_id
+#define acpi_thread_id                  acpi_native_uint
+#endif
+
 /*******************************************************************************
  *
  * Independent types
@@ -477,15 +490,15 @@
  */
 typedef u32 acpi_table_type;
 
-#define ACPI_TABLE_RSDP                 (acpi_table_type) 0
-#define ACPI_TABLE_DSDT                 (acpi_table_type) 1
-#define ACPI_TABLE_FADT                 (acpi_table_type) 2
-#define ACPI_TABLE_FACS                 (acpi_table_type) 3
-#define ACPI_TABLE_PSDT                 (acpi_table_type) 4
-#define ACPI_TABLE_SSDT                 (acpi_table_type) 5
-#define ACPI_TABLE_XSDT                 (acpi_table_type) 6
-#define ACPI_TABLE_MAX                  6
-#define NUM_ACPI_TABLE_TYPES            (ACPI_TABLE_MAX+1)
+#define ACPI_TABLE_ID_RSDP              (acpi_table_type) 0
+#define ACPI_TABLE_ID_DSDT              (acpi_table_type) 1
+#define ACPI_TABLE_ID_FADT              (acpi_table_type) 2
+#define ACPI_TABLE_ID_FACS              (acpi_table_type) 3
+#define ACPI_TABLE_ID_PSDT              (acpi_table_type) 4
+#define ACPI_TABLE_ID_SSDT              (acpi_table_type) 5
+#define ACPI_TABLE_ID_XSDT              (acpi_table_type) 6
+#define ACPI_TABLE_ID_MAX               6
+#define ACPI_NUM_TABLE_TYPES            (ACPI_TABLE_ID_MAX+1)
 
 /*
  * Types associated with ACPI names and objects.  The first group of
@@ -816,7 +829,7 @@
 	u32 debug_level;
 	u32 debug_layer;
 	u32 num_table_types;
-	struct acpi_table_info table_info[NUM_ACPI_TABLE_TYPES];
+	struct acpi_table_info table_info[ACPI_TABLE_ID_MAX + 1];
 };
 
 /*
@@ -858,7 +871,7 @@
 				      void *handler_context,
 				      void *region_context);
 
-#define ACPI_DEFAULT_HANDLER        NULL
+#define ACPI_DEFAULT_HANDLER            NULL
 
 typedef
 acpi_status(*acpi_adr_space_setup) (acpi_handle region_handle,
@@ -911,12 +924,13 @@
 #define ACPI_STA_DEVICE_PRESENT         0x01
 #define ACPI_STA_DEVICE_ENABLED         0x02
 #define ACPI_STA_DEVICE_UI              0x04
-#define ACPI_STA_DEVICE_OK              0x08
+#define ACPI_STA_DEVICE_FUNCTIONING     0x08
+#define ACPI_STA_DEVICE_OK              0x08	/* Synonym */
 #define ACPI_STA_BATTERY_PRESENT        0x10
 
 #define ACPI_COMMON_OBJ_INFO \
-	acpi_object_type                    type;           /* ACPI object type */ \
-	acpi_name                           name	/* ACPI object Name */
+	acpi_object_type                type;           /* ACPI object type */ \
+	acpi_name                       name	/* ACPI object Name */
 
 struct acpi_obj_info_header {
 	ACPI_COMMON_OBJ_INFO;
@@ -957,7 +971,7 @@
  * Definitions for Resource Attributes
  */
 typedef u16 acpi_rs_length;	/* Resource Length field is fixed at 16 bits */
-typedef u32 acpi_rsdesc_size;	/* Max Resource Descriptor size is (length+3) = (64_k-1)+3 */
+typedef u32 acpi_rsdesc_size;	/* Max Resource Descriptor size is (Length+3) = (64_k-1)+3 */
 
 /*
  *  Memory Attributes
@@ -972,8 +986,8 @@
 
 /*
  *  IO Attributes
- *  The ISA Io ranges are:     n000-n0_ffh, n400-n4_ffh, n800-n8_ffh, n_c00-n_cFFh.
- *  The non-ISA Io ranges are: n100-n3_ffh, n500-n7_ffh, n900-n_bFfh, n_cd0-n_fFFh.
+ *  The ISA IO ranges are:     n000-n0_fFh, n400-n4_fFh, n800-n8_fFh, n_c00-n_cFFh.
+ *  The non-ISA IO ranges are: n100-n3_fFh, n500-n7_fFh, n900-n_bFFh, n_cd0-n_fFFh.
  */
 #define ACPI_NON_ISA_ONLY_RANGES        (u8) 0x01
 #define ACPI_ISA_ONLY_RANGES            (u8) 0x02
@@ -1171,12 +1185,12 @@
 /* Fields common to all address descriptors, 16/32/64 bit */
 
 #define ACPI_RESOURCE_ADDRESS_COMMON \
-	u8                                  resource_type; \
-	u8                                  producer_consumer; \
-	u8                                  decode; \
-	u8                                  min_address_fixed; \
-	u8                                  max_address_fixed; \
-	union acpi_resource_attribute       info;
+	u8                              resource_type; \
+	u8                              producer_consumer; \
+	u8                              decode; \
+	u8                              min_address_fixed; \
+	u8                              max_address_fixed; \
+	union acpi_resource_attribute   info;
 
 struct acpi_resource_address {
 ACPI_RESOURCE_ADDRESS_COMMON};
@@ -1297,16 +1311,6 @@
 
 #define ACPI_NEXT_RESOURCE(res)             (struct acpi_resource *)((u8 *) res + res->length)
 
-#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED
-#define ACPI_ALIGN_RESOURCE_SIZE(length)    (length)
-#else
-#define ACPI_ALIGN_RESOURCE_SIZE(length)    ACPI_ROUND_UP_TO_NATIVE_WORD(length)
-#endif
-
-/*
- * END: of definitions for Resource Attributes
- */
-
 struct acpi_pci_routing_table {
 	u32 length;
 	u32 pin;
@@ -1315,8 +1319,4 @@
 	char source[4];		/* pad to 64 bits so sizeof() works in all cases */
 };
 
-/*
- * END: of definitions for PCI Routing tables
- */
-
 #endif				/* __ACTYPES_H__ */
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 0927765..ba039ea 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -50,24 +50,24 @@
 
 #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
 
-extern const char *acpi_gbl_BMdecode[2];
-extern const char *acpi_gbl_config_decode[4];
-extern const char *acpi_gbl_consume_decode[2];
-extern const char *acpi_gbl_DECdecode[2];
-extern const char *acpi_gbl_HEdecode[2];
-extern const char *acpi_gbl_io_decode[2];
-extern const char *acpi_gbl_LLdecode[2];
-extern const char *acpi_gbl_max_decode[2];
-extern const char *acpi_gbl_MEMdecode[4];
-extern const char *acpi_gbl_min_decode[2];
-extern const char *acpi_gbl_MTPdecode[4];
-extern const char *acpi_gbl_RNGdecode[4];
-extern const char *acpi_gbl_RWdecode[2];
-extern const char *acpi_gbl_SHRdecode[2];
-extern const char *acpi_gbl_SIZdecode[4];
-extern const char *acpi_gbl_TRSdecode[2];
-extern const char *acpi_gbl_TTPdecode[2];
-extern const char *acpi_gbl_TYPdecode[4];
+extern const char *acpi_gbl_bm_decode[];
+extern const char *acpi_gbl_config_decode[];
+extern const char *acpi_gbl_consume_decode[];
+extern const char *acpi_gbl_dec_decode[];
+extern const char *acpi_gbl_he_decode[];
+extern const char *acpi_gbl_io_decode[];
+extern const char *acpi_gbl_ll_decode[];
+extern const char *acpi_gbl_max_decode[];
+extern const char *acpi_gbl_mem_decode[];
+extern const char *acpi_gbl_min_decode[];
+extern const char *acpi_gbl_mtp_decode[];
+extern const char *acpi_gbl_rng_decode[];
+extern const char *acpi_gbl_rw_decode[];
+extern const char *acpi_gbl_shr_decode[];
+extern const char *acpi_gbl_siz_decode[];
+extern const char *acpi_gbl_trs_decode[];
+extern const char *acpi_gbl_ttp_decode[];
+extern const char *acpi_gbl_typ_decode[];
 #endif
 
 /* Types for Resource descriptor entries */
@@ -78,6 +78,12 @@
 #define ACPI_SMALL_VARIABLE_LENGTH      3
 
 typedef
+acpi_status(*acpi_walk_aml_callback) (u8 * aml,
+				      u32 length,
+				      u32 offset,
+				      u8 resource_index, void **context);
+
+typedef
 acpi_status(*acpi_pkg_callback) (u8 object_type,
 				 union acpi_operand_object * source_object,
 				 union acpi_generic_state * state,
@@ -277,6 +283,8 @@
 
 void acpi_ut_dump_buffer(u8 * buffer, u32 count, u32 display, u32 component_id);
 
+void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display);
+
 void acpi_ut_report_error(char *module_name, u32 line_number);
 
 void acpi_ut_report_info(char *module_name, u32 line_number);
@@ -445,6 +453,8 @@
 /*
  * utmisc
  */
+u8 acpi_ut_is_aml_table(struct acpi_table_header *table);
+
 acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id);
 
 void acpi_ut_release_owner_id(acpi_owner_id * owner_id);
@@ -460,7 +470,9 @@
 
 u8 acpi_ut_valid_acpi_name(u32 name);
 
-u8 acpi_ut_valid_acpi_character(char character);
+acpi_name acpi_ut_repair_name(acpi_name name);
+
+u8 acpi_ut_valid_acpi_char(char character, acpi_native_uint position);
 
 acpi_status
 acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer);
@@ -469,6 +481,25 @@
 
 #define ACPI_ANY_BASE        0
 
+u32 acpi_ut_dword_byte_swap(u32 value);
+
+void acpi_ut_set_integer_width(u8 revision);
+
+#ifdef ACPI_DEBUG_OUTPUT
+void
+acpi_ut_display_init_pathname(u8 type,
+			      struct acpi_namespace_node *obj_handle,
+			      char *path);
+#endif
+
+/*
+ * utresrc
+ */
+acpi_status
+acpi_ut_walk_aml_resources(u8 * aml,
+			   acpi_size aml_length,
+			   acpi_walk_aml_callback user_function, void **context);
+
 acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index);
 
 u32 acpi_ut_get_descriptor_length(void *aml);
@@ -483,20 +514,6 @@
 acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc,
 			     u8 ** end_tag);
 
-u8 acpi_ut_generate_checksum(u8 * buffer, u32 length);
-
-u32 acpi_ut_dword_byte_swap(u32 value);
-
-void acpi_ut_set_integer_width(u8 revision);
-
-#ifdef ACPI_DEBUG_OUTPUT
-void
-acpi_ut_display_init_pathname(u8 type,
-			      struct acpi_namespace_node *obj_handle,
-			      char *path);
-
-#endif
-
 /*
  * utmutex - mutex support
  */
@@ -523,14 +540,15 @@
 
 void *acpi_ut_allocate(acpi_size size, u32 component, char *module, u32 line);
 
-void *acpi_ut_callocate(acpi_size size, u32 component, char *module, u32 line);
+void *acpi_ut_allocate_zeroed(acpi_size size,
+			      u32 component, char *module, u32 line);
 
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 void *acpi_ut_allocate_and_track(acpi_size size,
 				 u32 component, char *module, u32 line);
 
-void *acpi_ut_callocate_and_track(acpi_size size,
-				  u32 component, char *module, u32 line);
+void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
+					u32 component, char *module, u32 line);
 
 void
 acpi_ut_free_and_track(void *address, u32 component, char *module, u32 line);
@@ -540,6 +558,11 @@
 #endif				/* ACPI_FUTURE_USAGE */
 
 void acpi_ut_dump_allocations(u32 component, char *module);
+
+acpi_status
+acpi_ut_create_list(char *list_name,
+		    u16 object_size, struct acpi_memory_list **return_cache);
+
 #endif
 
 #endif				/* _ACUTILS_H */
diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h
index 37964a5..cf18426 100644
--- a/include/acpi/amlcode.h
+++ b/include/acpi/amlcode.h
@@ -180,8 +180,10 @@
 #define AML_BANK_FIELD_OP           (u16) 0x5b87
 #define AML_DATA_REGION_OP          (u16) 0x5b88	/* ACPI 2.0 */
 
-/* Bogus opcodes (they are actually two separate opcodes) */
-
+/*
+ * Combination opcodes (actually two one-byte opcodes)
+ * Used by the disassembler and i_aSL compiler
+ */
 #define AML_LGREATEREQUAL_OP        (u16) 0x9295
 #define AML_LLESSEQUAL_OP           (u16) 0x9294
 #define AML_LNOTEQUAL_OP            (u16) 0x9293
diff --git a/include/acpi/amlresrc.h b/include/acpi/amlresrc.h
index fb47353..be03818 100644
--- a/include/acpi/amlresrc.h
+++ b/include/acpi/amlresrc.h
@@ -42,39 +42,45 @@
  * POSSIBILITY OF SUCH DAMAGES.
  */
 
+/* acpisrc:struct_defs -- for acpisrc conversion */
+
 #ifndef __AMLRESRC_H
 #define __AMLRESRC_H
 
-#define ASL_RESNAME_ADDRESS                     "_ADR"
-#define ASL_RESNAME_ALIGNMENT                   "_ALN"
-#define ASL_RESNAME_ADDRESSSPACE                "_ASI"
-#define ASL_RESNAME_ACCESSSIZE                  "_ASZ"
-#define ASL_RESNAME_TYPESPECIFICATTRIBUTES      "_ATT"
-#define ASL_RESNAME_BASEADDRESS                 "_BAS"
-#define ASL_RESNAME_BUSMASTER                   "_BM_"	/* Master(1), Slave(0) */
-#define ASL_RESNAME_DECODE                      "_DEC"
-#define ASL_RESNAME_DMA                         "_DMA"
-#define ASL_RESNAME_DMATYPE                     "_TYP"	/* Compatible(0), A(1), B(2), F(3) */
-#define ASL_RESNAME_GRANULARITY                 "_GRA"
-#define ASL_RESNAME_INTERRUPT                   "_INT"
-#define ASL_RESNAME_INTERRUPTLEVEL              "_LL_"	/* active_lo(1), active_hi(0) */
-#define ASL_RESNAME_INTERRUPTSHARE              "_SHR"	/* Shareable(1), no_share(0) */
-#define ASL_RESNAME_INTERRUPTTYPE               "_HE_"	/* Edge(1), Level(0) */
-#define ASL_RESNAME_LENGTH                      "_LEN"
-#define ASL_RESNAME_MEMATTRIBUTES               "_MTP"	/* Memory(0), Reserved(1), ACPI(2), NVS(3) */
-#define ASL_RESNAME_MEMTYPE                     "_MEM"	/* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */
-#define ASL_RESNAME_MAXADDR                     "_MAX"
-#define ASL_RESNAME_MINADDR                     "_MIN"
-#define ASL_RESNAME_MAXTYPE                     "_MAF"
-#define ASL_RESNAME_MINTYPE                     "_MIF"
-#define ASL_RESNAME_REGISTERBITOFFSET           "_RBO"
-#define ASL_RESNAME_REGISTERBITWIDTH            "_RBW"
-#define ASL_RESNAME_RANGETYPE                   "_RNG"
-#define ASL_RESNAME_READWRITETYPE               "_RW_"	/* read_only(0), Writeable (1) */
-#define ASL_RESNAME_TRANSLATION                 "_TRA"
-#define ASL_RESNAME_TRANSTYPE                   "_TRS"	/* Sparse(1), Dense(0) */
-#define ASL_RESNAME_TYPE                        "_TTP"	/* Translation(1), Static (0) */
-#define ASL_RESNAME_XFERTYPE                    "_SIz"	/* 8(0), 8_and16(1), 16(2) */
+/*
+ * Resource descriptor tags, as defined in the ACPI specification.
+ * Used to symbolically reference fields within a descriptor.
+ */
+#define ACPI_RESTAG_ADDRESS                     "_ADR"
+#define ACPI_RESTAG_ALIGNMENT                   "_ALN"
+#define ACPI_RESTAG_ADDRESSSPACE                "_ASI"
+#define ACPI_RESTAG_ACCESSSIZE                  "_ASZ"
+#define ACPI_RESTAG_TYPESPECIFICATTRIBUTES      "_ATT"
+#define ACPI_RESTAG_BASEADDRESS                 "_BAS"
+#define ACPI_RESTAG_BUSMASTER                   "_BM_"	/* Master(1), Slave(0) */
+#define ACPI_RESTAG_DECODE                      "_DEC"
+#define ACPI_RESTAG_DMA                         "_DMA"
+#define ACPI_RESTAG_DMATYPE                     "_TYP"	/* Compatible(0), A(1), B(2), F(3) */
+#define ACPI_RESTAG_GRANULARITY                 "_GRA"
+#define ACPI_RESTAG_INTERRUPT                   "_INT"
+#define ACPI_RESTAG_INTERRUPTLEVEL              "_LL_"	/* active_lo(1), active_hi(0) */
+#define ACPI_RESTAG_INTERRUPTSHARE              "_SHR"	/* Shareable(1), no_share(0) */
+#define ACPI_RESTAG_INTERRUPTTYPE               "_HE_"	/* Edge(1), Level(0) */
+#define ACPI_RESTAG_LENGTH                      "_LEN"
+#define ACPI_RESTAG_MEMATTRIBUTES               "_MTP"	/* Memory(0), Reserved(1), ACPI(2), NVS(3) */
+#define ACPI_RESTAG_MEMTYPE                     "_MEM"	/* non_cache(0), Cacheable(1) Cache+combine(2), Cache+prefetch(3) */
+#define ACPI_RESTAG_MAXADDR                     "_MAX"
+#define ACPI_RESTAG_MINADDR                     "_MIN"
+#define ACPI_RESTAG_MAXTYPE                     "_MAF"
+#define ACPI_RESTAG_MINTYPE                     "_MIF"
+#define ACPI_RESTAG_REGISTERBITOFFSET           "_RBO"
+#define ACPI_RESTAG_REGISTERBITWIDTH            "_RBW"
+#define ACPI_RESTAG_RANGETYPE                   "_RNG"
+#define ACPI_RESTAG_READWRITETYPE               "_RW_"	/* read_only(0), Writeable (1) */
+#define ACPI_RESTAG_TRANSLATION                 "_TRA"
+#define ACPI_RESTAG_TRANSTYPE                   "_TRS"	/* Sparse(1), Dense(0) */
+#define ACPI_RESTAG_TYPE                        "_TTP"	/* Translation(1), Static (0) */
+#define ACPI_RESTAG_XFERTYPE                    "_SIZ"	/* 8(0), 8_and16(1), 16(2) */
 
 /* Default sizes for "small" resource descriptors */
 
@@ -109,7 +115,7 @@
  * SMALL descriptors
  */
 #define AML_RESOURCE_SMALL_HEADER_COMMON \
-	u8                                  descriptor_type;
+	u8                              descriptor_type;
 
 struct aml_resource_small_header {
 AML_RESOURCE_SMALL_HEADER_COMMON};
@@ -162,8 +168,8 @@
  * LARGE descriptors
  */
 #define AML_RESOURCE_LARGE_HEADER_COMMON \
-	u8                                  descriptor_type;\
-	u16                                 resource_length;
+	u8                              descriptor_type;\
+	u16                             resource_length;
 
 struct aml_resource_large_header {
 AML_RESOURCE_LARGE_HEADER_COMMON};
@@ -194,9 +200,9 @@
 };
 
 #define AML_RESOURCE_ADDRESS_COMMON \
-	u8                                  resource_type; \
-	u8                                  flags; \
-	u8                                  specific_flags;
+	u8                              resource_type; \
+	u8                              flags; \
+	u8                              specific_flags;
 
 struct aml_resource_address {
 AML_RESOURCE_LARGE_HEADER_COMMON AML_RESOURCE_ADDRESS_COMMON};
@@ -266,6 +272,7 @@
 union aml_resource {
 	/* Descriptor headers */
 
+	u8 descriptor_type;
 	struct aml_resource_small_header small_header;
 	struct aml_resource_large_header large_header;
 
@@ -296,9 +303,9 @@
 	/* Utility overlays */
 
 	struct aml_resource_address address;
-	u32 u32_item;
-	u16 u16_item;
-	u8 U8item;
+	u32 dword_item;
+	u16 word_item;
+	u8 byte_item;
 };
 
 #endif
diff --git a/include/acpi/pdc_intel.h b/include/acpi/pdc_intel.h
index 3fa81d5..c5472be 100644
--- a/include/acpi/pdc_intel.h
+++ b/include/acpi/pdc_intel.h
@@ -18,6 +18,11 @@
 					 ACPI_PDC_C_C1_HALT | \
 					 ACPI_PDC_P_FFH)
 
+#define ACPI_PDC_EST_CAPABILITY_SWSMP	(ACPI_PDC_SMP_C1PT | \
+					 ACPI_PDC_C_C1_HALT | \
+					 ACPI_PDC_SMP_P_SWCOORD | \
+					 ACPI_PDC_P_FFH)
+
 #define ACPI_PDC_C_CAPABILITY_SMP	(ACPI_PDC_SMP_C2C3 | \
 					 ACPI_PDC_SMP_C1PT | \
 					 ACPI_PDC_C_C1_HALT)
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h
index 223ec64..453a469 100644
--- a/include/acpi/platform/acenv.h
+++ b/include/acpi/platform/acenv.h
@@ -49,33 +49,41 @@
  */
 
 #ifdef ACPI_LIBRARY
+/*
+ * Note: The non-debug version of the acpi_library does not contain any
+ * debug support, for minimimal size. The debug version uses ACPI_FULL_DEBUG
+ */
 #define ACPI_USE_LOCAL_CACHE
 #endif
 
-#ifdef ACPI_DUMP_APP
-#ifndef MSDOS
-#define ACPI_DEBUG_OUTPUT
-#endif
-#define ACPI_APPLICATION
-#define ACPI_DISASSEMBLER
-#define ACPI_NO_METHOD_EXECUTION
-#endif
-
-#ifdef ACPI_EXEC_APP
-#undef DEBUGGER_THREADING
-#define DEBUGGER_THREADING      DEBUGGER_SINGLE_THREADED
-#define ACPI_DEBUG_OUTPUT
-#define ACPI_APPLICATION
-#define ACPI_DEBUGGER
-#define ACPI_DISASSEMBLER
-#define ACPI_MUTEX_DEBUG
-#endif
-
 #ifdef ACPI_ASL_COMPILER
 #define ACPI_DEBUG_OUTPUT
 #define ACPI_APPLICATION
 #define ACPI_DISASSEMBLER
 #define ACPI_CONSTANT_EVAL_ONLY
+#define ACPI_LARGE_NAMESPACE_NODE
+#define ACPI_DATA_TABLE_DISASSEMBLY
+#endif
+
+#ifdef ACPI_EXEC_APP
+#undef DEBUGGER_THREADING
+#define DEBUGGER_THREADING      DEBUGGER_SINGLE_THREADED
+#define ACPI_FULL_DEBUG
+#define ACPI_APPLICATION
+#define ACPI_DEBUGGER
+#define ACPI_MUTEX_DEBUG
+#define ACPI_DBG_TRACK_ALLOCATIONS
+#endif
+
+#ifdef ACPI_DASM_APP
+#ifndef MSDOS
+#define ACPI_DEBUG_OUTPUT
+#endif
+#define ACPI_APPLICATION
+#define ACPI_DISASSEMBLER
+#define ACPI_NO_METHOD_EXECUTION
+#define ACPI_LARGE_NAMESPACE_NODE
+#define ACPI_DATA_TABLE_DISASSEMBLY
 #endif
 
 #ifdef ACPI_APPLICATION
@@ -83,6 +91,12 @@
 #define ACPI_USE_LOCAL_CACHE
 #endif
 
+#ifdef ACPI_FULL_DEBUG
+#define ACPI_DEBUGGER
+#define ACPI_DEBUG_OUTPUT
+#define ACPI_DISASSEMBLER
+#endif
+
 /*
  * Environment configuration.  The purpose of this file is to interface to the
  * local generation environment.
@@ -137,7 +151,7 @@
 #elif defined(MSDOS)		/* Must appear after WIN32 and WIN64 check */
 #include "acdos16.h"
 
-#elif defined(__FreeBSD__)
+#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 #include "acfreebsd.h"
 
 #elif defined(__NetBSD__)
@@ -163,17 +177,6 @@
 
 #endif
 
-/*
- * Memory allocation tracking.  Used only if
- * 1) This is the debug version
- * 2) This is NOT a 16-bit version of the code (not enough real-mode memory)
- */
-#ifdef ACPI_DEBUG_OUTPUT
-#if ACPI_MACHINE_WIDTH != 16
-#define ACPI_DBG_TRACK_ALLOCATIONS
-#endif
-#endif
-
 /*! [End] no source code translation !*/
 
 /*
@@ -271,8 +274,8 @@
 /*
  * Storage alignment properties
  */
-#define  _AUPBND                (sizeof (acpi_native_uint) - 1)
-#define  _ADNBND                (sizeof (acpi_native_uint) - 1)
+#define  _AUPBND                (sizeof (acpi_native_int) - 1)
+#define  _ADNBND                (sizeof (acpi_native_int) - 1)
 
 /*
  * Variable argument list macro definitions
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 2e6d545..277d35b 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -49,30 +49,24 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/ctype.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
 #include <asm/div64.h>
 #include <asm/acpi.h>
-
-#define strtoul simple_strtoul
-
-#define ACPI_MACHINE_WIDTH  BITS_PER_LONG
-
-/* Type(s) for the OSL */
-
-#ifdef ACPI_USE_LOCAL_CACHE
-#define acpi_cache_t	struct acpi_memory_list
-#else
 #include <linux/slab.h>
-#define acpi_cache_t	kmem_cache_t
-#endif
+
+/* Host-dependent types and defines */
+
+#define ACPI_MACHINE_WIDTH          BITS_PER_LONG
+#define acpi_cache_t                        kmem_cache_t
+#define ACPI_EXPORT_SYMBOL(symbol)  EXPORT_SYMBOL(symbol);
+#define strtoul                     simple_strtoul
 
 /* Full namespace pathname length limit - arbitrary */
-
 #define ACPI_PATHNAME_MAX              256
 
 #else				/* !__KERNEL__ */
@@ -104,4 +98,8 @@
 
 #define acpi_cpu_flags unsigned long
 
+#define acpi_thread_id u32
+
+static inline acpi_thread_id acpi_os_get_thread_id(void) { return 0; }
+
 #endif				/* __ACLINUX_H__ */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index badf027..77371b3 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -2,7 +2,7 @@
 #define __ACPI_PROCESSOR_H
 
 #include <linux/kernel.h>
-#include <linux/config.h>
+#include <linux/cpu.h>
 
 #include <asm/acpi.h>
 
@@ -18,6 +18,17 @@
 
 #define ACPI_PDC_REVISION_ID		0x1
 
+#define ACPI_PSD_REV0_REVISION		0 /* Support for _PSD as in ACPI 3.0 */
+#define ACPI_PSD_REV0_ENTRIES		5
+
+/*
+ * Types of coordination defined in ACPI 3.0. Same macros can be used across
+ * P, C and T states
+ */
+#define DOMAIN_COORD_TYPE_SW_ALL	0xfc
+#define DOMAIN_COORD_TYPE_SW_ANY	0xfd
+#define DOMAIN_COORD_TYPE_HW_ALL	0xfe
+
 /* Power Management */
 
 struct acpi_processor_cx;
@@ -66,6 +77,14 @@
 
 /* Performance Management */
 
+struct acpi_psd_package {
+	acpi_integer num_entries;
+	acpi_integer revision;
+	acpi_integer domain;
+	acpi_integer coord_type;
+	acpi_integer num_processors;
+} __attribute__ ((packed));
+
 struct acpi_pct_register {
 	u8 descriptor;
 	u16 length;
@@ -92,7 +111,9 @@
 	struct acpi_pct_register status_register;
 	unsigned int state_count;
 	struct acpi_processor_px *states;
-
+	struct acpi_psd_package domain_info;
+	cpumask_t shared_cpu_map;
+	unsigned int shared_type;
 };
 
 /* Throttling Control */
@@ -161,6 +182,9 @@
 	} piix4;
 };
 
+extern int acpi_processor_preregister_performance(
+		struct acpi_processor_performance **performance);
+
 extern int acpi_processor_register_performance(struct acpi_processor_performance
 					       *performance, unsigned int cpu);
 extern void acpi_processor_unregister_performance(struct
diff --git a/include/asm-alpha/bitops.h b/include/asm-alpha/bitops.h
index 3f88715..4b6ef7f 100644
--- a/include/asm-alpha/bitops.h
+++ b/include/asm-alpha/bitops.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_BITOPS_H
 #define _ALPHA_BITOPS_H
 
-#include <linux/config.h>
 #include <asm/compiler.h>
 
 /*
diff --git a/include/asm-alpha/cache.h b/include/asm-alpha/cache.h
index e6d4d16..f199e69 100644
--- a/include/asm-alpha/cache.h
+++ b/include/asm-alpha/cache.h
@@ -4,7 +4,6 @@
 #ifndef __ARCH_ALPHA_CACHE_H
 #define __ARCH_ALPHA_CACHE_H
 
-#include <linux/config.h>
 
 /* Bytes per L1 (data) cache line. */
 #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EV6)
diff --git a/include/asm-alpha/cacheflush.h b/include/asm-alpha/cacheflush.h
index 3fc6ef7..805640b4 100644
--- a/include/asm-alpha/cacheflush.h
+++ b/include/asm-alpha/cacheflush.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_CACHEFLUSH_H
 #define _ALPHA_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 /* Caches aren't brain-dead on the Alpha. */
diff --git a/include/asm-alpha/core_cia.h b/include/asm-alpha/core_cia.h
index 3a70d68..9e0516c 100644
--- a/include/asm-alpha/core_cia.h
+++ b/include/asm-alpha/core_cia.h
@@ -4,7 +4,6 @@
 /* Define to experiment with fitting everything into one 512MB HAE window.  */
 #define CIA_ONE_HAE_WINDOW 1
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/compiler.h>
 
diff --git a/include/asm-alpha/core_t2.h b/include/asm-alpha/core_t2.h
index 5c1c403..457c34b 100644
--- a/include/asm-alpha/core_t2.h
+++ b/include/asm-alpha/core_t2.h
@@ -1,7 +1,6 @@
 #ifndef __ALPHA_T2__H__
 #define __ALPHA_T2__H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/compiler.h>
@@ -436,7 +435,7 @@
 	set_hae(msb); \
 }
 
-static spinlock_t t2_hae_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(t2_hae_lock);
 
 __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
 {
diff --git a/include/asm-alpha/dma-mapping.h b/include/asm-alpha/dma-mapping.h
index 62d0d66..b9ff4d8 100644
--- a/include/asm-alpha/dma-mapping.h
+++ b/include/asm-alpha/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_DMA_MAPPING_H
 #define _ALPHA_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
diff --git a/include/asm-alpha/dma.h b/include/asm-alpha/dma.h
index 683afaa..87cfdbd 100644
--- a/include/asm-alpha/dma.h
+++ b/include/asm-alpha/dma.h
@@ -18,7 +18,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
diff --git a/include/asm-alpha/floppy.h b/include/asm-alpha/floppy.h
index 289a00d..21816d3 100644
--- a/include/asm-alpha/floppy.h
+++ b/include/asm-alpha/floppy.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_ALPHA_FLOPPY_H
 #define __ASM_ALPHA_FLOPPY_H
 
-#include <linux/config.h>
 
 #define fd_inb(port)			inb_p(port)
 #define fd_outb(value,port)		outb_p(value,port)
@@ -26,9 +25,8 @@
 #define fd_enable_irq()         enable_irq(FLOPPY_IRQ)
 #define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
 #define fd_cacheflush(addr,size) /* nothing */
-#define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt, \
-					    SA_INTERRUPT|SA_SAMPLE_RANDOM, \
-				            "floppy", NULL)
+#define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt,\
+					    SA_INTERRUPT, "floppy", NULL)
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
 
 #ifdef CONFIG_PCI
diff --git a/include/asm-alpha/hardirq.h b/include/asm-alpha/hardirq.h
index 7bb6a36..d953e23 100644
--- a/include/asm-alpha/hardirq.h
+++ b/include/asm-alpha/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_HARDIRQ_H
 #define _ALPHA_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cache.h>
 
diff --git a/include/asm-alpha/hw_irq.h b/include/asm-alpha/hw_irq.h
index a310b9e..ca9d43b 100644
--- a/include/asm-alpha/hw_irq.h
+++ b/include/asm-alpha/hw_irq.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_HW_IRQ_H
 #define _ALPHA_HW_IRQ_H
 
-#include <linux/config.h>
 
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
 
diff --git a/include/asm-alpha/ide.h b/include/asm-alpha/ide.h
index 6126afe..2a5cc0b 100644
--- a/include/asm-alpha/ide.h
+++ b/include/asm-alpha/ide.h
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define IDE_ARCH_OBSOLETE_DEFAULTS
 
diff --git a/include/asm-alpha/io.h b/include/asm-alpha/io.h
index 3ebbeee..f5ae98c 100644
--- a/include/asm-alpha/io.h
+++ b/include/asm-alpha/io.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/compiler.h>
 #include <asm/system.h>
diff --git a/include/asm-alpha/irq.h b/include/asm-alpha/irq.h
index 566db72..917b9fe 100644
--- a/include/asm-alpha/irq.h
+++ b/include/asm-alpha/irq.h
@@ -8,7 +8,6 @@
  */
 
 #include <linux/linkage.h>
-#include <linux/config.h>
 
 #if   defined(CONFIG_ALPHA_GENERIC)
 
@@ -93,8 +92,4 @@
 struct pt_regs;
 extern void (*perf_irq)(unsigned long, struct pt_regs *);
 
-struct irqaction;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
-
 #endif /* _ALPHA_IRQ_H */
diff --git a/include/asm-alpha/kmap_types.h b/include/asm-alpha/kmap_types.h
index 3d10cd3..3e6735a 100644
--- a/include/asm-alpha/kmap_types.h
+++ b/include/asm-alpha/kmap_types.h
@@ -3,7 +3,6 @@
 
 /* Dummy header just to define km_type. */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
diff --git a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h
index ece166a..aced22f 100644
--- a/include/asm-alpha/machvec.h
+++ b/include/asm-alpha/machvec.h
@@ -1,7 +1,6 @@
 #ifndef __ALPHA_MACHVEC_H
 #define __ALPHA_MACHVEC_H 1
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /*
diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h
index 0c017fc..fe249e9 100644
--- a/include/asm-alpha/mmu_context.h
+++ b/include/asm-alpha/mmu_context.h
@@ -7,7 +7,6 @@
  * Copyright (C) 1996, Linus Torvalds
  */
 
-#include <linux/config.h>
 #include <asm/system.h>
 #include <asm/machvec.h>
 #include <asm/compiler.h>
diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
index 192d80c..64d0ab9 100644
--- a/include/asm-alpha/mmzone.h
+++ b/include/asm-alpha/mmzone.h
@@ -5,7 +5,6 @@
 #ifndef _ASM_MMZONE_H_
 #define _ASM_MMZONE_H_
 
-#include <linux/config.h>
 #include <asm/smp.h>
 
 struct bootmem_data_t; /* stupid forward decl. */
diff --git a/include/asm-alpha/page.h b/include/asm-alpha/page.h
index 61bcf70..8c7cd50 100644
--- a/include/asm-alpha/page.h
+++ b/include/asm-alpha/page.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_PAGE_H
 #define _ALPHA_PAGE_H
 
-#include <linux/config.h>
 #include <asm/pal.h>
 
 /* PAGE_SHIFT determines the page size */
diff --git a/include/asm-alpha/param.h b/include/asm-alpha/param.h
index 3ed0b3b..214e799 100644
--- a/include/asm-alpha/param.h
+++ b/include/asm-alpha/param.h
@@ -5,7 +5,6 @@
    hardware ignores reprogramming.  We also need userland buy-in to the 
    change in HZ, since this is visible in the wait4 resources etc.  */
 
-#include <linux/config.h>
 
 #ifndef HZ
 # ifndef CONFIG_ALPHA_RAWHIDE
diff --git a/include/asm-alpha/pgalloc.h b/include/asm-alpha/pgalloc.h
index 3084756..471864e 100644
--- a/include/asm-alpha/pgalloc.h
+++ b/include/asm-alpha/pgalloc.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_PGALLOC_H
 #define _ALPHA_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/mmzone.h>
 
diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
index a985cd2..93eaa58 100644
--- a/include/asm-alpha/pgtable.h
+++ b/include/asm-alpha/pgtable.h
@@ -10,7 +10,6 @@
  * This hopefully works with any standard Alpha page-size, as defined
  * in <asm/page.h> (currently 8192).
  */
-#include <linux/config.h>
 #include <linux/mmzone.h>
 
 #include <asm/page.h>
diff --git a/include/asm-alpha/serial.h b/include/asm-alpha/serial.h
index 7e4b298..9d263e8 100644
--- a/include/asm-alpha/serial.h
+++ b/include/asm-alpha/serial.h
@@ -2,7 +2,6 @@
  * include/asm-alpha/serial.h
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff --git a/include/asm-alpha/smp.h b/include/asm-alpha/smp.h
index e143210..a1a1eca 100644
--- a/include/asm-alpha/smp.h
+++ b/include/asm-alpha/smp.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
diff --git a/include/asm-alpha/spinlock.h b/include/asm-alpha/spinlock.h
index 8197c69..0c294c9b 100644
--- a/include/asm-alpha/spinlock.h
+++ b/include/asm-alpha/spinlock.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_SPINLOCK_H
 #define _ALPHA_SPINLOCK_H
 
-#include <linux/config.h>
 #include <asm/system.h>
 #include <linux/kernel.h>
 #include <asm/current.h>
diff --git a/include/asm-alpha/system.h b/include/asm-alpha/system.h
index f3b7b1a..03e9c0e 100644
--- a/include/asm-alpha/system.h
+++ b/include/asm-alpha/system.h
@@ -1,7 +1,6 @@
 #ifndef __ALPHA_SYSTEM_H
 #define __ALPHA_SYSTEM_H
 
-#include <linux/config.h>
 #include <asm/pal.h>
 #include <asm/page.h>
 #include <asm/barrier.h>
diff --git a/include/asm-alpha/tlbflush.h b/include/asm-alpha/tlbflush.h
index 9d484c1..1ca3ed3 100644
--- a/include/asm-alpha/tlbflush.h
+++ b/include/asm-alpha/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _ALPHA_TLBFLUSH_H
 #define _ALPHA_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/compiler.h>
 
diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
index ef25b65..bc6e6a9 100644
--- a/include/asm-alpha/unistd.h
+++ b/include/asm-alpha/unistd.h
@@ -383,6 +383,8 @@
 #define __NR_inotify_add_watch		445
 #define __NR_inotify_rm_watch		446
 
+#ifdef __KERNEL__
+
 #define NR_SYSCALLS			447
 
 #if defined(__GNUC__)
@@ -565,9 +567,8 @@
 	_syscall_return(type);						\
 }
 
-#endif /* __LIBRARY__ && __GNUC__ */
+#endif /* __GNUC__ */
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -578,7 +579,6 @@
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -661,4 +661,5 @@
 
 #define cond_syscall(x)  asm(".weak\t" #x "\n" #x " = sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ALPHA_UNISTD_H */
diff --git a/include/asm-alpha/vga.h b/include/asm-alpha/vga.h
index 8ca4f6b..ed06f59b 100644
--- a/include/asm-alpha/vga.h
+++ b/include/asm-alpha/vga.h
@@ -46,6 +46,6 @@
 #define vga_readb(a)	readb((u8 __iomem *)(a))
 #define vga_writeb(v,a)	writeb(v, (u8 __iomem *)(a))
 
-#define VGA_MAP_MEM(x)	((unsigned long) ioremap(x, 0))
+#define VGA_MAP_MEM(x,s)	((unsigned long) ioremap(x, s))
 
 #endif
diff --git a/include/asm-arm/apm.h b/include/asm-arm/apm.h
index 3a50eb7..d09113b 100644
--- a/include/asm-arm/apm.h
+++ b/include/asm-arm/apm.h
@@ -13,7 +13,6 @@
 #ifndef ARM_ASM_SA1100_APM_H
 #define ARM_ASM_SA1100_APM_H
 
-#include <linux/config.h>
 #include <linux/apm_bios.h>
 
 /*
diff --git a/include/asm-arm/arch-aaec2000/io.h b/include/asm-arm/arch-aaec2000/io.h
index 8d67907..d710204 100644
--- a/include/asm-arm/arch-aaec2000/io.h
+++ b/include/asm-arm/arch-aaec2000/io.h
@@ -16,6 +16,5 @@
  */
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #endif
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
index d8209f8..24b51cc 100644
--- a/include/asm-arm/arch-aaec2000/memory.h
+++ b/include/asm-arm/arch-aaec2000/memory.h
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 
 #define PHYS_OFFSET	UL(0xf0000000)
 
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h
new file mode 100644
index 0000000..bff5ea4
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h
@@ -0,0 +1,81 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_spi.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * Serial Peripheral Interface (SPI) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_SPI_H
+#define AT91RM9200_SPI_H
+
+#define AT91_SPI_CR			0x00		/* Control Register */
+#define		AT91_SPI_SPIEN		(1 <<  0)		/* SPI Enable */
+#define		AT91_SPI_SPIDIS		(1 <<  1)		/* SPI Disable */
+#define		AT91_SPI_SWRST		(1 <<  7)		/* SPI Software Reset */
+#define		AT91_SPI_LASTXFER	(1 << 24)		/* Last Transfer [SAM9261 only] */
+
+#define AT91_SPI_MR			0x04		/* Mode Register */
+#define		AT91_SPI_MSTR		(1    <<  0)		/* Master/Slave Mode */
+#define		AT91_SPI_PS		(1    <<  1)		/* Peripheral Select */
+#define			AT91_SPI_PS_FIXED	(0 << 1)
+#define			AT91_SPI_PS_VARIABLE	(1 << 1)
+#define		AT91_SPI_PCSDEC		(1    <<  2)		/* Chip Select Decode */
+#define		AT91_SPI_DIV32		(1    <<  3)		/* Clock Selection */
+#define		AT91_SPI_MODFDIS	(1    <<  4)		/* Mode Fault Detection */
+#define		AT91_SPI_LLB		(1    <<  7)		/* Local Loopback Enable */
+#define		AT91_SPI_PCS		(0xf  << 16)		/* Peripheral Chip Select */
+#define		AT91_SPI_DLYBCS		(0xff << 24)		/* Delay Between Chip Selects */
+
+#define AT91_SPI_RDR		0x08			/* Receive Data Register */
+#define		AT91_SPI_RD		(0xffff <<  0)		/* Receive Data */
+#define		AT91_SPI_PCS		(0xf	<< 16)		/* Peripheral Chip Select */
+
+#define AT91_SPI_TDR		0x0c			/* Transmit Data Register */
+#define		AT91_SPI_TD		(0xffff <<  0)		/* Transmit Data */
+#define		AT91_SPI_PCS		(0xf	<< 16)		/* Peripheral Chip Select */
+#define		AT91_SPI_LASTXFER	(1	<< 24)		/* Last Transfer [SAM9261 only] */
+
+#define AT91_SPI_SR		0x10			/* Status Register */
+#define		AT91_SPI_RDRF		(1 <<  0)		/* Receive Data Register Full */
+#define		AT91_SPI_TDRE		(1 <<  1)		/* Transmit Data Register Full */
+#define		AT91_SPI_MODF		(1 <<  2)		/* Mode Fault Error */
+#define		AT91_SPI_OVRES		(1 <<  3)		/* Overrun Error Status */
+#define		AT91_SPI_ENDRX		(1 <<  4)		/* End of RX buffer */
+#define		AT91_SPI_ENDTX		(1 <<  5)		/* End of TX buffer */
+#define		AT91_SPI_RXBUFF		(1 <<  6)		/* RX Buffer Full */
+#define		AT91_SPI_TXBUFE		(1 <<  7)		/* TX Buffer Empty */
+#define		AT91_SPI_NSSR		(1 <<  8)		/* NSS Rising [SAM9261 only] */
+#define		AT91_SPI_TXEMPTY	(1 <<  9)		/* Transmission Register Empty [SAM9261 only] */
+#define		AT91_SPI_SPIENS		(1 << 16)		/* SPI Enable Status */
+
+#define AT91_SPI_IER		0x14			/* Interrupt Enable Register */
+#define AT91_SPI_IDR		0x18			/* Interrupt Disable Register */
+#define AT91_SPI_IMR		0x1c			/* Interrupt Mask Register */
+
+#define AT91_SPI_CSR(n)		(0x30 + ((n) * 4))	/* Chip Select Registers 0-3 */
+#define		AT91_SPI_CPOL		(1    <<  0)		/* Clock Polarity */
+#define		AT91_SPI_NCPHA		(1    <<  1)		/* Clock Phase */
+#define		AT91_SPI_CSAAT		(1    <<  3)		/* Chip Select Active After Transfer [SAM9261 only] */
+#define		AT91_SPI_BITS		(0xf  <<  4)		/* Bits Per Transfer */
+#define			AT91_SPI_BITS_8		(0 << 4)
+#define			AT91_SPI_BITS_9		(1 << 4)
+#define			AT91_SPI_BITS_10	(2 << 4)
+#define			AT91_SPI_BITS_11	(3 << 4)
+#define			AT91_SPI_BITS_12	(4 << 4)
+#define			AT91_SPI_BITS_13	(5 << 4)
+#define			AT91_SPI_BITS_14	(6 << 4)
+#define			AT91_SPI_BITS_15	(7 << 4)
+#define			AT91_SPI_BITS_16	(8 << 4)
+#define		AT91_SPI_SCBR		(0xff <<  8)		/* Serial Clock Baud Rate */
+#define		AT91_SPI_DLYBS		(0xff << 16)		/* Delay before SPCK */
+#define		AT91_SPI_DLYBCT		(0xff << 24)		/* Delay between Consecutive Transfers */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h
new file mode 100644
index 0000000..ac88022
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h
@@ -0,0 +1,96 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Serial Synchronous Controller (SSC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_SSC_H
+#define AT91RM9200_SSC_H
+
+#define AT91_SSC_CR		0x00	/* Control Register */
+#define		AT91_SSC_RXEN		(1 <<  0)	/* Receive Enable */
+#define		AT91_SSC_RXDIS		(1 <<  1)	/* Receive Disable */
+#define		AT91_SSC_TXEN		(1 <<  8)	/* Transmit Enable */
+#define		AT91_SSC_TXDIS		(1 <<  9)	/* Transmit Disable */
+#define		AT91_SSC_SWRST		(1 << 15)	/* Software Reset */
+
+#define AT91_SSC_CMR		0x04	/* Clock Mode Register */
+#define		AT91_SSC_CMR_DIV	(0xfff << 0)	/* Clock Divider */
+
+#define AT91_SSC_RCMR		0x10	/* Receive Clock Mode Register */
+#define		AT91_SSC_CKS		(3    <<  0)	/* Clock Selection */
+#define			AT91_SSC_CKS_DIV		(0 << 0)
+#define			AT91_SSC_CKS_CLOCK		(1 << 0)
+#define			AT91_SSC_CKS_PIN		(2 << 0)
+#define		AT91_SSC_CKO		(7    <<  2)	/* Clock Output Mode Selection */
+#define			AT91_SSC_CKO_NONE		(0 << 2)
+#define			AT91_SSC_CKO_CONTINUOUS		(1 << 2)
+#define		AT91_SSC_CKI		(1    <<  5)	/* Clock Inversion */
+#define			AT91_SSC_CKI_FALLING		(0 << 5)
+#define			AT91_SSC_CK_RISING		(1 << 5)
+#define		AT91_SSC_START		(0xf  <<  8)	/* Start Selection */
+#define			AT91_SSC_START_CONTINUOUS	(0 << 8)
+#define			AT91_SSC_START_TX_RX		(1 << 8)
+#define			AT91_SSC_START_LOW_RF		(2 << 8)
+#define			AT91_SSC_START_HIGH_RF		(3 << 8)
+#define			AT91_SSC_START_FALLING_RF	(4 << 8)
+#define			AT91_SSC_START_RISING_RF	(5 << 8)
+#define			AT91_SSC_START_LEVEL_RF		(6 << 8)
+#define			AT91_SSC_START_EDGE_RF		(7 << 8)
+#define		AT91_SSC_STTDLY		(0xff << 16)	/* Start Delay */
+#define		AT91_SSC_PERIOD		(0xff << 24)	/* Period Divider Selection */
+
+#define AT91_SSC_RFMR		0x14	/* Receive Frame Mode Register */
+#define		AT91_SSC_DATALEN	(0x1f <<  0)	/* Data Length */
+#define		AT91_SSC_LOOP		(1    <<  5)	/* Loop Mode */
+#define		AT91_SSC_MSBF		(1    <<  7)	/* Most Significant Bit First */
+#define		AT91_SSC_DATNB		(0xf  <<  8)	/* Data Number per Frame */
+#define		AT91_SSC_FSLEN		(0xf  << 16)	/* Frame Sync Length */
+#define		AT91_SSC_FSOS		(7    << 20)	/* Frame Sync Output Selection */
+#define			AT91_SSC_FSOS_NONE		(0 << 20)
+#define			AT91_SSC_FSOS_NEGATIVE		(1 << 20)
+#define			AT91_SSC_FSOS_POSITIVE		(2 << 20)
+#define			AT91_SSC_FSOS_LOW		(3 << 20)
+#define			AT91_SSC_FSOS_HIGH		(4 << 20)
+#define			AT91_SSC_FSOS_TOGGLE		(5 << 20)
+#define		AT91_SSC_FSEDGE		(1    << 24)	/* Frame Sync Edge Detection */
+#define			AT91_SSC_FSEDGE_POSITIVE	(0 << 24)
+#define			AT91_SSC_FSEDGE_NEGATIVE	(1 << 24)
+
+#define AT91_SSC_TCMR		0x18	/* Transmit Clock Mode Register */
+#define AT91_SSC_TFMR		0x1c	/* Transmit Fram Mode Register */
+#define		AT91_SSC_DATDEF		(1 <<  5)	/* Data Default Value */
+#define		AT91_SSC_FSDEN		(1 << 23)	/* Frame Sync Data Enable */
+
+#define AT91_SSC_RHR		0x20	/* Receive Holding Register */
+#define AT91_SSC_THR		0x24	/* Transmit Holding Register */
+#define AT91_SSC_RSHR		0x30	/* Receive Sync Holding Register */
+#define AT91_SSC_TSHR		0x34	/* Transmit Sync Holding Register */
+
+#define AT91_SSC_SR		0x40	/* Status Register */
+#define		AT91_SSC_TXRDY		(1 <<  0)	/* Transmit Ready */
+#define		AT91_SSC_TXEMPTY	(1 <<  1)	/* Transmit Empty */
+#define		AT91_SSC_ENDTX		(1 <<  2)	/* End of Transmission */
+#define		AT91_SSC_TXBUFE		(1 <<  3)	/* Transmit Buffer Empty */
+#define		AT91_SSC_RXRDY		(1 <<  4)	/* Receive Ready */
+#define		AT91_SSC_OVRUN		(1 <<  5)	/* Receive Overrun */
+#define		AT91_SSC_ENDRX		(1 <<  6)	/* End of Reception */
+#define		AT91_SSC_RXBUFF		(1 <<  7)	/* Receive Buffer Full */
+#define		AT91_SSC_TXSYN		(1 << 10)	/* Transmit Sync */
+#define		AT91_SSC_RXSYN		(1 << 11)	/* Receive Sync */
+#define		AT91_SSC_TXENA		(1 << 16)	/* Transmit Enable */
+#define		AT91_SSC_RXENA		(1 << 17)	/* Receive Enable */
+
+#define AT91_SSC_IER		0x44	/* Interrupt Enable Register */
+#define AT91_SSC_IDR		0x48	/* Interrupt Disable Register */
+#define AT91_SSC_IMR		0x4c	/* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
index 2910d35..0f4c12d 100644
--- a/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_sys.h
@@ -68,8 +68,17 @@
 #define AT91_DBGU_RHR		(AT91_DBGU + 0x18)	/* Receiver Holding Register */
 #define AT91_DBGU_THR		(AT91_DBGU + 0x1c)	/* Transmitter Holding Register */
 #define AT91_DBGU_BRGR		(AT91_DBGU + 0x20)	/* Baud Rate Generator Register */
+
 #define AT91_DBGU_CIDR		(AT91_DBGU + 0x40)	/* Chip ID Register */
 #define AT91_DBGU_EXID		(AT91_DBGU + 0x44)	/* Chip ID Extension Register */
+#define		AT91_CIDR_VERSION	(0x1f << 0)		/* Version of the Device */
+#define		AT91_CIDR_EPROC		(7    << 5)		/* Embedded Processor */
+#define		AT91_CIDR_NVPSIZ	(0xf  << 8)		/* Nonvolatile Program Memory Size */
+#define		AT91_CIDR_NVPSIZ2	(0xf  << 12)		/* Second Nonvolatile Program Memory Size */
+#define		AT91_CIDR_SRAMSIZ	(0xf  << 16)		/* Internal SRAM Size */
+#define		AT91_CIDR_ARCH		(0xff << 20)		/* Architecture Identifier */
+#define		AT91_CIDR_NVPTYP	(7    << 28)		/* Nonvolatile Program Memory Type */
+#define		AT91_CIDR_EXT		(1    << 31)		/* Extension Flag */
 
 
 /*
@@ -241,7 +250,7 @@
 #define		AT91_RTC_SEC		(0x7f <<  0)		/* Current Second */
 #define		AT91_RTC_MIN		(0x7f <<  8)		/* Current Minute */
 #define		AT91_RTC_HOUR 		(0x3f << 16)		/* Current Hour */
-#define		At91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */
+#define		AT91_RTC_AMPM		(1    << 22)		/* Ante Meridiem Post Meridiem Indicator */
 
 #define	AT91_RTC_CALR		(AT91_RTC + 0x0c)	/* Calendar Register */
 #define		AT91_RTC_CENT		(0x7f <<  0)		/* Current Century */
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h
new file mode 100644
index 0000000..f4da752
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h
@@ -0,0 +1,146 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_tc.h
+ *
+ * Copyright (C) SAN People
+ *
+ * Timer/Counter Unit (TC) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_TC_H
+#define AT91RM9200_TC_H
+
+#define AT91_TC_BCR		0xc0		/* TC Block Control Register */
+#define		AT91_TC_SYNC		(1 << 0)	/* Synchro Command */
+
+#define AT91_TC_BMR		0xc4		/* TC Block Mode Register */
+#define		AT91_TC_TC0XC0S		(3 << 0)	/* External Clock Signal 0 Selection */
+#define			AT91_TC_TC0XC0S_TCLK0		(0 << 0)
+#define			AT91_TC_TC0XC0S_NONE		(1 << 0)
+#define			AT91_TC_TC0XC0S_TIOA1		(2 << 0)
+#define			AT91_TC_TC0XC0S_TIOA2		(3 << 0)
+#define		AT91_TC_TC1XC1S		(3 << 2)	/* External Clock Signal 1 Selection */
+#define			AT91_TC_TC1XC1S_TCLK1		(0 << 2)
+#define			AT91_TC_TC1XC1S_NONE		(1 << 2)
+#define			AT91_TC_TC1XC1S_TIOA0		(2 << 2)
+#define			AT91_TC_TC1XC1S_TIOA2		(3 << 2)
+#define		AT91_TC_TC2XC2S		(3 << 4)	/* External Clock Signal 2 Selection */
+#define			AT91_TC_TC2XC2S_TCLK2		(0 << 4)
+#define			AT91_TC_TC2XC2S_NONE		(1 << 4)
+#define			AT91_TC_TC2XC2S_TIOA0		(2 << 4)
+#define			AT91_TC_TC2XC2S_TIOA1		(3 << 4)
+
+
+#define AT91_TC_CCR		0x00		/* Channel Control Register */
+#define		AT91_TC_CLKEN		(1 << 0)	/* Counter Clock Enable Command */
+#define		AT91_TC_CLKDIS		(1 << 1)	/* Counter CLock Disable Command */
+#define		AT91_TC_SWTRG		(1 << 2)	/* Software Trigger Command */
+
+#define AT91_TC_CMR		0x04		/* Channel Mode Register */
+#define		AT91_TC_TCCLKS		(7 << 0)	/* Capture/Waveform Mode: Clock Selection */
+#define			AT91_TC_TIMER_CLOCK1		(0 << 0)
+#define			AT91_TC_TIMER_CLOCK2		(1 << 0)
+#define			AT91_TC_TIMER_CLOCK3		(2 << 0)
+#define			AT91_TC_TIMER_CLOCK4		(3 << 0)
+#define			AT91_TC_TIMER_CLOCK5		(4 << 0)
+#define			AT91_TC_XC0			(5 << 0)
+#define			AT91_TC_XC1			(6 << 0)
+#define			AT91_TC_XC2			(7 << 0)
+#define		AT91_TC_CLKI		(1 << 3)	/* Capture/Waveform Mode: Clock Invert */
+#define		AT91_TC_BURST		(3 << 4)	/* Capture/Waveform Mode: Burst Signal Selection */
+#define		AT91_TC_LDBSTOP		(1 << 6)	/* Capture Mode: Counter Clock Stopped with TB Loading */
+#define		AT91_TC_LDBDIS		(1 << 7)	/* Capture Mode: Counter Clock Disable with RB Loading */
+#define		AT91_TC_ETRGEDG		(3 << 8)	/* Capture Mode: External Trigger Edge Selection */
+#define		AT91_TC_ABETRG		(1 << 10)	/* Capture Mode: TIOA or TIOB External Trigger Selection */
+#define		AT91_TC_CPCTRG		(1 << 14)	/* Capture Mode: RC Compare Trigger Enable */
+#define		AT91_TC_WAVE		(1 << 15)	/* Capture/Waveform mode */
+#define		AT91_TC_LDRA		(3 << 16)	/* Capture Mode: RA Loading Selection */
+#define		AT91_TC_LDRB		(3 << 18)	/* Capture Mode: RB Loading Selection */
+
+#define		AT91_TC_CPCSTOP		(1 <<  6)	/* Waveform Mode: Counter Clock Stopped with RC Compare */
+#define		AT91_TC_CPCDIS		(1 <<  7)	/* Waveform Mode: Counter Clock Disable with RC Compare */
+#define		AT91_TC_EEVTEDG		(3 <<  8)	/* Waveform Mode: External Event Edge Selection */
+#define			AT91_TC_EEVTEDG_NONE		(0 << 8)
+#define			AT91_TC_EEVTEDG_RISING		(1 << 8)
+#define			AT91_TC_EEVTEDG_FALLING		(2 << 8)
+#define			AT91_TC_EEVTEDG_BOTH		(3 << 8)
+#define		AT91_TC_EEVT		(3 << 10)	/* Waveform Mode: External Event Selection */
+#define			AT91_TC_EEVT_TIOB		(0 << 10)
+#define			AT91_TC_EEVT_XC0		(1 << 10)
+#define			AT91_TC_EEVT_XC1		(2 << 10)
+#define			AT91_TC_EEVT_XC2		(3 << 10)
+#define		AT91_TC_ENETRG		(1 << 12)	/* Waveform Mode: External Event Trigger Enable */
+#define		AT91_TC_WAVESEL		(3 << 13)	/* Waveform Mode: Waveform Selection */
+#define			AT91_TC_WAVESEL_UP		(0 << 13)
+#define			AT91_TC_WAVESEL_UP_AUTO		(2 << 13)
+#define			AT91_TC_WAVESEL_UPDOWN		(1 << 13)
+#define			AT91_TC_WAVESEL_UPDOWN_AUTO	(3 << 13)
+#define		AT91_TC_ACPA		(3 << 16)	/* Waveform Mode: RA Compare Effect on TIOA */
+#define			AT91_TC_ACPA_NONE		(0 << 16)
+#define			AT91_TC_ACPA_SET		(1 << 16)
+#define			AT91_TC_ACPA_CLEAR		(2 << 16)
+#define			AT91_TC_ACPA_TOGGLE		(3 << 16)
+#define		AT91_TC_ACPC		(3 << 18)	/* Waveform Mode: RC Compre Effect on TIOA */
+#define			AT91_TC_ACPC_NONE		(0 << 18)
+#define			AT91_TC_ACPC_SET		(1 << 18)
+#define			AT91_TC_ACPC_CLEAR		(2 << 18)
+#define			AT91_TC_ACPC_TOGGLE		(3 << 18)
+#define		AT91_TC_AEEVT		(3 << 20)	/* Waveform Mode: External Event Effect on TIOA */
+#define			AT91_TC_AEEVT_NONE		(0 << 20)
+#define			AT91_TC_AEEVT_SET		(1 << 20)
+#define			AT91_TC_AEEVT_CLEAR		(2 << 20)
+#define			AT91_TC_AEEVT_TOGGLE		(3 << 20)
+#define		AT91_TC_ASWTRG		(3 << 22)	/* Waveform Mode: Software Trigger Effect on TIOA */
+#define			AT91_TC_ASWTRG_NONE		(0 << 22)
+#define			AT91_TC_ASWTRG_SET		(1 << 22)
+#define			AT91_TC_ASWTRG_CLEAR		(2 << 22)
+#define			AT91_TC_ASWTRG_TOGGLE		(3 << 22)
+#define		AT91_TC_BCPB		(3 << 24)	/* Waveform Mode: RB Compare Effect on TIOB */
+#define			AT91_TC_BCPB_NONE		(0 << 24)
+#define			AT91_TC_BCPB_SET		(1 << 24)
+#define			AT91_TC_BCPB_CLEAR		(2 << 24)
+#define			AT91_TC_BCPB_TOGGLE		(3 << 24)
+#define		AT91_TC_BCPC		(3 << 26)	/* Waveform Mode: RC Compare Effect on TIOB */
+#define			AT91_TC_BCPC_NONE		(0 << 26)
+#define			AT91_TC_BCPC_SET		(1 << 26)
+#define			AT91_TC_BCPC_CLEAR		(2 << 26)
+#define			AT91_TC_BCPC_TOGGLE		(3 << 26)
+#define		AT91_TC_BEEVT		(3 << 28)	/* Waveform Mode: External Event Effect on TIOB */
+#define			AT91_TC_BEEVT_NONE		(0 << 28)
+#define			AT91_TC_BEEVT_SET		(1 << 28)
+#define			AT91_TC_BEEVT_CLEAR		(2 << 28)
+#define			AT91_TC_BEEVT_TOGGLE		(3 << 28)
+#define		AT91_TC_BSWTRG		(3 << 30)	/* Waveform Mode: Software Trigger Effect on TIOB */
+#define			AT91_TC_BSWTRG_NONE		(0 << 30)
+#define			AT91_TC_BSWTRG_SET		(1 << 30)
+#define			AT91_TC_BSWTRG_CLEAR		(2 << 30)
+#define			AT91_TC_BSWTRG_TOGGLE		(3 << 30)
+
+#define AT91_TC_CV		0x10		/* Counter Value */
+#define AT91_TC_RA		0x14		/* Register A */
+#define AT91_TC_RB		0x18		/* Register B */
+#define AT91_TC_RC		0x1c		/* Register C */
+
+#define AT91_TC_SR		0x20		/* Status Register */
+#define		AT91_TC_COVFS		(1 <<  0)	/* Counter Overflow Status */
+#define		AT91_TC_LOVRS		(1 <<  1)	/* Load Overrun Status */
+#define		AT91_TC_CPAS		(1 <<  2)	/* RA Compare Status */
+#define		AT91_TC_CPBS		(1 <<  3)	/* RB Compare Status */
+#define		AT91_TC_CPCS		(1 <<  4)	/* RC Compare Status */
+#define		AT91_TC_LDRAS		(1 <<  5)	/* RA Loading Status */
+#define		AT91_TC_LDRBS		(1 <<  6)	/* RB Loading Status */
+#define		AT91_TC_ETRGS		(1 <<  7)	/* External Trigger Status */
+#define		AT91_TC_CLKSTA		(1 << 16)	/* Clock Enabling Status */
+#define		AT91_TC_MTIOA		(1 << 17)	/* TIOA Mirror */
+#define		AT91_TC_MTIOB		(1 << 18)	/* TIOB Mirror */
+
+#define AT91_TC_IER		0x24		/* Interrupt Enable Register */
+#define AT91_TC_IDR		0x28		/* Interrupt Disable Register */
+#define AT91_TC_IMR		0x2c		/* Interrupt Mask Register */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h
new file mode 100644
index 0000000..951e3f6
--- /dev/null
+++ b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h
@@ -0,0 +1,77 @@
+/*
+ * include/asm-arm/arch-at91rm9200/at91rm9200_udp.h
+ *
+ * Copyright (C) 2005 Ivan Kokshaysky
+ * Copyright (C) SAN People
+ *
+ * USB Device Port (UDP) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91RM9200_UDP_H
+#define AT91RM9200_UDP_H
+
+#define AT91_UDP_FRM_NUM	0x00		/* Frame Number Register */
+#define		AT91_UDP_NUM		(0x7ff <<  0)		/* Frame Number */
+#define		AT91_UDP_FRM_ERR	(1     << 16)		/* Frame Error */
+#define		AT91_UDP_FRM_OK		(1     << 17)		/* Frame OK */
+
+#define AT91_UDP_GLB_STAT	0x04		/* Global State Register */
+#define		AT91_UDP_FADDEN		(1 <<  0)		/* Function Address Enable */
+#define		AT91_UDP_CONFG		(1 <<  1)		/* Configured */
+#define		AT91_UDP_ESR		(1 <<  2)		/* Enable Send Resume */
+#define		AT91_UDP_RSMINPR	(1 <<  3)		/* Resume has been sent */
+#define		AT91_UDP_RMWUPE		(1 <<  4)		/* Remote Wake Up Enable */
+
+#define AT91_UDP_FADDR		0x08		/* Function Address Register */
+#define		AT91_UDP_FADD		(0x7f << 0)		/* Function Address Value */
+#define		AT91_UDP_FEN		(1    << 8)		/* Function Enable */
+
+#define AT91_UDP_IER		0x10		/* Interrupt Enable Register */
+#define AT91_UDP_IDR		0x14		/* Interrupt Disable Register */
+#define AT91_UDP_IMR		0x18		/* Interrupt Mask Register */
+
+#define AT91_UDP_ISR		0x1c		/* Interrupt Status Register */
+#define		AT91_UDP_EP(n)		(1 << (n))		/* Endpoint Interrupt Status */
+#define		AT91_UDP_RXSUSP		(1 <<  8)		/* USB Suspend Interrupt Status */
+#define		AT91_UDP_RXRSM		(1 <<  9)		/* USB Resume Interrupt Status */
+#define		AT91_UDP_EXTRSM		(1 << 10)		/* External Resume Interrupt Status */
+#define		AT91_UDP_SOFINT		(1 << 11)		/* Start of Frame Interrupt Status */
+#define		AT91_UDP_ENDBUSRES	(1 << 12)		/* End of Bus Reset Interrpt Status */
+#define		AT91_UDP_WAKEUP		(1 << 13)		/* USB Wakeup Interrupt Status */
+
+#define AT91_UDP_ICR		0x20		/* Interrupt Clear Register */
+#define AT91_UDP_RST_EP		0x28		/* Reset Endpoint Register */
+
+#define AT91_UDP_CSR(n)		(0x30 + ((n) * 4))	/* Endpoint Control/Status Registers 0-7 */
+#define		AT91_UDP_TXCOMP		(1 <<  0)		/* Generates IN packet with data previously written in DPR */
+#define		AT91_UDP_RX_DATA_BK0	(1 <<  1)		/* Receive Data Bank 0 */
+#define		AT91_UDP_RXSETUP	(1 <<  2)		/* Send STALL to the host */
+#define		AT91_UDP_STALLSENT	(1 <<  3)		/* Stall Sent / Isochronous error (Isochronous endpoints) */
+#define		AT91_UDP_TXPKTRDY	(1 <<  4)		/* Transmit Packet Ready */
+#define		AT91_UDP_FORCESTALL	(1 <<  5)		/* Force Stall */
+#define		AT91_UDP_RX_DATA_BK1	(1 <<  6)		/* Receive Data Bank 1 */
+#define		AT91_UDP_DIR		(1 <<  7)		/* Transfer Direction */
+#define		AT91_UDP_EPTYPE		(7 <<  8)		/* Endpoint Type */
+#define			AT91_UDP_EPTYPE_CTRL		(0 <<  8)
+#define			AT91_UDP_EPTYPE_ISO_OUT		(1 <<  8)
+#define			AT91_UDP_EPTYPE_BULK_OUT	(2 <<  8)
+#define			AT91_UDP_EPTYPE_INT_OUT		(3 <<  8)
+#define			AT91_UDP_EPTYPE_ISO_IN		(5 <<  8)
+#define			AT91_UDP_EPTYPE_BULK_IN		(6 <<  8)
+#define			AT91_UDP_EPTYPE_INT_IN		(7 <<  8)
+#define		AT91_UDP_DTGLE		(1 << 11)		/* Data Toggle */
+#define		AT91_UDP_EPEDS		(1 << 15)		/* Endpoint Enable/Disable */
+#define		AT91_UDP_RXBYTECNT	(0x7ff << 16)		/* Number of bytes in FIFO */
+
+#define AT91_UDP_FDR(n)		(0x50 + ((n) * 4))	/* Endpoint FIFO Data Registers 0-7 */
+
+#define AT91_UDP_TXVC		0x74		/* Transceiver Control Register */
+#define		AT91_UDP_TXVC_TXVDIS	(1 << 8)		/* Transceiver Disable */
+
+#endif
diff --git a/include/asm-arm/arch-at91rm9200/board.h b/include/asm-arm/arch-at91rm9200/board.h
index 4fdef13..1fdd70b2 100644
--- a/include/asm-arm/arch-at91rm9200/board.h
+++ b/include/asm-arm/arch-at91rm9200/board.h
@@ -31,14 +31,9 @@
 #ifndef __ASM_ARCH_BOARD_H
 #define __ASM_ARCH_BOARD_H
 
- /* Clocks */
-extern unsigned long at91_master_clock;
-
- /* Serial Port */
-extern int at91_serial_map[AT91_NR_UART];
-extern int at91_console_port;
-
 #include <linux/mtd/partitions.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
 
  /* USB Device */
 struct at91_udc_data {
@@ -91,10 +86,25 @@
 extern void __init at91_add_device_nand(struct at91_nand_data *data);
 
  /* I2C*/
-void __init at91_add_device_i2c(void);
+extern void __init at91_add_device_i2c(void);
 
- /* RTC */
-void __init at91_add_device_rtc(void);
+ /* SPI */
+extern void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices);
+
+ /* Serial */
+struct at91_uart_config {
+	unsigned short	console_tty;	/* tty number of serial console */
+	unsigned short	nr_tty;		/* number of serial tty's */
+	short		tty_map[];	/* map UART to tty number */
+};
+extern struct platform_device *at91_default_console_device;
+extern void __init at91_init_serial(struct at91_uart_config *config);
+
+struct at91_uart_data {
+	short		use_dma_tx;	/* use transmit DMA? */
+	short		use_dma_rx;	/* use receive DMA? */
+};
+extern void __init at91_add_device_serial(void);
 
  /* LEDs */
 extern u8 at91_leds_cpu;
diff --git a/include/asm-arm/arch-at91rm9200/gpio.h b/include/asm-arm/arch-at91rm9200/gpio.h
index 6176ab2..dbde1ba 100644
--- a/include/asm-arm/arch-at91rm9200/gpio.h
+++ b/include/asm-arm/arch-at91rm9200/gpio.h
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_AT91RM9200_GPIO_H
 #define __ASM_ARCH_AT91RM9200_GPIO_H
 
+#include <asm/irq.h>
+
 #define PIN_BASE		NR_AIC_IRQS
 
 #define PQFP_GPIO_BANKS		3	/* PQFP package has 3 banks */
@@ -188,6 +190,9 @@
 /* callable at any time */
 extern int at91_set_gpio_value(unsigned pin, int value);
 extern int at91_get_gpio_value(unsigned pin);
+
+extern void at91_gpio_suspend(void);
+extern void at91_gpio_resume(void);
 #endif
 
 #endif
diff --git a/include/asm-arm/arch-at91rm9200/hardware.h b/include/asm-arm/arch-at91rm9200/hardware.h
index 59e6f44..235d39d 100644
--- a/include/asm-arm/arch-at91rm9200/hardware.h
+++ b/include/asm-arm/arch-at91rm9200/hardware.h
@@ -50,9 +50,12 @@
 #define AT91_VA_BASE_TCB0	AT91_IO_P2V(AT91_BASE_TCB0)
 
 /* Internal SRAM */
-#define AT91_BASE_SRAM		0x00200000	/* Internal SRAM base address */
+#define AT91_SRAM_BASE		0x00200000	/* Internal SRAM base address */
 #define AT91_SRAM_SIZE		0x00004000	/* Internal SRAM SIZE (16Kb) */
 
+ /* Internal SRAM is mapped below the IO devices */
+#define AT91_SRAM_VIRT_BASE	(AT91_IO_VIRT_BASE - AT91_SRAM_SIZE)
+
 /* Serial ports */
 #define AT91_NR_UART		5		/* 4 USART3's and one DBGU port */
 
@@ -81,14 +84,14 @@
 {
 	void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
 
-	return readl(addr + reg_offset);
+	return __raw_readl(addr + reg_offset);
 }
 
 static inline void at91_sys_write(unsigned int reg_offset, unsigned long value)
 {
 	void __iomem *addr = (void __iomem *)AT91_VA_BASE_SYS;
 
-	writel(value, addr + reg_offset);
+	__raw_writel(value, addr + reg_offset);
 }
 #endif
 
diff --git a/include/asm-arm/arch-at91rm9200/io.h b/include/asm-arm/arch-at91rm9200/io.h
index 23e670d..88fd1be 100644
--- a/include/asm-arm/arch-at91rm9200/io.h
+++ b/include/asm-arm/arch-at91rm9200/io.h
@@ -21,7 +21,6 @@
 #ifndef __ASM_ARCH_IO_H
 #define __ASM_ARCH_IO_H
 
-#include <asm/arch/at91rm9200.h>
 #include <asm/io.h>
 
 #define IO_SPACE_LIMIT		0xFFFFFFFF
diff --git a/include/asm-arm/arch-at91rm9200/irqs.h b/include/asm-arm/arch-at91rm9200/irqs.h
index 27b0497..2dc93b1 100644
--- a/include/asm-arm/arch-at91rm9200/irqs.h
+++ b/include/asm-arm/arch-at91rm9200/irqs.h
@@ -37,8 +37,6 @@
  * symbols in gpio.h for ones handled indirectly as GPIOs.
  * We make provision for 4 banks of GPIO.
  */
-#include <asm/arch/gpio.h>
-
 #define	NR_IRQS		(NR_AIC_IRQS + (4 * 32))
 
 
diff --git a/include/asm-arm/arch-at91rm9200/memory.h b/include/asm-arm/arch-at91rm9200/memory.h
index 462f1f0..3c327c4 100644
--- a/include/asm-arm/arch-at91rm9200/memory.h
+++ b/include/asm-arm/arch-at91rm9200/memory.h
@@ -21,7 +21,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 
 #define PHYS_OFFSET	(AT91_SDRAM_BASE)
 
diff --git a/include/asm-arm/arch-at91rm9200/pio.h b/include/asm-arm/arch-at91rm9200/pio.h
deleted file mode 100644
index a89501b..0000000
--- a/include/asm-arm/arch-at91rm9200/pio.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * include/asm-arm/arch-at91rm9200/pio.h
- *
- *  Copyright (C) 2003 SAN People
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- */
-
-#ifndef __ASM_ARCH_PIO_H
-#define __ASM_ARCH_PIO_H
-
-#include <asm/arch/hardware.h>
-
-static inline void AT91_CfgPIO_USART0(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA17_TXD0 | AT91_PA18_RXD0 | AT91_PA20_CTS0);
-
-	/*
-	 * Errata #39 - RTS0 is not internally connected to PA21.  We need to drive
-	 *  the pin manually.  Default is off (RTS is active low).
-	 */
-	at91_sys_write(AT91_PIOA + PIO_PER, AT91_PA21_RTS0);
-	at91_sys_write(AT91_PIOA + PIO_OER, AT91_PA21_RTS0);
-	at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0);
-}
-
-static inline void AT91_CfgPIO_USART1(void) {
-	at91_sys_write(AT91_PIOB + PIO_PDR, AT91_PB18_RI1 | AT91_PB19_DTR1
-			| AT91_PB20_TXD1 | AT91_PB21_RXD1 | AT91_PB23_DCD1
-			| AT91_PB24_CTS1 | AT91_PB25_DSR1 | AT91_PB26_RTS1);
-}
-
-static inline void AT91_CfgPIO_USART2(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA22_RXD2 | AT91_PA23_TXD2);
-}
-
-static inline void AT91_CfgPIO_USART3(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_TXD3 | AT91_PA6_RXD3);
-	at91_sys_write(AT91_PIOA + PIO_BSR, AT91_PA5_TXD3 | AT91_PA6_RXD3);
-}
-
-static inline void AT91_CfgPIO_DBGU(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA31_DTXD | AT91_PA30_DRXD);
-}
-
-/*
- * Enable the Two-Wire interface.
- */
-static inline void AT91_CfgPIO_TWI(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA25_TWD | AT91_PA26_TWCK);
-	at91_sys_write(AT91_PIOA + PIO_ASR, AT91_PA25_TWD | AT91_PA26_TWCK);
-	at91_sys_write(AT91_PIOA + PIO_MDER, AT91_PA25_TWD | AT91_PA26_TWCK);		/* open drain */
-}
-
-/*
- * Enable the Serial Peripheral Interface.
- */
-static inline void AT91_CfgPIO_SPI(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA0_MISO | AT91_PA1_MOSI | AT91_PA2_SPCK);
-}
-
-static inline void AT91_CfgPIO_SPI_CS0(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA3_NPCS0);
-}
-
-static inline void AT91_CfgPIO_SPI_CS1(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA4_NPCS1);
-}
-
-static inline void AT91_CfgPIO_SPI_CS2(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA5_NPCS2);
-}
-
-static inline void AT91_CfgPIO_SPI_CS3(void) {
-	at91_sys_write(AT91_PIOA + PIO_PDR, AT91_PA6_NPCS3);
-}
-
-/*
- * Select the DataFlash card.
- */
-static inline void AT91_CfgPIO_DataFlashCard(void) {
-	at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(7));
-	at91_sys_write(AT91_PIOB + PIO_OER, AT91_PIO_P(7));
-	at91_sys_write(AT91_PIOB + PIO_CODR, AT91_PIO_P(7));
-}
-
-/*
- * Enable NAND Flash (SmartMedia) interface.
- */
-static inline void AT91_CfgPIO_SmartMedia(void) {
-	/* enable PC0=SMCE, PC1=SMOE, PC3=SMWE, A21=CLE, A22=ALE */
-	at91_sys_write(AT91_PIOC + PIO_ASR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE);
-	at91_sys_write(AT91_PIOC + PIO_PDR, AT91_PC0_BFCK | AT91_PC1_BFRDY_SMOE | AT91_PC3_BFBAA_SMWE);
-
-	/* Configure PC2 as input (signal READY of the SmartMedia) */
-	at91_sys_write(AT91_PIOC + PIO_PER, AT91_PC2_BFAVD);	/* enable direct output enable */
-	at91_sys_write(AT91_PIOC + PIO_ODR, AT91_PC2_BFAVD);	/* disable output */
-
-	/* Configure PB1 as input (signal Card Detect of the SmartMedia) */
-	at91_sys_write(AT91_PIOB + PIO_PER, AT91_PIO_P(1));	/* enable direct output enable */
-	at91_sys_write(AT91_PIOB + PIO_ODR, AT91_PIO_P(1));	/* disable output */
-}
-
-static inline int AT91_PIO_SmartMedia_RDY(void) {
-	return (at91_sys_read(AT91_PIOC + PIO_PDSR) & AT91_PIO_P(2)) ? 1 : 0;
-}
-
-static inline int AT91_PIO_SmartMedia_CardDetect(void) {
-	return (at91_sys_read(AT91_PIOB + PIO_PDSR) & AT91_PIO_P(1)) ? 1 : 0;
-}
-
-#endif
diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h
index 29c4265..8a2ff47 100644
--- a/include/asm-arm/arch-at91rm9200/system.h
+++ b/include/asm-arm/arch-at91rm9200/system.h
@@ -21,7 +21,7 @@
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 
 static inline void arch_idle(void)
 {
@@ -48,4 +48,12 @@
 	at91_sys_write(AT91_ST_CR, AT91_ST_WDRST);
 }
 
+#define ARCH_ID_AT91RM9200	0x09200080
+#define ARCH_ID_AT91SAM9261	0x019000a0
+
+static inline unsigned long arch_identify(void)
+{
+	return at91_sys_read(AT91_DBGU_CIDR) & (AT91_CIDR_EPROC | AT91_CIDR_ARCH);
+}
+
 #endif
diff --git a/include/asm-arm/arch-at91rm9200/timex.h b/include/asm-arm/arch-at91rm9200/timex.h
index 3f112dd..88687ce 100644
--- a/include/asm-arm/arch-at91rm9200/timex.h
+++ b/include/asm-arm/arch-at91rm9200/timex.h
@@ -21,7 +21,7 @@
 #ifndef __ASM_ARCH_TIMEX_H
 #define __ASM_ARCH_TIMEX_H
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 
 #define CLOCK_TICK_RATE		(AT91_SLOW_CLOCK)
 
diff --git a/include/asm-arm/arch-at91rm9200/uncompress.h b/include/asm-arm/arch-at91rm9200/uncompress.h
index 7b38497..ec7811a 100644
--- a/include/asm-arm/arch-at91rm9200/uncompress.h
+++ b/include/asm-arm/arch-at91rm9200/uncompress.h
@@ -21,7 +21,7 @@
 #ifndef __ASM_ARCH_UNCOMPRESS_H
 #define __ASM_ARCH_UNCOMPRESS_H
 
-#include <asm/arch/hardware.h>
+#include <asm/hardware.h>
 
 /*
  * The following code assumes the serial port has already been
diff --git a/include/asm-arm/arch-at91rm9200/vmalloc.h b/include/asm-arm/arch-at91rm9200/vmalloc.h
index 34d9718..4c367eb 100644
--- a/include/asm-arm/arch-at91rm9200/vmalloc.h
+++ b/include/asm-arm/arch-at91rm9200/vmalloc.h
@@ -21,6 +21,6 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
-#define VMALLOC_END		(AT91_IO_VIRT_BASE & PGDIR_MASK)
+#define VMALLOC_END		(AT91_SRAM_VIRT_BASE & PGDIR_MASK)
 
 #endif
diff --git a/include/asm-arm/arch-cl7500/acornfb.h b/include/asm-arm/arch-cl7500/acornfb.h
index 3867231..aea6330 100644
--- a/include/asm-arm/arch-cl7500/acornfb.h
+++ b/include/asm-arm/arch-cl7500/acornfb.h
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 #define acornfb_valid_pixrate(var) (var->pixclock >= 39325 && var->pixclock <= 40119)
 
 static inline void
diff --git a/include/asm-arm/arch-clps711x/hardware.h b/include/asm-arm/arch-clps711x/hardware.h
index 1386871..0fdbe72 100644
--- a/include/asm-arm/arch-clps711x/hardware.h
+++ b/include/asm-arm/arch-clps711x/hardware.h
@@ -22,7 +22,6 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
 
 #define CLPS7111_VIRT_BASE	0xff000000
 #define CLPS7111_BASE		CLPS7111_VIRT_BASE
diff --git a/include/asm-arm/arch-clps711x/io.h b/include/asm-arm/arch-clps711x/io.h
index 62613b0..53d7902 100644
--- a/include/asm-arm/arch-clps711x/io.h
+++ b/include/asm-arm/arch-clps711x/io.h
@@ -26,7 +26,6 @@
 
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 /*
  * We don't support ins[lb]/outs[lb].  Make them fault.
diff --git a/include/asm-arm/arch-clps711x/memory.h b/include/asm-arm/arch-clps711x/memory.h
index 61d8717..c6e8dcf 100644
--- a/include/asm-arm/arch-clps711x/memory.h
+++ b/include/asm-arm/arch-clps711x/memory.h
@@ -20,7 +20,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 
 /*
  * Physical DRAM offset.
diff --git a/include/asm-arm/arch-clps711x/uncompress.h b/include/asm-arm/arch-clps711x/uncompress.h
index 07157b7..03d233a 100644
--- a/include/asm-arm/arch-clps711x/uncompress.h
+++ b/include/asm-arm/arch-clps711x/uncompress.h
@@ -17,7 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
 #include <asm/arch/io.h>
 #include <asm/hardware.h>
 #include <asm/hardware/clps7111.h>
diff --git a/include/asm-arm/arch-ebsa285/hardware.h b/include/asm-arm/arch-ebsa285/hardware.h
index ec51fe9..daad8ee 100644
--- a/include/asm-arm/arch-ebsa285/hardware.h
+++ b/include/asm-arm/arch-ebsa285/hardware.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
 #include <asm/arch/memory.h>
 
 #ifdef CONFIG_ARCH_FOOTBRIDGE
diff --git a/include/asm-arm/arch-ebsa285/io.h b/include/asm-arm/arch-ebsa285/io.h
index 776f9d3..f9c7291 100644
--- a/include/asm-arm/arch-ebsa285/io.h
+++ b/include/asm-arm/arch-ebsa285/io.h
@@ -24,7 +24,6 @@
 #define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
 #if 1
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		((a) + PCIMEM_BASE)
 #else
 
 static inline void __iomem *___mem_pci(void __iomem *p)
@@ -34,14 +33,7 @@
 	return p;
 }
 
-static inline void __iomem *___mem_isa(void __iomem *p)
-{
-	unsigned long a = (unsigned long)p;
-	BUG_ON(a >= 16*1048576);
-	return p + PCIMEM_BASE;
-}
 #define __mem_pci(a)		___mem_pci(a)
-#define __mem_isa(a)		___mem_isa(a)
 #endif
 
 #endif
diff --git a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h
index 99181ffc..cbd7ae6 100644
--- a/include/asm-arm/arch-ebsa285/memory.h
+++ b/include/asm-arm/arch-ebsa285/memory.h
@@ -19,7 +19,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_FOOTBRIDGE_ADDIN)
 /*
diff --git a/include/asm-arm/arch-ebsa285/vmalloc.h b/include/asm-arm/arch-ebsa285/vmalloc.h
index d1ca955..0259820 100644
--- a/include/asm-arm/arch-ebsa285/vmalloc.h
+++ b/include/asm-arm/arch-ebsa285/vmalloc.h
@@ -6,7 +6,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ARCH_FOOTBRIDGE
 #define VMALLOC_END       (PAGE_OFFSET + 0x30000000)
diff --git a/include/asm-arm/arch-ep93xx/ep93xx-regs.h b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
index 71cea0b..8c32297 100644
--- a/include/asm-arm/arch-ep93xx/ep93xx-regs.h
+++ b/include/asm-arm/arch-ep93xx/ep93xx-regs.h
@@ -115,6 +115,8 @@
 #define EP93XX_SYSCON_CLOCK_USH_EN	0x10000000
 #define EP93XX_SYSCON_HALT		EP93XX_SYSCON_REG(0x08)
 #define EP93XX_SYSCON_STANDBY		EP93XX_SYSCON_REG(0x0c)
+#define EP93XX_SYSCON_CLOCK_SET1	EP93XX_SYSCON_REG(0x20)
+#define EP93XX_SYSCON_CLOCK_SET2	EP93XX_SYSCON_REG(0x24)
 #define EP93XX_SYSCON_DEVICE_CONFIG	EP93XX_SYSCON_REG(0x80)
 #define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE	0x00800000
 #define EP93XX_SYSCON_SWLOCK		EP93XX_SYSCON_REG(0xc0)
diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
index df9cbb6..d7a34ce 100644
--- a/include/asm-arm/arch-ep93xx/platform.h
+++ b/include/asm-arm/arch-ep93xx/platform.h
@@ -8,6 +8,7 @@
 void ep93xx_init_irq(void);
 void ep93xx_init_time(unsigned long);
 void ep93xx_init_devices(void);
+void ep93xx_clock_init(void);
 extern struct sys_timer ep93xx_timer;
 
 
diff --git a/include/asm-arm/arch-imx/imx-dma.h b/include/asm-arm/arch-imx/imx-dma.h
index f2063c1..599f03e 100644
--- a/include/asm-arm/arch-imx/imx-dma.h
+++ b/include/asm-arm/arch-imx/imx-dma.h
@@ -46,7 +46,7 @@
 struct imx_dma_channel {
 	const char *name;
 	void (*irq_handler) (int, void *, struct pt_regs *);
-	void (*err_handler) (int, void *, struct pt_regs *);
+	void (*err_handler) (int, void *, struct pt_regs *, int errcode);
 	void *data;
 	dmamode_t  dma_mode;
 	struct scatterlist *sg;
@@ -58,6 +58,10 @@
 
 extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
 
+#define IMX_DMA_ERR_BURST     1
+#define IMX_DMA_ERR_REQUEST   2
+#define IMX_DMA_ERR_TRANSFER  4
+#define IMX_DMA_ERR_BUFFER    8
 
 /* The type to distinguish channel numbers parameter from ordinal int type */
 typedef int imx_dmach_t;
@@ -74,7 +78,7 @@
 int
 imx_dma_setup_handlers(imx_dmach_t dma_ch,
 		void (*irq_handler) (int, void *, struct pt_regs *),
-		void (*err_handler) (int, void *, struct pt_regs *), void *data);
+		void (*err_handler) (int, void *, struct pt_regs *, int), void *data);
 
 void imx_dma_enable(imx_dmach_t dma_ch);
 
diff --git a/include/asm-arm/arch-integrator/io.h b/include/asm-arm/arch-integrator/io.h
index 31f2dea..c8f2175 100644
--- a/include/asm-arm/arch-integrator/io.h
+++ b/include/asm-arm/arch-integrator/io.h
@@ -32,6 +32,5 @@
 
 #define __io(a)			((void __iomem *)(PCI_IO_VADDR + (a)))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		((a) + PCI_MEMORY_VADDR)
 
 #endif
diff --git a/include/asm-arm/arch-integrator/smp.h b/include/asm-arm/arch-integrator/smp.h
index da6981e..ab2c79b 100644
--- a/include/asm-arm/arch-integrator/smp.h
+++ b/include/asm-arm/arch-integrator/smp.h
@@ -1,7 +1,6 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-#include <linux/config.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
diff --git a/include/asm-arm/arch-iop3xx/io.h b/include/asm-arm/arch-iop3xx/io.h
index f39046a..36adbdf 100644
--- a/include/asm-arm/arch-iop3xx/io.h
+++ b/include/asm-arm/arch-iop3xx/io.h
@@ -17,6 +17,5 @@
 
 #define __io(p)			((void __iomem *)(p))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #endif
diff --git a/include/asm-arm/arch-iop3xx/memory.h b/include/asm-arm/arch-iop3xx/memory.h
index bc62f4b..e43ebd9 100644
--- a/include/asm-arm/arch-iop3xx/memory.h
+++ b/include/asm-arm/arch-iop3xx/memory.h
@@ -5,7 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 #include <asm/hardware.h>
 
 /*
diff --git a/include/asm-arm/arch-iop3xx/timex.h b/include/asm-arm/arch-iop3xx/timex.h
index 472badb..14ca8d0 100644
--- a/include/asm-arm/arch-iop3xx/timex.h
+++ b/include/asm-arm/arch-iop3xx/timex.h
@@ -3,7 +3,6 @@
  *
  * IOP3xx architecture timex specifications
  */
-#include <linux/config.h>
 #include <asm/hardware.h>
 
 #if defined(CONFIG_ARCH_IQ80321) || defined(CONFIG_ARCH_IQ31244)
diff --git a/include/asm-arm/arch-iop3xx/uncompress.h b/include/asm-arm/arch-iop3xx/uncompress.h
index c98eb62..fbdd5af 100644
--- a/include/asm-arm/arch-iop3xx/uncompress.h
+++ b/include/asm-arm/arch-iop3xx/uncompress.h
@@ -1,7 +1,6 @@
 /*
  *  linux/include/asm-arm/arch-iop3xx/uncompress.h
  */
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/mach-types.h>
 #include <linux/serial_reg.h>
diff --git a/include/asm-arm/arch-ixp23xx/entry-macro.S b/include/asm-arm/arch-ixp23xx/entry-macro.S
index 0ef4e60..8677616 100644
--- a/include/asm-arm/arch-ixp23xx/entry-macro.S
+++ b/include/asm-arm/arch-ixp23xx/entry-macro.S
@@ -8,7 +8,7 @@
 		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 		ldr	\irqnr, =(IXP23XX_INTC_VIRT + IXP23XX_INTR_IRQ_ENC_ST_OFFSET)
 		ldr	\irqnr, [\irqnr]	@ get interrupt number
-		cmp	\irqnr, #0x0		@ suprious interrupt ?
+		cmp	\irqnr, #0x0		@ spurious interrupt ?
 		movne	\irqnr, \irqnr, lsr #2	@ skip unwanted low order bits
 		subne	\irqnr, \irqnr, #1	@ convert to 0 based
 
diff --git a/include/asm-arm/arch-ixp23xx/ixp23xx.h b/include/asm-arm/arch-ixp23xx/ixp23xx.h
index e49e1ca..d0a7220 100644
--- a/include/asm-arm/arch-ixp23xx/ixp23xx.h
+++ b/include/asm-arm/arch-ixp23xx/ixp23xx.h
@@ -124,6 +124,7 @@
 
 #define IXP23XX_EXP_UNIT_FUSE		IXP23XX_EXP_CFG_REG(0x28)
 #define IXP23XX_EXP_MSF_MUX		IXP23XX_EXP_CFG_REG(0x30)
+#define IXP23XX_EXP_CFG_FUSE		IXP23XX_EXP_CFG_REG(0x34)
 
 #define IXP23XX_EXP_BUS_PHYS		0x90000000
 #define IXP23XX_EXP_BUS_WINDOW_SIZE	0x01000000
@@ -251,7 +252,7 @@
  * CAP CSRs.
  ****************************************************************************/
 #define IXP23XX_GLOBAL_REG(x)		((volatile unsigned long *)(IXP23XX_CAP_CSR_VIRT + 0x4a00 + (x)))
-#define IXP23XX_PROD_IDG		IXP23XX_GLOBAL_REG(0x00)
+#define IXP23XX_PRODUCT_ID		IXP23XX_GLOBAL_REG(0x00)
 #define IXP23XX_MISC_CONTROL		IXP23XX_GLOBAL_REG(0x04)
 #define IXP23XX_MSF_CLK_CNTRL		IXP23XX_GLOBAL_REG(0x08)
 #define IXP23XX_RESET0			IXP23XX_GLOBAL_REG(0x0c)
@@ -265,6 +266,8 @@
 #define IXP23XX_PCI_UNIT_RESET		(1 << 1)
 #define IXP23XX_XSCALE_RESET		(1 << 0)
 
+#define IXP23XX_UENGINE_CSR_VIRT_BASE	(IXP23XX_CAP_CSR_VIRT + 0x18000)
+
 
 /****************************************************************************
  * PCI CSRs.
diff --git a/include/asm-arm/arch-ixp23xx/platform.h b/include/asm-arm/arch-ixp23xx/platform.h
index e4d9906..19a73b3 100644
--- a/include/asm-arm/arch-ixp23xx/platform.h
+++ b/include/asm-arm/arch-ixp23xx/platform.h
@@ -14,6 +14,21 @@
 
 #ifndef __ASSEMBLY__
 
+extern inline unsigned long ixp2000_reg_read(volatile void *reg)
+{
+	return *((volatile unsigned long *)reg);
+}
+
+extern inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
+{
+	*((volatile unsigned long *)reg) = val;
+}
+
+extern inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val)
+{
+	*((volatile unsigned long *)reg) = val;
+}
+
 struct pci_sys_data;
 
 void ixp23xx_map_io(void);
diff --git a/include/asm-arm/arch-ixp4xx/dma.h b/include/asm-arm/arch-ixp4xx/dma.h
index b1a071e..789f7f5 100644
--- a/include/asm-arm/arch-ixp4xx/dma.h
+++ b/include/asm-arm/arch-ixp4xx/dma.h
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/pci.h>
 #include <asm/page.h>
diff --git a/include/asm-arm/arch-l7200/io.h b/include/asm-arm/arch-l7200/io.h
index cab8ad0..cd080d8 100644
--- a/include/asm-arm/arch-l7200/io.h
+++ b/include/asm-arm/arch-l7200/io.h
@@ -19,7 +19,6 @@
  */
 #define __io_pci(a)		((void __iomem *)(PCIO_BASE + (a)))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #define __ioaddr(p)             __io_pci(p)
 
diff --git a/include/asm-arm/arch-lh7a40x/clocks.h b/include/asm-arm/arch-lh7a40x/clocks.h
new file mode 100644
index 0000000..bee02fd
--- /dev/null
+++ b/include/asm-arm/arch-lh7a40x/clocks.h
@@ -0,0 +1,20 @@
+/* include/asm-arm/arch-lh7a40x/clocks.h
+ *
+ *  Copyright (C) 2004 Marc Singer
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  version 2 as published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/config.h>
+
+#ifndef __ASM_ARCH_CLOCKS_H
+#define __ASM_ARCH_CLOCKS_H
+
+unsigned int fclkfreq_get (void);
+unsigned int hclkfreq_get (void);
+unsigned int pclkfreq_get (void);
+
+#endif  /* _ASM_ARCH_CLOCKS_H */
diff --git a/include/asm-arm/arch-lh7a40x/constants.h b/include/asm-arm/arch-lh7a40x/constants.h
index 52c1cb9..51de96e 100644
--- a/include/asm-arm/arch-lh7a40x/constants.h
+++ b/include/asm-arm/arch-lh7a40x/constants.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_CONSTANTS_H
 #define __ASM_ARCH_CONSTANTS_H
 
-#include <linux/config.h>
 
 /* Addressing constants */
 
@@ -29,8 +28,7 @@
 
 #if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
 
-# define IOBARRIER_PHYS		0xc0000000 /* Start of SDRAM */
-/*# define IOBARRIER_PHYS		0x00000000 */ /* Start of flash */
+# define IOBARRIER_PHYS		0x10000000 /* Second bank, fastest timing */
 # define IOBARRIER_VIRT		0xf0000000
 # define IOBARRIER_SIZE		PAGE_SIZE
 
@@ -53,6 +51,9 @@
 # define CPLD08_PHYS		CPLDX_PHYS (0x08)
 # define CPLD08_VIRT		CPLDX_VIRT (0x08)
 # define CPLD08_SIZE		PAGE_SIZE
+# define CPLD0A_PHYS		CPLDX_PHYS (0x0a)
+# define CPLD0A_VIRT		CPLDX_VIRT (0x0a)
+# define CPLD0A_SIZE		PAGE_SIZE
 # define CPLD0C_PHYS		CPLDX_PHYS (0x0c)
 # define CPLD0C_VIRT		CPLDX_VIRT (0x0c)
 # define CPLD0C_SIZE		PAGE_SIZE
@@ -84,5 +85,7 @@
 #define	XTAL_IN			14745600	/* 14.7456 MHz crystal */
 #define PLL_CLOCK		(XTAL_IN * 21)	/* 309 MHz PLL clock */
 #define MAX_HCLK_KHZ		100000		/* HCLK max limit ~100MHz */
+#define HCLK			(99993600)
+//#define HCLK			(119808000)
 
 #endif /* __ASM_ARCH_CONSTANTS_H */
diff --git a/include/asm-arm/arch-lh7a40x/dma.h b/include/asm-arm/arch-lh7a40x/dma.h
index 15492e3..a8cbd14 100644
--- a/include/asm-arm/arch-lh7a40x/dma.h
+++ b/include/asm-arm/arch-lh7a40x/dma.h
@@ -1,9 +1,86 @@
 /* include/asm-arm/arch-lh7a40x/dma.h
  *
- *  Copyright (C) 2003 Coastal Environmental Systems
+ *  Copyright (C) 2005 Marc Singer
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  version 2 as published by the Free Software Foundation.
  *
  */
+
+typedef enum {
+	DMA_M2M0	= 0,
+	DMA_M2M1	= 1,
+	DMA_M2P0	= 2,	/* Tx */
+	DMA_M2P1	= 3,	/* Rx */
+	DMA_M2P2	= 4,	/* Tx */
+	DMA_M2P3	= 5,	/* Rx */
+	DMA_M2P4	= 6,	/* Tx - AC97 */
+	DMA_M2P5	= 7,	/* Rx - AC97 */
+	DMA_M2P6	= 8,	/* Tx */
+	DMA_M2P7	= 9,	/* Rx */
+} dma_device_t;
+
+#define DMA_LENGTH_MAX		((64*1024) - 4) /* bytes */
+
+#define DMAC_GCA		__REG(DMAC_PHYS + 0x2b80)
+#define DMAC_GIR		__REG(DMAC_PHYS + 0x2bc0)
+
+#define DMAC_GIR_MMI1		(1<<11)
+#define DMAC_GIR_MMI0		(1<<10)
+#define DMAC_GIR_MPI8		(1<<9)
+#define DMAC_GIR_MPI9		(1<<8)
+#define DMAC_GIR_MPI6		(1<<7)
+#define DMAC_GIR_MPI7		(1<<6)
+#define DMAC_GIR_MPI4		(1<<5)
+#define DMAC_GIR_MPI5		(1<<4)
+#define DMAC_GIR_MPI2		(1<<3)
+#define DMAC_GIR_MPI3		(1<<2)
+#define DMAC_GIR_MPI0		(1<<1)
+#define DMAC_GIR_MPI1		(1<<0)
+
+#define DMAC_M2P0		0x0000
+#define DMAC_M2P1		0x0040
+#define DMAC_M2P2		0x0080
+#define DMAC_M2P3		0x00c0
+#define DMAC_M2P4		0x0240
+#define DMAC_M2P5		0x0200
+#define DMAC_M2P6		0x02c0
+#define DMAC_M2P7		0x0280
+#define DMAC_M2P8		0x0340
+#define DMAC_M2P9		0x0300
+#define DMAC_M2M0		0x0100
+#define DMAC_M2M1		0x0140
+
+#define DMAC_P_PCONTROL(c)	__REG(DMAC_PHYS + (c) + 0x00)
+#define DMAC_P_PINTERRUPT(c)	__REG(DMAC_PHYS + (c) + 0x04)
+#define DMAC_P_PPALLOC(c)	__REG(DMAC_PHYS + (c) + 0x08)
+#define DMAC_P_PSTATUS(c)	__REG(DMAC_PHYS + (c) + 0x0c)
+#define DMAC_P_REMAIN(c)	__REG(DMAC_PHYS + (c) + 0x14)
+#define DMAC_P_MAXCNT0(c)	__REG(DMAC_PHYS + (c) + 0x20)
+#define DMAC_P_BASE0(c)		__REG(DMAC_PHYS + (c) + 0x24)
+#define DMAC_P_CURRENT0(c)	__REG(DMAC_PHYS + (c) + 0x28)
+#define DMAC_P_MAXCNT1(c)	__REG(DMAC_PHYS + (c) + 0x30)
+#define DMAC_P_BASE1(c)		__REG(DMAC_PHYS + (c) + 0x34)
+#define DMAC_P_CURRENT1(c)	__REG(DMAC_PHYS + (c) + 0x38)
+
+#define DMAC_PCONTROL_ENABLE	(1<<4)
+
+#define DMAC_PORT_USB		0
+#define DMAC_PORT_SDMMC		1
+#define DMAC_PORT_AC97_1	2
+#define DMAC_PORT_AC97_2	3
+#define DMAC_PORT_AC97_3	4
+#define DMAC_PORT_UART1		6
+#define DMAC_PORT_UART2		7
+#define DMAC_PORT_UART3		8
+
+#define DMAC_PSTATUS_CURRSTATE_SHIFT	4
+#define DMAC_PSTATUS_CURRSTATE_MASK	0x3
+
+#define DMAC_PSTATUS_NEXTBUF	 (1<<6)
+#define DMAC_PSTATUS_STALLRINT	 (1<<0)
+
+#define DMAC_INT_CHE		 (1<<3)
+#define DMAC_INT_NFB		 (1<<1)
+#define DMAC_INT_STALL		 (1<<0)
diff --git a/include/asm-arm/arch-lh7a40x/entry-macro.S b/include/asm-arm/arch-lh7a40x/entry-macro.S
index a2f67c0..9fc7f49 100644
--- a/include/asm-arm/arch-lh7a40x/entry-macro.S
+++ b/include/asm-arm/arch-lh7a40x/entry-macro.S
@@ -10,11 +10,73 @@
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
 
-# if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-#  error "LH7A400 and LH7A404 are mutually exclusive"
-# endif
+/* In order to allow there to be support for both of the processor
+   classes at the same time, we make a hack here that isn't very
+   pretty.  At startup, the link pointed to with the
+   branch_irq_lh7a400 symbol is replaced with a NOP when the CPU is
+   detected as a lh7a404.
 
-# if defined (CONFIG_ARCH_LH7A400)
+   *** FIXME: we should clean this up so that there is only one
+	      implementation for each CPU's design.
+
+*/
+
+#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+branch_irq_lh7a400: b 1000f
+
+@ Implementation of the LH7A404 get_irqnr_and_base.
+
+		mov	\irqnr, #0			@ VIC1 irq base
+		mov	\base, #io_p2v(0x80000000)	@ APB registers
+		add	\base, \base, #0x8000
+		ldr	\tmp, [\base, #0x0030]		@ VIC1_VECTADDR
+		tst	\tmp, #VA_VECTORED		@ Direct vectored
+		bne	1002f
+		tst	\tmp, #VA_VIC1DEFAULT		@ Default vectored VIC1
+		ldrne	\irqstat, [\base, #0]		@ VIC1_IRQSTATUS
+		bne	1001f
+		add	\base, \base, #(0xa000 - 0x8000)
+		ldr	\tmp, [\base, #0x0030]		@ VIC2_VECTADDR
+		tst	\tmp, #VA_VECTORED		@ Direct vectored
+		bne	1002f
+		ldr	\irqstat, [\base, #0]		@ VIC2_IRQSTATUS
+		mov	\irqnr, #32			@ VIC2 irq base
+
+1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
+		bcs	1008f				@ Bit set; irq found
+		add	\irqnr, \irqnr, #1
+		bne	1001b				@ Until no bits
+		b	1009f				@ Nothing?  Hmm.
+1002:		and	\irqnr, \tmp, #0x3f		@ Mask for valid bits
+1008:		movs	\irqstat, #1			@ Force !Z
+		str	\tmp, [\base, #0x0030]		@ Clear vector
+		b	1009f
+
+@ Implementation of the LH7A400 get_irqnr_and_base.
+
+1000:		mov	\irqnr, #0
+		mov	\base, #io_p2v(0x80000000)	@ APB registers
+		ldr	\irqstat, [\base, #0x500]	@ PIC INTSR
+
+1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
+		bcs	1008f				@ Bit set; irq found
+		add	\irqnr, \irqnr, #1
+		bne	1001b				@ Until no bits
+		b	1009f				@ Nothing?  Hmm.
+1008:		movs	\irqstat, #1			@ Force !Z
+
+1009:
+               .endm
+
+
+
+#elif defined (CONFIG_ARCH_LH7A400)
 		.macro	disable_fiq
 		.endm
 
diff --git a/include/asm-arm/arch-lh7a40x/hardware.h b/include/asm-arm/arch-lh7a40x/hardware.h
index aeb07c1..e9ff74f 100644
--- a/include/asm-arm/arch-lh7a40x/hardware.h
+++ b/include/asm-arm/arch-lh7a40x/hardware.h
@@ -13,6 +13,8 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
+#include <asm/sizes.h>		/* Added for the sake of amba-clcd driver */
+
 #define io_p2v(x) (0xf0000000 | (((x) & 0xfff00000) >> 4) | ((x) & 0x0000ffff))
 #define io_v2p(x) (             (((x) & 0x0fff0000) << 4) | ((x) & 0x0000ffff))
 
@@ -53,6 +55,8 @@
 
 #endif
 
+#define MASK_AND_SET(v,m,s)	(v) = ((v)&~(m))|(s)
+
 #include "registers.h"
 
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-lh7a40x/io.h b/include/asm-arm/arch-lh7a40x/io.h
index bbcd433..17bc94097 100644
--- a/include/asm-arm/arch-lh7a40x/io.h
+++ b/include/asm-arm/arch-lh7a40x/io.h
@@ -18,6 +18,5 @@
 /* No ISA or PCI bus on this machine. */
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #endif /* __ASM_ARCH_IO_H */
diff --git a/include/asm-arm/arch-lh7a40x/irqs.h b/include/asm-arm/arch-lh7a40x/irqs.h
index f91f3e5..afe8c7c 100644
--- a/include/asm-arm/arch-lh7a40x/irqs.h
+++ b/include/asm-arm/arch-lh7a40x/irqs.h
@@ -18,7 +18,6 @@
 #ifndef __ASM_ARCH_IRQS_H
 #define __ASM_ARCH_IRQS_H
 
-#include <linux/config.h>
 
 #define FIQ_START	80
 
@@ -154,9 +153,10 @@
 #if !defined (IRQ_GPIO0INTR)
 # define IRQ_GPIO0INTR	IRQ_GPIO0FIQ
 #endif
-#define IRQ_TICK 	IRQ_TINTR
+#define IRQ_TICK	IRQ_TINTR
 #define IRQ_PCC1_RDY	IRQ_GPIO6INTR	/* PCCard 1 ready */
 #define IRQ_PCC2_RDY	IRQ_GPIO7INTR	/* PCCard 2 ready */
+#define IRQ_USB		IRQ_USBINTR	/* USB device */
 
 #ifdef CONFIG_MACH_KEV7A400
 # define IRQ_TS		IRQ_GPIOFIQ	/* Touchscreen */
@@ -191,6 +191,10 @@
 # define IRQ_LPD7A400_TS	IRQ_LPD7A40X_CPLD + 1	/* Touch screen */
 #endif
 
+#if defined (CONFIG_MACH_LPD7A400)
+# define IRQ_TOUCH		IRQ_LPD7A400_TS
+#endif
+
 #define NR_IRQS		(NR_IRQ_CPU + NR_IRQ_BOARD)
 
 #endif
diff --git a/include/asm-arm/arch-lh7a40x/registers.h b/include/asm-arm/arch-lh7a40x/registers.h
index 2edb22e..b4f09b3 100644
--- a/include/asm-arm/arch-lh7a40x/registers.h
+++ b/include/asm-arm/arch-lh7a40x/registers.h
@@ -9,7 +9,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <asm/arch/constants.h>
 
 #ifndef __ASM_ARCH_REGISTERS_H
@@ -18,7 +17,7 @@
 
 	/* Physical register base addresses */
 
-#define AC97_PHYS	(0x80000000)	/* AC97 Controller */
+#define AC97C_PHYS	(0x80000000)	/* AC97 Controller */
 #define MMC_PHYS	(0x80000100)	/* Multimedia Card Controller */
 #define USB_PHYS	(0x80000200)	/* USB Client */
 #define SCI_PHYS	(0x80000300)	/* Secure Card Interface */
@@ -35,6 +34,8 @@
 #define RTC_PHYS	(0x80000d00)	/* Real-time Clock */
 #define GPIO_PHYS	(0x80000e00)	/* General Purpose IO */
 #define BMI_PHYS	(0x80000f00)	/* Battery Monitor Interface */
+#define HRTFTC_PHYS	(0x80001000)	/* High-res TFT Controller (LH7A400) */
+#define ALI_PHYS	(0x80001000)	/* Advanced LCD Interface (LH7A404) */
 #define WDT_PHYS	(0x80001400)	/* Watchdog Timer */
 #define SMC_PHYS	(0x80002000)	/* Static Memory Controller */
 #define SDRC_PHYS	(0x80002400)	/* SDRAM Controller */
@@ -43,6 +44,7 @@
 
 	/* Physical registers of the LH7A404 */
 
+#define ADC_PHYS	(0x80001300)	/* A/D & Touchscreen Controller */
 #define VIC1_PHYS	(0x80008000)	/* Vectored Interrupt Controller 1 */
 #define USBH_PHYS	(0x80009000)	/* USB OHCI host controller */
 #define VIC2_PHYS	(0x8000a000)	/* Vectored Interrupt Controller 2 */
@@ -53,10 +55,32 @@
 
 	/* Clock/State Controller register */
 
+#define CSC_PWRSR	__REG(CSC_PHYS + 0x00) /* Reset register & ID */
 #define CSC_PWRCNT	__REG(CSC_PHYS + 0x04) /* Power control */
+#define CSC_CLKSET	__REG(CSC_PHYS + 0x20) /* Clock speed control */
+#define CSC_USBDRESET	__REG(CSC_PHYS + 0x4c) /* USB Device resets */
 
 #define CSC_PWRCNT_USBH_EN	(1<<28)	/* USB Host power enable */
+#define CSC_PWRCNT_DMAC_M2M1_EN	(1<<27)
+#define CSC_PWRCNT_DMAC_M2M0_EN	(1<<26)
+#define CSC_PWRCNT_DMAC_M2P8_EN	(1<<25)
+#define CSC_PWRCNT_DMAC_M2P9_EN	(1<<24)
+#define CSC_PWRCNT_DMAC_M2P6_EN	(1<<23)
+#define CSC_PWRCNT_DMAC_M2P7_EN	(1<<22)
+#define CSC_PWRCNT_DMAC_M2P4_EN	(1<<21)
+#define CSC_PWRCNT_DMAC_M2P5_EN	(1<<20)
+#define CSC_PWRCNT_DMAC_M2P2_EN	(1<<19)
+#define CSC_PWRCNT_DMAC_M2P3_EN	(1<<18)
+#define CSC_PWRCNT_DMAC_M2P0_EN	(1<<17)
+#define CSC_PWRCNT_DMAC_M2P1_EN	(1<<16)
 
+#define CSC_PWRSR_CHIPMAN_SHIFT	(24)
+#define CSC_PWRSR_CHIPMAN_MASK	(0xff)
+#define CSC_PWRSR_CHIPID_SHIFT	(16)
+#define CSC_PWRSR_CHIPID_MASK	(0xff)
+
+#define CSC_USBDRESET_APBRESETREG	(1<<1)
+#define CSC_USBDRESET_IORESETREG	(1<<0)
 
 	/* Interrupt Controller registers */
 
@@ -109,6 +133,13 @@
 #define GPIO_GPIOFEOI	__REG(GPIO_PHYS + 0x54)	/* GPIO End-of-Interrupt */
 #define GPIO_GPIOINTEN	__REG(GPIO_PHYS + 0x58)	/* GPIO Interrupt Enable */
 #define GPIO_INTSTATUS	__REG(GPIO_PHYS + 0x5c)	/* GPIO Interrupt Status */
+#define GPIO_PINMUX	__REG(GPIO_PHYS + 0x2c)
+#define GPIO_PADD	__REG(GPIO_PHYS + 0x10)
+#define GPIO_PAD	__REG(GPIO_PHYS + 0x00)
+#define GPIO_PCD	__REG(GPIO_PHYS + 0x08)
+#define GPIO_PCDD	__REG(GPIO_PHYS + 0x18)
+#define GPIO_PEDD	__REG(GPIO_PHYS + 0x24)
+#define GPIO_PED	__REG(GPIO_PHYS + 0x20)
 
 
 	/* Static Memory Controller registers */
@@ -138,20 +169,21 @@
 #endif
 
 #if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-# define CPLD_CONTROL		__REG8(CPLD02_PHYS)
-# define CPLD_SPI_DATA		__REG8(CPLD06_PHYS)
-# define CPLD_SPI_CONTROL	__REG8(CPLD08_PHYS)
-# define CPLD_SPI_EEPROM	__REG8(CPLD0A_PHYS)
-# define CPLD_INTERRUPTS	__REG8(CPLD0C_PHYS) /* IRQ mask/status */
-# define CPLD_BOOT_MODE		__REG8(CPLD0E_PHYS)
-# define CPLD_FLASH		__REG8(CPLD10_PHYS)
-# define CPLD_POWER_MGMT	__REG8(CPLD12_PHYS)
-# define CPLD_REVISION		__REG8(CPLD14_PHYS)
-# define CPLD_GPIO_EXT		__REG8(CPLD16_PHYS)
-# define CPLD_GPIO_DATA		__REG8(CPLD18_PHYS)
-# define CPLD_GPIO_DIR		__REG8(CPLD1A_PHYS)
-#endif
 
+# define CPLD_CONTROL		__REG16(CPLD02_PHYS)
+# define CPLD_SPI_DATA		__REG16(CPLD06_PHYS)
+# define CPLD_SPI_CONTROL	__REG16(CPLD08_PHYS)
+# define CPLD_SPI_EEPROM	__REG16(CPLD0A_PHYS)
+# define CPLD_INTERRUPTS	__REG16(CPLD0C_PHYS) /* IRQ mask/status */
+# define CPLD_BOOT_MODE		__REG16(CPLD0E_PHYS)
+# define CPLD_FLASH		__REG16(CPLD10_PHYS)
+# define CPLD_POWER_MGMT	__REG16(CPLD12_PHYS)
+# define CPLD_REVISION		__REG16(CPLD14_PHYS)
+# define CPLD_GPIO_EXT		__REG16(CPLD16_PHYS)
+# define CPLD_GPIO_DATA		__REG16(CPLD18_PHYS)
+# define CPLD_GPIO_DIR		__REG16(CPLD1A_PHYS)
+
+#endif
 
 	/* Timer registers */
 
@@ -190,4 +222,3 @@
 
 
 #endif  /* _ASM_ARCH_REGISTERS_H */
-
diff --git a/include/asm-arm/arch-lh7a40x/ssp.h b/include/asm-arm/arch-lh7a40x/ssp.h
new file mode 100644
index 0000000..132b1c4d
--- /dev/null
+++ b/include/asm-arm/arch-lh7a40x/ssp.h
@@ -0,0 +1,71 @@
+/* ssp.h
+     $Id$
+
+   written by Marc Singer
+   6 Dec 2004
+
+   Copyright (C) 2004 Marc Singer
+
+   -----------
+   DESCRIPTION
+   -----------
+
+   This SSP header is available throughout the kernel, for this
+   machine/architecture, because drivers that use it may be dispersed.
+
+   This file was cloned from the 7952x implementation.  It would be
+   better to share them, but we're taking an easier approach for the
+   time being.
+
+*/
+
+#if !defined (__SSP_H__)
+#    define   __SSP_H__
+
+/* ----- Includes */
+
+/* ----- Types */
+
+struct ssp_driver {
+	int  (*init)		(void);
+	void (*exit)		(void);
+	void (*acquire)		(void);
+	void (*release)		(void);
+	int  (*configure)	(int device, int mode, int speed,
+				 int frame_size_write, int frame_size_read);
+	void (*chip_select)	(int enable);
+	void (*set_callbacks)   (void* handle,
+				 irqreturn_t (*callback_tx)(void*),
+				 irqreturn_t (*callback_rx)(void*));
+	void (*enable)		(void);
+	void (*disable)		(void);
+//	int  (*save_state)	(void*);
+//	void (*restore_state)	(void*);
+	int  (*read)		(void);
+	int  (*write)		(u16 data);
+	int  (*write_read)	(u16 data);
+	void (*flush)		(void);
+	void (*write_async)	(void* pv, size_t cb);
+	size_t (*write_pos)	(void);
+};
+
+	/* These modes are only available on the LH79524 */
+#define SSP_MODE_SPI		(1)
+#define SSP_MODE_SSI		(2)
+#define SSP_MODE_MICROWIRE	(3)
+#define SSP_MODE_I2S		(4)
+
+	/* CPLD SPI devices */
+#define DEVICE_EEPROM	0	/* Configuration eeprom */
+#define DEVICE_MAC	1	/* MAC eeprom (LPD79524) */
+#define DEVICE_CODEC	2	/* Audio codec */
+#define DEVICE_TOUCH	3	/* Touch screen (LPD79520) */
+
+/* ----- Globals */
+
+/* ----- Prototypes */
+
+//extern struct ssp_driver lh79520_i2s_driver;
+extern struct ssp_driver lh7a400_cpld_ssp_driver;
+
+#endif  /* __SSP_H__ */
diff --git a/include/asm-arm/arch-lh7a40x/uncompress.h b/include/asm-arm/arch-lh7a40x/uncompress.h
index f805334..3d1ce04 100644
--- a/include/asm-arm/arch-lh7a40x/uncompress.h
+++ b/include/asm-arm/arch-lh7a40x/uncompress.h
@@ -16,7 +16,7 @@
 #ifndef UART_R_STATUS
 # define UART_R_STATUS	(0x10)
 #endif
-#define nTxRdy  	(0x20)	/* Not TxReady (literally Tx FIFO full) */
+#define nTxRdy		(0x20)	/* Not TxReady (literally Tx FIFO full) */
 
 	/* Access UART with physical addresses before MMU is setup */
 #define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS))
diff --git a/include/asm-arm/arch-netx/debug-macro.S b/include/asm-arm/arch-netx/debug-macro.S
new file mode 100644
index 0000000..a940d0e
--- /dev/null
+++ b/include/asm-arm/arch-netx/debug-macro.S
@@ -0,0 +1,38 @@
+/* linux/include/asm-arm/arch-netx/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include "hardware.h"
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0x00100000		@ physical
+		movne	\rx, #io_p2v(0x00100000)	@ virtual
+		orr	\rx, \rx, #0x00000a00
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x18]
+		tst	\rd, #(1 << 3)
+		bne	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #0x18]
+		tst	\rd, #(1 << 3)
+		bne	1001b
+		.endm
diff --git a/include/asm-arm/arch-netx/dma.h b/include/asm-arm/arch-netx/dma.h
new file mode 100644
index 0000000..4eda5fe
--- /dev/null
+++ b/include/asm-arm/arch-netx/dma.h
@@ -0,0 +1,21 @@
+/*
+ *  linux/include/asm-arm/arch-netx/dma.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define MAX_DMA_CHANNELS 0
+#define MAX_DMA_ADDRESS ~0
diff --git a/include/asm-arm/arch-netx/entry-macro.S b/include/asm-arm/arch-netx/entry-macro.S
new file mode 100644
index 0000000..658df4d
--- /dev/null
+++ b/include/asm-arm/arch-netx/entry-macro.S
@@ -0,0 +1,35 @@
+/*
+ * include/asm-arm/arch-netx/entry-macro.S
+ *
+ * Low-level IRQ helper macros for Hilscher netX based platforms
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <asm/hardware.h>
+
+		.macro  disable_fiq
+		.endm
+
+		.macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+		mov	\base, #io_p2v(0x00100000)
+		add	\base, \base, #0x000ff000
+
+		ldr	\irqstat, [\base, #0]
+		clz	\irqnr, \irqstat
+		rsb     \irqnr, \irqnr, #31
+		cmp	\irqstat, #0
+		.endm
+
diff --git a/include/asm-arm/arch-netx/eth.h b/include/asm-arm/arch-netx/eth.h
new file mode 100644
index 0000000..643c90e
--- /dev/null
+++ b/include/asm-arm/arch-netx/eth.h
@@ -0,0 +1,27 @@
+/*
+ * include/asm-arm/arch-netx/eth.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef ASMARM_ARCH_ETH_H
+#define ASMARM_ARCH_ETH_H
+
+struct netxeth_platform_data {
+	unsigned int xcno;	/* number of xmac/xpec engine this eth uses */
+};
+
+#endif
diff --git a/include/asm-arm/arch-netx/hardware.h b/include/asm-arm/arch-netx/hardware.h
new file mode 100644
index 0000000..7786c45
--- /dev/null
+++ b/include/asm-arm/arch-netx/hardware.h
@@ -0,0 +1,39 @@
+/*
+ * include/asm-arm/arch-netx/hardware.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#define NETX_IO_PHYS	0x00100000
+#define NETX_IO_VIRT	0xe0000000
+#define NETX_IO_SIZE	0x00100000
+
+#define SRAM_INTERNAL_PHYS_0 0x00000
+#define SRAM_INTERNAL_PHYS_1 0x08000
+#define SRAM_INTERNAL_PHYS_2 0x10000
+#define SRAM_INTERNAL_PHYS_3 0x18000
+#define SRAM_INTERNAL_PHYS(no) ((no) * 0x8000)
+
+#define XPEC_MEM_SIZE 0x4000
+#define XMAC_MEM_SIZE 0x1000
+#define SRAM_MEM_SIZE 0x8000
+
+#define io_p2v(x) ((x) - NETX_IO_PHYS + NETX_IO_VIRT)
+#define io_v2p(x) ((x) - NETX_IO_VIRT + NETX_IO_PHYS)
+
+#endif
diff --git a/include/asm-arm/arch-netx/io.h b/include/asm-arm/arch-netx/io.h
new file mode 100644
index 0000000..a7a53f8
--- /dev/null
+++ b/include/asm-arm/arch-netx/io.h
@@ -0,0 +1,28 @@
+/*
+ *  linux/include/asm-arm/arch-netx/io.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)         ((void __iomem *)(a))
+#define __mem_pci(a)            (a)
+
+#endif
diff --git a/include/asm-arm/arch-netx/irqs.h b/include/asm-arm/arch-netx/irqs.h
new file mode 100644
index 0000000..a487dc6
--- /dev/null
+++ b/include/asm-arm/arch-netx/irqs.h
@@ -0,0 +1,70 @@
+/*
+ * include/asm-arm/arch-netx/irqs.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define NETX_IRQ_VIC_START   0
+#define NETX_IRQ_SOFTINT     0
+#define NETX_IRQ_TIMER0      1
+#define NETX_IRQ_TIMER1      2
+#define NETX_IRQ_TIMER2      3
+#define NETX_IRQ_SYSTIME_NS  4
+#define NETX_IRQ_SYSTIME_S   5
+#define NETX_IRQ_GPIO_15     6
+#define NETX_IRQ_WATCHDOG    7
+#define NETX_IRQ_UART0       8
+#define NETX_IRQ_UART1       9
+#define NETX_IRQ_UART2      10
+#define NETX_IRQ_USB        11
+#define NETX_IRQ_SPI        12
+#define NETX_IRQ_I2C        13
+#define NETX_IRQ_LCD        14
+#define NETX_IRQ_HIF        15
+#define NETX_IRQ_GPIO_0_14  16
+#define NETX_IRQ_XPEC0      17
+#define NETX_IRQ_XPEC1      18
+#define NETX_IRQ_XPEC2      19
+#define NETX_IRQ_XPEC3      20
+#define NETX_IRQ_XPEC(no)   (17 + (no))
+#define NETX_IRQ_MSYNC0     21
+#define NETX_IRQ_MSYNC1     22
+#define NETX_IRQ_MSYNC2     23
+#define NETX_IRQ_MSYNC3     24
+#define NETX_IRQ_IRQ_PHY    25
+#define NETX_IRQ_ISO_AREA   26
+/* int 27 is reserved */
+/* int 28 is reserved */
+#define NETX_IRQ_TIMER3     29
+#define NETX_IRQ_TIMER4     30
+/* int 31 is reserved */
+
+#define NETX_IRQS 32
+
+/* for multiplexed irqs on gpio 0..14 */
+#define NETX_IRQ_GPIO(x) (NETX_IRQS + (x))
+#define NETX_IRQ_GPIO_LAST NETX_IRQ_GPIO(14)
+
+/* Host interface interrupts */
+#define NETX_IRQ_HIF_CHAINED(x)    (NETX_IRQ_GPIO_LAST + 1 + (x))
+#define NETX_IRQ_HIF_PIO35         NETX_IRQ_HIF_CHAINED(0)
+#define NETX_IRQ_HIF_PIO36         NETX_IRQ_HIF_CHAINED(1)
+#define NETX_IRQ_HIF_PIO40         NETX_IRQ_HIF_CHAINED(2)
+#define NETX_IRQ_HIF_PIO47         NETX_IRQ_HIF_CHAINED(3)
+#define NETX_IRQ_HIF_PIO72         NETX_IRQ_HIF_CHAINED(4)
+#define NETX_IRQ_HIF_LAST          NETX_IRQ_HIF_CHAINED(4)
+
+#define NR_IRQS (NETX_IRQ_HIF_LAST + 1)
diff --git a/include/asm-arm/arch-netx/memory.h b/include/asm-arm/arch-netx/memory.h
new file mode 100644
index 0000000..6d8d2df
--- /dev/null
+++ b/include/asm-arm/arch-netx/memory.h
@@ -0,0 +1,36 @@
+/*
+ *  linux/include/asm-arm/arch-netx/memory.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#define PHYS_OFFSET UL(0x80000000)
+
+/*
+ * Virtual view <-> DMA view memory address translations
+ * virt_to_bus: Used to translate the virtual address to an
+ *              address suitable to be passed to set_dma_addr
+ * bus_to_virt: Used to convert an address for DMA operations
+ *              to an address that the kernel can use.
+ */
+#define __virt_to_bus(x)         __virt_to_phys(x)
+#define __bus_to_virt(x)         __phys_to_virt(x)
+
+#endif
+
diff --git a/include/asm-arm/arch-netx/netx-regs.h b/include/asm-arm/arch-netx/netx-regs.h
new file mode 100644
index 0000000..8ab45be
--- /dev/null
+++ b/include/asm-arm/arch-netx/netx-regs.h
@@ -0,0 +1,410 @@
+/*
+ * include/asm-arm/arch-netx/netx-regs.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_NETX_REGS_H
+#define __ASM_ARCH_NETX_REGS_H
+
+/* offsets relative to the beginning of the io space */
+#define NETX_OFS_SYSTEM  0x00000
+#define NETX_OFS_MEMCR   0x00100
+#define NETX_OFS_DPMAS   0x03000
+#define NETX_OFS_GPIO    0x00800
+#define NETX_OFS_PIO     0x00900
+#define NETX_OFS_UART0   0x00a00
+#define NETX_OFS_UART1   0x00a40
+#define NETX_OFS_UART2   0x00a80
+#define NETX_OF_MIIMU    0x00b00
+#define NETX_OFS_SPI     0x00c00
+#define NETX_OFS_I2C     0x00d00
+#define NETX_OFS_SYSTIME 0x01100
+#define NETX_OFS_RTC     0x01200
+#define NETX_OFS_EXTBUS  0x03600
+#define NETX_OFS_LCD     0x04000
+#define NETX_OFS_USB     0x20000
+#define NETX_OFS_XMAC0   0x60000
+#define NETX_OFS_XMAC1   0x61000
+#define NETX_OFS_XMAC2   0x62000
+#define NETX_OFS_XMAC3   0x63000
+#define NETX_OFS_XMAC(no) (0x60000 + (no) * 0x1000)
+#define NETX_OFS_PFIFO   0x64000
+#define NETX_OFS_XPEC0   0x70000
+#define NETX_OFS_XPEC1   0x74000
+#define NETX_OFS_XPEC2   0x78000
+#define NETX_OFS_XPEC3   0x7c000
+#define NETX_OFS_XPEC(no) (0x70000 + (no) * 0x4000)
+#define NETX_OFS_VIC     0xff000
+
+/* physical addresses */
+#define NETX_PA_SYSTEM   (NETX_IO_PHYS + NETX_OFS_SYSTEM)
+#define NETX_PA_MEMCR    (NETX_IO_PHYS + NETX_OFS_MEMCR)
+#define NETX_PA_DPMAS    (NETX_IO_PHYS + NETX_OFS_DPMAS)
+#define NETX_PA_GPIO     (NETX_IO_PHYS + NETX_OFS_GPIO)
+#define NETX_PA_PIO      (NETX_IO_PHYS + NETX_OFS_PIO)
+#define NETX_PA_UART0    (NETX_IO_PHYS + NETX_OFS_UART0)
+#define NETX_PA_UART1    (NETX_IO_PHYS + NETX_OFS_UART1)
+#define NETX_PA_UART2    (NETX_IO_PHYS + NETX_OFS_UART2)
+#define NETX_PA_MIIMU    (NETX_IO_PHYS + NETX_OF_MIIMU)
+#define NETX_PA_SPI      (NETX_IO_PHYS + NETX_OFS_SPI)
+#define NETX_PA_I2C      (NETX_IO_PHYS + NETX_OFS_I2C)
+#define NETX_PA_SYSTIME  (NETX_IO_PHYS + NETX_OFS_SYSTIME)
+#define NETX_PA_RTC      (NETX_IO_PHYS + NETX_OFS_RTC)
+#define NETX_PA_EXTBUS   (NETX_IO_PHYS + NETX_OFS_EXTBUS)
+#define NETX_PA_LCD      (NETX_IO_PHYS + NETX_OFS_LCD)
+#define NETX_PA_USB      (NETX_IO_PHYS + NETX_OFS_USB)
+#define NETX_PA_XMAC0    (NETX_IO_PHYS + NETX_OFS_XMAC0)
+#define NETX_PA_XMAC1    (NETX_IO_PHYS + NETX_OFS_XMAC1)
+#define NETX_PA_XMAC2    (NETX_IO_PHYS + NETX_OFS_XMAC2)
+#define NETX_PA_XMAC3    (NETX_IO_PHYS + NETX_OFS_XMAC3)
+#define NETX_PA_XMAC(no) (NETX_IO_PHYS + NETX_OFS_XMAC(no))
+#define NETX_PA_PFIFO    (NETX_IO_PHYS + NETX_OFS_PFIFO)
+#define NETX_PA_XPEC0    (NETX_IO_PHYS + NETX_OFS_XPEC0)
+#define NETX_PA_XPEC1    (NETX_IO_PHYS + NETX_OFS_XPEC1)
+#define NETX_PA_XPEC2    (NETX_IO_PHYS + NETX_OFS_XPEC2)
+#define NETX_PA_XPEC3    (NETX_IO_PHYS + NETX_OFS_XPEC3)
+#define NETX_PA_XPEC(no) (NETX_IO_PHYS + NETX_OFS_XPEC(no))
+#define NETX_PA_VIC      (NETX_IO_PHYS + NETX_OFS_VIC)
+
+/* virual addresses */
+#define NETX_VA_SYSTEM   (NETX_IO_VIRT + NETX_OFS_SYSTEM)
+#define NETX_VA_MEMCR    (NETX_IO_VIRT + NETX_OFS_MEMCR)
+#define NETX_VA_DPMAS    (NETX_IO_VIRT + NETX_OFS_DPMAS)
+#define NETX_VA_GPIO     (NETX_IO_VIRT + NETX_OFS_GPIO)
+#define NETX_VA_PIO      (NETX_IO_VIRT + NETX_OFS_PIO)
+#define NETX_VA_UART0    (NETX_IO_VIRT + NETX_OFS_UART0)
+#define NETX_VA_UART1    (NETX_IO_VIRT + NETX_OFS_UART1)
+#define NETX_VA_UART2    (NETX_IO_VIRT + NETX_OFS_UART2)
+#define NETX_VA_MIIMU    (NETX_IO_VIRT + NETX_OF_MIIMU)
+#define NETX_VA_SPI      (NETX_IO_VIRT + NETX_OFS_SPI)
+#define NETX_VA_I2C      (NETX_IO_VIRT + NETX_OFS_I2C)
+#define NETX_VA_SYSTIME  (NETX_IO_VIRT + NETX_OFS_SYSTIME)
+#define NETX_VA_RTC      (NETX_IO_VIRT + NETX_OFS_RTC)
+#define NETX_VA_EXTBUS   (NETX_IO_VIRT + NETX_OFS_EXTBUS)
+#define NETX_VA_LCD      (NETX_IO_VIRT + NETX_OFS_LCD)
+#define NETX_VA_USB      (NETX_IO_VIRT + NETX_OFS_USB)
+#define NETX_VA_XMAC0    (NETX_IO_VIRT + NETX_OFS_XMAC0)
+#define NETX_VA_XMAC1    (NETX_IO_VIRT + NETX_OFS_XMAC1)
+#define NETX_VA_XMAC2    (NETX_IO_VIRT + NETX_OFS_XMAC2)
+#define NETX_VA_XMAC3    (NETX_IO_VIRT + NETX_OFS_XMAC3)
+#define NETX_VA_XMAC(no) (NETX_IO_VIRT + NETX_OFS_XMAC(no))
+#define NETX_VA_PFIFO    (NETX_IO_VIRT + NETX_OFS_PFIFO)
+#define NETX_VA_XPEC0    (NETX_IO_VIRT + NETX_OFS_XPEC0)
+#define NETX_VA_XPEC1    (NETX_IO_VIRT + NETX_OFS_XPEC1)
+#define NETX_VA_XPEC2    (NETX_IO_VIRT + NETX_OFS_XPEC2)
+#define NETX_VA_XPEC3    (NETX_IO_VIRT + NETX_OFS_XPEC3)
+#define NETX_VA_XPEC(no) (NETX_IO_VIRT + NETX_OFS_XPEC(no))
+#define NETX_VA_VIC      (NETX_IO_VIRT + NETX_OFS_VIC)
+
+/*********************************
+ * System functions              *
+ *********************************/
+
+/* Registers */
+#define NETX_SYSTEM_REG(ofs)            __io(NETX_VA_SYSTEM + (ofs))
+#define NETX_SYSTEM_BOO_SR          NETX_SYSTEM_REG(0x00)
+#define NETX_SYSTEM_IOC_CR          NETX_SYSTEM_REG(0x04)
+#define NETX_SYSTEM_IOC_MR          NETX_SYSTEM_REG(0x08)
+
+/* FIXME: Docs are not consistent */
+#define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x08)
+/* #define NETX_SYSTEM_RES_CR          NETX_SYSTEM_REG(0x0c) */
+
+#define NETX_SYSTEM_PHY_CONTROL     NETX_SYSTEM_REG(0x10)
+#define NETX_SYSTEM_REV             NETX_SYSTEM_REG(0x34)
+#define NETX_SYSTEM_IOC_ACCESS_KEY  NETX_SYSTEM_REG(0x70)
+#define NETX_SYSTEM_WDG_TR          NETX_SYSTEM_REG(0x200)
+#define NETX_SYSTEM_WDG_CTR         NETX_SYSTEM_REG(0x204)
+#define NETX_SYSTEM_WDG_IRQ_TIMEOUT NETX_SYSTEM_REG(0x208)
+#define NETX_SYSTEM_WDG_RES_TIMEOUT NETX_SYSTEM_REG(0x20c)
+
+/* Bits */
+#define NETX_SYSTEM_RES_CR_RSTIN         (1<<0)
+#define NETX_SYSTEM_RES_CR_WDG_RES       (1<<1)
+#define NETX_SYSTEM_RES_CR_HOST_RES      (1<<2)
+#define NETX_SYSTEM_RES_CR_FIRMW_RES     (1<<3)
+#define NETX_SYSTEM_RES_CR_XPEC0_RES     (1<<4)
+#define NETX_SYSTEM_RES_CR_XPEC1_RES     (1<<5)
+#define NETX_SYSTEM_RES_CR_XPEC2_RES     (1<<6)
+#define NETX_SYSTEM_RES_CR_XPEC3_RES     (1<<7)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC0_RES (1<<16)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC1_RES (1<<17)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC2_RES (1<<18)
+#define NETX_SYSTEM_RES_CR_DIS_XPEC3_RES (1<<19)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG0    (1<<20)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG1    (1<<21)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG2    (1<<22)
+#define NETX_SYSTEM_RES_CR_FIRMW_FLG3    (1<<23)
+#define NETX_SYSTEM_RES_CR_FIRMW_RES_EN  (1<<24)
+#define NETX_SYSTEM_RES_CR_RSTOUT        (1<<25)
+#define NETX_SYSTEM_RES_CR_EN_RSTOUT     (1<<26)
+
+#define PHY_CONTROL_RESET            (1<<31)
+#define PHY_CONTROL_SIM_BYP          (1<<30)
+#define PHY_CONTROL_CLK_XLATIN       (1<<29)
+#define PHY_CONTROL_PHY1_EN          (1<<21)
+#define PHY_CONTROL_PHY1_NP_MSG_CODE
+#define PHY_CONTROL_PHY1_AUTOMDIX    (1<<17)
+#define PHY_CONTROL_PHY1_FIXMODE     (1<<16)
+#define PHY_CONTROL_PHY1_MODE(mode)  (((mode) & 0x7) << 13)
+#define PHY_CONTROL_PHY0_EN          (1<<12)
+#define PHY_CONTROL_PHY0_NP_MSG_CODE
+#define PHY_CONTROL_PHY0_AUTOMDIX    (1<<8)
+#define PHY_CONTROL_PHY0_FIXMODE     (1<<7)
+#define PHY_CONTROL_PHY0_MODE(mode)  (((mode) & 0x7) << 4)
+#define PHY_CONTROL_PHY_ADDRESS(adr) ((adr) & 0xf)
+
+#define PHY_MODE_10BASE_T_HALF      0
+#define PHY_MODE_10BASE_T_FULL      1
+#define PHY_MODE_100BASE_TX_FX_FULL 2
+#define PHY_MODE_100BASE_TX_FX_HALF 3
+#define PHY_MODE_100BASE_TX_HALF    4
+#define PHY_MODE_REPEATER           5
+#define PHY_MODE_POWER_DOWN         6
+#define PHY_MODE_ALL                7
+
+/* Bits */
+#define VECT_CNTL_ENABLE               (1 << 5)
+
+/*******************************
+ * GPIO and timer module       *
+ *******************************/
+
+/* Registers */
+#define NETX_GPIO_REG(ofs)                     __io(NETX_VA_GPIO + (ofs))
+#define NETX_GPIO_CFG(gpio)                NETX_GPIO_REG(0x0  + ((gpio)<<2))
+#define NETX_GPIO_THRESHOLD_CAPTURE(gpio)  NETX_GPIO_REG(0x40 + ((gpio)<<2))
+#define NETX_GPIO_COUNTER_CTRL(counter)    NETX_GPIO_REG(0x80 + ((counter)<<2))
+#define NETX_GPIO_COUNTER_MAX(counter)     NETX_GPIO_REG(0x94 + ((counter)<<2))
+#define NETX_GPIO_COUNTER_CURRENT(counter) NETX_GPIO_REG(0xa8 + ((counter)<<2))
+#define NETX_GPIO_IRQ_ENABLE               NETX_GPIO_REG(0xbc)
+#define NETX_GPIO_IRQ_DISABLE              NETX_GPIO_REG(0xc0)
+#define NETX_GPIO_SYSTIME_NS_CMP           NETX_GPIO_REG(0xc4)
+#define NETX_GPIO_LINE                     NETX_GPIO_REG(0xc8)
+#define NETX_GPIO_IRQ                      NETX_GPIO_REG(0xd0)
+
+/* Bits */
+#define NETX_GPIO_CFG_IOCFG_GP_INPUT                 (0x0)
+#define NETX_GPIO_CFG_IOCFG_GP_OUTPUT                (0x1)
+#define NETX_GPIO_CFG_IOCFG_GP_UART                  (0x2)
+#define NETX_GPIO_CFG_INV                            (1<<2)
+#define NETX_GPIO_CFG_MODE_INPUT_READ                (0<<3)
+#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_CONT_RISING (1<<3)
+#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_ONCE_RISING (2<<3)
+#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_HIGH_LEVEL  (3<<3)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER0             (0<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER1             (1<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER2             (2<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER3             (3<<5)
+#define NETX_GPIO_CFG_COUNT_REF_COUNTER4             (4<<5)
+#define NETX_GPIO_CFG_COUNT_REF_SYSTIME              (7<<5)
+
+#define NETX_GPIO_COUNTER_CTRL_RUN                   (1<<0)
+#define NETX_GPIO_COUNTER_CTRL_SYM                   (1<<1)
+#define NETX_GPIO_COUNTER_CTRL_ONCE                  (1<<2)
+#define NETX_GPIO_COUNTER_CTRL_IRQ_EN                (1<<3)
+#define NETX_GPIO_COUNTER_CTRL_CNT_EVENT             (1<<4)
+#define NETX_GPIO_COUNTER_CTRL_RST_EN                (1<<5)
+#define NETX_GPIO_COUNTER_CTRL_SEL_EVENT             (1<<6)
+#define NETX_GPIO_COUNTER_CTRL_GPIO_REF /* FIXME */
+
+#define GPIO_BIT(gpio)                     (1<<(gpio))
+#define COUNTER_BIT(counter)               ((1<<16)<<(counter))
+
+/*******************************
+ * PIO                         *
+ *******************************/
+
+/* Registers */
+#define NETX_PIO_REG(ofs)        __io(NETX_VA_PIO + (ofs))
+#define NETX_PIO_INPIO       NETX_PIO_REG(0x0)
+#define NETX_PIO_OUTPIO      NETX_PIO_REG(0x4)
+#define NETX_PIO_OEPIO       NETX_PIO_REG(0x8)
+
+/*******************************
+ * MII Unit                    *
+ *******************************/
+
+/* Registers */
+#define NETX_MIIMU           __io(NETX_VA_MIIMU)
+
+/* Bits */
+#define MIIMU_SNRDY        (1<<0)
+#define MIIMU_PREAMBLE     (1<<1)
+#define MIIMU_OPMODE_WRITE (1<<2)
+#define MIIMU_MDC_PERIOD   (1<<3)
+#define MIIMU_PHY_NRES     (1<<4)
+#define MIIMU_RTA          (1<<5)
+#define MIIMU_REGADDR(adr) (((adr) & 0x1f) << 6)
+#define MIIMU_PHYADDR(adr) (((adr) & 0x1f) << 11)
+#define MIIMU_DATA(data)   (((data) & 0xffff) << 16)
+
+/*******************************
+ * xmac / xpec                 *
+ *******************************/
+
+/* XPEC register offsets relative to NETX_VA_XPEC(no) */
+#define NETX_XPEC_R0_OFS           0x00
+#define NETX_XPEC_R1_OFS           0x04
+#define NETX_XPEC_R2_OFS           0x08
+#define NETX_XPEC_R3_OFS           0x0c
+#define NETX_XPEC_R4_OFS           0x10
+#define NETX_XPEC_R5_OFS           0x14
+#define NETX_XPEC_R6_OFS           0x18
+#define NETX_XPEC_R7_OFS           0x1c
+#define NETX_XPEC_RANGE01_OFS      0x20
+#define NETX_XPEC_RANGE23_OFS      0x24
+#define NETX_XPEC_RANGE45_OFS      0x28
+#define NETX_XPEC_RANGE67_OFS      0x2c
+#define NETX_XPEC_PC_OFS           0x48
+#define NETX_XPEC_TIMER_OFS(timer) (0x30 + ((timer)<<2))
+#define NETX_XPEC_IRQ_OFS          0x8c
+#define NETX_XPEC_SYSTIME_NS_OFS   0x90
+#define NETX_XPEC_FIFO_DATA_OFS    0x94
+#define NETX_XPEC_SYSTIME_S_OFS    0x98
+#define NETX_XPEC_ADC_OFS          0x9c
+#define NETX_XPEC_URX_COUNT_OFS    0x40
+#define NETX_XPEC_UTX_COUNT_OFS    0x44
+#define NETX_XPEC_PC_OFS           0x48
+#define NETX_XPEC_ZERO_OFS         0x4c
+#define NETX_XPEC_STATCFG_OFS      0x50
+#define NETX_XPEC_EC_MASKA_OFS     0x54
+#define NETX_XPEC_EC_MASKB_OFS     0x58
+#define NETX_XPEC_EC_MASK0_OFS     0x5c
+#define NETX_XPEC_EC_MASK8_OFS     0x7c
+#define NETX_XPEC_EC_MASK9_OFS     0x80
+#define NETX_XPEC_XPU_HOLD_PC_OFS  0x100
+#define NETX_XPEC_RAM_START_OFS    0x2000
+
+/* Bits */
+#define XPU_HOLD_PC (1<<0)
+
+/* XMAC register offsets relative to NETX_VA_XMAC(no) */
+#define NETX_XMAC_RPU_PROGRAM_START_OFS       0x000
+#define NETX_XMAC_RPU_PROGRAM_END_OFS         0x3ff
+#define NETX_XMAC_TPU_PROGRAM_START_OFS       0x400
+#define NETX_XMAC_TPU_PROGRAM_END_OFS         0x7ff
+#define NETX_XMAC_RPU_HOLD_PC_OFS             0xa00
+#define NETX_XMAC_TPU_HOLD_PC_OFS             0xa04
+#define NETX_XMAC_STATUS_SHARED0_OFS          0x840
+#define NETX_XMAC_CONFIG_SHARED0_OFS          0x844
+#define NETX_XMAC_STATUS_SHARED1_OFS          0x848
+#define NETX_XMAC_CONFIG_SHARED1_OFS          0x84c
+#define NETX_XMAC_STATUS_SHARED2_OFS          0x850
+#define NETX_XMAC_CONFIG_SHARED2_OFS          0x854
+#define NETX_XMAC_STATUS_SHARED3_OFS          0x858
+#define NETX_XMAC_CONFIG_SHARED3_OFS          0x85c
+
+#define RPU_HOLD_PC            (1<<15)
+#define TPU_HOLD_PC            (1<<15)
+
+/*******************************
+ * Pointer FIFO                *
+ *******************************/
+
+/* Registers */
+#define NETX_PFIFO_REG(ofs)               __io(NETX_VA_PFIFO + (ofs))
+#define NETX_PFIFO_BASE(pfifo)        NETX_PFIFO_REG(0x00 + ((pfifo)<<2))
+#define NETX_PFIFO_BORDER_BASE(pfifo) NETX_PFIFO_REG(0x80 + ((pfifo)<<2))
+#define NETX_PFIFO_RESET              NETX_PFIFO_REG(0x100)
+#define NETX_PFIFO_FULL               NETX_PFIFO_REG(0x104)
+#define NETX_PFIFO_EMPTY              NETX_PFIFO_REG(0x108)
+#define NETX_PFIFO_OVEFLOW            NETX_PFIFO_REG(0x10c)
+#define NETX_PFIFO_UNDERRUN           NETX_PFIFO_REG(0x110)
+#define NETX_PFIFO_FILL_LEVEL(pfifo)  NETX_PFIFO_REG(0x180 + ((pfifo)<<2))
+#define NETX_PFIFO_XPEC_ISR(xpec)     NETX_PFIFO_REG(0x400 + ((xpec) << 2))
+
+/*******************************
+ * Dual Port Memory            *
+ *******************************/
+
+/* Registers */
+#define NETX_DPMAS_REG(ofs)               __io(NETX_VA_DPMAS + (ofs))
+#define NETX_DPMAS_SYS_STAT           NETX_DPMAS_REG(0x4d8)
+#define NETX_DPMAS_INT_STAT           NETX_DPMAS_REG(0x4e0)
+#define NETX_DPMAS_INT_EN             NETX_DPMAS_REG(0x4f0)
+#define NETX_DPMAS_IF_CONF0           NETX_DPMAS_REG(0x608)
+#define NETX_DPMAS_IF_CONF1           NETX_DPMAS_REG(0x60c)
+#define NETX_DPMAS_EXT_CONFIG(cs)     NETX_DPMAS_REG(0x610 + 4 * (cs))
+#define NETX_DPMAS_IO_MODE0           NETX_DPMAS_REG(0x620) /* I/O 32..63 */
+#define NETX_DPMAS_DRV_EN0            NETX_DPMAS_REG(0x624)
+#define NETX_DPMAS_DATA0              NETX_DPMAS_REG(0x628)
+#define NETX_DPMAS_IO_MODE1           NETX_DPMAS_REG(0x630) /* I/O 64..84 */
+#define NETX_DPMAS_DRV_EN1            NETX_DPMAS_REG(0x634)
+#define NETX_DPMAS_DATA1              NETX_DPMAS_REG(0x638)
+
+/* Bits */
+#define NETX_DPMAS_INT_EN_GLB_EN         (1<<31)
+#define NETX_DPMAS_INT_EN_MEM_LCK        (1<<30)
+#define NETX_DPMAS_INT_EN_WDG            (1<<29)
+#define NETX_DPMAS_INT_EN_PIO72          (1<<28)
+#define NETX_DPMAS_INT_EN_PIO47          (1<<27)
+#define NETX_DPMAS_INT_EN_PIO40          (1<<26)
+#define NETX_DPMAS_INT_EN_PIO36          (1<<25)
+#define NETX_DPMAS_INT_EN_PIO35          (1<<24)
+
+#define NETX_DPMAS_IF_CONF0_HIF_DISABLED (0<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_EXT_BUS  (1<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_UP_8BIT  (2<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_UP_16BIT (3<<28)
+#define NETX_DPMAS_IF_CONF0_HIF_IO       (4<<28)
+#define NETX_DPMAS_IF_CONF0_WAIT_DRV_PP  (1<<14)
+#define NETX_DPMAS_IF_CONF0_WAIT_DRV_OD  (2<<14)
+#define NETX_DPMAS_IF_CONF0_WAIT_DRV_TRI (3<<14)
+
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO35 (1<<26)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO36 (1<<27)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO40 (1<<28)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO47 (1<<29)
+#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO72 (1<<30)
+
+#define NETX_EXT_CONFIG_TALEWIDTH(x) (((x) & 0x7) << 29)
+#define NETX_EXT_CONFIG_TADRHOLD(x)  (((x) & 0x7) << 26)
+#define NETX_EXT_CONFIG_TCSON(x)     (((x) & 0x7) << 23)
+#define NETX_EXT_CONFIG_TRDON(x)     (((x) & 0x7) << 20)
+#define NETX_EXT_CONFIG_TWRON(x)     (((x) & 0x7)  << 17)
+#define NETX_EXT_CONFIG_TWROFF(x)    (((x) & 0x1f) << 12)
+#define NETX_EXT_CONFIG_TRDWRCYC(x)  (((x) & 0x1f) << 7)
+#define NETX_EXT_CONFIG_WAIT_POL     (1<<6)
+#define NETX_EXT_CONFIG_WAIT_EN      (1<<5)
+#define NETX_EXT_CONFIG_NRD_MODE     (1<<4)
+#define NETX_EXT_CONFIG_DS_MODE      (1<<3)
+#define NETX_EXT_CONFIG_NWR_MODE     (1<<2)
+#define NETX_EXT_CONFIG_16BIT        (1<<1)
+#define NETX_EXT_CONFIG_CS_ENABLE    (1<<0)
+
+#define NETX_DPMAS_IO_MODE0_WRL   (1<<13)
+#define NETX_DPMAS_IO_MODE0_WAIT  (1<<14)
+#define NETX_DPMAS_IO_MODE0_READY (1<<15)
+#define NETX_DPMAS_IO_MODE0_CS0   (1<<19)
+#define NETX_DPMAS_IO_MODE0_EXTRD (1<<20)
+
+#define NETX_DPMAS_IO_MODE1_CS2           (1<<15)
+#define NETX_DPMAS_IO_MODE1_CS1           (1<<16)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_NPOR   (0<<30)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_100MHZ (1<<30)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_NPIO36 (2<<30)
+#define NETX_DPMAS_IO_MODE1_SAMPLE_PIO36  (3<<30)
+
+/*******************************
+ * I2C                         *
+ *******************************/
+#define NETX_I2C_REG(ofs)	__io(NETX_VA_I2C, (ofs))
+#define NETX_I2C_CTRL	NETX_I2C_REG(0x0)
+#define NETX_I2C_DATA	NETX_I2C_REG(0x4)
+
+#endif /* __ASM_ARCH_NETX_REGS_H */
diff --git a/include/asm-arm/arch-netx/param.h b/include/asm-arm/arch-netx/param.h
new file mode 100644
index 0000000..7a80c26
--- /dev/null
+++ b/include/asm-arm/arch-netx/param.h
@@ -0,0 +1,18 @@
+/*
+ *  linux/include/asm-arm/arch-netx/param.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
diff --git a/include/asm-arm/arch-netx/pfifo.h b/include/asm-arm/arch-netx/pfifo.h
new file mode 100644
index 0000000..4af2ee4
--- /dev/null
+++ b/include/asm-arm/arch-netx/pfifo.h
@@ -0,0 +1,54 @@
+/*
+ * include/asm-arm/arch-netx/pfifo.h
+ *
+ * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef ASM_ARCH_PFIFO_H
+#define ASM_ARCH_PFIFO_H
+
+static inline int pfifo_push(int no, unsigned int pointer)
+{
+	writel(pointer, NETX_PFIFO_BASE(no));
+	return 0;
+}
+
+static inline unsigned int pfifo_pop(int no)
+{
+	return readl(NETX_PFIFO_BASE(no));
+}
+
+static inline int pfifo_fill_level(int no)
+{
+
+	return readl(NETX_PFIFO_FILL_LEVEL(no));
+}
+
+static inline int pfifo_full(int no)
+{
+	return readl(NETX_PFIFO_FULL) & (1<<no) ? 1 : 0;
+}
+
+static inline int pfifo_empty(int no)
+{
+	return readl(NETX_PFIFO_EMPTY) & (1<<no) ? 1 : 0;
+}
+
+int pfifo_request(unsigned int pfifo_mask);
+void pfifo_free(unsigned int pfifo_mask);
+
+#endif /* ASM_ARCH_PFIFO_H */
diff --git a/include/asm-arm/arch-netx/system.h b/include/asm-arm/arch-netx/system.h
new file mode 100644
index 0000000..52adf36
--- /dev/null
+++ b/include/asm-arm/arch-netx/system.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-arm/arch-netx/system.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include "netx-regs.h"
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES,
+	       NETX_SYSTEM_RES_CR);
+}
+
+#endif
+
diff --git a/include/asm-arm/arch-netx/timex.h b/include/asm-arm/arch-netx/timex.h
new file mode 100644
index 0000000..7fdb42da
--- /dev/null
+++ b/include/asm-arm/arch-netx/timex.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-netx/timex.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define CLOCK_TICK_RATE 100000000
diff --git a/include/asm-arm/arch-netx/uncompress.h b/include/asm-arm/arch-netx/uncompress.h
new file mode 100644
index 0000000..f894345
--- /dev/null
+++ b/include/asm-arm/arch-netx/uncompress.h
@@ -0,0 +1,76 @@
+/*
+ * include/asm-arm/arch-netx/uncompress.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader.  We search for the first enabled
+ * port in the most probable order.  If you didn't setup a port in
+ * your bootloader then nothing will appear (which might be desired).
+ *
+ * This does not append a newline
+ */
+
+#define REG(x) (*(volatile unsigned long *)(x))
+
+#define UART1_BASE 0x100a00
+#define UART2_BASE 0x100a80
+
+#define UART_DR 0x0
+
+#define UART_CR 0x14
+#define CR_UART_EN (1<<0)
+
+#define UART_FR 0x18
+#define FR_BUSY (1<<3)
+#define FR_TXFF (1<<5)
+
+static void putc(char c)
+{
+	unsigned long base;
+
+	if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
+		base = UART1_BASE;
+	else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
+		base = UART2_BASE;
+	else
+		return;
+
+	while (REG(base + UART_FR) & FR_TXFF);
+	REG(base + UART_DR) = c;
+}
+
+static inline void flush(void)
+{
+	unsigned long base;
+
+	if (REG(UART1_BASE + UART_CR) & CR_UART_EN)
+		base = UART1_BASE;
+	else if (REG(UART2_BASE + UART_CR) & CR_UART_EN)
+		base = UART2_BASE;
+	else
+		return;
+
+	while (REG(base + UART_FR) & FR_BUSY);
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-netx/vmalloc.h b/include/asm-arm/arch-netx/vmalloc.h
new file mode 100644
index 0000000..da2da5a
--- /dev/null
+++ b/include/asm-arm/arch-netx/vmalloc.h
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-netx/vmalloc.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-netx/xc.h b/include/asm-arm/arch-netx/xc.h
new file mode 100644
index 0000000..659af19
--- /dev/null
+++ b/include/asm-arm/arch-netx/xc.h
@@ -0,0 +1,42 @@
+/*
+ *  linux/include/asm-arm/arch-netx/xc.h
+ *
+ * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __ASM_ARCH_XC_H
+#define __ASM_ARCH_XC_H
+
+struct xc {
+	int no;
+	unsigned int type;
+	unsigned int version;
+	void __iomem *xpec_base;
+	void __iomem *xmac_base;
+	void __iomem *sram_base;
+	int irq;
+	struct device *dev;
+};
+
+int xc_reset(struct xc *x);
+int xc_stop(struct xc* x);
+int xc_start(struct xc *x);
+int xc_running(struct xc *x);
+int xc_request_firmware(struct xc* x);
+struct xc* request_xc(int xcno, struct device *dev);
+void free_xc(struct xc *x);
+
+#endif /* __ASM_ARCH_XC_H */
diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h
index 6d6240a..dfdbf06 100644
--- a/include/asm-arm/arch-omap/board.h
+++ b/include/asm-arm/arch-omap/board.h
@@ -10,7 +10,6 @@
 #ifndef _OMAP_BOARD_H
 #define _OMAP_BOARD_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /* Different peripheral ids */
diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h
index 7909b72..c7d9e85 100644
--- a/include/asm-arm/arch-omap/hardware.h
+++ b/include/asm-arm/arch-omap/hardware.h
@@ -37,7 +37,6 @@
 #define __ASM_ARCH_OMAP_HARDWARE_H
 
 #include <asm/sizes.h>
-#include <linux/config.h>
 #ifndef __ASSEMBLER__
 #include <asm/types.h>
 #include <asm/arch/cpu.h>
diff --git a/include/asm-arm/arch-omap/io.h b/include/asm-arm/arch-omap/io.h
index b726acf..78f68e6 100644
--- a/include/asm-arm/arch-omap/io.h
+++ b/include/asm-arm/arch-omap/io.h
@@ -44,7 +44,6 @@
  */
 #define __io(a)			((void __iomem *)(PCIO_BASE + (a)))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 /*
  * ----------------------------------------------------------------------------
diff --git a/include/asm-arm/arch-omap/system.h b/include/asm-arm/arch-omap/system.h
index 67970d1..ac2bfa4 100644
--- a/include/asm-arm/arch-omap/system.h
+++ b/include/asm-arm/arch-omap/system.h
@@ -4,7 +4,6 @@
  */
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
-#include <linux/config.h>
 #include <linux/clk.h>
 
 #include <asm/mach-types.h>
diff --git a/include/asm-arm/arch-omap/uncompress.h b/include/asm-arm/arch-omap/uncompress.h
index ca2c8be..aca0adf 100644
--- a/include/asm-arm/arch-omap/uncompress.h
+++ b/include/asm-arm/arch-omap/uncompress.h
@@ -17,7 +17,6 @@
  * kind, whether express or implied.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/serial_reg.h>
 #include <asm/arch/serial.h>
diff --git a/include/asm-arm/arch-pnx4008/clock.h b/include/asm-arm/arch-pnx4008/clock.h
new file mode 100644
index 0000000..91ae003
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/clock.h
@@ -0,0 +1,61 @@
+/*
+ * include/asm-arm/arch-pnx4008/clock.h
+ *
+ * Clock control driver for PNX4008 - header file
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __PNX4008_CLOCK_H__
+#define __PNX4008_CLOCK_H__
+
+struct module;
+struct clk;
+
+#define PWRMAN_VA_BASE		IO_ADDRESS(PNX4008_PWRMAN_BASE)
+#define HCLKDIVCTRL_REG		(PWRMAN_VA_BASE + 0x40)
+#define PWRCTRL_REG		(PWRMAN_VA_BASE + 0x44)
+#define PLLCTRL_REG		(PWRMAN_VA_BASE + 0x48)
+#define OSC13CTRL_REG		(PWRMAN_VA_BASE + 0x4c)
+#define SYSCLKCTRL_REG		(PWRMAN_VA_BASE + 0x50)
+#define HCLKPLLCTRL_REG		(PWRMAN_VA_BASE + 0x58)
+#define USBCTRL_REG		(PWRMAN_VA_BASE + 0x64)
+#define SDRAMCLKCTRL_REG	(PWRMAN_VA_BASE + 0x68)
+#define MSCTRL_REG		(PWRMAN_VA_BASE + 0x80)
+#define BTCLKCTRL		(PWRMAN_VA_BASE + 0x84)
+#define DUMCLKCTRL_REG		(PWRMAN_VA_BASE + 0x90)
+#define I2CCLKCTRL_REG		(PWRMAN_VA_BASE + 0xac)
+#define KEYCLKCTRL_REG		(PWRMAN_VA_BASE + 0xb0)
+#define TSCLKCTRL_REG		(PWRMAN_VA_BASE + 0xb4)
+#define PWMCLKCTRL_REG		(PWRMAN_VA_BASE + 0xb8)
+#define SPICTRL_REG		(PWRMAN_VA_BASE + 0xc4)
+#define FLASHCLKCTRL_REG	(PWRMAN_VA_BASE + 0xc8)
+#define UART3CLK_REG		(PWRMAN_VA_BASE + 0xd0)
+#define UARTCLKCTRL_REG		(PWRMAN_VA_BASE + 0xe4)
+#define DMACLKCTRL_REG		(PWRMAN_VA_BASE + 0xe8)
+#define AUTOCLK_CTRL		(PWRMAN_VA_BASE + 0xec)
+#define JPEGCLKCTRL_REG		(PWRMAN_VA_BASE + 0xfc)
+
+#define AUDIOCONFIG_VA_BASE	IO_ADDRESS(PNX4008_AUDIOCONFIG_BASE)
+#define DSPPLLCTRL_REG		(AUDIOCONFIG_VA_BASE + 0x60)
+#define DSPCLKCTRL_REG		(AUDIOCONFIG_VA_BASE + 0x64)
+#define AUDIOCLKCTRL_REG	(AUDIOCONFIG_VA_BASE + 0x68)
+#define AUDIOPLLCTRL_REG	(AUDIOCONFIG_VA_BASE + 0x6C)
+
+#define USB_OTG_CLKCTRL_REG	IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xff4)
+
+#define VFP9CLKCTRL_REG		IO_ADDRESS(PNX4008_DEBUG_BASE)
+
+#define CLK_RATE_13MHZ 13000
+#define CLK_RATE_1MHZ 1000
+#define CLK_RATE_208MHZ 208000
+#define CLK_RATE_48MHZ 48000
+#define CLK_RATE_32KHZ 32
+
+#define PNX4008_UART_CLK CLK_RATE_13MHZ * 1000 /* in MHz */
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/debug-macro.S b/include/asm-arm/arch-pnx4008/debug-macro.S
new file mode 100644
index 0000000..67d18a2
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/debug-macro.S
@@ -0,0 +1,23 @@
+/* linux/include/asm-arm/arch-pnx4008/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+		.macro	addruart,rx
+		mrc	p15, 0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		mov	\rx, #0x00090000
+		addeq	\rx, \rx, #0x40000000
+		addne	\rx, \rx, #0xf4000000
+		.endm
+
+#define UART_SHIFT	2
+#include <asm/hardware/debug-8250.S>
diff --git a/include/asm-arm/arch-pnx4008/dma.h b/include/asm-arm/arch-pnx4008/dma.h
new file mode 100644
index 0000000..3aee120
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/dma.h
@@ -0,0 +1,162 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/dma.h
+ *
+ *  PNX4008 DMA header file
+ *
+ *  Author:	Vitaly Wool
+ *  Copyright:	MontaVista Software Inc. (c) 2005
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#include "platform.h"
+
+#define MAX_DMA_ADDRESS		0xffffffff
+
+#define MAX_DMA_CHANNELS	8
+
+#define DMAC_BASE		IO_ADDRESS(PNX4008_DMA_CONFIG_BASE)
+#define DMAC_INT_STAT		(DMAC_BASE + 0x0000)
+#define DMAC_INT_TC_STAT	(DMAC_BASE + 0x0004)
+#define DMAC_INT_TC_CLEAR	(DMAC_BASE + 0x0008)
+#define DMAC_INT_ERR_STAT	(DMAC_BASE + 0x000c)
+#define DMAC_INT_ERR_CLEAR	(DMAC_BASE + 0x0010)
+#define DMAC_SOFT_SREQ		(DMAC_BASE + 0x0024)
+#define DMAC_CONFIG		(DMAC_BASE + 0x0030)
+#define DMAC_Cx_SRC_ADDR(c)	(DMAC_BASE + 0x0100 + (c) * 0x20)
+#define DMAC_Cx_DEST_ADDR(c)	(DMAC_BASE + 0x0104 + (c) * 0x20)
+#define DMAC_Cx_LLI(c)		(DMAC_BASE + 0x0108 + (c) * 0x20)
+#define DMAC_Cx_CONTROL(c)	(DMAC_BASE + 0x010c + (c) * 0x20)
+#define DMAC_Cx_CONFIG(c)	(DMAC_BASE + 0x0110 + (c) * 0x20)
+
+enum {
+	WIDTH_BYTE = 0,
+	WIDTH_HWORD,
+	WIDTH_WORD
+};
+
+enum {
+	FC_MEM2MEM_DMA,
+	FC_MEM2PER_DMA,
+	FC_PER2MEM_DMA,
+	FC_PER2PER_DMA,
+	FC_PER2PER_DPER,
+	FC_MEM2PER_PER,
+	FC_PER2MEM_PER,
+	FC_PER2PER_SPER
+};
+
+enum {
+	DMA_INT_UNKNOWN = 0,
+	DMA_ERR_INT = 1,
+	DMA_TC_INT = 2,
+};
+
+enum {
+	DMA_BUFFER_ALLOCATED = 1,
+	DMA_HAS_LL = 2,
+};
+
+enum {
+	PER_CAM_DMA_1 = 0,
+	PER_NDF_FLASH = 1,
+	PER_MBX_SLAVE_FIFO = 2,
+	PER_SPI2_REC_XMIT = 3,
+	PER_MS_SD_RX_XMIT = 4,
+	PER_HS_UART_1_XMIT = 5,
+	PER_HS_UART_1_RX = 6,
+	PER_HS_UART_2_XMIT = 7,
+	PER_HS_UART_2_RX = 8,
+	PER_HS_UART_7_XMIT = 9,
+	PER_HS_UART_7_RX = 10,
+	PER_SPI1_REC_XMIT = 11,
+	PER_MLC_NDF_SREC = 12,
+	PER_CAM_DMA_2 = 13,
+	PER_PRNG_INFIFO = 14,
+	PER_PRNG_OUTFIFO = 15,
+};
+
+struct pnx4008_dma_ch_ctrl {
+	int tc_mask;
+	int cacheable;
+	int bufferable;
+	int priv_mode;
+	int di;
+	int si;
+	int dest_ahb1;
+	int src_ahb1;
+	int dwidth;
+	int swidth;
+	int dbsize;
+	int sbsize;
+	int tr_size;
+};
+
+struct pnx4008_dma_ch_config {
+	int halt;
+	int active;
+	int lock;
+	int itc;
+	int ie;
+	int flow_cntrl;
+	int dest_per;
+	int src_per;
+};
+
+struct pnx4008_dma_ll {
+	unsigned long src_addr;
+	unsigned long dest_addr;
+	u32 next_dma;
+	unsigned long ch_ctrl;
+	struct pnx4008_dma_ll *next;
+	int flags;
+	void *alloc_data;
+	int (*free) (void *);
+};
+
+struct pnx4008_dma_config {
+	int is_ll;
+	unsigned long src_addr;
+	unsigned long dest_addr;
+	unsigned long ch_ctrl;
+	unsigned long ch_cfg;
+	struct pnx4008_dma_ll *ll;
+	u32 ll_dma;
+	int flags;
+	void *alloc_data;
+	int (*free) (void *);
+};
+
+extern struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t *);
+extern void pnx4008_free_ll_entry(struct pnx4008_dma_ll *, dma_addr_t);
+extern void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll *);
+
+extern int pnx4008_request_channel(char *, int,
+				   void (*)(int, int, void *, struct pt_regs *),
+				   void *);
+extern void pnx4008_free_channel(int);
+extern int pnx4008_config_dma(int, int, int);
+extern int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl *,
+				    unsigned long *);
+extern int pnx4008_dma_parse_control(unsigned long,
+				     struct pnx4008_dma_ch_ctrl *);
+extern int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config *,
+				   unsigned long *);
+extern int pnx4008_dma_parse_config(unsigned long,
+				    struct pnx4008_dma_ch_config *);
+extern int pnx4008_config_channel(int, struct pnx4008_dma_config *);
+extern int pnx4008_channel_get_config(int, struct pnx4008_dma_config *);
+extern int pnx4008_dma_ch_enable(int);
+extern int pnx4008_dma_ch_disable(int);
+extern int pnx4008_dma_ch_enabled(int);
+extern void pnx4008_dma_split_head_entry(struct pnx4008_dma_config *,
+					 struct pnx4008_dma_ch_ctrl *);
+extern void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll *,
+				       struct pnx4008_dma_ch_ctrl *);
+
+#endif				/* _ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-pnx4008/entry-macro.S b/include/asm-arm/arch-pnx4008/entry-macro.S
new file mode 100644
index 0000000..c1c198e
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/entry-macro.S
@@ -0,0 +1,121 @@
+/*
+ * include/asm-arm/arch-pnx4008/entry-macro.S
+ *
+ * Low-level IRQ helper macros for PNX4008-based platforms
+ *
+ * 2005-2006 (c) MontaVista Software, Inc.
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include "platform.h"
+
+#define IO_BASE         0xF0000000
+#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
+
+#define INTRC_MASK			0x00
+#define INTRC_RAW_STAT			0x04
+#define INTRC_STAT			0x08
+#define INTRC_POLAR			0x0C
+#define INTRC_ACT_TYPE			0x10
+#define INTRC_TYPE			0x14
+
+#define SIC1_BASE_INT   32
+#define SIC2_BASE_INT   64
+
+		.macro	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+/* decode the MIC interrupt numbers */
+		ldr	\base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
+		ldr	\irqstat, [\base, #INTRC_STAT]
+
+		cmp	\irqstat,#1<<16
+		movhs	\irqnr,#16
+		movlo	\irqnr,#0
+		movhs	\irqstat,\irqstat,lsr#16
+		cmp	\irqstat,#1<<8
+		addhs	\irqnr,\irqnr,#8
+		movhs	\irqstat,\irqstat,lsr#8
+		cmp	\irqstat,#1<<4
+		addhs	\irqnr,\irqnr,#4
+		movhs	\irqstat,\irqstat,lsr#4
+		cmp	\irqstat,#1<<2
+		addhs	\irqnr,\irqnr,#2
+		movhs	\irqstat,\irqstat,lsr#2
+		cmp	\irqstat,#1<<1
+		addhs	\irqnr,\irqnr,#1
+
+/* was there an interrupt ? if not then drop out with EQ status */
+		teq	\irqstat,#0
+		beq	1003f
+
+/* and now check for extended IRQ reasons */
+		cmp	\irqnr,#1
+		bls	1003f
+		cmp	\irqnr,#30
+		blo	1002f
+
+/* IRQ 31,30  : High priority cascade IRQ handle */
+/* read the correct SIC */
+/* decoding status after compare : eq is 30 (SIC1) , ne is 31 (SIC2) */
+/* set the base IRQ number */
+		ldreq	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+		moveq  \irqnr,#SIC1_BASE_INT
+		ldrne	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+		movne   \irqnr,#SIC2_BASE_INT
+		ldr	\irqstat, [\base, #INTRC_STAT]
+		ldr	\tmp,	  [\base, #INTRC_TYPE]
+/* and with inverted mask : low priority interrupts  */
+		and	\irqstat,\irqstat,\tmp
+		b	1004f
+
+1003:
+/* IRQ 1,0  : Low priority cascade IRQ handle */
+/* read the correct SIC */
+/* decoding status after compare : eq is 1 (SIC2) , ne is 0 (SIC1)*/
+/* read the correct SIC */
+/* set the base IRQ number  */
+		ldrne	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+		movne   \irqnr,#SIC1_BASE_INT
+		ldreq	\base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+		moveq   \irqnr,#SIC2_BASE_INT
+		ldr	\irqstat, [\base, #INTRC_STAT]
+		ldr	\tmp,	  [\base, #INTRC_TYPE]
+/* and with inverted mask : low priority interrupts  */
+		bic	\irqstat,\irqstat,\tmp
+
+1004:
+
+		cmp	\irqstat,#1<<16
+		addhs	\irqnr,\irqnr,#16
+		movhs	\irqstat,\irqstat,lsr#16
+		cmp	\irqstat,#1<<8
+		addhs	\irqnr,\irqnr,#8
+		movhs	\irqstat,\irqstat,lsr#8
+		cmp	\irqstat,#1<<4
+		addhs	\irqnr,\irqnr,#4
+		movhs	\irqstat,\irqstat,lsr#4
+		cmp	\irqstat,#1<<2
+		addhs	\irqnr,\irqnr,#2
+		movhs	\irqstat,\irqstat,lsr#2
+		cmp	\irqstat,#1<<1
+		addhs	\irqnr,\irqnr,#1
+
+
+/* is irqstat not zero */
+
+1002:
+/* we assert that irqstat is not equal to zero and return ne status if true*/
+		teq	\irqstat,#0
+1003:
+		.endm
+
+
+		.macro	irq_prio_table
+		.endm
+
+
diff --git a/include/asm-arm/arch-pnx4008/gpio.h b/include/asm-arm/arch-pnx4008/gpio.h
new file mode 100644
index 0000000..d01bf83
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/gpio.h
@@ -0,0 +1,241 @@
+/*
+ * include/asm-arm/arch-pnx4008/gpio.h
+ *
+ * PNX4008 GPIO driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips:
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _PNX4008_GPIO_H_
+#define _PNX4008_GPIO_H_
+
+
+/* Block numbers */
+#define GPIO_IN		(0)
+#define GPIO_OUT		(0x100)
+#define GPIO_BID		(0x200)
+#define GPIO_RAM		(0x300)
+#define GPIO_MUX		(0x400)
+
+#define GPIO_TYPE_MASK(K) ((K) & 0x700)
+
+/* INPUT GPIOs */
+/* GPI */
+#define GPI_00		(GPIO_IN | 0)
+#define GPI_01		(GPIO_IN | 1)
+#define GPI_02   	(GPIO_IN | 2)
+#define GPI_03 	 	(GPIO_IN | 3)
+#define GPI_04   	(GPIO_IN | 4)
+#define GPI_05   	(GPIO_IN | 5)
+#define GPI_06   	(GPIO_IN | 6)
+#define GPI_07   	(GPIO_IN | 7)
+#define GPI_08   	(GPIO_IN | 8)
+#define GPI_09   	(GPIO_IN | 9)
+#define U1_RX 		(GPIO_IN | 15)
+#define U2_HTCS 	(GPIO_IN | 16)
+#define U2_RX	 	(GPIO_IN | 17)
+#define U3_RX		(GPIO_IN | 18)
+#define U4_RX		(GPIO_IN | 19)
+#define U5_RX		(GPIO_IN | 20)
+#define U6_IRRX 	(GPIO_IN | 21)
+#define U7_HCTS 	(GPIO_IN | 22)
+#define U7_RX		(GPIO_IN | 23)
+/* MISC IN */
+#define SPI1_DATIN	(GPIO_IN | 25)
+#define DISP_SYNC	(GPIO_IN | 26)
+#define SPI2_DATIN	(GPIO_IN | 27)
+#define GPI_11  	(GPIO_IN | 28)
+
+#define GPIO_IN_MASK   0x1eff83ff
+
+/* OUTPUT GPIOs */
+/* GPO */
+#define GPO_00		(GPIO_OUT | 0)
+#define GPO_01   	(GPIO_OUT | 1)
+#define GPO_02   	(GPIO_OUT | 2)
+#define GPO_03 	 	(GPIO_OUT | 3)
+#define GPO_04   	(GPIO_OUT | 4)
+#define GPO_05   	(GPIO_OUT | 5)
+#define GPO_06   	(GPIO_OUT | 6)
+#define GPO_07   	(GPIO_OUT | 7)
+#define GPO_08		(GPIO_OUT | 8)
+#define GPO_09   	(GPIO_OUT | 9)
+#define GPO_10   	(GPIO_OUT | 10)
+#define GPO_11 	 	(GPIO_OUT | 11)
+#define GPO_12   	(GPIO_OUT | 12)
+#define GPO_13   	(GPIO_OUT | 13)
+#define GPO_14   	(GPIO_OUT | 14)
+#define GPO_15   	(GPIO_OUT | 15)
+#define GPO_16  	(GPIO_OUT | 16)
+#define GPO_17 	 	(GPIO_OUT | 17)
+#define GPO_18   	(GPIO_OUT | 18)
+#define GPO_19   	(GPIO_OUT | 19)
+#define GPO_20   	(GPIO_OUT | 20)
+#define GPO_21   	(GPIO_OUT | 21)
+#define GPO_22   	(GPIO_OUT | 22)
+#define GPO_23   	(GPIO_OUT | 23)
+
+#define GPIO_OUT_MASK   0xffffff
+
+/* BIDIRECTIONAL GPIOs */
+/* RAM pins */
+#define RAM_D19		(GPIO_RAM | 0)
+#define RAM_D20  	(GPIO_RAM | 1)
+#define RAM_D21  	(GPIO_RAM | 2)
+#define RAM_D22 	(GPIO_RAM | 3)
+#define RAM_D23  	(GPIO_RAM | 4)
+#define RAM_D24  	(GPIO_RAM | 5)
+#define RAM_D25  	(GPIO_RAM | 6)
+#define RAM_D26  	(GPIO_RAM | 7)
+#define RAM_D27		(GPIO_RAM | 8)
+#define RAM_D28  	(GPIO_RAM | 9)
+#define RAM_D29  	(GPIO_RAM | 10)
+#define RAM_D30 	(GPIO_RAM | 11)
+#define RAM_D31  	(GPIO_RAM | 12)
+
+#define GPIO_RAM_MASK   0x1fff
+
+/* I/O pins */
+#define GPIO_00  	(GPIO_BID | 25)
+#define GPIO_01 	(GPIO_BID | 26)
+#define GPIO_02  	(GPIO_BID | 27)
+#define GPIO_03  	(GPIO_BID | 28)
+#define GPIO_04 	(GPIO_BID | 29)
+#define GPIO_05  	(GPIO_BID | 30)
+
+#define GPIO_BID_MASK   0x7e000000
+
+/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */
+#define GPIO_SDRAM_SEL 	(GPIO_MUX | 3)
+
+#define GPIO_MUX_MASK   0x8
+
+/* Extraction/assembly macros */
+#define GPIO_BIT_MASK(K) ((K) & 0x1F)
+#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K))
+#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK))
+#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK))
+#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK))
+#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
+#define GPIO_ISIN(K)  ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT   32
+
+#define SE_U7_RX_INT            63
+#define SE_U7_HCTS_INT          62
+#define SE_BT_CLKREQ_INT        61
+#define SE_U6_IRRX_INT          60
+/*59 unused*/
+#define SE_U5_RX_INT            58
+#define SE_GPI_11_INT           57
+#define SE_U3_RX_INT            56
+#define SE_U2_HCTS_INT          55
+#define SE_U2_RX_INT            54
+#define SE_U1_RX_INT            53
+#define SE_DISP_SYNC_INT        52
+/*51 unused*/
+#define SE_SDIO_INT_N           50
+#define SE_MSDIO_START_INT      49
+#define SE_GPI_06_INT           48
+#define SE_GPI_05_INT           47
+#define SE_GPI_04_INT           46
+#define SE_GPI_03_INT           45
+#define SE_GPI_02_INT           44
+#define SE_GPI_01_INT           43
+#define SE_GPI_00_INT           42
+#define SE_SYSCLKEN_PIN_INT     41
+#define SE_SPI1_DATAIN_INT      40
+#define SE_GPI_07_INT           39
+#define SE_SPI2_DATAIN_INT      38
+#define SE_GPI_10_INT           37
+#define SE_GPI_09_INT           36
+#define SE_GPI_08_INT           35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT   0
+
+#define SE_TS_IRQ               31
+#define SE_TS_P_INT             30
+#define SE_TS_AUX_INT           29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT          25
+#define SE_RTC_INT              24
+#define SE_USB_NEED_CLK_INT     23
+#define SE_USB_INT              22
+#define SE_USB_I2C_INT          21
+#define SE_USB_OTG_TIMER_INT    20
+#define SE_USB_OTG_ATX_INT_N    19
+/*18 unused*/
+#define SE_DSP_GPIO4_INT        17
+#define SE_KEY_IRQ              16
+#define SE_DSP_SLAVEPORT_INT    15
+#define SE_DSP_GPIO1_INT        14
+#define SE_DSP_GPIO0_INT        13
+#define SE_DSP_AHB_INT          12
+/*11-6 unused*/
+#define SE_GPIO_05_INT          5
+#define SE_GPIO_04_INT          4
+#define SE_GPIO_03_INT          3
+#define SE_GPIO_02_INT          2
+#define SE_GPIO_01_INT          1
+#define SE_GPIO_00_INT          0
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern int pnx4008_gpio_register_pin(unsigned short pin);
+extern int pnx4008_gpio_unregister_pin(unsigned short pin);
+extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
+extern int pnx4008_gpio_write_pin(unsigned short pin, int output);
+extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
+extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
+extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
+
+static inline void start_int_umask(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
+		     START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_mask(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
+		     ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
+}
+
+static inline void start_int_ack(u8 irq)
+{
+	__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
+}
+
+static inline void start_int_set_falling_edge(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
+		     ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+static inline void start_int_set_rising_edge(u8 irq)
+{
+	__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
+		     START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
+}
+
+#endif				/* _PNX4008_GPIO_H_ */
diff --git a/include/asm-arm/arch-pnx4008/hardware.h b/include/asm-arm/arch-pnx4008/hardware.h
new file mode 100644
index 0000000..a441039
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/hardware.h
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/hardware.h
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#include <asm/arch/platform.h>
+
+/* Start of virtual addresses for IO devices */
+#define IO_BASE         0xF0000000
+
+/* This macro relies on fact that for all HW i/o addresses bits 20-23 are 0 */
+#define IO_ADDRESS(x)  (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/io.h b/include/asm-arm/arch-pnx4008/io.h
new file mode 100644
index 0000000..29ee439
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/io.h
@@ -0,0 +1,21 @@
+
+/*
+ *  include/asm-arm/arch-pnx4008/io.h
+ *
+ * Author: Dmitry Chigirev <chigirev@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)			((void __iomem *)(a))
+#define __mem_pci(a)		(a)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/irq.h b/include/asm-arm/arch-pnx4008/irq.h
new file mode 100644
index 0000000..fabff5d
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/irq.h
@@ -0,0 +1,42 @@
+/*
+ * include/asm-arm/arch-pnx4008/irq.h
+ *
+ * PNX4008 IRQ controller driver - header file
+ * this one is used in entry-arnv.S as well so it cannot contain C code
+ *
+ * Copyright (c) 2005 Philips Semiconductors
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+#ifndef __PNX4008_IRQ_H__
+#define __PNX4008_IRQ_H__
+
+#define MIC_VA_BASE             IO_ADDRESS(PNX4008_INTCTRLMIC_BASE)
+#define SIC1_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE)
+#define SIC2_VA_BASE            IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE)
+
+/* Manual: Chapter 20, page 195 */
+
+#define INTC_BIT(irq) (1<< ((irq) & 0x1F))
+
+#define INTC_ER(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x0 + (((irq)&(0x3<<5))<<9)))
+#define INTC_RSR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x4 + (((irq)&(0x3<<5))<<9)))
+#define INTC_SR(irq)    IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x8 + (((irq)&(0x3<<5))<<9)))
+#define INTC_APR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0xC + (((irq)&(0x3<<5))<<9)))
+#define INTC_ATR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x10 + (((irq)&(0x3<<5))<<9)))
+#define INTC_ITR(irq)   IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x14 + (((irq)&(0x3<<5))<<9)))
+
+#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
+
+#define START_INT_ER_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_RSR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_SR_REG(irq)     IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
+#define START_INT_APR_REG(irq)    IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
+
+extern void __init pnx4008_init_irq(void);
+
+#endif /* __PNX4008_IRQ_H__ */
diff --git a/include/asm-arm/arch-pnx4008/irqs.h b/include/asm-arm/arch-pnx4008/irqs.h
new file mode 100644
index 0000000..13ec7ed
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/irqs.h
@@ -0,0 +1,215 @@
+/*
+ * include/asm-arm/arch-pnx4008/irqs.h
+ *
+ * PNX4008 IRQ controller driver - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __PNX4008_IRQS_h__
+#define __PNX4008_IRQS_h__
+
+#define NR_IRQS         96
+
+/*Manual: table 259, page 199*/
+
+/*SUB2 Interrupt Routing (SIC2)*/
+
+#define SIC2_BASE_INT   64
+
+#define CLK_SWITCH_ARM_INT 95	/*manual: Clkswitch ARM  */
+#define CLK_SWITCH_DSP_INT 94	/*manual: ClkSwitch DSP  */
+#define CLK_SWITCH_AUD_INT 93	/*manual: Clkswitch AUD  */
+#define GPI_06_INT         92
+#define GPI_05_INT         91
+#define GPI_04_INT         90
+#define GPI_03_INT         89
+#define GPI_02_INT         88
+#define GPI_01_INT         87
+#define GPI_00_INT         86
+#define BT_CLKREQ_INT      85
+#define SPI1_DATIN_INT     84
+#define U5_RX_INT          83
+#define SDIO_INT_N         82
+#define CAM_HS_INT         81
+#define CAM_VS_INT         80
+#define GPI_07_INT         79
+#define DISP_SYNC_INT      78
+#define DSP_INT8           77
+#define U7_HCTS_INT        76
+#define GPI_10_INT         75
+#define GPI_09_INT         74
+#define GPI_08_INT         73
+#define DSP_INT7           72
+#define U2_HCTS_INT        71
+#define SPI2_DATIN_INT     70
+#define GPIO_05_INT        69
+#define GPIO_04_INT        68
+#define GPIO_03_INT        67
+#define GPIO_02_INT        66
+#define GPIO_01_INT        65
+#define GPIO_00_INT        64
+
+/*Manual: table 258, page 198*/
+
+/*SUB1 Interrupt Routing (SIC1)*/
+
+#define SIC1_BASE_INT   32
+
+#define USB_I2C_INT        63
+#define USB_DEV_HP_INT     62
+#define USB_DEV_LP_INT     61
+#define USB_DEV_DMA_INT    60
+#define USB_HOST_INT       59
+#define USB_OTG_ATX_INT_N  58
+#define USB_OTG_TIMER_INT  57
+#define SW_INT             56
+#define SPI1_INT           55
+#define KEY_IRQ            54
+#define DSP_M_INT          53
+#define RTC_INT            52
+#define I2C_1_INT          51
+#define I2C_2_INT          50
+#define PLL1_LOCK_INT      49
+#define PLL2_LOCK_INT      48
+#define PLL3_LOCK_INT      47
+#define PLL4_LOCK_INT      46
+#define PLL5_LOCK_INT      45
+#define SPI2_INT           44
+#define DSP_INT1           43
+#define DSP_INT2           42
+#define DSP_TDM_INT2       41
+#define TS_AUX_INT         40
+#define TS_IRQ             39
+#define TS_P_INT           38
+#define UOUT1_TO_PAD_INT   37
+#define GPI_11_INT         36
+#define DSP_INT4           35
+#define JTAG_COMM_RX_INT   34
+#define JTAG_COMM_TX_INT   33
+#define DSP_INT3           32
+
+/*Manual: table 257, page 197*/
+
+/*MAIN Interrupt Routing*/
+
+#define MAIN_BASE_INT   0
+
+#define SUB2_FIQ_N         31	/*active low */
+#define SUB1_FIQ_N         30	/*active low */
+#define JPEG_INT           29
+#define DMA_INT            28
+#define MSTIMER_INT        27
+#define IIR1_INT           26
+#define IIR2_INT           25
+#define IIR7_INT           24
+#define DSP_TDM_INT0       23
+#define DSP_TDM_INT1       22
+#define DSP_P_INT          21
+#define DSP_INT0           20
+#define DUM_INT            19
+#define UOUT0_TO_PAD_INT   18
+#define MP4_ENC_INT        17
+#define MP4_DEC_INT        16
+#define SD0_INT            15
+#define MBX_INT            14
+#define SD1_INT            13
+#define MS_INT_N           12
+#define FLASH_INT          11 /*NAND*/
+#define IIR6_INT           10
+#define IIR5_INT           9
+#define IIR4_INT           8
+#define IIR3_INT           7
+#define WATCH_INT          6
+#define HSTIMER_INT        5
+#define ARCH_TIMER_IRQ     HSTIMER_INT
+#define CAM_INT            4
+#define PRNG_INT           3
+#define CRYPTO_INT         2
+#define SUB2_IRQ_N         1	/*active low */
+#define SUB1_IRQ_N         0	/*active low */
+
+#define PNX4008_IRQ_TYPES \
+{                                           /*IRQ #'s: */         \
+IRQT_LOW,  IRQT_LOW,  IRQT_LOW,  IRQT_HIGH, /*  0, 1, 2, 3 */     \
+IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  4, 5, 6, 7 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /*  8, 9,10,11 */     \
+IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 12,13,14,15 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 16,17,18,19 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 20,21,22,23 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 24,25,26,27 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 28,29,30,31 */     \
+IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, IRQT_HIGH, /* 32,33,34,35 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_FALLING, IRQT_HIGH, /* 36,37,38,39 */  \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 40,41,42,43 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 44,45,46,47 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_LOW,  /* 48,49,50,51 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 52,53,54,55 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_LOW,  IRQT_HIGH, /* 56,57,58,59 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 60,61,62,63 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 64,65,66,67 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 68,69,70,71 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 72,73,74,75 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 76,77,78,79 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 80,81,82,83 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 84,85,86,87 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 88,89,90,91 */     \
+IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 92,93,94,95 */     \
+}
+
+/* Start Enable Pin Interrupts - table 58 page 66 */
+
+#define SE_PIN_BASE_INT   32
+
+#define SE_U7_RX_INT            63
+#define SE_U7_HCTS_INT          62
+#define SE_BT_CLKREQ_INT        61
+#define SE_U6_IRRX_INT          60
+/*59 unused*/
+#define SE_U5_RX_INT            58
+#define SE_GPI_11_INT           57
+#define SE_U3_RX_INT            56
+#define SE_U2_HCTS_INT          55
+#define SE_U2_RX_INT            54
+#define SE_U1_RX_INT            53
+#define SE_DISP_SYNC_INT        52
+/*51 unused*/
+#define SE_SDIO_INT_N           50
+#define SE_MSDIO_START_INT      49
+#define SE_GPI_06_INT           48
+#define SE_GPI_05_INT           47
+#define SE_GPI_04_INT           46
+#define SE_GPI_03_INT           45
+#define SE_GPI_02_INT           44
+#define SE_GPI_01_INT           43
+#define SE_GPI_00_INT           42
+#define SE_SYSCLKEN_PIN_INT     41
+#define SE_SPI1_DATAIN_INT      40
+#define SE_GPI_07_INT           39
+#define SE_SPI2_DATAIN_INT      38
+#define SE_GPI_10_INT           37
+#define SE_GPI_09_INT           36
+#define SE_GPI_08_INT           35
+/*34-32 unused*/
+
+/* Start Enable Internal Interrupts - table 57 page 65 */
+
+#define SE_INT_BASE_INT   0
+
+#define SE_TS_IRQ               31
+#define SE_TS_P_INT             30
+#define SE_TS_AUX_INT           29
+/*27-28 unused*/
+#define SE_USB_AHB_NEED_CLK_INT 26
+#define SE_MSTIMER_INT          25
+#define SE_RTC_INT              24
+#define SE_USB_NEED_CLK_INT     23
+#define SE_USB_INT              22
+#define SE_USB_I2C_INT          21
+#define SE_USB_OTG_TIMER_INT    20
+
+#endif /* __PNX4008_IRQS_h__ */
diff --git a/include/asm-arm/arch-pnx4008/memory.h b/include/asm-arm/arch-pnx4008/memory.h
new file mode 100644
index 0000000..0d8268a
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/memory.h
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/memory.h
+ *
+ * Copyright (c) 2005 Philips Semiconductors
+ * Copyright (c) 2005 MontaVista Software, Inc.
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET     (0x80000000)
+
+#define __virt_to_bus(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __bus_to_virt(x) ((x) + PAGE_OFFSET - PHYS_OFFSET)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/param.h b/include/asm-arm/arch-pnx4008/param.h
new file mode 100644
index 0000000..95d5f54
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/param.h
@@ -0,0 +1,21 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/param.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define HZ 100
diff --git a/include/asm-arm/arch-pnx4008/platform.h b/include/asm-arm/arch-pnx4008/platform.h
new file mode 100644
index 0000000..485a365
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/platform.h
@@ -0,0 +1,69 @@
+/*
+ * include/asm-arm/arch-pnx4008/platfrom.h
+ *
+ * PNX4008 Base addresses - header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * Based on reference code received from Philips:
+ * Copyright (C) 2003 Philips Semiconductors
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+
+#ifndef __ASM_ARCH_PLATFORM_H__
+#define __ASM_ARCH_PLATFORM_H__
+
+#define PNX4008_IRAM_BASE		0x08000000
+#define PNX4008_IRAM_SIZE		0x00010000
+#define PNX4008_YUV_SLAVE_BASE		0x10000000
+#define PNX4008_DUM_SLAVE_BASE		0x18000000
+#define PNX4008_NDF_FLASH_BASE		0x20020000
+#define PNX4008_SPI1_BASE		0x20088000
+#define PNX4008_SPI2_BASE		0x20090000
+#define PNX4008_SD_CONFIG_BASE		0x20098000
+#define PNX4008_FLASH_DATA		0x200B0000
+#define PNX4008_MLC_FLASH_BASE		0x200B8000
+#define PNX4008_JPEG_CONFIG_BASE	0x300A0000
+#define PNX4008_DMA_CONFIG_BASE		0x31000000
+#define PNX4008_USB_CONFIG_BASE		0x31020000
+#define PNX4008_SDRAM_CFG_BASE		0x31080000
+#define PNX4008_AHB2FAB_BASE		0x40000000
+#define PNX4008_PWRMAN_BASE		0x40004000
+#define PNX4008_INTCTRLMIC_BASE		0x40008000
+#define PNX4008_INTCTRLSIC1_BASE	0x4000C000
+#define PNX4008_INTCTRLSIC2_BASE	0x40010000
+#define PNX4008_HSUART1_BASE		0x40014000
+#define PNX4008_HSUART2_BASE		0x40018000
+#define PNX4008_HSUART7_BASE		0x4001C000
+#define PNX4008_RTC_BASE		0x40024000
+#define PNX4008_PIO_BASE		0x40028000
+#define PNX4008_MSTIMER_BASE		0x40034000
+#define PNX4008_HSTIMER_BASE		0x40038000
+#define PNX4008_WDOG_BASE		0x4003C000
+#define PNX4008_DEBUG_BASE		0x40040000
+#define PNX4008_TOUCH1_BASE		0x40048000
+#define PNX4008_KEYSCAN_BASE		0x40050000
+#define PNX4008_UARTCTRL_BASE		0x40054000
+#define PNX4008_PWM_BASE		0x4005C000
+#define PNX4008_UART3_BASE		0x40080000
+#define PNX4008_UART4_BASE		0x40088000
+#define PNX4008_UART5_BASE		0x40090000
+#define PNX4008_UART6_BASE		0x40098000
+#define PNX4008_I2C1_BASE		0x400A0000
+#define PNX4008_I2C2_BASE		0x400A8000
+#define PNX4008_MAGICGATE_BASE		0x400B0000
+#define PNX4008_DUMCONF_BASE		0x400B8000
+#define PNX4008_DUM_MAINCFG_BASE       	0x400BC000
+#define PNX4008_DSP_BASE		0x400C0000
+#define PNX4008_PROFCOUNTER_BASE	0x400C8000
+#define PNX4008_CRYPTO_BASE		0x400D0000
+#define PNX4008_CAMIFCONF_BASE		0x400D8000
+#define PNX4008_YUV2RGB_BASE		0x400E0000
+#define PNX4008_AUDIOCONFIG_BASE	0x400E8000
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/pm.h b/include/asm-arm/arch-pnx4008/pm.h
new file mode 100644
index 0000000..bac1634c
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/pm.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-arm/arch-pnx4008/pm.h
+ *
+ * PNX4008 Power Management Routiness - header file
+ *
+ * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARCH_PNX4008_PM_H
+#define __ASM_ARCH_PNX4008_PM_H
+
+#ifndef __ASSEMBLER__
+#include "irq.h"
+#include "irqs.h"
+#include "clock.h"
+
+extern void pnx4008_pm_idle(void);
+extern void pnx4008_pm_suspend(void);
+extern unsigned int pnx4008_cpu_suspend_sz;
+extern void pnx4008_cpu_suspend(void);
+extern unsigned int pnx4008_cpu_standby_sz;
+extern void pnx4008_cpu_standby(void);
+
+extern int pnx4008_startup_pll(struct clk *);
+extern int pnx4008_shutdown_pll(struct clk *);
+
+#endif				/* ASSEMBLER */
+#endif				/* __ASM_ARCH_PNX4008_PM_H */
diff --git a/include/asm-arm/arch-pnx4008/system.h b/include/asm-arm/arch-pnx4008/system.h
new file mode 100644
index 0000000..6e3da70
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/system.h
@@ -0,0 +1,38 @@
+/*
+ * linux/include/asm-arm/arch-pnx4008/system.h
+ *
+ * Copyright (C) 2003 Philips Semiconductors
+ * Copyright (C) 2005 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/arch/platform.h>
+
+static void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	cpu_reset(0);
+}
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/timex.h b/include/asm-arm/arch-pnx4008/timex.h
new file mode 100644
index 0000000..ee470a3
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/timex.h
@@ -0,0 +1,73 @@
+/*
+ * include/asm-arm/arch-pnx4008/timex.h
+ *
+ * PNX4008 timers header file
+ *
+ * Author: Dmitry Chigirev <source@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __PNX4008_TIMEX_H
+#define __PNX4008_TIMEX_H
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#define CLOCK_TICK_RATE		1000000
+
+#define TICKS2USECS(x)	(x)
+
+/* MilliSecond Timer - Chapter 21 Page 202 */
+
+#define MSTIM_INT     IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0))
+#define MSTIM_CTRL    IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4))
+#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8))
+#define MSTIM_MCTRL   IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14))
+#define MSTIM_MATCH0  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18))
+#define MSTIM_MATCH1  IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c))
+
+/* High Speed Timer - Chpater 22, Page 205 */
+
+#define HSTIM_INT     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0))
+#define HSTIM_CTRL    IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4))
+#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8))
+#define HSTIM_PMATCH  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC))
+#define HSTIM_PCOUNT  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10))
+#define HSTIM_MCTRL   IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14))
+#define HSTIM_MATCH0  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18))
+#define HSTIM_MATCH1  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c))
+#define HSTIM_MATCH2  IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20))
+#define HSTIM_CCR     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28))
+#define HSTIM_CR0     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C))
+#define HSTIM_CR1     IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30))
+
+/* IMPORTANT: both timers are UPCOUNTING */
+
+/* xSTIM_MCTRL bit definitions */
+#define MR0_INT        1
+#define RESET_COUNT0   (1<<1)
+#define STOP_COUNT0    (1<<2)
+#define MR1_INT        (1<<3)
+#define RESET_COUNT1   (1<<4)
+#define STOP_COUNT1    (1<<5)
+#define MR2_INT        (1<<6)
+#define RESET_COUNT2   (1<<7)
+#define STOP_COUNT2    (1<<8)
+
+/* xSTIM_CTRL bit definitions */
+#define COUNT_ENAB     1
+#define RESET_COUNT    (1<<1)
+#define DEBUG_EN       (1<<2)
+
+/* xSTIM_INT bit definitions */
+#define MATCH0_INT     1
+#define MATCH1_INT     (1<<1)
+#define MATCH2_INT     (1<<2)
+#define RTC_TICK0      (1<<4)
+#define RTC_TICK1      (1<<5)
+
+#endif
diff --git a/include/asm-arm/arch-pnx4008/uncompress.h b/include/asm-arm/arch-pnx4008/uncompress.h
new file mode 100644
index 0000000..8fa4d24
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/uncompress.h
@@ -0,0 +1,46 @@
+/*
+ *  linux/include/asm-arm/arch-pnx4008/uncompress.h
+ *
+ *  Copyright (C) 1999 ARM Limited
+ *  Copyright (C) 2006 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define UART5_BASE 0x40090000
+
+#define UART5_DR    (*(volatile unsigned char *) (UART5_BASE))
+#define UART5_FR    (*(volatile unsigned char *) (UART5_BASE + 18))
+
+static __inline__ void putc(char c)
+{
+	while (UART5_FR & (1 << 5))
+		barrier();
+
+	UART5_DR = c;
+}
+
+/*
+ * This does not append a newline
+ */
+static inline void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/include/asm-arm/arch-pnx4008/vmalloc.h b/include/asm-arm/arch-pnx4008/vmalloc.h
new file mode 100644
index 0000000..140d925
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/vmalloc.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-arm/arch-pnx4008/vmalloc.h
+ *
+ * Author: Vitaly Wool <source@mvista.com>
+ *
+ * 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff --git a/include/asm-arm/arch-pxa/idp.h b/include/asm-arm/arch-pxa/idp.h
index e7ef497..b695253 100644
--- a/include/asm-arm/arch-pxa/idp.h
+++ b/include/asm-arm/arch-pxa/idp.h
@@ -15,7 +15,6 @@
  *             Changes for 2.6 kernel.
  */
 
-#include <linux/config.h>
 
 /*
  * Note: this file must be safe to include in assembly files
diff --git a/include/asm-arm/arch-pxa/io.h b/include/asm-arm/arch-pxa/io.h
index eb2dd58..7f8d817 100644
--- a/include/asm-arm/arch-pxa/io.h
+++ b/include/asm-arm/arch-pxa/io.h
@@ -16,6 +16,5 @@
  */
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #endif
diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
index 67af238a..f3bc70e 100644
--- a/include/asm-arm/arch-pxa/irqs.h
+++ b/include/asm-arm/arch-pxa/irqs.h
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PXA27x
 #define PXA_IRQ_SKIP	0
diff --git a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h
index 6b5ac51..4d6a403 100644
--- a/include/asm-arm/arch-pxa/poodle.h
+++ b/include/asm-arm/arch-pxa/poodle.h
@@ -31,6 +31,7 @@
 #define POODLE_GPIO_CF_CD		(14)
 #define POODLE_GPIO_CF_STSCHG		(14)
 #define POODLE_GPIO_SD_PWR		(33)
+#define POODLE_GPIO_SD_PWR1		(3)
 #define POODLE_GPIO_nSD_CLK		(6)
 #define POODLE_GPIO_nSD_WP		(7)
 #define POODLE_GPIO_nSD_INT		(8)
@@ -42,6 +43,7 @@
 #define POODLE_GPIO_BYPASS_ON		(36)
 #define POODLE_GPIO_CHRG_ON		(38)
 #define POODLE_GPIO_CHRG_FULL		(16)
+#define POODLE_GPIO_DISCHARGE_ON        (42) /* Enable battery discharge */
 
 /* PXA GPIOs */
 #define POODLE_IRQ_GPIO_ON_KEY		IRQ_GPIO(0)
@@ -68,4 +70,6 @@
 #define POODLE_SCOOP_IO_DIR	( POODLE_SCOOP_VPEN | POODLE_SCOOP_HS_OUT )
 #define POODLE_SCOOP_IO_OUT	( 0 )
 
+extern struct platform_device poodle_locomo_device;
+
 #endif /* __ASM_ARCH_POODLE_H  */
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index c8f53a7..9f83f4a 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -13,7 +13,6 @@
 #ifndef __PXA_REGS_H
 #define __PXA_REGS_H
 
-#include <linux/config.h>
 
 /*
  * PXA Chip selects
@@ -1626,7 +1625,7 @@
 #define SSCR0_RIM	(1 << 22)	/* Receive FIFO overrrun interrupt mask */
 #define SSCR0_TUM	(1 << 23)	/* Transmit FIFO underrun interrupt mask */
 #define SSCR0_FRDC	(0x07000000)	/* Frame rate divider control (mask) */
-#define SSCR0_SlotsPerFrm(c) ((x) - 1)	/* Time slots per frame [1..8] */
+#define SSCR0_SlotsPerFrm(x) ((x) - 1)	/* Time slots per frame [1..8] */
 #define SSCR0_ADC	(1 << 30)	/* Audio clock select */
 #define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
 #endif
@@ -1707,6 +1706,10 @@
 #if defined (CONFIG_PXA27x)
 #define SSTO_P1		__REG(0x41000028)  /* SSP Port 1 Time Out Register */
 #define SSPSP_P1	__REG(0x4100002C)  /* SSP Port 1 Programmable Serial Protocol */
+#define SSTSA_P1	__REG(0x41000030)  /* SSP Port 1 Tx Timeslot Active */
+#define SSRSA_P1	__REG(0x41000034)  /* SSP Port 1 Rx Timeslot Active */
+#define SSTSS_P1	__REG(0x41000038)  /* SSP Port 1 Timeslot Status */
+#define SSACD_P1	__REG(0x4100003C)  /* SSP Port 1 Audio Clock Divider */
 #define SSCR0_P2	__REG(0x41700000)  /* SSP Port 2 Control Register 0 */
 #define SSCR1_P2	__REG(0x41700004)  /* SSP Port 2 Control Register 1 */
 #define SSSR_P2		__REG(0x41700008)  /* SSP Port 2 Status Register */
@@ -1714,6 +1717,10 @@
 #define SSDR_P2		__REG(0x41700010)  /* (Write / Read) SSP Port 2 Data Write Register/SSP Data Read Register */
 #define SSTO_P2		__REG(0x41700028)  /* SSP Port 2 Time Out Register */
 #define SSPSP_P2	__REG(0x4170002C)  /* SSP Port 2 Programmable Serial Protocol */
+#define SSTSA_P2	__REG(0x41700030)  /* SSP Port 2 Tx Timeslot Active */
+#define SSRSA_P2	__REG(0x41700034)  /* SSP Port 2 Rx Timeslot Active */
+#define SSTSS_P2	__REG(0x41700038)  /* SSP Port 2 Timeslot Status */
+#define SSACD_P2	__REG(0x4170003C)  /* SSP Port 2 Audio Clock Divider */
 #define SSCR0_P3	__REG(0x41900000)  /* SSP Port 3 Control Register 0 */
 #define SSCR1_P3	__REG(0x41900004)  /* SSP Port 3 Control Register 1 */
 #define SSSR_P3		__REG(0x41900008)  /* SSP Port 3 Status Register */
@@ -1721,6 +1728,10 @@
 #define SSDR_P3		__REG(0x41900010)  /* (Write / Read) SSP Port 3 Data Write Register/SSP Data Read Register */
 #define SSTO_P3		__REG(0x41900028)  /* SSP Port 3 Time Out Register */
 #define SSPSP_P3	__REG(0x4190002C)  /* SSP Port 3 Programmable Serial Protocol */
+#define SSTSA_P3	__REG(0x41900030)  /* SSP Port 3 Tx Timeslot Active */
+#define SSRSA_P3	__REG(0x41900034)  /* SSP Port 3 Rx Timeslot Active */
+#define SSTSS_P3	__REG(0x41900038)  /* SSP Port 3 Timeslot Status */
+#define SSACD_P3	__REG(0x4190003C)  /* SSP Port 3 Audio Clock Divider */
 #else /* PXA255 (only port 2) and PXA26x ports*/
 #define SSTO_P1		__REG(0x41000028)  /* SSP Port 1 Time Out Register */
 #define SSPSP_P1	__REG(0x4100002C)  /* SSP Port 1 Programmable Serial Protocol */
@@ -1747,6 +1758,10 @@
 #define SSDR_P(x) (*(((x) == 1) ? &SSDR_P1 : ((x) == 2) ? &SSDR_P2 : ((x) == 3) ? &SSDR_P3 : NULL))
 #define SSTO_P(x) (*(((x) == 1) ? &SSTO_P1 : ((x) == 2) ? &SSTO_P2 : ((x) == 3) ? &SSTO_P3 : NULL))
 #define SSPSP_P(x) (*(((x) == 1) ? &SSPSP_P1 : ((x) == 2) ? &SSPSP_P2 : ((x) == 3) ? &SSPSP_P3 : NULL))
+#define SSTSA_P(x) (*(((x) == 1) ? &SSTSA_P1 : ((x) == 2) ? &SSTSA_P2 : ((x) == 3) ? &SSTSA_P3 : NULL))
+#define SSRSA_P(x) (*(((x) == 1) ? &SSRSA_P1 : ((x) == 2) ? &SSRSA_P2 : ((x) == 3) ? &SSRSA_P3 : NULL))
+#define SSTSS_P(x) (*(((x) == 1) ? &SSTSS_P1 : ((x) == 2) ? &SSTSS_P2 : ((x) == 3) ? &SSTSS_P3 : NULL))
+#define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL))
 
 /*
  * MultiMediaCard (MMC) controller
diff --git a/include/asm-arm/arch-pxa/system.h b/include/asm-arm/arch-pxa/system.h
index 840a46b..1d56a3e 100644
--- a/include/asm-arm/arch-pxa/system.h
+++ b/include/asm-arm/arch-pxa/system.h
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <asm/proc-fns.h>
 #include "hardware.h"
 #include "pxa-regs.h"
 
diff --git a/include/asm-arm/arch-pxa/timex.h b/include/asm-arm/arch-pxa/timex.h
index aa125ec..2473bb5 100644
--- a/include/asm-arm/arch-pxa/timex.h
+++ b/include/asm-arm/arch-pxa/timex.h
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PXA25x)
 /* PXA250/210 timer base */
diff --git a/include/asm-arm/arch-realview/io.h b/include/asm-arm/arch-realview/io.h
index d444a68..c70f1df 100644
--- a/include/asm-arm/arch-realview/io.h
+++ b/include/asm-arm/arch-realview/io.h
@@ -29,6 +29,5 @@
 
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #endif
diff --git a/include/asm-arm/arch-realview/smp.h b/include/asm-arm/arch-realview/smp.h
index fc87783..515819e 100644
--- a/include/asm-arm/arch-realview/smp.h
+++ b/include/asm-arm/arch-realview/smp.h
@@ -1,7 +1,6 @@
 #ifndef ASMARM_ARCH_SMP_H
 #define ASMARM_ARCH_SMP_H
 
-#include <linux/config.h>
 
 #include <asm/hardware/gic.h>
 
diff --git a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S
index 5f8223e..b7d15d1 100644
--- a/include/asm-arm/arch-s3c2410/debug-macro.S
+++ b/include/asm-arm/arch-s3c2410/debug-macro.S
@@ -33,7 +33,7 @@
 		.endm
 
 		.macro	senduart,rd,rx
-		str	\rd, [\rx, # S3C2410_UTXH ]
+		strb 	\rd, [\rx, # S3C2410_UTXH ]
 		.endm
 
 		.macro	busyuart, rd, rx
@@ -42,6 +42,12 @@
 		beq	1001f				@
 		@ FIFO enabled...
 1003:
+		@ check for arm920 vs arm926. currently assume all arm926
+		@ devices have an 64 byte FIFO identical to the s3c2440
+		mrc	p15, 0, \rd, c0, c0
+		and	\rd, \rd, #0xff0
+		teq	\rd, #0x260
+		beq	1004f
 		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1
 		addeq	\rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART)
@@ -50,7 +56,7 @@
 		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
 		and	\rd, \rd, #0x00ff0000
 		teq	\rd, #0x00440000		@ is it 2440?
-
+1004:
 		ldr	\rd, [ \rx, # S3C2410_UFSTAT ]
 		moveq	\rd, \rd, lsr #SHIFT_2440TXF
 		tst	\rd, #S3C2410_UFSTAT_TXFULL
diff --git a/include/asm-arm/arch-s3c2410/dma.h b/include/asm-arm/arch-s3c2410/dma.h
index b011e14..72964f9 100644
--- a/include/asm-arm/arch-s3c2410/dma.h
+++ b/include/asm-arm/arch-s3c2410/dma.h
@@ -18,7 +18,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H __FILE__
 
-#include <linux/config.h>
 #include <linux/sysdev.h>
 #include "hardware.h"
 
diff --git a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
index 894c35c..e09a6b8 100644
--- a/include/asm-arm/arch-s3c2410/entry-macro.S
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S
@@ -18,8 +18,6 @@
 
 #define INTPND		(0x10)
 #define INTOFFSET	(0x14)
-#define EXTINTPEND	(0xa8)
-#define EXTINTMASK	(0xa4)
 
 #include <asm/hardware.h>
 #include <asm/arch/irqs.h>
@@ -28,37 +26,23 @@
 
 		mov	\base, #S3C24XX_VA_IRQ
 
-		ldr	\irqstat, [ \base, #INTPND]
-		bics	\irqnr, \irqstat, #3<<4		@@ only an GPIO IRQ
-		beq	2000f
-
 		@@ try the interrupt offset register, since it is there
 
+		ldr	\irqstat, [ \base, #INTPND ]
+		teq	\irqstat, #0
+		beq	1002f
 		ldr	\irqnr, [ \base, #INTOFFSET ]
 		mov	\tmp, #1
 		tst	\irqstat, \tmp, lsl \irqnr
-		addne	\irqnr, \irqnr, #IRQ_EINT0
 		bne	1001f
 
 		@@ the number specified is not a valid irq, so try
 		@@ and work it out for ourselves
 
-		mov	\irqnr, #IRQ_EINT0		@@ start here
-		b	3000f
-
-2000:
-		@@ load the GPIO interrupt register, and check it
-
-		add	\tmp, \base, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
-		ldr	\irqstat, [ \tmp, # EXTINTPEND ]
-		ldr	\irqnr,   [ \tmp, # EXTINTMASK ]
-		bics	\irqstat, \irqstat, \irqnr
-		beq	1001f
-
-		mov	\irqnr, #(IRQ_EINT4 - 4)
+		mov	\irqnr, #0		@@ start here
 
 		@@ work out which irq (if any) we got
-3000:
+
 		movs	\tmp, \irqstat, lsl#16
 		addeq	\irqnr, \irqnr, #16
 		moveq	\irqstat, \irqstat, lsr#16
@@ -75,9 +59,9 @@
 		addeq	\irqnr, \irqnr, #1
 
 		@@ we have the value
-		movs	\irqnr, \irqnr
-
 1001:
+		adds	\irqnr, \irqnr, #IRQ_EINT0
+1002:
 		@@ exit here, Z flag unset if IRQ
 
 	.endm
diff --git a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
index c380d26..fae2766 100644
--- a/include/asm-arm/arch-s3c2410/map.h
+++ b/include/asm-arm/arch-s3c2410/map.h
@@ -126,9 +126,18 @@
 #define S3C24XX_SZ_IIS	   SZ_1M
 
 /* GPIO ports */
-#define S3C24XX_VA_GPIO	   S3C2410_ADDR(0x00E00000)
+
+/* the calculation for the VA of this must ensure that
+ * it is the same distance apart from the UART in the
+ * phsyical address space, as the initial mapping for the IO
+ * is done as a 1:1 maping. This puts it (currently) at
+ * 0xF6800000, which is not in the way of any current mapping
+ * by the base system.
+*/
+
 #define S3C2400_PA_GPIO	   (0x15600000)
 #define S3C2410_PA_GPIO	   (0x56000000)
+#define S3C24XX_VA_GPIO	   ((S3C2410_PA_GPIO - S3C24XX_PA_UART) + S3C24XX_VA_UART)
 #define S3C24XX_SZ_GPIO	   SZ_1M
 
 /* RTC */
@@ -227,4 +236,20 @@
 #define S3C24XX_PA_SPI      S3C2410_PA_SPI
 #endif
 
+/* deal with the registers that move under the 2412/2413 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+#ifndef __ASSEMBLY__
+extern void __iomem *s3c24xx_va_gpio2;
+#endif
+#ifdef CONFIG_CPU_S3C2412_ONLY
+#define S3C24XX_VA_GPIO2 (S3C24XX_VA_GPIO + 0x10)
+#else
+#define S3C24XX_VA_GPIO2 s3c24xx_va_gpio2
+#endif
+#else
+#define s3c24xx_va_gpio2 S3C24XX_VA_GPIO
+#define S3C24XX_VA_GPIO2 S3C24XX_VA_GPIO
+#endif
+
 #endif /* __ASM_ARCH_MAP_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
index 3436070..a7c61fe 100644
--- a/include/asm-arm/arch-s3c2410/regs-clock.h
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h
@@ -1,6 +1,6 @@
 /* linux/include/asm/arch-s3c2410/regs-clock.h
  *
- * Copyright (c) 2003,2004,2005 Simtec Electronics <linux@simtec.co.uk>
+ * Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk>
  *		      http://armlinux.simtec.co.uk/
  *
  * This program is free software; you can redistribute it and/or modify
@@ -114,7 +114,7 @@
 
 #endif /* __ASSEMBLY__ */
 
-#ifdef CONFIG_CPU_S3C2440
+#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
 
 /* extra registers */
 #define S3C2440_CAMDIVN	    S3C2410_CLKREG(0x18)
@@ -136,7 +136,70 @@
 #define S3C2440_CAMDIVN_HCLK4_HALF   (1<<9)
 #define S3C2440_CAMDIVN_DVSEN        (1<<12)
 
-#endif /* CONFIG_CPU_S3C2440 */
+#define S3C2442_CAMDIVN_CAMCLK_DIV3  (1<<5)
 
+#endif /* CONFIG_CPU_S3C2440 or CONFIG_CPU_S3C2442 */
+
+#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
+
+#define S3C2412_OSCSET		S3C2410_CLKREG(0x18)
+#define S3C2412_CLKSRC		S3C2410_CLKREG(0x1C)
+
+#define S3C2412_PLLCON_OFF		(1<<20)
+
+#define S3C2412_CLKDIVN_PDIVN		(1<<2)
+#define S3C2412_CLKDIVN_HDIVN_MASK	(3<<0)
+#define S3C2421_CLKDIVN_ARMDIVN		(1<<3)
+#define S3C2412_CLKDIVN_USB48DIV	(1<<6)
+#define S3C2412_CLKDIVN_UARTDIV_MASK	(15<<8)
+#define S3C2412_CLKDIVN_UARTDIV_SHIFT	(8)
+#define S3C2412_CLKDIVN_I2SDIV_MASK	(15<<12)
+#define S3C2412_CLKDIVN_I2SDIV_SHIFT	(12)
+#define S3C2412_CLKDIVN_CAMDIV_MASK	(15<<16)
+#define S3C2412_CLKDIVN_CAMDIV_SHIFT	(16)
+
+#define S3C2412_CLKCON_WDT		(1<<28)
+#define S3C2412_CLKCON_SPI		(1<<27)
+#define S3C2412_CLKCON_IIS		(1<<26)
+#define S3C2412_CLKCON_IIC		(1<<25)
+#define S3C2412_CLKCON_ADC		(1<<24)
+#define S3C2412_CLKCON_RTC		(1<<23)
+#define S3C2412_CLKCON_GPIO		(1<<22)
+#define S3C2412_CLKCON_UART2		(1<<21)
+#define S3C2412_CLKCON_UART1		(1<<20)
+#define S3C2412_CLKCON_UART0		(1<<19)
+#define S3C2412_CLKCON_SDI		(1<<18)
+#define S3C2412_CLKCON_PWMT		(1<<17)
+#define S3C2412_CLKCON_USBD		(1<<16)
+#define S3C2412_CLKCON_CAMCLK		(1<<15)
+#define S3C2412_CLKCON_UARTCLK		(1<<14)
+/* missing 13 */
+#define S3C2412_CLKCON_USB_HOST48	(1<<12)
+#define S3C2412_CLKCON_USB_DEV48	(1<<11)
+#define S3C2412_CLKCON_HCLKdiv2		(1<<10)
+#define S3C2412_CLKCON_HCLKx2		(1<<9)
+#define S3C2412_CLKCON_SDRAM		(1<<8)
+/* missing 7 */
+#define S3C2412_CLKCON_USBH		S3C2410_CLKCON_USBH
+#define S3C2412_CLKCON_LCDC		S3C2410_CLKCON_LCDC
+#define S3C2412_CLKCON_NAND		S3C2410_CLKCON_NAND
+#define S3C2412_CLKCON_DMA3		(1<<3)
+#define S3C2412_CLKCON_DMA2		(1<<2)
+#define S3C2412_CLKCON_DMA1		(1<<1)
+#define S3C2412_CLKCON_DMA0		(1<<0)
+
+/* clock sourec controls */
+
+#define S3C2412_CLKSRC_EXTCLKDIV_MASK		(7 << 0)
+#define S3C2412_CLKSRC_EXTCLKDIV_SHIFT		(0)
+#define S3C2412_CLKSRC_MDIVCLK_EXTCLKDIV	(1<<3)
+#define S3C2412_CLKSRC_MSYSCLK_MPLL		(1<<4)
+#define S3C2412_CLKSRC_USYSCLK_UPLL		(1<<5)
+#define S3C2412_CLKSRC_UARTCLK_MPLL		(1<<8)
+#define S3C2412_CLKSRC_I2SCLK_MPLL		(1<<9)
+#define S3C2412_CLKSRC_USBCLK_HCLK		(1<<10)
+#define S3C2412_CLKSRC_CAMCLK_HCLK		(1<<11)
+
+#endif /* CONFIG_CPU_S3C2412 | CONFIG_CPU_S3C2413 */
 
 #endif /* __ASM_ARM_REGS_CLOCK */
diff --git a/include/asm-arm/arch-s3c2410/regs-dsc.h b/include/asm-arm/arch-s3c2410/regs-dsc.h
index a023b04..84aca61 100644
--- a/include/asm-arm/arch-s3c2410/regs-dsc.h
+++ b/include/asm-arm/arch-s3c2410/regs-dsc.h
@@ -23,6 +23,9 @@
 #define S3C2440_DSC0	   S3C2410_GPIOREG(0xc4)
 #define S3C2440_DSC1	   S3C2410_GPIOREG(0xc8)
 
+#define S3C2412_DSC0	   S3C2410_GPIOREG(0xdc)
+#define S3C2412_DSC1	   S3C2410_GPIOREG(0xe0)
+
 #define S3C2440_SELECT_DSC0 (0)
 #define S3C2440_SELECT_DSC1 (1<<31)
 
@@ -170,7 +173,7 @@
 #define S3C2440_DSC1_CS1_4mA    (3<<2)
 #define S3C2440_DSC1_CS1_MASK   (3<<2)
 
-#define S3C2440_DSC1_CS0        (S3C2440_SELECT_DSC1 | 0
+#define S3C2440_DSC1_CS0        (S3C2440_SELECT_DSC1 | 0)
 #define S3C2440_DSC1_CS0_10mA   (0<<0)
 #define S3C2440_DSC1_CS0_8mA    (1<<0)
 #define S3C2440_DSC1_CS0_6mA    (2<<0)
diff --git a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
index d257408..6dd17f0f 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h
@@ -45,7 +45,7 @@
 #define S3C24XX_MISCCR        S3C2400_MISCCR
 #else
 #define S3C24XX_GPIO_BASE(x)  S3C2410_GPIO_BASE(x)
-#define S3C24XX_MISCCR        S3C2410_MISCCR
+#define S3C24XX_MISCCR	      S3C24XX_GPIOREG2(0x80)
 #endif /* CONFIG_CPU_S3C2400 */
 
 
@@ -73,9 +73,15 @@
 #define S3C2410_GPIO_SFN2    (0xFFFFFFF2)	/* not available on A */
 #define S3C2410_GPIO_SFN3    (0xFFFFFFF3)	/* not available on A */
 
-/* configure GPIO ports A..G */
+/* register address for the GPIO registers.
+ * S3C24XX_GPIOREG2 is for the second set of registers in the
+ * GPIO which move between s3c2410 and s3c2412 type systems */
 
 #define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)
+#define S3C24XX_GPIOREG2(x) ((x) + S3C24XX_VA_GPIO2)
+
+
+/* configure GPIO ports A..G */
 
 /* port A - S3C2410: 22bits, zero in bit X makes pin X output
  *          S3C2400: 18bits, zero in bit X makes pin X output
@@ -450,12 +456,14 @@
 #define S3C2410_GPD0_OUTP	(0x01 << 0)
 #define S3C2410_GPD0_VD8	(0x02 << 0)
 #define S3C2400_GPD0_VFRAME	(0x02 << 0)
+#define S3C2442_GPD0_nSPICS1	(0x03 << 0)
 
 #define S3C2410_GPD1            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 1)
 #define S3C2410_GPD1_INP	(0x00 << 2)
 #define S3C2410_GPD1_OUTP	(0x01 << 2)
 #define S3C2410_GPD1_VD9	(0x02 << 2)
 #define S3C2400_GPD1_VM		(0x02 << 2)
+#define S3C2442_GPD1_SPICLK1	(0x03 << 2)
 
 #define S3C2410_GPD2            S3C2410_GPIONO(S3C2410_GPIO_BANKD, 2)
 #define S3C2410_GPD2_INP	(0x00 << 4)
@@ -858,6 +866,7 @@
 #define S3C2410_GPG12_OUTP    (0x01 << 24)
 #define S3C2410_GPG12_EINT20  (0x02 << 24)
 #define S3C2410_GPG12_XMON    (0x03 << 24)
+#define S3C2442_GPG12_nSPICS0 (0x03 << 24)
 
 #define S3C2410_GPG13         S3C2410_GPIONO(S3C2410_GPIO_BANKG, 13)
 #define S3C2410_GPG13_INP     (0x00 << 26)
@@ -943,17 +952,25 @@
 #define S3C2410_GPH9_INP      (0x00 << 18)
 #define S3C2410_GPH9_OUTP     (0x01 << 18)
 #define S3C2410_GPH9_CLKOUT0  (0x02 << 18)
+#define S3C2442_GPH9_nSPICS0  (0x03 << 18)
 
 #define S3C2410_GPH10         S3C2410_GPIONO(S3C2410_GPIO_BANKH, 10)
 #define S3C2410_GPH10_INP     (0x00 << 20)
 #define S3C2410_GPH10_OUTP    (0x01 << 20)
 #define S3C2410_GPH10_CLKOUT1 (0x02 << 20)
 
+/* The S3C2412 and S3C2413 move the GPJ register set to after
+ * GPH, which means all registers after 0x80 are now offset by 0x10
+ * for the 2412/2413 from the 2410/2440/2442
+*/
+
 /* miscellaneous control */
 #define S3C2400_MISCCR	   S3C2410_GPIOREG(0x54)
 #define S3C2410_MISCCR	   S3C2410_GPIOREG(0x80)
 #define S3C2410_DCLKCON	   S3C2410_GPIOREG(0x84)
 
+#define S3C24XX_DCLKCON	   S3C24XX_GPIOREG2(0x84)
+
 /* see clock.h for dclk definitions */
 
 /* pullup control on databus */
@@ -981,6 +998,8 @@
 #define S3C2410_MISCCR_CLK0_DCLK0   (5<<4)
 #define S3C2410_MISCCR_CLK0_MASK    (7<<4)
 
+#define S3C2412_MISCCR_CLK0_RTC	    (2<<4)
+
 #define S3C2410_MISCCR_CLK1_MPLL    (0<<8)
 #define S3C2410_MISCCR_CLK1_UPLL    (1<<8)
 #define S3C2410_MISCCR_CLK1_FCLK    (2<<8)
@@ -989,6 +1008,8 @@
 #define S3C2410_MISCCR_CLK1_DCLK1   (5<<8)
 #define S3C2410_MISCCR_CLK1_MASK    (7<<8)
 
+#define S3C2412_MISCCR_CLK1_CLKsrc  (0<<8)
+
 #define S3C2410_MISCCR_USBSUSPND0   (1<<12)
 #define S3C2410_MISCCR_USBSUSPND1   (1<<13)
 
@@ -996,7 +1017,7 @@
 
 #define S3C2410_MISCCR_nEN_SCLK0    (1<<17)
 #define S3C2410_MISCCR_nEN_SCLK1    (1<<18)
-#define S3C2410_MISCCR_nEN_SCLKE    (1<<19)
+#define S3C2410_MISCCR_nEN_SCLKE    (1<<19)	/* not 2412 */
 #define S3C2410_MISCCR_SDSLEEP	    (7<<17)
 
 /* external interrupt control... */
@@ -1013,6 +1034,10 @@
 #define S3C2410_EXTINT1	   S3C2410_GPIOREG(0x8C)
 #define S3C2410_EXTINT2	   S3C2410_GPIOREG(0x90)
 
+#define S3C24XX_EXTINT0	   S3C24XX_GPIOREG2(0x88)
+#define S3C24XX_EXTINT1	   S3C24XX_GPIOREG2(0x8C)
+#define S3C24XX_EXTINT2	   S3C24XX_GPIOREG2(0x90)
+
 /* values for S3C2410_EXTINT0/1/2 */
 #define S3C2410_EXTINT_LOWLEV	 (0x00)
 #define S3C2410_EXTINT_HILEV	 (0x01)
@@ -1026,6 +1051,11 @@
 #define S3C2410_EINFLT2	   S3C2410_GPIOREG(0x9C)
 #define S3C2410_EINFLT3	   S3C2410_GPIOREG(0xA0)
 
+#define S3C24XX_EINFLT0	   S3C24XX_GPIOREG2(0x94)
+#define S3C24XX_EINFLT1	   S3C24XX_GPIOREG2(0x98)
+#define S3C24XX_EINFLT2	   S3C24XX_GPIOREG2(0x9C)
+#define S3C24XX_EINFLT3	   S3C24XX_GPIOREG2(0xA0)
+
 /* values for interrupt filtering */
 #define S3C2410_EINTFLT_PCLK		(0x00)
 #define S3C2410_EINTFLT_EXTCLK		(1<<7)
@@ -1035,6 +1065,7 @@
 
 /* GSTATUS have miscellaneous information in them
  *
+ * These move between s3c2410 and s3c2412 style systems.
  */
 
 #define S3C2410_GSTATUS0   S3C2410_GPIOREG(0x0AC)
@@ -1043,6 +1074,18 @@
 #define S3C2410_GSTATUS3   S3C2410_GPIOREG(0x0B8)
 #define S3C2410_GSTATUS4   S3C2410_GPIOREG(0x0BC)
 
+#define S3C2412_GSTATUS0   S3C2410_GPIOREG(0x0BC)
+#define S3C2412_GSTATUS1   S3C2410_GPIOREG(0x0C0)
+#define S3C2412_GSTATUS2   S3C2410_GPIOREG(0x0C4)
+#define S3C2412_GSTATUS3   S3C2410_GPIOREG(0x0C8)
+#define S3C2412_GSTATUS4   S3C2410_GPIOREG(0x0CC)
+
+#define S3C24XX_GSTATUS0   S3C24XX_GPIOREG2(0x0AC)
+#define S3C24XX_GSTATUS1   S3C24XX_GPIOREG2(0x0B0)
+#define S3C24XX_GSTATUS2   S3C24XX_GPIOREG2(0x0B4)
+#define S3C24XX_GSTATUS3   S3C24XX_GPIOREG2(0x0B8)
+#define S3C24XX_GSTATUS4   S3C24XX_GPIOREG2(0x0BC)
+
 #define S3C2410_GSTATUS0_nWAIT	   (1<<3)
 #define S3C2410_GSTATUS0_NCON	   (1<<2)
 #define S3C2410_GSTATUS0_RnB	   (1<<1)
@@ -1050,7 +1093,9 @@
 
 #define S3C2410_GSTATUS1_IDMASK	   (0xffff0000)
 #define S3C2410_GSTATUS1_2410	   (0x32410000)
+#define S3C2410_GSTATUS1_2412	   (0x32412001)
 #define S3C2410_GSTATUS1_2440	   (0x32440000)
+#define S3C2410_GSTATUS1_2442	   (0x32440aaa)
 
 #define S3C2410_GSTATUS2_WTRESET   (1<<2)
 #define S3C2410_GSTATUS2_OFFRESET  (1<<1)
@@ -1072,5 +1117,22 @@
 #define S3C2400_OPENCR_OPC_MOSIDIS  (0<<5)
 #define S3C2400_OPENCR_OPC_MOSIEN   (1<<5)
 
+/* 2412/2413 sleep configuration registers */
+
+#define S3C2412_GPBSLPCON	S3C2410_GPIOREG(0x1C)
+#define S3C2412_GPCSLPCON	S3C2410_GPIOREG(0x2C)
+#define S3C2412_GPDSLPCON	S3C2410_GPIOREG(0x3C)
+#define S3C2412_GPESLPCON	S3C2410_GPIOREG(0x4C)
+#define S3C2412_GPFSLPCON	S3C2410_GPIOREG(0x5C)
+#define S3C2412_GPGSLPCON	S3C2410_GPIOREG(0x6C)
+#define S3C2412_GPHSLPCON	S3C2410_GPIOREG(0x7C)
+
+/* definitions for each pin bit */
+#define S3C2412_SLPCON_LOW(x)	( 0x00 << ((x) * 2))
+#define S3C2412_SLPCON_HI(x)	( 0x01 << ((x) * 2))
+#define S3C2412_SLPCON_IN(x)	( 0x02 << ((x) * 2))
+#define S3C2412_SLPCON_PDWN(x)	( 0x03 << ((x) * 2))
+#define S3C2412_SLPCON_MASK(x)	( 0x03 << ((x) * 2))
+
 #endif	/* __ASM_ARCH_REGS_GPIO_H */
 
diff --git a/include/asm-arm/arch-s3c2410/regs-gpioj.h b/include/asm-arm/arch-s3c2410/regs-gpioj.h
index 3ad2324..18edae5 100644
--- a/include/asm-arm/arch-s3c2410/regs-gpioj.h
+++ b/include/asm-arm/arch-s3c2410/regs-gpioj.h
@@ -32,6 +32,11 @@
 #define S3C2440_GPJDAT	    S3C2410_GPIOREG(0xd4)
 #define S3C2440_GPJUP	    S3C2410_GPIOREG(0xd8)
 
+#define S3C2413_GPJCON		S3C2410_GPIOREG(0x80)
+#define S3C2413_GPJDAT		S3C2410_GPIOREG(0x84)
+#define S3C2413_GPJUP		S3C2410_GPIOREG(0x88)
+#define S3C2413_GPJSLPCON	S3C2410_GPIOREG(0x8C)
+
 #define S3C2440_GPJ0            S3C2410_GPIONO(S3C2440_GPIO_BANKJ, 0)
 #define S3C2440_GPJ0_INP        (0x00 << 0)
 #define S3C2440_GPJ0_OUTP       (0x01 << 0)
diff --git a/include/asm-arm/arch-s3c2410/regs-irq.h b/include/asm-arm/arch-s3c2410/regs-irq.h
index 24b7292..572fca5 100644
--- a/include/asm-arm/arch-s3c2410/regs-irq.h
+++ b/include/asm-arm/arch-s3c2410/regs-irq.h
@@ -23,6 +23,7 @@
 
 #define S3C2410_IRQREG(x)   ((x) + S3C24XX_VA_IRQ)
 #define S3C2410_EINTREG(x)  ((x) + S3C24XX_VA_GPIO)
+#define S3C24XX_EINTREG(x)  ((x) + S3C24XX_VA_GPIO2)
 
 #define S3C2410_SRCPND	       S3C2410_IRQREG(0x000)
 #define S3C2410_INTMOD	       S3C2410_IRQREG(0x004)
@@ -40,5 +41,10 @@
 
 #define S3C2410_EINTMASK       S3C2410_EINTREG(0x0A4)
 #define S3C2410_EINTPEND       S3C2410_EINTREG(0X0A8)
+#define S3C2412_EINTMASK       S3C2410_EINTREG(0x0B4)
+#define S3C2412_EINTPEND       S3C2410_EINTREG(0X0B8)
+
+#define S3C24XX_EINTMASK       S3C24XX_EINTREG(0x0A4)
+#define S3C24XX_EINTPEND       S3C24XX_EINTREG(0X0A8)
 
 #endif /* ___ASM_ARCH_REGS_IRQ_H */
diff --git a/include/asm-arm/arch-s3c2410/regs-nand.h b/include/asm-arm/arch-s3c2410/regs-nand.h
index 7cff235..c1470c6 100644
--- a/include/asm-arm/arch-s3c2410/regs-nand.h
+++ b/include/asm-arm/arch-s3c2410/regs-nand.h
@@ -39,10 +39,19 @@
 #define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
 #define S3C2440_NFMECC0  S3C2410_NFREG(0x2C)
 #define S3C2440_NFMECC1  S3C2410_NFREG(0x30)
-#define S3C2440_NFSECC   S3C2410_NFREG(0x34)
+#define S3C2440_NFSECC   S3C24E10_NFREG(0x34)
 #define S3C2440_NFSBLK   S3C2410_NFREG(0x38)
 #define S3C2440_NFEBLK   S3C2410_NFREG(0x3C)
 
+#define S3C2412_NFSBLK		S3C2410_NFREG(0x20)
+#define S3C2412_NFEBLK		S3C2410_NFREG(0x24)
+#define S3C2412_NFSTAT		S3C2410_NFREG(0x28)
+#define S3C2412_NFMECC_ERR0	S3C2410_NFREG(0x2C)
+#define S3C2412_NFMECC_ERR1	S3C2410_NFREG(0x30)
+#define S3C2412_NFMECC0		S3C2410_NFREG(0x34)
+#define S3C2412_NFMECC1		S3C2410_NFREG(0x38)
+#define S3C2412_NFSECC		S3C2410_NFREG(0x3C)
+
 #define S3C2410_NFCONF_EN          (1<<15)
 #define S3C2410_NFCONF_512BYTE     (1<<14)
 #define S3C2410_NFCONF_4STEP       (1<<13)
@@ -77,5 +86,42 @@
 #define S3C2440_NFSTAT_RnB_CHANGE	(1<<2)
 #define S3C2440_NFSTAT_ILLEGAL_ACCESS	(1<<3)
 
+#define S3C2412_NFCONF_NANDBOOT		(1<<31)
+#define S3C2412_NFCONF_ECCCLKCON	(1<<30)
+#define S3C2412_NFCONF_ECC_MLC		(1<<24)
+#define S3C2412_NFCONF_TACLS_MASK	(7<<12)	/* 1 extra bit of Tacls */
+
+#define S3C2412_NFCONT_ECC4_DIRWR	(1<<18)
+#define S3C2412_NFCONT_LOCKTIGHT	(1<<17)
+#define S3C2412_NFCONT_SOFTLOCK		(1<<16)
+#define S3C2412_NFCONT_ECC4_ENCINT	(1<<13)
+#define S3C2412_NFCONT_ECC4_DECINT	(1<<12)
+#define S3C2412_NFCONT_MAIN_ECC_LOCK	(1<<7)
+#define S3C2412_NFCONT_INIT_MAIN_ECC	(1<<5)
+#define S3C2412_NFCONT_nFCE1		(1<<2)
+#define S3C2412_NFCONT_nFCE0		(1<<1)
+
+#define S3C2412_NFSTAT_ECC_ENCDONE	(1<<7)
+#define S3C2412_NFSTAT_ECC_DECDONE	(1<<6)
+#define S3C2412_NFSTAT_ILLEGAL_ACCESS	(1<<5)
+#define S3C2412_NFSTAT_RnB_CHANGE	(1<<4)
+#define S3C2412_NFSTAT_nFCE1		(1<<3)
+#define S3C2412_NFSTAT_nFCE0		(1<<2)
+#define S3C2412_NFSTAT_Res1		(1<<1)
+#define S3C2412_NFSTAT_READY		(1<<0)
+
+#define S3C2412_NFECCERR_SERRDATA(x)	(((x) >> 21) & 0xf)
+#define S3C2412_NFECCERR_SERRBIT(x)	(((x) >> 18) & 0x7)
+#define S3C2412_NFECCERR_MERRDATA(x)	(((x) >> 7) & 0x3ff)
+#define S3C2412_NFECCERR_MERRBIT(x)	(((x) >> 4) & 0x7)
+#define S3C2412_NFECCERR_SPARE_ERR(x)	(((x) >> 2) & 0x3)
+#define S3C2412_NFECCERR_MAIN_ERR(x)	(((x) >> 2) & 0x3)
+#define S3C2412_NFECCERR_NONE		(0)
+#define S3C2412_NFECCERR_1BIT		(1)
+#define S3C2412_NFECCERR_MULTIBIT	(2)
+#define S3C2412_NFECCERR_ECCAREA	(3)
+
+
+
 #endif /* __ASM_ARM_REGS_NAND */
 
diff --git a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
index 83b0125..93f651a 100644
--- a/include/asm-arm/arch-s3c2410/regs-serial.h
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h
@@ -82,6 +82,12 @@
 #define S3C2440_UCON2_DIVMASK	  (7 << 12)
 #define S3C2440_UCON_DIVSHIFT	  (12)
 
+#define S3C2412_UCON_CLKMASK	(3<<10)
+#define S3C2412_UCON_UCLK	(1<<10)
+#define S3C2412_UCON_USYSCLK	(3<<10)
+#define S3C2412_UCON_PCLK	(0<<10)
+#define S3C2412_UCON_PCLK2	(2<<10)
+
 #define S3C2410_UCON_UCLK	  (1<<10)
 #define S3C2410_UCON_SBREAK	  (1<<4)
 
@@ -124,6 +130,15 @@
 #define	S3C2410_UMCOM_AFC	  (1<<4)
 #define	S3C2410_UMCOM_RTS_LOW	  (1<<0)
 
+#define S3C2412_UMCON_AFC_63	(0<<5)
+#define S3C2412_UMCON_AFC_56	(1<<5)
+#define S3C2412_UMCON_AFC_48	(2<<5)
+#define S3C2412_UMCON_AFC_40	(3<<5)
+#define S3C2412_UMCON_AFC_32	(4<<5)
+#define S3C2412_UMCON_AFC_24	(5<<5)
+#define S3C2412_UMCON_AFC_16	(6<<5)
+#define S3C2412_UMCON_AFC_8	(7<<5)
+
 #define S3C2410_UFSTAT_TXFULL	  (1<<9)
 #define S3C2410_UFSTAT_RXFULL	  (1<<8)
 #define S3C2410_UFSTAT_TXMASK	  (15<<4)
diff --git a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
index a6f6a0e..8e152a0 100644
--- a/include/asm-arm/arch-s3c2410/uncompress.h
+++ b/include/asm-arm/arch-s3c2410/uncompress.h
@@ -22,7 +22,6 @@
 #ifndef __ASM_ARCH_UNCOMPRESS_H
 #define __ASM_ARCH_UNCOMPRESS_H
 
-#include <linux/config.h>
 
 /* defines for UART registers */
 #include "asm/arch/regs-serial.h"
@@ -82,7 +81,8 @@
 		while (1) {
 			level = uart_rd(S3C2410_UFSTAT);
 
-			if (cpuid == S3C2410_GSTATUS1_2440) {
+			if (cpuid == S3C2410_GSTATUS1_2440 ||
+			    cpuid == S3C2410_GSTATUS1_2442) {
 				level &= S3C2440_UFSTAT_TXMASK;
 				level >>= S3C2440_UFSTAT_TXSHIFT;
 			} else {
@@ -130,7 +130,7 @@
 {
 	__raw_writel(WDOG_COUNT, S3C2410_WTDAT);
 	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
-	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x80), S3C2410_WTCON);
 }
 
 #else
diff --git a/include/asm-arm/arch-sa1100/assabet.h b/include/asm-arm/arch-sa1100/assabet.h
index 1f59b36..d6a1bb5 100644
--- a/include/asm-arm/arch-sa1100/assabet.h
+++ b/include/asm-arm/arch-sa1100/assabet.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_ASSABET_H
 #define __ASM_ARCH_ASSABET_H
 
-#include <linux/config.h>
 
 /* System Configuration Register flags */
 
diff --git a/include/asm-arm/arch-sa1100/cerf.h b/include/asm-arm/arch-sa1100/cerf.h
index 356d5ba..9a19c3d0 100644
--- a/include/asm-arm/arch-sa1100/cerf.h
+++ b/include/asm-arm/arch-sa1100/cerf.h
@@ -10,7 +10,6 @@
 #ifndef _INCLUDE_CERF_H_
 #define _INCLUDE_CERF_H_
 
-#include <linux/config.h>
 
 #define CERF_ETH_IO			0xf0000000
 #define CERF_ETH_IRQ IRQ_GPIO26
diff --git a/include/asm-arm/arch-sa1100/collie.h b/include/asm-arm/arch-sa1100/collie.h
index d49e5ff..14a344a 100644
--- a/include/asm-arm/arch-sa1100/collie.h
+++ b/include/asm-arm/arch-sa1100/collie.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_COLLIE_H
 #define __ASM_ARCH_COLLIE_H
 
-#include <linux/config.h>
 
 #define COLLIE_SCP_CHARGE_ON	SCOOP_GPCR_PA11
 #define COLLIE_SCP_DIAG_BOOT1	SCOOP_GPCR_PA12
diff --git a/include/asm-arm/arch-sa1100/dma.h b/include/asm-arm/arch-sa1100/dma.h
index 02575d7..6b7917a 100644
--- a/include/asm-arm/arch-sa1100/dma.h
+++ b/include/asm-arm/arch-sa1100/dma.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-#include <linux/config.h>
 #include "hardware.h"
 
 
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
index ee008a5..1abd7cf 100644
--- a/include/asm-arm/arch-sa1100/hardware.h
+++ b/include/asm-arm/arch-sa1100/hardware.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#include <linux/config.h>
 
 #define UNCACHEABLE_ADDR	0xfa050000
 
diff --git a/include/asm-arm/arch-sa1100/ide.h b/include/asm-arm/arch-sa1100/ide.h
index 2153538..98b10bc 100644
--- a/include/asm-arm/arch-sa1100/ide.h
+++ b/include/asm-arm/arch-sa1100/ide.h
@@ -9,7 +9,6 @@
  *              architectures.
  */
 
-#include <linux/config.h>
 #include <asm/irq.h>
 #include <asm/hardware.h>
 #include <asm/mach-types.h>
diff --git a/include/asm-arm/arch-sa1100/io.h b/include/asm-arm/arch-sa1100/io.h
index 040ccde..0756269 100644
--- a/include/asm-arm/arch-sa1100/io.h
+++ b/include/asm-arm/arch-sa1100/io.h
@@ -22,6 +22,5 @@
 }
 #define __io(a)			__io(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #endif
diff --git a/include/asm-arm/arch-sa1100/irqs.h b/include/asm-arm/arch-sa1100/irqs.h
index eabd3be..d794068 100644
--- a/include/asm-arm/arch-sa1100/irqs.h
+++ b/include/asm-arm/arch-sa1100/irqs.h
@@ -7,7 +7,6 @@
  *
  * 2001/11/14	RMK	Cleaned up and standardised a lot of the IRQs.
  */
-#include <linux/config.h>
 
 #define	IRQ_GPIO0		0
 #define	IRQ_GPIO1		1
diff --git a/include/asm-arm/arch-sa1100/memory.h b/include/asm-arm/arch-sa1100/memory.h
index a29fac1..1ff172d 100644
--- a/include/asm-arm/arch-sa1100/memory.h
+++ b/include/asm-arm/arch-sa1100/memory.h
@@ -7,7 +7,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#include <linux/config.h>
 #include <asm/sizes.h>
 
 /*
diff --git a/include/asm-arm/arch-sa1100/system.h b/include/asm-arm/arch-sa1100/system.h
index 0f0612f..aef91e3 100644
--- a/include/asm-arm/arch-sa1100/system.h
+++ b/include/asm-arm/arch-sa1100/system.h
@@ -3,7 +3,6 @@
  *
  * Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
  */
-#include <linux/config.h>
 #include <asm/hardware.h>
 
 static inline void arch_idle(void)
diff --git a/include/asm-arm/arch-versatile/io.h b/include/asm-arm/arch-versatile/io.h
index 47e904c..c4d0194 100644
--- a/include/asm-arm/arch-versatile/io.h
+++ b/include/asm-arm/arch-versatile/io.h
@@ -28,6 +28,5 @@
 }
 #define __io(a)	__io(a)
 #define __mem_pci(a)		(a)
-#define __mem_isa(a)		(a)
 
 #endif
diff --git a/include/asm-arm/arch-versatile/system.h b/include/asm-arm/arch-versatile/system.h
index 8889a18..71c6254 100644
--- a/include/asm-arm/arch-versatile/system.h
+++ b/include/asm-arm/arch-versatile/system.h
@@ -36,16 +36,14 @@
 
 static inline void arch_reset(char mode)
 {
-	unsigned int hdr_ctrl =	(IO_ADDRESS(VERSATILE_SYS_BASE) + VERSATILE_SYS_RESETCTL_OFFSET);
-	unsigned int val;
+	u32 val;
 
-	/*
-	 * To reset, we hit the on-board reset register
-	 * in the system FPGA
-	 */
-	val = __raw_readl(hdr_ctrl);
-	val |= VERSATILE_SYS_CTRL_RESET_CONFIGCLR;
-	__raw_writel(val, hdr_ctrl);
+	val = __raw_readl(IO_ADDRESS(VERSATILE_SYS_RESETCTL)) & ~0x7;
+	val |= 0x105;
+
+	__raw_writel(0xa05f, IO_ADDRESS(VERSATILE_SYS_LOCK));
+	__raw_writel(val, IO_ADDRESS(VERSATILE_SYS_RESETCTL));
+	__raw_writel(0, IO_ADDRESS(VERSATILE_SYS_LOCK));
 }
 
 #endif
diff --git a/include/asm-arm/assembler.h b/include/asm-arm/assembler.h
index d53bafa..fce8328 100644
--- a/include/asm-arm/assembler.h
+++ b/include/asm-arm/assembler.h
@@ -55,30 +55,6 @@
 #define PLD(code...)
 #endif
 
-#define MODE_USR	USR_MODE
-#define MODE_FIQ	FIQ_MODE
-#define MODE_IRQ	IRQ_MODE
-#define MODE_SVC	SVC_MODE
-
-#define DEFAULT_FIQ	MODE_FIQ
-
-/*
- * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc})
- */
-#ifdef __STDC__
-#define LOADREGS(cond, base, reglist...)\
-	ldm##cond	base,reglist
-#else
-#define LOADREGS(cond, base, reglist...)\
-	ldm/**/cond	base,reglist
-#endif
-
-/*
- * Build a return instruction for this processor type.
- */
-#define RETINSTR(instr, regs...)\
-	instr	regs
-
 /*
  * Enable and disable interrupts
  */
@@ -117,18 +93,6 @@
 	msr	cpsr_c, \oldcpsr
 	.endm
 
-/*
- * These two are used to save LR/restore PC over a user-based access.
- * The old 26-bit architecture requires that we do.  On 32-bit
- * architecture, we can safely ignore this requirement.
- */
-	.macro	save_lr
-	.endm
-
-	.macro	restore_pc
-	mov	pc, lr
-	.endm
-
 #define USER(x...)				\
 9999:	x;					\
 	.section __ex_table,"a";		\
diff --git a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
index 3d7283d..4b0ce3e 100644
--- a/include/asm-arm/atomic.h
+++ b/include/asm-arm/atomic.h
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARM_ATOMIC_H
 #define __ASM_ARM_ATOMIC_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 typedef struct { volatile int counter; } atomic_t;
diff --git a/include/asm-arm/bug.h b/include/asm-arm/bug.h
index 5ab8216..7fb0213 100644
--- a/include/asm-arm/bug.h
+++ b/include/asm-arm/bug.h
@@ -2,7 +2,6 @@
 #define _ASMARM_BUG_H
 
 #include <linux/config.h>
-#include <linux/stddef.h>
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
diff --git a/include/asm-arm/byteorder.h b/include/asm-arm/byteorder.h
index 17eaf8b..e6f7fcd 100644
--- a/include/asm-arm/byteorder.h
+++ b/include/asm-arm/byteorder.h
@@ -22,16 +22,18 @@
 {
 	__u32 t;
 
-	if (__builtin_constant_p(x)) {
-		t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */
-	} else {
+#ifndef __thumb__
+	if (!__builtin_constant_p(x)) {
 		/*
 		 * The compiler needs a bit of a hint here to always do the
 		 * right thing and not screw it up to different degrees
 		 * depending on the gcc version.
 		 */
 		asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
-	}
+	} else
+#endif
+		t = x ^ ((x << 16) | (x >> 16)); /* eor r1,r0,r0,ror #16 */
+
 	x = (x << 24) | (x >> 8);		/* mov r0,r0,ror #8      */
 	t &= ~0x00FF0000;			/* bic r1,r1,#0x00FF0000 */
 	x ^= (t >> 8);				/* eor r0,r0,r1,lsr #8   */
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 746be56..fe0c744 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -10,7 +10,6 @@
 #ifndef _ASMARM_CACHEFLUSH_H
 #define _ASMARM_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 
diff --git a/include/asm-arm/cpu.h b/include/asm-arm/cpu.h
index 751bc74..715426b 100644
--- a/include/asm-arm/cpu.h
+++ b/include/asm-arm/cpu.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARM_CPU_H
 #define __ASM_ARM_CPU_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 
 struct cpuinfo_arm {
diff --git a/include/asm-arm/dma-mapping.h b/include/asm-arm/dma-mapping.h
index 63ca741..55eb4dc 100644
--- a/include/asm-arm/dma-mapping.h
+++ b/include/asm-arm/dma-mapping.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/mm.h> /* need struct page */
 
 #include <asm/scatterlist.h>
diff --git a/include/asm-arm/dma.h b/include/asm-arm/dma.h
index 49c01e2..9f2c530 100644
--- a/include/asm-arm/dma.h
+++ b/include/asm-arm/dma.h
@@ -3,7 +3,6 @@
 
 typedef unsigned int dmach_t;
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/scatterlist.h>
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index 2d44b42..71061ca 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -1,7 +1,6 @@
 #ifndef __ASMARM_ELF_H
 #define __ASMARM_ELF_H
 
-#include <linux/config.h>
 
 /*
  * ELF register definitions..
diff --git a/include/asm-arm/floppy.h b/include/asm-arm/floppy.h
index 6ea657c..aa0c8d2 100644
--- a/include/asm-arm/floppy.h
+++ b/include/asm-arm/floppy.h
@@ -25,7 +25,7 @@
 
 #define fd_inb(port)		inb((port))
 #define fd_request_irq()	request_irq(IRQ_FLOPPYDISK,floppy_interrupt,\
-					SA_INTERRUPT|SA_SAMPLE_RANDOM,"floppy",NULL)
+					    SA_INTERRUPT,"floppy",NULL)
 #define fd_free_irq()		free_irq(IRQ_FLOPPYDISK,NULL)
 #define fd_disable_irq()	disable_irq(IRQ_FLOPPYDISK)
 #define fd_enable_irq()		enable_irq(IRQ_FLOPPYDISK)
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index 52bae08..132c3c5 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -11,7 +11,6 @@
 #ifndef __ASM_ARM_FPSTATE_H
 #define __ASM_ARM_FPSTATE_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-arm/glue.h b/include/asm-arm/glue.h
index 223e0d6..0cc5d3b 100644
--- a/include/asm-arm/glue.h
+++ b/include/asm-arm/glue.h
@@ -15,7 +15,6 @@
  */
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef __STDC__
 #define ____glue(name,fn)	name##fn
diff --git a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h
index 1cbb173..182310b 100644
--- a/include/asm-arm/hardirq.h
+++ b/include/asm-arm/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <asm/irq.h>
diff --git a/include/asm-arm/hardware/dec21285.h b/include/asm-arm/hardware/dec21285.h
index 6685e3f..546f707 100644
--- a/include/asm-arm/hardware/dec21285.h
+++ b/include/asm-arm/hardware/dec21285.h
@@ -18,7 +18,6 @@
 #define DC21285_PCI_IO			0x7c000000
 #define DC21285_PCI_MEM			0x80000000
 
-#include <linux/config.h>
 #ifndef __ASSEMBLY__
 #include <asm/hardware.h>
 #define DC21285_IO(x)		((volatile unsigned long *)(ARMCSR_BASE+(x)))
diff --git a/include/asm-arm/hardware/iomd.h b/include/asm-arm/hardware/iomd.h
index 82fa2c2..396e55a 100644
--- a/include/asm-arm/hardware/iomd.h
+++ b/include/asm-arm/hardware/iomd.h
@@ -13,7 +13,6 @@
 #ifndef __ASMARM_HARDWARE_IOMD_H
 #define __ASMARM_HARDWARE_IOMD_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-arm/hardware/locomo.h b/include/asm-arm/hardware/locomo.h
index 5f10048..22dfb17 100644
--- a/include/asm-arm/hardware/locomo.h
+++ b/include/asm-arm/hardware/locomo.h
@@ -111,6 +111,8 @@
 #define LOCOMO_ALS		0x00	/* Adjust light cycle */
 #define LOCOMO_ALD		0x04	/* Adjust light duty */
 
+#define LOCOMO_ALC_EN		0x8000
+
 /* Backlight controller: TFT signal */
 #define LOCOMO_BACKLIGHT	0x38
 #define LOCOMO_TC		0x00		/* TFT control signal */
@@ -203,4 +205,7 @@
 /* M62332 control function */
 void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel);
 
+/* Frontlight control */
+void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf);
+
 #endif
diff --git a/include/asm-arm/hardware/sharpsl_pm.h b/include/asm-arm/hardware/sharpsl_pm.h
index 36983e5..ecf15b8 100644
--- a/include/asm-arm/hardware/sharpsl_pm.h
+++ b/include/asm-arm/hardware/sharpsl_pm.h
@@ -16,6 +16,7 @@
 	void (*exit)(void);
 	int gpio_acin;
 	int gpio_batfull;
+	int batfull_irq;
 	int gpio_batlock;
 	int gpio_fatal;
 	void (*discharge)(int);
@@ -34,9 +35,19 @@
 #define SHARPSL_STATUS_FATAL    7
 	unsigned long (*charger_wakeup)(void);
 	int (*should_wakeup)(unsigned int resume_on_alarm);
+	void (*backlight_limit)(int);
+	int (*backlight_get_status) (void);
+	int charge_on_volt;
+	int charge_on_temp;
+	int charge_acin_high;
+	int charge_acin_low;
+	int fatal_acin_volt;
+	int fatal_noacin_volt;
 	int bat_levels;
 	struct battery_thresh *bat_levels_noac;
 	struct battery_thresh *bat_levels_acin;
+	struct battery_thresh *bat_levels_noac_bl;
+	struct battery_thresh *bat_levels_acin_bl;
 	int status_high_acin;
 	int status_low_acin;
 	int status_high_noac;
diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h
index 60b5105..66e67e6 100644
--- a/include/asm-arm/irq.h
+++ b/include/asm-arm/irq.h
@@ -47,10 +47,6 @@
 void enable_irq_wake(unsigned int irq);
 int setup_irq(unsigned int, struct irqaction *);
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 extern void migrate_irqs(void);
 #endif
 
diff --git a/include/asm-arm/leds.h b/include/asm-arm/leds.h
index 88ce412..12290ea 100644
--- a/include/asm-arm/leds.h
+++ b/include/asm-arm/leds.h
@@ -13,7 +13,6 @@
 #ifndef ASM_ARM_LEDS_H
 #define ASM_ARM_LEDS_H
 
-#include <linux/config.h>
 
 typedef enum {
 	led_idle_start,
diff --git a/include/asm-arm/mach/serial_at91.h b/include/asm-arm/mach/serial_at91.h
new file mode 100644
index 0000000..1290bb3
--- /dev/null
+++ b/include/asm-arm/mach/serial_at91.h
@@ -0,0 +1,33 @@
+/*
+ *  linux/include/asm-arm/mach/serial_at91.h
+ *
+ *  Based on serial_sa1100.h  by Nicolas Pitre
+ *
+ *  Copyright (C) 2002 ATMEL Rousset
+ *
+ *  Low level machine dependent UART functions.
+ */
+
+struct uart_port;
+
+/*
+ * This is a temporary structure for registering these
+ * functions; it is intended to be discarded after boot.
+ */
+struct at91_port_fns {
+	void	(*set_mctrl)(struct uart_port *, u_int);
+	u_int	(*get_mctrl)(struct uart_port *);
+	void	(*enable_ms)(struct uart_port *);
+	void	(*pm)(struct uart_port *, u_int, u_int);
+	int	(*set_wake)(struct uart_port *, u_int);
+	int	(*open)(struct uart_port *);
+	void	(*close)(struct uart_port *);
+};
+
+#if defined(CONFIG_SERIAL_AT91)
+void at91_register_uart_fns(struct at91_port_fns *fns);
+#else
+#define at91_register_uart_fns(fns) do { } while (0)
+#endif
+
+
diff --git a/include/asm-arm/mach/serial_at91rm9200.h b/include/asm-arm/mach/serial_at91rm9200.h
deleted file mode 100644
index 98f4b0c..0000000
--- a/include/asm-arm/mach/serial_at91rm9200.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  linux/include/asm-arm/mach/serial_at91rm9200.h
- *
- *  Based on serial_sa1100.h  by Nicolas Pitre
- *
- *  Copyright (C) 2002 ATMEL Rousset
- *
- *  Low level machine dependent UART functions.
- */
-#include <linux/config.h>
-
-struct uart_port;
-
-/*
- * This is a temporary structure for registering these
- * functions; it is intended to be discarded after boot.
- */
-struct at91rm9200_port_fns {
-	void	(*set_mctrl)(struct uart_port *, u_int);
-	u_int	(*get_mctrl)(struct uart_port *);
-	void	(*enable_ms)(struct uart_port *);
-	void	(*pm)(struct uart_port *, u_int, u_int);
-	int	(*set_wake)(struct uart_port *, u_int);
-	int	(*open)(struct uart_port *);
-	void	(*close)(struct uart_port *);
-};
-
-#if defined(CONFIG_SERIAL_AT91)
-void at91_register_uart_fns(struct at91rm9200_port_fns *fns);
-void at91_register_uart(int idx, int port);
-#else
-#define at91_register_uart_fns(fns) do { } while (0)
-#define at91_register_uart(idx,port) do { } while (0)
-#endif
-
-
diff --git a/include/asm-arm/mach/serial_sa1100.h b/include/asm-arm/mach/serial_sa1100.h
index 9162018..20c22bb 100644
--- a/include/asm-arm/mach/serial_sa1100.h
+++ b/include/asm-arm/mach/serial_sa1100.h
@@ -7,7 +7,6 @@
  *
  * Low level machine dependent UART functions.
  */
-#include <linux/config.h>
 
 struct uart_port;
 struct uart_info;
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index 96c6db7..9f28073 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -50,6 +50,7 @@
 #define DYN_TICK_ENABLED	(1 << 1)
 
 struct dyn_tick_timer {
+	spinlock_t	lock;
 	unsigned int	state;			/* Current state */
 	int		(*enable)(void);	/* Enables dynamic tick */
 	int		(*disable)(void);	/* Disables dynamic tick */
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index 2092894..731e321 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -22,7 +22,6 @@
 #define UL(x) (x)
 #endif
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/arch/memory.h>
 #include <asm/sizes.h>
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index a404d2b..66cfeb5 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -10,7 +10,6 @@
 #ifndef _ASMARM_PAGE_H
 #define _ASMARM_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT		12
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index ead3ced..f21abd4 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -2,7 +2,6 @@
 #define ASMARM_PCI_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <asm-generic/pci-dma-compat.h>
 
 #include <asm/hardware.h> /* for PCIBIOS_MIN_* */
diff --git a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h
index 106045e..e931089 100644
--- a/include/asm-arm/proc-fns.h
+++ b/include/asm-arm/proc-fns.h
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * Work out if we need multiple CPU support
diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h
index 77adb7f..2bebe3d 100644
--- a/include/asm-arm/ptrace.h
+++ b/include/asm-arm/ptrace.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARM_PTRACE_H
 #define __ASM_ARM_PTRACE_H
 
-#include <linux/config.h>
 
 #define PTRACE_GETREGS		12
 #define PTRACE_SETREGS		13
diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h
index fe45f7f..f67acce 100644
--- a/include/asm-arm/smp.h
+++ b/include/asm-arm/smp.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_ARM_SMP_H
 #define __ASM_ARM_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/thread_info.h>
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index 7c9568d..6001feb 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define CPU_ARCH_UNKNOWN	0
 #define CPU_ARCH_ARMv3		1
@@ -108,6 +107,9 @@
 extern int cpu_architecture(void);
 extern void cpu_init(void);
 
+void arm_machine_restart(char mode);
+extern void (*arm_pm_restart)(char str);
+
 /*
  * Intel's XScale3 core supports some v6 features (supersections, L2)
  * but advertises itself as v5 as it does not support the v6 ISA.  For
diff --git a/include/asm-arm/thread_notify.h b/include/asm-arm/thread_notify.h
new file mode 100644
index 0000000..8866e52
--- /dev/null
+++ b/include/asm-arm/thread_notify.h
@@ -0,0 +1,48 @@
+/*
+ *  linux/include/asm-arm/thread_notify.h
+ *
+ *  Copyright (C) 2006 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASMARM_THREAD_NOTIFY_H
+#define ASMARM_THREAD_NOTIFY_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+
+#include <linux/notifier.h>
+#include <asm/thread_info.h>
+
+static inline int thread_register_notifier(struct notifier_block *n)
+{
+	extern struct atomic_notifier_head thread_notify_head;
+	return atomic_notifier_chain_register(&thread_notify_head, n);
+}
+
+static inline void thread_unregister_notifier(struct notifier_block *n)
+{
+	extern struct atomic_notifier_head thread_notify_head;
+	atomic_notifier_chain_unregister(&thread_notify_head, n);
+}
+
+static inline void thread_notify(unsigned long rc, struct thread_info *thread)
+{
+	extern struct atomic_notifier_head thread_notify_head;
+	atomic_notifier_call_chain(&thread_notify_head, rc, thread);
+}
+
+#endif
+
+/*
+ * These are the reason codes for the thread notifier.
+ */
+#define THREAD_NOTIFY_FLUSH	0
+#define THREAD_NOTIFY_RELEASE	1
+#define THREAD_NOTIFY_SWITCH	2
+
+#endif
+#endif
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index 7289924..d97fc76 100644
--- a/include/asm-arm/tlbflush.h
+++ b/include/asm-arm/tlbflush.h
@@ -10,7 +10,6 @@
 #ifndef _ASMARM_TLBFLUSH_H
 #define _ASMARM_TLBFLUSH_H
 
-#include <linux/config.h>
 
 #ifndef CONFIG_MMU
 
diff --git a/include/asm-arm/ucontext.h b/include/asm-arm/ucontext.h
index f853130..9e6f7ca 100644
--- a/include/asm-arm/ucontext.h
+++ b/include/asm-arm/ucontext.h
@@ -1,12 +1,89 @@
 #ifndef _ASMARM_UCONTEXT_H
 #define _ASMARM_UCONTEXT_H
 
+#include <asm/fpstate.h>
+
+/*
+ * struct sigcontext only has room for the basic registers, but struct
+ * ucontext now has room for all registers which need to be saved and
+ * restored.  Coprocessor registers are stored in uc_regspace.  Each
+ * coprocessor's saved state should start with a documented 32-bit magic
+ * number, followed by a 32-bit word giving the coproccesor's saved size.
+ * uc_regspace may be expanded if necessary, although this takes some
+ * coordination with glibc.
+ */
+
 struct ucontext {
 	unsigned long	  uc_flags;
 	struct ucontext  *uc_link;
 	stack_t		  uc_stack;
 	struct sigcontext uc_mcontext;
-	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+	sigset_t	  uc_sigmask;
+	/* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */
+	int		  __unused[32 - (sizeof (sigset_t) / sizeof (int))];
+	/* Last for extensibility.  Eight byte aligned because some
+	   coprocessors require eight byte alignment.  */
+ 	unsigned long	  uc_regspace[128] __attribute__((__aligned__(8)));
 };
 
+#ifdef __KERNEL__
+
+/*
+ * Coprocessor save state.  The magic values and specific
+ * coprocessor's layouts are part of the userspace ABI.  Each one of
+ * these should be a multiple of eight bytes and aligned to eight
+ * bytes, to prevent unpredictable padding in the signal frame.
+ */
+
+#ifdef CONFIG_IWMMXT
+/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
+#define IWMMXT_MAGIC		0x12ef842a
+#define IWMMXT_STORAGE_SIZE	(IWMMXT_SIZE + 8)
+
+struct iwmmxt_sigframe {
+	unsigned long	magic;
+	unsigned long	size;
+	struct iwmmxt_struct storage;
+} __attribute__((__aligned__(8)));
+#endif /* CONFIG_IWMMXT */
+
+#ifdef CONFIG_VFP
+#if __LINUX_ARM_ARCH__ < 6
+/* For ARM pre-v6, we use fstmiax and fldmiax.  This adds one extra
+ * word after the registers, and a word of padding at the end for
+ * alignment.  */
+#define VFP_MAGIC		0x56465001
+#define VFP_STORAGE_SIZE	152
+#else
+#define VFP_MAGIC		0x56465002
+#define VFP_STORAGE_SIZE	144
+#endif
+
+struct vfp_sigframe
+{
+	unsigned long		magic;
+	unsigned long		size;
+	union vfp_state		storage;
+};
+#endif /* CONFIG_VFP */
+
+/*
+ * Auxiliary signal frame.  This saves stuff like FP state.
+ * The layout of this structure is not part of the user ABI,
+ * because the config options aren't.  uc_regspace is really
+ * one of these.
+ */
+struct aux_sigframe {
+#ifdef CONFIG_IWMMXT
+	struct iwmmxt_sigframe	iwmmxt;
+#endif
+#if 0 && defined CONFIG_VFP /* Not yet saved.  */
+	struct vfp_sigframe	vfp;
+#endif
+	/* Something that isn't a valid magic number for any coprocessor.  */
+	unsigned long		end_magic;
+} __attribute__((__aligned__(8)));
+
+#endif
+
 #endif /* !_ASMARM_UCONTEXT_H */
diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
index cbf39a5..1e891f8 100644
--- a/include/asm-arm/unistd.h
+++ b/include/asm-arm/unistd.h
@@ -13,8 +13,6 @@
 #ifndef __ASM_ARM_UNISTD_H
 #define __ASM_ARM_UNISTD_H
 
-#include <linux/linkage.h>
-
 #define __NR_OABI_SYSCALL_BASE	0x900000
 
 #if defined(__thumb__) || defined(__ARM_EABI__)
@@ -378,6 +376,9 @@
 #undef __NR_ipc
 #endif
 
+#ifdef __KERNEL__
+#include <linux/linkage.h>
+
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
 
@@ -526,7 +527,6 @@
   __syscall_return(type,__res);						\
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
@@ -547,7 +547,6 @@
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_SOCKETCALL
 #endif
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -571,7 +570,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -581,4 +580,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_ARM_UNISTD_H */
diff --git a/include/asm-arm/vga.h b/include/asm-arm/vga.h
index 926e5ee..1e0b913 100644
--- a/include/asm-arm/vga.h
+++ b/include/asm-arm/vga.h
@@ -4,7 +4,7 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 
-#define VGA_MAP_MEM(x)	(PCIMEM_BASE + (x))
+#define VGA_MAP_MEM(x,s)	(PCIMEM_BASE + (x))
 
 #define vga_readb(x)	(*((volatile unsigned char *)x))
 #define vga_writeb(x,y)	(*((volatile unsigned char *)y) = (x))
diff --git a/include/asm-arm26/atomic.h b/include/asm-arm26/atomic.h
index 1552c86..97e944f 100644
--- a/include/asm-arm26/atomic.h
+++ b/include/asm-arm26/atomic.h
@@ -20,7 +20,6 @@
 #ifndef __ASM_ARM_ATOMIC_H
 #define __ASM_ARM_ATOMIC_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #error SMP is NOT supported
diff --git a/include/asm-arm26/bug.h b/include/asm-arm26/bug.h
index 7177c73..8545d58 100644
--- a/include/asm-arm26/bug.h
+++ b/include/asm-arm26/bug.h
@@ -1,7 +1,6 @@
 #ifndef _ASMARM_BUG_H
 #define _ASMARM_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
diff --git a/include/asm-arm26/dma.h b/include/asm-arm26/dma.h
index 995e223..4326ba8 100644
--- a/include/asm-arm26/dma.h
+++ b/include/asm-arm26/dma.h
@@ -3,7 +3,6 @@
 
 typedef unsigned int dmach_t;
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/memory.h>
diff --git a/include/asm-arm26/floppy.h b/include/asm-arm26/floppy.h
index 9e090ad..a18af06 100644
--- a/include/asm-arm26/floppy.h
+++ b/include/asm-arm26/floppy.h
@@ -22,7 +22,7 @@
 
 #define fd_inb(port)		inb((port))
 #define fd_request_irq()	request_irq(IRQ_FLOPPYDISK,floppy_interrupt,\
-					SA_INTERRUPT|SA_SAMPLE_RANDOM,"floppy",NULL)
+					SA_INTERRUPT,"floppy",NULL)
 #define fd_free_irq()		free_irq(IRQ_FLOPPYDISK,NULL)
 #define fd_disable_irq()	disable_irq(IRQ_FLOPPYDISK)
 #define fd_enable_irq()		enable_irq(IRQ_FLOPPYDISK)
diff --git a/include/asm-arm26/hardirq.h b/include/asm-arm26/hardirq.h
index 87c19d2..e717742 100644
--- a/include/asm-arm26/hardirq.h
+++ b/include/asm-arm26/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <asm/irq.h>
diff --git a/include/asm-arm26/hardware.h b/include/asm-arm26/hardware.h
index 82fc55e..801df0b 100644
--- a/include/asm-arm26/hardware.h
+++ b/include/asm-arm26/hardware.h
@@ -16,7 +16,6 @@
 #ifndef __ASM_HARDWARE_H
 #define __ASM_HARDWARE_H
 
-#include <linux/config.h>
 
 
 /*
diff --git a/include/asm-arm26/io.h b/include/asm-arm26/io.h
index 02f94d8..2aa033b 100644
--- a/include/asm-arm26/io.h
+++ b/include/asm-arm26/io.h
@@ -22,7 +22,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
 #include <asm/memory.h>
diff --git a/include/asm-arm26/irq.h b/include/asm-arm26/irq.h
index 06bd5a5..9aaac87 100644
--- a/include/asm-arm26/irq.h
+++ b/include/asm-arm26/irq.h
@@ -44,9 +44,5 @@
 
 int set_irq_type(unsigned int irq, unsigned int type);
 
-int setup_irq(unsigned int, struct irqaction *);
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif
 
diff --git a/include/asm-arm26/leds.h b/include/asm-arm26/leds.h
index 88ce412..12290ea 100644
--- a/include/asm-arm26/leds.h
+++ b/include/asm-arm26/leds.h
@@ -13,7 +13,6 @@
 #ifndef ASM_ARM_LEDS_H
 #define ASM_ARM_LEDS_H
 
-#include <linux/config.h>
 
 typedef enum {
 	led_idle_start,
diff --git a/include/asm-arm26/mach-types.h b/include/asm-arm26/mach-types.h
index b34045b..0aeaedc 100644
--- a/include/asm-arm26/mach-types.h
+++ b/include/asm-arm26/mach-types.h
@@ -6,7 +6,6 @@
 #ifndef __ASM_ARM_MACH_TYPE_H
 #define __ASM_ARM_MACH_TYPE_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 extern unsigned int __machine_arch_type;
diff --git a/include/asm-arm26/page.h b/include/asm-arm26/page.h
index d3f23ac..fa19de2 100644
--- a/include/asm-arm26/page.h
+++ b/include/asm-arm26/page.h
@@ -1,7 +1,6 @@
 #ifndef _ASMARM_PAGE_H
 #define _ASMARM_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index a590250..19ac910 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -13,7 +13,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/memory.h>
 
 /*
diff --git a/include/asm-arm26/serial.h b/include/asm-arm26/serial.h
index 5fc747d..dd86a71 100644
--- a/include/asm-arm26/serial.h
+++ b/include/asm-arm26/serial.h
@@ -14,7 +14,6 @@
 #ifndef __ASM_SERIAL_H
 #define __ASM_SERIAL_H
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff --git a/include/asm-arm26/smp.h b/include/asm-arm26/smp.h
index 5ca7716..38349ec 100644
--- a/include/asm-arm26/smp.h
+++ b/include/asm-arm26/smp.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #error SMP not supported
diff --git a/include/asm-arm26/sysirq.h b/include/asm-arm26/sysirq.h
index cad250c..81dca90 100644
--- a/include/asm-arm26/sysirq.h
+++ b/include/asm-arm26/sysirq.h
@@ -11,7 +11,6 @@
  *   04-04-1998 PJB     Merged arc and a5k versions
  */
 
-#include <linux/config.h>
 
 #if defined(CONFIG_ARCH_A5K)
 #define IRQ_PRINTER             0
diff --git a/include/asm-arm26/system.h b/include/asm-arm26/system.h
index 7028849..d1f69d7 100644
--- a/include/asm-arm26/system.h
+++ b/include/asm-arm26/system.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * This is used to ensure the compiler did actually allocate the register we
diff --git a/include/asm-arm26/unistd.h b/include/asm-arm26/unistd.h
index be4c2fb..70eb6d9 100644
--- a/include/asm-arm26/unistd.h
+++ b/include/asm-arm26/unistd.h
@@ -14,8 +14,6 @@
 #ifndef __ASM_ARM_UNISTD_H
 #define __ASM_ARM_UNISTD_H
 
-#include <linux/linkage.h>
-
 #define __NR_SYSCALL_BASE	0x900000
 
 /*
@@ -312,6 +310,9 @@
 #define __ARM_NR_cacheflush		(__ARM_NR_BASE+2)
 #define __ARM_NR_usr26			(__ARM_NR_BASE+3)
 
+#ifdef __KERNEL__
+#include <linux/linkage.h>
+
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
 
@@ -443,7 +444,6 @@
   __syscall_return(type,__res);						\
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -462,7 +462,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -486,7 +485,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -496,4 +495,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_ARM_UNISTD_H */
diff --git a/include/asm-cris/arch-v10/io.h b/include/asm-cris/arch-v10/io.h
index dd39198..11ef5b5 100644
--- a/include/asm-cris/arch-v10/io.h
+++ b/include/asm-cris/arch-v10/io.h
@@ -2,7 +2,6 @@
 #define _ASM_ARCH_CRIS_IO_H
 
 #include <asm/arch/svinto.h>
-#include <linux/config.h>
 
 /* Etrax shadow registers - which live in arch/cris/kernel/shadows.c */
 
diff --git a/include/asm-cris/arch-v10/page.h b/include/asm-cris/arch-v10/page.h
index 407e6e6..7d8307a 100644
--- a/include/asm-cris/arch-v10/page.h
+++ b/include/asm-cris/arch-v10/page.h
@@ -1,7 +1,6 @@
 #ifndef _CRIS_ARCH_PAGE_H
 #define _CRIS_ARCH_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-cris/arch-v10/system.h b/include/asm-cris/arch-v10/system.h
index 1ac7b63..4a9cd36 100644
--- a/include/asm-cris/arch-v10/system.h
+++ b/include/asm-cris/arch-v10/system.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_CRIS_ARCH_SYSTEM_H
 #define __ASM_CRIS_ARCH_SYSTEM_H
 
-#include <linux/config.h>
 
 /* read the CPU version register */
 
diff --git a/include/asm-cris/arch-v32/io.h b/include/asm-cris/arch-v32/io.h
index 043c9ce..5efe4d9 100644
--- a/include/asm-cris/arch-v32/io.h
+++ b/include/asm-cris/arch-v32/io.h
@@ -4,7 +4,6 @@
 #include <asm/arch/hwregs/reg_map.h>
 #include <asm/arch/hwregs/reg_rdwr.h>
 #include <asm/arch/hwregs/gio_defs.h>
-#include <linux/config.h>
 
 enum crisv32_io_dir
 {
diff --git a/include/asm-cris/arch-v32/irq.h b/include/asm-cris/arch-v32/irq.h
index d35aa81..eeb0a80 100644
--- a/include/asm-cris/arch-v32/irq.h
+++ b/include/asm-cris/arch-v32/irq.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_ARCH_IRQ_H
 #define _ASM_ARCH_IRQ_H
 
-#include <linux/config.h>
 #include "hwregs/intr_vect.h"
 
 /* Number of non-cpu interrupts. */
diff --git a/include/asm-cris/arch-v32/page.h b/include/asm-cris/arch-v32/page.h
index 77827bc..fa454fe 100644
--- a/include/asm-cris/arch-v32/page.h
+++ b/include/asm-cris/arch-v32/page.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_CRIS_ARCH_PAGE_H
 #define _ASM_CRIS_ARCH_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-cris/arch-v32/processor.h b/include/asm-cris/arch-v32/processor.h
index 32bf2e5..5553b0c 100644
--- a/include/asm-cris/arch-v32/processor.h
+++ b/include/asm-cris/arch-v32/processor.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_CRIS_ARCH_PROCESSOR_H
 #define _ASM_CRIS_ARCH_PROCESSOR_H
 
-#include <linux/config.h>
 
 /* Return current instruction pointer. */
 #define current_text_addr() \
diff --git a/include/asm-cris/arch-v32/system.h b/include/asm-cris/arch-v32/system.h
index a3d75d5..d20e2d6 100644
--- a/include/asm-cris/arch-v32/system.h
+++ b/include/asm-cris/arch-v32/system.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_CRIS_ARCH_SYSTEM_H
 #define _ASM_CRIS_ARCH_SYSTEM_H
 
-#include <linux/config.h>
 
 /* Read the CPU version register. */
 static inline unsigned long rdvr(void)
diff --git a/include/asm-cris/eshlibld.h b/include/asm-cris/eshlibld.h
index 2b577cd..10ce36c 100644
--- a/include/asm-cris/eshlibld.h
+++ b/include/asm-cris/eshlibld.h
@@ -32,7 +32,6 @@
 /* We have dependencies all over the place for the host system
    for xsim being a linux system, so let's not pretend anything
    else with #ifdef:s here until fixed.  */
-#include <linux/config.h>
 #include <linux/limits.h>
 
 /* Maybe do sanity checking if file input. */
diff --git a/include/asm-cris/etraxgpio.h b/include/asm-cris/etraxgpio.h
index 80ee10f..5d0028d 100644
--- a/include/asm-cris/etraxgpio.h
+++ b/include/asm-cris/etraxgpio.h
@@ -25,7 +25,6 @@
 #ifndef _ASM_ETRAXGPIO_H
 #define _ASM_ETRAXGPIO_H
 
-#include <linux/config.h>
 /* etraxgpio _IOC_TYPE, bits 8 to 15 in ioctl cmd */
 #ifdef CONFIG_ETRAX_ARCH_V10
 #define ETRAXGPIO_IOCTYPE 43
diff --git a/include/asm-cris/fasttimer.h b/include/asm-cris/fasttimer.h
index 6952202..a3a7713 100644
--- a/include/asm-cris/fasttimer.h
+++ b/include/asm-cris/fasttimer.h
@@ -5,7 +5,6 @@
  * This may be useful in other OS than Linux so use 2 space indentation...
  * Copyright (C) 2000, 2002 Axis Communications AB
  */
-#include <linux/config.h>
 #include <linux/time.h> /* struct timeval */
 #include <linux/timex.h>
 
diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h
index 3787633..81832e9 100644
--- a/include/asm-cris/page.h
+++ b/include/asm-cris/page.h
@@ -1,7 +1,6 @@
 #ifndef _CRIS_PAGE_H
 #define _CRIS_PAGE_H
 
-#include <linux/config.h>
 #include <asm/arch/page.h>
 
 /* PAGE_SHIFT determines the page size */
diff --git a/include/asm-cris/pci.h b/include/asm-cris/pci.h
index 2064bc1..b2ac8a3 100644
--- a/include/asm-cris/pci.h
+++ b/include/asm-cris/pci.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_CRIS_PCI_H
 #define __ASM_CRIS_PCI_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 #include <linux/mm.h>		/* for struct page */
diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
index 70a8325..5d76c1c 100644
--- a/include/asm-cris/pgtable.h
+++ b/include/asm-cris/pgtable.h
@@ -9,7 +9,6 @@
 #include <asm-generic/pgtable-nopmd.h>
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <asm/mmu.h>
 #endif
diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h
index 961e2bc..568da1d 100644
--- a/include/asm-cris/processor.h
+++ b/include/asm-cris/processor.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_CRIS_PROCESSOR_H
 #define __ASM_CRIS_PROCESSOR_H
 
-#include <linux/config.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/ptrace.h>
diff --git a/include/asm-cris/rtc.h b/include/asm-cris/rtc.h
index 97c1303..cb4bf92 100644
--- a/include/asm-cris/rtc.h
+++ b/include/asm-cris/rtc.h
@@ -4,7 +4,6 @@
 #define __RTC_H__
 
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ETRAX_DS1302
    /* Dallas DS1302 clock/calendar register numbers. */
diff --git a/include/asm-cris/tlbflush.h b/include/asm-cris/tlbflush.h
index c522380..0569612 100644
--- a/include/asm-cris/tlbflush.h
+++ b/include/asm-cris/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _CRIS_TLBFLUSH_H
 #define _CRIS_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
diff --git a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
index bb2dfe4..c2954e9 100644
--- a/include/asm-cris/unistd.h
+++ b/include/asm-cris/unistd.h
@@ -295,11 +295,11 @@
 #define __NR_request_key	287
 #define __NR_keyctl		288
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 289
 
 
-
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -379,12 +379,10 @@
  * complaints.  We don't want to use -fno-builtin, so just use a
  * different name when in the kernel.
  */
-#ifdef __KERNEL__
 #define _exit kernel_syscall_exit
-#endif
 static inline _syscall1(int,_exit,int,exitcode)
 static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 
 /*
@@ -395,4 +393,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_CRIS_UNISTD_H_ */
diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h
index 5d9f84b..066386a 100644
--- a/include/asm-frv/atomic.h
+++ b/include/asm-frv/atomic.h
@@ -14,7 +14,6 @@
 #ifndef _ASM_ATOMIC_H
 #define _ASM_ATOMIC_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/spr-regs.h>
 
@@ -228,7 +227,7 @@
 		break;								\
 										\
 	default:								\
-		__xg_orig = 0;							\
+		__xg_orig = (__typeof__(__xg_orig))0;				\
 		asm volatile("break");						\
 		break;								\
 	}									\
@@ -248,7 +247,7 @@
 	switch (sizeof(__xg_orig)) {								\
 	case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr);	break;	\
 	default:										\
-		__xg_orig = 0;									\
+		__xg_orig = (__typeof__(__xg_orig))0;									\
 		asm volatile("break");								\
 		break;										\
 	}											\
diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
index 6344d06..980ae1b 100644
--- a/include/asm-frv/bitops.h
+++ b/include/asm-frv/bitops.h
@@ -14,7 +14,6 @@
 #ifndef _ASM_BITOPS_H
 #define _ASM_BITOPS_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/byteorder.h>
 #include <asm/system.h>
diff --git a/include/asm-frv/bug.h b/include/asm-frv/bug.h
index 451712c..6b1b44d 100644
--- a/include/asm-frv/bug.h
+++ b/include/asm-frv/bug.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_BUG_H
 #define _ASM_BUG_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 
 #ifdef CONFIG_BUG
diff --git a/include/asm-frv/cache.h b/include/asm-frv/cache.h
index cf69b63..2797163 100644
--- a/include/asm-frv/cache.h
+++ b/include/asm-frv/cache.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_CACHE_H
 #define __ASM_CACHE_H
 
-#include <linux/config.h>
 
 /* bytes per L1 cache line */
 #define L1_CACHE_SHIFT		(CONFIG_FRV_L1_CACHE_SHIFT)
diff --git a/include/asm-frv/checksum.h b/include/asm-frv/checksum.h
index 10236f68..42bf0db 100644
--- a/include/asm-frv/checksum.h
+++ b/include/asm-frv/checksum.h
@@ -43,7 +43,7 @@
  * here even more important to align src and dst on a 32-bit (or even
  * better 64-bit) boundary
  */
-extern unsigned int csum_partial_copy_from_user(const char *src, char *dst,
+extern unsigned int csum_partial_copy_from_user(const char __user *src, char *dst,
 						int len, int sum, int *csum_err);
 
 #define csum_partial_copy_nocheck(src, dst, len, sum)	\
diff --git a/include/asm-frv/dma.h b/include/asm-frv/dma.h
index d8f9a2f..18d6bb8 100644
--- a/include/asm-frv/dma.h
+++ b/include/asm-frv/dma.h
@@ -14,7 +14,6 @@
 
 //#define DMA_DEBUG 1
 
-#include <linux/config.h>
 #include <linux/interrupt.h>
 
 #undef MAX_DMA_CHANNELS		/* don't use kernel/dma.c */
diff --git a/include/asm-frv/elf.h b/include/asm-frv/elf.h
index 7d2098f..38656da 100644
--- a/include/asm-frv/elf.h
+++ b/include/asm-frv/elf.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_ELF_H
 #define __ASM_ELF_H
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff --git a/include/asm-frv/fpu.h b/include/asm-frv/fpu.h
index b1178f8..d73c60b 100644
--- a/include/asm-frv/fpu.h
+++ b/include/asm-frv/fpu.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_FPU_H
 #define __ASM_FPU_H
 
-#include <linux/config.h>
 
 /*
  * MAX floating point unit state size (FSAVE/FRESTORE)
diff --git a/include/asm-frv/hardirq.h b/include/asm-frv/hardirq.h
index 6851239..7581b5a 100644
--- a/include/asm-frv/hardirq.h
+++ b/include/asm-frv/hardirq.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h
index 295f74a..e2247c2 100644
--- a/include/asm-frv/highmem.h
+++ b/include/asm-frv/highmem.h
@@ -17,7 +17,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <asm/mem-layout.h>
 #include <asm/spr-regs.h>
@@ -135,7 +134,7 @@
 
 	default:
 		BUG();
-		return 0;
+		return NULL;
 	}
 }
 
diff --git a/include/asm-frv/ide.h b/include/asm-frv/ide.h
index ae031ea..f0bd2cb 100644
--- a/include/asm-frv/ide.h
+++ b/include/asm-frv/ide.h
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/irq.h>
diff --git a/include/asm-frv/io.h b/include/asm-frv/io.h
index 01247cb..7765f55 100644
--- a/include/asm-frv/io.h
+++ b/include/asm-frv/io.h
@@ -17,7 +17,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/virtconvert.h>
 #include <asm/string.h>
@@ -41,13 +40,13 @@
 //#define __iormb() asm volatile("membar")
 //#define __iowmb() asm volatile("membar")
 
-#define __raw_readb(addr) __builtin_read8((void *) (addr))
-#define __raw_readw(addr) __builtin_read16((void *) (addr))
-#define __raw_readl(addr) __builtin_read32((void *) (addr))
+#define __raw_readb __builtin_read8
+#define __raw_readw __builtin_read16
+#define __raw_readl __builtin_read32
 
-#define __raw_writeb(datum, addr) __builtin_write8((void *) (addr), datum)
-#define __raw_writew(datum, addr) __builtin_write16((void *) (addr), datum)
-#define __raw_writel(datum, addr) __builtin_write32((void *) (addr), datum)
+#define __raw_writeb(datum, addr) __builtin_write8(addr, datum)
+#define __raw_writew(datum, addr) __builtin_write16(addr, datum)
+#define __raw_writel(datum, addr) __builtin_write32(addr, datum)
 
 static inline void io_outsb(unsigned int addr, const void *buf, int len)
 {
@@ -117,7 +116,7 @@
 	memset((void __force *) addr, val, count);
 }
 
-static inline void memcpy_fromio(void *dst, volatile void __iomem *src, int count)
+static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
 {
 	memcpy(dst, (void __force *) src, count);
 }
@@ -129,12 +128,12 @@
 
 static inline uint8_t inb(unsigned long addr)
 {
-	return __builtin_read8((void *)addr);
+	return __builtin_read8((void __iomem *)addr);
 }
 
 static inline uint16_t inw(unsigned long addr)
 {
-	uint16_t ret = __builtin_read16((void *)addr);
+	uint16_t ret = __builtin_read16((void __iomem *)addr);
 
 	if (__is_PCI_IO(addr))
 		ret = _swapw(ret);
@@ -144,7 +143,7 @@
 
 static inline uint32_t inl(unsigned long addr)
 {
-	uint32_t ret = __builtin_read32((void *)addr);
+	uint32_t ret = __builtin_read32((void __iomem *)addr);
 
 	if (__is_PCI_IO(addr))
 		ret = _swapl(ret);
@@ -154,21 +153,21 @@
 
 static inline void outb(uint8_t datum, unsigned long addr)
 {
-	__builtin_write8((void *)addr, datum);
+	__builtin_write8((void __iomem *)addr, datum);
 }
 
 static inline void outw(uint16_t datum, unsigned long addr)
 {
 	if (__is_PCI_IO(addr))
 		datum = _swapw(datum);
-	__builtin_write16((void *)addr, datum);
+	__builtin_write16((void __iomem *)addr, datum);
 }
 
 static inline void outl(uint32_t datum, unsigned long addr)
 {
 	if (__is_PCI_IO(addr))
 		datum = _swapl(datum);
-	__builtin_write32((void *)addr, datum);
+	__builtin_write32((void __iomem *)addr, datum);
 }
 
 #define inb_p(addr)	inb(addr)
@@ -190,12 +189,12 @@
 
 static inline uint8_t readb(const volatile void __iomem *addr)
 {
-	return __builtin_read8((volatile uint8_t __force *) addr);
+	return __builtin_read8((__force void volatile __iomem *) addr);
 }
 
 static inline uint16_t readw(const volatile void __iomem *addr)
 {
-	uint16_t ret =	__builtin_read16((volatile uint16_t __force *)addr);
+	uint16_t ret =	__builtin_read16((__force void volatile __iomem *)addr);
 
 	if (__is_PCI_MEM(addr))
 		ret = _swapw(ret);
@@ -204,7 +203,7 @@
 
 static inline uint32_t readl(const volatile void __iomem *addr)
 {
-	uint32_t ret =	__builtin_read32((volatile uint32_t __force *)addr);
+	uint32_t ret =	__builtin_read32((__force void volatile __iomem *)addr);
 
 	if (__is_PCI_MEM(addr))
 		ret = _swapl(ret);
@@ -218,7 +217,7 @@
 
 static inline void writeb(uint8_t datum, volatile void __iomem *addr)
 {
-	__builtin_write8((volatile uint8_t __force *) addr, datum);
+	__builtin_write8(addr, datum);
 	if (__is_PCI_MEM(addr))
 		__flush_PCI_writes();
 }
@@ -228,7 +227,7 @@
 	if (__is_PCI_MEM(addr))
 		datum = _swapw(datum);
 
-	__builtin_write16((volatile uint16_t __force *) addr, datum);
+	__builtin_write16(addr, datum);
 	if (__is_PCI_MEM(addr))
 		__flush_PCI_writes();
 }
@@ -238,7 +237,7 @@
 	if (__is_PCI_MEM(addr))
 		datum = _swapl(datum);
 
-	__builtin_write32((volatile uint32_t __force *) addr, datum);
+	__builtin_write32(addr, datum);
 	if (__is_PCI_MEM(addr))
 		__flush_PCI_writes();
 }
@@ -272,7 +271,7 @@
 	return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
 }
 
-extern void iounmap(void __iomem *addr);
+extern void iounmap(void volatile __iomem *addr);
 
 static inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
diff --git a/include/asm-frv/irq.h b/include/asm-frv/irq.h
index 2c16d8d..58b6192 100644
--- a/include/asm-frv/irq.h
+++ b/include/asm-frv/irq.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_IRQ_H_
 #define _ASM_IRQ_H_
 
-#include <linux/config.h>
 
 /*
  * the system has an on-CPU PIC and another PIC on the FPGA and other PICs on other peripherals,
diff --git a/include/asm-frv/mb-regs.h b/include/asm-frv/mb-regs.h
index 93fa732..219e5f9 100644
--- a/include/asm-frv/mb-regs.h
+++ b/include/asm-frv/mb-regs.h
@@ -16,6 +16,17 @@
 #include <asm/sections.h>
 #include <asm/mem-layout.h>
 
+#ifndef __ASSEMBLY__
+/* gcc builtins, annotated */
+
+unsigned long __builtin_read8(volatile void __iomem *);
+unsigned long __builtin_read16(volatile void __iomem *);
+unsigned long __builtin_read32(volatile void __iomem *);
+void __builtin_write8(volatile void __iomem *, unsigned char);
+void __builtin_write16(volatile void __iomem *, unsigned short);
+void __builtin_write32(volatile void __iomem *, unsigned long);
+#endif
+
 #define __region_IO	KERNEL_IO_START	/* the region from 0xe0000000 to 0xffffffff has suitable
 					 * protection laid over the top for use in memory-mapped
 					 * I/O
@@ -59,7 +70,7 @@
 #define __region_PCI_MEM	(__region_CS2 + 0x08000000UL)
 #define __flush_PCI_writes()						\
 do {									\
-	__builtin_write8((volatile void *) __region_PCI_MEM, 0);	\
+	__builtin_write8((volatile void __iomem *) __region_PCI_MEM, 0);	\
 } while(0)
 
 #define __is_PCI_IO(addr) \
@@ -83,15 +94,15 @@
 #define __set_LEDS(X)							\
 do {									\
 	if (mb93090_mb00_detected)					\
-		__builtin_write32((void *) __addr_LEDS(), ~(X));	\
+		__builtin_write32((void __iomem *) __addr_LEDS(), ~(X));	\
 } while (0)
 #else
 #define __set_LEDS(X)
 #endif
 
 #define __addr_LCD()		(__region_CS2 + 0x01200008UL)
-#define __get_LCD(B)		__builtin_read32((volatile void *) (B))
-#define __set_LCD(B,X)		__builtin_write32((volatile void *) (B), (X))
+#define __get_LCD(B)		__builtin_read32((volatile void __iomem *) (B))
+#define __set_LCD(B,X)		__builtin_write32((volatile void __iomem *) (B), (X))
 
 #define LCD_D			0x000000ff		/* LCD data bus */
 #define LCD_RW			0x00000100		/* LCD R/W signal */
@@ -161,11 +172,11 @@
 #define __get_CLKIN()		66000000UL
 
 #define __addr_LEDS()		(__region_CS2 + 0x00000023UL)
-#define __set_LEDS(X)		__builtin_write8((volatile void *) __addr_LEDS(), (X))
+#define __set_LEDS(X)		__builtin_write8((volatile void __iomem *) __addr_LEDS(), (X))
 
 #define __addr_FPGATR()		(__region_CS2 + 0x00000030UL)
-#define __set_FPGATR(X)		__builtin_write32((volatile void *) __addr_FPGATR(), (X))
-#define __get_FPGATR()		__builtin_read32((volatile void *) __addr_FPGATR())
+#define __set_FPGATR(X)		__builtin_write32((volatile void __iomem *) __addr_FPGATR(), (X))
+#define __get_FPGATR()		__builtin_read32((volatile void __iomem *) __addr_FPGATR())
 
 #define MB93093_FPGA_FPGATR_AUDIO_CLK	0x00000003
 
@@ -180,7 +191,7 @@
 #define MB93093_FPGA_SWR_PUSHSWMASK	(0x1F<<26)
 #define MB93093_FPGA_SWR_PUSHSW4	(1<<29)
 
-#define __addr_FPGA_SWR		((volatile void *)(__region_CS2 + 0x28UL))
+#define __addr_FPGA_SWR		((volatile void __iomem *)(__region_CS2 + 0x28UL))
 #define __get_FPGA_PUSHSW1_5()	(__builtin_read32(__addr_FPGA_SWR) & MB93093_FPGA_SWR_PUSHSWMASK)
 
 
diff --git a/include/asm-frv/mmu_context.h b/include/asm-frv/mmu_context.h
index 4fb9ea3..72edcaa 100644
--- a/include/asm-frv/mmu_context.h
+++ b/include/asm-frv/mmu_context.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_MMU_CONTEXT_H
 #define _ASM_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
index dc0f7e0..134cc0c 100644
--- a/include/asm-frv/page.h
+++ b/include/asm-frv/page.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/virtconvert.h>
 #include <asm/mem-layout.h>
 #include <asm/sections.h>
diff --git a/include/asm-frv/pci.h b/include/asm-frv/pci.h
index 598b0c6..f35a451 100644
--- a/include/asm-frv/pci.h
+++ b/include/asm-frv/pci.h
@@ -13,7 +13,6 @@
 #ifndef ASM_PCI_H
 #define	ASM_PCI_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <asm-generic/pci-dma-compat.h>
diff --git a/include/asm-frv/pgalloc.h b/include/asm-frv/pgalloc.h
index 1bd28f4..ce982a6 100644
--- a/include/asm-frv/pgalloc.h
+++ b/include/asm-frv/pgalloc.h
@@ -15,7 +15,6 @@
 #ifndef _ASM_PGALLOC_H
 #define _ASM_PGALLOC_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/virtconvert.h>
 
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index d1c3b18..7af7485 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -16,7 +16,6 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
-#include <linux/config.h>
 #include <asm/mem-layout.h>
 #include <asm/setup.h>
 #include <asm/processor.h>
diff --git a/include/asm-frv/processor.h b/include/asm-frv/processor.h
index 5228c18..1c4dba1 100644
--- a/include/asm-frv/processor.h
+++ b/include/asm-frv/processor.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_PROCESSOR_H
 #define _ASM_PROCESSOR_H
 
-#include <linux/config.h>
 #include <asm/mem-layout.h>
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-frv/segment.h b/include/asm-frv/segment.h
index 61222f0..e3616a6 100644
--- a/include/asm-frv/segment.h
+++ b/include/asm-frv/segment.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_SEGMENT_H
 #define _ASM_SEGMENT_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-frv/serial.h b/include/asm-frv/serial.h
index 6917d55..dbb8259 100644
--- a/include/asm-frv/serial.h
+++ b/include/asm-frv/serial.h
@@ -6,7 +6,6 @@
  *
  * Based on linux/include/asm-i386/serial.h
  */
-#include <linux/config.h>
 #include <asm/serial-regs.h>
 
 /*
diff --git a/include/asm-frv/signal.h b/include/asm-frv/signal.h
index 6736689..dcc1b35 100644
--- a/include/asm-frv/signal.h
+++ b/include/asm-frv/signal.h
@@ -114,13 +114,13 @@
 	__sighandler_t sa_handler;
 	old_sigset_t sa_mask;
 	unsigned long sa_flags;
-	void (*sa_restorer)(void);
+	__sigrestore_t sa_restorer;
 };
 
 struct sigaction {
 	__sighandler_t sa_handler;
 	unsigned long sa_flags;
-	void (*sa_restorer)(void);
+	__sigrestore_t sa_restorer;
 	sigset_t sa_mask;		/* mask last for extensibility */
 };
 
@@ -146,7 +146,7 @@
 #endif /* __KERNEL__ */
 
 typedef struct sigaltstack {
-	void *ss_sp;
+	void __user *ss_sp;
 	int ss_flags;
 	size_t ss_size;
 } stack_t;
diff --git a/include/asm-frv/smp.h b/include/asm-frv/smp.h
index 5ca7716..38349ec 100644
--- a/include/asm-frv/smp.h
+++ b/include/asm-frv/smp.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #error SMP not supported
diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h
index 1734ed9..351863d 100644
--- a/include/asm-frv/system.h
+++ b/include/asm-frv/system.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 #include <asm/atomic.h>
 
diff --git a/include/asm-frv/tlbflush.h b/include/asm-frv/tlbflush.h
index bc346262..da3a317 100644
--- a/include/asm-frv/tlbflush.h
+++ b/include/asm-frv/tlbflush.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_TLBFLUSH_H
 #define _ASM_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
diff --git a/include/asm-frv/types.h b/include/asm-frv/types.h
index 2560f59..1b6d192 100644
--- a/include/asm-frv/types.h
+++ b/include/asm-frv/types.h
@@ -46,7 +46,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
diff --git a/include/asm-frv/uaccess.h b/include/asm-frv/uaccess.h
index a1d1404..3d90e10 100644
--- a/include/asm-frv/uaccess.h
+++ b/include/asm-frv/uaccess.h
@@ -22,7 +22,7 @@
 
 #define HAVE_ARCH_UNMAPPED_AREA	/* we decide where to put mmaps */
 
-#define __ptr(x) ((unsigned long *)(x))
+#define __ptr(x) ((unsigned long __force *)(x))
 
 #define VERIFY_READ	0
 #define VERIFY_WRITE	1
@@ -64,7 +64,7 @@
 
 #define __range_ok(addr,size) ___range_ok((unsigned long) (addr), (unsigned long) (size))
 
-#define access_ok(type,addr,size) (__range_ok((addr), (size)) == 0)
+#define access_ok(type,addr,size) (__range_ok((void __user *)(addr), (size)) == 0)
 #define __access_ok(addr,size) (__range_ok((addr), (size)) == 0)
 
 /*
@@ -97,6 +97,7 @@
 	int __pu_err = 0;						\
 									\
 	typeof(*(ptr)) __pu_val = (x);					\
+	__chk_user_ptr(ptr);						\
 									\
 	switch (sizeof (*(ptr))) {					\
 	case 1:								\
@@ -120,7 +121,7 @@
 
 #define put_user(x, ptr)			\
 ({						\
-	typeof(&*ptr) _p = (ptr);		\
+	typeof(*(ptr)) __user *_p = (ptr);	\
 	int _e;					\
 						\
 	_e = __range_ok(_p, sizeof(*_p));	\
@@ -175,33 +176,44 @@
  */
 #define __get_user(x, ptr)						\
 ({									\
-	typeof(*(ptr)) __gu_val = 0;					\
 	int __gu_err = 0;						\
+	__chk_user_ptr(ptr);						\
 									\
 	switch (sizeof(*(ptr))) {					\
-	case 1:								\
-		__get_user_asm(__gu_err, *(u8*)&__gu_val, ptr, "ub", "=r"); \
+	case 1: {							\
+		unsigned char __gu_val;					\
+		__get_user_asm(__gu_err, __gu_val, ptr, "ub", "=r");	\
+		(x) = *(__force __typeof__(*(ptr)) *) &__gu_val;	\
 		break;							\
-	case 2:								\
-		__get_user_asm(__gu_err, *(u16*)&__gu_val, ptr, "uh", "=r"); \
+	}								\
+	case 2: {							\
+		unsigned short __gu_val;				\
+		__get_user_asm(__gu_err, __gu_val, ptr, "uh", "=r");	\
+		(x) = *(__force __typeof__(*(ptr)) *) &__gu_val;	\
 		break;							\
-	case 4:								\
-		__get_user_asm(__gu_err, *(u32*)&__gu_val, ptr, "", "=r"); \
+	}								\
+	case 4: {							\
+		unsigned int __gu_val;					\
+		__get_user_asm(__gu_err, __gu_val, ptr, "", "=r");	\
+		(x) = *(__force __typeof__(*(ptr)) *) &__gu_val;	\
 		break;							\
-	case 8:								\
-		__get_user_asm(__gu_err, *(u64*)&__gu_val, ptr, "d", "=e"); \
+	}								\
+	case 8: {							\
+		unsigned long long __gu_val;				\
+		__get_user_asm(__gu_err, __gu_val, ptr, "d", "=e");	\
+		(x) = *(__force __typeof__(*(ptr)) *) &__gu_val;	\
 		break;							\
+	}								\
 	default:							\
 		__gu_err = __get_user_bad();				\
 		break;							\
 	}								\
-	(x) = __gu_val;							\
 	__gu_err;							\
 })
 
 #define get_user(x, ptr)			\
 ({						\
-	typeof(&*ptr) _p = (ptr);		\
+	const typeof(*(ptr)) __user *_p = (ptr);\
 	int _e;					\
 						\
 	_e = __range_ok(_p, sizeof(*_p));	\
@@ -248,19 +260,20 @@
 /*
  *
  */
+#define ____force(x) (__force void *)(void __user *)(x)
 #ifdef CONFIG_MMU
 extern long __memset_user(void *dst, unsigned long count);
 extern long __memcpy_user(void *dst, const void *src, unsigned long count);
 
-#define clear_user(dst,count)			__memset_user((dst), (count))
-#define __copy_from_user_inatomic(to, from, n)	__memcpy_user((to), (from), (n))
-#define __copy_to_user_inatomic(to, from, n)	__memcpy_user((to), (from), (n))
+#define clear_user(dst,count)			__memset_user(____force(dst), (count))
+#define __copy_from_user_inatomic(to, from, n)	__memcpy_user((to), ____force(from), (n))
+#define __copy_to_user_inatomic(to, from, n)	__memcpy_user(____force(to), (from), (n))
 
 #else
 
-#define clear_user(dst,count)			(memset((dst), 0, (count)), 0)
-#define __copy_from_user_inatomic(to, from, n)	(memcpy((to), (from), (n)), 0)
-#define __copy_to_user_inatomic(to, from, n)	(memcpy((to), (from), (n)), 0)
+#define clear_user(dst,count)			(memset(____force(dst), 0, (count)), 0)
+#define __copy_from_user_inatomic(to, from, n)	(memcpy((to), ____force(from), (n)), 0)
+#define __copy_to_user_inatomic(to, from, n)	(memcpy(____force(to), (from), (n)), 0)
 
 #endif
 
@@ -278,7 +291,7 @@
        return __copy_from_user_inatomic(to, from, n);
 }
 
-static inline long copy_from_user(void *to, const void *from, unsigned long n)
+static inline long copy_from_user(void *to, const void __user *from, unsigned long n)
 {
 	unsigned long ret = n;
 
@@ -291,16 +304,13 @@
 	return ret;
 }
 
-static inline long copy_to_user(void *to, const void *from, unsigned long n)
+static inline long copy_to_user(void __user *to, const void *from, unsigned long n)
 {
 	return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n;
 }
 
-#define copy_to_user_ret(to,from,n,retval)	({ if (copy_to_user(to,from,n)) return retval; })
-#define copy_from_user_ret(to,from,n,retval)	({ if (copy_from_user(to,from,n)) return retval; })
-
-extern long strncpy_from_user(char *dst, const char *src, long count);
-extern long strnlen_user(const char *src, long count);
+extern long strncpy_from_user(char *dst, const char __user *src, long count);
+extern long strnlen_user(const char __user *src, long count);
 
 #define strlen_user(str) strnlen_user(str, 32767)
 
diff --git a/include/asm-frv/unaligned.h b/include/asm-frv/unaligned.h
index a0d199b..dc8e9c9 100644
--- a/include/asm-frv/unaligned.h
+++ b/include/asm-frv/unaligned.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_UNALIGNED_H
 #define _ASM_UNALIGNED_H
 
-#include <linux/config.h>
 
 /*
  * Unaligned accesses on uClinux can't be performed in a fault handler - the
diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
index 2662a3e..b80dbd8 100644
--- a/include/asm-frv/unistd.h
+++ b/include/asm-frv/unistd.h
@@ -306,7 +306,7 @@
 #define __NR_mknodat		297
 #define __NR_fchownat		298
 #define __NR_futimesat		299
-#define __NR_newfstatat		300
+#define __NR_fstatat64		300
 #define __NR_unlinkat		301
 #define __NR_renameat		302
 #define __NR_linkat		303
@@ -317,6 +317,8 @@
 #define __NR_pselect6		308
 #define __NR_ppoll		309
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 310
 
 /*
@@ -458,28 +460,10 @@
  * some others too.
  */
 #define __NR__exit __NR_exit
-static inline _syscall0(int,pause)
-static inline _syscall0(int,sync)
-static inline _syscall0(pid_t,setsid)
-static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
-static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
-static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
-static inline _syscall1(int,dup,int,fd)
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
-static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
-static inline _syscall1(int,delete_module,const char *,name)
 
-static inline pid_t wait(int * wait_stat)
-{
-	return waitpid(-1,wait_stat,0);
-}
+#endif /* __KERNEL_SYSCALLS__ */
 
-#endif
-
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 /* #define __ARCH_WANT_OLD_READDIR */
 #define __ARCH_WANT_OLD_STAT
@@ -503,7 +487,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
 
 /*
  * "Conditional" syscalls
@@ -515,4 +498,5 @@
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_UNISTD_H_ */
diff --git a/include/asm-frv/virtconvert.h b/include/asm-frv/virtconvert.h
index a29a0ae..59788fa 100644
--- a/include/asm-frv/virtconvert.h
+++ b/include/asm-frv/virtconvert.h
@@ -17,7 +17,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/setup.h>
 
 #ifdef CONFIG_MMU
diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
index 1a565a9..8ceab7b 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -2,7 +2,6 @@
 #define _ASM_GENERIC_BUG_H
 
 #include <linux/compiler.h>
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 #ifndef HAVE_ARCH_BUG
@@ -39,4 +38,23 @@
 #endif
 #endif
 
+#define WARN_ON_ONCE(condition)				\
+({							\
+	static int __warn_once = 1;			\
+	int __ret = 0;					\
+							\
+	if (unlikely((condition) && __warn_once)) {	\
+		__warn_once = 0;			\
+		WARN_ON(1);				\
+		__ret = 1;				\
+	}						\
+	__ret;						\
+})
+
+#ifdef CONFIG_SMP
+# define WARN_ON_SMP(x)			WARN_ON(x)
+#else
+# define WARN_ON_SMP(x)			do { } while (0)
+#endif
+
 #endif
diff --git a/include/asm-generic/dma-mapping.h b/include/asm-generic/dma-mapping.h
index 1b35620..b541e48 100644
--- a/include/asm-generic/dma-mapping.h
+++ b/include/asm-generic/dma-mapping.h
@@ -7,7 +7,6 @@
 #ifndef _ASM_GENERIC_DMA_MAPPING_H
 #define _ASM_GENERIC_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
diff --git a/include/asm-generic/fcntl.h b/include/asm-generic/fcntl.h
index b663520..c154b9d 100644
--- a/include/asm-generic/fcntl.h
+++ b/include/asm-generic/fcntl.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_GENERIC_FCNTL_H
 #define _ASM_GENERIC_FCNTL_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
diff --git a/include/asm-generic/local.h b/include/asm-generic/local.h
index 9291c24..ab46929 100644
--- a/include/asm-generic/local.h
+++ b/include/asm-generic/local.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_GENERIC_LOCAL_H
 #define _ASM_GENERIC_LOCAL_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
 #include <asm/atomic.h>
diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h
index 0cfb086..8078cbd 100644
--- a/include/asm-generic/memory_model.h
+++ b/include/asm-generic/memory_model.h
@@ -23,29 +23,23 @@
 
 #endif /* CONFIG_DISCONTIGMEM */
 
-#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
-struct page;
-/* this is useful when inlined pfn_to_page is too big */
-extern struct page *pfn_to_page(unsigned long pfn);
-extern unsigned long page_to_pfn(struct page *page);
-#else
 /*
  * supports 3 memory models.
  */
 #if defined(CONFIG_FLATMEM)
 
-#define pfn_to_page(pfn)	(mem_map + ((pfn) - ARCH_PFN_OFFSET))
-#define page_to_pfn(page)	((unsigned long)((page) - mem_map) + \
+#define __pfn_to_page(pfn)	(mem_map + ((pfn) - ARCH_PFN_OFFSET))
+#define __page_to_pfn(page)	((unsigned long)((page) - mem_map) + \
 				 ARCH_PFN_OFFSET)
 #elif defined(CONFIG_DISCONTIGMEM)
 
-#define pfn_to_page(pfn)			\
+#define __pfn_to_page(pfn)			\
 ({	unsigned long __pfn = (pfn);		\
 	unsigned long __nid = arch_pfn_to_nid(pfn);  \
 	NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\
 })
 
-#define page_to_pfn(pg)							\
+#define __page_to_pfn(pg)						\
 ({	struct page *__pg = (pg);					\
 	struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg));	\
 	(unsigned long)(__pg - __pgdat->node_mem_map) +			\
@@ -57,18 +51,27 @@
  * Note: section's mem_map is encorded to reflect its start_pfn.
  * section[i].section_mem_map == mem_map's address - start_pfn;
  */
-#define page_to_pfn(pg)					\
+#define __page_to_pfn(pg)					\
 ({	struct page *__pg = (pg);				\
 	int __sec = page_to_section(__pg);			\
 	__pg - __section_mem_map_addr(__nr_to_section(__sec));	\
 })
 
-#define pfn_to_page(pfn)				\
+#define __pfn_to_page(pfn)				\
 ({	unsigned long __pfn = (pfn);			\
 	struct mem_section *__sec = __pfn_to_section(__pfn);	\
 	__section_mem_map_addr(__sec) + __pfn;		\
 })
 #endif /* CONFIG_FLATMEM/DISCONTIGMEM/SPARSEMEM */
+
+#ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
+struct page;
+/* this is useful when inlined pfn_to_page is too big */
+extern struct page *pfn_to_page(unsigned long pfn);
+extern unsigned long page_to_pfn(struct page *page);
+#else
+#define page_to_pfn __page_to_pfn
+#define pfn_to_page __pfn_to_page
 #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
 
 #endif /* __ASSEMBLY__ */
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index c0caf43..c745211 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -14,6 +14,7 @@
 /* var is in discarded region: offset to particular copy we want */
 #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
 #define __get_cpu_var(var) per_cpu(var, smp_processor_id())
+#define __raw_get_cpu_var(var) per_cpu(var, raw_smp_processor_id())
 
 /* A macro to avoid #include hell... */
 #define percpu_modcopy(pcpudst, src, size)			\
@@ -30,6 +31,7 @@
 
 #define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
 #define __get_cpu_var(var)			per_cpu__##var
+#define __raw_get_cpu_var(var)			per_cpu__##var
 
 #endif	/* SMP */
 
diff --git a/include/asm-generic/rtc.h b/include/asm-generic/rtc.h
index cef08db..4087037 100644
--- a/include/asm-generic/rtc.h
+++ b/include/asm-generic/rtc.h
@@ -114,6 +114,7 @@
 /* Set the current date and time in the real time clock. */
 static inline int set_rtc_time(struct rtc_time *time)
 {
+	unsigned long flags;
 	unsigned char mon, day, hrs, min, sec;
 	unsigned char save_control, save_freq_select;
 	unsigned int yrs;
@@ -131,7 +132,7 @@
 	if (yrs > 255)	/* They are unsigned */
 		return -EINVAL;
 
-	spin_lock_irq(&rtc_lock);
+	spin_lock_irqsave(&rtc_lock, flags);
 #ifdef CONFIG_MACH_DECSTATION
 	real_yrs = yrs;
 	leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
@@ -152,7 +153,7 @@
 	 * whether the chip is in binary mode or not.
 	 */
 	if (yrs > 169) {
-		spin_unlock_irq(&rtc_lock);
+		spin_unlock_irqrestore(&rtc_lock, flags);
 		return -EINVAL;
 	}
 
@@ -187,7 +188,7 @@
 	CMOS_WRITE(save_control, RTC_CONTROL);
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
 
-	spin_unlock_irq(&rtc_lock);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 
 	return 0;
 }
diff --git a/include/asm-generic/signal.h b/include/asm-generic/signal.h
index 9418d6e..dae1d87 100644
--- a/include/asm-generic/signal.h
+++ b/include/asm-generic/signal.h
@@ -1,3 +1,8 @@
+#ifndef __ASM_GENERIC_SIGNAL_H
+#define __ASM_GENERIC_SIGNAL_H
+
+#include <linux/compiler.h>
+
 #ifndef SIG_BLOCK
 #define SIG_BLOCK          0	/* for blocking signals */
 #endif
@@ -19,3 +24,5 @@
 #define SIG_IGN	((__force __sighandler_t)1)	/* ignore signal */
 #define SIG_ERR	((__force __sighandler_t)-1)	/* error return from signal */
 #endif
+
+#endif /* __ASM_GENERIC_SIGNAL_H */
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index cdd4145..867d900 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -13,7 +13,6 @@
 #ifndef _ASM_GENERIC__TLB_H
 #define _ASM_GENERIC__TLB_H
 
-#include <linux/config.h>
 #include <linux/swap.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 9d11550..db5a373 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -58,6 +58,20 @@
 		VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .;		\
 	}								\
 									\
+	/* Kernel symbol table: Normal unused symbols */		\
+	__ksymtab_unused  : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__start___ksymtab_unused) = .;		\
+		*(__ksymtab_unused)					\
+		VMLINUX_SYMBOL(__stop___ksymtab_unused) = .;		\
+	}								\
+									\
+	/* Kernel symbol table: GPL-only unused symbols */		\
+	__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
+		VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .;	\
+		*(__ksymtab_unused_gpl)					\
+		VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .;	\
+	}								\
+									\
 	/* Kernel symbol table: GPL-future-only symbols */		\
 	__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
 		VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .;	\
@@ -79,6 +93,20 @@
 		VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .;		\
 	}								\
 									\
+	/* Kernel symbol table: Normal unused symbols */		\
+	__kcrctab_unused  : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__start___kcrctab_unused) = .;		\
+		*(__kcrctab_unused)					\
+		VMLINUX_SYMBOL(__stop___kcrctab_unused) = .;		\
+	}								\
+									\
+	/* Kernel symbol table: GPL-only unused symbols */		\
+	__kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
+		VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .;	\
+		*(__kcrctab_unused_gpl)					\
+		VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .;	\
+	}								\
+									\
 	/* Kernel symbol table: GPL-future-only symbols */		\
 	__kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
 		VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .;	\
diff --git a/include/asm-h8300/bitops.h b/include/asm-h8300/bitops.h
index 574f57b6..d76299c 100644
--- a/include/asm-h8300/bitops.h
+++ b/include/asm-h8300/bitops.h
@@ -6,7 +6,6 @@
  * Copyright 2002, Yoshinori Sato
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/system.h>
 
diff --git a/include/asm-h8300/dma.h b/include/asm-h8300/dma.h
index 3708681..3edbaaa 100644
--- a/include/asm-h8300/dma.h
+++ b/include/asm-h8300/dma.h
@@ -1,7 +1,6 @@
 #ifndef _H8300_DMA_H
 #define _H8300_DMA_H 
  
-#include <linux/config.h>
 
 /*
  * Set number of channels of DMA on ColdFire for different implementations.
diff --git a/include/asm-h8300/elf.h b/include/asm-h8300/elf.h
index f4af155..7ba6a0a 100644
--- a/include/asm-h8300/elf.h
+++ b/include/asm-h8300/elf.h
@@ -5,7 +5,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff --git a/include/asm-h8300/hardirq.h b/include/asm-h8300/hardirq.h
index e961bfe..18fa793 100644
--- a/include/asm-h8300/hardirq.h
+++ b/include/asm-h8300/hardirq.h
@@ -2,7 +2,6 @@
 #define __H8300_HARDIRQ_H
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff --git a/include/asm-h8300/io.h b/include/asm-h8300/io.h
index 1773e37..91b7487 100644
--- a/include/asm-h8300/io.h
+++ b/include/asm-h8300/io.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/virtconvert.h>
 
 #if defined(CONFIG_H83007) || defined(CONFIG_H83068)
diff --git a/include/asm-h8300/irq.h b/include/asm-h8300/irq.h
index 73065f5..42a3ac4 100644
--- a/include/asm-h8300/irq.h
+++ b/include/asm-h8300/irq.h
@@ -63,8 +63,4 @@
 extern void disable_irq(unsigned int);
 #define disable_irq_nosync(x)	disable_irq(x)
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif /* _H8300_IRQ_H_ */
diff --git a/include/asm-h8300/keyboard.h b/include/asm-h8300/keyboard.h
index b05d113..fbad65e 100644
--- a/include/asm-h8300/keyboard.h
+++ b/include/asm-h8300/keyboard.h
@@ -7,7 +7,6 @@
 #ifndef _H8300_KEYBOARD_H
 #define _H8300_KEYBOARD_H
 
-#include <linux/config.h>
 
 /* dummy i.e. no real keyboard */
 #define kbd_setkeycode(x...)	(-ENOSYS)
diff --git a/include/asm-h8300/mmu_context.h b/include/asm-h8300/mmu_context.h
index 23b555b..855721a 100644
--- a/include/asm-h8300/mmu_context.h
+++ b/include/asm-h8300/mmu_context.h
@@ -1,7 +1,6 @@
 #ifndef __H8300_MMU_CONTEXT_H
 #define __H8300_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
diff --git a/include/asm-h8300/page.h b/include/asm-h8300/page.h
index 6472c9f..f9f9d3e 100644
--- a/include/asm-h8300/page.h
+++ b/include/asm-h8300/page.h
@@ -1,7 +1,6 @@
 #ifndef _H8300_PAGE_H
 #define _H8300_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 
diff --git a/include/asm-h8300/page_offset.h b/include/asm-h8300/page_offset.h
index 8cc6e17..f870646 100644
--- a/include/asm-h8300/page_offset.h
+++ b/include/asm-h8300/page_offset.h
@@ -1,4 +1,3 @@
 
-#include <linux/config.h>
 #define PAGE_OFFSET_RAW		0x00000000
 
diff --git a/include/asm-h8300/param.h b/include/asm-h8300/param.h
index 126dddf..c25806e 100644
--- a/include/asm-h8300/param.h
+++ b/include/asm-h8300/param.h
@@ -1,7 +1,6 @@
 #ifndef _H8300_PARAM_H
 #define _H8300_PARAM_H
 
-#include <linux/config.h>
 
 #ifndef HZ
 #define HZ 100
diff --git a/include/asm-h8300/pgtable.h b/include/asm-h8300/pgtable.h
index f6e296f..8b7c685 100644
--- a/include/asm-h8300/pgtable.h
+++ b/include/asm-h8300/pgtable.h
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/processor.h>
 #include <asm/page.h>
diff --git a/include/asm-h8300/processor.h b/include/asm-h8300/processor.h
index c6f0a710..c7e2f45 100644
--- a/include/asm-h8300/processor.h
+++ b/include/asm-h8300/processor.h
@@ -17,7 +17,6 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#include <linux/config.h>
 #include <asm/segment.h>
 #include <asm/fpu.h>
 #include <asm/ptrace.h>
diff --git a/include/asm-h8300/semaphore-helper.h b/include/asm-h8300/semaphore-helper.h
index 29e0fbf..4fea36b 100644
--- a/include/asm-h8300/semaphore-helper.h
+++ b/include/asm-h8300/semaphore-helper.h
@@ -10,7 +10,6 @@
  * m68k version by Andreas Schwab
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 
 /*
diff --git a/include/asm-h8300/shm.h b/include/asm-h8300/shm.h
index bec7585..ed6623c 100644
--- a/include/asm-h8300/shm.h
+++ b/include/asm-h8300/shm.h
@@ -1,7 +1,6 @@
 #ifndef _H8300_SHM_H
 #define _H8300_SHM_H
 
-#include <linux/config.h>
 
 /* format of page table entries that correspond to shared memory pages
    currently out in swap space (see also mm/swap.c):
diff --git a/include/asm-h8300/system.h b/include/asm-h8300/system.h
index 8e81cf6..134e092 100644
--- a/include/asm-h8300/system.h
+++ b/include/asm-h8300/system.h
@@ -1,7 +1,6 @@
 #ifndef _H8300_SYSTEM_H
 #define _H8300_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 
 /*
diff --git a/include/asm-h8300/unaligned.h b/include/asm-h8300/unaligned.h
index 8a93961..ffb67f4 100644
--- a/include/asm-h8300/unaligned.h
+++ b/include/asm-h8300/unaligned.h
@@ -1,7 +1,6 @@
 #ifndef __H8300_UNALIGNED_H
 #define __H8300_UNALIGNED_H
 
-#include <linux/config.h>
 
 /* Use memmove here, so gcc does not insert a __builtin_memcpy. */
 
diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h
index adb0515..226dd59 100644
--- a/include/asm-h8300/unistd.h
+++ b/include/asm-h8300/unistd.h
@@ -292,6 +292,8 @@
 #define __NR_request_key	287
 #define __NR_keyctl		288
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 289
 
 
@@ -460,7 +462,6 @@
   __syscall_return(type, __res);			\
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -483,7 +484,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -534,7 +534,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -543,4 +543,5 @@
   asm (".weak\t_" #name "\n"				\
        ".set\t_" #name ",_sys_ni_syscall");
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_H8300_UNISTD_H_ */
diff --git a/include/asm-h8300/virtconvert.h b/include/asm-h8300/virtconvert.h
index 3b344c1..ee7d5ea 100644
--- a/include/asm-h8300/virtconvert.h
+++ b/include/asm-h8300/virtconvert.h
@@ -7,7 +7,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h
index e201dec..c61bd1a 100644
--- a/include/asm-i386/alternative.h
+++ b/include/asm-i386/alternative.h
@@ -3,6 +3,10 @@
 
 #ifdef __KERNEL__
 
+#include <asm/types.h>
+
+#include <linux/types.h>
+
 struct alt_instr {
 	u8 *instr; 		/* original instruction */
 	u8 *replacement;
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index 288233f..2c1e371 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_APIC_H
 #define __ASM_APIC_H
 
-#include <linux/config.h>
 #include <linux/pm.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
@@ -112,24 +111,12 @@
 extern void smp_local_timer_interrupt (struct pt_regs * regs);
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
-extern void setup_apic_nmi_watchdog (void);
-extern int reserve_lapic_nmi(void);
-extern void release_lapic_nmi(void);
-extern void disable_timer_nmi_watchdog(void);
-extern void enable_timer_nmi_watchdog(void);
-extern void nmi_watchdog_tick (struct pt_regs * regs);
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
 
 extern void enable_NMI_through_LVT0 (void * dummy);
 
-extern unsigned int nmi_watchdog;
-#define NMI_NONE	0
-#define NMI_IO_APIC	1
-#define NMI_LOCAL_APIC	2
-#define NMI_INVALID	3
-
 extern int disable_timer_pin_1;
 
 void smp_send_timer_broadcast_ipi(struct pt_regs *regs);
@@ -139,8 +126,6 @@
 
 extern int timer_over_8254;
 
-extern int modern_apic(void);
-
 #else /* !CONFIG_X86_LOCAL_APIC */
 static inline void lapic_shutdown(void) { }
 
diff --git a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
index 5e4a35a..9f69953 100644
--- a/include/asm-i386/apicdef.h
+++ b/include/asm-i386/apicdef.h
@@ -121,7 +121,6 @@
  */
 #define u32 unsigned int
 
-#define lapic ((volatile struct local_apic *)APIC_BASE)
 
 struct local_apic {
 
diff --git a/include/asm-i386/atomic.h b/include/asm-i386/atomic.h
index 4ddce52..4f061fa 100644
--- a/include/asm-i386/atomic.h
+++ b/include/asm-i386/atomic.h
@@ -1,7 +1,6 @@
 #ifndef __ARCH_I386_ATOMIC__
 #define __ARCH_I386_ATOMIC__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/processor.h>
 
diff --git a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h
index 08deaee..1c780fa 100644
--- a/include/asm-i386/bitops.h
+++ b/include/asm-i386/bitops.h
@@ -5,7 +5,6 @@
  * Copyright 1992, Linus Torvalds.
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/alternative.h>
 
diff --git a/include/asm-i386/bug.h b/include/asm-i386/bug.h
index 8f79de1..8062cdb 100644
--- a/include/asm-i386/bug.h
+++ b/include/asm-i386/bug.h
@@ -1,7 +1,6 @@
 #ifndef _I386_BUG_H
 #define _I386_BUG_H
 
-#include <linux/config.h>
 
 /*
  * Tell the user there is some problem.
diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h
index 50233e0..2a9e4ee 100644
--- a/include/asm-i386/bugs.h
+++ b/include/asm-i386/bugs.h
@@ -17,7 +17,6 @@
  *	void check_bugs(void);
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
diff --git a/include/asm-i386/byteorder.h b/include/asm-i386/byteorder.h
index a0d73f4..a45470a 100644
--- a/include/asm-i386/byteorder.h
+++ b/include/asm-i386/byteorder.h
@@ -8,7 +8,6 @@
 
 /* For avoiding bswap on i386 */
 #ifdef __KERNEL__
-#include <linux/config.h>
 #endif
 
 static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
diff --git a/include/asm-i386/cache.h b/include/asm-i386/cache.h
index ca15c9c..57c62f4 100644
--- a/include/asm-i386/cache.h
+++ b/include/asm-i386/cache.h
@@ -4,7 +4,6 @@
 #ifndef __ARCH_I386_CACHE_H
 #define __ARCH_I386_CACHE_H
 
-#include <linux/config.h>
 
 /* L1 cache line size */
 #define L1_CACHE_SHIFT	(CONFIG_X86_L1_CACHE_SHIFT)
diff --git a/include/asm-i386/cpu.h b/include/asm-i386/cpu.h
index e7252c2..b1bc7b1 100644
--- a/include/asm-i386/cpu.h
+++ b/include/asm-i386/cpu.h
@@ -7,8 +7,6 @@
 #include <linux/nodemask.h>
 #include <linux/percpu.h>
 
-#include <asm/node.h>
-
 struct i386_cpu {
 	struct cpu cpu;
 };
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index b44bfc6..d314ebb 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -72,6 +72,7 @@
 #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
 #define X86_FEATURE_UP		(3*32+ 9) /* smp kernel running on up */
 #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
+#define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
@@ -88,6 +89,12 @@
 #define X86_FEATURE_XSTORE_EN	(5*32+ 3) /* on-CPU RNG enabled */
 #define X86_FEATURE_XCRYPT	(5*32+ 6) /* on-CPU crypto (xcrypt insn) */
 #define X86_FEATURE_XCRYPT_EN	(5*32+ 7) /* on-CPU crypto enabled */
+#define X86_FEATURE_ACE2	(5*32+ 8) /* Advanced Cryptography Engine v2 */
+#define X86_FEATURE_ACE2_EN	(5*32+ 9) /* ACE v2 enabled */
+#define X86_FEATURE_PHE		(5*32+ 10) /* PadLock Hash Engine */
+#define X86_FEATURE_PHE_EN	(5*32+ 11) /* PHE enabled */
+#define X86_FEATURE_PMM		(5*32+ 12) /* PadLock Montgomery Multiplier */
+#define X86_FEATURE_PMM_EN	(5*32+ 13) /* PMM enabled */
 
 /* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
 #define X86_FEATURE_LAHF_LM	(6*32+ 0) /* LAHF/SAHF in long mode */
@@ -121,6 +128,12 @@
 #define cpu_has_xstore_enabled	boot_cpu_has(X86_FEATURE_XSTORE_EN)
 #define cpu_has_xcrypt		boot_cpu_has(X86_FEATURE_XCRYPT)
 #define cpu_has_xcrypt_enabled	boot_cpu_has(X86_FEATURE_XCRYPT_EN)
+#define cpu_has_ace2		boot_cpu_has(X86_FEATURE_ACE2)
+#define cpu_has_ace2_enabled	boot_cpu_has(X86_FEATURE_ACE2_EN)
+#define cpu_has_phe		boot_cpu_has(X86_FEATURE_PHE)
+#define cpu_has_phe_enabled	boot_cpu_has(X86_FEATURE_PHE_EN)
+#define cpu_has_pmm		boot_cpu_has(X86_FEATURE_PMM)
+#define cpu_has_pmm_enabled	boot_cpu_has(X86_FEATURE_PMM_EN)
 
 #endif /* __ASM_I386_CPUFEATURE_H */
 
diff --git a/include/asm-i386/delay.h b/include/asm-i386/delay.h
index 456db85..b1c7650 100644
--- a/include/asm-i386/delay.h
+++ b/include/asm-i386/delay.h
@@ -23,4 +23,6 @@
 	((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
 	__ndelay(n))
 
+void use_tsc_delay(void);
+
 #endif /* defined(_I386_DELAY_H) */
diff --git a/include/asm-i386/dma.h b/include/asm-i386/dma.h
index f24b2bb..d23aac8 100644
--- a/include/asm-i386/dma.h
+++ b/include/asm-i386/dma.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>	/* And spinlocks */
 #include <asm/io.h>		/* need byte IO */
 #include <linux/delay.h>
diff --git a/include/asm-i386/dwarf2.h b/include/asm-i386/dwarf2.h
new file mode 100644
index 0000000..2280f62
--- /dev/null
+++ b/include/asm-i386/dwarf2.h
@@ -0,0 +1,54 @@
+#ifndef _DWARF2_H
+#define _DWARF2_H
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+#warning "asm/dwarf2.h should be only included in pure assembly files"
+#endif
+
+/*
+   Macros for dwarf2 CFI unwind table entries.
+   See "as.info" for details on these pseudo ops. Unfortunately
+   they are only supported in very new binutils, so define them
+   away for older version.
+ */
+
+#ifdef CONFIG_UNWIND_INFO
+
+#define CFI_STARTPROC .cfi_startproc
+#define CFI_ENDPROC .cfi_endproc
+#define CFI_DEF_CFA .cfi_def_cfa
+#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register
+#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset
+#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
+#define CFI_OFFSET .cfi_offset
+#define CFI_REL_OFFSET .cfi_rel_offset
+#define CFI_REGISTER .cfi_register
+#define CFI_RESTORE .cfi_restore
+#define CFI_REMEMBER_STATE .cfi_remember_state
+#define CFI_RESTORE_STATE .cfi_restore_state
+
+#else
+
+/* Due to the structure of pre-exisiting code, don't use assembler line
+   comment character # to ignore the arguments. Instead, use a dummy macro. */
+.macro ignore a=0, b=0, c=0, d=0
+.endm
+
+#define CFI_STARTPROC	ignore
+#define CFI_ENDPROC	ignore
+#define CFI_DEF_CFA	ignore
+#define CFI_DEF_CFA_REGISTER	ignore
+#define CFI_DEF_CFA_OFFSET	ignore
+#define CFI_ADJUST_CFA_OFFSET	ignore
+#define CFI_OFFSET	ignore
+#define CFI_REL_OFFSET	ignore
+#define CFI_REGISTER	ignore
+#define CFI_RESTORE	ignore
+#define CFI_REMEMBER_STATE ignore
+#define CFI_RESTORE_STATE ignore
+
+#endif
+
+#endif
diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h
index 4153d80..1eac92c 100644
--- a/include/asm-i386/elf.h
+++ b/include/asm-i386/elf.h
@@ -10,6 +10,7 @@
 #include <asm/processor.h>
 #include <asm/system.h>		/* for savesegment */
 #include <asm/auxvec.h>
+#include <asm/desc.h>
 
 #include <linux/utsname.h>
 
@@ -129,15 +130,41 @@
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
 #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs)
 
-#define VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
-#define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
-#define VSYSCALL_ENTRY	((unsigned long) &__kernel_vsyscall)
+#define VDSO_HIGH_BASE		(__fix_to_virt(FIX_VDSO))
+#define VDSO_BASE		((unsigned long)current->mm->context.vdso)
+
+#ifdef CONFIG_COMPAT_VDSO
+# define VDSO_COMPAT_BASE	VDSO_HIGH_BASE
+# define VDSO_PRELINK		VDSO_HIGH_BASE
+#else
+# define VDSO_COMPAT_BASE	VDSO_BASE
+# define VDSO_PRELINK		0
+#endif
+
+#define VDSO_COMPAT_SYM(x) \
+		(VDSO_COMPAT_BASE + (unsigned long)(x) - VDSO_PRELINK)
+
+#define VDSO_SYM(x) \
+		(VDSO_BASE + (unsigned long)(x) - VDSO_PRELINK)
+
+#define VDSO_HIGH_EHDR		((const struct elfhdr *) VDSO_HIGH_BASE)
+#define VDSO_EHDR		((const struct elfhdr *) VDSO_COMPAT_BASE)
+
 extern void __kernel_vsyscall;
 
+#define VDSO_ENTRY		VDSO_SYM(&__kernel_vsyscall)
+
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+                                       int executable_stack);
+
+extern unsigned int vdso_enabled;
+
 #define ARCH_DLINFO						\
-do {								\
-		NEW_AUX_ENT(AT_SYSINFO,	VSYSCALL_ENTRY);	\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);	\
+do if (vdso_enabled) {						\
+		NEW_AUX_ENT(AT_SYSINFO,	VDSO_ENTRY);		\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_COMPAT_BASE);	\
 } while (0)
 
 /*
@@ -148,15 +175,15 @@
  * Dumping its extra ELF program headers includes all the other information
  * a debugger needs to easily find how the vsyscall DSO was being used.
  */
-#define ELF_CORE_EXTRA_PHDRS		(VSYSCALL_EHDR->e_phnum)
+#define ELF_CORE_EXTRA_PHDRS		(VDSO_HIGH_EHDR->e_phnum)
 #define ELF_CORE_WRITE_EXTRA_PHDRS					      \
 do {									      \
 	const struct elf_phdr *const vsyscall_phdrs =			      \
-		(const struct elf_phdr *) (VSYSCALL_BASE		      \
-					   + VSYSCALL_EHDR->e_phoff);	      \
+		(const struct elf_phdr *) (VDSO_HIGH_BASE		      \
+					   + VDSO_HIGH_EHDR->e_phoff);    \
 	int i;								      \
 	Elf32_Off ofs = 0;						      \
-	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+	for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) {		      \
 		struct elf_phdr phdr = vsyscall_phdrs[i];		      \
 		if (phdr.p_type == PT_LOAD) {				      \
 			BUG_ON(ofs != 0);				      \
@@ -174,10 +201,10 @@
 #define ELF_CORE_WRITE_EXTRA_DATA					      \
 do {									      \
 	const struct elf_phdr *const vsyscall_phdrs =			      \
-		(const struct elf_phdr *) (VSYSCALL_BASE		      \
-					   + VSYSCALL_EHDR->e_phoff);	      \
+		(const struct elf_phdr *) (VDSO_HIGH_BASE		      \
+					   + VDSO_HIGH_EHDR->e_phoff);    \
 	int i;								      \
-	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+	for (i = 0; i < VDSO_HIGH_EHDR->e_phnum; ++i) {		      \
 		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
 			DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,	      \
 				   PAGE_ALIGN(vsyscall_phdrs[i].p_memsz));    \
diff --git a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h
index cfb1c61..a48cc3f 100644
--- a/include/asm-i386/fixmap.h
+++ b/include/asm-i386/fixmap.h
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 
 /* used by vmalloc.c, vsyscall.lds.S.
  *
@@ -52,7 +51,7 @@
  */
 enum fixed_addresses {
 	FIX_HOLE,
-	FIX_VSYSCALL,
+	FIX_VDSO,
 #ifdef CONFIG_X86_LOCAL_APIC
 	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
 #endif
@@ -116,14 +115,6 @@
 #define __fix_to_virt(x)	(FIXADDR_TOP - ((x) << PAGE_SHIFT))
 #define __virt_to_fix(x)	((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
 
-/*
- * This is the range that is readable by user mode, and things
- * acting like user mode such as get_user_pages.
- */
-#define FIXADDR_USER_START	(__fix_to_virt(FIX_VSYSCALL))
-#define FIXADDR_USER_END	(FIXADDR_USER_START + PAGE_SIZE)
-
-
 extern void __this_fixmap_does_not_exist(void);
 
 /*
diff --git a/include/asm-i386/floppy.h b/include/asm-i386/floppy.h
index 03403045..9cb2793 100644
--- a/include/asm-i386/floppy.h
+++ b/include/asm-i386/floppy.h
@@ -147,9 +147,8 @@
 		return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
 						   "floppy", NULL);
 	else
-		return request_irq(FLOPPY_IRQ, floppy_interrupt,
-						   SA_INTERRUPT|SA_SAMPLE_RANDOM,
-						   "floppy", NULL);	
+		return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT,
+				   "floppy", NULL);
 
 }
 
diff --git a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
index ee754d3..0e358dc 100644
--- a/include/asm-i386/hardirq.h
+++ b/include/asm-i386/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
index 0fd3313..e9a34eb 100644
--- a/include/asm-i386/highmem.h
+++ b/include/asm-i386/highmem.h
@@ -20,7 +20,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/interrupt.h>
 #include <linux/threads.h>
 #include <asm/kmap_types.h>
diff --git a/include/asm-i386/hpet.h b/include/asm-i386/hpet.h
index 7f1a8a6..af5d435 100644
--- a/include/asm-i386/hpet.h
+++ b/include/asm-i386/hpet.h
@@ -27,7 +27,6 @@
 #include <asm/processor.h>
 
 #include <linux/timex.h>
-#include <linux/config.h>
 
 #include <asm/fixmap.h>
 
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 622815b..a4c0a5a 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -12,7 +12,6 @@
  *	<tomsoft@informatik.tu-chemnitz.de>
  */
 
-#include <linux/config.h>
 #include <linux/profile.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
@@ -20,6 +19,8 @@
 
 struct hw_interrupt_type;
 
+#define NMI_VECTOR		0x02
+
 /*
  * Various low-level irq details needed by irq.c, process.c,
  * time.c, io_apic.c and smp.c
diff --git a/include/asm-i386/ide.h b/include/asm-i386/ide.h
index 4544401..73465d2 100644
--- a/include/asm-i386/ide.h
+++ b/include/asm-i386/ide.h
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
diff --git a/include/asm-i386/intel_arch_perfmon.h b/include/asm-i386/intel_arch_perfmon.h
new file mode 100644
index 0000000..134ea9c
--- /dev/null
+++ b/include/asm-i386/intel_arch_perfmon.h
@@ -0,0 +1,19 @@
+#ifndef X86_INTEL_ARCH_PERFMON_H
+#define X86_INTEL_ARCH_PERFMON_H 1
+
+#define MSR_ARCH_PERFMON_PERFCTR0		0xc1
+#define MSR_ARCH_PERFMON_PERFCTR1		0xc2
+
+#define MSR_ARCH_PERFMON_EVENTSEL0		0x186
+#define MSR_ARCH_PERFMON_EVENTSEL1		0x187
+
+#define ARCH_PERFMON_EVENTSEL0_ENABLE      (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_INT          (1 << 20)
+#define ARCH_PERFMON_EVENTSEL_OS           (1 << 17)
+#define ARCH_PERFMON_EVENTSEL_USR          (1 << 16)
+
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL	(0x3c)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK	(0x00 << 8)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0)
+
+#endif	/* X86_INTEL_ARCH_PERFMON_H */
diff --git a/include/asm-i386/io.h b/include/asm-i386/io.h
index 79670bb..b3724fe 100644
--- a/include/asm-i386/io.h
+++ b/include/asm-i386/io.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/compiler.h>
 
diff --git a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h
index d92e253..5092e81 100644
--- a/include/asm-i386/io_apic.h
+++ b/include/asm-i386/io_apic.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_IO_APIC_H
 #define __ASM_IO_APIC_H
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/mpspec.h>
 
diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h
index 5169d7a..331726b 100644
--- a/include/asm-i386/irq.h
+++ b/include/asm-i386/irq.h
@@ -10,7 +10,6 @@
  *	<tomsoft@informatik.tu-chemnitz.de>
  */
 
-#include <linux/config.h>
 #include <linux/sched.h>
 /* include comes from machine specific directory */
 #include "irq_vectors.h"
diff --git a/include/asm-i386/k8.h b/include/asm-i386/k8.h
new file mode 100644
index 0000000..dfd88a6
--- /dev/null
+++ b/include/asm-i386/k8.h
@@ -0,0 +1 @@
+#include <asm-x86_64/k8.h>
diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
index 96d0828..d18cdb9 100644
--- a/include/asm-i386/kdebug.h
+++ b/include/asm-i386/kdebug.h
@@ -19,6 +19,8 @@
 
 extern int register_die_notifier(struct notifier_block *);
 extern int unregister_die_notifier(struct notifier_block *);
+extern int register_page_fault_notifier(struct notifier_block *);
+extern int unregister_page_fault_notifier(struct notifier_block *);
 extern struct atomic_notifier_head i386die_chain;
 
 
diff --git a/include/asm-i386/kmap_types.h b/include/asm-i386/kmap_types.h
index 6886a0c..806aae3 100644
--- a/include/asm-i386/kmap_types.h
+++ b/include/asm-i386/kmap_types.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 57d157c..0730a20 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -44,6 +44,7 @@
 
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 #define ARCH_SUPPORTS_KRETPROBES
+#define  ARCH_INACTIVE_KPROBE_COUNT 0
 
 void arch_remove_kprobe(struct kprobe *p);
 void kretprobe_trampoline(void);
diff --git a/include/asm-i386/local.h b/include/asm-i386/local.h
index e67fa08..3b4998c 100644
--- a/include/asm-i386/local.h
+++ b/include/asm-i386/local.h
@@ -55,12 +55,26 @@
  * much more efficient than these naive implementations.  Note they take
  * a variable, not an address.
  */
-#define cpu_local_read(v)	local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)	local_set(&__get_cpu_var(v), (i))
-#define cpu_local_inc(v)	local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)	local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)	local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)	local_sub((i), &__get_cpu_var(v))
+
+/* Need to disable preemption for the cpu local counters otherwise we could
+   still access a variable of a previous CPU in a non atomic way. */
+#define cpu_local_wrap_v(v)	 	\
+	({ local_t res__;		\
+	   preempt_disable(); 		\
+	   res__ = (v);			\
+	   preempt_enable();		\
+	   res__; })
+#define cpu_local_wrap(v)		\
+	({ preempt_disable();		\
+	   v;				\
+	   preempt_enable(); })		\
+
+#define cpu_local_read(v)    cpu_local_wrap_v(local_read(&__get_cpu_var(v)))
+#define cpu_local_set(v, i)  cpu_local_wrap(local_set(&__get_cpu_var(v), (i)))
+#define cpu_local_inc(v)     cpu_local_wrap(local_inc(&__get_cpu_var(v)))
+#define cpu_local_dec(v)     cpu_local_wrap(local_dec(&__get_cpu_var(v)))
+#define cpu_local_add(i, v)  cpu_local_wrap(local_add((i), &__get_cpu_var(v)))
+#define cpu_local_sub(i, v)  cpu_local_wrap(local_sub((i), &__get_cpu_var(v)))
 
 #define __cpu_local_inc(v)	cpu_local_inc(v)
 #define __cpu_local_dec(v)	cpu_local_dec(v)
diff --git a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h
index a1d0072..0dba244 100644
--- a/include/asm-i386/mach-default/mach_ipi.h
+++ b/include/asm-i386/mach-default/mach_ipi.h
@@ -1,6 +1,9 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
+/* Avoid include hell */
+#define NMI_VECTOR 0x02
+
 void send_IPI_mask_bitmask(cpumask_t mask, int vector);
 void __send_IPI_shortcut(unsigned int shortcut, int vector);
 
@@ -13,7 +16,7 @@
 
 static inline void __local_send_IPI_allbutself(int vector)
 {
-	if (no_broadcast) {
+	if (no_broadcast || vector == NMI_VECTOR) {
 		cpumask_t mask = cpu_online_map;
 
 		cpu_clear(smp_processor_id(), mask);
@@ -24,7 +27,7 @@
 
 static inline void __local_send_IPI_all(int vector)
 {
-	if (no_broadcast)
+	if (no_broadcast || vector == NMI_VECTOR)
 		send_IPI_mask(cpu_online_map, vector);
 	else
 		__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
diff --git a/include/asm-i386/mach-default/mach_timer.h b/include/asm-i386/mach-default/mach_timer.h
index 4b9703b..807992f 100644
--- a/include/asm-i386/mach-default/mach_timer.h
+++ b/include/asm-i386/mach-default/mach_timer.h
@@ -15,7 +15,9 @@
 #ifndef _MACH_TIMER_H
 #define _MACH_TIMER_H
 
-#define CALIBRATE_LATCH	(5 * LATCH)
+#define CALIBRATE_TIME_MSEC 30 /* 30 msecs */
+#define CALIBRATE_LATCH	\
+	((CLOCK_TICK_RATE * CALIBRATE_TIME_MSEC + 1000/2)/1000)
 
 static inline void mach_prepare_counter(void)
 {
diff --git a/include/asm-i386/mach-default/setup_arch_pre.h b/include/asm-i386/mach-default/setup_arch.h
similarity index 100%
rename from include/asm-i386/mach-default/setup_arch_pre.h
rename to include/asm-i386/mach-default/setup_arch.h
diff --git a/include/asm-i386/mach-default/setup_arch_post.h b/include/asm-i386/mach-default/setup_arch_post.h
deleted file mode 100644
index 2fc4888..0000000
--- a/include/asm-i386/mach-default/setup_arch_post.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * machine_specific_memory_setup - Hook for machine specific memory setup.
- *
- * Description:
- *	This is included late in kernel/setup.c so that it can make
- *	use of all of the static functions.
- **/
-
-static char * __init machine_specific_memory_setup(void)
-{
-	char *who;
-
-
-	who = "BIOS-e820";
-
-	/*
-	 * Try to copy the BIOS-supplied E820-map.
-	 *
-	 * Otherwise fake a memory map; one section from 0k->640k,
-	 * the next section from 1mb->appropriate_mem_k
-	 */
-	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
-	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
-		unsigned long mem_size;
-
-		/* compare results from other methods and take the greater */
-		if (ALT_MEM_K < EXT_MEM_K) {
-			mem_size = EXT_MEM_K;
-			who = "BIOS-88";
-		} else {
-			mem_size = ALT_MEM_K;
-			who = "BIOS-e801";
-		}
-
-		e820.nr_map = 0;
-		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
-  	}
-	return who;
-}
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 3d6d129..9fd0732 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_APIC_H
 #define __ASM_MACH_APIC_H
 
-#include <linux/config.h>
 #include <asm/smp.h>
 
 #define esr_disable (1)
diff --git a/include/asm-i386/mach-summit/mach_mpparse.h b/include/asm-i386/mach-summit/mach_mpparse.h
index 1cce2b9..9426839 100644
--- a/include/asm-i386/mach-summit/mach_mpparse.h
+++ b/include/asm-i386/mach-summit/mach_mpparse.h
@@ -2,6 +2,7 @@
 #define __ASM_MACH_MPPARSE_H
 
 #include <mach_apic.h>
+#include <asm/tsc.h>
 
 extern int use_cyclone;
 
@@ -29,6 +30,7 @@
 			(!strncmp(productid, "VIGIL SMP", 9) 
 			 || !strncmp(productid, "EXA", 3)
 			 || !strncmp(productid, "RUTHLESS SMP", 12))){
+		mark_tsc_unstable();
 		use_cyclone = 1; /*enable cyclone-timer*/
 		setup_summit();
 		return 1;
@@ -42,6 +44,7 @@
 	if (!strncmp(oem_id, "IBM", 3) &&
 	    (!strncmp(oem_table_id, "SERVIGIL", 8)
 	     || !strncmp(oem_table_id, "EXA", 3))){
+		mark_tsc_unstable();
 		use_cyclone = 1; /*enable cyclone-timer*/
 		setup_summit();
 		return 1;
diff --git a/include/asm-i386/mach-visws/setup_arch_pre.h b/include/asm-i386/mach-visws/setup_arch.h
similarity index 100%
rename from include/asm-i386/mach-visws/setup_arch_pre.h
rename to include/asm-i386/mach-visws/setup_arch.h
diff --git a/include/asm-i386/mach-visws/setup_arch_post.h b/include/asm-i386/mach-visws/setup_arch_post.h
deleted file mode 100644
index cdbd895..0000000
--- a/include/asm-i386/mach-visws/setup_arch_post.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Hook for machine specific memory setup.
- *
- * This is included late in kernel/setup.c so that it can make use of all of
- * the static functions. */
-
-#define MB (1024 * 1024)
-
-unsigned long sgivwfb_mem_phys;
-unsigned long sgivwfb_mem_size;
-
-long long mem_size __initdata = 0;
-
-static char * __init machine_specific_memory_setup(void)
-{
-	long long gfx_mem_size = 8 * MB;
-
-	mem_size = ALT_MEM_K;
-
-	if (!mem_size) {
-		printk(KERN_WARNING "Bootloader didn't set memory size, upgrade it !\n");
-		mem_size = 128 * MB;
-	}
-
-	/*
-	 * this hardcodes the graphics memory to 8 MB
-	 * it really should be sized dynamically (or at least
-	 * set as a boot param)
-	 */
-	if (!sgivwfb_mem_size) {
-		printk(KERN_WARNING "Defaulting to 8 MB framebuffer size\n");
-		sgivwfb_mem_size = 8 * MB;
-	}
-
-	/*
-	 * Trim to nearest MB
-	 */
-	sgivwfb_mem_size &= ~((1 << 20) - 1);
-	sgivwfb_mem_phys = mem_size - gfx_mem_size;
-
-	add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-	add_memory_region(HIGH_MEMORY, mem_size - sgivwfb_mem_size - HIGH_MEMORY, E820_RAM);
-	add_memory_region(sgivwfb_mem_phys, sgivwfb_mem_size, E820_RESERVED);
-
-	return "PROM";
-
-	/* Remove gcc warnings */
-	(void) sanitize_e820_map(NULL, NULL);
-	(void) copy_e820_map(NULL, 0);
-}
diff --git a/include/asm-i386/mach-voyager/setup_arch.h b/include/asm-i386/mach-voyager/setup_arch.h
new file mode 100644
index 0000000..84d01ad
--- /dev/null
+++ b/include/asm-i386/mach-voyager/setup_arch.h
@@ -0,0 +1,10 @@
+#include <asm/voyager.h>
+#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *)(PARAM+0x40))
+
+/* Hook to call BIOS initialisation function */
+
+/* for voyager, pass the voyager BIOS/SUS info area to the detection
+ * routines */
+
+#define ARCH_SETUP	voyager_detect(VOYAGER_BIOS_INFO);
+
diff --git a/include/asm-i386/mach-voyager/setup_arch_post.h b/include/asm-i386/mach-voyager/setup_arch_post.h
deleted file mode 100644
index f6f6c2c..0000000
--- a/include/asm-i386/mach-voyager/setup_arch_post.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Hook for machine specific memory setup.
- *
- * This is included late in kernel/setup.c so that it can make use of all of
- * the static functions. */
-
-static char * __init machine_specific_memory_setup(void)
-{
-	char *who;
-
-	who = "NOT VOYAGER";
-
-	if(voyager_level == 5) {
-		__u32 addr, length;
-		int i;
-
-		who = "Voyager-SUS";
-
-		e820.nr_map = 0;
-		for(i=0; voyager_memory_detect(i, &addr, &length); i++) {
-			add_memory_region(addr, length, E820_RAM);
-		}
-		return who;
-	} else if(voyager_level == 4) {
-		__u32 tom;
-		__u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT)<<8;
-		/* select the DINO config space */
-		outb(VOYAGER_DINO, VOYAGER_CAT_CONFIG_PORT);
-		/* Read DINO top of memory register */
-		tom = ((inb(catbase + 0x4) & 0xf0) << 16)
-			+ ((inb(catbase + 0x5) & 0x7f) << 24);
-
-		if(inb(catbase) != VOYAGER_DINO) {
-			printk(KERN_ERR "Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K\n");
-			tom = (EXT_MEM_K)<<10;
-		}
-		who = "Voyager-TOM";
-		add_memory_region(0, 0x9f000, E820_RAM);
-		/* map from 1M to top of memory */
-		add_memory_region(1*1024*1024, tom - 1*1024*1024, E820_RAM);
-		/* FIXME: Should check the ASICs to see if I need to
-		 * take out the 8M window.  Just do it at the moment
-		 * */
-		add_memory_region(8*1024*1024, 8*1024*1024, E820_RESERVED);
-		return who;
-	}
-
-	who = "BIOS-e820";
-
-	/*
-	 * Try to copy the BIOS-supplied E820-map.
-	 *
-	 * Otherwise fake a memory map; one section from 0k->640k,
-	 * the next section from 1mb->appropriate_mem_k
-	 */
-	sanitize_e820_map(E820_MAP, &E820_MAP_NR);
-	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
-		unsigned long mem_size;
-
-		/* compare results from other methods and take the greater */
-		if (ALT_MEM_K < EXT_MEM_K) {
-			mem_size = EXT_MEM_K;
-			who = "BIOS-88";
-		} else {
-			mem_size = ALT_MEM_K;
-			who = "BIOS-e801";
-		}
-
-		e820.nr_map = 0;
-		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
-  	}
-	return who;
-}
diff --git a/include/asm-i386/mach-voyager/setup_arch_pre.h b/include/asm-i386/mach-voyager/setup_arch_pre.h
deleted file mode 100644
index 48f7e6f..0000000
--- a/include/asm-i386/mach-voyager/setup_arch_pre.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <asm/voyager.h>
-#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *)(PARAM+0x40))
-
-/* Hook to call BIOS initialisation function */
-
-/* for voyager, pass the voyager BIOS/SUS info area to the detection 
- * routines */
-
-#define ARCH_SETUP	voyager_detect(VOYAGER_BIOS_INFO);
-
diff --git a/include/asm-i386/mce.h b/include/asm-i386/mce.h
new file mode 100644
index 0000000..7cc1a973
--- /dev/null
+++ b/include/asm-i386/mce.h
@@ -0,0 +1,5 @@
+#ifdef CONFIG_X86_MCE
+extern void mcheck_init(struct cpuinfo_x86 *c);
+#else
+#define mcheck_init(c) do {} while(0)
+#endif
diff --git a/include/asm-i386/mmu.h b/include/asm-i386/mmu.h
index f431a0b..8358dd3 100644
--- a/include/asm-i386/mmu.h
+++ b/include/asm-i386/mmu.h
@@ -12,6 +12,7 @@
 	int size;
 	struct semaphore sem;
 	void *ldt;
+	void *vdso;
 } mm_context_t;
 
 #endif
diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
index bf08218..62b7bf1 100644
--- a/include/asm-i386/mmu_context.h
+++ b/include/asm-i386/mmu_context.h
@@ -1,7 +1,6 @@
 #ifndef __I386_SCHED_H
 #define __I386_SCHED_H
 
-#include <linux/config.h>
 #include <asm/desc.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h
index f041d44..b11c4b7 100644
--- a/include/asm-i386/msi.h
+++ b/include/asm-i386/msi.h
@@ -9,7 +9,15 @@
 #include <asm/desc.h>
 #include <mach_apic.h>
 
-#define LAST_DEVICE_VECTOR		232
+#define LAST_DEVICE_VECTOR	(FIRST_SYSTEM_VECTOR - 1)
 #define MSI_TARGET_CPU_SHIFT	12
 
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+	msi_register(&msi_apic_ops);
+	return 0;
+}
+
 #endif /* ASM_MSI_H */
diff --git a/include/asm-i386/mtrr.h b/include/asm-i386/mtrr.h
index 64cf937..07f063a 100644
--- a/include/asm-i386/mtrr.h
+++ b/include/asm-i386/mtrr.h
@@ -23,7 +23,6 @@
 #ifndef _LINUX_MTRR_H
 #define _LINUX_MTRR_H
 
-#include <linux/config.h>
 #include <linux/ioctl.h>
 #include <linux/errno.h>
 
@@ -77,6 +76,8 @@
 extern int mtrr_del (int reg, unsigned long base, unsigned long size);
 extern int mtrr_del_page (int reg, unsigned long base, unsigned long size);
 extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
+extern void mtrr_ap_init(void);
+extern void mtrr_bp_init(void);
 #  else
 static __inline__ int mtrr_add (unsigned long base, unsigned long size,
 				unsigned int type, char increment)
@@ -101,6 +102,8 @@
 
 static __inline__ void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) {;}
 
+#define mtrr_ap_init() do {} while (0)
+#define mtrr_bp_init() do {} while (0)
 #  endif
 
 #endif
diff --git a/include/asm-i386/nmi.h b/include/asm-i386/nmi.h
index 21f1663..67d9947 100644
--- a/include/asm-i386/nmi.h
+++ b/include/asm-i386/nmi.h
@@ -5,24 +5,38 @@
 #define ASM_NMI_H
 
 #include <linux/pm.h>
- 
+
 struct pt_regs;
- 
+
 typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu);
- 
-/** 
+
+/**
  * set_nmi_callback
  *
  * Set a handler for an NMI. Only one handler may be
  * set. Return 1 if the NMI was handled.
  */
 void set_nmi_callback(nmi_callback_t callback);
- 
-/** 
+
+/**
  * unset_nmi_callback
  *
  * Remove the handler previously set.
  */
 void unset_nmi_callback(void);
- 
+
+extern void setup_apic_nmi_watchdog (void);
+extern int reserve_lapic_nmi(void);
+extern void release_lapic_nmi(void);
+extern void disable_timer_nmi_watchdog(void);
+extern void enable_timer_nmi_watchdog(void);
+extern void nmi_watchdog_tick (struct pt_regs * regs);
+
+extern unsigned int nmi_watchdog;
+#define NMI_DEFAULT     -1
+#define NMI_NONE	0
+#define NMI_IO_APIC	1
+#define NMI_LOCAL_APIC	2
+#define NMI_INVALID	3
+
 #endif /* ASM_NMI_H */
diff --git a/include/asm-i386/node.h b/include/asm-i386/node.h
deleted file mode 100644
index e13c6ff..0000000
--- a/include/asm-i386/node.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _ASM_I386_NODE_H_
-#define _ASM_I386_NODE_H_
-
-#include <linux/device.h>
-#include <linux/mmzone.h>
-#include <linux/node.h>
-#include <linux/topology.h>
-#include <linux/nodemask.h>
-
-struct i386_node {
-	struct node node;
-};
-extern struct i386_node node_devices[MAX_NUMNODES];
-
-static inline int arch_register_node(int num){
-	int p_node;
-	struct node *parent = NULL;
-
-	if (!node_online(num))
-		return 0;
-	p_node = parent_node(num);
-
-	if (p_node != num)
-		parent = &node_devices[p_node].node;
-
-	return register_node(&node_devices[num].node, num, parent);
-}
-
-#endif /* _ASM_I386_NODE_H_ */
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index 30f52a2..f5bf544 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -12,7 +12,6 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_X86_USE_3DNOW
 
@@ -97,6 +96,8 @@
 
 #ifndef __ASSEMBLY__
 
+struct vm_area_struct;
+
 /*
  * This much address space is reserved for vmalloc() and iomap()
  * as well as fixmap mappings.
@@ -137,9 +138,10 @@
 	((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
 		 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#endif /* __KERNEL__ */
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#define __HAVE_ARCH_GATE_AREA 1
+#endif /* __KERNEL__ */
+
 #endif /* _I386_PAGE_H */
diff --git a/include/asm-i386/param.h b/include/asm-i386/param.h
index 095580f..745dc5b 100644
--- a/include/asm-i386/param.h
+++ b/include/asm-i386/param.h
@@ -2,7 +2,6 @@
 #define _ASMi386_PARAM_H
 
 #ifdef __KERNEL__
-# include <linux/config.h>
 # define HZ		CONFIG_HZ	/* Internal kernel timer frequency */
 # define USER_HZ	100		/* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC		(USER_HZ)	/* like times() */
diff --git a/include/asm-i386/pci.h b/include/asm-i386/pci.h
index 78c85985a..64b6d0b 100644
--- a/include/asm-i386/pci.h
+++ b/include/asm-i386/pci.h
@@ -1,7 +1,6 @@
 #ifndef __i386_PCI_H
 #define __i386_PCI_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 #include <linux/mm.h>		/* for struct page */
diff --git a/include/asm-i386/pgalloc.h b/include/asm-i386/pgalloc.h
index 0380c3d..4b1e613 100644
--- a/include/asm-i386/pgalloc.h
+++ b/include/asm-i386/pgalloc.h
@@ -1,7 +1,6 @@
 #ifndef _I386_PGALLOC_H
 #define _I386_PGALLOC_H
 
-#include <linux/config.h>
 #include <asm/fixmap.h>
 #include <linux/threads.h>
 #include <linux/mm.h>		/* for struct page */
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 672c3f7..09697fe 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -1,7 +1,6 @@
 #ifndef _I386_PGTABLE_H
 #define _I386_PGTABLE_H
 
-#include <linux/config.h>
 
 /*
  * The Linux memory management assumes a three-level page table setup. On
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 805f0dc..b32346d 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -17,7 +17,6 @@
 #include <asm/msr.h>
 #include <asm/system.h>
 #include <linux/cache.h>
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/percpu.h>
 #include <linux/cpumask.h>
@@ -72,8 +71,12 @@
 	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
 #endif
 	unsigned char x86_max_cores;	/* cpuid returned max cores value */
-	unsigned char booted_cores;	/* number of cores as seen by OS */
 	unsigned char apicid;
+#ifdef CONFIG_SMP
+	unsigned char booted_cores;	/* number of cores as seen by OS */
+	__u8 phys_proc_id; 		/* Physical processor id. */
+	__u8 cpu_core_id;  		/* Core id */
+#endif
 } __attribute__((__aligned__(SMP_CACHE_BYTES)));
 
 #define X86_VENDOR_INTEL 0
@@ -105,14 +108,13 @@
 #define current_cpu_data boot_cpu_data
 #endif
 
-extern	int phys_proc_id[NR_CPUS];
-extern	int cpu_core_id[NR_CPUS];
 extern	int cpu_llc_id[NR_CPUS];
 extern char ignore_fpu_irq;
 
 extern void identify_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+extern unsigned short num_cache_leaves;
 
 #ifdef CONFIG_X86_HT
 extern void detect_ht(struct cpuinfo_x86 *c);
@@ -555,7 +557,7 @@
 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
 
 extern unsigned long thread_saved_pc(struct task_struct *tsk);
-void show_trace(struct task_struct *task, unsigned long *stack);
+void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long *stack);
 
 unsigned long get_wchan(struct task_struct *p);
 
@@ -729,18 +731,4 @@
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
-#ifdef CONFIG_MTRR
-extern void mtrr_ap_init(void);
-extern void mtrr_bp_init(void);
-#else
-#define mtrr_ap_init() do {} while (0)
-#define mtrr_bp_init() do {} while (0)
-#endif
-
-#ifdef CONFIG_X86_MCE
-extern void mcheck_init(struct cpuinfo_x86 *c);
-#else
-#define mcheck_init(c) do {} while(0)
-#endif
-
 #endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-i386/serial.h b/include/asm-i386/serial.h
index e1ecfcc..bd67480 100644
--- a/include/asm-i386/serial.h
+++ b/include/asm-i386/serial.h
@@ -2,7 +2,6 @@
  * include/asm-i386/serial.h
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index ee94145..f737e42 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -59,6 +59,21 @@
 #define EDD_MBR_SIGNATURE ((unsigned int *) (PARAM+EDD_MBR_SIG_BUF))
 #define EDD_BUF     ((struct edd_info *) (PARAM+EDDBUF))
 
+/*
+ * Do NOT EVER look at the BIOS memory size location.
+ * It does not work on many machines.
+ */
+#define LOWMEMSIZE()	(0x9f000)
+
+struct e820entry;
+
+char * __init machine_specific_memory_setup(void);
+
+int __init copy_e820_map(struct e820entry * biosmap, int nr_map);
+int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map);
+void __init add_memory_region(unsigned long long start,
+			      unsigned long long size, int type);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _i386_SETUP_H */
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 61d3ab9..142d10e 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -5,7 +5,6 @@
  * We need the APIC definitions automatically as part of 'smp.h'
  */
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
index d76b769..04ba302 100644
--- a/include/asm-i386/spinlock.h
+++ b/include/asm-i386/spinlock.h
@@ -4,7 +4,6 @@
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 /*
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
index bb5f88a..b927736 100644
--- a/include/asm-i386/string.h
+++ b/include/asm-i386/string.h
@@ -2,7 +2,6 @@
 #define _I386_STRING_H_
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 /*
  * On a 486 or Pentium, we are better off not using the
  * byte string operations. But on a 386 or a PPro the
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index 19cc79c..cab0180 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
 #include <asm/cpufeature.h>
@@ -428,7 +427,7 @@
  * does not enforce ordering, since there is no data dependency between
  * the read of "a" and the read of "b".  Therefore, on some CPUs, such
  * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like thiswhere there are no data dependencies.
+ * in cases like this where there are no data dependencies.
  **/
 
 #define read_barrier_depends()	do { } while(0)
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 1f7d48c..2833fa2 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/page.h>
 
@@ -38,6 +37,7 @@
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
 						*/
+	void			*sysenter_return;
 	struct restart_block    restart_block;
 
 	unsigned long           previous_esp;   /* ESP of the previous stack in case
@@ -84,17 +84,15 @@
 #define init_stack		(init_thread_union.stack)
 
 
+/* how to get the current stack pointer from C */
+register unsigned long current_stack_pointer asm("esp") __attribute_used__;
+
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
-	struct thread_info *ti;
-	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
-	return ti;
+	return (struct thread_info *)(current_stack_pointer & ~(THREAD_SIZE - 1));
 }
 
-/* how to get the current stack pointer from C */
-register unsigned long current_stack_pointer asm("esp") __attribute_used__;
-
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
 #define alloc_thread_info(tsk)					\
@@ -141,8 +139,7 @@
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_SECCOMP		8	/* secure computing */
 #define TIF_RESTORE_SIGMASK	9	/* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
-#define TIF_MEMDIE		17
+#define TIF_MEMDIE		16
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -154,7 +151,6 @@
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
@@ -171,6 +167,9 @@
  * have to worry about atomic accesses.
  */
 #define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
+#define TS_POLLING		0x0002	/* True if in idle loop and not sleeping */
+
+#define tsk_is_polling(t) ((t)->thread_info->status & TS_POLLING)
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index aed1643..d0ebd05 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -3,68 +3,11 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 
-/**
- * struct timer_ops - used to define a timer source
- *
- * @name: name of the timer.
- * @init: Probes and initializes the timer. Takes clock= override 
- *        string as an argument. Returns 0 on success, anything else
- *        on failure.
- * @mark_offset: called by the timer interrupt.
- * @get_offset:  called by gettimeofday(). Returns the number of microseconds
- *               since the last timer interupt.
- * @monotonic_clock: returns the number of nanoseconds since the init of the
- *                   timer.
- * @delay: delays this many clock cycles.
- */
-struct timer_opts {
-	char* name;
-	void (*mark_offset)(void);
-	unsigned long (*get_offset)(void);
-	unsigned long long (*monotonic_clock)(void);
-	void (*delay)(unsigned long);
-	unsigned long (*read_timer)(void);
-	int (*suspend)(pm_message_t state);
-	int (*resume)(void);
-};
-
-struct init_timer_opts {
-	int (*init)(char *override);
-	struct timer_opts *opts;
-};
-
 #define TICK_SIZE (tick_nsec / 1000)
-
-extern struct timer_opts* __init select_timer(void);
-extern void clock_fallback(void);
 void setup_pit_timer(void);
-
 /* Modifiers for buggy PIT handling */
-
 extern int pit_latch_buggy;
-
-extern struct timer_opts *cur_timer;
 extern int timer_ack;
-
-/* list of externed timers */
-extern struct timer_opts timer_none;
-extern struct timer_opts timer_pit;
-extern struct init_timer_opts timer_pit_init;
-extern struct init_timer_opts timer_tsc_init;
-#ifdef CONFIG_X86_CYCLONE_TIMER
-extern struct init_timer_opts timer_cyclone_init;
-#endif
-
-extern unsigned long calibrate_tsc(void);
-extern unsigned long read_timer_tsc(void);
-extern void init_cpu_khz(void);
 extern int recalibrate_cpu_khz(void);
-#ifdef CONFIG_HPET_TIMER
-extern struct init_timer_opts timer_hpet_init;
-extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr);
-#endif
 
-#ifdef CONFIG_X86_PM_TIMER
-extern struct init_timer_opts timer_pmtmr_init;
-#endif
 #endif
diff --git a/include/asm-i386/timex.h b/include/asm-i386/timex.h
index 292b5a6..3666044 100644
--- a/include/asm-i386/timex.h
+++ b/include/asm-i386/timex.h
@@ -6,8 +6,8 @@
 #ifndef _ASMi386_TIMEX_H
 #define _ASMi386_TIMEX_H
 
-#include <linux/config.h>
 #include <asm/processor.h>
+#include <asm/tsc.h>
 
 #ifdef CONFIG_X86_ELAN
 #  define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */
@@ -16,39 +16,6 @@
 #endif
 
 
-/*
- * Standard way to access the cycle counter on i586+ CPUs.
- * Currently only used on SMP.
- *
- * If you really have a SMP machine with i486 chips or older,
- * compile for that, and this will just always return zero.
- * That's ok, it just means that the nicer scheduling heuristics
- * won't work for you.
- *
- * We only use the low 32 bits, and we'd simply better make sure
- * that we reschedule before that wraps. Scheduling at least every
- * four billion cycles just basically sounds like a good idea,
- * regardless of how fast the machine is. 
- */
-typedef unsigned long long cycles_t;
-
-static inline cycles_t get_cycles (void)
-{
-	unsigned long long ret=0;
-
-#ifndef CONFIG_X86_TSC
-	if (!cpu_has_tsc)
-		return 0;
-#endif
-
-#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
-	rdtscll(ret);
-#endif
-	return ret;
-}
-
-extern unsigned int cpu_khz;
-
 extern int read_current_timer(unsigned long *timer_value);
 #define ARCH_HAS_READ_CURRENT_TIMER	1
 
diff --git a/include/asm-i386/tlbflush.h b/include/asm-i386/tlbflush.h
index ab216e1..d57ca5c 100644
--- a/include/asm-i386/tlbflush.h
+++ b/include/asm-i386/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _I386_TLBFLUSH_H
 #define _I386_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index b94e5ee..6adbd9b 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -28,10 +28,8 @@
 #define _ASM_I386_TOPOLOGY_H
 
 #ifdef CONFIG_X86_HT
-#define topology_physical_package_id(cpu)				\
-	(phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu])
-#define topology_core_id(cpu)						\
-	(cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu])
+#define topology_physical_package_id(cpu)	(cpu_data[cpu].phys_proc_id)
+#define topology_core_id(cpu)			(cpu_data[cpu].cpu_core_id)
 #define topology_core_siblings(cpu)		(cpu_core_map[cpu])
 #define topology_thread_siblings(cpu)		(cpu_sibling_map[cpu])
 #endif
@@ -114,4 +112,9 @@
 
 extern cpumask_t cpu_coregroup_map(int cpu);
 
+#ifdef CONFIG_SMP
+#define mc_capable()	(boot_cpu_data.x86_max_cores > 1)
+#define smt_capable()	(smp_num_siblings > 1)
+#endif
+
 #endif /* _ASM_I386_TOPOLOGY_H */
diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h
new file mode 100644
index 0000000..97b828c
--- /dev/null
+++ b/include/asm-i386/tsc.h
@@ -0,0 +1,49 @@
+/*
+ * linux/include/asm-i386/tsc.h
+ *
+ * i386 TSC related functions
+ */
+#ifndef _ASM_i386_TSC_H
+#define _ASM_i386_TSC_H
+
+#include <linux/config.h>
+#include <asm/processor.h>
+
+/*
+ * Standard way to access the cycle counter on i586+ CPUs.
+ * Currently only used on SMP.
+ *
+ * If you really have a SMP machine with i486 chips or older,
+ * compile for that, and this will just always return zero.
+ * That's ok, it just means that the nicer scheduling heuristics
+ * won't work for you.
+ *
+ * We only use the low 32 bits, and we'd simply better make sure
+ * that we reschedule before that wraps. Scheduling at least every
+ * four billion cycles just basically sounds like a good idea,
+ * regardless of how fast the machine is.
+ */
+typedef unsigned long long cycles_t;
+
+extern unsigned int cpu_khz;
+extern unsigned int tsc_khz;
+
+static inline cycles_t get_cycles(void)
+{
+	unsigned long long ret = 0;
+
+#ifndef CONFIG_X86_TSC
+	if (!cpu_has_tsc)
+		return 0;
+#endif
+
+#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC)
+	rdtscll(ret);
+#endif
+	return ret;
+}
+
+extern void tsc_init(void);
+extern void mark_tsc_unstable(void);
+
+#endif
diff --git a/include/asm-i386/types.h b/include/asm-i386/types.h
index e50a08bd..4b4b295 100644
--- a/include/asm-i386/types.h
+++ b/include/asm-i386/types.h
@@ -35,7 +35,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 371457b..54d905e 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -4,7 +4,6 @@
 /*
  * User space memory access functions
  */
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
 #include <linux/prefetch.h>
@@ -59,7 +58,7 @@
 	__chk_user_ptr(addr); \
 	asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \
 		:"=&r" (flag), "=r" (sum) \
-		:"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \
+		:"1" (addr),"g" ((int)(size)),"rm" (current_thread_info()->addr_limit.seg)); \
 	flag; })
 
 /**
@@ -391,6 +390,12 @@
 				const void *from, unsigned long n);
 unsigned long __must_check __copy_from_user_ll(void *to,
 				const void __user *from, unsigned long n);
+unsigned long __must_check __copy_from_user_ll_nozero(void *to,
+				const void __user *from, unsigned long n);
+unsigned long __must_check __copy_from_user_ll_nocache(void *to,
+				const void __user *from, unsigned long n);
+unsigned long __must_check __copy_from_user_ll_nocache_nozero(void *to,
+				const void __user *from, unsigned long n);
 
 /*
  * Here we special-case 1, 2 and 4-byte copy_*_user invocations.  On a fault
@@ -457,10 +462,41 @@
  *
  * If some data could not be copied, this function will pad the copied
  * data to the requested size using zero bytes.
+ *
+ * An alternate version - __copy_from_user_inatomic() - may be called from
+ * atomic context and will fail rather than sleep.  In this case the
+ * uncopied bytes will *NOT* be padded with zeros.  See fs/filemap.h
+ * for explanation of why this is needed.
  */
 static __always_inline unsigned long
 __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 {
+	/* Avoid zeroing the tail if the copy fails..
+	 * If 'n' is constant and 1, 2, or 4, we do still zero on a failure,
+	 * but as the zeroing behaviour is only significant when n is not
+	 * constant, that shouldn't be a problem.
+	 */
+	if (__builtin_constant_p(n)) {
+		unsigned long ret;
+
+		switch (n) {
+		case 1:
+			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			return ret;
+		case 2:
+			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			return ret;
+		case 4:
+			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			return ret;
+		}
+	}
+	return __copy_from_user_ll_nozero(to, from, n);
+}
+static __always_inline unsigned long
+__copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+	might_sleep();
 	if (__builtin_constant_p(n)) {
 		unsigned long ret;
 
@@ -479,12 +515,36 @@
 	return __copy_from_user_ll(to, from, n);
 }
 
-static __always_inline unsigned long
-__copy_from_user(void *to, const void __user *from, unsigned long n)
+#define ARCH_HAS_NOCACHE_UACCESS
+
+static __always_inline unsigned long __copy_from_user_nocache(void *to,
+				const void __user *from, unsigned long n)
 {
-       might_sleep();
-       return __copy_from_user_inatomic(to, from, n);
+	might_sleep();
+	if (__builtin_constant_p(n)) {
+		unsigned long ret;
+
+		switch (n) {
+		case 1:
+			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			return ret;
+		case 2:
+			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			return ret;
+		case 4:
+			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			return ret;
+		}
+	}
+	return __copy_from_user_ll_nocache(to, from, n);
 }
+
+static __always_inline unsigned long
+__copy_from_user_inatomic_nocache(void *to, const void __user *from, unsigned long n)
+{
+       return __copy_from_user_ll_nocache_nozero(to, from, n);
+}
+
 unsigned long __must_check copy_to_user(void __user *to,
 				const void *from, unsigned long n);
 unsigned long __must_check copy_from_user(void *to,
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index eb4b152..fc1c8dd 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -322,8 +322,11 @@
 #define __NR_sync_file_range	314
 #define __NR_tee		315
 #define __NR_vmsplice		316
+#define __NR_move_pages		317
 
-#define NR_syscalls 317
+#ifdef __KERNEL__
+
+#define NR_syscalls 318
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
@@ -422,7 +425,6 @@
 __syscall_return(type,__res); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -446,7 +448,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -485,7 +486,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -497,4 +498,5 @@
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_I386_UNISTD_H_ */
diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h
new file mode 100644
index 0000000..69f0f1d
--- /dev/null
+++ b/include/asm-i386/unwind.h
@@ -0,0 +1,98 @@
+#ifndef _ASM_I386_UNWIND_H
+#define _ASM_I386_UNWIND_H
+
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *	Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ */
+
+#ifdef CONFIG_STACK_UNWIND
+
+#include <linux/sched.h>
+#include <asm/fixmap.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+
+struct unwind_frame_info
+{
+	struct pt_regs regs;
+	struct task_struct *task;
+};
+
+#define UNW_PC(frame)        (frame)->regs.eip
+#define UNW_SP(frame)        (frame)->regs.esp
+#ifdef CONFIG_FRAME_POINTER
+#define UNW_FP(frame)        (frame)->regs.ebp
+#define FRAME_RETADDR_OFFSET 4
+#define FRAME_LINK_OFFSET    0
+#define STACK_BOTTOM(tsk)    STACK_LIMIT((tsk)->thread.esp0)
+#define STACK_TOP(tsk)       ((tsk)->thread.esp0)
+#endif
+#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
+
+#define UNW_REGISTER_INFO \
+	PTREGS_INFO(eax), \
+	PTREGS_INFO(ecx), \
+	PTREGS_INFO(edx), \
+	PTREGS_INFO(ebx), \
+	PTREGS_INFO(esp), \
+	PTREGS_INFO(ebp), \
+	PTREGS_INFO(esi), \
+	PTREGS_INFO(edi), \
+	PTREGS_INFO(eip)
+
+static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
+                                            /*const*/ struct pt_regs *regs)
+{
+	if (user_mode_vm(regs))
+		info->regs = *regs;
+	else {
+		memcpy(&info->regs, regs, offsetof(struct pt_regs, esp));
+		info->regs.esp = (unsigned long)&regs->esp;
+		info->regs.xss = __KERNEL_DS;
+	}
+}
+
+static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
+{
+	memset(&info->regs, 0, sizeof(info->regs));
+	info->regs.eip = info->task->thread.eip;
+	info->regs.xcs = __KERNEL_CS;
+	__get_user(info->regs.ebp, (long *)info->task->thread.esp);
+	info->regs.esp = info->task->thread.esp;
+	info->regs.xss = __KERNEL_DS;
+	info->regs.xds = __USER_DS;
+	info->regs.xes = __USER_DS;
+}
+
+extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *,
+                                               asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                                          void *arg),
+                                               void *arg);
+
+static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
+{
+#if 0 /* This can only work when selector register and EFLAGS saves/restores
+         are properly annotated (and tracked in UNW_REGISTER_INFO). */
+	return user_mode_vm(&info->regs);
+#else
+	return info->regs.eip < PAGE_OFFSET
+	       || (info->regs.eip >= __fix_to_virt(FIX_VDSO)
+	            && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE)
+	       || info->regs.esp < PAGE_OFFSET;
+#endif
+}
+
+#else
+
+#define UNW_PC(frame) ((void)(frame), 0)
+
+static inline int arch_unw_user_mode(const void *info)
+{
+	return 0;
+}
+
+#endif
+
+#endif /* _ASM_I386_UNWIND_H */
diff --git a/include/asm-i386/vga.h b/include/asm-i386/vga.h
index ef0c0e5..0ecf68a 100644
--- a/include/asm-i386/vga.h
+++ b/include/asm-i386/vga.h
@@ -12,7 +12,7 @@
  *	access the videoram directly without any black magic.
  */
 
-#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x)
 
 #define vga_readb(x) (*(x))
 #define vga_writeb(x,y) (*(y) = (x))
diff --git a/include/asm-ia64/asmmacro.h b/include/asm-ia64/asmmacro.h
index edf2cebb..c22b465 100644
--- a/include/asm-ia64/asmmacro.h
+++ b/include/asm-ia64/asmmacro.h
@@ -6,7 +6,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #define ENTRY(name)				\
 	.align 32;				\
diff --git a/include/asm-ia64/cache.h b/include/asm-ia64/cache.h
index f0a104d..e7482bd 100644
--- a/include/asm-ia64/cache.h
+++ b/include/asm-ia64/cache.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_CACHE_H
 #define _ASM_IA64_CACHE_H
 
-#include <linux/config.h>
 
 /*
  * Copyright (C) 1998-2000 Hewlett-Packard Co
diff --git a/include/asm-ia64/delay.h b/include/asm-ia64/delay.h
index bba7020..a30a62f 100644
--- a/include/asm-ia64/delay.h
+++ b/include/asm-ia64/delay.h
@@ -12,7 +12,6 @@
  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/compiler.h>
diff --git a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h
index df67d40..99a8f8e 100644
--- a/include/asm-ia64/dma-mapping.h
+++ b/include/asm-ia64/dma-mapping.h
@@ -5,7 +5,6 @@
  * Copyright (C) 2003-2004 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
-#include <linux/config.h>
 #include <asm/machvec.h>
 
 #define dma_alloc_coherent	platform_dma_alloc_coherent
diff --git a/include/asm-ia64/dma.h b/include/asm-ia64/dma.h
index 3be1b49..dad3a73 100644
--- a/include/asm-ia64/dma.h
+++ b/include/asm-ia64/dma.h
@@ -6,7 +6,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/io.h>		/* need byte IO */
 
diff --git a/include/asm-ia64/elf.h b/include/asm-ia64/elf.h
index 446fce0..25f9835 100644
--- a/include/asm-ia64/elf.h
+++ b/include/asm-ia64/elf.h
@@ -8,7 +8,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/fpu.h>
 #include <asm/page.h>
diff --git a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
index 33ef8f0..140e495 100644
--- a/include/asm-ia64/hardirq.h
+++ b/include/asm-ia64/hardirq.h
@@ -6,7 +6,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <linux/threads.h>
 #include <linux/irq.h>
diff --git a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
index 0cf119b..ea8b8c4 100644
--- a/include/asm-ia64/hw_irq.h
+++ b/include/asm-ia64/hw_irq.h
@@ -47,9 +47,19 @@
 #define IA64_CMC_VECTOR			0x1f	/* corrected machine-check interrupt vector */
 /*
  * Vectors 0x20-0x2f are reserved for legacy ISA IRQs.
+ * Use vectors 0x30-0xe7 as the default device vector range for ia64.
+ * Platforms may choose to reduce this range in platform_irq_setup, but the
+ * platform range must fall within
+ *	[IA64_DEF_FIRST_DEVICE_VECTOR..IA64_DEF_LAST_DEVICE_VECTOR]
  */
-#define IA64_FIRST_DEVICE_VECTOR	0x30
-#define IA64_LAST_DEVICE_VECTOR		0xe7
+extern int ia64_first_device_vector;
+extern int ia64_last_device_vector;
+
+#define IA64_DEF_FIRST_DEVICE_VECTOR	0x30
+#define IA64_DEF_LAST_DEVICE_VECTOR	0xe7
+#define IA64_FIRST_DEVICE_VECTOR	ia64_first_device_vector
+#define IA64_LAST_DEVICE_VECTOR		ia64_last_device_vector
+#define IA64_MAX_DEVICE_VECTORS		(IA64_DEF_LAST_DEVICE_VECTOR - IA64_DEF_FIRST_DEVICE_VECTOR + 1)
 #define IA64_NUM_DEVICE_VECTORS		(IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1)
 
 #define IA64_MCA_RENDEZ_VECTOR		0xe8	/* MCA rendez interrupt */
@@ -83,6 +93,7 @@
 
 extern int assign_irq_vector (int irq);	/* allocate a free vector */
 extern void free_irq_vector (int vector);
+extern int reserve_irq_vector (int vector);
 extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
 extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
 
diff --git a/include/asm-ia64/ia32.h b/include/asm-ia64/ia32.h
index f8044a1..5ff8d74 100644
--- a/include/asm-ia64/ia32.h
+++ b/include/asm-ia64/ia32.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_IA32_H
 #define _ASM_IA64_IA32_H
 
-#include <linux/config.h>
 
 #include <asm/ptrace.h>
 #include <asm/signal.h>
diff --git a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h
index 93f45c5..e928675 100644
--- a/include/asm-ia64/ide.h
+++ b/include/asm-ia64/ide.h
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #include <linux/irq.h>
 
diff --git a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h
index 8089f95..3a95aa4 100644
--- a/include/asm-ia64/intrinsics.h
+++ b/include/asm-ia64/intrinsics.h
@@ -9,7 +9,6 @@
  */
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 
 /* include compiler specific intrinsics */
 #include <asm/ia64regs.h>
diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h
index c2e3742..781ee2c 100644
--- a/include/asm-ia64/io.h
+++ b/include/asm-ia64/io.h
@@ -88,6 +88,7 @@
 }
 
 #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size);
 extern int valid_phys_addr_range (unsigned long addr, size_t count); /* efi.c */
 extern int valid_mmap_phys_addr_range (unsigned long addr, size_t count);
 
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
index c195a9a..aed7142 100644
--- a/include/asm-ia64/kdebug.h
+++ b/include/asm-ia64/kdebug.h
@@ -40,6 +40,8 @@
 
 extern int register_die_notifier(struct notifier_block *);
 extern int unregister_die_notifier(struct notifier_block *);
+extern int register_page_fault_notifier(struct notifier_block *);
+extern int unregister_page_fault_notifier(struct notifier_block *);
 extern struct atomic_notifier_head ia64die_chain;
 
 enum die_val {
diff --git a/include/asm-ia64/kmap_types.h b/include/asm-ia64/kmap_types.h
index bc77752..5d1658a 100644
--- a/include/asm-ia64/kmap_types.h
+++ b/include/asm-ia64/kmap_types.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_IA64_KMAP_TYPES_H
 #define _ASM_IA64_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 8c0fc22..2418a78 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -82,6 +82,7 @@
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 
 #define ARCH_SUPPORTS_KRETPROBES
+#define  ARCH_INACTIVE_KPROBE_COUNT 1
 
 #define SLOT0_OPCODE_SHIFT	(37)
 #define SLOT1_p1_OPCODE_SHIFT	(37 - (64-46))
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index a9c995a..15b545a 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_IA64_MACHVEC_H
 #define _ASM_IA64_MACHVEC_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /* forward declarations: */
@@ -76,6 +75,7 @@
 typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
 typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
 typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
+typedef int ia64_mv_msi_init_t (void);
 
 static inline void
 machvec_noop (void)
@@ -154,6 +154,7 @@
 #  define platform_readl_relaxed        ia64_mv.readl_relaxed
 #  define platform_readq_relaxed        ia64_mv.readq_relaxed
 #  define platform_migrate		ia64_mv.migrate
+#  define platform_msi_init		ia64_mv.msi_init
 # endif
 
 /* __attribute__((__aligned__(16))) is required to make size of the
@@ -203,6 +204,7 @@
 	ia64_mv_readl_relaxed_t *readl_relaxed;
 	ia64_mv_readq_relaxed_t *readq_relaxed;
 	ia64_mv_migrate_t *migrate;
+	ia64_mv_msi_init_t *msi_init;
 } __attribute__((__aligned__(16))); /* align attrib? see above comment */
 
 #define MACHVEC_INIT(name)			\
@@ -248,6 +250,7 @@
 	platform_readl_relaxed,			\
 	platform_readq_relaxed,			\
 	platform_migrate,			\
+	platform_msi_init,			\
 }
 
 extern struct ia64_machine_vector ia64_mv;
@@ -401,5 +404,8 @@
 #ifndef platform_migrate
 # define platform_migrate machvec_noop_task
 #endif
+#ifndef platform_msi_init
+# define platform_msi_init	((ia64_mv_msi_init_t*)NULL)
+#endif
 
 #endif /* _ASM_IA64_MACHVEC_H */
diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
index da1d437..cf724dc 100644
--- a/include/asm-ia64/machvec_sn2.h
+++ b/include/asm-ia64/machvec_sn2.h
@@ -67,6 +67,8 @@
 extern ia64_mv_dma_mapping_error	sn_dma_mapping_error;
 extern ia64_mv_dma_supported		sn_dma_supported;
 extern ia64_mv_migrate_t		sn_migrate;
+extern ia64_mv_msi_init_t		sn_msi_init;
+
 
 /*
  * This stuff has dual use!
@@ -117,6 +119,11 @@
 #define platform_dma_mapping_error		sn_dma_mapping_error
 #define platform_dma_supported		sn_dma_supported
 #define platform_migrate		sn_migrate
+#ifdef CONFIG_PCI_MSI
+#define platform_msi_init		sn_msi_init
+#else
+#define platform_msi_init		((ia64_mv_msi_init_t*)NULL)
+#endif
 
 #include <asm/sn/io.h>
 
diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
index 9c5389b..ee97f7c 100644
--- a/include/asm-ia64/mca.h
+++ b/include/asm-ia64/mca.h
@@ -69,14 +69,16 @@
  */
 
 struct ia64_sal_os_state {
-	/* SAL to OS, must be at offset 0 */
+
+	/* SAL to OS */
 	u64			os_gp;			/* GP of the os registered with the SAL, physical */
 	u64			pal_proc;		/* PAL_PROC entry point, physical */
 	u64			sal_proc;		/* SAL_PROC entry point, physical */
 	u64			rv_rc;			/* MCA - Rendezvous state, INIT - reason code */
 	u64			proc_state_param;	/* from R18 */
 	u64			monarch;		/* 1 for a monarch event, 0 for a slave */
-	/* common, must follow SAL to OS */
+
+	/* common */
 	u64			sal_ra;			/* Return address in SAL, physical */
 	u64			sal_gp;			/* GP of the SAL - physical */
 	pal_min_state_area_t	*pal_min_state;		/* from R17.  physical in asm, virtual in C */
@@ -98,7 +100,8 @@
 	u64			iipa;
 	u64			iim;
 	u64			iha;
-	/* OS to SAL, must follow common */
+
+	/* OS to SAL */
 	u64			os_status;		/* OS status to SAL, enum below */
 	u64			context;		/* 0 if return to same context
 							   1 if return to new context */
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
index 46501b0..894bc4d 100644
--- a/include/asm-ia64/meminit.h
+++ b/include/asm-ia64/meminit.h
@@ -7,7 +7,6 @@
  * for more details.
  */
 
-#include <linux/config.h>
 
 /*
  * Entries defined so far:
diff --git a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h
index 97890f7..bb92b0d 100644
--- a/include/asm-ia64/msi.h
+++ b/include/asm-ia64/msi.h
@@ -14,4 +14,16 @@
 #define ack_APIC_irq		ia64_eoi
 #define MSI_TARGET_CPU_SHIFT	4
 
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+	if (platform_msi_init)
+		return platform_msi_init();
+
+	/* default ops for most ia64 platforms */
+	msi_register(&msi_apic_ops);
+	return 0;
+}
+
 #endif /* ASM_MSI_H */
diff --git a/include/asm-ia64/nodedata.h b/include/asm-ia64/nodedata.h
index 9978c7c..2fb337b 100644
--- a/include/asm-ia64/nodedata.h
+++ b/include/asm-ia64/nodedata.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_IA64_NODEDATA_H
 #define _ASM_IA64_NODEDATA_H
 
-#include <linux/config.h>
 #include <linux/numa.h>
 
 #include <asm/percpu.h>
@@ -47,6 +46,18 @@
  */
 #define NODE_DATA(nid)		(local_node_data->pg_data_ptrs[nid])
 
+/*
+ * LOCAL_DATA_ADDR - This is to calculate the address of other node's
+ *		     "local_node_data" at hot-plug phase. The local_node_data
+ *		     is pointed by per_cpu_page. Kernel usually use it for
+ *		     just executing cpu. However, when new node is hot-added,
+ *		     the addresses of local data for other nodes are necessary
+ *		     to update all of them.
+ */
+#define LOCAL_DATA_ADDR(pgdat)  			\
+	((struct ia64_node_data *)((u64)(pgdat) + 	\
+				   L1_CACHE_ALIGN(sizeof(struct pglist_data))))
+
 #endif /* CONFIG_NUMA */
 
 #endif /* _ASM_IA64_NODEDATA_H */
diff --git a/include/asm-ia64/numa.h b/include/asm-ia64/numa.h
index dae6aeb..e5a8260 100644
--- a/include/asm-ia64/numa.h
+++ b/include/asm-ia64/numa.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_IA64_NUMA_H
 #define _ASM_IA64_NUMA_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NUMA
 
diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h
index 2087825..f5a949e 100644
--- a/include/asm-ia64/page.h
+++ b/include/asm-ia64/page.h
@@ -7,7 +7,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/intrinsics.h>
 #include <asm/types.h>
diff --git a/include/asm-ia64/param.h b/include/asm-ia64/param.h
index 5e1e0d2..49c62dd 100644
--- a/include/asm-ia64/param.h
+++ b/include/asm-ia64/param.h
@@ -19,7 +19,6 @@
 #define MAXHOSTNAMELEN	64	/* max length of hostname */
 
 #ifdef __KERNEL__
-# include <linux/config.h>	/* mustn't include <linux/config.h> outside of #ifdef __KERNEL__ */
 # ifdef CONFIG_IA64_HP_SIM
   /*
    * Yeah, simulating stuff is slow, so let us catch some breath between
diff --git a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
index 2b14dee..24d898b 100644
--- a/include/asm-ia64/percpu.h
+++ b/include/asm-ia64/percpu.h
@@ -12,7 +12,6 @@
 # define THIS_CPU(var)	(per_cpu__##var)  /* use this to mark accesses to per-CPU variables... */
 #else /* !__ASSEMBLY__ */
 
-#include <linux/config.h>
 
 #include <linux/threads.h>
 
@@ -43,6 +42,7 @@
 
 #define per_cpu(var, cpu)  (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
 #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset)))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset)))
 
 extern void percpu_modcopy(void *pcpudst, const void *src, unsigned long size);
 extern void setup_per_cpu_areas (void);
@@ -52,6 +52,7 @@
 
 #define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
 #define __get_cpu_var(var)			per_cpu__##var
+#define __raw_get_cpu_var(var)			per_cpu__##var
 #define per_cpu_init()				(__phys_per_cpu_start)
 
 #endif	/* SMP */
diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h
index f2f2338..9cb68e9 100644
--- a/include/asm-ia64/pgalloc.h
+++ b/include/asm-ia64/pgalloc.h
@@ -13,7 +13,6 @@
  * Copyright (C) 2000, Goutham Rao <goutham.rao@intel.com>
  */
 
-#include <linux/config.h>
 
 #include <linux/compiler.h>
 #include <linux/mm.h>
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index c0f8144..228981c 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -12,7 +12,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <asm/mman.h>
 #include <asm/page.h>
@@ -317,22 +316,20 @@
 #define pte_mkhuge(pte)		(__pte(pte_val(pte)))
 
 /*
- * Macro to a page protection value as "uncacheable".  Note that "protection" is really a
- * misnomer here as the protection value contains the memory attribute bits, dirty bits,
- * and various other bits as well.
+ * Make page protection values cacheable, uncacheable, or write-
+ * combining.  Note that "protection" is really a misnomer here as the
+ * protection value contains the memory attribute bits, dirty bits, and
+ * various other bits as well.
  */
+#define pgprot_cacheable(prot)		__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WB)
 #define pgprot_noncached(prot)		__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_UC)
-
-/*
- * Macro to make mark a page protection value as "write-combining".
- * Note that "protection" is really a misnomer here as the protection
- * value contains the memory attribute bits, dirty bits, and various
- * other bits as well.  Accesses through a write-combining translation
- * works bypasses the caches, but does allow for consecutive writes to
- * be combined into single (but larger) write transactions.
- */
 #define pgprot_writecombine(prot)	__pgprot((pgprot_val(prot) & ~_PAGE_MA_MASK) | _PAGE_MA_WC)
 
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+				     unsigned long size, pgprot_t vma_prot);
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+
 static inline unsigned long
 pgd_index (unsigned long address)
 {
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index b3bd58e..265f482 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -13,7 +13,6 @@
  * 06/16/00	A. Mallick	added csd/ssd/tssd for ia32 support
  */
 
-#include <linux/config.h>
 
 #include <asm/intrinsics.h>
 #include <asm/kregs.h>
diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h
index 9471cdc..415abb2 100644
--- a/include/asm-ia64/ptrace.h
+++ b/include/asm-ia64/ptrace.h
@@ -54,7 +54,6 @@
  * This is because ar.ec is saved as part of ar.pfs.
  */
 
-#include <linux/config.h>
 
 #include <asm/fpu.h>
 #ifndef ASM_OFFSETS_C
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index a391435..719ff30 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_IA64_SMP_H
 #define _ASM_IA64_SMP_H
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h
index 60a51a4..12b54dd 100644
--- a/include/asm-ia64/sn/intr.h
+++ b/include/asm-ia64/sn/intr.h
@@ -10,6 +10,7 @@
 #define _ASM_IA64_SN_INTR_H
 
 #include <linux/rcupdate.h>
+#include <asm/sn/types.h>
 
 #define SGI_UART_VECTOR		0xe9
 
@@ -40,6 +41,7 @@
 	int		irq_cpuid;	/* kernel logical cpuid	     */
 	int		irq_irq;	/* the IRQ number */
 	int		irq_int_bit;	/* Bridge interrupt pin */
+					/* <0 means MSI */
 	u64	irq_xtalkaddr;	/* xtalkaddr IRQ is sent to  */
 	int		irq_bridge_type;/* pciio asic type (pciio.h) */
 	void	       *irq_bridge;	/* bridge generating irq     */
@@ -53,6 +55,12 @@
 };
 
 extern void sn_send_IPI_phys(int, long, int, int);
+extern u64 sn_intr_alloc(nasid_t, int,
+			      struct sn_irq_info *,
+			      int, nasid_t, int);
+extern void sn_intr_free(nasid_t, int, struct sn_irq_info *);
+extern struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *, nasid_t, int);
+extern struct list_head **sn_irq_lh;
 
 #define CPU_VECTOR_TO_IRQ(cpuid,vector) (vector)
 
diff --git a/include/asm-ia64/sn/pcibr_provider.h b/include/asm-ia64/sn/pcibr_provider.h
index 51260ab..e3b0c3f 100644
--- a/include/asm-ia64/sn/pcibr_provider.h
+++ b/include/asm-ia64/sn/pcibr_provider.h
@@ -55,6 +55,7 @@
 #define PCI32_ATE_V                     (0x1 << 0)
 #define PCI32_ATE_CO                    (0x1 << 1)
 #define PCI32_ATE_PREC                  (0x1 << 2)
+#define PCI32_ATE_MSI                   (0x1 << 2)
 #define PCI32_ATE_PREF                  (0x1 << 3)
 #define PCI32_ATE_BAR                   (0x1 << 4)
 #define PCI32_ATE_ADDR_SHFT             12
@@ -117,8 +118,8 @@
 
 extern int  pcibr_init_provider(void);
 extern void *pcibr_bus_fixup(struct pcibus_bussoft *, struct pci_controller *);
-extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t);
-extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t);
+extern dma_addr_t pcibr_dma_map(struct pci_dev *, unsigned long, size_t, int type);
+extern dma_addr_t pcibr_dma_map_consistent(struct pci_dev *, unsigned long, size_t, int type);
 extern void pcibr_dma_unmap(struct pci_dev *, dma_addr_t, int);
 
 /*
diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h
index ce3f6c3..8f7c83d 100644
--- a/include/asm-ia64/sn/pcibus_provider_defs.h
+++ b/include/asm-ia64/sn/pcibus_provider_defs.h
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
  */
 #ifndef _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
 #define _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H
@@ -45,13 +45,24 @@
  */
 
 struct sn_pcibus_provider {
-	dma_addr_t	(*dma_map)(struct pci_dev *, unsigned long, size_t);
-	dma_addr_t	(*dma_map_consistent)(struct pci_dev *, unsigned long, size_t);
+	dma_addr_t	(*dma_map)(struct pci_dev *, unsigned long, size_t, int flags);
+	dma_addr_t	(*dma_map_consistent)(struct pci_dev *, unsigned long, size_t, int flags);
 	void		(*dma_unmap)(struct pci_dev *, dma_addr_t, int);
 	void *		(*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
  	void		(*force_interrupt)(struct sn_irq_info *);
  	void		(*target_interrupt)(struct sn_irq_info *);
 };
 
+/*
+ * Flags used by the map interfaces
+ * bits 3:0 specifies format of passed in address
+ * bit  4   specifies that address is to be used for MSI
+ */
+
+#define SN_DMA_ADDRTYPE(x)	((x) & 0xf)
+#define     SN_DMA_ADDR_PHYS	1	/* address is an xio address. */
+#define     SN_DMA_ADDR_XIO	2	/* address is phys memory */
+#define SN_DMA_MSI		0x10	/* Bus address is to be used for MSI */
+
 extern struct sn_pcibus_provider *sn_pci_provider[];
 #endif				/* _ASM_IA64_SN_PCI_PCIBUS_PROVIDER_H */
diff --git a/include/asm-ia64/sn/simulator.h b/include/asm-ia64/sn/simulator.h
index 16a48b5..c3fd3eb 100644
--- a/include/asm-ia64/sn/simulator.h
+++ b/include/asm-ia64/sn/simulator.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_IA64_SN_SIMULATOR_H
 #define _ASM_IA64_SN_SIMULATOR_H
 
-#include <linux/config.h>
 
 #define SNMAGIC 0xaeeeeeee8badbeefL
 #define IS_MEDUSA()			({long sn; asm("mov %0=cpuid[%1]" : "=r"(sn) : "r"(2)); sn == SNMAGIC;})
diff --git a/include/asm-ia64/sn/sn_cpuid.h b/include/asm-ia64/sn/sn_cpuid.h
index 749deb2..a676dd9 100644
--- a/include/asm-ia64/sn/sn_cpuid.h
+++ b/include/asm-ia64/sn/sn_cpuid.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_IA64_SN_SN_CPUID_H
 #define _ASM_IA64_SN_SN_CPUID_H
 
-#include <linux/config.h>
 #include <linux/smp.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/pda.h>
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 51aca02..bd4452b 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -12,7 +12,6 @@
  */
 
 
-#include <linux/config.h>
 #include <asm/sal.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/sn/arch.h>
@@ -86,6 +85,7 @@
 #define  SN_SAL_GET_PROM_FEATURE_SET		   0x02000065
 #define  SN_SAL_SET_OS_FEATURE_SET		   0x02000066
 #define  SN_SAL_INJECT_ERROR			   0x02000067
+#define  SN_SAL_SET_CPU_NUMBER			   0x02000068
 
 /*
  * Service-specific constants
@@ -346,7 +346,7 @@
 	ret_stuff.v1 = 0;
 	ret_stuff.v2 = 0;
 	SAL_CALL_REENTRANT(ret_stuff, SN_SAL_SET_ERROR_HANDLING_FEATURES,
-		(SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV | SAL_ERR_FEAT_LOG_SBES),
+		SAL_ERR_FEAT_LOG_SBES,
 		0, 0, 0, 0, 0, 0);
 
 	return ret_stuff.status;
@@ -1151,4 +1151,13 @@
 	local_irq_restore(irq_flags);
 	return ret_stuff.status;
 }
+
+static inline int
+ia64_sn_set_cpu_number(int cpu)
+{
+	struct ia64_sal_retval rv;
+
+	SAL_CALL_NOLOCK(rv, SN_SAL_SET_CPU_NUMBER, cpu, 0, 0, 0, 0, 0, 0);
+	return rv.status;
+}
 #endif /* _ASM_IA64_SN_SN_SAL_H */
diff --git a/include/asm-ia64/sn/tiocp.h b/include/asm-ia64/sn/tiocp.h
index f47c08a..e8ad0bb 100644
--- a/include/asm-ia64/sn/tiocp.h
+++ b/include/asm-ia64/sn/tiocp.h
@@ -3,13 +3,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2003-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc. All rights reserved.
  */
 #ifndef _ASM_IA64_SN_PCI_TIOCP_H
 #define _ASM_IA64_SN_PCI_TIOCP_H
 
 #define TIOCP_HOST_INTR_ADDR            0x003FFFFFFFFFFFFFUL
 #define TIOCP_PCI64_CMDTYPE_MEM         (0x1ull << 60)
+#define TIOCP_PCI64_CMDTYPE_MSI         (0x3ull << 60)
 
 
 /*****************************************************************************
diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index aa3b8ac..8406f1e 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -15,7 +15,6 @@
 #define _ASM_IA64_SN_XPC_H
 
 
-#include <linux/config.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/device.h>
diff --git a/include/asm-ia64/string.h b/include/asm-ia64/string.h
index 43502d3..85fd65c 100644
--- a/include/asm-ia64/string.h
+++ b/include/asm-ia64/string.h
@@ -9,7 +9,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>	/* remove this once we remove the A-step workaround... */
 
 #define __HAVE_ARCH_STRLEN	1 /* see arch/ia64/lib/strlen.S */
 #define __HAVE_ARCH_MEMSET	1 /* see arch/ia64/lib/memset.S */
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 2f362059..65db43c 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -12,7 +12,6 @@
  * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
  */
-#include <linux/config.h>
 
 #include <asm/kregs.h>
 #include <asm/page.h>
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index e5392c4..8bc9869 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -27,6 +27,7 @@
 	__u32 flags;			/* thread_info flags (see TIF_*) */
 	__u32 cpu;			/* current CPU */
 	__u32 last_cpu;			/* Last CPU thread ran on */
+	__u32 status;			/* Thread synchronous flags */
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
 	struct restart_block restart_block;
@@ -103,4 +104,8 @@
 /* like TIF_ALLWORK_BITS but sans TIF_SYSCALL_TRACE or TIF_SYSCALL_AUDIT */
 #define TIF_WORK_MASK		(TIF_ALLWORK_MASK&~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT))
 
+#define TS_POLLING		1 	/* true if in idle loop and not sleeping */
+
+#define tsk_is_polling(t) ((t)->thread_info->status & TS_POLLING)
+
 #endif /* _ASM_IA64_THREAD_INFO_H */
diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
index 834370b..26edcb7 100644
--- a/include/asm-ia64/tlb.h
+++ b/include/asm-ia64/tlb.h
@@ -37,7 +37,6 @@
  *	}
  *	tlb_finish_mmu(tlb, start, end);	// finish unmap for address space MM
  */
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
diff --git a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h
index a35b323..cf9acb9 100644
--- a/include/asm-ia64/tlbflush.h
+++ b/include/asm-ia64/tlbflush.h
@@ -6,7 +6,6 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/config.h>
 
 #include <linux/mm.h>
 
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 616b5ed..937c2125 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -112,6 +112,7 @@
 #define topology_core_id(cpu)			(cpu_data(cpu)->core_id)
 #define topology_core_siblings(cpu)		(cpu_core_map[cpu])
 #define topology_thread_siblings(cpu)		(cpu_sibling_map[cpu])
+#define smt_capable() 				(smp_num_siblings > 1)
 #endif
 
 #include <asm-generic/topology.h>
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 7107763..bb0eb72 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -265,7 +265,7 @@
 #define __NR_keyctl			1273
 #define __NR_ioprio_set			1274
 #define __NR_ioprio_get			1275
-/* 1276 is available for reuse (was briefly sys_set_zone_reclaim) */
+#define __NR_move_pages			1276
 #define __NR_inotify_init		1277
 #define __NR_inotify_add_watch		1278
 #define __NR_inotify_rm_watch		1279
@@ -294,7 +294,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define NR_syscalls			279 /* length of syscall table */
 
diff --git a/include/asm-ia64/vga.h b/include/asm-ia64/vga.h
index 091177c..02184ec 100644
--- a/include/asm-ia64/vga.h
+++ b/include/asm-ia64/vga.h
@@ -17,7 +17,7 @@
 extern unsigned long vga_console_iobase;
 extern unsigned long vga_console_membase;
 
-#define VGA_MAP_MEM(x)	((unsigned long) ioremap_nocache(vga_console_membase + (x), 0))
+#define VGA_MAP_MEM(x,s)	((unsigned long) ioremap_nocache(vga_console_membase + (x), s))
 
 #define vga_readb(x)	(*(x))
 #define vga_writeb(x,y)	(*(y) = (x))
diff --git a/include/asm-m32r/assembler.h b/include/asm-m32r/assembler.h
index 1a1aa17..47041d1 100644
--- a/include/asm-m32r/assembler.h
+++ b/include/asm-m32r/assembler.h
@@ -9,7 +9,6 @@
  * This file contains M32R architecture specific macro definitions.
  */
 
-#include <linux/config.h>
 
 #ifndef __STR
 #ifdef __ASSEMBLY__
diff --git a/include/asm-m32r/atomic.h b/include/asm-m32r/atomic.h
index 3122fe1..f5a7d73 100644
--- a/include/asm-m32r/atomic.h
+++ b/include/asm-m32r/atomic.h
@@ -9,7 +9,6 @@
  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <asm/assembler.h>
 #include <asm/system.h>
 
diff --git a/include/asm-m32r/bitops.h b/include/asm-m32r/bitops.h
index 902a366..66ab672 100644
--- a/include/asm-m32r/bitops.h
+++ b/include/asm-m32r/bitops.h
@@ -11,7 +11,6 @@
  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/assembler.h>
 #include <asm/system.h>
diff --git a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
index e57427b..8b261b4 100644
--- a/include/asm-m32r/cacheflush.h
+++ b/include/asm-m32r/cacheflush.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_CACHEFLUSH_H
 #define _ASM_M32R_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 extern void _flush_cache_all(void);
diff --git a/include/asm-m32r/hardirq.h b/include/asm-m32r/hardirq.h
index 5da830e..cb8aa76 100644
--- a/include/asm-m32r/hardirq.h
+++ b/include/asm-m32r/hardirq.h
@@ -2,7 +2,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
index f7aa969..219a0f7 100644
--- a/include/asm-m32r/ide.h
+++ b/include/asm-m32r/ide.h
@@ -15,7 +15,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef MAX_HWIFS
 # ifdef CONFIG_BLK_DEV_IDEPCI
diff --git a/include/asm-m32r/irq.h b/include/asm-m32r/irq.h
index ca94395..2f93f47 100644
--- a/include/asm-m32r/irq.h
+++ b/include/asm-m32r/irq.h
@@ -2,7 +2,6 @@
 #ifndef _ASM_M32R_IRQ_H
 #define _ASM_M32R_IRQ_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_USRV)
 /*
diff --git a/include/asm-m32r/kmap_types.h b/include/asm-m32r/kmap_types.h
index 7429591..0524d89 100644
--- a/include/asm-m32r/kmap_types.h
+++ b/include/asm-m32r/kmap_types.h
@@ -3,7 +3,6 @@
 
 /* Dummy header just to define km_type. */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
diff --git a/include/asm-m32r/m32104ut/m32104ut_pld.h b/include/asm-m32r/m32104ut/m32104ut_pld.h
index a4eac20..6ba4ddf 100644
--- a/include/asm-m32r/m32104ut/m32104ut_pld.h
+++ b/include/asm-m32r/m32104ut/m32104ut_pld.h
@@ -15,7 +15,6 @@
 #ifndef _M32104UT_M32104UT_PLD_H
 #define _M32104UT_M32104UT_PLD_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PLAT_M32104UT)
 #define PLD_PLAT_BASE		0x02c00000
diff --git a/include/asm-m32r/m32700ut/m32700ut_lan.h b/include/asm-m32r/m32700ut/m32700ut_lan.h
index 50545ec..c050b19 100644
--- a/include/asm-m32r/m32700ut/m32700ut_lan.h
+++ b/include/asm-m32r/m32700ut/m32700ut_lan.h
@@ -15,7 +15,6 @@
 #ifndef _M32700UT_M32700UT_LAN_H
 #define _M32700UT_M32700UT_LAN_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/include/asm-m32r/m32700ut/m32700ut_lcd.h b/include/asm-m32r/m32700ut/m32700ut_lcd.h
index ede6c77..4da4e82 100644
--- a/include/asm-m32r/m32700ut/m32700ut_lcd.h
+++ b/include/asm-m32r/m32700ut/m32700ut_lcd.h
@@ -15,7 +15,6 @@
 #ifndef _M32700UT_M32700UT_LCD_H
 #define _M32700UT_M32700UT_LCD_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/include/asm-m32r/m32700ut/m32700ut_pld.h b/include/asm-m32r/m32700ut/m32700ut_pld.h
index f5e4794..f35f915 100644
--- a/include/asm-m32r/m32700ut/m32700ut_pld.h
+++ b/include/asm-m32r/m32700ut/m32700ut_pld.h
@@ -15,7 +15,6 @@
 #ifndef _M32700UT_M32700UT_PLD_H
 #define _M32700UT_M32700UT_PLD_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_PLAT_M32700UT_Alpha)
 #define PLD_PLAT_BASE		0x08c00000
diff --git a/include/asm-m32r/m32r.h b/include/asm-m32r/m32r.h
index b133ca6..decfc59 100644
--- a/include/asm-m32r/m32r.h
+++ b/include/asm-m32r/m32r.h
@@ -7,7 +7,6 @@
  * Copyright (C) 2003, 2004  Renesas Technology Corp.
  */
 
-#include <linux/config.h>
 
 /* Chip type */
 #if defined(CONFIG_CHIP_XNUX_MP) || defined(CONFIG_CHIP_XNUX2_MP)
diff --git a/include/asm-m32r/mmu.h b/include/asm-m32r/mmu.h
index 9c00eb7..cf3f6d7 100644
--- a/include/asm-m32r/mmu.h
+++ b/include/asm-m32r/mmu.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_MMU_H
 #define _ASM_M32R_MMU_H
 
-#include <linux/config.h>
 
 #if !defined(CONFIG_MMU)
 typedef struct {
diff --git a/include/asm-m32r/mmu_context.h b/include/asm-m32r/mmu_context.h
index 3634c53..542302e 100644
--- a/include/asm-m32r/mmu_context.h
+++ b/include/asm-m32r/mmu_context.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #include <asm/m32r.h>
 
@@ -15,7 +14,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu.h>
diff --git a/include/asm-m32r/opsput/opsput_lan.h b/include/asm-m32r/opsput/opsput_lan.h
index 7a2a839..6194829 100644
--- a/include/asm-m32r/opsput/opsput_lan.h
+++ b/include/asm-m32r/opsput/opsput_lan.h
@@ -15,7 +15,6 @@
 #ifndef _OPSPUT_OPSPUT_LAN_H
 #define _OPSPUT_OPSPUT_LAN_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/include/asm-m32r/opsput/opsput_lcd.h b/include/asm-m32r/opsput/opsput_lcd.h
index 3a883e3..44cfd7f 100644
--- a/include/asm-m32r/opsput/opsput_lcd.h
+++ b/include/asm-m32r/opsput/opsput_lcd.h
@@ -15,7 +15,6 @@
 #ifndef _OPSPUT_OPSPUT_LCD_H
 #define _OPSPUT_OPSPUT_LCD_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 /*
diff --git a/include/asm-m32r/opsput/opsput_pld.h b/include/asm-m32r/opsput/opsput_pld.h
index 2018e69..46296fe 100644
--- a/include/asm-m32r/opsput/opsput_pld.h
+++ b/include/asm-m32r/opsput/opsput_pld.h
@@ -15,7 +15,6 @@
 #ifndef _OPSPUT_OPSPUT_PLD_H
 #define _OPSPUT_OPSPUT_PLD_H
 
-#include <linux/config.h>
 
 #define PLD_PLAT_BASE		0x1cc00000
 
diff --git a/include/asm-m32r/page.h b/include/asm-m32r/page.h
index 9ddbc08..9688be0 100644
--- a/include/asm-m32r/page.h
+++ b/include/asm-m32r/page.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_PAGE_H
 #define _ASM_M32R_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
diff --git a/include/asm-m32r/pgalloc.h b/include/asm-m32r/pgalloc.h
index 6da309b..e09a86c 100644
--- a/include/asm-m32r/pgalloc.h
+++ b/include/asm-m32r/pgalloc.h
@@ -3,7 +3,6 @@
 
 /* $Id$ */
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 #include <asm/io.h>
diff --git a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
index 861727c2..be0f167e 100644
--- a/include/asm-m32r/pgtable-2level.h
+++ b/include/asm-m32r/pgtable-2level.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * traditional M32R two-level paging structure:
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 75740de..1983b7f 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -20,7 +20,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/processor.h>
 #include <asm/addrspace.h>
diff --git a/include/asm-m32r/processor.h b/include/asm-m32r/processor.h
index 09fd181..32755bf 100644
--- a/include/asm-m32r/processor.h
+++ b/include/asm-m32r/processor.h
@@ -14,7 +14,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <asm/cache.h>
 #include <asm/ptrace.h>  /* pt_regs */
 
diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h
index 53c7924..a07fa90 100644
--- a/include/asm-m32r/ptrace.h
+++ b/include/asm-m32r/ptrace.h
@@ -12,7 +12,6 @@
  *   Copyright (C) 2001-2002, 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <asm/m32r.h>		/* M32R_PSW_BSM, M32R_PSW_BPM */
 
 /* 0 - 13 are integer registers (general purpose registers).  */
diff --git a/include/asm-m32r/rtc.h b/include/asm-m32r/rtc.h
index ec3cdf6..6b2b837 100644
--- a/include/asm-m32r/rtc.h
+++ b/include/asm-m32r/rtc.h
@@ -4,7 +4,6 @@
 #define __RTC_H__
 
 
-#include <linux/config.h>
 
    /* Dallas DS1302 clock/calendar register numbers. */
 #  define RTC_SECONDS      0
diff --git a/include/asm-m32r/semaphore.h b/include/asm-m32r/semaphore.h
index 81750ed..41e45d7 100644
--- a/include/asm-m32r/semaphore.h
+++ b/include/asm-m32r/semaphore.h
@@ -12,7 +12,6 @@
  * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <linux/wait.h>
 #include <linux/rwsem.h>
 #include <asm/assembler.h>
diff --git a/include/asm-m32r/serial.h b/include/asm-m32r/serial.h
index 1bf480f..5ac244c 100644
--- a/include/asm-m32r/serial.h
+++ b/include/asm-m32r/serial.h
@@ -3,7 +3,6 @@
 
 /* include/asm-m32r/serial.h */
 
-#include <linux/config.h>
 
 #define BASE_BAUD	115200
 
diff --git a/include/asm-m32r/sigcontext.h b/include/asm-m32r/sigcontext.h
index 942b8a3..73025c0 100644
--- a/include/asm-m32r/sigcontext.h
+++ b/include/asm-m32r/sigcontext.h
@@ -3,7 +3,6 @@
 
 /* $Id$ */
 
-#include <linux/config.h>
 
 struct sigcontext {
 	/* CPU registers */
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
index 1184293..650d255 100644
--- a/include/asm-m32r/smp.h
+++ b/include/asm-m32r/smp.h
@@ -3,7 +3,6 @@
 
 /* $Id$ */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 #ifndef __ASSEMBLY__
diff --git a/include/asm-m32r/spinlock.h b/include/asm-m32r/spinlock.h
index 7de7def..f94c1a6 100644
--- a/include/asm-m32r/spinlock.h
+++ b/include/asm-m32r/spinlock.h
@@ -9,7 +9,6 @@
  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>	/* CONFIG_DEBUG_SPINLOCK, CONFIG_SMP */
 #include <linux/compiler.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index e55013f..66c4742f 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -10,7 +10,6 @@
  * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
-#include <linux/config.h>
 #include <asm/assembler.h>
 
 #ifdef __KERNEL__
@@ -319,7 +318,7 @@
  * does not enforce ordering, since there is no data dependency between
  * the read of "a" and the read of "b".  Therefore, on some CPUs, such
  * as Alpha, "y" could be set to 3 and "x" to 0.  Use rmb()
- * in cases like thiswhere there are no data dependencies.
+ * in cases like this where there are no data dependencies.
  **/
 
 #define read_barrier_depends()	do { } while (0)
diff --git a/include/asm-m32r/timex.h b/include/asm-m32r/timex.h
index abf12e7..e89bfd1 100644
--- a/include/asm-m32r/timex.h
+++ b/include/asm-m32r/timex.h
@@ -9,7 +9,6 @@
  * m32r architecture timex specifications
  */
 
-#include <linux/config.h>
 
 #define CLOCK_TICK_RATE	(CONFIG_BUS_CLOCK / CONFIG_TIMER_DIVIDE)
 #define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
diff --git a/include/asm-m32r/tlbflush.h b/include/asm-m32r/tlbflush.h
index bc7c407..ae44949 100644
--- a/include/asm-m32r/tlbflush.h
+++ b/include/asm-m32r/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_M32R_TLBFLUSH_H
 #define _ASM_M32R_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <asm/m32r.h>
 
 /*
diff --git a/include/asm-m32r/uaccess.h b/include/asm-m32r/uaccess.h
index 819cc28..26e978c 100644
--- a/include/asm-m32r/uaccess.h
+++ b/include/asm-m32r/uaccess.h
@@ -11,7 +11,6 @@
 /*
  * User space memory access functions
  */
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
 #include <asm/page.h>
diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
index be0eb01..cc31790 100644
--- a/include/asm-m32r/unistd.h
+++ b/include/asm-m32r/unistd.h
@@ -295,6 +295,8 @@
 #define __NR_kexec_load		283
 #define __NR_waitid		284
 
+#ifdef __KERNEL__
+
 #define NR_syscalls 285
 
 /* user-visible error numbers are in the range -1 - -124: see
@@ -405,7 +407,6 @@
 __syscall_return(type,__res); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
@@ -421,7 +422,6 @@
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT /*will be unused*/
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -470,4 +470,5 @@
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_M32R_UNISTD_H */
diff --git a/include/asm-m32r/vga.h b/include/asm-m32r/vga.h
index d0f4b6e..5331634 100644
--- a/include/asm-m32r/vga.h
+++ b/include/asm-m32r/vga.h
@@ -14,7 +14,7 @@
  *	access the videoram directly without any black magic.
  */
 
-#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x)
 
 #define vga_readb(x) (*(x))
 #define vga_writeb(x,y) (*(y) = (x))
diff --git a/include/asm-m68k/amigaints.h b/include/asm-m68k/amigaints.h
index aa968d0..7c87134 100644
--- a/include/asm-m68k/amigaints.h
+++ b/include/asm-m68k/amigaints.h
@@ -13,6 +13,8 @@
 #ifndef _ASMm68k_AMIGAINTS_H_
 #define _ASMm68k_AMIGAINTS_H_
 
+#include <asm/irq.h>
+
 /*
 ** Amiga Interrupt sources.
 **
@@ -23,72 +25,52 @@
 #define CIA_IRQS            (5)
 #define AMI_IRQS            (32) /* AUTO_IRQS+AMI_STD_IRQS+2*CIA_IRQS */
 
-/* vertical blanking interrupt */
-#define IRQ_AMIGA_VERTB     0
-
-/* copper interrupt */
-#define IRQ_AMIGA_COPPER    1
-
-/* Audio interrupts */
-#define IRQ_AMIGA_AUD0	    2
-#define IRQ_AMIGA_AUD1	    3
-#define IRQ_AMIGA_AUD2	    4
-#define IRQ_AMIGA_AUD3	    5
-
-/* Blitter done interrupt */
-#define IRQ_AMIGA_BLIT	    6
+/* builtin serial port interrupts */
+#define IRQ_AMIGA_TBE		(IRQ_USER+0)
+#define IRQ_AMIGA_RBF		(IRQ_USER+11)
 
 /* floppy disk interrupts */
-#define IRQ_AMIGA_DSKSYN    7
-#define IRQ_AMIGA_DSKBLK    8
-
-/* builtin serial port interrupts */
-#define IRQ_AMIGA_RBF	    9
-#define IRQ_AMIGA_TBE	    10
+#define IRQ_AMIGA_DSKBLK	(IRQ_USER+1)
+#define IRQ_AMIGA_DSKSYN	(IRQ_USER+12)
 
 /* software interrupts */
-#define IRQ_AMIGA_SOFT      11
+#define IRQ_AMIGA_SOFT		(IRQ_USER+2)
 
 /* interrupts from external hardware */
-#define IRQ_AMIGA_PORTS	    12
-#define IRQ_AMIGA_EXTER	    13
+#define IRQ_AMIGA_PORTS		IRQ_AUTO_2
+#define IRQ_AMIGA_EXTER		IRQ_AUTO_6
+
+/* copper interrupt */
+#define IRQ_AMIGA_COPPER	(IRQ_USER+4)
+
+/* vertical blanking interrupt */
+#define IRQ_AMIGA_VERTB		(IRQ_USER+5)
+
+/* Blitter done interrupt */
+#define IRQ_AMIGA_BLIT		(IRQ_USER+6)
+
+/* Audio interrupts */
+#define IRQ_AMIGA_AUD0		(IRQ_USER+7)
+#define IRQ_AMIGA_AUD1		(IRQ_USER+8)
+#define IRQ_AMIGA_AUD2		(IRQ_USER+9)
+#define IRQ_AMIGA_AUD3		(IRQ_USER+10)
 
 /* CIA interrupt sources */
-#define IRQ_AMIGA_CIAA      14
-#define IRQ_AMIGA_CIAA_TA   14
-#define IRQ_AMIGA_CIAA_TB   15
-#define IRQ_AMIGA_CIAA_ALRM 16
-#define IRQ_AMIGA_CIAA_SP   17
-#define IRQ_AMIGA_CIAA_FLG  18
-#define IRQ_AMIGA_CIAB      19
-#define IRQ_AMIGA_CIAB_TA   19
-#define IRQ_AMIGA_CIAB_TB   20
-#define IRQ_AMIGA_CIAB_ALRM 21
-#define IRQ_AMIGA_CIAB_SP   22
-#define IRQ_AMIGA_CIAB_FLG  23
+#define IRQ_AMIGA_CIAA		(IRQ_USER+14)
+#define IRQ_AMIGA_CIAA_TA	(IRQ_USER+14)
+#define IRQ_AMIGA_CIAA_TB	(IRQ_USER+15)
+#define IRQ_AMIGA_CIAA_ALRM	(IRQ_USER+16)
+#define IRQ_AMIGA_CIAA_SP	(IRQ_USER+17)
+#define IRQ_AMIGA_CIAA_FLG	(IRQ_USER+18)
+#define IRQ_AMIGA_CIAB		(IRQ_USER+19)
+#define IRQ_AMIGA_CIAB_TA	(IRQ_USER+19)
+#define IRQ_AMIGA_CIAB_TB	(IRQ_USER+20)
+#define IRQ_AMIGA_CIAB_ALRM	(IRQ_USER+21)
+#define IRQ_AMIGA_CIAB_SP	(IRQ_USER+22)
+#define IRQ_AMIGA_CIAB_FLG	(IRQ_USER+23)
 
-/* auto-vector interrupts */
-#define IRQ_AMIGA_AUTO      24
-#define IRQ_AMIGA_AUTO_0    24 /* This is just a dummy */
-#define IRQ_AMIGA_AUTO_1    25
-#define IRQ_AMIGA_AUTO_2    26
-#define IRQ_AMIGA_AUTO_3    27
-#define IRQ_AMIGA_AUTO_4    28
-#define IRQ_AMIGA_AUTO_5    29
-#define IRQ_AMIGA_AUTO_6    30
-#define IRQ_AMIGA_AUTO_7    31
-
-#define IRQ_FLOPPY	    IRQ_AMIGA_DSKBLK
 
 /* INTREQR masks */
-#define IRQ1_MASK   0x0007	/* INTREQR mask for IRQ 1 */
-#define IRQ2_MASK   0x0008	/* INTREQR mask for IRQ 2 */
-#define IRQ3_MASK   0x0070	/* INTREQR mask for IRQ 3 */
-#define IRQ4_MASK   0x0780	/* INTREQR mask for IRQ 4 */
-#define IRQ5_MASK   0x1800	/* INTREQR mask for IRQ 5 */
-#define IRQ6_MASK   0x2000	/* INTREQR mask for IRQ 6 */
-#define IRQ7_MASK   0x4000	/* INTREQR mask for IRQ 7 */
-
 #define IF_SETCLR   0x8000      /* set/clr bit */
 #define IF_INTEN    0x4000	/* master interrupt bit in INT* registers */
 #define IF_EXTER    0x2000	/* external level 6 and CIA B interrupt */
@@ -106,9 +88,6 @@
 #define IF_DSKBLK   0x0002	/* diskblock DMA finished */
 #define IF_TBE	    0x0001	/* serial transmit buffer empty interrupt */
 
-extern void amiga_do_irq(int irq, struct pt_regs *fp);
-extern void amiga_do_irq_list(int irq, struct pt_regs *fp);
-
 /* CIA interrupt control register bits */
 
 #define CIA_ICR_TA	0x01
@@ -125,6 +104,7 @@
 
 extern struct ciabase ciaa_base, ciab_base;
 
+extern void cia_init_IRQ(struct ciabase *base);
 extern unsigned char cia_set_irq(struct ciabase *base, unsigned char mask);
 extern unsigned char cia_able_irq(struct ciabase *base, unsigned char mask);
 
diff --git a/include/asm-m68k/apollohw.h b/include/asm-m68k/apollohw.h
index 4304e1c..a1373b9 100644
--- a/include/asm-m68k/apollohw.h
+++ b/include/asm-m68k/apollohw.h
@@ -3,6 +3,8 @@
 #ifndef _ASMm68k_APOLLOHW_H_
 #define _ASMm68k_APOLLOHW_H_
 
+#include <linux/types.h>
+
 /*
    apollo models
 */
@@ -101,4 +103,6 @@
 
 #define isaIO2mem(x) (((((x) & 0x3f8)  << 7) | (((x) & 0xfc00) >> 6) | ((x) & 0x7)) + 0x40000 + IO_BASE)
 
+#define IRQ_APOLLO	IRQ_USER
+
 #endif
diff --git a/include/asm-m68k/atari_stdma.h b/include/asm-m68k/atari_stdma.h
index 64f9288..b4eadf8 100644
--- a/include/asm-m68k/atari_stdma.h
+++ b/include/asm-m68k/atari_stdma.h
@@ -3,7 +3,7 @@
 #define _atari_stdma_h
 
 
-#include <asm/irq.h>
+#include <linux/interrupt.h>
 
 
 /***************************** Prototypes *****************************/
diff --git a/include/asm-m68k/atariints.h b/include/asm-m68k/atariints.h
index 42952c8..0ed454f 100644
--- a/include/asm-m68k/atariints.h
+++ b/include/asm-m68k/atariints.h
@@ -45,17 +45,6 @@
 #define IRQ_TYPE_FAST     1
 #define IRQ_TYPE_PRIO     2
 
-#define	IRQ_SPURIOUS      (0)
-
-/* auto-vector interrupts */
-#define IRQ_AUTO_1        (1)
-#define IRQ_AUTO_2        (2)
-#define IRQ_AUTO_3        (3)
-#define IRQ_AUTO_4        (4)
-#define IRQ_AUTO_5        (5)
-#define IRQ_AUTO_6        (6)
-#define IRQ_AUTO_7        (7)
-
 /* ST-MFP interrupts */
 #define IRQ_MFP_BUSY      (8)
 #define IRQ_MFP_DCD       (9)
diff --git a/include/asm-m68k/atomic.h b/include/asm-m68k/atomic.h
index 732d696..d5eed64 100644
--- a/include/asm-m68k/atomic.h
+++ b/include/asm-m68k/atomic.h
@@ -1,7 +1,6 @@
 #ifndef __ARCH_M68K_ATOMIC__
 #define __ARCH_M68K_ATOMIC__
 
-#include <linux/config.h>
 
 #include <asm/system.h>	/* local_irq_XXX() */
 
diff --git a/include/asm-m68k/bug.h b/include/asm-m68k/bug.h
index 072ce27..7b60776c 100644
--- a/include/asm-m68k/bug.h
+++ b/include/asm-m68k/bug.h
@@ -1,7 +1,6 @@
 #ifndef _M68K_BUG_H
 #define _M68K_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 #ifdef CONFIG_DEBUG_BUGVERBOSE
diff --git a/include/asm-m68k/bvme6000hw.h b/include/asm-m68k/bvme6000hw.h
index 28a859b..f40d2f8 100644
--- a/include/asm-m68k/bvme6000hw.h
+++ b/include/asm-m68k/bvme6000hw.h
@@ -109,23 +109,23 @@
 
 #define BVME_IRQ_TYPE_PRIO	0
 
-#define BVME_IRQ_PRN		0x54
-#define BVME_IRQ_I596		0x1a
-#define BVME_IRQ_SCSI		0x1b
-#define BVME_IRQ_TIMER		0x59
-#define BVME_IRQ_RTC		0x1e
-#define BVME_IRQ_ABORT		0x1f
+#define BVME_IRQ_PRN		(IRQ_USER+20)
+#define BVME_IRQ_TIMER		(IRQ_USER+25)
+#define BVME_IRQ_I596		IRQ_AUTO_2
+#define BVME_IRQ_SCSI		IRQ_AUTO_3
+#define BVME_IRQ_RTC		IRQ_AUTO_6
+#define BVME_IRQ_ABORT		IRQ_AUTO_7
 
 /* SCC interrupts */
-#define BVME_IRQ_SCC_BASE		0x40
-#define BVME_IRQ_SCCB_TX		0x40
-#define BVME_IRQ_SCCB_STAT		0x42
-#define BVME_IRQ_SCCB_RX		0x44
-#define BVME_IRQ_SCCB_SPCOND		0x46
-#define BVME_IRQ_SCCA_TX		0x48
-#define BVME_IRQ_SCCA_STAT		0x4a
-#define BVME_IRQ_SCCA_RX		0x4c
-#define BVME_IRQ_SCCA_SPCOND		0x4e
+#define BVME_IRQ_SCC_BASE		IRQ_USER
+#define BVME_IRQ_SCCB_TX		IRQ_USER
+#define BVME_IRQ_SCCB_STAT		(IRQ_USER+2)
+#define BVME_IRQ_SCCB_RX		(IRQ_USER+4)
+#define BVME_IRQ_SCCB_SPCOND		(IRQ_USER+6)
+#define BVME_IRQ_SCCA_TX		(IRQ_USER+8)
+#define BVME_IRQ_SCCA_STAT		(IRQ_USER+10)
+#define BVME_IRQ_SCCA_RX		(IRQ_USER+12)
+#define BVME_IRQ_SCCA_SPCOND		(IRQ_USER+14)
 
 /* Address control registers */
 
diff --git a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
index 8aba971..24d3ff4 100644
--- a/include/asm-m68k/cacheflush.h
+++ b/include/asm-m68k/cacheflush.h
@@ -3,26 +3,30 @@
 
 #include <linux/mm.h>
 
+/* cache code */
+#define FLUSH_I_AND_D	(0x00000808)
+#define FLUSH_I		(0x00000008)
+
 /*
  * Cache handling functions
  */
 
-#define flush_icache()						\
-({								\
-	if (CPU_IS_040_OR_060)					\
-		__asm__ __volatile__("nop\n\t"			\
-				     ".chip 68040\n\t"		\
-				     "cinva %%ic\n\t"		\
-				     ".chip 68k" : );		\
-	else {							\
-		unsigned long _tmp;				\
-		__asm__ __volatile__("movec %%cacr,%0\n\t"	\
-				     "orw %1,%0\n\t"		\
-				     "movec %0,%%cacr"		\
-				     : "=&d" (_tmp)		\
-				     : "id" (FLUSH_I));	\
-	}							\
-})
+static inline void flush_icache(void)
+{
+	if (CPU_IS_040_OR_060)
+		asm volatile (	"nop\n"
+			"	.chip	68040\n"
+			"	cpusha	%bc\n"
+			"	.chip	68k");
+	else {
+		unsigned long tmp;
+		asm volatile (	"movec	%%cacr,%0\n"
+			"	or.w	%1,%0\n"
+			"	movec	%0,%%cacr"
+			: "=&d" (tmp)
+			: "id" (FLUSH_I));
+	}
+}
 
 /*
  * invalidate the cache for the specified memory range.
@@ -43,10 +47,6 @@
  */
 extern void cache_push_v(unsigned long vaddr, int len);
 
-/* cache code */
-#define FLUSH_I_AND_D	(0x00000808)
-#define FLUSH_I		(0x00000008)
-
 /* This is needed whenever the virtual mapping of the current
    process changes.  */
 #define __flush_cache_all()					\
diff --git a/include/asm-m68k/dma-mapping.h b/include/asm-m68k/dma-mapping.h
index b1920c7..cebbb03 100644
--- a/include/asm-m68k/dma-mapping.h
+++ b/include/asm-m68k/dma-mapping.h
@@ -1,12 +1,91 @@
 #ifndef _M68K_DMA_MAPPING_H
 #define _M68K_DMA_MAPPING_H
 
-#include <linux/config.h>
+#include <asm/cache.h>
 
-#ifdef CONFIG_PCI
-#include <asm-generic/dma-mapping.h>
-#else
-#include <asm-generic/dma-mapping-broken.h>
-#endif
+struct scatterlist;
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+	return 1;
+}
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+	return 0;
+}
+
+static inline int dma_get_cache_alignment(void)
+{
+	return 1 << L1_CACHE_SHIFT;
+}
+
+static inline int dma_is_consistent(dma_addr_t dma_addr)
+{
+	return 0;
+}
+
+extern void *dma_alloc_coherent(struct device *, size_t,
+				dma_addr_t *, int);
+extern void dma_free_coherent(struct device *, size_t,
+			      void *, dma_addr_t);
+
+static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
+					  dma_addr_t *handle, int flag)
+{
+	return dma_alloc_coherent(dev, size, handle, flag);
+}
+static inline void dma_free_noncoherent(struct device *dev, size_t size,
+					void *addr, dma_addr_t handle)
+{
+	dma_free_coherent(dev, size, addr, handle);
+}
+static inline void dma_cache_sync(void *vaddr, size_t size,
+				  enum dma_data_direction dir)
+{
+	/* we use coherent allocation, so not much to do here. */
+}
+
+extern dma_addr_t dma_map_single(struct device *, void *, size_t,
+				 enum dma_data_direction);
+static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
+				    size_t size, enum dma_data_direction dir)
+{
+}
+
+extern dma_addr_t dma_map_page(struct device *, struct page *,
+			       unsigned long, size_t size,
+			       enum dma_data_direction);
+static inline void dma_unmap_page(struct device *dev, dma_addr_t address,
+				  size_t size, enum dma_data_direction dir)
+{
+}
+
+extern int dma_map_sg(struct device *, struct scatterlist *, int,
+		      enum dma_data_direction);
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+				int nhwentries, enum dma_data_direction dir)
+{
+}
+
+extern void dma_sync_single_for_device(struct device *, dma_addr_t, size_t,
+				       enum dma_data_direction);
+extern void dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
+				   enum dma_data_direction);
+
+static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle,
+					   size_t size, enum dma_data_direction dir)
+{
+}
+
+static inline void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+				       int nents, enum dma_data_direction dir)
+{
+}
+
+static inline int dma_mapping_error(dma_addr_t handle)
+{
+	return 0;
+}
 
 #endif  /* _M68K_DMA_MAPPING_H */
diff --git a/include/asm-m68k/dma.h b/include/asm-m68k/dma.h
index d5266a8..d0c9e61 100644
--- a/include/asm-m68k/dma.h
+++ b/include/asm-m68k/dma.h
@@ -1,7 +1,6 @@
 #ifndef _M68K_DMA_H
 #define _M68K_DMA_H 1
 
-#include <linux/config.h>
 
 /* it's useless on the m68k, but unfortunately needed by the new
    bootmem allocator (but this should do it for this) */
diff --git a/include/asm-m68k/dvma.h b/include/asm-m68k/dvma.h
index 5978f87..e1112de 100644
--- a/include/asm-m68k/dvma.h
+++ b/include/asm-m68k/dvma.h
@@ -9,7 +9,6 @@
 #ifndef __M68K_DVMA_H
 #define __M68K_DVMA_H
 
-#include <linux/config.h>
 
 #define DVMA_PAGE_SHIFT	13
 #define DVMA_PAGE_SIZE	(1UL << DVMA_PAGE_SHIFT)
diff --git a/include/asm-m68k/elf.h b/include/asm-m68k/elf.h
index 38bf834..eb63b85 100644
--- a/include/asm-m68k/elf.h
+++ b/include/asm-m68k/elf.h
@@ -5,7 +5,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff --git a/include/asm-m68k/entry.h b/include/asm-m68k/entry.h
index 0396495..f8f6b18 100644
--- a/include/asm-m68k/entry.h
+++ b/include/asm-m68k/entry.h
@@ -1,7 +1,6 @@
 #ifndef __M68K_ENTRY_H
 #define __M68K_ENTRY_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
diff --git a/include/asm-m68k/fpu.h b/include/asm-m68k/fpu.h
index 3bcf850..59701d7 100644
--- a/include/asm-m68k/fpu.h
+++ b/include/asm-m68k/fpu.h
@@ -1,7 +1,6 @@
 #ifndef __M68K_FPU_H
 #define __M68K_FPU_H
 
-#include <linux/config.h>
 
 /*
  * MAX floating point unit state size (FSAVE/FRESTORE)
diff --git a/include/asm-m68k/hardirq.h b/include/asm-m68k/hardirq.h
index 5e1c5826..394ee94 100644
--- a/include/asm-m68k/hardirq.h
+++ b/include/asm-m68k/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __M68K_HARDIRQ_H
 #define __M68K_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cache.h>
 
diff --git a/include/asm-m68k/ide.h b/include/asm-m68k/ide.h
index 36118fd..365f76f 100644
--- a/include/asm-m68k/ide.h
+++ b/include/asm-m68k/ide.h
@@ -31,7 +31,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #include <asm/setup.h>
 #include <asm/io.h>
diff --git a/include/asm-m68k/io.h b/include/asm-m68k/io.h
index dcfaa35..5e0fcf4 100644
--- a/include/asm-m68k/io.h
+++ b/include/asm-m68k/io.h
@@ -23,7 +23,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/raw_io.h>
 #include <asm/virtconvert.h>
diff --git a/include/asm-m68k/irq.h b/include/asm-m68k/irq.h
index 9ac047c..f4ae7d8 100644
--- a/include/asm-m68k/irq.h
+++ b/include/asm-m68k/irq.h
@@ -1,14 +1,9 @@
 #ifndef _M68K_IRQ_H_
 #define _M68K_IRQ_H_
 
-#include <linux/config.h>
-#include <linux/interrupt.h>
-
-/*
- * # of m68k interrupts
- */
-
-#define SYS_IRQS 8
+#include <linux/linkage.h>
+#include <linux/hardirq.h>
+#include <linux/spinlock_types.h>
 
 /*
  * This should be the same as the max(NUM_X_SOURCES) for all the
@@ -16,10 +11,20 @@
  * Currently the Atari has 72 and the Amiga 24, but if both are
  * supported in the kernel it is better to make room for 72.
  */
-#if defined(CONFIG_ATARI) || defined(CONFIG_MAC)
-#define NR_IRQS (72+SYS_IRQS)
+#if defined(CONFIG_VME) || defined(CONFIG_SUN3) || defined(CONFIG_SUN3X)
+#define NR_IRQS 200
+#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
+#define NR_IRQS 72
+#elif defined(CONFIG_Q40)
+#define NR_IRQS	43
+#elif defined(CONFIG_AMIGA)
+#define NR_IRQS	32
+#elif defined(CONFIG_APOLLO)
+#define NR_IRQS	24
+#elif defined(CONFIG_HP300)
+#define NR_IRQS	8
 #else
-#define NR_IRQS (24+SYS_IRQS)
+#error unknown nr of irqs
 #endif
 
 /*
@@ -41,53 +46,25 @@
  * that routine requires service.
  */
 
-#define IRQ1		(1)	/* level 1 interrupt */
-#define IRQ2		(2)	/* level 2 interrupt */
-#define IRQ3		(3)	/* level 3 interrupt */
-#define IRQ4		(4)	/* level 4 interrupt */
-#define IRQ5		(5)	/* level 5 interrupt */
-#define IRQ6		(6)	/* level 6 interrupt */
-#define IRQ7		(7)	/* level 7 interrupt (non-maskable) */
+#define IRQ_SPURIOUS	0
 
-/*
- * "Generic" interrupt sources
- */
+#define IRQ_AUTO_1	1	/* level 1 interrupt */
+#define IRQ_AUTO_2	2	/* level 2 interrupt */
+#define IRQ_AUTO_3	3	/* level 3 interrupt */
+#define IRQ_AUTO_4	4	/* level 4 interrupt */
+#define IRQ_AUTO_5	5	/* level 5 interrupt */
+#define IRQ_AUTO_6	6	/* level 6 interrupt */
+#define IRQ_AUTO_7	7	/* level 7 interrupt (non-maskable) */
 
-#define IRQ_SCHED_TIMER	(8)    /* interrupt source for scheduling timer */
+#define IRQ_USER	8
 
-static __inline__ int irq_canonicalize(int irq)
-{
-	return irq;
-}
-
-/*
- * Machine specific interrupt sources.
- *
- * Adding an interrupt service routine for a source with this bit
- * set indicates a special machine specific interrupt source.
- * The machine specific files define these sources.
- *
- * The IRQ_MACHSPEC bit is now gone - the only thing it did was to
- * introduce unnecessary overhead.
- *
- * All interrupt handling is actually machine specific so it is better
- * to use function pointers, as used by the Sparc port, and select the
- * interrupt handling functions when initializing the kernel. This way
- * we save some unnecessary overhead at run-time.
- *                                                      01/11/97 - Jes
- */
-
-extern void (*enable_irq)(unsigned int);
-extern void (*disable_irq)(unsigned int);
+extern unsigned int irq_canonicalize(unsigned int irq);
+extern void enable_irq(unsigned int);
+extern void disable_irq(unsigned int);
 #define disable_irq_nosync	disable_irq
 
 struct pt_regs;
 
-extern int cpu_request_irq(unsigned int,
-			   irqreturn_t (*)(int, void *, struct pt_regs *),
-			   unsigned long, const char *, void *);
-extern void cpu_free_irq(unsigned int, void *);
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - SA_INTERRUPT and SA_SHIRQ
@@ -106,33 +83,45 @@
  * interrupt source (if it supports chaining).
  */
 typedef struct irq_node {
-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
-	unsigned long	flags;
+	int		(*handler)(int, void *, struct pt_regs *);
 	void		*dev_id;
-	const char	*devname;
 	struct irq_node *next;
+	unsigned long	flags;
+	const char	*devname;
 } irq_node_t;
 
 /*
  * This structure has only 4 elements for speed reasons
  */
 typedef struct irq_handler {
-	irqreturn_t	(*handler)(int, void *, struct pt_regs *);
+	int		(*handler)(int, void *, struct pt_regs *);
 	unsigned long	flags;
 	void		*dev_id;
 	const char	*devname;
 } irq_handler_t;
 
-/* count of spurious interrupts */
-extern volatile unsigned int num_spurious;
+struct irq_controller {
+	const char *name;
+	spinlock_t lock;
+	int (*startup)(unsigned int irq);
+	void (*shutdown)(unsigned int irq);
+	void (*enable)(unsigned int irq);
+	void (*disable)(unsigned int irq);
+};
+
+extern int m68k_irq_startup(unsigned int);
+extern void m68k_irq_shutdown(unsigned int);
 
 /*
  * This function returns a new irq_node_t
  */
 extern irq_node_t *new_irq_node(void);
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
+				      void (*handler)(unsigned int, struct pt_regs *));
+extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
+
+asmlinkage void m68k_handle_int(unsigned int, struct pt_regs *);
 
 #endif /* _M68K_IRQ_H_ */
diff --git a/include/asm-m68k/mac_oss.h b/include/asm-m68k/mac_oss.h
index 7644a63..7221f72 100644
--- a/include/asm-m68k/mac_oss.h
+++ b/include/asm-m68k/mac_oss.h
@@ -69,12 +69,12 @@
 
 #define OSS_IRQLEV_DISABLED	0
 #define OSS_IRQLEV_IOPISM	1	/* ADB? */
-#define OSS_IRQLEV_SCSI		2
-#define OSS_IRQLEV_NUBUS	3	/* keep this on its own level */
-#define OSS_IRQLEV_IOPSCC	4	/* matches VIA alternate mapping */
-#define OSS_IRQLEV_SOUND	5	/* matches VIA alternate mapping */
+#define OSS_IRQLEV_SCSI		IRQ_AUTO_2
+#define OSS_IRQLEV_NUBUS	IRQ_AUTO_3	/* keep this on its own level */
+#define OSS_IRQLEV_IOPSCC	IRQ_AUTO_4	/* matches VIA alternate mapping */
+#define OSS_IRQLEV_SOUND	IRQ_AUTO_5	/* matches VIA alternate mapping */
 #define OSS_IRQLEV_60HZ		6	/* matches VIA alternate mapping */
-#define OSS_IRQLEV_VIA1		6	/* matches VIA alternate mapping */
+#define OSS_IRQLEV_VIA1		IRQ_AUTO_6	/* matches VIA alternate mapping */
 #define OSS_IRQLEV_PARITY	7	/* matches VIA alternate mapping */
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-m68k/machdep.h b/include/asm-m68k/machdep.h
index 7d3fee3..df898f2 100644
--- a/include/asm-m68k/machdep.h
+++ b/include/asm-m68k/machdep.h
@@ -13,14 +13,8 @@
 extern void (*mach_sched_init) (irqreturn_t (*handler)(int, void *, struct pt_regs *));
 /* machine dependent irq functions */
 extern void (*mach_init_IRQ) (void);
-extern irqreturn_t (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
-extern int (*mach_request_irq) (unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                                unsigned long flags, const char *devname, void *dev_id);
-extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
 extern void (*mach_get_model) (char *model);
 extern int (*mach_get_hardware_list) (char *buffer);
-extern int (*mach_get_irq_list) (struct seq_file *p, void *v);
-extern irqreturn_t (*mach_process_int) (int irq, struct pt_regs *fp);
 /* machine dependent timer functions */
 extern unsigned long (*mach_gettimeoffset)(void);
 extern int (*mach_hwclk)(int, struct rtc_time*);
diff --git a/include/asm-m68k/macintosh.h b/include/asm-m68k/macintosh.h
index 6fc3d19..27d11da 100644
--- a/include/asm-m68k/macintosh.h
+++ b/include/asm-m68k/macintosh.h
@@ -11,17 +11,7 @@
 extern void mac_reset(void);
 extern void mac_poweroff(void);
 extern void mac_init_IRQ(void);
-extern int mac_request_irq (unsigned int, irqreturn_t (*)(int, void *,
-				struct pt_regs *),
-				unsigned long, const char *, void *);
-extern void mac_free_irq(unsigned int, void *);
-extern void mac_enable_irq(unsigned int);
-extern void mac_disable_irq(unsigned int);
 extern int mac_irq_pending(unsigned int);
-extern int show_mac_interrupts(struct seq_file *, void *);
-#if 0
-extern void mac_default_handler(int irq);
-#endif
 extern void mac_identify(void);
 extern void mac_report_hardware(void);
 extern void mac_debugging_penguin(int);
diff --git a/include/asm-m68k/macints.h b/include/asm-m68k/macints.h
index fd8c3a9..679c48a 100644
--- a/include/asm-m68k/macints.h
+++ b/include/asm-m68k/macints.h
@@ -59,17 +59,6 @@
 #define IRQ_SRC(irq)	(irq >> 3)
 #define	IRQ_IDX(irq)	(irq & 7)
 
-#define	IRQ_SPURIOUS      (0)
-
-/* auto-vector interrupts */
-#define IRQ_AUTO_1        (1)
-#define IRQ_AUTO_2        (2)
-#define IRQ_AUTO_3        (3)
-#define IRQ_AUTO_4        (4)
-#define IRQ_AUTO_5        (5)
-#define IRQ_AUTO_6        (6)
-#define IRQ_AUTO_7        (7)
-
 /* VIA1 interrupts */
 #define IRQ_VIA1_0	  (8)		/* one second int. */
 #define IRQ_VIA1_1        (9)		/* VBlank int. */
@@ -163,7 +152,4 @@
 #define INT_CLK   24576	    /* CLK while int_clk =2.456MHz and divide = 100 */
 #define INT_TICKS 246	    /* to make sched_time = 99.902... HZ */
 
-extern irq_node_t *mac_irq_list[NUM_MAC_SOURCES];
-extern void mac_do_irq_list(int irq, struct pt_regs *);
-
 #endif /* asm/macints.h */
diff --git a/include/asm-m68k/mc146818rtc.h b/include/asm-m68k/mc146818rtc.h
index 1144209..11fe12d 100644
--- a/include/asm-m68k/mc146818rtc.h
+++ b/include/asm-m68k/mc146818rtc.h
@@ -4,7 +4,6 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ATARI
 /* RTC in Atari machines */
diff --git a/include/asm-m68k/mmu_context.h b/include/asm-m68k/mmu_context.h
index 661191d..231d11b 100644
--- a/include/asm-m68k/mmu_context.h
+++ b/include/asm-m68k/mmu_context.h
@@ -1,7 +1,6 @@
 #ifndef __M68K_MMU_CONTEXT_H
 #define __M68K_MMU_CONTEXT_H
 
-#include <linux/config.h>
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 {
diff --git a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
index 1628723..1ccc733 100644
--- a/include/asm-m68k/motorola_pgtable.h
+++ b/include/asm-m68k/motorola_pgtable.h
@@ -1,7 +1,6 @@
 #ifndef _MOTOROLA_PGTABLE_H
 #define _MOTOROLA_PGTABLE_H
 
-#include <linux/config.h>
 
 /*
  * Definitions for MMU descriptors
diff --git a/include/asm-m68k/mvme147hw.h b/include/asm-m68k/mvme147hw.h
index f245139..b810431 100644
--- a/include/asm-m68k/mvme147hw.h
+++ b/include/asm-m68k/mvme147hw.h
@@ -1,6 +1,8 @@
 #ifndef _MVME147HW_H_
 #define _MVME147HW_H_
 
+#include <asm/irq.h>
+
 typedef struct {
 	unsigned char
 		ctrl,
@@ -72,39 +74,39 @@
 #define PCC_LEVEL_SCSI_PORT	0x04
 #define PCC_LEVEL_SCSI_DMA	0x04
 
-#define PCC_IRQ_AC_FAIL		0x40
-#define PCC_IRQ_BERR		0x41
-#define PCC_IRQ_ABORT		0x42
-/* #define PCC_IRQ_SERIAL	0x43 */
-#define PCC_IRQ_PRINTER		0x47
-#define PCC_IRQ_TIMER1		0x48
-#define PCC_IRQ_TIMER2		0x49
-#define PCC_IRQ_SOFTWARE1	0x4a
-#define PCC_IRQ_SOFTWARE2	0x4b
+#define PCC_IRQ_AC_FAIL		(IRQ_USER+0)
+#define PCC_IRQ_BERR		(IRQ_USER+1)
+#define PCC_IRQ_ABORT		(IRQ_USER+2)
+/* #define PCC_IRQ_SERIAL	(IRQ_USER+3) */
+#define PCC_IRQ_PRINTER		(IRQ_USER+7)
+#define PCC_IRQ_TIMER1		(IRQ_USER+8)
+#define PCC_IRQ_TIMER2		(IRQ_USER+9)
+#define PCC_IRQ_SOFTWARE1	(IRQ_USER+10)
+#define PCC_IRQ_SOFTWARE2	(IRQ_USER+11)
 
 
 #define M147_SCC_A_ADDR		0xfffe3002
 #define M147_SCC_B_ADDR		0xfffe3000
 #define M147_SCC_PCLK		5000000
 
-#define MVME147_IRQ_SCSI_PORT	0x45
-#define MVME147_IRQ_SCSI_DMA	0x46
+#define MVME147_IRQ_SCSI_PORT	(IRQ_USER+0x45)
+#define MVME147_IRQ_SCSI_DMA	(IRQ_USER+0x46)
 
 /* SCC interrupts, for MVME147 */
 
 #define MVME147_IRQ_TYPE_PRIO	0
-#define MVME147_IRQ_SCC_BASE		0x60
-#define MVME147_IRQ_SCCB_TX		0x60
-#define MVME147_IRQ_SCCB_STAT		0x62
-#define MVME147_IRQ_SCCB_RX		0x64
-#define MVME147_IRQ_SCCB_SPCOND		0x66
-#define MVME147_IRQ_SCCA_TX		0x68
-#define MVME147_IRQ_SCCA_STAT		0x6a
-#define MVME147_IRQ_SCCA_RX		0x6c
-#define MVME147_IRQ_SCCA_SPCOND		0x6e
+#define MVME147_IRQ_SCC_BASE		(IRQ_USER+32)
+#define MVME147_IRQ_SCCB_TX		(IRQ_USER+32)
+#define MVME147_IRQ_SCCB_STAT		(IRQ_USER+34)
+#define MVME147_IRQ_SCCB_RX		(IRQ_USER+36)
+#define MVME147_IRQ_SCCB_SPCOND		(IRQ_USER+38)
+#define MVME147_IRQ_SCCA_TX		(IRQ_USER+40)
+#define MVME147_IRQ_SCCA_STAT		(IRQ_USER+42)
+#define MVME147_IRQ_SCCA_RX		(IRQ_USER+44)
+#define MVME147_IRQ_SCCA_SPCOND		(IRQ_USER+46)
 
 #define MVME147_LANCE_BASE	0xfffe1800
-#define MVME147_LANCE_IRQ	0x44
+#define MVME147_LANCE_IRQ	(IRQ_USER+4)
 
 #define ETHERNET_ADDRESS 0xfffe0778
 
diff --git a/include/asm-m68k/mvme16xhw.h b/include/asm-m68k/mvme16xhw.h
index 5d07231..6117f56 100644
--- a/include/asm-m68k/mvme16xhw.h
+++ b/include/asm-m68k/mvme16xhw.h
@@ -66,28 +66,28 @@
 
 #define MVME162_IRQ_TYPE_PRIO	0
 
-#define MVME167_IRQ_PRN		0x54
-#define MVME16x_IRQ_I596	0x57
-#define MVME16x_IRQ_SCSI	0x55
-#define MVME16x_IRQ_FLY		0x7f
-#define MVME167_IRQ_SER_ERR	0x5c
-#define MVME167_IRQ_SER_MODEM	0x5d
-#define MVME167_IRQ_SER_TX	0x5e
-#define MVME167_IRQ_SER_RX	0x5f
-#define MVME16x_IRQ_TIMER	0x59
-#define MVME167_IRQ_ABORT	0x6e
-#define MVME162_IRQ_ABORT	0x5e
+#define MVME167_IRQ_PRN		(IRQ_USER+20)
+#define MVME16x_IRQ_I596	(IRQ_USER+23)
+#define MVME16x_IRQ_SCSI	(IRQ_USER+21)
+#define MVME16x_IRQ_FLY		(IRQ_USER+63)
+#define MVME167_IRQ_SER_ERR	(IRQ_USER+28)
+#define MVME167_IRQ_SER_MODEM	(IRQ_USER+29)
+#define MVME167_IRQ_SER_TX	(IRQ_USER+30)
+#define MVME167_IRQ_SER_RX	(IRQ_USER+31)
+#define MVME16x_IRQ_TIMER	(IRQ_USER+25)
+#define MVME167_IRQ_ABORT	(IRQ_USER+46)
+#define MVME162_IRQ_ABORT	(IRQ_USER+30)
 
 /* SCC interrupts, for MVME162 */
-#define MVME162_IRQ_SCC_BASE		0x40
-#define MVME162_IRQ_SCCB_TX		0x40
-#define MVME162_IRQ_SCCB_STAT		0x42
-#define MVME162_IRQ_SCCB_RX		0x44
-#define MVME162_IRQ_SCCB_SPCOND		0x46
-#define MVME162_IRQ_SCCA_TX		0x48
-#define MVME162_IRQ_SCCA_STAT		0x4a
-#define MVME162_IRQ_SCCA_RX		0x4c
-#define MVME162_IRQ_SCCA_SPCOND		0x4e
+#define MVME162_IRQ_SCC_BASE		(IRQ_USER+0)
+#define MVME162_IRQ_SCCB_TX		(IRQ_USER+0)
+#define MVME162_IRQ_SCCB_STAT		(IRQ_USER+2)
+#define MVME162_IRQ_SCCB_RX		(IRQ_USER+4)
+#define MVME162_IRQ_SCCB_SPCOND		(IRQ_USER+6)
+#define MVME162_IRQ_SCCA_TX		(IRQ_USER+8)
+#define MVME162_IRQ_SCCA_STAT		(IRQ_USER+10)
+#define MVME162_IRQ_SCCA_RX		(IRQ_USER+12)
+#define MVME162_IRQ_SCCA_SPCOND		(IRQ_USER+14)
 
 /* MVME162 version register */
 
diff --git a/include/asm-m68k/openprom.h b/include/asm-m68k/openprom.h
index efbfb0b..869ab91 100644
--- a/include/asm-m68k/openprom.h
+++ b/include/asm-m68k/openprom.h
@@ -8,7 +8,6 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 
 /* Empirical constants... */
 #ifdef CONFIG_SUN3
diff --git a/include/asm-m68k/page.h b/include/asm-m68k/page.h
index f206dfb..db017f8 100644
--- a/include/asm-m68k/page.h
+++ b/include/asm-m68k/page.h
@@ -1,7 +1,6 @@
 #ifndef _M68K_PAGE_H
 #define _M68K_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #ifndef CONFIG_SUN3
diff --git a/include/asm-m68k/page_offset.h b/include/asm-m68k/page_offset.h
index 86d3c28..1cbdb7f 100644
--- a/include/asm-m68k/page_offset.h
+++ b/include/asm-m68k/page_offset.h
@@ -1,4 +1,3 @@
-#include <linux/config.h>
 
 /* This handles the memory map.. */
 #ifndef CONFIG_SUN3
diff --git a/include/asm-m68k/pgalloc.h b/include/asm-m68k/pgalloc.h
index b468b79..a9cfb4b 100644
--- a/include/asm-m68k/pgalloc.h
+++ b/include/asm-m68k/pgalloc.h
@@ -2,7 +2,6 @@
 #ifndef M68K_PGALLOC_H
 #define M68K_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <asm/setup.h>
diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
index add129e..f3aa053 100644
--- a/include/asm-m68k/pgtable.h
+++ b/include/asm-m68k/pgtable.h
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/setup.h>
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h
index 7982285..8455f77 100644
--- a/include/asm-m68k/processor.h
+++ b/include/asm-m68k/processor.h
@@ -13,7 +13,6 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#include <linux/config.h>
 #include <linux/thread_info.h>
 #include <asm/segment.h>
 #include <asm/fpu.h>
@@ -72,10 +71,10 @@
 };
 
 #define INIT_THREAD  {							\
-	ksp:	sizeof(init_stack) + (unsigned long) init_stack,	\
-	sr:	PS_S,							\
-	fs:	__KERNEL_DS,						\
-	info:	INIT_THREAD_INFO(init_task)				\
+	.ksp	= sizeof(init_stack) + (unsigned long) init_stack,	\
+	.sr	= PS_S,							\
+	.fs	= __KERNEL_DS,						\
+	.info	= INIT_THREAD_INFO(init_task),				\
 }
 
 /*
diff --git a/include/asm-m68k/scatterlist.h b/include/asm-m68k/scatterlist.h
index d7c9b5c..8e61226 100644
--- a/include/asm-m68k/scatterlist.h
+++ b/include/asm-m68k/scatterlist.h
@@ -2,18 +2,17 @@
 #define _M68K_SCATTERLIST_H
 
 struct scatterlist {
-	/* These two are only valid if ADDRESS member of this
-	 * struct is NULL.
-	 */
 	struct page *page;
 	unsigned int offset;
-
 	unsigned int length;
 
-	__u32 dvma_address; /* A place to hang host-specific addresses at. */
+	__u32 dma_address;	/* A place to hang host-specific addresses at. */
 };
 
 /* This is bogus and should go away. */
 #define ISA_DMA_THRESHOLD (0x00ffffff)
 
+#define sg_dma_address(sg)	((sg)->dma_address)
+#define sg_dma_len(sg)		((sg)->length)
+
 #endif /* !(_M68K_SCATTERLIST_H) */
diff --git a/include/asm-m68k/semaphore-helper.h b/include/asm-m68k/semaphore-helper.h
index 1516a642..eef30ba 100644
--- a/include/asm-m68k/semaphore-helper.h
+++ b/include/asm-m68k/semaphore-helper.h
@@ -9,7 +9,6 @@
  * m68k version by Andreas Schwab
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 
 /*
diff --git a/include/asm-m68k/serial.h b/include/asm-m68k/serial.h
index 3fe29f8..2b90d6e 100644
--- a/include/asm-m68k/serial.h
+++ b/include/asm-m68k/serial.h
@@ -6,7 +6,6 @@
  *
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff --git a/include/asm-m68k/setup.h b/include/asm-m68k/setup.h
index a89aa84..7facc9a 100644
--- a/include/asm-m68k/setup.h
+++ b/include/asm-m68k/setup.h
@@ -23,7 +23,6 @@
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
-#include <linux/config.h>
 
 
     /*
diff --git a/include/asm-m68k/shm.h b/include/asm-m68k/shm.h
index 3fa2f36..fa56ec8 100644
--- a/include/asm-m68k/shm.h
+++ b/include/asm-m68k/shm.h
@@ -1,7 +1,6 @@
 #ifndef _M68K_SHM_H
 #define _M68K_SHM_H
 
-#include <linux/config.h>
 
 /* format of page table entries that correspond to shared memory pages
    currently out in swap space (see also mm/swap.c):
diff --git a/include/asm-m68k/signal.h b/include/asm-m68k/signal.h
index b7b7ea2..85037a3 100644
--- a/include/asm-m68k/signal.h
+++ b/include/asm-m68k/signal.h
@@ -156,13 +156,17 @@
 
 static inline void sigaddset(sigset_t *set, int _sig)
 {
-	__asm__("bfset %0{%1,#1}" : "=m" (*set) : "id" ((_sig - 1) ^ 31)
+	asm ("bfset %0{%1,#1}"
+		: "+od" (*set)
+		: "id" ((_sig - 1) ^ 31)
 		: "cc");
 }
 
 static inline void sigdelset(sigset_t *set, int _sig)
 {
-	__asm__("bfclr %0{%1,#1}" : "=m"(*set) : "id"((_sig - 1) ^ 31)
+	asm ("bfclr %0{%1,#1}"
+		: "+od" (*set)
+		: "id" ((_sig - 1) ^ 31)
 		: "cc");
 }
 
@@ -175,8 +179,10 @@
 static inline int __gen_sigismember(sigset_t *set, int _sig)
 {
 	int ret;
-	__asm__("bfextu %1{%2,#1},%0"
-		: "=d"(ret) : "m"(*set), "id"((_sig-1) ^ 31));
+	asm ("bfextu %1{%2,#1},%0"
+		: "=d" (ret)
+		: "od" (*set), "id" ((_sig-1) ^ 31)
+		: "cc");
 	return ret;
 }
 
@@ -187,7 +193,10 @@
 
 static inline int sigfindinword(unsigned long word)
 {
-	__asm__("bfffo %1{#0,#0},%0" : "=d"(word) : "d"(word & -word) : "cc");
+	asm ("bfffo %1{#0,#0},%0"
+		: "=d" (word)
+		: "d" (word & -word)
+		: "cc");
 	return word ^ 31;
 }
 
diff --git a/include/asm-m68k/sun3ints.h b/include/asm-m68k/sun3ints.h
index bd038fc..de91fa0 100644
--- a/include/asm-m68k/sun3ints.h
+++ b/include/asm-m68k/sun3ints.h
@@ -12,37 +12,25 @@
 #define SUN3INTS_H
 
 #include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
-#include <linux/seq_file.h>
-#include <asm/segment.h>
 #include <asm/intersil.h>
 #include <asm/oplib.h>
+#include <asm/traps.h>
 
 #define SUN3_INT_VECS 192
 
 void sun3_enable_irq(unsigned int irq);
 void sun3_disable_irq(unsigned int irq);
-int sun3_request_irq(unsigned int irq,
-                     irqreturn_t (*handler)(int, void *, struct pt_regs *),
-                     unsigned long flags, const char *devname, void *dev_id
-		    );
 extern void sun3_init_IRQ (void);
-extern irqreturn_t (*sun3_default_handler[]) (int, void *, struct pt_regs *);
-extern void sun3_free_irq (unsigned int irq, void *dev_id);
 extern void sun3_enable_interrupts (void);
 extern void sun3_disable_interrupts (void);
-extern int show_sun3_interrupts(struct seq_file *, void *);
-extern irqreturn_t sun3_process_int(int, struct pt_regs *);
 extern volatile unsigned char* sun3_intreg;
 
 /* master list of VME vectors -- don't fuck with this */
-#define SUN3_VEC_FLOPPY 0x40
-#define SUN3_VEC_VMESCSI0 0x40
-#define SUN3_VEC_VMESCSI1 0x41
-#define SUN3_VEC_CG 0xA8
+#define SUN3_VEC_FLOPPY		(IRQ_USER+0)
+#define SUN3_VEC_VMESCSI0	(IRQ_USER+0)
+#define SUN3_VEC_VMESCSI1	(IRQ_USER+1)
+#define SUN3_VEC_CG		(IRQ_USER+104)
 
 
 #endif /* SUN3INTS_H */
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index 64d3481..d6dd805 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -1,7 +1,6 @@
 #ifndef _M68K_SYSTEM_H
 #define _M68K_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
diff --git a/include/asm-m68k/tlbflush.h b/include/asm-m68k/tlbflush.h
index 8e61ccf..3167883 100644
--- a/include/asm-m68k/tlbflush.h
+++ b/include/asm-m68k/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _M68K_TLBFLUSH_H
 #define _M68K_TLBFLUSH_H
 
-#include <linux/config.h>
 
 #ifndef CONFIG_SUN3
 
diff --git a/include/asm-m68k/traps.h b/include/asm-m68k/traps.h
index 4750561..8caef25 100644
--- a/include/asm-m68k/traps.h
+++ b/include/asm-m68k/traps.h
@@ -13,8 +13,15 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+
 typedef void (*e_vector)(void);
 
+asmlinkage void auto_inthandler(void);
+asmlinkage void user_inthandler(void);
+asmlinkage void bad_inthandler(void);
+
 extern e_vector vectors[];
 
 #endif
diff --git a/include/asm-m68k/uaccess.h b/include/asm-m68k/uaccess.h
index 2ffd87b..88b1f47 100644
--- a/include/asm-m68k/uaccess.h
+++ b/include/asm-m68k/uaccess.h
@@ -4,8 +4,9 @@
 /*
  * User space memory access functions
  */
+#include <linux/compiler.h>
 #include <linux/errno.h>
-#include <linux/sched.h>
+#include <linux/types.h>
 #include <asm/segment.h>
 
 #define VERIFY_READ	0
@@ -32,858 +33,335 @@
 	unsigned long insn, fixup;
 };
 
+extern int __put_user_bad(void);
+extern int __get_user_bad(void);
+
+#define __put_user_asm(res, x, ptr, bwl, reg, err)	\
+asm volatile ("\n"					\
+	"1:	moves."#bwl"	%2,%1\n"		\
+	"2:\n"						\
+	"	.section .fixup,\"ax\"\n"		\
+	"	.even\n"				\
+	"10:	moveq.l	%3,%0\n"			\
+	"	jra 2b\n"				\
+	"	.previous\n"				\
+	"\n"						\
+	"	.section __ex_table,\"a\"\n"		\
+	"	.align	4\n"				\
+	"	.long	1b,10b\n"			\
+	"	.long	2b,10b\n"			\
+	"	.previous"				\
+	: "+d" (res), "=m" (*(ptr))			\
+	: #reg (x), "i" (err))
 
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
  */
 
-#define put_user(x, ptr)				\
-({							\
-    int __pu_err;					\
-    typeof(*(ptr)) __pu_val = (x);			\
-    __chk_user_ptr(ptr);				\
-    switch (sizeof (*(ptr))) {				\
-    case 1:						\
-	__put_user_asm(__pu_err, __pu_val, ptr, b);	\
-	break;						\
-    case 2:						\
-	__put_user_asm(__pu_err, __pu_val, ptr, w);	\
-	break;						\
-    case 4:						\
-	__put_user_asm(__pu_err, __pu_val, ptr, l);	\
-	break;						\
-    case 8:                                             \
-       __pu_err = __constant_copy_to_user(ptr, &__pu_val, 8);        \
-       break;                                           \
-    default:						\
-	__pu_err = __put_user_bad();			\
-	break;						\
-    }							\
-    __pu_err;						\
+#define __put_user(x, ptr)						\
+({									\
+	typeof(*(ptr)) __pu_val = (x);					\
+	int __pu_err = 0;						\
+	__chk_user_ptr(ptr);						\
+	switch (sizeof (*(ptr))) {					\
+	case 1:								\
+		__put_user_asm(__pu_err, __pu_val, ptr, b, d, -EFAULT);	\
+		break;							\
+	case 2:								\
+		__put_user_asm(__pu_err, __pu_val, ptr, w, d, -EFAULT);	\
+		break;							\
+	case 4:								\
+		__put_user_asm(__pu_err, __pu_val, ptr, l, r, -EFAULT);	\
+		break;							\
+	case 8:								\
+ 	    {								\
+ 		const void *__pu_ptr = (ptr);				\
+		asm volatile ("\n"					\
+			"1:	moves.l	%2,(%1)+\n"			\
+			"2:	moves.l	%R2,(%1)\n"			\
+			"3:\n"						\
+			"	.section .fixup,\"ax\"\n"		\
+			"	.even\n"				\
+			"10:	movel %3,%0\n"				\
+			"	jra 3b\n"				\
+			"	.previous\n"				\
+			"\n"						\
+			"	.section __ex_table,\"a\"\n"		\
+			"	.align 4\n"				\
+			"	.long 1b,10b\n"				\
+			"	.long 2b,10b\n"				\
+			"	.long 3b,10b\n"				\
+			"	.previous"				\
+			: "+d" (__pu_err), "+a" (__pu_ptr)		\
+			: "r" (__pu_val), "i" (-EFAULT)			\
+			: "memory");					\
+		break;							\
+	    }								\
+	default:							\
+		__pu_err = __put_user_bad();				\
+		break;							\
+	}								\
+	__pu_err;							\
 })
-#define __put_user(x, ptr) put_user(x, ptr)
+#define put_user(x, ptr)	__put_user(x, ptr)
 
-extern int __put_user_bad(void);
 
-/*
- * Tell gcc we read from memory instead of writing: this is because
- * we do not write to any memory gcc knows about, so there are no
- * aliasing issues.
- */
-#define __put_user_asm(err,x,ptr,bwl)			\
-__asm__ __volatile__					\
-    ("21:moves" #bwl " %2,%1\n"				\
-     "1:\n"						\
-     ".section .fixup,\"ax\"\n"				\
-     "   .even\n"					\
-     "2: movel %3,%0\n"					\
-     "   jra 1b\n"					\
-     ".previous\n"					\
-     ".section __ex_table,\"a\"\n"			\
-     "   .align 4\n"					\
-     "   .long 21b,2b\n"				\
-     "   .long 1b,2b\n"					\
-     ".previous"					\
-     : "=d"(err)					\
-     : "m"(*(ptr)), "r"(x), "i"(-EFAULT), "0"(0))
-
-#define get_user(x, ptr)					\
-({								\
-    int __gu_err;						\
-    typeof(*(ptr)) __gu_val;					\
-    __chk_user_ptr(ptr);					\
-    switch (sizeof(*(ptr))) {					\
-    case 1:							\
-	__get_user_asm(__gu_err, __gu_val, ptr, b, "=d");	\
-	break;							\
-    case 2:							\
-	__get_user_asm(__gu_err, __gu_val, ptr, w, "=r");	\
-	break;							\
-    case 4:							\
-	__get_user_asm(__gu_err, __gu_val, ptr, l, "=r");	\
-	break;							\
-    case 8:                                                     \
-        __gu_err = __constant_copy_from_user(&__gu_val, ptr, 8);  \
-        break;                                                  \
-    default:							\
-	__gu_val = (typeof(*(ptr)))0;				\
-	__gu_err = __get_user_bad();				\
-	break;							\
-    }								\
-    (x) = __gu_val;						\
-    __gu_err;							\
+#define __get_user_asm(res, x, ptr, type, bwl, reg, err) ({	\
+	type __gu_val;						\
+	asm volatile ("\n"					\
+		"1:	moves."#bwl"	%2,%1\n"		\
+		"2:\n"						\
+		"	.section .fixup,\"ax\"\n"		\
+		"	.even\n"				\
+		"10:	move.l	%3,%0\n"			\
+		"	sub."#bwl"	%1,%1\n"		\
+		"	jra	2b\n"				\
+		"	.previous\n"				\
+		"\n"						\
+		"	.section __ex_table,\"a\"\n"		\
+		"	.align	4\n"				\
+		"	.long	1b,10b\n"			\
+		"	.previous"				\
+		: "+d" (res), "=&" #reg (__gu_val)		\
+		: "m" (*(ptr)), "i" (err));			\
+	(x) = (typeof(*(ptr)))(long)__gu_val;			\
 })
-#define __get_user(x, ptr) get_user(x, ptr)
 
-extern int __get_user_bad(void);
+#define __get_user(x, ptr)						\
+({									\
+	int __gu_err = 0;						\
+	__chk_user_ptr(ptr);						\
+	switch (sizeof(*(ptr))) {					\
+	case 1:								\
+		__get_user_asm(__gu_err, x, ptr, u8, b, d, -EFAULT);	\
+		break;							\
+	case 2:								\
+		__get_user_asm(__gu_err, x, ptr, u16, w, d, -EFAULT);	\
+		break;							\
+	case 4:								\
+		__get_user_asm(__gu_err, x, ptr, u32, l, r, -EFAULT);	\
+		break;							\
+/*	case 8:	disabled because gcc-4.1 has a broken typeof		\
+ 	    {								\
+ 		const void *__gu_ptr = (ptr);				\
+ 		u64 __gu_val;						\
+		asm volatile ("\n"					\
+			"1:	moves.l	(%2)+,%1\n"			\
+			"2:	moves.l	(%2),%R1\n"			\
+			"3:\n"						\
+			"	.section .fixup,\"ax\"\n"		\
+			"	.even\n"				\
+			"10:	move.l	%3,%0\n"			\
+			"	sub.l	%1,%1\n"			\
+			"	sub.l	%R1,%R1\n"			\
+			"	jra	3b\n"				\
+			"	.previous\n"				\
+			"\n"						\
+			"	.section __ex_table,\"a\"\n"		\
+			"	.align	4\n"				\
+			"	.long	1b,10b\n"			\
+			"	.long	2b,10b\n"			\
+			"	.previous"				\
+			: "+d" (__gu_err), "=&r" (__gu_val),		\
+			  "+a" (__gu_ptr)				\
+			: "i" (-EFAULT)					\
+			: "memory");					\
+		(x) = (typeof(*(ptr)))__gu_val;				\
+		break;							\
+	    }	*/							\
+	default:							\
+		__gu_err = __get_user_bad();				\
+		break;							\
+	}								\
+	__gu_err;							\
+})
+#define get_user(x, ptr) __get_user(x, ptr)
 
-#define __get_user_asm(err,x,ptr,bwl,reg)	\
-__asm__ __volatile__				\
-    ("1: moves" #bwl " %2,%1\n"			\
-     "2:\n"					\
-     ".section .fixup,\"ax\"\n"			\
-     "   .even\n"				\
-     "3: movel %3,%0\n"				\
-     "   sub" #bwl " %1,%1\n"			\
-     "   jra 2b\n"				\
-     ".previous\n"				\
-     ".section __ex_table,\"a\"\n"		\
-     "   .align 4\n"				\
-     "   .long 1b,3b\n"				\
-     ".previous"				\
-     : "=d"(err), reg(x)			\
-     : "m"(*(ptr)), "i" (-EFAULT), "0"(0))
+unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n);
+unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n);
 
-static inline unsigned long
-__generic_copy_from_user(void *to, const void __user *from, unsigned long n)
-{
-    unsigned long tmp;
-    __asm__ __volatile__
-	("   tstl %2\n"
-	 "   jeq 2f\n"
-	 "1: movesl (%1)+,%3\n"
-	 "   movel %3,(%0)+\n"
-	 "   subql #1,%2\n"
-	 "   jne 1b\n"
-	 "2: movel %4,%2\n"
-	 "   bclr #1,%2\n"
-	 "   jeq 4f\n"
-	 "3: movesw (%1)+,%3\n"
-	 "   movew %3,(%0)+\n"
-	 "4: bclr #0,%2\n"
-	 "   jeq 6f\n"
-	 "5: movesb (%1)+,%3\n"
-	 "   moveb %3,(%0)+\n"
-	 "6:\n"
-	 ".section .fixup,\"ax\"\n"
-	 "   .even\n"
-	 "7: movel %2,%%d0\n"
-	 "71:clrl (%0)+\n"
-	 "   subql #1,%%d0\n"
-	 "   jne 71b\n"
-	 "   lsll #2,%2\n"
-	 "   addl %4,%2\n"
-	 "   btst #1,%4\n"
-	 "   jne 81f\n"
-	 "   btst #0,%4\n"
-	 "   jne 91f\n"
-	 "   jra 6b\n"
-	 "8: addql #2,%2\n"
-	 "81:clrw (%0)+\n"
-	 "   btst #0,%4\n"
-	 "   jne 91f\n"
-	 "   jra 6b\n"
-	 "9: addql #1,%2\n"
-	 "91:clrb (%0)+\n"
-	 "   jra 6b\n"
-         ".previous\n"
-	 ".section __ex_table,\"a\"\n"
-	 "   .align 4\n"
-	 "   .long 1b,7b\n"
-	 "   .long 3b,8b\n"
-	 "   .long 5b,9b\n"
-	 ".previous"
-	 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
-	 : "d"(n & 3), "0"(to), "1"(from), "2"(n/4)
-	 : "d0", "memory");
-    return n;
-}
+#define __constant_copy_from_user_asm(res, to, from, tmp, n, s1, s2, s3)\
+	asm volatile ("\n"						\
+		"1:	moves."#s1"	(%2)+,%3\n"			\
+		"	move."#s1"	%3,(%1)+\n"			\
+		"2:	moves."#s2"	(%2)+,%3\n"			\
+		"	move."#s2"	%3,(%1)+\n"			\
+		"	.ifnc	\""#s3"\",\"\"\n"			\
+		"3:	moves."#s3"	(%2)+,%3\n"			\
+		"	move."#s3"	%3,(%1)+\n"			\
+		"	.endif\n"					\
+		"4:\n"							\
+		"	.section __ex_table,\"a\"\n"			\
+		"	.align	4\n"					\
+		"	.long	1b,10f\n"				\
+		"	.long	2b,20f\n"				\
+		"	.ifnc	\""#s3"\",\"\"\n"			\
+		"	.long	3b,30f\n"				\
+		"	.endif\n"					\
+		"	.previous\n"					\
+		"\n"							\
+		"	.section .fixup,\"ax\"\n"			\
+		"	.even\n"					\
+		"10:	clr."#s1"	(%1)+\n"			\
+		"20:	clr."#s2"	(%1)+\n"			\
+		"	.ifnc	\""#s3"\",\"\"\n"			\
+		"30:	clr."#s3"	(%1)+\n"			\
+		"	.endif\n"					\
+		"	moveq.l	#"#n",%0\n"				\
+		"	jra	4b\n"					\
+		"	.previous\n"					\
+		: "+d" (res), "+&a" (to), "+a" (from), "=&d" (tmp)	\
+		: : "memory")
 
-static inline unsigned long
-__generic_copy_to_user(void __user *to, const void *from, unsigned long n)
-{
-    unsigned long tmp;
-    __asm__ __volatile__
-	("   tstl %2\n"
-	 "   jeq 3f\n"
-	 "1: movel (%1)+,%3\n"
-	 "22:movesl %3,(%0)+\n"
-	 "2: subql #1,%2\n"
-	 "   jne 1b\n"
-	 "3: movel %4,%2\n"
-	 "   bclr #1,%2\n"
-	 "   jeq 4f\n"
-	 "   movew (%1)+,%3\n"
-	 "24:movesw %3,(%0)+\n"
-	 "4: bclr #0,%2\n"
-	 "   jeq 5f\n"
-	 "   moveb (%1)+,%3\n"
-	 "25:movesb %3,(%0)+\n"
-	 "5:\n"
-	 ".section .fixup,\"ax\"\n"
-	 "   .even\n"
-	 "60:addql #1,%2\n"
-	 "6: lsll #2,%2\n"
-	 "   addl %4,%2\n"
-	 "   jra 5b\n"
-	 "7: addql #2,%2\n"
-	 "   jra 5b\n"
-	 "8: addql #1,%2\n"
-	 "   jra 5b\n"
-	 ".previous\n"
-	 ".section __ex_table,\"a\"\n"
-	 "   .align 4\n"
-	 "   .long 1b,60b\n"
-	 "   .long 22b,6b\n"
-	 "   .long 2b,6b\n"
-	 "   .long 24b,7b\n"
-	 "   .long 3b,60b\n"
-	 "   .long 4b,7b\n"
-	 "   .long 25b,8b\n"
-	 "   .long 5b,8b\n"
-	 ".previous"
-	 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
-	 : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
-	 : "memory");
-    return n;
-}
-
-#define __copy_from_user_big(to, from, n, fixup, copy)	\
-    __asm__ __volatile__				\
-	("10: movesl (%1)+,%%d0\n"			\
-	 "    movel %%d0,(%0)+\n"			\
-	 "    subql #1,%2\n"				\
-	 "    jne 10b\n"				\
-	 ".section .fixup,\"ax\"\n"			\
-	 "    .even\n"					\
-	 "11: movel %2,%%d0\n"				\
-	 "13: clrl (%0)+\n"				\
-	 "    subql #1,%%d0\n"				\
-	 "    jne 13b\n"				\
-	 "    lsll #2,%2\n"				\
-	 fixup "\n"					\
-	 "    jra 12f\n"				\
-	 ".previous\n"					\
-	 ".section __ex_table,\"a\"\n"			\
-	 "    .align 4\n"				\
-	 "    .long 10b,11b\n"				\
-	 ".previous\n"					\
-	 copy "\n"					\
-	 "12:"						\
-	 : "=a"(to), "=a"(from), "=d"(n)		\
-	 : "0"(to), "1"(from), "2"(n/4)			\
-	 : "d0", "memory")
-
-static inline unsigned long
+static __always_inline unsigned long
 __constant_copy_from_user(void *to, const void __user *from, unsigned long n)
 {
-    switch (n) {
-    case 0:
-	break;
-    case 1:
-	__asm__ __volatile__
-	    ("1: movesb (%1)+,%%d0\n"
-	     "   moveb %%d0,(%0)+\n"
-	     "2:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "3: addql #1,%2\n"
-	     "   clrb (%0)+\n"
-	     "   jra 2b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 1b,3b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 2:
-	__asm__ __volatile__
-	    ("1: movesw (%1)+,%%d0\n"
-	     "   movew %%d0,(%0)+\n"
-	     "2:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "3: addql #2,%2\n"
-	     "   clrw (%0)+\n"
-	     "   jra 2b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 1b,3b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 3:
-	__asm__ __volatile__
-	    ("1: movesw (%1)+,%%d0\n"
-	     "   movew %%d0,(%0)+\n"
-	     "2: movesb (%1)+,%%d0\n"
-	     "   moveb %%d0,(%0)+\n"
-	     "3:"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "4: addql #2,%2\n"
-	     "   clrw (%0)+\n"
-	     "5: addql #1,%2\n"
-	     "   clrb (%0)+\n"
-	     "   jra 3b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 1b,4b\n"
-	     "   .long 2b,5b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 4:
-	__asm__ __volatile__
-	    ("1: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "2:"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "3: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "   jra 2b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 1b,3b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 8:
-	__asm__ __volatile__
-	    ("1: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "2: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "3:"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "4: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "5: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "   jra 3b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 1b,4b\n"
-	     "   .long 2b,5b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 12:
-	__asm__ __volatile__
-	    ("1: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "2: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "3: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "4:"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "5: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "6: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "7: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "   jra 4b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 1b,5b\n"
-	     "   .long 2b,6b\n"
-	     "   .long 3b,7b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 16:
-	__asm__ __volatile__
-	    ("1: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "2: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "3: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "4: movesl (%1)+,%%d0\n"
-	     "   movel %%d0,(%0)+\n"
-	     "5:"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "6: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "7: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "8: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "9: addql #4,%2\n"
-	     "   clrl (%0)+\n"
-	     "   jra 5b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 1b,6b\n"
-	     "   .long 2b,7b\n"
-	     "   .long 3b,8b\n"
-	     "   .long 4b,9b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    default:
-	switch (n & 3) {
-	case 0:
-	    __copy_from_user_big(to, from, n, "", "");
-	    break;
+	unsigned long res = 0, tmp;
+
+	switch (n) {
 	case 1:
-	    __copy_from_user_big(to, from, n,
-				 /* fixup */
-				 "1: addql #1,%2\n"
-				 "   clrb (%0)+",
-				 /* copy */
-				 "2: movesb (%1)+,%%d0\n"
-				 "   moveb %%d0,(%0)+\n"
-				 ".section __ex_table,\"a\"\n"
-				 "   .long 2b,1b\n"
-				 ".previous");
-	    break;
+		__get_user_asm(res, *(u8 *)to, (u8 *)from, u8, b, d, 1);
+		break;
 	case 2:
-	    __copy_from_user_big(to, from, n,
-				 /* fixup */
-				 "1: addql #2,%2\n"
-				 "   clrw (%0)+",
-				 /* copy */
-				 "2: movesw (%1)+,%%d0\n"
-				 "   movew %%d0,(%0)+\n"
-				 ".section __ex_table,\"a\"\n"
-				 "   .long 2b,1b\n"
-				 ".previous");
-	    break;
+		__get_user_asm(res, *(u16 *)to, (u16 *)from, u16, w, d, 2);
+		break;
 	case 3:
-	    __copy_from_user_big(to, from, n,
-				 /* fixup */
-				 "1: addql #2,%2\n"
-				 "   clrw (%0)+\n"
-				 "2: addql #1,%2\n"
-				 "   clrb (%0)+",
-				 /* copy */
-				 "3: movesw (%1)+,%%d0\n"
-				 "   movew %%d0,(%0)+\n"
-				 "4: movesb (%1)+,%%d0\n"
-				 "   moveb %%d0,(%0)+\n"
-				 ".section __ex_table,\"a\"\n"
-				 "   .long 3b,1b\n"
-				 "   .long 4b,2b\n"
-				 ".previous");
-	    break;
+		__constant_copy_from_user_asm(res, to, from, tmp, 3, w, b,);
+		break;
+	case 4:
+		__get_user_asm(res, *(u32 *)to, (u32 *)from, u32, l, r, 4);
+		break;
+	case 5:
+		__constant_copy_from_user_asm(res, to, from, tmp, 5, l, b,);
+		break;
+	case 6:
+		__constant_copy_from_user_asm(res, to, from, tmp, 6, l, w,);
+		break;
+	case 7:
+		__constant_copy_from_user_asm(res, to, from, tmp, 7, l, w, b);
+		break;
+	case 8:
+		__constant_copy_from_user_asm(res, to, from, tmp, 8, l, l,);
+		break;
+	case 9:
+		__constant_copy_from_user_asm(res, to, from, tmp, 9, l, l, b);
+		break;
+	case 10:
+		__constant_copy_from_user_asm(res, to, from, tmp, 10, l, l, w);
+		break;
+	case 12:
+		__constant_copy_from_user_asm(res, to, from, tmp, 12, l, l, l);
+		break;
+	default:
+		/* we limit the inlined version to 3 moves */
+		return __generic_copy_from_user(to, from, n);
 	}
-	break;
-    }
-    return n;
+
+	return res;
 }
 
-#define __copy_to_user_big(to, from, n, fixup, copy)	\
-    __asm__ __volatile__				\
-	("10: movel (%1)+,%%d0\n"			\
-	 "31: movesl %%d0,(%0)+\n"			\
-	 "11: subql #1,%2\n"				\
-	 "    jne 10b\n"				\
-	 "41:\n"					\
-	 ".section .fixup,\"ax\"\n"			\
-	 "   .even\n"					\
-	 "22: addql #1,%2\n"				\
-	 "12: lsll #2,%2\n"				\
-	 fixup "\n"					\
-	 "    jra 13f\n"				\
-	 ".previous\n"					\
-	 ".section __ex_table,\"a\"\n"			\
-	 "    .align 4\n"				\
-	 "    .long 10b,22b\n"				\
-	 "    .long 31b,12b\n"				\
-	 "    .long 11b,12b\n"				\
-	 "    .long 41b,22b\n"				\
-	 ".previous\n"					\
-	 copy "\n"					\
-	 "13:"						\
-	 : "=a"(to), "=a"(from), "=d"(n)		\
-	 : "0"(to), "1"(from), "2"(n/4)			\
-	 : "d0", "memory")
+#define __constant_copy_to_user_asm(res, to, from, tmp, n, s1, s2, s3)	\
+	asm volatile ("\n"						\
+		"	move."#s1"	(%2)+,%3\n"			\
+		"11:	moves."#s1"	%3,(%1)+\n"			\
+		"12:	move."#s2"	(%2)+,%3\n"			\
+		"21:	moves."#s2"	%3,(%1)+\n"			\
+		"22:\n"							\
+		"	.ifnc	\""#s3"\",\"\"\n"			\
+		"	move."#s3"	(%2)+,%3\n"			\
+		"31:	moves."#s3"	%3,(%1)+\n"			\
+		"32:\n"							\
+		"	.endif\n"					\
+		"4:\n"							\
+		"\n"							\
+		"	.section __ex_table,\"a\"\n"			\
+		"	.align	4\n"					\
+		"	.long	11b,5f\n"				\
+		"	.long	12b,5f\n"				\
+		"	.long	21b,5f\n"				\
+		"	.long	22b,5f\n"				\
+		"	.ifnc	\""#s3"\",\"\"\n"			\
+		"	.long	31b,5f\n"				\
+		"	.long	32b,5f\n"				\
+		"	.endif\n"					\
+		"	.previous\n"					\
+		"\n"							\
+		"	.section .fixup,\"ax\"\n"			\
+		"	.even\n"					\
+		"5:	moveq.l	#"#n",%0\n"				\
+		"	jra	4b\n"					\
+		"	.previous\n"					\
+		: "+d" (res), "+a" (to), "+a" (from), "=&d" (tmp)	\
+		: : "memory")
 
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
-
-static inline unsigned long
+static __always_inline unsigned long
 __constant_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
-    switch (n) {
-    case 0:
-	break;
-    case 1:
-	__asm__ __volatile__
-	    ("   moveb (%1)+,%%d0\n"
-	     "21:movesb %%d0,(%0)+\n"
-	     "1:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "2: addql #1,%2\n"
-	     "   jra 1b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n  "
-	     "   .long 21b,2b\n"
-	     "   .long 1b,2b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 2:
-	__asm__ __volatile__
-	    ("   movew (%1)+,%%d0\n"
-	     "21:movesw %%d0,(%0)+\n"
-	     "1:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "2: addql #2,%2\n"
-	     "   jra 1b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 21b,2b\n"
-	     "   .long 1b,2b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 3:
-	__asm__ __volatile__
-	    ("   movew (%1)+,%%d0\n"
-	     "21:movesw %%d0,(%0)+\n"
-	     "1: moveb (%1)+,%%d0\n"
-	     "22:movesb %%d0,(%0)+\n"
-	     "2:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "3: addql #2,%2\n"
-	     "4: addql #1,%2\n"
-	     "   jra 2b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 21b,3b\n"
-	     "   .long 1b,3b\n"
-	     "   .long 22b,4b\n"
-	     "   .long 2b,4b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 4:
-	__asm__ __volatile__
-	    ("   movel (%1)+,%%d0\n"
-	     "21:movesl %%d0,(%0)+\n"
-	     "1:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "2: addql #4,%2\n"
-	     "   jra 1b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 21b,2b\n"
-	     "   .long 1b,2b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 8:
-	__asm__ __volatile__
-	    ("   movel (%1)+,%%d0\n"
-	     "21:movesl %%d0,(%0)+\n"
-	     "1: movel (%1)+,%%d0\n"
-	     "22:movesl %%d0,(%0)+\n"
-	     "2:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "3: addql #4,%2\n"
-	     "4: addql #4,%2\n"
-	     "   jra 2b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 21b,3b\n"
-	     "   .long 1b,3b\n"
-	     "   .long 22b,4b\n"
-	     "   .long 2b,4b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 12:
-	__asm__ __volatile__
-	    ("   movel (%1)+,%%d0\n"
-	     "21:movesl %%d0,(%0)+\n"
-	     "1: movel (%1)+,%%d0\n"
-	     "22:movesl %%d0,(%0)+\n"
-	     "2: movel (%1)+,%%d0\n"
-	     "23:movesl %%d0,(%0)+\n"
-	     "3:\n"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "4: addql #4,%2\n"
-	     "5: addql #4,%2\n"
-	     "6: addql #4,%2\n"
-	     "   jra 3b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 21b,4b\n"
-	     "   .long 1b,4b\n"
-	     "   .long 22b,5b\n"
-	     "   .long 2b,5b\n"
-	     "   .long 23b,6b\n"
-	     "   .long 3b,6b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    case 16:
-	__asm__ __volatile__
-	    ("   movel (%1)+,%%d0\n"
-	     "21:movesl %%d0,(%0)+\n"
-	     "1: movel (%1)+,%%d0\n"
-	     "22:movesl %%d0,(%0)+\n"
-	     "2: movel (%1)+,%%d0\n"
-	     "23:movesl %%d0,(%0)+\n"
-	     "3: movel (%1)+,%%d0\n"
-	     "24:movesl %%d0,(%0)+\n"
-	     "4:"
-	     ".section .fixup,\"ax\"\n"
-	     "   .even\n"
-	     "5: addql #4,%2\n"
-	     "6: addql #4,%2\n"
-	     "7: addql #4,%2\n"
-	     "8: addql #4,%2\n"
-	     "   jra 4b\n"
-	     ".previous\n"
-	     ".section __ex_table,\"a\"\n"
-	     "   .align 4\n"
-	     "   .long 21b,5b\n"
-	     "   .long 1b,5b\n"
-	     "   .long 22b,6b\n"
-	     "   .long 2b,6b\n"
-	     "   .long 23b,7b\n"
-	     "   .long 3b,7b\n"
-	     "   .long 24b,8b\n"
-	     "   .long 4b,8b\n"
-	     ".previous"
-	     : "=a"(to), "=a"(from), "=d"(n)
-	     : "0"(to), "1"(from), "2"(0)
-	     : "d0", "memory");
-	break;
-    default:
-	switch (n & 3) {
-	case 0:
-	    __copy_to_user_big(to, from, n, "", "");
-	    break;
+	unsigned long res = 0, tmp;
+
+	switch (n) {
 	case 1:
-	    __copy_to_user_big(to, from, n,
-			       /* fixup */
-			       "1: addql #1,%2",
-			       /* copy */
-			       "   moveb (%1)+,%%d0\n"
-			       "22:movesb %%d0,(%0)+\n"
-			       "2:"
-			       ".section __ex_table,\"a\"\n"
-			       "   .long 22b,1b\n"
-			       "   .long 2b,1b\n"
-			       ".previous");
-	    break;
+		__put_user_asm(res, *(u8 *)from, (u8 *)to, b, d, 1);
+		break;
 	case 2:
-	    __copy_to_user_big(to, from, n,
-			       /* fixup */
-			       "1: addql #2,%2",
-			       /* copy */
-			       "   movew (%1)+,%%d0\n"
-			       "22:movesw %%d0,(%0)+\n"
-			       "2:"
-			       ".section __ex_table,\"a\"\n"
-			       "   .long 22b,1b\n"
-			       "   .long 2b,1b\n"
-			       ".previous");
-	    break;
+		__put_user_asm(res, *(u16 *)from, (u16 *)to, w, d, 2);
+		break;
 	case 3:
-	    __copy_to_user_big(to, from, n,
-			       /* fixup */
-			       "1: addql #2,%2\n"
-			       "2: addql #1,%2",
-			       /* copy */
-			       "   movew (%1)+,%%d0\n"
-			       "23:movesw %%d0,(%0)+\n"
-			       "3: moveb (%1)+,%%d0\n"
-			       "24:movesb %%d0,(%0)+\n"
-			       "4:"
-			       ".section __ex_table,\"a\"\n"
-			       "   .long 23b,1b\n"
-			       "   .long 3b,1b\n"
-			       "   .long 24b,2b\n"
-			       "   .long 4b,2b\n"
-			       ".previous");
-	    break;
+		__constant_copy_to_user_asm(res, to, from, tmp, 3, w, b,);
+		break;
+	case 4:
+		__put_user_asm(res, *(u32 *)from, (u32 *)to, l, r, 4);
+		break;
+	case 5:
+		__constant_copy_to_user_asm(res, to, from, tmp, 5, l, b,);
+		break;
+	case 6:
+		__constant_copy_to_user_asm(res, to, from, tmp, 6, l, w,);
+		break;
+	case 7:
+		__constant_copy_to_user_asm(res, to, from, tmp, 7, l, w, b);
+		break;
+	case 8:
+		__constant_copy_to_user_asm(res, to, from, tmp, 8, l, l,);
+		break;
+	case 9:
+		__constant_copy_to_user_asm(res, to, from, tmp, 9, l, l, b);
+		break;
+	case 10:
+		__constant_copy_to_user_asm(res, to, from, tmp, 10, l, l, w);
+		break;
+	case 12:
+		__constant_copy_to_user_asm(res, to, from, tmp, 12, l, l, l);
+		break;
+	default:
+		/* limit the inlined version to 3 moves */
+		return __generic_copy_to_user(to, from, n);
 	}
-	break;
-    }
-    return n;
+
+	return res;
 }
 
-#define copy_from_user(to, from, n)		\
+#define __copy_from_user(to, from, n)		\
 (__builtin_constant_p(n) ?			\
  __constant_copy_from_user(to, from, n) :	\
  __generic_copy_from_user(to, from, n))
 
-#define copy_to_user(to, from, n)		\
+#define __copy_to_user(to, from, n)		\
 (__builtin_constant_p(n) ?			\
  __constant_copy_to_user(to, from, n) :		\
  __generic_copy_to_user(to, from, n))
 
-#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
-#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
+#define __copy_to_user_inatomic		__copy_to_user
+#define __copy_from_user_inatomic	__copy_from_user
 
-/*
- * Copy a null terminated string from userspace.
- */
+#define copy_from_user(to, from, n)	__copy_from_user(to, from, n)
+#define copy_to_user(to, from, n)	__copy_to_user(to, from, n)
 
-static inline long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
-    long res;
-    if (count == 0) return count;
-    __asm__ __volatile__
-	("1: movesb (%2)+,%%d0\n"
-	 "12:moveb %%d0,(%1)+\n"
-	 "   jeq 2f\n"
-	 "   subql #1,%3\n"
-	 "   jne 1b\n"
-	 "2: subl %3,%0\n"
-	 "3:\n"
-	 ".section .fixup,\"ax\"\n"
-	 "   .even\n"
-	 "4: movel %4,%0\n"
-	 "   jra 3b\n"
-	 ".previous\n"
-	 ".section __ex_table,\"a\"\n"
-	 "   .align 4\n"
-	 "   .long 1b,4b\n"
-	 "   .long 12b,4b\n"
-	 ".previous"
-	 : "=d"(res), "=a"(dst), "=a"(src), "=d"(count)
-	 : "i"(-EFAULT), "0"(count), "1"(dst), "2"(src), "3"(count)
-	 : "d0", "memory");
-    return res;
-}
-
-/*
- * Return the size of a string (including the ending 0)
- *
- * Return 0 on exception, a value greater than N if too long
- */
-static inline long strnlen_user(const char __user *src, long n)
-{
-	long res;
-
-	res = -(unsigned long)src;
-	__asm__ __volatile__
-		("1:\n"
-		 "   tstl %2\n"
-		 "   jeq 3f\n"
-		 "2: movesb (%1)+,%%d0\n"
-		 "22:\n"
-		 "   subql #1,%2\n"
-		 "   tstb %%d0\n"
-		 "   jne 1b\n"
-		 "   jra 4f\n"
-		 "3:\n"
-		 "   addql #1,%0\n"
-		 "4:\n"
-		 "   addl %1,%0\n"
-		 "5:\n"
-		 ".section .fixup,\"ax\"\n"
-		 "   .even\n"
-		 "6: moveq %3,%0\n"
-		 "   jra 5b\n"
-		 ".previous\n"
-		 ".section __ex_table,\"a\"\n"
-		 "   .align 4\n"
-		 "   .long 2b,6b\n"
-		 "   .long 22b,6b\n"
-		 ".previous"
-		 : "=d"(res), "=a"(src), "=d"(n)
-		 : "i"(0), "0"(res), "1"(src), "2"(n)
-		 : "d0");
-	return res;
-}
+long strncpy_from_user(char *dst, const char __user *src, long count);
+long strnlen_user(const char __user *src, long n);
+unsigned long clear_user(void __user *to, unsigned long n);
 
 #define strlen_user(str) strnlen_user(str, 32767)
 
-/*
- * Zero Userspace
- */
-
-static inline unsigned long
-clear_user(void __user *to, unsigned long n)
-{
-    __asm__ __volatile__
-	("   tstl %1\n"
-	 "   jeq 3f\n"
-	 "1: movesl %3,(%0)+\n"
-	 "2: subql #1,%1\n"
-	 "   jne 1b\n"
-	 "3: movel %2,%1\n"
-	 "   bclr #1,%1\n"
-	 "   jeq 4f\n"
-	 "24:movesw %3,(%0)+\n"
-	 "4: bclr #0,%1\n"
-	 "   jeq 5f\n"
-	 "25:movesb %3,(%0)+\n"
-	 "5:\n"
-	 ".section .fixup,\"ax\"\n"
-	 "   .even\n"
-	 "61:addql #1,%1\n"
-	 "6: lsll #2,%1\n"
-	 "   addl %2,%1\n"
-	 "   jra 5b\n"
-	 "7: addql #2,%1\n"
-	 "   jra 5b\n"
-	 "8: addql #1,%1\n"
-	 "   jra 5b\n"
-	 ".previous\n"
-	 ".section __ex_table,\"a\"\n"
-	 "   .align 4\n"
-	 "   .long 1b,61b\n"
-	 "   .long 2b,6b\n"
-	 "   .long 3b,61b\n"
-	 "   .long 24b,7b\n"
-	 "   .long 4b,7b\n"
-	 "   .long 25b,8b\n"
-	 "   .long 5b,8b\n"
-	 ".previous"
-	 : "=a"(to), "=d"(n)
-	 : "r"(n & 3), "r"(0), "0"(to), "1"(n/4));
-    return n;
-}
-
 #endif /* _M68K_UACCESS_H */
diff --git a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
index c2554bc..7c0b629 100644
--- a/include/asm-m68k/unistd.h
+++ b/include/asm-m68k/unistd.h
@@ -285,6 +285,8 @@
 #define __NR_request_key	280
 #define __NR_keyctl		281
 
+#ifdef __KERNEL__
+
 #define NR_syscalls		282
 
 /* user-visible error numbers are in the range -1 - -124: see
@@ -383,7 +385,6 @@
 __syscall_return(type,__res); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -406,52 +407,12 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
-#include <linux/compiler.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-
-/*
- * we need this inline - forking from kernel space will result
- * in NO COPY ON WRITE (!!!), until an execve is executed. This
- * is no problem, but for the stack. This is handled by not letting
- * main() use the stack at all after fork(). Thus, no function
- * calls - which means inline code for fork too, as otherwise we
- * would use the stack upon exit from 'fork()'.
- *
- * Actually only pause and fork are needed inline, so that there
- * won't be any messing with the stack from main(), but we define
- * some others too.
- */
-#define __NR__exit __NR_exit
-static inline _syscall0(pid_t,setsid)
-static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
-static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
-static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
-static inline _syscall1(int,dup,int,fd)
 static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
-static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
-static inline _syscall1(int,close,int,fd)
-static inline _syscall1(int,_exit,int,exitcode)
-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
 
-asmlinkage long sys_mmap2(
-			unsigned long addr, unsigned long len,
-			unsigned long prot, unsigned long flags,
-			unsigned long fd, unsigned long pgoff);
-asmlinkage int sys_execve(char *name, char **argv, char **envp);
-asmlinkage int sys_pipe(unsigned long *fildes);
-struct pt_regs;
-struct sigaction;
-asmlinkage long sys_rt_sigaction(int sig,
-				const struct sigaction __user *act,
-				struct sigaction __user *oact,
-				size_t sigsetsize);
-
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -461,4 +422,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/include/asm-m68k/virtconvert.h b/include/asm-m68k/virtconvert.h
index 8c4e803..83a87c9 100644
--- a/include/asm-m68k/virtconvert.h
+++ b/include/asm-m68k/virtconvert.h
@@ -7,7 +7,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/setup.h>
 #include <asm/page.h>
diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
index 0b68ccd..d7fa7d9 100644
--- a/include/asm-m68knommu/bitops.h
+++ b/include/asm-m68knommu/bitops.h
@@ -5,7 +5,6 @@
  * Copyright 1992, Linus Torvalds.
  */
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/byteorder.h>	/* swab32 */
 #include <asm/system.h>		/* save_flags */
diff --git a/include/asm-m68knommu/bootstd.h b/include/asm-m68knommu/bootstd.h
index 3fdc79f..bdc1a4a 100644
--- a/include/asm-m68knommu/bootstd.h
+++ b/include/asm-m68knommu/bootstd.h
@@ -52,7 +52,7 @@
    __asm__ __volatile__ ("trap #2" \
                          : "=g" (__res) \
                          : "0" (__res) \
-                         : "%d0"); \
+                         ); \
    __bsc_return(type,__res); \
 }
 
@@ -64,7 +64,7 @@
    __asm__ __volatile__ ("trap #2" \
                          : "=g" (__res) \
                          : "0" (__res), "d" (__a) \
-                         : "%d0"); \
+                         ); \
    __bsc_return(type,__res); \
 }
 
@@ -77,7 +77,7 @@
    __asm__ __volatile__ ("trap #2" \
                          : "=g" (__res) \
                          : "0" (__res), "d" (__a), "d" (__b) \
-                         : "%d0"); \
+                         ); \
    __bsc_return(type,__res); \
 }
 
@@ -92,7 +92,7 @@
                          : "=g" (__res) \
                          : "0" (__res), "d" (__a), "d" (__b), \
                            "d" (__c) \
-                         : "%d0"); \
+                         ); \
    __bsc_return(type,__res); \
 }
 
@@ -108,7 +108,7 @@
                          : "=g" (__res) \
                          : "0" (__res), "d" (__a), "d" (__b), \
                            "d" (__c), "d" (__d) \
-                         : "%d0"); \
+                         ); \
    __bsc_return(type,__res); \
 }
 
@@ -125,7 +125,7 @@
                          : "=g" (__res) \
                          : "0" (__res), "d" (__a), "d" (__b), \
                            "d" (__c), "d" (__d), "d" (__e) \
-                         : "%d0"); \
+                         ); \
    __bsc_return(type,__res); \
 }
 
diff --git a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
index 49925e9..c3aadf3 100644
--- a/include/asm-m68knommu/cacheflush.h
+++ b/include/asm-m68knommu/cacheflush.h
@@ -57,13 +57,13 @@
 		"nop\n\t"
 		: : : "d0" );
 #endif /* CONFIG_M527x || CONFIG_M528x */
-#ifdef CONFIG_M5272
+#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || defined(CONFIG_M5272)
 	__asm__ __volatile__ (
-        	"movel	#0x01000000, %%d0\n\t"
+        	"movel	#0x81000100, %%d0\n\t"
         	"movec	%%d0, %%CACR\n\t"
 		"nop\n\t"
 		: : : "d0" );
-#endif /* CONFIG_M5272 */
+#endif /* CONFIG_M5206 || CONFIG_M5206e || CONFIG_M5272 */
 #ifdef CONFIG_M5249
 	__asm__ __volatile__ (
         	"movel	#0xa1000200, %%d0\n\t"
@@ -71,6 +71,13 @@
 		"nop\n\t"
 		: : : "d0" );
 #endif /* CONFIG_M5249 */
+#ifdef CONFIG_M532x
+	__asm__ __volatile__ (
+        	"movel	#0x81000200, %%d0\n\t"
+        	"movec	%%d0, %%CACR\n\t"
+		"nop\n\t"
+		: : : "d0" );
+#endif /* CONFIG_M532x */
 }
 
 #endif /* _M68KNOMMU_CACHEFLUSH_H */
diff --git a/include/asm-m68knommu/coldfire.h b/include/asm-m68knommu/coldfire.h
index 6190f77..83a9fa4 100644
--- a/include/asm-m68knommu/coldfire.h
+++ b/include/asm-m68knommu/coldfire.h
@@ -3,7 +3,7 @@
 /*
  *	coldfire.h -- Motorola ColdFire CPU sepecific defines
  *
- *	(C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	(C) Copyright 1999-2006, Greg Ungerer (gerg@snapgear.com)
  *	(C) Copyright 2000, Lineo (www.lineo.com)
  */
 
@@ -12,7 +12,19 @@
 #define	coldfire_h
 /****************************************************************************/
 
-#include <linux/config.h>
+
+/*
+ *	Define master clock frequency. This is essentially done at config
+ *	time now. No point enumerating dozens of possible clock options
+ *	here. Also the peripheral clock (bus clock) divide ratio is set
+ *	at config time too.
+ */
+#ifdef CONFIG_CLOCK_SET
+#define	MCF_CLK		CONFIG_CLOCK_FREQ
+#define	MCF_BUSCLK	(CONFIG_CLOCK_FREQ / CONFIG_CLOCK_DIV)
+#else
+#error "Don't know what your ColdFire CPU clock frequency is??"
+#endif
 
 /*
  *	Define the processor support peripherals base address.
@@ -30,64 +42,9 @@
     defined(CONFIG_M520x)
 #undef MCF_MBAR
 #define	MCF_MBAR	MCF_IPSBAR
-#endif
-
-/*
- *	Define master clock frequency.
- */
-#if defined(CONFIG_CLOCK_11MHz)
-#define	MCF_CLK		11289600
-#elif defined(CONFIG_CLOCK_16MHz)
-#define	MCF_CLK		16000000
-#elif defined(CONFIG_CLOCK_20MHz)
-#define	MCF_CLK		20000000
-#elif defined(CONFIG_CLOCK_24MHz)
-#define	MCF_CLK		24000000
-#elif defined(CONFIG_CLOCK_25MHz)
-#define	MCF_CLK		25000000
-#elif defined(CONFIG_CLOCK_33MHz)
-#define	MCF_CLK		33000000
-#elif defined(CONFIG_CLOCK_40MHz)
-#define	MCF_CLK		40000000
-#elif defined(CONFIG_CLOCK_45MHz)
-#define	MCF_CLK		45000000
-#elif defined(CONFIG_CLOCK_48MHz)
-#define	MCF_CLK		48000000
-#elif defined(CONFIG_CLOCK_50MHz)
-#define	MCF_CLK		50000000
-#elif defined(CONFIG_CLOCK_54MHz)
-#define	MCF_CLK		54000000
-#elif defined(CONFIG_CLOCK_60MHz)
-#define	MCF_CLK		60000000
-#elif defined(CONFIG_CLOCK_62_5MHz)
-#define MCF_CLK		62500000
-#elif defined(CONFIG_CLOCK_64MHz)
-#define	MCF_CLK		64000000
-#elif defined(CONFIG_CLOCK_66MHz)
-#define	MCF_CLK		66000000
-#elif defined(CONFIG_CLOCK_70MHz)
-#define	MCF_CLK		70000000
-#elif defined(CONFIG_CLOCK_100MHz)
-#define	MCF_CLK		100000000
-#elif defined(CONFIG_CLOCK_140MHz)
-#define	MCF_CLK		140000000
-#elif defined(CONFIG_CLOCK_150MHz)
-#define	MCF_CLK		150000000
-#elif defined(CONFIG_CLOCK_166MHz)
-#define	MCF_CLK		166000000
-#else
-#error "Don't know what your ColdFire CPU clock frequency is??"
-#endif
-
-/*
- *	One some ColdFire family members the bus clock (used by internal
- *	peripherals) is not the same as the CPU clock.
- */
-#if defined(CONFIG_M523x) || defined(CONFIG_M5249) || defined(CONFIG_M527x) || \
-    defined(CONFIG_M520x)
-#define	MCF_BUSCLK	(MCF_CLK / 2)
-#else
-#define	MCF_BUSCLK	MCF_CLK
+#elif defined(CONFIG_M532x)
+#undef MCF_MBAR
+#define MCF_MBAR	0x00000000
 #endif
 
 /****************************************************************************/
diff --git a/include/asm-m68knommu/commproc.h b/include/asm-m68knommu/commproc.h
index e522ca8..0161ebb 100644
--- a/include/asm-m68knommu/commproc.h
+++ b/include/asm-m68knommu/commproc.h
@@ -17,7 +17,6 @@
 #ifndef __CPM_360__
 #define __CPM_360__
 
-#include <linux/config.h>
 
 /* CPM Command register masks: */
 #define CPM_CR_RST	((ushort)0x8000)
diff --git a/include/asm-m68knommu/dma-mapping.h b/include/asm-m68knommu/dma-mapping.h
index a6c42ba..5622b85 100644
--- a/include/asm-m68knommu/dma-mapping.h
+++ b/include/asm-m68knommu/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_DMA_MAPPING_H
 #define _M68KNOMMU_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
diff --git a/include/asm-m68knommu/dma.h b/include/asm-m68knommu/dma.h
index 43e98c9..3338001 100644
--- a/include/asm-m68knommu/dma.h
+++ b/include/asm-m68knommu/dma.h
@@ -3,7 +3,6 @@
  
 //#define	DMA_DEBUG	1
 
-#include <linux/config.h>
 
 #ifdef CONFIG_COLDFIRE
 /*
diff --git a/include/asm-m68knommu/elf.h b/include/asm-m68knommu/elf.h
index 9919487..40b1ed6 100644
--- a/include/asm-m68knommu/elf.h
+++ b/include/asm-m68knommu/elf.h
@@ -5,7 +5,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/user.h>
 
diff --git a/include/asm-m68knommu/elia.h b/include/asm-m68knommu/elia.h
index f18b8e9..e037d4e 100644
--- a/include/asm-m68knommu/elia.h
+++ b/include/asm-m68knommu/elia.h
@@ -12,7 +12,6 @@
 #define	elia_h
 /****************************************************************************/
 
-#include <linux/config.h>
 #include <asm/coldfire.h>
 
 #ifdef CONFIG_eLIA
diff --git a/include/asm-m68knommu/entry.h b/include/asm-m68knommu/entry.h
index 06f5aa7..c2553d2 100644
--- a/include/asm-m68knommu/entry.h
+++ b/include/asm-m68knommu/entry.h
@@ -1,7 +1,6 @@
 #ifndef __M68KNOMMU_ENTRY_H
 #define __M68KNOMMU_ENTRY_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 
diff --git a/include/asm-m68knommu/fpu.h b/include/asm-m68knommu/fpu.h
index 2250829..b16b2e4 100644
--- a/include/asm-m68knommu/fpu.h
+++ b/include/asm-m68knommu/fpu.h
@@ -1,7 +1,6 @@
 #ifndef __M68KNOMMU_FPU_H
 #define __M68KNOMMU_FPU_H
 
-#include <linux/config.h>
 
 /*
  * MAX floating point unit state size (FSAVE/FRESTORE)
diff --git a/include/asm-m68knommu/hardirq.h b/include/asm-m68knommu/hardirq.h
index 476180f..980075b 100644
--- a/include/asm-m68knommu/hardirq.h
+++ b/include/asm-m68knommu/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __M68K_HARDIRQ_H
 #define __M68K_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <asm/irq.h>
diff --git a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
index e08f2ee..8df4cee 100644
--- a/include/asm-m68knommu/io.h
+++ b/include/asm-m68knommu/io.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * These are for ISA/PCI shared memory _only_ and should never be used
diff --git a/include/asm-m68knommu/irq.h b/include/asm-m68knommu/irq.h
index 20c48ec..5355727 100644
--- a/include/asm-m68knommu/irq.h
+++ b/include/asm-m68knommu/irq.h
@@ -1,7 +1,6 @@
 #ifndef _M68K_IRQ_H_
 #define _M68K_IRQ_H_
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_COLDFIRE
@@ -84,12 +83,8 @@
 /*
  * Some drivers want these entry points
  */
-#define enable_irq(x)	0
+#define enable_irq(x)	do { } while (0)
 #define disable_irq(x)	do { } while (0)
 #define disable_irq_nosync(x)	disable_irq(x)
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif /* _M68K_IRQ_H_ */
diff --git a/include/asm-m68knommu/m5206sim.h b/include/asm-m68knommu/m5206sim.h
index d1e7509..7e3594d 100644
--- a/include/asm-m68knommu/m5206sim.h
+++ b/include/asm-m68knommu/m5206sim.h
@@ -12,7 +12,6 @@
 #define	m5206sim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Define the 5206 SIM register set addresses.
diff --git a/include/asm-m68knommu/m520xsim.h b/include/asm-m68knommu/m520xsim.h
index 6dc6286..1dac22e 100644
--- a/include/asm-m68knommu/m520xsim.h
+++ b/include/asm-m68knommu/m520xsim.h
@@ -11,7 +11,6 @@
 #define m520xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *  Define the 5282 SIM register set addresses.
diff --git a/include/asm-m68knommu/m523xsim.h b/include/asm-m68knommu/m523xsim.h
index 926cfb8..bf39731 100644
--- a/include/asm-m68knommu/m523xsim.h
+++ b/include/asm-m68knommu/m523xsim.h
@@ -11,7 +11,6 @@
 #define	m523xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Define the 523x SIM register set addresses.
diff --git a/include/asm-m68knommu/m5249sim.h b/include/asm-m68knommu/m5249sim.h
index 9344f52..399814f 100644
--- a/include/asm-m68knommu/m5249sim.h
+++ b/include/asm-m68knommu/m5249sim.h
@@ -157,7 +157,7 @@
 	movel	%d0,0x180(%a1)			/* set PLL register */
 	nop
 
-#ifdef CONFIG_CLOCK_140MHz
+#if CONFIG_CLOCK_FREQ == 140000000
 	/*
 	 *	Set initial clock frequency. This assumes M5249C3 board
 	 *	is fitted with 11.2896MHz crystal. It will program the
diff --git a/include/asm-m68knommu/m5272sim.h b/include/asm-m68knommu/m5272sim.h
index b408753..6217edc 100644
--- a/include/asm-m68knommu/m5272sim.h
+++ b/include/asm-m68knommu/m5272sim.h
@@ -12,7 +12,6 @@
 #define	m5272sim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Define the 5272 SIM register set addresses.
diff --git a/include/asm-m68knommu/m527xsim.h b/include/asm-m68knommu/m527xsim.h
index e7878d0..1f63ab3 100644
--- a/include/asm-m68knommu/m527xsim.h
+++ b/include/asm-m68knommu/m527xsim.h
@@ -11,7 +11,6 @@
 #define	m527xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Define the 5270/5271 SIM register set addresses.
diff --git a/include/asm-m68knommu/m528xsim.h b/include/asm-m68knommu/m528xsim.h
index 610774a..1a3b1ae 100644
--- a/include/asm-m68knommu/m528xsim.h
+++ b/include/asm-m68knommu/m528xsim.h
@@ -11,7 +11,6 @@
 #define	m528xsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Define the 5280/5282 SIM register set addresses.
diff --git a/include/asm-m68knommu/m532xsim.h b/include/asm-m68knommu/m532xsim.h
new file mode 100644
index 0000000..1835fd2
--- /dev/null
+++ b/include/asm-m68knommu/m532xsim.h
@@ -0,0 +1,2238 @@
+/****************************************************************************/
+
+/*
+ *	m532xsim.h -- ColdFire 5329 registers
+ */
+
+/****************************************************************************/
+#ifndef	m532xsim_h
+#define	m532xsim_h
+/****************************************************************************/
+
+#define MCF_REG32(x) (*(volatile unsigned long  *)(x))
+#define MCF_REG16(x) (*(volatile unsigned short *)(x))
+#define MCF_REG08(x) (*(volatile unsigned char  *)(x))
+
+#define MCFINT_VECBASE      64
+#define MCFINT_UART0        26          /* Interrupt number for UART0 */
+#define MCFINT_UART1        27          /* Interrupt number for UART1 */
+
+#define MCF_WTM_WCR	MCF_REG16(0xFC098000)
+
+/*
+ *	Define the 532x SIM register set addresses.
+ */
+#define	MCFSIM_IPRL		0xFC048004
+#define	MCFSIM_IPRH		0xFC048000
+#define	MCFSIM_IPR		MCFSIM_IPRL
+#define	MCFSIM_IMRL		0xFC04800C
+#define	MCFSIM_IMRH		0xFC048008
+#define	MCFSIM_IMR		MCFSIM_IMRL
+#define	MCFSIM_ICR0		0xFC048040	
+#define	MCFSIM_ICR1		0xFC048041	
+#define	MCFSIM_ICR2		0xFC048042	
+#define	MCFSIM_ICR3		0xFC048043	
+#define	MCFSIM_ICR4		0xFC048044	
+#define	MCFSIM_ICR5		0xFC048045	
+#define	MCFSIM_ICR6		0xFC048046	
+#define	MCFSIM_ICR7		0xFC048047	
+#define	MCFSIM_ICR8		0xFC048048	
+#define	MCFSIM_ICR9		0xFC048049	
+#define	MCFSIM_ICR10		0xFC04804A
+#define	MCFSIM_ICR11		0xFC04804B
+
+/*
+ *	Some symbol defines for the above...
+ */
+#define	MCFSIM_SWDICR		MCFSIM_ICR0	/* Watchdog timer ICR */
+#define	MCFSIM_TIMER1ICR	MCFSIM_ICR1	/* Timer 1 ICR */
+#define	MCFSIM_TIMER2ICR	MCFSIM_ICR2	/* Timer 2 ICR */
+#define	MCFSIM_UART1ICR		MCFSIM_ICR4	/* UART 1 ICR */
+#define	MCFSIM_UART2ICR		MCFSIM_ICR5	/* UART 2 ICR */
+#define	MCFSIM_DMA0ICR		MCFSIM_ICR6	/* DMA 0 ICR */
+#define	MCFSIM_DMA1ICR		MCFSIM_ICR7	/* DMA 1 ICR */
+#define	MCFSIM_DMA2ICR		MCFSIM_ICR8	/* DMA 2 ICR */
+#define	MCFSIM_DMA3ICR		MCFSIM_ICR9	/* DMA 3 ICR */
+
+
+#define	MCFSIM_IMR_MASKALL	0xFFFFFFFF	/* All SIM intr sources */
+
+#define MCFSIM_IMR_SIMR0	0xFC04801C
+#define MCFSIM_IMR_SIMR1	0xFC04C01C
+#define MCFSIM_IMR_CIMR0	0xFC04801D
+#define MCFSIM_IMR_CIMR1	0xFC04C01D
+
+#define MCFSIM_ICR_TIMER1	(0xFC048040+32)
+#define MCFSIM_ICR_TIMER2	(0xFC048040+33)
+
+
+/*
+ *	Macro to set IMR register. It is 32 bits on the 5307.
+ */
+#define	mcf_getimr()		\
+	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR))
+
+#define	mcf_setimr(imr)		\
+	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr);
+
+#define	mcf_getipr()		\
+	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR))
+
+#define	mcf_getiprl()		\
+	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRL))
+
+#define	mcf_getiprh()		\
+	*((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRH))
+
+
+#define mcf_enable_irq0(irq)		\
+	*((volatile unsigned char*) (MCFSIM_IMR_CIMR0)) = (irq);
+
+#define mcf_enable_irq1(irq)		\
+	*((volatile unsigned char*) (MCFSIM_IMR_CIMR1)) = (irq);
+
+#define mcf_disable_irq0(irq)		\
+	*((volatile unsigned char*) (MCFSIM_IMR_SIMR0)) = (irq);
+
+#define mcf_disable_irq1(irq)		\
+	*((volatile unsigned char*) (MCFSIM_IMR_SIMR1)) = (irq);
+
+/*
+ *	Define the Cache register flags.
+ */
+#define	CACR_EC			(1<<31)
+#define	CACR_ESB		(1<<29)
+#define	CACR_DPI		(1<<28)
+#define	CACR_HLCK		(1<<27)
+#define	CACR_CINVA		(1<<24)
+#define	CACR_DNFB		(1<<10)
+#define	CACR_DCM_WTHRU		(0<<8)
+#define	CACR_DCM_WBACK		(1<<8)
+#define	CACR_DCM_OFF_PRE	(2<<8)
+#define	CACR_DCM_OFF_IMP	(3<<8)
+#define	CACR_DW			(1<<5)
+
+#define	ACR_BASE_POS		24
+#define	ACR_MASK_POS		16
+#define	ACR_ENABLE		(1<<15)
+#define	ACR_USER		(0<<13)
+#define	ACR_SUPER		(1<<13)
+#define	ACR_ANY			(2<<13)
+#define	ACR_CM_WTHRU		(0<<5)
+#define	ACR_CM_WBACK		(1<<5)
+#define	ACR_CM_OFF_PRE		(2<<5)
+#define	ACR_CM_OFF_IMP		(3<<5)
+#define	ACR_WPROTECT		(1<<2)
+
+/*********************************************************************
+ *
+ * Inter-IC (I2C) Module
+ *
+ *********************************************************************/
+
+/* Read/Write access macros for general use */
+#define MCF532x_I2C_I2ADR       (volatile u8 *) (0xFC058000) // Address 
+#define MCF532x_I2C_I2FDR       (volatile u8 *) (0xFC058004) // Freq Divider
+#define MCF532x_I2C_I2CR        (volatile u8 *) (0xFC058008) // Control
+#define MCF532x_I2C_I2SR        (volatile u8 *) (0xFC05800C) // Status
+#define MCF532x_I2C_I2DR        (volatile u8 *) (0xFC058010) // Data I/O
+
+/* Bit level definitions and macros */
+#define MCF532x_I2C_I2ADR_ADDR(x)                       (((x)&0x7F)<<0x01)
+
+#define MCF532x_I2C_I2FDR_IC(x)                         (((x)&0x3F))
+
+#define MCF532x_I2C_I2CR_IEN    (0x80)	// I2C enable
+#define MCF532x_I2C_I2CR_IIEN   (0x40)  // interrupt enable
+#define MCF532x_I2C_I2CR_MSTA   (0x20)  // master/slave mode
+#define MCF532x_I2C_I2CR_MTX    (0x10)  // transmit/receive mode
+#define MCF532x_I2C_I2CR_TXAK   (0x08)  // transmit acknowledge enable
+#define MCF532x_I2C_I2CR_RSTA   (0x04)  // repeat start
+
+#define MCF532x_I2C_I2SR_ICF    (0x80)  // data transfer bit
+#define MCF532x_I2C_I2SR_IAAS   (0x40)  // I2C addressed as a slave
+#define MCF532x_I2C_I2SR_IBB    (0x20)  // I2C bus busy
+#define MCF532x_I2C_I2SR_IAL    (0x10)  // aribitration lost
+#define MCF532x_I2C_I2SR_SRW    (0x04)  // slave read/write
+#define MCF532x_I2C_I2SR_IIF    (0x02)  // I2C interrupt
+#define MCF532x_I2C_I2SR_RXAK   (0x01)  // received acknowledge
+
+#define MCF532x_PAR_FECI2C	(volatile u8 *) (0xFC0A4053)
+
+
+/*
+ *	The M5329EVB board needs a help getting its devices initialized 
+ *	at kernel start time if dBUG doesn't set it up (for example 
+ *	it is not used), so we need to do it manually.
+ */
+#ifdef __ASSEMBLER__
+.macro m5329EVB_setup
+	movel	#0xFC098000, %a7
+	movel	#0x0, (%a7)
+#define CORE_SRAM	0x80000000	
+#define CORE_SRAM_SIZE	0x8000
+	movel	#CORE_SRAM, %d0
+	addl	#0x221, %d0
+	movec	%d0,%RAMBAR1
+	movel	#CORE_SRAM, %sp
+	addl	#CORE_SRAM_SIZE, %sp
+	jsr	sysinit
+.endm
+#define	PLATFORM_SETUP	m5329EVB_setup
+
+#endif /* __ASSEMBLER__ */
+
+/*********************************************************************
+ *
+ * Chip Configuration Module (CCM)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_CCM_CCR               MCF_REG16(0xFC0A0004)
+#define MCF_CCM_RCON              MCF_REG16(0xFC0A0008)
+#define MCF_CCM_CIR               MCF_REG16(0xFC0A000A)
+#define MCF_CCM_MISCCR            MCF_REG16(0xFC0A0010)
+#define MCF_CCM_CDR               MCF_REG16(0xFC0A0012)
+#define MCF_CCM_UHCSR             MCF_REG16(0xFC0A0014)
+#define MCF_CCM_UOCSR             MCF_REG16(0xFC0A0016)
+
+/* Bit definitions and macros for MCF_CCM_CCR */
+#define MCF_CCM_CCR_RESERVED      (0x0001)
+#define MCF_CCM_CCR_PLL_MODE      (0x0003)
+#define MCF_CCM_CCR_OSC_MODE      (0x0005)
+#define MCF_CCM_CCR_BOOTPS(x)     (((x)&0x0003)<<3|0x0001)
+#define MCF_CCM_CCR_LOAD          (0x0021)
+#define MCF_CCM_CCR_LIMP          (0x0041)
+#define MCF_CCM_CCR_CSC(x)        (((x)&0x0003)<<8|0x0001)
+
+/* Bit definitions and macros for MCF_CCM_RCON */
+#define MCF_CCM_RCON_RESERVED     (0x0001)
+#define MCF_CCM_RCON_PLL_MODE     (0x0003)
+#define MCF_CCM_RCON_OSC_MODE     (0x0005)
+#define MCF_CCM_RCON_BOOTPS(x)    (((x)&0x0003)<<3|0x0001)
+#define MCF_CCM_RCON_LOAD         (0x0021)
+#define MCF_CCM_RCON_LIMP         (0x0041)
+#define MCF_CCM_RCON_CSC(x)       (((x)&0x0003)<<8|0x0001)
+
+/* Bit definitions and macros for MCF_CCM_CIR */
+#define MCF_CCM_CIR_PRN(x)        (((x)&0x003F)<<0)
+#define MCF_CCM_CIR_PIN(x)        (((x)&0x03FF)<<6)
+
+/* Bit definitions and macros for MCF_CCM_MISCCR */
+#define MCF_CCM_MISCCR_USBSRC     (0x0001)
+#define MCF_CCM_MISCCR_USBDIV     (0x0002)
+#define MCF_CCM_MISCCR_SSI_SRC    (0x0010)
+#define MCF_CCM_MISCCR_TIM_DMA   (0x0020)
+#define MCF_CCM_MISCCR_SSI_PUS    (0x0040)
+#define MCF_CCM_MISCCR_SSI_PUE    (0x0080)
+#define MCF_CCM_MISCCR_LCD_CHEN   (0x0100)
+#define MCF_CCM_MISCCR_LIMP       (0x1000)
+#define MCF_CCM_MISCCR_PLL_LOCK   (0x2000)
+
+/* Bit definitions and macros for MCF_CCM_CDR */
+#define MCF_CCM_CDR_SSIDIV(x)     (((x)&0x000F)<<0)
+#define MCF_CCM_CDR_LPDIV(x)      (((x)&0x000F)<<8)
+
+/* Bit definitions and macros for MCF_CCM_UHCSR */
+#define MCF_CCM_UHCSR_XPDE        (0x0001)
+#define MCF_CCM_UHCSR_UHMIE       (0x0002)
+#define MCF_CCM_UHCSR_WKUP        (0x0004)
+#define MCF_CCM_UHCSR_PORTIND(x)  (((x)&0x0003)<<14)
+
+/* Bit definitions and macros for MCF_CCM_UOCSR */
+#define MCF_CCM_UOCSR_XPDE        (0x0001)
+#define MCF_CCM_UOCSR_UOMIE       (0x0002)
+#define MCF_CCM_UOCSR_WKUP        (0x0004)
+#define MCF_CCM_UOCSR_PWRFLT      (0x0008)
+#define MCF_CCM_UOCSR_SEND        (0x0010)
+#define MCF_CCM_UOCSR_VVLD        (0x0020)
+#define MCF_CCM_UOCSR_BVLD        (0x0040)
+#define MCF_CCM_UOCSR_AVLD        (0x0080)
+#define MCF_CCM_UOCSR_DPPU        (0x0100)
+#define MCF_CCM_UOCSR_DCR_VBUS    (0x0200)
+#define MCF_CCM_UOCSR_CRG_VBUS    (0x0400)
+#define MCF_CCM_UOCSR_DRV_VBUS    (0x0800)
+#define MCF_CCM_UOCSR_DMPD        (0x1000)
+#define MCF_CCM_UOCSR_DPPD        (0x2000)
+#define MCF_CCM_UOCSR_PORTIND(x)  (((x)&0x0003)<<14)
+
+/*********************************************************************
+ *
+ * DMA Timers (DTIM)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_DTIM0_DTMR           MCF_REG16(0xFC070000)
+#define MCF_DTIM0_DTXMR          MCF_REG08(0xFC070002)
+#define MCF_DTIM0_DTER           MCF_REG08(0xFC070003)
+#define MCF_DTIM0_DTRR           MCF_REG32(0xFC070004)
+#define MCF_DTIM0_DTCR           MCF_REG32(0xFC070008)
+#define MCF_DTIM0_DTCN           MCF_REG32(0xFC07000C)
+#define MCF_DTIM1_DTMR           MCF_REG16(0xFC074000)
+#define MCF_DTIM1_DTXMR          MCF_REG08(0xFC074002)
+#define MCF_DTIM1_DTER           MCF_REG08(0xFC074003)
+#define MCF_DTIM1_DTRR           MCF_REG32(0xFC074004)
+#define MCF_DTIM1_DTCR           MCF_REG32(0xFC074008)
+#define MCF_DTIM1_DTCN           MCF_REG32(0xFC07400C)
+#define MCF_DTIM2_DTMR           MCF_REG16(0xFC078000)
+#define MCF_DTIM2_DTXMR          MCF_REG08(0xFC078002)
+#define MCF_DTIM2_DTER           MCF_REG08(0xFC078003)
+#define MCF_DTIM2_DTRR           MCF_REG32(0xFC078004)
+#define MCF_DTIM2_DTCR           MCF_REG32(0xFC078008)
+#define MCF_DTIM2_DTCN           MCF_REG32(0xFC07800C)
+#define MCF_DTIM3_DTMR           MCF_REG16(0xFC07C000)
+#define MCF_DTIM3_DTXMR          MCF_REG08(0xFC07C002)
+#define MCF_DTIM3_DTER           MCF_REG08(0xFC07C003)
+#define MCF_DTIM3_DTRR           MCF_REG32(0xFC07C004)
+#define MCF_DTIM3_DTCR           MCF_REG32(0xFC07C008)
+#define MCF_DTIM3_DTCN           MCF_REG32(0xFC07C00C)
+#define MCF_DTIM_DTMR(x)         MCF_REG16(0xFC070000+((x)*0x4000))
+#define MCF_DTIM_DTXMR(x)        MCF_REG08(0xFC070002+((x)*0x4000))
+#define MCF_DTIM_DTER(x)         MCF_REG08(0xFC070003+((x)*0x4000))
+#define MCF_DTIM_DTRR(x)         MCF_REG32(0xFC070004+((x)*0x4000))
+#define MCF_DTIM_DTCR(x)         MCF_REG32(0xFC070008+((x)*0x4000))
+#define MCF_DTIM_DTCN(x)         MCF_REG32(0xFC07000C+((x)*0x4000))
+
+/* Bit definitions and macros for MCF_DTIM_DTMR */
+#define MCF_DTIM_DTMR_RST        (0x0001)
+#define MCF_DTIM_DTMR_CLK(x)     (((x)&0x0003)<<1)
+#define MCF_DTIM_DTMR_FRR        (0x0008)
+#define MCF_DTIM_DTMR_ORRI       (0x0010)
+#define MCF_DTIM_DTMR_OM         (0x0020)
+#define MCF_DTIM_DTMR_CE(x)      (((x)&0x0003)<<6)
+#define MCF_DTIM_DTMR_PS(x)      (((x)&0x00FF)<<8)
+#define MCF_DTIM_DTMR_CE_ANY     (0x00C0)
+#define MCF_DTIM_DTMR_CE_FALL    (0x0080)
+#define MCF_DTIM_DTMR_CE_RISE    (0x0040)
+#define MCF_DTIM_DTMR_CE_NONE    (0x0000)
+#define MCF_DTIM_DTMR_CLK_DTIN   (0x0006)
+#define MCF_DTIM_DTMR_CLK_DIV16  (0x0004)
+#define MCF_DTIM_DTMR_CLK_DIV1   (0x0002)
+#define MCF_DTIM_DTMR_CLK_STOP   (0x0000)
+
+/* Bit definitions and macros for MCF_DTIM_DTXMR */
+#define MCF_DTIM_DTXMR_MODE16    (0x01)
+#define MCF_DTIM_DTXMR_DMAEN     (0x80)
+
+/* Bit definitions and macros for MCF_DTIM_DTER */
+#define MCF_DTIM_DTER_CAP        (0x01)
+#define MCF_DTIM_DTER_REF        (0x02)
+
+/* Bit definitions and macros for MCF_DTIM_DTRR */
+#define MCF_DTIM_DTRR_REF(x)     (((x)&0xFFFFFFFF)<<0)
+
+/* Bit definitions and macros for MCF_DTIM_DTCR */
+#define MCF_DTIM_DTCR_CAP(x)     (((x)&0xFFFFFFFF)<<0)
+
+/* Bit definitions and macros for MCF_DTIM_DTCN */
+#define MCF_DTIM_DTCN_CNT(x)     (((x)&0xFFFFFFFF)<<0)
+
+/*********************************************************************
+ *
+ * FlexBus Chip Selects (FBCS)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_FBCS0_CSAR		MCF_REG32(0xFC008000)
+#define MCF_FBCS0_CSMR		MCF_REG32(0xFC008004)
+#define MCF_FBCS0_CSCR		MCF_REG32(0xFC008008)
+#define MCF_FBCS1_CSAR		MCF_REG32(0xFC00800C)
+#define MCF_FBCS1_CSMR		MCF_REG32(0xFC008010)
+#define MCF_FBCS1_CSCR		MCF_REG32(0xFC008014)
+#define MCF_FBCS2_CSAR		MCF_REG32(0xFC008018)
+#define MCF_FBCS2_CSMR		MCF_REG32(0xFC00801C)
+#define MCF_FBCS2_CSCR		MCF_REG32(0xFC008020)
+#define MCF_FBCS3_CSAR		MCF_REG32(0xFC008024)
+#define MCF_FBCS3_CSMR		MCF_REG32(0xFC008028)
+#define MCF_FBCS3_CSCR		MCF_REG32(0xFC00802C)
+#define MCF_FBCS4_CSAR		MCF_REG32(0xFC008030)
+#define MCF_FBCS4_CSMR		MCF_REG32(0xFC008034)
+#define MCF_FBCS4_CSCR		MCF_REG32(0xFC008038)
+#define MCF_FBCS5_CSAR		MCF_REG32(0xFC00803C)
+#define MCF_FBCS5_CSMR		MCF_REG32(0xFC008040)
+#define MCF_FBCS5_CSCR		MCF_REG32(0xFC008044)
+#define MCF_FBCS_CSAR(x)	MCF_REG32(0xFC008000+((x)*0x00C))
+#define MCF_FBCS_CSMR(x)	MCF_REG32(0xFC008004+((x)*0x00C))
+#define MCF_FBCS_CSCR(x)	MCF_REG32(0xFC008008+((x)*0x00C))
+
+/* Bit definitions and macros for MCF_FBCS_CSAR */
+#define MCF_FBCS_CSAR_BA(x)	((x)&0xFFFF0000)
+
+/* Bit definitions and macros for MCF_FBCS_CSMR */
+#define MCF_FBCS_CSMR_V		(0x00000001)
+#define MCF_FBCS_CSMR_WP	(0x00000100)
+#define MCF_FBCS_CSMR_BAM(x)	(((x)&0x0000FFFF)<<16)
+#define MCF_FBCS_CSMR_BAM_4G	(0xFFFF0000)
+#define MCF_FBCS_CSMR_BAM_2G	(0x7FFF0000)
+#define MCF_FBCS_CSMR_BAM_1G	(0x3FFF0000)
+#define MCF_FBCS_CSMR_BAM_1024M	(0x3FFF0000)
+#define MCF_FBCS_CSMR_BAM_512M	(0x1FFF0000)
+#define MCF_FBCS_CSMR_BAM_256M	(0x0FFF0000)
+#define MCF_FBCS_CSMR_BAM_128M	(0x07FF0000)
+#define MCF_FBCS_CSMR_BAM_64M	(0x03FF0000)
+#define MCF_FBCS_CSMR_BAM_32M	(0x01FF0000)
+#define MCF_FBCS_CSMR_BAM_16M	(0x00FF0000)
+#define MCF_FBCS_CSMR_BAM_8M	(0x007F0000)
+#define MCF_FBCS_CSMR_BAM_4M	(0x003F0000)
+#define MCF_FBCS_CSMR_BAM_2M	(0x001F0000)
+#define MCF_FBCS_CSMR_BAM_1M	(0x000F0000)
+#define MCF_FBCS_CSMR_BAM_1024K	(0x000F0000)
+#define MCF_FBCS_CSMR_BAM_512K	(0x00070000)
+#define MCF_FBCS_CSMR_BAM_256K	(0x00030000)
+#define MCF_FBCS_CSMR_BAM_128K	(0x00010000)
+#define MCF_FBCS_CSMR_BAM_64K	(0x00000000)
+
+/* Bit definitions and macros for MCF_FBCS_CSCR */
+#define MCF_FBCS_CSCR_BSTW	(0x00000008)
+#define MCF_FBCS_CSCR_BSTR	(0x00000010)
+#define MCF_FBCS_CSCR_BEM	(0x00000020)
+#define MCF_FBCS_CSCR_PS(x)	(((x)&0x00000003)<<6)
+#define MCF_FBCS_CSCR_AA	(0x00000100)
+#define MCF_FBCS_CSCR_SBM	(0x00000200)
+#define MCF_FBCS_CSCR_WS(x)	(((x)&0x0000003F)<<10)
+#define MCF_FBCS_CSCR_WRAH(x)	(((x)&0x00000003)<<16)
+#define MCF_FBCS_CSCR_RDAH(x)	(((x)&0x00000003)<<18)
+#define MCF_FBCS_CSCR_ASET(x)	(((x)&0x00000003)<<20)
+#define MCF_FBCS_CSCR_SWSEN	(0x00800000)
+#define MCF_FBCS_CSCR_SWS(x)	(((x)&0x0000003F)<<26)
+#define MCF_FBCS_CSCR_PS_8	(0x0040)
+#define MCF_FBCS_CSCR_PS_16	(0x0080)
+#define MCF_FBCS_CSCR_PS_32	(0x0000)
+
+/*********************************************************************
+ *
+ * General Purpose I/O (GPIO)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_GPIO_PODR_FECH		MCF_REG08(0xFC0A4000)
+#define MCF_GPIO_PODR_FECL		MCF_REG08(0xFC0A4001)
+#define MCF_GPIO_PODR_SSI		MCF_REG08(0xFC0A4002)
+#define MCF_GPIO_PODR_BUSCTL		MCF_REG08(0xFC0A4003)
+#define MCF_GPIO_PODR_BE		MCF_REG08(0xFC0A4004)
+#define MCF_GPIO_PODR_CS		MCF_REG08(0xFC0A4005)
+#define MCF_GPIO_PODR_PWM		MCF_REG08(0xFC0A4006)
+#define MCF_GPIO_PODR_FECI2C		MCF_REG08(0xFC0A4007)
+#define MCF_GPIO_PODR_UART		MCF_REG08(0xFC0A4009)
+#define MCF_GPIO_PODR_QSPI		MCF_REG08(0xFC0A400A)
+#define MCF_GPIO_PODR_TIMER		MCF_REG08(0xFC0A400B)
+#define MCF_GPIO_PODR_LCDDATAH		MCF_REG08(0xFC0A400D)
+#define MCF_GPIO_PODR_LCDDATAM		MCF_REG08(0xFC0A400E)
+#define MCF_GPIO_PODR_LCDDATAL		MCF_REG08(0xFC0A400F)
+#define MCF_GPIO_PODR_LCDCTLH		MCF_REG08(0xFC0A4010)
+#define MCF_GPIO_PODR_LCDCTLL		MCF_REG08(0xFC0A4011)
+#define MCF_GPIO_PDDR_FECH		MCF_REG08(0xFC0A4014)
+#define MCF_GPIO_PDDR_FECL		MCF_REG08(0xFC0A4015)
+#define MCF_GPIO_PDDR_SSI		MCF_REG08(0xFC0A4016)
+#define MCF_GPIO_PDDR_BUSCTL		MCF_REG08(0xFC0A4017)
+#define MCF_GPIO_PDDR_BE		MCF_REG08(0xFC0A4018)
+#define MCF_GPIO_PDDR_CS		MCF_REG08(0xFC0A4019)
+#define MCF_GPIO_PDDR_PWM		MCF_REG08(0xFC0A401A)
+#define MCF_GPIO_PDDR_FECI2C		MCF_REG08(0xFC0A401B)
+#define MCF_GPIO_PDDR_UART		MCF_REG08(0xFC0A401C)
+#define MCF_GPIO_PDDR_QSPI		MCF_REG08(0xFC0A401E)
+#define MCF_GPIO_PDDR_TIMER		MCF_REG08(0xFC0A401F)
+#define MCF_GPIO_PDDR_LCDDATAH		MCF_REG08(0xFC0A4021)
+#define MCF_GPIO_PDDR_LCDDATAM		MCF_REG08(0xFC0A4022)
+#define MCF_GPIO_PDDR_LCDDATAL		MCF_REG08(0xFC0A4023)
+#define MCF_GPIO_PDDR_LCDCTLH		MCF_REG08(0xFC0A4024)
+#define MCF_GPIO_PDDR_LCDCTLL		MCF_REG08(0xFC0A4025)
+#define MCF_GPIO_PPDSDR_FECH		MCF_REG08(0xFC0A4028)
+#define MCF_GPIO_PPDSDR_FECL		MCF_REG08(0xFC0A4029)
+#define MCF_GPIO_PPDSDR_SSI		MCF_REG08(0xFC0A402A)
+#define MCF_GPIO_PPDSDR_BUSCTL		MCF_REG08(0xFC0A402B)
+#define MCF_GPIO_PPDSDR_BE		MCF_REG08(0xFC0A402C)
+#define MCF_GPIO_PPDSDR_CS		MCF_REG08(0xFC0A402D)
+#define MCF_GPIO_PPDSDR_PWM		MCF_REG08(0xFC0A402E)
+#define MCF_GPIO_PPDSDR_FECI2C		MCF_REG08(0xFC0A402F)
+#define MCF_GPIO_PPDSDR_UART		MCF_REG08(0xFC0A4031)
+#define MCF_GPIO_PPDSDR_QSPI		MCF_REG08(0xFC0A4032)
+#define MCF_GPIO_PPDSDR_TIMER		MCF_REG08(0xFC0A4033)
+#define MCF_GPIO_PPDSDR_LCDDATAH	MCF_REG08(0xFC0A4035)
+#define MCF_GPIO_PPDSDR_LCDDATAM	MCF_REG08(0xFC0A4036)
+#define MCF_GPIO_PPDSDR_LCDDATAL	MCF_REG08(0xFC0A4037)
+#define MCF_GPIO_PPDSDR_LCDCTLH		MCF_REG08(0xFC0A4038)
+#define MCF_GPIO_PPDSDR_LCDCTLL		MCF_REG08(0xFC0A4039)
+#define MCF_GPIO_PCLRR_FECH		MCF_REG08(0xFC0A403C)
+#define MCF_GPIO_PCLRR_FECL		MCF_REG08(0xFC0A403D)
+#define MCF_GPIO_PCLRR_SSI		MCF_REG08(0xFC0A403E)
+#define MCF_GPIO_PCLRR_BUSCTL		MCF_REG08(0xFC0A403F)
+#define MCF_GPIO_PCLRR_BE		MCF_REG08(0xFC0A4040)
+#define MCF_GPIO_PCLRR_CS		MCF_REG08(0xFC0A4041)
+#define MCF_GPIO_PCLRR_PWM		MCF_REG08(0xFC0A4042)
+#define MCF_GPIO_PCLRR_FECI2C		MCF_REG08(0xFC0A4043)
+#define MCF_GPIO_PCLRR_UART		MCF_REG08(0xFC0A4045)
+#define MCF_GPIO_PCLRR_QSPI		MCF_REG08(0xFC0A4046)
+#define MCF_GPIO_PCLRR_TIMER		MCF_REG08(0xFC0A4047)
+#define MCF_GPIO_PCLRR_LCDDATAH		MCF_REG08(0xFC0A4049)
+#define MCF_GPIO_PCLRR_LCDDATAM		MCF_REG08(0xFC0A404A)
+#define MCF_GPIO_PCLRR_LCDDATAL		MCF_REG08(0xFC0A404B)
+#define MCF_GPIO_PCLRR_LCDCTLH		MCF_REG08(0xFC0A404C)
+#define MCF_GPIO_PCLRR_LCDCTLL		MCF_REG08(0xFC0A404D)
+#define MCF_GPIO_PAR_FEC		MCF_REG08(0xFC0A4050)
+#define MCF_GPIO_PAR_PWM		MCF_REG08(0xFC0A4051)
+#define MCF_GPIO_PAR_BUSCTL		MCF_REG08(0xFC0A4052)
+#define MCF_GPIO_PAR_FECI2C		MCF_REG08(0xFC0A4053)
+#define MCF_GPIO_PAR_BE			MCF_REG08(0xFC0A4054)
+#define MCF_GPIO_PAR_CS			MCF_REG08(0xFC0A4055)
+#define MCF_GPIO_PAR_SSI		MCF_REG16(0xFC0A4056)
+#define MCF_GPIO_PAR_UART		MCF_REG16(0xFC0A4058)
+#define MCF_GPIO_PAR_QSPI		MCF_REG16(0xFC0A405A)
+#define MCF_GPIO_PAR_TIMER		MCF_REG08(0xFC0A405C)
+#define MCF_GPIO_PAR_LCDDATA		MCF_REG08(0xFC0A405D)
+#define MCF_GPIO_PAR_LCDCTL		MCF_REG16(0xFC0A405E)
+#define MCF_GPIO_PAR_IRQ		MCF_REG16(0xFC0A4060)
+#define MCF_GPIO_MSCR_FLEXBUS		MCF_REG08(0xFC0A4064)
+#define MCF_GPIO_MSCR_SDRAM		MCF_REG08(0xFC0A4065)
+#define MCF_GPIO_DSCR_I2C		MCF_REG08(0xFC0A4068)
+#define MCF_GPIO_DSCR_PWM		MCF_REG08(0xFC0A4069)
+#define MCF_GPIO_DSCR_FEC		MCF_REG08(0xFC0A406A)
+#define MCF_GPIO_DSCR_UART		MCF_REG08(0xFC0A406B)
+#define MCF_GPIO_DSCR_QSPI		MCF_REG08(0xFC0A406C)
+#define MCF_GPIO_DSCR_TIMER		MCF_REG08(0xFC0A406D)
+#define MCF_GPIO_DSCR_SSI		MCF_REG08(0xFC0A406E)
+#define MCF_GPIO_DSCR_LCD		MCF_REG08(0xFC0A406F)
+#define MCF_GPIO_DSCR_DEBUG		MCF_REG08(0xFC0A4070)
+#define MCF_GPIO_DSCR_CLKRST		MCF_REG08(0xFC0A4071)
+#define MCF_GPIO_DSCR_IRQ		MCF_REG08(0xFC0A4072)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_FECH */
+#define MCF_GPIO_PODR_FECH_PODR_FECH0              (0x01)
+#define MCF_GPIO_PODR_FECH_PODR_FECH1              (0x02)
+#define MCF_GPIO_PODR_FECH_PODR_FECH2              (0x04)
+#define MCF_GPIO_PODR_FECH_PODR_FECH3              (0x08)
+#define MCF_GPIO_PODR_FECH_PODR_FECH4              (0x10)
+#define MCF_GPIO_PODR_FECH_PODR_FECH5              (0x20)
+#define MCF_GPIO_PODR_FECH_PODR_FECH6              (0x40)
+#define MCF_GPIO_PODR_FECH_PODR_FECH7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_FECL */
+#define MCF_GPIO_PODR_FECL_PODR_FECL0              (0x01)
+#define MCF_GPIO_PODR_FECL_PODR_FECL1              (0x02)
+#define MCF_GPIO_PODR_FECL_PODR_FECL2              (0x04)
+#define MCF_GPIO_PODR_FECL_PODR_FECL3              (0x08)
+#define MCF_GPIO_PODR_FECL_PODR_FECL4              (0x10)
+#define MCF_GPIO_PODR_FECL_PODR_FECL5              (0x20)
+#define MCF_GPIO_PODR_FECL_PODR_FECL6              (0x40)
+#define MCF_GPIO_PODR_FECL_PODR_FECL7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_SSI */
+#define MCF_GPIO_PODR_SSI_PODR_SSI0                (0x01)
+#define MCF_GPIO_PODR_SSI_PODR_SSI1                (0x02)
+#define MCF_GPIO_PODR_SSI_PODR_SSI2                (0x04)
+#define MCF_GPIO_PODR_SSI_PODR_SSI3                (0x08)
+#define MCF_GPIO_PODR_SSI_PODR_SSI4                (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_BUSCTL */
+#define MCF_GPIO_PODR_BUSCTL_POSDR_BUSCTL0         (0x01)
+#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL1          (0x02)
+#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL2          (0x04)
+#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_BE */
+#define MCF_GPIO_PODR_BE_PODR_BE0                  (0x01)
+#define MCF_GPIO_PODR_BE_PODR_BE1                  (0x02)
+#define MCF_GPIO_PODR_BE_PODR_BE2                  (0x04)
+#define MCF_GPIO_PODR_BE_PODR_BE3                  (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_CS */
+#define MCF_GPIO_PODR_CS_PODR_CS1                  (0x02)
+#define MCF_GPIO_PODR_CS_PODR_CS2                  (0x04)
+#define MCF_GPIO_PODR_CS_PODR_CS3                  (0x08)
+#define MCF_GPIO_PODR_CS_PODR_CS4                  (0x10)
+#define MCF_GPIO_PODR_CS_PODR_CS5                  (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_PWM */
+#define MCF_GPIO_PODR_PWM_PODR_PWM2                (0x04)
+#define MCF_GPIO_PODR_PWM_PODR_PWM3                (0x08)
+#define MCF_GPIO_PODR_PWM_PODR_PWM4                (0x10)
+#define MCF_GPIO_PODR_PWM_PODR_PWM5                (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_FECI2C */
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C0          (0x01)
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C1          (0x02)
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C2          (0x04)
+#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_UART */
+#define MCF_GPIO_PODR_UART_PODR_UART0              (0x01)
+#define MCF_GPIO_PODR_UART_PODR_UART1              (0x02)
+#define MCF_GPIO_PODR_UART_PODR_UART2              (0x04)
+#define MCF_GPIO_PODR_UART_PODR_UART3              (0x08)
+#define MCF_GPIO_PODR_UART_PODR_UART4              (0x10)
+#define MCF_GPIO_PODR_UART_PODR_UART5              (0x20)
+#define MCF_GPIO_PODR_UART_PODR_UART6              (0x40)
+#define MCF_GPIO_PODR_UART_PODR_UART7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_QSPI */
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI0              (0x01)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI1              (0x02)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI2              (0x04)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI3              (0x08)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI4              (0x10)
+#define MCF_GPIO_PODR_QSPI_PODR_QSPI5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_TIMER */
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER0            (0x01)
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER1            (0x02)
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER2            (0x04)
+#define MCF_GPIO_PODR_TIMER_PODR_TIMER3            (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAH */
+#define MCF_GPIO_PODR_LCDDATAH_PODR_LCDDATAH0      (0x01)
+#define MCF_GPIO_PODR_LCDDATAH_PODR_LCDDATAH1      (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAM */
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM0      (0x01)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM1      (0x02)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM2      (0x04)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM3      (0x08)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM4      (0x10)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM5      (0x20)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM6      (0x40)
+#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAL */
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL0      (0x01)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL1      (0x02)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL2      (0x04)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL3      (0x08)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL4      (0x10)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL5      (0x20)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL6      (0x40)
+#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDCTLH */
+#define MCF_GPIO_PODR_LCDCTLH_PODR_LCDCTLH0        (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PODR_LCDCTLL */
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL0        (0x01)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL1        (0x02)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL2        (0x04)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL3        (0x08)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL4        (0x10)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL5        (0x20)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL6        (0x40)
+#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL7        (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_FECH */
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH0              (0x01)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH1              (0x02)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH2              (0x04)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH3              (0x08)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH4              (0x10)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH5              (0x20)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH6              (0x40)
+#define MCF_GPIO_PDDR_FECH_PDDR_FECH7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_FECL */
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL0              (0x01)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL1              (0x02)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL2              (0x04)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL3              (0x08)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL4              (0x10)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL5              (0x20)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL6              (0x40)
+#define MCF_GPIO_PDDR_FECL_PDDR_FECL7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_SSI */
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI0                (0x01)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI1                (0x02)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI2                (0x04)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI3                (0x08)
+#define MCF_GPIO_PDDR_SSI_PDDR_SSI4                (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_BUSCTL */
+#define MCF_GPIO_PDDR_BUSCTL_POSDR_BUSCTL0         (0x01)
+#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL1          (0x02)
+#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL2          (0x04)
+#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_BE */
+#define MCF_GPIO_PDDR_BE_PDDR_BE0                  (0x01)
+#define MCF_GPIO_PDDR_BE_PDDR_BE1                  (0x02)
+#define MCF_GPIO_PDDR_BE_PDDR_BE2                  (0x04)
+#define MCF_GPIO_PDDR_BE_PDDR_BE3                  (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_CS */
+#define MCF_GPIO_PDDR_CS_PDDR_CS1                  (0x02)
+#define MCF_GPIO_PDDR_CS_PDDR_CS2                  (0x04)
+#define MCF_GPIO_PDDR_CS_PDDR_CS3                  (0x08)
+#define MCF_GPIO_PDDR_CS_PDDR_CS4                  (0x10)
+#define MCF_GPIO_PDDR_CS_PDDR_CS5                  (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_PWM */
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM2                (0x04)
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM3                (0x08)
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM4                (0x10)
+#define MCF_GPIO_PDDR_PWM_PDDR_PWM5                (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_FECI2C */
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0          (0x01)
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1          (0x02)
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C2          (0x04)
+#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_UART */
+#define MCF_GPIO_PDDR_UART_PDDR_UART0              (0x01)
+#define MCF_GPIO_PDDR_UART_PDDR_UART1              (0x02)
+#define MCF_GPIO_PDDR_UART_PDDR_UART2              (0x04)
+#define MCF_GPIO_PDDR_UART_PDDR_UART3              (0x08)
+#define MCF_GPIO_PDDR_UART_PDDR_UART4              (0x10)
+#define MCF_GPIO_PDDR_UART_PDDR_UART5              (0x20)
+#define MCF_GPIO_PDDR_UART_PDDR_UART6              (0x40)
+#define MCF_GPIO_PDDR_UART_PDDR_UART7              (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_QSPI */
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI0              (0x01)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI1              (0x02)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI2              (0x04)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI3              (0x08)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI4              (0x10)
+#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_TIMER */
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER0            (0x01)
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER1            (0x02)
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER2            (0x04)
+#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER3            (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAH */
+#define MCF_GPIO_PDDR_LCDDATAH_PDDR_LCDDATAH0      (0x01)
+#define MCF_GPIO_PDDR_LCDDATAH_PDDR_LCDDATAH1      (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAM */
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM0      (0x01)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM1      (0x02)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM2      (0x04)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM3      (0x08)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM4      (0x10)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM5      (0x20)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM6      (0x40)
+#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAL */
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL0      (0x01)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL1      (0x02)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL2      (0x04)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL3      (0x08)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL4      (0x10)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL5      (0x20)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL6      (0x40)
+#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDCTLH */
+#define MCF_GPIO_PDDR_LCDCTLH_PDDR_LCDCTLH0        (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PDDR_LCDCTLL */
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL0        (0x01)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL1        (0x02)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL2        (0x04)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL3        (0x08)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL4        (0x10)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL5        (0x20)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL6        (0x40)
+#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL7        (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECH */
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH0          (0x01)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH1          (0x02)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH2          (0x04)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH3          (0x08)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH4          (0x10)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH5          (0x20)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH6          (0x40)
+#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH7          (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECL */
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL0          (0x01)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL1          (0x02)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL2          (0x04)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL3          (0x08)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL4          (0x10)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL5          (0x20)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL6          (0x40)
+#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL7          (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_SSI */
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI0            (0x01)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI1            (0x02)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI2            (0x04)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI3            (0x08)
+#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI4            (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_BUSCTL */
+#define MCF_GPIO_PPDSDR_BUSCTL_POSDR_BUSCTL0       (0x01)
+#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL1      (0x02)
+#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL2      (0x04)
+#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL3      (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_BE */
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE0              (0x01)
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE1              (0x02)
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE2              (0x04)
+#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE3              (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_CS */
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS1              (0x02)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS2              (0x04)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS3              (0x08)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS4              (0x10)
+#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_PWM */
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM2            (0x04)
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM3            (0x08)
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM4            (0x10)
+#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM5            (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECI2C */
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C0      (0x01)
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C1      (0x02)
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C2      (0x04)
+#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C3      (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_UART */
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART0          (0x01)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART1          (0x02)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART2          (0x04)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART3          (0x08)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART4          (0x10)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART5          (0x20)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART6          (0x40)
+#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART7          (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_QSPI */
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI0          (0x01)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI1          (0x02)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI2          (0x04)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI3          (0x08)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI4          (0x10)
+#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI5          (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_TIMER */
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER0        (0x01)
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER1        (0x02)
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER2        (0x04)
+#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER3        (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAH */
+#define MCF_GPIO_PPDSDR_LCDDATAH_PPDSDR_LCDDATAH0  (0x01)
+#define MCF_GPIO_PPDSDR_LCDDATAH_PPDSDR_LCDDATAH1  (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAM */
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM0  (0x01)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM1  (0x02)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM2  (0x04)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM3  (0x08)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM4  (0x10)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM5  (0x20)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM6  (0x40)
+#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM7  (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAL */
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL0  (0x01)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL1  (0x02)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL2  (0x04)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL3  (0x08)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL4  (0x10)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL5  (0x20)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL6  (0x40)
+#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL7  (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDCTLH */
+#define MCF_GPIO_PPDSDR_LCDCTLH_PPDSDR_LCDCTLH0    (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDCTLL */
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL0    (0x01)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL1    (0x02)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL2    (0x04)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL3    (0x08)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL4    (0x10)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL5    (0x20)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL6    (0x40)
+#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL7    (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_FECH */
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH0            (0x01)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH1            (0x02)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH2            (0x04)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH3            (0x08)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH4            (0x10)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH5            (0x20)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH6            (0x40)
+#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH7            (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_FECL */
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL0            (0x01)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL1            (0x02)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL2            (0x04)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL3            (0x08)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL4            (0x10)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL5            (0x20)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL6            (0x40)
+#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL7            (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_SSI */
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI0              (0x01)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI1              (0x02)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI2              (0x04)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI3              (0x08)
+#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI4              (0x10)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_BUSCTL */
+#define MCF_GPIO_PCLRR_BUSCTL_POSDR_BUSCTL0        (0x01)
+#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL1        (0x02)
+#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL2        (0x04)
+#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL3        (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_BE */
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE0                (0x01)
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE1                (0x02)
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE2                (0x04)
+#define MCF_GPIO_PCLRR_BE_PCLRR_BE3                (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_CS */
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS1                (0x02)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS2                (0x04)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS3                (0x08)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS4                (0x10)
+#define MCF_GPIO_PCLRR_CS_PCLRR_CS5                (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_PWM */
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM2              (0x04)
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM3              (0x08)
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM4              (0x10)
+#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM5              (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_FECI2C */
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C0        (0x01)
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C1        (0x02)
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C2        (0x04)
+#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C3        (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_UART */
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART0            (0x01)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART1            (0x02)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART2            (0x04)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART3            (0x08)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART4            (0x10)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART5            (0x20)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART6            (0x40)
+#define MCF_GPIO_PCLRR_UART_PCLRR_UART7            (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_QSPI */
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI0            (0x01)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI1            (0x02)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI2            (0x04)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI3            (0x08)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI4            (0x10)
+#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI5            (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_TIMER */
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER0          (0x01)
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER1          (0x02)
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER2          (0x04)
+#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER3          (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAH */
+#define MCF_GPIO_PCLRR_LCDDATAH_PCLRR_LCDDATAH0    (0x01)
+#define MCF_GPIO_PCLRR_LCDDATAH_PCLRR_LCDDATAH1    (0x02)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAM */
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM0    (0x01)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM1    (0x02)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM2    (0x04)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM3    (0x08)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM4    (0x10)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM5    (0x20)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM6    (0x40)
+#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM7    (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAL */
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL0    (0x01)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL1    (0x02)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL2    (0x04)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL3    (0x08)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL4    (0x10)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL5    (0x20)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL6    (0x40)
+#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL7    (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDCTLH */
+#define MCF_GPIO_PCLRR_LCDCTLH_PCLRR_LCDCTLH0      (0x01)
+
+/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDCTLL */
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL0      (0x01)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL1      (0x02)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL2      (0x04)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL3      (0x08)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL4      (0x10)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL5      (0x20)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL6      (0x40)
+#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL7      (0x80)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_FEC */
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII(x)            (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W(x)             (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_GPIO           (0x00)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_URTS1          (0x04)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC            (0x0C)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_GPIO          (0x00)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_UART          (0x01)
+#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC           (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_PWM */
+#define MCF_GPIO_PAR_PWM_PAR_PWM1(x)               (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_PWM_PAR_PWM3(x)               (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_PWM_PAR_PWM5                  (0x10)
+#define MCF_GPIO_PAR_PWM_PAR_PWM7                  (0x20)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_BUSCTL */
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS(x)              (((x)&0x03)<<3)
+#define MCF_GPIO_PAR_BUSCTL_PAR_RWB                (0x20)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TA                 (0x40)
+#define MCF_GPIO_PAR_BUSCTL_PAR_OE                 (0x80)
+#define MCF_GPIO_PAR_BUSCTL_PAR_OE_GPIO            (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_OE_OE              (0x80)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TA_GPIO            (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TA_TA              (0x40)
+#define MCF_GPIO_PAR_BUSCTL_PAR_RWB_GPIO           (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_RWB_RWB            (0x20)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS_GPIO            (0x00)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS_DACK0           (0x10)
+#define MCF_GPIO_PAR_BUSCTL_PAR_TS_TS              (0x18)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_FECI2C */
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA(x)             (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL(x)             (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO(x)            (((x)&0x03)<<4)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC(x)             (((x)&0x03)<<6)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_GPIO           (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_UTXD2          (0x40)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_SCL            (0x80)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC           (0xC0)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_GPIO          (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_URXD2         (0x10)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_SDA           (0x20)
+#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO         (0x30)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL_GPIO           (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2          (0x04)
+#define MCF_GPIO_PAR_FECI2C_PAR_SCL_SCL            (0x0C)
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA_GPIO           (0x00)
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2          (0x02)
+#define MCF_GPIO_PAR_FECI2C_PAR_SDA_SDA            (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_BE */
+#define MCF_GPIO_PAR_BE_PAR_BE0                    (0x01)
+#define MCF_GPIO_PAR_BE_PAR_BE1                    (0x02)
+#define MCF_GPIO_PAR_BE_PAR_BE2                    (0x04)
+#define MCF_GPIO_PAR_BE_PAR_BE3                    (0x08)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_CS */
+#define MCF_GPIO_PAR_CS_PAR_CS1                    (0x02)
+#define MCF_GPIO_PAR_CS_PAR_CS2                    (0x04)
+#define MCF_GPIO_PAR_CS_PAR_CS3                    (0x08)
+#define MCF_GPIO_PAR_CS_PAR_CS4                    (0x10)
+#define MCF_GPIO_PAR_CS_PAR_CS5                    (0x20)
+#define MCF_GPIO_PAR_CS_PAR_CS_CS1_GPIO            (0x00)
+#define MCF_GPIO_PAR_CS_PAR_CS_CS1_SDCS1           (0x01)
+#define MCF_GPIO_PAR_CS_PAR_CS_CS1_CS1             (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_SSI */
+#define MCF_GPIO_PAR_SSI_PAR_MCLK                  (0x0080)
+#define MCF_GPIO_PAR_SSI_PAR_TXD(x)                (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_SSI_PAR_RXD(x)                (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_SSI_PAR_FS(x)                 (((x)&0x0003)<<12)
+#define MCF_GPIO_PAR_SSI_PAR_BCLK(x)               (((x)&0x0003)<<14)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_UART */
+#define MCF_GPIO_PAR_UART_PAR_UTXD0                (0x0001)
+#define MCF_GPIO_PAR_UART_PAR_URXD0                (0x0002)
+#define MCF_GPIO_PAR_UART_PAR_URTS0                (0x0004)
+#define MCF_GPIO_PAR_UART_PAR_UCTS0                (0x0008)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1(x)             (((x)&0x0003)<<4)
+#define MCF_GPIO_PAR_UART_PAR_URXD1(x)             (((x)&0x0003)<<6)
+#define MCF_GPIO_PAR_UART_PAR_URTS1(x)             (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1(x)             (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_SSI_BCLK       (0x0800)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_ULPI_D7        (0x0400)
+#define MCF_GPIO_PAR_UART_PAR_UCTS1_UCTS1          (0x0C00)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_SSI_FS         (0x0200)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_ULPI_D6        (0x0100)
+#define MCF_GPIO_PAR_UART_PAR_URTS1_URTS1          (0x0300)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_SSI_RXD        (0x0080)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_ULPI_D5        (0x0040)
+#define MCF_GPIO_PAR_UART_PAR_URXD1_URXD1          (0x00C0)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_GPIO           (0x0000)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_SSI_TXD        (0x0020)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_ULPI_D4        (0x0010)
+#define MCF_GPIO_PAR_UART_PAR_UTXD1_UTXD1          (0x0030)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_QSPI */
+#define MCF_GPIO_PAR_QSPI_PAR_SCK(x)               (((x)&0x0003)<<4)
+#define MCF_GPIO_PAR_QSPI_PAR_DOUT(x)              (((x)&0x0003)<<6)
+#define MCF_GPIO_PAR_QSPI_PAR_DIN(x)               (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_QSPI_PAR_PCS0(x)              (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_QSPI_PAR_PCS1(x)              (((x)&0x0003)<<12)
+#define MCF_GPIO_PAR_QSPI_PAR_PCS2(x)              (((x)&0x0003)<<14)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_TIMER */
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0(x)             (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1(x)             (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2(x)             (((x)&0x03)<<4)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3(x)             (((x)&0x03)<<6)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_TOUT3          (0x80)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_URXD2          (0x40)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN3_TIN3           (0xC0)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_TOUT2          (0x20)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_UTXD2          (0x10)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN2_TIN2           (0x30)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_TOUT1          (0x08)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_DACK1          (0x04)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN1_TIN1           (0x0C)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_GPIO           (0x00)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_TOUT0          (0x02)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_DREQ0          (0x01)
+#define MCF_GPIO_PAR_TIMER_PAR_TIN0_TIN0           (0x03)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_LCDDATA */
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD7_0(x)          (((x)&0x03)<<0)
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD15_8(x)         (((x)&0x03)<<2)
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD16(x)           (((x)&0x03)<<4)
+#define MCF_GPIO_PAR_LCDDATA_PAR_LD17(x)           (((x)&0x03)<<6)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_LCDCTL */
+#define MCF_GPIO_PAR_LCDCTL_PAR_CLS                (0x0001)
+#define MCF_GPIO_PAR_LCDCTL_PAR_PS                 (0x0002)
+#define MCF_GPIO_PAR_LCDCTL_PAR_REV                (0x0004)
+#define MCF_GPIO_PAR_LCDCTL_PAR_SPL_SPR            (0x0008)
+#define MCF_GPIO_PAR_LCDCTL_PAR_CONTRAST           (0x0010)
+#define MCF_GPIO_PAR_LCDCTL_PAR_LSCLK              (0x0020)
+#define MCF_GPIO_PAR_LCDCTL_PAR_LP_HSYNC           (0x0040)
+#define MCF_GPIO_PAR_LCDCTL_PAR_FLM_VSYNC          (0x0080)
+#define MCF_GPIO_PAR_LCDCTL_PAR_ACD_OE             (0x0100)
+
+/* Bit definitions and macros for MCF_GPIO_PAR_IRQ */
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ1(x)               (((x)&0x0003)<<4)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ2(x)               (((x)&0x0003)<<6)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ4(x)               (((x)&0x0003)<<8)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ5(x)               (((x)&0x0003)<<10)
+#define MCF_GPIO_PAR_IRQ_PAR_IRQ6(x)               (((x)&0x0003)<<12)
+
+/* Bit definitions and macros for MCF_GPIO_MSCR_FLEXBUS */
+#define MCF_GPIO_MSCR_FLEXBUS_MSCR_ADDRCTL(x)      (((x)&0x03)<<0)
+#define MCF_GPIO_MSCR_FLEXBUS_MSCR_DLOWER(x)       (((x)&0x03)<<2)
+#define MCF_GPIO_MSCR_FLEXBUS_MSCR_DUPPER(x)       (((x)&0x03)<<4)
+
+/* Bit definitions and macros for MCF_GPIO_MSCR_SDRAM */
+#define MCF_GPIO_MSCR_SDRAM_MSCR_SDRAM(x)          (((x)&0x03)<<0)
+#define MCF_GPIO_MSCR_SDRAM_MSCR_SDCLK(x)          (((x)&0x03)<<2)
+#define MCF_GPIO_MSCR_SDRAM_MSCR_SDCLKB(x)         (((x)&0x03)<<4)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_I2C */
+#define MCF_GPIO_DSCR_I2C_I2C_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_PWM */
+#define MCF_GPIO_DSCR_PWM_PWM_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_FEC */
+#define MCF_GPIO_DSCR_FEC_FEC_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_UART */
+#define MCF_GPIO_DSCR_UART_UART0_DSE(x)            (((x)&0x03)<<0)
+#define MCF_GPIO_DSCR_UART_UART1_DSE(x)            (((x)&0x03)<<2)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_QSPI */
+#define MCF_GPIO_DSCR_QSPI_QSPI_DSE(x)             (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_TIMER */
+#define MCF_GPIO_DSCR_TIMER_TIMER_DSE(x)           (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_SSI */
+#define MCF_GPIO_DSCR_SSI_SSI_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_LCD */
+#define MCF_GPIO_DSCR_LCD_LCD_DSE(x)               (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_DEBUG */
+#define MCF_GPIO_DSCR_DEBUG_DEBUG_DSE(x)           (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_CLKRST */
+#define MCF_GPIO_DSCR_CLKRST_CLKRST_DSE(x)         (((x)&0x03)<<0)
+
+/* Bit definitions and macros for MCF_GPIO_DSCR_IRQ */
+#define MCF_GPIO_DSCR_IRQ_IRQ_DSE(x)               (((x)&0x03)<<0)
+
+/*********************************************************************
+ *
+ * Interrupt Controller (INTC)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_INTC0_IPRH             MCF_REG32(0xFC048000)
+#define MCF_INTC0_IPRL             MCF_REG32(0xFC048004)
+#define MCF_INTC0_IMRH             MCF_REG32(0xFC048008)
+#define MCF_INTC0_IMRL             MCF_REG32(0xFC04800C)
+#define MCF_INTC0_INTFRCH          MCF_REG32(0xFC048010)
+#define MCF_INTC0_INTFRCL          MCF_REG32(0xFC048014)
+#define MCF_INTC0_ICONFIG          MCF_REG16(0xFC04801A)
+#define MCF_INTC0_SIMR             MCF_REG08(0xFC04801C)
+#define MCF_INTC0_CIMR             MCF_REG08(0xFC04801D)
+#define MCF_INTC0_CLMASK           MCF_REG08(0xFC04801E)
+#define MCF_INTC0_SLMASK           MCF_REG08(0xFC04801F)
+#define MCF_INTC0_ICR0             MCF_REG08(0xFC048040)
+#define MCF_INTC0_ICR1             MCF_REG08(0xFC048041)
+#define MCF_INTC0_ICR2             MCF_REG08(0xFC048042)
+#define MCF_INTC0_ICR3             MCF_REG08(0xFC048043)
+#define MCF_INTC0_ICR4             MCF_REG08(0xFC048044)
+#define MCF_INTC0_ICR5             MCF_REG08(0xFC048045)
+#define MCF_INTC0_ICR6             MCF_REG08(0xFC048046)
+#define MCF_INTC0_ICR7             MCF_REG08(0xFC048047)
+#define MCF_INTC0_ICR8             MCF_REG08(0xFC048048)
+#define MCF_INTC0_ICR9             MCF_REG08(0xFC048049)
+#define MCF_INTC0_ICR10            MCF_REG08(0xFC04804A)
+#define MCF_INTC0_ICR11            MCF_REG08(0xFC04804B)
+#define MCF_INTC0_ICR12            MCF_REG08(0xFC04804C)
+#define MCF_INTC0_ICR13            MCF_REG08(0xFC04804D)
+#define MCF_INTC0_ICR14            MCF_REG08(0xFC04804E)
+#define MCF_INTC0_ICR15            MCF_REG08(0xFC04804F)
+#define MCF_INTC0_ICR16            MCF_REG08(0xFC048050)
+#define MCF_INTC0_ICR17            MCF_REG08(0xFC048051)
+#define MCF_INTC0_ICR18            MCF_REG08(0xFC048052)
+#define MCF_INTC0_ICR19            MCF_REG08(0xFC048053)
+#define MCF_INTC0_ICR20            MCF_REG08(0xFC048054)
+#define MCF_INTC0_ICR21            MCF_REG08(0xFC048055)
+#define MCF_INTC0_ICR22            MCF_REG08(0xFC048056)
+#define MCF_INTC0_ICR23            MCF_REG08(0xFC048057)
+#define MCF_INTC0_ICR24            MCF_REG08(0xFC048058)
+#define MCF_INTC0_ICR25            MCF_REG08(0xFC048059)
+#define MCF_INTC0_ICR26            MCF_REG08(0xFC04805A)
+#define MCF_INTC0_ICR27            MCF_REG08(0xFC04805B)
+#define MCF_INTC0_ICR28            MCF_REG08(0xFC04805C)
+#define MCF_INTC0_ICR29            MCF_REG08(0xFC04805D)
+#define MCF_INTC0_ICR30            MCF_REG08(0xFC04805E)
+#define MCF_INTC0_ICR31            MCF_REG08(0xFC04805F)
+#define MCF_INTC0_ICR32            MCF_REG08(0xFC048060)
+#define MCF_INTC0_ICR33            MCF_REG08(0xFC048061)
+#define MCF_INTC0_ICR34            MCF_REG08(0xFC048062)
+#define MCF_INTC0_ICR35            MCF_REG08(0xFC048063)
+#define MCF_INTC0_ICR36            MCF_REG08(0xFC048064)
+#define MCF_INTC0_ICR37            MCF_REG08(0xFC048065)
+#define MCF_INTC0_ICR38            MCF_REG08(0xFC048066)
+#define MCF_INTC0_ICR39            MCF_REG08(0xFC048067)
+#define MCF_INTC0_ICR40            MCF_REG08(0xFC048068)
+#define MCF_INTC0_ICR41            MCF_REG08(0xFC048069)
+#define MCF_INTC0_ICR42            MCF_REG08(0xFC04806A)
+#define MCF_INTC0_ICR43            MCF_REG08(0xFC04806B)
+#define MCF_INTC0_ICR44            MCF_REG08(0xFC04806C)
+#define MCF_INTC0_ICR45            MCF_REG08(0xFC04806D)
+#define MCF_INTC0_ICR46            MCF_REG08(0xFC04806E)
+#define MCF_INTC0_ICR47            MCF_REG08(0xFC04806F)
+#define MCF_INTC0_ICR48            MCF_REG08(0xFC048070)
+#define MCF_INTC0_ICR49            MCF_REG08(0xFC048071)
+#define MCF_INTC0_ICR50            MCF_REG08(0xFC048072)
+#define MCF_INTC0_ICR51            MCF_REG08(0xFC048073)
+#define MCF_INTC0_ICR52            MCF_REG08(0xFC048074)
+#define MCF_INTC0_ICR53            MCF_REG08(0xFC048075)
+#define MCF_INTC0_ICR54            MCF_REG08(0xFC048076)
+#define MCF_INTC0_ICR55            MCF_REG08(0xFC048077)
+#define MCF_INTC0_ICR56            MCF_REG08(0xFC048078)
+#define MCF_INTC0_ICR57            MCF_REG08(0xFC048079)
+#define MCF_INTC0_ICR58            MCF_REG08(0xFC04807A)
+#define MCF_INTC0_ICR59            MCF_REG08(0xFC04807B)
+#define MCF_INTC0_ICR60            MCF_REG08(0xFC04807C)
+#define MCF_INTC0_ICR61            MCF_REG08(0xFC04807D)
+#define MCF_INTC0_ICR62            MCF_REG08(0xFC04807E)
+#define MCF_INTC0_ICR63            MCF_REG08(0xFC04807F)
+#define MCF_INTC0_ICR(x)           MCF_REG08(0xFC048040+((x)*0x001))
+#define MCF_INTC0_SWIACK           MCF_REG08(0xFC0480E0)
+#define MCF_INTC0_L1IACK           MCF_REG08(0xFC0480E4)
+#define MCF_INTC0_L2IACK           MCF_REG08(0xFC0480E8)
+#define MCF_INTC0_L3IACK           MCF_REG08(0xFC0480EC)
+#define MCF_INTC0_L4IACK           MCF_REG08(0xFC0480F0)
+#define MCF_INTC0_L5IACK           MCF_REG08(0xFC0480F4)
+#define MCF_INTC0_L6IACK           MCF_REG08(0xFC0480F8)
+#define MCF_INTC0_L7IACK           MCF_REG08(0xFC0480FC)
+#define MCF_INTC0_LIACK(x)         MCF_REG08(0xFC0480E4+((x)*0x004))
+#define MCF_INTC1_IPRH             MCF_REG32(0xFC04C000)
+#define MCF_INTC1_IPRL             MCF_REG32(0xFC04C004)
+#define MCF_INTC1_IMRH             MCF_REG32(0xFC04C008)
+#define MCF_INTC1_IMRL             MCF_REG32(0xFC04C00C)
+#define MCF_INTC1_INTFRCH          MCF_REG32(0xFC04C010)
+#define MCF_INTC1_INTFRCL          MCF_REG32(0xFC04C014)
+#define MCF_INTC1_ICONFIG          MCF_REG16(0xFC04C01A)
+#define MCF_INTC1_SIMR             MCF_REG08(0xFC04C01C)
+#define MCF_INTC1_CIMR             MCF_REG08(0xFC04C01D)
+#define MCF_INTC1_CLMASK           MCF_REG08(0xFC04C01E)
+#define MCF_INTC1_SLMASK           MCF_REG08(0xFC04C01F)
+#define MCF_INTC1_ICR0             MCF_REG08(0xFC04C040)
+#define MCF_INTC1_ICR1             MCF_REG08(0xFC04C041)
+#define MCF_INTC1_ICR2             MCF_REG08(0xFC04C042)
+#define MCF_INTC1_ICR3             MCF_REG08(0xFC04C043)
+#define MCF_INTC1_ICR4             MCF_REG08(0xFC04C044)
+#define MCF_INTC1_ICR5             MCF_REG08(0xFC04C045)
+#define MCF_INTC1_ICR6             MCF_REG08(0xFC04C046)
+#define MCF_INTC1_ICR7             MCF_REG08(0xFC04C047)
+#define MCF_INTC1_ICR8             MCF_REG08(0xFC04C048)
+#define MCF_INTC1_ICR9             MCF_REG08(0xFC04C049)
+#define MCF_INTC1_ICR10            MCF_REG08(0xFC04C04A)
+#define MCF_INTC1_ICR11            MCF_REG08(0xFC04C04B)
+#define MCF_INTC1_ICR12            MCF_REG08(0xFC04C04C)
+#define MCF_INTC1_ICR13            MCF_REG08(0xFC04C04D)
+#define MCF_INTC1_ICR14            MCF_REG08(0xFC04C04E)
+#define MCF_INTC1_ICR15            MCF_REG08(0xFC04C04F)
+#define MCF_INTC1_ICR16            MCF_REG08(0xFC04C050)
+#define MCF_INTC1_ICR17            MCF_REG08(0xFC04C051)
+#define MCF_INTC1_ICR18            MCF_REG08(0xFC04C052)
+#define MCF_INTC1_ICR19            MCF_REG08(0xFC04C053)
+#define MCF_INTC1_ICR20            MCF_REG08(0xFC04C054)
+#define MCF_INTC1_ICR21            MCF_REG08(0xFC04C055)
+#define MCF_INTC1_ICR22            MCF_REG08(0xFC04C056)
+#define MCF_INTC1_ICR23            MCF_REG08(0xFC04C057)
+#define MCF_INTC1_ICR24            MCF_REG08(0xFC04C058)
+#define MCF_INTC1_ICR25            MCF_REG08(0xFC04C059)
+#define MCF_INTC1_ICR26            MCF_REG08(0xFC04C05A)
+#define MCF_INTC1_ICR27            MCF_REG08(0xFC04C05B)
+#define MCF_INTC1_ICR28            MCF_REG08(0xFC04C05C)
+#define MCF_INTC1_ICR29            MCF_REG08(0xFC04C05D)
+#define MCF_INTC1_ICR30            MCF_REG08(0xFC04C05E)
+#define MCF_INTC1_ICR31            MCF_REG08(0xFC04C05F)
+#define MCF_INTC1_ICR32            MCF_REG08(0xFC04C060)
+#define MCF_INTC1_ICR33            MCF_REG08(0xFC04C061)
+#define MCF_INTC1_ICR34            MCF_REG08(0xFC04C062)
+#define MCF_INTC1_ICR35            MCF_REG08(0xFC04C063)
+#define MCF_INTC1_ICR36            MCF_REG08(0xFC04C064)
+#define MCF_INTC1_ICR37            MCF_REG08(0xFC04C065)
+#define MCF_INTC1_ICR38            MCF_REG08(0xFC04C066)
+#define MCF_INTC1_ICR39            MCF_REG08(0xFC04C067)
+#define MCF_INTC1_ICR40            MCF_REG08(0xFC04C068)
+#define MCF_INTC1_ICR41            MCF_REG08(0xFC04C069)
+#define MCF_INTC1_ICR42            MCF_REG08(0xFC04C06A)
+#define MCF_INTC1_ICR43            MCF_REG08(0xFC04C06B)
+#define MCF_INTC1_ICR44            MCF_REG08(0xFC04C06C)
+#define MCF_INTC1_ICR45            MCF_REG08(0xFC04C06D)
+#define MCF_INTC1_ICR46            MCF_REG08(0xFC04C06E)
+#define MCF_INTC1_ICR47            MCF_REG08(0xFC04C06F)
+#define MCF_INTC1_ICR48            MCF_REG08(0xFC04C070)
+#define MCF_INTC1_ICR49            MCF_REG08(0xFC04C071)
+#define MCF_INTC1_ICR50            MCF_REG08(0xFC04C072)
+#define MCF_INTC1_ICR51            MCF_REG08(0xFC04C073)
+#define MCF_INTC1_ICR52            MCF_REG08(0xFC04C074)
+#define MCF_INTC1_ICR53            MCF_REG08(0xFC04C075)
+#define MCF_INTC1_ICR54            MCF_REG08(0xFC04C076)
+#define MCF_INTC1_ICR55            MCF_REG08(0xFC04C077)
+#define MCF_INTC1_ICR56            MCF_REG08(0xFC04C078)
+#define MCF_INTC1_ICR57            MCF_REG08(0xFC04C079)
+#define MCF_INTC1_ICR58            MCF_REG08(0xFC04C07A)
+#define MCF_INTC1_ICR59            MCF_REG08(0xFC04C07B)
+#define MCF_INTC1_ICR60            MCF_REG08(0xFC04C07C)
+#define MCF_INTC1_ICR61            MCF_REG08(0xFC04C07D)
+#define MCF_INTC1_ICR62            MCF_REG08(0xFC04C07E)
+#define MCF_INTC1_ICR63            MCF_REG08(0xFC04C07F)
+#define MCF_INTC1_ICR(x)           MCF_REG08(0xFC04C040+((x)*0x001))
+#define MCF_INTC1_SWIACK           MCF_REG08(0xFC04C0E0)
+#define MCF_INTC1_L1IACK           MCF_REG08(0xFC04C0E4)
+#define MCF_INTC1_L2IACK           MCF_REG08(0xFC04C0E8)
+#define MCF_INTC1_L3IACK           MCF_REG08(0xFC04C0EC)
+#define MCF_INTC1_L4IACK           MCF_REG08(0xFC04C0F0)
+#define MCF_INTC1_L5IACK           MCF_REG08(0xFC04C0F4)
+#define MCF_INTC1_L6IACK           MCF_REG08(0xFC04C0F8)
+#define MCF_INTC1_L7IACK           MCF_REG08(0xFC04C0FC)
+#define MCF_INTC1_LIACK(x)         MCF_REG08(0xFC04C0E4+((x)*0x004))
+#define MCF_INTC_IPRH(x)           MCF_REG32(0xFC048000+((x)*0x4000))
+#define MCF_INTC_IPRL(x)           MCF_REG32(0xFC048004+((x)*0x4000))
+#define MCF_INTC_IMRH(x)           MCF_REG32(0xFC048008+((x)*0x4000))
+#define MCF_INTC_IMRL(x)           MCF_REG32(0xFC04800C+((x)*0x4000))
+#define MCF_INTC_INTFRCH(x)        MCF_REG32(0xFC048010+((x)*0x4000))
+#define MCF_INTC_INTFRCL(x)        MCF_REG32(0xFC048014+((x)*0x4000))
+#define MCF_INTC_ICONFIG(x)        MCF_REG16(0xFC04801A+((x)*0x4000))
+#define MCF_INTC_SIMR(x)           MCF_REG08(0xFC04801C+((x)*0x4000))
+#define MCF_INTC_CIMR(x)           MCF_REG08(0xFC04801D+((x)*0x4000))
+#define MCF_INTC_CLMASK(x)         MCF_REG08(0xFC04801E+((x)*0x4000))
+#define MCF_INTC_SLMASK(x)         MCF_REG08(0xFC04801F+((x)*0x4000))
+#define MCF_INTC_ICR0(x)           MCF_REG08(0xFC048040+((x)*0x4000))
+#define MCF_INTC_ICR1(x)           MCF_REG08(0xFC048041+((x)*0x4000))
+#define MCF_INTC_ICR2(x)           MCF_REG08(0xFC048042+((x)*0x4000))
+#define MCF_INTC_ICR3(x)           MCF_REG08(0xFC048043+((x)*0x4000))
+#define MCF_INTC_ICR4(x)           MCF_REG08(0xFC048044+((x)*0x4000))
+#define MCF_INTC_ICR5(x)           MCF_REG08(0xFC048045+((x)*0x4000))
+#define MCF_INTC_ICR6(x)           MCF_REG08(0xFC048046+((x)*0x4000))
+#define MCF_INTC_ICR7(x)           MCF_REG08(0xFC048047+((x)*0x4000))
+#define MCF_INTC_ICR8(x)           MCF_REG08(0xFC048048+((x)*0x4000))
+#define MCF_INTC_ICR9(x)           MCF_REG08(0xFC048049+((x)*0x4000))
+#define MCF_INTC_ICR10(x)          MCF_REG08(0xFC04804A+((x)*0x4000))
+#define MCF_INTC_ICR11(x)          MCF_REG08(0xFC04804B+((x)*0x4000))
+#define MCF_INTC_ICR12(x)          MCF_REG08(0xFC04804C+((x)*0x4000))
+#define MCF_INTC_ICR13(x)          MCF_REG08(0xFC04804D+((x)*0x4000))
+#define MCF_INTC_ICR14(x)          MCF_REG08(0xFC04804E+((x)*0x4000))
+#define MCF_INTC_ICR15(x)          MCF_REG08(0xFC04804F+((x)*0x4000))
+#define MCF_INTC_ICR16(x)          MCF_REG08(0xFC048050+((x)*0x4000))
+#define MCF_INTC_ICR17(x)          MCF_REG08(0xFC048051+((x)*0x4000))
+#define MCF_INTC_ICR18(x)          MCF_REG08(0xFC048052+((x)*0x4000))
+#define MCF_INTC_ICR19(x)          MCF_REG08(0xFC048053+((x)*0x4000))
+#define MCF_INTC_ICR20(x)          MCF_REG08(0xFC048054+((x)*0x4000))
+#define MCF_INTC_ICR21(x)          MCF_REG08(0xFC048055+((x)*0x4000))
+#define MCF_INTC_ICR22(x)          MCF_REG08(0xFC048056+((x)*0x4000))
+#define MCF_INTC_ICR23(x)          MCF_REG08(0xFC048057+((x)*0x4000))
+#define MCF_INTC_ICR24(x)          MCF_REG08(0xFC048058+((x)*0x4000))
+#define MCF_INTC_ICR25(x)          MCF_REG08(0xFC048059+((x)*0x4000))
+#define MCF_INTC_ICR26(x)          MCF_REG08(0xFC04805A+((x)*0x4000))
+#define MCF_INTC_ICR27(x)          MCF_REG08(0xFC04805B+((x)*0x4000))
+#define MCF_INTC_ICR28(x)          MCF_REG08(0xFC04805C+((x)*0x4000))
+#define MCF_INTC_ICR29(x)          MCF_REG08(0xFC04805D+((x)*0x4000))
+#define MCF_INTC_ICR30(x)          MCF_REG08(0xFC04805E+((x)*0x4000))
+#define MCF_INTC_ICR31(x)          MCF_REG08(0xFC04805F+((x)*0x4000))
+#define MCF_INTC_ICR32(x)          MCF_REG08(0xFC048060+((x)*0x4000))
+#define MCF_INTC_ICR33(x)          MCF_REG08(0xFC048061+((x)*0x4000))
+#define MCF_INTC_ICR34(x)          MCF_REG08(0xFC048062+((x)*0x4000))
+#define MCF_INTC_ICR35(x)          MCF_REG08(0xFC048063+((x)*0x4000))
+#define MCF_INTC_ICR36(x)          MCF_REG08(0xFC048064+((x)*0x4000))
+#define MCF_INTC_ICR37(x)          MCF_REG08(0xFC048065+((x)*0x4000))
+#define MCF_INTC_ICR38(x)          MCF_REG08(0xFC048066+((x)*0x4000))
+#define MCF_INTC_ICR39(x)          MCF_REG08(0xFC048067+((x)*0x4000))
+#define MCF_INTC_ICR40(x)          MCF_REG08(0xFC048068+((x)*0x4000))
+#define MCF_INTC_ICR41(x)          MCF_REG08(0xFC048069+((x)*0x4000))
+#define MCF_INTC_ICR42(x)          MCF_REG08(0xFC04806A+((x)*0x4000))
+#define MCF_INTC_ICR43(x)          MCF_REG08(0xFC04806B+((x)*0x4000))
+#define MCF_INTC_ICR44(x)          MCF_REG08(0xFC04806C+((x)*0x4000))
+#define MCF_INTC_ICR45(x)          MCF_REG08(0xFC04806D+((x)*0x4000))
+#define MCF_INTC_ICR46(x)          MCF_REG08(0xFC04806E+((x)*0x4000))
+#define MCF_INTC_ICR47(x)          MCF_REG08(0xFC04806F+((x)*0x4000))
+#define MCF_INTC_ICR48(x)          MCF_REG08(0xFC048070+((x)*0x4000))
+#define MCF_INTC_ICR49(x)          MCF_REG08(0xFC048071+((x)*0x4000))
+#define MCF_INTC_ICR50(x)          MCF_REG08(0xFC048072+((x)*0x4000))
+#define MCF_INTC_ICR51(x)          MCF_REG08(0xFC048073+((x)*0x4000))
+#define MCF_INTC_ICR52(x)          MCF_REG08(0xFC048074+((x)*0x4000))
+#define MCF_INTC_ICR53(x)          MCF_REG08(0xFC048075+((x)*0x4000))
+#define MCF_INTC_ICR54(x)          MCF_REG08(0xFC048076+((x)*0x4000))
+#define MCF_INTC_ICR55(x)          MCF_REG08(0xFC048077+((x)*0x4000))
+#define MCF_INTC_ICR56(x)          MCF_REG08(0xFC048078+((x)*0x4000))
+#define MCF_INTC_ICR57(x)          MCF_REG08(0xFC048079+((x)*0x4000))
+#define MCF_INTC_ICR58(x)          MCF_REG08(0xFC04807A+((x)*0x4000))
+#define MCF_INTC_ICR59(x)          MCF_REG08(0xFC04807B+((x)*0x4000))
+#define MCF_INTC_ICR60(x)          MCF_REG08(0xFC04807C+((x)*0x4000))
+#define MCF_INTC_ICR61(x)          MCF_REG08(0xFC04807D+((x)*0x4000))
+#define MCF_INTC_ICR62(x)          MCF_REG08(0xFC04807E+((x)*0x4000))
+#define MCF_INTC_ICR63(x)          MCF_REG08(0xFC04807F+((x)*0x4000))
+#define MCF_INTC_SWIACK(x)         MCF_REG08(0xFC0480E0+((x)*0x4000))
+#define MCF_INTC_L1IACK(x)         MCF_REG08(0xFC0480E4+((x)*0x4000))
+#define MCF_INTC_L2IACK(x)         MCF_REG08(0xFC0480E8+((x)*0x4000))
+#define MCF_INTC_L3IACK(x)         MCF_REG08(0xFC0480EC+((x)*0x4000))
+#define MCF_INTC_L4IACK(x)         MCF_REG08(0xFC0480F0+((x)*0x4000))
+#define MCF_INTC_L5IACK(x)         MCF_REG08(0xFC0480F4+((x)*0x4000))
+#define MCF_INTC_L6IACK(x)         MCF_REG08(0xFC0480F8+((x)*0x4000))
+#define MCF_INTC_L7IACK(x)         MCF_REG08(0xFC0480FC+((x)*0x4000))
+
+/* Bit definitions and macros for MCF_INTC_IPRH */
+#define MCF_INTC_IPRH_INT32        (0x00000001)
+#define MCF_INTC_IPRH_INT33        (0x00000002)
+#define MCF_INTC_IPRH_INT34        (0x00000004)
+#define MCF_INTC_IPRH_INT35        (0x00000008)
+#define MCF_INTC_IPRH_INT36        (0x00000010)
+#define MCF_INTC_IPRH_INT37        (0x00000020)
+#define MCF_INTC_IPRH_INT38        (0x00000040)
+#define MCF_INTC_IPRH_INT39        (0x00000080)
+#define MCF_INTC_IPRH_INT40        (0x00000100)
+#define MCF_INTC_IPRH_INT41        (0x00000200)
+#define MCF_INTC_IPRH_INT42        (0x00000400)
+#define MCF_INTC_IPRH_INT43        (0x00000800)
+#define MCF_INTC_IPRH_INT44        (0x00001000)
+#define MCF_INTC_IPRH_INT45        (0x00002000)
+#define MCF_INTC_IPRH_INT46        (0x00004000)
+#define MCF_INTC_IPRH_INT47        (0x00008000)
+#define MCF_INTC_IPRH_INT48        (0x00010000)
+#define MCF_INTC_IPRH_INT49        (0x00020000)
+#define MCF_INTC_IPRH_INT50        (0x00040000)
+#define MCF_INTC_IPRH_INT51        (0x00080000)
+#define MCF_INTC_IPRH_INT52        (0x00100000)
+#define MCF_INTC_IPRH_INT53        (0x00200000)
+#define MCF_INTC_IPRH_INT54        (0x00400000)
+#define MCF_INTC_IPRH_INT55        (0x00800000)
+#define MCF_INTC_IPRH_INT56        (0x01000000)
+#define MCF_INTC_IPRH_INT57        (0x02000000)
+#define MCF_INTC_IPRH_INT58        (0x04000000)
+#define MCF_INTC_IPRH_INT59        (0x08000000)
+#define MCF_INTC_IPRH_INT60        (0x10000000)
+#define MCF_INTC_IPRH_INT61        (0x20000000)
+#define MCF_INTC_IPRH_INT62        (0x40000000)
+#define MCF_INTC_IPRH_INT63        (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_IPRL */
+#define MCF_INTC_IPRL_INT0         (0x00000001)
+#define MCF_INTC_IPRL_INT1         (0x00000002)
+#define MCF_INTC_IPRL_INT2         (0x00000004)
+#define MCF_INTC_IPRL_INT3         (0x00000008)
+#define MCF_INTC_IPRL_INT4         (0x00000010)
+#define MCF_INTC_IPRL_INT5         (0x00000020)
+#define MCF_INTC_IPRL_INT6         (0x00000040)
+#define MCF_INTC_IPRL_INT7         (0x00000080)
+#define MCF_INTC_IPRL_INT8         (0x00000100)
+#define MCF_INTC_IPRL_INT9         (0x00000200)
+#define MCF_INTC_IPRL_INT10        (0x00000400)
+#define MCF_INTC_IPRL_INT11        (0x00000800)
+#define MCF_INTC_IPRL_INT12        (0x00001000)
+#define MCF_INTC_IPRL_INT13        (0x00002000)
+#define MCF_INTC_IPRL_INT14        (0x00004000)
+#define MCF_INTC_IPRL_INT15        (0x00008000)
+#define MCF_INTC_IPRL_INT16        (0x00010000)
+#define MCF_INTC_IPRL_INT17        (0x00020000)
+#define MCF_INTC_IPRL_INT18        (0x00040000)
+#define MCF_INTC_IPRL_INT19        (0x00080000)
+#define MCF_INTC_IPRL_INT20        (0x00100000)
+#define MCF_INTC_IPRL_INT21        (0x00200000)
+#define MCF_INTC_IPRL_INT22        (0x00400000)
+#define MCF_INTC_IPRL_INT23        (0x00800000)
+#define MCF_INTC_IPRL_INT24        (0x01000000)
+#define MCF_INTC_IPRL_INT25        (0x02000000)
+#define MCF_INTC_IPRL_INT26        (0x04000000)
+#define MCF_INTC_IPRL_INT27        (0x08000000)
+#define MCF_INTC_IPRL_INT28        (0x10000000)
+#define MCF_INTC_IPRL_INT29        (0x20000000)
+#define MCF_INTC_IPRL_INT30        (0x40000000)
+#define MCF_INTC_IPRL_INT31        (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_IMRH */
+#define MCF_INTC_IMRH_INT_MASK32   (0x00000001)
+#define MCF_INTC_IMRH_INT_MASK33   (0x00000002)
+#define MCF_INTC_IMRH_INT_MASK34   (0x00000004)
+#define MCF_INTC_IMRH_INT_MASK35   (0x00000008)
+#define MCF_INTC_IMRH_INT_MASK36   (0x00000010)
+#define MCF_INTC_IMRH_INT_MASK37   (0x00000020)
+#define MCF_INTC_IMRH_INT_MASK38   (0x00000040)
+#define MCF_INTC_IMRH_INT_MASK39   (0x00000080)
+#define MCF_INTC_IMRH_INT_MASK40   (0x00000100)
+#define MCF_INTC_IMRH_INT_MASK41   (0x00000200)
+#define MCF_INTC_IMRH_INT_MASK42   (0x00000400)
+#define MCF_INTC_IMRH_INT_MASK43   (0x00000800)
+#define MCF_INTC_IMRH_INT_MASK44   (0x00001000)
+#define MCF_INTC_IMRH_INT_MASK45   (0x00002000)
+#define MCF_INTC_IMRH_INT_MASK46   (0x00004000)
+#define MCF_INTC_IMRH_INT_MASK47   (0x00008000)
+#define MCF_INTC_IMRH_INT_MASK48   (0x00010000)
+#define MCF_INTC_IMRH_INT_MASK49   (0x00020000)
+#define MCF_INTC_IMRH_INT_MASK50   (0x00040000)
+#define MCF_INTC_IMRH_INT_MASK51   (0x00080000)
+#define MCF_INTC_IMRH_INT_MASK52   (0x00100000)
+#define MCF_INTC_IMRH_INT_MASK53   (0x00200000)
+#define MCF_INTC_IMRH_INT_MASK54   (0x00400000)
+#define MCF_INTC_IMRH_INT_MASK55   (0x00800000)
+#define MCF_INTC_IMRH_INT_MASK56   (0x01000000)
+#define MCF_INTC_IMRH_INT_MASK57   (0x02000000)
+#define MCF_INTC_IMRH_INT_MASK58   (0x04000000)
+#define MCF_INTC_IMRH_INT_MASK59   (0x08000000)
+#define MCF_INTC_IMRH_INT_MASK60   (0x10000000)
+#define MCF_INTC_IMRH_INT_MASK61   (0x20000000)
+#define MCF_INTC_IMRH_INT_MASK62   (0x40000000)
+#define MCF_INTC_IMRH_INT_MASK63   (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_IMRL */
+#define MCF_INTC_IMRL_INT_MASK0    (0x00000001)
+#define MCF_INTC_IMRL_INT_MASK1    (0x00000002)
+#define MCF_INTC_IMRL_INT_MASK2    (0x00000004)
+#define MCF_INTC_IMRL_INT_MASK3    (0x00000008)
+#define MCF_INTC_IMRL_INT_MASK4    (0x00000010)
+#define MCF_INTC_IMRL_INT_MASK5    (0x00000020)
+#define MCF_INTC_IMRL_INT_MASK6    (0x00000040)
+#define MCF_INTC_IMRL_INT_MASK7    (0x00000080)
+#define MCF_INTC_IMRL_INT_MASK8    (0x00000100)
+#define MCF_INTC_IMRL_INT_MASK9    (0x00000200)
+#define MCF_INTC_IMRL_INT_MASK10   (0x00000400)
+#define MCF_INTC_IMRL_INT_MASK11   (0x00000800)
+#define MCF_INTC_IMRL_INT_MASK12   (0x00001000)
+#define MCF_INTC_IMRL_INT_MASK13   (0x00002000)
+#define MCF_INTC_IMRL_INT_MASK14   (0x00004000)
+#define MCF_INTC_IMRL_INT_MASK15   (0x00008000)
+#define MCF_INTC_IMRL_INT_MASK16   (0x00010000)
+#define MCF_INTC_IMRL_INT_MASK17   (0x00020000)
+#define MCF_INTC_IMRL_INT_MASK18   (0x00040000)
+#define MCF_INTC_IMRL_INT_MASK19   (0x00080000)
+#define MCF_INTC_IMRL_INT_MASK20   (0x00100000)
+#define MCF_INTC_IMRL_INT_MASK21   (0x00200000)
+#define MCF_INTC_IMRL_INT_MASK22   (0x00400000)
+#define MCF_INTC_IMRL_INT_MASK23   (0x00800000)
+#define MCF_INTC_IMRL_INT_MASK24   (0x01000000)
+#define MCF_INTC_IMRL_INT_MASK25   (0x02000000)
+#define MCF_INTC_IMRL_INT_MASK26   (0x04000000)
+#define MCF_INTC_IMRL_INT_MASK27   (0x08000000)
+#define MCF_INTC_IMRL_INT_MASK28   (0x10000000)
+#define MCF_INTC_IMRL_INT_MASK29   (0x20000000)
+#define MCF_INTC_IMRL_INT_MASK30   (0x40000000)
+#define MCF_INTC_IMRL_INT_MASK31   (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_INTFRCH */
+#define MCF_INTC_INTFRCH_INTFRC32  (0x00000001)
+#define MCF_INTC_INTFRCH_INTFRC33  (0x00000002)
+#define MCF_INTC_INTFRCH_INTFRC34  (0x00000004)
+#define MCF_INTC_INTFRCH_INTFRC35  (0x00000008)
+#define MCF_INTC_INTFRCH_INTFRC36  (0x00000010)
+#define MCF_INTC_INTFRCH_INTFRC37  (0x00000020)
+#define MCF_INTC_INTFRCH_INTFRC38  (0x00000040)
+#define MCF_INTC_INTFRCH_INTFRC39  (0x00000080)
+#define MCF_INTC_INTFRCH_INTFRC40  (0x00000100)
+#define MCF_INTC_INTFRCH_INTFRC41  (0x00000200)
+#define MCF_INTC_INTFRCH_INTFRC42  (0x00000400)
+#define MCF_INTC_INTFRCH_INTFRC43  (0x00000800)
+#define MCF_INTC_INTFRCH_INTFRC44  (0x00001000)
+#define MCF_INTC_INTFRCH_INTFRC45  (0x00002000)
+#define MCF_INTC_INTFRCH_INTFRC46  (0x00004000)
+#define MCF_INTC_INTFRCH_INTFRC47  (0x00008000)
+#define MCF_INTC_INTFRCH_INTFRC48  (0x00010000)
+#define MCF_INTC_INTFRCH_INTFRC49  (0x00020000)
+#define MCF_INTC_INTFRCH_INTFRC50  (0x00040000)
+#define MCF_INTC_INTFRCH_INTFRC51  (0x00080000)
+#define MCF_INTC_INTFRCH_INTFRC52  (0x00100000)
+#define MCF_INTC_INTFRCH_INTFRC53  (0x00200000)
+#define MCF_INTC_INTFRCH_INTFRC54  (0x00400000)
+#define MCF_INTC_INTFRCH_INTFRC55  (0x00800000)
+#define MCF_INTC_INTFRCH_INTFRC56  (0x01000000)
+#define MCF_INTC_INTFRCH_INTFRC57  (0x02000000)
+#define MCF_INTC_INTFRCH_INTFRC58  (0x04000000)
+#define MCF_INTC_INTFRCH_INTFRC59  (0x08000000)
+#define MCF_INTC_INTFRCH_INTFRC60  (0x10000000)
+#define MCF_INTC_INTFRCH_INTFRC61  (0x20000000)
+#define MCF_INTC_INTFRCH_INTFRC62  (0x40000000)
+#define MCF_INTC_INTFRCH_INTFRC63  (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_INTFRCL */
+#define MCF_INTC_INTFRCL_INTFRC0   (0x00000001)
+#define MCF_INTC_INTFRCL_INTFRC1   (0x00000002)
+#define MCF_INTC_INTFRCL_INTFRC2   (0x00000004)
+#define MCF_INTC_INTFRCL_INTFRC3   (0x00000008)
+#define MCF_INTC_INTFRCL_INTFRC4   (0x00000010)
+#define MCF_INTC_INTFRCL_INTFRC5   (0x00000020)
+#define MCF_INTC_INTFRCL_INTFRC6   (0x00000040)
+#define MCF_INTC_INTFRCL_INTFRC7   (0x00000080)
+#define MCF_INTC_INTFRCL_INTFRC8   (0x00000100)
+#define MCF_INTC_INTFRCL_INTFRC9   (0x00000200)
+#define MCF_INTC_INTFRCL_INTFRC10  (0x00000400)
+#define MCF_INTC_INTFRCL_INTFRC11  (0x00000800)
+#define MCF_INTC_INTFRCL_INTFRC12  (0x00001000)
+#define MCF_INTC_INTFRCL_INTFRC13  (0x00002000)
+#define MCF_INTC_INTFRCL_INTFRC14  (0x00004000)
+#define MCF_INTC_INTFRCL_INTFRC15  (0x00008000)
+#define MCF_INTC_INTFRCL_INTFRC16  (0x00010000)
+#define MCF_INTC_INTFRCL_INTFRC17  (0x00020000)
+#define MCF_INTC_INTFRCL_INTFRC18  (0x00040000)
+#define MCF_INTC_INTFRCL_INTFRC19  (0x00080000)
+#define MCF_INTC_INTFRCL_INTFRC20  (0x00100000)
+#define MCF_INTC_INTFRCL_INTFRC21  (0x00200000)
+#define MCF_INTC_INTFRCL_INTFRC22  (0x00400000)
+#define MCF_INTC_INTFRCL_INTFRC23  (0x00800000)
+#define MCF_INTC_INTFRCL_INTFRC24  (0x01000000)
+#define MCF_INTC_INTFRCL_INTFRC25  (0x02000000)
+#define MCF_INTC_INTFRCL_INTFRC26  (0x04000000)
+#define MCF_INTC_INTFRCL_INTFRC27  (0x08000000)
+#define MCF_INTC_INTFRCL_INTFRC28  (0x10000000)
+#define MCF_INTC_INTFRCL_INTFRC29  (0x20000000)
+#define MCF_INTC_INTFRCL_INTFRC30  (0x40000000)
+#define MCF_INTC_INTFRCL_INTFRC31  (0x80000000)
+
+/* Bit definitions and macros for MCF_INTC_ICONFIG */
+#define MCF_INTC_ICONFIG_EMASK     (0x0020)
+#define MCF_INTC_ICONFIG_ELVLPRI1  (0x0200)
+#define MCF_INTC_ICONFIG_ELVLPRI2  (0x0400)
+#define MCF_INTC_ICONFIG_ELVLPRI3  (0x0800)
+#define MCF_INTC_ICONFIG_ELVLPRI4  (0x1000)
+#define MCF_INTC_ICONFIG_ELVLPRI5  (0x2000)
+#define MCF_INTC_ICONFIG_ELVLPRI6  (0x4000)
+#define MCF_INTC_ICONFIG_ELVLPRI7  (0x8000)
+
+/* Bit definitions and macros for MCF_INTC_SIMR */
+#define MCF_INTC_SIMR_SIMR(x)      (((x)&0x7F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_CIMR */
+#define MCF_INTC_CIMR_CIMR(x)      (((x)&0x7F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_CLMASK */
+#define MCF_INTC_CLMASK_CLMASK(x)  (((x)&0x0F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_SLMASK */
+#define MCF_INTC_SLMASK_SLMASK(x)  (((x)&0x0F)<<0)
+
+/* Bit definitions and macros for MCF_INTC_ICR */
+#define MCF_INTC_ICR_IL(x)         (((x)&0x07)<<0)
+
+/* Bit definitions and macros for MCF_INTC_SWIACK */
+#define MCF_INTC_SWIACK_VECTOR(x)  (((x)&0xFF)<<0)
+
+/* Bit definitions and macros for MCF_INTC_LIACK */
+#define MCF_INTC_LIACK_VECTOR(x)   (((x)&0xFF)<<0)
+
+/********************************************************************/
+/*********************************************************************
+*
+* LCD Controller (LCDC)
+*
+*********************************************************************/
+
+/* Register read/write macros */
+#define MCF_LCDC_LSSAR                  MCF_REG32(0xFC0AC000)
+#define MCF_LCDC_LSR                    MCF_REG32(0xFC0AC004)
+#define MCF_LCDC_LVPWR                  MCF_REG32(0xFC0AC008)
+#define MCF_LCDC_LCPR                   MCF_REG32(0xFC0AC00C)
+#define MCF_LCDC_LCWHBR                 MCF_REG32(0xFC0AC010)
+#define MCF_LCDC_LCCMR                  MCF_REG32(0xFC0AC014)
+#define MCF_LCDC_LPCR                   MCF_REG32(0xFC0AC018)
+#define MCF_LCDC_LHCR                   MCF_REG32(0xFC0AC01C)
+#define MCF_LCDC_LVCR                   MCF_REG32(0xFC0AC020)
+#define MCF_LCDC_LPOR                   MCF_REG32(0xFC0AC024)
+#define MCF_LCDC_LSCR                   MCF_REG32(0xFC0AC028)
+#define MCF_LCDC_LPCCR                  MCF_REG32(0xFC0AC02C)
+#define MCF_LCDC_LDCR                   MCF_REG32(0xFC0AC030)
+#define MCF_LCDC_LRMCR                  MCF_REG32(0xFC0AC034)
+#define MCF_LCDC_LICR                   MCF_REG32(0xFC0AC038)
+#define MCF_LCDC_LIER                   MCF_REG32(0xFC0AC03C)
+#define MCF_LCDC_LISR                   MCF_REG32(0xFC0AC040)
+#define MCF_LCDC_LGWSAR                 MCF_REG32(0xFC0AC050)
+#define MCF_LCDC_LGWSR                  MCF_REG32(0xFC0AC054)
+#define MCF_LCDC_LGWVPWR                MCF_REG32(0xFC0AC058)
+#define MCF_LCDC_LGWPOR                 MCF_REG32(0xFC0AC05C)
+#define MCF_LCDC_LGWPR                  MCF_REG32(0xFC0AC060)
+#define MCF_LCDC_LGWCR                  MCF_REG32(0xFC0AC064)
+#define MCF_LCDC_LGWDCR                 MCF_REG32(0xFC0AC068)
+#define MCF_LCDC_BPLUT_BASE             MCF_REG32(0xFC0AC800)
+#define MCF_LCDC_GWLUT_BASE             MCF_REG32(0xFC0ACC00)
+
+/* Bit definitions and macros for MCF_LCDC_LSSAR */
+#define MCF_LCDC_LSSAR_SSA(x)           (((x)&0x3FFFFFFF)<<2)
+
+/* Bit definitions and macros for MCF_LCDC_LSR */
+#define MCF_LCDC_LSR_YMAX(x)            (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LSR_XMAX(x)            (((x)&0x0000003F)<<20)
+
+/* Bit definitions and macros for MCF_LCDC_LVPWR */
+#define MCF_LCDC_LVPWR_VPW(x)           (((x)&0x000003FF)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LCPR */
+#define MCF_LCDC_LCPR_CYP(x)            (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LCPR_CXP(x)            (((x)&0x000003FF)<<16)
+#define MCF_LCDC_LCPR_OP                (0x10000000)
+#define MCF_LCDC_LCPR_CC(x)             (((x)&0x00000003)<<30)
+#define MCF_LCDC_LCPR_CC_TRANSPARENT    (0x00000000)
+#define MCF_LCDC_LCPR_CC_OR             (0x40000000)
+#define MCF_LCDC_LCPR_CC_XOR            (0x80000000)
+#define MCF_LCDC_LCPR_CC_AND            (0xC0000000)
+#define MCF_LCDC_LCPR_OP_ON             (0x10000000)
+#define MCF_LCDC_LCPR_OP_OFF            (0x00000000)
+
+/* Bit definitions and macros for MCF_LCDC_LCWHBR */
+#define MCF_LCDC_LCWHBR_BD(x)           (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LCWHBR_CH(x)           (((x)&0x0000001F)<<16)
+#define MCF_LCDC_LCWHBR_CW(x)           (((x)&0x0000001F)<<24)
+#define MCF_LCDC_LCWHBR_BK_EN           (0x80000000)
+#define MCF_LCDC_LCWHBR_BK_EN_ON        (0x80000000)
+#define MCF_LCDC_LCWHBR_BK_EN_OFF       (0x00000000)
+
+/* Bit definitions and macros for MCF_LCDC_LCCMR */
+#define MCF_LCDC_LCCMR_CUR_COL_B(x)     (((x)&0x0000003F)<<0)
+#define MCF_LCDC_LCCMR_CUR_COL_G(x)     (((x)&0x0000003F)<<6)
+#define MCF_LCDC_LCCMR_CUR_COL_R(x)     (((x)&0x0000003F)<<12)
+
+/* Bit definitions and macros for MCF_LCDC_LPCR */
+#define MCF_LCDC_LPCR_PCD(x)            (((x)&0x0000003F)<<0)
+#define MCF_LCDC_LPCR_SHARP             (0x00000040)
+#define MCF_LCDC_LPCR_SCLKSEL           (0x00000080)
+#define MCF_LCDC_LPCR_ACD(x)            (((x)&0x0000007F)<<8)
+#define MCF_LCDC_LPCR_ACDSEL            (0x00008000)
+#define MCF_LCDC_LPCR_REV_VS            (0x00010000)
+#define MCF_LCDC_LPCR_SWAP_SEL          (0x00020000)
+#define MCF_LCDC_LPCR_ENDSEL            (0x00040000)
+#define MCF_LCDC_LPCR_SCLKIDLE          (0x00080000)
+#define MCF_LCDC_LPCR_OEPOL             (0x00100000)
+#define MCF_LCDC_LPCR_CLKPOL            (0x00200000)
+#define MCF_LCDC_LPCR_LPPOL             (0x00400000)
+#define MCF_LCDC_LPCR_FLM               (0x00800000)
+#define MCF_LCDC_LPCR_PIXPOL            (0x01000000)
+#define MCF_LCDC_LPCR_BPIX(x)           (((x)&0x00000007)<<25)
+#define MCF_LCDC_LPCR_PBSIZ(x)          (((x)&0x00000003)<<28)
+#define MCF_LCDC_LPCR_COLOR             (0x40000000)
+#define MCF_LCDC_LPCR_TFT               (0x80000000)
+#define MCF_LCDC_LPCR_MODE_MONOCGROME   (0x00000000)
+#define MCF_LCDC_LPCR_MODE_CSTN         (0x40000000)
+#define MCF_LCDC_LPCR_MODE_TFT          (0xC0000000)
+#define MCF_LCDC_LPCR_PBSIZ_1           (0x00000000)
+#define MCF_LCDC_LPCR_PBSIZ_2           (0x10000000)
+#define MCF_LCDC_LPCR_PBSIZ_4           (0x20000000)
+#define MCF_LCDC_LPCR_PBSIZ_8           (0x30000000)
+#define MCF_LCDC_LPCR_BPIX_1bpp         (0x00000000)
+#define MCF_LCDC_LPCR_BPIX_2bpp         (0x02000000)
+#define MCF_LCDC_LPCR_BPIX_4bpp         (0x04000000)
+#define MCF_LCDC_LPCR_BPIX_8bpp         (0x06000000)
+#define MCF_LCDC_LPCR_BPIX_12bpp        (0x08000000)
+#define MCF_LCDC_LPCR_BPIX_16bpp        (0x0A000000)
+#define MCF_LCDC_LPCR_BPIX_18bpp        (0x0C000000)
+
+#define MCF_LCDC_LPCR_PANEL_TYPE(x)     (((x)&0x00000003)<<30) 
+
+/* Bit definitions and macros for MCF_LCDC_LHCR */
+#define MCF_LCDC_LHCR_H_WAIT_2(x)       (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LHCR_H_WAIT_1(x)       (((x)&0x000000FF)<<8)
+#define MCF_LCDC_LHCR_H_WIDTH(x)        (((x)&0x0000003F)<<26)
+
+/* Bit definitions and macros for MCF_LCDC_LVCR */
+#define MCF_LCDC_LVCR_V_WAIT_2(x)       (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LVCR_V_WAIT_1(x)       (((x)&0x000000FF)<<8)
+#define MCF_LCDC_LVCR_V_WIDTH(x)      (((x)&0x0000003F)<<26)
+
+/* Bit definitions and macros for MCF_LCDC_LPOR */
+#define MCF_LCDC_LPOR_POS(x)            (((x)&0x0000001F)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LPCCR */
+#define MCF_LCDC_LPCCR_PW(x)            (((x)&0x000000FF)<<0)
+#define MCF_LCDC_LPCCR_CC_EN            (0x00000100)
+#define MCF_LCDC_LPCCR_SCR(x)           (((x)&0x00000003)<<9)
+#define MCF_LCDC_LPCCR_LDMSK            (0x00008000)
+#define MCF_LCDC_LPCCR_CLS_HI_WIDTH(x)  (((x)&0x000001FF)<<16)
+#define MCF_LCDC_LPCCR_SCR_LINEPULSE    (0x00000000)
+#define MCF_LCDC_LPCCR_SCR_PIXELCLK     (0x00002000)
+#define MCF_LCDC_LPCCR_SCR_LCDCLOCK     (0x00004000)
+
+/* Bit definitions and macros for MCF_LCDC_LDCR */
+#define MCF_LCDC_LDCR_TM(x)             (((x)&0x0000001F)<<0)
+#define MCF_LCDC_LDCR_HM(x)             (((x)&0x0000001F)<<16)
+#define MCF_LCDC_LDCR_BURST             (0x80000000)
+
+/* Bit definitions and macros for MCF_LCDC_LRMCR */
+#define MCF_LCDC_LRMCR_SEL_REF          (0x00000001)
+
+/* Bit definitions and macros for MCF_LCDC_LICR */
+#define MCF_LCDC_LICR_INTCON            (0x00000001)
+#define MCF_LCDC_LICR_INTSYN            (0x00000004)
+#define MCF_LCDC_LICR_GW_INT_CON        (0x00000010)
+
+/* Bit definitions and macros for MCF_LCDC_LIER */
+#define MCF_LCDC_LIER_BOF_EN            (0x00000001)
+#define MCF_LCDC_LIER_EOF_EN            (0x00000002)
+#define MCF_LCDC_LIER_ERR_RES_EN        (0x00000004)
+#define MCF_LCDC_LIER_UDR_ERR_EN        (0x00000008)
+#define MCF_LCDC_LIER_GW_BOF_EN         (0x00000010)
+#define MCF_LCDC_LIER_GW_EOF_EN         (0x00000020)
+#define MCF_LCDC_LIER_GW_ERR_RES_EN     (0x00000040)
+#define MCF_LCDC_LIER_GW_UDR_ERR_EN     (0x00000080)
+
+/* Bit definitions and macros for MCF_LCDC_LISR */
+#define MCF_LCDC_LISR_BOF               (0x00000001)
+#define MCF_LCDC_LISR_EOF               (0x00000002)
+#define MCF_LCDC_LISR_ERR_RES           (0x00000004)
+#define MCF_LCDC_LISR_UDR_ERR           (0x00000008)
+#define MCF_LCDC_LISR_GW_BOF            (0x00000010)
+#define MCF_LCDC_LISR_GW_EOF            (0x00000020)
+#define MCF_LCDC_LISR_GW_ERR_RES        (0x00000040)
+#define MCF_LCDC_LISR_GW_UDR_ERR        (0x00000080)
+
+/* Bit definitions and macros for MCF_LCDC_LGWSAR */
+#define MCF_LCDC_LGWSAR_GWSA(x)         (((x)&0x3FFFFFFF)<<2)
+
+/* Bit definitions and macros for MCF_LCDC_LGWSR */
+#define MCF_LCDC_LGWSR_GWH(x)           (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LGWSR_GWW(x)           (((x)&0x0000003F)<<20)
+
+/* Bit definitions and macros for MCF_LCDC_LGWVPWR */
+#define MCF_LCDC_LGWVPWR_GWVPW(x)       (((x)&0x000003FF)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LGWPOR */
+#define MCF_LCDC_LGWPOR_GWPO(x)         (((x)&0x0000001F)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_LGWPR */
+#define MCF_LCDC_LGWPR_GWYP(x)          (((x)&0x000003FF)<<0)
+#define MCF_LCDC_LGWPR_GWXP(x)          (((x)&0x000003FF)<<16)
+
+/* Bit definitions and macros for MCF_LCDC_LGWCR */
+#define MCF_LCDC_LGWCR_GWCKB(x)         (((x)&0x0000003F)<<0)
+#define MCF_LCDC_LGWCR_GWCKG(x)         (((x)&0x0000003F)<<6)
+#define MCF_LCDC_LGWCR_GWCKR(x)         (((x)&0x0000003F)<<12)
+#define MCF_LCDC_LGWCR_GW_RVS           (0x00200000)
+#define MCF_LCDC_LGWCR_GWE              (0x00400000)
+#define MCF_LCDC_LGWCR_GWCKE            (0x00800000)
+#define MCF_LCDC_LGWCR_GWAV(x)          (((x)&0x000000FF)<<24)
+
+/* Bit definitions and macros for MCF_LCDC_LGWDCR */
+#define MCF_LCDC_LGWDCR_GWTM(x)         (((x)&0x0000001F)<<0)
+#define MCF_LCDC_LGWDCR_GWHM(x)         (((x)&0x0000001F)<<16)
+#define MCF_LCDC_LGWDCR_GWBT            (0x80000000)
+
+/* Bit definitions and macros for MCF_LCDC_LSCR */
+#define MCF_LCDC_LSCR_PS_RISE_DELAY(x)    (((x)&0x0000003F)<<26)
+#define MCF_LCDC_LSCR_CLS_RISE_DELAY(x)   (((x)&0x000000FF)<<16)
+#define MCF_LCDC_LSCR_REV_TOGGLE_DELAY(x) (((x)&0x0000000F)<<8)
+#define MCF_LCDC_LSCR_GRAY_2(x)  		  (((x)&0x0000000F)<<4)
+#define MCF_LCDC_LSCR_GRAY_1(x)  		  (((x)&0x0000000F)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_BPLUT_BASE */
+#define MCF_LCDC_BPLUT_BASE_BASE(x)     (((x)&0xFFFFFFFF)<<0)
+
+/* Bit definitions and macros for MCF_LCDC_GWLUT_BASE */
+#define MCF_LCDC_GWLUT_BASE_BASE(x)     (((x)&0xFFFFFFFF)<<0)
+
+/*********************************************************************
+ *
+ * Phase Locked Loop (PLL)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_PLL_PODR              MCF_REG08(0xFC0C0000)
+#define MCF_PLL_PLLCR             MCF_REG08(0xFC0C0004)
+#define MCF_PLL_PMDR              MCF_REG08(0xFC0C0008)
+#define MCF_PLL_PFDR              MCF_REG08(0xFC0C000C)
+
+/* Bit definitions and macros for MCF_PLL_PODR */
+#define MCF_PLL_PODR_BUSDIV(x)    (((x)&0x0F)<<0)
+#define MCF_PLL_PODR_CPUDIV(x)    (((x)&0x0F)<<4)
+
+/* Bit definitions and macros for MCF_PLL_PLLCR */
+#define MCF_PLL_PLLCR_DITHDEV(x)  (((x)&0x07)<<0)
+#define MCF_PLL_PLLCR_DITHEN      (0x80)
+
+/* Bit definitions and macros for MCF_PLL_PMDR */
+#define MCF_PLL_PMDR_MODDIV(x)    (((x)&0xFF)<<0)
+
+/* Bit definitions and macros for MCF_PLL_PFDR */
+#define MCF_PLL_PFDR_MFD(x)       (((x)&0xFF)<<0)
+
+/*********************************************************************
+ *
+ * System Control Module Registers (SCM)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_SCM_MPR			MCF_REG32(0xFC000000)
+#define MCF_SCM_PACRA			MCF_REG32(0xFC000020)
+#define MCF_SCM_PACRB			MCF_REG32(0xFC000024)
+#define MCF_SCM_PACRC			MCF_REG32(0xFC000028)
+#define MCF_SCM_PACRD			MCF_REG32(0xFC00002C)
+#define MCF_SCM_PACRE			MCF_REG32(0xFC000040)
+#define MCF_SCM_PACRF			MCF_REG32(0xFC000044)
+
+#define MCF_SCM_BCR			MCF_REG32(0xFC040024)
+
+/*********************************************************************
+ *
+ * SDRAM Controller (SDRAMC)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_SDRAMC_SDMR			MCF_REG32(0xFC0B8000)
+#define MCF_SDRAMC_SDCR			MCF_REG32(0xFC0B8004)
+#define MCF_SDRAMC_SDCFG1		MCF_REG32(0xFC0B8008)
+#define MCF_SDRAMC_SDCFG2		MCF_REG32(0xFC0B800C)
+#define MCF_SDRAMC_LIMP_FIX		MCF_REG32(0xFC0B8080)
+#define MCF_SDRAMC_SDDS			MCF_REG32(0xFC0B8100)
+#define MCF_SDRAMC_SDCS0		MCF_REG32(0xFC0B8110)
+#define MCF_SDRAMC_SDCS1		MCF_REG32(0xFC0B8114)
+#define MCF_SDRAMC_SDCS2		MCF_REG32(0xFC0B8118)
+#define MCF_SDRAMC_SDCS3		MCF_REG32(0xFC0B811C)
+#define MCF_SDRAMC_SDCS(x)		MCF_REG32(0xFC0B8110+((x)*0x004))
+
+/* Bit definitions and macros for MCF_SDRAMC_SDMR */
+#define MCF_SDRAMC_SDMR_CMD		(0x00010000)
+#define MCF_SDRAMC_SDMR_AD(x)		(((x)&0x00000FFF)<<18)
+#define MCF_SDRAMC_SDMR_BNKAD(x)	(((x)&0x00000003)<<30)
+#define MCF_SDRAMC_SDMR_BNKAD_LMR	(0x00000000)
+#define MCF_SDRAMC_SDMR_BNKAD_LEMR	(0x40000000)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCR */
+#define MCF_SDRAMC_SDCR_IPALL		(0x00000002)
+#define MCF_SDRAMC_SDCR_IREF		(0x00000004)
+#define MCF_SDRAMC_SDCR_DQS_OE(x)	(((x)&0x0000000F)<<8)
+#define MCF_SDRAMC_SDCR_PS(x)		(((x)&0x00000003)<<12)
+#define MCF_SDRAMC_SDCR_RCNT(x)		(((x)&0x0000003F)<<16)
+#define MCF_SDRAMC_SDCR_OE_RULE		(0x00400000)
+#define MCF_SDRAMC_SDCR_MUX(x)		(((x)&0x00000003)<<24)
+#define MCF_SDRAMC_SDCR_REF		(0x10000000)
+#define MCF_SDRAMC_SDCR_DDR		(0x20000000)
+#define MCF_SDRAMC_SDCR_CKE		(0x40000000)
+#define MCF_SDRAMC_SDCR_MODE_EN		(0x80000000)
+#define MCF_SDRAMC_SDCR_PS_16		(0x00002000)
+#define MCF_SDRAMC_SDCR_PS_32		(0x00000000)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCFG1 */
+#define MCF_SDRAMC_SDCFG1_WTLAT(x)	(((x)&0x00000007)<<4)
+#define MCF_SDRAMC_SDCFG1_REF2ACT(x)	(((x)&0x0000000F)<<8)
+#define MCF_SDRAMC_SDCFG1_PRE2ACT(x)	(((x)&0x00000007)<<12)
+#define MCF_SDRAMC_SDCFG1_ACT2RW(x)	(((x)&0x00000007)<<16)
+#define MCF_SDRAMC_SDCFG1_RDLAT(x)	(((x)&0x0000000F)<<20)
+#define MCF_SDRAMC_SDCFG1_SWT2RD(x)	(((x)&0x00000007)<<24)
+#define MCF_SDRAMC_SDCFG1_SRD2RW(x)	(((x)&0x0000000F)<<28)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCFG2 */
+#define MCF_SDRAMC_SDCFG2_BL(x)		(((x)&0x0000000F)<<16)
+#define MCF_SDRAMC_SDCFG2_BRD2WT(x)	(((x)&0x0000000F)<<20)
+#define MCF_SDRAMC_SDCFG2_BWT2RW(x)	(((x)&0x0000000F)<<24)
+#define MCF_SDRAMC_SDCFG2_BRD2PRE(x)	(((x)&0x0000000F)<<28)
+
+/* Device Errata - LIMP mode work around */
+#define MCF_SDRAMC_REFRESH		(0x40000000)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDDS */
+#define MCF_SDRAMC_SDDS_SB_D(x)		(((x)&0x00000003)<<0)
+#define MCF_SDRAMC_SDDS_SB_S(x)		(((x)&0x00000003)<<2)
+#define MCF_SDRAMC_SDDS_SB_A(x)		(((x)&0x00000003)<<4)
+#define MCF_SDRAMC_SDDS_SB_C(x)		(((x)&0x00000003)<<6)
+#define MCF_SDRAMC_SDDS_SB_E(x)		(((x)&0x00000003)<<8)
+
+/* Bit definitions and macros for MCF_SDRAMC_SDCS */
+#define MCF_SDRAMC_SDCS_CSSZ(x)		(((x)&0x0000001F)<<0)
+#define MCF_SDRAMC_SDCS_BASE(x)		(((x)&0x00000FFF)<<20)
+#define MCF_SDRAMC_SDCS_BA(x)		((x)&0xFFF00000)
+#define MCF_SDRAMC_SDCS_CSSZ_DIABLE	(0x00000000)
+#define MCF_SDRAMC_SDCS_CSSZ_1MBYTE	(0x00000013)
+#define MCF_SDRAMC_SDCS_CSSZ_2MBYTE	(0x00000014)
+#define MCF_SDRAMC_SDCS_CSSZ_4MBYTE	(0x00000015)
+#define MCF_SDRAMC_SDCS_CSSZ_8MBYTE	(0x00000016)
+#define MCF_SDRAMC_SDCS_CSSZ_16MBYTE	(0x00000017)
+#define MCF_SDRAMC_SDCS_CSSZ_32MBYTE	(0x00000018)
+#define MCF_SDRAMC_SDCS_CSSZ_64MBYTE	(0x00000019)
+#define MCF_SDRAMC_SDCS_CSSZ_128MBYTE	(0x0000001A)
+#define MCF_SDRAMC_SDCS_CSSZ_256MBYTE	(0x0000001B)
+#define MCF_SDRAMC_SDCS_CSSZ_512MBYTE	(0x0000001C)
+#define MCF_SDRAMC_SDCS_CSSZ_1GBYTE	(0x0000001D)
+#define MCF_SDRAMC_SDCS_CSSZ_2GBYTE	(0x0000001E)
+#define MCF_SDRAMC_SDCS_CSSZ_4GBYTE	(0x0000001F)
+
+/*********************************************************************
+ *
+ *      FlexCAN module registers
+ *
+ *********************************************************************/
+#define MCF_FLEXCAN_BASEADDR(x)		(0xFC020000+(x)*0x0800)
+#define MCF_FLEXCAN_CANMCR(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x00)
+#define MCF_FLEXCAN_CANCTRL(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x04)
+#define MCF_FLEXCAN_TIMER(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x08)
+#define MCF_FLEXCAN_RXGMASK(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x10)
+#define MCF_FLEXCAN_RX14MASK(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x14)
+#define MCF_FLEXCAN_RX15MASK(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x18)
+#define MCF_FLEXCAN_ERRCNT(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x1C)
+#define MCF_FLEXCAN_ERRSTAT(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x20)
+#define MCF_FLEXCAN_IMASK(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x28)
+#define MCF_FLEXCAN_IFLAG(x)		MCF_REG32(0xFC020000+(x)*0x0800+0x30)
+
+#define MCF_FLEXCAN_MB_CNT(x,y)		MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x0)
+#define MCF_FLEXCAN_MB_ID(x,y)		MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x4)
+#define MCF_FLEXCAN_MB_DB(x,y,z)	MCF_REG08(0xFC020080+(x)*0x0800+(y)*0x10+0x8+(z)*0x1)
+
+/*
+ *      FlexCAN Module Configuration Register
+ */
+#define CANMCR_MDIS		(0x80000000)
+#define CANMCR_FRZ		(0x40000000)
+#define CANMCR_HALT		(0x10000000)
+#define CANMCR_SOFTRST		(0x02000000)
+#define CANMCR_FRZACK		(0x01000000)
+#define CANMCR_SUPV		(0x00800000)
+#define CANMCR_MAXMB(x)         ((x)&0x0F)
+
+/*
+ *      FlexCAN Control Register
+ */
+#define CANCTRL_PRESDIV(x)      (((x)&0xFF)<<24)
+#define CANCTRL_RJW(x)          (((x)&0x03)<<22)
+#define CANCTRL_PSEG1(x)        (((x)&0x07)<<19)
+#define CANCTRL_PSEG2(x)        (((x)&0x07)<<16)
+#define CANCTRL_BOFFMSK         (0x00008000)
+#define CANCTRL_ERRMSK	        (0x00004000)
+#define CANCTRL_CLKSRC		(0x00002000)
+#define CANCTRL_LPB	        (0x00001000)
+#define CANCTRL_SAMP	        (0x00000080)
+#define CANCTRL_BOFFREC         (0x00000040)
+#define CANCTRL_TSYNC           (0x00000020)
+#define CANCTRL_LBUF            (0x00000010)
+#define CANCTRL_LOM             (0x00000008)
+#define CANCTRL_PROPSEG(x)      ((x)&0x07)
+
+/*
+ *      FlexCAN Error Counter Register
+ */
+#define ERRCNT_RXECTR(x)        (((x)&0xFF)<<8)
+#define ERRCNT_TXECTR(x)        ((x)&0xFF)
+
+/*
+ *      FlexCAN Error and Status Register
+ */
+#define ERRSTAT_BITERR(x)       (((x)&0x03)<<14)
+#define ERRSTAT_ACKERR           (0x00002000)
+#define ERRSTAT_CRCERR           (0x00001000)
+#define ERRSTAT_FRMERR           (0x00000800)
+#define ERRSTAT_STFERR           (0x00000400)
+#define ERRSTAT_TXWRN            (0x00000200)
+#define ERRSTAT_RXWRN            (0x00000100)
+#define ERRSTAT_IDLE             (0x00000080)
+#define ERRSTAT_TXRX             (0x00000040)
+#define ERRSTAT_FLTCONF(x)       (((x)&0x03)<<4)
+#define ERRSTAT_BOFFINT          (0x00000004)
+#define ERRSTAT_ERRINT           (0x00000002)
+
+/*
+ *      Interrupt Mask Register
+ */
+#define IMASK_BUF15M		(0x8000)
+#define IMASK_BUF14M		(0x4000)
+#define IMASK_BUF13M		(0x2000)
+#define IMASK_BUF12M		(0x1000)
+#define IMASK_BUF11M		(0x0800)
+#define IMASK_BUF10M		(0x0400)
+#define IMASK_BUF9M		(0x0200)
+#define IMASK_BUF8M		(0x0100)
+#define IMASK_BUF7M		(0x0080)
+#define IMASK_BUF6M		(0x0040)
+#define IMASK_BUF5M		(0x0020)
+#define IMASK_BUF4M		(0x0010)
+#define IMASK_BUF3M		(0x0008)
+#define IMASK_BUF2M		(0x0004)
+#define IMASK_BUF1M		(0x0002)
+#define IMASK_BUF0M		(0x0001)
+#define IMASK_BUFnM(x)		(0x1<<(x))
+#define IMASK_BUFF_ENABLE_ALL	(0x1111)
+#define IMASK_BUFF_DISABLE_ALL	(0x0000)
+
+/*
+ *      Interrupt Flag Register
+ */
+#define IFLAG_BUF15M		(0x8000)
+#define IFLAG_BUF14M		(0x4000)
+#define IFLAG_BUF13M		(0x2000)
+#define IFLAG_BUF12M		(0x1000)
+#define IFLAG_BUF11M		(0x0800)
+#define IFLAG_BUF10M		(0x0400)
+#define IFLAG_BUF9M		(0x0200)
+#define IFLAG_BUF8M		(0x0100)
+#define IFLAG_BUF7M		(0x0080)
+#define IFLAG_BUF6M		(0x0040)
+#define IFLAG_BUF5M		(0x0020)
+#define IFLAG_BUF4M		(0x0010)
+#define IFLAG_BUF3M		(0x0008)
+#define IFLAG_BUF2M		(0x0004)
+#define IFLAG_BUF1M		(0x0002)
+#define IFLAG_BUF0M		(0x0001)
+#define IFLAG_BUFF_SET_ALL	(0xFFFF)
+#define IFLAG_BUFF_CLEAR_ALL	(0x0000)
+#define IFLAG_BUFnM(x)		(0x1<<(x))
+
+/*
+ *      Message Buffers
+ */
+#define MB_CNT_CODE(x)		(((x)&0x0F)<<24)
+#define MB_CNT_SRR		(0x00400000)
+#define MB_CNT_IDE		(0x00200000)
+#define MB_CNT_RTR		(0x00100000)
+#define MB_CNT_LENGTH(x)	(((x)&0x0F)<<16)
+#define MB_CNT_TIMESTAMP(x)	((x)&0xFFFF)
+#define MB_ID_STD(x)		(((x)&0x07FF)<<18)
+#define MB_ID_EXT(x)		((x)&0x3FFFF)
+
+/*********************************************************************
+ *
+ * Edge Port Module (EPORT)
+ *
+ *********************************************************************/
+
+/* Register read/write macros */
+#define MCF_EPORT_EPPAR                MCF_REG16(0xFC094000)
+#define MCF_EPORT_EPDDR                MCF_REG08(0xFC094002)
+#define MCF_EPORT_EPIER                MCF_REG08(0xFC094003)
+#define MCF_EPORT_EPDR                 MCF_REG08(0xFC094004)
+#define MCF_EPORT_EPPDR                MCF_REG08(0xFC094005)
+#define MCF_EPORT_EPFR                 MCF_REG08(0xFC094006)
+
+/* Bit definitions and macros for MCF_EPORT_EPPAR */
+#define MCF_EPORT_EPPAR_EPPA1(x)       (((x)&0x0003)<<2)
+#define MCF_EPORT_EPPAR_EPPA2(x)       (((x)&0x0003)<<4)
+#define MCF_EPORT_EPPAR_EPPA3(x)       (((x)&0x0003)<<6)
+#define MCF_EPORT_EPPAR_EPPA4(x)       (((x)&0x0003)<<8)
+#define MCF_EPORT_EPPAR_EPPA5(x)       (((x)&0x0003)<<10)
+#define MCF_EPORT_EPPAR_EPPA6(x)       (((x)&0x0003)<<12)
+#define MCF_EPORT_EPPAR_EPPA7(x)       (((x)&0x0003)<<14)
+#define MCF_EPORT_EPPAR_LEVEL          (0)
+#define MCF_EPORT_EPPAR_RISING         (1)
+#define MCF_EPORT_EPPAR_FALLING        (2)
+#define MCF_EPORT_EPPAR_BOTH           (3)
+#define MCF_EPORT_EPPAR_EPPA7_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA7_RISING   (0x4000)
+#define MCF_EPORT_EPPAR_EPPA7_FALLING  (0x8000)
+#define MCF_EPORT_EPPAR_EPPA7_BOTH     (0xC000)
+#define MCF_EPORT_EPPAR_EPPA6_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA6_RISING   (0x1000)
+#define MCF_EPORT_EPPAR_EPPA6_FALLING  (0x2000)
+#define MCF_EPORT_EPPAR_EPPA6_BOTH     (0x3000)
+#define MCF_EPORT_EPPAR_EPPA5_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA5_RISING   (0x0400)
+#define MCF_EPORT_EPPAR_EPPA5_FALLING  (0x0800)
+#define MCF_EPORT_EPPAR_EPPA5_BOTH     (0x0C00)
+#define MCF_EPORT_EPPAR_EPPA4_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA4_RISING   (0x0100)
+#define MCF_EPORT_EPPAR_EPPA4_FALLING  (0x0200)
+#define MCF_EPORT_EPPAR_EPPA4_BOTH     (0x0300)
+#define MCF_EPORT_EPPAR_EPPA3_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA3_RISING   (0x0040)
+#define MCF_EPORT_EPPAR_EPPA3_FALLING  (0x0080)
+#define MCF_EPORT_EPPAR_EPPA3_BOTH     (0x00C0)
+#define MCF_EPORT_EPPAR_EPPA2_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA2_RISING   (0x0010)
+#define MCF_EPORT_EPPAR_EPPA2_FALLING  (0x0020)
+#define MCF_EPORT_EPPAR_EPPA2_BOTH     (0x0030)
+#define MCF_EPORT_EPPAR_EPPA1_LEVEL    (0x0000)
+#define MCF_EPORT_EPPAR_EPPA1_RISING   (0x0004)
+#define MCF_EPORT_EPPAR_EPPA1_FALLING  (0x0008)
+#define MCF_EPORT_EPPAR_EPPA1_BOTH     (0x000C)
+
+/* Bit definitions and macros for MCF_EPORT_EPDDR */
+#define MCF_EPORT_EPDDR_EPDD1          (0x02)
+#define MCF_EPORT_EPDDR_EPDD2          (0x04)
+#define MCF_EPORT_EPDDR_EPDD3          (0x08)
+#define MCF_EPORT_EPDDR_EPDD4          (0x10)
+#define MCF_EPORT_EPDDR_EPDD5          (0x20)
+#define MCF_EPORT_EPDDR_EPDD6          (0x40)
+#define MCF_EPORT_EPDDR_EPDD7          (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPIER */
+#define MCF_EPORT_EPIER_EPIE1          (0x02)
+#define MCF_EPORT_EPIER_EPIE2          (0x04)
+#define MCF_EPORT_EPIER_EPIE3          (0x08)
+#define MCF_EPORT_EPIER_EPIE4          (0x10)
+#define MCF_EPORT_EPIER_EPIE5          (0x20)
+#define MCF_EPORT_EPIER_EPIE6          (0x40)
+#define MCF_EPORT_EPIER_EPIE7          (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPDR */
+#define MCF_EPORT_EPDR_EPD1            (0x02)
+#define MCF_EPORT_EPDR_EPD2            (0x04)
+#define MCF_EPORT_EPDR_EPD3            (0x08)
+#define MCF_EPORT_EPDR_EPD4            (0x10)
+#define MCF_EPORT_EPDR_EPD5            (0x20)
+#define MCF_EPORT_EPDR_EPD6            (0x40)
+#define MCF_EPORT_EPDR_EPD7            (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPPDR */
+#define MCF_EPORT_EPPDR_EPPD1          (0x02)
+#define MCF_EPORT_EPPDR_EPPD2          (0x04)
+#define MCF_EPORT_EPPDR_EPPD3          (0x08)
+#define MCF_EPORT_EPPDR_EPPD4          (0x10)
+#define MCF_EPORT_EPPDR_EPPD5          (0x20)
+#define MCF_EPORT_EPPDR_EPPD6          (0x40)
+#define MCF_EPORT_EPPDR_EPPD7          (0x80)
+
+/* Bit definitions and macros for MCF_EPORT_EPFR */
+#define MCF_EPORT_EPFR_EPF1            (0x02)
+#define MCF_EPORT_EPFR_EPF2            (0x04)
+#define MCF_EPORT_EPFR_EPF3            (0x08)
+#define MCF_EPORT_EPFR_EPF4            (0x10)
+#define MCF_EPORT_EPFR_EPF5            (0x20)
+#define MCF_EPORT_EPFR_EPF6            (0x40)
+#define MCF_EPORT_EPFR_EPF7            (0x80)
+
+/********************************************************************/
+#endif	/* m532xsim_h */
diff --git a/include/asm-m68knommu/mcfcache.h b/include/asm-m68knommu/mcfcache.h
index 9cb4014..7b61a8a 100644
--- a/include/asm-m68knommu/mcfcache.h
+++ b/include/asm-m68knommu/mcfcache.h
@@ -11,7 +11,6 @@
 #define	__M68KNOMMU_MCFCACHE_H
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	The different ColdFire families have different cache arrangments.
@@ -93,6 +92,21 @@
 .endm
 #endif /* CONFIG_M5249 || CONFIG_M5307 */
 
+#if defined(CONFIG_M532x)
+.macro CACHE_ENABLE
+	movel	#0x01000000,%d0		/* invalidate cache cmd */
+	movec	%d0,%CACR		/* do invalidate cache */
+	nop
+	movel	#0x4001C000,%d0		/* set SDRAM cached (write-thru) */
+	movec	%d0,%ACR0
+	movel	#0x00000000,%d0		/* no other regions cached */
+	movec	%d0,%ACR1
+	movel	#0x80000200,%d0		/* setup cache mask */
+	movec	%d0,%CACR		/* enable cache */
+	nop
+.endm
+#endif /* CONFIG_M532x */
+
 #if defined(CONFIG_M5407)
 /*
  *	Version 4 cores have a true harvard style separate instruction
diff --git a/include/asm-m68knommu/mcfdma.h b/include/asm-m68knommu/mcfdma.h
index b93f8ba..ea729e8 100644
--- a/include/asm-m68knommu/mcfdma.h
+++ b/include/asm-m68knommu/mcfdma.h
@@ -11,7 +11,6 @@
 #define	mcfdma_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Get address specific defines for this Coldfire member.
diff --git a/include/asm-m68knommu/mcfmbus.h b/include/asm-m68knommu/mcfmbus.h
index 4762589..13df9d4 100644
--- a/include/asm-m68knommu/mcfmbus.h
+++ b/include/asm-m68knommu/mcfmbus.h
@@ -11,7 +11,6 @@
 
 #ifndef mcfmbus_h
 #define mcfmbus_h
-#include <linux/config.h>
 
 
 #define MCFMBUS_BASE		0x280
diff --git a/include/asm-m68knommu/mcfne.h b/include/asm-m68knommu/mcfne.h
index a71b1c8..c920ccd 100644
--- a/include/asm-m68knommu/mcfne.h
+++ b/include/asm-m68knommu/mcfne.h
@@ -18,7 +18,6 @@
 #define	mcfne_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Support for NE2000 clones devices in ColdFire based boards.
diff --git a/include/asm-m68knommu/mcfpci.h b/include/asm-m68knommu/mcfpci.h
index d622904..f1507dd 100644
--- a/include/asm-m68knommu/mcfpci.h
+++ b/include/asm-m68knommu/mcfpci.h
@@ -12,7 +12,6 @@
 #define	mcfpci_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
diff --git a/include/asm-m68knommu/mcfpit.h b/include/asm-m68knommu/mcfpit.h
index a685f1b..f570cf6 100644
--- a/include/asm-m68knommu/mcfpit.h
+++ b/include/asm-m68knommu/mcfpit.h
@@ -11,7 +11,6 @@
 #define	mcfpit_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Get address specific defines for the 5270/5271, 5280/5282, and 5208.
@@ -29,11 +28,9 @@
 /*
  *	Define the PIT timer register set addresses.
  */
-struct mcfpit {
-	unsigned short	pcsr;			/* PIT control and status */
-	unsigned short	pmr;			/* PIT modulus register */
-	unsigned short	pcntr;			/* PIT count register */
-} __attribute__((packed));
+#define	MCFPIT_PCSR		0x0		/* PIT control register */
+#define	MCFPIT_PMR		0x2		/* PIT modulus register */
+#define	MCFPIT_PCNTR		0x4		/* PIT count register */
 
 /*
  *	Bit definitions for the PIT Control and Status register.
diff --git a/include/asm-m68knommu/mcfsim.h b/include/asm-m68knommu/mcfsim.h
index 81d74a3..1074ae7 100644
--- a/include/asm-m68knommu/mcfsim.h
+++ b/include/asm-m68knommu/mcfsim.h
@@ -12,7 +12,6 @@
 #define	mcfsim_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Include 5204, 5206/e, 5235, 5249, 5270/5271, 5272, 5280/5282,
@@ -36,6 +35,8 @@
 #include <asm/m528xsim.h>
 #elif defined(CONFIG_M5307)
 #include <asm/m5307sim.h>
+#elif defined(CONFIG_M532x)
+#include <asm/m532xsim.h>
 #elif defined(CONFIG_M5407)
 #include <asm/m5407sim.h>
 #endif
@@ -101,6 +102,7 @@
 #define	MCFSIM_IMR_MASKALL	0x3ffe		/* All intr sources */
 #endif
 
+
 /*
  *	PIT interrupt settings, if not found in mXXXXsim.h file.
  */
diff --git a/include/asm-m68knommu/mcfsmc.h b/include/asm-m68knommu/mcfsmc.h
index 2583900..2d7a4db 100644
--- a/include/asm-m68knommu/mcfsmc.h
+++ b/include/asm-m68knommu/mcfsmc.h
@@ -17,7 +17,6 @@
  *	allow 8 bit accesses. So this code is 16bit access only.
  */
 
-#include <linux/config.h>
 
 #undef	outb
 #undef	inb
diff --git a/include/asm-m68knommu/mcftimer.h b/include/asm-m68knommu/mcftimer.h
index 0f47164..6f4d796 100644
--- a/include/asm-m68knommu/mcftimer.h
+++ b/include/asm-m68knommu/mcftimer.h
@@ -3,7 +3,7 @@
 /*
  *	mcftimer.h -- ColdFire internal TIMER support defines.
  *
- *	(C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	(C) Copyright 1999-2006, Greg Ungerer <gerg@snapgear.com>
  * 	(C) Copyright 2000, Lineo Inc. (www.lineo.com) 
  */
 
@@ -12,7 +12,6 @@
 #define	mcftimer_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Get address specific defines for this ColdFire member.
@@ -28,6 +27,11 @@
 #elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
 #define MCFTIMER_BASE1		0x140           /* Base address of TIMER1 */
 #define MCFTIMER_BASE2		0x180           /* Base address of TIMER2 */
+#elif defined(CONFIG_M532x)
+#define MCFTIMER_BASE1		0xfc070000	/* Base address of TIMER1 */
+#define MCFTIMER_BASE2		0xfc074000	/* Base address of TIMER2 */
+#define MCFTIMER_BASE3		0xfc078000	/* Base address of TIMER3 */
+#define MCFTIMER_BASE4		0xfc07c000	/* Base address of TIMER4 */
 #endif
 
 
@@ -35,23 +39,14 @@
  *	Define the TIMER register set addresses.
  */
 #define	MCFTIMER_TMR		0x00		/* Timer Mode reg (r/w) */
-#define	MCFTIMER_TRR		0x02		/* Timer Reference (r/w) */
-#define	MCFTIMER_TCR		0x04		/* Timer Capture reg (r/w) */
-#define	MCFTIMER_TCN		0x06		/* Timer Counter reg (r/w) */
+#define	MCFTIMER_TRR		0x04		/* Timer Reference (r/w) */
+#define	MCFTIMER_TCR		0x08		/* Timer Capture reg (r/w) */
+#define	MCFTIMER_TCN		0x0C		/* Timer Counter reg (r/w) */
+#if defined(CONFIG_M532x)
+#define	MCFTIMER_TER		0x03		/* Timer Event reg (r/w) */
+#else
 #define	MCFTIMER_TER		0x11		/* Timer Event reg (r/w) */
-
-struct mcftimer {
-	unsigned short	tmr;			/* Timer Mode reg (r/w) */
-	unsigned short	reserved1;
-	unsigned short	trr;			/* Timer Reference (r/w) */
-	unsigned short	reserved2;
-	unsigned short	tcr;			/* Timer Capture reg (r/w) */
-	unsigned short	reserved3;
-	unsigned short	tcn;			/* Timer Counter reg (r/w) */
-	unsigned short	reserved4;
-	unsigned char	reserved5;
-	unsigned char	ter;			/* Timer Event reg (r/w) */
-} __attribute__((packed));
+#endif
 
 /*
  *	Bit definitions for the Timer Mode Register (TMR).
diff --git a/include/asm-m68knommu/mcfuart.h b/include/asm-m68knommu/mcfuart.h
index b016fad..dc0146c 100644
--- a/include/asm-m68knommu/mcfuart.h
+++ b/include/asm-m68knommu/mcfuart.h
@@ -12,7 +12,6 @@
 #define	mcfuart_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /*
  *	Define the base address of the UARTS within the MBAR address
@@ -45,6 +44,10 @@
 #define MCFUART_BASE1		0x60000		/* Base address of UART1 */
 #define MCFUART_BASE2		0x64000		/* Base address of UART2 */
 #define MCFUART_BASE3		0x68000		/* Base address of UART2 */
+#elif defined(CONFIG_M532x)
+#define MCFUART_BASE1		0xfc060000	/* Base address of UART1 */
+#define MCFUART_BASE2		0xfc064000	/* Base address of UART2 */
+#define MCFUART_BASE3		0xfc068000	/* Base address of UART3 */
 #endif
 
 
diff --git a/include/asm-m68knommu/mcfwdebug.h b/include/asm-m68knommu/mcfwdebug.h
index 6ceae10..27f70e4 100644
--- a/include/asm-m68knommu/mcfwdebug.h
+++ b/include/asm-m68knommu/mcfwdebug.h
@@ -10,7 +10,6 @@
 #ifndef mcfdebug_h
 #define mcfdebug_h
 /****************************************************************************/
-#include <linux/config.h>
 
 /* Define the debug module registers */
 #define MCFDEBUG_CSR	0x0			/* Configuration status		*/
diff --git a/include/asm-m68knommu/mmu_context.h b/include/asm-m68knommu/mmu_context.h
index 1e080ec..6c077d3 100644
--- a/include/asm-m68knommu/mmu_context.h
+++ b/include/asm-m68knommu/mmu_context.h
@@ -1,7 +1,6 @@
 #ifndef __M68KNOMMU_MMU_CONTEXT_H
 #define __M68KNOMMU_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
diff --git a/include/asm-m68knommu/nettel.h b/include/asm-m68knommu/nettel.h
index 9bda307..0299f6a 100644
--- a/include/asm-m68knommu/nettel.h
+++ b/include/asm-m68knommu/nettel.h
@@ -13,7 +13,6 @@
 #define	nettel_h
 /****************************************************************************/
 
-#include <linux/config.h>
 
 /****************************************************************************/
 #ifdef CONFIG_NETtel
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index 942dfbe..a22bf5a 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_PAGE_H
 #define _M68KNOMMU_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 
diff --git a/include/asm-m68knommu/page_offset.h b/include/asm-m68knommu/page_offset.h
index 2b45645..d4e73e0 100644
--- a/include/asm-m68knommu/page_offset.h
+++ b/include/asm-m68knommu/page_offset.h
@@ -1,47 +1,5 @@
 
-#include <linux/config.h>
 
 /* This handles the memory map.. */
-
-#ifdef CONFIG_COLDFIRE
-#if defined(CONFIG_SMALL)
-#define PAGE_OFFSET_RAW		0x30020000
-#elif defined(CONFIG_CFV240)
-#define PAGE_OFFSET_RAW		0x02000000
-#else
-#define PAGE_OFFSET_RAW		0x00000000
-#endif
-#endif
-
-#ifdef CONFIG_M68360
-#define PAGE_OFFSET_RAW     0x00000000
-#endif
-
-#ifdef CONFIG_PILOT
-#ifdef CONFIG_M68328
-#define PAGE_OFFSET_RAW		0x10000000
-#endif
-#ifdef CONFIG_M68EZ328
-#define PAGE_OFFSET_RAW		0x00000000
-#endif
-#endif
-#ifdef CONFIG_UCSIMM
-#define PAGE_OFFSET_RAW		0x00000000
-#endif
-
-#if defined(CONFIG_UCDIMM) || defined(CONFIG_DRAGEN2)
-#ifdef CONFIG_M68VZ328 
-#define PAGE_OFFSET_RAW		0x00000000
-#endif /* CONFIG_M68VZ328 */
-#endif /* CONFIG_UCDIMM */
-
-#ifdef CONFIG_M68EZ328ADS
-#define PAGE_OFFSET_RAW		0x00000000
-#endif
-#ifdef CONFIG_ALMA_ANS
-#define PAGE_OFFSET_RAW		0x00000000
-#endif
-#ifdef CONFIG_M68EN302
-#define PAGE_OFFSET_RAW		0x00000000
-#endif
+#define	PAGE_OFFSET_RAW		CONFIG_RAMBASE
 
diff --git a/include/asm-m68knommu/param.h b/include/asm-m68knommu/param.h
index 3f57d5db..4c9904d 100644
--- a/include/asm-m68knommu/param.h
+++ b/include/asm-m68knommu/param.h
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_PARAM_H
 #define _M68KNOMMU_PARAM_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_CLEOPATRA)
 #define	HZ 1000
diff --git a/include/asm-m68knommu/pgtable.h b/include/asm-m68knommu/pgtable.h
index 0089305..549ad23 100644
--- a/include/asm-m68knommu/pgtable.h
+++ b/include/asm-m68knommu/pgtable.h
@@ -7,7 +7,6 @@
  * (C) Copyright 2000-2002, Greg Ungerer <gerg@snapgear.com>
  */
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <asm/processor.h>
 #include <asm/page.h>
diff --git a/include/asm-m68knommu/processor.h b/include/asm-m68knommu/processor.h
index ba393b1..0ee158e 100644
--- a/include/asm-m68knommu/processor.h
+++ b/include/asm-m68knommu/processor.h
@@ -13,7 +13,6 @@
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/types.h>
 #include <asm/segment.h>
@@ -79,19 +78,31 @@
 }
 
 /*
+ * Coldfire stacks need to be re-aligned on trap exit, conventional
+ * 68k can handle this case cleanly.
+ */
+#if defined(CONFIG_COLDFIRE)
+#define	reformat(_regs)		do { (_regs)->format = 0x4; } while(0)
+#else
+#define	reformat(_regs)		do { } while (0)
+#endif
+
+/*
  * Do necessary setup to start up a newly executed thread.
  *
  * pass the data segment into user programs if it exists,
  * it can't hurt anything as far as I can tell
  */
-#define start_thread(_regs, _pc, _usp)           \
-do {                                             \
-	set_fs(USER_DS); /* reads from user space */ \
-	(_regs)->pc = (_pc);                         \
-	if (current->mm)                             \
-		(_regs)->d5 = current->mm->start_data;   \
-	(_regs)->sr &= ~0x2000;                      \
-	wrusp(_usp);                                 \
+#define start_thread(_regs, _pc, _usp)			\
+do {							\
+	set_fs(USER_DS); /* reads from user space */	\
+	(_regs)->pc = (_pc);				\
+	((struct switch_stack *)(_regs))[-1].a6 = 0;	\
+	reformat(_regs);				\
+	if (current->mm)				\
+		(_regs)->d5 = current->mm->start_data;	\
+	(_regs)->sr &= ~0x2000;				\
+	wrusp(_usp);					\
 } while(0)
 
 /* Forward declaration, a strange C thing */
diff --git a/include/asm-m68knommu/ptrace.h b/include/asm-m68knommu/ptrace.h
index f65bd90..47258e8 100644
--- a/include/asm-m68knommu/ptrace.h
+++ b/include/asm-m68knommu/ptrace.h
@@ -46,11 +46,9 @@
 #else
   unsigned short sr;
   unsigned long  pc;
-#ifndef NO_FORMAT_VEC
   unsigned format :  4; /* frame format specifier */
   unsigned vector : 12; /* vector offset */
 #endif
-#endif
 };
 
 /*
@@ -70,7 +68,7 @@
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
 #define PTRACE_GETREGS            12
 #define PTRACE_SETREGS            13
-#ifdef COFNIG_FPU
+#ifdef CONFIG_FPU
 #define PTRACE_GETFPREGS          14
 #define PTRACE_SETFPREGS          15
 #endif
diff --git a/include/asm-m68knommu/semaphore-helper.h b/include/asm-m68knommu/semaphore-helper.h
index a658641..43da7bc 100644
--- a/include/asm-m68knommu/semaphore-helper.h
+++ b/include/asm-m68knommu/semaphore-helper.h
@@ -9,7 +9,6 @@
  * m68k version by Andreas Schwab
  */
 
-#include <linux/config.h>
 
 /*
  * These two _must_ execute atomically wrt each other.
diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
index 6338afc..2bbe2db 100644
--- a/include/asm-m68knommu/system.h
+++ b/include/asm-m68knommu/system.h
@@ -1,7 +1,6 @@
 #ifndef _M68KNOMMU_SYSTEM_H
 #define _M68KNOMMU_SYSTEM_H
 
-#include <linux/config.h> /* get configuration macros */
 #include <linux/linkage.h>
 #include <asm/segment.h>
 #include <asm/entry.h>
diff --git a/include/asm-m68knommu/unaligned.h b/include/asm-m68knommu/unaligned.h
index 8876f03..869e9dd2 100644
--- a/include/asm-m68knommu/unaligned.h
+++ b/include/asm-m68knommu/unaligned.h
@@ -1,7 +1,6 @@
 #ifndef __M68K_UNALIGNED_H
 #define __M68K_UNALIGNED_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_COLDFIRE
 
diff --git a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h
index 5373988..1b2abdf 100644
--- a/include/asm-m68knommu/unistd.h
+++ b/include/asm-m68knommu/unistd.h
@@ -286,6 +286,8 @@
 #define __NR_request_key	280
 #define __NR_keyctl		281
  
+#ifdef __KERNEL__
+
 #define NR_syscalls		282
 
 /* user-visible error numbers are in the range -1 - -122: see
@@ -437,7 +439,6 @@
   return (type)__res;								\
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -460,7 +461,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -515,7 +515,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -525,4 +525,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
diff --git a/include/asm-mips/a.out.h b/include/asm-mips/a.out.h
index 2b3dc3b..ef33c3f 100644
--- a/include/asm-mips/a.out.h
+++ b/include/asm-mips/a.out.h
@@ -10,7 +10,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #endif
 
diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
index 1386af1..45c706e 100644
--- a/include/asm-mips/addrspace.h
+++ b/include/asm-mips/addrspace.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_ADDRSPACE_H
 #define _ASM_ADDRSPACE_H
 
-#include <linux/config.h>
 #include <spaces.h>
 
 /*
@@ -133,57 +132,22 @@
     || defined (CONFIG_CPU_NEVADA)					\
     || defined (CONFIG_CPU_TX49XX)					\
     || defined (CONFIG_CPU_MIPS64)
-#define KUSIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define KUSIZE_64	_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define K0SIZE		_LLCONST_(0x0000001000000000)	/* 2^^36 */
-#define K1SIZE		_LLCONST_(0x0000001000000000)	/* 2^^36 */
-#define K2SIZE		_LLCONST_(0x000000ff80000000)
-#define KSEGSIZE	_LLCONST_(0x000000ff80000000)	/* max syssegsz */
 #define TO_PHYS_MASK	_LLCONST_(0x0000000fffffffff)	/* 2^^36 - 1 */
 #endif
 
 #if defined (CONFIG_CPU_R8000)
 /* We keep KUSIZE consistent with R4000 for now (2^^40) instead of (2^^48) */
-#define KUSIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define KUSIZE_64	_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define K0SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define K1SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define K2SIZE		_LLCONST_(0x0001000000000000)
-#define KSEGSIZE	_LLCONST_(0x0000010000000000)	/* max syssegsz */
 #define TO_PHYS_MASK	_LLCONST_(0x000000ffffffffff)	/* 2^^40 - 1 */
 #endif
 
 #if defined (CONFIG_CPU_R10000)
-#define KUSIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define KUSIZE_64	_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define K0SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define K1SIZE		_LLCONST_(0x0000010000000000)	/* 2^^40 */
-#define K2SIZE		_LLCONST_(0x00000fff80000000)
-#define KSEGSIZE	_LLCONST_(0x00000fff80000000)	/* max syssegsz */
 #define TO_PHYS_MASK	_LLCONST_(0x000000ffffffffff)	/* 2^^40 - 1 */
 #endif
 
 #if defined(CONFIG_CPU_SB1) || defined(CONFIG_CPU_SB1A)
-#define KUSIZE		_LLCONST_(0x0000100000000000)	/* 2^^44 */
-#define KUSIZE_64	_LLCONST_(0x0000100000000000)	/* 2^^44 */
-#define K0SIZE		_LLCONST_(0x0000100000000000)	/* 2^^44 */
-#define K1SIZE		_LLCONST_(0x0000100000000000)	/* 2^^44 */
-#define K2SIZE		_LLCONST_(0x0000ffff80000000)
-#define KSEGSIZE	_LLCONST_(0x0000ffff80000000)	/* max syssegsz */
 #define TO_PHYS_MASK	_LLCONST_(0x00000fffffffffff)	/* 2^^44 - 1 */
 #endif
 
-/*
- * Further names for SGI source compatibility.  These are stolen from
- * IRIX's <sys/mips_addrspace.h>.
- */
-#define KUBASE		_LLCONST_(0)
-#define KUSIZE_32	_LLCONST_(0x0000000080000000)	/* KUSIZE
-							   for a 32 bit proc */
-#define K0BASE_EXL_WR	_LLCONST_(0xa800000000000000)	/* exclusive on write */
-#define K0BASE_NONCOH	_LLCONST_(0x9800000000000000)	/* noncoherent */
-#define K0BASE_EXL	_LLCONST_(0xa000000000000000)	/* exclusive */
-
 #ifndef CONFIG_CPU_R8000
 
 /*
diff --git a/include/asm-mips/apm.h b/include/asm-mips/apm.h
new file mode 100644
index 0000000..e8c6920
--- /dev/null
+++ b/include/asm-mips/apm.h
@@ -0,0 +1,65 @@
+/* -*- linux-c -*-
+ *
+ * (C) 2003 zecke@handhelds.org
+ *
+ * GPL version 2
+ *
+ * based on arch/arm/kernel/apm.c
+ * factor out the information needed by architectures to provide
+ * apm status
+ *
+ *
+ */
+#ifndef MIPS_ASM_SA1100_APM_H
+#define MIPS_ASM_SA1100_APM_H
+
+#include <linux/config.h>
+#include <linux/apm_bios.h>
+
+/*
+ * This structure gets filled in by the machine specific 'get_power_status'
+ * implementation.  Any fields which are not set default to a safe value.
+ */
+struct apm_power_info {
+	unsigned char	ac_line_status;
+#define APM_AC_OFFLINE			0
+#define APM_AC_ONLINE			1
+#define APM_AC_BACKUP			2
+#define APM_AC_UNKNOWN			0xff
+
+	unsigned char	battery_status;
+#define APM_BATTERY_STATUS_HIGH		0
+#define APM_BATTERY_STATUS_LOW		1
+#define APM_BATTERY_STATUS_CRITICAL	2
+#define APM_BATTERY_STATUS_CHARGING	3
+#define APM_BATTERY_STATUS_NOT_PRESENT	4
+#define APM_BATTERY_STATUS_UNKNOWN	0xff
+
+	unsigned char	battery_flag;
+#define APM_BATTERY_FLAG_HIGH		(1 << 0)
+#define APM_BATTERY_FLAG_LOW		(1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL	(1 << 2)
+#define APM_BATTERY_FLAG_CHARGING	(1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT	(1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN	0xff
+
+	int		battery_life;
+	int		time;
+	int		units;
+#define APM_UNITS_MINS			0
+#define APM_UNITS_SECS			1
+#define APM_UNITS_UNKNOWN		-1
+
+};
+
+/*
+ * This allows machines to provide their own "apm get power status" function.
+ */
+extern void (*apm_get_power_status)(struct apm_power_info *);
+
+/*
+ * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND)
+ */
+void apm_queue_event(apm_event_t event);
+
+#endif
diff --git a/include/asm-mips/arc/types.h b/include/asm-mips/arc/types.h
index bbb725c..b9adcd6f 100644
--- a/include/asm-mips/arc/types.h
+++ b/include/asm-mips/arc/types.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_ARC_TYPES_H
 #define _ASM_ARC_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_ARC32
 
diff --git a/include/asm-mips/asm.h b/include/asm-mips/asm.h
index 4b090f3..e3038a4 100644
--- a/include/asm-mips/asm.h
+++ b/include/asm-mips/asm.h
@@ -17,7 +17,6 @@
 #ifndef __ASM_ASM_H
 #define __ASM_ASM_H
 
-#include <linux/config.h>
 #include <asm/sgidefs.h>
 
 #ifndef CAT
diff --git a/include/asm-mips/asmmacro-32.h b/include/asm-mips/asmmacro-32.h
index 11daf5c..5de3963 100644
--- a/include/asm-mips/asmmacro-32.h
+++ b/include/asm-mips/asmmacro-32.h
@@ -12,7 +12,7 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 
-	.macro	fpu_save_double thread status tmp1=t0 tmp2
+	.macro	fpu_save_double thread status tmp1=t0
 	cfc1	\tmp1,  fcr31
 	sdc1	$f0,  THREAD_FPR0(\thread)
 	sdc1	$f2,  THREAD_FPR2(\thread)
@@ -70,7 +70,7 @@
 	sw	\tmp, THREAD_FCR31(\thread)
 	.endm
 
-	.macro	fpu_restore_double thread tmp=t0
+	.macro	fpu_restore_double thread status tmp=t0
 	lw	\tmp, THREAD_FCR31(\thread)
 	ldc1	$f0,  THREAD_FPR0(\thread)
 	ldc1	$f2,  THREAD_FPR2(\thread)
diff --git a/include/asm-mips/asmmacro-64.h b/include/asm-mips/asmmacro-64.h
index 559c355..225feef 100644
--- a/include/asm-mips/asmmacro-64.h
+++ b/include/asm-mips/asmmacro-64.h
@@ -53,12 +53,12 @@
 	sdc1	$f31, THREAD_FPR31(\thread)
 	.endm
 
-	.macro	fpu_save_double thread status tmp1 tmp2
-	sll	\tmp2, \tmp1, 5
-	bgez	\tmp2, 2f
+	.macro	fpu_save_double thread status tmp
+	sll	\tmp, \status, 5
+	bgez	\tmp, 2f
 	fpu_save_16odd \thread
 2:
-	fpu_save_16even \thread \tmp1			# clobbers t1
+	fpu_save_16even \thread \tmp
 	.endm
 
 	.macro	fpu_restore_16even thread tmp=t0
@@ -101,13 +101,12 @@
 	ldc1	$f31, THREAD_FPR31(\thread)
 	.endm
 
-	.macro	fpu_restore_double thread tmp
-	mfc0	t0, CP0_STATUS
-	sll	t1, t0, 5
-	bgez	t1, 1f				# 16 register mode?
+	.macro	fpu_restore_double thread status tmp
+	sll	\tmp, \status, 5
+	bgez	\tmp, 1f				# 16 register mode?
 
-	fpu_restore_16odd a0
-1:	fpu_restore_16even a0, t0		# clobbers t0
+	fpu_restore_16odd \thread
+1:	fpu_restore_16even \thread \tmp
 	.endm
 
 	.macro	cpu_save_nonscratch thread
diff --git a/include/asm-mips/asmmacro.h b/include/asm-mips/asmmacro.h
index f54aa14..2c42f6b 100644
--- a/include/asm-mips/asmmacro.h
+++ b/include/asm-mips/asmmacro.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_ASMMACRO_H
 #define _ASM_ASMMACRO_H
 
-#include <linux/config.h>
 #include <asm/hazards.h>
 
 #ifdef CONFIG_32BIT
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index 2c8b853..13d44e1 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -17,7 +17,6 @@
  * <linux/spinlock.h> we have to include <linux/spinlock.h> outside the
  * main big wrapper ...
  */
-#include <linux/config.h>
 #include <linux/spinlock.h>
 
 #ifndef _ASM_ATOMIC_H
diff --git a/include/asm-mips/bcache.h b/include/asm-mips/bcache.h
index 446102b..3646a3f2 100644
--- a/include/asm-mips/bcache.h
+++ b/include/asm-mips/bcache.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_BCACHE_H
 #define _ASM_BCACHE_H
 
-#include <linux/config.h>
 
 /* Some R4000 / R4400 / R4600 / R5000 machines may have a non-dma-coherent,
    chipset implemented caches.  On machines with other CPUs the CPU does the
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h
index d2f4445..098cec2 100644
--- a/include/asm-mips/bitops.h
+++ b/include/asm-mips/bitops.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_BITOPS_H
 #define _ASM_BITOPS_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/bug.h>
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index 14fc88f..3b745e7 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -217,6 +217,13 @@
  */
 #define MACH_GROUP_TITAN       22	/* PMC-Sierra Titan		*/
 #define  MACH_TITAN_YOSEMITE	1	/* PMC-Sierra Yosemite		*/
+#define  MACH_TITAN_EXCITE	2	/* Basler eXcite		*/
+
+/*
+ * Valid machtype for group NEC EMMA2RH
+ */
+#define MACH_GROUP_NEC_EMMA2RH 25	/* NEC EMMA2RH (was 23)		*/
+#define  MACH_NEC_MARKEINS	0	/* NEC EMMA2RH Mark-eins	*/
 
 #define CL_SIZE			COMMAND_LINE_SIZE
 
@@ -258,4 +265,10 @@
  * Registers a0, a1, a3 and a4 as passed to the kenrel entry by firmware
  */
 extern unsigned long fw_arg0, fw_arg1, fw_arg2, fw_arg3;
+
+/*
+ * Platform memory detection hook called by setup_arch
+ */
+extern void plat_mem_setup(void);
+
 #endif /* _ASM_BOOTINFO_H */
diff --git a/include/asm-mips/bug.h b/include/asm-mips/bug.h
index 87d49a5..7b4739d 100644
--- a/include/asm-mips/bug.h
+++ b/include/asm-mips/bug.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_BUG_H
 #define __ASM_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 
diff --git a/include/asm-mips/bugs.h b/include/asm-mips/bugs.h
index cb2ea7c..0d7f9c1 100644
--- a/include/asm-mips/bugs.h
+++ b/include/asm-mips/bugs.h
@@ -7,7 +7,6 @@
 #ifndef _ASM_BUGS_H
 #define _ASM_BUGS_H
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
diff --git a/include/asm-mips/byteorder.h b/include/asm-mips/byteorder.h
index aefc02f..eee83cb 100644
--- a/include/asm-mips/byteorder.h
+++ b/include/asm-mips/byteorder.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_BYTEORDER_H
 #define _ASM_BYTEORDER_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/types.h>
 
diff --git a/include/asm-mips/cache.h b/include/asm-mips/cache.h
index 55e19f2..37f175c 100644
--- a/include/asm-mips/cache.h
+++ b/include/asm-mips/cache.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_CACHE_H
 #define _ASM_CACHE_H
 
-#include <linux/config.h>
 #include <kmalloc.h>
 
 #define L1_CACHE_SHIFT		CONFIG_MIPS_L1_CACHE_SHIFT
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index b09f897..a5e6050 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_CHECKSUM_H
 #define _ASM_CHECKSUM_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 
 #include <asm/uaccess.h>
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index 986511d..900f472 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -145,8 +145,5 @@
 
 	return (void __user *) (regs->regs[29] - len);
 }
-#if defined (__MIPSEL__)
-#define __COMPAT_ENDIAN_SWAP__ 	1
-#endif
 
 #endif /* _ASM_COMPAT_H */
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 254e11e..881ce1f 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -9,7 +9,6 @@
 #ifndef __ASM_CPU_FEATURES_H
 #define __ASM_CPU_FEATURES_H
 
-#include <linux/config.h>
 
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index 6572ac7..a2f0c8e 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_CPU_INFO_H
 #define __ASM_CPU_INFO_H
 
-#include <linux/config.h>
 #include <asm/cache.h>
 
 #ifdef CONFIG_SGI_IP27
diff --git a/include/asm-mips/ddb5074.h b/include/asm-mips/ddb5074.h
deleted file mode 100644
index 0d09ac2..0000000
--- a/include/asm-mips/ddb5074.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- *  include/asm-mips/ddb5074.h -- NEC DDB Vrc-5074 definitions
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-
-extern void ddb5074_led_hex(int hex);
-extern void ddb5074_led_d2(int on);
-extern void ddb5074_led_d3(int on);
-
diff --git a/include/asm-mips/ddb5xxx/ddb5074.h b/include/asm-mips/ddb5xxx/ddb5074.h
deleted file mode 100644
index 58d8830..0000000
--- a/include/asm-mips/ddb5xxx/ddb5074.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  include/asm-mips/ddb5074.h -- NEC DDB Vrc-5074 definitions
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-
-#ifndef _ASM_DDB5XXX_DDB5074_H
-#define _ASM_DDB5XXX_DDB5074_H
-
-#include <asm/nile4.h>
-
-#define DDB_SDRAM_SIZE      0x04000000      /* 64MB */
-
-#define DDB_PCI_IO_BASE     0x06000000
-#define DDB_PCI_IO_SIZE     0x02000000      /* 32 MB */
-
-#define DDB_PCI_MEM_BASE    0x08000000
-#define DDB_PCI_MEM_SIZE    0x08000000  /* 128 MB */
-
-#define DDB_PCI_CONFIG_BASE DDB_PCI_MEM_BASE
-#define DDB_PCI_CONFIG_SIZE DDB_PCI_MEM_SIZE
-
-#define NILE4_PCI_IO_BASE   0xa6000000
-#define NILE4_PCI_MEM_BASE  0xa8000000
-#define NILE4_PCI_CFG_BASE  NILE4_PCI_MEM_BASE
-#define DDB_PCI_IACK_BASE NILE4_PCI_IO_BASE
-
-#define NILE4_IRQ_BASE NUM_I8259_INTERRUPTS
-#define CPU_IRQ_BASE (NUM_NILE4_INTERRUPTS + NILE4_IRQ_BASE)
-#define CPU_NILE4_CASCADE 2
-
-extern void ddb5074_led_hex(int hex);
-extern void ddb5074_led_d2(int on);
-extern void ddb5074_led_d3(int on);
-
-extern void nile4_irq_setup(u32 base);
-#endif
diff --git a/include/asm-mips/ddb5xxx/ddb5476.h b/include/asm-mips/ddb5xxx/ddb5476.h
deleted file mode 100644
index 4c23390..0000000
--- a/include/asm-mips/ddb5xxx/ddb5476.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * header file specific for ddb5476
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- */
-
-/*
- *  Memory map (physical address)
- *
- *  Note most of the following address must be properly aligned by the
- *  corresponding size.  For example, if PCI_IO_SIZE is 16MB, then
- *  PCI_IO_BASE must be aligned along 16MB boundary.
- */
-#define DDB_SDRAM_BASE		0x00000000
-#define DDB_SDRAM_SIZE		0x04000000      /* 64MB */
-
-#define	DDB_DCS3_BASE		0x04000000	/* flash 1 */
-#define	DDB_DCS3_SIZE		0x01000000	/* 16MB */
-
-#define	DDB_DCS2_BASE		0x05000000	/* flash 2 */
-#define	DDB_DCS2_SIZE		0x01000000	/* 16MB */
-
-#define DDB_PCI_IO_BASE		0x06000000
-#define DDB_PCI_IO_SIZE		0x02000000      /* 32 MB */
-
-#define	DDB_PCI_MEM_BASE	0x08000000
-#define	DDB_PCI_MEM_SIZE	0x08000000	/* 128 MB */
-
-#define	DDB_DCS5_BASE		0x13000000	/* DDB status regs */
-#define	DDB_DCS5_SIZE		0x00200000	/* 2MB, 8-bit */
-
-#define	DDB_DCS4_BASE		0x14000000	/* DDB control regs */
-#define	DDB_DCS4_SIZE		0x00200000	/* 2MB, 8-bit */
-
-#define DDB_INTCS_BASE		0x1fa00000      /* VRC5476 control regs */
-#define DDB_INTCS_SIZE		0x00200000      /* 2MB */
-
-#define DDB_BOOTCS_BASE         0x1fc00000      /* Boot ROM / EPROM /Flash */
-#define DDB_BOOTCS_SIZE         0x00200000      /* 2 MB - doc says 4MB */
-
-
-/* aliases */
-#define	DDB_PCI_CONFIG_BASE	DDB_PCI_MEM_BASE
-#define	DDB_PCI_CONFIG_SIZE	DDB_PCI_MEM_SIZE
-
-/* PCI intr ack share PCIW0 with PCI IO */
-#define	DDB_PCI_IACK_BASE	DDB_PCI_IO_BASE
-
-/*
- * Interrupt mapping
- *
- * We have three interrupt controllers:
- *
- *   . CPU itself - 8 sources
- *   . i8259 - 16 sources
- *   . vrc5476 - 16 sources
- *
- *  They connected as follows:
- *    all vrc5476 interrupts are routed to cpu IP2 (by software setting)
- *    all i2869 are routed to INTC in vrc5476 (by hardware connection)
- *
- *  All VRC5476 PCI interrupts are level-triggered (no ack needed).
- *  All PCI irq but INTC are active low.
- */
-
-/*
- * irq number block assignment
- */
-
-#define	NUM_CPU_IRQ		8
-#define	NUM_I8259_IRQ		16
-#define	NUM_VRC5476_IRQ		16
-
-#define	DDB_IRQ_BASE		0
-
-#define	I8259_IRQ_BASE		DDB_IRQ_BASE
-#define	VRC5476_IRQ_BASE	(I8259_IRQ_BASE + NUM_I8259_IRQ)
-#define	CPU_IRQ_BASE		(VRC5476_IRQ_BASE + NUM_VRC5476_IRQ)
-
-/*
- * vrc5476 irq defs, see page 52-64 of Vrc5074 system controller manual
- */
-
-#define VRC5476_IRQ_CPCE	0	/* cpu parity error */
-#define VRC5476_IRQ_CNTD	1	/* cpu no target */
-#define VRC5476_IRQ_MCE		2	/* memory check error */
-#define VRC5476_IRQ_DMA		3	/* DMA */
-#define VRC5476_IRQ_UART	4	/* vrc5476 builtin UART, not used */
-#define VRC5476_IRQ_WDOG	5	/* watchdog timer */
-#define VRC5476_IRQ_GPT		6	/* general purpose timer */
-#define VRC5476_IRQ_LBRT	7	/* local bus read timeout */
-#define VRC5476_IRQ_INTA	8	/* PCI INT #A */
-#define VRC5476_IRQ_INTB	9	/* PCI INT #B */
-#define VRC5476_IRQ_INTC	10	/* PCI INT #C */
-#define VRC5476_IRQ_INTD	11	/* PCI INT #D */
-#define VRC5476_IRQ_INTE	12	/* PCI INT #E */
-#define VRC5476_IRQ_RESERVED_13	13	/* reserved  */
-#define VRC5476_IRQ_PCIS	14	/* PCI SERR #  */
-#define VRC5476_IRQ_PCI		15	/* PCI internal error */
-
-/*
- * i2859 irq assignment
- */
-#define I8259_IRQ_RESERVED_0	0
-#define I8259_IRQ_KEYBOARD	1	/* M1543 default */
-#define I8259_IRQ_CASCADE	2
-#define I8259_IRQ_UART_B	3	/* M1543 default, may conflict with RTC according to schematic diagram  */
-#define I8259_IRQ_UART_A	4	/* M1543 default */
-#define I8259_IRQ_PARALLEL	5	/* M1543 default */
-#define I8259_IRQ_RESERVED_6	6
-#define I8259_IRQ_RESERVED_7	7
-#define I8259_IRQ_RTC		8	/* who set this? */
-#define I8259_IRQ_USB		9	/* ddb_setup */
-#define I8259_IRQ_PMU		10	/* ddb_setup */
-#define I8259_IRQ_RESERVED_11	11
-#define I8259_IRQ_RESERVED_12	12	/* m1543_irq_setup */
-#define I8259_IRQ_RESERVED_13	13
-#define I8259_IRQ_HDC1		14	/* default and ddb_setup */
-#define I8259_IRQ_HDC2		15	/* default */
-
-
-/*
- * misc
- */
-#define	VRC5476_I8259_CASCADE	VRC5476_IRQ_INTC
-#define	CPU_VRC5476_CASCADE	2
-
-#define is_i8259_irq(irq)       ((irq) < NUM_I8259_IRQ)
-#define nile4_to_irq(n)         ((n)+NUM_I8259_IRQ)
-#define irq_to_nile4(n)         ((n)-NUM_I8259_IRQ)
-
-/*
- * low-level irq functions
- */
-#ifndef __ASSEMBLY__
-extern void nile4_map_irq(int nile4_irq, int cpu_irq);
-extern void nile4_map_irq_all(int cpu_irq);
-extern void nile4_enable_irq(int nile4_irq);
-extern void nile4_disable_irq(int nile4_irq);
-extern void nile4_disable_irq_all(void);
-extern u16 nile4_get_irq_stat(int cpu_irq);
-extern void nile4_enable_irq_output(int cpu_irq);
-extern void nile4_disable_irq_output(int cpu_irq);
-extern void nile4_set_pci_irq_polarity(int pci_irq, int high);
-extern void nile4_set_pci_irq_level_or_edge(int pci_irq, int level);
-extern void nile4_clear_irq(int nile4_irq);
-extern void nile4_clear_irq_mask(u32 mask);
-extern u8 nile4_i8259_iack(void);
-extern void nile4_dump_irq_status(void);        /* Debug */
-#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-mips/ddb5xxx/ddb5477.h b/include/asm-mips/ddb5xxx/ddb5477.h
index a438548..c5af4b7 100644
--- a/include/asm-mips/ddb5xxx/ddb5477.h
+++ b/include/asm-mips/ddb5xxx/ddb5477.h
@@ -17,7 +17,6 @@
 #ifndef __ASM_DDB5XXX_DDB5477_H
 #define __ASM_DDB5XXX_DDB5477_H
 
-#include <linux/config.h>
 
 /*
  * This contains macros that are specific to DDB5477 or renamed from
diff --git a/include/asm-mips/ddb5xxx/ddb5xxx.h b/include/asm-mips/ddb5xxx/ddb5xxx.h
index 873c03f..e97fcc8 100644
--- a/include/asm-mips/ddb5xxx/ddb5xxx.h
+++ b/include/asm-mips/ddb5xxx/ddb5xxx.h
@@ -18,7 +18,6 @@
 #ifndef __ASM_DDB5XXX_DDB5XXX_H
 #define __ASM_DDB5XXX_DDB5XXX_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /*
@@ -174,13 +173,8 @@
 
 static inline void ddb_sync(void)
 {
-/* The DDB5074 doesn't seem to like these accesses. They kill the board on
- * interrupt load
- */
-#ifndef CONFIG_DDB5074
     volatile u32 *p = (volatile u32 *)0xbfc00000;
     (void)(*p);
-#endif
 }
 
 static inline void ddb_out32(u32 offset, u32 val)
@@ -260,11 +254,7 @@
 /*
  * include the board dependent part
  */
-#if defined(CONFIG_DDB5074)
-#include <asm/ddb5xxx/ddb5074.h>
-#elif defined(CONFIG_DDB5476)
-#include <asm/ddb5xxx/ddb5476.h>
-#elif defined(CONFIG_DDB5477)
+#if defined(CONFIG_DDB5477)
 #include <asm/ddb5xxx/ddb5477.h>
 #else
 #error "Unknown DDB board!"
diff --git a/include/asm-mips/debug.h b/include/asm-mips/debug.h
index 930f2b7..1fd5a2b 100644
--- a/include/asm-mips/debug.h
+++ b/include/asm-mips/debug.h
@@ -15,7 +15,6 @@
 #ifndef _ASM_DEBUG_H
 #define _ASM_DEBUG_H
 
-#include <linux/config.h>
 
 /*
  * run-time macros for catching spurious errors.  Eable CONFIG_RUNTIME_DEBUG in
diff --git a/include/asm-mips/dec/prom.h b/include/asm-mips/dec/prom.h
index 1384dd0..b9c8203 100644
--- a/include/asm-mips/dec/prom.h
+++ b/include/asm-mips/dec/prom.h
@@ -15,7 +15,6 @@
 #ifndef _ASM_DEC_PROM_H
 #define _ASM_DEC_PROM_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
diff --git a/include/asm-mips/delay.h b/include/asm-mips/delay.h
index 928f30f..ea77050 100644
--- a/include/asm-mips/delay.h
+++ b/include/asm-mips/delay.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_DELAY_H
 #define _ASM_DELAY_H
 
-#include <linux/config.h>
 #include <linux/param.h>
 #include <linux/smp.h>
 #include <asm/compiler.h>
diff --git a/include/asm-mips/dma.h b/include/asm-mips/dma.h
index 6aaf993..e85849a 100644
--- a/include/asm-mips/dma.h
+++ b/include/asm-mips/dma.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <asm/io.h>			/* need byte IO */
 #include <linux/spinlock.h>		/* And spinlocks */
 #include <linux/delay.h>
diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h
index bdc9de2..ebd6bfb 100644
--- a/include/asm-mips/elf.h
+++ b/include/asm-mips/elf.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_ELF_H
 #define _ASM_ELF_H
 
-#include <linux/config.h>
 
 /* ELF header e_flags defines. */
 /* MIPS architecture level. */
diff --git a/include/asm-mips/emma2rh/emma2rh.h b/include/asm-mips/emma2rh/emma2rh.h
new file mode 100644
index 0000000..4fb8df7
--- /dev/null
+++ b/include/asm-mips/emma2rh/emma2rh.h
@@ -0,0 +1,330 @@
+/*
+ *  include/asm-mips/emma2rh/emma2rh.h
+ *      This file is EMMA2RH common header.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
+ *          Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_EMMA2RH_EMMA2RH_H
+#define __ASM_EMMA2RH_EMMA2RH_H
+
+/*
+ * EMMA2RH registers
+ */
+#define REGBASE 0x10000000
+
+#define EMMA2RH_BHIF_STRAP_0	(0x000010+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_0	(0x000030+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_1	(0x000034+REGBASE)
+#define EMMA2RH_BHIF_INT_ST_2	(0x000038+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_0	(0x000040+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_1	(0x000044+REGBASE)
+#define EMMA2RH_BHIF_INT_EN_2	(0x000048+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_0	(0x000050+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_1	(0x000054+REGBASE)
+#define EMMA2RH_BHIF_INT1_EN_2	(0x000058+REGBASE)
+#define EMMA2RH_BHIF_SW_INT	(0x000070+REGBASE)
+#define EMMA2RH_BHIF_SW_INT_EN	(0x000080+REGBASE)
+#define EMMA2RH_BHIF_SW_INT_CLR	(0x000090+REGBASE)
+#define EMMA2RH_BHIF_MAIN_CTRL	(0x0000b4+REGBASE)
+#define EMMA2RH_BHIF_EXCEPT_VECT_BASE_ADDRESS	(0x0000c0+REGBASE)
+#define EMMA2RH_GPIO_DIR	(0x110d20+REGBASE)
+#define EMMA2RH_GPIO_INT_ST	(0x110d30+REGBASE)
+#define EMMA2RH_GPIO_INT_MASK	(0x110d3c+REGBASE)
+#define EMMA2RH_GPIO_INT_MODE	(0x110d48+REGBASE)
+#define EMMA2RH_GPIO_INT_CND_A	(0x110d54+REGBASE)
+#define EMMA2RH_GPIO_INT_CND_B	(0x110d60+REGBASE)
+#define EMMA2RH_PBRD_INT_EN	(0x100010+REGBASE)
+#define EMMA2RH_PBRD_CLKSEL	(0x100028+REGBASE)
+#define EMMA2RH_PFUR0_BASE	(0x101000+REGBASE)
+#define EMMA2RH_PFUR1_BASE	(0x102000+REGBASE)
+#define EMMA2RH_PFUR2_BASE	(0x103000+REGBASE)
+#define EMMA2RH_PIIC0_BASE	(0x107000+REGBASE)
+#define EMMA2RH_PIIC1_BASE	(0x108000+REGBASE)
+#define EMMA2RH_PIIC2_BASE	(0x109000+REGBASE)
+#define EMMA2RH_PCI_CONTROL	(0x200000+REGBASE)
+#define EMMA2RH_PCI_ARBIT_CTR	(0x200004+REGBASE)
+#define EMMA2RH_PCI_IWIN0_CTR	(0x200010+REGBASE)
+#define EMMA2RH_PCI_IWIN1_CTR	(0x200014+REGBASE)
+#define EMMA2RH_PCI_INIT_ESWP	(0x200018+REGBASE)
+#define EMMA2RH_PCI_INT		(0x200020+REGBASE)
+#define EMMA2RH_PCI_INT_EN	(0x200024+REGBASE)
+#define EMMA2RH_PCI_TWIN_CTR	(0x200030+REGBASE)
+#define EMMA2RH_PCI_TWIN_BADR	(0x200034+REGBASE)
+#define EMMA2RH_PCI_TWIN0_DADR	(0x200038+REGBASE)
+#define EMMA2RH_PCI_TWIN1_DADR	(0x20003c+REGBASE)
+
+/*
+ *  Memory map (physical address)
+ *
+ *  Note most of the following address must be properly aligned by the
+ *  corresponding size.  For example, if PCI_IO_SIZE is 16MB, then
+ *  PCI_IO_BASE must be aligned along 16MB boundary.
+ */
+
+/* the actual ram size is detected at run-time */
+#define EMMA2RH_RAM_BASE	0x00000000
+#define EMMA2RH_RAM_SIZE	0x10000000	/* less than 256MB */
+
+#define EMMA2RH_IO_BASE		0x10000000
+#define EMMA2RH_IO_SIZE		0x01000000	/* 16 MB */
+
+#define EMMA2RH_GENERALIO_BASE	0x11000000
+#define EMMA2RH_GENERALIO_SIZE	0x01000000	/* 16 MB */
+
+#define EMMA2RH_PCI_IO_BASE	0x12000000
+#define EMMA2RH_PCI_IO_SIZE	0x02000000	/* 32 MB */
+
+#define EMMA2RH_PCI_MEM_BASE	0x14000000
+#define EMMA2RH_PCI_MEM_SIZE	0x08000000	/* 128 MB */
+
+#define EMMA2RH_ROM_BASE	0x1c000000
+#define EMMA2RH_ROM_SIZE	0x04000000	/* 64 MB */
+
+#define EMMA2RH_PCI_CONFIG_BASE	EMMA2RH_PCI_IO_BASE
+#define EMMA2RH_PCI_CONFIG_SIZE	EMMA2RH_PCI_IO_SIZE
+
+#define NUM_CPU_IRQ		8
+#define NUM_EMMA2RH_IRQ		96
+
+#define CPU_EMMA2RH_CASCADE	2
+#define EMMA2RH_IRQ_BASE	0
+
+/*
+ * emma2rh irq defs
+ */
+
+#define EMMA2RH_IRQ_INT0	(0 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT1	(1 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT2	(2 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT3	(3 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT4	(4 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT5	(5 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT6	(6 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT7	(7 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT8	(8 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT9	(9 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT10	(10 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT11	(11 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT12	(12 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT13	(13 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT14	(14 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT15	(15 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT16	(16 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT17	(17 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT18	(18 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT19	(19 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT20	(20 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT21	(21 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT22	(22 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT23	(23 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT24	(24 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT25	(25 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT26	(26 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT27	(27 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT28	(28 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT29	(29 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT30	(30 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT31	(31 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT32	(32 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT33	(33 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT34	(34 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT35	(35 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT36	(36 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT37	(37 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT38	(38 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT39	(39 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT40	(40 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT41	(41 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT42	(42 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT43	(43 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT44	(44 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT45	(45 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT46	(46 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT47	(47 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT48	(48 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT49	(49 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT50	(50 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT51	(51 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT52	(52 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT53	(53 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT54	(54 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT55	(55 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT56	(56 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT57	(57 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT58	(58 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT59	(59 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT60	(60 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT61	(61 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT62	(62 + EMMA2RH_IRQ_BASE)
+#define EMMA2RH_IRQ_INT63	(63 + EMMA2RH_IRQ_BASE)
+
+#define EMMA2RH_IRQ_PFUR0	EMMA2RH_IRQ_INT49
+#define EMMA2RH_IRQ_PFUR1	EMMA2RH_IRQ_INT50
+#define EMMA2RH_IRQ_PFUR2	EMMA2RH_IRQ_INT51
+#define EMMA2RH_IRQ_PIIC0	EMMA2RH_IRQ_INT56
+#define EMMA2RH_IRQ_PIIC1	EMMA2RH_IRQ_INT57
+#define EMMA2RH_IRQ_PIIC2	EMMA2RH_IRQ_INT58
+
+/*
+ *  EMMA2RH Register Access
+ */
+
+#define EMMA2RH_BASE (0xa0000000)
+
+static inline void emma2rh_sync(void)
+{
+	volatile u32 *p = (volatile u32 *)0xbfc00000;
+	(void)(*p);
+}
+
+static inline void emma2rh_out32(u32 offset, u32 val)
+{
+	*(volatile u32 *)(EMMA2RH_BASE | offset) = val;
+	emma2rh_sync();
+}
+
+static inline u32 emma2rh_in32(u32 offset)
+{
+	u32 val = *(volatile u32 *)(EMMA2RH_BASE | offset);
+	emma2rh_sync();
+	return val;
+}
+
+static inline void emma2rh_out16(u32 offset, u16 val)
+{
+	*(volatile u16 *)(EMMA2RH_BASE | offset) = val;
+	emma2rh_sync();
+}
+
+static inline u16 emma2rh_in16(u32 offset)
+{
+	u16 val = *(volatile u16 *)(EMMA2RH_BASE | offset);
+	emma2rh_sync();
+	return val;
+}
+
+static inline void emma2rh_out8(u32 offset, u8 val)
+{
+	*(volatile u8 *)(EMMA2RH_BASE | offset) = val;
+	emma2rh_sync();
+}
+
+static inline u8 emma2rh_in8(u32 offset)
+{
+	u8 val = *(volatile u8 *)(EMMA2RH_BASE | offset);
+	emma2rh_sync();
+	return val;
+}
+
+/**
+ * IIC registers map
+ **/
+
+/*---------------------------------------------------------------------------*/
+/* CNT - Control register (00H R/W)                                          */
+/*---------------------------------------------------------------------------*/
+#define SPT         0x00000001
+#define STT         0x00000002
+#define ACKE        0x00000004
+#define WTIM        0x00000008
+#define SPIE        0x00000010
+#define WREL        0x00000020
+#define LREL        0x00000040
+#define IICE        0x00000080
+#define CNT_RESERVED    0x000000ff	/* reserved bit 0 */
+
+#define I2C_EMMA_START      (IICE | STT)
+#define I2C_EMMA_STOP       (IICE | SPT)
+#define I2C_EMMA_REPSTART   I2C_EMMA_START
+
+/*---------------------------------------------------------------------------*/
+/* STA - Status register (10H Read)                                          */
+/*---------------------------------------------------------------------------*/
+#define MSTS        0x00000080
+#define ALD         0x00000040
+#define EXC         0x00000020
+#define COI         0x00000010
+#define TRC         0x00000008
+#define ACKD        0x00000004
+#define STD         0x00000002
+#define SPD         0x00000001
+
+/*---------------------------------------------------------------------------*/
+/* CSEL - Clock select register (20H R/W)                                    */
+/*---------------------------------------------------------------------------*/
+#define FCL         0x00000080
+#define ND50        0x00000040
+#define CLD         0x00000020
+#define DAD         0x00000010
+#define SMC         0x00000008
+#define DFC         0x00000004
+#define CL          0x00000003
+#define CSEL_RESERVED   0x000000ff	/* reserved bit 0 */
+
+#define FAST397     0x0000008b
+#define FAST297     0x0000008a
+#define FAST347     0x0000000b
+#define FAST260     0x0000000a
+#define FAST130     0x00000008
+#define STANDARD108 0x00000083
+#define STANDARD83  0x00000082
+#define STANDARD95  0x00000003
+#define STANDARD73  0x00000002
+#define STANDARD36  0x00000001
+#define STANDARD71  0x00000000
+
+/*---------------------------------------------------------------------------*/
+/* SVA - Slave address register (30H R/W)                                    */
+/*---------------------------------------------------------------------------*/
+#define SVA         0x000000fe
+
+/*---------------------------------------------------------------------------*/
+/* SHR - Shift register (40H R/W)                                            */
+/*---------------------------------------------------------------------------*/
+#define SR          0x000000ff
+
+/*---------------------------------------------------------------------------*/
+/* INT - Interrupt register (50H R/W)                                        */
+/* INTM - Interrupt mask register (60H R/W)                                  */
+/*---------------------------------------------------------------------------*/
+#define INTE0       0x00000001
+
+/***********************************************************************
+ * I2C registers
+ ***********************************************************************
+ */
+#define I2C_EMMA_CNT            0x00
+#define I2C_EMMA_STA            0x10
+#define I2C_EMMA_CSEL           0x20
+#define I2C_EMMA_SVA            0x30
+#define I2C_EMMA_SHR            0x40
+#define I2C_EMMA_INT            0x50
+#define I2C_EMMA_INTM           0x60
+
+/*
+ * include the board dependent part
+ */
+#if defined(CONFIG_MARKEINS)
+#include <asm/emma2rh/markeins.h>
+#else
+#error "Unknown EMMA2RH board!"
+#endif
+
+#endif /* __ASM_EMMA2RH_EMMA2RH_H */
diff --git a/include/asm-mips/emma2rh/markeins.h b/include/asm-mips/emma2rh/markeins.h
new file mode 100644
index 0000000..8fa7667
--- /dev/null
+++ b/include/asm-mips/emma2rh/markeins.h
@@ -0,0 +1,76 @@
+/*
+ *  include/asm-mips/emma2rh/markeins.h
+ *      This file is EMMA2RH board depended header.
+ *
+ *  Copyright (C) NEC Electronics Corporation 2005-2006
+ *
+ *  This file based on include/asm-mips/ddb5xxx/ddb5xxx.h
+ *          Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef MARKEINS_H
+#define MARKEINS_H
+
+#define NUM_EMMA2RH_IRQ_SW	32
+#define NUM_EMMA2RH_IRQ_GPIO	32
+
+#define EMMA2RH_SW_CASCADE	(EMMA2RH_IRQ_INT7 - EMMA2RH_IRQ_INT0)
+#define EMMA2RH_GPIO_CASCADE	(EMMA2RH_IRQ_INT46 - EMMA2RH_IRQ_INT0)
+
+#define EMMA2RH_SW_IRQ_BASE	(EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ)
+#define EMMA2RH_GPIO_IRQ_BASE	(EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW)
+#define CPU_IRQ_BASE		(EMMA2RH_GPIO_IRQ_BASE + NUM_EMMA2RH_IRQ_GPIO)
+
+#define EMMA2RH_SW_IRQ_INT0	(0+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT1	(1+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT2	(2+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT3	(3+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT4	(4+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT5	(5+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT6	(6+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT7	(7+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT8	(8+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT9	(9+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT10	(10+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT11	(11+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT12	(12+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT13	(13+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT14	(14+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT15	(15+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT16	(16+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT17	(17+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT18	(18+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT19	(19+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT20	(20+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT21	(21+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT22	(22+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT23	(23+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT24	(24+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT25	(25+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT26	(26+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT27	(27+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT28	(28+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT29	(29+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT30	(30+EMMA2RH_SW_IRQ_BASE)
+#define EMMA2RH_SW_IRQ_INT31	(31+EMMA2RH_SW_IRQ_BASE)
+
+#define MARKEINS_PCI_IRQ_INTA	EMMA2RH_GPIO_IRQ_BASE+15
+#define MARKEINS_PCI_IRQ_INTB	EMMA2RH_GPIO_IRQ_BASE+16
+#define MARKEINS_PCI_IRQ_INTC	EMMA2RH_GPIO_IRQ_BASE+17
+#define MARKEINS_PCI_IRQ_INTD	EMMA2RH_GPIO_IRQ_BASE+18
+
+#endif /* CONFIG_MARKEINS */
diff --git a/include/asm-mips/fcntl.h b/include/asm-mips/fcntl.h
index 43d047a..787220e 100644
--- a/include/asm-mips/fcntl.h
+++ b/include/asm-mips/fcntl.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_FCNTL_H
 #define _ASM_FCNTL_H
 
-#include <linux/config.h>
 
 #define O_APPEND	0x0008
 #define O_SYNC		0x0010
diff --git a/include/asm-mips/fixmap.h b/include/asm-mips/fixmap.h
index 73a3028..1cadefb 100644
--- a/include/asm-mips/fixmap.h
+++ b/include/asm-mips/fixmap.h
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index b0f5001..58c561a 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_FPU_H
 #define _ASM_FPU_H
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/thread_info.h>
 
@@ -138,10 +137,9 @@
 	if (cpu_has_fpu) {
 		if ((tsk == current) && __is_fpu_owner())
 			_save_fp(current);
-		return tsk->thread.fpu.hard.fpr;
 	}
 
-	return tsk->thread.fpu.soft.fpr;
+	return tsk->thread.fpu.fpr;
 }
 
 #endif /* _ASM_FPU_H */
diff --git a/include/asm-mips/fpu_emulator.h b/include/asm-mips/fpu_emulator.h
index 16cb4d1..2731c38 100644
--- a/include/asm-mips/fpu_emulator.h
+++ b/include/asm-mips/fpu_emulator.h
@@ -12,8 +12,8 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
- * Further private data for which no space exists in mips_fpu_soft_struct.
- * This should be subsumed into the mips_fpu_soft_struct structure as
+ * Further private data for which no space exists in mips_fpu_struct.
+ * This should be subsumed into the mips_fpu_struct structure as
  * defined in processor.h as soon as the absurd wired absolute assembler
  * offsets become dynamic at compile time.
  *
diff --git a/include/asm-mips/futex.h b/include/asm-mips/futex.h
index 12d118f..ed023ea 100644
--- a/include/asm-mips/futex.h
+++ b/include/asm-mips/futex.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/futex.h>
 #include <asm/errno.h>
 #include <asm/uaccess.h>
@@ -22,51 +21,53 @@
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
 		"	.set	mips3				\n"	\
-		"1:	ll	%1, (%3)	# __futex_atomic_op	\n" \
+		"1:	ll	%1, %4	# __futex_atomic_op	\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
 		"	.set	mips3				\n"	\
-		"2:	sc	$1, (%3)			\n"	\
+		"2:	sc	$1, %2				\n"	\
 		"	beqzl	$1, 1b				\n"	\
 		__FUTEX_SMP_SYNC					\
 		"3:						\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.section .fixup,\"ax\"			\n"	\
-		"4:	li	%0, %5				\n"	\
+		"4:	li	%0, %6				\n"	\
 		"	j	2b				\n"	\
 		"	.previous				\n"	\
 		"	.section __ex_table,\"a\"		\n"	\
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=r" (oldval)				\
-		: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));	\
+		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
+		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "memory");						\
 	} else if (cpu_has_llsc) {					\
 		__asm__ __volatile__(					\
 		"	.set	push				\n"	\
 		"	.set	noat				\n"	\
 		"	.set	mips3				\n"	\
-		"1:	ll	%1, (%3)	# __futex_atomic_op	\n" \
+		"1:	ll	%1, %4	# __futex_atomic_op	\n"	\
 		"	.set	mips0				\n"	\
 		"	" insn	"				\n"	\
 		"	.set	mips3				\n"	\
-		"2:	sc	$1, (%3)			\n"	\
+		"2:	sc	$1, %2				\n"	\
 		"	beqz	$1, 1b				\n"	\
 		__FUTEX_SMP_SYNC					\
 		"3:						\n"	\
 		"	.set	pop				\n"	\
 		"	.set	mips0				\n"	\
 		"	.section .fixup,\"ax\"			\n"	\
-		"4:	li	%0, %5				\n"	\
+		"4:	li	%0, %6				\n"	\
 		"	j	2b				\n"	\
 		"	.previous				\n"	\
 		"	.section __ex_table,\"a\"		\n"	\
 		"	"__UA_ADDR "\t1b, 4b			\n"	\
 		"	"__UA_ADDR "\t2b, 4b			\n"	\
 		"	.previous				\n"	\
-		: "=r" (ret), "=r" (oldval)				\
-		: "0" (0), "r" (uaddr), "Jr" (oparg), "i" (-EFAULT));	\
+		: "=r" (ret), "=&r" (oldval), "=R" (*uaddr)		\
+		: "0" (0), "R" (*uaddr), "Jr" (oparg), "i" (-EFAULT)	\
+		: "memory");						\
 	} else								\
 		ret = -ENOSYS;						\
 }
@@ -89,23 +90,23 @@
 
 	switch (op) {
 	case FUTEX_OP_SET:
-		__futex_atomic_op("move	$1, %z4", ret, oldval, uaddr, oparg);
+		__futex_atomic_op("move	$1, %z5", ret, oldval, uaddr, oparg);
 		break;
 
 	case FUTEX_OP_ADD:
-		__futex_atomic_op("addu	$1, %1, %z4",
+		__futex_atomic_op("addu	$1, %1, %z5",
 		                  ret, oldval, uaddr, oparg);
 		break;
 	case FUTEX_OP_OR:
-		__futex_atomic_op("or	$1, %1, %z4",
+		__futex_atomic_op("or	$1, %1, %z5",
 		                  ret, oldval, uaddr, oparg);
 		break;
 	case FUTEX_OP_ANDN:
-		__futex_atomic_op("and	$1, %1, %z4",
+		__futex_atomic_op("and	$1, %1, %z5",
 		                  ret, oldval, uaddr, ~oparg);
 		break;
 	case FUTEX_OP_XOR:
-		__futex_atomic_op("xor	$1, %1, %z4",
+		__futex_atomic_op("xor	$1, %1, %z5",
 		                  ret, oldval, uaddr, oparg);
 		break;
 	default:
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index dadc051..66943c4 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_HAZARDS_H
 #define _ASM_HAZARDS_H
 
-#include <linux/config.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/include/asm-mips/highmem.h b/include/asm-mips/highmem.h
index 8cf5984..c976bfaa 100644
--- a/include/asm-mips/highmem.h
+++ b/include/asm-mips/highmem.h
@@ -19,7 +19,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/kmap_types.h>
diff --git a/include/asm-mips/interrupt.h b/include/asm-mips/interrupt.h
index 4bb9c06..a99d686 100644
--- a/include/asm-mips/interrupt.h
+++ b/include/asm-mips/interrupt.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_INTERRUPT_H
 #define _ASM_INTERRUPT_H
 
-#include <linux/config.h>
 #include <asm/hazards.h>
 
 __asm__ (
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 6b17eb9..df624e1 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
diff --git a/include/asm-mips/ip32/machine.h b/include/asm-mips/ip32/machine.h
index e440fdf..1b631b8 100644
--- a/include/asm-mips/ip32/machine.h
+++ b/include/asm-mips/ip32/machine.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_IP32_MACHINE_H
 #define _ASM_IP32_MACHINE_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SGI_IP32
 
diff --git a/include/asm-mips/irq.h b/include/asm-mips/irq.h
index dde677f..d35c617 100644
--- a/include/asm-mips/irq.h
+++ b/include/asm-mips/irq.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 
 #include <asm/mipsmtregs.h>
diff --git a/include/asm-mips/isadep.h b/include/asm-mips/isadep.h
index 7bb0035..24c6cda 100644
--- a/include/asm-mips/isadep.h
+++ b/include/asm-mips/isadep.h
@@ -5,7 +5,6 @@
  *
  * Copyright (c) 1998 Harald Koerfgen
  */
-#include <linux/config.h>
 
 #ifndef __ASM_ISADEP_H
 #define __ASM_ISADEP_H
diff --git a/include/asm-mips/jmr3927/irq.h b/include/asm-mips/jmr3927/irq.h
index b0c325a..fe551f3 100644
--- a/include/asm-mips/jmr3927/irq.h
+++ b/include/asm-mips/jmr3927/irq.h
@@ -12,7 +12,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/irq.h>
 
 struct tb_irq_space {
diff --git a/include/asm-mips/kmap_types.h b/include/asm-mips/kmap_types.h
index 6886a0c..806aae3 100644
--- a/include/asm-mips/kmap_types.h
+++ b/include/asm-mips/kmap_types.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
diff --git a/include/asm-mips/local.h b/include/asm-mips/local.h
index c38844f..9e2d43b 100644
--- a/include/asm-mips/local.h
+++ b/include/asm-mips/local.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_LOCAL_H
 #define _ASM_LOCAL_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 #include <asm/atomic.h>
 
diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h
index 4686e17..582acd8 100644
--- a/include/asm-mips/mach-au1x00/au1000.h
+++ b/include/asm-mips/mach-au1x00/au1000.h
@@ -35,7 +35,6 @@
 #ifndef _AU1000_H_
 #define _AU1000_H_
 
-#include <linux/config.h>
 
 #ifndef _LANGUAGE_ASSEMBLY
 
diff --git a/include/asm-mips/mach-au1x00/au1xxx.h b/include/asm-mips/mach-au1x00/au1xxx.h
index b7b46dd..9471359 100644
--- a/include/asm-mips/mach-au1x00/au1xxx.h
+++ b/include/asm-mips/mach-au1x00/au1xxx.h
@@ -23,7 +23,6 @@
 #ifndef _AU1XXX_H_
 #define _AU1XXX_H_
 
-#include <linux/config.h>
 
 #include <asm/mach-au1x00/au1000.h>
 
diff --git a/include/asm-mips/mach-au1x00/au1xxx_dbdma.h b/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
index b327bcd..d5b38a2 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_dbdma.h
@@ -34,7 +34,6 @@
 #ifndef _AU1000_DBDMA_H_
 #define _AU1000_DBDMA_H_
 
-#include <linux/config.h>
 
 #ifndef _LANGUAGE_ASSEMBLY
 
diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h
index e867b4e..301e713 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_ide.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h
@@ -29,7 +29,6 @@
  * Note: for more information, please refer "AMD Alchemy Au1200/Au1550 IDE
  *       Interface and Linux Device Driver" Application Note.
  */
-#include <linux/config.h>
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
         #define DMA_WAIT_TIMEOUT        100
diff --git a/include/asm-mips/mach-au1x00/au1xxx_psc.h b/include/asm-mips/mach-au1x00/au1xxx_psc.h
index 8e5fb3c..d7cbacd 100644
--- a/include/asm-mips/mach-au1x00/au1xxx_psc.h
+++ b/include/asm-mips/mach-au1x00/au1xxx_psc.h
@@ -33,14 +33,18 @@
 #ifndef _AU1000_PSC_H_
 #define _AU1000_PSC_H_
 
-#include <linux/config.h>
 
 /* The PSC base addresses.  */
 #ifdef CONFIG_SOC_AU1550
 #define PSC0_BASE_ADDR		0xb1a00000
 #define PSC1_BASE_ADDR		0xb1b00000
 #define PSC2_BASE_ADDR		0xb0a00000
-#define PSC3_BASE_ADDR		0xb0d00000
+#define PSC3_BASE_ADDR		0xb0b00000
+#endif
+
+#ifdef CONFIG_SOC_AU1200
+#define PSC0_BASE_ADDR		0xb1a00000
+#define PSC1_BASE_ADDR		0xb1b00000
 #endif
 
 /* The PSC select and control registers are common to
@@ -228,6 +232,8 @@
 #define PSC_I2SCFG_DD_DISABLE	(1 << 27)
 #define PSC_I2SCFG_DE_ENABLE	(1 << 26)
 #define PSC_I2SCFG_SET_WS(x)	(((((x) / 2) - 1) & 0x7f) << 16)
+#define PSC_I2SCFG_WS(n)	((n & 0xFF) << 16)
+#define PSC_I2SCFG_WS_MASK	(PSC_I2SCFG_WS(0x3F))
 #define PSC_I2SCFG_WI		(1 << 15)
 
 #define PSC_I2SCFG_DIV_MASK	(3 << 13)
diff --git a/include/asm-mips/mach-au1x00/ioremap.h b/include/asm-mips/mach-au1x00/ioremap.h
index d3ec627..098fca4 100644
--- a/include/asm-mips/mach-au1x00/ioremap.h
+++ b/include/asm-mips/mach-au1x00/ioremap.h
@@ -9,7 +9,6 @@
 #ifndef __ASM_MACH_AU1X00_IOREMAP_H
 #define __ASM_MACH_AU1X00_IOREMAP_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
diff --git a/include/asm-mips/mach-cobalt/cpu-feature-overrides.h b/include/asm-mips/mach-cobalt/cpu-feature-overrides.h
index ace8c5e..e0e08fc 100644
--- a/include/asm-mips/mach-cobalt/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-cobalt/cpu-feature-overrides.h
@@ -8,7 +8,6 @@
 #ifndef __ASM_COBALT_CPU_FEATURE_OVERRIDES_H
 #define __ASM_COBALT_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
diff --git a/include/asm-mips/mach-db1x00/db1x00.h b/include/asm-mips/mach-db1x00/db1x00.h
index 7b28b23..0f5f4c2 100644
--- a/include/asm-mips/mach-db1x00/db1x00.h
+++ b/include/asm-mips/mach-db1x00/db1x00.h
@@ -28,11 +28,22 @@
 #ifndef __ASM_DB1X00_H
 #define __ASM_DB1X00_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_MIPS_DB1550
+
+#define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
+#define DBDMA_AC97_RX_CHAN DSCR_CMD0_PSC1_RX
+#define DBDMA_I2S_TX_CHAN  DSCR_CMD0_PSC3_TX
+#define DBDMA_I2S_RX_CHAN  DSCR_CMD0_PSC3_RX
+
+#define SPI_PSC_BASE       PSC0_BASE_ADDR
+#define AC97_PSC_BASE      PSC1_BASE_ADDR
+#define SMBUS_PSC_BASE     PSC2_BASE_ADDR
+#define I2S_PSC_BASE       PSC3_BASE_ADDR
+
 #define BCSR_KSEG1_ADDR 0xAF000000
 #define NAND_PHYS_ADDR  0x20000000
+
 #else
 #define BCSR_KSEG1_ADDR 0xAE000000
 #endif
diff --git a/include/asm-mips/mach-ddb5074/mc146818rtc.h b/include/asm-mips/mach-ddb5074/mc146818rtc.h
deleted file mode 100644
index 2eb9acb..0000000
--- a/include/asm-mips/mach-ddb5074/mc146818rtc.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1998, 2001, 03 by Ralf Baechle
- *
- * RTC routines for PC style attached Dallas chip.
- */
-#ifndef __ASM_MACH_DDB5074_MC146818RTC_H
-#define __ASM_MACH_DDB5074_MC146818RTC_H
-
-#include <asm/ddb5xxx/ddb5074.h>
-#include <asm/ddb5xxx/ddb5xxx.h>
-
-#define RTC_PORT(x)	(0x70 + (x))
-#define RTC_IRQ		8
-
-static inline unsigned char CMOS_READ(unsigned long addr)
-{
-	return *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr);
-}
-
-static inline void CMOS_WRITE(unsigned char data, unsigned long addr)
-{
-	*(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr) = data;
-}
-
-#define RTC_ALWAYS_BCD	1
-
-#endif /* __ASM_MACH_DDB5074_MC146818RTC_H */
diff --git a/include/asm-mips/mach-dec/param.h b/include/asm-mips/mach-dec/param.h
deleted file mode 100644
index 3e4f0e3..0000000
--- a/include/asm-mips/mach-dec/param.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_DEC_PARAM_H
-#define __ASM_MACH_DEC_PARAM_H
-
-/*
- * log2(HZ), change this here if you want another HZ value. This is also
- * used in dec_time_init.  Minimum is 1, Maximum is 15.
- */
-#define LOG_2_HZ 7
-#define HZ (1 << LOG_2_HZ)
-
-#endif /* __ASM_MACH_DEC_PARAM_H */
diff --git a/include/asm-mips/mach-emma2rh/irq.h b/include/asm-mips/mach-emma2rh/irq.h
new file mode 100644
index 0000000..bce6424
--- /dev/null
+++ b/include/asm-mips/mach-emma2rh/irq.h
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_EMMA2RH_IRQ_H
+#define __ASM_MACH_EMMA2RH_IRQ_H
+
+#define NR_IRQS	256
+
+#endif /* __ASM_MACH_EMMA2RH_IRQ_H */
diff --git a/include/asm-mips/mach-excite/cpu-feature-overrides.h b/include/asm-mips/mach-excite/cpu-feature-overrides.h
new file mode 100644
index 0000000..abb76b2
--- /dev/null
+++ b/include/asm-mips/mach-excite/cpu-feature-overrides.h
@@ -0,0 +1,40 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004 Thomas Koeller <thomas.koeller@baslerweb.com>
+ */
+#ifndef __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H
+
+/*
+ * Basler eXcite has an RM9122 processor.
+ */
+#define cpu_has_watch		1
+#define cpu_has_mips16		0
+#define cpu_has_divec		0
+#define cpu_has_vce		0
+#define cpu_has_cache_cdex_p	0
+#define cpu_has_cache_cdex_s	0
+#define cpu_has_prefetch	1
+#define cpu_has_mcheck		0
+#define cpu_has_ejtag		0
+
+#define cpu_has_llsc		1
+#define cpu_has_vtag_icache	0
+#define cpu_has_dc_aliases	0
+#define cpu_has_ic_fills_f_dc	0
+#define cpu_has_dsp		0
+#define cpu_icache_snoops_remote_store	0
+
+#define cpu_has_nofpuex		0
+#define cpu_has_64bits		1
+
+#define cpu_has_subset_pcaches	0
+
+#define cpu_dcache_line_size()	32
+#define cpu_icache_line_size()	32
+#define cpu_scache_line_size()	32
+
+#endif /* __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-excite/excite.h b/include/asm-mips/mach-excite/excite.h
new file mode 100644
index 0000000..c52610d
--- /dev/null
+++ b/include/asm-mips/mach-excite/excite.h
@@ -0,0 +1,155 @@
+#ifndef __EXCITE_H__
+#define __EXCITE_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+
+#define EXCITE_CPU_EXT_CLOCK 100000000
+
+#if !defined(__ASSEMBLER__)
+void __init excite_kgdb_init(void);
+void excite_procfs_init(void);
+extern unsigned long memsize;
+extern char modetty[];
+extern u32 unit_id;
+#endif
+
+/* Base name for XICAP devices */
+#define XICAP_NAME	"xicap_gpi"
+
+/* OCD register offsets */
+#define LKB0		0x0038
+#define LKB5		0x0128
+#define LKM5		0x012C
+#define LKB7		0x0138
+#define LKM7		0x013c
+#define LKB8		0x0140
+#define LKM8		0x0144
+#define LKB9		0x0148
+#define LKM9		0x014c
+#define LKB10		0x0150
+#define LKM10		0x0154
+#define LKB11		0x0158
+#define LKM11		0x015c
+#define LKB12		0x0160
+#define LKM12		0x0164
+#define LKB13		0x0168
+#define LKM13		0x016c
+#define LDP0		0x0200
+#define LDP1		0x0210
+#define LDP2		0x0220
+#define LDP3		0x0230
+#define INTPIN0		0x0A40
+#define INTPIN1		0x0A44
+#define INTPIN2		0x0A48
+#define INTPIN3		0x0A4C
+#define INTPIN4		0x0A50
+#define INTPIN5		0x0A54
+#define INTPIN6		0x0A58
+#define INTPIN7		0x0A5C
+
+
+
+
+/* TITAN register offsets */
+#define CPRR		0x0004
+#define CPDSR		0x0008
+#define CPTC0R		0x000c
+#define CPTC1R		0x0010
+#define CPCFG0		0x0020
+#define CPCFG1		0x0024
+#define CPDST0A		0x0028
+#define CPDST0B		0x002c
+#define CPDST1A		0x0030
+#define CPDST1B		0x0034
+#define CPXDSTA		0x0038
+#define CPXDSTB		0x003c
+#define CPXCISRA	0x0048
+#define CPXCISRB	0x004c
+#define CPGIG0ER	0x0050
+#define CPGIG1ER	0x0054
+#define CPGRWL		0x0068
+#define CPURSLMT	0x00f8
+#define UACFG		0x0200
+#define UAINTS		0x0204
+#define SDRXFCIE	0x4828
+#define SDTXFCIE	0x4928
+#define INTP0Status0	0x1B00
+#define INTP0Mask0	0x1B04
+#define INTP0Set0	0x1B08
+#define INTP0Clear0	0x1B0C
+#define GXCFG		0x5000
+#define GXDMADRPFX	0x5018
+#define GXDMA_DESCADR	0x501c
+#define GXCH0TDESSTRT	0x5054
+
+/* IRQ definitions */
+#define NMICONFIG		0xac0
+#define TITAN_MSGINT	0xc4
+#define TITAN_IRQ	((TITAN_MSGINT / 0x20) + 2)
+#define FPGA0_MSGINT	0x5a
+#define FPGA0_IRQ	((FPGA0_MSGINT / 0x20) + 2)
+#define FPGA1_MSGINT	0x7b
+#define FPGA1_IRQ	((FPGA1_MSGINT / 0x20) + 2)
+#define PHY_MSGINT	0x9c
+#define PHY_IRQ		((PHY_MSGINT   / 0x20) + 2)
+
+#if defined(CONFIG_BASLER_EXCITE_PROTOTYPE)
+/* Pre-release units used interrupt pin #9 */
+#define USB_IRQ		11
+#else
+/* Re-designed units use interrupt pin #1 */
+#define USB_MSGINT	0x39
+#define USB_IRQ		((USB_MSGINT / 0x20) + 2)
+#endif
+#define TIMER_IRQ	12
+
+
+/* Device address ranges */
+#define EXCITE_OFFS_OCD		0x1fffc000
+#define	EXCITE_SIZE_OCD		(16 * 1024)
+#define EXCITE_PHYS_OCD		CPHYSADDR(EXCITE_OFFS_OCD)
+#define EXCITE_ADDR_OCD		CKSEG1ADDR(EXCITE_OFFS_OCD)
+
+#define EXCITE_OFFS_SCRAM 	0x1fffa000
+#define	EXCITE_SIZE_SCRAM	(8 << 10)
+#define EXCITE_PHYS_SCRAM 	CPHYSADDR(EXCITE_OFFS_SCRAM)
+#define EXCITE_ADDR_SCRAM 	CKSEG1ADDR(EXCITE_OFFS_SCRAM)
+
+#define EXCITE_OFFS_PCI_IO	0x1fff8000
+#define	EXCITE_SIZE_PCI_IO	(8 << 10)
+#define EXCITE_PHYS_PCI_IO	CPHYSADDR(EXCITE_OFFS_PCI_IO)
+#define EXCITE_ADDR_PCI_IO 	CKSEG1ADDR(EXCITE_OFFS_PCI_IO)
+
+#define EXCITE_OFFS_TITAN	0x1fff0000
+#define EXCITE_SIZE_TITAN	(32 << 10)
+#define EXCITE_PHYS_TITAN	CPHYSADDR(EXCITE_OFFS_TITAN)
+#define EXCITE_ADDR_TITAN	CKSEG1ADDR(EXCITE_OFFS_TITAN)
+
+#define EXCITE_OFFS_PCI_MEM	0x1ffe0000
+#define EXCITE_SIZE_PCI_MEM	(64 << 10)
+#define EXCITE_PHYS_PCI_MEM	CPHYSADDR(EXCITE_OFFS_PCI_MEM)
+#define EXCITE_ADDR_PCI_MEM	CKSEG1ADDR(EXCITE_OFFS_PCI_MEM)
+
+#define EXCITE_OFFS_FPGA	0x1ffdc000
+#define EXCITE_SIZE_FPGA	(16 << 10)
+#define EXCITE_PHYS_FPGA	CPHYSADDR(EXCITE_OFFS_FPGA)
+#define EXCITE_ADDR_FPGA	CKSEG1ADDR(EXCITE_OFFS_FPGA)
+
+#define EXCITE_OFFS_NAND	0x1ffd8000
+#define EXCITE_SIZE_NAND	(16 << 10)
+#define EXCITE_PHYS_NAND	CPHYSADDR(EXCITE_OFFS_NAND)
+#define EXCITE_ADDR_NAND	CKSEG1ADDR(EXCITE_OFFS_NAND)
+
+#define EXCITE_OFFS_BOOTROM	0x1f000000
+#define EXCITE_SIZE_BOOTROM	(8 << 20)
+#define EXCITE_PHYS_BOOTROM	CPHYSADDR(EXCITE_OFFS_BOOTROM)
+#define EXCITE_ADDR_BOOTROM	CKSEG1ADDR(EXCITE_OFFS_BOOTROM)
+
+/* FPGA address offsets */
+#define EXCITE_FPGA_DPR		0x0104	/* dual-ported ram */
+#define EXCITE_FPGA_SYSCTL	0x0200	/* system control register block */
+
+#endif /* __EXCITE_H__ */
diff --git a/include/asm-mips/mach-excite/excite_nandflash.h b/include/asm-mips/mach-excite/excite_nandflash.h
new file mode 100644
index 0000000..c4cf614
--- /dev/null
+++ b/include/asm-mips/mach-excite/excite_nandflash.h
@@ -0,0 +1,7 @@
+#ifndef __EXCITE_NANDFLASH_H__
+#define __EXCITE_NANDFLASH_H__
+
+/* Resource names */
+#define EXCITE_NANDFLASH_RESOURCE_REGS	"excite_nandflash_regs"
+
+#endif /* __EXCITE_NANDFLASH_H__ */
diff --git a/include/asm-mips/mach-excite/rm9k_eth.h b/include/asm-mips/mach-excite/rm9k_eth.h
new file mode 100644
index 0000000..94705a4
--- /dev/null
+++ b/include/asm-mips/mach-excite/rm9k_eth.h
@@ -0,0 +1,23 @@
+#if !defined(__RM9K_ETH_H__)
+#define __RM9K_ETH_H__
+
+#define RM9K_GE_NAME			"rm9k_ge"
+
+/* Resource names */
+#define RM9K_GE_RESOURCE_MAC      	"rm9k_ge_mac"
+#define RM9K_GE_RESOURCE_MSTAT      	"rm9k_ge_mstat"
+#define RM9K_GE_RESOURCE_PKTPROC	"rm9k_ge_pktproc"
+#define RM9K_GE_RESOURCE_XDMA		"rm9k_ge_xdma"
+#define RM9K_GE_RESOURCE_FIFO_RX  	"rm9k_ge_fifo_rx"
+#define RM9K_GE_RESOURCE_FIFO_TX  	"rm9k_ge_fifo_tx"
+#define RM9K_GE_RESOURCE_FIFOMEM_RX  	"rm9k_ge_fifo_memory_rx"
+#define RM9K_GE_RESOURCE_FIFOMEM_TX  	"rm9k_ge_fifo_memory_tx"
+#define RM9K_GE_RESOURCE_PHY      	"rm9k_ge_phy"
+#define RM9K_GE_RESOURCE_DMADESC_RX  	"rm9k_ge_dmadesc_rx"
+#define RM9K_GE_RESOURCE_DMADESC_TX  	"rm9k_ge_dmadesc_tx"
+#define RM9K_GE_RESOURCE_IRQ_MAIN	"rm9k_ge_irq_main"
+#define RM9K_GE_RESOURCE_IRQ_PHY	"rm9k_ge_irq_phy"
+#define RM9K_GE_RESOURCE_GPI_SLICE	"rm9k_ge_gpi_slice"
+#define RM9K_GE_RESOURCE_MDIO_CHANNEL	"rm9k_ge_mdio_channel"
+
+#endif /* !defined(__RM9K_ETH_H__) */
diff --git a/include/asm-mips/mach-excite/rm9k_wdt.h b/include/asm-mips/mach-excite/rm9k_wdt.h
new file mode 100644
index 0000000..3fa3c08
--- /dev/null
+++ b/include/asm-mips/mach-excite/rm9k_wdt.h
@@ -0,0 +1,12 @@
+#ifndef __RM9K_WDT_H__
+#define __RM9K_WDT_H__
+
+/* Device name */
+#define WDT_NAME		"wdt_gpi"
+
+/* Resource names */
+#define WDT_RESOURCE_REGS	"excite_watchdog_regs"
+#define WDT_RESOURCE_IRQ	"excite_watchdog_irq"
+#define WDT_RESOURCE_COUNTER	"excite_watchdog_counter"
+
+#endif /* __RM9K_WDT_H__ */
diff --git a/include/asm-mips/mach-excite/rm9k_xicap.h b/include/asm-mips/mach-excite/rm9k_xicap.h
new file mode 100644
index 0000000..0095777
--- /dev/null
+++ b/include/asm-mips/mach-excite/rm9k_xicap.h
@@ -0,0 +1,16 @@
+#ifndef __EXCITE_XICAP_H__
+#define __EXCITE_XICAP_H__
+
+
+/* Resource names */
+#define XICAP_RESOURCE_FIFO_RX		"xicap_fifo_rx"
+#define XICAP_RESOURCE_FIFO_TX		"xicap_fifo_tx"
+#define XICAP_RESOURCE_XDMA 		"xicap_xdma"
+#define XICAP_RESOURCE_DMADESC		"xicap_dmadesc"
+#define XICAP_RESOURCE_PKTPROC  	"xicap_pktproc"
+#define XICAP_RESOURCE_IRQ		"xicap_irq"
+#define XICAP_RESOURCE_GPI_SLICE	"xicap_gpi_slice"
+#define XICAP_RESOURCE_FIFO_BLK		"xicap_fifo_blocks"
+#define XICAP_RESOURCE_PKT_STREAM	"xicap_pkt_stream"
+
+#endif /* __EXCITE_XICAP_H__ */
diff --git a/include/asm-mips/mach-generic/floppy.h b/include/asm-mips/mach-generic/floppy.h
index 682a585..83cd69e 100644
--- a/include/asm-mips/mach-generic/floppy.h
+++ b/include/asm-mips/mach-generic/floppy.h
@@ -98,7 +98,7 @@
 static inline int fd_request_irq(void)
 {
 	return request_irq(FLOPPY_IRQ, floppy_interrupt,
-	                   SA_INTERRUPT | SA_SAMPLE_RANDOM, "floppy", NULL);
+	                   SA_INTERRUPT, "floppy", NULL);
 }
 
 static inline void fd_free_irq(void)
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index e331535..6eba2e5 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -15,7 +15,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/stddef.h>
 #include <asm/processor.h>
diff --git a/include/asm-mips/mach-generic/kmalloc.h b/include/asm-mips/mach-generic/kmalloc.h
index 373d66d..410ab5f 100644
--- a/include/asm-mips/mach-generic/kmalloc.h
+++ b/include/asm-mips/mach-generic/kmalloc.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_GENERIC_KMALLOC_H
 #define __ASM_MACH_GENERIC_KMALLOC_H
 
-#include <linux/config.h>
 
 #ifndef CONFIG_DMA_COHERENT
 /*
diff --git a/include/asm-mips/mach-generic/param.h b/include/asm-mips/mach-generic/param.h
deleted file mode 100644
index a0d12f9..0000000
--- a/include/asm-mips/mach-generic/param.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_GENERIC_PARAM_H
-#define __ASM_MACH_GENERIC_PARAM_H
-
-#define HZ		1000		/* Internal kernel timer frequency */
-
-#endif /* __ASM_MACH_GENERIC_PARAM_H */
diff --git a/include/asm-mips/mach-generic/spaces.h b/include/asm-mips/mach-generic/spaces.h
index b849d8d..0ae9997 100644
--- a/include/asm-mips/mach-generic/spaces.h
+++ b/include/asm-mips/mach-generic/spaces.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_MACH_GENERIC_SPACES_H
 #define _ASM_MACH_GENERIC_SPACES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_32BIT
 
diff --git a/include/asm-mips/mach-ip22/cpu-feature-overrides.h b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
index 2a37bed..f7c5dc8 100644
--- a/include/asm-mips/mach-ip22/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip22/cpu-feature-overrides.h
@@ -13,7 +13,7 @@
  */
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4kcache		1
+#define cpu_has_4k_cache	1
 #define cpu_has_fpu		1
 #define cpu_has_32fpr		1
 #define cpu_has_counter		1
diff --git a/include/asm-mips/mach-ip22/spaces.h b/include/asm-mips/mach-ip22/spaces.h
index 8385f71..ab20c02 100644
--- a/include/asm-mips/mach-ip22/spaces.h
+++ b/include/asm-mips/mach-ip22/spaces.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_MACH_IP22_SPACES_H
 #define _ASM_MACH_IP22_SPACES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_32BIT
 
diff --git a/include/asm-mips/mach-ip27/cpu-feature-overrides.h b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
index 2d2f5b9..19c2d13 100644
--- a/include/asm-mips/mach-ip27/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip27/cpu-feature-overrides.h
@@ -31,6 +31,9 @@
 #define cpu_has_nofpuex		0
 #define cpu_has_64bits		1
 
+#define cpu_has_4kex		1
+#define cpu_has_4k_cache	1
+
 #define cpu_has_subset_pcaches	1
 
 #define cpu_dcache_line_size()	32
diff --git a/include/asm-mips/mach-ip32/cpu-feature-overrides.h b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
index 36070b5..2a3de09 100644
--- a/include/asm-mips/mach-ip32/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-ip32/cpu-feature-overrides.h
@@ -9,7 +9,6 @@
 #ifndef __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_IP32_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 /*
  * R5000 has an interesting "restriction":  ll(d)/sc(d)
@@ -38,6 +37,8 @@
 #define cpu_has_vtag_icache	0
 #define cpu_has_ic_fills_f_dc	0
 #define cpu_has_dsp		0
+#define cpu_has_4k_cache	1
+
 
 #define cpu_has_mips32r1	0
 #define cpu_has_mips32r2	0
diff --git a/include/asm-mips/mach-ip32/kmalloc.h b/include/asm-mips/mach-ip32/kmalloc.h
index 9d2d4d9..f6198a2 100644
--- a/include/asm-mips/mach-ip32/kmalloc.h
+++ b/include/asm-mips/mach-ip32/kmalloc.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_IP32_KMALLOC_H
 #define __ASM_MACH_IP32_KMALLOC_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_CPU_R5000) || defined (CONFIG_CPU_RM7000)
 #define ARCH_KMALLOC_MINALIGN	32
diff --git a/include/asm-mips/mach-jazz/floppy.h b/include/asm-mips/mach-jazz/floppy.h
index c9dad99..9413117 100644
--- a/include/asm-mips/mach-jazz/floppy.h
+++ b/include/asm-mips/mach-jazz/floppy.h
@@ -90,7 +90,7 @@
 static inline int fd_request_irq(void)
 {
 	return request_irq(FLOPPY_IRQ, floppy_interrupt,
-	                   SA_INTERRUPT | SA_SAMPLE_RANDOM, "floppy", NULL);
+	                   SA_INTERRUPT, "floppy", NULL);
 }
 
 static inline void fd_free_irq(void)
diff --git a/include/asm-mips/mach-jazz/param.h b/include/asm-mips/mach-jazz/param.h
deleted file mode 100644
index 639763a..0000000
--- a/include/asm-mips/mach-jazz/param.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_JAZZ_PARAM_H
-#define __ASM_MACH_JAZZ_PARAM_H
-
-/*
- * Jazz is currently using the internal 100Hz timer of the R4030
- */
-#define HZ		100		/* Internal kernel timer frequency */
-
-#endif /* __ASM_MACH_JAZZ_PARAM_H */
diff --git a/include/asm-mips/mach-mips/cpu-feature-overrides.h b/include/asm-mips/mach-mips/cpu-feature-overrides.h
index e06af6c..e960679 100644
--- a/include/asm-mips/mach-mips/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-mips/cpu-feature-overrides.h
@@ -9,7 +9,6 @@
 #ifndef __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 /*
  * CPU feature overrides for MIPS boards
@@ -17,7 +16,7 @@
 #ifdef CONFIG_CPU_MIPS32
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4kcache		1
+#define cpu_has_4k_cache	1
 /* #define cpu_has_fpu		? */
 /* #define cpu_has_32fpr	? */
 #define cpu_has_counter		1
@@ -47,7 +46,7 @@
 #ifdef CONFIG_CPU_MIPS64
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4kcache		1
+#define cpu_has_4k_cache	1
 /* #define cpu_has_fpu		? */
 /* #define cpu_has_32fpr	? */
 #define cpu_has_counter		1
diff --git a/include/asm-mips/mach-mips/irq.h b/include/asm-mips/mach-mips/irq.h
index f857969..083d9c5 100644
--- a/include/asm-mips/mach-mips/irq.h
+++ b/include/asm-mips/mach-mips/irq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_MACH_MIPS_IRQ_H
 #define __ASM_MACH_MIPS_IRQ_H
 
-#include <linux/config.h>
 
 #define NR_IRQS	256
 
diff --git a/include/asm-mips/mach-mips/param.h b/include/asm-mips/mach-mips/param.h
deleted file mode 100644
index 805ef6d..0000000
--- a/include/asm-mips/mach-mips/param.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 by Ralf Baechle
- */
-#ifndef __ASM_MACH_MIPS_PARAM_H
-#define __ASM_MACH_MIPS_PARAM_H
-
-#define HZ		100		/* Internal kernel timer frequency */
-
-#endif /* __ASM_MACH_MIPS_PARAM_H */
diff --git a/include/asm-mips/mach-pb1x00/pb1550.h b/include/asm-mips/mach-pb1x00/pb1550.h
index 9578ead..9a4955c 100644
--- a/include/asm-mips/mach-pb1x00/pb1550.h
+++ b/include/asm-mips/mach-pb1x00/pb1550.h
@@ -27,7 +27,6 @@
 #ifndef __ASM_PB1550_H
 #define __ASM_PB1550_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #define DBDMA_AC97_TX_CHAN DSCR_CMD0_PSC1_TX
diff --git a/include/asm-mips/mach-qemu/param.h b/include/asm-mips/mach-qemu/param.h
deleted file mode 100644
index cb30ee4..0000000
--- a/include/asm-mips/mach-qemu/param.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005 by Ralf Baechle
- */
-#ifndef __ASM_MACH_QEMU_PARAM_H
-#define __ASM_MACH_QEMU_PARAM_H
-
-#define HZ		100		/* Internal kernel timer frequency */
-
-#endif /* __ASM_MACH_QEMU_PARAM_H */
diff --git a/include/asm-mips/mach-rm200/cpu-feature-overrides.h b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
index 91e7cf5..11410ae 100644
--- a/include/asm-mips/mach-rm200/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-rm200/cpu-feature-overrides.h
@@ -14,7 +14,7 @@
 
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4kcache		1
+#define cpu_has_4k_cache	1
 #define cpu_has_fpu		1
 #define cpu_has_32fpr		1
 #define cpu_has_counter		1
@@ -35,10 +35,8 @@
 #define cpu_has_nofpuex		0
 #define cpu_has_64bits		1
 
-#define cpu_has_subset_pcaches	0	/* No S-cache on R5000 I think ...  */
 #define cpu_dcache_line_size()	32
 #define cpu_icache_line_size()	32
-#define cpu_scache_line_size()	0	/* No S-cache on R5000 I think ...  */
 
 #define cpu_has_mips32r1	0
 #define cpu_has_mips32r2	0
diff --git a/include/asm-mips/mach-sim/cpu-feature-overrides.h b/include/asm-mips/mach-sim/cpu-feature-overrides.h
index cadbe8e..d736bda 100644
--- a/include/asm-mips/mach-sim/cpu-feature-overrides.h
+++ b/include/asm-mips/mach-sim/cpu-feature-overrides.h
@@ -8,7 +8,6 @@
 #ifndef __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_SIM_CPU_FEATURE_OVERRIDES_H
 
-#include <linux/config.h>
 
 /*
  * CPU feature overrides for MIPS boards
@@ -16,7 +15,7 @@
 #ifdef CONFIG_CPU_MIPS32
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4kcache		1
+#define cpu_has_4k_cache	1
 #define cpu_has_fpu		0
 /* #define cpu_has_32fpr	? */
 #define cpu_has_counter		1
@@ -41,7 +40,7 @@
 #ifdef CONFIG_CPU_MIPS64
 #define cpu_has_tlb		1
 #define cpu_has_4kex		1
-#define cpu_has_4kcache		1
+#define cpu_has_4k_cache	1
 /* #define cpu_has_fpu		? */
 /* #define cpu_has_32fpr	? */
 #define cpu_has_counter		1
diff --git a/include/asm-mips/mach-wrppmc/mach-gt64120.h b/include/asm-mips/mach-wrppmc/mach-gt64120.h
new file mode 100644
index 0000000..ba9205a
--- /dev/null
+++ b/include/asm-mips/mach-wrppmc/mach-gt64120.h
@@ -0,0 +1,84 @@
+/*
+ * This is a direct copy of the ev96100.h file, with a global
+ * search and replace.  The numbers are the same.
+ *
+ * The reason I'm duplicating this is so that the 64120/96100
+ * defines won't be confusing in the source code.
+ */
+#ifndef __ASM_MIPS_GT64120_H
+#define __ASM_MIPS_GT64120_H
+
+/*
+ * This is the CPU physical memory map of PPMC Board:
+ *
+ *    0x00000000-0x03FFFFFF      - 64MB SDRAM (SCS[0]#)
+ *    0x1C000000-0x1C000000      - LED (CS0)
+ *    0x1C800000-0x1C800007      - UART 16550 port (CS1)
+ *    0x1F000000-0x1F000000      - MailBox (CS3)
+ *    0x1FC00000-0x20000000      - 4MB Flash (BOOT CS)
+ */
+
+#define WRPPMC_SDRAM_SCS0_BASE	0x00000000
+#define WRPPMC_SDRAM_SCS0_SIZE	0x04000000
+
+#define WRPPMC_UART16550_BASE	0x1C800000
+#define WRPPMC_UART16550_CLOCK	3686400 /* 3.68MHZ */
+
+#define WRPPMC_LED_BASE		0x1C000000
+#define WRPPMC_MBOX_BASE	0x1F000000
+
+#define WRPPMC_BOOTROM_BASE	0x1FC00000
+#define WRPPMC_BOOTROM_SIZE	0x00400000 /* 4M Flash */
+
+#define WRPPMC_MIPS_TIMER_IRQ	7 /* MIPS compare/count timer interrupt */
+#define WRPPMC_UART16550_IRQ	6
+#define WRPPMC_PCI_INTA_IRQ	3
+
+/*
+ * PCI Bus I/O and Memory resources allocation
+ *
+ * NOTE: We only have PCI_0 hose interface
+ */
+#define GT_PCI_MEM_BASE	0x13000000UL
+#define GT_PCI_MEM_SIZE	0x02000000UL
+#define GT_PCI_IO_BASE	0x11000000UL
+#define GT_PCI_IO_SIZE	0x02000000UL
+#define GT_ISA_IO_BASE	PCI_IO_BASE
+
+/*
+ * PCI interrupts will come in on either the INTA or INTD interrups lines,
+ * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
+ * boards, they all either come in on IntD or they all come in on IntA, they
+ * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
+ * "requested" interrupt numbers and go through the list whenever we get an
+ * IntA/D.
+ *
+ * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and
+ * INTD is 11.
+ */
+#define GT_TIMER	4
+#define GT_INTA		2
+#define GT_INTD		5
+
+#ifndef __ASSEMBLY__
+
+/*
+ * GT64120 internal register space base address
+ */
+extern unsigned long gt64120_base;
+
+#define GT64120_BASE	(gt64120_base)
+
+/* define WRPPMC_EARLY_DEBUG to enable early output something to UART */
+#undef WRPPMC_EARLY_DEBUG
+
+#ifdef WRPPMC_EARLY_DEBUG
+extern void wrppmc_led_on(int mask);
+extern void wrppmc_led_off(int mask);
+extern void wrppmc_early_printk(const char *fmt, ...);
+#else
+#define wrppmc_early_printk(fmt, ...) do {} while (0)
+#endif /* WRPPMC_EARLY_DEBUG */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_MIPS_GT64120_H */
diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
index fa8b913..b98f165 100644
--- a/include/asm-mips/mips-boards/generic.h
+++ b/include/asm-mips/mips-boards/generic.h
@@ -20,7 +20,6 @@
 #ifndef __ASM_MIPS_BOARDS_GENERIC_H
 #define __ASM_MIPS_BOARDS_GENERIC_H
 
-#include <linux/config.h>
 #include <asm/addrspace.h>
 #include <asm/byteorder.h>
 #include <asm/mips-boards/bonito64.h>
diff --git a/include/asm-mips/mipsregs.h b/include/asm-mips/mipsregs.h
index 5af7517f..6739779 100644
--- a/include/asm-mips/mipsregs.h
+++ b/include/asm-mips/mipsregs.h
@@ -13,7 +13,6 @@
 #ifndef _ASM_MIPSREGS_H
 #define _ASM_MIPSREGS_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 #include <asm/hazards.h>
 
@@ -1451,12 +1450,10 @@
 {
 	if ((previous & __EMT_ENABLE))
 		__asm__ __volatile__(
-		"	.set	noreorder				\n"
 		"	.set	mips32r2				\n"
 		"	.word	0x41600be1		# emt		\n"
 		"	ehb						\n"
-		"	.set	mips0					\n"
-		"	.set	reorder					\n");
+		"	.set	mips0					\n");
 }
 
 static inline void __ehb(void)
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index 6e09f4c..18b69de 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_MMU_CONTEXT_H
 #define _ASM_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h
index 7bde443..f53ec54 100644
--- a/include/asm-mips/mmzone.h
+++ b/include/asm-mips/mmzone.h
@@ -5,26 +5,13 @@
 #ifndef _ASM_MMZONE_H_
 #define _ASM_MMZONE_H_
 
-#include <linux/config.h>
 #include <asm/page.h>
 #include <mmzone.h>
 
 #ifdef CONFIG_DISCONTIGMEM
 
-#define kvaddr_to_nid(kvaddr)	pa_to_nid(__pa(kvaddr))
 #define pfn_to_nid(pfn)		pa_to_nid((pfn) << PAGE_SHIFT)
 
-#define pfn_valid(pfn)						\
-({								\
- 	unsigned long __pfn = (pfn);				\
- 	int __n = pfn_to_nid(__pfn);				\
-	((__n >= 0) ? (__pfn < NODE_DATA(__n)->node_start_pfn +	\
-		       NODE_DATA(__n)->node_spanned_pages) : 0);\
-})
-
-/* XXX: FIXME -- wli */
-#define kern_addr_valid(addr)	(0)
-
 #endif /* CONFIG_DISCONTIGMEM */
 
 #endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-mips/module.h b/include/asm-mips/module.h
index 2af496c..399d03f 100644
--- a/include/asm-mips/module.h
+++ b/include/asm-mips/module.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_MODULE_H
 #define _ASM_MODULE_H
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <asm/uaccess.h>
 
diff --git a/include/asm-mips/msgbuf.h b/include/asm-mips/msgbuf.h
index a153395..0d6c7f1 100644
--- a/include/asm-mips/msgbuf.h
+++ b/include/asm-mips/msgbuf.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_MSGBUF_H
 #define _ASM_MSGBUF_H
 
-#include <linux/config.h>
 
 /*
  * The msqid64_ds structure for the MIPS architecture.
diff --git a/include/asm-mips/paccess.h b/include/asm-mips/paccess.h
index 46f2d23..147844e 100644
--- a/include/asm-mips/paccess.h
+++ b/include/asm-mips/paccess.h
@@ -13,7 +13,6 @@
 #ifndef _ASM_PACCESS_H
 #define _ASM_PACCESS_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 
 #ifdef CONFIG_32BIT
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index 4035ec7..6b97744 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_PAGE_H
 #define _ASM_PAGE_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 
@@ -145,6 +144,25 @@
 #endif
 #endif
 
+#ifdef CONFIG_FLATMEM
+
+#define pfn_valid(pfn)		((pfn) < max_mapnr)
+
+#elif defined(CONFIG_NEED_MULTIPLE_NODES)
+
+#define pfn_valid(pfn)							\
+({									\
+	unsigned long __pfn = (pfn);					\
+	int __n = pfn_to_nid(__pfn);					\
+	((__n >= 0) ? (__pfn < NODE_DATA(__n)->node_start_pfn +		\
+	                       NODE_DATA(__n)->node_spanned_pages)	\
+	            : 0);						\
+})
+
+#else
+#error Provide a definition of pfn_valid
+#endif
+
 #define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
diff --git a/include/asm-mips/param.h b/include/asm-mips/param.h
index 2bead82..1d9bb8c 100644
--- a/include/asm-mips/param.h
+++ b/include/asm-mips/param.h
@@ -11,7 +11,7 @@
 
 #ifdef __KERNEL__
 
-# include <param.h>			/* Internal kernel timer frequency */
+# define HZ		CONFIG_HZ	/* Internal kernel timer frequency */
 # define USER_HZ	100		/* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
 #endif
diff --git a/include/asm-mips/pci.h b/include/asm-mips/pci.h
index 6c9ad81..c4d68be 100644
--- a/include/asm-mips/pci.h
+++ b/include/asm-mips/pci.h
@@ -6,7 +6,6 @@
 #ifndef _ASM_PCI_H
 #define _ASM_PCI_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 #ifdef __KERNEL__
diff --git a/include/asm-mips/pci/bridge.h b/include/asm-mips/pci/bridge.h
index b4ee995..0c45e75 100644
--- a/include/asm-mips/pci/bridge.h
+++ b/include/asm-mips/pci/bridge.h
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <asm/xtalk/xwidget.h>		/* generic widget header */
+#include <asm/sn/types.h>
 
 /* I/O page size */
 
@@ -848,4 +849,6 @@
 extern void register_bridge_irq(unsigned int irq);
 extern int request_bridge_irq(struct bridge_controller *bc);
 
+extern struct pci_ops bridge_pci_ops;
+
 #endif /* _ASM_PCI_BRIDGE_H */
diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
index fe1df57..582c1fe 100644
--- a/include/asm-mips/pgalloc.h
+++ b/include/asm-mips/pgalloc.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_PGALLOC_H
 #define _ASM_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/highmem.h>
 #include <linux/mm.h>
 
diff --git a/include/asm-mips/pgtable-32.h b/include/asm-mips/pgtable-32.h
index 087c207..4b26d85 100644
--- a/include/asm-mips/pgtable-32.h
+++ b/include/asm-mips/pgtable-32.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_PGTABLE_32_H
 #define _ASM_PGTABLE_32_H
 
-#include <linux/config.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
 
diff --git a/include/asm-mips/pgtable-64.h b/include/asm-mips/pgtable-64.h
index 2faf5c9..e3db932 100644
--- a/include/asm-mips/pgtable-64.h
+++ b/include/asm-mips/pgtable-64.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_PGTABLE_64_H
 #define _ASM_PGTABLE_64_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 
 #include <asm/addrspace.h>
diff --git a/include/asm-mips/pgtable-bits.h b/include/asm-mips/pgtable-bits.h
index 01e76e9..7494ba9 100644
--- a/include/asm-mips/pgtable-bits.h
+++ b/include/asm-mips/pgtable-bits.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_PGTABLE_BITS_H
 #define _ASM_PGTABLE_BITS_H
 
-#include <linux/config.h>
 
 /*
  * Note that we shift the lower 32bits of each EntryLo[01] entry
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index d0af2a3..a36ca1b 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
 
-#include <linux/config.h>
 #ifdef CONFIG_32BIT
 #include <asm/pgtable-32.h>
 #endif
@@ -379,9 +378,7 @@
 	__update_cache(vma, address, pte);
 }
 
-#ifndef CONFIG_NEED_MULTIPLE_NODES
 #define kern_addr_valid(addr)	(1)
-#endif
 
 #ifdef CONFIG_64BIT_PHYS_ADDR
 extern int remap_pfn_range(struct vm_area_struct *vma, unsigned long from, unsigned long pfn, unsigned long size, pgprot_t prot);
diff --git a/include/asm-mips/prefetch.h b/include/asm-mips/prefetch.h
index 71293ec..1785083 100644
--- a/include/asm-mips/prefetch.h
+++ b/include/asm-mips/prefetch.h
@@ -8,7 +8,6 @@
 #ifndef __ASM_PREFETCH_H
 #define __ASM_PREFETCH_H
 
-#include <linux/config.h>
 
 /*
  * R5000 and RM5200 implements pref and prefx instructions but they're nops, so
diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
index 0fb75f0..5f80ba7 100644
--- a/include/asm-mips/processor.h
+++ b/include/asm-mips/processor.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_PROCESSOR_H
 #define _ASM_PROCESSOR_H
 
-#include <linux/config.h>
 #include <linux/cpumask.h>
 #include <linux/threads.h>
 
@@ -71,11 +70,6 @@
 
 typedef __u64 fpureg_t;
 
-struct mips_fpu_hard_struct {
-	fpureg_t	fpr[NUM_FPU_REGS];
-	unsigned int	fcr31;
-};
-
 /*
  * It would be nice to add some more fields for emulator statistics, but there
  * are a number of fixed offsets in offset.h and elsewhere that would have to
@@ -83,18 +77,13 @@
  * the FPU emulator for now.  See asm-mips/fpu_emulator.h.
  */
 
-struct mips_fpu_soft_struct {
+struct mips_fpu_struct {
 	fpureg_t	fpr[NUM_FPU_REGS];
 	unsigned int	fcr31;
 };
 
-union mips_fpu_union {
-        struct mips_fpu_hard_struct hard;
-        struct mips_fpu_soft_struct soft;
-};
-
 #define INIT_FPU { \
-	{{0,},} \
+	{0,} \
 }
 
 #define NUM_DSP_REGS   6
@@ -133,7 +122,7 @@
 	unsigned long cp0_status;
 
 	/* Saved fpu/fpu emulator stuff. */
-	union mips_fpu_union fpu;
+	struct mips_fpu_struct fpu;
 #ifdef CONFIG_MIPS_MT_FPAFF
 	/* Emulated instruction count */
 	unsigned long emulated_fp;
diff --git a/include/asm-mips/ptrace.h b/include/asm-mips/ptrace.h
index fa9d871..4113316 100644
--- a/include/asm-mips/ptrace.h
+++ b/include/asm-mips/ptrace.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_PTRACE_H
 #define _ASM_PTRACE_H
 
-#include <linux/config.h>
 
 #include <asm/isadep.h>
 
diff --git a/include/asm-mips/qemu.h b/include/asm-mips/qemu.h
index 905c395..531caf4 100644
--- a/include/asm-mips/qemu.h
+++ b/include/asm-mips/qemu.h
@@ -21,4 +21,10 @@
  */
 #define QEMU_C0_COUNTER_CLOCK	100000000
 
+/*
+ * Magic qemu system control location.
+ */
+#define QEMU_RESTART_REG	0xBFBF0000
+#define QEMU_HALT_REG		0xBFBF0004
+
 #endif /* __ASM_QEMU_H */
diff --git a/include/asm-mips/reg.h b/include/asm-mips/reg.h
index 6173004..634b55d 100644
--- a/include/asm-mips/reg.h
+++ b/include/asm-mips/reg.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_MIPS_REG_H
 #define __ASM_MIPS_REG_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_32BIT) || defined(WANT_COMPAT_REG_H)
 
diff --git a/include/asm-mips/resource.h b/include/asm-mips/resource.h
index 1fba00c..87cb308 100644
--- a/include/asm-mips/resource.h
+++ b/include/asm-mips/resource.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_RESOURCE_H
 #define _ASM_RESOURCE_H
 
-#include <linux/config.h>
 
 /*
  * These five resource limit IDs have a MIPS/Linux-specific ordering,
diff --git a/include/asm-mips/rm9k-ocd.h b/include/asm-mips/rm9k-ocd.h
new file mode 100644
index 0000000..b0b80d9
--- /dev/null
+++ b/include/asm-mips/rm9k-ocd.h
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (C) 2004 by Basler Vision Technologies AG
+ *  Author: Thomas Koeller <thomas.koeller@baslerweb.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined(_ASM_RM9K_OCD_H)
+#define _ASM_RM9K_OCD_H
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+extern volatile void __iomem * const ocd_base;
+extern volatile void __iomem * const titan_base;
+
+#define ocd_addr(__x__)		(ocd_base + (__x__))
+#define titan_addr(__x__)	(titan_base + (__x__))
+#define scram_addr(__x__)	(scram_base + (__x__))
+
+/* OCD register access */
+#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__))
+#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__))
+#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__))
+#define ocd_writel(__val__, __offs__) \
+	__raw_writel((__val__), ocd_addr(__offs__))
+#define ocd_writew(__val__, __offs__) \
+	__raw_writew((__val__), ocd_addr(__offs__))
+#define ocd_writeb(__val__, __offs__) \
+	__raw_writeb((__val__), ocd_addr(__offs__))
+
+/* TITAN register access - 32 bit-wide only */
+#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__))
+#define titan_writel(__val__, __offs__) \
+	__raw_writel((__val__), titan_addr(__offs__))
+
+/* Protect access to shared TITAN registers */
+extern spinlock_t titan_lock;
+extern int titan_irqflags;
+#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags)
+#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags)
+
+#endif	/* !defined(_ASM_RM9K_OCD_H) */
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index 7196ceb..584bd9c 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_SERIAL_H
 #define _ASM_SERIAL_H
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff --git a/include/asm-mips/sgiarcs.h b/include/asm-mips/sgiarcs.h
index 722b77a..ddb859d 100644
--- a/include/asm-mips/sgiarcs.h
+++ b/include/asm-mips/sgiarcs.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_SGIARCS_H
 #define _ASM_SGIARCS_H
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/arc/types.h>
 
diff --git a/include/asm-mips/sibyte/board.h b/include/asm-mips/sibyte/board.h
index 900edcb..3dfe29e 100644
--- a/include/asm-mips/sibyte/board.h
+++ b/include/asm-mips/sibyte/board.h
@@ -19,7 +19,6 @@
 #ifndef _SIBYTE_BOARD_H
 #define _SIBYTE_BOARD_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_PTSWARM) || \
     defined(CONFIG_SIBYTE_CRHONE) || defined(CONFIG_SIBYTE_CRHINE) || \
diff --git a/include/asm-mips/sibyte/carmel.h b/include/asm-mips/sibyte/carmel.h
index b5e7dae..57c53e6 100644
--- a/include/asm-mips/sibyte/carmel.h
+++ b/include/asm-mips/sibyte/carmel.h
@@ -18,7 +18,6 @@
 #ifndef __ASM_SIBYTE_CARMEL_H
 #define __ASM_SIBYTE_CARMEL_H
 
-#include <linux/config.h>
 
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
diff --git a/include/asm-mips/sibyte/sentosa.h b/include/asm-mips/sibyte/sentosa.h
index 8246058..64c4787 100644
--- a/include/asm-mips/sibyte/sentosa.h
+++ b/include/asm-mips/sibyte/sentosa.h
@@ -18,7 +18,6 @@
 #ifndef __ASM_SIBYTE_SENTOSA_H
 #define __ASM_SIBYTE_SENTOSA_H
 
-#include <linux/config.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
 
diff --git a/include/asm-mips/sibyte/swarm.h b/include/asm-mips/sibyte/swarm.h
index 06e1d52..86db37e 100644
--- a/include/asm-mips/sibyte/swarm.h
+++ b/include/asm-mips/sibyte/swarm.h
@@ -18,7 +18,6 @@
 #ifndef __ASM_SIBYTE_SWARM_H
 #define __ASM_SIBYTE_SWARM_H
 
-#include <linux/config.h>
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_int.h>
 
diff --git a/include/asm-mips/siginfo.h b/include/asm-mips/siginfo.h
index 2ba313d..2e32949 100644
--- a/include/asm-mips/siginfo.h
+++ b/include/asm-mips/siginfo.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_SIGINFO_H
 #define _ASM_SIGINFO_H
 
-#include <linux/config.h>
 
 #define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(long) + 2*sizeof(int))
 #undef __ARCH_SI_TRAPNO	/* exception code needs to fill this ...  */
diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h
index d8349e4..a1f3a3f 100644
--- a/include/asm-mips/signal.h
+++ b/include/asm-mips/signal.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_SIGNAL_H
 #define _ASM_SIGNAL_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #define _NSIG		128
diff --git a/include/asm-mips/sim.h b/include/asm-mips/sim.h
index 9c2af1b..67c4fe5 100644
--- a/include/asm-mips/sim.h
+++ b/include/asm-mips/sim.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_SIM_H
 #define _ASM_SIM_H
 
-#include <linux/config.h>
 
 #include <asm/asm-offsets.h>
 
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index e14e4b6..1608fd7 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -11,7 +11,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SMP
 
diff --git a/include/asm-mips/sn/addrs.h b/include/asm-mips/sn/addrs.h
index 2b5cef1..8fa0af6 100644
--- a/include/asm-mips/sn/addrs.h
+++ b/include/asm-mips/sn/addrs.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_SN_ADDRS_H
 #define _ASM_SN_ADDRS_H
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
@@ -27,13 +26,8 @@
 
 #ifndef __ASSEMBLY__
 
-#if defined(CONFIG_SGI_IO)	/* FIXME */
-#define PS_UINT_CAST		(__psunsigned_t)
-#define UINT64_CAST		(__uint64_t)
-#else	/* CONFIG_SGI_IO */
 #define PS_UINT_CAST		(unsigned long)
 #define UINT64_CAST		(unsigned long)
-#endif	/* CONFIG_SGI_IO */
 
 #define HUBREG_CAST		(volatile hubreg_t *)
 
@@ -253,14 +247,6 @@
  * for _x.
  */
 
-#ifdef _STANDALONE
-
-/* DO NOT USE THESE DIRECTLY IN THE KERNEL. SEE BELOW. */
-#define LOCAL_HUB(_x)		(HUBREG_CAST (IALIAS_BASE + (_x)))
-#define REMOTE_HUB(_n, _x)	(HUBREG_CAST (NODE_SWIN_BASE(_n, 1) +	\
-					      0x800000 + (_x)))
-#endif /* _STANDALONE */
-
 /*
  * WARNING:
  *	When certain Hub chip workaround are defined, it's not sufficient
@@ -327,20 +313,6 @@
 	PHYS_TO_K0(NODE_OFFSET(nasid) | ARCS_SPB_OFFSET)
 #define ARCS_SPB_SIZE		0x0400
 
-#ifdef _STANDALONE
-
-#define ARCS_TVECTOR_OFFSET	0x2800
-#define ARCS_PVECTOR_OFFSET	0x2c00
-
-/*
- * These addresses are used by the master CPU to install the transfer
- * and private vectors.  All others use the SPB to find them.
- */
-#define TVADDR	(NODE_CAC_BASE(get_nasid()) + ARCS_TVECTOR_OFFSET)
-#define PVADDR	(NODE_CAC_BASE(get_nasid()) + ARCS_PVECTOR_OFFSET)
-
-#endif /* _STANDALONE */
-
 #define KLDIR_OFFSET		0x2000
 #define KLDIR_ADDR(nasid)						\
 	TO_NODE_UNCAC((nasid), KLDIR_OFFSET)
diff --git a/include/asm-mips/sn/agent.h b/include/asm-mips/sn/agent.h
index d6df13a..ac4ea85 100644
--- a/include/asm-mips/sn/agent.h
+++ b/include/asm-mips/sn/agent.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_SGI_SN_AGENT_H
 #define _ASM_SGI_SN_AGENT_H
 
-#include <linux/config.h>
 #include <linux/topology.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
diff --git a/include/asm-mips/sn/arch.h b/include/asm-mips/sn/arch.h
index d247a81..51174af 100644
--- a/include/asm-mips/sn/arch.h
+++ b/include/asm-mips/sn/arch.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_SN_ARCH_H
 #define _ASM_SN_ARCH_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/sn/types.h>
 #ifdef CONFIG_SGI_IP27
diff --git a/include/asm-mips/sn/fru.h b/include/asm-mips/sn/fru.h
new file mode 100644
index 0000000..b3e3606
--- /dev/null
+++ b/include/asm-mips/sn/fru.h
@@ -0,0 +1,44 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Derived from IRIX <sys/SN/SN0/sn0_fru.h>
+ *
+ * Copyright (C) 1992 - 1997, 1999 Silcon Graphics, Inc.
+ * Copyright (C) 1999, 2006 Ralf Baechle (ralf@linux-mips)
+ */
+#ifndef __ASM_SN_FRU_H
+#define __ASM_SN_FRU_H
+
+#define MAX_DIMMS			8	 /* max # of dimm banks */
+#define MAX_PCIDEV			8	 /* max # of pci devices on a pci bus */
+
+typedef unsigned char confidence_t;
+
+typedef struct kf_mem_s {
+	confidence_t km_confidence; /* confidence level that the memory is bad
+				     * is this necessary ?
+				     */
+	confidence_t km_dimm[MAX_DIMMS];
+	                            /* confidence level that dimm[i] is bad
+				     *I think this is the right number
+				     */
+
+} kf_mem_t;
+
+typedef struct kf_cpu_s {
+	confidence_t  	kc_confidence; /* confidence level that cpu is bad */
+	confidence_t  	kc_icache; /* confidence level that instr. cache is bad */
+	confidence_t  	kc_dcache; /* confidence level that data   cache is bad */
+	confidence_t  	kc_scache; /* confidence level that sec.   cache is bad */
+	confidence_t	kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */
+} kf_cpu_t;
+
+typedef struct kf_pci_bus_s {
+	confidence_t	kpb_belief;	/* confidence level  that the  pci bus is bad */
+	confidence_t	kpb_pcidev_belief[MAX_PCIDEV];
+	                                /* confidence level that the pci dev is bad */
+} kf_pci_bus_t;
+
+#endif /* __ASM_SN_FRU_H */
diff --git a/include/asm-mips/sn/io.h b/include/asm-mips/sn/io.h
index 1332645..ab2fa8c 100644
--- a/include/asm-mips/sn/io.h
+++ b/include/asm-mips/sn/io.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_SN_IO_H
 #define _ASM_SN_IO_H
 
-#include <linux/config.h>
 #if defined (CONFIG_SGI_IP27)
 #include <asm/sn/sn0/hubio.h>
 #endif
diff --git a/include/asm-mips/sn/klconfig.h b/include/asm-mips/sn/klconfig.h
index 9709ff7..52238e6 100644
--- a/include/asm-mips/sn/klconfig.h
+++ b/include/asm-mips/sn/klconfig.h
@@ -27,7 +27,6 @@
  *      that offsets of existing fields do not change.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/sn/types.h>
 
@@ -37,7 +36,7 @@
 //#include <sys/SN/router.h>
 // XXX Stolen from <sys/SN/router.h>:
 #define MAX_ROUTER_PORTS (6)    /* Max. number of ports on a router */
-#include <asm/sn/sn0/sn0_fru.h>
+#include <asm/sn/fru.h>
 //#include <sys/graph.h>
 //#include <sys/xtalk/xbow.h>
 
@@ -54,32 +53,21 @@
 #include <asm/sn/agent.h>
 #include <asm/arc/types.h>
 #include <asm/arc/hinv.h>
-#if defined(CONFIG_SGI_IO) || defined(CONFIG_SGI_IP35)
+#if defined(CONFIG_SGI_IP35)
 // The hack file has to be before vector and after sn0_fru....
 #include <asm/hack.h>
 #include <asm/sn/vector.h>
 #include <asm/xtalk/xtalk.h>
-#endif /* CONFIG_SGI_IO || CONFIG_SGI_IP35 */
+#endif /* CONFIG_SGI_IP35 */
 #endif /* CONFIG_SGI_IP27 || CONFIG_SGI_IP35 */
 
 #define KLCFGINFO_MAGIC	0xbeedbabe
 
-#ifdef FRUTEST
-typedef u64 klconf_off_t;
-#else
 typedef s32 klconf_off_t;
-#endif
 
 /*
  * Some IMPORTANT OFFSETS. These are the offsets on all NODES.
  */
-#if 0
-#define RAMBASE                 0
-#define ARCSSPB_OFF             0x1000 /* shift it to sys/arcs/spb.h */
-
-#define OFF_HWGRAPH 		0
-#endif
-
 #define	MAX_MODULE_ID		255
 #define SIZE_PAD		4096 /* 4k padding for structures */
 /*
@@ -134,15 +122,9 @@
 
 
 typedef struct console_s {
-#if defined(CONFIG_SGI_IO)	/* FIXME */
-	__psunsigned_t 	uart_base;
-	__psunsigned_t 	config_base;
-	__psunsigned_t 	memory_base;
-#else
 	unsigned long 	uart_base;
 	unsigned long 	config_base;
 	unsigned long 	memory_base;
-#endif
 	short		baud;
 	short		flag;
 	int		type;
@@ -174,10 +156,6 @@
 
 
 #define KL_CONFIG_HDR(_nasid) 	((kl_config_hdr_t *)(KLCONFIG_ADDR(_nasid)))
-#if 0
-#define KL_CONFIG_MALLOC_HDR(_nasid) \
-                                (KL_CONFIG_HDR(_nasid)->ch_malloc_hdr)
-#endif
 #define KL_CONFIG_INFO_OFFSET(_nasid)					\
         (KL_CONFIG_HDR(_nasid)->ch_board_info)
 #define KL_CONFIG_INFO_SET_OFFSET(_nasid, _off)				\
@@ -197,23 +175,13 @@
 
 /* --- New Macros for the changed kl_config_hdr_t structure --- */
 
-#if defined(CONFIG_SGI_IO)
-#define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
-			((__psunsigned_t)_k + (_k->ch_malloc_hdr_off)))
-#else
 #define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
 			(unsigned long)_k + (_k->ch_malloc_hdr_off)))
-#endif
 
 #define KL_CONFIG_CH_MALLOC_HDR(_n)   PTR_CH_MALLOC_HDR(KL_CONFIG_HDR(_n))
 
-#if defined(CONFIG_SGI_IO)
-#define PTR_CH_CONS_INFO(_k)	((console_t *)\
-			((__psunsigned_t)_k + (_k->ch_cons_off)))
-#else
 #define PTR_CH_CONS_INFO(_k)	((console_t *)\
 			((unsigned long)_k + (_k->ch_cons_off)))
-#endif
 
 #define KL_CONFIG_CH_CONS_INFO(_n)   PTR_CH_CONS_INFO(KL_CONFIG_HDR(_n))
 
@@ -490,14 +458,6 @@
 #define KLCF_NUM_COMPS(_brd)	((_brd)->brd_numcompts)
 #define KLCF_MODULE_ID(_brd)	((_brd)->brd_module)
 
-#ifdef FRUTEST
-
-#define KLCF_NEXT(_brd) 		((_brd)->brd_next ? (lboard_t *)((_brd)->brd_next):  NULL)
-#define KLCF_COMP(_brd, _ndx)   	(klinfo_t *)((_brd)->brd_compts[(_ndx)])
-#define KLCF_COMP_ERROR(_brd, _comp)   	(_brd = _brd , (_comp)->errinfo)
-
-#else
-
 #define KLCF_NEXT(_brd) 	\
         ((_brd)->brd_next ? 	\
 	 (lboard_t *)(NODE_OFFSET_TO_K1(NASID_GET(_brd), (_brd)->brd_next)):\
@@ -509,8 +469,6 @@
 #define KLCF_COMP_ERROR(_brd, _comp)	\
                (NODE_OFFSET_TO_K1(NASID_GET(_brd), (_comp)->errinfo))
 
-#endif
-
 #define KLCF_COMP_TYPE(_comp)	((_comp)->struct_type)
 #define KLCF_BRIDGE_W_ID(_comp)	((_comp)->physid)	/* Widget ID */
 
@@ -631,18 +589,6 @@
 	klconf_off_t	port_offset;
 } klport_t;
 
-#if 0
-/*
- * This is very similar to the klport_s but instead of having a componant
- * offset it has a board offset.
- */
-typedef struct klxbow_port_s {
-	nasid_t		port_nasid;
-	unsigned char	port_flag;
-	klconf_off_t	board_offset;
-} klxbow_port_t;
-#endif
-
 typedef struct klcpu_s {                          /* CPU */
 	klinfo_t 	cpu_info;
 	unsigned short 	cpu_prid;	/* Processor PRID value */
@@ -945,36 +891,6 @@
 extern lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_class);
 
 
-#if defined(CONFIG_SGI_IO)
-extern xwidgetnum_t nodevertex_widgetnum_get(vertex_hdl_t node_vtx);
-extern vertex_hdl_t nodevertex_xbow_peer_get(vertex_hdl_t node_vtx);
-extern lboard_t *find_gfxpipe(int pipenum);
-extern void setup_gfxpipe_link(vertex_hdl_t vhdl,int pipenum);
-extern lboard_t *find_lboard_module_class(lboard_t *start, moduleid_t mod,
-                                               unsigned char brd_class);
-extern lboard_t *find_nic_lboard(lboard_t *, nic_t);
-extern lboard_t *find_nic_type_lboard(nasid_t, unsigned char, nic_t);
-extern lboard_t *find_lboard_modslot(lboard_t *start, moduleid_t mod, slotid_t slot);
-extern lboard_t *find_lboard_module(lboard_t *start, moduleid_t mod);
-extern lboard_t *get_board_name(nasid_t nasid, moduleid_t mod, slotid_t slot, char *name);
-extern int	config_find_nic_router(nasid_t, nic_t, lboard_t **, klrou_t**);
-extern int	config_find_nic_hub(nasid_t, nic_t, lboard_t **, klhub_t**);
-extern int	config_find_xbow(nasid_t, lboard_t **, klxbow_t**);
-extern klcpu_t *get_cpuinfo(cpuid_t cpu);
-extern int 	update_klcfg_cpuinfo(nasid_t, int);
-extern void 	board_to_path(lboard_t *brd, char *path);
-extern moduleid_t get_module_id(nasid_t nasid);
-extern void 	nic_name_convert(char *old_name, char *new_name);
-extern int 	module_brds(nasid_t nasid, lboard_t **module_brds, int n);
-extern lboard_t *brd_from_key(ulong_t key);
-extern void 	device_component_canonical_name_get(lboard_t *,klinfo_t *,
-						    char *);
-extern int	board_serial_number_get(lboard_t *,char *);
-extern int	is_master_baseio(nasid_t,moduleid_t,slotid_t);
-extern nasid_t	get_actual_nasid(lboard_t *brd) ;
-extern net_vec_t klcfg_discover_route(lboard_t *, lboard_t *, int);
-#else	/* CONFIG_SGI_IO */
 extern klcpu_t *sn_get_cpuinfo(cpuid_t cpu);
-#endif	/* CONFIG_SGI_IO */
 
 #endif /* _ASM_SN_KLCONFIG_H */
diff --git a/include/asm-mips/sn/kldir.h b/include/asm-mips/sn/kldir.h
index f0efab1..0573cbf 100644
--- a/include/asm-mips/sn/kldir.h
+++ b/include/asm-mips/sn/kldir.h
@@ -11,11 +11,6 @@
 #ifndef _ASM_SN_KLDIR_H
 #define _ASM_SN_KLDIR_H
 
-#include <linux/config.h>
-
-#if defined(CONFIG_SGI_IO)
-#include <asm/hack.h>
-#endif
 
 /*
  * The kldir memory area resides at a fixed place in each node's memory and
@@ -136,8 +131,6 @@
 #define KLDIR_OFF_STRIDE		0x28
 #endif /* __ASSEMBLY__ */
 
-#if !defined(CONFIG_SGI_IO)
-
 /*
  * This is defined here because IP27_SYMMON_STK_SIZE must be at least what
  * we define here.  Since it's set up in the prom.  We can't redefine it later
@@ -147,7 +140,7 @@
  */
 #define SYMMON_STACK_SIZE		0x8000
 
-#if defined (PROM) || defined (SABLE)
+#if defined (PROM)
 
 /*
  * These defines are prom version dependent.  No code other than the IP27
@@ -184,7 +177,7 @@
 #define IP27_FREEMEM_COUNT		1
 #define IP27_FREEMEM_STRIDE		0
 
-#endif /* PROM || SABLE*/
+#endif /* PROM */
 /*
  * There will be only one of these in a partition so the IO6 must set it up.
  */
@@ -207,17 +200,11 @@
 #define KLDIR_ENT_SIZE			0x40
 #define KLDIR_MAX_ENTRIES		(0x400 / 0x40)
 
-#endif	/* !CONFIG_SGI_IO */
-
 #ifndef __ASSEMBLY__
 typedef struct kldir_ent_s {
 	u64		magic;		/* Indicates validity of entry      */
 	off_t		offset;		/* Offset from start of node space  */
-#if defined(CONFIG_SGI_IO)	/* FIXME */
-	__psunsigned_t	pointer;	/* Pointer to area in some cases    */
-#else
 	unsigned long	pointer;	/* Pointer to area in some cases    */
-#endif
 	size_t		size;		/* Size in bytes 		    */
 	u64		count;		/* Repeat count if array, 1 if not  */
 	size_t		stride;		/* Stride if array, 0 if not        */
@@ -227,22 +214,4 @@
 } kldir_ent_t;
 #endif /* !__ASSEMBLY__ */
 
-#if defined(CONFIG_SGI_IO)
-
-#define KLDIR_ENT_SIZE			0x40
-#define KLDIR_MAX_ENTRIES		(0x400 / 0x40)
-
-/*
- * The actual offsets of each memory area are machine-dependent
- */
-#ifdef CONFIG_SGI_IP27
-// Not yet #include <asm/sn/sn0/kldir.h>
-#elif defined(CONFIG_SGI_IP35)
-#include <asm/sn/sn1/kldir.h>
-#else
-#error "kldir.h is currently defined for IP27 and IP35 platforms only"
-#endif
-
-#endif	/* CONFIG_SGI_IO */
-
 #endif /* _ASM_SN_KLDIR_H */
diff --git a/include/asm-mips/sn/launch.h b/include/asm-mips/sn/launch.h
index b67699c..b7c2226 100644
--- a/include/asm-mips/sn/launch.h
+++ b/include/asm-mips/sn/launch.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_SN_LAUNCH_H
 #define _ASM_SN_LAUNCH_H
 
-#include <linux/config.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
 
diff --git a/include/asm-mips/sn/mapped_kernel.h b/include/asm-mips/sn/mapped_kernel.h
index 59edb20..c3dd5d0 100644
--- a/include/asm-mips/sn/mapped_kernel.h
+++ b/include/asm-mips/sn/mapped_kernel.h
@@ -20,7 +20,6 @@
  * code. So no jumps can be done before we have switched to using
  * cksseg addresses.
  */
-#include <linux/config.h>
 #include <asm/addrspace.h>
 
 #define REP_BASE	CAC_BASE
diff --git a/include/asm-mips/sn/sn0/addrs.h b/include/asm-mips/sn/sn0/addrs.h
index 3988156..9e8cc52 100644
--- a/include/asm-mips/sn/sn0/addrs.h
+++ b/include/asm-mips/sn/sn0/addrs.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_SN_SN0_ADDRS_H
 #define _ASM_SN_SN0_ADDRS_H
 
-#include <linux/config.h>
 
 /*
  * SN0 (on a T5) Address map
@@ -49,7 +48,7 @@
  * so for now we just use defines bracketed by an ifdef.
  */
 
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
 
 #define NODE_SIZE_BITS		31
 #define BWIN_SIZE_BITS		28
@@ -63,7 +62,7 @@
 #define BDDIR_UPPER_MASK	(UINT64_CAST 0x7ffff << 10)
 #define BDECC_UPPER_MASK	(UINT64_CAST 0x3ffffff << 3)
 
-#else /* !defined(CONFIG_SGI_SN0_N_MODE), assume that M-mode is desired */
+#else /* !defined(CONFIG_SGI_SN_N_MODE), assume that M-mode is desired */
 
 #define NODE_SIZE_BITS		32
 #define BWIN_SIZE_BITS		29
@@ -77,7 +76,7 @@
 #define BDDIR_UPPER_MASK	(UINT64_CAST 0xfffff << 10)
 #define BDECC_UPPER_MASK	(UINT64_CAST 0x7ffffff << 3)
 
-#endif /* !defined(CONFIG_SGI_SN0_N_MODE) */
+#endif /* !defined(CONFIG_SGI_SN_N_MODE) */
 
 #define NODE_ADDRSPACE_SIZE	(UINT64_CAST 1 << NODE_SIZE_BITS)
 
@@ -85,15 +84,15 @@
 #define NASID_GET(_pa)		(int) ((UINT64_CAST (_pa) >>		\
 					NASID_SHFT) & NASID_BITMASK)
 
-#if !defined(__ASSEMBLY__) && !defined(_STANDALONE)
+#if !defined(__ASSEMBLY__)
 
 #define NODE_SWIN_BASE(nasid, widget)					\
 	((widget == 0) ? NODE_BWIN_BASE((nasid), SWIN0_BIGWIN)		\
 	: RAW_NODE_SWIN_BASE(nasid, widget))
-#else /* __ASSEMBLY__ || _STANDALONE */
+#else /* __ASSEMBLY__ */
 #define NODE_SWIN_BASE(nasid, widget) \
      (NODE_IO_BASE(nasid) + (UINT64_CAST (widget) << SWIN_SIZE_BITS))
-#endif /* __ASSEMBLY__ || _STANDALONE */
+#endif /* __ASSEMBLY__ */
 
 /*
  * The following definitions pertain to the IO special address
@@ -143,12 +142,7 @@
 #define SN0_WIDGET_BASE(_nasid, _wid)	(NODE_SWIN_BASE((_nasid), (_wid)))
 
 /* Turn on sable logging for the processors whose bits are set. */
-#ifdef SABLE
-#define SABLE_LOG_TRIGGER(_map)	\
-		*((volatile hubreg_t *)(IO_BASE + 0x17ffff0)) = (_map)
-#else
 #define SABLE_LOG_TRIGGER(_map)
-#endif /* SABLE */
 
 #ifndef __ASSEMBLY__
 #define KERN_NMI_ADDR(nasid, slice)					\
@@ -281,76 +275,6 @@
 
 #define _ARCSPROM
 
-#ifdef _STANDALONE
-
-/*
- * The PROM needs to pass the device base address and the
- * device pci cfg space address to the device drivers during
- * install. The COMPONENT->Key field is used for this purpose.
- * Macros needed by SN0 device drivers to convert the
- * COMPONENT->Key field to the respective base address.
- * Key field looks as follows:
- *
- *  +----------------------------------------------------+
- *  |devnasid | widget  |pciid |hubwidid|hstnasid | adap |
- *  |   2     |   1     |  1   |   1    |    2    |   1  |
- *  +----------------------------------------------------+
- *  |         |         |      |        |         |      |
- *  64        48        40     32       24        8      0
- *
- * These are used by standalone drivers till the io infrastructure
- * is in place.
- */
-
-#ifndef __ASSEMBLY__
-
-#define uchar unsigned char
-
-#define KEY_DEVNASID_SHFT  48
-#define KEY_WIDID_SHFT	   40
-#define KEY_PCIID_SHFT	   32
-#define KEY_HUBWID_SHFT	   24
-#define KEY_HSTNASID_SHFT  8
-
-#define MK_SN0_KEY(nasid, widid, pciid) \
-			((((__psunsigned_t)nasid)<< KEY_DEVNASID_SHFT |\
-				((__psunsigned_t)widid) << KEY_WIDID_SHFT) |\
-				((__psunsigned_t)pciid) << KEY_PCIID_SHFT)
-
-#define ADD_HUBWID_KEY(key,hubwid)\
-			(key|=((__psunsigned_t)hubwid << KEY_HUBWID_SHFT))
-
-#define ADD_HSTNASID_KEY(key,hstnasid)\
-			(key|=((__psunsigned_t)hstnasid << KEY_HSTNASID_SHFT))
-
-#define GET_DEVNASID_FROM_KEY(key)	((short)(key >> KEY_DEVNASID_SHFT))
-#define GET_WIDID_FROM_KEY(key)		((uchar)(key >> KEY_WIDID_SHFT))
-#define GET_PCIID_FROM_KEY(key)		((uchar)(key >> KEY_PCIID_SHFT))
-#define GET_HUBWID_FROM_KEY(key)	((uchar)(key >> KEY_HUBWID_SHFT))
-#define GET_HSTNASID_FROM_KEY(key)	((short)(key >> KEY_HSTNASID_SHFT))
-
-#define PCI_64_TARGID_SHFT		60
-
-#define GET_PCIBASE_FROM_KEY(key)  (NODE_SWIN_BASE(GET_DEVNASID_FROM_KEY(key),\
-					GET_WIDID_FROM_KEY(key))\
-					| BRIDGE_DEVIO(GET_PCIID_FROM_KEY(key)))
-
-#define GET_PCICFGBASE_FROM_KEY(key) \
-			(NODE_SWIN_BASE(GET_DEVNASID_FROM_KEY(key),\
-			      GET_WIDID_FROM_KEY(key))\
-			| BRIDGE_TYPE0_CFG_DEV(GET_PCIID_FROM_KEY(key)))
-
-#define GET_WIDBASE_FROM_KEY(key) \
-                        (NODE_SWIN_BASE(GET_DEVNASID_FROM_KEY(key),\
-                              GET_WIDID_FROM_KEY(key)))
-
-#define PUT_INSTALL_STATUS(c,s)		c->Revision = s
-#define GET_INSTALL_STATUS(c)		c->Revision
-
-#endif /* !__ASSEMBLY__ */
-
-#endif /* _STANDALONE */
-
 #if defined (HUB_ERR_STS_WAR)
 
 #define ERR_STS_WAR_REGISTER	IIO_IIBUSERR
diff --git a/include/asm-mips/sn/sn0/arch.h b/include/asm-mips/sn/sn0/arch.h
index fb78773..f734f20 100644
--- a/include/asm-mips/sn/sn0/arch.h
+++ b/include/asm-mips/sn/sn0/arch.h
@@ -11,9 +11,6 @@
 #ifndef _ASM_SN_SN0_ARCH_H
 #define _ASM_SN_SN0_ARCH_H
 
-#include <linux/config.h>
-
-#ifndef SABLE
 
 #ifndef SN0XXL  /* 128 cpu SMP max */
 /*
@@ -54,25 +51,16 @@
  */
 #define MAX_PARTITIONS		MAX_REGIONS
 
-
-#else
-
-#define MAX_COMPACT_NODES	4
-#define MAX_NASIDS		4
-#define MAXCPUS			8
-
-#endif
-
 #define NASID_MASK_BYTES	((MAX_NASIDS + 7) / 8)
 
 /*
  * Slot constants for SN0
  */
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
 #define MAX_MEM_SLOTS   16                      /* max slots per node */
-#else /* !CONFIG_SGI_SN0_N_MODE, assume M_MODE */
+#else /* !CONFIG_SGI_SN_N_MODE, assume CONFIG_SGI_SN_M_MODE */
 #define MAX_MEM_SLOTS   32                      /* max slots per node */
-#endif /* defined(N_MODE) */
+#endif /* CONFIG_SGI_SN_M_MODE */
 
 #define SLOT_SHIFT      	(27)
 #define SLOT_MIN_MEM_SIZE	(32*1024*1024)
diff --git a/include/asm-mips/sn/sn0/hub.h b/include/asm-mips/sn/sn0/hub.h
index f5dbba6..3e228f8 100644
--- a/include/asm-mips/sn/sn0/hub.h
+++ b/include/asm-mips/sn/sn0/hub.h
@@ -31,10 +31,6 @@
 #include <asm/sn/sn0/hubni.h>
 //#include <asm/sn/sn0/hubcore.h>
 
-#ifdef SABLE
-#define IP27_NO_HUBUART_INT	1
-#endif
-
 /* Translation of uncached attributes */
 #define	UATTR_HSPEC	0
 #define	UATTR_IO	1
diff --git a/include/asm-mips/sn/sn0/hubio.h b/include/asm-mips/sn/sn0/hubio.h
index f314da2..ef91b33 100644
--- a/include/asm-mips/sn/sn0/hubio.h
+++ b/include/asm-mips/sn/sn0/hubio.h
@@ -486,22 +486,6 @@
 #define ICRBN_A_CERR_SHFT	54
 #define ICRBN_A_ERR_MASK	0x3ff
 
-#if 0	/* Disabled, this causes namespace polution and break allmodconfig */
-/*
- * Easy access macros.
- */
-#define	a_error		icrba_fields_s.error
-#define	a_ecode		icrba_fields_s.ecode
-#define	a_lnetuce	icrba_fields_s.lnetuce
-#define	a_mark		icrba_fields_s.mark
-#define	a_xerr		icrba_fields_s.xerr
-#define	a_sidn		icrba_fields_s.sidn
-#define	a_tnum		icrba_fields_s.tnum
-#define	a_addr		icrba_fields_s.addr
-#define	a_valid		icrba_fields_s.valid
-#define	a_iow		icrba_fields_s.iow
-#endif
-
 #endif /* !__ASSEMBLY__ */
 
 #define	IIO_ICRB_ADDR_SHFT	2	/* Shift to get proper address */
diff --git a/include/asm-mips/sn/sn0/hubmd.h b/include/asm-mips/sn/sn0/hubmd.h
index a66def4..14c225d 100644
--- a/include/asm-mips/sn/sn0/hubmd.h
+++ b/include/asm-mips/sn/sn0/hubmd.h
@@ -11,7 +11,6 @@
 #ifndef	_ASM_SN_SN0_HUBMD_H
 #define	_ASM_SN_SN0_HUBMD_H
 
-#include <linux/config.h>
 
 /*
  * Hub Memory/Directory interface registers
@@ -92,7 +91,7 @@
 #define MD_UREG1_14		0x2200f0 /* uController/UART 1 register     */
 #define MD_UREG1_15		0x2200f8 /* uController/UART 1 register     */
 
-#ifdef CONFIG_SGI_SN0_N_MODE
+#ifdef CONFIG_SGI_SN_N_MODE
 #define MD_MEM_BANKS		4	 /* 4 banks of memory max in N mode */
 #else
 #define MD_MEM_BANKS		8	 /* 8 banks of memory max in M mode */
diff --git a/include/asm-mips/sn/sn0/hubpi.h b/include/asm-mips/sn/sn0/hubpi.h
index 355bba8..e39f5f9 100644
--- a/include/asm-mips/sn/sn0/hubpi.h
+++ b/include/asm-mips/sn/sn0/hubpi.h
@@ -398,24 +398,6 @@
 
 /* PI_RT_FILTER_CTRL mask and shift definitions */
 
-#if 0
-/*
- * XXX - This register's definition has changed, but it's only implemented
- * in Hub 2.
- */
-#define PRFC_DROP_COUNT_SHFT	27
-#define PRFC_DROP_COUNT_MASK	(UINT64_CAST 0x3ff << 27)
-#define PRFC_DROP_CTR_SHFT	18
-#define PRFC_DROP_CTR_MASK	(UINT64_CAST 0x1ff << 18)
-#define PRFC_MASK_ENABLE_SHFT	10
-#define PRFC_MASK_ENABLE_MASK	(UINT64_CAST 0x7f << 10)
-#define PRFC_MASK_CTR_SHFT	2
-#define PRFC_MASK_CTR_MASK	(UINT64_CAST 0xff << 2)
-#define PRFC_OFFSET_SHFT	0
-#define PRFC_OFFSET_MASK	(UINT64_CAST 3)
-#endif /* 0 */
-
-
 /*
  * Bits for NACK_CNT_A/B and NACK_CMP
  */
diff --git a/include/asm-mips/sn/sn0/ip27.h b/include/asm-mips/sn/sn0/ip27.h
index ade0e97..3c97e08 100644
--- a/include/asm-mips/sn/sn0/ip27.h
+++ b/include/asm-mips/sn/sn0/ip27.h
@@ -6,7 +6,7 @@
  * Derived from IRIX <sys/SN/SN0/IP27.h>.
  *
  * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc.
- * Copyright (C) 1999 by Ralf Baechle
+ * Copyright (C) 1999, 2006 by Ralf Baechle
  */
 #ifndef _ASM_SN_SN0_IP27_H
 #define _ASM_SN_SN0_IP27_H
@@ -82,11 +82,4 @@
 #define SEND_NMI(_nasid, _slice)	\
           REMOTE_HUB_S((_nasid),  (PI_NMI_A + ((_slice) * PI_NMI_OFFSET)), 1)
 
-/* Sanity hazzard ...  Below all the Origin hacks are following.  */
-
-#define SN00_BRIDGE		0x9200000008000000
-#define SN00I_BRIDGE0		0x920000000b000000
-#define SN00I_BRIDGE1		0x920000000e000000
-#define SN00I_BRIDGE2		0x920000000f000000
-
 #endif /* _ASM_SN_SN0_IP27_H */
diff --git a/include/asm-mips/sn/sn0/sn0_fru.h b/include/asm-mips/sn/sn0/sn0_fru.h
deleted file mode 100644
index 82c6377..0000000
--- a/include/asm-mips/sn/sn0/sn0_fru.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Derived from IRIX <sys/SN/SN0/sn0_fru.h>
- *
- * Copyright (C) 1992 - 1997, 1999 Silcon Graphics, Inc.
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
- */
-#ifndef _ASM_SN_SN0_SN0_FRU_H
-#define _ASM_SN_SN0_SN0_FRU_H
-
-#define MAX_DIMMS			8	 /* max # of dimm banks */
-#define MAX_PCIDEV			8	 /* max # of pci devices on a pci bus */
-
-typedef unsigned char confidence_t;
-
-typedef struct kf_mem_s {
-	confidence_t km_confidence; /* confidence level that the memory is bad
-				     * is this necessary ?
-				     */
-	confidence_t km_dimm[MAX_DIMMS];
-	                            /* confidence level that dimm[i] is bad
-				     *I think this is the right number
-				     */
-
-} kf_mem_t;
-
-typedef struct kf_cpu_s {
-	confidence_t  	kc_confidence; /* confidence level that cpu is bad */
-	confidence_t  	kc_icache; /* confidence level that instr. cache is bad */
-	confidence_t  	kc_dcache; /* confidence level that data   cache is bad */
-	confidence_t  	kc_scache; /* confidence level that sec.   cache is bad */
-	confidence_t	kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */
-} kf_cpu_t;
-
-typedef struct kf_pci_bus_s {
-	confidence_t	kpb_belief;	/* confidence level  that the  pci bus is bad */
-	confidence_t	kpb_pcidev_belief[MAX_PCIDEV];
-	                                /* confidence level that the pci dev is bad */
-} kf_pci_bus_t;
-
-#endif /* _ASM_SN_SN0_SN0_FRU_H */
diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
index b3bc698..b9ba54d 100644
--- a/include/asm-mips/sni.h
+++ b/include/asm-mips/sni.h
@@ -15,9 +15,6 @@
 /*
  * ASIC PCI registers for little endian configuration.
  */
-#ifndef __MIPSEL__
-#error "Fix me for big endian"
-#endif
 #define PCIMT_UCONF		0xbfff0000
 #define PCIMT_IOADTIMEOUT2	0xbfff0008
 #define PCIMT_IOMEMCONF		0xbfff0010
@@ -51,9 +48,9 @@
 #define PCIMT_PCI_CONF		0xbfff0100
 
 /*
- * Data port for the PCI bus.
+ * Data port for the PCI bus in IO space
  */
-#define PCIMT_CONFIG_DATA	0xb4000cfc
+#define PCIMT_CONFIG_DATA	0x0cfc
 
 /*
  * Board specific registers
diff --git a/include/asm-mips/stackframe.h b/include/asm-mips/stackframe.h
index c4856a8..513aa51 100644
--- a/include/asm-mips/stackframe.h
+++ b/include/asm-mips/stackframe.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_STACKFRAME_H
 #define _ASM_STACKFRAME_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 
 #include <asm/asm.h>
diff --git a/include/asm-mips/string.h b/include/asm-mips/string.h
index 907da60..436e3ad 100644
--- a/include/asm-mips/string.h
+++ b/include/asm-mips/string.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_STRING_H
 #define _ASM_STRING_H
 
-#include <linux/config.h>
 
 /*
  * Most of the inline functions are rather naive implementations so I just
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 261f71d..130333d 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -12,7 +12,6 @@
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index f8d97da..ae8ada5 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -9,7 +9,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-mips/tlbflush.h b/include/asm-mips/tlbflush.h
index bb4ae3c..276be77 100644
--- a/include/asm-mips/tlbflush.h
+++ b/include/asm-mips/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_TLBFLUSH_H
 #define __ASM_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
 /*
diff --git a/include/asm-mips/tx4927/toshiba_rbtx4927.h b/include/asm-mips/tx4927/toshiba_rbtx4927.h
index 6ce1e94..94bef03 100644
--- a/include/asm-mips/tx4927/toshiba_rbtx4927.h
+++ b/include/asm-mips/tx4927/toshiba_rbtx4927.h
@@ -27,7 +27,6 @@
 #ifndef __ASM_TX4927_TOSHIBA_RBTX4927_H
 #define __ASM_TX4927_TOSHIBA_RBTX4927_H
 
-#include <linux/config.h>
 #include <asm/tx4927/tx4927.h>
 #include <asm/tx4927/tx4927_mips.h>
 #ifdef CONFIG_PCI
diff --git a/include/asm-mips/types.h b/include/asm-mips/types.h
index cd2813d8..2b52e18 100644
--- a/include/asm-mips/types.h
+++ b/include/asm-mips/types.h
@@ -52,7 +52,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef __signed char s8;
 typedef unsigned char u8;
diff --git a/include/asm-mips/uaccess.h b/include/asm-mips/uaccess.h
index b96f3e0..1cdd4ee 100644
--- a/include/asm-mips/uaccess.h
+++ b/include/asm-mips/uaccess.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/thread_info.h>
diff --git a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
index 1068fe9..8bb0bb9 100644
--- a/include/asm-mips/unistd.h
+++ b/include/asm-mips/unistd.h
@@ -905,6 +905,8 @@
 #define __NR_N32_Linux			6000
 #define __NR_N32_Linux_syscalls		268
 
+#ifdef __KERNEL__
+
 #ifndef __ASSEMBLY__
 
 /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
@@ -1168,9 +1170,6 @@
 
 #endif /* (_MIPS_SIM == _MIPS_SIM_NABI32) || (_MIPS_SIM == _MIPS_SIM_ABI64) */
 
-#ifdef __KERNEL__
-
-#include <linux/config.h>
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
@@ -1197,7 +1196,6 @@
 # ifdef CONFIG_MIPS32_O32
 #  define __ARCH_WANT_COMPAT_SYS_TIME
 # endif
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -1248,4 +1246,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_UNISTD_H */
diff --git a/include/asm-mips/vga.h b/include/asm-mips/vga.h
index 34755c0..c1dd0b1 100644
--- a/include/asm-mips/vga.h
+++ b/include/asm-mips/vga.h
@@ -13,7 +13,7 @@
  *	access the videoram directly without any black magic.
  */
 
-#define VGA_MAP_MEM(x)	(0xb0000000L + (unsigned long)(x))
+#define VGA_MAP_MEM(x,s)	(0xb0000000L + (unsigned long)(x))
 
 #define vga_readb(x)	(*(x))
 #define vga_writeb(x,y)	(*(y) = (x))
diff --git a/include/asm-mips/vr41xx/vrc4173.h b/include/asm-mips/vr41xx/vrc4173.h
index 4d41a9c..96fdcd5 100644
--- a/include/asm-mips/vr41xx/vrc4173.h
+++ b/include/asm-mips/vr41xx/vrc4173.h
@@ -24,7 +24,6 @@
 #ifndef __NEC_VRC4173_H
 #define __NEC_VRC4173_H
 
-#include <linux/config.h>
 #include <asm/io.h>
 
 /*
diff --git a/include/asm-mips/war.h b/include/asm-mips/war.h
index ad374bd..3ac146c 100644
--- a/include/asm-mips/war.h
+++ b/include/asm-mips/war.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_WAR_H
 #define _ASM_WAR_H
 
-#include <linux/config.h>
 
 /*
  * Another R4600 erratum.  Due to the lack of errata information the exact
@@ -172,7 +171,8 @@
  * On the RM9000 there is a problem which makes the CreateDirtyExclusive
  * cache operation unusable on SMP systems.
  */
-#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE)
+#if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_PMC_YOSEMITE) || \
+    defined(CONFIG_BASLER_EXCITE)
 #define  RM9000_CDEX_SMP_WAR		1
 #endif
 
@@ -182,7 +182,7 @@
  * being fetched may case spurious exceptions.
  */
 #if defined(CONFIG_MOMENCO_JAGUAR_ATX) || defined(CONFIG_MOMENCO_OCELOT_3) || \
-    defined(CONFIG_PMC_YOSEMITE)
+    defined(CONFIG_PMC_YOSEMITE) || defined(CONFIG_BASLER_EXCITE)
 #define ICACHE_REFILLS_WORKAROUND_WAR	1
 #endif
 
diff --git a/include/asm-mips/wbflush.h b/include/asm-mips/wbflush.h
index c3bef50..eadc0ac 100644
--- a/include/asm-mips/wbflush.h
+++ b/include/asm-mips/wbflush.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_WBFLUSH_H
 #define _ASM_WBFLUSH_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_CPU_HAS_WB
 
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h
index 403ea97..48bf9b8 100644
--- a/include/asm-parisc/atomic.h
+++ b/include/asm-parisc/atomic.h
@@ -5,7 +5,6 @@
 #ifndef _ASM_PARISC_ATOMIC_H_
 #define _ASM_PARISC_ATOMIC_H_
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/system.h>
 
diff --git a/include/asm-parisc/cache.h b/include/asm-parisc/cache.h
index c831665..7d22fa2 100644
--- a/include/asm-parisc/cache.h
+++ b/include/asm-parisc/cache.h
@@ -5,7 +5,6 @@
 #ifndef __ARCH_PARISC_CACHE_H
 #define __ARCH_PARISC_CACHE_H
 
-#include <linux/config.h>
 
 /*
  * PA 2.0 processors have 64-byte cachelines; PA 1.1 processors have
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 76b6b7d6..0b459cd 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -1,7 +1,6 @@
 #ifndef _PARISC_CACHEFLUSH_H
 #define _PARISC_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/cache.h>	/* for flush_user_dcache_range_asm() proto */
 
diff --git a/include/asm-parisc/dma-mapping.h b/include/asm-parisc/dma-mapping.h
index 74d4ac6..1e387e1 100644
--- a/include/asm-parisc/dma-mapping.h
+++ b/include/asm-parisc/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef _PARISC_DMA_MAPPING_H
 #define _PARISC_DMA_MAPPING_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/cacheflush.h>
 #include <asm/scatterlist.h>
diff --git a/include/asm-parisc/dma.h b/include/asm-parisc/dma.h
index 31fd10d..9979c3c 100644
--- a/include/asm-parisc/dma.h
+++ b/include/asm-parisc/dma.h
@@ -9,7 +9,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <asm/io.h>		/* need byte IO */
 #include <asm/system.h>	
 
diff --git a/include/asm-parisc/floppy.h b/include/asm-parisc/floppy.h
index ca3aed7..458cdb2 100644
--- a/include/asm-parisc/floppy.h
+++ b/include/asm-parisc/floppy.h
@@ -159,10 +159,8 @@
 		return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
 						   "floppy", NULL);
 	else
-		return request_irq(FLOPPY_IRQ, floppy_interrupt,
-						   SA_INTERRUPT|SA_SAMPLE_RANDOM,
-						   "floppy", NULL);	
-
+		return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT,
+				   "floppy", NULL);
 }
 
 static unsigned long dma_mem_alloc(unsigned long size)
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index 244f6b8..b9eb245 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/pgtable.h>
 
diff --git a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
index b0a30e2..377ba90 100644
--- a/include/asm-parisc/irq.h
+++ b/include/asm-parisc/irq.h
@@ -7,7 +7,6 @@
 #ifndef _ASM_PARISC_IRQ_H
 #define _ASM_PARISC_IRQ_H
 
-#include <linux/config.h>
 #include <linux/cpumask.h>
 #include <asm/types.h>
 
diff --git a/include/asm-parisc/kmap_types.h b/include/asm-parisc/kmap_types.h
index 6886a0c..806aae3 100644
--- a/include/asm-parisc/kmap_types.h
+++ b/include/asm-parisc/kmap_types.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_KMAP_TYPES_H
 #define _ASM_KMAP_TYPES_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h
index ceb9b73..c878136 100644
--- a/include/asm-parisc/mmzone.h
+++ b/include/asm-parisc/mmzone.h
@@ -14,11 +14,6 @@
 
 #define NODE_DATA(nid)          (&node_data[nid].pg_data)
 
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define kvaddr_to_nid(kaddr)	pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
-
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)						\
 ({									\
diff --git a/include/asm-parisc/page.h b/include/asm-parisc/page.h
index c0dd461..0695bc9 100644
--- a/include/asm-parisc/page.h
+++ b/include/asm-parisc/page.h
@@ -10,7 +10,6 @@
 
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 
 #if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
 # define PAGE_SHIFT	12	/* 4k */
diff --git a/include/asm-parisc/param.h b/include/asm-parisc/param.h
index f4694d4..07cb9b93 100644
--- a/include/asm-parisc/param.h
+++ b/include/asm-parisc/param.h
@@ -2,7 +2,6 @@
 #define _ASMPARISC_PARAM_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 # ifdef CONFIG_PA20
 #  define HZ		1000		/* Faster machines */
 # else
diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
index 77bbafb..8b631f4 100644
--- a/include/asm-parisc/pci.h
+++ b/include/asm-parisc/pci.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_PARISC_PCI_H
 #define __ASM_PARISC_PCI_H
 
-#include <linux/config.h>
 #include <asm/scatterlist.h>
 
 
diff --git a/include/asm-parisc/pdc.h b/include/asm-parisc/pdc.h
index 0a3face..08364f9 100644
--- a/include/asm-parisc/pdc.h
+++ b/include/asm-parisc/pdc.h
@@ -1,7 +1,6 @@
 #ifndef _PARISC_PDC_H
 #define _PARISC_PDC_H
 
-#include <linux/config.h>
 
 /*
  *	PDC return values ...
diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
index aec089e..b6bcc67 100644
--- a/include/asm-parisc/pgtable.h
+++ b/include/asm-parisc/pgtable.h
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/fixmap.h>
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
index 89f2f1c..ca49dc9 100644
--- a/include/asm-parisc/processor.h
+++ b/include/asm-parisc/processor.h
@@ -9,7 +9,6 @@
 #define __ASM_PARISC_PROCESSOR_H
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/spinlock_types.h>
 
diff --git a/include/asm-parisc/psw.h b/include/asm-parisc/psw.h
index 4334d6c..5a3e23c 100644
--- a/include/asm-parisc/psw.h
+++ b/include/asm-parisc/psw.h
@@ -1,6 +1,5 @@
 #ifndef _PARISC_PSW_H
 
-#include <linux/config.h>
 
 #define	PSW_I	0x00000001
 #define	PSW_D	0x00000002
diff --git a/include/asm-parisc/smp.h b/include/asm-parisc/smp.h
index dbdbd2e..d4c0e26 100644
--- a/include/asm-parisc/smp.h
+++ b/include/asm-parisc/smp.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_SMP)
 
diff --git a/include/asm-parisc/system.h b/include/asm-parisc/system.h
index a5a973c..8638761 100644
--- a/include/asm-parisc/system.h
+++ b/include/asm-parisc/system.h
@@ -1,7 +1,6 @@
 #ifndef __PARISC_SYSTEM_H
 #define __PARISC_SYSTEM_H
 
-#include <linux/config.h>
 #include <asm/psw.h>
 
 /* The program status word as bitfields.  */
diff --git a/include/asm-parisc/tlbflush.h b/include/asm-parisc/tlbflush.h
index 825994a..f662e83 100644
--- a/include/asm-parisc/tlbflush.h
+++ b/include/asm-parisc/tlbflush.h
@@ -3,7 +3,6 @@
 
 /* TLB flushing routines.... */
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 
diff --git a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
index 0e1a30b..12b8672 100644
--- a/include/asm-parisc/unistd.h
+++ b/include/asm-parisc/unistd.h
@@ -792,6 +792,7 @@
 #define HPUX_GATEWAY_ADDR       0xC0000004
 #define LINUX_GATEWAY_ADDR      0x100
 
+#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #define SYS_ify(syscall_name)   __NR_##syscall_name
@@ -934,7 +935,6 @@
     return K_INLINE_SYSCALL(name, 5, arg1, arg2, arg3, arg4, arg5);	\
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_ALARM
@@ -956,7 +956,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 /* mmap & mmap2 take 6 arguments */
 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5,type6,arg6) \
@@ -1056,4 +1055,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_PARISC_UNISTD_H_ */
diff --git a/include/asm-powerpc/abs_addr.h b/include/asm-powerpc/abs_addr.h
index c5c3259..4aa2207 100644
--- a/include/asm-powerpc/abs_addr.h
+++ b/include/asm-powerpc/abs_addr.h
@@ -2,7 +2,6 @@
 #define _ASM_POWERPC_ABS_ADDR_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * c 2001 PPC 64 Team, IBM Corp
diff --git a/include/asm-powerpc/backlight.h b/include/asm-powerpc/backlight.h
index 1ba1f27..a5e9e65 100644
--- a/include/asm-powerpc/backlight.h
+++ b/include/asm-powerpc/backlight.h
@@ -2,30 +2,30 @@
  * Routines for handling backlight control on PowerBooks
  *
  * For now, implementation resides in
- * arch/powerpc/platforms/powermac/pmac_support.c
+ * arch/powerpc/platforms/powermac/backlight.c
  *
  */
 #ifndef __ASM_POWERPC_BACKLIGHT_H
 #define __ASM_POWERPC_BACKLIGHT_H
 #ifdef __KERNEL__
 
-/* Abstract values */
-#define BACKLIGHT_OFF	0
-#define BACKLIGHT_MIN	1
-#define BACKLIGHT_MAX	0xf
+#include <linux/fb.h>
+#include <linux/mutex.h>
 
-struct backlight_controller {
-	int (*set_enable)(int enable, int level, void *data);
-	int (*set_level)(int level, void *data);
-};
+/* For locking instructions, see the implementation file */
+extern struct backlight_device *pmac_backlight;
+extern struct mutex pmac_backlight_mutex;
 
-extern void register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type);
-extern void unregister_backlight_controller(struct backlight_controller *ctrler, void *data);
+extern void pmac_backlight_calc_curve(struct fb_info*);
+extern int pmac_backlight_curve_lookup(struct fb_info *info, int value);
 
-extern int set_backlight_enable(int enable);
-extern int get_backlight_enable(void);
-extern int set_backlight_level(int level);
-extern int get_backlight_level(void);
+extern int pmac_has_backlight_type(const char *type);
+
+extern void pmac_backlight_key_up(void);
+extern void pmac_backlight_key_down(void);
+
+extern int pmac_backlight_set_legacy_brightness(int brightness);
+extern int pmac_backlight_get_legacy_brightness(void);
 
 #endif /* __KERNEL__ */
 #endif
diff --git a/include/asm-powerpc/bitops.h b/include/asm-powerpc/bitops.h
index d1c2a44..76e2f08 100644
--- a/include/asm-powerpc/bitops.h
+++ b/include/asm-powerpc/bitops.h
@@ -288,8 +288,8 @@
 #define __test_and_clear_le_bit(nr, addr) \
 	__test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
 
-#define find_first_zero_le_bit(addr, size) find_next_zero_le_bit((addr), (size), 0)
-unsigned long find_next_zero_le_bit(const unsigned long *addr,
+#define find_first_zero_le_bit(addr, size) generic_find_next_zero_le_bit((addr), (size), 0)
+unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
 				    unsigned long size, unsigned long offset);
 
 /* Bitmap functions for the ext2 filesystem */
@@ -309,7 +309,7 @@
 #define ext2_find_first_zero_bit(addr, size) \
 	find_first_zero_le_bit((unsigned long*)addr, size)
 #define ext2_find_next_zero_bit(addr, size, off) \
-	find_next_zero_le_bit((unsigned long*)addr, size, off)
+	generic_find_next_zero_le_bit((unsigned long*)addr, size, off)
 
 /* Bitmap functions for the minix filesystem.  */
 
diff --git a/include/asm-powerpc/cache.h b/include/asm-powerpc/cache.h
index 6379c2d..642be62 100644
--- a/include/asm-powerpc/cache.h
+++ b/include/asm-powerpc/cache.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /* bytes per L1 cache line */
 #if defined(CONFIG_8xx) || defined(CONFIG_403GCX)
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index f6265c2..fab41c2 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -24,6 +24,9 @@
 #define PPC_FEATURE_ICACHE_SNOOP	0x00002000
 #define PPC_FEATURE_ARCH_2_05		0x00001000
 
+#define PPC_FEATURE_TRUE_LE		0x00000002
+#define PPC_FEATURE_PPC_LE		0x00000001
+
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
@@ -69,6 +72,13 @@
 	/* Processor specific oprofile operations */
 	enum powerpc_oprofile_type oprofile_type;
 
+	/* Bit locations inside the mmcra change */
+	unsigned long	oprofile_mmcra_sihv;
+	unsigned long	oprofile_mmcra_sipr;
+
+	/* Bits to clear during an oprofile exception */
+	unsigned long	oprofile_mmcra_clear;
+
 	/* Name of processor class, for the ELF AT_PLATFORM entry */
 	char		*platform;
 };
@@ -104,6 +114,8 @@
 #define CPU_FTR_NO_BTIC			ASM_CONST(0x0000000000040000)
 #define CPU_FTR_BIG_PHYS		ASM_CONST(0x0000000000080000)
 #define CPU_FTR_NODSISRALIGN		ASM_CONST(0x0000000000100000)
+#define CPU_FTR_PPC_LE			ASM_CONST(0x0000000000200000)
+#define CPU_FTR_REAL_LE			ASM_CONST(0x0000000000400000)
 
 #ifdef __powerpc64__
 /* Add the 64b processor unique features in the top half of the word */
@@ -117,7 +129,6 @@
 #define CPU_FTR_SMT			ASM_CONST(0x0000010000000000)
 #define CPU_FTR_COHERENT_ICACHE		ASM_CONST(0x0000020000000000)
 #define CPU_FTR_LOCKLESS_TLBIE		ASM_CONST(0x0000040000000000)
-#define CPU_FTR_MMCRA_SIHV		ASM_CONST(0x0000080000000000)
 #define CPU_FTR_CI_LARGE_PAGE		ASM_CONST(0x0000100000000000)
 #define CPU_FTR_PAUSE_ZERO		ASM_CONST(0x0000200000000000)
 #define CPU_FTR_PURR			ASM_CONST(0x0000400000000000)
@@ -134,7 +145,6 @@
 #define CPU_FTR_SMT			ASM_CONST(0x0)
 #define CPU_FTR_COHERENT_ICACHE		ASM_CONST(0x0)
 #define CPU_FTR_LOCKLESS_TLBIE		ASM_CONST(0x0)
-#define CPU_FTR_MMCRA_SIHV		ASM_CONST(0x0)
 #define CPU_FTR_CI_LARGE_PAGE		ASM_CONST(0x0)
 #define CPU_FTR_PURR			ASM_CONST(0x0)
 #endif
@@ -192,92 +202,95 @@
 #define CPU_FTRS_PPC601	(CPU_FTR_COMMON | CPU_FTR_601 | CPU_FTR_HPTE_TABLE)
 #define CPU_FTRS_603	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
-	    CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_604	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE)
+	    CPU_FTR_USE_TB | CPU_FTR_604_PERF_MON | CPU_FTR_HPTE_TABLE | \
+	    CPU_FTR_PPC_LE)
 #define CPU_FTRS_740_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_740	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_PPC_LE)
 #define CPU_FTRS_750	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
-	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
+	    CPU_FTR_PPC_LE)
 #define CPU_FTRS_750FX1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM)
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
 #define CPU_FTRS_750FX2	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_NO_DPM)
+	    CPU_FTR_NO_DPM | CPU_FTR_PPC_LE)
 #define CPU_FTRS_750FX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
 #define CPU_FTRS_750GX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
 	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP | \
-	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS)
+	    CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7400_NOTAU	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
-	    CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7400	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | \
 	    CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | \
-	    CPU_FTR_MAYBE_CAN_NAP)
+	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7450_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7450_21	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7450_23	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
-	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7455_1	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7455_20	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_L3_DISABLE_NAP | \
-	    CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7455	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7447_10	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_NO_BTIC | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7447	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_L3CR | CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_7447A	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | \
 	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450 | \
 	    CPU_FTR_NAP_DISABLE_L2_PR | CPU_FTR_HAS_HIGH_BATS | \
-	    CPU_FTR_NEED_COHERENT)
+	    CPU_FTR_NEED_COHERENT | CPU_FTR_PPC_LE)
 #define CPU_FTRS_82XX	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB)
 #define CPU_FTRS_G2_LE	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | \
@@ -287,13 +300,6 @@
 	    CPU_FTR_COMMON)
 #define CPU_FTRS_CLASSIC32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
 	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_POWER3_32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE)
-#define CPU_FTRS_POWER4_32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_NODSISRALIGN)
-#define CPU_FTRS_970_32	(CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | \
-	    CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | CPU_FTR_ALTIVEC_COMP | \
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN)
 #define CPU_FTRS_8XX	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB)
 #define CPU_FTRS_40X	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_NODSISRALIGN)
@@ -307,7 +313,7 @@
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 #ifdef __powerpc64__
 #define CPU_FTRS_POWER3	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
-	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR)
+	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | CPU_FTR_PPC_LE)
 #define CPU_FTRS_RS64	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_IABR | \
 	    CPU_FTR_MMCRA | CPU_FTR_CTRL)
@@ -320,12 +326,12 @@
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-	    CPU_FTR_MMCRA_SIHV | CPU_FTR_PURR)
+	    CPU_FTR_PURR)
 #define CPU_FTRS_POWER6 (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_MMCRA | CPU_FTR_SMT | \
 	    CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
-	    CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE)
+	    CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE)
 #define CPU_FTRS_CELL	(CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
 	    CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \
 	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
@@ -354,12 +360,6 @@
 #else
 	    CPU_FTRS_GENERIC_32 |
 #endif
-#ifdef CONFIG_PPC64BRIDGE
-	    CPU_FTRS_POWER3_32 |
-#endif
-#ifdef CONFIG_POWER4
-	    CPU_FTRS_POWER4_32 | CPU_FTRS_970_32 |
-#endif
 #ifdef CONFIG_8xx
 	    CPU_FTRS_8XX |
 #endif
@@ -399,12 +399,6 @@
 #else
 	    CPU_FTRS_GENERIC_32 &
 #endif
-#ifdef CONFIG_PPC64BRIDGE
-	    CPU_FTRS_POWER3_32 &
-#endif
-#ifdef CONFIG_POWER4
-	    CPU_FTRS_POWER4_32 & CPU_FTRS_970_32 &
-#endif
 #ifdef CONFIG_8xx
 	    CPU_FTRS_8XX &
 #endif
diff --git a/include/asm-powerpc/delay.h b/include/asm-powerpc/delay.h
index 057a609..f9200a6 100644
--- a/include/asm-powerpc/delay.h
+++ b/include/asm-powerpc/delay.h
@@ -17,5 +17,18 @@
 extern void __delay(unsigned long loops);
 extern void udelay(unsigned long usecs);
 
+/*
+ * On shared processor machines the generic implementation of mdelay can
+ * result in large errors. While each iteration of the loop inside mdelay
+ * is supposed to take 1ms, the hypervisor could sleep our partition for
+ * longer (eg 10ms). With the right timing these errors can add up.
+ *
+ * Since there is no 32bit overflow issue on 64bit kernels, just call
+ * udelay directly.
+ */
+#ifdef CONFIG_PPC64
+#define mdelay(n)	udelay((n) * 1000)
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_DELAY_H */
diff --git a/include/asm-powerpc/dma-mapping.h b/include/asm-powerpc/dma-mapping.h
index 2ac63f5..2ab9baf 100644
--- a/include/asm-powerpc/dma-mapping.h
+++ b/include/asm-powerpc/dma-mapping.h
@@ -8,7 +8,6 @@
 #define _ASM_DMA_MAPPING_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/cache.h>
 /* need struct page definitions */
diff --git a/include/asm-powerpc/dma.h b/include/asm-powerpc/dma.h
index 4bb57fe..7a4374b 100644
--- a/include/asm-powerpc/dma.h
+++ b/include/asm-powerpc/dma.h
@@ -22,7 +22,6 @@
  * with a grain of salt.
  */
 
-#include <linux/config.h>
 #include <asm/io.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
diff --git a/include/asm-powerpc/eeh.h b/include/asm-powerpc/eeh.h
index 868c713..4df3e80 100644
--- a/include/asm-powerpc/eeh.h
+++ b/include/asm-powerpc/eeh.h
@@ -21,7 +21,6 @@
 #define _PPC64_EEH_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/string.h>
@@ -293,8 +292,6 @@
 static inline u8 eeh_inb(unsigned long port)
 {
 	u8 val;
-	if (!_IO_IS_VALID(port))
-		return ~0;
 	val = in_8((u8 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u8))
 		return eeh_check_failure((void __iomem *)(port), val);
@@ -303,15 +300,12 @@
 
 static inline void eeh_outb(u8 val, unsigned long port)
 {
-	if (_IO_IS_VALID(port))
-		out_8((u8 __iomem *)(port+pci_io_base), val);
+	out_8((u8 __iomem *)(port+pci_io_base), val);
 }
 
 static inline u16 eeh_inw(unsigned long port)
 {
 	u16 val;
-	if (!_IO_IS_VALID(port))
-		return ~0;
 	val = in_le16((u16 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u16))
 		return eeh_check_failure((void __iomem *)(port), val);
@@ -320,15 +314,12 @@
 
 static inline void eeh_outw(u16 val, unsigned long port)
 {
-	if (_IO_IS_VALID(port))
-		out_le16((u16 __iomem *)(port+pci_io_base), val);
+	out_le16((u16 __iomem *)(port+pci_io_base), val);
 }
 
 static inline u32 eeh_inl(unsigned long port)
 {
 	u32 val;
-	if (!_IO_IS_VALID(port))
-		return ~0;
 	val = in_le32((u32 __iomem *)(port+pci_io_base));
 	if (EEH_POSSIBLE_ERROR(val, u32))
 		return eeh_check_failure((void __iomem *)(port), val);
@@ -337,8 +328,7 @@
 
 static inline void eeh_outl(u32 val, unsigned long port)
 {
-	if (_IO_IS_VALID(port))
-		out_le32((u32 __iomem *)(port+pci_io_base), val);
+	out_le32((u32 __iomem *)(port+pci_io_base), val);
 }
 
 /* in-string eeh macros */
diff --git a/include/asm-powerpc/eeh_event.h b/include/asm-powerpc/eeh_event.h
index 93d55a2..dc6bf0f 100644
--- a/include/asm-powerpc/eeh_event.h
+++ b/include/asm-powerpc/eeh_event.h
@@ -18,8 +18,8 @@
  * Copyright (c) 2005 Linas Vepstas <linas@linas.org>
  */
 
-#ifndef ASM_PPC64_EEH_EVENT_H
-#define ASM_PPC64_EEH_EVENT_H
+#ifndef ASM_POWERPC_EEH_EVENT_H
+#define ASM_POWERPC_EEH_EVENT_H
 #ifdef __KERNEL__
 
 /** EEH event -- structure holding pci controller data that describes
@@ -39,7 +39,7 @@
  * @dev pci device
  *
  * This routine builds a PCI error event which will be delivered
- * to all listeners on the peh_notifier_chain.
+ * to all listeners on the eeh_notifier_chain.
  *
  * This routine can be called within an interrupt context;
  * the actual event will be delivered in a normal context
@@ -51,7 +51,7 @@
                             int time_unavail);
 
 /* Main recovery function */
-void handle_eeh_events (struct eeh_event *);
+struct pci_dn * handle_eeh_events (struct eeh_event *);
 
 #endif /* __KERNEL__ */
-#endif /* ASM_PPC64_EEH_EVENT_H */
+#endif /* ASM_POWERPC_EEH_EVENT_H */
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index 94d228f..9a83a98 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -3,14 +3,14 @@
 
 #ifdef __KERNEL__
 #include <linux/sched.h>	/* for task_struct */
+#include <asm/page.h>
+#include <asm/string.h>
 #endif
 
 #include <asm/types.h>
 #include <asm/ptrace.h>
 #include <asm/cputable.h>
 #include <asm/auxvec.h>
-#include <asm/page.h>
-#include <asm/string.h>
 
 /* PowerPC relocations defined by the ABIs */
 #define R_PPC_NONE		0
@@ -129,7 +129,7 @@
   /* Assumption: ELF_ARCH == EM_PPC and ELF_CLASS == ELFCLASS32 */
   typedef elf_greg_t32 elf_greg_t;
   typedef elf_gregset_t32 elf_gregset_t;
-# define elf_addr_t u32
+# define elf_addr_t __u32
 #endif /* ELF_ARCH */
 
 /* Floating point registers */
@@ -161,6 +161,7 @@
 typedef elf_vrreg_t elf_vrregset_t32[ELF_NVRREG32];
 #endif
 
+#ifdef __KERNEL__
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
@@ -176,8 +177,6 @@
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
-#ifdef __KERNEL__
-
 /* Common routine for both 32-bit and 64-bit processes */
 static inline void ppc_elf_core_copy_regs(elf_gregset_t elf_regs,
 					    struct pt_regs *regs)
@@ -294,7 +293,7 @@
 	NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize);			\
 	NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize);			\
 	NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize);			\
-	VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base)	\
+	VDSO_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso_base)	\
 } while (0)
 
 /* PowerPC64 relocations defined by the ABIs */
diff --git a/include/asm-powerpc/floppy.h b/include/asm-powerpc/floppy.h
index 608164c..9c8d91b 100644
--- a/include/asm-powerpc/floppy.h
+++ b/include/asm-powerpc/floppy.h
@@ -11,7 +11,6 @@
 #define __ASM_POWERPC_FLOPPY_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/machdep.h>
 
 #define fd_inb(port)		inb_p(port)
@@ -28,8 +27,7 @@
 #define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
 #define fd_cacheflush(addr,size) /* nothing */
 #define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt, \
-					    SA_INTERRUPT|SA_SAMPLE_RANDOM, \
-				            "floppy", NULL)
+					    SA_INTERRUPT, "floppy", NULL)
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL);
 
 #ifdef CONFIG_PCI
diff --git a/include/asm-powerpc/hvcall.h b/include/asm-powerpc/hvcall.h
index 6cc7e1f..0d3c4e8 100644
--- a/include/asm-powerpc/hvcall.h
+++ b/include/asm-powerpc/hvcall.h
@@ -102,6 +102,15 @@
 #define H_PP1			(1UL<<(63-62))
 #define H_PP2			(1UL<<(63-63))
 
+/* VASI States */
+#define H_VASI_INVALID          0
+#define H_VASI_ENABLED          1
+#define H_VASI_ABORTED          2
+#define H_VASI_SUSPENDING       3
+#define H_VASI_SUSPENDED        4
+#define H_VASI_RESUMED          5
+#define H_VASI_COMPLETED        6
+
 /* DABRX flags */
 #define H_DABRX_HYPERVISOR	(1UL<<(63-61))
 #define H_DABRX_KERNEL		(1UL<<(63-62))
@@ -190,6 +199,7 @@
 #define H_QUERY_INT_STATE       0x1E4
 #define H_POLL_PENDING		0x1D8
 #define H_JOIN			0x298
+#define H_VASI_STATE            0x2A4
 #define H_ENABLE_CRQ		0x2B0
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index 26b89d8..ce0f7db 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -6,7 +6,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
diff --git a/include/asm-powerpc/ide.h b/include/asm-powerpc/ide.h
index da5f640..b09b42a 100644
--- a/include/asm-powerpc/ide.h
+++ b/include/asm-powerpc/ide.h
@@ -22,7 +22,6 @@
 #endif
 
 #ifndef  __powerpc64__
-#include <linux/config.h>
 #include <linux/hdreg.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h
new file mode 100644
index 0000000..d905b66
--- /dev/null
+++ b/include/asm-powerpc/immap_86xx.h
@@ -0,0 +1,199 @@
+/*
+ * MPC86xx Internal Memory Map
+ *
+ * Author: Jeff Brown
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __ASM_POWERPC_IMMAP_86XX_H__
+#define __ASM_POWERPC_IMMAP_86XX_H__
+#ifdef __KERNEL__
+
+/* Eventually this should define all the IO block registers in 86xx */
+
+/* PCI Registers */
+typedef struct ccsr_pci {
+	uint	cfg_addr;	/* 0x.000 - PCI Configuration Address Register */
+	uint	cfg_data;	/* 0x.004 - PCI Configuration Data Register */
+	uint	int_ack;	/* 0x.008 - PCI Interrupt Acknowledge Register */
+	char	res1[3060];
+	uint	potar0;		/* 0x.c00 - PCI Outbound Transaction Address Register 0 */
+	uint	potear0;	/* 0x.c04 - PCI Outbound Translation Extended Address Register 0 */
+	uint	powbar0;	/* 0x.c08 - PCI Outbound Window Base Address Register 0 */
+	char	res2[4];
+	uint	powar0;		/* 0x.c10 - PCI Outbound Window Attributes Register 0 */
+	char	res3[12];
+	uint	potar1;		/* 0x.c20 - PCI Outbound Transaction Address Register 1 */
+	uint	potear1;	/* 0x.c24 - PCI Outbound Translation Extended Address Register 1 */
+	uint	powbar1;	/* 0x.c28 - PCI Outbound Window Base Address Register 1 */
+	char	res4[4];
+	uint	powar1;		/* 0x.c30 - PCI Outbound Window Attributes Register 1 */
+	char	res5[12];
+	uint	potar2;		/* 0x.c40 - PCI Outbound Transaction Address Register 2 */
+	uint	potear2;	/* 0x.c44 - PCI Outbound Translation Extended Address Register 2 */
+	uint	powbar2;	/* 0x.c48 - PCI Outbound Window Base Address Register 2 */
+	char	res6[4];
+	uint	powar2;		/* 0x.c50 - PCI Outbound Window Attributes Register 2 */
+	char	res7[12];
+	uint	potar3;		/* 0x.c60 - PCI Outbound Transaction Address Register 3 */
+	uint	potear3;	/* 0x.c64 - PCI Outbound Translation Extended Address Register 3 */
+	uint	powbar3;	/* 0x.c68 - PCI Outbound Window Base Address Register 3 */
+	char	res8[4];
+	uint	powar3;		/* 0x.c70 - PCI Outbound Window Attributes Register 3 */
+	char	res9[12];
+	uint	potar4;		/* 0x.c80 - PCI Outbound Transaction Address Register 4 */
+	uint	potear4;	/* 0x.c84 - PCI Outbound Translation Extended Address Register 4 */
+	uint	powbar4;	/* 0x.c88 - PCI Outbound Window Base Address Register 4 */
+	char	res10[4];
+	uint	powar4;		/* 0x.c90 - PCI Outbound Window Attributes Register 4 */
+	char	res11[268];
+	uint	pitar3;		/* 0x.da0 - PCI Inbound Translation Address Register 3  */
+	char	res12[4];
+	uint	piwbar3;	/* 0x.da8 - PCI Inbound Window Base Address Register 3 */
+	uint	piwbear3;	/* 0x.dac - PCI Inbound Window Base Extended Address Register 3 */
+	uint	piwar3;		/* 0x.db0 - PCI Inbound Window Attributes Register 3 */
+	char	res13[12];
+	uint	pitar2;		/* 0x.dc0 - PCI Inbound Translation Address Register 2  */
+	char	res14[4];
+	uint	piwbar2;	/* 0x.dc8 - PCI Inbound Window Base Address Register 2 */
+	uint	piwbear2;	/* 0x.dcc - PCI Inbound Window Base Extended Address Register 2 */
+	uint	piwar2;		/* 0x.dd0 - PCI Inbound Window Attributes Register 2 */
+	char	res15[12];
+	uint	pitar1;		/* 0x.de0 - PCI Inbound Translation Address Register 1  */
+	char	res16[4];
+	uint	piwbar1;	/* 0x.de8 - PCI Inbound Window Base Address Register 1 */
+	char	res17[4];
+	uint	piwar1;		/* 0x.df0 - PCI Inbound Window Attributes Register 1 */
+	char	res18[12];
+	uint	err_dr;		/* 0x.e00 - PCI Error Detect Register */
+	uint	err_cap_dr;	/* 0x.e04 - PCI Error Capture Disable Register */
+	uint	err_en;		/* 0x.e08 - PCI Error Enable Register */
+	uint	err_attrib;	/* 0x.e0c - PCI Error Attributes Capture Register */
+	uint	err_addr;	/* 0x.e10 - PCI Error Address Capture Register */
+	uint	err_ext_addr;	/* 0x.e14 - PCI Error Extended Address Capture Register */
+	uint	err_dl;		/* 0x.e18 - PCI Error Data Low Capture Register */
+	uint	err_dh;		/* 0x.e1c - PCI Error Data High Capture Register */
+	uint	gas_timr;	/* 0x.e20 - PCI Gasket Timer Register */
+	uint	pci_timr;	/* 0x.e24 - PCI Timer Register */
+	char	res19[472];
+} ccsr_pci_t;
+
+/* PCI Express Registers */
+typedef struct ccsr_pex {
+	uint    pex_config_addr;        /* 0x.000 - PCI Express Configuration Address Register */
+	uint    pex_config_data;        /* 0x.004 - PCI Express Configuration Data Register */
+	char    res1[4];
+	uint    pex_otb_cpl_tor;        /* 0x.00c - PCI Express Outbound completion timeout register */
+	uint    pex_conf_tor;           /* 0x.010 - PCI Express configuration timeout register */
+	char    res2[12];
+	uint    pex_pme_mes_dr;         /* 0x.020 - PCI Express PME and message detect register */
+	uint    pex_pme_mes_disr;       /* 0x.024 - PCI Express PME and message disable register */
+	uint    pex_pme_mes_ier;        /* 0x.028 - PCI Express PME and message interrupt enable register */
+	uint    pex_pmcr;               /* 0x.02c - PCI Express power management command register */
+	char    res3[3024];
+	uint    pexotar0;               /* 0x.c00 - PCI Express outbound translation address register 0 */
+	uint    pexotear0;              /* 0x.c04 - PCI Express outbound translation extended address register 0*/
+	char    res4[8];
+	uint    pexowar0;               /* 0x.c10 - PCI Express outbound window attributes register 0*/
+	char    res5[12];
+	uint    pexotar1;               /* 0x.c20 - PCI Express outbound translation address register 1 */
+	uint    pexotear1;              /* 0x.c24 - PCI Express outbound translation extended address register 1*/
+	uint    pexowbar1;              /* 0x.c28 - PCI Express outbound window base address register 1*/
+	char    res6[4];
+	uint    pexowar1;               /* 0x.c30 - PCI Express outbound window attributes register 1*/
+	char    res7[12];
+	uint    pexotar2;               /* 0x.c40 - PCI Express outbound translation address register 2 */
+	uint    pexotear2;              /* 0x.c44 - PCI Express outbound translation extended address register 2*/
+	uint    pexowbar2;              /* 0x.c48 - PCI Express outbound window base address register 2*/
+	char    res8[4];
+	uint    pexowar2;               /* 0x.c50 - PCI Express outbound window attributes register 2*/
+	char    res9[12];
+	uint    pexotar3;               /* 0x.c60 - PCI Express outbound translation address register 3 */
+	uint    pexotear3;              /* 0x.c64 - PCI Express outbound translation extended address register 3*/
+	uint    pexowbar3;              /* 0x.c68 - PCI Express outbound window base address register 3*/
+	char    res10[4];
+	uint    pexowar3;               /* 0x.c70 - PCI Express outbound window attributes register 3*/
+	char    res11[12];
+	uint    pexotar4;               /* 0x.c80 - PCI Express outbound translation address register 4 */
+	uint    pexotear4;              /* 0x.c84 - PCI Express outbound translation extended address register 4*/
+	uint    pexowbar4;              /* 0x.c88 - PCI Express outbound window base address register 4*/
+	char    res12[4];
+	uint    pexowar4;               /* 0x.c90 - PCI Express outbound window attributes register 4*/
+	char    res13[12];
+	char    res14[256];
+	uint    pexitar3;               /* 0x.da0 - PCI Express inbound translation address register 3 */
+	char    res15[4];
+	uint    pexiwbar3;              /* 0x.da8 - PCI Express inbound window base address register 3 */
+	uint    pexiwbear3;             /* 0x.dac - PCI Express inbound window base extended address register 3 */
+	uint    pexiwar3;               /* 0x.db0 - PCI Express inbound window attributes register 3 */
+	char    res16[12];
+	uint    pexitar2;               /* 0x.dc0 - PCI Express inbound translation address register 2 */
+	char    res17[4];
+	uint    pexiwbar2;              /* 0x.dc8 - PCI Express inbound window base address register 2 */
+	uint    pexiwbear2;             /* 0x.dcc - PCI Express inbound window base extended address register 2 */
+	uint    pexiwar2;               /* 0x.dd0 - PCI Express inbound window attributes register 2 */
+	char    res18[12];
+	uint    pexitar1;               /* 0x.de0 - PCI Express inbound translation address register 2 */
+	char    res19[4];
+	uint    pexiwbar1;              /* 0x.de8 - PCI Express inbound window base address register 2 */
+	uint    pexiwbear1;             /* 0x.dec - PCI Express inbound window base extended address register 2 */
+	uint    pexiwar1;               /* 0x.df0 - PCI Express inbound window attributes register 2 */
+	char    res20[12];
+	uint    pex_err_dr;             /* 0x.e00 - PCI Express error detect register */
+	char    res21[4];
+	uint    pex_err_en;             /* 0x.e08 - PCI Express error interrupt enable register */
+	char    res22[4];
+	uint    pex_err_disr;           /* 0x.e10 - PCI Express error disable register */
+	char    res23[12];
+	uint    pex_err_cap_stat;       /* 0x.e20 - PCI Express error capture status register */
+	char    res24[4];
+	uint    pex_err_cap_r0;         /* 0x.e28 - PCI Express error capture register 0 */
+	uint    pex_err_cap_r1;         /* 0x.e2c - PCI Express error capture register 0 */
+	uint    pex_err_cap_r2;         /* 0x.e30 - PCI Express error capture register 0 */
+	uint    pex_err_cap_r3;         /* 0x.e34 - PCI Express error capture register 0 */
+} ccsr_pex_t;
+
+/* Global Utility Registers */
+typedef struct ccsr_guts {
+	uint	porpllsr;	/* 0x.0000 - POR PLL Ratio Status Register */
+	uint	porbmsr;	/* 0x.0004 - POR Boot Mode Status Register */
+	uint	porimpscr;	/* 0x.0008 - POR I/O Impedance Status and Control Register */
+	uint	pordevsr;	/* 0x.000c - POR I/O Device Status Register */
+	uint	pordbgmsr;	/* 0x.0010 - POR Debug Mode Status Register */
+	char	res1[12];
+	uint	gpporcr;	/* 0x.0020 - General-Purpose POR Configuration Register */
+	char	res2[12];
+	uint	gpiocr;		/* 0x.0030 - GPIO Control Register */
+	char	res3[12];
+	uint	gpoutdr;	/* 0x.0040 - General-Purpose Output Data Register */
+	char	res4[12];
+	uint	gpindr;		/* 0x.0050 - General-Purpose Input Data Register */
+	char	res5[12];
+	uint	pmuxcr;		/* 0x.0060 - Alternate Function Signal Multiplex Control */
+	char	res6[12];
+	uint	devdisr;	/* 0x.0070 - Device Disable Control */
+	char	res7[12];
+	uint	powmgtcsr;	/* 0x.0080 - Power Management Status and Control Register */
+	char	res8[12];
+	uint	mcpsumr;	/* 0x.0090 - Machine Check Summary Register */
+	char	res9[12];
+	uint	pvr;		/* 0x.00a0 - Processor Version Register */
+	uint	svr;		/* 0x.00a4 - System Version Register */
+	char	res10[3416];
+	uint	clkocr;		/* 0x.0e00 - Clock Out Select Register */
+	char	res11[12];
+	uint	ddrdllcr;	/* 0x.0e10 - DDR DLL Control Register */
+	char	res12[12];
+	uint	lbcdllcr;	/* 0x.0e20 - LBC DLL Control Register */
+	char	res13[61916];
+} ccsr_guts_t;
+
+#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index f1c2469..a9496f3 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -40,12 +40,6 @@
 
 extern unsigned long isa_io_base;
 extern unsigned long pci_io_base;
-extern unsigned long io_page_mask;
-
-#define MAX_ISA_PORT 0x10000
-
-#define _IO_IS_VALID(port) ((port) >= MAX_ISA_PORT || (1 << (port>>PAGE_SHIFT)) \
-			    & io_page_mask)
 
 #ifdef CONFIG_PPC_ISERIES
 /* __raw_* accessors aren't supported on iSeries */
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index 18ca29e91..a5e9864 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -22,7 +22,6 @@
 #define _ASM_IOMMU_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
@@ -67,7 +66,8 @@
 /* Initializes an iommu_table based in values set in the passed-in
  * structure
  */
-extern struct iommu_table *iommu_init_table(struct iommu_table * tbl);
+extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
+					    int nid);
 
 extern int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 		struct scatterlist *sglist, int nelems, unsigned long mask,
@@ -76,7 +76,8 @@
 		int nelems, enum dma_data_direction direction);
 
 extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag);
+		dma_addr_t *dma_handle, unsigned long mask,
+		gfp_t flag, int node);
 extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
 		void *vaddr, dma_addr_t dma_handle);
 extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
diff --git a/include/asm-powerpc/irq.h b/include/asm-powerpc/irq.h
index 7bc6d73..a10feec 100644
--- a/include/asm-powerpc/irq.h
+++ b/include/asm-powerpc/irq.h
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/threads.h>
 
 #include <asm/types.h>
@@ -348,6 +347,92 @@
 #define	SIU_INT_PC1		((uint)0x3e+CPM_IRQ_OFFSET)
 #define	SIU_INT_PC0		((uint)0x3f+CPM_IRQ_OFFSET)
 
+#elif defined(CONFIG_PPC_86xx)
+#include <asm/mpc86xx.h>
+
+#define NR_EPIC_INTS 48
+#ifndef NR_8259_INTS
+#define NR_8259_INTS 16 /*ULI 1575 can route 12 interrupts */
+#endif
+#define NUM_8259_INTERRUPTS NR_8259_INTS
+
+#ifndef I8259_OFFSET
+#define I8259_OFFSET 0
+#endif
+
+#define NR_IRQS 256
+
+/* Internal IRQs on MPC86xx OpenPIC */
+
+#ifndef MPC86xx_OPENPIC_IRQ_OFFSET
+#define MPC86xx_OPENPIC_IRQ_OFFSET NR_8259_INTS
+#endif
+
+/* The 48 internal sources */
+#define MPC86xx_IRQ_NULL        ( 0 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_MCM         ( 1 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_DDR         ( 2 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_LBC         ( 3 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_DMA0        ( 4 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_DMA1        ( 5 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_DMA2        ( 6 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_DMA3        ( 7 + MPC86xx_OPENPIC_IRQ_OFFSET)
+
+/* no 10,11 */
+#define MPC86xx_IRQ_UART2       (12 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC1_TX    (13 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC1_RX    (14 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC3_TX    (15 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC3_RX    (16 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC3_ERROR (17 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC1_ERROR (18 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC2_TX    (19 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC2_RX    (20 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC4_TX    (21 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC4_RX    (22 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC4_ERROR (23 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_TSEC2_ERROR (24 + MPC86xx_OPENPIC_IRQ_OFFSET)
+/* no 25 */
+#define MPC86xx_IRQ_UART1       (26 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_IIC         (27 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_PERFMON       (28 + MPC86xx_OPENPIC_IRQ_OFFSET)
+/* no 29,30,31 */
+#define MPC86xx_IRQ_SRIO_ERROR    (32 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_SRIO_OUT_BELL (33 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_SRIO_IN_BELL  (34 + MPC86xx_OPENPIC_IRQ_OFFSET)
+/* no 35,36 */
+#define MPC86xx_IRQ_SRIO_OUT_MSG1 (37 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_SRIO_IN_MSG1  (38 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_SRIO_OUT_MSG2 (39 + MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_SRIO_IN_MSG2  (40 + MPC86xx_OPENPIC_IRQ_OFFSET)
+
+/* The 12 external interrupt lines */
+#define MPC86xx_IRQ_EXT_BASE	48
+#define MPC86xx_IRQ_EXT0	(0 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT1	(1 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT2	(2 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT3	(3 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT4	(4 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT5	(5 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT6	(6 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT7	(7 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT8	(8 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT9	(9 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT10	(10 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+#define MPC86xx_IRQ_EXT11	(11 + MPC86xx_IRQ_EXT_BASE \
+		+ MPC86xx_OPENPIC_IRQ_OFFSET)
+
 #else /* CONFIG_40x + CONFIG_8xx */
 /*
  * this is the # irq's for all ppc arch's (pmac/chrp/prep)
diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h
new file mode 100644
index 0000000..0edbfe1
--- /dev/null
+++ b/include/asm-powerpc/iseries/iommu.h
@@ -0,0 +1,35 @@
+#ifndef _ASM_POWERPC_ISERIES_IOMMU_H
+#define _ASM_POWERPC_ISERIES_IOMMU_H
+
+/*
+ * Copyright (C) 2005  Stephen Rothwell, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ * Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330,
+ * Boston, MA  02111-1307  USA
+ */
+
+struct device_node;
+struct iommu_table;
+
+/* Creates table for an individual device node */
+extern void iommu_devnode_init_iSeries(struct device_node *dn);
+
+/* Get table parameters from HV */
+extern void iommu_table_getparms_iSeries(unsigned long busno,
+		unsigned char slotno, unsigned char virtbus,
+		struct iommu_table *tbl);
+
+#endif /* _ASM_POWERPC_ISERIES_IOMMU_H */
diff --git a/include/asm-powerpc/iseries/iseries_io.h b/include/asm-powerpc/iseries/iseries_io.h
index 496aa85..f29009b 100644
--- a/include/asm-powerpc/iseries/iseries_io.h
+++ b/include/asm-powerpc/iseries/iseries_io.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_POWERPC_ISERIES_ISERIES_IO_H
 #define _ASM_POWERPC_ISERIES_ISERIES_IO_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PPC_ISERIES
 #include <linux/types.h>
diff --git a/include/asm-powerpc/kdebug.h b/include/asm-powerpc/kdebug.h
index c01786a..532bfee 100644
--- a/include/asm-powerpc/kdebug.h
+++ b/include/asm-powerpc/kdebug.h
@@ -18,6 +18,8 @@
 
 extern int register_die_notifier(struct notifier_block *);
 extern int unregister_die_notifier(struct notifier_block *);
+extern int register_page_fault_notifier(struct notifier_block *);
+extern int unregister_page_fault_notifier(struct notifier_block *);
 extern struct atomic_notifier_head powerpc_die_chain;
 
 /* Grossly misnamed. */
diff --git a/include/asm-powerpc/kdump.h b/include/asm-powerpc/kdump.h
index a87aed0..5a5c3b5 100644
--- a/include/asm-powerpc/kdump.h
+++ b/include/asm-powerpc/kdump.h
@@ -1,13 +1,38 @@
 #ifndef _PPC64_KDUMP_H
 #define _PPC64_KDUMP_H
 
+/* Kdump kernel runs at 32 MB, change at your peril. */
+#define KDUMP_KERNELBASE	0x2000000
+
 /* How many bytes to reserve at zero for kdump. The reserve limit should
- * be greater or equal to the trampoline's end address. */
+ * be greater or equal to the trampoline's end address.
+ * Reserve to the end of the FWNMI area, see head_64.S */
 #define KDUMP_RESERVE_LIMIT	0x8000
 
+#ifdef CONFIG_CRASH_DUMP
+
+#define PHYSICAL_START	KDUMP_KERNELBASE
 #define KDUMP_TRAMPOLINE_START	0x0100
 #define KDUMP_TRAMPOLINE_END	0x3000
 
-extern void kdump_setup(void);
+#else /* !CONFIG_CRASH_DUMP */
+
+#define PHYSICAL_START	0x0
+
+#endif /* CONFIG_CRASH_DUMP */
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_CRASH_DUMP
+
+extern void reserve_kdump_trampoline(void);
+extern void setup_kdump_trampoline(void);
+
+#else /* !CONFIG_CRASH_DUMP */
+
+static inline void reserve_kdump_trampoline(void) { ; }
+static inline void setup_kdump_trampoline(void) { ; }
+
+#endif /* CONFIG_CRASH_DUMP */
+#endif /* __ASSEMBLY__ */
 
 #endif /* __PPC64_KDUMP_H */
diff --git a/include/asm-powerpc/kexec.h b/include/asm-powerpc/kexec.h
index 6a2af2f..efe8872 100644
--- a/include/asm-powerpc/kexec.h
+++ b/include/asm-powerpc/kexec.h
@@ -31,9 +31,10 @@
 #define KEXEC_ARCH KEXEC_ARCH_PPC
 #endif
 
+#ifndef __ASSEMBLY__
+
 #ifdef CONFIG_KEXEC
 
-#ifndef __ASSEMBLY__
 #ifdef __powerpc64__
 /*
  * This function is responsible for capturing register states if coming
@@ -123,8 +124,19 @@
 extern void default_machine_crash_shutdown(struct pt_regs *regs);
 
 extern void machine_kexec_simple(struct kimage *image);
+extern int overlaps_crashkernel(unsigned long start, unsigned long size);
+extern void reserve_crashkernel(void);
 
-#endif /* ! __ASSEMBLY__ */
+#else /* !CONFIG_KEXEC */
+
+static inline int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+	return 0;
+}
+
+static inline void reserve_crashkernel(void) { ; }
+
 #endif /* CONFIG_KEXEC */
+#endif /* ! __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_KEXEC_H */
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index f466bc8..2d0af52 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -50,6 +50,8 @@
 			IS_TWI(instr) || IS_TDI(instr))
 
 #define ARCH_SUPPORTS_KRETPROBES
+#define  ARCH_INACTIVE_KPROBE_COUNT 1
+
 void kretprobe_trampoline(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h
index 0f9254c..73db1f7 100644
--- a/include/asm-powerpc/machdep.h
+++ b/include/asm-powerpc/machdep.h
@@ -9,7 +9,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
@@ -238,6 +237,11 @@
 	 */
 	void (*machine_kexec)(struct kimage *image);
 #endif /* CONFIG_KEXEC */
+
+#ifdef CONFIG_PCI_MSI
+	int (*enable_msi)(struct pci_dev *pdev);
+	void (*disable_msi)(struct pci_dev *pdev);
+#endif /* CONFIG_PCI_MSI */
 };
 
 extern void power4_idle(void);
diff --git a/include/asm-powerpc/mmu.h b/include/asm-powerpc/mmu.h
index 31f7219..3a5ebe2 100644
--- a/include/asm-powerpc/mmu.h
+++ b/include/asm-powerpc/mmu.h
@@ -96,6 +96,8 @@
 #define HPTE_R_FLAGS		ASM_CONST(0x00000000000003ff)
 #define HPTE_R_PP		ASM_CONST(0x0000000000000003)
 #define HPTE_R_N		ASM_CONST(0x0000000000000004)
+#define HPTE_R_C		ASM_CONST(0x0000000000000080)
+#define HPTE_R_R		ASM_CONST(0x0000000000000100)
 
 /* Values for PP (assumes Ks=0, Kp=1) */
 /* pp0 will always be 0 for linux     */
@@ -163,6 +165,16 @@
 extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
 extern int mmu_linear_psize;
 extern int mmu_virtual_psize;
+extern int mmu_vmalloc_psize;
+extern int mmu_io_psize;
+
+/*
+ * If the processor supports 64k normal pages but not 64k cache
+ * inhibited pages, we have to be prepared to switch processes
+ * to use 4k pages when they create cache-inhibited mappings.
+ * If this is the case, mmu_ci_restrictions will be set to 1.
+ */
+extern int mmu_ci_restrictions;
 
 #ifdef CONFIG_HUGETLB_PAGE
 /*
@@ -254,6 +266,7 @@
 
 extern void stabs_alloc(void);
 extern void slb_initialize(void);
+extern void slb_flush_and_rebolt(void);
 extern void stab_initialize(unsigned long stab);
 
 #endif /* __ASSEMBLY__ */
@@ -357,9 +370,12 @@
 
 typedef struct {
 	mm_context_id_t id;
+	u16 user_psize;			/* page size index */
+	u16 sllp;			/* SLB entry page size encoding */
 #ifdef CONFIG_HUGETLB_PAGE
 	u16 low_htlb_areas, high_htlb_areas;
 #endif
+	unsigned long vdso_base;
 } mm_context_t;
 
 
diff --git a/include/asm-powerpc/mmu_context.h b/include/asm-powerpc/mmu_context.h
index 1b8a25f..8c6b1a6d 100644
--- a/include/asm-powerpc/mmu_context.h
+++ b/include/asm-powerpc/mmu_context.h
@@ -20,16 +20,9 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-/*
- * Getting into a kernel thread, there is no valid user segment, mark
- * paca->pgdir NULL so that SLB miss on user addresses will fault
- */
 static inline void enter_lazy_tlb(struct mm_struct *mm,
 				  struct task_struct *tsk)
 {
-#ifdef CONFIG_PPC_64K_PAGES
-	get_paca()->pgdir = NULL;
-#endif /* CONFIG_PPC_64K_PAGES */
 }
 
 #define NO_CONTEXT	0
@@ -52,13 +45,8 @@
 		cpu_set(smp_processor_id(), next->cpu_vm_mask);
 
 	/* No need to flush userspace segments if the mm doesnt change */
-#ifdef CONFIG_PPC_64K_PAGES
-	if (prev == next && get_paca()->pgdir == next->pgd)
-		return;
-#else
 	if (prev == next)
 		return;
-#endif /* CONFIG_PPC_64K_PAGES */
 
 #ifdef CONFIG_ALTIVEC
 	if (cpu_has_feature(CPU_FTR_ALTIVEC))
diff --git a/include/asm-powerpc/mmzone.h b/include/asm-powerpc/mmzone.h
index 88d70ba..d484ca9 100644
--- a/include/asm-powerpc/mmzone.h
+++ b/include/asm-powerpc/mmzone.h
@@ -8,7 +8,6 @@
 #define _ASM_MMZONE_H_
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /*
  * generic non-linear memory support:
diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h
new file mode 100644
index 0000000..d0a6718
--- /dev/null
+++ b/include/asm-powerpc/mpc86xx.h
@@ -0,0 +1,47 @@
+/*
+ * MPC86xx definitions
+ *
+ * Author: Jeff Brown
+ *
+ * Copyright 2004 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_POWERPC_MPC86xx_H__
+#define __ASM_POWERPC_MPC86xx_H__
+
+#include <linux/config.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_PPC_86xx
+
+#ifdef CONFIG_MPC8641_HPCN
+#include <platforms/86xx/mpc8641_hpcn.h>
+#endif
+
+#define _IO_BASE        isa_io_base
+#define _ISA_MEM_BASE   isa_mem_base
+#ifdef CONFIG_PCI
+#define PCI_DRAM_OFFSET pci_dram_offset
+#else
+#define PCI_DRAM_OFFSET 0
+#endif
+
+#define CPU0_BOOT_RELEASE 0x01000000
+#define CPU1_BOOT_RELEASE 0x02000000
+#define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE)
+#define MCM_PORT_CONFIG_OFFSET 0x1010
+
+/* Offset from CCSRBAR */
+#define MPC86xx_OPENPIC_OFFSET	(0x40000)
+#define MPC86xx_MCM_OFFSET      (0x00000)
+#define MPC86xx_MCM_SIZE        (0x02000)
+
+#endif /* CONFIG_PPC_86xx */
+#endif /* __ASM_POWERPC_MPC86xx_H__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h
index 6b9e781..f0d22ac 100644
--- a/include/asm-powerpc/mpic.h
+++ b/include/asm-powerpc/mpic.h
@@ -22,6 +22,10 @@
 #define		MPIC_GREG_GCONF_8259_PTHROU_DIS		0x20000000
 #define		MPIC_GREG_GCONF_BASE_MASK		0x000fffff
 #define MPIC_GREG_GLOBAL_CONF_1		0x00030
+#define		MPIC_GREG_GLOBAL_CONF_1_SIE		0x08000000
+#define		MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK	0x70000000
+#define		MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO(r)	\
+			(((r) << 28) & MPIC_GREG_GLOBAL_CONF_1_CLK_RATIO_MASK)
 #define MPIC_GREG_VENDOR_0		0x00040
 #define MPIC_GREG_VENDOR_1		0x00050
 #define MPIC_GREG_VENDOR_2		0x00060
@@ -284,6 +288,12 @@
 /* This one gets to the primary mpic */
 extern int mpic_get_irq(struct pt_regs *regs);
 
+/* Set the EPIC clock ratio */
+void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio);
+
+/* Enable/Disable EPIC serial interrupt mode */
+void mpic_set_serial_int(struct mpic *mpic, int enable);
+
 /* global mpic for pSeries */
 extern struct mpic *pSeries_mpic;
 
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h
index 706325f..2d4585f 100644
--- a/include/asm-powerpc/paca.h
+++ b/include/asm-powerpc/paca.h
@@ -16,7 +16,6 @@
 #define _ASM_POWERPC_PACA_H
 #ifdef __KERNEL__
 
-#include	<linux/config.h>
 #include	<asm/types.h>
 #include	<asm/lppaca.h>
 #include	<asm/mmu.h>
@@ -79,11 +78,9 @@
 	u64 exmc[10];		/* used for machine checks */
 	u64 exslb[10];		/* used for SLB/segment table misses
  				 * on the linear mapping */
-#ifdef CONFIG_PPC_64K_PAGES
-	pgd_t *pgdir;
-#endif /* CONFIG_PPC_64K_PAGES */
 
 	mm_context_t context;
+	u16 vmalloc_sllp;
 	u16 slb_cache[SLB_CACHE_ENTRIES];
 	u16 slb_cache_ptr;
 
diff --git a/include/asm-powerpc/page.h b/include/asm-powerpc/page.h
index 2fbeceb..fb597b3 100644
--- a/include/asm-powerpc/page.h
+++ b/include/asm-powerpc/page.h
@@ -11,8 +11,8 @@
  */
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <asm/asm-compat.h>
+#include <asm/kdump.h>
 
 /*
  * On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
@@ -52,13 +52,6 @@
  * If you want to test if something's a kernel address, use is_kernel_addr().
  */
 
-#ifdef CONFIG_CRASH_DUMP
-/* Kdump kernel runs at 32 MB, change at your peril. */
-#define PHYSICAL_START	0x2000000
-#else
-#define PHYSICAL_START	0x0
-#endif
-
 #define PAGE_OFFSET     ASM_CONST(CONFIG_KERNEL_START)
 #define KERNELBASE      (PAGE_OFFSET + PHYSICAL_START)
 
@@ -198,6 +191,9 @@
 		struct page *p);
 extern int page_is_ram(unsigned long pfn);
 
+struct vm_area_struct;
+extern const char *arch_vma_name(struct vm_area_struct *vma);
+
 #include <asm-generic/memory_model.h>
 #endif /* __ASSEMBLY__ */
 
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 38de92d..4f55573 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -6,6 +6,7 @@
 #include <asm-ppc/pci-bridge.h>
 #else
 
+#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/list.h>
 
@@ -22,6 +23,7 @@
 struct pci_controller {
 	struct pci_bus *bus;
 	char is_dynamic;
+	int node;
 	void *arch_data;
 	struct list_head list_node;
 
@@ -78,12 +80,6 @@
 	struct	iommu_table *iommu_table;	/* for phb's or bridges */
 	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
 	struct	device_node *node;	/* back-pointer to the device_node */
-#ifdef CONFIG_PPC_ISERIES
-	struct	list_head Device_List;
-	int	Irq;			/* Assigned IRQ */
-	int	Flags;			/* Possible flags(disable/bist)*/
-	u8	LogicalSlot;		/* Hv Slot Index for Tces */
-#endif
 	u32	config_space[16];	/* saved PCI config space */
 };
 
@@ -171,6 +167,12 @@
 #define PCI_PROBE_NORMAL	0	/* Do normal PCI probing */
 #define PCI_PROBE_DEVTREE	1	/* Instantiate from device tree */
 
+#ifdef CONFIG_NUMA
+#define PHB_SET_NODE(PHB, NODE)		((PHB)->node = (NODE))
+#else
+#define PHB_SET_NODE(PHB, NODE)		((PHB)->node = -1)
+#endif
+
 #endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
 #endif
diff --git a/include/asm-powerpc/percpu.h b/include/asm-powerpc/percpu.h
index 184a7a4..faa1fc7 100644
--- a/include/asm-powerpc/percpu.h
+++ b/include/asm-powerpc/percpu.h
@@ -22,6 +22,7 @@
 /* var is in discarded region: offset to particular copy we want */
 #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
 #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
 
 /* A macro to avoid #include hell... */
 #define percpu_modcopy(pcpudst, src, size)			\
@@ -41,6 +42,7 @@
 
 #define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
 #define __get_cpu_var(var)			per_cpu__##var
+#define __raw_get_cpu_var(var)			per_cpu__##var
 
 #endif	/* SMP */
 
diff --git a/include/asm-powerpc/pgtable-4k.h b/include/asm-powerpc/pgtable-4k.h
index b2e1862..e703615 100644
--- a/include/asm-powerpc/pgtable-4k.h
+++ b/include/asm-powerpc/pgtable-4k.h
@@ -78,6 +78,8 @@
 
 #define pte_iterate_hashed_end() } while(0)
 
+#define pte_pagesize_index(pte)	MMU_PAGE_4K
+
 /*
  * 4-level page tables related bits
  */
diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h
index 6539150..4b7126c 100644
--- a/include/asm-powerpc/pgtable-64k.h
+++ b/include/asm-powerpc/pgtable-64k.h
@@ -90,6 +90,8 @@
 
 #define pte_iterate_hashed_end() } while(0); } } while(0)
 
+#define pte_pagesize_index(pte)	\
+	(((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K)
 
 #endif /*  __ASSEMBLY__ */
 #endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/pgtable.h b/include/asm-powerpc/pgtable.h
index e9f1f46..8dbf5ad 100644
--- a/include/asm-powerpc/pgtable.h
+++ b/include/asm-powerpc/pgtable.h
@@ -12,7 +12,6 @@
  */
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <asm/processor.h>		/* For TASK_SIZE */
 #include <asm/mmu.h>
@@ -47,8 +46,8 @@
 /*
  * Define the address range of the vmalloc VM area.
  */
-#define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_SIZE  (0x80000000000UL)
+#define VMALLOC_START ASM_CONST(0xD000000000000000)
+#define VMALLOC_SIZE  ASM_CONST(0x80000000000)
 #define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
 
 /*
@@ -413,12 +412,6 @@
 		flush_tlb_pending();
 	}
 	pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS);
-
-#ifdef CONFIG_PPC_64K_PAGES
-	if (mmu_virtual_psize != MMU_PAGE_64K)
-		pte = __pte(pte_val(pte) | _PAGE_COMBO);
-#endif /* CONFIG_PPC_64K_PAGES */
-
 	*ptep = pte;
 }
 
diff --git a/include/asm-powerpc/ppc_asm.h b/include/asm-powerpc/ppc_asm.h
index dd1c0a9..a940cfe 100644
--- a/include/asm-powerpc/ppc_asm.h
+++ b/include/asm-powerpc/ppc_asm.h
@@ -5,7 +5,6 @@
 #define _ASM_POWERPC_PPC_ASM_H
 
 #include <linux/stringify.h>
-#include <linux/config.h>
 #include <asm/asm-compat.h>
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index 93f83ef..22e54a2 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -149,11 +149,11 @@
 		unsigned int val;	/* Floating point status */
 	} fpscr;
 	int		fpexc_mode;	/* floating-point exception mode */
+	unsigned int	align_ctl;	/* alignment handling control */
 #ifdef CONFIG_PPC64
 	unsigned long	start_tb;	/* Start purr when proc switched in */
 	unsigned long	accum_tb;	/* Total accumilated purr for process */
 #endif
-	unsigned long	vdso_base;	/* base of the vDSO library */
 	unsigned long	dabr;		/* Data address breakpoint register */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
@@ -190,7 +190,7 @@
 	.fs = KERNEL_DS, \
 	.fpr = {0}, \
 	.fpscr = { .val = 0, }, \
-	.fpexc_mode = MSR_FE0|MSR_FE1, \
+	.fpexc_mode = 0, \
 }
 #endif
 
@@ -212,6 +212,18 @@
 extern int get_fpexc_mode(struct task_struct *tsk, unsigned long adr);
 extern int set_fpexc_mode(struct task_struct *tsk, unsigned int val);
 
+#define GET_ENDIAN(tsk, adr) get_endian((tsk), (adr))
+#define SET_ENDIAN(tsk, val) set_endian((tsk), (val))
+
+extern int get_endian(struct task_struct *tsk, unsigned long adr);
+extern int set_endian(struct task_struct *tsk, unsigned int val);
+
+#define GET_UNALIGN_CTL(tsk, adr)	get_unalign_ctl((tsk), (adr))
+#define SET_UNALIGN_CTL(tsk, val)	set_unalign_ctl((tsk), (val))
+
+extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
+extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
+
 static inline unsigned int __unpack_fe01(unsigned long msr_bits)
 {
 	return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8);
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 97ef1cd..010d186 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -15,7 +15,6 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <asm/atomic.h>
@@ -230,7 +229,16 @@
 extern int of_pci_address_to_resource(struct device_node *dev, int bar,
 				      struct resource *r);
 
+/* Parse the ibm,dma-window property of an OF node into the busno, phys and
+ * size parameters.
+ */
+void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop,
+		unsigned long *busno, unsigned long *phys, unsigned long *size);
+
 extern void kdump_move_device_tree(void);
 
+/* CPU OF node matching */
+struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
+
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_PROM_H */
diff --git a/include/asm-powerpc/ptrace.h b/include/asm-powerpc/ptrace.h
index 9c550b3..dc4cb9c 100644
--- a/include/asm-powerpc/ptrace.h
+++ b/include/asm-powerpc/ptrace.h
@@ -229,13 +229,13 @@
 #define PTRACE_GET_DEBUGREG	25
 #define PTRACE_SET_DEBUGREG	26
 
-#ifdef __powerpc64__
 /* Additional PTRACE requests implemented on PowerPC. */
 #define PPC_PTRACE_GETREGS	0x99	/* Get GPRs 0 - 31 */
 #define PPC_PTRACE_SETREGS	0x98	/* Set GPRs 0 - 31 */
 #define PPC_PTRACE_GETFPREGS	0x97	/* Get FPRs 0 - 31 */
 #define PPC_PTRACE_SETFPREGS	0x96	/* Set FPRs 0 - 31 */
 
+#ifdef __powerpc64__
 /* Calls to trace a 64bit program from a 32bit program */
 #define PPC_PTRACE_PEEKTEXT_3264 0x95
 #define PPC_PTRACE_PEEKDATA_3264 0x94
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index bd467bf..cf73475 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -93,8 +93,8 @@
 #define MSR_LE		__MASK(MSR_LE_LG)	/* Little Endian */
 
 #ifdef CONFIG_PPC64
-#define MSR_		MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF
-#define MSR_KERNEL      MSR_ | MSR_SF | MSR_HV
+#define MSR_		MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV
+#define MSR_KERNEL      MSR_ | MSR_SF
 
 #define MSR_USER32	MSR_ | MSR_PR | MSR_EE
 #define MSR_USER64	MSR_USER32 | MSR_SF
@@ -153,7 +153,7 @@
 #define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
 #define   DABR_TRANSLATION	(1UL << 2)
 #define SPRN_DAR	0x013	/* Data Address Register */
-#define	SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
+#define SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
 #define   DSISR_NOHPTE		0x40000000	/* no translation found */
 #define   DSISR_PROTFAULT	0x08000000	/* protection fault */
 #define   DSISR_ISSTORE		0x02000000	/* access was a store */
@@ -258,16 +258,16 @@
 #define SPRN_IABR	0x3F2	/* Instruction Address Breakpoint Register */
 #define SPRN_HID4	0x3F4		/* 970 HID4 */
 #define SPRN_HID5	0x3F6		/* 970 HID5 */
-#define	SPRN_HID6	0x3F9	/* BE HID 6 */
-#define	  HID6_LB	(0x0F<<12) /* Concurrent Large Page Modes */
-#define	  HID6_DLP	(1<<20)	/* Disable all large page modes (4K only) */
-#define	SPRN_TSC_CELL	0x399	/* Thread switch control on Cell */
-#define	  TSC_CELL_DEC_ENABLE_0	0x400000 /* Decrementer Interrupt */
-#define	  TSC_CELL_DEC_ENABLE_1	0x200000 /* Decrementer Interrupt */
-#define	  TSC_CELL_EE_ENABLE	0x100000 /* External Interrupt */
-#define	  TSC_CELL_EE_BOOST	0x080000 /* External Interrupt Boost */
-#define	SPRN_TSC 	0x3FD	/* Thread switch control on others */
-#define	SPRN_TST 	0x3FC	/* Thread switch timeout on others */
+#define SPRN_HID6	0x3F9	/* BE HID 6 */
+#define   HID6_LB	(0x0F<<12) /* Concurrent Large Page Modes */
+#define   HID6_DLP	(1<<20)	/* Disable all large page modes (4K only) */
+#define SPRN_TSC_CELL	0x399	/* Thread switch control on Cell */
+#define   TSC_CELL_DEC_ENABLE_0	0x400000 /* Decrementer Interrupt */
+#define   TSC_CELL_DEC_ENABLE_1	0x200000 /* Decrementer Interrupt */
+#define   TSC_CELL_EE_ENABLE	0x100000 /* External Interrupt */
+#define   TSC_CELL_EE_BOOST	0x080000 /* External Interrupt Boost */
+#define SPRN_TSC 	0x3FD	/* Thread switch control on others */
+#define SPRN_TST 	0x3FC	/* Thread switch timeout on others */
 #if !defined(SPRN_IAC1) && !defined(SPRN_IAC2)
 #define SPRN_IAC1	0x3F4		/* Instruction Address Compare 1 */
 #define SPRN_IAC2	0x3F5		/* Instruction Address Compare 2 */
@@ -362,7 +362,7 @@
 #endif
 #define SPRN_PTEHI	0x3D5	/* 981 7450 PTE HI word (S/W TLB load) */
 #define SPRN_PTELO	0x3D6	/* 982 7450 PTE LO word (S/W TLB load) */
-#define	SPRN_PURR	0x135	/* Processor Utilization of Resources Reg */
+#define SPRN_PURR	0x135	/* Processor Utilization of Resources Reg */
 #define SPRN_PVR	0x11F	/* Processor Version Register */
 #define SPRN_RPA	0x3D6	/* Required Physical Address Register */
 #define SPRN_SDA	0x3BF	/* Sampled Data Address Register */
@@ -386,6 +386,8 @@
 #define   SRR1_WAKEMT		0x00280000 /* mtctrl */
 #define   SRR1_WAKEDEC		0x00180000 /* Decrementer interrupt */
 #define   SRR1_WAKETHERM	0x00100000 /* Thermal management interrupt */
+#define SPRN_HSRR0	0x13A	/* Save/Restore Register 0 */
+#define SPRN_HSRR1	0x13B	/* Save/Restore Register 1 */
 
 #ifndef SPRN_SVR
 #define SPRN_SVR	0x11E	/* System Version Register */
@@ -443,6 +445,10 @@
 #define   MMCRA_SIHV	0x10000000UL /* state of MSR HV when SIAR set */
 #define   MMCRA_SIPR	0x08000000UL /* state of MSR PR when SIAR set */
 #define   MMCRA_SAMPLE_ENABLE 0x00000001UL /* enable sampling */
+#define   POWER6_MMCRA_SIHV   0x0000040000000000ULL
+#define   POWER6_MMCRA_SIPR   0x0000020000000000ULL
+#define   POWER6_MMCRA_THRM	0x00000020UL
+#define   POWER6_MMCRA_OTHER	0x0000000EUL
 #define SPRN_PMC1	787
 #define SPRN_PMC2	788
 #define SPRN_PMC3	789
@@ -495,6 +501,19 @@
 #define MMCR0_PMC2_LOADMISSTIME	0x5
 #endif
 
+/*
+ * An mtfsf instruction with the L bit set. On CPUs that support this a
+ * full 64bits of FPSCR is restored and on other CPUs it is ignored.
+ *
+ * Until binutils gets the new form of mtfsf, hardwire the instruction.
+ */
+#ifdef CONFIG_PPC64
+#define MTFSF_L(REG) \
+	.long (0xfc00058e | ((0xff) << 17) | ((REG) << 11) | (1 << 25))
+#else
+#define MTFSF_L(REG)	mtfsf	0xff, (REG)
+#endif
+
 /* Processor Version Register (PVR) field extraction */
 
 #define PVR_VER(pvr)	(((pvr) >>  16) & 0xFFFF)	/* Version field */
@@ -559,20 +578,20 @@
 
 /* 64-bit processors */
 /* XXX the prefix should be PVR_, we'll do a global sweep to fix it one day */
-#define	PV_NORTHSTAR	0x0033
-#define	PV_PULSAR	0x0034
-#define	PV_POWER4	0x0035
-#define	PV_ICESTAR	0x0036
-#define	PV_SSTAR	0x0037
-#define	PV_POWER4p	0x0038
+#define PV_NORTHSTAR	0x0033
+#define PV_PULSAR	0x0034
+#define PV_POWER4	0x0035
+#define PV_ICESTAR	0x0036
+#define PV_SSTAR	0x0037
+#define PV_POWER4p	0x0038
 #define PV_970		0x0039
-#define	PV_POWER5	0x003A
+#define PV_POWER5	0x003A
 #define PV_POWER5p	0x003B
 #define PV_970FX	0x003C
-#define	PV_630		0x0040
-#define	PV_630p	0x0041
-#define	PV_970MP	0x0044
-#define	PV_BE		0x0070
+#define PV_630		0x0040
+#define PV_630p	0x0041
+#define PV_970MP	0x0044
+#define PV_BE		0x0070
 
 /*
  * Number of entries in the SLB. If this ever changes we should handle
diff --git a/include/asm-powerpc/rtas.h b/include/asm-powerpc/rtas.h
index f43c683..02e213e 100644
--- a/include/asm-powerpc/rtas.h
+++ b/include/asm-powerpc/rtas.h
@@ -24,6 +24,7 @@
 #define RTAS_RMOBUF_MAX (64 * 1024)
 
 /* RTAS return status codes */
+#define RTAS_NOT_SUSPENDABLE	-9004
 #define RTAS_BUSY		-2    /* RTAS Busy */
 #define RTAS_EXTENDED_DELAY_MIN	9900
 #define RTAS_EXTENDED_DELAY_MAX	9905
@@ -177,12 +178,8 @@
 extern void rtas_get_rtc_time(struct rtc_time *rtc_time);
 extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
 
-/* Given an RTAS status code of 9900..9905 compute the hinted delay */
-unsigned int rtas_extended_busy_delay_time(int status);
-static inline int rtas_is_extended_busy(int status)
-{
-	return status >= 9900 && status <= 9909;
-}
+extern unsigned int rtas_busy_delay_time(int status);
+extern unsigned int rtas_busy_delay(int status);
 
 extern void pSeries_log_error(char *buf, unsigned int err_type, int fatal);
 
diff --git a/include/asm-powerpc/smp.h b/include/asm-powerpc/smp.h
index 4a716f7..068f119 100644
--- a/include/asm-powerpc/smp.h
+++ b/include/asm-powerpc/smp.h
@@ -17,7 +17,6 @@
 #define _ASM_POWERPC_SMP_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/kernel.h>
diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h
index 2dc93632..51e65fc 100644
--- a/include/asm-powerpc/smu.h
+++ b/include/asm-powerpc/smu.h
@@ -5,7 +5,6 @@
  * Definitions for talking to the SMU chip in newer G5 PowerMacs
  */
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/list.h>
 #endif
 #include <linux/types.h>
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 7cfcff3..9609d3e 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -24,9 +24,8 @@
 #define _SPU_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
-#include <linux/kref.h>
 #include <linux/workqueue.h>
+#include <linux/sysdev.h>
 
 #define LS_SIZE (256 * 1024)
 #define LS_ADDR_MASK (LS_SIZE - 1)
@@ -123,7 +122,6 @@
 	u64 flags;
 	u64 dar;
 	u64 dsisr;
-	struct kref kref;
 	size_t ls_size;
 	unsigned int slb_replace;
 	struct mm_struct *mm;
@@ -135,7 +133,6 @@
 	int class_0_pending;
 	spinlock_t register_lock;
 
-	u32 stop_code;
 	void (* wbox_callback)(struct spu *spu);
 	void (* ibox_callback)(struct spu *spu);
 	void (* stop_callback)(struct spu *spu);
@@ -144,6 +141,8 @@
 	char irq_c0[8];
 	char irq_c1[8];
 	char irq_c2[8];
+
+	struct sys_device sysdev;
 };
 
 struct spu *spu_alloc(void);
@@ -182,29 +181,6 @@
 #endif /* MODULE */
 
 
-/* access to priv1 registers */
-void spu_int_mask_and(struct spu *spu, int class, u64 mask);
-void spu_int_mask_or(struct spu *spu, int class, u64 mask);
-void spu_int_mask_set(struct spu *spu, int class, u64 mask);
-u64 spu_int_mask_get(struct spu *spu, int class);
-void spu_int_stat_clear(struct spu *spu, int class, u64 stat);
-u64 spu_int_stat_get(struct spu *spu, int class);
-void spu_int_route_set(struct spu *spu, u64 route);
-u64 spu_mfc_dar_get(struct spu *spu);
-u64 spu_mfc_dsisr_get(struct spu *spu);
-void spu_mfc_dsisr_set(struct spu *spu, u64 dsisr);
-void spu_mfc_sdr_set(struct spu *spu, u64 sdr);
-void spu_mfc_sr1_set(struct spu *spu, u64 sr1);
-u64 spu_mfc_sr1_get(struct spu *spu);
-void spu_mfc_tclass_id_set(struct spu *spu, u64 tclass_id);
-u64 spu_mfc_tclass_id_get(struct spu *spu);
-void spu_tlb_invalidate(struct spu *spu);
-void spu_resource_allocation_groupID_set(struct spu *spu, u64 id);
-u64 spu_resource_allocation_groupID_get(struct spu *spu);
-void spu_resource_allocation_enable_set(struct spu *spu, u64 enable);
-u64 spu_resource_allocation_enable_get(struct spu *spu);
-
-
 /*
  * This defines the Local Store, Problem Area and Privlege Area of an SPU.
  */
diff --git a/include/asm-powerpc/spu_csa.h b/include/asm-powerpc/spu_csa.h
index ba18d7d..964c2d3 100644
--- a/include/asm-powerpc/spu_csa.h
+++ b/include/asm-powerpc/spu_csa.h
@@ -86,10 +86,18 @@
 	struct spu_reg128 event_mask;
 	struct spu_reg128 srr0;
 	struct spu_reg128 stopped_status;
-	struct spu_reg128 pad[119];	/* 'ls' must be page-aligned. */
-	unsigned char ls[LS_SIZE];
+
+	/*
+	 * 'ls' must be page-aligned on all configurations.
+	 * Since we don't want to rely on having the spu-gcc
+	 * installed to build the kernel and this structure
+	 * is used in the SPU-side code, make it 64k-page
+	 * aligned for now.
+	 */
+	unsigned char ls[LS_SIZE] __attribute__((aligned(65536)));
 };
 
+#ifndef __SPU__
 /*
  * struct spu_problem_collapsed - condensed problem state area, w/o pads.
  */
@@ -250,6 +258,7 @@
 extern int spu_switch(struct spu_state *prev, struct spu_state *new,
 		      struct spu *spu);
 
+#endif /* !__SPU__ */
 #endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY__ */
 #endif /* _SPU_CSA_H_ */
diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h
new file mode 100644
index 0000000..300c458
--- /dev/null
+++ b/include/asm-powerpc/spu_priv1.h
@@ -0,0 +1,182 @@
+/*
+ * Defines an spu hypervisor abstraction layer.
+ *
+ *  Copyright 2006 Sony Corp.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#if !defined(_SPU_PRIV1_H)
+#define _SPU_PRIV1_H
+#if defined(__KERNEL__)
+
+struct spu;
+
+/* access to priv1 registers */
+
+struct spu_priv1_ops
+{
+	void (*int_mask_and) (struct spu *spu, int class, u64 mask);
+	void (*int_mask_or) (struct spu *spu, int class, u64 mask);
+	void (*int_mask_set) (struct spu *spu, int class, u64 mask);
+	u64 (*int_mask_get) (struct spu *spu, int class);
+	void (*int_stat_clear) (struct spu *spu, int class, u64 stat);
+	u64 (*int_stat_get) (struct spu *spu, int class);
+	void (*cpu_affinity_set) (struct spu *spu, int cpu);
+	u64 (*mfc_dar_get) (struct spu *spu);
+	u64 (*mfc_dsisr_get) (struct spu *spu);
+	void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr);
+	void (*mfc_sdr_set) (struct spu *spu, u64 sdr);
+	void (*mfc_sr1_set) (struct spu *spu, u64 sr1);
+	u64 (*mfc_sr1_get) (struct spu *spu);
+	void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id);
+	u64 (*mfc_tclass_id_get) (struct spu *spu);
+	void (*tlb_invalidate) (struct spu *spu);
+	void (*resource_allocation_groupID_set) (struct spu *spu, u64 id);
+	u64 (*resource_allocation_groupID_get) (struct spu *spu);
+	void (*resource_allocation_enable_set) (struct spu *spu, u64 enable);
+	u64 (*resource_allocation_enable_get) (struct spu *spu);
+};
+
+extern const struct spu_priv1_ops* spu_priv1_ops;
+
+static inline void
+spu_int_mask_and (struct spu *spu, int class, u64 mask)
+{
+	spu_priv1_ops->int_mask_and(spu, class, mask);
+}
+
+static inline void
+spu_int_mask_or (struct spu *spu, int class, u64 mask)
+{
+	spu_priv1_ops->int_mask_or(spu, class, mask);
+}
+
+static inline void
+spu_int_mask_set (struct spu *spu, int class, u64 mask)
+{
+	spu_priv1_ops->int_mask_set(spu, class, mask);
+}
+
+static inline u64
+spu_int_mask_get (struct spu *spu, int class)
+{
+	return spu_priv1_ops->int_mask_get(spu, class);
+}
+
+static inline void
+spu_int_stat_clear (struct spu *spu, int class, u64 stat)
+{
+	spu_priv1_ops->int_stat_clear(spu, class, stat);
+}
+
+static inline u64
+spu_int_stat_get (struct spu *spu, int class)
+{
+	return spu_priv1_ops->int_stat_get (spu, class);
+}
+
+static inline void
+spu_cpu_affinity_set (struct spu *spu, int cpu)
+{
+	spu_priv1_ops->cpu_affinity_set(spu, cpu);
+}
+
+static inline u64
+spu_mfc_dar_get (struct spu *spu)
+{
+	return spu_priv1_ops->mfc_dar_get(spu);
+}
+
+static inline u64
+spu_mfc_dsisr_get (struct spu *spu)
+{
+	return spu_priv1_ops->mfc_dsisr_get(spu);
+}
+
+static inline void
+spu_mfc_dsisr_set (struct spu *spu, u64 dsisr)
+{
+	spu_priv1_ops->mfc_dsisr_set(spu, dsisr);
+}
+
+static inline void
+spu_mfc_sdr_set (struct spu *spu, u64 sdr)
+{
+	spu_priv1_ops->mfc_sdr_set(spu, sdr);
+}
+
+static inline void
+spu_mfc_sr1_set (struct spu *spu, u64 sr1)
+{
+	spu_priv1_ops->mfc_sr1_set(spu, sr1);
+}
+
+static inline u64
+spu_mfc_sr1_get (struct spu *spu)
+{
+	return spu_priv1_ops->mfc_sr1_get(spu);
+}
+
+static inline void
+spu_mfc_tclass_id_set (struct spu *spu, u64 tclass_id)
+{
+	spu_priv1_ops->mfc_tclass_id_set(spu, tclass_id);
+}
+
+static inline u64
+spu_mfc_tclass_id_get (struct spu *spu)
+{
+	return spu_priv1_ops->mfc_tclass_id_get(spu);
+}
+
+static inline void
+spu_tlb_invalidate (struct spu *spu)
+{
+	spu_priv1_ops->tlb_invalidate(spu);
+}
+
+static inline void
+spu_resource_allocation_groupID_set (struct spu *spu, u64 id)
+{
+	spu_priv1_ops->resource_allocation_groupID_set(spu, id);
+}
+
+static inline u64
+spu_resource_allocation_groupID_get (struct spu *spu)
+{
+	return spu_priv1_ops->resource_allocation_groupID_get(spu);
+}
+
+static inline void
+spu_resource_allocation_enable_set (struct spu *spu, u64 enable)
+{
+	spu_priv1_ops->resource_allocation_enable_set(spu, enable);
+}
+
+static inline u64
+spu_resource_allocation_enable_get (struct spu *spu)
+{
+	return spu_priv1_ops->resource_allocation_enable_get(spu);
+}
+
+/* The declarations folowing are put here for convenience
+ * and only intended to be used by the platform setup code
+ * for initializing spu_priv1_ops.
+ */
+
+extern const struct spu_priv1_ops spu_priv1_mmio_ops;
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
new file mode 100644
index 0000000..eac85ce
--- /dev/null
+++ b/include/asm-powerpc/systbl.h
@@ -0,0 +1,306 @@
+/*
+ * List of powerpc syscalls. For the meaning of the _SPU suffix see
+ * arch/powerpc/platforms/cell/spu_callbacks.c
+ */
+
+SYSCALL(restart_syscall)
+SYSCALL(exit)
+PPC_SYS(fork)
+SYSCALL_SPU(read)
+SYSCALL_SPU(write)
+COMPAT_SYS_SPU(open)
+SYSCALL_SPU(close)
+COMPAT_SYS_SPU(waitpid)
+COMPAT_SYS_SPU(creat)
+SYSCALL_SPU(link)
+SYSCALL_SPU(unlink)
+COMPAT_SYS(execve)
+SYSCALL_SPU(chdir)
+COMPAT_SYS_SPU(time)
+SYSCALL_SPU(mknod)
+SYSCALL_SPU(chmod)
+SYSCALL_SPU(lchown)
+SYSCALL(ni_syscall)
+OLDSYS(stat)
+SYSX_SPU(sys_lseek,ppc32_lseek,sys_lseek)
+SYSCALL_SPU(getpid)
+COMPAT_SYS(mount)
+SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount)
+SYSCALL_SPU(setuid)
+SYSCALL_SPU(getuid)
+COMPAT_SYS_SPU(stime)
+COMPAT_SYS(ptrace)
+SYSCALL_SPU(alarm)
+OLDSYS(fstat)
+COMPAT_SYS(pause)
+COMPAT_SYS(utime)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(access)
+COMPAT_SYS_SPU(nice)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(sync)
+COMPAT_SYS_SPU(kill)
+SYSCALL_SPU(rename)
+COMPAT_SYS_SPU(mkdir)
+SYSCALL_SPU(rmdir)
+SYSCALL_SPU(dup)
+SYSCALL_SPU(pipe)
+COMPAT_SYS_SPU(times)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(brk)
+SYSCALL_SPU(setgid)
+SYSCALL_SPU(getgid)
+SYSCALL(signal)
+SYSCALL_SPU(geteuid)
+SYSCALL_SPU(getegid)
+SYSCALL(acct)
+SYSCALL(umount)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(ioctl)
+COMPAT_SYS_SPU(fcntl)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(setpgid)
+SYSCALL(ni_syscall)
+SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
+COMPAT_SYS_SPU(umask)
+SYSCALL_SPU(chroot)
+SYSCALL(ustat)
+SYSCALL_SPU(dup2)
+SYSCALL_SPU(getppid)
+SYSCALL_SPU(getpgrp)
+SYSCALL_SPU(setsid)
+SYS32ONLY(sigaction)
+SYSCALL_SPU(sgetmask)
+COMPAT_SYS_SPU(ssetmask)
+SYSCALL_SPU(setreuid)
+SYSCALL_SPU(setregid)
+SYS32ONLY(sigsuspend)
+COMPAT_SYS(sigpending)
+COMPAT_SYS_SPU(sethostname)
+COMPAT_SYS_SPU(setrlimit)
+COMPAT_SYS(old_getrlimit)
+COMPAT_SYS_SPU(getrusage)
+COMPAT_SYS_SPU(gettimeofday)
+COMPAT_SYS_SPU(settimeofday)
+COMPAT_SYS_SPU(getgroups)
+COMPAT_SYS_SPU(setgroups)
+SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select)
+SYSCALL_SPU(symlink)
+OLDSYS(lstat)
+COMPAT_SYS_SPU(readlink)
+SYSCALL(uselib)
+SYSCALL(swapon)
+SYSCALL(reboot)
+SYSX(sys_ni_syscall,old32_readdir,old_readdir)
+SYSCALL_SPU(mmap)
+SYSCALL_SPU(munmap)
+SYSCALL_SPU(truncate)
+SYSCALL_SPU(ftruncate)
+SYSCALL_SPU(fchmod)
+SYSCALL_SPU(fchown)
+COMPAT_SYS_SPU(getpriority)
+COMPAT_SYS_SPU(setpriority)
+SYSCALL(ni_syscall)
+COMPAT_SYS(statfs)
+COMPAT_SYS(fstatfs)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(socketcall)
+COMPAT_SYS_SPU(syslog)
+COMPAT_SYS_SPU(setitimer)
+COMPAT_SYS_SPU(getitimer)
+COMPAT_SYS_SPU(newstat)
+COMPAT_SYS_SPU(newlstat)
+COMPAT_SYS_SPU(newfstat)
+SYSX(sys_ni_syscall,sys_uname,sys_uname)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(vhangup)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(wait4)
+SYSCALL(swapoff)
+COMPAT_SYS_SPU(sysinfo)
+COMPAT_SYS(ipc)
+SYSCALL_SPU(fsync)
+SYS32ONLY(sigreturn)
+PPC_SYS(clone)
+COMPAT_SYS_SPU(setdomainname)
+PPC_SYS_SPU(newuname)
+SYSCALL(ni_syscall)
+COMPAT_SYS_SPU(adjtimex)
+SYSCALL_SPU(mprotect)
+SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask)
+SYSCALL(ni_syscall)
+SYSCALL(init_module)
+SYSCALL(delete_module)
+SYSCALL(ni_syscall)
+SYSCALL(quotactl)
+COMPAT_SYS_SPU(getpgid)
+SYSCALL_SPU(fchdir)
+SYSCALL_SPU(bdflush)
+COMPAT_SYS(sysfs)
+SYSX_SPU(ppc64_personality,ppc64_personality,sys_personality)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(setfsuid)
+SYSCALL_SPU(setfsgid)
+SYSCALL_SPU(llseek)
+COMPAT_SYS_SPU(getdents)
+SYSX_SPU(sys_select,ppc32_select,ppc_select)
+SYSCALL_SPU(flock)
+SYSCALL_SPU(msync)
+COMPAT_SYS_SPU(readv)
+COMPAT_SYS_SPU(writev)
+COMPAT_SYS_SPU(getsid)
+SYSCALL_SPU(fdatasync)
+COMPAT_SYS(sysctl)
+SYSCALL_SPU(mlock)
+SYSCALL_SPU(munlock)
+SYSCALL_SPU(mlockall)
+SYSCALL_SPU(munlockall)
+COMPAT_SYS_SPU(sched_setparam)
+COMPAT_SYS_SPU(sched_getparam)
+COMPAT_SYS_SPU(sched_setscheduler)
+COMPAT_SYS_SPU(sched_getscheduler)
+SYSCALL_SPU(sched_yield)
+COMPAT_SYS_SPU(sched_get_priority_max)
+COMPAT_SYS_SPU(sched_get_priority_min)
+COMPAT_SYS_SPU(sched_rr_get_interval)
+COMPAT_SYS_SPU(nanosleep)
+SYSCALL_SPU(mremap)
+SYSCALL_SPU(setresuid)
+SYSCALL_SPU(getresuid)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(poll)
+COMPAT_SYS(nfsservctl)
+SYSCALL_SPU(setresgid)
+SYSCALL_SPU(getresgid)
+COMPAT_SYS_SPU(prctl)
+COMPAT_SYS(rt_sigreturn)
+COMPAT_SYS(rt_sigaction)
+COMPAT_SYS(rt_sigprocmask)
+COMPAT_SYS(rt_sigpending)
+COMPAT_SYS(rt_sigtimedwait)
+COMPAT_SYS(rt_sigqueueinfo)
+COMPAT_SYS(rt_sigsuspend)
+COMPAT_SYS_SPU(pread64)
+COMPAT_SYS_SPU(pwrite64)
+SYSCALL_SPU(chown)
+SYSCALL_SPU(getcwd)
+SYSCALL_SPU(capget)
+SYSCALL_SPU(capset)
+COMPAT_SYS(sigaltstack)
+SYSX_SPU(sys_sendfile64,compat_sys_sendfile,sys_sendfile)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+PPC_SYS(vfork)
+COMPAT_SYS_SPU(getrlimit)
+COMPAT_SYS_SPU(readahead)
+SYS32ONLY(mmap2)
+SYS32ONLY(truncate64)
+SYS32ONLY(ftruncate64)
+SYSX(sys_ni_syscall,sys_stat64,sys_stat64)
+SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64)
+SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64)
+SYSCALL(pciconfig_read)
+SYSCALL(pciconfig_write)
+SYSCALL(pciconfig_iobase)
+SYSCALL(ni_syscall)
+SYSCALL_SPU(getdents64)
+SYSCALL_SPU(pivot_root)
+SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64)
+SYSCALL_SPU(madvise)
+SYSCALL_SPU(mincore)
+SYSCALL_SPU(gettid)
+SYSCALL_SPU(tkill)
+SYSCALL_SPU(setxattr)
+SYSCALL_SPU(lsetxattr)
+SYSCALL_SPU(fsetxattr)
+SYSCALL_SPU(getxattr)
+SYSCALL_SPU(lgetxattr)
+SYSCALL_SPU(fgetxattr)
+SYSCALL_SPU(listxattr)
+SYSCALL_SPU(llistxattr)
+SYSCALL_SPU(flistxattr)
+SYSCALL_SPU(removexattr)
+SYSCALL_SPU(lremovexattr)
+SYSCALL_SPU(fremovexattr)
+COMPAT_SYS_SPU(futex)
+COMPAT_SYS_SPU(sched_setaffinity)
+COMPAT_SYS_SPU(sched_getaffinity)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYS32ONLY(sendfile64)
+COMPAT_SYS_SPU(io_setup)
+SYSCALL_SPU(io_destroy)
+COMPAT_SYS_SPU(io_getevents)
+COMPAT_SYS_SPU(io_submit)
+SYSCALL_SPU(io_cancel)
+SYSCALL(set_tid_address)
+SYSX_SPU(sys_fadvise64,ppc32_fadvise64,sys_fadvise64)
+SYSCALL(exit_group)
+SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie)
+SYSCALL_SPU(epoll_create)
+SYSCALL_SPU(epoll_ctl)
+SYSCALL_SPU(epoll_wait)
+SYSCALL_SPU(remap_file_pages)
+SYSX_SPU(sys_timer_create,compat_sys_timer_create,sys_timer_create)
+COMPAT_SYS_SPU(timer_settime)
+COMPAT_SYS_SPU(timer_gettime)
+SYSCALL_SPU(timer_getoverrun)
+SYSCALL_SPU(timer_delete)
+COMPAT_SYS_SPU(clock_settime)
+COMPAT_SYS_SPU(clock_gettime)
+COMPAT_SYS_SPU(clock_getres)
+COMPAT_SYS_SPU(clock_nanosleep)
+SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext)
+COMPAT_SYS_SPU(tgkill)
+COMPAT_SYS_SPU(utimes)
+COMPAT_SYS_SPU(statfs64)
+COMPAT_SYS_SPU(fstatfs64)
+SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
+PPC_SYS_SPU(rtas)
+OLDSYS(debug_setcontext)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+COMPAT_SYS(mbind)
+COMPAT_SYS(get_mempolicy)
+COMPAT_SYS(set_mempolicy)
+COMPAT_SYS(mq_open)
+SYSCALL(mq_unlink)
+COMPAT_SYS(mq_timedsend)
+COMPAT_SYS(mq_timedreceive)
+COMPAT_SYS(mq_notify)
+COMPAT_SYS(mq_getsetattr)
+COMPAT_SYS(kexec_load)
+COMPAT_SYS(add_key)
+COMPAT_SYS(request_key)
+COMPAT_SYS(keyctl)
+COMPAT_SYS(waitid)
+COMPAT_SYS(ioprio_set)
+COMPAT_SYS(ioprio_get)
+SYSCALL(inotify_init)
+SYSCALL(inotify_add_watch)
+SYSCALL(inotify_rm_watch)
+SYSCALL(spu_run)
+SYSCALL(spu_create)
+COMPAT_SYS(pselect6)
+COMPAT_SYS(ppoll)
+SYSCALL_SPU(unshare)
+SYSCALL_SPU(splice)
+SYSCALL_SPU(tee)
+SYSCALL_SPU(vmsplice)
+COMPAT_SYS_SPU(openat)
+SYSCALL_SPU(mkdirat)
+SYSCALL_SPU(mknodat)
+SYSCALL_SPU(fchownat)
+COMPAT_SYS_SPU(futimesat)
+SYSX_SPU(sys_newfstatat, sys_fstatat64, sys_fstatat64)
+SYSCALL_SPU(unlinkat)
+SYSCALL_SPU(renameat)
+SYSCALL_SPU(linkat)
+SYSCALL_SPU(symlinkat)
+SYSCALL_SPU(readlinkat)
+SYSCALL_SPU(fchmodat)
+SYSCALL_SPU(faccessat)
+COMPAT_SYS_SPU(get_robust_list)
+COMPAT_SYS_SPU(set_robust_list)
diff --git a/include/asm-powerpc/tce.h b/include/asm-powerpc/tce.h
index 6fa200a..c9483ad 100644
--- a/include/asm-powerpc/tce.h
+++ b/include/asm-powerpc/tce.h
@@ -35,32 +35,15 @@
 #define TCE_PAGE_SIZE	(1 << TCE_SHIFT)
 #define TCE_PAGE_FACTOR	(PAGE_SHIFT - TCE_SHIFT)
 
+#define TCE_ENTRY_SIZE		8		/* each TCE is 64 bits */
 
-/* tce_entry
- * Used by pSeries (SMP) and iSeries/pSeries LPAR, but there it's
- * abstracted so layout is irrelevant.
- */
-union tce_entry {
-   	unsigned long te_word;
-	struct {
-		unsigned int  tb_cacheBits :6;	/* Cache hash bits - not used */
-		unsigned int  tb_rsvd      :6;
-		unsigned long tb_rpn       :40;	/* Real page number */
-		unsigned int  tb_valid     :1;	/* Tce is valid (vb only) */
-		unsigned int  tb_allio     :1;	/* Tce is valid for all lps (vb only) */
-		unsigned int  tb_lpindex   :8;	/* LpIndex for user of TCE (vb only) */
-		unsigned int  tb_pciwr     :1;	/* Write allowed (pci only) */
-		unsigned int  tb_rdwr      :1;	/* Read allowed  (pci), Write allowed (vb) */
-	} te_bits;
-#define te_cacheBits te_bits.tb_cacheBits
-#define te_rpn       te_bits.tb_rpn
-#define te_valid     te_bits.tb_valid
-#define te_allio     te_bits.tb_allio
-#define te_lpindex   te_bits.tb_lpindex
-#define te_pciwr     te_bits.tb_pciwr
-#define te_rdwr      te_bits.tb_rdwr
-};
-
+#define TCE_RPN_MASK		0xfffffffffful  /* 40-bit RPN (4K pages) */
+#define TCE_RPN_SHIFT		12
+#define TCE_VALID		0x800		/* TCE valid */
+#define TCE_ALLIO		0x400		/* TCE valid for all lpars */
+#define TCE_PCI_WRITE		0x2		/* write from PCI allowed */
+#define TCE_PCI_READ		0x1		/* read from PCI allowed */
+#define TCE_VB_WRITE		0x1		/* write from VB allowed */
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_TCE_H */
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 88b553c..d339e2e 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -21,7 +21,6 @@
 #define THREAD_SIZE		(1 << THREAD_SHIFT)
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <asm/processor.h>
 #include <asm/page.h>
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h
index 912118d..4463148 100644
--- a/include/asm-powerpc/time.h
+++ b/include/asm-powerpc/time.h
@@ -14,7 +14,6 @@
 #define __POWERPC_TIME_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/percpu.h>
 
diff --git a/include/asm-powerpc/timex.h b/include/asm-powerpc/timex.h
index c02d15ac..3b9a8e7 100644
--- a/include/asm-powerpc/timex.h
+++ b/include/asm-powerpc/timex.h
@@ -7,7 +7,6 @@
  * PowerPC architecture timex specifications
  */
 
-#include <linux/config.h>
 #include <asm/cputable.h>
 
 #define CLOCK_TICK_RATE	1024000 /* Underlying HZ */
diff --git a/include/asm-powerpc/tlb.h b/include/asm-powerpc/tlb.h
index 601a53c..4e2a834 100644
--- a/include/asm-powerpc/tlb.h
+++ b/include/asm-powerpc/tlb.h
@@ -13,7 +13,6 @@
 #define _ASM_POWERPC_TLB_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #ifndef __powerpc64__
 #include <asm/pgtable.h>
 #endif
diff --git a/include/asm-powerpc/tlbflush.h b/include/asm-powerpc/tlbflush.h
index a2998ee..93c7d0c 100644
--- a/include/asm-powerpc/tlbflush.h
+++ b/include/asm-powerpc/tlbflush.h
@@ -17,7 +17,6 @@
  */
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 struct mm_struct;
 
diff --git a/include/asm-powerpc/topology.h b/include/asm-powerpc/topology.h
index 87362a0..bbc3844 100644
--- a/include/asm-powerpc/topology.h
+++ b/include/asm-powerpc/topology.h
@@ -2,7 +2,6 @@
 #define _ASM_POWERPC_TOPOLOGY_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 struct sys_device;
 struct device_node;
@@ -32,8 +31,13 @@
 
 int of_node_to_nid(struct device_node *device);
 
-#define pcibus_to_node(node)    (-1)
-#define pcibus_to_cpumask(bus)	(cpu_online_map)
+struct pci_bus;
+extern int pcibus_to_node(struct pci_bus *bus);
+
+#define pcibus_to_cpumask(bus)	(pcibus_to_node(bus) == -1 ? \
+					CPU_MASK_ALL : \
+					node_to_cpumask(pcibus_to_node(bus)) \
+				)
 
 /* sched_domains SD_NODE_INIT for PPC64 machines */
 #define SD_NODE_INIT (struct sched_domain) {		\
@@ -89,5 +93,10 @@
 
 #endif /* CONFIG_NUMA */
 
+#ifdef CONFIG_SMP
+#include <asm/cputable.h>
+#define smt_capable() 		(cpu_has_feature(CPU_FTR_SMT))
+#endif
+
 #endif /* __KERNEL__ */
 #endif	/* _ASM_POWERPC_TOPOLOGY_H */
diff --git a/include/asm-powerpc/types.h b/include/asm-powerpc/types.h
index baabba9..d6fb56b 100644
--- a/include/asm-powerpc/types.h
+++ b/include/asm-powerpc/types.h
@@ -64,7 +64,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
diff --git a/include/asm-powerpc/udbg.h b/include/asm-powerpc/udbg.h
index 5c4236c3..19a1517 100644
--- a/include/asm-powerpc/udbg.h
+++ b/include/asm-powerpc/udbg.h
@@ -23,7 +23,8 @@
 extern int udbg_read(char *buf, int buflen);
 
 extern void register_early_udbg_console(void);
-extern void udbg_printf(const char *fmt, ...);
+extern void udbg_printf(const char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
 extern void udbg_progress(char *s, unsigned short hex);
 
 extern void udbg_init_uart(void __iomem *comport, unsigned int speed,
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index edde246..eb66eae 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -324,12 +324,12 @@
 #define __NR_get_robust_list	299
 #define __NR_set_robust_list	300
 
+#ifdef __KERNEL__
+
 #define __NR_syscalls		301
 
-#ifdef __KERNEL__
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
-#endif
 
 #ifndef __ASSEMBLY__
 
@@ -441,9 +441,7 @@
 	__syscall_nr(6, type, name, arg1, arg2, arg3, arg4, arg5, arg6); \
 }
 
-#ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
 #include <linux/linkage.h>
@@ -499,8 +497,8 @@
 #define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall")
 #endif
 
-#endif		/* __KERNEL__ */
 
 #endif		/* __ASSEMBLY__ */
+#endif		/* __KERNEL__ */
 
 #endif /* _ASM_PPC_UNISTD_H_ */
diff --git a/include/asm-powerpc/vga.h b/include/asm-powerpc/vga.h
index f8d350a..a2eac40 100644
--- a/include/asm-powerpc/vga.h
+++ b/include/asm-powerpc/vga.h
@@ -12,7 +12,6 @@
 
 #include <asm/io.h>
 
-#include <linux/config.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
 
@@ -42,9 +41,9 @@
 extern unsigned long vgacon_remap_base;
 
 #ifdef __powerpc64__
-#define VGA_MAP_MEM(x) ((unsigned long) ioremap((x), 0))
+#define VGA_MAP_MEM(x,s) ((unsigned long) ioremap((x), s))
 #else
-#define VGA_MAP_MEM(x) (x + vgacon_remap_base)
+#define VGA_MAP_MEM(x,s) (x + vgacon_remap_base)
 #endif
 
 #define vga_readb(x) (*(x))
diff --git a/include/asm-powerpc/vio.h b/include/asm-powerpc/vio.h
index 0544ece..dc9bd101 100644
--- a/include/asm-powerpc/vio.h
+++ b/include/asm-powerpc/vio.h
@@ -15,7 +15,6 @@
 #define _ASM_POWERPC_VIO_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/device.h>
@@ -64,32 +63,22 @@
 	struct device_driver driver;
 };
 
-struct vio_bus_ops {
-	int (*match)(const struct vio_device_id *id, const struct vio_dev *dev);
-	void (*unregister_device)(struct vio_dev *);
-	void (*release_device)(struct device *);
-};
-
 extern struct dma_mapping_ops vio_dma_ops;
 extern struct bus_type vio_bus_type;
-extern struct vio_dev vio_bus_device;
 
 extern int vio_register_driver(struct vio_driver *drv);
 extern void vio_unregister_driver(struct vio_driver *drv);
 
-extern struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev);
 extern void __devinit vio_unregister_device(struct vio_dev *dev);
 
-extern int vio_bus_init(struct vio_bus_ops *);
-
-#ifdef CONFIG_PPC_PSERIES
 struct device_node;
 
 extern struct vio_dev * __devinit vio_register_device_node(
 		struct device_node *node_vdev);
-extern struct vio_dev *vio_find_node(struct device_node *vnode);
-extern const void *vio_get_attribute(struct vio_dev *vdev, void *which,
+extern const void *vio_get_attribute(struct vio_dev *vdev, char *which,
 		int *length);
+#ifdef CONFIG_PPC_PSERIES
+extern struct vio_dev *vio_find_node(struct device_node *vnode);
 extern int vio_enable_interrupts(struct vio_dev *dev);
 extern int vio_disable_interrupts(struct vio_dev *dev);
 #endif
diff --git a/include/asm-ppc/amigahw.h b/include/asm-ppc/amigahw.h
index 8c98945..90fd127 100644
--- a/include/asm-ppc/amigahw.h
+++ b/include/asm-ppc/amigahw.h
@@ -2,7 +2,6 @@
 #ifndef __ASMPPC_AMIGAHW_H
 #define __ASMPPC_AMIGAHW_H
 
-#include <linux/config.h>
 #include <asm-m68k/amigahw.h>
 
 #undef CHIP_PHYSADDR
diff --git a/include/asm-ppc/bootinfo.h b/include/asm-ppc/bootinfo.h
index 93d955c..2ace4a7 100644
--- a/include/asm-ppc/bootinfo.h
+++ b/include/asm-ppc/bootinfo.h
@@ -9,7 +9,6 @@
 #ifndef _PPC_BOOTINFO_H
 #define _PPC_BOOTINFO_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 #if defined(CONFIG_APUS) && !defined(__BOOTER__)
diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
index 31f3629..3247bea 100644
--- a/include/asm-ppc/commproc.h
+++ b/include/asm-ppc/commproc.h
@@ -17,7 +17,6 @@
 #ifndef __CPM_8XX__
 #define __CPM_8XX__
 
-#include <linux/config.h>
 #include <asm/8xx_immap.h>
 #include <asm/ptrace.h>
 
diff --git a/include/asm-ppc/floppy.h b/include/asm-ppc/floppy.h
index 8ccd4a2..2ba191e 100644
--- a/include/asm-ppc/floppy.h
+++ b/include/asm-ppc/floppy.h
@@ -99,10 +99,8 @@
 		return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
 						   "floppy", NULL);
 	else
-		return request_irq(FLOPPY_IRQ, floppy_interrupt,
-						   SA_INTERRUPT|SA_SAMPLE_RANDOM,
-						   "floppy", NULL);
-
+		return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT,
+				   "floppy", NULL);
 }
 
 static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
diff --git a/include/asm-ppc/ibm403.h b/include/asm-ppc/ibm403.h
index bf6efa0..c9c5d53 100644
--- a/include/asm-ppc/ibm403.h
+++ b/include/asm-ppc/ibm403.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_IBM403_H__
 #define __ASM_IBM403_H__
 
-#include <linux/config.h>
 
 #if defined(CONFIG_403GCX)
 
diff --git a/include/asm-ppc/ibm44x.h b/include/asm-ppc/ibm44x.h
index 3acc382..7818b54 100644
--- a/include/asm-ppc/ibm44x.h
+++ b/include/asm-ppc/ibm44x.h
@@ -17,7 +17,6 @@
 #ifndef __ASM_IBM44x_H__
 #define __ASM_IBM44x_H__
 
-#include <linux/config.h>
 
 #ifndef NR_BOARD_IRQS
 #define NR_BOARD_IRQS 0
diff --git a/include/asm-ppc/ibm4xx.h b/include/asm-ppc/ibm4xx.h
index 38f9971..cf62b69 100644
--- a/include/asm-ppc/ibm4xx.h
+++ b/include/asm-ppc/ibm4xx.h
@@ -14,7 +14,6 @@
 #ifndef __ASM_IBM4XX_H__
 #define __ASM_IBM4XX_H__
 
-#include <linux/config.h>
 #include <asm/types.h>
 
 #ifdef CONFIG_40x
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index b919d8f..89c6f1b 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -2,7 +2,6 @@
 #ifndef _PPC_IO_H
 #define _PPC_IO_H
 
-#include <linux/config.h>
 #include <linux/string.h>
 #include <linux/types.h>
 
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index e1a0a7b..da77467 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -2,7 +2,6 @@
 #ifndef _PPC_MACHDEP_H
 #define _PPC_MACHDEP_H
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kexec.h>
 
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index 9205db4..14584e5 100644
--- a/include/asm-ppc/mmu.h
+++ b/include/asm-ppc/mmu.h
@@ -6,7 +6,6 @@
 #ifndef _PPC_MMU_H_
 #define _PPC_MMU_H_
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 
@@ -24,25 +23,18 @@
 #define PHYS_FMT	"%16Lx"
 #endif
 
-/* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
+typedef struct {
+	unsigned long id;
+	unsigned long vdso_base;
+} mm_context_t;
 
 /* Hardware Page Table Entry */
 typedef struct _PTE {
-#ifdef CONFIG_PPC64BRIDGE
-	unsigned long long vsid:52;
-	unsigned long api:5;
-	unsigned long :5;
-	unsigned long h:1;
-	unsigned long v:1;
-	unsigned long long rpn:52;
-#else /* CONFIG_PPC64BRIDGE */
 	unsigned long v:1;	/* Entry is valid */
 	unsigned long vsid:24;	/* Virtual segment identifier */
 	unsigned long h:1;	/* Hash algorithm indicator */
 	unsigned long api:6;	/* Abbreviated page index */
 	unsigned long rpn:20;	/* Real (physical) page number */
-#endif /* CONFIG_PPC64BRIDGE */
 	unsigned long    :3;	/* Unused */
 	unsigned long r:1;	/* Referenced */
 	unsigned long c:1;	/* Changed */
@@ -83,11 +75,7 @@
 } P601_BATU;
 
 typedef struct _BATU {		/* Upper part of BAT (all except 601) */
-#ifdef CONFIG_PPC64BRIDGE
-	unsigned long long bepi:47;
-#else /* CONFIG_PPC64BRIDGE */
 	unsigned long bepi:15;	/* Effective page index (virtual address) */
-#endif /* CONFIG_PPC64BRIDGE */
 	unsigned long :4;	/* Unused */
 	unsigned long bl:11;	/* Block size mask */
 	unsigned long vs:1;	/* Supervisor valid */
@@ -102,11 +90,7 @@
 } P601_BATL;
 
 typedef struct _BATL {		/* Lower part of BAT (all except 601) */
-#ifdef CONFIG_PPC64BRIDGE
-	unsigned long long brpn:47;
-#else /* CONFIG_PPC64BRIDGE */
 	unsigned long brpn:15;	/* Real page index (physical address) */
-#endif /* CONFIG_PPC64BRIDGE */
 	unsigned long :10;	/* Unused */
 	unsigned long w:1;	/* Write-thru cache */
 	unsigned long i:1;	/* Cache inhibit */
diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
index 4f152cc..2bc8589 100644
--- a/include/asm-ppc/mmu_context.h
+++ b/include/asm-ppc/mmu_context.h
@@ -2,7 +2,6 @@
 #ifndef __PPC_MMU_CONTEXT_H
 #define __PPC_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/atomic.h>
 #include <asm/bitops.h>
 #include <asm/mmu.h>
@@ -71,7 +70,7 @@
 #else
 
 /* PPC 6xx, 7xx CPUs */
-#define NO_CONTEXT      	((mm_context_t) -1)
+#define NO_CONTEXT      	((unsigned long) -1)
 #define LAST_CONTEXT    	32767
 #define FIRST_CONTEXT    	1
 #endif
@@ -86,7 +85,7 @@
  * can be used for debugging on all processors (if you happen to have
  * an Abatron).
  */
-extern void set_context(mm_context_t context, pgd_t *pgd);
+extern void set_context(unsigned long contextid, pgd_t *pgd);
 
 /*
  * Bitmap of contexts in use.
@@ -99,7 +98,7 @@
  * Its use is an optimization only, we can't rely on this context
  * number to be free, but it usually will be.
  */
-extern mm_context_t next_mmu_context;
+extern unsigned long next_mmu_context;
 
 /*
  * If we don't have sufficient contexts to give one to every task
@@ -118,9 +117,9 @@
  */
 static inline void get_mmu_context(struct mm_struct *mm)
 {
-	mm_context_t ctx;
+	unsigned long ctx;
 
-	if (mm->context != NO_CONTEXT)
+	if (mm->context.id != NO_CONTEXT)
 		return;
 #ifdef FEW_CONTEXTS
 	while (atomic_dec_if_positive(&nr_free_contexts) < 0)
@@ -133,7 +132,7 @@
 			ctx = 0;
 	}
 	next_mmu_context = (ctx + 1) & LAST_CONTEXT;
-	mm->context = ctx;
+	mm->context.id = ctx;
 #ifdef FEW_CONTEXTS
 	context_mm[ctx] = mm;
 #endif
@@ -142,7 +141,12 @@
 /*
  * Set up the context for a new address space.
  */
-#define init_new_context(tsk,mm)	(((mm)->context = NO_CONTEXT), 0)
+static inline int init_new_context(struct task_struct *t, struct mm_struct *mm)
+{
+	mm->context.id = NO_CONTEXT;
+	mm->context.vdso_base = 0;
+	return 0;
+}
 
 /*
  * We're finished using the context for an address space.
@@ -150,9 +154,9 @@
 static inline void destroy_context(struct mm_struct *mm)
 {
 	preempt_disable();
-	if (mm->context != NO_CONTEXT) {
-		clear_bit(mm->context, context_map);
-		mm->context = NO_CONTEXT;
+	if (mm->context.id != NO_CONTEXT) {
+		clear_bit(mm->context.id, context_map);
+		mm->context.id = NO_CONTEXT;
 #ifdef FEW_CONTEXTS
 		atomic_inc(&nr_free_contexts);
 #endif
@@ -180,7 +184,7 @@
 
 	/* Setup new userspace context */
 	get_mmu_context(next);
-	set_context(next->context, next->pgd);
+	set_context(next->context.id, next->pgd);
 }
 
 #define deactivate_mm(tsk,mm)	do { } while (0)
diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
index 6ba69a8..4b93481e 100644
--- a/include/asm-ppc/mpc8260.h
+++ b/include/asm-ppc/mpc8260.h
@@ -8,7 +8,6 @@
 #ifndef __ASM_PPC_MPC8260_H__
 #define __ASM_PPC_MPC8260_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_8260
 
diff --git a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
index 3c23fc4..02ed2c3 100644
--- a/include/asm-ppc/mpc83xx.h
+++ b/include/asm-ppc/mpc83xx.h
@@ -17,7 +17,6 @@
 #ifndef __ASM_MPC83xx_H__
 #define __ASM_MPC83xx_H__
 
-#include <linux/config.h>
 #include <asm/mmu.h>
 
 #ifdef CONFIG_83xx
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index f47002a..9b48511 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -17,7 +17,6 @@
 #ifndef __ASM_MPC85xx_H__
 #define __ASM_MPC85xx_H__
 
-#include <linux/config.h>
 #include <asm/mmu.h>
 
 #ifdef CONFIG_85xx
@@ -28,6 +27,9 @@
 #if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
 #include <platforms/85xx/mpc8555_cds.h>
 #endif
+#ifdef CONFIG_MPC85xx_CDS
+#include <platforms/85xx/mpc85xx_cds.h>
+#endif
 #ifdef CONFIG_MPC8560_ADS
 #include <platforms/85xx/mpc8560_ads.h>
 #endif
diff --git a/include/asm-ppc/mpc8xx.h b/include/asm-ppc/mpc8xx.h
index 3515a7f..adcce33 100644
--- a/include/asm-ppc/mpc8xx.h
+++ b/include/asm-ppc/mpc8xx.h
@@ -8,7 +8,6 @@
 #ifndef __CONFIG_8xx_DEFS
 #define __CONFIG_8xx_DEFS
 
-#include <linux/config.h>
 
 #ifdef CONFIG_8xx
 
diff --git a/include/asm-ppc/mv64x60.h b/include/asm-ppc/mv64x60.h
index 4f2405b..663edbe 100644
--- a/include/asm-ppc/mv64x60.h
+++ b/include/asm-ppc/mv64x60.h
@@ -17,7 +17,6 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/config.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
diff --git a/include/asm-ppc/ocp.h b/include/asm-ppc/ocp.h
index 983116f..3be5d76 100644
--- a/include/asm-ppc/ocp.h
+++ b/include/asm-ppc/ocp.h
@@ -26,7 +26,6 @@
 
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/config.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/device.h>
 
diff --git a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h
index ec2f466..a4fe962 100644
--- a/include/asm-ppc/open_pic.h
+++ b/include/asm-ppc/open_pic.h
@@ -12,7 +12,6 @@
 #ifndef _PPC_KERNEL_OPEN_PIC_H
 #define _PPC_KERNEL_OPEN_PIC_H
 
-#include <linux/config.h>
 #include <linux/irq.h>
 
 #define OPENPIC_SIZE	0x40000
diff --git a/include/asm-ppc/page.h b/include/asm-ppc/page.h
index 0fb68a0..0b19af8 100644
--- a/include/asm-ppc/page.h
+++ b/include/asm-ppc/page.h
@@ -1,7 +1,6 @@
 #ifndef _PPC_PAGE_H
 #define _PPC_PAGE_H
 
-#include <linux/config.h>
 #include <asm/asm-compat.h>
 
 /* PAGE_SHIFT determines the page size */
@@ -15,7 +14,6 @@
 #define PAGE_MASK	(~((1 << PAGE_SHIFT) - 1))
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 
 /* This must match what is in arch/ppc/Makefile */
 #define PAGE_OFFSET	CONFIG_KERNEL_START
diff --git a/include/asm-ppc/pc_serial.h b/include/asm-ppc/pc_serial.h
index 8f994f9..81a2d0f 100644
--- a/include/asm-ppc/pc_serial.h
+++ b/include/asm-ppc/pc_serial.h
@@ -9,7 +9,6 @@
  * anyone using any of those on a PPC platform.  -- paulus
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff --git a/include/asm-ppc/pgalloc.h b/include/asm-ppc/pgalloc.h
index bdefd1c..44d88a9 100644
--- a/include/asm-ppc/pgalloc.h
+++ b/include/asm-ppc/pgalloc.h
@@ -2,7 +2,6 @@
 #ifndef _PPC_PGALLOC_H
 #define _PPC_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 
 extern void __bad_pte(pmd_t *pmd);
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index 570b355..51fa7c6 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -4,7 +4,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 #include <linux/sched.h>
@@ -663,7 +662,7 @@
 	return (old & _PAGE_ACCESSED) != 0;
 }
 #define ptep_test_and_clear_young(__vma, __addr, __ptep) \
-	__ptep_test_and_clear_young((__vma)->vm_mm->context, __addr, __ptep)
+	__ptep_test_and_clear_young((__vma)->vm_mm->context.id, __addr, __ptep)
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
diff --git a/include/asm-ppc/ppc4xx_dma.h b/include/asm-ppc/ppc4xx_dma.h
index 46a086f..935d1e0 100644
--- a/include/asm-ppc/ppc4xx_dma.h
+++ b/include/asm-ppc/ppc4xx_dma.h
@@ -24,7 +24,6 @@
 #ifndef __ASMPPC_PPC4xx_DMA_H
 #define __ASMPPC_PPC4xx_DMA_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/mmu.h>
 #include <asm/ibm4xx.h>
diff --git a/include/asm-ppc/ppc4xx_pic.h b/include/asm-ppc/ppc4xx_pic.h
index c16c7f8..e442612 100644
--- a/include/asm-ppc/ppc4xx_pic.h
+++ b/include/asm-ppc/ppc4xx_pic.h
@@ -17,7 +17,6 @@
 #ifndef	__PPC4XX_PIC_H__
 #define	__PPC4XX_PIC_H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index b74af54..8a59f88 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -6,7 +6,6 @@
 #ifndef __ASM_SERIAL_H__
 #define __ASM_SERIAL_H__
 
-#include <linux/config.h>
 
 #if defined(CONFIG_EV64260)
 #include <platforms/ev64260.h>
diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h
index 30e9268..0b7fa89 100644
--- a/include/asm-ppc/smp.h
+++ b/include/asm-ppc/smp.h
@@ -10,7 +10,6 @@
 #ifndef _PPC_SMP_H
 #define _PPC_SMP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 #include <linux/errno.h>
diff --git a/include/asm-ppc/time.h b/include/asm-ppc/time.h
index c861123..f7eadf6 100644
--- a/include/asm-ppc/time.h
+++ b/include/asm-ppc/time.h
@@ -9,7 +9,6 @@
 #ifndef __ASM_TIME_H__
 #define __ASM_TIME_H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/rtc.h>
 #include <linux/threads.h>
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
index ca092ff..4d2b126 100644
--- a/include/asm-s390/bitops.h
+++ b/include/asm-s390/bitops.h
@@ -12,7 +12,6 @@
  *    Copyright (C) 1992, Linus Torvalds
  *
  */
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 /*
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h
index dae1dd4..2d09950 100644
--- a/include/asm-s390/cmb.h
+++ b/include/asm-s390/cmb.h
@@ -47,7 +47,7 @@
 /* reset channel measurement block */
 #define BIODASDRESETCMB		_IO(DASD_IOCTL_LETTER,34)
 /* read channel measurement data */
-#define BIODASDREADCMB		_IOWR(DASD_IOCTL_LETTER,32,u64)
+#define BIODASDREADCMB		_IOWR(DASD_IOCTL_LETTER,32,__u64)
 /* read channel measurement data */
 #define BIODASDREADALLCMB	_IOWR(DASD_IOCTL_LETTER,33,struct cmbdata)
 
diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
index 23450ed..7f1ef99 100644
--- a/include/asm-s390/debug.h
+++ b/include/asm-s390/debug.h
@@ -9,7 +9,6 @@
 #ifndef DEBUG_H
 #define DEBUG_H
 
-#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/string.h>
 
diff --git a/include/asm-s390/hardirq.h b/include/asm-s390/hardirq.h
index 6792c55..e84b7ef 100644
--- a/include/asm-s390/hardirq.h
+++ b/include/asm-s390/hardirq.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/sched.h>
 #include <linux/cache.h>
diff --git a/include/asm-s390/idals.h b/include/asm-s390/idals.h
index 8038858..e82c10e 100644
--- a/include/asm-s390/idals.h
+++ b/include/asm-s390/idals.h
@@ -13,7 +13,6 @@
 #ifndef _S390_IDALS_H
 #define _S390_IDALS_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/types.h>
diff --git a/include/asm-s390/io.h b/include/asm-s390/io.h
index b05825d..d4614b3 100644
--- a/include/asm-s390/io.h
+++ b/include/asm-s390/io.h
@@ -86,20 +86,25 @@
 #define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
 #define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
 #define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
+#define readq(addr) (*(volatile unsigned long long *) __io_virt(addr))
 
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
+#define readq_relaxed(addr) readq(addr)
 #define __raw_readb readb
 #define __raw_readw readw
 #define __raw_readl readl
+#define __raw_readq readq
 
 #define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
 #define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
 #define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+#define writeq(b,addr) (*(volatile unsigned long long *) __io_virt(addr) = (b))
 #define __raw_writeb writeb
 #define __raw_writew writew
 #define __raw_writel writel
+#define __raw_writeq writeq
 
 #define memset_io(a,b,c)        memset(__io_virt(a),(b),(c))
 #define memcpy_fromio(a,b,c)    memcpy((a),__io_virt(b),(c))
diff --git a/include/asm-s390/irq.h b/include/asm-s390/irq.h
index 916a1aa..bd1a721 100644
--- a/include/asm-s390/irq.h
+++ b/include/asm-s390/irq.h
@@ -21,10 +21,6 @@
 
 #define touch_nmi_watchdog() do { } while(0)
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif /* __KERNEL__ */
 #endif
 
diff --git a/include/asm-s390/local.h b/include/asm-s390/local.h
index cf81890..86745a1 100644
--- a/include/asm-s390/local.h
+++ b/include/asm-s390/local.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_LOCAL_H
 #define _ASM_LOCAL_H
 
-#include <linux/config.h>
 #include <linux/percpu.h>
 #include <asm/atomic.h>
 
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index bea7279..596c8b1 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -124,7 +124,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <linux/types.h>
 #include <asm/sigp.h>
diff --git a/include/asm-s390/page.h b/include/asm-s390/page.h
index 3b1138a..b2628dc 100644
--- a/include/asm-s390/page.h
+++ b/include/asm-s390/page.h
@@ -9,7 +9,6 @@
 #ifndef _S390_PAGE_H
 #define _S390_PAGE_H
 
-#include <asm/setup.h>
 #include <asm/types.h>
 
 /* PAGE_SHIFT determines the page size */
@@ -20,6 +19,7 @@
 #define PAGE_DEFAULT_KEY	(PAGE_DEFAULT_ACC << 4)
 
 #ifdef __KERNEL__
+#include <asm/setup.h>
 #ifndef __ASSEMBLY__
 
 #ifndef __s390x__
@@ -189,9 +189,9 @@
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
-#endif /* __KERNEL__ */
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#endif /* __KERNEL__ */
+
 #endif /* _S390_PAGE_H */
diff --git a/include/asm-s390/percpu.h b/include/asm-s390/percpu.h
index 436d216..d9a8cca 100644
--- a/include/asm-s390/percpu.h
+++ b/include/asm-s390/percpu.h
@@ -40,6 +40,7 @@
     __typeof__(type) per_cpu__##name
 
 #define __get_cpu_var(var) __reloc_hide(var,S390_lowcore.percpu_offset)
+#define __raw_get_cpu_var(var) __reloc_hide(var,S390_lowcore.percpu_offset)
 #define per_cpu(var,cpu) __reloc_hide(var,__per_cpu_offset[cpu])
 
 /* A macro to avoid #include hell... */
@@ -57,6 +58,7 @@
     __typeof__(type) per_cpu__##name
 
 #define __get_cpu_var(var) __reloc_hide(var,0)
+#define __raw_get_cpu_var(var) __reloc_hide(var,0)
 #define per_cpu(var,cpu) __reloc_hide(var,0)
 
 #endif /* SMP */
diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
index e28aaf2..3002fda 100644
--- a/include/asm-s390/pgalloc.h
+++ b/include/asm-s390/pgalloc.h
@@ -13,7 +13,6 @@
 #ifndef _S390_PGALLOC_H
 #define _S390_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/gfp.h>
 #include <linux/mm.h>
diff --git a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h
index 61788de..b94c988 100644
--- a/include/asm-s390/posix_types.h
+++ b/include/asm-s390/posix_types.h
@@ -76,24 +76,36 @@
 } __kernel_fsid_t;
 
 
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+#ifdef __KERNEL__
 
-#ifndef _S390_BITOPS_H
-#include <asm/bitops.h>
-#endif
+#undef __FD_SET
+static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
 
-#undef  __FD_SET
-#define __FD_SET(fd,fdsetp)  set_bit((fd),(fdsetp)->fds_bits)
+#undef __FD_CLR
+static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
 
-#undef  __FD_CLR
-#define __FD_CLR(fd,fdsetp)  clear_bit((fd),(fdsetp)->fds_bits)
-
-#undef  __FD_ISSET
-#define __FD_ISSET(fd,fdsetp)  test_bit((fd),(fdsetp)->fds_bits)
+#undef __FD_ISSET
+static inline int __FD_ISSET(unsigned long fd, const __kernel_fd_set *fdsetp)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (fdsetp->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
 
 #undef  __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset ((fdsetp), 0, sizeof(*(fd_set *)(fdsetp))))
+#define __FD_ZERO(fdsetp) \
+	((void) memset ((__ptr_t) (fdsetp), 0, sizeof (__kernel_fd_set)))
 
-#endif     /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)*/
+#endif     /* __KERNEL__ */
 
 #endif
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index a949cc0..4d75d77 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -181,11 +181,8 @@
 #define PTRACE_OLDSETOPTIONS         21
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
-#include <asm/setup.h>
-#include <asm/page.h>
 
 typedef union
 {
@@ -301,6 +298,9 @@
 } s390_regs;
 
 #ifdef __KERNEL__
+#include <asm/setup.h>
+#include <asm/page.h>
+
 /*
  * The pt_regs struct defines the way the registers are stored on
  * the stack during a system call.
diff --git a/include/asm-s390/sfp-machine.h b/include/asm-s390/sfp-machine.h
index 3c79b53..de69dfa 100644
--- a/include/asm-s390/sfp-machine.h
+++ b/include/asm-s390/sfp-machine.h
@@ -25,7 +25,6 @@
 #ifndef _SFP_MACHINE_H
 #define _SFP_MACHINE_H
    
-#include <linux/config.h>
 
 #define _FP_W_TYPE_SIZE		32
 #define _FP_W_TYPE		unsigned long
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index 444dae5..6576460 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 6a89dbb..71a0732 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -11,7 +11,6 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/types.h>
 #include <asm/ptrace.h>
diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
index 1bb73b0..73cd85b 100644
--- a/include/asm-s390/tlbflush.h
+++ b/include/asm-s390/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _S390_TLBFLUSH_H
 #define _S390_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
diff --git a/include/asm-s390/types.h b/include/asm-s390/types.h
index 5738ad63..ae2951c 100644
--- a/include/asm-s390/types.h
+++ b/include/asm-s390/types.h
@@ -58,7 +58,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef signed char s8;
 typedef unsigned char u8;
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index 41c2792..e21443d 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -392,6 +392,8 @@
 
 #endif
 
+#ifdef __KERNEL__
+
 /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
 
 #define __syscall_return(type, res)			     \
@@ -546,7 +548,6 @@
 	__syscall_return(type,__res);			     \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_SYS_ALARM
@@ -573,11 +574,9 @@
 #   define __ARCH_WANT_COMPAT_SYS_TIME
 #   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 # endif
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/ptrace.h>
@@ -625,7 +624,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -635,4 +634,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _ASM_S390_UNISTD_H_ */
diff --git a/include/asm-s390/vtoc.h b/include/asm-s390/vtoc.h
index d1de5b7..3a5267d 100644
--- a/include/asm-s390/vtoc.h
+++ b/include/asm-s390/vtoc.h
@@ -177,27 +177,27 @@
 } __attribute__ ((packed));
 
 struct vtoc_cms_label {
-	u8 label_id[4];		/* Label identifier */
-	u8 vol_id[6];		/* Volid */
-	u16 version_id;		/* Version identifier */
-	u32 block_size;		/* Disk block size */
-	u32 origin_ptr;		/* Disk origin pointer */
-	u32 usable_count;	/* Number of usable cylinders/blocks */
-	u32 formatted_count;	/* Maximum number of formatted cylinders/
+	__u8 label_id[4];		/* Label identifier */
+	__u8 vol_id[6];		/* Volid */
+	__u16 version_id;		/* Version identifier */
+	__u32 block_size;		/* Disk block size */
+	__u32 origin_ptr;		/* Disk origin pointer */
+	__u32 usable_count;	/* Number of usable cylinders/blocks */
+	__u32 formatted_count;	/* Maximum number of formatted cylinders/
 				 * blocks */
-	u32 block_count;	/* Disk size in CMS blocks */
-	u32 used_count;		/* Number of CMS blocks in use */
-	u32 fst_size;		/* File Status Table (FST) size */
-	u32 fst_count;		/* Number of FSTs per CMS block */
-	u8 format_date[6];	/* Disk FORMAT date */
-	u8 reserved1[2];
-	u32 disk_offset;	/* Disk offset when reserved*/
-	u32 map_block;		/* Allocation Map Block with next hole */
-	u32 hblk_disp;		/* Displacement into HBLK data of next hole */
-	u32 user_disp;		/* Displacement into user part of Allocation
+	__u32 block_count;	/* Disk size in CMS blocks */
+	__u32 used_count;		/* Number of CMS blocks in use */
+	__u32 fst_size;		/* File Status Table (FST) size */
+	__u32 fst_count;		/* Number of FSTs per CMS block */
+	__u8 format_date[6];	/* Disk FORMAT date */
+	__u8 reserved1[2];
+	__u32 disk_offset;	/* Disk offset when reserved*/
+	__u32 map_block;		/* Allocation Map Block with next hole */
+	__u32 hblk_disp;		/* Displacement into HBLK data of next hole */
+	__u32 user_disp;		/* Displacement into user part of Allocation
 				 * map */
-	u8 reserved2[4];
-	u8 segment_name[8];	/* Name of shared segment */
+	__u8 reserved2[4];
+	__u8 segment_name[8];	/* Name of shared segment */
 } __attribute__ ((packed));
 
 #endif /* _ASM_S390_VTOC_H */
diff --git a/include/asm-s390/z90crypt.h b/include/asm-s390/z90crypt.h
new file mode 100644
index 0000000..31a2439
--- /dev/null
+++ b/include/asm-s390/z90crypt.h
@@ -0,0 +1,212 @@
+/*
+ *  include/asm-s390/z90crypt.h
+ *
+ *  z90crypt 1.3.3 (user-visible header)
+ *
+ *  Copyright (C)  2001, 2005 IBM Corporation
+ *  Author(s): Robert Burroughs
+ *             Eric Rossman (edrossma@us.ibm.com)
+ *
+ *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __ASM_S390_Z90CRYPT_H
+#define __ASM_S390_Z90CRYPT_H
+#include <linux/ioctl.h>
+
+#define z90crypt_VERSION 1
+#define z90crypt_RELEASE 3	// 2 = PCIXCC, 3 = rewrite for coding standards
+#define z90crypt_VARIANT 3	// 3 = CEX2A support
+
+/**
+ * struct ica_rsa_modexpo
+ *
+ * Requirements:
+ * - outputdatalength is at least as large as inputdatalength.
+ * - All key parts are right justified in their fields, padded on
+ *   the left with zeroes.
+ * - length(b_key) = inputdatalength
+ * - length(n_modulus) = inputdatalength
+ */
+struct ica_rsa_modexpo {
+	char __user *	inputdata;
+	unsigned int	inputdatalength;
+	char __user *	outputdata;
+	unsigned int	outputdatalength;
+	char __user *	b_key;
+	char __user *	n_modulus;
+};
+
+/**
+ * struct ica_rsa_modexpo_crt
+ *
+ * Requirements:
+ * - inputdatalength is even.
+ * - outputdatalength is at least as large as inputdatalength.
+ * - All key parts are right justified in their fields, padded on
+ *   the left with zeroes.
+ * - length(bp_key)	= inputdatalength/2 + 8
+ * - length(bq_key)	= inputdatalength/2
+ * - length(np_key)	= inputdatalength/2 + 8
+ * - length(nq_key)	= inputdatalength/2
+ * - length(u_mult_inv) = inputdatalength/2 + 8
+ */
+struct ica_rsa_modexpo_crt {
+	char __user *	inputdata;
+	unsigned int	inputdatalength;
+	char __user *	outputdata;
+	unsigned int	outputdatalength;
+	char __user *	bp_key;
+	char __user *	bq_key;
+	char __user *	np_prime;
+	char __user *	nq_prime;
+	char __user *	u_mult_inv;
+};
+
+#define Z90_IOCTL_MAGIC 'z'  // NOTE:  Need to allocate from linux folks
+
+/**
+ * Interface notes:
+ *
+ * The ioctl()s which are implemented (along with relevant details)
+ * are:
+ *
+ *   ICARSAMODEXPO
+ *     Perform an RSA operation using a Modulus-Exponent pair
+ *     This takes an ica_rsa_modexpo struct as its arg.
+ *
+ *     NOTE: please refer to the comments preceding this structure
+ *           for the implementation details for the contents of the
+ *           block
+ *
+ *   ICARSACRT
+ *     Perform an RSA operation using a Chinese-Remainder Theorem key
+ *     This takes an ica_rsa_modexpo_crt struct as its arg.
+ *
+ *     NOTE: please refer to the comments preceding this structure
+ *           for the implementation details for the contents of the
+ *           block
+ *
+ *   Z90STAT_TOTALCOUNT
+ *     Return an integer count of all device types together.
+ *
+ *   Z90STAT_PCICACOUNT
+ *     Return an integer count of all PCICAs.
+ *
+ *   Z90STAT_PCICCCOUNT
+ *     Return an integer count of all PCICCs.
+ *
+ *   Z90STAT_PCIXCCMCL2COUNT
+ *     Return an integer count of all MCL2 PCIXCCs.
+ *
+ *   Z90STAT_PCIXCCMCL3COUNT
+ *     Return an integer count of all MCL3 PCIXCCs.
+ *
+ *   Z90STAT_CEX2CCOUNT
+ *     Return an integer count of all CEX2Cs.
+ *
+ *   Z90STAT_CEX2ACOUNT
+ *     Return an integer count of all CEX2As.
+ *
+ *   Z90STAT_REQUESTQ_COUNT
+ *     Return an integer count of the number of entries waiting to be
+ *     sent to a device.
+ *
+ *   Z90STAT_PENDINGQ_COUNT
+ *     Return an integer count of the number of entries sent to a
+ *     device awaiting the reply.
+ *
+ *   Z90STAT_TOTALOPEN_COUNT
+ *     Return an integer count of the number of open file handles.
+ *
+ *   Z90STAT_DOMAIN_INDEX
+ *     Return the integer value of the Cryptographic Domain.
+ *
+ *   Z90STAT_STATUS_MASK
+ *     Return an 64 element array of unsigned chars for the status of
+ *     all devices.
+ *       0x01: PCICA
+ *       0x02: PCICC
+ *       0x03: PCIXCC_MCL2
+ *       0x04: PCIXCC_MCL3
+ *       0x05: CEX2C
+ *       0x06: CEX2A
+ *       0x0d: device is disabled via the proc filesystem
+ *
+ *   Z90STAT_QDEPTH_MASK
+ *     Return an 64 element array of unsigned chars for the queue
+ *     depth of all devices.
+ *
+ *   Z90STAT_PERDEV_REQCNT
+ *     Return an 64 element array of unsigned integers for the number
+ *     of successfully completed requests per device since the device
+ *     was detected and made available.
+ *
+ *   ICAZ90STATUS (deprecated)
+ *     Return some device driver status in a ica_z90_status struct
+ *     This takes an ica_z90_status struct as its arg.
+ *
+ *     NOTE: this ioctl() is deprecated, and has been replaced with
+ *           single ioctl()s for each type of status being requested
+ *
+ *   Z90STAT_PCIXCCCOUNT (deprecated)
+ *     Return an integer count of all PCIXCCs (MCL2 + MCL3).
+ *     This is DEPRECATED now that MCL3 PCIXCCs are treated differently from
+ *     MCL2 PCIXCCs.
+ *
+ *   Z90QUIESCE (not recommended)
+ *     Quiesce the driver.  This is intended to stop all new
+ *     requests from being processed.  Its use is NOT recommended,
+ *     except in circumstances where there is no other way to stop
+ *     callers from accessing the driver.  Its original use was to
+ *     allow the driver to be "drained" of work in preparation for
+ *     a system shutdown.
+ *
+ *     NOTE: once issued, this ban on new work cannot be undone
+ *           except by unloading and reloading the driver.
+ */
+
+/**
+ * Supported ioctl calls
+ */
+#define ICARSAMODEXPO	_IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0)
+#define ICARSACRT	_IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0)
+
+/* DEPRECATED status calls (bound for removal at some point) */
+#define ICAZ90STATUS	_IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status)
+#define Z90STAT_PCIXCCCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x43, int)
+
+/* unrelated to ICA callers */
+#define Z90QUIESCE	_IO(Z90_IOCTL_MAGIC, 0x11)
+
+/* New status calls */
+#define Z90STAT_TOTALCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x40, int)
+#define Z90STAT_PCICACOUNT	_IOR(Z90_IOCTL_MAGIC, 0x41, int)
+#define Z90STAT_PCICCCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x42, int)
+#define Z90STAT_PCIXCCMCL2COUNT	_IOR(Z90_IOCTL_MAGIC, 0x4b, int)
+#define Z90STAT_PCIXCCMCL3COUNT	_IOR(Z90_IOCTL_MAGIC, 0x4c, int)
+#define Z90STAT_CEX2CCOUNT	_IOR(Z90_IOCTL_MAGIC, 0x4d, int)
+#define Z90STAT_CEX2ACOUNT	_IOR(Z90_IOCTL_MAGIC, 0x4e, int)
+#define Z90STAT_REQUESTQ_COUNT	_IOR(Z90_IOCTL_MAGIC, 0x44, int)
+#define Z90STAT_PENDINGQ_COUNT	_IOR(Z90_IOCTL_MAGIC, 0x45, int)
+#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
+#define Z90STAT_DOMAIN_INDEX	_IOR(Z90_IOCTL_MAGIC, 0x47, int)
+#define Z90STAT_STATUS_MASK	_IOR(Z90_IOCTL_MAGIC, 0x48, char[64])
+#define Z90STAT_QDEPTH_MASK	_IOR(Z90_IOCTL_MAGIC, 0x49, char[64])
+#define Z90STAT_PERDEV_REQCNT	_IOR(Z90_IOCTL_MAGIC, 0x4a, int[64])
+
+#endif /* __ASM_S390_Z90CRYPT_H */
diff --git a/include/asm-sh/bug.h b/include/asm-sh/bug.h
index 70508a3..1b4fc52 100644
--- a/include/asm-sh/bug.h
+++ b/include/asm-sh/bug.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_BUG_H
 #define __ASM_SH_BUG_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BUG
 /*
diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
index 5ebd0f2..fa03b30 100644
--- a/include/asm-sh/checksum.h
+++ b/include/asm-sh/checksum.h
@@ -9,7 +9,6 @@
  * Copyright (C) 1999 by Kaz Kojima & Niibe Yutaka
  */
 
-#include <linux/config.h>
 #include <linux/in6.h>
 
 /*
diff --git a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
index 48f1f42..124968f9 100644
--- a/include/asm-sh/dma-mapping.h
+++ b/include/asm-sh/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_DMA_MAPPING_H
 #define __ASM_SH_DMA_MAPPING_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <asm/cacheflush.h>
diff --git a/include/asm-sh/dma.h b/include/asm-sh/dma.h
index a118a0d4..e62a6d0 100644
--- a/include/asm-sh/dma.h
+++ b/include/asm-sh/dma.h
@@ -11,7 +11,6 @@
 #define __ASM_SH_DMA_H
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <linux/sysdev.h>
diff --git a/include/asm-sh/fixmap.h b/include/asm-sh/fixmap.h
index 509224b..412bcca 100644
--- a/include/asm-sh/fixmap.h
+++ b/include/asm-sh/fixmap.h
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/page.h>
 #ifdef CONFIG_HIGHMEM
diff --git a/include/asm-sh/floppy.h b/include/asm-sh/floppy.h
index 38d7a29..307d9ce 100644
--- a/include/asm-sh/floppy.h
+++ b/include/asm-sh/floppy.h
@@ -147,11 +147,10 @@
 {
 	if(can_use_virtual_dma)
 		return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
-						   "floppy", NULL);
+				   "floppy", NULL);
 	else
-		return request_irq(FLOPPY_IRQ, floppy_interrupt,
-						   SA_INTERRUPT|SA_SAMPLE_RANDOM,
-						   "floppy", NULL);	
+		return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT,
+				   "floppy", NULL);
 
 }
 
diff --git a/include/asm-sh/hardirq.h b/include/asm-sh/hardirq.h
index f2fdf0f..715ee23 100644
--- a/include/asm-sh/hardirq.h
+++ b/include/asm-sh/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_HARDIRQ_H
 #define __ASM_SH_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-sh/hd64461/hd64461.h b/include/asm-sh/hd64461/hd64461.h
index c457ca2..87f13d2 100644
--- a/include/asm-sh/hd64461/hd64461.h
+++ b/include/asm-sh/hd64461/hd64461.h
@@ -5,7 +5,6 @@
  *	Copyright (C) 2000 YAEGASHI Takeshi
  *	Hitachi HD64461 companion chip support
  */
-#include <linux/config.h>
 
 /* Constants for PCMCIA mappings */
 #define HD64461_PCC_WINDOW	0x01000000
diff --git a/include/asm-sh/hd64465/hd64465.h b/include/asm-sh/hd64465/hd64465.h
index c672032..cfd0e80 100644
--- a/include/asm-sh/hd64465/hd64465.h
+++ b/include/asm-sh/hd64465/hd64465.h
@@ -11,7 +11,6 @@
  * Derived from <asm/hd64461.h> which bore the message:
  * Copyright (C) 2000 YAEGASHI Takeshi
  */
-#include <linux/config.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
diff --git a/include/asm-sh/ide.h b/include/asm-sh/ide.h
index 711dad4..9f8e914 100644
--- a/include/asm-sh/ide.h
+++ b/include/asm-sh/ide.h
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #define ide_default_io_ctl(base)	(0)
 
diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h
index 2c3afe7..894e64b 100644
--- a/include/asm-sh/io.h
+++ b/include/asm-sh/io.h
@@ -23,7 +23,6 @@
  *  inb   by default expands to _inb, but the machine specific code may
  *        define it to __inb if it chooses.
  */
-#include <linux/config.h>
 #include <asm/cache.h>
 #include <asm/system.h>
 #include <asm/addrspace.h>
diff --git a/include/asm-sh/irq.h b/include/asm-sh/irq.h
index 42b8394..611e67c 100644
--- a/include/asm-sh/irq.h
+++ b/include/asm-sh/irq.h
@@ -11,7 +11,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <asm/machvec.h>
 #include <asm/ptrace.h>		/* for pt_regs */
 
diff --git a/include/asm-sh/keyboard.h b/include/asm-sh/keyboard.h
index 1103df0..31dcc4f 100644
--- a/include/asm-sh/keyboard.h
+++ b/include/asm-sh/keyboard.h
@@ -5,7 +5,6 @@
  */
 
 #include <linux/kd.h>
-#include <linux/config.h>
 #include <asm/machvec.h>
 
 #ifdef CONFIG_SH_MPC1211
diff --git a/include/asm-sh/kmap_types.h b/include/asm-sh/kmap_types.h
index 2492ba0..84d565c 100644
--- a/include/asm-sh/kmap_types.h
+++ b/include/asm-sh/kmap_types.h
@@ -3,7 +3,6 @@
 
 /* Dummy header just to define km_type. */
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DEBUG_HIGHMEM
 # define D(n) __KM_FENCE_##n ,
diff --git a/include/asm-sh/machvec.h b/include/asm-sh/machvec.h
index 550c50a..550501f 100644
--- a/include/asm-sh/machvec.h
+++ b/include/asm-sh/machvec.h
@@ -10,7 +10,6 @@
 #ifndef _ASM_SH_MACHVEC_H
 #define _ASM_SH_MACHVEC_H 1
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/time.h>
 
diff --git a/include/asm-sh/machvec_init.h b/include/asm-sh/machvec_init.h
index 9e7de80..e397798 100644
--- a/include/asm-sh/machvec_init.h
+++ b/include/asm-sh/machvec_init.h
@@ -12,7 +12,6 @@
 #ifndef __SH_MACHVEC_INIT_H
 #define __SH_MACHVEC_INIT_H
 
-#include <linux/config.h>
 
 /*
  * In a GENERIC kernel, we have lots of these vectors floating about,
diff --git a/include/asm-sh/mpc1211/dma.h b/include/asm-sh/mpc1211/dma.h
index 0a2fdab..e506d1a 100644
--- a/include/asm-sh/mpc1211/dma.h
+++ b/include/asm-sh/mpc1211/dma.h
@@ -8,7 +8,6 @@
 #ifndef _ASM_MPC1211_DMA_H
 #define _ASM_MPC1211_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>	/* And spinlocks */
 #include <asm/io.h>		/* need byte IO */
 #include <linux/delay.h>
diff --git a/include/asm-sh/overdrive/overdrive.h b/include/asm-sh/overdrive/overdrive.h
index aa62ae6..fc746c2 100644
--- a/include/asm-sh/overdrive/overdrive.h
+++ b/include/asm-sh/overdrive/overdrive.h
@@ -6,7 +6,6 @@
  *
  */
 
-#include <linux/config.h>
 
 #ifndef __OVERDRIVE_H__
 #define __OVERDRIVE_H__
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 9c89287..a5559e3 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -13,7 +13,6 @@
    [ P4 control   ]		0xE0000000
  */
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index bb0efb3..dcd23a0 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -8,7 +8,6 @@
  * Copyright (C) 2002, 2003, 2004 Paul Mundt
  */
 
-#include <linux/config.h>
 #include <asm/pgtable-2level.h>
 
 /*
diff --git a/include/asm-sh/serial.h b/include/asm-sh/serial.h
index f51e232..8734590 100644
--- a/include/asm-sh/serial.h
+++ b/include/asm-sh/serial.h
@@ -7,7 +7,6 @@
 #ifndef _ASM_SERIAL_H
 #define _ASM_SERIAL_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 
 #ifdef CONFIG_SH_EC3104
diff --git a/include/asm-sh/smp.h b/include/asm-sh/smp.h
index f19a8b3..f57c4fe 100644
--- a/include/asm-sh/smp.h
+++ b/include/asm-sh/smp.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_SH_SMP_H
 #define __ASM_SH_SMP_H
 
-#include <linux/config.h>
 #include <linux/bitops.h>
 #include <linux/cpumask.h>
 
diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h
index bb03304..b752e5c 100644
--- a/include/asm-sh/system.h
+++ b/include/asm-sh/system.h
@@ -6,7 +6,6 @@
  * Copyright (C) 2002 Paul Mundt
  */
 
-#include <linux/config.h>
 
 /*
  *	switch_to() should switch tasks to task nr n, first
diff --git a/include/asm-sh/types.h b/include/asm-sh/types.h
index 488552f..3c09dd4 100644
--- a/include/asm-sh/types.h
+++ b/include/asm-sh/types.h
@@ -35,7 +35,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 
 typedef __signed__ char s8;
 typedef unsigned char u8;
diff --git a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
index 05520ce..76b5430 100644
--- a/include/asm-sh/unistd.h
+++ b/include/asm-sh/unistd.h
@@ -304,6 +304,8 @@
 
 #define NR_syscalls 293
 
+#ifdef __KERNEL__
+
 /* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
 
 #define __syscall_return(type, res) \
@@ -420,7 +422,6 @@
 __syscall_return(type,__sc0); \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -443,7 +444,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -513,7 +513,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -525,4 +525,5 @@
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_SH_UNISTD_H */
diff --git a/include/asm-sh/watchdog.h b/include/asm-sh/watchdog.h
index f0cf4be..09ca419 100644
--- a/include/asm-sh/watchdog.h
+++ b/include/asm-sh/watchdog.h
@@ -13,7 +13,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <asm/cpu/watchdog.h>
 #include <asm/io.h>
 
diff --git a/include/asm-sh64/bug.h b/include/asm-sh64/bug.h
index 5d659ec..81f722e 100644
--- a/include/asm-sh64/bug.h
+++ b/include/asm-sh64/bug.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH64_BUG_H
 #define __ASM_SH64_BUG_H
 
-#include <linux/config.h>
 
 /*
  * Tell the user there is some problem, then force a segfault (in process
diff --git a/include/asm-sh64/dma-mapping.h b/include/asm-sh64/dma-mapping.h
index cc9a2e8..a74a49e 100644
--- a/include/asm-sh64/dma-mapping.h
+++ b/include/asm-sh64/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH_DMA_MAPPING_H
 #define __ASM_SH_DMA_MAPPING_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
diff --git a/include/asm-sh64/hardirq.h b/include/asm-sh64/hardirq.h
index ad2330e..555fd7a 100644
--- a/include/asm-sh64/hardirq.h
+++ b/include/asm-sh64/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_SH64_HARDIRQ_H
 #define __ASM_SH64_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-sh64/ide.h b/include/asm-sh64/ide.h
index 852f50a..c9d84d5 100644
--- a/include/asm-sh64/ide.h
+++ b/include/asm-sh64/ide.h
@@ -15,7 +15,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 /* Without this, the initialisation of PCI IDE cards end up calling
  * ide_init_hwif_ports, which won't work. */
diff --git a/include/asm-sh64/irq.h b/include/asm-sh64/irq.h
index f815b43..1ca49e2 100644
--- a/include/asm-sh64/irq.h
+++ b/include/asm-sh64/irq.h
@@ -12,7 +12,6 @@
  *
  */
 
-#include <linux/config.h>
 
 /*
  * Encoded IRQs are not considered worth to be supported.
diff --git a/include/asm-sh64/mmu_context.h b/include/asm-sh64/mmu_context.h
index 991cfda..8c860da 100644
--- a/include/asm-sh64/mmu_context.h
+++ b/include/asm-sh64/mmu_context.h
@@ -26,7 +26,6 @@
  */
 extern unsigned long mmu_context_cache;
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 
diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h
index e4937cd..34fb347 100644
--- a/include/asm-sh64/page.h
+++ b/include/asm-sh64/page.h
@@ -17,7 +17,6 @@
  *
  */
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
diff --git a/include/asm-sh64/param.h b/include/asm-sh64/param.h
index d18cc87..f409adb 100644
--- a/include/asm-sh64/param.h
+++ b/include/asm-sh64/param.h
@@ -12,7 +12,6 @@
 #ifndef __ASM_SH64_PARAM_H
 #define __ASM_SH64_PARAM_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 # ifdef CONFIG_SH_WDT
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 57af6b3..54c7821 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -22,7 +22,6 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <linux/threads.h>
-#include <linux/config.h>
 
 struct vm_area_struct;
 
diff --git a/include/asm-sh64/system.h b/include/asm-sh64/system.h
index 3002e988..7606f6e 100644
--- a/include/asm-sh64/system.h
+++ b/include/asm-sh64/system.h
@@ -14,7 +14,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <asm/registers.h>
 #include <asm/processor.h>
 
diff --git a/include/asm-sh64/unistd.h b/include/asm-sh64/unistd.h
index 1f8f394..9a1590f 100644
--- a/include/asm-sh64/unistd.h
+++ b/include/asm-sh64/unistd.h
@@ -344,6 +344,8 @@
 #define __NR_inotify_add_watch	319
 #define __NR_inotify_rm_watch	320
 
+#ifdef __KERNEL__ 
+
 #define NR_syscalls 321
 
 /* user-visible error numbers are in the range -1 - -125: see <asm-sh64/errno.h> */
@@ -486,7 +488,6 @@
 __syscall_return(type,__sc0); 						    \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
@@ -509,7 +510,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -550,7 +550,7 @@
 {
 	return waitpid(-1,wait_stat,0);
 }
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -562,4 +562,5 @@
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_SH64_UNISTD_H */
diff --git a/include/asm-sparc/asmmacro.h b/include/asm-sparc/asmmacro.h
index 0d4b65b..a619a4d 100644
--- a/include/asm-sparc/asmmacro.h
+++ b/include/asm-sparc/asmmacro.h
@@ -6,7 +6,6 @@
 #ifndef _SPARC_ASMMACRO_H
 #define _SPARC_ASMMACRO_H
 
-#include <linux/config.h>
 #include <asm/btfixup.h>
 #include <asm/asi.h>
 
diff --git a/include/asm-sparc/atomic.h b/include/asm-sparc/atomic.h
index e103317..731fa56 100644
--- a/include/asm-sparc/atomic.h
+++ b/include/asm-sparc/atomic.h
@@ -10,7 +10,6 @@
 #ifndef __ARCH_SPARC_ATOMIC__
 #define __ARCH_SPARC_ATOMIC__
 
-#include <linux/config.h>
 
 typedef struct { volatile int counter; } atomic_t;
 
diff --git a/include/asm-sparc/bugs.h b/include/asm-sparc/bugs.h
index e652f89..a0f939b 100644
--- a/include/asm-sparc/bugs.h
+++ b/include/asm-sparc/bugs.h
@@ -5,7 +5,6 @@
  */
 
 #include <asm/cpudata.h>
-#include <linux/config.h>
 
 extern unsigned long loops_per_jiffy;
 
diff --git a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
index 4901217..fc632f8 100644
--- a/include/asm-sparc/cacheflush.h
+++ b/include/asm-sparc/cacheflush.h
@@ -1,7 +1,6 @@
 #ifndef _SPARC_CACHEFLUSH_H
 #define _SPARC_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>		/* Common for other includes */
 // #include <linux/kernel.h> from pgalloc.h
 // #include <linux/sched.h>  from pgalloc.h
diff --git a/include/asm-sparc/delay.h b/include/asm-sparc/delay.h
index 7ec8e9f..48aa70e 100644
--- a/include/asm-sparc/delay.h
+++ b/include/asm-sparc/delay.h
@@ -7,7 +7,6 @@
 #ifndef __SPARC_DELAY_H
 #define __SPARC_DELAY_H
 
-#include <linux/config.h>
 #include <asm/cpudata.h>
 
 static inline void __delay(unsigned long loops)
diff --git a/include/asm-sparc/dma-mapping.h b/include/asm-sparc/dma-mapping.h
index d7c3b0f..6db83dc 100644
--- a/include/asm-sparc/dma-mapping.h
+++ b/include/asm-sparc/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_SPARC_DMA_MAPPING_H
 #define _ASM_SPARC_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
diff --git a/include/asm-sparc/dma.h b/include/asm-sparc/dma.h
index 8ec206a..407b361 100644
--- a/include/asm-sparc/dma.h
+++ b/include/asm-sparc/dma.h
@@ -7,7 +7,6 @@
 #ifndef _ASM_SPARC_DMA_H
 #define _ASM_SPARC_DMA_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
diff --git a/include/asm-sparc/ebus.h b/include/asm-sparc/ebus.h
index 2d6a997..5465288 100644
--- a/include/asm-sparc/ebus.h
+++ b/include/asm-sparc/ebus.h
@@ -13,13 +13,14 @@
 #include <linux/ioport.h>
 #endif
 #include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
 
 struct linux_ebus_child {
 	struct linux_ebus_child		*next;
 	struct linux_ebus_device	*parent;
 	struct linux_ebus		*bus;
-	int				 prom_node;
-	char				 prom_name[64];
+	struct device_node		*prom_node;
 	struct resource			 resource[PROMREG_MAX];
 	int				 num_addrs;
 	unsigned int			 irqs[PROMINTR_MAX];
@@ -27,27 +28,27 @@
 };
 
 struct linux_ebus_device {
+	struct of_device		ofdev;
 	struct linux_ebus_device	*next;
 	struct linux_ebus_child		*children;
 	struct linux_ebus		*bus;
-	int				 prom_node;
-	char				 prom_name[64];
+	struct device_node		*prom_node;
 	struct resource			 resource[PROMREG_MAX];
 	int				 num_addrs;
 	unsigned int			 irqs[PROMINTR_MAX];
 	int				 num_irqs;
 };
+#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev)
 
 struct linux_ebus {
+	struct of_device		ofdev;
 	struct linux_ebus		*next;
 	struct linux_ebus_device	*devices;
 	struct linux_pbm_info		*parent;
 	struct pci_dev			*self;
-	int				 prom_node;
-	char				 prom_name[64];
-	struct linux_prom_ebus_ranges	 ebus_ranges[PROMREG_MAX];
-	int				 num_ebus_ranges;
+	struct device_node		*prom_node;
 };
+#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev)
 
 struct linux_ebus_dma {
 	unsigned int dcsr;
diff --git a/include/asm-sparc/elf.h b/include/asm-sparc/elf.h
index 4a71d7c..83a3dd1 100644
--- a/include/asm-sparc/elf.h
+++ b/include/asm-sparc/elf.h
@@ -6,7 +6,6 @@
  * ELF register definitions..
  */
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 
 #ifdef __KERNEL__
diff --git a/include/asm-sparc/fixmap.h b/include/asm-sparc/fixmap.h
index 9de52b4..f18fc07 100644
--- a/include/asm-sparc/fixmap.h
+++ b/include/asm-sparc/fixmap.h
@@ -13,7 +13,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/page.h>
 #ifdef CONFIG_HIGHMEM
diff --git a/include/asm-sparc/hardirq.h b/include/asm-sparc/hardirq.h
index 2a668c4..4f63ed8 100644
--- a/include/asm-sparc/hardirq.h
+++ b/include/asm-sparc/hardirq.h
@@ -7,7 +7,6 @@
 #ifndef __SPARC_HARDIRQ_H
 #define __SPARC_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
diff --git a/include/asm-sparc/ide.h b/include/asm-sparc/ide.h
index 64d8103..a6d735a 100644
--- a/include/asm-sparc/ide.h
+++ b/include/asm-sparc/ide.h
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/psr.h>
diff --git a/include/asm-sparc/io.h b/include/asm-sparc/io.h
index a42df20..cab0b85 100644
--- a/include/asm-sparc/io.h
+++ b/include/asm-sparc/io.h
@@ -249,6 +249,22 @@
 #define ioremap_nocache(X,Y)	ioremap((X),(Y))
 extern void iounmap(volatile void __iomem *addr);
 
+#define ioread8(X)			readb(X)
+#define ioread16(X)			readw(X)
+#define ioread32(X)			readl(X)
+#define iowrite8(val,X)			writeb(val,X)
+#define iowrite16(val,X)		writew(val,X)
+#define iowrite32(val,X)		writel(val,X)
+
+/* Create a virtual mapping cookie for an IO port range */
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *);
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+struct pci_dev;
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
 /*
  * Bus number may be in res->flags... somewhere.
  */
diff --git a/include/asm-sparc/irq.h b/include/asm-sparc/irq.h
index cee356b..3141ddf 100644
--- a/include/asm-sparc/irq.h
+++ b/include/asm-sparc/irq.h
@@ -7,7 +7,6 @@
 #ifndef _SPARC_IRQ_H
 #define _SPARC_IRQ_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/threads.h>     /* For NR_CPUS */
 #include <linux/interrupt.h>
@@ -17,8 +16,6 @@
 
 #define __irq_ino(irq) irq
 #define __irq_pil(irq) irq
-BTFIXUPDEF_CALL(char *, __irq_itoa, unsigned int)
-#define __irq_itoa(irq) BTFIXUP_CALL(__irq_itoa)(irq)
 
 #define NR_IRQS    16
 
@@ -184,8 +181,4 @@
 #define SUN4M_INT_SBUS(x)	(1 << (x+7))
 #define SUN4M_INT_VME(x)	(1 << (x))
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif
diff --git a/include/asm-sparc/mostek.h b/include/asm-sparc/mostek.h
index 59b86bc..bd92a78 100644
--- a/include/asm-sparc/mostek.h
+++ b/include/asm-sparc/mostek.h
@@ -9,7 +9,6 @@
 #ifndef _SPARC_MOSTEK_H
 #define _SPARC_MOSTEK_H
 
-#include <linux/config.h>
 #include <asm/idprom.h>
 #include <asm/io.h>
 
diff --git a/include/asm-sparc/of_device.h b/include/asm-sparc/of_device.h
new file mode 100644
index 0000000..4816d10
--- /dev/null
+++ b/include/asm-sparc/of_device.h
@@ -0,0 +1,63 @@
+#ifndef _ASM_SPARC_OF_DEVICE_H
+#define _ASM_SPARC_OF_DEVICE_H
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <asm/prom.h>
+
+extern struct bus_type ebus_bus_type;
+extern struct bus_type sbus_bus_type;
+
+/*
+ * The of_device is a kind of "base class" that is a superset of
+ * struct device for use by devices attached to an OF node and
+ * probed using OF properties.
+ */
+struct of_device
+{
+	struct device_node	*node;		/* OF device node */
+	struct device		dev;		/* Generic device interface */
+};
+#define	to_of_device(d) container_of(d, struct of_device, dev)
+
+extern const struct of_device_id *of_match_device(
+	const struct of_device_id *matches, const struct of_device *dev);
+
+extern struct of_device *of_dev_get(struct of_device *dev);
+extern void of_dev_put(struct of_device *dev);
+
+/*
+ * An of_platform_driver driver is attached to a basic of_device on
+ * the ISA, EBUS, and SBUS busses on sparc64.
+ */
+struct of_platform_driver
+{
+	char			*name;
+	struct of_device_id	*match_table;
+	struct module		*owner;
+
+	int	(*probe)(struct of_device* dev, const struct of_device_id *match);
+	int	(*remove)(struct of_device* dev);
+
+	int	(*suspend)(struct of_device* dev, pm_message_t state);
+	int	(*resume)(struct of_device* dev);
+	int	(*shutdown)(struct of_device* dev);
+
+	struct device_driver	driver;
+};
+#define	to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
+
+extern int of_register_driver(struct of_platform_driver *drv,
+			      struct bus_type *bus);
+extern void of_unregister_driver(struct of_platform_driver *drv);
+extern int of_device_register(struct of_device *ofdev);
+extern void of_device_unregister(struct of_device *ofdev);
+extern struct of_device *of_platform_device_create(struct device_node *np,
+						   const char *bus_id,
+						   struct device *parent,
+						   struct bus_type *bus);
+extern void of_release_dev(struct device *dev);
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_SPARC_OF_DEVICE_H */
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index ec3274b..5bab8a7 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -8,7 +8,6 @@
 #ifndef _SPARC_PAGE_H
 #define _SPARC_PAGE_H
 
-#include <linux/config.h>
 #ifdef CONFIG_SUN4
 #define PAGE_SHIFT   13
 #else
diff --git a/include/asm-sparc/pbm.h b/include/asm-sparc/pbm.h
index 0aba3a8..fedd9c6 100644
--- a/include/asm-sparc/pbm.h
+++ b/include/asm-sparc/pbm.h
@@ -22,6 +22,7 @@
 
 #include <linux/pci.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 
 struct linux_pbm_info {
 	int		prom_node;
@@ -40,7 +41,7 @@
  */
 struct pcidev_cookie {
 	struct linux_pbm_info		*pbm;
-	int				prom_node;
+	struct device_node		*prom_node;
 };
 
 #endif /* !(__SPARC_PBM_H) */
diff --git a/include/asm-sparc/pgalloc.h b/include/asm-sparc/pgalloc.h
index 126800a..a449cd4 100644
--- a/include/asm-sparc/pgalloc.h
+++ b/include/asm-sparc/pgalloc.h
@@ -2,7 +2,6 @@
 #ifndef _SPARC_PGALLOC_H
 #define _SPARC_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 
diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
index 9eea8f4..226c647 100644
--- a/include/asm-sparc/pgtable.h
+++ b/include/asm-sparc/pgtable.h
@@ -11,7 +11,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/swap.h>
 #include <asm/types.h>
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
new file mode 100644
index 0000000..f9cf44c
--- /dev/null
+++ b/include/asm-sparc/prom.h
@@ -0,0 +1,108 @@
+#ifndef _SPARC_PROM_H
+#define _SPARC_PROM_H
+#ifdef __KERNEL__
+
+
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ * Updates for SPARC32 by David S. Miller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/atomic.h>
+
+typedef u32 phandle;
+typedef u32 ihandle;
+
+struct interrupt_info {
+	int	line;
+	int	sense;		/* +ve/-ve logic, edge or level, etc. */
+};
+
+struct property {
+	char	*name;
+	int	length;
+	void	*value;
+	struct property *next;
+	unsigned long _flags;
+	unsigned int unique_id;
+};
+
+struct device_node {
+	char	*name;
+	char	*type;
+	phandle	node;
+	phandle linux_phandle;
+	int	n_intrs;
+	struct	interrupt_info *intrs;
+	char	*path_component_name;
+	char	*full_name;
+
+	struct	property *properties;
+	struct  property *deadprops; /* removed properties */
+	struct	device_node *parent;
+	struct	device_node *child;
+	struct	device_node *sibling;
+	struct	device_node *next;	/* next device of same type */
+	struct	device_node *allnext;	/* next in list of all nodes */
+	struct  proc_dir_entry *pde;	/* this node's proc directory */
+	struct  kref kref;
+	unsigned long _flags;
+	void	*data;
+	unsigned int unique_id;
+};
+
+/* flag descriptions */
+#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+
+#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
+#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
+
+static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
+{
+	dn->pde = de;
+}
+
+extern struct device_node *of_find_node_by_name(struct device_node *from,
+	const char *name);
+#define for_each_node_by_name(dn, name) \
+	for (dn = of_find_node_by_name(NULL, name); dn; \
+	     dn = of_find_node_by_name(dn, name))
+extern struct device_node *of_find_node_by_type(struct device_node *from,
+	const char *type);
+#define for_each_node_by_type(dn, type) \
+	for (dn = of_find_node_by_type(NULL, type); dn; \
+	     dn = of_find_node_by_type(dn, type))
+extern struct device_node *of_find_compatible_node(struct device_node *from,
+	const char *type, const char *compat);
+extern struct device_node *of_find_node_by_path(const char *path);
+extern struct device_node *of_find_node_by_phandle(phandle handle);
+extern struct device_node *of_get_parent(const struct device_node *node);
+extern struct device_node *of_get_next_child(const struct device_node *node,
+					     struct device_node *prev);
+extern struct property *of_find_property(struct device_node *np,
+					 const char *name,
+					 int *lenp);
+extern int of_device_is_compatible(struct device_node *device, const char *);
+extern void *of_get_property(struct device_node *node, const char *name,
+			     int *lenp);
+extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
+extern int of_getintprop_default(struct device_node *np,
+				 const char *name,
+				 int def);
+
+extern void prom_build_devicetree(void);
+
+#endif /* __KERNEL__ */
+#endif /* _SPARC_PROM_H */
diff --git a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h
index a13cddc..d036e44 100644
--- a/include/asm-sparc/sbus.h
+++ b/include/asm-sparc/sbus.h
@@ -11,7 +11,8 @@
 #include <linux/ioport.h>
 
 #include <asm/oplib.h>
-/* #include <asm/iommu.h> */ /* Unused since we use opaque iommu (|io-unit) */
+#include <asm/prom.h>
+#include <asm/of_device.h>
 #include <asm/scatterlist.h>
 
 /* We scan which devices are on the SBus using the PROM node device
@@ -42,18 +43,19 @@
 
 /* Linux SBUS device tables */
 struct sbus_dev {
-	struct sbus_bus	*bus;       /* Back ptr to sbus */
-	struct sbus_dev	*next;      /* next device on this SBus or null */
-	struct sbus_dev	*child;     /* For ledma and espdma on sun4m */
-	struct sbus_dev	*parent;    /* Parent device if not toplevel */
-	int prom_node;              /* PROM device tree node for this device */
-	char prom_name[64];         /* PROM device name */
+	struct of_device	ofdev;
+	struct sbus_bus		*bus;
+	struct sbus_dev		*next;
+	struct sbus_dev		*child;
+	struct sbus_dev		*parent;
+	int prom_node;	
+	char prom_name[64];
 	int slot;
 
 	struct resource resource[PROMREG_MAX];
 
 	struct linux_prom_registers reg_addrs[PROMREG_MAX];
-	int num_registers, ranges_applied;
+	int num_registers;
 
 	struct linux_prom_ranges device_ranges[PROMREG_MAX];
 	int num_device_ranges;
@@ -61,9 +63,11 @@
 	unsigned int irqs[4];
 	int num_irqs;
 };
+#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)
 
 /* This struct describes the SBus(s) found on this machine. */
 struct sbus_bus {
+	struct of_device	ofdev;
 	void			*iommu;		/* Opaque IOMMU cookie */
 	struct sbus_dev		*devices;	/* Link to devices on this SBus */
 	struct sbus_bus		*next;		/* next SBus, if more than one SBus */
@@ -77,6 +81,7 @@
 	int devid;
 	int board;
 };
+#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)
 
 extern struct sbus_bus *sbus_root;
 
@@ -102,6 +107,7 @@
 #define sbus_can_dma_64bit(sdev)	(0) /* actually, sparc_cpu_model==sun4d */
 #define sbus_can_burst64(sdev)		(0) /* actually, sparc_cpu_model==sun4d */
 extern void sbus_set_sbus64(struct sbus_dev *, int);
+extern void sbus_fill_device_irq(struct sbus_dev *);
 
 /* These yield IOMMU mappings in consistent mode. */
 extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp);
@@ -139,4 +145,10 @@
 BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int)
 #define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint)
 
+extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
+extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
+extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
+extern int sbus_arch_preinit(void);
+extern void sbus_arch_postinit(void);
+
 #endif /* !(_SPARC_SBUS_H) */
diff --git a/include/asm-sparc/sfp-machine.h b/include/asm-sparc/sfp-machine.h
index b4ca2d9..ecfc86a 100644
--- a/include/asm-sparc/sfp-machine.h
+++ b/include/asm-sparc/sfp-machine.h
@@ -25,7 +25,6 @@
 #ifndef _SFP_MACHINE_H
 #define _SFP_MACHINE_H
 
-#include <linux/config.h>
    
 #define _FP_W_TYPE_SIZE		32
 #define _FP_W_TYPE		unsigned long
diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h
index 98c46e3..b9da9a6 100644
--- a/include/asm-sparc/smp.h
+++ b/include/asm-sparc/smp.h
@@ -6,7 +6,6 @@
 #ifndef _SPARC_SMP_H
 #define _SPARC_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/head.h>
 #include <asm/btfixup.h>
@@ -146,6 +145,8 @@
 #define prof_multiplier(__cpu)		cpu_data(__cpu).multiplier
 #define prof_counter(__cpu)		cpu_data(__cpu).counter
 
+void smp_setup_cpu_possible_map(void);
+
 #endif /* !(__ASSEMBLY__) */
 
 /* Sparc specific messages. */
@@ -162,7 +163,11 @@
 #define MBOX_IDLECPU2         0xFD
 #define MBOX_STOPCPU2         0xFE
 
-#endif /* SMP */
+#else /* SMP */
+
+#define smp_setup_cpu_possible_map() do { } while (0)
+
+#endif /* !(SMP) */
 
 #define NO_PROC_ID            0xFF
 
diff --git a/include/asm-sparc/spinlock.h b/include/asm-sparc/spinlock.h
index 3350c90..1c75474 100644
--- a/include/asm-sparc/spinlock.h
+++ b/include/asm-sparc/spinlock.h
@@ -154,6 +154,9 @@
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
 #define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
 
+#define __raw_read_can_lock(rw) (!((rw)->lock & 0xff))
+#define __raw_write_can_lock(rw) (!(rw)->lock)
+
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* __SPARC_SPINLOCK_H */
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 58dd162..cb7dda1 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -1,10 +1,8 @@
 /* $Id: system.h,v 1.86 2001/10/30 04:57:10 davem Exp $ */
-#include <linux/config.h>
 
 #ifndef __SPARC_SYSTEM_H
 #define __SPARC_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/threads.h>	/* NR_CPUS */
 #include <linux/thread_info.h>
diff --git a/include/asm-sparc/timer.h b/include/asm-sparc/timer.h
index b16eb73..cb1fa1d 100644
--- a/include/asm-sparc/timer.h
+++ b/include/asm-sparc/timer.h
@@ -4,7 +4,6 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 
 #ifndef _SPARC_TIMER_H
 #define _SPARC_TIMER_H
diff --git a/include/asm-sparc/tlbflush.h b/include/asm-sparc/tlbflush.h
index 5643ca3..4a3b666 100644
--- a/include/asm-sparc/tlbflush.h
+++ b/include/asm-sparc/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _SPARC_TLBFLUSH_H
 #define _SPARC_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 // #include <asm/processor.h>
 
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index 45a5765..2553762 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -319,6 +319,7 @@
 #define __NR_set_robust_list	300
 #define __NR_get_robust_list	301
 
+#ifdef __KERNEL__
 /* WARNING: You MAY NOT add syscall numbers larger than 301, since
  *          all of the syscall tables in the Sparc kernel are
  *          sized to have 301 entries (starting at zero).  Therefore
@@ -455,7 +456,6 @@
 return -1; \
 }
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -477,7 +477,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -534,4 +533,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _SPARC_UNISTD_H */
diff --git a/include/asm-sparc/vac-ops.h b/include/asm-sparc/vac-ops.h
index 9e01723..ab6f53b 100644
--- a/include/asm-sparc/vac-ops.h
+++ b/include/asm-sparc/vac-ops.h
@@ -8,7 +8,6 @@
  * Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 #include <asm/sysen.h>
 #include <asm/contregs.h>
 #include <asm/asi.h>
diff --git a/include/asm-sparc/winmacro.h b/include/asm-sparc/winmacro.h
index 557257e..096f3d3 100644
--- a/include/asm-sparc/winmacro.h
+++ b/include/asm-sparc/winmacro.h
@@ -7,7 +7,6 @@
 #ifndef _SPARC_WINMACRO_H
 #define _SPARC_WINMACRO_H
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 
 /* Store the register window onto the 8-byte aligned area starting
diff --git a/include/asm-sparc64/atomic.h b/include/asm-sparc64/atomic.h
index 468eb48..2f0bec2 100644
--- a/include/asm-sparc64/atomic.h
+++ b/include/asm-sparc64/atomic.h
@@ -8,7 +8,6 @@
 #ifndef __ARCH_SPARC64_ATOMIC__
 #define __ARCH_SPARC64_ATOMIC__
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 typedef struct { volatile int counter; } atomic_t;
diff --git a/include/asm-sparc64/bitops.h b/include/asm-sparc64/bitops.h
index 71944b0..3d5e1af 100644
--- a/include/asm-sparc64/bitops.h
+++ b/include/asm-sparc64/bitops.h
@@ -7,7 +7,6 @@
 #ifndef _SPARC64_BITOPS_H
 #define _SPARC64_BITOPS_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/byteorder.h>
 
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
index 360dd04..120422f 100644
--- a/include/asm-sparc64/bugs.h
+++ b/include/asm-sparc64/bugs.h
@@ -4,7 +4,6 @@
  *  Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <linux/config.h>
 
 extern unsigned long loops_per_jiffy;
 
diff --git a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
index b3f6165..745d1ab 100644
--- a/include/asm-sparc64/cacheflush.h
+++ b/include/asm-sparc64/cacheflush.h
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_CACHEFLUSH_H
 #define _SPARC64_CACHEFLUSH_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
index 9d6a6db..f2cc941 100644
--- a/include/asm-sparc64/cpudata.h
+++ b/include/asm-sparc64/cpudata.h
@@ -74,8 +74,10 @@
 	unsigned long		tsb_huge;
 	unsigned long		tsb_huge_temp;
 
-/* Dcache line 8: Unused, needed to keep trap_block a power-of-2 in size.  */
-	unsigned long		__pad2[4];
+/* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size.  */
+	unsigned int		irq_worklist;
+	unsigned int		__pad1;
+	unsigned long		__pad2[3];
 } __attribute__((aligned(64)));
 extern struct trap_per_cpu trap_block[NR_CPUS];
 extern void init_cur_cpu_trap(struct thread_info *);
@@ -119,6 +121,7 @@
 #define TRAP_PER_CPU_CPU_LIST_PA	0xc8
 #define TRAP_PER_CPU_TSB_HUGE		0xd0
 #define TRAP_PER_CPU_TSB_HUGE_TEMP	0xd8
+#define TRAP_PER_CPU_IRQ_WORKLIST	0xe0
 
 #define TRAP_BLOCK_SZ_SHIFT		8
 
@@ -171,11 +174,8 @@
 
 /* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
 #define TRAP_LOAD_IRQ_WORK(DEST, TMP)		\
-	__GET_CPUID(TMP)			\
-	sethi	%hi(__irq_work), DEST;		\
-	sllx	TMP, 6, TMP;			\
-	or	DEST, %lo(__irq_work), DEST;	\
-	add	DEST, TMP, DEST;
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST, DEST;
 
 /* Clobbers TMP, loads DEST with current thread info pointer.  */
 #define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
@@ -211,9 +211,10 @@
 	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
 	ldx	[DEST + TRAP_PER_CPU_PGD_PADDR], DEST;
 
+/* Clobbers TMP, loads local processor's IRQ work area into DEST.  */
 #define TRAP_LOAD_IRQ_WORK(DEST, TMP)		\
-	sethi	%hi(__irq_work), DEST;		\
-	or	DEST, %lo(__irq_work), DEST;
+	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
+	add	DEST, TRAP_PER_CPU_IRQ_WORKLIST, DEST;
 
 #define TRAP_LOAD_THREAD_REG(DEST, TMP)		\
 	TRAP_LOAD_TRAP_BLOCK(DEST, TMP)		\
diff --git a/include/asm-sparc64/delay.h b/include/asm-sparc64/delay.h
index 2901ea0..a4aae6f 100644
--- a/include/asm-sparc64/delay.h
+++ b/include/asm-sparc64/delay.h
@@ -11,7 +11,6 @@
 #ifndef __SPARC64_DELAY_H
 #define __SPARC64_DELAY_H
 
-#include <linux/config.h>
 #include <linux/param.h>
 #include <asm/cpudata.h>
 
diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h
index a8d39f2..0f5b89c 100644
--- a/include/asm-sparc64/dma-mapping.h
+++ b/include/asm-sparc64/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_SPARC64_DMA_MAPPING_H
 #define _ASM_SPARC64_DMA_MAPPING_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 
@@ -163,4 +162,47 @@
 
 #endif /* PCI */
 
+
+/* Now for the API extensions over the pci_ one */
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d)	(1)
+
+static inline int
+dma_get_cache_alignment(void)
+{
+	/* no easy way to get cache size on all processors, so return
+	 * the maximum possible, to be safe */
+	return (1 << INTERNODE_CACHE_SHIFT);
+}
+
+static inline void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+			      unsigned long offset, size_t size,
+			      enum dma_data_direction direction)
+{
+	/* just sync everything, that's all the pci API can do */
+	dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
+}
+
+static inline void
+dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+				 unsigned long offset, size_t size,
+				 enum dma_data_direction direction)
+{
+	/* just sync everything, that's all the pci API can do */
+	dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
+}
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	/* could define this in terms of the dma_cache ... operations,
+	 * but if you get this on a platform, you should convert the platform
+	 * to using the generic device DMA API */
+	BUG();
+}
+
 #endif /* _ASM_SPARC64_DMA_MAPPING_H */
diff --git a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h
index 1aab3c8..27f6597 100644
--- a/include/asm-sparc64/dma.h
+++ b/include/asm-sparc64/dma.h
@@ -7,7 +7,6 @@
 #ifndef _ASM_SPARC64_DMA_H
 #define _ASM_SPARC64_DMA_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/spinlock.h>
diff --git a/include/asm-sparc64/ebus.h b/include/asm-sparc64/ebus.h
index 7a408a0..a4afe9d 100644
--- a/include/asm-sparc64/ebus.h
+++ b/include/asm-sparc64/ebus.h
@@ -10,13 +10,14 @@
 
 #include <asm/pbm.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
 
 struct linux_ebus_child {
 	struct linux_ebus_child		*next;
 	struct linux_ebus_device	*parent;
 	struct linux_ebus		*bus;
-	int				 prom_node;
-	char				 prom_name[64];
+	struct device_node		*prom_node;
 	struct resource			 resource[PROMREG_MAX];
 	int				 num_addrs;
 	unsigned int			 irqs[PROMINTR_MAX];
@@ -24,32 +25,29 @@
 };
 
 struct linux_ebus_device {
+	struct of_device		ofdev;
 	struct linux_ebus_device	*next;
 	struct linux_ebus_child		*children;
 	struct linux_ebus		*bus;
-	int				 prom_node;
-	char				 prom_name[64];
+	struct device_node		*prom_node;
 	struct resource			 resource[PROMREG_MAX];
 	int				 num_addrs;
 	unsigned int			 irqs[PROMINTR_MAX];
 	int				 num_irqs;
 };
+#define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev)
 
 struct linux_ebus {
+	struct of_device		ofdev;
 	struct linux_ebus		*next;
 	struct linux_ebus_device	*devices;
 	struct pci_pbm_info		*parent;
 	struct pci_dev			*self;
 	int				 index;
 	int				 is_rio;
-	int				 prom_node;
-	char				 prom_name[64];
-	struct linux_prom_ebus_ranges	 ebus_ranges[PROMREG_MAX];
-	int				 num_ebus_ranges;
-	struct linux_prom_ebus_intmap	 ebus_intmap[PROMREG_MAX];
-	int				 num_ebus_intmap;
-	struct linux_prom_ebus_intmask	 ebus_intmask;
+	struct device_node		*prom_node;
 };
+#define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev)
 
 struct ebus_dma_info {
 	spinlock_t	lock;
diff --git a/include/asm-sparc64/fhc.h b/include/asm-sparc64/fhc.h
index f29eaa2..9e7f1b0 100644
--- a/include/asm-sparc64/fhc.h
+++ b/include/asm-sparc64/fhc.h
@@ -10,6 +10,7 @@
 #include <linux/timer.h>
 
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/upa.h>
 
 struct linux_fhc;
@@ -34,8 +35,7 @@
 	unsigned long			clkregs;
 	unsigned long			clkver;
 	int				slots;
-	int				prom_node;
-	char				prom_name[64];
+	struct device_node		*prom_node;
 
 	struct linux_prom_ranges	central_ranges[PROMREG_MAX];
 	int				num_central_ranges;
@@ -112,8 +112,7 @@
 	struct fhc_regs			fhc_regs;
 	int				board;
 	int				jtag_master;
-	int				prom_node;
-	char				prom_name[64];
+	struct device_node		*prom_node;
 
 	struct linux_prom_ranges	fhc_ranges[PROMREG_MAX];
 	int				num_fhc_ranges;
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index 6a95d5d..b591d0e 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -10,7 +10,6 @@
 #ifndef __ASM_SPARC64_FLOPPY_H
 #define __ASM_SPARC64_FLOPPY_H
 
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <asm/page.h>
@@ -209,7 +208,55 @@
 	pdma_areasize = pdma_size;
 }
 
-extern irqreturn_t sparc_floppy_irq(int, void *, struct pt_regs *);
+irqreturn_t sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
+{
+	if (likely(doing_pdma)) {
+		void __iomem *stat = (void __iomem *) fdc_status;
+		unsigned char *vaddr = pdma_vaddr;
+		unsigned long size = pdma_size;
+		u8 val;
+
+		while (size) {
+			val = readb(stat);
+			if (unlikely(!(val & 0x80))) {
+				pdma_vaddr = vaddr;
+				pdma_size = size;
+				return IRQ_HANDLED;
+			}
+			if (unlikely(!(val & 0x20))) {
+				pdma_vaddr = vaddr;
+				pdma_size = size;
+				doing_pdma = 0;
+				goto main_interrupt;
+			}
+			if (val & 0x40) {
+				/* read */
+				*vaddr++ = readb(stat + 1);
+			} else {
+				unsigned char data = *vaddr++;
+
+				/* write */
+				writeb(data, stat + 1);
+			}
+			size--;
+		}
+
+		pdma_vaddr = vaddr;
+		pdma_size = size;
+
+		/* Send Terminal Count pulse to floppy controller. */
+		val = readb(auxio_register);
+		val |= AUXIO_AUX1_FTCNT;
+		writeb(val, auxio_register);
+		val &= ~AUXIO_AUX1_FTCNT;
+		writeb(val, auxio_register);
+
+		doing_pdma = 0;
+	}
+
+main_interrupt:
+	return floppy_interrupt(irq, dev_cookie, regs);
+}
 
 static int sun_fd_request_irq(void)
 {
@@ -499,15 +546,14 @@
 #ifdef CONFIG_PCI
 static int __init ebus_fdthree_p(struct linux_ebus_device *edev)
 {
-	if (!strcmp(edev->prom_name, "fdthree"))
+	if (!strcmp(edev->prom_node->name, "fdthree"))
 		return 1;
-	if (!strcmp(edev->prom_name, "floppy")) {
-		char compat[16];
-		prom_getstring(edev->prom_node,
-			       "compatible",
-			       compat, sizeof(compat));
-		compat[15] = '\0';
-		if (!strcmp(compat, "fdthree"))
+	if (!strcmp(edev->prom_node->name, "floppy")) {
+		char *compat;
+
+		compat = of_get_property(edev->prom_node,
+					 "compatible", NULL);
+		if (compat && !strcmp(compat, "fdthree"))
 			return 1;
 	}
 	return 0;
@@ -525,12 +571,12 @@
 
 	for_each_isa(isa_br) {
 		for_each_isadev(isa_dev, isa_br) {
-			if (!strcmp(isa_dev->prom_name, "dma")) {
+			if (!strcmp(isa_dev->prom_node->name, "dma")) {
 				struct sparc_isa_device *child =
 					isa_dev->child;
 
 				while (child) {
-					if (!strcmp(child->prom_name,
+					if (!strcmp(child->prom_node->name,
 						    "floppy")) {
 						isa_dev = child;
 						goto isa_done;
@@ -615,6 +661,7 @@
 		struct linux_ebus_device *edev = NULL;
 		unsigned long config = 0;
 		void __iomem *auxio_reg;
+		char *state_prop;
 
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
@@ -631,9 +678,8 @@
 #endif
 		}
 
-		prom_getproperty(edev->prom_node, "status",
-				 state, sizeof(state));
-		if (!strncmp(state, "disabled", 8))
+		state_prop = of_get_property(edev->prom_node, "status", NULL);
+		if (state_prop && !strncmp(state_prop, "disabled", 8))
 			return 0;
 			
 		FLOPPY_IRQ = edev->irqs[0];
@@ -704,7 +750,7 @@
 		 */
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
-				if (!strcmp(edev->prom_name, "ecpp")) {
+				if (!strcmp(edev->prom_node->name, "ecpp")) {
 					config = edev->resource[1].start;
 					goto config_done;
 				}
diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
index f0cf713..7c29fd1 100644
--- a/include/asm-sparc64/hardirq.h
+++ b/include/asm-sparc64/hardirq.h
@@ -12,6 +12,8 @@
 #define local_softirq_pending() \
 	(local_cpu_data().__softirq_pending)
 
+void ack_bad_irq(unsigned int irq);
+
 #define HARDIRQ_BITS	8
 
 #endif /* !(__SPARC64_HARDIRQ_H) */
diff --git a/include/asm-sparc64/hw_irq.h b/include/asm-sparc64/hw_irq.h
index 153cae2..599b3b0 100644
--- a/include/asm-sparc64/hw_irq.h
+++ b/include/asm-sparc64/hw_irq.h
@@ -1,6 +1,6 @@
 #ifndef __ASM_SPARC64_HW_IRQ_H
 #define __ASM_SPARC64_HW_IRQ_H
 
-/* Dummy include. */
+extern void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq);
 
 #endif
diff --git a/include/asm-sparc64/ide.h b/include/asm-sparc64/ide.h
index c393f81..55149cf 100644
--- a/include/asm-sparc64/ide.h
+++ b/include/asm-sparc64/ide.h
@@ -10,7 +10,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <asm/pgalloc.h>
 #include <asm/io.h>
 #include <asm/spitfire.h>
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index de33d6e..905e59b 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -8,7 +8,6 @@
 #ifndef _SPARC64_IRQ_H
 #define _SPARC64_IRQ_H
 
-#include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -16,58 +15,6 @@
 #include <asm/pil.h>
 #include <asm/ptrace.h>
 
-struct ino_bucket;
-
-#define MAX_IRQ_DESC_ACTION	4
-
-struct irq_desc {
-	void			(*pre_handler)(struct ino_bucket *, void *, void *);
-	void			*pre_handler_arg1;
-	void			*pre_handler_arg2;
-	u32			action_active_mask;
-	struct irqaction	action[MAX_IRQ_DESC_ACTION];
-};
-
-/* You should not mess with this directly. That's the job of irq.c.
- *
- * If you make changes here, please update hand coded assembler of
- * the vectored interrupt trap handler in entry.S -DaveM
- *
- * This is currently one DCACHE line, two buckets per L2 cache
- * line.  Keep this in mind please.
- */
-struct ino_bucket {
-	/* Next handler in per-CPU PIL worklist.  We know that
-	 * bucket pointers have the high 32-bits clear, so to
-	 * save space we only store the bits we need.
-	 */
-/*0x00*/unsigned int irq_chain;
-
-	/* PIL to schedule this IVEC at. */
-/*0x04*/unsigned char pil;
-
-	/* If an IVEC arrives while irq_info is NULL, we
-	 * set this to notify request_irq() about the event.
-	 */
-/*0x05*/unsigned char pending;
-
-	/* Miscellaneous flags. */
-/*0x06*/unsigned char flags;
-
-	/* Currently unused.  */
-/*0x07*/unsigned char __pad;
-
-	/* Reference to IRQ descriptor for this bucket. */
-/*0x08*/struct irq_desc *irq_info;
-
-	/* Sun5 Interrupt Clear Register. */
-/*0x10*/unsigned long iclr;
-
-	/* Sun5 Interrupt Mapping Register. */
-/*0x18*/unsigned long imap;
-
-};
-
 /* IMAP/ICLR register defines */
 #define IMAP_VALID		0x80000000	/* IRQ Enabled		*/
 #define IMAP_TID_UPA		0x7c000000	/* UPA TargetID		*/
@@ -85,36 +32,20 @@
 #define ICLR_TRANSMIT		0x00000001	/* Transmit state	*/
 #define ICLR_PENDING		0x00000003	/* Pending state	*/
 
-/* Only 8-bits are available, be careful.  -DaveM */
-#define IBF_PCI		0x02	/* PSYCHO/SABRE/SCHIZO PCI interrupt.	 */
-#define IBF_ACTIVE	0x04	/* Interrupt is active and has a handler.*/
-#define IBF_INPROGRESS	0x10	/* IRQ is being serviced.		 */
+/* The largest number of unique interrupt sources we support.
+ * If this needs to ever be larger than 255, you need to change
+ * the type of ino_bucket->virt_irq as appropriate.
+ *
+ * ino_bucket->virt_irq allocation is made during {sun4v_,}build_irq().
+ */
+#define NR_IRQS    255
 
-#define NUM_IVECS	(IMAP_INR + 1)
-extern struct ino_bucket ivector_table[NUM_IVECS];
-
-#define __irq_ino(irq) \
-        (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0])
-#define __irq_pil(irq) ((struct ino_bucket *)(unsigned long)(irq))->pil
-#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq))
-#define __irq(bucket) ((unsigned int)(unsigned long)(bucket))
-
-static __inline__ char *__irq_itoa(unsigned int irq)
-{
-	static char buff[16];
-
-	sprintf(buff, "%d,%x", __irq_pil(irq), (unsigned int)__irq_ino(irq));
-	return buff;
-}
-
-#define NR_IRQS    16
-
+extern void irq_install_pre_handler(int virt_irq,
+				    void (*func)(unsigned int, void *, void *),
+				    void *arg1, void *arg2);
 #define irq_canonicalize(irq)	(irq)
-extern void disable_irq(unsigned int);
-#define disable_irq_nosync disable_irq
-extern void enable_irq(unsigned int);
-extern unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap);
-extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags);
+extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
+extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
 extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
 
 static __inline__ void set_softint(unsigned long bits)
@@ -140,8 +71,4 @@
 	return retval;
 }
 
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif
diff --git a/include/asm-sparc64/isa.h b/include/asm-sparc64/isa.h
index 4601bbf..d9728b9 100644
--- a/include/asm-sparc64/isa.h
+++ b/include/asm-sparc64/isa.h
@@ -9,37 +9,32 @@
 
 #include <asm/pbm.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
 
 struct sparc_isa_bridge;
 
 struct sparc_isa_device {
+	struct of_device	ofdev;
 	struct sparc_isa_device	*next;
 	struct sparc_isa_device	*child;
 	struct sparc_isa_bridge	*bus;
-	int			prom_node;
-	char			prom_name[64];
-	char			compatible[64];
+	struct device_node	*prom_node;
 	struct resource		resource;
 	unsigned int		irq;
 };
+#define to_isa_device(d) container_of(d, struct sparc_isa_device, ofdev.dev)
 
 struct sparc_isa_bridge {
+	struct of_device	ofdev;
 	struct sparc_isa_bridge	*next;
 	struct sparc_isa_device	*devices;
 	struct pci_pbm_info	*parent;
 	struct pci_dev		*self;
 	int			index;
-	int			prom_node;
-	char			prom_name[64];
-#define linux_prom_isa_ranges linux_prom_ebus_ranges
-	struct linux_prom_isa_ranges	isa_ranges[PROMREG_MAX];
-	int			num_isa_ranges;
-#define linux_prom_isa_intmap	linux_prom_ebus_intmap
-	struct linux_prom_isa_intmap	isa_intmap[PROMREG_MAX];
-	int			num_isa_intmap;
-#define linux_prom_isa_intmask	linux_prom_ebus_intmask
-	struct linux_prom_isa_intmap	isa_intmask;
+	struct device_node	*prom_node;
 };
+#define to_isa_bridge(d) container_of(d, struct sparc_isa_bridge, ofdev.dev)
 
 extern struct sparc_isa_bridge	*isa_chain;
 
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index 4040d12..11251bd 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -17,6 +17,8 @@
 
 extern int register_die_notifier(struct notifier_block *);
 extern int unregister_die_notifier(struct notifier_block *);
+extern int register_page_fault_notifier(struct notifier_block *);
+extern int unregister_page_fault_notifier(struct notifier_block *);
 extern struct atomic_notifier_head sparc64die_chain;
 
 extern void bad_trap(struct pt_regs *, long);
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index e4efe65..15065af 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/percpu.h>
 
@@ -13,6 +12,7 @@
 
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 #define arch_remove_kprobe(p)	do {} while (0)
+#define  ARCH_INACTIVE_KPROBE_COUNT 0
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
diff --git a/include/asm-sparc64/mc146818rtc.h b/include/asm-sparc64/mc146818rtc.h
index 75bd572..e9c0fcc 100644
--- a/include/asm-sparc64/mc146818rtc.h
+++ b/include/asm-sparc64/mc146818rtc.h
@@ -4,7 +4,6 @@
 #ifndef __ASM_SPARC64_MC146818RTC_H
 #define __ASM_SPARC64_MC146818RTC_H
 
-#include <linux/config.h>
 #include <asm/io.h>
 
 #ifndef RTC_PORT
diff --git a/include/asm-sparc64/mmu.h b/include/asm-sparc64/mmu.h
index 2d4f2ea..70af4b6 100644
--- a/include/asm-sparc64/mmu.h
+++ b/include/asm-sparc64/mmu.h
@@ -1,7 +1,6 @@
 #ifndef __MMU_H
 #define __MMU_H
 
-#include <linux/config.h>
 #include <asm/page.h>
 #include <asm/const.h>
 #include <asm/hypervisor.h>
diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h
new file mode 100644
index 0000000..024088e
--- /dev/null
+++ b/include/asm-sparc64/of_device.h
@@ -0,0 +1,64 @@
+#ifndef _ASM_SPARC64_OF_DEVICE_H
+#define _ASM_SPARC64_OF_DEVICE_H
+#ifdef __KERNEL__
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <asm/prom.h>
+
+extern struct bus_type isa_bus_type;
+extern struct bus_type ebus_bus_type;
+extern struct bus_type sbus_bus_type;
+
+/*
+ * The of_device is a kind of "base class" that is a superset of
+ * struct device for use by devices attached to an OF node and
+ * probed using OF properties.
+ */
+struct of_device
+{
+	struct device_node	*node;		/* OF device node */
+	struct device		dev;		/* Generic device interface */
+};
+#define	to_of_device(d) container_of(d, struct of_device, dev)
+
+extern const struct of_device_id *of_match_device(
+	const struct of_device_id *matches, const struct of_device *dev);
+
+extern struct of_device *of_dev_get(struct of_device *dev);
+extern void of_dev_put(struct of_device *dev);
+
+/*
+ * An of_platform_driver driver is attached to a basic of_device on
+ * the ISA, EBUS, and SBUS busses on sparc64.
+ */
+struct of_platform_driver
+{
+	char			*name;
+	struct of_device_id	*match_table;
+	struct module		*owner;
+
+	int	(*probe)(struct of_device* dev, const struct of_device_id *match);
+	int	(*remove)(struct of_device* dev);
+
+	int	(*suspend)(struct of_device* dev, pm_message_t state);
+	int	(*resume)(struct of_device* dev);
+	int	(*shutdown)(struct of_device* dev);
+
+	struct device_driver	driver;
+};
+#define	to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
+
+extern int of_register_driver(struct of_platform_driver *drv,
+			      struct bus_type *bus);
+extern void of_unregister_driver(struct of_platform_driver *drv);
+extern int of_device_register(struct of_device *ofdev);
+extern void of_device_unregister(struct of_device *ofdev);
+extern struct of_device *of_platform_device_create(struct device_node *np,
+						   const char *bus_id,
+						   struct device *parent,
+						   struct bus_type *bus);
+extern void of_release_dev(struct device *dev);
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_SPARC64_OF_DEVICE_H */
diff --git a/include/asm-sparc64/oplib.h b/include/asm-sparc64/oplib.h
index c754676..a68b0bb 100644
--- a/include/asm-sparc64/oplib.h
+++ b/include/asm-sparc64/oplib.h
@@ -9,7 +9,6 @@
 #ifndef __SPARC64_OPLIB_H
 #define __SPARC64_OPLIB_H
 
-#include <linux/config.h>
 #include <asm/openprom.h>
 
 /* OBP version string. */
@@ -324,8 +323,9 @@
 extern int prom_inst2pkg(int);
 
 /* CPU probing helpers.  */
-int cpu_find_by_instance(int instance, int *prom_node, int *mid);
-int cpu_find_by_mid(int mid, int *prom_node);
+struct device_node;
+int cpu_find_by_instance(int instance, struct device_node **dev_node, int *mid);
+int cpu_find_by_mid(int mid, struct device_node **prom_node);
 
 /* Client interface level routines. */
 extern void prom_set_trap_table(unsigned long tba);
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index aabb219..fdf0ceb 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -3,7 +3,6 @@
 #ifndef _SPARC64_PAGE_H
 #define _SPARC64_PAGE_H
 
-#include <linux/config.h>
 #include <asm/const.h>
 
 #if defined(CONFIG_SPARC64_PAGE_SIZE_8KB)
diff --git a/include/asm-sparc64/param.h b/include/asm-sparc64/param.h
index a1cd497..f0125cf 100644
--- a/include/asm-sparc64/param.h
+++ b/include/asm-sparc64/param.h
@@ -1,7 +1,6 @@
 #ifndef _ASMSPARC64_PARAM_H
 #define _ASMSPARC64_PARAM_H
 
-#include <linux/config.h>
 
 #ifdef __KERNEL__
 # define HZ		CONFIG_HZ	/* Internal kernel timer frequency */
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index 56b5197d..d389587 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -67,18 +67,17 @@
 
 static int ebus_ecpp_p(struct linux_ebus_device *edev)
 {
-	if (!strcmp(edev->prom_name, "ecpp"))
+	if (!strcmp(edev->prom_node->name, "ecpp"))
 		return 1;
-	if (!strcmp(edev->prom_name, "parallel")) {
-		char compat[19];
-		prom_getstring(edev->prom_node,
-			       "compatible",
-			       compat, sizeof(compat));
-		compat[18] = '\0';
-		if (!strcmp(compat, "ecpp"))
-			return 1;
-		if (!strcmp(compat, "ns87317-ecpp") &&
-		    !strcmp(compat + 13, "ecpp"))
+	if (!strcmp(edev->prom_node->name, "parallel")) {
+		char *compat;
+
+		compat = of_get_property(edev->prom_node,
+					 "compatible", NULL);
+		if (compat &&
+		    (!strcmp(compat, "ecpp") ||
+		     !strcmp(compat, "ns87317-ecpp") ||
+		     !strcmp(compat + 13, "ecpp")))
 			return 1;
 	}
 	return 0;
@@ -94,12 +93,12 @@
 			struct sparc_isa_device *child;
 			unsigned long base;
 
-			if (strcmp(isa_dev->prom_name, "dma"))
+			if (strcmp(isa_dev->prom_node->name, "dma"))
 				continue;
 
 			child = isa_dev->child;
 			while (child) {
-				if (!strcmp(child->prom_name, "parallel"))
+				if (!strcmp(child->prom_node->name, "parallel"))
 					break;
 				child = child->next;
 			}
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
index 1396f11..cebe80b 100644
--- a/include/asm-sparc64/pbm.h
+++ b/include/asm-sparc64/pbm.h
@@ -15,6 +15,7 @@
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/oplib.h>
+#include <asm/prom.h>
 #include <asm/iommu.h>
 
 /* The abstraction used here is that there are PCI controllers,
@@ -153,16 +154,15 @@
 	int				chip_revision;
 
 	/* Name used for top-level resources. */
-	char				name[64];
+	char				*name;
 
 	/* OBP specific information. */
-	int				prom_node;
-	char				prom_name[64];
-	struct linux_prom_pci_ranges	pbm_ranges[PROM_PCIRNG_MAX];
+	struct device_node		*prom_node;
+	struct linux_prom_pci_ranges	*pbm_ranges;
 	int				num_pbm_ranges;
-	struct linux_prom_pci_intmap	pbm_intmap[PROM_PCIIMAP_MAX];
+	struct linux_prom_pci_intmap	*pbm_intmap;
 	int				num_pbm_intmap;
-	struct linux_prom_pci_intmask	pbm_intmask;
+	struct linux_prom_pci_intmask	*pbm_intmask;
 	u64				ino_bitmap;
 
 	/* PBM I/O and Memory space resources. */
@@ -227,8 +227,7 @@
  */
 struct pcidev_cookie {
 	struct pci_pbm_info		*pbm;
-	char				prom_name[64];
-	int				prom_node;
+	struct device_node		*prom_node;
 	struct linux_prom_pci_registers	prom_regs[PROMREG_MAX];
 	int num_prom_regs;
 	struct linux_prom_pci_registers prom_assignments[PROMREG_MAX];
diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
index baef13b..a6ece06 100644
--- a/include/asm-sparc64/percpu.h
+++ b/include/asm-sparc64/percpu.h
@@ -21,6 +21,7 @@
 /* var is in discarded region: offset to particular copy we want */
 #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
 #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
 
 /* A macro to avoid #include hell... */
 #define percpu_modcopy(pcpudst, src, size)			\
@@ -37,6 +38,7 @@
 
 #define per_cpu(var, cpu)			(*((void)cpu, &per_cpu__##var))
 #define __get_cpu_var(var)			per_cpu__##var
+#define __raw_get_cpu_var(var)			per_cpu__##var
 
 #endif	/* SMP */
 
diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
index 12e4a27..010f9cd 100644
--- a/include/asm-sparc64/pgalloc.h
+++ b/include/asm-sparc64/pgalloc.h
@@ -2,7 +2,6 @@
 #ifndef _SPARC64_PGALLOC_H
 #define _SPARC64_PGALLOC_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index cd464f4..03f5bc9 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -14,7 +14,6 @@
 
 #include <asm-generic/pgtable-nopud.h>
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <asm/types.h>
 #include <asm/spitfire.h>
@@ -757,6 +756,8 @@
 #define kern_addr_valid(addr)	\
 	(test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
 
+extern int page_in_phys_avail(unsigned long paddr);
+
 extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
 			       unsigned long pfn,
 			       unsigned long size, pgprot_t prot);
diff --git a/include/asm-sparc64/pil.h b/include/asm-sparc64/pil.h
index 79f827e..7292774 100644
--- a/include/asm-sparc64/pil.h
+++ b/include/asm-sparc64/pil.h
@@ -5,9 +5,9 @@
 /* To avoid some locking problems, we hard allocate certain PILs
  * for SMP cross call messages that must do a etrap/rtrap.
  *
- * A cli() does not block the cross call delivery, so when SMP
- * locking is an issue we reschedule the event into a PIL interrupt
- * which is blocked by cli().
+ * A local_irq_disable() does not block the cross call delivery, so
+ * when SMP locking is an issue we reschedule the event into a PIL
+ * interrupt which is blocked by local_irq_disable().
  *
  * In fact any XCALL which has to etrap/rtrap has a problem because
  * it is difficult to prevent rtrap from running BH's, and that would
@@ -17,6 +17,7 @@
 #define PIL_SMP_RECEIVE_SIGNAL	2
 #define PIL_SMP_CAPTURE		3
 #define PIL_SMP_CTX_NEW_VERSION	4
+#define PIL_DEVICE_IRQ		5
 
 #ifndef __ASSEMBLY__
 #define PIL_RESERVED(PIL)	((PIL) == PIL_SMP_CALL_FUNC || \
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index c6896b8..66dd2fa 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -13,7 +13,6 @@
  */
 #define current_text_addr() ({ void *pc; __asm__("rd %%pc, %0" : "=r" (pc)); pc; })
 
-#include <linux/config.h>
 #include <asm/asi.h>
 #include <asm/a.out.h>
 #include <asm/pstate.h>
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
new file mode 100644
index 0000000..265614d
--- /dev/null
+++ b/include/asm-sparc64/prom.h
@@ -0,0 +1,108 @@
+#ifndef _SPARC64_PROM_H
+#define _SPARC64_PROM_H
+#ifdef __KERNEL__
+
+
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
+ * Updates for SPARC64 by David S. Miller
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/atomic.h>
+
+typedef u32 phandle;
+typedef u32 ihandle;
+
+struct interrupt_info {
+	int	line;
+	int	sense;		/* +ve/-ve logic, edge or level, etc. */
+};
+
+struct property {
+	char	*name;
+	int	length;
+	void	*value;
+	struct property *next;
+	unsigned long _flags;
+	unsigned int unique_id;
+};
+
+struct device_node {
+	char	*name;
+	char	*type;
+	phandle	node;
+	phandle linux_phandle;
+	int	n_intrs;
+	struct	interrupt_info *intrs;
+	char	*path_component_name;
+	char	*full_name;
+
+	struct	property *properties;
+	struct  property *deadprops; /* removed properties */
+	struct	device_node *parent;
+	struct	device_node *child;
+	struct	device_node *sibling;
+	struct	device_node *next;	/* next device of same type */
+	struct	device_node *allnext;	/* next in list of all nodes */
+	struct  proc_dir_entry *pde;	/* this node's proc directory */
+	struct  kref kref;
+	unsigned long _flags;
+	void	*data;
+	unsigned int unique_id;
+};
+
+/* flag descriptions */
+#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */
+
+#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
+#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
+
+static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de)
+{
+	dn->pde = de;
+}
+
+extern struct device_node *of_find_node_by_name(struct device_node *from,
+	const char *name);
+#define for_each_node_by_name(dn, name) \
+	for (dn = of_find_node_by_name(NULL, name); dn; \
+	     dn = of_find_node_by_name(dn, name))
+extern struct device_node *of_find_node_by_type(struct device_node *from,
+	const char *type);
+#define for_each_node_by_type(dn, type) \
+	for (dn = of_find_node_by_type(NULL, type); dn; \
+	     dn = of_find_node_by_type(dn, type))
+extern struct device_node *of_find_compatible_node(struct device_node *from,
+	const char *type, const char *compat);
+extern struct device_node *of_find_node_by_path(const char *path);
+extern struct device_node *of_find_node_by_phandle(phandle handle);
+extern struct device_node *of_get_parent(const struct device_node *node);
+extern struct device_node *of_get_next_child(const struct device_node *node,
+					     struct device_node *prev);
+extern struct property *of_find_property(struct device_node *np,
+					 const char *name,
+					 int *lenp);
+extern int of_device_is_compatible(struct device_node *device, const char *);
+extern void *of_get_property(struct device_node *node, const char *name,
+			     int *lenp);
+extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
+extern int of_getintprop_default(struct device_node *np,
+				 const char *name,
+				 int def);
+
+extern void prom_build_devicetree(void);
+
+#endif /* __KERNEL__ */
+#endif /* _SPARC64_PROM_H */
diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
index 48279e1..56ee985 100644
--- a/include/asm-sparc64/sbus.h
+++ b/include/asm-sparc64/sbus.h
@@ -11,6 +11,8 @@
 #include <linux/ioport.h>
 
 #include <asm/oplib.h>
+#include <asm/prom.h>
+#include <asm/of_device.h>
 #include <asm/iommu.h>
 #include <asm/scatterlist.h>
 
@@ -42,18 +44,19 @@
 
 /* Linux SBUS device tables */
 struct sbus_dev {
-	struct sbus_bus *bus;	/* Our toplevel parent SBUS	*/
-	struct sbus_dev *next;	/* Chain of siblings		*/
-	struct sbus_dev *child;	/* Chain of children		*/
-	struct sbus_dev *parent;/* Parent device if not toplevel*/
-	int prom_node;		/* OBP node of this device	*/
-	char prom_name[64];	/* OBP device name property	*/
-	int slot;		/* SBUS slot number		*/
+	struct of_device	ofdev;
+	struct sbus_bus		*bus;
+	struct sbus_dev		*next;
+	struct sbus_dev		*child;
+	struct sbus_dev		*parent;
+	int prom_node;	
+	char prom_name[64];
+	int slot;
 
 	struct resource resource[PROMREG_MAX];
 
 	struct linux_prom_registers reg_addrs[PROMREG_MAX];
-	int num_registers, ranges_applied;
+	int num_registers;
 
 	struct linux_prom_ranges device_ranges[PROMREG_MAX];
 	int num_device_ranges;
@@ -61,9 +64,11 @@
 	unsigned int irqs[4];
 	int num_irqs;
 };
+#define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev)
 
 /* This struct describes the SBus(s) found on this machine. */
 struct sbus_bus {
+	struct of_device	ofdev;
 	void			*iommu;		/* Opaque IOMMU cookie	*/
 	struct sbus_dev		*devices;	/* Tree of SBUS devices	*/
 	struct sbus_bus		*next;		/* Next SBUS in system	*/
@@ -77,6 +82,7 @@
 	int portid;
 	void *starfire_cookie;
 };
+#define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev)
 
 extern struct sbus_bus *sbus_root;
 
@@ -95,6 +101,7 @@
 #define sbus_can_dma_64bit(sdev)	(1)
 #define sbus_can_burst64(sdev)		(1)
 extern void sbus_set_sbus64(struct sbus_dev *, int);
+extern void sbus_fill_device_irq(struct sbus_dev *);
 
 /* These yield IOMMU mappings in consistent mode. */
 extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp);
@@ -119,4 +126,10 @@
 #define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
 extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int);
 
+extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
+extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);
+extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *);
+extern int sbus_arch_preinit(void);
+extern void sbus_arch_postinit(void);
+
 #endif /* !(_SPARC64_SBUS_H) */
diff --git a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
index df17e47..c96e6c3 100644
--- a/include/asm-sparc64/siginfo.h
+++ b/include/asm-sparc64/siginfo.h
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compat.h>
 
 #ifdef CONFIG_COMPAT
diff --git a/include/asm-sparc64/signal.h b/include/asm-sparc64/signal.h
index e3059bb..fdc42a1 100644
--- a/include/asm-sparc64/signal.h
+++ b/include/asm-sparc64/signal.h
@@ -6,7 +6,6 @@
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/personality.h>
 #include <linux/types.h>
 #include <linux/compat.h>
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index 89d86ec..388249b 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -6,7 +6,6 @@
 #ifndef _SPARC64_SMP_H
 #define _SPARC64_SMP_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/asi.h>
 #include <asm/starfire.h>
diff --git a/include/asm-sparc64/spinlock.h b/include/asm-sparc64/spinlock.h
index 508c416..bd5ffc7 100644
--- a/include/asm-sparc64/spinlock.h
+++ b/include/asm-sparc64/spinlock.h
@@ -6,7 +6,6 @@
 #ifndef __SPARC64_SPINLOCK_H
 #define __SPARC64_SPINLOCK_H
 
-#include <linux/config.h>
 #include <linux/threads.h>	/* For NR_CPUS */
 
 #ifndef __ASSEMBLY__
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index a18ec87..4ca6860 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -2,7 +2,6 @@
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
-#include <linux/config.h>
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/visasm.h>
diff --git a/include/asm-sparc64/timer.h b/include/asm-sparc64/timer.h
index edc8e08..d435594 100644
--- a/include/asm-sparc64/timer.h
+++ b/include/asm-sparc64/timer.h
@@ -9,7 +9,6 @@
 
 #include <linux/types.h>
 
-#include <linux/config.h>
 
 struct sparc64_tick_ops {
 	void (*init_tick)(unsigned long);
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index 61c0188..7af1e11 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_TLB_H
 #define _SPARC64_TLB_H
 
-#include <linux/config.h>
 #include <linux/swap.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
diff --git a/include/asm-sparc64/tlbflush.h b/include/asm-sparc64/tlbflush.h
index e3a7c45..3487328 100644
--- a/include/asm-sparc64/tlbflush.h
+++ b/include/asm-sparc64/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _SPARC64_TLBFLUSH_H
 #define _SPARC64_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 
diff --git a/include/asm-sparc64/topology.h b/include/asm-sparc64/topology.h
index 0e234e2..98a6c61 100644
--- a/include/asm-sparc64/topology.h
+++ b/include/asm-sparc64/topology.h
@@ -1,6 +1,9 @@
 #ifndef _ASM_SPARC64_TOPOLOGY_H
 #define _ASM_SPARC64_TOPOLOGY_H
 
+#include <asm/spitfire.h>
+#define smt_capable()	(tlb_type == hypervisor)
+
 #include <asm-generic/topology.h>
 
 #endif /* _ASM_SPARC64_TOPOLOGY_H */
diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h
index 2d5e3c4..f235260 100644
--- a/include/asm-sparc64/ttable.h
+++ b/include/asm-sparc64/ttable.h
@@ -2,7 +2,6 @@
 #ifndef _SPARC64_TTABLE_H
 #define _SPARC64_TTABLE_H
 
-#include <linux/config.h>
 #include <asm/utrap.h>
 
 #ifdef __ASSEMBLY__
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index 998ef4a..badc73f 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -321,6 +321,7 @@
 #define __NR_set_robust_list	300
 #define __NR_get_robust_list	301
 
+#ifdef __KERNEL__
 /* WARNING: You MAY NOT add syscall numbers larger than 301, since
  *          all of the syscall tables in the Sparc kernel are
  *          sized to have 301 entries (starting at zero).  Therefore
@@ -487,7 +488,6 @@
 
 #endif /* __KERNEL_SYSCALLS__ */
 
-#ifdef __KERNEL__
 /* sysconf options, for SunOS compatibility */
 #define   _SC_ARG_MAX             1
 #define   _SC_CHILD_MAX           2
@@ -521,7 +521,6 @@
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
-#endif
 
 /*
  * "Conditional" syscalls
@@ -531,4 +530,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif /* _SPARC64_UNISTD_H */
diff --git a/include/asm-sparc64/vdev.h b/include/asm-sparc64/vdev.h
index 996e6be..25637c5 100644
--- a/include/asm-sparc64/vdev.h
+++ b/include/asm-sparc64/vdev.h
@@ -7,10 +7,11 @@
 #define _SPARC64_VDEV_H
 
 #include <linux/types.h>
+#include <asm/prom.h>
 
 extern u32 sun4v_vdev_devhandle;
-extern int sun4v_vdev_root;
+extern struct device_node *sun4v_vdev_root;
 
-extern unsigned int sun4v_vdev_device_interrupt(unsigned int);
+extern unsigned int sun4v_vdev_device_interrupt(struct device_node *dev_node);
 
 #endif /* !(_SPARC64_VDEV_H) */
diff --git a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h
index 9c57eb3..c69d5b2 100644
--- a/include/asm-sparc64/vga.h
+++ b/include/asm-sparc64/vga.h
@@ -28,6 +28,6 @@
 	return *addr;
 }
 
-#define VGA_MAP_MEM(x) (x)
+#define VGA_MAP_MEM(x,s) (x)
 
 #endif
diff --git a/include/asm-um/a.out.h b/include/asm-um/a.out.h
index 7c26265..50cee7b 100644
--- a/include/asm-um/a.out.h
+++ b/include/asm-um/a.out.h
@@ -1,7 +1,6 @@
 #ifndef __UM_A_OUT_H
 #define __UM_A_OUT_H
 
-#include "linux/config.h"
 #include "asm/arch/a.out.h"
 #include "choose-mode.h"
 
diff --git a/include/asm-um/cache.h b/include/asm-um/cache.h
index 3d05870..19e1bdd 100644
--- a/include/asm-um/cache.h
+++ b/include/asm-um/cache.h
@@ -1,7 +1,6 @@
 #ifndef __UM_CACHE_H
 #define __UM_CACHE_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_UML_X86) && !defined(CONFIG_64BIT)
 # define L1_CACHE_SHIFT		(CONFIG_X86_L1_CACHE_SHIFT)
diff --git a/include/asm-um/elf-ppc.h b/include/asm-um/elf-ppc.h
index 2998cf9..9971113 100644
--- a/include/asm-um/elf-ppc.h
+++ b/include/asm-um/elf-ppc.h
@@ -1,7 +1,6 @@
 #ifndef __UM_ELF_PPC_H
 #define __UM_ELF_PPC_H
 
-#include "linux/config.h"
 
 extern long elf_aux_hwcap;
 #define ELF_HWCAP (elf_aux_hwcap)
diff --git a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h
index ae0ca39..d352a35 100644
--- a/include/asm-um/fixmap.h
+++ b/include/asm-um/fixmap.h
@@ -1,7 +1,6 @@
 #ifndef __UM_FIXMAP_H
 #define __UM_FIXMAP_H
 
-#include <linux/config.h>
 #include <asm/kmap_types.h>
 #include <asm/archparam.h>
 #include <asm/elf.h>
diff --git a/include/asm-um/hardirq.h b/include/asm-um/hardirq.h
index 1224b26..313ebb8 100644
--- a/include/asm-um/hardirq.h
+++ b/include/asm-um/hardirq.h
@@ -3,7 +3,6 @@
 #ifndef __ASM_UM_HARDIRQ_H
 #define __ASM_UM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 
diff --git a/include/asm-um/linkage.h b/include/asm-um/linkage.h
index e3d62dcb..78b8624 100644
--- a/include/asm-um/linkage.h
+++ b/include/asm-um/linkage.h
@@ -3,7 +3,6 @@
 
 #include "asm/arch/linkage.h"
 
-#include <linux/config.h>
 
 /* <linux/linkage.h> will pick sane defaults */
 #ifdef CONFIG_GPROF
diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
index 9a0e48e..f709c78 100644
--- a/include/asm-um/mmu_context.h
+++ b/include/asm-um/mmu_context.h
@@ -7,7 +7,6 @@
 #define __UM_MMU_CONTEXT_H
 
 #include "linux/sched.h"
-#include "linux/config.h"
 #include "choose-mode.h"
 #include "um_mmu.h"
 
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 4136433..4296d31 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -9,7 +9,6 @@
 
 struct page;
 
-#include <linux/config.h>
 #include <asm/vm-flags.h>
 
 /* PAGE_SHIFT determines the page size */
diff --git a/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h
index ea49411..34ab268 100644
--- a/include/asm-um/pgalloc.h
+++ b/include/asm-um/pgalloc.h
@@ -8,7 +8,6 @@
 #ifndef __UM_PGALLOC_H
 #define __UM_PGALLOC_H
 
-#include "linux/config.h"
 #include "linux/mm.h"
 #include "asm/fixmap.h"
 
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index da07a69..824c288 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -10,7 +10,6 @@
 
 struct task_struct;
 
-#include "linux/config.h"
 #include "asm/ptrace.h"
 #include "choose-mode.h"
 #include "registers.h"
diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
index 5034843..a36f537 100644
--- a/include/asm-um/ptrace-generic.h
+++ b/include/asm-um/ptrace-generic.h
@@ -8,7 +8,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include "linux/config.h"
 
 #define pt_regs pt_regs_subarch
 #define show_regs show_regs_subarch
diff --git a/include/asm-um/smp.h b/include/asm-um/smp.h
index aeda665..ca55226 100644
--- a/include/asm-um/smp.h
+++ b/include/asm-um/smp.h
@@ -3,7 +3,6 @@
 
 #ifdef CONFIG_SMP
 
-#include "linux/config.h"
 #include "linux/bitops.h"
 #include "asm/current.h"
 #include "linux/cpumask.h"
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index f166b98..261e2f4 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -8,7 +8,6 @@
 
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/types.h>
 
diff --git a/include/asm-v850/atomic.h b/include/asm-v850/atomic.h
index 166df00..e4e57de 100644
--- a/include/asm-v850/atomic.h
+++ b/include/asm-v850/atomic.h
@@ -14,7 +14,6 @@
 #ifndef __V850_ATOMIC_H__
 #define __V850_ATOMIC_H__
 
-#include <linux/config.h>
 
 #include <asm/system.h>
 
diff --git a/include/asm-v850/bitops.h b/include/asm-v850/bitops.h
index 1f6fd5a..1fa99ba 100644
--- a/include/asm-v850/bitops.h
+++ b/include/asm-v850/bitops.h
@@ -14,7 +14,6 @@
 #define __V850_BITOPS_H__
 
 
-#include <linux/config.h>
 #include <linux/compiler.h>	/* unlikely  */
 #include <asm/byteorder.h>	/* swab32 */
 #include <asm/system.h>		/* interrupt enable/disable */
diff --git a/include/asm-v850/dma-mapping.h b/include/asm-v850/dma-mapping.h
index c63fb50..1cc42c6 100644
--- a/include/asm-v850/dma-mapping.h
+++ b/include/asm-v850/dma-mapping.h
@@ -1,7 +1,6 @@
 #ifndef __V850_DMA_MAPPING_H__
 #define __V850_DMA_MAPPING_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PCI
 #include <asm-generic/dma-mapping.h>
diff --git a/include/asm-v850/hardirq.h b/include/asm-v850/hardirq.h
index d98488c..04e2012 100644
--- a/include/asm-v850/hardirq.h
+++ b/include/asm-v850/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __V850_HARDIRQ_H__
 #define __V850_HARDIRQ_H__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cache.h>
 
diff --git a/include/asm-v850/irq.h b/include/asm-v850/irq.h
index 4443115..1bf096d 100644
--- a/include/asm-v850/irq.h
+++ b/include/asm-v850/irq.h
@@ -62,8 +62,6 @@
 /* Disable an irq without waiting. */
 extern void disable_irq_nosync (unsigned int irq);
 
-extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __V850_IRQ_H__ */
diff --git a/include/asm-v850/machdep.h b/include/asm-v850/machdep.h
index 98d8bf6..f1e3b8b 100644
--- a/include/asm-v850/machdep.h
+++ b/include/asm-v850/machdep.h
@@ -14,7 +14,6 @@
 #ifndef __V850_MACHDEP_H__
 #define __V850_MACHDEP_H__
 
-#include <linux/config.h>
 
 /* chips */
 #ifdef CONFIG_V850E_MA1
diff --git a/include/asm-v850/pgtable.h b/include/asm-v850/pgtable.h
index 3cf8775..1ea2a90 100644
--- a/include/asm-v850/pgtable.h
+++ b/include/asm-v850/pgtable.h
@@ -3,7 +3,6 @@
 
 #include <asm-generic/4level-fixup.h>
 
-#include <linux/config.h>
 #include <asm/page.h>
 
 
diff --git a/include/asm-v850/processor.h b/include/asm-v850/processor.h
index 2d31308..6965b66 100644
--- a/include/asm-v850/processor.h
+++ b/include/asm-v850/processor.h
@@ -14,7 +14,6 @@
 #ifndef __V850_PROCESSOR_H__
 #define __V850_PROCESSOR_H__
 
-#include <linux/config.h>
 #ifndef __ASSEMBLY__ /* <linux/thread_info.h> is not asm-safe.  */
 #include <linux/thread_info.h>
 #endif
diff --git a/include/asm-v850/serial.h b/include/asm-v850/serial.h
index 8c2a609..36d8f4c 100644
--- a/include/asm-v850/serial.h
+++ b/include/asm-v850/serial.h
@@ -6,7 +6,6 @@
  * Copyright (C) 1999 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */ 
-#include <linux/config.h>
 
 #ifdef CONFIG_RTE_CB_ME2
 
diff --git a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
index 82460a7..bcb44bf 100644
--- a/include/asm-v850/unistd.h
+++ b/include/asm-v850/unistd.h
@@ -14,8 +14,6 @@
 #ifndef __V850_UNISTD_H__
 #define __V850_UNISTD_H__
 
-#include <asm/clinkage.h>
-
 #define __NR_restart_syscall	  0
 #define __NR_exit		  1
 #define __NR_fork		  2
@@ -237,10 +235,9 @@
    except the syscall number (r12).  */
 #define SYSCALL_SHORT_CLOBBERS	SYSCALL_CLOBBERS, "r13", "r14"
 
+#ifdef __KERNEL__
 
-/* User programs sometimes end up including this header file
-   (indirectly, via uClibc header files), so I'm a bit nervous just
-   including <linux/compiler.h>.  */
+#include <asm/clinkage.h>
 
 #define __syscall_return(type, res)					      \
   do {									      \
@@ -368,7 +365,6 @@
 }
 		
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
@@ -389,7 +385,6 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
 
 #ifdef __KERNEL_SYSCALLS__
 
@@ -440,7 +435,7 @@
 				struct sigaction __user *oact,
 				size_t sigsetsize);
 
-#endif
+#endif /* __KERNEL_SYSCALLS__ */
 
 /*
  * "Conditional" syscalls
@@ -455,4 +450,5 @@
   void name (void) __attribute__ ((weak, alias ("sys_ni_syscall")));
 #endif
 
+#endif /* __KERNEL__ */
 #endif /* __V850_UNISTD_H__ */
diff --git a/include/asm-v850/v850e_uart.h b/include/asm-v850/v850e_uart.h
index 5930d59..5182fb4 100644
--- a/include/asm-v850/v850e_uart.h
+++ b/include/asm-v850/v850e_uart.h
@@ -19,7 +19,6 @@
 #ifndef __V850_V850E_UART_H__
 #define __V850_V850E_UART_H__
 
-#include <linux/config.h>
 #include <linux/termios.h>
 
 #include <asm/v850e_utils.h>
diff --git a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h
index aa1c7b2..2c95a31 100644
--- a/include/asm-x86_64/acpi.h
+++ b/include/asm-x86_64/acpi.h
@@ -162,6 +162,8 @@
 
 extern u8 x86_acpiid_to_apicid[];
 
+#define ARCH_HAS_POWER_INIT 1
+
 extern int acpi_skip_timer_override;
 
 #endif /*__KERNEL__*/
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
new file mode 100644
index 0000000..387c8f6
--- /dev/null
+++ b/include/asm-x86_64/alternative.h
@@ -0,0 +1,146 @@
+#ifndef _X86_64_ALTERNATIVE_H
+#define _X86_64_ALTERNATIVE_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+
+struct alt_instr {
+	u8 *instr; 		/* original instruction */
+	u8 *replacement;
+	u8  cpuid;		/* cpuid bit set for replacement */
+	u8  instrlen;		/* length of original instruction */
+	u8  replacementlen; 	/* length of new instruction, <= instrlen */
+	u8  pad[5];
+};
+
+extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
+
+struct module;
+extern void alternatives_smp_module_add(struct module *mod, char *name,
+					void *locks, void *locks_end,
+					void *text, void *text_end);
+extern void alternatives_smp_module_del(struct module *mod);
+extern void alternatives_smp_switch(int smp);
+
+#endif
+
+/*
+ * Alternative instructions for different CPU types or capabilities.
+ *
+ * This allows to use optimized instructions even on generic binary
+ * kernels.
+ *
+ * length of oldinstr must be longer or equal the length of newinstr
+ * It can be padded with nops as needed.
+ *
+ * For non barrier like inlines please define new variants
+ * without volatile and memory clobber.
+ */
+#define alternative(oldinstr, newinstr, feature) 	\
+	asm volatile ("661:\n\t" oldinstr "\n662:\n" 		     \
+		      ".section .altinstructions,\"a\"\n"     	     \
+		      "  .align 8\n"				       \
+		      "  .quad 661b\n"            /* label */          \
+		      "  .quad 663f\n"		  /* new instruction */ \
+		      "  .byte %c0\n"             /* feature bit */    \
+		      "  .byte 662b-661b\n"       /* sourcelen */      \
+		      "  .byte 664f-663f\n"       /* replacementlen */ \
+		      ".previous\n"					\
+		      ".section .altinstr_replacement,\"ax\"\n"		\
+		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+		      ".previous" :: "i" (feature) : "memory")
+
+/*
+ * Alternative inline assembly with input.
+ *
+ * Pecularities:
+ * No memory clobber here.
+ * Argument numbers start with 1.
+ * Best is to use constraints that are fixed size (like (%1) ... "r")
+ * If you use variable sized constraints like "m" or "g" in the
+ * replacement make sure to pad to the worst case length.
+ */
+#define alternative_input(oldinstr, newinstr, feature, input...)	\
+	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
+		      ".section .altinstructions,\"a\"\n"		\
+		      "  .align 8\n"					\
+		      "  .quad 661b\n"            /* label */		\
+		      "  .quad 663f\n"		  /* new instruction */	\
+		      "  .byte %c0\n"             /* feature bit */	\
+		      "  .byte 662b-661b\n"       /* sourcelen */	\
+		      "  .byte 664f-663f\n"       /* replacementlen */	\
+		      ".previous\n"					\
+		      ".section .altinstr_replacement,\"ax\"\n"		\
+		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+		      ".previous" :: "i" (feature), ##input)
+
+/* Like alternative_input, but with a single output argument */
+#define alternative_io(oldinstr, newinstr, feature, output, input...) \
+	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
+		      ".section .altinstructions,\"a\"\n"		\
+		      "  .align 8\n"					\
+		      "  .quad 661b\n"            /* label */		\
+		      "  .quad 663f\n"		  /* new instruction */	\
+		      "  .byte %c[feat]\n"        /* feature bit */	\
+		      "  .byte 662b-661b\n"       /* sourcelen */	\
+		      "  .byte 664f-663f\n"       /* replacementlen */	\
+		      ".previous\n"					\
+		      ".section .altinstr_replacement,\"ax\"\n"		\
+		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
+		      ".previous" : output : [feat] "i" (feature), ##input)
+
+/*
+ * Alternative inline assembly for SMP.
+ *
+ * alternative_smp() takes two versions (SMP first, UP second) and is
+ * for more complex stuff such as spinlocks.
+ *
+ * The LOCK_PREFIX macro defined here replaces the LOCK and
+ * LOCK_PREFIX macros used everywhere in the source tree.
+ *
+ * SMP alternatives use the same data structures as the other
+ * alternatives and the X86_FEATURE_UP flag to indicate the case of a
+ * UP system running a SMP kernel.  The existing apply_alternatives()
+ * works fine for patching a SMP kernel for UP.
+ *
+ * The SMP alternative tables can be kept after boot and contain both
+ * UP and SMP versions of the instructions to allow switching back to
+ * SMP at runtime, when hotplugging in a new CPU, which is especially
+ * useful in virtualized environments.
+ *
+ * The very common lock prefix is handled as special case in a
+ * separate table which is a pure address list without replacement ptr
+ * and size information.  That keeps the table sizes small.
+ */
+
+#ifdef CONFIG_SMP
+#define alternative_smp(smpinstr, upinstr, args...)			\
+	asm volatile ("661:\n\t" smpinstr "\n662:\n"			\
+		      ".section .smp_altinstructions,\"a\"\n"		\
+		      "  .align 8\n"					\
+		      "  .quad 661b\n"            /* label */		\
+		      "  .quad 663f\n"		  /* new instruction */	\
+		      "  .byte 0x66\n"            /* X86_FEATURE_UP */	\
+		      "  .byte 662b-661b\n"       /* sourcelen */	\
+		      "  .byte 664f-663f\n"       /* replacementlen */	\
+		      ".previous\n"					\
+		      ".section .smp_altinstr_replacement,\"awx\"\n"	\
+		      "663:\n\t" upinstr "\n"     /* replacement */	\
+		      "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
+		      ".previous" : args)
+
+#define LOCK_PREFIX \
+		".section .smp_locks,\"a\"\n"	\
+		"  .align 8\n"			\
+		"  .quad 661f\n" /* address */	\
+		".previous\n"			\
+	       	"661:\n\tlock; "
+
+#else /* ! CONFIG_SMP */
+#define alternative_smp(smpinstr, upinstr, args...) \
+	asm volatile (upinstr : args)
+#define LOCK_PREFIX ""
+#endif
+
+#endif /* _X86_64_ALTERNATIVE_H */
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index bdbd893..9c96a0a 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_APIC_H
 #define __ASM_APIC_H
 
-#include <linux/config.h>
 #include <linux/pm.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
@@ -50,7 +49,8 @@
 
 static __inline__ void apic_wait_icr_idle(void)
 {
-	while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY );
+	while (apic_read( APIC_ICR ) & APIC_ICR_BUSY)
+		cpu_relax();
 }
 
 static inline void ack_APIC_irq(void)
@@ -80,30 +80,23 @@
 extern void smp_local_timer_interrupt (struct pt_regs * regs);
 extern void setup_boot_APIC_clock (void);
 extern void setup_secondary_APIC_clock (void);
-extern void setup_apic_nmi_watchdog (void);
-extern int reserve_lapic_nmi(void);
-extern void release_lapic_nmi(void);
-extern void disable_timer_nmi_watchdog(void);
-extern void enable_timer_nmi_watchdog(void);
-extern void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
 extern int APIC_init_uniprocessor (void);
 extern void disable_APIC_timer(void);
 extern void enable_APIC_timer(void);
 extern void clustered_apic_check(void);
 
-extern void nmi_watchdog_default(void);
-extern int setup_nmi_watchdog(char *);
+extern void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
+				   unsigned char msg_type, unsigned char mask);
 
-extern unsigned int nmi_watchdog;
-#define NMI_DEFAULT	-1
-#define NMI_NONE	0
-#define NMI_IO_APIC	1
-#define NMI_LOCAL_APIC	2
-#define NMI_INVALID	3
+#define K8_APIC_EXT_LVT_BASE    0x500
+#define K8_APIC_EXT_INT_MSG_FIX 0x0
+#define K8_APIC_EXT_INT_MSG_SMI 0x2
+#define K8_APIC_EXT_INT_MSG_NMI 0x4
+#define K8_APIC_EXT_INT_MSG_EXT 0x7
+#define K8_APIC_EXT_LVT_ENTRY_THRESHOLD    0
 
 extern int disable_timer_pin_1;
 
-extern void setup_threshold_lvt(unsigned long lvt_off);
 
 void smp_send_timer_broadcast_ipi(void);
 void switch_APIC_timer_to_ipi(void *cpumask);
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index 5a48e9b..1dd4006 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -137,8 +137,6 @@
  */
 #define u32 unsigned int
 
-#define lapic ((volatile struct local_apic *)APIC_BASE)
-
 struct local_apic {
 
 /*000*/	struct { u32 __reserved[4]; } __reserved_01;
diff --git a/include/asm-x86_64/atomic.h b/include/asm-x86_64/atomic.h
index cecbf7b..007e88d 100644
--- a/include/asm-x86_64/atomic.h
+++ b/include/asm-x86_64/atomic.h
@@ -1,8 +1,7 @@
 #ifndef __ARCH_X86_64_ATOMIC__
 #define __ARCH_X86_64_ATOMIC__
 
-#include <linux/config.h>
-#include <asm/types.h>
+#include <asm/alternative.h>
 
 /* atomic_t should be 32 bit signed type */
 
@@ -53,7 +52,7 @@
 static __inline__ void atomic_add(int i, atomic_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "addl %1,%0"
+		LOCK_PREFIX "addl %1,%0"
 		:"=m" (v->counter)
 		:"ir" (i), "m" (v->counter));
 }
@@ -68,7 +67,7 @@
 static __inline__ void atomic_sub(int i, atomic_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "subl %1,%0"
+		LOCK_PREFIX "subl %1,%0"
 		:"=m" (v->counter)
 		:"ir" (i), "m" (v->counter));
 }
@@ -87,7 +86,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "subl %2,%0; sete %1"
+		LOCK_PREFIX "subl %2,%0; sete %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"ir" (i), "m" (v->counter) : "memory");
 	return c;
@@ -102,7 +101,7 @@
 static __inline__ void atomic_inc(atomic_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "incl %0"
+		LOCK_PREFIX "incl %0"
 		:"=m" (v->counter)
 		:"m" (v->counter));
 }
@@ -116,7 +115,7 @@
 static __inline__ void atomic_dec(atomic_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "decl %0"
+		LOCK_PREFIX "decl %0"
 		:"=m" (v->counter)
 		:"m" (v->counter));
 }
@@ -134,7 +133,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "decl %0; sete %1"
+		LOCK_PREFIX "decl %0; sete %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"m" (v->counter) : "memory");
 	return c != 0;
@@ -153,7 +152,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "incl %0; sete %1"
+		LOCK_PREFIX "incl %0; sete %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"m" (v->counter) : "memory");
 	return c != 0;
@@ -173,7 +172,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "addl %2,%0; sets %1"
+		LOCK_PREFIX "addl %2,%0; sets %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"ir" (i), "m" (v->counter) : "memory");
 	return c;
@@ -190,7 +189,7 @@
 {
 	int __i = i;
 	__asm__ __volatile__(
-		LOCK "xaddl %0, %1;"
+		LOCK_PREFIX "xaddl %0, %1;"
 		:"=r"(i)
 		:"m"(v->counter), "0"(i));
 	return i + __i;
@@ -238,7 +237,7 @@
 static __inline__ void atomic64_add(long i, atomic64_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "addq %1,%0"
+		LOCK_PREFIX "addq %1,%0"
 		:"=m" (v->counter)
 		:"ir" (i), "m" (v->counter));
 }
@@ -253,7 +252,7 @@
 static __inline__ void atomic64_sub(long i, atomic64_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "subq %1,%0"
+		LOCK_PREFIX "subq %1,%0"
 		:"=m" (v->counter)
 		:"ir" (i), "m" (v->counter));
 }
@@ -272,7 +271,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "subq %2,%0; sete %1"
+		LOCK_PREFIX "subq %2,%0; sete %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"ir" (i), "m" (v->counter) : "memory");
 	return c;
@@ -287,7 +286,7 @@
 static __inline__ void atomic64_inc(atomic64_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "incq %0"
+		LOCK_PREFIX "incq %0"
 		:"=m" (v->counter)
 		:"m" (v->counter));
 }
@@ -301,7 +300,7 @@
 static __inline__ void atomic64_dec(atomic64_t *v)
 {
 	__asm__ __volatile__(
-		LOCK "decq %0"
+		LOCK_PREFIX "decq %0"
 		:"=m" (v->counter)
 		:"m" (v->counter));
 }
@@ -319,7 +318,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "decq %0; sete %1"
+		LOCK_PREFIX "decq %0; sete %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"m" (v->counter) : "memory");
 	return c != 0;
@@ -338,7 +337,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "incq %0; sete %1"
+		LOCK_PREFIX "incq %0; sete %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"m" (v->counter) : "memory");
 	return c != 0;
@@ -358,7 +357,7 @@
 	unsigned char c;
 
 	__asm__ __volatile__(
-		LOCK "addq %2,%0; sets %1"
+		LOCK_PREFIX "addq %2,%0; sets %1"
 		:"=m" (v->counter), "=qm" (c)
 		:"ir" (i), "m" (v->counter) : "memory");
 	return c;
@@ -375,7 +374,7 @@
 {
 	long __i = i;
 	__asm__ __volatile__(
-		LOCK "xaddq %0, %1;"
+		LOCK_PREFIX "xaddq %0, %1;"
 		:"=r"(i)
 		:"m"(v->counter), "0"(i));
 	return i + __i;
@@ -419,11 +418,11 @@
 
 /* These are x86-specific, used by some header files */
 #define atomic_clear_mask(mask, addr) \
-__asm__ __volatile__(LOCK "andl %0,%1" \
+__asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
 : : "r" (~(mask)),"m" (*addr) : "memory")
 
 #define atomic_set_mask(mask, addr) \
-__asm__ __volatile__(LOCK "orl %0,%1" \
+__asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \
 : : "r" ((unsigned)mask),"m" (*(addr)) : "memory")
 
 /* Atomic operations are already serializing on x86 */
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 7921212..f7ba57b 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -5,13 +5,7 @@
  * Copyright 1992, Linus Torvalds.
  */
 
-#include <linux/config.h>
-
-#ifdef CONFIG_SMP
-#define LOCK_PREFIX "lock ; "
-#else
-#define LOCK_PREFIX ""
-#endif
+#include <asm/alternative.h>
 
 #define ADDR (*(volatile long *) addr)
 
diff --git a/include/asm-x86_64/bugs.h b/include/asm-x86_64/bugs.h
index 59bc689..d86c5dd 100644
--- a/include/asm-x86_64/bugs.h
+++ b/include/asm-x86_64/bugs.h
@@ -10,7 +10,6 @@
  *	void check_bugs(void);
  */
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/msr.h>
diff --git a/include/asm-x86_64/cache.h b/include/asm-x86_64/cache.h
index f8dff1c..ed8a9d25 100644
--- a/include/asm-x86_64/cache.h
+++ b/include/asm-x86_64/cache.h
@@ -4,7 +4,6 @@
 #ifndef __ARCH_X8664_CACHE_H
 #define __ARCH_X8664_CACHE_H
 
-#include <linux/config.h>
 
 /* L1 cache line size */
 #define L1_CACHE_SHIFT	(CONFIG_X86_L1_CACHE_SHIFT)
diff --git a/include/asm-x86_64/calgary.h b/include/asm-x86_64/calgary.h
new file mode 100644
index 0000000..6e1654f
--- /dev/null
+++ b/include/asm-x86_64/calgary.h
@@ -0,0 +1,66 @@
+/*
+ * Derived from include/asm-powerpc/iommu.h
+ *
+ * Copyright (C) 2006 Jon Mason <jdmason@us.ibm.com>, IBM Corporation
+ * Copyright (C) 2006 Muli Ben-Yehuda <muli@il.ibm.com>, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _ASM_X86_64_CALGARY_H
+#define _ASM_X86_64_CALGARY_H
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/types.h>
+
+struct iommu_table {
+	unsigned long  it_base;      /* mapped address of tce table */
+	unsigned long  it_hint;      /* Hint for next alloc */
+	unsigned long *it_map;       /* A simple allocation bitmap for now */
+	spinlock_t     it_lock;      /* Protects it_map */
+	unsigned int   it_size;      /* Size of iommu table in entries */
+	unsigned char  it_busno;     /* Bus number this table belongs to */
+	void __iomem  *bbar;
+	u64	       tar_val;
+	struct timer_list watchdog_timer;
+};
+
+#define TCE_TABLE_SIZE_UNSPECIFIED	~0
+#define TCE_TABLE_SIZE_64K		0
+#define TCE_TABLE_SIZE_128K		1
+#define TCE_TABLE_SIZE_256K		2
+#define TCE_TABLE_SIZE_512K		3
+#define TCE_TABLE_SIZE_1M		4
+#define TCE_TABLE_SIZE_2M		5
+#define TCE_TABLE_SIZE_4M		6
+#define TCE_TABLE_SIZE_8M		7
+
+#ifdef CONFIG_CALGARY_IOMMU
+extern int calgary_iommu_init(void);
+extern void detect_calgary(void);
+#else
+static inline int calgary_iommu_init(void) { return 1; }
+static inline void detect_calgary(void) { return; }
+#endif
+
+static inline unsigned int bus_to_phb(unsigned char busno)
+{
+	return ((busno % 15 == 0) ? 0 : busno / 2 + 1);
+}
+
+#endif /* _ASM_X86_64_CALGARY_H */
diff --git a/include/asm-x86_64/calling.h b/include/asm-x86_64/calling.h
index fc2c5a6..6f4f63a 100644
--- a/include/asm-x86_64/calling.h
+++ b/include/asm-x86_64/calling.h
@@ -2,7 +2,6 @@
  * Some macros to handle stack frames in assembly.
  */ 
 
-#include <linux/config.h>
 
 #define R15 0
 #define R14 8
diff --git a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h
index 662964b..ee792fa 100644
--- a/include/asm-x86_64/cpufeature.h
+++ b/include/asm-x86_64/cpufeature.h
@@ -46,6 +46,7 @@
 #define X86_FEATURE_SYSCALL	(1*32+11) /* SYSCALL/SYSRET */
 #define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
 #define X86_FEATURE_FXSR_OPT	(1*32+25) /* FXSR optimizations */
+#define X86_FEATURE_RDTSCP	(1*32+27) /* RDTSCP */
 #define X86_FEATURE_LM		(1*32+29) /* Long Mode (x86-64) */
 #define X86_FEATURE_3DNOWEXT	(1*32+30) /* AMD 3DNow! extensions */
 #define X86_FEATURE_3DNOW	(1*32+31) /* 3DNow! */
@@ -65,6 +66,8 @@
 #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
 #define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
 #define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
+#define X86_FEATURE_UP		(3*32+8) /* SMP kernel running on UP */
+#define X86_FEATURE_ARCH_PERFMON (3*32+9) /* Intel Architectural PerfMon */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3	(4*32+ 0) /* Streaming SIMD Extensions-3 */
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
index 49a81a6..b6da83d 100644
--- a/include/asm-x86_64/dma-mapping.h
+++ b/include/asm-x86_64/dma-mapping.h
@@ -6,7 +6,6 @@
  * documentation.
  */
 
-#include <linux/config.h>
 
 #include <asm/scatterlist.h>
 #include <asm/io.h>
@@ -56,6 +55,13 @@
 extern struct dma_mapping_ops* dma_ops;
 extern int iommu_merge;
 
+static inline int valid_dma_direction(int dma_direction)
+{
+	return ((dma_direction == DMA_BIDIRECTIONAL) ||
+		(dma_direction == DMA_TO_DEVICE) ||
+		(dma_direction == DMA_FROM_DEVICE));
+}
+
 static inline int dma_mapping_error(dma_addr_t dma_addr)
 {
 	if (dma_ops->mapping_error)
@@ -73,6 +79,7 @@
 dma_map_single(struct device *hwdev, void *ptr, size_t size,
 	       int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	return dma_ops->map_single(hwdev, ptr, size, direction);
 }
 
@@ -80,6 +87,7 @@
 dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size,
 		 int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	dma_ops->unmap_single(dev, addr, size, direction);
 }
 
@@ -92,6 +100,7 @@
 dma_sync_single_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
 			size_t size, int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	if (dma_ops->sync_single_for_cpu)
 		dma_ops->sync_single_for_cpu(hwdev, dma_handle, size,
 					     direction);
@@ -102,6 +111,7 @@
 dma_sync_single_for_device(struct device *hwdev, dma_addr_t dma_handle,
 			   size_t size, int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	if (dma_ops->sync_single_for_device)
 		dma_ops->sync_single_for_device(hwdev, dma_handle, size,
 						direction);
@@ -112,6 +122,7 @@
 dma_sync_single_range_for_cpu(struct device *hwdev, dma_addr_t dma_handle,
 			      unsigned long offset, size_t size, int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	if (dma_ops->sync_single_range_for_cpu) {
 		dma_ops->sync_single_range_for_cpu(hwdev, dma_handle, offset, size, direction);
 	}
@@ -123,6 +134,7 @@
 dma_sync_single_range_for_device(struct device *hwdev, dma_addr_t dma_handle,
 				 unsigned long offset, size_t size, int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	if (dma_ops->sync_single_range_for_device)
 		dma_ops->sync_single_range_for_device(hwdev, dma_handle,
 						      offset, size, direction);
@@ -134,6 +146,7 @@
 dma_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
 		    int nelems, int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	if (dma_ops->sync_sg_for_cpu)
 		dma_ops->sync_sg_for_cpu(hwdev, sg, nelems, direction);
 	flush_write_buffers();
@@ -143,6 +156,7 @@
 dma_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
 		       int nelems, int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	if (dma_ops->sync_sg_for_device) {
 		dma_ops->sync_sg_for_device(hwdev, sg, nelems, direction);
 	}
@@ -153,6 +167,7 @@
 static inline int
 dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	return dma_ops->map_sg(hwdev, sg, nents, direction);
 }
 
@@ -160,6 +175,7 @@
 dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
 	     int direction)
 {
+	BUG_ON(!valid_dma_direction(direction));
 	dma_ops->unmap_sg(hwdev, sg, nents, direction);
 }
 
diff --git a/include/asm-x86_64/dma.h b/include/asm-x86_64/dma.h
index 6f2a817..a37c16f 100644
--- a/include/asm-x86_64/dma.h
+++ b/include/asm-x86_64/dma.h
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.1.1.1 2001/04/19 20:00:38 ak Exp $
+/*
  * linux/include/asm/dma.h: Defines for using and allocating dma channels.
  * Written by Hennus Bergman, 1992.
  * High DMA channel support & info by Hannu Savolainen
@@ -8,7 +8,6 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>	/* And spinlocks */
 #include <asm/io.h>		/* need byte IO */
 #include <linux/delay.h>
diff --git a/include/asm-x86_64/dwarf2.h b/include/asm-x86_64/dwarf2.h
index 07654bd..0744db7 100644
--- a/include/asm-x86_64/dwarf2.h
+++ b/include/asm-x86_64/dwarf2.h
@@ -1,7 +1,6 @@
 #ifndef _DWARF2_H
 #define _DWARF2_H 1
 
-#include <linux/config.h>
 
 #ifndef __ASSEMBLY__
 #warning "asm/dwarf2.h should be only included in pure assembly files"
diff --git a/include/asm-x86_64/fixmap.h b/include/asm-x86_64/fixmap.h
index 7b286bd..0b4ffbd 100644
--- a/include/asm-x86_64/fixmap.h
+++ b/include/asm-x86_64/fixmap.h
@@ -11,7 +11,6 @@
 #ifndef _ASM_FIXMAP_H
 #define _ASM_FIXMAP_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/apicdef.h>
 #include <asm/page.h>
diff --git a/include/asm-x86_64/floppy.h b/include/asm-x86_64/floppy.h
index 52825ce..006291e 100644
--- a/include/asm-x86_64/floppy.h
+++ b/include/asm-x86_64/floppy.h
@@ -147,10 +147,8 @@
 		return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT,
 						   "floppy", NULL);
 	else
-		return request_irq(FLOPPY_IRQ, floppy_interrupt,
-						   SA_INTERRUPT|SA_SAMPLE_RANDOM,
-						   "floppy", NULL);	
-
+		return request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT,
+				   "floppy", NULL);
 }
 
 static unsigned long dma_mem_alloc(unsigned long size)
diff --git a/include/asm-x86_64/gart-mapping.h b/include/asm-x86_64/gart-mapping.h
deleted file mode 100644
index ada497b..0000000
--- a/include/asm-x86_64/gart-mapping.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _X8664_GART_MAPPING_H
-#define _X8664_GART_MAPPING_H 1
-
-#include <linux/types.h>
-#include <asm/types.h>
-
-struct device;
-
-extern void*
-gart_alloc_coherent(struct device *dev, size_t size,
-        dma_addr_t *dma_handle, gfp_t gfp);
-
-extern int
-gart_dma_supported(struct device *hwdev, u64 mask);
-
-#endif /* _X8664_GART_MAPPING_H */
diff --git a/include/asm-x86_64/hardirq.h b/include/asm-x86_64/hardirq.h
index 8689951..64a65ce 100644
--- a/include/asm-x86_64/hardirq.h
+++ b/include/asm-x86_64/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/irq.h>
 #include <asm/pda.h>
diff --git a/include/asm-x86_64/hpet.h b/include/asm-x86_64/hpet.h
index 18ff7ee..b390984 100644
--- a/include/asm-x86_64/hpet.h
+++ b/include/asm-x86_64/hpet.h
@@ -55,7 +55,7 @@
 
 extern int is_hpet_enabled(void);
 extern int hpet_rtc_timer_init(void);
-extern int oem_force_hpet_timer(void);
+extern int apic_is_clustered_box(void);
 
 extern int hpet_use_timer;
 
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 0df1715..9318774 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -12,12 +12,9 @@
  *	<tomsoft@informatik.tu-chemnitz.de>
  *
  *	hacked by Andi Kleen for x86-64.
- * 
- *  $Id: hw_irq.h,v 1.24 2001/09/14 20:55:03 vojtech Exp $
  */
 
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <asm/atomic.h>
 #include <asm/irq.h>
 #include <linux/profile.h>
@@ -127,7 +124,7 @@
 __asm__( \
 "\n.p2align\n" \
 "IRQ" #nr "_interrupt:\n\t" \
-	"push $" #nr "-256 ; " \
+	"push $~(" #nr ") ; " \
 	"jmp common_interrupt");
 
 #if defined(CONFIG_X86_IO_APIC)
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
index e6b7f22..0190b7c 100644
--- a/include/asm-x86_64/ia32.h
+++ b/include/asm-x86_64/ia32.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_X86_64_IA32_H
 #define _ASM_X86_64_IA32_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_IA32_EMULATION
 
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index b4f4b17..5b52ce5 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -4,317 +4,15 @@
 /*
  * This file contains the system call numbers of the ia32 port,
  * this is for the kernel only.
+ * Only add syscalls here where some part of the kernel needs to know
+ * the number. This should be otherwise in sync with asm-i386/unistd.h. -AK
  */
 
 #define __NR_ia32_restart_syscall 0
 #define __NR_ia32_exit		  1
-#define __NR_ia32_fork		  2
 #define __NR_ia32_read		  3
 #define __NR_ia32_write		  4
-#define __NR_ia32_open		  5
-#define __NR_ia32_close		  6
-#define __NR_ia32_waitpid		  7
-#define __NR_ia32_creat		  8
-#define __NR_ia32_link		  9
-#define __NR_ia32_unlink		 10
-#define __NR_ia32_execve		 11
-#define __NR_ia32_chdir		 12
-#define __NR_ia32_time		 13
-#define __NR_ia32_mknod		 14
-#define __NR_ia32_chmod		 15
-#define __NR_ia32_lchown		 16
-#define __NR_ia32_break		 17
-#define __NR_ia32_oldstat		 18
-#define __NR_ia32_lseek		 19
-#define __NR_ia32_getpid		 20
-#define __NR_ia32_mount		 21
-#define __NR_ia32_umount		 22
-#define __NR_ia32_setuid		 23
-#define __NR_ia32_getuid		 24
-#define __NR_ia32_stime		 25
-#define __NR_ia32_ptrace		 26
-#define __NR_ia32_alarm		 27
-#define __NR_ia32_oldfstat		 28
-#define __NR_ia32_pause		 29
-#define __NR_ia32_utime		 30
-#define __NR_ia32_stty		 31
-#define __NR_ia32_gtty		 32
-#define __NR_ia32_access		 33
-#define __NR_ia32_nice		 34
-#define __NR_ia32_ftime		 35
-#define __NR_ia32_sync		 36
-#define __NR_ia32_kill		 37
-#define __NR_ia32_rename		 38
-#define __NR_ia32_mkdir		 39
-#define __NR_ia32_rmdir		 40
-#define __NR_ia32_dup		 41
-#define __NR_ia32_pipe		 42
-#define __NR_ia32_times		 43
-#define __NR_ia32_prof		 44
-#define __NR_ia32_brk		 45
-#define __NR_ia32_setgid		 46
-#define __NR_ia32_getgid		 47
-#define __NR_ia32_signal		 48
-#define __NR_ia32_geteuid		 49
-#define __NR_ia32_getegid		 50
-#define __NR_ia32_acct		 51
-#define __NR_ia32_umount2		 52
-#define __NR_ia32_lock		 53
-#define __NR_ia32_ioctl		 54
-#define __NR_ia32_fcntl		 55
-#define __NR_ia32_mpx		 56
-#define __NR_ia32_setpgid		 57
-#define __NR_ia32_ulimit		 58
-#define __NR_ia32_oldolduname	 59
-#define __NR_ia32_umask		 60
-#define __NR_ia32_chroot		 61
-#define __NR_ia32_ustat		 62
-#define __NR_ia32_dup2		 63
-#define __NR_ia32_getppid		 64
-#define __NR_ia32_getpgrp		 65
-#define __NR_ia32_setsid		 66
-#define __NR_ia32_sigaction		 67
-#define __NR_ia32_sgetmask		 68
-#define __NR_ia32_ssetmask		 69
-#define __NR_ia32_setreuid		 70
-#define __NR_ia32_setregid		 71
-#define __NR_ia32_sigsuspend		 72
-#define __NR_ia32_sigpending		 73
-#define __NR_ia32_sethostname	 74
-#define __NR_ia32_setrlimit		 75
-#define __NR_ia32_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
-#define __NR_ia32_getrusage		 77
-#define __NR_ia32_gettimeofday	 78
-#define __NR_ia32_settimeofday	 79
-#define __NR_ia32_getgroups		 80
-#define __NR_ia32_setgroups		 81
-#define __NR_ia32_select		 82
-#define __NR_ia32_symlink		 83
-#define __NR_ia32_oldlstat		 84
-#define __NR_ia32_readlink		 85
-#define __NR_ia32_uselib		 86
-#define __NR_ia32_swapon		 87
-#define __NR_ia32_reboot		 88
-#define __NR_ia32_readdir		 89
-#define __NR_ia32_mmap		 90
-#define __NR_ia32_munmap		 91
-#define __NR_ia32_truncate		 92
-#define __NR_ia32_ftruncate		 93
-#define __NR_ia32_fchmod		 94
-#define __NR_ia32_fchown		 95
-#define __NR_ia32_getpriority	 96
-#define __NR_ia32_setpriority	 97
-#define __NR_ia32_profil		 98
-#define __NR_ia32_statfs		 99
-#define __NR_ia32_fstatfs		100
-#define __NR_ia32_ioperm		101
-#define __NR_ia32_socketcall		102
-#define __NR_ia32_syslog		103
-#define __NR_ia32_setitimer		104
-#define __NR_ia32_getitimer		105
-#define __NR_ia32_stat		106
-#define __NR_ia32_lstat		107
-#define __NR_ia32_fstat		108
-#define __NR_ia32_olduname		109
-#define __NR_ia32_iopl		110
-#define __NR_ia32_vhangup		111
-#define __NR_ia32_idle		112
-#define __NR_ia32_vm86old		113
-#define __NR_ia32_wait4		114
-#define __NR_ia32_swapoff		115
-#define __NR_ia32_sysinfo		116
-#define __NR_ia32_ipc		117
-#define __NR_ia32_fsync		118
-#define __NR_ia32_sigreturn		119
-#define __NR_ia32_clone		120
-#define __NR_ia32_setdomainname	121
-#define __NR_ia32_uname		122
-#define __NR_ia32_modify_ldt		123
-#define __NR_ia32_adjtimex		124
-#define __NR_ia32_mprotect		125
-#define __NR_ia32_sigprocmask	126
-#define __NR_ia32_create_module	127
-#define __NR_ia32_init_module	128
-#define __NR_ia32_delete_module	129
-#define __NR_ia32_get_kernel_syms	130
-#define __NR_ia32_quotactl		131
-#define __NR_ia32_getpgid		132
-#define __NR_ia32_fchdir		133
-#define __NR_ia32_bdflush		134
-#define __NR_ia32_sysfs		135
-#define __NR_ia32_personality	136
-#define __NR_ia32_afs_syscall	137 /* Syscall for Andrew File System */
-#define __NR_ia32_setfsuid		138
-#define __NR_ia32_setfsgid		139
-#define __NR_ia32__llseek		140
-#define __NR_ia32_getdents		141
-#define __NR_ia32__newselect		142
-#define __NR_ia32_flock		143
-#define __NR_ia32_msync		144
-#define __NR_ia32_readv		145
-#define __NR_ia32_writev		146
-#define __NR_ia32_getsid		147
-#define __NR_ia32_fdatasync		148
-#define __NR_ia32__sysctl		149
-#define __NR_ia32_mlock		150
-#define __NR_ia32_munlock		151
-#define __NR_ia32_mlockall		152
-#define __NR_ia32_munlockall		153
-#define __NR_ia32_sched_setparam		154
-#define __NR_ia32_sched_getparam		155
-#define __NR_ia32_sched_setscheduler		156
-#define __NR_ia32_sched_getscheduler		157
-#define __NR_ia32_sched_yield		158
-#define __NR_ia32_sched_get_priority_max	159
-#define __NR_ia32_sched_get_priority_min	160
-#define __NR_ia32_sched_rr_get_interval	161
-#define __NR_ia32_nanosleep		162
-#define __NR_ia32_mremap		163
-#define __NR_ia32_setresuid		164
-#define __NR_ia32_getresuid		165
-#define __NR_ia32_vm86		166
-#define __NR_ia32_query_module	167
-#define __NR_ia32_poll		168
-#define __NR_ia32_nfsservctl		169
-#define __NR_ia32_setresgid		170
-#define __NR_ia32_getresgid		171
-#define __NR_ia32_prctl              172
+#define __NR_ia32_sigreturn	119
 #define __NR_ia32_rt_sigreturn	173
-#define __NR_ia32_rt_sigaction	174
-#define __NR_ia32_rt_sigprocmask	175
-#define __NR_ia32_rt_sigpending	176
-#define __NR_ia32_rt_sigtimedwait	177
-#define __NR_ia32_rt_sigqueueinfo	178
-#define __NR_ia32_rt_sigsuspend	179
-#define __NR_ia32_pread		180
-#define __NR_ia32_pwrite		181
-#define __NR_ia32_chown		182
-#define __NR_ia32_getcwd		183
-#define __NR_ia32_capget		184
-#define __NR_ia32_capset		185
-#define __NR_ia32_sigaltstack	186
-#define __NR_ia32_sendfile		187
-#define __NR_ia32_getpmsg		188	/* some people actually want streams */
-#define __NR_ia32_putpmsg		189	/* some people actually want streams */
-#define __NR_ia32_vfork		190
-#define __NR_ia32_ugetrlimit		191	/* SuS compliant getrlimit */
-#define __NR_ia32_mmap2		192
-#define __NR_ia32_truncate64		193
-#define __NR_ia32_ftruncate64	194
-#define __NR_ia32_stat64		195
-#define __NR_ia32_lstat64		196
-#define __NR_ia32_fstat64		197
-#define __NR_ia32_lchown32		198
-#define __NR_ia32_getuid32		199
-#define __NR_ia32_getgid32		200
-#define __NR_ia32_geteuid32		201
-#define __NR_ia32_getegid32		202
-#define __NR_ia32_setreuid32		203
-#define __NR_ia32_setregid32		204
-#define __NR_ia32_getgroups32	205
-#define __NR_ia32_setgroups32	206
-#define __NR_ia32_fchown32		207
-#define __NR_ia32_setresuid32	208
-#define __NR_ia32_getresuid32	209
-#define __NR_ia32_setresgid32	210
-#define __NR_ia32_getresgid32	211
-#define __NR_ia32_chown32		212
-#define __NR_ia32_setuid32		213
-#define __NR_ia32_setgid32		214
-#define __NR_ia32_setfsuid32		215
-#define __NR_ia32_setfsgid32		216
-#define __NR_ia32_pivot_root		217
-#define __NR_ia32_mincore		218
-#define __NR_ia32_madvise		219
-#define __NR_ia32_madvise1		219	/* delete when C lib stub is removed */
-#define __NR_ia32_getdents64		220
-#define __NR_ia32_fcntl64		221
-#define __NR_ia32_tuxcall		222
-#define __NR_ia32_security		223
-#define __NR_ia32_gettid		224
-#define __NR_ia32_readahead		225
-#define __NR_ia32_setxattr		226
-#define __NR_ia32_lsetxattr		227
-#define __NR_ia32_fsetxattr		228
-#define __NR_ia32_getxattr		229
-#define __NR_ia32_lgetxattr		230
-#define __NR_ia32_fgetxattr		231
-#define __NR_ia32_listxattr		232
-#define __NR_ia32_llistxattr		233
-#define __NR_ia32_flistxattr		234
-#define __NR_ia32_removexattr	235
-#define __NR_ia32_lremovexattr	236
-#define __NR_ia32_fremovexattr	237
-#define __NR_ia32_tkill		238
-#define __NR_ia32_sendfile64		239
-#define __NR_ia32_futex		240
-#define __NR_ia32_sched_setaffinity	241
-#define __NR_ia32_sched_getaffinity	242
-#define __NR_ia32_set_thread_area   243
-#define __NR_ia32_get_thread_area	244
-#define __NR_ia32_io_setup		245
-#define __NR_ia32_io_destroy		246
-#define __NR_ia32_io_getevents	247
-#define __NR_ia32_io_submit		248
-#define __NR_ia32_io_cancel		249
-#define __NR_ia32_exit_group		252
-#define __NR_ia32_lookup_dcookie	253
-#define __NR_ia32_sys_epoll_create	254
-#define __NR_ia32_sys_epoll_ctl	255
-#define __NR_ia32_sys_epoll_wait	256
-#define __NR_ia32_remap_file_pages	257
-#define __NR_ia32_set_tid_address	258
-#define __NR_ia32_timer_create		259
-#define __NR_ia32_timer_settime	(__NR_ia32_timer_create+1)
-#define __NR_ia32_timer_gettime	(__NR_ia32_timer_create+2)
-#define __NR_ia32_timer_getoverrun	(__NR_ia32_timer_create+3)
-#define __NR_ia32_timer_delete	(__NR_ia32_timer_create+4)
-#define __NR_ia32_clock_settime	(__NR_ia32_timer_create+5)
-#define __NR_ia32_clock_gettime	(__NR_ia32_timer_create+6)
-#define __NR_ia32_clock_getres	(__NR_ia32_timer_create+7)
-#define __NR_ia32_clock_nanosleep	(__NR_ia32_timer_create+8)
-#define __NR_ia32_statfs64		268
-#define __NR_ia32_fstatfs64		269
-#define __NR_ia32_tgkill		270
-#define __NR_ia32_utimes		271
-#define __NR_ia32_fadvise64_64		272
-#define __NR_ia32_vserver		273
-#define __NR_ia32_mbind		274
-#define __NR_ia32_get_mempolicy	275
-#define __NR_ia32_set_mempolicy	276
-#define __NR_ia32_mq_open 		277
-#define __NR_ia32_mq_unlink		(__NR_ia32_mq_open+1)
-#define __NR_ia32_mq_timedsend	(__NR_ia32_mq_open+2)
-#define __NR_ia32_mq_timedreceive	(__NR_ia32_mq_open+3)
-#define __NR_ia32_mq_notify		(__NR_ia32_mq_open+4)
-#define __NR_ia32_mq_getsetattr	(__NR_ia32_mq_open+5)
-#define __NR_ia32_kexec		283
-#define __NR_ia32_waitid		284
-/* #define __NR_sys_setaltroot	285 */
-#define __NR_ia32_add_key		286
-#define __NR_ia32_request_key	287
-#define __NR_ia32_keyctl		288
-#define __NR_ia32_ioprio_set		289
-#define __NR_ia32_ioprio_get		290
-#define __NR_ia32_inotify_init		291
-#define __NR_ia32_inotify_add_watch	292
-#define __NR_ia32_inotify_rm_watch	293
-#define __NR_ia32_migrate_pages		294
-#define __NR_ia32_openat		295
-#define __NR_ia32_mkdirat		296
-#define __NR_ia32_mknodat		297
-#define __NR_ia32_fchownat		298
-#define __NR_ia32_futimesat		299
-#define __NR_ia32_fstatat64		300
-#define __NR_ia32_unlinkat		301
-#define __NR_ia32_renameat		302
-#define __NR_ia32_linkat		303
-#define __NR_ia32_symlinkat		304
-#define __NR_ia32_readlinkat		305
-#define __NR_ia32_fchmodat		306
-#define __NR_ia32_faccessat		307
-#define __NR_ia32_pselect6		308
-#define __NR_ia32_ppoll			309
-#define __NR_ia32_unshare		310
 
 #endif /* _ASM_X86_64_IA32_UNISTD_H_ */
diff --git a/include/asm-x86_64/intel_arch_perfmon.h b/include/asm-x86_64/intel_arch_perfmon.h
new file mode 100644
index 0000000..59c3964
--- /dev/null
+++ b/include/asm-x86_64/intel_arch_perfmon.h
@@ -0,0 +1,19 @@
+#ifndef X86_64_INTEL_ARCH_PERFMON_H
+#define X86_64_INTEL_ARCH_PERFMON_H 1
+
+#define MSR_ARCH_PERFMON_PERFCTR0		0xc1
+#define MSR_ARCH_PERFMON_PERFCTR1		0xc2
+
+#define MSR_ARCH_PERFMON_EVENTSEL0		0x186
+#define MSR_ARCH_PERFMON_EVENTSEL1		0x187
+
+#define ARCH_PERFMON_EVENTSEL0_ENABLE      (1 << 22)
+#define ARCH_PERFMON_EVENTSEL_INT          (1 << 20)
+#define ARCH_PERFMON_EVENTSEL_OS           (1 << 17)
+#define ARCH_PERFMON_EVENTSEL_USR          (1 << 16)
+
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL	(0x3c)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK	(0x00 << 8)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0)
+
+#endif	/* X86_64_INTEL_ARCH_PERFMON_H */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index a05da8a..70e91fe 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-#include <linux/config.h>
 
 /*
  * This file contains the definitions for the x86 IO instructions
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index 52484e8..fb7a090 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -1,7 +1,6 @@
 #ifndef __ASM_IO_APIC_H
 #define __ASM_IO_APIC_H
 
-#include <linux/config.h>
 #include <asm/types.h>
 #include <asm/mpspec.h>
 
diff --git a/include/asm-x86_64/k8.h b/include/asm-x86_64/k8.h
new file mode 100644
index 0000000..699dd69
--- /dev/null
+++ b/include/asm-x86_64/k8.h
@@ -0,0 +1,14 @@
+#ifndef _ASM_K8_H
+#define _ASM_K8_H 1
+
+#include <linux/pci.h>
+
+extern struct pci_device_id k8_nb_ids[];
+
+extern int early_is_k8_nb(u32 value);
+extern struct pci_dev **k8_northbridges;
+extern int num_k8_northbridges;
+extern int cache_k8_northbridges(void);
+extern void k8_flush_garts(void);
+
+#endif
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index cf79563..cd52c7f 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -15,6 +15,8 @@
 
 extern int register_die_notifier(struct notifier_block *);
 extern int unregister_die_notifier(struct notifier_block *);
+extern int register_page_fault_notifier(struct notifier_block *);
+extern int unregister_page_fault_notifier(struct notifier_block *);
 extern struct atomic_notifier_head die_chain;
 
 /* Grossly misnamed. */
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index 98a1e95d..d36febd 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -43,6 +43,7 @@
 
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
 #define ARCH_SUPPORTS_KRETPROBES
+#define  ARCH_INACTIVE_KPROBE_COUNT 1
 
 void kretprobe_trampoline(void);
 extern void arch_remove_kprobe(struct kprobe *p);
diff --git a/include/asm-x86_64/local.h b/include/asm-x86_64/local.h
index cd17945..e769e62 100644
--- a/include/asm-x86_64/local.h
+++ b/include/asm-x86_64/local.h
@@ -59,12 +59,26 @@
  * This could be done better if we moved the per cpu data directly
  * after GS.
  */
-#define cpu_local_read(v)	local_read(&__get_cpu_var(v))
-#define cpu_local_set(v, i)	local_set(&__get_cpu_var(v), (i))
-#define cpu_local_inc(v)	local_inc(&__get_cpu_var(v))
-#define cpu_local_dec(v)	local_dec(&__get_cpu_var(v))
-#define cpu_local_add(i, v)	local_add((i), &__get_cpu_var(v))
-#define cpu_local_sub(i, v)	local_sub((i), &__get_cpu_var(v))
+
+/* Need to disable preemption for the cpu local counters otherwise we could
+   still access a variable of a previous CPU in a non atomic way. */
+#define cpu_local_wrap_v(v)	 	\
+	({ local_t res__;		\
+	   preempt_disable(); 		\
+	   res__ = (v);			\
+	   preempt_enable();		\
+	   res__; })
+#define cpu_local_wrap(v)		\
+	({ preempt_disable();		\
+	   v;				\
+	   preempt_enable(); })		\
+
+#define cpu_local_read(v)    cpu_local_wrap_v(local_read(&__get_cpu_var(v)))
+#define cpu_local_set(v, i)  cpu_local_wrap(local_set(&__get_cpu_var(v), (i)))
+#define cpu_local_inc(v)     cpu_local_wrap(local_inc(&__get_cpu_var(v)))
+#define cpu_local_dec(v)     cpu_local_wrap(local_dec(&__get_cpu_var(v)))
+#define cpu_local_add(i, v)  cpu_local_wrap(local_add((i), &__get_cpu_var(v)))
+#define cpu_local_sub(i, v)  cpu_local_wrap(local_sub((i), &__get_cpu_var(v)))
 
 #define __cpu_local_inc(v)	cpu_local_inc(v)
 #define __cpu_local_dec(v)	cpu_local_dec(v)
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h
index 7229785..d13687d 100644
--- a/include/asm-x86_64/mce.h
+++ b/include/asm-x86_64/mce.h
@@ -67,13 +67,22 @@
 /* Software defined banks */
 #define MCE_EXTENDED_BANK	128
 #define MCE_THERMAL_BANK	MCE_EXTENDED_BANK + 0
-#define MCE_THRESHOLD_BASE      MCE_EXTENDED_BANK + 1 /* MCE_AMD */
-#define MCE_THRESHOLD_DRAM_ECC  MCE_THRESHOLD_BASE + 4
+
+#define K8_MCE_THRESHOLD_BASE      (MCE_EXTENDED_BANK + 1)      /* MCE_AMD */
+#define K8_MCE_THRESHOLD_BANK_0    (MCE_THRESHOLD_BASE + 0 * 9)
+#define K8_MCE_THRESHOLD_BANK_1    (MCE_THRESHOLD_BASE + 1 * 9)
+#define K8_MCE_THRESHOLD_BANK_2    (MCE_THRESHOLD_BASE + 2 * 9)
+#define K8_MCE_THRESHOLD_BANK_3    (MCE_THRESHOLD_BASE + 3 * 9)
+#define K8_MCE_THRESHOLD_BANK_4    (MCE_THRESHOLD_BASE + 4 * 9)
+#define K8_MCE_THRESHOLD_BANK_5    (MCE_THRESHOLD_BASE + 5 * 9)
+#define K8_MCE_THRESHOLD_DRAM_ECC  (MCE_THRESHOLD_BANK_4 + 0)
 
 #ifdef __KERNEL__
 #include <asm/atomic.h>
 
 void mce_log(struct mce *m);
+DECLARE_PER_CPU(struct sys_device, device_mce);
+
 #ifdef CONFIG_X86_MCE_INTEL
 void mce_intel_feature_init(struct cpuinfo_x86 *c);
 #else
diff --git a/include/asm-x86_64/mmu_context.h b/include/asm-x86_64/mmu_context.h
index 19f0c83..af03b9f 100644
--- a/include/asm-x86_64/mmu_context.h
+++ b/include/asm-x86_64/mmu_context.h
@@ -1,7 +1,6 @@
 #ifndef __X86_64_MMU_CONTEXT_H
 #define __X86_64_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <asm/desc.h>
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index 6944e71..c38ebdf 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -4,7 +4,6 @@
 #ifndef _ASM_X86_64_MMZONE_H
 #define _ASM_X86_64_MMZONE_H 1
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NUMA
 
@@ -43,7 +42,6 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 #define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
-#define kvaddr_to_nid(kaddr)	phys_to_nid(__pa(kaddr))
 
 extern int pfn_valid(unsigned long pfn);
 #endif
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h
index 356e0e8..3ad23466 100644
--- a/include/asm-x86_64/msi.h
+++ b/include/asm-x86_64/msi.h
@@ -10,7 +10,15 @@
 #include <asm/mach_apic.h>
 #include <asm/smp.h>
 
-#define LAST_DEVICE_VECTOR		232
+#define LAST_DEVICE_VECTOR	(FIRST_SYSTEM_VECTOR - 1)
 #define MSI_TARGET_CPU_SHIFT	12
 
+extern struct msi_ops msi_apic_ops;
+
+static inline int msi_arch_init(void)
+{
+	msi_register(&msi_apic_ops);
+	return 0;
+}
+
 #endif /* ASM_MSI_H */
diff --git a/include/asm-x86_64/mtrr.h b/include/asm-x86_64/mtrr.h
index 66ac1c0..d6135b2 100644
--- a/include/asm-x86_64/mtrr.h
+++ b/include/asm-x86_64/mtrr.h
@@ -23,9 +23,7 @@
 #ifndef _LINUX_MTRR_H
 #define _LINUX_MTRR_H
 
-#include <linux/config.h>
 #include <linux/ioctl.h>
-#include <linux/compat.h>
 
 #define	MTRR_IOCTL_BASE	'M'
 
@@ -102,11 +100,10 @@
     return -ENODEV;
 }
 
-#  endif
-
-#endif
+#endif /* CONFIG_MTRR */
 
 #ifdef CONFIG_COMPAT
+#include <linux/compat.h>
 
 struct mtrr_sentry32
 {
@@ -138,4 +135,6 @@
 
 #endif /* CONFIG_COMPAT */
 
+#endif /* __KERNEL__ */
+
 #endif  /*  _LINUX_MTRR_H  */
diff --git a/include/asm-x86_64/mutex.h b/include/asm-x86_64/mutex.h
index 11fbee2..06fab6d 100644
--- a/include/asm-x86_64/mutex.h
+++ b/include/asm-x86_64/mutex.h
@@ -24,7 +24,7 @@
 	typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);		\
 									\
 	__asm__ __volatile__(						\
-		LOCK	"   decl (%%rdi)	\n"			\
+		LOCK_PREFIX "   decl (%%rdi)	\n"			\
 			"   js 2f		\n"			\
 			"1:			\n"			\
 									\
@@ -74,7 +74,7 @@
 	typecheck_fn(fastcall void (*)(atomic_t *), fail_fn);		\
 									\
 	__asm__ __volatile__(						\
-		LOCK	"   incl (%%rdi)	\n"			\
+		LOCK_PREFIX "   incl (%%rdi)	\n"			\
 			"   jle 2f		\n"			\
 			"1:			\n"			\
 									\
diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h
index d3abfc6..efb45c8 100644
--- a/include/asm-x86_64/nmi.h
+++ b/include/asm-x86_64/nmi.h
@@ -5,26 +5,27 @@
 #define ASM_NMI_H
 
 #include <linux/pm.h>
+#include <asm/io.h>
  
 struct pt_regs;
- 
+
 typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu);
- 
-/** 
+
+/**
  * set_nmi_callback
  *
  * Set a handler for an NMI. Only one handler may be
  * set. Return 1 if the NMI was handled.
  */
 void set_nmi_callback(nmi_callback_t callback);
- 
-/** 
+
+/**
  * unset_nmi_callback
  *
  * Remove the handler previously set.
  */
 void unset_nmi_callback(void);
- 
+
 #ifdef CONFIG_PM
  
 /** Replace the PM callback routine for NMI. */
@@ -56,4 +57,21 @@
 
 extern int check_nmi_watchdog(void);
  
+extern void setup_apic_nmi_watchdog (void);
+extern int reserve_lapic_nmi(void);
+extern void release_lapic_nmi(void);
+extern void disable_timer_nmi_watchdog(void);
+extern void enable_timer_nmi_watchdog(void);
+extern void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
+
+extern void nmi_watchdog_default(void);
+extern int setup_nmi_watchdog(char *);
+
+extern unsigned int nmi_watchdog;
+#define NMI_DEFAULT	-1
+#define NMI_NONE	0
+#define NMI_IO_APIC	1
+#define NMI_LOCAL_APIC	2
+#define NMI_INVALID	3
+
 #endif /* ASM_NMI_H */
diff --git a/include/asm-x86_64/numa.h b/include/asm-x86_64/numa.h
index 1cc92fe..933ff11 100644
--- a/include/asm-x86_64/numa.h
+++ b/include/asm-x86_64/numa.h
@@ -8,7 +8,6 @@
 };
 
 extern int compute_hash_shift(struct bootnode *nodes, int numnodes);
-extern int pxm_to_node(int nid);
 
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 408185b..f7bf875 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -1,7 +1,6 @@
 #ifndef _X86_64_PAGE_H
 #define _X86_64_PAGE_H
 
-#include <linux/config.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
@@ -136,9 +135,9 @@
 
 #define __HAVE_ARCH_GATE_AREA 1	
 
-#endif /* __KERNEL__ */
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+#endif /* __KERNEL__ */
+
 #endif /* _X86_64_PAGE_H */
diff --git a/include/asm-x86_64/param.h b/include/asm-x86_64/param.h
index 5956b23..a728786 100644
--- a/include/asm-x86_64/param.h
+++ b/include/asm-x86_64/param.h
@@ -2,7 +2,6 @@
 #define _ASMx86_64_PARAM_H
 
 #ifdef __KERNEL__
-# include <linux/config.h>
 # define HZ            CONFIG_HZ	/* Internal kernel timer frequency */
 # define USER_HZ       100		/* .. some user interfaces are in "ticks */
 #define CLOCKS_PER_SEC        (USER_HZ)       /* like times() */
diff --git a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h
index 8a05af2..49c5e92 100644
--- a/include/asm-x86_64/pci.h
+++ b/include/asm-x86_64/pci.h
@@ -1,7 +1,6 @@
 #ifndef __x8664_PCI_H
 #define __x8664_PCI_H
 
-#include <linux/config.h>
 #include <asm/io.h>
 
 #ifdef __KERNEL__
@@ -40,8 +39,8 @@
 #include <asm/scatterlist.h>
 #include <linux/string.h>
 #include <asm/page.h>
-#include <linux/dma-mapping.h> /* for have_iommu */
 
+extern void pci_iommu_alloc(void);
 extern int iommu_setup(char *opt);
 
 /* The PCI address space does equal the physical memory
@@ -53,7 +52,7 @@
  */
 #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)
 
-#ifdef CONFIG_GART_IOMMU
+#if defined(CONFIG_IOMMU) || defined(CONFIG_CALGARY_IOMMU)
 
 /*
  * x86-64 always supports DAC, but sometimes it is useful to force
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 7f33aaf..549eb92 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -21,6 +21,7 @@
 /* var is in discarded region: offset to particular copy we want */
 #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
 #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
+#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __my_cpu_offset()))
 
 /* A macro to avoid #include hell... */
 #define percpu_modcopy(pcpudst, src, size)			\
@@ -40,6 +41,7 @@
 
 #define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
 #define __get_cpu_var(var)			per_cpu__##var
+#define __raw_get_cpu_var(var)			per_cpu__##var
 
 #endif	/* SMP */
 
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index 31e83c3..a31ab4e 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -337,14 +337,8 @@
 /* to find an entry in a page-table-directory. */
 #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1))
 #define pud_offset(pgd, address) ((pud_t *) pgd_page(*(pgd)) + pud_index(address))
-#define pud_offset_k(pgd, addr) pud_offset(pgd, addr)
 #define pud_present(pud) (pud_val(pud) & _PAGE_PRESENT)
 
-static inline pud_t *__pud_offset_k(pud_t *pud, unsigned long address)
-{ 
-	return pud + pud_index(address);
-} 
-
 /* PMD  - Level 2 access */
 #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
 #define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 37a3ec4..3b3c121 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -12,7 +12,6 @@
 #include <asm/types.h>
 #include <asm/sigcontext.h>
 #include <asm/cpufeature.h>
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <asm/msr.h>
 #include <asm/current.h>
@@ -70,7 +69,11 @@
 	cpumask_t llc_shared_map;	/* cpus sharing the last level cache */
 #endif
 	__u8	apicid;
+#ifdef CONFIG_SMP
 	__u8	booted_cores;	/* number of cores as seen by OS */
+	__u8	phys_proc_id;	/* Physical Processor id. */
+	__u8	cpu_core_id;	/* Core id. */
+#endif
 } ____cacheline_aligned;
 
 #define X86_VENDOR_INTEL 0
@@ -97,6 +100,7 @@
 extern void identify_cpu(struct cpuinfo_x86 *);
 extern void print_cpu_info(struct cpuinfo_x86 *);
 extern unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c);
+extern unsigned short num_cache_leaves;
 
 /*
  * EFLAGS bits
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index 8abf2a4..038fe1f4 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -37,7 +37,6 @@
 
 extern void config_acpi_tables(void);
 extern void ia32_syscall(void);
-extern void iommu_hole_init(void);
 
 extern int pmtimer_mark_offset(void);
 extern void pmtimer_resume(void);
@@ -75,7 +74,7 @@
 
 extern unsigned long end_pfn_map; 
 
-extern void show_trace(unsigned long * rsp);
+extern void show_trace(struct task_struct *, struct pt_regs *, unsigned long * rsp);
 extern void show_registers(struct pt_regs *regs);
 
 extern void exception_table_check(void);
@@ -101,13 +100,9 @@
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
 
-extern void gart_parse_options(char *);
-extern void __init no_iommu_init(void);
-
 extern unsigned long table_start, table_end;
 
 extern int exception_trace;
-extern int force_iommu, no_iommu;
 extern int using_apic_timer;
 extern int disable_apic;
 extern unsigned cpu_khz;
@@ -116,7 +111,13 @@
 extern int acpi_ht;
 extern int acpi_disabled;
 
-#ifdef CONFIG_GART_IOMMU
+extern void no_iommu_init(void);
+extern int force_iommu, no_iommu;
+extern int iommu_detected;
+#ifdef CONFIG_IOMMU
+extern void gart_iommu_init(void);
+extern void gart_parse_options(char *);
+extern void iommu_hole_init(void);
 extern int fallback_aper_order;
 extern int fallback_aper_force;
 extern int iommu_aperture;
diff --git a/include/asm-x86_64/rwlock.h b/include/asm-x86_64/rwlock.h
index 9942cc3..dea0e94 100644
--- a/include/asm-x86_64/rwlock.h
+++ b/include/asm-x86_64/rwlock.h
@@ -24,7 +24,7 @@
 #define RW_LOCK_BIAS_STR	"0x01000000"
 
 #define __build_read_lock_ptr(rw, helper)   \
-	asm volatile(LOCK "subl $1,(%0)\n\t" \
+	asm volatile(LOCK_PREFIX "subl $1,(%0)\n\t" \
 		     "js 2f\n" \
 		     "1:\n" \
 		    LOCK_SECTION_START("") \
@@ -34,7 +34,7 @@
 		     ::"a" (rw) : "memory")
 
 #define __build_read_lock_const(rw, helper)   \
-	asm volatile(LOCK "subl $1,%0\n\t" \
+	asm volatile(LOCK_PREFIX "subl $1,%0\n\t" \
 		     "js 2f\n" \
 		     "1:\n" \
 		    LOCK_SECTION_START("") \
@@ -54,7 +54,7 @@
 					} while (0)
 
 #define __build_write_lock_ptr(rw, helper) \
-	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
+	asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
 		     "jnz 2f\n" \
 		     "1:\n" \
 		     LOCK_SECTION_START("") \
@@ -64,7 +64,7 @@
 		     ::"a" (rw) : "memory")
 
 #define __build_write_lock_const(rw, helper) \
-	asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
+	asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
 		     "jnz 2f\n" \
 		     "1:\n" \
 		    LOCK_SECTION_START("") \
diff --git a/include/asm-x86_64/semaphore.h b/include/asm-x86_64/semaphore.h
index a389aa6f..064df08 100644
--- a/include/asm-x86_64/semaphore.h
+++ b/include/asm-x86_64/semaphore.h
@@ -106,7 +106,7 @@
 
 	__asm__ __volatile__(
 		"# atomic down operation\n\t"
-		LOCK "decl %0\n\t"     /* --sem->count */
+		LOCK_PREFIX "decl %0\n\t"     /* --sem->count */
 		"js 2f\n"
 		"1:\n"
 		LOCK_SECTION_START("")
@@ -130,7 +130,7 @@
 
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
-		LOCK "decl %1\n\t"     /* --sem->count */
+		LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
 		"js 2f\n\t"
 		"xorl %0,%0\n"
 		"1:\n"
@@ -154,7 +154,7 @@
 
 	__asm__ __volatile__(
 		"# atomic interruptible down operation\n\t"
-		LOCK "decl %1\n\t"     /* --sem->count */
+		LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
 		"js 2f\n\t"
 		"xorl %0,%0\n"
 		"1:\n"
@@ -178,7 +178,7 @@
 {
 	__asm__ __volatile__(
 		"# atomic up operation\n\t"
-		LOCK "incl %0\n\t"     /* ++sem->count */
+		LOCK_PREFIX "incl %0\n\t"     /* ++sem->count */
 		"jle 2f\n"
 		"1:\n"
 		LOCK_SECTION_START("")
diff --git a/include/asm-x86_64/serial.h b/include/asm-x86_64/serial.h
index dc752ea..b0496e0 100644
--- a/include/asm-x86_64/serial.h
+++ b/include/asm-x86_64/serial.h
@@ -2,7 +2,6 @@
  * include/asm-x86_64/serial.h
  */
 
-#include <linux/config.h>
 
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index a4fdaeb..6805e1f 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -5,7 +5,6 @@
  * We need the APIC definitions automatically as part of 'smp.h'
  */
 #ifndef __ASSEMBLY__
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
@@ -54,8 +53,6 @@
 
 extern cpumask_t cpu_sibling_map[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
-extern u8 phys_proc_id[NR_CPUS];
-extern u8 cpu_core_id[NR_CPUS];
 extern u8 cpu_llc_id[NR_CPUS];
 
 #define SMP_TRAMPOLINE_BASE 0x6000
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
index fe484a6..8d34219 100644
--- a/include/asm-x86_64/spinlock.h
+++ b/include/asm-x86_64/spinlock.h
@@ -4,7 +4,6 @@
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
-#include <linux/config.h>
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
@@ -32,15 +31,19 @@
 	"jmp 1b\n" \
 	LOCK_SECTION_END
 
+#define __raw_spin_lock_string_up \
+	"\n\tdecl %0"
+
 #define __raw_spin_unlock_string \
 	"movl $1,%0" \
 		:"=m" (lock->slock) : : "memory"
 
 static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
-	__asm__ __volatile__(
-		__raw_spin_lock_string
-		:"=m" (lock->slock) : : "memory");
+	alternative_smp(
+		__raw_spin_lock_string,
+		__raw_spin_lock_string_up,
+		"=m" (lock->slock) : : "memory");
 }
 
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
diff --git a/include/asm-x86_64/string.h b/include/asm-x86_64/string.h
index ee6bf27..9505d9f 100644
--- a/include/asm-x86_64/string.h
+++ b/include/asm-x86_64/string.h
@@ -6,7 +6,8 @@
 /* Written 2002 by Andi Kleen */ 
 
 /* Only used for special circumstances. Stolen from i386/string.h */ 
-static inline void * __inline_memcpy(void * to, const void * from, size_t n)
+static __always_inline void *
+__inline_memcpy(void * to, const void * from, size_t n)
 {
 unsigned long d0, d1, d2;
 __asm__ __volatile__(
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h
index 60757ef..5f9a018 100644
--- a/include/asm-x86_64/swiotlb.h
+++ b/include/asm-x86_64/swiotlb.h
@@ -1,7 +1,6 @@
 #ifndef _ASM_SWIOTLB_H
 #define _ASM_SWTIOLB_H 1
 
-#include <linux/config.h>
 
 #include <asm/dma-mapping.h>
 
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index 3975989..68e559f 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -1,18 +1,12 @@
 #ifndef __ASM_SYSTEM_H
 #define __ASM_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/segment.h>
+#include <asm/alternative.h>
 
 #ifdef __KERNEL__
 
-#ifdef CONFIG_SMP
-#define LOCK_PREFIX "lock ; "
-#else
-#define LOCK_PREFIX ""
-#endif
-
 #define __STR(x) #x
 #define STR(x) __STR(x)
 
@@ -35,7 +29,7 @@
 		     "thread_return:\n\t"					    \
 		     "movq %%gs:%P[pda_pcurrent],%%rsi\n\t"			  \
 		     "movq %P[thread_info](%%rsi),%%r8\n\t"			  \
-		     LOCK "btr  %[tif_fork],%P[ti_flags](%%r8)\n\t"		  \
+		     LOCK_PREFIX "btr  %[tif_fork],%P[ti_flags](%%r8)\n\t"	  \
 		     "movq %%rax,%%rdi\n\t" 					  \
 		     "jc   ret_from_fork\n\t"					  \
 		     RESTORE_CONTEXT						    \
@@ -70,82 +64,6 @@
 		".previous"			\
 		: :"r" (value), "r" (0))
 
-#ifdef __KERNEL__
-struct alt_instr { 
-	__u8 *instr; 		/* original instruction */
-	__u8 *replacement;
-	__u8  cpuid;		/* cpuid bit set for replacement */
-	__u8  instrlen;		/* length of original instruction */
-	__u8  replacementlen; 	/* length of new instruction, <= instrlen */ 
-	__u8  pad[5];
-}; 
-#endif
-
-/*
- * Alternative instructions for different CPU types or capabilities.
- * 
- * This allows to use optimized instructions even on generic binary
- * kernels.
- * 
- * length of oldinstr must be longer or equal the length of newinstr
- * It can be padded with nops as needed.
- * 
- * For non barrier like inlines please define new variants
- * without volatile and memory clobber.
- */
-#define alternative(oldinstr, newinstr, feature) 	\
-	asm volatile ("661:\n\t" oldinstr "\n662:\n" 		     \
-		      ".section .altinstructions,\"a\"\n"     	     \
-		      "  .align 8\n"				       \
-		      "  .quad 661b\n"            /* label */          \
-		      "  .quad 663f\n"		  /* new instruction */ \
-		      "  .byte %c0\n"             /* feature bit */    \
-		      "  .byte 662b-661b\n"       /* sourcelen */      \
-		      "  .byte 664f-663f\n"       /* replacementlen */ \
-		      ".previous\n"					\
-		      ".section .altinstr_replacement,\"ax\"\n"		\
-		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
-		      ".previous" :: "i" (feature) : "memory")  
-
-/*
- * Alternative inline assembly with input.
- * 
- * Peculiarities:
- * No memory clobber here. 
- * Argument numbers start with 1.
- * Best is to use constraints that are fixed size (like (%1) ... "r")
- * If you use variable sized constraints like "m" or "g" in the 
- * replacement make sure to pad to the worst case length.
- */
-#define alternative_input(oldinstr, newinstr, feature, input...)	\
-	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
-		      ".section .altinstructions,\"a\"\n"		\
-		      "  .align 8\n"					\
-		      "  .quad 661b\n"            /* label */		\
-		      "  .quad 663f\n"		  /* new instruction */	\
-		      "  .byte %c0\n"             /* feature bit */	\
-		      "  .byte 662b-661b\n"       /* sourcelen */	\
-		      "  .byte 664f-663f\n"       /* replacementlen */	\
-		      ".previous\n"					\
-		      ".section .altinstr_replacement,\"ax\"\n"		\
-		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
-		      ".previous" :: "i" (feature), ##input)
-
-/* Like alternative_input, but with a single output argument */
-#define alternative_io(oldinstr, newinstr, feature, output, input...) \
-	asm volatile ("661:\n\t" oldinstr "\n662:\n"			\
-		      ".section .altinstructions,\"a\"\n"		\
-		      "  .align 8\n"					\
-		      "  .quad 661b\n"            /* label */		\
-		      "  .quad 663f\n"		  /* new instruction */	\
-		      "  .byte %c[feat]\n"        /* feature bit */	\
-		      "  .byte 662b-661b\n"       /* sourcelen */	\
-		      "  .byte 664f-663f\n"       /* replacementlen */	\
-		      ".previous\n"					\
-		      ".section .altinstr_replacement,\"ax\"\n"		\
-		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ \
-		      ".previous" : output : [feat] "i" (feature), ##input)
-
 /*
  * Clear and set 'TS' bit respectively
  */
@@ -367,5 +285,6 @@
 void cpu_idle_wait(void);
 
 extern unsigned long arch_align_stack(unsigned long sp);
+extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
 
 #endif
diff --git a/include/asm-x86_64/tce.h b/include/asm-x86_64/tce.h
new file mode 100644
index 0000000..ee51d315
--- /dev/null
+++ b/include/asm-x86_64/tce.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2006 Muli Ben-Yehuda <muli@il.ibm.com>, IBM Corporation
+ * Copyright (C) 2006 Jon Mason <jdmason@us.ibm.com>, IBM Corporation
+ *
+ * This file is derived from asm-powerpc/tce.h.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#ifndef _ASM_X86_64_TCE_H
+#define _ASM_X86_64_TCE_H
+
+extern void* tce_table_kva[];
+extern unsigned int specified_table_size;
+struct iommu_table;
+
+#define TCE_ENTRY_SIZE   8   /* in bytes */
+
+#define TCE_READ_SHIFT   0
+#define TCE_WRITE_SHIFT  1
+#define TCE_HUBID_SHIFT  2   /* unused */
+#define TCE_RSVD_SHIFT   8   /* unused */
+#define TCE_RPN_SHIFT    12
+#define TCE_UNUSED_SHIFT 48  /* unused */
+
+#define TCE_RPN_MASK     0x0000fffffffff000ULL
+
+extern void tce_build(struct iommu_table *tbl, unsigned long index,
+        unsigned int npages, unsigned long uaddr, int direction);
+extern void tce_free(struct iommu_table *tbl, long index, unsigned int npages);
+extern void* alloc_tce_table(void);
+extern void free_tce_table(void *tbl);
+extern int build_tce_table(struct pci_dev *dev, void __iomem *bbar);
+
+#endif /* _ASM_X86_64_TCE_H */
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index 4ac0e0a..2029b00 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -73,8 +73,21 @@
 }
 
 /* thread information allocation */
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(tsk)					\
+    ({								\
+	struct thread_info *ret;				\
+								\
+	ret = ((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER)); \
+	if (ret)						\
+		memset(ret, 0, THREAD_SIZE);			\
+	ret;							\
+    })
+#else
 #define alloc_thread_info(tsk) \
 	((struct thread_info *) __get_free_pages(GFP_KERNEL,THREAD_ORDER))
+#endif
+
 #define free_thread_info(ti) free_pages((unsigned long) (ti), THREAD_ORDER)
 
 #else /* !__ASSEMBLY__ */
@@ -101,7 +114,7 @@
 #define TIF_IRET		5	/* force IRET */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_SECCOMP		8	/* secure computing */
-#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+/* 16 free */
 #define TIF_IA32		17	/* 32bit process */ 
 #define TIF_FORK		18	/* ret_from_fork */
 #define TIF_ABI_PENDING		19
@@ -115,7 +128,6 @@
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1<<TIF_SECCOMP)
-#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_IA32		(1<<TIF_IA32)
 #define _TIF_FORK		(1<<TIF_FORK)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
@@ -137,6 +149,9 @@
  */
 #define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
 #define TS_COMPAT		0x0002	/* 32bit syscall active */
+#define TS_POLLING		0x0004	/* true if in idle loop and not sleeping */
+
+#define tsk_is_polling(t) ((t)->thread_info->status & TS_POLLING)
 
 #endif /* __KERNEL__ */
 
diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h
index 4a9c20e..d16d5b6 100644
--- a/include/asm-x86_64/tlbflush.h
+++ b/include/asm-x86_64/tlbflush.h
@@ -1,7 +1,6 @@
 #ifndef _X8664_TLBFLUSH_H
 #define _X8664_TLBFLUSH_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 #include <asm/processor.h>
 
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index 9db54e9..6e7a2e9 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -1,15 +1,12 @@
 #ifndef _ASM_X86_64_TOPOLOGY_H
 #define _ASM_X86_64_TOPOLOGY_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NUMA
 
 #include <asm/mpspec.h>
 #include <asm/bitops.h>
 
-/* Map the K8 CPU local memory controllers to a simple 1:1 CPU:NODE topology */
-
 extern cpumask_t cpu_online_map;
 
 extern unsigned char cpu_to_node[];
@@ -58,12 +55,12 @@
 #endif
 
 #ifdef CONFIG_SMP
-#define topology_physical_package_id(cpu)				\
-	(phys_proc_id[cpu] == BAD_APICID ? -1 : phys_proc_id[cpu])
-#define topology_core_id(cpu)						\
-	(cpu_core_id[cpu] == BAD_APICID ? 0 : cpu_core_id[cpu])
+#define topology_physical_package_id(cpu)	(cpu_data[cpu].phys_proc_id)
+#define topology_core_id(cpu)			(cpu_data[cpu].cpu_core_id)
 #define topology_core_siblings(cpu)		(cpu_core_map[cpu])
 #define topology_thread_siblings(cpu)		(cpu_sibling_map[cpu])
+#define mc_capable()			(boot_cpu_data.x86_max_cores > 1)
+#define smt_capable() 			(smp_num_siblings > 1)
 #endif
 
 #include <asm-generic/topology.h>
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index bddffcb..1e1fa00 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -4,7 +4,6 @@
 /*
  * User space memory access functions
  */
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index feb77cb..94387c9 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -617,8 +617,12 @@
 __SYSCALL(__NR_sync_file_range, sys_sync_file_range)
 #define __NR_vmsplice		278
 __SYSCALL(__NR_vmsplice, sys_vmsplice)
+#define __NR_move_pages		279
+__SYSCALL(__NR_move_pages, sys_move_pages)
 
-#define __NR_syscall_max __NR_vmsplice
+#ifdef __KERNEL__
+
+#define __NR_syscall_max __NR_move_pages
 
 #ifndef __NO_STUBS
 
@@ -635,7 +639,6 @@
 	return (type) (res); \
 } while (0)
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
 #define __ARCH_WANT_SYS_ALARM
@@ -657,7 +660,6 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_TIME
 #define __ARCH_WANT_COMPAT_SYS_TIME
-#endif
 
 #ifndef __KERNEL_SYSCALLS__
 
@@ -821,7 +823,7 @@
 
 #endif /* __KERNEL_SYSCALLS__ */
 
-#if !defined(__ASSEMBLY__) && defined(__KERNEL__)
+#ifndef __ASSEMBLY__
 
 #include <linux/linkage.h>
 #include <linux/compiler.h>
@@ -848,4 +850,5 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
+#endif /* __KERNEL__ */
 #endif
diff --git a/include/asm-x86_64/unwind.h b/include/asm-x86_64/unwind.h
new file mode 100644
index 0000000..f3e7124
--- /dev/null
+++ b/include/asm-x86_64/unwind.h
@@ -0,0 +1,106 @@
+#ifndef _ASM_X86_64_UNWIND_H
+#define _ASM_X86_64_UNWIND_H
+
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *	Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ */
+
+#ifdef CONFIG_STACK_UNWIND
+
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/uaccess.h>
+#include <asm/vsyscall.h>
+
+struct unwind_frame_info
+{
+	struct pt_regs regs;
+	struct task_struct *task;
+};
+
+#define UNW_PC(frame)        (frame)->regs.rip
+#define UNW_SP(frame)        (frame)->regs.rsp
+#ifdef CONFIG_FRAME_POINTER
+#define UNW_FP(frame)        (frame)->regs.rbp
+#define FRAME_RETADDR_OFFSET 8
+#define FRAME_LINK_OFFSET    0
+#define STACK_BOTTOM(tsk)    (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1))
+#define STACK_TOP(tsk)       ((tsk)->thread.rsp0)
+#endif
+/* Might need to account for the special exception and interrupt handling
+   stacks here, since normally
+	EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER,
+   but the construct is needed only for getting across the stack switch to
+   the interrupt stack - thus considering the IRQ stack itself is unnecessary,
+   and the overhead of comparing against all exception handling stacks seems
+   not desirable. */
+#define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
+
+#define UNW_REGISTER_INFO \
+	PTREGS_INFO(rax), \
+	PTREGS_INFO(rdx), \
+	PTREGS_INFO(rcx), \
+	PTREGS_INFO(rbx), \
+	PTREGS_INFO(rsi), \
+	PTREGS_INFO(rdi), \
+	PTREGS_INFO(rbp), \
+	PTREGS_INFO(rsp), \
+	PTREGS_INFO(r8), \
+	PTREGS_INFO(r9), \
+	PTREGS_INFO(r10), \
+	PTREGS_INFO(r11), \
+	PTREGS_INFO(r12), \
+	PTREGS_INFO(r13), \
+	PTREGS_INFO(r14), \
+	PTREGS_INFO(r15), \
+	PTREGS_INFO(rip)
+
+static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
+                                            /*const*/ struct pt_regs *regs)
+{
+	info->regs = *regs;
+}
+
+static inline void arch_unw_init_blocked(struct unwind_frame_info *info)
+{
+	extern const char thread_return[];
+
+	memset(&info->regs, 0, sizeof(info->regs));
+	info->regs.rip = (unsigned long)thread_return;
+	info->regs.cs = __KERNEL_CS;
+	__get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp);
+	info->regs.rsp = info->task->thread.rsp;
+	info->regs.ss = __KERNEL_DS;
+}
+
+extern int arch_unwind_init_running(struct unwind_frame_info *,
+                                    int (*callback)(struct unwind_frame_info *,
+                                                    void *arg),
+                                    void *arg);
+
+static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
+{
+#if 0 /* This can only work when selector register saves/restores
+         are properly annotated (and tracked in UNW_REGISTER_INFO). */
+	return user_mode(&info->regs);
+#else
+	return (long)info->regs.rip >= 0
+	       || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END)
+	       || (long)info->regs.rsp >= 0;
+#endif
+}
+
+#else
+
+#define UNW_PC(frame) ((void)(frame), 0)
+
+static inline int arch_unw_user_mode(const void *info)
+{
+	return 0;
+}
+
+#endif
+
+#endif /* _ASM_X86_64_UNWIND_H */
diff --git a/include/asm-x86_64/vga.h b/include/asm-x86_64/vga.h
index ef0c0e5..0ecf68a 100644
--- a/include/asm-x86_64/vga.h
+++ b/include/asm-x86_64/vga.h
@@ -12,7 +12,7 @@
  *	access the videoram directly without any black magic.
  */
 
-#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x)
 
 #define vga_readb(x) (*(x))
 #define vga_writeb(x,y) (*(y) = (x))
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h
index fe105a1..5c26720 100644
--- a/include/asm-xtensa/atomic.h
+++ b/include/asm-xtensa/atomic.h
@@ -13,7 +13,6 @@
 #ifndef _XTENSA_ATOMIC_H
 #define _XTENSA_ATOMIC_H
 
-#include <linux/config.h>
 #include <linux/stringify.h>
 
 typedef struct { volatile int counter; } atomic_t;
diff --git a/include/asm-xtensa/checksum.h b/include/asm-xtensa/checksum.h
index 81a797a..03114f8 100644
--- a/include/asm-xtensa/checksum.h
+++ b/include/asm-xtensa/checksum.h
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_CHECKSUM_H
 #define _XTENSA_CHECKSUM_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 #include <xtensa/config/core.h>
 
@@ -44,8 +43,7 @@
  *	Note: when you get a NULL pointer exception here this means someone
  *	passed in an incorrect kernel address to one of these functions.
  *
- *	If you use these functions directly please don't forget the
- *	verify_area().
+ *	If you use these functions directly please don't forget the access_ok().
  */
 static inline
 unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
diff --git a/include/asm-xtensa/delay.h b/include/asm-xtensa/delay.h
index 1bc601e..e1d8c9e 100644
--- a/include/asm-xtensa/delay.h
+++ b/include/asm-xtensa/delay.h
@@ -12,7 +12,6 @@
 #ifndef _XTENSA_DELAY_H
 #define _XTENSA_DELAY_H
 
-#include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/param.h>
 
diff --git a/include/asm-xtensa/dma.h b/include/asm-xtensa/dma.h
index 1c22b02..db2633f 100644
--- a/include/asm-xtensa/dma.h
+++ b/include/asm-xtensa/dma.h
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_DMA_H
 #define _XTENSA_DMA_H
 
-#include <linux/config.h>
 #include <asm/io.h>		/* need byte IO */
 #include <xtensa/config/core.h>
 
diff --git a/include/asm-xtensa/hardirq.h b/include/asm-xtensa/hardirq.h
index aa9c1ad..87cb19d 100644
--- a/include/asm-xtensa/hardirq.h
+++ b/include/asm-xtensa/hardirq.h
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_HARDIRQ_H
 #define _XTENSA_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/cache.h>
 #include <asm/irq.h>
 
diff --git a/include/asm-xtensa/ide.h b/include/asm-xtensa/ide.h
index b523cd4..6b91274 100644
--- a/include/asm-xtensa/ide.h
+++ b/include/asm-xtensa/ide.h
@@ -14,7 +14,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifndef MAX_HWIFS
 # define MAX_HWIFS	1
diff --git a/include/asm-xtensa/io.h b/include/asm-xtensa/io.h
index c5c1398..556e5ee 100644
--- a/include/asm-xtensa/io.h
+++ b/include/asm-xtensa/io.h
@@ -12,7 +12,6 @@
 #define _XTENSA_IO_H
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <asm/byteorder.h>
 
 #include <linux/types.h>
diff --git a/include/asm-xtensa/irq.h b/include/asm-xtensa/irq.h
index d984e95..049fde7 100644
--- a/include/asm-xtensa/irq.h
+++ b/include/asm-xtensa/irq.h
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_IRQ_H
 #define _XTENSA_IRQ_H
 
-#include <linux/config.h>
 #include <asm/platform/hardware.h>
 
 #include <xtensa/config/core.h>
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
index 364a7b0..af683a7 100644
--- a/include/asm-xtensa/mmu_context.h
+++ b/include/asm-xtensa/mmu_context.h
@@ -13,7 +13,6 @@
 #ifndef _XTENSA_MMU_CONTEXT_H
 #define _XTENSA_MMU_CONTEXT_H
 
-#include <linux/config.h>
 #include <linux/stringify.h>
 
 #include <asm/pgtable.h>
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
index 992bac5..40f4c6c 100644
--- a/include/asm-xtensa/page.h
+++ b/include/asm-xtensa/page.h
@@ -14,7 +14,6 @@
 #ifdef __KERNEL__
 
 #include <asm/processor.h>
-#include <linux/config.h>
 
 /*
  * PAGE_SHIFT determines the page size
diff --git a/include/asm-xtensa/pgalloc.h b/include/asm-xtensa/pgalloc.h
index 734a8d0..d56ddf2 100644
--- a/include/asm-xtensa/pgalloc.h
+++ b/include/asm-xtensa/pgalloc.h
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/threads.h>
 #include <linux/highmem.h>
 #include <asm/processor.h>
diff --git a/include/asm-xtensa/platform.h b/include/asm-xtensa/platform.h
index 3616389..48135a9 100644
--- a/include/asm-xtensa/platform.h
+++ b/include/asm-xtensa/platform.h
@@ -13,7 +13,6 @@
 #ifndef _XTENSA_PLATFORM_H
 #define _XTENSA_PLATFORM_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 
diff --git a/include/asm-xtensa/rwsem.h b/include/asm-xtensa/rwsem.h
index 3c02b0e..abcd86d 100644
--- a/include/asm-xtensa/rwsem.h
+++ b/include/asm-xtensa/rwsem.h
@@ -172,4 +172,9 @@
 	return atomic_add_return(delta, (atomic_t *)(&sem->count));
 }
 
-#endif	/* _XTENSA_RWSEM_XADD_H */
+static inline int rwsem_is_locked(struct rw_semaphore *sem)
+{
+	return (sem->count != 0);
+}
+
+#endif	/* _XTENSA_RWSEM_H */
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
index b29f7ae..f986170 100644
--- a/include/asm-xtensa/system.h
+++ b/include/asm-xtensa/system.h
@@ -11,7 +11,6 @@
 #ifndef _XTENSA_SYSTEM_H
 #define _XTENSA_SYSTEM_H
 
-#include <linux/config.h>
 #include <linux/stringify.h>
 
 #include <asm/processor.h>
diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h
index 06a22b8..88a64e1 100644
--- a/include/asm-xtensa/uaccess.h
+++ b/include/asm-xtensa/uaccess.h
@@ -154,35 +154,6 @@
 .Laccess_ok_\@:
 	.endm
 
-/*
- * verify_area determines whether a memory access is allowed.  It's
- * mostly an unnecessary wrapper for access_ok, but we provide it as a
- * duplicate of the verify_area() C inline function below.  See the
- * equivalent C version below for clarity.
- *
- * On error, verify_area branches to a label indicated by parameter
- * <error>.  This implies that the macro falls through to the next
- * instruction on success.
- *
- * Note that we assume success is the common case, and we optimize the
- * branch fall-through case on success.
- *
- * On Entry:
- * 	<aa>	register containing memory address
- * 	<as>	register containing memory size
- * 	<at>	temp register
- * 	<error>	label to branch to on error; implies fall-through
- * 		macro on success
- * On Exit:
- * 	<aa>	preserved
- * 	<as>	preserved
- * 	<at>	destroyed
- */
-	.macro	verify_area	aa, as, at, sp, error
-	access_ok  \at, \aa, \as, \sp, \error
-	.endm
-
-
 #else /* __ASSEMBLY__ not defined */
 
 #include <linux/sched.h>
@@ -211,11 +182,6 @@
 #define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
 #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
 
-static inline int verify_area(int type, const void * addr, unsigned long size)
-{
-	return access_ok(type,addr,size) ? 0 : -EFAULT;
-}
-
 /*
  * These are the main single-value transfer routines.  They
  * automatically use the right size if we just have the right pointer
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
index 6b39d66..5e1b99d 100644
--- a/include/asm-xtensa/unistd.h
+++ b/include/asm-xtensa/unistd.h
@@ -11,8 +11,6 @@
 #ifndef _XTENSA_UNISTD_H
 #define _XTENSA_UNISTD_H
 
-#include <linux/linkage.h>
-
 #define __NR_spill		  0
 #define __NR_exit		  1
 #define __NR_read		  3
@@ -221,21 +219,9 @@
 #define SYSXTENSA_COUNT		   5	/* count of syscall0 functions*/
 
 #ifdef __KERNEL__
-#define __syscall_return(type, res) return ((type)(res))
-#else
-#define __syscall_return(type, res) \
-do { \
-	if ((unsigned long)(res) >= (unsigned long)(-125)) { \
-	/* Avoid using "res" which is declared to be in register r2; \
-	 * errno might expand to a function call and clobber it.  */ \
-		int __err = -(res); \
-		errno = __err; \
-		res = -1; \
-	} \
-	return (type) (res); \
-} while (0)
-#endif
+#include <linux/linkage.h>
 
+#define __syscall_return(type, res) return ((type)(res))
 
 /* Tensilica's xt-xcc compiler is much more agressive at code
  * optimization than gcc.  Multiple __asm__ statements are
@@ -429,11 +415,10 @@
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
 
-#ifdef __KERNEL__
 #define __ARCH_WANT_STAT64
 #define __ARCH_WANT_SYS_UTIME
 #define __ARCH_WANT_SYS_LLSEEK
 #define __ARCH_WANT_SYS_RT_SIGACTION
-#endif
+#endif /* __KERNEL__ */
 
 #endif	/* _XTENSA_UNISTD_H */
diff --git a/include/asm-xtensa/vga.h b/include/asm-xtensa/vga.h
index 23d82f6..1fd8cab 100644
--- a/include/asm-xtensa/vga.h
+++ b/include/asm-xtensa/vga.h
@@ -11,7 +11,7 @@
 #ifndef _XTENSA_VGA_H
 #define _XTENSA_VGA_H
 
-#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+#define VGA_MAP_MEM(x,s) (unsigned long)phys_to_virt(x)
 
 #define vga_readb(x)	(*(x))
 #define vga_writeb(x,y)	(*(y) = (x))
diff --git a/include/keys/user-type.h b/include/keys/user-type.h
index a3dae18..c37c342 100644
--- a/include/keys/user-type.h
+++ b/include/keys/user-type.h
@@ -37,6 +37,7 @@
 extern int user_instantiate(struct key *key, const void *data, size_t datalen);
 extern int user_update(struct key *key, const void *data, size_t datalen);
 extern int user_match(const struct key *key, const void *criterion);
+extern void user_revoke(struct key *key);
 extern void user_destroy(struct key *key);
 extern void user_describe(const struct key *user, struct seq_file *m);
 extern long user_read(const struct key *key,
diff --git a/include/linux/ac97_codec.h b/include/linux/ac97_codec.h
index c358338..2ed2fd8 100644
--- a/include/linux/ac97_codec.h
+++ b/include/linux/ac97_codec.h
@@ -259,7 +259,7 @@
 	int type;
 	u32 model;
 
-	int modem:1;
+	unsigned int modem:1;
 
 	struct ac97_ops *codec_ops;
 
diff --git a/include/linux/acct.h b/include/linux/acct.h
index 9a66401..e86bae7 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -16,7 +16,6 @@
 #define _LINUX_ACCT_H
 
 #include <linux/types.h>
-#include <linux/jiffies.h>
 
 #include <asm/param.h>
 #include <asm/byteorder.h>
@@ -116,20 +115,23 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_BSD_PROCESS_ACCT
 struct vfsmount;
 struct super_block;
 extern void acct_auto_close_mnt(struct vfsmount *m);
 extern void acct_auto_close(struct super_block *sb);
-extern void acct_process(long exitcode);
+extern void acct_init_pacct(struct pacct_struct *pacct);
+extern void acct_collect(long exitcode, int group_dead);
+extern void acct_process(void);
 extern void acct_update_integrals(struct task_struct *tsk);
 extern void acct_clear_integrals(struct task_struct *tsk);
 #else
 #define acct_auto_close_mnt(x)	do { } while (0)
 #define acct_auto_close(x)	do { } while (0)
-#define acct_process(x)		do { } while (0)
+#define acct_init_pacct(x)	do { } while (0)
+#define acct_collect(x,y)	do { } while (0)
+#define acct_process()		do { } while (0)
 #define acct_update_integrals(x)		do { } while (0)
 #define acct_clear_integrals(task)	do { } while (0)
 #endif
@@ -165,6 +167,7 @@
 #endif	/* __KERNEL */
 
 #ifdef __KERNEL__
+#include <linux/jiffies.h>
 /*
  * Yet another set of HZ to *HZ helper functions.
  * See <linux/jiffies.h> for the original.
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d3bc25e..88b5dfd 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -25,7 +25,6 @@
 #ifndef _LINUX_ACPI_H
 #define _LINUX_ACPI_H
 
-#include <linux/config.h>
 
 #ifdef	CONFIG_ACPI
 
@@ -38,6 +37,7 @@
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
+#include <acpi/acpi_numa.h>
 #include <asm/acpi.h>
 
 
@@ -408,10 +408,18 @@
 void acpi_table_print_srat_entry (acpi_table_entry_header *srat);
 
 /* the following four functions are architecture-dependent */
+#ifdef CONFIG_HAVE_ARCH_PARSE_SRAT
+#define NR_NODE_MEMBLKS MAX_NUMNODES
+#define acpi_numa_slit_init(slit) do {} while (0)
+#define acpi_numa_processor_affinity_init(pa) do {} while (0)
+#define acpi_numa_memory_affinity_init(ma) do {} while (0)
+#define acpi_numa_arch_fixup() do {} while (0)
+#else
 void acpi_numa_slit_init (struct acpi_table_slit *slit);
 void acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa);
 void acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma);
 void acpi_numa_arch_fixup(void);
+#endif
 
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 /* Arch dependent functions for cpu hotplug support */
@@ -520,12 +528,18 @@
 
 #ifdef CONFIG_ACPI_NUMA
 int acpi_get_pxm(acpi_handle handle);
+int acpi_get_node(acpi_handle *handle);
 #else
 static inline int acpi_get_pxm(acpi_handle handle)
 {
 	return 0;
 }
+static inline int acpi_get_node(acpi_handle *handle)
+{
+	return 0;
+}
 #endif
+extern int acpi_paddr_to_node(u64 start_addr, u64 size);
 
 extern int pnpacpi_disabled;
 
diff --git a/include/linux/affs_hardblocks.h b/include/linux/affs_hardblocks.h
index 3fb8699..f1b948c 100644
--- a/include/linux/affs_hardblocks.h
+++ b/include/linux/affs_hardblocks.h
@@ -1,45 +1,47 @@
 #ifndef	AFFS_HARDBLOCKS_H
 #define	AFFS_HARDBLOCKS_H
 
+#include <linux/types.h>
+
 /* Just the needed definitions for the RDB of an Amiga HD. */
 
 struct RigidDiskBlock {
-	u32	rdb_ID;
+	__u32	rdb_ID;
 	__be32	rdb_SummedLongs;
-	s32	rdb_ChkSum;
-	u32	rdb_HostID;
+	__s32	rdb_ChkSum;
+	__u32	rdb_HostID;
 	__be32	rdb_BlockBytes;
-	u32	rdb_Flags;
-	u32	rdb_BadBlockList;
+	__u32	rdb_Flags;
+	__u32	rdb_BadBlockList;
 	__be32	rdb_PartitionList;
-	u32	rdb_FileSysHeaderList;
-	u32	rdb_DriveInit;
-	u32	rdb_Reserved1[6];
-	u32	rdb_Cylinders;
-	u32	rdb_Sectors;
-	u32	rdb_Heads;
-	u32	rdb_Interleave;
-	u32	rdb_Park;
-	u32	rdb_Reserved2[3];
-	u32	rdb_WritePreComp;
-	u32	rdb_ReducedWrite;
-	u32	rdb_StepRate;
-	u32	rdb_Reserved3[5];
-	u32	rdb_RDBBlocksLo;
-	u32	rdb_RDBBlocksHi;
-	u32	rdb_LoCylinder;
-	u32	rdb_HiCylinder;
-	u32	rdb_CylBlocks;
-	u32	rdb_AutoParkSeconds;
-	u32	rdb_HighRDSKBlock;
-	u32	rdb_Reserved4;
+	__u32	rdb_FileSysHeaderList;
+	__u32	rdb_DriveInit;
+	__u32	rdb_Reserved1[6];
+	__u32	rdb_Cylinders;
+	__u32	rdb_Sectors;
+	__u32	rdb_Heads;
+	__u32	rdb_Interleave;
+	__u32	rdb_Park;
+	__u32	rdb_Reserved2[3];
+	__u32	rdb_WritePreComp;
+	__u32	rdb_ReducedWrite;
+	__u32	rdb_StepRate;
+	__u32	rdb_Reserved3[5];
+	__u32	rdb_RDBBlocksLo;
+	__u32	rdb_RDBBlocksHi;
+	__u32	rdb_LoCylinder;
+	__u32	rdb_HiCylinder;
+	__u32	rdb_CylBlocks;
+	__u32	rdb_AutoParkSeconds;
+	__u32	rdb_HighRDSKBlock;
+	__u32	rdb_Reserved4;
 	char	rdb_DiskVendor[8];
 	char	rdb_DiskProduct[16];
 	char	rdb_DiskRevision[4];
 	char	rdb_ControllerVendor[8];
 	char	rdb_ControllerProduct[16];
 	char	rdb_ControllerRevision[4];
-	u32	rdb_Reserved5[10];
+	__u32	rdb_Reserved5[10];
 };
 
 #define	IDNAME_RIGIDDISK	0x5244534B	/* "RDSK" */
@@ -47,16 +49,16 @@
 struct PartitionBlock {
 	__be32	pb_ID;
 	__be32	pb_SummedLongs;
-	s32	pb_ChkSum;
-	u32	pb_HostID;
+	__s32	pb_ChkSum;
+	__u32	pb_HostID;
 	__be32	pb_Next;
-	u32	pb_Flags;
-	u32	pb_Reserved1[2];
-	u32	pb_DevFlags;
-	u8	pb_DriveName[32];
-	u32	pb_Reserved2[15];
+	__u32	pb_Flags;
+	__u32	pb_Reserved1[2];
+	__u32	pb_DevFlags;
+	__u8	pb_DriveName[32];
+	__u32	pb_Reserved2[15];
 	__be32	pb_Environment[17];
-	u32	pb_EReserved[15];
+	__u32	pb_EReserved[15];
 };
 
 #define	IDNAME_PARTITION	0x50415254	/* "PART" */
diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h
index 6d59c8e..bfb8ec7 100644
--- a/include/linux/agpgart.h
+++ b/include/linux/agpgart.h
@@ -27,8 +27,6 @@
 #ifndef _AGP_H
 #define _AGP_H 1
 
-#include <linux/agp_backend.h>
-
 #define AGPIOC_BASE       'A'
 #define AGPIOC_INFO       _IOR (AGPIOC_BASE, 0, struct agp_info*)
 #define AGPIOC_ACQUIRE    _IO  (AGPIOC_BASE, 1)
@@ -112,6 +110,7 @@
 
 #else				/* __KERNEL__ */
 #include <linux/mutex.h>
+#include <linux/agp_backend.h>
 
 #define AGPGART_MINOR 175
 
diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h
index 9cf64b1..29c0448 100644
--- a/include/linux/amba/clcd.h
+++ b/include/linux/amba/clcd.h
@@ -9,7 +9,6 @@
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
-#include <linux/config.h>
 #include <linux/fb.h>
 
 /*
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 312a2c0..3671af8 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -97,6 +97,9 @@
 	ATA_DRQ			= (1 << 3),	/* data request i/o */
 	ATA_ERR			= (1 << 0),	/* have an error */
 	ATA_SRST		= (1 << 2),	/* software reset */
+	ATA_ICRC		= (1 << 7),	/* interface CRC error */
+	ATA_UNC			= (1 << 6),	/* uncorrectable media error */
+	ATA_IDNF		= (1 << 4),	/* ID not found */
 	ATA_ABORTED		= (1 << 2),	/* command aborted */
 
 	/* ATA command block registers */
@@ -130,6 +133,8 @@
 	ATA_CMD_WRITE		= 0xCA,
 	ATA_CMD_WRITE_EXT	= 0x35,
 	ATA_CMD_WRITE_FUA_EXT	= 0x3D,
+	ATA_CMD_FPDMA_READ	= 0x60,
+	ATA_CMD_FPDMA_WRITE	= 0x61,
 	ATA_CMD_PIO_READ	= 0x20,
 	ATA_CMD_PIO_READ_EXT	= 0x24,
 	ATA_CMD_PIO_WRITE	= 0x30,
@@ -148,6 +153,10 @@
 	ATA_CMD_INIT_DEV_PARAMS	= 0x91,
 	ATA_CMD_READ_NATIVE_MAX	= 0xF8,
 	ATA_CMD_READ_NATIVE_MAX_EXT = 0x27,
+	ATA_CMD_READ_LOG_EXT	= 0x2f,
+
+	/* READ_LOG_EXT pages */
+	ATA_LOG_SATA_NCQ	= 0x10,
 
 	/* SETFEATURES stuff */
 	SETFEATURES_XFER	= 0x03,
@@ -172,6 +181,9 @@
 	XFER_PIO_0		= 0x08,
 	XFER_PIO_SLOW		= 0x00,
 
+	SETFEATURES_WC_ON	= 0x02, /* Enable write cache */
+	SETFEATURES_WC_OFF	= 0x82, /* Disable write cache */
+
 	/* ATAPI stuff */
 	ATAPI_PKT_DMA		= (1 << 0),
 	ATAPI_DMADIR		= (1 << 2),	/* ATAPI data dir:
@@ -192,6 +204,16 @@
 	SCR_ACTIVE		= 3,
 	SCR_NOTIFICATION	= 4,
 
+	/* SError bits */
+	SERR_DATA_RECOVERED	= (1 << 0), /* recovered data error */
+	SERR_COMM_RECOVERED	= (1 << 1), /* recovered comm failure */
+	SERR_DATA		= (1 << 8), /* unrecovered data error */
+	SERR_PERSISTENT		= (1 << 9), /* persistent data/comm error */
+	SERR_PROTOCOL		= (1 << 10), /* protocol violation */
+	SERR_INTERNAL		= (1 << 11), /* host internal error */
+	SERR_PHYRDY_CHG		= (1 << 16), /* PHY RDY changed */
+	SERR_DEV_XCHG		= (1 << 26), /* device exchanged */
+
 	/* struct ata_taskfile flags */
 	ATA_TFLAG_LBA48		= (1 << 0), /* enable 48-bit LBA and "HOB" */
 	ATA_TFLAG_ISADDR	= (1 << 1), /* enable r/w to nsect/lba regs */
@@ -199,6 +221,7 @@
 	ATA_TFLAG_WRITE		= (1 << 3), /* data dir: host->dev==1 (write) */
 	ATA_TFLAG_LBA		= (1 << 4), /* enable LBA */
 	ATA_TFLAG_FUA		= (1 << 5), /* enable FUA */
+	ATA_TFLAG_POLLING	= (1 << 6), /* set nIEN to 1 and use polling */
 };
 
 enum ata_tf_protocols {
@@ -207,6 +230,7 @@
 	ATA_PROT_NODATA,	/* no data */
 	ATA_PROT_PIO,		/* PIO single sector */
 	ATA_PROT_DMA,		/* DMA */
+	ATA_PROT_NCQ,		/* NCQ */
 	ATA_PROT_ATAPI,		/* packet command, PIO data xfer*/
 	ATA_PROT_ATAPI_NODATA,	/* packet command, no data */
 	ATA_PROT_ATAPI_DMA,	/* packet command with special DMA sauce */
@@ -262,6 +286,8 @@
 #define ata_id_has_pm(id)	((id)[82] & (1 << 3))
 #define ata_id_has_lba(id)	((id)[49] & (1 << 9))
 #define ata_id_has_dma(id)	((id)[49] & (1 << 8))
+#define ata_id_has_ncq(id)	((id)[76] & (1 << 8))
+#define ata_id_queue_depth(id)	(((id)[75] & 0x1f) + 1)
 #define ata_id_removeable(id)	((id)[0] & (1 << 7))
 #define ata_id_has_dword_io(id)	((id)[50] & (1 << 0))
 #define ata_id_u32(id,n)	\
@@ -272,6 +298,8 @@
 	  ((u64) (id)[(n) + 1] << 16) |	\
 	  ((u64) (id)[(n) + 0]) )
 
+#define ata_id_cdb_intr(id)	(((id)[0] & 0x60) == 0x20)
+
 static inline unsigned int ata_id_major_version(const u16 *id)
 {
 	unsigned int mver;
@@ -311,6 +339,15 @@
 	       (tf->protocol == ATA_PROT_ATAPI_DMA);
 }
 
+static inline int is_multi_taskfile(struct ata_taskfile *tf)
+{
+	return (tf->command == ATA_CMD_READ_MULTI) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI) ||
+	       (tf->command == ATA_CMD_READ_MULTI_EXT) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI_EXT) ||
+	       (tf->command == ATA_CMD_WRITE_MULTI_FUA_EXT);
+}
+
 static inline int ata_ok(u8 status)
 {
 	return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index b203ea8..1eb238a 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -209,7 +209,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/wait.h> /* wait_queue_head_t */
 #include <linux/time.h> /* struct timeval */
 #include <linux/net.h>
diff --git a/include/linux/audit.h b/include/linux/audit.h
index b74c148..e051ff9 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -24,8 +24,7 @@
 #ifndef _LINUX_AUDIT_H_
 #define _LINUX_AUDIT_H_
 
-#include <linux/sched.h>
-#include <linux/elf.h>
+#include <linux/elf-em.h>
 
 /* The netlink messages for the audit system is divided into blocks:
  * 1000 - 1099 are for commanding the audit system
@@ -83,7 +82,12 @@
 #define AUDIT_CONFIG_CHANGE	1305	/* Audit system configuration change */
 #define AUDIT_SOCKADDR		1306	/* sockaddr copied as syscall arg */
 #define AUDIT_CWD		1307	/* Current working directory */
+#define AUDIT_EXECVE		1309	/* execve arguments */
 #define AUDIT_IPC_SET_PERM	1311	/* IPC new permissions record type */
+#define AUDIT_MQ_OPEN		1312	/* POSIX MQ open record type */
+#define AUDIT_MQ_SENDRECV	1313	/* POSIX MQ send/receive record type */
+#define AUDIT_MQ_NOTIFY		1314	/* POSIX MQ notify record type */
+#define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -151,6 +155,7 @@
 #define AUDIT_SE_TYPE	15	/* security label type */
 #define AUDIT_SE_SEN	16	/* security label sensitivity label */
 #define AUDIT_SE_CLR	17	/* security label clearance label */
+#define AUDIT_PPID	18
 
 				/* These are ONLY useful when checking
 				 * at syscall exit time (AUDIT_AT_EXIT). */
@@ -159,6 +164,7 @@
 #define AUDIT_INODE	102
 #define AUDIT_EXIT	103
 #define AUDIT_SUCCESS   104	/* exit >= 0; value ignored */
+#define AUDIT_WATCH	105
 
 #define AUDIT_ARG0      200
 #define AUDIT_ARG1      (AUDIT_ARG0+1)
@@ -273,16 +279,21 @@
 };
 
 #ifdef __KERNEL__
+#include <linux/sched.h>
 
 struct audit_sig_info {
 	uid_t		uid;
 	pid_t		pid;
+	char		ctx[0];
 };
 
 struct audit_buffer;
 struct audit_context;
 struct inode;
 struct netlink_skb_parms;
+struct linux_binprm;
+struct mq_attr;
+struct mqstat;
 
 #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
@@ -297,15 +308,19 @@
 				int major, unsigned long a0, unsigned long a1,
 				unsigned long a2, unsigned long a3);
 extern void audit_syscall_exit(int failed, long return_code);
-extern void audit_getname(const char *name);
+extern void __audit_getname(const char *name);
 extern void audit_putname(const char *name);
-extern void __audit_inode(const char *name, const struct inode *inode, unsigned flags);
+extern void __audit_inode(const char *name, const struct inode *inode);
 extern void __audit_inode_child(const char *dname, const struct inode *inode,
 				unsigned long pino);
-static inline void audit_inode(const char *name, const struct inode *inode,
-			       unsigned flags) {
+static inline void audit_getname(const char *name)
+{
 	if (unlikely(current->audit_context))
-		__audit_inode(name, inode, flags);
+		__audit_getname(name);
+}
+static inline void audit_inode(const char *name, const struct inode *inode) {
+	if (unlikely(current->audit_context))
+		__audit_inode(name, inode);
 }
 static inline void audit_inode_child(const char *dname, 
 				     const struct inode *inode, 
@@ -320,13 +335,61 @@
 			      struct timespec *t, unsigned int *serial);
 extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
 extern uid_t audit_get_loginuid(struct audit_context *ctx);
-extern int audit_ipc_obj(struct kern_ipc_perm *ipcp);
-extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
+extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
+extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
+extern int audit_bprm(struct linux_binprm *bprm);
 extern int audit_socketcall(int nargs, unsigned long *args);
 extern int audit_sockaddr(int len, void *addr);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
-extern void audit_signal_info(int sig, struct task_struct *t);
 extern int audit_set_macxattr(const char *name);
+extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
+extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout);
+extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout);
+extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification);
+extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat);
+
+static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
+{
+	if (unlikely(current->audit_context))
+		return __audit_ipc_obj(ipcp);
+	return 0;
+}
+static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
+{
+	if (unlikely(current->audit_context))
+		return __audit_ipc_set_perm(qbytes, uid, gid, mode);
+	return 0;
+}
+static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
+{
+	if (unlikely(current->audit_context))
+		return __audit_mq_open(oflag, mode, u_attr);
+	return 0;
+}
+static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout)
+{
+	if (unlikely(current->audit_context))
+		return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
+	return 0;
+}
+static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout)
+{
+	if (unlikely(current->audit_context))
+		return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
+	return 0;
+}
+static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+{
+	if (unlikely(current->audit_context))
+		return __audit_mq_notify(mqdes, u_notification);
+	return 0;
+}
+static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+{
+	if (unlikely(current->audit_context))
+		return __audit_mq_getsetattr(mqdes, mqstat);
+	return 0;
+}
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -334,19 +397,24 @@
 #define audit_syscall_exit(f,r) do { ; } while (0)
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
-#define __audit_inode(n,i,f) do { ; } while (0)
+#define __audit_inode(n,i) do { ; } while (0)
 #define __audit_inode_child(d,i,p) do { ; } while (0)
-#define audit_inode(n,i,f) do { ; } while (0)
+#define audit_inode(n,i) do { ; } while (0)
 #define audit_inode_child(d,i,p) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_ipc_obj(i) ({ 0; })
-#define audit_ipc_set_perm(q,u,g,m,i) ({ 0; })
+#define audit_ipc_set_perm(q,u,g,m) ({ 0; })
+#define audit_bprm(p) ({ 0; })
 #define audit_socketcall(n,a) ({ 0; })
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_avc_path(dentry, mnt) ({ 0; })
-#define audit_signal_info(s,t) do { ; } while (0)
 #define audit_set_macxattr(n) do { ; } while (0)
+#define audit_mq_open(o,m,a) ({ 0; })
+#define audit_mq_timedsend(d,l,p,t) ({ 0; })
+#define audit_mq_timedreceive(d,l,p,t) ({ 0; })
+#define audit_mq_notify(d,n) ({ 0; })
+#define audit_mq_getsetattr(d,s) ({ 0; })
 #endif
 
 #ifdef CONFIG_AUDIT
@@ -364,8 +432,11 @@
 extern void		    audit_log_hex(struct audit_buffer *ab,
 					  const unsigned char *buf,
 					  size_t len);
-extern void		    audit_log_untrustedstring(struct audit_buffer *ab,
+extern const char *	    audit_log_untrustedstring(struct audit_buffer *ab,
 						      const char *string);
+extern const char *	    audit_log_n_untrustedstring(struct audit_buffer *ab,
+							size_t n,
+							const char *string);
 extern void		    audit_log_d_path(struct audit_buffer *ab,
 					     const char *prefix,
 					     struct dentry *dentry,
@@ -383,8 +454,8 @@
 #define audit_log_end(b) do { ; } while (0)
 #define audit_log_hex(a,b,l) do { ; } while (0)
 #define audit_log_untrustedstring(a,s) do { ; } while (0)
+#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
 #define audit_log_d_path(b,p,d,v) do { ; } while (0)
-#define audit_panic(m) do { ; } while (0)
 #endif
 #endif
 #endif
diff --git a/include/linux/bio.h b/include/linux/bio.h
index b60ffe3..76bdaea 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -47,7 +47,7 @@
 #define BIO_BUG_ON
 #endif
 
-#define BIO_MAX_PAGES		(256)
+#define BIO_MAX_PAGES		256
 #define BIO_MAX_SIZE		(BIO_MAX_PAGES << PAGE_CACHE_SHIFT)
 #define BIO_MAX_SECTORS		(BIO_MAX_SIZE >> 9)
 
diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index d9ed279..dcc5de7 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -24,6 +24,9 @@
  * The available bitmap operations and their rough meaning in the
  * case that the bitmap is a single unsigned long are thus:
  *
+ * Note that nbits should be always a compile time evaluable constant.
+ * Otherwise many inlines will generate horrible code.
+ *
  * bitmap_zero(dst, nbits)			*dst = 0UL
  * bitmap_fill(dst, nbits)			*dst = ~0UL
  * bitmap_copy(dst, src, nbits)			*dst = *src
@@ -244,6 +247,8 @@
 
 static inline int bitmap_weight(const unsigned long *src, int nbits)
 {
+	if (nbits <= BITS_PER_LONG)
+		return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
 	return __bitmap_weight(src, nbits);
 }
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 59e1259..aafe827 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_BLKDEV_H
 #define _LINUX_BLKDEV_H
 
-#include <linux/config.h>
 #include <linux/major.h>
 #include <linux/genhd.h>
 #include <linux/list.h>
@@ -152,11 +151,9 @@
 	void *elevator_private;
 	void *completion_data;
 
-	unsigned short ioprio;
-
 	int rq_status;	/* should split this into a few status bits */
-	struct gendisk *rq_disk;
 	int errors;
+	struct gendisk *rq_disk;
 	unsigned long start_time;
 
 	/* Number of scatter-gather DMA addr+len pairs after
@@ -171,8 +168,9 @@
 	 */
 	unsigned short nr_hw_segments;
 
+	unsigned short ioprio;
+
 	int tag;
-	char *buffer;
 
 	int ref_count;
 	request_queue_t *q;
@@ -180,6 +178,7 @@
 
 	struct completion *waiting;
 	void *special;
+	char *buffer;
 
 	/*
 	 * when request is used as a packet command carrier
@@ -188,20 +187,14 @@
 	unsigned char cmd[BLK_MAX_CDB];
 
 	unsigned int data_len;
-	void *data;
-
 	unsigned int sense_len;
+	void *data;
 	void *sense;
 
 	unsigned int timeout;
 	int retries;
 
 	/*
-	 * For Power Management requests
-	 */
-	struct request_pm_state *pm;
-
-	/*
 	 * completion callback. end_io_data should be folded in with waiting
 	 */
 	rq_end_io_fn *end_io;
@@ -242,6 +235,7 @@
 	__REQ_PM_RESUME,	/* resume request */
 	__REQ_PM_SHUTDOWN,	/* shutdown request */
 	__REQ_ORDERED_COLOR,	/* is before or after barrier */
+	__REQ_RW_SYNC,		/* request is sync (O_DIRECT) */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -271,6 +265,7 @@
 #define REQ_PM_RESUME	(1 << __REQ_PM_RESUME)
 #define REQ_PM_SHUTDOWN	(1 << __REQ_PM_SHUTDOWN)
 #define REQ_ORDERED_COLOR	(1 << __REQ_ORDERED_COLOR)
+#define REQ_RW_SYNC	(1 << __REQ_RW_SYNC)
 
 /*
  * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -439,9 +434,6 @@
 
 #define RQ_INACTIVE		(-1)
 #define RQ_ACTIVE		1
-#define RQ_SCSI_BUSY		0xffff
-#define RQ_SCSI_DONE		0xfffe
-#define RQ_SCSI_DISCONNECTING	0xffe0
 
 #define QUEUE_FLAG_CLUSTER	0	/* cluster several segments into 1 */
 #define QUEUE_FLAG_QUEUED	1	/* uses generic tag queueing */
diff --git a/include/linux/blkpg.h b/include/linux/blkpg.h
index be5d0f4..faf8a45 100644
--- a/include/linux/blkpg.h
+++ b/include/linux/blkpg.h
@@ -24,6 +24,7 @@
  *
  * For today, only the partition stuff - aeb, 990515
  */
+#include <linux/compiler.h>
 #include <linux/ioctl.h>
 
 #define BLKPG      _IO(0x12,105)
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index b34d3e7..a7e8cef 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -1,7 +1,6 @@
 #ifndef BLKTRACE_H
 #define BLKTRACE_H
 
-#include <linux/config.h>
 #include <linux/blkdev.h>
 #include <linux/relay.h>
 
@@ -91,9 +90,9 @@
  * The remap event
  */
 struct blk_io_trace_remap {
-	u32 device;
+	__be32 device;
 	u32 __pad;
-	u64 sector;
+	__be64 sector;
 };
 
 enum {
@@ -225,7 +224,7 @@
 					 struct bio *bio, unsigned int pdu)
 {
 	struct blk_trace *bt = q->blk_trace;
-	u64 rpdu = cpu_to_be64(pdu);
+	__be64 rpdu = cpu_to_be64(pdu);
 
 	if (likely(!bt))
 		return;
diff --git a/include/linux/blockgroup_lock.h b/include/linux/blockgroup_lock.h
index 0137ee5..8607312 100644
--- a/include/linux/blockgroup_lock.h
+++ b/include/linux/blockgroup_lock.h
@@ -6,7 +6,6 @@
  * Simple hashed spinlocking.
  */
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index da2d107..22866fa 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -91,8 +91,8 @@
 }
 #endif
 
-extern unsigned long __initdata nr_kernel_pages;
-extern unsigned long __initdata nr_all_pages;
+extern unsigned long nr_kernel_pages;
+extern unsigned long nr_all_pages;
 
 extern void *__init alloc_large_system_hash(const char *tablename,
 					    unsigned long bucketsize,
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index fb7e9b7..737e407 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -149,7 +149,6 @@
 			unsigned long b_state);
 void end_buffer_read_sync(struct buffer_head *bh, int uptodate);
 void end_buffer_write_sync(struct buffer_head *bh, int uptodate);
-void end_buffer_async_write(struct buffer_head *bh, int uptodate);
 
 /* Things to do with buffers at mapping->private_list */
 void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode);
@@ -214,6 +213,7 @@
 int nobh_writepage(struct page *page, get_block_t *get_block,
                         struct writeback_control *wbc);
 
+void buffer_init(void);
 
 /*
  * inline definitions
diff --git a/include/linux/cache.h b/include/linux/cache.h
index cc4b3aa..4552504 100644
--- a/include/linux/cache.h
+++ b/include/linux/cache.h
@@ -2,7 +2,6 @@
 #define __LINUX_CACHE_H
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <asm/cache.h>
 
 #ifndef L1_CACHE_ALIGN
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
new file mode 100644
index 0000000..d852024
--- /dev/null
+++ b/include/linux/clocksource.h
@@ -0,0 +1,185 @@
+/*  linux/include/linux/clocksource.h
+ *
+ *  This file contains the structure definitions for clocksources.
+ *
+ *  If you are not a clocksource, or timekeeping code, you should
+ *  not be including this file!
+ */
+#ifndef _LINUX_CLOCKSOURCE_H
+#define _LINUX_CLOCKSOURCE_H
+
+#include <linux/types.h>
+#include <linux/timex.h>
+#include <linux/time.h>
+#include <linux/list.h>
+#include <asm/div64.h>
+#include <asm/io.h>
+
+/* clocksource cycle base type */
+typedef u64 cycle_t;
+
+/**
+ * struct clocksource - hardware abstraction for a free running counter
+ *	Provides mostly state-free accessors to the underlying hardware.
+ *
+ * @name:		ptr to clocksource name
+ * @list:		list head for registration
+ * @rating:		rating value for selection (higher is better)
+ *			To avoid rating inflation the following
+ *			list should give you a guide as to how
+ *			to assign your clocksource a rating
+ *			1-99: Unfit for real use
+ *				Only available for bootup and testing purposes.
+ *			100-199: Base level usability.
+ *				Functional for real use, but not desired.
+ *			200-299: Good.
+ *				A correct and usable clocksource.
+ *			300-399: Desired.
+ *				A reasonably fast and accurate clocksource.
+ *			400-499: Perfect
+ *				The ideal clocksource. A must-use where
+ *				available.
+ * @read:		returns a cycle value
+ * @mask:		bitmask for two's complement
+ *			subtraction of non 64 bit counters
+ * @mult:		cycle to nanosecond multiplier
+ * @shift:		cycle to nanosecond divisor (power of two)
+ * @update_callback:	called when safe to alter clocksource values
+ * @is_continuous:	defines if clocksource is free-running.
+ * @cycle_interval:	Used internally by timekeeping core, please ignore.
+ * @xtime_interval:	Used internally by timekeeping core, please ignore.
+ */
+struct clocksource {
+	char *name;
+	struct list_head list;
+	int rating;
+	cycle_t (*read)(void);
+	cycle_t mask;
+	u32 mult;
+	u32 shift;
+	int (*update_callback)(void);
+	int is_continuous;
+
+	/* timekeeping specific data, ignore */
+	cycle_t cycle_last, cycle_interval;
+	u64 xtime_nsec, xtime_interval;
+	s64 error;
+};
+
+/* simplify initialization of mask field */
+#define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1)
+
+/**
+ * clocksource_khz2mult - calculates mult from khz and shift
+ * @khz:		Clocksource frequency in KHz
+ * @shift_constant:	Clocksource shift factor
+ *
+ * Helper functions that converts a khz counter frequency to a timsource
+ * multiplier, given the clocksource shift value
+ */
+static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant)
+{
+	/*  khz = cyc/(Million ns)
+	 *  mult/2^shift  = ns/cyc
+	 *  mult = ns/cyc * 2^shift
+	 *  mult = 1Million/khz * 2^shift
+	 *  mult = 1000000 * 2^shift / khz
+	 *  mult = (1000000<<shift) / khz
+	 */
+	u64 tmp = ((u64)1000000) << shift_constant;
+
+	tmp += khz/2; /* round for do_div */
+	do_div(tmp, khz);
+
+	return (u32)tmp;
+}
+
+/**
+ * clocksource_hz2mult - calculates mult from hz and shift
+ * @hz:			Clocksource frequency in Hz
+ * @shift_constant:	Clocksource shift factor
+ *
+ * Helper functions that converts a hz counter
+ * frequency to a timsource multiplier, given the
+ * clocksource shift value
+ */
+static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant)
+{
+	/*  hz = cyc/(Billion ns)
+	 *  mult/2^shift  = ns/cyc
+	 *  mult = ns/cyc * 2^shift
+	 *  mult = 1Billion/hz * 2^shift
+	 *  mult = 1000000000 * 2^shift / hz
+	 *  mult = (1000000000<<shift) / hz
+	 */
+	u64 tmp = ((u64)1000000000) << shift_constant;
+
+	tmp += hz/2; /* round for do_div */
+	do_div(tmp, hz);
+
+	return (u32)tmp;
+}
+
+/**
+ * clocksource_read: - Access the clocksource's current cycle value
+ * @cs:		pointer to clocksource being read
+ *
+ * Uses the clocksource to return the current cycle_t value
+ */
+static inline cycle_t clocksource_read(struct clocksource *cs)
+{
+	return cs->read();
+}
+
+/**
+ * cyc2ns - converts clocksource cycles to nanoseconds
+ * @cs:		Pointer to clocksource
+ * @cycles:	Cycles
+ *
+ * Uses the clocksource and ntp ajdustment to convert cycle_ts to nanoseconds.
+ *
+ * XXX - This could use some mult_lxl_ll() asm optimization
+ */
+static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles)
+{
+	u64 ret = (u64)cycles;
+	ret = (ret * cs->mult) >> cs->shift;
+	return ret;
+}
+
+/**
+ * clocksource_calculate_interval - Calculates a clocksource interval struct
+ *
+ * @c:		Pointer to clocksource.
+ * @length_nsec: Desired interval length in nanoseconds.
+ *
+ * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment
+ * pair and interval request.
+ *
+ * Unless you're the timekeeping code, you should not be using this!
+ */
+static inline void clocksource_calculate_interval(struct clocksource *c,
+						unsigned long length_nsec)
+{
+	u64 tmp;
+
+	/* XXX - All of this could use a whole lot of optimization */
+	tmp = length_nsec;
+	tmp <<= c->shift;
+	tmp += c->mult/2;
+	do_div(tmp, c->mult);
+
+	c->cycle_interval = (cycle_t)tmp;
+	if (c->cycle_interval == 0)
+		c->cycle_interval = 1;
+
+	c->xtime_interval = (u64)c->cycle_interval * c->mult;
+}
+
+
+/* used to install a new clocksource */
+int clocksource_register(struct clocksource*);
+void clocksource_reselect(void);
+struct clocksource* clocksource_get_next(void);
+
+#endif /* _LINUX_CLOCKSOURCE_H */
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
index 1417de9..dbb7769 100644
--- a/include/linux/cn_proc.h
+++ b/include/linux/cn_proc.h
@@ -3,31 +3,22 @@
  *
  * Copyright (C) Matt Helsley, IBM Corp. 2005
  * Based on cn_fork.h by Nguyen Anh Quynh and Guillaume Thouvenin
- * Original copyright notice follows:
  * Copyright (C) 2005 Nguyen Anh Quynh <aquynh@gmail.com>
  * Copyright (C) 2005 Guillaume Thouvenin <guillaume.thouvenin@bull.net>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  */
 
 #ifndef CN_PROC_H
 #define CN_PROC_H
 
 #include <linux/types.h>
-#include <linux/time.h>
-#include <linux/connector.h>
 
 /*
  * Userspace sends this enum to register with the kernel that it is listening
diff --git a/include/linux/coda.h b/include/linux/coda.h
index bbc5afc..b5cf078 100644
--- a/include/linux/coda.h
+++ b/include/linux/coda.h
@@ -59,7 +59,6 @@
 #ifndef _CODA_HEADER_
 #define _CODA_HEADER_
 
-#include <linux/config.h>
 
 /* Catch new _KERNEL defn for NetBSD and DJGPP/__CYGWIN32__ */
 #if defined(__NetBSD__) || \
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index b3ecf8f..be512cc 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -27,8 +27,8 @@
 extern struct inode_operations coda_file_inode_operations;
 extern struct inode_operations coda_ioctl_inode_operations;
 
-extern struct address_space_operations coda_file_aops;
-extern struct address_space_operations coda_symlink_aops;
+extern const struct address_space_operations coda_file_aops;
+extern const struct address_space_operations coda_symlink_aops;
 
 extern const struct file_operations coda_dir_operations;
 extern const struct file_operations coda_file_operations;
@@ -36,7 +36,7 @@
 
 /* operations shared over more than one file */
 int coda_open(struct inode *i, struct file *f);
-int coda_flush(struct file *f);
+int coda_flush(struct file *f, fl_owner_t id);
 int coda_release(struct inode *i, struct file *f);
 int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
 int coda_revalidate_inode(struct dentry *);
diff --git a/include/linux/coda_psdev.h b/include/linux/coda_psdev.h
index d539262..98f6c52 100644
--- a/include/linux/coda_psdev.h
+++ b/include/linux/coda_psdev.h
@@ -70,7 +70,7 @@
 		 unsigned int cmd, struct PioctlData *data);
 int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
 int venus_fsync(struct super_block *sb, struct CodaFid *fid);
-int venus_statfs(struct super_block *sb, struct kstatfs *sfs);
+int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
 
 
 /* messages between coda filesystem in kernel and Venus */
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 6d3a654..9760753 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -4,7 +4,6 @@
  * These are the type definitions for the architecture specific
  * syscall compatibility layer.
  */
-#include <linux/config.h>
 
 #ifdef CONFIG_COMPAT
 
@@ -227,5 +226,7 @@
 
 asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
 
+extern int compat_printk(const char *fmt, ...);
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 89ab677..917d62e 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -673,6 +673,11 @@
 COMPATIBLE_IOCTL(CAPI_CLR_FLAGS)
 COMPATIBLE_IOCTL(CAPI_NCCI_OPENCOUNT)
 COMPATIBLE_IOCTL(CAPI_NCCI_GETUNIT)
+/* Siemens Gigaset */
+COMPATIBLE_IOCTL(GIGASET_REDIR)
+COMPATIBLE_IOCTL(GIGASET_CONFIG)
+COMPATIBLE_IOCTL(GIGASET_BRKCHARS)
+COMPATIBLE_IOCTL(GIGASET_VERSION)
 /* Misc. */
 COMPATIBLE_IOCTL(0x41545900)		/* ATYIO_CLKR */
 COMPATIBLE_IOCTL(0x41545901)		/* ATYIO_CLKW */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index f23d3c6..9b4f110 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -78,6 +78,7 @@
 
 #endif /* __ASSEMBLY__ */
 
+#ifdef __KERNEL__
 /*
  * Allow us to mark functions as 'deprecated' and have gcc emit a nice
  * warning for each use, in hopes of speeding the functions removal.
@@ -127,6 +128,16 @@
 # define __attribute_pure__	/* unimplemented */
 #endif
 
+#ifndef noinline
+#define noinline
+#endif
+
+#ifndef __always_inline
+#define __always_inline inline
+#endif
+
+#endif /* __KERNEL__ */
+
 /*
  * From the GCC manual:
  *
@@ -145,12 +156,4 @@
 # define __attribute_const__	/* unimplemented */
 #endif
 
-#ifndef noinline
-#define noinline
-#endif
-
-#ifndef __always_inline
-#define __always_inline inline
-#endif
-
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/connector.h b/include/linux/connector.h
index ad1a22c..4c02119 100644
--- a/include/linux/connector.h
+++ b/include/linux/connector.h
@@ -34,8 +34,11 @@
 #define CN_VAL_PROC			0x1
 #define CN_IDX_CIFS			0x2
 #define CN_VAL_CIFS                     0x1
+#define CN_W1_IDX			0x3	/* w1 communication */
+#define CN_W1_VAL			0x1
 
-#define CN_NETLINK_USERS		1
+
+#define CN_NETLINK_USERS		4
 
 /*
  * Maximum connector's message size.
diff --git a/include/linux/console.h b/include/linux/console.h
index 7213713..3bdf215 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -63,9 +63,11 @@
 extern const struct consw newport_con;	/* SGI Newport console  */
 extern const struct consw prom_con;	/* SPARC PROM console */
 
+int con_is_bound(const struct consw *csw);
+int register_con_driver(const struct consw *csw, int first, int last);
+int unregister_con_driver(const struct consw *csw);
 int take_over_console(const struct consw *sw, int first, int last, int deflt);
 void give_up_console(const struct consw *sw);
-
 /* scroll */
 #define SM_UP       (1)
 #define SM_DOWN     (2)
@@ -87,6 +89,7 @@
 #define CON_CONSDEV	(2) /* Last on the command line */
 #define CON_ENABLED	(4)
 #define CON_BOOT	(8)
+#define CON_ANYTIME	(16) /* Safe to call when cpu is offline */
 
 struct console
 {
@@ -117,6 +120,10 @@
 extern void console_start(struct console *);
 extern int is_console_locked(void);
 
+/* Suspend and resume console messages over PM events */
+extern void suspend_console(void);
+extern void resume_console(void);
+
 /* Some debug stub to catch some of the obvious races in the VT code */
 #if 1
 #define WARN_CONSOLE_UNLOCKED()	WARN_ON(!is_console_locked() && !oops_in_progress)
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 08d50c5..a3caf68 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -31,17 +31,23 @@
 	struct sys_device sysdev;
 };
 
-extern int register_cpu(struct cpu *, int, struct node *);
+extern int register_cpu(struct cpu *cpu, int num);
 extern struct sys_device *get_cpu_sysdev(unsigned cpu);
 #ifdef CONFIG_HOTPLUG_CPU
-extern void unregister_cpu(struct cpu *, struct node *);
+extern void unregister_cpu(struct cpu *cpu);
 #endif
 struct notifier_block;
 
 #ifdef CONFIG_SMP
 /* Need to know about CPUs going up/down? */
 extern int register_cpu_notifier(struct notifier_block *nb);
+#ifdef CONFIG_HOTPLUG_CPU
 extern void unregister_cpu_notifier(struct notifier_block *nb);
+#else
+static inline void unregister_cpu_notifier(struct notifier_block *nb)
+{
+}
+#endif
 extern int current_in_cpu_hotplug(void);
 
 int cpu_up(unsigned int cpu);
@@ -73,6 +79,8 @@
 		{ .notifier_call = fn, .priority = pri };	\
 	register_cpu_notifier(&fn##_nb);			\
 }
+#define register_hotcpu_notifier(nb)	register_cpu_notifier(nb)
+#define unregister_hotcpu_notifier(nb)	unregister_cpu_notifier(nb)
 int cpu_down(unsigned int cpu);
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
 #else
@@ -80,6 +88,8 @@
 #define unlock_cpu_hotplug()	do { } while (0)
 #define lock_cpu_hotplug_interruptible() 0
 #define hotcpu_notifier(fn, pri)
+#define register_hotcpu_notifier(nb)
+#define unregister_hotcpu_notifier(nb)
 
 /* CPUs don't go offline once they're online w/o CONFIG_HOTPLUG_CPU */
 static inline int cpu_is_offline(int cpu) { return 0; }
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 17866d7..466fbe9 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -15,7 +15,6 @@
 #define _LINUX_CPUFREQ_H
 
 #include <linux/mutex.h>
-#include <linux/config.h>
 #include <linux/notifier.h>
 #include <linux/threads.h>
 #include <linux/device.h>
@@ -73,6 +72,8 @@
 
 struct cpufreq_policy {
 	cpumask_t		cpus;	/* affected CPUs */
+	unsigned int		shared_type; /* ANY or ALL affected CPUs
+						should set cpufreq */
 	unsigned int		cpu;    /* cpu nr of registered CPU */
 	struct cpufreq_cpuinfo	cpuinfo;/* see above */
 
@@ -99,6 +100,8 @@
 #define CPUFREQ_INCOMPATIBLE	(1)
 #define CPUFREQ_NOTIFY		(2)
 
+#define CPUFREQ_SHARED_TYPE_ALL	(0) /* All dependent CPUs should set freq */
+#define CPUFREQ_SHARED_TYPE_ANY	(1) /* Freq can be set from any dependent CPU */
 
 /******************** cpufreq transition notifiers *******************/
 
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 9cbb781..b268a3c 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -317,7 +317,8 @@
 		(cpu) < NR_CPUS;		\
 		(cpu) = next_cpu((cpu), (mask)))
 #else /* NR_CPUS == 1 */
-#define for_each_cpu_mask(cpu, mask) for ((cpu) = 0; (cpu) < 1; (cpu)++)
+#define for_each_cpu_mask(cpu, mask)		\
+	for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask)
 #endif /* NR_CPUS */
 
 /*
@@ -405,7 +406,6 @@
 #define any_online_cpu(mask)		0
 #endif
 
-#define for_each_cpu(cpu)  for_each_cpu_mask((cpu), cpu_possible_map)
 #define for_each_possible_cpu(cpu)  for_each_cpu_mask((cpu), cpu_possible_map)
 #define for_each_online_cpu(cpu)  for_each_cpu_mask((cpu), cpu_online_map)
 #define for_each_present_cpu(cpu) for_each_cpu_mask((cpu), cpu_present_map)
diff --git a/include/linux/cramfs_fs.h b/include/linux/cramfs_fs.h
index a8948f3..a41f384 100644
--- a/include/linux/cramfs_fs.h
+++ b/include/linux/cramfs_fs.h
@@ -1,13 +1,7 @@
 #ifndef __CRAMFS_H
 #define __CRAMFS_H
 
-#ifndef __KERNEL__
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-#endif
+#include <linux/types.h>
 
 #define CRAMFS_MAGIC		0x28cd3d45	/* some random number */
 #define CRAMFS_SIGNATURE	"Compressed ROMFS"
@@ -33,9 +27,9 @@
  * Reasonably terse representation of the inode data.
  */
 struct cramfs_inode {
-	u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;
+	__u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH;
 	/* SIZE for device files is i_rdev */
-	u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;
+	__u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH;
 	/* NAMELEN is the length of the file name, divided by 4 and
            rounded up.  (cramfs doesn't support hard links.) */
 	/* OFFSET: For symlinks and non-empty regular files, this
@@ -44,27 +38,27 @@
 	   see README).  For non-empty directories it is the offset
 	   (divided by 4) of the inode of the first file in that
 	   directory.  For anything else, offset is zero. */
-	u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;
+	__u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH;
 };
 
 struct cramfs_info {
-	u32 crc;
-	u32 edition;
-	u32 blocks;
-	u32 files;
+	__u32 crc;
+	__u32 edition;
+	__u32 blocks;
+	__u32 files;
 };
 
 /*
  * Superblock information at the beginning of the FS.
  */
 struct cramfs_super {
-	u32 magic;			/* 0x28cd3d45 - random number */
-	u32 size;			/* length in bytes */
-	u32 flags;			/* feature flags */
-	u32 future;			/* reserved for future use */
-	u8 signature[16];		/* "Compressed ROMFS" */
+	__u32 magic;			/* 0x28cd3d45 - random number */
+	__u32 size;			/* length in bytes */
+	__u32 flags;			/* feature flags */
+	__u32 future;			/* reserved for future use */
+	__u8 signature[16];		/* "Compressed ROMFS" */
 	struct cramfs_info fsid;	/* unique filesystem info */
-	u8 name[16];			/* user-defined name */
+	__u8 name[16];			/* user-defined name */
 	struct cramfs_inode root;	/* root inode data */
 };
 
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 0ab1bc1..7f94624 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -17,7 +17,6 @@
 #ifndef _LINUX_CRYPTO_H
 #define _LINUX_CRYPTO_H
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -67,7 +66,7 @@
 
 struct cipher_desc {
 	struct crypto_tfm *tfm;
-	void (*crfn)(void *ctx, u8 *dst, const u8 *src);
+	void (*crfn)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 	unsigned int (*prfn)(const struct cipher_desc *desc, u8 *dst,
 			     const u8 *src, unsigned int nbytes);
 	void *info;
@@ -80,10 +79,10 @@
 struct cipher_alg {
 	unsigned int cia_min_keysize;
 	unsigned int cia_max_keysize;
-	int (*cia_setkey)(void *ctx, const u8 *key,
+	int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key,
 	                  unsigned int keylen, u32 *flags);
-	void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src);
-	void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src);
+	void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+	void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 
 	unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc,
 					u8 *dst, const u8 *src,
@@ -101,20 +100,19 @@
 
 struct digest_alg {
 	unsigned int dia_digestsize;
-	void (*dia_init)(void *ctx);
-	void (*dia_update)(void *ctx, const u8 *data, unsigned int len);
-	void (*dia_final)(void *ctx, u8 *out);
-	int (*dia_setkey)(void *ctx, const u8 *key,
+	void (*dia_init)(struct crypto_tfm *tfm);
+	void (*dia_update)(struct crypto_tfm *tfm, const u8 *data,
+			   unsigned int len);
+	void (*dia_final)(struct crypto_tfm *tfm, u8 *out);
+	int (*dia_setkey)(struct crypto_tfm *tfm, const u8 *key,
 	                  unsigned int keylen, u32 *flags);
 };
 
 struct compress_alg {
-	int (*coa_init)(void *ctx);
-	void (*coa_exit)(void *ctx);
-	int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen,
-	                    u8 *dst, unsigned int *dlen);
-	int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen,
-	                      u8 *dst, unsigned int *dlen);
+	int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src,
+			    unsigned int slen, u8 *dst, unsigned int *dlen);
+	int (*coa_decompress)(struct crypto_tfm *tfm, const u8 *src,
+			      unsigned int slen, u8 *dst, unsigned int *dlen);
 };
 
 #define cra_cipher	cra_u.cipher
@@ -130,14 +128,17 @@
 
 	int cra_priority;
 
-	const char cra_name[CRYPTO_MAX_ALG_NAME];
-	const char cra_driver_name[CRYPTO_MAX_ALG_NAME];
+	char cra_name[CRYPTO_MAX_ALG_NAME];
+	char cra_driver_name[CRYPTO_MAX_ALG_NAME];
 
 	union {
 		struct cipher_alg cipher;
 		struct digest_alg digest;
 		struct compress_alg compress;
 	} cra_u;
+
+	int (*cra_init)(struct crypto_tfm *tfm);
+	void (*cra_exit)(struct crypto_tfm *tfm);
 	
 	struct module *cra_module;
 };
diff --git a/include/linux/cyclomx.h b/include/linux/cyclomx.h
index 300d704..b88f7f4 100644
--- a/include/linux/cyclomx.h
+++ b/include/linux/cyclomx.h
@@ -24,7 +24,6 @@
 * 1998/08/08	acme		Version 0.0.1
 */
 
-#include <linux/config.h>
 #include <linux/wanrouter.h>
 #include <linux/spinlock.h>
 
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 836325e..0dd1610 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -217,7 +217,6 @@
 extern struct dentry * d_splice_alias(struct inode *, struct dentry *);
 extern void shrink_dcache_sb(struct super_block *);
 extern void shrink_dcache_parent(struct dentry *);
-extern void shrink_dcache_anon(struct hlist_head *);
 extern int d_invalidate(struct dentry *);
 
 /* only used at mount-time */
diff --git a/include/linux/dcookies.h b/include/linux/dcookies.h
index 1d68428..0fe7cdf 100644
--- a/include/linux/dcookies.h
+++ b/include/linux/dcookies.h
@@ -9,7 +9,6 @@
 #ifndef DCOOKIES_H
 #define DCOOKIES_H
  
-#include <linux/config.h>
 
 #ifdef CONFIG_PROFILING
  
diff --git a/include/linux/delay.h b/include/linux/delay.h
index acb7486..17ddb55 100644
--- a/include/linux/delay.h
+++ b/include/linux/delay.h
@@ -25,10 +25,7 @@
 #define MAX_UDELAY_MS	5
 #endif
 
-#ifdef notdef
-#define mdelay(n) (\
-	{unsigned long __ms=(n); while (__ms--) udelay(1000);})
-#else
+#ifndef mdelay
 #define mdelay(n) (\
 	(__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : \
 	({unsigned long __ms=(n); while (__ms--) udelay(1000);}))
diff --git a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
index 89810e7..0d74a6f 100644
--- a/include/linux/devfs_fs_kernel.h
+++ b/include/linux/devfs_fs_kernel.h
@@ -2,7 +2,6 @@
 #define _LINUX_DEVFS_FS_KERNEL_H
 
 #include <linux/fs.h>
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index aee10b2..e3d1c33 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -8,9 +8,12 @@
 #ifndef _LINUX_DEVICE_MAPPER_H
 #define _LINUX_DEVICE_MAPPER_H
 
+#ifdef __KERNEL__
+
 struct dm_target;
 struct dm_table;
 struct dm_dev;
+struct mapped_device;
 
 typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
 
@@ -78,7 +81,7 @@
 struct target_type {
 	const char *name;
 	struct module *module;
-        unsigned version[3];
+	unsigned version[3];
 	dm_ctr_fn ctr;
 	dm_dtr_fn dtr;
 	dm_map_fn map;
@@ -128,4 +131,108 @@
 int dm_register_target(struct target_type *t);
 int dm_unregister_target(struct target_type *t);
 
-#endif				/* _LINUX_DEVICE_MAPPER_H */
+
+/*-----------------------------------------------------------------
+ * Functions for creating and manipulating mapped devices.
+ * Drop the reference with dm_put when you finish with the object.
+ *---------------------------------------------------------------*/
+
+/*
+ * DM_ANY_MINOR chooses the next available minor number.
+ */
+#define DM_ANY_MINOR (-1)
+int dm_create(int minor, struct mapped_device **md);
+
+/*
+ * Reference counting for md.
+ */
+struct mapped_device *dm_get_md(dev_t dev);
+void dm_get(struct mapped_device *md);
+void dm_put(struct mapped_device *md);
+
+/*
+ * An arbitrary pointer may be stored alongside a mapped device.
+ */
+void dm_set_mdptr(struct mapped_device *md, void *ptr);
+void *dm_get_mdptr(struct mapped_device *md);
+
+/*
+ * A device can still be used while suspended, but I/O is deferred.
+ */
+int dm_suspend(struct mapped_device *md, int with_lockfs);
+int dm_resume(struct mapped_device *md);
+
+/*
+ * Event functions.
+ */
+uint32_t dm_get_event_nr(struct mapped_device *md);
+int dm_wait_event(struct mapped_device *md, int event_nr);
+
+/*
+ * Info functions.
+ */
+const char *dm_device_name(struct mapped_device *md);
+struct gendisk *dm_disk(struct mapped_device *md);
+int dm_suspended(struct mapped_device *md);
+
+/*
+ * Geometry functions.
+ */
+int dm_get_geometry(struct mapped_device *md, struct hd_geometry *geo);
+int dm_set_geometry(struct mapped_device *md, struct hd_geometry *geo);
+
+
+/*-----------------------------------------------------------------
+ * Functions for manipulating device-mapper tables.
+ *---------------------------------------------------------------*/
+
+/*
+ * First create an empty table.
+ */
+int dm_table_create(struct dm_table **result, int mode,
+		    unsigned num_targets, struct mapped_device *md);
+
+/*
+ * Then call this once for each target.
+ */
+int dm_table_add_target(struct dm_table *t, const char *type,
+			sector_t start, sector_t len, char *params);
+
+/*
+ * Finally call this to make the table ready for use.
+ */
+int dm_table_complete(struct dm_table *t);
+
+/*
+ * Table reference counting.
+ */
+struct dm_table *dm_get_table(struct mapped_device *md);
+void dm_table_get(struct dm_table *t);
+void dm_table_put(struct dm_table *t);
+
+/*
+ * Queries
+ */
+sector_t dm_table_get_size(struct dm_table *t);
+unsigned int dm_table_get_num_targets(struct dm_table *t);
+int dm_table_get_mode(struct dm_table *t);
+struct mapped_device *dm_table_get_md(struct dm_table *t);
+
+/*
+ * Trigger an event.
+ */
+void dm_table_event(struct dm_table *t);
+
+/*
+ * The device must be suspended before calling this method.
+ */
+int dm_swap_table(struct mapped_device *md, struct dm_table *t);
+
+/*
+ * Prepare a table for a device that will error all I/O.
+ * To make it active, call dm_suspend(), dm_swap_table() then dm_resume().
+ */
+int dm_create_error_table(struct dm_table **result, struct mapped_device *md);
+
+#endif	/* __KERNEL__ */
+#endif	/* _LINUX_DEVICE_MAPPER_H */
diff --git a/include/linux/device.h b/include/linux/device.h
index e8e53b9..1e5f30d 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -11,7 +11,6 @@
 #ifndef _DEVICE_H_
 #define _DEVICE_H_
 
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/kobject.h>
 #include <linux/klist.h>
@@ -61,11 +60,6 @@
 
 extern void bus_rescan_devices(struct bus_type * bus);
 
-extern struct bus_type * get_bus(struct bus_type * bus);
-extern void put_bus(struct bus_type * bus);
-
-extern struct bus_type * find_bus(char * name);
-
 /* iterator helpers for buses */
 
 int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
@@ -148,6 +142,7 @@
 
 	struct subsystem	subsys;
 	struct list_head	children;
+	struct list_head	devices;
 	struct list_head	interfaces;
 	struct semaphore	sem;	/* locks both the children and interfaces lists */
 
@@ -164,9 +159,6 @@
 extern int class_register(struct class *);
 extern void class_unregister(struct class *);
 
-extern struct class * class_get(struct class *);
-extern void class_put(struct class *);
-
 
 struct class_attribute {
 	struct attribute	attr;
@@ -314,6 +306,7 @@
 	struct kobject kobj;
 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
 	struct device_attribute uevent_attr;
+	struct device_attribute *devt_attr;
 
 	struct semaphore	sem;	/* semaphore to synchronize calls to
 					 * its driver.
@@ -341,6 +334,11 @@
 	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
 					     override */
 
+	/* class_device migration path */
+	struct list_head	node;
+	struct class		*class;		/* optional*/
+	dev_t			devt;		/* dev_t, creates the sysfs "dev" */
+
 	void	(*release)(struct device * dev);
 };
 
@@ -382,6 +380,13 @@
 extern void driver_attach(struct device_driver * drv);
 extern void device_reprobe(struct device *dev);
 
+/*
+ * Easy functions for dynamically creating devices on the fly
+ */
+extern struct device *device_create(struct class *cls, struct device *parent,
+				    dev_t devt, char *fmt, ...)
+				    __attribute__((format(printf,4,5)));
+extern void device_destroy(struct class *cls, dev_t devt);
 
 /*
  * Platform "fixup" functions - allow the platform to have their say
@@ -411,8 +416,9 @@
 extern void firmware_unregister(struct subsystem *);
 
 /* debugging and troubleshooting/diagnostic helpers. */
+extern const char *dev_driver_string(struct device *dev);
 #define dev_printk(level, dev, format, arg...)	\
-	printk(level "%s %s: " format , (dev)->driver ? (dev)->driver->name : "" , (dev)->bus_id , ## arg)
+	printk(level "%s %s: " format , dev_driver_string(dev) , (dev)->bus_id , ## arg)
 
 #ifdef DEBUG
 #define dev_dbg(dev, format, arg...)		\
diff --git a/include/linux/divert.h b/include/linux/divert.h
index 6919b09..8fb4e9d 100644
--- a/include/linux/divert.h
+++ b/include/linux/divert.h
@@ -27,10 +27,10 @@
 {
 	int		divert;  /* are we active */
 	unsigned int protos;	/* protocols */
-	u16		tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
-	u16		tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
-	u16		udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
-	u16		udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
+	__u16		tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */
+	__u16		tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */
+	__u16		udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */
+	__u16		udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */
 };
 
 /*
@@ -40,12 +40,12 @@
 
 typedef union _divert_cf_arg
 {
-	s16		int16;
-	u16		uint16;
-	s32		int32;
-	u32		uint32;
-	s64		int64;
-	u64		uint64;
+	__s16		int16;
+	__u16		uint16;
+	__s32		int32;
+	__u32		uint32;
+	__s64		int64;
+	__u64		uint64;
 	void	__user *ptr;
 } divert_cf_arg;
 
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index c67c678..9623bb6 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -285,9 +285,9 @@
 #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	6
+#define DM_VERSION_MINOR	7
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2006-02-17)"
+#define DM_VERSION_EXTRA	"-ioctl (2006-06-24)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */
@@ -314,7 +314,7 @@
 #define DM_BUFFER_FULL_FLAG	(1 << 8) /* Out */
 
 /*
- * Set this to improve performance when you aren't going to use open_count.
+ * This flag is now ignored.
  */
 #define DM_SKIP_BDGET_FLAG	(1 << 9) /* In */
 
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
new file mode 100644
index 0000000..272010a6
--- /dev/null
+++ b/include/linux/dmaengine.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef DMAENGINE_H
+#define DMAENGINE_H
+
+#ifdef CONFIG_DMA_ENGINE
+
+#include <linux/device.h>
+#include <linux/uio.h>
+#include <linux/kref.h>
+#include <linux/completion.h>
+#include <linux/rcupdate.h>
+
+/**
+ * enum dma_event - resource PNP/power managment events
+ * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
+ * @DMA_RESOURCE_RESUME: DMA device returning to full power
+ * @DMA_RESOURCE_ADDED: DMA device added to the system
+ * @DMA_RESOURCE_REMOVED: DMA device removed from the system
+ */
+enum dma_event {
+	DMA_RESOURCE_SUSPEND,
+	DMA_RESOURCE_RESUME,
+	DMA_RESOURCE_ADDED,
+	DMA_RESOURCE_REMOVED,
+};
+
+/**
+ * typedef dma_cookie_t
+ *
+ * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code
+ */
+typedef s32 dma_cookie_t;
+
+#define dma_submit_error(cookie) ((cookie) < 0 ? 1 : 0)
+
+/**
+ * enum dma_status - DMA transaction status
+ * @DMA_SUCCESS: transaction completed successfully
+ * @DMA_IN_PROGRESS: transaction not yet processed
+ * @DMA_ERROR: transaction failed
+ */
+enum dma_status {
+	DMA_SUCCESS,
+	DMA_IN_PROGRESS,
+	DMA_ERROR,
+};
+
+/**
+ * struct dma_chan_percpu - the per-CPU part of struct dma_chan
+ * @refcount: local_t used for open-coded "bigref" counting
+ * @memcpy_count: transaction counter
+ * @bytes_transferred: byte counter
+ */
+
+struct dma_chan_percpu {
+	local_t refcount;
+	/* stats */
+	unsigned long memcpy_count;
+	unsigned long bytes_transferred;
+};
+
+/**
+ * struct dma_chan - devices supply DMA channels, clients use them
+ * @client: ptr to the client user of this chan, will be NULL when unused
+ * @device: ptr to the dma device who supplies this channel, always !NULL
+ * @cookie: last cookie value returned to client
+ * @chan_id:
+ * @class_dev:
+ * @refcount: kref, used in "bigref" slow-mode
+ * @slow_ref:
+ * @rcu:
+ * @client_node: used to add this to the client chan list
+ * @device_node: used to add this to the device chan list
+ * @local: per-cpu pointer to a struct dma_chan_percpu
+ */
+struct dma_chan {
+	struct dma_client *client;
+	struct dma_device *device;
+	dma_cookie_t cookie;
+
+	/* sysfs */
+	int chan_id;
+	struct class_device class_dev;
+
+	struct kref refcount;
+	int slow_ref;
+	struct rcu_head rcu;
+
+	struct list_head client_node;
+	struct list_head device_node;
+	struct dma_chan_percpu *local;
+};
+
+void dma_chan_cleanup(struct kref *kref);
+
+static inline void dma_chan_get(struct dma_chan *chan)
+{
+	if (unlikely(chan->slow_ref))
+		kref_get(&chan->refcount);
+	else {
+		local_inc(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
+		put_cpu();
+	}
+}
+
+static inline void dma_chan_put(struct dma_chan *chan)
+{
+	if (unlikely(chan->slow_ref))
+		kref_put(&chan->refcount, dma_chan_cleanup);
+	else {
+		local_dec(&(per_cpu_ptr(chan->local, get_cpu())->refcount));
+		put_cpu();
+	}
+}
+
+/*
+ * typedef dma_event_callback - function pointer to a DMA event callback
+ */
+typedef void (*dma_event_callback) (struct dma_client *client,
+		struct dma_chan *chan, enum dma_event event);
+
+/**
+ * struct dma_client - info on the entity making use of DMA services
+ * @event_callback: func ptr to call when something happens
+ * @chan_count: number of chans allocated
+ * @chans_desired: number of chans requested. Can be +/- chan_count
+ * @lock: protects access to the channels list
+ * @channels: the list of DMA channels allocated
+ * @global_node: list_head for global dma_client_list
+ */
+struct dma_client {
+	dma_event_callback	event_callback;
+	unsigned int		chan_count;
+	unsigned int		chans_desired;
+
+	spinlock_t		lock;
+	struct list_head	channels;
+	struct list_head	global_node;
+};
+
+/**
+ * struct dma_device - info on the entity supplying DMA services
+ * @chancnt: how many DMA channels are supported
+ * @channels: the list of struct dma_chan
+ * @global_node: list_head for global dma_device_list
+ * @refcount:
+ * @done:
+ * @dev_id:
+ * Other func ptrs: used to make use of this device's capabilities
+ */
+struct dma_device {
+
+	unsigned int chancnt;
+	struct list_head channels;
+	struct list_head global_node;
+
+	struct kref refcount;
+	struct completion done;
+
+	int dev_id;
+
+	int (*device_alloc_chan_resources)(struct dma_chan *chan);
+	void (*device_free_chan_resources)(struct dma_chan *chan);
+	dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan,
+			void *dest, void *src, size_t len);
+	dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan,
+			struct page *page, unsigned int offset, void *kdata,
+			size_t len);
+	dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan,
+			struct page *dest_pg, unsigned int dest_off,
+			struct page *src_pg, unsigned int src_off, size_t len);
+	enum dma_status (*device_memcpy_complete)(struct dma_chan *chan,
+			dma_cookie_t cookie, dma_cookie_t *last,
+			dma_cookie_t *used);
+	void (*device_memcpy_issue_pending)(struct dma_chan *chan);
+};
+
+/* --- public DMA engine API --- */
+
+struct dma_client *dma_async_client_register(dma_event_callback event_callback);
+void dma_async_client_unregister(struct dma_client *client);
+void dma_async_client_chan_request(struct dma_client *client,
+		unsigned int number);
+
+/**
+ * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses
+ * @chan: DMA channel to offload copy to
+ * @dest: destination address (virtual)
+ * @src: source address (virtual)
+ * @len: length
+ *
+ * Both @dest and @src must be mappable to a bus address according to the
+ * DMA mapping API rules for streaming mappings.
+ * Both @dest and @src must stay memory resident (kernel memory or locked
+ * user space pages)
+ */
+static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan,
+	void *dest, void *src, size_t len)
+{
+	int cpu = get_cpu();
+	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+	put_cpu();
+
+	return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len);
+}
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy
+ * @chan: DMA channel to offload copy to
+ * @page: destination page
+ * @offset: offset in page to copy to
+ * @kdata: source address (virtual)
+ * @len: length
+ *
+ * Both @page/@offset and @kdata must be mappable to a bus address according
+ * to the DMA mapping API rules for streaming mappings.
+ * Both @page/@offset and @kdata must stay memory resident (kernel memory or
+ * locked user space pages)
+ */
+static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan,
+	struct page *page, unsigned int offset, void *kdata, size_t len)
+{
+	int cpu = get_cpu();
+	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+	put_cpu();
+
+	return chan->device->device_memcpy_buf_to_pg(chan, page, offset,
+	                                             kdata, len);
+}
+
+/**
+ * dma_async_memcpy_buf_to_pg - offloaded copy
+ * @chan: DMA channel to offload copy to
+ * @dest_page: destination page
+ * @dest_off: offset in page to copy to
+ * @src_page: source page
+ * @src_off: offset in page to copy from
+ * @len: length
+ *
+ * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus
+ * address according to the DMA mapping API rules for streaming mappings.
+ * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident
+ * (kernel memory or locked user space pages)
+ */
+static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan,
+	struct page *dest_pg, unsigned int dest_off, struct page *src_pg,
+	unsigned int src_off, size_t len)
+{
+	int cpu = get_cpu();
+	per_cpu_ptr(chan->local, cpu)->bytes_transferred += len;
+	per_cpu_ptr(chan->local, cpu)->memcpy_count++;
+	put_cpu();
+
+	return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off,
+	                                            src_pg, src_off, len);
+}
+
+/**
+ * dma_async_memcpy_issue_pending - flush pending copies to HW
+ * @chan:
+ *
+ * This allows drivers to push copies to HW in batches,
+ * reducing MMIO writes where possible.
+ */
+static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan)
+{
+	return chan->device->device_memcpy_issue_pending(chan);
+}
+
+/**
+ * dma_async_memcpy_complete - poll for transaction completion
+ * @chan: DMA channel
+ * @cookie: transaction identifier to check status of
+ * @last: returns last completed cookie, can be NULL
+ * @used: returns last issued cookie, can be NULL
+ *
+ * If @last and @used are passed in, upon return they reflect the driver
+ * internal state and can be used with dma_async_is_complete() to check
+ * the status of multiple cookies without re-checking hardware state.
+ */
+static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan,
+	dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used)
+{
+	return chan->device->device_memcpy_complete(chan, cookie, last, used);
+}
+
+/**
+ * dma_async_is_complete - test a cookie against chan state
+ * @cookie: transaction identifier to test status of
+ * @last_complete: last know completed transaction
+ * @last_used: last cookie value handed out
+ *
+ * dma_async_is_complete() is used in dma_async_memcpy_complete()
+ * the test logic is seperated for lightweight testing of multiple cookies
+ */
+static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie,
+			dma_cookie_t last_complete, dma_cookie_t last_used)
+{
+	if (last_complete <= last_used) {
+		if ((cookie <= last_complete) || (cookie > last_used))
+			return DMA_SUCCESS;
+	} else {
+		if ((cookie <= last_complete) && (cookie > last_used))
+			return DMA_SUCCESS;
+	}
+	return DMA_IN_PROGRESS;
+}
+
+
+/* --- DMA device --- */
+
+int dma_async_device_register(struct dma_device *device);
+void dma_async_device_unregister(struct dma_device *device);
+
+/* --- Helper iov-locking functions --- */
+
+struct dma_page_list {
+	char *base_address;
+	int nr_pages;
+	struct page **pages;
+};
+
+struct dma_pinned_list {
+	int nr_iovecs;
+	struct dma_page_list page_list[0];
+};
+
+struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len);
+void dma_unpin_iovec_pages(struct dma_pinned_list* pinned_list);
+
+dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov,
+	struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len);
+dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov,
+	struct dma_pinned_list *pinned_list, struct page *page,
+	unsigned int offset, size_t len);
+
+#endif /* CONFIG_DMA_ENGINE */
+#endif /* DMAENGINE_H */
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 64fd6c3..b2cd207 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -2,7 +2,6 @@
 #define __DMI_H__
 
 #include <linux/list.h>
-#include <linux/config.h>
 
 enum dmi_field {
 	DMI_NONE,
diff --git a/include/linux/dnotify.h b/include/linux/dnotify.h
index f134a01..102a902 100644
--- a/include/linux/dnotify.h
+++ b/include/linux/dnotify.h
@@ -18,7 +18,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_DNOTIFY
 
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index 2787b8a..c6a2353 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -88,20 +88,6 @@
 #define DMX_PES_PCR      DMX_PES_PCR0
 
 
-typedef enum
-{
-	DMX_SCRAMBLING_EV,
-	DMX_FRONTEND_EV
-} dmx_event_t;
-
-
-typedef enum
-{
-	DMX_SCRAMBLING_OFF,
-	DMX_SCRAMBLING_ON
-} dmx_scrambling_status_t;
-
-
 typedef struct dmx_filter
 {
 	__u8  filter[DMX_FILTER_SIZE];
@@ -132,17 +118,6 @@
 	__u32          flags;
 };
 
-
-struct dmx_event
-{
-	dmx_event_t         event;
-	time_t              timeStamp;
-	union
-	{
-		dmx_scrambling_status_t scrambling;
-	} u;
-};
-
 typedef struct dmx_caps {
 	__u32 caps;
 	int num_decoders;
@@ -171,7 +146,6 @@
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
 #define DMX_SET_PES_FILTER       _IOW('o', 44, struct dmx_pes_filter_params)
 #define DMX_SET_BUFFER_SIZE      _IO('o', 45)
-#define DMX_GET_EVENT            _IOR('o', 46, struct dmx_event)
 #define DMX_GET_PES_PIDS         _IOR('o', 47, __u16[5])
 #define DMX_GET_CAPS             _IOR('o', 48, dmx_caps_t)
 #define DMX_SET_SOURCE           _IOW('o', 49, dmx_source_t)
diff --git a/include/linux/efi.h b/include/linux/efi.h
index e203613..66d621d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -294,6 +294,7 @@
 extern u64 efi_get_iobase (void);
 extern u32 efi_mem_type (unsigned long phys_addr);
 extern u64 efi_mem_attributes (unsigned long phys_addr);
+extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size);
 extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size,
 				    u64 attr);
 extern int __init efi_uart_console_only (void);
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index fbfa6b5..278ef44 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -38,7 +38,7 @@
 
 extern struct inode_operations efs_dir_inode_operations;
 extern const struct file_operations efs_dir_operations;
-extern struct address_space_operations efs_symlink_aops;
+extern const struct address_space_operations efs_symlink_aops;
 
 extern void efs_read_inode(struct inode *);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
diff --git a/include/linux/elf-em.h b/include/linux/elf-em.h
new file mode 100644
index 0000000..114a96d
--- /dev/null
+++ b/include/linux/elf-em.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_ELF_EM_H
+#define _LINUX_ELF_EM_H
+
+/* These constants define the various ELF target machines */
+#define EM_NONE		0
+#define EM_M32		1
+#define EM_SPARC	2
+#define EM_386		3
+#define EM_68K		4
+#define EM_88K		5
+#define EM_486		6	/* Perhaps disused */
+#define EM_860		7
+#define EM_MIPS		8	/* MIPS R3000 (officially, big-endian only) */
+#define EM_MIPS_RS4_BE	10	/* MIPS R4000 big-endian */
+#define EM_PARISC	15	/* HPPA */
+#define EM_SPARC32PLUS	18	/* Sun's "v8plus" */
+#define EM_PPC		20	/* PowerPC */
+#define EM_PPC64	21       /* PowerPC64 */
+#define EM_SH		42	/* SuperH */
+#define EM_SPARCV9	43	/* SPARC v9 64-bit */
+#define EM_IA_64	50	/* HP/Intel IA-64 */
+#define EM_X86_64	62	/* AMD x86-64 */
+#define EM_S390		22	/* IBM S/390 */
+#define EM_CRIS		76	/* Axis Communications 32-bit embedded processor */
+#define EM_V850		87	/* NEC v850 */
+#define EM_M32R		88	/* Renesas M32R */
+#define EM_H8_300	46	/* Renesas H8/300,300H,H8S */
+#define EM_FRV		0x5441	/* Fujitsu FR-V */
+
+/*
+ * This is an interim value that we will use until the committee comes
+ * up with a final number.
+ */
+#define EM_ALPHA	0x9026
+
+/* Bogus old v850 magic number, used by old tools. */
+#define EM_CYGNUS_V850	0x9080
+/* Bogus old m32r magic number, used by old tools. */
+#define EM_CYGNUS_M32R	0x9041
+/* This is the old interim value for S/390 architecture */
+#define EM_S390_OLD	0xA390
+
+
+#endif /* _LINUX_ELF_EM_H */
diff --git a/include/linux/elf.h b/include/linux/elf.h
index d3bfacb..b70d1d2 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/auxvec.h>
+#include <linux/elf-em.h>
 #include <asm/elf.h>
 
 #ifndef elf_read_implies_exec
@@ -55,64 +56,6 @@
 #define ET_LOPROC 0xff00
 #define ET_HIPROC 0xffff
 
-/* These constants define the various ELF target machines */
-#define EM_NONE  0
-#define EM_M32   1
-#define EM_SPARC 2
-#define EM_386   3
-#define EM_68K   4
-#define EM_88K   5
-#define EM_486   6   /* Perhaps disused */
-#define EM_860   7
-
-#define EM_MIPS		8	/* MIPS R3000 (officially, big-endian only) */
-
-#define EM_MIPS_RS4_BE 10	/* MIPS R4000 big-endian */
-
-#define EM_PARISC      15	/* HPPA */
-
-#define EM_SPARC32PLUS 18	/* Sun's "v8plus" */
-
-#define EM_PPC	       20	/* PowerPC */
-#define EM_PPC64       21       /* PowerPC64 */
-
-#define EM_SH	       42	/* SuperH */
-
-#define EM_SPARCV9     43	/* SPARC v9 64-bit */
-
-#define EM_IA_64	50	/* HP/Intel IA-64 */
-
-#define EM_X86_64	62	/* AMD x86-64 */
-
-#define EM_S390		22	/* IBM S/390 */
-
-#define EM_CRIS         76      /* Axis Communications 32-bit embedded processor */
-
-#define EM_V850		87	/* NEC v850 */
-
-#define EM_M32R		88	/* Renesas M32R */
-
-#define EM_H8_300       46      /* Renesas H8/300,300H,H8S */
-
-/*
- * This is an interim value that we will use until the committee comes
- * up with a final number.
- */
-#define EM_ALPHA	0x9026
-
-/* Bogus old v850 magic number, used by old tools.  */
-#define EM_CYGNUS_V850	0x9080
-
-/* Bogus old m32r magic number, used by old tools.  */
-#define EM_CYGNUS_M32R	0x9041
-
-/*
- * This is the old interim value for S/390 architecture
- */
-#define EM_S390_OLD     0xA390
-
-#define EM_FRV		0x5441		/* Fujitsu FR-V */
-
 /* This is the info that is needed to parse the dynamic section of the file */
 #define DT_NULL		0
 #define DT_NEEDED	1
diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h
index 174582f..408118a 100644
--- a/include/linux/errqueue.h
+++ b/include/linux/errqueue.h
@@ -21,7 +21,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <net/ip.h>
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/ipv6.h>
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 93535f0..c6310ae 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -15,24 +15,24 @@
 
 /* This should work for both 32 and 64 bit userland. */
 struct ethtool_cmd {
-	u32	cmd;
-	u32	supported;	/* Features this interface supports */
-	u32	advertising;	/* Features this interface advertises */
-	u16	speed;		/* The forced speed, 10Mb, 100Mb, gigabit */
-	u8	duplex;		/* Duplex, half or full */
-	u8	port;		/* Which connector port */
-	u8	phy_address;
-	u8	transceiver;	/* Which transceiver to use */
-	u8	autoneg;	/* Enable or disable autonegotiation */
-	u32	maxtxpkt;	/* Tx pkts before generating tx int */
-	u32	maxrxpkt;	/* Rx pkts before generating rx int */
-	u32	reserved[4];
+	__u32	cmd;
+	__u32	supported;	/* Features this interface supports */
+	__u32	advertising;	/* Features this interface advertises */
+	__u16	speed;		/* The forced speed, 10Mb, 100Mb, gigabit */
+	__u8	duplex;		/* Duplex, half or full */
+	__u8	port;		/* Which connector port */
+	__u8	phy_address;
+	__u8	transceiver;	/* Which transceiver to use */
+	__u8	autoneg;	/* Enable or disable autonegotiation */
+	__u32	maxtxpkt;	/* Tx pkts before generating tx int */
+	__u32	maxrxpkt;	/* Rx pkts before generating rx int */
+	__u32	reserved[4];
 };
 
 #define ETHTOOL_BUSINFO_LEN	32
 /* these strings are set to whatever the driver author decides... */
 struct ethtool_drvinfo {
-	u32	cmd;
+	__u32	cmd;
 	char	driver[32];	/* driver short name, "tulip", "eepro100" */
 	char	version[32];	/* driver version string */
 	char	fw_version[32];	/* firmware version string, if applicable */
@@ -40,53 +40,53 @@
 				/* For PCI devices, use pci_name(pci_dev). */
 	char	reserved1[32];
 	char	reserved2[16];
-	u32	n_stats;	/* number of u64's from ETHTOOL_GSTATS */
-	u32	testinfo_len;
-	u32	eedump_len;	/* Size of data from ETHTOOL_GEEPROM (bytes) */
-	u32	regdump_len;	/* Size of data from ETHTOOL_GREGS (bytes) */
+	__u32	n_stats;	/* number of u64's from ETHTOOL_GSTATS */
+	__u32	testinfo_len;
+	__u32	eedump_len;	/* Size of data from ETHTOOL_GEEPROM (bytes) */
+	__u32	regdump_len;	/* Size of data from ETHTOOL_GREGS (bytes) */
 };
 
 #define SOPASS_MAX	6
 /* wake-on-lan settings */
 struct ethtool_wolinfo {
-	u32	cmd;
-	u32	supported;
-	u32	wolopts;
-	u8	sopass[SOPASS_MAX]; /* SecureOn(tm) password */
+	__u32	cmd;
+	__u32	supported;
+	__u32	wolopts;
+	__u8	sopass[SOPASS_MAX]; /* SecureOn(tm) password */
 };
 
 /* for passing single values */
 struct ethtool_value {
-	u32	cmd;
-	u32	data;
+	__u32	cmd;
+	__u32	data;
 };
 
 /* for passing big chunks of data */
 struct ethtool_regs {
-	u32	cmd;
-	u32	version; /* driver-specific, indicates different chips/revs */
-	u32	len; /* bytes */
-	u8	data[0];
+	__u32	cmd;
+	__u32	version; /* driver-specific, indicates different chips/revs */
+	__u32	len; /* bytes */
+	__u8	data[0];
 };
 
 /* for passing EEPROM chunks */
 struct ethtool_eeprom {
-	u32	cmd;
-	u32	magic;
-	u32	offset; /* in bytes */
-	u32	len; /* in bytes */
-	u8	data[0];
+	__u32	cmd;
+	__u32	magic;
+	__u32	offset; /* in bytes */
+	__u32	len; /* in bytes */
+	__u8	data[0];
 };
 
 /* for configuring coalescing parameters of chip */
 struct ethtool_coalesce {
-	u32	cmd;	/* ETHTOOL_{G,S}COALESCE */
+	__u32	cmd;	/* ETHTOOL_{G,S}COALESCE */
 
 	/* How many usecs to delay an RX interrupt after
 	 * a packet arrives.  If 0, only rx_max_coalesced_frames
 	 * is used.
 	 */
-	u32	rx_coalesce_usecs;
+	__u32	rx_coalesce_usecs;
 
 	/* How many packets to delay an RX interrupt after
 	 * a packet arrives.  If 0, only rx_coalesce_usecs is
@@ -94,21 +94,21 @@
 	 * to zero as this would cause RX interrupts to never be
 	 * generated.
 	 */
-	u32	rx_max_coalesced_frames;
+	__u32	rx_max_coalesced_frames;
 
 	/* Same as above two parameters, except that these values
 	 * apply while an IRQ is being serviced by the host.  Not
 	 * all cards support this feature and the values are ignored
 	 * in that case.
 	 */
-	u32	rx_coalesce_usecs_irq;
-	u32	rx_max_coalesced_frames_irq;
+	__u32	rx_coalesce_usecs_irq;
+	__u32	rx_max_coalesced_frames_irq;
 
 	/* How many usecs to delay a TX interrupt after
 	 * a packet is sent.  If 0, only tx_max_coalesced_frames
 	 * is used.
 	 */
-	u32	tx_coalesce_usecs;
+	__u32	tx_coalesce_usecs;
 
 	/* How many packets to delay a TX interrupt after
 	 * a packet is sent.  If 0, only tx_coalesce_usecs is
@@ -116,22 +116,22 @@
 	 * to zero as this would cause TX interrupts to never be
 	 * generated.
 	 */
-	u32	tx_max_coalesced_frames;
+	__u32	tx_max_coalesced_frames;
 
 	/* Same as above two parameters, except that these values
 	 * apply while an IRQ is being serviced by the host.  Not
 	 * all cards support this feature and the values are ignored
 	 * in that case.
 	 */
-	u32	tx_coalesce_usecs_irq;
-	u32	tx_max_coalesced_frames_irq;
+	__u32	tx_coalesce_usecs_irq;
+	__u32	tx_max_coalesced_frames_irq;
 
 	/* How many usecs to delay in-memory statistics
 	 * block updates.  Some drivers do not have an in-memory
 	 * statistic block, and in such cases this value is ignored.
 	 * This value must not be zero.
 	 */
-	u32	stats_block_coalesce_usecs;
+	__u32	stats_block_coalesce_usecs;
 
 	/* Adaptive RX/TX coalescing is an algorithm implemented by
 	 * some drivers to improve latency under low packet rates and
@@ -140,18 +140,18 @@
 	 * not implemented by the driver causes these values to be
 	 * silently ignored.
 	 */
-	u32	use_adaptive_rx_coalesce;
-	u32	use_adaptive_tx_coalesce;
+	__u32	use_adaptive_rx_coalesce;
+	__u32	use_adaptive_tx_coalesce;
 
 	/* When the packet rate (measured in packets per second)
 	 * is below pkt_rate_low, the {rx,tx}_*_low parameters are
 	 * used.
 	 */
-	u32	pkt_rate_low;
-	u32	rx_coalesce_usecs_low;
-	u32	rx_max_coalesced_frames_low;
-	u32	tx_coalesce_usecs_low;
-	u32	tx_max_coalesced_frames_low;
+	__u32	pkt_rate_low;
+	__u32	rx_coalesce_usecs_low;
+	__u32	rx_max_coalesced_frames_low;
+	__u32	tx_coalesce_usecs_low;
+	__u32	tx_max_coalesced_frames_low;
 
 	/* When the packet rate is below pkt_rate_high but above
 	 * pkt_rate_low (both measured in packets per second) the
@@ -162,43 +162,43 @@
 	 * is above pkt_rate_high, the {rx,tx}_*_high parameters are
 	 * used.
 	 */
-	u32	pkt_rate_high;
-	u32	rx_coalesce_usecs_high;
-	u32	rx_max_coalesced_frames_high;
-	u32	tx_coalesce_usecs_high;
-	u32	tx_max_coalesced_frames_high;
+	__u32	pkt_rate_high;
+	__u32	rx_coalesce_usecs_high;
+	__u32	rx_max_coalesced_frames_high;
+	__u32	tx_coalesce_usecs_high;
+	__u32	tx_max_coalesced_frames_high;
 
 	/* How often to do adaptive coalescing packet rate sampling,
 	 * measured in seconds.  Must not be zero.
 	 */
-	u32	rate_sample_interval;
+	__u32	rate_sample_interval;
 };
 
 /* for configuring RX/TX ring parameters */
 struct ethtool_ringparam {
-	u32	cmd;	/* ETHTOOL_{G,S}RINGPARAM */
+	__u32	cmd;	/* ETHTOOL_{G,S}RINGPARAM */
 
 	/* Read only attributes.  These indicate the maximum number
 	 * of pending RX/TX ring entries the driver will allow the
 	 * user to set.
 	 */
-	u32	rx_max_pending;
-	u32	rx_mini_max_pending;
-	u32	rx_jumbo_max_pending;
-	u32	tx_max_pending;
+	__u32	rx_max_pending;
+	__u32	rx_mini_max_pending;
+	__u32	rx_jumbo_max_pending;
+	__u32	tx_max_pending;
 
 	/* Values changeable by the user.  The valid values are
 	 * in the range 1 to the "*_max_pending" counterpart above.
 	 */
-	u32	rx_pending;
-	u32	rx_mini_pending;
-	u32	rx_jumbo_pending;
-	u32	tx_pending;
+	__u32	rx_pending;
+	__u32	rx_mini_pending;
+	__u32	rx_jumbo_pending;
+	__u32	tx_pending;
 };
 
 /* for configuring link flow control parameters */
 struct ethtool_pauseparam {
-	u32	cmd;	/* ETHTOOL_{G,S}PAUSEPARAM */
+	__u32	cmd;	/* ETHTOOL_{G,S}PAUSEPARAM */
 
 	/* If the link is being auto-negotiated (via ethtool_cmd.autoneg
 	 * being true) the user may set 'autonet' here non-zero to have the
@@ -210,9 +210,9 @@
 	 * then {rx,tx}_pause force the driver to use/not-use pause
 	 * flow control.
 	 */
-	u32	autoneg;
-	u32	rx_pause;
-	u32	tx_pause;
+	__u32	autoneg;
+	__u32	rx_pause;
+	__u32	tx_pause;
 };
 
 #define ETH_GSTRING_LEN		32
@@ -223,10 +223,10 @@
 
 /* for passing string sets for data tagging */
 struct ethtool_gstrings {
-	u32	cmd;		/* ETHTOOL_GSTRINGS */
-	u32	string_set;	/* string set id e.c. ETH_SS_TEST, etc*/
-	u32	len;		/* number of strings in the string set */
-	u8	data[0];
+	__u32	cmd;		/* ETHTOOL_GSTRINGS */
+	__u32	string_set;	/* string set id e.c. ETH_SS_TEST, etc*/
+	__u32	len;		/* number of strings in the string set */
+	__u8	data[0];
 };
 
 enum ethtool_test_flags {
@@ -236,26 +236,28 @@
 
 /* for requesting NIC test and getting results*/
 struct ethtool_test {
-	u32	cmd;		/* ETHTOOL_TEST */
-	u32	flags;		/* ETH_TEST_FL_xxx */
-	u32	reserved;
-	u32	len;		/* result length, in number of u64 elements */
-	u64	data[0];
+	__u32	cmd;		/* ETHTOOL_TEST */
+	__u32	flags;		/* ETH_TEST_FL_xxx */
+	__u32	reserved;
+	__u32	len;		/* result length, in number of u64 elements */
+	__u64	data[0];
 };
 
 /* for dumping NIC-specific statistics */
 struct ethtool_stats {
-	u32	cmd;		/* ETHTOOL_GSTATS */
-	u32	n_stats;	/* number of u64's being returned */
-	u64	data[0];
+	__u32	cmd;		/* ETHTOOL_GSTATS */
+	__u32	n_stats;	/* number of u64's being returned */
+	__u64	data[0];
 };
 
 struct ethtool_perm_addr {
-	u32	cmd;		/* ETHTOOL_GPERMADDR */
-	u32	size;
-	u8	data[0];
+	__u32	cmd;		/* ETHTOOL_GPERMADDR */
+	__u32	size;
+	__u8	data[0];
 };
 
+#ifdef __KERNEL__
+
 struct net_device;
 
 /* Some generic methods drivers may use in their ethtool_ops */
@@ -371,6 +373,7 @@
 	u32     (*get_ufo)(struct net_device *);
 	int     (*set_ufo)(struct net_device *, u32);
 };
+#endif /* __KERNEL__ */
 
 /* CMDs currently supported */
 #define ETHTOOL_GSET		0x00000001 /* Get settings. */
@@ -408,6 +411,8 @@
 #define ETHTOOL_GPERMADDR	0x00000020 /* Get permanent hardware address */
 #define ETHTOOL_GUFO		0x00000021 /* Get UFO enable (ethtool_value) */
 #define ETHTOOL_SUFO		0x00000022 /* Set UFO enable (ethtool_value) */
+#define ETHTOOL_GGSO		0x00000023 /* Get GSO enable (ethtool_value) */
+#define ETHTOOL_SGSO		0x00000024 /* Set GSO enable (ethtool_value) */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index 1e4bdfc..84cfa8b 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -1,6 +1,6 @@
 /*
  *  include/linux/eventpoll.h ( Efficent event polling implementation )
- *  Copyright (C) 2001,...,2003	 Davide Libenzi
+ *  Copyright (C) 2001,...,2006	 Davide Libenzi
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index f7bd1c7..facf34e 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -17,7 +17,6 @@
 #define _LINUX_EXT2_FS_H
 
 #include <linux/types.h>
-#include <linux/ext2_fs_sb.h>
 
 /*
  * The second extended filesystem constants/structures
@@ -70,6 +69,7 @@
 #define EXT2_SUPER_MAGIC	0xEF53
 
 #ifdef __KERNEL__
+#include <linux/ext2_fs_sb.h>
 static inline struct ext2_sb_info *EXT2_SB(struct super_block *sb)
 {
 	return sb->s_fs_info;
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 3ade6a4..5607e64 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -17,11 +17,6 @@
 #define _LINUX_EXT3_FS_H
 
 #include <linux/types.h>
-#include <linux/ext3_fs_i.h>
-#include <linux/ext3_fs_sb.h>
-
-
-struct statfs;
 
 /*
  * The second extended filesystem constants/structures
@@ -487,6 +482,8 @@
 };
 
 #ifdef __KERNEL__
+#include <linux/ext3_fs_i.h>
+#include <linux/ext3_fs_sb.h>
 static inline struct ext3_sb_info * EXT3_SB(struct super_block *sb)
 {
 	return sb->s_fs_info;
@@ -664,6 +661,8 @@
 #define DX_HASH_HALF_MD4	1
 #define DX_HASH_TEA		2
 
+#ifdef __KERNEL__
+
 /* hash info structure used by the directory hash */
 struct dx_hash_info
 {
@@ -675,7 +674,6 @@
 
 #define EXT3_HTREE_EOF	0x7fffffff
 
-#ifdef __KERNEL__
 /*
  * Control parameters used by ext3_htree_next_block
  */
@@ -712,6 +710,14 @@
 	__u32		next_hash;
 };
 
+/* calculate the first block number of the group */
+static inline ext3_fsblk_t
+ext3_group_first_block_no(struct super_block *sb, unsigned long group_no)
+{
+	return group_no * (ext3_fsblk_t)EXT3_BLOCKS_PER_GROUP(sb) +
+		le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block);
+}
+
 /*
  * Special error return code only used by dx_probe() and its callers.
  */
@@ -732,14 +738,16 @@
 /* balloc.c */
 extern int ext3_bg_has_super(struct super_block *sb, int group);
 extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
-extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
-extern int ext3_new_blocks (handle_t *, struct inode *, unsigned long,
-			unsigned long *, int *);
-extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
-			      unsigned long);
-extern void ext3_free_blocks_sb (handle_t *, struct super_block *,
-				 unsigned long, unsigned long, int *);
-extern unsigned long ext3_count_free_blocks (struct super_block *);
+extern ext3_fsblk_t ext3_new_block (handle_t *handle, struct inode *inode,
+			ext3_fsblk_t goal, int *errp);
+extern ext3_fsblk_t ext3_new_blocks (handle_t *handle, struct inode *inode,
+			ext3_fsblk_t goal, unsigned long *count, int *errp);
+extern void ext3_free_blocks (handle_t *handle, struct inode *inode,
+			ext3_fsblk_t block, unsigned long count);
+extern void ext3_free_blocks_sb (handle_t *handle, struct super_block *sb,
+				 ext3_fsblk_t block, unsigned long count,
+				unsigned long *pdquot_freed_blocks);
+extern ext3_fsblk_t ext3_count_free_blocks (struct super_block *);
 extern void ext3_check_blocks_bitmap (struct super_block *);
 extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
 						    unsigned int block_group,
@@ -775,7 +783,8 @@
 
 
 /* inode.c */
-int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
+int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
+		struct buffer_head *bh, ext3_fsblk_t blocknr);
 struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
 struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
 int ext3_get_blocks_handle(handle_t *handle, struct inode *inode,
@@ -810,7 +819,7 @@
 				struct ext3_new_group_data *input);
 extern int ext3_group_extend(struct super_block *sb,
 				struct ext3_super_block *es,
-				unsigned long n_blocks_count);
+				ext3_fsblk_t n_blocks_count);
 
 /* super.c */
 extern void ext3_error (struct super_block *, const char *, const char *, ...)
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
index 7abf901..2f18b95 100644
--- a/include/linux/ext3_fs_i.h
+++ b/include/linux/ext3_fs_i.h
@@ -21,9 +21,17 @@
 #include <linux/seqlock.h>
 #include <linux/mutex.h>
 
+/* data type for block offset of block group */
+typedef int ext3_grpblk_t;
+
+/* data type for filesystem-wide blocks number */
+typedef unsigned long ext3_fsblk_t;
+
+#define E3FSBLK "%lu"
+
 struct ext3_reserve_window {
-	__u32			_rsv_start;	/* First byte reserved */
-	__u32			_rsv_end;	/* Last byte reserved or 0 */
+	ext3_fsblk_t	_rsv_start;	/* First byte reserved */
+	ext3_fsblk_t	_rsv_end;	/* Last byte reserved or 0 */
 };
 
 struct ext3_reserve_window_node {
@@ -50,7 +58,7 @@
 	 * allocated to this file.  This give us the goal (target) for the next
 	 * allocation when we detect linearly ascending requests.
 	 */
-	__u32                   last_alloc_physical_block;
+	ext3_fsblk_t		last_alloc_physical_block;
 };
 
 #define rsv_start rsv_window._rsv_start
@@ -67,7 +75,7 @@
 	__u8	i_frag_no;
 	__u8	i_frag_size;
 #endif
-	__u32	i_file_acl;
+	ext3_fsblk_t	i_file_acl;
 	__u32	i_dir_acl;
 	__u32	i_dtime;
 
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 315d897..07a08e9 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1,6 +1,7 @@
 #ifndef _LINUX_FB_H
 #define _LINUX_FB_H
 
+#include <linux/backlight.h>
 #include <asm/types.h>
 
 /* Definitions of frame buffers						*/
@@ -366,6 +367,12 @@
 	struct fb_image	image;	/* Cursor image */
 };
 
+#ifdef CONFIG_FB_BACKLIGHT
+/* Settings for the generic backlight code */
+#define FB_BACKLIGHT_LEVELS	128
+#define FB_BACKLIGHT_MAX	0xFF
+#endif
+
 #ifdef __KERNEL__
 
 #include <linux/fs.h>
@@ -497,23 +504,19 @@
 #define FB_EVENT_MODE_DELETE            0x04
 /*      A driver registered itself */
 #define FB_EVENT_FB_REGISTERED          0x05
+/*      A driver unregistered itself */
+#define FB_EVENT_FB_UNREGISTERED        0x06
 /*      CONSOLE-SPECIFIC: get console to framebuffer mapping */
-#define FB_EVENT_GET_CONSOLE_MAP        0x06
+#define FB_EVENT_GET_CONSOLE_MAP        0x07
 /*      CONSOLE-SPECIFIC: set console to framebuffer mapping */
-#define FB_EVENT_SET_CONSOLE_MAP        0x07
+#define FB_EVENT_SET_CONSOLE_MAP        0x08
 /*      A display blank is requested       */
-#define FB_EVENT_BLANK                  0x08
+#define FB_EVENT_BLANK                  0x09
 /*      Private modelist is to be replaced */
-#define FB_EVENT_NEW_MODELIST           0x09
+#define FB_EVENT_NEW_MODELIST           0x0A
 /*	The resolution of the passed in fb_info about to change and
         all vc's should be changed         */
-#define FB_EVENT_MODE_CHANGE_ALL	0x0A
-/*      CONSOLE-SPECIFIC: set console rotation */
-#define FB_EVENT_SET_CON_ROTATE         0x0B
-/*      CONSOLE-SPECIFIC: get console rotation */
-#define FB_EVENT_GET_CON_ROTATE         0x0C
-/*      CONSOLE-SPECIFIC: rotate all consoles */
-#define FB_EVENT_SET_CON_ROTATE_ALL     0x0D
+#define FB_EVENT_MODE_CHANGE_ALL	0x0B
 
 struct fb_event {
 	struct fb_info *info;
@@ -756,6 +759,21 @@
 	struct fb_cmap cmap;		/* Current cmap */
 	struct list_head modelist;      /* mode list */
 	struct fb_videomode *mode;	/* current mode */
+
+#ifdef CONFIG_FB_BACKLIGHT
+	/* Lock ordering:
+	 * bl_mutex (protects bl_dev and bl_curve)
+	 *   bl_dev->sem (backlight class)
+	 */
+	struct mutex bl_mutex;
+
+	/* assigned backlight device */
+	struct backlight_device *bl_dev;
+
+	/* Backlight level curve */
+	u8 bl_curve[FB_BACKLIGHT_LEVELS];
+#endif
+
 	struct fb_ops *fbops;
 	struct device *device;
 	struct class_device *class_device; /* sysfs per device attrs */
@@ -870,7 +888,6 @@
 			      struct fb_fix_screeninfo *fix);
 extern int fb_get_options(char *name, char **option);
 extern int fb_new_modelist(struct fb_info *info);
-extern int fb_con_duit(struct fb_info *info, int event, void *data);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
@@ -895,6 +912,7 @@
 extern void framebuffer_release(struct fb_info *info);
 extern int fb_init_class_device(struct fb_info *fb_info);
 extern void fb_cleanup_class_device(struct fb_info *head);
+extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max);
 
 /* drivers/video/fbmon.c */
 #define FB_MAXTIMINGS		0
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index c52a637..996f561 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -29,6 +29,7 @@
 #define AT_SYMLINK_NOFOLLOW	0x100   /* Do not follow symbolic links.  */
 #define AT_REMOVEDIR		0x200   /* Remove directory instead of
                                            unlinking file.  */
+#define AT_SYMLINK_FOLLOW	0x400   /* Follow symbolic links.  */
 
 #ifdef __KERNEL__
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f813bc8..e04a5cfe 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -6,7 +6,6 @@
  * structures etc.
  */
 
-#include <linux/config.h>
 #include <linux/limits.h>
 #include <linux/ioctl.h>
 
@@ -377,7 +376,8 @@
 	struct page* (*get_xip_page)(struct address_space *, sector_t,
 			int);
 	/* migrate the contents of a page to the specified target */
-	int (*migratepage) (struct page *, struct page *);
+	int (*migratepage) (struct address_space *,
+			struct page *, struct page *);
 };
 
 struct backing_dev_info;
@@ -392,7 +392,7 @@
 	unsigned int		truncate_count;	/* Cover race condition with truncate */
 	unsigned long		nrpages;	/* number of total pages */
 	pgoff_t			writeback_index;/* writeback starts here */
-	struct address_space_operations *a_ops;	/* methods */
+	const struct address_space_operations *a_ops;	/* methods */
 	unsigned long		flags;		/* error bits/gfp mask */
 	struct backing_dev_info *backing_dev_info; /* device readahead, etc */
 	spinlock_t		private_lock;	/* for use by the address_space */
@@ -683,6 +683,7 @@
 #define FL_FLOCK	2
 #define FL_ACCESS	8	/* not trying to lock, just looking */
 #define FL_LEASE	32	/* lease held on this file */
+#define FL_CLOSE	64	/* unlock on close */
 #define FL_SLEEP	128	/* A blocking lock */
 
 /*
@@ -775,7 +776,6 @@
 extern int posix_lock_file(struct file *, struct file_lock *);
 extern int posix_lock_file_wait(struct file *, struct file_lock *);
 extern int posix_unblock_lock(struct file *, struct file_lock *);
-extern int posix_locks_deadlock(struct file_lock *, struct file_lock *);
 extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl);
 extern int __break_lease(struct inode *inode, unsigned int flags);
 extern void lease_get_mtime(struct inode *, struct timespec *time);
@@ -783,7 +783,6 @@
 extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
-extern void steal_locks(fl_owner_t from);
 
 struct fasync_struct {
 	int	magic;
@@ -1026,7 +1025,7 @@
 	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
 	int (*mmap) (struct file *, struct vm_area_struct *);
 	int (*open) (struct inode *, struct file *);
-	int (*flush) (struct file *);
+	int (*flush) (struct file *, fl_owner_t id);
 	int (*release) (struct inode *, struct file *);
 	int (*fsync) (struct file *, struct dentry *, int datasync);
 	int (*aio_fsync) (struct kiocb *, int datasync);
@@ -1098,10 +1097,10 @@
 	int (*sync_fs)(struct super_block *sb, int wait);
 	void (*write_super_lockfs) (struct super_block *);
 	void (*unlockfs) (struct super_block *);
-	int (*statfs) (struct super_block *, struct kstatfs *);
+	int (*statfs) (struct dentry *, struct kstatfs *);
 	int (*remount_fs) (struct super_block *, int *, char *);
 	void (*clear_inode) (struct inode *);
-	void (*umount_begin) (struct super_block *);
+	void (*umount_begin) (struct vfsmount *, int);
 
 	int (*show_options)(struct seq_file *, struct vfsmount *);
 	int (*show_stats)(struct seq_file *, struct vfsmount *);
@@ -1271,23 +1270,26 @@
 struct file_system_type {
 	const char *name;
 	int fs_flags;
-	struct super_block *(*get_sb) (struct file_system_type *, int,
-				       const char *, void *);
+	int (*get_sb) (struct file_system_type *, int,
+		       const char *, void *, struct vfsmount *);
 	void (*kill_sb) (struct super_block *);
 	struct module *owner;
 	struct file_system_type * next;
 	struct list_head fs_supers;
 };
 
-struct super_block *get_sb_bdev(struct file_system_type *fs_type,
+extern int get_sb_bdev(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data,
-	int (*fill_super)(struct super_block *, void *, int));
-struct super_block *get_sb_single(struct file_system_type *fs_type,
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt);
+extern int get_sb_single(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int));
-struct super_block *get_sb_nodev(struct file_system_type *fs_type,
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt);
+extern int get_sb_nodev(struct file_system_type *fs_type,
 	int flags, void *data,
-	int (*fill_super)(struct super_block *, void *, int));
+	int (*fill_super)(struct super_block *, void *, int),
+	struct vfsmount *mnt);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);
@@ -1298,8 +1300,10 @@
 			int (*test)(struct super_block *,void *),
 			int (*set)(struct super_block *,void *),
 			void *data);
-struct super_block *get_sb_pseudo(struct file_system_type *, char *,
-			struct super_operations *ops, unsigned long);
+extern int get_sb_pseudo(struct file_system_type *, char *,
+	struct super_operations *ops, unsigned long,
+	struct vfsmount *mnt);
+extern int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb);
 int __put_super(struct super_block *sb);
 int __put_super_and_need_restart(struct super_block *sb);
 void unnamed_dev_init(void);
@@ -1322,7 +1326,7 @@
 extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
 				  struct vfsmount *);
 
-extern int vfs_statfs(struct super_block *, struct kstatfs *);
+extern int vfs_statfs(struct dentry *, struct kstatfs *);
 
 /* /sys/fs */
 extern struct subsystem fs_subsys;
@@ -1401,7 +1405,7 @@
 extern void bdput(struct block_device *);
 extern struct block_device *open_by_devnum(dev_t, unsigned);
 extern const struct file_operations def_blk_fops;
-extern struct address_space_operations def_blk_aops;
+extern const struct address_space_operations def_blk_aops;
 extern const struct file_operations def_chr_fops;
 extern const struct file_operations bad_sock_fops;
 extern const struct file_operations def_fifo_fops;
@@ -1743,7 +1747,7 @@
 extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
 extern int dcache_readdir(struct file *, void *, filldir_t);
 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int simple_statfs(struct super_block *, struct kstatfs *);
+extern int simple_statfs(struct dentry *, struct kstatfs *);
 extern int simple_link(struct dentry *, struct inode *, struct dentry *);
 extern int simple_unlink(struct inode *, struct dentry *);
 extern int simple_rmdir(struct inode *, struct dentry *);
@@ -1763,13 +1767,14 @@
 struct tree_descr { char *name; const struct file_operations *ops; int mode; };
 struct dentry *d_alloc_name(struct dentry *, const char *);
 extern int simple_fill_super(struct super_block *, int, struct tree_descr *);
-extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count);
+extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
 extern void simple_release_fs(struct vfsmount **mount, int *count);
 
 extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t);
 
 #ifdef CONFIG_MIGRATION
-extern int buffer_migrate_page(struct page *, struct page *);
+extern int buffer_migrate_page(struct address_space *,
+				struct page *, struct page *);
 #else
 #define buffer_migrate_page NULL
 #endif
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 11438ef..cc5dec7 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -54,19 +54,20 @@
 
 	if (isdir)
 		isdir = IN_ISDIR;
-	inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name);
-	inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name);
+	inotify_inode_queue_event(old_dir, IN_MOVED_FROM|isdir,cookie,old_name,
+				  source);
+	inotify_inode_queue_event(new_dir, IN_MOVED_TO|isdir, cookie, new_name,
+				  source);
 
 	if (target) {
-		inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL);
+		inotify_inode_queue_event(target, IN_DELETE_SELF, 0, NULL, NULL);
 		inotify_inode_is_dead(target);
 	}
 
 	if (source) {
-		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
+		inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL, NULL);
 	}
-	audit_inode_child(old_name, source, old_dir->i_ino);
-	audit_inode_child(new_name, target, new_dir->i_ino);
+	audit_inode_child(new_name, source, new_dir->i_ino);
 }
 
 /*
@@ -85,7 +86,7 @@
  */
 static inline void fsnotify_inoderemove(struct inode *inode)
 {
-	inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL);
+	inotify_inode_queue_event(inode, IN_DELETE_SELF, 0, NULL, NULL);
 	inotify_inode_is_dead(inode);
 }
 
@@ -95,7 +96,8 @@
 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 {
 	inode_dir_notify(inode, DN_CREATE);
-	inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name);
+	inotify_inode_queue_event(inode, IN_CREATE, 0, dentry->d_name.name,
+				  dentry->d_inode);
 	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
 }
 
@@ -106,7 +108,7 @@
 {
 	inode_dir_notify(inode, DN_CREATE);
 	inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, 
-				  dentry->d_name.name);
+				  dentry->d_name.name, dentry->d_inode);
 	audit_inode_child(dentry->d_name.name, dentry->d_inode, inode->i_ino);
 }
 
@@ -123,7 +125,7 @@
 
 	dnotify_parent(dentry, DN_ACCESS);
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -139,7 +141,7 @@
 
 	dnotify_parent(dentry, DN_MODIFY);
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -154,7 +156,7 @@
 		mask |= IN_ISDIR;
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);	
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -172,7 +174,7 @@
 		mask |= IN_ISDIR;
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -187,7 +189,7 @@
 		mask |= IN_ISDIR;
 
 	inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
-	inotify_inode_queue_event(inode, mask, 0, NULL);
+	inotify_inode_queue_event(inode, mask, 0, NULL, NULL);
 }
 
 /*
@@ -234,7 +236,7 @@
 	if (in_mask) {
 		if (S_ISDIR(inode->i_mode))
 			in_mask |= IN_ISDIR;
-		inotify_inode_queue_event(inode, in_mask, 0, NULL);
+		inotify_inode_queue_event(inode, in_mask, 0, NULL, NULL);
 		inotify_dentry_parent_queue_event(dentry, in_mask, 0,
 						  dentry->d_name.name);
 	}
diff --git a/include/linux/ftape.h b/include/linux/ftape.h
index 72faeec..7e7038c 100644
--- a/include/linux/ftape.h
+++ b/include/linux/ftape.h
@@ -35,7 +35,6 @@
 #include <linux/mm.h>
 #endif
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/mtio.h>
 
 #define FT_SECTOR(x)		(x+1)	/* sector offset into real sector */
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 5425b60..9fc48a6 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -1,6 +1,6 @@
 /*
     FUSE: Filesystem in Userspace
-    Copyright (C) 2001-2005  Miklos Szeredi <miklos@szeredi.hu>
+    Copyright (C) 2001-2006  Miklos Szeredi <miklos@szeredi.hu>
 
     This program can be distributed under the terms of the GNU GPL.
     See the file COPYING.
@@ -9,18 +9,19 @@
 /* This file defines the kernel interface of FUSE */
 
 #include <asm/types.h>
+#include <linux/major.h>
 
 /** Version number of this interface */
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 6
+#define FUSE_KERNEL_MINOR_VERSION 7
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
 
 /** The major number of the fuse character device */
-#define FUSE_MAJOR 10
+#define FUSE_MAJOR MISC_MAJOR
 
 /** The minor number of the fuse character device */
 #define FUSE_MINOR 229
@@ -58,6 +59,13 @@
 	__u32	spare[6];
 };
 
+struct fuse_file_lock {
+	__u64	start;
+	__u64	end;
+	__u32	type;
+	__u32	pid; /* tgid */
+};
+
 /**
  * Bitmasks for fuse_setattr_in.valid
  */
@@ -82,6 +90,7 @@
  * INIT request/reply flags
  */
 #define FUSE_ASYNC_READ		(1 << 0)
+#define FUSE_POSIX_LOCKS	(1 << 1)
 
 enum fuse_opcode {
 	FUSE_LOOKUP	   = 1,
@@ -112,8 +121,12 @@
 	FUSE_READDIR       = 28,
 	FUSE_RELEASEDIR    = 29,
 	FUSE_FSYNCDIR      = 30,
+	FUSE_GETLK         = 31,
+	FUSE_SETLK         = 32,
+	FUSE_SETLKW        = 33,
 	FUSE_ACCESS        = 34,
-	FUSE_CREATE        = 35
+	FUSE_CREATE        = 35,
+	FUSE_INTERRUPT     = 36,
 };
 
 /* The read buffer is required to be at least 8k, but may be much larger */
@@ -199,6 +212,7 @@
 	__u64	fh;
 	__u32	flush_flags;
 	__u32	padding;
+	__u64	lock_owner;
 };
 
 struct fuse_read_in {
@@ -247,6 +261,16 @@
 	__u32	padding;
 };
 
+struct fuse_lk_in {
+	__u64	fh;
+	__u64	owner;
+	struct fuse_file_lock lk;
+};
+
+struct fuse_lk_out {
+	struct fuse_file_lock lk;
+};
+
 struct fuse_access_in {
 	__u32	mask;
 	__u32	padding;
@@ -268,6 +292,10 @@
 	__u32	max_write;
 };
 
+struct fuse_interrupt_in {
+	__u64	unique;
+};
+
 struct fuse_in_header {
 	__u32	len;
 	__u32	opcode;
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 966a5b3..34c3a21 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -12,6 +12,9 @@
 #define FUTEX_REQUEUE		3
 #define FUTEX_CMP_REQUEUE	4
 #define FUTEX_WAKE_OP		5
+#define FUTEX_LOCK_PI		6
+#define FUTEX_UNLOCK_PI		7
+#define FUTEX_TRYLOCK_PI	8
 
 /*
  * Support for robust futexes: the kernel cleans up held futexes at
@@ -90,18 +93,21 @@
  */
 #define ROBUST_LIST_LIMIT	2048
 
-long do_futex(unsigned long uaddr, int op, int val,
-		unsigned long timeout, unsigned long uaddr2, int val2,
-		int val3);
+long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
+	      u32 __user *uaddr2, u32 val2, u32 val3);
 
 extern int handle_futex_death(u32 __user *uaddr, struct task_struct *curr);
 
 #ifdef CONFIG_FUTEX
 extern void exit_robust_list(struct task_struct *curr);
+extern void exit_pi_state_list(struct task_struct *curr);
 #else
 static inline void exit_robust_list(struct task_struct *curr)
 {
 }
+static inline void exit_pi_state_list(struct task_struct *curr)
+{
+}
 #endif
 
 #define FUTEX_OP_SET		0	/* *(int *)UADDR2 = OPARG; */
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index 71e7b28..2cdba0c 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 
+#ifdef __KERNEL__
 #include <asm/io.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -154,6 +155,8 @@
 
 void gameport_unregister_driver(struct gameport_driver *drv);
 
+#endif /* __KERNEL__ */
+
 #define GAMEPORT_MODE_DISABLED		0
 #define GAMEPORT_MODE_RAW		1
 #define GAMEPORT_MODE_COOKED		2
@@ -169,6 +172,8 @@
 #define GAMEPORT_ID_VENDOR_GRAVIS	0x0009
 #define GAMEPORT_ID_VENDOR_GUILLEMOT	0x000a
 
+#ifdef __KERNEL__
+
 static inline void gameport_trigger(struct gameport *gameport)
 {
 	if (gameport->trigger)
@@ -219,4 +224,5 @@
 void gameport_start_polling(struct gameport *gameport);
 void gameport_stop_polling(struct gameport *gameport);
 
+#endif /* __KERNEL__ */
 #endif
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
index 7fd0576..690c428 100644
--- a/include/linux/genalloc.h
+++ b/include/linux/genalloc.h
@@ -4,37 +4,32 @@
  * Uses for this includes on-device special memory, uncached memory
  * etc.
  *
- * This code is based on the buddy allocator found in the sym53c8xx_2
- * driver, adapted for general purpose use.
- *
  * This source code is licensed under the GNU General Public License,
  * Version 2.  See the file COPYING for more details.
  */
 
-#include <linux/spinlock.h>
-
-#define ALLOC_MIN_SHIFT		5 /* 32 bytes minimum */
-/*
- *  Link between free memory chunks of a given size.
- */
-struct gen_pool_link {
-	struct gen_pool_link *next;
-};
 
 /*
- *  Memory pool descriptor.
+ *  General purpose special memory pool descriptor.
  */
 struct gen_pool {
-	spinlock_t lock;
-	unsigned long (*get_new_chunk)(struct gen_pool *);
-	struct gen_pool *next;
-	struct gen_pool_link *h;
-	unsigned long private;
-	int max_chunk_shift;
+	rwlock_t lock;
+	struct list_head chunks;	/* list of chunks in this pool */
+	int min_alloc_order;		/* minimum allocation order */
 };
 
-unsigned long gen_pool_alloc(struct gen_pool *poolp, int size);
-void gen_pool_free(struct gen_pool *mp, unsigned long ptr, int size);
-struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift,
-				 unsigned long (*fp)(struct gen_pool *),
-				 unsigned long data);
+/*
+ *  General purpose special memory pool chunk descriptor.
+ */
+struct gen_pool_chunk {
+	spinlock_t lock;
+	struct list_head next_chunk;	/* next chunk in pool */
+	unsigned long start_addr;	/* starting address of memory chunk */
+	unsigned long end_addr;		/* ending address of memory chunk */
+	unsigned long bits[0];		/* bitmap for allocating memory chunk */
+};
+
+extern struct gen_pool *gen_pool_create(int, int);
+extern int gen_pool_add(struct gen_pool *, unsigned long, size_t, int);
+extern unsigned long gen_pool_alloc(struct gen_pool *, size_t);
+extern void gen_pool_free(struct gen_pool *, unsigned long, size_t);
diff --git a/include/linux/generic_serial.h b/include/linux/generic_serial.h
index 652611a..e253845 100644
--- a/include/linux/generic_serial.h
+++ b/include/linux/generic_serial.h
@@ -12,6 +12,7 @@
 #ifndef GENERIC_SERIAL_H
 #define GENERIC_SERIAL_H
 
+#ifdef __KERNEL__
 #include <linux/mutex.h>
 
 struct real_driver {
@@ -54,6 +55,7 @@
   spinlock_t              driver_lock;
 };
 
+#endif /* __KERNEL__ */
 
 /* Flags */
 /* Warning: serial.h defines some ASYNC_ flags, they say they are "only"
@@ -75,7 +77,7 @@
 #define GS_DEBUG_FLOW    0x00000020
 #define GS_DEBUG_WRITE   0x00000040
 
-
+#ifdef __KERNEL__
 void gs_put_char(struct tty_struct *tty, unsigned char ch);
 int  gs_write(struct tty_struct *tty, 
              const unsigned char *buf, int count);
@@ -94,5 +96,5 @@
 int  gs_setserial(struct gs_port *port, struct serial_struct __user *sp);
 int  gs_getserial(struct gs_port *port, struct serial_struct __user *sp);
 void gs_got_break(struct gs_port *port);
-
+#endif /* __KERNEL__ */
 #endif
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 2ef845b..3498a0c 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -9,13 +9,7 @@
  *		<drew@colorado.edu>
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
-#include <linux/major.h>
-#include <linux/device.h>
-#include <linux/smp.h>
-#include <linux/string.h>
-#include <linux/fs.h>
 
 enum {
 /* These three have identical behaviour; use the second one if DOS FDISK gets
@@ -61,6 +55,12 @@
 #endif
 
 #ifdef __KERNEL__
+#include <linux/major.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+
 struct partition {
 	unsigned char boot_ind;		/* 0x80 - active */
 	unsigned char head;		/* starting head */
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 3ac4529..cc9e6084 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -4,7 +4,6 @@
 #include <linux/mmzone.h>
 #include <linux/stddef.h>
 #include <linux/linkage.h>
-#include <linux/config.h>
 
 struct vm_area_struct;
 
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index eab5370..114ae58 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -1,7 +1,6 @@
 #ifndef LINUX_HARDIRQ_H
 #define LINUX_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/preempt.h>
 #include <linux/smp_lock.h>
 #include <asm/hardirq.h>
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index df695e9a..4513f9e 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -188,7 +188,7 @@
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 
 /* Must be used by hardware driver on module startup/exit */
-int register_hdlc_device(struct net_device *dev);
+#define register_hdlc_device(dev)	register_netdev(dev)
 void unregister_hdlc_device(struct net_device *dev);
 
 struct net_device *alloc_hdlcdev(void *priv);
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 892c4ea..85ce7ef 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_HIGHMEM_H
 #define _LINUX_HIGHMEM_H
 
-#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 
diff --git a/include/linux/highuid.h b/include/linux/highuid.h
index 53ecac3..434e562 100644
--- a/include/linux/highuid.h
+++ b/include/linux/highuid.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_HIGHUID_H
 #define _LINUX_HIGHUID_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 /*
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 306acf1..07d7305 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -40,7 +40,6 @@
 
 /**
  * struct hrtimer - the basic hrtimer structure
- *
  * @node:	red black tree node for time ordered insertion
  * @expires:	the absolute expiry time in the hrtimers internal
  *		representation. The time is related to the clock on
@@ -59,7 +58,6 @@
 
 /**
  * struct hrtimer_sleeper - simple sleeper structure
- *
  * @timer:	embedded timer structure
  * @task:	task to wake up
  *
@@ -72,7 +70,6 @@
 
 /**
  * struct hrtimer_base - the timer base for a specific clock
- *
  * @index:		clock type index for per_cpu support when moving a timer
  *			to a base on another cpu.
  * @lock:		lock protecting the base and associated timers
@@ -127,7 +124,7 @@
 
 static inline int hrtimer_active(const struct hrtimer *timer)
 {
-	return timer->node.rb_parent != HRTIMER_INACTIVE;
+	return rb_parent(&timer->node) != &timer->node;
 }
 
 /* Forward a hrtimer so it expires after now: */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 4c5e610..c25a38d 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -23,6 +23,8 @@
 unsigned long hugetlb_total_pages(void);
 int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 			unsigned long address, int write_access);
+int hugetlb_reserve_pages(struct inode *inode, long from, long to);
+void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
 
 extern unsigned long max_huge_pages;
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
@@ -139,8 +141,6 @@
 
 struct hugetlbfs_inode_info {
 	struct shared_policy policy;
-	/* Protected by the (global) hugetlb_lock */
-	unsigned long prereserved_hpages;
 	struct inode vfs_inode;
 };
 
@@ -157,10 +157,6 @@
 extern const struct file_operations hugetlbfs_file_operations;
 extern struct vm_operations_struct hugetlb_vm_ops;
 struct file *hugetlb_zero_setup(size_t);
-int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info,
-			       unsigned long atleast_hpages);
-void hugetlb_truncate_reservation(struct hugetlbfs_inode_info *info,
-				  unsigned long atmost_hpages);
 int hugetlb_get_quota(struct address_space *mapping);
 void hugetlb_put_quota(struct address_space *mapping);
 
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
new file mode 100644
index 0000000..21ea761
--- /dev/null
+++ b/include/linux/hw_random.h
@@ -0,0 +1,50 @@
+/*
+	Hardware Random Number Generator
+
+	Please read Documentation/hw_random.txt for details on use.
+
+	----------------------------------------------------------
+	This software may be used and distributed according to the terms
+        of the GNU General Public License, incorporated herein by reference.
+
+ */
+
+#ifndef LINUX_HWRANDOM_H_
+#define LINUX_HWRANDOM_H_
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/list.h>
+
+/**
+ * struct hwrng - Hardware Random Number Generator driver
+ * @name:		Unique RNG name.
+ * @init:		Initialization callback (can be NULL).
+ * @cleanup:		Cleanup callback (can be NULL).
+ * @data_present:	Callback to determine if data is available
+ *			on the RNG. If NULL, it is assumed that
+ *			there is always data available.
+ * @data_read:		Read data from the RNG device.
+ *			Returns the number of lower random bytes in "data".
+ *			Must not be NULL.
+ * @priv:		Private data, for use by the RNG driver.
+ */
+struct hwrng {
+	const char *name;
+	int (*init)(struct hwrng *rng);
+	void (*cleanup)(struct hwrng *rng);
+	int (*data_present)(struct hwrng *rng);
+	int (*data_read)(struct hwrng *rng, u32 *data);
+	unsigned long priv;
+
+	/* internal. */
+	struct list_head list;
+};
+
+/** Register a new Hardware Random Number Generator driver. */
+extern int hwrng_register(struct hwrng *rng);
+/** Unregister a Hardware Random Number Generator driver. */
+extern void hwrng_unregister(struct hwrng *rng);
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_HWRANDOM_H_ */
diff --git a/include/linux/i2c-algo-ite.h b/include/linux/i2c-algo-ite.h
index 26a8b89..0073fe9 100644
--- a/include/linux/i2c-algo-ite.h
+++ b/include/linux/i2c-algo-ite.h
@@ -29,7 +29,7 @@
 #ifndef I2C_ALGO_ITE_H
 #define I2C_ALGO_ITE_H 1
 
-#include <linux/i2c.h>
+#include <linux/types.h>
 
 /* Example of a sequential read request:
 	struct i2c_iic_msg s_msg; 
@@ -49,6 +49,9 @@
 	char *buf;	/* pointer to msg data */
 };
 
+#ifdef __KERNEL__
+struct i2c_adapter;
+
 struct i2c_algo_iic_data {
 	void *data;		/* private data for lolevel routines	*/
 	void (*setiic) (void *data, int ctl, int val);
@@ -65,5 +68,5 @@
 
 int i2c_iic_add_bus(struct i2c_adapter *);
 int i2c_iic_del_bus(struct i2c_adapter *);
-
+#endif /* __KERNEL__ */
 #endif /* I2C_ALGO_ITE_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index c8b81f4..21338bb 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -112,6 +112,9 @@
 #define I2C_DRIVERID_X1205	82	/* Xicor/Intersil X1205 RTC	*/
 #define I2C_DRIVERID_PCF8563	83	/* Philips PCF8563 RTC		*/
 #define I2C_DRIVERID_RS5C372	84	/* Ricoh RS5C372 RTC		*/
+#define I2C_DRIVERID_BT866	85	/* Conexant bt866 video encoder */
+#define I2C_DRIVERID_KS0127	86	/* Samsung ks0127 video decoder */
+#define I2C_DRIVERID_TLV320AIC23B 87	/* TI TLV320AIC23B audio codec  */
 
 #define I2C_DRIVERID_I2CDEV	900
 #define I2C_DRIVERID_ARP        902    /* SMBus ARP Client              */
diff --git a/include/linux/i2c-ocores.h b/include/linux/i2c-ocores.h
new file mode 100644
index 0000000..8ed591b
--- /dev/null
+++ b/include/linux/i2c-ocores.h
@@ -0,0 +1,19 @@
+/*
+ * i2c-ocores.h - definitions for the i2c-ocores interface
+ *
+ * Peter Korsgaard <jacmet@sunsite.dk>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef _LINUX_I2C_OCORES_H
+#define _LINUX_I2C_OCORES_H
+
+struct ocores_i2c_platform_data {
+	u32 regstep;   /* distance between registers */
+	u32 clock_khz; /* input clock in kHz */
+};
+
+#endif /* _LINUX_I2C_OCORES_H */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 1635ee2..526ddc8 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -20,14 +20,15 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
 /* ------------------------------------------------------------------------- */
 
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
    Frodo Looijaard <frodol@dds.nl> */
 
 #ifndef _LINUX_I2C_H
 #define _LINUX_I2C_H
 
-#include <linux/module.h>
 #include <linux/types.h>
+#ifdef __KERNEL__ 
+#include <linux/module.h>
 #include <linux/i2c-id.h>
 #include <linux/mod_devicetable.h>
 #include <linux/device.h>	/* for struct device */
@@ -96,13 +97,13 @@
                                      u8 command, u16 value);
 extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
 				      u8 command, u8 length,
-				      u8 *values);
+				      const u8 *values);
 /* Returns the number of read bytes */
 extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
 					 u8 command, u8 *values);
 extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
 					  u8 command, u8 length,
-					  u8 *values);
+					  const u8 *values);
 
 /*
  * A driver is capable of handling one or more physical devices present on
@@ -354,6 +355,7 @@
 {
 	return adap->nr;
 }
+#endif /* __KERNEL__ */
 
 /*
  * I2C Message - used for pure i2c transaction, also from /dev interface
@@ -469,6 +471,7 @@
 #define I2C_SMBUS	0x0720	/* SMBus-level access */
 
 /* ----- I2C-DEV: char device interface stuff ------------------------- */
+#ifdef __KERNEL__
 
 #define I2C_MAJOR	89		/* Device major number		*/
 
@@ -646,5 +649,5 @@
 				    force_##chip6, force_##chip7,	\
 				    force_##chip8, NULL };		\
 I2C_CLIENT_INSMOD_COMMON
-
+#endif /* __KERNEL__ */
 #endif /* _LINUX_I2C_H */
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
index 36fd18c..c2519df 100644
--- a/include/linux/i2o-dev.h
+++ b/include/linux/i2o-dev.h
@@ -13,7 +13,7 @@
  * This header file defines the I2O APIs that are available to both
  * the kernel and user level applications.  Kernel specific structures
  * are defined in i2o_osm. OSMs should include _only_ i2o_osm.h which
- * automatically includs this file.
+ * automatically includes this file.
  *
  */
 
@@ -23,14 +23,7 @@
 /* How many controllers are we allowing */
 #define MAX_I2O_CONTROLLERS	32
 
-//#include <linux/ioctl.h>
-#ifndef __KERNEL__
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-#endif				/* __KERNEL__ */
+#include <linux/ioctl.h>
 
 /*
  * I2O Control IOCTLs and structures
@@ -53,7 +46,7 @@
 
 struct i2o_cmd_passthru32 {
 	unsigned int iop;	/* IOP unit number */
-	u32 msg;		/* message */
+	__u32 msg;		/* message */
 };
 
 struct i2o_cmd_passthru {
@@ -138,53 +131,53 @@
 #define I2O_BUS_UNKNOWN 0x80
 
 typedef struct _i2o_pci_bus {
-	u8 PciFunctionNumber;
-	u8 PciDeviceNumber;
-	u8 PciBusNumber;
-	u8 reserved;
-	u16 PciVendorID;
-	u16 PciDeviceID;
+	__u8 PciFunctionNumber;
+	__u8 PciDeviceNumber;
+	__u8 PciBusNumber;
+	__u8 reserved;
+	__u16 PciVendorID;
+	__u16 PciDeviceID;
 } i2o_pci_bus;
 
 typedef struct _i2o_local_bus {
-	u16 LbBaseIOPort;
-	u16 reserved;
-	u32 LbBaseMemoryAddress;
+	__u16 LbBaseIOPort;
+	__u16 reserved;
+	__u32 LbBaseMemoryAddress;
 } i2o_local_bus;
 
 typedef struct _i2o_isa_bus {
-	u16 IsaBaseIOPort;
-	u8 CSN;
-	u8 reserved;
-	u32 IsaBaseMemoryAddress;
+	__u16 IsaBaseIOPort;
+	__u8 CSN;
+	__u8 reserved;
+	__u32 IsaBaseMemoryAddress;
 } i2o_isa_bus;
 
 typedef struct _i2o_eisa_bus_info {
-	u16 EisaBaseIOPort;
-	u8 reserved;
-	u8 EisaSlotNumber;
-	u32 EisaBaseMemoryAddress;
+	__u16 EisaBaseIOPort;
+	__u8 reserved;
+	__u8 EisaSlotNumber;
+	__u32 EisaBaseMemoryAddress;
 } i2o_eisa_bus;
 
 typedef struct _i2o_mca_bus {
-	u16 McaBaseIOPort;
-	u8 reserved;
-	u8 McaSlotNumber;
-	u32 McaBaseMemoryAddress;
+	__u16 McaBaseIOPort;
+	__u8 reserved;
+	__u8 McaSlotNumber;
+	__u32 McaBaseMemoryAddress;
 } i2o_mca_bus;
 
 typedef struct _i2o_other_bus {
-	u16 BaseIOPort;
-	u16 reserved;
-	u32 BaseMemoryAddress;
+	__u16 BaseIOPort;
+	__u16 reserved;
+	__u32 BaseMemoryAddress;
 } i2o_other_bus;
 
 typedef struct _i2o_hrt_entry {
-	u32 adapter_id;
-	u32 parent_tid:12;
-	u32 state:4;
-	u32 bus_num:8;
-	u32 bus_type:8;
+	__u32 adapter_id;
+	__u32 parent_tid:12;
+	__u32 state:4;
+	__u32 bus_num:8;
+	__u32 bus_type:8;
 	union {
 		i2o_pci_bus pci_bus;
 		i2o_local_bus local_bus;
@@ -196,66 +189,66 @@
 } i2o_hrt_entry;
 
 typedef struct _i2o_hrt {
-	u16 num_entries;
-	u8 entry_len;
-	u8 hrt_version;
-	u32 change_ind;
+	__u16 num_entries;
+	__u8 entry_len;
+	__u8 hrt_version;
+	__u32 change_ind;
 	i2o_hrt_entry hrt_entry[1];
 } i2o_hrt;
 
 typedef struct _i2o_lct_entry {
-	u32 entry_size:16;
-	u32 tid:12;
-	u32 reserved:4;
-	u32 change_ind;
-	u32 device_flags;
-	u32 class_id:12;
-	u32 version:4;
-	u32 vendor_id:16;
-	u32 sub_class;
-	u32 user_tid:12;
-	u32 parent_tid:12;
-	u32 bios_info:8;
-	u8 identity_tag[8];
-	u32 event_capabilities;
+	__u32 entry_size:16;
+	__u32 tid:12;
+	__u32 reserved:4;
+	__u32 change_ind;
+	__u32 device_flags;
+	__u32 class_id:12;
+	__u32 version:4;
+	__u32 vendor_id:16;
+	__u32 sub_class;
+	__u32 user_tid:12;
+	__u32 parent_tid:12;
+	__u32 bios_info:8;
+	__u8 identity_tag[8];
+	__u32 event_capabilities;
 } i2o_lct_entry;
 
 typedef struct _i2o_lct {
-	u32 table_size:16;
-	u32 boot_tid:12;
-	u32 lct_ver:4;
-	u32 iop_flags;
-	u32 change_ind;
+	__u32 table_size:16;
+	__u32 boot_tid:12;
+	__u32 lct_ver:4;
+	__u32 iop_flags;
+	__u32 change_ind;
 	i2o_lct_entry lct_entry[1];
 } i2o_lct;
 
 typedef struct _i2o_status_block {
-	u16 org_id;
-	u16 reserved;
-	u16 iop_id:12;
-	u16 reserved1:4;
-	u16 host_unit_id;
-	u16 segment_number:12;
-	u16 i2o_version:4;
-	u8 iop_state;
-	u8 msg_type;
-	u16 inbound_frame_size;
-	u8 init_code;
-	u8 reserved2;
-	u32 max_inbound_frames;
-	u32 cur_inbound_frames;
-	u32 max_outbound_frames;
+	__u16 org_id;
+	__u16 reserved;
+	__u16 iop_id:12;
+	__u16 reserved1:4;
+	__u16 host_unit_id;
+	__u16 segment_number:12;
+	__u16 i2o_version:4;
+	__u8 iop_state;
+	__u8 msg_type;
+	__u16 inbound_frame_size;
+	__u8 init_code;
+	__u8 reserved2;
+	__u32 max_inbound_frames;
+	__u32 cur_inbound_frames;
+	__u32 max_outbound_frames;
 	char product_id[24];
-	u32 expected_lct_size;
-	u32 iop_capabilities;
-	u32 desired_mem_size;
-	u32 current_mem_size;
-	u32 current_mem_base;
-	u32 desired_io_size;
-	u32 current_io_size;
-	u32 current_io_base;
-	u32 reserved3:24;
-	u32 cmd_status:8;
+	__u32 expected_lct_size;
+	__u32 iop_capabilities;
+	__u32 desired_mem_size;
+	__u32 current_mem_size;
+	__u32 current_mem_base;
+	__u32 desired_io_size;
+	__u32 current_io_size;
+	__u32 current_io_base;
+	__u32 reserved3:24;
+	__u32 cmd_status:8;
 } i2o_status_block;
 
 /* Event indicator mask flags */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index a8bef1d..0c10016 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -6,7 +6,6 @@
  *  Copyright (C) 1994-2002  Linus Torvalds & authors
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/hdreg.h>
@@ -631,6 +630,7 @@
 	unsigned int	usage;		/* current "open()" count for drive */
 	unsigned int	failures;	/* current failure count */
 	unsigned int	max_failures;	/* maximum allowed failure count */
+	u64		probed_capacity;/* initial reported media capacity (ide-cd only currently) */
 
 	u64		capacity64;	/* total number of sectors */
 
@@ -793,6 +793,7 @@
 	unsigned	auto_poll  : 1; /* supports nop auto-poll */
 	unsigned	sg_mapped  : 1;	/* sg_table and sg_nents are ready */
 	unsigned	no_io_32bit : 1; /* 1 = can not do 32-bit IO ops */
+	unsigned	err_stops_fifo : 1; /* 1=data FIFO is cleared by an error */
 
 	struct device	gendev;
 	struct completion gendev_rel_comp; /* To deal with device release() */
@@ -1006,6 +1007,8 @@
 extern int noautodma;
 
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
+int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
+			     int uptodate, int nr_sectors);
 
 /*
  * This is used on exit from the driver to designate the next irq handler
diff --git a/include/linux/idr.h b/include/linux/idr.h
index d37c8d8..f559a71 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -78,6 +78,7 @@
 int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
 int idr_get_new(struct idr *idp, void *ptr, int *id);
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
+void *idr_replace(struct idr *idp, void *ptr, int id);
 void idr_remove(struct idr *idp, int id);
 void idr_destroy(struct idr *idp);
 void idr_init(struct idr *idp);
diff --git a/include/linux/if_fddi.h b/include/linux/if_fddi.h
index 1288a16..e0a1500 100644
--- a/include/linux/if_fddi.h
+++ b/include/linux/if_fddi.h
@@ -102,6 +102,7 @@
 		} hdr;
 	} __attribute__ ((packed));
 
+#ifdef __KERNEL__
 /* Define FDDI statistics structure */
 struct fddi_statistics {
 
@@ -193,5 +194,6 @@
 	__u32	port_ler_flag[2];
 	__u32	port_hardware_present[2];
 	};
+#endif /* __KERNEL__ */
 
 #endif	/* _LINUX_IF_FDDI_H */
diff --git a/include/linux/if_frad.h b/include/linux/if_frad.h
index 395f0aa..f272a80 100644
--- a/include/linux/if_frad.h
+++ b/include/linux/if_frad.h
@@ -24,7 +24,6 @@
 #ifndef _FRAD_H_
 #define _FRAD_H_
 
-#include <linux/config.h>
 #include <linux/if.h>
 
 #if defined(CONFIG_DLCI) || defined(CONFIG_DLCI_MODULE)
diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h
index 5502f59..2f94cf2 100644
--- a/include/linux/if_tr.h
+++ b/include/linux/if_tr.h
@@ -43,7 +43,6 @@
 };
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 static inline struct trh_hdr *tr_hdr(const struct sk_buff *skb)
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 28f4f3b..899c3d4 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -169,7 +169,7 @@
 struct ip_mc_list
 {
 	struct in_device	*interface;
-	unsigned long		multiaddr;
+	__be32			multiaddr;
 	struct ip_sf_list	*sources;
 	struct ip_sf_list	*tomb;
 	unsigned int		sfmode;
diff --git a/include/linux/init.h b/include/linux/init.h
index 93dcbe1..6667785 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_INIT_H
 #define _LINUX_INIT_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 
 /* These macros are used to mark some functions or 
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 41ecbb8..3a25695 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -87,6 +87,7 @@
 	.lock_depth	= -1,						\
 	.prio		= MAX_PRIO-20,					\
 	.static_prio	= MAX_PRIO-20,					\
+	.normal_prio	= MAX_PRIO-20,					\
 	.policy		= SCHED_NORMAL,					\
 	.cpus_allowed	= CPU_MASK_ALL,					\
 	.mm		= NULL,						\
@@ -119,10 +120,11 @@
 		.signal = {{0}}},					\
 	.blocked	= {{0}},					\
 	.alloc_lock	= SPIN_LOCK_UNLOCKED,				\
-	.proc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
 	.fs_excl	= ATOMIC_INIT(0),				\
+	.pi_lock	= SPIN_LOCK_UNLOCKED,				\
+	INIT_RT_MUTEXES(tsk)						\
 }
 
 
diff --git a/include/linux/inotify.h b/include/linux/inotify.h
index 09e0043..d4f48c6 100644
--- a/include/linux/inotify.h
+++ b/include/linux/inotify.h
@@ -67,20 +67,66 @@
 
 #include <linux/dcache.h>
 #include <linux/fs.h>
-#include <linux/config.h>
+
+/*
+ * struct inotify_watch - represents a watch request on a specific inode
+ *
+ * h_list is protected by ih->mutex of the associated inotify_handle.
+ * i_list, mask are protected by inode->inotify_mutex of the associated inode.
+ * ih, inode, and wd are never written to once the watch is created.
+ *
+ * Callers must use the established inotify interfaces to access inotify_watch
+ * contents.  The content of this structure is private to the inotify
+ * implementation.
+ */
+struct inotify_watch {
+	struct list_head	h_list;	/* entry in inotify_handle's list */
+	struct list_head	i_list;	/* entry in inode's list */
+	atomic_t		count;	/* reference count */
+	struct inotify_handle	*ih;	/* associated inotify handle */
+	struct inode		*inode;	/* associated inode */
+	__s32			wd;	/* watch descriptor */
+	__u32			mask;	/* event mask for this watch */
+};
+
+struct inotify_operations {
+	void (*handle_event)(struct inotify_watch *, u32, u32, u32,
+			     const char *, struct inode *);
+	void (*destroy_watch)(struct inotify_watch *);
+};
 
 #ifdef CONFIG_INOTIFY
 
+/* Kernel API for producing events */
+
 extern void inotify_d_instantiate(struct dentry *, struct inode *);
 extern void inotify_d_move(struct dentry *);
 extern void inotify_inode_queue_event(struct inode *, __u32, __u32,
-				      const char *);
+				      const char *, struct inode *);
 extern void inotify_dentry_parent_queue_event(struct dentry *, __u32, __u32,
 					      const char *);
 extern void inotify_unmount_inodes(struct list_head *);
 extern void inotify_inode_is_dead(struct inode *);
 extern u32 inotify_get_cookie(void);
 
+/* Kernel Consumer API */
+
+extern struct inotify_handle *inotify_init(const struct inotify_operations *);
+extern void inotify_init_watch(struct inotify_watch *);
+extern void inotify_destroy(struct inotify_handle *);
+extern __s32 inotify_find_watch(struct inotify_handle *, struct inode *,
+				struct inotify_watch **);
+extern __s32 inotify_find_update_watch(struct inotify_handle *, struct inode *,
+				       u32);
+extern __s32 inotify_add_watch(struct inotify_handle *, struct inotify_watch *,
+			       struct inode *, __u32);
+extern int inotify_rm_watch(struct inotify_handle *, struct inotify_watch *);
+extern int inotify_rm_wd(struct inotify_handle *, __u32);
+extern void inotify_remove_watch_locked(struct inotify_handle *,
+					struct inotify_watch *);
+extern void get_inotify_watch(struct inotify_watch *);
+extern void put_inotify_watch(struct inotify_watch *);
+
 #else
 
 static inline void inotify_d_instantiate(struct dentry *dentry,
@@ -94,7 +140,8 @@
 
 static inline void inotify_inode_queue_event(struct inode *inode,
 					     __u32 mask, __u32 cookie,
-					     const char *filename)
+					     const char *filename,
+					     struct inode *n_inode)
 {
 }
 
@@ -117,6 +164,62 @@
 	return 0;
 }
 
+static inline struct inotify_handle *inotify_init(const struct inotify_operations *ops)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void inotify_init_watch(struct inotify_watch *watch)
+{
+}
+
+static inline void inotify_destroy(struct inotify_handle *ih)
+{
+}
+
+static inline __s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode,
+				       struct inotify_watch **watchp)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline __s32 inotify_find_update_watch(struct inotify_handle *ih,
+					      struct inode *inode, u32 mask)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline __s32 inotify_add_watch(struct inotify_handle *ih,
+				      struct inotify_watch *watch,
+				      struct inode *inode, __u32 mask)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int inotify_rm_watch(struct inotify_handle *ih,
+				   struct inotify_watch *watch)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int inotify_rm_wd(struct inotify_handle *ih, __u32 wd)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline void inotify_remove_watch_locked(struct inotify_handle *ih,
+					       struct inotify_watch *watch)
+{
+}
+
+static inline void get_inotify_watch(struct inotify_watch *watch)
+{
+}
+
+static inline void put_inotify_watch(struct inotify_watch *watch)
+{
+}
+
 #endif	/* CONFIG_INOTIFY */
 
 #endif	/* __KERNEL __ */
diff --git a/include/linux/input.h b/include/linux/input.h
index ce1a756..56f1e0e 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -15,6 +15,7 @@
 #else
 #include <sys/time.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
 #include <asm/types.h>
 #endif
 
@@ -231,7 +232,8 @@
 #define KEY_PAUSE		119
 
 #define KEY_KPCOMMA		121
-#define KEY_HANGUEL		122
+#define KEY_HANGEUL		122
+#define KEY_HANGUEL		KEY_HANGEUL
 #define KEY_HANJA		123
 #define KEY_YEN			124
 #define KEY_LEFTMETA		125
@@ -1004,6 +1006,7 @@
 }
 
 struct input_dev *input_allocate_device(void);
+void input_free_device(struct input_dev *dev);
 
 static inline struct input_dev *input_get_device(struct input_dev *dev)
 {
@@ -1015,12 +1018,6 @@
 	class_device_put(&dev->cdev);
 }
 
-static inline void input_free_device(struct input_dev *dev)
-{
-	if (dev)
-		input_put_device(dev);
-}
-
 int input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);
 
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 2c08fdc..70741e1 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -2,38 +2,18 @@
 #ifndef _LINUX_INTERRUPT_H
 #define _LINUX_INTERRUPT_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/linkage.h>
 #include <linux/bitops.h>
 #include <linux/preempt.h>
 #include <linux/cpumask.h>
+#include <linux/irqreturn.h>
 #include <linux/hardirq.h>
 #include <linux/sched.h>
 #include <asm/atomic.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 
-/*
- * For 2.4.x compatibility, 2.4.x can use
- *
- *	typedef void irqreturn_t;
- *	#define IRQ_NONE
- *	#define IRQ_HANDLED
- *	#define IRQ_RETVAL(x)
- *
- * To mix old-style and new-style irq handler returns.
- *
- * IRQ_NONE means we didn't handle it.
- * IRQ_HANDLED means that we did have a valid interrupt and handled it.
- * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled)
- */
-typedef int irqreturn_t;
-
-#define IRQ_NONE	(0)
-#define IRQ_HANDLED	(1)
-#define IRQ_RETVAL(x)	((x) != 0)
-
 struct irqaction {
 	irqreturn_t (*handler)(int, void *, struct pt_regs *);
 	unsigned long flags;
diff --git a/include/linux/io.h b/include/linux/io.h
index 85533ec..420e2fd 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -21,5 +21,6 @@
 #include <asm/io.h>
 
 void __iowrite32_copy(void __iomem *to, const void *from, size_t count);
+void __iowrite64_copy(void __iomem *to, const void *from, size_t count);
 
 #endif /* _LINUX_IO_H */
diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h
index 3dd18b7..de73a32 100644
--- a/include/linux/ioc4.h
+++ b/include/linux/ioc4.h
@@ -147,6 +147,10 @@
 #define IOC4_GPCR_EDGE_6 0x40
 #define IOC4_GPCR_EDGE_7 0x80
 
+#define IOC4_VARIANT_IO9	0x0900
+#define IOC4_VARIANT_PCI_RT	0x0901
+#define IOC4_VARIANT_IO10	0x1000
+
 /* One of these per IOC4 */
 struct ioc4_driver_data {
 	struct list_head idd_list;
@@ -156,6 +160,7 @@
 	struct __iomem ioc4_misc_regs *idd_misc_regs;
 	unsigned long count_period;
 	void *idd_serial_data;
+	unsigned int idd_variant;
 };
 
 /* One per submodule */
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index cd6bd00..edfc733 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -105,6 +105,9 @@
 int adjust_resource(struct resource *res, unsigned long start,
 		    unsigned long size);
 
+/* get registered SYSTEM_RAM resources in specified area */
+extern int find_next_system_ram(struct resource *res);
+
 /* Convenience shorthand with allocation */
 #define request_region(start,n,name)	__request_region(&ioport_resource, (start), (n), (name))
 #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name))
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 0a84b56..d09fbea 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -36,7 +36,6 @@
 
 #include <linux/ipmi_msgdefs.h>
 #include <linux/compiler.h>
-#include <linux/device.h>
 
 /*
  * This file describes an interface to an IPMI driver.  You have to
@@ -210,11 +209,8 @@
  */
 #include <linux/list.h>
 #include <linux/module.h>
-
-#ifdef CONFIG_PROC_FS
+#include <linux/device.h>
 #include <linux/proc_fs.h>
-extern struct proc_dir_entry *proc_ipmi_root;
-#endif /* CONFIG_PROC_FS */
 
 /* Opaque type for a IPMI message user.  One of these is needed to
    send and receive messages. */
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 1263d8c..297853c 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -1,7 +1,6 @@
 #ifndef _IPV6_H
 #define _IPV6_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 #include <asm/byteorder.h>
 
diff --git a/include/linux/irq.h b/include/linux/irq.h
index ee2a82a..676e00d 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -9,7 +9,6 @@
  * Thanks. --rmk
  */
 
-#include <linux/config.h>
 #include <linux/smp.h>
 
 #if !defined(CONFIG_S390)
@@ -18,6 +17,7 @@
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 #include <linux/cpumask.h>
+#include <linux/irqreturn.h>
 
 #include <asm/irq.h>
 #include <asm/ptrace.h>
@@ -165,10 +165,18 @@
 
 #endif // CONFIG_SMP
 
+#ifdef CONFIG_IRQBALANCE
+extern void set_balance_irq_affinity(unsigned int irq, cpumask_t mask);
+#else
+static inline void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
+{
+}
+#endif
+
 extern int no_irq_affinity;
 extern int noirqdebug_setup(char *str);
 
-extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
+extern fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
 					struct irqaction *action);
 extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
 extern void note_interrupt(unsigned int irq, irq_desc_t *desc,
diff --git a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h
index af93505..77e4bac 100644
--- a/include/linux/irq_cpustat.h
+++ b/include/linux/irq_cpustat.h
@@ -9,7 +9,6 @@
  * Keith Owens <kaos@ocs.com.au> July 2000.
  */
 
-#include <linux/config.h>
 
 /*
  * Simple wrappers reducing source bloat.  Define all irq_stat fields
diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h
new file mode 100644
index 0000000..881883c
--- /dev/null
+++ b/include/linux/irqreturn.h
@@ -0,0 +1,25 @@
+/* irqreturn.h */
+#ifndef _LINUX_IRQRETURN_H
+#define _LINUX_IRQRETURN_H
+
+/*
+ * For 2.4.x compatibility, 2.4.x can use
+ *
+ *	typedef void irqreturn_t;
+ *	#define IRQ_NONE
+ *	#define IRQ_HANDLED
+ *	#define IRQ_RETVAL(x)
+ *
+ * To mix old-style and new-style irq handler returns.
+ *
+ * IRQ_NONE means we didn't handle it.
+ * IRQ_HANDLED means that we did have a valid interrupt and handled it.
+ * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled)
+ */
+typedef int irqreturn_t;
+
+#define IRQ_NONE	(0)
+#define IRQ_HANDLED	(1)
+#define IRQ_RETVAL(x)	((x) != 0)
+
+#endif
diff --git a/include/linux/isa.h b/include/linux/isa.h
new file mode 100644
index 0000000..1b85533
--- /dev/null
+++ b/include/linux/isa.h
@@ -0,0 +1,28 @@
+/*
+ * ISA bus.
+ */
+
+#ifndef __LINUX_ISA_H
+#define __LINUX_ISA_H
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+struct isa_driver {
+	int (*match)(struct device *, unsigned int);
+	int (*probe)(struct device *, unsigned int);
+	int (*remove)(struct device *, unsigned int);
+	void (*shutdown)(struct device *, unsigned int);
+	int (*suspend)(struct device *, unsigned int, pm_message_t);
+	int (*resume)(struct device *, unsigned int);
+
+	struct device_driver driver;
+	struct device *devices;
+};
+
+#define to_isa_driver(x) container_of((x), struct isa_driver, driver)
+
+int isa_register_driver(struct isa_driver *, unsigned int);
+void isa_unregister_driver(struct isa_driver *);
+
+#endif /* __LINUX_ISA_H */
diff --git a/include/linux/isapnp.h b/include/linux/isapnp.h
index 26c64c2..1e8728a 100644
--- a/include/linux/isapnp.h
+++ b/include/linux/isapnp.h
@@ -22,7 +22,6 @@
 #ifndef LINUX_ISAPNP_H
 #define LINUX_ISAPNP_H
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/pnp.h>
 
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 53eaee9..6299114 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -146,7 +146,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/major.h>
diff --git a/include/linux/isdn/tpam.h b/include/linux/isdn/tpam.h
index 9f65bea..d18dd0d 100644
--- a/include/linux/isdn/tpam.h
+++ b/include/linux/isdn/tpam.h
@@ -26,7 +26,6 @@
 #define _TPAM_H_
 
 #include <linux/types.h>
-#include <linux/pci.h>
 
 /* IOCTL commands */
 #define TPAM_CMD_DSPLOAD	0x0001
diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
index 26b00a7..8687a7d 100644
--- a/include/linux/isdn_ppp.h
+++ b/include/linux/isdn_ppp.h
@@ -67,7 +67,6 @@
 #ifdef __KERNEL__
 
 
-#include <linux/config.h>
 
 #ifdef CONFIG_IPPP_FILTER
 #include <linux/filter.h>
diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h
index 04e10f9..b9b5a68 100644
--- a/include/linux/isdnif.h
+++ b/include/linux/isdnif.h
@@ -54,7 +54,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 /***************************************************************************/
diff --git a/include/linux/jbd.h b/include/linux/jbd.h
index 6a425e3..20eb344 100644
--- a/include/linux/jbd.h
+++ b/include/linux/jbd.h
@@ -501,6 +501,12 @@
 	struct journal_head	*t_checkpoint_list;
 
 	/*
+	 * Doubly-linked circular list of all buffers submitted for IO while
+	 * checkpointing. [j_list_lock]
+	 */
+	struct journal_head	*t_checkpoint_io_list;
+
+	/*
 	 * Doubly-linked circular list of temporary buffers currently undergoing
 	 * IO in the log [j_list_lock]
 	 */
@@ -849,7 +855,7 @@
 
 /* Checkpoint list management */
 int __journal_clean_checkpoint_list(journal_t *journal);
-void __journal_remove_checkpoint(struct journal_head *);
+int __journal_remove_checkpoint(struct journal_head *);
 void __journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
 /* Buffer IO */
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index cf792bb..c9c7607 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -65,6 +65,18 @@
 
 #define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6)
 
+#define JFFS2_NODETYPE_XATTR (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 8)
+#define JFFS2_NODETYPE_XREF (JFFS2_FEATURE_INCOMPAT | JFFS2_NODE_ACCURATE | 9)
+
+/* XATTR Related */
+#define JFFS2_XPREFIX_USER		1	/* for "user." */
+#define JFFS2_XPREFIX_SECURITY		2	/* for "security." */
+#define JFFS2_XPREFIX_ACL_ACCESS	3	/* for "system.posix_acl_access" */
+#define JFFS2_XPREFIX_ACL_DEFAULT	4	/* for "system.posix_acl_default" */
+#define JFFS2_XPREFIX_TRUSTED		5	/* for "trusted.*" */
+
+#define JFFS2_ACL_VERSION		0x0001
+
 // Maybe later...
 //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3)
 //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4)
@@ -82,11 +94,11 @@
 
 typedef struct {
 	uint32_t v32;
-} __attribute__((packed))  jint32_t;
+} __attribute__((packed)) jint32_t;
 
 typedef struct {
 	uint32_t m;
-} __attribute__((packed))  jmode_t;
+} __attribute__((packed)) jmode_t;
 
 typedef struct {
 	uint16_t v16;
@@ -99,7 +111,7 @@
 	jint16_t nodetype;
 	jint32_t totlen; /* So we can skip over nodes we don't grok */
 	jint32_t hdr_crc;
-} __attribute__((packed));
+};
 
 struct jffs2_raw_dirent
 {
@@ -117,7 +129,7 @@
 	jint32_t node_crc;
 	jint32_t name_crc;
 	uint8_t name[0];
-} __attribute__((packed));
+};
 
 /* The JFFS2 raw inode structure: Used for storage on physical media.  */
 /* The uid, gid, atime, mtime and ctime members could be longer, but
@@ -149,6 +161,33 @@
 	jint32_t data_crc;   /* CRC for the (compressed) data.  */
 	jint32_t node_crc;   /* CRC for the raw inode (excluding data)  */
 	uint8_t data[0];
+};
+
+struct jffs2_raw_xattr {
+	jint16_t magic;
+	jint16_t nodetype;	/* = JFFS2_NODETYPE_XATTR */
+	jint32_t totlen;
+	jint32_t hdr_crc;
+	jint32_t xid;		/* XATTR identifier number */
+	jint32_t version;
+	uint8_t xprefix;
+	uint8_t name_len;
+	jint16_t value_len;
+	jint32_t data_crc;
+	jint32_t node_crc;
+	uint8_t data[0];
+} __attribute__((packed));
+
+struct jffs2_raw_xref
+{
+	jint16_t magic;
+	jint16_t nodetype;	/* = JFFS2_NODETYPE_XREF */
+	jint32_t totlen;
+	jint32_t hdr_crc;
+	jint32_t ino;		/* inode number */
+	jint32_t xid;		/* XATTR identifier number */
+	jint32_t xseqno;	/* xref sequencial number */
+	jint32_t node_crc;
 } __attribute__((packed));
 
 struct jffs2_raw_summary
@@ -163,14 +202,22 @@
 	jint32_t sum_crc;	/* summary information crc */
 	jint32_t node_crc; 	/* node crc */
 	jint32_t sum[0]; 	/* inode summary info */
-} __attribute__((packed));
+};
 
 union jffs2_node_union
 {
 	struct jffs2_raw_inode i;
 	struct jffs2_raw_dirent d;
+	struct jffs2_raw_xattr x;
+	struct jffs2_raw_xref r;
 	struct jffs2_raw_summary s;
 	struct jffs2_unknown_node u;
 };
 
+/* Data payload for device nodes. */
+union jffs2_device_node {
+	jint16_t old;
+	jint32_t new;
+};
+
 #endif /* __LINUX_JFFS2_H__ */
diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h
deleted file mode 100644
index ad565bf..0000000
--- a/include/linux/jffs2_fs_i.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */
-
-#ifndef _JFFS2_FS_I
-#define _JFFS2_FS_I
-
-#include <linux/version.h>
-#include <linux/rbtree.h>
-#include <asm/semaphore.h>
-
-struct jffs2_inode_info {
-	/* We need an internal mutex similar to inode->i_mutex.
-	   Unfortunately, we can't used the existing one, because
-	   either the GC would deadlock, or we'd have to release it
-	   before letting GC proceed. Or we'd have to put ugliness
-	   into the GC code so it didn't attempt to obtain the i_mutex
-	   for the inode(s) which are already locked */
-	struct semaphore sem;
-
-	/* The highest (datanode) version number used for this ino */
-	uint32_t highest_version;
-
-	/* List of data fragments which make up the file */
-	struct rb_root fragtree;
-
-	/* There may be one datanode which isn't referenced by any of the
-	   above fragments, if it contains a metadata update but no actual
-	   data - or if this is a directory inode */
-	/* This also holds the _only_ dnode for symlinks/device nodes,
-	   etc. */
-	struct jffs2_full_dnode *metadata;
-
-	/* Directory entries */
-	struct jffs2_full_dirent *dents;
-
-	/* The target path if this is the inode of a symlink */
-	unsigned char *target;
-
-	/* Some stuff we just have to keep in-core at all times, for each inode. */
-	struct jffs2_inode_cache *inocache;
-
-	uint16_t flags;
-	uint8_t usercompr;
-#if !defined (__ECOS)
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2)
-	struct inode vfs_inode;
-#endif
-#endif
-};
-
-#endif /* _JFFS2_FS_I */
diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h
deleted file mode 100644
index 4bcfb55..0000000
--- a/include/linux/jffs2_fs_sb.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */
-
-#ifndef _JFFS2_FS_SB
-#define _JFFS2_FS_SB
-
-#include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/completion.h>
-#include <asm/semaphore.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/rwsem.h>
-
-#define JFFS2_SB_FLAG_RO 1
-#define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */
-#define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */
-
-struct jffs2_inodirty;
-
-/* A struct for the overall file system control.  Pointers to
-   jffs2_sb_info structs are named `c' in the source code.
-   Nee jffs_control
-*/
-struct jffs2_sb_info {
-	struct mtd_info *mtd;
-
-	uint32_t highest_ino;
-	uint32_t checked_ino;
-
-	unsigned int flags;
-
-	struct task_struct *gc_task;	/* GC task struct */
-	struct completion gc_thread_start; /* GC thread start completion */
-	struct completion gc_thread_exit; /* GC thread exit completion port */
-
-	struct semaphore alloc_sem;	/* Used to protect all the following
-					   fields, and also to protect against
-					   out-of-order writing of nodes. And GC. */
-	uint32_t cleanmarker_size;	/* Size of an _inline_ CLEANMARKER
-					 (i.e. zero for OOB CLEANMARKER */
-
-	uint32_t flash_size;
-	uint32_t used_size;
-	uint32_t dirty_size;
-	uint32_t wasted_size;
-	uint32_t free_size;
-	uint32_t erasing_size;
-	uint32_t bad_size;
-	uint32_t sector_size;
-	uint32_t unchecked_size;
-
-	uint32_t nr_free_blocks;
-	uint32_t nr_erasing_blocks;
-
-	/* Number of free blocks there must be before we... */
-	uint8_t resv_blocks_write;	/* ... allow a normal filesystem write */
-	uint8_t resv_blocks_deletion;	/* ... allow a normal filesystem deletion */
-	uint8_t resv_blocks_gctrigger;	/* ... wake up the GC thread */
-	uint8_t resv_blocks_gcbad;	/* ... pick a block from the bad_list to GC */
-	uint8_t resv_blocks_gcmerge;	/* ... merge pages when garbage collecting */
-
-	uint32_t nospc_dirty_size;
-
-	uint32_t nr_blocks;
-	struct jffs2_eraseblock *blocks;	/* The whole array of blocks. Used for getting blocks
-						 * from the offset (blocks[ofs / sector_size]) */
-	struct jffs2_eraseblock *nextblock;	/* The block we're currently filling */
-
-	struct jffs2_eraseblock *gcblock;	/* The block we're currently garbage-collecting */
-
-	struct list_head clean_list;		/* Blocks 100% full of clean data */
-	struct list_head very_dirty_list;	/* Blocks with lots of dirty space */
-	struct list_head dirty_list;		/* Blocks with some dirty space */
-	struct list_head erasable_list;		/* Blocks which are completely dirty, and need erasing */
-	struct list_head erasable_pending_wbuf_list;	/* Blocks which need erasing but only after the current wbuf is flushed */
-	struct list_head erasing_list;		/* Blocks which are currently erasing */
-	struct list_head erase_pending_list;	/* Blocks which need erasing now */
-	struct list_head erase_complete_list;	/* Blocks which are erased and need the clean marker written to them */
-	struct list_head free_list;		/* Blocks which are free and ready to be used */
-	struct list_head bad_list;		/* Bad blocks. */
-	struct list_head bad_used_list;		/* Bad blocks with valid data in. */
-
-	spinlock_t erase_completion_lock;	/* Protect free_list and erasing_list
-						   against erase completion handler */
-	wait_queue_head_t erase_wait;		/* For waiting for erases to complete */
-
-	wait_queue_head_t inocache_wq;
-	struct jffs2_inode_cache **inocache_list;
-	spinlock_t inocache_lock;
-
-	/* Sem to allow jffs2_garbage_collect_deletion_dirent to
-	   drop the erase_completion_lock while it's holding a pointer
-	   to an obsoleted node. I don't like this. Alternatives welcomed. */
-	struct semaphore erase_free_sem;
-
-	uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
-
-#ifdef CONFIG_JFFS2_FS_WRITEBUFFER
-	/* Write-behind buffer for NAND flash */
-	unsigned char *wbuf;
-	uint32_t wbuf_ofs;
-	uint32_t wbuf_len;
-	struct jffs2_inodirty *wbuf_inodes;
-
-	struct rw_semaphore wbuf_sem;	/* Protects the write buffer */
-
-	/* Information about out-of-band area usage... */
-	struct nand_oobinfo *oobinfo;
-	uint32_t badblock_pos;
-	uint32_t fsdata_pos;
-	uint32_t fsdata_len;
-#endif
-
-	struct jffs2_summary *summary;		/* Summary information */
-
-	/* OS-private pointer for getting back to master superblock info */
-	void *os_priv;
-};
-
-#endif /* _JFFS2_FB_SB */
diff --git a/include/linux/joystick.h b/include/linux/joystick.h
index 5fd20dd..e2d3a18 100644
--- a/include/linux/joystick.h
+++ b/include/linux/joystick.h
@@ -111,25 +111,25 @@
 #define JS_SET_ALL		8
 
 struct JS_DATA_TYPE {
-	int32_t buttons;
-	int32_t x;
-	int32_t y;
+	__s32 buttons;
+	__s32 x;
+	__s32 y;
 };
 
 struct JS_DATA_SAVE_TYPE_32 {
-	int32_t JS_TIMEOUT;
-	int32_t BUSY;
-	int32_t JS_EXPIRETIME;
-	int32_t JS_TIMELIMIT;
+	__s32 JS_TIMEOUT;
+	__s32 BUSY;
+	__s32 JS_EXPIRETIME;
+	__s32 JS_TIMELIMIT;
 	struct JS_DATA_TYPE JS_SAVE;
 	struct JS_DATA_TYPE JS_CORR;
 };
 
 struct JS_DATA_SAVE_TYPE_64 {
-	int32_t JS_TIMEOUT;
-	int32_t BUSY;
-	int64_t JS_EXPIRETIME;
-	int64_t JS_TIMELIMIT;
+	__s32 JS_TIMEOUT;
+	__s32 BUSY;
+	__s64 JS_EXPIRETIME;
+	__s64 JS_TIMELIMIT;
 	struct JS_DATA_TYPE JS_SAVE;
 	struct JS_DATA_TYPE JS_CORR;
 };
diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index 9bbd040..54e2549 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -5,7 +5,6 @@
 #ifndef _LINUX_KALLSYMS_H
 #define _LINUX_KALLSYMS_H
 
-#include <linux/config.h>
 
 #define KSYM_NAME_LEN 127
 
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index 4eb851e..efe0ee4 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -155,10 +155,8 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&t->buf.lock, flags);
-	if (t->buf.tail != NULL) {
-		t->buf.tail->active = 0;
+	if (t->buf.tail != NULL)
 		t->buf.tail->commit = t->buf.tail->used;
-	}
 	spin_unlock_irqrestore(&t->buf.lock, flags);
 	schedule_work(&t->buf.work);
 }
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index f4fc576..5c1ec1f 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -24,11 +24,15 @@
 #define LONG_MAX	((long)(~0UL>>1))
 #define LONG_MIN	(-LONG_MAX - 1)
 #define ULONG_MAX	(~0UL)
+#define LLONG_MAX	((long long)(~0ULL>>1))
+#define LLONG_MIN	(-LLONG_MAX - 1)
+#define ULLONG_MAX	(~0ULL)
 
 #define STACK_MAGIC	0xdeadbeef
 
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 #define ALIGN(x,a) (((x)+(a)-1)&~((a)-1))
+#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
 
 #define	KERN_EMERG	"<0>"	/* system is unusable			*/
 #define	KERN_ALERT	"<1>"	/* action must be taken immediately	*/
@@ -75,7 +79,7 @@
 # define might_sleep() do { might_resched(); } while (0)
 #endif
 
-#define might_sleep_if(cond) do { if (unlikely(cond)) might_sleep(); } while (0)
+#define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0)
 
 #define abs(x) ({				\
 		int __x = (x);			\
@@ -114,6 +118,8 @@
 	__attribute__ ((format (printf, 3, 4)));
 extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
 	__attribute__ ((format (printf, 3, 0)));
+extern char *kasprintf(gfp_t gfp, const char *fmt, ...)
+	__attribute__ ((format (printf, 2, 3)));
 
 extern int sscanf(const char *, const char *, ...)
 	__attribute__ ((format (scanf, 2, 3)));
@@ -331,6 +337,12 @@
 /* Force a compilation error if condition is true */
 #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
 
+/* Force a compilation error if condition is true, but also produce a
+   result (of value 0 and type size_t), so the expression can be used
+   e.g. in a structure initializer (or where-ever else comma expressions
+   aren't permitted). */
+#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
+
 /* Trap pasters of __FUNCTION__ at compile-time */
 #define __FUNCTION__ (__func__)
 
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index b462490..43e895f 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_KERNEL_STAT_H
 #define _LINUX_KERNEL_STAT_H
 
-#include <linux/config.h>
 #include <asm/irq.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index cfb3410..6427949 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -106,6 +106,7 @@
 extern void crash_kexec(struct pt_regs *);
 int kexec_should_crash(struct task_struct *);
 extern struct kimage *kexec_image;
+extern struct kimage *kexec_crash_image;
 
 #define KEXEC_ON_CRASH  0x00000001
 #define KEXEC_ARCH_MASK 0xffff0000
diff --git a/include/linux/key.h b/include/linux/key.h
index cbf464a..e693e72 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -205,6 +205,11 @@
 	/* match a key against a description */
 	int (*match)(const struct key *key, const void *desc);
 
+	/* clear some of the data from a key on revokation (optional)
+	 * - the key's semaphore will be write-locked by the caller
+	 */
+	void (*revoke)(struct key *key);
+
 	/* clear the data from a key (optional) */
 	void (*destroy)(struct key *key);
 
@@ -241,8 +246,16 @@
 
 extern struct key *key_alloc(struct key_type *type,
 			     const char *desc,
-			     uid_t uid, gid_t gid, key_perm_t perm,
-			     int not_in_quota);
+			     uid_t uid, gid_t gid,
+			     struct task_struct *ctx,
+			     key_perm_t perm,
+			     unsigned long flags);
+
+
+#define KEY_ALLOC_IN_QUOTA	0x0000	/* add to quota, reject if would overrun */
+#define KEY_ALLOC_QUOTA_OVERRUN	0x0001	/* add to quota, permit even if overrun */
+#define KEY_ALLOC_NOT_IN_QUOTA	0x0002	/* not in quota */
+
 extern int key_payload_reserve(struct key *key, size_t datalen);
 extern int key_instantiate_and_link(struct key *key,
 				    const void *data,
@@ -279,7 +292,7 @@
 				      const char *description,
 				      const void *payload,
 				      size_t plen,
-				      int not_in_quota);
+				      unsigned long flags);
 
 extern int key_update(key_ref_t key,
 		      const void *payload,
@@ -292,7 +305,9 @@
 		      struct key *key);
 
 extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
-				 int not_in_quota, struct key *dest);
+				 struct task_struct *ctx,
+				 unsigned long flags,
+				 struct key *dest);
 
 extern int keyring_clear(struct key *keyring);
 
@@ -313,7 +328,8 @@
  * the userspace interface
  */
 extern struct key root_user_keyring, root_session_keyring;
-extern int alloc_uid_keyring(struct user_struct *user);
+extern int alloc_uid_keyring(struct user_struct *user,
+			     struct task_struct *ctx);
 extern void switch_uid_keyring(struct user_struct *new_user);
 extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
 extern int copy_thread_group_keys(struct task_struct *tsk);
@@ -342,7 +358,7 @@
 #define make_key_ref(k)			({ NULL; })
 #define key_ref_to_ptr(k)		({ NULL; })
 #define is_key_possessed(k)		0
-#define alloc_uid_keyring(u)		0
+#define alloc_uid_keyring(u,c)		0
 #define switch_uid_keyring(u)		do { } while(0)
 #define __install_session_keyring(t, k)	({ NULL; })
 #define copy_keys(f,t)			0
@@ -355,6 +371,10 @@
 #define key_fsgid_changed(t)		do { } while(0)
 #define key_init()			do { } while(0)
 
+/* Initial keyrings */
+extern struct key root_user_keyring;
+extern struct key root_session_keyring;
+
 #endif /* CONFIG_KEYS */
 #endif /* __KERNEL__ */
 #endif /* _LINUX_KEY_H */
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index e4a2315..0db22a1 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -20,7 +20,6 @@
  */
 
 #include <linux/stddef.h>
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/compiler.h>
 
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index c187c53..2d22932 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -190,6 +190,8 @@
 
 /* The global /sys/kernel/ subsystem for people to chain off of */
 extern struct subsystem kernel_subsys;
+/* The global /sys/hypervisor/ subsystem  */
+extern struct subsystem hypervisor_subsys;
 
 /**
  * Helpers for setting the kset of registered objects.
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 778adc0..8bf6702 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,6 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
 #include <linux/smp.h>
diff --git a/include/linux/kthread.h b/include/linux/kthread.h
index ebdd41f..7cce5df 100644
--- a/include/linux/kthread.h
+++ b/include/linux/kthread.h
@@ -4,37 +4,19 @@
 #include <linux/err.h>
 #include <linux/sched.h>
 
-/**
- * kthread_create: create a kthread.
- * @threadfn: the function to run until signal_pending(current).
- * @data: data ptr for @threadfn.
- * @namefmt: printf-style name for the thread.
- *
- * Description: This helper function creates and names a kernel
- * thread.  The thread will be stopped: use wake_up_process() to start
- * it.  See also kthread_run(), kthread_create_on_cpu().
- *
- * When woken, the thread will run @threadfn() with @data as its
- * argument. @threadfn can either call do_exit() directly if it is a
- * standalone thread for which noone will call kthread_stop(), or
- * return when 'kthread_should_stop()' is true (which means
- * kthread_stop() has been called).  The return value should be zero
- * or a negative error number: it will be passed to kthread_stop().
- *
- * Returns a task_struct or ERR_PTR(-ENOMEM).
- */
 struct task_struct *kthread_create(int (*threadfn)(void *data),
 				   void *data,
 				   const char namefmt[], ...);
 
 /**
- * kthread_run: create and wake a thread.
+ * kthread_run - create and wake a thread.
  * @threadfn: the function to run until signal_pending(current).
  * @data: data ptr for @threadfn.
  * @namefmt: printf-style name for the thread.
  *
  * Description: Convenient wrapper for kthread_create() followed by
- * wake_up_process().  Returns the kthread, or ERR_PTR(-ENOMEM). */
+ * wake_up_process().  Returns the kthread or ERR_PTR(-ENOMEM).
+ */
 #define kthread_run(threadfn, data, namefmt, ...)			   \
 ({									   \
 	struct task_struct *__k						   \
@@ -44,50 +26,9 @@
 	__k;								   \
 })
 
-/**
- * kthread_bind: bind a just-created kthread to a cpu.
- * @k: thread created by kthread_create().
- * @cpu: cpu (might not be online, must be possible) for @k to run on.
- *
- * Description: This function is equivalent to set_cpus_allowed(),
- * except that @cpu doesn't need to be online, and the thread must be
- * stopped (ie. just returned from kthread_create().
- */
 void kthread_bind(struct task_struct *k, unsigned int cpu);
-
-/**
- * kthread_stop: stop a thread created by kthread_create().
- * @k: thread created by kthread_create().
- *
- * Sets kthread_should_stop() for @k to return true, wakes it, and
- * waits for it to exit.  Your threadfn() must not call do_exit()
- * itself if you use this function!  This can also be called after
- * kthread_create() instead of calling wake_up_process(): the thread
- * will exit without calling threadfn().
- *
- * Returns the result of threadfn(), or -EINTR if wake_up_process()
- * was never called. */
 int kthread_stop(struct task_struct *k);
-
-/**
- * kthread_stop_sem: stop a thread created by kthread_create().
- * @k: thread created by kthread_create().
- * @s: semaphore that @k waits on while idle.
- *
- * Does essentially the same thing as kthread_stop() above, but wakes
- * @k by calling up(@s).
- *
- * Returns the result of threadfn(), or -EINTR if wake_up_process()
- * was never called. */
 int kthread_stop_sem(struct task_struct *k, struct semaphore *s);
-
-/**
- * kthread_should_stop: should this kthread return now?
- *
- * When someone calls kthread_stop on your kthread, it will be woken
- * and this will return true.  You should then return, and your return
- * value will be passed through to kthread_stop().
- */
 int kthread_should_stop(void);
 
 #endif /* _LINUX_KTHREAD_H */
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 62bc575..ed3396d 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -66,7 +66,6 @@
 
 /**
  * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value
- *
  * @secs:	seconds to set
  * @nsecs:	nanoseconds to set
  *
@@ -138,7 +137,6 @@
 
 /**
  * ktime_sub - subtract two ktime_t variables
- *
  * @lhs:	minuend
  * @rhs:	subtrahend
  *
@@ -157,7 +155,6 @@
 
 /**
  * ktime_add - add two ktime_t variables
- *
  * @add1:	addend1
  * @add2:	addend2
  *
@@ -184,7 +181,6 @@
 
 /**
  * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
- *
  * @kt:		addend
  * @nsec:	the scalar nsec value to add
  *
@@ -194,7 +190,6 @@
 
 /**
  * timespec_to_ktime - convert a timespec to ktime_t format
- *
  * @ts:		the timespec variable to convert
  *
  * Returns a ktime_t variable with the converted timespec value
@@ -207,7 +202,6 @@
 
 /**
  * timeval_to_ktime - convert a timeval to ktime_t format
- *
  * @tv:		the timeval variable to convert
  *
  * Returns a ktime_t variable with the converted timeval value
@@ -220,7 +214,6 @@
 
 /**
  * ktime_to_timespec - convert a ktime_t variable to timespec format
- *
  * @kt:		the ktime_t variable to convert
  *
  * Returns the timespec representation of the ktime value
@@ -233,7 +226,6 @@
 
 /**
  * ktime_to_timeval - convert a ktime_t variable to timeval format
- *
  * @kt:		the ktime_t variable to convert
  *
  * Returns the timeval representation of the ktime value
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b80d2e7..f4284bf 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -30,9 +30,11 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
+#include <asm/scatterlist.h>
 #include <asm/io.h>
 #include <linux/ata.h>
 #include <linux/workqueue.h>
+#include <scsi/scsi_host.h>
 
 /*
  * compile-time options: to be removed as soon as all the drivers are
@@ -44,7 +46,6 @@
 #undef ATA_NDEBUG		/* define to disable quick runtime checks */
 #undef ATA_ENABLE_PATA		/* define to enable PATA support in some
 				 * low-level drivers */
-#undef ATAPI_ENABLE_DMADIR	/* enables ATAPI DMADIR bridge support */
 
 
 /* note: prints function name for you */
@@ -108,8 +109,11 @@
 	LIBATA_MAX_PRD		= ATA_MAX_PRD / 2,
 	ATA_MAX_PORTS		= 8,
 	ATA_DEF_QUEUE		= 1,
-	ATA_MAX_QUEUE		= 1,
+	/* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */
+	ATA_MAX_QUEUE		= 32,
+	ATA_TAG_INTERNAL	= ATA_MAX_QUEUE - 1,
 	ATA_MAX_SECTORS		= 200,	/* FIXME */
+	ATA_MAX_SECTORS_LBA48	= 65535,
 	ATA_MAX_BUS		= 2,
 	ATA_DEF_BUSY_WAIT	= 10000,
 	ATA_SHORT_PAUSE		= (HZ >> 6) + 1,
@@ -120,9 +124,17 @@
 	ATA_SHT_USE_CLUSTERING	= 1,
 
 	/* struct ata_device stuff */
-	ATA_DFLAG_LBA48		= (1 << 0), /* device supports LBA48 */
-	ATA_DFLAG_PIO		= (1 << 1), /* device currently in PIO mode */
-	ATA_DFLAG_LBA		= (1 << 2), /* device supports LBA */
+	ATA_DFLAG_LBA		= (1 << 0), /* device supports LBA */
+	ATA_DFLAG_LBA48		= (1 << 1), /* device supports LBA48 */
+	ATA_DFLAG_CDB_INTR	= (1 << 2), /* device asserts INTRQ when ready for CDB */
+	ATA_DFLAG_NCQ		= (1 << 3), /* device supports NCQ */
+	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
+
+	ATA_DFLAG_PIO		= (1 << 8), /* device currently in PIO mode */
+	ATA_DFLAG_INIT_MASK	= (1 << 16) - 1,
+
+	ATA_DFLAG_DETACH	= (1 << 16),
+	ATA_DFLAG_DETACHED	= (1 << 17),
 
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
@@ -132,43 +144,57 @@
 	ATA_DEV_NONE		= 5,	/* no device */
 
 	/* struct ata_port flags */
-	ATA_FLAG_SLAVE_POSS	= (1 << 1), /* host supports slave dev */
+	ATA_FLAG_SLAVE_POSS	= (1 << 0), /* host supports slave dev */
 					    /* (doesn't imply presence) */
-	ATA_FLAG_PORT_DISABLED	= (1 << 2), /* port is disabled, ignore it */
-	ATA_FLAG_SATA		= (1 << 3),
-	ATA_FLAG_NO_LEGACY	= (1 << 4), /* no legacy mode check */
-	ATA_FLAG_SRST		= (1 << 5), /* (obsolete) use ATA SRST, not E.D.D. */
-	ATA_FLAG_MMIO		= (1 << 6), /* use MMIO, not PIO */
-	ATA_FLAG_SATA_RESET	= (1 << 7), /* (obsolete) use COMRESET */
-	ATA_FLAG_PIO_DMA	= (1 << 8), /* PIO cmds via DMA */
-	ATA_FLAG_NOINTR		= (1 << 9), /* FIXME: Remove this once
-					     * proper HSM is in place. */
-	ATA_FLAG_DEBUGMSG	= (1 << 10),
-	ATA_FLAG_NO_ATAPI	= (1 << 11), /* No ATAPI support */
+	ATA_FLAG_SATA		= (1 << 1),
+	ATA_FLAG_NO_LEGACY	= (1 << 2), /* no legacy mode check */
+	ATA_FLAG_MMIO		= (1 << 3), /* use MMIO, not PIO */
+	ATA_FLAG_SRST		= (1 << 4), /* (obsolete) use ATA SRST, not E.D.D. */
+	ATA_FLAG_SATA_RESET	= (1 << 5), /* (obsolete) use COMRESET */
+	ATA_FLAG_NO_ATAPI	= (1 << 6), /* No ATAPI support */
+	ATA_FLAG_PIO_DMA	= (1 << 7), /* PIO cmds via DMA */
+	ATA_FLAG_PIO_LBA48	= (1 << 8), /* Host DMA engine is LBA28 only */
+	ATA_FLAG_PIO_POLLING	= (1 << 9), /* use polling PIO if LLD
+					     * doesn't handle PIO interrupts */
+	ATA_FLAG_NCQ		= (1 << 10), /* host supports NCQ */
+	ATA_FLAG_HRST_TO_RESUME	= (1 << 11), /* hardreset to resume phy */
+	ATA_FLAG_SKIP_D2H_BSY	= (1 << 12), /* can't wait for the first D2H
+					      * Register FIS clearing BSY */
 
-	ATA_FLAG_SUSPENDED	= (1 << 12), /* port is suspended */
+	ATA_FLAG_DEBUGMSG	= (1 << 13),
+	ATA_FLAG_FLUSH_PORT_TASK = (1 << 14), /* flush port task */
 
-	ATA_FLAG_PIO_LBA48	= (1 << 13), /* Host DMA engine is LBA28 only */
-	ATA_FLAG_IRQ_MASK	= (1 << 14), /* Mask IRQ in PIO xfers */
+	ATA_FLAG_EH_PENDING	= (1 << 15), /* EH pending */
+	ATA_FLAG_EH_IN_PROGRESS	= (1 << 16), /* EH in progress */
+	ATA_FLAG_FROZEN		= (1 << 17), /* port is frozen */
+	ATA_FLAG_RECOVERED	= (1 << 18), /* recovery action performed */
+	ATA_FLAG_LOADING	= (1 << 19), /* boot/loading probe */
+	ATA_FLAG_UNLOADING	= (1 << 20), /* module is unloading */
+	ATA_FLAG_SCSI_HOTPLUG	= (1 << 21), /* SCSI hotplug scheduled */
 
-	ATA_FLAG_FLUSH_PORT_TASK = (1 << 15), /* Flush port task */
-	ATA_FLAG_IN_EH		= (1 << 16), /* EH in progress */
+	ATA_FLAG_DISABLED	= (1 << 22), /* port is disabled, ignore it */
+	ATA_FLAG_SUSPENDED	= (1 << 23), /* port is suspended (power) */
 
-	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
-	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
-	ATA_QCFLAG_SINGLE	= (1 << 4), /* no s/g, just a single buffer */
+	/* bits 24:31 of ap->flags are reserved for LLDD specific flags */
+
+	/* struct ata_queued_cmd flags */
+	ATA_QCFLAG_ACTIVE	= (1 << 0), /* cmd not yet ack'd to scsi lyer */
+	ATA_QCFLAG_SG		= (1 << 1), /* have s/g table? */
+	ATA_QCFLAG_SINGLE	= (1 << 2), /* no s/g, just a single buffer */
 	ATA_QCFLAG_DMAMAP	= ATA_QCFLAG_SG | ATA_QCFLAG_SINGLE,
-	ATA_QCFLAG_EH_SCHEDULED = (1 << 5), /* EH scheduled */
+	ATA_QCFLAG_IO		= (1 << 3), /* standard IO command */
+	ATA_QCFLAG_RESULT_TF	= (1 << 4), /* result TF requested */
+
+	ATA_QCFLAG_FAILED	= (1 << 16), /* cmd failed and is owned by EH */
+	ATA_QCFLAG_SENSE_VALID	= (1 << 17), /* sense data valid */
+	ATA_QCFLAG_EH_SCHEDULED = (1 << 18), /* EH scheduled (obsolete) */
 
 	/* host set flags */
 	ATA_HOST_SIMPLEX	= (1 << 0),	/* Host is simplex, one DMA channel per host_set only */
 	
 	/* various lengths of time */
-	ATA_TMOUT_PIO		= 30 * HZ,
 	ATA_TMOUT_BOOT		= 30 * HZ,	/* heuristic */
 	ATA_TMOUT_BOOT_QUICK	= 7 * HZ,	/* heuristic */
-	ATA_TMOUT_CDB		= 30 * HZ,
-	ATA_TMOUT_CDB_QUICK	= 5 * HZ,
 	ATA_TMOUT_INTERNAL	= 30 * HZ,
 	ATA_TMOUT_INTERNAL_QUICK = 5 * HZ,
 
@@ -207,21 +233,56 @@
 	/* size of buffer to pad xfers ending on unaligned boundaries */
 	ATA_DMA_PAD_SZ		= 4,
 	ATA_DMA_PAD_BUF_SZ	= ATA_DMA_PAD_SZ * ATA_MAX_QUEUE,
-	
-	/* Masks for port functions */
+
+	/* masks for port functions */
 	ATA_PORT_PRIMARY	= (1 << 0),
 	ATA_PORT_SECONDARY	= (1 << 1),
+
+	/* ering size */
+	ATA_ERING_SIZE		= 32,
+
+	/* desc_len for ata_eh_info and context */
+	ATA_EH_DESC_LEN		= 80,
+
+	/* reset / recovery action types */
+	ATA_EH_REVALIDATE	= (1 << 0),
+	ATA_EH_SOFTRESET	= (1 << 1),
+	ATA_EH_HARDRESET	= (1 << 2),
+
+	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
+	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+
+	/* ata_eh_info->flags */
+	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
+
+	ATA_EHI_DID_RESET	= (1 << 16), /* already reset this port */
+
+	/* max repeat if error condition is still set after ->error_handler */
+	ATA_EH_MAX_REPEAT	= 5,
+
+	/* how hard are we gonna try to probe/recover devices */
+	ATA_PROBE_MAX_TRIES	= 3,
+	ATA_EH_RESET_TRIES	= 3,
+	ATA_EH_DEV_TRIES	= 3,
+
+	/* Drive spinup time (time from power-on to the first D2H FIS)
+	 * in msecs - 8s currently.  Failing to get ready in this time
+	 * isn't critical.  It will result in reset failure for
+	 * controllers which can't wait for the first D2H FIS.  libata
+	 * will retry, so it just has to be long enough to spin up
+	 * most devices.
+	 */
+	ATA_SPINUP_WAIT		= 8000,
 };
 
 enum hsm_task_states {
-	HSM_ST_UNKNOWN,
-	HSM_ST_IDLE,
-	HSM_ST_POLL,
-	HSM_ST_TMOUT,
-	HSM_ST,
-	HSM_ST_LAST,
-	HSM_ST_LAST_POLL,
-	HSM_ST_ERR,
+	HSM_ST_UNKNOWN,		/* state unknown */
+	HSM_ST_IDLE,		/* no command on going */
+	HSM_ST,			/* (waiting the device to) transfer data */
+	HSM_ST_LAST,		/* (waiting the device to) complete command */
+	HSM_ST_ERR,		/* error */
+	HSM_ST_FIRST,		/* (waiting the device to)
+				   write CDB or first data block */
 };
 
 enum ata_completion_errors {
@@ -244,9 +305,9 @@
 
 /* typedefs */
 typedef void (*ata_qc_cb_t) (struct ata_queued_cmd *qc);
-typedef void (*ata_probeinit_fn_t)(struct ata_port *);
-typedef int (*ata_reset_fn_t)(struct ata_port *, int, unsigned int *);
-typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *);
+typedef int (*ata_prereset_fn_t)(struct ata_port *ap);
+typedef int (*ata_reset_fn_t)(struct ata_port *ap, unsigned int *classes);
+typedef void (*ata_postreset_fn_t)(struct ata_port *ap, unsigned int *classes);
 
 struct ata_ioports {
 	unsigned long		cmd_addr;
@@ -297,7 +358,8 @@
 	unsigned long		flags;
 	int			simplex_claimed;	/* Keep seperate in case we
 							   ever need to do this locked */
-	struct ata_port *	ports[0];
+	struct ata_host_set	*next;		/* for legacy mode */
+	struct ata_port		*ports[0];
 };
 
 struct ata_queued_cmd {
@@ -336,7 +398,7 @@
 	struct scatterlist	*__sg;
 
 	unsigned int		err_mask;
-
+	struct ata_taskfile	result_tf;
 	ata_qc_cb_t		complete_fn;
 
 	void			*private_data;
@@ -348,12 +410,26 @@
 	unsigned long		rw_reqbuf;
 };
 
+struct ata_ering_entry {
+	int			is_io;
+	unsigned int		err_mask;
+	u64			timestamp;
+};
+
+struct ata_ering {
+	int			cursor;
+	struct ata_ering_entry	ring[ATA_ERING_SIZE];
+};
+
 struct ata_device {
-	u64			n_sectors;	/* size of device, if ATA */
-	unsigned long		flags;		/* ATA_DFLAG_xxx */
-	unsigned int		class;		/* ATA_DEV_xxx */
+	struct ata_port		*ap;
 	unsigned int		devno;		/* 0 or 1 */
-	u16			*id;		/* IDENTIFY xxx DEVICE data */
+	unsigned long		flags;		/* ATA_DFLAG_xxx */
+	struct scsi_device	*sdev;		/* attached SCSI device */
+	/* n_sector is used as CLEAR_OFFSET, read comment above CLEAR_OFFSET */
+	u64			n_sectors;	/* size of device, if ATA */
+	unsigned int		class;		/* ATA_DEV_xxx */
+	u16			id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
 	u8			pio_mode;
 	u8			dma_mode;
 	u8			xfer_mode;
@@ -373,11 +449,42 @@
 	u16			cylinders;	/* Number of cylinders */
 	u16			heads;		/* Number of heads */
 	u16			sectors;	/* Number of sectors per track */
+
+	/* error history */
+	struct ata_ering	ering;
+};
+
+/* Offset into struct ata_device.  Fields above it are maintained
+ * acress device init.  Fields below are zeroed.
+ */
+#define ATA_DEVICE_CLEAR_OFFSET		offsetof(struct ata_device, n_sectors)
+
+struct ata_eh_info {
+	struct ata_device	*dev;		/* offending device */
+	u32			serror;		/* SError from LLDD */
+	unsigned int		err_mask;	/* port-wide err_mask */
+	unsigned int		action;		/* ATA_EH_* action mask */
+	unsigned int		dev_action[ATA_MAX_DEVICES]; /* dev EH action */
+	unsigned int		flags;		/* ATA_EHI_* flags */
+
+	unsigned long		hotplug_timestamp;
+	unsigned int		probe_mask;
+
+	char			desc[ATA_EH_DESC_LEN];
+	int			desc_len;
+};
+
+struct ata_eh_context {
+	struct ata_eh_info	i;
+	int			tries[ATA_MAX_DEVICES];
+	unsigned int		classes[ATA_MAX_DEVICES];
+	unsigned int		did_probe_mask;
 };
 
 struct ata_port {
 	struct Scsi_Host	*host;	/* our co-allocated scsi host */
 	const struct ata_port_operations *ops;
+	spinlock_t		*lock;
 	unsigned long		flags;	/* ATA_FLAG_xxx */
 	unsigned int		id;	/* unique id req'd by scsi midlyr */
 	unsigned int		port_no; /* unique port #; from zero */
@@ -397,26 +504,40 @@
 	unsigned int		mwdma_mask;
 	unsigned int		udma_mask;
 	unsigned int		cbl;	/* cable type; ATA_CBL_xxx */
+	unsigned int		hw_sata_spd_limit;
+	unsigned int		sata_spd_limit;	/* SATA PHY speed limit */
+
+	/* record runtime error info, protected by host_set lock */
+	struct ata_eh_info	eh_info;
+	/* EH context owned by EH */
+	struct ata_eh_context	eh_context;
 
 	struct ata_device	device[ATA_MAX_DEVICES];
 
 	struct ata_queued_cmd	qcmd[ATA_MAX_QUEUE];
-	unsigned long		qactive;
+	unsigned long		qc_allocated;
+	unsigned int		qc_active;
+
 	unsigned int		active_tag;
+	u32			sactive;
 
 	struct ata_host_stats	stats;
 	struct ata_host_set	*host_set;
 	struct device 		*dev;
 
 	struct work_struct	port_task;
+	struct work_struct	hotplug_task;
+	struct work_struct	scsi_rescan_task;
 
 	unsigned int		hsm_task_state;
-	unsigned long		pio_task_timeout;
 
 	u32			msg_enable;
 	struct list_head	eh_done_q;
+	wait_queue_head_t	eh_wait_q;
 
 	void			*private_data;
+
+	u8			sector_buf[ATA_SECT_SIZE]; /* owned by EH */
 };
 
 struct ata_port_operations {
@@ -438,7 +559,6 @@
 
 	void (*phy_reset) (struct ata_port *ap); /* obsolete */
 	void (*set_mode) (struct ata_port *ap);
-	int (*probe_reset) (struct ata_port *ap, unsigned int *classes);
 
 	void (*post_set_mode) (struct ata_port *ap);
 
@@ -447,10 +567,20 @@
 	void (*bmdma_setup) (struct ata_queued_cmd *qc);
 	void (*bmdma_start) (struct ata_queued_cmd *qc);
 
+	void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
+
 	void (*qc_prep) (struct ata_queued_cmd *qc);
 	unsigned int (*qc_issue) (struct ata_queued_cmd *qc);
 
-	void (*eng_timeout) (struct ata_port *ap);
+	/* Error handlers.  ->error_handler overrides ->eng_timeout and
+	 * indicates that new-style EH is in place.
+	 */
+	void (*eng_timeout) (struct ata_port *ap); /* obsolete */
+
+	void (*freeze) (struct ata_port *ap);
+	void (*thaw) (struct ata_port *ap);
+	void (*error_handler) (struct ata_port *ap);
+	void (*post_internal_cmd) (struct ata_queued_cmd *qc);
 
 	irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
 	void (*irq_clear) (struct ata_port *);
@@ -492,22 +622,22 @@
 
 #define FIT(v,vmin,vmax)	max_t(short,min_t(short,v,vmax),vmin)
 
+extern const unsigned long sata_deb_timing_boot[];
+extern const unsigned long sata_deb_timing_eh[];
+extern const unsigned long sata_deb_timing_before_fsrst[];
+
 extern void ata_port_probe(struct ata_port *);
 extern void __sata_phy_reset(struct ata_port *ap);
 extern void sata_phy_reset(struct ata_port *ap);
 extern void ata_bus_reset(struct ata_port *ap);
-extern int ata_drive_probe_reset(struct ata_port *ap,
-			ata_probeinit_fn_t probeinit,
-			ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-			ata_postreset_fn_t postreset, unsigned int *classes);
-extern void ata_std_probeinit(struct ata_port *ap);
-extern int ata_std_softreset(struct ata_port *ap, int verbose,
-			     unsigned int *classes);
-extern int sata_std_hardreset(struct ata_port *ap, int verbose,
-			      unsigned int *class);
+extern int sata_set_spd(struct ata_port *ap);
+extern int sata_phy_debounce(struct ata_port *ap, const unsigned long *param);
+extern int sata_phy_resume(struct ata_port *ap, const unsigned long *param);
+extern int ata_std_prereset(struct ata_port *ap);
+extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes);
+extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class);
 extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes);
-extern int ata_dev_revalidate(struct ata_port *ap, struct ata_device *dev,
-			      int post_reset);
+extern int ata_dev_revalidate(struct ata_device *dev, int post_reset);
 extern void ata_port_disable(struct ata_port *);
 extern void ata_std_ports(struct ata_ioports *ioaddr);
 #ifdef CONFIG_PCI
@@ -519,24 +649,32 @@
 extern int ata_pci_clear_simplex(struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
 extern int ata_device_add(const struct ata_probe_ent *ent);
+extern void ata_port_detach(struct ata_port *ap);
 extern void ata_host_set_remove(struct ata_host_set *host_set);
 extern int ata_scsi_detect(struct scsi_host_template *sht);
 extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
 extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
-extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
-extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
 extern int ata_scsi_release(struct Scsi_Host *host);
 extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+extern int sata_scr_valid(struct ata_port *ap);
+extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val);
+extern int sata_scr_write(struct ata_port *ap, int reg, u32 val);
+extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val);
+extern int ata_port_online(struct ata_port *ap);
+extern int ata_port_offline(struct ata_port *ap);
 extern int ata_scsi_device_resume(struct scsi_device *);
 extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
-extern int ata_device_resume(struct ata_port *, struct ata_device *);
-extern int ata_device_suspend(struct ata_port *, struct ata_device *, pm_message_t state);
+extern int ata_device_resume(struct ata_device *);
+extern int ata_device_suspend(struct ata_device *, pm_message_t state);
 extern int ata_ratelimit(void);
 extern unsigned int ata_busy_sleep(struct ata_port *ap,
 				   unsigned long timeout_pat,
 				   unsigned long timeout);
 extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
 				void *data, unsigned long delay);
+extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
+			     unsigned long interval_msec,
+			     unsigned long timeout_msec);
 
 /*
  * Default driver ops implementations
@@ -550,11 +688,16 @@
 extern u8 ata_check_status(struct ata_port *ap);
 extern u8 ata_altstatus(struct ata_port *ap);
 extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
-extern int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern void ata_host_stop (struct ata_host_set *host_set);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+extern void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
+			       unsigned int buflen, int write_data);
+extern void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
+			      unsigned int buflen, int write_data);
+extern void ata_pio_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
+			      unsigned int buflen, int write_data);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);
 extern unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -572,17 +715,29 @@
 extern void ata_bmdma_stop(struct ata_queued_cmd *qc);
 extern u8   ata_bmdma_status(struct ata_port *ap);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
-extern void __ata_qc_complete(struct ata_queued_cmd *qc);
-extern void ata_eng_timeout(struct ata_port *ap);
-extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
-			      struct scsi_cmnd *cmd,
+extern void ata_bmdma_freeze(struct ata_port *ap);
+extern void ata_bmdma_thaw(struct ata_port *ap);
+extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+			       ata_reset_fn_t softreset,
+			       ata_reset_fn_t hardreset,
+			       ata_postreset_fn_t postreset);
+extern void ata_bmdma_error_handler(struct ata_port *ap);
+extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
+extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
+			u8 status, int in_wq);
+extern void ata_qc_complete(struct ata_queued_cmd *qc);
+extern int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+				    void (*finish_qc)(struct ata_queued_cmd *));
+extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
 			      void (*done)(struct scsi_cmnd *));
 extern int ata_std_bios_param(struct scsi_device *sdev,
 			      struct block_device *bdev,
 			      sector_t capacity, int geom[]);
 extern int ata_scsi_slave_config(struct scsi_device *sdev);
-extern struct ata_device *ata_dev_pair(struct ata_port *ap, 
-				       struct ata_device *adev);
+extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
+extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
+				       int queue_depth);
+extern struct ata_device *ata_dev_pair(struct ata_device *adev);
 
 /*
  * Timing helpers
@@ -628,7 +783,64 @@
 extern unsigned long ata_pci_default_filter(const struct ata_port *, struct ata_device *, unsigned long);
 #endif /* CONFIG_PCI */
 
+/*
+ * EH
+ */
+extern void ata_eng_timeout(struct ata_port *ap);
 
+extern void ata_port_schedule_eh(struct ata_port *ap);
+extern int ata_port_abort(struct ata_port *ap);
+extern int ata_port_freeze(struct ata_port *ap);
+
+extern void ata_eh_freeze_port(struct ata_port *ap);
+extern void ata_eh_thaw_port(struct ata_port *ap);
+
+extern void ata_eh_qc_complete(struct ata_queued_cmd *qc);
+extern void ata_eh_qc_retry(struct ata_queued_cmd *qc);
+
+extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+		      ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+		      ata_postreset_fn_t postreset);
+
+/*
+ * printk helpers
+ */
+#define ata_port_printk(ap, lv, fmt, args...) \
+	printk(lv"ata%u: "fmt, (ap)->id , ##args)
+
+#define ata_dev_printk(dev, lv, fmt, args...) \
+	printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args)
+
+/*
+ * ata_eh_info helpers
+ */
+#define ata_ehi_push_desc(ehi, fmt, args...) do { \
+	(ehi)->desc_len += scnprintf((ehi)->desc + (ehi)->desc_len, \
+				     ATA_EH_DESC_LEN - (ehi)->desc_len, \
+				     fmt , ##args); \
+} while (0)
+
+#define ata_ehi_clear_desc(ehi) do { \
+	(ehi)->desc[0] = '\0'; \
+	(ehi)->desc_len = 0; \
+} while (0)
+
+static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
+{
+	if (ehi->flags & ATA_EHI_HOTPLUGGED)
+		return;
+
+	ehi->flags |= ATA_EHI_HOTPLUGGED;
+	ehi->hotplug_timestamp = jiffies;
+
+	ehi->err_mask |= AC_ERR_ATA_BUS;
+	ehi->action |= ATA_EH_SOFTRESET;
+	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
+}
+
+/*
+ * qc helpers
+ */
 static inline int
 ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc)
 {
@@ -671,16 +883,55 @@
 	return (tag < ATA_MAX_QUEUE) ? 1 : 0;
 }
 
-static inline unsigned int ata_class_present(unsigned int class)
+static inline unsigned int ata_tag_internal(unsigned int tag)
+{
+	return tag == ATA_MAX_QUEUE - 1;
+}
+
+/*
+ * device helpers
+ */
+static inline unsigned int ata_class_enabled(unsigned int class)
 {
 	return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
 }
 
-static inline unsigned int ata_dev_present(const struct ata_device *dev)
+static inline unsigned int ata_class_disabled(unsigned int class)
 {
-	return ata_class_present(dev->class);
+	return class == ATA_DEV_ATA_UNSUP || class == ATA_DEV_ATAPI_UNSUP;
 }
 
+static inline unsigned int ata_class_absent(unsigned int class)
+{
+	return !ata_class_enabled(class) && !ata_class_disabled(class);
+}
+
+static inline unsigned int ata_dev_enabled(const struct ata_device *dev)
+{
+	return ata_class_enabled(dev->class);
+}
+
+static inline unsigned int ata_dev_disabled(const struct ata_device *dev)
+{
+	return ata_class_disabled(dev->class);
+}
+
+static inline unsigned int ata_dev_absent(const struct ata_device *dev)
+{
+	return ata_class_absent(dev->class);
+}
+
+/*
+ * port helpers
+ */
+static inline int ata_port_max_devices(const struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_SLAVE_POSS)
+		return 2;
+	return 1;
+}
+
+
 static inline u8 ata_chk_status(struct ata_port *ap)
 {
 	return ap->ops->check_status(ap);
@@ -759,20 +1010,35 @@
 	qc->tf.ctl |= ATA_NIEN;
 }
 
-static inline struct ata_queued_cmd *ata_qc_from_tag (struct ata_port *ap,
-						      unsigned int tag)
+static inline struct ata_queued_cmd *__ata_qc_from_tag(struct ata_port *ap,
+						       unsigned int tag)
 {
 	if (likely(ata_tag_valid(tag)))
 		return &ap->qcmd[tag];
 	return NULL;
 }
 
-static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, unsigned int device)
+static inline struct ata_queued_cmd *ata_qc_from_tag(struct ata_port *ap,
+						     unsigned int tag)
+{
+	struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
+
+	if (unlikely(!qc) || !ap->ops->error_handler)
+		return qc;
+
+	if ((qc->flags & (ATA_QCFLAG_ACTIVE |
+			  ATA_QCFLAG_FAILED)) == ATA_QCFLAG_ACTIVE)
+		return qc;
+
+	return NULL;
+}
+
+static inline void ata_tf_init(struct ata_device *dev, struct ata_taskfile *tf)
 {
 	memset(tf, 0, sizeof(*tf));
 
-	tf->ctl = ap->ctl;
-	if (device == 0)
+	tf->ctl = dev->ap->ctl;
+	if (dev->devno == 0)
 		tf->device = ATA_DEVICE_OBS;
 	else
 		tf->device = ATA_DEVICE_OBS | ATA_DEV1;
@@ -787,26 +1053,11 @@
 	qc->nbytes = qc->curbytes = 0;
 	qc->err_mask = 0;
 
-	ata_tf_init(qc->ap, &qc->tf, qc->dev->devno);
-}
+	ata_tf_init(qc->dev, &qc->tf);
 
-/**
- *	ata_qc_complete - Complete an active ATA command
- *	@qc: Command to complete
- *	@err_mask: ATA Status register contents
- *
- *	Indicate to the mid and upper layers that an ATA
- *	command has completed, with either an ok or not-ok status.
- *
- *	LOCKING:
- *	spin_lock_irqsave(host_set lock)
- */
-static inline void ata_qc_complete(struct ata_queued_cmd *qc)
-{
-	if (unlikely(qc->flags & ATA_QCFLAG_EH_SCHEDULED))
-		return;
-
-	__ata_qc_complete(qc);
+	/* init result_tf such that it indicates normal completion */
+	qc->result_tf.command = ATA_DRDY;
+	qc->result_tf.feature = 0;
 }
 
 /**
@@ -885,28 +1136,6 @@
 	return status;
 }
 
-static inline u32 scr_read(struct ata_port *ap, unsigned int reg)
-{
-	return ap->ops->scr_read(ap, reg);
-}
-
-static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val)
-{
-	ap->ops->scr_write(ap, reg, val);
-}
-
-static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
-				   u32 val)
-{
-	ap->ops->scr_write(ap, reg, val);
-	(void) ap->ops->scr_read(ap, reg);
-}
-
-static inline unsigned int sata_dev_present(struct ata_port *ap)
-{
-	return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
-}
-
 static inline int ata_try_flush_cache(const struct ata_device *dev)
 {
 	return ata_id_wcache_enabled(dev->id) ||
@@ -916,7 +1145,7 @@
 
 static inline unsigned int ac_err_mask(u8 status)
 {
-	if (status & ATA_BUSY)
+	if (status & (ATA_BUSY | ATA_DRQ))
 		return AC_ERR_HSM;
 	if (status & (ATA_ERR | ATA_DF))
 		return AC_ERR_DEV;
@@ -944,4 +1173,9 @@
 	dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma);
 }
 
+static inline struct ata_port *ata_shost_to_port(struct Scsi_Host *host)
+{
+	return (struct ata_port *) &host->hostdata[0];
+}
+
 #endif /* __LINUX_LIBATA_H__ */
diff --git a/include/linux/license.h b/include/linux/license.h
new file mode 100644
index 0000000..decdbf4
--- /dev/null
+++ b/include/linux/license.h
@@ -0,0 +1,14 @@
+#ifndef __LICENSE_H
+#define __LICENSE_H
+
+static inline int license_is_gpl_compatible(const char *license)
+{
+	return (strcmp(license, "GPL") == 0
+		|| strcmp(license, "GPL v2") == 0
+		|| strcmp(license, "GPL and additional rights") == 0
+		|| strcmp(license, "Dual BSD/GPL") == 0
+		|| strcmp(license, "Dual MIT/GPL") == 0
+		|| strcmp(license, "Dual MPL/GPL") == 0);
+}
+
+#endif
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index c08c998..932021f 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_LINKAGE_H
 #define _LINUX_LINKAGE_H
 
-#include <linux/config.h>
 #include <asm/linkage.h>
 
 #ifdef __cplusplus
diff --git a/include/linux/list.h b/include/linux/list.h
index 76f0571..6b74adf 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -4,18 +4,11 @@
 #ifdef __KERNEL__
 
 #include <linux/stddef.h>
+#include <linux/poison.h>
 #include <linux/prefetch.h>
 #include <asm/system.h>
 
 /*
- * These are non-NULL pointers that will result in page faults
- * under normal circumstances, used to verify that nobody uses
- * non-initialized list entries.
- */
-#define LIST_POISON1  ((void *) 0x00100100)
-#define LIST_POISON2  ((void *) 0x00200200)
-
-/*
  * Simple doubly linked list implementation.
  *
  * Some of the internal functions ("__xxx") are useful when
@@ -197,12 +190,35 @@
 	entry->prev = LIST_POISON2;
 }
 
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ * Note: if 'old' was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+				struct list_head *new)
+{
+	new->next = old->next;
+	new->next->prev = new;
+	new->prev = old->prev;
+	new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+					struct list_head *new)
+{
+	list_replace(old, new);
+	INIT_LIST_HEAD(old);
+}
+
 /*
  * list_replace_rcu - replace old entry by new one
  * @old : the element to be replaced
  * @new : the new element to insert
  *
  * The old entry will be replaced with the new entry atomically.
+ * Note: 'old' should not be empty.
  */
 static inline void list_replace_rcu(struct list_head *old,
 				struct list_head *new)
@@ -258,16 +274,17 @@
 }
 
 /**
- * list_empty_careful - tests whether a list is
- * empty _and_ checks that no other CPU might be
- * in the process of still modifying either member
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
  *
  * NOTE: using list_empty_careful() without synchronization
  * can only be safe if the only activity that can happen
  * to the list entry is list_del_init(). Eg. it cannot be used
  * if another CPU could re-list_add() it.
- *
- * @head: the list to test.
  */
 static inline int list_empty_careful(const struct list_head *head)
 {
@@ -327,7 +344,7 @@
 
 /**
  * list_for_each	-	iterate over a list
- * @pos:	the &struct list_head to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
  */
 #define list_for_each(pos, head) \
@@ -336,7 +353,7 @@
 
 /**
  * __list_for_each	-	iterate over a list
- * @pos:	the &struct list_head to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
  *
  * This variant differs from list_for_each() in that it's the
@@ -349,7 +366,7 @@
 
 /**
  * list_for_each_prev	-	iterate over a list backwards
- * @pos:	the &struct list_head to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
  */
 #define list_for_each_prev(pos, head) \
@@ -357,8 +374,8 @@
         	pos = pos->prev)
 
 /**
- * list_for_each_safe	-	iterate over a list safe against removal of list entry
- * @pos:	the &struct list_head to use as a loop counter.
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop cursor.
  * @n:		another &struct list_head to use as temporary storage
  * @head:	the head for your list.
  */
@@ -368,7 +385,7 @@
 
 /**
  * list_for_each_entry	-	iterate over list of given type
- * @pos:	the type * to use as a loop counter.
+ * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
  */
@@ -379,7 +396,7 @@
 
 /**
  * list_for_each_entry_reverse - iterate backwards over list of given type.
- * @pos:	the type * to use as a loop counter.
+ * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
  */
@@ -389,21 +406,24 @@
 	     pos = list_entry(pos->member.prev, typeof(*pos), member))
 
 /**
- * list_prepare_entry - prepare a pos entry for use as a start point in
- *			list_for_each_entry_continue
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue
  * @pos:	the type * to use as a start point
  * @head:	the head of the list
  * @member:	the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue.
  */
 #define list_prepare_entry(pos, head, member) \
 	((pos) ? : list_entry(head, typeof(*pos), member))
 
 /**
- * list_for_each_entry_continue -	iterate over list of given type
- *			continuing after existing point
- * @pos:	the type * to use as a loop counter.
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
  */
 #define list_for_each_entry_continue(pos, head, member) 		\
 	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
@@ -411,11 +431,12 @@
 	     pos = list_entry(pos->member.next, typeof(*pos), member))
 
 /**
- * list_for_each_entry_from -	iterate over list of given type
- *			continuing from existing point
- * @pos:	the type * to use as a loop counter.
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
  */
 #define list_for_each_entry_from(pos, head, member) 			\
 	for (; prefetch(pos->member.next), &pos->member != (head);	\
@@ -423,7 +444,7 @@
 
 /**
  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @pos:	the type * to use as a loop counter.
+ * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
@@ -435,12 +456,14 @@
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /**
- * list_for_each_entry_safe_continue -	iterate over list of given type
- *			continuing after existing point safe against removal of list entry
- * @pos:	the type * to use as a loop counter.
+ * list_for_each_entry_safe_continue
+ * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
  */
 #define list_for_each_entry_safe_continue(pos, n, head, member) 		\
 	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
@@ -449,12 +472,14 @@
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /**
- * list_for_each_entry_safe_from - iterate over list of given type
- *			from existing point safe against removal of list entry
- * @pos:	the type * to use as a loop counter.
+ * list_for_each_entry_safe_from
+ * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
  */
 #define list_for_each_entry_safe_from(pos, n, head, member) 			\
 	for (n = list_entry(pos->member.next, typeof(*pos), member);		\
@@ -462,12 +487,14 @@
 	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
 
 /**
- * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
- *				      removal of list entry
- * @pos:	the type * to use as a loop counter.
+ * list_for_each_entry_safe_reverse
+ * @pos:	the type * to use as a loop cursor.
  * @n:		another type * to use as temporary storage
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
  */
 #define list_for_each_entry_safe_reverse(pos, n, head, member)		\
 	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
@@ -477,7 +504,7 @@
 
 /**
  * list_for_each_rcu	-	iterate over an rcu-protected list
- * @pos:	the &struct list_head to use as a loop counter.
+ * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
  *
  * This list-traversal primitive may safely run concurrently with
@@ -495,12 +522,13 @@
         	pos = pos->next)
 
 /**
- * list_for_each_safe_rcu	-	iterate over an rcu-protected list safe
- *					against removal of list entry
- * @pos:	the &struct list_head to use as a loop counter.
+ * list_for_each_safe_rcu
+ * @pos:	the &struct list_head to use as a loop cursor.
  * @n:		another &struct list_head to use as temporary storage
  * @head:	the head for your list.
  *
+ * Iterate over an rcu-protected list, safe against removal of list entry.
+ *
  * This list-traversal primitive may safely run concurrently with
  * the _rcu list-mutation primitives such as list_add_rcu()
  * as long as the traversal is guarded by rcu_read_lock().
@@ -512,7 +540,7 @@
 
 /**
  * list_for_each_entry_rcu	-	iterate over rcu list of given type
- * @pos:	the type * to use as a loop counter.
+ * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
  * @member:	the name of the list_struct within the struct.
  *
@@ -528,11 +556,12 @@
 
 
 /**
- * list_for_each_continue_rcu	-	iterate over an rcu-protected list
- *			continuing after existing point.
- * @pos:	the &struct list_head to use as a loop counter.
+ * list_for_each_continue_rcu
+ * @pos:	the &struct list_head to use as a loop cursor.
  * @head:	the head for your list.
  *
+ * Iterate over an rcu-protected list, continuing after current point.
+ *
  * This list-traversal primitive may safely run concurrently with
  * the _rcu list-mutation primitives such as list_add_rcu()
  * as long as the traversal is guarded by rcu_read_lock().
@@ -658,11 +687,14 @@
 
 
 /**
- * hlist_add_head_rcu - adds the specified element to the specified hlist,
- * while permitting racing traversals.
+ * hlist_add_head_rcu
  * @n: the element to add to the hash list.
  * @h: the list to add to.
  *
+ * Description:
+ * Adds the specified element to the specified hlist,
+ * while permitting racing traversals.
+ *
  * The caller must take whatever precautions are necessary
  * (such as holding appropriate locks) to avoid racing
  * with another list-mutation primitive, such as hlist_add_head_rcu()
@@ -707,11 +739,14 @@
 }
 
 /**
- * hlist_add_before_rcu - adds the specified element to the specified hlist
- * before the specified node while permitting racing traversals.
+ * hlist_add_before_rcu
  * @n: the new element to add to the hash list.
  * @next: the existing element to add the new element before.
  *
+ * Description:
+ * Adds the specified element to the specified hlist
+ * before the specified node while permitting racing traversals.
+ *
  * The caller must take whatever precautions are necessary
  * (such as holding appropriate locks) to avoid racing
  * with another list-mutation primitive, such as hlist_add_head_rcu()
@@ -732,11 +767,14 @@
 }
 
 /**
- * hlist_add_after_rcu - adds the specified element to the specified hlist
- * after the specified node while permitting racing traversals.
+ * hlist_add_after_rcu
  * @prev: the existing element to add the new element after.
  * @n: the new element to add to the hash list.
  *
+ * Description:
+ * Adds the specified element to the specified hlist
+ * after the specified node while permitting racing traversals.
+ *
  * The caller must take whatever precautions are necessary
  * (such as holding appropriate locks) to avoid racing
  * with another list-mutation primitive, such as hlist_add_head_rcu()
@@ -769,8 +807,8 @@
 
 /**
  * hlist_for_each_entry	- iterate over list of given type
- * @tpos:	the type * to use as a loop counter.
- * @pos:	the &struct hlist_node to use as a loop counter.
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
  * @head:	the head for your list.
  * @member:	the name of the hlist_node within the struct.
  */
@@ -781,9 +819,9 @@
 	     pos = pos->next)
 
 /**
- * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
- * @tpos:	the type * to use as a loop counter.
- * @pos:	the &struct hlist_node to use as a loop counter.
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
  * @member:	the name of the hlist_node within the struct.
  */
 #define hlist_for_each_entry_continue(tpos, pos, member)		 \
@@ -793,9 +831,9 @@
 	     pos = pos->next)
 
 /**
- * hlist_for_each_entry_from - iterate over a hlist continuing from existing point
- * @tpos:	the type * to use as a loop counter.
- * @pos:	the &struct hlist_node to use as a loop counter.
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
  * @member:	the name of the hlist_node within the struct.
  */
 #define hlist_for_each_entry_from(tpos, pos, member)			 \
@@ -805,8 +843,8 @@
 
 /**
  * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @tpos:	the type * to use as a loop counter.
- * @pos:	the &struct hlist_node to use as a loop counter.
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
  * @n:		another &struct hlist_node to use as temporary storage
  * @head:	the head for your list.
  * @member:	the name of the hlist_node within the struct.
@@ -819,8 +857,8 @@
 
 /**
  * hlist_for_each_entry_rcu - iterate over rcu list of given type
- * @tpos:	the type * to use as a loop counter.
- * @pos:	the &struct hlist_node to use as a loop counter.
+ * @tpos:	the type * to use as a loop cursor.
+ * @pos:	the &struct hlist_node to use as a loop cursor.
  * @head:	the head for your list.
  * @member:	the name of the hlist_node within the struct.
  *
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 995f89d..aa4fe90 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/in.h>
 #include <linux/fs.h>
 #include <linux/kref.h>
@@ -50,11 +49,12 @@
 				h_killed     : 1,
 				h_monitored  : 1;
 	wait_queue_head_t	h_gracewait;	/* wait while reclaiming */
+	struct rw_semaphore	h_rwsem;	/* Reboot recovery lock */
 	u32			h_state;	/* pseudo-state counter */
 	u32			h_nsmstate;	/* true remote NSM state */
 	u32			h_pidcount;	/* Pseudopids */
 	atomic_t		h_count;	/* reference count */
-	struct semaphore	h_sema;		/* mutex for pmap binding */
+	struct mutex		h_mutex;	/* mutex for pmap binding */
 	unsigned long		h_nextrebind;	/* next portmap call */
 	unsigned long		h_expires;	/* eligible for GC */
 	struct list_head	h_lockowners;	/* Lockowners for the client */
@@ -220,6 +220,7 @@
 nlm_compare_locks(const struct file_lock *fl1, const struct file_lock *fl2)
 {
 	return	fl1->fl_pid   == fl2->fl_pid
+	     && fl1->fl_owner == fl2->fl_owner
 	     && fl1->fl_start == fl2->fl_start
 	     && fl1->fl_end   == fl2->fl_end
 	     &&(fl1->fl_type  == fl2->fl_type || fl2->fl_type == F_UNLCK);
diff --git a/include/linux/lockd/nlm.h b/include/linux/lockd/nlm.h
index 869b630..d9d46e4 100644
--- a/include/linux/lockd/nlm.h
+++ b/include/linux/lockd/nlm.h
@@ -9,7 +9,6 @@
 #ifndef LINUX_LOCKD_NLM_H
 #define LINUX_LOCKD_NLM_H
 
-#include <linux/config.h>
 
 /* Maximum file offset in file_lock.fl_end */
 # define NLM_OFFSET_MAX		((s32) 0x7fffffff)
diff --git a/include/linux/m41t00.h b/include/linux/m41t00.h
new file mode 100644
index 0000000..b423360
--- /dev/null
+++ b/include/linux/m41t00.h
@@ -0,0 +1,50 @@
+/*
+ * Definitions for the ST M41T00 family of i2c rtc chips.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef _M41T00_H
+#define _M41T00_H
+
+#define	M41T00_DRV_NAME		"m41t00"
+#define	M41T00_I2C_ADDR		0x68
+
+#define	M41T00_TYPE_M41T00	0
+#define	M41T00_TYPE_M41T81	81
+#define	M41T00_TYPE_M41T85	85
+
+struct m41t00_platform_data {
+	u8	type;
+	u8	i2c_addr;
+	u8	sqw_freq;
+};
+
+/* SQW output disabled, this is default value by power on */
+#define M41T00_SQW_DISABLE	(0)
+
+#define M41T00_SQW_32KHZ	(1<<4)		/* 32.768 KHz */
+#define M41T00_SQW_8KHZ		(2<<4)		/* 8.192 KHz */
+#define M41T00_SQW_4KHZ		(3<<4)		/* 4.096 KHz */
+#define M41T00_SQW_2KHZ		(4<<4)		/* 2.048 KHz */
+#define M41T00_SQW_1KHZ		(5<<4)		/* 1.024 KHz */
+#define M41T00_SQW_512HZ	(6<<4)		/* 512 Hz */
+#define M41T00_SQW_256HZ	(7<<4)		/* 256 Hz */
+#define M41T00_SQW_128HZ	(8<<4)		/* 128 Hz */
+#define M41T00_SQW_64HZ		(9<<4)		/* 64 Hz */
+#define M41T00_SQW_32HZ		(10<<4)		/* 32 Hz */
+#define M41T00_SQW_16HZ		(11<<4)		/* 16 Hz */
+#define M41T00_SQW_8HZ		(12<<4)		/* 8 Hz */
+#define M41T00_SQW_4HZ		(13<<4)		/* 4 Hz */
+#define M41T00_SQW_2HZ		(14<<4)		/* 2 Hz */
+#define M41T00_SQW_1HZ		(15<<4)		/* 1 Hz */
+
+extern ulong m41t00_get_rtc_time(void);
+extern int m41t00_set_rtc_time(ulong nowtime);
+
+#endif /* _M41T00_H */
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 9112063..218501c 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -63,6 +63,76 @@
 /* reasonably generic interface to expand the physical pages in a zone  */
 extern int __add_pages(struct zone *zone, unsigned long start_pfn,
 	unsigned long nr_pages);
+
+#ifdef CONFIG_NUMA
+extern int memory_add_physaddr_to_nid(u64 start);
+#else
+static inline int memory_add_physaddr_to_nid(u64 start)
+{
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION
+/*
+ * For supporting node-hotadd, we have to allocate a new pgdat.
+ *
+ * If an arch has generic style NODE_DATA(),
+ * node_data[nid] = kzalloc() works well. But it depends on the architecture.
+ *
+ * In general, generic_alloc_nodedata() is used.
+ * Now, arch_free_nodedata() is just defined for error path of node_hot_add.
+ *
+ */
+extern pg_data_t *arch_alloc_nodedata(int nid);
+extern void arch_free_nodedata(pg_data_t *pgdat);
+extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat);
+
+#else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
+
+#define arch_alloc_nodedata(nid)	generic_alloc_nodedata(nid)
+#define arch_free_nodedata(pgdat)	generic_free_nodedata(pgdat)
+
+#ifdef CONFIG_NUMA
+/*
+ * If ARCH_HAS_NODEDATA_EXTENSION=n, this func is used to allocate pgdat.
+ * XXX: kmalloc_node() can't work well to get new node's memory at this time.
+ *	Because, pgdat for the new node is not allocated/initialized yet itself.
+ *	To use new node's memory, more consideration will be necessary.
+ */
+#define generic_alloc_nodedata(nid)				\
+({								\
+	kzalloc(sizeof(pg_data_t), GFP_KERNEL);			\
+})
+/*
+ * This definition is just for error path in node hotadd.
+ * For node hotremove, we have to replace this.
+ */
+#define generic_free_nodedata(pgdat)	kfree(pgdat)
+
+extern pg_data_t *node_data[];
+static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
+{
+	node_data[nid] = pgdat;
+}
+
+#else /* !CONFIG_NUMA */
+
+/* never called */
+static inline pg_data_t *generic_alloc_nodedata(int nid)
+{
+	BUG();
+	return NULL;
+}
+static inline void generic_free_nodedata(pg_data_t *pgdat)
+{
+}
+static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
+{
+}
+#endif /* CONFIG_NUMA */
+#endif /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */
+
 #else /* ! CONFIG_MEMORY_HOTPLUG */
 /*
  * Stub functions for when hotplug is off
@@ -99,7 +169,8 @@
 	return -ENOSYS;
 }
 
-extern int add_memory(u64 start, u64 size);
+extern int add_memory(int nid, u64 start, u64 size);
+extern int arch_add_memory(int nid, u64 start, u64 size);
 extern int remove_memory(u64 start, u64 size);
 
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h
index f5fdca1..72440f0 100644
--- a/include/linux/mempolicy.h
+++ b/include/linux/mempolicy.h
@@ -28,7 +28,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/mmzone.h>
 #include <linux/slab.h>
 #include <linux/rbtree.h>
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index ff0a640..48148e0 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -1,36 +1,44 @@
 #ifndef _LINUX_MIGRATE_H
 #define _LINUX_MIGRATE_H
 
-#include <linux/config.h>
 #include <linux/mm.h>
 
+typedef struct page *new_page_t(struct page *, unsigned long private, int **);
+
 #ifdef CONFIG_MIGRATION
 extern int isolate_lru_page(struct page *p, struct list_head *pagelist);
 extern int putback_lru_pages(struct list_head *l);
-extern int migrate_page(struct page *, struct page *);
-extern void migrate_page_copy(struct page *, struct page *);
-extern int migrate_page_remove_references(struct page *, struct page *, int);
-extern int migrate_pages(struct list_head *l, struct list_head *t,
-		struct list_head *moved, struct list_head *failed);
-extern int migrate_pages_to(struct list_head *pagelist,
-			struct vm_area_struct *vma, int dest);
-extern int fail_migrate_page(struct page *, struct page *);
+extern int migrate_page(struct address_space *,
+			struct page *, struct page *);
+extern int migrate_pages(struct list_head *l, new_page_t x, unsigned long);
+
+extern int fail_migrate_page(struct address_space *,
+			struct page *, struct page *);
 
 extern int migrate_prep(void);
-
+extern int migrate_vmas(struct mm_struct *mm,
+		const nodemask_t *from, const nodemask_t *to,
+		unsigned long flags);
 #else
 
 static inline int isolate_lru_page(struct page *p, struct list_head *list)
 					{ return -ENOSYS; }
 static inline int putback_lru_pages(struct list_head *l) { return 0; }
-static inline int migrate_pages(struct list_head *l, struct list_head *t,
-	struct list_head *moved, struct list_head *failed) { return -ENOSYS; }
+static inline int migrate_pages(struct list_head *l, new_page_t x,
+		unsigned long private) { return -ENOSYS; }
 
 static inline int migrate_pages_to(struct list_head *pagelist,
 			struct vm_area_struct *vma, int dest) { return 0; }
 
 static inline int migrate_prep(void) { return -ENOSYS; }
 
+static inline int migrate_vmas(struct mm_struct *mm,
+		const nodemask_t *from, const nodemask_t *to,
+		unsigned long flags)
+{
+	return -ENOSYS;
+}
+
 /* Possible settings for the migrate_page() method in address_operations */
 #define migrate_page NULL
 #define fail_migrate_page NULL
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 68f5a0f..beddc6d 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -9,7 +9,6 @@
 #define __LINUX_MII_H__
 
 #include <linux/types.h>
-#include <linux/if.h>
 
 /* Generic MII registers. */
 
@@ -136,6 +135,20 @@
 #define LPA_1000FULL            0x0800  /* Link partner 1000BASE-T full duplex */
 #define LPA_1000HALF            0x0400  /* Link partner 1000BASE-T half duplex */
 
+/* This structure is used in all SIOCxMIIxxx ioctl calls */
+struct mii_ioctl_data {
+	__u16		phy_id;
+	__u16		reg_num;
+	__u16		val_in;
+	__u16		val_out;
+};
+
+#ifdef __KERNEL__ 
+
+#include <linux/if.h>
+
+struct ethtool_cmd;
+
 struct mii_if_info {
 	int phy_id;
 	int advertising;
@@ -151,9 +164,6 @@
 	void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
 };
 
-struct ethtool_cmd;
-struct mii_ioctl_data;
-
 extern int mii_link_ok (struct mii_if_info *mii);
 extern int mii_nway_restart (struct mii_if_info *mii);
 extern int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
@@ -168,16 +178,6 @@
 			     unsigned int *duplex_changed);
 
 
-
-/* This structure is used in all SIOCxMIIxxx ioctl calls */
-struct mii_ioctl_data {
-	u16		phy_id;
-	u16		reg_num;
-	u16		val_in;
-	u16		val_out;
-};
-
-
 static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
 {
 	return (struct mii_ioctl_data *) &rq->ifr_ifru;
@@ -235,5 +235,5 @@
 	return 0;
 }
 
-
+#endif /* __KERNEL__ */
 #endif /* __LINUX_MII_H__ */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 1154684..c41a129 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -7,7 +7,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/gfp.h>
 #include <linux/list.h>
 #include <linux/mmzone.h>
@@ -146,7 +145,6 @@
 
 #define VM_GROWSDOWN	0x00000100	/* general info on the segment */
 #define VM_GROWSUP	0x00000200
-#define VM_SHM		0x00000000	/* Means nothing: delete it later */
 #define VM_PFNMAP	0x00000400	/* Page-ranges managed without "struct page", just pure PFN */
 #define VM_DENYWRITE	0x00000800	/* ETXTBSY on write attempts.. */
 
@@ -200,10 +198,16 @@
 	void (*close)(struct vm_area_struct * area);
 	struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type);
 	int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
+
+	/* notification that a previously read-only page is about to become
+	 * writable, if an error is returned it will cause a SIGBUS */
+	int (*page_mkwrite)(struct vm_area_struct *vma, struct page *page);
 #ifdef CONFIG_NUMA
 	int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
 	struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
 					unsigned long addr);
+	int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from,
+		const nodemask_t *to, unsigned long flags);
 #endif
 };
 
@@ -466,10 +470,13 @@
 struct zone;
 extern struct zone *zone_table[];
 
+static inline int page_zone_id(struct page *page)
+{
+	return (page->flags >> ZONETABLE_PGSHIFT) & ZONETABLE_MASK;
+}
 static inline struct zone *page_zone(struct page *page)
 {
-	return zone_table[(page->flags >> ZONETABLE_PGSHIFT) &
-			ZONETABLE_MASK];
+	return zone_table[page_zone_id(page)];
 }
 
 static inline unsigned long page_to_nid(struct page *page)
@@ -1023,13 +1030,20 @@
 }
 #endif /* CONFIG_PROC_FS */
 
+static inline void
+debug_check_no_locks_freed(const void *from, unsigned long len)
+{
+	mutex_debug_check_no_locks_freed(from, len);
+	rt_mutex_debug_check_no_locks_freed(from, len);
+}
+
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable)
 {
 	if (!PageHighMem(page) && !enable)
-		mutex_debug_check_no_locks_freed(page_address(page),
-						 numpages * PAGE_SIZE);
+		debug_check_no_locks_freed(page_address(page),
+					   numpages * PAGE_SIZE);
 }
 #endif
 
@@ -1058,5 +1072,7 @@
 extern int randomize_va_space;
 #endif
 
+const char *arch_vma_name(struct vm_area_struct *vma);
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 18a5689..87920a0 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -1,10 +1,6 @@
 #ifndef _LINUX_MMAN_H
 #define _LINUX_MMAN_H
 
-#include <linux/config.h>
-#include <linux/mm.h>
-
-#include <asm/atomic.h>
 #include <asm/mman.h>
 
 #define MREMAP_MAYMOVE	1
@@ -13,6 +9,12 @@
 #define OVERCOMMIT_GUESS		0
 #define OVERCOMMIT_ALWAYS		1
 #define OVERCOMMIT_NEVER		2
+
+#ifdef __KERNEL__
+#include <linux/mm.h>
+
+#include <asm/atomic.h>
+
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
 extern atomic_t vm_committed_space;
@@ -63,5 +65,5 @@
 	       _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) |
 	       _calc_vm_trans(flags, MAP_LOCKED,     VM_LOCKED    );
 }
-
+#endif /* __KERNEL__ */
 #endif /* _LINUX_MMAN_H */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 2d83371..d6120fa 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -4,7 +4,6 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/wait.h>
@@ -198,7 +197,7 @@
 
 	/*
 	 * wait_table		-- the array holding the hash table
-	 * wait_table_size	-- the size of the hash table array
+	 * wait_table_hash_nr_entries	-- the size of the hash table array
 	 * wait_table_bits	-- wait_table_size == (1 << wait_table_bits)
 	 *
 	 * The purpose of all these is to keep track of the people
@@ -221,7 +220,7 @@
 	 * free_area_init_core() performs the initialization of them.
 	 */
 	wait_queue_head_t	* wait_table;
-	unsigned long		wait_table_size;
+	unsigned long		wait_table_hash_nr_entries;
 	unsigned long		wait_table_bits;
 
 	/*
@@ -334,6 +333,9 @@
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
 		int classzone_idx, int alloc_flags);
 
+extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
+				     unsigned long size);
+
 #ifdef CONFIG_HAVE_MEMORY_PRESENT
 void memory_present(int nid, unsigned long start, unsigned long end);
 #else
@@ -507,6 +509,10 @@
 	 * pages.  However, it is stored with some other magic.
 	 * (see sparse.c::sparse_init_one_section())
 	 *
+	 * Additionally during early boot we encode node id of
+	 * the location of the section here to guide allocation.
+	 * (see sparse.c::memory_present())
+	 *
 	 * Making it a UL at least makes someone do a cast
 	 * before using it wrong.
 	 */
@@ -546,6 +552,7 @@
 #define SECTION_HAS_MEM_MAP	(1UL<<1)
 #define SECTION_MAP_LAST_BIT	(1UL<<2)
 #define SECTION_MAP_MASK	(~(SECTION_MAP_LAST_BIT-1))
+#define SECTION_NID_SHIFT	2
 
 static inline struct page *__section_mem_map_addr(struct mem_section *section)
 {
diff --git a/include/linux/module.h b/include/linux/module.h
index eaec13d..9e9dc7c 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -6,7 +6,6 @@
  * Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
  * Rewritten again by Rusty Russell, 2002
  */
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
@@ -106,6 +105,8 @@
  *	"GPL and additional rights"	[GNU Public License v2 rights and more]
  *	"Dual BSD/GPL"			[GNU Public License v2
  *					 or BSD license choice]
+ *	"Dual MIT/GPL"			[GNU Public License v2
+ *					 or MIT license choice]
  *	"Dual MPL/GPL"			[GNU Public License v2
  *					 or Mozilla license choice]
  *
@@ -202,6 +203,15 @@
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)				\
 	__EXPORT_SYMBOL(sym, "_gpl_future")
 
+
+#ifdef CONFIG_UNUSED_SYMBOLS
+#define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused")
+#define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl")
+#else
+#define EXPORT_UNUSED_SYMBOL(sym)
+#define EXPORT_UNUSED_SYMBOL_GPL(sym)
+#endif
+
 #endif
 
 struct module_ref
@@ -260,6 +270,15 @@
 	unsigned int num_gpl_syms;
 	const unsigned long *gpl_crcs;
 
+	/* unused exported symbols. */
+	const struct kernel_symbol *unused_syms;
+	unsigned int num_unused_syms;
+	const unsigned long *unused_crcs;
+	/* GPL-only, unused exported symbols. */
+	const struct kernel_symbol *unused_gpl_syms;
+	unsigned int num_unused_gpl_syms;
+	const unsigned long *unused_gpl_crcs;
+
 	/* symbols that will be GPL-only in the near future. */
 	const struct kernel_symbol *gpl_future_syms;
 	unsigned int num_gpl_future_syms;
@@ -284,6 +303,9 @@
 	/* The size of the executable code in each section.  */
 	unsigned long init_text_size, core_text_size;
 
+	/* The handle returned from unwind_add_table. */
+	void *unwind_info;
+
 	/* Arch-specific module values */
 	struct mod_arch_specific arch;
 
@@ -452,6 +474,8 @@
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
+#define EXPORT_UNUSED_SYMBOL(sym)
+#define EXPORT_UNUSED_SYMBOL_GPL(sym)
 
 /* Given an address, look for it in the exception tables. */
 static inline const struct exception_table_entry *
@@ -557,13 +581,4 @@
 
 #define __MODULE_STRING(x) __stringify(x)
 
-/* Use symbol_get and symbol_put instead.  You'll thank me. */
-#define HAVE_INTER_MODULE
-extern void __deprecated inter_module_register(const char *,
-		struct module *, const void *);
-extern void __deprecated inter_module_unregister(const char *);
-extern const void * __deprecated inter_module_get_request(const char *,
-		const char *);
-extern void __deprecated inter_module_put(const char *);
-
 #endif /* _LINUX_MODULE_H */
diff --git a/include/linux/mount.h b/include/linux/mount.h
index b7472ae..403d1a9 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -17,12 +17,19 @@
 #include <linux/spinlock.h>
 #include <asm/atomic.h>
 
+struct super_block;
+struct vfsmount;
+struct dentry;
+struct namespace;
+
 #define MNT_NOSUID	0x01
 #define MNT_NODEV	0x02
 #define MNT_NOEXEC	0x04
 #define MNT_NOATIME	0x08
 #define MNT_NODIRATIME	0x10
 
+#define MNT_SHRINKABLE	0x100
+
 #define MNT_SHARED	0x1000	/* if the vfsmount is a shared mount */
 #define MNT_UNBINDABLE	0x2000	/* if the vfsmount is a unbindable mount */
 #define MNT_PNODE_MASK	0x3000	/* propogation flag mask */
@@ -73,12 +80,18 @@
 extern struct vfsmount *do_kern_mount(const char *fstype, int flags,
 				      const char *name, void *data);
 
+struct file_system_type;
+extern struct vfsmount *vfs_kern_mount(struct file_system_type *type,
+				      int flags, const char *name,
+				      void *data);
+
 struct nameidata;
 
 extern int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd,
 			int mnt_flags, struct list_head *fslist);
 
 extern void mark_mounts_for_expiry(struct list_head *mounts);
+extern void shrink_submounts(struct vfsmount *mountpoint, struct list_head *mounts);
 
 extern spinlock_t vfsmount_lock;
 extern dev_t name_to_dev_t(char *name);
diff --git a/include/linux/msg.h b/include/linux/msg.h
index 903e0ab..acc7c17 100644
--- a/include/linux/msg.h
+++ b/include/linux/msg.h
@@ -2,7 +2,6 @@
 #define _LINUX_MSG_H
 
 #include <linux/ipc.h>
-#include <linux/list.h>
 
 /* ipcs ctl commands */
 #define MSG_STAT 11
@@ -63,6 +62,7 @@
 #define MSGSEG (__MSGSEG <= 0xffff ? __MSGSEG : 0xffff)
 
 #ifdef __KERNEL__
+#include <linux/list.h>
 
 /* one msg_msg structure for each message */
 struct msg_msg {
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h
index 23a5689..09bfae6 100644
--- a/include/linux/mtd/cfi.h
+++ b/include/linux/mtd/cfi.h
@@ -7,7 +7,6 @@
 #ifndef __MTD_CFI_H__
 #define __MTD_CFI_H__
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h
index d7eaa40..6977780 100644
--- a/include/linux/mtd/inftl.h
+++ b/include/linux/mtd/inftl.h
@@ -46,7 +46,7 @@
         unsigned int nb_blocks;		/* number of physical blocks */
         unsigned int nb_boot_blocks;	/* number of blocks used by the bios */
         struct erase_info instr;
-        struct nand_oobinfo oobinfo;
+        struct nand_ecclayout oobinfo;
 };
 
 int INFTL_mount(struct INFTLrecord *s);
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 7dfd6e1f..28d461d 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -5,7 +5,6 @@
 #ifndef __LINUX_MTD_MAP_H__
 #define __LINUX_MTD_MAP_H__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/string.h>
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index b6f2fda..9b7a2b5 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -13,7 +13,6 @@
 #error This is a kernel header. Perhaps include mtd-user.h instead?
 #endif
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/uio.h>
@@ -56,18 +55,69 @@
 	u_int32_t numblocks;		/* Number of blocks of erasesize in this region */
 };
 
+/*
+ * oob operation modes
+ *
+ * MTD_OOB_PLACE:	oob data are placed at the given offset
+ * MTD_OOB_AUTO:	oob data are automatically placed at the free areas
+ *			which are defined by the ecclayout
+ * MTD_OOB_RAW:		mode to read raw data+oob in one chunk. The oob data
+ *			is inserted into the data. Thats a raw image of the
+ *			flash contents.
+ */
+typedef enum {
+	MTD_OOB_PLACE,
+	MTD_OOB_AUTO,
+	MTD_OOB_RAW,
+} mtd_oob_mode_t;
+
+/**
+ * struct mtd_oob_ops - oob operation operands
+ * @mode:	operation mode
+ *
+ * @len:	number of bytes to write/read. When a data buffer is given
+ *		(datbuf != NULL) this is the number of data bytes. When
+ +		no data buffer is available this is the number of oob bytes.
+ *
+ * @retlen:	number of bytes written/read. When a data buffer is given
+ *		(datbuf != NULL) this is the number of data bytes. When
+ +		no data buffer is available this is the number of oob bytes.
+ *
+ * @ooblen:	number of oob bytes per page
+ * @ooboffs:	offset of oob data in the oob area (only relevant when
+ *		mode = MTD_OOB_PLACE)
+ * @datbuf:	data buffer - if NULL only oob data are read/written
+ * @oobbuf:	oob data buffer
+ */
+struct mtd_oob_ops {
+	mtd_oob_mode_t	mode;
+	size_t		len;
+	size_t		retlen;
+	size_t		ooblen;
+	uint32_t	ooboffs;
+	uint8_t		*datbuf;
+	uint8_t		*oobbuf;
+};
+
 struct mtd_info {
 	u_char type;
 	u_int32_t flags;
 	u_int32_t size;	 // Total size of the MTD
 
-	/* "Major" erase size for the device. Naïve users may take this
+	/* "Major" erase size for the device. Naïve users may take this
 	 * to be the only erase size available, or may use the more detailed
 	 * information below if they desire
 	 */
 	u_int32_t erasesize;
+	/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
+	 * though individual bits can be cleared), in case of NAND flash it is
+	 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
+	 * it is of ECC block size, etc. It is illegal to have writesize = 0.
+	 * Any driver registering a struct mtd_info must ensure a writesize of
+	 * 1 or larger.
+	 */
+	u_int32_t writesize;
 
-	u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
 	u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
 	u_int32_t ecctype;
 	u_int32_t eccsize;
@@ -79,7 +129,6 @@
 	 * MTD_PROGRAM_REGIONS flag is set.
 	 * (Maybe we should have an union for those?)
 	 */
-#define MTD_PROGREGION_SIZE(mtd)  (mtd)->oobblock
 #define MTD_PROGREGION_CTRLMODE_VALID(mtd)  (mtd)->oobsize
 #define MTD_PROGREGION_CTRLMODE_INVALID(mtd)  (mtd)->ecctype
 
@@ -87,9 +136,8 @@
 	char *name;
 	int index;
 
-	// oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO)
-	struct nand_oobinfo oobinfo;
-	u_int32_t oobavail;  // Number of bytes in OOB area available for fs
+	/* ecc layout structure pointer - read only ! */
+	struct nand_ecclayout *ecclayout;
 
 	/* Data for variable erase regions. If numeraseregions is zero,
 	 * it means that the whole device has erasesize as given above.
@@ -112,11 +160,10 @@
 	int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 	int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
 
-	int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
-	int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
-
-	int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
-	int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+	int (*read_oob) (struct mtd_info *mtd, loff_t from,
+			 struct mtd_oob_ops *ops);
+	int (*write_oob) (struct mtd_info *mtd, loff_t to,
+			 struct mtd_oob_ops *ops);
 
 	/*
 	 * Methods to access the protection register area, present in some
@@ -130,17 +177,11 @@
 	int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
 	int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
 
-	/* kvec-based read/write methods. We need these especially for NAND flash,
-	   with its limited number of write cycles per erase.
+	/* kvec-based read/write methods.
 	   NB: The 'count' parameter is the number of _vectors_, each of
 	   which contains an (ofs, len) tuple.
 	*/
-	int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen);
-	int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from,
-		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 	int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
-	int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to,
-		size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel);
 
 	/* Sync */
 	void (*sync) (struct mtd_info *mtd);
@@ -159,6 +200,9 @@
 
 	struct notifier_block reboot_notifier;  /* default mode before reboot */
 
+	/* ECC status information */
+	struct mtd_ecc_stats ecc_stats;
+
 	void *priv;
 
 	struct module *owner;
@@ -192,20 +236,6 @@
 int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs,
 		      unsigned long count, loff_t from, size_t *retlen);
 
-#define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
-#define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
-#define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
-#define MTD_READ(mtd, args...) (*(mtd->read))(mtd, args)
-#define MTD_WRITE(mtd, args...) (*(mtd->write))(mtd, args)
-#define MTD_READV(mtd, args...) (*(mtd->readv))(mtd, args)
-#define MTD_WRITEV(mtd, args...) (*(mtd->writev))(mtd, args)
-#define MTD_READECC(mtd, args...) (*(mtd->read_ecc))(mtd, args)
-#define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args)
-#define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args)
-#define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
-#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0)
-
-
 #ifdef CONFIG_MTD_PARTITIONS
 void mtd_erase_callback(struct erase_info *instr);
 #else
@@ -226,7 +256,7 @@
 
 #ifdef CONFIG_MTD_DEBUG
 #define DEBUG(n, args...)				\
- 	do {						\
+	do {						\
 		if (n <= CONFIG_MTD_DEBUG_VERBOSE)	\
 			printk(KERN_INFO args);		\
 	} while(0)
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index da5e67b..6655927 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -11,52 +11,15 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  Info:
- *   Contains standard defines and IDs for NAND flash devices
+ * Info:
+ *	Contains standard defines and IDs for NAND flash devices
  *
- *  Changelog:
- *   01-31-2000 DMW     Created
- *   09-18-2000 SJH     Moved structure out of the Disk-On-Chip drivers
- *			so it can be used by other NAND flash device
- *			drivers. I also changed the copyright since none
- *			of the original contents of this file are specific
- *			to DoC devices. David can whack me with a baseball
- *			bat later if I did something naughty.
- *   10-11-2000 SJH     Added private NAND flash structure for driver
- *   10-24-2000 SJH     Added prototype for 'nand_scan' function
- *   10-29-2001 TG	changed nand_chip structure to support
- *			hardwarespecific function for accessing control lines
- *   02-21-2002 TG	added support for different read/write adress and
- *			ready/busy line access function
- *   02-26-2002 TG	added chip_delay to nand_chip structure to optimize
- *			command delay times for different chips
- *   04-28-2002 TG	OOB config defines moved from nand.c to avoid duplicate
- *			defines in jffs2/wbuf.c
- *   08-07-2002 TG	forced bad block location to byte 5 of OOB, even if
- *			CONFIG_MTD_NAND_ECC_JFFS2 is not set
- *   08-10-2002 TG	extensions to nand_chip structure to support HW-ECC
- *
- *   08-29-2002 tglx 	nand_chip structure: data_poi for selecting
- *			internal / fs-driver buffer
- *			support for 6byte/512byte hardware ECC
- *			read_ecc, write_ecc extended for different oob-layout
- *			oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB,
- *			NAND_YAFFS_OOB
- *  11-25-2002 tglx	Added Manufacturer code FUJITSU, NATIONAL
- *			Split manufacturer and device ID structures
- *
- *  02-08-2004 tglx 	added option field to nand structure for chip anomalities
- *  05-25-2004 tglx 	added bad block table support, ST-MICRO manufacturer id
- *			update of nand_chip structure description
- *  01-17-2005 dmarlin	added extended commands for AG-AND device and added option
- * 			for BBT_AUTO_REFRESH.
- *  01-20-2005 dmarlin	added optional pointer to hardware specific callback for
- *			extra error status checks.
+ * Changelog:
+ *	See git changelog.
  */
 #ifndef __LINUX_MTD_NAND_H
 #define __LINUX_MTD_NAND_H
 
-#include <linux/config.h>
 #include <linux/wait.h>
 #include <linux/spinlock.h>
 #include <linux/mtd/mtd.h>
@@ -67,10 +30,6 @@
 /* Free resources held by the NAND device */
 extern void nand_release (struct mtd_info *mtd);
 
-/* Read raw data from the device without ECC */
-extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_t len, size_t ooblen);
-
-
 /* The maximum number of NAND chips in an array */
 #define NAND_MAX_CHIPS		8
 
@@ -79,44 +38,45 @@
  * adjust this accordingly.
  */
 #define NAND_MAX_OOBSIZE	64
+#define NAND_MAX_PAGESIZE	2048
 
 /*
  * Constants for hardware specific CLE/ALE/NCE function
-*/
+ *
+ * These are bits which can be or'ed to set/clear multiple
+ * bits in one go.
+ */
 /* Select the chip by setting nCE to low */
-#define NAND_CTL_SETNCE 	1
-/* Deselect the chip by setting nCE to high */
-#define NAND_CTL_CLRNCE		2
+#define NAND_NCE		0x01
 /* Select the command latch by setting CLE to high */
-#define NAND_CTL_SETCLE		3
-/* Deselect the command latch by setting CLE to low */
-#define NAND_CTL_CLRCLE		4
+#define NAND_CLE		0x02
 /* Select the address latch by setting ALE to high */
-#define NAND_CTL_SETALE		5
-/* Deselect the address latch by setting ALE to low */
-#define NAND_CTL_CLRALE		6
-/* Set write protection by setting WP to high. Not used! */
-#define NAND_CTL_SETWP		7
-/* Clear write protection by setting WP to low. Not used! */
-#define NAND_CTL_CLRWP		8
+#define NAND_ALE		0x04
+
+#define NAND_CTRL_CLE		(NAND_NCE | NAND_CLE)
+#define NAND_CTRL_ALE		(NAND_NCE | NAND_ALE)
+#define NAND_CTRL_CHANGE	0x80
 
 /*
  * Standard NAND flash commands
  */
 #define NAND_CMD_READ0		0
 #define NAND_CMD_READ1		1
+#define NAND_CMD_RNDOUT		5
 #define NAND_CMD_PAGEPROG	0x10
 #define NAND_CMD_READOOB	0x50
 #define NAND_CMD_ERASE1		0x60
 #define NAND_CMD_STATUS		0x70
 #define NAND_CMD_STATUS_MULTI	0x71
 #define NAND_CMD_SEQIN		0x80
+#define NAND_CMD_RNDIN		0x85
 #define NAND_CMD_READID		0x90
 #define NAND_CMD_ERASE2		0xd0
 #define NAND_CMD_RESET		0xff
 
 /* Extended commands for large page devices */
 #define NAND_CMD_READSTART	0x30
+#define NAND_CMD_RNDOUTSTART	0xE0
 #define NAND_CMD_CACHEDPROG	0x15
 
 /* Extended commands for AG-AND device */
@@ -138,6 +98,8 @@
 #define NAND_CMD_STATUS_RESET	0x7f
 #define NAND_CMD_STATUS_CLEAR	0xff
 
+#define NAND_CMD_NONE		-1
+
 /* Status bits */
 #define NAND_STATUS_FAIL	0x01
 #define NAND_STATUS_FAIL_N1	0x02
@@ -148,21 +110,12 @@
 /*
  * Constants for ECC_MODES
  */
-
-/* No ECC. Usage is not recommended ! */
-#define NAND_ECC_NONE		0
-/* Software ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_SOFT		1
-/* Hardware ECC 3 byte ECC per 256 Byte data */
-#define NAND_ECC_HW3_256	2
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW3_512	3
-/* Hardware ECC 3 byte ECC per 512 Byte data */
-#define NAND_ECC_HW6_512	4
-/* Hardware ECC 8 byte ECC per 512 Byte data */
-#define NAND_ECC_HW8_512	6
-/* Hardware ECC 12 byte ECC per 2048 Byte data */
-#define NAND_ECC_HW12_2048	7
+typedef enum {
+	NAND_ECC_NONE,
+	NAND_ECC_SOFT,
+	NAND_ECC_HW,
+	NAND_ECC_HW_SYNDROME,
+} nand_ecc_modes_t;
 
 /*
  * Constants for Hardware ECC
@@ -201,6 +154,10 @@
  * bits from adjacent blocks from 'leaking' in altering data.
  * This happens with the Renesas AG-AND chips, possibly others.  */
 #define BBT_AUTO_REFRESH	0x00000080
+/* Chip does not require ready check on read. True
+ * for all large page devices, as they do not support
+ * autoincrement.*/
+#define NAND_NO_READRDY		0x00000100
 
 /* Options valid for Samsung large page devices */
 #define NAND_SAMSUNG_LP_OPTIONS \
@@ -219,18 +176,12 @@
 /* Use a flash based bad block table. This option is passed to the
  * default bad block table function. */
 #define NAND_USE_FLASH_BBT	0x00010000
-/* The hw ecc generator provides a syndrome instead a ecc value on read
- * This can only work if we have the ecc bytes directly behind the
- * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
-#define NAND_HWECC_SYNDROME	0x00020000
 /* This option skips the bbt scan during initialization. */
-#define NAND_SKIP_BBTSCAN	0x00040000
+#define NAND_SKIP_BBTSCAN	0x00020000
 
 /* Options set by nand scan */
-/* Nand scan has allocated oob_buf */
-#define NAND_OOBBUF_ALLOC	0x40000000
-/* Nand scan has allocated data_buf */
-#define NAND_DATABUF_ALLOC	0x80000000
+/* Nand scan has allocated controller struct */
+#define NAND_CONTROLLER_ALLOC	0x80000000
 
 
 /*
@@ -264,45 +215,102 @@
 };
 
 /**
+ * struct nand_ecc_ctrl - Control structure for ecc
+ * @mode:	ecc mode
+ * @steps:	number of ecc steps per page
+ * @size:	data bytes per ecc step
+ * @bytes:	ecc bytes per step
+ * @total:	total number of ecc bytes per page
+ * @prepad:	padding information for syndrome based ecc generators
+ * @postpad:	padding information for syndrome based ecc generators
+ * @hwctl:	function to control hardware ecc generator. Must only
+ *		be provided if an hardware ECC is available
+ * @calculate:	function for ecc calculation or readback from ecc hardware
+ * @correct:	function for ecc correction, matching to ecc generator (sw/hw)
+ * @read_page:	function to read a page according to the ecc generator requirements
+ * @write_page:	function to write a page according to the ecc generator requirements
+ */
+struct nand_ecc_ctrl {
+	nand_ecc_modes_t	mode;
+	int			steps;
+	int			size;
+	int			bytes;
+	int			total;
+	int			prepad;
+	int			postpad;
+	struct nand_ecclayout	*layout;
+	void			(*hwctl)(struct mtd_info *mtd, int mode);
+	int			(*calculate)(struct mtd_info *mtd,
+					     const uint8_t *dat,
+					     uint8_t *ecc_code);
+	int			(*correct)(struct mtd_info *mtd, uint8_t *dat,
+					   uint8_t *read_ecc,
+					   uint8_t *calc_ecc);
+	int			(*read_page)(struct mtd_info *mtd,
+					     struct nand_chip *chip,
+					     uint8_t *buf);
+	void			(*write_page)(struct mtd_info *mtd,
+					      struct nand_chip *chip,
+					      const uint8_t *buf);
+	int			(*read_oob)(struct mtd_info *mtd,
+					    struct nand_chip *chip,
+					    int page,
+					    int sndcmd);
+	int			(*write_oob)(struct mtd_info *mtd,
+					     struct nand_chip *chip,
+					     int page);
+};
+
+/**
+ * struct nand_buffers - buffer structure for read/write
+ * @ecccalc:	buffer for calculated ecc
+ * @ecccode:	buffer for ecc read from flash
+ * @oobwbuf:	buffer for write oob data
+ * @databuf:	buffer for data - dynamically sized
+ * @oobrbuf:	buffer to read oob data
+ *
+ * Do not change the order of buffers. databuf and oobrbuf must be in
+ * consecutive order.
+ */
+struct nand_buffers {
+	uint8_t	ecccalc[NAND_MAX_OOBSIZE];
+	uint8_t	ecccode[NAND_MAX_OOBSIZE];
+	uint8_t	oobwbuf[NAND_MAX_OOBSIZE];
+	uint8_t databuf[NAND_MAX_PAGESIZE];
+	uint8_t	oobrbuf[NAND_MAX_OOBSIZE];
+};
+
+/**
  * struct nand_chip - NAND Private Flash Chip Data
  * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the flash device
  * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the flash device
  * @read_byte:		[REPLACEABLE] read one byte from the chip
- * @write_byte:		[REPLACEABLE] write one byte to the chip
  * @read_word:		[REPLACEABLE] read one word from the chip
- * @write_word:		[REPLACEABLE] write one word to the chip
  * @write_buf:		[REPLACEABLE] write data from the buffer to the chip
  * @read_buf:		[REPLACEABLE] read data from the chip into the buffer
  * @verify_buf:		[REPLACEABLE] verify buffer contents against the chip data
  * @select_chip:	[REPLACEABLE] select chip nr
  * @block_bad:		[REPLACEABLE] check, if the block is bad
  * @block_markbad:	[REPLACEABLE] mark the block bad
- * @hwcontrol:		[BOARDSPECIFIC] hardwarespecific function for accesing control-lines
+ * @cmd_ctrl:		[BOARDSPECIFIC] hardwarespecific funtion for controlling
+ *			ALE/CLE/nCE. Also used to write command and address
  * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing device ready/busy line
  *			If set to NULL no access to ready/busy is available and the ready/busy information
  *			is read from the chip status register
  * @cmdfunc:		[REPLACEABLE] hardwarespecific function for writing commands to the chip
  * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on ready
- * @calculate_ecc: 	[REPLACEABLE] function for ecc calculation or readback from ecc hardware
- * @correct_data:	[REPLACEABLE] function for ecc correction, matching to ecc generator (sw/hw)
- * @enable_hwecc:	[BOARDSPECIFIC] function to enable (reset) hardware ecc generator. Must only
- *			be provided if a hardware ECC is available
+ * @ecc:		[BOARDSPECIFIC] ecc control ctructure
  * @erase_cmd:		[INTERN] erase command write function, selectable due to AND support
  * @scan_bbt:		[REPLACEABLE] function to scan bad block table
- * @eccmode:		[BOARDSPECIFIC] mode of ecc, see defines
- * @eccsize: 		[INTERN] databytes used per ecc-calculation
- * @eccbytes: 		[INTERN] number of ecc bytes per ecc-calculation step
- * @eccsteps:		[INTERN] number of ecc calculation steps per page
  * @chip_delay:		[BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR)
- * @chip_lock:		[INTERN] spinlock used to protect access to this structure and the chip
  * @wq:			[INTERN] wait queue to sleep on if a NAND operation is in progress
- * @state: 		[INTERN] the current state of the NAND device
+ * @state:		[INTERN] the current state of the NAND device
  * @page_shift:		[INTERN] number of address bits in a page (column address bits)
  * @phys_erase_shift:	[INTERN] number of address bits in a physical eraseblock
  * @bbt_erase_shift:	[INTERN] number of address bits in a bbt entry
  * @chip_shift:		[INTERN] number of address bits in one chip
- * @data_buf:		[INTERN] internal buffer for one page + oob
- * @oob_buf:		[INTERN] oob buffer for one eraseblock
+ * @datbuf:		[INTERN] internal buffer for one page + oob
+ * @oobbuf:		[INTERN] oob buffer for one eraseblock
  * @oobdirty:		[INTERN] indicates that oob_buf must be reinitialized
  * @data_poi:		[INTERN] pointer to a data buffer
  * @options:		[BOARDSPECIFIC] various chip options. They can partly be set to inform nand_scan about
@@ -312,12 +320,13 @@
  * @chipsize:		[INTERN] the size of one chip for multichip arrays
  * @pagemask:		[INTERN] page number mask = number of (pages / chip) - 1
  * @pagebuf:		[INTERN] holds the pagenumber which is currently in data_buf
- * @autooob:		[REPLACEABLE] the default (auto)placement scheme
+ * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash lookup
  * @bbt_md:		[REPLACEABLE] bad block table mirror descriptor
  * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial bad block scan
- * @controller:		[OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices
+ * @controller:		[REPLACEABLE] a pointer to a hardware controller structure
+ *			which is shared among multiple independend devices
  * @priv:		[OPTIONAL] pointer to private chip date
  * @errstat:		[OPTIONAL] hardware specific function to perform additional error status checks
  *			(determine if errors are correctable)
@@ -325,58 +334,57 @@
 
 struct nand_chip {
 	void  __iomem	*IO_ADDR_R;
-	void  __iomem 	*IO_ADDR_W;
+	void  __iomem	*IO_ADDR_W;
 
-	u_char		(*read_byte)(struct mtd_info *mtd);
-	void		(*write_byte)(struct mtd_info *mtd, u_char byte);
+	uint8_t		(*read_byte)(struct mtd_info *mtd);
 	u16		(*read_word)(struct mtd_info *mtd);
-	void		(*write_word)(struct mtd_info *mtd, u16 word);
-
-	void		(*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);
-	void		(*read_buf)(struct mtd_info *mtd, u_char *buf, int len);
-	int		(*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);
+	void		(*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+	void		(*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
+	int		(*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
 	void		(*select_chip)(struct mtd_info *mtd, int chip);
 	int		(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
 	int		(*block_markbad)(struct mtd_info *mtd, loff_t ofs);
-	void 		(*hwcontrol)(struct mtd_info *mtd, int cmd);
-	int  		(*dev_ready)(struct mtd_info *mtd);
-	void 		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
-	int 		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);
-	int		(*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
-	int 		(*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
-	void		(*enable_hwecc)(struct mtd_info *mtd, int mode);
+	void		(*cmd_ctrl)(struct mtd_info *mtd, int dat,
+				    unsigned int ctrl);
+	int		(*dev_ready)(struct mtd_info *mtd);
+	void		(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);
+	int		(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
 	void		(*erase_cmd)(struct mtd_info *mtd, int page);
 	int		(*scan_bbt)(struct mtd_info *mtd);
-	int		eccmode;
-	int		eccsize;
-	int		eccbytes;
-	int		eccsteps;
-	int 		chip_delay;
-	spinlock_t	chip_lock;
-	wait_queue_head_t wq;
-	nand_state_t 	state;
-	int 		page_shift;
+	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
+
+	int		chip_delay;
+	unsigned int	options;
+
+	int		page_shift;
 	int		phys_erase_shift;
 	int		bbt_erase_shift;
 	int		chip_shift;
-	u_char 		*data_buf;
-	u_char		*oob_buf;
-	int		oobdirty;
-	u_char		*data_poi;
-	unsigned int	options;
-	int		badblockpos;
 	int		numchips;
 	unsigned long	chipsize;
 	int		pagemask;
 	int		pagebuf;
-	struct nand_oobinfo	*autooob;
+	int		badblockpos;
+
+	nand_state_t	state;
+
+	uint8_t		*oob_poi;
+	struct nand_hw_control  *controller;
+	struct nand_ecclayout	*ecclayout;
+
+	struct nand_ecc_ctrl ecc;
+	struct nand_buffers buffers;
+	struct nand_hw_control hwcontrol;
+
+	struct mtd_oob_ops ops;
+
 	uint8_t		*bbt;
 	struct nand_bbt_descr	*bbt_td;
 	struct nand_bbt_descr	*bbt_md;
+
 	struct nand_bbt_descr	*badblock_pattern;
-	struct nand_hw_control  *controller;
+
 	void		*priv;
-	int		(*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state, int status, int page);
 };
 
 /*
@@ -388,19 +396,19 @@
 #define NAND_MFR_NATIONAL	0x8f
 #define NAND_MFR_RENESAS	0x07
 #define NAND_MFR_STMICRO	0x20
-#define NAND_MFR_HYNIX          0xad
+#define NAND_MFR_HYNIX		0xad
 
 /**
  * struct nand_flash_dev - NAND Flash Device ID Structure
  *
- * @name:  	Identify the device type
- * @id:   	device ID code
- * @pagesize:  	Pagesize in bytes. Either 256 or 512 or 0
+ * @name:	Identify the device type
+ * @id:		device ID code
+ * @pagesize:	Pagesize in bytes. Either 256 or 512 or 0
  *		If the pagesize is 0, then the real pagesize
  *		and the eraseize are determined from the
  *		extended id bytes in the chip
- * @erasesize: 	Size of an erase block in the flash device.
- * @chipsize:  	Total chipsize in Mega Bytes
+ * @erasesize:	Size of an erase block in the flash device.
+ * @chipsize:	Total chipsize in Mega Bytes
  * @options:	Bitfield to store chip relevant options
  */
 struct nand_flash_dev {
@@ -415,7 +423,7 @@
 /**
  * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
  * @name:	Manufacturer name
- * @id: 	manufacturer ID code of device.
+ * @id:		manufacturer ID code of device.
 */
 struct nand_manufacturers {
 	int id;
@@ -455,7 +463,7 @@
 	int	veroffs;
 	uint8_t	version[NAND_MAX_CHIPS];
 	int	len;
-	int 	maxblocks;
+	int	maxblocks;
 	int	reserved_block_code;
 	uint8_t	*pattern;
 };
@@ -494,14 +502,14 @@
 /* The maximum number of blocks to scan for a bbt */
 #define NAND_BBT_SCAN_MAXBLOCKS	4
 
-extern int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int nand_update_bbt (struct mtd_info *mtd, loff_t offs);
-extern int nand_default_bbt (struct mtd_info *mtd);
-extern int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt);
-extern int nand_erase_nand (struct mtd_info *mtd, struct erase_info *instr, int allowbbt);
-extern int nand_do_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
-                             size_t * retlen, u_char * buf, u_char * oob_buf,
-                             struct nand_oobinfo *oobsel, int flags);
+extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
+extern int nand_default_bbt(struct mtd_info *mtd);
+extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
+extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
+			   int allowbbt);
+extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
+			size_t * retlen, uint8_t * buf);
 
 /*
 * Constants for oob configuration
@@ -509,4 +517,53 @@
 #define NAND_SMALL_BADBLOCK_POS		5
 #define NAND_LARGE_BADBLOCK_POS		0
 
+/**
+ * struct platform_nand_chip - chip level device structure
+ *
+ * @nr_chips:		max. number of chips to scan for
+ * @chip_offs:		chip number offset
+ * @nr_partitions:	number of partitions pointed to by partitions (or zero)
+ * @partitions:		mtd partition list
+ * @chip_delay:		R/B delay value in us
+ * @options:		Option flags, e.g. 16bit buswidth
+ * @ecclayout:		ecc layout info structure
+ * @priv:		hardware controller specific settings
+ */
+struct platform_nand_chip {
+	int			nr_chips;
+	int			chip_offset;
+	int			nr_partitions;
+	struct mtd_partition	*partitions;
+	struct nand_ecclayout	*ecclayout;
+	int			chip_delay;
+	unsigned int		options;
+	void			*priv;
+};
+
+/**
+ * struct platform_nand_ctrl - controller level device structure
+ *
+ * @hwcontrol:		platform specific hardware control structure
+ * @dev_ready:		platform specific function to read ready/busy pin
+ * @select_chip:	platform specific chip select function
+ * @priv_data:		private data to transport driver specific settings
+ *
+ * All fields are optional and depend on the hardware driver requirements
+ */
+struct platform_nand_ctrl {
+	void		(*hwcontrol)(struct mtd_info *mtd, int cmd);
+	int		(*dev_ready)(struct mtd_info *mtd);
+	void		(*select_chip)(struct mtd_info *mtd, int chip);
+	void		*priv;
+};
+
+/* Some helpers to access the data structures */
+static inline
+struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	return chip->priv;
+}
+
 #endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/ndfc.h b/include/linux/mtd/ndfc.h
new file mode 100644
index 0000000..d0558a9
--- /dev/null
+++ b/include/linux/mtd/ndfc.h
@@ -0,0 +1,67 @@
+/*
+ *  linux/include/linux/mtd/ndfc.h
+ *
+ *  Copyright (c) 2006 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Info:
+ *   Contains defines, datastructures for ndfc nand controller
+ *
+ */
+#ifndef __LINUX_MTD_NDFC_H
+#define __LINUX_MTD_NDFC_H
+
+/* NDFC Register definitions */
+#define NDFC_CMD		0x00
+#define NDFC_ALE		0x04
+#define NDFC_DATA		0x08
+#define NDFC_ECC		0x10
+#define NDFC_BCFG0		0x30
+#define NDFC_BCFG1		0x34
+#define NDFC_BCFG2		0x38
+#define NDFC_BCFG3		0x3c
+#define NDFC_CCR		0x40
+#define NDFC_STAT		0x44
+#define NDFC_HWCTL		0x48
+#define NDFC_REVID		0x50
+
+#define NDFC_STAT_IS_READY	0x01000000
+
+#define NDFC_CCR_RESET_CE	0x80000000 /* CE Reset */
+#define NDFC_CCR_RESET_ECC	0x40000000 /* ECC Reset */
+#define NDFC_CCR_RIE		0x20000000 /* Interrupt Enable on Device Rdy */
+#define NDFC_CCR_REN		0x10000000 /* Enable wait for Rdy in LinearR */
+#define NDFC_CCR_ROMEN		0x08000000 /* Enable ROM In LinearR */
+#define NDFC_CCR_ARE		0x04000000 /* Auto-Read Enable */
+#define NDFC_CCR_BS(x)		(((x) & 0x3) << 24) /* Select Bank on CE[x] */
+#define NDFC_CCR_BS_MASK	0x03000000 /* Select Bank */
+#define NDFC_CCR_ARAC0		0x00000000 /* 3 Addr, 1 Col 2 Row 512b page */
+#define NDFC_CCR_ARAC1		0x00001000 /* 4 Addr, 1 Col 3 Row 512b page */
+#define NDFC_CCR_ARAC2		0x00002000 /* 4 Addr, 2 Col 2 Row 2K page */
+#define NDFC_CCR_ARAC3		0x00003000 /* 5 Addr, 2 Col 3 Row 2K page */
+#define NDFC_CCR_ARAC_MASK	0x00003000 /* Auto-Read mode Addr Cycles */
+#define NDFC_CCR_RPG		0x0000C000 /* Auto-Read Page */
+#define NDFC_CCR_EBCC		0x00000004 /* EBC Configuration Completed */
+#define NDFC_CCR_DHC		0x00000002 /* Direct Hardware Control Enable */
+
+#define NDFC_BxCFG_EN		0x80000000 /* Bank Enable */
+#define NDFC_BxCFG_CED		0x40000000 /* nCE Style */
+#define NDFC_BxCFG_SZ_MASK	0x08000000 /* Bank Size */
+#define NDFC_BxCFG_SZ_8BIT	0x00000000 /* 8bit */
+#define NDFC_BxCFG_SZ_16BIT	0x08000000 /* 16bit */
+
+#define NDFC_MAX_BANKS		4
+
+struct ndfc_controller_settings {
+	uint32_t	ccr_settings;
+	uint64_t	ndfc_erpn;
+};
+
+struct ndfc_chip_settings {
+	uint32_t	bank_settings;
+};
+
+#endif
diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h
index d35d2c2..bcf2fb3f 100644
--- a/include/linux/mtd/nftl.h
+++ b/include/linux/mtd/nftl.h
@@ -37,7 +37,7 @@
         unsigned int nb_blocks;		/* number of physical blocks */
         unsigned int nb_boot_blocks;	/* number of blocks used by the bios */
         struct erase_info instr;
-	struct nand_oobinfo oobinfo;
+	struct nand_ecclayout oobinfo;
 };
 
 int NFTL_mount(struct NFTLrecord *s);
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 7419b5f..9ce9a48 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -35,6 +35,8 @@
 	FL_SYNCING,
 	FL_UNLOCKING,
 	FL_LOCKING,
+	FL_RESETING,
+	FL_OTPING,
 	FL_PM_SUSPENDED,
 } onenand_state_t;
 
@@ -75,7 +77,7 @@
  * @param chip_lock	[INTERN] spinlock used to protect access to this structure and the chip
  * @param wq		[INTERN] wait queue to sleep on if a OneNAND operation is in progress
  * @param state		[INTERN] the current state of the OneNAND device
- * @param autooob	[REPLACEABLE] the default (auto)placement scheme
+ * @param ecclayout	[REPLACEABLE] the default ecc placement scheme
  * @param bbm		[REPLACEABLE] pointer to Bad Block Management
  * @param priv		[OPTIONAL] pointer to private chip date
  */
@@ -111,9 +113,9 @@
 	onenand_state_t		state;
 	unsigned char		*page_buf;
 
-	struct nand_oobinfo	*autooob;
+	struct nand_ecclayout	*ecclayout;
 
-	void 			*bbm;
+	void			*bbm;
 
 	void			*priv;
 };
@@ -130,6 +132,9 @@
 #define ONENAND_SET_SYS_CFG1(v, this)					\
 	(this->write_word(v, this->base + ONENAND_REG_SYS_CFG1))
 
+/* Check byte access in OneNAND */
+#define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
+
 /*
  * Options bits
  */
diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h
index d7832ef..4a72818 100644
--- a/include/linux/mtd/onenand_regs.h
+++ b/include/linux/mtd/onenand_regs.h
@@ -112,6 +112,7 @@
 #define ONENAND_CMD_LOCK_TIGHT		(0x2C)
 #define ONENAND_CMD_ERASE		(0x94)
 #define ONENAND_CMD_RESET		(0xF0)
+#define ONENAND_CMD_OTP_ACCESS		(0x65)
 #define ONENAND_CMD_READID		(0x90)
 
 /* NOTE: Those are not *REAL* commands */
@@ -152,6 +153,8 @@
 #define ONENAND_CTRL_ERASE		(1 << 11)
 #define ONENAND_CTRL_ERROR		(1 << 10)
 #define ONENAND_CTRL_RSTB		(1 << 7)
+#define ONENAND_CTRL_OTP_L		(1 << 6)
+#define ONENAND_CTRL_OTP_BL		(1 << 5)
 
 /*
  * Interrupt Status Register F241h (R)
@@ -177,4 +180,9 @@
 #define ONENAND_ECC_2BIT		(1 << 1)
 #define ONENAND_ECC_2BIT_ALL		(0xAAAA)
 
+/*
+ * One-Time Programmable (OTP)
+ */
+#define ONENAND_OTP_LOCK_OFFSET		(14)
+
 #endif	/* __ONENAND_REG_H */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index b03f512..da6b3d6 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -41,7 +41,7 @@
 	u_int32_t size;			/* partition size */
 	u_int32_t offset;		/* offset within the master MTD space */
 	u_int32_t mask_flags;		/* master MTD flags to mask out for this partition */
-	struct nand_oobinfo *oobsel;	/* out of band layout for this partition (NAND only)*/
+	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only)*/
 	struct mtd_info **mtdp;		/* pointer to store the MTD object */
 };
 
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index c7b8bcd..86831e3 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -15,33 +15,26 @@
  */
 
 #ifndef __LINUX_MTD_PHYSMAP__
-
-#include <linux/config.h>
-
-#if defined(CONFIG_MTD_PHYSMAP)
+#define __LINUX_MTD_PHYSMAP__
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/partitions.h>
 
-/*
- * The map_info for physmap.  Board can override size, buswidth, phys,
- * (*set_vpp)(), etc in their initial setup routine.
- */
-extern struct map_info physmap_map;
+struct physmap_flash_data {
+	unsigned int		width;
+	void			(*set_vpp)(struct map_info *, int);
+	unsigned int		nr_parts;
+	struct mtd_partition	*parts;
+};
 
 /*
  * Board needs to specify the exact mapping during their setup time.
  */
-static inline void physmap_configure(unsigned long addr, unsigned long size, int bankwidth, void (*set_vpp)(struct map_info *, int) )
-{
-	physmap_map.phys = addr;
-	physmap_map.size = size;
-	physmap_map.bankwidth = bankwidth;
-	physmap_map.set_vpp = set_vpp;
-}
+void physmap_configure(unsigned long addr, unsigned long size,
+		int bankwidth, void (*set_vpp)(struct map_info *, int) );
 
-#if defined(CONFIG_MTD_PARTITIONS)
+#ifdef CONFIG_MTD_PARTITIONS
 
 /*
  * Machines that wish to do flash partition may want to call this function in
@@ -55,7 +48,5 @@
 void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
 
 #endif /* defined(CONFIG_MTD_PARTITIONS) */
-#endif /* defined(CONFIG_MTD) */
 
 #endif /* __LINUX_MTD_PHYSMAP__ */
-
diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h
index 220d50b..e9d40bd 100644
--- a/include/linux/mtd/xip.h
+++ b/include/linux/mtd/xip.h
@@ -18,7 +18,6 @@
 #ifndef __LINUX_MTD_XIP_H__
 #define __LINUX_MTD_XIP_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_MTD_XIP
 
diff --git a/include/linux/nbd.h b/include/linux/nbd.h
index a6ce409..e712e7d 100644
--- a/include/linux/nbd.h
+++ b/include/linux/nbd.h
@@ -77,11 +77,11 @@
  * server. All data are in network byte order.
  */
 struct nbd_request {
-	u32 magic;
-	u32 type;	/* == READ || == WRITE 	*/
+	__be32 magic;
+	__be32 type;	/* == READ || == WRITE 	*/
 	char handle[8];
-	u64 from;
-	u32 len;
+	__be64 from;
+	__be32 len;
 }
 #ifdef __GNUC__
 	__attribute__ ((packed))
@@ -93,8 +93,8 @@
  * it has completed an I/O request (or an error occurs).
  */
 struct nbd_reply {
-	u32 magic;
-	u32 error;		/* 0 = ok, else error	*/
+	__be32 magic;
+	__be32 error;		/* 0 = ok, else error	*/
 	char handle[8];		/* handle you got from request	*/
 };
 #endif
diff --git a/include/linux/ncp_fs.h b/include/linux/ncp_fs.h
index 96dc237..b208f0c 100644
--- a/include/linux/ncp_fs.h
+++ b/include/linux/ncp_fs.h
@@ -12,8 +12,6 @@
 #include <linux/in.h>
 #include <linux/types.h>
 
-#include <linux/ncp_fs_i.h>
-#include <linux/ncp_fs_sb.h>
 #include <linux/ipx.h>
 #include <linux/ncp_no.h>
 
@@ -146,7 +144,8 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
+#include <linux/ncp_fs_i.h>
+#include <linux/ncp_fs_sb.h>
 
 /* undef because public define in umsdos_fs.h (ncp_fs.h isn't public) */
 #undef PRINTK
diff --git a/include/linux/net.h b/include/linux/net.h
index 84a490e..385e68f 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -18,9 +18,7 @@
 #ifndef _LINUX_NET_H
 #define _LINUX_NET_H
 
-#include <linux/config.h>
 #include <linux/wait.h>
-#include <linux/stringify.h>
 #include <asm/socket.h>
 
 struct poll_table_struct;
@@ -57,6 +55,7 @@
 #define __SO_ACCEPTCON	(1 << 16)	/* performed a listen		*/
 
 #ifdef __KERNEL__
+#include <linux/stringify.h>
 
 #define SOCK_ASYNC_NOSPACE	0
 #define SOCK_ASYNC_WAITDATA	1
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f4169bb..03cd755 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -34,9 +34,9 @@
 #include <asm/cache.h>
 #include <asm/byteorder.h>
 
-#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/percpu.h>
+#include <linux/dmaengine.h>
 
 struct divert_blk;
 struct vlan_group;
@@ -232,6 +232,7 @@
 	__LINK_STATE_RX_SCHED,
 	__LINK_STATE_LINKWATCH_PENDING,
 	__LINK_STATE_DORMANT,
+	__LINK_STATE_QDISC_RUNNING,
 };
 
 
@@ -307,9 +308,16 @@
 #define NETIF_F_HW_VLAN_RX	256	/* Receive VLAN hw acceleration */
 #define NETIF_F_HW_VLAN_FILTER	512	/* Receive filtering on VLAN */
 #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
-#define NETIF_F_TSO		2048	/* Can offload TCP/IP segmentation */
+#define NETIF_F_GSO		2048	/* Enable software GSO. */
 #define NETIF_F_LLTX		4096	/* LockLess TX */
-#define NETIF_F_UFO             8192    /* Can offload UDP Large Send*/
+
+	/* Segmentation offload features */
+#define NETIF_F_GSO_SHIFT	16
+#define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
+#define NETIF_F_UFO		(SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
+
+#define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
+#define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
 
 	struct net_device	*next_sched;
 
@@ -398,6 +406,9 @@
 	struct list_head	qdisc_list;
 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
 
+	/* Partially transmitted GSO packet. */
+	struct sk_buff		*gso_skb;
+
 	/* ingress path synchronizer */
 	spinlock_t		ingress_lock;
 	struct Qdisc		*qdisc_ingress;
@@ -406,7 +417,7 @@
  * One part is mostly used on xmit path (device)
  */
 	/* hard_start_xmit synchronizer */
-	spinlock_t		xmit_lock ____cacheline_aligned_in_smp;
+	spinlock_t		_xmit_lock ____cacheline_aligned_in_smp;
 	/* cpu id of processor entered to hard_start_xmit or -1,
 	   if nobody entered there.
 	 */
@@ -532,6 +543,7 @@
 					 struct net_device *,
 					 struct packet_type *,
 					 struct net_device *);
+	struct sk_buff		*(*gso_segment)(struct sk_buff *skb, int sg);
 	void			*af_packet_priv;
 	struct list_head	list;
 };
@@ -593,6 +605,9 @@
 	struct sk_buff		*completion_queue;
 
 	struct net_device	backlog_dev;	/* Sorry. 8) */
+#ifdef CONFIG_NET_DMA
+	struct dma_chan		*net_dma;
+#endif
 };
 
 DECLARE_PER_CPU(struct softnet_data,softnet_data);
@@ -679,11 +694,11 @@
 extern int		dev_set_mtu(struct net_device *, int);
 extern int		dev_set_mac_address(struct net_device *,
 					    struct sockaddr *);
-extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
+extern int		dev_hard_start_xmit(struct sk_buff *skb,
+					    struct net_device *dev);
 
 extern void		dev_init(void);
 
-extern int		netdev_nit;
 extern int		netdev_budget;
 
 /* Called by rtnetlink.c:rtnl_unlock() */
@@ -889,11 +904,43 @@
 	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
 }
 
+static inline void netif_tx_lock(struct net_device *dev)
+{
+	spin_lock(&dev->_xmit_lock);
+	dev->xmit_lock_owner = smp_processor_id();
+}
+
+static inline void netif_tx_lock_bh(struct net_device *dev)
+{
+	spin_lock_bh(&dev->_xmit_lock);
+	dev->xmit_lock_owner = smp_processor_id();
+}
+
+static inline int netif_tx_trylock(struct net_device *dev)
+{
+	int err = spin_trylock(&dev->_xmit_lock);
+	if (!err)
+		dev->xmit_lock_owner = smp_processor_id();
+	return err;
+}
+
+static inline void netif_tx_unlock(struct net_device *dev)
+{
+	dev->xmit_lock_owner = -1;
+	spin_unlock(&dev->_xmit_lock);
+}
+
+static inline void netif_tx_unlock_bh(struct net_device *dev)
+{
+	dev->xmit_lock_owner = -1;
+	spin_unlock_bh(&dev->_xmit_lock);
+}
+
 static inline void netif_tx_disable(struct net_device *dev)
 {
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	netif_stop_queue(dev);
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 }
 
 /* These functions live elsewhere (drivers/net/net_init.c, but related) */
@@ -921,6 +968,7 @@
 extern int		weight_p;
 extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
 extern int skb_checksum_help(struct sk_buff *skb, int inward);
+extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg);
 #ifdef CONFIG_BUG
 extern void netdev_rx_csum_fault(struct net_device *dev);
 #else
@@ -940,6 +988,13 @@
 
 extern void linkwatch_run_queue(void);
 
+static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
+{
+	int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
+	return skb_shinfo(skb)->gso_size &&
+	       (dev->features & feature) != feature;
+}
+
 #endif /* __KERNEL__ */
 
 #endif	/* _LINUX_DEV_H */
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index b31a9bc..10168e2 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -40,7 +40,6 @@
 #endif
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #ifdef CONFIG_NETFILTER
 
 extern void netfilter_init(void);
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 3ff88c8..d2e4bd7 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -69,6 +69,10 @@
 	/* Connection is dying (removed from lists), can not be unset. */
 	IPS_DYING_BIT = 9,
 	IPS_DYING = (1 << IPS_DYING_BIT),
+
+	/* Connection has fixed timeout. */
+	IPS_FIXED_TIMEOUT_BIT = 10,
+	IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
 };
 
 /* Connection tracking event bits */
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h
index 668ec94..b5883cc 100644
--- a/include/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux/netfilter/nfnetlink_conntrack.h
@@ -27,13 +27,15 @@
 	CTA_STATUS,
 	CTA_PROTOINFO,
 	CTA_HELP,
-	CTA_NAT,
+	CTA_NAT_SRC,
+#define CTA_NAT	CTA_NAT_SRC	/* backwards compatibility */
 	CTA_TIMEOUT,
 	CTA_MARK,
 	CTA_COUNTERS_ORIG,
 	CTA_COUNTERS_REPLY,
 	CTA_USE,
 	CTA_ID,
+	CTA_NAT_DST,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
diff --git a/include/linux/netfilter/xt_CONNSECMARK.h b/include/linux/netfilter/xt_CONNSECMARK.h
new file mode 100644
index 0000000..c6bd754
--- /dev/null
+++ b/include/linux/netfilter/xt_CONNSECMARK.h
@@ -0,0 +1,13 @@
+#ifndef _XT_CONNSECMARK_H_target
+#define _XT_CONNSECMARK_H_target
+
+enum {
+	CONNSECMARK_SAVE = 1,
+	CONNSECMARK_RESTORE,
+};
+
+struct xt_connsecmark_target_info {
+	u_int8_t mode;
+};
+
+#endif /*_XT_CONNSECMARK_H_target */
diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h
new file mode 100644
index 0000000..c53fbff
--- /dev/null
+++ b/include/linux/netfilter/xt_SECMARK.h
@@ -0,0 +1,26 @@
+#ifndef _XT_SECMARK_H_target
+#define _XT_SECMARK_H_target
+
+/*
+ * This is intended for use by various security subsystems (but not
+ * at the same time).
+ *
+ * 'mode' refers to the specific security subsystem which the
+ * packets are being marked for.
+ */
+#define SECMARK_MODE_SEL	0x01		/* SELinux */
+#define SECMARK_SELCTX_MAX	256
+
+struct xt_secmark_target_selinux_info {
+	u_int32_t selsid;
+	char selctx[SECMARK_SELCTX_MAX];
+};
+
+struct xt_secmark_target_info {
+	u_int8_t mode;
+	union {
+		struct xt_secmark_target_selinux_info sel;
+	} u;
+};
+
+#endif /*_XT_SECMARK_H_target */
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h
index 34f63cf..4c2d994 100644
--- a/include/linux/netfilter/xt_conntrack.h
+++ b/include/linux/netfilter/xt_conntrack.h
@@ -42,7 +42,7 @@
 		} u;
 
 		/* The protocol. */
-		u16 protonum;
+		__u16 protonum;
 	} dst;
 };
 
diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h
new file mode 100644
index 0000000..acd7fd7
--- /dev/null
+++ b/include/linux/netfilter/xt_quota.h
@@ -0,0 +1,16 @@
+#ifndef _XT_QUOTA_H
+#define _XT_QUOTA_H
+
+enum xt_quota_flags {
+	XT_QUOTA_INVERT		= 0x1,
+};
+#define XT_QUOTA_MASK		0x1
+
+struct xt_quota_info {
+	u_int32_t		flags;
+	u_int32_t		pad;
+	aligned_u64		quota;
+	struct xt_quota_info	*master;
+};
+
+#endif /* _XT_QUOTA_H */
diff --git a/include/linux/netfilter/xt_statistic.h b/include/linux/netfilter/xt_statistic.h
new file mode 100644
index 0000000..c344e99
--- /dev/null
+++ b/include/linux/netfilter/xt_statistic.h
@@ -0,0 +1,32 @@
+#ifndef _XT_STATISTIC_H
+#define _XT_STATISTIC_H
+
+enum xt_statistic_mode {
+	XT_STATISTIC_MODE_RANDOM,
+	XT_STATISTIC_MODE_NTH,
+	__XT_STATISTIC_MODE_MAX
+};
+#define XT_STATISTIC_MODE_MAX (__XT_STATISTIC_MODE_MAX - 1)
+
+enum xt_statistic_flags {
+	XT_STATISTIC_INVERT		= 0x1,
+};
+#define XT_STATISTIC_MASK		0x1
+
+struct xt_statistic_info {
+	u_int16_t			mode;
+	u_int16_t			flags;
+	union {
+		struct {
+			u_int32_t	probability;
+		} random;
+		struct {
+			u_int32_t	every;
+			u_int32_t	packet;
+			u_int32_t	count;
+		} nth;
+	} u;
+	struct xt_statistic_info	*master __attribute__((aligned(8)));
+};
+
+#endif /* _XT_STATISTIC_H */
diff --git a/include/linux/netfilter_arp.h b/include/linux/netfilter_arp.h
index a3f8977..92bc6dd 100644
--- a/include/linux/netfilter_arp.h
+++ b/include/linux/netfilter_arp.h
@@ -5,7 +5,6 @@
  * (C)2002 Rusty Russell IBM -- This code is GPL.
  */
 
-#include <linux/config.h>
 #include <linux/netfilter.h>
 
 /* There is no PF_ARP. */
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index a75b84b..8776402 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -4,7 +4,6 @@
 /* bridge-specific defines for netfilter. 
  */
 
-#include <linux/config.h>
 #include <linux/netfilter.h>
 #if defined(__KERNEL__) && defined(CONFIG_BRIDGE_NETFILTER)
 #include <asm/atomic.h>
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 85301c5..ce02c98 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -5,7 +5,6 @@
  * (C)1998 Rusty Russell -- This code is GPL.
  */
 
-#include <linux/config.h>
 #include <linux/netfilter.h>
 
 /* only for userspace compatibility */
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h
index d54d7b27..51dbec1 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack.h
@@ -4,7 +4,6 @@
 #include <linux/netfilter/nf_conntrack_common.h>
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
 #include <linux/bitops.h>
 #include <linux/compiler.h>
@@ -121,6 +120,10 @@
 	u_int32_t mark;
 #endif
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+	u_int32_t secmark;
+#endif
+
 	/* Traversed often, so hopefully in different cacheline to top */
 	/* These are my tuples; original and reply */
 	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
@@ -154,6 +157,7 @@
 	unsigned int flags;
 
 #ifdef CONFIG_IP_NF_NAT_NEEDED
+	u_int32_t saved_ip;
 	/* This is the original per-proto part, used to map the
 	 * expected connection the way the recipient expects. */
 	union ip_conntrack_manip_proto saved_proto;
@@ -293,6 +297,7 @@
 }
 
 extern unsigned int ip_conntrack_htable_size;
+extern int ip_conntrack_checksum;
  
 #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
 
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_h323.h b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
index eace86b..3cbff73 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_h323.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_h323.h
@@ -71,6 +71,13 @@
 			     unsigned char **data, int dataoff,
 			     TransportAddress * addr, u_int16_t port,
 			     struct ip_conntrack_expect * exp);
+extern int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
+				       struct ip_conntrack * ct,
+				       enum ip_conntrack_info ctinfo,
+				       unsigned char **data, int dataoff,
+				       TransportAddress * addr,
+				       u_int16_t port,
+				       struct ip_conntrack_expect * exp);
 extern int (*nat_q931_hook) (struct sk_buff ** pskb, struct ip_conntrack * ct,
 			     enum ip_conntrack_info ctinfo,
 			     unsigned char **data, TransportAddress * addr,
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
index cc98f7a..3d4a773 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_helper_h323_types.h
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -412,6 +412,7 @@
 		eFacility_UUIE_destinationInfo = (1 << 14),
 		eFacility_UUIE_h245SecurityMode = (1 << 13),
 	} options;
+	TransportAddress alternativeAddress;
 	FacilityReason reason;
 	TransportAddress h245Address;
 	Facility_UUIE_fastStart fastStart;
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
new file mode 100644
index 0000000..913dad6
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h
@@ -0,0 +1,44 @@
+#ifndef __IP_CONNTRACK_SIP_H__
+#define __IP_CONNTRACK_SIP_H__
+#ifdef __KERNEL__
+
+#define SIP_PORT	5060
+#define SIP_TIMEOUT	3600
+
+#define POS_VIA		0
+#define POS_CONTACT	1
+#define POS_CONTENT	2
+#define POS_MEDIA	3
+#define POS_OWNER	4
+#define POS_CONNECTION	5
+#define POS_REQ_HEADER	6
+#define POS_SDP_HEADER	7
+
+struct sip_header_nfo {
+	const char	*lname;
+	const char	*sname;
+	const char	*ln_str;
+	size_t		lnlen;
+	size_t		snlen;
+	size_t		ln_strlen;
+	int		(*match_len)(const char *, const char *, int *);
+};
+
+extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+				       enum ip_conntrack_info ctinfo,
+				       struct ip_conntrack *ct,
+				       const char **dptr);
+extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
+				       enum ip_conntrack_info ctinfo,
+				       struct ip_conntrack_expect *exp,
+				       const char *dptr);
+
+extern int ct_sip_get_info(const char *dptr, size_t dlen,
+			   unsigned int *matchoff,
+			   unsigned int *matchlen,
+			   struct sip_header_nfo *hnfo);
+extern int ct_sip_lnlen(const char *line, const char *limit);
+extern const char *ct_sip_search(const char *needle, const char *haystack,
+                                 size_t needle_len, size_t haystack_len);
+#endif /* __KERNEL__ */
+#endif /* __IP_CONNTRACK_SIP_H__ */
diff --git a/include/linux/netfilter_ipv4/listhelp.h b/include/linux/netfilter_ipv4/listhelp.h
index 360429f..5d92cf0 100644
--- a/include/linux/netfilter_ipv4/listhelp.h
+++ b/include/linux/netfilter_ipv4/listhelp.h
@@ -1,6 +1,5 @@
 #ifndef _LISTHELP_H
 #define _LISTHELP_H
-#include <linux/config.h>
 #include <linux/list.h>
 
 /* Header to do more comprehensive job than linux/list.h; assume list
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 87b8a57..855b446 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -5,7 +5,7 @@
 #include <linux/types.h>
 
 #define NETLINK_ROUTE		0	/* Routing/device hook				*/
-#define NETLINK_W1		1	/* 1-wire subsystem				*/
+#define NETLINK_UNUSED		1	/* Unused number				*/
 #define NETLINK_USERSOCK	2	/* Reserved for user mode socket protocols 	*/
 #define NETLINK_FIREWALL	3	/* Firewalling hook				*/
 #define NETLINK_INET_DIAG	4	/* INET socket monitoring			*/
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index ca5a873..1efe60c 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -31,6 +31,7 @@
 	int rx_flags;
 	spinlock_t rx_lock;
 	struct netpoll *rx_np; /* netpoll that registered an rx_hook */
+	struct sk_buff_head arp_tx; /* list of arp requests to reply to */
 };
 
 void netpoll_poll(struct netpoll *np);
diff --git a/include/linux/nfs.h b/include/linux/nfs.h
index ca2ffa6..54af92c 100644
--- a/include/linux/nfs.h
+++ b/include/linux/nfs.h
@@ -7,9 +7,6 @@
 #ifndef _LINUX_NFS_H
 #define _LINUX_NFS_H
 
-#include <linux/sunrpc/msg_prot.h>
-#include <linux/string.h>
-
 #define NFS_PROGRAM	100003
 #define NFS_PORT	2049
 #define NFS_MAXDATA	8192
@@ -129,7 +126,10 @@
 	NFFIFO = 8
 };
 
-#if defined(__KERNEL__)
+#ifdef __KERNEL__
+#include <linux/sunrpc/msg_prot.h>
+#include <linux/string.h>
+
 /*
  * This is the kernel NFS client file handle representation
  */
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 0c1c306..5f681d5 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -14,7 +14,6 @@
 #define _LINUX_NFS4_H
 
 #include <linux/types.h>
-#include <linux/list.h>
 
 #define NFS4_VERIFIER_SIZE	8
 #define NFS4_FHSIZE		128
@@ -97,6 +96,9 @@
 	NFS4_ACL_WHO_EVERYONE,
 };
 
+#ifdef __KERNEL__
+#include <linux/list.h>
+
 struct nfs4_ace {
 	uint32_t	type;
 	uint32_t	flag;
@@ -345,8 +347,6 @@
 #define NFS4_MINOR_VERSION 0
 #define NFS4_DEBUG 1
 
-#ifdef __KERNEL__
-
 /* Index of predefined Linux client operations */
 
 enum {
@@ -384,6 +384,7 @@
 	NFSPROC4_CLNT_DELEGRETURN,
 	NFSPROC4_CLNT_GETACL,
 	NFSPROC4_CLNT_SETACL,
+	NFSPROC4_CLNT_FS_LOCATIONS,
 };
 
 #endif
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index c71227d..d90b1bb 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -16,8 +16,6 @@
 #include <linux/rwsem.h>
 #include <linux/wait.h>
 
-#include <linux/nfs_fs_sb.h>
-
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/sunrpc/clnt.h>
@@ -27,6 +25,9 @@
 #include <linux/nfs3.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_xdr.h>
+
+#include <linux/nfs_fs_sb.h>
+
 #include <linux/rwsem.h>
 #include <linux/mempool.h>
 
@@ -61,6 +62,7 @@
 #define FLUSH_LOWPRI		8	/* low priority background flush */
 #define FLUSH_HIGHPRI		16	/* high priority memory reclaim flush */
 #define FLUSH_NOCOMMIT		32	/* Don't send the NFSv3/v4 COMMIT */
+#define FLUSH_INVALIDATE	64	/* Invalidate the page cache */
 
 #ifdef __KERNEL__
 
@@ -234,8 +236,12 @@
 
 static inline void nfs_mark_for_revalidate(struct inode *inode)
 {
+	struct nfs_inode *nfsi = NFS_I(inode);
+
 	spin_lock(&inode->i_lock);
-	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+	nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+	if (S_ISDIR(inode->i_mode))
+		nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA;
 	spin_unlock(&inode->i_lock);
 }
 
@@ -297,7 +303,7 @@
 extern int nfs_attribute_timeout(struct inode *inode);
 extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
-extern void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
+extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern void nfs_begin_attr_update(struct inode *);
@@ -307,6 +313,10 @@
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode);
+extern struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+					const struct dentry *dentry,
+					struct nfs_fh *fh,
+					struct nfs_fattr *fattr);
 
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern u32 root_nfs_parse_addr(char *name); /*__init*/
@@ -325,7 +335,7 @@
 extern struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
-extern struct address_space_operations nfs_file_aops;
+extern const struct address_space_operations nfs_file_aops;
 
 static inline struct rpc_cred *nfs_file_cred(struct file *file)
 {
@@ -393,6 +403,15 @@
 #endif
 
 /*
+ * linux/fs/nfs/namespace.c
+ */
+extern struct list_head nfs_automount_list;
+extern struct inode_operations nfs_mountpoint_inode_operations;
+extern struct inode_operations nfs_referral_inode_operations;
+extern int nfs_mountpoint_expiry_timeout;
+extern void nfs_release_automount_timer(void);
+
+/*
  * linux/fs/nfs/unlink.c
  */
 extern int  nfs_async_unlink(struct dentry *);
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 65dec21..6b4a13c 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -35,6 +35,7 @@
 	char *			hostname;	/* remote hostname */
 	struct nfs_fh		fh;
 	struct sockaddr_in	addr;
+	struct nfs_fsid		fsid;
 	unsigned long		mount_time;	/* when this fs was mounted */
 #ifdef CONFIG_NFS_V4
 	/* Our own IP address, as a null-terminated string.
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 66e2ed6..1f7bd28 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -13,7 +13,6 @@
 #include <linux/list.h>
 #include <linux/pagemap.h>
 #include <linux/wait.h>
-#include <linux/nfs_fs_sb.h>
 #include <linux/sunrpc/auth.h>
 #include <linux/nfs_xdr.h>
 
@@ -63,8 +62,8 @@
 
 extern  int nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
 				unsigned long idx_start, unsigned int npages);
-extern	int nfs_scan_list(struct list_head *, struct list_head *,
-			  unsigned long, unsigned int);
+extern	int nfs_scan_list(struct nfs_inode *nfsi, struct list_head *head, struct list_head *dst,
+			  unsigned long idx_start, unsigned int npages);
 extern	int nfs_coalesce_requests(struct list_head *, struct list_head *,
 				  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 7fafc4c..7c7320f 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -14,11 +14,19 @@
 #define NFS_DEF_FILE_IO_SIZE	(4096U)
 #define NFS_MIN_FILE_IO_SIZE	(1024U)
 
-struct nfs4_fsid {
-	__u64 major;
-	__u64 minor;
+struct nfs_fsid {
+	uint64_t		major;
+	uint64_t		minor;
 };
 
+/*
+ * Helper for checking equality between 2 fsids.
+ */
+static inline int nfs_fsid_equal(const struct nfs_fsid *a, const struct nfs_fsid *b)
+{
+	return a->major == b->major && a->minor == b->minor;
+}
+
 struct nfs_fattr {
 	unsigned short		valid;		/* which fields are valid */
 	__u64			pre_size;	/* pre_op_attr.size	  */
@@ -40,10 +48,7 @@
 		} nfs3;
 	} du;
 	dev_t			rdev;
-	union {
-		__u64		nfs3;		/* also nfs2 */
-		struct nfs4_fsid nfs4;
-	} fsid_u;
+	struct nfs_fsid		fsid;
 	__u64			fileid;
 	struct timespec		atime;
 	struct timespec		mtime;
@@ -57,8 +62,8 @@
 #define NFS_ATTR_WCC		0x0001		/* pre-op WCC data    */
 #define NFS_ATTR_FATTR		0x0002		/* post-op attributes */
 #define NFS_ATTR_FATTR_V3	0x0004		/* NFSv3 attributes */
-#define NFS_ATTR_FATTR_V4	0x0008
-#define NFS_ATTR_PRE_CHANGE	0x0010
+#define NFS_ATTR_FATTR_V4	0x0008		/* NFSv4 change attribute */
+#define NFS_ATTR_FATTR_V4_REFERRAL	0x0010		/* NFSv4 referral */
 
 /*
  * Info on the file system
@@ -675,6 +680,40 @@
 	u32				has_symlinks;
 };
 
+struct nfs4_string {
+	unsigned int len;
+	char *data;
+};
+
+#define NFS4_PATHNAME_MAXCOMPONENTS 512
+struct nfs4_pathname {
+	unsigned int ncomponents;
+	struct nfs4_string components[NFS4_PATHNAME_MAXCOMPONENTS];
+};
+
+#define NFS4_FS_LOCATION_MAXSERVERS 10
+struct nfs4_fs_location {
+	unsigned int nservers;
+	struct nfs4_string servers[NFS4_FS_LOCATION_MAXSERVERS];
+	struct nfs4_pathname rootpath;
+};
+
+#define NFS4_FS_LOCATIONS_MAXENTRIES 10
+struct nfs4_fs_locations {
+	struct nfs_fattr fattr;
+	const struct nfs_server *server;
+	struct nfs4_pathname fs_path;
+	int nlocations;
+	struct nfs4_fs_location locations[NFS4_FS_LOCATIONS_MAXENTRIES];
+};
+
+struct nfs4_fs_locations_arg {
+	const struct nfs_fh *dir_fh;
+	const struct qstr *name;
+	struct page *page;
+	const u32 *bitmask;
+};
+
 #endif /* CONFIG_NFS_V4 */
 
 struct nfs_page;
@@ -695,7 +734,7 @@
 #ifdef CONFIG_NFS_V4
 	unsigned long		timestamp;	/* For lease renewal */
 #endif
-	struct page		*page_array[NFS_PAGEVEC_SIZE + 1];
+	struct page		*page_array[NFS_PAGEVEC_SIZE];
 };
 
 struct nfs_write_data {
@@ -713,7 +752,7 @@
 #ifdef CONFIG_NFS_V4
 	unsigned long		timestamp;	/* For lease renewal */
 #endif
-	struct page		*page_array[NFS_PAGEVEC_SIZE + 1];
+	struct page		*page_array[NFS_PAGEVEC_SIZE];
 };
 
 struct nfs_access_entry;
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index ec7c2e8..2dcad29 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -10,7 +10,6 @@
 #ifndef LINUX_NFSD_NFSD_H
 #define LINUX_NFSD_NFSD_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/unistd.h>
 #include <linux/dirent.h>
diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h
index 0798b77..f9edcd2 100644
--- a/include/linux/nfsd/nfsfh.h
+++ b/include/linux/nfsd/nfsfh.h
@@ -16,7 +16,6 @@
 
 #include <asm/types.h>
 #ifdef __KERNEL__
-# include <linux/config.h>
 # include <linux/types.h>
 # include <linux/string.h>
 # include <linux/fs.h>
diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h
index 781efbf..dae0fae 100644
--- a/include/linux/nfsd/syscall.h
+++ b/include/linux/nfsd/syscall.h
@@ -11,7 +11,6 @@
 
 #include <asm/types.h>
 #ifdef __KERNEL__
-# include <linux/config.h>
 # include <linux/types.h>
 # include <linux/in.h>
 #endif 
diff --git a/include/linux/node.h b/include/linux/node.h
index 254dc3d..81dcec8 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -26,8 +26,25 @@
 	struct sys_device	sysdev;
 };
 
+extern struct node node_devices[];
+
 extern int register_node(struct node *, int, struct node *);
 extern void unregister_node(struct node *node);
+extern int register_one_node(int nid);
+extern void unregister_one_node(int nid);
+#ifdef CONFIG_NUMA
+extern int register_cpu_under_node(unsigned int cpu, unsigned int nid);
+extern int unregister_cpu_under_node(unsigned int cpu, unsigned int nid);
+#else
+static inline int register_cpu_under_node(unsigned int cpu, unsigned int nid)
+{
+	return 0;
+}
+static inline int unregister_cpu_under_node(unsigned int cpu, unsigned int nid)
+{
+	return 0;
+}
+#endif
 
 #define to_node(sys_device) container_of(sys_device, struct node, sysdev)
 
diff --git a/include/linux/nsc_gpio.h b/include/linux/nsc_gpio.h
new file mode 100644
index 0000000..135742c
--- /dev/null
+++ b/include/linux/nsc_gpio.h
@@ -0,0 +1,42 @@
+/**
+   nsc_gpio.c
+
+   National Semiconductor GPIO common access methods.
+
+   struct nsc_gpio_ops abstracts the low-level access
+   operations for the GPIO units on 2 NSC chip families; the GEODE
+   integrated CPU, and the PC-8736[03456] integrated PC-peripheral
+   chips.
+
+   The GPIO units on these chips have the same pin architecture, but
+   the access methods differ.  Thus, scx200_gpio and pc8736x_gpio
+   implement their own versions of these routines; and use the common
+   file-operations routines implemented in nsc_gpio module.
+
+   Copyright (c) 2005 Jim Cromie <jim.cromie@gmail.com>
+
+   NB: this work was tested on the Geode SC-1100 and PC-87366 chips.
+   NSC sold the GEODE line to AMD, and the PC-8736x line to Winbond.
+*/
+
+struct nsc_gpio_ops {
+	struct module*	owner;
+	u32	(*gpio_config)	(unsigned iminor, u32 mask, u32 bits);
+	void	(*gpio_dump)	(struct nsc_gpio_ops *amp, unsigned iminor);
+	int	(*gpio_get)	(unsigned iminor);
+	void	(*gpio_set)	(unsigned iminor, int state);
+	void	(*gpio_set_high)(unsigned iminor);
+	void	(*gpio_set_low)	(unsigned iminor);
+	void	(*gpio_change)	(unsigned iminor);
+	int	(*gpio_current)	(unsigned iminor);
+	struct device*	dev;	/* for dev_dbg() support, set in init  */
+};
+
+extern ssize_t nsc_gpio_write(struct file *file, const char __user *data,
+			      size_t len, loff_t *ppos);
+
+extern ssize_t nsc_gpio_read(struct file *file, char __user *buf,
+			     size_t len, loff_t *ppos);
+
+extern void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index);
+
diff --git a/include/linux/numa.h b/include/linux/numa.h
index e481feb..a31a730 100644
--- a/include/linux/numa.h
+++ b/include/linux/numa.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_NUMA_H
 #define _LINUX_NUMA_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_NODES_SHIFT
 #define NODES_SHIFT     CONFIG_NODES_SHIFT
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index d276a4e..0c076d5 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -7,6 +7,8 @@
 
 #include <linux/percpu.h>
 #include <linux/cache.h>
+#include <linux/types.h>
+
 #include <asm/pgtable.h>
 
 /*
@@ -88,7 +90,17 @@
 #define PG_nosave_free		18	/* Free, should not be written */
 #define PG_buddy		19	/* Page is free, on buddy lists */
 
-#define PG_uncached		20	/* Page has been mapped as uncached */
+
+#if (BITS_PER_LONG > 32)
+/*
+ * 64-bit-only flags build down from bit 31
+ *
+ * 32 bit  -------------------------------| FIELDS |       FLAGS         |
+ * 64 bit  |           FIELDS             | ??????         FLAGS         |
+ *         63                            32                              0
+ */
+#define PG_uncached		31	/* Page has been mapped as uncached */
+#endif
 
 /*
  * Global page accounting.  One instance per CPU.  Only unsigned longs are
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 7a1af57..1245df7 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -99,6 +99,13 @@
 extern int read_cache_pages(struct address_space *mapping,
 		struct list_head *pages, filler_t *filler, void *data);
 
+static inline struct page *read_mapping_page(struct address_space *mapping,
+					     unsigned long index, void *data)
+{
+	filler_t *filler = (filler_t *)mapping->a_ops->readpage;
+	return read_cache_page(mapping, index, filler, data);
+}
+
 int add_to_page_cache(struct page *page, struct address_space *mapping,
 				unsigned long index, gfp_t gfp_mask);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
diff --git a/include/linux/parport.h b/include/linux/parport.h
index 008d736..5bf321e 100644
--- a/include/linux/parport.h
+++ b/include/linux/parport.h
@@ -96,7 +96,6 @@
 /* The rest is for the kernel only */
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/jiffies.h>
 #include <linux/proc_fs.h>
 #include <linux/spinlock.h>
@@ -128,6 +127,10 @@
        unsigned char statusdir;/* ciab.ddrb & 7 */
 };
 
+struct ax88796_parport_state {
+	unsigned char cpr;
+};
+
 struct ip32_parport_state {
 	unsigned int dcr;
 	unsigned int ecr;
@@ -139,6 +142,7 @@
 		/* ARC has no state. */
 		struct ax_parport_state ax;
 		struct amiga_parport_state amiga;
+		struct ax88796_parport_state ax88796;
 		/* Atari has not state. */
 		struct ip32_parport_state ip32;
 		void *misc; 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 3a6a4e3..62a8c22 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -17,8 +17,6 @@
 #ifndef LINUX_PCI_H
 #define LINUX_PCI_H
 
-#include <linux/mod_devicetable.h>
-
 /* Include the pci register defines */
 #include <linux/pci_regs.h>
 
@@ -46,8 +44,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/mod_devicetable.h>
+
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
@@ -163,6 +162,9 @@
 	unsigned int	is_busmaster:1; /* device is busmaster */
 	unsigned int	no_msi:1;	/* device may not use msi */
 	unsigned int	block_ucfg_access:1;	/* userspace config space access is blocked */
+	unsigned int	broken_parity_status:1;	/* Device generates false positive parity */
+	unsigned int 	msi_enabled:1;
+	unsigned int	msix_enabled:1;
 
 	u32		saved_config_space[16]; /* config space saved at suspend time */
 	struct hlist_head saved_cap_space;
@@ -442,6 +444,7 @@
 struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn);
 int pci_find_capability (struct pci_dev *dev, int cap);
 int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap);
+int pci_find_ext_capability (struct pci_dev *dev, int cap);
 struct pci_bus * pci_find_next_bus(const struct pci_bus *from);
 
 struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
@@ -496,6 +499,7 @@
 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
 int pci_assign_resource(struct pci_dev *dev, int i);
+int pci_assign_resource_fixed(struct pci_dev *dev, int i);
 void pci_restore_bars(struct pci_dev *dev);
 
 /* ROM control related routines */
@@ -662,6 +666,7 @@
 static inline void pci_unregister_driver(struct pci_driver *drv) { }
 static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline int pci_find_next_capability (struct pci_dev *dev, u8 post, int cap) { return 0; }
+static inline int pci_find_ext_capability (struct pci_dev *dev, int cap) {return 0; }
 static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; }
 
 /* Power management related routines */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 590dc6d..9ae6b1a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -352,8 +352,11 @@
 #define PCI_DEVICE_ID_ATI_RS480         0x5950
 /* ATI IXP Chipset */
 #define PCI_DEVICE_ID_ATI_IXP200_IDE	0x4349
+#define PCI_DEVICE_ID_ATI_IXP200_SMBUS	0x4353
+#define PCI_DEVICE_ID_ATI_IXP300_SMBUS	0x4363
 #define PCI_DEVICE_ID_ATI_IXP300_IDE	0x4369
 #define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
+#define PCI_DEVICE_ID_ATI_IXP400_SMBUS	0x4372
 #define PCI_DEVICE_ID_ATI_IXP400_IDE	0x4376
 #define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
 #define PCI_DEVICE_ID_ATI_IXP400_SATA2	0x437a
@@ -848,7 +851,12 @@
 
 
 #define PCI_VENDOR_ID_QLOGIC		0x1077
+#define PCI_DEVICE_ID_QLOGIC_ISP10160	0x1016
 #define PCI_DEVICE_ID_QLOGIC_ISP1020	0x1020
+#define PCI_DEVICE_ID_QLOGIC_ISP1080	0x1080
+#define PCI_DEVICE_ID_QLOGIC_ISP12160	0x1216
+#define PCI_DEVICE_ID_QLOGIC_ISP1240	0x1240
+#define PCI_DEVICE_ID_QLOGIC_ISP1280	0x1280
 #define PCI_DEVICE_ID_QLOGIC_ISP2100	0x2100
 #define PCI_DEVICE_ID_QLOGIC_ISP2200	0x2200
 #define PCI_DEVICE_ID_QLOGIC_ISP2300	0x2300
@@ -935,6 +943,7 @@
 #define PCI_DEVICE_ID_PLX_DJINN_ITOO	0x1151
 #define PCI_DEVICE_ID_PLX_R753		0x1152
 #define PCI_DEVICE_ID_PLX_OLITEC	0x1187
+#define PCI_DEVICE_ID_PLX_PCI200SYN	0x3196
 #define PCI_DEVICE_ID_PLX_9050		0x9050
 #define PCI_DEVICE_ID_PLX_9080		0x9080
 #define PCI_DEVICE_ID_PLX_GTEK_SERIAL2	0xa001
@@ -1017,6 +1026,7 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_8		0x0056
 #define PCI_DEVICE_ID_NVIDIA_NVENET_9		0x0057
 #define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO	0x0059
+#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE		0x005d
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS	0x0064
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
 #define PCI_DEVICE_ID_NVIDIA_NVENET_2		0x0066
@@ -1126,9 +1136,11 @@
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL	0x0258
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL	0x0259
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL	0x025B
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS	0x0264
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE	0x0265
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA	0x0266
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2	0x0267
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS	0x0368
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE	0x036E
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA	0x037E
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2	0x037F
@@ -1182,6 +1194,19 @@
 #define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
 #define PCI_DEVICE_ID_NVIDIA_NVENET_14              0x0372
 #define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
+#define PCI_DEVICE_ID_NVIDIA_NVENET_16              0x03E5
+#define PCI_DEVICE_ID_NVIDIA_NVENET_17              0x03E6
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE       0x03EC
+#define PCI_DEVICE_ID_NVIDIA_NVENET_18              0x03EE
+#define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE	    0x0448
+#define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
+#define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
+#define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
+#define PCI_DEVICE_ID_NVIDIA_NVENET_23              0x0453
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_TT128		0x9128
@@ -1235,6 +1260,7 @@
 #define PCI_DEVICE_ID_VIA_PX8X0_0	0x0259
 #define PCI_DEVICE_ID_VIA_3269_0	0x0269
 #define PCI_DEVICE_ID_VIA_K8T800PRO_0	0x0282
+#define PCI_DEVICE_ID_VIA_3296_0	0x0296
 #define PCI_DEVICE_ID_VIA_8363_0	0x0305
 #define PCI_DEVICE_ID_VIA_P4M800CE	0x0314
 #define PCI_DEVICE_ID_VIA_8371_0	0x0391
@@ -1242,6 +1268,7 @@
 #define PCI_DEVICE_ID_VIA_82C561	0x0561
 #define PCI_DEVICE_ID_VIA_82C586_1	0x0571
 #define PCI_DEVICE_ID_VIA_82C576	0x0576
+#define PCI_DEVICE_ID_VIA_SATA_EIDE	0x0581
 #define PCI_DEVICE_ID_VIA_82C586_0	0x0586
 #define PCI_DEVICE_ID_VIA_82C596	0x0596
 #define PCI_DEVICE_ID_VIA_82C597_0	0x0597
@@ -1282,10 +1309,11 @@
 #define PCI_DEVICE_ID_VIA_8783_0	0x3208
 #define PCI_DEVICE_ID_VIA_8237		0x3227
 #define PCI_DEVICE_ID_VIA_8251		0x3287
-#define PCI_DEVICE_ID_VIA_3296_0	0x0296
+#define PCI_DEVICE_ID_VIA_8237A		0x3337
 #define PCI_DEVICE_ID_VIA_8231		0x8231
 #define PCI_DEVICE_ID_VIA_8231_4	0x8235
 #define PCI_DEVICE_ID_VIA_8365_1	0x8305
+#define PCI_DEVICE_ID_VIA_CX700		0x8324
 #define PCI_DEVICE_ID_VIA_8371_1	0x8391
 #define PCI_DEVICE_ID_VIA_82C598_1	0x8598
 #define PCI_DEVICE_ID_VIA_838X_1	0xB188
@@ -1827,6 +1855,7 @@
 
 #define PCI_VENDOR_ID_SAMSUNG		0x144d
 
+#define PCI_VENDOR_ID_MYRICOM		0x14c1
 
 #define PCI_VENDOR_ID_TITAN		0x14D2
 #define PCI_DEVICE_ID_TITAN_010L	0x8001
@@ -1887,6 +1916,7 @@
 #define PCI_DEVICE_ID_TIGON3_5751F	0x167e
 #define PCI_DEVICE_ID_TIGON3_5787M	0x1693
 #define PCI_DEVICE_ID_TIGON3_5782	0x1696
+#define PCI_DEVICE_ID_TIGON3_5786	0x169a
 #define PCI_DEVICE_ID_TIGON3_5787	0x169b
 #define PCI_DEVICE_ID_TIGON3_5788	0x169c
 #define PCI_DEVICE_ID_TIGON3_5789	0x169d
@@ -1935,6 +1965,7 @@
 
 #define PCI_VENDOR_ID_MELLANOX		0x15b3
 #define PCI_DEVICE_ID_MELLANOX_TAVOR	0x5a44
+#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE	0x5a46
 #define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278
 #define PCI_DEVICE_ID_MELLANOX_ARBEL	0x6282
 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
@@ -1958,6 +1989,9 @@
 #define PCI_VENDOR_ID_NETCELL		0x169c
 #define PCI_DEVICE_ID_REVOLUTION	0x0044
 
+#define PCI_VENDOR_ID_VITESSE		0x1725
+#define PCI_DEVICE_ID_VITESSE_VSC7174	0x7174
+
 #define PCI_VENDOR_ID_LINKSYS		0x1737
 #define PCI_DEVICE_ID_LINKSYS_EG1064	0x1064
 
@@ -2043,6 +2077,7 @@
 #define PCI_DEVICE_ID_INTEL_80960_RP	0x1960
 #define PCI_DEVICE_ID_INTEL_82840_HB	0x1a21
 #define PCI_DEVICE_ID_INTEL_82845_HB	0x1a30
+#define PCI_DEVICE_ID_INTEL_IOAT	0x1a38
 #define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1	0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_3	0x2413
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index d27a78b..6bce4a2 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -197,6 +197,7 @@
 #define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
 #define  PCI_CAP_ID_PCIX	0x07	/* PCI-X */
 #define  PCI_CAP_ID_HT_IRQCONF	0x08	/* HyperTransport IRQ Configuration */
+#define  PCI_CAP_ID_VNDR	0x09	/* Vendor specific capability */
 #define  PCI_CAP_ID_SHPC 	0x0C	/* PCI Standard Hot-Plug Controller */
 #define  PCI_CAP_ID_EXP 	0x10	/* PCI Express */
 #define  PCI_CAP_ID_MSIX	0x11	/* MSI-X */
diff --git a/include/linux/percpu_counter.h b/include/linux/percpu_counter.h
index 6825255..f5aa593 100644
--- a/include/linux/percpu_counter.h
+++ b/include/linux/percpu_counter.h
@@ -6,18 +6,18 @@
  * WARNING: these things are HUGE.  4 kbytes per counter on 32-way P4.
  */
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/smp.h>
 #include <linux/threads.h>
 #include <linux/percpu.h>
+#include <linux/types.h>
 
 #ifdef CONFIG_SMP
 
 struct percpu_counter {
 	spinlock_t lock;
-	long count;
-	long *counters;
+	s64 count;
+	s32 *counters;
 };
 
 #if NR_CPUS >= 16
@@ -26,11 +26,11 @@
 #define FBC_BATCH	(NR_CPUS*4)
 #endif
 
-static inline void percpu_counter_init(struct percpu_counter *fbc)
+static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
 {
 	spin_lock_init(&fbc->lock);
-	fbc->count = 0;
-	fbc->counters = alloc_percpu(long);
+	fbc->count = amount;
+	fbc->counters = alloc_percpu(s32);
 }
 
 static inline void percpu_counter_destroy(struct percpu_counter *fbc)
@@ -38,10 +38,10 @@
 	free_percpu(fbc->counters);
 }
 
-void percpu_counter_mod(struct percpu_counter *fbc, long amount);
-long percpu_counter_sum(struct percpu_counter *fbc);
+void percpu_counter_mod(struct percpu_counter *fbc, s32 amount);
+s64 percpu_counter_sum(struct percpu_counter *fbc);
 
-static inline long percpu_counter_read(struct percpu_counter *fbc)
+static inline s64 percpu_counter_read(struct percpu_counter *fbc)
 {
 	return fbc->count;
 }
@@ -49,13 +49,14 @@
 /*
  * It is possible for the percpu_counter_read() to return a small negative
  * number for some counter which should never be negative.
+ *
  */
-static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
+static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
 {
-	long ret = fbc->count;
+	s64 ret = fbc->count;
 
 	barrier();		/* Prevent reloads of fbc->count */
-	if (ret > 0)
+	if (ret >= 0)
 		return ret;
 	return 1;
 }
@@ -63,12 +64,12 @@
 #else
 
 struct percpu_counter {
-	long count;
+	s64 count;
 };
 
-static inline void percpu_counter_init(struct percpu_counter *fbc)
+static inline void percpu_counter_init(struct percpu_counter *fbc, s64 amount)
 {
-	fbc->count = 0;
+	fbc->count = amount;
 }
 
 static inline void percpu_counter_destroy(struct percpu_counter *fbc)
@@ -76,24 +77,24 @@
 }
 
 static inline void
-percpu_counter_mod(struct percpu_counter *fbc, long amount)
+percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
 {
 	preempt_disable();
 	fbc->count += amount;
 	preempt_enable();
 }
 
-static inline long percpu_counter_read(struct percpu_counter *fbc)
+static inline s64 percpu_counter_read(struct percpu_counter *fbc)
 {
 	return fbc->count;
 }
 
-static inline long percpu_counter_read_positive(struct percpu_counter *fbc)
+static inline s64 percpu_counter_read_positive(struct percpu_counter *fbc)
 {
 	return fbc->count;
 }
 
-static inline long percpu_counter_sum(struct percpu_counter *fbc)
+static inline s64 percpu_counter_sum(struct percpu_counter *fbc)
 {
 	return percpu_counter_read_positive(fbc);
 }
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index bac0fb3..d5dd471 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -159,7 +159,7 @@
 struct sadb_x_kmprivate {
 	uint16_t	sadb_x_kmprivate_len;
 	uint16_t	sadb_x_kmprivate_exttype;
-	u_int32_t	sadb_x_kmprivate_reserved;
+	uint32_t	sadb_x_kmprivate_reserved;
 } __attribute__((packed));
 /* sizeof(struct sadb_x_kmprivate) == 8 */
 
diff --git a/include/linux/plist.h b/include/linux/plist.h
new file mode 100644
index 0000000..b95818a
--- /dev/null
+++ b/include/linux/plist.h
@@ -0,0 +1,248 @@
+/*
+ * Descending-priority-sorted double-linked list
+ *
+ * (C) 2002-2003 Intel Corp
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
+ *
+ * 2001-2005 (c) MontaVista Software, Inc.
+ * Daniel Walker <dwalker@mvista.com>
+ *
+ * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Simplifications of the original code by
+ * Oleg Nesterov <oleg@tv-sign.ru>
+ *
+ * Licensed under the FSF's GNU Public License v2 or later.
+ *
+ * Based on simple lists (include/linux/list.h).
+ *
+ * This is a priority-sorted list of nodes; each node has a
+ * priority from INT_MIN (highest) to INT_MAX (lowest).
+ *
+ * Addition is O(K), removal is O(1), change of priority of a node is
+ * O(K) and K is the number of RT priority levels used in the system.
+ * (1 <= K <= 99)
+ *
+ * This list is really a list of lists:
+ *
+ *  - The tier 1 list is the prio_list, different priority nodes.
+ *
+ *  - The tier 2 list is the node_list, serialized nodes.
+ *
+ * Simple ASCII art explanation:
+ *
+ * |HEAD          |
+ * |              |
+ * |prio_list.prev|<------------------------------------|
+ * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-|
+ * |10            |   |10|   |21|   |21|   |21|   |40|   (prio)
+ * |              |   |  |   |  |   |  |   |  |   |  |
+ * |              |   |  |   |  |   |  |   |  |   |  |
+ * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-|
+ * |node_list.prev|<------------------------------------|
+ *
+ * The nodes on the prio_list list are sorted by priority to simplify
+ * the insertion of new nodes. There are no nodes with duplicate
+ * priorites on the list.
+ *
+ * The nodes on the node_list is ordered by priority and can contain
+ * entries which have the same priority. Those entries are ordered
+ * FIFO
+ *
+ * Addition means: look for the prio_list node in the prio_list
+ * for the priority of the node and insert it before the node_list
+ * entry of the next prio_list node. If it is the first node of
+ * that priority, add it to the prio_list in the right position and
+ * insert it into the serialized node_list list
+ *
+ * Removal means remove it from the node_list and remove it from
+ * the prio_list if the node_list list_head is non empty. In case
+ * of removal from the prio_list it must be checked whether other
+ * entries of the same priority are on the list or not. If there
+ * is another entry of the same priority then this entry has to
+ * replace the removed entry on the prio_list. If the entry which
+ * is removed is the only entry of this priority then a simple
+ * remove from both list is sufficient.
+ *
+ * INT_MIN is the highest priority, 0 is the medium highest, INT_MAX
+ * is lowest priority.
+ *
+ * No locking is done, up to the caller.
+ *
+ */
+#ifndef _LINUX_PLIST_H_
+#define _LINUX_PLIST_H_
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock_types.h>
+
+struct plist_head {
+	struct list_head prio_list;
+	struct list_head node_list;
+#ifdef CONFIG_DEBUG_PI_LIST
+	spinlock_t *lock;
+#endif
+};
+
+struct plist_node {
+	int			prio;
+	struct plist_head	plist;
+};
+
+#ifdef CONFIG_DEBUG_PI_LIST
+# define PLIST_HEAD_LOCK_INIT(_lock)	.lock = _lock
+#else
+# define PLIST_HEAD_LOCK_INIT(_lock)
+#endif
+
+/**
+ * #PLIST_HEAD_INIT - static struct plist_head initializer
+ *
+ * @head:	struct plist_head variable name
+ */
+#define PLIST_HEAD_INIT(head, _lock)			\
+{							\
+	.prio_list = LIST_HEAD_INIT((head).prio_list),	\
+	.node_list = LIST_HEAD_INIT((head).node_list),	\
+	PLIST_HEAD_LOCK_INIT(&(_lock))			\
+}
+
+/**
+ * #PLIST_NODE_INIT - static struct plist_node initializer
+ *
+ * @node:	struct plist_node variable name
+ * @__prio:	initial node priority
+ */
+#define PLIST_NODE_INIT(node, __prio)			\
+{							\
+	.prio  = (__prio),				\
+	.plist = PLIST_HEAD_INIT((node).plist, NULL),	\
+}
+
+/**
+ * plist_head_init - dynamic struct plist_head initializer
+ *
+ * @head:	&struct plist_head pointer
+ */
+static inline void
+plist_head_init(struct plist_head *head, spinlock_t *lock)
+{
+	INIT_LIST_HEAD(&head->prio_list);
+	INIT_LIST_HEAD(&head->node_list);
+#ifdef CONFIG_DEBUG_PI_LIST
+	head->lock = lock;
+#endif
+}
+
+/**
+ * plist_node_init - Dynamic struct plist_node initializer
+ *
+ * @node:	&struct plist_node pointer
+ * @prio:	initial node priority
+ */
+static inline void plist_node_init(struct plist_node *node, int prio)
+{
+	node->prio = prio;
+	plist_head_init(&node->plist, NULL);
+}
+
+extern void plist_add(struct plist_node *node, struct plist_head *head);
+extern void plist_del(struct plist_node *node, struct plist_head *head);
+
+/**
+ * plist_for_each - iterate over the plist
+ *
+ * @pos1:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define plist_for_each(pos, head)	\
+	 list_for_each_entry(pos, &(head)->node_list, plist.node_list)
+
+/**
+ * plist_for_each_entry_safe - iterate over a plist of given type safe
+ * against removal of list entry
+ *
+ * @pos1:	the type * to use as a loop counter.
+ * @n1:	another type * to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define plist_for_each_safe(pos, n, head)	\
+	 list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list)
+
+/**
+ * plist_for_each_entry	- iterate over list of given type
+ *
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define plist_for_each_entry(pos, head, mem)	\
+	 list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list)
+
+/**
+ * plist_for_each_entry_safe - iterate over list of given type safe against
+ * removal of list entry
+ *
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @m:		the name of the list_struct within the struct.
+ */
+#define plist_for_each_entry_safe(pos, n, head, m)	\
+	list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list)
+
+/**
+ * plist_head_empty - return !0 if a plist_head is empty
+ *
+ * @head:	&struct plist_head pointer
+ */
+static inline int plist_head_empty(const struct plist_head *head)
+{
+	return list_empty(&head->node_list);
+}
+
+/**
+ * plist_node_empty - return !0 if plist_node is not on a list
+ *
+ * @node:	&struct plist_node pointer
+ */
+static inline int plist_node_empty(const struct plist_node *node)
+{
+	return plist_head_empty(&node->plist);
+}
+
+/* All functions below assume the plist_head is not empty. */
+
+/**
+ * plist_first_entry - get the struct for the first entry
+ *
+ * @ptr:	the &struct plist_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#ifdef CONFIG_DEBUG_PI_LIST
+# define plist_first_entry(head, type, member)	\
+({ \
+	WARN_ON(plist_head_empty(head)); \
+	container_of(plist_first(head), type, member); \
+})
+#else
+# define plist_first_entry(head, type, member)	\
+	container_of(plist_first(head), type, member)
+#endif
+
+/**
+ * plist_first - return the first node (and thus, highest priority)
+ *
+ * @head:	the &struct plist_head pointer
+ *
+ * Assumes the plist is _not_ empty.
+ */
+static inline struct plist_node* plist_first(const struct plist_head *head)
+{
+	return list_entry(head->node_list.next,
+			  struct plist_node, plist.node_list);
+}
+
+#endif
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 66be589..658c1b9 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -23,7 +23,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <asm/atomic.h>
 
diff --git a/include/linux/pm_legacy.h b/include/linux/pm_legacy.h
index 008932d..78027c5 100644
--- a/include/linux/pm_legacy.h
+++ b/include/linux/pm_legacy.h
@@ -1,7 +1,6 @@
 #ifndef __LINUX_PM_LEGACY_H__
 #define __LINUX_PM_LEGACY_H__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_PM_LEGACY
 
diff --git a/include/linux/pmu.h b/include/linux/pmu.h
index 217d3da..2ed807d 100644
--- a/include/linux/pmu.h
+++ b/include/linux/pmu.h
@@ -6,7 +6,6 @@
  * Copyright (C) 1998 Paul Mackerras.
  */
 
-#include <linux/config.h>
 
 #define PMU_DRIVER_VERSION	2
 
@@ -231,4 +230,8 @@
 extern struct pmu_battery_info pmu_batteries[PMU_MAX_BATTERIES];
 extern unsigned int pmu_power_flags;
 
+/* Backlight */
+extern int disable_kernel_backlight;
+extern void pmu_backlight_init(struct device_node*);
+
 #endif	/* __KERNEL__ */
diff --git a/include/linux/poison.h b/include/linux/poison.h
new file mode 100644
index 0000000..a5347c0
--- /dev/null
+++ b/include/linux/poison.h
@@ -0,0 +1,58 @@
+#ifndef _LINUX_POISON_H
+#define _LINUX_POISON_H
+
+/********** include/linux/list.h **********/
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1  ((void *) 0x00100100)
+#define LIST_POISON2  ((void *) 0x00200200)
+
+/********** mm/slab.c **********/
+/*
+ * Magic nums for obj red zoning.
+ * Placed in the first word before and the first word after an obj.
+ */
+#define	RED_INACTIVE	0x5A2CF071UL	/* when obj is inactive */
+#define	RED_ACTIVE	0x170FC2A5UL	/* when obj is active */
+
+/* ...and for poisoning */
+#define	POISON_INUSE	0x5a	/* for use-uninitialised poisoning */
+#define POISON_FREE	0x6b	/* for use-after-free poisoning */
+#define	POISON_END	0xa5	/* end-byte of poisoning */
+
+/********** arch/$ARCH/mm/init.c **********/
+#define POISON_FREE_INITMEM	0xcc
+
+/********** arch/x86_64/mm/init.c **********/
+#define	POISON_FREE_INITDATA	0xba
+
+/********** arch/ia64/hp/common/sba_iommu.c **********/
+/*
+ * arch/ia64/hp/common/sba_iommu.c uses a 16-byte poison string with a
+ * value of "SBAIOMMU POISON\0" for spill-over poisoning.
+ */
+
+/********** fs/jbd/journal.c **********/
+#define JBD_POISON_FREE	0x5b
+
+/********** drivers/base/dmapool.c **********/
+#define	POOL_POISON_FREED	0xa7	/* !inuse */
+#define	POOL_POISON_ALLOCATED	0xa9	/* !initted */
+
+/********** drivers/atm/ **********/
+#define ATM_POISON_FREE		0x12
+
+/********** kernel/mutexes **********/
+#define MUTEX_DEBUG_INIT	0x11
+#define MUTEX_DEBUG_FREE	0x22
+
+/********** security/ **********/
+#define KEY_DESTROY		0xbd
+
+/********** sound/oss/ **********/
+#define OSS_POISON_FREE		0xAB
+
+#endif
diff --git a/include/linux/ppp_defs.h b/include/linux/ppp_defs.h
index 402056c..c6b13ff 100644
--- a/include/linux/ppp_defs.h
+++ b/include/linux/ppp_defs.h
@@ -42,8 +42,6 @@
 #ifndef _PPP_DEFS_H_
 #define _PPP_DEFS_H_
 
-#include <linux/crc-ccitt.h>
-
 /*
  * The basic PPP frame.
  */
@@ -97,7 +95,11 @@
 
 #define PPP_INITFCS	0xffff	/* Initial FCS value */
 #define PPP_GOODFCS	0xf0b8	/* Good final FCS value */
+
+#ifdef __KERNEL__
+#include <linux/crc-ccitt.h>
 #define PPP_FCS(fcs, c) crc_ccitt_byte(fcs, c)
+#endif
 
 /*
  * Extended asyncmap - allows any character to be escaped.
@@ -179,12 +181,4 @@
     time_t recv_idle;		/* time since last NP packet received */
 };
 
-#ifndef __P
-#ifdef __STDC__
-#define __P(x)	x
-#else
-#define __P(x)	()
-#endif
-#endif
-
 #endif /* _PPP_DEFS_H_ */
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index bf022c43..52a9be4 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -52,4 +52,11 @@
 #define PR_SET_NAME    15		/* Set process name */
 #define PR_GET_NAME    16		/* Get process name */
 
+/* Get/set process endian */
+#define PR_GET_ENDIAN	19
+#define PR_SET_ENDIAN	20
+# define PR_ENDIAN_BIG		0
+# define PR_ENDIAN_LITTLE	1	/* True little endian mode */
+# define PR_ENDIAN_PPC_LITTLE	2	/* "PowerPC" pseudo little endian */
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index 5769d14..d0926d6 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -6,7 +6,6 @@
  * preempt_count (used for kernel preemption, interrupt count, etc.)
  */
 
-#include <linux/config.h>
 #include <linux/thread_info.h>
 #include <linux/linkage.h>
 
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 4b47a02..17e7578 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_PROC_FS_H
 #define _LINUX_PROC_FS_H
 
-#include <linux/config.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/spinlock.h>
@@ -100,9 +99,8 @@
 
 struct mm_struct;
 
+void proc_flush_task(struct task_struct *task);
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
-struct dentry *proc_pid_unhash(struct task_struct *p);
-void proc_pid_flush(struct dentry *proc_dentry);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 unsigned long task_vsize(struct mm_struct *);
 int task_statm(struct mm_struct *, int *, int *, int *, int *);
@@ -212,8 +210,7 @@
 #define proc_net_create(name, mode, info)	({ (void)(mode), NULL; })
 static inline void proc_net_remove(const char *name) {}
 
-static inline struct dentry *proc_pid_unhash(struct task_struct *p) { return NULL; }
-static inline void proc_pid_flush(struct dentry *proc_dentry) { }
+static inline void proc_flush_task(struct task_struct *task) { }
 
 static inline struct proc_dir_entry *create_proc_entry(const char *name,
 	mode_t mode, struct proc_dir_entry *parent) { return NULL; }
@@ -249,8 +246,8 @@
 #endif
 
 struct proc_inode {
-	struct task_struct *task;
-	int type;
+	struct pid *pid;
+	int fd;
 	union {
 		int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
 		int (*proc_read)(struct task_struct *task, char *page);
@@ -269,4 +266,10 @@
 	return PROC_I(inode)->pde;
 }
 
+struct proc_maps_private {
+	struct pid *pid;
+	struct task_struct *task;
+	struct vm_area_struct *tail_vma;
+};
+
 #endif /* _LINUX_PROC_FS_H */
diff --git a/include/linux/profile.h b/include/linux/profile.h
index 1f2fea6..e633004 100644
--- a/include/linux/profile.h
+++ b/include/linux/profile.h
@@ -4,7 +4,6 @@
 #ifdef __KERNEL__
 
 #include <linux/kernel.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/cpumask.h>
 #include <asm/errno.h>
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 0d36750..8b2749a 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -51,6 +51,10 @@
 #ifdef __KERNEL__
 /*
  * Ptrace flags
+ *
+ * The owner ship rules for task->ptrace which holds the ptrace
+ * flags is simple.  When a task is running it owns it's task->ptrace
+ * flags.  When the a task is stopped the ptracer owns task->ptrace.
  */
 
 #define PT_PTRACED	0x00000001
@@ -84,7 +88,6 @@
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern int ptrace_attach(struct task_struct *tsk);
 extern int ptrace_detach(struct task_struct *, unsigned int);
-extern void __ptrace_detach(struct task_struct *, unsigned int);
 extern void ptrace_disable(struct task_struct *);
 extern int ptrace_check_attach(struct task_struct *task, int kill);
 extern int ptrace_request(struct task_struct *child, long request, long addr, long data);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 2dab71e..b8fbf26 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -37,8 +37,6 @@
 
 #include <linux/errno.h>
 #include <linux/types.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
 
 #define __DQUOT_VERSION__	"dquot_6.5.1"
 #define __DQUOT_NUM_VERSION__	6*10000+5*100+1
@@ -133,6 +131,8 @@
 };
 
 #ifdef __KERNEL__
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
 
 #include <linux/dqblk_xfs.h>
 #include <linux/dqblk_v1.h>
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 21e5a91..5110201 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -10,7 +10,6 @@
 #ifndef _LINUX_QUOTAOPS_
 #define _LINUX_QUOTAOPS_
 
-#include <linux/config.h>
 #include <linux/smp_lock.h>
 
 #include <linux/fs.h>
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index dd83cca..9158a68 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -23,6 +23,9 @@
 #include <linux/preempt.h>
 #include <linux/types.h>
 
+#define RADIX_TREE_MAX_TAGS 2
+
+/* root tags are stored in gfp_mask, shifted by __GFP_BITS_SHIFT */
 struct radix_tree_root {
 	unsigned int		height;
 	gfp_t			gfp_mask;
@@ -45,8 +48,6 @@
 	(root)->rnode = NULL;						\
 } while (0)
 
-#define RADIX_TREE_MAX_TAGS 2
-
 int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
 void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
 void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
index 8994378..63df898 100644
--- a/include/linux/raid/bitmap.h
+++ b/include/linux/raid/bitmap.h
@@ -140,6 +140,7 @@
 enum bitmap_state {
 	BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
 	BITMAP_STALE  = 0x002,  /* the bitmap file is out of date or had -EIO */
+	BITMAP_WRITE_ERROR = 0x004, /* A write error has occurred */
 	BITMAP_HOSTENDIAN = 0x8000,
 };
 
@@ -244,15 +245,9 @@
 	unsigned long daemon_lastrun; /* jiffies of last run */
 	unsigned long daemon_sleep; /* how many seconds between updates? */
 
-	/*
-	 * bitmap_writeback_daemon waits for file-pages that have been written,
-	 * as there is no way to get a call-back when a page write completes.
-	 */
-	mdk_thread_t *writeback_daemon;
-	spinlock_t write_lock;
+	atomic_t pending_writes; /* pending writes to the bitmap file */
 	wait_queue_head_t write_wait;
-	struct list_head complete_pages;
-	mempool_t *write_pool;
+
 };
 
 /* the bitmap API */
diff --git a/include/linux/raid/linear.h b/include/linux/raid/linear.h
index 7eaf290..ba15469 100644
--- a/include/linux/raid/linear.h
+++ b/include/linux/raid/linear.h
@@ -13,8 +13,10 @@
 
 struct linear_private_data
 {
+	struct linear_private_data *prev;	/* earlier version */
 	dev_info_t		**hash_table;
 	sector_t		hash_spacing;
+	sector_t		array_size;
 	int			preshift; /* shift before dividing by hash_spacing */
 	dev_info_t		disks[0];
 };
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index 66b44e5..eb3e547 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -85,8 +85,6 @@
 extern void md_error (mddev_t *mddev, mdk_rdev_t *rdev);
 extern void md_unplug_mddev(mddev_t *mddev);
 
-extern void md_print_devices (void);
-
 extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
 			   sector_t sector, int size, struct page *page);
 extern void md_super_wait(mddev_t *mddev);
@@ -97,7 +95,5 @@
 
 extern void md_update_sb(mddev_t * mddev);
 
-#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
-
 #endif 
 
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index e2df61f..c1e0ac5 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -40,7 +40,8 @@
  * options passed in raidrun:
  */
 
-#define MAX_CHUNK_SIZE (4096*1024)
+/* Currently this must fix in an 'int' */
+#define MAX_CHUNK_SIZE (1<<30)
 
 /*
  * MD's 'extended' device
@@ -57,6 +58,7 @@
 
 	struct page	*sb_page;
 	int		sb_loaded;
+	__u64		sb_events;
 	sector_t	data_offset;	/* start of data in array */
 	sector_t	sb_offset;
 	int		sb_size;	/* bytes in the superblock */
@@ -87,6 +89,10 @@
 					 * array and could again if we did a partial
 					 * resync from the bitmap
 					 */
+	sector_t	recovery_offset;/* If this device has been partially
+					 * recovered, this is where we were
+					 * up to.
+					 */
 
 	atomic_t	nr_pending;	/* number of pending requests.
 					 * only maintained for arrays that
@@ -182,6 +188,8 @@
 #define	MD_RECOVERY_REQUESTED	6
 #define	MD_RECOVERY_CHECK	7
 #define MD_RECOVERY_RESHAPE	8
+#define	MD_RECOVERY_FROZEN	9
+
 	unsigned long			recovery;
 
 	int				in_sync;	/* know to not need resync */
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index f1fbae7..b6ebc69 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -265,9 +265,12 @@
 
 /* feature_map bits */
 #define MD_FEATURE_BITMAP_OFFSET	1
+#define	MD_FEATURE_RECOVERY_OFFSET	2 /* recovery_offset is present and
+					   * must be honoured
+					   */
 #define	MD_FEATURE_RESHAPE_ACTIVE	4
 
-#define	MD_FEATURE_ALL			5
+#define	MD_FEATURE_ALL			(1|2|4)
 
 #endif 
 
diff --git a/include/linux/raid/raid10.h b/include/linux/raid/raid10.h
index b110329..c41e56a 100644
--- a/include/linux/raid/raid10.h
+++ b/include/linux/raid/raid10.h
@@ -24,11 +24,16 @@
 	int 			far_copies;   /* number of copies layed out
 					       * at large strides across drives
 					       */
+	int			far_offset;   /* far_copies are offset by 1 stripe
+					       * instead of many
+					       */
 	int			copies;	      /* near_copies * far_copies.
 					       * must be <= raid_disks
 					       */
 	sector_t		stride;	      /* distance between far copies.
-					       * This is size / far_copies
+					       * This is size / far_copies unless
+					       * far_offset, in which case it is
+					       * 1 stripe.
 					       */
 
 	int chunk_shift; /* shift from chunks to sectors */
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h
index 914af66..20ed4c9 100644
--- a/include/linux/raid/raid5.h
+++ b/include/linux/raid/raid5.h
@@ -212,6 +212,7 @@
 	mddev_t			*mddev;
 	struct disk_info	*spare;
 	int			chunk_size, level, algorithm;
+	int			max_degraded;
 	int			raid_disks, working_disks, failed_disks;
 	int			max_nr_stripes;
 
diff --git a/include/linux/ramfs.h b/include/linux/ramfs.h
index 78ecfa2..00b340b 100644
--- a/include/linux/ramfs.h
+++ b/include/linux/ramfs.h
@@ -2,8 +2,8 @@
 #define _LINUX_RAMFS_H
 
 struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev);
-struct super_block *ramfs_get_sb(struct file_system_type *fs_type,
-	 int flags, const char *dev_name, void *data);
+extern int ramfs_get_sb(struct file_system_type *fs_type,
+	 int flags, const char *dev_name, void *data, struct vfsmount *mnt);
 
 #ifndef CONFIG_MMU
 extern unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index 4b7cc4f..8d5382e 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -99,22 +99,43 @@
 
 struct rb_node
 {
-	struct rb_node *rb_parent;
-	int rb_color;
+	unsigned long  rb_parent_color;
 #define	RB_RED		0
 #define	RB_BLACK	1
 	struct rb_node *rb_right;
 	struct rb_node *rb_left;
-};
+} __attribute__((aligned(sizeof(long))));
+    /* The alignment might seem pointless, but allegedly CRIS needs it */
 
 struct rb_root
 {
 	struct rb_node *rb_node;
 };
 
+
+#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
+#define rb_color(r)   ((r)->rb_parent_color & 1)
+#define rb_is_red(r)   (!rb_color(r))
+#define rb_is_black(r) rb_color(r)
+#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
+#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)
+
+static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
+{
+	rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
+}
+static inline void rb_set_color(struct rb_node *rb, int color)
+{
+	rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
+}
+
 #define RB_ROOT	(struct rb_root) { NULL, }
 #define	rb_entry(ptr, type, member) container_of(ptr, type, member)
 
+#define RB_EMPTY_ROOT(root)	((root)->rb_node == NULL)
+#define RB_EMPTY_NODE(node)	(rb_parent(node) != node)
+#define RB_CLEAR_NODE(node)	(rb_set_parent(node, node))
+
 extern void rb_insert_color(struct rb_node *, struct rb_root *);
 extern void rb_erase(struct rb_node *, struct rb_root *);
 
@@ -131,8 +152,7 @@
 static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
 				struct rb_node ** rb_link)
 {
-	node->rb_parent = parent;
-	node->rb_color = RB_RED;
+	node->rb_parent_color = (unsigned long )parent;
 	node->rb_left = node->rb_right = NULL;
 
 	*rb_link = node;
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 970284f..48dfe00 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -246,7 +246,7 @@
  * softirq handlers will have completed, since in some kernels, these
  * handlers can run in process context, and can block.
  *
- * This primitive provides the guarantees made by the (deprecated)
+ * This primitive provides the guarantees made by the (now removed)
  * synchronize_kernel() API.  In contrast, synchronize_rcu() only
  * guarantees that rcu_read_lock() sections will have completed.
  * In "classic RCU", these two guarantees happen to be one and
@@ -258,13 +258,13 @@
 extern void rcu_check_callbacks(int cpu, int user);
 extern void rcu_restart_cpu(int cpu);
 extern long rcu_batches_completed(void);
+extern long rcu_batches_completed_bh(void);
 
 /* Exported interfaces */
 extern void FASTCALL(call_rcu(struct rcu_head *head, 
 				void (*func)(struct rcu_head *head)));
 extern void FASTCALL(call_rcu_bh(struct rcu_head *head,
 				void (*func)(struct rcu_head *head)));
-extern __deprecated_for_modules void synchronize_kernel(void);
 extern void synchronize_rcu(void);
 void synchronize_idle(void);
 extern void rcu_barrier(void);
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 015297f..1dd1c70 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -59,13 +59,13 @@
  * Architecture independent implemenations of sys_reboot commands.
  */
 
-extern void kernel_restart_prepare(char *cmd);
 extern void kernel_shutdown_prepare(enum system_states state);
 
 extern void kernel_restart(char *cmd);
 extern void kernel_halt(void);
 extern void kernel_power_off(void);
-extern void kernel_kexec(void);
+
+void ctrl_alt_del(void);
 
 /*
  * Emergency restart, callable from an interrupt handler.
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 5676c42..daa2d83 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1973,7 +1973,7 @@
 /* file.c */
 extern struct inode_operations reiserfs_file_inode_operations;
 extern const struct file_operations reiserfs_file_operations;
-extern struct address_space_operations reiserfs_address_space_operations;
+extern const struct address_space_operations reiserfs_address_space_operations;
 
 /* fix_nodes.c */
 
diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
index 5353afb..5e96103 100644
--- a/include/linux/reiserfs_xattr.h
+++ b/include/linux/reiserfs_xattr.h
@@ -2,8 +2,6 @@
   File: linux/reiserfs_xattr.h
 */
 
-#include <linux/config.h>
-#include <linux/init.h>
 #include <linux/xattr.h>
 
 /* Magic value in header */
@@ -15,6 +13,7 @@
 };
 
 #ifdef __KERNEL__
+#include <linux/init.h>
 
 struct reiserfs_xattr_handler {
 	char *prefix;
diff --git a/include/linux/relay.h b/include/linux/relay.h
index 4bcc153..24accb4 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -10,7 +10,6 @@
 #ifndef _LINUX_RELAY_H
 #define _LINUX_RELAY_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
diff --git a/include/linux/resource.h b/include/linux/resource.h
index 21a86cb..ae13db7 100644
--- a/include/linux/resource.h
+++ b/include/linux/resource.h
@@ -3,6 +3,8 @@
 
 #include <linux/time.h>
 
+struct task_struct;
+
 /*
  * Resource control/accounting header file for linux
  */
@@ -67,4 +69,6 @@
  */
 #include <asm/resource.h>
 
+int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
+
 #endif
diff --git a/include/linux/resume-trace.h b/include/linux/resume-trace.h
new file mode 100644
index 0000000..a376bd4
--- /dev/null
+++ b/include/linux/resume-trace.h
@@ -0,0 +1,30 @@
+#ifndef RESUME_TRACE_H
+#define RESUME_TRACE_H
+
+#ifdef CONFIG_PM_TRACE
+
+struct device;
+extern void set_trace_device(struct device *);
+extern void generate_resume_trace(void *tracedata, unsigned int user);
+
+#define TRACE_DEVICE(dev) set_trace_device(dev)
+#define TRACE_RESUME(user) do {				\
+	void *tracedata;				\
+	asm volatile("movl $1f,%0\n"			\
+		".section .tracedata,\"a\"\n"		\
+		"1:\t.word %c1\n"			\
+		"\t.long %c2\n"				\
+		".previous"				\
+		:"=r" (tracedata)			\
+		: "i" (__LINE__), "i" (__FILE__));	\
+	generate_resume_trace(tracedata, user);		\
+} while (0)
+
+#else
+
+#define TRACE_DEVICE(dev) do { } while (0)
+#define TRACE_RESUME(dev) do { } while (0)
+
+#endif
+
+#endif
diff --git a/include/linux/rio.h b/include/linux/rio.h
index c7e907f..d938570 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -17,7 +17,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h
index f54772d..7adb2a1 100644
--- a/include/linux/rio_drv.h
+++ b/include/linux/rio_drv.h
@@ -16,7 +16,6 @@
 #ifdef __KERNEL__
 
 #include <linux/types.h>
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index d6b9bcd..bf97b09 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -4,7 +4,6 @@
  * Declarations for Reverse Mapping functions in mm/rmap.c
  */
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
@@ -92,7 +91,6 @@
  */
 int page_referenced(struct page *, int is_locked);
 int try_to_unmap(struct page *, int ignore_refs);
-void remove_from_swap(struct page *page);
 
 /*
  * Called from mm/filemap_xip.c to unmap empty zero page
diff --git a/include/linux/rtc-v3020.h b/include/linux/rtc-v3020.h
new file mode 100644
index 0000000..bf74e63
--- /dev/null
+++ b/include/linux/rtc-v3020.h
@@ -0,0 +1,35 @@
+/*
+ * v3020.h - Registers definition and platform data structure for the v3020 RTC.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006, 8D Technologies inc.
+ */
+#ifndef __LINUX_V3020_H
+#define __LINUX_V3020_H
+
+/* The v3020 has only one data pin but which one
+ * is used depends on the board. */
+struct v3020_platform_data {
+	int leftshift; /* (1<<(leftshift)) & readl() */
+};
+
+#define V3020_STATUS_0	0x00
+#define V3020_STATUS_1	0x01
+#define V3020_SECONDS	0x02
+#define V3020_MINUTES	0x03
+#define V3020_HOURS		0x04
+#define V3020_MONTH_DAY	0x05
+#define V3020_MONTH		0x06
+#define V3020_YEAR		0x07
+#define V3020_WEEK_DAY	0x08
+#define V3020_WEEK		0x09
+
+#define V3020_IS_COMMAND(val) ((val)>=0x0E)
+
+#define V3020_CMD_RAM2CLOCK	0x0E
+#define V3020_CMD_CLOCK2RAM	0x0F
+
+#endif /* __LINUX_V3020_H */
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index ab61cd1..36e2bf4 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -102,6 +102,7 @@
 #include <linux/interrupt.h>
 
 extern int rtc_month_days(unsigned int month, unsigned int year);
+extern int rtc_year_days(unsigned int day, unsigned int month, unsigned int year);
 extern int rtc_valid_tm(struct rtc_time *tm);
 extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
 extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
@@ -155,6 +156,17 @@
 	struct rtc_task *irq_task;
 	spinlock_t irq_task_lock;
 	int irq_freq;
+	int max_user_freq;
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+	struct work_struct uie_task;
+	struct timer_list uie_timer;
+	/* Those fields are protected by rtc->irq_lock */
+	unsigned int oldsecs;
+	unsigned int irq_active:1;
+	unsigned int stop_uie_polling:1;
+	unsigned int uie_task_active:1;
+	unsigned int uie_timer_active:1;
+#endif
 };
 #define to_rtc_device(d) container_of(d, struct rtc_device, class_dev)
 
diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h
new file mode 100644
index 0000000..fa4a3b8
--- /dev/null
+++ b/include/linux/rtmutex.h
@@ -0,0 +1,117 @@
+/*
+ * RT Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains the public data structure and API definitions.
+ */
+
+#ifndef __LINUX_RT_MUTEX_H
+#define __LINUX_RT_MUTEX_H
+
+#include <linux/linkage.h>
+#include <linux/plist.h>
+#include <linux/spinlock_types.h>
+
+/*
+ * The rt_mutex structure
+ *
+ * @wait_lock:	spinlock to protect the structure
+ * @wait_list:	pilist head to enqueue waiters in priority order
+ * @owner:	the mutex owner
+ */
+struct rt_mutex {
+	spinlock_t		wait_lock;
+	struct plist_head	wait_list;
+	struct task_struct	*owner;
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+	int			save_state;
+	struct list_head	held_list_entry;
+	unsigned long		acquire_ip;
+	const char 		*name, *file;
+	int			line;
+	void			*magic;
+#endif
+};
+
+struct rt_mutex_waiter;
+struct hrtimer_sleeper;
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+ extern int rt_mutex_debug_check_no_locks_freed(const void *from,
+						unsigned long len);
+ extern void rt_mutex_debug_check_no_locks_held(struct task_struct *task);
+#else
+ static inline int rt_mutex_debug_check_no_locks_freed(const void *from,
+						       unsigned long len)
+ {
+	return 0;
+ }
+# define rt_mutex_debug_check_no_locks_held(task)	do { } while (0)
+#endif
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \
+	, .name = #mutexname, .file = __FILE__, .line = __LINE__
+# define rt_mutex_init(mutex)			__rt_mutex_init(mutex, __FUNCTION__)
+ extern void rt_mutex_debug_task_free(struct task_struct *tsk);
+#else
+# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname)
+# define rt_mutex_init(mutex)			__rt_mutex_init(mutex, NULL)
+# define rt_mutex_debug_task_free(t)			do { } while (0)
+#endif
+
+#define __RT_MUTEX_INITIALIZER(mutexname) \
+	{ .wait_lock = SPIN_LOCK_UNLOCKED \
+	, .wait_list = PLIST_HEAD_INIT(mutexname.wait_list, mutexname.wait_lock) \
+	, .owner = NULL \
+	__DEBUG_RT_MUTEX_INITIALIZER(mutexname)}
+
+#define DEFINE_RT_MUTEX(mutexname) \
+	struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname)
+
+/***
+ * rt_mutex_is_locked - is the mutex locked
+ * @lock: the mutex to be queried
+ *
+ * Returns 1 if the mutex is locked, 0 if unlocked.
+ */
+static inline int rt_mutex_is_locked(struct rt_mutex *lock)
+{
+	return lock->owner != NULL;
+}
+
+extern void __rt_mutex_init(struct rt_mutex *lock, const char *name);
+extern void rt_mutex_destroy(struct rt_mutex *lock);
+
+extern void rt_mutex_lock(struct rt_mutex *lock);
+extern int rt_mutex_lock_interruptible(struct rt_mutex *lock,
+						int detect_deadlock);
+extern int rt_mutex_timed_lock(struct rt_mutex *lock,
+					struct hrtimer_sleeper *timeout,
+					int detect_deadlock);
+
+extern int rt_mutex_trylock(struct rt_mutex *lock);
+
+extern void rt_mutex_unlock(struct rt_mutex *lock);
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# define INIT_RT_MUTEX_DEBUG(tsk)					\
+	.held_list_head	= LIST_HEAD_INIT(tsk.held_list_head),		\
+	.held_list_lock	= SPIN_LOCK_UNLOCKED
+#else
+# define INIT_RT_MUTEX_DEBUG(tsk)
+#endif
+
+#ifdef CONFIG_RT_MUTEXES
+# define INIT_RT_MUTEXES(tsk)						\
+	.pi_waiters	= PLIST_HEAD_INIT(tsk.pi_waiters, tsk.pi_lock),	\
+	INIT_RT_MUTEX_DEBUG(tsk)
+#else
+# define INIT_RT_MUTEXES(tsk)
+#endif
+
+#endif
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index df0cdd4..facd9ee 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -909,7 +909,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/mutex.h>
 
 extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size);
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index bfb9888..f99fe90 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -13,7 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <asm/system.h>
diff --git a/include/linux/scc.h b/include/linux/scc.h
index 885a4a0..3495bd9 100644
--- a/include/linux/scc.h
+++ b/include/linux/scc.h
@@ -3,7 +3,6 @@
 #ifndef	_SCC_H
 #define	_SCC_H
 
-#include <linux/config.h>
 
 /* selection of hardware types */
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 29b7d4f..821f048 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1,9 +1,46 @@
 #ifndef _LINUX_SCHED_H
 #define _LINUX_SCHED_H
 
+#include <linux/auxvec.h>	/* For AT_VECTOR_SIZE */
+
+/*
+ * cloning flags:
+ */
+#define CSIGNAL		0x000000ff	/* signal mask to be sent at exit */
+#define CLONE_VM	0x00000100	/* set if VM shared between processes */
+#define CLONE_FS	0x00000200	/* set if fs info shared between processes */
+#define CLONE_FILES	0x00000400	/* set if open files shared between processes */
+#define CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
+#define CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
+#define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mm_release */
+#define CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
+#define CLONE_THREAD	0x00010000	/* Same thread group? */
+#define CLONE_NEWNS	0x00020000	/* New namespace group? */
+#define CLONE_SYSVSEM	0x00040000	/* share system V SEM_UNDO semantics */
+#define CLONE_SETTLS	0x00080000	/* create a new TLS for the child */
+#define CLONE_PARENT_SETTID	0x00100000	/* set the TID in the parent */
+#define CLONE_CHILD_CLEARTID	0x00200000	/* clear the TID in the child */
+#define CLONE_DETACHED		0x00400000	/* Unused, ignored */
+#define CLONE_UNTRACED		0x00800000	/* set if the tracing process can't force CLONE_PTRACE on this clone */
+#define CLONE_CHILD_SETTID	0x01000000	/* set the TID in the child */
+#define CLONE_STOPPED		0x02000000	/* Start in stopped state */
+
+/*
+ * Scheduling policies
+ */
+#define SCHED_NORMAL		0
+#define SCHED_FIFO		1
+#define SCHED_RR		2
+#define SCHED_BATCH		3
+
+#ifdef __KERNEL__
+
+struct sched_param {
+	int sched_priority;
+};
+
 #include <asm/param.h>	/* for HZ */
 
-#include <linux/config.h>
 #include <linux/capability.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
@@ -36,32 +73,18 @@
 #include <linux/seccomp.h>
 #include <linux/rcupdate.h>
 #include <linux/futex.h>
+#include <linux/rtmutex.h>
 
-#include <linux/auxvec.h>	/* For AT_VECTOR_SIZE */
+#include <linux/time.h>
+#include <linux/param.h>
+#include <linux/resource.h>
+#include <linux/timer.h>
+#include <linux/hrtimer.h>
+
+#include <asm/processor.h>
 
 struct exec_domain;
-
-/*
- * cloning flags:
- */
-#define CSIGNAL		0x000000ff	/* signal mask to be sent at exit */
-#define CLONE_VM	0x00000100	/* set if VM shared between processes */
-#define CLONE_FS	0x00000200	/* set if fs info shared between processes */
-#define CLONE_FILES	0x00000400	/* set if open files shared between processes */
-#define CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
-#define CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
-#define CLONE_VFORK	0x00004000	/* set if the parent wants the child to wake it up on mm_release */
-#define CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
-#define CLONE_THREAD	0x00010000	/* Same thread group? */
-#define CLONE_NEWNS	0x00020000	/* New namespace group? */
-#define CLONE_SYSVSEM	0x00040000	/* share system V SEM_UNDO semantics */
-#define CLONE_SETTLS	0x00080000	/* create a new TLS for the child */
-#define CLONE_PARENT_SETTID	0x00100000	/* set the TID in the parent */
-#define CLONE_CHILD_CLEARTID	0x00200000	/* clear the TID in the child */
-#define CLONE_DETACHED		0x00400000	/* Unused, ignored */
-#define CLONE_UNTRACED		0x00800000	/* set if the tracing process can't force CLONE_PTRACE on this clone */
-#define CLONE_CHILD_SETTID	0x01000000	/* set the TID in the child */
-#define CLONE_STOPPED		0x02000000	/* Start in stopped state */
+struct futex_pi_state;
 
 /*
  * List of flags we want to share for kernel threads,
@@ -102,14 +125,8 @@
 extern unsigned long nr_uninterruptible(void);
 extern unsigned long nr_active(void);
 extern unsigned long nr_iowait(void);
+extern unsigned long weighted_cpuload(const int cpu);
 
-#include <linux/time.h>
-#include <linux/param.h>
-#include <linux/resource.h>
-#include <linux/timer.h>
-#include <linux/hrtimer.h>
-
-#include <asm/processor.h>
 
 /*
  * Task state bitmask. NOTE! These bits are also
@@ -156,20 +173,6 @@
 /* Task command name length */
 #define TASK_COMM_LEN 16
 
-/*
- * Scheduling policies
- */
-#define SCHED_NORMAL		0
-#define SCHED_FIFO		1
-#define SCHED_RR		2
-#define SCHED_BATCH		3
-
-struct sched_param {
-	int sched_priority;
-};
-
-#ifdef __KERNEL__
-
 #include <linux/spinlock.h>
 
 /*
@@ -358,6 +361,14 @@
 	spinlock_t		siglock;
 };
 
+struct pacct_struct {
+	int			ac_flag;
+	long			ac_exitcode;
+	unsigned long		ac_mem;
+	cputime_t		ac_utime, ac_stime;
+	unsigned long		ac_minflt, ac_majflt;
+};
+
 /*
  * NOTE! "signal_struct" does not have it's own
  * locking, because a shared signal_struct always
@@ -449,6 +460,9 @@
 	struct key *session_keyring;	/* keyring inherited over fork */
 	struct key *process_keyring;	/* keyring private to this process */
 #endif
+#ifdef CONFIG_BSD_PROCESS_ACCT
+	struct pacct_struct pacct;	/* per-process accounting information */
+#endif
 };
 
 /* Context switch must be unlocked if interrupts are to be enabled */
@@ -483,8 +497,11 @@
 
 #define MAX_PRIO		(MAX_RT_PRIO + 40)
 
-#define rt_task(p)		(unlikely((p)->prio < MAX_RT_PRIO))
+#define rt_prio(prio)		unlikely((prio) < MAX_RT_PRIO)
+#define rt_task(p)		rt_prio((p)->prio)
 #define batch_task(p)		(unlikely((p)->policy == SCHED_BATCH))
+#define has_rt_policy(p) \
+	unlikely((p)->policy != SCHED_NORMAL && (p)->policy != SCHED_BATCH)
 
 /*
  * Some day this will be a full-fledged user tracking system..
@@ -494,7 +511,7 @@
 	atomic_t processes;	/* How many processes does this user have? */
 	atomic_t files;		/* How many open files does this user have? */
 	atomic_t sigpending;	/* How many pending signals does this user have? */
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
 	atomic_t inotify_watches; /* How many inotify watches does this user have? */
 	atomic_t inotify_devs;	/* How many inotify devs does this user have opened? */
 #endif
@@ -547,9 +564,9 @@
 /*
  * sched-domains (multiprocessor balancing) declarations:
  */
-#ifdef CONFIG_SMP
 #define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
 
+#ifdef CONFIG_SMP
 #define SD_LOAD_BALANCE		1	/* Do load balancing on this domain. */
 #define SD_BALANCE_NEWIDLE	2	/* Balance when about to become idle */
 #define SD_BALANCE_EXEC		4	/* Balance on exec */
@@ -558,6 +575,11 @@
 #define SD_WAKE_AFFINE		32	/* Wake task to waking CPU */
 #define SD_WAKE_BALANCE		64	/* Perform balancing at task wakeup */
 #define SD_SHARE_CPUPOWER	128	/* Domain members share cpu power */
+#define SD_POWERSAVINGS_BALANCE	256	/* Balance for power savings */
+
+#define BALANCE_FOR_POWER	((sched_mc_power_savings || sched_smt_power_savings) \
+				 ? SD_POWERSAVINGS_BALANCE : 0)
+
 
 struct sched_group {
 	struct sched_group *next;	/* Must be a circular list */
@@ -627,7 +649,7 @@
 #endif
 };
 
-extern void partition_sched_domains(cpumask_t *partition1,
+extern int partition_sched_domains(cpumask_t *partition1,
 				    cpumask_t *partition2);
 
 /*
@@ -702,10 +724,13 @@
 
 	int lock_depth;		/* BKL lock depth */
 
-#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+#ifdef CONFIG_SMP
+#ifdef __ARCH_WANT_UNLOCKED_CTXSW
 	int oncpu;
 #endif
-	int prio, static_prio;
+#endif
+	int load_weight;	/* for niceness load balancing purposes */
+	int prio, static_prio, normal_prio;
 	struct list_head run_list;
 	prio_array_t *array;
 
@@ -831,8 +856,20 @@
    	u32 self_exec_id;
 /* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
 	spinlock_t alloc_lock;
-/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
-	spinlock_t proc_lock;
+
+	/* Protection of the PI data structures: */
+	spinlock_t pi_lock;
+
+#ifdef CONFIG_RT_MUTEXES
+	/* PI waiters blocked on a rt_mutex held by this task */
+	struct plist_head pi_waiters;
+	/* Deadlock detection and priority inheritance handling */
+	struct rt_mutex_waiter *pi_blocked_on;
+# ifdef CONFIG_DEBUG_RT_MUTEXES
+	spinlock_t held_list_lock;
+	struct list_head held_list_head;
+# endif
+#endif
 
 #ifdef CONFIG_DEBUG_MUTEXES
 	/* mutex deadlock detection */
@@ -845,7 +882,6 @@
 /* VM state */
 	struct reclaim_state *reclaim_state;
 
-	struct dentry *proc_dentry;
 	struct backing_dev_info *backing_dev_info;
 
 	struct io_context *io_context;
@@ -880,6 +916,8 @@
 #ifdef CONFIG_COMPAT
 	struct compat_robust_list_head __user *compat_robust_list;
 #endif
+	struct list_head pi_state_list;
+	struct futex_pi_state *pi_state_cache;
 
 	atomic_t fs_excl;	/* holding fs exclusive resources */
 	struct rcu_head rcu;
@@ -941,13 +979,13 @@
 #define PF_KSWAPD	0x00040000	/* I am kswapd */
 #define PF_SWAPOFF	0x00080000	/* I am in swapoff */
 #define PF_LESS_THROTTLE 0x00100000	/* Throttle me less: I clean memory */
-#define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
-#define PF_BORROWED_MM	0x00400000	/* I am a kthread doing use_mm */
-#define PF_RANDOMIZE	0x00800000	/* randomize virtual address space */
-#define PF_SWAPWRITE	0x01000000	/* Allowed to write to swap */
-#define PF_SPREAD_PAGE	0x04000000	/* Spread page cache over cpuset */
-#define PF_SPREAD_SLAB	0x08000000	/* Spread some slab caches over cpuset */
+#define PF_BORROWED_MM	0x00200000	/* I am a kthread doing use_mm */
+#define PF_RANDOMIZE	0x00400000	/* randomize virtual address space */
+#define PF_SWAPWRITE	0x00800000	/* Allowed to write to swap */
+#define PF_SPREAD_PAGE	0x01000000	/* Spread page cache over cpuset */
+#define PF_SPREAD_SLAB	0x02000000	/* Spread some slab caches over cpuset */
 #define PF_MEMPOLICY	0x10000000	/* Non-default NUMA mempolicy */
+#define PF_MUTEX_TESTER	0x20000000	/* Thread belongs to the rt mutex tester */
 
 /*
  * Only the _current_ task can read/write to tsk->flags, but other
@@ -1002,6 +1040,19 @@
 #endif
 
 extern void sched_idle_next(void);
+
+#ifdef CONFIG_RT_MUTEXES
+extern int rt_mutex_getprio(task_t *p);
+extern void rt_mutex_setprio(task_t *p, int prio);
+extern void rt_mutex_adjust_pi(task_t *p);
+#else
+static inline int rt_mutex_getprio(task_t *p)
+{
+	return p->normal_prio;
+}
+# define rt_mutex_adjust_pi(p)		do { } while (0)
+#endif
+
 extern void set_user_nice(task_t *p, long nice);
 extern int task_prio(const task_t *p);
 extern int task_nice(const task_t *p);
@@ -1225,7 +1276,7 @@
 		(thread_group_leader(p) && !thread_group_empty(p))
 
 /*
- * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring
+ * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring
  * subscriptions and synchronises with wait4().  Also used in procfs.  Also
  * pins the final release of task.io_context.  Also protects ->cpuset.
  *
@@ -1401,6 +1452,11 @@
 extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
 extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
 
+#include <linux/sysdev.h>
+extern int sched_mc_power_savings, sched_smt_power_savings;
+extern struct sysdev_attribute attr_sched_mc_power_savings, attr_sched_smt_power_savings;
+extern int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls);
+
 extern void normalize_rt_tasks(void);
 
 #ifdef CONFIG_PM
diff --git a/include/linux/scx200.h b/include/linux/scx200.h
index a22f9e1..693c055 100644
--- a/include/linux/scx200.h
+++ b/include/linux/scx200.h
@@ -49,10 +49,3 @@
 #define SCx200_REV 0x3d		/* Revision Register */
 #define SCx200_CBA 0x3e		/* Configuration Base Address Register */
 #define SCx200_CBA_SCRATCH 0x64	/* Configuration Base Address Scratchpad */
-
-/*
-    Local variables:
-        compile-command: "make -C ../.. bzImage modules"
-        c-basic-offset: 8
-    End:
-*/
diff --git a/include/linux/scx200_gpio.h b/include/linux/scx200_gpio.h
index 30cdd64..90dd069 100644
--- a/include/linux/scx200_gpio.h
+++ b/include/linux/scx200_gpio.h
@@ -1,6 +1,6 @@
 #include <linux/spinlock.h>
 
-u32 scx200_gpio_configure(int index, u32 set, u32 clear);
+u32 scx200_gpio_configure(unsigned index, u32 set, u32 clear);
 
 extern unsigned scx200_gpio_base;
 extern long scx200_gpio_shadow[2];
@@ -17,7 +17,7 @@
 
 /* returns the value of the GPIO pin */
 
-static inline int scx200_gpio_get(int index) {
+static inline int scx200_gpio_get(unsigned index) {
 	__SCx200_GPIO_BANK;
 	__SCx200_GPIO_IOADDR + 0x04;
 	__SCx200_GPIO_INDEX;
@@ -29,7 +29,7 @@
    driven if the GPIO is configured as an output, it might not be the
    state of the GPIO right now if the GPIO is configured as an input) */
 
-static inline int scx200_gpio_current(int index) {
+static inline int scx200_gpio_current(unsigned index) {
         __SCx200_GPIO_BANK;
 	__SCx200_GPIO_INDEX;
 		
@@ -38,7 +38,7 @@
 
 /* drive the GPIO signal high */
 
-static inline void scx200_gpio_set_high(int index) {
+static inline void scx200_gpio_set_high(unsigned index) {
 	__SCx200_GPIO_BANK;
 	__SCx200_GPIO_IOADDR;
 	__SCx200_GPIO_SHADOW;
@@ -49,7 +49,7 @@
 
 /* drive the GPIO signal low */
 
-static inline void scx200_gpio_set_low(int index) {
+static inline void scx200_gpio_set_low(unsigned index) {
 	__SCx200_GPIO_BANK;
 	__SCx200_GPIO_IOADDR;
 	__SCx200_GPIO_SHADOW;
@@ -60,7 +60,7 @@
 
 /* drive the GPIO signal to state */
 
-static inline void scx200_gpio_set(int index, int state) {
+static inline void scx200_gpio_set(unsigned index, int state) {
 	__SCx200_GPIO_BANK;
 	__SCx200_GPIO_IOADDR;
 	__SCx200_GPIO_SHADOW;
@@ -73,7 +73,7 @@
 }
 
 /* toggle the GPIO signal */
-static inline void scx200_gpio_change(int index) {
+static inline void scx200_gpio_change(unsigned index) {
 	__SCx200_GPIO_BANK;
 	__SCx200_GPIO_IOADDR;
 	__SCx200_GPIO_SHADOW;
@@ -87,10 +87,3 @@
 #undef __SCx200_GPIO_SHADOW
 #undef __SCx200_GPIO_INDEX
 #undef __SCx200_GPIO_OUT
-
-/*
-    Local variables:
-        compile-command: "make -C ../.. bzImage modules"
-        c-basic-offset: 8
-    End:
-*/
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index cd2773b..3e8b1cf 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_SECCOMP_H
 #define _LINUX_SECCOMP_H
 
-#include <linux/config.h>
 
 #ifdef CONFIG_SECCOMP
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 1bab48f..5180580 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -171,9 +171,9 @@
  *	Deallocate and clear the sb->s_security field.
  *	@sb contains the super_block structure to be modified.
  * @sb_statfs:
- *	Check permission before obtaining filesystem statistics for the @sb
- *	filesystem.
- *	@sb contains the super_block structure for the filesystem.
+ *	Check permission before obtaining filesystem statistics for the @mnt
+ *	mountpoint.
+ *	@dentry is a handle on the superblock for the filesystem.
  *	Return 0 if permission is granted.  
  * @sb_mount:
  *	Check permission before an object specified by @dev_name is mounted on
@@ -577,6 +577,11 @@
  *	@p contains the task_struct of process.
  *	@nice contains the new nice value.
  *	Return 0 if permission is granted.
+ * @task_setioprio
+ *	Check permission before setting the ioprio value of @p to @ioprio.
+ *	@p contains the task_struct of process.
+ *	@ioprio contains the new ioprio value
+ *	Return 0 if permission is granted.
  * @task_setrlimit:
  *	Check permission before setting the resource limits of the current
  *	process for @resource to @new_rlim.  The old resource limit values can
@@ -596,6 +601,10 @@
  *	@p.
  *	@p contains the task_struct for process.
  *	Return 0 if permission is granted.
+ * @task_movememory
+ *	Check permission before moving memory owned by process @p.
+ *	@p contains the task_struct for process.
+ *	Return 0 if permission is granted.
  * @task_kill:
  *	Check permission before sending signal @sig to @p.  @info can be NULL,
  *	the constant 1, or a pointer to a siginfo structure.  If @info is 1 or
@@ -805,31 +814,37 @@
  *	used by the XFRM system.
  *	@sec_ctx contains the security context information being provided by
  *	the user-level policy update program (e.g., setkey).
- *	Allocate a security structure to the xp->selector.security field.
+ *	Allocate a security structure to the xp->security field.
  *	The security field is initialized to NULL when the xfrm_policy is
  *	allocated.
  *	Return 0 if operation was successful (memory to allocate, legal context)
  * @xfrm_policy_clone_security:
  *	@old contains an existing xfrm_policy in the SPD.
  *	@new contains a new xfrm_policy being cloned from old.
- *	Allocate a security structure to the new->selector.security field
- *	that contains the information from the old->selector.security field.
+ *	Allocate a security structure to the new->security field
+ *	that contains the information from the old->security field.
  *	Return 0 if operation was successful (memory to allocate).
  * @xfrm_policy_free_security:
  *	@xp contains the xfrm_policy
- *	Deallocate xp->selector.security.
+ *	Deallocate xp->security.
+ * @xfrm_policy_delete_security:
+ *	@xp contains the xfrm_policy.
+ *	Authorize deletion of xp->security.
  * @xfrm_state_alloc_security:
  *	@x contains the xfrm_state being added to the Security Association
  *	Database by the XFRM system.
  *	@sec_ctx contains the security context information being provided by
  *	the user-level SA generation program (e.g., setkey or racoon).
- *	Allocate a security structure to the x->sel.security field.  The
+ *	Allocate a security structure to the x->security field.  The
  *	security field is initialized to NULL when the xfrm_state is
  *	allocated.
  *	Return 0 if operation was successful (memory to allocate, legal context).
  * @xfrm_state_free_security:
  *	@x contains the xfrm_state.
- *	Deallocate x>sel.security.
+ *	Deallocate x->security.
+ * @xfrm_state_delete_security:
+ *	@x contains the xfrm_state.
+ *	Authorize deletion of x->security.
  * @xfrm_policy_lookup:
  *	@xp contains the xfrm_policy for which the access control is being
  *	checked.
@@ -847,6 +862,7 @@
  *	Permit allocation of a key and assign security data. Note that key does
  *	not have a serial number assigned at this point.
  *	@key points to the key.
+ *	@flags is the allocation flags
  *	Return 0 if permission is granted, -ve error otherwise.
  * @key_free:
  *	Notification of destruction; free security data.
@@ -1121,7 +1137,7 @@
 	int (*sb_copy_data)(struct file_system_type *type,
 			    void *orig, void *copy);
 	int (*sb_kern_mount) (struct super_block *sb, void *data);
-	int (*sb_statfs) (struct super_block * sb);
+	int (*sb_statfs) (struct dentry *dentry);
 	int (*sb_mount) (char *dev_name, struct nameidata * nd,
 			 char *type, unsigned long flags, void *data);
 	int (*sb_check_sb) (struct vfsmount * mnt, struct nameidata * nd);
@@ -1204,10 +1220,12 @@
 	int (*task_getsid) (struct task_struct * p);
 	int (*task_setgroups) (struct group_info *group_info);
 	int (*task_setnice) (struct task_struct * p, int nice);
+	int (*task_setioprio) (struct task_struct * p, int ioprio);
 	int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim);
 	int (*task_setscheduler) (struct task_struct * p, int policy,
 				  struct sched_param * lp);
 	int (*task_getscheduler) (struct task_struct * p);
+	int (*task_movememory) (struct task_struct * p);
 	int (*task_kill) (struct task_struct * p,
 			  struct siginfo * info, int sig);
 	int (*task_wait) (struct task_struct * p);
@@ -1298,14 +1316,16 @@
 	int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
 	int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
 	void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
+	int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
 	int (*xfrm_state_alloc_security) (struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
 	void (*xfrm_state_free_security) (struct xfrm_state *x);
+	int (*xfrm_state_delete_security) (struct xfrm_state *x);
 	int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
 #endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 
 	/* key management security hooks */
 #ifdef CONFIG_KEYS
-	int (*key_alloc)(struct key *key);
+	int (*key_alloc)(struct key *key, struct task_struct *tsk, unsigned long flags);
 	void (*key_free)(struct key *key);
 	int (*key_permission)(key_ref_t key_ref,
 			      struct task_struct *context,
@@ -1442,9 +1462,9 @@
 	return security_ops->sb_kern_mount (sb, data);
 }
 
-static inline int security_sb_statfs (struct super_block *sb)
+static inline int security_sb_statfs (struct dentry *dentry)
 {
-	return security_ops->sb_statfs (sb);
+	return security_ops->sb_statfs (dentry);
 }
 
 static inline int security_sb_mount (char *dev_name, struct nameidata *nd,
@@ -1828,6 +1848,11 @@
 	return security_ops->task_setnice (p, nice);
 }
 
+static inline int security_task_setioprio (struct task_struct *p, int ioprio)
+{
+	return security_ops->task_setioprio (p, ioprio);
+}
+
 static inline int security_task_setrlimit (unsigned int resource,
 					   struct rlimit *new_rlim)
 {
@@ -1846,6 +1871,11 @@
 	return security_ops->task_getscheduler (p);
 }
 
+static inline int security_task_movememory (struct task_struct *p)
+{
+	return security_ops->task_movememory (p);
+}
+
 static inline int security_task_kill (struct task_struct *p,
 				      struct siginfo *info, int sig)
 {
@@ -2154,7 +2184,7 @@
 	return 0;
 }
 
-static inline int security_sb_statfs (struct super_block *sb)
+static inline int security_sb_statfs (struct dentry *dentry)
 {
 	return 0;
 }
@@ -2470,6 +2500,11 @@
 	return 0;
 }
 
+static inline int security_task_setioprio (struct task_struct *p, int ioprio)
+{
+	return 0;
+}
+
 static inline int security_task_setrlimit (unsigned int resource,
 					   struct rlimit *new_rlim)
 {
@@ -2488,6 +2523,11 @@
 	return 0;
 }
 
+static inline int security_task_movememory (struct task_struct *p)
+{
+	return 0;
+}
+
 static inline int security_task_kill (struct task_struct *p,
 				      struct siginfo *info, int sig)
 {
@@ -2934,11 +2974,21 @@
 	security_ops->xfrm_policy_free_security(xp);
 }
 
+static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
+{
+	return security_ops->xfrm_policy_delete_security(xp);
+}
+
 static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
 {
 	return security_ops->xfrm_state_alloc_security(x, sec_ctx);
 }
 
+static inline int security_xfrm_state_delete(struct xfrm_state *x)
+{
+	return security_ops->xfrm_state_delete_security(x);
+}
+
 static inline void security_xfrm_state_free(struct xfrm_state *x)
 {
 	security_ops->xfrm_state_free_security(x);
@@ -2963,6 +3013,11 @@
 {
 }
 
+static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
+{
+	return 0;
+}
+
 static inline int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
 {
 	return 0;
@@ -2972,6 +3027,11 @@
 {
 }
 
+static inline int security_xfrm_state_delete(struct xfrm_state *x)
+{
+	return 0;
+}
+
 static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
 {
 	return 0;
@@ -2980,9 +3040,11 @@
 
 #ifdef CONFIG_KEYS
 #ifdef CONFIG_SECURITY
-static inline int security_key_alloc(struct key *key)
+static inline int security_key_alloc(struct key *key,
+				     struct task_struct *tsk,
+				     unsigned long flags)
 {
-	return security_ops->key_alloc(key);
+	return security_ops->key_alloc(key, tsk, flags);
 }
 
 static inline void security_key_free(struct key *key)
@@ -2999,7 +3061,9 @@
 
 #else
 
-static inline int security_key_alloc(struct key *key)
+static inline int security_key_alloc(struct key *key,
+				     struct task_struct *tsk,
+				     unsigned long flags)
 {
 	return 0;
 }
diff --git a/include/linux/selinux.h b/include/linux/selinux.h
index 4047bcd..aad4e39 100644
--- a/include/linux/selinux.h
+++ b/include/linux/selinux.h
@@ -118,6 +118,27 @@
  */
 void selinux_get_task_sid(struct task_struct *tsk, u32 *sid);
 
+/**
+ *     selinux_string_to_sid - map a security context string to a security ID
+ *     @str: the security context string to be mapped
+ *     @sid: ID value returned via this.
+ *
+ *     Returns 0 if successful, with the SID stored in sid.  A value
+ *     of zero for sid indicates no SID could be determined (but no error
+ *     occurred).
+ */
+int selinux_string_to_sid(char *str, u32 *sid);
+
+/**
+ *     selinux_relabel_packet_permission - check permission to relabel a packet
+ *     @sid: ID value to be applied to network packet (via SECMARK, most likely)
+ *
+ *     Returns 0 if the current task is allowed to label packets with the
+ *     supplied security ID.  Note that it is implicit that the packet is always
+ *     being relabeled from the default unlabled value, and that the access
+ *     control decision is made in the AVC.
+ */
+int selinux_relabel_packet_permission(u32 sid);
 
 #else
 
@@ -172,6 +193,17 @@
 	*sid = 0;
 }
 
+static inline int selinux_string_to_sid(const char *str, u32 *sid)
+{
+       *sid = 0;
+       return 0;
+}
+
+static inline int selinux_relabel_packet_permission(u32 sid)
+{
+	return 0;
+}
+
 #endif	/* CONFIG_SECURITY_SELINUX */
 
 #endif /* _LINUX_SELINUX_H */
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 3c1f112..9aaffb0 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -2,7 +2,6 @@
 #define _LINUX_SEM_H
 
 #include <linux/ipc.h>
-#include <asm/atomic.h>
 
 /* semop flags */
 #define SEM_UNDO        0x1000  /* undo the operation on exit */
@@ -78,6 +77,7 @@
 #define SEMUSZ  20		/* sizeof struct sem_undo */
 
 #ifdef __KERNEL__
+#include <asm/atomic.h>
 
 struct task_struct;
 
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 5a09557..7bc5c7c 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -26,7 +26,6 @@
  * by Keith Owens and Andrea Arcangeli
  */
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/preempt.h>
 
diff --git a/include/linux/serialP.h b/include/linux/serialP.h
index 2b9e6b9..e811a61 100644
--- a/include/linux/serialP.h
+++ b/include/linux/serialP.h
@@ -19,7 +19,6 @@
  * For definitions of the flags field, see tty.h
  */
 
-#include <linux/config.h>
 #include <linux/termios.h>
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index bd14858..951c4e8 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -67,8 +67,8 @@
 /* Parisc type numbers. */
 #define PORT_MUX	48
 
-/* Atmel AT91RM9200 SoC */
-#define PORT_AT91RM9200 49
+/* Atmel AT91xxx SoC */
+#define PORT_AT91	49
 
 /* Macintosh Zilog type numbers */
 #define PORT_MAC_ZILOG	50	/* m68k : not yet implemented */
@@ -130,9 +130,11 @@
 /* SUN4V Hypervisor Console */
 #define PORT_SUNHV	72
 
+#define PORT_S3C2412	73
+
+
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/interrupt.h>
 #include <linux/circ_buf.h>
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 70739f5..1e4ce72 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -1,12 +1,12 @@
 #ifndef _LINUX_SIGNAL_H
 #define _LINUX_SIGNAL_H
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
 #include <asm/signal.h>
 #include <asm/siginfo.h>
 
 #ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/spinlock.h>
 
 /*
  * These values of sa_flags are used only by the kernel as part of the
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index f8f2347..16eef03 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -14,7 +14,6 @@
 #ifndef _LINUX_SKBUFF_H
 #define _LINUX_SKBUFF_H
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/time.h>
@@ -29,6 +28,7 @@
 #include <linux/net.h>
 #include <linux/textsearch.h>
 #include <net/checksum.h>
+#include <linux/dmaengine.h>
 
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB	/* Ditto 8)		   */
@@ -134,9 +134,10 @@
 struct skb_shared_info {
 	atomic_t	dataref;
 	unsigned short	nr_frags;
-	unsigned short	tso_size;
-	unsigned short	tso_segs;
-	unsigned short  ufo_size;
+	unsigned short	gso_size;
+	/* Warning: this field is not always filled in (UFO)! */
+	unsigned short	gso_segs;
+	unsigned short  gso_type;
 	unsigned int    ip6_frag_id;
 	struct sk_buff	*frag_list;
 	skb_frag_t	frags[MAX_SKB_FRAGS];
@@ -168,6 +169,11 @@
 	SKB_FCLONE_CLONE,
 };
 
+enum {
+	SKB_GSO_TCPV4 = 1 << 0,
+	SKB_GSO_UDPV4 = 1 << 1,
+};
+
 /** 
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
@@ -209,6 +215,9 @@
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *	@tc_index: Traffic control index
  *	@tc_verd: traffic control verdict
+ *	@dma_cookie: a cookie to one of several possible DMA operations
+ *		done by skb DMA functions
+ *	@secmark: security marking
  */
 
 struct sk_buff {
@@ -285,6 +294,12 @@
 	__u16			tc_verd;	/* traffic control verdict */
 #endif
 #endif
+#ifdef CONFIG_NET_DMA
+	dma_cookie_t		dma_cookie;
+#endif
+#ifdef CONFIG_NETWORK_SECMARK
+	__u32			secmark;
+#endif
 
 
 	/* These elements must be at the end, see alloc_skb() for details.  */
@@ -338,7 +353,7 @@
 extern struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
 				       int newheadroom, int newtailroom,
 				       gfp_t priority);
-extern struct sk_buff *		skb_pad(struct sk_buff *skb, int pad);
+extern int	       skb_pad(struct sk_buff *skb, int pad);
 #define dev_kfree_skb(a)	kfree_skb(a)
 extern void	      skb_over_panic(struct sk_buff *skb, int len,
 				     void *here);
@@ -967,15 +982,16 @@
 #define NET_SKB_PAD	16
 #endif
 
-extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
+extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
 
 static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
 {
-	if (!skb->data_len) {
-		skb->len  = len;
-		skb->tail = skb->data + len;
-	} else
-		___pskb_trim(skb, len, 0);
+	if (unlikely(skb->data_len)) {
+		WARN_ON(1);
+		return;
+	}
+	skb->len  = len;
+	skb->tail = skb->data + len;
 }
 
 /**
@@ -985,6 +1001,7 @@
  *
  *	Cut the length of a buffer down by removing data from the tail. If
  *	the buffer is already under the length specified it is not modified.
+ *	The skb must be linear.
  */
 static inline void skb_trim(struct sk_buff *skb, unsigned int len)
 {
@@ -995,12 +1012,10 @@
 
 static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
 {
-	if (!skb->data_len) {
-		skb->len  = len;
-		skb->tail = skb->data+len;
-		return 0;
-	}
-	return ___pskb_trim(skb, len, 1);
+	if (skb->data_len)
+		return ___pskb_trim(skb, len);
+	__skb_trim(skb, len);
+	return 0;
 }
 
 static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
@@ -1115,16 +1130,15 @@
  *
  *	Pads up a buffer to ensure the trailing bytes exist and are
  *	blanked. If the buffer already contains sufficient data it
- *	is untouched. Returns the buffer, which may be a replacement
- *	for the original, or NULL for out of memory - in which case
- *	the original buffer is still freed.
+ *	is untouched. Otherwise it is extended. Returns zero on
+ *	success. The skb is freed on error.
  */
  
-static inline struct sk_buff *skb_padto(struct sk_buff *skb, unsigned int len)
+static inline int skb_padto(struct sk_buff *skb, unsigned int len)
 {
 	unsigned int size = skb->len;
 	if (likely(size >= len))
-		return skb;
+		return 0;
 	return skb_pad(skb, len-size);
 }
 
@@ -1161,18 +1175,34 @@
 	return 0;
 }
 
+static inline int __skb_linearize(struct sk_buff *skb)
+{
+	return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM;
+}
+
 /**
  *	skb_linearize - convert paged skb to linear one
  *	@skb: buffer to linarize
- *	@gfp: allocation mode
  *
  *	If there is no free memory -ENOMEM is returned, otherwise zero
  *	is returned and the old skb data released.
  */
-extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp);
-static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
+static inline int skb_linearize(struct sk_buff *skb)
 {
-	return __skb_linearize(skb, gfp);
+	return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
+}
+
+/**
+ *	skb_linearize_cow - make sure skb is linear and writable
+ *	@skb: buffer to process
+ *
+ *	If there is no free memory -ENOMEM is returned, otherwise zero
+ *	is returned and the old skb data released.
+ */
+static inline int skb_linearize_cow(struct sk_buff *skb)
+{
+	return skb_is_nonlinear(skb) || skb_cloned(skb) ?
+	       __skb_linearize(skb) : 0;
 }
 
 /**
@@ -1269,6 +1299,7 @@
 				 struct sk_buff *skb1, const u32 len);
 
 extern void	       skb_release_data(struct sk_buff *skb);
+extern struct sk_buff *skb_segment(struct sk_buff *skb, int sg);
 
 static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
 				       int len, void *buffer)
@@ -1396,5 +1427,23 @@
 static inline void nf_reset(struct sk_buff *skb) {}
 #endif /* CONFIG_NETFILTER */
 
+#ifdef CONFIG_NETWORK_SECMARK
+static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
+{
+	to->secmark = from->secmark;
+}
+
+static inline void skb_init_secmark(struct sk_buff *skb)
+{
+	skb->secmark = 0;
+}
+#else
+static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from)
+{ }
+
+static inline void skb_init_secmark(struct sk_buff *skb)
+{ }
+#endif
+
 #endif	/* __KERNEL__ */
 #endif	/* _LINUX_SKBUFF_H */
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 2d985d5..45ad55b 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -11,7 +11,6 @@
 
 typedef struct kmem_cache kmem_cache_t;
 
-#include	<linux/config.h>	/* kmalloc_sizes.h needs CONFIG_ options */
 #include	<linux/gfp.h>
 #include	<linux/init.h>
 #include	<linux/types.h>
@@ -87,6 +86,51 @@
     __kmalloc_track_caller(size, flags, __builtin_return_address(0))
 #endif
 
+/**
+ * kmalloc - allocate memory
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate.
+ *
+ * kmalloc is the normal method of allocating memory
+ * in the kernel.
+ *
+ * The @flags argument may be one of:
+ *
+ * %GFP_USER - Allocate memory on behalf of user.  May sleep.
+ *
+ * %GFP_KERNEL - Allocate normal kernel ram.  May sleep.
+ *
+ * %GFP_ATOMIC - Allocation will not sleep.
+ *   For example, use this inside interrupt handlers.
+ *
+ * %GFP_HIGHUSER - Allocate pages from high memory.
+ *
+ * %GFP_NOIO - Do not do any I/O at all while trying to get memory.
+ *
+ * %GFP_NOFS - Do not make any fs calls while trying to get memory.
+ *
+ * Also it is possible to set different flags by OR'ing
+ * in one or more of the following additional @flags:
+ *
+ * %__GFP_COLD - Request cache-cold pages instead of
+ *   trying to return cache-warm pages.
+ *
+ * %__GFP_DMA - Request memory from the DMA-capable zone.
+ *
+ * %__GFP_HIGH - This allocation has high priority and may use emergency pools.
+ *
+ * %__GFP_HIGHMEM - Allocated memory may be from highmem.
+ *
+ * %__GFP_NOFAIL - Indicate that this allocation is in no way allowed to fail
+ *   (think twice before using).
+ *
+ * %__GFP_NORETRY - If memory is not immediately available,
+ *   then give up at once.
+ *
+ * %__GFP_NOWARN - If allocation fails, don't issue any warnings.
+ *
+ * %__GFP_REPEAT - If allocation fails initially, try once more before failing.
+ */
 static inline void *kmalloc(size_t size, gfp_t flags)
 {
 	if (__builtin_constant_p(size)) {
@@ -112,6 +156,11 @@
 
 extern void *__kzalloc(size_t, gfp_t);
 
+/**
+ * kzalloc - allocate memory. The memory is set to zero.
+ * @size: how many bytes of memory are required.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
 static inline void *kzalloc(size_t size, gfp_t flags)
 {
 	if (__builtin_constant_p(size)) {
diff --git a/include/linux/smb_fs.h b/include/linux/smb_fs.h
index 621a3d3..367d6c3e 100644
--- a/include/linux/smb_fs.h
+++ b/include/linux/smb_fs.h
@@ -10,8 +10,6 @@
 #define _LINUX_SMB_FS_H
 
 #include <linux/smb.h>
-#include <linux/smb_fs_i.h>
-#include <linux/smb_fs_sb.h>
 
 /*
  * ioctl commands
@@ -24,6 +22,8 @@
 
 
 #ifdef __KERNEL__
+#include <linux/smb_fs_i.h>
+#include <linux/smb_fs_sb.h>
 
 #include <linux/fs.h>
 #include <linux/pagemap.h>
diff --git a/include/linux/smp.h b/include/linux/smp.h
index e2fa3ab..c93c3fe 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -6,7 +6,6 @@
  *		Alan Cox. <alan@redhat.com>
  */
 
-#include <linux/config.h>
 
 extern void cpu_idle(void);
 
diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h
index fa1ff3b..cf715a4 100644
--- a/include/linux/smp_lock.h
+++ b/include/linux/smp_lock.h
@@ -1,7 +1,6 @@
 #ifndef __LINUX_SMPLOCK_H
 #define __LINUX_SMPLOCK_H
 
-#include <linux/config.h>
 #ifdef CONFIG_LOCK_KERNEL
 #include <linux/sched.h>
 #include <linux/spinlock.h>
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 9ab2ddd..3614090 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -18,8 +18,6 @@
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
-#include <linux/config.h>		/* for CONFIG_COMPAT */
-#include <linux/linkage.h>
 #include <asm/socket.h>			/* arch-dependent defines	*/
 #include <linux/sockios.h>		/* the SIOCxxx I/O controls	*/
 #include <linux/uio.h>			/* iovec support		*/
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index e928c0d..c8bb680 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -642,10 +642,14 @@
 	u16		bus_num;
 	u16		chip_select;
 
+	/* mode becomes spi_device.mode, and is essential for chips
+	 * where the default of SPI_CS_HIGH = 0 is wrong.
+	 */
+	u8		mode;
+
 	/* ... may need additional spi_device chip config data here.
 	 * avoid stuff protocol drivers can set; but include stuff
 	 * needed to behave without being bound to a driver:
-	 *  - chipselect polarity
 	 *  - quirks like clock rate mattering when not selected
 	 */
 };
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 799be67..ae23bee 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -46,7 +46,6 @@
  *  linux/spinlock.h:     builds the final spin_*() APIs.
  */
 
-#include <linux/config.h>
 #include <linux/preempt.h>
 #include <linux/linkage.h>
 #include <linux/compiler.h>
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 151a803e..5bfc553 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -4,7 +4,6 @@
    very heavy lock, which is equivalent to grabbing every spinlock
    (and more).  So the "read" side to such a lock is anything which
    diables preeempt. */
-#include <linux/config.h>
 #include <linux/cpu.h>
 #include <asm/system.h>
 
diff --git a/include/linux/string.h b/include/linux/string.h
index c61306d..e4c7558 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -56,6 +56,7 @@
 #ifndef __HAVE_ARCH_STRRCHR
 extern char * strrchr(const char *,int);
 #endif
+extern char * strstrip(char *);
 #ifndef __HAVE_ARCH_STRSTR
 extern char * strstr(const char *,const char *);
 #endif
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index be4772e..a6de332 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -11,7 +11,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/msg_prot.h>
 #include <linux/sunrpc/xdr.h>
diff --git a/include/linux/sunrpc/debug.h b/include/linux/sunrpc/debug.h
index 1a42d90..e4729aa 100644
--- a/include/linux/sunrpc/debug.h
+++ b/include/linux/sunrpc/debug.h
@@ -9,19 +9,6 @@
 #ifndef _LINUX_SUNRPC_DEBUG_H_
 #define _LINUX_SUNRPC_DEBUG_H_
 
-#include <linux/config.h>
-
-#include <linux/timer.h>
-#include <linux/workqueue.h>
-
-/*
- * Enable RPC debugging/profiling.
- */
-#ifdef CONFIG_SYSCTL
-#define  RPC_DEBUG
-#endif
-/* #define  RPC_PROFILE */
-
 /*
  * RPC debug facilities
  */
@@ -41,6 +28,17 @@
 
 #ifdef __KERNEL__
 
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
+/*
+ * Enable RPC debugging/profiling.
+ */
+#ifdef CONFIG_SYSCTL
+#define  RPC_DEBUG
+#endif
+/* #define  RPC_PROFILE */
+
 /*
  * Debugging macros etc
  */
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
index 9b8bcf1..6e112cc 100644
--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -126,7 +126,7 @@
 /* Just increments the mechanism's reference count and returns its input: */
 struct gss_api_mech * gss_mech_get(struct gss_api_mech *);
 
-/* For every succesful gss_mech_get or gss_mech_get_by_* call there must be a
+/* For every successful gss_mech_get or gss_mech_get_by_* call there must be a
  * corresponding call to gss_mech_put. */
 void gss_mech_put(struct gss_api_mech *);
 
diff --git a/include/linux/sunrpc/stats.h b/include/linux/sunrpc/stats.h
index d93c24b..5fa0f20 100644
--- a/include/linux/sunrpc/stats.h
+++ b/include/linux/sunrpc/stats.h
@@ -9,7 +9,6 @@
 #ifndef _LINUX_SUNRPC_STATS_H
 #define _LINUX_SUNRPC_STATS_H
 
-#include <linux/config.h>
 #include <linux/proc_fs.h>
 
 struct rpc_stat {
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 84c35d4..e6d3d34 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -194,6 +194,7 @@
 extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p);
 extern uint32_t *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
+extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 37c1c76..96e31aa 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -6,7 +6,6 @@
 #endif
 #include <linux/swap.h>
 #include <linux/notifier.h>
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/pm.h>
 
diff --git a/include/linux/swap.h b/include/linux/swap.h
index f03c247..c41e2d6 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_SWAP_H
 #define _LINUX_SWAP_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/linkage.h>
 #include <linux/mmzone.h>
@@ -29,7 +28,14 @@
  * the type/offset into the pte as 5/27 as well.
  */
 #define MAX_SWAPFILES_SHIFT	5
+#ifndef CONFIG_MIGRATION
 #define MAX_SWAPFILES		(1 << MAX_SWAPFILES_SHIFT)
+#else
+/* Use last two entries for page migration swap entries */
+#define MAX_SWAPFILES		((1 << MAX_SWAPFILES_SHIFT)-2)
+#define SWP_MIGRATION_READ	MAX_SWAPFILES
+#define SWP_MIGRATION_WRITE	(MAX_SWAPFILES + 1)
+#endif
 
 /*
  * Magic header for a swap area. The first part of the union is
@@ -49,12 +55,14 @@
 		char magic[10];			/* SWAP-SPACE or SWAPSPACE2 */
 	} magic;
 	struct {
-		char	     bootbits[1024];	/* Space for disklabel etc. */
-		unsigned int version;
-		unsigned int last_page;
-		unsigned int nr_badpages;
-		unsigned int padding[125];
-		unsigned int badpages[1];
+		char		bootbits[1024];	/* Space for disklabel etc. */
+		__u32		version;
+		__u32		last_page;
+		__u32		nr_badpages;
+		unsigned char	sws_uuid[16];
+		unsigned char	sws_volume[16];
+		__u32		padding[117];
+		__u32		badpages[1];
 	} info;
 };
 
@@ -177,20 +185,7 @@
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
 extern int remove_mapping(struct address_space *mapping, struct page *page);
-
-/* possible outcome of pageout() */
-typedef enum {
-	/* failed to write page out, page is locked */
-	PAGE_KEEP,
-	/* move page to the active list, page is locked */
-	PAGE_ACTIVATE,
-	/* page has been sent to the disk successfully, page is unlocked */
-	PAGE_SUCCESS,
-	/* page is clean and locked */
-	PAGE_CLEAN,
-} pageout_t;
-
-extern pageout_t pageout(struct page *page, struct address_space *mapping);
+extern long vm_total_pages;
 
 #ifdef CONFIG_NUMA
 extern int zone_reclaim_mode;
@@ -204,6 +199,8 @@
 }
 #endif
 
+extern int kswapd_run(int nid);
+
 #ifdef CONFIG_MMU
 /* linux/mm/shmem.c */
 extern int shmem_unuse(swp_entry_t entry, struct page *page);
@@ -251,7 +248,6 @@
 struct backing_dev_info;
 
 extern spinlock_t swap_lock;
-extern int remove_vma_swap(struct vm_area_struct *vma, struct page *page);
 
 /* linux/mm/thrash.c */
 extern struct mm_struct * swap_token_mm;
@@ -289,18 +285,60 @@
 #define free_pages_and_swap_cache(pages, nr) \
 	release_pages((pages), (nr), 0);
 
-#define show_swap_cache_info()			/*NOTHING*/
-#define free_swap_and_cache(swp)		/*NOTHING*/
-#define swap_duplicate(swp)			/*NOTHING*/
-#define swap_free(swp)				/*NOTHING*/
-#define read_swap_cache_async(swp,vma,addr)	NULL
-#define lookup_swap_cache(swp)			NULL
-#define valid_swaphandles(swp, off)		0
+static inline void show_swap_cache_info(void)
+{
+}
+
+static inline void free_swap_and_cache(swp_entry_t swp)
+{
+}
+
+static inline int swap_duplicate(swp_entry_t swp)
+{
+	return 0;
+}
+
+static inline void swap_free(swp_entry_t swp)
+{
+}
+
+static inline struct page *read_swap_cache_async(swp_entry_t swp,
+			struct vm_area_struct *vma, unsigned long addr)
+{
+	return NULL;
+}
+
+static inline struct page *lookup_swap_cache(swp_entry_t swp)
+{
+	return NULL;
+}
+
+static inline int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
+{
+	return 0;
+}
+
 #define can_share_swap_page(p)			(page_mapcount(p) == 1)
-#define move_to_swap_cache(p, swp)		1
-#define move_from_swap_cache(p, i, m)		1
-#define __delete_from_swap_cache(p)		/*NOTHING*/
-#define delete_from_swap_cache(p)		/*NOTHING*/
+
+static inline int move_to_swap_cache(struct page *page, swp_entry_t entry)
+{
+	return 1;
+}
+
+static inline int move_from_swap_cache(struct page *page, unsigned long index,
+					struct address_space *mapping)
+{
+	return 1;
+}
+
+static inline void __delete_from_swap_cache(struct page *page)
+{
+}
+
+static inline void delete_from_swap_cache(struct page *page)
+{
+}
+
 #define swap_token_default_timeout		0
 
 static inline int remove_exclusive_swap_page(struct page *p)
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index 87b9d14..ec639aa 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -67,3 +67,56 @@
 	BUG_ON(pte_file(__swp_entry_to_pte(arch_entry)));
 	return __swp_entry_to_pte(arch_entry);
 }
+
+#ifdef CONFIG_MIGRATION
+static inline swp_entry_t make_migration_entry(struct page *page, int write)
+{
+	BUG_ON(!PageLocked(page));
+	return swp_entry(write ? SWP_MIGRATION_WRITE : SWP_MIGRATION_READ,
+			page_to_pfn(page));
+}
+
+static inline int is_migration_entry(swp_entry_t entry)
+{
+	return unlikely(swp_type(entry) == SWP_MIGRATION_READ ||
+			swp_type(entry) == SWP_MIGRATION_WRITE);
+}
+
+static inline int is_write_migration_entry(swp_entry_t entry)
+{
+	return unlikely(swp_type(entry) == SWP_MIGRATION_WRITE);
+}
+
+static inline struct page *migration_entry_to_page(swp_entry_t entry)
+{
+	struct page *p = pfn_to_page(swp_offset(entry));
+	/*
+	 * Any use of migration entries may only occur while the
+	 * corresponding page is locked
+	 */
+	BUG_ON(!PageLocked(p));
+	return p;
+}
+
+static inline void make_migration_entry_read(swp_entry_t *entry)
+{
+	*entry = swp_entry(SWP_MIGRATION_READ, swp_offset(*entry));
+}
+
+extern void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
+					unsigned long address);
+#else
+
+#define make_migration_entry(page, write) swp_entry(0, 0)
+#define is_migration_entry(swp) 0
+#define migration_entry_to_page(swp) NULL
+static inline void make_migration_entry_read(swp_entry_t *entryp) { }
+static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
+					 unsigned long address) { }
+static inline int is_write_migration_entry(swp_entry_t entry)
+{
+	return 0;
+}
+
+#endif
+
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index 2993302..0577f52 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -1,7 +1,7 @@
 /*
  * SyncLink Multiprotocol Serial Adapter Driver
  *
- * $Id: synclink.h,v 3.11 2006/02/06 21:20:29 paulkf Exp $
+ * $Id: synclink.h,v 3.13 2006/05/23 18:25:06 paulkf Exp $
  *
  * Copyright (C) 1998-2000 by Microgate Corporation
  *
@@ -97,6 +97,8 @@
 #define HDLC_TXIDLE_ALT_MARK_SPACE	4
 #define HDLC_TXIDLE_SPACE		5
 #define HDLC_TXIDLE_MARK		6
+#define HDLC_TXIDLE_CUSTOM_8            0x10000000
+#define HDLC_TXIDLE_CUSTOM_16           0x20000000
 
 #define HDLC_ENCODING_NRZ			0
 #define HDLC_ENCODING_NRZB			1
@@ -170,6 +172,7 @@
 #define SYNCLINK_GT_DEVICE_ID 0x0070
 #define SYNCLINK_GT4_DEVICE_ID 0x0080
 #define SYNCLINK_AC_DEVICE_ID  0x0090
+#define SYNCLINK_GT2_DEVICE_ID 0x00A0
 #define MGSL_MAX_SERIAL_NUMBER 30
 
 /*
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 60d49e5..008f04c 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -54,7 +54,6 @@
 struct compat_timeval;
 struct robust_list_head;
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/aio_abi.h>
 #include <linux/capability.h>
@@ -175,9 +174,9 @@
 			   int options, struct rusage __user *ru);
 asmlinkage long sys_waitpid(pid_t pid, int __user *stat_addr, int options);
 asmlinkage long sys_set_tid_address(int __user *tidptr);
-asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
+asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
 			struct timespec __user *utime, u32 __user *uaddr2,
-			int val3);
+			u32 val3);
 
 asmlinkage long sys_init_module(void __user *umod, unsigned long len,
 				const char __user *uargs);
@@ -517,6 +516,16 @@
 asmlinkage long sys_migrate_pages(pid_t pid, unsigned long maxnode,
 				const unsigned long __user *from,
 				const unsigned long __user *to);
+asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
+				const void __user * __user *pages,
+				const int __user *nodes,
+				int __user *status,
+				int flags);
+asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_page,
+				__u32 __user *pages,
+				const int __user *nodes,
+				int __user *status,
+				int flags);
 asmlinkage long sys_mbind(unsigned long start, unsigned long len,
 				unsigned long mode,
 				unsigned long __user *nmask,
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 76eaeff..46e4d8f 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -55,7 +55,7 @@
 	CTL_KERN=1,		/* General kernel info and control */
 	CTL_VM=2,		/* VM management */
 	CTL_NET=3,		/* Networking */
-	CTL_PROC=4,		/* Process info */
+	/* was CTL_PROC */
 	CTL_FS=5,		/* Filesystems */
 	CTL_DEBUG=6,		/* Debugging */
 	CTL_DEV=7,		/* Devices */
@@ -148,9 +148,12 @@
 	KERN_SPIN_RETRY=70,	/* int: number of spinlock retries */
 	KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */
 	KERN_IA64_UNALIGNED=72, /* int: ia64 unaligned userland trap enable */
+	KERN_COMPAT_LOG=73,	/* int: print compat layer  messages */
+	KERN_MAX_LOCK_DEPTH=74,
 };
 
 
+
 /* CTL_VM names: */
 enum
 {
@@ -186,6 +189,8 @@
 	VM_PERCPU_PAGELIST_FRACTION=30,/* int: fraction of pages in each percpu_pagelist */
 	VM_ZONE_RECLAIM_MODE=31, /* reclaim local zone memory before going off node */
 	VM_ZONE_RECLAIM_INTERVAL=32, /* time period to wait after reclaim failure */
+	VM_PANIC_ON_OOM=33,	/* panic at out-of-memory */
+	VM_VDSO_ENABLED=34,	/* map VDSO into new processes? */
 };
 
 
@@ -313,6 +318,7 @@
 	NET_NF_CONNTRACK_FRAG6_TIMEOUT=29,
 	NET_NF_CONNTRACK_FRAG6_LOW_THRESH=30,
 	NET_NF_CONNTRACK_FRAG6_HIGH_THRESH=31,
+	NET_NF_CONNTRACK_CHECKSUM=32,
 };
 
 /* /proc/sys/net/ipv4 */
@@ -403,6 +409,8 @@
  	NET_TCP_MTU_PROBING=113,
 	NET_TCP_BASE_MSS=114,
 	NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
+	NET_TCP_DMA_COPYBREAK=116,
+	NET_TCP_SLOW_START_AFTER_IDLE=117,
 };
 
 enum {
@@ -491,6 +499,7 @@
  	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_RECD=25,
  	NET_IPV4_NF_CONNTRACK_SCTP_TIMEOUT_SHUTDOWN_ACK_SENT=26,
 	NET_IPV4_NF_CONNTRACK_COUNT=27,
+	NET_IPV4_NF_CONNTRACK_CHECKSUM=28,
 };
  
 /* /proc/sys/net/ipv6 */
@@ -762,8 +771,6 @@
 	NET_BRIDGE_NF_FILTER_VLAN_TAGGED = 4,
 };
 
-/* CTL_PROC names: */
-
 /* CTL_FS names: */
 enum
 {
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index 2a4b432..166a2e5 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -37,11 +37,27 @@
 	struct kset		kset;
 };
 
+struct sysdev_class_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct sysdev_class *, char *);
+	ssize_t (*store)(struct sysdev_class *, const char *, size_t);
+};
+
+#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) 		\
+struct sysdev_class_attribute attr_##_name = { 			\
+	.attr = {.name = __stringify(_name), .mode = _mode },	\
+	.show	= _show,					\
+	.store	= _store,					\
+};
+
 
 extern int sysdev_class_register(struct sysdev_class *);
 extern void sysdev_class_unregister(struct sysdev_class *);
 
-
+extern int sysdev_class_create_file(struct sysdev_class *,
+	struct sysdev_class_attribute *);
+extern void sysdev_class_remove_file(struct sysdev_class *,
+	struct sysdev_class_attribute *);
 /**
  * Auxillary system device drivers.
  */
diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h
index ea819b8..4812ff6 100644
--- a/include/linux/sysrq.h
+++ b/include/linux/sysrq.h
@@ -11,7 +11,6 @@
  *	based upon discusions in irc://irc.openprojects.net/#kernelnewbies
  */
 
-#include <linux/config.h>
 
 struct pt_regs;
 struct tty_struct;
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 542d395..8ebf497 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -159,8 +159,8 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
+#include <linux/dmaengine.h>
 #include <net/sock.h>
 #include <net/inet_connection_sock.h>
 #include <net/inet_timewait_sock.h>
@@ -233,6 +233,13 @@
 		struct iovec		*iov;
 		int			memory;
 		int			len;
+#ifdef CONFIG_NET_DMA
+		/* members for async copy */
+		struct dma_chan		*dma_chan;
+		int			wakeup;
+		struct dma_pinned_list	*pinned_list;
+		dma_cookie_t		dma_cookie;
+#endif
 	} ucopy;
 
 	__u32	snd_wl1;	/* Sequence for window update		*/
diff --git a/include/linux/threads.h b/include/linux/threads.h
index e646bcd..38d1a5d 100644
--- a/include/linux/threads.h
+++ b/include/linux/threads.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_THREADS_H
 #define _LINUX_THREADS_H
 
-#include <linux/config.h>
 
 /*
  * The default limit for the nr of threads is now in
diff --git a/include/linux/time.h b/include/linux/time.h
index 0cd696c..c05f8bb 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -28,10 +28,13 @@
 #ifdef __KERNEL__
 
 /* Parameters used to convert the timespec values: */
-#define MSEC_PER_SEC		1000L
-#define USEC_PER_SEC		1000000L
-#define NSEC_PER_SEC		1000000000L
-#define NSEC_PER_USEC		1000L
+#define MSEC_PER_SEC	1000L
+#define USEC_PER_MSEC	1000L
+#define NSEC_PER_USEC	1000L
+#define NSEC_PER_MSEC	1000000L
+#define USEC_PER_SEC	1000000L
+#define NSEC_PER_SEC	1000000000L
+#define FSEC_PER_SEC	1000000000000000L
 
 static inline int timespec_equal(struct timespec *a, struct timespec *b)
 {
@@ -77,6 +80,8 @@
 extern struct timespec wall_to_monotonic;
 extern seqlock_t xtime_lock;
 
+void timekeeping_init(void);
+
 static inline unsigned long get_seconds(void)
 {
 	return xtime.tv_sec;
@@ -100,6 +105,7 @@
 extern void getnstimeofday(struct timespec *tv);
 
 extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
+extern int timekeeping_is_continuous(void);
 
 /**
  * timespec_to_ns - Convert timespec to nanoseconds
@@ -142,6 +148,20 @@
  */
 extern struct timeval ns_to_timeval(const s64 nsec);
 
+/**
+ * timespec_add_ns - Adds nanoseconds to a timespec
+ * @a:		pointer to timespec to be incremented
+ * @ns:		unsigned nanoseconds value to be added
+ */
+static inline void timespec_add_ns(struct timespec *a, u64 ns)
+{
+	ns += a->tv_nsec;
+	while(unlikely(ns >= NSEC_PER_SEC)) {
+		ns -= NSEC_PER_SEC;
+		a->tv_sec++;
+	}
+	a->tv_nsec = ns;
+}
 #endif /* __KERNEL__ */
 
 #define NFDBITS			__NFDBITS
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 0a485be..c982304 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -1,7 +1,6 @@
 #ifndef _LINUX_TIMER_H
 #define _LINUX_TIMER_H
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
diff --git a/include/linux/timex.h b/include/linux/timex.h
index 03914b7..19bb653 100644
--- a/include/linux/timex.h
+++ b/include/linux/timex.h
@@ -53,7 +53,6 @@
 #ifndef _LINUX_TIMEX_H
 #define _LINUX_TIMEX_H
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/time.h>
 
@@ -304,6 +303,8 @@
 
 #endif /* !CONFIG_TIME_INTERPOLATION */
 
+#define TICK_LENGTH_SHIFT	32
+
 /* Returns how long ticks are at present, in ns / 2^(SHIFT_SCALE-10). */
 extern u64 current_tick_length(void);
 
diff --git a/include/linux/topology.h b/include/linux/topology.h
index a305ae2..ec1eca8 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -134,7 +134,8 @@
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_NEWIDLE	\
 				| SD_BALANCE_EXEC	\
-				| SD_WAKE_AFFINE,	\
+				| SD_WAKE_AFFINE	\
+				| BALANCE_FOR_POWER,	\
 	.last_balance		= jiffies,		\
 	.balance_interval	= 1,			\
 	.nr_balance_failed	= 0,			\
diff --git a/include/linux/tty.h b/include/linux/tty.h
index f13f49a..b3b807e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -16,7 +16,6 @@
 		   consoles 16 and higher (since it returns a short) */
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/termios.h>
@@ -58,7 +57,6 @@
 	unsigned char *flag_buf_ptr;
 	int used;
 	int size;
-	int active;
 	int commit;
 	int read;
 	/* Data points here */
@@ -260,7 +258,6 @@
 #define TTY_DO_WRITE_WAKEUP 	5	/* Call write_wakeup after queuing new */
 #define TTY_PUSH 		6	/* n_tty private */
 #define TTY_CLOSING 		7	/* ->close() in progress */
-#define TTY_DONT_FLIP 		8	/* Defer buffer flip */
 #define TTY_LDISC 		9	/* Line discipline attached */
 #define TTY_HW_COOK_OUT 	14	/* Hardware can do output cooking */
 #define TTY_HW_COOK_IN 		15	/* Hardware can do input cooking */
@@ -291,7 +288,9 @@
 extern int tty_unregister_ldisc(int disc);
 extern int tty_register_driver(struct tty_driver *driver);
 extern int tty_unregister_driver(struct tty_driver *driver);
-extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev);
+extern struct class_device *tty_register_device(struct tty_driver *driver,
+						unsigned index,
+						struct device *dev);
 extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
 extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
 			     int buflen);
diff --git a/include/linux/tty_flip.h b/include/linux/tty_flip.h
index 3154830..eb677cf5 100644
--- a/include/linux/tty_flip.h
+++ b/include/linux/tty_flip.h
@@ -12,7 +12,7 @@
 					unsigned char ch, char flag)
 {
 	struct tty_buffer *tb = tty->buf.tail;
-	if (tb && tb->active && tb->used < tb->size) {
+	if (tb && tb->used < tb->size) {
 		tb->flag_buf_ptr[tb->used] = flag;
 		tb->char_buf_ptr[tb->used++] = ch;
 		return 1;
diff --git a/include/linux/types.h b/include/linux/types.h
index 1046c7a..a5e46e7 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -2,7 +2,6 @@
 #define _LINUX_TYPES_H
 
 #ifdef	__KERNEL__
-#include <linux/config.h>
 
 #define BITS_TO_LONGS(bits) \
 	(((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
new file mode 100644
index 0000000..391e7ed
--- /dev/null
+++ b/include/linux/uaccess.h
@@ -0,0 +1,22 @@
+#ifndef __LINUX_UACCESS_H__
+#define __LINUX_UACCESS_H__
+
+#include <asm/uaccess.h>
+
+#ifndef ARCH_HAS_NOCACHE_UACCESS
+
+static inline unsigned long __copy_from_user_inatomic_nocache(void *to,
+				const void __user *from, unsigned long n)
+{
+	return __copy_from_user_inatomic(to, from, n);
+}
+
+static inline unsigned long __copy_from_user_nocache(void *to,
+				const void __user *from, unsigned long n)
+{
+	return __copy_from_user(to, from, n);
+}
+
+#endif		/* ARCH_HAS_NOCACHE_UACCESS */
+
+#endif		/* __LINUX_UACCESS_H__ */
diff --git a/include/linux/udp.h b/include/linux/udp.h
index 85a5565..bdd39be 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -35,7 +35,6 @@
 #define UDP_ENCAP_ESPINUDP	2 /* draft-ietf-ipsec-udp-encaps-06 */
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <net/inet_sock.h>
diff --git a/include/linux/ufs_fs.h b/include/linux/ufs_fs.h
index 843aeaa..e39b7cc 100644
--- a/include/linux/ufs_fs.h
+++ b/include/linux/ufs_fs.h
@@ -32,7 +32,6 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/time.h>
 #include <linux/stat.h>
 #include <linux/fs.h>
 
@@ -221,6 +220,19 @@
  */
 #define UFS_MINFREE         5
 #define UFS_DEFAULTOPT      UFS_OPTTIME
+
+/*
+ * Debug code
+ */
+#ifdef CONFIG_UFS_DEBUG
+#	define UFSD(f, a...)	{					\
+		printk ("UFSD (%s, %d): %s:",				\
+			__FILE__, __LINE__, __FUNCTION__);		\
+		printk (f, ## a);					\
+	}
+#else
+#	define UFSD(f, a...)	/**/
+#endif
             
 /*
  * Turn file system block numbers into disk block addresses.
@@ -340,7 +352,22 @@
 };
 
 /*
+ * File system flags
+ */
+#define UFS_UNCLEAN      0x01    /* file system not clean at mount (unused) */
+#define UFS_DOSOFTDEP    0x02    /* file system using soft dependencies */
+#define UFS_NEEDSFSCK    0x04    /* needs sync fsck (FreeBSD compat, unused) */
+#define UFS_INDEXDIRS    0x08    /* kernel supports indexed directories */
+#define UFS_ACLS         0x10    /* file system has ACLs enabled */
+#define UFS_MULTILABEL   0x20    /* file system is MAC multi-label */
+#define UFS_FLAGS_UPDATED 0x80   /* flags have been moved to new location */
+
+#if 0
+/*
  * This is the actual superblock, as it is laid out on the disk.
+ * Do NOT use this structure, because of sizeof(ufs_super_block) > 512 and
+ * it may occupy several blocks, use
+ * struct ufs_super_block_(first,second,third) instead.
  */
 struct ufs_super_block {
 	__fs32	fs_link;	/* UNUSED */
@@ -417,7 +444,7 @@
 	__s8	fs_fmod;	/* super block modified flag */
 	__s8	fs_clean;	/* file system is clean flag */
 	__s8	fs_ronly;	/* mounted read-only flag */
-	__s8	fs_flags;	/* currently unused flag */
+	__s8	fs_flags;
 	union {
 		struct {
 			__s8	fs_fsmnt[UFS_MAXMNTLEN];/* name mounted on */
@@ -486,6 +513,7 @@
 	__fs32	fs_magic;		/* magic number */
 	__u8	fs_space[1];		/* list of blocks for each rotation */
 };
+#endif/*struct ufs_super_block*/
 
 /*
  * Preference for optimization.
@@ -667,7 +695,7 @@
 };
 
 struct ufs_cg_private_info {
-	struct ufs_cylinder_group ucg;
+	struct ufs_buffer_head c_ubh;
 	__u32	c_cgx;		/* number of cylidner group */
 	__u16	c_ncyl;		/* number of cyl's this cg */
 	__u16	c_niblk;	/* number of inode blocks this cg */
@@ -687,6 +715,7 @@
 
 struct ufs_sb_private_info {
 	struct ufs_buffer_head s_ubh; /* buffer containing super block */
+	struct ufs2_csum_total cs_total;
 	__u32	s_sblkno;	/* offset of super-blocks in filesys */
 	__u32	s_cblkno;	/* offset of cg-block in filesys */
 	__u32	s_iblkno;	/* offset of inode-blocks in filesys */
@@ -825,16 +854,54 @@
 };
 
 struct ufs_super_block_second {
-	__s8	fs_fsmnt[212];
-	__fs32	fs_cgrotor;
-	__fs32	fs_csp[UFS_MAXCSBUFS];
-	__fs32	fs_maxcluster;
-	__fs32	fs_cpc;
-	__fs16	fs_opostbl[82];
-};	
+	union {
+		struct {
+			__s8	fs_fsmnt[212];
+			__fs32	fs_cgrotor;
+			__fs32	fs_csp[UFS_MAXCSBUFS];
+			__fs32	fs_maxcluster;
+			__fs32	fs_cpc;
+			__fs16	fs_opostbl[82];
+		} fs_u1;
+		struct {
+			__s8  fs_fsmnt[UFS2_MAXMNTLEN - UFS_MAXMNTLEN + 212];
+			__u8   fs_volname[UFS2_MAXVOLLEN];
+			__fs64  fs_swuid;
+			__fs32  fs_pad;
+			__fs32   fs_cgrotor;
+			__fs32   fs_ocsp[UFS2_NOCSPTRS];
+			__fs32   fs_contigdirs;
+			__fs32   fs_csp;
+			__fs32   fs_maxcluster;
+			__fs32   fs_active;
+			__fs32   fs_old_cpc;
+			__fs32   fs_maxbsize;
+			__fs64   fs_sparecon64[17];
+			__fs64   fs_sblockloc;
+			__fs64	cs_ndir;
+			__fs64	cs_nbfree;
+		} fs_u2;
+	} fs_un;
+};
 
 struct ufs_super_block_third {
-	__fs16	fs_opostbl[46];
+	union {
+		struct {
+			__fs16	fs_opostbl[46];
+		} fs_u1;
+		struct {
+			__fs64	cs_nifree;	/* number of free inodes */
+			__fs64	cs_nffree;	/* number of free frags */
+			__fs64   cs_numclusters;	/* number of free clusters */
+			__fs64   cs_spare[3];	/* future expansion */
+			struct  ufs_timeval    fs_time;		/* last time written */
+			__fs64    fs_size;		/* number of blocks in fs */
+			__fs64    fs_dsize;	/* number of data blocks in fs */
+			__fs64   fs_csaddr;	/* blk addr of cyl grp summary area */
+			__fs64    fs_pendingblocks;/* blocks in process of being freed */
+			__fs32    fs_pendinginodes;/*inodes in process of being freed */
+		} fs_u2;
+	} fs_un1;
 	union {
 		struct {
 			__fs32	fs_sparecon[53];/* reserved for future constants */
@@ -862,7 +929,7 @@
 			__fs32	fs_qfmask[2];	/* ~usb_fmask */
 			__fs32	fs_state;	/* file system state time stamp */
 		} fs_44;
-	} fs_u2;
+	} fs_un2;
 	__fs32	fs_postblformat;
 	__fs32	fs_nrpos;
 	__fs32	fs_postbloff;
@@ -876,7 +943,8 @@
 /* balloc.c */
 extern void ufs_free_fragments (struct inode *, unsigned, unsigned);
 extern void ufs_free_blocks (struct inode *, unsigned, unsigned);
-extern unsigned ufs_new_fragments (struct inode *, __fs32 *, unsigned, unsigned, unsigned, int *);
+extern unsigned ufs_new_fragments(struct inode *, __fs32 *, unsigned, unsigned,
+				  unsigned, int *, struct page *);
 
 /* cylinder.c */
 extern struct ufs_cg_private_info * ufs_load_cylinder (struct super_block *, unsigned);
@@ -887,30 +955,29 @@
 extern int ufs_add_link (struct dentry *, struct inode *);
 extern ino_t ufs_inode_by_name(struct inode *, struct dentry *);
 extern int ufs_make_empty(struct inode *, struct inode *);
-extern struct ufs_dir_entry * ufs_find_entry (struct dentry *, struct buffer_head **);
-extern int ufs_delete_entry (struct inode *, struct ufs_dir_entry *, struct buffer_head *);
+extern struct ufs_dir_entry *ufs_find_entry(struct inode *, struct dentry *, struct page **);
+extern int ufs_delete_entry(struct inode *, struct ufs_dir_entry *, struct page *);
 extern int ufs_empty_dir (struct inode *);
-extern struct ufs_dir_entry * ufs_dotdot (struct inode *, struct buffer_head **);
-extern void ufs_set_link(struct inode *, struct ufs_dir_entry *, struct buffer_head *, struct inode *);
+extern struct ufs_dir_entry *ufs_dotdot(struct inode *, struct page **);
+extern void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
+			 struct page *page, struct inode *inode);
 
 /* file.c */
 extern struct inode_operations ufs_file_inode_operations;
 extern const struct file_operations ufs_file_operations;
 
-extern struct address_space_operations ufs_aops;
+extern const struct address_space_operations ufs_aops;
 
 /* ialloc.c */
 extern void ufs_free_inode (struct inode *inode);
 extern struct inode * ufs_new_inode (struct inode *, int);
 
 /* inode.c */
-extern u64  ufs_frag_map (struct inode *, sector_t);
 extern void ufs_read_inode (struct inode *);
 extern void ufs_put_inode (struct inode *);
 extern int ufs_write_inode (struct inode *, int);
 extern int ufs_sync_inode (struct inode *);
 extern void ufs_delete_inode (struct inode *);
-extern struct buffer_head * ufs_getfrag (struct inode *, unsigned, int, int *);
 extern struct buffer_head * ufs_bread (struct inode *, unsigned, int, int *);
 extern int ufs_getfrag_block (struct inode *inode, sector_t fragment, struct buffer_head *bh_result, int create);
 
diff --git a/include/linux/ufs_fs_i.h b/include/linux/ufs_fs_i.h
index 21665a9..f50ce3b 100644
--- a/include/linux/ufs_fs_i.h
+++ b/include/linux/ufs_fs_i.h
@@ -27,6 +27,7 @@
 	__u32	i_oeftflag;
 	__u16	i_osync;
 	__u32	i_lastfrag;
+	__u32   i_dir_start_lookup;
 	struct inode vfs_inode;
 };
 
diff --git a/include/linux/unistd.h b/include/linux/unistd.h
index 10ed983..c18c60f 100644
--- a/include/linux/unistd.h
+++ b/include/linux/unistd.h
@@ -1,7 +1,9 @@
 #ifndef _LINUX_UNISTD_H_
 #define _LINUX_UNISTD_H_
 
+#ifdef __KERNEL__
 extern int errno;
+#endif
 
 /*
  * Include machine specific syscallX macros
diff --git a/include/linux/unwind.h b/include/linux/unwind.h
new file mode 100644
index 0000000..ce48e2c
--- /dev/null
+++ b/include/linux/unwind.h
@@ -0,0 +1,127 @@
+#ifndef _LINUX_UNWIND_H
+#define _LINUX_UNWIND_H
+
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *	Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ *
+ * A simple API for unwinding kernel stacks.  This is used for
+ * debugging and error reporting purposes.  The kernel doesn't need
+ * full-blown stack unwinding with all the bells and whistles, so there
+ * is not much point in implementing the full Dwarf2 unwind API.
+ */
+
+#include <linux/config.h>
+
+struct module;
+
+#ifdef CONFIG_STACK_UNWIND
+
+#include <asm/unwind.h>
+
+#ifndef ARCH_UNWIND_SECTION_NAME
+#define ARCH_UNWIND_SECTION_NAME ".eh_frame"
+#endif
+
+/*
+ * Initialize unwind support.
+ */
+extern void unwind_init(void);
+
+#ifdef CONFIG_MODULES
+
+extern void *unwind_add_table(struct module *,
+                              const void *table_start,
+                              unsigned long table_size);
+
+extern void unwind_remove_table(void *handle, int init_only);
+
+#endif
+
+extern int unwind_init_frame_info(struct unwind_frame_info *,
+                                  struct task_struct *,
+                                  /*const*/ struct pt_regs *);
+
+/*
+ * Prepare to unwind a blocked task.
+ */
+extern int unwind_init_blocked(struct unwind_frame_info *,
+                               struct task_struct *);
+
+/*
+ * Prepare to unwind the currently running thread.
+ */
+extern int unwind_init_running(struct unwind_frame_info *,
+                               asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                          void *arg),
+                               void *arg);
+
+/*
+ * Unwind to previous to frame.  Returns 0 if successful, negative
+ * number in case of an error.
+ */
+extern int unwind(struct unwind_frame_info *);
+
+/*
+ * Unwind until the return pointer is in user-land (or until an error
+ * occurs).  Returns 0 if successful, negative number in case of
+ * error.
+ */
+extern int unwind_to_user(struct unwind_frame_info *);
+
+#else
+
+struct unwind_frame_info {};
+
+static inline void unwind_init(void) {}
+
+#ifdef CONFIG_MODULES
+
+static inline void *unwind_add_table(struct module *mod,
+                                     const void *table_start,
+                                     unsigned long table_size)
+{
+	return NULL;
+}
+
+#endif
+
+static inline void unwind_remove_table(void *handle, int init_only)
+{
+}
+
+static inline int unwind_init_frame_info(struct unwind_frame_info *info,
+                                         struct task_struct *tsk,
+                                         const struct pt_regs *regs)
+{
+	return -ENOSYS;
+}
+
+static inline int unwind_init_blocked(struct unwind_frame_info *info,
+                                      struct task_struct *tsk)
+{
+	return -ENOSYS;
+}
+
+static inline int unwind_init_running(struct unwind_frame_info *info,
+                                      asmlinkage int (*cb)(struct unwind_frame_info *,
+                                                           void *arg),
+                                      void *arg)
+{
+	return -ENOSYS;
+}
+
+static inline int unwind(struct unwind_frame_info *info)
+{
+	return -ENOSYS;
+}
+
+static inline int unwind_to_user(struct unwind_frame_info *info)
+{
+	return -ENOSYS;
+}
+
+#endif
+
+#endif /* _LINUX_UNWIND_H */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index e34e5e3..8dead32 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -10,7 +10,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/errno.h>        /* for -ENODEV */
 #include <linux/delay.h>	/* for mdelay() */
 #include <linux/interrupt.h>	/* for in_interrupt() */
@@ -41,6 +40,8 @@
  * Devices may also have class-specific or vendor-specific descriptors.
  */
 
+struct ep_device;
+
 /**
  * struct usb_host_endpoint - host-side endpoint descriptor and queue
  * @desc: descriptor for this endpoint, wMaxPacketSize in native byteorder
@@ -58,7 +59,7 @@
 	struct usb_endpoint_descriptor	desc;
 	struct list_head		urb_list;
 	void				*hcpriv;
-	struct kobject			*kobj;	/* For sysfs info */
+	struct ep_device 		*ep_dev;	/* For sysfs info */
 
 	unsigned char *extra;   /* Extra descriptors */
 	int extralen;
@@ -102,7 +103,8 @@
  * @condition: binding state of the interface: not bound, binding
  *	(in probe()), bound to a driver, or unbinding (in disconnect())
  * @dev: driver model's view of this device
- * @class_dev: driver model's class view of this device.
+ * @usb_dev: if an interface is bound to the USB major, this will point
+ *	to the sysfs representation for that device.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -142,7 +144,7 @@
 					 * bound to */
 	enum usb_interface_condition condition;		/* state of binding */
 	struct device dev;		/* interface specific device info */
-	struct class_device *class_dev;
+	struct device *usb_dev;		/* pointer to the usb class's device, if any */
 };
 #define	to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define	interface_to_usbdev(intf) \
@@ -359,7 +361,7 @@
 	char *serial;			/* iSerialNumber string, if present */
 
 	struct list_head filelist;
-	struct class_device *class_dev;
+	struct device *usbfs_dev;
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the device */
 
 	/*
@@ -387,6 +389,8 @@
 
 /* USB port reset for device reinitialization */
 extern int usb_reset_device(struct usb_device *dev);
+extern int usb_reset_composite_device(struct usb_device *dev,
+		struct usb_interface *iface);
 
 extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
 
@@ -555,6 +559,10 @@
  *	do (or don't) show up otherwise in the filesystem.
  * @suspend: Called when the device is going to be suspended by the system.
  * @resume: Called when the device is being resumed by the system.
+ * @pre_reset: Called by usb_reset_composite_device() when the device
+ *	is about to be reset.
+ * @post_reset: Called by usb_reset_composite_device() after the device
+ *	has been reset.
  * @id_table: USB drivers use ID table to support hotplugging.
  *	Export this with MODULE_DEVICE_TABLE(usb,...).  This must be set
  *	or your driver's probe function will never get called.
@@ -593,6 +601,9 @@
 	int (*suspend) (struct usb_interface *intf, pm_message_t message);
 	int (*resume) (struct usb_interface *intf);
 
+	void (*pre_reset) (struct usb_interface *intf);
+	void (*post_reset) (struct usb_interface *intf);
+
 	const struct usb_device_id *id_table;
 
 	struct usb_dynids dynids;
@@ -1009,6 +1020,8 @@
 extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
 	__u8 request, __u8 requesttype, __u16 value, __u16 index,
 	void *data, __u16 size, int timeout);
+extern int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
+	void *data, int len, int *actual_length, int timeout);
 extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
 	void *data, int len, int *actual_length,
 	int timeout);
diff --git a/include/linux/usb_cdc.h b/include/linux/usb/cdc.h
similarity index 100%
rename from include/linux/usb_cdc.h
rename to include/linux/usb/cdc.h
diff --git a/include/linux/usb_input.h b/include/linux/usb/input.h
similarity index 100%
rename from include/linux/usb_input.h
rename to include/linux/usb/input.h
diff --git a/include/linux/usb_isp116x.h b/include/linux/usb/isp116x.h
similarity index 100%
rename from include/linux/usb_isp116x.h
rename to include/linux/usb/isp116x.h
diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h
new file mode 100644
index 0000000..397ee3b
--- /dev/null
+++ b/include/linux/usb/sl811.h
@@ -0,0 +1,26 @@
+
+/*
+ * board initialization should put one of these into dev->platform_data
+ * and place the sl811hs onto platform_bus named "sl811-hcd".
+ */
+
+struct sl811_platform_data {
+	unsigned	can_wakeup:1;
+
+	/* given port_power, msec/2 after power on till power good */
+	u8		potpg;
+
+	/* mA/2 power supplied on this port (max = default = 250) */
+	u8		power;
+
+	/* sl811 relies on an external source of VBUS current */
+	void		(*port_power)(struct device *dev, int is_on);
+
+	/* pulse sl811 nRST (probably with a GPIO) */
+	void		(*reset)(struct device *dev);
+
+	// some boards need something like these:
+	// int		(*check_overcurrent)(struct device *dev);
+	// void		(*clock_enable)(struct device *dev, int is_on);
+};
+
diff --git a/include/linux/usb_sl811.h b/include/linux/usb_sl811.h
deleted file mode 100644
index 4f2d012..0000000
--- a/include/linux/usb_sl811.h
+++ /dev/null
@@ -1,26 +0,0 @@
-
-/*
- * board initialization should put one of these into dev->platform_data
- * and place the sl811hs onto platform_bus named "sl811-hcd".
- */
-
-struct sl811_platform_data {
-	unsigned	can_wakeup:1;
-
-	/* given port_power, msec/2 after power on till power good */
-	u8		potpg;
-
-	/* mA/2 power supplied on this port (max = default = 250) */
-	u8		power;
-
-	/* sl811 relies on an external source of VBUS current */
-	void 		(*port_power)(struct device *dev, int is_on);
-
-	/* pulse sl811 nRST (probably with a GPIO) */
-	void 		(*reset)(struct device *dev);
-
-	// some boards need something like these:
- 	// int 		(*check_overcurrent)(struct device *dev);
- 	// void 	(*clock_enable)(struct device *dev, int is_on);
-};
-
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
index b2d08984..608487a 100644
--- a/include/linux/usb_usual.h
+++ b/include/linux/usb_usual.h
@@ -9,7 +9,6 @@
 #ifndef __LINUX_USB_USUAL_H
 #define __LINUX_USB_USUAL_H
 
-#include <linux/config.h>
 
 /* We should do this for cleanliness... But other usb_foo.h do not do this. */
 /* #include <linux/usb.h> */
diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
index 8859f0b..7b7aadb 100644
--- a/include/linux/usbdevice_fs.h
+++ b/include/linux/usbdevice_fs.h
@@ -123,6 +123,7 @@
 	char port [127];	/* e.g. port 3 connects to device 27 */
 };
 
+#ifdef __KERNEL__
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
 struct usbdevfs_urb32 {
@@ -147,6 +148,7 @@
 	compat_caddr_t data;
 };
 #endif
+#endif /* __KERNEL__ */
 
 #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
 #define USBDEVFS_BULK              _IOWR('U', 2, struct usbdevfs_bulktransfer)
diff --git a/include/linux/videodev.h b/include/linux/videodev.h
index 9114009..41bc7e9 100644
--- a/include/linux/videodev.h
+++ b/include/linux/videodev.h
@@ -1,49 +1,21 @@
+/*
+ *	Video for Linux version 1 - OBSOLETE
+ *
+ *	Header file for v4l1 drivers and applications, for
+ *	Linux kernels 2.2.x or 2.4.x.
+ *
+ *	Provides header for legacy drivers and applications
+ *
+ *	See http://linuxtv.org for more info
+ *
+ */
 #ifndef __LINUX_VIDEODEV_H
 #define __LINUX_VIDEODEV_H
 
-#include <linux/types.h>
-
 #define HAVE_V4L1 1
 
 #include <linux/videodev2.h>
 
-#ifdef __KERNEL__
-
-#include <linux/mm.h>
-
-extern struct video_device* video_devdata(struct file*);
-
-#define to_video_device(cd) container_of(cd, struct video_device, class_dev)
-static inline void
-video_device_create_file(struct video_device *vfd,
-			 struct class_device_attribute *attr)
-{
-	class_device_create_file(&vfd->class_dev, attr);
-}
-static inline void
-video_device_remove_file(struct video_device *vfd,
-			 struct class_device_attribute *attr)
-{
-	class_device_remove_file(&vfd->class_dev, attr);
-}
-
-#if OBSOLETE_OWNER /* to be removed in 2.6.15 */
-/* helper functions to access driver private data. */
-static inline void *video_get_drvdata(struct video_device *dev)
-{
-	return dev->priv;
-}
-
-static inline void video_set_drvdata(struct video_device *dev, void *data)
-{
-	dev->priv = data;
-}
-#endif
-
-extern int video_exclusive_open(struct inode *inode, struct file *file);
-extern int video_exclusive_release(struct inode *inode, struct file *file);
-#endif /* __KERNEL__ */
-
 struct video_capability
 {
 	char name[32];
@@ -363,6 +335,7 @@
 #define VID_HARDWARE_SAA7114H   37
 #define VID_HARDWARE_SN9C102	38
 #define VID_HARDWARE_ARV	39
+
 #endif /* __LINUX_VIDEODEV_H */
 
 /*
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index ad7fa9c..a62673d 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1,35 +1,33 @@
-#ifndef __LINUX_VIDEODEV2_H
-#define __LINUX_VIDEODEV2_H
 /*
  *	Video for Linux Two
  *
- *	Header file for v4l or V4L2 drivers and applications, for
- *	Linux kernels 2.2.x or 2.4.x.
+ *	Header file for v4l or V4L2 drivers and applications
+ * with public API.
+ * All kernel-specific stuff were moved to media/v4l2-dev.h, so
+ * no #if __KERNEL tests are allowed here
  *
- *	See http://bytesex.org/v4l/ for API specs and other
- *	v4l2 documentation.
+ *	See http://linuxtv.org for more info
  *
  *	Author: Bill Dirks <bdirks@pacbell.net>
  *		Justin Schoeman
  *		et al.
  */
+#ifndef __LINUX_VIDEODEV2_H
+#define __LINUX_VIDEODEV2_H
 #ifdef __KERNEL__
-#include <linux/time.h> /* need struct timeval */
-#include <linux/poll.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#endif
+#include <linux/time.h>     /* need struct timeval */
 #include <linux/compiler.h> /* need __user */
+#else
+#define __user
+#endif
+#include <linux/types.h>
 
-
-#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.17 */
 #define HAVE_V4L2 1
 
 /*
  * Common stuff for both V4L1 and V4L2
  * Moved from videodev.h
  */
-
 #define VIDEO_MAX_FRAME               32
 
 #define VID_TYPE_CAPTURE	1	/* Can capture */
@@ -47,71 +45,6 @@
 #define VID_TYPE_MJPEG_DECODER	4096	/* Can decode MJPEG streams */
 #define VID_TYPE_MJPEG_ENCODER	8192	/* Can encode MJPEG streams */
 
-#ifdef __KERNEL__
-
-/* Minor device allocation */
-#define MINOR_VFL_TYPE_GRABBER_MIN   0
-#define MINOR_VFL_TYPE_GRABBER_MAX  63
-#define MINOR_VFL_TYPE_RADIO_MIN    64
-#define MINOR_VFL_TYPE_RADIO_MAX   127
-#define MINOR_VFL_TYPE_VTX_MIN     192
-#define MINOR_VFL_TYPE_VTX_MAX     223
-#define MINOR_VFL_TYPE_VBI_MIN     224
-#define MINOR_VFL_TYPE_VBI_MAX     255
-
-#define VFL_TYPE_GRABBER	0
-#define VFL_TYPE_VBI		1
-#define VFL_TYPE_RADIO		2
-#define VFL_TYPE_VTX		3
-
-struct video_device
-{
-	/* device info */
-	struct device *dev;
-	char name[32];
-	int type;       /* v4l1 */
-	int type2;      /* v4l2 */
-	int hardware;
-	int minor;
-
-	/* device ops + callbacks */
-	const struct file_operations *fops;
-	void (*release)(struct video_device *vfd);
-
-
-#if OBSOLETE_OWNER /* to be removed in 2.6.15 */
-	/* obsolete -- fops->owner is used instead */
-	struct module *owner;
-	/* dev->driver_data will be used instead some day.
-	 * Use the video_{get|set}_drvdata() helper functions,
-	 * so the switch over will be transparent for you.
-	 * Or use {pci|usb}_{get|set}_drvdata() directly. */
-	void *priv;
-#endif
-
-	/* for videodev.c intenal usage -- please don't touch */
-	int users;                     /* video_exclusive_{open|close} ... */
-	struct mutex lock;             /* ... helper function uses these   */
-	char devfs_name[64];           /* devfs */
-	struct class_device class_dev; /* sysfs */
-};
-
-#define VIDEO_MAJOR	81
-
-extern int video_register_device(struct video_device *, int type, int nr);
-extern void video_unregister_device(struct video_device *);
-extern int video_usercopy(struct inode *inode, struct file *file,
-			  unsigned int cmd, unsigned long arg,
-			  int (*func)(struct inode *inode, struct file *file,
-				      unsigned int cmd, void *arg));
-
-/* helper functions to alloc / release struct video_device, the
-   later can be used for video_device->release() */
-struct video_device *video_device_alloc(void);
-void video_device_release(struct video_device *vfd);
-
-#endif
-
 /*
  *	M I S C E L L A N E O U S
  */
@@ -172,6 +105,8 @@
 	V4L2_CTRL_TYPE_BOOLEAN	     = 2,
 	V4L2_CTRL_TYPE_MENU	     = 3,
 	V4L2_CTRL_TYPE_BUTTON	     = 4,
+	V4L2_CTRL_TYPE_INTEGER64     = 5,
+	V4L2_CTRL_TYPE_CTRL_CLASS    = 6,
 };
 
 enum v4l2_tuner_type {
@@ -270,7 +205,6 @@
 /*
  *	V I D E O   I M A G E   F O R M A T
  */
-
 struct v4l2_pix_format
 {
 	__u32         		width;
@@ -283,7 +217,7 @@
 	__u32			priv;		/* private data, depends on pixelformat */
 };
 
-/*           Pixel format    FOURCC                  depth  Description   */
+/*      Pixel format         FOURCC                        depth  Description  */
 #define V4L2_PIX_FMT_RGB332  v4l2_fourcc('R','G','B','1') /*  8  RGB-3-3-2     */
 #define V4L2_PIX_FMT_RGB555  v4l2_fourcc('R','G','B','O') /* 16  RGB-5-5-5     */
 #define V4L2_PIX_FMT_RGB565  v4l2_fourcc('R','G','B','P') /* 16  RGB-5-6-5     */
@@ -311,6 +245,7 @@
 #define V4L2_PIX_FMT_YUV420  v4l2_fourcc('Y','U','1','2') /* 12  YUV 4:2:0     */
 #define V4L2_PIX_FMT_YYUV    v4l2_fourcc('Y','Y','U','V') /* 16  YUV 4:2:2     */
 #define V4L2_PIX_FMT_HI240   v4l2_fourcc('H','I','2','4') /*  8  8-bit color   */
+#define V4L2_PIX_FMT_HM12    v4l2_fourcc('H','M','1','2') /*  8  YUV 4:1:1 16x16 macroblocks */
 
 /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B','A','8','1') /*  8  BGBG.. GRGR.. */
@@ -319,7 +254,7 @@
 #define V4L2_PIX_FMT_MJPEG    v4l2_fourcc('M','J','P','G') /* Motion-JPEG   */
 #define V4L2_PIX_FMT_JPEG     v4l2_fourcc('J','P','E','G') /* JFIF JPEG     */
 #define V4L2_PIX_FMT_DV       v4l2_fourcc('d','v','s','d') /* 1394          */
-#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M','P','E','G') /* MPEG          */
+#define V4L2_PIX_FMT_MPEG     v4l2_fourcc('M','P','E','G') /* MPEG-1/2/4    */
 
 /*  Vendor-specific formats   */
 #define V4L2_PIX_FMT_WNVA     v4l2_fourcc('W','N','V','A') /* Winnov hw compress */
@@ -343,7 +278,6 @@
 
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 
-
 /*
  *	T I M E C O D E
  */
@@ -373,16 +307,15 @@
 #define V4L2_TC_USERBITS_8BITCHARS	0x0008
 /* The above is based on SMPTE timecodes */
 
-
+#ifdef __KERNEL__
 /*
  *	M P E G   C O M P R E S S I O N   P A R A M E T E R S
  *
- *  ### WARNING: this is still work-in-progress right now, most likely
- *  ###          there will be some incompatible changes.
+ *  ### WARNING: This experimental MPEG compression API is obsolete.
+ *  ###          It is replaced by the MPEG controls API.
+ *  ###          This old API will disappear in the near future!
  *
  */
-
-
 enum v4l2_bitrate_mode {
 	V4L2_BITRATE_NONE = 0,	/* not specified */
 	V4L2_BITRATE_CBR,	/* constant bitrate */
@@ -460,6 +393,7 @@
 	/* I don't expect the above being perfect yet ;) */
 	__u32				reserved_5[8];
 };
+#endif
 
 struct v4l2_jpegcompression
 {
@@ -491,7 +425,6 @@
 					* allways use APP0 */
 };
 
-
 /*
  *	M E M O R Y - M A P P I N G   B U F F E R S
  */
@@ -573,7 +506,6 @@
 	void			__user *bitmap;
 };
 
-
 /*
  *	C A P T U R E   P A R A M E T E R S
  */
@@ -586,6 +518,7 @@
 	__u32              readbuffers;   /*  # of buffers for read */
 	__u32		   reserved[4];
 };
+
 /*  Flags for 'capability' and 'capturemode' fields */
 #define V4L2_MODE_HIGHQUALITY	0x0001	/*  High quality imaging mode */
 #define V4L2_CAP_TIMEPERFRAME	0x1000	/*  timeperframe field is supported */
@@ -603,7 +536,6 @@
 /*
  *	I N P U T   I M A G E   C R O P P I N G
  */
-
 struct v4l2_cropcap {
 	enum v4l2_buf_type      type;
 	struct v4l2_rect        bounds;
@@ -710,7 +642,6 @@
 	__u32		     reserved[4];
 };
 
-
 /*
  *	V I D E O   I N P U T S
  */
@@ -725,6 +656,7 @@
 	__u32	     status;
 	__u32	     reserved[4];
 };
+
 /*  Values for the 'type' field */
 #define V4L2_INPUT_TYPE_TUNER		1
 #define V4L2_INPUT_TYPE_CAMERA		2
@@ -775,6 +707,34 @@
 	__s32		     value;
 };
 
+struct v4l2_ext_control
+{
+	__u32 id;
+	__u32 reserved2[2];
+	union {
+		__s32 value;
+		__s64 value64;
+		void *reserved;
+	};
+};
+
+struct v4l2_ext_controls
+{
+	__u32 ctrl_class;
+	__u32 count;
+	__u32 error_idx;
+	__u32 reserved[2];
+	struct v4l2_ext_control *controls;
+};
+
+/*  Values for ctrl_class field */
+#define V4L2_CTRL_CLASS_USER 0x00980000	/* Old-style 'user' controls */
+#define V4L2_CTRL_CLASS_MPEG 0x00990000	/* MPEG-compression controls */
+
+#define V4L2_CTRL_ID_MASK      	  (0x0fffffff)
+#define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
+#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000)
+
 /*  Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
 struct v4l2_queryctrl
 {
@@ -801,12 +761,21 @@
 /*  Control flags  */
 #define V4L2_CTRL_FLAG_DISABLED		0x0001
 #define V4L2_CTRL_FLAG_GRABBED		0x0002
+#define V4L2_CTRL_FLAG_READ_ONLY 	0x0004
+#define V4L2_CTRL_FLAG_UPDATE 		0x0008
+#define V4L2_CTRL_FLAG_INACTIVE 	0x0010
+#define V4L2_CTRL_FLAG_SLIDER 		0x0020
 
-/*  Control IDs defined by V4L2 */
-#define V4L2_CID_BASE			0x00980900
+/*  Query flag, to be ORed with the control ID */
+#define V4L2_CTRL_FLAG_NEXT_CTRL	0x80000000
+
+/*  User-class control IDs defined by V4L2 */
+#define V4L2_CID_BASE			(V4L2_CTRL_CLASS_USER | 0x900)
+#define V4L2_CID_USER_BASE 		V4L2_CID_BASE
 /*  IDs reserved for driver specific controls */
 #define V4L2_CID_PRIVATE_BASE		0x08000000
 
+#define V4L2_CID_USER_CLASS 		(V4L2_CTRL_CLASS_USER | 1)
 #define V4L2_CID_BRIGHTNESS		(V4L2_CID_BASE+0)
 #define V4L2_CID_CONTRAST		(V4L2_CID_BASE+1)
 #define V4L2_CID_SATURATION		(V4L2_CID_BASE+2)
@@ -833,6 +802,188 @@
 #define V4L2_CID_VCENTER		(V4L2_CID_BASE+23)
 #define V4L2_CID_LASTP1			(V4L2_CID_BASE+24) /* last CID + 1 */
 
+/*  MPEG-class control IDs defined by V4L2 */
+#define V4L2_CID_MPEG_BASE 			(V4L2_CTRL_CLASS_MPEG | 0x900)
+#define V4L2_CID_MPEG_CLASS 			(V4L2_CTRL_CLASS_MPEG | 1)
+
+/*  MPEG streams */
+#define V4L2_CID_MPEG_STREAM_TYPE 		(V4L2_CID_MPEG_BASE+0)
+enum v4l2_mpeg_stream_type {
+	V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
+	V4L2_MPEG_STREAM_TYPE_MPEG2_TS   = 1, /* MPEG-2 transport stream */
+	V4L2_MPEG_STREAM_TYPE_MPEG1_SS   = 2, /* MPEG-1 system stream */
+	V4L2_MPEG_STREAM_TYPE_MPEG2_DVD  = 3, /* MPEG-2 DVD-compatible stream */
+	V4L2_MPEG_STREAM_TYPE_MPEG1_VCD  = 4, /* MPEG-1 VCD-compatible stream */
+	V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */
+};
+#define V4L2_CID_MPEG_STREAM_PID_PMT 		(V4L2_CID_MPEG_BASE+1)
+#define V4L2_CID_MPEG_STREAM_PID_AUDIO 		(V4L2_CID_MPEG_BASE+2)
+#define V4L2_CID_MPEG_STREAM_PID_VIDEO 		(V4L2_CID_MPEG_BASE+3)
+#define V4L2_CID_MPEG_STREAM_PID_PCR 		(V4L2_CID_MPEG_BASE+4)
+#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO 	(V4L2_CID_MPEG_BASE+5)
+#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO 	(V4L2_CID_MPEG_BASE+6)
+#define V4L2_CID_MPEG_STREAM_VBI_FMT 		(V4L2_CID_MPEG_BASE+7)
+enum v4l2_mpeg_stream_vbi_fmt {
+	V4L2_MPEG_STREAM_VBI_FMT_NONE = 0,  /* No VBI in the MPEG stream */
+	V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
+};
+
+/*  MPEG audio */
+#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ 	(V4L2_CID_MPEG_BASE+100)
+enum v4l2_mpeg_audio_sampling_freq {
+	V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
+	V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1,
+	V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_ENCODING 		(V4L2_CID_MPEG_BASE+101)
+enum v4l2_mpeg_audio_encoding {
+	V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0,
+	V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1,
+	V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_L1_BITRATE 		(V4L2_CID_MPEG_BASE+102)
+enum v4l2_mpeg_audio_l1_bitrate {
+	V4L2_MPEG_AUDIO_L1_BITRATE_32K  = 0,
+	V4L2_MPEG_AUDIO_L1_BITRATE_64K  = 1,
+	V4L2_MPEG_AUDIO_L1_BITRATE_96K  = 2,
+	V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3,
+	V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4,
+	V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5,
+	V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6,
+	V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7,
+	V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8,
+	V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9,
+	V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10,
+	V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11,
+	V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12,
+	V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_L2_BITRATE 		(V4L2_CID_MPEG_BASE+103)
+enum v4l2_mpeg_audio_l2_bitrate {
+	V4L2_MPEG_AUDIO_L2_BITRATE_32K  = 0,
+	V4L2_MPEG_AUDIO_L2_BITRATE_48K  = 1,
+	V4L2_MPEG_AUDIO_L2_BITRATE_56K  = 2,
+	V4L2_MPEG_AUDIO_L2_BITRATE_64K  = 3,
+	V4L2_MPEG_AUDIO_L2_BITRATE_80K  = 4,
+	V4L2_MPEG_AUDIO_L2_BITRATE_96K  = 5,
+	V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6,
+	V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7,
+	V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8,
+	V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9,
+	V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10,
+	V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11,
+	V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12,
+	V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_L3_BITRATE 		(V4L2_CID_MPEG_BASE+104)
+enum v4l2_mpeg_audio_l3_bitrate {
+	V4L2_MPEG_AUDIO_L3_BITRATE_32K  = 0,
+	V4L2_MPEG_AUDIO_L3_BITRATE_40K  = 1,
+	V4L2_MPEG_AUDIO_L3_BITRATE_48K  = 2,
+	V4L2_MPEG_AUDIO_L3_BITRATE_56K  = 3,
+	V4L2_MPEG_AUDIO_L3_BITRATE_64K  = 4,
+	V4L2_MPEG_AUDIO_L3_BITRATE_80K  = 5,
+	V4L2_MPEG_AUDIO_L3_BITRATE_96K  = 6,
+	V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7,
+	V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8,
+	V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9,
+	V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10,
+	V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11,
+	V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12,
+	V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_MODE 		(V4L2_CID_MPEG_BASE+105)
+enum v4l2_mpeg_audio_mode {
+	V4L2_MPEG_AUDIO_MODE_STEREO       = 0,
+	V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1,
+	V4L2_MPEG_AUDIO_MODE_DUAL         = 2,
+	V4L2_MPEG_AUDIO_MODE_MONO         = 3,
+};
+#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION 	(V4L2_CID_MPEG_BASE+106)
+enum v4l2_mpeg_audio_mode_extension {
+	V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4  = 0,
+	V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8  = 1,
+	V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2,
+	V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3,
+};
+#define V4L2_CID_MPEG_AUDIO_EMPHASIS 		(V4L2_CID_MPEG_BASE+107)
+enum v4l2_mpeg_audio_emphasis {
+	V4L2_MPEG_AUDIO_EMPHASIS_NONE         = 0,
+	V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1,
+	V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17    = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_CRC 		(V4L2_CID_MPEG_BASE+108)
+enum v4l2_mpeg_audio_crc {
+	V4L2_MPEG_AUDIO_CRC_NONE  = 0,
+	V4L2_MPEG_AUDIO_CRC_CRC16 = 1,
+};
+
+/*  MPEG video */
+#define V4L2_CID_MPEG_VIDEO_ENCODING 		(V4L2_CID_MPEG_BASE+200)
+enum v4l2_mpeg_video_encoding {
+	V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0,
+	V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_ASPECT 		(V4L2_CID_MPEG_BASE+201)
+enum v4l2_mpeg_video_aspect {
+	V4L2_MPEG_VIDEO_ASPECT_1x1     = 0,
+	V4L2_MPEG_VIDEO_ASPECT_4x3     = 1,
+	V4L2_MPEG_VIDEO_ASPECT_16x9    = 2,
+	V4L2_MPEG_VIDEO_ASPECT_221x100 = 3,
+};
+#define V4L2_CID_MPEG_VIDEO_B_FRAMES 		(V4L2_CID_MPEG_BASE+202)
+#define V4L2_CID_MPEG_VIDEO_GOP_SIZE 		(V4L2_CID_MPEG_BASE+203)
+#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE 	(V4L2_CID_MPEG_BASE+204)
+#define V4L2_CID_MPEG_VIDEO_PULLDOWN 		(V4L2_CID_MPEG_BASE+205)
+#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE 	(V4L2_CID_MPEG_BASE+206)
+enum v4l2_mpeg_video_bitrate_mode {
+	V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0,
+	V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_BITRATE 		(V4L2_CID_MPEG_BASE+207)
+#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK 	(V4L2_CID_MPEG_BASE+208)
+#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209)
+
+/*  MPEG-class control IDs specific to the CX2584x driver as defined by V4L2 */
+#define V4L2_CID_MPEG_CX2341X_BASE 				(V4L2_CTRL_CLASS_MPEG | 0x1000)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE 	(V4L2_CID_MPEG_CX2341X_BASE+0)
+enum v4l2_mpeg_cx2341x_video_spatial_filter_mode {
+	V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0,
+	V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO   = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER 		(V4L2_CID_MPEG_CX2341X_BASE+1)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE 	(V4L2_CID_MPEG_CX2341X_BASE+2)
+enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type {
+	V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF                  = 0,
+	V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR               = 1,
+	V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT              = 2,
+	V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE      = 3,
+	V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE 	(V4L2_CID_MPEG_CX2341X_BASE+3)
+enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type {
+	V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF    = 0,
+	V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE 	(V4L2_CID_MPEG_CX2341X_BASE+4)
+enum v4l2_mpeg_cx2341x_video_temporal_filter_mode {
+	V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0,
+	V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO   = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER 		(V4L2_CID_MPEG_CX2341X_BASE+5)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE 		(V4L2_CID_MPEG_CX2341X_BASE+6)
+enum v4l2_mpeg_cx2341x_video_median_filter_type {
+	V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF      = 0,
+	V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR      = 1,
+	V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT     = 2,
+	V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3,
+	V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG     = 4,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM 	(V4L2_CID_MPEG_CX2341X_BASE+7)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP 	(V4L2_CID_MPEG_CX2341X_BASE+8)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM	(V4L2_CID_MPEG_CX2341X_BASE+9)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP 	(V4L2_CID_MPEG_CX2341X_BASE+10)
+
 /*
  *	T U N I N G
  */
@@ -904,6 +1055,7 @@
 	__u32	mode;
 	__u32	reserved[2];
 };
+
 /*  Flags for the 'capability' field */
 #define V4L2_AUDCAP_STEREO		0x00001
 #define V4L2_AUDCAP_AVL			0x00002
@@ -927,7 +1079,6 @@
  */
 
 /* Raw VBI */
-
 struct v4l2_vbi_format
 {
 	__u32	sampling_rate;		/* in 1 Hz */
@@ -1034,8 +1185,6 @@
 	} parm;
 };
 
-
-
 /*
  *	I O C T L   C O D E S   F O R   V I D E O   D E V I C E S
  *
@@ -1045,8 +1194,10 @@
 #define VIDIOC_ENUM_FMT         _IOWR ('V',  2, struct v4l2_fmtdesc)
 #define VIDIOC_G_FMT		_IOWR ('V',  4, struct v4l2_format)
 #define VIDIOC_S_FMT		_IOWR ('V',  5, struct v4l2_format)
+#ifdef __KERNEL__
 #define VIDIOC_G_MPEGCOMP       _IOR  ('V',  6, struct v4l2_mpeg_compression)
 #define VIDIOC_S_MPEGCOMP     	_IOW  ('V',  7, struct v4l2_mpeg_compression)
+#endif
 #define VIDIOC_REQBUFS		_IOWR ('V',  8, struct v4l2_requestbuffers)
 #define VIDIOC_QUERYBUF		_IOWR ('V',  9, struct v4l2_buffer)
 #define VIDIOC_G_FBUF		_IOR  ('V', 10, struct v4l2_framebuffer)
@@ -1096,7 +1247,11 @@
 #define VIDIOC_G_SLICED_VBI_CAP _IOR  ('V', 69, struct v4l2_sliced_vbi_cap)
 #endif
 #define VIDIOC_LOG_STATUS       _IO   ('V', 70)
+#define VIDIOC_G_EXT_CTRLS	_IOWR ('V', 71, struct v4l2_ext_controls)
+#define VIDIOC_S_EXT_CTRLS	_IOWR ('V', 72, struct v4l2_ext_controls)
+#define VIDIOC_TRY_EXT_CTRLS	_IOWR ('V', 73, struct v4l2_ext_controls)
 
+#ifdef __OLD_VIDIOC_
 /* for compatibility, will go away some day */
 #define VIDIOC_OVERLAY_OLD     	_IOWR ('V', 14, int)
 #define VIDIOC_S_PARM_OLD      	_IOW  ('V', 22, struct v4l2_streamparm)
@@ -1104,57 +1259,10 @@
 #define VIDIOC_G_AUDIO_OLD     	_IOWR ('V', 33, struct v4l2_audio)
 #define VIDIOC_G_AUDOUT_OLD    	_IOWR ('V', 49, struct v4l2_audioout)
 #define VIDIOC_CROPCAP_OLD     	_IOR  ('V', 58, struct v4l2_cropcap)
+#endif
 
 #define BASE_VIDIOC_PRIVATE	192		/* 192-255 are private */
 
-
-#ifdef __KERNEL__
-/*
- *
- *	V 4 L 2   D R I V E R   H E L P E R   A P I
- *
- *	Some commonly needed functions for drivers (v4l2-common.o module)
- */
-#include <linux/fs.h>
-
-/*  Video standard functions  */
-extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
-extern int v4l2_video_std_construct(struct v4l2_standard *vs,
-				    int id, char *name);
-
-/* prority handling */
-struct v4l2_prio_state {
-	atomic_t prios[4];
-};
-int v4l2_prio_init(struct v4l2_prio_state *global);
-int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
-		     enum v4l2_priority new);
-int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
-int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
-enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
-int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
-
-/* names for fancy debug output */
-extern char *v4l2_field_names[];
-extern char *v4l2_type_names[];
-
-/*  Compatibility layer interface  --  v4l1-compat module */
-typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
-			   unsigned int cmd, void *arg);
-
-#ifdef CONFIG_VIDEO_V4L1_COMPAT
-int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
-			       int cmd, void *arg, v4l2_kioctl driver_ioctl);
-#else
-#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL
-#endif
-
-/* 32 Bits compatibility layer for 64 bits processors */
-extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
-				unsigned long arg);
-
-
-#endif /* __KERNEL__ */
 #endif /* __LINUX_VIDEODEV2_H */
 
 /*
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 1d5577b..f6024ab 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -4,10 +4,13 @@
 #include <linux/spinlock.h>
 #include <asm/page.h>		/* pgprot_t */
 
+struct vm_area_struct;
+
 /* bits in vm_struct->flags */
 #define VM_IOREMAP	0x00000001	/* ioremap() and friends */
 #define VM_ALLOC	0x00000002	/* vmalloc() */
 #define VM_MAP		0x00000004	/* vmap()ed pages */
+#define VM_USERMAP	0x00000008	/* suitable for remap_vmalloc_range */
 /* bits [20..32] reserved for arch specific ioremap internals */
 
 /*
@@ -32,9 +35,11 @@
  *	Highlevel APIs for driver use
  */
 extern void *vmalloc(unsigned long size);
+extern void *vmalloc_user(unsigned long size);
 extern void *vmalloc_node(unsigned long size, int node);
 extern void *vmalloc_exec(unsigned long size);
 extern void *vmalloc_32(unsigned long size);
+extern void *vmalloc_32_user(unsigned long size);
 extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot);
 extern void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask,
 				pgprot_t prot);
@@ -45,6 +50,9 @@
 extern void *vmap(struct page **pages, unsigned int count,
 			unsigned long flags, pgprot_t prot);
 extern void vunmap(void *addr);
+
+extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
+							unsigned long pgoff);
  
 /*
  *	Lowlevel-APIs (not for driver use!)
diff --git a/include/linux/vt_buffer.h b/include/linux/vt_buffer.h
index 1f7ba36..057db7d 100644
--- a/include/linux/vt_buffer.h
+++ b/include/linux/vt_buffer.h
@@ -13,7 +13,6 @@
 #ifndef _LINUX_VT_BUFFER_H_
 #define _LINUX_VT_BUFFER_H_
 
-#include <linux/config.h>
 
 #if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_MDA_CONSOLE)
 #include <asm/vga.h>
diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h
index fab5aed..940d026 100644
--- a/include/linux/vt_kern.h
+++ b/include/linux/vt_kern.h
@@ -6,7 +6,6 @@
  * with information needed by the vt package
  */
 
-#include <linux/config.h>
 #include <linux/vt.h>
 #include <linux/kd.h>
 #include <linux/tty.h>
diff --git a/include/linux/wait.h b/include/linux/wait.h
index d285182..544e855 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -19,7 +19,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/stddef.h>
 #include <linux/spinlock.h>
diff --git a/include/linux/wanrouter.h b/include/linux/wanrouter.h
index 1b6b76a..2cd0501 100644
--- a/include/linux/wanrouter.h
+++ b/include/linux/wanrouter.h
@@ -44,8 +44,6 @@
 * Jan 02, 1997	Gene Kozin	Initial version (based on wanpipe.h).
 *****************************************************************************/
 
-#include <linux/spinlock.h>       /* Support for SMP Locking */
-
 #ifndef	_ROUTER_H
 #define	_ROUTER_H
 
@@ -457,6 +455,8 @@
 #include <linux/fs.h>		/* support for device drivers */
 #include <linux/proc_fs.h>	/* proc filesystem pragmatics */
 #include <linux/netdevice.h>	/* support for network drivers */
+#include <linux/spinlock.h>     /* Support for SMP Locking */
+
 /*----------------------------------------------------------------------------
  * WAN device data space.
  */
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 56f92fc..9e38b56 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -50,14 +50,15 @@
 	 * a hint that the filesystem need only write out the pages inside that
 	 * byterange.  The byte at `end' is included in the writeout request.
 	 */
-	loff_t start;
-	loff_t end;
+	loff_t range_start;
+	loff_t range_end;
 
 	unsigned nonblocking:1;		/* Don't get stuck on request queues */
 	unsigned encountered_congestion:1; /* An output: a queue is full */
 	unsigned for_kupdate:1;		/* A kupdate writeback */
 	unsigned for_reclaim:1;		/* Invoked from the page allocator */
 	unsigned for_writepages:1;	/* This is a writepages() call */
+	unsigned range_cyclic:1;	/* range_start is cyclic */
 };
 
 /*
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index 6b42cc4..46a15c7 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -118,6 +118,10 @@
 	XFRM_SHARE_UNIQUE	/* Use once */
 };
 
+#define XFRM_MODE_TRANSPORT 0
+#define XFRM_MODE_TUNNEL 1
+#define XFRM_MODE_MAX 2
+
 /* Netlink configuration messages.  */
 enum {
 	XFRM_MSG_BASE = 0x10,
diff --git a/include/linux/zconf.h b/include/linux/zconf.h
index f1cfd66..0beb75e 100644
--- a/include/linux/zconf.h
+++ b/include/linux/zconf.h
@@ -35,6 +35,18 @@
 #  define MAX_WBITS   15 /* 32K LZ77 window */
 #endif
 
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+
                         /* Type declarations */
 
 typedef unsigned char  Byte;  /* 8 bits */
diff --git a/include/linux/zlib.h b/include/linux/zlib.h
index 4fa32f0..9e3192a 100644
--- a/include/linux/zlib.h
+++ b/include/linux/zlib.h
@@ -1,7 +1,6 @@
 /* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.1.3, July 9th, 1998
 
-  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+  Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -24,7 +23,7 @@
 
 
   The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+  Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
   (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
 */
 
@@ -33,7 +32,22 @@
 
 #include <linux/zconf.h>
 
-#define ZLIB_VERSION "1.1.3"
+/* zlib deflate based on ZLIB_VERSION "1.1.3" */
+/* zlib inflate based on ZLIB_VERSION "1.2.3" */
+
+/*
+  This is a modified version of zlib for use inside the Linux kernel.
+  The main changes are to perform all memory allocation in advance.
+
+  Inflation Changes:
+    * Z_PACKET_FLUSH is added and used by ppp_deflate. Before returning
+      this checks there is no more input data available and the next data
+      is a STORED block. It also resets the mode to be read for the next
+      data, all as per PPP requirements.
+    * Addition of zlib_inflateIncomp which copies incompressible data into
+      the history window and adjusts the accoutning without calling
+      zlib_inflate itself to inflate the data.
+*/
 
 /* 
      The 'zlib' compression library provides in-memory compression and
@@ -48,9 +62,18 @@
   application must provide more input and/or consume the output
   (providing more output space) before each call.
 
+     The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
      The library also supports reading and writing files in gzip (.gz) format
   with an interface similar to that of stdio.
 
+     The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
      The library does not install any signal handler. The decoder checks
   the consistency of the compressed data, so the library should never
   crash even in case of corrupted input.
@@ -119,7 +142,8 @@
 #define Z_SYNC_FLUSH    3
 #define Z_FULL_FLUSH    4
 #define Z_FINISH        5
-/* Allowed flush values; see deflate() below for details */
+#define Z_BLOCK         6 /* Only for inflate at present */
+/* Allowed flush values; see deflate() and inflate() below for details */
 
 #define Z_OK            0
 #define Z_STREAM_END    1
@@ -155,13 +179,6 @@
 
                         /* basic functions */
 
-extern const char * zlib_zlibVersion (void);
-/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
-   This check is automatically made by deflateInit and inflateInit.
- */
-
 extern int zlib_deflate_workspacesize (void);
 /*
    Returns the number of bytes that needs to be allocated for a per-
@@ -315,9 +332,9 @@
 extern int zlib_inflate (z_streamp strm, int flush);
 /*
     inflate decompresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may some
-  introduce some output latency (reading input without producing any output)
-  except when forced to flush.
+  buffer becomes empty or the output buffer becomes full. It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
 
   The detailed semantics are as follows. inflate performs one or both of the
   following actions:
@@ -341,11 +358,26 @@
   must be called again after making room in the output buffer because there
   might be more output pending.
 
-    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
-  output as possible to the output buffer. The flushing behavior of inflate is
-  not specified for values of the flush parameter other than Z_SYNC_FLUSH
-  and Z_FINISH, but the current implementation actually flushes as much output
-  as possible anyway.
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+  Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+  if and when it gets to the next deflate block boundary. When decoding the
+  zlib or gzip format, this will cause inflate() to return immediately after
+  the header and before the first block. When doing a raw inflate, inflate()
+  will go ahead and process the first block, and will return when it gets to
+  the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64
+  if inflate() is currently decoding the last block in the deflate stream,
+  plus 128 if inflate() returned immediately after decoding an end-of-block
+  code or decoding the complete header up to just before the first byte of the
+  deflate stream. The end-of-block will not be indicated until all of the
+  uncompressed data from that block has been written to strm->next_out.  The
+  number of unused bits may in general be greater than seven, except when
+  bit 7 of data_type is set, in which case the number of unused bits will be
+  less than eight.
 
     inflate() should normally be called until it returns Z_STREAM_END or an
   error. However if all decompression is to be performed in a single step
@@ -355,29 +387,44 @@
   uncompressed data. (The size of the uncompressed data may have been saved
   by the compressor for this purpose.) The next operation on this stream must
   be inflateEnd to deallocate the decompression state. The use of Z_FINISH
-  is never required, but can be used to inform inflate that a faster routine
+  is never required, but can be used to inform inflate that a faster approach
   may be used for the single inflate() call.
 
-     If a preset dictionary is needed at this point (see inflateSetDictionary
-  below), inflate sets strm-adler to the adler32 checksum of the
-  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
-  it sets strm->adler to the adler32 checksum of all output produced
-  so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
-  an error code as described below. At the end of the stream, inflate()
-  checks that its computed adler32 checksum is equal to that saved by the
-  compressor and returns Z_STREAM_END only if the checksum is correct.
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call. So the only effect of the flush parameter in this implementation
+  is on the return value of inflate(), as noted below, or when it returns early
+  because Z_BLOCK is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the adler32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the adler32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below. At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically.  Any information
+  contained in the gzip header is not retained, so applications that need that
+  information should instead use raw inflate, see inflateInit2() below, or
+  inflateBack() and perform their own processing of the gzip header and
+  trailer.
 
     inflate() returns Z_OK if some progress has been made (more input processed
   or more output produced), Z_STREAM_END if the end of the compressed data has
   been reached and all uncompressed output has been produced, Z_NEED_DICT if a
   preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
-  corrupted (input stream not conforming to the zlib format or incorrect
-  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
-  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
-  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
-  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
-  case, the application may then call inflateSync to look for a good
-  compression block.
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing. If Z_DATA_ERROR is returned, the application may then
+  call inflateSync() to look for a good compression block if a partial recovery
+  of the data is desired.
 */
 
 
@@ -547,16 +594,36 @@
      The windowBits parameter is the base two logarithm of the maximum window
    size (the size of the history buffer).  It should be in the range 8..15 for
    this version of the library. The default value is 15 if inflateInit is used
-   instead. If a compressed stream with a larger window size is given as
-   input, inflate() will return with the error code Z_DATA_ERROR instead of
-   trying to allocate a larger window.
+   instead. windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used. If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
 
-      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
-   memLevel). msg is set to null if there is no error message.  inflateInit2
-   does not perform any decompression apart from reading the zlib header if
-   present: this will be done by inflate(). (So next_in and avail_in may be
-   modified, but next_out and avail_out are unchanged.)
+     windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+   determines the window size. inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream. This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values. If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is. Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding. Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is
+   a crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+   is set to null if there is no error message.  inflateInit2 does not perform
+   any decompression apart from reading the zlib header if present: this will
+   be done by inflate(). (So next_in and avail_in may be modified, but next_out
+   and avail_out are unchanged.)
 */
 
 extern int zlib_inflateSetDictionary (z_streamp strm,
@@ -564,16 +631,19 @@
 						     uInt  dictLength);
 /*
      Initializes the decompression dictionary from the given uncompressed byte
-   sequence. This function must be called immediately after a call of inflate
-   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
-   can be determined from the Adler32 value returned by this call of
-   inflate. The compressor and decompressor must use exactly the same
-   dictionary (see deflateSetDictionary).
+   sequence. This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called
+   immediately after inflateInit2() or inflateReset() and before any call of
+   inflate() to set the dictionary.  The application must insure that the
+   dictionary that was used for compression is provided.
 
      inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
    parameter is invalid (such as NULL dictionary) or the stream state is
    inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
-   expected one (incorrect Adler32 value). inflateSetDictionary does not
+   expected one (incorrect adler32 value). inflateSetDictionary does not
    perform any decompression: this will be done by subsequent calls of
    inflate().
 */
@@ -614,40 +684,19 @@
    containing the data at next_in (except that the data is not output).
 */
 
-                        /* various hacks, don't look :) */
-
-/* deflateInit and inflateInit are macros to allow checking the zlib version
- * and the compiler's view of z_stream:
- */
-extern int zlib_deflateInit_ (z_streamp strm, int level,
-                                     const char *version, int stream_size);
-extern int zlib_inflateInit_ (z_streamp strm,
-                                     const char *version, int stream_size);
-extern int zlib_deflateInit2_ (z_streamp strm, int  level, int  method,
-                                      int windowBits, int memLevel,
-                                      int strategy, const char *version,
-                                      int stream_size);
-extern int zlib_inflateInit2_ (z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size);
 #define zlib_deflateInit(strm, level) \
-        zlib_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+	zlib_deflateInit2((strm), (level), Z_DEFLATED, MAX_WBITS, \
+			      DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY)
 #define zlib_inflateInit(strm) \
-        zlib_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
-#define zlib_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
-        zlib_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                      (strategy), ZLIB_VERSION, sizeof(z_stream))
-#define zlib_inflateInit2(strm, windowBits) \
-        zlib_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+	zlib_inflateInit2((strm), DEF_WBITS)
 
+extern int zlib_deflateInit2(z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy);
+extern int zlib_inflateInit2(z_streamp strm, int  windowBits);
 
 #if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
     struct internal_state {int dummy;}; /* hack for buggy compilers */
 #endif
 
-extern const char  * zlib_zError           (int err);
-#if 0
-extern int           zlib_inflateSyncPoint (z_streamp z);
-#endif
-extern const uLong * zlib_get_crc_table    (void);
-
 #endif /* _ZLIB_H */
diff --git a/include/linux/zorro.h b/include/linux/zorro.h
index 2f135cf..913bfc2 100644
--- a/include/linux/zorro.h
+++ b/include/linux/zorro.h
@@ -11,8 +11,6 @@
 #ifndef _LINUX_ZORRO_H
 #define _LINUX_ZORRO_H
 
-#ifndef __ASSEMBLY__
-
 #include <linux/device.h>
 
 
@@ -112,45 +110,6 @@
     __u32		cd_Unused[4];	/* for whatever the driver wants */
 } __attribute__ ((packed));
 
-#else /* __ASSEMBLY__ */
-
-LN_Succ		= 0
-LN_Pred		= LN_Succ+4
-LN_Type		= LN_Pred+4
-LN_Pri		= LN_Type+1
-LN_Name		= LN_Pri+1
-LN_sizeof	= LN_Name+4
-
-ER_Type		= 0
-ER_Product	= ER_Type+1
-ER_Flags	= ER_Product+1
-ER_Reserved03	= ER_Flags+1
-ER_Manufacturer	= ER_Reserved03+1
-ER_SerialNumber	= ER_Manufacturer+2
-ER_InitDiagVec	= ER_SerialNumber+4
-ER_Reserved0c	= ER_InitDiagVec+2
-ER_Reserved0d	= ER_Reserved0c+1
-ER_Reserved0e	= ER_Reserved0d+1
-ER_Reserved0f	= ER_Reserved0e+1
-ER_sizeof	= ER_Reserved0f+1
-
-CD_Node		= 0
-CD_Flags	= CD_Node+LN_sizeof
-CD_Pad		= CD_Flags+1
-CD_Rom		= CD_Pad+1
-CD_BoardAddr	= CD_Rom+ER_sizeof
-CD_BoardSize	= CD_BoardAddr+4
-CD_SlotAddr	= CD_BoardSize+4
-CD_SlotSize	= CD_SlotAddr+2
-CD_Driver	= CD_SlotSize+2
-CD_NextCD	= CD_Driver+4
-CD_Unused	= CD_NextCD+4
-CD_sizeof	= CD_Unused+(4*4)
-
-#endif /* __ASSEMBLY__ */
-
-#ifndef __ASSEMBLY__
-
 #define ZORRO_NUM_AUTO		16
 
 #ifdef __KERNEL__
@@ -290,7 +249,6 @@
 #define Z2RAM_CHUNKSHIFT	(16)
 
 
-#endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_ZORRO_H */
diff --git a/include/linux/zutil.h b/include/linux/zutil.h
index ee0c59c..6adfa9a 100644
--- a/include/linux/zutil.h
+++ b/include/linux/zutil.h
@@ -23,18 +23,6 @@
 
         /* common constants */
 
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
 #define STORED_BLOCK 0
 #define STATIC_TREES 1
 #define DYN_TREES    2
diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h
new file mode 100644
index 0000000..d91d88f
--- /dev/null
+++ b/include/media/cx2341x.h
@@ -0,0 +1,195 @@
+/*
+    cx23415/6 header containing common defines.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef CX2341X_H
+#define CX2341X_H
+
+enum cx2341x_port {
+	CX2341X_PORT_MEMORY    = 0,
+	CX2341X_PORT_STREAMING = 1,
+	CX2341X_PORT_SERIAL    = 2
+};
+
+enum cx2341x_cap {
+	CX2341X_CAP_HAS_SLICED_VBI = 1 << 0,
+};
+
+struct cx2341x_mpeg_params {
+	/* misc */
+	u32 capabilities;
+	enum cx2341x_port port;
+	u16 width;
+	u16 height;
+	u16 is_50hz;
+
+	/* stream */
+	enum v4l2_mpeg_stream_type stream_type;
+	enum v4l2_mpeg_stream_vbi_fmt stream_vbi_fmt;
+
+	/* audio */
+	enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq;
+	enum v4l2_mpeg_audio_encoding audio_encoding;
+	enum v4l2_mpeg_audio_l2_bitrate audio_l2_bitrate;
+	enum v4l2_mpeg_audio_mode audio_mode;
+	enum v4l2_mpeg_audio_mode_extension audio_mode_extension;
+	enum v4l2_mpeg_audio_emphasis audio_emphasis;
+	enum v4l2_mpeg_audio_crc audio_crc;
+	u8 audio_properties;
+
+	/* video */
+	enum v4l2_mpeg_video_encoding video_encoding;
+	enum v4l2_mpeg_video_aspect video_aspect;
+	u16 video_b_frames;
+	u16 video_gop_size;
+	u16 video_gop_closure;
+	u16 video_pulldown;
+	enum v4l2_mpeg_video_bitrate_mode video_bitrate_mode;
+	u32 video_bitrate;
+	u32 video_bitrate_peak;
+	u16 video_temporal_decimation;
+
+	/* encoding filters */
+	enum v4l2_mpeg_cx2341x_video_spatial_filter_mode video_spatial_filter_mode;
+	u16 video_spatial_filter;
+	enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type video_luma_spatial_filter_type;
+	enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type video_chroma_spatial_filter_type;
+	enum v4l2_mpeg_cx2341x_video_temporal_filter_mode video_temporal_filter_mode;
+	u16 video_temporal_filter;
+	enum v4l2_mpeg_cx2341x_video_median_filter_type video_median_filter_type;
+	u16 video_luma_median_filter_top;
+	u16 video_luma_median_filter_bottom;
+	u16 video_chroma_median_filter_top;
+	u16 video_chroma_median_filter_bottom;
+};
+
+#define CX2341X_MBOX_MAX_DATA 16
+
+extern const u32 cx2341x_mpeg_ctrls[];
+typedef int (*cx2341x_mbox_func)(void *priv, int cmd, int in, int out,
+		u32 data[CX2341X_MBOX_MAX_DATA]);
+int cx2341x_update(void *priv, cx2341x_mbox_func func,
+		const struct cx2341x_mpeg_params *old,
+		const struct cx2341x_mpeg_params *new);
+int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params,
+		struct v4l2_queryctrl *qctrl);
+const char **cx2341x_ctrl_get_menu(u32 id);
+int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params,
+		struct v4l2_ext_controls *ctrls, unsigned int cmd);
+void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p);
+void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix);
+
+/* Firmware names */
+#define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw"
+/* Decoder firmware for the cx23415 only */
+#define CX2341X_FIRM_DEC_FILENAME "v4l-cx2341x-dec.fw"
+
+/* Firmware API commands */
+
+/* MPEG decoder API, specific to the cx23415 */
+#define CX2341X_DEC_PING_FW 			0x00
+#define CX2341X_DEC_START_PLAYBACK 		0x01
+#define CX2341X_DEC_STOP_PLAYBACK 		0x02
+#define CX2341X_DEC_SET_PLAYBACK_SPEED 		0x03
+#define CX2341X_DEC_STEP_VIDEO 			0x05
+#define CX2341X_DEC_SET_DMA_BLOCK_SIZE 		0x08
+#define CX2341X_DEC_GET_XFER_INFO		0x09
+#define CX2341X_DEC_GET_DMA_STATUS		0x0a
+#define CX2341X_DEC_SCHED_DMA_FROM_HOST		0x0b
+#define CX2341X_DEC_PAUSE_PLAYBACK 		0x0d
+#define CX2341X_DEC_HALT_FW 			0x0e
+#define CX2341X_DEC_SET_STANDARD 		0x10
+#define CX2341X_DEC_GET_VERSION			0x11
+#define CX2341X_DEC_SET_STREAM_INPUT 		0x14
+#define CX2341X_DEC_GET_TIMING_INFO 		0x15
+#define CX2341X_DEC_SET_AUDIO_MODE 		0x16
+#define CX2341X_DEC_SET_EVENT_NOTIFICATION	0x17
+#define CX2341X_DEC_SET_DISPLAY_BUFFERS		0x18
+#define CX2341X_DEC_EXTRACT_VBI 		0x19
+#define CX2341X_DEC_SET_DECODER_SOURCE 		0x1a
+#define CX2341X_DEC_SET_AUDIO_OUTPUT 		0x1b
+#define CX2341X_DEC_SET_AV_DELAY 		0x1c
+#define CX2341X_DEC_SET_PREBUFFERING		0x1e
+
+/* MPEG encoder API */
+#define CX2341X_ENC_PING_FW 			0x80
+#define CX2341X_ENC_START_CAPTURE 		0x81
+#define CX2341X_ENC_STOP_CAPTURE 		0x82
+#define CX2341X_ENC_SET_AUDIO_ID 		0x89
+#define CX2341X_ENC_SET_VIDEO_ID 		0x8b
+#define CX2341X_ENC_SET_PCR_ID 			0x8d
+#define CX2341X_ENC_SET_FRAME_RATE 		0x8f
+#define CX2341X_ENC_SET_FRAME_SIZE 		0x91
+#define CX2341X_ENC_SET_BIT_RATE 		0x95
+#define CX2341X_ENC_SET_GOP_PROPERTIES 		0x97
+#define CX2341X_ENC_SET_ASPECT_RATIO 		0x99
+#define CX2341X_ENC_SET_DNR_FILTER_MODE 	0x9b
+#define CX2341X_ENC_SET_DNR_FILTER_PROPS 	0x9d
+#define CX2341X_ENC_SET_CORING_LEVELS 		0x9f
+#define CX2341X_ENC_SET_SPATIAL_FILTER_TYPE 	0xa1
+#define CX2341X_ENC_SET_3_2_PULLDOWN 		0xb1
+#define CX2341X_ENC_SET_VBI_LINE 		0xb7
+#define CX2341X_ENC_SET_STREAM_TYPE 		0xb9
+#define CX2341X_ENC_SET_OUTPUT_PORT 		0xbb
+#define CX2341X_ENC_SET_AUDIO_PROPERTIES 	0xbd
+#define CX2341X_ENC_HALT_FW 			0xc3
+#define CX2341X_ENC_GET_VERSION			0xc4
+#define CX2341X_ENC_SET_GOP_CLOSURE 		0xc5
+#define CX2341X_ENC_GET_SEQ_END 		0xc6
+#define CX2341X_ENC_SET_PGM_INDEX_INFO 		0xc7
+#define CX2341X_ENC_SET_VBI_CONFIG		0xc8
+#define CX2341X_ENC_SET_DMA_BLOCK_SIZE 		0xc9
+#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_10	0xca
+#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_9	0xcb
+#define CX2341X_ENC_SCHED_DMA_TO_HOST 		0xcc
+#define CX2341X_ENC_INITIALIZE_INPUT 		0xcd
+#define CX2341X_ENC_SET_FRAME_DROP_RATE 	0xd0
+#define CX2341X_ENC_PAUSE_ENCODER 		0xd2
+#define CX2341X_ENC_REFRESH_INPUT 		0xd3
+#define CX2341X_ENC_SET_COPYRIGHT		0xd4
+#define CX2341X_ENC_SET_EVENT_NOTIFICATION 	0xd5
+#define CX2341X_ENC_SET_NUM_VSYNC_LINES 	0xd6
+#define CX2341X_ENC_SET_PLACEHOLDER 		0xd7
+#define CX2341X_ENC_MUTE_VIDEO 			0xd9
+#define CX2341X_ENC_MUTE_AUDIO 			0xda
+#define CX2341X_ENC_UNKNOWN			0xdb
+#define CX2341X_ENC_MISC 			0xdc
+
+/* OSD API, specific to the cx23415 */
+#define CX2341X_OSD_GET_FRAMEBUFFER 		0x41
+#define CX2341X_OSD_GET_PIXEL_FORMAT 		0x42
+#define CX2341X_OSD_SET_PIXEL_FORMAT 		0x43
+#define CX2341X_OSD_GET_STATE 			0x44
+#define CX2341X_OSD_SET_STATE 			0x45
+#define CX2341X_OSD_GET_OSD_COORDS 		0x46
+#define CX2341X_OSD_SET_OSD_COORDS 		0x47
+#define CX2341X_OSD_GET_SCREEN_COORDS 		0x48
+#define CX2341X_OSD_SET_SCREEN_COORDS 		0x49
+#define CX2341X_OSD_GET_GLOBAL_ALPHA 		0x4a
+#define CX2341X_OSD_SET_GLOBAL_ALPHA 		0x4b
+#define CX2341X_OSD_SET_BLEND_COORDS 		0x4c
+#define CX2341X_OSD_GET_FLICKER_STATE 		0x4f
+#define CX2341X_OSD_SET_FLICKER_STATE 		0x50
+#define CX2341X_OSD_BLT_COPY 			0x52
+#define CX2341X_OSD_BLT_FILL 			0x53
+#define CX2341X_OSD_BLT_TEXT 			0x54
+#define CX2341X_OSD_SET_FRAMEBUFFER_WINDOW 	0x56
+#define CX2341X_OSD_SET_CHROMA_KEY 		0x60
+#define CX2341X_OSD_GET_ALPHA_CONTENT_INDEX 	0x61
+#define CX2341X_OSD_SET_ALPHA_CONTENT_INDEX 	0x62
+
+#endif /* CX2341X_H */
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 302d5b39..7bab09b 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -73,7 +73,7 @@
 extern IR_KEYTAB_TYPE ir_codes_avertv_303[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_dntv_live_dvbt_pro[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE];
-extern IR_KEYTAB_TYPE ir_codes_em_pinnacle_usb[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pinnacle_grey[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_flyvideo[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_flydvb[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_cinergy[IR_KEYTAB_SIZE];
@@ -87,8 +87,9 @@
 extern IR_KEYTAB_TYPE ir_codes_pv951[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
-extern IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pinnacle_color[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_npgtech[IR_KEYTAB_SIZE];
 
 #endif
 
diff --git a/include/media/ir-kbd-i2c.h b/include/media/ir-kbd-i2c.h
index 730f21e..a455f7c 100644
--- a/include/media/ir-kbd-i2c.h
+++ b/include/media/ir-kbd-i2c.h
@@ -20,5 +20,6 @@
 	int                    (*get_key)(struct IR_i2c*, u32*, u32*);
 };
 
-int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
+int get_key_pinnacle_grey(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
+int get_key_pinnacle_color(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
 #endif
diff --git a/include/media/ovcamchip.h b/include/media/ovcamchip.h
index 8138983..0f43451 100644
--- a/include/media/ovcamchip.h
+++ b/include/media/ovcamchip.h
@@ -15,6 +15,7 @@
 #define __LINUX_OVCAMCHIP_H
 
 #include <linux/videodev.h>
+#include <media/v4l2-common.h>
 #include <linux/i2c.h>
 
 /* --------------------------------- */
diff --git a/include/media/pwc-ioctl.h b/include/media/pwc-ioctl.h
new file mode 100644
index 0000000..adc1254
--- /dev/null
+++ b/include/media/pwc-ioctl.h
@@ -0,0 +1,325 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+   (C) 2004-2006 Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* This is pwc-ioctl.h belonging to PWC 10.0.10
+   It contains structures and defines to communicate from user space
+   directly to the driver.
+ */
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added ioctl constants to access methods for
+			  changing white balance and red/blue gains
+   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
+   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
+	       PWCX easier
+   2006/01/01  Luc Saillard Add raw format definition
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API.
+
+   The #define names are built up like follows:
+   VIDIOC		VIDeo IOCtl prefix
+	 PWC		Philps WebCam
+	    G           optional: Get
+	    S           optional: Set
+	     ... 	the function
+ */
+
+#include <linux/types.h>
+#include <linux/version.h>
+
+
+ /* Enumeration of image sizes */
+#define PSZ_SQCIF	0x00
+#define PSZ_QSIF	0x01
+#define PSZ_QCIF	0x02
+#define PSZ_SIF		0x03
+#define PSZ_CIF		0x04
+#define PSZ_VGA		0x05
+#define PSZ_MAX		6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+   This value can also be passing using the private flag when using v4l2 and
+   VIDIOC_S_FMT ioctl.
+
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour
+   balance controls.
+ */
+#define PWC_FPS_SHIFT		16
+#define PWC_FPS_MASK		0x00FF0000
+#define PWC_FPS_FRMASK		0x003F0000
+#define PWC_FPS_SNAPSHOT	0x00400000
+#define PWC_QLT_MASK		0x03000000
+#define PWC_QLT_SHIFT		24
+
+
+/* structure for transferring x & y coordinates */
+struct pwc_coord
+{
+	int x, y;		/* guess what */
+	int size;		/* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+	char name[32];
+	int type;
+};
+
+struct pwc_serial
+{
+	char serial[30];	/* String with serial number. Contains terminating 0 */
+};
+
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR		0
+#define PWC_WB_OUTDOOR		1
+#define PWC_WB_FL		2
+#define PWC_WB_MANUAL		3
+#define PWC_WB_AUTO		4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance).
+   Set mode to one of the PWC_WB_* values above.
+   *red and *blue are the respective gains of these colour components inside
+   the camera; range 0..65535
+   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read;
+   otherwise undefined.
+   'read_red' and 'read_blue' are read-only.
+*/
+struct pwc_whitebalance
+{
+	int mode;
+	int manual_red, manual_blue;	/* R/W */
+	int read_red, read_blue;	/* R/O */
+};
+
+/*
+   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+   and tell the camera how fast it should react to changes in lighting, and
+   with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+	int control_speed;
+	int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+	int led_on;			/* Led on-time; range = 0..25000 */
+	int led_off;			/* Led off-time; range = 0..25000  */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+	int width;
+	int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN		0x01
+#define PWC_MPT_TILT		0x02
+#define PWC_MPT_TIMEOUT		0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the
+   driver calculates the relative offset for you. This can only
+   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+   absolute angles.
+ */
+struct pwc_mpt_angles
+{
+	int absolute;		/* write-only */
+	int pan;		/* degrees * 100 */
+	int tilt;		/* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+	int pan_min, pan_max;		/* degrees * 100 */
+	int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+	int status;
+	int time_pan;
+	int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+   all the necessary information to initialize and use the decompressor
+   routines in standalone applications.
+ */
+struct pwc_video_command
+{
+	int type;		/* camera type (645, 675, 730, etc.) */
+	int release;		/* release number */
+
+	int size;		/* one of PSZ_* */
+	int alternate;
+	int command_len;	/* length of USB video command */
+	unsigned char command_buf[13];	/* Actual USB video command */
+	int bandlength;		/* >0 = compressed */
+	int frame_size;		/* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR	0x0001
+#define PWCX_FLAG_BAYER		0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER		_IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER		_IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY	_IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL		_IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL		_IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL	_IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+    becomes difficult to include all the names in programs that want to
+    check for the enhanced Philips stuff. So in stead, try this PROBE;
+    it returns a structure with the original name, and the corresponding
+    Philips type.
+    To use, fill the structure with zeroes, call PROBE and if that succeeds,
+    compare the name with that returned from VIDIOCGCAP; they should be the
+    same. If so, you can be assured it is a Philips (OEM) cam and the type
+    is valid.
+ */
+#define VIDIOCPWCPROBE		_IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC		_IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC		_IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER	_IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED	_IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED	_IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
+
+  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR	_IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR	_IOR('v', 206, int)
+
+  /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT	_IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT	_IOR('v', 207, int)
+
+  /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER	_IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER	_IOR('v', 208, int)
+
+  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE	_IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE	_IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE	_IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */
+#define VIDIOCPWCMPTRESET	_IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE	_IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE	_IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE	_IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS	_IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD	_IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+   int len;
+   char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE	_IOR('v', 216, struct pwc_table_init_buffer)
+
+/*
+ * This is private command used when communicating with v4l2.
+ * In the future all private ioctl will be remove/replace to
+ * use interface offer by v4l2.
+ */
+
+#define V4L2_CID_PRIVATE_SAVE_USER       (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_PRIVATE_RESTORE_USER    (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_PRIVATE_COLOUR_MODE     (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_PRIVATE_AUTOCONTOUR     (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_PRIVATE_CONTOUR         (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_PRIVATE_BACKLIGHT       (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_PRIVATE_FLICKERLESS     (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8)
+
+struct pwc_raw_frame {
+   __le16 type;		/* type of the webcam */
+   __le16 vbandlength;	/* Size of 4lines compressed (used by the decompressor) */
+   __u8   cmd[4];	/* the four byte of the command (in case of nala,
+			   only the first 3 bytes is filled) */
+   __u8   rawframe[0];	/* frame_size = H/4*vbandlength */
+} __attribute__ ((packed));
+
+
+#endif
diff --git a/include/media/saa7115.h b/include/media/saa7115.h
index 6b4836f..9f0e228 100644
--- a/include/media/saa7115.h
+++ b/include/media/saa7115.h
@@ -1,5 +1,5 @@
 /*
-    saa7115.h - definition for saa7113/4/5 inputs
+    saa7115.h - definition for saa7113/4/5 inputs and frequency flags
 
     Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
 
@@ -33,5 +33,14 @@
 #define SAA7115_SVIDEO2    8
 #define SAA7115_SVIDEO3    9
 
+/* SAA7115 v4l2_crystal_freq frequency values */
+#define SAA7115_FREQ_32_11_MHZ  32110000   /* 32.11 MHz crystal, SAA7114/5 only */
+#define SAA7115_FREQ_24_576_MHZ 24576000   /* 24.576 MHz crystal */
+
+/* SAA7115 v4l2_crystal_freq audio clock control flags */
+#define SAA7115_FREQ_FL_UCGC   (1 << 0)	   /* SA 3A[7], UCGC, SAA7115 only */
+#define SAA7115_FREQ_FL_CGCDIV (1 << 1)	   /* SA 3A[6], CGCDIV, SAA7115 only */
+#define SAA7115_FREQ_FL_APLL   (1 << 2)	   /* SA 3A[3], APLL, SAA7114/5 only */
+
 #endif
 
diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
index 4507cb6..83fe2e3 100644
--- a/include/media/saa7146_vv.h
+++ b/include/media/saa7146_vv.h
@@ -2,7 +2,7 @@
 #define __SAA7146_VV__
 
 #include <linux/videodev.h>
-
+#include <media/v4l2-common.h>
 #include <media/saa7146.h>
 #include <media/video-buf.h>
 
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 017fed7..2f7b00b 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -25,6 +25,8 @@
 #include <linux/videodev2.h>
 #include <media/tuner-types.h>
 
+extern int tuner_debug;
+
 #define ADDR_UNSET (255)
 
 #define TUNER_TEMIC_PAL			0        /* 4002 FH5 (3X 7756, 9483) */
@@ -108,7 +110,7 @@
 #define TUNER_TEA5767			62	/* Only FM Radio Tuner */
 #define TUNER_PHILIPS_FMD1216ME_MK3	63
 
-#define TUNER_LG_TDVS_H062F		64	/* DViCO FusionHDTV 5 */
+#define TUNER_LG_TDVS_H06XF		64	/* TDVS H061F, H062F, H064F */
 #define TUNER_YMEC_TVF66T5_B_DFF	65	/* Acorp Y878F */
 #define TUNER_LG_TALN			66
 #define TUNER_PHILIPS_TD1316		67
@@ -119,6 +121,8 @@
 #define TUNER_XCEIVE_XC3028		71
 
 #define TUNER_THOMSON_FE6600		72	/* DViCO FusionHDTV DVB-T Hybrid */
+#define TUNER_SAMSUNG_TCPG_6121P30A     73 	/* Hauppauge PVR-500 PAL */
+#define TUNER_TDA9887                   74      /* This tuner should be used only internally */
 
 /* tv card specific */
 #define TDA9887_PRESENT 		(1<<0)
@@ -190,6 +194,10 @@
 
 	int          using_v4l2;
 
+	/* used by tda9887 */
+	unsigned int       tda9887_config;
+	unsigned char 	   tda9887_data[4];
+
 	/* used by MT2032 */
 	unsigned int xogc;
 	unsigned int radio_if2;
@@ -206,6 +214,8 @@
 	void (*set_radio_freq)(struct i2c_client *c, unsigned int freq);
 	int  (*has_signal)(struct i2c_client *c);
 	int  (*is_stereo)(struct i2c_client *c);
+	int  (*get_afc)(struct i2c_client *c);
+	void (*tuner_status)(struct i2c_client *c);
 	void (*standby)(struct i2c_client *c);
 };
 
@@ -218,6 +228,7 @@
 extern int tea5767_tuner_init(struct i2c_client *c);
 extern int default_tuner_init(struct i2c_client *c);
 extern int tea5767_autodetection(struct i2c_client *c);
+extern int tda9887_tuner_init(struct i2c_client *c);
 
 #define tuner_warn(fmt, arg...) do {\
 	printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->driver.name, \
diff --git a/include/media/tvp5150.h b/include/media/tvp5150.h
new file mode 100644
index 0000000..72bd2a2
--- /dev/null
+++ b/include/media/tvp5150.h
@@ -0,0 +1,34 @@
+/*
+    tvp5150.h - definition for tvp5150 inputs
+
+    Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl)
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _TVP5150_H_
+#define _TVP5150_H_
+
+/* TVP5150 HW inputs */
+#define TVP5150_COMPOSITE0 0
+#define TVP5150_COMPOSITE1 1
+#define TVP5150_SVIDEO     2
+
+/* TVP5150 HW outputs */
+#define TVP5150_NORMAL       0
+#define TVP5150_BLACK_SCREEN 1
+
+#endif
+
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 642520a..5564db1 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -26,8 +26,14 @@
 #ifndef V4L2_COMMON_H_
 #define V4L2_COMMON_H_
 
+#include <media/v4l2-dev.h>
+
 /* v4l debugging and diagnostics */
 
+/* Debug bitmask flags to be used on V4L2 */
+#define V4L2_DEBUG_IOCTL     0x01
+#define V4L2_DEBUG_IOCTL_ARG 0x02
+
 /* Common printk constucts for v4l-i2c drivers. These macros create a unique
    prefix consisting of the driver name, the adapter number and the i2c
    address. */
@@ -78,6 +84,19 @@
 
 /* ------------------------------------------------------------------------- */
 
+/* Control helper functions */
+
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+		const char **menu_items);
+const char **v4l2_ctrl_get_menu(u32 id);
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def);
+int v4l2_ctrl_query_fill_std(struct v4l2_queryctrl *qctrl);
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu,
+		struct v4l2_queryctrl *qctrl, const char **menu_items);
+u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
+
+/* ------------------------------------------------------------------------- */
+
 /* Internal ioctls */
 
 /* VIDIOC_INT_G_REGISTER and VIDIOC_INT_S_REGISTER */
@@ -112,6 +131,8 @@
 	V4L2_IDENT_SAA7129 = 159,
 
 	/* module cx25840: reserved range 200-249 */
+	V4L2_IDENT_CX25836 = 236,
+	V4L2_IDENT_CX25837 = 237,
 	V4L2_IDENT_CX25840 = 240,
 	V4L2_IDENT_CX25841 = 241,
 	V4L2_IDENT_CX25842 = 242,
@@ -211,4 +232,15 @@
 #define	VIDIOC_INT_S_VIDEO_ROUTING	_IOW ('d', 111, struct v4l2_routing)
 #define	VIDIOC_INT_G_VIDEO_ROUTING	_IOR ('d', 112, struct v4l2_routing)
 
+struct v4l2_crystal_freq {
+	u32 freq;	/* frequency in Hz of the crystal */
+	u32 flags; 	/* device specific flags */
+};
+
+/* Sets the frequency of the crystal used to generate the clocks.
+   An extra flags field allows device specific configuration regarding
+   clock frequency dividers, etc. If not used, then set flags to 0.
+   If the frequency is not supported, then -EINVAL is returned. */
+#define VIDIOC_INT_S_CRYSTAL_FREQ 	_IOW ('d', 113, struct v4l2_crystal_freq)
+
 #endif /* V4L2_COMMON_H_ */
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
new file mode 100644
index 0000000..a1b4731
--- /dev/null
+++ b/include/media/v4l2-dev.h
@@ -0,0 +1,375 @@
+/*
+ *
+ *	V 4 L 2   D R I V E R   H E L P E R   A P I
+ *
+ * Moved from videodev2.h
+ *
+ *	Some commonly needed functions for drivers (v4l2-common.o module)
+ */
+#ifndef _V4L2_DEV_H
+#define _V4L2_DEV_H
+
+#define OBSOLETE_OWNER 1 /* to be removed soon */
+
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/compiler.h> /* need __user */
+#ifdef CONFIG_VIDEO_V4L1
+#include <linux/videodev.h>
+#else
+#include <linux/videodev2.h>
+#endif
+
+#include <linux/fs.h>
+
+#define VIDEO_MAJOR	81
+/* Minor device allocation */
+#define MINOR_VFL_TYPE_GRABBER_MIN   0
+#define MINOR_VFL_TYPE_GRABBER_MAX  63
+#define MINOR_VFL_TYPE_RADIO_MIN    64
+#define MINOR_VFL_TYPE_RADIO_MAX   127
+#define MINOR_VFL_TYPE_VTX_MIN     192
+#define MINOR_VFL_TYPE_VTX_MAX     223
+#define MINOR_VFL_TYPE_VBI_MIN     224
+#define MINOR_VFL_TYPE_VBI_MAX     255
+
+#define VFL_TYPE_GRABBER	0
+#define VFL_TYPE_VBI		1
+#define VFL_TYPE_RADIO		2
+#define VFL_TYPE_VTX		3
+
+/*  Video standard functions  */
+extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs);
+extern int v4l2_video_std_construct(struct v4l2_standard *vs,
+				    int id, char *name);
+
+/* prority handling */
+struct v4l2_prio_state {
+	atomic_t prios[4];
+};
+int v4l2_prio_init(struct v4l2_prio_state *global);
+int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
+		     enum v4l2_priority new);
+int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local);
+int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local);
+enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global);
+int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local);
+
+/* names for fancy debug output */
+extern char *v4l2_field_names[];
+extern char *v4l2_type_names[];
+
+/*  Compatibility layer interface  --  v4l1-compat module */
+typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file,
+			   unsigned int cmd, void *arg);
+#ifdef CONFIG_VIDEO_V4L1_COMPAT
+int v4l_compat_translate_ioctl(struct inode *inode, struct file *file,
+			       int cmd, void *arg, v4l2_kioctl driver_ioctl);
+#else
+#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL
+#endif
+
+/* 32 Bits compatibility layer for 64 bits processors */
+extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd,
+				unsigned long arg);
+
+/*
+ * Newer version of video_device, handled by videodev2.c
+ * 	This version moves redundant code from video device code to
+ *	the common handler
+ */
+struct v4l2_tvnorm {
+	char          *name;
+	v4l2_std_id   id;
+
+	void          *priv_data;
+};
+
+struct video_device
+{
+	/* device ops */
+	const struct file_operations *fops;
+
+	/* device info */
+	struct device *dev;
+	char name[32];
+	int type;       /* v4l1 */
+	int type2;      /* v4l2 */
+	int hardware;
+	int minor;
+
+	int debug;	/* Activates debug level*/
+
+	/* Video standard vars */
+	int tvnormsize;	/* Size of tvnorm array */
+	v4l2_std_id current_norm; /* Current tvnorm */
+	struct v4l2_tvnorm *tvnorms;
+
+	/* callbacks */
+	void (*release)(struct video_device *vfd);
+
+	/* ioctl callbacks */
+
+	/* VIDIOC_QUERYCAP handler */
+	int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap);
+
+	/* Priority handling */
+	int (*vidioc_g_priority)   (struct file *file, void *fh,
+				    enum v4l2_priority *p);
+	int (*vidioc_s_priority)   (struct file *file, void *fh,
+				    enum v4l2_priority p);
+
+	/* VIDIOC_ENUM_FMT handlers */
+	int (*vidioc_enum_fmt_cap)         (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_overlay)     (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_vbi)         (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_vbi_capture) (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_video_output)(struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_vbi_output)  (struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
+	int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f);
+
+	/* VIDIOC_G_FMT handlers */
+	int (*vidioc_g_fmt_cap)        (struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_g_fmt_overlay)    (struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_g_fmt_vbi)        (struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_g_fmt_vbi_output) (struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_g_fmt_vbi_capture)(struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_g_fmt_video_output)(struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
+					struct v4l2_format *f);
+
+	/* VIDIOC_S_FMT handlers */
+	int (*vidioc_s_fmt_cap)        (struct file *file, void *fh,
+					struct v4l2_format *f);
+
+	int (*vidioc_s_fmt_overlay)    (struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_s_fmt_vbi)        (struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_s_fmt_vbi_output) (struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_s_fmt_vbi_capture)(struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_s_fmt_video_output)(struct file *file, void *fh,
+					struct v4l2_format *f);
+	int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
+					struct v4l2_format *f);
+
+	/* VIDIOC_TRY_FMT handlers */
+	int (*vidioc_try_fmt_cap)        (struct file *file, void *fh,
+					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_overlay)    (struct file *file, void *fh,
+					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_vbi)        (struct file *file, void *fh,
+					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_vbi_output) (struct file *file, void *fh,
+					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_vbi_capture)(struct file *file, void *fh,
+					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_video_output)(struct file *file, void *fh,
+					  struct v4l2_format *f);
+	int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
+					  struct v4l2_format *f);
+
+	/* Buffer handlers */
+	int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
+	int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b);
+	int (*vidioc_qbuf)    (struct file *file, void *fh, struct v4l2_buffer *b);
+	int (*vidioc_dqbuf)   (struct file *file, void *fh, struct v4l2_buffer *b);
+
+
+	int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i);
+#ifdef HAVE_V4L1
+			/* buffer type is struct vidio_mbuf * */
+	int (*vidiocgmbuf)  (struct file *file, void *fh, struct video_mbuf *p);
+#endif
+	int (*vidioc_g_fbuf)   (struct file *file, void *fh,
+				struct v4l2_framebuffer *a);
+	int (*vidioc_s_fbuf)   (struct file *file, void *fh,
+				struct v4l2_framebuffer *a);
+
+		/* Stream on/off */
+	int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
+	int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i);
+
+		/* Standard handling
+			G_STD and ENUMSTD are handled by videodev.c
+		 */
+	int (*vidioc_s_std)    (struct file *file, void *fh, v4l2_std_id a);
+	int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a);
+
+		/* Input handling */
+	int (*vidioc_enum_input)(struct file *file, void *fh,
+				 struct v4l2_input *inp);
+	int (*vidioc_g_input)   (struct file *file, void *fh, unsigned int *i);
+	int (*vidioc_s_input)   (struct file *file, void *fh, unsigned int i);
+
+		/* Output handling */
+	int (*vidioc_enumoutput) (struct file *file, void *fh,
+				  struct v4l2_output *a);
+	int (*vidioc_g_output)   (struct file *file, void *fh, unsigned int *i);
+	int (*vidioc_s_output)   (struct file *file, void *fh, unsigned int i);
+
+		/* Control handling */
+	int (*vidioc_queryctrl)        (struct file *file, void *fh,
+					struct v4l2_queryctrl *a);
+	int (*vidioc_g_ctrl)           (struct file *file, void *fh,
+					struct v4l2_control *a);
+	int (*vidioc_s_ctrl)           (struct file *file, void *fh,
+					struct v4l2_control *a);
+	int (*vidioc_g_ext_ctrls)      (struct file *file, void *fh,
+					struct v4l2_ext_controls *a);
+	int (*vidioc_s_ext_ctrls)      (struct file *file, void *fh,
+					struct v4l2_ext_controls *a);
+	int (*vidioc_try_ext_ctrls)    (struct file *file, void *fh,
+					struct v4l2_ext_controls *a);
+	int (*vidioc_querymenu)        (struct file *file, void *fh,
+					struct v4l2_querymenu *a);
+
+	/* Audio ioctls */
+	int (*vidioc_enumaudio)        (struct file *file, void *fh,
+					struct v4l2_audio *a);
+	int (*vidioc_g_audio)          (struct file *file, void *fh,
+					struct v4l2_audio *a);
+	int (*vidioc_s_audio)          (struct file *file, void *fh,
+					struct v4l2_audio *a);
+
+	/* Audio out ioctls */
+	int (*vidioc_enumaudout)       (struct file *file, void *fh,
+					struct v4l2_audioout *a);
+	int (*vidioc_g_audout)         (struct file *file, void *fh,
+					struct v4l2_audioout *a);
+	int (*vidioc_s_audout)         (struct file *file, void *fh,
+					struct v4l2_audioout *a);
+	int (*vidioc_g_modulator)      (struct file *file, void *fh,
+					struct v4l2_modulator *a);
+	int (*vidioc_s_modulator)      (struct file *file, void *fh,
+					struct v4l2_modulator *a);
+	/* Crop ioctls */
+	int (*vidioc_cropcap)          (struct file *file, void *fh,
+					struct v4l2_cropcap *a);
+	int (*vidioc_g_crop)           (struct file *file, void *fh,
+					struct v4l2_crop *a);
+	int (*vidioc_s_crop)           (struct file *file, void *fh,
+					struct v4l2_crop *a);
+	/* Compression ioctls */
+	int (*vidioc_g_mpegcomp)       (struct file *file, void *fh,
+					struct v4l2_mpeg_compression *a);
+	int (*vidioc_s_mpegcomp)       (struct file *file, void *fh,
+					struct v4l2_mpeg_compression *a);
+	int (*vidioc_g_jpegcomp)       (struct file *file, void *fh,
+					struct v4l2_jpegcompression *a);
+	int (*vidioc_s_jpegcomp)       (struct file *file, void *fh,
+					struct v4l2_jpegcompression *a);
+
+	/* Stream type-dependent parameter ioctls */
+	int (*vidioc_g_parm)           (struct file *file, void *fh,
+					struct v4l2_streamparm *a);
+	int (*vidioc_s_parm)           (struct file *file, void *fh,
+					struct v4l2_streamparm *a);
+
+	/* Tuner ioctls */
+	int (*vidioc_g_tuner)          (struct file *file, void *fh,
+					struct v4l2_tuner *a);
+	int (*vidioc_s_tuner)          (struct file *file, void *fh,
+					struct v4l2_tuner *a);
+	int (*vidioc_g_frequency)      (struct file *file, void *fh,
+					struct v4l2_frequency *a);
+	int (*vidioc_s_frequency)      (struct file *file, void *fh,
+					struct v4l2_frequency *a);
+
+	/* Sliced VBI cap */
+	int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh,
+					struct v4l2_sliced_vbi_cap *a);
+
+	/* Log status ioctl */
+	int (*vidioc_log_status)       (struct file *file, void *fh);
+
+
+#ifdef OBSOLETE_OWNER /* to be removed soon */
+/* obsolete -- fops->owner is used instead */
+struct module *owner;
+/* dev->driver_data will be used instead some day.
+	* Use the video_{get|set}_drvdata() helper functions,
+	* so the switch over will be transparent for you.
+	* Or use {pci|usb}_{get|set}_drvdata() directly. */
+void *priv;
+#endif
+
+	/* for videodev.c intenal usage -- please don't touch */
+	int users;                     /* video_exclusive_{open|close} ... */
+	struct mutex lock;             /* ... helper function uses these   */
+	char devfs_name[64];           /* devfs */
+	struct class_device class_dev; /* sysfs */
+};
+
+/* Version 2 functions */
+extern int video_register_device(struct video_device *vfd, int type, int nr);
+void video_unregister_device(struct video_device *);
+extern int video_ioctl2(struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg);
+
+/* helper functions to alloc / release struct video_device, the
+   later can be used for video_device->release() */
+struct video_device *video_device_alloc(void);
+void video_device_release(struct video_device *vfd);
+
+/* Include support for obsoleted stuff */
+extern int video_usercopy(struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg,
+			  int (*func)(struct inode *inode, struct file *file,
+				      unsigned int cmd, void *arg));
+
+
+#ifdef HAVE_V4L1
+#include <linux/mm.h>
+
+extern struct video_device* video_devdata(struct file*);
+
+#define to_video_device(cd) container_of(cd, struct video_device, class_dev)
+static inline void
+video_device_create_file(struct video_device *vfd,
+			 struct class_device_attribute *attr)
+{
+	class_device_create_file(&vfd->class_dev, attr);
+}
+static inline void
+video_device_remove_file(struct video_device *vfd,
+			 struct class_device_attribute *attr)
+{
+	class_device_remove_file(&vfd->class_dev, attr);
+}
+
+#ifdef OBSOLETE_OWNER /* to be removed soon */
+/* helper functions to access driver private data. */
+static inline void *video_get_drvdata(struct video_device *dev)
+{
+	return dev->priv;
+}
+
+static inline void video_set_drvdata(struct video_device *dev, void *data)
+{
+	dev->priv = data;
+}
+#endif
+
+extern int video_exclusive_open(struct inode *inode, struct file *file);
+extern int video_exclusive_release(struct inode *inode, struct file *file);
+#endif /* HAVE_V4L1 */
+
+#endif /* _V4L2_DEV_H */
diff --git a/include/media/video-buf-dvb.h b/include/media/video-buf-dvb.h
index b78d90f..8233caf 100644
--- a/include/media/video-buf-dvb.h
+++ b/include/media/video-buf-dvb.h
@@ -26,7 +26,8 @@
 
 int videobuf_dvb_register(struct videobuf_dvb *dvb,
 			  struct module *module,
-			  void *adapter_priv);
+			  void *adapter_priv,
+			  struct device *device);
 void videobuf_dvb_unregister(struct videobuf_dvb *dvb);
 
 /*
diff --git a/include/media/video-buf.h b/include/media/video-buf.h
index fff3fd0..1115a25 100644
--- a/include/media/video-buf.h
+++ b/include/media/video-buf.h
@@ -23,6 +23,7 @@
  */
 
 #include <linux/videodev2.h>
+#include <linux/poll.h>
 
 #define UNSET (-1U)
 
diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index b5994ea..31329fc 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -7,8 +7,9 @@
 #ifndef __MTD_ABI_H__
 #define __MTD_ABI_H__
 
-#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into
-		    separate files was to avoid #ifdef __KERNEL__ */
+#ifndef __KERNEL__ 
+/* Urgh. The whole point of splitting this out into
+   separate files was to avoid #ifdef __KERNEL__ */
 #define __user
 #endif
 
@@ -28,28 +29,17 @@
 #define MTD_ROM			2
 #define MTD_NORFLASH		3
 #define MTD_NANDFLASH		4
-#define MTD_PEROM		5
 #define MTD_DATAFLASH		6
-#define MTD_OTHER		14
-#define MTD_UNKNOWN		15
 
-#define MTD_CLEAR_BITS		1       // Bits can be cleared (flash)
-#define MTD_SET_BITS		2       // Bits can be set
-#define MTD_ERASEABLE		4       // Has an erase function
-#define MTD_WRITEB_WRITEABLE	8       // Direct IO is possible
-#define MTD_VOLATILE		16      // Set for RAMs
-#define MTD_XIP			32	// eXecute-In-Place possible
-#define MTD_OOB			64	// Out-of-band data (NAND flash)
-#define MTD_ECC			128	// Device capable of automatic ECC
-#define MTD_NO_VIRTBLOCKS	256	// Virtual blocks not allowed
-#define MTD_PROGRAM_REGIONS	512	// Configurable Programming Regions
+#define MTD_WRITEABLE		0x400	/* Device is writeable */
+#define MTD_BIT_WRITEABLE	0x800	/* Single bits can be flipped */
+#define MTD_NO_ERASE		0x1000	/* No erase necessary */
 
 // Some common devices / combinations of capabilities
 #define MTD_CAP_ROM		0
-#define MTD_CAP_RAM		(MTD_CLEAR_BITS|MTD_SET_BITS|MTD_WRITEB_WRITEABLE)
-#define MTD_CAP_NORFLASH        (MTD_CLEAR_BITS|MTD_ERASEABLE)
-#define MTD_CAP_NANDFLASH       (MTD_CLEAR_BITS|MTD_ERASEABLE|MTD_OOB)
-#define MTD_WRITEABLE		(MTD_CLEAR_BITS|MTD_SET_BITS)
+#define MTD_CAP_RAM		(MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
+#define MTD_CAP_NORFLASH	(MTD_WRITEABLE | MTD_BIT_WRITEABLE)
+#define MTD_CAP_NANDFLASH	(MTD_WRITEABLE)
 
 
 // Types of automatic ECC/Checksum available
@@ -74,7 +64,7 @@
 	uint32_t flags;
 	uint32_t size;	 // Total size of the MTD
 	uint32_t erasesize;
-	uint32_t oobblock;  // Size of OOB blocks (e.g. 512)
+	uint32_t writesize;
 	uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
 	uint32_t ecctype;
 	uint32_t eccsize;
@@ -94,12 +84,12 @@
 	uint32_t locked;
 };
 
-#define MEMGETINFO              _IOR('M', 1, struct mtd_info_user)
-#define MEMERASE                _IOW('M', 2, struct erase_info_user)
-#define MEMWRITEOOB             _IOWR('M', 3, struct mtd_oob_buf)
-#define MEMREADOOB              _IOWR('M', 4, struct mtd_oob_buf)
-#define MEMLOCK                 _IOW('M', 5, struct erase_info_user)
-#define MEMUNLOCK               _IOW('M', 6, struct erase_info_user)
+#define MEMGETINFO		_IOR('M', 1, struct mtd_info_user)
+#define MEMERASE		_IOW('M', 2, struct erase_info_user)
+#define MEMWRITEOOB		_IOWR('M', 3, struct mtd_oob_buf)
+#define MEMREADOOB		_IOWR('M', 4, struct mtd_oob_buf)
+#define MEMLOCK			_IOW('M', 5, struct erase_info_user)
+#define MEMUNLOCK		_IOW('M', 6, struct erase_info_user)
 #define MEMGETREGIONCOUNT	_IOR('M', 7, int)
 #define MEMGETREGIONINFO	_IOWR('M', 8, struct region_info_user)
 #define MEMSETOOBSEL		_IOW('M', 9, struct nand_oobinfo)
@@ -109,8 +99,15 @@
 #define OTPSELECT		_IOR('M', 13, int)
 #define OTPGETREGIONCOUNT	_IOW('M', 14, int)
 #define OTPGETREGIONINFO	_IOW('M', 15, struct otp_info)
-#define OTPLOCK		_IOR('M', 16, struct otp_info)
+#define OTPLOCK			_IOR('M', 16, struct otp_info)
+#define ECCGETLAYOUT		_IOR('M', 17, struct nand_ecclayout)
+#define ECCGETSTATS		_IOR('M', 18, struct mtd_ecc_stats)
+#define MTDFILEMODE		_IO('M', 19)
 
+/*
+ * Obsolete legacy interface. Keep it in order not to break userspace
+ * interfaces
+ */
 struct nand_oobinfo {
 	uint32_t useecc;
 	uint32_t eccbytes;
@@ -118,4 +115,46 @@
 	uint32_t eccpos[32];
 };
 
+struct nand_oobfree {
+	uint32_t offset;
+	uint32_t length;
+};
+
+#define MTD_MAX_OOBFREE_ENTRIES	8
+/*
+ * ECC layout control structure. Exported to userspace for
+ * diagnosis and to allow creation of raw images
+ */
+struct nand_ecclayout {
+	uint32_t eccbytes;
+	uint32_t eccpos[64];
+	uint32_t oobavail;
+	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
+};
+
+/**
+ * struct mtd_ecc_stats - error correction status
+ *
+ * @corrected:	number of corrected bits
+ * @failed:	number of uncorrectable errors
+ * @badblocks:	number of bad blocks in this partition
+ * @bbtblocks:	number of blocks reserved for bad block tables
+ */
+struct mtd_ecc_stats {
+	uint32_t corrected;
+	uint32_t failed;
+	uint32_t badblocks;
+	uint32_t bbtblocks;
+};
+
+/*
+ * Read/write file modes for access to MTD
+ */
+enum mtd_file_modes {
+	MTD_MODE_NORMAL = MTD_OTP_OFF,
+	MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
+	MTD_MODE_OTP_USER = MTD_OTP_USER,
+	MTD_MODE_RAW,
+};
+
 #endif /* __MTD_ABI_H__ */
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h
index 1c13fc7..713f34d 100644
--- a/include/mtd/mtd-user.h
+++ b/include/mtd/mtd-user.h
@@ -16,5 +16,6 @@
 typedef struct erase_info_user erase_info_t;
 typedef struct region_info_user region_info_t;
 typedef struct nand_oobinfo nand_oobinfo_t;
+typedef struct nand_ecclayout nand_ecclayout_t;
 
 #endif /* __MTD_USER_H__ */
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 750e250..3d71251 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -45,7 +45,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/netdevice.h>
 #include <net/if_inet6.h>
 #include <net/ipv6.h>
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 427dac9..795f81f 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -1,7 +1,6 @@
 #ifndef __LINUX_NET_AFUNIX_H
 #define __LINUX_NET_AFUNIX_H
 
-#include <linux/config.h>
 #include <linux/socket.h>
 #include <linux/un.h>
 #include <linux/mutex.h>
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 5bd9974..7cd528e 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -6,7 +6,6 @@
 #ifndef _AX25_H
 #define _AX25_H 
 
-#include <linux/config.h>
 #include <linux/ax25.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
diff --git a/include/net/compat.h b/include/net/compat.h
index e65cbed..9859b60 100644
--- a/include/net/compat.h
+++ b/include/net/compat.h
@@ -1,7 +1,6 @@
 #ifndef NET_COMPAT_H
 #define NET_COMPAT_H
 
-#include <linux/config.h>
 
 struct sock;
 
diff --git a/include/net/dst.h b/include/net/dst.h
index 5161e89..36d54fc 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -8,7 +8,6 @@
 #ifndef _NET_DST_H
 #define _NET_DST_H
 
-#include <linux/config.h>
 #include <linux/netdevice.h>
 #include <linux/rtnetlink.h>
 #include <linux/rcupdate.h>
diff --git a/include/net/icmp.h b/include/net/icmp.h
index e7c3f20..05f8ff7 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -18,7 +18,6 @@
 #ifndef _ICMP_H
 #define	_ICMP_H
 
-#include <linux/config.h>
 #include <linux/icmp.h>
 
 #include <net/inet_sock.h>
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h
index d5926bf..ecc4286 100644
--- a/include/net/ieee80211.h
+++ b/include/net/ieee80211.h
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>	/* ARRAY_SIZE */
 #include <linux/wireless.h>
 
-#define IEEE80211_VERSION "git-1.1.7"
+#define IEEE80211_VERSION "git-1.1.13"
 
 #define IEEE80211_DATA_LEN		2304
 /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
@@ -104,6 +104,9 @@
 #define IEEE80211_SCTL_FRAG		0x000F
 #define IEEE80211_SCTL_SEQ		0xFFF0
 
+/* QOS control */
+#define IEEE80211_QCTL_TID		0x000F
+
 /* debug macros */
 
 #ifdef CONFIG_IEEE80211_DEBUG
@@ -965,6 +968,7 @@
 
 enum {
 	IEEE80211_CH_PASSIVE_ONLY = (1 << 0),
+	IEEE80211_CH_80211H_RULES = (1 << 1),
 	IEEE80211_CH_B_ONLY = (1 << 2),
 	IEEE80211_CH_NO_IBSS = (1 << 3),
 	IEEE80211_CH_UNIFORM_SPREADING = (1 << 4),
@@ -973,10 +977,10 @@
 };
 
 struct ieee80211_channel {
-	u32 freq;
+	u32 freq;	/* in MHz */
 	u8 channel;
 	u8 flags;
-	u8 max_power;
+	u8 max_power;	/* in dBm */
 };
 
 struct ieee80211_geo {
@@ -1075,6 +1079,7 @@
 
 	int (*handle_management) (struct net_device * dev,
 				  struct ieee80211_network * network, u16 type);
+	int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb);
 
 	/* Typical STA methods */
 	int (*handle_auth) (struct net_device * dev,
@@ -1243,7 +1248,8 @@
 extern int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
 extern void ieee80211_txb_free(struct ieee80211_txb *);
 extern int ieee80211_tx_frame(struct ieee80211_device *ieee,
-			      struct ieee80211_hdr *frame, int len);
+			      struct ieee80211_hdr *frame, int hdr_len,
+			      int total_len, int encrypt_mpdu);
 
 /* ieee80211_rx.c */
 extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index 052ed59..7a483ab 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -86,6 +86,9 @@
 	
 	/* BSSID we're trying to associate to */
 	char bssid[ETH_ALEN];
+
+	/* Rates supported by the network */
+	struct ieee80211softmac_ratesinfo supported_rates;
 	
 	/* some flags.
 	 * static_essid is valid if the essid is constant,
@@ -132,23 +135,26 @@
 struct ieee80211softmac_txrates {
 	/* The Bit-Rate to be used for multicast frames. */
 	u8 mcast_rate;
-	/* The Bit-Rate to be used for multicast fallback
-	 * (If the device supports fallback and hardware-retry)
-	 */
-	u8 mcast_fallback;
+
+	/* The Bit-Rate to be used for multicast management frames. */
+	u8 mgt_mcast_rate;
+
 	/* The Bit-Rate to be used for any other (normal) data packet. */
 	u8 default_rate;
 	/* The Bit-Rate to be used for default fallback
 	 * (If the device supports fallback and hardware-retry)
 	 */
 	u8 default_fallback;
+
+	/* This is the rate that the user asked for */
+	u8 user_rate;
 };
 
 /* Bits for txrates_change callback. */
 #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT		(1 << 0) /* default_rate */
 #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK	(1 << 1) /* default_fallback */
 #define IEEE80211SOFTMAC_TXRATECHG_MCAST		(1 << 2) /* mcast_rate */
-#define IEEE80211SOFTMAC_TXRATECHG_MCAST_FBACK		(1 << 3) /* mcast_fallback */
+#define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST		(1 << 3) /* mgt_mcast_rate */
 
 struct ieee80211softmac_device {
 	/* 802.11 structure for data stuff */
@@ -250,6 +256,28 @@
  * Note that the rates need to be sorted. */
 extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
 
+/* Helper function which advises you the rate at which a frame should be
+ * transmitted at. */
+static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
+						 int is_multicast,
+						 int is_mgt)
+{
+	struct ieee80211softmac_txrates *txrates = &mac->txrates;
+
+	if (!mac->associated)
+		return txrates->mgt_mcast_rate;
+
+	/* We are associated, sending unicast frame */
+	if (!is_multicast)
+		return txrates->default_rate;
+
+	/* We are associated, sending multicast frame */
+	if (is_mgt)
+		return txrates->mgt_mcast_rate;
+	else
+		return txrates->mcast_rate;
+}
+
 /* Start the SoftMAC. Call this after you initialized the device
  * and it is ready to run.
  */
@@ -282,7 +310,7 @@
  *	- context set to the context data you want passed
  * The return value is 0, or an error.
  */
-typedef void (*notify_function_ptr)(struct net_device *dev, void *context);
+typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context);
 
 #define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL);
 #define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC);
diff --git a/include/net/ieee80211softmac_wx.h b/include/net/ieee80211softmac_wx.h
index 3e0be45..4ee3ad5 100644
--- a/include/net/ieee80211softmac_wx.h
+++ b/include/net/ieee80211softmac_wx.h
@@ -91,4 +91,9 @@
 			      struct iw_request_info *info,
 			      union iwreq_data *wrqu,
 			      char *extra);
+extern int
+ieee80211softmac_wx_set_mlme(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra);
 #endif /* _IEEE80211SOFTMAC_WX */
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index 59f0c83..bc6a71d 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -14,7 +14,6 @@
 #ifndef _INET6_HASHTABLES_H
 #define _INET6_HASHTABLES_H
 
-#include <linux/config.h>
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/in6.h>
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 135d80f..98e0bb3 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -14,7 +14,6 @@
 #ifndef _INET_HASHTABLES_H
 #define _INET_HASHTABLES_H
 
-#include <linux/config.h>
 
 #include <linux/interrupt.h>
 #include <linux/ipv6.h>
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 883eb52..1f4a9a6 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -16,7 +16,6 @@
 #ifndef _INET_SOCK_H
 #define _INET_SOCK_H
 
-#include <linux/config.h>
 
 #include <linux/string.h>
 #include <linux/types.h>
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index e837f98..600cb54 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -15,7 +15,6 @@
 #ifndef _INET_TIMEWAIT_SOCK_
 #define _INET_TIMEWAIT_SOCK_
 
-#include <linux/config.h>
 
 #include <linux/list.h>
 #include <linux/module.h>
diff --git a/include/net/ip.h b/include/net/ip.h
index 3d2e5ca..98f9084 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -22,7 +22,6 @@
 #ifndef _IP_H
 #define _IP_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/ip.h>
 #include <linux/in.h>
@@ -147,7 +146,6 @@
 struct ipv4_config
 {
 	int	log_martians;
-	int	autoconfig;
 	int	no_pmtu_disc;
 };
 
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index e000fa2..a095d1d 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -16,7 +16,6 @@
 #ifndef _NET_IP_FIB_H
 #define _NET_IP_FIB_H
 
-#include <linux/config.h>
 #include <net/flow.h>
 #include <linux/seq_file.h>
 
diff --git a/include/net/ip_mp_alg.h b/include/net/ip_mp_alg.h
index 7722573..ac747b6 100644
--- a/include/net/ip_mp_alg.h
+++ b/include/net/ip_mp_alg.h
@@ -7,7 +7,6 @@
 #ifndef _NET_IP_MP_ALG_H
 #define _NET_IP_MP_ALG_H
 
-#include <linux/config.h>
 #include <linux/ip_mp_alg.h>
 #include <net/flow.h>
 #include <net/route.h>
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 7d2674f..3b57b15 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -248,7 +248,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/list.h>                 /* for struct list_head */
 #include <linux/spinlock.h>             /* for struct rwlock_t */
 #include <asm/atomic.h>                 /* for struct atomic_t */
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 4abedb8..a8fdf79 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -104,7 +104,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <net/sock.h>
 
 /* sysctls */
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 1880e46..1cb0607 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -26,7 +26,6 @@
 #ifndef NET_IRDA_H
 #define NET_IRDA_H
 
-#include <linux/config.h>
 #include <linux/skbuff.h>		/* struct sk_buff */
 #include <linux/kernel.h>
 #include <linux/if.h>			/* sa_family_t in <linux/irda.h> */
diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
index 92c8280..0575c59 100644
--- a/include/net/irda/irda_device.h
+++ b/include/net/irda/irda_device.h
@@ -39,7 +39,6 @@
 #ifndef IRDA_DEVICE_H
 #define IRDA_DEVICE_H
 
-#include <linux/config.h>
 #include <linux/tty.h>
 #include <linux/netdevice.h>
 #include <linux/spinlock.h>
diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h
index 2127cae..e77eb88 100644
--- a/include/net/irda/irlap.h
+++ b/include/net/irda/irlap.h
@@ -27,7 +27,6 @@
 #ifndef IRLAP_H
 #define IRLAP_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index c0c895d..11ecfa5 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -29,7 +29,6 @@
 
 #include <asm/param.h>  /* for HZ */
 
-#include <linux/config.h>
 #include <linux/types.h>
 
 #include <net/irda/irda.h>
diff --git a/include/net/irda/irlmp_frame.h b/include/net/irda/irlmp_frame.h
index eb3ad15..c463f8b 100644
--- a/include/net/irda/irlmp_frame.h
+++ b/include/net/irda/irlmp_frame.h
@@ -26,7 +26,6 @@
 #ifndef IRMLP_FRAME_H
 #define IRMLP_FRAME_H
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 #include <net/irda/discovery.h>
diff --git a/include/net/irda/qos.h b/include/net/irda/qos.h
index 9ae3d6b..cc577dc 100644
--- a/include/net/irda/qos.h
+++ b/include/net/irda/qos.h
@@ -31,7 +31,6 @@
 #ifndef IRDA_QOS_H
 #define IRDA_QOS_H
 
-#include <linux/config.h>
 #include <linux/skbuff.h>
 
 #include <net/irda/parameters.h>
diff --git a/include/net/llc_if.h b/include/net/llc_if.h
index 090eaa0..c608812 100644
--- a/include/net/llc_if.h
+++ b/include/net/llc_if.h
@@ -16,6 +16,7 @@
 #include <linux/if.h>
 #include <linux/if_arp.h>
 #include <linux/llc.h>
+#include <linux/etherdevice.h>
 #include <net/llc.h>
 
 #define LLC_DATAUNIT_PRIM	1
@@ -61,8 +62,6 @@
 #define LLC_STATUS_CONFLICT	7 /* disconnect conn */
 #define LLC_STATUS_RESET_DONE	8 /*  */
 
-extern u8 llc_mac_null_var[IFHWADDRLEN];
-
 /**
  *      llc_mac_null - determines if a address is a null mac address
  *      @mac: Mac address to test if null.
@@ -70,16 +69,20 @@
  *      Determines if a given address is a null mac address.  Returns 0 if the
  *      address is not a null mac, 1 if the address is a null mac.
  */
-static __inline__ int llc_mac_null(u8 *mac)
+static inline int llc_mac_null(const u8 *mac)
 {
-	return !memcmp(mac, llc_mac_null_var, IFHWADDRLEN);
+	return is_zero_ether_addr(mac);
 }
 
-static __inline__ int llc_addrany(struct llc_addr *addr)
+static inline int llc_addrany(const struct llc_addr *addr)
 {
 	return llc_mac_null(addr->mac) && !addr->lsap;
 }
 
+static inline int llc_mac_multicast(const u8 *mac)
+{
+	return is_multicast_ether_addr(mac);
+}
 /**
  *	llc_mac_match - determines if two mac addresses are the same
  *	@mac1: First mac address to compare.
@@ -89,9 +92,9 @@
  *	is not a complete match up to len, 1 if a complete match up to len is
  *	found.
  */
-static __inline__ int llc_mac_match(u8 *mac1, u8 *mac2)
+static inline int llc_mac_match(const u8 *mac1, const u8 *mac2)
 {
-	return !memcmp(mac1, mac2, IFHWADDRLEN);
+	return !compare_ether_addr(mac1, mac2);
 }
 
 extern int llc_establish_connection(struct sock *sk, u8 *lmac,
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 91fa271..d3915dab 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -37,7 +37,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 #include <linux/compiler.h>
 #include <linux/icmpv6.h>
 #include <linux/in6.h>
diff --git a/include/net/netdma.h b/include/net/netdma.h
new file mode 100644
index 0000000..19760eb
--- /dev/null
+++ b/include/net/netdma.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+#ifndef NETDMA_H
+#define NETDMA_H
+#include <linux/config.h>
+#ifdef CONFIG_NET_DMA
+#include <linux/dmaengine.h>
+#include <linux/skbuff.h>
+
+static inline struct dma_chan *get_softnet_dma(void)
+{
+	struct dma_chan *chan;
+	rcu_read_lock();
+	chan = rcu_dereference(__get_cpu_var(softnet_data.net_dma));
+	if (chan)
+		dma_chan_get(chan);
+	rcu_read_unlock();
+	return chan;
+}
+
+int dma_skb_copy_datagram_iovec(struct dma_chan* chan,
+		const struct sk_buff *skb, int offset, struct iovec *to,
+		size_t len, struct dma_pinned_list *pinned_list);
+
+#endif /* CONFIG_NET_DMA */
+#endif /* NETDMA_H */
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 916013c..1fbd819 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -15,7 +15,6 @@
 #include <linux/netfilter/nf_conntrack_common.h>
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 #include <linux/bitops.h>
 #include <linux/compiler.h>
 #include <asm/atomic.h>
@@ -114,6 +113,10 @@
 	u_int32_t mark;
 #endif
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+	u_int32_t secmark;
+#endif
+
 	/* Storage reserved for other modules: */
 	union nf_conntrack_proto proto;
 
@@ -285,6 +288,7 @@
 }
 
 extern unsigned int nf_conntrack_htable_size;
+extern int nf_conntrack_checksum;
 
 #define NF_CT_STAT_INC(count) (__get_cpu_var(nf_conntrack_stat).count++)
 
diff --git a/include/net/netfilter/nf_conntrack_compat.h b/include/net/netfilter/nf_conntrack_compat.h
index 3cac19f..f1b1482 100644
--- a/include/net/netfilter/nf_conntrack_compat.h
+++ b/include/net/netfilter/nf_conntrack_compat.h
@@ -20,6 +20,19 @@
 }
 #endif /* CONFIG_IP_NF_CONNTRACK_MARK */
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+					   u_int32_t *ctinfo)
+{
+	struct ip_conntrack *ct = ip_conntrack_get(skb, ctinfo);
+
+	if (ct)
+		return &ct->secmark;
+	else
+		return NULL;
+}
+#endif /* CONFIG_IP_NF_CONNTRACK_SECMARK */
+
 #ifdef CONFIG_IP_NF_CT_ACCT
 static inline struct ip_conntrack_counter *
 nf_ct_get_counters(const struct sk_buff *skb)
@@ -70,6 +83,19 @@
 }
 #endif /* CONFIG_NF_CONNTRACK_MARK */
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+static inline u_int32_t *nf_ct_get_secmark(const struct sk_buff *skb,
+					   u_int32_t *ctinfo)
+{
+	struct nf_conn *ct = nf_ct_get(skb, ctinfo);
+
+	if (ct)
+		return &ct->secmark;
+	else
+		return NULL;
+}
+#endif /* CONFIG_NF_CONNTRACK_MARK */
+
 #ifdef CONFIG_NF_CT_ACCT
 static inline struct ip_conntrack_counter *
 nf_ct_get_counters(const struct sk_buff *skb)
diff --git a/include/net/pkt_act.h b/include/net/pkt_act.h
index b225d84..cf5e4d2 100644
--- a/include/net/pkt_act.h
+++ b/include/net/pkt_act.h
@@ -4,7 +4,6 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <linux/bitops.h>
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index b94d1ad..75b5b93 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -218,12 +218,13 @@
 		struct rtattr *tab);
 extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
 
-extern int qdisc_restart(struct net_device *dev);
+extern void __qdisc_run(struct net_device *dev);
 
 static inline void qdisc_run(struct net_device *dev)
 {
-	while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0)
-		/* NOTHING */;
+	if (!netif_queue_stopped(dev) &&
+	    !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
+		__qdisc_run(dev);
 }
 
 extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 6dc5970..3b6dc15 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -24,7 +24,6 @@
 #ifndef _PROTOCOL_H
 #define _PROTOCOL_H
 
-#include <linux/config.h>
 #include <linux/in6.h>
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/ipv6.h>
@@ -37,6 +36,7 @@
 struct net_protocol {
 	int			(*handler)(struct sk_buff *skb);
 	void			(*err_handler)(struct sk_buff *skb, u32 info);
+	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb, int sg);
 	int			no_policy;
 };
 
diff --git a/include/net/raw.h b/include/net/raw.h
index e67b28a..e4af597 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -17,7 +17,6 @@
 #ifndef _RAW_H
 #define _RAW_H
 
-#include <linux/config.h>
 
 #include <net/protocol.h>
 
@@ -36,7 +35,7 @@
 
 
 extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
-				    unsigned long raddr, unsigned long laddr,
+				    __be32 raddr, __be32 laddr,
 				    int dif);
 
 extern int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash);
diff --git a/include/net/red.h b/include/net/red.h
index 2ed4358..5ccdbb3 100644
--- a/include/net/red.h
+++ b/include/net/red.h
@@ -1,7 +1,6 @@
 #ifndef __NET_SCHED_RED_H
 #define __NET_SCHED_RED_H
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <net/pkt_sched.h>
 #include <net/inet_ecn.h>
diff --git a/include/net/route.h b/include/net/route.h
index 98c915a..c4a0686 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -24,7 +24,6 @@
 #ifndef _ROUTE_H
 #define _ROUTE_H
 
-#include <linux/config.h>
 #include <net/dst.h>
 #include <net/inetpeer.h>
 #include <net/flow.h>
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 7b6ec99..b0e9108 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -1,7 +1,6 @@
 #ifndef __NET_SCHED_GENERIC_H
 #define __NET_SCHED_GENERIC_H
 
-#include <linux/config.h>
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/rcupdate.h>
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index aa6033c..a9663b4 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -63,7 +63,6 @@
  */
 
 
-#include <linux/config.h>
 
 #ifdef TEST_FRAME
 #undef CONFIG_PROC_FS
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7f4fea1..5f69158 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -555,7 +555,8 @@
 	int		(*to_addr_param) (const union sctp_addr *,
 					  union sctp_addr_param *); 
 	int		(*addr_valid)	(union sctp_addr *,
-					 struct sctp_sock *);
+					 struct sctp_sock *,
+					 const struct sk_buff *);
 	sctp_scope_t	(*scope) (union sctp_addr *);
 	void		(*inaddr_any)	(union sctp_addr *, unsigned short);
 	int		(*is_any)	(const union sctp_addr *);
diff --git a/include/net/sock.h b/include/net/sock.h
index c9fad6f..2d8d6ad 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -40,7 +40,6 @@
 #ifndef _SOCK_H
 #define _SOCK_H
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/cache.h>
@@ -132,6 +131,7 @@
   *	@sk_receive_queue: incoming packets
   *	@sk_wmem_alloc: transmit queue bytes committed
   *	@sk_write_queue: Packet sending queue
+  *	@sk_async_wait_queue: DMA copied packets
   *	@sk_omem_alloc: "o" is "option" or "other"
   *	@sk_wmem_queued: persistent queue size
   *	@sk_forward_alloc: space allocated forward
@@ -205,6 +205,7 @@
 	atomic_t		sk_omem_alloc;
 	struct sk_buff_head	sk_receive_queue;
 	struct sk_buff_head	sk_write_queue;
+	struct sk_buff_head	sk_async_wait_queue;
 	int			sk_wmem_queued;
 	int			sk_forward_alloc;
 	gfp_t			sk_allocation;
@@ -871,10 +872,7 @@
 		if (filter) {
 			unsigned int pkt_len = sk_run_filter(skb, filter->insns,
 							     filter->len);
-			if (!pkt_len)
-				err = -EPERM;
-			else
-				skb_trim(skb, pkt_len);
+			err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
 		}
 
 		if (needlock)
@@ -1032,9 +1030,13 @@
 {
 	__sk_dst_set(sk, dst);
 	sk->sk_route_caps = dst->dev->features;
+	if (sk->sk_route_caps & NETIF_F_GSO)
+		sk->sk_route_caps |= NETIF_F_TSO;
 	if (sk->sk_route_caps & NETIF_F_TSO) {
 		if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
 			sk->sk_route_caps &= ~NETIF_F_TSO;
+		else 
+			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
 	}
 }
 
@@ -1267,15 +1269,27 @@
  * sk_eat_skb - Release a skb if it is no longer needed
  * @sk: socket to eat this skb from
  * @skb: socket buffer to eat
+ * @copied_early: flag indicating whether DMA operations copied this data early
  *
  * This routine must be called with interrupts disabled or with the socket
  * locked so that the sk_buff queue operation is ok.
 */
-static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
+#ifdef CONFIG_NET_DMA
+static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early)
+{
+	__skb_unlink(skb, &sk->sk_receive_queue);
+	if (!copied_early)
+		__kfree_skb(skb);
+	else
+		__skb_queue_tail(&sk->sk_async_wait_queue, skb);
+}
+#else
+static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early)
 {
 	__skb_unlink(skb, &sk->sk_receive_queue);
 	__kfree_skb(skb);
 }
+#endif
 
 extern void sock_enable_timestamp(struct sock *sk);
 extern int sock_get_timestamp(struct sock *, struct timeval __user *);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 3c989db..ca3d38d 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -21,13 +21,13 @@
 #define TCP_DEBUG 1
 #define FASTRETRANS_DEBUG 1
 
-#include <linux/config.h>
 #include <linux/list.h>
 #include <linux/tcp.h>
 #include <linux/slab.h>
 #include <linux/cache.h>
 #include <linux/percpu.h>
 #include <linux/skbuff.h>
+#include <linux/dmaengine.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/inet_timewait_sock.h>
@@ -218,6 +218,7 @@
 extern int sysctl_tcp_tw_reuse;
 extern int sysctl_tcp_frto;
 extern int sysctl_tcp_low_latency;
+extern int sysctl_tcp_dma_copybreak;
 extern int sysctl_tcp_nometrics_save;
 extern int sysctl_tcp_moderate_rcvbuf;
 extern int sysctl_tcp_tso_win_divisor;
@@ -225,6 +226,7 @@
 extern int sysctl_tcp_mtu_probing;
 extern int sysctl_tcp_base_mss;
 extern int sysctl_tcp_workaround_signed_windows;
+extern int sysctl_tcp_slow_start_after_idle;
 
 extern atomic_t tcp_memory_allocated;
 extern atomic_t tcp_sockets_allocated;
@@ -293,6 +295,8 @@
 
 extern void			tcp_rcv_space_adjust(struct sock *sk);
 
+extern void			tcp_cleanup_rbuf(struct sock *sk, int copied);
+
 extern int			tcp_twsk_unique(struct sock *sk,
 						struct sock *sktw, void *twp);
 
@@ -565,13 +569,13 @@
  */
 static inline int tcp_skb_pcount(const struct sk_buff *skb)
 {
-	return skb_shinfo(skb)->tso_segs;
+	return skb_shinfo(skb)->gso_segs;
 }
 
 /* This is valid iff tcp_skb_pcount() > 1. */
 static inline int tcp_skb_mss(const struct sk_buff *skb)
 {
-	return skb_shinfo(skb)->tso_size;
+	return skb_shinfo(skb)->gso_size;
 }
 
 static inline void tcp_dec_pcount_approx(__u32 *count,
@@ -628,7 +632,7 @@
 	/* return slow start threshold (required) */
 	u32 (*ssthresh)(struct sock *sk);
 	/* lower bound for congestion window (optional) */
-	u32 (*min_cwnd)(struct sock *sk);
+	u32 (*min_cwnd)(const struct sock *sk);
 	/* do new cwnd calculation (required) */
 	void (*cong_avoid)(struct sock *sk, u32 ack,
 			   u32 rtt, u32 in_flight, int good_ack);
@@ -663,7 +667,7 @@
 extern u32 tcp_reno_ssthresh(struct sock *sk);
 extern void tcp_reno_cong_avoid(struct sock *sk, u32 ack,
 				u32 rtt, u32 in_flight, int flag);
-extern u32 tcp_reno_min_cwnd(struct sock *sk);
+extern u32 tcp_reno_min_cwnd(const struct sock *sk);
 extern struct tcp_congestion_ops tcp_reno;
 
 static inline void tcp_set_ca_state(struct sock *sk, const u8 ca_state)
@@ -817,6 +821,12 @@
 	tp->ucopy.len = 0;
 	tp->ucopy.memory = 0;
 	skb_queue_head_init(&tp->ucopy.prequeue);
+#ifdef CONFIG_NET_DMA
+	tp->ucopy.dma_chan = NULL;
+	tp->ucopy.wakeup = 0;
+	tp->ucopy.pinned_list = NULL;
+	tp->ucopy.dma_cookie = 0;
+#endif
 }
 
 /* Packet is added to VJ-style prequeue for processing in process
@@ -1076,6 +1086,8 @@
 
 extern int tcp_v4_destroy_sock(struct sock *sk);
 
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg);
+
 #ifdef CONFIG_PROC_FS
 extern int  tcp4_proc_init(void);
 extern void tcp4_proc_exit(void);
diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h
index 098607c..e07136d 100644
--- a/include/net/tipc/tipc_bearer.h
+++ b/include/net/tipc/tipc_bearer.h
@@ -49,10 +49,18 @@
 
 #define TIPC_MEDIA_TYPE_ETH	1
 
+/* 
+ * Destination address structure used by TIPC bearers when sending messages
+ * 
+ * IMPORTANT: The fields of this structure MUST be stored using the specified
+ * byte order indicated below, as the structure is exchanged between nodes
+ * as part of a link setup process.
+ */
+
 struct tipc_media_addr {
-	__u32  type;
+	__u32  type;			/* bearer type (network byte order) */
 	union {
-		__u8   eth_addr[6];	/* Ethernet bearer */ 
+		__u8   eth_addr[6];	/* 48 bit Ethernet addr (byte array) */ 
 #if 0
 		/* Prototypes for other possible bearer types */
 
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index afa508d..9c5ee9f 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -20,6 +20,8 @@
 #include <net/ip6_fib.h>
 
 #define XFRM_ALIGN8(len)	(((len) + 7) & ~7)
+#define MODULE_ALIAS_XFRM_MODE(family, encap) \
+	MODULE_ALIAS("xfrm-mode-" __stringify(family) "-" __stringify(encap))
 
 extern struct sock *xfrm_nl;
 extern u32 sysctl_xfrm_aevent_etime;
@@ -164,6 +166,7 @@
 	/* Reference to data common to all the instances of this
 	 * transformer. */
 	struct xfrm_type	*type;
+	struct xfrm_mode	*mode;
 
 	/* Security context */
 	struct xfrm_sec_ctx	*security;
@@ -204,8 +207,8 @@
 struct xfrm_dst;
 struct xfrm_policy_afinfo {
 	unsigned short		family;
-	rwlock_t		lock;
-	struct xfrm_type_map	*type_map;
+	struct xfrm_type	*type_map[IPPROTO_MAX];
+	struct xfrm_mode	*mode_map[XFRM_MODE_MAX];
 	struct dst_ops		*dst_ops;
 	void			(*garbage_collect)(void);
 	int			(*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);
@@ -232,7 +235,6 @@
 
 struct xfrm_state_afinfo {
 	unsigned short		family;
-	rwlock_t		lock;
 	struct list_head	*state_bydst;
 	struct list_head	*state_byspi;
 	int			(*init_flags)(struct xfrm_state *x);
@@ -264,16 +266,24 @@
 	u32			(*get_max_size)(struct xfrm_state *, int size);
 };
 
-struct xfrm_type_map {
-	rwlock_t		lock;
-	struct xfrm_type	*map[256];
-};
-
 extern int xfrm_register_type(struct xfrm_type *type, unsigned short family);
 extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family);
 extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family);
 extern void xfrm_put_type(struct xfrm_type *type);
 
+struct xfrm_mode {
+	int (*input)(struct xfrm_state *x, struct sk_buff *skb);
+	int (*output)(struct sk_buff *skb);
+
+	struct module *owner;
+	unsigned int encap;
+};
+
+extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
+extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+extern struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family);
+extern void xfrm_put_mode(struct xfrm_mode *mode);
+
 struct xfrm_tmpl
 {
 /* id in template is interpreted as:
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 5e0a01a..ede6398 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -15,7 +15,6 @@
 #ifndef _LINUX_SS_H
 #define _LINUX_SS_H
 
-#include <linux/config.h>
 #include <linux/device.h>
 #include <linux/sched.h>	/* task_struct, completion */
 #include <linux/mutex.h>
diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h
new file mode 100644
index 0000000..fcb5ba87d
--- /dev/null
+++ b/include/rdma/ib_addr.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(IB_ADDR_H)
+#define IB_ADDR_H
+
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/netdevice.h>
+#include <linux/socket.h>
+#include <rdma/ib_verbs.h>
+
+struct rdma_dev_addr {
+	unsigned char src_dev_addr[MAX_ADDR_LEN];
+	unsigned char dst_dev_addr[MAX_ADDR_LEN];
+	unsigned char broadcast[MAX_ADDR_LEN];
+	enum ib_node_type dev_type;
+};
+
+/**
+ * rdma_translate_ip - Translate a local IP address to an RDMA hardware
+ *   address.
+ */
+int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr);
+
+/**
+ * rdma_resolve_ip - Resolve source and destination IP addresses to
+ *   RDMA hardware addresses.
+ * @src_addr: An optional source address to use in the resolution.  If a
+ *   source address is not provided, a usable address will be returned via
+ *   the callback.
+ * @dst_addr: The destination address to resolve.
+ * @addr: A reference to a data location that will receive the resolved
+ *   addresses.  The data location must remain valid until the callback has
+ *   been invoked.
+ * @timeout_ms: Amount of time to wait for the address resolution to complete.
+ * @callback: Call invoked once address resolution has completed, timed out,
+ *   or been canceled.  A status of 0 indicates success.
+ * @context: User-specified context associated with the call.
+ */
+int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr,
+		    struct rdma_dev_addr *addr, int timeout_ms,
+		    void (*callback)(int status, struct sockaddr *src_addr,
+				     struct rdma_dev_addr *addr, void *context),
+		    void *context);
+
+void rdma_addr_cancel(struct rdma_dev_addr *addr);
+
+static inline int ip_addr_size(struct sockaddr *addr)
+{
+	return addr->sa_family == AF_INET6 ?
+	       sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
+}
+
+static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr)
+{
+	return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9];
+}
+
+static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey)
+{
+	dev_addr->broadcast[8] = pkey >> 8;
+	dev_addr->broadcast[9] = (unsigned char) pkey;
+}
+
+static inline union ib_gid *ib_addr_get_sgid(struct rdma_dev_addr *dev_addr)
+{
+	return 	(union ib_gid *) (dev_addr->src_dev_addr + 4);
+}
+
+static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr,
+				    union ib_gid *gid)
+{
+	memcpy(dev_addr->src_dev_addr + 4, gid, sizeof *gid);
+}
+
+static inline union ib_gid *ib_addr_get_dgid(struct rdma_dev_addr *dev_addr)
+{
+	return 	(union ib_gid *) (dev_addr->dst_dev_addr + 4);
+}
+
+static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr,
+				    union ib_gid *gid)
+{
+	memcpy(dev_addr->dst_dev_addr + 4, gid, sizeof *gid);
+}
+
+#endif /* IB_ADDR_H */
diff --git a/include/rdma/ib_cache.h b/include/rdma/ib_cache.h
index 5bf9834f..f179d23 100644
--- a/include/rdma/ib_cache.h
+++ b/include/rdma/ib_cache.h
@@ -102,4 +102,17 @@
 			u16                  pkey,
 			u16                 *index);
 
+/**
+ * ib_get_cached_lmc - Returns a cached lmc table entry
+ * @device: The device to query.
+ * @port_num: The port number of the device to query.
+ * @lmc: The lmc value for the specified port for that device.
+ *
+ * ib_get_cached_lmc() fetches the specified lmc table entry stored in
+ * the local software cache.
+ */
+int ib_get_cached_lmc(struct ib_device *device,
+		      u8                port_num,
+		      u8                *lmc);
+
 #endif /* _IB_CACHE_H */
diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h
index 0a9fcd5..c9b4738 100644
--- a/include/rdma/ib_cm.h
+++ b/include/rdma/ib_cm.h
@@ -32,7 +32,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ib_cm.h 2730 2005-06-28 16:43:03Z sean.hefty $
+ * $Id: ib_cm.h 4311 2005-12-05 18:42:01Z sean.hefty $
  */
 #if !defined(IB_CM_H)
 #define IB_CM_H
@@ -102,7 +102,8 @@
 	IB_CM_APR_INFO_LENGTH		 = 72,
 	IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
 	IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
-	IB_CM_SIDR_REP_INFO_LENGTH	 = 72
+	IB_CM_SIDR_REP_INFO_LENGTH	 = 72,
+	IB_CM_COMPARE_SIZE		 = 64
 };
 
 struct ib_cm_id;
@@ -238,7 +239,6 @@
 	u32			qpn;
 	void			*info;
 	u8			info_len;
-
 };
 
 struct ib_cm_event {
@@ -317,6 +317,15 @@
 
 #define IB_SERVICE_ID_AGN_MASK	__constant_cpu_to_be64(0xFF00000000000000ULL)
 #define IB_CM_ASSIGN_SERVICE_ID __constant_cpu_to_be64(0x0200000000000000ULL)
+#define IB_CMA_SERVICE_ID	__constant_cpu_to_be64(0x0000000001000000ULL)
+#define IB_CMA_SERVICE_ID_MASK	__constant_cpu_to_be64(0xFFFFFFFFFF000000ULL)
+#define IB_SDP_SERVICE_ID	__constant_cpu_to_be64(0x0000000000010000ULL)
+#define IB_SDP_SERVICE_ID_MASK	__constant_cpu_to_be64(0xFFFFFFFFFFFF0000ULL)
+
+struct ib_cm_compare_data {
+	u8  data[IB_CM_COMPARE_SIZE];
+	u8  mask[IB_CM_COMPARE_SIZE];
+};
 
 /**
  * ib_cm_listen - Initiates listening on the specified service ID for
@@ -330,10 +339,12 @@
  *   range of service IDs.  If set to 0, the service ID is matched
  *   exactly.  This parameter is ignored if %service_id is set to
  *   IB_CM_ASSIGN_SERVICE_ID.
+ * @compare_data: This parameter is optional.  It specifies data that must
+ *   appear in the private data of a connection request for the specified
+ *   listen request.
  */
-int ib_cm_listen(struct ib_cm_id *cm_id,
-		 __be64 service_id,
-		 __be64 service_mask);
+int ib_cm_listen(struct ib_cm_id *cm_id, __be64 service_id, __be64 service_mask,
+		 struct ib_cm_compare_data *compare_data);
 
 struct ib_cm_req_param {
 	struct ib_sa_path_rec	*primary_path;
@@ -535,7 +546,6 @@
 	const void		*private_data;
 	u8			private_data_len;
 	u8			max_cm_retries;
-	u16			pkey;
 };
 
 /**
@@ -559,7 +569,7 @@
 };
 
 /**
- * ib_send_cm_sidr_rep - Sends a service ID resolution request to the
+ * ib_send_cm_sidr_rep - Sends a service ID resolution reply to the
  *   remote node.
  * @cm_id: Communication identifier associated with the received service ID
  *   resolution request.
diff --git a/include/rdma/ib_marshall.h b/include/rdma/ib_marshall.h
new file mode 100644
index 0000000..66bf4d7
--- /dev/null
+++ b/include/rdma/ib_marshall.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if !defined(IB_USER_MARSHALL_H)
+#define IB_USER_MARSHALL_H
+
+#include <rdma/ib_verbs.h>
+#include <rdma/ib_sa.h>
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_user_sa.h>
+
+void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst,
+			     struct ib_qp_attr *src);
+
+void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst,
+			      struct ib_sa_path_rec *src);
+
+void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst,
+				struct ib_user_path_rec *src);
+
+#endif /* IB_USER_MARSHALL_H */
diff --git a/include/rdma/ib_sa.h b/include/rdma/ib_sa.h
index ad63c21..c99e442 100644
--- a/include/rdma/ib_sa.h
+++ b/include/rdma/ib_sa.h
@@ -370,5 +370,12 @@
 					context, query);
 }
 
+/**
+ * ib_init_ah_from_path - Initialize address handle attributes based on an SA
+ *   path record.
+ */
+int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
+			 struct ib_sa_path_rec *rec,
+			 struct ib_ah_attr *ah_attr);
 
 #endif /* IB_SA_H */
diff --git a/include/rdma/ib_smi.h b/include/rdma/ib_smi.h
index 87f6073..f29af13 100644
--- a/include/rdma/ib_smi.h
+++ b/include/rdma/ib_smi.h
@@ -85,6 +85,42 @@
 #define IB_SMP_ATTR_LED_INFO			__constant_htons(0x0031)
 #define IB_SMP_ATTR_VENDOR_MASK			__constant_htons(0xFF00)
 
+struct ib_port_info {
+	__be64 mkey;
+	__be64 gid_prefix;
+	__be16 lid;
+	__be16 sm_lid;
+	__be32 cap_mask;
+	__be16 diag_code;
+	__be16 mkey_lease_period;
+	u8 local_port_num;
+	u8 link_width_enabled;
+	u8 link_width_supported;
+	u8 link_width_active;
+	u8 linkspeed_portstate;			/* 4 bits, 4 bits */
+	u8 portphysstate_linkdown;		/* 4 bits, 4 bits */
+	u8 mkeyprot_resv_lmc;			/* 2 bits, 3, 3 */
+	u8 linkspeedactive_enabled;		/* 4 bits, 4 bits */
+	u8 neighbormtu_mastersmsl;		/* 4 bits, 4 bits */
+	u8 vlcap_inittype;			/* 4 bits, 4 bits */
+	u8 vl_high_limit;
+	u8 vl_arb_high_cap;
+	u8 vl_arb_low_cap;
+	u8 inittypereply_mtucap;		/* 4 bits, 4 bits */
+	u8 vlstallcnt_hoqlife;			/* 3 bits, 5 bits */
+	u8 operationalvl_pei_peo_fpi_fpo;	/* 4 bits, 1, 1, 1, 1 */
+	__be16 mkey_violations;
+	__be16 pkey_violations;
+	__be16 qkey_violations;
+	u8 guid_cap;
+	u8 clientrereg_resv_subnetto;		/* 1 bit, 2 bits, 5 */
+	u8 resv_resptimevalue;			/* 3 bits, 5 bits */
+	u8 localphyerrors_overrunerrors;	/* 4 bits, 4 bits */
+	__be16 max_credit_hint;
+	u8 resv;
+	u8 link_roundtrip_latency[3];
+};
+
 static inline u8
 ib_get_smp_direction(struct ib_smp *smp)
 {
diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h
index 19be116..066c20b 100644
--- a/include/rdma/ib_user_cm.h
+++ b/include/rdma/ib_user_cm.h
@@ -30,13 +30,13 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ib_user_cm.h 2576 2005-06-09 17:00:30Z libor $
+ * $Id: ib_user_cm.h 4019 2005-11-11 00:33:09Z sean.hefty $
  */
 
 #ifndef IB_USER_CM_H
 #define IB_USER_CM_H
 
-#include <linux/types.h>
+#include <rdma/ib_user_sa.h>
 
 #define IB_USER_CM_ABI_VERSION 4
 
@@ -110,58 +110,6 @@
 	__u32 qp_state;
 };
 
-struct ib_ucm_ah_attr {
-	__u8	grh_dgid[16];
-	__u32	grh_flow_label;
-	__u16	dlid;
-	__u16	reserved;
-	__u8	grh_sgid_index;
-	__u8	grh_hop_limit;
-	__u8	grh_traffic_class;
-	__u8	sl;
-	__u8	src_path_bits;
-	__u8	static_rate;
-	__u8	is_global;
-	__u8	port_num;
-};
-
-struct ib_ucm_init_qp_attr_resp {
-	__u32	qp_attr_mask;
-	__u32	qp_state;
-	__u32	cur_qp_state;
-	__u32	path_mtu;
-	__u32	path_mig_state;
-	__u32	qkey;
-	__u32	rq_psn;
-	__u32	sq_psn;
-	__u32	dest_qp_num;
-	__u32	qp_access_flags;
-
-	struct ib_ucm_ah_attr	ah_attr;
-	struct ib_ucm_ah_attr	alt_ah_attr;
-
-	/* ib_qp_cap */
-	__u32	max_send_wr;
-	__u32	max_recv_wr;
-	__u32	max_send_sge;
-	__u32	max_recv_sge;
-	__u32	max_inline_data;
-
-	__u16	pkey_index;
-	__u16	alt_pkey_index;
-	__u8	en_sqd_async_notify;
-	__u8	sq_draining;
-	__u8	max_rd_atomic;
-	__u8	max_dest_rd_atomic;
-	__u8	min_rnr_timer;
-	__u8	port_num;
-	__u8	timeout;
-	__u8	retry_cnt;
-	__u8	rnr_retry;
-	__u8	alt_port_num;
-	__u8	alt_timeout;
-};
-
 struct ib_ucm_listen {
 	__be64 service_id;
 	__be64 service_mask;
@@ -180,28 +128,6 @@
 	__u8  reserved[3];
 };
 
-struct ib_ucm_path_rec {
-	__u8  dgid[16];
-	__u8  sgid[16];
-	__be16 dlid;
-	__be16 slid;
-	__u32 raw_traffic;
-	__be32 flow_label;
-	__u32 reversible;
-	__u32 mtu;
-	__be16 pkey;
-	__u8  hop_limit;
-	__u8  traffic_class;
-	__u8  numb_path;
-	__u8  sl;
-	__u8  mtu_selector;
-	__u8  rate_selector;
-	__u8  rate;
-	__u8  packet_life_time_selector;
-	__u8  packet_life_time;
-	__u8  preference;
-};
-
 struct ib_ucm_req {
 	__u32 id;
 	__u32 qpn;
@@ -274,7 +200,7 @@
 	__be64 sid;
 	__u64 data;
 	__u64 path;
-	__u16 pkey;
+	__u16 reserved_pkey;
 	__u8  len;
 	__u8  max_cm_retries;
 	__u8  reserved[4];
@@ -304,8 +230,8 @@
 };
 
 struct ib_ucm_req_event_resp {
-	struct ib_ucm_path_rec primary_path;
-	struct ib_ucm_path_rec alternate_path;
+	struct ib_user_path_rec primary_path;
+	struct ib_user_path_rec alternate_path;
 	__be64                 remote_ca_guid;
 	__u32                  remote_qkey;
 	__u32                  remote_qpn;
@@ -349,7 +275,7 @@
 };
 
 struct ib_ucm_lap_event_resp {
-	struct ib_ucm_path_rec path;
+	struct ib_user_path_rec path;
 };
 
 struct ib_ucm_apr_event_resp {
diff --git a/include/rdma/ib_user_sa.h b/include/rdma/ib_user_sa.h
new file mode 100644
index 0000000..6591201
--- /dev/null
+++ b/include/rdma/ib_user_sa.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef IB_USER_SA_H
+#define IB_USER_SA_H
+
+#include <linux/types.h>
+
+struct ib_user_path_rec {
+	__u8	dgid[16];
+	__u8	sgid[16];
+	__be16	dlid;
+	__be16	slid;
+	__u32	raw_traffic;
+	__be32	flow_label;
+	__u32	reversible;
+	__u32	mtu;
+	__be16	pkey;
+	__u8	hop_limit;
+	__u8	traffic_class;
+	__u8	numb_path;
+	__u8	sl;
+	__u8	mtu_selector;
+	__u8	rate_selector;
+	__u8	rate;
+	__u8	packet_life_time_selector;
+	__u8	packet_life_time;
+	__u8	preference;
+};
+
+#endif /* IB_USER_SA_H */
diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h
index 338ed43..7b53720 100644
--- a/include/rdma/ib_user_verbs.h
+++ b/include/rdma/ib_user_verbs.h
@@ -32,7 +32,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  *
- * $Id: ib_user_verbs.h 2708 2005-06-24 17:27:21Z roland $
+ * $Id: ib_user_verbs.h 4019 2005-11-11 00:33:09Z sean.hefty $
  */
 
 #ifndef IB_USER_VERBS_H
@@ -323,6 +323,64 @@
 	__u32 async_events_reported;
 };
 
+struct ib_uverbs_global_route {
+	__u8  dgid[16];
+	__u32 flow_label;
+	__u8  sgid_index;
+	__u8  hop_limit;
+	__u8  traffic_class;
+	__u8  reserved;
+};
+
+struct ib_uverbs_ah_attr {
+	struct ib_uverbs_global_route grh;
+	__u16 dlid;
+	__u8  sl;
+	__u8  src_path_bits;
+	__u8  static_rate;
+	__u8  is_global;
+	__u8  port_num;
+	__u8  reserved;
+};
+
+struct ib_uverbs_qp_attr {
+	__u32	qp_attr_mask;
+	__u32	qp_state;
+	__u32	cur_qp_state;
+	__u32	path_mtu;
+	__u32	path_mig_state;
+	__u32	qkey;
+	__u32	rq_psn;
+	__u32	sq_psn;
+	__u32	dest_qp_num;
+	__u32	qp_access_flags;
+
+	struct ib_uverbs_ah_attr ah_attr;
+	struct ib_uverbs_ah_attr alt_ah_attr;
+
+	/* ib_qp_cap */
+	__u32	max_send_wr;
+	__u32	max_recv_wr;
+	__u32	max_send_sge;
+	__u32	max_recv_sge;
+	__u32	max_inline_data;
+
+	__u16	pkey_index;
+	__u16	alt_pkey_index;
+	__u8	en_sqd_async_notify;
+	__u8	sq_draining;
+	__u8	max_rd_atomic;
+	__u8	max_dest_rd_atomic;
+	__u8	min_rnr_timer;
+	__u8	port_num;
+	__u8	timeout;
+	__u8	retry_cnt;
+	__u8	rnr_retry;
+	__u8	alt_port_num;
+	__u8	alt_timeout;
+	__u8	reserved[5];
+};
+
 struct ib_uverbs_create_qp {
 	__u64 response;
 	__u64 user_handle;
@@ -541,26 +599,6 @@
 	__u32 bad_wr;
 };
 
-struct ib_uverbs_global_route {
-	__u8  dgid[16];
-	__u32 flow_label;
-	__u8  sgid_index;
-	__u8  hop_limit;
-	__u8  traffic_class;
-	__u8  reserved;
-};
-
-struct ib_uverbs_ah_attr {
-	struct ib_uverbs_global_route grh;
-	__u16 dlid;
-	__u8  sl;
-	__u8  src_path_bits;
-	__u8  static_rate;
-	__u8  is_global;
-	__u8  port_num;
-	__u8  reserved;
-};
-
 struct ib_uverbs_create_ah {
 	__u64 response;
 	__u64 user_handle;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 6bbf1b3..ee1f3a3 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -260,7 +260,8 @@
 	IB_EVENT_SM_CHANGE,
 	IB_EVENT_SRQ_ERR,
 	IB_EVENT_SRQ_LIMIT_REACHED,
-	IB_EVENT_QP_LAST_WQE_REACHED
+	IB_EVENT_QP_LAST_WQE_REACHED,
+	IB_EVENT_CLIENT_REREGISTER
 };
 
 struct ib_event {
@@ -696,8 +697,12 @@
 struct ib_uobject {
 	u64			user_handle;	/* handle given to us by userspace */
 	struct ib_ucontext     *context;	/* associated user context */
+	void		       *object;		/* containing object */
 	struct list_head	list;		/* link to context's list */
 	u32			id;		/* index into kernel idr */
+	struct kref		ref;
+	struct rw_semaphore	mutex;		/* protects .live */
+	int			live;
 };
 
 struct ib_umem {
@@ -827,6 +832,7 @@
 	struct ib_event_handler event_handler;
 	struct ib_pkey_cache  **pkey_cache;
 	struct ib_gid_cache   **gid_cache;
+	u8                     *lmc_cache;
 };
 
 struct ib_device {
@@ -1086,6 +1092,20 @@
 struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr);
 
 /**
+ * ib_init_ah_from_wc - Initializes address handle attributes from a
+ *   work completion.
+ * @device: Device on which the received message arrived.
+ * @port_num: Port on which the received message arrived.
+ * @wc: Work completion associated with the received message.
+ * @grh: References the received global route header.  This parameter is
+ *   ignored unless the work completion indicates that the GRH is valid.
+ * @ah_attr: Returned attributes that can be used when creating an address
+ *   handle for replying to the message.
+ */
+int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, struct ib_wc *wc,
+		       struct ib_grh *grh, struct ib_ah_attr *ah_attr);
+
+/**
  * ib_create_ah_from_wc - Creates an address handle associated with the
  *   sender of the specified work completion.
  * @pd: The protection domain associated with the address handle.
diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h
new file mode 100644
index 0000000..402c63d
--- /dev/null
+++ b/include/rdma/rdma_cm.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(RDMA_CM_H)
+#define RDMA_CM_H
+
+#include <linux/socket.h>
+#include <linux/in6.h>
+#include <rdma/ib_addr.h>
+#include <rdma/ib_sa.h>
+
+/*
+ * Upon receiving a device removal event, users must destroy the associated
+ * RDMA identifier and release all resources allocated with the device.
+ */
+enum rdma_cm_event_type {
+	RDMA_CM_EVENT_ADDR_RESOLVED,
+	RDMA_CM_EVENT_ADDR_ERROR,
+	RDMA_CM_EVENT_ROUTE_RESOLVED,
+	RDMA_CM_EVENT_ROUTE_ERROR,
+	RDMA_CM_EVENT_CONNECT_REQUEST,
+	RDMA_CM_EVENT_CONNECT_RESPONSE,
+	RDMA_CM_EVENT_CONNECT_ERROR,
+	RDMA_CM_EVENT_UNREACHABLE,
+	RDMA_CM_EVENT_REJECTED,
+	RDMA_CM_EVENT_ESTABLISHED,
+	RDMA_CM_EVENT_DISCONNECTED,
+	RDMA_CM_EVENT_DEVICE_REMOVAL,
+};
+
+enum rdma_port_space {
+	RDMA_PS_SDP  = 0x0001,
+	RDMA_PS_TCP  = 0x0106,
+	RDMA_PS_UDP  = 0x0111,
+	RDMA_PS_SCTP = 0x0183
+};
+
+struct rdma_addr {
+	struct sockaddr src_addr;
+	u8		src_pad[sizeof(struct sockaddr_in6) -
+				sizeof(struct sockaddr)];
+	struct sockaddr dst_addr;
+	u8		dst_pad[sizeof(struct sockaddr_in6) -
+				sizeof(struct sockaddr)];
+	struct rdma_dev_addr dev_addr;
+};
+
+struct rdma_route {
+	struct rdma_addr addr;
+	struct ib_sa_path_rec *path_rec;
+	int num_paths;
+};
+
+struct rdma_cm_event {
+	enum rdma_cm_event_type	 event;
+	int			 status;
+	void			*private_data;
+	u8			 private_data_len;
+};
+
+struct rdma_cm_id;
+
+/**
+ * rdma_cm_event_handler - Callback used to report user events.
+ *
+ * Notes: Users may not call rdma_destroy_id from this callback to destroy
+ *   the passed in id, or a corresponding listen id.  Returning a
+ *   non-zero value from the callback will destroy the passed in id.
+ */
+typedef int (*rdma_cm_event_handler)(struct rdma_cm_id *id,
+				     struct rdma_cm_event *event);
+
+struct rdma_cm_id {
+	struct ib_device	*device;
+	void			*context;
+	struct ib_qp		*qp;
+	rdma_cm_event_handler	 event_handler;
+	struct rdma_route	 route;
+	enum rdma_port_space	 ps;
+	u8			 port_num;
+};
+
+/**
+ * rdma_create_id - Create an RDMA identifier.
+ *
+ * @event_handler: User callback invoked to report events associated with the
+ *   returned rdma_id.
+ * @context: User specified context associated with the id.
+ * @ps: RDMA port space.
+ */
+struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
+				  void *context, enum rdma_port_space ps);
+
+void rdma_destroy_id(struct rdma_cm_id *id);
+
+/**
+ * rdma_bind_addr - Bind an RDMA identifier to a source address and
+ *   associated RDMA device, if needed.
+ *
+ * @id: RDMA identifier.
+ * @addr: Local address information.  Wildcard values are permitted.
+ *
+ * This associates a source address with the RDMA identifier before calling
+ * rdma_listen.  If a specific local address is given, the RDMA identifier will
+ * be bound to a local RDMA device.
+ */
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr);
+
+/**
+ * rdma_resolve_addr - Resolve destination and optional source addresses
+ *   from IP addresses to an RDMA address.  If successful, the specified
+ *   rdma_cm_id will be bound to a local device.
+ *
+ * @id: RDMA identifier.
+ * @src_addr: Source address information.  This parameter may be NULL.
+ * @dst_addr: Destination address information.
+ * @timeout_ms: Time to wait for resolution to complete.
+ */
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,
+		      struct sockaddr *dst_addr, int timeout_ms);
+
+/**
+ * rdma_resolve_route - Resolve the RDMA address bound to the RDMA identifier
+ *   into route information needed to establish a connection.
+ *
+ * This is called on the client side of a connection.
+ * Users must have first called rdma_resolve_addr to resolve a dst_addr
+ * into an RDMA address before calling this routine.
+ */
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms);
+
+/**
+ * rdma_create_qp - Allocate a QP and associate it with the specified RDMA
+ * identifier.
+ *
+ * QPs allocated to an rdma_cm_id will automatically be transitioned by the CMA
+ * through their states.
+ */
+int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
+		   struct ib_qp_init_attr *qp_init_attr);
+
+/**
+ * rdma_destroy_qp - Deallocate the QP associated with the specified RDMA
+ * identifier.
+ *
+ * Users must destroy any QP associated with an RDMA identifier before
+ * destroying the RDMA ID.
+ */
+void rdma_destroy_qp(struct rdma_cm_id *id);
+
+/**
+ * rdma_init_qp_attr - Initializes the QP attributes for use in transitioning
+ *   to a specified QP state.
+ * @id: Communication identifier associated with the QP attributes to
+ *   initialize.
+ * @qp_attr: On input, specifies the desired QP state.  On output, the
+ *   mandatory and desired optional attributes will be set in order to
+ *   modify the QP to the specified state.
+ * @qp_attr_mask: The QP attribute mask that may be used to transition the
+ *   QP to the specified state.
+ *
+ * Users must set the @qp_attr->qp_state to the desired QP state.  This call
+ * will set all required attributes for the given transition, along with
+ * known optional attributes.  Users may override the attributes returned from
+ * this call before calling ib_modify_qp.
+ *
+ * Users that wish to have their QP automatically transitioned through its
+ * states can associate a QP with the rdma_cm_id by calling rdma_create_qp().
+ */
+int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
+		       int *qp_attr_mask);
+
+struct rdma_conn_param {
+	const void *private_data;
+	u8 private_data_len;
+	u8 responder_resources;
+	u8 initiator_depth;
+	u8 flow_control;
+	u8 retry_count;		/* ignored when accepting */
+	u8 rnr_retry_count;
+	/* Fields below ignored if a QP is created on the rdma_cm_id. */
+	u8 srq;
+	u32 qp_num;
+	enum ib_qp_type qp_type;
+};
+
+/**
+ * rdma_connect - Initiate an active connection request.
+ *
+ * Users must have resolved a route for the rdma_cm_id to connect with
+ * by having called rdma_resolve_route before calling this routine.
+ */
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_listen - This function is called by the passive side to
+ *   listen for incoming connection requests.
+ *
+ * Users must have bound the rdma_cm_id to a local address by calling
+ * rdma_bind_addr before calling this routine.
+ */
+int rdma_listen(struct rdma_cm_id *id, int backlog);
+
+/**
+ * rdma_accept - Called to accept a connection request or response.
+ * @id: Connection identifier associated with the request.
+ * @conn_param: Information needed to establish the connection.  This must be
+ *   provided if accepting a connection request.  If accepting a connection
+ *   response, this parameter must be NULL.
+ *
+ * Typically, this routine is only called by the listener to accept a connection
+ * request.  It must also be called on the active side of a connection if the
+ * user is performing their own QP transitions.
+ */
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);
+
+/**
+ * rdma_reject - Called to reject a connection request or response.
+ */
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,
+		u8 private_data_len);
+
+/**
+ * rdma_disconnect - This function disconnects the associated QP and
+ *   transitions it into the error state.
+ */
+int rdma_disconnect(struct rdma_cm_id *id);
+
+#endif /* RDMA_CM_H */
+
diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h
new file mode 100644
index 0000000..e8c3af1
--- /dev/null
+++ b/include/rdma/rdma_cm_ib.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ */
+
+#if !defined(RDMA_CM_IB_H)
+#define RDMA_CM_IB_H
+
+#include <rdma/rdma_cm.h>
+
+/**
+ * rdma_set_ib_paths - Manually sets the path records used to establish a
+ *   connection.
+ * @id: Connection identifier associated with the request.
+ * @path_rec: Reference to the path record
+ *
+ * This call permits a user to specify routing information for rdma_cm_id's
+ * bound to Infiniband devices.  It is called on the client side of a
+ * connection and replaces the call to rdma_resolve_route.
+ */
+int rdma_set_ib_paths(struct rdma_cm_id *id,
+		      struct ib_sa_path_rec *path_rec, int num_paths);
+
+#endif /* RDMA_CM_IB_H */
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index e5618b9..253797c 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -43,6 +43,10 @@
 	ISCSI_UEVENT_GET_STATS		= UEVENT_BASE + 10,
 	ISCSI_UEVENT_GET_PARAM		= UEVENT_BASE + 11,
 
+	ISCSI_UEVENT_TRANSPORT_EP_CONNECT	= UEVENT_BASE + 12,
+	ISCSI_UEVENT_TRANSPORT_EP_POLL		= UEVENT_BASE + 13,
+	ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT	= UEVENT_BASE + 14,
+
 	/* up events */
 	ISCSI_KEVENT_RECV_PDU		= KEVENT_BASE + 1,
 	ISCSI_KEVENT_CONN_ERROR		= KEVENT_BASE + 2,
@@ -60,61 +64,83 @@
 			uint32_t	initial_cmdsn;
 		} c_session;
 		struct msg_destroy_session {
-			uint64_t	session_handle;
 			uint32_t	sid;
 		} d_session;
 		struct msg_create_conn {
-			uint64_t	session_handle;
-			uint32_t	cid;
 			uint32_t	sid;
+			uint32_t	cid;
 		} c_conn;
 		struct msg_bind_conn {
-			uint64_t	session_handle;
-			uint64_t	conn_handle;
-			uint32_t	transport_fd;
+			uint32_t	sid;
+			uint32_t	cid;
+			uint64_t	transport_eph;
 			uint32_t	is_leading;
 		} b_conn;
 		struct msg_destroy_conn {
-			uint64_t	conn_handle;
+			uint32_t	sid;
 			uint32_t	cid;
 		} d_conn;
 		struct msg_send_pdu {
+			uint32_t	sid;
+			uint32_t	cid;
 			uint32_t	hdr_size;
 			uint32_t	data_size;
-			uint64_t	conn_handle;
 		} send_pdu;
 		struct msg_set_param {
-			uint64_t	conn_handle;
+			uint32_t	sid;
+			uint32_t	cid;
 			uint32_t	param; /* enum iscsi_param */
-			uint32_t	value;
+			uint32_t	len;
 		} set_param;
 		struct msg_start_conn {
-			uint64_t	conn_handle;
+			uint32_t	sid;
+			uint32_t	cid;
 		} start_conn;
 		struct msg_stop_conn {
+			uint32_t	sid;
+			uint32_t	cid;
 			uint64_t	conn_handle;
 			uint32_t	flag;
 		} stop_conn;
 		struct msg_get_stats {
-			uint64_t	conn_handle;
+			uint32_t	sid;
+			uint32_t	cid;
 		} get_stats;
+		struct msg_transport_connect {
+			uint32_t	non_blocking;
+		} ep_connect;
+		struct msg_transport_poll {
+			uint64_t	ep_handle;
+			uint32_t	timeout_ms;
+		} ep_poll;
+		struct msg_transport_disconnect {
+			uint64_t	ep_handle;
+		} ep_disconnect;
 	} u;
 	union {
 		/* messages k -> u */
-		uint64_t		handle;
 		int			retcode;
 		struct msg_create_session_ret {
-			uint64_t	session_handle;
 			uint32_t	sid;
+			uint32_t	host_no;
 		} c_session_ret;
+		struct msg_create_conn_ret {
+			uint32_t	sid;
+			uint32_t	cid;
+		} c_conn_ret;
 		struct msg_recv_req {
+			uint32_t	sid;
+			uint32_t	cid;
 			uint64_t	recv_handle;
-			uint64_t	conn_handle;
 		} recv_req;
 		struct msg_conn_error {
-			uint64_t	conn_handle;
+			uint32_t	sid;
+			uint32_t	cid;
 			uint32_t	error; /* enum iscsi_err */
 		} connerror;
+		struct msg_transport_connect_ret {
+			uint64_t	handle;
+		} ep_connect_ret;
 	} r;
 } __attribute__ ((aligned (sizeof(uint64_t))));
 
@@ -139,29 +165,66 @@
 	ISCSI_ERR_SESSION_FAILED	= ISCSI_ERR_BASE + 13,
 	ISCSI_ERR_HDR_DGST		= ISCSI_ERR_BASE + 14,
 	ISCSI_ERR_DATA_DGST		= ISCSI_ERR_BASE + 15,
-	ISCSI_ERR_PARAM_NOT_FOUND	= ISCSI_ERR_BASE + 16
+	ISCSI_ERR_PARAM_NOT_FOUND	= ISCSI_ERR_BASE + 16,
+	ISCSI_ERR_NO_SCSI_CMD		= ISCSI_ERR_BASE + 17,
 };
 
 /*
  * iSCSI Parameters (RFC3720)
  */
 enum iscsi_param {
-	ISCSI_PARAM_MAX_RECV_DLENGTH	= 0,
-	ISCSI_PARAM_MAX_XMIT_DLENGTH	= 1,
-	ISCSI_PARAM_HDRDGST_EN		= 2,
-	ISCSI_PARAM_DATADGST_EN		= 3,
-	ISCSI_PARAM_INITIAL_R2T_EN	= 4,
-	ISCSI_PARAM_MAX_R2T		= 5,
-	ISCSI_PARAM_IMM_DATA_EN		= 6,
-	ISCSI_PARAM_FIRST_BURST		= 7,
-	ISCSI_PARAM_MAX_BURST		= 8,
-	ISCSI_PARAM_PDU_INORDER_EN	= 9,
-	ISCSI_PARAM_DATASEQ_INORDER_EN	= 10,
-	ISCSI_PARAM_ERL			= 11,
-	ISCSI_PARAM_IFMARKER_EN		= 12,
-	ISCSI_PARAM_OFMARKER_EN		= 13,
+	/* passed in using netlink set param */
+	ISCSI_PARAM_MAX_RECV_DLENGTH,
+	ISCSI_PARAM_MAX_XMIT_DLENGTH,
+	ISCSI_PARAM_HDRDGST_EN,
+	ISCSI_PARAM_DATADGST_EN,
+	ISCSI_PARAM_INITIAL_R2T_EN,
+	ISCSI_PARAM_MAX_R2T,
+	ISCSI_PARAM_IMM_DATA_EN,
+	ISCSI_PARAM_FIRST_BURST,
+	ISCSI_PARAM_MAX_BURST,
+	ISCSI_PARAM_PDU_INORDER_EN,
+	ISCSI_PARAM_DATASEQ_INORDER_EN,
+	ISCSI_PARAM_ERL,
+	ISCSI_PARAM_IFMARKER_EN,
+	ISCSI_PARAM_OFMARKER_EN,
+	ISCSI_PARAM_EXP_STATSN,
+	ISCSI_PARAM_TARGET_NAME,
+	ISCSI_PARAM_TPGT,
+	ISCSI_PARAM_PERSISTENT_ADDRESS,
+	ISCSI_PARAM_PERSISTENT_PORT,
+	ISCSI_PARAM_SESS_RECOVERY_TMO,
+
+	/* pased in through bind conn using transport_fd */
+	ISCSI_PARAM_CONN_PORT,
+	ISCSI_PARAM_CONN_ADDRESS,
+
+	/* must always be last */
+	ISCSI_PARAM_MAX,
 };
-#define ISCSI_PARAM_MAX			14
+
+#define ISCSI_MAX_RECV_DLENGTH		(1 << ISCSI_PARAM_MAX_RECV_DLENGTH)
+#define ISCSI_MAX_XMIT_DLENGTH		(1 << ISCSI_PARAM_MAX_XMIT_DLENGTH)
+#define ISCSI_HDRDGST_EN		(1 << ISCSI_PARAM_HDRDGST_EN)
+#define ISCSI_DATADGST_EN		(1 << ISCSI_PARAM_DATADGST_EN)
+#define ISCSI_INITIAL_R2T_EN		(1 << ISCSI_PARAM_INITIAL_R2T_EN)
+#define ISCSI_MAX_R2T			(1 << ISCSI_PARAM_MAX_R2T)
+#define ISCSI_IMM_DATA_EN		(1 << ISCSI_PARAM_IMM_DATA_EN)
+#define ISCSI_FIRST_BURST		(1 << ISCSI_PARAM_FIRST_BURST)
+#define ISCSI_MAX_BURST			(1 << ISCSI_PARAM_MAX_BURST)
+#define ISCSI_PDU_INORDER_EN		(1 << ISCSI_PARAM_PDU_INORDER_EN)
+#define ISCSI_DATASEQ_INORDER_EN	(1 << ISCSI_PARAM_DATASEQ_INORDER_EN)
+#define ISCSI_ERL			(1 << ISCSI_PARAM_ERL)
+#define ISCSI_IFMARKER_EN		(1 << ISCSI_PARAM_IFMARKER_EN)
+#define ISCSI_OFMARKER_EN		(1 << ISCSI_PARAM_OFMARKER_EN)
+#define ISCSI_EXP_STATSN		(1 << ISCSI_PARAM_EXP_STATSN)
+#define ISCSI_TARGET_NAME		(1 << ISCSI_PARAM_TARGET_NAME)
+#define ISCSI_TPGT			(1 << ISCSI_PARAM_TPGT)
+#define ISCSI_PERSISTENT_ADDRESS	(1 << ISCSI_PARAM_PERSISTENT_ADDRESS)
+#define ISCSI_PERSISTENT_PORT		(1 << ISCSI_PARAM_PERSISTENT_PORT)
+#define ISCSI_SESS_RECOVERY_TMO		(1 << ISCSI_PARAM_SESS_RECOVERY_TMO)
+#define ISCSI_CONN_PORT			(1 << ISCSI_PARAM_CONN_PORT)
+#define ISCSI_CONN_ADDRESS		(1 << ISCSI_PARAM_CONN_ADDRESS)
 
 #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle)
 #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr)
diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h
index 4feda05..02f6e4b 100644
--- a/include/scsi/iscsi_proto.h
+++ b/include/scsi/iscsi_proto.h
@@ -21,8 +21,6 @@
 #ifndef ISCSI_PROTO_H
 #define ISCSI_PROTO_H
 
-#define ISCSI_VERSION_STR	"0.3"
-#define ISCSI_DATE_STR		"22-Apr-2005"
 #define ISCSI_DRAFT20_VERSION	0x00
 
 /* default iSCSI listen port for incoming connections */
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
new file mode 100644
index 0000000..cbf7e58
--- /dev/null
+++ b/include/scsi/libiscsi.h
@@ -0,0 +1,282 @@
+/*
+ * iSCSI lib definitions
+ *
+ * Copyright (C) 2006 Red Hat, Inc.  All rights reserved.
+ * Copyright (C) 2004 - 2006 Mike Christie
+ * Copyright (C) 2004 - 2005 Dmitry Yusupov
+ * Copyright (C) 2004 - 2005 Alex Aizman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef LIBISCSI_H
+#define LIBISCSI_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <scsi/iscsi_proto.h>
+#include <scsi/iscsi_if.h>
+
+struct scsi_transport_template;
+struct scsi_device;
+struct Scsi_Host;
+struct scsi_cmnd;
+struct socket;
+struct iscsi_transport;
+struct iscsi_cls_session;
+struct iscsi_cls_conn;
+struct iscsi_session;
+struct iscsi_nopin;
+
+/* #define DEBUG_SCSI */
+#ifdef DEBUG_SCSI
+#define debug_scsi(fmt...) printk(KERN_INFO "iscsi: " fmt)
+#else
+#define debug_scsi(fmt...)
+#endif
+
+#define ISCSI_XMIT_CMDS_MAX	128	/* must be power of 2 */
+#define ISCSI_MGMT_CMDS_MAX	32	/* must be power of 2 */
+#define ISCSI_CONN_MAX			1
+
+#define ISCSI_MGMT_ITT_OFFSET	0xa00
+
+#define ISCSI_DEF_CMD_PER_LUN		32
+#define ISCSI_MAX_CMD_PER_LUN		128
+
+/* Task Mgmt states */
+#define TMABORT_INITIAL			0x0
+#define TMABORT_SUCCESS			0x1
+#define TMABORT_FAILED			0x2
+#define TMABORT_TIMEDOUT		0x3
+
+/* Connection suspend "bit" */
+#define ISCSI_SUSPEND_BIT		1
+
+#define ISCSI_ITT_MASK			(0xfff)
+#define ISCSI_CID_SHIFT			12
+#define ISCSI_CID_MASK			(0xffff << ISCSI_CID_SHIFT)
+#define ISCSI_AGE_SHIFT			28
+#define ISCSI_AGE_MASK			(0xf << ISCSI_AGE_SHIFT)
+
+struct iscsi_mgmt_task {
+	/*
+	 * Becuae LLDs allocate their hdr differently, this is a pointer to
+	 * that storage. It must be setup at session creation time.
+	 */
+	struct iscsi_hdr	*hdr;
+	char			*data;		/* mgmt payload */
+	int			data_count;	/* counts data to be sent */
+	uint32_t		itt;		/* this ITT */
+	void			*dd_data;	/* driver/transport data */
+	struct list_head	running;
+};
+
+struct iscsi_cmd_task {
+	/*
+	 * Becuae LLDs allocate their hdr differently, this is a pointer to
+	 * that storage. It must be setup at session creation time.
+	 */
+	struct iscsi_cmd	*hdr;
+	int			itt;		/* this ITT */
+	int			datasn;		/* DataSN */
+
+	uint32_t		unsol_datasn;
+	int			imm_count;	/* imm-data (bytes)   */
+	int			unsol_count;	/* unsolicited (bytes)*/
+	int			data_count;	/* remaining Data-Out */
+	struct scsi_cmnd	*sc;		/* associated SCSI cmd*/
+	int			total_length;
+	struct iscsi_conn	*conn;		/* used connection    */
+	struct iscsi_mgmt_task	*mtask;		/* tmf mtask in progr */
+
+	struct list_head	running;	/* running cmd list */
+	void			*dd_data;	/* driver/transport data */
+};
+
+struct iscsi_conn {
+	struct iscsi_cls_conn	*cls_conn;	/* ptr to class connection */
+	void			*dd_data;	/* iscsi_transport data */
+	struct iscsi_session	*session;	/* parent session */
+	/*
+	 * LLDs should set this lock. It protects the transport recv
+	 * code
+	 */
+	rwlock_t		*recv_lock;
+	/*
+	 * conn_stop() flag: stop to recover, stop to terminate
+	 */
+        int			stop_stage;
+
+	/* iSCSI connection-wide sequencing */
+	uint32_t		exp_statsn;
+
+	/* control data */
+	int			id;		/* CID */
+	struct list_head	item;		/* maintains list of conns */
+	int			c_stage;	/* connection state */
+	struct iscsi_mgmt_task	*login_mtask;	/* mtask used for login/text */
+	struct iscsi_mgmt_task	*mtask;		/* xmit mtask in progress */
+	struct iscsi_cmd_task	*ctask;		/* xmit ctask in progress */
+
+	/* xmit */
+	struct kfifo		*immqueue;	/* immediate xmit queue */
+	struct kfifo		*mgmtqueue;	/* mgmt (control) xmit queue */
+	struct list_head	mgmt_run_list;	/* list of control tasks */
+	struct kfifo		*xmitqueue;	/* data-path cmd queue */
+	struct list_head	run_list;	/* list of cmds in progress */
+	struct work_struct	xmitwork;	/* per-conn. xmit workqueue */
+	/*
+	 * serializes connection xmit, access to kfifos:
+	 * xmitqueue, immqueue, mgmtqueue
+	 */
+	struct mutex		xmitmutex;
+
+	unsigned long		suspend_tx;	/* suspend Tx */
+	unsigned long		suspend_rx;	/* suspend Rx */
+
+	/* abort */
+	wait_queue_head_t	ehwait;		/* used in eh_abort() */
+	struct iscsi_tm		tmhdr;
+	struct timer_list	tmabort_timer;
+	int			tmabort_state;	/* see TMABORT_INITIAL, etc.*/
+
+	/* negotiated params */
+	int			max_recv_dlength; /* initiator_max_recv_dsl*/
+	int			max_xmit_dlength; /* target_max_recv_dsl */
+	int			hdrdgst_en;
+	int			datadgst_en;
+
+	/* MIB-statistics */
+	uint64_t		txdata_octets;
+	uint64_t		rxdata_octets;
+	uint32_t		scsicmd_pdus_cnt;
+	uint32_t		dataout_pdus_cnt;
+	uint32_t		scsirsp_pdus_cnt;
+	uint32_t		datain_pdus_cnt;
+	uint32_t		r2t_pdus_cnt;
+	uint32_t		tmfcmd_pdus_cnt;
+	int32_t			tmfrsp_pdus_cnt;
+
+	/* custom statistics */
+	uint32_t		eh_abort_cnt;
+};
+
+struct iscsi_queue {
+	struct kfifo		*queue;		/* FIFO Queue */
+	void			**pool;		/* Pool of elements */
+	int			max;		/* Max number of elements */
+};
+
+struct iscsi_session {
+	/* iSCSI session-wide sequencing */
+	uint32_t		cmdsn;
+	uint32_t		exp_cmdsn;
+	uint32_t		max_cmdsn;
+
+	/* configuration */
+	int			initial_r2t_en;
+	int			max_r2t;
+	int			imm_data_en;
+	int			first_burst;
+	int			max_burst;
+	int			time2wait;
+	int			time2retain;
+	int			pdu_inorder_en;
+	int			dataseq_inorder_en;
+	int			erl;
+	int			ifmarker_en;
+	int			ofmarker_en;
+
+	/* control data */
+	struct iscsi_transport	*tt;
+	struct Scsi_Host	*host;
+	struct iscsi_conn	*leadconn;	/* leading connection */
+	spinlock_t		lock;		/* protects session state, *
+						 * sequence numbers,       *
+						 * session resources:      *
+						 * - cmdpool,		   *
+						 * - mgmtpool,		   *
+						 * - r2tpool		   */
+	int			state;		/* session state           */
+	struct list_head	item;
+	int			age;		/* counts session re-opens */
+
+	struct list_head	connections;	/* list of connections */
+	int			cmds_max;	/* size of cmds array */
+	struct iscsi_cmd_task	**cmds;		/* Original Cmds arr */
+	struct iscsi_queue	cmdpool;	/* PDU's pool */
+	int			mgmtpool_max;	/* size of mgmt array */
+	struct iscsi_mgmt_task	**mgmt_cmds;	/* Original mgmt arr */
+	struct iscsi_queue	mgmtpool;	/* Mgmt PDU's pool */
+};
+
+/*
+ * scsi host template
+ */
+extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth);
+extern int iscsi_eh_abort(struct scsi_cmnd *sc);
+extern int iscsi_eh_host_reset(struct scsi_cmnd *sc);
+extern int iscsi_queuecommand(struct scsi_cmnd *sc,
+			      void (*done)(struct scsi_cmnd *));
+
+/*
+ * session management
+ */
+extern struct iscsi_cls_session *
+iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *,
+		    int, int, uint32_t, uint32_t *);
+extern void iscsi_session_teardown(struct iscsi_cls_session *);
+extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *);
+extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *);
+
+#define session_to_cls(_sess) \
+	hostdata_session(_sess->host->hostdata)
+
+/*
+ * connection management
+ */
+extern struct iscsi_cls_conn *iscsi_conn_setup(struct iscsi_cls_session *,
+					       uint32_t);
+extern void iscsi_conn_teardown(struct iscsi_cls_conn *);
+extern int iscsi_conn_start(struct iscsi_cls_conn *);
+extern void iscsi_conn_stop(struct iscsi_cls_conn *, int);
+extern int iscsi_conn_bind(struct iscsi_cls_session *, struct iscsi_cls_conn *,
+			   int);
+extern void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err);
+
+/*
+ * pdu and task processing
+ */
+extern int iscsi_check_assign_cmdsn(struct iscsi_session *,
+				    struct iscsi_nopin *);
+extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *,
+					struct iscsi_data *hdr,
+					int transport_data_cnt);
+extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *,
+				char *, uint32_t);
+extern int iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+			      char *, int);
+extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
+				char *, int);
+extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *,
+			    uint32_t *);
+
+/*
+ * generic helpers
+ */
+extern void iscsi_pool_free(struct iscsi_queue *, void **);
+extern int iscsi_pool_init(struct iscsi_queue *, int, void ***, int);
+
+#endif
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 1ace1b9..e46cd40 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -9,7 +9,6 @@
 struct request;
 struct scatterlist;
 struct scsi_device;
-struct scsi_request;
 
 
 /* embedded in scsi_cmnd */
@@ -29,13 +28,8 @@
 };
 
 struct scsi_cmnd {
-	int     sc_magic;
-
 	struct scsi_device *device;
-	struct scsi_request *sc_request;
-
 	struct list_head list;  /* scsi_cmnd participates in queue lists */
-
 	struct list_head eh_entry; /* entry for the host eh_cmd_q */
 	int eh_eflags;		/* Used by error handlr */
 	void (*done) (struct scsi_cmnd *);	/* Mid-level done function */
@@ -151,5 +145,10 @@
 extern void scsi_put_command(struct scsi_cmnd *);
 extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
 extern void scsi_finish_command(struct scsi_cmnd *cmd);
+extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd);
+
+extern void *scsi_kmap_atomic_sg(struct scatterlist *sg, int sg_count,
+				 size_t *offset, size_t *len);
+extern void scsi_kunmap_atomic_sg(void *virt);
 
 #endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
index 4d69dee..3bbbfbe 100644
--- a/include/scsi/scsi_dbg.h
+++ b/include/scsi/scsi_dbg.h
@@ -2,14 +2,12 @@
 #define _SCSI_SCSI_DBG_H
 
 struct scsi_cmnd;
-struct scsi_request;
 struct scsi_sense_hdr;
 
 extern void scsi_print_command(struct scsi_cmnd *);
 extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *);
 extern void __scsi_print_command(unsigned char *);
 extern void scsi_print_sense(const char *, struct scsi_cmnd *);
-extern void scsi_print_req_sense(const char *, struct scsi_request *);
 extern void __scsi_print_sense(const char *name,
 			       const unsigned char *sense_buffer,
 			       int sense_len);
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index d31b16d..b4ddd3b 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -29,4 +29,5 @@
 #define BLIST_SELECT_NO_ATN	0x200000 /* select without ATN */
 #define BLIST_RETRY_HWERROR	0x400000 /* retry HARDWARE_ERROR */
 #define BLIST_MAX_512		0x800000 /* maximum 512 sector cdb length */
+#define BLIST_ATTACH_PQ3	0x1000000 /* Scan: Attach to PQ3 devices */
 #endif
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index d160880..c5c0f67 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -3,7 +3,6 @@
 
 struct scsi_cmnd;
 struct scsi_device;
-struct scsi_request;
 struct Scsi_Host;
 
 /*
@@ -43,8 +42,6 @@
 extern int scsi_block_when_processing_errors(struct scsi_device *);
 extern int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
 		struct scsi_sense_hdr *sshdr);
-extern int scsi_request_normalize_sense(struct scsi_request *sreq,
-		struct scsi_sense_hdr *sshdr);
 extern int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
 		struct scsi_sense_hdr *sshdr);
 
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index de6ce54..a42efd6 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -472,6 +472,7 @@
 	 */
 	unsigned int host_busy;		   /* commands actually active on low-level */
 	unsigned int host_failed;	   /* commands that failed. */
+	unsigned int host_eh_scheduled;    /* EH scheduled without command */
     
 	unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
 	int resetting; /* if set, it means that last_reset is a valid value */
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
deleted file mode 100644
index 98d69fd..0000000
--- a/include/scsi/scsi_request.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#ifndef _SCSI_SCSI_REQUEST_H
-#define _SCSI_SCSI_REQUEST_H
-
-#include <scsi/scsi_cmnd.h>
-
-struct request;
-struct scsi_cmnd;
-struct scsi_device;
-struct Scsi_Host;
-
-
-/*
- * This is essentially a slimmed down version of Scsi_Cmnd.  The point of
- * having this is that requests that are injected into the queue as result
- * of things like ioctls and character devices shouldn't be using a
- * Scsi_Cmnd until such a time that the command is actually at the head
- * of the queue and being sent to the driver.
- */
-struct scsi_request {
-	int     sr_magic;
-	int     sr_result;	/* Status code from lower level driver */
-	unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE];		/* obtained by REQUEST SENSE
-						 * when CHECK CONDITION is
-						 * received on original command 
-						 * (auto-sense) */
-
-	struct Scsi_Host *sr_host;
-	struct scsi_device *sr_device;
-	struct scsi_cmnd *sr_command;
-	struct request *sr_request;	/* A copy of the command we are
-				   working on */
-	unsigned sr_bufflen;	/* Size of data buffer */
-	void *sr_buffer;		/* Data buffer */
-	int sr_allowed;
-	enum dma_data_direction sr_data_direction;
-	unsigned char sr_cmd_len;
-	unsigned char sr_cmnd[MAX_COMMAND_SIZE];
-	void (*sr_done) (struct scsi_cmnd *);	/* Mid-level done function */
-	int sr_timeout_per_command;
-	unsigned short sr_use_sg;	/* Number of pieces of scatter-gather */
-	unsigned short sr_sglist_len;	/* size of malloc'd scatter-gather list */
-	unsigned sr_underflow;	/* Return error if less than
-				   this amount is transferred */
- 	void *upper_private_data;	/* reserved for owner (usually upper
- 					   level driver) of this request */
-};
-
-extern struct scsi_request *scsi_allocate_request(struct scsi_device *, gfp_t);
-extern void scsi_release_request(struct scsi_request *);
-extern void scsi_do_req(struct scsi_request *, const void *cmnd,
-			void *buffer, unsigned bufflen,
-			void (*done) (struct scsi_cmnd *),
-			int timeout, int retries);
-#endif /* _SCSI_SCSI_REQUEST_H */
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
index 5626225..6d28b03 100644
--- a/include/scsi/scsi_transport_fc.h
+++ b/include/scsi/scsi_transport_fc.h
@@ -27,7 +27,6 @@
 #ifndef SCSI_TRANSPORT_FC_H
 #define SCSI_TRANSPORT_FC_H
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <scsi/scsi.h>
 
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index b41cf07..b684426 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -2,7 +2,7 @@
  * iSCSI transport class definitions
  *
  * Copyright (C) IBM Corporation, 2004
- * Copyright (C) Mike Christie, 2004 - 2005
+ * Copyright (C) Mike Christie, 2004 - 2006
  * Copyright (C) Dmitry Yusupov, 2004 - 2005
  * Copyright (C) Alex Aizman, 2004 - 2005
  *
@@ -27,9 +27,13 @@
 #include <scsi/iscsi_if.h>
 
 struct scsi_transport_template;
+struct iscsi_transport;
 struct Scsi_Host;
 struct mempool_zone;
 struct iscsi_cls_conn;
+struct iscsi_conn;
+struct iscsi_cmd_task;
+struct iscsi_mgmt_task;
 
 /**
  * struct iscsi_transport - iSCSI Transport template
@@ -46,6 +50,24 @@
  * @start_conn:		set connection to be operational
  * @stop_conn:		suspend/recover/terminate connection
  * @send_pdu:		send iSCSI PDU, Login, Logout, NOP-Out, Reject, Text.
+ * @session_recovery_timedout: notify LLD a block during recovery timed out
+ * @suspend_conn_recv:	susepend the recv side of the connection
+ * @termincate_conn:	destroy socket connection. Called with mutex lock.
+ * @init_cmd_task:	Initialize a iscsi_cmd_task and any internal structs.
+ *			Called from queuecommand with session lock held.
+ * @init_mgmt_task:	Initialize a iscsi_mgmt_task and any internal structs.
+ *			Called from iscsi_conn_send_generic with xmitmutex.
+ * @xmit_cmd_task:	Requests LLD to transfer cmd task. Returns 0 or the
+ *			the number of bytes transferred on success, and -Exyz
+ *			value on error.
+ * @xmit_mgmt_task:	Requests LLD to transfer mgmt task. Returns 0 or the
+ *			the number of bytes transferred on success, and -Exyz
+ *			value on error.
+ * @cleanup_cmd_task:	requests LLD to fail cmd task. Called with xmitmutex
+ *			and session->lock after the connection has been
+ *			suspended and terminated during recovery. If called
+ *			from abort task then connection is not suspended
+ *			or terminated but sk_callback_lock is held
  *
  * Template API provided by iSCSI Transport
  */
@@ -53,38 +75,58 @@
 	struct module *owner;
 	char *name;
 	unsigned int caps;
+	/* LLD sets this to indicate what values it can export to sysfs */
+	unsigned int param_mask;
 	struct scsi_host_template *host_template;
-	/* LLD session/scsi_host data size */
-	int hostdata_size;
-	/* LLD iscsi_host data size */
-	int ihostdata_size;
 	/* LLD connection data size */
 	int conndata_size;
+	/* LLD session data size */
+	int sessiondata_size;
 	int max_lun;
 	unsigned int max_conn;
 	unsigned int max_cmd_len;
-	struct iscsi_cls_session *(*create_session)
-		(struct scsi_transport_template *t, uint32_t sn, uint32_t *sid);
+	struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it,
+		struct scsi_transport_template *t, uint32_t sn, uint32_t *hn);
 	void (*destroy_session) (struct iscsi_cls_session *session);
 	struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess,
 				uint32_t cid);
 	int (*bind_conn) (struct iscsi_cls_session *session,
 			  struct iscsi_cls_conn *cls_conn,
-			  uint32_t transport_fd, int is_leading);
+			  uint64_t transport_eph, int is_leading);
 	int (*start_conn) (struct iscsi_cls_conn *conn);
 	void (*stop_conn) (struct iscsi_cls_conn *conn, int flag);
 	void (*destroy_conn) (struct iscsi_cls_conn *conn);
 	int (*set_param) (struct iscsi_cls_conn *conn, enum iscsi_param param,
 			  uint32_t value);
 	int (*get_conn_param) (struct iscsi_cls_conn *conn,
-			       enum iscsi_param param,
-			       uint32_t *value);
+			       enum iscsi_param param, uint32_t *value);
 	int (*get_session_param) (struct iscsi_cls_session *session,
 				  enum iscsi_param param, uint32_t *value);
+	int (*get_conn_str_param) (struct iscsi_cls_conn *conn,
+				   enum iscsi_param param, char *buf);
+	int (*get_session_str_param) (struct iscsi_cls_session *session,
+				      enum iscsi_param param, char *buf);
 	int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
 			 char *data, uint32_t data_size);
 	void (*get_stats) (struct iscsi_cls_conn *conn,
 			   struct iscsi_stats *stats);
+	void (*suspend_conn_recv) (struct iscsi_conn *conn);
+	void (*terminate_conn) (struct iscsi_conn *conn);
+	void (*init_cmd_task) (struct iscsi_cmd_task *ctask);
+	void (*init_mgmt_task) (struct iscsi_conn *conn,
+				struct iscsi_mgmt_task *mtask,
+				char *data, uint32_t data_size);
+	int (*xmit_cmd_task) (struct iscsi_conn *conn,
+			      struct iscsi_cmd_task *ctask);
+	void (*cleanup_cmd_task) (struct iscsi_conn *conn,
+				  struct iscsi_cmd_task *ctask);
+	int (*xmit_mgmt_task) (struct iscsi_conn *conn,
+			       struct iscsi_mgmt_task *mtask);
+	void (*session_recovery_timedout) (struct iscsi_cls_session *session);
+	int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking,
+			   uint64_t *ep_handle);
+	int (*ep_poll) (uint64_t ep_handle, int timeout_ms);
+	void (*ep_disconnect) (uint64_t ep_handle);
 };
 
 /*
@@ -100,10 +142,26 @@
 extern int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
 			  char *data, uint32_t data_size);
 
+
+/* Connection's states */
+#define ISCSI_CONN_INITIAL_STAGE	0
+#define ISCSI_CONN_STARTED		1
+#define ISCSI_CONN_STOPPED		2
+#define ISCSI_CONN_CLEANUP_WAIT		3
+
 struct iscsi_cls_conn {
 	struct list_head conn_list;	/* item in connlist */
 	void *dd_data;			/* LLD private data */
 	struct iscsi_transport *transport;
+	uint32_t cid;			/* connection id */
+
+	/* portal/group values we got during discovery */
+	char *persistent_address;
+	int persistent_port;
+	/* portal/group values we are currently using */
+	char *address;
+	int port;
+
 	int active;			/* must be accessed with the connlock */
 	struct device dev;		/* sysfs transport/container device */
 	struct mempool_zone *z_error;
@@ -114,9 +172,32 @@
 #define iscsi_dev_to_conn(_dev) \
 	container_of(_dev, struct iscsi_cls_conn, dev)
 
+/* Session's states */
+#define ISCSI_STATE_FREE		1
+#define ISCSI_STATE_LOGGED_IN		2
+#define ISCSI_STATE_FAILED		3
+#define ISCSI_STATE_TERMINATE		4
+#define ISCSI_STATE_IN_RECOVERY		5
+#define ISCSI_STATE_RECOVERY_FAILED	6
+
 struct iscsi_cls_session {
 	struct list_head sess_list;		/* item in session_list */
+	struct list_head host_list;
 	struct iscsi_transport *transport;
+
+	/* iSCSI values used as unique id by userspace. */
+	char *targetname;
+	int tpgt;
+
+	/* recovery fields */
+	int recovery_tmo;
+	struct work_struct recovery_work;
+
+	int target_id;
+	int channel;
+
+	int sid;				/* session id */
+	void *dd_data;				/* LLD private data */
 	struct device dev;	/* sysfs transport/container device */
 };
 
@@ -126,22 +207,22 @@
 #define iscsi_session_to_shost(_session) \
 	dev_to_shost(_session->dev.parent)
 
+struct iscsi_host {
+	int next_target_id;
+	struct list_head sessions;
+	struct mutex mutex;
+};
+
 /*
  * session and connection functions that can be used by HW iSCSI LLDs
  */
 extern struct iscsi_cls_session *iscsi_create_session(struct Scsi_Host *shost,
-				struct iscsi_transport *t);
+				struct iscsi_transport *t, int channel);
 extern int iscsi_destroy_session(struct iscsi_cls_session *session);
 extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess,
 					    uint32_t cid);
 extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
-
-/*
- * session functions used by software iscsi
- */
-extern struct Scsi_Host *
-iscsi_transport_create_session(struct scsi_transport_template *scsit,
-                               struct iscsi_transport *transport);
-extern int iscsi_transport_destroy_session(struct Scsi_Host *shost);
+extern void iscsi_unblock_session(struct iscsi_cls_session *session);
+extern void iscsi_block_session(struct iscsi_cls_session *session);
 
 #endif
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index 5e1d619..302680c 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -20,7 +20,6 @@
 #ifndef SCSI_TRANSPORT_SPI_H
 #define SCSI_TRANSPORT_SPI_H
 
-#include <linux/config.h>
 #include <linux/transport_class.h>
 #include <linux/mutex.h>
 
diff --git a/include/scsi/sg_request.h b/include/scsi/sg_request.h
deleted file mode 100644
index 57ff525..0000000
--- a/include/scsi/sg_request.h
+++ /dev/null
@@ -1,26 +0,0 @@
-typedef struct scsi_request Scsi_Request;
-
-static Scsi_Request *dummy_cmdp;	/* only used for sizeof */
-
-typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
-	unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
-	unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
-	unsigned bufflen;	/* Size of (aggregate) data buffer */
-	unsigned b_malloc_len;	/* actual len malloc'ed in buffer */
-	void *buffer;		/* Data buffer or scatter list (k_use_sg>0) */
-	char dio_in_use;	/* 0->indirect IO (or mmap), 1->dio */
-	unsigned char cmd_opcode; /* first byte of command */
-} Sg_scatter_hold;
-
-typedef struct sg_request {	/* SG_MAX_QUEUE requests outstanding per file */
-	Scsi_Request *my_cmdp;	/* != 0  when request with lower levels */
-	struct sg_request *nextrp;	/* NULL -> tail request (slist) */
-	struct sg_fd *parentfp;	/* NULL -> not in use */
-	Sg_scatter_hold data;	/* hold buffer, perhaps scatter list */
-	sg_io_hdr_t header;	/* scsi command+info, see <scsi/sg.h> */
-	unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)];
-	char res_used;		/* 1 -> using reserve buffer, 0 -> not ... */
-	char orphan;		/* 1 -> drop on sight, 0 -> normal */
-	char sg_io_owned;	/* 1 -> packet belongs to SG_IO */
-	volatile char done;	/* 0->before bh, 1->before read, 2->read */
-} Sg_request;
diff --git a/include/scsi/srp.h b/include/scsi/srp.h
index 637f77e..ad178fa 100644
--- a/include/scsi/srp.h
+++ b/include/scsi/srp.h
@@ -87,6 +87,11 @@
 	SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED		= 0x00010006
 };
 
+enum {
+	SRP_REV10_IB_IO_CLASS	= 0xff00,
+	SRP_REV16A_IB_IO_CLASS	= 0x0100
+};
+
 struct srp_direct_buf {
 	__be64	va;
 	__be32	key;
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index b45a737..446afc3 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -378,6 +378,7 @@
 #define AC97_HAS_NO_MIC	(1<<15) /* no MIC volume */
 #define AC97_HAS_NO_TONE	(1<<16) /* no Tone volume */
 #define AC97_HAS_NO_STD_PCM	(1<<17)	/* no standard AC97 PCM volume and mute */
+#define AC97_HAS_NO_AUX		(1<<18) /* no standard AC97 AUX volume and mute */
 
 /* rates indexes */
 #define AC97_RATES_FRONT_DAC	0
diff --git a/include/sound/asequencer.h b/include/sound/asequencer.h
index 6691e4a..3f2f404 100644
--- a/include/sound/asequencer.h
+++ b/include/sound/asequencer.h
@@ -605,6 +605,10 @@
 #define SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE (1<<11)	/* Sampling device (support sample download) */
 #define SNDRV_SEQ_PORT_TYPE_SAMPLE	(1<<12)	/* Sampling device (sample can be downloaded at any time) */
 /*...*/
+#define SNDRV_SEQ_PORT_TYPE_HARDWARE	(1<<16)	/* driver for a hardware device */
+#define SNDRV_SEQ_PORT_TYPE_SOFTWARE	(1<<17)	/* implemented in software */
+#define SNDRV_SEQ_PORT_TYPE_SYNTHESIZER	(1<<18)	/* generates sound */
+#define SNDRV_SEQ_PORT_TYPE_PORT	(1<<19)	/* connects to other device(s) */
 #define SNDRV_SEQ_PORT_TYPE_APPLICATION	(1<<20)	/* application (sequencer/editor) */
 
 /* misc. conditioning flags */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 9cc021c..41885f4 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -137,7 +137,7 @@
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 7)
+#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 8)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
diff --git a/include/sound/core.h b/include/sound/core.h
index 5135147..5d184be 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -233,9 +233,8 @@
 
 /* init.c */
 
-extern unsigned int snd_cards_lock;
 extern struct snd_card *snd_cards[SNDRV_CARDS];
-extern rwlock_t snd_card_rwlock;
+int snd_card_locked(int card);
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
 #define SND_MIXER_OSS_NOTIFY_REGISTER	0
 #define SND_MIXER_OSS_NOTIFY_DISCONNECT	1
diff --git a/include/sound/driver.h b/include/sound/driver.h
index 89c6a73..3c522e5 100644
--- a/include/sound/driver.h
+++ b/include/sound/driver.h
@@ -26,7 +26,6 @@
 #include "config.h"
 #endif
 
-#include <linux/config.h>
 
 /* number of supported soundcards */
 #ifdef CONFIG_SND_DYNAMIC_MINORS
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 186e00a..884bbf5 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -245,6 +245,7 @@
 #define A_IOCFG_GPOUT0		0x0044		/* analog/digital				*/
 #define A_IOCFG_DISABLE_ANALOG	0x0040		/* = 'enable' for Audigy2 (chiprev=4)		*/
 #define A_IOCFG_ENABLE_DIGITAL	0x0004
+#define A_IOCFG_ENABLE_DIGITAL_AUDIGY4	0x0080
 #define A_IOCFG_UNKNOWN_20      0x0020
 #define A_IOCFG_DISABLE_AC97_FRONT      0x0080  /* turn off ac97 front -> front (10k2.1)	*/
 #define A_IOCFG_GPOUT1		0x0002		/* IR? drive's internal bypass (?)		*/
@@ -1065,6 +1066,7 @@
 	unsigned char emu1212m;     /* EMU 1212m card */
 	unsigned char spi_dac;      /* SPI interface for DAC */
 	unsigned char i2c_adc;      /* I2C interface for ADC */
+	unsigned char adc_1361t;    /* Use Philips 1361T ADC */
 	const char *driver;
 	const char *name;
 	const char *id;		/* for backward compatibility - can be NULL if not needed */
diff --git a/include/sound/hdsp.h b/include/sound/hdsp.h
index 25e1951..dec6b1d 100644
--- a/include/sound/hdsp.h
+++ b/include/sound/hdsp.h
@@ -30,13 +30,13 @@
 };
 
 struct hdsp_peak_rms {
-	u32 input_peaks[26];
-	u32 playback_peaks[26];
-	u32 output_peaks[28];
-	u64 input_rms[26];
-	u64 playback_rms[26];
+	__u32 input_peaks[26];
+	__u32 playback_peaks[26];
+	__u32 output_peaks[28];
+	__u64 input_rms[26];
+	__u64 playback_rms[26];
 	/* These are only used for H96xx cards */
-	u64 output_rms[26];
+	__u64 output_rms[26];
 };
 
 #define SNDRV_HDSP_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct hdsp_peak_rms)
diff --git a/include/sound/info.h b/include/sound/info.h
index f23d838..74f69967 100644
--- a/include/sound/info.h
+++ b/include/sound/info.h
@@ -27,9 +27,9 @@
 /* buffer for information */
 struct snd_info_buffer {
 	char *buffer;		/* pointer to begin of buffer */
-	char *curr;		/* current position in buffer */
-	unsigned long size;	/* current size */
-	unsigned long len;	/* total length of buffer */
+	unsigned int curr;	/* current position in buffer */
+	unsigned int size;	/* current size */
+	unsigned int len;	/* total length of buffer */
 	int stop;		/* stop flag */
 	int error;		/* error code */
 };
@@ -40,8 +40,6 @@
 struct snd_info_entry;
 
 struct snd_info_entry_text {
-	unsigned long read_size;
-	unsigned long write_size;
 	void (*read) (struct snd_info_entry *entry, struct snd_info_buffer *buffer);
 	void (*write) (struct snd_info_entry *entry, struct snd_info_buffer *buffer);
 };
@@ -132,11 +130,9 @@
 
 static inline void snd_info_set_text_ops(struct snd_info_entry *entry, 
 					 void *private_data,
-					 long read_size,
 					 void (*read)(struct snd_info_entry *, struct snd_info_buffer *))
 {
 	entry->private_data = private_data;
-	entry->c.text.read_size = read_size;
 	entry->c.text.read = read;
 }
 
@@ -167,7 +163,6 @@
 				    struct snd_info_entry **entryp) { return -EINVAL; }
 static inline void snd_info_set_text_ops(struct snd_info_entry *entry __attribute__((unused)),
 					 void *private_data,
-					 long read_size,
 					 void (*read)(struct snd_info_entry *, struct snd_info_buffer *)) {}
 
 static inline int snd_info_check_reserved_words(const char *str) { return 1; }
diff --git a/include/sound/mpu401.h b/include/sound/mpu401.h
index 8e97ace..ac50432 100644
--- a/include/sound/mpu401.h
+++ b/include/sound/mpu401.h
@@ -45,6 +45,12 @@
 #define MPU401_HW_PC98II		18	/* Roland PC98II */
 #define MPU401_HW_AUREAL		19	/* Aureal Vortex */
 
+#define MPU401_INFO_INPUT	(1 << 0)	/* input stream */
+#define MPU401_INFO_OUTPUT	(1 << 1)	/* output stream */
+#define MPU401_INFO_INTEGRATED	(1 << 2)	/* integrated h/w port */
+#define MPU401_INFO_MMIO	(1 << 3)	/* MMIO access */
+#define MPU401_INFO_TX_IRQ	(1 << 4)	/* independent TX irq */
+
 #define MPU401_MODE_BIT_INPUT		0
 #define MPU401_MODE_BIT_OUTPUT		1
 #define MPU401_MODE_BIT_INPUT_TRIGGER	2
@@ -62,6 +68,7 @@
 	struct snd_rawmidi *rmidi;
 
 	unsigned short hardware;	/* MPU401_HW_XXXX */
+	unsigned int info_flags;	/* MPU401_INFO_XXX */
 	unsigned long port;		/* base port of MPU-401 chip */
 	unsigned long cport;		/* port + 1 (usually) */
 	struct resource *res;		/* port resource */
@@ -99,13 +106,16 @@
 
  */
 
-irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id,
+				      struct pt_regs *regs);
+irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id,
+					 struct pt_regs *regs);
 
 int snd_mpu401_uart_new(struct snd_card *card,
 			int device,
 			unsigned short hardware,
 			unsigned long port,
-			int integrated,
+			unsigned int info_flags,
 			int irq,
 			int irq_flags,
 			struct snd_rawmidi ** rrawmidi);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 3734258..f84d849 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -300,7 +300,6 @@
 	/* -- mmap -- */
 	volatile struct snd_pcm_mmap_status *status;
 	volatile struct snd_pcm_mmap_control *control;
-	atomic_t mmap_count;
 
 	/* -- locking / scheduling -- */
 	wait_queue_head_t sleep;
@@ -368,7 +367,9 @@
 	struct snd_pcm_group *group;		/* pointer to current group */
 	/* -- assigned files -- */
 	void *file;
-	struct file *ffile;
+	int ref_count;
+	atomic_t mmap_count;
+	unsigned int f_flags;
 	void (*pcm_release)(struct snd_pcm_substream *);
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
@@ -387,7 +388,7 @@
 	unsigned int hw_opened: 1;
 };
 
-#define SUBSTREAM_BUSY(substream) ((substream)->file != NULL)
+#define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0)
 
 
 struct snd_pcm_str {
@@ -825,14 +826,6 @@
 
 void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params);
 void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params, snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_near(struct snd_pcm_substream *substream, 
-			  struct snd_pcm_hw_params *params,
-			  snd_pcm_hw_param_t var, 
-			  unsigned int val, int *dir);
-int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
-			 struct snd_pcm_hw_params *params,
-			 snd_pcm_hw_param_t var,
-			 unsigned int val, int dir);
 int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
 
 int snd_pcm_hw_refine(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params);
@@ -979,13 +972,13 @@
 static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area)
 {
 	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data;
-	atomic_inc(&substream->runtime->mmap_count);
+	atomic_inc(&substream->mmap_count);
 }
 
 static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area)
 {
 	struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data;
-	atomic_dec(&substream->runtime->mmap_count);
+	atomic_dec(&substream->mmap_count);
 }
 
 /* mmap for io-memory area */
diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h
index fb18aef7..85cf1cf 100644
--- a/include/sound/pcm_params.h
+++ b/include/sound/pcm_params.h
@@ -22,29 +22,21 @@
  *
  */
 
-extern int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
-				 snd_pcm_hw_param_t var, const struct snd_mask *val);
-extern unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
-					       snd_pcm_hw_param_t var, int *dir);
-extern unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
-					       snd_pcm_hw_param_t var, int *dir);
-extern int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
-				 snd_pcm_hw_param_t var, unsigned int val, int dir);
-extern int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
-					snd_pcm_hw_param_t var);
-extern int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
-				 snd_pcm_hw_param_t var, unsigned int val, int dir);
-
-/* To share the same code we have  alsa-lib */
-#define INLINE static inline
-#define assert(a) (void)(a)
+int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, 
+			   struct snd_pcm_hw_params *params,
+			   snd_pcm_hw_param_t var, int *dir);
+int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, 
+			  struct snd_pcm_hw_params *params,
+			  snd_pcm_hw_param_t var, int *dir);
+int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
+			   snd_pcm_hw_param_t var, int *dir);
 
 #define SNDRV_MASK_BITS	64	/* we use so far 64bits only */
 #define SNDRV_MASK_SIZE	(SNDRV_MASK_BITS / 32)
 #define MASK_OFS(i)	((i) >> 5)
 #define MASK_BIT(i)	(1U << ((i) & 31))
 
-INLINE unsigned int ld2(u_int32_t v)
+static inline unsigned int ld2(u_int32_t v)
 {
         unsigned r = 0;
 
@@ -69,22 +61,22 @@
         return r;
 }
 
-INLINE size_t snd_mask_sizeof(void)
+static inline size_t snd_mask_sizeof(void)
 {
 	return sizeof(struct snd_mask);
 }
 
-INLINE void snd_mask_none(struct snd_mask *mask)
+static inline void snd_mask_none(struct snd_mask *mask)
 {
 	memset(mask, 0, sizeof(*mask));
 }
 
-INLINE void snd_mask_any(struct snd_mask *mask)
+static inline void snd_mask_any(struct snd_mask *mask)
 {
 	memset(mask, 0xff, SNDRV_MASK_SIZE * sizeof(u_int32_t));
 }
 
-INLINE int snd_mask_empty(const struct snd_mask *mask)
+static inline int snd_mask_empty(const struct snd_mask *mask)
 {
 	int i;
 	for (i = 0; i < SNDRV_MASK_SIZE; i++)
@@ -93,10 +85,9 @@
 	return 1;
 }
 
-INLINE unsigned int snd_mask_min(const struct snd_mask *mask)
+static inline unsigned int snd_mask_min(const struct snd_mask *mask)
 {
 	int i;
-	assert(!snd_mask_empty(mask));
 	for (i = 0; i < SNDRV_MASK_SIZE; i++) {
 		if (mask->bits[i])
 			return ffs(mask->bits[i]) - 1 + (i << 5);
@@ -104,10 +95,9 @@
 	return 0;
 }
 
-INLINE unsigned int snd_mask_max(const struct snd_mask *mask)
+static inline unsigned int snd_mask_max(const struct snd_mask *mask)
 {
 	int i;
-	assert(!snd_mask_empty(mask));
 	for (i = SNDRV_MASK_SIZE - 1; i >= 0; i--) {
 		if (mask->bits[i])
 			return ld2(mask->bits[i]) + (i << 5);
@@ -115,70 +105,68 @@
 	return 0;
 }
 
-INLINE void snd_mask_set(struct snd_mask *mask, unsigned int val)
+static inline void snd_mask_set(struct snd_mask *mask, unsigned int val)
 {
-	assert(val <= SNDRV_MASK_BITS);
 	mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
 }
 
-INLINE void snd_mask_reset(struct snd_mask *mask, unsigned int val)
+static inline void snd_mask_reset(struct snd_mask *mask, unsigned int val)
 {
-	assert(val <= SNDRV_MASK_BITS);
 	mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
 }
 
-INLINE void snd_mask_set_range(struct snd_mask *mask, unsigned int from, unsigned int to)
+static inline void snd_mask_set_range(struct snd_mask *mask,
+				      unsigned int from, unsigned int to)
 {
 	unsigned int i;
-	assert(to <= SNDRV_MASK_BITS && from <= to);
 	for (i = from; i <= to; i++)
 		mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
 }
 
-INLINE void snd_mask_reset_range(struct snd_mask *mask, unsigned int from, unsigned int to)
+static inline void snd_mask_reset_range(struct snd_mask *mask,
+					unsigned int from, unsigned int to)
 {
 	unsigned int i;
-	assert(to <= SNDRV_MASK_BITS && from <= to);
 	for (i = from; i <= to; i++)
 		mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
 }
 
-INLINE void snd_mask_leave(struct snd_mask *mask, unsigned int val)
+static inline void snd_mask_leave(struct snd_mask *mask, unsigned int val)
 {
 	unsigned int v;
-	assert(val <= SNDRV_MASK_BITS);
 	v = mask->bits[MASK_OFS(val)] & MASK_BIT(val);
 	snd_mask_none(mask);
 	mask->bits[MASK_OFS(val)] = v;
 }
 
-INLINE void snd_mask_intersect(struct snd_mask *mask, const struct snd_mask *v)
+static inline void snd_mask_intersect(struct snd_mask *mask,
+				      const struct snd_mask *v)
 {
 	int i;
 	for (i = 0; i < SNDRV_MASK_SIZE; i++)
 		mask->bits[i] &= v->bits[i];
 }
 
-INLINE int snd_mask_eq(const struct snd_mask *mask, const struct snd_mask *v)
+static inline int snd_mask_eq(const struct snd_mask *mask,
+			      const struct snd_mask *v)
 {
 	return ! memcmp(mask, v, SNDRV_MASK_SIZE * sizeof(u_int32_t));
 }
 
-INLINE void snd_mask_copy(struct snd_mask *mask, const struct snd_mask *v)
+static inline void snd_mask_copy(struct snd_mask *mask,
+				 const struct snd_mask *v)
 {
 	*mask = *v;
 }
 
-INLINE int snd_mask_test(const struct snd_mask *mask, unsigned int val)
+static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val)
 {
-	assert(val <= SNDRV_MASK_BITS);
 	return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
 }
 
-INLINE int snd_mask_single(const struct snd_mask *mask)
+static inline int snd_mask_single(const struct snd_mask *mask)
 {
 	int i, c = 0;
-	assert(!snd_mask_empty(mask));
 	for (i = 0; i < SNDRV_MASK_SIZE; i++) {
 		if (! mask->bits[i])
 			continue;
@@ -191,10 +179,10 @@
 	return 1;
 }
 
-INLINE int snd_mask_refine(struct snd_mask *mask, const struct snd_mask *v)
+static inline int snd_mask_refine(struct snd_mask *mask,
+				  const struct snd_mask *v)
 {
 	struct snd_mask old;
-	assert(!snd_mask_empty(mask));
 	snd_mask_copy(&old, mask);
 	snd_mask_intersect(mask, v);
 	if (snd_mask_empty(mask))
@@ -202,27 +190,24 @@
 	return !snd_mask_eq(mask, &old);
 }
 
-INLINE int snd_mask_refine_first(struct snd_mask *mask)
+static inline int snd_mask_refine_first(struct snd_mask *mask)
 {
-	assert(!snd_mask_empty(mask));
 	if (snd_mask_single(mask))
 		return 0;
 	snd_mask_leave(mask, snd_mask_min(mask));
 	return 1;
 }
 
-INLINE int snd_mask_refine_last(struct snd_mask *mask)
+static inline int snd_mask_refine_last(struct snd_mask *mask)
 {
-	assert(!snd_mask_empty(mask));
 	if (snd_mask_single(mask))
 		return 0;
 	snd_mask_leave(mask, snd_mask_max(mask));
 	return 1;
 }
 
-INLINE int snd_mask_refine_min(struct snd_mask *mask, unsigned int val)
+static inline int snd_mask_refine_min(struct snd_mask *mask, unsigned int val)
 {
-	assert(!snd_mask_empty(mask));
 	if (snd_mask_min(mask) >= val)
 		return 0;
 	snd_mask_reset_range(mask, 0, val - 1);
@@ -231,9 +216,8 @@
 	return 1;
 }
 
-INLINE int snd_mask_refine_max(struct snd_mask *mask, unsigned int val)
+static inline int snd_mask_refine_max(struct snd_mask *mask, unsigned int val)
 {
-	assert(!snd_mask_empty(mask));
 	if (snd_mask_max(mask) <= val)
 		return 0;
 	snd_mask_reset_range(mask, val + 1, SNDRV_MASK_BITS);
@@ -242,10 +226,9 @@
 	return 1;
 }
 
-INLINE int snd_mask_refine_set(struct snd_mask *mask, unsigned int val)
+static inline int snd_mask_refine_set(struct snd_mask *mask, unsigned int val)
 {
 	int changed;
-	assert(!snd_mask_empty(mask));
 	changed = !snd_mask_single(mask);
 	snd_mask_leave(mask, val);
 	if (snd_mask_empty(mask))
@@ -253,13 +236,12 @@
 	return changed;
 }
 
-INLINE int snd_mask_value(const struct snd_mask *mask)
+static inline int snd_mask_value(const struct snd_mask *mask)
 {
-	assert(!snd_mask_empty(mask));
 	return snd_mask_min(mask);
 }
 
-INLINE void snd_interval_any(struct snd_interval *i)
+static inline void snd_interval_any(struct snd_interval *i)
 {
 	i->min = 0;
 	i->openmin = 0;
@@ -269,63 +251,59 @@
 	i->empty = 0;
 }
 
-INLINE void snd_interval_none(struct snd_interval *i)
+static inline void snd_interval_none(struct snd_interval *i)
 {
 	i->empty = 1;
 }
 
-INLINE int snd_interval_checkempty(const struct snd_interval *i)
+static inline int snd_interval_checkempty(const struct snd_interval *i)
 {
 	return (i->min > i->max ||
 		(i->min == i->max && (i->openmin || i->openmax)));
 }
 
-INLINE int snd_interval_empty(const struct snd_interval *i)
+static inline int snd_interval_empty(const struct snd_interval *i)
 {
 	return i->empty;
 }
 
-INLINE int snd_interval_single(const struct snd_interval *i)
+static inline int snd_interval_single(const struct snd_interval *i)
 {
-	assert(!snd_interval_empty(i));
 	return (i->min == i->max || 
 		(i->min + 1 == i->max && i->openmax));
 }
 
-INLINE int snd_interval_value(const struct snd_interval *i)
+static inline int snd_interval_value(const struct snd_interval *i)
 {
-	assert(snd_interval_single(i));
 	return i->min;
 }
 
-INLINE int snd_interval_min(const struct snd_interval *i)
+static inline int snd_interval_min(const struct snd_interval *i)
 {
-	assert(!snd_interval_empty(i));
 	return i->min;
 }
 
-INLINE int snd_interval_max(const struct snd_interval *i)
+static inline int snd_interval_max(const struct snd_interval *i)
 {
 	unsigned int v;
-	assert(!snd_interval_empty(i));
 	v = i->max;
 	if (i->openmax)
 		v--;
 	return v;
 }
 
-INLINE int snd_interval_test(const struct snd_interval *i, unsigned int val)
+static inline int snd_interval_test(const struct snd_interval *i, unsigned int val)
 {
 	return !((i->min > val || (i->min == val && i->openmin) ||
 		  i->max < val || (i->max == val && i->openmax)));
 }
 
-INLINE void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s)
+static inline void snd_interval_copy(struct snd_interval *d, const struct snd_interval *s)
 {
 	*d = *s;
 }
 
-INLINE int snd_interval_setinteger(struct snd_interval *i)
+static inline int snd_interval_setinteger(struct snd_interval *i)
 {
 	if (i->integer)
 		return 0;
@@ -335,7 +313,7 @@
 	return 1;
 }
 
-INLINE int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2)
+static inline int snd_interval_eq(const struct snd_interval *i1, const struct snd_interval *i2)
 {
 	if (i1->empty)
 		return i2->empty;
@@ -359,8 +337,5 @@
 	return 0;
 }
 
-#undef INLINE
-#undef assert
-
 #endif /* __SOUND_PCM_PARAMS_H */
 
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 584e73d..7dbcd10 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -46,6 +46,7 @@
 
 struct snd_rawmidi;
 struct snd_rawmidi_substream;
+struct snd_seq_port_info;
 
 struct snd_rawmidi_ops {
 	int (*open) (struct snd_rawmidi_substream * substream);
@@ -57,6 +58,8 @@
 struct snd_rawmidi_global_ops {
 	int (*dev_register) (struct snd_rawmidi * rmidi);
 	int (*dev_unregister) (struct snd_rawmidi * rmidi);
+	void (*get_port_info)(struct snd_rawmidi *rmidi, int number,
+			      struct snd_seq_port_info *info);
 };
 
 struct snd_rawmidi_runtime {
diff --git a/include/sound/tea575x-tuner.h b/include/sound/tea575x-tuner.h
index a4f55452..b5067d3 100644
--- a/include/sound/tea575x-tuner.h
+++ b/include/sound/tea575x-tuner.h
@@ -20,9 +20,10 @@
  *   along with this program; if not, write to the Free Software
  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- */      
+ */
 
 #include <linux/videodev.h>
+#include <media/v4l2-dev.h>
 
 struct snd_tea575x;
 
diff --git a/include/sound/version.h b/include/sound/version.h
index 4f0e658..2ee849d 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
 /* include/version.h.  Generated by configure.  */
-#define CONFIG_SND_VERSION "1.0.11rc4"
-#define CONFIG_SND_DATE " (Wed Mar 22 10:27:24 2006 UTC)"
+#define CONFIG_SND_VERSION "1.0.12rc1"
+#define CONFIG_SND_DATE " (Thu Jun 22 13:55:50 2006 UTC)"
diff --git a/include/video/edid.h b/include/video/edid.h
index b913f19..f6a42d6 100644
--- a/include/video/edid.h
+++ b/include/video/edid.h
@@ -3,7 +3,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
 
 #ifdef CONFIG_X86
 struct edid_info {
diff --git a/include/video/vga.h b/include/video/vga.h
index 700d6c8..b49a512 100644
--- a/include/video/vga.h
+++ b/include/video/vga.h
@@ -17,7 +17,6 @@
 #ifndef __linux_video_vga_h__
 #define __linux_video_vga_h__
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/io.h>
 #ifndef CONFIG_AMIGA
diff --git a/init/Kconfig b/init/Kconfig
index 3b36a1d..f70f2fd 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1,3 +1,11 @@
+config DEFCONFIG_LIST
+	string
+	option defconfig_list
+	default "/lib/modules/$UNAME_RELEASE/.config"
+	default "/etc/kernel-config"
+	default "/boot/config-$UNAME_RELEASE"
+	default "arch/$ARCH/defconfig"
+
 menu "Code maturity level options"
 
 config EXPERIMENTAL
@@ -151,7 +159,8 @@
 	  at <http://www.physik3.uni-rostock.de/tim/kernel/utils/acct/>.
 
 config SYSCTL
-	bool "Sysctl support"
+	bool "Sysctl support" if EMBEDDED
+	default y
 	---help---
 	  The sysctl interface provides a means of dynamically changing
 	  certain kernel parameters and variables on the fly without requiring
@@ -182,7 +191,8 @@
 	help
 	  Enable low-overhead system-call auditing infrastructure that
 	  can be used independently or with another kernel subsystem,
-	  such as SELinux.
+	  such as SELinux.  To use audit's filesystem watch feature, please
+	  ensure that INOTIFY is configured.
 
 config IKCONFIG
 	bool "Kernel .config support"
@@ -234,16 +244,6 @@
 	help
 	  This enables the legacy 16-bit UID syscall wrappers.
 
-config VM86
-	depends X86
-	default y
-	bool "Enable VM86 support" if EMBEDDED
-	help
-          This option is required by programs like DOSEMU to run 16-bit legacy
-	  code on X86 processors. It also may be needed by software like
-          XFree86 to initialize some video cards via BIOS. Disabling this
-          option saves about 6k.
-
 config CC_OPTIMIZE_FOR_SIZE
 	bool "Optimize for size (Look out for broken compilers!)"
 	default y
@@ -339,9 +339,14 @@
 	  kernel data structures. This saves memory on small machines,
 	  but may reduce performance.
 
+config RT_MUTEXES
+	boolean
+	select PLIST
+
 config FUTEX
 	bool "Enable futex support" if EMBEDDED
 	default y
+	select RT_MUTEXES
 	help
 	  Disabling this option will cause the kernel to be built without
 	  support for "fast userspace mutexes".  The resulting kernel may not
@@ -389,9 +394,6 @@
 	default !SLAB
 	bool
 
-config OBSOLETE_INTERMODULE
-	tristate
-
 menu "Loadable module support"
 
 config MODULES
diff --git a/init/do_mounts.c b/init/do_mounts.c
index f4b7b9d..21b3b8f 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -409,6 +409,10 @@
 
 	if (saved_root_name[0]) {
 		root_device_name = saved_root_name;
+		if (!strncmp(root_device_name, "mtd", 3)) {
+			mount_block_root(root_device_name, root_mountflags);
+			goto out;
+		}
 		ROOT_DEV = name_to_dev_t(root_device_name);
 		if (strncmp(root_device_name, "/dev/", 5) == 0)
 			root_device_name += 5;
diff --git a/init/initramfs.c b/init/initramfs.c
index f81cfa4..d28c109 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -30,6 +30,7 @@
 
 static __initdata struct hash {
 	int ino, minor, major;
+	mode_t mode;
 	struct hash *next;
 	char name[N_ALIGN(PATH_MAX)];
 } *head[32];
@@ -41,7 +42,8 @@
 	return tmp & 31;
 }
 
-static char __init *find_link(int major, int minor, int ino, char *name)
+static char __init *find_link(int major, int minor, int ino,
+			      mode_t mode, char *name)
 {
 	struct hash **p, *q;
 	for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
@@ -51,14 +53,17 @@
 			continue;
 		if ((*p)->major != major)
 			continue;
+		if (((*p)->mode ^ mode) & S_IFMT)
+			continue;
 		return (*p)->name;
 	}
 	q = (struct hash *)malloc(sizeof(struct hash));
 	if (!q)
 		panic("can't allocate link hash entry");
-	q->ino = ino;
-	q->minor = minor;
 	q->major = major;
+	q->minor = minor;
+	q->ino = ino;
+	q->mode = mode;
 	strcpy(q->name, name);
 	q->next = NULL;
 	*p = q;
@@ -229,13 +234,25 @@
 static int __init maybe_link(void)
 {
 	if (nlink >= 2) {
-		char *old = find_link(major, minor, ino, collected);
+		char *old = find_link(major, minor, ino, mode, collected);
 		if (old)
 			return (sys_link(old, collected) < 0) ? -1 : 1;
 	}
 	return 0;
 }
 
+static void __init clean_path(char *path, mode_t mode)
+{
+	struct stat st;
+
+	if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) {
+		if (S_ISDIR(st.st_mode))
+			sys_rmdir(path);
+		else
+			sys_unlink(path);
+	}
+}
+
 static __initdata int wfd;
 
 static int __init do_name(void)
@@ -248,9 +265,15 @@
 	}
 	if (dry_run)
 		return 0;
+	clean_path(collected, mode);
 	if (S_ISREG(mode)) {
-		if (maybe_link() >= 0) {
-			wfd = sys_open(collected, O_WRONLY|O_CREAT, mode);
+		int ml = maybe_link();
+		if (ml >= 0) {
+			int openflags = O_WRONLY|O_CREAT;
+			if (ml != 1)
+				openflags |= O_TRUNC;
+			wfd = sys_open(collected, openflags, mode);
+
 			if (wfd >= 0) {
 				sys_fchown(wfd, uid, gid);
 				sys_fchmod(wfd, mode);
@@ -291,6 +314,7 @@
 static int __init do_symlink(void)
 {
 	collected[N_ALIGN(name_len) + body_len] = '\0';
+	clean_path(collected, 0);
 	sys_symlink(collected + N_ALIGN(name_len), collected);
 	sys_lchown(collected, uid, gid);
 	state = SkipIt;
diff --git a/init/main.c b/init/main.c
index f715b9b..0d57f6c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -47,6 +47,8 @@
 #include <linux/rmap.h>
 #include <linux/mempolicy.h>
 #include <linux/key.h>
+#include <linux/unwind.h>
+#include <linux/buffer_head.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -79,7 +81,6 @@
 extern void sbus_init(void);
 extern void sysctl_init(void);
 extern void signals_init(void);
-extern void buffer_init(void);
 extern void pidhash_init(void);
 extern void pidmap_init(void);
 extern void prio_tree_init(void);
@@ -482,6 +483,7 @@
 		   __stop___param - __start___param,
 		   &unknown_bootoption);
 	sort_main_extable();
+	unwind_init();
 	trap_init();
 	rcu_init();
 	init_IRQ();
@@ -490,6 +492,7 @@
 	hrtimers_init();
 	softirq_init();
 	time_init();
+	timekeeping_init();
 
 	/*
 	 * HACK ALERT! This is early. We're enabling the console before
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 41ecbd4..02e6f67 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -8,6 +8,8 @@
  * Lockless receive & send, fd based notify:
  * 			    Manfred Spraul	    (manfred@colorfullife.com)
  *
+ * Audit:                   George Wilson           (ltcgcw@us.ibm.com)
+ *
  * This file is released under the GPL.
  */
 
@@ -24,6 +26,7 @@
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/syscalls.h>
+#include <linux/audit.h>
 #include <linux/signal.h>
 #include <linux/mutex.h>
 
@@ -202,11 +205,11 @@
 	return 0;
 }
 
-static struct super_block *mqueue_get_sb(struct file_system_type *fs_type,
-					 int flags, const char *dev_name,
-					 void *data)
+static int mqueue_get_sb(struct file_system_type *fs_type,
+			 int flags, const char *dev_name,
+			 void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, mqueue_fill_super);
+	return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
 }
 
 static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
@@ -356,7 +359,7 @@
 	return count;
 }
 
-static int mqueue_flush_file(struct file *filp)
+static int mqueue_flush_file(struct file *filp, fl_owner_t id)
 {
 	struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
 
@@ -657,6 +660,10 @@
 	char *name;
 	int fd, error;
 
+	error = audit_mq_open(oflag, mode, u_attr);
+	if (error != 0)
+		return error;
+
 	if (IS_ERR(name = getname(u_name)))
 		return PTR_ERR(name);
 
@@ -814,6 +821,10 @@
 	long timeout;
 	int ret;
 
+	ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
+	if (ret != 0)
+		return ret;
+
 	if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
 		return -EINVAL;
 
@@ -896,6 +907,10 @@
 	struct mqueue_inode_info *info;
 	struct ext_wait_queue wait;
 
+	ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
+	if (ret != 0)
+		return ret;
+
 	timeout = prepare_timeout(u_abs_timeout);
 
 	ret = -EBADF;
@@ -975,6 +990,10 @@
 	struct mqueue_inode_info *info;
 	struct sk_buff *nc;
 
+	ret = audit_mq_notify(mqdes, u_notification);
+	if (ret != 0)
+		return ret;
+
 	nc = NULL;
 	sock = NULL;
 	if (u_notification != NULL) {
@@ -1115,6 +1134,9 @@
 	omqstat = info->attr;
 	omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
 	if (u_mqstat) {
+		ret = audit_mq_getsetattr(mqdes, &mqstat);
+		if (ret != 0)
+			goto out;
 		if (mqstat.mq_flags & O_NONBLOCK)
 			filp->f_flags |= O_NONBLOCK;
 		else
diff --git a/ipc/msg.c b/ipc/msg.c
index 7d1340c..00f015a 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -454,6 +454,11 @@
 	err = audit_ipc_obj(ipcp);
 	if (err)
 		goto out_unlock_up;
+	if (cmd==IPC_SET) {
+		err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode);
+		if (err)
+			goto out_unlock_up;
+	}
 
 	err = -EPERM;
 	if (current->euid != ipcp->cuid && 
@@ -468,10 +473,6 @@
 	switch (cmd) {
 	case IPC_SET:
 	{
-		err = audit_ipc_set_perm(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
-		if (err)
-			goto out_unlock_up;
-
 		err = -EPERM;
 		if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
 			goto out_unlock_up;
diff --git a/ipc/sem.c b/ipc/sem.c
index 7919f8e..fce0bc8 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -828,6 +828,11 @@
 	if (err)
 		goto out_unlock;
 
+	if (cmd == IPC_SET) {
+		err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
+		if (err)
+			goto out_unlock;
+	}
 	if (current->euid != ipcp->cuid && 
 	    current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
 	    	err=-EPERM;
@@ -844,9 +849,6 @@
 		err = 0;
 		break;
 	case IPC_SET:
-		err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp);
-		if (err)
-			goto out_unlock;
 		ipcp->uid = setbuf.uid;
 		ipcp->gid = setbuf.gid;
 		ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
diff --git a/ipc/shm.c b/ipc/shm.c
index 8098968..fe7ae73 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -643,7 +643,7 @@
 		err = audit_ipc_obj(&(shp->shm_perm));
 		if (err)
 			goto out_unlock_up;
-		err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode, &(shp->shm_perm));
+		err = audit_ipc_set_perm(0, setbuf.uid, setbuf.gid, setbuf.mode);
 		if (err)
 			goto out_unlock_up;
 		err=-EPERM;
@@ -698,7 +698,6 @@
 	int    err;
 	unsigned long flags;
 	unsigned long prot;
-	unsigned long o_flags;
 	int acc_mode;
 	void *user_addr;
 
@@ -725,11 +724,9 @@
 
 	if (shmflg & SHM_RDONLY) {
 		prot = PROT_READ;
-		o_flags = O_RDONLY;
 		acc_mode = S_IRUGO;
 	} else {
 		prot = PROT_READ | PROT_WRITE;
-		o_flags = O_RDWR;
 		acc_mode = S_IRUGO | S_IWUGO;
 	}
 	if (shmflg & SHM_EXEC) {
diff --git a/kernel/Makefile b/kernel/Makefile
index 58908f9..82fb182 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -10,18 +10,22 @@
 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
 	    hrtimer.o
 
+obj-y += time/
 obj-$(CONFIG_DEBUG_MUTEXES) += mutex-debug.o
 obj-$(CONFIG_FUTEX) += futex.o
 ifeq ($(CONFIG_COMPAT),y)
 obj-$(CONFIG_FUTEX) += futex_compat.o
 endif
+obj-$(CONFIG_RT_MUTEXES) += rtmutex.o
+obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o
+obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o spinlock.o
 obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
-obj-$(CONFIG_OBSOLETE_INTERMODULE) += intermodule.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
+obj-$(CONFIG_STACK_UNWIND) += unwind.o
 obj-$(CONFIG_PM) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_KEXEC) += kexec.o
diff --git a/kernel/acct.c b/kernel/acct.c
index b327f4d..126ca43 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -75,7 +75,7 @@
 /*
  * External references and all of the globals.
  */
-static void do_acct_process(long, struct file *);
+static void do_acct_process(struct file *);
 
 /*
  * This structure is used so that all the data protected by lock
@@ -118,7 +118,7 @@
 	spin_unlock(&acct_globals.lock);
 
 	/* May block */
-	if (vfs_statfs(file->f_dentry->d_inode->i_sb, &sbuf))
+	if (vfs_statfs(file->f_dentry, &sbuf))
 		return res;
 	suspend = sbuf.f_blocks * SUSPEND;
 	resume = sbuf.f_blocks * RESUME;
@@ -196,7 +196,7 @@
 	if (old_acct) {
 		mnt_unpin(old_acct->f_vfsmnt);
 		spin_unlock(&acct_globals.lock);
-		do_acct_process(0, old_acct);
+		do_acct_process(old_acct);
 		filp_close(old_acct, NULL);
 		spin_lock(&acct_globals.lock);
 	}
@@ -419,16 +419,15 @@
 /*
  *  do_acct_process does all actual work. Caller holds the reference to file.
  */
-static void do_acct_process(long exitcode, struct file *file)
+static void do_acct_process(struct file *file)
 {
+	struct pacct_struct *pacct = &current->signal->pacct;
 	acct_t ac;
 	mm_segment_t fs;
-	unsigned long vsize;
 	unsigned long flim;
 	u64 elapsed;
 	u64 run_time;
 	struct timespec uptime;
-	unsigned long jiffies;
 
 	/*
 	 * First check to see if there is enough free_space to continue
@@ -469,12 +468,6 @@
 #endif
 	do_div(elapsed, AHZ);
 	ac.ac_btime = xtime.tv_sec - elapsed;
-	jiffies = cputime_to_jiffies(cputime_add(current->utime,
-						 current->signal->utime));
-	ac.ac_utime = encode_comp_t(jiffies_to_AHZ(jiffies));
-	jiffies = cputime_to_jiffies(cputime_add(current->stime,
-						 current->signal->stime));
-	ac.ac_stime = encode_comp_t(jiffies_to_AHZ(jiffies));
 	/* we really need to bite the bullet and change layout */
 	ac.ac_uid = current->uid;
 	ac.ac_gid = current->gid;
@@ -496,37 +489,18 @@
 		old_encode_dev(tty_devnum(current->signal->tty)) : 0;
 	read_unlock(&tasklist_lock);
 
-	ac.ac_flag = 0;
-	if (current->flags & PF_FORKNOEXEC)
-		ac.ac_flag |= AFORK;
-	if (current->flags & PF_SUPERPRIV)
-		ac.ac_flag |= ASU;
-	if (current->flags & PF_DUMPCORE)
-		ac.ac_flag |= ACORE;
-	if (current->flags & PF_SIGNALED)
-		ac.ac_flag |= AXSIG;
-
-	vsize = 0;
-	if (current->mm) {
-		struct vm_area_struct *vma;
-		down_read(&current->mm->mmap_sem);
-		vma = current->mm->mmap;
-		while (vma) {
-			vsize += vma->vm_end - vma->vm_start;
-			vma = vma->vm_next;
-		}
-		up_read(&current->mm->mmap_sem);
-	}
-	vsize = vsize / 1024;
-	ac.ac_mem = encode_comp_t(vsize);
+	spin_lock(&current->sighand->siglock);
+	ac.ac_utime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_utime)));
+	ac.ac_stime = encode_comp_t(jiffies_to_AHZ(cputime_to_jiffies(pacct->ac_stime)));
+	ac.ac_flag = pacct->ac_flag;
+	ac.ac_mem = encode_comp_t(pacct->ac_mem);
+	ac.ac_minflt = encode_comp_t(pacct->ac_minflt);
+	ac.ac_majflt = encode_comp_t(pacct->ac_majflt);
+	ac.ac_exitcode = pacct->ac_exitcode;
+	spin_unlock(&current->sighand->siglock);
 	ac.ac_io = encode_comp_t(0 /* current->io_usage */);	/* %% */
 	ac.ac_rw = encode_comp_t(ac.ac_io / 1024);
-	ac.ac_minflt = encode_comp_t(current->signal->min_flt +
-				     current->min_flt);
-	ac.ac_majflt = encode_comp_t(current->signal->maj_flt +
-				     current->maj_flt);
 	ac.ac_swaps = encode_comp_t(0);
-	ac.ac_exitcode = exitcode;
 
 	/*
          * Kernel segment override to datasegment and write it
@@ -546,12 +520,64 @@
 }
 
 /**
+ * acct_init_pacct - initialize a new pacct_struct
+ * @pacct: per-process accounting info struct to initialize
+ */
+void acct_init_pacct(struct pacct_struct *pacct)
+{
+	memset(pacct, 0, sizeof(struct pacct_struct));
+	pacct->ac_utime = pacct->ac_stime = cputime_zero;
+}
+
+/**
+ * acct_collect - collect accounting information into pacct_struct
+ * @exitcode: task exit code
+ * @group_dead: not 0, if this thread is the last one in the process.
+ */
+void acct_collect(long exitcode, int group_dead)
+{
+	struct pacct_struct *pacct = &current->signal->pacct;
+	unsigned long vsize = 0;
+
+	if (group_dead && current->mm) {
+		struct vm_area_struct *vma;
+		down_read(&current->mm->mmap_sem);
+		vma = current->mm->mmap;
+		while (vma) {
+			vsize += vma->vm_end - vma->vm_start;
+			vma = vma->vm_next;
+		}
+		up_read(&current->mm->mmap_sem);
+	}
+
+	spin_lock_irq(&current->sighand->siglock);
+	if (group_dead)
+		pacct->ac_mem = vsize / 1024;
+	if (thread_group_leader(current)) {
+		pacct->ac_exitcode = exitcode;
+		if (current->flags & PF_FORKNOEXEC)
+			pacct->ac_flag |= AFORK;
+	}
+	if (current->flags & PF_SUPERPRIV)
+		pacct->ac_flag |= ASU;
+	if (current->flags & PF_DUMPCORE)
+		pacct->ac_flag |= ACORE;
+	if (current->flags & PF_SIGNALED)
+		pacct->ac_flag |= AXSIG;
+	pacct->ac_utime = cputime_add(pacct->ac_utime, current->utime);
+	pacct->ac_stime = cputime_add(pacct->ac_stime, current->stime);
+	pacct->ac_minflt += current->min_flt;
+	pacct->ac_majflt += current->maj_flt;
+	spin_unlock_irq(&current->sighand->siglock);
+}
+
+/**
  * acct_process - now just a wrapper around do_acct_process
  * @exitcode: task exit code
  *
  * handles process accounting for an exiting task
  */
-void acct_process(long exitcode)
+void acct_process(void)
 {
 	struct file *file = NULL;
 
@@ -570,7 +596,7 @@
 	get_file(file);
 	spin_unlock(&acct_globals.lock);
 
-	do_acct_process(exitcode, file);
+	do_acct_process(file);
 	fput(file);
 }
 
@@ -599,9 +625,7 @@
  */
 void acct_clear_integrals(struct task_struct *tsk)
 {
-	if (tsk) {
-		tsk->acct_stimexpd = 0;
-		tsk->acct_rss_mem1 = 0;
-		tsk->acct_vm_mem1 = 0;
-	}
+	tsk->acct_stimexpd = 0;
+	tsk->acct_rss_mem1 = 0;
+	tsk->acct_vm_mem1 = 0;
 }
diff --git a/kernel/audit.c b/kernel/audit.c
index df57b49..82443fb 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -56,6 +56,7 @@
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/selinux.h>
+#include <linux/inotify.h>
 
 #include "audit.h"
 
@@ -89,6 +90,7 @@
 /* The identity of the user shutting down the audit system. */
 uid_t		audit_sig_uid = -1;
 pid_t		audit_sig_pid = -1;
+u32		audit_sig_sid = 0;
 
 /* Records can be lost in several ways:
    0) [suppressed in audit_alloc]
@@ -102,6 +104,12 @@
 /* The netlink socket. */
 static struct sock *audit_sock;
 
+/* Inotify handle. */
+struct inotify_handle *audit_ih;
+
+/* Hash for inode-based rules */
+struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
+
 /* The audit_freelist is a list of pre-allocated audit buffers (if more
  * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of
  * being placed on the freelist). */
@@ -114,10 +122,8 @@
 static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
 static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
 
-/* The netlink socket is only to be read by 1 CPU, which lets us assume
- * that list additions and deletions never happen simultaneously in
- * auditsc.c */
-DEFINE_MUTEX(audit_netlink_mutex);
+/* Serialize requests from userspace. */
+static DEFINE_MUTEX(audit_cmd_mutex);
 
 /* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
  * audit records.  Since printk uses a 1024 byte buffer, this buffer
@@ -250,7 +256,7 @@
 			"audit_rate_limit=%d old=%d by auid=%u",
 			limit, old, loginuid);
 	audit_rate_limit = limit;
-	return old;
+	return 0;
 }
 
 static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
@@ -273,7 +279,7 @@
 			"audit_backlog_limit=%d old=%d by auid=%u",
 			limit, old, loginuid);
 	audit_backlog_limit = limit;
-	return old;
+	return 0;
 }
 
 static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
@@ -299,7 +305,7 @@
 			"audit_enabled=%d old=%d by auid=%u",
 			state, old, loginuid);
 	audit_enabled = state;
-	return old;
+	return 0;
 }
 
 static int audit_set_failure(int state, uid_t loginuid, u32 sid)
@@ -327,7 +333,7 @@
 			"audit_failure=%d old=%d by auid=%u",
 			state, old, loginuid);
 	audit_failure = state;
-	return old;
+	return 0;
 }
 
 static int kauditd_thread(void *dummy)
@@ -363,9 +369,52 @@
 			remove_wait_queue(&kauditd_wait, &wait);
 		}
 	}
+}
+
+int audit_send_list(void *_dest)
+{
+	struct audit_netlink_list *dest = _dest;
+	int pid = dest->pid;
+	struct sk_buff *skb;
+
+	/* wait for parent to finish and send an ACK */
+	mutex_lock(&audit_cmd_mutex);
+	mutex_unlock(&audit_cmd_mutex);
+
+	while ((skb = __skb_dequeue(&dest->q)) != NULL)
+		netlink_unicast(audit_sock, skb, pid, 0);
+
+	kfree(dest);
+
 	return 0;
 }
 
+struct sk_buff *audit_make_reply(int pid, int seq, int type, int done,
+				 int multi, void *payload, int size)
+{
+	struct sk_buff	*skb;
+	struct nlmsghdr	*nlh;
+	int		len = NLMSG_SPACE(size);
+	void		*data;
+	int		flags = multi ? NLM_F_MULTI : 0;
+	int		t     = done  ? NLMSG_DONE  : type;
+
+	skb = alloc_skb(len, GFP_KERNEL);
+	if (!skb)
+		return NULL;
+
+	nlh		 = NLMSG_PUT(skb, pid, seq, t, size);
+	nlh->nlmsg_flags = flags;
+	data		 = NLMSG_DATA(nlh);
+	memcpy(data, payload, size);
+	return skb;
+
+nlmsg_failure:			/* Used by NLMSG_PUT */
+	if (skb)
+		kfree_skb(skb);
+	return NULL;
+}
+
 /**
  * audit_send_reply - send an audit reply message via netlink
  * @pid: process id to send reply to
@@ -383,29 +432,13 @@
 		      void *payload, int size)
 {
 	struct sk_buff	*skb;
-	struct nlmsghdr	*nlh;
-	int		len = NLMSG_SPACE(size);
-	void		*data;
-	int		flags = multi ? NLM_F_MULTI : 0;
-	int		t     = done  ? NLMSG_DONE  : type;
-
-	skb = alloc_skb(len, GFP_KERNEL);
+	skb = audit_make_reply(pid, seq, type, done, multi, payload, size);
 	if (!skb)
 		return;
-
-	nlh		 = NLMSG_PUT(skb, pid, seq, t, size);
-	nlh->nlmsg_flags = flags;
-	data		 = NLMSG_DATA(nlh);
-	memcpy(data, payload, size);
-
 	/* Ignore failure. It'll only happen if the sender goes away,
 	   because our timeout is set to infinite. */
 	netlink_unicast(audit_sock, skb, pid, 0);
 	return;
-
-nlmsg_failure:			/* Used by NLMSG_PUT */
-	if (skb)
-		kfree_skb(skb);
 }
 
 /*
@@ -451,7 +484,9 @@
 	struct audit_buffer	*ab;
 	u16			msg_type = nlh->nlmsg_type;
 	uid_t			loginuid; /* loginuid of sender */
-	struct audit_sig_info   sig_data;
+	struct audit_sig_info   *sig_data;
+	char			*ctx;
+	u32			len;
 
 	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
 	if (err)
@@ -503,12 +538,9 @@
 		if (status_get->mask & AUDIT_STATUS_PID) {
 			int old   = audit_pid;
 			if (sid) {
-				char *ctx = NULL;
-				u32 len;
-				int rc;
-				if ((rc = selinux_ctxid_to_string(
+				if ((err = selinux_ctxid_to_string(
 						sid, &ctx, &len)))
-					return rc;
+					return err;
 				else
 					audit_log(NULL, GFP_KERNEL,
 						AUDIT_CONFIG_CHANGE,
@@ -523,10 +555,10 @@
 			audit_pid = status_get->pid;
 		}
 		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
-			audit_set_rate_limit(status_get->rate_limit,
+			err = audit_set_rate_limit(status_get->rate_limit,
 							 loginuid, sid);
 		if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
-			audit_set_backlog_limit(status_get->backlog_limit,
+			err = audit_set_backlog_limit(status_get->backlog_limit,
 							loginuid, sid);
 		break;
 	case AUDIT_USER:
@@ -544,8 +576,6 @@
 						 "user pid=%d uid=%u auid=%u",
 						 pid, uid, loginuid);
 				if (sid) {
-					char *ctx = NULL;
-					u32 len;
 					if (selinux_ctxid_to_string(
 							sid, &ctx, &len)) {
 						audit_log_format(ab, 
@@ -584,10 +614,21 @@
 					   loginuid, sid);
 		break;
 	case AUDIT_SIGNAL_INFO:
-		sig_data.uid = audit_sig_uid;
-		sig_data.pid = audit_sig_pid;
+		err = selinux_ctxid_to_string(audit_sig_sid, &ctx, &len);
+		if (err)
+			return err;
+		sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+		if (!sig_data) {
+			kfree(ctx);
+			return -ENOMEM;
+		}
+		sig_data->uid = audit_sig_uid;
+		sig_data->pid = audit_sig_pid;
+		memcpy(sig_data->ctx, ctx, len);
+		kfree(ctx);
 		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 
-				0, 0, &sig_data, sizeof(sig_data));
+				0, 0, sig_data, sizeof(*sig_data) + len);
+		kfree(sig_data);
 		break;
 	default:
 		err = -EINVAL;
@@ -629,20 +670,30 @@
 	struct sk_buff  *skb;
 	unsigned int qlen;
 
-	mutex_lock(&audit_netlink_mutex);
+	mutex_lock(&audit_cmd_mutex);
 
 	for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
 		skb = skb_dequeue(&sk->sk_receive_queue);
 		audit_receive_skb(skb);
 		kfree_skb(skb);
 	}
-	mutex_unlock(&audit_netlink_mutex);
+	mutex_unlock(&audit_cmd_mutex);
 }
 
+#ifdef CONFIG_AUDITSYSCALL
+static const struct inotify_operations audit_inotify_ops = {
+	.handle_event	= audit_handle_ievent,
+	.destroy_watch	= audit_free_parent,
+};
+#endif
 
 /* Initialize audit support at boot time. */
 static int __init audit_init(void)
 {
+#ifdef CONFIG_AUDITSYSCALL
+	int i;
+#endif
+
 	printk(KERN_INFO "audit: initializing netlink socket (%s)\n",
 	       audit_default ? "enabled" : "disabled");
 	audit_sock = netlink_kernel_create(NETLINK_AUDIT, 0, audit_receive,
@@ -661,6 +712,16 @@
 	selinux_audit_set_callback(&selinux_audit_rule_update);
 
 	audit_log(NULL, GFP_KERNEL, AUDIT_KERNEL, "initialized");
+
+#ifdef CONFIG_AUDITSYSCALL
+	audit_ih = inotify_init(&audit_inotify_ops);
+	if (IS_ERR(audit_ih))
+		audit_panic("cannot initialize inotify handle");
+
+	for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
+		INIT_LIST_HEAD(&audit_inode_hash[i]);
+#endif
+
 	return 0;
 }
 __initcall(audit_init);
@@ -690,10 +751,12 @@
 		kfree_skb(ab->skb);
 
 	spin_lock_irqsave(&audit_freelist_lock, flags);
-	if (++audit_freelist_count > AUDIT_MAXFREE)
+	if (audit_freelist_count > AUDIT_MAXFREE)
 		kfree(ab);
-	else
+	else {
+		audit_freelist_count++;
 		list_add(&ab->list, &audit_freelist);
+	}
 	spin_unlock_irqrestore(&audit_freelist_lock, flags);
 }
 
@@ -755,7 +818,7 @@
  */
 unsigned int audit_serial(void)
 {
-	static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
+	static DEFINE_SPINLOCK(serial_lock);
 	static unsigned int serial = 0;
 
 	unsigned long flags;
@@ -988,28 +1051,76 @@
 	skb_put(skb, len << 1); /* new string is twice the old string */
 }
 
+/*
+ * Format a string of no more than slen characters into the audit buffer,
+ * enclosed in quote marks.
+ */
+static void audit_log_n_string(struct audit_buffer *ab, size_t slen,
+			       const char *string)
+{
+	int avail, new_len;
+	unsigned char *ptr;
+	struct sk_buff *skb;
+
+	BUG_ON(!ab->skb);
+	skb = ab->skb;
+	avail = skb_tailroom(skb);
+	new_len = slen + 3;	/* enclosing quotes + null terminator */
+	if (new_len > avail) {
+		avail = audit_expand(ab, new_len);
+		if (!avail)
+			return;
+	}
+	ptr = skb->tail;
+	*ptr++ = '"';
+	memcpy(ptr, string, slen);
+	ptr += slen;
+	*ptr++ = '"';
+	*ptr = 0;
+	skb_put(skb, slen + 2);	/* don't include null terminator */
+}
+
 /**
- * audit_log_unstrustedstring - log a string that may contain random characters
+ * audit_log_n_unstrustedstring - log a string that may contain random characters
  * @ab: audit_buffer
+ * @len: lenth of string (not including trailing null)
  * @string: string to be logged
  *
  * This code will escape a string that is passed to it if the string
  * contains a control character, unprintable character, double quote mark,
  * or a space. Unescaped strings will start and end with a double quote mark.
  * Strings that are escaped are printed in hex (2 digits per char).
+ *
+ * The caller specifies the number of characters in the string to log, which may
+ * or may not be the entire string.
  */
-void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+const char *audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len,
+					const char *string)
 {
 	const unsigned char *p = string;
 
 	while (*p) {
 		if (*p == '"' || *p < 0x21 || *p > 0x7f) {
-			audit_log_hex(ab, string, strlen(string));
-			return;
+			audit_log_hex(ab, string, len);
+			return string + len + 1;
 		}
 		p++;
 	}
-	audit_log_format(ab, "\"%s\"", string);
+	audit_log_n_string(ab, len, string);
+	return p + 1;
+}
+
+/**
+ * audit_log_unstrustedstring - log a string that may contain random characters
+ * @ab: audit_buffer
+ * @string: string to be logged
+ *
+ * Same as audit_log_n_unstrustedstring(), except that strlen is used to
+ * determine string length.
+ */
+const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+{
+	return audit_log_n_untrustedstring(ab, strlen(string), string);
 }
 
 /* This is a helper-function to print the escaped d_path */
diff --git a/kernel/audit.h b/kernel/audit.h
index 6f73392..8323e41 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -19,9 +19,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/audit.h>
+#include <linux/skbuff.h>
 
 /* 0 = no checking
    1 = put_count checking
@@ -53,6 +53,18 @@
 };
 
 /* Rule lists */
+struct audit_parent;
+
+struct audit_watch {
+	atomic_t		count;	/* reference count */
+	char			*path;	/* insertion path */
+	dev_t			dev;	/* associated superblock device */
+	unsigned long		ino;	/* associated inode number */
+	struct audit_parent	*parent; /* associated parent */
+	struct list_head	wlist;	/* entry in parent->watches list */
+	struct list_head	rules;	/* associated rules */
+};
+
 struct audit_field {
 	u32				type;
 	u32				val;
@@ -70,6 +82,9 @@
 	u32			buflen; /* for data alloc on list rules */
 	u32			field_count;
 	struct audit_field	*fields;
+	struct audit_field	*inode_f; /* quick access to an inode field */
+	struct audit_watch	*watch;	/* associated watch */
+	struct list_head	rlist;	/* entry in audit_watch.rules list */
 };
 
 struct audit_entry {
@@ -78,15 +93,53 @@
 	struct audit_krule	rule;
 };
 
-
 extern int audit_pid;
-extern int audit_comparator(const u32 left, const u32 op, const u32 right);
 
+#define AUDIT_INODE_BUCKETS	32
+extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
+
+static inline int audit_hash_ino(u32 ino)
+{
+	return (ino & (AUDIT_INODE_BUCKETS-1));
+}
+
+extern int audit_comparator(const u32 left, const u32 op, const u32 right);
+extern int audit_compare_dname_path(const char *dname, const char *path,
+				    int *dirlen);
+extern struct sk_buff *	    audit_make_reply(int pid, int seq, int type,
+					     int done, int multi,
+					     void *payload, int size);
 extern void		    audit_send_reply(int pid, int seq, int type,
 					     int done, int multi,
 					     void *payload, int size);
 extern void		    audit_log_lost(const char *message);
 extern void		    audit_panic(const char *message);
-extern struct mutex audit_netlink_mutex;
 
+struct audit_netlink_list {
+	int pid;
+	struct sk_buff_head q;
+};
+
+int audit_send_list(void *);
+
+struct inotify_watch;
+extern void audit_free_parent(struct inotify_watch *);
+extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32,
+				const char *, struct inode *);
 extern int selinux_audit_rule_update(void);
+
+#ifdef CONFIG_AUDITSYSCALL
+extern void __audit_signal_info(int sig, struct task_struct *t);
+static inline void audit_signal_info(int sig, struct task_struct *t)
+{
+	if (unlikely(audit_pid && t->tgid == audit_pid))
+		__audit_signal_info(sig, t);
+}
+extern enum audit_state audit_filter_inodes(struct task_struct *,
+					    struct audit_context *);
+extern void audit_set_auditable(struct audit_context *);
+#else
+#define audit_signal_info(s,t)
+#define audit_filter_inodes(t,c) AUDIT_DISABLED
+#define audit_set_auditable(c)
+#endif
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 7c13490..4c99d2c 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -22,13 +22,59 @@
 #include <linux/kernel.h>
 #include <linux/audit.h>
 #include <linux/kthread.h>
+#include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/namei.h>
 #include <linux/netlink.h>
+#include <linux/sched.h>
+#include <linux/inotify.h>
 #include <linux/selinux.h>
 #include "audit.h"
 
-/* There are three lists of rules -- one to search at task creation
- * time, one to search at syscall entry time, and another to search at
- * syscall exit time. */
+/*
+ * Locking model:
+ *
+ * audit_filter_mutex:
+ * 		Synchronizes writes and blocking reads of audit's filterlist
+ * 		data.  Rcu is used to traverse the filterlist and access
+ * 		contents of structs audit_entry, audit_watch and opaque
+ * 		selinux rules during filtering.  If modified, these structures
+ * 		must be copied and replace their counterparts in the filterlist.
+ * 		An audit_parent struct is not accessed during filtering, so may
+ * 		be written directly provided audit_filter_mutex is held.
+ */
+
+/*
+ * Reference counting:
+ *
+ * audit_parent: lifetime is from audit_init_parent() to receipt of an IN_IGNORED
+ * 	event.  Each audit_watch holds a reference to its associated parent.
+ *
+ * audit_watch: if added to lists, lifetime is from audit_init_watch() to
+ * 	audit_remove_watch().  Additionally, an audit_watch may exist
+ * 	temporarily to assist in searching existing filter data.  Each
+ * 	audit_krule holds a reference to its associated watch.
+ */
+
+struct audit_parent {
+	struct list_head	ilist;	/* entry in inotify registration list */
+	struct list_head	watches; /* associated watches */
+	struct inotify_watch	wdata;	/* inotify watch data */
+	unsigned		flags;	/* status flags */
+};
+
+/*
+ * audit_parent status flags:
+ *
+ * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to
+ * a filesystem event to ensure we're adding audit watches to a valid parent.
+ * Technically not needed for IN_DELETE_SELF or IN_UNMOUNT events, as we cannot
+ * receive them while we have nameidata, but must be used for IN_MOVE_SELF which
+ * we can receive while holding nameidata.
+ */
+#define AUDIT_PARENT_INVALID	0x001
+
+/* Audit filter lists, defined in <linux/audit.h> */
 struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
 	LIST_HEAD_INIT(audit_filter_list[0]),
 	LIST_HEAD_INIT(audit_filter_list[1]),
@@ -41,9 +87,53 @@
 #endif
 };
 
+static DEFINE_MUTEX(audit_filter_mutex);
+
+/* Inotify handle */
+extern struct inotify_handle *audit_ih;
+
+/* Inotify events we care about. */
+#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
+
+void audit_free_parent(struct inotify_watch *i_watch)
+{
+	struct audit_parent *parent;
+
+	parent = container_of(i_watch, struct audit_parent, wdata);
+	WARN_ON(!list_empty(&parent->watches));
+	kfree(parent);
+}
+
+static inline void audit_get_watch(struct audit_watch *watch)
+{
+	atomic_inc(&watch->count);
+}
+
+static void audit_put_watch(struct audit_watch *watch)
+{
+	if (atomic_dec_and_test(&watch->count)) {
+		WARN_ON(watch->parent);
+		WARN_ON(!list_empty(&watch->rules));
+		kfree(watch->path);
+		kfree(watch);
+	}
+}
+
+static void audit_remove_watch(struct audit_watch *watch)
+{
+	list_del(&watch->wlist);
+	put_inotify_watch(&watch->parent->wdata);
+	watch->parent = NULL;
+	audit_put_watch(watch); /* match initial get */
+}
+
 static inline void audit_free_rule(struct audit_entry *e)
 {
 	int i;
+
+	/* some rules don't have associated watches */
+	if (e->rule.watch)
+		audit_put_watch(e->rule.watch);
 	if (e->rule.fields)
 		for (i = 0; i < e->rule.field_count; i++) {
 			struct audit_field *f = &e->rule.fields[i];
@@ -60,6 +150,50 @@
 	audit_free_rule(e);
 }
 
+/* Initialize a parent watch entry. */
+static struct audit_parent *audit_init_parent(struct nameidata *ndp)
+{
+	struct audit_parent *parent;
+	s32 wd;
+
+	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+	if (unlikely(!parent))
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&parent->watches);
+	parent->flags = 0;
+
+	inotify_init_watch(&parent->wdata);
+	/* grab a ref so inotify watch hangs around until we take audit_filter_mutex */
+	get_inotify_watch(&parent->wdata);
+	wd = inotify_add_watch(audit_ih, &parent->wdata, ndp->dentry->d_inode,
+			       AUDIT_IN_WATCH);
+	if (wd < 0) {
+		audit_free_parent(&parent->wdata);
+		return ERR_PTR(wd);
+	}
+
+	return parent;
+}
+
+/* Initialize a watch entry. */
+static struct audit_watch *audit_init_watch(char *path)
+{
+	struct audit_watch *watch;
+
+	watch = kzalloc(sizeof(*watch), GFP_KERNEL);
+	if (unlikely(!watch))
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&watch->rules);
+	atomic_set(&watch->count, 1);
+	watch->path = path;
+	watch->dev = (dev_t)-1;
+	watch->ino = (unsigned long)-1;
+
+	return watch;
+}
+
 /* Initialize an audit filterlist entry. */
 static inline struct audit_entry *audit_init_entry(u32 field_count)
 {
@@ -107,6 +241,43 @@
 	return str;
 }
 
+/* Translate an inode field to kernel respresentation. */
+static inline int audit_to_inode(struct audit_krule *krule,
+				 struct audit_field *f)
+{
+	if (krule->listnr != AUDIT_FILTER_EXIT ||
+	    krule->watch || krule->inode_f)
+		return -EINVAL;
+
+	krule->inode_f = f;
+	return 0;
+}
+
+/* Translate a watch string to kernel respresentation. */
+static int audit_to_watch(struct audit_krule *krule, char *path, int len,
+			  u32 op)
+{
+	struct audit_watch *watch;
+
+	if (!audit_ih)
+		return -EOPNOTSUPP;
+
+	if (path[0] != '/' || path[len-1] == '/' ||
+	    krule->listnr != AUDIT_FILTER_EXIT ||
+	    op & ~AUDIT_EQUAL ||
+	    krule->inode_f || krule->watch) /* 1 inode # per rule, for hash */
+		return -EINVAL;
+
+	watch = audit_init_watch(path);
+	if (unlikely(IS_ERR(watch)))
+		return PTR_ERR(watch);
+
+	audit_get_watch(watch);
+	krule->watch = watch;
+
+	return 0;
+}
+
 /* Common user-space to kernel rule translation. */
 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
 {
@@ -128,8 +299,11 @@
 #endif
 		;
 	}
-	if (rule->action != AUDIT_NEVER && rule->action != AUDIT_POSSIBLE &&
-	    rule->action != AUDIT_ALWAYS)
+	if (unlikely(rule->action == AUDIT_POSSIBLE)) {
+		printk(KERN_ERR "AUDIT_POSSIBLE is deprecated\n");
+		goto exit_err;
+	}
+	if (rule->action != AUDIT_NEVER && rule->action != AUDIT_ALWAYS)
 		goto exit_err;
 	if (rule->field_count > AUDIT_MAX_FIELDS)
 		goto exit_err;
@@ -158,6 +332,7 @@
 static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
 {
 	struct audit_entry *entry;
+	struct audit_field *f;
 	int err = 0;
 	int i;
 
@@ -172,14 +347,37 @@
 		f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS);
 		f->val = rule->values[i];
 
-		if (f->type & AUDIT_UNUSED_BITS ||
-		    f->type == AUDIT_SE_USER ||
-		    f->type == AUDIT_SE_ROLE ||
-		    f->type == AUDIT_SE_TYPE ||
-		    f->type == AUDIT_SE_SEN ||
-		    f->type == AUDIT_SE_CLR) {
-			err = -EINVAL;
+		err = -EINVAL;
+		switch(f->type) {
+		default:
 			goto exit_free;
+		case AUDIT_PID:
+		case AUDIT_UID:
+		case AUDIT_EUID:
+		case AUDIT_SUID:
+		case AUDIT_FSUID:
+		case AUDIT_GID:
+		case AUDIT_EGID:
+		case AUDIT_SGID:
+		case AUDIT_FSGID:
+		case AUDIT_LOGINUID:
+		case AUDIT_PERS:
+		case AUDIT_ARCH:
+		case AUDIT_MSGTYPE:
+		case AUDIT_DEVMAJOR:
+		case AUDIT_DEVMINOR:
+		case AUDIT_EXIT:
+		case AUDIT_SUCCESS:
+		case AUDIT_ARG0:
+		case AUDIT_ARG1:
+		case AUDIT_ARG2:
+		case AUDIT_ARG3:
+			break;
+		case AUDIT_INODE:
+			err = audit_to_inode(&entry->rule, f);
+			if (err)
+				goto exit_free;
+			break;
 		}
 
 		entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1;
@@ -196,6 +394,18 @@
 		}
 	}
 
+	f = entry->rule.inode_f;
+	if (f) {
+		switch(f->op) {
+		case AUDIT_NOT_EQUAL:
+			entry->rule.inode_f = NULL;
+		case AUDIT_EQUAL:
+			break;
+		default:
+			goto exit_free;
+		}
+	}
+
 exit_nofree:
 	return entry;
 
@@ -210,6 +420,7 @@
 {
 	int err = 0;
 	struct audit_entry *entry;
+	struct audit_field *f;
 	void *bufp;
 	size_t remain = datasz - sizeof(struct audit_rule_data);
 	int i;
@@ -235,6 +446,29 @@
 		f->se_str = NULL;
 		f->se_rule = NULL;
 		switch(f->type) {
+		case AUDIT_PID:
+		case AUDIT_UID:
+		case AUDIT_EUID:
+		case AUDIT_SUID:
+		case AUDIT_FSUID:
+		case AUDIT_GID:
+		case AUDIT_EGID:
+		case AUDIT_SGID:
+		case AUDIT_FSGID:
+		case AUDIT_LOGINUID:
+		case AUDIT_PERS:
+		case AUDIT_ARCH:
+		case AUDIT_MSGTYPE:
+		case AUDIT_PPID:
+		case AUDIT_DEVMAJOR:
+		case AUDIT_DEVMINOR:
+		case AUDIT_EXIT:
+		case AUDIT_SUCCESS:
+		case AUDIT_ARG0:
+		case AUDIT_ARG1:
+		case AUDIT_ARG2:
+		case AUDIT_ARG3:
+			break;
 		case AUDIT_SE_USER:
 		case AUDIT_SE_ROLE:
 		case AUDIT_SE_TYPE:
@@ -260,6 +494,37 @@
 			} else
 				f->se_str = str;
 			break;
+		case AUDIT_WATCH:
+			str = audit_unpack_string(&bufp, &remain, f->val);
+			if (IS_ERR(str))
+				goto exit_free;
+			entry->rule.buflen += f->val;
+
+			err = audit_to_watch(&entry->rule, str, f->val, f->op);
+			if (err) {
+				kfree(str);
+				goto exit_free;
+			}
+			break;
+		case AUDIT_INODE:
+			err = audit_to_inode(&entry->rule, f);
+			if (err)
+				goto exit_free;
+			break;
+		default:
+			goto exit_free;
+		}
+	}
+
+	f = entry->rule.inode_f;
+	if (f) {
+		switch(f->op) {
+		case AUDIT_NOT_EQUAL:
+			entry->rule.inode_f = NULL;
+		case AUDIT_EQUAL:
+			break;
+		default:
+			goto exit_free;
 		}
 	}
 
@@ -291,7 +556,7 @@
 
 	rule = kmalloc(sizeof(*rule), GFP_KERNEL);
 	if (unlikely(!rule))
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 	memset(rule, 0, sizeof(*rule));
 
 	rule->flags = krule->flags | krule->listnr;
@@ -322,7 +587,7 @@
 
 	data = kmalloc(sizeof(*data) + krule->buflen, GFP_KERNEL);
 	if (unlikely(!data))
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 	memset(data, 0, sizeof(*data));
 
 	data->flags = krule->flags | krule->listnr;
@@ -343,6 +608,10 @@
 			data->buflen += data->values[i] =
 				audit_pack_string(&bufp, f->se_str);
 			break;
+		case AUDIT_WATCH:
+			data->buflen += data->values[i] =
+				audit_pack_string(&bufp, krule->watch->path);
+			break;
 		default:
 			data->values[i] = f->val;
 		}
@@ -378,6 +647,10 @@
 			if (strcmp(a->fields[i].se_str, b->fields[i].se_str))
 				return 1;
 			break;
+		case AUDIT_WATCH:
+			if (strcmp(a->watch->path, b->watch->path))
+				return 1;
+			break;
 		default:
 			if (a->fields[i].val != b->fields[i].val)
 				return 1;
@@ -391,6 +664,32 @@
 	return 0;
 }
 
+/* Duplicate the given audit watch.  The new watch's rules list is initialized
+ * to an empty list and wlist is undefined. */
+static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
+{
+	char *path;
+	struct audit_watch *new;
+
+	path = kstrdup(old->path, GFP_KERNEL);
+	if (unlikely(!path))
+		return ERR_PTR(-ENOMEM);
+
+	new = audit_init_watch(path);
+	if (unlikely(IS_ERR(new))) {
+		kfree(path);
+		goto out;
+	}
+
+	new->dev = old->dev;
+	new->ino = old->ino;
+	get_inotify_watch(&old->parent->wdata);
+	new->parent = old->parent;
+
+out:
+	return new;
+}
+
 /* Duplicate selinux field information.  The se_rule is opaque, so must be
  * re-initialized. */
 static inline int audit_dupe_selinux_field(struct audit_field *df,
@@ -422,8 +721,11 @@
 /* Duplicate an audit rule.  This will be a deep copy with the exception
  * of the watch - that pointer is carried over.  The selinux specific fields
  * will be updated in the copy.  The point is to be able to replace the old
- * rule with the new rule in the filterlist, then free the old rule. */
-static struct audit_entry *audit_dupe_rule(struct audit_krule *old)
+ * rule with the new rule in the filterlist, then free the old rule.
+ * The rlist element is undefined; list manipulations are handled apart from
+ * the initial copy. */
+static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+					   struct audit_watch *watch)
 {
 	u32 fcount = old->field_count;
 	struct audit_entry *entry;
@@ -442,6 +744,8 @@
 	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
 		new->mask[i] = old->mask[i];
 	new->buflen = old->buflen;
+	new->inode_f = old->inode_f;
+	new->watch = NULL;
 	new->field_count = old->field_count;
 	memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount);
 
@@ -463,68 +767,409 @@
 		}
 	}
 
+	if (watch) {
+		audit_get_watch(watch);
+		new->watch = watch;
+	}
+
 	return entry;
 }
 
-/* Add rule to given filterlist if not a duplicate.  Protected by
- * audit_netlink_mutex. */
-static inline int audit_add_rule(struct audit_entry *entry,
-				  struct list_head *list)
+/* Update inode info in audit rules based on filesystem event. */
+static void audit_update_watch(struct audit_parent *parent,
+			       const char *dname, dev_t dev,
+			       unsigned long ino, unsigned invalidating)
 {
+	struct audit_watch *owatch, *nwatch, *nextw;
+	struct audit_krule *r, *nextr;
+	struct audit_entry *oentry, *nentry;
+	struct audit_buffer *ab;
+
+	mutex_lock(&audit_filter_mutex);
+	list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
+		if (audit_compare_dname_path(dname, owatch->path, NULL))
+			continue;
+
+		/* If the update involves invalidating rules, do the inode-based
+		 * filtering now, so we don't omit records. */
+		if (invalidating &&
+		    audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT)
+			audit_set_auditable(current->audit_context);
+
+		nwatch = audit_dupe_watch(owatch);
+		if (unlikely(IS_ERR(nwatch))) {
+			mutex_unlock(&audit_filter_mutex);
+			audit_panic("error updating watch, skipping");
+			return;
+		}
+		nwatch->dev = dev;
+		nwatch->ino = ino;
+
+		list_for_each_entry_safe(r, nextr, &owatch->rules, rlist) {
+
+			oentry = container_of(r, struct audit_entry, rule);
+			list_del(&oentry->rule.rlist);
+			list_del_rcu(&oentry->list);
+
+			nentry = audit_dupe_rule(&oentry->rule, nwatch);
+			if (unlikely(IS_ERR(nentry)))
+				audit_panic("error updating watch, removing");
+			else {
+				int h = audit_hash_ino((u32)ino);
+				list_add(&nentry->rule.rlist, &nwatch->rules);
+				list_add_rcu(&nentry->list, &audit_inode_hash[h]);
+			}
+
+			call_rcu(&oentry->rcu, audit_free_rule_rcu);
+		}
+
+		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+		audit_log_format(ab, "audit updated rules specifying watch=");
+		audit_log_untrustedstring(ab, owatch->path);
+		audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
+		audit_log_end(ab);
+
+		audit_remove_watch(owatch);
+		goto add_watch_to_parent; /* event applies to a single watch */
+	}
+	mutex_unlock(&audit_filter_mutex);
+	return;
+
+add_watch_to_parent:
+	list_add(&nwatch->wlist, &parent->watches);
+	mutex_unlock(&audit_filter_mutex);
+	return;
+}
+
+/* Remove all watches & rules associated with a parent that is going away. */
+static void audit_remove_parent_watches(struct audit_parent *parent)
+{
+	struct audit_watch *w, *nextw;
+	struct audit_krule *r, *nextr;
 	struct audit_entry *e;
 
-	/* Do not use the _rcu iterator here, since this is the only
-	 * addition routine. */
-	list_for_each_entry(e, list, list) {
-		if (!audit_compare_rule(&entry->rule, &e->rule))
-			return -EEXIST;
+	mutex_lock(&audit_filter_mutex);
+	parent->flags |= AUDIT_PARENT_INVALID;
+	list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
+		list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
+			e = container_of(r, struct audit_entry, rule);
+			list_del(&r->rlist);
+			list_del_rcu(&e->list);
+			call_rcu(&e->rcu, audit_free_rule_rcu);
+
+			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+				 "audit implicitly removed rule from list=%d\n",
+				  AUDIT_FILTER_EXIT);
+		}
+		audit_remove_watch(w);
+	}
+	mutex_unlock(&audit_filter_mutex);
+}
+
+/* Unregister inotify watches for parents on in_list.
+ * Generates an IN_IGNORED event. */
+static void audit_inotify_unregister(struct list_head *in_list)
+{
+	struct audit_parent *p, *n;
+
+	list_for_each_entry_safe(p, n, in_list, ilist) {
+		list_del(&p->ilist);
+		inotify_rm_watch(audit_ih, &p->wdata);
+		/* the put matching the get in audit_do_del_rule() */
+		put_inotify_watch(&p->wdata);
+	}
+}
+
+/* Find an existing audit rule.
+ * Caller must hold audit_filter_mutex to prevent stale rule data. */
+static struct audit_entry *audit_find_rule(struct audit_entry *entry,
+					   struct list_head *list)
+{
+	struct audit_entry *e, *found = NULL;
+	int h;
+
+	if (entry->rule.watch) {
+		/* we don't know the inode number, so must walk entire hash */
+		for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
+			list = &audit_inode_hash[h];
+			list_for_each_entry(e, list, list)
+				if (!audit_compare_rule(&entry->rule, &e->rule)) {
+					found = e;
+					goto out;
+				}
+		}
+		goto out;
 	}
 
-	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
-		list_add_rcu(&entry->list, list);
-	} else {
-		list_add_tail_rcu(&entry->list, list);
+	list_for_each_entry(e, list, list)
+		if (!audit_compare_rule(&entry->rule, &e->rule)) {
+			found = e;
+			goto out;
+		}
+
+out:
+	return found;
+}
+
+/* Get path information necessary for adding watches. */
+static int audit_get_nd(char *path, struct nameidata **ndp,
+			struct nameidata **ndw)
+{
+	struct nameidata *ndparent, *ndwatch;
+	int err;
+
+	ndparent = kmalloc(sizeof(*ndparent), GFP_KERNEL);
+	if (unlikely(!ndparent))
+		return -ENOMEM;
+
+	ndwatch = kmalloc(sizeof(*ndwatch), GFP_KERNEL);
+	if (unlikely(!ndwatch)) {
+		kfree(ndparent);
+		return -ENOMEM;
 	}
 
+	err = path_lookup(path, LOOKUP_PARENT, ndparent);
+	if (err) {
+		kfree(ndparent);
+		kfree(ndwatch);
+		return err;
+	}
+
+	err = path_lookup(path, 0, ndwatch);
+	if (err) {
+		kfree(ndwatch);
+		ndwatch = NULL;
+	}
+
+	*ndp = ndparent;
+	*ndw = ndwatch;
+
 	return 0;
 }
 
-/* Remove an existing rule from filterlist.  Protected by
- * audit_netlink_mutex. */
+/* Release resources used for watch path information. */
+static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
+{
+	if (ndp) {
+		path_release(ndp);
+		kfree(ndp);
+	}
+	if (ndw) {
+		path_release(ndw);
+		kfree(ndw);
+	}
+}
+
+/* Associate the given rule with an existing parent inotify_watch.
+ * Caller must hold audit_filter_mutex. */
+static void audit_add_to_parent(struct audit_krule *krule,
+				struct audit_parent *parent)
+{
+	struct audit_watch *w, *watch = krule->watch;
+	int watch_found = 0;
+
+	list_for_each_entry(w, &parent->watches, wlist) {
+		if (strcmp(watch->path, w->path))
+			continue;
+
+		watch_found = 1;
+
+		/* put krule's and initial refs to temporary watch */
+		audit_put_watch(watch);
+		audit_put_watch(watch);
+
+		audit_get_watch(w);
+		krule->watch = watch = w;
+		break;
+	}
+
+	if (!watch_found) {
+		get_inotify_watch(&parent->wdata);
+		watch->parent = parent;
+
+		list_add(&watch->wlist, &parent->watches);
+	}
+	list_add(&krule->rlist, &watch->rules);
+}
+
+/* Find a matching watch entry, or add this one.
+ * Caller must hold audit_filter_mutex. */
+static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
+			   struct nameidata *ndw)
+{
+	struct audit_watch *watch = krule->watch;
+	struct inotify_watch *i_watch;
+	struct audit_parent *parent;
+	int ret = 0;
+
+	/* update watch filter fields */
+	if (ndw) {
+		watch->dev = ndw->dentry->d_inode->i_sb->s_dev;
+		watch->ino = ndw->dentry->d_inode->i_ino;
+	}
+
+	/* The audit_filter_mutex must not be held during inotify calls because
+	 * we hold it during inotify event callback processing.  If an existing
+	 * inotify watch is found, inotify_find_watch() grabs a reference before
+	 * returning.
+	 */
+	mutex_unlock(&audit_filter_mutex);
+
+	if (inotify_find_watch(audit_ih, ndp->dentry->d_inode, &i_watch) < 0) {
+		parent = audit_init_parent(ndp);
+		if (IS_ERR(parent)) {
+			/* caller expects mutex locked */
+			mutex_lock(&audit_filter_mutex);
+			return PTR_ERR(parent);
+		}
+	} else
+		parent = container_of(i_watch, struct audit_parent, wdata);
+
+	mutex_lock(&audit_filter_mutex);
+
+	/* parent was moved before we took audit_filter_mutex */
+	if (parent->flags & AUDIT_PARENT_INVALID)
+		ret = -ENOENT;
+	else
+		audit_add_to_parent(krule, parent);
+
+	/* match get in audit_init_parent or inotify_find_watch */
+	put_inotify_watch(&parent->wdata);
+	return ret;
+}
+
+/* Add rule to given filterlist if not a duplicate. */
+static inline int audit_add_rule(struct audit_entry *entry,
+				 struct list_head *list)
+{
+	struct audit_entry *e;
+	struct audit_field *inode_f = entry->rule.inode_f;
+	struct audit_watch *watch = entry->rule.watch;
+	struct nameidata *ndp, *ndw;
+	int h, err, putnd_needed = 0;
+
+	if (inode_f) {
+		h = audit_hash_ino(inode_f->val);
+		list = &audit_inode_hash[h];
+	}
+
+	mutex_lock(&audit_filter_mutex);
+	e = audit_find_rule(entry, list);
+	mutex_unlock(&audit_filter_mutex);
+	if (e) {
+		err = -EEXIST;
+		goto error;
+	}
+
+	/* Avoid calling path_lookup under audit_filter_mutex. */
+	if (watch) {
+		err = audit_get_nd(watch->path, &ndp, &ndw);
+		if (err)
+			goto error;
+		putnd_needed = 1;
+	}
+
+	mutex_lock(&audit_filter_mutex);
+	if (watch) {
+		/* audit_filter_mutex is dropped and re-taken during this call */
+		err = audit_add_watch(&entry->rule, ndp, ndw);
+		if (err) {
+			mutex_unlock(&audit_filter_mutex);
+			goto error;
+		}
+		h = audit_hash_ino((u32)watch->ino);
+		list = &audit_inode_hash[h];
+	}
+
+	if (entry->rule.flags & AUDIT_FILTER_PREPEND) {
+		list_add_rcu(&entry->list, list);
+		entry->rule.flags &= ~AUDIT_FILTER_PREPEND;
+	} else {
+		list_add_tail_rcu(&entry->list, list);
+	}
+	mutex_unlock(&audit_filter_mutex);
+
+	if (putnd_needed)
+		audit_put_nd(ndp, ndw);
+
+ 	return 0;
+
+error:
+	if (putnd_needed)
+		audit_put_nd(ndp, ndw);
+	if (watch)
+		audit_put_watch(watch); /* tmp watch, matches initial get */
+	return err;
+}
+
+/* Remove an existing rule from filterlist. */
 static inline int audit_del_rule(struct audit_entry *entry,
 				 struct list_head *list)
 {
 	struct audit_entry  *e;
+	struct audit_field *inode_f = entry->rule.inode_f;
+	struct audit_watch *watch, *tmp_watch = entry->rule.watch;
+	LIST_HEAD(inotify_list);
+	int h, ret = 0;
 
-	/* Do not use the _rcu iterator here, since this is the only
-	 * deletion routine. */
-	list_for_each_entry(e, list, list) {
-		if (!audit_compare_rule(&entry->rule, &e->rule)) {
-			list_del_rcu(&e->list);
-			call_rcu(&e->rcu, audit_free_rule_rcu);
-			return 0;
+	if (inode_f) {
+		h = audit_hash_ino(inode_f->val);
+		list = &audit_inode_hash[h];
+	}
+
+	mutex_lock(&audit_filter_mutex);
+	e = audit_find_rule(entry, list);
+	if (!e) {
+		mutex_unlock(&audit_filter_mutex);
+		ret = -ENOENT;
+		goto out;
+	}
+
+	watch = e->rule.watch;
+	if (watch) {
+		struct audit_parent *parent = watch->parent;
+
+		list_del(&e->rule.rlist);
+
+		if (list_empty(&watch->rules)) {
+			audit_remove_watch(watch);
+
+			if (list_empty(&parent->watches)) {
+				/* Put parent on the inotify un-registration
+				 * list.  Grab a reference before releasing
+				 * audit_filter_mutex, to be released in
+				 * audit_inotify_unregister(). */
+				list_add(&parent->ilist, &inotify_list);
+				get_inotify_watch(&parent->wdata);
+			}
 		}
 	}
-	return -ENOENT;		/* No matching rule */
+
+	list_del_rcu(&e->list);
+	call_rcu(&e->rcu, audit_free_rule_rcu);
+
+	mutex_unlock(&audit_filter_mutex);
+
+	if (!list_empty(&inotify_list))
+		audit_inotify_unregister(&inotify_list);
+
+out:
+	if (tmp_watch)
+		audit_put_watch(tmp_watch); /* match initial get */
+
+	return ret;
 }
 
 /* List rules using struct audit_rule.  Exists for backward
  * compatibility with userspace. */
-static int audit_list(void *_dest)
+static void audit_list(int pid, int seq, struct sk_buff_head *q)
 {
-	int pid, seq;
-	int *dest = _dest;
+	struct sk_buff *skb;
 	struct audit_entry *entry;
 	int i;
 
-	pid = dest[0];
-	seq = dest[1];
-	kfree(dest);
-
-	mutex_lock(&audit_netlink_mutex);
-
-	/* The *_rcu iterators not needed here because we are
-	   always called with audit_netlink_mutex held. */
+	/* This is a blocking read, so use audit_filter_mutex instead of rcu
+	 * iterator to sync with list writers. */
 	for (i=0; i<AUDIT_NR_FILTERS; i++) {
 		list_for_each_entry(entry, &audit_filter_list[i], list) {
 			struct audit_rule *rule;
@@ -532,33 +1177,41 @@
 			rule = audit_krule_to_rule(&entry->rule);
 			if (unlikely(!rule))
 				break;
-			audit_send_reply(pid, seq, AUDIT_LIST, 0, 1,
+			skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
 					 rule, sizeof(*rule));
+			if (skb)
+				skb_queue_tail(q, skb);
 			kfree(rule);
 		}
 	}
-	audit_send_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
-	
-	mutex_unlock(&audit_netlink_mutex);
-	return 0;
+	for (i = 0; i < AUDIT_INODE_BUCKETS; i++) {
+		list_for_each_entry(entry, &audit_inode_hash[i], list) {
+			struct audit_rule *rule;
+
+			rule = audit_krule_to_rule(&entry->rule);
+			if (unlikely(!rule))
+				break;
+			skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1,
+					 rule, sizeof(*rule));
+			if (skb)
+				skb_queue_tail(q, skb);
+			kfree(rule);
+		}
+	}
+	skb = audit_make_reply(pid, seq, AUDIT_LIST, 1, 1, NULL, 0);
+	if (skb)
+		skb_queue_tail(q, skb);
 }
 
 /* List rules using struct audit_rule_data. */
-static int audit_list_rules(void *_dest)
+static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
 {
-	int pid, seq;
-	int *dest = _dest;
+	struct sk_buff *skb;
 	struct audit_entry *e;
 	int i;
 
-	pid = dest[0];
-	seq = dest[1];
-	kfree(dest);
-
-	mutex_lock(&audit_netlink_mutex);
-
-	/* The *_rcu iterators not needed here because we are
-	   always called with audit_netlink_mutex held. */
+	/* This is a blocking read, so use audit_filter_mutex instead of rcu
+	 * iterator to sync with list writers. */
 	for (i=0; i<AUDIT_NR_FILTERS; i++) {
 		list_for_each_entry(e, &audit_filter_list[i], list) {
 			struct audit_rule_data *data;
@@ -566,15 +1219,30 @@
 			data = audit_krule_to_data(&e->rule);
 			if (unlikely(!data))
 				break;
-			audit_send_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
-					 data, sizeof(*data));
+			skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
+					 data, sizeof(*data) + data->buflen);
+			if (skb)
+				skb_queue_tail(q, skb);
 			kfree(data);
 		}
 	}
-	audit_send_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
+	for (i=0; i< AUDIT_INODE_BUCKETS; i++) {
+		list_for_each_entry(e, &audit_inode_hash[i], list) {
+			struct audit_rule_data *data;
 
-	mutex_unlock(&audit_netlink_mutex);
-	return 0;
+			data = audit_krule_to_data(&e->rule);
+			if (unlikely(!data))
+				break;
+			skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1,
+					 data, sizeof(*data) + data->buflen);
+			if (skb)
+				skb_queue_tail(q, skb);
+			kfree(data);
+		}
+	}
+	skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0);
+	if (skb)
+		skb_queue_tail(q, skb);
 }
 
 /**
@@ -592,7 +1260,7 @@
 			 size_t datasz, uid_t loginuid, u32 sid)
 {
 	struct task_struct *tsk;
-	int *dest;
+	struct audit_netlink_list *dest;
 	int err = 0;
 	struct audit_entry *entry;
 
@@ -605,18 +1273,22 @@
 		 * happen if we're actually running in the context of auditctl
 		 * trying to _send_ the stuff */
 		 
-		dest = kmalloc(2 * sizeof(int), GFP_KERNEL);
+		dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
 		if (!dest)
 			return -ENOMEM;
-		dest[0] = pid;
-		dest[1] = seq;
+		dest->pid = pid;
+		skb_queue_head_init(&dest->q);
 
+		mutex_lock(&audit_filter_mutex);
 		if (type == AUDIT_LIST)
-			tsk = kthread_run(audit_list, dest, "audit_list");
+			audit_list(pid, seq, &dest->q);
 		else
-			tsk = kthread_run(audit_list_rules, dest,
-					  "audit_list_rules");
+			audit_list_rules(pid, seq, &dest->q);
+		mutex_unlock(&audit_filter_mutex);
+
+		tsk = kthread_run(audit_send_list, dest, "audit_send_list");
 		if (IS_ERR(tsk)) {
+			skb_queue_purge(&dest->q);
 			kfree(dest);
 			err = PTR_ERR(tsk);
 		}
@@ -632,6 +1304,7 @@
 
 		err = audit_add_rule(entry,
 				     &audit_filter_list[entry->rule.listnr]);
+
 		if (sid) {
 			char *ctx = NULL;
 			u32 len;
@@ -712,7 +1385,43 @@
 	return 0;
 }
 
+/* Compare given dentry name with last component in given path,
+ * return of 0 indicates a match. */
+int audit_compare_dname_path(const char *dname, const char *path,
+			     int *dirlen)
+{
+	int dlen, plen;
+	const char *p;
 
+	if (!dname || !path)
+		return 1;
+
+	dlen = strlen(dname);
+	plen = strlen(path);
+	if (plen < dlen)
+		return 1;
+
+	/* disregard trailing slashes */
+	p = path + plen - 1;
+	while ((*p == '/') && (p > path))
+		p--;
+
+	/* find last path component */
+	p = p - dlen + 1;
+	if (p < path)
+		return 1;
+	else if (p > path) {
+		if (*--p != '/')
+			return 1;
+		else
+			p++;
+	}
+
+	/* return length of path's directory component */
+	if (dirlen)
+		*dirlen = p - path;
+	return strncmp(p, dname, dlen);
+}
 
 static int audit_filter_user_rules(struct netlink_skb_parms *cb,
 				   struct audit_krule *rule,
@@ -744,7 +1453,6 @@
 	}
 	switch (rule->action) {
 	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
-	case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
 	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
 	}
 	return 1;
@@ -826,32 +1534,65 @@
 int selinux_audit_rule_update(void)
 {
 	struct audit_entry *entry, *n, *nentry;
+	struct audit_watch *watch;
 	int i, err = 0;
 
-	/* audit_netlink_mutex synchronizes the writers */
-	mutex_lock(&audit_netlink_mutex);
+	/* audit_filter_mutex synchronizes the writers */
+	mutex_lock(&audit_filter_mutex);
 
 	for (i = 0; i < AUDIT_NR_FILTERS; i++) {
 		list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) {
 			if (!audit_rule_has_selinux(&entry->rule))
 				continue;
 
-			nentry = audit_dupe_rule(&entry->rule);
+			watch = entry->rule.watch;
+			nentry = audit_dupe_rule(&entry->rule, watch);
 			if (unlikely(IS_ERR(nentry))) {
 				/* save the first error encountered for the
 				 * return value */
 				if (!err)
 					err = PTR_ERR(nentry);
 				audit_panic("error updating selinux filters");
+				if (watch)
+					list_del(&entry->rule.rlist);
 				list_del_rcu(&entry->list);
 			} else {
+				if (watch) {
+					list_add(&nentry->rule.rlist,
+						 &watch->rules);
+					list_del(&entry->rule.rlist);
+				}
 				list_replace_rcu(&entry->list, &nentry->list);
 			}
 			call_rcu(&entry->rcu, audit_free_rule_rcu);
 		}
 	}
 
-	mutex_unlock(&audit_netlink_mutex);
+	mutex_unlock(&audit_filter_mutex);
 
 	return err;
 }
+
+/* Update watch data in audit rules based on inotify events. */
+void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
+			 u32 cookie, const char *dname, struct inode *inode)
+{
+	struct audit_parent *parent;
+
+	parent = container_of(i_watch, struct audit_parent, wdata);
+
+	if (mask & (IN_CREATE|IN_MOVED_TO) && inode)
+		audit_update_watch(parent, dname, inode->i_sb->s_dev,
+				   inode->i_ino, 0);
+	else if (mask & (IN_DELETE|IN_MOVED_FROM))
+		audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1);
+	/* inotify automatically removes the watch and sends IN_IGNORED */
+	else if (mask & (IN_DELETE_SELF|IN_UNMOUNT))
+		audit_remove_parent_watches(parent);
+	/* inotify does not remove the watch, so remove it manually */
+	else if(mask & IN_MOVE_SELF) {
+		audit_remove_parent_watches(parent);
+		inotify_remove_watch_locked(audit_ih, i_watch);
+	} else if (mask & IN_IGNORED)
+		put_inotify_watch(i_watch);
+}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 1c03a4e..dc5e3f0 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
  * Copyright 2005 Hewlett-Packard Development Company, L.P.
- * Copyright (C) 2005 IBM Corporation
+ * Copyright (C) 2005, 2006 IBM Corporation
  * All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,6 +29,9 @@
  * this file -- see entry.S) is based on a GPL'd patch written by
  * okir@suse.de and Copyright 2003 SuSE Linux AG.
  *
+ * POSIX message queue support added by George Wilson <ltcgcw@us.ibm.com>,
+ * 2006.
+ *
  * The support of additional filter rules compares (>, <, >=, <=) was
  * added by Dustin Kirkland <dustin.kirkland@us.ibm.com>, 2005.
  *
@@ -49,6 +52,7 @@
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/socket.h>
+#include <linux/mqueue.h>
 #include <linux/audit.h>
 #include <linux/personality.h>
 #include <linux/time.h>
@@ -59,6 +63,8 @@
 #include <linux/list.h>
 #include <linux/tty.h>
 #include <linux/selinux.h>
+#include <linux/binfmts.h>
+#include <linux/syscalls.h>
 
 #include "audit.h"
 
@@ -76,6 +82,9 @@
  * path_lookup. */
 #define AUDIT_NAMES_RESERVED 7
 
+/* Indicates that audit should log the full pathname. */
+#define AUDIT_NAME_FULL -1
+
 /* When fs/namei.c:getname() is called, we store the pointer in name and
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
@@ -83,8 +92,9 @@
  * Further, in fs/namei.c:path_lookup() we store the inode and device. */
 struct audit_names {
 	const char	*name;
+	int		name_len;	/* number of name's characters to log */
+	unsigned	name_put;	/* call __putname() for this name */
 	unsigned long	ino;
-	unsigned long	pino;
 	dev_t		dev;
 	umode_t		mode;
 	uid_t		uid;
@@ -100,6 +110,33 @@
 
 #define AUDIT_AUX_IPCPERM	0
 
+struct audit_aux_data_mq_open {
+	struct audit_aux_data	d;
+	int			oflag;
+	mode_t			mode;
+	struct mq_attr		attr;
+};
+
+struct audit_aux_data_mq_sendrecv {
+	struct audit_aux_data	d;
+	mqd_t			mqdes;
+	size_t			msg_len;
+	unsigned int		msg_prio;
+	struct timespec		abs_timeout;
+};
+
+struct audit_aux_data_mq_notify {
+	struct audit_aux_data	d;
+	mqd_t			mqdes;
+	struct sigevent 	notification;
+};
+
+struct audit_aux_data_mq_getsetattr {
+	struct audit_aux_data	d;
+	mqd_t			mqdes;
+	struct mq_attr 		mqstat;
+};
+
 struct audit_aux_data_ipcctl {
 	struct audit_aux_data	d;
 	struct ipc_perm		p;
@@ -110,6 +147,13 @@
 	u32			osid;
 };
 
+struct audit_aux_data_execve {
+	struct audit_aux_data	d;
+	int argc;
+	int envc;
+	char mem[0];
+};
+
 struct audit_aux_data_socketcall {
 	struct audit_aux_data	d;
 	int			nargs;
@@ -148,7 +192,7 @@
 	struct audit_aux_data *aux;
 
 				/* Save things to print about task_struct */
-	pid_t		    pid;
+	pid_t		    pid, ppid;
 	uid_t		    uid, euid, suid, fsuid;
 	gid_t		    gid, egid, sgid, fsgid;
 	unsigned long	    personality;
@@ -160,12 +204,13 @@
 #endif
 };
 
-
+/* Determine if any context name data matches a rule's watch data */
 /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
  * otherwise. */
 static int audit_filter_rules(struct task_struct *tsk,
 			      struct audit_krule *rule,
 			      struct audit_context *ctx,
+			      struct audit_names *name,
 			      enum audit_state *state)
 {
 	int i, j, need_sid = 1;
@@ -179,6 +224,10 @@
 		case AUDIT_PID:
 			result = audit_comparator(tsk->pid, f->op, f->val);
 			break;
+		case AUDIT_PPID:
+			if (ctx)
+				result = audit_comparator(ctx->ppid, f->op, f->val);
+			break;
 		case AUDIT_UID:
 			result = audit_comparator(tsk->uid, f->op, f->val);
 			break;
@@ -224,7 +273,10 @@
 			}
 			break;
 		case AUDIT_DEVMAJOR:
-			if (ctx) {
+			if (name)
+				result = audit_comparator(MAJOR(name->dev),
+							  f->op, f->val);
+			else if (ctx) {
 				for (j = 0; j < ctx->name_count; j++) {
 					if (audit_comparator(MAJOR(ctx->names[j].dev),	f->op, f->val)) {
 						++result;
@@ -234,7 +286,10 @@
 			}
 			break;
 		case AUDIT_DEVMINOR:
-			if (ctx) {
+			if (name)
+				result = audit_comparator(MINOR(name->dev),
+							  f->op, f->val);
+			else if (ctx) {
 				for (j = 0; j < ctx->name_count; j++) {
 					if (audit_comparator(MINOR(ctx->names[j].dev), f->op, f->val)) {
 						++result;
@@ -244,16 +299,22 @@
 			}
 			break;
 		case AUDIT_INODE:
-			if (ctx) {
+			if (name)
+				result = (name->ino == f->val);
+			else if (ctx) {
 				for (j = 0; j < ctx->name_count; j++) {
-					if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
-					    audit_comparator(ctx->names[j].pino, f->op, f->val)) {
+					if (audit_comparator(ctx->names[j].ino, f->op, f->val)) {
 						++result;
 						break;
 					}
 				}
 			}
 			break;
+		case AUDIT_WATCH:
+			if (name && rule->watch->ino != (unsigned long)-1)
+				result = (name->dev == rule->watch->dev &&
+					  name->ino == rule->watch->ino);
+			break;
 		case AUDIT_LOGINUID:
 			result = 0;
 			if (ctx)
@@ -294,7 +355,6 @@
 	}
 	switch (rule->action) {
 	case AUDIT_NEVER:    *state = AUDIT_DISABLED;	    break;
-	case AUDIT_POSSIBLE: *state = AUDIT_BUILD_CONTEXT;  break;
 	case AUDIT_ALWAYS:   *state = AUDIT_RECORD_CONTEXT; break;
 	}
 	return 1;
@@ -311,7 +371,7 @@
 
 	rcu_read_lock();
 	list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
-		if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+		if (audit_filter_rules(tsk, &e->rule, NULL, NULL, &state)) {
 			rcu_read_unlock();
 			return state;
 		}
@@ -341,8 +401,9 @@
 		int bit  = AUDIT_BIT(ctx->major);
 
 		list_for_each_entry_rcu(e, list, list) {
-			if ((e->rule.mask[word] & bit) == bit
-					&& audit_filter_rules(tsk, &e->rule, ctx, &state)) {
+			if ((e->rule.mask[word] & bit) == bit &&
+			    audit_filter_rules(tsk, &e->rule, ctx, NULL,
+					       &state)) {
 				rcu_read_unlock();
 				return state;
 			}
@@ -352,6 +413,49 @@
 	return AUDIT_BUILD_CONTEXT;
 }
 
+/* At syscall exit time, this filter is called if any audit_names[] have been
+ * collected during syscall processing.  We only check rules in sublists at hash
+ * buckets applicable to the inode numbers in audit_names[].
+ * Regarding audit_state, same rules apply as for audit_filter_syscall().
+ */
+enum audit_state audit_filter_inodes(struct task_struct *tsk,
+				     struct audit_context *ctx)
+{
+	int i;
+	struct audit_entry *e;
+	enum audit_state state;
+
+	if (audit_pid && tsk->tgid == audit_pid)
+		return AUDIT_DISABLED;
+
+	rcu_read_lock();
+	for (i = 0; i < ctx->name_count; i++) {
+		int word = AUDIT_WORD(ctx->major);
+		int bit  = AUDIT_BIT(ctx->major);
+		struct audit_names *n = &ctx->names[i];
+		int h = audit_hash_ino((u32)n->ino);
+		struct list_head *list = &audit_inode_hash[h];
+
+		if (list_empty(list))
+			continue;
+
+		list_for_each_entry_rcu(e, list, list) {
+			if ((e->rule.mask[word] & bit) == bit &&
+			    audit_filter_rules(tsk, &e->rule, ctx, n, &state)) {
+				rcu_read_unlock();
+				return state;
+			}
+		}
+	}
+	rcu_read_unlock();
+	return AUDIT_BUILD_CONTEXT;
+}
+
+void audit_set_auditable(struct audit_context *ctx)
+{
+	ctx->auditable = 1;
+}
+
 static inline struct audit_context *audit_get_context(struct task_struct *tsk,
 						      int return_valid,
 						      int return_code)
@@ -365,12 +469,22 @@
 
 	if (context->in_syscall && !context->auditable) {
 		enum audit_state state;
+
 		state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]);
+		if (state == AUDIT_RECORD_CONTEXT) {
+			context->auditable = 1;
+			goto get_context;
+		}
+
+		state = audit_filter_inodes(tsk, context);
 		if (state == AUDIT_RECORD_CONTEXT)
 			context->auditable = 1;
+
 	}
 
+get_context:
 	context->pid = tsk->pid;
+	context->ppid = sys_getppid();	/* sic.  tsk == current in all cases */
 	context->uid = tsk->uid;
 	context->gid = tsk->gid;
 	context->euid = tsk->euid;
@@ -413,7 +527,7 @@
 #endif
 
 	for (i = 0; i < context->name_count; i++) {
-		if (context->names[i].name)
+		if (context->names[i].name && context->names[i].name_put)
 			__putname(context->names[i].name);
 	}
 	context->name_count = 0;
@@ -544,8 +658,7 @@
 	return;
 
 error_path:
-	if (ctx)
-		kfree(ctx);
+	kfree(ctx);
 	audit_panic("error in audit_log_task_context");
 	return;
 }
@@ -606,7 +719,7 @@
 		tty = "(none)";
 	audit_log_format(ab,
 		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
-		  " pid=%d auid=%u uid=%u gid=%u"
+		  " ppid=%d pid=%d auid=%u uid=%u gid=%u"
 		  " euid=%u suid=%u fsuid=%u"
 		  " egid=%u sgid=%u fsgid=%u tty=%s",
 		  context->argv[0],
@@ -614,6 +727,7 @@
 		  context->argv[2],
 		  context->argv[3],
 		  context->name_count,
+		  context->ppid,
 		  context->pid,
 		  context->loginuid,
 		  context->uid,
@@ -630,11 +744,48 @@
 			continue; /* audit_panic has been called */
 
 		switch (aux->type) {
+		case AUDIT_MQ_OPEN: {
+			struct audit_aux_data_mq_open *axi = (void *)aux;
+			audit_log_format(ab,
+				"oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld "
+				"mq_msgsize=%ld mq_curmsgs=%ld",
+				axi->oflag, axi->mode, axi->attr.mq_flags,
+				axi->attr.mq_maxmsg, axi->attr.mq_msgsize,
+				axi->attr.mq_curmsgs);
+			break; }
+
+		case AUDIT_MQ_SENDRECV: {
+			struct audit_aux_data_mq_sendrecv *axi = (void *)aux;
+			audit_log_format(ab,
+				"mqdes=%d msg_len=%zd msg_prio=%u "
+				"abs_timeout_sec=%ld abs_timeout_nsec=%ld",
+				axi->mqdes, axi->msg_len, axi->msg_prio,
+				axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec);
+			break; }
+
+		case AUDIT_MQ_NOTIFY: {
+			struct audit_aux_data_mq_notify *axi = (void *)aux;
+			audit_log_format(ab,
+				"mqdes=%d sigev_signo=%d",
+				axi->mqdes,
+				axi->notification.sigev_signo);
+			break; }
+
+		case AUDIT_MQ_GETSETATTR: {
+			struct audit_aux_data_mq_getsetattr *axi = (void *)aux;
+			audit_log_format(ab,
+				"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
+				"mq_curmsgs=%ld ",
+				axi->mqdes,
+				axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg,
+				axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs);
+			break; }
+
 		case AUDIT_IPC: {
 			struct audit_aux_data_ipcctl *axi = (void *)aux;
 			audit_log_format(ab, 
-				 " qbytes=%lx iuid=%u igid=%u mode=%x",
-				 axi->qbytes, axi->uid, axi->gid, axi->mode);
+				 "ouid=%u ogid=%u mode=%x",
+				 axi->uid, axi->gid, axi->mode);
 			if (axi->osid != 0) {
 				char *ctx = NULL;
 				u32 len;
@@ -652,19 +803,18 @@
 		case AUDIT_IPC_SET_PERM: {
 			struct audit_aux_data_ipcctl *axi = (void *)aux;
 			audit_log_format(ab,
-				" new qbytes=%lx new iuid=%u new igid=%u new mode=%x",
+				"qbytes=%lx ouid=%u ogid=%u mode=%x",
 				axi->qbytes, axi->uid, axi->gid, axi->mode);
-			if (axi->osid != 0) {
-				char *ctx = NULL;
-				u32 len;
-				if (selinux_ctxid_to_string(
-						axi->osid, &ctx, &len)) {
-					audit_log_format(ab, " osid=%u",
-							axi->osid);
-					call_panic = 1;
-				} else
-					audit_log_format(ab, " obj=%s", ctx);
-				kfree(ctx);
+			break; }
+
+		case AUDIT_EXECVE: {
+			struct audit_aux_data_execve *axi = (void *)aux;
+			int i;
+			const char *p;
+			for (i = 0, p = axi->mem; i < axi->argc; i++) {
+				audit_log_format(ab, "a%d=", i);
+				p = audit_log_untrustedstring(ab, p);
+				audit_log_format(ab, "\n");
 			}
 			break; }
 
@@ -700,8 +850,7 @@
 		}
 	}
 	for (i = 0; i < context->name_count; i++) {
-		unsigned long ino  = context->names[i].ino;
-		unsigned long pino = context->names[i].pino;
+		struct audit_names *n = &context->names[i];
 
 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
 		if (!ab)
@@ -709,33 +858,47 @@
 
 		audit_log_format(ab, "item=%d", i);
 
-		audit_log_format(ab, " name=");
-		if (context->names[i].name)
-			audit_log_untrustedstring(ab, context->names[i].name);
-		else
-			audit_log_format(ab, "(null)");
+		if (n->name) {
+			switch(n->name_len) {
+			case AUDIT_NAME_FULL:
+				/* log the full path */
+				audit_log_format(ab, " name=");
+				audit_log_untrustedstring(ab, n->name);
+				break;
+			case 0:
+				/* name was specified as a relative path and the
+				 * directory component is the cwd */
+				audit_log_d_path(ab, " name=", context->pwd,
+						 context->pwdmnt);
+				break;
+			default:
+				/* log the name's directory component */
+				audit_log_format(ab, " name=");
+				audit_log_n_untrustedstring(ab, n->name_len,
+							    n->name);
+			}
+		} else
+			audit_log_format(ab, " name=(null)");
 
-		if (pino != (unsigned long)-1)
-			audit_log_format(ab, " parent=%lu",  pino);
-		if (ino != (unsigned long)-1)
-			audit_log_format(ab, " inode=%lu",  ino);
-		if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1))
-			audit_log_format(ab, " dev=%02x:%02x mode=%#o" 
-					 " ouid=%u ogid=%u rdev=%02x:%02x", 
-					 MAJOR(context->names[i].dev), 
-					 MINOR(context->names[i].dev), 
-					 context->names[i].mode, 
-					 context->names[i].uid, 
-					 context->names[i].gid, 
-					 MAJOR(context->names[i].rdev), 
-					 MINOR(context->names[i].rdev));
-		if (context->names[i].osid != 0) {
+		if (n->ino != (unsigned long)-1) {
+			audit_log_format(ab, " inode=%lu"
+					 " dev=%02x:%02x mode=%#o"
+					 " ouid=%u ogid=%u rdev=%02x:%02x",
+					 n->ino,
+					 MAJOR(n->dev),
+					 MINOR(n->dev),
+					 n->mode,
+					 n->uid,
+					 n->gid,
+					 MAJOR(n->rdev),
+					 MINOR(n->rdev));
+		}
+		if (n->osid != 0) {
 			char *ctx = NULL;
 			u32 len;
 			if (selinux_ctxid_to_string(
-				context->names[i].osid, &ctx, &len)) {
-				audit_log_format(ab, " osid=%u",
-						context->names[i].osid);
+				n->osid, &ctx, &len)) {
+				audit_log_format(ab, " osid=%u", n->osid);
 				call_panic = 2;
 			} else
 				audit_log_format(ab, " obj=%s", ctx);
@@ -908,11 +1071,11 @@
  * Add a name to the list of audit names for this context.
  * Called from fs/namei.c:getname().
  */
-void audit_getname(const char *name)
+void __audit_getname(const char *name)
 {
 	struct audit_context *context = current->audit_context;
 
-	if (!context || IS_ERR(name) || !name)
+	if (IS_ERR(name) || !name)
 		return;
 
 	if (!context->in_syscall) {
@@ -925,6 +1088,8 @@
 	}
 	BUG_ON(context->name_count >= AUDIT_NAMES);
 	context->names[context->name_count].name = name;
+	context->names[context->name_count].name_len = AUDIT_NAME_FULL;
+	context->names[context->name_count].name_put = 1;
 	context->names[context->name_count].ino  = (unsigned long)-1;
 	++context->name_count;
 	if (!context->pwd) {
@@ -991,11 +1156,10 @@
  * audit_inode - store the inode and device from a lookup
  * @name: name being audited
  * @inode: inode being audited
- * @flags: lookup flags (as used in path_lookup())
  *
  * Called from fs/namei.c:path_lookup().
  */
-void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
+void __audit_inode(const char *name, const struct inode *inode)
 {
 	int idx;
 	struct audit_context *context = current->audit_context;
@@ -1021,20 +1185,13 @@
 		++context->ino_count;
 #endif
 	}
+	context->names[idx].ino   = inode->i_ino;
 	context->names[idx].dev	  = inode->i_sb->s_dev;
 	context->names[idx].mode  = inode->i_mode;
 	context->names[idx].uid   = inode->i_uid;
 	context->names[idx].gid   = inode->i_gid;
 	context->names[idx].rdev  = inode->i_rdev;
 	audit_inode_context(idx, inode);
-	if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) && 
-	    (strcmp(name, ".") != 0)) {
-		context->names[idx].ino   = (unsigned long)-1;
-		context->names[idx].pino  = inode->i_ino;
-	} else {
-		context->names[idx].ino   = inode->i_ino;
-		context->names[idx].pino  = (unsigned long)-1;
-	}
 }
 
 /**
@@ -1056,51 +1213,40 @@
 {
 	int idx;
 	struct audit_context *context = current->audit_context;
+	const char *found_name = NULL;
+	int dirlen = 0;
 
 	if (!context->in_syscall)
 		return;
 
 	/* determine matching parent */
-	if (dname)
-		for (idx = 0; idx < context->name_count; idx++)
-			if (context->names[idx].pino == pino) {
-				const char *n;
-				const char *name = context->names[idx].name;
-				int dlen = strlen(dname);
-				int nlen = name ? strlen(name) : 0;
+	if (!dname)
+		goto update_context;
+	for (idx = 0; idx < context->name_count; idx++)
+		if (context->names[idx].ino == pino) {
+			const char *name = context->names[idx].name;
 
-				if (nlen < dlen)
-					continue;
-				
-				/* disregard trailing slashes */
-				n = name + nlen - 1;
-				while ((*n == '/') && (n > name))
-					n--;
+			if (!name)
+				continue;
 
-				/* find last path component */
-				n = n - dlen + 1;
-				if (n < name)
-					continue;
-				else if (n > name) {
-					if (*--n != '/')
-						continue;
-					else
-						n++;
-				}
-
-				if (strncmp(n, dname, dlen) == 0)
-					goto update_context;
+			if (audit_compare_dname_path(dname, name, &dirlen) == 0) {
+				context->names[idx].name_len = dirlen;
+				found_name = name;
+				break;
 			}
+		}
 
-	/* catch-all in case match not found */
+update_context:
 	idx = context->name_count++;
-	context->names[idx].name  = NULL;
-	context->names[idx].pino  = pino;
 #if AUDIT_DEBUG
 	context->ino_count++;
 #endif
+	/* Re-use the name belonging to the slot for a matching parent directory.
+	 * All names for this context are relinquished in audit_free_names() */
+	context->names[idx].name = found_name;
+	context->names[idx].name_len = AUDIT_NAME_FULL;
+	context->names[idx].name_put = 0;	/* don't call __putname() */
 
-update_context:
 	if (inode) {
 		context->names[idx].ino   = inode->i_ino;
 		context->names[idx].dev	  = inode->i_sb->s_dev;
@@ -1109,7 +1255,8 @@
 		context->names[idx].gid   = inode->i_gid;
 		context->names[idx].rdev  = inode->i_rdev;
 		audit_inode_context(idx, inode);
-	}
+	} else
+		context->names[idx].ino   = (unsigned long)-1;
 }
 
 /**
@@ -1142,18 +1289,23 @@
  */
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
-	if (task->audit_context) {
-		struct audit_buffer *ab;
+	struct audit_context *context = task->audit_context;
 
-		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
-		if (ab) {
-			audit_log_format(ab, "login pid=%d uid=%u "
-				"old auid=%u new auid=%u",
-				task->pid, task->uid, 
-				task->audit_context->loginuid, loginuid);
-			audit_log_end(ab);
+	if (context) {
+		/* Only log if audit is enabled */
+		if (context->in_syscall) {
+			struct audit_buffer *ab;
+
+			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
+			if (ab) {
+				audit_log_format(ab, "login pid=%d uid=%u "
+					"old auid=%u new auid=%u",
+					task->pid, task->uid,
+					context->loginuid, loginuid);
+				audit_log_end(ab);
+			}
 		}
-		task->audit_context->loginuid = loginuid;
+		context->loginuid = loginuid;
 	}
 	return 0;
 }
@@ -1170,19 +1322,220 @@
 }
 
 /**
+ * __audit_mq_open - record audit data for a POSIX MQ open
+ * @oflag: open flag
+ * @mode: mode bits
+ * @u_attr: queue attributes
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr)
+{
+	struct audit_aux_data_mq_open *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (!audit_enabled)
+		return 0;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+	if (!ax)
+		return -ENOMEM;
+
+	if (u_attr != NULL) {
+		if (copy_from_user(&ax->attr, u_attr, sizeof(ax->attr))) {
+			kfree(ax);
+			return -EFAULT;
+		}
+	} else
+		memset(&ax->attr, 0, sizeof(ax->attr));
+
+	ax->oflag = oflag;
+	ax->mode = mode;
+
+	ax->d.type = AUDIT_MQ_OPEN;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+/**
+ * __audit_mq_timedsend - record audit data for a POSIX MQ timed send
+ * @mqdes: MQ descriptor
+ * @msg_len: Message length
+ * @msg_prio: Message priority
+ * @u_abs_timeout: Message timeout in absolute time
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio,
+			const struct timespec __user *u_abs_timeout)
+{
+	struct audit_aux_data_mq_sendrecv *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (!audit_enabled)
+		return 0;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+	if (!ax)
+		return -ENOMEM;
+
+	if (u_abs_timeout != NULL) {
+		if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
+			kfree(ax);
+			return -EFAULT;
+		}
+	} else
+		memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
+
+	ax->mqdes = mqdes;
+	ax->msg_len = msg_len;
+	ax->msg_prio = msg_prio;
+
+	ax->d.type = AUDIT_MQ_SENDRECV;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+/**
+ * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive
+ * @mqdes: MQ descriptor
+ * @msg_len: Message length
+ * @u_msg_prio: Message priority
+ * @u_abs_timeout: Message timeout in absolute time
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len,
+				unsigned int __user *u_msg_prio,
+				const struct timespec __user *u_abs_timeout)
+{
+	struct audit_aux_data_mq_sendrecv *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (!audit_enabled)
+		return 0;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+	if (!ax)
+		return -ENOMEM;
+
+	if (u_msg_prio != NULL) {
+		if (get_user(ax->msg_prio, u_msg_prio)) {
+			kfree(ax);
+			return -EFAULT;
+		}
+	} else
+		ax->msg_prio = 0;
+
+	if (u_abs_timeout != NULL) {
+		if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) {
+			kfree(ax);
+			return -EFAULT;
+		}
+	} else
+		memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout));
+
+	ax->mqdes = mqdes;
+	ax->msg_len = msg_len;
+
+	ax->d.type = AUDIT_MQ_SENDRECV;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+/**
+ * __audit_mq_notify - record audit data for a POSIX MQ notify
+ * @mqdes: MQ descriptor
+ * @u_notification: Notification event
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+
+int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification)
+{
+	struct audit_aux_data_mq_notify *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (!audit_enabled)
+		return 0;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+	if (!ax)
+		return -ENOMEM;
+
+	if (u_notification != NULL) {
+		if (copy_from_user(&ax->notification, u_notification, sizeof(ax->notification))) {
+			kfree(ax);
+			return -EFAULT;
+		}
+	} else
+		memset(&ax->notification, 0, sizeof(ax->notification));
+
+	ax->mqdes = mqdes;
+
+	ax->d.type = AUDIT_MQ_NOTIFY;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+/**
+ * __audit_mq_getsetattr - record audit data for a POSIX MQ get/set attribute
+ * @mqdes: MQ descriptor
+ * @mqstat: MQ flags
+ *
+ * Returns 0 for success or NULL context or < 0 on error.
+ */
+int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
+{
+	struct audit_aux_data_mq_getsetattr *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (!audit_enabled)
+		return 0;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+	if (!ax)
+		return -ENOMEM;
+
+	ax->mqdes = mqdes;
+	ax->mqstat = *mqstat;
+
+	ax->d.type = AUDIT_MQ_GETSETATTR;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+/**
  * audit_ipc_obj - record audit data for ipc object
  * @ipcp: ipc permissions
  *
  * Returns 0 for success or NULL context or < 0 on error.
  */
-int audit_ipc_obj(struct kern_ipc_perm *ipcp)
+int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
 	struct audit_aux_data_ipcctl *ax;
 	struct audit_context *context = current->audit_context;
 
-	if (likely(!context))
-		return 0;
-
 	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
 	if (!ax)
 		return -ENOMEM;
@@ -1207,14 +1560,11 @@
  *
  * Returns 0 for success or NULL context or < 0 on error.
  */
-int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp)
+int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
 {
 	struct audit_aux_data_ipcctl *ax;
 	struct audit_context *context = current->audit_context;
 
-	if (likely(!context))
-		return 0;
-
 	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
 	if (!ax)
 		return -ENOMEM;
@@ -1223,7 +1573,6 @@
 	ax->uid = uid;
 	ax->gid = gid;
 	ax->mode = mode;
-	selinux_get_ipc_sid(ipcp, &ax->osid);
 
 	ax->d.type = AUDIT_IPC_SET_PERM;
 	ax->d.next = context->aux;
@@ -1231,6 +1580,39 @@
 	return 0;
 }
 
+int audit_bprm(struct linux_binprm *bprm)
+{
+	struct audit_aux_data_execve *ax;
+	struct audit_context *context = current->audit_context;
+	unsigned long p, next;
+	void *to;
+
+	if (likely(!audit_enabled || !context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p,
+				GFP_KERNEL);
+	if (!ax)
+		return -ENOMEM;
+
+	ax->argc = bprm->argc;
+	ax->envc = bprm->envc;
+	for (p = bprm->p, to = ax->mem; p < MAX_ARG_PAGES*PAGE_SIZE; p = next) {
+		struct page *page = bprm->page[p / PAGE_SIZE];
+		void *kaddr = kmap(page);
+		next = (p + PAGE_SIZE) & ~(PAGE_SIZE - 1);
+		memcpy(to, kaddr + (p & (PAGE_SIZE - 1)), next - p);
+		to += next - p;
+		kunmap(page);
+	}
+
+	ax->d.type = AUDIT_EXECVE;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+
 /**
  * audit_socketcall - record audit data for sys_socketcall
  * @nargs: number of args
@@ -1325,19 +1707,20 @@
  * If the audit subsystem is being terminated, record the task (pid)
  * and uid that is doing that.
  */
-void audit_signal_info(int sig, struct task_struct *t)
+void __audit_signal_info(int sig, struct task_struct *t)
 {
 	extern pid_t audit_sig_pid;
 	extern uid_t audit_sig_uid;
+	extern u32 audit_sig_sid;
 
-	if (unlikely(audit_pid && t->tgid == audit_pid)) {
-		if (sig == SIGTERM || sig == SIGHUP) {
-			struct audit_context *ctx = current->audit_context;
-			audit_sig_pid = current->pid;
-			if (ctx)
-				audit_sig_uid = ctx->loginuid;
-			else
-				audit_sig_uid = current->uid;
-		}
+	if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
+		struct task_struct *tsk = current;
+		struct audit_context *ctx = tsk->audit_context;
+		audit_sig_pid = tsk->pid;
+		if (ctx)
+			audit_sig_uid = ctx->loginuid;
+		else
+			audit_sig_uid = tsk->uid;
+		selinux_get_task_sid(tsk, &audit_sig_sid);
 	}
 }
diff --git a/kernel/compat.c b/kernel/compat.c
index c1601a8..126dee9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -21,6 +21,7 @@
 #include <linux/unistd.h>
 #include <linux/security.h>
 #include <linux/timex.h>
+#include <linux/migrate.h>
 
 #include <asm/uaccess.h>
 
@@ -729,17 +730,10 @@
 sigset_from_compat (sigset_t *set, compat_sigset_t *compat)
 {
 	switch (_NSIG_WORDS) {
-#if defined (__COMPAT_ENDIAN_SWAP__)
-	case 4: set->sig[3] = compat->sig[7] | (((long)compat->sig[6]) << 32 );
-	case 3: set->sig[2] = compat->sig[5] | (((long)compat->sig[4]) << 32 );
-	case 2: set->sig[1] = compat->sig[3] | (((long)compat->sig[2]) << 32 );
-	case 1: set->sig[0] = compat->sig[1] | (((long)compat->sig[0]) << 32 );
-#else
 	case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 );
 	case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 );
 	case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 );
 	case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 );
-#endif
 	}
 }
 
@@ -934,3 +928,25 @@
 
 	return ret;
 }
+
+#ifdef CONFIG_NUMA
+asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages,
+		compat_uptr_t __user *pages32,
+		const int __user *nodes,
+		int __user *status,
+		int flags)
+{
+	const void __user * __user *pages;
+	int i;
+
+	pages = compat_alloc_user_space(nr_pages * sizeof(void *));
+	for (i = 0; i < nr_pages; i++) {
+		compat_uptr_t p;
+
+		if (get_user(p, pages32 + i) ||
+			put_user(compat_ptr(p), pages + i))
+			return -EFAULT;
+	}
+	return sys_move_pages(pid, nr_pages, pages, nodes, status, flags);
+}
+#endif
diff --git a/kernel/cpu.c b/kernel/cpu.c
index fe2b8d0..70fbf2e 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -13,12 +13,12 @@
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <linux/stop_machine.h>
-#include <asm/semaphore.h>
+#include <linux/mutex.h>
 
 /* This protects CPUs going up and down... */
-static DECLARE_MUTEX(cpucontrol);
+static DEFINE_MUTEX(cpucontrol);
 
-static BLOCKING_NOTIFIER_HEAD(cpu_chain);
+static __cpuinitdata BLOCKING_NOTIFIER_HEAD(cpu_chain);
 
 #ifdef CONFIG_HOTPLUG_CPU
 static struct task_struct *lock_cpu_hotplug_owner;
@@ -30,9 +30,9 @@
 
 	if (lock_cpu_hotplug_owner != current) {
 		if (interruptible)
-			ret = down_interruptible(&cpucontrol);
+			ret = mutex_lock_interruptible(&cpucontrol);
 		else
-			down(&cpucontrol);
+			mutex_lock(&cpucontrol);
 	}
 
 	/*
@@ -56,7 +56,7 @@
 {
 	if (--lock_cpu_hotplug_depth == 0) {
 		lock_cpu_hotplug_owner = NULL;
-		up(&cpucontrol);
+		mutex_unlock(&cpucontrol);
 	}
 }
 EXPORT_SYMBOL_GPL(unlock_cpu_hotplug);
@@ -69,10 +69,13 @@
 #endif	/* CONFIG_HOTPLUG_CPU */
 
 /* Need to know about CPUs going up/down? */
-int register_cpu_notifier(struct notifier_block *nb)
+int __cpuinit register_cpu_notifier(struct notifier_block *nb)
 {
 	return blocking_notifier_chain_register(&cpu_chain, nb);
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+
 EXPORT_SYMBOL(register_cpu_notifier);
 
 void unregister_cpu_notifier(struct notifier_block *nb)
@@ -81,7 +84,6 @@
 }
 EXPORT_SYMBOL(unregister_cpu_notifier);
 
-#ifdef CONFIG_HOTPLUG_CPU
 static inline void check_for_tasks(int cpu)
 {
 	struct task_struct *p;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index ab81fdd..1535af3 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -41,6 +41,7 @@
 #include <linux/rcupdate.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
+#include <linux/security.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
@@ -392,11 +393,11 @@
 	return 0;
 }
 
-static struct super_block *cpuset_get_sb(struct file_system_type *fs_type,
-					int flags, const char *unused_dev_name,
-					void *data)
+static int cpuset_get_sb(struct file_system_type *fs_type,
+			 int flags, const char *unused_dev_name,
+			 void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, cpuset_fill_super);
+	return get_sb_single(fs_type, flags, data, cpuset_fill_super, mnt);
 }
 
 static struct file_system_type cpuset_fs_type = {
@@ -1177,6 +1178,7 @@
 	cpumask_t cpus;
 	nodemask_t from, to;
 	struct mm_struct *mm;
+	int retval;
 
 	if (sscanf(pidbuf, "%d", &pid) != 1)
 		return -EIO;
@@ -1205,6 +1207,12 @@
 		get_task_struct(tsk);
 	}
 
+	retval = security_task_setscheduler(tsk, 0, NULL);
+	if (retval) {
+		put_task_struct(tsk);
+		return retval;
+	}
+
 	mutex_lock(&callback_mutex);
 
 	task_lock(tsk);
@@ -2434,31 +2442,43 @@
  */
 static int proc_cpuset_show(struct seq_file *m, void *v)
 {
+	struct pid *pid;
 	struct task_struct *tsk;
 	char *buf;
-	int retval = 0;
+	int retval;
 
+	retval = -ENOMEM;
 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!buf)
-		return -ENOMEM;
+		goto out;
 
-	tsk = m->private;
+	retval = -ESRCH;
+	pid = m->private;
+	tsk = get_pid_task(pid, PIDTYPE_PID);
+	if (!tsk)
+		goto out_free;
+
+	retval = -EINVAL;
 	mutex_lock(&manage_mutex);
+
 	retval = cpuset_path(tsk->cpuset, buf, PAGE_SIZE);
 	if (retval < 0)
-		goto out;
+		goto out_unlock;
 	seq_puts(m, buf);
 	seq_putc(m, '\n');
-out:
+out_unlock:
 	mutex_unlock(&manage_mutex);
+	put_task_struct(tsk);
+out_free:
 	kfree(buf);
+out:
 	return retval;
 }
 
 static int cpuset_open(struct inode *inode, struct file *file)
 {
-	struct task_struct *tsk = PROC_I(inode)->task;
-	return single_open(file, proc_cpuset_show, tsk);
+	struct pid *pid = PROC_I(inode)->pid;
+	return single_open(file, proc_cpuset_show, pid);
 }
 
 struct file_operations proc_cpuset_operations = {
diff --git a/kernel/exit.c b/kernel/exit.c
index e06d0c1..ab06b9f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -36,6 +36,7 @@
 #include <linux/compat.h>
 #include <linux/pipe_fs_i.h>
 #include <linux/audit.h> /* for audit_free() */
+#include <linux/resource.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -45,8 +46,6 @@
 extern void sem_exit (void);
 extern struct task_struct *child_reaper;
 
-int getrusage(struct task_struct *, int, struct rusage __user *);
-
 static void exit_mm(struct task_struct * tsk);
 
 static void __unhash_process(struct task_struct *p)
@@ -138,12 +137,8 @@
 {
 	int zap_leader;
 	task_t *leader;
-	struct dentry *proc_dentry;
-
 repeat:
 	atomic_dec(&p->user->processes);
-	spin_lock(&p->proc_lock);
-	proc_dentry = proc_pid_unhash(p);
 	write_lock_irq(&tasklist_lock);
 	ptrace_unlink(p);
 	BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
@@ -172,8 +167,7 @@
 
 	sched_exit(p);
 	write_unlock_irq(&tasklist_lock);
-	spin_unlock(&p->proc_lock);
-	proc_pid_flush(proc_dentry);
+	proc_flush_task(p);
 	release_thread(p);
 	call_rcu(&p->rcu, delayed_put_task_struct);
 
@@ -579,7 +573,7 @@
 		down_read(&mm->mmap_sem);
 	}
 	atomic_inc(&mm->mm_count);
-	if (mm != tsk->active_mm) BUG();
+	BUG_ON(mm != tsk->active_mm);
 	/* more a memory barrier than a real lock */
 	task_lock(tsk);
 	tsk->mm = NULL;
@@ -895,11 +889,11 @@
 	if (group_dead) {
  		hrtimer_cancel(&tsk->signal->real_timer);
 		exit_itimers(tsk->signal);
-		acct_process(code);
 	}
+	acct_collect(code, group_dead);
 	if (unlikely(tsk->robust_list))
 		exit_robust_list(tsk);
-#ifdef CONFIG_COMPAT
+#if defined(CONFIG_FUTEX) && defined(CONFIG_COMPAT)
 	if (unlikely(tsk->compat_robust_list))
 		compat_exit_robust_list(tsk);
 #endif
@@ -907,6 +901,8 @@
 		audit_free(tsk);
 	exit_mm(tsk);
 
+	if (group_dead)
+		acct_process();
 	exit_sem(tsk);
 	__exit_files(tsk);
 	__exit_fs(tsk);
@@ -930,9 +926,18 @@
 	tsk->mempolicy = NULL;
 #endif
 	/*
+	 * This must happen late, after the PID is not
+	 * hashed anymore:
+	 */
+	if (unlikely(!list_empty(&tsk->pi_state_list)))
+		exit_pi_state_list(tsk);
+	if (unlikely(current->pi_state_cache))
+		kfree(current->pi_state_cache);
+	/*
 	 * If DEBUG_MUTEXES is on, make sure we are holding no locks:
 	 */
 	mutex_debug_check_no_locks_held(tsk);
+	rt_mutex_debug_check_no_locks_held(tsk);
 
 	if (tsk->io_context)
 		exit_io_context();
@@ -1530,8 +1535,7 @@
 		if (options & __WNOTHREAD)
 			break;
 		tsk = next_thread(tsk);
-		if (tsk->signal != current->signal)
-			BUG();
+		BUG_ON(tsk->signal != current->signal);
 	} while (tsk != current);
 
 	read_unlock(&tasklist_lock);
diff --git a/kernel/fork.c b/kernel/fork.c
index ac8100e..628198a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -104,6 +104,7 @@
 void free_task(struct task_struct *tsk)
 {
 	free_thread_info(tsk->thread_info);
+	rt_mutex_debug_task_free(tsk);
 	free_task_struct(tsk);
 }
 EXPORT_SYMBOL(free_task);
@@ -368,6 +369,8 @@
  */
 void mmput(struct mm_struct *mm)
 {
+	might_sleep();
+
 	if (atomic_dec_and_test(&mm->mm_users)) {
 		exit_aio(mm);
 		exit_mmap(mm);
@@ -623,6 +626,7 @@
 /*
  * Allocate a new files structure and copy contents from the
  * passed in files structure.
+ * errorp will be valid only when the returned files_struct is NULL.
  */
 static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
 {
@@ -631,6 +635,7 @@
 	int open_files, size, i, expand;
 	struct fdtable *old_fdt, *new_fdt;
 
+	*errorp = -ENOMEM;
 	newf = alloc_files();
 	if (!newf)
 		goto out;
@@ -744,7 +749,6 @@
 	 * break this.
 	 */
 	tsk->files = NULL;
-	error = -ENOMEM;
 	newf = dup_fd(oldf, &error);
 	if (!newf)
 		goto out;
@@ -871,6 +875,7 @@
 		tsk->it_prof_expires =
 			secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
 	}
+	acct_init_pacct(&sig->pacct);
 
 	return 0;
 }
@@ -909,6 +914,19 @@
 	return current->pid;
 }
 
+static inline void rt_mutex_init_task(struct task_struct *p)
+{
+#ifdef CONFIG_RT_MUTEXES
+	spin_lock_init(&p->pi_lock);
+	plist_head_init(&p->pi_waiters, &p->pi_lock);
+	p->pi_blocked_on = NULL;
+# ifdef CONFIG_DEBUG_RT_MUTEXES
+	spin_lock_init(&p->held_list_lock);
+	INIT_LIST_HEAD(&p->held_list_head);
+# endif
+#endif
+}
+
 /*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
@@ -989,13 +1007,10 @@
 		if (put_user(p->pid, parent_tidptr))
 			goto bad_fork_cleanup;
 
-	p->proc_dentry = NULL;
-
 	INIT_LIST_HEAD(&p->children);
 	INIT_LIST_HEAD(&p->sibling);
 	p->vfork_done = NULL;
 	spin_lock_init(&p->alloc_lock);
-	spin_lock_init(&p->proc_lock);
 
 	clear_tsk_thread_flag(p, TIF_SIGPENDING);
 	init_sigpending(&p->pending);
@@ -1033,6 +1048,8 @@
 	mpol_fix_fork_child_flag(p);
 #endif
 
+	rt_mutex_init_task(p);
+
 #ifdef CONFIG_DEBUG_MUTEXES
 	p->blocked_on = NULL; /* not blocked yet */
 #endif
@@ -1075,6 +1092,9 @@
 #ifdef CONFIG_COMPAT
 	p->compat_robust_list = NULL;
 #endif
+	INIT_LIST_HEAD(&p->pi_state_list);
+	p->pi_state_cache = NULL;
+
 	/*
 	 * sigaltstack should be cleared when sharing the same VM
 	 */
@@ -1155,18 +1175,6 @@
 	}
 
 	if (clone_flags & CLONE_THREAD) {
-		/*
-		 * Important: if an exit-all has been started then
-		 * do not create this new thread - the whole thread
-		 * group is supposed to exit anyway.
-		 */
-		if (current->signal->flags & SIGNAL_GROUP_EXIT) {
-			spin_unlock(&current->sighand->siglock);
-			write_unlock_irq(&tasklist_lock);
-			retval = -EAGAIN;
-			goto bad_fork_cleanup_namespace;
-		}
-
 		p->group_leader = current->group_leader;
 		list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
 
diff --git a/kernel/futex.c b/kernel/futex.c
index 5699c51..6c91f93 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -12,6 +12,10 @@
  *  (C) Copyright 2006 Red Hat Inc, All Rights Reserved
  *  Thanks to Thomas Gleixner for suggestions, analysis and fixes.
  *
+ *  PI-futex support started by Ingo Molnar and Thomas Gleixner
+ *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
  *  Thanks to Ben LaHaise for yelling "hashed waitqueues" loudly
  *  enough at me, Linus for the original (flawed) idea, Matthew
  *  Kirkwood for proof-of-concept implementation.
@@ -46,6 +50,8 @@
 #include <linux/signal.h>
 #include <asm/futex.h>
 
+#include "rtmutex_common.h"
+
 #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
 /*
@@ -63,7 +69,7 @@
 		int offset;
 	} shared;
 	struct {
-		unsigned long uaddr;
+		unsigned long address;
 		struct mm_struct *mm;
 		int offset;
 	} private;
@@ -75,6 +81,27 @@
 };
 
 /*
+ * Priority Inheritance state:
+ */
+struct futex_pi_state {
+	/*
+	 * list of 'owned' pi_state instances - these have to be
+	 * cleaned up in do_exit() if the task exits prematurely:
+	 */
+	struct list_head list;
+
+	/*
+	 * The PI object:
+	 */
+	struct rt_mutex pi_mutex;
+
+	struct task_struct *owner;
+	atomic_t refcount;
+
+	union futex_key key;
+};
+
+/*
  * We use this hashed waitqueue instead of a normal wait_queue_t, so
  * we can wake only the relevant ones (hashed queues may be shared).
  *
@@ -87,15 +114,19 @@
 	struct list_head list;
 	wait_queue_head_t waiters;
 
-	/* Which hash list lock to use. */
+	/* Which hash list lock to use: */
 	spinlock_t *lock_ptr;
 
-	/* Key which the futex is hashed on. */
+	/* Key which the futex is hashed on: */
 	union futex_key key;
 
-	/* For fd, sigio sent using these. */
+	/* For fd, sigio sent using these: */
 	int fd;
 	struct file *filp;
+
+	/* Optional priority inheritance state: */
+	struct futex_pi_state *pi_state;
+	struct task_struct *task;
 };
 
 /*
@@ -144,8 +175,9 @@
  *
  * Should be called with &current->mm->mmap_sem but NOT any spinlocks.
  */
-static int get_futex_key(unsigned long uaddr, union futex_key *key)
+static int get_futex_key(u32 __user *uaddr, union futex_key *key)
 {
+	unsigned long address = (unsigned long)uaddr;
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	struct page *page;
@@ -154,16 +186,16 @@
 	/*
 	 * The futex address must be "naturally" aligned.
 	 */
-	key->both.offset = uaddr % PAGE_SIZE;
+	key->both.offset = address % PAGE_SIZE;
 	if (unlikely((key->both.offset % sizeof(u32)) != 0))
 		return -EINVAL;
-	uaddr -= key->both.offset;
+	address -= key->both.offset;
 
 	/*
 	 * The futex is hashed differently depending on whether
 	 * it's in a shared or private mapping.  So check vma first.
 	 */
-	vma = find_extend_vma(mm, uaddr);
+	vma = find_extend_vma(mm, address);
 	if (unlikely(!vma))
 		return -EFAULT;
 
@@ -184,7 +216,7 @@
 	 */
 	if (likely(!(vma->vm_flags & VM_MAYSHARE))) {
 		key->private.mm = mm;
-		key->private.uaddr = uaddr;
+		key->private.address = address;
 		return 0;
 	}
 
@@ -194,7 +226,7 @@
 	key->shared.inode = vma->vm_file->f_dentry->d_inode;
 	key->both.offset++; /* Bit 0 of offset indicates inode-based key. */
 	if (likely(!(vma->vm_flags & VM_NONLINEAR))) {
-		key->shared.pgoff = (((uaddr - vma->vm_start) >> PAGE_SHIFT)
+		key->shared.pgoff = (((address - vma->vm_start) >> PAGE_SHIFT)
 				     + vma->vm_pgoff);
 		return 0;
 	}
@@ -205,7 +237,7 @@
 	 * from swap.  But that's a lot of code to duplicate here
 	 * for a rare case, so we simply fetch the page.
 	 */
-	err = get_user_pages(current, mm, uaddr, 1, 0, 0, &page, NULL);
+	err = get_user_pages(current, mm, address, 1, 0, 0, &page, NULL);
 	if (err >= 0) {
 		key->shared.pgoff =
 			page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
@@ -246,18 +278,244 @@
 	}
 }
 
-static inline int get_futex_value_locked(int *dest, int __user *from)
+static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
 {
 	int ret;
 
 	inc_preempt_count();
-	ret = __copy_from_user_inatomic(dest, from, sizeof(int));
+	ret = __copy_from_user_inatomic(dest, from, sizeof(u32));
 	dec_preempt_count();
 
 	return ret ? -EFAULT : 0;
 }
 
 /*
+ * Fault handling. Called with current->mm->mmap_sem held.
+ */
+static int futex_handle_fault(unsigned long address, int attempt)
+{
+	struct vm_area_struct * vma;
+	struct mm_struct *mm = current->mm;
+
+	if (attempt >= 2 || !(vma = find_vma(mm, address)) ||
+	    vma->vm_start > address || !(vma->vm_flags & VM_WRITE))
+		return -EFAULT;
+
+	switch (handle_mm_fault(mm, vma, address, 1)) {
+	case VM_FAULT_MINOR:
+		current->min_flt++;
+		break;
+	case VM_FAULT_MAJOR:
+		current->maj_flt++;
+		break;
+	default:
+		return -EFAULT;
+	}
+	return 0;
+}
+
+/*
+ * PI code:
+ */
+static int refill_pi_state_cache(void)
+{
+	struct futex_pi_state *pi_state;
+
+	if (likely(current->pi_state_cache))
+		return 0;
+
+	pi_state = kmalloc(sizeof(*pi_state), GFP_KERNEL);
+
+	if (!pi_state)
+		return -ENOMEM;
+
+	memset(pi_state, 0, sizeof(*pi_state));
+	INIT_LIST_HEAD(&pi_state->list);
+	/* pi_mutex gets initialized later */
+	pi_state->owner = NULL;
+	atomic_set(&pi_state->refcount, 1);
+
+	current->pi_state_cache = pi_state;
+
+	return 0;
+}
+
+static struct futex_pi_state * alloc_pi_state(void)
+{
+	struct futex_pi_state *pi_state = current->pi_state_cache;
+
+	WARN_ON(!pi_state);
+	current->pi_state_cache = NULL;
+
+	return pi_state;
+}
+
+static void free_pi_state(struct futex_pi_state *pi_state)
+{
+	if (!atomic_dec_and_test(&pi_state->refcount))
+		return;
+
+	/*
+	 * If pi_state->owner is NULL, the owner is most probably dying
+	 * and has cleaned up the pi_state already
+	 */
+	if (pi_state->owner) {
+		spin_lock_irq(&pi_state->owner->pi_lock);
+		list_del_init(&pi_state->list);
+		spin_unlock_irq(&pi_state->owner->pi_lock);
+
+		rt_mutex_proxy_unlock(&pi_state->pi_mutex, pi_state->owner);
+	}
+
+	if (current->pi_state_cache)
+		kfree(pi_state);
+	else {
+		/*
+		 * pi_state->list is already empty.
+		 * clear pi_state->owner.
+		 * refcount is at 0 - put it back to 1.
+		 */
+		pi_state->owner = NULL;
+		atomic_set(&pi_state->refcount, 1);
+		current->pi_state_cache = pi_state;
+	}
+}
+
+/*
+ * Look up the task based on what TID userspace gave us.
+ * We dont trust it.
+ */
+static struct task_struct * futex_find_get_task(pid_t pid)
+{
+	struct task_struct *p;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+	if (!p)
+		goto out_unlock;
+	if ((current->euid != p->euid) && (current->euid != p->uid)) {
+		p = NULL;
+		goto out_unlock;
+	}
+	if (p->state == EXIT_ZOMBIE || p->exit_state == EXIT_ZOMBIE) {
+		p = NULL;
+		goto out_unlock;
+	}
+	get_task_struct(p);
+out_unlock:
+	read_unlock(&tasklist_lock);
+
+	return p;
+}
+
+/*
+ * This task is holding PI mutexes at exit time => bad.
+ * Kernel cleans up PI-state, but userspace is likely hosed.
+ * (Robust-futex cleanup is separate and might save the day for userspace.)
+ */
+void exit_pi_state_list(struct task_struct *curr)
+{
+	struct futex_hash_bucket *hb;
+	struct list_head *next, *head = &curr->pi_state_list;
+	struct futex_pi_state *pi_state;
+	union futex_key key;
+
+	/*
+	 * We are a ZOMBIE and nobody can enqueue itself on
+	 * pi_state_list anymore, but we have to be careful
+	 * versus waiters unqueueing themselfs
+	 */
+	spin_lock_irq(&curr->pi_lock);
+	while (!list_empty(head)) {
+
+		next = head->next;
+		pi_state = list_entry(next, struct futex_pi_state, list);
+		key = pi_state->key;
+		spin_unlock_irq(&curr->pi_lock);
+
+		hb = hash_futex(&key);
+		spin_lock(&hb->lock);
+
+		spin_lock_irq(&curr->pi_lock);
+		if (head->next != next) {
+			spin_unlock(&hb->lock);
+			continue;
+		}
+
+		list_del_init(&pi_state->list);
+
+		WARN_ON(pi_state->owner != curr);
+
+		pi_state->owner = NULL;
+		spin_unlock_irq(&curr->pi_lock);
+
+		rt_mutex_unlock(&pi_state->pi_mutex);
+
+		spin_unlock(&hb->lock);
+
+		spin_lock_irq(&curr->pi_lock);
+	}
+	spin_unlock_irq(&curr->pi_lock);
+}
+
+static int
+lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, struct futex_q *me)
+{
+	struct futex_pi_state *pi_state = NULL;
+	struct futex_q *this, *next;
+	struct list_head *head;
+	struct task_struct *p;
+	pid_t pid;
+
+	head = &hb->chain;
+
+	list_for_each_entry_safe(this, next, head, list) {
+		if (match_futex (&this->key, &me->key)) {
+			/*
+			 * Another waiter already exists - bump up
+			 * the refcount and return its pi_state:
+			 */
+			pi_state = this->pi_state;
+			atomic_inc(&pi_state->refcount);
+			me->pi_state = pi_state;
+
+			return 0;
+		}
+	}
+
+	/*
+	 * We are the first waiter - try to look up the real owner and
+	 * attach the new pi_state to it:
+	 */
+	pid = uval & FUTEX_TID_MASK;
+	p = futex_find_get_task(pid);
+	if (!p)
+		return -ESRCH;
+
+	pi_state = alloc_pi_state();
+
+	/*
+	 * Initialize the pi_mutex in locked state and make 'p'
+	 * the owner of it:
+	 */
+	rt_mutex_init_proxy_locked(&pi_state->pi_mutex, p);
+
+	/* Store the key for possible exit cleanups: */
+	pi_state->key = me->key;
+
+	spin_lock_irq(&p->pi_lock);
+	list_add(&pi_state->list, &p->pi_state_list);
+	pi_state->owner = p;
+	spin_unlock_irq(&p->pi_lock);
+
+	put_task_struct(p);
+
+	me->pi_state = pi_state;
+
+	return 0;
+}
+
+/*
  * The hash bucket lock must be held when this is called.
  * Afterwards, the futex_q must not be accessed.
  */
@@ -284,16 +542,80 @@
 	q->lock_ptr = NULL;
 }
 
+static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this)
+{
+	struct task_struct *new_owner;
+	struct futex_pi_state *pi_state = this->pi_state;
+	u32 curval, newval;
+
+	if (!pi_state)
+		return -EINVAL;
+
+	new_owner = rt_mutex_next_owner(&pi_state->pi_mutex);
+
+	/*
+	 * This happens when we have stolen the lock and the original
+	 * pending owner did not enqueue itself back on the rt_mutex.
+	 * Thats not a tragedy. We know that way, that a lock waiter
+	 * is on the fly. We make the futex_q waiter the pending owner.
+	 */
+	if (!new_owner)
+		new_owner = this->task;
+
+	/*
+	 * We pass it to the next owner. (The WAITERS bit is always
+	 * kept enabled while there is PI state around. We must also
+	 * preserve the owner died bit.)
+	 */
+	newval = (uval & FUTEX_OWNER_DIED) | FUTEX_WAITERS | new_owner->pid;
+
+	inc_preempt_count();
+	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	dec_preempt_count();
+
+	if (curval == -EFAULT)
+		return -EFAULT;
+	if (curval != uval)
+		return -EINVAL;
+
+	list_del_init(&pi_state->owner->pi_state_list);
+	list_add(&pi_state->list, &new_owner->pi_state_list);
+	pi_state->owner = new_owner;
+	rt_mutex_unlock(&pi_state->pi_mutex);
+
+	return 0;
+}
+
+static int unlock_futex_pi(u32 __user *uaddr, u32 uval)
+{
+	u32 oldval;
+
+	/*
+	 * There is no waiter, so we unlock the futex. The owner died
+	 * bit has not to be preserved here. We are the owner:
+	 */
+	inc_preempt_count();
+	oldval = futex_atomic_cmpxchg_inatomic(uaddr, uval, 0);
+	dec_preempt_count();
+
+	if (oldval == -EFAULT)
+		return oldval;
+	if (oldval != uval)
+		return -EAGAIN;
+
+	return 0;
+}
+
 /*
  * Wake up all waiters hashed on the physical page that is mapped
  * to this virtual address:
  */
-static int futex_wake(unsigned long uaddr, int nr_wake)
+static int futex_wake(u32 __user *uaddr, int nr_wake)
 {
-	union futex_key key;
-	struct futex_hash_bucket *bh;
-	struct list_head *head;
+	struct futex_hash_bucket *hb;
 	struct futex_q *this, *next;
+	struct list_head *head;
+	union futex_key key;
 	int ret;
 
 	down_read(&current->mm->mmap_sem);
@@ -302,19 +624,21 @@
 	if (unlikely(ret != 0))
 		goto out;
 
-	bh = hash_futex(&key);
-	spin_lock(&bh->lock);
-	head = &bh->chain;
+	hb = hash_futex(&key);
+	spin_lock(&hb->lock);
+	head = &hb->chain;
 
 	list_for_each_entry_safe(this, next, head, list) {
 		if (match_futex (&this->key, &key)) {
+			if (this->pi_state)
+				return -EINVAL;
 			wake_futex(this);
 			if (++ret >= nr_wake)
 				break;
 		}
 	}
 
-	spin_unlock(&bh->lock);
+	spin_unlock(&hb->lock);
 out:
 	up_read(&current->mm->mmap_sem);
 	return ret;
@@ -324,10 +648,12 @@
  * Wake up all waiters hashed on the physical page that is mapped
  * to this virtual address:
  */
-static int futex_wake_op(unsigned long uaddr1, unsigned long uaddr2, int nr_wake, int nr_wake2, int op)
+static int
+futex_wake_op(u32 __user *uaddr1, u32 __user *uaddr2,
+	      int nr_wake, int nr_wake2, int op)
 {
 	union futex_key key1, key2;
-	struct futex_hash_bucket *bh1, *bh2;
+	struct futex_hash_bucket *hb1, *hb2;
 	struct list_head *head;
 	struct futex_q *this, *next;
 	int ret, op_ret, attempt = 0;
@@ -342,27 +668,29 @@
 	if (unlikely(ret != 0))
 		goto out;
 
-	bh1 = hash_futex(&key1);
-	bh2 = hash_futex(&key2);
+	hb1 = hash_futex(&key1);
+	hb2 = hash_futex(&key2);
 
 retry:
-	if (bh1 < bh2)
-		spin_lock(&bh1->lock);
-	spin_lock(&bh2->lock);
-	if (bh1 > bh2)
-		spin_lock(&bh1->lock);
+	if (hb1 < hb2)
+		spin_lock(&hb1->lock);
+	spin_lock(&hb2->lock);
+	if (hb1 > hb2)
+		spin_lock(&hb1->lock);
 
-	op_ret = futex_atomic_op_inuser(op, (int __user *)uaddr2);
+	op_ret = futex_atomic_op_inuser(op, uaddr2);
 	if (unlikely(op_ret < 0)) {
-		int dummy;
+		u32 dummy;
 
-		spin_unlock(&bh1->lock);
-		if (bh1 != bh2)
-			spin_unlock(&bh2->lock);
+		spin_unlock(&hb1->lock);
+		if (hb1 != hb2)
+			spin_unlock(&hb2->lock);
 
 #ifndef CONFIG_MMU
-		/* we don't get EFAULT from MMU faults if we don't have an MMU,
-		 * but we might get them from range checking */
+		/*
+		 * we don't get EFAULT from MMU faults if we don't have an MMU,
+		 * but we might get them from range checking
+		 */
 		ret = op_ret;
 		goto out;
 #endif
@@ -372,47 +700,34 @@
 			goto out;
 		}
 
-		/* futex_atomic_op_inuser needs to both read and write
+		/*
+		 * futex_atomic_op_inuser needs to both read and write
 		 * *(int __user *)uaddr2, but we can't modify it
 		 * non-atomically.  Therefore, if get_user below is not
 		 * enough, we need to handle the fault ourselves, while
-		 * still holding the mmap_sem.  */
+		 * still holding the mmap_sem.
+		 */
 		if (attempt++) {
-			struct vm_area_struct * vma;
-			struct mm_struct *mm = current->mm;
-
-			ret = -EFAULT;
-			if (attempt >= 2 ||
-			    !(vma = find_vma(mm, uaddr2)) ||
-			    vma->vm_start > uaddr2 ||
-			    !(vma->vm_flags & VM_WRITE))
+			if (futex_handle_fault((unsigned long)uaddr2,
+					       attempt))
 				goto out;
-
-			switch (handle_mm_fault(mm, vma, uaddr2, 1)) {
-			case VM_FAULT_MINOR:
-				current->min_flt++;
-				break;
-			case VM_FAULT_MAJOR:
-				current->maj_flt++;
-				break;
-			default:
-				goto out;
-			}
 			goto retry;
 		}
 
-		/* If we would have faulted, release mmap_sem,
-		 * fault it in and start all over again.  */
+		/*
+		 * If we would have faulted, release mmap_sem,
+		 * fault it in and start all over again.
+		 */
 		up_read(&current->mm->mmap_sem);
 
-		ret = get_user(dummy, (int __user *)uaddr2);
+		ret = get_user(dummy, uaddr2);
 		if (ret)
 			return ret;
 
 		goto retryfull;
 	}
 
-	head = &bh1->chain;
+	head = &hb1->chain;
 
 	list_for_each_entry_safe(this, next, head, list) {
 		if (match_futex (&this->key, &key1)) {
@@ -423,7 +738,7 @@
 	}
 
 	if (op_ret > 0) {
-		head = &bh2->chain;
+		head = &hb2->chain;
 
 		op_ret = 0;
 		list_for_each_entry_safe(this, next, head, list) {
@@ -436,9 +751,9 @@
 		ret += op_ret;
 	}
 
-	spin_unlock(&bh1->lock);
-	if (bh1 != bh2)
-		spin_unlock(&bh2->lock);
+	spin_unlock(&hb1->lock);
+	if (hb1 != hb2)
+		spin_unlock(&hb2->lock);
 out:
 	up_read(&current->mm->mmap_sem);
 	return ret;
@@ -448,11 +763,11 @@
  * Requeue all waiters hashed on one physical page to another
  * physical page.
  */
-static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
-			 int nr_wake, int nr_requeue, int *valp)
+static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2,
+			 int nr_wake, int nr_requeue, u32 *cmpval)
 {
 	union futex_key key1, key2;
-	struct futex_hash_bucket *bh1, *bh2;
+	struct futex_hash_bucket *hb1, *hb2;
 	struct list_head *head1;
 	struct futex_q *this, *next;
 	int ret, drop_count = 0;
@@ -467,68 +782,72 @@
 	if (unlikely(ret != 0))
 		goto out;
 
-	bh1 = hash_futex(&key1);
-	bh2 = hash_futex(&key2);
+	hb1 = hash_futex(&key1);
+	hb2 = hash_futex(&key2);
 
-	if (bh1 < bh2)
-		spin_lock(&bh1->lock);
-	spin_lock(&bh2->lock);
-	if (bh1 > bh2)
-		spin_lock(&bh1->lock);
+	if (hb1 < hb2)
+		spin_lock(&hb1->lock);
+	spin_lock(&hb2->lock);
+	if (hb1 > hb2)
+		spin_lock(&hb1->lock);
 
-	if (likely(valp != NULL)) {
-		int curval;
+	if (likely(cmpval != NULL)) {
+		u32 curval;
 
-		ret = get_futex_value_locked(&curval, (int __user *)uaddr1);
+		ret = get_futex_value_locked(&curval, uaddr1);
 
 		if (unlikely(ret)) {
-			spin_unlock(&bh1->lock);
-			if (bh1 != bh2)
-				spin_unlock(&bh2->lock);
+			spin_unlock(&hb1->lock);
+			if (hb1 != hb2)
+				spin_unlock(&hb2->lock);
 
-			/* If we would have faulted, release mmap_sem, fault
+			/*
+			 * If we would have faulted, release mmap_sem, fault
 			 * it in and start all over again.
 			 */
 			up_read(&current->mm->mmap_sem);
 
-			ret = get_user(curval, (int __user *)uaddr1);
+			ret = get_user(curval, uaddr1);
 
 			if (!ret)
 				goto retry;
 
 			return ret;
 		}
-		if (curval != *valp) {
+		if (curval != *cmpval) {
 			ret = -EAGAIN;
 			goto out_unlock;
 		}
 	}
 
-	head1 = &bh1->chain;
+	head1 = &hb1->chain;
 	list_for_each_entry_safe(this, next, head1, list) {
 		if (!match_futex (&this->key, &key1))
 			continue;
 		if (++ret <= nr_wake) {
 			wake_futex(this);
 		} else {
-			list_move_tail(&this->list, &bh2->chain);
-			this->lock_ptr = &bh2->lock;
+			/*
+			 * If key1 and key2 hash to the same bucket, no need to
+			 * requeue.
+			 */
+			if (likely(head1 != &hb2->chain)) {
+				list_move_tail(&this->list, &hb2->chain);
+				this->lock_ptr = &hb2->lock;
+			}
 			this->key = key2;
 			get_key_refs(&key2);
 			drop_count++;
 
 			if (ret - nr_wake >= nr_requeue)
 				break;
-			/* Make sure to stop if key1 == key2 */
-			if (head1 == &bh2->chain && head1 != &next->list)
-				head1 = &this->list;
 		}
 	}
 
 out_unlock:
-	spin_unlock(&bh1->lock);
-	if (bh1 != bh2)
-		spin_unlock(&bh2->lock);
+	spin_unlock(&hb1->lock);
+	if (hb1 != hb2)
+		spin_unlock(&hb2->lock);
 
 	/* drop_key_refs() must be called outside the spinlocks. */
 	while (--drop_count >= 0)
@@ -543,7 +862,7 @@
 static inline struct futex_hash_bucket *
 queue_lock(struct futex_q *q, int fd, struct file *filp)
 {
-	struct futex_hash_bucket *bh;
+	struct futex_hash_bucket *hb;
 
 	q->fd = fd;
 	q->filp = filp;
@@ -551,23 +870,24 @@
 	init_waitqueue_head(&q->waiters);
 
 	get_key_refs(&q->key);
-	bh = hash_futex(&q->key);
-	q->lock_ptr = &bh->lock;
+	hb = hash_futex(&q->key);
+	q->lock_ptr = &hb->lock;
 
-	spin_lock(&bh->lock);
-	return bh;
+	spin_lock(&hb->lock);
+	return hb;
 }
 
-static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *bh)
+static inline void __queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
 {
-	list_add_tail(&q->list, &bh->chain);
-	spin_unlock(&bh->lock);
+	list_add_tail(&q->list, &hb->chain);
+	q->task = current;
+	spin_unlock(&hb->lock);
 }
 
 static inline void
-queue_unlock(struct futex_q *q, struct futex_hash_bucket *bh)
+queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
 {
-	spin_unlock(&bh->lock);
+	spin_unlock(&hb->lock);
 	drop_key_refs(&q->key);
 }
 
@@ -579,16 +899,17 @@
 /* The key must be already stored in q->key. */
 static void queue_me(struct futex_q *q, int fd, struct file *filp)
 {
-	struct futex_hash_bucket *bh;
-	bh = queue_lock(q, fd, filp);
-	__queue_me(q, bh);
+	struct futex_hash_bucket *hb;
+
+	hb = queue_lock(q, fd, filp);
+	__queue_me(q, hb);
 }
 
 /* Return 1 if we were still queued (ie. 0 means we were woken) */
 static int unqueue_me(struct futex_q *q)
 {
-	int ret = 0;
 	spinlock_t *lock_ptr;
+	int ret = 0;
 
 	/* In the common case we don't take the spinlock, which is nice. */
  retry:
@@ -614,6 +935,9 @@
 		}
 		WARN_ON(list_empty(&q->list));
 		list_del(&q->list);
+
+		BUG_ON(q->pi_state);
+
 		spin_unlock(lock_ptr);
 		ret = 1;
 	}
@@ -622,21 +946,42 @@
 	return ret;
 }
 
-static int futex_wait(unsigned long uaddr, int val, unsigned long time)
+/*
+ * PI futexes can not be requeued and must remove themself from the
+ * hash bucket. The hash bucket lock is held on entry and dropped here.
+ */
+static void unqueue_me_pi(struct futex_q *q, struct futex_hash_bucket *hb)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	int ret, curval;
-	struct futex_q q;
-	struct futex_hash_bucket *bh;
+	WARN_ON(list_empty(&q->list));
+	list_del(&q->list);
 
+	BUG_ON(!q->pi_state);
+	free_pi_state(q->pi_state);
+	q->pi_state = NULL;
+
+	spin_unlock(&hb->lock);
+
+	drop_key_refs(&q->key);
+}
+
+static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)
+{
+	struct task_struct *curr = current;
+	DECLARE_WAITQUEUE(wait, curr);
+	struct futex_hash_bucket *hb;
+	struct futex_q q;
+	u32 uval;
+	int ret;
+
+	q.pi_state = NULL;
  retry:
-	down_read(&current->mm->mmap_sem);
+	down_read(&curr->mm->mmap_sem);
 
 	ret = get_futex_key(uaddr, &q.key);
 	if (unlikely(ret != 0))
 		goto out_release_sem;
 
-	bh = queue_lock(&q, -1, NULL);
+	hb = queue_lock(&q, -1, NULL);
 
 	/*
 	 * Access the page AFTER the futex is queued.
@@ -658,37 +1003,35 @@
 	 * We hold the mmap semaphore, so the mapping cannot have changed
 	 * since we looked it up in get_futex_key.
 	 */
-
-	ret = get_futex_value_locked(&curval, (int __user *)uaddr);
+	ret = get_futex_value_locked(&uval, uaddr);
 
 	if (unlikely(ret)) {
-		queue_unlock(&q, bh);
+		queue_unlock(&q, hb);
 
-		/* If we would have faulted, release mmap_sem, fault it in and
+		/*
+		 * If we would have faulted, release mmap_sem, fault it in and
 		 * start all over again.
 		 */
-		up_read(&current->mm->mmap_sem);
+		up_read(&curr->mm->mmap_sem);
 
-		ret = get_user(curval, (int __user *)uaddr);
+		ret = get_user(uval, uaddr);
 
 		if (!ret)
 			goto retry;
 		return ret;
 	}
-	if (curval != val) {
-		ret = -EWOULDBLOCK;
-		queue_unlock(&q, bh);
-		goto out_release_sem;
-	}
+	ret = -EWOULDBLOCK;
+	if (uval != val)
+		goto out_unlock_release_sem;
 
 	/* Only actually queue if *uaddr contained val.  */
-	__queue_me(&q, bh);
+	__queue_me(&q, hb);
 
 	/*
 	 * Now the futex is queued and we have checked the data, we
 	 * don't want to hold mmap_sem while we sleep.
-	 */	
-	up_read(&current->mm->mmap_sem);
+	 */
+	up_read(&curr->mm->mmap_sem);
 
 	/*
 	 * There might have been scheduling since the queue_me(), as we
@@ -720,12 +1063,421 @@
 		return 0;
 	if (time == 0)
 		return -ETIMEDOUT;
-	/* We expect signal_pending(current), but another thread may
-	 * have handled it for us already. */
+	/*
+	 * We expect signal_pending(current), but another thread may
+	 * have handled it for us already.
+	 */
 	return -EINTR;
 
+ out_unlock_release_sem:
+	queue_unlock(&q, hb);
+
  out_release_sem:
+	up_read(&curr->mm->mmap_sem);
+	return ret;
+}
+
+/*
+ * Userspace tried a 0 -> TID atomic transition of the futex value
+ * and failed. The kernel side here does the whole locking operation:
+ * if there are waiters then it will block, it does PI, etc. (Due to
+ * races the kernel might see a 0 value of the futex too.)
+ */
+static int do_futex_lock_pi(u32 __user *uaddr, int detect, int trylock,
+			    struct hrtimer_sleeper *to)
+{
+	struct task_struct *curr = current;
+	struct futex_hash_bucket *hb;
+	u32 uval, newval, curval;
+	struct futex_q q;
+	int ret, attempt = 0;
+
+	if (refill_pi_state_cache())
+		return -ENOMEM;
+
+	q.pi_state = NULL;
+ retry:
+	down_read(&curr->mm->mmap_sem);
+
+	ret = get_futex_key(uaddr, &q.key);
+	if (unlikely(ret != 0))
+		goto out_release_sem;
+
+	hb = queue_lock(&q, -1, NULL);
+
+ retry_locked:
+	/*
+	 * To avoid races, we attempt to take the lock here again
+	 * (by doing a 0 -> TID atomic cmpxchg), while holding all
+	 * the locks. It will most likely not succeed.
+	 */
+	newval = current->pid;
+
+	inc_preempt_count();
+	curval = futex_atomic_cmpxchg_inatomic(uaddr, 0, newval);
+	dec_preempt_count();
+
+	if (unlikely(curval == -EFAULT))
+		goto uaddr_faulted;
+
+	/* We own the lock already */
+	if (unlikely((curval & FUTEX_TID_MASK) == current->pid)) {
+		if (!detect && 0)
+			force_sig(SIGKILL, current);
+		ret = -EDEADLK;
+		goto out_unlock_release_sem;
+	}
+
+	/*
+	 * Surprise - we got the lock. Just return
+	 * to userspace:
+	 */
+	if (unlikely(!curval))
+		goto out_unlock_release_sem;
+
+	uval = curval;
+	newval = uval | FUTEX_WAITERS;
+
+	inc_preempt_count();
+	curval = futex_atomic_cmpxchg_inatomic(uaddr, uval, newval);
+	dec_preempt_count();
+
+	if (unlikely(curval == -EFAULT))
+		goto uaddr_faulted;
+	if (unlikely(curval != uval))
+		goto retry_locked;
+
+	/*
+	 * We dont have the lock. Look up the PI state (or create it if
+	 * we are the first waiter):
+	 */
+	ret = lookup_pi_state(uval, hb, &q);
+
+	if (unlikely(ret)) {
+		/*
+		 * There were no waiters and the owner task lookup
+		 * failed. When the OWNER_DIED bit is set, then we
+		 * know that this is a robust futex and we actually
+		 * take the lock. This is safe as we are protected by
+		 * the hash bucket lock. We also set the waiters bit
+		 * unconditionally here, to simplify glibc handling of
+		 * multiple tasks racing to acquire the lock and
+		 * cleanup the problems which were left by the dead
+		 * owner.
+		 */
+		if (curval & FUTEX_OWNER_DIED) {
+			uval = newval;
+			newval = current->pid |
+				FUTEX_OWNER_DIED | FUTEX_WAITERS;
+
+			inc_preempt_count();
+			curval = futex_atomic_cmpxchg_inatomic(uaddr,
+							       uval, newval);
+			dec_preempt_count();
+
+			if (unlikely(curval == -EFAULT))
+				goto uaddr_faulted;
+			if (unlikely(curval != uval))
+				goto retry_locked;
+			ret = 0;
+		}
+		goto out_unlock_release_sem;
+	}
+
+	/*
+	 * Only actually queue now that the atomic ops are done:
+	 */
+	__queue_me(&q, hb);
+
+	/*
+	 * Now the futex is queued and we have checked the data, we
+	 * don't want to hold mmap_sem while we sleep.
+	 */
+	up_read(&curr->mm->mmap_sem);
+
+	WARN_ON(!q.pi_state);
+	/*
+	 * Block on the PI mutex:
+	 */
+	if (!trylock)
+		ret = rt_mutex_timed_lock(&q.pi_state->pi_mutex, to, 1);
+	else {
+		ret = rt_mutex_trylock(&q.pi_state->pi_mutex);
+		/* Fixup the trylock return value: */
+		ret = ret ? 0 : -EWOULDBLOCK;
+	}
+
+	down_read(&curr->mm->mmap_sem);
+	hb = queue_lock(&q, -1, NULL);
+
+	/*
+	 * Got the lock. We might not be the anticipated owner if we
+	 * did a lock-steal - fix up the PI-state in that case.
+	 */
+	if (!ret && q.pi_state->owner != curr) {
+		u32 newtid = current->pid | FUTEX_WAITERS;
+
+		/* Owner died? */
+		if (q.pi_state->owner != NULL) {
+			spin_lock_irq(&q.pi_state->owner->pi_lock);
+			list_del_init(&q.pi_state->list);
+			spin_unlock_irq(&q.pi_state->owner->pi_lock);
+		} else
+			newtid |= FUTEX_OWNER_DIED;
+
+		q.pi_state->owner = current;
+
+		spin_lock_irq(&current->pi_lock);
+		list_add(&q.pi_state->list, &current->pi_state_list);
+		spin_unlock_irq(&current->pi_lock);
+
+		/* Unqueue and drop the lock */
+		unqueue_me_pi(&q, hb);
+		up_read(&curr->mm->mmap_sem);
+		/*
+		 * We own it, so we have to replace the pending owner
+		 * TID. This must be atomic as we have preserve the
+		 * owner died bit here.
+		 */
+		ret = get_user(uval, uaddr);
+		while (!ret) {
+			newval = (uval & FUTEX_OWNER_DIED) | newtid;
+			curval = futex_atomic_cmpxchg_inatomic(uaddr,
+							       uval, newval);
+			if (curval == -EFAULT)
+				ret = -EFAULT;
+			if (curval == uval)
+				break;
+			uval = curval;
+		}
+	} else {
+		/*
+		 * Catch the rare case, where the lock was released
+		 * when we were on the way back before we locked
+		 * the hash bucket.
+		 */
+		if (ret && q.pi_state->owner == curr) {
+			if (rt_mutex_trylock(&q.pi_state->pi_mutex))
+				ret = 0;
+		}
+		/* Unqueue and drop the lock */
+		unqueue_me_pi(&q, hb);
+		up_read(&curr->mm->mmap_sem);
+	}
+
+	if (!detect && ret == -EDEADLK && 0)
+		force_sig(SIGKILL, current);
+
+	return ret;
+
+ out_unlock_release_sem:
+	queue_unlock(&q, hb);
+
+ out_release_sem:
+	up_read(&curr->mm->mmap_sem);
+	return ret;
+
+ uaddr_faulted:
+	/*
+	 * We have to r/w  *(int __user *)uaddr, but we can't modify it
+	 * non-atomically.  Therefore, if get_user below is not
+	 * enough, we need to handle the fault ourselves, while
+	 * still holding the mmap_sem.
+	 */
+	if (attempt++) {
+		if (futex_handle_fault((unsigned long)uaddr, attempt))
+			goto out_unlock_release_sem;
+
+		goto retry_locked;
+	}
+
+	queue_unlock(&q, hb);
+	up_read(&curr->mm->mmap_sem);
+
+	ret = get_user(uval, uaddr);
+	if (!ret && (uval != -EFAULT))
+		goto retry;
+
+	return ret;
+}
+
+/*
+ * Restart handler
+ */
+static long futex_lock_pi_restart(struct restart_block *restart)
+{
+	struct hrtimer_sleeper timeout, *to = NULL;
+	int ret;
+
+	restart->fn = do_no_restart_syscall;
+
+	if (restart->arg2 || restart->arg3) {
+		to = &timeout;
+		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
+		hrtimer_init_sleeper(to, current);
+		to->timer.expires.tv64 = ((u64)restart->arg1 << 32) |
+			(u64) restart->arg0;
+	}
+
+	pr_debug("lock_pi restart: %p, %d (%d)\n",
+		 (u32 __user *)restart->arg0, current->pid);
+
+	ret = do_futex_lock_pi((u32 __user *)restart->arg0, restart->arg1,
+			       0, to);
+
+	if (ret != -EINTR)
+		return ret;
+
+	restart->fn = futex_lock_pi_restart;
+
+	/* The other values are filled in */
+	return -ERESTART_RESTARTBLOCK;
+}
+
+/*
+ * Called from the syscall entry below.
+ */
+static int futex_lock_pi(u32 __user *uaddr, int detect, unsigned long sec,
+			 long nsec, int trylock)
+{
+	struct hrtimer_sleeper timeout, *to = NULL;
+	struct restart_block *restart;
+	int ret;
+
+	if (sec != MAX_SCHEDULE_TIMEOUT) {
+		to = &timeout;
+		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
+		hrtimer_init_sleeper(to, current);
+		to->timer.expires = ktime_set(sec, nsec);
+	}
+
+	ret = do_futex_lock_pi(uaddr, detect, trylock, to);
+
+	if (ret != -EINTR)
+		return ret;
+
+	pr_debug("lock_pi interrupted: %p, %d (%d)\n", uaddr, current->pid);
+
+	restart = &current_thread_info()->restart_block;
+	restart->fn = futex_lock_pi_restart;
+	restart->arg0 = (unsigned long) uaddr;
+	restart->arg1 = detect;
+	if (to) {
+		restart->arg2 = to->timer.expires.tv64 & 0xFFFFFFFF;
+		restart->arg3 = to->timer.expires.tv64 >> 32;
+	} else
+		restart->arg2 = restart->arg3 = 0;
+
+	return -ERESTART_RESTARTBLOCK;
+}
+
+/*
+ * Userspace attempted a TID -> 0 atomic transition, and failed.
+ * This is the in-kernel slowpath: we look up the PI state (if any),
+ * and do the rt-mutex unlock.
+ */
+static int futex_unlock_pi(u32 __user *uaddr)
+{
+	struct futex_hash_bucket *hb;
+	struct futex_q *this, *next;
+	u32 uval;
+	struct list_head *head;
+	union futex_key key;
+	int ret, attempt = 0;
+
+retry:
+	if (get_user(uval, uaddr))
+		return -EFAULT;
+	/*
+	 * We release only a lock we actually own:
+	 */
+	if ((uval & FUTEX_TID_MASK) != current->pid)
+		return -EPERM;
+	/*
+	 * First take all the futex related locks:
+	 */
+	down_read(&current->mm->mmap_sem);
+
+	ret = get_futex_key(uaddr, &key);
+	if (unlikely(ret != 0))
+		goto out;
+
+	hb = hash_futex(&key);
+	spin_lock(&hb->lock);
+
+retry_locked:
+	/*
+	 * To avoid races, try to do the TID -> 0 atomic transition
+	 * again. If it succeeds then we can return without waking
+	 * anyone else up:
+	 */
+	inc_preempt_count();
+	uval = futex_atomic_cmpxchg_inatomic(uaddr, current->pid, 0);
+	dec_preempt_count();
+
+	if (unlikely(uval == -EFAULT))
+		goto pi_faulted;
+	/*
+	 * Rare case: we managed to release the lock atomically,
+	 * no need to wake anyone else up:
+	 */
+	if (unlikely(uval == current->pid))
+		goto out_unlock;
+
+	/*
+	 * Ok, other tasks may need to be woken up - check waiters
+	 * and do the wakeup if necessary:
+	 */
+	head = &hb->chain;
+
+	list_for_each_entry_safe(this, next, head, list) {
+		if (!match_futex (&this->key, &key))
+			continue;
+		ret = wake_futex_pi(uaddr, uval, this);
+		/*
+		 * The atomic access to the futex value
+		 * generated a pagefault, so retry the
+		 * user-access and the wakeup:
+		 */
+		if (ret == -EFAULT)
+			goto pi_faulted;
+		goto out_unlock;
+	}
+	/*
+	 * No waiters - kernel unlocks the futex:
+	 */
+	ret = unlock_futex_pi(uaddr, uval);
+	if (ret == -EFAULT)
+		goto pi_faulted;
+
+out_unlock:
+	spin_unlock(&hb->lock);
+out:
 	up_read(&current->mm->mmap_sem);
+
+	return ret;
+
+pi_faulted:
+	/*
+	 * We have to r/w  *(int __user *)uaddr, but we can't modify it
+	 * non-atomically.  Therefore, if get_user below is not
+	 * enough, we need to handle the fault ourselves, while
+	 * still holding the mmap_sem.
+	 */
+	if (attempt++) {
+		if (futex_handle_fault((unsigned long)uaddr, attempt))
+			goto out_unlock;
+
+		goto retry_locked;
+	}
+
+	spin_unlock(&hb->lock);
+	up_read(&current->mm->mmap_sem);
+
+	ret = get_user(uval, uaddr);
+	if (!ret && (uval != -EFAULT))
+		goto retry;
+
 	return ret;
 }
 
@@ -735,6 +1487,7 @@
 
 	unqueue_me(q);
 	kfree(q);
+
 	return 0;
 }
 
@@ -766,7 +1519,7 @@
  * Signal allows caller to avoid the race which would occur if they
  * set the sigio stuff up afterwards.
  */
-static int futex_fd(unsigned long uaddr, int signal)
+static int futex_fd(u32 __user *uaddr, int signal)
 {
 	struct futex_q *q;
 	struct file *filp;
@@ -803,6 +1556,7 @@
 		err = -ENOMEM;
 		goto error;
 	}
+	q->pi_state = NULL;
 
 	down_read(&current->mm->mmap_sem);
 	err = get_futex_key(uaddr, &q->key);
@@ -840,7 +1594,7 @@
  * Implementation: user-space maintains a per-thread list of locks it
  * is holding. Upon do_exit(), the kernel carefully walks this list,
  * and marks all locks that are owned by this thread with the
- * FUTEX_OWNER_DEAD bit, and wakes up a waiter (if any). The list is
+ * FUTEX_OWNER_DIED bit, and wakes up a waiter (if any). The list is
  * always manipulated with the lock held, so the list is private and
  * per-thread. Userspace also maintains a per-thread 'list_op_pending'
  * field, to allow the kernel to clean up if the thread dies after
@@ -915,7 +1669,7 @@
  */
 int handle_futex_death(u32 __user *uaddr, struct task_struct *curr)
 {
-	u32 uval;
+	u32 uval, nval;
 
 retry:
 	if (get_user(uval, uaddr))
@@ -932,12 +1686,16 @@
 		 * thread-death.) The rest of the cleanup is done in
 		 * userspace.
 		 */
-		if (futex_atomic_cmpxchg_inatomic(uaddr, uval,
-					 uval | FUTEX_OWNER_DIED) != uval)
+		nval = futex_atomic_cmpxchg_inatomic(uaddr, uval,
+						     uval | FUTEX_OWNER_DIED);
+		if (nval == -EFAULT)
+			return -1;
+
+		if (nval != uval)
 			goto retry;
 
 		if (uval & FUTEX_WAITERS)
-			futex_wake((unsigned long)uaddr, 1);
+			futex_wake(uaddr, 1);
 	}
 	return 0;
 }
@@ -978,7 +1736,7 @@
 	while (entry != &head->list) {
 		/*
 		 * A pending lock might already be on the list, so
-		 * dont process it twice:
+		 * don't process it twice:
 		 */
 		if (entry != pending)
 			if (handle_futex_death((void *)entry + futex_offset,
@@ -999,8 +1757,8 @@
 	}
 }
 
-long do_futex(unsigned long uaddr, int op, int val, unsigned long timeout,
-		unsigned long uaddr2, int val2, int val3)
+long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
+		u32 __user *uaddr2, u32 val2, u32 val3)
 {
 	int ret;
 
@@ -1024,6 +1782,15 @@
 	case FUTEX_WAKE_OP:
 		ret = futex_wake_op(uaddr, uaddr2, val, val2, val3);
 		break;
+	case FUTEX_LOCK_PI:
+		ret = futex_lock_pi(uaddr, val, timeout, val2, 0);
+		break;
+	case FUTEX_UNLOCK_PI:
+		ret = futex_unlock_pi(uaddr);
+		break;
+	case FUTEX_TRYLOCK_PI:
+		ret = futex_lock_pi(uaddr, 0, timeout, val2, 1);
+		break;
 	default:
 		ret = -ENOSYS;
 	}
@@ -1031,36 +1798,40 @@
 }
 
 
-asmlinkage long sys_futex(u32 __user *uaddr, int op, int val,
+asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
 			  struct timespec __user *utime, u32 __user *uaddr2,
-			  int val3)
+			  u32 val3)
 {
 	struct timespec t;
 	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
-	int val2 = 0;
+	u32 val2 = 0;
 
-	if (utime && (op == FUTEX_WAIT)) {
+	if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
 		if (copy_from_user(&t, utime, sizeof(t)) != 0)
 			return -EFAULT;
 		if (!timespec_valid(&t))
 			return -EINVAL;
-		timeout = timespec_to_jiffies(&t) + 1;
+		if (op == FUTEX_WAIT)
+			timeout = timespec_to_jiffies(&t) + 1;
+		else {
+			timeout = t.tv_sec;
+			val2 = t.tv_nsec;
+		}
 	}
 	/*
 	 * requeue parameter in 'utime' if op == FUTEX_REQUEUE.
 	 */
-	if (op >= FUTEX_REQUEUE)
-		val2 = (int) (unsigned long) utime;
+	if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE)
+		val2 = (u32) (unsigned long) utime;
 
-	return do_futex((unsigned long)uaddr, op, val, timeout,
-			(unsigned long)uaddr2, val2, val3);
+	return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3);
 }
 
-static struct super_block *
-futexfs_get_sb(struct file_system_type *fs_type,
-	       int flags, const char *dev_name, void *data)
+static int futexfs_get_sb(struct file_system_type *fs_type,
+			  int flags, const char *dev_name, void *data,
+			  struct vfsmount *mnt)
 {
-	return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA);
+	return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA, mnt);
 }
 
 static struct file_system_type futex_fs_type = {
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
index 1ab6a0e..d1d92b4 100644
--- a/kernel/futex_compat.c
+++ b/kernel/futex_compat.c
@@ -129,16 +129,20 @@
 	unsigned long timeout = MAX_SCHEDULE_TIMEOUT;
 	int val2 = 0;
 
-	if (utime && (op == FUTEX_WAIT)) {
+	if (utime && (op == FUTEX_WAIT || op == FUTEX_LOCK_PI)) {
 		if (get_compat_timespec(&t, utime))
 			return -EFAULT;
 		if (!timespec_valid(&t))
 			return -EINVAL;
-		timeout = timespec_to_jiffies(&t) + 1;
+		if (op == FUTEX_WAIT)
+			timeout = timespec_to_jiffies(&t) + 1;
+		else {
+			timeout = t.tv_sec;
+			val2 = t.tv_nsec;
+		}
 	}
-	if (op >= FUTEX_REQUEUE)
+	if (op == FUTEX_REQUEUE || op == FUTEX_CMP_REQUEUE)
 		val2 = (int) (unsigned long) utime;
 
-	return do_futex((unsigned long)uaddr, op, val, timeout,
-			(unsigned long)uaddr2, val2, val3);
+	return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3);
 }
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index 01fa2ae..8d3dc29 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -98,7 +98,6 @@
 
 /**
  * ktime_get_ts - get the monotonic clock in timespec format
- *
  * @ts:		pointer to timespec variable
  *
  * The function calculates the monotonic clock from the realtime
@@ -238,7 +237,6 @@
 # ifndef CONFIG_KTIME_SCALAR
 /**
  * ktime_add_ns - Add a scalar nanoseconds value to a ktime_t variable
- *
  * @kt:		addend
  * @nsec:	the scalar nsec value to add
  *
@@ -299,7 +297,6 @@
 
 /**
  * hrtimer_forward - forward the timer expiry
- *
  * @timer:	hrtimer to forward
  * @now:	forward past this time
  * @interval:	the interval to forward
@@ -393,7 +390,7 @@
 	if (base->first == &timer->node)
 		base->first = rb_next(&timer->node);
 	rb_erase(&timer->node, &base->active);
-	timer->node.rb_parent = HRTIMER_INACTIVE;
+	rb_set_parent(&timer->node, &timer->node);
 }
 
 /*
@@ -411,7 +408,6 @@
 
 /**
  * hrtimer_start - (re)start an relative timer on the current CPU
- *
  * @timer:	the timer to be added
  * @tim:	expiry time
  * @mode:	expiry mode: absolute (HRTIMER_ABS) or relative (HRTIMER_REL)
@@ -460,14 +456,13 @@
 
 /**
  * hrtimer_try_to_cancel - try to deactivate a timer
- *
  * @timer:	hrtimer to stop
  *
  * Returns:
  *  0 when the timer was not active
  *  1 when the timer was active
  * -1 when the timer is currently excuting the callback function and
- *    can not be stopped
+ *    cannot be stopped
  */
 int hrtimer_try_to_cancel(struct hrtimer *timer)
 {
@@ -489,7 +484,6 @@
 
 /**
  * hrtimer_cancel - cancel a timer and wait for the handler to finish.
- *
  * @timer:	the timer to be cancelled
  *
  * Returns:
@@ -510,7 +504,6 @@
 
 /**
  * hrtimer_get_remaining - get remaining time for the timer
- *
  * @timer:	the timer to read
  */
 ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
@@ -564,7 +557,6 @@
 
 /**
  * hrtimer_init - initialize a timer to the given clock
- *
  * @timer:	the timer to be initialized
  * @clock_id:	the clock to be used
  * @mode:	timer mode abs/rel
@@ -576,19 +568,18 @@
 
 	memset(timer, 0, sizeof(struct hrtimer));
 
-	bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+	bases = __raw_get_cpu_var(hrtimer_bases);
 
 	if (clock_id == CLOCK_REALTIME && mode != HRTIMER_ABS)
 		clock_id = CLOCK_MONOTONIC;
 
 	timer->base = &bases[clock_id];
-	timer->node.rb_parent = HRTIMER_INACTIVE;
+	rb_set_parent(&timer->node, &timer->node);
 }
 EXPORT_SYMBOL_GPL(hrtimer_init);
 
 /**
  * hrtimer_get_res - get the timer resolution for a clock
- *
  * @which_clock: which clock to query
  * @tp:		 pointer to timespec variable to store the resolution
  *
@@ -599,7 +590,7 @@
 {
 	struct hrtimer_base *bases;
 
-	bases = per_cpu(hrtimer_bases, raw_smp_processor_id());
+	bases = __raw_get_cpu_var(hrtimer_bases);
 	*tp = ktime_to_timespec(bases[which_clock].resolution);
 
 	return 0;
@@ -842,7 +833,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int hrtimer_cpu_notify(struct notifier_block *self,
+static int __devinit hrtimer_cpu_notify(struct notifier_block *self,
 					unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -866,7 +857,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block hrtimers_nb = {
+static struct notifier_block __devinitdata hrtimers_nb = {
 	.notifier_call = hrtimer_cpu_notify,
 };
 
diff --git a/kernel/intermodule.c b/kernel/intermodule.c
deleted file mode 100644
index 55b1e5b..0000000
--- a/kernel/intermodule.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/* Deprecated, do not use.  Moved from module.c to here. --RR */
-
-/* Written by Keith Owens <kaos@ocs.com.au> Oct 2000 */
-#include <linux/module.h>
-#include <linux/kmod.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-
-/* inter_module functions are always available, even when the kernel is
- * compiled without modules.  Consumers of inter_module_xxx routines
- * will always work, even when both are built into the kernel, this
- * approach removes lots of #ifdefs in mainline code.
- */
-
-static struct list_head ime_list = LIST_HEAD_INIT(ime_list);
-static DEFINE_SPINLOCK(ime_lock);
-static int kmalloc_failed;
-
-struct inter_module_entry {
-	struct list_head list;
-	const char *im_name;
-	struct module *owner;
-	const void *userdata;
-};
-
-/**
- * inter_module_register - register a new set of inter module data.
- * @im_name: an arbitrary string to identify the data, must be unique
- * @owner: module that is registering the data, always use THIS_MODULE
- * @userdata: pointer to arbitrary userdata to be registered
- *
- * Description: Check that the im_name has not already been registered,
- * complain if it has.  For new data, add it to the inter_module_entry
- * list.
- */
-void inter_module_register(const char *im_name, struct module *owner, const void *userdata)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime, *ime_new;
-
-	if (!(ime_new = kzalloc(sizeof(*ime), GFP_KERNEL))) {
-		/* Overloaded kernel, not fatal */
-		printk(KERN_ERR
-			"Aiee, inter_module_register: cannot kmalloc entry for '%s'\n",
-			im_name);
-		kmalloc_failed = 1;
-		return;
-	}
-	ime_new->im_name = im_name;
-	ime_new->owner = owner;
-	ime_new->userdata = userdata;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			spin_unlock(&ime_lock);
-			kfree(ime_new);
-			/* Program logic error, fatal */
-			printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name);
-			BUG();
-		}
-	}
-	list_add(&(ime_new->list), &ime_list);
-	spin_unlock(&ime_lock);
-}
-
-/**
- * inter_module_unregister - unregister a set of inter module data.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: Check that the im_name has been registered, complain if
- * it has not.  For existing data, remove it from the
- * inter_module_entry list.
- */
-void inter_module_unregister(const char *im_name)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			list_del(&(ime->list));
-			spin_unlock(&ime_lock);
-			kfree(ime);
-			return;
-		}
-	}
-	spin_unlock(&ime_lock);
-	if (kmalloc_failed) {
-		printk(KERN_ERR
-			"inter_module_unregister: no entry for '%s', "
-			"probably caused by previous kmalloc failure\n",
-			im_name);
-		return;
-	}
-	else {
-		/* Program logic error, fatal */
-		printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name);
-		BUG();
-	}
-}
-
-/**
- * inter_module_get - return arbitrary userdata from another module.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: If the im_name has not been registered, return NULL.
- * Try to increment the use count on the owning module, if that fails
- * then return NULL.  Otherwise return the userdata.
- */
-static const void *inter_module_get(const char *im_name)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime;
-	const void *result = NULL;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			if (try_module_get(ime->owner))
-				result = ime->userdata;
-			break;
-		}
-	}
-	spin_unlock(&ime_lock);
-	return(result);
-}
-
-/**
- * inter_module_get_request - im get with automatic request_module.
- * @im_name: an arbitrary string to identify the data, must be unique
- * @modname: module that is expected to register im_name
- *
- * Description: If inter_module_get fails, do request_module then retry.
- */
-const void *inter_module_get_request(const char *im_name, const char *modname)
-{
-	const void *result = inter_module_get(im_name);
-	if (!result) {
-		request_module("%s", modname);
-		result = inter_module_get(im_name);
-	}
-	return(result);
-}
-
-/**
- * inter_module_put - release use of data from another module.
- * @im_name: an arbitrary string to identify the data, must be unique
- *
- * Description: If the im_name has not been registered, complain,
- * otherwise decrement the use count on the owning module.
- */
-void inter_module_put(const char *im_name)
-{
-	struct list_head *tmp;
-	struct inter_module_entry *ime;
-
-	spin_lock(&ime_lock);
-	list_for_each(tmp, &ime_list) {
-		ime = list_entry(tmp, struct inter_module_entry, list);
-		if (strcmp(ime->im_name, im_name) == 0) {
-			if (ime->owner)
-				module_put(ime->owner);
-			spin_unlock(&ime_lock);
-			return;
-		}
-	}
-	spin_unlock(&ime_lock);
-	printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name);
-	BUG();
-}
-
-EXPORT_SYMBOL(inter_module_register);
-EXPORT_SYMBOL(inter_module_unregister);
-EXPORT_SYMBOL(inter_module_get_request);
-EXPORT_SYMBOL(inter_module_put);
-
-MODULE_LICENSE("GPL");
-
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 51df337..0f65301 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -76,10 +76,11 @@
 /*
  * Have got an event to handle:
  */
-fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
+fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
 				struct irqaction *action)
 {
-	int ret, retval = 0, status = 0;
+	irqreturn_t ret, retval = IRQ_NONE;
+	unsigned int status = 0;
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 134f9f2..a12d00e 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -30,7 +30,7 @@
 
 	desc->move_irq = 0;
 
-	if (likely(cpus_empty(pending_irq_cpumask[irq])))
+	if (unlikely(cpus_empty(pending_irq_cpumask[irq])))
 		return;
 
 	if (!desc->handler->set_affinity)
@@ -49,7 +49,7 @@
 	 * cause some ioapics to mal-function.
 	 * Being paranoid i guess!
 	 */
-	if (unlikely(!cpus_empty(tmp))) {
+	if (likely(!cpus_empty(tmp))) {
 		if (likely(!(desc->status & IRQ_DISABLED)))
 			desc->handler->disable(irq);
 
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index d03b5ee..afacd6f 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -24,6 +24,8 @@
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
 {
+	set_balance_irq_affinity(irq, mask_val);
+
 	/*
 	 * Save these away for later use. Re-progam when the
 	 * interrupt is pending
@@ -33,6 +35,7 @@
 #else
 void proc_set_irq_affinity(unsigned int irq, cpumask_t mask_val)
 {
+	set_balance_irq_affinity(irq, mask_val);
 	irq_affinity[irq] = mask_val;
 	irq_desc[irq].handler->set_affinity(irq, mask_val);
 }
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 7df9abd..b2fb3c1 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -11,7 +11,7 @@
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
 
-static int irqfixup;
+static int irqfixup __read_mostly;
 
 /*
  * Recovery handler for misrouted interrupts.
@@ -136,9 +136,9 @@
 void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret,
 			struct pt_regs *regs)
 {
-	if (action_ret != IRQ_HANDLED) {
+	if (unlikely(action_ret != IRQ_HANDLED)) {
 		desc->irqs_unhandled++;
-		if (action_ret != IRQ_NONE)
+		if (unlikely(action_ret != IRQ_NONE))
 			report_bad_irq(irq, desc, action_ret);
 	}
 
@@ -152,11 +152,11 @@
 	}
 
 	desc->irq_count++;
-	if (desc->irq_count < 100000)
+	if (likely(desc->irq_count < 100000))
 		return;
 
 	desc->irq_count = 0;
-	if (desc->irqs_unhandled > 99900) {
+	if (unlikely(desc->irqs_unhandled > 99900)) {
 		/*
 		 * The interrupt is stuck
 		 */
@@ -171,7 +171,7 @@
 	desc->irqs_unhandled = 0;
 }
 
-int noirqdebug;
+int noirqdebug __read_mostly;
 
 int __init noirqdebug_setup(char *str)
 {
diff --git a/kernel/kexec.c b/kernel/kexec.c
index bf39d28..58f0f38 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -902,14 +902,14 @@
  * kexec does not sync, or unmount filesystems so if you need
  * that to happen you need to do that yourself.
  */
-struct kimage *kexec_image = NULL;
-static struct kimage *kexec_crash_image = NULL;
+struct kimage *kexec_image;
+struct kimage *kexec_crash_image;
 /*
  * A home grown binary mutex.
  * Nothing can wait so this mutex is safe to use
  * in interrupt context :)
  */
-static int kexec_lock = 0;
+static int kexec_lock;
 
 asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
 				struct kexec_segment __user *segments,
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 1fbf466..64aab08 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -47,11 +47,17 @@
 
 static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
 static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
+static atomic_t kprobe_count;
 
 DEFINE_MUTEX(kprobe_mutex);		/* Protects kprobe_table */
 DEFINE_SPINLOCK(kretprobe_lock);	/* Protects kretprobe_inst_table */
 static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
 
+static struct notifier_block kprobe_page_fault_nb = {
+	.notifier_call = kprobe_exceptions_notify,
+	.priority = 0x7fffffff /* we need to notified first */
+};
+
 #ifdef __ARCH_WANT_KPROBES_INSN_SLOT
 /*
  * kprobe->ainsn.insn points to the copy of the instruction to be
@@ -368,16 +374,15 @@
 */
 static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
 {
-        struct kprobe *kp;
-
 	if (p->break_handler) {
-		list_for_each_entry_rcu(kp, &old_p->list, list) {
-			if (kp->break_handler)
-				return -EEXIST;
-		}
+		if (old_p->break_handler)
+			return -EEXIST;
 		list_add_tail_rcu(&p->list, &old_p->list);
+		old_p->break_handler = aggr_break_handler;
 	} else
 		list_add_rcu(&p->list, &old_p->list);
+	if (p->post_handler && !old_p->post_handler)
+		old_p->post_handler = aggr_post_handler;
 	return 0;
 }
 
@@ -390,9 +395,11 @@
 	copy_kprobe(p, ap);
 	ap->addr = p->addr;
 	ap->pre_handler = aggr_pre_handler;
-	ap->post_handler = aggr_post_handler;
 	ap->fault_handler = aggr_fault_handler;
-	ap->break_handler = aggr_break_handler;
+	if (p->post_handler)
+		ap->post_handler = aggr_post_handler;
+	if (p->break_handler)
+		ap->break_handler = aggr_break_handler;
 
 	INIT_LIST_HEAD(&ap->list);
 	list_add_rcu(&p->list, &ap->list);
@@ -464,6 +471,8 @@
 	old_p = get_kprobe(p->addr);
 	if (old_p) {
 		ret = register_aggr_kprobe(old_p, p);
+		if (!ret)
+			atomic_inc(&kprobe_count);
 		goto out;
 	}
 
@@ -474,6 +483,10 @@
 	hlist_add_head_rcu(&p->hlist,
 		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
 
+	if (atomic_add_return(1, &kprobe_count) == \
+				(ARCH_INACTIVE_KPROBE_COUNT + 1))
+		register_page_fault_notifier(&kprobe_page_fault_nb);
+
   	arch_arm_kprobe(p);
 
 out:
@@ -536,14 +549,40 @@
 			kfree(old_p);
 		}
 		arch_remove_kprobe(p);
+	} else {
+		mutex_lock(&kprobe_mutex);
+		if (p->break_handler)
+			old_p->break_handler = NULL;
+		if (p->post_handler){
+			list_for_each_entry_rcu(list_p, &old_p->list, list){
+				if (list_p->post_handler){
+					cleanup_p = 2;
+					break;
+				}
+			}
+			if (cleanup_p == 0)
+				old_p->post_handler = NULL;
+		}
+		mutex_unlock(&kprobe_mutex);
 	}
+
+	/* Call unregister_page_fault_notifier()
+	 * if no probes are active
+	 */
+	mutex_lock(&kprobe_mutex);
+	if (atomic_add_return(-1, &kprobe_count) == \
+				ARCH_INACTIVE_KPROBE_COUNT)
+		unregister_page_fault_notifier(&kprobe_page_fault_nb);
+	mutex_unlock(&kprobe_mutex);
+	return;
 }
 
 static struct notifier_block kprobe_exceptions_nb = {
 	.notifier_call = kprobe_exceptions_notify,
-	.priority = 0x7fffffff /* we need to notified first */
+	.priority = 0x7fffffff /* we need to be notified first */
 };
 
+
 int __kprobes register_jprobe(struct jprobe *jp)
 {
 	/* Todo: Verify probepoint is a function entry point */
@@ -652,6 +691,7 @@
 		INIT_HLIST_HEAD(&kprobe_table[i]);
 		INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
 	}
+	atomic_set(&kprobe_count, 0);
 
 	err = arch_init_kprobes();
 	if (!err)
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index f119e09..9e28478 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -14,6 +14,7 @@
 #include <linux/sysfs.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/kexec.h>
 
 #define KERNEL_ATTR_RO(_name) \
 static struct subsys_attribute _name##_attr = __ATTR_RO(_name)
@@ -48,6 +49,20 @@
 KERNEL_ATTR_RW(uevent_helper);
 #endif
 
+#ifdef CONFIG_KEXEC
+static ssize_t kexec_loaded_show(struct subsystem *subsys, char *page)
+{
+	return sprintf(page, "%d\n", !!kexec_image);
+}
+KERNEL_ATTR_RO(kexec_loaded);
+
+static ssize_t kexec_crash_loaded_show(struct subsystem *subsys, char *page)
+{
+	return sprintf(page, "%d\n", !!kexec_crash_image);
+}
+KERNEL_ATTR_RO(kexec_crash_loaded);
+#endif /* CONFIG_KEXEC */
+
 decl_subsys(kernel, NULL, NULL);
 EXPORT_SYMBOL_GPL(kernel_subsys);
 
@@ -56,6 +71,10 @@
 	&uevent_seqnum_attr.attr,
 	&uevent_helper_attr.attr,
 #endif
+#ifdef CONFIG_KEXEC
+	&kexec_loaded_attr.attr,
+	&kexec_crash_loaded_attr.attr,
+#endif
 	NULL
 };
 
diff --git a/kernel/kthread.c b/kernel/kthread.c
index c5f3c66..24be714 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -45,6 +45,13 @@
 static DEFINE_MUTEX(kthread_stop_lock);
 static struct kthread_stop_info kthread_stop_info;
 
+/**
+ * kthread_should_stop - should this kthread return now?
+ *
+ * When someone calls kthread_stop on your kthread, it will be woken
+ * and this will return true.  You should then return, and your return
+ * value will be passed through to kthread_stop().
+ */
 int kthread_should_stop(void)
 {
 	return (kthread_stop_info.k == current);
@@ -122,6 +129,25 @@
 	complete(&create->done);
 }
 
+/**
+ * kthread_create - create a kthread.
+ * @threadfn: the function to run until signal_pending(current).
+ * @data: data ptr for @threadfn.
+ * @namefmt: printf-style name for the thread.
+ *
+ * Description: This helper function creates and names a kernel
+ * thread.  The thread will be stopped: use wake_up_process() to start
+ * it.  See also kthread_run(), kthread_create_on_cpu().
+ *
+ * When woken, the thread will run @threadfn() with @data as its
+ * argument. @threadfn can either call do_exit() directly if it is a
+ * standalone thread for which noone will call kthread_stop(), or
+ * return when 'kthread_should_stop()' is true (which means
+ * kthread_stop() has been called).  The return value should be zero
+ * or a negative error number; it will be passed to kthread_stop().
+ *
+ * Returns a task_struct or ERR_PTR(-ENOMEM).
+ */
 struct task_struct *kthread_create(int (*threadfn)(void *data),
 				   void *data,
 				   const char namefmt[],
@@ -156,6 +182,15 @@
 }
 EXPORT_SYMBOL(kthread_create);
 
+/**
+ * kthread_bind - bind a just-created kthread to a cpu.
+ * @k: thread created by kthread_create().
+ * @cpu: cpu (might not be online, must be possible) for @k to run on.
+ *
+ * Description: This function is equivalent to set_cpus_allowed(),
+ * except that @cpu doesn't need to be online, and the thread must be
+ * stopped (i.e., just returned from kthread_create().
+ */
 void kthread_bind(struct task_struct *k, unsigned int cpu)
 {
 	BUG_ON(k->state != TASK_INTERRUPTIBLE);
@@ -166,12 +201,36 @@
 }
 EXPORT_SYMBOL(kthread_bind);
 
+/**
+ * kthread_stop - stop a thread created by kthread_create().
+ * @k: thread created by kthread_create().
+ *
+ * Sets kthread_should_stop() for @k to return true, wakes it, and
+ * waits for it to exit.  Your threadfn() must not call do_exit()
+ * itself if you use this function!  This can also be called after
+ * kthread_create() instead of calling wake_up_process(): the thread
+ * will exit without calling threadfn().
+ *
+ * Returns the result of threadfn(), or %-EINTR if wake_up_process()
+ * was never called.
+ */
 int kthread_stop(struct task_struct *k)
 {
 	return kthread_stop_sem(k, NULL);
 }
 EXPORT_SYMBOL(kthread_stop);
 
+/**
+ * kthread_stop_sem - stop a thread created by kthread_create().
+ * @k: thread created by kthread_create().
+ * @s: semaphore that @k waits on while idle.
+ *
+ * Does essentially the same thing as kthread_stop() above, but wakes
+ * @k by calling up(@s).
+ *
+ * Returns the result of threadfn(), or %-EINTR if wake_up_process()
+ * was never called.
+ */
 int kthread_stop_sem(struct task_struct *k, struct semaphore *s)
 {
 	int ret;
@@ -210,5 +269,5 @@
 
 	return 0;
 }
-core_initcall(helper_init);
 
+core_initcall(helper_init);
diff --git a/kernel/module.c b/kernel/module.c
index bbe0486..99c022ac 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1,4 +1,4 @@
-/* Rewritten by Rusty Russell, on the backs of many others...
+/*
    Copyright (C) 2002 Richard Henderson
    Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
 
@@ -40,9 +40,11 @@
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/mutex.h>
+#include <linux/unwind.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <asm/cacheflush.h>
+#include <linux/license.h>
 
 #if 0
 #define DEBUGP printk
@@ -120,9 +122,17 @@
 extern const struct kernel_symbol __stop___ksymtab_gpl[];
 extern const struct kernel_symbol __start___ksymtab_gpl_future[];
 extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
+extern const struct kernel_symbol __start___ksymtab_unused[];
+extern const struct kernel_symbol __stop___ksymtab_unused[];
+extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
+extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
+extern const struct kernel_symbol __start___ksymtab_gpl_future[];
+extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
 extern const unsigned long __start___kcrctab[];
 extern const unsigned long __start___kcrctab_gpl[];
 extern const unsigned long __start___kcrctab_gpl_future[];
+extern const unsigned long __start___kcrctab_unused[];
+extern const unsigned long __start___kcrctab_unused_gpl[];
 
 #ifndef CONFIG_MODVERSIONS
 #define symversion(base, idx) NULL
@@ -142,6 +152,17 @@
 	return NULL;
 }
 
+static void printk_unused_warning(const char *name)
+{
+	printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
+		"however this module is using it.\n", name);
+	printk(KERN_WARNING "This symbol will go away in the future.\n");
+	printk(KERN_WARNING "Please evalute if this is the right api to use, "
+		"and if it really is, submit a report the linux kernel "
+		"mailinglist together with submitting your code for "
+		"inclusion.\n");
+}
+
 /* Find a symbol, return value, crc and module which owns it */
 static unsigned long __find_symbol(const char *name,
 				   struct module **owner,
@@ -184,6 +205,25 @@
 		return ks->value;
 	}
 
+	ks = lookup_symbol(name, __start___ksymtab_unused,
+				 __stop___ksymtab_unused);
+	if (ks) {
+		printk_unused_warning(name);
+		*crc = symversion(__start___kcrctab_unused,
+				  (ks - __start___ksymtab_unused));
+		return ks->value;
+	}
+
+	if (gplok)
+		ks = lookup_symbol(name, __start___ksymtab_unused_gpl,
+				 __stop___ksymtab_unused_gpl);
+	if (ks) {
+		printk_unused_warning(name);
+		*crc = symversion(__start___kcrctab_unused_gpl,
+				  (ks - __start___ksymtab_unused_gpl));
+		return ks->value;
+	}
+
 	/* Now try modules. */ 
 	list_for_each_entry(mod, &modules, list) {
 		*owner = mod;
@@ -202,6 +242,23 @@
 				return ks->value;
 			}
 		}
+		ks = lookup_symbol(name, mod->unused_syms, mod->unused_syms + mod->num_unused_syms);
+		if (ks) {
+			printk_unused_warning(name);
+			*crc = symversion(mod->unused_crcs, (ks - mod->unused_syms));
+			return ks->value;
+		}
+
+		if (gplok) {
+			ks = lookup_symbol(name, mod->unused_gpl_syms,
+					   mod->unused_gpl_syms + mod->num_unused_gpl_syms);
+			if (ks) {
+				printk_unused_warning(name);
+				*crc = symversion(mod->unused_gpl_crcs,
+						  (ks - mod->unused_gpl_syms));
+				return ks->value;
+			}
+		}
 		ks = lookup_symbol(name, mod->gpl_future_syms,
 				   (mod->gpl_future_syms +
 				    mod->num_gpl_future_syms));
@@ -1051,6 +1108,8 @@
 	remove_sect_attrs(mod);
 	mod_kobject_remove(mod);
 
+	unwind_remove_table(mod->unwind_info, 0);
+
 	/* Arch-specific cleanup. */
 	module_arch_cleanup(mod);
 
@@ -1248,16 +1307,6 @@
 	}
 }
 
-static inline int license_is_gpl_compatible(const char *license)
-{
-	return (strcmp(license, "GPL") == 0
-		|| strcmp(license, "GPL v2") == 0
-		|| strcmp(license, "GPL and additional rights") == 0
-		|| strcmp(license, "Dual BSD/GPL") == 0
-		|| strcmp(license, "Dual MIT/GPL") == 0
-		|| strcmp(license, "Dual MPL/GPL") == 0);
-}
-
 static void set_license(struct module *mod, const char *license)
 {
 	if (!license)
@@ -1326,7 +1375,7 @@
 	if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
 		return 1;
 	else
-		if (lookup_symbol(name, mod->syms, mod->syms + mod->num_syms))
+		if (mod && lookup_symbol(name, mod->syms, mod->syms + mod->num_syms))
 			return 1;
 		else
 			return 0;
@@ -1409,10 +1458,27 @@
 	Elf_Ehdr *hdr;
 	Elf_Shdr *sechdrs;
 	char *secstrings, *args, *modmagic, *strtab = NULL;
-	unsigned int i, symindex = 0, strindex = 0, setupindex, exindex,
-		exportindex, modindex, obsparmindex, infoindex, gplindex,
-		crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
-		gplfuturecrcindex;
+	unsigned int i;
+	unsigned int symindex = 0;
+	unsigned int strindex = 0;
+	unsigned int setupindex;
+	unsigned int exindex;
+	unsigned int exportindex;
+	unsigned int modindex;
+	unsigned int obsparmindex;
+	unsigned int infoindex;
+	unsigned int gplindex;
+	unsigned int crcindex;
+	unsigned int gplcrcindex;
+	unsigned int versindex;
+	unsigned int pcpuindex;
+	unsigned int gplfutureindex;
+	unsigned int gplfuturecrcindex;
+	unsigned int unwindex = 0;
+	unsigned int unusedindex;
+	unsigned int unusedcrcindex;
+	unsigned int unusedgplindex;
+	unsigned int unusedgplcrcindex;
 	struct module *mod;
 	long err = 0;
 	void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -1493,15 +1559,22 @@
 	exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
 	gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
 	gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
+	unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
+	unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
 	crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
 	gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
 	gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
+	unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");
+	unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");
 	setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
 	exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
 	obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
 	versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
 	infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
 	pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);
+#ifdef ARCH_UNWIND_SECTION_NAME
+	unwindex = find_sec(hdr, sechdrs, secstrings, ARCH_UNWIND_SECTION_NAME);
+#endif
 
 	/* Don't keep modinfo section */
 	sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
@@ -1510,6 +1583,8 @@
 	sechdrs[symindex].sh_flags |= SHF_ALLOC;
 	sechdrs[strindex].sh_flags |= SHF_ALLOC;
 #endif
+	if (unwindex)
+		sechdrs[unwindex].sh_flags |= SHF_ALLOC;
 
 	/* Check module struct version now, before we try to use module. */
 	if (!check_modstruct_version(sechdrs, versindex, mod)) {
@@ -1639,14 +1714,27 @@
 		mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
 	mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
 					sizeof(*mod->gpl_future_syms);
+	mod->num_unused_syms = sechdrs[unusedindex].sh_size /
+					sizeof(*mod->unused_syms);
+	mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
+					sizeof(*mod->unused_gpl_syms);
 	mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
 	if (gplfuturecrcindex)
 		mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
 
+	mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;
+	if (unusedcrcindex)
+		mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
+	mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;
+	if (unusedgplcrcindex)
+		mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr;
+
 #ifdef CONFIG_MODVERSIONS
 	if ((mod->num_syms && !crcindex) || 
 	    (mod->num_gpl_syms && !gplcrcindex) ||
-	    (mod->num_gpl_future_syms && !gplfuturecrcindex)) {
+	    (mod->num_gpl_future_syms && !gplfuturecrcindex) ||
+	    (mod->num_unused_syms && !unusedcrcindex) ||
+	    (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
 		printk(KERN_WARNING "%s: No versions for exported symbols."
 		       " Tainting kernel.\n", mod->name);
 		add_taint(TAINT_FORCED_MODULE);
@@ -1738,6 +1826,11 @@
 		goto arch_cleanup;
 	add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);
 
+	/* Size of section 0 is 0, so this works well if no unwind info. */
+	mod->unwind_info = unwind_add_table(mod,
+	                                    (void *)sechdrs[unwindex].sh_addr,
+	                                    sechdrs[unwindex].sh_size);
+
 	/* Get rid of temporary copy */
 	vfree(hdr);
 
@@ -1836,6 +1929,7 @@
 	mod->state = MODULE_STATE_LIVE;
 	/* Drop initial reference. */
 	module_put(mod);
+	unwind_remove_table(mod->unwind_info, 1);
 	module_free(mod, mod->module_init);
 	mod->module_init = NULL;
 	mod->init_size = 0;
diff --git a/kernel/mutex-debug.c b/kernel/mutex-debug.c
index f4913c3..e38e4ba 100644
--- a/kernel/mutex-debug.c
+++ b/kernel/mutex-debug.c
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/poison.h>
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
@@ -153,13 +154,13 @@
 			continue;
 		count++;
 		cursor = curr->next;
-		debug_spin_lock_restore(&debug_mutex_lock, flags);
+		debug_spin_unlock_restore(&debug_mutex_lock, flags);
 
 		printk("\n#%03d:            ", count);
 		printk_lock(lock, filter ? 0 : 1);
 		goto next;
 	}
-	debug_spin_lock_restore(&debug_mutex_lock, flags);
+	debug_spin_unlock_restore(&debug_mutex_lock, flags);
 	printk("\n");
 }
 
@@ -316,7 +317,7 @@
 			continue;
 		list_del_init(curr);
 		DEBUG_OFF();
-		debug_spin_lock_restore(&debug_mutex_lock, flags);
+		debug_spin_unlock_restore(&debug_mutex_lock, flags);
 
 		printk("BUG: %s/%d, lock held at task exit time!\n",
 			task->comm, task->pid);
@@ -325,7 +326,7 @@
 			printk("exiting task is not even the owner??\n");
 		return;
 	}
-	debug_spin_lock_restore(&debug_mutex_lock, flags);
+	debug_spin_unlock_restore(&debug_mutex_lock, flags);
 }
 
 /*
@@ -352,7 +353,7 @@
 			continue;
 		list_del_init(curr);
 		DEBUG_OFF();
-		debug_spin_lock_restore(&debug_mutex_lock, flags);
+		debug_spin_unlock_restore(&debug_mutex_lock, flags);
 
 		printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n",
 			current->comm, current->pid, lock, from, to);
@@ -362,7 +363,7 @@
 			printk("freeing task is not even the owner??\n");
 		return;
 	}
-	debug_spin_lock_restore(&debug_mutex_lock, flags);
+	debug_spin_unlock_restore(&debug_mutex_lock, flags);
 }
 
 /*
@@ -381,7 +382,7 @@
 
 void debug_mutex_init_waiter(struct mutex_waiter *waiter)
 {
-	memset(waiter, 0x11, sizeof(*waiter));
+	memset(waiter, MUTEX_DEBUG_INIT, sizeof(*waiter));
 	waiter->magic = waiter;
 	INIT_LIST_HEAD(&waiter->list);
 }
@@ -397,7 +398,7 @@
 void debug_mutex_free_waiter(struct mutex_waiter *waiter)
 {
 	DEBUG_WARN_ON(!list_empty(&waiter->list));
-	memset(waiter, 0x22, sizeof(*waiter));
+	memset(waiter, MUTEX_DEBUG_FREE, sizeof(*waiter));
 }
 
 void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
diff --git a/kernel/mutex-debug.h b/kernel/mutex-debug.h
index fd38405..a5196c3 100644
--- a/kernel/mutex-debug.h
+++ b/kernel/mutex-debug.h
@@ -46,21 +46,6 @@
 extern void debug_mutex_unlock(struct mutex *lock);
 extern void debug_mutex_init(struct mutex *lock, const char *name);
 
-#define debug_spin_lock(lock)				\
-	do {						\
-		local_irq_disable();			\
-		if (debug_mutex_on)			\
-			spin_lock(lock);		\
-	} while (0)
-
-#define debug_spin_unlock(lock)				\
-	do {						\
-		if (debug_mutex_on)			\
-			spin_unlock(lock);		\
-		local_irq_enable();			\
-		preempt_check_resched();		\
-	} while (0)
-
 #define debug_spin_lock_save(lock, flags)		\
 	do {						\
 		local_irq_save(flags);			\
@@ -68,7 +53,7 @@
 			spin_lock(lock);		\
 	} while (0)
 
-#define debug_spin_lock_restore(lock, flags)		\
+#define debug_spin_unlock_restore(lock, flags)		\
 	do {						\
 		if (debug_mutex_on)			\
 			spin_unlock(lock);		\
@@ -76,20 +61,20 @@
 		preempt_check_resched();		\
 	} while (0)
 
-#define spin_lock_mutex(lock)				\
+#define spin_lock_mutex(lock, flags)			\
 	do {						\
 		struct mutex *l = container_of(lock, struct mutex, wait_lock); \
 							\
 		DEBUG_WARN_ON(in_interrupt());		\
-		debug_spin_lock(&debug_mutex_lock);	\
+		debug_spin_lock_save(&debug_mutex_lock, flags); \
 		spin_lock(lock);			\
 		DEBUG_WARN_ON(l->magic != l);		\
 	} while (0)
 
-#define spin_unlock_mutex(lock)				\
+#define spin_unlock_mutex(lock, flags)			\
 	do {						\
 		spin_unlock(lock);			\
-		debug_spin_unlock(&debug_mutex_lock);	\
+		debug_spin_unlock_restore(&debug_mutex_lock, flags);	\
 	} while (0)
 
 #define DEBUG_OFF()					\
diff --git a/kernel/mutex.c b/kernel/mutex.c
index 5449b21..7043db2 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -125,10 +125,11 @@
 	struct task_struct *task = current;
 	struct mutex_waiter waiter;
 	unsigned int old_val;
+	unsigned long flags;
 
 	debug_mutex_init_waiter(&waiter);
 
-	spin_lock_mutex(&lock->wait_lock);
+	spin_lock_mutex(&lock->wait_lock, flags);
 
 	debug_mutex_add_waiter(lock, &waiter, task->thread_info, ip);
 
@@ -157,7 +158,7 @@
 		if (unlikely(state == TASK_INTERRUPTIBLE &&
 						signal_pending(task))) {
 			mutex_remove_waiter(lock, &waiter, task->thread_info);
-			spin_unlock_mutex(&lock->wait_lock);
+			spin_unlock_mutex(&lock->wait_lock, flags);
 
 			debug_mutex_free_waiter(&waiter);
 			return -EINTR;
@@ -165,9 +166,9 @@
 		__set_task_state(task, state);
 
 		/* didnt get the lock, go to sleep: */
-		spin_unlock_mutex(&lock->wait_lock);
+		spin_unlock_mutex(&lock->wait_lock, flags);
 		schedule();
-		spin_lock_mutex(&lock->wait_lock);
+		spin_lock_mutex(&lock->wait_lock, flags);
 	}
 
 	/* got the lock - rejoice! */
@@ -178,7 +179,7 @@
 	if (likely(list_empty(&lock->wait_list)))
 		atomic_set(&lock->count, 0);
 
-	spin_unlock_mutex(&lock->wait_lock);
+	spin_unlock_mutex(&lock->wait_lock, flags);
 
 	debug_mutex_free_waiter(&waiter);
 
@@ -203,10 +204,11 @@
 __mutex_unlock_slowpath(atomic_t *lock_count __IP_DECL__)
 {
 	struct mutex *lock = container_of(lock_count, struct mutex, count);
+	unsigned long flags;
 
 	DEBUG_WARN_ON(lock->owner != current_thread_info());
 
-	spin_lock_mutex(&lock->wait_lock);
+	spin_lock_mutex(&lock->wait_lock, flags);
 
 	/*
 	 * some architectures leave the lock unlocked in the fastpath failure
@@ -231,7 +233,7 @@
 
 	debug_mutex_clear_owner(lock);
 
-	spin_unlock_mutex(&lock->wait_lock);
+	spin_unlock_mutex(&lock->wait_lock, flags);
 }
 
 /*
@@ -276,9 +278,10 @@
 static inline int __mutex_trylock_slowpath(atomic_t *lock_count)
 {
 	struct mutex *lock = container_of(lock_count, struct mutex, count);
+	unsigned long flags;
 	int prev;
 
-	spin_lock_mutex(&lock->wait_lock);
+	spin_lock_mutex(&lock->wait_lock, flags);
 
 	prev = atomic_xchg(&lock->count, -1);
 	if (likely(prev == 1))
@@ -287,7 +290,7 @@
 	if (likely(list_empty(&lock->wait_list)))
 		atomic_set(&lock->count, 0);
 
-	spin_unlock_mutex(&lock->wait_lock);
+	spin_unlock_mutex(&lock->wait_lock, flags);
 
 	return prev == 1;
 }
diff --git a/kernel/mutex.h b/kernel/mutex.h
index 00fe84e..0691899 100644
--- a/kernel/mutex.h
+++ b/kernel/mutex.h
@@ -9,8 +9,10 @@
  * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs:
  */
 
-#define spin_lock_mutex(lock)			spin_lock(lock)
-#define spin_unlock_mutex(lock)			spin_unlock(lock)
+#define spin_lock_mutex(lock, flags) \
+		do { spin_lock(lock); (void)(flags); } while (0)
+#define spin_unlock_mutex(lock, flags) \
+		do { spin_unlock(lock); (void)(flags); } while (0)
 #define mutex_remove_waiter(lock, waiter, ti) \
 		__list_del((waiter)->list.prev, (waiter)->list.next)
 
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index ce0dfb8..857b4fa 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -36,6 +36,24 @@
 	code. This is helpful when debugging and reporting various PM bugs, 
 	like suspend support.
 
+config PM_TRACE
+	bool "Suspend/resume event tracing"
+	depends on PM && PM_DEBUG && X86_32 && EXPERIMENTAL
+	default n
+	---help---
+	This enables some cheesy code to save the last PM event point in the
+	RTC across reboots, so that you can debug a machine that just hangs
+	during suspend (or more commonly, during resume).
+
+	To use this debugging feature you should attempt to suspend the machine,
+	then reboot it, then run
+
+		dmesg -s 1000000 | grep 'hash matches'
+
+	CAUTION: this option will cause your machine's real-time clock to be
+	set to an invalid time after a resume.
+
+
 config SOFTWARE_SUSPEND
 	bool "Software Suspend"
 	depends on PM && SWAP && (X86 && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 81d4d98..e13e740 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -231,7 +231,7 @@
 late_initcall(software_resume);
 
 
-static char * pm_disk_modes[] = {
+static const char * const pm_disk_modes[] = {
 	[PM_DISK_FIRMWARE]	= "firmware",
 	[PM_DISK_PLATFORM]	= "platform",
 	[PM_DISK_SHUTDOWN]	= "shutdown",
diff --git a/kernel/power/main.c b/kernel/power/main.c
index a6d9ef4..6d295c7 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -15,7 +15,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/pm.h>
-
+#include <linux/console.h>
 
 #include "power.h"
 
@@ -86,6 +86,7 @@
 			goto Thaw;
 	}
 
+	suspend_console();
 	if ((error = device_suspend(PMSG_SUSPEND))) {
 		printk(KERN_ERR "Some devices failed to suspend\n");
 		goto Finish;
@@ -133,6 +134,7 @@
 static void suspend_finish(suspend_state_t state)
 {
 	device_resume();
+	resume_console();
 	thaw_processes();
 	enable_nonboot_cpus();
 	if (pm_ops && pm_ops->finish)
@@ -143,7 +145,7 @@
 
 
 
-static char *pm_states[PM_SUSPEND_MAX] = {
+static const char * const pm_states[PM_SUSPEND_MAX] = {
 	[PM_SUSPEND_STANDBY]	= "standby",
 	[PM_SUSPEND_MEM]	= "mem",
 #ifdef CONFIG_SOFTWARE_SUSPEND
@@ -260,7 +262,7 @@
 static ssize_t state_store(struct subsystem * subsys, const char * buf, size_t n)
 {
 	suspend_state_t state = PM_SUSPEND_STANDBY;
-	char ** s;
+	const char * const *s;
 	char *p;
 	int error;
 	int len;
diff --git a/kernel/power/power.h b/kernel/power/power.h
index f06f12f..57a7929 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -55,7 +55,7 @@
 	unsigned int	page;
 	unsigned int	page_offset;
 	unsigned int	prev;
-	struct pbe	*pbe;
+	struct pbe	*pbe, *last_pbe;
 	void		*buffer;
 	unsigned int	buf_offset;
 };
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index 3eeedbb..24c96f3 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -150,6 +150,10 @@
 	}
 	return 0;
 }
+#else
+static inline unsigned int count_highmem_pages(void) {return 0;}
+static inline int save_highmem(void) {return 0;}
+static inline int restore_highmem(void) {return 0;}
 #endif
 
 static int pfn_is_nosave(unsigned long pfn)
@@ -293,62 +297,29 @@
 	}
 }
 
-/**
- *	On resume it is necessary to trace and eventually free the unsafe
- *	pages that have been allocated, because they are needed for I/O
- *	(on x86-64 we likely will "eat" these pages once again while
- *	creating the temporary page translation tables)
- */
-
-struct eaten_page {
-	struct eaten_page *next;
-	char padding[PAGE_SIZE - sizeof(void *)];
-};
-
-static struct eaten_page *eaten_pages = NULL;
-
-static void release_eaten_pages(void)
-{
-	struct eaten_page *p, *q;
-
-	p = eaten_pages;
-	while (p) {
-		q = p->next;
-		/* We don't want swsusp_free() to free this page again */
-		ClearPageNosave(virt_to_page(p));
-		free_page((unsigned long)p);
-		p = q;
-	}
-	eaten_pages = NULL;
-}
+static unsigned int unsafe_pages;
 
 /**
  *	@safe_needed - on resume, for storing the PBE list and the image,
  *	we can only use memory pages that do not conflict with the pages
- *	which had been used before suspend.
+ *	used before suspend.
  *
  *	The unsafe pages are marked with the PG_nosave_free flag
- *
- *	Allocated but unusable (ie eaten) memory pages should be marked
- *	so that swsusp_free() can release them
+ *	and we count them using unsafe_pages
  */
 
 static inline void *alloc_image_page(gfp_t gfp_mask, int safe_needed)
 {
 	void *res;
 
+	res = (void *)get_zeroed_page(gfp_mask);
 	if (safe_needed)
-		do {
+		while (res && PageNosaveFree(virt_to_page(res))) {
+			/* The page is unsafe, mark it for swsusp_free() */
+			SetPageNosave(virt_to_page(res));
+			unsafe_pages++;
 			res = (void *)get_zeroed_page(gfp_mask);
-			if (res && PageNosaveFree(virt_to_page(res))) {
-				/* This is for swsusp_free() */
-				SetPageNosave(virt_to_page(res));
-				((struct eaten_page *)res)->next = eaten_pages;
-				eaten_pages = res;
-			}
-		} while (res && PageNosaveFree(virt_to_page(res)));
-	else
-		res = (void *)get_zeroed_page(gfp_mask);
+		}
 	if (res) {
 		SetPageNosave(virt_to_page(res));
 		SetPageNosaveFree(virt_to_page(res));
@@ -374,7 +345,8 @@
  *	On each page we set up a list of struct_pbe elements.
  */
 
-struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed)
+static struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask,
+				 int safe_needed)
 {
 	unsigned int num;
 	struct pbe *pblist, *pbe;
@@ -642,6 +614,8 @@
 			return -EFAULT;
 	}
 
+	unsafe_pages = 0;
+
 	return 0;
 }
 
@@ -719,42 +693,99 @@
 }
 
 /**
- *	create_image - use metadata contained in the PBE list
+ *	prepare_image - use metadata contained in the PBE list
  *	pointed to by pagedir_nosave to mark the pages that will
  *	be overwritten in the process of restoring the system
- *	memory state from the image and allocate memory for
- *	the image avoiding these pages
+ *	memory state from the image ("unsafe" pages) and allocate
+ *	memory for the image
+ *
+ *	The idea is to allocate the PBE list first and then
+ *	allocate as many pages as it's needed for the image data,
+ *	but not to assign these pages to the PBEs initially.
+ *	Instead, we just mark them as allocated and create a list
+ *	of "safe" which will be used later
  */
 
-static int create_image(struct snapshot_handle *handle)
+struct safe_page {
+	struct safe_page *next;
+	char padding[PAGE_SIZE - sizeof(void *)];
+};
+
+static struct safe_page *safe_pages;
+
+static int prepare_image(struct snapshot_handle *handle)
 {
 	int error = 0;
-	struct pbe *p, *pblist;
+	unsigned int nr_pages = nr_copy_pages;
+	struct pbe *p, *pblist = NULL;
 
 	p = pagedir_nosave;
 	error = mark_unsafe_pages(p);
 	if (!error) {
-		pblist = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
+		pblist = alloc_pagedir(nr_pages, GFP_ATOMIC, 1);
 		if (pblist)
 			copy_page_backup_list(pblist, p);
 		free_pagedir(p, 0);
 		if (!pblist)
 			error = -ENOMEM;
 	}
-	if (!error)
-		error = alloc_data_pages(pblist, GFP_ATOMIC, 1);
+	safe_pages = NULL;
+	if (!error && nr_pages > unsafe_pages) {
+		nr_pages -= unsafe_pages;
+		while (nr_pages--) {
+			struct safe_page *ptr;
+
+			ptr = (struct safe_page *)get_zeroed_page(GFP_ATOMIC);
+			if (!ptr) {
+				error = -ENOMEM;
+				break;
+			}
+			if (!PageNosaveFree(virt_to_page(ptr))) {
+				/* The page is "safe", add it to the list */
+				ptr->next = safe_pages;
+				safe_pages = ptr;
+			}
+			/* Mark the page as allocated */
+			SetPageNosave(virt_to_page(ptr));
+			SetPageNosaveFree(virt_to_page(ptr));
+		}
+	}
 	if (!error) {
-		release_eaten_pages();
 		pagedir_nosave = pblist;
 	} else {
-		pagedir_nosave = NULL;
 		handle->pbe = NULL;
-		nr_copy_pages = 0;
-		nr_meta_pages = 0;
+		swsusp_free();
 	}
 	return error;
 }
 
+static void *get_buffer(struct snapshot_handle *handle)
+{
+	struct pbe *pbe = handle->pbe, *last = handle->last_pbe;
+	struct page *page = virt_to_page(pbe->orig_address);
+
+	if (PageNosave(page) && PageNosaveFree(page)) {
+		/*
+		 * We have allocated the "original" page frame and we can
+		 * use it directly to store the read page
+		 */
+		pbe->address = 0;
+		if (last && last->next)
+			last->next = NULL;
+		return (void *)pbe->orig_address;
+	}
+	/*
+	 * The "original" page frame has not been allocated and we have to
+	 * use a "safe" page frame to store the read page
+	 */
+	pbe->address = (unsigned long)safe_pages;
+	safe_pages = safe_pages->next;
+	if (last)
+		last->next = pbe;
+	handle->last_pbe = pbe;
+	return (void *)pbe->address;
+}
+
 /**
  *	snapshot_write_next - used for writing the system memory snapshot.
  *
@@ -799,15 +830,16 @@
 		} else if (handle->prev <= nr_meta_pages) {
 			handle->pbe = unpack_orig_addresses(buffer, handle->pbe);
 			if (!handle->pbe) {
-				error = create_image(handle);
+				error = prepare_image(handle);
 				if (error)
 					return error;
 				handle->pbe = pagedir_nosave;
-				handle->buffer = (void *)handle->pbe->address;
+				handle->last_pbe = NULL;
+				handle->buffer = get_buffer(handle);
 			}
 		} else {
 			handle->pbe = handle->pbe->next;
-			handle->buffer = (void *)handle->pbe->address;
+			handle->buffer = get_buffer(handle);
 		}
 		handle->prev = handle->page;
 	}
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index c4016cb..17f669c 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -67,9 +67,9 @@
 int save_highmem(void);
 int restore_highmem(void);
 #else
-static int save_highmem(void) { return 0; }
-static int restore_highmem(void) { return 0; }
-static unsigned int count_highmem_pages(void) { return 0; }
+static inline int save_highmem(void) { return 0; }
+static inline int restore_highmem(void) { return 0; }
+static inline unsigned int count_highmem_pages(void) { return 0; }
 #endif
 
 /**
@@ -175,6 +175,12 @@
  */
 
 #define SHRINK_BITE	10000
+static inline unsigned long __shrink_memory(long tmp)
+{
+	if (tmp > SHRINK_BITE)
+		tmp = SHRINK_BITE;
+	return shrink_all_memory(tmp);
+}
 
 int swsusp_shrink_memory(void)
 {
@@ -192,15 +198,17 @@
 			PAGES_FOR_IO;
 		tmp = size;
 		for_each_zone (zone)
-			if (!is_highmem(zone))
+			if (!is_highmem(zone) && populated_zone(zone)) {
 				tmp -= zone->free_pages;
+				tmp += zone->lowmem_reserve[ZONE_NORMAL];
+			}
 		if (tmp > 0) {
-			tmp = shrink_all_memory(SHRINK_BITE);
+			tmp = __shrink_memory(tmp);
 			if (!tmp)
 				return -ENOMEM;
 			pages += tmp;
 		} else if (size > image_size / PAGE_SIZE) {
-			tmp = shrink_all_memory(SHRINK_BITE);
+			tmp = __shrink_memory(size - (image_size / PAGE_SIZE));
 			pages += tmp;
 		}
 		printk("\b%c", p[i++%4]);
diff --git a/kernel/printk.c b/kernel/printk.c
index c056f33..95b7fe1 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -24,6 +24,7 @@
 #include <linux/console.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/interrupt.h>			/* For in_interrupt() */
 #include <linux/config.h>
 #include <linux/delay.h>
@@ -67,6 +68,7 @@
  * driver system.
  */
 static DECLARE_MUTEX(console_sem);
+static DECLARE_MUTEX(secondary_console_sem);
 struct console *console_drivers;
 /*
  * This is used for debugging the mess that is the VT code by
@@ -76,7 +78,7 @@
  * path in the console code where we end up in places I want
  * locked without the console sempahore held
  */
-static int console_locked;
+static int console_locked, console_suspended;
 
 /*
  * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
@@ -326,7 +328,9 @@
 	struct console *con;
 
 	for (con = console_drivers; con; con = con->next) {
-		if ((con->flags & CON_ENABLED) && con->write)
+		if ((con->flags & CON_ENABLED) && con->write &&
+				(cpu_online(smp_processor_id()) ||
+				(con->flags & CON_ANYTIME)))
 			con->write(con, &LOG_BUF(start), end - start);
 	}
 }
@@ -436,6 +440,7 @@
 #else
 static int printk_time = 0;
 #endif
+module_param(printk_time, int, S_IRUGO | S_IWUSR);
 
 static int __init printk_time_setup(char *str)
 {
@@ -452,6 +457,18 @@
 	return sched_clock();
 }
 
+/* Check if we have any console registered that can be called early in boot. */
+static int have_callable_console(void)
+{
+	struct console *con;
+
+	for (con = console_drivers; con; con = con->next)
+		if (con->flags & CON_ANYTIME)
+			return 1;
+
+	return 0;
+}
+
 /**
  * printk - print a kernel message
  * @fmt: format string
@@ -565,27 +582,29 @@
 			log_level_unknown = 1;
 	}
 
-	if (!cpu_online(smp_processor_id())) {
-		/*
-		 * Some console drivers may assume that per-cpu resources have
-		 * been allocated.  So don't allow them to be called by this
-		 * CPU until it is officially up.  We shouldn't be calling into
-		 * random console drivers on a CPU which doesn't exist yet..
-		 */
-		printk_cpu = UINT_MAX;
-		spin_unlock_irqrestore(&logbuf_lock, flags);
-		goto out;
-	}
 	if (!down_trylock(&console_sem)) {
-		console_locked = 1;
 		/*
-		 * We own the drivers.  We can drop the spinlock and let
-		 * release_console_sem() print the text
+		 * We own the drivers.  We can drop the spinlock and
+		 * let release_console_sem() print the text, maybe ...
 		 */
+		console_locked = 1;
 		printk_cpu = UINT_MAX;
 		spin_unlock_irqrestore(&logbuf_lock, flags);
-		console_may_schedule = 0;
-		release_console_sem();
+
+		/*
+		 * Console drivers may assume that per-cpu resources have
+		 * been allocated. So unless they're explicitly marked as
+		 * being able to cope (CON_ANYTIME) don't call them until
+		 * this CPU is officially up.
+		 */
+		if (cpu_online(smp_processor_id()) || have_callable_console()) {
+			console_may_schedule = 0;
+			release_console_sem();
+		} else {
+			/* Release by hand to avoid flushing the buffer. */
+			console_locked = 0;
+			up(&console_sem);
+		}
 	} else {
 		/*
 		 * Someone else owns the drivers.  We drop the spinlock, which
@@ -595,7 +614,7 @@
 		printk_cpu = UINT_MAX;
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 	}
-out:
+
 	preempt_enable();
 	return printed_len;
 }
@@ -698,6 +717,23 @@
 }
 
 /**
+ * suspend_console - suspend the console subsystem
+ *
+ * This disables printk() while we go into suspend states
+ */
+void suspend_console(void)
+{
+	acquire_console_sem();
+	console_suspended = 1;
+}
+
+void resume_console(void)
+{
+	console_suspended = 0;
+	release_console_sem();
+}
+
+/**
  * acquire_console_sem - lock the console system for exclusive use.
  *
  * Acquires a semaphore which guarantees that the caller has
@@ -708,6 +744,10 @@
 void acquire_console_sem(void)
 {
 	BUG_ON(in_interrupt());
+	if (console_suspended) {
+		down(&secondary_console_sem);
+		return;
+	}
 	down(&console_sem);
 	console_locked = 1;
 	console_may_schedule = 1;
@@ -750,6 +790,10 @@
 	unsigned long _con_start, _log_end;
 	unsigned long wake_klogd = 0;
 
+	if (console_suspended) {
+		up(&secondary_console_sem);
+		return;
+	}
 	for ( ; ; ) {
 		spin_lock_irqsave(&logbuf_lock, flags);
 		wake_klogd |= log_start - log_end;
diff --git a/kernel/profile.c b/kernel/profile.c
index 68afe12..5a730fd 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -299,7 +299,7 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static int profile_cpu_callback(struct notifier_block *info,
+static int __devinit profile_cpu_callback(struct notifier_block *info,
 					unsigned long action, void *__cpu)
 {
 	int node, cpu = (unsigned long)__cpu;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 921c22a..335c5b9 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -120,8 +120,18 @@
 
 static int may_attach(struct task_struct *task)
 {
-	if (!task->mm)
-		return -EPERM;
+	/* May we inspect the given task?
+	 * This check is used both for attaching with ptrace
+	 * and for allowing access to sensitive information in /proc.
+	 *
+	 * ptrace_attach denies several cases that /proc allows
+	 * because setting up the necessary parent/child relationship
+	 * or halting the specified task is impossible.
+	 */
+	int dumpable = 0;
+	/* Don't let security modules deny introspection */
+	if (task == current)
+		return 0;
 	if (((current->uid != task->euid) ||
 	     (current->uid != task->suid) ||
 	     (current->uid != task->uid) ||
@@ -130,7 +140,9 @@
 	     (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
 		return -EPERM;
 	smp_rmb();
-	if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+	if (task->mm)
+		dumpable = task->mm->dumpable;
+	if (!dumpable && !capable(CAP_SYS_PTRACE))
 		return -EPERM;
 
 	return security_ptrace(current, task);
@@ -176,6 +188,8 @@
 		goto repeat;
 	}
 
+	if (!task->mm)
+		goto bad;
 	/* the same process cannot be attached many times */
 	if (task->ptrace & PT_PTRACED)
 		goto bad;
@@ -200,7 +214,7 @@
 	return retval;
 }
 
-void __ptrace_detach(struct task_struct *child, unsigned int data)
+static inline void __ptrace_detach(struct task_struct *child, unsigned int data)
 {
 	child->exit_code = data;
 	/* .. re-parent .. */
@@ -219,6 +233,7 @@
 	ptrace_disable(child);
 
 	write_lock_irq(&tasklist_lock);
+	/* protect against de_thread()->release_task() */
 	if (child->ptrace)
 		__ptrace_detach(child, data);
 	write_unlock_irq(&tasklist_lock);
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index 2058f88..f464f5a 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -182,6 +182,15 @@
 	return rcu_ctrlblk.completed;
 }
 
+/*
+ * Return the number of RCU batches processed thus far.  Useful
+ * for debug and statistics.
+ */
+long rcu_batches_completed_bh(void)
+{
+	return rcu_bh_ctrlblk.completed;
+}
+
 static void rcu_barrier_callback(struct rcu_head *notused)
 {
 	if (atomic_dec_and_test(&rcu_barrier_cpu_count))
@@ -539,7 +548,7 @@
 	tasklet_init(&per_cpu(rcu_tasklet, cpu), rcu_process_callbacks, 0UL);
 }
 
-static int rcu_cpu_notify(struct notifier_block *self,
+static int __devinit rcu_cpu_notify(struct notifier_block *self,
 				unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -556,7 +565,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block rcu_nb = {
+static struct notifier_block __devinitdata rcu_nb = {
 	.notifier_call	= rcu_cpu_notify,
 };
 
@@ -612,14 +621,6 @@
 	wait_for_completion(&rcu.completion);
 }
 
-/*
- * Deprecated, use synchronize_rcu() or synchronize_sched() instead.
- */
-void synchronize_kernel(void)
-{
-	synchronize_rcu();
-}
-
 module_param(blimit, int, 0);
 module_param(qhimark, int, 0);
 module_param(qlowmark, int, 0);
@@ -627,7 +628,7 @@
 module_param(rsinterval, int, 0);
 #endif
 EXPORT_SYMBOL_GPL(rcu_batches_completed);
-EXPORT_SYMBOL_GPL_FUTURE(call_rcu);	/* WARNING: GPL-only in April 2006. */
-EXPORT_SYMBOL_GPL_FUTURE(call_rcu_bh);	/* WARNING: GPL-only in April 2006. */
+EXPORT_SYMBOL_GPL(rcu_batches_completed_bh);
+EXPORT_SYMBOL_GPL(call_rcu);
+EXPORT_SYMBOL_GPL(call_rcu_bh);
 EXPORT_SYMBOL_GPL(synchronize_rcu);
-EXPORT_SYMBOL_GPL_FUTURE(synchronize_kernel); /* WARNING: GPL-only in April 2006. */
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 8154e75..4d1c3d2 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -1,5 +1,5 @@
 /*
- * Read-Copy Update /proc-based torture test facility
+ * Read-Copy Update module-based torture test facility
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -53,6 +53,7 @@
 static int verbose;		/* Print more debug info. */
 static int test_no_idle_hz;	/* Test RCU's support for tickless idle CPUs. */
 static int shuffle_interval = 5; /* Interval between shuffles (in sec)*/
+static char *torture_type = "rcu"; /* What to torture. */
 
 module_param(nreaders, int, 0);
 MODULE_PARM_DESC(nreaders, "Number of RCU reader threads");
@@ -64,13 +65,16 @@
 MODULE_PARM_DESC(test_no_idle_hz, "Test support for tickless idle CPUs");
 module_param(shuffle_interval, int, 0);
 MODULE_PARM_DESC(shuffle_interval, "Number of seconds between shuffles");
-#define TORTURE_FLAG "rcutorture: "
+module_param(torture_type, charp, 0);
+MODULE_PARM_DESC(torture_type, "Type of RCU to torture (rcu, rcu_bh)");
+
+#define TORTURE_FLAG "-torture:"
 #define PRINTK_STRING(s) \
-	do { printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0)
+	do { printk(KERN_ALERT "%s" TORTURE_FLAG s "\n", torture_type); } while (0)
 #define VERBOSE_PRINTK_STRING(s) \
-	do { if (verbose) printk(KERN_ALERT TORTURE_FLAG s "\n"); } while (0)
+	do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG s "\n", torture_type); } while (0)
 #define VERBOSE_PRINTK_ERRSTRING(s) \
-	do { if (verbose) printk(KERN_ALERT TORTURE_FLAG "!!! " s "\n"); } while (0)
+	do { if (verbose) printk(KERN_ALERT "%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
 
 static char printk_buf[4096];
 
@@ -139,28 +143,6 @@
 	spin_unlock_bh(&rcu_torture_lock);
 }
 
-static void
-rcu_torture_cb(struct rcu_head *p)
-{
-	int i;
-	struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu);
-
-	if (fullstop) {
-		/* Test is ending, just drop callbacks on the floor. */
-		/* The next initialization will pick up the pieces. */
-		return;
-	}
-	i = rp->rtort_pipe_count;
-	if (i > RCU_TORTURE_PIPE_LEN)
-		i = RCU_TORTURE_PIPE_LEN;
-	atomic_inc(&rcu_torture_wcount[i]);
-	if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
-		rp->rtort_mbtest = 0;
-		rcu_torture_free(rp);
-	} else
-		call_rcu(p, rcu_torture_cb);
-}
-
 struct rcu_random_state {
 	unsigned long rrs_state;
 	unsigned long rrs_count;
@@ -191,6 +173,119 @@
 }
 
 /*
+ * Operations vector for selecting different types of tests.
+ */
+
+struct rcu_torture_ops {
+	void (*init)(void);
+	void (*cleanup)(void);
+	int (*readlock)(void);
+	void (*readunlock)(int idx);
+	int (*completed)(void);
+	void (*deferredfree)(struct rcu_torture *p);
+	int (*stats)(char *page);
+	char *name;
+};
+static struct rcu_torture_ops *cur_ops = NULL;
+
+/*
+ * Definitions for rcu torture testing.
+ */
+
+static int rcu_torture_read_lock(void)
+{
+	rcu_read_lock();
+	return 0;
+}
+
+static void rcu_torture_read_unlock(int idx)
+{
+	rcu_read_unlock();
+}
+
+static int rcu_torture_completed(void)
+{
+	return rcu_batches_completed();
+}
+
+static void
+rcu_torture_cb(struct rcu_head *p)
+{
+	int i;
+	struct rcu_torture *rp = container_of(p, struct rcu_torture, rtort_rcu);
+
+	if (fullstop) {
+		/* Test is ending, just drop callbacks on the floor. */
+		/* The next initialization will pick up the pieces. */
+		return;
+	}
+	i = rp->rtort_pipe_count;
+	if (i > RCU_TORTURE_PIPE_LEN)
+		i = RCU_TORTURE_PIPE_LEN;
+	atomic_inc(&rcu_torture_wcount[i]);
+	if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
+		rp->rtort_mbtest = 0;
+		rcu_torture_free(rp);
+	} else
+		cur_ops->deferredfree(rp);
+}
+
+static void rcu_torture_deferred_free(struct rcu_torture *p)
+{
+	call_rcu(&p->rtort_rcu, rcu_torture_cb);
+}
+
+static struct rcu_torture_ops rcu_ops = {
+	.init = NULL,
+	.cleanup = NULL,
+	.readlock = rcu_torture_read_lock,
+	.readunlock = rcu_torture_read_unlock,
+	.completed = rcu_torture_completed,
+	.deferredfree = rcu_torture_deferred_free,
+	.stats = NULL,
+	.name = "rcu"
+};
+
+/*
+ * Definitions for rcu_bh torture testing.
+ */
+
+static int rcu_bh_torture_read_lock(void)
+{
+	rcu_read_lock_bh();
+	return 0;
+}
+
+static void rcu_bh_torture_read_unlock(int idx)
+{
+	rcu_read_unlock_bh();
+}
+
+static int rcu_bh_torture_completed(void)
+{
+	return rcu_batches_completed_bh();
+}
+
+static void rcu_bh_torture_deferred_free(struct rcu_torture *p)
+{
+	call_rcu_bh(&p->rtort_rcu, rcu_torture_cb);
+}
+
+static struct rcu_torture_ops rcu_bh_ops = {
+	.init = NULL,
+	.cleanup = NULL,
+	.readlock = rcu_bh_torture_read_lock,
+	.readunlock = rcu_bh_torture_read_unlock,
+	.completed = rcu_bh_torture_completed,
+	.deferredfree = rcu_bh_torture_deferred_free,
+	.stats = NULL,
+	.name = "rcu_bh"
+};
+
+static struct rcu_torture_ops *torture_ops[] =
+	{ &rcu_ops, &rcu_bh_ops, NULL };
+
+/*
  * RCU torture writer kthread.  Repeatedly substitutes a new structure
  * for that pointed to by rcu_torture_current, freeing the old structure
  * after a series of grace periods (the "pipeline").
@@ -209,8 +304,6 @@
 
 	do {
 		schedule_timeout_uninterruptible(1);
-		if (rcu_batches_completed() == oldbatch)
-			continue;
 		if ((rp = rcu_torture_alloc()) == NULL)
 			continue;
 		rp->rtort_pipe_count = 0;
@@ -225,10 +318,10 @@
 				i = RCU_TORTURE_PIPE_LEN;
 			atomic_inc(&rcu_torture_wcount[i]);
 			old_rp->rtort_pipe_count++;
-			call_rcu(&old_rp->rtort_rcu, rcu_torture_cb);
+			cur_ops->deferredfree(old_rp);
 		}
 		rcu_torture_current_version++;
-		oldbatch = rcu_batches_completed();
+		oldbatch = cur_ops->completed();
 	} while (!kthread_should_stop() && !fullstop);
 	VERBOSE_PRINTK_STRING("rcu_torture_writer task stopping");
 	while (!kthread_should_stop())
@@ -246,6 +339,7 @@
 rcu_torture_reader(void *arg)
 {
 	int completed;
+	int idx;
 	DEFINE_RCU_RANDOM(rand);
 	struct rcu_torture *p;
 	int pipe_count;
@@ -254,12 +348,12 @@
 	set_user_nice(current, 19);
 
 	do {
-		rcu_read_lock();
-		completed = rcu_batches_completed();
+		idx = cur_ops->readlock();
+		completed = cur_ops->completed();
 		p = rcu_dereference(rcu_torture_current);
 		if (p == NULL) {
 			/* Wait for rcu_torture_writer to get underway */
-			rcu_read_unlock();
+			cur_ops->readunlock(idx);
 			schedule_timeout_interruptible(HZ);
 			continue;
 		}
@@ -273,14 +367,14 @@
 			pipe_count = RCU_TORTURE_PIPE_LEN;
 		}
 		++__get_cpu_var(rcu_torture_count)[pipe_count];
-		completed = rcu_batches_completed() - completed;
+		completed = cur_ops->completed() - completed;
 		if (completed > RCU_TORTURE_PIPE_LEN) {
 			/* Should not happen, but... */
 			completed = RCU_TORTURE_PIPE_LEN;
 		}
 		++__get_cpu_var(rcu_torture_batch)[completed];
 		preempt_enable();
-		rcu_read_unlock();
+		cur_ops->readunlock(idx);
 		schedule();
 	} while (!kthread_should_stop() && !fullstop);
 	VERBOSE_PRINTK_STRING("rcu_torture_reader task stopping");
@@ -311,7 +405,7 @@
 		if (pipesummary[i] != 0)
 			break;
 	}
-	cnt += sprintf(&page[cnt], "rcutorture: ");
+	cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
 	cnt += sprintf(&page[cnt],
 		       "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d "
 		       "rtmbe: %d",
@@ -324,7 +418,7 @@
 		       atomic_read(&n_rcu_torture_mberror));
 	if (atomic_read(&n_rcu_torture_mberror) != 0)
 		cnt += sprintf(&page[cnt], " !!!");
-	cnt += sprintf(&page[cnt], "\nrcutorture: ");
+	cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
 	if (i > 1) {
 		cnt += sprintf(&page[cnt], "!!! ");
 		atomic_inc(&n_rcu_torture_error);
@@ -332,17 +426,19 @@
 	cnt += sprintf(&page[cnt], "Reader Pipe: ");
 	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
 		cnt += sprintf(&page[cnt], " %ld", pipesummary[i]);
-	cnt += sprintf(&page[cnt], "\nrcutorture: ");
+	cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
 	cnt += sprintf(&page[cnt], "Reader Batch: ");
-	for (i = 0; i < RCU_TORTURE_PIPE_LEN; i++)
+	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
 		cnt += sprintf(&page[cnt], " %ld", batchsummary[i]);
-	cnt += sprintf(&page[cnt], "\nrcutorture: ");
+	cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
 	cnt += sprintf(&page[cnt], "Free-Block Circulation: ");
 	for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
 		cnt += sprintf(&page[cnt], " %d",
 			       atomic_read(&rcu_torture_wcount[i]));
 	}
 	cnt += sprintf(&page[cnt], "\n");
+	if (cur_ops->stats != NULL)
+		cnt += cur_ops->stats(&page[cnt]);
 	return cnt;
 }
 
@@ -444,11 +540,11 @@
 static inline void
 rcu_torture_print_module_parms(char *tag)
 {
-	printk(KERN_ALERT TORTURE_FLAG "--- %s: nreaders=%d "
+	printk(KERN_ALERT "%s" TORTURE_FLAG "--- %s: nreaders=%d "
 		"stat_interval=%d verbose=%d test_no_idle_hz=%d "
 		"shuffle_interval = %d\n",
-		tag, nrealreaders, stat_interval, verbose, test_no_idle_hz,
-		shuffle_interval);
+		torture_type, tag, nrealreaders, stat_interval, verbose,
+		test_no_idle_hz, shuffle_interval);
 }
 
 static void
@@ -493,6 +589,9 @@
 	rcu_barrier();
 
 	rcu_torture_stats_print();  /* -After- the stats thread is stopped! */
+
+	if (cur_ops->cleanup != NULL)
+		cur_ops->cleanup();
 	if (atomic_read(&n_rcu_torture_error))
 		rcu_torture_print_module_parms("End of test: FAILURE");
 	else
@@ -508,6 +607,20 @@
 
 	/* Process args and tell the world that the torturer is on the job. */
 
+	for (i = 0; cur_ops = torture_ops[i], cur_ops != NULL; i++) {
+		cur_ops = torture_ops[i];
+		if (strcmp(torture_type, cur_ops->name) == 0) {
+			break;
+		}
+	}
+	if (cur_ops == NULL) {
+		printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n",
+		       torture_type);
+		return (-EINVAL);
+	}
+	if (cur_ops->init != NULL)
+		cur_ops->init(); /* no "goto unwind" prior to this point!!! */
+
 	if (nreaders >= 0)
 		nrealreaders = nreaders;
 	else
diff --git a/kernel/resource.c b/kernel/resource.c
index e3080fc..2404f9b 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -232,6 +232,44 @@
 
 EXPORT_SYMBOL(release_resource);
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+/*
+ * Finds the lowest memory reosurce exists within [res->start.res->end)
+ * the caller must specify res->start, res->end, res->flags.
+ * If found, returns 0, res is overwritten, if not found, returns -1.
+ */
+int find_next_system_ram(struct resource *res)
+{
+	resource_size_t start, end;
+	struct resource *p;
+
+	BUG_ON(!res);
+
+	start = res->start;
+	end = res->end;
+
+	read_lock(&resource_lock);
+	for (p = iomem_resource.child; p ; p = p->sibling) {
+		/* system ram is just marked as IORESOURCE_MEM */
+		if (p->flags != res->flags)
+			continue;
+		if (p->start > end) {
+			p = NULL;
+			break;
+		}
+		if (p->start >= start)
+			break;
+	}
+	read_unlock(&resource_lock);
+	if (!p)
+		return -1;
+	/* copy data */
+	res->start = p->start;
+	res->end = p->end;
+	return 0;
+}
+#endif
+
 /*
  * Find empty slot in the resource tree given range and alignment.
  */
diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c
new file mode 100644
index 0000000..4aa8a2c9
--- /dev/null
+++ b/kernel/rtmutex-debug.c
@@ -0,0 +1,513 @@
+/*
+ * RT-Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This code is based on the rt.c implementation in the preempt-rt tree.
+ * Portions of said code are
+ *
+ *  Copyright (C) 2004  LynuxWorks, Inc., Igor Manyilov, Bill Huey
+ *  Copyright (C) 2006  Esben Nielsen
+ *  Copyright (C) 2006  Kihon Technologies Inc.,
+ *			Steven Rostedt <rostedt@goodmis.org>
+ *
+ * See rt.c in preempt-rt for proper credits and further information
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/kallsyms.h>
+#include <linux/syscalls.h>
+#include <linux/interrupt.h>
+#include <linux/plist.h>
+#include <linux/fs.h>
+
+#include "rtmutex_common.h"
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
+
+# define TRACE_WARN_ON(x)			WARN_ON(x)
+# define TRACE_BUG_ON(x)			BUG_ON(x)
+
+# define TRACE_OFF()						\
+do {								\
+	if (rt_trace_on) {					\
+		rt_trace_on = 0;				\
+		console_verbose();				\
+		if (spin_is_locked(&current->pi_lock))		\
+			spin_unlock(&current->pi_lock);		\
+		if (spin_is_locked(&current->held_list_lock))	\
+			spin_unlock(&current->held_list_lock);	\
+	}							\
+} while (0)
+
+# define TRACE_OFF_NOLOCK()					\
+do {								\
+	if (rt_trace_on) {					\
+		rt_trace_on = 0;				\
+		console_verbose();				\
+	}							\
+} while (0)
+
+# define TRACE_BUG_LOCKED()			\
+do {						\
+	TRACE_OFF();				\
+	BUG();					\
+} while (0)
+
+# define TRACE_WARN_ON_LOCKED(c)		\
+do {						\
+	if (unlikely(c)) {			\
+		TRACE_OFF();			\
+		WARN_ON(1);			\
+	}					\
+} while (0)
+
+# define TRACE_BUG_ON_LOCKED(c)			\
+do {						\
+	if (unlikely(c))			\
+		TRACE_BUG_LOCKED();		\
+} while (0)
+
+#ifdef CONFIG_SMP
+# define SMP_TRACE_BUG_ON_LOCKED(c)	TRACE_BUG_ON_LOCKED(c)
+#else
+# define SMP_TRACE_BUG_ON_LOCKED(c)	do { } while (0)
+#endif
+
+/*
+ * deadlock detection flag. We turn it off when we detect
+ * the first problem because we dont want to recurse back
+ * into the tracing code when doing error printk or
+ * executing a BUG():
+ */
+int rt_trace_on = 1;
+
+void deadlock_trace_off(void)
+{
+	rt_trace_on = 0;
+}
+
+static void printk_task(task_t *p)
+{
+	if (p)
+		printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio);
+	else
+		printk("<none>");
+}
+
+static void printk_task_short(task_t *p)
+{
+	if (p)
+		printk("%s/%d [%p, %3d]", p->comm, p->pid, p, p->prio);
+	else
+		printk("<none>");
+}
+
+static void printk_lock(struct rt_mutex *lock, int print_owner)
+{
+	if (lock->name)
+		printk(" [%p] {%s}\n",
+			lock, lock->name);
+	else
+		printk(" [%p] {%s:%d}\n",
+			lock, lock->file, lock->line);
+
+	if (print_owner && rt_mutex_owner(lock)) {
+		printk(".. ->owner: %p\n", lock->owner);
+		printk(".. held by:  ");
+		printk_task(rt_mutex_owner(lock));
+		printk("\n");
+	}
+	if (rt_mutex_owner(lock)) {
+		printk("... acquired at:               ");
+		print_symbol("%s\n", lock->acquire_ip);
+	}
+}
+
+static void printk_waiter(struct rt_mutex_waiter *w)
+{
+	printk("-------------------------\n");
+	printk("| waiter struct %p:\n", w);
+	printk("| w->list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n",
+	       w->list_entry.plist.prio_list.prev, w->list_entry.plist.prio_list.next,
+	       w->list_entry.plist.node_list.prev, w->list_entry.plist.node_list.next,
+	       w->list_entry.prio);
+	printk("| w->pi_list_entry: [DP:%p/%p|SP:%p/%p|PRI:%d]\n",
+	       w->pi_list_entry.plist.prio_list.prev, w->pi_list_entry.plist.prio_list.next,
+	       w->pi_list_entry.plist.node_list.prev, w->pi_list_entry.plist.node_list.next,
+	       w->pi_list_entry.prio);
+	printk("\n| lock:\n");
+	printk_lock(w->lock, 1);
+	printk("| w->ti->task:\n");
+	printk_task(w->task);
+	printk("| blocked at:  ");
+	print_symbol("%s\n", w->ip);
+	printk("-------------------------\n");
+}
+
+static void show_task_locks(task_t *p)
+{
+	switch (p->state) {
+	case TASK_RUNNING:		printk("R"); break;
+	case TASK_INTERRUPTIBLE:	printk("S"); break;
+	case TASK_UNINTERRUPTIBLE:	printk("D"); break;
+	case TASK_STOPPED:		printk("T"); break;
+	case EXIT_ZOMBIE:		printk("Z"); break;
+	case EXIT_DEAD:			printk("X"); break;
+	default:			printk("?"); break;
+	}
+	printk_task(p);
+	if (p->pi_blocked_on) {
+		struct rt_mutex *lock = p->pi_blocked_on->lock;
+
+		printk(" blocked on:");
+		printk_lock(lock, 1);
+	} else
+		printk(" (not blocked)\n");
+}
+
+void rt_mutex_show_held_locks(task_t *task, int verbose)
+{
+	struct list_head *curr, *cursor = NULL;
+	struct rt_mutex *lock;
+	task_t *t;
+	unsigned long flags;
+	int count = 0;
+
+	if (!rt_trace_on)
+		return;
+
+	if (verbose) {
+		printk("------------------------------\n");
+		printk("| showing all locks held by: |  (");
+		printk_task_short(task);
+		printk("):\n");
+		printk("------------------------------\n");
+	}
+
+next:
+	spin_lock_irqsave(&task->held_list_lock, flags);
+	list_for_each(curr, &task->held_list_head) {
+		if (cursor && curr != cursor)
+			continue;
+		lock = list_entry(curr, struct rt_mutex, held_list_entry);
+		t = rt_mutex_owner(lock);
+		WARN_ON(t != task);
+		count++;
+		cursor = curr->next;
+		spin_unlock_irqrestore(&task->held_list_lock, flags);
+
+		printk("\n#%03d:            ", count);
+		printk_lock(lock, 0);
+		goto next;
+	}
+	spin_unlock_irqrestore(&task->held_list_lock, flags);
+
+	printk("\n");
+}
+
+void rt_mutex_show_all_locks(void)
+{
+	task_t *g, *p;
+	int count = 10;
+	int unlock = 1;
+
+	printk("\n");
+	printk("----------------------\n");
+	printk("| showing all tasks: |\n");
+	printk("----------------------\n");
+
+	/*
+	 * Here we try to get the tasklist_lock as hard as possible,
+	 * if not successful after 2 seconds we ignore it (but keep
+	 * trying). This is to enable a debug printout even if a
+	 * tasklist_lock-holding task deadlocks or crashes.
+	 */
+retry:
+	if (!read_trylock(&tasklist_lock)) {
+		if (count == 10)
+			printk("hm, tasklist_lock locked, retrying... ");
+		if (count) {
+			count--;
+			printk(" #%d", 10-count);
+			mdelay(200);
+			goto retry;
+		}
+		printk(" ignoring it.\n");
+		unlock = 0;
+	}
+	if (count != 10)
+		printk(" locked it.\n");
+
+	do_each_thread(g, p) {
+		show_task_locks(p);
+		if (!unlock)
+			if (read_trylock(&tasklist_lock))
+				unlock = 1;
+	} while_each_thread(g, p);
+
+	printk("\n");
+
+	printk("-----------------------------------------\n");
+	printk("| showing all locks held in the system: |\n");
+	printk("-----------------------------------------\n");
+
+	do_each_thread(g, p) {
+		rt_mutex_show_held_locks(p, 0);
+		if (!unlock)
+			if (read_trylock(&tasklist_lock))
+				unlock = 1;
+	} while_each_thread(g, p);
+
+
+	printk("=============================================\n\n");
+
+	if (unlock)
+		read_unlock(&tasklist_lock);
+}
+
+void rt_mutex_debug_check_no_locks_held(task_t *task)
+{
+	struct rt_mutex_waiter *w;
+	struct list_head *curr;
+	struct rt_mutex *lock;
+
+	if (!rt_trace_on)
+		return;
+	if (!rt_prio(task->normal_prio) && rt_prio(task->prio)) {
+		printk("BUG: PI priority boost leaked!\n");
+		printk_task(task);
+		printk("\n");
+	}
+	if (list_empty(&task->held_list_head))
+		return;
+
+	spin_lock(&task->pi_lock);
+	plist_for_each_entry(w, &task->pi_waiters, pi_list_entry) {
+		TRACE_OFF();
+
+		printk("hm, PI interest held at exit time? Task:\n");
+		printk_task(task);
+		printk_waiter(w);
+		return;
+	}
+	spin_unlock(&task->pi_lock);
+
+	list_for_each(curr, &task->held_list_head) {
+		lock = list_entry(curr, struct rt_mutex, held_list_entry);
+
+		printk("BUG: %s/%d, lock held at task exit time!\n",
+		       task->comm, task->pid);
+		printk_lock(lock, 1);
+		if (rt_mutex_owner(lock) != task)
+			printk("exiting task is not even the owner??\n");
+	}
+}
+
+int rt_mutex_debug_check_no_locks_freed(const void *from, unsigned long len)
+{
+	const void *to = from + len;
+	struct list_head *curr;
+	struct rt_mutex *lock;
+	unsigned long flags;
+	void *lock_addr;
+
+	if (!rt_trace_on)
+		return 0;
+
+	spin_lock_irqsave(&current->held_list_lock, flags);
+	list_for_each(curr, &current->held_list_head) {
+		lock = list_entry(curr, struct rt_mutex, held_list_entry);
+		lock_addr = lock;
+		if (lock_addr < from || lock_addr >= to)
+			continue;
+		TRACE_OFF();
+
+		printk("BUG: %s/%d, active lock [%p(%p-%p)] freed!\n",
+			current->comm, current->pid, lock, from, to);
+		dump_stack();
+		printk_lock(lock, 1);
+		if (rt_mutex_owner(lock) != current)
+			printk("freeing task is not even the owner??\n");
+		return 1;
+	}
+	spin_unlock_irqrestore(&current->held_list_lock, flags);
+
+	return 0;
+}
+
+void rt_mutex_debug_task_free(struct task_struct *task)
+{
+	WARN_ON(!plist_head_empty(&task->pi_waiters));
+	WARN_ON(task->pi_blocked_on);
+}
+
+/*
+ * We fill out the fields in the waiter to store the information about
+ * the deadlock. We print when we return. act_waiter can be NULL in
+ * case of a remove waiter operation.
+ */
+void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *act_waiter,
+			     struct rt_mutex *lock)
+{
+	struct task_struct *task;
+
+	if (!rt_trace_on || detect || !act_waiter)
+		return;
+
+	task = rt_mutex_owner(act_waiter->lock);
+	if (task && task != current) {
+		act_waiter->deadlock_task_pid = task->pid;
+		act_waiter->deadlock_lock = lock;
+	}
+}
+
+void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)
+{
+	struct task_struct *task;
+
+	if (!waiter->deadlock_lock || !rt_trace_on)
+		return;
+
+	task = find_task_by_pid(waiter->deadlock_task_pid);
+	if (!task)
+		return;
+
+	TRACE_OFF_NOLOCK();
+
+	printk("\n============================================\n");
+	printk(  "[ BUG: circular locking deadlock detected! ]\n");
+	printk(  "--------------------------------------------\n");
+	printk("%s/%d is deadlocking current task %s/%d\n\n",
+	       task->comm, task->pid, current->comm, current->pid);
+
+	printk("\n1) %s/%d is trying to acquire this lock:\n",
+	       current->comm, current->pid);
+	printk_lock(waiter->lock, 1);
+
+	printk("... trying at:                 ");
+	print_symbol("%s\n", waiter->ip);
+
+	printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid);
+	printk_lock(waiter->deadlock_lock, 1);
+
+	rt_mutex_show_held_locks(current, 1);
+	rt_mutex_show_held_locks(task, 1);
+
+	printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid);
+	show_stack(task, NULL);
+	printk("\n%s/%d's [current] stackdump:\n\n",
+	       current->comm, current->pid);
+	dump_stack();
+	rt_mutex_show_all_locks();
+	printk("[ turning off deadlock detection."
+	       "Please report this trace. ]\n\n");
+	local_irq_disable();
+}
+
+void debug_rt_mutex_lock(struct rt_mutex *lock __IP_DECL__)
+{
+	unsigned long flags;
+
+	if (rt_trace_on) {
+		TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry));
+
+		spin_lock_irqsave(&current->held_list_lock, flags);
+		list_add_tail(&lock->held_list_entry, &current->held_list_head);
+		spin_unlock_irqrestore(&current->held_list_lock, flags);
+
+		lock->acquire_ip = ip;
+	}
+}
+
+void debug_rt_mutex_unlock(struct rt_mutex *lock)
+{
+	unsigned long flags;
+
+	if (rt_trace_on) {
+		TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current);
+		TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry));
+
+		spin_lock_irqsave(&current->held_list_lock, flags);
+		list_del_init(&lock->held_list_entry);
+		spin_unlock_irqrestore(&current->held_list_lock, flags);
+	}
+}
+
+void debug_rt_mutex_proxy_lock(struct rt_mutex *lock,
+			       struct task_struct *powner __IP_DECL__)
+{
+	unsigned long flags;
+
+	if (rt_trace_on) {
+		TRACE_WARN_ON_LOCKED(!list_empty(&lock->held_list_entry));
+
+		spin_lock_irqsave(&powner->held_list_lock, flags);
+		list_add_tail(&lock->held_list_entry, &powner->held_list_head);
+		spin_unlock_irqrestore(&powner->held_list_lock, flags);
+
+		lock->acquire_ip = ip;
+	}
+}
+
+void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock)
+{
+	unsigned long flags;
+
+	if (rt_trace_on) {
+		struct task_struct *owner = rt_mutex_owner(lock);
+
+		TRACE_WARN_ON_LOCKED(!owner);
+		TRACE_WARN_ON_LOCKED(list_empty(&lock->held_list_entry));
+
+		spin_lock_irqsave(&owner->held_list_lock, flags);
+		list_del_init(&lock->held_list_entry);
+		spin_unlock_irqrestore(&owner->held_list_lock, flags);
+	}
+}
+
+void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
+{
+	memset(waiter, 0x11, sizeof(*waiter));
+	plist_node_init(&waiter->list_entry, MAX_PRIO);
+	plist_node_init(&waiter->pi_list_entry, MAX_PRIO);
+}
+
+void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
+{
+	TRACE_WARN_ON(!plist_node_empty(&waiter->list_entry));
+	TRACE_WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
+	TRACE_WARN_ON(waiter->task);
+	memset(waiter, 0x22, sizeof(*waiter));
+}
+
+void debug_rt_mutex_init(struct rt_mutex *lock, const char *name)
+{
+	void *addr = lock;
+
+	if (rt_trace_on) {
+		rt_mutex_debug_check_no_locks_freed(addr,
+						    sizeof(struct rt_mutex));
+		INIT_LIST_HEAD(&lock->held_list_entry);
+		lock->name = name;
+	}
+}
+
+void rt_mutex_deadlock_account_lock(struct rt_mutex *lock, task_t *task)
+{
+}
+
+void rt_mutex_deadlock_account_unlock(struct task_struct *task)
+{
+}
+
diff --git a/kernel/rtmutex-debug.h b/kernel/rtmutex-debug.h
new file mode 100644
index 0000000..7612fbc
--- /dev/null
+++ b/kernel/rtmutex-debug.h
@@ -0,0 +1,37 @@
+/*
+ * RT-Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains macros used solely by rtmutex.c. Debug version.
+ */
+
+#define __IP_DECL__		, unsigned long ip
+#define __IP__			, ip
+#define __RET_IP__		, (unsigned long)__builtin_return_address(0)
+
+extern void
+rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task);
+extern void rt_mutex_deadlock_account_unlock(struct task_struct *task);
+extern void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter);
+extern void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter);
+extern void debug_rt_mutex_init(struct rt_mutex *lock, const char *name);
+extern void debug_rt_mutex_lock(struct rt_mutex *lock __IP_DECL__);
+extern void debug_rt_mutex_unlock(struct rt_mutex *lock);
+extern void debug_rt_mutex_proxy_lock(struct rt_mutex *lock,
+				      struct task_struct *powner __IP_DECL__);
+extern void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock);
+extern void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *waiter,
+				    struct rt_mutex *lock);
+extern void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter);
+# define debug_rt_mutex_reset_waiter(w)			\
+	do { (w)->deadlock_lock = NULL; } while (0)
+
+static inline int debug_rt_mutex_detect_deadlock(struct rt_mutex_waiter *waiter,
+						 int detect)
+{
+	return (waiter != NULL);
+}
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
new file mode 100644
index 0000000..e82c2f8
--- /dev/null
+++ b/kernel/rtmutex-tester.c
@@ -0,0 +1,440 @@
+/*
+ * RT-Mutex-tester: scriptable tester for rt mutexes
+ *
+ * started by Thomas Gleixner:
+ *
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ */
+#include <linux/config.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/sysdev.h>
+#include <linux/timer.h>
+
+#include "rtmutex.h"
+
+#define MAX_RT_TEST_THREADS	8
+#define MAX_RT_TEST_MUTEXES	8
+
+static spinlock_t rttest_lock;
+static atomic_t rttest_event;
+
+struct test_thread_data {
+	int			opcode;
+	int			opdata;
+	int			mutexes[MAX_RT_TEST_MUTEXES];
+	int			bkl;
+	int			event;
+	struct sys_device	sysdev;
+};
+
+static struct test_thread_data thread_data[MAX_RT_TEST_THREADS];
+static task_t *threads[MAX_RT_TEST_THREADS];
+static struct rt_mutex mutexes[MAX_RT_TEST_MUTEXES];
+
+enum test_opcodes {
+	RTTEST_NOP = 0,
+	RTTEST_SCHEDOT,		/* 1 Sched other, data = nice */
+	RTTEST_SCHEDRT,		/* 2 Sched fifo, data = prio */
+	RTTEST_LOCK,		/* 3 Lock uninterruptible, data = lockindex */
+	RTTEST_LOCKNOWAIT,	/* 4 Lock uninterruptible no wait in wakeup, data = lockindex */
+	RTTEST_LOCKINT,		/* 5 Lock interruptible, data = lockindex */
+	RTTEST_LOCKINTNOWAIT,	/* 6 Lock interruptible no wait in wakeup, data = lockindex */
+	RTTEST_LOCKCONT,	/* 7 Continue locking after the wakeup delay */
+	RTTEST_UNLOCK,		/* 8 Unlock, data = lockindex */
+	RTTEST_LOCKBKL,		/* 9 Lock BKL */
+	RTTEST_UNLOCKBKL,	/* 10 Unlock BKL */
+	RTTEST_SIGNAL,		/* 11 Signal other test thread, data = thread id */
+	RTTEST_RESETEVENT = 98,	/* 98 Reset event counter */
+	RTTEST_RESET = 99,	/* 99 Reset all pending operations */
+};
+
+static int handle_op(struct test_thread_data *td, int lockwakeup)
+{
+	int i, id, ret = -EINVAL;
+
+	switch(td->opcode) {
+
+	case RTTEST_NOP:
+		return 0;
+
+	case RTTEST_LOCKCONT:
+		td->mutexes[td->opdata] = 1;
+		td->event = atomic_add_return(1, &rttest_event);
+		return 0;
+
+	case RTTEST_RESET:
+		for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) {
+			if (td->mutexes[i] == 4) {
+				rt_mutex_unlock(&mutexes[i]);
+				td->mutexes[i] = 0;
+			}
+		}
+
+		if (!lockwakeup && td->bkl == 4) {
+			unlock_kernel();
+			td->bkl = 0;
+		}
+		return 0;
+
+	case RTTEST_RESETEVENT:
+		atomic_set(&rttest_event, 0);
+		return 0;
+
+	default:
+		if (lockwakeup)
+			return ret;
+	}
+
+	switch(td->opcode) {
+
+	case RTTEST_LOCK:
+	case RTTEST_LOCKNOWAIT:
+		id = td->opdata;
+		if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
+			return ret;
+
+		td->mutexes[id] = 1;
+		td->event = atomic_add_return(1, &rttest_event);
+		rt_mutex_lock(&mutexes[id]);
+		td->event = atomic_add_return(1, &rttest_event);
+		td->mutexes[id] = 4;
+		return 0;
+
+	case RTTEST_LOCKINT:
+	case RTTEST_LOCKINTNOWAIT:
+		id = td->opdata;
+		if (id < 0 || id >= MAX_RT_TEST_MUTEXES)
+			return ret;
+
+		td->mutexes[id] = 1;
+		td->event = atomic_add_return(1, &rttest_event);
+		ret = rt_mutex_lock_interruptible(&mutexes[id], 0);
+		td->event = atomic_add_return(1, &rttest_event);
+		td->mutexes[id] = ret ? 0 : 4;
+		return ret ? -EINTR : 0;
+
+	case RTTEST_UNLOCK:
+		id = td->opdata;
+		if (id < 0 || id >= MAX_RT_TEST_MUTEXES || td->mutexes[id] != 4)
+			return ret;
+
+		td->event = atomic_add_return(1, &rttest_event);
+		rt_mutex_unlock(&mutexes[id]);
+		td->event = atomic_add_return(1, &rttest_event);
+		td->mutexes[id] = 0;
+		return 0;
+
+	case RTTEST_LOCKBKL:
+		if (td->bkl)
+			return 0;
+		td->bkl = 1;
+		lock_kernel();
+		td->bkl = 4;
+		return 0;
+
+	case RTTEST_UNLOCKBKL:
+		if (td->bkl != 4)
+			break;
+		unlock_kernel();
+		td->bkl = 0;
+		return 0;
+
+	default:
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Schedule replacement for rtsem_down(). Only called for threads with
+ * PF_MUTEX_TESTER set.
+ *
+ * This allows us to have finegrained control over the event flow.
+ *
+ */
+void schedule_rt_mutex_test(struct rt_mutex *mutex)
+{
+	int tid, op, dat;
+	struct test_thread_data *td;
+
+	/* We have to lookup the task */
+	for (tid = 0; tid < MAX_RT_TEST_THREADS; tid++) {
+		if (threads[tid] == current)
+			break;
+	}
+
+	BUG_ON(tid == MAX_RT_TEST_THREADS);
+
+	td = &thread_data[tid];
+
+	op = td->opcode;
+	dat = td->opdata;
+
+	switch (op) {
+	case RTTEST_LOCK:
+	case RTTEST_LOCKINT:
+	case RTTEST_LOCKNOWAIT:
+	case RTTEST_LOCKINTNOWAIT:
+		if (mutex != &mutexes[dat])
+			break;
+
+		if (td->mutexes[dat] != 1)
+			break;
+
+		td->mutexes[dat] = 2;
+		td->event = atomic_add_return(1, &rttest_event);
+		break;
+
+	case RTTEST_LOCKBKL:
+	default:
+		break;
+	}
+
+	schedule();
+
+
+	switch (op) {
+	case RTTEST_LOCK:
+	case RTTEST_LOCKINT:
+		if (mutex != &mutexes[dat])
+			return;
+
+		if (td->mutexes[dat] != 2)
+			return;
+
+		td->mutexes[dat] = 3;
+		td->event = atomic_add_return(1, &rttest_event);
+		break;
+
+	case RTTEST_LOCKNOWAIT:
+	case RTTEST_LOCKINTNOWAIT:
+		if (mutex != &mutexes[dat])
+			return;
+
+		if (td->mutexes[dat] != 2)
+			return;
+
+		td->mutexes[dat] = 1;
+		td->event = atomic_add_return(1, &rttest_event);
+		return;
+
+	case RTTEST_LOCKBKL:
+		return;
+	default:
+		return;
+	}
+
+	td->opcode = 0;
+
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (td->opcode > 0) {
+			int ret;
+
+			set_current_state(TASK_RUNNING);
+			ret = handle_op(td, 1);
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (td->opcode == RTTEST_LOCKCONT)
+				break;
+			td->opcode = ret;
+		}
+
+		/* Wait for the next command to be executed */
+		schedule();
+	}
+
+	/* Restore previous command and data */
+	td->opcode = op;
+	td->opdata = dat;
+}
+
+static int test_func(void *data)
+{
+	struct test_thread_data *td = data;
+	int ret;
+
+	current->flags |= PF_MUTEX_TESTER;
+	allow_signal(SIGHUP);
+
+	for(;;) {
+
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if (td->opcode > 0) {
+			set_current_state(TASK_RUNNING);
+			ret = handle_op(td, 0);
+			set_current_state(TASK_INTERRUPTIBLE);
+			td->opcode = ret;
+		}
+
+		/* Wait for the next command to be executed */
+		schedule();
+
+		if (signal_pending(current))
+			flush_signals(current);
+
+		if(kthread_should_stop())
+			break;
+	}
+	return 0;
+}
+
+/**
+ * sysfs_test_command - interface for test commands
+ * @dev:	thread reference
+ * @buf:	command for actual step
+ * @count:	length of buffer
+ *
+ * command syntax:
+ *
+ * opcode:data
+ */
+static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf,
+				  size_t count)
+{
+	struct sched_param schedpar;
+	struct test_thread_data *td;
+	char cmdbuf[32];
+	int op, dat, tid, ret;
+
+	td = container_of(dev, struct test_thread_data, sysdev);
+	tid = td->sysdev.id;
+
+	/* strings from sysfs write are not 0 terminated! */
+	if (count >= sizeof(cmdbuf))
+		return -EINVAL;
+
+	/* strip of \n: */
+	if (buf[count-1] == '\n')
+		count--;
+	if (count < 1)
+		return -EINVAL;
+
+	memcpy(cmdbuf, buf, count);
+	cmdbuf[count] = 0;
+
+	if (sscanf(cmdbuf, "%d:%d", &op, &dat) != 2)
+		return -EINVAL;
+
+	switch (op) {
+	case RTTEST_SCHEDOT:
+		schedpar.sched_priority = 0;
+		ret = sched_setscheduler(threads[tid], SCHED_NORMAL, &schedpar);
+		if (ret)
+			return ret;
+		set_user_nice(current, 0);
+		break;
+
+	case RTTEST_SCHEDRT:
+		schedpar.sched_priority = dat;
+		ret = sched_setscheduler(threads[tid], SCHED_FIFO, &schedpar);
+		if (ret)
+			return ret;
+		break;
+
+	case RTTEST_SIGNAL:
+		send_sig(SIGHUP, threads[tid], 0);
+		break;
+
+	default:
+		if (td->opcode > 0)
+			return -EBUSY;
+		td->opdata = dat;
+		td->opcode = op;
+		wake_up_process(threads[tid]);
+	}
+
+	return count;
+}
+
+/**
+ * sysfs_test_status - sysfs interface for rt tester
+ * @dev:	thread to query
+ * @buf:	char buffer to be filled with thread status info
+ */
+static ssize_t sysfs_test_status(struct sys_device *dev, char *buf)
+{
+	struct test_thread_data *td;
+	char *curr = buf;
+	task_t *tsk;
+	int i;
+
+	td = container_of(dev, struct test_thread_data, sysdev);
+	tsk = threads[td->sysdev.id];
+
+	spin_lock(&rttest_lock);
+
+	curr += sprintf(curr,
+		"O: %4d, E:%8d, S: 0x%08lx, P: %4d, N: %4d, B: %p, K: %d, M:",
+		td->opcode, td->event, tsk->state,
+			(MAX_RT_PRIO - 1) - tsk->prio,
+			(MAX_RT_PRIO - 1) - tsk->normal_prio,
+		tsk->pi_blocked_on, td->bkl);
+
+	for (i = MAX_RT_TEST_MUTEXES - 1; i >=0 ; i--)
+		curr += sprintf(curr, "%d", td->mutexes[i]);
+
+	spin_unlock(&rttest_lock);
+
+	curr += sprintf(curr, ", T: %p, R: %p\n", tsk,
+			mutexes[td->sysdev.id].owner);
+
+	return curr - buf;
+}
+
+static SYSDEV_ATTR(status, 0600, sysfs_test_status, NULL);
+static SYSDEV_ATTR(command, 0600, NULL, sysfs_test_command);
+
+static struct sysdev_class rttest_sysclass = {
+	set_kset_name("rttest"),
+};
+
+static int init_test_thread(int id)
+{
+	thread_data[id].sysdev.cls = &rttest_sysclass;
+	thread_data[id].sysdev.id = id;
+
+	threads[id] = kthread_run(test_func, &thread_data[id], "rt-test-%d", id);
+	if (IS_ERR(threads[id]))
+		return PTR_ERR(threads[id]);
+
+	return sysdev_register(&thread_data[id].sysdev);
+}
+
+static int init_rttest(void)
+{
+	int ret, i;
+
+	spin_lock_init(&rttest_lock);
+
+	for (i = 0; i < MAX_RT_TEST_MUTEXES; i++)
+		rt_mutex_init(&mutexes[i]);
+
+	ret = sysdev_class_register(&rttest_sysclass);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < MAX_RT_TEST_THREADS; i++) {
+		ret = init_test_thread(i);
+		if (ret)
+			break;
+		ret = sysdev_create_file(&thread_data[i].sysdev, &attr_status);
+		if (ret)
+			break;
+		ret = sysdev_create_file(&thread_data[i].sysdev, &attr_command);
+		if (ret)
+			break;
+	}
+
+	printk("Initializing RT-Tester: %s\n", ret ? "Failed" : "OK" );
+
+	return ret;
+}
+
+device_initcall(init_rttest);
diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c
new file mode 100644
index 0000000..45d6101
--- /dev/null
+++ b/kernel/rtmutex.c
@@ -0,0 +1,990 @@
+/*
+ * RT-Mutexes: simple blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner.
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *  Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt
+ *  Copyright (C) 2006 Esben Nielsen
+ */
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+
+#include "rtmutex_common.h"
+
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+# include "rtmutex-debug.h"
+#else
+# include "rtmutex.h"
+#endif
+
+/*
+ * lock->owner state tracking:
+ *
+ * lock->owner holds the task_struct pointer of the owner. Bit 0 and 1
+ * are used to keep track of the "owner is pending" and "lock has
+ * waiters" state.
+ *
+ * owner	bit1	bit0
+ * NULL		0	0	lock is free (fast acquire possible)
+ * NULL		0	1	invalid state
+ * NULL		1	0	Transitional State*
+ * NULL		1	1	invalid state
+ * taskpointer	0	0	lock is held (fast release possible)
+ * taskpointer	0	1	task is pending owner
+ * taskpointer	1	0	lock is held and has waiters
+ * taskpointer	1	1	task is pending owner and lock has more waiters
+ *
+ * Pending ownership is assigned to the top (highest priority)
+ * waiter of the lock, when the lock is released. The thread is woken
+ * up and can now take the lock. Until the lock is taken (bit 0
+ * cleared) a competing higher priority thread can steal the lock
+ * which puts the woken up thread back on the waiters list.
+ *
+ * The fast atomic compare exchange based acquire and release is only
+ * possible when bit 0 and 1 of lock->owner are 0.
+ *
+ * (*) There's a small time where the owner can be NULL and the
+ * "lock has waiters" bit is set.  This can happen when grabbing the lock.
+ * To prevent a cmpxchg of the owner releasing the lock, we need to set this
+ * bit before looking at the lock, hence the reason this is a transitional
+ * state.
+ */
+
+static void
+rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner,
+		   unsigned long mask)
+{
+	unsigned long val = (unsigned long)owner | mask;
+
+	if (rt_mutex_has_waiters(lock))
+		val |= RT_MUTEX_HAS_WAITERS;
+
+	lock->owner = (struct task_struct *)val;
+}
+
+static inline void clear_rt_mutex_waiters(struct rt_mutex *lock)
+{
+	lock->owner = (struct task_struct *)
+			((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
+}
+
+static void fixup_rt_mutex_waiters(struct rt_mutex *lock)
+{
+	if (!rt_mutex_has_waiters(lock))
+		clear_rt_mutex_waiters(lock);
+}
+
+/*
+ * We can speed up the acquire/release, if the architecture
+ * supports cmpxchg and if there's no debugging state to be set up
+ */
+#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES)
+# define rt_mutex_cmpxchg(l,c,n)	(cmpxchg(&l->owner, c, n) == c)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+	unsigned long owner, *p = (unsigned long *) &lock->owner;
+
+	do {
+		owner = *p;
+	} while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner);
+}
+#else
+# define rt_mutex_cmpxchg(l,c,n)	(0)
+static inline void mark_rt_mutex_waiters(struct rt_mutex *lock)
+{
+	lock->owner = (struct task_struct *)
+			((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS);
+}
+#endif
+
+/*
+ * Calculate task priority from the waiter list priority
+ *
+ * Return task->normal_prio when the waiter list is empty or when
+ * the waiter is not allowed to do priority boosting
+ */
+int rt_mutex_getprio(struct task_struct *task)
+{
+	if (likely(!task_has_pi_waiters(task)))
+		return task->normal_prio;
+
+	return min(task_top_pi_waiter(task)->pi_list_entry.prio,
+		   task->normal_prio);
+}
+
+/*
+ * Adjust the priority of a task, after its pi_waiters got modified.
+ *
+ * This can be both boosting and unboosting. task->pi_lock must be held.
+ */
+static void __rt_mutex_adjust_prio(struct task_struct *task)
+{
+	int prio = rt_mutex_getprio(task);
+
+	if (task->prio != prio)
+		rt_mutex_setprio(task, prio);
+}
+
+/*
+ * Adjust task priority (undo boosting). Called from the exit path of
+ * rt_mutex_slowunlock() and rt_mutex_slowlock().
+ *
+ * (Note: We do this outside of the protection of lock->wait_lock to
+ * allow the lock to be taken while or before we readjust the priority
+ * of task. We do not use the spin_xx_mutex() variants here as we are
+ * outside of the debug path.)
+ */
+static void rt_mutex_adjust_prio(struct task_struct *task)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&task->pi_lock, flags);
+	__rt_mutex_adjust_prio(task);
+	spin_unlock_irqrestore(&task->pi_lock, flags);
+}
+
+/*
+ * Max number of times we'll walk the boosting chain:
+ */
+int max_lock_depth = 1024;
+
+/*
+ * Adjust the priority chain. Also used for deadlock detection.
+ * Decreases task's usage by one - may thus free the task.
+ * Returns 0 or -EDEADLK.
+ */
+static int rt_mutex_adjust_prio_chain(task_t *task,
+				      int deadlock_detect,
+				      struct rt_mutex *orig_lock,
+				      struct rt_mutex_waiter *orig_waiter,
+				      struct task_struct *top_task
+				      __IP_DECL__)
+{
+	struct rt_mutex *lock;
+	struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter;
+	int detect_deadlock, ret = 0, depth = 0;
+	unsigned long flags;
+
+	detect_deadlock = debug_rt_mutex_detect_deadlock(orig_waiter,
+							 deadlock_detect);
+
+	/*
+	 * The (de)boosting is a step by step approach with a lot of
+	 * pitfalls. We want this to be preemptible and we want hold a
+	 * maximum of two locks per step. So we have to check
+	 * carefully whether things change under us.
+	 */
+ again:
+	if (++depth > max_lock_depth) {
+		static int prev_max;
+
+		/*
+		 * Print this only once. If the admin changes the limit,
+		 * print a new message when reaching the limit again.
+		 */
+		if (prev_max != max_lock_depth) {
+			prev_max = max_lock_depth;
+			printk(KERN_WARNING "Maximum lock depth %d reached "
+			       "task: %s (%d)\n", max_lock_depth,
+			       top_task->comm, top_task->pid);
+		}
+		put_task_struct(task);
+
+		return deadlock_detect ? -EDEADLK : 0;
+	}
+ retry:
+	/*
+	 * Task can not go away as we did a get_task() before !
+	 */
+	spin_lock_irqsave(&task->pi_lock, flags);
+
+	waiter = task->pi_blocked_on;
+	/*
+	 * Check whether the end of the boosting chain has been
+	 * reached or the state of the chain has changed while we
+	 * dropped the locks.
+	 */
+	if (!waiter || !waiter->task)
+		goto out_unlock_pi;
+
+	if (top_waiter && (!task_has_pi_waiters(task) ||
+			   top_waiter != task_top_pi_waiter(task)))
+		goto out_unlock_pi;
+
+	/*
+	 * When deadlock detection is off then we check, if further
+	 * priority adjustment is necessary.
+	 */
+	if (!detect_deadlock && waiter->list_entry.prio == task->prio)
+		goto out_unlock_pi;
+
+	lock = waiter->lock;
+	if (!spin_trylock(&lock->wait_lock)) {
+		spin_unlock_irqrestore(&task->pi_lock, flags);
+		cpu_relax();
+		goto retry;
+	}
+
+	/* Deadlock detection */
+	if (lock == orig_lock || rt_mutex_owner(lock) == top_task) {
+		debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock);
+		spin_unlock(&lock->wait_lock);
+		ret = deadlock_detect ? -EDEADLK : 0;
+		goto out_unlock_pi;
+	}
+
+	top_waiter = rt_mutex_top_waiter(lock);
+
+	/* Requeue the waiter */
+	plist_del(&waiter->list_entry, &lock->wait_list);
+	waiter->list_entry.prio = task->prio;
+	plist_add(&waiter->list_entry, &lock->wait_list);
+
+	/* Release the task */
+	spin_unlock_irqrestore(&task->pi_lock, flags);
+	put_task_struct(task);
+
+	/* Grab the next task */
+	task = rt_mutex_owner(lock);
+	spin_lock_irqsave(&task->pi_lock, flags);
+
+	if (waiter == rt_mutex_top_waiter(lock)) {
+		/* Boost the owner */
+		plist_del(&top_waiter->pi_list_entry, &task->pi_waiters);
+		waiter->pi_list_entry.prio = waiter->list_entry.prio;
+		plist_add(&waiter->pi_list_entry, &task->pi_waiters);
+		__rt_mutex_adjust_prio(task);
+
+	} else if (top_waiter == waiter) {
+		/* Deboost the owner */
+		plist_del(&waiter->pi_list_entry, &task->pi_waiters);
+		waiter = rt_mutex_top_waiter(lock);
+		waiter->pi_list_entry.prio = waiter->list_entry.prio;
+		plist_add(&waiter->pi_list_entry, &task->pi_waiters);
+		__rt_mutex_adjust_prio(task);
+	}
+
+	get_task_struct(task);
+	spin_unlock_irqrestore(&task->pi_lock, flags);
+
+	top_waiter = rt_mutex_top_waiter(lock);
+	spin_unlock(&lock->wait_lock);
+
+	if (!detect_deadlock && waiter != top_waiter)
+		goto out_put_task;
+
+	goto again;
+
+ out_unlock_pi:
+	spin_unlock_irqrestore(&task->pi_lock, flags);
+ out_put_task:
+	put_task_struct(task);
+	return ret;
+}
+
+/*
+ * Optimization: check if we can steal the lock from the
+ * assigned pending owner [which might not have taken the
+ * lock yet]:
+ */
+static inline int try_to_steal_lock(struct rt_mutex *lock)
+{
+	struct task_struct *pendowner = rt_mutex_owner(lock);
+	struct rt_mutex_waiter *next;
+	unsigned long flags;
+
+	if (!rt_mutex_owner_pending(lock))
+		return 0;
+
+	if (pendowner == current)
+		return 1;
+
+	spin_lock_irqsave(&pendowner->pi_lock, flags);
+	if (current->prio >= pendowner->prio) {
+		spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+		return 0;
+	}
+
+	/*
+	 * Check if a waiter is enqueued on the pending owners
+	 * pi_waiters list. Remove it and readjust pending owners
+	 * priority.
+	 */
+	if (likely(!rt_mutex_has_waiters(lock))) {
+		spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+		return 1;
+	}
+
+	/* No chain handling, pending owner is not blocked on anything: */
+	next = rt_mutex_top_waiter(lock);
+	plist_del(&next->pi_list_entry, &pendowner->pi_waiters);
+	__rt_mutex_adjust_prio(pendowner);
+	spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+
+	/*
+	 * We are going to steal the lock and a waiter was
+	 * enqueued on the pending owners pi_waiters queue. So
+	 * we have to enqueue this waiter into
+	 * current->pi_waiters list. This covers the case,
+	 * where current is boosted because it holds another
+	 * lock and gets unboosted because the booster is
+	 * interrupted, so we would delay a waiter with higher
+	 * priority as current->normal_prio.
+	 *
+	 * Note: in the rare case of a SCHED_OTHER task changing
+	 * its priority and thus stealing the lock, next->task
+	 * might be current:
+	 */
+	if (likely(next->task != current)) {
+		spin_lock_irqsave(&current->pi_lock, flags);
+		plist_add(&next->pi_list_entry, &current->pi_waiters);
+		__rt_mutex_adjust_prio(current);
+		spin_unlock_irqrestore(&current->pi_lock, flags);
+	}
+	return 1;
+}
+
+/*
+ * Try to take an rt-mutex
+ *
+ * This fails
+ * - when the lock has a real owner
+ * - when a different pending owner exists and has higher priority than current
+ *
+ * Must be called with lock->wait_lock held.
+ */
+static int try_to_take_rt_mutex(struct rt_mutex *lock __IP_DECL__)
+{
+	/*
+	 * We have to be careful here if the atomic speedups are
+	 * enabled, such that, when
+	 *  - no other waiter is on the lock
+	 *  - the lock has been released since we did the cmpxchg
+	 * the lock can be released or taken while we are doing the
+	 * checks and marking the lock with RT_MUTEX_HAS_WAITERS.
+	 *
+	 * The atomic acquire/release aware variant of
+	 * mark_rt_mutex_waiters uses a cmpxchg loop. After setting
+	 * the WAITERS bit, the atomic release / acquire can not
+	 * happen anymore and lock->wait_lock protects us from the
+	 * non-atomic case.
+	 *
+	 * Note, that this might set lock->owner =
+	 * RT_MUTEX_HAS_WAITERS in the case the lock is not contended
+	 * any more. This is fixed up when we take the ownership.
+	 * This is the transitional state explained at the top of this file.
+	 */
+	mark_rt_mutex_waiters(lock);
+
+	if (rt_mutex_owner(lock) && !try_to_steal_lock(lock))
+		return 0;
+
+	/* We got the lock. */
+	debug_rt_mutex_lock(lock __IP__);
+
+	rt_mutex_set_owner(lock, current, 0);
+
+	rt_mutex_deadlock_account_lock(lock, current);
+
+	return 1;
+}
+
+/*
+ * Task blocks on lock.
+ *
+ * Prepare waiter and propagate pi chain
+ *
+ * This must be called with lock->wait_lock held.
+ */
+static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
+				   struct rt_mutex_waiter *waiter,
+				   int detect_deadlock
+				   __IP_DECL__)
+{
+	struct rt_mutex_waiter *top_waiter = waiter;
+	task_t *owner = rt_mutex_owner(lock);
+	int boost = 0, res;
+	unsigned long flags;
+
+	spin_lock_irqsave(&current->pi_lock, flags);
+	__rt_mutex_adjust_prio(current);
+	waiter->task = current;
+	waiter->lock = lock;
+	plist_node_init(&waiter->list_entry, current->prio);
+	plist_node_init(&waiter->pi_list_entry, current->prio);
+
+	/* Get the top priority waiter on the lock */
+	if (rt_mutex_has_waiters(lock))
+		top_waiter = rt_mutex_top_waiter(lock);
+	plist_add(&waiter->list_entry, &lock->wait_list);
+
+	current->pi_blocked_on = waiter;
+
+	spin_unlock_irqrestore(&current->pi_lock, flags);
+
+	if (waiter == rt_mutex_top_waiter(lock)) {
+		spin_lock_irqsave(&owner->pi_lock, flags);
+		plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters);
+		plist_add(&waiter->pi_list_entry, &owner->pi_waiters);
+
+		__rt_mutex_adjust_prio(owner);
+		if (owner->pi_blocked_on) {
+			boost = 1;
+			/* gets dropped in rt_mutex_adjust_prio_chain()! */
+			get_task_struct(owner);
+		}
+		spin_unlock_irqrestore(&owner->pi_lock, flags);
+	}
+	else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) {
+		spin_lock_irqsave(&owner->pi_lock, flags);
+		if (owner->pi_blocked_on) {
+			boost = 1;
+			/* gets dropped in rt_mutex_adjust_prio_chain()! */
+			get_task_struct(owner);
+		}
+		spin_unlock_irqrestore(&owner->pi_lock, flags);
+	}
+	if (!boost)
+		return 0;
+
+	spin_unlock(&lock->wait_lock);
+
+	res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter,
+					 current __IP__);
+
+	spin_lock(&lock->wait_lock);
+
+	return res;
+}
+
+/*
+ * Wake up the next waiter on the lock.
+ *
+ * Remove the top waiter from the current tasks waiter list and from
+ * the lock waiter list. Set it as pending owner. Then wake it up.
+ *
+ * Called with lock->wait_lock held.
+ */
+static void wakeup_next_waiter(struct rt_mutex *lock)
+{
+	struct rt_mutex_waiter *waiter;
+	struct task_struct *pendowner;
+	unsigned long flags;
+
+	spin_lock_irqsave(&current->pi_lock, flags);
+
+	waiter = rt_mutex_top_waiter(lock);
+	plist_del(&waiter->list_entry, &lock->wait_list);
+
+	/*
+	 * Remove it from current->pi_waiters. We do not adjust a
+	 * possible priority boost right now. We execute wakeup in the
+	 * boosted mode and go back to normal after releasing
+	 * lock->wait_lock.
+	 */
+	plist_del(&waiter->pi_list_entry, &current->pi_waiters);
+	pendowner = waiter->task;
+	waiter->task = NULL;
+
+	rt_mutex_set_owner(lock, pendowner, RT_MUTEX_OWNER_PENDING);
+
+	spin_unlock_irqrestore(&current->pi_lock, flags);
+
+	/*
+	 * Clear the pi_blocked_on variable and enqueue a possible
+	 * waiter into the pi_waiters list of the pending owner. This
+	 * prevents that in case the pending owner gets unboosted a
+	 * waiter with higher priority than pending-owner->normal_prio
+	 * is blocked on the unboosted (pending) owner.
+	 */
+	spin_lock_irqsave(&pendowner->pi_lock, flags);
+
+	WARN_ON(!pendowner->pi_blocked_on);
+	WARN_ON(pendowner->pi_blocked_on != waiter);
+	WARN_ON(pendowner->pi_blocked_on->lock != lock);
+
+	pendowner->pi_blocked_on = NULL;
+
+	if (rt_mutex_has_waiters(lock)) {
+		struct rt_mutex_waiter *next;
+
+		next = rt_mutex_top_waiter(lock);
+		plist_add(&next->pi_list_entry, &pendowner->pi_waiters);
+	}
+	spin_unlock_irqrestore(&pendowner->pi_lock, flags);
+
+	wake_up_process(pendowner);
+}
+
+/*
+ * Remove a waiter from a lock
+ *
+ * Must be called with lock->wait_lock held
+ */
+static void remove_waiter(struct rt_mutex *lock,
+			  struct rt_mutex_waiter *waiter  __IP_DECL__)
+{
+	int first = (waiter == rt_mutex_top_waiter(lock));
+	int boost = 0;
+	task_t *owner = rt_mutex_owner(lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&current->pi_lock, flags);
+	plist_del(&waiter->list_entry, &lock->wait_list);
+	waiter->task = NULL;
+	current->pi_blocked_on = NULL;
+	spin_unlock_irqrestore(&current->pi_lock, flags);
+
+	if (first && owner != current) {
+
+		spin_lock_irqsave(&owner->pi_lock, flags);
+
+		plist_del(&waiter->pi_list_entry, &owner->pi_waiters);
+
+		if (rt_mutex_has_waiters(lock)) {
+			struct rt_mutex_waiter *next;
+
+			next = rt_mutex_top_waiter(lock);
+			plist_add(&next->pi_list_entry, &owner->pi_waiters);
+		}
+		__rt_mutex_adjust_prio(owner);
+
+		if (owner->pi_blocked_on) {
+			boost = 1;
+			/* gets dropped in rt_mutex_adjust_prio_chain()! */
+			get_task_struct(owner);
+		}
+		spin_unlock_irqrestore(&owner->pi_lock, flags);
+	}
+
+	WARN_ON(!plist_node_empty(&waiter->pi_list_entry));
+
+	if (!boost)
+		return;
+
+	spin_unlock(&lock->wait_lock);
+
+	rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current __IP__);
+
+	spin_lock(&lock->wait_lock);
+}
+
+/*
+ * Recheck the pi chain, in case we got a priority setting
+ *
+ * Called from sched_setscheduler
+ */
+void rt_mutex_adjust_pi(struct task_struct *task)
+{
+	struct rt_mutex_waiter *waiter;
+	unsigned long flags;
+
+	spin_lock_irqsave(&task->pi_lock, flags);
+
+	waiter = task->pi_blocked_on;
+	if (!waiter || waiter->list_entry.prio == task->prio) {
+		spin_unlock_irqrestore(&task->pi_lock, flags);
+		return;
+	}
+
+	/* gets dropped in rt_mutex_adjust_prio_chain()! */
+	get_task_struct(task);
+	spin_unlock_irqrestore(&task->pi_lock, flags);
+
+	rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task __RET_IP__);
+}
+
+/*
+ * Slow path lock function:
+ */
+static int __sched
+rt_mutex_slowlock(struct rt_mutex *lock, int state,
+		  struct hrtimer_sleeper *timeout,
+		  int detect_deadlock __IP_DECL__)
+{
+	struct rt_mutex_waiter waiter;
+	int ret = 0;
+
+	debug_rt_mutex_init_waiter(&waiter);
+	waiter.task = NULL;
+
+	spin_lock(&lock->wait_lock);
+
+	/* Try to acquire the lock again: */
+	if (try_to_take_rt_mutex(lock __IP__)) {
+		spin_unlock(&lock->wait_lock);
+		return 0;
+	}
+
+	set_current_state(state);
+
+	/* Setup the timer, when timeout != NULL */
+	if (unlikely(timeout))
+		hrtimer_start(&timeout->timer, timeout->timer.expires,
+			      HRTIMER_ABS);
+
+	for (;;) {
+		/* Try to acquire the lock: */
+		if (try_to_take_rt_mutex(lock __IP__))
+			break;
+
+		/*
+		 * TASK_INTERRUPTIBLE checks for signals and
+		 * timeout. Ignored otherwise.
+		 */
+		if (unlikely(state == TASK_INTERRUPTIBLE)) {
+			/* Signal pending? */
+			if (signal_pending(current))
+				ret = -EINTR;
+			if (timeout && !timeout->task)
+				ret = -ETIMEDOUT;
+			if (ret)
+				break;
+		}
+
+		/*
+		 * waiter.task is NULL the first time we come here and
+		 * when we have been woken up by the previous owner
+		 * but the lock got stolen by a higher prio task.
+		 */
+		if (!waiter.task) {
+			ret = task_blocks_on_rt_mutex(lock, &waiter,
+						      detect_deadlock __IP__);
+			/*
+			 * If we got woken up by the owner then start loop
+			 * all over without going into schedule to try
+			 * to get the lock now:
+			 */
+			if (unlikely(!waiter.task))
+				continue;
+
+			if (unlikely(ret))
+				break;
+		}
+
+		spin_unlock(&lock->wait_lock);
+
+		debug_rt_mutex_print_deadlock(&waiter);
+
+		if (waiter.task)
+			schedule_rt_mutex(lock);
+
+		spin_lock(&lock->wait_lock);
+		set_current_state(state);
+	}
+
+	set_current_state(TASK_RUNNING);
+
+	if (unlikely(waiter.task))
+		remove_waiter(lock, &waiter __IP__);
+
+	/*
+	 * try_to_take_rt_mutex() sets the waiter bit
+	 * unconditionally. We might have to fix that up.
+	 */
+	fixup_rt_mutex_waiters(lock);
+
+	spin_unlock(&lock->wait_lock);
+
+	/* Remove pending timer: */
+	if (unlikely(timeout))
+		hrtimer_cancel(&timeout->timer);
+
+	/*
+	 * Readjust priority, when we did not get the lock. We might
+	 * have been the pending owner and boosted. Since we did not
+	 * take the lock, the PI boost has to go.
+	 */
+	if (unlikely(ret))
+		rt_mutex_adjust_prio(current);
+
+	debug_rt_mutex_free_waiter(&waiter);
+
+	return ret;
+}
+
+/*
+ * Slow path try-lock function:
+ */
+static inline int
+rt_mutex_slowtrylock(struct rt_mutex *lock __IP_DECL__)
+{
+	int ret = 0;
+
+	spin_lock(&lock->wait_lock);
+
+	if (likely(rt_mutex_owner(lock) != current)) {
+
+		ret = try_to_take_rt_mutex(lock __IP__);
+		/*
+		 * try_to_take_rt_mutex() sets the lock waiters
+		 * bit unconditionally. Clean this up.
+		 */
+		fixup_rt_mutex_waiters(lock);
+	}
+
+	spin_unlock(&lock->wait_lock);
+
+	return ret;
+}
+
+/*
+ * Slow path to release a rt-mutex:
+ */
+static void __sched
+rt_mutex_slowunlock(struct rt_mutex *lock)
+{
+	spin_lock(&lock->wait_lock);
+
+	debug_rt_mutex_unlock(lock);
+
+	rt_mutex_deadlock_account_unlock(current);
+
+	if (!rt_mutex_has_waiters(lock)) {
+		lock->owner = NULL;
+		spin_unlock(&lock->wait_lock);
+		return;
+	}
+
+	wakeup_next_waiter(lock);
+
+	spin_unlock(&lock->wait_lock);
+
+	/* Undo pi boosting if necessary: */
+	rt_mutex_adjust_prio(current);
+}
+
+/*
+ * debug aware fast / slowpath lock,trylock,unlock
+ *
+ * The atomic acquire/release ops are compiled away, when either the
+ * architecture does not support cmpxchg or when debugging is enabled.
+ */
+static inline int
+rt_mutex_fastlock(struct rt_mutex *lock, int state,
+		  int detect_deadlock,
+		  int (*slowfn)(struct rt_mutex *lock, int state,
+				struct hrtimer_sleeper *timeout,
+				int detect_deadlock __IP_DECL__))
+{
+	if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) {
+		rt_mutex_deadlock_account_lock(lock, current);
+		return 0;
+	} else
+		return slowfn(lock, state, NULL, detect_deadlock __RET_IP__);
+}
+
+static inline int
+rt_mutex_timed_fastlock(struct rt_mutex *lock, int state,
+			struct hrtimer_sleeper *timeout, int detect_deadlock,
+			int (*slowfn)(struct rt_mutex *lock, int state,
+				      struct hrtimer_sleeper *timeout,
+				      int detect_deadlock __IP_DECL__))
+{
+	if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) {
+		rt_mutex_deadlock_account_lock(lock, current);
+		return 0;
+	} else
+		return slowfn(lock, state, timeout, detect_deadlock __RET_IP__);
+}
+
+static inline int
+rt_mutex_fasttrylock(struct rt_mutex *lock,
+		     int (*slowfn)(struct rt_mutex *lock __IP_DECL__))
+{
+	if (likely(rt_mutex_cmpxchg(lock, NULL, current))) {
+		rt_mutex_deadlock_account_lock(lock, current);
+		return 1;
+	}
+	return slowfn(lock __RET_IP__);
+}
+
+static inline void
+rt_mutex_fastunlock(struct rt_mutex *lock,
+		    void (*slowfn)(struct rt_mutex *lock))
+{
+	if (likely(rt_mutex_cmpxchg(lock, current, NULL)))
+		rt_mutex_deadlock_account_unlock(current);
+	else
+		slowfn(lock);
+}
+
+/**
+ * rt_mutex_lock - lock a rt_mutex
+ *
+ * @lock: the rt_mutex to be locked
+ */
+void __sched rt_mutex_lock(struct rt_mutex *lock)
+{
+	might_sleep();
+
+	rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_lock);
+
+/**
+ * rt_mutex_lock_interruptible - lock a rt_mutex interruptible
+ *
+ * @lock: 		the rt_mutex to be locked
+ * @detect_deadlock:	deadlock detection on/off
+ *
+ * Returns:
+ *  0 		on success
+ * -EINTR 	when interrupted by a signal
+ * -EDEADLK	when the lock would deadlock (when deadlock detection is on)
+ */
+int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock,
+						 int detect_deadlock)
+{
+	might_sleep();
+
+	return rt_mutex_fastlock(lock, TASK_INTERRUPTIBLE,
+				 detect_deadlock, rt_mutex_slowlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible);
+
+/**
+ * rt_mutex_lock_interruptible_ktime - lock a rt_mutex interruptible
+ *				       the timeout structure is provided
+ *				       by the caller
+ *
+ * @lock: 		the rt_mutex to be locked
+ * @timeout:		timeout structure or NULL (no timeout)
+ * @detect_deadlock:	deadlock detection on/off
+ *
+ * Returns:
+ *  0 		on success
+ * -EINTR 	when interrupted by a signal
+ * -ETIMEOUT	when the timeout expired
+ * -EDEADLK	when the lock would deadlock (when deadlock detection is on)
+ */
+int
+rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout,
+		    int detect_deadlock)
+{
+	might_sleep();
+
+	return rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout,
+				       detect_deadlock, rt_mutex_slowlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_timed_lock);
+
+/**
+ * rt_mutex_trylock - try to lock a rt_mutex
+ *
+ * @lock:	the rt_mutex to be locked
+ *
+ * Returns 1 on success and 0 on contention
+ */
+int __sched rt_mutex_trylock(struct rt_mutex *lock)
+{
+	return rt_mutex_fasttrylock(lock, rt_mutex_slowtrylock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_trylock);
+
+/**
+ * rt_mutex_unlock - unlock a rt_mutex
+ *
+ * @lock: the rt_mutex to be unlocked
+ */
+void __sched rt_mutex_unlock(struct rt_mutex *lock)
+{
+	rt_mutex_fastunlock(lock, rt_mutex_slowunlock);
+}
+EXPORT_SYMBOL_GPL(rt_mutex_unlock);
+
+/***
+ * rt_mutex_destroy - mark a mutex unusable
+ * @lock: the mutex to be destroyed
+ *
+ * This function marks the mutex uninitialized, and any subsequent
+ * use of the mutex is forbidden. The mutex must not be locked when
+ * this function is called.
+ */
+void rt_mutex_destroy(struct rt_mutex *lock)
+{
+	WARN_ON(rt_mutex_is_locked(lock));
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+	lock->magic = NULL;
+#endif
+}
+
+EXPORT_SYMBOL_GPL(rt_mutex_destroy);
+
+/**
+ * __rt_mutex_init - initialize the rt lock
+ *
+ * @lock: the rt lock to be initialized
+ *
+ * Initialize the rt lock to unlocked state.
+ *
+ * Initializing of a locked rt lock is not allowed
+ */
+void __rt_mutex_init(struct rt_mutex *lock, const char *name)
+{
+	lock->owner = NULL;
+	spin_lock_init(&lock->wait_lock);
+	plist_head_init(&lock->wait_list, &lock->wait_lock);
+
+	debug_rt_mutex_init(lock, name);
+}
+EXPORT_SYMBOL_GPL(__rt_mutex_init);
+
+/**
+ * rt_mutex_init_proxy_locked - initialize and lock a rt_mutex on behalf of a
+ *				proxy owner
+ *
+ * @lock: 	the rt_mutex to be locked
+ * @proxy_owner:the task to set as owner
+ *
+ * No locking. Caller has to do serializing itself
+ * Special API call for PI-futex support
+ */
+void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
+				struct task_struct *proxy_owner)
+{
+	__rt_mutex_init(lock, NULL);
+	debug_rt_mutex_proxy_lock(lock, proxy_owner __RET_IP__);
+	rt_mutex_set_owner(lock, proxy_owner, 0);
+	rt_mutex_deadlock_account_lock(lock, proxy_owner);
+}
+
+/**
+ * rt_mutex_proxy_unlock - release a lock on behalf of owner
+ *
+ * @lock: 	the rt_mutex to be locked
+ *
+ * No locking. Caller has to do serializing itself
+ * Special API call for PI-futex support
+ */
+void rt_mutex_proxy_unlock(struct rt_mutex *lock,
+			   struct task_struct *proxy_owner)
+{
+	debug_rt_mutex_proxy_unlock(lock);
+	rt_mutex_set_owner(lock, NULL, 0);
+	rt_mutex_deadlock_account_unlock(proxy_owner);
+}
+
+/**
+ * rt_mutex_next_owner - return the next owner of the lock
+ *
+ * @lock: the rt lock query
+ *
+ * Returns the next owner of the lock or NULL
+ *
+ * Caller has to serialize against other accessors to the lock
+ * itself.
+ *
+ * Special API call for PI-futex support
+ */
+struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock)
+{
+	if (!rt_mutex_has_waiters(lock))
+		return NULL;
+
+	return rt_mutex_top_waiter(lock)->task;
+}
diff --git a/kernel/rtmutex.h b/kernel/rtmutex.h
new file mode 100644
index 0000000..1e0fca1
--- /dev/null
+++ b/kernel/rtmutex.h
@@ -0,0 +1,29 @@
+/*
+ * RT-Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains macros used solely by rtmutex.c.
+ * Non-debug version.
+ */
+
+#define __IP_DECL__
+#define __IP__
+#define __RET_IP__
+#define rt_mutex_deadlock_check(l)			(0)
+#define rt_mutex_deadlock_account_lock(m, t)		do { } while (0)
+#define rt_mutex_deadlock_account_unlock(l)		do { } while (0)
+#define debug_rt_mutex_init_waiter(w)			do { } while (0)
+#define debug_rt_mutex_free_waiter(w)			do { } while (0)
+#define debug_rt_mutex_lock(l)				do { } while (0)
+#define debug_rt_mutex_proxy_lock(l,p)			do { } while (0)
+#define debug_rt_mutex_proxy_unlock(l)			do { } while (0)
+#define debug_rt_mutex_unlock(l)			do { } while (0)
+#define debug_rt_mutex_init(m, n)			do { } while (0)
+#define debug_rt_mutex_deadlock(d, a ,l)		do { } while (0)
+#define debug_rt_mutex_print_deadlock(w)		do { } while (0)
+#define debug_rt_mutex_detect_deadlock(w,d)		(d)
+#define debug_rt_mutex_reset_waiter(w)			do { } while (0)
diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h
new file mode 100644
index 0000000..9c75856
--- /dev/null
+++ b/kernel/rtmutex_common.h
@@ -0,0 +1,123 @@
+/*
+ * RT Mutexes: blocking mutual exclusion locks with PI support
+ *
+ * started by Ingo Molnar and Thomas Gleixner:
+ *
+ *  Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
+ *  Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
+ *
+ * This file contains the private data structure and API definitions.
+ */
+
+#ifndef __KERNEL_RTMUTEX_COMMON_H
+#define __KERNEL_RTMUTEX_COMMON_H
+
+#include <linux/rtmutex.h>
+
+/*
+ * The rtmutex in kernel tester is independent of rtmutex debugging. We
+ * call schedule_rt_mutex_test() instead of schedule() for the tasks which
+ * belong to the tester. That way we can delay the wakeup path of those
+ * threads to provoke lock stealing and testing of  complex boosting scenarios.
+ */
+#ifdef CONFIG_RT_MUTEX_TESTER
+
+extern void schedule_rt_mutex_test(struct rt_mutex *lock);
+
+#define schedule_rt_mutex(_lock)				\
+  do {								\
+	if (!(current->flags & PF_MUTEX_TESTER))		\
+		schedule();					\
+	else							\
+		schedule_rt_mutex_test(_lock);			\
+  } while (0)
+
+#else
+# define schedule_rt_mutex(_lock)			schedule()
+#endif
+
+/*
+ * This is the control structure for tasks blocked on a rt_mutex,
+ * which is allocated on the kernel stack on of the blocked task.
+ *
+ * @list_entry:		pi node to enqueue into the mutex waiters list
+ * @pi_list_entry:	pi node to enqueue into the mutex owner waiters list
+ * @task:		task reference to the blocked task
+ */
+struct rt_mutex_waiter {
+	struct plist_node	list_entry;
+	struct plist_node	pi_list_entry;
+	struct task_struct	*task;
+	struct rt_mutex		*lock;
+#ifdef CONFIG_DEBUG_RT_MUTEXES
+	unsigned long		ip;
+	pid_t			deadlock_task_pid;
+	struct rt_mutex		*deadlock_lock;
+#endif
+};
+
+/*
+ * Various helpers to access the waiters-plist:
+ */
+static inline int rt_mutex_has_waiters(struct rt_mutex *lock)
+{
+	return !plist_head_empty(&lock->wait_list);
+}
+
+static inline struct rt_mutex_waiter *
+rt_mutex_top_waiter(struct rt_mutex *lock)
+{
+	struct rt_mutex_waiter *w;
+
+	w = plist_first_entry(&lock->wait_list, struct rt_mutex_waiter,
+			       list_entry);
+	BUG_ON(w->lock != lock);
+
+	return w;
+}
+
+static inline int task_has_pi_waiters(struct task_struct *p)
+{
+	return !plist_head_empty(&p->pi_waiters);
+}
+
+static inline struct rt_mutex_waiter *
+task_top_pi_waiter(struct task_struct *p)
+{
+	return plist_first_entry(&p->pi_waiters, struct rt_mutex_waiter,
+				  pi_list_entry);
+}
+
+/*
+ * lock->owner state tracking:
+ */
+#define RT_MUTEX_OWNER_PENDING	1UL
+#define RT_MUTEX_HAS_WAITERS	2UL
+#define RT_MUTEX_OWNER_MASKALL	3UL
+
+static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock)
+{
+	return (struct task_struct *)
+		((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL);
+}
+
+static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock)
+{
+ 	return (struct task_struct *)
+		((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS);
+}
+
+static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock)
+{
+	return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING;
+}
+
+/*
+ * PI-futex support (proxy locking functions, etc.):
+ */
+extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock);
+extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock,
+				       struct task_struct *proxy_owner);
+extern void rt_mutex_proxy_unlock(struct rt_mutex *lock,
+				  struct task_struct *proxy_owner);
+#endif
diff --git a/kernel/sched.c b/kernel/sched.c
index c13f1bd..2629c17 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -168,15 +168,21 @@
  */
 
 #define SCALE_PRIO(x, prio) \
-	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE)
+	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)
 
-static unsigned int task_timeslice(task_t *p)
+static unsigned int static_prio_timeslice(int static_prio)
 {
-	if (p->static_prio < NICE_TO_PRIO(0))
-		return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio);
+	if (static_prio < NICE_TO_PRIO(0))
+		return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);
 	else
-		return SCALE_PRIO(DEF_TIMESLICE, p->static_prio);
+		return SCALE_PRIO(DEF_TIMESLICE, static_prio);
 }
+
+static inline unsigned int task_timeslice(task_t *p)
+{
+	return static_prio_timeslice(p->static_prio);
+}
+
 #define task_hot(p, now, sd) ((long long) ((now) - (p)->last_ran)	\
 				< (long long) (sd)->cache_hot_time)
 
@@ -184,13 +190,11 @@
  * These are the runqueue data structures:
  */
 
-#define BITMAP_SIZE ((((MAX_PRIO+1+7)/8)+sizeof(long)-1)/sizeof(long))
-
 typedef struct runqueue runqueue_t;
 
 struct prio_array {
 	unsigned int nr_active;
-	unsigned long bitmap[BITMAP_SIZE];
+	DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
 	struct list_head queue[MAX_PRIO];
 };
 
@@ -209,6 +213,7 @@
 	 * remote CPUs use both these fields when doing load calculation.
 	 */
 	unsigned long nr_running;
+	unsigned long raw_weighted_load;
 #ifdef CONFIG_SMP
 	unsigned long cpu_load[3];
 #endif
@@ -239,7 +244,6 @@
 
 	task_t *migration_thread;
 	struct list_head migration_queue;
-	int cpu;
 #endif
 
 #ifdef CONFIG_SCHEDSTATS
@@ -351,11 +355,30 @@
 #endif /* __ARCH_WANT_UNLOCKED_CTXSW */
 
 /*
+ * __task_rq_lock - lock the runqueue a given task resides on.
+ * Must be called interrupts disabled.
+ */
+static inline runqueue_t *__task_rq_lock(task_t *p)
+	__acquires(rq->lock)
+{
+	struct runqueue *rq;
+
+repeat_lock_task:
+	rq = task_rq(p);
+	spin_lock(&rq->lock);
+	if (unlikely(rq != task_rq(p))) {
+		spin_unlock(&rq->lock);
+		goto repeat_lock_task;
+	}
+	return rq;
+}
+
+/*
  * task_rq_lock - lock the runqueue a given task resides on and disable
  * interrupts.  Note the ordering: we can safely lookup the task_rq without
  * explicitly disabling preemption.
  */
-static inline runqueue_t *task_rq_lock(task_t *p, unsigned long *flags)
+static runqueue_t *task_rq_lock(task_t *p, unsigned long *flags)
 	__acquires(rq->lock)
 {
 	struct runqueue *rq;
@@ -371,6 +394,12 @@
 	return rq;
 }
 
+static inline void __task_rq_unlock(runqueue_t *rq)
+	__releases(rq->lock)
+{
+	spin_unlock(&rq->lock);
+}
+
 static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags)
 	__releases(rq->lock)
 {
@@ -634,7 +663,7 @@
 }
 
 /*
- * effective_prio - return the priority that is based on the static
+ * __normal_prio - return the priority that is based on the static
  * priority but is modified by bonuses/penalties.
  *
  * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
@@ -647,13 +676,11 @@
  *
  * Both properties are important to certain workloads.
  */
-static int effective_prio(task_t *p)
+
+static inline int __normal_prio(task_t *p)
 {
 	int bonus, prio;
 
-	if (rt_task(p))
-		return p->prio;
-
 	bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
 
 	prio = p->static_prio - bonus;
@@ -665,6 +692,106 @@
 }
 
 /*
+ * To aid in avoiding the subversion of "niceness" due to uneven distribution
+ * of tasks with abnormal "nice" values across CPUs the contribution that
+ * each task makes to its run queue's load is weighted according to its
+ * scheduling class and "nice" value.  For SCHED_NORMAL tasks this is just a
+ * scaled version of the new time slice allocation that they receive on time
+ * slice expiry etc.
+ */
+
+/*
+ * Assume: static_prio_timeslice(NICE_TO_PRIO(0)) == DEF_TIMESLICE
+ * If static_prio_timeslice() is ever changed to break this assumption then
+ * this code will need modification
+ */
+#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE
+#define LOAD_WEIGHT(lp) \
+	(((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)
+#define PRIO_TO_LOAD_WEIGHT(prio) \
+	LOAD_WEIGHT(static_prio_timeslice(prio))
+#define RTPRIO_TO_LOAD_WEIGHT(rp) \
+	(PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))
+
+static void set_load_weight(task_t *p)
+{
+	if (has_rt_policy(p)) {
+#ifdef CONFIG_SMP
+		if (p == task_rq(p)->migration_thread)
+			/*
+			 * The migration thread does the actual balancing.
+			 * Giving its load any weight will skew balancing
+			 * adversely.
+			 */
+			p->load_weight = 0;
+		else
+#endif
+			p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);
+	} else
+		p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);
+}
+
+static inline void inc_raw_weighted_load(runqueue_t *rq, const task_t *p)
+{
+	rq->raw_weighted_load += p->load_weight;
+}
+
+static inline void dec_raw_weighted_load(runqueue_t *rq, const task_t *p)
+{
+	rq->raw_weighted_load -= p->load_weight;
+}
+
+static inline void inc_nr_running(task_t *p, runqueue_t *rq)
+{
+	rq->nr_running++;
+	inc_raw_weighted_load(rq, p);
+}
+
+static inline void dec_nr_running(task_t *p, runqueue_t *rq)
+{
+	rq->nr_running--;
+	dec_raw_weighted_load(rq, p);
+}
+
+/*
+ * Calculate the expected normal priority: i.e. priority
+ * without taking RT-inheritance into account. Might be
+ * boosted by interactivity modifiers. Changes upon fork,
+ * setprio syscalls, and whenever the interactivity
+ * estimator recalculates.
+ */
+static inline int normal_prio(task_t *p)
+{
+	int prio;
+
+	if (has_rt_policy(p))
+		prio = MAX_RT_PRIO-1 - p->rt_priority;
+	else
+		prio = __normal_prio(p);
+	return prio;
+}
+
+/*
+ * Calculate the current priority, i.e. the priority
+ * taken into account by the scheduler. This value might
+ * be boosted by RT tasks, or might be boosted by
+ * interactivity modifiers. Will be RT if the task got
+ * RT-boosted. If not then it returns p->normal_prio.
+ */
+static int effective_prio(task_t *p)
+{
+	p->normal_prio = normal_prio(p);
+	/*
+	 * If we are RT tasks or we were boosted to RT priority,
+	 * keep the priority unchanged. Otherwise, update priority
+	 * to the normal priority:
+	 */
+	if (!rt_prio(p->prio))
+		return p->normal_prio;
+	return p->prio;
+}
+
+/*
  * __activate_task - move a task to the runqueue.
  */
 static void __activate_task(task_t *p, runqueue_t *rq)
@@ -674,7 +801,7 @@
 	if (batch_task(p))
 		target = rq->expired;
 	enqueue_task(p, target);
-	rq->nr_running++;
+	inc_nr_running(p, rq);
 }
 
 /*
@@ -683,39 +810,45 @@
 static inline void __activate_idle_task(task_t *p, runqueue_t *rq)
 {
 	enqueue_task_head(p, rq->active);
-	rq->nr_running++;
+	inc_nr_running(p, rq);
 }
 
+/*
+ * Recalculate p->normal_prio and p->prio after having slept,
+ * updating the sleep-average too:
+ */
 static int recalc_task_prio(task_t *p, unsigned long long now)
 {
 	/* Caller must always ensure 'now >= p->timestamp' */
-	unsigned long long __sleep_time = now - p->timestamp;
-	unsigned long sleep_time;
+	unsigned long sleep_time = now - p->timestamp;
 
 	if (batch_task(p))
 		sleep_time = 0;
-	else {
-		if (__sleep_time > NS_MAX_SLEEP_AVG)
-			sleep_time = NS_MAX_SLEEP_AVG;
-		else
-			sleep_time = (unsigned long)__sleep_time;
-	}
 
 	if (likely(sleep_time > 0)) {
 		/*
-		 * User tasks that sleep a long time are categorised as
-		 * idle. They will only have their sleep_avg increased to a
-		 * level that makes them just interactive priority to stay
-		 * active yet prevent them suddenly becoming cpu hogs and
-		 * starving other processes.
+		 * This ceiling is set to the lowest priority that would allow
+		 * a task to be reinserted into the active array on timeslice
+		 * completion.
 		 */
-		if (p->mm && sleep_time > INTERACTIVE_SLEEP(p)) {
-				unsigned long ceiling;
+		unsigned long ceiling = INTERACTIVE_SLEEP(p);
 
-				ceiling = JIFFIES_TO_NS(MAX_SLEEP_AVG -
-					DEF_TIMESLICE);
-				if (p->sleep_avg < ceiling)
-					p->sleep_avg = ceiling;
+		if (p->mm && sleep_time > ceiling && p->sleep_avg < ceiling) {
+			/*
+			 * Prevents user tasks from achieving best priority
+			 * with one single large enough sleep.
+			 */
+			p->sleep_avg = ceiling;
+			/*
+			 * Using INTERACTIVE_SLEEP() as a ceiling places a
+			 * nice(0) task 1ms sleep away from promotion, and
+			 * gives it 700ms to round-robin with no chance of
+			 * being demoted.  This is more than generous, so
+			 * mark this sleep as non-interactive to prevent the
+			 * on-runqueue bonus logic from intervening should
+			 * this task not receive cpu immediately.
+			 */
+			p->sleep_type = SLEEP_NONINTERACTIVE;
 		} else {
 			/*
 			 * Tasks waking from uninterruptible sleep are
@@ -723,12 +856,12 @@
 			 * are likely to be waiting on I/O
 			 */
 			if (p->sleep_type == SLEEP_NONINTERACTIVE && p->mm) {
-				if (p->sleep_avg >= INTERACTIVE_SLEEP(p))
+				if (p->sleep_avg >= ceiling)
 					sleep_time = 0;
 				else if (p->sleep_avg + sleep_time >=
-						INTERACTIVE_SLEEP(p)) {
-					p->sleep_avg = INTERACTIVE_SLEEP(p);
-					sleep_time = 0;
+					 ceiling) {
+						p->sleep_avg = ceiling;
+						sleep_time = 0;
 				}
 			}
 
@@ -742,9 +875,9 @@
 			 */
 			p->sleep_avg += sleep_time;
 
-			if (p->sleep_avg > NS_MAX_SLEEP_AVG)
-				p->sleep_avg = NS_MAX_SLEEP_AVG;
 		}
+		if (p->sleep_avg > NS_MAX_SLEEP_AVG)
+			p->sleep_avg = NS_MAX_SLEEP_AVG;
 	}
 
 	return effective_prio(p);
@@ -805,7 +938,7 @@
  */
 static void deactivate_task(struct task_struct *p, runqueue_t *rq)
 {
-	rq->nr_running--;
+	dec_nr_running(p, rq);
 	dequeue_task(p, p->array);
 	p->array = NULL;
 }
@@ -818,6 +951,11 @@
  * the target CPU.
  */
 #ifdef CONFIG_SMP
+
+#ifndef tsk_is_polling
+#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
+#endif
+
 static void resched_task(task_t *p)
 {
 	int cpu;
@@ -833,9 +971,9 @@
 	if (cpu == smp_processor_id())
 		return;
 
-	/* NEED_RESCHED must be visible before we test POLLING_NRFLAG */
+	/* NEED_RESCHED must be visible before we test polling */
 	smp_mb();
-	if (!test_tsk_thread_flag(p, TIF_POLLING_NRFLAG))
+	if (!tsk_is_polling(p))
 		smp_send_reschedule(cpu);
 }
 #else
@@ -855,6 +993,12 @@
 	return cpu_curr(task_cpu(p)) == p;
 }
 
+/* Used instead of source_load when we know the type == 0 */
+unsigned long weighted_cpuload(const int cpu)
+{
+	return cpu_rq(cpu)->raw_weighted_load;
+}
+
 #ifdef CONFIG_SMP
 typedef struct {
 	struct list_head list;
@@ -944,7 +1088,8 @@
 }
 
 /*
- * Return a low guess at the load of a migration-source cpu.
+ * Return a low guess at the load of a migration-source cpu weighted
+ * according to the scheduling class and "nice" value.
  *
  * We want to under-estimate the load of migration sources, to
  * balance conservatively.
@@ -952,24 +1097,36 @@
 static inline unsigned long source_load(int cpu, int type)
 {
 	runqueue_t *rq = cpu_rq(cpu);
-	unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE;
-	if (type == 0)
-		return load_now;
 
-	return min(rq->cpu_load[type-1], load_now);
+	if (type == 0)
+		return rq->raw_weighted_load;
+
+	return min(rq->cpu_load[type-1], rq->raw_weighted_load);
 }
 
 /*
- * Return a high guess at the load of a migration-target cpu
+ * Return a high guess at the load of a migration-target cpu weighted
+ * according to the scheduling class and "nice" value.
  */
 static inline unsigned long target_load(int cpu, int type)
 {
 	runqueue_t *rq = cpu_rq(cpu);
-	unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE;
-	if (type == 0)
-		return load_now;
 
-	return max(rq->cpu_load[type-1], load_now);
+	if (type == 0)
+		return rq->raw_weighted_load;
+
+	return max(rq->cpu_load[type-1], rq->raw_weighted_load);
+}
+
+/*
+ * Return the average load per task on the cpu's run queue
+ */
+static inline unsigned long cpu_avg_load_per_task(int cpu)
+{
+	runqueue_t *rq = cpu_rq(cpu);
+	unsigned long n = rq->nr_running;
+
+	return n ?  rq->raw_weighted_load / n : SCHED_LOAD_SCALE;
 }
 
 /*
@@ -1042,7 +1199,7 @@
 	cpus_and(tmp, group->cpumask, p->cpus_allowed);
 
 	for_each_cpu_mask(i, tmp) {
-		load = source_load(i, 0);
+		load = weighted_cpuload(i);
 
 		if (load < min_load || (load == min_load && i == this_cpu)) {
 			min_load = load;
@@ -1069,9 +1226,15 @@
 	struct task_struct *t = current;
 	struct sched_domain *tmp, *sd = NULL;
 
-	for_each_domain(cpu, tmp)
+	for_each_domain(cpu, tmp) {
+ 		/*
+ 	 	 * If power savings logic is enabled for a domain, stop there.
+ 	 	 */
+		if (tmp->flags & SD_POWERSAVINGS_BALANCE)
+			break;
 		if (tmp->flags & flag)
 			sd = tmp;
+	}
 
 	while (sd) {
 		cpumask_t span;
@@ -1221,17 +1384,19 @@
 
 		if (this_sd->flags & SD_WAKE_AFFINE) {
 			unsigned long tl = this_load;
+			unsigned long tl_per_task = cpu_avg_load_per_task(this_cpu);
+
 			/*
 			 * If sync wakeup then subtract the (maximum possible)
 			 * effect of the currently running task from the load
 			 * of the current CPU:
 			 */
 			if (sync)
-				tl -= SCHED_LOAD_SCALE;
+				tl -= current->load_weight;
 
 			if ((tl <= load &&
-				tl + target_load(cpu, idx) <= SCHED_LOAD_SCALE) ||
-				100*(tl + SCHED_LOAD_SCALE) <= imbalance*load) {
+				tl + target_load(cpu, idx) <= tl_per_task) ||
+				100*(tl + p->load_weight) <= imbalance*load) {
 				/*
 				 * This domain has SD_WAKE_AFFINE and
 				 * p is cache cold in this domain, and
@@ -1348,6 +1513,12 @@
 	 * event cannot wake it up and insert it on the runqueue either.
 	 */
 	p->state = TASK_RUNNING;
+
+	/*
+	 * Make sure we do not leak PI boosting priority to the child:
+	 */
+	p->prio = current->normal_prio;
+
 	INIT_LIST_HEAD(&p->run_list);
 	p->array = NULL;
 #ifdef CONFIG_SCHEDSTATS
@@ -1427,10 +1598,11 @@
 				__activate_task(p, rq);
 			else {
 				p->prio = current->prio;
+				p->normal_prio = current->normal_prio;
 				list_add_tail(&p->run_list, &current->run_list);
 				p->array = current->array;
 				p->array->nr_active++;
-				rq->nr_running++;
+				inc_nr_running(p, rq);
 			}
 			set_need_resched();
 		} else
@@ -1648,7 +1820,8 @@
 
 unsigned long long nr_context_switches(void)
 {
-	unsigned long long i, sum = 0;
+	int i;
+	unsigned long long sum = 0;
 
 	for_each_possible_cpu(i)
 		sum += cpu_rq(i)->nr_switches;
@@ -1686,9 +1859,6 @@
 /*
  * double_rq_lock - safely lock two runqueues
  *
- * We must take them in cpu order to match code in
- * dependent_sleeper and wake_dependent_sleeper.
- *
  * Note this does not disable interrupts like task_rq_lock,
  * you need to do so manually before calling.
  */
@@ -1700,7 +1870,7 @@
 		spin_lock(&rq1->lock);
 		__acquire(rq2->lock);	/* Fake it out ;) */
 	} else {
-		if (rq1->cpu < rq2->cpu) {
+		if (rq1 < rq2) {
 			spin_lock(&rq1->lock);
 			spin_lock(&rq2->lock);
 		} else {
@@ -1736,7 +1906,7 @@
 	__acquires(this_rq->lock)
 {
 	if (unlikely(!spin_trylock(&busiest->lock))) {
-		if (busiest->cpu < this_rq->cpu) {
+		if (busiest < this_rq) {
 			spin_unlock(&this_rq->lock);
 			spin_lock(&busiest->lock);
 			spin_lock(&this_rq->lock);
@@ -1799,9 +1969,9 @@
 	       runqueue_t *this_rq, prio_array_t *this_array, int this_cpu)
 {
 	dequeue_task(p, src_array);
-	src_rq->nr_running--;
+	dec_nr_running(p, src_rq);
 	set_task_cpu(p, this_cpu);
-	this_rq->nr_running++;
+	inc_nr_running(p, this_rq);
 	enqueue_task(p, this_array);
 	p->timestamp = (p->timestamp - src_rq->timestamp_last_tick)
 				+ this_rq->timestamp_last_tick;
@@ -1848,26 +2018,42 @@
 	return 1;
 }
 
+#define rq_best_prio(rq) min((rq)->curr->prio, (rq)->best_expired_prio)
 /*
- * move_tasks tries to move up to max_nr_move tasks from busiest to this_rq,
- * as part of a balancing operation within "domain". Returns the number of
- * tasks moved.
+ * move_tasks tries to move up to max_nr_move tasks and max_load_move weighted
+ * load from busiest to this_rq, as part of a balancing operation within
+ * "domain". Returns the number of tasks moved.
  *
  * Called with both runqueues locked.
  */
 static int move_tasks(runqueue_t *this_rq, int this_cpu, runqueue_t *busiest,
-		      unsigned long max_nr_move, struct sched_domain *sd,
-		      enum idle_type idle, int *all_pinned)
+		      unsigned long max_nr_move, unsigned long max_load_move,
+		      struct sched_domain *sd, enum idle_type idle,
+		      int *all_pinned)
 {
 	prio_array_t *array, *dst_array;
 	struct list_head *head, *curr;
-	int idx, pulled = 0, pinned = 0;
+	int idx, pulled = 0, pinned = 0, this_best_prio, busiest_best_prio;
+	int busiest_best_prio_seen;
+	int skip_for_load; /* skip the task based on weighted load issues */
+	long rem_load_move;
 	task_t *tmp;
 
-	if (max_nr_move == 0)
+	if (max_nr_move == 0 || max_load_move == 0)
 		goto out;
 
+	rem_load_move = max_load_move;
 	pinned = 1;
+	this_best_prio = rq_best_prio(this_rq);
+	busiest_best_prio = rq_best_prio(busiest);
+	/*
+	 * Enable handling of the case where there is more than one task
+	 * with the best priority.   If the current running task is one
+	 * of those with prio==busiest_best_prio we know it won't be moved
+	 * and therefore it's safe to override the skip (based on load) of
+	 * any task we find with that prio.
+	 */
+	busiest_best_prio_seen = busiest_best_prio == busiest->curr->prio;
 
 	/*
 	 * We first consider expired tasks. Those will likely not be
@@ -1907,7 +2093,17 @@
 
 	curr = curr->prev;
 
-	if (!can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
+	/*
+	 * To help distribute high priority tasks accross CPUs we don't
+	 * skip a task if it will be the highest priority task (i.e. smallest
+	 * prio value) on its new queue regardless of its load weight
+	 */
+	skip_for_load = tmp->load_weight > rem_load_move;
+	if (skip_for_load && idx < this_best_prio)
+		skip_for_load = !busiest_best_prio_seen && idx == busiest_best_prio;
+	if (skip_for_load ||
+	    !can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
+		busiest_best_prio_seen |= idx == busiest_best_prio;
 		if (curr != head)
 			goto skip_queue;
 		idx++;
@@ -1921,9 +2117,15 @@
 
 	pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu);
 	pulled++;
+	rem_load_move -= tmp->load_weight;
 
-	/* We only want to steal up to the prescribed number of tasks. */
-	if (pulled < max_nr_move) {
+	/*
+	 * We only want to steal up to the prescribed number of tasks
+	 * and the prescribed amount of weighted load.
+	 */
+	if (pulled < max_nr_move && rem_load_move > 0) {
+		if (idx < this_best_prio)
+			this_best_prio = idx;
 		if (curr != head)
 			goto skip_queue;
 		idx++;
@@ -1944,7 +2146,7 @@
 
 /*
  * find_busiest_group finds and returns the busiest CPU group within the
- * domain. It calculates and returns the number of tasks which should be
+ * domain. It calculates and returns the amount of weighted load which should be
  * moved to restore balance via the imbalance parameter.
  */
 static struct sched_group *
@@ -1954,9 +2156,19 @@
 	struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
 	unsigned long max_load, avg_load, total_load, this_load, total_pwr;
 	unsigned long max_pull;
+	unsigned long busiest_load_per_task, busiest_nr_running;
+	unsigned long this_load_per_task, this_nr_running;
 	int load_idx;
+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+	int power_savings_balance = 1;
+	unsigned long leader_nr_running = 0, min_load_per_task = 0;
+	unsigned long min_nr_running = ULONG_MAX;
+	struct sched_group *group_min = NULL, *group_leader = NULL;
+#endif
 
 	max_load = this_load = total_load = total_pwr = 0;
+	busiest_load_per_task = busiest_nr_running = 0;
+	this_load_per_task = this_nr_running = 0;
 	if (idle == NOT_IDLE)
 		load_idx = sd->busy_idx;
 	else if (idle == NEWLY_IDLE)
@@ -1965,16 +2177,19 @@
 		load_idx = sd->idle_idx;
 
 	do {
-		unsigned long load;
+		unsigned long load, group_capacity;
 		int local_group;
 		int i;
+		unsigned long sum_nr_running, sum_weighted_load;
 
 		local_group = cpu_isset(this_cpu, group->cpumask);
 
 		/* Tally up the load of all CPUs in the group */
-		avg_load = 0;
+		sum_weighted_load = sum_nr_running = avg_load = 0;
 
 		for_each_cpu_mask(i, group->cpumask) {
+			runqueue_t *rq = cpu_rq(i);
+
 			if (*sd_idle && !idle_cpu(i))
 				*sd_idle = 0;
 
@@ -1985,6 +2200,8 @@
 				load = source_load(i, load_idx);
 
 			avg_load += load;
+			sum_nr_running += rq->nr_running;
+			sum_weighted_load += rq->raw_weighted_load;
 		}
 
 		total_load += avg_load;
@@ -1993,17 +2210,80 @@
 		/* Adjust by relative CPU power of the group */
 		avg_load = (avg_load * SCHED_LOAD_SCALE) / group->cpu_power;
 
+		group_capacity = group->cpu_power / SCHED_LOAD_SCALE;
+
 		if (local_group) {
 			this_load = avg_load;
 			this = group;
-		} else if (avg_load > max_load) {
+			this_nr_running = sum_nr_running;
+			this_load_per_task = sum_weighted_load;
+		} else if (avg_load > max_load &&
+			   sum_nr_running > group_capacity) {
 			max_load = avg_load;
 			busiest = group;
+			busiest_nr_running = sum_nr_running;
+			busiest_load_per_task = sum_weighted_load;
 		}
+
+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+		/*
+		 * Busy processors will not participate in power savings
+		 * balance.
+		 */
+ 		if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
+ 			goto group_next;
+
+		/*
+		 * If the local group is idle or completely loaded
+		 * no need to do power savings balance at this domain
+		 */
+		if (local_group && (this_nr_running >= group_capacity ||
+				    !this_nr_running))
+			power_savings_balance = 0;
+
+ 		/*
+		 * If a group is already running at full capacity or idle,
+		 * don't include that group in power savings calculations
+ 		 */
+ 		if (!power_savings_balance || sum_nr_running >= group_capacity
+		    || !sum_nr_running)
+ 			goto group_next;
+
+ 		/*
+		 * Calculate the group which has the least non-idle load.
+ 		 * This is the group from where we need to pick up the load
+ 		 * for saving power
+ 		 */
+ 		if ((sum_nr_running < min_nr_running) ||
+ 		    (sum_nr_running == min_nr_running &&
+		     first_cpu(group->cpumask) <
+		     first_cpu(group_min->cpumask))) {
+ 			group_min = group;
+ 			min_nr_running = sum_nr_running;
+			min_load_per_task = sum_weighted_load /
+						sum_nr_running;
+ 		}
+
+ 		/*
+		 * Calculate the group which is almost near its
+ 		 * capacity but still has some space to pick up some load
+ 		 * from other group and save more power
+ 		 */
+ 		if (sum_nr_running <= group_capacity - 1)
+ 			if (sum_nr_running > leader_nr_running ||
+ 			    (sum_nr_running == leader_nr_running &&
+ 			     first_cpu(group->cpumask) >
+ 			      first_cpu(group_leader->cpumask))) {
+ 				group_leader = group;
+ 				leader_nr_running = sum_nr_running;
+ 			}
+
+group_next:
+#endif
 		group = group->next;
 	} while (group != sd->groups);
 
-	if (!busiest || this_load >= max_load || max_load <= SCHED_LOAD_SCALE)
+	if (!busiest || this_load >= max_load || busiest_nr_running == 0)
 		goto out_balanced;
 
 	avg_load = (SCHED_LOAD_SCALE * total_load) / total_pwr;
@@ -2012,6 +2292,7 @@
 			100*max_load <= sd->imbalance_pct*this_load)
 		goto out_balanced;
 
+	busiest_load_per_task /= busiest_nr_running;
 	/*
 	 * We're trying to get all the cpus to the average_load, so we don't
 	 * want to push ourselves above the average load, nor do we wish to
@@ -2023,21 +2304,50 @@
 	 * by pulling tasks to us.  Be careful of negative numbers as they'll
 	 * appear as very large values with unsigned longs.
 	 */
+	if (max_load <= busiest_load_per_task)
+		goto out_balanced;
+
+	/*
+	 * In the presence of smp nice balancing, certain scenarios can have
+	 * max load less than avg load(as we skip the groups at or below
+	 * its cpu_power, while calculating max_load..)
+	 */
+	if (max_load < avg_load) {
+		*imbalance = 0;
+		goto small_imbalance;
+	}
 
 	/* Don't want to pull so many tasks that a group would go idle */
-	max_pull = min(max_load - avg_load, max_load - SCHED_LOAD_SCALE);
+	max_pull = min(max_load - avg_load, max_load - busiest_load_per_task);
 
 	/* How much load to actually move to equalise the imbalance */
 	*imbalance = min(max_pull * busiest->cpu_power,
 				(avg_load - this_load) * this->cpu_power)
 			/ SCHED_LOAD_SCALE;
 
-	if (*imbalance < SCHED_LOAD_SCALE) {
-		unsigned long pwr_now = 0, pwr_move = 0;
+	/*
+	 * if *imbalance is less than the average load per runnable task
+	 * there is no gaurantee that any tasks will be moved so we'll have
+	 * a think about bumping its value to force at least one task to be
+	 * moved
+	 */
+	if (*imbalance < busiest_load_per_task) {
+		unsigned long pwr_now, pwr_move;
 		unsigned long tmp;
+		unsigned int imbn;
 
-		if (max_load - this_load >= SCHED_LOAD_SCALE*2) {
-			*imbalance = 1;
+small_imbalance:
+		pwr_move = pwr_now = 0;
+		imbn = 2;
+		if (this_nr_running) {
+			this_load_per_task /= this_nr_running;
+			if (busiest_load_per_task > this_load_per_task)
+				imbn = 1;
+		} else
+			this_load_per_task = SCHED_LOAD_SCALE;
+
+		if (max_load - this_load >= busiest_load_per_task * imbn) {
+			*imbalance = busiest_load_per_task;
 			return busiest;
 		}
 
@@ -2047,39 +2357,47 @@
 		 * moving them.
 		 */
 
-		pwr_now += busiest->cpu_power*min(SCHED_LOAD_SCALE, max_load);
-		pwr_now += this->cpu_power*min(SCHED_LOAD_SCALE, this_load);
+		pwr_now += busiest->cpu_power *
+			min(busiest_load_per_task, max_load);
+		pwr_now += this->cpu_power *
+			min(this_load_per_task, this_load);
 		pwr_now /= SCHED_LOAD_SCALE;
 
 		/* Amount of load we'd subtract */
-		tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/busiest->cpu_power;
+		tmp = busiest_load_per_task*SCHED_LOAD_SCALE/busiest->cpu_power;
 		if (max_load > tmp)
-			pwr_move += busiest->cpu_power*min(SCHED_LOAD_SCALE,
-							max_load - tmp);
+			pwr_move += busiest->cpu_power *
+				min(busiest_load_per_task, max_load - tmp);
 
 		/* Amount of load we'd add */
 		if (max_load*busiest->cpu_power <
-				SCHED_LOAD_SCALE*SCHED_LOAD_SCALE)
+				busiest_load_per_task*SCHED_LOAD_SCALE)
 			tmp = max_load*busiest->cpu_power/this->cpu_power;
 		else
-			tmp = SCHED_LOAD_SCALE*SCHED_LOAD_SCALE/this->cpu_power;
-		pwr_move += this->cpu_power*min(SCHED_LOAD_SCALE, this_load + tmp);
+			tmp = busiest_load_per_task*SCHED_LOAD_SCALE/this->cpu_power;
+		pwr_move += this->cpu_power*min(this_load_per_task, this_load + tmp);
 		pwr_move /= SCHED_LOAD_SCALE;
 
 		/* Move if we gain throughput */
 		if (pwr_move <= pwr_now)
 			goto out_balanced;
 
-		*imbalance = 1;
-		return busiest;
+		*imbalance = busiest_load_per_task;
 	}
 
-	/* Get rid of the scaling factor, rounding down as we divide */
-	*imbalance = *imbalance / SCHED_LOAD_SCALE;
 	return busiest;
 
 out_balanced:
+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+	if (idle == NOT_IDLE || !(sd->flags & SD_POWERSAVINGS_BALANCE))
+		goto ret;
 
+	if (this == group_leader && group_leader != group_min) {
+		*imbalance = min_load_per_task;
+		return group_min;
+	}
+ret:
+#endif
 	*imbalance = 0;
 	return NULL;
 }
@@ -2088,18 +2406,21 @@
  * find_busiest_queue - find the busiest runqueue among the cpus in group.
  */
 static runqueue_t *find_busiest_queue(struct sched_group *group,
-	enum idle_type idle)
+	enum idle_type idle, unsigned long imbalance)
 {
-	unsigned long load, max_load = 0;
-	runqueue_t *busiest = NULL;
+	unsigned long max_load = 0;
+	runqueue_t *busiest = NULL, *rqi;
 	int i;
 
 	for_each_cpu_mask(i, group->cpumask) {
-		load = source_load(i, 0);
+		rqi = cpu_rq(i);
 
-		if (load > max_load) {
-			max_load = load;
-			busiest = cpu_rq(i);
+		if (rqi->nr_running == 1 && rqi->raw_weighted_load > imbalance)
+			continue;
+
+		if (rqi->raw_weighted_load > max_load) {
+			max_load = rqi->raw_weighted_load;
+			busiest = rqi;
 		}
 	}
 
@@ -2112,6 +2433,7 @@
  */
 #define MAX_PINNED_INTERVAL	512
 
+#define minus_1_or_zero(n) ((n) > 0 ? (n) - 1 : 0)
 /*
  * Check this_cpu to ensure it is balanced within domain. Attempt to move
  * tasks if there is an imbalance.
@@ -2128,7 +2450,8 @@
 	int active_balance = 0;
 	int sd_idle = 0;
 
-	if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER)
+	if (idle != NOT_IDLE && sd->flags & SD_SHARE_CPUPOWER &&
+	    !sched_smt_power_savings)
 		sd_idle = 1;
 
 	schedstat_inc(sd, lb_cnt[idle]);
@@ -2139,7 +2462,7 @@
 		goto out_balanced;
 	}
 
-	busiest = find_busiest_queue(group, idle);
+	busiest = find_busiest_queue(group, idle, imbalance);
 	if (!busiest) {
 		schedstat_inc(sd, lb_nobusyq[idle]);
 		goto out_balanced;
@@ -2159,6 +2482,7 @@
 		 */
 		double_rq_lock(this_rq, busiest);
 		nr_moved = move_tasks(this_rq, this_cpu, busiest,
+					minus_1_or_zero(busiest->nr_running),
 					imbalance, sd, idle, &all_pinned);
 		double_rq_unlock(this_rq, busiest);
 
@@ -2216,7 +2540,8 @@
 			sd->balance_interval *= 2;
 	}
 
-	if (!nr_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+	if (!nr_moved && !sd_idle && sd->flags & SD_SHARE_CPUPOWER &&
+	    !sched_smt_power_savings)
 		return -1;
 	return nr_moved;
 
@@ -2231,7 +2556,7 @@
 			(sd->balance_interval < sd->max_interval))
 		sd->balance_interval *= 2;
 
-	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER && !sched_smt_power_savings)
 		return -1;
 	return 0;
 }
@@ -2252,7 +2577,7 @@
 	int nr_moved = 0;
 	int sd_idle = 0;
 
-	if (sd->flags & SD_SHARE_CPUPOWER)
+	if (sd->flags & SD_SHARE_CPUPOWER && !sched_smt_power_savings)
 		sd_idle = 1;
 
 	schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
@@ -2262,7 +2587,7 @@
 		goto out_balanced;
 	}
 
-	busiest = find_busiest_queue(group, NEWLY_IDLE);
+	busiest = find_busiest_queue(group, NEWLY_IDLE, imbalance);
 	if (!busiest) {
 		schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
 		goto out_balanced;
@@ -2277,6 +2602,7 @@
 		/* Attempt to move tasks */
 		double_lock_balance(this_rq, busiest);
 		nr_moved = move_tasks(this_rq, this_cpu, busiest,
+					minus_1_or_zero(busiest->nr_running),
 					imbalance, sd, NEWLY_IDLE, NULL);
 		spin_unlock(&busiest->lock);
 	}
@@ -2292,7 +2618,7 @@
 
 out_balanced:
 	schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
-	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER)
+	if (!sd_idle && sd->flags & SD_SHARE_CPUPOWER && !sched_smt_power_savings)
 		return -1;
 	sd->nr_balance_failed = 0;
 	return 0;
@@ -2347,17 +2673,19 @@
 	double_lock_balance(busiest_rq, target_rq);
 
 	/* Search for an sd spanning us and the target CPU. */
-	for_each_domain(target_cpu, sd)
+	for_each_domain(target_cpu, sd) {
 		if ((sd->flags & SD_LOAD_BALANCE) &&
 			cpu_isset(busiest_cpu, sd->span))
 				break;
+	}
 
 	if (unlikely(sd == NULL))
 		goto out;
 
 	schedstat_inc(sd, alb_cnt);
 
-	if (move_tasks(target_rq, target_cpu, busiest_rq, 1, sd, SCHED_IDLE, NULL))
+	if (move_tasks(target_rq, target_cpu, busiest_rq, 1,
+			RTPRIO_TO_LOAD_WEIGHT(100), sd, SCHED_IDLE, NULL))
 		schedstat_inc(sd, alb_pushed);
 	else
 		schedstat_inc(sd, alb_failed);
@@ -2385,7 +2713,7 @@
 	struct sched_domain *sd;
 	int i;
 
-	this_load = this_rq->nr_running * SCHED_LOAD_SCALE;
+	this_load = this_rq->raw_weighted_load;
 	/* Update our load */
 	for (i = 0; i < 3; i++) {
 		unsigned long new_load = this_load;
@@ -2686,48 +3014,35 @@
 		resched_task(rq->idle);
 }
 
-static void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
+/*
+ * Called with interrupt disabled and this_rq's runqueue locked.
+ */
+static void wake_sleeping_dependent(int this_cpu)
 {
 	struct sched_domain *tmp, *sd = NULL;
-	cpumask_t sibling_map;
 	int i;
 
-	for_each_domain(this_cpu, tmp)
-		if (tmp->flags & SD_SHARE_CPUPOWER)
+	for_each_domain(this_cpu, tmp) {
+		if (tmp->flags & SD_SHARE_CPUPOWER) {
 			sd = tmp;
+			break;
+		}
+	}
 
 	if (!sd)
 		return;
 
-	/*
-	 * Unlock the current runqueue because we have to lock in
-	 * CPU order to avoid deadlocks. Caller knows that we might
-	 * unlock. We keep IRQs disabled.
-	 */
-	spin_unlock(&this_rq->lock);
-
-	sibling_map = sd->span;
-
-	for_each_cpu_mask(i, sibling_map)
-		spin_lock(&cpu_rq(i)->lock);
-	/*
-	 * We clear this CPU from the mask. This both simplifies the
-	 * inner loop and keps this_rq locked when we exit:
-	 */
-	cpu_clear(this_cpu, sibling_map);
-
-	for_each_cpu_mask(i, sibling_map) {
+	for_each_cpu_mask(i, sd->span) {
 		runqueue_t *smt_rq = cpu_rq(i);
 
-		wakeup_busy_runqueue(smt_rq);
-	}
+		if (i == this_cpu)
+			continue;
+		if (unlikely(!spin_trylock(&smt_rq->lock)))
+			continue;
 
-	for_each_cpu_mask(i, sibling_map)
-		spin_unlock(&cpu_rq(i)->lock);
-	/*
-	 * We exit with this_cpu's rq still held and IRQs
-	 * still disabled:
-	 */
+		wakeup_busy_runqueue(smt_rq);
+		spin_unlock(&smt_rq->lock);
+	}
 }
 
 /*
@@ -2740,52 +3055,46 @@
 	return p->time_slice * (100 - sd->per_cpu_gain) / 100;
 }
 
-static int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
+/*
+ * To minimise lock contention and not have to drop this_rq's runlock we only
+ * trylock the sibling runqueues and bypass those runqueues if we fail to
+ * acquire their lock. As we only trylock the normal locking order does not
+ * need to be obeyed.
+ */
+static int dependent_sleeper(int this_cpu, runqueue_t *this_rq, task_t *p)
 {
 	struct sched_domain *tmp, *sd = NULL;
-	cpumask_t sibling_map;
-	prio_array_t *array;
 	int ret = 0, i;
-	task_t *p;
 
-	for_each_domain(this_cpu, tmp)
-		if (tmp->flags & SD_SHARE_CPUPOWER)
+	/* kernel/rt threads do not participate in dependent sleeping */
+	if (!p->mm || rt_task(p))
+		return 0;
+
+	for_each_domain(this_cpu, tmp) {
+		if (tmp->flags & SD_SHARE_CPUPOWER) {
 			sd = tmp;
+			break;
+		}
+	}
 
 	if (!sd)
 		return 0;
 
-	/*
-	 * The same locking rules and details apply as for
-	 * wake_sleeping_dependent():
-	 */
-	spin_unlock(&this_rq->lock);
-	sibling_map = sd->span;
-	for_each_cpu_mask(i, sibling_map)
-		spin_lock(&cpu_rq(i)->lock);
-	cpu_clear(this_cpu, sibling_map);
+	for_each_cpu_mask(i, sd->span) {
+		runqueue_t *smt_rq;
+		task_t *smt_curr;
 
-	/*
-	 * Establish next task to be run - it might have gone away because
-	 * we released the runqueue lock above:
-	 */
-	if (!this_rq->nr_running)
-		goto out_unlock;
-	array = this_rq->active;
-	if (!array->nr_active)
-		array = this_rq->expired;
-	BUG_ON(!array->nr_active);
+		if (i == this_cpu)
+			continue;
 
-	p = list_entry(array->queue[sched_find_first_bit(array->bitmap)].next,
-		task_t, run_list);
+		smt_rq = cpu_rq(i);
+		if (unlikely(!spin_trylock(&smt_rq->lock)))
+			continue;
 
-	for_each_cpu_mask(i, sibling_map) {
-		runqueue_t *smt_rq = cpu_rq(i);
-		task_t *smt_curr = smt_rq->curr;
+		smt_curr = smt_rq->curr;
 
-		/* Kernel threads do not participate in dependent sleeping */
-		if (!p->mm || !smt_curr->mm || rt_task(p))
-			goto check_smt_task;
+		if (!smt_curr->mm)
+			goto unlock;
 
 		/*
 		 * If a user task with lower static priority than the
@@ -2803,49 +3112,24 @@
 			if ((jiffies % DEF_TIMESLICE) >
 				(sd->per_cpu_gain * DEF_TIMESLICE / 100))
 					ret = 1;
-		} else
+		} else {
 			if (smt_curr->static_prio < p->static_prio &&
 				!TASK_PREEMPTS_CURR(p, smt_rq) &&
 				smt_slice(smt_curr, sd) > task_timeslice(p))
 					ret = 1;
-
-check_smt_task:
-		if ((!smt_curr->mm && smt_curr != smt_rq->idle) ||
-			rt_task(smt_curr))
-				continue;
-		if (!p->mm) {
-			wakeup_busy_runqueue(smt_rq);
-			continue;
 		}
-
-		/*
-		 * Reschedule a lower priority task on the SMT sibling for
-		 * it to be put to sleep, or wake it up if it has been put to
-		 * sleep for priority reasons to see if it should run now.
-		 */
-		if (rt_task(p)) {
-			if ((jiffies % DEF_TIMESLICE) >
-				(sd->per_cpu_gain * DEF_TIMESLICE / 100))
-					resched_task(smt_curr);
-		} else {
-			if (TASK_PREEMPTS_CURR(p, smt_rq) &&
-				smt_slice(p, sd) > task_timeslice(smt_curr))
-					resched_task(smt_curr);
-			else
-				wakeup_busy_runqueue(smt_rq);
-		}
+unlock:
+		spin_unlock(&smt_rq->lock);
 	}
-out_unlock:
-	for_each_cpu_mask(i, sibling_map)
-		spin_unlock(&cpu_rq(i)->lock);
 	return ret;
 }
 #else
-static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
+static inline void wake_sleeping_dependent(int this_cpu)
 {
 }
 
-static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
+static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq,
+					task_t *p)
 {
 	return 0;
 }
@@ -2967,32 +3251,13 @@
 
 	cpu = smp_processor_id();
 	if (unlikely(!rq->nr_running)) {
-go_idle:
 		idle_balance(cpu, rq);
 		if (!rq->nr_running) {
 			next = rq->idle;
 			rq->expired_timestamp = 0;
-			wake_sleeping_dependent(cpu, rq);
-			/*
-			 * wake_sleeping_dependent() might have released
-			 * the runqueue, so break out if we got new
-			 * tasks meanwhile:
-			 */
-			if (!rq->nr_running)
-				goto switch_tasks;
-		}
-	} else {
-		if (dependent_sleeper(cpu, rq)) {
-			next = rq->idle;
+			wake_sleeping_dependent(cpu);
 			goto switch_tasks;
 		}
-		/*
-		 * dependent_sleeper() releases and reacquires the runqueue
-		 * lock, hence go into the idle loop if the rq went
-		 * empty meanwhile:
-		 */
-		if (unlikely(!rq->nr_running))
-			goto go_idle;
 	}
 
 	array = rq->active;
@@ -3030,6 +3295,8 @@
 		}
 	}
 	next->sleep_type = SLEEP_NORMAL;
+	if (dependent_sleeper(cpu, rq, next))
+		next = rq->idle;
 switch_tasks:
 	if (next == rq->idle)
 		schedstat_inc(rq, sched_goidle);
@@ -3473,12 +3740,65 @@
 
 EXPORT_SYMBOL(sleep_on_timeout);
 
+#ifdef CONFIG_RT_MUTEXES
+
+/*
+ * rt_mutex_setprio - set the current priority of a task
+ * @p: task
+ * @prio: prio value (kernel-internal form)
+ *
+ * This function changes the 'effective' priority of a task. It does
+ * not touch ->normal_prio like __setscheduler().
+ *
+ * Used by the rt_mutex code to implement priority inheritance logic.
+ */
+void rt_mutex_setprio(task_t *p, int prio)
+{
+	unsigned long flags;
+	prio_array_t *array;
+	runqueue_t *rq;
+	int oldprio;
+
+	BUG_ON(prio < 0 || prio > MAX_PRIO);
+
+	rq = task_rq_lock(p, &flags);
+
+	oldprio = p->prio;
+	array = p->array;
+	if (array)
+		dequeue_task(p, array);
+	p->prio = prio;
+
+	if (array) {
+		/*
+		 * If changing to an RT priority then queue it
+		 * in the active array!
+		 */
+		if (rt_task(p))
+			array = rq->active;
+		enqueue_task(p, array);
+		/*
+		 * Reschedule if we are currently running on this runqueue and
+		 * our priority decreased, or if we are not currently running on
+		 * this runqueue and our priority is higher than the current's
+		 */
+		if (task_running(rq, p)) {
+			if (p->prio > oldprio)
+				resched_task(rq->curr);
+		} else if (TASK_PREEMPTS_CURR(p, rq))
+			resched_task(rq->curr);
+	}
+	task_rq_unlock(rq, &flags);
+}
+
+#endif
+
 void set_user_nice(task_t *p, long nice)
 {
 	unsigned long flags;
 	prio_array_t *array;
 	runqueue_t *rq;
-	int old_prio, new_prio, delta;
+	int old_prio, delta;
 
 	if (TASK_NICE(p) == nice || nice < -20 || nice > 19)
 		return;
@@ -3493,22 +3813,25 @@
 	 * it wont have any effect on scheduling until the task is
 	 * not SCHED_NORMAL/SCHED_BATCH:
 	 */
-	if (rt_task(p)) {
+	if (has_rt_policy(p)) {
 		p->static_prio = NICE_TO_PRIO(nice);
 		goto out_unlock;
 	}
 	array = p->array;
-	if (array)
+	if (array) {
 		dequeue_task(p, array);
+		dec_raw_weighted_load(rq, p);
+	}
 
-	old_prio = p->prio;
-	new_prio = NICE_TO_PRIO(nice);
-	delta = new_prio - old_prio;
 	p->static_prio = NICE_TO_PRIO(nice);
-	p->prio += delta;
+	set_load_weight(p);
+	old_prio = p->prio;
+	p->prio = effective_prio(p);
+	delta = p->prio - old_prio;
 
 	if (array) {
 		enqueue_task(p, array);
+		inc_raw_weighted_load(rq, p);
 		/*
 		 * If the task increased its priority or is running and
 		 * lowered its priority, then reschedule its CPU:
@@ -3519,7 +3842,6 @@
 out_unlock:
 	task_rq_unlock(rq, &flags);
 }
-
 EXPORT_SYMBOL(set_user_nice);
 
 /*
@@ -3634,16 +3956,15 @@
 	BUG_ON(p->array);
 	p->policy = policy;
 	p->rt_priority = prio;
-	if (policy != SCHED_NORMAL && policy != SCHED_BATCH) {
-		p->prio = MAX_RT_PRIO-1 - p->rt_priority;
-	} else {
-		p->prio = p->static_prio;
-		/*
-		 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
-		 */
-		if (policy == SCHED_BATCH)
-			p->sleep_avg = 0;
-	}
+	p->normal_prio = normal_prio(p);
+	/* we are holding p->pi_lock already */
+	p->prio = rt_mutex_getprio(p);
+	/*
+	 * SCHED_BATCH tasks are treated as perpetual CPU hogs:
+	 */
+	if (policy == SCHED_BATCH)
+		p->sleep_avg = 0;
+	set_load_weight(p);
 }
 
 /**
@@ -3662,6 +3983,8 @@
 	unsigned long flags;
 	runqueue_t *rq;
 
+	/* may grab non-irq protected spin_locks */
+	BUG_ON(in_interrupt());
 recheck:
 	/* double check policy once rq lock held */
 	if (policy < 0)
@@ -3710,14 +4033,20 @@
 	if (retval)
 		return retval;
 	/*
+	 * make sure no PI-waiters arrive (or leave) while we are
+	 * changing the priority of the task:
+	 */
+	spin_lock_irqsave(&p->pi_lock, flags);
+	/*
 	 * To be able to change p->policy safely, the apropriate
 	 * runqueue lock must be held.
 	 */
-	rq = task_rq_lock(p, &flags);
+	rq = __task_rq_lock(p);
 	/* recheck policy now with rq lock held */
 	if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
 		policy = oldpolicy = -1;
-		task_rq_unlock(rq, &flags);
+		__task_rq_unlock(rq);
+		spin_unlock_irqrestore(&p->pi_lock, flags);
 		goto recheck;
 	}
 	array = p->array;
@@ -3738,7 +4067,11 @@
 		} else if (TASK_PREEMPTS_CURR(p, rq))
 			resched_task(rq->curr);
 	}
-	task_rq_unlock(rq, &flags);
+	__task_rq_unlock(rq);
+	spin_unlock_irqrestore(&p->pi_lock, flags);
+
+	rt_mutex_adjust_pi(p);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(sched_setscheduler);
@@ -3760,8 +4093,10 @@
 		read_unlock_irq(&tasklist_lock);
 		return -ESRCH;
 	}
-	retval = sched_setscheduler(p, policy, &lparam);
+	get_task_struct(p);
 	read_unlock_irq(&tasklist_lock);
+	retval = sched_setscheduler(p, policy, &lparam);
+	put_task_struct(p);
 	return retval;
 }
 
@@ -3886,6 +4221,10 @@
 			!capable(CAP_SYS_NICE))
 		goto out_unlock;
 
+	retval = security_task_setscheduler(p, 0, NULL);
+	if (retval)
+		goto out_unlock;
+
 	cpus_allowed = cpuset_cpus_allowed(p);
 	cpus_and(new_mask, new_mask, cpus_allowed);
 	retval = set_cpus_allowed(p, new_mask);
@@ -3954,7 +4293,10 @@
 	if (!p)
 		goto out_unlock;
 
-	retval = 0;
+	retval = security_task_getscheduler(p);
+	if (retval)
+		goto out_unlock;
+
 	cpus_and(*mask, p->cpus_allowed, cpu_online_map);
 
 out_unlock:
@@ -4046,6 +4388,9 @@
 
 static inline void __cond_resched(void)
 {
+#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
+	__might_sleep(__FILE__, __LINE__);
+#endif
 	/*
 	 * The BKS might be reacquired before we have dropped
 	 * PREEMPT_ACTIVE, which could trigger a second
@@ -4142,7 +4487,7 @@
  */
 void __sched io_schedule(void)
 {
-	struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
+	struct runqueue *rq = &__raw_get_cpu_var(runqueues);
 
 	atomic_inc(&rq->nr_iowait);
 	schedule();
@@ -4153,7 +4498,7 @@
 
 long __sched io_schedule_timeout(long timeout)
 {
-	struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
+	struct runqueue *rq = &__raw_get_cpu_var(runqueues);
 	long ret;
 
 	atomic_inc(&rq->nr_iowait);
@@ -4237,7 +4582,7 @@
 	if (retval)
 		goto out_unlock;
 
-	jiffies_to_timespec(p->policy & SCHED_FIFO ?
+	jiffies_to_timespec(p->policy == SCHED_FIFO ?
 				0 : task_timeslice(p), &t);
 	read_unlock(&tasklist_lock);
 	retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
@@ -4363,7 +4708,7 @@
 	idle->timestamp = sched_clock();
 	idle->sleep_avg = 0;
 	idle->array = NULL;
-	idle->prio = MAX_PRIO;
+	idle->prio = idle->normal_prio = MAX_PRIO;
 	idle->state = TASK_RUNNING;
 	idle->cpus_allowed = cpumask_of_cpu(cpu);
 	set_task_cpu(idle, cpu);
@@ -4459,13 +4804,16 @@
  *
  * So we race with normal scheduler movements, but that's OK, as long
  * as the task is no longer on this CPU.
+ *
+ * Returns non-zero if task was successfully migrated.
  */
-static void __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
+static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
 	runqueue_t *rq_dest, *rq_src;
+	int ret = 0;
 
 	if (unlikely(cpu_is_offline(dest_cpu)))
-		return;
+		return ret;
 
 	rq_src = cpu_rq(src_cpu);
 	rq_dest = cpu_rq(dest_cpu);
@@ -4493,9 +4841,10 @@
 		if (TASK_PREEMPTS_CURR(p, rq_dest))
 			resched_task(rq_dest->curr);
 	}
-
+	ret = 1;
 out:
 	double_rq_unlock(rq_src, rq_dest);
+	return ret;
 }
 
 /*
@@ -4565,9 +4914,12 @@
 /* Figure out where task on dead CPU should go, use force if neccessary. */
 static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk)
 {
+	runqueue_t *rq;
+	unsigned long flags;
 	int dest_cpu;
 	cpumask_t mask;
 
+restart:
 	/* On same node? */
 	mask = node_to_cpumask(cpu_to_node(dead_cpu));
 	cpus_and(mask, mask, tsk->cpus_allowed);
@@ -4579,8 +4931,10 @@
 
 	/* No more Mr. Nice Guy. */
 	if (dest_cpu == NR_CPUS) {
+		rq = task_rq_lock(tsk, &flags);
 		cpus_setall(tsk->cpus_allowed);
 		dest_cpu = any_online_cpu(tsk->cpus_allowed);
+		task_rq_unlock(rq, &flags);
 
 		/*
 		 * Don't tell them about moving exiting tasks or
@@ -4592,7 +4946,8 @@
 			       "longer affine to cpu%d\n",
 			       tsk->pid, tsk->comm, dead_cpu);
 	}
-	__migrate_task(tsk, dead_cpu, dest_cpu);
+	if (!__migrate_task(tsk, dead_cpu, dest_cpu))
+		goto restart;
 }
 
 /*
@@ -4719,8 +5074,9 @@
  * migration_call - callback that gets triggered when a CPU is added.
  * Here we can start up the necessary migration thread for the new CPU.
  */
-static int migration_call(struct notifier_block *nfb, unsigned long action,
-			  void *hcpu)
+static int __cpuinit migration_call(struct notifier_block *nfb,
+			unsigned long action,
+			void *hcpu)
 {
 	int cpu = (long)hcpu;
 	struct task_struct *p;
@@ -4746,6 +5102,8 @@
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_UP_CANCELED:
+		if (!cpu_rq(cpu)->migration_thread)
+			break;
 		/* Unbind it from offline cpu so it can run.  Fall thru. */
 		kthread_bind(cpu_rq(cpu)->migration_thread,
 			     any_online_cpu(cpu_online_map));
@@ -4788,7 +5146,7 @@
 /* Register at highest priority so that task migration (migrate_all_tasks)
  * happens before everything else.
  */
-static struct notifier_block migration_notifier = {
+static struct notifier_block __cpuinitdata migration_notifier = {
 	.notifier_call = migration_call,
 	.priority = 10
 };
@@ -5589,6 +5947,7 @@
 }
 #endif
 
+int sched_smt_power_savings = 0, sched_mc_power_savings = 0;
 /*
  * At the moment, CONFIG_SCHED_SMT is never defined, but leave it in so we
  * can switch it on easily if needed.
@@ -5604,7 +5963,7 @@
 
 #ifdef CONFIG_SCHED_MC
 static DEFINE_PER_CPU(struct sched_domain, core_domains);
-static struct sched_group sched_group_core[NR_CPUS];
+static struct sched_group *sched_group_core_bycpu[NR_CPUS];
 #endif
 
 #if defined(CONFIG_SCHED_MC) && defined(CONFIG_SCHED_SMT)
@@ -5620,7 +5979,7 @@
 #endif
 
 static DEFINE_PER_CPU(struct sched_domain, phys_domains);
-static struct sched_group sched_group_phys[NR_CPUS];
+static struct sched_group *sched_group_phys_bycpu[NR_CPUS];
 static int cpu_to_phys_group(int cpu)
 {
 #if defined(CONFIG_SCHED_MC)
@@ -5677,13 +6036,74 @@
 }
 #endif
 
+/* Free memory allocated for various sched_group structures */
+static void free_sched_groups(const cpumask_t *cpu_map)
+{
+	int cpu;
+#ifdef CONFIG_NUMA
+	int i;
+
+	for_each_cpu_mask(cpu, *cpu_map) {
+		struct sched_group *sched_group_allnodes
+			= sched_group_allnodes_bycpu[cpu];
+		struct sched_group **sched_group_nodes
+			= sched_group_nodes_bycpu[cpu];
+
+		if (sched_group_allnodes) {
+			kfree(sched_group_allnodes);
+			sched_group_allnodes_bycpu[cpu] = NULL;
+		}
+
+		if (!sched_group_nodes)
+			continue;
+
+		for (i = 0; i < MAX_NUMNODES; i++) {
+			cpumask_t nodemask = node_to_cpumask(i);
+			struct sched_group *oldsg, *sg = sched_group_nodes[i];
+
+			cpus_and(nodemask, nodemask, *cpu_map);
+			if (cpus_empty(nodemask))
+				continue;
+
+			if (sg == NULL)
+				continue;
+			sg = sg->next;
+next_sg:
+			oldsg = sg;
+			sg = sg->next;
+			kfree(oldsg);
+			if (oldsg != sched_group_nodes[i])
+				goto next_sg;
+		}
+		kfree(sched_group_nodes);
+		sched_group_nodes_bycpu[cpu] = NULL;
+	}
+#endif
+	for_each_cpu_mask(cpu, *cpu_map) {
+		if (sched_group_phys_bycpu[cpu]) {
+			kfree(sched_group_phys_bycpu[cpu]);
+			sched_group_phys_bycpu[cpu] = NULL;
+		}
+#ifdef CONFIG_SCHED_MC
+		if (sched_group_core_bycpu[cpu]) {
+			kfree(sched_group_core_bycpu[cpu]);
+			sched_group_core_bycpu[cpu] = NULL;
+		}
+#endif
+	}
+}
+
 /*
  * Build sched domains for a given set of cpus and attach the sched domains
  * to the individual cpus
  */
-void build_sched_domains(const cpumask_t *cpu_map)
+static int build_sched_domains(const cpumask_t *cpu_map)
 {
 	int i;
+	struct sched_group *sched_group_phys = NULL;
+#ifdef CONFIG_SCHED_MC
+	struct sched_group *sched_group_core = NULL;
+#endif
 #ifdef CONFIG_NUMA
 	struct sched_group **sched_group_nodes = NULL;
 	struct sched_group *sched_group_allnodes = NULL;
@@ -5691,11 +6111,11 @@
 	/*
 	 * Allocate the per-node list of sched groups
 	 */
-	sched_group_nodes = kmalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
-					   GFP_ATOMIC);
+	sched_group_nodes = kzalloc(sizeof(struct sched_group*)*MAX_NUMNODES,
+					   GFP_KERNEL);
 	if (!sched_group_nodes) {
 		printk(KERN_WARNING "Can not alloc sched group node list\n");
-		return;
+		return -ENOMEM;
 	}
 	sched_group_nodes_bycpu[first_cpu(*cpu_map)] = sched_group_nodes;
 #endif
@@ -5721,7 +6141,7 @@
 				if (!sched_group_allnodes) {
 					printk(KERN_WARNING
 					"Can not alloc allnodes sched group\n");
-					break;
+					goto error;
 				}
 				sched_group_allnodes_bycpu[i]
 						= sched_group_allnodes;
@@ -5742,6 +6162,18 @@
 		cpus_and(sd->span, sd->span, *cpu_map);
 #endif
 
+		if (!sched_group_phys) {
+			sched_group_phys
+				= kmalloc(sizeof(struct sched_group) * NR_CPUS,
+					  GFP_KERNEL);
+			if (!sched_group_phys) {
+				printk (KERN_WARNING "Can not alloc phys sched"
+						     "group\n");
+				goto error;
+			}
+			sched_group_phys_bycpu[i] = sched_group_phys;
+		}
+
 		p = sd;
 		sd = &per_cpu(phys_domains, i);
 		group = cpu_to_phys_group(i);
@@ -5751,6 +6183,18 @@
 		sd->groups = &sched_group_phys[group];
 
 #ifdef CONFIG_SCHED_MC
+		if (!sched_group_core) {
+			sched_group_core
+				= kmalloc(sizeof(struct sched_group) * NR_CPUS,
+					  GFP_KERNEL);
+			if (!sched_group_core) {
+				printk (KERN_WARNING "Can not alloc core sched"
+						     "group\n");
+				goto error;
+			}
+			sched_group_core_bycpu[i] = sched_group_core;
+		}
+
 		p = sd;
 		sd = &per_cpu(core_domains, i);
 		group = cpu_to_core_group(i);
@@ -5834,24 +6278,21 @@
 		domainspan = sched_domain_node_span(i);
 		cpus_and(domainspan, domainspan, *cpu_map);
 
-		sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
+		sg = kmalloc_node(sizeof(struct sched_group), GFP_KERNEL, i);
+		if (!sg) {
+			printk(KERN_WARNING "Can not alloc domain group for "
+				"node %d\n", i);
+			goto error;
+		}
 		sched_group_nodes[i] = sg;
 		for_each_cpu_mask(j, nodemask) {
 			struct sched_domain *sd;
 			sd = &per_cpu(node_domains, j);
 			sd->groups = sg;
-			if (sd->groups == NULL) {
-				/* Turn off balancing if we have no groups */
-				sd->flags = 0;
-			}
-		}
-		if (!sg) {
-			printk(KERN_WARNING
-			"Can not alloc domain group for node %d\n", i);
-			continue;
 		}
 		sg->cpu_power = 0;
 		sg->cpumask = nodemask;
+		sg->next = sg;
 		cpus_or(covered, covered, nodemask);
 		prev = sg;
 
@@ -5870,54 +6311,90 @@
 			if (cpus_empty(tmp))
 				continue;
 
-			sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
+			sg = kmalloc_node(sizeof(struct sched_group),
+					  GFP_KERNEL, i);
 			if (!sg) {
 				printk(KERN_WARNING
 				"Can not alloc domain group for node %d\n", j);
-				break;
+				goto error;
 			}
 			sg->cpu_power = 0;
 			sg->cpumask = tmp;
+			sg->next = prev->next;
 			cpus_or(covered, covered, tmp);
 			prev->next = sg;
 			prev = sg;
 		}
-		prev->next = sched_group_nodes[i];
 	}
 #endif
 
 	/* Calculate CPU power for physical packages and nodes */
+#ifdef CONFIG_SCHED_SMT
+	for_each_cpu_mask(i, *cpu_map) {
+		struct sched_domain *sd;
+		sd = &per_cpu(cpu_domains, i);
+		sd->groups->cpu_power = SCHED_LOAD_SCALE;
+	}
+#endif
+#ifdef CONFIG_SCHED_MC
 	for_each_cpu_mask(i, *cpu_map) {
 		int power;
 		struct sched_domain *sd;
-#ifdef CONFIG_SCHED_SMT
-		sd = &per_cpu(cpu_domains, i);
-		power = SCHED_LOAD_SCALE;
-		sd->groups->cpu_power = power;
-#endif
-#ifdef CONFIG_SCHED_MC
 		sd = &per_cpu(core_domains, i);
-		power = SCHED_LOAD_SCALE + (cpus_weight(sd->groups->cpumask)-1)
+		if (sched_smt_power_savings)
+			power = SCHED_LOAD_SCALE * cpus_weight(sd->groups->cpumask);
+		else
+			power = SCHED_LOAD_SCALE + (cpus_weight(sd->groups->cpumask)-1)
 					    * SCHED_LOAD_SCALE / 10;
 		sd->groups->cpu_power = power;
+	}
+#endif
 
+	for_each_cpu_mask(i, *cpu_map) {
+		struct sched_domain *sd;
+#ifdef CONFIG_SCHED_MC
 		sd = &per_cpu(phys_domains, i);
+		if (i != first_cpu(sd->groups->cpumask))
+			continue;
 
- 		/*
- 		 * This has to be < 2 * SCHED_LOAD_SCALE
- 		 * Lets keep it SCHED_LOAD_SCALE, so that
- 		 * while calculating NUMA group's cpu_power
- 		 * we can simply do
- 		 *  numa_group->cpu_power += phys_group->cpu_power;
- 		 *
- 		 * See "only add power once for each physical pkg"
- 		 * comment below
- 		 */
- 		sd->groups->cpu_power = SCHED_LOAD_SCALE;
+		sd->groups->cpu_power = 0;
+		if (sched_mc_power_savings || sched_smt_power_savings) {
+			int j;
+
+ 			for_each_cpu_mask(j, sd->groups->cpumask) {
+				struct sched_domain *sd1;
+ 				sd1 = &per_cpu(core_domains, j);
+ 				/*
+ 			 	 * for each core we will add once
+ 				 * to the group in physical domain
+ 			 	 */
+  	 			if (j != first_cpu(sd1->groups->cpumask))
+ 					continue;
+
+ 				if (sched_smt_power_savings)
+   					sd->groups->cpu_power += sd1->groups->cpu_power;
+ 				else
+   					sd->groups->cpu_power += SCHED_LOAD_SCALE;
+   			}
+ 		} else
+ 			/*
+ 			 * This has to be < 2 * SCHED_LOAD_SCALE
+ 			 * Lets keep it SCHED_LOAD_SCALE, so that
+ 			 * while calculating NUMA group's cpu_power
+ 			 * we can simply do
+ 			 *  numa_group->cpu_power += phys_group->cpu_power;
+ 			 *
+ 			 * See "only add power once for each physical pkg"
+ 			 * comment below
+ 			 */
+ 			sd->groups->cpu_power = SCHED_LOAD_SCALE;
 #else
+		int power;
 		sd = &per_cpu(phys_domains, i);
-		power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE *
-				(cpus_weight(sd->groups->cpumask)-1) / 10;
+		if (sched_smt_power_savings)
+			power = SCHED_LOAD_SCALE * cpus_weight(sd->groups->cpumask);
+		else
+			power = SCHED_LOAD_SCALE;
 		sd->groups->cpu_power = power;
 #endif
 	}
@@ -5945,13 +6422,20 @@
 	 * Tune cache-hot values:
 	 */
 	calibrate_migration_costs(cpu_map);
+
+	return 0;
+
+error:
+	free_sched_groups(cpu_map);
+	return -ENOMEM;
 }
 /*
  * Set up scheduler domains and groups.  Callers must hold the hotplug lock.
  */
-static void arch_init_sched_domains(const cpumask_t *cpu_map)
+static int arch_init_sched_domains(const cpumask_t *cpu_map)
 {
 	cpumask_t cpu_default_map;
+	int err;
 
 	/*
 	 * Setup mask for cpus without special case scheduling requirements.
@@ -5960,51 +6444,14 @@
 	 */
 	cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
 
-	build_sched_domains(&cpu_default_map);
+	err = build_sched_domains(&cpu_default_map);
+
+	return err;
 }
 
 static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
 {
-#ifdef CONFIG_NUMA
-	int i;
-	int cpu;
-
-	for_each_cpu_mask(cpu, *cpu_map) {
-		struct sched_group *sched_group_allnodes
-			= sched_group_allnodes_bycpu[cpu];
-		struct sched_group **sched_group_nodes
-			= sched_group_nodes_bycpu[cpu];
-
-		if (sched_group_allnodes) {
-			kfree(sched_group_allnodes);
-			sched_group_allnodes_bycpu[cpu] = NULL;
-		}
-
-		if (!sched_group_nodes)
-			continue;
-
-		for (i = 0; i < MAX_NUMNODES; i++) {
-			cpumask_t nodemask = node_to_cpumask(i);
-			struct sched_group *oldsg, *sg = sched_group_nodes[i];
-
-			cpus_and(nodemask, nodemask, *cpu_map);
-			if (cpus_empty(nodemask))
-				continue;
-
-			if (sg == NULL)
-				continue;
-			sg = sg->next;
-next_sg:
-			oldsg = sg;
-			sg = sg->next;
-			kfree(oldsg);
-			if (oldsg != sched_group_nodes[i])
-				goto next_sg;
-		}
-		kfree(sched_group_nodes);
-		sched_group_nodes_bycpu[cpu] = NULL;
-	}
-#endif
+	free_sched_groups(cpu_map);
 }
 
 /*
@@ -6029,9 +6476,10 @@
  * correct sched domains
  * Call with hotplug lock held
  */
-void partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2)
+int partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2)
 {
 	cpumask_t change_map;
+	int err = 0;
 
 	cpus_and(*partition1, *partition1, cpu_online_map);
 	cpus_and(*partition2, *partition2, cpu_online_map);
@@ -6040,11 +6488,87 @@
 	/* Detach sched domains from all of the affected cpus */
 	detach_destroy_domains(&change_map);
 	if (!cpus_empty(*partition1))
-		build_sched_domains(partition1);
-	if (!cpus_empty(*partition2))
-		build_sched_domains(partition2);
+		err = build_sched_domains(partition1);
+	if (!err && !cpus_empty(*partition2))
+		err = build_sched_domains(partition2);
+
+	return err;
 }
 
+#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
+int arch_reinit_sched_domains(void)
+{
+	int err;
+
+	lock_cpu_hotplug();
+	detach_destroy_domains(&cpu_online_map);
+	err = arch_init_sched_domains(&cpu_online_map);
+	unlock_cpu_hotplug();
+
+	return err;
+}
+
+static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt)
+{
+	int ret;
+
+	if (buf[0] != '0' && buf[0] != '1')
+		return -EINVAL;
+
+	if (smt)
+		sched_smt_power_savings = (buf[0] == '1');
+	else
+		sched_mc_power_savings = (buf[0] == '1');
+
+	ret = arch_reinit_sched_domains();
+
+	return ret ? ret : count;
+}
+
+int sched_create_sysfs_power_savings_entries(struct sysdev_class *cls)
+{
+	int err = 0;
+#ifdef CONFIG_SCHED_SMT
+	if (smt_capable())
+		err = sysfs_create_file(&cls->kset.kobj,
+					&attr_sched_smt_power_savings.attr);
+#endif
+#ifdef CONFIG_SCHED_MC
+	if (!err && mc_capable())
+		err = sysfs_create_file(&cls->kset.kobj,
+					&attr_sched_mc_power_savings.attr);
+#endif
+	return err;
+}
+#endif
+
+#ifdef CONFIG_SCHED_MC
+static ssize_t sched_mc_power_savings_show(struct sys_device *dev, char *page)
+{
+	return sprintf(page, "%u\n", sched_mc_power_savings);
+}
+static ssize_t sched_mc_power_savings_store(struct sys_device *dev, const char *buf, size_t count)
+{
+	return sched_power_savings_store(buf, count, 0);
+}
+SYSDEV_ATTR(sched_mc_power_savings, 0644, sched_mc_power_savings_show,
+	    sched_mc_power_savings_store);
+#endif
+
+#ifdef CONFIG_SCHED_SMT
+static ssize_t sched_smt_power_savings_show(struct sys_device *dev, char *page)
+{
+	return sprintf(page, "%u\n", sched_smt_power_savings);
+}
+static ssize_t sched_smt_power_savings_store(struct sys_device *dev, const char *buf, size_t count)
+{
+	return sched_power_savings_store(buf, count, 1);
+}
+SYSDEV_ATTR(sched_smt_power_savings, 0644, sched_smt_power_savings_show,
+	    sched_smt_power_savings_store);
+#endif
+
+
 #ifdef CONFIG_HOTPLUG_CPU
 /*
  * Force a reinitialization of the sched domains hierarchy.  The domains
@@ -6126,7 +6650,6 @@
 		rq->push_cpu = 0;
 		rq->migration_thread = NULL;
 		INIT_LIST_HEAD(&rq->migration_queue);
-		rq->cpu = i;
 #endif
 		atomic_set(&rq->nr_iowait, 0);
 
@@ -6141,6 +6664,7 @@
 		}
 	}
 
+	set_load_weight(&init_task);
 	/*
 	 * The boot idle thread does lazy MMU switching as well:
 	 */
@@ -6187,11 +6711,12 @@
 	runqueue_t *rq;
 
 	read_lock_irq(&tasklist_lock);
-	for_each_process (p) {
+	for_each_process(p) {
 		if (!rt_task(p))
 			continue;
 
-		rq = task_rq_lock(p, &flags);
+		spin_lock_irqsave(&p->pi_lock, flags);
+		rq = __task_rq_lock(p);
 
 		array = p->array;
 		if (array)
@@ -6202,7 +6727,8 @@
 			resched_task(rq->curr);
 		}
 
-		task_rq_unlock(rq, &flags);
+		__task_rq_unlock(rq);
+		spin_unlock_irqrestore(&p->pi_lock, flags);
 	}
 	read_unlock_irq(&tasklist_lock);
 }
diff --git a/kernel/signal.c b/kernel/signal.c
index e5f8aea..52adf53 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -23,12 +23,12 @@
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
-#include <linux/audit.h>
 #include <linux/capability.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/siginfo.h>
+#include "audit.h"	/* audit_signal_info() */
 
 /*
  * SLAB caches for signal bits.
@@ -1531,6 +1531,35 @@
 	spin_unlock_irqrestore(&sighand->siglock, flags);
 }
 
+static inline int may_ptrace_stop(void)
+{
+	if (!likely(current->ptrace & PT_PTRACED))
+		return 0;
+
+	if (unlikely(current->parent == current->real_parent &&
+		    (current->ptrace & PT_ATTACHED)))
+		return 0;
+
+	if (unlikely(current->signal == current->parent->signal) &&
+	    unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))
+		return 0;
+
+	/*
+	 * Are we in the middle of do_coredump?
+	 * If so and our tracer is also part of the coredump stopping
+	 * is a deadlock situation, and pointless because our tracer
+	 * is dead so don't allow us to stop.
+	 * If SIGKILL was already sent before the caller unlocked
+	 * ->siglock we must see ->core_waiters != 0. Otherwise it
+	 * is safe to enter schedule().
+	 */
+	if (unlikely(current->mm->core_waiters) &&
+	    unlikely(current->mm == current->parent->mm))
+		return 0;
+
+	return 1;
+}
+
 /*
  * This must be called with current->sighand->siglock held.
  *
@@ -1559,11 +1588,7 @@
 	spin_unlock_irq(&current->sighand->siglock);
 	try_to_freeze();
 	read_lock(&tasklist_lock);
-	if (likely(current->ptrace & PT_PTRACED) &&
-	    likely(current->parent != current->real_parent ||
-		   !(current->ptrace & PT_ATTACHED)) &&
-	    (likely(current->parent->signal != current->signal) ||
-	     !unlikely(current->signal->flags & SIGNAL_GROUP_EXIT))) {
+	if (may_ptrace_stop()) {
 		do_notify_parent_cldstop(current, CLD_TRAPPED);
 		read_unlock(&tasklist_lock);
 		schedule();
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 336f92d..8f03e3b 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -446,7 +446,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int cpu_callback(struct notifier_block *nfb,
+static int __devinit cpu_callback(struct notifier_block *nfb,
 				  unsigned long action,
 				  void *hcpu)
 {
@@ -470,6 +470,8 @@
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_UP_CANCELED:
+		if (!per_cpu(ksoftirqd, hotcpu))
+			break;
 		/* Unbind so it can run.  Fall thru. */
 		kthread_bind(per_cpu(ksoftirqd, hotcpu),
 			     any_online_cpu(cpu_online_map));
@@ -484,7 +486,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block cpu_nfb = {
+static struct notifier_block __devinitdata cpu_nfb = {
 	.notifier_call = cpu_callback
 };
 
diff --git a/kernel/softlockup.c b/kernel/softlockup.c
index 14c7faf..6b76caa 100644
--- a/kernel/softlockup.c
+++ b/kernel/softlockup.c
@@ -36,7 +36,7 @@
 
 void touch_softlockup_watchdog(void)
 {
-	per_cpu(touch_timestamp, raw_smp_processor_id()) = jiffies;
+	__raw_get_cpu_var(touch_timestamp) = jiffies;
 }
 EXPORT_SYMBOL(touch_softlockup_watchdog);
 
@@ -104,7 +104,7 @@
 /*
  * Create/destroy watchdog threads as CPUs come and go:
  */
-static int
+static int __devinit
 cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
 	int hotcpu = (unsigned long)hcpu;
@@ -127,6 +127,8 @@
 		break;
 #ifdef CONFIG_HOTPLUG_CPU
 	case CPU_UP_CANCELED:
+		if (!per_cpu(watchdog_task, hotcpu))
+			break;
 		/* Unbind so it can run.  Fall thru. */
 		kthread_bind(per_cpu(watchdog_task, hotcpu),
 			     any_online_cpu(cpu_online_map));
@@ -140,7 +142,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block cpu_nfb = {
+static struct notifier_block __devinitdata cpu_nfb = {
 	.notifier_call = cpu_callback
 };
 
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index dcfb5d7..2c0aacc 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -4,6 +4,7 @@
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/syscalls.h>
+#include <linux/kthread.h>
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -25,13 +26,11 @@
 static atomic_t stopmachine_thread_ack;
 static DECLARE_MUTEX(stopmachine_mutex);
 
-static int stopmachine(void *cpu)
+static int stopmachine(void *unused)
 {
 	int irqs_disabled = 0;
 	int prepared = 0;
 
-	set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu));
-
 	/* Ack: we are alive */
 	smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */
 	atomic_inc(&stopmachine_thread_ack);
@@ -85,7 +84,8 @@
 
 static int stop_machine(void)
 {
-	int i, ret = 0;
+	int ret = 0;
+	unsigned int i;
 	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
 	/* One high-prio thread per cpu.  We'll do this one. */
@@ -96,11 +96,16 @@
 	stopmachine_state = STOPMACHINE_WAIT;
 
 	for_each_online_cpu(i) {
+		struct task_struct *tsk;
 		if (i == raw_smp_processor_id())
 			continue;
-		ret = kernel_thread(stopmachine, (void *)(long)i,CLONE_KERNEL);
-		if (ret < 0)
+		tsk = kthread_create(stopmachine, NULL, "stopmachine");
+		if (IS_ERR(tsk)) {
+			ret = PTR_ERR(tsk);
 			break;
+		}
+		kthread_bind(tsk, i);
+		wake_up_process(tsk);
 		stopmachine_num_threads++;
 	}
 
diff --git a/kernel/sys.c b/kernel/sys.c
index 0b6ec0e..2d5179c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -13,7 +13,6 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/prctl.h>
-#include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -57,6 +56,12 @@
 #ifndef GET_FPEXC_CTL
 # define GET_FPEXC_CTL(a,b)	(-EINVAL)
 #endif
+#ifndef GET_ENDIAN
+# define GET_ENDIAN(a,b)	(-EINVAL)
+#endif
+#ifndef SET_ENDIAN
+# define SET_ENDIAN(a,b)	(-EINVAL)
+#endif
 
 /*
  * this is where the system-wide overflow UID and GID are defined, for
@@ -132,14 +137,15 @@
 		unsigned long val, void *v)
 {
 	int ret = NOTIFY_DONE;
-	struct notifier_block *nb;
+	struct notifier_block *nb, *next_nb;
 
 	nb = rcu_dereference(*nl);
 	while (nb) {
+		next_nb = rcu_dereference(nb->next);
 		ret = nb->notifier_call(nb, val, v);
 		if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
 			break;
-		nb = rcu_dereference(nb->next);
+		nb = next_nb;
 	}
 	return ret;
 }
@@ -583,7 +589,7 @@
 }
 EXPORT_SYMBOL_GPL(emergency_restart);
 
-void kernel_restart_prepare(char *cmd)
+static void kernel_restart_prepare(char *cmd)
 {
 	blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
 	system_state = SYSTEM_RESTART;
@@ -617,7 +623,7 @@
  *	Move into place and start executing a preloaded standalone
  *	executable.  If nothing was preloaded return an error.
  */
-void kernel_kexec(void)
+static void kernel_kexec(void)
 {
 #ifdef CONFIG_KEXEC
 	struct kimage *image;
@@ -631,7 +637,6 @@
 	machine_kexec(image);
 #endif
 }
-EXPORT_SYMBOL_GPL(kernel_kexec);
 
 void kernel_shutdown_prepare(enum system_states state)
 {
@@ -1860,23 +1865,20 @@
  * fields when reaping, so a sample either gets all the additions of a
  * given child after it's reaped, or none so this sample is before reaping.
  *
- * tasklist_lock locking optimisation:
- * If we are current and single threaded, we do not need to take the tasklist
- * lock or the siglock.  No one else can take our signal_struct away,
- * no one else can reap the children to update signal->c* counters, and
- * no one else can race with the signal-> fields.
- * If we do not take the tasklist_lock, the signal-> fields could be read
- * out of order while another thread was just exiting. So we place a
- * read memory barrier when we avoid the lock.  On the writer side,
- * write memory barrier is implied in  __exit_signal as __exit_signal releases
- * the siglock spinlock after updating the signal-> fields.
- *
- * We don't really need the siglock when we access the non c* fields
- * of the signal_struct (for RUSAGE_SELF) even in multithreaded
- * case, since we take the tasklist lock for read and the non c* signal->
- * fields are updated only in __exit_signal, which is called with
- * tasklist_lock taken for write, hence these two threads cannot execute
- * concurrently.
+ * Locking:
+ * We need to take the siglock for CHILDEREN, SELF and BOTH
+ * for  the cases current multithreaded, non-current single threaded
+ * non-current multithreaded.  Thread traversal is now safe with
+ * the siglock held.
+ * Strictly speaking, we donot need to take the siglock if we are current and
+ * single threaded,  as no one else can take our signal_struct away, no one
+ * else can  reap the  children to update signal->c* counters, and no one else
+ * can race with the signal-> fields. If we do not take any lock, the
+ * signal-> fields could be read out of order while another thread was just
+ * exiting. So we should  place a read memory barrier when we avoid the lock.
+ * On the writer side,  write memory barrier is implied in  __exit_signal
+ * as __exit_signal releases  the siglock spinlock after updating the signal->
+ * fields. But we don't do this yet to keep things simple.
  *
  */
 
@@ -1885,35 +1887,25 @@
 	struct task_struct *t;
 	unsigned long flags;
 	cputime_t utime, stime;
-	int need_lock = 0;
 
 	memset((char *) r, 0, sizeof *r);
 	utime = stime = cputime_zero;
 
-	if (p != current || !thread_group_empty(p))
-		need_lock = 1;
-
-	if (need_lock) {
-		read_lock(&tasklist_lock);
-		if (unlikely(!p->signal)) {
-			read_unlock(&tasklist_lock);
-			return;
-		}
-	} else
-		/* See locking comments above */
-		smp_rmb();
+	rcu_read_lock();
+	if (!lock_task_sighand(p, &flags)) {
+		rcu_read_unlock();
+		return;
+	}
 
 	switch (who) {
 		case RUSAGE_BOTH:
 		case RUSAGE_CHILDREN:
-			spin_lock_irqsave(&p->sighand->siglock, flags);
 			utime = p->signal->cutime;
 			stime = p->signal->cstime;
 			r->ru_nvcsw = p->signal->cnvcsw;
 			r->ru_nivcsw = p->signal->cnivcsw;
 			r->ru_minflt = p->signal->cmin_flt;
 			r->ru_majflt = p->signal->cmaj_flt;
-			spin_unlock_irqrestore(&p->sighand->siglock, flags);
 
 			if (who == RUSAGE_CHILDREN)
 				break;
@@ -1941,8 +1933,9 @@
 			BUG();
 	}
 
-	if (need_lock)
-		read_unlock(&tasklist_lock);
+	unlock_task_sighand(p, &flags);
+	rcu_read_unlock();
+
 	cputime_to_timeval(utime, &r->ru_utime);
 	cputime_to_timeval(stime, &r->ru_stime);
 }
@@ -2057,6 +2050,13 @@
 				return -EFAULT;
 			return 0;
 		}
+		case PR_GET_ENDIAN:
+			error = GET_ENDIAN(current, arg2);
+			break;
+		case PR_SET_ENDIAN:
+			error = SET_ENDIAN(current, arg2);
+			break;
+
 		default:
 			error = -EINVAL;
 			break;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 5433195..6991bec 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -87,6 +87,7 @@
 cond_syscall(sys_inotify_add_watch);
 cond_syscall(sys_inotify_rm_watch);
 cond_syscall(sys_migrate_pages);
+cond_syscall(sys_move_pages);
 cond_syscall(sys_chown16);
 cond_syscall(sys_fchown16);
 cond_syscall(sys_getegid16);
@@ -132,3 +133,4 @@
 cond_syscall(sys_madvise);
 cond_syscall(sys_mremap);
 cond_syscall(sys_remap_file_pages);
+cond_syscall(compat_sys_move_pages);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index e82726f..93a2c53 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -59,6 +59,7 @@
 extern int C_A_D;
 extern int sysctl_overcommit_memory;
 extern int sysctl_overcommit_ratio;
+extern int sysctl_panic_on_oom;
 extern int max_threads;
 extern int sysrq_enabled;
 extern int core_uses_pid;
@@ -72,6 +73,7 @@
 extern int pid_max_min, pid_max_max;
 extern int sysctl_drop_caches;
 extern int percpu_pagelist_fraction;
+extern int compat_log;
 
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
 int unknown_nmi_panic;
@@ -131,6 +133,10 @@
 extern int no_unaligned_warning;
 #endif
 
+#ifdef CONFIG_RT_MUTEXES
+extern int max_lock_depth;
+#endif
+
 static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
 		       ctl_table *, void **);
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
@@ -142,7 +148,6 @@
 
 static ctl_table kern_table[];
 static ctl_table vm_table[];
-static ctl_table proc_table[];
 static ctl_table fs_table[];
 static ctl_table debug_table[];
 static ctl_table dev_table[];
@@ -150,7 +155,7 @@
 #ifdef CONFIG_UNIX98_PTYS
 extern ctl_table pty_table[];
 #endif
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
 extern ctl_table inotify_table[];
 #endif
 
@@ -202,12 +207,6 @@
 	},
 #endif
 	{
-		.ctl_name	= CTL_PROC,
-		.procname	= "proc",
-		.mode		= 0555,
-		.child		= proc_table,
-	},
-	{
 		.ctl_name	= CTL_FS,
 		.procname	= "fs",
 		.mode		= 0555,
@@ -398,7 +397,7 @@
 		.strategy	= &sysctl_string,
 	},
 #endif
-#ifdef CONFIG_HOTPLUG
+#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
 	{
 		.ctl_name	= KERN_HOTPLUG,
 		.procname	= "hotplug",
@@ -683,6 +682,27 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+#ifdef CONFIG_COMPAT
+	{
+		.ctl_name	= KERN_COMPAT_LOG,
+		.procname	= "compat-log",
+		.data		= &compat_log,
+		.maxlen		= sizeof (int),
+	 	.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
+#ifdef CONFIG_RT_MUTEXES
+	{
+		.ctl_name	= KERN_MAX_LOCK_DEPTH,
+		.procname	= "max_lock_depth",
+		.data		= &max_lock_depth,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
+
 	{ .ctl_name = 0 }
 };
 
@@ -702,6 +722,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 	{
+		.ctl_name	= VM_PANIC_ON_OOM,
+		.procname	= "panic_on_oom",
+		.data		= &sysctl_panic_on_oom,
+		.maxlen		= sizeof(sysctl_panic_on_oom),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
 		.ctl_name	= VM_OVERCOMMIT_RATIO,
 		.procname	= "overcommit_ratio",
 		.data		= &sysctl_overcommit_ratio,
@@ -915,10 +943,18 @@
 		.strategy	= &sysctl_jiffies,
 	},
 #endif
-	{ .ctl_name = 0 }
-};
-
-static ctl_table proc_table[] = {
+#ifdef CONFIG_X86_32
+	{
+		.ctl_name	= VM_VDSO_ENABLED,
+		.procname	= "vdso_enabled",
+		.data		= &vdso_enabled,
+		.maxlen		= sizeof(vdso_enabled),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+		.strategy	= &sysctl_intvec,
+		.extra1		= &zero,
+	},
+#endif
 	{ .ctl_name = 0 }
 };
 
@@ -1028,7 +1064,7 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_doulongvec_minmax,
 	},
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
 	{
 		.ctl_name	= FS_INOTIFY,
 		.procname	= "inotify",
diff --git a/kernel/time.c b/kernel/time.c
index b00ddc7..5bd4897 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -523,6 +523,7 @@
 
 
 #else
+#ifndef CONFIG_GENERIC_TIME
 /*
  * Simulate gettimeofday using do_gettimeofday which only allows a timeval
  * and therefore only yields usec accuracy
@@ -537,6 +538,7 @@
 }
 EXPORT_SYMBOL_GPL(getnstimeofday);
 #endif
+#endif
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
new file mode 100644
index 0000000..e1dfd8e
--- /dev/null
+++ b/kernel/time/Makefile
@@ -0,0 +1 @@
+obj-y += clocksource.o jiffies.o
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
new file mode 100644
index 0000000..74eca59
--- /dev/null
+++ b/kernel/time/clocksource.c
@@ -0,0 +1,349 @@
+/*
+ * linux/kernel/time/clocksource.c
+ *
+ * This file contains the functions which manage clocksource drivers.
+ *
+ * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * TODO WishList:
+ *   o Allow clocksource drivers to be unregistered
+ *   o get rid of clocksource_jiffies extern
+ */
+
+#include <linux/clocksource.h>
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+/* XXX - Would like a better way for initializing curr_clocksource */
+extern struct clocksource clocksource_jiffies;
+
+/*[Clocksource internal variables]---------
+ * curr_clocksource:
+ *	currently selected clocksource. Initialized to clocksource_jiffies.
+ * next_clocksource:
+ *	pending next selected clocksource.
+ * clocksource_list:
+ *	linked list with the registered clocksources
+ * clocksource_lock:
+ *	protects manipulations to curr_clocksource and next_clocksource
+ *	and the clocksource_list
+ * override_name:
+ *	Name of the user-specified clocksource.
+ */
+static struct clocksource *curr_clocksource = &clocksource_jiffies;
+static struct clocksource *next_clocksource;
+static LIST_HEAD(clocksource_list);
+static DEFINE_SPINLOCK(clocksource_lock);
+static char override_name[32];
+static int finished_booting;
+
+/* clocksource_done_booting - Called near the end of bootup
+ *
+ * Hack to avoid lots of clocksource churn at boot time
+ */
+static int __init clocksource_done_booting(void)
+{
+	finished_booting = 1;
+	return 0;
+}
+
+late_initcall(clocksource_done_booting);
+
+/**
+ * clocksource_get_next - Returns the selected clocksource
+ *
+ */
+struct clocksource *clocksource_get_next(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocksource_lock, flags);
+	if (next_clocksource && finished_booting) {
+		curr_clocksource = next_clocksource;
+		next_clocksource = NULL;
+	}
+	spin_unlock_irqrestore(&clocksource_lock, flags);
+
+	return curr_clocksource;
+}
+
+/**
+ * select_clocksource - Finds the best registered clocksource.
+ *
+ * Private function. Must hold clocksource_lock when called.
+ *
+ * Looks through the list of registered clocksources, returning
+ * the one with the highest rating value. If there is a clocksource
+ * name that matches the override string, it returns that clocksource.
+ */
+static struct clocksource *select_clocksource(void)
+{
+	struct clocksource *best = NULL;
+	struct list_head *tmp;
+
+	list_for_each(tmp, &clocksource_list) {
+		struct clocksource *src;
+
+		src = list_entry(tmp, struct clocksource, list);
+		if (!best)
+			best = src;
+
+		/* check for override: */
+		if (strlen(src->name) == strlen(override_name) &&
+		    !strcmp(src->name, override_name)) {
+			best = src;
+			break;
+		}
+		/* pick the highest rating: */
+		if (src->rating > best->rating)
+		 	best = src;
+	}
+
+	return best;
+}
+
+/**
+ * is_registered_source - Checks if clocksource is registered
+ * @c:		pointer to a clocksource
+ *
+ * Private helper function. Must hold clocksource_lock when called.
+ *
+ * Returns one if the clocksource is already registered, zero otherwise.
+ */
+static int is_registered_source(struct clocksource *c)
+{
+	int len = strlen(c->name);
+	struct list_head *tmp;
+
+	list_for_each(tmp, &clocksource_list) {
+		struct clocksource *src;
+
+		src = list_entry(tmp, struct clocksource, list);
+		if (strlen(src->name) == len &&	!strcmp(src->name, c->name))
+			return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * clocksource_register - Used to install new clocksources
+ * @t:		clocksource to be registered
+ *
+ * Returns -EBUSY if registration fails, zero otherwise.
+ */
+int clocksource_register(struct clocksource *c)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocksource_lock, flags);
+	/* check if clocksource is already registered */
+	if (is_registered_source(c)) {
+		printk("register_clocksource: Cannot register %s. "
+			"Already registered!", c->name);
+		ret = -EBUSY;
+	} else {
+		/* register it */
+ 		list_add(&c->list, &clocksource_list);
+		/* scan the registered clocksources, and pick the best one */
+		next_clocksource = select_clocksource();
+	}
+	spin_unlock_irqrestore(&clocksource_lock, flags);
+	return ret;
+}
+EXPORT_SYMBOL(clocksource_register);
+
+/**
+ * clocksource_reselect - Rescan list for next clocksource
+ *
+ * A quick helper function to be used if a clocksource changes its
+ * rating. Forces the clocksource list to be re-scanned for the best
+ * clocksource.
+ */
+void clocksource_reselect(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocksource_lock, flags);
+	next_clocksource = select_clocksource();
+	spin_unlock_irqrestore(&clocksource_lock, flags);
+}
+EXPORT_SYMBOL(clocksource_reselect);
+
+/**
+ * sysfs_show_current_clocksources - sysfs interface for current clocksource
+ * @dev:	unused
+ * @buf:	char buffer to be filled with clocksource list
+ *
+ * Provides sysfs interface for listing current clocksource.
+ */
+static ssize_t
+sysfs_show_current_clocksources(struct sys_device *dev, char *buf)
+{
+	char *curr = buf;
+
+	spin_lock_irq(&clocksource_lock);
+	curr += sprintf(curr, "%s ", curr_clocksource->name);
+	spin_unlock_irq(&clocksource_lock);
+
+	curr += sprintf(curr, "\n");
+
+	return curr - buf;
+}
+
+/**
+ * sysfs_override_clocksource - interface for manually overriding clocksource
+ * @dev:	unused
+ * @buf:	name of override clocksource
+ * @count:	length of buffer
+ *
+ * Takes input from sysfs interface for manually overriding the default
+ * clocksource selction.
+ */
+static ssize_t sysfs_override_clocksource(struct sys_device *dev,
+					  const char *buf, size_t count)
+{
+	size_t ret = count;
+	/* strings from sysfs write are not 0 terminated! */
+	if (count >= sizeof(override_name))
+		return -EINVAL;
+
+	/* strip of \n: */
+	if (buf[count-1] == '\n')
+		count--;
+	if (count < 1)
+		return -EINVAL;
+
+	spin_lock_irq(&clocksource_lock);
+
+	/* copy the name given: */
+	memcpy(override_name, buf, count);
+	override_name[count] = 0;
+
+	/* try to select it: */
+	next_clocksource = select_clocksource();
+
+	spin_unlock_irq(&clocksource_lock);
+
+	return ret;
+}
+
+/**
+ * sysfs_show_available_clocksources - sysfs interface for listing clocksource
+ * @dev:	unused
+ * @buf:	char buffer to be filled with clocksource list
+ *
+ * Provides sysfs interface for listing registered clocksources
+ */
+static ssize_t
+sysfs_show_available_clocksources(struct sys_device *dev, char *buf)
+{
+	struct list_head *tmp;
+	char *curr = buf;
+
+	spin_lock_irq(&clocksource_lock);
+	list_for_each(tmp, &clocksource_list) {
+		struct clocksource *src;
+
+		src = list_entry(tmp, struct clocksource, list);
+		curr += sprintf(curr, "%s ", src->name);
+	}
+	spin_unlock_irq(&clocksource_lock);
+
+	curr += sprintf(curr, "\n");
+
+	return curr - buf;
+}
+
+/*
+ * Sysfs setup bits:
+ */
+static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources,
+			sysfs_override_clocksource);
+
+static SYSDEV_ATTR(available_clocksource, 0600,
+			sysfs_show_available_clocksources, NULL);
+
+static struct sysdev_class clocksource_sysclass = {
+	set_kset_name("clocksource"),
+};
+
+static struct sys_device device_clocksource = {
+	.id	= 0,
+	.cls	= &clocksource_sysclass,
+};
+
+static int __init init_clocksource_sysfs(void)
+{
+	int error = sysdev_class_register(&clocksource_sysclass);
+
+	if (!error)
+		error = sysdev_register(&device_clocksource);
+	if (!error)
+		error = sysdev_create_file(
+				&device_clocksource,
+				&attr_current_clocksource);
+	if (!error)
+		error = sysdev_create_file(
+				&device_clocksource,
+				&attr_available_clocksource);
+	return error;
+}
+
+device_initcall(init_clocksource_sysfs);
+
+/**
+ * boot_override_clocksource - boot clock override
+ * @str:	override name
+ *
+ * Takes a clocksource= boot argument and uses it
+ * as the clocksource override name.
+ */
+static int __init boot_override_clocksource(char* str)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&clocksource_lock, flags);
+	if (str)
+		strlcpy(override_name, str, sizeof(override_name));
+	spin_unlock_irqrestore(&clocksource_lock, flags);
+	return 1;
+}
+
+__setup("clocksource=", boot_override_clocksource);
+
+/**
+ * boot_override_clock - Compatibility layer for deprecated boot option
+ * @str:	override name
+ *
+ * DEPRECATED! Takes a clock= boot argument and uses it
+ * as the clocksource override name
+ */
+static int __init boot_override_clock(char* str)
+{
+	if (!strcmp(str, "pmtmr")) {
+		printk("Warning: clock=pmtmr is deprecated. "
+			"Use clocksource=acpi_pm.\n");
+		return boot_override_clocksource("acpi_pm");
+	}
+	printk("Warning! clock= boot option is deprecated. "
+		"Use clocksource=xyz\n");
+	return boot_override_clocksource(str);
+}
+
+__setup("clock=", boot_override_clock);
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
new file mode 100644
index 0000000..126bb30
--- /dev/null
+++ b/kernel/time/jiffies.c
@@ -0,0 +1,73 @@
+/***********************************************************************
+* linux/kernel/time/jiffies.c
+*
+* This file contains the jiffies based clocksource.
+*
+* Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com)
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+************************************************************************/
+#include <linux/clocksource.h>
+#include <linux/jiffies.h>
+#include <linux/init.h>
+
+/* The Jiffies based clocksource is the lowest common
+ * denominator clock source which should function on
+ * all systems. It has the same coarse resolution as
+ * the timer interrupt frequency HZ and it suffers
+ * inaccuracies caused by missed or lost timer
+ * interrupts and the inability for the timer
+ * interrupt hardware to accuratly tick at the
+ * requested HZ value. It is also not reccomended
+ * for "tick-less" systems.
+ */
+#define NSEC_PER_JIFFY	((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ))
+
+/* Since jiffies uses a simple NSEC_PER_JIFFY multiplier
+ * conversion, the .shift value could be zero. However
+ * this would make NTP adjustments impossible as they are
+ * in units of 1/2^.shift. Thus we use JIFFIES_SHIFT to
+ * shift both the nominator and denominator the same
+ * amount, and give ntp adjustments in units of 1/2^8
+ *
+ * The value 8 is somewhat carefully chosen, as anything
+ * larger can result in overflows. NSEC_PER_JIFFY grows as
+ * HZ shrinks, so values greater then 8 overflow 32bits when
+ * HZ=100.
+ */
+#define JIFFIES_SHIFT	8
+
+static cycle_t jiffies_read(void)
+{
+	return (cycle_t) jiffies;
+}
+
+struct clocksource clocksource_jiffies = {
+	.name		= "jiffies",
+	.rating		= 0, /* lowest rating*/
+	.read		= jiffies_read,
+	.mask		= 0xffffffff, /*32bits*/
+	.mult		= NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */
+	.shift		= JIFFIES_SHIFT,
+	.is_continuous	= 0, /* tick based, not free running */
+};
+
+static int __init init_jiffies_clocksource(void)
+{
+	return clocksource_register(&clocksource_jiffies);
+}
+
+module_init(init_jiffies_clocksource);
diff --git a/kernel/timer.c b/kernel/timer.c
index 9e49dee..5a89602 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -146,7 +146,7 @@
 void fastcall init_timer(struct timer_list *timer)
 {
 	timer->entry.next = NULL;
-	timer->base = per_cpu(tvec_bases, raw_smp_processor_id());
+	timer->base = __raw_get_cpu_var(tvec_bases);
 }
 EXPORT_SYMBOL(init_timer);
 
@@ -383,23 +383,19 @@
 static int cascade(tvec_base_t *base, tvec_t *tv, int index)
 {
 	/* cascade all the timers from tv up one level */
-	struct list_head *head, *curr;
+	struct timer_list *timer, *tmp;
+	struct list_head tv_list;
 
-	head = tv->vec + index;
-	curr = head->next;
+	list_replace_init(tv->vec + index, &tv_list);
+
 	/*
-	 * We are removing _all_ timers from the list, so we don't  have to
-	 * detach them individually, just clear the list afterwards.
+	 * We are removing _all_ timers from the list, so we
+	 * don't have to detach them individually.
 	 */
-	while (curr != head) {
-		struct timer_list *tmp;
-
-		tmp = list_entry(curr, struct timer_list, entry);
-		BUG_ON(tmp->base != base);
-		curr = curr->next;
-		internal_add_timer(base, tmp);
+	list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
+		BUG_ON(timer->base != base);
+		internal_add_timer(base, timer);
 	}
-	INIT_LIST_HEAD(head);
 
 	return index;
 }
@@ -419,10 +415,10 @@
 
 	spin_lock_irq(&base->lock);
 	while (time_after_eq(jiffies, base->timer_jiffies)) {
-		struct list_head work_list = LIST_HEAD_INIT(work_list);
+		struct list_head work_list;
 		struct list_head *head = &work_list;
  		int index = base->timer_jiffies & TVR_MASK;
- 
+
 		/*
 		 * Cascade timers:
 		 */
@@ -431,8 +427,8 @@
 				(!cascade(base, &base->tv3, INDEX(1))) &&
 					!cascade(base, &base->tv4, INDEX(2)))
 			cascade(base, &base->tv5, INDEX(3));
-		++base->timer_jiffies; 
-		list_splice_init(base->tv1.vec + index, &work_list);
+		++base->timer_jiffies;
+		list_replace_init(base->tv1.vec + index, &work_list);
 		while (!list_empty(head)) {
 			void (*fn)(unsigned long);
 			unsigned long data;
@@ -601,7 +597,6 @@
 long time_precision = 1;		/* clock precision (us)		*/
 long time_maxerror = NTP_PHASE_LIMIT;	/* maximum error (us)		*/
 long time_esterror = NTP_PHASE_LIMIT;	/* estimated error (us)		*/
-static long time_phase;			/* phase offset (scaled us)	*/
 long time_freq = (((NSEC_PER_SEC + HZ/2) % HZ - HZ/2) << SHIFT_USEC) / NSEC_PER_USEC;
 					/* frequency offset (scaled ppm)*/
 static long time_adj;			/* tick adjust (scaled 1 / HZ)	*/
@@ -751,27 +746,14 @@
 }
 
 /* in the NTP reference this is called "hardclock()" */
-static void update_wall_time_one_tick(void)
+static void update_ntp_one_tick(void)
 {
-	long time_adjust_step, delta_nsec;
+	long time_adjust_step;
 
 	time_adjust_step = adjtime_adjustment();
 	if (time_adjust_step)
 		/* Reduce by this step the amount of time left  */
 		time_adjust -= time_adjust_step;
-	delta_nsec = tick_nsec + time_adjust_step * 1000;
-	/*
-	 * Advance the phase, once it gets to one microsecond, then
-	 * advance the tick more.
-	 */
-	time_phase += time_adj;
-	if ((time_phase >= FINENSEC) || (time_phase <= -FINENSEC)) {
-		long ltemp = shift_right(time_phase, (SHIFT_SCALE - 10));
-		time_phase -= ltemp << (SHIFT_SCALE - 10);
-		delta_nsec += ltemp;
-	}
-	xtime.tv_nsec += delta_nsec;
-	time_interpolator_update(delta_nsec);
 
 	/* Changes by adjtime() do not take effect till next tick. */
 	if (time_next_adjust != 0) {
@@ -784,36 +766,378 @@
  * Return how long ticks are at the moment, that is, how much time
  * update_wall_time_one_tick will add to xtime next time we call it
  * (assuming no calls to do_adjtimex in the meantime).
- * The return value is in fixed-point nanoseconds with SHIFT_SCALE-10
- * bits to the right of the binary point.
+ * The return value is in fixed-point nanoseconds shifted by the
+ * specified number of bits to the right of the binary point.
  * This function has no side-effects.
  */
 u64 current_tick_length(void)
 {
 	long delta_nsec;
+	u64 ret;
 
+	/* calculate the finest interval NTP will allow.
+	 *    ie: nanosecond value shifted by (SHIFT_SCALE - 10)
+	 */
 	delta_nsec = tick_nsec + adjtime_adjustment() * 1000;
-	return ((u64) delta_nsec << (SHIFT_SCALE - 10)) + time_adj;
+	ret = (u64)delta_nsec << TICK_LENGTH_SHIFT;
+	ret += (s64)time_adj << (TICK_LENGTH_SHIFT - (SHIFT_SCALE - 10));
+
+	return ret;
+}
+
+/* XXX - all of this timekeeping code should be later moved to time.c */
+#include <linux/clocksource.h>
+static struct clocksource *clock; /* pointer to current clocksource */
+
+#ifdef CONFIG_GENERIC_TIME
+/**
+ * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
+ *
+ * private function, must hold xtime_lock lock when being
+ * called. Returns the number of nanoseconds since the
+ * last call to update_wall_time() (adjusted by NTP scaling)
+ */
+static inline s64 __get_nsec_offset(void)
+{
+	cycle_t cycle_now, cycle_delta;
+	s64 ns_offset;
+
+	/* read clocksource: */
+	cycle_now = clocksource_read(clock);
+
+	/* calculate the delta since the last update_wall_time: */
+	cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
+
+	/* convert to nanoseconds: */
+	ns_offset = cyc2ns(clock, cycle_delta);
+
+	return ns_offset;
+}
+
+/**
+ * __get_realtime_clock_ts - Returns the time of day in a timespec
+ * @ts:		pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec. Used by
+ * do_gettimeofday() and get_realtime_clock_ts().
+ */
+static inline void __get_realtime_clock_ts(struct timespec *ts)
+{
+	unsigned long seq;
+	s64 nsecs;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+
+		*ts = xtime;
+		nsecs = __get_nsec_offset();
+
+	} while (read_seqretry(&xtime_lock, seq));
+
+	timespec_add_ns(ts, nsecs);
+}
+
+/**
+ * getnstimeofday - Returns the time of day in a timespec
+ * @ts:		pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec.
+ */
+void getnstimeofday(struct timespec *ts)
+{
+	__get_realtime_clock_ts(ts);
+}
+
+EXPORT_SYMBOL(getnstimeofday);
+
+/**
+ * do_gettimeofday - Returns the time of day in a timeval
+ * @tv:		pointer to the timeval to be set
+ *
+ * NOTE: Users should be converted to using get_realtime_clock_ts()
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	struct timespec now;
+
+	__get_realtime_clock_ts(&now);
+	tv->tv_sec = now.tv_sec;
+	tv->tv_usec = now.tv_nsec/1000;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+/**
+ * do_settimeofday - Sets the time of day
+ * @tv:		pointer to the timespec variable containing the new time
+ *
+ * Sets the time of day to the new time and update NTP and notify hrtimers
+ */
+int do_settimeofday(struct timespec *tv)
+{
+	unsigned long flags;
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+
+	if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+		return -EINVAL;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+
+	nsec -= __get_nsec_offset();
+
+	wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+	wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+	set_normalized_timespec(&xtime, sec, nsec);
+	set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+	ntp_clear();
+
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	/* signal hrtimers about time change */
+	clock_was_set();
+
+	return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/**
+ * change_clocksource - Swaps clocksources if a new one is available
+ *
+ * Accumulates current time interval and initializes new clocksource
+ */
+static int change_clocksource(void)
+{
+	struct clocksource *new;
+	cycle_t now;
+	u64 nsec;
+	new = clocksource_get_next();
+	if (clock != new) {
+		now = clocksource_read(new);
+		nsec =  __get_nsec_offset();
+		timespec_add_ns(&xtime, nsec);
+
+		clock = new;
+		clock->cycle_last = now;
+		printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+					clock->name);
+		return 1;
+	} else if (clock->update_callback) {
+		return clock->update_callback();
+	}
+	return 0;
+}
+#else
+#define change_clocksource() (0)
+#endif
+
+/**
+ * timeofday_is_continuous - check to see if timekeeping is free running
+ */
+int timekeeping_is_continuous(void)
+{
+	unsigned long seq;
+	int ret;
+
+	do {
+		seq = read_seqbegin(&xtime_lock);
+
+		ret = clock->is_continuous;
+
+	} while (read_seqretry(&xtime_lock, seq));
+
+	return ret;
 }
 
 /*
- * Using a loop looks inefficient, but "ticks" is
- * usually just one (we shouldn't be losing ticks,
- * we're doing this this way mainly for interrupt
- * latency reasons, not because we think we'll
- * have lots of lost timer ticks
+ * timekeeping_init - Initializes the clocksource and common timekeeping values
  */
-static void update_wall_time(unsigned long ticks)
+void __init timekeeping_init(void)
 {
-	do {
-		ticks--;
-		update_wall_time_one_tick();
-		if (xtime.tv_nsec >= 1000000000) {
-			xtime.tv_nsec -= 1000000000;
+	unsigned long flags;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+	clock = clocksource_get_next();
+	clocksource_calculate_interval(clock, tick_nsec);
+	clock->cycle_last = clocksource_read(clock);
+	ntp_clear();
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+}
+
+
+/*
+ * timekeeping_resume - Resumes the generic timekeeping subsystem.
+ * @dev:	unused
+ *
+ * This is for the generic clocksource timekeeping.
+ * xtime/wall_to_monotonic/jiffies/wall_jiffies/etc are
+ * still managed by arch specific suspend/resume code.
+ */
+static int timekeeping_resume(struct sys_device *dev)
+{
+	unsigned long flags;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+	/* restart the last cycle value */
+	clock->cycle_last = clocksource_read(clock);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+	return 0;
+}
+
+/* sysfs resume/suspend bits for timekeeping */
+static struct sysdev_class timekeeping_sysclass = {
+	.resume		= timekeeping_resume,
+	set_kset_name("timekeeping"),
+};
+
+static struct sys_device device_timer = {
+	.id		= 0,
+	.cls		= &timekeeping_sysclass,
+};
+
+static int __init timekeeping_init_device(void)
+{
+	int error = sysdev_class_register(&timekeeping_sysclass);
+	if (!error)
+		error = sysdev_register(&device_timer);
+	return error;
+}
+
+device_initcall(timekeeping_init_device);
+
+/*
+ * If the error is already larger, we look ahead another tick,
+ * to compensate for late or lost adjustments.
+ */
+static __always_inline int clocksource_bigadjust(int sign, s64 error, s64 *interval, s64 *offset)
+{
+	int adj;
+
+	/*
+	 * As soon as the machine is synchronized to the external time
+	 * source this should be the common case.
+	 */
+	error >>= 2;
+	if (likely(sign > 0 ? error <= *interval : error >= *interval))
+		return sign;
+
+	/*
+	 * An extra look ahead dampens the effect of the current error,
+	 * which can grow quite large with continously late updates, as
+	 * it would dominate the adjustment value and can lead to
+	 * oscillation.
+	 */
+	error += current_tick_length() >> (TICK_LENGTH_SHIFT - clock->shift + 1);
+	error -= clock->xtime_interval >> 1;
+
+	adj = 0;
+	while (1) {
+		error >>= 1;
+		if (sign > 0 ? error <= *interval : error >= *interval)
+			break;
+		adj++;
+	}
+
+	/*
+	 * Add the current adjustments to the error and take the offset
+	 * into account, the latter can cause the error to be hardly
+	 * reduced at the next tick. Check the error again if there's
+	 * room for another adjustment, thus further reducing the error
+	 * which otherwise had to be corrected at the next update.
+	 */
+	error = (error << 1) - *interval + *offset;
+	if (sign > 0 ? error > *interval : error < *interval)
+		adj++;
+
+	*interval <<= adj;
+	*offset <<= adj;
+	return sign << adj;
+}
+
+/*
+ * Adjust the multiplier to reduce the error value,
+ * this is optimized for the most common adjustments of -1,0,1,
+ * for other values we can do a bit more work.
+ */
+static void clocksource_adjust(struct clocksource *clock, s64 offset)
+{
+	s64 error, interval = clock->cycle_interval;
+	int adj;
+
+	error = clock->error >> (TICK_LENGTH_SHIFT - clock->shift - 1);
+	if (error > interval) {
+		adj = clocksource_bigadjust(1, error, &interval, &offset);
+	} else if (error < -interval) {
+		interval = -interval;
+		offset = -offset;
+		adj = clocksource_bigadjust(-1, error, &interval, &offset);
+	} else
+		return;
+
+	clock->mult += adj;
+	clock->xtime_interval += interval;
+	clock->xtime_nsec -= offset;
+	clock->error -= (interval - offset) << (TICK_LENGTH_SHIFT - clock->shift);
+}
+
+/*
+ * update_wall_time - Uses the current clocksource to increment the wall time
+ *
+ * Called from the timer interrupt, must hold a write on xtime_lock.
+ */
+static void update_wall_time(void)
+{
+	cycle_t offset;
+
+	clock->xtime_nsec += (s64)xtime.tv_nsec << clock->shift;
+
+#ifdef CONFIG_GENERIC_TIME
+	offset = (clocksource_read(clock) - clock->cycle_last) & clock->mask;
+#else
+	offset = clock->cycle_interval;
+#endif
+
+	/* normally this loop will run just once, however in the
+	 * case of lost or late ticks, it will accumulate correctly.
+	 */
+	while (offset >= clock->cycle_interval) {
+		/* accumulate one interval */
+		clock->xtime_nsec += clock->xtime_interval;
+		clock->cycle_last += clock->cycle_interval;
+		offset -= clock->cycle_interval;
+
+		if (clock->xtime_nsec >= (u64)NSEC_PER_SEC << clock->shift) {
+			clock->xtime_nsec -= (u64)NSEC_PER_SEC << clock->shift;
 			xtime.tv_sec++;
 			second_overflow();
 		}
-	} while (ticks);
+
+		/* interpolator bits */
+		time_interpolator_update(clock->xtime_interval
+						>> clock->shift);
+		/* increment the NTP state machine */
+		update_ntp_one_tick();
+
+		/* accumulate error between NTP and clock interval */
+		clock->error += current_tick_length();
+		clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
+	}
+
+	/* correct the clock when NTP error is too big */
+	clocksource_adjust(clock, offset);
+
+	/* store full nanoseconds into xtime */
+	xtime.tv_nsec = clock->xtime_nsec >> clock->shift;
+	clock->xtime_nsec -= (s64)xtime.tv_nsec << clock->shift;
+
+	/* check to see if there is a new clocksource to use */
+	if (change_clocksource()) {
+		clock->error = 0;
+		clock->xtime_nsec = 0;
+		clocksource_calculate_interval(clock, tick_nsec);
+	}
 }
 
 /*
@@ -919,10 +1243,8 @@
 	unsigned long ticks;
 
 	ticks = jiffies - wall_jiffies;
-	if (ticks) {
-		wall_jiffies += ticks;
-		update_wall_time(ticks);
-	}
+	wall_jiffies += ticks;
+	update_wall_time();
 	calc_load(ticks);
 }
   
@@ -1330,7 +1652,7 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
-static int timer_cpu_notify(struct notifier_block *self,
+static int __devinit timer_cpu_notify(struct notifier_block *self,
 				unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -1350,7 +1672,7 @@
 	return NOTIFY_OK;
 }
 
-static struct notifier_block timers_nb = {
+static struct notifier_block __devinitdata timers_nb = {
 	.notifier_call	= timer_cpu_notify,
 };
 
diff --git a/kernel/unwind.c b/kernel/unwind.c
new file mode 100644
index 0000000..f69c804
--- /dev/null
+++ b/kernel/unwind.c
@@ -0,0 +1,918 @@
+/*
+ * Copyright (C) 2002-2006 Novell, Inc.
+ *	Jan Beulich <jbeulich@novell.com>
+ * This code is released under version 2 of the GNU GPL.
+ *
+ * A simple API for unwinding kernel stacks.  This is used for
+ * debugging and error reporting purposes.  The kernel doesn't need
+ * full-blown stack unwinding with all the bells and whistles, so there
+ * is not much point in implementing the full Dwarf2 unwind API.
+ */
+
+#include <linux/unwind.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/stop_machine.h>
+#include <asm/sections.h>
+#include <asm/uaccess.h>
+#include <asm/unaligned.h>
+
+extern char __start_unwind[], __end_unwind[];
+
+#define MAX_STACK_DEPTH 8
+
+#define EXTRA_INFO(f) { \
+		BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
+		                  % FIELD_SIZEOF(struct unwind_frame_info, f)) \
+		+ offsetof(struct unwind_frame_info, f) \
+		  / FIELD_SIZEOF(struct unwind_frame_info, f), \
+		FIELD_SIZEOF(struct unwind_frame_info, f) \
+	}
+#define PTREGS_INFO(f) EXTRA_INFO(regs.f)
+
+static const struct {
+	unsigned offs:BITS_PER_LONG / 2;
+	unsigned width:BITS_PER_LONG / 2;
+} reg_info[] = {
+	UNW_REGISTER_INFO
+};
+
+#undef PTREGS_INFO
+#undef EXTRA_INFO
+
+#ifndef REG_INVALID
+#define REG_INVALID(r) (reg_info[r].width == 0)
+#endif
+
+#define DW_CFA_nop                          0x00
+#define DW_CFA_set_loc                      0x01
+#define DW_CFA_advance_loc1                 0x02
+#define DW_CFA_advance_loc2                 0x03
+#define DW_CFA_advance_loc4                 0x04
+#define DW_CFA_offset_extended              0x05
+#define DW_CFA_restore_extended             0x06
+#define DW_CFA_undefined                    0x07
+#define DW_CFA_same_value                   0x08
+#define DW_CFA_register                     0x09
+#define DW_CFA_remember_state               0x0a
+#define DW_CFA_restore_state                0x0b
+#define DW_CFA_def_cfa                      0x0c
+#define DW_CFA_def_cfa_register             0x0d
+#define DW_CFA_def_cfa_offset               0x0e
+#define DW_CFA_def_cfa_expression           0x0f
+#define DW_CFA_expression                   0x10
+#define DW_CFA_offset_extended_sf           0x11
+#define DW_CFA_def_cfa_sf                   0x12
+#define DW_CFA_def_cfa_offset_sf            0x13
+#define DW_CFA_val_offset                   0x14
+#define DW_CFA_val_offset_sf                0x15
+#define DW_CFA_val_expression               0x16
+#define DW_CFA_lo_user                      0x1c
+#define DW_CFA_GNU_window_save              0x2d
+#define DW_CFA_GNU_args_size                0x2e
+#define DW_CFA_GNU_negative_offset_extended 0x2f
+#define DW_CFA_hi_user                      0x3f
+
+#define DW_EH_PE_FORM     0x07
+#define DW_EH_PE_native   0x00
+#define DW_EH_PE_leb128   0x01
+#define DW_EH_PE_data2    0x02
+#define DW_EH_PE_data4    0x03
+#define DW_EH_PE_data8    0x04
+#define DW_EH_PE_signed   0x08
+#define DW_EH_PE_ADJUST   0x70
+#define DW_EH_PE_abs      0x00
+#define DW_EH_PE_pcrel    0x10
+#define DW_EH_PE_textrel  0x20
+#define DW_EH_PE_datarel  0x30
+#define DW_EH_PE_funcrel  0x40
+#define DW_EH_PE_aligned  0x50
+#define DW_EH_PE_indirect 0x80
+#define DW_EH_PE_omit     0xff
+
+typedef unsigned long uleb128_t;
+typedef   signed long sleb128_t;
+
+static struct unwind_table {
+	struct {
+		unsigned long pc;
+		unsigned long range;
+	} core, init;
+	const void *address;
+	unsigned long size;
+	struct unwind_table *link;
+	const char *name;
+} root_table, *last_table;
+
+struct unwind_item {
+	enum item_location {
+		Nowhere,
+		Memory,
+		Register,
+		Value
+	} where;
+	uleb128_t value;
+};
+
+struct unwind_state {
+	uleb128_t loc, org;
+	const u8 *cieStart, *cieEnd;
+	uleb128_t codeAlign;
+	sleb128_t dataAlign;
+	struct cfa {
+		uleb128_t reg, offs;
+	} cfa;
+	struct unwind_item regs[ARRAY_SIZE(reg_info)];
+	unsigned stackDepth:8;
+	unsigned version:8;
+	const u8 *label;
+	const u8 *stack[MAX_STACK_DEPTH];
+};
+
+static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 };
+
+static struct unwind_table *find_table(unsigned long pc)
+{
+	struct unwind_table *table;
+
+	for (table = &root_table; table; table = table->link)
+		if ((pc >= table->core.pc
+		     && pc < table->core.pc + table->core.range)
+		    || (pc >= table->init.pc
+		        && pc < table->init.pc + table->init.range))
+			break;
+
+	return table;
+}
+
+static void init_unwind_table(struct unwind_table *table,
+                              const char *name,
+                              const void *core_start,
+                              unsigned long core_size,
+                              const void *init_start,
+                              unsigned long init_size,
+                              const void *table_start,
+                              unsigned long table_size)
+{
+	table->core.pc = (unsigned long)core_start;
+	table->core.range = core_size;
+	table->init.pc = (unsigned long)init_start;
+	table->init.range = init_size;
+	table->address = table_start;
+	table->size = table_size;
+	table->link = NULL;
+	table->name = name;
+}
+
+void __init unwind_init(void)
+{
+	init_unwind_table(&root_table, "kernel",
+	                  _text, _end - _text,
+	                  NULL, 0,
+	                  __start_unwind, __end_unwind - __start_unwind);
+}
+
+#ifdef CONFIG_MODULES
+
+/* Must be called with module_mutex held. */
+void *unwind_add_table(struct module *module,
+                       const void *table_start,
+                       unsigned long table_size)
+{
+	struct unwind_table *table;
+
+	if (table_size <= 0)
+		return NULL;
+
+	table = kmalloc(sizeof(*table), GFP_KERNEL);
+	if (!table)
+		return NULL;
+
+	init_unwind_table(table, module->name,
+	                  module->module_core, module->core_size,
+	                  module->module_init, module->init_size,
+	                  table_start, table_size);
+
+	if (last_table)
+		last_table->link = table;
+	else
+		root_table.link = table;
+	last_table = table;
+
+	return table;
+}
+
+struct unlink_table_info
+{
+	struct unwind_table *table;
+	int init_only;
+};
+
+static int unlink_table(void *arg)
+{
+	struct unlink_table_info *info = arg;
+	struct unwind_table *table = info->table, *prev;
+
+	for (prev = &root_table; prev->link && prev->link != table; prev = prev->link)
+		;
+
+	if (prev->link) {
+		if (info->init_only) {
+			table->init.pc = 0;
+			table->init.range = 0;
+			info->table = NULL;
+		} else {
+			prev->link = table->link;
+			if (!prev->link)
+				last_table = prev;
+		}
+	} else
+		info->table = NULL;
+
+	return 0;
+}
+
+/* Must be called with module_mutex held. */
+void unwind_remove_table(void *handle, int init_only)
+{
+	struct unwind_table *table = handle;
+	struct unlink_table_info info;
+
+	if (!table || table == &root_table)
+		return;
+
+	if (init_only && table == last_table) {
+		table->init.pc = 0;
+		table->init.range = 0;
+		return;
+	}
+
+	info.table = table;
+	info.init_only = init_only;
+	stop_machine_run(unlink_table, &info, NR_CPUS);
+
+	if (info.table)
+		kfree(table);
+}
+
+#endif /* CONFIG_MODULES */
+
+static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
+{
+	const u8 *cur = *pcur;
+	uleb128_t value;
+	unsigned shift;
+
+	for (shift = 0, value = 0; cur < end; shift += 7) {
+		if (shift + 7 > 8 * sizeof(value)
+		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+			cur = end + 1;
+			break;
+		}
+		value |= (uleb128_t)(*cur & 0x7f) << shift;
+		if (!(*cur++ & 0x80))
+			break;
+	}
+	*pcur = cur;
+
+	return value;
+}
+
+static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
+{
+	const u8 *cur = *pcur;
+	sleb128_t value;
+	unsigned shift;
+
+	for (shift = 0, value = 0; cur < end; shift += 7) {
+		if (shift + 7 > 8 * sizeof(value)
+		    && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) {
+			cur = end + 1;
+			break;
+		}
+		value |= (sleb128_t)(*cur & 0x7f) << shift;
+		if (!(*cur & 0x80)) {
+			value |= -(*cur++ & 0x40) << shift;
+			break;
+		}
+	}
+	*pcur = cur;
+
+	return value;
+}
+
+static unsigned long read_pointer(const u8 **pLoc,
+                                  const void *end,
+                                  signed ptrType)
+{
+	unsigned long value = 0;
+	union {
+		const u8 *p8;
+		const u16 *p16u;
+		const s16 *p16s;
+		const u32 *p32u;
+		const s32 *p32s;
+		const unsigned long *pul;
+	} ptr;
+
+	if (ptrType < 0 || ptrType == DW_EH_PE_omit)
+		return 0;
+	ptr.p8 = *pLoc;
+	switch(ptrType & DW_EH_PE_FORM) {
+	case DW_EH_PE_data2:
+		if (end < (const void *)(ptr.p16u + 1))
+			return 0;
+		if(ptrType & DW_EH_PE_signed)
+			value = get_unaligned(ptr.p16s++);
+		else
+			value = get_unaligned(ptr.p16u++);
+		break;
+	case DW_EH_PE_data4:
+#ifdef CONFIG_64BIT
+		if (end < (const void *)(ptr.p32u + 1))
+			return 0;
+		if(ptrType & DW_EH_PE_signed)
+			value = get_unaligned(ptr.p32s++);
+		else
+			value = get_unaligned(ptr.p32u++);
+		break;
+	case DW_EH_PE_data8:
+		BUILD_BUG_ON(sizeof(u64) != sizeof(value));
+#else
+		BUILD_BUG_ON(sizeof(u32) != sizeof(value));
+#endif
+	case DW_EH_PE_native:
+		if (end < (const void *)(ptr.pul + 1))
+			return 0;
+		value = get_unaligned(ptr.pul++);
+		break;
+	case DW_EH_PE_leb128:
+		BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value));
+		value = ptrType & DW_EH_PE_signed
+		        ? get_sleb128(&ptr.p8, end)
+		        : get_uleb128(&ptr.p8, end);
+		if ((const void *)ptr.p8 > end)
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+	switch(ptrType & DW_EH_PE_ADJUST) {
+	case DW_EH_PE_abs:
+		break;
+	case DW_EH_PE_pcrel:
+		value += (unsigned long)*pLoc;
+		break;
+	default:
+		return 0;
+	}
+	if ((ptrType & DW_EH_PE_indirect)
+	    && __get_user(value, (unsigned long *)value))
+		return 0;
+	*pLoc = ptr.p8;
+
+	return value;
+}
+
+static signed fde_pointer_type(const u32 *cie)
+{
+	const u8 *ptr = (const u8 *)(cie + 2);
+	unsigned version = *ptr;
+
+	if (version != 1)
+		return -1; /* unsupported */
+	if (*++ptr) {
+		const char *aug;
+		const u8 *end = (const u8 *)(cie + 1) + *cie;
+		uleb128_t len;
+
+		/* check if augmentation size is first (and thus present) */
+		if (*ptr != 'z')
+			return -1;
+		/* check if augmentation string is nul-terminated */
+		if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
+			return -1;
+		++ptr; /* skip terminator */
+		get_uleb128(&ptr, end); /* skip code alignment */
+		get_sleb128(&ptr, end); /* skip data alignment */
+		/* skip return address column */
+		version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end);
+		len = get_uleb128(&ptr, end); /* augmentation length */
+		if (ptr + len < ptr || ptr + len > end)
+			return -1;
+		end = ptr + len;
+		while (*++aug) {
+			if (ptr >= end)
+				return -1;
+			switch(*aug) {
+			case 'L':
+				++ptr;
+				break;
+			case 'P': {
+					signed ptrType = *ptr++;
+
+					if (!read_pointer(&ptr, end, ptrType) || ptr > end)
+						return -1;
+				}
+				break;
+			case 'R':
+				return *ptr;
+			default:
+				return -1;
+			}
+		}
+	}
+	return DW_EH_PE_native|DW_EH_PE_abs;
+}
+
+static int advance_loc(unsigned long delta, struct unwind_state *state)
+{
+	state->loc += delta * state->codeAlign;
+
+	return delta > 0;
+}
+
+static void set_rule(uleb128_t reg,
+                     enum item_location where,
+                     uleb128_t value,
+                     struct unwind_state *state)
+{
+	if (reg < ARRAY_SIZE(state->regs)) {
+		state->regs[reg].where = where;
+		state->regs[reg].value = value;
+	}
+}
+
+static int processCFI(const u8 *start,
+                      const u8 *end,
+                      unsigned long targetLoc,
+                      signed ptrType,
+                      struct unwind_state *state)
+{
+	union {
+		const u8 *p8;
+		const u16 *p16;
+		const u32 *p32;
+	} ptr;
+	int result = 1;
+
+	if (start != state->cieStart) {
+		state->loc = state->org;
+		result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state);
+		if (targetLoc == 0 && state->label == NULL)
+			return result;
+	}
+	for (ptr.p8 = start; result && ptr.p8 < end; ) {
+		switch(*ptr.p8 >> 6) {
+			uleb128_t value;
+
+		case 0:
+			switch(*ptr.p8++) {
+			case DW_CFA_nop:
+				break;
+			case DW_CFA_set_loc:
+				if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0)
+					result = 0;
+				break;
+			case DW_CFA_advance_loc1:
+				result = ptr.p8 < end && advance_loc(*ptr.p8++, state);
+				break;
+			case DW_CFA_advance_loc2:
+				result = ptr.p8 <= end + 2
+				         && advance_loc(*ptr.p16++, state);
+				break;
+			case DW_CFA_advance_loc4:
+				result = ptr.p8 <= end + 4
+				         && advance_loc(*ptr.p32++, state);
+				break;
+			case DW_CFA_offset_extended:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_val_offset:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value, Value, get_uleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_offset_extended_sf:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value, Memory, get_sleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_val_offset_sf:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value, Value, get_sleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_restore_extended:
+			case DW_CFA_undefined:
+			case DW_CFA_same_value:
+				set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state);
+				break;
+			case DW_CFA_register:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value,
+				         Register,
+				         get_uleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_remember_state:
+				if (ptr.p8 == state->label) {
+					state->label = NULL;
+					return 1;
+				}
+				if (state->stackDepth >= MAX_STACK_DEPTH)
+					return 0;
+				state->stack[state->stackDepth++] = ptr.p8;
+				break;
+			case DW_CFA_restore_state:
+				if (state->stackDepth) {
+					const uleb128_t loc = state->loc;
+					const u8 *label = state->label;
+
+					state->label = state->stack[state->stackDepth - 1];
+					memcpy(&state->cfa, &badCFA, sizeof(state->cfa));
+					memset(state->regs, 0, sizeof(state->regs));
+					state->stackDepth = 0;
+					result = processCFI(start, end, 0, ptrType, state);
+					state->loc = loc;
+					state->label = label;
+				} else
+					return 0;
+				break;
+			case DW_CFA_def_cfa:
+				state->cfa.reg = get_uleb128(&ptr.p8, end);
+				/*nobreak*/
+			case DW_CFA_def_cfa_offset:
+				state->cfa.offs = get_uleb128(&ptr.p8, end);
+				break;
+			case DW_CFA_def_cfa_sf:
+				state->cfa.reg = get_uleb128(&ptr.p8, end);
+				/*nobreak*/
+			case DW_CFA_def_cfa_offset_sf:
+				state->cfa.offs = get_sleb128(&ptr.p8, end)
+				                  * state->dataAlign;
+				break;
+			case DW_CFA_def_cfa_register:
+				state->cfa.reg = get_uleb128(&ptr.p8, end);
+				break;
+			/*todo case DW_CFA_def_cfa_expression: */
+			/*todo case DW_CFA_expression: */
+			/*todo case DW_CFA_val_expression: */
+			case DW_CFA_GNU_args_size:
+				get_uleb128(&ptr.p8, end);
+				break;
+			case DW_CFA_GNU_negative_offset_extended:
+				value = get_uleb128(&ptr.p8, end);
+				set_rule(value,
+				         Memory,
+				         (uleb128_t)0 - get_uleb128(&ptr.p8, end), state);
+				break;
+			case DW_CFA_GNU_window_save:
+			default:
+				result = 0;
+				break;
+			}
+			break;
+		case 1:
+			result = advance_loc(*ptr.p8++ & 0x3f, state);
+			break;
+		case 2:
+			value = *ptr.p8++ & 0x3f;
+			set_rule(value, Memory, get_uleb128(&ptr.p8, end), state);
+			break;
+		case 3:
+			set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state);
+			break;
+		}
+		if (ptr.p8 > end)
+			result = 0;
+		if (result && targetLoc != 0 && targetLoc < state->loc)
+			return 1;
+	}
+
+	return result
+	   && ptr.p8 == end
+	   && (targetLoc == 0
+	    || (/*todo While in theory this should apply, gcc in practice omits
+	          everything past the function prolog, and hence the location
+	          never reaches the end of the function.
+	        targetLoc < state->loc &&*/ state->label == NULL));
+}
+
+/* Unwind to previous to frame.  Returns 0 if successful, negative
+ * number in case of an error. */
+int unwind(struct unwind_frame_info *frame)
+{
+#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
+	const u32 *fde = NULL, *cie = NULL;
+	const u8 *ptr = NULL, *end = NULL;
+	unsigned long startLoc = 0, endLoc = 0, cfa;
+	unsigned i;
+	signed ptrType = -1;
+	uleb128_t retAddrReg = 0;
+	struct unwind_table *table;
+	struct unwind_state state;
+
+	if (UNW_PC(frame) == 0)
+		return -EINVAL;
+	if ((table = find_table(UNW_PC(frame))) != NULL
+	    && !(table->size & (sizeof(*fde) - 1))) {
+		unsigned long tableSize = table->size;
+
+		for (fde = table->address;
+		     tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde;
+		     tableSize -= sizeof(*fde) + *fde,
+		     fde += 1 + *fde / sizeof(*fde)) {
+			if (!*fde || (*fde & (sizeof(*fde) - 1)))
+				break;
+			if (!fde[1])
+				continue; /* this is a CIE */
+			if ((fde[1] & (sizeof(*fde) - 1))
+			    || fde[1] > (unsigned long)(fde + 1)
+			                - (unsigned long)table->address)
+				continue; /* this is not a valid FDE */
+			cie = fde + 1 - fde[1] / sizeof(*fde);
+			if (*cie <= sizeof(*cie) + 4
+			    || *cie >= fde[1] - sizeof(*fde)
+			    || (*cie & (sizeof(*cie) - 1))
+			    || cie[1]
+			    || (ptrType = fde_pointer_type(cie)) < 0) {
+				cie = NULL; /* this is not a (valid) CIE */
+				continue;
+			}
+			ptr = (const u8 *)(fde + 2);
+			startLoc = read_pointer(&ptr,
+			                        (const u8 *)(fde + 1) + *fde,
+			                        ptrType);
+			endLoc = startLoc
+			         + read_pointer(&ptr,
+			                        (const u8 *)(fde + 1) + *fde,
+			                        ptrType & DW_EH_PE_indirect
+			                        ? ptrType
+			                        : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
+			if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
+				break;
+			cie = NULL;
+		}
+	}
+	if (cie != NULL) {
+		memset(&state, 0, sizeof(state));
+		state.cieEnd = ptr; /* keep here temporarily */
+		ptr = (const u8 *)(cie + 2);
+		end = (const u8 *)(cie + 1) + *cie;
+		if ((state.version = *ptr) != 1)
+			cie = NULL; /* unsupported version */
+		else if (*++ptr) {
+			/* check if augmentation size is first (and thus present) */
+			if (*ptr == 'z') {
+				/* check for ignorable (or already handled)
+				 * nul-terminated augmentation string */
+				while (++ptr < end && *ptr)
+					if (strchr("LPR", *ptr) == NULL)
+						break;
+			}
+			if (ptr >= end || *ptr)
+				cie = NULL;
+		}
+		++ptr;
+	}
+	if (cie != NULL) {
+		/* get code aligment factor */
+		state.codeAlign = get_uleb128(&ptr, end);
+		/* get data aligment factor */
+		state.dataAlign = get_sleb128(&ptr, end);
+		if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end)
+			cie = NULL;
+		else {
+			retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end);
+			/* skip augmentation */
+			if (((const char *)(cie + 2))[1] == 'z')
+				ptr += get_uleb128(&ptr, end);
+			if (ptr > end
+			   || retAddrReg >= ARRAY_SIZE(reg_info)
+			   || REG_INVALID(retAddrReg)
+			   || reg_info[retAddrReg].width != sizeof(unsigned long))
+				cie = NULL;
+		}
+	}
+	if (cie != NULL) {
+		state.cieStart = ptr;
+		ptr = state.cieEnd;
+		state.cieEnd = end;
+		end = (const u8 *)(fde + 1) + *fde;
+		/* skip augmentation */
+		if (((const char *)(cie + 2))[1] == 'z') {
+			uleb128_t augSize = get_uleb128(&ptr, end);
+
+			if ((ptr += augSize) > end)
+				fde = NULL;
+		}
+	}
+	if (cie == NULL || fde == NULL) {
+#ifdef CONFIG_FRAME_POINTER
+		unsigned long top, bottom;
+#endif
+
+#ifdef CONFIG_FRAME_POINTER
+		top = STACK_TOP(frame->task);
+		bottom = STACK_BOTTOM(frame->task);
+# if FRAME_RETADDR_OFFSET < 0
+		if (UNW_SP(frame) < top
+		    && UNW_FP(frame) <= UNW_SP(frame)
+		    && bottom < UNW_FP(frame)
+# else
+		if (UNW_SP(frame) > top
+		    && UNW_FP(frame) >= UNW_SP(frame)
+		    && bottom > UNW_FP(frame)
+# endif
+		   && !((UNW_SP(frame) | UNW_FP(frame))
+		        & (sizeof(unsigned long) - 1))) {
+			unsigned long link;
+
+			if (!__get_user(link,
+			                (unsigned long *)(UNW_FP(frame)
+			                                  + FRAME_LINK_OFFSET))
+# if FRAME_RETADDR_OFFSET < 0
+			   && link > bottom && link < UNW_FP(frame)
+# else
+			   && link > UNW_FP(frame) && link < bottom
+# endif
+			   && !(link & (sizeof(link) - 1))
+			   && !__get_user(UNW_PC(frame),
+			                  (unsigned long *)(UNW_FP(frame)
+			                                    + FRAME_RETADDR_OFFSET))) {
+				UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET
+# if FRAME_RETADDR_OFFSET < 0
+					-
+# else
+					+
+# endif
+					  sizeof(UNW_PC(frame));
+				UNW_FP(frame) = link;
+				return 0;
+			}
+		}
+#endif
+		return -ENXIO;
+	}
+	state.org = startLoc;
+	memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
+	/* process instructions */
+	if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
+	   || state.loc > endLoc
+	   || state.regs[retAddrReg].where == Nowhere
+	   || state.cfa.reg >= ARRAY_SIZE(reg_info)
+	   || reg_info[state.cfa.reg].width != sizeof(unsigned long)
+	   || state.cfa.offs % sizeof(unsigned long))
+		return -EIO;
+	/* update frame */
+	cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
+	startLoc = min((unsigned long)UNW_SP(frame), cfa);
+	endLoc = max((unsigned long)UNW_SP(frame), cfa);
+	if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) {
+		startLoc = min(STACK_LIMIT(cfa), cfa);
+		endLoc = max(STACK_LIMIT(cfa), cfa);
+	}
+#ifndef CONFIG_64BIT
+# define CASES CASE(8); CASE(16); CASE(32)
+#else
+# define CASES CASE(8); CASE(16); CASE(32); CASE(64)
+#endif
+	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+		if (REG_INVALID(i)) {
+			if (state.regs[i].where == Nowhere)
+				continue;
+			return -EIO;
+		}
+		switch(state.regs[i].where) {
+		default:
+			break;
+		case Register:
+			if (state.regs[i].value >= ARRAY_SIZE(reg_info)
+			   || REG_INVALID(state.regs[i].value)
+			   || reg_info[i].width > reg_info[state.regs[i].value].width)
+				return -EIO;
+			switch(reg_info[state.regs[i].value].width) {
+#define CASE(n) \
+			case sizeof(u##n): \
+				state.regs[i].value = FRAME_REG(state.regs[i].value, \
+				                                const u##n); \
+				break
+			CASES;
+#undef CASE
+			default:
+				return -EIO;
+			}
+			break;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(state.regs); ++i) {
+		if (REG_INVALID(i))
+			continue;
+		switch(state.regs[i].where) {
+		case Nowhere:
+			if (reg_info[i].width != sizeof(UNW_SP(frame))
+			   || &FRAME_REG(i, __typeof__(UNW_SP(frame)))
+			      != &UNW_SP(frame))
+				continue;
+			UNW_SP(frame) = cfa;
+			break;
+		case Register:
+			switch(reg_info[i].width) {
+#define CASE(n) case sizeof(u##n): \
+				FRAME_REG(i, u##n) = state.regs[i].value; \
+				break
+			CASES;
+#undef CASE
+			default:
+				return -EIO;
+			}
+			break;
+		case Value:
+			if (reg_info[i].width != sizeof(unsigned long))
+				return -EIO;
+			FRAME_REG(i, unsigned long) = cfa + state.regs[i].value
+			                                    * state.dataAlign;
+			break;
+		case Memory: {
+				unsigned long addr = cfa + state.regs[i].value
+				                           * state.dataAlign;
+
+				if ((state.regs[i].value * state.dataAlign)
+				    % sizeof(unsigned long)
+				    || addr < startLoc
+				    || addr + sizeof(unsigned long) < addr
+				    || addr + sizeof(unsigned long) > endLoc)
+					return -EIO;
+				switch(reg_info[i].width) {
+#define CASE(n)     case sizeof(u##n): \
+					__get_user(FRAME_REG(i, u##n), (u##n *)addr); \
+					break
+				CASES;
+#undef CASE
+				default:
+					return -EIO;
+				}
+			}
+			break;
+		}
+	}
+
+	return 0;
+#undef CASES
+#undef FRAME_REG
+}
+EXPORT_SYMBOL(unwind);
+
+int unwind_init_frame_info(struct unwind_frame_info *info,
+                           struct task_struct *tsk,
+                           /*const*/ struct pt_regs *regs)
+{
+	info->task = tsk;
+	arch_unw_init_frame_info(info, regs);
+
+	return 0;
+}
+EXPORT_SYMBOL(unwind_init_frame_info);
+
+/*
+ * Prepare to unwind a blocked task.
+ */
+int unwind_init_blocked(struct unwind_frame_info *info,
+                        struct task_struct *tsk)
+{
+	info->task = tsk;
+	arch_unw_init_blocked(info);
+
+	return 0;
+}
+EXPORT_SYMBOL(unwind_init_blocked);
+
+/*
+ * Prepare to unwind the currently running thread.
+ */
+int unwind_init_running(struct unwind_frame_info *info,
+                        asmlinkage int (*callback)(struct unwind_frame_info *,
+                                                   void *arg),
+                        void *arg)
+{
+	info->task = current;
+
+	return arch_unwind_init_running(info, callback, arg);
+}
+EXPORT_SYMBOL(unwind_init_running);
+
+/*
+ * Unwind until the return pointer is in user-land (or until an error
+ * occurs).  Returns 0 if successful, negative number in case of
+ * error.
+ */
+int unwind_to_user(struct unwind_frame_info *info)
+{
+	while (!arch_unw_user_mode(info)) {
+		int err = unwind(info);
+
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(unwind_to_user);
diff --git a/kernel/user.c b/kernel/user.c
index 2116642..6408c04 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -140,7 +140,7 @@
 		atomic_set(&new->processes, 0);
 		atomic_set(&new->files, 0);
 		atomic_set(&new->sigpending, 0);
-#ifdef CONFIG_INOTIFY
+#ifdef CONFIG_INOTIFY_USER
 		atomic_set(&new->inotify_watches, 0);
 		atomic_set(&new->inotify_devs, 0);
 #endif
@@ -148,7 +148,7 @@
 		new->mq_bytes = 0;
 		new->locked_shm = 0;
 
-		if (alloc_uid_keyring(new) < 0) {
+		if (alloc_uid_keyring(new, current) < 0) {
 			kmem_cache_free(uid_cachep, new);
 			return NULL;
 		}
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 880fb41..59f0b42 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -428,22 +428,34 @@
 	return ret;
 }
 
-int schedule_on_each_cpu(void (*func) (void *info), void *info)
+/**
+ * schedule_on_each_cpu - call a function on each online CPU from keventd
+ * @func: the function to call
+ * @info: a pointer to pass to func()
+ *
+ * Returns zero on success.
+ * Returns -ve errno on failure.
+ *
+ * Appears to be racy against CPU hotplug.
+ *
+ * schedule_on_each_cpu() is very slow.
+ */
+int schedule_on_each_cpu(void (*func)(void *info), void *info)
 {
 	int cpu;
-	struct work_struct *work;
+	struct work_struct *works;
 
-	work = kmalloc(NR_CPUS * sizeof(struct work_struct), GFP_KERNEL);
-
-	if (!work)
+	works = alloc_percpu(struct work_struct);
+	if (!works)
 		return -ENOMEM;
+
 	for_each_online_cpu(cpu) {
-		INIT_WORK(work + cpu, func, info);
+		INIT_WORK(per_cpu_ptr(works, cpu), func, info);
 		__queue_work(per_cpu_ptr(keventd_wq->cpu_wq, cpu),
-				work + cpu);
+				per_cpu_ptr(works, cpu));
 	}
 	flush_workqueue(keventd_wq);
-	kfree(work);
+	free_percpu(works);
 	return 0;
 }
 
@@ -531,11 +543,11 @@
 static void take_over_work(struct workqueue_struct *wq, unsigned int cpu)
 {
 	struct cpu_workqueue_struct *cwq = per_cpu_ptr(wq->cpu_wq, cpu);
-	LIST_HEAD(list);
+	struct list_head list;
 	struct work_struct *work;
 
 	spin_lock_irq(&cwq->lock);
-	list_splice_init(&cwq->worklist, &list);
+	list_replace_init(&cwq->worklist, &list);
 
 	while (!list_empty(&list)) {
 		printk("Taking work for %s\n", wq->name);
@@ -547,7 +559,7 @@
 }
 
 /* We're holding the cpucontrol mutex here */
-static int workqueue_cpu_callback(struct notifier_block *nfb,
+static int __devinit workqueue_cpu_callback(struct notifier_block *nfb,
 				  unsigned long action,
 				  void *hcpu)
 {
@@ -578,6 +590,8 @@
 
 	case CPU_UP_CANCELED:
 		list_for_each_entry(wq, &workqueues, list) {
+			if (!per_cpu_ptr(wq->cpu_wq, hotcpu)->thread)
+				continue;
 			/* Unbind so it can run. */
 			kthread_bind(per_cpu_ptr(wq->cpu_wq, hotcpu)->thread,
 				     any_online_cpu(cpu_online_map));
diff --git a/lib/Kconfig b/lib/Kconfig
index 3de9335..f629934 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -86,4 +86,10 @@
 config TEXTSEARCH_FSM
 	tristate
 
+#
+# plist support is select#ed if needed
+#
+config PLIST
+	boolean
+
 endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ccb0c1f..e4fcbd1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -23,6 +23,22 @@
 	  keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
 	  unless you really know what this hack does.
 
+config UNUSED_SYMBOLS
+	bool "Enable unused/obsolete exported symbols"
+	default y if X86
+	help
+	  Unused but exported symbols make the kernel needlessly bigger.  For
+	  that reason most of these unused exports will soon be removed.  This
+	  option is provided temporarily to provide a transition period in case
+	  some external kernel module needs one of these symbols anyway. If you
+	  encounter such a case in your module, consider if you are actually
+	  using the right API.  (rationale: since nobody in the kernel is using
+	  this in a module, there is a pretty good chance it's actually the
+	  wrong interface to use).  If you really need the symbol, please send a
+	  mail to the linux kernel mailing list mentioning the symbol and why
+	  you really need it, and what the merge plan to the mainline kernel for
+	  your module is.
+
 config DEBUG_KERNEL
 	bool "Kernel debugging"
 	help
@@ -107,6 +123,24 @@
 	 This allows mutex semantics violations and mutex related deadlocks
 	 (lockups) to be detected and reported automatically.
 
+config DEBUG_RT_MUTEXES
+	bool "RT Mutex debugging, deadlock detection"
+	depends on DEBUG_KERNEL && RT_MUTEXES
+	help
+	 This allows rt mutex semantics violations and rt mutex related
+	 deadlocks (lockups) to be detected and reported automatically.
+
+config DEBUG_PI_LIST
+	bool
+	default y
+	depends on DEBUG_RT_MUTEXES
+
+config RT_MUTEX_TESTER
+	bool "Built-in scriptable tester for rt-mutexes"
+	depends on DEBUG_KERNEL && RT_MUTEXES
+	help
+	  This option enables a rt-mutex tester.
+
 config DEBUG_SPINLOCK
 	bool "Spinlock debugging"
 	depends on DEBUG_KERNEL
@@ -188,14 +222,22 @@
 
 config UNWIND_INFO
 	bool "Compile the kernel with frame unwind information"
-	depends on !IA64
-	depends on !MODULES || !(MIPS || PARISC || PPC || SUPERH || V850)
+	depends on !IA64 && !PARISC
+	depends on !MODULES || !(MIPS || PPC || SUPERH || V850)
 	help
 	  If you say Y here the resulting kernel image will be slightly larger
 	  but not slower, and it will give very useful debugging information.
 	  If you don't debug the kernel, you can say N, but we may not be able
 	  to solve problems without frame unwind information or frame pointers.
 
+config STACK_UNWIND
+	bool "Stack unwind support"
+	depends on UNWIND_INFO
+	depends on X86
+	help
+	  This enables more precise stack traces, omitting all unrelated
+	  occurrences of pointers into kernel code from the dump.
+
 config FORCED_INLINING
 	bool "Force gcc to inline functions marked 'inline'"
 	depends on DEBUG_KERNEL
diff --git a/lib/Makefile b/lib/Makefile
index b830c9a..10c13c9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -25,6 +25,7 @@
 lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
 lib-$(CONFIG_GENERIC_HWEIGHT) += hweight.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+obj-$(CONFIG_PLIST) += plist.o
 obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
@@ -46,6 +47,7 @@
 obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
 obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
 obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
+obj-$(CONFIG_SMP) += percpu_counter.o
 
 obj-$(CONFIG_SWIOTLB) += swiotlb.o
 
diff --git a/lib/bitmap.c b/lib/bitmap.c
index ed2ae3b..d71e38c 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -317,16 +317,16 @@
 
 /**
  * bitmap_parse - convert an ASCII hex string into a bitmap.
- * @buf: pointer to buffer in user space containing string.
- * @buflen: buffer size in bytes.  If string is smaller than this
+ * @ubuf: pointer to buffer in user space containing string.
+ * @ubuflen: buffer size in bytes.  If string is smaller than this
  *    then it must be terminated with a \0.
  * @maskp: pointer to bitmap array that will contain result.
  * @nmaskbits: size of bitmap, in bits.
  *
  * Commas group hex digits into chunks.  Each chunk defines exactly 32
  * bits of the resultant bitmask.  No chunk may specify a value larger
- * than 32 bits (-EOVERFLOW), and if a chunk specifies a smaller value
- * then leading 0-bits are prepended.  -EINVAL is returned for illegal
+ * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
+ * then leading 0-bits are prepended.  %-EINVAL is returned for illegal
  * characters and for grouping errors such as "1,,5", ",44", "," and "".
  * Leading and trailing whitespace accepted, but not embedded whitespace.
  */
@@ -452,8 +452,8 @@
 
 /**
  * bitmap_parselist - convert list format ASCII string to bitmap
- * @buf: read nul-terminated user string from this buffer
- * @mask: write resulting mask here
+ * @bp: read nul-terminated user string from this buffer
+ * @maskp: write resulting mask here
  * @nmaskbits: number of bits in mask to be written
  *
  * Input format is a comma-separated list of decimal numbers and
@@ -461,10 +461,11 @@
  * decimal numbers, the smallest and largest bit numbers set in
  * the range.
  *
- * Returns 0 on success, -errno on invalid input strings:
- *    -EINVAL:   second number in range smaller than first
- *    -EINVAL:   invalid character in string
- *    -ERANGE:   bit number specified too large for mask
+ * Returns 0 on success, -errno on invalid input strings.
+ * Error values:
+ *    %-EINVAL: second number in range smaller than first
+ *    %-EINVAL: invalid character in string
+ *    %-ERANGE: bit number specified too large for mask
  */
 int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
 {
@@ -625,10 +626,10 @@
 
 /**
  * bitmap_bitremap - Apply map defined by a pair of bitmaps to a single bit
- *	@oldbit - bit position to be mapped
- *      @old: defines domain of map
- *      @new: defines range of map
- *      @bits: number of bits in each of these bitmaps
+ *	@oldbit: bit position to be mapped
+ *	@old: defines domain of map
+ *	@new: defines range of map
+ *	@bits: number of bits in each of these bitmaps
  *
  * Let @old and @new define a mapping of bit positions, such that
  * whatever position is held by the n-th set bit in @old is mapped
@@ -790,7 +791,7 @@
  *
  * Allocate (set bits in) a specified region of a bitmap.
  *
- * Return 0 on success, or -EBUSY if specified region wasn't
+ * Return 0 on success, or %-EBUSY if specified region wasn't
  * free (not all bits were zero).
  */
 int bitmap_allocate_region(unsigned long *bitmap, int pos, int order)
diff --git a/lib/crc-ccitt.c b/lib/crc-ccitt.c
index 115d149..7f6dd68 100644
--- a/lib/crc-ccitt.c
+++ b/lib/crc-ccitt.c
@@ -53,9 +53,9 @@
 
 /**
  *	crc_ccitt - recompute the CRC for the data buffer
- *	@crc - previous CRC value
- *	@buffer - data pointer
- *	@len - number of bytes in the buffer
+ *	@crc: previous CRC value
+ *	@buffer: data pointer
+ *	@len: number of bytes in the buffer
  */
 u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
 {
diff --git a/lib/crc16.c b/lib/crc16.c
index 011fe57..8737b08 100644
--- a/lib/crc16.c
+++ b/lib/crc16.c
@@ -47,12 +47,12 @@
 EXPORT_SYMBOL(crc16_table);
 
 /**
- * Compute the CRC-16 for the data buffer
+ * crc16 - compute the CRC-16 for the data buffer
+ * @crc:	previous CRC value
+ * @buffer:	data pointer
+ * @len:	number of bytes in the buffer
  *
- * @param crc     previous CRC value
- * @param buffer  data pointer
- * @param len     number of bytes in the buffer
- * @return        the updated CRC value
+ * Returns the updated CRC value.
  */
 u16 crc16(u16 crc, u8 const *buffer, size_t len)
 {
diff --git a/lib/crc32.c b/lib/crc32.c
index 065198f..285fd9b 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -42,20 +42,21 @@
 MODULE_DESCRIPTION("Ethernet CRC32 calculations");
 MODULE_LICENSE("GPL");
 
+/**
+ * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
+ * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
+ *	other uses, or the previous crc32 value if computing incrementally.
+ * @p: pointer to buffer over which CRC is run
+ * @len: length of buffer @p
+ */
+u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len);
+
 #if CRC_LE_BITS == 1
 /*
  * In fact, the table-based code will work in this case, but it can be
  * simplified by inlining the table in ?: form.
  */
 
-/**
- * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
 u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
 {
 	int i;
@@ -68,14 +69,6 @@
 }
 #else				/* Table-based approach */
 
-/**
- * crc32_le() - Calculate bitwise little-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
 u32 __attribute_pure__ crc32_le(u32 crc, unsigned char const *p, size_t len)
 {
 # if CRC_LE_BITS == 8
@@ -145,20 +138,21 @@
 }
 #endif
 
+/**
+ * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
+ * @crc: seed value for computation.  ~0 for Ethernet, sometimes 0 for
+ *	other uses, or the previous crc32 value if computing incrementally.
+ * @p: pointer to buffer over which CRC is run
+ * @len: length of buffer @p
+ */
+u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len);
+
 #if CRC_BE_BITS == 1
 /*
  * In fact, the table-based code will work in this case, but it can be
  * simplified by inlining the table in ?: form.
  */
 
-/**
- * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
 u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
 {
 	int i;
@@ -173,14 +167,6 @@
 }
 
 #else				/* Table-based approach */
-/**
- * crc32_be() - Calculate bitwise big-endian Ethernet AUTODIN II CRC32
- * @crc - seed value for computation.  ~0 for Ethernet, sometimes 0 for
- *        other uses, or the previous crc32 value if computing incrementally.
- * @p   - pointer to buffer over which CRC is run
- * @len - length of buffer @p
- * 
- */
 u32 __attribute_pure__ crc32_be(u32 crc, unsigned char const *p, size_t len)
 {
 # if CRC_BE_BITS == 8
@@ -249,6 +235,10 @@
 }
 #endif
 
+/**
+ * bitreverse - reverse the order of bits in a u32 value
+ * @x: value to be bit-reversed
+ */
 u32 bitreverse(u32 x)
 {
 	x = (x >> 16) | (x << 16);
diff --git a/lib/genalloc.c b/lib/genalloc.c
index 9ce0a6a..71338b4 100644
--- a/lib/genalloc.c
+++ b/lib/genalloc.c
@@ -4,10 +4,6 @@
  * Uses for this includes on-device special memory, uncached memory
  * etc.
  *
- * This code is based on the buddy allocator found in the sym53c8xx_2
- * driver Copyright (C) 1999-2001  Gerard Roudier <groudier@free.fr>,
- * and adapted for general purpose use.
- *
  * Copyright 2005 (C) Jes Sorensen <jes@trained-monkey.org>
  *
  * This source code is licensed under the GNU General Public License,
@@ -15,172 +11,155 @@
  */
 
 #include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
 #include <linux/genalloc.h>
 
-#include <asm/page.h>
 
-
-struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift,
-				 unsigned long (*fp)(struct gen_pool *),
-				 unsigned long data)
+/*
+ * Create a new special memory pool.
+ *
+ * @min_alloc_order: log base 2 of number of bytes each bitmap bit represents
+ * @nid: node id of the node the pool structure should be allocated on, or -1
+ */
+struct gen_pool *gen_pool_create(int min_alloc_order, int nid)
 {
-	struct gen_pool *poolp;
-	unsigned long tmp;
-	int i;
+	struct gen_pool *pool;
 
-	/*
-	 * This is really an arbitrary limit, +10 is enough for
-	 * IA64_GRANULE_SHIFT, aka 16MB. If anyone needs a large limit
-	 * this can be increased without problems.
-	 */
-	if ((max_chunk_shift > (PAGE_SHIFT + 10)) ||
-	    ((max_chunk_shift < ALLOC_MIN_SHIFT) && max_chunk_shift))
-		return NULL;
-
-	if (!max_chunk_shift)
-		max_chunk_shift = PAGE_SHIFT;
-
-	poolp = kmalloc(sizeof(struct gen_pool), GFP_KERNEL);
-	if (!poolp)
-		return NULL;
-	memset(poolp, 0, sizeof(struct gen_pool));
-	poolp->h = kmalloc(sizeof(struct gen_pool_link) *
-			   (max_chunk_shift - ALLOC_MIN_SHIFT + 1),
-			   GFP_KERNEL);
-	if (!poolp->h) {
-		printk(KERN_WARNING "gen_pool_alloc() failed to allocate\n");
-		kfree(poolp);
-		return NULL;
+	pool = kmalloc_node(sizeof(struct gen_pool), GFP_KERNEL, nid);
+	if (pool != NULL) {
+		rwlock_init(&pool->lock);
+		INIT_LIST_HEAD(&pool->chunks);
+		pool->min_alloc_order = min_alloc_order;
 	}
-	memset(poolp->h, 0, sizeof(struct gen_pool_link) *
-	       (max_chunk_shift - ALLOC_MIN_SHIFT + 1));
-
-	spin_lock_init(&poolp->lock);
-	poolp->get_new_chunk = fp;
-	poolp->max_chunk_shift = max_chunk_shift;
-	poolp->private = data;
-
-	for (i = 0; i < nr_chunks; i++) {
-		tmp = poolp->get_new_chunk(poolp);
-		printk(KERN_INFO "allocated %lx\n", tmp);
-		if (!tmp)
-			break;
-		gen_pool_free(poolp, tmp, (1 << poolp->max_chunk_shift));
-	}
-
-	return poolp;
+	return pool;
 }
 EXPORT_SYMBOL(gen_pool_create);
 
 
 /*
- *  Simple power of two buddy-like generic allocator.
- *  Provides naturally aligned memory chunks.
+ * Add a new chunk of memory to the specified pool.
+ *
+ * @pool: pool to add new memory chunk to
+ * @addr: starting address of memory chunk to add to pool
+ * @size: size in bytes of the memory chunk to add to pool
+ * @nid: node id of the node the chunk structure and bitmap should be
+ *       allocated on, or -1
  */
-unsigned long gen_pool_alloc(struct gen_pool *poolp, int size)
+int gen_pool_add(struct gen_pool *pool, unsigned long addr, size_t size,
+		 int nid)
 {
-	int j, i, s, max_chunk_size;
-	unsigned long a, flags;
-	struct gen_pool_link *h = poolp->h;
+	struct gen_pool_chunk *chunk;
+	int nbits = size >> pool->min_alloc_order;
+	int nbytes = sizeof(struct gen_pool_chunk) +
+				(nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
 
-	max_chunk_size = 1 << poolp->max_chunk_shift;
+	chunk = kmalloc_node(nbytes, GFP_KERNEL, nid);
+	if (unlikely(chunk == NULL))
+		return -1;
 
-	if (size > max_chunk_size)
+	memset(chunk, 0, nbytes);
+	spin_lock_init(&chunk->lock);
+	chunk->start_addr = addr;
+	chunk->end_addr = addr + size;
+
+	write_lock(&pool->lock);
+	list_add(&chunk->next_chunk, &pool->chunks);
+	write_unlock(&pool->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(gen_pool_add);
+
+
+/*
+ * Allocate the requested number of bytes from the specified pool.
+ * Uses a first-fit algorithm.
+ *
+ * @pool: pool to allocate from
+ * @size: number of bytes to allocate from the pool
+ */
+unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
+{
+	struct list_head *_chunk;
+	struct gen_pool_chunk *chunk;
+	unsigned long addr, flags;
+	int order = pool->min_alloc_order;
+	int nbits, bit, start_bit, end_bit;
+
+	if (size == 0)
 		return 0;
 
-	size = max(size, 1 << ALLOC_MIN_SHIFT);
-	i = fls(size - 1);
-	s = 1 << i;
-	j = i -= ALLOC_MIN_SHIFT;
+	nbits = (size + (1UL << order) - 1) >> order;
 
-	spin_lock_irqsave(&poolp->lock, flags);
-	while (!h[j].next) {
-		if (s == max_chunk_size) {
-			struct gen_pool_link *ptr;
-			spin_unlock_irqrestore(&poolp->lock, flags);
-			ptr = (struct gen_pool_link *)poolp->get_new_chunk(poolp);
-			spin_lock_irqsave(&poolp->lock, flags);
-			h[j].next = ptr;
-			if (h[j].next)
-				h[j].next->next = NULL;
-			break;
+	read_lock(&pool->lock);
+	list_for_each(_chunk, &pool->chunks) {
+		chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
+
+		end_bit = (chunk->end_addr - chunk->start_addr) >> order;
+		end_bit -= nbits + 1;
+
+		spin_lock_irqsave(&chunk->lock, flags);
+		bit = -1;
+		while (bit + 1 < end_bit) {
+			bit = find_next_zero_bit(chunk->bits, end_bit, bit + 1);
+			if (bit >= end_bit)
+				break;
+
+			start_bit = bit;
+			if (nbits > 1) {
+				bit = find_next_bit(chunk->bits, bit + nbits,
+							bit + 1);
+				if (bit - start_bit < nbits)
+					continue;
+			}
+
+			addr = chunk->start_addr +
+					    ((unsigned long)start_bit << order);
+			while (nbits--)
+				__set_bit(start_bit++, &chunk->bits);
+			spin_unlock_irqrestore(&chunk->lock, flags);
+			read_unlock(&pool->lock);
+			return addr;
 		}
-		j++;
-		s <<= 1;
+		spin_unlock_irqrestore(&chunk->lock, flags);
 	}
-	a = (unsigned long) h[j].next;
-	if (a) {
-		h[j].next = h[j].next->next;
-		/*
-		 * This should be split into a seperate function doing
-		 * the chunk split in order to support custom
-		 * handling memory not physically accessible by host
-		 */
-		while (j > i) {
-			j -= 1;
-			s >>= 1;
-			h[j].next = (struct gen_pool_link *) (a + s);
-			h[j].next->next = NULL;
-		}
-	}
-	spin_unlock_irqrestore(&poolp->lock, flags);
-	return a;
+	read_unlock(&pool->lock);
+	return 0;
 }
 EXPORT_SYMBOL(gen_pool_alloc);
 
 
 /*
- *  Counter-part of the generic allocator.
+ * Free the specified memory back to the specified pool.
+ *
+ * @pool: pool to free to
+ * @addr: starting address of memory to free back to pool
+ * @size: size in bytes of memory to free
  */
-void gen_pool_free(struct gen_pool *poolp, unsigned long ptr, int size)
+void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size)
 {
-	struct gen_pool_link *q;
-	struct gen_pool_link *h = poolp->h;
-	unsigned long a, b, flags;
-	int i, s, max_chunk_size;
+	struct list_head *_chunk;
+	struct gen_pool_chunk *chunk;
+	unsigned long flags;
+	int order = pool->min_alloc_order;
+	int bit, nbits;
 
-	max_chunk_size = 1 << poolp->max_chunk_shift;
+	nbits = (size + (1UL << order) - 1) >> order;
 
-	if (size > max_chunk_size)
-		return;
+	read_lock(&pool->lock);
+	list_for_each(_chunk, &pool->chunks) {
+		chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);
 
-	size = max(size, 1 << ALLOC_MIN_SHIFT);
-	i = fls(size - 1);
-	s = 1 << i;
-	i -= ALLOC_MIN_SHIFT;
-
-	a = ptr;
-
-	spin_lock_irqsave(&poolp->lock, flags);
-	while (1) {
-		if (s == max_chunk_size) {
-			((struct gen_pool_link *)a)->next = h[i].next;
-			h[i].next = (struct gen_pool_link *)a;
+		if (addr >= chunk->start_addr && addr < chunk->end_addr) {
+			BUG_ON(addr + size > chunk->end_addr);
+			spin_lock_irqsave(&chunk->lock, flags);
+			bit = (addr - chunk->start_addr) >> order;
+			while (nbits--)
+				__clear_bit(bit++, &chunk->bits);
+			spin_unlock_irqrestore(&chunk->lock, flags);
 			break;
 		}
-		b = a ^ s;
-		q = &h[i];
-
-		while (q->next && q->next != (struct gen_pool_link *)b)
-			q = q->next;
-
-		if (!q->next) {
-			((struct gen_pool_link *)a)->next = h[i].next;
-			h[i].next = (struct gen_pool_link *)a;
-			break;
-		}
-		q->next = q->next->next;
-		a = a & b;
-		s <<= 1;
-		i++;
 	}
-	spin_unlock_irqrestore(&poolp->lock, flags);
+	BUG_ON(nbits > 0);
+	read_unlock(&pool->lock);
 }
 EXPORT_SYMBOL(gen_pool_free);
diff --git a/lib/idr.c b/lib/idr.c
index d226259..4d09681 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -29,6 +29,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #endif
+#include <linux/err.h>
 #include <linux/string.h>
 #include <linux/idr.h>
 
@@ -48,15 +49,21 @@
 	return(p);
 }
 
+/* only called when idp->lock is held */
+static void __free_layer(struct idr *idp, struct idr_layer *p)
+{
+	p->ary[0] = idp->id_free;
+	idp->id_free = p;
+	idp->id_free_cnt++;
+}
+
 static void free_layer(struct idr *idp, struct idr_layer *p)
 {
 	/*
 	 * Depends on the return element being zeroed.
 	 */
 	spin_lock(&idp->lock);
-	p->ary[0] = idp->id_free;
-	idp->id_free = p;
-	idp->id_free_cnt++;
+	__free_layer(idp, p);
 	spin_unlock(&idp->lock);
 }
 
@@ -184,12 +191,14 @@
 			 * The allocation failed.  If we built part of
 			 * the structure tear it down.
 			 */
+			spin_lock(&idp->lock);
 			for (new = p; p && p != idp->top; new = p) {
 				p = p->ary[0];
 				new->ary[0] = NULL;
 				new->bitmap = new->count = 0;
-				free_layer(idp, new);
+				__free_layer(idp, new);
 			}
+			spin_unlock(&idp->lock);
 			return -1;
 		}
 		new->ary[0] = p;
@@ -390,6 +399,48 @@
 }
 EXPORT_SYMBOL(idr_find);
 
+/**
+ * idr_replace - replace pointer for given id
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the id
+ * @id: lookup key
+ *
+ * Replace the pointer registered with an id and return the old value.
+ * A -ENOENT return indicates that @id was not found.
+ * A -EINVAL return indicates that @id was not within valid constraints.
+ *
+ * The caller must serialize vs idr_find(), idr_get_new(), and idr_remove().
+ */
+void *idr_replace(struct idr *idp, void *ptr, int id)
+{
+	int n;
+	struct idr_layer *p, *old_p;
+
+	n = idp->layers * IDR_BITS;
+	p = idp->top;
+
+	id &= MAX_ID_MASK;
+
+	if (id >= (1 << n))
+		return ERR_PTR(-EINVAL);
+
+	n -= IDR_BITS;
+	while ((n > 0) && p) {
+		p = p->ary[(id >> n) & IDR_MASK];
+		n -= IDR_BITS;
+	}
+
+	n = id & IDR_MASK;
+	if (unlikely(p == NULL || !test_bit(n, &p->bitmap)))
+		return ERR_PTR(-ENOENT);
+
+	old_p = p->ary[n];
+	p->ary[n] = ptr;
+
+	return old_p;
+}
+EXPORT_SYMBOL(idr_replace);
+
 static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache,
 		unsigned long flags)
 {
diff --git a/lib/iomap_copy.c b/lib/iomap_copy.c
index 351045f..864fc5e 100644
--- a/lib/iomap_copy.c
+++ b/lib/iomap_copy.c
@@ -40,3 +40,31 @@
 		__raw_writel(*src++, dst++);
 }
 EXPORT_SYMBOL_GPL(__iowrite32_copy);
+
+/**
+ * __iowrite64_copy - copy data to MMIO space, in 64-bit or 32-bit units
+ * @to: destination, in MMIO space (must be 64-bit aligned)
+ * @from: source (must be 64-bit aligned)
+ * @count: number of 64-bit quantities to copy
+ *
+ * Copy data from kernel space to MMIO space, in units of 32 or 64 bits at a
+ * time.  Order of access is not guaranteed, nor is a memory barrier
+ * performed afterwards.
+ */
+void __attribute__((weak)) __iowrite64_copy(void __iomem *to,
+					    const void *from,
+					    size_t count)
+{
+#ifdef CONFIG_64BIT
+	u64 __iomem *dst = to;
+	const u64 *src = from;
+	const u64 *end = src + count;
+
+	while (src < end)
+		__raw_writeq(*src++, dst++);
+#else
+	__iowrite32_copy(to, from, count * 2);
+#endif
+}
+
+EXPORT_SYMBOL_GPL(__iowrite64_copy);
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index cb5490e..e713e86 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -14,7 +14,7 @@
  * The 'big kernel semaphore'
  *
  * This mutex is taken and released recursively by lock_kernel()
- * and unlock_kernel().  It is transparently dropped and reaquired
+ * and unlock_kernel().  It is transparently dropped and reacquired
  * over schedule().  It is used to protect legacy code that hasn't
  * been migrated to a proper locking design yet.
  *
@@ -92,7 +92,7 @@
  * The 'big kernel lock'
  *
  * This spinlock is taken and released recursively by lock_kernel()
- * and unlock_kernel().  It is transparently dropped and reaquired
+ * and unlock_kernel().  It is transparently dropped and reacquired
  * over schedule().  It is used to protect legacy code that hasn't
  * been migrated to a proper locking design yet.
  *
diff --git a/lib/kobject.c b/lib/kobject.c
index 687ab41..8e7c719 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -198,14 +198,14 @@
 
 		/* be noisy on error issues */
 		if (error == -EEXIST)
-			pr_debug("kobject_add failed for %s with -EEXIST, "
+			printk("kobject_add failed for %s with -EEXIST, "
 			       "don't try to register things with the "
 			       "same name in the same directory.\n",
 			       kobject_name(kobj));
 		else
-			pr_debug("kobject_add failed for %s (%d)\n",
+			printk("kobject_add failed for %s (%d)\n",
 			       kobject_name(kobj), error);
-		/* dump_stack(); */
+		 dump_stack();
 	}
 
 	return error;
diff --git a/lib/libcrc32c.c b/lib/libcrc32c.c
index 52b6dc1..60f4680 100644
--- a/lib/libcrc32c.c
+++ b/lib/libcrc32c.c
@@ -88,7 +88,7 @@
  * reflect output bytes = true
  */
 
-static u32 crc32c_table[256] = {
+static const u32 crc32c_table[256] = {
 	0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
 	0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
 	0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c
new file mode 100644
index 0000000..8504490
--- /dev/null
+++ b/lib/percpu_counter.c
@@ -0,0 +1,46 @@
+/*
+ * Fast batching percpu counters.
+ */
+
+#include <linux/percpu_counter.h>
+#include <linux/module.h>
+
+void percpu_counter_mod(struct percpu_counter *fbc, s32 amount)
+{
+	long count;
+	s32 *pcount;
+	int cpu = get_cpu();
+
+	pcount = per_cpu_ptr(fbc->counters, cpu);
+	count = *pcount + amount;
+	if (count >= FBC_BATCH || count <= -FBC_BATCH) {
+		spin_lock(&fbc->lock);
+		fbc->count += count;
+		*pcount = 0;
+		spin_unlock(&fbc->lock);
+	} else {
+		*pcount = count;
+	}
+	put_cpu();
+}
+EXPORT_SYMBOL(percpu_counter_mod);
+
+/*
+ * Add up all the per-cpu counts, return the result.  This is a more accurate
+ * but much slower version of percpu_counter_read_positive()
+ */
+s64 percpu_counter_sum(struct percpu_counter *fbc)
+{
+	s64 ret;
+	int cpu;
+
+	spin_lock(&fbc->lock);
+	ret = fbc->count;
+	for_each_possible_cpu(cpu) {
+		s32 *pcount = per_cpu_ptr(fbc->counters, cpu);
+		ret += *pcount;
+	}
+	spin_unlock(&fbc->lock);
+	return ret < 0 ? 0 : ret;
+}
+EXPORT_SYMBOL(percpu_counter_sum);
diff --git a/lib/plist.c b/lib/plist.c
new file mode 100644
index 0000000..3074a02
--- /dev/null
+++ b/lib/plist.c
@@ -0,0 +1,118 @@
+/*
+ * lib/plist.c
+ *
+ * Descending-priority-sorted double-linked list
+ *
+ * (C) 2002-2003 Intel Corp
+ * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>.
+ *
+ * 2001-2005 (c) MontaVista Software, Inc.
+ * Daniel Walker <dwalker@mvista.com>
+ *
+ * (C) 2005 Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Simplifications of the original code by
+ * Oleg Nesterov <oleg@tv-sign.ru>
+ *
+ * Licensed under the FSF's GNU Public License v2 or later.
+ *
+ * Based on simple lists (include/linux/list.h).
+ *
+ * This file contains the add / del functions which are considered to
+ * be too large to inline. See include/linux/plist.h for further
+ * information.
+ */
+
+#include <linux/plist.h>
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_DEBUG_PI_LIST
+
+static void plist_check_prev_next(struct list_head *t, struct list_head *p,
+				  struct list_head *n)
+{
+	if (n->prev != p || p->next != n) {
+		printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev);
+		printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev);
+		printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev);
+		WARN_ON(1);
+	}
+}
+
+static void plist_check_list(struct list_head *top)
+{
+	struct list_head *prev = top, *next = top->next;
+
+	plist_check_prev_next(top, prev, next);
+	while (next != top) {
+		prev = next;
+		next = prev->next;
+		plist_check_prev_next(top, prev, next);
+	}
+}
+
+static void plist_check_head(struct plist_head *head)
+{
+	WARN_ON(!head->lock);
+	if (head->lock)
+		WARN_ON_SMP(!spin_is_locked(head->lock));
+	plist_check_list(&head->prio_list);
+	plist_check_list(&head->node_list);
+}
+
+#else
+# define plist_check_head(h)	do { } while (0)
+#endif
+
+/**
+ * plist_add - add @node to @head
+ *
+ * @node:	&struct plist_node pointer
+ * @head:	&struct plist_head pointer
+ */
+void plist_add(struct plist_node *node, struct plist_head *head)
+{
+	struct plist_node *iter;
+
+	plist_check_head(head);
+	WARN_ON(!plist_node_empty(node));
+
+	list_for_each_entry(iter, &head->prio_list, plist.prio_list) {
+		if (node->prio < iter->prio)
+			goto lt_prio;
+		else if (node->prio == iter->prio) {
+			iter = list_entry(iter->plist.prio_list.next,
+					struct plist_node, plist.prio_list);
+			goto eq_prio;
+		}
+	}
+
+lt_prio:
+	list_add_tail(&node->plist.prio_list, &iter->plist.prio_list);
+eq_prio:
+	list_add_tail(&node->plist.node_list, &iter->plist.node_list);
+
+	plist_check_head(head);
+}
+
+/**
+ * plist_del - Remove a @node from plist.
+ *
+ * @node:	&struct plist_node pointer - entry to be removed
+ * @head:	&struct plist_head pointer - list head
+ */
+void plist_del(struct plist_node *node, struct plist_head *head)
+{
+	plist_check_head(head);
+
+	if (!list_empty(&node->plist.prio_list)) {
+		struct plist_node *next = plist_first(&node->plist);
+
+		list_move_tail(&next->plist.prio_list, &node->plist.prio_list);
+		list_del_init(&node->plist.prio_list);
+	}
+
+	list_del_init(&node->plist.node_list);
+
+	plist_check_head(head);
+}
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 7097bb2..637d556 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -33,7 +33,7 @@
 
 
 #ifdef __KERNEL__
-#define RADIX_TREE_MAP_SHIFT	6
+#define RADIX_TREE_MAP_SHIFT	(CONFIG_BASE_SMALL ? 4 : 6)
 #else
 #define RADIX_TREE_MAP_SHIFT	3	/* For more stressful testing */
 #endif
@@ -74,6 +74,11 @@
 };
 DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, };
 
+static inline gfp_t root_gfp_mask(struct radix_tree_root *root)
+{
+	return root->gfp_mask & __GFP_BITS_MASK;
+}
+
 /*
  * This assumes that the caller has performed appropriate preallocation, and
  * that the caller has pinned this thread of control to the current CPU.
@@ -82,9 +87,10 @@
 radix_tree_node_alloc(struct radix_tree_root *root)
 {
 	struct radix_tree_node *ret;
+	gfp_t gfp_mask = root_gfp_mask(root);
 
-	ret = kmem_cache_alloc(radix_tree_node_cachep, root->gfp_mask);
-	if (ret == NULL && !(root->gfp_mask & __GFP_WAIT)) {
+	ret = kmem_cache_alloc(radix_tree_node_cachep, gfp_mask);
+	if (ret == NULL && !(gfp_mask & __GFP_WAIT)) {
 		struct radix_tree_preload *rtp;
 
 		rtp = &__get_cpu_var(radix_tree_preloads);
@@ -152,6 +158,27 @@
 	return test_bit(offset, node->tags[tag]);
 }
 
+static inline void root_tag_set(struct radix_tree_root *root, unsigned int tag)
+{
+	root->gfp_mask |= (1 << (tag + __GFP_BITS_SHIFT));
+}
+
+
+static inline void root_tag_clear(struct radix_tree_root *root, unsigned int tag)
+{
+	root->gfp_mask &= ~(1 << (tag + __GFP_BITS_SHIFT));
+}
+
+static inline void root_tag_clear_all(struct radix_tree_root *root)
+{
+	root->gfp_mask &= __GFP_BITS_MASK;
+}
+
+static inline int root_tag_get(struct radix_tree_root *root, unsigned int tag)
+{
+	return root->gfp_mask & (1 << (tag + __GFP_BITS_SHIFT));
+}
+
 /*
  * Returns 1 if any slot in the node has this tag set.
  * Otherwise returns 0.
@@ -182,7 +209,6 @@
 {
 	struct radix_tree_node *node;
 	unsigned int height;
-	char tags[RADIX_TREE_MAX_TAGS];
 	int tag;
 
 	/* Figure out what the height should be.  */
@@ -195,16 +221,6 @@
 		goto out;
 	}
 
-	/*
-	 * Prepare the tag status of the top-level node for propagation
-	 * into the newly-pushed top-level node(s)
-	 */
-	for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
-		tags[tag] = 0;
-		if (any_tag_set(root->rnode, tag))
-			tags[tag] = 1;
-	}
-
 	do {
 		if (!(node = radix_tree_node_alloc(root)))
 			return -ENOMEM;
@@ -214,7 +230,7 @@
 
 		/* Propagate the aggregated tag info into the new root */
 		for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
-			if (tags[tag])
+			if (root_tag_get(root, tag))
 				tag_set(node, tag, 0);
 		}
 
@@ -243,8 +259,7 @@
 	int error;
 
 	/* Make sure the tree is high enough.  */
-	if ((!index && !root->rnode) ||
-			index > radix_tree_maxindex(root->height)) {
+	if (index > radix_tree_maxindex(root->height)) {
 		error = radix_tree_extend(root, index);
 		if (error)
 			return error;
@@ -255,7 +270,7 @@
 	shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 
 	offset = 0;			/* uninitialised var warning */
-	do {
+	while (height > 0) {
 		if (slot == NULL) {
 			/* Have to add a child node.  */
 			if (!(slot = radix_tree_node_alloc(root)))
@@ -273,16 +288,21 @@
 		slot = node->slots[offset];
 		shift -= RADIX_TREE_MAP_SHIFT;
 		height--;
-	} while (height > 0);
+	}
 
 	if (slot != NULL)
 		return -EEXIST;
 
-	BUG_ON(!node);
-	node->count++;
-	node->slots[offset] = item;
-	BUG_ON(tag_get(node, 0, offset));
-	BUG_ON(tag_get(node, 1, offset));
+	if (node) {
+		node->count++;
+		node->slots[offset] = item;
+		BUG_ON(tag_get(node, 0, offset));
+		BUG_ON(tag_get(node, 1, offset));
+	} else {
+		root->rnode = item;
+		BUG_ON(root_tag_get(root, 0));
+		BUG_ON(root_tag_get(root, 1));
+	}
 
 	return 0;
 }
@@ -295,9 +315,13 @@
 	struct radix_tree_node **slot;
 
 	height = root->height;
+
 	if (index > radix_tree_maxindex(height))
 		return NULL;
 
+	if (height == 0 && root->rnode)
+		return (void **)&root->rnode;
+
 	shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 	slot = &root->rnode;
 
@@ -365,11 +389,10 @@
 	struct radix_tree_node *slot;
 
 	height = root->height;
-	if (index > radix_tree_maxindex(height))
-		return NULL;
+	BUG_ON(index > radix_tree_maxindex(height));
 
-	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
 	slot = root->rnode;
+	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
 
 	while (height > 0) {
 		int offset;
@@ -383,6 +406,10 @@
 		height--;
 	}
 
+	/* set the root's tag bit */
+	if (slot && !root_tag_get(root, tag))
+		root_tag_set(root, tag);
+
 	return slot;
 }
 EXPORT_SYMBOL(radix_tree_tag_set);
@@ -405,9 +432,8 @@
 			unsigned long index, unsigned int tag)
 {
 	struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
-	struct radix_tree_node *slot;
+	struct radix_tree_node *slot = NULL;
 	unsigned int height, shift;
-	void *ret = NULL;
 
 	height = root->height;
 	if (index > radix_tree_maxindex(height))
@@ -432,20 +458,24 @@
 		height--;
 	}
 
-	ret = slot;
-	if (ret == NULL)
+	if (slot == NULL)
 		goto out;
 
-	do {
+	while (pathp->node) {
 		if (!tag_get(pathp->node, tag, pathp->offset))
 			goto out;
 		tag_clear(pathp->node, tag, pathp->offset);
 		if (any_tag_set(pathp->node, tag))
 			goto out;
 		pathp--;
-	} while (pathp->node);
+	}
+
+	/* clear the root's tag bit */
+	if (root_tag_get(root, tag))
+		root_tag_clear(root, tag);
+
 out:
-	return ret;
+	return slot;
 }
 EXPORT_SYMBOL(radix_tree_tag_clear);
 
@@ -458,9 +488,8 @@
  *
  * Return values:
  *
- *  0: tag not present
- *  1: tag present, set
- * -1: tag present, unset
+ *  0: tag not present or not set
+ *  1: tag set
  */
 int radix_tree_tag_get(struct radix_tree_root *root,
 			unsigned long index, unsigned int tag)
@@ -473,6 +502,13 @@
 	if (index > radix_tree_maxindex(height))
 		return 0;
 
+	/* check the root's tag bit */
+	if (!root_tag_get(root, tag))
+		return 0;
+
+	if (height == 0)
+		return 1;
+
 	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
 	slot = root->rnode;
 
@@ -494,7 +530,7 @@
 			int ret = tag_get(slot, tag, offset);
 
 			BUG_ON(ret && saw_unset_tag);
-			return ret ? 1 : -1;
+			return !!ret;
 		}
 		slot = slot->slots[offset];
 		shift -= RADIX_TREE_MAP_SHIFT;
@@ -514,8 +550,11 @@
 	unsigned long i;
 
 	height = root->height;
-	if (height == 0)
+	if (height == 0) {
+		if (root->rnode && index == 0)
+			results[nr_found++] = root->rnode;
 		goto out;
+	}
 
 	shift = (height-1) * RADIX_TREE_MAP_SHIFT;
 	slot = root->rnode;
@@ -603,10 +642,16 @@
 	unsigned int height = root->height;
 	struct radix_tree_node *slot;
 
+	if (height == 0) {
+		if (root->rnode && index == 0)
+			results[nr_found++] = root->rnode;
+		goto out;
+	}
+
 	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
 	slot = root->rnode;
 
-	while (height > 0) {
+	do {
 		unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK;
 
 		for ( ; i < RADIX_TREE_MAP_SIZE; i++) {
@@ -637,7 +682,7 @@
 		}
 		shift -= RADIX_TREE_MAP_SHIFT;
 		slot = slot->slots[i];
-	}
+	} while (height > 0);
 out:
 	*next_index = index;
 	return nr_found;
@@ -665,6 +710,10 @@
 	unsigned long cur_index = first_index;
 	unsigned int ret = 0;
 
+	/* check the root's tag bit */
+	if (!root_tag_get(root, tag))
+		return 0;
+
 	while (ret < max_items) {
 		unsigned int nr_found;
 		unsigned long next_index;	/* Index of next search */
@@ -689,7 +738,7 @@
 static inline void radix_tree_shrink(struct radix_tree_root *root)
 {
 	/* try to shrink tree height */
-	while (root->height > 1 &&
+	while (root->height > 0 &&
 			root->rnode->count == 1 &&
 			root->rnode->slots[0]) {
 		struct radix_tree_node *to_free = root->rnode;
@@ -717,12 +766,8 @@
 void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 {
 	struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path;
-	struct radix_tree_path *orig_pathp;
-	struct radix_tree_node *slot;
+	struct radix_tree_node *slot = NULL;
 	unsigned int height, shift;
-	void *ret = NULL;
-	char tags[RADIX_TREE_MAX_TAGS];
-	int nr_cleared_tags;
 	int tag;
 	int offset;
 
@@ -730,11 +775,17 @@
 	if (index > radix_tree_maxindex(height))
 		goto out;
 
+	slot = root->rnode;
+	if (height == 0 && root->rnode) {
+		root_tag_clear_all(root);
+		root->rnode = NULL;
+		goto out;
+	}
+
 	shift = (height - 1) * RADIX_TREE_MAP_SHIFT;
 	pathp->node = NULL;
-	slot = root->rnode;
 
-	for ( ; height > 0; height--) {
+	do {
 		if (slot == NULL)
 			goto out;
 
@@ -744,44 +795,22 @@
 		pathp->node = slot;
 		slot = slot->slots[offset];
 		shift -= RADIX_TREE_MAP_SHIFT;
-	}
+		height--;
+	} while (height > 0);
 
-	ret = slot;
-	if (ret == NULL)
+	if (slot == NULL)
 		goto out;
 
-	orig_pathp = pathp;
-
 	/*
 	 * Clear all tags associated with the just-deleted item
 	 */
-	nr_cleared_tags = 0;
 	for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
-		tags[tag] = 1;
-		if (tag_get(pathp->node, tag, pathp->offset)) {
-			tag_clear(pathp->node, tag, pathp->offset);
-			if (!any_tag_set(pathp->node, tag)) {
-				tags[tag] = 0;
-				nr_cleared_tags++;
-			}
-		}
-	}
-
-	for (pathp--; nr_cleared_tags && pathp->node; pathp--) {
-		for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++) {
-			if (tags[tag])
-				continue;
-
-			tag_clear(pathp->node, tag, pathp->offset);
-			if (any_tag_set(pathp->node, tag)) {
-				tags[tag] = 1;
-				nr_cleared_tags--;
-			}
-		}
+		if (tag_get(pathp->node, tag, pathp->offset))
+			radix_tree_tag_clear(root, index, tag);
 	}
 
 	/* Now free the nodes we do not need anymore */
-	for (pathp = orig_pathp; pathp->node; pathp--) {
+	while (pathp->node) {
 		pathp->node->slots[pathp->offset] = NULL;
 		pathp->node->count--;
 
@@ -793,11 +822,15 @@
 
 		/* Node with zero slots in use so free it */
 		radix_tree_node_free(pathp->node);
+
+		pathp--;
 	}
-	root->rnode = NULL;
+	root_tag_clear_all(root);
 	root->height = 0;
+	root->rnode = NULL;
+
 out:
-	return ret;
+	return slot;
 }
 EXPORT_SYMBOL(radix_tree_delete);
 
@@ -808,11 +841,7 @@
  */
 int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag)
 {
-  	struct radix_tree_node *rnode;
-  	rnode = root->rnode;
-  	if (!rnode)
-  		return 0;
-	return any_tag_set(rnode, tag);
+	return root_tag_get(root, tag);
 }
 EXPORT_SYMBOL(radix_tree_tagged);
 
diff --git a/lib/rbtree.c b/lib/rbtree.c
index 14b791a..1e55ba1 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -26,60 +26,66 @@
 static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
 {
 	struct rb_node *right = node->rb_right;
+	struct rb_node *parent = rb_parent(node);
 
 	if ((node->rb_right = right->rb_left))
-		right->rb_left->rb_parent = node;
+		rb_set_parent(right->rb_left, node);
 	right->rb_left = node;
 
-	if ((right->rb_parent = node->rb_parent))
+	rb_set_parent(right, parent);
+
+	if (parent)
 	{
-		if (node == node->rb_parent->rb_left)
-			node->rb_parent->rb_left = right;
+		if (node == parent->rb_left)
+			parent->rb_left = right;
 		else
-			node->rb_parent->rb_right = right;
+			parent->rb_right = right;
 	}
 	else
 		root->rb_node = right;
-	node->rb_parent = right;
+	rb_set_parent(node, right);
 }
 
 static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
 {
 	struct rb_node *left = node->rb_left;
+	struct rb_node *parent = rb_parent(node);
 
 	if ((node->rb_left = left->rb_right))
-		left->rb_right->rb_parent = node;
+		rb_set_parent(left->rb_right, node);
 	left->rb_right = node;
 
-	if ((left->rb_parent = node->rb_parent))
+	rb_set_parent(left, parent);
+
+	if (parent)
 	{
-		if (node == node->rb_parent->rb_right)
-			node->rb_parent->rb_right = left;
+		if (node == parent->rb_right)
+			parent->rb_right = left;
 		else
-			node->rb_parent->rb_left = left;
+			parent->rb_left = left;
 	}
 	else
 		root->rb_node = left;
-	node->rb_parent = left;
+	rb_set_parent(node, left);
 }
 
 void rb_insert_color(struct rb_node *node, struct rb_root *root)
 {
 	struct rb_node *parent, *gparent;
 
-	while ((parent = node->rb_parent) && parent->rb_color == RB_RED)
+	while ((parent = rb_parent(node)) && rb_is_red(parent))
 	{
-		gparent = parent->rb_parent;
+		gparent = rb_parent(parent);
 
 		if (parent == gparent->rb_left)
 		{
 			{
 				register struct rb_node *uncle = gparent->rb_right;
-				if (uncle && uncle->rb_color == RB_RED)
+				if (uncle && rb_is_red(uncle))
 				{
-					uncle->rb_color = RB_BLACK;
-					parent->rb_color = RB_BLACK;
-					gparent->rb_color = RB_RED;
+					rb_set_black(uncle);
+					rb_set_black(parent);
+					rb_set_red(gparent);
 					node = gparent;
 					continue;
 				}
@@ -94,17 +100,17 @@
 				node = tmp;
 			}
 
-			parent->rb_color = RB_BLACK;
-			gparent->rb_color = RB_RED;
+			rb_set_black(parent);
+			rb_set_red(gparent);
 			__rb_rotate_right(gparent, root);
 		} else {
 			{
 				register struct rb_node *uncle = gparent->rb_left;
-				if (uncle && uncle->rb_color == RB_RED)
+				if (uncle && rb_is_red(uncle))
 				{
-					uncle->rb_color = RB_BLACK;
-					parent->rb_color = RB_BLACK;
-					gparent->rb_color = RB_RED;
+					rb_set_black(uncle);
+					rb_set_black(parent);
+					rb_set_red(gparent);
 					node = gparent;
 					continue;
 				}
@@ -119,13 +125,13 @@
 				node = tmp;
 			}
 
-			parent->rb_color = RB_BLACK;
-			gparent->rb_color = RB_RED;
+			rb_set_black(parent);
+			rb_set_red(gparent);
 			__rb_rotate_left(gparent, root);
 		}
 	}
 
-	root->rb_node->rb_color = RB_BLACK;
+	rb_set_black(root->rb_node);
 }
 EXPORT_SYMBOL(rb_insert_color);
 
@@ -134,43 +140,40 @@
 {
 	struct rb_node *other;
 
-	while ((!node || node->rb_color == RB_BLACK) && node != root->rb_node)
+	while ((!node || rb_is_black(node)) && node != root->rb_node)
 	{
 		if (parent->rb_left == node)
 		{
 			other = parent->rb_right;
-			if (other->rb_color == RB_RED)
+			if (rb_is_red(other))
 			{
-				other->rb_color = RB_BLACK;
-				parent->rb_color = RB_RED;
+				rb_set_black(other);
+				rb_set_red(parent);
 				__rb_rotate_left(parent, root);
 				other = parent->rb_right;
 			}
-			if ((!other->rb_left ||
-			     other->rb_left->rb_color == RB_BLACK)
-			    && (!other->rb_right ||
-				other->rb_right->rb_color == RB_BLACK))
+			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
+			    (!other->rb_right || rb_is_black(other->rb_right)))
 			{
-				other->rb_color = RB_RED;
+				rb_set_red(other);
 				node = parent;
-				parent = node->rb_parent;
+				parent = rb_parent(node);
 			}
 			else
 			{
-				if (!other->rb_right ||
-				    other->rb_right->rb_color == RB_BLACK)
+				if (!other->rb_right || rb_is_black(other->rb_right))
 				{
-					register struct rb_node *o_left;
+					struct rb_node *o_left;
 					if ((o_left = other->rb_left))
-						o_left->rb_color = RB_BLACK;
-					other->rb_color = RB_RED;
+						rb_set_black(o_left);
+					rb_set_red(other);
 					__rb_rotate_right(other, root);
 					other = parent->rb_right;
 				}
-				other->rb_color = parent->rb_color;
-				parent->rb_color = RB_BLACK;
+				rb_set_color(other, rb_color(parent));
+				rb_set_black(parent);
 				if (other->rb_right)
-					other->rb_right->rb_color = RB_BLACK;
+					rb_set_black(other->rb_right);
 				__rb_rotate_left(parent, root);
 				node = root->rb_node;
 				break;
@@ -179,38 +182,35 @@
 		else
 		{
 			other = parent->rb_left;
-			if (other->rb_color == RB_RED)
+			if (rb_is_red(other))
 			{
-				other->rb_color = RB_BLACK;
-				parent->rb_color = RB_RED;
+				rb_set_black(other);
+				rb_set_red(parent);
 				__rb_rotate_right(parent, root);
 				other = parent->rb_left;
 			}
-			if ((!other->rb_left ||
-			     other->rb_left->rb_color == RB_BLACK)
-			    && (!other->rb_right ||
-				other->rb_right->rb_color == RB_BLACK))
+			if ((!other->rb_left || rb_is_black(other->rb_left)) &&
+			    (!other->rb_right || rb_is_black(other->rb_right)))
 			{
-				other->rb_color = RB_RED;
+				rb_set_red(other);
 				node = parent;
-				parent = node->rb_parent;
+				parent = rb_parent(node);
 			}
 			else
 			{
-				if (!other->rb_left ||
-				    other->rb_left->rb_color == RB_BLACK)
+				if (!other->rb_left || rb_is_black(other->rb_left))
 				{
 					register struct rb_node *o_right;
 					if ((o_right = other->rb_right))
-						o_right->rb_color = RB_BLACK;
-					other->rb_color = RB_RED;
+						rb_set_black(o_right);
+					rb_set_red(other);
 					__rb_rotate_left(other, root);
 					other = parent->rb_left;
 				}
-				other->rb_color = parent->rb_color;
-				parent->rb_color = RB_BLACK;
+				rb_set_color(other, rb_color(parent));
+				rb_set_black(parent);
 				if (other->rb_left)
-					other->rb_left->rb_color = RB_BLACK;
+					rb_set_black(other->rb_left);
 				__rb_rotate_right(parent, root);
 				node = root->rb_node;
 				break;
@@ -218,7 +218,7 @@
 		}
 	}
 	if (node)
-		node->rb_color = RB_BLACK;
+		rb_set_black(node);
 }
 
 void rb_erase(struct rb_node *node, struct rb_root *root)
@@ -238,48 +238,41 @@
 		while ((left = node->rb_left) != NULL)
 			node = left;
 		child = node->rb_right;
-		parent = node->rb_parent;
-		color = node->rb_color;
+		parent = rb_parent(node);
+		color = rb_color(node);
 
 		if (child)
-			child->rb_parent = parent;
-		if (parent)
-		{
-			if (parent->rb_left == node)
-				parent->rb_left = child;
-			else
-				parent->rb_right = child;
-		}
-		else
-			root->rb_node = child;
-
-		if (node->rb_parent == old)
+			rb_set_parent(child, parent);
+		if (parent == old) {
+			parent->rb_right = child;
 			parent = node;
-		node->rb_parent = old->rb_parent;
-		node->rb_color = old->rb_color;
+		} else
+			parent->rb_left = child;
+
+		node->rb_parent_color = old->rb_parent_color;
 		node->rb_right = old->rb_right;
 		node->rb_left = old->rb_left;
 
-		if (old->rb_parent)
+		if (rb_parent(old))
 		{
-			if (old->rb_parent->rb_left == old)
-				old->rb_parent->rb_left = node;
+			if (rb_parent(old)->rb_left == old)
+				rb_parent(old)->rb_left = node;
 			else
-				old->rb_parent->rb_right = node;
+				rb_parent(old)->rb_right = node;
 		} else
 			root->rb_node = node;
 
-		old->rb_left->rb_parent = node;
+		rb_set_parent(old->rb_left, node);
 		if (old->rb_right)
-			old->rb_right->rb_parent = node;
+			rb_set_parent(old->rb_right, node);
 		goto color;
 	}
 
-	parent = node->rb_parent;
-	color = node->rb_color;
+	parent = rb_parent(node);
+	color = rb_color(node);
 
 	if (child)
-		child->rb_parent = parent;
+		rb_set_parent(child, parent);
 	if (parent)
 	{
 		if (parent->rb_left == node)
@@ -327,6 +320,8 @@
 
 struct rb_node *rb_next(struct rb_node *node)
 {
+	struct rb_node *parent;
+
 	/* If we have a right-hand child, go down and then left as far
 	   as we can. */
 	if (node->rb_right) {
@@ -342,15 +337,17 @@
 	   ancestor is a right-hand child of its parent, keep going
 	   up. First time it's a left-hand child of its parent, said
 	   parent is our 'next' node. */
-	while (node->rb_parent && node == node->rb_parent->rb_right)
-		node = node->rb_parent;
+	while ((parent = rb_parent(node)) && node == parent->rb_right)
+		node = parent;
 
-	return node->rb_parent;
+	return parent;
 }
 EXPORT_SYMBOL(rb_next);
 
 struct rb_node *rb_prev(struct rb_node *node)
 {
+	struct rb_node *parent;
+
 	/* If we have a left-hand child, go down and then right as far
 	   as we can. */
 	if (node->rb_left) {
@@ -362,17 +359,17 @@
 
 	/* No left-hand children. Go up till we find an ancestor which
 	   is a right-hand child of its parent */
-	while (node->rb_parent && node == node->rb_parent->rb_left)
-		node = node->rb_parent;
+	while ((parent = rb_parent(node)) && node == parent->rb_left)
+		node = parent;
 
-	return node->rb_parent;
+	return parent;
 }
 EXPORT_SYMBOL(rb_prev);
 
 void rb_replace_node(struct rb_node *victim, struct rb_node *new,
 		     struct rb_root *root)
 {
-	struct rb_node *parent = victim->rb_parent;
+	struct rb_node *parent = rb_parent(victim);
 
 	/* Set the surrounding nodes to point to the replacement */
 	if (parent) {
@@ -384,9 +381,9 @@
 		root->rb_node = new;
 	}
 	if (victim->rb_left)
-		victim->rb_left->rb_parent = new;
+		rb_set_parent(victim->rb_left, new);
 	if (victim->rb_right)
-		victim->rb_right->rb_parent = new;
+		rb_set_parent(victim->rb_right, new);
 
 	/* Copy the pointers/colour from the victim to the replacement */
 	*new = *victim;
diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c
index f8ac9fa..2cc11fa 100644
--- a/lib/reed_solomon/reed_solomon.c
+++ b/lib/reed_solomon/reed_solomon.c
@@ -54,7 +54,6 @@
 
 /**
  * rs_init - Initialize a Reed-Solomon codec
- *
  * @symsize:	symbol size, bits (1-8)
  * @gfpoly:	Field generator polynomial coefficients
  * @fcr:	first root of RS code generator polynomial, index form
@@ -62,7 +61,7 @@
  * @nroots:	RS code generator polynomial degree (number of roots)
  *
  * Allocate a control structure and the polynom arrays for faster
- * en/decoding. Fill the arrays according to the given parameters
+ * en/decoding. Fill the arrays according to the given parameters.
  */
 static struct rs_control *rs_init(int symsize, int gfpoly, int fcr,
 				   int prim, int nroots)
@@ -155,8 +154,7 @@
 
 
 /**
- *  free_rs - Free the rs control structure, if its not longer used
- *
+ *  free_rs - Free the rs control structure, if it is no longer used
  *  @rs:	the control structure which is not longer used by the
  *		caller
  */
@@ -176,7 +174,6 @@
 
 /**
  * init_rs - Find a matching or allocate a new rs control structure
- *
  *  @symsize:	the symbol size (number of bits)
  *  @gfpoly:	the extended Galois field generator polynomial coefficients,
  *		with the 0th coefficient in the low order bit. The polynomial
@@ -236,7 +233,6 @@
 #ifdef CONFIG_REED_SOLOMON_ENC8
 /**
  *  encode_rs8 - Calculate the parity for data values (8bit data width)
- *
  *  @rs:	the rs control structure
  *  @data:	data field of a given type
  *  @len:	data length
@@ -258,7 +254,6 @@
 #ifdef CONFIG_REED_SOLOMON_DEC8
 /**
  *  decode_rs8 - Decode codeword (8bit data width)
- *
  *  @rs:	the rs control structure
  *  @data:	data field of a given type
  *  @par:	received parity data field
@@ -285,7 +280,6 @@
 #ifdef CONFIG_REED_SOLOMON_ENC16
 /**
  *  encode_rs16 - Calculate the parity for data values (16bit data width)
- *
  *  @rs:	the rs control structure
  *  @data:	data field of a given type
  *  @len:	data length
@@ -305,7 +299,6 @@
 #ifdef CONFIG_REED_SOLOMON_DEC16
 /**
  *  decode_rs16 - Decode codeword (16bit data width)
- *
  *  @rs:	the rs control structure
  *  @data:	data field of a given type
  *  @par:	received parity data field
diff --git a/lib/string.c b/lib/string.c
index 064f631..6307726 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -301,6 +301,36 @@
 EXPORT_SYMBOL(strnchr);
 #endif
 
+/**
+ * strstrip - Removes leading and trailing whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Note that the first trailing whitespace is replaced with a %NUL-terminator
+ * in the given string @s. Returns a pointer to the first non-whitespace
+ * character in @s.
+ */
+char *strstrip(char *s)
+{
+	size_t size;
+	char *end;
+
+	size = strlen(s);
+
+	if (!size)
+		return s;
+
+	end = s + size - 1;
+	while (end != s && isspace(*end))
+		end--;
+	*(end + 1) = '\0';
+
+	while (*s && isspace(*s))
+		s++;
+
+	return s;
+}
+EXPORT_SYMBOL(strstrip);
+
 #ifndef __HAVE_ARCH_STRLEN
 /**
  * strlen - Find the length of a string
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b07db5c..797428a 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -187,49 +187,49 @@
 	size -= precision;
 	if (!(type&(ZEROPAD+LEFT))) {
 		while(size-->0) {
-			if (buf <= end)
+			if (buf < end)
 				*buf = ' ';
 			++buf;
 		}
 	}
 	if (sign) {
-		if (buf <= end)
+		if (buf < end)
 			*buf = sign;
 		++buf;
 	}
 	if (type & SPECIAL) {
 		if (base==8) {
-			if (buf <= end)
+			if (buf < end)
 				*buf = '0';
 			++buf;
 		} else if (base==16) {
-			if (buf <= end)
+			if (buf < end)
 				*buf = '0';
 			++buf;
-			if (buf <= end)
+			if (buf < end)
 				*buf = digits[33];
 			++buf;
 		}
 	}
 	if (!(type & LEFT)) {
 		while (size-- > 0) {
-			if (buf <= end)
+			if (buf < end)
 				*buf = c;
 			++buf;
 		}
 	}
 	while (i < precision--) {
-		if (buf <= end)
+		if (buf < end)
 			*buf = '0';
 		++buf;
 	}
 	while (i-- > 0) {
-		if (buf <= end)
+		if (buf < end)
 			*buf = tmp[i];
 		++buf;
 	}
 	while (size-- > 0) {
-		if (buf <= end)
+		if (buf < end)
 			*buf = ' ';
 		++buf;
 	}
@@ -272,7 +272,8 @@
 				/* 'z' changed to 'Z' --davidm 1/25/99 */
 				/* 't' added for ptrdiff_t */
 
-	/* Reject out-of-range values early */
+	/* Reject out-of-range values early.  Large positive sizes are
+	   used for unknown buffer sizes. */
 	if (unlikely((int) size < 0)) {
 		/* There can be only one.. */
 		static int warn = 1;
@@ -282,16 +283,17 @@
 	}
 
 	str = buf;
-	end = buf + size - 1;
+	end = buf + size;
 
-	if (end < buf - 1) {
-		end = ((void *) -1);
-		size = end - buf + 1;
+	/* Make sure end is always >= buf */
+	if (end < buf) {
+		end = ((void *)-1);
+		size = end - buf;
 	}
 
 	for (; *fmt ; ++fmt) {
 		if (*fmt != '%') {
-			if (str <= end)
+			if (str < end)
 				*str = *fmt;
 			++str;
 			continue;
@@ -357,17 +359,17 @@
 			case 'c':
 				if (!(flags & LEFT)) {
 					while (--field_width > 0) {
-						if (str <= end)
+						if (str < end)
 							*str = ' ';
 						++str;
 					}
 				}
 				c = (unsigned char) va_arg(args, int);
-				if (str <= end)
+				if (str < end)
 					*str = c;
 				++str;
 				while (--field_width > 0) {
-					if (str <= end)
+					if (str < end)
 						*str = ' ';
 					++str;
 				}
@@ -382,18 +384,18 @@
 
 				if (!(flags & LEFT)) {
 					while (len < field_width--) {
-						if (str <= end)
+						if (str < end)
 							*str = ' ';
 						++str;
 					}
 				}
 				for (i = 0; i < len; ++i) {
-					if (str <= end)
+					if (str < end)
 						*str = *s;
 					++str; ++s;
 				}
 				while (len < field_width--) {
-					if (str <= end)
+					if (str < end)
 						*str = ' ';
 					++str;
 				}
@@ -426,7 +428,7 @@
 				continue;
 
 			case '%':
-				if (str <= end)
+				if (str < end)
 					*str = '%';
 				++str;
 				continue;
@@ -449,11 +451,11 @@
 				break;
 
 			default:
-				if (str <= end)
+				if (str < end)
 					*str = '%';
 				++str;
 				if (*fmt) {
-					if (str <= end)
+					if (str < end)
 						*str = *fmt;
 					++str;
 				} else {
@@ -483,14 +485,13 @@
 		str = number(str, end, num, base,
 				field_width, precision, flags);
 	}
-	if (str <= end)
-		*str = '\0';
-	else if (size > 0)
-		/* don't write out a null byte if the buf size is zero */
-		*end = '\0';
-	/* the trailing null byte doesn't count towards the total
-	* ++str;
-	*/
+	if (size > 0) {
+		if (str < end)
+			*str = '\0';
+		else
+			*end = '\0';
+	}
+	/* the trailing null byte doesn't count towards the total */
 	return str-buf;
 }
 
@@ -848,3 +849,26 @@
 }
 
 EXPORT_SYMBOL(sscanf);
+
+
+/* Simplified asprintf. */
+char *kasprintf(gfp_t gfp, const char *fmt, ...)
+{
+	va_list ap;
+	unsigned int len;
+	char *p;
+
+	va_start(ap, fmt);
+	len = vsnprintf(NULL, 0, fmt, ap);
+	va_end(ap);
+
+	p = kmalloc(len+1, gfp);
+	if (!p)
+		return NULL;
+	va_start(ap, fmt);
+	vsnprintf(p, len+1, fmt, ap);
+	va_end(ap);
+	return p;
+}
+
+EXPORT_SYMBOL(kasprintf);
diff --git a/lib/zlib_deflate/deflate.c b/lib/zlib_deflate/deflate.c
index 1653dd9..c3e4a2ba 100644
--- a/lib/zlib_deflate/deflate.c
+++ b/lib/zlib_deflate/deflate.c
@@ -164,34 +164,17 @@
     memset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head));
 
 /* ========================================================================= */
-int zlib_deflateInit_(
-	z_streamp strm,
-	int level,
-	const char *version,
-	int stream_size
-)
-{
-    return zlib_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS,
-			      DEF_MEM_LEVEL,
-			      Z_DEFAULT_STRATEGY, version, stream_size);
-    /* To do: ignore strm->next_in if we use it as window */
-}
-
-/* ========================================================================= */
-int zlib_deflateInit2_(
+int zlib_deflateInit2(
 	z_streamp strm,
 	int  level,
 	int  method,
 	int  windowBits,
 	int  memLevel,
-	int  strategy,
-	const char *version,
-	int stream_size
+	int  strategy
 )
 {
     deflate_state *s;
     int noheader = 0;
-    static char* my_version = ZLIB_VERSION;
     deflate_workspace *mem;
 
     ush *overlay;
@@ -199,10 +182,6 @@
      * output size for (length,distance) codes is <= 24 bits.
      */
 
-    if (version == NULL || version[0] != my_version[0] ||
-        stream_size != sizeof(z_stream)) {
-	return Z_VERSION_ERROR;
-    }
     if (strm == NULL) return Z_STREAM_ERROR;
 
     strm->msg = NULL;
diff --git a/lib/zlib_deflate/deflate_syms.c b/lib/zlib_deflate/deflate_syms.c
index 767b573..ccfe25f 100644
--- a/lib/zlib_deflate/deflate_syms.c
+++ b/lib/zlib_deflate/deflate_syms.c
@@ -12,8 +12,7 @@
 
 EXPORT_SYMBOL(zlib_deflate_workspacesize);
 EXPORT_SYMBOL(zlib_deflate);
-EXPORT_SYMBOL(zlib_deflateInit_);
-EXPORT_SYMBOL(zlib_deflateInit2_);
+EXPORT_SYMBOL(zlib_deflateInit2);
 EXPORT_SYMBOL(zlib_deflateEnd);
 EXPORT_SYMBOL(zlib_deflateReset);
 MODULE_LICENSE("GPL");
diff --git a/lib/zlib_inflate/Makefile b/lib/zlib_inflate/Makefile
index 221c139..bf06548 100644
--- a/lib/zlib_inflate/Makefile
+++ b/lib/zlib_inflate/Makefile
@@ -15,5 +15,5 @@
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate.o
 
-zlib_inflate-objs := infblock.o infcodes.o inffast.o inflate.o \
-		     inflate_sync.o inftrees.o infutil.o inflate_syms.o
+zlib_inflate-objs := inffast.o inflate.o \
+		     inftrees.o inflate_syms.o
diff --git a/lib/zlib_inflate/infblock.c b/lib/zlib_inflate/infblock.c
deleted file mode 100644
index c16cdef..0000000
--- a/lib/zlib_inflate/infblock.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include <linux/zutil.h>
-#include "infblock.h"
-#include "inftrees.h"
-#include "infcodes.h"
-#include "infutil.h"
-
-struct inflate_codes_state;
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* Table for deflate from PKZIP's appnote.txt. */
-static const uInt border[] = { /* Order of the bit length code lengths */
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
-   Notes beyond the 1.93a appnote.txt:
-
-   1. Distance pointers never point before the beginning of the output
-      stream.
-   2. Distance pointers can point back across blocks, up to 32k away.
-   3. There is an implied maximum of 7 bits for the bit length table and
-      15 bits for the actual data.
-   4. If only one code exists, then it is encoded using one bit.  (Zero
-      would be more efficient, but perhaps a little confusing.)  If two
-      codes exist, they are coded using one bit each (0 and 1).
-   5. There is no way of sending zero distance codes--a dummy must be
-      sent if there are none.  (History: a pre 2.0 version of PKZIP would
-      store blocks with no distance codes, but this was discovered to be
-      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
-      zero distance codes, which is sent as one code of zero bits in
-      length.
-   6. There are up to 286 literal/length codes.  Code 256 represents the
-      end-of-block.  Note however that the static length tree defines
-      288 codes just to fill out the Huffman codes.  Codes 286 and 287
-      cannot be used though, since there is no length base or extra bits
-      defined for them.  Similarily, there are up to 30 distance codes.
-      However, static trees define 32 codes (all 5 bits) to fill out the
-      Huffman codes, but the last two had better not show up in the data.
-   7. Unzip can check dynamic Huffman blocks for complete code sets.
-      The exception is that a single code would not be complete (see #4).
-   8. The five bits following the block type is really the number of
-      literal codes sent minus 257.
-   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
-      (1+6+6).  Therefore, to output three times the length, you output
-      three codes (1+1+1), whereas to output four times the same length,
-      you only need two codes (1+3).  Hmm.
-  10. In the tree reconstruction algorithm, Code = Code + Increment
-      only if BitLength(i) is not zero.  (Pretty obvious.)
-  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
-  12. Note: length code 284 can represent 227-258, but length code 285
-      really is 258.  The last length deserves its own, short code
-      since it gets used a lot in very redundant files.  The length
-      258 is special since 258 - 3 (the min match length) is 255.
-  13. The literal/length and distance code bit lengths are read as a
-      single stream of lengths.  It is possible (and advantageous) for
-      a repeat code (16, 17, or 18) to go across the boundary between
-      the two sets of lengths.
- */
-
-
-void zlib_inflate_blocks_reset(
-	inflate_blocks_statef *s,
-	z_streamp z,
-	uLong *c
-)
-{
-  if (c != NULL)
-    *c = s->check;
-  if (s->mode == CODES)
-    zlib_inflate_codes_free(s->sub.decode.codes, z);
-  s->mode = TYPE;
-  s->bitk = 0;
-  s->bitb = 0;
-  s->read = s->write = s->window;
-  if (s->checkfn != NULL)
-    z->adler = s->check = (*s->checkfn)(0L, NULL, 0);
-}
-
-inflate_blocks_statef *zlib_inflate_blocks_new(
-	z_streamp z,
-	check_func c,
-	uInt w
-)
-{
-  inflate_blocks_statef *s;
-
-  s = &WS(z)->working_blocks_state;
-  s->hufts = WS(z)->working_hufts;
-  s->window = WS(z)->working_window;
-  s->end = s->window + w;
-  s->checkfn = c;
-  s->mode = TYPE;
-  zlib_inflate_blocks_reset(s, z, NULL);
-  return s;
-}
-
-
-int zlib_inflate_blocks(
-	inflate_blocks_statef *s,
-	z_streamp z,
-	int r
-)
-{
-  uInt t;               /* temporary storage */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Byte *p;              /* input data pointer */
-  uInt n;               /* bytes available there */
-  Byte *q;              /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input based on current state */
-  while (1) switch (s->mode)
-  {
-    case TYPE:
-      NEEDBITS(3)
-      t = (uInt)b & 7;
-      s->last = t & 1;
-      switch (t >> 1)
-      {
-        case 0:                         /* stored */
-          DUMPBITS(3)
-          t = k & 7;                    /* go to byte boundary */
-          DUMPBITS(t)
-          s->mode = LENS;               /* get length of stored block */
-          break;
-        case 1:                         /* fixed */
-          {
-            uInt bl, bd;
-            inflate_huft *tl, *td;
-
-            zlib_inflate_trees_fixed(&bl, &bd, &tl, &td, s->hufts, z);
-            s->sub.decode.codes = zlib_inflate_codes_new(bl, bd, tl, td, z);
-            if (s->sub.decode.codes == NULL)
-            {
-              r = Z_MEM_ERROR;
-              LEAVE
-            }
-          }
-          DUMPBITS(3)
-          s->mode = CODES;
-          break;
-        case 2:                         /* dynamic */
-          DUMPBITS(3)
-          s->mode = TABLE;
-          break;
-        case 3:                         /* illegal */
-          DUMPBITS(3)
-          s->mode = B_BAD;
-          z->msg = (char*)"invalid block type";
-          r = Z_DATA_ERROR;
-          LEAVE
-      }
-      break;
-    case LENS:
-      NEEDBITS(32)
-      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
-      {
-        s->mode = B_BAD;
-        z->msg = (char*)"invalid stored block lengths";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-      s->sub.left = (uInt)b & 0xffff;
-      b = k = 0;                      /* dump bits */
-      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
-      break;
-    case STORED:
-      if (n == 0)
-        LEAVE
-      NEEDOUT
-      t = s->sub.left;
-      if (t > n) t = n;
-      if (t > m) t = m;
-      memcpy(q, p, t);
-      p += t;  n -= t;
-      q += t;  m -= t;
-      if ((s->sub.left -= t) != 0)
-        break;
-      s->mode = s->last ? DRY : TYPE;
-      break;
-    case TABLE:
-      NEEDBITS(14)
-      s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
-      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
-      {
-        s->mode = B_BAD;
-        z->msg = (char*)"too many length or distance symbols";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-#endif
-      {
-      	s->sub.trees.blens = WS(z)->working_blens;
-      }
-      DUMPBITS(14)
-      s->sub.trees.index = 0;
-      s->mode = BTREE;
-    case BTREE:
-      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
-      {
-        NEEDBITS(3)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
-        DUMPBITS(3)
-      }
-      while (s->sub.trees.index < 19)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
-      s->sub.trees.bb = 7;
-      t = zlib_inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
-				  &s->sub.trees.tb, s->hufts, z);
-      if (t != Z_OK)
-      {
-        r = t;
-        if (r == Z_DATA_ERROR)
-          s->mode = B_BAD;
-        LEAVE
-      }
-      s->sub.trees.index = 0;
-      s->mode = DTREE;
-    case DTREE:
-      while (t = s->sub.trees.table,
-             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
-      {
-        inflate_huft *h;
-        uInt i, j, c;
-
-        t = s->sub.trees.bb;
-        NEEDBITS(t)
-        h = s->sub.trees.tb + ((uInt)b & zlib_inflate_mask[t]);
-        t = h->bits;
-        c = h->base;
-        if (c < 16)
-        {
-          DUMPBITS(t)
-          s->sub.trees.blens[s->sub.trees.index++] = c;
-        }
-        else /* c == 16..18 */
-        {
-          i = c == 18 ? 7 : c - 14;
-          j = c == 18 ? 11 : 3;
-          NEEDBITS(t + i)
-          DUMPBITS(t)
-          j += (uInt)b & zlib_inflate_mask[i];
-          DUMPBITS(i)
-          i = s->sub.trees.index;
-          t = s->sub.trees.table;
-          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
-              (c == 16 && i < 1))
-          {
-            s->mode = B_BAD;
-            z->msg = (char*)"invalid bit length repeat";
-            r = Z_DATA_ERROR;
-            LEAVE
-          }
-          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
-          do {
-            s->sub.trees.blens[i++] = c;
-          } while (--j);
-          s->sub.trees.index = i;
-        }
-      }
-      s->sub.trees.tb = NULL;
-      {
-        uInt bl, bd;
-        inflate_huft *tl, *td;
-        inflate_codes_statef *c;
-
-        bl = 9;         /* must be <= 9 for lookahead assumptions */
-        bd = 6;         /* must be <= 9 for lookahead assumptions */
-        t = s->sub.trees.table;
-        t = zlib_inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
-				       s->sub.trees.blens, &bl, &bd, &tl, &td,
-				       s->hufts, z);
-        if (t != Z_OK)
-        {
-          if (t == (uInt)Z_DATA_ERROR)
-            s->mode = B_BAD;
-          r = t;
-          LEAVE
-        }
-        if ((c = zlib_inflate_codes_new(bl, bd, tl, td, z)) == NULL)
-        {
-          r = Z_MEM_ERROR;
-          LEAVE
-        }
-        s->sub.decode.codes = c;
-      }
-      s->mode = CODES;
-    case CODES:
-      UPDATE
-      if ((r = zlib_inflate_codes(s, z, r)) != Z_STREAM_END)
-        return zlib_inflate_flush(s, z, r);
-      r = Z_OK;
-      zlib_inflate_codes_free(s->sub.decode.codes, z);
-      LOAD
-      if (!s->last)
-      {
-        s->mode = TYPE;
-        break;
-      }
-      s->mode = DRY;
-    case DRY:
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      s->mode = B_DONE;
-    case B_DONE:
-      r = Z_STREAM_END;
-      LEAVE
-    case B_BAD:
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-int zlib_inflate_blocks_free(
-	inflate_blocks_statef *s,
-	z_streamp z
-)
-{
-  zlib_inflate_blocks_reset(s, z, NULL);
-  return Z_OK;
-}
-
-
-#if 0
-void zlib_inflate_set_dictionary(
-	inflate_blocks_statef *s,
-	const Byte *d,
-	uInt  n
-)
-{
-  memcpy(s->window, d, n);
-  s->read = s->write = s->window + n;
-}
-#endif  /*  0  */
-
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
- * IN assertion: s != NULL
- */
-#if 0
-int zlib_inflate_blocks_sync_point(
-	inflate_blocks_statef *s
-)
-{
-  return s->mode == LENS;
-}
-#endif  /*  0  */
diff --git a/lib/zlib_inflate/infblock.h b/lib/zlib_inflate/infblock.h
deleted file mode 100644
index ceee60b..0000000
--- a/lib/zlib_inflate/infblock.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFBLOCK_H
-#define _INFBLOCK_H
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state inflate_blocks_statef;
-
-extern inflate_blocks_statef * zlib_inflate_blocks_new (
-    z_streamp z,
-    check_func c,              /* check function */
-    uInt w);                   /* window size */
-
-extern int zlib_inflate_blocks (
-    inflate_blocks_statef *,
-    z_streamp ,
-    int);                      /* initial return code */
-
-extern void zlib_inflate_blocks_reset (
-    inflate_blocks_statef *,
-    z_streamp ,
-    uLong *);                  /* check value on output */
-
-extern int zlib_inflate_blocks_free (
-    inflate_blocks_statef *,
-    z_streamp);
-
-#if 0
-extern void zlib_inflate_set_dictionary (
-    inflate_blocks_statef *s,
-    const Byte *d,  /* dictionary */
-    uInt  n);       /* dictionary length */
-#endif  /*  0  */
-
-#if 0
-extern int zlib_inflate_blocks_sync_point (
-    inflate_blocks_statef *s);
-#endif  /*  0  */
-
-#endif /* _INFBLOCK_H */
diff --git a/lib/zlib_inflate/infcodes.c b/lib/zlib_inflate/infcodes.c
deleted file mode 100644
index 07cd759..0000000
--- a/lib/zlib_inflate/infcodes.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include <linux/zutil.h>
-#include "inftrees.h"
-#include "infblock.h"
-#include "infcodes.h"
-#include "infutil.h"
-#include "inffast.h"
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-inflate_codes_statef *zlib_inflate_codes_new(
-	uInt bl,
-	uInt bd,
-	inflate_huft *tl,
-	inflate_huft *td, /* need separate declaration for Borland C++ */
-	z_streamp z
-)
-{
-  inflate_codes_statef *c;
-
-  c = &WS(z)->working_state;
-  {
-    c->mode = START;
-    c->lbits = (Byte)bl;
-    c->dbits = (Byte)bd;
-    c->ltree = tl;
-    c->dtree = td;
-  }
-  return c;
-}
-
-
-int zlib_inflate_codes(
-	inflate_blocks_statef *s,
-	z_streamp z,
-	int r
-)
-{
-  uInt j;               /* temporary storage */
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Byte *p;              /* input data pointer */
-  uInt n;               /* bytes available there */
-  Byte *q;              /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  Byte *f;              /* pointer to copy strings from */
-  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input and output based on current state */
-  while (1) switch (c->mode)
-  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-    case START:         /* x: set up for LEN */
-#ifndef SLOW
-      if (m >= 258 && n >= 10)
-      {
-        UPDATE
-        r = zlib_inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
-        LOAD
-        if (r != Z_OK)
-        {
-          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
-          break;
-        }
-      }
-#endif /* !SLOW */
-      c->sub.code.need = c->lbits;
-      c->sub.code.tree = c->ltree;
-      c->mode = LEN;
-    case LEN:           /* i: get length/literal/eob next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e == 0)               /* literal */
-      {
-        c->sub.lit = t->base;
-        c->mode = LIT;
-        break;
-      }
-      if (e & 16)               /* length */
-      {
-        c->sub.copy.get = e & 15;
-        c->len = t->base;
-        c->mode = LENEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t + t->base;
-        break;
-      }
-      if (e & 32)               /* end of block */
-      {
-        c->mode = WASH;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = (char*)"invalid literal/length code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case LENEXT:        /* i: getting length extra (have base) */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->len += (uInt)b & zlib_inflate_mask[j];
-      DUMPBITS(j)
-      c->sub.code.need = c->dbits;
-      c->sub.code.tree = c->dtree;
-      c->mode = DIST;
-    case DIST:          /* i: get distance next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e & 16)               /* distance */
-      {
-        c->sub.copy.get = e & 15;
-        c->sub.copy.dist = t->base;
-        c->mode = DISTEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t + t->base;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = (char*)"invalid distance code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case DISTEXT:       /* i: getting distance extra */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->sub.copy.dist += (uInt)b & zlib_inflate_mask[j];
-      DUMPBITS(j)
-      c->mode = COPY;
-    case COPY:          /* o: copying bytes in window, waiting for space */
-      f = q - c->sub.copy.dist;
-      while (f < s->window)             /* modulo window size-"while" instead */
-        f += s->end - s->window;        /* of "if" handles invalid distances */
-      while (c->len)
-      {
-        NEEDOUT
-        OUTBYTE(*f++)
-        if (f == s->end)
-          f = s->window;
-        c->len--;
-      }
-      c->mode = START;
-      break;
-    case LIT:           /* o: got literal, waiting for output space */
-      NEEDOUT
-      OUTBYTE(c->sub.lit)
-      c->mode = START;
-      break;
-    case WASH:          /* o: got eob, possibly more output */
-      if (k > 7)        /* return unused byte, if any */
-      {
-        k -= 8;
-        n++;
-        p--;            /* can always return one */
-      }
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      c->mode = END;
-    case END:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADCODE:       /* x: got error */
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-#ifdef NEED_DUMMY_RETURN
-  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
-#endif
-}
-
-
-void zlib_inflate_codes_free(
-	inflate_codes_statef *c,
-	z_streamp z
-)
-{
-}
diff --git a/lib/zlib_inflate/infcodes.h b/lib/zlib_inflate/infcodes.h
deleted file mode 100644
index 5cff417..0000000
--- a/lib/zlib_inflate/infcodes.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFCODES_H
-#define _INFCODES_H
-
-#include "infblock.h"
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state inflate_codes_statef;
-
-extern inflate_codes_statef *zlib_inflate_codes_new (
-    uInt, uInt,
-    inflate_huft *, inflate_huft *,
-    z_streamp );
-
-extern int zlib_inflate_codes (
-    inflate_blocks_statef *,
-    z_streamp ,
-    int);
-
-extern void zlib_inflate_codes_free (
-    inflate_codes_statef *,
-    z_streamp );
-
-#endif /* _INFCODES_H */
diff --git a/lib/zlib_inflate/inffast.c b/lib/zlib_inflate/inffast.c
index 0bd7623..d84560c 100644
--- a/lib/zlib_inflate/inffast.c
+++ b/lib/zlib_inflate/inffast.c
@@ -1,176 +1,312 @@
-/* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 #include <linux/zutil.h>
 #include "inftrees.h"
-#include "infblock.h"
-#include "infcodes.h"
-#include "infutil.h"
+#include "inflate.h"
 #include "inffast.h"
 
-struct inflate_codes_state;
+#ifndef ASMINF
 
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
+/* Allow machine dependent optimization for post-increment or pre-increment.
+   Based on testing to date,
+   Pre-increment preferred for:
+   - PowerPC G3 (Adler)
+   - MIPS R5000 (Randers-Pehrson)
+   Post-increment preferred for:
+   - none
+   No measurable difference:
+   - Pentium III (Anderson)
+   - M68060 (Nikl)
+ */
+#ifdef POSTINC
+#  define OFF 0
+#  define PUP(a) *(a)++
+#else
+#  define OFF 1
+#  define PUP(a) *++(a)
+#endif
 
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+/*
+   Decode literal, length, and distance codes and write out the resulting
+   literal and match bytes until either not enough input or output is
+   available, an end-of-block is encountered, or a data error is encountered.
+   When large enough input and output buffers are supplied to inflate(), for
+   example, a 16K input buffer and a 64K output buffer, more than 95% of the
+   inflate execution time is spent in this routine.
 
-/* Called with number of bytes left to write in window at least 258
-   (the maximum string length) and number of input bytes available
-   at least ten.  The ten bytes are six bytes for the longest length/
-   distance pair plus four bytes for overloading the bit buffer. */
+   Entry assumptions:
 
-int zlib_inflate_fast(
-	uInt bl,
-	uInt bd,
-	inflate_huft *tl,
-	inflate_huft *td, /* need separate declaration for Borland C++ */
-	inflate_blocks_statef *s,
-	z_streamp z
-)
+        state->mode == LEN
+        strm->avail_in >= 6
+        strm->avail_out >= 258
+        start >= strm->avail_out
+        state->bits < 8
+
+   On return, state->mode is one of:
+
+        LEN -- ran out of enough output space or enough available input
+        TYPE -- reached end of block code, inflate() to interpret next block
+        BAD -- error in block data
+
+   Notes:
+
+    - The maximum input bits used by a length/distance pair is 15 bits for the
+      length code, 5 bits for the length extra, 15 bits for the distance code,
+      and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
+      Therefore if strm->avail_in >= 6, then there is enough input to avoid
+      checking for available input while decoding.
+
+    - The maximum bytes that a single length/distance pair can output is 258
+      bytes, which is the maximum length that can be coded.  inflate_fast()
+      requires strm->avail_out >= 258 for each loop to avoid checking for
+      output space.
+
+    - @start:	inflate()'s starting value for strm->avail_out
+ */
+void inflate_fast(z_streamp strm, unsigned start)
 {
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Byte *p;              /* input data pointer */
-  uInt n;               /* bytes available there */
-  Byte *q;              /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  uInt ml;              /* mask for literal/length tree */
-  uInt md;              /* mask for distance tree */
-  uInt c;               /* bytes to copy */
-  uInt d;               /* distance back to copy from */
-  Byte *r;              /* copy source pointer */
+    struct inflate_state *state;
+    unsigned char *in;      /* local strm->next_in */
+    unsigned char *last;    /* while in < last, enough input available */
+    unsigned char *out;     /* local strm->next_out */
+    unsigned char *beg;     /* inflate()'s initial strm->next_out */
+    unsigned char *end;     /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+    unsigned dmax;              /* maximum distance from zlib header */
+#endif
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned write;             /* window write index */
+    unsigned char *window;  /* allocated sliding window, if wsize != 0 */
+    unsigned long hold;         /* local strm->hold */
+    unsigned bits;              /* local strm->bits */
+    code const *lcode;      /* local strm->lencode */
+    code const *dcode;      /* local strm->distcode */
+    unsigned lmask;             /* mask for first level of length codes */
+    unsigned dmask;             /* mask for first level of distance codes */
+    code this;                  /* retrieved table entry */
+    unsigned op;                /* code bits, operation, extra bits, or */
+                                /*  window position, window bytes to copy */
+    unsigned len;               /* match length, unused bytes */
+    unsigned dist;              /* match distance */
+    unsigned char *from;    /* where to copy match from */
 
-  /* load input, output, bit values */
-  LOAD
+    /* copy state to local variables */
+    state = (struct inflate_state *)strm->state;
+    in = strm->next_in - OFF;
+    last = in + (strm->avail_in - 5);
+    out = strm->next_out - OFF;
+    beg = out - (start - strm->avail_out);
+    end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+    dmax = state->dmax;
+#endif
+    wsize = state->wsize;
+    whave = state->whave;
+    write = state->write;
+    window = state->window;
+    hold = state->hold;
+    bits = state->bits;
+    lcode = state->lencode;
+    dcode = state->distcode;
+    lmask = (1U << state->lenbits) - 1;
+    dmask = (1U << state->distbits) - 1;
 
-  /* initialize masks */
-  ml = zlib_inflate_mask[bl];
-  md = zlib_inflate_mask[bd];
-
-  /* do until not enough input or output space for fast loop */
-  do {                          /* assume called with m >= 258 && n >= 10 */
-    /* get literal/length code */
-    GRABBITS(20)                /* max bits for literal/length code */
-    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
-    {
-      DUMPBITS(t->bits)
-      *q++ = (Byte)t->base;
-      m--;
-      continue;
-    }
+    /* decode literals and length/distances until end-of-block or not enough
+       input data or output space */
     do {
-      DUMPBITS(t->bits)
-      if (e & 16)
-      {
-        /* get extra bits for length */
-        e &= 15;
-        c = t->base + ((uInt)b & zlib_inflate_mask[e]);
-        DUMPBITS(e)
-
-        /* decode distance base of block to copy */
-        GRABBITS(15);           /* max bits for distance code */
-        e = (t = td + ((uInt)b & md))->exop;
-        do {
-          DUMPBITS(t->bits)
-          if (e & 16)
-          {
-            /* get extra bits to add to distance base */
-            e &= 15;
-            GRABBITS(e)         /* get extra bits (up to 13) */
-            d = t->base + ((uInt)b & zlib_inflate_mask[e]);
-            DUMPBITS(e)
-
-            /* do the copy */
-            m -= c;
-            r = q - d;
-            if (r < s->window)                  /* wrap if needed */
-            {
-              do {
-                r += s->end - s->window;        /* force pointer in window */
-              } while (r < s->window);          /* covers invalid distances */
-              e = s->end - r;
-              if (c > e)
-              {
-                c -= e;                         /* wrapped copy */
-                do {
-                    *q++ = *r++;
-                } while (--e);
-                r = s->window;
-                do {
-                    *q++ = *r++;
-                } while (--c);
-              }
-              else                              /* normal copy */
-              {
-                *q++ = *r++;  c--;
-                *q++ = *r++;  c--;
-                do {
-                    *q++ = *r++;
-                } while (--c);
-              }
-            }
-            else                                /* normal copy */
-            {
-              *q++ = *r++;  c--;
-              *q++ = *r++;  c--;
-              do {
-                *q++ = *r++;
-              } while (--c);
-            }
-            break;
-          }
-          else if ((e & 64) == 0)
-          {
-            t += t->base;
-            e = (t += ((uInt)b & zlib_inflate_mask[e]))->exop;
-          }
-          else
-          {
-            z->msg = (char*)"invalid distance code";
-            UNGRAB
-            UPDATE
-            return Z_DATA_ERROR;
-          }
-        } while (1);
-        break;
-      }
-      if ((e & 64) == 0)
-      {
-        t += t->base;
-        if ((e = (t += ((uInt)b & zlib_inflate_mask[e]))->exop) == 0)
-        {
-          DUMPBITS(t->bits)
-          *q++ = (Byte)t->base;
-          m--;
-          break;
+        if (bits < 15) {
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
+            hold += (unsigned long)(PUP(in)) << bits;
+            bits += 8;
         }
-      }
-      else if (e & 32)
-      {
-        UNGRAB
-        UPDATE
-        return Z_STREAM_END;
-      }
-      else
-      {
-        z->msg = (char*)"invalid literal/length code";
-        UNGRAB
-        UPDATE
-        return Z_DATA_ERROR;
-      }
-    } while (1);
-  } while (m >= 258 && n >= 10);
+        this = lcode[hold & lmask];
+      dolen:
+        op = (unsigned)(this.bits);
+        hold >>= op;
+        bits -= op;
+        op = (unsigned)(this.op);
+        if (op == 0) {                          /* literal */
+            PUP(out) = (unsigned char)(this.val);
+        }
+        else if (op & 16) {                     /* length base */
+            len = (unsigned)(this.val);
+            op &= 15;                           /* number of extra bits */
+            if (op) {
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                }
+                len += (unsigned)hold & ((1U << op) - 1);
+                hold >>= op;
+                bits -= op;
+            }
+            if (bits < 15) {
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+                hold += (unsigned long)(PUP(in)) << bits;
+                bits += 8;
+            }
+            this = dcode[hold & dmask];
+          dodist:
+            op = (unsigned)(this.bits);
+            hold >>= op;
+            bits -= op;
+            op = (unsigned)(this.op);
+            if (op & 16) {                      /* distance base */
+                dist = (unsigned)(this.val);
+                op &= 15;                       /* number of extra bits */
+                if (bits < op) {
+                    hold += (unsigned long)(PUP(in)) << bits;
+                    bits += 8;
+                    if (bits < op) {
+                        hold += (unsigned long)(PUP(in)) << bits;
+                        bits += 8;
+                    }
+                }
+                dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+                if (dist > dmax) {
+                    strm->msg = (char *)"invalid distance too far back";
+                    state->mode = BAD;
+                    break;
+                }
+#endif
+                hold >>= op;
+                bits -= op;
+                op = (unsigned)(out - beg);     /* max distance in output */
+                if (dist > op) {                /* see if copy from window */
+                    op = dist - op;             /* distance back in window */
+                    if (op > whave) {
+                        strm->msg = (char *)"invalid distance too far back";
+                        state->mode = BAD;
+                        break;
+                    }
+                    from = window - OFF;
+                    if (write == 0) {           /* very common case */
+                        from += wsize - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    else if (write < op) {      /* wrap around window */
+                        from += wsize + write - op;
+                        op -= write;
+                        if (op < len) {         /* some from end of window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = window - OFF;
+                            if (write < len) {  /* some from start of window */
+                                op = write;
+                                len -= op;
+                                do {
+                                    PUP(out) = PUP(from);
+                                } while (--op);
+                                from = out - dist;      /* rest from output */
+                            }
+                        }
+                    }
+                    else {                      /* contiguous in window */
+                        from += write - op;
+                        if (op < len) {         /* some from window */
+                            len -= op;
+                            do {
+                                PUP(out) = PUP(from);
+                            } while (--op);
+                            from = out - dist;  /* rest from output */
+                        }
+                    }
+                    while (len > 2) {
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    }
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+                else {
+                    from = out - dist;          /* copy direct from output */
+                    do {                        /* minimum length is three */
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        PUP(out) = PUP(from);
+                        len -= 3;
+                    } while (len > 2);
+                    if (len) {
+                        PUP(out) = PUP(from);
+                        if (len > 1)
+                            PUP(out) = PUP(from);
+                    }
+                }
+            }
+            else if ((op & 64) == 0) {          /* 2nd level distance code */
+                this = dcode[this.val + (hold & ((1U << op) - 1))];
+                goto dodist;
+            }
+            else {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+        }
+        else if ((op & 64) == 0) {              /* 2nd level length code */
+            this = lcode[this.val + (hold & ((1U << op) - 1))];
+            goto dolen;
+        }
+        else if (op & 32) {                     /* end-of-block */
+            state->mode = TYPE;
+            break;
+        }
+        else {
+            strm->msg = (char *)"invalid literal/length code";
+            state->mode = BAD;
+            break;
+        }
+    } while (in < last && out < end);
 
-  /* not enough input or output--restore pointers and return */
-  UNGRAB
-  UPDATE
-  return Z_OK;
+    /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+    len = bits >> 3;
+    in -= len;
+    bits -= len << 3;
+    hold &= (1U << bits) - 1;
+
+    /* update state and return */
+    strm->next_in = in + OFF;
+    strm->next_out = out + OFF;
+    strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+    strm->avail_out = (unsigned)(out < end ?
+                                 257 + (end - out) : 257 - (out - end));
+    state->hold = hold;
+    state->bits = bits;
+    return;
 }
+
+/*
+   inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+   - Using bit fields for code structure
+   - Different op definition to avoid & for extra bits (do & for table bits)
+   - Three separate decoding do-loops for direct, window, and write == 0
+   - Special case for distance > 1 copies to do overlapped load and store copy
+   - Explicit branch predictions (based on measured branch probabilities)
+   - Deferring match copy and interspersed it with decoding subsequent codes
+   - Swapping literal/length else
+   - Swapping window/direct else
+   - Larger unrolled copy loops (three is about right)
+   - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/lib/zlib_inflate/inffast.h b/lib/zlib_inflate/inffast.h
index fc720f0..40315d9 100644
--- a/lib/zlib_inflate/inffast.h
+++ b/lib/zlib_inflate/inffast.h
@@ -1,6 +1,6 @@
 /* inffast.h -- header to use inffast.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* WARNING: this file should *not* be used by applications. It is
@@ -8,10 +8,4 @@
    subject to change. Applications should only use zlib.h.
  */
 
-extern int zlib_inflate_fast (
-    uInt,
-    uInt,
-    inflate_huft *,
-    inflate_huft *,
-    inflate_blocks_statef *,
-    z_streamp );
+void inflate_fast (z_streamp strm, unsigned start);
diff --git a/lib/zlib_inflate/inffixed.h b/lib/zlib_inflate/inffixed.h
new file mode 100644
index 0000000..75ed4b5
--- /dev/null
+++ b/lib/zlib_inflate/inffixed.h
@@ -0,0 +1,94 @@
+    /* inffixed.h -- table for decoding fixed codes
+     * Generated automatically by makefixed().
+     */
+
+    /* WARNING: this file should *not* be used by applications. It
+       is part of the implementation of the compression library and
+       is subject to change. Applications should only use zlib.h.
+     */
+
+    static const code lenfix[512] = {
+        {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+        {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+        {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+        {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+        {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+        {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+        {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+        {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+        {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+        {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+        {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+        {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+        {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+        {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+        {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+        {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+        {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+        {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+        {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+        {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+        {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+        {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+        {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+        {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+        {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+        {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+        {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+        {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+        {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+        {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+        {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+        {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+        {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+        {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+        {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+        {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+        {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+        {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+        {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+        {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+        {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+        {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+        {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+        {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+        {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+        {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+        {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+        {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+        {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+        {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+        {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+        {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+        {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+        {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+        {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+        {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+        {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+        {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+        {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+        {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+        {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+        {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+        {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+        {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+        {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+        {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+        {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+        {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+        {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+        {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+        {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+        {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+        {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+        {0,9,255}
+    };
+
+    static const code distfix[32] = {
+        {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+        {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+        {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+        {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+        {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+        {22,5,193},{64,5,0}
+    };
diff --git a/lib/zlib_inflate/inflate.c b/lib/zlib_inflate/inflate.c
index 31b9e90..7f922dc 100644
--- a/lib/zlib_inflate/inflate.c
+++ b/lib/zlib_inflate/inflate.c
@@ -1,89 +1,148 @@
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Based on zlib 1.2.3 but modified for the Linux Kernel by
+ * Richard Purdie <richard@openedhand.com>
+ *
+ * Changes mainly for static instead of dynamic memory allocation
+ *
  */
 
 #include <linux/zutil.h>
-#include "infblock.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
 #include "infutil.h"
 
 int zlib_inflate_workspacesize(void)
 {
-  return sizeof(struct inflate_workspace);
+    return sizeof(struct inflate_workspace);
+}
+
+int zlib_inflateReset(z_streamp strm)
+{
+    struct inflate_state *state;
+
+    if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state *)strm->state;
+    strm->total_in = strm->total_out = state->total = 0;
+    strm->msg = NULL;
+    strm->adler = 1;        /* to support ill-conceived Java test suite */
+    state->mode = HEAD;
+    state->last = 0;
+    state->havedict = 0;
+    state->dmax = 32768U;
+    state->hold = 0;
+    state->bits = 0;
+    state->lencode = state->distcode = state->next = state->codes;
+
+    /* Initialise Window */
+    state->wsize = 1U << state->wbits;
+    state->write = 0;
+    state->whave = 0;
+
+    return Z_OK;
+}
+
+#if 0
+int zlib_inflatePrime(z_streamp strm, int bits, int value)
+{
+    struct inflate_state *state;
+
+    if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state *)strm->state;
+    if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+    value &= (1L << bits) - 1;
+    state->hold += value << state->bits;
+    state->bits += bits;
+    return Z_OK;
+}
+#endif
+
+int zlib_inflateInit2(z_streamp strm, int windowBits)
+{
+    struct inflate_state *state;
+
+    if (strm == NULL) return Z_STREAM_ERROR;
+    strm->msg = NULL;                 /* in case we return an error */
+
+    state = &WS(strm)->inflate_state;
+    strm->state = (struct internal_state *)state;
+
+    if (windowBits < 0) {
+        state->wrap = 0;
+        windowBits = -windowBits;
+    }
+    else {
+        state->wrap = (windowBits >> 4) + 1;
+    }
+    if (windowBits < 8 || windowBits > 15) {
+        return Z_STREAM_ERROR;
+    }
+    state->wbits = (unsigned)windowBits;
+    state->window = &WS(strm)->working_window[0];
+
+    return zlib_inflateReset(strm);
+}
+
+/*
+   Return state with length and distance decoding tables and index sizes set to
+   fixed code decoding.  This returns fixed tables from inffixed.h.
+ */
+static void zlib_fixedtables(struct inflate_state *state)
+{
+#   include "inffixed.h"
+    state->lencode = lenfix;
+    state->lenbits = 9;
+    state->distcode = distfix;
+    state->distbits = 5;
 }
 
 
-int zlib_inflateReset(
-	z_streamp z
-)
+/*
+   Update the window with the last wsize (normally 32K) bytes written before
+   returning. This is only called when a window is already in use, or when
+   output has been written during this inflate call, but the end of the deflate
+   stream has not been reached yet. It is also called to window dictionary data
+   when a dictionary is loaded.
+
+   Providing output buffers larger than 32K to inflate() should provide a speed
+   advantage, since only the last 32K of output is copied to the sliding window
+   upon return from inflate(), and since all distances after the first 32K of
+   output will fall in the output data, making match copies simpler and faster.
+   The advantage may be dependent on the size of the processor's data caches.
+ */
+static void zlib_updatewindow(z_streamp strm, unsigned out)
 {
-  if (z == NULL || z->state == NULL || z->workspace == NULL)
-    return Z_STREAM_ERROR;
-  z->total_in = z->total_out = 0;
-  z->msg = NULL;
-  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
-  zlib_inflate_blocks_reset(z->state->blocks, z, NULL);
-  return Z_OK;
-}
+    struct inflate_state *state;
+    unsigned copy, dist;
 
+    state = (struct inflate_state *)strm->state;
 
-int zlib_inflateEnd(
-	z_streamp z
-)
-{
-  if (z == NULL || z->state == NULL || z->workspace == NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->blocks != NULL)
-    zlib_inflate_blocks_free(z->state->blocks, z);
-  z->state = NULL;
-  return Z_OK;
-}
-
-
-int zlib_inflateInit2_(
-	z_streamp z,
-	int w,
-	const char *version,
-	int stream_size
-)
-{
-  if (version == NULL || version[0] != ZLIB_VERSION[0] ||
-      stream_size != sizeof(z_stream) || z->workspace == NULL)
-      return Z_VERSION_ERROR;
-
-  /* initialize state */
-  z->msg = NULL;
-  z->state = &WS(z)->internal_state;
-  z->state->blocks = NULL;
-
-  /* handle undocumented nowrap option (no zlib header or check) */
-  z->state->nowrap = 0;
-  if (w < 0)
-  {
-    w = - w;
-    z->state->nowrap = 1;
-  }
-
-  /* set window size */
-  if (w < 8 || w > 15)
-  {
-    zlib_inflateEnd(z);
-    return Z_STREAM_ERROR;
-  }
-  z->state->wbits = (uInt)w;
-
-  /* create inflate_blocks state */
-  if ((z->state->blocks =
-      zlib_inflate_blocks_new(z, z->state->nowrap ? NULL : zlib_adler32, (uInt)1 << w))
-      == NULL)
-  {
-    zlib_inflateEnd(z);
-    return Z_MEM_ERROR;
-  }
-
-  /* reset state */
-  zlib_inflateReset(z);
-  return Z_OK;
+    /* copy state->wsize or less output bytes into the circular window */
+    copy = out - strm->avail_out;
+    if (copy >= state->wsize) {
+        memcpy(state->window, strm->next_out - state->wsize, state->wsize);
+        state->write = 0;
+        state->whave = state->wsize;
+    }
+    else {
+        dist = state->wsize - state->write;
+        if (dist > copy) dist = copy;
+        memcpy(state->window + state->write, strm->next_out - copy, dist);
+        copy -= dist;
+        if (copy) {
+            memcpy(state->window, strm->next_out - copy, copy);
+            state->write = copy;
+            state->whave = state->wsize;
+        }
+        else {
+            state->write += dist;
+            if (state->write == state->wsize) state->write = 0;
+            if (state->whave < state->wsize) state->whave += dist;
+        }
+    }
 }
 
 
@@ -91,157 +150,764 @@
  * At the end of a Deflate-compressed PPP packet, we expect to have seen
  * a `stored' block type value but not the (zero) length bytes.
  */
-static int zlib_inflate_packet_flush(inflate_blocks_statef *s)
+/*
+   Returns true if inflate is currently at the end of a block generated by
+   Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+   implementation to provide an additional safety check. PPP uses
+   Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+   block. When decompressing, PPP checks that at the end of input packet,
+   inflate is waiting for these length bytes.
+ */
+static int zlib_inflateSyncPacket(z_streamp strm)
 {
-    if (s->mode != LENS)
-	return Z_DATA_ERROR;
-    s->mode = TYPE;
+    struct inflate_state *state;
+
+    if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state *)strm->state;
+
+    if (state->mode == STORED && state->bits == 0) {
+	state->mode = TYPE;
+        return Z_OK;
+    }
+    return Z_DATA_ERROR;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#define UPDATE(check, buf, len) zlib_adler32(check, buf, len)
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+    do { \
+        put = strm->next_out; \
+        left = strm->avail_out; \
+        next = strm->next_in; \
+        have = strm->avail_in; \
+        hold = state->hold; \
+        bits = state->bits; \
+    } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+    do { \
+        strm->next_out = put; \
+        strm->avail_out = left; \
+        strm->next_in = next; \
+        strm->avail_in = have; \
+        state->hold = hold; \
+        state->bits = bits; \
+    } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+    do { \
+        hold = 0; \
+        bits = 0; \
+    } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+   if there is no input available. */
+#define PULLBYTE() \
+    do { \
+        if (have == 0) goto inf_leave; \
+        have--; \
+        hold += (unsigned long)(*next++) << bits; \
+        bits += 8; \
+    } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator.  If there is
+   not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+    do { \
+        while (bits < (unsigned)(n)) \
+            PULLBYTE(); \
+    } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+    ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+    do { \
+        hold >>= (n); \
+        bits -= (unsigned)(n); \
+    } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+    do { \
+        hold >>= bits & 7; \
+        bits -= bits & 7; \
+    } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+    ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+     (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+   inflate() uses a state machine to process as much input data and generate as
+   much output data as possible before returning.  The state machine is
+   structured roughly as follows:
+
+    for (;;) switch (state) {
+    ...
+    case STATEn:
+        if (not enough input data or output space to make progress)
+            return;
+        ... make progress ...
+        state = STATEm;
+        break;
+    ...
+    }
+
+   so when inflate() is called again, the same case is attempted again, and
+   if the appropriate resources are provided, the machine proceeds to the
+   next state.  The NEEDBITS() macro is usually the way the state evaluates
+   whether it can proceed or should return.  NEEDBITS() does the return if
+   the requested bits are not available.  The typical use of the BITS macros
+   is:
+
+        NEEDBITS(n);
+        ... do something with BITS(n) ...
+        DROPBITS(n);
+
+   where NEEDBITS(n) either returns from inflate() if there isn't enough
+   input left to load n bits into the accumulator, or it continues.  BITS(n)
+   gives the low n bits in the accumulator.  When done, DROPBITS(n) drops
+   the low n bits off the accumulator.  INITBITS() clears the accumulator
+   and sets the number of available bits to zero.  BYTEBITS() discards just
+   enough bits to put the accumulator on a byte boundary.  After BYTEBITS()
+   and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+   NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+   if there is no input available.  The decoding of variable length codes uses
+   PULLBYTE() directly in order to pull just enough bytes to decode the next
+   code, and no more.
+
+   Some states loop until they get enough input, making sure that enough
+   state information is maintained to continue the loop where it left off
+   if NEEDBITS() returns in the loop.  For example, want, need, and keep
+   would all have to actually be part of the saved state in case NEEDBITS()
+   returns:
+
+    case STATEw:
+        while (want < need) {
+            NEEDBITS(n);
+            keep[want++] = BITS(n);
+            DROPBITS(n);
+        }
+        state = STATEx;
+    case STATEx:
+
+   As shown above, if the next state is also the next case, then the break
+   is omitted.
+
+   A state may also return if there is not enough output space available to
+   complete that state.  Those states are copying stored data, writing a
+   literal byte, and copying a matching string.
+
+   When returning, a "goto inf_leave" is used to update the total counters,
+   update the check value, and determine whether any progress has been made
+   during that inflate() call in order to return the proper return code.
+   Progress is defined as a change in either strm->avail_in or strm->avail_out.
+   When there is a window, goto inf_leave will update the window with the last
+   output written.  If a goto inf_leave occurs in the middle of decompression
+   and there is no window currently, goto inf_leave will create one and copy
+   output to the window for the next call of inflate().
+
+   In this implementation, the flush parameter of inflate() only affects the
+   return code (per zlib.h).  inflate() always writes as much as possible to
+   strm->next_out, given the space available and the provided input--the effect
+   documented in zlib.h of Z_SYNC_FLUSH.  Furthermore, inflate() always defers
+   the allocation of and copying into a sliding window until necessary, which
+   provides the effect documented in zlib.h for Z_FINISH when the entire input
+   stream available.  So the only thing the flush parameter actually does is:
+   when flush is set to Z_FINISH, inflate() cannot return Z_OK.  Instead it
+   will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int zlib_inflate(z_streamp strm, int flush)
+{
+    struct inflate_state *state;
+    unsigned char *next;    /* next input */
+    unsigned char *put;     /* next output */
+    unsigned have, left;        /* available input and output */
+    unsigned long hold;         /* bit buffer */
+    unsigned bits;              /* bits in bit buffer */
+    unsigned in, out;           /* save starting available input and output */
+    unsigned copy;              /* number of stored or match bytes to copy */
+    unsigned char *from;    /* where to copy match bytes from */
+    code this;                  /* current decoding table entry */
+    code last;                  /* parent table entry */
+    unsigned len;               /* length to copy for repeats, bits to drop */
+    int ret;                    /* return code */
+    static const unsigned short order[19] = /* permutation of code lengths */
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+    if (strm == NULL || strm->state == NULL || strm->next_out == NULL ||
+        (strm->next_in == NULL && strm->avail_in != 0))
+        return Z_STREAM_ERROR;
+
+    state = (struct inflate_state *)strm->state;
+
+    if (state->mode == TYPE) state->mode = TYPEDO;      /* skip check */
+    LOAD();
+    in = have;
+    out = left;
+    ret = Z_OK;
+    for (;;)
+        switch (state->mode) {
+        case HEAD:
+            if (state->wrap == 0) {
+                state->mode = TYPEDO;
+                break;
+            }
+            NEEDBITS(16);
+            if (
+                ((BITS(8) << 8) + (hold >> 8)) % 31) {
+                strm->msg = (char *)"incorrect header check";
+                state->mode = BAD;
+                break;
+            }
+            if (BITS(4) != Z_DEFLATED) {
+                strm->msg = (char *)"unknown compression method";
+                state->mode = BAD;
+                break;
+            }
+            DROPBITS(4);
+            len = BITS(4) + 8;
+            if (len > state->wbits) {
+                strm->msg = (char *)"invalid window size";
+                state->mode = BAD;
+                break;
+            }
+            state->dmax = 1U << len;
+            strm->adler = state->check = zlib_adler32(0L, NULL, 0);
+            state->mode = hold & 0x200 ? DICTID : TYPE;
+            INITBITS();
+            break;
+        case DICTID:
+            NEEDBITS(32);
+            strm->adler = state->check = REVERSE(hold);
+            INITBITS();
+            state->mode = DICT;
+        case DICT:
+            if (state->havedict == 0) {
+                RESTORE();
+                return Z_NEED_DICT;
+            }
+            strm->adler = state->check = zlib_adler32(0L, NULL, 0);
+            state->mode = TYPE;
+        case TYPE:
+            if (flush == Z_BLOCK) goto inf_leave;
+        case TYPEDO:
+            if (state->last) {
+                BYTEBITS();
+                state->mode = CHECK;
+                break;
+            }
+            NEEDBITS(3);
+            state->last = BITS(1);
+            DROPBITS(1);
+            switch (BITS(2)) {
+            case 0:                             /* stored block */
+                state->mode = STORED;
+                break;
+            case 1:                             /* fixed block */
+                zlib_fixedtables(state);
+                state->mode = LEN;              /* decode codes */
+                break;
+            case 2:                             /* dynamic block */
+                state->mode = TABLE;
+                break;
+            case 3:
+                strm->msg = (char *)"invalid block type";
+                state->mode = BAD;
+            }
+            DROPBITS(2);
+            break;
+        case STORED:
+            BYTEBITS();                         /* go to byte boundary */
+            NEEDBITS(32);
+            if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+                strm->msg = (char *)"invalid stored block lengths";
+                state->mode = BAD;
+                break;
+            }
+            state->length = (unsigned)hold & 0xffff;
+            INITBITS();
+            state->mode = COPY;
+        case COPY:
+            copy = state->length;
+            if (copy) {
+                if (copy > have) copy = have;
+                if (copy > left) copy = left;
+                if (copy == 0) goto inf_leave;
+                memcpy(put, next, copy);
+                have -= copy;
+                next += copy;
+                left -= copy;
+                put += copy;
+                state->length -= copy;
+                break;
+            }
+            state->mode = TYPE;
+            break;
+        case TABLE:
+            NEEDBITS(14);
+            state->nlen = BITS(5) + 257;
+            DROPBITS(5);
+            state->ndist = BITS(5) + 1;
+            DROPBITS(5);
+            state->ncode = BITS(4) + 4;
+            DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+            if (state->nlen > 286 || state->ndist > 30) {
+                strm->msg = (char *)"too many length or distance symbols";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            state->have = 0;
+            state->mode = LENLENS;
+        case LENLENS:
+            while (state->have < state->ncode) {
+                NEEDBITS(3);
+                state->lens[order[state->have++]] = (unsigned short)BITS(3);
+                DROPBITS(3);
+            }
+            while (state->have < 19)
+                state->lens[order[state->have++]] = 0;
+            state->next = state->codes;
+            state->lencode = (code const *)(state->next);
+            state->lenbits = 7;
+            ret = zlib_inflate_table(CODES, state->lens, 19, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid code lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->have = 0;
+            state->mode = CODELENS;
+        case CODELENS:
+            while (state->have < state->nlen + state->ndist) {
+                for (;;) {
+                    this = state->lencode[BITS(state->lenbits)];
+                    if ((unsigned)(this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                if (this.val < 16) {
+                    NEEDBITS(this.bits);
+                    DROPBITS(this.bits);
+                    state->lens[state->have++] = this.val;
+                }
+                else {
+                    if (this.val == 16) {
+                        NEEDBITS(this.bits + 2);
+                        DROPBITS(this.bits);
+                        if (state->have == 0) {
+                            strm->msg = (char *)"invalid bit length repeat";
+                            state->mode = BAD;
+                            break;
+                        }
+                        len = state->lens[state->have - 1];
+                        copy = 3 + BITS(2);
+                        DROPBITS(2);
+                    }
+                    else if (this.val == 17) {
+                        NEEDBITS(this.bits + 3);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 3 + BITS(3);
+                        DROPBITS(3);
+                    }
+                    else {
+                        NEEDBITS(this.bits + 7);
+                        DROPBITS(this.bits);
+                        len = 0;
+                        copy = 11 + BITS(7);
+                        DROPBITS(7);
+                    }
+                    if (state->have + copy > state->nlen + state->ndist) {
+                        strm->msg = (char *)"invalid bit length repeat";
+                        state->mode = BAD;
+                        break;
+                    }
+                    while (copy--)
+                        state->lens[state->have++] = (unsigned short)len;
+                }
+            }
+
+            /* handle error breaks in while */
+            if (state->mode == BAD) break;
+
+            /* build code tables */
+            state->next = state->codes;
+            state->lencode = (code const *)(state->next);
+            state->lenbits = 9;
+            ret = zlib_inflate_table(LENS, state->lens, state->nlen, &(state->next),
+                                &(state->lenbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid literal/lengths set";
+                state->mode = BAD;
+                break;
+            }
+            state->distcode = (code const *)(state->next);
+            state->distbits = 6;
+            ret = zlib_inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+                            &(state->next), &(state->distbits), state->work);
+            if (ret) {
+                strm->msg = (char *)"invalid distances set";
+                state->mode = BAD;
+                break;
+            }
+            state->mode = LEN;
+        case LEN:
+            if (have >= 6 && left >= 258) {
+                RESTORE();
+                inflate_fast(strm, out);
+                LOAD();
+                break;
+            }
+            for (;;) {
+                this = state->lencode[BITS(state->lenbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if (this.op && (this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->lencode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            state->length = (unsigned)this.val;
+            if ((int)(this.op) == 0) {
+                state->mode = LIT;
+                break;
+            }
+            if (this.op & 32) {
+                state->mode = TYPE;
+                break;
+            }
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid literal/length code";
+                state->mode = BAD;
+                break;
+            }
+            state->extra = (unsigned)(this.op) & 15;
+            state->mode = LENEXT;
+        case LENEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->length += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+            state->mode = DIST;
+        case DIST:
+            for (;;) {
+                this = state->distcode[BITS(state->distbits)];
+                if ((unsigned)(this.bits) <= bits) break;
+                PULLBYTE();
+            }
+            if ((this.op & 0xf0) == 0) {
+                last = this;
+                for (;;) {
+                    this = state->distcode[last.val +
+                            (BITS(last.bits + last.op) >> last.bits)];
+                    if ((unsigned)(last.bits + this.bits) <= bits) break;
+                    PULLBYTE();
+                }
+                DROPBITS(last.bits);
+            }
+            DROPBITS(this.bits);
+            if (this.op & 64) {
+                strm->msg = (char *)"invalid distance code";
+                state->mode = BAD;
+                break;
+            }
+            state->offset = (unsigned)this.val;
+            state->extra = (unsigned)(this.op) & 15;
+            state->mode = DISTEXT;
+        case DISTEXT:
+            if (state->extra) {
+                NEEDBITS(state->extra);
+                state->offset += BITS(state->extra);
+                DROPBITS(state->extra);
+            }
+#ifdef INFLATE_STRICT
+            if (state->offset > state->dmax) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+#endif
+            if (state->offset > state->whave + out - left) {
+                strm->msg = (char *)"invalid distance too far back";
+                state->mode = BAD;
+                break;
+            }
+            state->mode = MATCH;
+        case MATCH:
+            if (left == 0) goto inf_leave;
+            copy = out - left;
+            if (state->offset > copy) {         /* copy from window */
+                copy = state->offset - copy;
+                if (copy > state->write) {
+                    copy -= state->write;
+                    from = state->window + (state->wsize - copy);
+                }
+                else
+                    from = state->window + (state->write - copy);
+                if (copy > state->length) copy = state->length;
+            }
+            else {                              /* copy from output */
+                from = put - state->offset;
+                copy = state->length;
+            }
+            if (copy > left) copy = left;
+            left -= copy;
+            state->length -= copy;
+            do {
+                *put++ = *from++;
+            } while (--copy);
+            if (state->length == 0) state->mode = LEN;
+            break;
+        case LIT:
+            if (left == 0) goto inf_leave;
+            *put++ = (unsigned char)(state->length);
+            left--;
+            state->mode = LEN;
+            break;
+        case CHECK:
+            if (state->wrap) {
+                NEEDBITS(32);
+                out -= left;
+                strm->total_out += out;
+                state->total += out;
+                if (out)
+                    strm->adler = state->check =
+                        UPDATE(state->check, put - out, out);
+                out = left;
+                if ((
+                     REVERSE(hold)) != state->check) {
+                    strm->msg = (char *)"incorrect data check";
+                    state->mode = BAD;
+                    break;
+                }
+                INITBITS();
+            }
+            state->mode = DONE;
+        case DONE:
+            ret = Z_STREAM_END;
+            goto inf_leave;
+        case BAD:
+            ret = Z_DATA_ERROR;
+            goto inf_leave;
+        case MEM:
+            return Z_MEM_ERROR;
+        case SYNC:
+        default:
+            return Z_STREAM_ERROR;
+        }
+
+    /*
+       Return from inflate(), updating the total counts and the check value.
+       If there was no progress during the inflate() call, return a buffer
+       error.  Call zlib_updatewindow() to create and/or update the window state.
+     */
+  inf_leave:
+    RESTORE();
+    if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+        zlib_updatewindow(strm, out);
+
+    in -= strm->avail_in;
+    out -= strm->avail_out;
+    strm->total_in += in;
+    strm->total_out += out;
+    state->total += out;
+    if (state->wrap && out)
+        strm->adler = state->check =
+            UPDATE(state->check, strm->next_out - out, out);
+
+    strm->data_type = state->bits + (state->last ? 64 : 0) +
+                      (state->mode == TYPE ? 128 : 0);
+    if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+        ret = Z_BUF_ERROR;
+
+    if (flush == Z_PACKET_FLUSH && ret == Z_OK &&
+            (strm->avail_out != 0 || strm->avail_in == 0))
+		return zlib_inflateSyncPacket(strm);
+    return ret;
+}
+
+int zlib_inflateEnd(z_streamp strm)
+{
+    if (strm == NULL || strm->state == NULL)
+        return Z_STREAM_ERROR;
     return Z_OK;
 }
 
-
-int zlib_inflateInit_(
-	z_streamp z,
-	const char *version,
-	int stream_size
-)
+#if 0
+int zlib_inflateSetDictionary(z_streamp strm, const Byte *dictionary,
+        uInt dictLength)
 {
-  return zlib_inflateInit2_(z, DEF_WBITS, version, stream_size);
+    struct inflate_state *state;
+    unsigned long id;
+
+    /* check state */
+    if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state *)strm->state;
+    if (state->wrap != 0 && state->mode != DICT)
+        return Z_STREAM_ERROR;
+
+    /* check for correct dictionary id */
+    if (state->mode == DICT) {
+        id = zlib_adler32(0L, NULL, 0);
+        id = zlib_adler32(id, dictionary, dictLength);
+        if (id != state->check)
+            return Z_DATA_ERROR;
+    }
+
+    /* copy dictionary to window */
+    zlib_updatewindow(strm, strm->avail_out);
+
+    if (dictLength > state->wsize) {
+        memcpy(state->window, dictionary + dictLength - state->wsize,
+                state->wsize);
+        state->whave = state->wsize;
+    }
+    else {
+        memcpy(state->window + state->wsize - dictLength, dictionary,
+                dictLength);
+        state->whave = dictLength;
+    }
+    state->havedict = 1;
+    return Z_OK;
 }
+#endif
 
-#undef NEEDBYTE
-#undef NEXTBYTE
-#define NEEDBYTE {if(z->avail_in==0)goto empty;r=trv;}
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-int zlib_inflate(
-	z_streamp z,
-	int f
-)
+#if 0
+/*
+   Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff.  Return when found
+   or when out of input.  When called, *have is the number of pattern bytes
+   found in order so far, in 0..3.  On return *have is updated to the new
+   state.  If on return *have equals four, then the pattern was found and the
+   return value is how many bytes were read including the last byte of the
+   pattern.  If *have is less than four, then the pattern has not been found
+   yet and the return value is len.  In the latter case, zlib_syncsearch() can be
+   called again with more data and the *have state.  *have is initialized to
+   zero for the first call.
+ */
+static unsigned zlib_syncsearch(unsigned *have, unsigned char *buf,
+        unsigned len)
 {
-  int r, trv;
-  uInt b;
+    unsigned got;
+    unsigned next;
 
-  if (z == NULL || z->state == NULL || z->next_in == NULL)
-    return Z_STREAM_ERROR;
-  trv = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
-  r = Z_BUF_ERROR;
-  while (1) switch (z->state->mode)
-  {
-    case METHOD:
-      NEEDBYTE
-      if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
-      {
-        z->state->mode = I_BAD;
-        z->msg = (char*)"unknown compression method";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
-      {
-        z->state->mode = I_BAD;
-        z->msg = (char*)"invalid window size";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      z->state->mode = FLAG;
-    case FLAG:
-      NEEDBYTE
-      b = NEXTBYTE;
-      if (((z->state->sub.method << 8) + b) % 31)
-      {
-        z->state->mode = I_BAD;
-        z->msg = (char*)"incorrect header check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if (!(b & PRESET_DICT))
-      {
-        z->state->mode = BLOCKS;
-        break;
-      }
-      z->state->mode = DICT4;
-    case DICT4:
-      NEEDBYTE
-      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
-      z->state->mode = DICT3;
-    case DICT3:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
-      z->state->mode = DICT2;
-    case DICT2:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
-      z->state->mode = DICT1;
-    case DICT1:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE;
-      z->adler = z->state->sub.check.need;
-      z->state->mode = DICT0;
-      return Z_NEED_DICT;
-    case DICT0:
-      z->state->mode = I_BAD;
-      z->msg = (char*)"need dictionary";
-      z->state->sub.marker = 0;       /* can try inflateSync */
-      return Z_STREAM_ERROR;
-    case BLOCKS:
-      r = zlib_inflate_blocks(z->state->blocks, z, r);
-      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
-	  r = zlib_inflate_packet_flush(z->state->blocks);
-      if (r == Z_DATA_ERROR)
-      {
-        z->state->mode = I_BAD;
-        z->state->sub.marker = 0;       /* can try inflateSync */
-        break;
-      }
-      if (r == Z_OK)
-        r = trv;
-      if (r != Z_STREAM_END)
-        return r;
-      r = trv;
-      zlib_inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
-      if (z->state->nowrap)
-      {
-        z->state->mode = I_DONE;
-        break;
-      }
-      z->state->mode = CHECK4;
-    case CHECK4:
-      NEEDBYTE
-      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
-      z->state->mode = CHECK3;
-    case CHECK3:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
-      z->state->mode = CHECK2;
-    case CHECK2:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
-      z->state->mode = CHECK1;
-    case CHECK1:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE;
+    got = *have;
+    next = 0;
+    while (next < len && got < 4) {
+        if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+            got++;
+        else if (buf[next])
+            got = 0;
+        else
+            got = 4 - got;
+        next++;
+    }
+    *have = got;
+    return next;
+}
+#endif
 
-      if (z->state->sub.check.was != z->state->sub.check.need)
-      {
-        z->state->mode = I_BAD;
-        z->msg = (char*)"incorrect data check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      z->state->mode = I_DONE;
-    case I_DONE:
-      return Z_STREAM_END;
-    case I_BAD:
-      return Z_DATA_ERROR;
-    default:
-      return Z_STREAM_ERROR;
-  }
- empty:
-  if (f != Z_PACKET_FLUSH)
-    return r;
-  z->state->mode = I_BAD;
-  z->msg = (char *)"need more for packet flush";
-  z->state->sub.marker = 0;       /* can try inflateSync */
-  return Z_DATA_ERROR;
+#if 0
+int zlib_inflateSync(z_streamp strm)
+{
+    unsigned len;               /* number of bytes to look at or looked at */
+    unsigned long in, out;      /* temporary to save total_in and total_out */
+    unsigned char buf[4];       /* to restore bit buffer to byte string */
+    struct inflate_state *state;
+
+    /* check parameters */
+    if (strm == NULL || strm->state == NULL) return Z_STREAM_ERROR;
+    state = (struct inflate_state *)strm->state;
+    if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+    /* if first time, start search in bit buffer */
+    if (state->mode != SYNC) {
+        state->mode = SYNC;
+        state->hold <<= state->bits & 7;
+        state->bits -= state->bits & 7;
+        len = 0;
+        while (state->bits >= 8) {
+            buf[len++] = (unsigned char)(state->hold);
+            state->hold >>= 8;
+            state->bits -= 8;
+        }
+        state->have = 0;
+        zlib_syncsearch(&(state->have), buf, len);
+    }
+
+    /* search available input */
+    len = zlib_syncsearch(&(state->have), strm->next_in, strm->avail_in);
+    strm->avail_in -= len;
+    strm->next_in += len;
+    strm->total_in += len;
+
+    /* return no joy or set up to restart inflate() on a new block */
+    if (state->have != 4) return Z_DATA_ERROR;
+    in = strm->total_in;  out = strm->total_out;
+    zlib_inflateReset(strm);
+    strm->total_in = in;  strm->total_out = out;
+    state->mode = TYPE;
+    return Z_OK;
+}
+#endif
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output.  The output buffer must be "caught up";
+ * i.e. no pending output but this should always be the case. The state must
+ * be waiting on the start of a block (i.e. mode == TYPE or HEAD).  On exit,
+ * the output will also be caught up, and the checksum will have been updated
+ * if need be.
+ */
+int zlib_inflateIncomp(z_stream *z)
+{
+    struct inflate_state *state = (struct inflate_state *)z->state;
+    Byte *saved_no = z->next_out;
+    uInt saved_ao = z->avail_out;
+
+    if (state->mode != TYPE && state->mode != HEAD)
+	return Z_DATA_ERROR;
+
+    /* Setup some variables to allow misuse of updateWindow */
+    z->avail_out = 0;
+    z->next_out = z->next_in + z->avail_in;
+
+    zlib_updatewindow(z, z->avail_in);
+
+    /* Restore saved variables */
+    z->avail_out = saved_ao;
+    z->next_out = saved_no;
+
+    z->adler = state->check =
+        UPDATE(state->check, z->next_in, z->avail_in);
+
+    z->total_out += z->avail_in;
+    z->total_in += z->avail_in;
+    z->next_in += z->avail_in;
+    state->total += z->avail_in;
+    z->avail_in = 0;
+
+    return Z_OK;
 }
diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h
new file mode 100644
index 0000000..df8a6c9
--- /dev/null
+++ b/lib/zlib_inflate/inflate.h
@@ -0,0 +1,107 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+    HEAD,       /* i: waiting for magic header */
+    FLAGS,      /* i: waiting for method and flags (gzip) */
+    TIME,       /* i: waiting for modification time (gzip) */
+    OS,         /* i: waiting for extra flags and operating system (gzip) */
+    EXLEN,      /* i: waiting for extra length (gzip) */
+    EXTRA,      /* i: waiting for extra bytes (gzip) */
+    NAME,       /* i: waiting for end of file name (gzip) */
+    COMMENT,    /* i: waiting for end of comment (gzip) */
+    HCRC,       /* i: waiting for header crc (gzip) */
+    DICTID,     /* i: waiting for dictionary check value */
+    DICT,       /* waiting for inflateSetDictionary() call */
+        TYPE,       /* i: waiting for type bits, including last-flag bit */
+        TYPEDO,     /* i: same, but skip check to exit inflate on new block */
+        STORED,     /* i: waiting for stored size (length and complement) */
+        COPY,       /* i/o: waiting for input or output to copy stored block */
+        TABLE,      /* i: waiting for dynamic block table lengths */
+        LENLENS,    /* i: waiting for code length code lengths */
+        CODELENS,   /* i: waiting for length/lit and distance code lengths */
+            LEN,        /* i: waiting for length/lit code */
+            LENEXT,     /* i: waiting for length extra bits */
+            DIST,       /* i: waiting for distance code */
+            DISTEXT,    /* i: waiting for distance extra bits */
+            MATCH,      /* o: waiting for output space to copy string */
+            LIT,        /* o: waiting for output space to write literal */
+    CHECK,      /* i: waiting for 32-bit check value */
+    LENGTH,     /* i: waiting for 32-bit length (gzip) */
+    DONE,       /* finished check, done -- remain here until reset */
+    BAD,        /* got a data error -- remain here until reset */
+    MEM,        /* got an inflate() memory error -- remain here until reset */
+    SYNC        /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+    State transitions between above modes -
+
+    (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+    Process header:
+        HEAD -> (gzip) or (zlib)
+        (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+        NAME -> COMMENT -> HCRC -> TYPE
+        (zlib) -> DICTID or TYPE
+        DICTID -> DICT -> TYPE
+    Read deflate blocks:
+            TYPE -> STORED or TABLE or LEN or CHECK
+            STORED -> COPY -> TYPE
+            TABLE -> LENLENS -> CODELENS -> LEN
+    Read deflate codes:
+                LEN -> LENEXT or LIT or TYPE
+                LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+                LIT -> LEN
+    Process trailer:
+        CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls.  Approximately 7K bytes. */
+struct inflate_state {
+    inflate_mode mode;          /* current inflate mode */
+    int last;                   /* true if processing last block */
+    int wrap;                   /* bit 0 true for zlib, bit 1 true for gzip */
+    int havedict;               /* true if dictionary provided */
+    int flags;                  /* gzip header method and flags (0 if zlib) */
+    unsigned dmax;              /* zlib header max distance (INFLATE_STRICT) */
+    unsigned long check;        /* protected copy of check value */
+    unsigned long total;        /* protected copy of output count */
+ /*   gz_headerp head; */           /* where to save gzip header information */
+        /* sliding window */
+    unsigned wbits;             /* log base 2 of requested window size */
+    unsigned wsize;             /* window size or zero if not using window */
+    unsigned whave;             /* valid bytes in the window */
+    unsigned write;             /* window write index */
+    unsigned char *window;  /* allocated sliding window, if needed */
+        /* bit accumulator */
+    unsigned long hold;         /* input bit accumulator */
+    unsigned bits;              /* number of bits in "in" */
+        /* for string and stored block copying */
+    unsigned length;            /* literal or length of data to copy */
+    unsigned offset;            /* distance back to copy string from */
+        /* for table and code decoding */
+    unsigned extra;             /* extra bits needed */
+        /* fixed and dynamic code tables */
+    code const *lencode;    /* starting table for length/literal codes */
+    code const *distcode;   /* starting table for distance codes */
+    unsigned lenbits;           /* index bits for lencode */
+    unsigned distbits;          /* index bits for distcode */
+        /* dynamic table building */
+    unsigned ncode;             /* number of code length code lengths */
+    unsigned nlen;              /* number of length code lengths */
+    unsigned ndist;             /* number of distance code lengths */
+    unsigned have;              /* number of code lengths in lens[] */
+    code *next;             /* next available space in codes[] */
+    unsigned short lens[320];   /* temporary storage for code lengths */
+    unsigned short work[288];   /* work area for code table building */
+    code codes[ENOUGH];         /* space for code tables */
+};
diff --git a/lib/zlib_inflate/inflate_syms.c b/lib/zlib_inflate/inflate_syms.c
index ef49738..2061d4f 100644
--- a/lib/zlib_inflate/inflate_syms.c
+++ b/lib/zlib_inflate/inflate_syms.c
@@ -12,8 +12,7 @@
 
 EXPORT_SYMBOL(zlib_inflate_workspacesize);
 EXPORT_SYMBOL(zlib_inflate);
-EXPORT_SYMBOL(zlib_inflateInit_);
-EXPORT_SYMBOL(zlib_inflateInit2_);
+EXPORT_SYMBOL(zlib_inflateInit2);
 EXPORT_SYMBOL(zlib_inflateEnd);
 EXPORT_SYMBOL(zlib_inflateReset);
 EXPORT_SYMBOL(zlib_inflateIncomp); 
diff --git a/lib/zlib_inflate/inflate_sync.c b/lib/zlib_inflate/inflate_sync.c
deleted file mode 100644
index 61411ff..0000000
--- a/lib/zlib_inflate/inflate_sync.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include <linux/zutil.h>
-#include "infblock.h"
-#include "infutil.h"
-
-#if 0
-int zlib_inflateSync(
-	z_streamp z
-)
-{
-  uInt n;       /* number of bytes to look at */
-  Byte *p;      /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == NULL || z->state == NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != I_BAD)
-  {
-    z->state->mode = I_BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    static const Byte mark[4] = {0, 0, 0xff, 0xff};
-    if (*p == mark[m])
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  zlib_inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-#endif  /*  0  */
-
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
- * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
- * but removes the length bytes of the resulting empty stored block. When
- * decompressing, PPP checks that at the end of input packet, inflate is
- * waiting for these length bytes.
- */
-#if 0
-int zlib_inflateSyncPoint(
-	z_streamp z
-)
-{
-  if (z == NULL || z->state == NULL || z->state->blocks == NULL)
-    return Z_STREAM_ERROR;
-  return zlib_inflate_blocks_sync_point(z->state->blocks);
-}
-#endif  /*  0  */
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-static int zlib_inflate_addhistory(inflate_blocks_statef *s,
-				      z_stream              *z)
-{
-    uLong b;              /* bit buffer */  /* NOT USED HERE */
-    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
-    uInt t;               /* temporary storage */
-    Byte *p;              /* input data pointer */
-    uInt n;               /* bytes available there */
-    Byte *q;              /* output window write pointer */
-    uInt m;               /* bytes to end of window or read pointer */
-
-    if (s->read != s->write)
-	return Z_STREAM_ERROR;
-    if (s->mode != TYPE)
-	return Z_DATA_ERROR;
-
-    /* we're ready to rock */
-    LOAD
-    /* while there is input ready, copy to output buffer, moving
-     * pointers as needed.
-     */
-    while (n) {
-	t = n;  /* how many to do */
-	/* is there room until end of buffer? */
-	if (t > m) t = m;
-	/* update check information */
-	if (s->checkfn != NULL)
-	    s->check = (*s->checkfn)(s->check, q, t);
-	memcpy(q, p, t);
-	q += t;
-	p += t;
-	n -= t;
-	z->total_out += t;
-	s->read = q;    /* drag read pointer forward */
-/*      WWRAP  */ 	/* expand WWRAP macro by hand to handle s->read */
-	if (q == s->end) {
-	    s->read = q = s->window;
-	    m = WAVAIL;
-	}
-    }
-    UPDATE
-    return Z_OK;
-}
-
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int zlib_inflateIncomp(
-	z_stream *z
-
-)
-{
-    if (z->state->mode != BLOCKS)
-	return Z_DATA_ERROR;
-    return zlib_inflate_addhistory(z->state->blocks, z);
-}
diff --git a/lib/zlib_inflate/inftrees.c b/lib/zlib_inflate/inftrees.c
index 874950e..3fe6ce5 100644
--- a/lib/zlib_inflate/inftrees.c
+++ b/lib/zlib_inflate/inftrees.c
@@ -1,412 +1,315 @@
 /* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 #include <linux/zutil.h>
 #include "inftrees.h"
-#include "infutil.h"
 
-static const char inflate_copyright[] __attribute_used__ =
-   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
+#define MAXBITS 15
+
 /*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
+   Build a set of tables to decode the provided canonical Huffman code.
+   The code lengths are lens[0..codes-1].  The result starts at *table,
+   whose indices are 0..2^bits-1.  work is a writable array of at least
+   lens shorts, which is used as a work area.  type is the type of code
+   to be generated, CODES, LENS, or DISTS.  On return, zero is success,
+   -1 is an invalid code, and +1 means that ENOUGH isn't enough.  table
+   on return points to the next available entry's address.  bits is the
+   requested root table index bits, and on return it is the actual root
+   table index bits.  It will differ if the request is greater than the
+   longest code or if it is less than the shortest code.
  */
-struct internal_state;
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-static int huft_build (
-    uInt *,             /* code lengths in bits */
-    uInt,               /* number of codes */
-    uInt,               /* number of "simple" codes */
-    const uInt *,       /* list of base values for non-simple codes */
-    const uInt *,       /* list of extra bits for non-simple codes */
-    inflate_huft **,    /* result: starting table */
-    uInt *,             /* maximum lookup bits (returns actual) */
-    inflate_huft *,     /* space for trees */
-    uInt *,             /* hufts used in space */
-    uInt * );           /* space for values */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-static const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+int zlib_inflate_table(codetype type, unsigned short *lens, unsigned codes,
+			code **table, unsigned *bits, unsigned short *work)
+{
+    unsigned len;               /* a code's length in bits */
+    unsigned sym;               /* index of code symbols */
+    unsigned min, max;          /* minimum and maximum code lengths */
+    unsigned root;              /* number of index bits for root table */
+    unsigned curr;              /* number of index bits for current table */
+    unsigned drop;              /* code bits to drop for sub-table */
+    int left;                   /* number of prefix codes available */
+    unsigned used;              /* code entries in table used */
+    unsigned huff;              /* Huffman code */
+    unsigned incr;              /* for incrementing code, index */
+    unsigned fill;              /* index for replicating entries */
+    unsigned low;               /* low bits for current root entry */
+    unsigned mask;              /* mask for low root bits */
+    code this;                  /* table entry for duplication */
+    code *next;             /* next available space in table */
+    const unsigned short *base;     /* base value table to use */
+    const unsigned short *extra;    /* extra bits table to use */
+    int end;                    /* use base and extra for symbol > end */
+    unsigned short count[MAXBITS+1];    /* number of codes of each length */
+    unsigned short offs[MAXBITS+1];     /* offsets in table for each length */
+    static const unsigned short lbase[31] = { /* Length codes 257..285 base */
         3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-        /* see note #13 above about 258 */
-static const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
-        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
-        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
-static const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+    static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+        16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+        19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+    static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577};
-static const uInt cpdext[30] = { /* Extra bits for distance codes */
-        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
-        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-        12, 12, 13, 13};
+        8193, 12289, 16385, 24577, 0, 0};
+    static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+        16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+        23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+        28, 28, 29, 29, 64, 64};
 
-/*
-   Huffman code decoding is performed using a multi-level table lookup.
-   The fastest way to decode is to simply build a lookup table whose
-   size is determined by the longest code.  However, the time it takes
-   to build this table can also be a factor if the data being decoded
-   is not very long.  The most common codes are necessarily the
-   shortest codes, so those codes dominate the decoding time, and hence
-   the speed.  The idea is you can have a shorter table that decodes the
-   shorter, more probable codes, and then point to subsidiary tables for
-   the longer codes.  The time it costs to decode the longer codes is
-   then traded against the time it takes to make longer tables.
+    /*
+       Process a set of code lengths to create a canonical Huffman code.  The
+       code lengths are lens[0..codes-1].  Each length corresponds to the
+       symbols 0..codes-1.  The Huffman code is generated by first sorting the
+       symbols by length from short to long, and retaining the symbol order
+       for codes with equal lengths.  Then the code starts with all zero bits
+       for the first code of the shortest length, and the codes are integer
+       increments for the same length, and zeros are appended as the length
+       increases.  For the deflate format, these bits are stored backwards
+       from their more natural integer increment ordering, and so when the
+       decoding tables are built in the large loop below, the integer codes
+       are incremented backwards.
 
-   This results of this trade are in the variables lbits and dbits
-   below.  lbits is the number of bits the first level table for literal/
-   length codes can decode in one step, and dbits is the same thing for
-   the distance codes.  Subsequent tables are also less than or equal to
-   those sizes.  These values may be adjusted either when all of the
-   codes are shorter than that, in which case the longest code length in
-   bits is used, or when the shortest code is *longer* than the requested
-   table size, in which case the length of the shortest code in bits is
-   used.
+       This routine assumes, but does not check, that all of the entries in
+       lens[] are in the range 0..MAXBITS.  The caller must assure this.
+       1..MAXBITS is interpreted as that code length.  zero means that that
+       symbol does not occur in this code.
 
-   There are two different values for the two tables, since they code a
-   different number of possibilities each.  The literal/length table
-   codes 286 possible values, or in a flat code, a little over eight
-   bits.  The distance table codes 30 possible values, or a little less
-   than five bits, flat.  The optimum values for speed end up being
-   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
-   The optimum values may differ though from machine to machine, and
-   possibly even between compilers.  Your mileage may vary.
- */
+       The codes are sorted by computing a count of codes for each length,
+       creating from that a table of starting indices for each length in the
+       sorted table, and then entering the symbols in order in the sorted
+       table.  The sorted table is work[], with that space being provided by
+       the caller.
 
+       The length counts are used for other purposes as well, i.e. finding
+       the minimum and maximum length codes, determining if there are any
+       codes at all, checking for a valid set of lengths, and looking ahead
+       at length counts to determine sub-table sizes when building the
+       decoding tables.
+     */
 
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15         /* maximum bit length of any code */
+    /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+    for (len = 0; len <= MAXBITS; len++)
+        count[len] = 0;
+    for (sym = 0; sym < codes; sym++)
+        count[lens[sym]]++;
 
-static int huft_build(
-	uInt *b,               /* code lengths in bits (all assumed <= BMAX) */
-	uInt n,                /* number of codes (assumed <= 288) */
-	uInt s,                /* number of simple-valued codes (0..s-1) */
-	const uInt *d,         /* list of base values for non-simple codes */
-	const uInt *e,         /* list of extra bits for non-simple codes */
-	inflate_huft **t,      /* result: starting table */
-	uInt *m,               /* maximum lookup bits, returns actual */
-	inflate_huft *hp,      /* space for trees */
-	uInt *hn,              /* hufts used in space */
-	uInt *v                /* working area: values in order of bit length */
-)
-/* Given a list of code lengths and a maximum table size, make a set of
-   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
-   if the given code set is incomplete (the tables are still built in this
-   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
-   lengths), or Z_MEM_ERROR if not enough memory. */
-{
+    /* bound code lengths, force root to be within code lengths */
+    root = *bits;
+    for (max = MAXBITS; max >= 1; max--)
+        if (count[max] != 0) break;
+    if (root > max) root = max;
+    if (max == 0) {                     /* no symbols to code at all */
+        this.op = (unsigned char)64;    /* invalid code marker */
+        this.bits = (unsigned char)1;
+        this.val = (unsigned short)0;
+        *(*table)++ = this;             /* make a table to force an error */
+        *(*table)++ = this;
+        *bits = 1;
+        return 0;     /* no symbols, but wait for decoding to report error */
+    }
+    for (min = 1; min <= MAXBITS; min++)
+        if (count[min] != 0) break;
+    if (root < min) root = min;
 
-  uInt a;                       /* counter for codes of length k */
-  uInt c[BMAX+1];               /* bit length count table */
-  uInt f;                       /* i repeats in table every f entries */
-  int g;                        /* maximum code length */
-  int h;                        /* table level */
-  register uInt i;              /* counter, current code */
-  register uInt j;              /* counter */
-  register int k;               /* number of bits in current code */
-  int l;                        /* bits per table (returned in m) */
-  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
-  register uInt *p;             /* pointer into c[], b[], or v[] */
-  inflate_huft *q;              /* points to current table */
-  struct inflate_huft_s r;      /* table entry for structure assignment */
-  inflate_huft *u[BMAX];        /* table stack */
-  register int w;               /* bits before this table == (l * h) */
-  uInt x[BMAX+1];               /* bit offsets, then code stack */
-  uInt *xp;                     /* pointer into x */
-  int y;                        /* number of dummy codes added */
-  uInt z;                       /* number of entries in current table */
+    /* check for an over-subscribed or incomplete set of lengths */
+    left = 1;
+    for (len = 1; len <= MAXBITS; len++) {
+        left <<= 1;
+        left -= count[len];
+        if (left < 0) return -1;        /* over-subscribed */
+    }
+    if (left > 0 && (type == CODES || max != 1))
+        return -1;                      /* incomplete set */
 
+    /* generate offsets into symbol table for each length for sorting */
+    offs[1] = 0;
+    for (len = 1; len < MAXBITS; len++)
+        offs[len + 1] = offs[len] + count[len];
 
-  /* Generate counts for each bit length */
-  p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
-  C4                            /* clear c[]--assume BMAX+1 is 16 */
-  p = b;  i = n;
-  do {
-    c[*p++]++;                  /* assume all entries <= BMAX */
-  } while (--i);
-  if (c[0] == n)                /* null input--all zero length codes */
-  {
-    *t = NULL;
-    *m = 0;
-    return Z_OK;
-  }
+    /* sort symbols by length, by symbol order within each length */
+    for (sym = 0; sym < codes; sym++)
+        if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
 
+    /*
+       Create and fill in decoding tables.  In this loop, the table being
+       filled is at next and has curr index bits.  The code being used is huff
+       with length len.  That code is converted to an index by dropping drop
+       bits off of the bottom.  For codes where len is less than drop + curr,
+       those top drop + curr - len bits are incremented through all values to
+       fill the table with replicated entries.
 
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((uInt)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((uInt)l > i)
-    l = i;
-  *m = l;
+       root is the number of index bits for the root table.  When len exceeds
+       root, sub-tables are created pointed to by the root entry with an index
+       of the low root bits of huff.  This is saved in low to check for when a
+       new sub-table should be started.  drop is zero when the root table is
+       being filled, and drop is root when sub-tables are being filled.
 
+       When a new sub-table is needed, it is necessary to look ahead in the
+       code lengths to determine what size sub-table is needed.  The length
+       counts are used for this, and so count[] is decremented as codes are
+       entered in the tables.
 
-  /* Adjust last length count to fill out codes, if needed */
-  for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return Z_DATA_ERROR;
-  if ((y -= c[i]) < 0)
-    return Z_DATA_ERROR;
-  c[i] += y;
+       used keeps track of how many table entries have been allocated from the
+       provided *table space.  It is checked when a LENS table is being made
+       against the space in *table, ENOUGH, minus the maximum space needed by
+       the worst case distance code, MAXD.  This should never happen, but the
+       sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+       This assumes that when type == LENS, bits == 9.
 
+       sym increments through all symbols, and the loop terminates when
+       all codes of length max, i.e. all codes, have been processed.  This
+       routine permits incomplete codes, so another loop after this one fills
+       in the rest of the decoding tables with invalid code markers.
+     */
 
-  /* Generate starting offsets into the value table for each length */
-  x[1] = j = 0;
-  p = c + 1;  xp = x + 2;
-  while (--i) {                 /* note that i == g from above */
-    *xp++ = (j += *p++);
-  }
+    /* set up for code type */
+    switch (type) {
+    case CODES:
+        base = extra = work;    /* dummy value--not used */
+        end = 19;
+        break;
+    case LENS:
+        base = lbase;
+        base -= 257;
+        extra = lext;
+        extra -= 257;
+        end = 256;
+        break;
+    default:            /* DISTS */
+        base = dbase;
+        extra = dext;
+        end = -1;
+    }
 
+    /* initialize state for loop */
+    huff = 0;                   /* starting code */
+    sym = 0;                    /* starting code symbol */
+    len = min;                  /* starting code length */
+    next = *table;              /* current table to fill in */
+    curr = root;                /* current table index bits */
+    drop = 0;                   /* current bits to drop from code for index */
+    low = (unsigned)(-1);       /* trigger new sub-table when len > root */
+    used = 1U << root;          /* use root table entries */
+    mask = used - 1;            /* mask for comparing low */
 
-  /* Make a table of values in order of bit lengths */
-  p = b;  i = 0;
-  do {
-    if ((j = *p++) != 0)
-      v[x[j]++] = i;
-  } while (++i < n);
-  n = x[g];                     /* set n to length of v */
+    /* check available table space */
+    if (type == LENS && used >= ENOUGH - MAXD)
+        return 1;
 
-
-  /* Generate the Huffman codes and for each, make the table entries */
-  x[0] = i = 0;                 /* first Huffman code is zero */
-  p = v;                        /* grab values in bit order */
-  h = -1;                       /* no tables yet--level -1 */
-  w = -l;                       /* bits decoded == (l * h) */
-  u[0] = NULL;                  /* just to keep compilers happy */
-  q = NULL;                     /* ditto */
-  z = 0;                        /* ditto */
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-    a = c[k];
-    while (a--)
-    {
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = g - w;
-        z = z > (uInt)l ? l : z;        /* table size upper limit */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-          f -= a + 1;           /* deduct codes from patterns left */
-          xp = c + k;
-          if (j < z)
-            while (++j < z)     /* try smaller tables up to z bits */
-            {
-              if ((f <<= 1) <= *++xp)
-                break;          /* enough codes to use up j bits */
-              f -= *xp;         /* else deduct codes from patterns */
-            }
+    /* process all codes and make table entries */
+    for (;;) {
+        /* create table entry */
+        this.bits = (unsigned char)(len - drop);
+        if ((int)(work[sym]) < end) {
+            this.op = (unsigned char)0;
+            this.val = work[sym];
         }
-        z = 1 << j;             /* table entries for j-bit table */
+        else if ((int)(work[sym]) > end) {
+            this.op = (unsigned char)(extra[work[sym]]);
+            this.val = base[work[sym]];
+        }
+        else {
+            this.op = (unsigned char)(32 + 64);         /* end of block */
+            this.val = 0;
+        }
 
-        /* allocate new table */
-        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
-          return Z_DATA_ERROR;  /* overflow of MANY */
-        u[h] = q = hp + *hn;
-        *hn += z;
+        /* replicate for those indices with low len bits equal to huff */
+        incr = 1U << (len - drop);
+        fill = 1U << curr;
+        min = fill;                 /* save offset to next table */
+        do {
+            fill -= incr;
+            next[(huff >> drop) + fill] = this;
+        } while (fill != 0);
 
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.bits = (Byte)l;     /* bits to dump before this table */
-          r.exop = (Byte)j;     /* bits in this table */
-          j = i >> (w - l);
-          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
-          u[h-1][j] = r;        /* connect to last table */
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
         }
         else
-          *t = q;               /* first table is returned result */
-      }
+            huff = 0;
 
-      /* set up table entry in r */
-      r.bits = (Byte)(k - w);
-      if (p >= v + n)
-        r.exop = 128 + 64;      /* out of values--invalid code */
-      else if (*p < s)
-      {
-        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
-        r.base = *p++;          /* simple code is just the value */
-      }
-      else
-      {
-        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
-        r.base = d[*p++ - s];
-      }
+        /* go to next symbol, update count, len */
+        sym++;
+        if (--(count[len]) == 0) {
+            if (len == max) break;
+            len = lens[work[sym]];
+        }
 
-      /* fill code-like entries with r */
-      f = 1 << (k - w);
-      for (j = i >> w; j < z; j += f)
-        q[j] = r;
+        /* create new sub-table if needed */
+        if (len > root && (huff & mask) != low) {
+            /* if first time, transition to sub-tables */
+            if (drop == 0)
+                drop = root;
 
-      /* backwards increment the k-bit code i */
-      for (j = 1 << (k - 1); i & j; j >>= 1)
-        i ^= j;
-      i ^= j;
+            /* increment past last table */
+            next += min;            /* here min is 1 << curr */
 
-      /* backup over finished tables */
-      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
-      while ((i & mask) != x[h])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-        mask = (1 << w) - 1;
-      }
+            /* determine length of next table */
+            curr = len - drop;
+            left = (int)(1 << curr);
+            while (curr + drop < max) {
+                left -= count[curr + drop];
+                if (left <= 0) break;
+                curr++;
+                left <<= 1;
+            }
+
+            /* check for enough space */
+            used += 1U << curr;
+            if (type == LENS && used >= ENOUGH - MAXD)
+                return 1;
+
+            /* point entry in root table to sub-table */
+            low = huff & mask;
+            (*table)[low].op = (unsigned char)curr;
+            (*table)[low].bits = (unsigned char)root;
+            (*table)[low].val = (unsigned short)(next - *table);
+        }
     }
-  }
 
+    /*
+       Fill in rest of table for incomplete codes.  This loop is similar to the
+       loop above in incrementing huff for table indices.  It is assumed that
+       len is equal to curr + drop, so there is no loop needed to increment
+       through high index bits.  When the current sub-table is filled, the loop
+       drops back to the root table to fill in any remaining entries there.
+     */
+    this.op = (unsigned char)64;                /* invalid code marker */
+    this.bits = (unsigned char)(len - drop);
+    this.val = (unsigned short)0;
+    while (huff != 0) {
+        /* when done with sub-table, drop back to root table */
+        if (drop != 0 && (huff & mask) != low) {
+            drop = 0;
+            len = root;
+            next = *table;
+            this.bits = (unsigned char)len;
+        }
 
-  /* Return Z_BUF_ERROR if we were given an incomplete table */
-  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
+        /* put invalid code marker in table */
+        next[huff >> drop] = this;
 
-
-int zlib_inflate_trees_bits(
-	uInt *c,                /* 19 code lengths */
-	uInt *bb,               /* bits tree desired/actual depth */
-	inflate_huft **tb,      /* bits tree result */
-	inflate_huft *hp,       /* space for trees */
-	z_streamp z             /* for messages */
-)
-{
-  int r;
-  uInt hn = 0;          /* hufts used in space */
-  uInt *v;              /* work area for huft_build */
-  
-  v = WS(z)->tree_work_area_1;
-  r = huft_build(c, 19, 19, NULL, NULL, tb, bb, hp, &hn, v);
-  if (r == Z_DATA_ERROR)
-    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
-  else if (r == Z_BUF_ERROR || *bb == 0)
-  {
-    z->msg = (char*)"incomplete dynamic bit lengths tree";
-    r = Z_DATA_ERROR;
-  }
-  return r;
-}
-
-int zlib_inflate_trees_dynamic(
-	uInt nl,                /* number of literal/length codes */
-	uInt nd,                /* number of distance codes */
-	uInt *c,                /* that many (total) code lengths */
-	uInt *bl,               /* literal desired/actual bit depth */
-	uInt *bd,               /* distance desired/actual bit depth */
-	inflate_huft **tl,      /* literal/length tree result */
-	inflate_huft **td,      /* distance tree result */
-	inflate_huft *hp,       /* space for trees */
-	z_streamp z             /* for messages */
-)
-{
-  int r;
-  uInt hn = 0;          /* hufts used in space */
-  uInt *v;              /* work area for huft_build */
-
-  /* allocate work area */
-  v = WS(z)->tree_work_area_2;
-
-  /* build literal/length tree */
-  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
-  if (r != Z_OK || *bl == 0)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = (char*)"oversubscribed literal/length tree";
-    else if (r != Z_MEM_ERROR)
-    {
-      z->msg = (char*)"incomplete literal/length tree";
-      r = Z_DATA_ERROR;
+        /* backwards increment the len-bit code huff */
+        incr = 1U << (len - 1);
+        while (huff & incr)
+            incr >>= 1;
+        if (incr != 0) {
+            huff &= incr - 1;
+            huff += incr;
+        }
+        else
+            huff = 0;
     }
-    return r;
-  }
 
-  /* build distance tree */
-  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
-  if (r != Z_OK || (*bd == 0 && nl > 257))
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = (char*)"oversubscribed distance tree";
-    else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
-      r = Z_OK;
-    }
-#else
-      z->msg = (char*)"incomplete distance tree";
-      r = Z_DATA_ERROR;
-    }
-    else if (r != Z_MEM_ERROR)
-    {
-      z->msg = (char*)"empty distance tree with lengths";
-      r = Z_DATA_ERROR;
-    }
-    return r;
-#endif
-  }
-
-  /* done */
-  return Z_OK;
-}
-
-
-int zlib_inflate_trees_fixed(
-	uInt *bl,                /* literal desired/actual bit depth */
-	uInt *bd,                /* distance desired/actual bit depth */
-	inflate_huft **tl,       /* literal/length tree result */
-	inflate_huft **td,       /* distance tree result */
-	inflate_huft *hp,       /* space for trees */
-	z_streamp z              /* for memory allocation */
-)
-{
-  int i;                /* temporary variable */
-  unsigned l[288];      /* length list for huft_build */
-  uInt *v;              /* work area for huft_build */
-
-  /* set up literal table */
-  for (i = 0; i < 144; i++)
-    l[i] = 8;
-  for (; i < 256; i++)
-    l[i] = 9;
-  for (; i < 280; i++)
-    l[i] = 7;
-  for (; i < 288; i++)          /* make a complete, but wrong code set */
-    l[i] = 8;
-  *bl = 9;
-  v = WS(z)->tree_work_area_1;
-  if ((i = huft_build(l, 288, 257, cplens, cplext, tl, bl, hp,  &i, v)) != 0)
-    return i;
-
-  /* set up distance table */
-  for (i = 0; i < 30; i++)      /* make an incomplete code set */
-    l[i] = 5;
-  *bd = 5;
-  if ((i = huft_build(l, 30, 0, cpdist, cpdext, td, bd, hp, &i, v)) > 1)
-    return i;
-
-  return Z_OK;
+    /* set return parameters */
+    *table += used;
+    *bits = root;
+    return 0;
 }
diff --git a/lib/zlib_inflate/inftrees.h b/lib/zlib_inflate/inftrees.h
index e37705a..5f5219b 100644
--- a/lib/zlib_inflate/inftrees.h
+++ b/lib/zlib_inflate/inftrees.h
@@ -1,6 +1,6 @@
 /* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
 /* WARNING: this file should *not* be used by applications. It is
@@ -8,57 +8,48 @@
    subject to change. Applications should only use zlib.h.
  */
 
-/* Huffman code lookup table entry--this entry is four bytes for machines
-   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+/* Structure for decoding tables.  Each entry provides either the
+   information needed to do the operation requested by the code that
+   indexed that table entry, or it provides a pointer to another
+   table that indexes more bits of the code.  op indicates whether
+   the entry is a pointer to another table, a literal, a length or
+   distance, an end-of-block, or an invalid code.  For a table
+   pointer, the low four bits of op is the number of index bits of
+   that table.  For a length or distance, the low four bits of op
+   is the number of extra bits to get after the code.  bits is
+   the number of bits in this code or part of the code to drop off
+   of the bit buffer.  val is the actual byte to output in the case
+   of a literal, the base length or distance, or the offset from
+   the current table to the next table.  Each entry is four bytes. */
+typedef struct {
+    unsigned char op;           /* operation, extra bits, table bits */
+    unsigned char bits;         /* bits in this part of the code */
+    unsigned short val;         /* offset in table or code value */
+} code;
 
-#ifndef _INFTREES_H
-#define _INFTREES_H
-
-typedef struct inflate_huft_s inflate_huft;
-
-struct inflate_huft_s {
-  union {
-    struct {
-      Byte Exop;        /* number of extra bits or operation */
-      Byte Bits;        /* number of bits in this code or subcode */
-    } what;
-    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
-  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
-  uInt base;            /* literal, length base, distance base,
-                           or table offset */
-};
+/* op values as set by inflate_table():
+    00000000 - literal
+    0000tttt - table link, tttt != 0 is the number of table index bits
+    0001eeee - length or distance, eeee is the number of extra bits
+    01100000 - end of block
+    01000000 - invalid code
+ */
 
 /* Maximum size of dynamic tree.  The maximum found in a long but non-
-   exhaustive search was 1004 huft structures (850 for length/literals
-   and 154 for distances, the latter actually the result of an
-   exhaustive search).  The actual maximum is not known, but the
-   value below is more than safe. */
-#define MANY 1440
+   exhaustive search was 1444 code structures (852 for length/literals
+   and 592 for distances, the latter actually the result of an
+   exhaustive search).  The true maximum is not known, but the value
+   below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
 
-extern int zlib_inflate_trees_bits (
-    uInt *,                     /* 19 code lengths */
-    uInt *,                     /* bits tree desired/actual depth */
-    inflate_huft **,            /* bits tree result */
-    inflate_huft *,             /* space for trees */
-    z_streamp);                 /* for messages */
+/* Type of code to build for inftable() */
+typedef enum {
+    CODES,
+    LENS,
+    DISTS
+} codetype;
 
-extern int zlib_inflate_trees_dynamic (
-    uInt,                       /* number of literal/length codes */
-    uInt,                       /* number of distance codes */
-    uInt *,                     /* that many (total) code lengths */
-    uInt *,                     /* literal desired/actual bit depth */
-    uInt *,                     /* distance desired/actual bit depth */
-    inflate_huft **,            /* literal/length tree result */
-    inflate_huft **,            /* distance tree result */
-    inflate_huft *,             /* space for trees */
-    z_streamp);                 /* for messages */
-
-extern int zlib_inflate_trees_fixed (
-    uInt *,                     /* literal desired/actual bit depth */
-    uInt *,                     /* distance desired/actual bit depth */
-    inflate_huft **,            /* literal/length tree result */
-    inflate_huft **,            /* distance tree result */
-    inflate_huft *,             /* space for trees */
-    z_streamp);                 /* for memory allocation */
-
-#endif /* _INFTREES_H */
+extern int zlib_inflate_table (codetype type, unsigned short *lens,
+                             unsigned codes, code **table,
+                             unsigned *bits, unsigned short *work);
diff --git a/lib/zlib_inflate/infutil.c b/lib/zlib_inflate/infutil.c
deleted file mode 100644
index 00202b3..0000000
--- a/lib/zlib_inflate/infutil.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#include <linux/zutil.h>
-#include "infblock.h"
-#include "inftrees.h"
-#include "infcodes.h"
-#include "infutil.h"
-
-struct inflate_codes_state;
-
-/* And'ing with mask[n] masks the lower n bits */
-uInt zlib_inflate_mask[17] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-
-/* copy as much as possible from the sliding window to the output area */
-int zlib_inflate_flush(
-	inflate_blocks_statef *s,
-	z_streamp z,
-	int r
-)
-{
-  uInt n;
-  Byte *p;
-  Byte *q;
-
-  /* local copies of source and destination pointers */
-  p = z->next_out;
-  q = s->read;
-
-  /* compute number of bytes to copy as far as end of window */
-  n = (uInt)((q <= s->write ? s->write : s->end) - q);
-  if (n > z->avail_out) n = z->avail_out;
-  if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-  /* update counters */
-  z->avail_out -= n;
-  z->total_out += n;
-
-  /* update check information */
-  if (s->checkfn != NULL)
-    z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
-  /* copy as far as end of window */
-  memcpy(p, q, n);
-  p += n;
-  q += n;
-
-  /* see if more to copy at beginning of window */
-  if (q == s->end)
-  {
-    /* wrap pointers */
-    q = s->window;
-    if (s->write == s->end)
-      s->write = s->window;
-
-    /* compute bytes to copy */
-    n = (uInt)(s->write - q);
-    if (n > z->avail_out) n = z->avail_out;
-    if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-    /* update counters */
-    z->avail_out -= n;
-    z->total_out += n;
-
-    /* update check information */
-    if (s->checkfn != NULL)
-      z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
-    /* copy */
-    memcpy(p, q, n);
-    p += n;
-    q += n;
-  }
-
-  /* update pointers */
-  z->next_out = p;
-  s->read = q;
-
-  /* done */
-  return r;
-}
diff --git a/lib/zlib_inflate/infutil.h b/lib/zlib_inflate/infutil.h
index a15875f..eb1a900 100644
--- a/lib/zlib_inflate/infutil.h
+++ b/lib/zlib_inflate/infutil.h
@@ -11,184 +11,12 @@
 #ifndef _INFUTIL_H
 #define _INFUTIL_H
 
-#include <linux/zconf.h>
-#include "inftrees.h"
-#include "infcodes.h"
-
-typedef enum {
-      TYPE,     /* get type bits (3, including end bit) */
-      LENS,     /* get lengths for stored */
-      STORED,   /* processing stored block */
-      TABLE,    /* get table lengths */
-      BTREE,    /* get bit lengths tree for a dynamic block */
-      DTREE,    /* get length, distance trees for a dynamic block */
-      CODES,    /* processing fixed or dynamic block */
-      DRY,      /* output remaining window bytes */
-      B_DONE,   /* finished last block, done */
-      B_BAD}    /* got a data error--stuck here */
-inflate_block_mode;
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
-  /* mode */
-  inflate_block_mode  mode;     /* current inflate_block mode */
-
-  /* mode dependent information */
-  union {
-    uInt left;          /* if STORED, bytes left to copy */
-    struct {
-      uInt table;               /* table lengths (14 bits) */
-      uInt index;               /* index into blens (or border) */
-      uInt *blens;              /* bit lengths of codes */
-      uInt bb;                  /* bit length tree depth */
-      inflate_huft *tb;         /* bit length decoding tree */
-    } trees;            /* if DTREE, decoding info for trees */
-    struct {
-      inflate_codes_statef 
-         *codes;
-    } decode;           /* if CODES, current state */
-  } sub;                /* submode */
-  uInt last;            /* true if this block is the last block */
-
-  /* mode independent information */
-  uInt bitk;            /* bits in bit buffer */
-  uLong bitb;           /* bit buffer */
-  inflate_huft *hufts;  /* single malloc for tree space */
-  Byte *window;         /* sliding window */
-  Byte *end;            /* one byte after sliding window */
-  Byte *read;           /* window read pointer */
-  Byte *write;          /* window write pointer */
-  check_func checkfn;   /* check function */
-  uLong check;          /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/*   update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return zlib_inflate_flush(s,z,r);}
-/*   get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/*   output bytes */
-#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
-#define FLUSH {UPDOUT r=zlib_inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/*   load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
-extern uInt zlib_inflate_mask[17];
-
-/* copy as much as possible from the sliding window to the output area */
-extern int zlib_inflate_flush (
-    inflate_blocks_statef *,
-    z_streamp ,
-    int);
-
-/* inflate private state */
-typedef enum {
-      METHOD,   /* waiting for method byte */
-      FLAG,     /* waiting for flag byte */
-      DICT4,    /* four dictionary check bytes to go */
-      DICT3,    /* three dictionary check bytes to go */
-      DICT2,    /* two dictionary check bytes to go */
-      DICT1,    /* one dictionary check byte to go */
-      DICT0,    /* waiting for inflateSetDictionary */
-      BLOCKS,   /* decompressing blocks */
-      CHECK4,   /* four check bytes to go */
-      CHECK3,   /* three check bytes to go */
-      CHECK2,   /* two check bytes to go */
-      CHECK1,   /* one check byte to go */
-      I_DONE,   /* finished check, done */
-      I_BAD}    /* got an error--stay here */
-inflate_mode;
-
-struct internal_state {
-
-  /* mode */
-  inflate_mode  mode;   /* current inflate mode */
-
-  /* mode dependent information */
-  union {
-    uInt method;        /* if FLAGS, method byte */
-    struct {
-      uLong was;                /* computed check value */
-      uLong need;               /* stream check value */
-    } check;            /* if CHECK, check values to compare */
-    uInt marker;        /* if BAD, inflateSync's marker bytes count */
-  } sub;        /* submode */
-
-  /* mode independent information */
-  int  nowrap;          /* flag for no wrapper */
-  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
-  inflate_blocks_statef 
-    *blocks;            /* current inflate_blocks state */
-
-};
-
-/* inflate codes private state */
-typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-      START,    /* x: set up for LEN */
-      LEN,      /* i: get length/literal/eob next */
-      LENEXT,   /* i: getting length extra (have base) */
-      DIST,     /* i: get distance next */
-      DISTEXT,  /* i: getting distance extra */
-      COPY,     /* o: copying bytes in window, waiting for space */
-      LIT,      /* o: got literal, waiting for output space */
-      WASH,     /* o: got eob, possibly still output waiting */
-      END,      /* x: got eob and all data flushed */
-      BADCODE}  /* x: got error */
-inflate_codes_mode;
-
-struct inflate_codes_state {
-
-  /* mode */
-  inflate_codes_mode mode;      /* current inflate_codes mode */
-
-  /* mode dependent information */
-  uInt len;
-  union {
-    struct {
-      inflate_huft *tree;       /* pointer into tree */
-      uInt need;                /* bits needed */
-    } code;             /* if LEN or DIST, where in tree */
-    uInt lit;           /* if LIT, literal */
-    struct {
-      uInt get;                 /* bits to get for extra */
-      uInt dist;                /* distance back to copy from */
-    } copy;             /* if EXT or COPY, where and how much */
-  } sub;                /* submode */
-
-  /* mode independent information */
-  Byte lbits;           /* ltree bits decoded per branch */
-  Byte dbits;           /* dtree bits decoder per branch */
-  inflate_huft *ltree;          /* literal/length/eob tree */
-  inflate_huft *dtree;          /* distance tree */
-
-};
+#include <linux/zlib.h>
 
 /* memory allocation for inflation */
 
 struct inflate_workspace {
-	inflate_codes_statef working_state;
-	struct inflate_blocks_state working_blocks_state;
-	struct internal_state internal_state;
-	unsigned int tree_work_area_1[19];
-	unsigned int tree_work_area_2[288];
-	unsigned working_blens[258 + 0x1f + 0x1f];
-	inflate_huft working_hufts[MANY];
+	struct inflate_state inflate_state;
 	unsigned char working_window[1 << MAX_WBITS];
 };
 
diff --git a/mm/Kconfig b/mm/Kconfig
index 332f5c2..e76c023 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -116,6 +116,7 @@
 config MEMORY_HOTPLUG
 	bool "Allow for memory hot-add"
 	depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND
+	depends on (IA64 || X86 || PPC64)
 
 comment "Memory hotplug is currently incompatible with Software Suspend"
 	depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
@@ -138,8 +139,8 @@
 #
 config MIGRATION
 	bool "Page migration"
-	def_bool y if NUMA
-	depends on SWAP && NUMA
+	def_bool y
+	depends on NUMA
 	help
 	  Allows the migration of the physical location of pages of processes
 	  while the virtual addresses are not changed. This is useful for
diff --git a/mm/filemap.c b/mm/filemap.c
index fd57442..4082b3b 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/compiler.h>
 #include <linux/fs.h>
+#include <linux/uaccess.h>
 #include <linux/aio.h>
 #include <linux/capability.h>
 #include <linux/kernel_stat.h>
@@ -38,7 +39,6 @@
  */
 #include <linux/buffer_head.h> /* for generic_osync_inode */
 
-#include <asm/uaccess.h>
 #include <asm/mman.h>
 
 static ssize_t
@@ -171,15 +171,17 @@
 }
 
 /**
- * filemap_fdatawrite_range - start writeback against all of a mapping's
- * dirty pages that lie within the byte offsets <start, end>
+ * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
  * @mapping:	address space structure to write
  * @start:	offset in bytes where the range starts
  * @end:	offset in bytes where the range ends (inclusive)
  * @sync_mode:	enable synchronous operation
  *
+ * Start writeback against all of a mapping's dirty pages that lie
+ * within the byte offsets <start, end> inclusive.
+ *
  * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as
- * opposed to a regular memory * cleansing writeback.  The difference between
+ * opposed to a regular memory cleansing writeback.  The difference between
  * these two operations is that if a dirty page/buffer is encountered, it must
  * be waited upon, and not just skipped over.
  */
@@ -190,8 +192,8 @@
 	struct writeback_control wbc = {
 		.sync_mode = sync_mode,
 		.nr_to_write = mapping->nrpages * 2,
-		.start = start,
-		.end = end,
+		.range_start = start,
+		.range_end = end,
 	};
 
 	if (!mapping_cap_writeback_dirty(mapping))
@@ -204,7 +206,7 @@
 static inline int __filemap_fdatawrite(struct address_space *mapping,
 	int sync_mode)
 {
-	return __filemap_fdatawrite_range(mapping, 0, 0, sync_mode);
+	return __filemap_fdatawrite_range(mapping, 0, LLONG_MAX, sync_mode);
 }
 
 int filemap_fdatawrite(struct address_space *mapping)
@@ -219,7 +221,10 @@
 	return __filemap_fdatawrite_range(mapping, start, end, WB_SYNC_ALL);
 }
 
-/*
+/**
+ * filemap_flush - mostly a non-blocking flush
+ * @mapping:	target address_space
+ *
  * This is a mostly non-blocking flush.  Not suitable for data-integrity
  * purposes - I/O may not be started against all dirty pages.
  */
@@ -229,7 +234,12 @@
 }
 EXPORT_SYMBOL(filemap_flush);
 
-/*
+/**
+ * wait_on_page_writeback_range - wait for writeback to complete
+ * @mapping:	target address_space
+ * @start:	beginning page index
+ * @end:	ending page index
+ *
  * Wait for writeback to complete against pages indexed by start->end
  * inclusive
  */
@@ -276,7 +286,13 @@
 	return ret;
 }
 
-/*
+/**
+ * sync_page_range - write and wait on all pages in the passed range
+ * @inode:	target inode
+ * @mapping:	target address_space
+ * @pos:	beginning offset in pages to write
+ * @count:	number of bytes to write
+ *
  * Write and wait upon all the pages in the passed range.  This is a "data
  * integrity" operation.  It waits upon in-flight writeout before starting and
  * waiting upon new writeout.  If there was an IO error, return it.
@@ -305,7 +321,13 @@
 }
 EXPORT_SYMBOL(sync_page_range);
 
-/*
+/**
+ * sync_page_range_nolock
+ * @inode:	target inode
+ * @mapping:	target address_space
+ * @pos:	beginning offset in pages to write
+ * @count:	number of bytes to write
+ *
  * Note: Holding i_mutex across sync_page_range_nolock is not a good idea
  * as it forces O_SYNC writers to different parts of the same file
  * to be serialised right until io completion.
@@ -329,10 +351,11 @@
 EXPORT_SYMBOL(sync_page_range_nolock);
 
 /**
- * filemap_fdatawait - walk the list of under-writeback pages of the given
- *     address space and wait for all of them.
- *
+ * filemap_fdatawait - wait for all under-writeback pages to complete
  * @mapping: address space structure to wait for
+ *
+ * Walk the list of under-writeback pages of the given address space
+ * and wait for all of them.
  */
 int filemap_fdatawait(struct address_space *mapping)
 {
@@ -368,7 +391,12 @@
 }
 EXPORT_SYMBOL(filemap_write_and_wait);
 
-/*
+/**
+ * filemap_write_and_wait_range - write out & wait on a file range
+ * @mapping:	the address_space for the pages
+ * @lstart:	offset in bytes where the range starts
+ * @lend:	offset in bytes where the range ends (inclusive)
+ *
  * Write out and wait upon file offsets lstart->lend, inclusive.
  *
  * Note that `lend' is inclusive (describes the last byte to be written) so
@@ -394,8 +422,14 @@
 	return err;
 }
 
-/*
- * This function is used to add newly allocated pagecache pages:
+/**
+ * add_to_page_cache - add newly allocated pagecache pages
+ * @page:	page to add
+ * @mapping:	the page's address_space
+ * @offset:	page index
+ * @gfp_mask:	page allocation mode
+ *
+ * This function is used to add newly allocated pagecache pages;
  * the page is new, so we can just run SetPageLocked() against it.
  * The other page state flags were set by rmqueue().
  *
@@ -422,7 +456,6 @@
 	}
 	return error;
 }
-
 EXPORT_SYMBOL(add_to_page_cache);
 
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
@@ -489,8 +522,7 @@
 EXPORT_SYMBOL(wait_on_page_bit);
 
 /**
- * unlock_page() - unlock a locked page
- *
+ * unlock_page - unlock a locked page
  * @page: the page
  *
  * Unlocks the page and wakes up sleepers in ___wait_on_page_locked().
@@ -513,8 +545,9 @@
 }
 EXPORT_SYMBOL(unlock_page);
 
-/*
- * End writeback against a page.
+/**
+ * end_page_writeback - end writeback against a page
+ * @page: the page
  */
 void end_page_writeback(struct page *page)
 {
@@ -527,10 +560,11 @@
 }
 EXPORT_SYMBOL(end_page_writeback);
 
-/*
- * Get a lock on the page, assuming we need to sleep to get it.
+/**
+ * __lock_page - get a lock on the page, assuming we need to sleep to get it
+ * @page: the page to lock
  *
- * Ugly: running sync_page() in state TASK_UNINTERRUPTIBLE is scary.  If some
+ * Ugly. Running sync_page() in state TASK_UNINTERRUPTIBLE is scary.  If some
  * random driver's requestfn sets TASK_RUNNING, we could busywait.  However
  * chances are that on the second loop, the block layer's plug list is empty,
  * so sync_page() will then return in state TASK_UNINTERRUPTIBLE.
@@ -544,8 +578,12 @@
 }
 EXPORT_SYMBOL(__lock_page);
 
-/*
- * a rather lightweight function, finding and getting a reference to a
+/**
+ * find_get_page - find and get a page reference
+ * @mapping: the address_space to search
+ * @offset: the page index
+ *
+ * A rather lightweight function, finding and getting a reference to a
  * hashed page atomically.
  */
 struct page * find_get_page(struct address_space *mapping, unsigned long offset)
@@ -559,11 +597,14 @@
 	read_unlock_irq(&mapping->tree_lock);
 	return page;
 }
-
 EXPORT_SYMBOL(find_get_page);
 
-/*
- * Same as above, but trylock it instead of incrementing the count.
+/**
+ * find_trylock_page - find and lock a page
+ * @mapping: the address_space to search
+ * @offset: the page index
+ *
+ * Same as find_get_page(), but trylock it instead of incrementing the count.
  */
 struct page *find_trylock_page(struct address_space *mapping, unsigned long offset)
 {
@@ -576,12 +617,10 @@
 	read_unlock_irq(&mapping->tree_lock);
 	return page;
 }
-
 EXPORT_SYMBOL(find_trylock_page);
 
 /**
  * find_lock_page - locate, pin and lock a pagecache page
- *
  * @mapping: the address_space to search
  * @offset: the page index
  *
@@ -617,12 +656,10 @@
 	read_unlock_irq(&mapping->tree_lock);
 	return page;
 }
-
 EXPORT_SYMBOL(find_lock_page);
 
 /**
  * find_or_create_page - locate or add a pagecache page
- *
  * @mapping: the page's address_space
  * @index: the page's index into the mapping
  * @gfp_mask: page allocation mode
@@ -663,7 +700,6 @@
 		page_cache_release(cached_page);
 	return page;
 }
-
 EXPORT_SYMBOL(find_or_create_page);
 
 /**
@@ -729,9 +765,16 @@
 	return i;
 }
 
-/*
+/**
+ * find_get_pages_tag - find and return pages that match @tag
+ * @mapping:	the address_space to search
+ * @index:	the starting page index
+ * @tag:	the tag index
+ * @nr_pages:	the maximum number of pages
+ * @pages:	where the resulting pages are placed
+ *
  * Like find_get_pages, except we only return pages which are tagged with
- * `tag'.   We update *index to index the next page for the traversal.
+ * @tag.   We update @index to index the next page for the traversal.
  */
 unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index,
 			int tag, unsigned int nr_pages, struct page **pages)
@@ -750,7 +793,11 @@
 	return ret;
 }
 
-/*
+/**
+ * grab_cache_page_nowait - returns locked page at given index in given cache
+ * @mapping: target address_space
+ * @index: the page index
+ *
  * Same as grab_cache_page, but do not wait if the page is unavailable.
  * This is intended for speculative data generators, where the data can
  * be regenerated if the page couldn't be grabbed.  This routine should
@@ -779,19 +826,51 @@
 	}
 	return page;
 }
-
 EXPORT_SYMBOL(grab_cache_page_nowait);
 
 /*
+ * CD/DVDs are error prone. When a medium error occurs, the driver may fail
+ * a _large_ part of the i/o request. Imagine the worst scenario:
+ *
+ *      ---R__________________________________________B__________
+ *         ^ reading here                             ^ bad block(assume 4k)
+ *
+ * read(R) => miss => readahead(R...B) => media error => frustrating retries
+ * => failing the whole request => read(R) => read(R+1) =>
+ * readahead(R+1...B+1) => bang => read(R+2) => read(R+3) =>
+ * readahead(R+3...B+2) => bang => read(R+3) => read(R+4) =>
+ * readahead(R+4...B+3) => bang => read(R+4) => read(R+5) => ......
+ *
+ * It is going insane. Fix it by quickly scaling down the readahead size.
+ */
+static void shrink_readahead_size_eio(struct file *filp,
+					struct file_ra_state *ra)
+{
+	if (!ra->ra_pages)
+		return;
+
+	ra->ra_pages /= 4;
+	printk(KERN_WARNING "Reducing readahead size to %luK\n",
+			ra->ra_pages << (PAGE_CACHE_SHIFT - 10));
+}
+
+/**
+ * do_generic_mapping_read - generic file read routine
+ * @mapping:	address_space to be read
+ * @_ra:	file's readahead state
+ * @filp:	the file to read
+ * @ppos:	current file position
+ * @desc:	read_descriptor
+ * @actor:	read method
+ *
  * This is a generic file read routine, and uses the
- * mapping->a_ops->readpage() function for the actual low-level
- * stuff.
+ * mapping->a_ops->readpage() function for the actual low-level stuff.
  *
  * This is really ugly. But the goto's actually try to clarify some
  * of the logic when it comes to error handling etc.
  *
- * Note the struct file* is only passed for the use of readpage.  It may be
- * NULL.
+ * Note the struct file* is only passed for the use of readpage.
+ * It may be NULL.
  */
 void do_generic_mapping_read(struct address_space *mapping,
 			     struct file_ra_state *_ra,
@@ -932,6 +1011,7 @@
 				}
 				unlock_page(page);
 				error = -EIO;
+				shrink_readahead_size_eio(filp, &ra);
 				goto readpage_error;
 			}
 			unlock_page(page);
@@ -1004,7 +1084,6 @@
 	if (filp)
 		file_accessed(filp);
 }
-
 EXPORT_SYMBOL(do_generic_mapping_read);
 
 int file_read_actor(read_descriptor_t *desc, struct page *page,
@@ -1045,7 +1124,13 @@
 	return size;
 }
 
-/*
+/**
+ * __generic_file_aio_read - generic filesystem read routine
+ * @iocb:	kernel I/O control block
+ * @iov:	io vector request
+ * @nr_segs:	number of segments in the iovec
+ * @ppos:	current file position
+ *
  * This is the "read()" routine for all filesystems
  * that can use the page cache directly.
  */
@@ -1124,7 +1209,6 @@
 out:
 	return retval;
 }
-
 EXPORT_SYMBOL(__generic_file_aio_read);
 
 ssize_t
@@ -1135,7 +1219,6 @@
 	BUG_ON(iocb->ki_pos != pos);
 	return __generic_file_aio_read(iocb, &local_iov, 1, &iocb->ki_pos);
 }
-
 EXPORT_SYMBOL(generic_file_aio_read);
 
 ssize_t
@@ -1151,7 +1234,6 @@
 		ret = wait_on_sync_kiocb(&kiocb);
 	return ret;
 }
-
 EXPORT_SYMBOL(generic_file_read);
 
 int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
@@ -1192,7 +1274,6 @@
 		return desc.written;
 	return desc.error;
 }
-
 EXPORT_SYMBOL(generic_file_sendfile);
 
 static ssize_t
@@ -1228,11 +1309,15 @@
 }
 
 #ifdef CONFIG_MMU
-/*
+static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
+/**
+ * page_cache_read - adds requested page to the page cache if not already there
+ * @file:	file to read
+ * @offset:	page index
+ *
  * This adds the requested page to the page cache if it isn't already there,
  * and schedules an I/O to read in its contents from disk.
  */
-static int FASTCALL(page_cache_read(struct file * file, unsigned long offset));
 static int fastcall page_cache_read(struct file * file, unsigned long offset)
 {
 	struct address_space *mapping = file->f_mapping;
@@ -1259,7 +1344,12 @@
 
 #define MMAP_LOTSAMISS  (100)
 
-/*
+/**
+ * filemap_nopage - read in file data for page fault handling
+ * @area:	the applicable vm_area
+ * @address:	target address to read in
+ * @type:	returned with VM_FAULT_{MINOR,MAJOR} if not %NULL
+ *
  * filemap_nopage() is invoked via the vma operations vector for a
  * mapped memory region to read in file data during a page fault.
  *
@@ -1459,10 +1549,10 @@
 	 * Things didn't work out. Return zero to tell the
 	 * mm layer so, possibly freeing the page cache page first.
 	 */
+	shrink_readahead_size_eio(file, ra);
 	page_cache_release(page);
 	return NULL;
 }
-
 EXPORT_SYMBOL(filemap_nopage);
 
 static struct page * filemap_getpage(struct file *file, unsigned long pgoff,
@@ -1716,7 +1806,13 @@
 	return page;
 }
 
-/*
+/**
+ * read_cache_page - read into page cache, fill it if needed
+ * @mapping:	the page's address_space
+ * @index:	the page index
+ * @filler:	function to perform the read
+ * @data:	destination for read data
+ *
  * Read into the page cache. If a page already exists,
  * and PageUptodate() is not set, try to fill the page.
  */
@@ -1754,7 +1850,6 @@
  out:
 	return page;
 }
-
 EXPORT_SYMBOL(read_cache_page);
 
 /*
@@ -1825,7 +1920,7 @@
 EXPORT_SYMBOL(remove_suid);
 
 size_t
-__filemap_copy_from_user_iovec(char *vaddr, 
+__filemap_copy_from_user_iovec_inatomic(char *vaddr,
 			const struct iovec *iov, size_t base, size_t bytes)
 {
 	size_t copied = 0, left = 0;
@@ -1835,18 +1930,14 @@
 		int copy = min(bytes, iov->iov_len - base);
 
 		base = 0;
-		left = __copy_from_user_inatomic(vaddr, buf, copy);
+		left = __copy_from_user_inatomic_nocache(vaddr, buf, copy);
 		copied += copy;
 		bytes -= copy;
 		vaddr += copy;
 		iov++;
 
-		if (unlikely(left)) {
-			/* zero the rest of the target like __copy_from_user */
-			if (bytes)
-				memset(vaddr, 0, bytes);
+		if (unlikely(left))
 			break;
-		}
 	}
 	return copied - left;
 }
@@ -1854,7 +1945,7 @@
 /*
  * Performs necessary checks before doing a write
  *
- * Can adjust writing position aor amount of bytes to write.
+ * Can adjust writing position or amount of bytes to write.
  * Returns appropriate error code that caller should return or
  * zero in case that write should be allowed.
  */
@@ -1978,7 +2069,7 @@
 {
 	struct file *file = iocb->ki_filp;
 	struct address_space * mapping = file->f_mapping;
-	struct address_space_operations *a_ops = mapping->a_ops;
+	const struct address_space_operations *a_ops = mapping->a_ops;
 	struct inode 	*inode = mapping->host;
 	long		status = 0;
 	struct page	*page;
@@ -2004,14 +2095,21 @@
 	do {
 		unsigned long index;
 		unsigned long offset;
-		unsigned long maxlen;
 		size_t copied;
 
 		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
 		index = pos >> PAGE_CACHE_SHIFT;
 		bytes = PAGE_CACHE_SIZE - offset;
-		if (bytes > count)
-			bytes = count;
+
+		/* Limit the size of the copy to the caller's write size */
+		bytes = min(bytes, count);
+
+		/*
+		 * Limit the size of the copy to that of the current segment,
+		 * because fault_in_pages_readable() doesn't know how to walk
+		 * segments.
+		 */
+		bytes = min(bytes, cur_iov->iov_len - iov_base);
 
 		/*
 		 * Bring in the user page that we will copy from _first_.
@@ -2019,10 +2117,7 @@
 		 * same page as we're writing to, without it being marked
 		 * up-to-date.
 		 */
-		maxlen = cur_iov->iov_len - iov_base;
-		if (maxlen > bytes)
-			maxlen = bytes;
-		fault_in_pages_readable(buf, maxlen);
+		fault_in_pages_readable(buf, bytes);
 
 		page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
 		if (!page) {
@@ -2124,7 +2219,7 @@
 				unsigned long nr_segs, loff_t *ppos)
 {
 	struct file *file = iocb->ki_filp;
-	struct address_space * mapping = file->f_mapping;
+	const struct address_space * mapping = file->f_mapping;
 	size_t ocount;		/* original count */
 	size_t count;		/* after file limit checks */
 	struct inode 	*inode = mapping->host;
diff --git a/mm/filemap.h b/mm/filemap.h
index 13793ba..536979f 100644
--- a/mm/filemap.h
+++ b/mm/filemap.h
@@ -13,18 +13,26 @@
 #include <linux/highmem.h>
 #include <linux/uio.h>
 #include <linux/config.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 size_t
-__filemap_copy_from_user_iovec(char *vaddr,
-			       const struct iovec *iov,
-			       size_t base,
-			       size_t bytes);
+__filemap_copy_from_user_iovec_inatomic(char *vaddr,
+					const struct iovec *iov,
+					size_t base,
+					size_t bytes);
 
 /*
  * Copy as much as we can into the page and return the number of bytes which
  * were sucessfully copied.  If a fault is encountered then clear the page
  * out to (offset+bytes) and return the number of bytes which were copied.
+ *
+ * NOTE: For this to work reliably we really want copy_from_user_inatomic_nocache
+ * to *NOT* zero any tail of the buffer that it failed to copy.  If it does,
+ * and if the following non-atomic copy succeeds, then there is a small window
+ * where the target page contains neither the data before the write, nor the
+ * data after the write (it contains zero).  A read at this time will see
+ * data that is inconsistent with any ordering of the read and the write.
+ * (This has been detected in practice).
  */
 static inline size_t
 filemap_copy_from_user(struct page *page, unsigned long offset,
@@ -34,13 +42,13 @@
 	int left;
 
 	kaddr = kmap_atomic(page, KM_USER0);
-	left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
+	left = __copy_from_user_inatomic_nocache(kaddr + offset, buf, bytes);
 	kunmap_atomic(kaddr, KM_USER0);
 
 	if (left != 0) {
 		/* Do it the slow way */
 		kaddr = kmap(page);
-		left = __copy_from_user(kaddr + offset, buf, bytes);
+		left = __copy_from_user_nocache(kaddr + offset, buf, bytes);
 		kunmap(page);
 	}
 	return bytes - left;
@@ -60,13 +68,15 @@
 	size_t copied;
 
 	kaddr = kmap_atomic(page, KM_USER0);
-	copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
-						base, bytes);
+	copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
+							 base, bytes);
 	kunmap_atomic(kaddr, KM_USER0);
 	if (copied != bytes) {
 		kaddr = kmap(page);
-		copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
-							base, bytes);
+		copied = __filemap_copy_from_user_iovec_inatomic(kaddr + offset, iov,
+								 base, bytes);
+		if (bytes - copied)
+			memset(kaddr + offset + copied, 0, bytes - copied);
 		kunmap(page);
 	}
 	return copied;
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index b960ac8..b4fd0d7 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -273,7 +273,7 @@
 		  size_t count, loff_t pos, loff_t *ppos)
 {
 	struct address_space * mapping = filp->f_mapping;
-	struct address_space_operations *a_ops = mapping->a_ops;
+	const struct address_space_operations *a_ops = mapping->a_ops;
 	struct inode 	*inode = mapping->host;
 	long		status = 0;
 	struct page	*page;
diff --git a/mm/fremap.c b/mm/fremap.c
index 9f381e58..21b7d0c 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -83,6 +83,7 @@
 	page_add_file_rmap(page);
 	pte_val = *pte;
 	update_mmu_cache(vma, addr, pte_val);
+	lazy_mmu_prot_update(pte_val);
 	err = 0;
 unlock:
 	pte_unmap_unlock(pte, ptl);
@@ -114,7 +115,13 @@
 
 	set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff));
 	pte_val = *pte;
-	update_mmu_cache(vma, addr, pte_val);
+	/*
+	 * We don't need to run update_mmu_cache() here because the "file pte"
+	 * being installed by install_file_pte() is not a real pte - it's a
+	 * non-present entry (like a swap entry), noting what file offset should
+	 * be mapped there when there's a fault (in a non-linear vma where
+	 * that's not obvious).
+	 */
 	pte_unmap_unlock(pte, ptl);
 	err = 0;
 out:
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 832f676..df49997 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -22,7 +22,7 @@
 #include "internal.h"
 
 const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
-static unsigned long nr_huge_pages, free_huge_pages, reserved_huge_pages;
+static unsigned long nr_huge_pages, free_huge_pages, resv_huge_pages;
 unsigned long max_huge_pages;
 static struct list_head hugepage_freelists[MAX_NUMNODES];
 static unsigned int nr_huge_pages_node[MAX_NUMNODES];
@@ -123,39 +123,13 @@
 static struct page *alloc_huge_page(struct vm_area_struct *vma,
 				    unsigned long addr)
 {
-	struct inode *inode = vma->vm_file->f_dentry->d_inode;
 	struct page *page;
-	int use_reserve = 0;
-	unsigned long idx;
 
 	spin_lock(&hugetlb_lock);
-
-	if (vma->vm_flags & VM_MAYSHARE) {
-
-		/* idx = radix tree index, i.e. offset into file in
-		 * HPAGE_SIZE units */
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-
-		/* The hugetlbfs specific inode info stores the number
-		 * of "guaranteed available" (huge) pages.  That is,
-		 * the first 'prereserved_hpages' pages of the inode
-		 * are either already instantiated, or have been
-		 * pre-reserved (by hugetlb_reserve_for_inode()). Here
-		 * we're in the process of instantiating the page, so
-		 * we use this to determine whether to draw from the
-		 * pre-reserved pool or the truly free pool. */
-		if (idx < HUGETLBFS_I(inode)->prereserved_hpages)
-			use_reserve = 1;
-	}
-
-	if (!use_reserve) {
-		if (free_huge_pages <= reserved_huge_pages)
-			goto fail;
-	} else {
-		BUG_ON(reserved_huge_pages == 0);
-		reserved_huge_pages--;
-	}
+	if (vma->vm_flags & VM_MAYSHARE)
+		resv_huge_pages--;
+	else if (free_huge_pages <= resv_huge_pages)
+		goto fail;
 
 	page = dequeue_huge_page(vma, addr);
 	if (!page)
@@ -165,96 +139,11 @@
 	set_page_refcounted(page);
 	return page;
 
- fail:
-	WARN_ON(use_reserve); /* reserved allocations shouldn't fail */
+fail:
 	spin_unlock(&hugetlb_lock);
 	return NULL;
 }
 
-/* hugetlb_extend_reservation()
- *
- * Ensure that at least 'atleast' hugepages are, and will remain,
- * available to instantiate the first 'atleast' pages of the given
- * inode.  If the inode doesn't already have this many pages reserved
- * or instantiated, set aside some hugepages in the reserved pool to
- * satisfy later faults (or fail now if there aren't enough, rather
- * than getting the SIGBUS later).
- */
-int hugetlb_extend_reservation(struct hugetlbfs_inode_info *info,
-			       unsigned long atleast)
-{
-	struct inode *inode = &info->vfs_inode;
-	unsigned long change_in_reserve = 0;
-	int ret = 0;
-
-	spin_lock(&hugetlb_lock);
-	read_lock_irq(&inode->i_mapping->tree_lock);
-
-	if (info->prereserved_hpages >= atleast)
-		goto out;
-
-	/* Because we always call this on shared mappings, none of the
-	 * pages beyond info->prereserved_hpages can have been
-	 * instantiated, so we need to reserve all of them now. */
-	change_in_reserve = atleast - info->prereserved_hpages;
-
-	if ((reserved_huge_pages + change_in_reserve) > free_huge_pages) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	reserved_huge_pages += change_in_reserve;
-	info->prereserved_hpages = atleast;
-
- out:
-	read_unlock_irq(&inode->i_mapping->tree_lock);
-	spin_unlock(&hugetlb_lock);
-
-	return ret;
-}
-
-/* hugetlb_truncate_reservation()
- *
- * This returns pages reserved for the given inode to the general free
- * hugepage pool.  If the inode has any pages prereserved, but not
- * instantiated, beyond offset (atmost << HPAGE_SIZE), then release
- * them.
- */
-void hugetlb_truncate_reservation(struct hugetlbfs_inode_info *info,
-				  unsigned long atmost)
-{
-	struct inode *inode = &info->vfs_inode;
-	struct address_space *mapping = inode->i_mapping;
-	unsigned long idx;
-	unsigned long change_in_reserve = 0;
-	struct page *page;
-
-	spin_lock(&hugetlb_lock);
-	read_lock_irq(&inode->i_mapping->tree_lock);
-
-	if (info->prereserved_hpages <= atmost)
-		goto out;
-
-	/* Count pages which were reserved, but not instantiated, and
-	 * which we can now release. */
-	for (idx = atmost; idx < info->prereserved_hpages; idx++) {
-		page = radix_tree_lookup(&mapping->page_tree, idx);
-		if (!page)
-			/* Pages which are already instantiated can't
-			 * be unreserved (and in fact have already
-			 * been removed from the reserved pool) */
-			change_in_reserve++;
-	}
-
-	BUG_ON(reserved_huge_pages < change_in_reserve);
-	reserved_huge_pages -= change_in_reserve;
-	info->prereserved_hpages = atmost;
-
- out:
-	read_unlock_irq(&inode->i_mapping->tree_lock);
-	spin_unlock(&hugetlb_lock);
-}
-
 static int __init hugetlb_init(void)
 {
 	unsigned long i;
@@ -334,7 +223,7 @@
 		return nr_huge_pages;
 
 	spin_lock(&hugetlb_lock);
-	count = max(count, reserved_huge_pages);
+	count = max(count, resv_huge_pages);
 	try_to_free_low(count);
 	while (count < nr_huge_pages) {
 		struct page *page = dequeue_huge_page(NULL, 0);
@@ -361,11 +250,11 @@
 	return sprintf(buf,
 			"HugePages_Total: %5lu\n"
 			"HugePages_Free:  %5lu\n"
-		        "HugePages_Rsvd:  %5lu\n"
+			"HugePages_Rsvd:  %5lu\n"
 			"Hugepagesize:    %5lu kB\n",
 			nr_huge_pages,
 			free_huge_pages,
-		        reserved_huge_pages,
+			resv_huge_pages,
 			HPAGE_SIZE/1024);
 }
 
@@ -754,3 +643,156 @@
 	flush_tlb_range(vma, start, end);
 }
 
+struct file_region {
+	struct list_head link;
+	long from;
+	long to;
+};
+
+static long region_add(struct list_head *head, long f, long t)
+{
+	struct file_region *rg, *nrg, *trg;
+
+	/* Locate the region we are either in or before. */
+	list_for_each_entry(rg, head, link)
+		if (f <= rg->to)
+			break;
+
+	/* Round our left edge to the current segment if it encloses us. */
+	if (f > rg->from)
+		f = rg->from;
+
+	/* Check for and consume any regions we now overlap with. */
+	nrg = rg;
+	list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+		if (&rg->link == head)
+			break;
+		if (rg->from > t)
+			break;
+
+		/* If this area reaches higher then extend our area to
+		 * include it completely.  If this is not the first area
+		 * which we intend to reuse, free it. */
+		if (rg->to > t)
+			t = rg->to;
+		if (rg != nrg) {
+			list_del(&rg->link);
+			kfree(rg);
+		}
+	}
+	nrg->from = f;
+	nrg->to = t;
+	return 0;
+}
+
+static long region_chg(struct list_head *head, long f, long t)
+{
+	struct file_region *rg, *nrg;
+	long chg = 0;
+
+	/* Locate the region we are before or in. */
+	list_for_each_entry(rg, head, link)
+		if (f <= rg->to)
+			break;
+
+	/* If we are below the current region then a new region is required.
+	 * Subtle, allocate a new region at the position but make it zero
+	 * size such that we can guarentee to record the reservation. */
+	if (&rg->link == head || t < rg->from) {
+		nrg = kmalloc(sizeof(*nrg), GFP_KERNEL);
+		if (nrg == 0)
+			return -ENOMEM;
+		nrg->from = f;
+		nrg->to   = f;
+		INIT_LIST_HEAD(&nrg->link);
+		list_add(&nrg->link, rg->link.prev);
+
+		return t - f;
+	}
+
+	/* Round our left edge to the current segment if it encloses us. */
+	if (f > rg->from)
+		f = rg->from;
+	chg = t - f;
+
+	/* Check for and consume any regions we now overlap with. */
+	list_for_each_entry(rg, rg->link.prev, link) {
+		if (&rg->link == head)
+			break;
+		if (rg->from > t)
+			return chg;
+
+		/* We overlap with this area, if it extends futher than
+		 * us then we must extend ourselves.  Account for its
+		 * existing reservation. */
+		if (rg->to > t) {
+			chg += rg->to - t;
+			t = rg->to;
+		}
+		chg -= rg->to - rg->from;
+	}
+	return chg;
+}
+
+static long region_truncate(struct list_head *head, long end)
+{
+	struct file_region *rg, *trg;
+	long chg = 0;
+
+	/* Locate the region we are either in or before. */
+	list_for_each_entry(rg, head, link)
+		if (end <= rg->to)
+			break;
+	if (&rg->link == head)
+		return 0;
+
+	/* If we are in the middle of a region then adjust it. */
+	if (end > rg->from) {
+		chg = rg->to - end;
+		rg->to = end;
+		rg = list_entry(rg->link.next, typeof(*rg), link);
+	}
+
+	/* Drop any remaining regions. */
+	list_for_each_entry_safe(rg, trg, rg->link.prev, link) {
+		if (&rg->link == head)
+			break;
+		chg += rg->to - rg->from;
+		list_del(&rg->link);
+		kfree(rg);
+	}
+	return chg;
+}
+
+static int hugetlb_acct_memory(long delta)
+{
+	int ret = -ENOMEM;
+
+	spin_lock(&hugetlb_lock);
+	if ((delta + resv_huge_pages) <= free_huge_pages) {
+		resv_huge_pages += delta;
+		ret = 0;
+	}
+	spin_unlock(&hugetlb_lock);
+	return ret;
+}
+
+int hugetlb_reserve_pages(struct inode *inode, long from, long to)
+{
+	long ret, chg;
+
+	chg = region_chg(&inode->i_mapping->private_list, from, to);
+	if (chg < 0)
+		return chg;
+	ret = hugetlb_acct_memory(chg);
+	if (ret < 0)
+		return ret;
+	region_add(&inode->i_mapping->private_list, from, to);
+	return 0;
+}
+
+void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
+{
+	long chg = region_truncate(&inode->i_mapping->private_list, offset);
+	hugetlb_acct_memory(freed - chg);
+}
diff --git a/mm/memory.c b/mm/memory.c
index 0ec7bc6..247b5c3 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -434,7 +434,9 @@
 	/* pte contains position in swap or file, so copy. */
 	if (unlikely(!pte_present(pte))) {
 		if (!pte_file(pte)) {
-			swap_duplicate(pte_to_swp_entry(pte));
+			swp_entry_t entry = pte_to_swp_entry(pte);
+
+			swap_duplicate(entry);
 			/* make sure dst_mm is on swapoff's mmlist. */
 			if (unlikely(list_empty(&dst_mm->mmlist))) {
 				spin_lock(&mmlist_lock);
@@ -443,6 +445,16 @@
 						 &src_mm->mmlist);
 				spin_unlock(&mmlist_lock);
 			}
+			if (is_write_migration_entry(entry) &&
+					is_cow_mapping(vm_flags)) {
+				/*
+				 * COW mappings require pages in both parent
+				 * and child to be set to read.
+				 */
+				make_migration_entry_read(&entry);
+				pte = swp_entry_to_pte(entry);
+				set_pte_at(src_mm, addr, src_pte, pte);
+			}
 		}
 		goto out_set_pte;
 	}
@@ -1445,25 +1457,60 @@
 {
 	struct page *old_page, *new_page;
 	pte_t entry;
-	int ret = VM_FAULT_MINOR;
+	int reuse, ret = VM_FAULT_MINOR;
 
 	old_page = vm_normal_page(vma, address, orig_pte);
 	if (!old_page)
 		goto gotten;
 
-	if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
-		int reuse = can_share_swap_page(old_page);
-		unlock_page(old_page);
-		if (reuse) {
-			flush_cache_page(vma, address, pte_pfn(orig_pte));
-			entry = pte_mkyoung(orig_pte);
-			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-			ptep_set_access_flags(vma, address, page_table, entry, 1);
-			update_mmu_cache(vma, address, entry);
-			lazy_mmu_prot_update(entry);
-			ret |= VM_FAULT_WRITE;
-			goto unlock;
+	if (unlikely((vma->vm_flags & (VM_SHARED|VM_WRITE)) ==
+				(VM_SHARED|VM_WRITE))) {
+		if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
+			/*
+			 * Notify the address space that the page is about to
+			 * become writable so that it can prohibit this or wait
+			 * for the page to get into an appropriate state.
+			 *
+			 * We do this without the lock held, so that it can
+			 * sleep if it needs to.
+			 */
+			page_cache_get(old_page);
+			pte_unmap_unlock(page_table, ptl);
+
+			if (vma->vm_ops->page_mkwrite(vma, old_page) < 0)
+				goto unwritable_page;
+
+			page_cache_release(old_page);
+
+			/*
+			 * Since we dropped the lock we need to revalidate
+			 * the PTE as someone else may have changed it.  If
+			 * they did, we just return, as we can count on the
+			 * MMU to tell us if they didn't also make it writable.
+			 */
+			page_table = pte_offset_map_lock(mm, pmd, address,
+							 &ptl);
+			if (!pte_same(*page_table, orig_pte))
+				goto unlock;
 		}
+
+		reuse = 1;
+	} else if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
+		reuse = can_share_swap_page(old_page);
+		unlock_page(old_page);
+	} else {
+		reuse = 0;
+	}
+
+	if (reuse) {
+		flush_cache_page(vma, address, pte_pfn(orig_pte));
+		entry = pte_mkyoung(orig_pte);
+		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+		ptep_set_access_flags(vma, address, page_table, entry, 1);
+		update_mmu_cache(vma, address, entry);
+		lazy_mmu_prot_update(entry);
+		ret |= VM_FAULT_WRITE;
+		goto unlock;
 	}
 
 	/*
@@ -1523,6 +1570,10 @@
 	if (old_page)
 		page_cache_release(old_page);
 	return VM_FAULT_OOM;
+
+unwritable_page:
+	page_cache_release(old_page);
+	return VM_FAULT_SIGBUS;
 }
 
 /*
@@ -1879,7 +1930,10 @@
 		goto out;
 
 	entry = pte_to_swp_entry(orig_pte);
-again:
+	if (is_migration_entry(entry)) {
+		migration_entry_wait(mm, pmd, address);
+		goto out;
+	}
 	page = lookup_swap_cache(entry);
 	if (!page) {
  		swapin_readahead(entry, address, vma);
@@ -1903,12 +1957,6 @@
 
 	mark_page_accessed(page);
 	lock_page(page);
-	if (!PageSwapCache(page)) {
-		/* Page migration has occured */
-		unlock_page(page);
-		page_cache_release(page);
-		goto again;
-	}
 
 	/*
 	 * Back out if somebody else already faulted in this pte.
@@ -2074,18 +2122,31 @@
 	/*
 	 * Should we do an early C-O-W break?
 	 */
-	if (write_access && !(vma->vm_flags & VM_SHARED)) {
-		struct page *page;
+	if (write_access) {
+		if (!(vma->vm_flags & VM_SHARED)) {
+			struct page *page;
 
-		if (unlikely(anon_vma_prepare(vma)))
-			goto oom;
-		page = alloc_page_vma(GFP_HIGHUSER, vma, address);
-		if (!page)
-			goto oom;
-		copy_user_highpage(page, new_page, address);
-		page_cache_release(new_page);
-		new_page = page;
-		anon = 1;
+			if (unlikely(anon_vma_prepare(vma)))
+				goto oom;
+			page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+			if (!page)
+				goto oom;
+			copy_user_highpage(page, new_page, address);
+			page_cache_release(new_page);
+			new_page = page;
+			anon = 1;
+
+		} else {
+			/* if the page will be shareable, see if the backing
+			 * address space wants to know that the page is about
+			 * to become writable */
+			if (vma->vm_ops->page_mkwrite &&
+			    vma->vm_ops->page_mkwrite(vma, new_page) < 0
+			    ) {
+				page_cache_release(new_page);
+				return VM_FAULT_SIGBUS;
+			}
+		}
 	}
 
 	page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 70df5c0..ea40388 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -21,12 +21,13 @@
 #include <linux/memory_hotplug.h>
 #include <linux/highmem.h>
 #include <linux/vmalloc.h>
+#include <linux/ioport.h>
 
 #include <asm/tlbflush.h>
 
 extern void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
 			  unsigned long size);
-static void __add_zone(struct zone *zone, unsigned long phys_start_pfn)
+static int __add_zone(struct zone *zone, unsigned long phys_start_pfn)
 {
 	struct pglist_data *pgdat = zone->zone_pgdat;
 	int nr_pages = PAGES_PER_SECTION;
@@ -34,8 +35,15 @@
 	int zone_type;
 
 	zone_type = zone - pgdat->node_zones;
+	if (!populated_zone(zone)) {
+		int ret = 0;
+		ret = init_currently_empty_zone(zone, phys_start_pfn, nr_pages);
+		if (ret < 0)
+			return ret;
+	}
 	memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn);
 	zonetable_add(zone, nid, zone_type, phys_start_pfn, nr_pages);
+	return 0;
 }
 
 extern int sparse_add_one_section(struct zone *zone, unsigned long start_pfn,
@@ -50,7 +58,11 @@
 	if (ret < 0)
 		return ret;
 
-	__add_zone(zone, phys_start_pfn);
+	ret = __add_zone(zone, phys_start_pfn);
+
+	if (ret < 0)
+		return ret;
+
 	return register_new_memory(__pfn_to_section(phys_start_pfn));
 }
 
@@ -115,7 +127,11 @@
 	unsigned long i;
 	unsigned long flags;
 	unsigned long onlined_pages = 0;
+	struct resource res;
+	u64 section_end;
+	unsigned long start_pfn;
 	struct zone *zone;
+	int need_zonelists_rebuild = 0;
 
 	/*
 	 * This doesn't need a lock to do pfn_to_page().
@@ -128,15 +144,140 @@
 	grow_pgdat_span(zone->zone_pgdat, pfn, pfn + nr_pages);
 	pgdat_resize_unlock(zone->zone_pgdat, &flags);
 
-	for (i = 0; i < nr_pages; i++) {
-		struct page *page = pfn_to_page(pfn + i);
-		online_page(page);
-		onlined_pages++;
+	/*
+	 * If this zone is not populated, then it is not in zonelist.
+	 * This means the page allocator ignores this zone.
+	 * So, zonelist must be updated after online.
+	 */
+	if (!populated_zone(zone))
+		need_zonelists_rebuild = 1;
+
+	res.start = (u64)pfn << PAGE_SHIFT;
+	res.end = res.start + ((u64)nr_pages << PAGE_SHIFT) - 1;
+	res.flags = IORESOURCE_MEM; /* we just need system ram */
+	section_end = res.end;
+
+	while (find_next_system_ram(&res) >= 0) {
+		start_pfn = (unsigned long)(res.start >> PAGE_SHIFT);
+		nr_pages = (unsigned long)
+                           ((res.end + 1 - res.start) >> PAGE_SHIFT);
+
+		if (PageReserved(pfn_to_page(start_pfn))) {
+			/* this region's page is not onlined now */
+			for (i = 0; i < nr_pages; i++) {
+				struct page *page = pfn_to_page(start_pfn + i);
+				online_page(page);
+				onlined_pages++;
+			}
+		}
+
+		res.start = res.end + 1;
+		res.end = section_end;
 	}
 	zone->present_pages += onlined_pages;
 	zone->zone_pgdat->node_present_pages += onlined_pages;
 
 	setup_per_zone_pages_min();
 
+	if (need_zonelists_rebuild)
+		build_all_zonelists();
+	vm_total_pages = nr_free_pagecache_pages();
 	return 0;
 }
+
+static pg_data_t *hotadd_new_pgdat(int nid, u64 start)
+{
+	struct pglist_data *pgdat;
+	unsigned long zones_size[MAX_NR_ZONES] = {0};
+	unsigned long zholes_size[MAX_NR_ZONES] = {0};
+	unsigned long start_pfn = start >> PAGE_SHIFT;
+
+	pgdat = arch_alloc_nodedata(nid);
+	if (!pgdat)
+		return NULL;
+
+	arch_refresh_nodedata(nid, pgdat);
+
+	/* we can use NODE_DATA(nid) from here */
+
+	/* init node's zones as empty zones, we don't have any present pages.*/
+	free_area_init_node(nid, pgdat, zones_size, start_pfn, zholes_size);
+
+	return pgdat;
+}
+
+static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
+{
+	arch_refresh_nodedata(nid, NULL);
+	arch_free_nodedata(pgdat);
+	return;
+}
+
+/* add this memory to iomem resource */
+static void register_memory_resource(u64 start, u64 size)
+{
+	struct resource *res;
+
+	res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+	BUG_ON(!res);
+
+	res->name = "System RAM";
+	res->start = start;
+	res->end = start + size - 1;
+	res->flags = IORESOURCE_MEM;
+	if (request_resource(&iomem_resource, res) < 0) {
+		printk("System RAM resource %llx - %llx cannot be added\n",
+		(unsigned long long)res->start, (unsigned long long)res->end);
+		kfree(res);
+	}
+}
+
+
+
+int add_memory(int nid, u64 start, u64 size)
+{
+	pg_data_t *pgdat = NULL;
+	int new_pgdat = 0;
+	int ret;
+
+	if (!node_online(nid)) {
+		pgdat = hotadd_new_pgdat(nid, start);
+		if (!pgdat)
+			return -ENOMEM;
+		new_pgdat = 1;
+		ret = kswapd_run(nid);
+		if (ret)
+			goto error;
+	}
+
+	/* call arch's memory hotadd */
+	ret = arch_add_memory(nid, start, size);
+
+	if (ret < 0)
+		goto error;
+
+	/* we online node here. we can't roll back from here. */
+	node_set_online(nid);
+
+	if (new_pgdat) {
+		ret = register_one_node(nid);
+		/*
+		 * If sysfs file of new node can't create, cpu on the node
+		 * can't be hot-added. There is no rollback way now.
+		 * So, check by BUG_ON() to catch it reluctantly..
+		 */
+		BUG_ON(ret);
+	}
+
+	/* register this memory as resource */
+	register_memory_resource(start, size);
+
+	return ret;
+error:
+	/* rollback pgdat allocation and others */
+	if (new_pgdat)
+		rollback_node_hotadd(nid, pgdat);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(add_memory);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 8778f58..6b9740b 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -87,6 +87,8 @@
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
 #include <linux/migrate.h>
+#include <linux/rmap.h>
+#include <linux/security.h>
 
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
@@ -587,6 +589,11 @@
 		isolate_lru_page(page, pagelist);
 }
 
+static struct page *new_node_page(struct page *page, unsigned long node, int **x)
+{
+	return alloc_pages_node(node, GFP_HIGHUSER, 0);
+}
+
 /*
  * Migrate pages from one node to a target node.
  * Returns error or the number of pages not migrated.
@@ -603,11 +610,9 @@
 	check_range(mm, mm->mmap->vm_start, TASK_SIZE, &nmask,
 			flags | MPOL_MF_DISCONTIG_OK, &pagelist);
 
-	if (!list_empty(&pagelist)) {
-		err = migrate_pages_to(&pagelist, NULL, dest);
-		if (!list_empty(&pagelist))
-			putback_lru_pages(&pagelist);
-	}
+	if (!list_empty(&pagelist))
+		err = migrate_pages(&pagelist, new_node_page, dest);
+
 	return err;
 }
 
@@ -627,6 +632,10 @@
 
   	down_read(&mm->mmap_sem);
 
+	err = migrate_vmas(mm, from_nodes, to_nodes, flags);
+	if (err)
+		goto out;
+
 /*
  * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
  * bit in 'to' is not also set in 'tmp'.  Clear the found 'source'
@@ -686,7 +695,7 @@
 		if (err < 0)
 			break;
 	}
-
+out:
 	up_read(&mm->mmap_sem);
 	if (err < 0)
 		return err;
@@ -694,6 +703,12 @@
 
 }
 
+static struct page *new_vma_page(struct page *page, unsigned long private, int **x)
+{
+	struct vm_area_struct *vma = (struct vm_area_struct *)private;
+
+	return alloc_page_vma(GFP_HIGHUSER, vma, page_address_in_vma(page, vma));
+}
 #else
 
 static void migrate_page_add(struct page *page, struct list_head *pagelist,
@@ -706,6 +721,11 @@
 {
 	return -ENOSYS;
 }
+
+static struct page *new_vma_page(struct page *page, unsigned long private)
+{
+	return NULL;
+}
 #endif
 
 long do_mbind(unsigned long start, unsigned long len,
@@ -767,15 +787,13 @@
 		err = mbind_range(vma, start, end, new);
 
 		if (!list_empty(&pagelist))
-			nr_failed = migrate_pages_to(&pagelist, vma, -1);
+			nr_failed = migrate_pages(&pagelist, new_vma_page,
+						(unsigned long)vma);
 
 		if (!err && nr_failed && (flags & MPOL_MF_STRICT))
 			err = -EIO;
 	}
 
-	if (!list_empty(&pagelist))
-		putback_lru_pages(&pagelist);
-
 	up_write(&mm->mmap_sem);
 	mpol_free(new);
 	return err;
@@ -929,6 +947,10 @@
 		goto out;
 	}
 
+	err = security_task_movememory(task);
+	if (err)
+		goto out;
+
 	err = do_migrate_pages(mm, &old, &new,
 		capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
 out:
@@ -1799,7 +1821,7 @@
 
 int show_numa_map(struct seq_file *m, void *v)
 {
-	struct task_struct *task = m->private;
+	struct proc_maps_private *priv = m->private;
 	struct vm_area_struct *vma = v;
 	struct numa_maps *md;
 	struct file *file = vma->vm_file;
@@ -1815,7 +1837,7 @@
 		return 0;
 
 	mpol_to_str(buffer, sizeof(buffer),
-			get_vma_policy(task, vma, vma->vm_start));
+			    get_vma_policy(priv->task, vma, vma->vm_start));
 
 	seq_printf(m, "%08lx %s", vma->vm_start, buffer);
 
@@ -1869,7 +1891,7 @@
 	kfree(md);
 
 	if (m->count < m->size)
-		m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0;
+		m->version = (vma != priv->tail_vma) ? vma->vm_start : 0;
 	return 0;
 }
 
diff --git a/mm/migrate.c b/mm/migrate.c
index 1c25040..3f1e0c2 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -15,6 +15,7 @@
 #include <linux/migrate.h>
 #include <linux/module.h>
 #include <linux/swap.h>
+#include <linux/swapops.h>
 #include <linux/pagemap.h>
 #include <linux/buffer_head.h>
 #include <linux/mm_inline.h>
@@ -23,13 +24,13 @@
 #include <linux/topology.h>
 #include <linux/cpu.h>
 #include <linux/cpuset.h>
-#include <linux/swapops.h>
+#include <linux/writeback.h>
+#include <linux/mempolicy.h>
+#include <linux/vmalloc.h>
+#include <linux/security.h>
 
 #include "internal.h"
 
-/* The maximum number of pages to take off the LRU for migration */
-#define MIGRATE_CHUNK_SIZE 256
-
 #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
 
 /*
@@ -64,16 +65,11 @@
 }
 
 /*
- * migrate_prep() needs to be called after we have compiled the list of pages
- * to be migrated using isolate_lru_page() but before we begin a series of calls
- * to migrate_pages().
+ * migrate_prep() needs to be called before we start compiling a list of pages
+ * to be migrated using isolate_lru_page().
  */
 int migrate_prep(void)
 {
-	/* Must have swap device for migration */
-	if (nr_swap_pages <= 0)
-		return -ENODEV;
-
 	/*
 	 * Clear the LRU lists so pages can be isolated.
 	 * Note that pages may be moved off the LRU after we have
@@ -87,7 +83,6 @@
 
 static inline void move_to_lru(struct page *page)
 {
-	list_del(&page->lru);
 	if (PageActive(page)) {
 		/*
 		 * lru_cache_add_active checks that
@@ -113,113 +108,200 @@
 	int count = 0;
 
 	list_for_each_entry_safe(page, page2, l, lru) {
+		list_del(&page->lru);
 		move_to_lru(page);
 		count++;
 	}
 	return count;
 }
 
-/*
- * Non migratable page
- */
-int fail_migrate_page(struct page *newpage, struct page *page)
+static inline int is_swap_pte(pte_t pte)
 {
-	return -EIO;
-}
-EXPORT_SYMBOL(fail_migrate_page);
-
-/*
- * swapout a single page
- * page is locked upon entry, unlocked on exit
- */
-static int swap_page(struct page *page)
-{
-	struct address_space *mapping = page_mapping(page);
-
-	if (page_mapped(page) && mapping)
-		if (try_to_unmap(page, 1) != SWAP_SUCCESS)
-			goto unlock_retry;
-
-	if (PageDirty(page)) {
-		/* Page is dirty, try to write it out here */
-		switch(pageout(page, mapping)) {
-		case PAGE_KEEP:
-		case PAGE_ACTIVATE:
-			goto unlock_retry;
-
-		case PAGE_SUCCESS:
-			goto retry;
-
-		case PAGE_CLEAN:
-			; /* try to free the page below */
-		}
-	}
-
-	if (PagePrivate(page)) {
-		if (!try_to_release_page(page, GFP_KERNEL) ||
-		    (!mapping && page_count(page) == 1))
-			goto unlock_retry;
-	}
-
-	if (remove_mapping(mapping, page)) {
-		/* Success */
-		unlock_page(page);
-		return 0;
-	}
-
-unlock_retry:
-	unlock_page(page);
-
-retry:
-	return -EAGAIN;
+	return !pte_none(pte) && !pte_present(pte) && !pte_file(pte);
 }
 
 /*
- * Remove references for a page and establish the new page with the correct
- * basic settings to be able to stop accesses to the page.
+ * Restore a potential migration pte to a working pte entry
  */
-int migrate_page_remove_references(struct page *newpage,
-				struct page *page, int nr_refs)
+static void remove_migration_pte(struct vm_area_struct *vma,
+		struct page *old, struct page *new)
 {
-	struct address_space *mapping = page_mapping(page);
+	struct mm_struct *mm = vma->vm_mm;
+	swp_entry_t entry;
+ 	pgd_t *pgd;
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+	pte_t *ptep, pte;
+ 	spinlock_t *ptl;
+	unsigned long addr = page_address_in_vma(new, vma);
+
+	if (addr == -EFAULT)
+		return;
+
+ 	pgd = pgd_offset(mm, addr);
+	if (!pgd_present(*pgd))
+                return;
+
+	pud = pud_offset(pgd, addr);
+	if (!pud_present(*pud))
+                return;
+
+	pmd = pmd_offset(pud, addr);
+	if (!pmd_present(*pmd))
+		return;
+
+	ptep = pte_offset_map(pmd, addr);
+
+	if (!is_swap_pte(*ptep)) {
+		pte_unmap(ptep);
+ 		return;
+ 	}
+
+ 	ptl = pte_lockptr(mm, pmd);
+ 	spin_lock(ptl);
+	pte = *ptep;
+	if (!is_swap_pte(pte))
+		goto out;
+
+	entry = pte_to_swp_entry(pte);
+
+	if (!is_migration_entry(entry) || migration_entry_to_page(entry) != old)
+		goto out;
+
+	get_page(new);
+	pte = pte_mkold(mk_pte(new, vma->vm_page_prot));
+	if (is_write_migration_entry(entry))
+		pte = pte_mkwrite(pte);
+	set_pte_at(mm, addr, ptep, pte);
+
+	if (PageAnon(new))
+		page_add_anon_rmap(new, vma, addr);
+	else
+		page_add_file_rmap(new);
+
+	/* No need to invalidate - it was non-present before */
+	update_mmu_cache(vma, addr, pte);
+	lazy_mmu_prot_update(pte);
+
+out:
+	pte_unmap_unlock(ptep, ptl);
+}
+
+/*
+ * Note that remove_file_migration_ptes will only work on regular mappings,
+ * Nonlinear mappings do not use migration entries.
+ */
+static void remove_file_migration_ptes(struct page *old, struct page *new)
+{
+	struct vm_area_struct *vma;
+	struct address_space *mapping = page_mapping(new);
+	struct prio_tree_iter iter;
+	pgoff_t pgoff = new->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+
+	if (!mapping)
+		return;
+
+	spin_lock(&mapping->i_mmap_lock);
+
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff)
+		remove_migration_pte(vma, old, new);
+
+	spin_unlock(&mapping->i_mmap_lock);
+}
+
+/*
+ * Must hold mmap_sem lock on at least one of the vmas containing
+ * the page so that the anon_vma cannot vanish.
+ */
+static void remove_anon_migration_ptes(struct page *old, struct page *new)
+{
+	struct anon_vma *anon_vma;
+	struct vm_area_struct *vma;
+	unsigned long mapping;
+
+	mapping = (unsigned long)new->mapping;
+
+	if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0)
+		return;
+
+	/*
+	 * We hold the mmap_sem lock. So no need to call page_lock_anon_vma.
+	 */
+	anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON);
+	spin_lock(&anon_vma->lock);
+
+	list_for_each_entry(vma, &anon_vma->head, anon_vma_node)
+		remove_migration_pte(vma, old, new);
+
+	spin_unlock(&anon_vma->lock);
+}
+
+/*
+ * Get rid of all migration entries and replace them by
+ * references to the indicated page.
+ */
+static void remove_migration_ptes(struct page *old, struct page *new)
+{
+	if (PageAnon(new))
+		remove_anon_migration_ptes(old, new);
+	else
+		remove_file_migration_ptes(old, new);
+}
+
+/*
+ * Something used the pte of a page under migration. We need to
+ * get to the page and wait until migration is finished.
+ * When we return from this function the fault will be retried.
+ *
+ * This function is called from do_swap_page().
+ */
+void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd,
+				unsigned long address)
+{
+	pte_t *ptep, pte;
+	spinlock_t *ptl;
+	swp_entry_t entry;
+	struct page *page;
+
+	ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+	pte = *ptep;
+	if (!is_swap_pte(pte))
+		goto out;
+
+	entry = pte_to_swp_entry(pte);
+	if (!is_migration_entry(entry))
+		goto out;
+
+	page = migration_entry_to_page(entry);
+
+	get_page(page);
+	pte_unmap_unlock(ptep, ptl);
+	wait_on_page_locked(page);
+	put_page(page);
+	return;
+out:
+	pte_unmap_unlock(ptep, ptl);
+}
+
+/*
+ * Replace the page in the mapping.
+ *
+ * The number of remaining references must be:
+ * 1 for anonymous pages without a mapping
+ * 2 for pages with a mapping
+ * 3 for pages with a mapping and PagePrivate set.
+ */
+static int migrate_page_move_mapping(struct address_space *mapping,
+		struct page *newpage, struct page *page)
+{
 	struct page **radix_pointer;
 
-	/*
-	 * Avoid doing any of the following work if the page count
-	 * indicates that the page is in use or truncate has removed
-	 * the page.
-	 */
-	if (!mapping || page_mapcount(page) + nr_refs != page_count(page))
-		return -EAGAIN;
-
-	/*
-	 * Establish swap ptes for anonymous pages or destroy pte
-	 * maps for files.
-	 *
-	 * In order to reestablish file backed mappings the fault handlers
-	 * will take the radix tree_lock which may then be used to stop
-  	 * processses from accessing this page until the new page is ready.
-	 *
-	 * A process accessing via a swap pte (an anonymous page) will take a
-	 * page_lock on the old page which will block the process until the
-	 * migration attempt is complete. At that time the PageSwapCache bit
-	 * will be examined. If the page was migrated then the PageSwapCache
-	 * bit will be clear and the operation to retrieve the page will be
-	 * retried which will find the new page in the radix tree. Then a new
-	 * direct mapping may be generated based on the radix tree contents.
-	 *
-	 * If the page was not migrated then the PageSwapCache bit
-	 * is still set and the operation may continue.
-	 */
-	if (try_to_unmap(page, 1) == SWAP_FAIL)
-		/* A vma has VM_LOCKED set -> permanent failure */
-		return -EPERM;
-
-	/*
-	 * Give up if we were unable to remove all mappings.
-	 */
-	if (page_mapcount(page))
-		return -EAGAIN;
+	if (!mapping) {
+		/* Anonymous page */
+		if (page_count(page) != 1)
+			return -EAGAIN;
+		return 0;
+	}
 
 	write_lock_irq(&mapping->tree_lock);
 
@@ -227,7 +309,7 @@
 						&mapping->page_tree,
 						page_index(page));
 
-	if (!page_mapping(page) || page_count(page) != nr_refs ||
+	if (page_count(page) != 2 + !!PagePrivate(page) ||
 			*radix_pointer != page) {
 		write_unlock_irq(&mapping->tree_lock);
 		return -EAGAIN;
@@ -235,19 +317,14 @@
 
 	/*
 	 * Now we know that no one else is looking at the page.
-	 *
-	 * Certain minimal information about a page must be available
-	 * in order for other subsystems to properly handle the page if they
-	 * find it through the radix tree update before we are finished
-	 * copying the page.
 	 */
 	get_page(newpage);
-	newpage->index = page->index;
-	newpage->mapping = page->mapping;
+#ifdef CONFIG_SWAP
 	if (PageSwapCache(page)) {
 		SetPageSwapCache(newpage);
 		set_page_private(newpage, page_private(page));
 	}
+#endif
 
 	*radix_pointer = newpage;
 	__put_page(page);
@@ -255,12 +332,11 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(migrate_page_remove_references);
 
 /*
  * Copy the page to its new location
  */
-void migrate_page_copy(struct page *newpage, struct page *page)
+static void migrate_page_copy(struct page *newpage, struct page *page)
 {
 	copy_highpage(newpage, page);
 
@@ -282,7 +358,9 @@
 		set_page_dirty(newpage);
  	}
 
+#ifdef CONFIG_SWAP
 	ClearPageSwapCache(page);
+#endif
 	ClearPageActive(page);
 	ClearPagePrivate(page);
 	set_page_private(page, 0);
@@ -295,7 +373,18 @@
 	if (PageWriteback(newpage))
 		end_page_writeback(newpage);
 }
-EXPORT_SYMBOL(migrate_page_copy);
+
+/************************************************************
+ *                    Migration functions
+ ***********************************************************/
+
+/* Always fail migration. Used for mappings that are not movable */
+int fail_migrate_page(struct address_space *mapping,
+			struct page *newpage, struct page *page)
+{
+	return -EIO;
+}
+EXPORT_SYMBOL(fail_migrate_page);
 
 /*
  * Common logic to directly migrate a single page suitable for
@@ -303,251 +392,40 @@
  *
  * Pages are locked upon entry and exit.
  */
-int migrate_page(struct page *newpage, struct page *page)
+int migrate_page(struct address_space *mapping,
+		struct page *newpage, struct page *page)
 {
 	int rc;
 
 	BUG_ON(PageWriteback(page));	/* Writeback must be complete */
 
-	rc = migrate_page_remove_references(newpage, page, 2);
+	rc = migrate_page_move_mapping(mapping, newpage, page);
 
 	if (rc)
 		return rc;
 
 	migrate_page_copy(newpage, page);
-
-	/*
-	 * Remove auxiliary swap entries and replace
-	 * them with real ptes.
-	 *
-	 * Note that a real pte entry will allow processes that are not
-	 * waiting on the page lock to use the new page via the page tables
-	 * before the new page is unlocked.
-	 */
-	remove_from_swap(newpage);
 	return 0;
 }
 EXPORT_SYMBOL(migrate_page);
 
 /*
- * migrate_pages
- *
- * Two lists are passed to this function. The first list
- * contains the pages isolated from the LRU to be migrated.
- * The second list contains new pages that the pages isolated
- * can be moved to. If the second list is NULL then all
- * pages are swapped out.
- *
- * The function returns after 10 attempts or if no pages
- * are movable anymore because to has become empty
- * or no retryable pages exist anymore.
- *
- * Return: Number of pages not migrated when "to" ran empty.
- */
-int migrate_pages(struct list_head *from, struct list_head *to,
-		  struct list_head *moved, struct list_head *failed)
-{
-	int retry;
-	int nr_failed = 0;
-	int pass = 0;
-	struct page *page;
-	struct page *page2;
-	int swapwrite = current->flags & PF_SWAPWRITE;
-	int rc;
-
-	if (!swapwrite)
-		current->flags |= PF_SWAPWRITE;
-
-redo:
-	retry = 0;
-
-	list_for_each_entry_safe(page, page2, from, lru) {
-		struct page *newpage = NULL;
-		struct address_space *mapping;
-
-		cond_resched();
-
-		rc = 0;
-		if (page_count(page) == 1)
-			/* page was freed from under us. So we are done. */
-			goto next;
-
-		if (to && list_empty(to))
-			break;
-
-		/*
-		 * Skip locked pages during the first two passes to give the
-		 * functions holding the lock time to release the page. Later we
-		 * use lock_page() to have a higher chance of acquiring the
-		 * lock.
-		 */
-		rc = -EAGAIN;
-		if (pass > 2)
-			lock_page(page);
-		else
-			if (TestSetPageLocked(page))
-				goto next;
-
-		/*
-		 * Only wait on writeback if we have already done a pass where
-		 * we we may have triggered writeouts for lots of pages.
-		 */
-		if (pass > 0) {
-			wait_on_page_writeback(page);
-		} else {
-			if (PageWriteback(page))
-				goto unlock_page;
-		}
-
-		/*
-		 * Anonymous pages must have swap cache references otherwise
-		 * the information contained in the page maps cannot be
-		 * preserved.
-		 */
-		if (PageAnon(page) && !PageSwapCache(page)) {
-			if (!add_to_swap(page, GFP_KERNEL)) {
-				rc = -ENOMEM;
-				goto unlock_page;
-			}
-		}
-
-		if (!to) {
-			rc = swap_page(page);
-			goto next;
-		}
-
-		newpage = lru_to_page(to);
-		lock_page(newpage);
-
-		/*
-		 * Pages are properly locked and writeback is complete.
-		 * Try to migrate the page.
-		 */
-		mapping = page_mapping(page);
-		if (!mapping)
-			goto unlock_both;
-
-		if (mapping->a_ops->migratepage) {
-			/*
-			 * Most pages have a mapping and most filesystems
-			 * should provide a migration function. Anonymous
-			 * pages are part of swap space which also has its
-			 * own migration function. This is the most common
-			 * path for page migration.
-			 */
-			rc = mapping->a_ops->migratepage(newpage, page);
-			goto unlock_both;
-                }
-
-		/* Make sure the dirty bit is up to date */
-		if (try_to_unmap(page, 1) == SWAP_FAIL) {
-			rc = -EPERM;
-			goto unlock_both;
-		}
-
-		if (page_mapcount(page)) {
-			rc = -EAGAIN;
-			goto unlock_both;
-		}
-
-		/*
-		 * Default handling if a filesystem does not provide
-		 * a migration function. We can only migrate clean
-		 * pages so try to write out any dirty pages first.
-		 */
-		if (PageDirty(page)) {
-			switch (pageout(page, mapping)) {
-			case PAGE_KEEP:
-			case PAGE_ACTIVATE:
-				goto unlock_both;
-
-			case PAGE_SUCCESS:
-				unlock_page(newpage);
-				goto next;
-
-			case PAGE_CLEAN:
-				; /* try to migrate the page below */
-			}
-                }
-
-		/*
-		 * Buffers are managed in a filesystem specific way.
-		 * We must have no buffers or drop them.
-		 */
-		if (!page_has_buffers(page) ||
-		    try_to_release_page(page, GFP_KERNEL)) {
-			rc = migrate_page(newpage, page);
-			goto unlock_both;
-		}
-
-		/*
-		 * On early passes with mapped pages simply
-		 * retry. There may be a lock held for some
-		 * buffers that may go away. Later
-		 * swap them out.
-		 */
-		if (pass > 4) {
-			/*
-			 * Persistently unable to drop buffers..... As a
-			 * measure of last resort we fall back to
-			 * swap_page().
-			 */
-			unlock_page(newpage);
-			newpage = NULL;
-			rc = swap_page(page);
-			goto next;
-		}
-
-unlock_both:
-		unlock_page(newpage);
-
-unlock_page:
-		unlock_page(page);
-
-next:
-		if (rc == -EAGAIN) {
-			retry++;
-		} else if (rc) {
-			/* Permanent failure */
-			list_move(&page->lru, failed);
-			nr_failed++;
-		} else {
-			if (newpage) {
-				/* Successful migration. Return page to LRU */
-				move_to_lru(newpage);
-			}
-			list_move(&page->lru, moved);
-		}
-	}
-	if (retry && pass++ < 10)
-		goto redo;
-
-	if (!swapwrite)
-		current->flags &= ~PF_SWAPWRITE;
-
-	return nr_failed + retry;
-}
-
-/*
  * Migration function for pages with buffers. This function can only be used
  * if the underlying filesystem guarantees that no other references to "page"
  * exist.
  */
-int buffer_migrate_page(struct page *newpage, struct page *page)
+int buffer_migrate_page(struct address_space *mapping,
+		struct page *newpage, struct page *page)
 {
-	struct address_space *mapping = page->mapping;
 	struct buffer_head *bh, *head;
 	int rc;
 
-	if (!mapping)
-		return -EAGAIN;
-
 	if (!page_has_buffers(page))
-		return migrate_page(newpage, page);
+		return migrate_page(mapping, newpage, page);
 
 	head = page_buffers(page);
 
-	rc = migrate_page_remove_references(newpage, page, 3);
+	rc = migrate_page_move_mapping(mapping, newpage, page);
 
 	if (rc)
 		return rc;
@@ -590,73 +468,529 @@
 EXPORT_SYMBOL(buffer_migrate_page);
 
 /*
- * Migrate the list 'pagelist' of pages to a certain destination.
- *
- * Specify destination with either non-NULL vma or dest_node >= 0
- * Return the number of pages not migrated or error code
+ * Writeback a page to clean the dirty state
  */
-int migrate_pages_to(struct list_head *pagelist,
-			struct vm_area_struct *vma, int dest)
+static int writeout(struct address_space *mapping, struct page *page)
 {
-	LIST_HEAD(newlist);
-	LIST_HEAD(moved);
-	LIST_HEAD(failed);
-	int err = 0;
-	unsigned long offset = 0;
-	int nr_pages;
-	struct page *page;
-	struct list_head *p;
+	struct writeback_control wbc = {
+		.sync_mode = WB_SYNC_NONE,
+		.nr_to_write = 1,
+		.range_start = 0,
+		.range_end = LLONG_MAX,
+		.nonblocking = 1,
+		.for_reclaim = 1
+	};
+	int rc;
 
-redo:
-	nr_pages = 0;
-	list_for_each(p, pagelist) {
-		if (vma) {
-			/*
-			 * The address passed to alloc_page_vma is used to
-			 * generate the proper interleave behavior. We fake
-			 * the address here by an increasing offset in order
-			 * to get the proper distribution of pages.
-			 *
-			 * No decision has been made as to which page
-			 * a certain old page is moved to so we cannot
-			 * specify the correct address.
-			 */
-			page = alloc_page_vma(GFP_HIGHUSER, vma,
-					offset + vma->vm_start);
-			offset += PAGE_SIZE;
-		}
+	if (!mapping->a_ops->writepage)
+		/* No write method for the address space */
+		return -EINVAL;
+
+	if (!clear_page_dirty_for_io(page))
+		/* Someone else already triggered a write */
+		return -EAGAIN;
+
+	/*
+	 * A dirty page may imply that the underlying filesystem has
+	 * the page on some queue. So the page must be clean for
+	 * migration. Writeout may mean we loose the lock and the
+	 * page state is no longer what we checked for earlier.
+	 * At this point we know that the migration attempt cannot
+	 * be successful.
+	 */
+	remove_migration_ptes(page, page);
+
+	rc = mapping->a_ops->writepage(page, &wbc);
+	if (rc < 0)
+		/* I/O Error writing */
+		return -EIO;
+
+	if (rc != AOP_WRITEPAGE_ACTIVATE)
+		/* unlocked. Relock */
+		lock_page(page);
+
+	return -EAGAIN;
+}
+
+/*
+ * Default handling if a filesystem does not provide a migration function.
+ */
+static int fallback_migrate_page(struct address_space *mapping,
+	struct page *newpage, struct page *page)
+{
+	if (PageDirty(page))
+		return writeout(mapping, page);
+
+	/*
+	 * Buffers may be managed in a filesystem specific way.
+	 * We must have no buffers or drop them.
+	 */
+	if (page_has_buffers(page) &&
+	    !try_to_release_page(page, GFP_KERNEL))
+		return -EAGAIN;
+
+	return migrate_page(mapping, newpage, page);
+}
+
+/*
+ * Move a page to a newly allocated page
+ * The page is locked and all ptes have been successfully removed.
+ *
+ * The new page will have replaced the old page if this function
+ * is successful.
+ */
+static int move_to_new_page(struct page *newpage, struct page *page)
+{
+	struct address_space *mapping;
+	int rc;
+
+	/*
+	 * Block others from accessing the page when we get around to
+	 * establishing additional references. We are the only one
+	 * holding a reference to the new page at this point.
+	 */
+	if (TestSetPageLocked(newpage))
+		BUG();
+
+	/* Prepare mapping for the new page.*/
+	newpage->index = page->index;
+	newpage->mapping = page->mapping;
+
+	mapping = page_mapping(page);
+	if (!mapping)
+		rc = migrate_page(mapping, newpage, page);
+	else if (mapping->a_ops->migratepage)
+		/*
+		 * Most pages have a mapping and most filesystems
+		 * should provide a migration function. Anonymous
+		 * pages are part of swap space which also has its
+		 * own migration function. This is the most common
+		 * path for page migration.
+		 */
+		rc = mapping->a_ops->migratepage(mapping,
+						newpage, page);
+	else
+		rc = fallback_migrate_page(mapping, newpage, page);
+
+	if (!rc)
+		remove_migration_ptes(page, newpage);
+	else
+		newpage->mapping = NULL;
+
+	unlock_page(newpage);
+
+	return rc;
+}
+
+/*
+ * Obtain the lock on page, remove all ptes and migrate the page
+ * to the newly allocated page in newpage.
+ */
+static int unmap_and_move(new_page_t get_new_page, unsigned long private,
+			struct page *page, int force)
+{
+	int rc = 0;
+	int *result = NULL;
+	struct page *newpage = get_new_page(page, private, &result);
+
+	if (!newpage)
+		return -ENOMEM;
+
+	if (page_count(page) == 1)
+		/* page was freed from under us. So we are done. */
+		goto move_newpage;
+
+	rc = -EAGAIN;
+	if (TestSetPageLocked(page)) {
+		if (!force)
+			goto move_newpage;
+		lock_page(page);
+	}
+
+	if (PageWriteback(page)) {
+		if (!force)
+			goto unlock;
+		wait_on_page_writeback(page);
+	}
+
+	/*
+	 * Establish migration ptes or remove ptes
+	 */
+	try_to_unmap(page, 1);
+	if (!page_mapped(page))
+		rc = move_to_new_page(newpage, page);
+
+	if (rc)
+		remove_migration_ptes(page, page);
+
+unlock:
+	unlock_page(page);
+
+	if (rc != -EAGAIN) {
+ 		/*
+ 		 * A page that has been migrated has all references
+ 		 * removed and will be freed. A page that has not been
+ 		 * migrated will have kepts its references and be
+ 		 * restored.
+ 		 */
+ 		list_del(&page->lru);
+ 		move_to_lru(page);
+	}
+
+move_newpage:
+	/*
+	 * Move the new page to the LRU. If migration was not successful
+	 * then this will free the page.
+	 */
+	move_to_lru(newpage);
+	if (result) {
+		if (rc)
+			*result = rc;
 		else
-			page = alloc_pages_node(dest, GFP_HIGHUSER, 0);
+			*result = page_to_nid(newpage);
+	}
+	return rc;
+}
 
-		if (!page) {
-			err = -ENOMEM;
-			goto out;
+/*
+ * migrate_pages
+ *
+ * The function takes one list of pages to migrate and a function
+ * that determines from the page to be migrated and the private data
+ * the target of the move and allocates the page.
+ *
+ * The function returns after 10 attempts or if no pages
+ * are movable anymore because to has become empty
+ * or no retryable pages exist anymore. All pages will be
+ * retruned to the LRU or freed.
+ *
+ * Return: Number of pages not migrated or error code.
+ */
+int migrate_pages(struct list_head *from,
+		new_page_t get_new_page, unsigned long private)
+{
+	int retry = 1;
+	int nr_failed = 0;
+	int pass = 0;
+	struct page *page;
+	struct page *page2;
+	int swapwrite = current->flags & PF_SWAPWRITE;
+	int rc;
+
+	if (!swapwrite)
+		current->flags |= PF_SWAPWRITE;
+
+	for(pass = 0; pass < 10 && retry; pass++) {
+		retry = 0;
+
+		list_for_each_entry_safe(page, page2, from, lru) {
+			cond_resched();
+
+			rc = unmap_and_move(get_new_page, private,
+						page, pass > 2);
+
+			switch(rc) {
+			case -ENOMEM:
+				goto out;
+			case -EAGAIN:
+				retry++;
+				break;
+			case 0:
+				break;
+			default:
+				/* Permanent failure */
+				nr_failed++;
+				break;
+			}
 		}
-		list_add_tail(&page->lru, &newlist);
-		nr_pages++;
-		if (nr_pages > MIGRATE_CHUNK_SIZE)
-			break;
 	}
-	err = migrate_pages(pagelist, &newlist, &moved, &failed);
-
-	putback_lru_pages(&moved);	/* Call release pages instead ?? */
-
-	if (err >= 0 && list_empty(&newlist) && !list_empty(pagelist))
-		goto redo;
+	rc = 0;
 out:
-	/* Return leftover allocated pages */
-	while (!list_empty(&newlist)) {
-		page = list_entry(newlist.next, struct page, lru);
-		list_del(&page->lru);
-		__free_page(page);
-	}
-	list_splice(&failed, pagelist);
-	if (err < 0)
-		return err;
+	if (!swapwrite)
+		current->flags &= ~PF_SWAPWRITE;
 
-	/* Calculate number of leftover pages */
-	nr_pages = 0;
-	list_for_each(p, pagelist)
-		nr_pages++;
-	return nr_pages;
+	putback_lru_pages(from);
+
+	if (rc)
+		return rc;
+
+	return nr_failed + retry;
+}
+
+#ifdef CONFIG_NUMA
+/*
+ * Move a list of individual pages
+ */
+struct page_to_node {
+	unsigned long addr;
+	struct page *page;
+	int node;
+	int status;
+};
+
+static struct page *new_page_node(struct page *p, unsigned long private,
+		int **result)
+{
+	struct page_to_node *pm = (struct page_to_node *)private;
+
+	while (pm->node != MAX_NUMNODES && pm->page != p)
+		pm++;
+
+	if (pm->node == MAX_NUMNODES)
+		return NULL;
+
+	*result = &pm->status;
+
+	return alloc_pages_node(pm->node, GFP_HIGHUSER, 0);
+}
+
+/*
+ * Move a set of pages as indicated in the pm array. The addr
+ * field must be set to the virtual address of the page to be moved
+ * and the node number must contain a valid target node.
+ */
+static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm,
+				int migrate_all)
+{
+	int err;
+	struct page_to_node *pp;
+	LIST_HEAD(pagelist);
+
+	down_read(&mm->mmap_sem);
+
+	/*
+	 * Build a list of pages to migrate
+	 */
+	migrate_prep();
+	for (pp = pm; pp->node != MAX_NUMNODES; pp++) {
+		struct vm_area_struct *vma;
+		struct page *page;
+
+		/*
+		 * A valid page pointer that will not match any of the
+		 * pages that will be moved.
+		 */
+		pp->page = ZERO_PAGE(0);
+
+		err = -EFAULT;
+		vma = find_vma(mm, pp->addr);
+		if (!vma)
+			goto set_status;
+
+		page = follow_page(vma, pp->addr, FOLL_GET);
+		err = -ENOENT;
+		if (!page)
+			goto set_status;
+
+		if (PageReserved(page))		/* Check for zero page */
+			goto put_and_set;
+
+		pp->page = page;
+		err = page_to_nid(page);
+
+		if (err == pp->node)
+			/*
+			 * Node already in the right place
+			 */
+			goto put_and_set;
+
+		err = -EACCES;
+		if (page_mapcount(page) > 1 &&
+				!migrate_all)
+			goto put_and_set;
+
+		err = isolate_lru_page(page, &pagelist);
+put_and_set:
+		/*
+		 * Either remove the duplicate refcount from
+		 * isolate_lru_page() or drop the page ref if it was
+		 * not isolated.
+		 */
+		put_page(page);
+set_status:
+		pp->status = err;
+	}
+
+	if (!list_empty(&pagelist))
+		err = migrate_pages(&pagelist, new_page_node,
+				(unsigned long)pm);
+	else
+		err = -ENOENT;
+
+	up_read(&mm->mmap_sem);
+	return err;
+}
+
+/*
+ * Determine the nodes of a list of pages. The addr in the pm array
+ * must have been set to the virtual address of which we want to determine
+ * the node number.
+ */
+static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm)
+{
+	down_read(&mm->mmap_sem);
+
+	for ( ; pm->node != MAX_NUMNODES; pm++) {
+		struct vm_area_struct *vma;
+		struct page *page;
+		int err;
+
+		err = -EFAULT;
+		vma = find_vma(mm, pm->addr);
+		if (!vma)
+			goto set_status;
+
+		page = follow_page(vma, pm->addr, 0);
+		err = -ENOENT;
+		/* Use PageReserved to check for zero page */
+		if (!page || PageReserved(page))
+			goto set_status;
+
+		err = page_to_nid(page);
+set_status:
+		pm->status = err;
+	}
+
+	up_read(&mm->mmap_sem);
+	return 0;
+}
+
+/*
+ * Move a list of pages in the address space of the currently executing
+ * process.
+ */
+asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
+			const void __user * __user *pages,
+			const int __user *nodes,
+			int __user *status, int flags)
+{
+	int err = 0;
+	int i;
+	struct task_struct *task;
+	nodemask_t task_nodes;
+	struct mm_struct *mm;
+	struct page_to_node *pm = NULL;
+
+	/* Check flags */
+	if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL))
+		return -EINVAL;
+
+	if ((flags & MPOL_MF_MOVE_ALL) && !capable(CAP_SYS_NICE))
+		return -EPERM;
+
+	/* Find the mm_struct */
+	read_lock(&tasklist_lock);
+	task = pid ? find_task_by_pid(pid) : current;
+	if (!task) {
+		read_unlock(&tasklist_lock);
+		return -ESRCH;
+	}
+	mm = get_task_mm(task);
+	read_unlock(&tasklist_lock);
+
+	if (!mm)
+		return -EINVAL;
+
+	/*
+	 * Check if this process has the right to modify the specified
+	 * process. The right exists if the process has administrative
+	 * capabilities, superuser privileges or the same
+	 * userid as the target process.
+	 */
+	if ((current->euid != task->suid) && (current->euid != task->uid) &&
+	    (current->uid != task->suid) && (current->uid != task->uid) &&
+	    !capable(CAP_SYS_NICE)) {
+		err = -EPERM;
+		goto out2;
+	}
+
+ 	err = security_task_movememory(task);
+ 	if (err)
+ 		goto out2;
+
+
+	task_nodes = cpuset_mems_allowed(task);
+
+	/* Limit nr_pages so that the multiplication may not overflow */
+	if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) {
+		err = -E2BIG;
+		goto out2;
+	}
+
+	pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node));
+	if (!pm) {
+		err = -ENOMEM;
+		goto out2;
+	}
+
+	/*
+	 * Get parameters from user space and initialize the pm
+	 * array. Return various errors if the user did something wrong.
+	 */
+	for (i = 0; i < nr_pages; i++) {
+		const void *p;
+
+		err = -EFAULT;
+		if (get_user(p, pages + i))
+			goto out;
+
+		pm[i].addr = (unsigned long)p;
+		if (nodes) {
+			int node;
+
+			if (get_user(node, nodes + i))
+				goto out;
+
+			err = -ENODEV;
+			if (!node_online(node))
+				goto out;
+
+			err = -EACCES;
+			if (!node_isset(node, task_nodes))
+				goto out;
+
+			pm[i].node = node;
+		}
+	}
+	/* End marker */
+	pm[nr_pages].node = MAX_NUMNODES;
+
+	if (nodes)
+		err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL);
+	else
+		err = do_pages_stat(mm, pm);
+
+	if (err >= 0)
+		/* Return status information */
+		for (i = 0; i < nr_pages; i++)
+			if (put_user(pm[i].status, status + i))
+				err = -EFAULT;
+
+out:
+	vfree(pm);
+out2:
+	mmput(mm);
+	return err;
+}
+#endif
+
+/*
+ * Call migration functions in the vma_ops that may prepare
+ * memory in a vm for migration. migration functions may perform
+ * the migration for vmas that do not have an underlying page struct.
+ */
+int migrate_vmas(struct mm_struct *mm, const nodemask_t *to,
+	const nodemask_t *from, unsigned long flags)
+{
+ 	struct vm_area_struct *vma;
+ 	int err = 0;
+
+ 	for(vma = mm->mmap; vma->vm_next && !err; vma = vma->vm_next) {
+ 		if (vma->vm_ops && vma->vm_ops->migrate) {
+ 			err = vma->vm_ops->migrate(vma, to, from, flags);
+ 			if (err)
+ 				break;
+ 		}
+ 	}
+ 	return err;
 }
diff --git a/mm/mmap.c b/mm/mmap.c
index e6ee123..6446c61 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1065,7 +1065,8 @@
 	vma->vm_start = addr;
 	vma->vm_end = addr + len;
 	vma->vm_flags = vm_flags;
-	vma->vm_page_prot = protection_map[vm_flags & 0x0f];
+	vma->vm_page_prot = protection_map[vm_flags &
+				(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
 	vma->vm_pgoff = pgoff;
 
 	if (file) {
@@ -1089,6 +1090,12 @@
 			goto free_vma;
 	}
 
+	/* Don't make the VMA automatically writable if it's shared, but the
+	 * backer wishes to know when pages are first written to */
+	if (vma->vm_ops && vma->vm_ops->page_mkwrite)
+		vma->vm_page_prot =
+			protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC)];
+
 	/* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
 	 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
 	 * that memory reservation must be checked; but that reservation
@@ -1921,7 +1928,8 @@
 	vma->vm_end = addr + len;
 	vma->vm_pgoff = pgoff;
 	vma->vm_flags = flags;
-	vma->vm_page_prot = protection_map[flags & 0x0f];
+	vma->vm_page_prot = protection_map[flags &
+				(VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
 	vma_link(mm, vma, prev, rb_link, rb_parent);
 out:
 	mm->total_vm += len >> PAGE_SHIFT;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 4c14d42..638edab 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -19,7 +19,8 @@
 #include <linux/mempolicy.h>
 #include <linux/personality.h>
 #include <linux/syscalls.h>
-
+#include <linux/swap.h>
+#include <linux/swapops.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
@@ -28,12 +29,13 @@
 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
 		unsigned long addr, unsigned long end, pgprot_t newprot)
 {
-	pte_t *pte;
+	pte_t *pte, oldpte;
 	spinlock_t *ptl;
 
 	pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
 	do {
-		if (pte_present(*pte)) {
+		oldpte = *pte;
+		if (pte_present(oldpte)) {
 			pte_t ptent;
 
 			/* Avoid an SMP race with hardware updated dirty/clean
@@ -43,7 +45,22 @@
 			ptent = pte_modify(ptep_get_and_clear(mm, addr, pte), newprot);
 			set_pte_at(mm, addr, pte, ptent);
 			lazy_mmu_prot_update(ptent);
+#ifdef CONFIG_MIGRATION
+		} else if (!pte_file(oldpte)) {
+			swp_entry_t entry = pte_to_swp_entry(oldpte);
+
+			if (is_write_migration_entry(entry)) {
+				/*
+				 * A protection check is difficult so
+				 * just be safe and disable write
+				 */
+				make_migration_entry_read(&entry);
+				set_pte_at(mm, addr, pte,
+					swp_entry_to_pte(entry));
+			}
+#endif
 		}
+
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 	pte_unmap_unlock(pte - 1, ptl);
 }
@@ -106,6 +123,7 @@
 	unsigned long oldflags = vma->vm_flags;
 	long nrpages = (end - start) >> PAGE_SHIFT;
 	unsigned long charged = 0;
+	unsigned int mask;
 	pgprot_t newprot;
 	pgoff_t pgoff;
 	int error;
@@ -132,8 +150,6 @@
 		}
 	}
 
-	newprot = protection_map[newflags & 0xf];
-
 	/*
 	 * First try to merge with previous and/or next vma.
 	 */
@@ -160,6 +176,14 @@
 	}
 
 success:
+	/* Don't make the VMA automatically writable if it's shared, but the
+	 * backer wishes to know when pages are first written to */
+	mask = VM_READ|VM_WRITE|VM_EXEC|VM_SHARED;
+	if (vma->vm_ops && vma->vm_ops->page_mkwrite)
+		mask &= ~VM_SHARED;
+
+	newprot = protection_map[newflags & mask];
+
 	/*
 	 * vm_flags and vm_page_prot are protected by the mmap_sem
 	 * held in write mode.
@@ -205,8 +229,7 @@
 	/*
 	 * Does the application expect PROT_READ to imply PROT_EXEC:
 	 */
-	if (unlikely((prot & PROT_READ) &&
-			(current->personality & READ_IMPLIES_EXEC)))
+	if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
 		prot |= PROT_EXEC;
 
 	vm_flags = calc_vm_prot_bits(prot);
diff --git a/mm/msync.c b/mm/msync.c
index bc6c953..d083544 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -170,8 +170,6 @@
 	 * just ignore them, but return -ENOMEM at the end.
 	 */
 	down_read(&current->mm->mmap_sem);
-	if (flags & MS_SYNC)
-		current->flags |= PF_SYNCWRITE;
 	vma = find_vma(current->mm, start);
 	if (!vma) {
 		error = -ENOMEM;
@@ -228,7 +226,6 @@
 		}
 	} while (vma && !done);
 out_unlock:
-	current->flags &= ~PF_SYNCWRITE;
 	up_read(&current->mm->mmap_sem);
 out:
 	return error;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 042e643..d46ed0f 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -22,10 +22,11 @@
 #include <linux/jiffies.h>
 #include <linux/cpuset.h>
 
+int sysctl_panic_on_oom;
 /* #define DEBUG */
 
 /**
- * oom_badness - calculate a numeric value for how bad this task has been
+ * badness - calculate a numeric value for how bad this task has been
  * @p: task struct of which task we should calculate
  * @uptime: current uptime in seconds
  *
@@ -200,7 +201,7 @@
 			continue;
 
 		/*
-		 * This is in the process of releasing memory so for wait it
+		 * This is in the process of releasing memory so wait for it
 		 * to finish before killing some other task by mistake.
 		 */
 		releasing = test_tsk_thread_flag(p, TIF_MEMDIE) ||
@@ -306,7 +307,7 @@
 }
 
 /**
- * oom_kill - kill the "best" process when we run out of memory
+ * out_of_memory - kill the "best" process when we run out of memory
  *
  * If we run out of memory, we have the choice between either
  * killing a random task (bad), letting the system crash (worse)
@@ -344,6 +345,8 @@
 		break;
 
 	case CONSTRAINT_NONE:
+		if (sysctl_panic_on_oom)
+			panic("out of memory. panic_on_oom is selected\n");
 retry:
 		/*
 		 * Rambo mode: Shoot down a process and hope it solves whatever
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 75d7f48..4ec7026 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -204,6 +204,7 @@
 			.sync_mode	= WB_SYNC_NONE,
 			.older_than_this = NULL,
 			.nr_to_write	= write_chunk,
+			.range_cyclic	= 1,
 		};
 
 		get_dirty_limits(&wbs, &background_thresh,
@@ -331,6 +332,7 @@
 		.older_than_this = NULL,
 		.nr_to_write	= 0,
 		.nonblocking	= 1,
+		.range_cyclic	= 1,
 	};
 
 	for ( ; ; ) {
@@ -407,6 +409,7 @@
 		.nr_to_write	= 0,
 		.nonblocking	= 1,
 		.for_kupdate	= 1,
+		.range_cyclic	= 1,
 	};
 
 	sync_supers();
@@ -513,14 +516,14 @@
 		ratelimit_pages = (4096 * 1024) / PAGE_CACHE_SIZE;
 }
 
-static int
+static int __cpuinit
 ratelimit_handler(struct notifier_block *self, unsigned long u, void *v)
 {
 	set_ratelimit();
 	return 0;
 }
 
-static struct notifier_block ratelimit_nb = {
+static struct notifier_block __cpuinitdata ratelimit_nb = {
 	.notifier_call	= ratelimit_handler,
 	.next		= NULL,
 };
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 253a450..084a2de 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -37,6 +37,7 @@
 #include <linux/nodemask.h>
 #include <linux/vmalloc.h>
 #include <linux/mempolicy.h>
+#include <linux/stop_machine.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -83,8 +84,8 @@
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "DMA32", "Normal", "HighMem" };
 int min_free_kbytes = 1024;
 
-unsigned long __initdata nr_kernel_pages;
-unsigned long __initdata nr_all_pages;
+unsigned long __meminitdata nr_kernel_pages;
+unsigned long __meminitdata nr_all_pages;
 
 #ifdef CONFIG_DEBUG_VM
 static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
@@ -265,7 +266,7 @@
  * satisfies the following equation:
  *     P = B & ~(1 << O)
  *
- * Assumption: *_mem_map is contigious at least up to MAX_ORDER
+ * Assumption: *_mem_map is contiguous at least up to MAX_ORDER
  */
 static inline struct page *
 __page_find_buddy(struct page *page, unsigned long page_idx, unsigned int order)
@@ -286,22 +287,27 @@
  * we can do coalesce a page and its buddy if
  * (a) the buddy is not in a hole &&
  * (b) the buddy is in the buddy system &&
- * (c) a page and its buddy have the same order.
+ * (c) a page and its buddy have the same order &&
+ * (d) a page and its buddy are in the same zone.
  *
  * For recording whether a page is in the buddy system, we use PG_buddy.
  * Setting, clearing, and testing PG_buddy is serialized by zone->lock.
  *
  * For recording page's order, we use page_private(page).
  */
-static inline int page_is_buddy(struct page *page, int order)
+static inline int page_is_buddy(struct page *page, struct page *buddy,
+								int order)
 {
 #ifdef CONFIG_HOLES_IN_ZONE
-	if (!pfn_valid(page_to_pfn(page)))
+	if (!pfn_valid(page_to_pfn(buddy)))
 		return 0;
 #endif
 
-	if (PageBuddy(page) && page_order(page) == order) {
-		BUG_ON(page_count(page) != 0);
+	if (page_zone_id(page) != page_zone_id(buddy))
+		return 0;
+
+	if (PageBuddy(buddy) && page_order(buddy) == order) {
+		BUG_ON(page_count(buddy) != 0);
 		return 1;
 	}
 	return 0;
@@ -352,7 +358,7 @@
 		struct page *buddy;
 
 		buddy = __page_find_buddy(page, page_idx, order);
-		if (!page_is_buddy(buddy, order))
+		if (!page_is_buddy(page, buddy, order))
 			break;		/* Move the buddy up one level. */
 
 		list_del(&buddy->lru);
@@ -440,8 +446,8 @@
 
 	arch_free_page(page, order);
 	if (!PageHighMem(page))
-		mutex_debug_check_no_locks_freed(page_address(page),
-						 PAGE_SIZE<<order);
+		debug_check_no_locks_freed(page_address(page),
+					   PAGE_SIZE<<order);
 
 	for (i = 0 ; i < (1 << order) ; ++i)
 		reserved += free_pages_check(page + i);
@@ -951,8 +957,7 @@
 		goto got_pg;
 
 	do {
-		if (cpuset_zone_allowed(*z, gfp_mask|__GFP_HARDWALL))
-			wakeup_kswapd(*z, order);
+		wakeup_kswapd(*z, order);
 	} while (*(++z));
 
 	/*
@@ -1485,7 +1490,7 @@
 	}
 
 	for_each_zone(zone) {
- 		unsigned long nr, flags, order, total = 0;
+ 		unsigned long nr[MAX_ORDER], flags, order, total = 0;
 
 		show_node(zone);
 		printk("%s: ", zone->name);
@@ -1496,11 +1501,12 @@
 
 		spin_lock_irqsave(&zone->lock, flags);
 		for (order = 0; order < MAX_ORDER; order++) {
-			nr = zone->free_area[order].nr_free;
-			total += nr << order;
-			printk("%lu*%lukB ", nr, K(1UL) << order);
+			nr[order] = zone->free_area[order].nr_free;
+			total += nr[order] << order;
 		}
 		spin_unlock_irqrestore(&zone->lock, flags);
+		for (order = 0; order < MAX_ORDER; order++)
+			printk("%lu*%lukB ", nr[order], K(1UL) << order);
 		printk("= %lukB\n", K(total));
 	}
 
@@ -1512,7 +1518,7 @@
  *
  * Add all populated zones of a node to the zonelist.
  */
-static int __init build_zonelists_node(pg_data_t *pgdat,
+static int __meminit build_zonelists_node(pg_data_t *pgdat,
 			struct zonelist *zonelist, int nr_zones, int zone_type)
 {
 	struct zone *zone;
@@ -1548,7 +1554,7 @@
 
 #ifdef CONFIG_NUMA
 #define MAX_NODE_LOAD (num_online_nodes())
-static int __initdata node_load[MAX_NUMNODES];
+static int __meminitdata node_load[MAX_NUMNODES];
 /**
  * find_next_best_node - find the next node that should appear in a given node's fallback list
  * @node: node whose fallback list we're appending
@@ -1563,7 +1569,7 @@
  * on them otherwise.
  * It returns -1 if no node is found.
  */
-static int __init find_next_best_node(int node, nodemask_t *used_node_mask)
+static int __meminit find_next_best_node(int node, nodemask_t *used_node_mask)
 {
 	int n, val;
 	int min_val = INT_MAX;
@@ -1609,7 +1615,7 @@
 	return best_node;
 }
 
-static void __init build_zonelists(pg_data_t *pgdat)
+static void __meminit build_zonelists(pg_data_t *pgdat)
 {
 	int i, j, k, node, local_node;
 	int prev_node, load;
@@ -1661,7 +1667,7 @@
 
 #else	/* CONFIG_NUMA */
 
-static void __init build_zonelists(pg_data_t *pgdat)
+static void __meminit build_zonelists(pg_data_t *pgdat)
 {
 	int i, j, k, node, local_node;
 
@@ -1699,14 +1705,29 @@
 
 #endif	/* CONFIG_NUMA */
 
-void __init build_all_zonelists(void)
+/* return values int ....just for stop_machine_run() */
+static int __meminit __build_all_zonelists(void *dummy)
 {
-	int i;
+	int nid;
+	for_each_online_node(nid)
+		build_zonelists(NODE_DATA(nid));
+	return 0;
+}
 
-	for_each_online_node(i)
-		build_zonelists(NODE_DATA(i));
-	printk("Built %i zonelists\n", num_online_nodes());
-	cpuset_init_current_mems_allowed();
+void __meminit build_all_zonelists(void)
+{
+	if (system_state == SYSTEM_BOOTING) {
+		__build_all_zonelists(0);
+		cpuset_init_current_mems_allowed();
+	} else {
+		/* we have to stop all cpus to guaranntee there is no user
+		   of zonelist */
+		stop_machine_run(__build_all_zonelists, NULL, NR_CPUS);
+		/* cpuset refresh routine should be here */
+	}
+	vm_total_pages = nr_free_pagecache_pages();
+	printk("Built %i zonelists.  Total pages: %ld\n",
+			num_online_nodes(), vm_total_pages);
 }
 
 /*
@@ -1722,7 +1743,8 @@
  */
 #define PAGES_PER_WAITQUEUE	256
 
-static inline unsigned long wait_table_size(unsigned long pages)
+#ifndef CONFIG_MEMORY_HOTPLUG
+static inline unsigned long wait_table_hash_nr_entries(unsigned long pages)
 {
 	unsigned long size = 1;
 
@@ -1740,6 +1762,29 @@
 
 	return max(size, 4UL);
 }
+#else
+/*
+ * A zone's size might be changed by hot-add, so it is not possible to determine
+ * a suitable size for its wait_table.  So we use the maximum size now.
+ *
+ * The max wait table size = 4096 x sizeof(wait_queue_head_t).   ie:
+ *
+ *    i386 (preemption config)    : 4096 x 16 = 64Kbyte.
+ *    ia64, x86-64 (no preemption): 4096 x 20 = 80Kbyte.
+ *    ia64, x86-64 (preemption)   : 4096 x 24 = 96Kbyte.
+ *
+ * The maximum entries are prepared when a zone's memory is (512K + 256) pages
+ * or more by the traditional way. (See above).  It equals:
+ *
+ *    i386, x86-64, powerpc(4K page size) : =  ( 2G + 1M)byte.
+ *    ia64(16K page size)                 : =  ( 8G + 4M)byte.
+ *    powerpc (64K page size)             : =  (32G +16M)byte.
+ */
+static inline unsigned long wait_table_hash_nr_entries(unsigned long pages)
+{
+	return 4096UL;
+}
+#endif
 
 /*
  * This is an integer logarithm so that shifts can be used later
@@ -1964,7 +2009,7 @@
 	}
 }
 
-static int pageset_cpuup_callback(struct notifier_block *nfb,
+static int __cpuinit pageset_cpuup_callback(struct notifier_block *nfb,
 		unsigned long action,
 		void *hcpu)
 {
@@ -1986,7 +2031,7 @@
 	return ret;
 }
 
-static struct notifier_block pageset_notifier =
+static struct notifier_block __cpuinitdata pageset_notifier =
 	{ &pageset_cpuup_callback, NULL, 0 };
 
 void __init setup_per_cpu_pageset(void)
@@ -2005,23 +2050,46 @@
 #endif
 
 static __meminit
-void zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
+int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages)
 {
 	int i;
 	struct pglist_data *pgdat = zone->zone_pgdat;
+	size_t alloc_size;
 
 	/*
 	 * The per-page waitqueue mechanism uses hashed waitqueues
 	 * per zone.
 	 */
-	zone->wait_table_size = wait_table_size(zone_size_pages);
-	zone->wait_table_bits =	wait_table_bits(zone->wait_table_size);
-	zone->wait_table = (wait_queue_head_t *)
-		alloc_bootmem_node(pgdat, zone->wait_table_size
-					* sizeof(wait_queue_head_t));
+	zone->wait_table_hash_nr_entries =
+		 wait_table_hash_nr_entries(zone_size_pages);
+	zone->wait_table_bits =
+		wait_table_bits(zone->wait_table_hash_nr_entries);
+	alloc_size = zone->wait_table_hash_nr_entries
+					* sizeof(wait_queue_head_t);
 
-	for(i = 0; i < zone->wait_table_size; ++i)
+ 	if (system_state == SYSTEM_BOOTING) {
+		zone->wait_table = (wait_queue_head_t *)
+			alloc_bootmem_node(pgdat, alloc_size);
+	} else {
+		/*
+		 * This case means that a zone whose size was 0 gets new memory
+		 * via memory hot-add.
+		 * But it may be the case that a new node was hot-added.  In
+		 * this case vmalloc() will not be able to use this new node's
+		 * memory - this wait_table must be initialized to use this new
+		 * node itself as well.
+		 * To use this new node's memory, further consideration will be
+		 * necessary.
+		 */
+		zone->wait_table = (wait_queue_head_t *)vmalloc(alloc_size);
+	}
+	if (!zone->wait_table)
+		return -ENOMEM;
+
+	for(i = 0; i < zone->wait_table_hash_nr_entries; ++i)
 		init_waitqueue_head(zone->wait_table + i);
+
+	return 0;
 }
 
 static __meminit void zone_pcp_init(struct zone *zone)
@@ -2043,12 +2111,15 @@
 			zone->name, zone->present_pages, batch);
 }
 
-static __meminit void init_currently_empty_zone(struct zone *zone,
-		unsigned long zone_start_pfn, unsigned long size)
+__meminit int init_currently_empty_zone(struct zone *zone,
+					unsigned long zone_start_pfn,
+					unsigned long size)
 {
 	struct pglist_data *pgdat = zone->zone_pgdat;
-
-	zone_wait_table_init(zone, size);
+	int ret;
+	ret = zone_wait_table_init(zone, size);
+	if (ret)
+		return ret;
 	pgdat->nr_zones = zone_idx(zone) + 1;
 
 	zone->zone_start_pfn = zone_start_pfn;
@@ -2056,6 +2127,8 @@
 	memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn);
 
 	zone_init_free_lists(pgdat, zone, zone->spanned_pages);
+
+	return 0;
 }
 
 /*
@@ -2064,12 +2137,13 @@
  *   - mark all memory queues empty
  *   - clear the memory bitmaps
  */
-static void __init free_area_init_core(struct pglist_data *pgdat,
+static void __meminit free_area_init_core(struct pglist_data *pgdat,
 		unsigned long *zones_size, unsigned long *zholes_size)
 {
 	unsigned long j;
 	int nid = pgdat->node_id;
 	unsigned long zone_start_pfn = pgdat->node_start_pfn;
+	int ret;
 
 	pgdat_resize_init(pgdat);
 	pgdat->nr_zones = 0;
@@ -2111,7 +2185,8 @@
 			continue;
 
 		zonetable_add(zone, nid, j, zone_start_pfn, size);
-		init_currently_empty_zone(zone, zone_start_pfn, size);
+		ret = init_currently_empty_zone(zone, zone_start_pfn, size);
+		BUG_ON(ret);
 		zone_start_pfn += size;
 	}
 }
@@ -2152,7 +2227,7 @@
 #endif /* CONFIG_FLAT_NODE_MEM_MAP */
 }
 
-void __init free_area_init_node(int nid, struct pglist_data *pgdat,
+void __meminit free_area_init_node(int nid, struct pglist_data *pgdat,
 		unsigned long *zones_size, unsigned long node_start_pfn,
 		unsigned long *zholes_size)
 {
@@ -2804,42 +2879,14 @@
 }
 
 #ifdef CONFIG_OUT_OF_LINE_PFN_TO_PAGE
-/*
- * pfn <-> page translation. out-of-line version.
- * (see asm-generic/memory_model.h)
- */
-#if defined(CONFIG_FLATMEM)
 struct page *pfn_to_page(unsigned long pfn)
 {
-	return mem_map + (pfn - ARCH_PFN_OFFSET);
+	return __pfn_to_page(pfn);
 }
 unsigned long page_to_pfn(struct page *page)
 {
-	return (page - mem_map) + ARCH_PFN_OFFSET;
+	return __page_to_pfn(page);
 }
-#elif defined(CONFIG_DISCONTIGMEM)
-struct page *pfn_to_page(unsigned long pfn)
-{
-	int nid = arch_pfn_to_nid(pfn);
-	return NODE_DATA(nid)->node_mem_map + arch_local_page_offset(pfn,nid);
-}
-unsigned long page_to_pfn(struct page *page)
-{
-	struct pglist_data *pgdat = NODE_DATA(page_to_nid(page));
-	return (page - pgdat->node_mem_map) + pgdat->node_start_pfn;
-}
-#elif defined(CONFIG_SPARSEMEM)
-struct page *pfn_to_page(unsigned long pfn)
-{
-	return __section_mem_map_addr(__pfn_to_section(pfn)) + pfn;
-}
-
-unsigned long page_to_pfn(struct page *page)
-{
-	long section_id = page_to_section(page);
-	return page - __section_mem_map_addr(__nr_to_section(section_id));
-}
-#endif /* CONFIG_FLATMEM/DISCONTIGMME/SPARSEMEM */
 EXPORT_SYMBOL(pfn_to_page);
 EXPORT_SYMBOL(page_to_pfn);
 #endif /* CONFIG_OUT_OF_LINE_PFN_TO_PAGE */
diff --git a/mm/pdflush.c b/mm/pdflush.c
index c4b6d0a..b02102f 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -104,21 +104,20 @@
 		list_move(&my_work->list, &pdflush_list);
 		my_work->when_i_went_to_sleep = jiffies;
 		spin_unlock_irq(&pdflush_lock);
-
 		schedule();
-		if (try_to_freeze()) {
-			spin_lock_irq(&pdflush_lock);
-			continue;
-		}
-
+		try_to_freeze();
 		spin_lock_irq(&pdflush_lock);
 		if (!list_empty(&my_work->list)) {
-			printk("pdflush: bogus wakeup!\n");
+			/*
+			 * Someone woke us up, but without removing our control
+			 * structure from the global list.  swsusp will do this
+			 * in try_to_freeze()->refrigerator().  Handle it.
+			 */
 			my_work->fn = NULL;
 			continue;
 		}
 		if (my_work->fn == NULL) {
-			printk("pdflush: NULL work function\n");
+			printk("pdflush: bogus wakeup\n");
 			continue;
 		}
 		spin_unlock_irq(&pdflush_lock);
@@ -202,8 +201,7 @@
 	unsigned long flags;
 	int ret = 0;
 
-	if (fn == NULL)
-		BUG();		/* Hard to diagnose if it's deferred */
+	BUG_ON(fn == NULL);	/* Hard to diagnose if it's deferred */
 
 	spin_lock_irqsave(&pdflush_lock, flags);
 	if (list_empty(&pdflush_list)) {
diff --git a/mm/readahead.c b/mm/readahead.c
index 0f142a4..aa7ec42 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -118,8 +118,7 @@
 #define list_to_page(head) (list_entry((head)->prev, struct page, lru))
 
 /**
- * read_cache_pages - populate an address space with some pages, and
- * 			start reads against them.
+ * read_cache_pages - populate an address space with some pages & start reads against them
  * @mapping: the address_space
  * @pages: The address of a list_head which contains the target pages.  These
  *   pages have their ->index populated and are otherwise uninitialised.
@@ -182,14 +181,11 @@
 		list_del(&page->lru);
 		if (!add_to_page_cache(page, mapping,
 					page->index, GFP_KERNEL)) {
-			ret = mapping->a_ops->readpage(filp, page);
-			if (ret != AOP_TRUNCATED_PAGE) {
-				if (!pagevec_add(&lru_pvec, page))
-					__pagevec_lru_add(&lru_pvec);
-				continue;
-			} /* else fall through to release */
-		}
-		page_cache_release(page);
+			mapping->a_ops->readpage(filp, page);
+			if (!pagevec_add(&lru_pvec, page))
+				__pagevec_lru_add(&lru_pvec);
+		} else
+			page_cache_release(page);
 	}
 	pagevec_lru_add(&lru_pvec);
 	ret = 0;
@@ -394,8 +390,8 @@
  * Read 'nr_to_read' pages starting at page 'offset'. If the flag 'block'
  * is set wait till the read completes.  Otherwise attempt to read without
  * blocking.
- * Returns 1 meaning 'success' if read is succesfull without switching off
- * readhaead mode. Otherwise return failure.
+ * Returns 1 meaning 'success' if read is successful without switching off
+ * readahead mode. Otherwise return failure.
  */
 static int
 blockable_page_cache_readahead(struct address_space *mapping, struct file *filp,
diff --git a/mm/rmap.c b/mm/rmap.c
index 1963e26..e76909e 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -103,7 +103,7 @@
 		spin_lock(&mm->page_table_lock);
 		if (likely(!vma->anon_vma)) {
 			vma->anon_vma = anon_vma;
-			list_add(&vma->anon_vma_node, &anon_vma->head);
+			list_add_tail(&vma->anon_vma_node, &anon_vma->head);
 			allocated = NULL;
 		}
 		spin_unlock(&mm->page_table_lock);
@@ -127,7 +127,7 @@
 	struct anon_vma *anon_vma = vma->anon_vma;
 
 	if (anon_vma) {
-		list_add(&vma->anon_vma_node, &anon_vma->head);
+		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
 		validate_anon_vma(vma);
 	}
 }
@@ -138,7 +138,7 @@
 
 	if (anon_vma) {
 		spin_lock(&anon_vma->lock);
-		list_add(&vma->anon_vma_node, &anon_vma->head);
+		list_add_tail(&vma->anon_vma_node, &anon_vma->head);
 		validate_anon_vma(vma);
 		spin_unlock(&anon_vma->lock);
 	}
@@ -205,44 +205,6 @@
 	return anon_vma;
 }
 
-#ifdef CONFIG_MIGRATION
-/*
- * Remove an anonymous page from swap replacing the swap pte's
- * through real pte's pointing to valid pages and then releasing
- * the page from the swap cache.
- *
- * Must hold page lock on page and mmap_sem of one vma that contains
- * the page.
- */
-void remove_from_swap(struct page *page)
-{
-	struct anon_vma *anon_vma;
-	struct vm_area_struct *vma;
-	unsigned long mapping;
-
-	if (!PageSwapCache(page))
-		return;
-
-	mapping = (unsigned long)page->mapping;
-
-	if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0)
-		return;
-
-	/*
-	 * We hold the mmap_sem lock. So no need to call page_lock_anon_vma.
-	 */
-	anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON);
-	spin_lock(&anon_vma->lock);
-
-	list_for_each_entry(vma, &anon_vma->head, anon_vma_node)
-		remove_vma_swap(vma, page);
-
-	spin_unlock(&anon_vma->lock);
-	delete_from_swap_cache(page);
-}
-EXPORT_SYMBOL(remove_from_swap);
-#endif
-
 /*
  * At what user virtual address is page expected in vma?
  */
@@ -578,7 +540,7 @@
  * repeatedly from either try_to_unmap_anon or try_to_unmap_file.
  */
 static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
-				int ignore_refs)
+				int migration)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long address;
@@ -600,9 +562,8 @@
 	 * If it's recently referenced (perhaps page_referenced
 	 * skipped over this mm) then we should reactivate it.
 	 */
-	if ((vma->vm_flags & VM_LOCKED) ||
-			(ptep_clear_flush_young(vma, address, pte)
-				&& !ignore_refs)) {
+	if (!migration && ((vma->vm_flags & VM_LOCKED) ||
+			(ptep_clear_flush_young(vma, address, pte)))) {
 		ret = SWAP_FAIL;
 		goto out_unmap;
 	}
@@ -620,24 +581,45 @@
 
 	if (PageAnon(page)) {
 		swp_entry_t entry = { .val = page_private(page) };
-		/*
-		 * Store the swap location in the pte.
-		 * See handle_pte_fault() ...
-		 */
-		BUG_ON(!PageSwapCache(page));
-		swap_duplicate(entry);
-		if (list_empty(&mm->mmlist)) {
-			spin_lock(&mmlist_lock);
-			if (list_empty(&mm->mmlist))
-				list_add(&mm->mmlist, &init_mm.mmlist);
-			spin_unlock(&mmlist_lock);
+
+		if (PageSwapCache(page)) {
+			/*
+			 * Store the swap location in the pte.
+			 * See handle_pte_fault() ...
+			 */
+			swap_duplicate(entry);
+			if (list_empty(&mm->mmlist)) {
+				spin_lock(&mmlist_lock);
+				if (list_empty(&mm->mmlist))
+					list_add(&mm->mmlist, &init_mm.mmlist);
+				spin_unlock(&mmlist_lock);
+			}
+			dec_mm_counter(mm, anon_rss);
+#ifdef CONFIG_MIGRATION
+		} else {
+			/*
+			 * Store the pfn of the page in a special migration
+			 * pte. do_swap_page() will wait until the migration
+			 * pte is removed and then restart fault handling.
+			 */
+			BUG_ON(!migration);
+			entry = make_migration_entry(page, pte_write(pteval));
+#endif
 		}
 		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
 		BUG_ON(pte_file(*pte));
-		dec_mm_counter(mm, anon_rss);
 	} else
+#ifdef CONFIG_MIGRATION
+	if (migration) {
+		/* Establish migration entry for a file page */
+		swp_entry_t entry;
+		entry = make_migration_entry(page, pte_write(pteval));
+		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
+	} else
+#endif
 		dec_mm_counter(mm, file_rss);
 
+
 	page_remove_rmap(page);
 	page_cache_release(page);
 
@@ -736,7 +718,7 @@
 	pte_unmap_unlock(pte - 1, ptl);
 }
 
-static int try_to_unmap_anon(struct page *page, int ignore_refs)
+static int try_to_unmap_anon(struct page *page, int migration)
 {
 	struct anon_vma *anon_vma;
 	struct vm_area_struct *vma;
@@ -747,7 +729,7 @@
 		return ret;
 
 	list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
-		ret = try_to_unmap_one(page, vma, ignore_refs);
+		ret = try_to_unmap_one(page, vma, migration);
 		if (ret == SWAP_FAIL || !page_mapped(page))
 			break;
 	}
@@ -764,7 +746,7 @@
  *
  * This function is only called from try_to_unmap for object-based pages.
  */
-static int try_to_unmap_file(struct page *page, int ignore_refs)
+static int try_to_unmap_file(struct page *page, int migration)
 {
 	struct address_space *mapping = page->mapping;
 	pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
@@ -778,7 +760,7 @@
 
 	spin_lock(&mapping->i_mmap_lock);
 	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
-		ret = try_to_unmap_one(page, vma, ignore_refs);
+		ret = try_to_unmap_one(page, vma, migration);
 		if (ret == SWAP_FAIL || !page_mapped(page))
 			goto out;
 	}
@@ -788,7 +770,7 @@
 
 	list_for_each_entry(vma, &mapping->i_mmap_nonlinear,
 						shared.vm_set.list) {
-		if (vma->vm_flags & VM_LOCKED)
+		if ((vma->vm_flags & VM_LOCKED) && !migration)
 			continue;
 		cursor = (unsigned long) vma->vm_private_data;
 		if (cursor > max_nl_cursor)
@@ -822,7 +804,7 @@
 	do {
 		list_for_each_entry(vma, &mapping->i_mmap_nonlinear,
 						shared.vm_set.list) {
-			if (vma->vm_flags & VM_LOCKED)
+			if ((vma->vm_flags & VM_LOCKED) && !migration)
 				continue;
 			cursor = (unsigned long) vma->vm_private_data;
 			while ( cursor < max_nl_cursor &&
@@ -863,16 +845,16 @@
  * SWAP_AGAIN	- we missed a mapping, try again later
  * SWAP_FAIL	- the page is unswappable
  */
-int try_to_unmap(struct page *page, int ignore_refs)
+int try_to_unmap(struct page *page, int migration)
 {
 	int ret;
 
 	BUG_ON(!PageLocked(page));
 
 	if (PageAnon(page))
-		ret = try_to_unmap_anon(page, ignore_refs);
+		ret = try_to_unmap_anon(page, migration);
 	else
-		ret = try_to_unmap_file(page, ignore_refs);
+		ret = try_to_unmap_file(page, migration);
 
 	if (!page_mapped(page))
 		ret = SWAP_SUCCESS;
diff --git a/mm/shmem.c b/mm/shmem.c
index 1e43c8a..ea64c07 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -174,7 +174,7 @@
 }
 
 static struct super_operations shmem_ops;
-static struct address_space_operations shmem_aops;
+static const struct address_space_operations shmem_aops;
 static struct file_operations shmem_file_operations;
 static struct inode_operations shmem_inode_operations;
 static struct inode_operations shmem_dir_inode_operations;
@@ -1081,14 +1081,6 @@
 			page_cache_release(swappage);
 			goto repeat;
 		}
-		if (!PageSwapCache(swappage)) {
-			/* Page migration has occured */
-			shmem_swp_unmap(entry);
-			spin_unlock(&info->lock);
-			unlock_page(swappage);
-			page_cache_release(swappage);
-			goto repeat;
-		}
 		if (PageWriteback(swappage)) {
 			shmem_swp_unmap(entry);
 			spin_unlock(&info->lock);
@@ -1654,9 +1646,9 @@
 	return desc.error;
 }
 
-static int shmem_statfs(struct super_block *sb, struct kstatfs *buf)
+static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
-	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
+	struct shmem_sb_info *sbinfo = SHMEM_SB(dentry->d_sb);
 
 	buf->f_type = TMPFS_MAGIC;
 	buf->f_bsize = PAGE_CACHE_SIZE;
@@ -2170,7 +2162,7 @@
 		printk(KERN_INFO "shmem_inode_cache: not all structures were freed\n");
 }
 
-static struct address_space_operations shmem_aops = {
+static const struct address_space_operations shmem_aops = {
 	.writepage	= shmem_writepage,
 	.set_page_dirty	= __set_page_dirty_nobuffers,
 #ifdef CONFIG_TMPFS
@@ -2233,10 +2225,10 @@
 };
 
 
-static struct super_block *shmem_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int shmem_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_nodev(fs_type, flags, data, shmem_fill_super);
+	return get_sb_nodev(fs_type, flags, data, shmem_fill_super, mnt);
 }
 
 static struct file_system_type tmpfs_fs_type = {
@@ -2263,7 +2255,7 @@
 #ifdef CONFIG_TMPFS
 	devfs_mk_dir("shm");
 #endif
-	shm_mnt = do_kern_mount(tmpfs_fs_type.name, MS_NOUSER,
+	shm_mnt = vfs_kern_mount(&tmpfs_fs_type, MS_NOUSER,
 				tmpfs_fs_type.name, NULL);
 	if (IS_ERR(shm_mnt)) {
 		error = PTR_ERR(shm_mnt);
diff --git a/mm/slab.c b/mm/slab.c
index f1b644e..233e39d 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -89,6 +89,7 @@
 #include	<linux/config.h>
 #include	<linux/slab.h>
 #include	<linux/mm.h>
+#include	<linux/poison.h>
 #include	<linux/swap.h>
 #include	<linux/cache.h>
 #include	<linux/interrupt.h>
@@ -106,6 +107,7 @@
 #include	<linux/nodemask.h>
 #include	<linux/mempolicy.h>
 #include	<linux/mutex.h>
+#include	<linux/rtmutex.h>
 
 #include	<asm/uaccess.h>
 #include	<asm/cacheflush.h>
@@ -331,6 +333,8 @@
 	return 0;
 }
 
+static int slab_early_init = 1;
+
 #define INDEX_AC index_of(sizeof(struct arraycache_init))
 #define INDEX_L3 index_of(sizeof(struct kmem_list3))
 
@@ -490,17 +494,6 @@
 #endif
 
 #if DEBUG
-/*
- * Magic nums for obj red zoning.
- * Placed in the first word before and the first word after an obj.
- */
-#define	RED_INACTIVE	0x5A2CF071UL	/* when obj is inactive */
-#define	RED_ACTIVE	0x170FC2A5UL	/* when obj is active */
-
-/* ...and for poisoning */
-#define	POISON_INUSE	0x5a	/* for use-uninitialised poisoning */
-#define POISON_FREE	0x6b	/* for use-after-free poisoning */
-#define	POISON_END	0xa5	/* end-byte of poisoning */
 
 /*
  * memory layout of objects:
@@ -592,6 +585,7 @@
 {
 	if (unlikely(PageCompound(page)))
 		page = (struct page *)page_private(page);
+	BUG_ON(!PageSlab(page));
 	return (struct kmem_cache *)page->lru.next;
 }
 
@@ -604,6 +598,7 @@
 {
 	if (unlikely(PageCompound(page)))
 		page = (struct page *)page_private(page);
+	BUG_ON(!PageSlab(page));
 	return (struct slab *)page->lru.prev;
 }
 
@@ -1024,6 +1019,40 @@
 		}
 	}
 }
+
+static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
+{
+	struct slab *slabp = virt_to_slab(objp);
+	int nodeid = slabp->nodeid;
+	struct kmem_list3 *l3;
+	struct array_cache *alien = NULL;
+
+	/*
+	 * Make sure we are not freeing a object from another node to the array
+	 * cache on this cpu.
+	 */
+	if (likely(slabp->nodeid == numa_node_id()))
+		return 0;
+
+	l3 = cachep->nodelists[numa_node_id()];
+	STATS_INC_NODEFREES(cachep);
+	if (l3->alien && l3->alien[nodeid]) {
+		alien = l3->alien[nodeid];
+		spin_lock(&alien->lock);
+		if (unlikely(alien->avail == alien->limit)) {
+			STATS_INC_ACOVERFLOW(cachep);
+			__drain_alien_cache(cachep, alien, nodeid);
+		}
+		alien->entry[alien->avail++] = objp;
+		spin_unlock(&alien->lock);
+	} else {
+		spin_lock(&(cachep->nodelists[nodeid])->list_lock);
+		free_block(cachep, &objp, 1, nodeid);
+		spin_unlock(&(cachep->nodelists[nodeid])->list_lock);
+	}
+	return 1;
+}
+
 #else
 
 #define drain_alien_cache(cachep, alien) do { } while (0)
@@ -1038,9 +1067,14 @@
 {
 }
 
+static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
+{
+	return 0;
+}
+
 #endif
 
-static int cpuup_callback(struct notifier_block *nfb,
+static int __devinit cpuup_callback(struct notifier_block *nfb,
 				    unsigned long action, void *hcpu)
 {
 	long cpu = (long)hcpu;
@@ -1222,7 +1256,9 @@
 	return NOTIFY_BAD;
 }
 
-static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 };
+static struct notifier_block __cpuinitdata cpucache_notifier = {
+	&cpuup_callback, NULL, 0
+};
 
 /*
  * swap the static kmem_list3 with kmalloced memory
@@ -1335,6 +1371,8 @@
 				NULL, NULL);
 	}
 
+	slab_early_init = 0;
+
 	while (sizes->cs_size != ULONG_MAX) {
 		/*
 		 * For performance, all the general caches are L1 aligned.
@@ -1450,31 +1488,29 @@
 static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
 	struct page *page;
-	void *addr;
+	int nr_pages;
 	int i;
 
-	flags |= cachep->gfpflags;
 #ifndef CONFIG_MMU
-	/* nommu uses slab's for process anonymous memory allocations, so
-	 * requires __GFP_COMP to properly refcount higher order allocations"
+	/*
+	 * Nommu uses slab's for process anonymous memory allocations, and thus
+	 * requires __GFP_COMP to properly refcount higher order allocations
 	 */
-	page = alloc_pages_node(nodeid, (flags | __GFP_COMP), cachep->gfporder);
-#else
-	page = alloc_pages_node(nodeid, flags, cachep->gfporder);
+	flags |= __GFP_COMP;
 #endif
+	flags |= cachep->gfpflags;
+
+	page = alloc_pages_node(nodeid, flags, cachep->gfporder);
 	if (!page)
 		return NULL;
-	addr = page_address(page);
 
-	i = (1 << cachep->gfporder);
+	nr_pages = (1 << cachep->gfporder);
 	if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
-		atomic_add(i, &slab_reclaim_pages);
-	add_page_state(nr_slab, i);
-	while (i--) {
-		__SetPageSlab(page);
-		page++;
-	}
-	return addr;
+		atomic_add(nr_pages, &slab_reclaim_pages);
+	add_page_state(nr_slab, nr_pages);
+	for (i = 0; i < nr_pages; i++)
+		__SetPageSlab(page + i);
+	return page_address(page);
 }
 
 /*
@@ -1913,8 +1949,7 @@
 	void (*dtor)(void*, struct kmem_cache *, unsigned long))
 {
 	size_t left_over, slab_size, ralign;
-	struct kmem_cache *cachep = NULL;
-	struct list_head *p;
+	struct kmem_cache *cachep = NULL, *pc;
 
 	/*
 	 * Sanity checks... these are all serious usage bugs.
@@ -1934,8 +1969,7 @@
 
 	mutex_lock(&cache_chain_mutex);
 
-	list_for_each(p, &cache_chain) {
-		struct kmem_cache *pc = list_entry(p, struct kmem_cache, next);
+	list_for_each_entry(pc, &cache_chain, next) {
 		mm_segment_t old_fs = get_fs();
 		char tmp;
 		int res;
@@ -2069,8 +2103,12 @@
 #endif
 #endif
 
-	/* Determine if the slab management is 'on' or 'off' slab. */
-	if (size >= (PAGE_SIZE >> 3))
+	/*
+	 * Determine if the slab management is 'on' or 'off' slab.
+	 * (bootstrapping cannot cope with offslab caches so don't do
+	 * it too early on.)
+	 */
+	if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init)
 		/*
 		 * Size is large, assume best to place the slab management obj
 		 * off-slab (should allow better packing of objs).
@@ -2460,23 +2498,28 @@
 	slabp->inuse--;
 }
 
-static void set_slab_attr(struct kmem_cache *cachep, struct slab *slabp,
-			void *objp)
+/*
+ * Map pages beginning at addr to the given cache and slab. This is required
+ * for the slab allocator to be able to lookup the cache and slab of a
+ * virtual address for kfree, ksize, kmem_ptr_validate, and slab debugging.
+ */
+static void slab_map_pages(struct kmem_cache *cache, struct slab *slab,
+			   void *addr)
 {
-	int i;
+	int nr_pages;
 	struct page *page;
 
-	/* Nasty!!!!!! I hope this is OK. */
-	page = virt_to_page(objp);
+	page = virt_to_page(addr);
 
-	i = 1;
+	nr_pages = 1;
 	if (likely(!PageCompound(page)))
-		i <<= cachep->gfporder;
+		nr_pages <<= cache->gfporder;
+
 	do {
-		page_set_cache(page, cachep);
-		page_set_slab(page, slabp);
+		page_set_cache(page, cache);
+		page_set_slab(page, slab);
 		page++;
-	} while (--i);
+	} while (--nr_pages);
 }
 
 /*
@@ -2548,7 +2591,7 @@
 		goto opps1;
 
 	slabp->nodeid = nodeid;
-	set_slab_attr(cachep, slabp, objp);
+	slab_map_pages(cachep, slabp, objp);
 
 	cache_init_objs(cachep, slabp, ctor_flags);
 
@@ -2596,6 +2639,28 @@
 	}
 }
 
+static inline void verify_redzone_free(struct kmem_cache *cache, void *obj)
+{
+	unsigned long redzone1, redzone2;
+
+	redzone1 = *dbg_redzone1(cache, obj);
+	redzone2 = *dbg_redzone2(cache, obj);
+
+	/*
+	 * Redzone is ok.
+	 */
+	if (redzone1 == RED_ACTIVE && redzone2 == RED_ACTIVE)
+		return;
+
+	if (redzone1 == RED_INACTIVE && redzone2 == RED_INACTIVE)
+		slab_error(cache, "double free detected");
+	else
+		slab_error(cache, "memory outside object was overwritten");
+
+	printk(KERN_ERR "%p: redzone 1:0x%lx, redzone 2:0x%lx.\n",
+			obj, redzone1, redzone2);
+}
+
 static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp,
 				   void *caller)
 {
@@ -2607,27 +2672,10 @@
 	kfree_debugcheck(objp);
 	page = virt_to_page(objp);
 
-	if (page_get_cache(page) != cachep) {
-		printk(KERN_ERR "mismatch in kmem_cache_free: expected "
-				"cache %p, got %p\n",
-		       page_get_cache(page), cachep);
-		printk(KERN_ERR "%p is %s.\n", cachep, cachep->name);
-		printk(KERN_ERR "%p is %s.\n", page_get_cache(page),
-		       page_get_cache(page)->name);
-		WARN_ON(1);
-	}
 	slabp = page_get_slab(page);
 
 	if (cachep->flags & SLAB_RED_ZONE) {
-		if (*dbg_redzone1(cachep, objp) != RED_ACTIVE ||
-				*dbg_redzone2(cachep, objp) != RED_ACTIVE) {
-			slab_error(cachep, "double free, or memory outside"
-						" object was overwritten");
-			printk(KERN_ERR "%p: redzone 1:0x%lx, "
-					"redzone 2:0x%lx.\n",
-			       objp, *dbg_redzone1(cachep, objp),
-			       *dbg_redzone2(cachep, objp));
-		}
+		verify_redzone_free(cachep, objp);
 		*dbg_redzone1(cachep, objp) = RED_INACTIVE;
 		*dbg_redzone2(cachep, objp) = RED_INACTIVE;
 	}
@@ -3087,41 +3135,9 @@
 	check_irq_off();
 	objp = cache_free_debugcheck(cachep, objp, __builtin_return_address(0));
 
-	/* Make sure we are not freeing a object from another
-	 * node to the array cache on this cpu.
-	 */
-#ifdef CONFIG_NUMA
-	{
-		struct slab *slabp;
-		slabp = virt_to_slab(objp);
-		if (unlikely(slabp->nodeid != numa_node_id())) {
-			struct array_cache *alien = NULL;
-			int nodeid = slabp->nodeid;
-			struct kmem_list3 *l3;
+	if (cache_free_alien(cachep, objp))
+		return;
 
-			l3 = cachep->nodelists[numa_node_id()];
-			STATS_INC_NODEFREES(cachep);
-			if (l3->alien && l3->alien[nodeid]) {
-				alien = l3->alien[nodeid];
-				spin_lock(&alien->lock);
-				if (unlikely(alien->avail == alien->limit)) {
-					STATS_INC_ACOVERFLOW(cachep);
-					__drain_alien_cache(cachep,
-							    alien, nodeid);
-				}
-				alien->entry[alien->avail++] = objp;
-				spin_unlock(&alien->lock);
-			} else {
-				spin_lock(&(cachep->nodelists[nodeid])->
-					  list_lock);
-				free_block(cachep, &objp, 1, nodeid);
-				spin_unlock(&(cachep->nodelists[nodeid])->
-					    list_lock);
-			}
-			return;
-		}
-	}
-#endif
 	if (likely(ac->avail < ac->limit)) {
 		STATS_INC_FREEHIT(cachep);
 		ac->entry[ac->avail++] = objp;
@@ -3254,26 +3270,10 @@
 #endif
 
 /**
- * kmalloc - allocate memory
+ * __do_kmalloc - allocate memory
  * @size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
+ * @flags: the type of memory to allocate (see kmalloc).
  * @caller: function caller for debug tracking of the caller
- *
- * kmalloc is the normal method of allocating memory
- * in the kernel.
- *
- * The @flags argument may be one of:
- *
- * %GFP_USER - Allocate memory on behalf of user.  May sleep.
- *
- * %GFP_KERNEL - Allocate normal kernel ram.  May sleep.
- *
- * %GFP_ATOMIC - Allocation will not sleep.  Use inside interrupt handlers.
- *
- * Additionally, the %GFP_DMA flag may be set to indicate the memory
- * must be suitable for DMA.  This can mean different things on different
- * platforms.  For example, on i386, it means that the memory must come
- * from the first 16MB.
  */
 static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
 					  void *caller)
@@ -3371,6 +3371,8 @@
 {
 	unsigned long flags;
 
+	BUG_ON(virt_to_cache(objp) != cachep);
+
 	local_irq_save(flags);
 	__cache_free(cachep, objp);
 	local_irq_restore(flags);
@@ -3396,7 +3398,7 @@
 	local_irq_save(flags);
 	kfree_debugcheck(objp);
 	c = virt_to_cache(objp);
-	mutex_debug_check_no_locks_freed(objp, obj_size(c));
+	debug_check_no_locks_freed(objp, obj_size(c));
 	__cache_free(c, (void *)objp);
 	local_irq_restore(flags);
 }
@@ -3680,7 +3682,7 @@
  */
 static void cache_reap(void *unused)
 {
-	struct list_head *walk;
+	struct kmem_cache *searchp;
 	struct kmem_list3 *l3;
 	int node = numa_node_id();
 
@@ -3691,13 +3693,11 @@
 		return;
 	}
 
-	list_for_each(walk, &cache_chain) {
-		struct kmem_cache *searchp;
+	list_for_each_entry(searchp, &cache_chain, next) {
 		struct list_head *p;
 		int tofree;
 		struct slab *slabp;
 
-		searchp = list_entry(walk, struct kmem_cache, next);
 		check_irq_on();
 
 		/*
@@ -3825,7 +3825,6 @@
 static int s_show(struct seq_file *m, void *p)
 {
 	struct kmem_cache *cachep = p;
-	struct list_head *q;
 	struct slab *slabp;
 	unsigned long active_objs;
 	unsigned long num_objs;
@@ -3846,15 +3845,13 @@
 		check_irq_on();
 		spin_lock_irq(&l3->list_lock);
 
-		list_for_each(q, &l3->slabs_full) {
-			slabp = list_entry(q, struct slab, list);
+		list_for_each_entry(slabp, &l3->slabs_full, list) {
 			if (slabp->inuse != cachep->num && !error)
 				error = "slabs_full accounting error";
 			active_objs += cachep->num;
 			active_slabs++;
 		}
-		list_for_each(q, &l3->slabs_partial) {
-			slabp = list_entry(q, struct slab, list);
+		list_for_each_entry(slabp, &l3->slabs_partial, list) {
 			if (slabp->inuse == cachep->num && !error)
 				error = "slabs_partial inuse accounting error";
 			if (!slabp->inuse && !error)
@@ -3862,8 +3859,7 @@
 			active_objs += slabp->inuse;
 			active_slabs++;
 		}
-		list_for_each(q, &l3->slabs_free) {
-			slabp = list_entry(q, struct slab, list);
+		list_for_each_entry(slabp, &l3->slabs_free, list) {
 			if (slabp->inuse && !error)
 				error = "slabs_free/inuse accounting error";
 			num_slabs++;
@@ -3956,7 +3952,7 @@
 {
 	char kbuf[MAX_SLABINFO_WRITE + 1], *tmp;
 	int limit, batchcount, shared, res;
-	struct list_head *p;
+	struct kmem_cache *cachep;
 
 	if (count > MAX_SLABINFO_WRITE)
 		return -EINVAL;
@@ -3975,10 +3971,7 @@
 	/* Find the cache in the chain of caches. */
 	mutex_lock(&cache_chain_mutex);
 	res = -EINVAL;
-	list_for_each(p, &cache_chain) {
-		struct kmem_cache *cachep;
-
-		cachep = list_entry(p, struct kmem_cache, next);
+	list_for_each_entry(cachep, &cache_chain, next) {
 		if (!strcmp(cachep->name, kbuf)) {
 			if (limit < 1 || batchcount < 1 ||
 					batchcount > limit || shared < 0) {
@@ -4080,7 +4073,6 @@
 static int leaks_show(struct seq_file *m, void *p)
 {
 	struct kmem_cache *cachep = p;
-	struct list_head *q;
 	struct slab *slabp;
 	struct kmem_list3 *l3;
 	const char *name;
@@ -4105,14 +4097,10 @@
 		check_irq_on();
 		spin_lock_irq(&l3->list_lock);
 
-		list_for_each(q, &l3->slabs_full) {
-			slabp = list_entry(q, struct slab, list);
+		list_for_each_entry(slabp, &l3->slabs_full, list)
 			handle_slab(n, cachep, slabp);
-		}
-		list_for_each(q, &l3->slabs_partial) {
-			slabp = list_entry(q, struct slab, list);
+		list_for_each_entry(slabp, &l3->slabs_partial, list)
 			handle_slab(n, cachep, slabp);
-		}
 		spin_unlock_irq(&l3->list_lock);
 	}
 	name = cachep->name;
diff --git a/mm/sparse.c b/mm/sparse.c
index 100040c..c7a2b3a 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -45,7 +45,7 @@
 
 static int sparse_index_init(unsigned long section_nr, int nid)
 {
-	static spinlock_t index_init_lock = SPIN_LOCK_UNLOCKED;
+	static DEFINE_SPINLOCK(index_init_lock);
 	unsigned long root = SECTION_NR_TO_ROOT(section_nr);
 	struct mem_section *section;
 	int ret = 0;
@@ -99,6 +99,22 @@
 	return (root_nr * SECTIONS_PER_ROOT) + (ms - root);
 }
 
+/*
+ * During early boot, before section_mem_map is used for an actual
+ * mem_map, we use section_mem_map to store the section's NUMA
+ * node.  This keeps us from having to use another data structure.  The
+ * node information is cleared just before we store the real mem_map.
+ */
+static inline unsigned long sparse_encode_early_nid(int nid)
+{
+	return (nid << SECTION_NID_SHIFT);
+}
+
+static inline int sparse_early_nid(struct mem_section *section)
+{
+	return (section->section_mem_map >> SECTION_NID_SHIFT);
+}
+
 /* Record a memory area against a node. */
 void memory_present(int nid, unsigned long start, unsigned long end)
 {
@@ -113,7 +129,8 @@
 
 		ms = __nr_to_section(section);
 		if (!ms->section_mem_map)
-			ms->section_mem_map = SECTION_MARKED_PRESENT;
+			ms->section_mem_map = sparse_encode_early_nid(nid) |
+							SECTION_MARKED_PRESENT;
 	}
 }
 
@@ -164,6 +181,7 @@
 	if (!valid_section(ms))
 		return -EINVAL;
 
+	ms->section_mem_map &= ~SECTION_MAP_MASK;
 	ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum);
 
 	return 1;
@@ -172,8 +190,8 @@
 static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
 {
 	struct page *map;
-	int nid = early_pfn_to_nid(section_nr_to_pfn(pnum));
 	struct mem_section *ms = __nr_to_section(pnum);
+	int nid = sparse_early_nid(ms);
 
 	map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
 	if (map)
diff --git a/mm/swap.c b/mm/swap.c
index 88895c2..990868a 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -86,8 +86,7 @@
 	zone = page_zone(page);
 	spin_lock_irqsave(&zone->lru_lock, flags);
 	if (PageLRU(page) && !PageActive(page)) {
-		list_del(&page->lru);
-		list_add_tail(&page->lru, &zone->inactive_list);
+		list_move_tail(&page->lru, &zone->inactive_list);
 		inc_page_state(pgrotated);
 	}
 	if (!test_clear_page_writeback(page))
@@ -480,48 +479,6 @@
 #endif /* CONFIG_HOTPLUG_CPU */
 #endif /* CONFIG_SMP */
 
-#ifdef CONFIG_SMP
-void percpu_counter_mod(struct percpu_counter *fbc, long amount)
-{
-	long count;
-	long *pcount;
-	int cpu = get_cpu();
-
-	pcount = per_cpu_ptr(fbc->counters, cpu);
-	count = *pcount + amount;
-	if (count >= FBC_BATCH || count <= -FBC_BATCH) {
-		spin_lock(&fbc->lock);
-		fbc->count += count;
-		*pcount = 0;
-		spin_unlock(&fbc->lock);
-	} else {
-		*pcount = count;
-	}
-	put_cpu();
-}
-EXPORT_SYMBOL(percpu_counter_mod);
-
-/*
- * Add up all the per-cpu counts, return the result.  This is a more accurate
- * but much slower version of percpu_counter_read_positive()
- */
-long percpu_counter_sum(struct percpu_counter *fbc)
-{
-	long ret;
-	int cpu;
-
-	spin_lock(&fbc->lock);
-	ret = fbc->count;
-	for_each_possible_cpu(cpu) {
-		long *pcount = per_cpu_ptr(fbc->counters, cpu);
-		ret += *pcount;
-	}
-	spin_unlock(&fbc->lock);
-	return ret < 0 ? 0 : ret;
-}
-EXPORT_SYMBOL(percpu_counter_sum);
-#endif
-
 /*
  * Perform any setup for the swap system
  */
diff --git a/mm/swap_state.c b/mm/swap_state.c
index e0e1583..7535211 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -24,7 +24,7 @@
  * vmscan's shrink_list, to make sync_page look nicer, and to allow
  * future use of radix_tree tags in the swap cache.
  */
-static struct address_space_operations swap_aops = {
+static const struct address_space_operations swap_aops = {
 	.writepage	= swap_writepage,
 	.sync_page	= block_sync_page,
 	.set_page_dirty	= __set_page_dirty_nobuffers,
diff --git a/mm/swapfile.c b/mm/swapfile.c
index e5fd538..cc367f7 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -395,6 +395,9 @@
 	struct swap_info_struct * p;
 	struct page *page = NULL;
 
+	if (is_migration_entry(entry))
+		return;
+
 	p = swap_info_get(entry);
 	if (p) {
 		if (swap_entry_free(p, swp_offset(entry)) == 1) {
@@ -615,15 +618,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_MIGRATION
-int remove_vma_swap(struct vm_area_struct *vma, struct page *page)
-{
-	swp_entry_t entry = { .val = page_private(page) };
-
-	return unuse_vma(vma, entry, page);
-}
-#endif
-
 /*
  * Scan swap_map from current position to next entry still in use.
  * Recycle to start on reaching the end, returning 0 when empty.
@@ -716,7 +710,6 @@
 		 */
 		swap_map = &si->swap_map[i];
 		entry = swp_entry(type, i);
-again:
 		page = read_swap_cache_async(entry, NULL, 0);
 		if (!page) {
 			/*
@@ -751,12 +744,6 @@
 		wait_on_page_locked(page);
 		wait_on_page_writeback(page);
 		lock_page(page);
-		if (!PageSwapCache(page)) {
-			/* Page migration has occured */
-			unlock_page(page);
-			page_cache_release(page);
-			goto again;
-		}
 		wait_on_page_writeback(page);
 
 		/*
@@ -785,10 +772,8 @@
 			while (*swap_map > 1 && !retval &&
 					(p = p->next) != &start_mm->mmlist) {
 				mm = list_entry(p, struct mm_struct, mmlist);
-				if (atomic_inc_return(&mm->mm_users) == 1) {
-					atomic_dec(&mm->mm_users);
+				if (!atomic_inc_not_zero(&mm->mm_users))
 					continue;
-				}
 				spin_unlock(&mmlist_lock);
 				mmput(prev_mm);
 				prev_mm = mm;
@@ -1407,19 +1392,7 @@
 		if (!(p->flags & SWP_USED))
 			break;
 	error = -EPERM;
-	/*
-	 * Test if adding another swap device is possible. There are
-	 * two limiting factors: 1) the number of bits for the swap
-	 * type swp_entry_t definition and 2) the number of bits for
-	 * the swap type in the swap ptes as defined by the different
-	 * architectures. To honor both limitations a swap entry
-	 * with swap offset 0 and swap type ~0UL is created, encoded
-	 * to a swap pte, decoded to a swp_entry_t again and finally
-	 * the swap type part is extracted. This will mask all bits
-	 * from the initial ~0UL that can't be encoded in either the
-	 * swp_entry_t or the architecture definition of a swap pte.
-	 */
-	if (type > swp_type(pte_to_swp_entry(swp_entry_to_pte(swp_entry(~0UL,0))))) {
+	if (type >= MAX_SWAPFILES) {
 		spin_unlock(&swap_lock);
 		goto out;
 	}
@@ -1504,8 +1477,7 @@
 		error = -EINVAL;
 		goto bad_swap;
 	}
-	page = read_cache_page(mapping, 0,
-			(filler_t *)mapping->a_ops->readpage, swap_file);
+	page = read_mapping_page(mapping, 0, swap_file);
 	if (IS_ERR(page)) {
 		error = PTR_ERR(page);
 		goto bad_swap;
@@ -1709,6 +1681,9 @@
 	unsigned long offset, type;
 	int result = 0;
 
+	if (is_migration_entry(entry))
+		return 1;
+
 	type = swp_type(entry);
 	if (type >= nr_swapfiles)
 		goto bad_file;
diff --git a/mm/truncate.c b/mm/truncate.c
index 6cb3fff..cf1b015 100644
--- a/mm/truncate.c
+++ b/mm/truncate.c
@@ -230,14 +230,24 @@
 			pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
 		for (i = 0; i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
+			pgoff_t index;
+			int lock_failed;
 
-			if (TestSetPageLocked(page)) {
-				next++;
-				continue;
-			}
-			if (page->index > next)
-				next = page->index;
+			lock_failed = TestSetPageLocked(page);
+
+			/*
+			 * We really shouldn't be looking at the ->index of an
+			 * unlocked page.  But we're not allowed to lock these
+			 * pages.  So we rely upon nobody altering the ->index
+			 * of this (pinned-by-us) page.
+			 */
+			index = page->index;
+			if (index > next)
+				next = index;
 			next++;
+			if (lock_failed)
+				continue;
+
 			if (PageDirty(page) || PageWriteback(page))
 				goto unlock;
 			if (page_mapped(page))
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index c0504f1..35f8553 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -257,6 +257,19 @@
 }
 
 /* Caller must hold vmlist_lock */
+static struct vm_struct *__find_vm_area(void *addr)
+{
+	struct vm_struct *tmp;
+
+	for (tmp = vmlist; tmp != NULL; tmp = tmp->next) {
+		 if (tmp->addr == addr)
+			break;
+	}
+
+	return tmp;
+}
+
+/* Caller must hold vmlist_lock */
 struct vm_struct *__remove_vm_area(void *addr)
 {
 	struct vm_struct **p, *tmp;
@@ -498,11 +511,33 @@
  */
 void *vmalloc(unsigned long size)
 {
-       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
+	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
 }
 EXPORT_SYMBOL(vmalloc);
 
 /**
+ *	vmalloc_user  -  allocate virtually contiguous memory which has
+ *			   been zeroed so it can be mapped to userspace without
+ *			   leaking data.
+ *
+ *	@size:		allocation size
+ */
+void *vmalloc_user(unsigned long size)
+{
+	struct vm_struct *area;
+	void *ret;
+
+	ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+	write_lock(&vmlist_lock);
+	area = __find_vm_area(ret);
+	area->flags |= VM_USERMAP;
+	write_unlock(&vmlist_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(vmalloc_user);
+
+/**
  *	vmalloc_node  -  allocate memory on a specific node
  *
  *	@size:		allocation size
@@ -516,7 +551,7 @@
  */
 void *vmalloc_node(unsigned long size, int node)
 {
-       return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node);
+	return __vmalloc_node(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL, node);
 }
 EXPORT_SYMBOL(vmalloc_node);
 
@@ -556,6 +591,28 @@
 }
 EXPORT_SYMBOL(vmalloc_32);
 
+/**
+ *	vmalloc_32_user  -  allocate virtually contiguous memory (32bit
+ *			      addressable) which is zeroed so it can be
+ *			      mapped to userspace without leaking data.
+ *
+ *	@size:		allocation size
+ */
+void *vmalloc_32_user(unsigned long size)
+{
+	struct vm_struct *area;
+	void *ret;
+
+	ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
+	write_lock(&vmlist_lock);
+	area = __find_vm_area(ret);
+	area->flags |= VM_USERMAP;
+	write_unlock(&vmlist_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(vmalloc_32_user);
+
 long vread(char *buf, char *addr, unsigned long count)
 {
 	struct vm_struct *tmp;
@@ -630,3 +687,64 @@
 	read_unlock(&vmlist_lock);
 	return buf - buf_start;
 }
+
+/**
+ *	remap_vmalloc_range  -  map vmalloc pages to userspace
+ *
+ *	@vma:		vma to cover (map full range of vma)
+ *	@addr:		vmalloc memory
+ *	@pgoff:		number of pages into addr before first page to map
+ *	@returns:	0 for success, -Exxx on failure
+ *
+ *	This function checks that addr is a valid vmalloc'ed area, and
+ *	that it is big enough to cover the vma. Will return failure if
+ *	that criteria isn't met.
+ *
+ *	Similar to remap_pfn_range (see mm/memory.c)
+ */
+int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
+						unsigned long pgoff)
+{
+	struct vm_struct *area;
+	unsigned long uaddr = vma->vm_start;
+	unsigned long usize = vma->vm_end - vma->vm_start;
+	int ret;
+
+	if ((PAGE_SIZE-1) & (unsigned long)addr)
+		return -EINVAL;
+
+	read_lock(&vmlist_lock);
+	area = __find_vm_area(addr);
+	if (!area)
+		goto out_einval_locked;
+
+	if (!(area->flags & VM_USERMAP))
+		goto out_einval_locked;
+
+	if (usize + (pgoff << PAGE_SHIFT) > area->size - PAGE_SIZE)
+		goto out_einval_locked;
+	read_unlock(&vmlist_lock);
+
+	addr += pgoff << PAGE_SHIFT;
+	do {
+		struct page *page = vmalloc_to_page(addr);
+		ret = vm_insert_page(vma, uaddr, page);
+		if (ret)
+			return ret;
+
+		uaddr += PAGE_SIZE;
+		addr += PAGE_SIZE;
+		usize -= PAGE_SIZE;
+	} while (usize > 0);
+
+	/* Prevent "things" like memory migration? VM_flags need a cleanup... */
+	vma->vm_flags |= VM_RESERVED;
+
+	return ret;
+
+out_einval_locked:
+	read_unlock(&vmlist_lock);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(remap_vmalloc_range);
+
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 440a733..eeacb0d 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -34,6 +34,7 @@
 #include <linux/notifier.h>
 #include <linux/rwsem.h>
 #include <linux/delay.h>
+#include <linux/kthread.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -61,6 +62,8 @@
 	 * In this context, it doesn't matter that we scan the
 	 * whole list at once. */
 	int swap_cluster_max;
+
+	int swappiness;
 };
 
 /*
@@ -108,7 +111,7 @@
  * From 0 .. 100.  Higher means more swappy.
  */
 int vm_swappiness = 60;
-static long total_memory;
+long vm_total_pages;	/* The total number of pages which the VM controls */
 
 static LIST_HEAD(shrinker_list);
 static DECLARE_RWSEM(shrinker_rwsem);
@@ -288,11 +291,23 @@
 	unlock_page(page);
 }
 
+/* possible outcome of pageout() */
+typedef enum {
+	/* failed to write page out, page is locked */
+	PAGE_KEEP,
+	/* move page to the active list, page is locked */
+	PAGE_ACTIVATE,
+	/* page has been sent to the disk successfully, page is unlocked */
+	PAGE_SUCCESS,
+	/* page is clean and locked */
+	PAGE_CLEAN,
+} pageout_t;
+
 /*
  * pageout is called by shrink_page_list() for each dirty page.
  * Calls ->writepage().
  */
-pageout_t pageout(struct page *page, struct address_space *mapping)
+static pageout_t pageout(struct page *page, struct address_space *mapping)
 {
 	/*
 	 * If the page is dirty, only perform writeback if that write
@@ -337,6 +352,8 @@
 		struct writeback_control wbc = {
 			.sync_mode = WB_SYNC_NONE,
 			.nr_to_write = SWAP_CLUSTER_MAX,
+			.range_start = 0,
+			.range_end = LLONG_MAX,
 			.nonblocking = 1,
 			.for_reclaim = 1,
 		};
@@ -727,7 +744,7 @@
 		 * how much memory
 		 * is mapped.
 		 */
-		mapped_ratio = (sc->nr_mapped * 100) / total_memory;
+		mapped_ratio = (sc->nr_mapped * 100) / vm_total_pages;
 
 		/*
 		 * Now decide how much we really want to unmap some pages.  The
@@ -741,7 +758,7 @@
 		 * A 100% value of vm_swappiness overrides this algorithm
 		 * altogether.
 		 */
-		swap_tendency = mapped_ratio / 2 + distress + vm_swappiness;
+		swap_tendency = mapped_ratio / 2 + distress + sc->swappiness;
 
 		/*
 		 * Now use this metric to decide whether to start moving mapped
@@ -957,6 +974,7 @@
 		.may_writepage = !laptop_mode,
 		.swap_cluster_max = SWAP_CLUSTER_MAX,
 		.may_swap = 1,
+		.swappiness = vm_swappiness,
 	};
 
 	inc_page_state(allocstall);
@@ -1021,10 +1039,6 @@
  * For kswapd, balance_pgdat() will work across all this node's zones until
  * they are all at pages_high.
  *
- * If `nr_pages' is non-zero then it is the number of pages which are to be
- * reclaimed, regardless of the zone occupancies.  This is a software suspend
- * special.
- *
  * Returns the number of pages which were actually freed.
  *
  * There is special handling here for zones which are full of pinned pages.
@@ -1042,10 +1056,8 @@
  * the page allocator fallback scheme to ensure that aging of pages is balanced
  * across the zones.
  */
-static unsigned long balance_pgdat(pg_data_t *pgdat, unsigned long nr_pages,
-				int order)
+static unsigned long balance_pgdat(pg_data_t *pgdat, int order)
 {
-	unsigned long to_free = nr_pages;
 	int all_zones_ok;
 	int priority;
 	int i;
@@ -1055,7 +1067,8 @@
 	struct scan_control sc = {
 		.gfp_mask = GFP_KERNEL,
 		.may_swap = 1,
-		.swap_cluster_max = nr_pages ? nr_pages : SWAP_CLUSTER_MAX,
+		.swap_cluster_max = SWAP_CLUSTER_MAX,
+		.swappiness = vm_swappiness,
 	};
 
 loop_again:
@@ -1082,31 +1095,26 @@
 
 		all_zones_ok = 1;
 
-		if (nr_pages == 0) {
-			/*
-			 * Scan in the highmem->dma direction for the highest
-			 * zone which needs scanning
-			 */
-			for (i = pgdat->nr_zones - 1; i >= 0; i--) {
-				struct zone *zone = pgdat->node_zones + i;
+		/*
+		 * Scan in the highmem->dma direction for the highest
+		 * zone which needs scanning
+		 */
+		for (i = pgdat->nr_zones - 1; i >= 0; i--) {
+			struct zone *zone = pgdat->node_zones + i;
 
-				if (!populated_zone(zone))
-					continue;
+			if (!populated_zone(zone))
+				continue;
 
-				if (zone->all_unreclaimable &&
-						priority != DEF_PRIORITY)
-					continue;
+			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
+				continue;
 
-				if (!zone_watermark_ok(zone, order,
-						zone->pages_high, 0, 0)) {
-					end_zone = i;
-					goto scan;
-				}
+			if (!zone_watermark_ok(zone, order, zone->pages_high,
+					       0, 0)) {
+				end_zone = i;
+				goto scan;
 			}
-			goto out;
-		} else {
-			end_zone = pgdat->nr_zones - 1;
 		}
+		goto out;
 scan:
 		for (i = 0; i <= end_zone; i++) {
 			struct zone *zone = pgdat->node_zones + i;
@@ -1133,11 +1141,9 @@
 			if (zone->all_unreclaimable && priority != DEF_PRIORITY)
 				continue;
 
-			if (nr_pages == 0) {	/* Not software suspend */
-				if (!zone_watermark_ok(zone, order,
-						zone->pages_high, end_zone, 0))
-					all_zones_ok = 0;
-			}
+			if (!zone_watermark_ok(zone, order, zone->pages_high,
+					       end_zone, 0))
+				all_zones_ok = 0;
 			zone->temp_priority = priority;
 			if (zone->prev_priority > priority)
 				zone->prev_priority = priority;
@@ -1162,8 +1168,6 @@
 			    total_scanned > nr_reclaimed + nr_reclaimed / 2)
 				sc.may_writepage = 1;
 		}
-		if (nr_pages && to_free > nr_reclaimed)
-			continue;	/* swsusp: need to do more work */
 		if (all_zones_ok)
 			break;		/* kswapd: all done */
 		/*
@@ -1179,7 +1183,7 @@
 		 * matches the direct reclaim path behaviour in terms of impact
 		 * on zone->*_priority.
 		 */
-		if ((nr_reclaimed >= SWAP_CLUSTER_MAX) && !nr_pages)
+		if (nr_reclaimed >= SWAP_CLUSTER_MAX)
 			break;
 	}
 out:
@@ -1220,7 +1224,6 @@
 	};
 	cpumask_t cpumask;
 
-	daemonize("kswapd%d", pgdat->node_id);
 	cpumask = node_to_cpumask(pgdat->node_id);
 	if (!cpus_empty(cpumask))
 		set_cpus_allowed(tsk, cpumask);
@@ -1261,7 +1264,7 @@
 		}
 		finish_wait(&pgdat->kswapd_wait, &wait);
 
-		balance_pgdat(pgdat, 0, order);
+		balance_pgdat(pgdat, order);
 	}
 	return 0;
 }
@@ -1290,35 +1293,154 @@
 
 #ifdef CONFIG_PM
 /*
- * Try to free `nr_pages' of memory, system-wide.  Returns the number of freed
- * pages.
+ * Helper function for shrink_all_memory().  Tries to reclaim 'nr_pages' pages
+ * from LRU lists system-wide, for given pass and priority, and returns the
+ * number of reclaimed pages
+ *
+ * For pass > 3 we also try to shrink the LRU lists that contain a few pages
+ */
+static unsigned long shrink_all_zones(unsigned long nr_pages, int pass,
+				      int prio, struct scan_control *sc)
+{
+	struct zone *zone;
+	unsigned long nr_to_scan, ret = 0;
+
+	for_each_zone(zone) {
+
+		if (!populated_zone(zone))
+			continue;
+
+		if (zone->all_unreclaimable && prio != DEF_PRIORITY)
+			continue;
+
+		/* For pass = 0 we don't shrink the active list */
+		if (pass > 0) {
+			zone->nr_scan_active += (zone->nr_active >> prio) + 1;
+			if (zone->nr_scan_active >= nr_pages || pass > 3) {
+				zone->nr_scan_active = 0;
+				nr_to_scan = min(nr_pages, zone->nr_active);
+				shrink_active_list(nr_to_scan, zone, sc);
+			}
+		}
+
+		zone->nr_scan_inactive += (zone->nr_inactive >> prio) + 1;
+		if (zone->nr_scan_inactive >= nr_pages || pass > 3) {
+			zone->nr_scan_inactive = 0;
+			nr_to_scan = min(nr_pages, zone->nr_inactive);
+			ret += shrink_inactive_list(nr_to_scan, zone, sc);
+			if (ret >= nr_pages)
+				return ret;
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Try to free `nr_pages' of memory, system-wide, and return the number of
+ * freed pages.
+ *
+ * Rather than trying to age LRUs the aim is to preserve the overall
+ * LRU order by reclaiming preferentially
+ * inactive > active > active referenced > active mapped
  */
 unsigned long shrink_all_memory(unsigned long nr_pages)
 {
-	pg_data_t *pgdat;
-	unsigned long nr_to_free = nr_pages;
+	unsigned long lru_pages, nr_slab;
 	unsigned long ret = 0;
-	unsigned retry = 2;
-	struct reclaim_state reclaim_state = {
-		.reclaimed_slab = 0,
+	int pass;
+	struct reclaim_state reclaim_state;
+	struct zone *zone;
+	struct scan_control sc = {
+		.gfp_mask = GFP_KERNEL,
+		.may_swap = 0,
+		.swap_cluster_max = nr_pages,
+		.may_writepage = 1,
+		.swappiness = vm_swappiness,
 	};
 
 	current->reclaim_state = &reclaim_state;
-repeat:
-	for_each_online_pgdat(pgdat) {
-		unsigned long freed;
 
-		freed = balance_pgdat(pgdat, nr_to_free, 0);
-		ret += freed;
-		nr_to_free -= freed;
-		if ((long)nr_to_free <= 0)
+	lru_pages = 0;
+	for_each_zone(zone)
+		lru_pages += zone->nr_active + zone->nr_inactive;
+
+	nr_slab = read_page_state(nr_slab);
+	/* If slab caches are huge, it's better to hit them first */
+	while (nr_slab >= lru_pages) {
+		reclaim_state.reclaimed_slab = 0;
+		shrink_slab(nr_pages, sc.gfp_mask, lru_pages);
+		if (!reclaim_state.reclaimed_slab)
 			break;
+
+		ret += reclaim_state.reclaimed_slab;
+		if (ret >= nr_pages)
+			goto out;
+
+		nr_slab -= reclaim_state.reclaimed_slab;
 	}
-	if (retry-- && ret < nr_pages) {
-		blk_congestion_wait(WRITE, HZ/5);
-		goto repeat;
+
+	/*
+	 * We try to shrink LRUs in 5 passes:
+	 * 0 = Reclaim from inactive_list only
+	 * 1 = Reclaim from active list but don't reclaim mapped
+	 * 2 = 2nd pass of type 1
+	 * 3 = Reclaim mapped (normal reclaim)
+	 * 4 = 2nd pass of type 3
+	 */
+	for (pass = 0; pass < 5; pass++) {
+		int prio;
+
+		/* Needed for shrinking slab caches later on */
+		if (!lru_pages)
+			for_each_zone(zone) {
+				lru_pages += zone->nr_active;
+				lru_pages += zone->nr_inactive;
+			}
+
+		/* Force reclaiming mapped pages in the passes #3 and #4 */
+		if (pass > 2) {
+			sc.may_swap = 1;
+			sc.swappiness = 100;
+		}
+
+		for (prio = DEF_PRIORITY; prio >= 0; prio--) {
+			unsigned long nr_to_scan = nr_pages - ret;
+
+			sc.nr_mapped = read_page_state(nr_mapped);
+			sc.nr_scanned = 0;
+
+			ret += shrink_all_zones(nr_to_scan, prio, pass, &sc);
+			if (ret >= nr_pages)
+				goto out;
+
+			reclaim_state.reclaimed_slab = 0;
+			shrink_slab(sc.nr_scanned, sc.gfp_mask, lru_pages);
+			ret += reclaim_state.reclaimed_slab;
+			if (ret >= nr_pages)
+				goto out;
+
+			if (sc.nr_scanned && prio < DEF_PRIORITY - 2)
+				blk_congestion_wait(WRITE, HZ / 10);
+		}
+
+		lru_pages = 0;
 	}
+
+	/*
+	 * If ret = 0, we could not shrink LRUs, but there may be something
+	 * in slab caches
+	 */
+	if (!ret)
+		do {
+			reclaim_state.reclaimed_slab = 0;
+			shrink_slab(nr_pages, sc.gfp_mask, lru_pages);
+			ret += reclaim_state.reclaimed_slab;
+		} while (ret < nr_pages && reclaim_state.reclaimed_slab > 0);
+
+out:
 	current->reclaim_state = NULL;
+
 	return ret;
 }
 #endif
@@ -1328,7 +1450,7 @@
    not required for correctness.  So if the last cpu in a node goes
    away, we get changed to run anywhere: as the first one comes back,
    restore their cpu bindings. */
-static int cpu_callback(struct notifier_block *nfb,
+static int __devinit cpu_callback(struct notifier_block *nfb,
 				  unsigned long action, void *hcpu)
 {
 	pg_data_t *pgdat;
@@ -1346,21 +1468,35 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * This kswapd start function will be called by init and node-hot-add.
+ * On node-hot-add, kswapd will moved to proper cpus if cpus are hot-added.
+ */
+int kswapd_run(int nid)
+{
+	pg_data_t *pgdat = NODE_DATA(nid);
+	int ret = 0;
+
+	if (pgdat->kswapd)
+		return 0;
+
+	pgdat->kswapd = kthread_run(kswapd, pgdat, "kswapd%d", nid);
+	if (IS_ERR(pgdat->kswapd)) {
+		/* failure at boot is fatal */
+		BUG_ON(system_state == SYSTEM_BOOTING);
+		printk("Failed to start kswapd on node %d\n",nid);
+		ret = -1;
+	}
+	return ret;
+}
+
 static int __init kswapd_init(void)
 {
-	pg_data_t *pgdat;
+	int nid;
 
 	swap_setup();
-	for_each_online_pgdat(pgdat) {
-		pid_t pid;
-
-		pid = kernel_thread(kswapd, pgdat, CLONE_KERNEL);
-		BUG_ON(pid < 0);
-		read_lock(&tasklist_lock);
-		pgdat->kswapd = find_task_by_pid(pid);
-		read_unlock(&tasklist_lock);
-	}
-	total_memory = nr_free_pagecache_pages();
+	for_each_online_node(nid)
+ 		kswapd_run(nid);
 	hotcpu_notifier(cpu_callback, 0);
 	return 0;
 }
@@ -1416,6 +1552,7 @@
 		.swap_cluster_max = max_t(unsigned long, nr_pages,
 					SWAP_CLUSTER_MAX),
 		.gfp_mask = gfp_mask,
+		.swappiness = vm_swappiness,
 	};
 
 	disable_swap_token();
diff --git a/net/Kconfig b/net/Kconfig
index 4193cdc..c6cec5a 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -66,6 +66,13 @@
 
 endif # if INET
 
+config NETWORK_SECMARK
+	bool "Security Marking"
+	help
+	  This enables security marking of network packets, similar
+	  to nfmark, but designated for security purposes.
+	  If you are unsure how to answer this question, answer N.
+
 menuconfig NETFILTER
 	bool "Network packet filtering (replaces ipchains)"
 	---help---
@@ -215,6 +222,21 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called pktgen.
 
+config NET_TCPPROBE
+	tristate "TCP connection probing"
+	depends on INET && EXPERIMENTAL && PROC_FS && KPROBES
+	---help---
+	This module allows for capturing the changes to TCP connection
+	state in response to incoming packets. It is used for debugging
+	TCP congestion avoidance modules. If you don't understand
+	what was just said, you don't need it: say N.
+
+	Documentation on how to use the packet generator can be found
+	at http://linux-net.osdl.org/index.php/TcpProbe
+
+	To compile this code as a module, choose M here: the
+	module will be called tcp_probe.
+
 endmenu
 
 endmenu
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 72d8529..f92f9c9 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -98,7 +98,7 @@
 		printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n", clip_vcc);
 		return;
 	}
-	spin_lock_bh(&entry->neigh->dev->xmit_lock);	/* block clip_start_xmit() */
+	netif_tx_lock_bh(entry->neigh->dev);	/* block clip_start_xmit() */
 	entry->neigh->used = jiffies;
 	for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
 		if (*walk == clip_vcc) {
@@ -122,7 +122,7 @@
 	printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
 	       "0x%p)\n", entry, clip_vcc);
       out:
-	spin_unlock_bh(&entry->neigh->dev->xmit_lock);
+	netif_tx_unlock_bh(entry->neigh->dev);
 }
 
 /* The neighbour entry n->lock is held. */
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index c304ef1..5fe77df 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -229,20 +229,15 @@
 /* this is buggered - we need locking for qos_head */
 void atm_mpoa_disp_qos(struct seq_file *m)
 {
-	unsigned char *ip;
-	char ipaddr[16];
 	struct atm_mpoa_qos *qos;
 
 	qos = qos_head;
 	seq_printf(m, "QoS entries for shortcuts:\n");
 	seq_printf(m, "IP address\n  TX:max_pcr pcr     min_pcr max_cdv max_sdu\n  RX:max_pcr pcr     min_pcr max_cdv max_sdu\n");
 
-	ipaddr[sizeof(ipaddr)-1] = '\0';
 	while (qos != NULL) {
-		ip = (unsigned char *)&qos->ipaddr;
-		sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip));
 		seq_printf(m, "%u.%u.%u.%u\n     %-7d %-7d %-7d %-7d %-7d\n     %-7d %-7d %-7d %-7d %-7d\n",
-				NIPQUAD(ipaddr),
+				NIPQUAD(qos->ipaddr),
 				qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
 				qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
 		qos = qos->next;
@@ -1083,7 +1078,6 @@
 static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry)
 {
 	uint32_t dst_ip = msg->content.in_info.in_dst_ip;
-	unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
 	struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
 	eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
 
@@ -1097,7 +1091,7 @@
 				    entry->shortcut = eg_entry->shortcut;
 		}
 	 	if(entry->shortcut){
-			dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip));
+			dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(dst_ip));
 			client->eg_ops->put(eg_entry);
 			return;
 		}
@@ -1119,12 +1113,10 @@
 
 static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
 {
-	unsigned char *ip;
-
 	uint32_t dst_ip = msg->content.in_info.in_dst_ip;
 	in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
-	ip = (unsigned char *)&dst_ip;
-	dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip));
+
+	dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(dst_ip));
 	ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
 	if(entry == NULL){
 		printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c
index 64ddebb..781ed1b 100644
--- a/net/atm/mpoa_caches.c
+++ b/net/atm/mpoa_caches.c
@@ -223,7 +223,6 @@
    but an easy one... */
 static void clear_count_and_expired(struct mpoa_client *client)
 {
-	unsigned char *ip;
 	in_cache_entry *entry, *next_entry;
 	struct timeval now;
 
@@ -236,8 +235,7 @@
 		next_entry = entry->next;
 		if((now.tv_sec - entry->tv.tv_sec)
 		   > entry->ctrl_info.holding_time){
-			ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
-			dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+			dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(entry->ctrl_info.in_dst_ip));
 			client->in_ops->remove_entry(entry, client);
 		}
 		entry = next_entry;
@@ -455,7 +453,6 @@
 
 static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client)
 {
-	unsigned char *ip;
 	eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
 
 	if (entry == NULL) {
@@ -463,8 +460,7 @@
 		return NULL;
 	}
 
-	ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
-	dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(ip));
+	dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(msg->content.eg_info.eg_dst_ip));
 	memset(entry, 0, sizeof(eg_cache_entry));
 
 	atomic_set(&entry->use, 1);
@@ -481,8 +477,8 @@
 	do_gettimeofday(&(entry->tv));
 	entry->entry_state = EGRESS_RESOLVED;
 	dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
-	ip = (unsigned char *)&entry->ctrl_info.mps_ip;
-	dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+	dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n",
+		NIPQUAD(entry->ctrl_info.mps_ip));
 	atomic_inc(&entry->use);
 
 	write_unlock_irq(&client->egress_lock);
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 74368f7..b81fad8 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -480,12 +480,8 @@
 
 	BT_DBG("dlc %p tty %p len %d", dlc, tty, skb->len);
 
-	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
-		tty_buffer_request_room(tty, skb->len);
-		tty_insert_flip_string(tty, skb->data, skb->len);
-		tty_flip_buffer_push(tty);
-	} else
-		tty->ldisc.receive_buf(tty, skb->data, NULL, skb->len);
+	tty_insert_flip_string(tty, skb->data, skb->len);
+	tty_flip_buffer_push(tty);
 
 	kfree_skb(skb);
 }
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index 59556e4..f444c12 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -6,7 +6,7 @@
 
 bridge-y	:= br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
 			br_ioctl.o br_notify.o br_stp.o br_stp_bpdu.o \
-			br_stp_if.o br_stp_timer.o
+			br_stp_if.o br_stp_timer.o br_netlink.o
 
 bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
 
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 12da21a..654401c 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -30,36 +30,46 @@
 
 static int __init br_init(void)
 {
+	int err;
+
 	br_stp_sap = llc_sap_open(LLC_SAP_BSPAN, br_stp_rcv);
 	if (!br_stp_sap) {
 		printk(KERN_ERR "bridge: can't register sap for STP\n");
-		return -EBUSY;
+		return -EADDRINUSE;
 	}
 
 	br_fdb_init();
 
-#ifdef CONFIG_BRIDGE_NETFILTER
-	if (br_netfilter_init())
-		return 1;
-#endif
+	err = br_netfilter_init();
+	if (err)
+		goto err_out1;
+
+	err = register_netdevice_notifier(&br_device_notifier);
+	if (err)
+		goto err_out2;
+
+	br_netlink_init();
 	brioctl_set(br_ioctl_deviceless_stub);
 	br_handle_frame_hook = br_handle_frame;
 
 	br_fdb_get_hook = br_fdb_get;
 	br_fdb_put_hook = br_fdb_put;
 
-	register_netdevice_notifier(&br_device_notifier);
-
 	return 0;
+
+err_out2:
+	br_netfilter_fini();
+err_out1:
+	llc_sap_put(br_stp_sap);
+	return err;
 }
 
 static void __exit br_deinit(void)
 {
 	rcu_assign_pointer(br_stp_sap->rcv_func, NULL);
 
-#ifdef CONFIG_BRIDGE_NETFILTER
+	br_netlink_fini();
 	br_netfilter_fini();
-#endif
 	unregister_netdevice_notifier(&br_device_notifier);
 	brioctl_set(NULL);
 
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 0c88a2a..2afdc7c 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -145,9 +145,9 @@
 	struct net_bridge *br = netdev_priv(dev);
 
 	if (data)
-		br->feature_mask |= NETIF_F_IP_CSUM;
+		br->feature_mask |= NETIF_F_NO_CSUM;
 	else
-		br->feature_mask &= ~NETIF_F_IP_CSUM;
+		br->feature_mask &= ~NETIF_F_ALL_CSUM;
 
 	br_features_recompute(br);
 	return 0;
@@ -185,5 +185,5 @@
 	dev->priv_flags = IFF_EBRIDGE;
 
  	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
- 		| NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM;
+ 		| NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_NO_CSUM;
 }
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 56f3aa47..8be9f21 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -20,14 +20,11 @@
 #include <linux/netfilter_bridge.h>
 #include "br_private.h"
 
+/* Don't forward packets to originating port or forwarding diasabled */
 static inline int should_deliver(const struct net_bridge_port *p, 
 				 const struct sk_buff *skb)
 {
-	if (skb->dev == p->dev ||
-	    p->state != BR_STATE_FORWARDING)
-		return 0;
-
-	return 1;
+	return (skb->dev != p->dev && p->state == BR_STATE_FORWARDING);
 }
 
 static inline unsigned packet_length(const struct sk_buff *skb)
@@ -37,8 +34,8 @@
 
 int br_dev_queue_push_xmit(struct sk_buff *skb)
 {
-	/* drop mtu oversized packets except tso */
-	if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
+	/* drop mtu oversized packets except gso */
+	if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
 		kfree_skb(skb);
 	else {
 #ifdef CONFIG_BRIDGE_NETFILTER
@@ -55,10 +52,9 @@
 
 int br_forward_finish(struct sk_buff *skb)
 {
-	NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
-			br_dev_queue_push_xmit);
+	return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
+		       br_dev_queue_push_xmit);
 
-	return 0;
 }
 
 static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index f5d47bf..07956ec 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -372,14 +372,24 @@
 	struct net_bridge_port *p;
 	unsigned long features, checksum;
 
-	features = br->feature_mask &~ NETIF_F_IP_CSUM;
-	checksum = br->feature_mask & NETIF_F_IP_CSUM;
+	checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0;
+	features = br->feature_mask & ~NETIF_F_ALL_CSUM;
 
 	list_for_each_entry(p, &br->port_list, list) {
-		if (!(p->dev->features 
-		      & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)))
+		unsigned long feature = p->dev->features;
+
+		if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
+			checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
+		if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
+			checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
+		if (!(feature & NETIF_F_IP_CSUM))
 			checksum = 0;
-		features &= p->dev->features;
+
+		if (feature & NETIF_F_GSO)
+			feature |= NETIF_F_TSO;
+		feature |= NETIF_F_GSO;
+
+		features &= feature;
 	}
 
 	br->dev->features = features | checksum | NETIF_F_LLTX;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 3da9264..8298a51 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -407,12 +407,8 @@
 	if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
 		if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
 			goto inhdr_error;
-		if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
-			if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)))
-				goto inhdr_error;
-			if (skb->ip_summed == CHECKSUM_HW)
-				skb->ip_summed = CHECKSUM_NONE;
-		}
+		if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr)))
+			goto inhdr_error;
 	}
 	if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
 		goto inhdr_error;
@@ -495,11 +491,7 @@
 	if (skb->len < len || len < 4 * iph->ihl)
 		goto inhdr_error;
 
-	if (skb->len > len) {
-		__pskb_trim(skb, len);
-		if (skb->ip_summed == CHECKSUM_HW)
-			skb->ip_summed = CHECKSUM_NONE;
-	}
+	pskb_trim_rcsum(skb, len);
 
 	nf_bridge_put(skb->nf_bridge);
 	if (!nf_bridge_alloc(skb))
@@ -769,7 +761,7 @@
 {
 	if (skb->protocol == htons(ETH_P_IP) &&
 	    skb->len > skb->dev->mtu &&
-	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+	    !skb_shinfo(skb)->gso_size)
 		return ip_fragment(skb, br_dev_queue_push_xmit);
 	else
 		return br_dev_queue_push_xmit(skb);
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
new file mode 100644
index 0000000..881d7d1
--- /dev/null
+++ b/net/bridge/br_netlink.c
@@ -0,0 +1,199 @@
+/*
+ *	Bridge netlink control interface
+ *
+ *	Authors:
+ *	Stephen Hemminger		<shemminger@osdl.org>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/rtnetlink.h>
+#include "br_private.h"
+
+/*
+ * Create one netlink message for one interface
+ * Contains port and master info as well as carrier and bridge state.
+ */
+static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port,
+			  u32 pid, u32 seq, int event, unsigned int flags)
+{
+	const struct net_bridge *br = port->br;
+	const struct net_device *dev = port->dev;
+	struct ifinfomsg *r;
+	struct nlmsghdr *nlh;
+	unsigned char *b = skb->tail;
+	u32 mtu = dev->mtu;
+	u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+	u8 portstate = port->state;
+
+	pr_debug("br_fill_info event %d port %s master %s\n",
+		 event, dev->name, br->dev->name);
+
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
+	r = NLMSG_DATA(nlh);
+	r->ifi_family = AF_BRIDGE;
+	r->__ifi_pad = 0;
+	r->ifi_type = dev->type;
+	r->ifi_index = dev->ifindex;
+	r->ifi_flags = dev_get_flags(dev);
+	r->ifi_change = 0;
+
+	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
+
+	RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex);
+
+	if (dev->addr_len)
+		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
+
+	RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
+	if (dev->ifindex != dev->iflink)
+		RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink);
+
+
+	RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
+
+	if (event == RTM_NEWLINK)
+		RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate);
+
+	nlh->nlmsg_len = skb->tail - b;
+
+	return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+
+	skb_trim(skb, b - skb->data);
+	return -EINVAL;
+}
+
+/*
+ * Notify listeners of a change in port information
+ */
+void br_ifinfo_notify(int event, struct net_bridge_port *port)
+{
+	struct sk_buff *skb;
+	int err = -ENOMEM;
+
+	pr_debug("bridge notify event=%d\n", event);
+	skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128),
+			GFP_ATOMIC);
+	if (!skb)
+		goto err_out;
+
+	err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0);
+	if (err)
+		goto err_kfree;
+
+	NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
+	netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC);
+	return;
+
+err_kfree:
+	kfree_skb(skb);
+err_out:
+	netlink_set_err(rtnl, 0, RTNLGRP_LINK, err);
+}
+
+/*
+ * Dump information about all ports, in response to GETLINK
+ */
+static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	struct net_device *dev;
+	int idx;
+	int s_idx = cb->args[0];
+	int err = 0;
+
+	read_lock(&dev_base_lock);
+	for (dev = dev_base, idx = 0; dev; dev = dev->next) {
+		struct net_bridge_port *p = dev->br_port;
+
+		/* not a bridge port */
+		if (!p)
+			continue;
+
+		if (idx < s_idx)
+			continue;
+
+		err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid,
+				     cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
+		if (err <= 0)
+			break;
+		++idx;
+	}
+	read_unlock(&dev_base_lock);
+
+	cb->args[0] = idx;
+
+	return skb->len;
+}
+
+/*
+ * Change state of port (ie from forwarding to blocking etc)
+ * Used by spanning tree in user space.
+ */
+static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+{
+	struct rtattr  **rta = arg;
+	struct ifinfomsg *ifm = NLMSG_DATA(nlh);
+	struct net_device *dev;
+	struct net_bridge_port *p;
+	u8 new_state;
+
+	if (ifm->ifi_family != AF_BRIDGE)
+		return -EPFNOSUPPORT;
+
+	/* Must pass valid state as PROTINFO */
+	if (rta[IFLA_PROTINFO-1]) {
+		u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]);
+		new_state = *pstate;
+	} else
+		return -EINVAL;
+
+	if (new_state > BR_STATE_BLOCKING)
+		return -EINVAL;
+
+	/* Find bridge port */
+	dev = __dev_get_by_index(ifm->ifi_index);
+	if (!dev)
+		return -ENODEV;
+
+	p = dev->br_port;
+	if (!p)
+		return -EINVAL;
+
+	/* if kernel STP is running, don't allow changes */
+	if (p->br->stp_enabled)
+		return -EBUSY;
+
+	if (!netif_running(dev))
+		return -ENETDOWN;
+
+	if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)
+		return -ENETDOWN;
+
+	p->state = new_state;
+	br_log_state(p);
+	return 0;
+}
+
+
+static struct rtnetlink_link bridge_rtnetlink_table[RTM_NR_MSGTYPES] = {
+	[RTM_GETLINK - RTM_BASE] = { .dumpit	= br_dump_ifinfo, },
+	[RTM_SETLINK - RTM_BASE] = { .doit      = br_rtm_setlink, },
+};
+
+void __init br_netlink_init(void)
+{
+	rtnetlink_links[PF_BRIDGE] = bridge_rtnetlink_table;
+}
+
+void __exit br_netlink_fini(void)
+{
+	rtnetlink_links[PF_BRIDGE] = NULL;
+}
+
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index a43a9c1..2027849 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -14,6 +14,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/rtnetlink.h>
 
 #include "br_private.h"
 
@@ -49,6 +50,7 @@
 
 	case NETDEV_CHANGEADDR:
 		br_fdb_changeaddr(p, dev->dev_addr);
+		br_ifinfo_notify(RTM_NEWLINK, p);
 		br_stp_recalculate_bridge_id(br);
 		break;
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 86ecea7..c491fb2 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -29,7 +29,7 @@
 
 #define BR_PORT_DEBOUNCE (HZ/10)
 
-#define BR_VERSION	"2.1"
+#define BR_VERSION	"2.2"
 
 typedef struct bridge_id bridge_id;
 typedef struct mac_addr mac_addr;
@@ -192,8 +192,13 @@
 extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg);
 
 /* br_netfilter.c */
+#ifdef CONFIG_BRIDGE_NETFILTER
 extern int br_netfilter_init(void);
 extern void br_netfilter_fini(void);
+#else
+#define br_netfilter_init()	(0)
+#define br_netfilter_fini()	do { } while(0)
+#endif
 
 /* br_stp.c */
 extern void br_log_state(const struct net_bridge_port *p);
@@ -232,6 +237,11 @@
 extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
 
 
+/* br_netlink.c */
+extern void br_netlink_init(void);
+extern void br_netlink_fini(void);
+extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
+
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
 extern struct sysfs_ops brport_sysfs_ops;
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 23dea14..14cd025 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 
 #include "br_private.h"
 #include "br_private_stp.h"
@@ -86,6 +87,7 @@
 void br_stp_enable_port(struct net_bridge_port *p)
 {
 	br_init_port(p);
+	br_ifinfo_notify(RTM_NEWLINK, p);
 	br_port_state_selection(p->br);
 }
 
@@ -99,6 +101,8 @@
 	printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
 	       br->dev->name, p->port_no, p->dev->name, "disabled");
 
+	br_ifinfo_notify(RTM_DELLINK, p);
+
 	wasroot = br_is_root_bridge(br);
 	br_become_designated_port(p);
 	p->state = BR_STATE_DISABLED;
diff --git a/net/core/Makefile b/net/core/Makefile
index 79fe12c..e9bd246 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -16,3 +16,4 @@
 obj-$(CONFIG_NET_PKTGEN) += pktgen.o
 obj-$(CONFIG_WIRELESS_EXT) += wireless.o
 obj-$(CONFIG_NETPOLL) += netpoll.o
+obj-$(CONFIG_NET_DMA) += user_dma.o
diff --git a/net/core/dev.c b/net/core/dev.c
index 4fba549..f1c52cb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -115,6 +115,8 @@
 #include <net/iw_handler.h>
 #include <asm/current.h>
 #include <linux/audit.h>
+#include <linux/dmaengine.h>
+#include <linux/err.h>
 
 /*
  *	The list of packet types we will receive (as opposed to discard)
@@ -148,6 +150,12 @@
 static struct list_head ptype_base[16];	/* 16 way hashed list */
 static struct list_head ptype_all;		/* Taps */
 
+#ifdef CONFIG_NET_DMA
+static struct dma_client *net_dma_client;
+static unsigned int net_dma_count;
+static spinlock_t net_dma_event_lock;
+#endif
+
 /*
  * The @dev_base list is protected by @dev_base_lock and the rtnl
  * semaphore.
@@ -222,7 +230,7 @@
  *	For efficiency
  */
 
-int netdev_nit;
+static int netdev_nit;
 
 /*
  *	Add a protocol ID to the list. Now that the input handler is
@@ -1041,7 +1049,7 @@
  *	taps currently in use.
  */
 
-void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
+static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct packet_type *ptype;
 
@@ -1179,6 +1187,40 @@
 	return ret;
 }
 
+/**
+ *	skb_gso_segment - Perform segmentation on skb.
+ *	@skb: buffer to segment
+ *	@sg: whether scatter-gather is supported on the target.
+ *
+ *	This function segments the given skb and returns a list of segments.
+ */
+struct sk_buff *skb_gso_segment(struct sk_buff *skb, int sg)
+{
+	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
+	struct packet_type *ptype;
+	int type = skb->protocol;
+
+	BUG_ON(skb_shinfo(skb)->frag_list);
+	BUG_ON(skb->ip_summed != CHECKSUM_HW);
+
+	skb->mac.raw = skb->data;
+	skb->mac_len = skb->nh.raw - skb->data;
+	__skb_pull(skb, skb->mac_len);
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
+		if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
+			segs = ptype->gso_segment(skb, sg);
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	return segs;
+}
+
+EXPORT_SYMBOL(skb_gso_segment);
+
 /* Take action when hardware reception checksum errors are detected. */
 #ifdef CONFIG_BUG
 void netdev_rx_csum_fault(struct net_device *dev)
@@ -1215,75 +1257,98 @@
 #define illegal_highdma(dev, skb)	(0)
 #endif
 
-/* Keep head the same: replace data */
-int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
+struct dev_gso_cb {
+	void (*destructor)(struct sk_buff *skb);
+};
+
+#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb)
+
+static void dev_gso_skb_destructor(struct sk_buff *skb)
 {
-	unsigned int size;
-	u8 *data;
-	long offset;
-	struct skb_shared_info *ninfo;
-	int headerlen = skb->data - skb->head;
-	int expand = (skb->tail + skb->data_len) - skb->end;
+	struct dev_gso_cb *cb;
 
-	if (skb_shared(skb))
-		BUG();
+	do {
+		struct sk_buff *nskb = skb->next;
 
-	if (expand <= 0)
-		expand = 0;
+		skb->next = nskb->next;
+		nskb->next = NULL;
+		kfree_skb(nskb);
+	} while (skb->next);
 
-	size = skb->end - skb->head + expand;
-	size = SKB_DATA_ALIGN(size);
-	data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
-	if (!data)
-		return -ENOMEM;
+	cb = DEV_GSO_CB(skb);
+	if (cb->destructor)
+		cb->destructor(skb);
+}
 
-	/* Copy entire thing */
-	if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
-		BUG();
+/**
+ *	dev_gso_segment - Perform emulated hardware segmentation on skb.
+ *	@skb: buffer to segment
+ *
+ *	This function segments the given skb and stores the list of segments
+ *	in skb->next.
+ */
+static int dev_gso_segment(struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+	struct sk_buff *segs;
 
-	/* Set up shinfo */
-	ninfo = (struct skb_shared_info*)(data + size);
-	atomic_set(&ninfo->dataref, 1);
-	ninfo->tso_size = skb_shinfo(skb)->tso_size;
-	ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
-	ninfo->nr_frags = 0;
-	ninfo->frag_list = NULL;
+	segs = skb_gso_segment(skb, dev->features & NETIF_F_SG &&
+				    !illegal_highdma(dev, skb));
+	if (unlikely(IS_ERR(segs)))
+		return PTR_ERR(segs);
 
-	/* Offset between the two in bytes */
-	offset = data - skb->head;
+	skb->next = segs;
+	DEV_GSO_CB(skb)->destructor = skb->destructor;
+	skb->destructor = dev_gso_skb_destructor;
 
-	/* Free old data. */
-	skb_release_data(skb);
+	return 0;
+}
 
-	skb->head = data;
-	skb->end  = data + size;
+int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	if (likely(!skb->next)) {
+		if (netdev_nit)
+			dev_queue_xmit_nit(skb, dev);
 
-	/* Set up new pointers */
-	skb->h.raw   += offset;
-	skb->nh.raw  += offset;
-	skb->mac.raw += offset;
-	skb->tail    += offset;
-	skb->data    += offset;
+		if (!netif_needs_gso(dev, skb))
+			return dev->hard_start_xmit(skb, dev);
 
-	/* We are no longer a clone, even if we were. */
-	skb->cloned    = 0;
+		if (unlikely(dev_gso_segment(skb)))
+			goto out_kfree_skb;
+	}
 
-	skb->tail     += skb->data_len;
-	skb->data_len  = 0;
+	do {
+		struct sk_buff *nskb = skb->next;
+		int rc;
+
+		skb->next = nskb->next;
+		nskb->next = NULL;
+		rc = dev->hard_start_xmit(nskb, dev);
+		if (unlikely(rc)) {
+			nskb->next = skb->next;
+			skb->next = nskb;
+			return rc;
+		}
+		if (unlikely(netif_queue_stopped(dev) && skb->next))
+			return NETDEV_TX_BUSY;
+	} while (skb->next);
+	
+	skb->destructor = DEV_GSO_CB(skb)->destructor;
+
+out_kfree_skb:
+	kfree_skb(skb);
 	return 0;
 }
 
 #define HARD_TX_LOCK(dev, cpu) {			\
 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
-		spin_lock(&dev->xmit_lock);		\
-		dev->xmit_lock_owner = cpu;		\
+		netif_tx_lock(dev);			\
 	}						\
 }
 
 #define HARD_TX_UNLOCK(dev) {				\
 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
-		dev->xmit_lock_owner = -1;		\
-		spin_unlock(&dev->xmit_lock);		\
+		netif_tx_unlock(dev);			\
 	}						\
 }
 
@@ -1319,9 +1384,13 @@
 	struct Qdisc *q;
 	int rc = -ENOMEM;
 
+	/* GSO will handle the following emulations directly. */
+	if (netif_needs_gso(dev, skb))
+		goto gso;
+
 	if (skb_shinfo(skb)->frag_list &&
 	    !(dev->features & NETIF_F_FRAGLIST) &&
-	    __skb_linearize(skb, GFP_ATOMIC))
+	    __skb_linearize(skb))
 		goto out_kfree_skb;
 
 	/* Fragmented skb is linearized if device does not support SG,
@@ -1330,25 +1399,26 @@
 	 */
 	if (skb_shinfo(skb)->nr_frags &&
 	    (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
-	    __skb_linearize(skb, GFP_ATOMIC))
+	    __skb_linearize(skb))
 		goto out_kfree_skb;
 
 	/* If packet is not checksummed and device does not support
 	 * checksumming for this protocol, complete checksumming here.
 	 */
 	if (skb->ip_summed == CHECKSUM_HW &&
-	    (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
+	    (!(dev->features & NETIF_F_GEN_CSUM) &&
 	     (!(dev->features & NETIF_F_IP_CSUM) ||
 	      skb->protocol != htons(ETH_P_IP))))
 	      	if (skb_checksum_help(skb, 0))
 	      		goto out_kfree_skb;
 
+gso:
 	spin_lock_prefetch(&dev->queue_lock);
 
 	/* Disable soft irqs for various locks below. Also 
 	 * stops preemption for RCU. 
 	 */
-	local_bh_disable(); 
+	rcu_read_lock_bh(); 
 
 	/* Updates of qdisc are serialized by queue_lock. 
 	 * The struct Qdisc which is pointed to by qdisc is now a 
@@ -1382,8 +1452,8 @@
 	/* The device has no queue. Common case for software devices:
 	   loopback, all the sorts of tunnels...
 
-	   Really, it is unlikely that xmit_lock protection is necessary here.
-	   (f.e. loopback and IP tunnels are clean ignoring statistics
+	   Really, it is unlikely that netif_tx_lock protection is necessary
+	   here.  (f.e. loopback and IP tunnels are clean ignoring statistics
 	   counters.)
 	   However, it is possible, that they rely on protection
 	   made by us here.
@@ -1399,11 +1469,8 @@
 			HARD_TX_LOCK(dev, cpu);
 
 			if (!netif_queue_stopped(dev)) {
-				if (netdev_nit)
-					dev_queue_xmit_nit(skb, dev);
-
 				rc = 0;
-				if (!dev->hard_start_xmit(skb, dev)) {
+				if (!dev_hard_start_xmit(skb, dev)) {
 					HARD_TX_UNLOCK(dev);
 					goto out;
 				}
@@ -1422,13 +1489,13 @@
 	}
 
 	rc = -ENETDOWN;
-	local_bh_enable();
+	rcu_read_unlock_bh();
 
 out_kfree_skb:
 	kfree_skb(skb);
 	return rc;
 out:
-	local_bh_enable();
+	rcu_read_unlock_bh();
 	return rc;
 }
 
@@ -1846,6 +1913,19 @@
 		}
 	}
 out:
+#ifdef CONFIG_NET_DMA
+	/*
+	 * There may not be any more sk_buffs coming right now, so push
+	 * any pending DMA copies to hardware
+	 */
+	if (net_dma_client) {
+		struct dma_chan *chan;
+		rcu_read_lock();
+		list_for_each_entry_rcu(chan, &net_dma_client->channels, client_node)
+			dma_async_memcpy_issue_pending(chan);
+		rcu_read_unlock();
+	}
+#endif
 	local_irq_enable();
 	return;
 
@@ -2785,7 +2865,7 @@
 	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
 
 	spin_lock_init(&dev->queue_lock);
-	spin_lock_init(&dev->xmit_lock);
+	spin_lock_init(&dev->_xmit_lock);
 	dev->xmit_lock_owner = -1;
 #ifdef CONFIG_NET_CLS_ACT
 	spin_lock_init(&dev->ingress_lock);
@@ -2829,9 +2909,7 @@
 
 	/* Fix illegal SG+CSUM combinations. */
 	if ((dev->features & NETIF_F_SG) &&
-	    !(dev->features & (NETIF_F_IP_CSUM |
-			       NETIF_F_NO_CSUM |
-			       NETIF_F_HW_CSUM))) {
+	    !(dev->features & NETIF_F_ALL_CSUM)) {
 		printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
 		       dev->name);
 		dev->features &= ~NETIF_F_SG;
@@ -3022,7 +3100,7 @@
 static DEFINE_MUTEX(net_todo_run_mutex);
 void netdev_run_todo(void)
 {
-	struct list_head list = LIST_HEAD_INIT(list);
+	struct list_head list;
 
 	/* Need to guard against multiple cpu's getting out of order. */
 	mutex_lock(&net_todo_run_mutex);
@@ -3037,9 +3115,9 @@
 
 	/* Snapshot list, allow later requests */
 	spin_lock(&net_todo_list_lock);
-	list_splice_init(&net_todo_list, &list);
+	list_replace_init(&net_todo_list, &list);
 	spin_unlock(&net_todo_list_lock);
-		
+
 	while (!list_empty(&list)) {
 		struct net_device *dev
 			= list_entry(list.next, struct net_device, todo_list);
@@ -3300,6 +3378,88 @@
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+#ifdef CONFIG_NET_DMA
+/**
+ * net_dma_rebalance -
+ * This is called when the number of channels allocated to the net_dma_client
+ * changes.  The net_dma_client tries to have one DMA channel per CPU.
+ */
+static void net_dma_rebalance(void)
+{
+	unsigned int cpu, i, n;
+	struct dma_chan *chan;
+
+	lock_cpu_hotplug();
+
+	if (net_dma_count == 0) {
+		for_each_online_cpu(cpu)
+			rcu_assign_pointer(per_cpu(softnet_data.net_dma, cpu), NULL);
+		unlock_cpu_hotplug();
+		return;
+	}
+
+	i = 0;
+	cpu = first_cpu(cpu_online_map);
+
+	rcu_read_lock();
+	list_for_each_entry(chan, &net_dma_client->channels, client_node) {
+		n = ((num_online_cpus() / net_dma_count)
+		   + (i < (num_online_cpus() % net_dma_count) ? 1 : 0));
+
+		while(n) {
+			per_cpu(softnet_data.net_dma, cpu) = chan;
+			cpu = next_cpu(cpu, cpu_online_map);
+			n--;
+		}
+		i++;
+	}
+	rcu_read_unlock();
+
+	unlock_cpu_hotplug();
+}
+
+/**
+ * netdev_dma_event - event callback for the net_dma_client
+ * @client: should always be net_dma_client
+ * @chan: DMA channel for the event
+ * @event: event type
+ */
+static void netdev_dma_event(struct dma_client *client, struct dma_chan *chan,
+	enum dma_event event)
+{
+	spin_lock(&net_dma_event_lock);
+	switch (event) {
+	case DMA_RESOURCE_ADDED:
+		net_dma_count++;
+		net_dma_rebalance();
+		break;
+	case DMA_RESOURCE_REMOVED:
+		net_dma_count--;
+		net_dma_rebalance();
+		break;
+	default:
+		break;
+	}
+	spin_unlock(&net_dma_event_lock);
+}
+
+/**
+ * netdev_dma_regiser - register the networking subsystem as a DMA client
+ */
+static int __init netdev_dma_register(void)
+{
+	spin_lock_init(&net_dma_event_lock);
+	net_dma_client = dma_async_client_register(netdev_dma_event);
+	if (net_dma_client == NULL)
+		return -ENOMEM;
+
+	dma_async_client_chan_request(net_dma_client, num_online_cpus());
+	return 0;
+}
+
+#else
+static int __init netdev_dma_register(void) { return -ENODEV; }
+#endif /* CONFIG_NET_DMA */
 
 /*
  *	Initialize the DEV module. At boot time this walks the device list and
@@ -3353,6 +3513,8 @@
 		atomic_set(&queue->backlog_dev.refcnt, 1);
 	}
 
+	netdev_dma_register();
+
 	dev_boot_phase = 0;
 
 	open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
@@ -3371,7 +3533,6 @@
 EXPORT_SYMBOL(__dev_get_by_index);
 EXPORT_SYMBOL(__dev_get_by_name);
 EXPORT_SYMBOL(__dev_remove_pack);
-EXPORT_SYMBOL(__skb_linearize);
 EXPORT_SYMBOL(dev_valid_name);
 EXPORT_SYMBOL(dev_add_pack);
 EXPORT_SYMBOL(dev_alloc_name);
diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
index 05d60850..c57d887 100644
--- a/net/core/dev_mcast.c
+++ b/net/core/dev_mcast.c
@@ -62,7 +62,7 @@
  *	Device mc lists are changed by bh at least if IPv6 is enabled,
  *	so that it must be bh protected.
  *
- *	We block accesses to device mc filters with dev->xmit_lock.
+ *	We block accesses to device mc filters with netif_tx_lock.
  */
 
 /*
@@ -93,9 +93,9 @@
 
 void dev_mc_upload(struct net_device *dev)
 {
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	__dev_mc_upload(dev);
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 }
 
 /*
@@ -107,7 +107,7 @@
 	int err = 0;
 	struct dev_mc_list *dmi, **dmip;
 
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 
 	for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
 		/*
@@ -139,13 +139,13 @@
 			 */
 			__dev_mc_upload(dev);
 			
-			spin_unlock_bh(&dev->xmit_lock);
+			netif_tx_unlock_bh(dev);
 			return 0;
 		}
 	}
 	err = -ENOENT;
 done:
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 	return err;
 }
 
@@ -160,7 +160,7 @@
 
 	dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
 
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
 		if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
 		    dmi->dmi_addrlen == alen) {
@@ -176,7 +176,7 @@
 	}
 
 	if ((dmi = dmi1) == NULL) {
-		spin_unlock_bh(&dev->xmit_lock);
+		netif_tx_unlock_bh(dev);
 		return -ENOMEM;
 	}
 	memcpy(dmi->dmi_addr, addr, alen);
@@ -189,11 +189,11 @@
 
 	__dev_mc_upload(dev);
 	
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 	return 0;
 
 done:
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 	kfree(dmi1);
 	return err;
 }
@@ -204,7 +204,7 @@
 
 void dev_mc_discard(struct net_device *dev)
 {
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	
 	while (dev->mc_list != NULL) {
 		struct dev_mc_list *tmp = dev->mc_list;
@@ -215,7 +215,7 @@
 	}
 	dev->mc_count = 0;
 
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -250,7 +250,7 @@
 	struct dev_mc_list *m;
 	struct net_device *dev = v;
 
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	for (m = dev->mc_list; m; m = m->next) {
 		int i;
 
@@ -262,7 +262,7 @@
 
 		seq_putc(seq, '\n');
 	}
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 	return 0;
 }
 
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index e6f7610..27ce168 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -30,7 +30,7 @@
 
 u32 ethtool_op_get_tx_csum(struct net_device *dev)
 {
-	return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0;
+	return (dev->features & NETIF_F_ALL_CSUM) != 0;
 }
 
 int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
@@ -551,9 +551,7 @@
 		return -EFAULT;
 
 	if (edata.data && 
-	    !(dev->features & (NETIF_F_IP_CSUM |
-			       NETIF_F_NO_CSUM |
-			       NETIF_F_HW_CSUM)))
+	    !(dev->features & NETIF_F_ALL_CSUM))
 		return -EINVAL;
 
 	return __ethtool_set_sg(dev, edata.data);
@@ -591,7 +589,7 @@
 
 static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr)
 {
-	struct ethtool_value edata = { ETHTOOL_GTSO };
+	struct ethtool_value edata = { ETHTOOL_GUFO };
 
 	if (!dev->ethtool_ops->get_ufo)
 		return -EOPNOTSUPP;
@@ -600,6 +598,7 @@
 		 return -EFAULT;
 	return 0;
 }
+
 static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_value edata;
@@ -615,6 +614,29 @@
 	return dev->ethtool_ops->set_ufo(dev, edata.data);
 }
 
+static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata = { ETHTOOL_GGSO };
+
+	edata.data = dev->features & NETIF_F_GSO;
+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
+		 return -EFAULT;
+	return 0;
+}
+
+static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
+{
+	struct ethtool_value edata;
+
+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
+		return -EFAULT;
+	if (edata.data)
+		dev->features |= NETIF_F_GSO;
+	else
+		dev->features &= ~NETIF_F_GSO;
+	return 0;
+}
+
 static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_test test;
@@ -906,6 +928,12 @@
 	case ETHTOOL_SUFO:
 		rc = ethtool_set_ufo(dev, useraddr);
 		break;
+	case ETHTOOL_GGSO:
+		rc = ethtool_get_gso(dev, useraddr);
+		break;
+	case ETHTOOL_SGSO:
+		rc = ethtool_set_gso(dev, useraddr);
+		break;
 	default:
 		rc =  -EOPNOTSUPP;
 	}
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index 646937c..0f37266 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -91,11 +91,10 @@
 /* Must be called with the rtnl semaphore held */
 void linkwatch_run_queue(void)
 {
-	LIST_HEAD(head);
-	struct list_head *n, *next;
+	struct list_head head, *n, *next;
 
 	spin_lock_irq(&lweventlist_lock);
-	list_splice_init(&lweventlist, &head);
+	list_replace_init(&lweventlist, &head);
 	spin_unlock_irq(&lweventlist_lock);
 
 	list_for_each_safe(n, next, &head) {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index e8e05ce..471da45 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -54,6 +54,7 @@
 				sizeof(struct iphdr) + sizeof(struct ethhdr))
 
 static void zap_completion_queue(void);
+static void arp_reply(struct sk_buff *skb);
 
 static void queue_process(void *p)
 {
@@ -153,6 +154,22 @@
 	}
 }
 
+static void service_arp_queue(struct netpoll_info *npi)
+{
+	struct sk_buff *skb;
+
+	if (unlikely(!npi))
+		return;
+
+	skb = skb_dequeue(&npi->arp_tx);
+
+	while (skb != NULL) {
+		arp_reply(skb);
+		skb = skb_dequeue(&npi->arp_tx);
+	}
+	return;
+}
+
 void netpoll_poll(struct netpoll *np)
 {
 	if(!np->dev || !netif_running(np->dev) || !np->dev->poll_controller)
@@ -163,6 +180,8 @@
 	if (np->dev->poll)
 		poll_napi(np);
 
+	service_arp_queue(np->dev->npinfo);
+
 	zap_completion_queue();
 }
 
@@ -273,24 +292,17 @@
 
 	do {
 		npinfo->tries--;
-		spin_lock(&np->dev->xmit_lock);
-		np->dev->xmit_lock_owner = smp_processor_id();
+		netif_tx_lock(np->dev);
 
 		/*
 		 * network drivers do not expect to be called if the queue is
 		 * stopped.
 		 */
-		if (netif_queue_stopped(np->dev)) {
-			np->dev->xmit_lock_owner = -1;
-			spin_unlock(&np->dev->xmit_lock);
-			netpoll_poll(np);
-			udelay(50);
-			continue;
-		}
+		status = NETDEV_TX_BUSY;
+		if (!netif_queue_stopped(np->dev))
+			status = np->dev->hard_start_xmit(skb, np->dev);
 
-		status = np->dev->hard_start_xmit(skb, np->dev);
-		np->dev->xmit_lock_owner = -1;
-		spin_unlock(&np->dev->xmit_lock);
+		netif_tx_unlock(np->dev);
 
 		/* success */
 		if(!status) {
@@ -449,7 +461,9 @@
 	int proto, len, ulen;
 	struct iphdr *iph;
 	struct udphdr *uh;
-	struct netpoll *np = skb->dev->npinfo->rx_np;
+	struct netpoll_info *npi = skb->dev->npinfo;
+	struct netpoll *np = npi->rx_np;
+
 
 	if (!np)
 		goto out;
@@ -459,7 +473,7 @@
 	/* check if netpoll clients need ARP */
 	if (skb->protocol == __constant_htons(ETH_P_ARP) &&
 	    atomic_read(&trapped)) {
-		arp_reply(skb);
+		skb_queue_tail(&npi->arp_tx, skb);
 		return 1;
 	}
 
@@ -654,6 +668,7 @@
 		npinfo->poll_owner = -1;
 		npinfo->tries = MAX_RETRIES;
 		spin_lock_init(&npinfo->rx_lock);
+		skb_queue_head_init(&npinfo->arp_tx);
 	} else
 		npinfo = ndev->npinfo;
 
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index c23e9c0..67ed14d 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2897,7 +2897,7 @@
 		}
 	}
 
-	spin_lock_bh(&odev->xmit_lock);
+	netif_tx_lock_bh(odev);
 	if (!netif_queue_stopped(odev)) {
 
 		atomic_inc(&(pkt_dev->skb->users));
@@ -2942,7 +2942,7 @@
 		pkt_dev->next_tx_ns = 0;
 	}
 
-	spin_unlock_bh(&odev->xmit_lock);
+	netif_tx_unlock_bh(odev);
 
 	/* If pkt_dev->count is zero, then run forever */
 	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index fb3770f..6edbb90 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -172,9 +172,9 @@
 	shinfo = skb_shinfo(skb);
 	atomic_set(&shinfo->dataref, 1);
 	shinfo->nr_frags  = 0;
-	shinfo->tso_size = 0;
-	shinfo->tso_segs = 0;
-	shinfo->ufo_size = 0;
+	shinfo->gso_size = 0;
+	shinfo->gso_segs = 0;
+	shinfo->gso_type = 0;
 	shinfo->ip6_frag_id = 0;
 	shinfo->frag_list = NULL;
 
@@ -238,8 +238,9 @@
 
 	atomic_set(&(skb_shinfo(skb)->dataref), 1);
 	skb_shinfo(skb)->nr_frags  = 0;
-	skb_shinfo(skb)->tso_size = 0;
-	skb_shinfo(skb)->tso_segs = 0;
+	skb_shinfo(skb)->gso_size = 0;
+	skb_shinfo(skb)->gso_segs = 0;
+	skb_shinfo(skb)->gso_type = 0;
 	skb_shinfo(skb)->frag_list = NULL;
 out:
 	return skb;
@@ -464,7 +465,7 @@
 	n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
 	C(input_dev);
 #endif
-
+	skb_copy_secmark(n, skb);
 #endif
 	C(truesize);
 	atomic_set(&n->users, 1);
@@ -526,9 +527,11 @@
 #endif
 	new->tc_index	= old->tc_index;
 #endif
+	skb_copy_secmark(new, old);
 	atomic_set(&new->users, 1);
-	skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size;
-	skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs;
+	skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
+	skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
+	skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
 }
 
 /**
@@ -780,32 +783,46 @@
  *	filled. Used by network drivers which may DMA or transfer data
  *	beyond the buffer end onto the wire.
  *
- *	May return NULL in out of memory cases.
+ *	May return error in out of memory cases. The skb is freed on error.
  */
  
-struct sk_buff *skb_pad(struct sk_buff *skb, int pad)
+int skb_pad(struct sk_buff *skb, int pad)
 {
-	struct sk_buff *nskb;
+	int err;
+	int ntail;
 	
 	/* If the skbuff is non linear tailroom is always zero.. */
-	if (skb_tailroom(skb) >= pad) {
+	if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) {
 		memset(skb->data+skb->len, 0, pad);
-		return skb;
+		return 0;
 	}
-	
-	nskb = skb_copy_expand(skb, skb_headroom(skb), skb_tailroom(skb) + pad, GFP_ATOMIC);
+
+	ntail = skb->data_len + pad - (skb->end - skb->tail);
+	if (likely(skb_cloned(skb) || ntail > 0)) {
+		err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC);
+		if (unlikely(err))
+			goto free_skb;
+	}
+
+	/* FIXME: The use of this function with non-linear skb's really needs
+	 * to be audited.
+	 */
+	err = skb_linearize(skb);
+	if (unlikely(err))
+		goto free_skb;
+
+	memset(skb->data + skb->len, 0, pad);
+	return 0;
+
+free_skb:
 	kfree_skb(skb);
-	if (nskb)
-		memset(nskb->data+nskb->len, 0, pad);
-	return nskb;
+	return err;
 }	
  
-/* Trims skb to length len. It can change skb pointers, if "realloc" is 1.
- * If realloc==0 and trimming is impossible without change of data,
- * it is BUG().
+/* Trims skb to length len. It can change skb pointers.
  */
 
-int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
+int ___pskb_trim(struct sk_buff *skb, unsigned int len)
 {
 	int offset = skb_headlen(skb);
 	int nfrags = skb_shinfo(skb)->nr_frags;
@@ -815,7 +832,6 @@
 		int end = offset + skb_shinfo(skb)->frags[i].size;
 		if (end > len) {
 			if (skb_cloned(skb)) {
-				BUG_ON(!realloc);
 				if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
 					return -ENOMEM;
 			}
@@ -1723,12 +1739,15 @@
 			   unsigned int to, struct ts_config *config,
 			   struct ts_state *state)
 {
+	unsigned int ret;
+
 	config->get_next_block = skb_ts_get_next_block;
 	config->finish = skb_ts_finish;
 
 	skb_prepare_seq_read(skb, from, to, TS_SKB_CB(state));
 
-	return textsearch_find(config, state);
+	ret = textsearch_find(config, state);
+	return (ret <= to - from ? ret : UINT_MAX);
 }
 
 /**
@@ -1826,6 +1845,132 @@
 
 EXPORT_SYMBOL_GPL(skb_pull_rcsum);
 
+/**
+ *	skb_segment - Perform protocol segmentation on skb.
+ *	@skb: buffer to segment
+ *	@sg: whether scatter-gather can be used for generated segments
+ *
+ *	This function performs segmentation on the given skb.  It returns
+ *	the segment at the given position.  It returns NULL if there are
+ *	no more segments to generate, or when an error is encountered.
+ */
+struct sk_buff *skb_segment(struct sk_buff *skb, int sg)
+{
+	struct sk_buff *segs = NULL;
+	struct sk_buff *tail = NULL;
+	unsigned int mss = skb_shinfo(skb)->gso_size;
+	unsigned int doffset = skb->data - skb->mac.raw;
+	unsigned int offset = doffset;
+	unsigned int headroom;
+	unsigned int len;
+	int nfrags = skb_shinfo(skb)->nr_frags;
+	int err = -ENOMEM;
+	int i = 0;
+	int pos;
+
+	__skb_push(skb, doffset);
+	headroom = skb_headroom(skb);
+	pos = skb_headlen(skb);
+
+	do {
+		struct sk_buff *nskb;
+		skb_frag_t *frag;
+		int hsize, nsize;
+		int k;
+		int size;
+
+		len = skb->len - offset;
+		if (len > mss)
+			len = mss;
+
+		hsize = skb_headlen(skb) - offset;
+		if (hsize < 0)
+			hsize = 0;
+		nsize = hsize + doffset;
+		if (nsize > len + doffset || !sg)
+			nsize = len + doffset;
+
+		nskb = alloc_skb(nsize + headroom, GFP_ATOMIC);
+		if (unlikely(!nskb))
+			goto err;
+
+		if (segs)
+			tail->next = nskb;
+		else
+			segs = nskb;
+		tail = nskb;
+
+		nskb->dev = skb->dev;
+		nskb->priority = skb->priority;
+		nskb->protocol = skb->protocol;
+		nskb->dst = dst_clone(skb->dst);
+		memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
+		nskb->pkt_type = skb->pkt_type;
+		nskb->mac_len = skb->mac_len;
+
+		skb_reserve(nskb, headroom);
+		nskb->mac.raw = nskb->data;
+		nskb->nh.raw = nskb->data + skb->mac_len;
+		nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw);
+		memcpy(skb_put(nskb, doffset), skb->data, doffset);
+
+		if (!sg) {
+			nskb->csum = skb_copy_and_csum_bits(skb, offset,
+							    skb_put(nskb, len),
+							    len, 0);
+			continue;
+		}
+
+		frag = skb_shinfo(nskb)->frags;
+		k = 0;
+
+		nskb->ip_summed = CHECKSUM_HW;
+		nskb->csum = skb->csum;
+		memcpy(skb_put(nskb, hsize), skb->data + offset, hsize);
+
+		while (pos < offset + len) {
+			BUG_ON(i >= nfrags);
+
+			*frag = skb_shinfo(skb)->frags[i];
+			get_page(frag->page);
+			size = frag->size;
+
+			if (pos < offset) {
+				frag->page_offset += offset - pos;
+				frag->size -= offset - pos;
+			}
+
+			k++;
+
+			if (pos + size <= offset + len) {
+				i++;
+				pos += size;
+			} else {
+				frag->size -= pos + size - (offset + len);
+				break;
+			}
+
+			frag++;
+		}
+
+		skb_shinfo(nskb)->nr_frags = k;
+		nskb->data_len = len - hsize;
+		nskb->len += nskb->data_len;
+		nskb->truesize += nskb->data_len;
+	} while ((offset += len) < skb->len);
+
+	return segs;
+
+err:
+	while ((skb = segs)) {
+		segs = skb->next;
+		kfree(skb);
+	}
+	return ERR_PTR(err);
+}
+
+EXPORT_SYMBOL_GPL(skb_segment);
+
 void __init skb_init(void)
 {
 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
diff --git a/net/core/sock.c b/net/core/sock.c
index ed2afdb..5d820c3 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -832,6 +832,9 @@
 		atomic_set(&newsk->sk_omem_alloc, 0);
 		skb_queue_head_init(&newsk->sk_receive_queue);
 		skb_queue_head_init(&newsk->sk_write_queue);
+#ifdef CONFIG_NET_DMA
+		skb_queue_head_init(&newsk->sk_async_wait_queue);
+#endif
 
 		rwlock_init(&newsk->sk_dst_lock);
 		rwlock_init(&newsk->sk_callback_lock);
@@ -1383,6 +1386,9 @@
 	skb_queue_head_init(&sk->sk_receive_queue);
 	skb_queue_head_init(&sk->sk_write_queue);
 	skb_queue_head_init(&sk->sk_error_queue);
+#ifdef CONFIG_NET_DMA
+	skb_queue_head_init(&sk->sk_async_wait_queue);
+#endif
 
 	sk->sk_send_head	=	NULL;
 
diff --git a/net/core/user_dma.c b/net/core/user_dma.c
new file mode 100644
index 0000000..b7c98db
--- /dev/null
+++ b/net/core/user_dma.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
+ * Portions based on net/core/datagram.c and copyrighted by their authors.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING.
+ */
+
+/*
+ * This code allows the net stack to make use of a DMA engine for
+ * skb to iovec copies.
+ */
+
+#include <linux/dmaengine.h>
+#include <linux/socket.h>
+#include <linux/rtnetlink.h> /* for BUG_TRAP */
+#include <net/tcp.h>
+
+#define NET_DMA_DEFAULT_COPYBREAK 4096
+
+int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK;
+
+/**
+ *	dma_skb_copy_datagram_iovec - Copy a datagram to an iovec.
+ *	@skb - buffer to copy
+ *	@offset - offset in the buffer to start copying from
+ *	@iovec - io vector to copy to
+ *	@len - amount of data to copy from buffer to iovec
+ *	@pinned_list - locked iovec buffer data
+ *
+ *	Note: the iovec is modified during the copy.
+ */
+int dma_skb_copy_datagram_iovec(struct dma_chan *chan,
+			struct sk_buff *skb, int offset, struct iovec *to,
+			size_t len, struct dma_pinned_list *pinned_list)
+{
+	int start = skb_headlen(skb);
+	int i, copy = start - offset;
+	dma_cookie_t cookie = 0;
+
+	/* Copy header. */
+	if (copy > 0) {
+		if (copy > len)
+			copy = len;
+		cookie = dma_memcpy_to_iovec(chan, to, pinned_list,
+		                            skb->data + offset, copy);
+		if (cookie < 0)
+			goto fault;
+		len -= copy;
+		if (len == 0)
+			goto end;
+		offset += copy;
+	}
+
+	/* Copy paged appendix. Hmm... why does this look so complicated? */
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		int end;
+
+		BUG_TRAP(start <= offset + len);
+
+		end = start + skb_shinfo(skb)->frags[i].size;
+		copy = end - offset;
+		if ((copy = end - offset) > 0) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			struct page *page = frag->page;
+
+			if (copy > len)
+				copy = len;
+
+			cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page,
+					frag->page_offset + offset - start, copy);
+			if (cookie < 0)
+				goto fault;
+			len -= copy;
+			if (len == 0)
+				goto end;
+			offset += copy;
+		}
+		start = end;
+	}
+
+	if (skb_shinfo(skb)->frag_list) {
+		struct sk_buff *list = skb_shinfo(skb)->frag_list;
+
+		for (; list; list = list->next) {
+			int end;
+
+			BUG_TRAP(start <= offset + len);
+
+			end = start + list->len;
+			copy = end - offset;
+			if (copy > 0) {
+				if (copy > len)
+					copy = len;
+				cookie = dma_skb_copy_datagram_iovec(chan, list,
+				                offset - start, to, copy,
+				                pinned_list);
+				if (cookie < 0)
+					goto fault;
+				len -= copy;
+				if (len == 0)
+					goto end;
+				offset += copy;
+			}
+			start = end;
+		}
+	}
+
+end:
+	if (!len) {
+		skb->dma_cookie = cookie;
+		return cookie;
+	}
+
+fault:
+ 	return -EFAULT;
+}
diff --git a/net/dccp/Kconfig b/net/dccp/Kconfig
index 7e096ba..859e335 100644
--- a/net/dccp/Kconfig
+++ b/net/dccp/Kconfig
@@ -26,7 +26,7 @@
 
 config IP_DCCP_ACKVEC
 	depends on IP_DCCP
-	def_bool N
+	bool
 
 source "net/dccp/ccids/Kconfig"
 
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 2e0ee83..5317fd3 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -719,7 +719,7 @@
 		}
 		dccp_pr_debug("packet_type=%s\n",
 			      dccp_packet_name(dh->dccph_type));
-		sk_eat_skb(sk, skb);
+		sk_eat_skb(sk, skb, 0);
 verify_sock_status:
 		if (sock_flag(sk, SOCK_DONE)) {
 			len = 0;
@@ -773,7 +773,7 @@
 		}
 	found_fin_ok:
 		if (!(flags & MSG_PEEK))
-			sk_eat_skb(sk, skb);
+			sk_eat_skb(sk, skb, 0);
 		break;
 	} while (1);
 out:
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 547523b..a2ba9db 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -801,8 +801,7 @@
 		 * We linearize everything except data segments here.
 		 */
 		if (cb->nsp_flags & ~0x60) {
-			if (unlikely(skb_is_nonlinear(skb)) &&
-			    skb_linearize(skb, GFP_ATOMIC) != 0)
+			if (unlikely(skb_linearize(skb)))
 				goto free_out;
 		}
 
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index e172cf9..5abf705 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -629,8 +629,7 @@
 			padlen);
 
         if (flags & DN_RT_PKT_CNTL) {
-		if (unlikely(skb_is_nonlinear(skb)) &&
-		    skb_linearize(skb, GFP_ATOMIC) != 0)
+		if (unlikely(skb_linearize(skb)))
 			goto dump_it;
 
                 switch(flags & DN_RT_CNTL_MSK) {
diff --git a/net/ieee80211/ieee80211_crypt_tkip.c b/net/ieee80211/ieee80211_crypt_tkip.c
index 93def94..3fa5df2 100644
--- a/net/ieee80211/ieee80211_crypt_tkip.c
+++ b/net/ieee80211/ieee80211_crypt_tkip.c
@@ -501,8 +501,11 @@
 static void michael_mic_hdr(struct sk_buff *skb, u8 * hdr)
 {
 	struct ieee80211_hdr_4addr *hdr11;
+	u16 stype;
 
 	hdr11 = (struct ieee80211_hdr_4addr *)skb->data;
+	stype  = WLAN_FC_GET_STYPE(le16_to_cpu(hdr11->frame_ctl));
+
 	switch (le16_to_cpu(hdr11->frame_ctl) &
 		(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
 	case IEEE80211_FCTL_TODS:
@@ -523,7 +526,13 @@
 		break;
 	}
 
-	hdr[12] = 0;		/* priority */
+	if (stype & IEEE80211_STYPE_QOS_DATA) {
+		const struct ieee80211_hdr_3addrqos *qoshdr =
+			(struct ieee80211_hdr_3addrqos *)skb->data;
+		hdr[12] = le16_to_cpu(qoshdr->qos_ctl) & IEEE80211_QCTL_TID;
+	} else
+		hdr[12] = 0;		/* priority */
+
 	hdr[13] = hdr[14] = hdr[15] = 0;	/* reserved */
 }
 
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index 604b7b0..2bf567f 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -369,7 +369,6 @@
 
 	/* Put this code here so that we avoid duplicating it in all
 	 * Rx paths. - Jean II */
-#ifdef CONFIG_WIRELESS_EXT
 #ifdef IW_WIRELESS_SPY		/* defined in iw_handler.h */
 	/* If spy monitoring on */
 	if (ieee->spy_data.spy_number > 0) {
@@ -398,7 +397,6 @@
 		wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
 	}
 #endif				/* IW_WIRELESS_SPY */
-#endif				/* CONFIG_WIRELESS_EXT */
 
 #ifdef NOT_YET
 	hostap_update_rx_stats(local->ap, hdr, rx_stats);
@@ -1692,8 +1690,8 @@
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
 
-		IEEE80211_WARNING("%s: IEEE80211_REASSOC_REQ received\n",
-				  ieee->dev->name);
+		IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n",
+				     ieee->dev->name);
 		if (ieee->handle_reassoc_request != NULL)
 			ieee->handle_reassoc_request(ieee->dev,
 						    (struct ieee80211_reassoc_request *)
@@ -1705,8 +1703,8 @@
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
 
-		IEEE80211_WARNING("%s: IEEE80211_ASSOC_REQ received\n",
-				  ieee->dev->name);
+		IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n",
+				     ieee->dev->name);
 		if (ieee->handle_assoc_request != NULL)
 			ieee->handle_assoc_request(ieee->dev);
 		break;
@@ -1722,10 +1720,10 @@
 		IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
 				     WLAN_FC_GET_STYPE(le16_to_cpu
 						       (header->frame_ctl)));
-		IEEE80211_WARNING("%s: Unknown management packet: %d\n",
-				  ieee->dev->name,
-				  WLAN_FC_GET_STYPE(le16_to_cpu
-						    (header->frame_ctl)));
+		IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n",
+				     ieee->dev->name,
+				     WLAN_FC_GET_STYPE(le16_to_cpu
+						       (header->frame_ctl)));
 		break;
 	}
 }
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c
index 8b4332f..6a5de1b8 100644
--- a/net/ieee80211/ieee80211_tx.c
+++ b/net/ieee80211/ieee80211_tx.c
@@ -220,13 +220,43 @@
 	return txb;
 }
 
+static int ieee80211_classify(struct sk_buff *skb)
+{
+	struct ethhdr *eth;
+	struct iphdr *ip;
+
+	eth = (struct ethhdr *)skb->data;
+	if (eth->h_proto != __constant_htons(ETH_P_IP))
+		return 0;
+
+	ip = skb->nh.iph;
+	switch (ip->tos & 0xfc) {
+	case 0x20:
+		return 2;
+	case 0x40:
+		return 1;
+	case 0x60:
+		return 3;
+	case 0x80:
+		return 4;
+	case 0xa0:
+		return 5;
+	case 0xc0:
+		return 6;
+	case 0xe0:
+		return 7;
+	default:
+		return 0;
+	}
+}
+
 /* Incoming skb is converted to a txb which consists of
  * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct ieee80211_device *ieee = netdev_priv(dev);
 	struct ieee80211_txb *txb = NULL;
-	struct ieee80211_hdr_3addr *frag_hdr;
+	struct ieee80211_hdr_3addrqos *frag_hdr;
 	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
 	    rts_required;
 	unsigned long flags;
@@ -234,9 +264,10 @@
 	int ether_type, encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
 	int bytes, fc, hdr_len;
 	struct sk_buff *skb_frag;
-	struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
+	struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */
 		.duration_id = 0,
-		.seq_ctl = 0
+		.seq_ctl = 0,
+		.qos_ctl = 0
 	};
 	u8 dest[ETH_ALEN], src[ETH_ALEN];
 	struct ieee80211_crypt_data *crypt;
@@ -282,12 +313,6 @@
 	memcpy(dest, skb->data, ETH_ALEN);
 	memcpy(src, skb->data + ETH_ALEN, ETH_ALEN);
 
-	/* Advance the SKB to the start of the payload */
-	skb_pull(skb, sizeof(struct ethhdr));
-
-	/* Determine total amount of storage required for TXB packets */
-	bytes = skb->len + SNAP_SIZE + sizeof(u16);
-
 	if (host_encrypt || host_build_iv)
 		fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
 		    IEEE80211_FCTL_PROTECTED;
@@ -306,9 +331,23 @@
 		memcpy(header.addr2, src, ETH_ALEN);
 		memcpy(header.addr3, ieee->bssid, ETH_ALEN);
 	}
-	header.frame_ctl = cpu_to_le16(fc);
 	hdr_len = IEEE80211_3ADDR_LEN;
 
+	if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
+		fc |= IEEE80211_STYPE_QOS_DATA;
+		hdr_len += 2;
+
+		skb->priority = ieee80211_classify(skb);
+		header.qos_ctl |= skb->priority & IEEE80211_QCTL_TID;
+	}
+	header.frame_ctl = cpu_to_le16(fc);
+
+	/* Advance the SKB to the start of the payload */
+	skb_pull(skb, sizeof(struct ethhdr));
+
+	/* Determine total amount of storage required for TXB packets */
+	bytes = skb->len + SNAP_SIZE + sizeof(u16);
+
 	/* Encrypt msdu first on the whole data packet. */
 	if ((host_encrypt || host_encrypt_msdu) &&
 	    crypt && crypt->ops && crypt->ops->encrypt_msdu) {
@@ -402,7 +441,7 @@
 	if (rts_required) {
 		skb_frag = txb->fragments[0];
 		frag_hdr =
-		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+		    (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
 
 		/*
 		 * Set header frame_ctl to the RTS.
@@ -433,7 +472,7 @@
 				    crypt->ops->extra_mpdu_prefix_len);
 
 		frag_hdr =
-		    (struct ieee80211_hdr_3addr *)skb_put(skb_frag, hdr_len);
+		    (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
 		memcpy(frag_hdr, &header, hdr_len);
 
 		/* If this is not the last fragment, then add the MOREFRAGS
@@ -516,7 +555,8 @@
 /* Incoming 802.11 strucure is converted to a TXB
  * a block of 802.11 fragment packets (stored as skbs) */
 int ieee80211_tx_frame(struct ieee80211_device *ieee,
-		       struct ieee80211_hdr *frame, int len)
+		       struct ieee80211_hdr *frame, int hdr_len, int total_len,
+		       int encrypt_mpdu)
 {
 	struct ieee80211_txb *txb = NULL;
 	unsigned long flags;
@@ -526,6 +566,9 @@
 
 	spin_lock_irqsave(&ieee->lock, flags);
 
+	if (encrypt_mpdu && !ieee->sec.encrypt)
+		encrypt_mpdu = 0;
+
 	/* If there is no driver handler to take the TXB, dont' bother
 	 * creating it... */
 	if (!ieee->hard_start_xmit) {
@@ -533,32 +576,41 @@
 		goto success;
 	}
 
-	if (unlikely(len < 24)) {
+	if (unlikely(total_len < 24)) {
 		printk(KERN_WARNING "%s: skb too small (%d).\n",
-		       ieee->dev->name, len);
+		       ieee->dev->name, total_len);
 		goto success;
 	}
 
+	if (encrypt_mpdu)
+		frame->frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
 	/* When we allocate the TXB we allocate enough space for the reserve
 	 * and full fragment bytes (bytes_per_frag doesn't include prefix,
 	 * postfix, header, FCS, etc.) */
-	txb = ieee80211_alloc_txb(1, len, ieee->tx_headroom, GFP_ATOMIC);
+	txb = ieee80211_alloc_txb(1, total_len, ieee->tx_headroom, GFP_ATOMIC);
 	if (unlikely(!txb)) {
 		printk(KERN_WARNING "%s: Could not allocate TXB\n",
 		       ieee->dev->name);
 		goto failed;
 	}
 	txb->encrypted = 0;
-	txb->payload_size = len;
+	txb->payload_size = total_len;
 
 	skb_frag = txb->fragments[0];
 
-	memcpy(skb_put(skb_frag, len), frame, len);
+	memcpy(skb_put(skb_frag, total_len), frame, total_len);
 
 	if (ieee->config &
 	    (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
 		skb_put(skb_frag, 4);
 
+	/* To avoid overcomplicating things, we do the corner-case frame
+	 * encryption in software. The only real situation where encryption is
+	 * needed here is during software-based shared key authentication. */
+	if (encrypt_mpdu)
+		ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+
       success:
 	spin_unlock_irqrestore(&ieee->lock, flags);
 
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index b885fd1..a78c4f8 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -50,7 +50,8 @@
 	char *p;
 	struct iw_event iwe;
 	int i, j;
-	u8 max_rate, rate;
+	char *current_val;	/* For rates */
+	u8 rate;
 
 	/* First entry *MUST* be the AP MAC address */
 	iwe.cmd = SIOCGIWAP;
@@ -107,9 +108,13 @@
 	start = iwe_stream_add_point(start, stop, &iwe, network->ssid);
 
 	/* Add basic and extended rates */
-	max_rate = 0;
-	p = custom;
-	p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): ");
+	/* Rate : stuffing multiple values in a single event require a bit
+	 * more of magic - Jean II */
+	current_val = start + IW_EV_LCP_LEN;
+	iwe.cmd = SIOCGIWRATE;
+	/* Those two flags are ignored... */
+	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
 	for (i = 0, j = 0; i < network->rates_len;) {
 		if (j < network->rates_ex_len &&
 		    ((network->rates_ex[j] & 0x7F) <
@@ -117,28 +122,21 @@
 			rate = network->rates_ex[j++] & 0x7F;
 		else
 			rate = network->rates[i++] & 0x7F;
-		if (rate > max_rate)
-			max_rate = rate;
-		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
+		/* Bit rate given in 500 kb/s units (+ 0x80) */
+		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+		/* Add new value to event */
+		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
 	}
 	for (; j < network->rates_ex_len; j++) {
 		rate = network->rates_ex[j] & 0x7F;
-		p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
-			      "%d%s ", rate >> 1, (rate & 1) ? ".5" : "");
-		if (rate > max_rate)
-			max_rate = rate;
+		/* Bit rate given in 500 kb/s units (+ 0x80) */
+		iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+		/* Add new value to event */
+		current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN);
 	}
-
-	iwe.cmd = SIOCGIWRATE;
-	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-	iwe.u.bitrate.value = max_rate * 500000;
-	start = iwe_stream_add_event(start, stop, &iwe, IW_EV_PARAM_LEN);
-
-	iwe.cmd = IWEVCUSTOM;
-	iwe.u.data.length = p - custom;
-	if (iwe.u.data.length)
-		start = iwe_stream_add_point(start, stop, &iwe, custom);
+	/* Check if we added any rate */
+	if((current_val - start) > IW_EV_LCP_LEN)
+		start = current_val;
 
 	/* Add quality statistics */
 	iwe.cmd = IWEVQUAL;
@@ -505,7 +503,7 @@
 	len = sec->key_sizes[key];
 	memcpy(keybuf, sec->keys[key], len);
 
-	erq->length = (len >= 0 ? len : 0);
+	erq->length = len;
 	erq->flags |= IW_ENCODE_ENABLED;
 
 	if (ieee->open_wep)
diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig
index f2a27cc..2811651 100644
--- a/net/ieee80211/softmac/Kconfig
+++ b/net/ieee80211/softmac/Kconfig
@@ -2,6 +2,7 @@
 	tristate "Software MAC add-on to the IEEE 802.11 networking stack"
 	depends on IEEE80211 && EXPERIMENTAL
 	select WIRELESS_EXT
+	select IEEE80211_CRYPT_WEP
 	---help---
 	This option enables the hardware independent software MAC addon
 	for the IEEE 802.11 networking stack.
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index 57ea9f6..5e9a906 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -82,51 +82,52 @@
 	ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
 }
 
-/* Sends out a disassociation request to the desired AP */
-static void
-ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
+void
+ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
 {
 	unsigned long flags;
+
+	spin_lock_irqsave(&mac->lock, flags);
+	if (mac->associnfo.associating)
+		cancel_delayed_work(&mac->associnfo.timeout);
+
+	netif_carrier_off(mac->dev);
+
+	mac->associated = 0;
+	mac->associnfo.bssvalid = 0;
+	mac->associnfo.associating = 0;
+	ieee80211softmac_init_txrates(mac);
+	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+	spin_unlock_irqrestore(&mac->lock, flags);
+}
+
+/* Sends out a disassociation request to the desired AP */
+void
+ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason)
+{
 	struct ieee80211softmac_network *found;
 
 	if (mac->associnfo.bssvalid && mac->associated) {
 		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
 		if (found)
 			ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
-	} else if (mac->associnfo.associating) {
-		cancel_delayed_work(&mac->associnfo.timeout);
 	}
 
-	/* Change our state */
-	spin_lock_irqsave(&mac->lock, flags);
-	/* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
-	mac->associated = 0;
-	mac->associnfo.associating = 0;
-	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
-	spin_unlock_irqrestore(&mac->lock, flags);
+	ieee80211softmac_disassoc(mac);
 }
 
 static inline int
 we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
 {
-	int idx, search, found;
-	u8 rate, search_rate;
+	int idx;
+	u8 rate;
 
 	for (idx = 0; idx < (from_len); idx++) {
 		rate = (from)[idx];
 		if (!(rate & IEEE80211_BASIC_RATE_MASK))
 			continue;
-		found = 0;
 		rate &= ~IEEE80211_BASIC_RATE_MASK;
-		for (search = 0; search < mac->ratesinfo.count; search++) {
-			search_rate = mac->ratesinfo.rates[search];
-			search_rate &= ~IEEE80211_BASIC_RATE_MASK;
-			if (rate == search_rate) {
-				found = 1;
-				break;
-			}
-		}
-		if (!found)
+		if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
 			return 0;
 	}
 	return 1;
@@ -163,12 +164,28 @@
 }
 
 static void
-ieee80211softmac_assoc_notify(struct net_device *dev, void *context)
+ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context)
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
 	ieee80211softmac_assoc_work((void*)mac);
 }
 
+static void
+ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context)
+{
+	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+	switch (event_type) {
+	case IEEE80211SOFTMAC_EVENT_AUTHENTICATED:
+		ieee80211softmac_assoc_work((void*)mac);
+		break;
+	case IEEE80211SOFTMAC_EVENT_AUTH_FAILED:
+	case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT:
+		ieee80211softmac_disassoc(mac);
+		break;
+	}
+}
+
 /* This function is called to handle userspace requests (asynchronously) */
 void
 ieee80211softmac_assoc_work(void *d)
@@ -176,14 +193,18 @@
 	struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
 	struct ieee80211softmac_network *found = NULL;
 	struct ieee80211_network *net = NULL, *best = NULL;
+	int bssvalid;
 	unsigned long flags;
-	
+
+	/* ieee80211_disassoc might clear this */
+	bssvalid = mac->associnfo.bssvalid;
+
 	/* meh */
 	if (mac->associated)
-		ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
+		ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
 
 	/* try to find the requested network in our list, if we found one already */
-	if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
+	if (bssvalid || mac->associnfo.bssfixed)
 		found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);	
 	
 	/* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -244,7 +265,7 @@
 			 * Maybe we can hope to have more memory after scanning finishes ;)
 			 */
 			dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n");
-			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify, NULL);
+			ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL);
 			if (ieee80211softmac_start_scan(mac))
 				dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n");
 			return;
@@ -279,7 +300,7 @@
 		 * otherwise adding the notification would be racy. */
 		if (!ieee80211softmac_auth_req(mac, found)) {
 			dprintk(KERN_INFO PFX "cannot associate without being authenticated, requested authentication\n");
-			ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify, NULL, GFP_KERNEL);
+			ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL);
 		} else {
 			printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n");
 			ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found);
@@ -297,6 +318,9 @@
 	struct ieee80211softmac_network *net)
 {
 	mac->associnfo.associating = 0;
+	mac->associnfo.supported_rates = net->supported_rates;
+	ieee80211softmac_recalc_txrates(mac);
+
 	mac->associated = 1;
 	if (mac->set_bssid_filter)
 		mac->set_bssid_filter(mac->dev, net->bssid);
@@ -380,7 +404,6 @@
 				 struct ieee80211_disassoc *disassoc)
 {
 	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-	unsigned long flags;
 
 	if (unlikely(!mac->running))
 		return -ENODEV;
@@ -392,14 +415,11 @@
 		return 0;
 
 	dprintk(KERN_INFO PFX "got disassoc frame\n");
-	netif_carrier_off(dev);
-	spin_lock_irqsave(&mac->lock, flags);
-	mac->associnfo.bssvalid = 0;
-	mac->associated = 0;
-	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+	ieee80211softmac_disassoc(mac);
+
+	/* try to reassociate */
 	schedule_work(&mac->associnfo.work);
-	spin_unlock_irqrestore(&mac->lock, flags);
-	
+
 	return 0;
 }
 
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 06e3326..90b8484 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -107,6 +107,7 @@
 	printkl(KERN_WARNING PFX "Authentication timed out with "MAC_FMT"\n", MAC_ARG(net->bssid));
 	/* Remove this item from the queue */
 	spin_lock_irqsave(&mac->lock, flags);
+	net->authenticating = 0;
 	ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net);
 	cancel_delayed_work(&auth->work); /* just to make sure... */
 	list_del(&auth->list);
@@ -212,13 +213,13 @@
 			aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; 
 			spin_unlock_irqrestore(&mac->lock, flags);
 
-			/* Switch to correct channel for this network */
-			mac->set_channel(mac->dev, net->channel);
-			
-			/* Send our response (How to encrypt?) */
+			/* Send our response */
 			ieee80211softmac_send_mgt_frame(mac, aq->net, IEEE80211_STYPE_AUTH, aq->state);
-			break;
+			return 0;
 		case IEEE80211SOFTMAC_AUTH_SHARED_PASS:
+			kfree(net->challenge);
+			net->challenge = NULL;
+			net->challenge_len = 0;
 			/* Check the status code of the response */
 			switch(auth->status) {
 			case WLAN_STATUS_SUCCESS:
@@ -229,6 +230,7 @@
 				spin_unlock_irqrestore(&mac->lock, flags);
 				printkl(KERN_NOTICE PFX "Shared Key Authentication completed with "MAC_FMT"\n", 
 					MAC_ARG(net->bssid));
+				ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net);
 				break;
 			default:
 				printkl(KERN_NOTICE PFX "Shared Key Authentication with "MAC_FMT" failed, error code: %i\n", 
@@ -279,6 +281,9 @@
 	struct list_head *list_ptr;
 	unsigned long flags;
 
+	/* deauthentication implies disassociation */
+	ieee80211softmac_disassoc(mac);
+
 	/* Lock and reset status flags */
 	spin_lock_irqsave(&mac->lock, flags);
 	net->authenticating = 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c
index 8cc8f3f..f34fa2e 100644
--- a/net/ieee80211/softmac/ieee80211softmac_event.c
+++ b/net/ieee80211/softmac/ieee80211softmac_event.c
@@ -38,7 +38,8 @@
  * The event context is private and can only be used from
  * within this module. Its meaning varies with the event
  * type:
- *  SCAN_FINISHED:	no special meaning
+ *  SCAN_FINISHED,
+ *  DISASSOCIATED:	NULL
  *  ASSOCIATED,
  *  ASSOCIATE_FAILED,
  *  ASSOCIATE_TIMEOUT,
@@ -59,15 +60,15 @@
  */
 
 static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = {
-	"scan finished",
-	"associated",
+	NULL, /* scan finished */
+	NULL, /* associated */
 	"associating failed",
 	"associating timed out",
 	"authenticated",
 	"authenticating failed",
 	"authenticating timed out",
 	"associating failed because no suitable network was found",
-	"disassociated",
+	NULL, /* disassociated */
 };
 
 
@@ -77,7 +78,7 @@
 	struct ieee80211softmac_event event = *(struct ieee80211softmac_event*) d;
 	kfree(d);
 	
-	event.fun(event.mac->dev, event.context);
+	event.fun(event.mac->dev, event.event_type, event.context);
 }
 
 int
@@ -136,30 +137,24 @@
 		int we_event;
 		char *msg = NULL;
 
+		memset(&wrqu, '\0', sizeof (union iwreq_data));
+
 		switch(event) {
 		case IEEE80211SOFTMAC_EVENT_ASSOCIATED:
 			network = (struct ieee80211softmac_network *)event_ctx;
-			wrqu.data.length = 0;
-			wrqu.data.flags = 0;
 			memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN);
-			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-			we_event = SIOCGIWAP;
-			break;
+			/* fall through */
 		case IEEE80211SOFTMAC_EVENT_DISASSOCIATED:
-			wrqu.data.length = 0;
-			wrqu.data.flags = 0;
-			memset(&wrqu, '\0', sizeof (union iwreq_data));
 			wrqu.ap_addr.sa_family = ARPHRD_ETHER;
 			we_event = SIOCGIWAP;
 			break;
 		case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED:
-			wrqu.data.length = 0;
-			wrqu.data.flags = 0;
-			memset(&wrqu, '\0', sizeof (union iwreq_data));
 			we_event = SIOCGIWSCAN;
 			break;
 		default:
 			msg = event_descriptions[event];
+			if (!msg)
+				msg = "SOFTMAC EVENT BUG";
 			wrqu.data.length = strlen(msg);
 			we_event = IWEVCUSTOM;
 			break;
@@ -172,6 +167,9 @@
 			if ((eventptr->event_type == event || eventptr->event_type == -1)
 				&& (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) {
 				list_del(&eventptr->list);
+				/* User may have subscribed to ANY event, so
+				 * we tell them which event triggered it. */
+				eventptr->event_type = event;
 				schedule_work(&eventptr->work);
 			}
 		}
diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c
index cc6cd56..0954161 100644
--- a/net/ieee80211/softmac/ieee80211softmac_io.c
+++ b/net/ieee80211/softmac/ieee80211softmac_io.c
@@ -149,6 +149,56 @@
 	 * shouldn't the sequence number be in ieee80211? */
 }
 
+static u16
+ieee80211softmac_capabilities(struct ieee80211softmac_device *mac,
+	struct ieee80211softmac_network *net)
+{
+	u16 capability = 0;
+
+	/* ESS and IBSS bits are set according to the current mode */
+	switch (mac->ieee->iw_mode) {
+	case IW_MODE_INFRA:
+		capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
+		break;
+	case IW_MODE_ADHOC:
+		capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
+		break;
+	case IW_MODE_AUTO:
+		capability = net->capabilities &
+			(WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
+		break;
+	default:
+		/* bleh. we don't ever go to these modes */
+		printk(KERN_ERR PFX "invalid iw_mode!\n");
+		break;
+	}
+
+	/* CF Pollable / CF Poll Request */
+	/* Needs to be implemented, for now, the 0's == not supported */
+
+	/* Privacy Bit */
+	capability |= mac->ieee->sec.level ?
+		cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
+
+	/* Short Preamble */
+	/* Always supported: we probably won't ever be powering devices which
+	 * dont support this... */
+	capability |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+	/* PBCC */
+	/* Not widely used */
+
+	/* Channel Agility */
+	/* Not widely used */
+
+	/* Short Slot */
+	/* Will be implemented later */
+
+	/* DSSS-OFDM */
+	/* Not widely used */
+
+	return capability;
+}
 
 /*****************************************************************************
  * Create Management packets
@@ -179,27 +229,6 @@
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid);
 
-	/* Fill in capability Info */
-	switch (mac->ieee->iw_mode) {
-	case IW_MODE_INFRA:
-		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS);
-		break;
-	case IW_MODE_ADHOC:
-		(*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS);
-		break;
-	case IW_MODE_AUTO:
-		(*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS);
-		break;
-	default:
-		/* bleh. we don't ever go to these modes */
-		printk(KERN_ERR PFX "invalid iw_mode!\n");
-		break;
-	}
-	/* Need to add this
-	(*pkt)->capability |= mac->ieee->short_slot ? 
-			cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
-	 */
-	(*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
 	/* Fill in Listen Interval (?) */
 	(*pkt)->listen_interval = cpu_to_le16(10);
 	
@@ -239,17 +268,9 @@
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid);
 
-	/* Fill in capability Info */
-	(*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? 
-				cpu_to_le16(WLAN_CAPABILITY_ESS) :
-				cpu_to_le16(WLAN_CAPABILITY_IBSS);
-	/*
-	(*pkt)->capability |= mac->ieee->short_slot ? 
-			cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0;
-	 */
-	(*pkt)->capability |= mac->ieee->sec.level ?
-			cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0;
-		
+	/* Fill in the capabilities */
+	(*pkt)->capability = ieee80211softmac_capabilities(mac, net);
+
 	/* Fill in Listen Interval (?) */
 	(*pkt)->listen_interval = cpu_to_le16(10);
 	/* Fill in the current AP MAC */
@@ -268,26 +289,27 @@
 static u32
 ieee80211softmac_auth(struct ieee80211_auth **pkt, 
 	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net,
-	u16 transaction, u16 status)
+	u16 transaction, u16 status, int *encrypt_mpdu)
 {
 	u8 *data;
+	int auth_mode = mac->ieee->sec.auth_mode;
+	int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY
+		&& transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE);
+
 	/* Allocate Packet */
 	(*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt(
 		2 +		/* Auth Algorithm */
 		2 +		/* Auth Transaction Seq */
 		2 +		/* Status Code */
 		 /* Challenge Text IE */
-		mac->ieee->open_wep ? 0 : 
-		1 + 1 + WLAN_AUTH_CHALLENGE_LEN
-	);	
+		is_shared_response ? 0 : 1 + 1 + net->challenge_len
+	);
 	if (unlikely((*pkt) == NULL))
 		return 0;
 	ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid);
 		
 	/* Algorithm */
-	(*pkt)->algorithm = mac->ieee->open_wep ? 
-		cpu_to_le16(WLAN_AUTH_OPEN) :
-		cpu_to_le16(WLAN_AUTH_SHARED_KEY);
+	(*pkt)->algorithm = cpu_to_le16(auth_mode);
 	/* Transaction */
 	(*pkt)->transaction = cpu_to_le16(transaction);
 	/* Status */
@@ -295,18 +317,20 @@
 	
 	data = (u8 *)(*pkt)->info_element;
 	/* Challenge Text */
-	if(!mac->ieee->open_wep){
+	if (is_shared_response) {
 		*data = MFIE_TYPE_CHALLENGE;
 		data++;
 		
 		/* Copy the challenge in */
-		// *data = challenge length
-		// data += sizeof(u16);
-		// memcpy(data, challenge, challenge length);
-		// data += challenge length;
-		
-		/* Add the full size to the packet length */
-	}
+		*data = net->challenge_len;
+		data++;
+		memcpy(data, net->challenge, net->challenge_len);
+		data += net->challenge_len;
+
+		/* Make sure this frame gets encrypted with the shared key */
+		*encrypt_mpdu = 1;
+	} else
+		*encrypt_mpdu = 0;
 
 	/* Return the packet size */
 	return (data - (u8 *)(*pkt));
@@ -396,6 +420,7 @@
 {
 	void *pkt = NULL;
 	u32 pkt_size = 0;
+	int encrypt_mpdu = 0;
 
 	switch(type) {
 	case IEEE80211_STYPE_ASSOC_REQ:
@@ -405,7 +430,7 @@
 		pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg);
 		break;
 	case IEEE80211_STYPE_AUTH:
-		pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16));
+		pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu);
 		break;
 	case IEEE80211_STYPE_DISASSOC:
 	case IEEE80211_STYPE_DEAUTH:
@@ -434,52 +459,8 @@
 	 * or get rid of it alltogether?
 	 * Does this work for you now?
 	 */
-	ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, pkt_size);
-
-	kfree(pkt);
-	return 0;
-}
-
-
-/* Create an rts/cts frame */
-static u32
-ieee80211softmac_rts_cts(struct ieee80211_hdr_2addr **pkt,
-	struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, 
-	u32 type)
-{
-	/* Allocate Packet */
-	(*pkt) = kmalloc(IEEE80211_2ADDR_LEN, GFP_ATOMIC);	
-	memset(*pkt, 0, IEEE80211_2ADDR_LEN);
-	if((*pkt) == NULL)
-		return 0;
-	ieee80211softmac_hdr_2addr(mac, (*pkt), type, net->bssid);
-	return IEEE80211_2ADDR_LEN;
-}
-
-
-/* Sends a control packet */
-static int
-ieee80211softmac_send_ctl_frame(struct ieee80211softmac_device *mac,
-	struct ieee80211softmac_network *net, u32 type, u32 arg)
-{
-	void *pkt = NULL;
-	u32 pkt_size = 0;
-	
-	switch(type) {
-	case IEEE80211_STYPE_RTS:
-	case IEEE80211_STYPE_CTS:
-		pkt_size = ieee80211softmac_rts_cts((struct ieee80211_hdr_2addr **)(&pkt), mac, net, type);
-		break;
-	default:
-		printkl(KERN_DEBUG PFX "Unsupported Control Frame type: %i\n", type);
-		return -EINVAL;
-	}
-
-	if(pkt_size == 0)
-		return -ENOMEM;
-	
-	/* Send the packet to the ieee80211 layer for tx */
-	ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *) pkt, pkt_size);
+	ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt,
+		IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu);
 
 	kfree(pkt);
 	return 0;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 6252be2..4b2e57d 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -26,6 +26,7 @@
 
 #include "ieee80211softmac_priv.h"
 #include <linux/sort.h>
+#include <linux/etherdevice.h>
 
 struct net_device *alloc_ieee80211softmac(int sizeof_priv)
 {
@@ -61,14 +62,6 @@
 	softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
 	softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
 
-	//TODO: The mcast rate has to be assigned dynamically somewhere (in scanning, association. Not sure...)
-	//      It has to be set to the highest rate all stations in the current network can handle.
-	softmac->txrates.mcast_rate = IEEE80211_CCK_RATE_1MB;
-	softmac->txrates.mcast_fallback = IEEE80211_CCK_RATE_1MB;
-	/* This is reassigned in ieee80211softmac_start to sane values. */
-	softmac->txrates.default_rate = IEEE80211_CCK_RATE_1MB;
-	softmac->txrates.default_fallback = IEEE80211_CCK_RATE_1MB;
-
 	/* to start with, we can't send anything ... */
 	netif_carrier_off(dev);
 	
@@ -170,15 +163,82 @@
 	}
 }
 
-void ieee80211softmac_start(struct net_device *dev)
+int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
 {
-	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+	int search;
+	u8 search_rate;
+
+	for (search = 0; search < ri->count; search++) {
+		search_rate = ri->rates[search];
+		search_rate &= ~IEEE80211_BASIC_RATE_MASK;
+		if (rate == search_rate)
+			return 1;
+	}
+
+	return 0;
+}
+
+/* Finds the highest rate which is:
+ *  1. Present in ri (optionally a basic rate)
+ *  2. Supported by the device
+ *  3. Less than or equal to the user-defined rate
+ */
+static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
+	struct ieee80211softmac_ratesinfo *ri, int basic_only)
+{
+	u8 user_rate = mac->txrates.user_rate;
+	int i;
+
+	if (ri->count == 0) {
+		dprintk(KERN_ERR PFX "empty ratesinfo?\n");
+		return IEEE80211_CCK_RATE_1MB;
+	}
+
+	for (i = ri->count - 1; i >= 0; i--) {
+		u8 rate = ri->rates[i];
+		if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
+			continue;
+		rate &= ~IEEE80211_BASIC_RATE_MASK;
+		if (rate > user_rate)
+			continue;
+		if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
+			return rate;
+	}
+
+	/* If we haven't found a suitable rate by now, just trust the user */
+	return user_rate;
+}
+
+void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
+{
+	struct ieee80211softmac_txrates *txrates = &mac->txrates;
+	struct ieee80211softmac_txrates oldrates;
+	u32 change = 0;
+
+	if (mac->txrates_change)
+		oldrates = mac->txrates;
+
+	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+	txrates->default_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 0);
+
+	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+	txrates->default_fallback = lower_rate(mac, txrates->default_rate);
+
+	change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+	txrates->mcast_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 1);
+
+	if (mac->txrates_change)
+		mac->txrates_change(mac->dev, change, &oldrates);
+
+}
+
+void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
+{
 	struct ieee80211_device *ieee = mac->ieee;
 	u32 change = 0;
+	struct ieee80211softmac_txrates *txrates = &mac->txrates;
 	struct ieee80211softmac_txrates oldrates;
 
-	ieee80211softmac_start_check_rates(mac);
-
 	/* TODO: We need some kind of state machine to lower the default rates
 	 *       if we loose too many packets.
 	 */
@@ -193,22 +253,37 @@
 	   more reliable. Note similar logic in
 	   ieee80211softmac_wx_set_rate() */	 
 	if (ieee->modulation & IEEE80211_CCK_MODULATION) {
-		mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB;
-		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-		mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB;
-		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+		txrates->user_rate = IEEE80211_CCK_RATE_11MB;
 	} else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-		mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
-		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-		mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
-		change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+		txrates->user_rate = IEEE80211_OFDM_RATE_54MB;
 	} else
 		assert(0);
+
+	txrates->default_rate = IEEE80211_CCK_RATE_1MB;
+	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+
+	txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
+	change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+
+	txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
+	change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+
+	txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
+	change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
+
 	if (mac->txrates_change)
-		mac->txrates_change(dev, change, &oldrates);
+		mac->txrates_change(mac->dev, change, &oldrates);
 
 	mac->running = 1;
 }
+
+void ieee80211softmac_start(struct net_device *dev)
+{
+	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+	ieee80211softmac_start_check_rates(mac);
+	ieee80211softmac_init_txrates(mac);
+}
 EXPORT_SYMBOL_GPL(ieee80211softmac_start);
 
 void ieee80211softmac_stop(struct net_device *dev)
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
index 65d9816..fa1f8e3 100644
--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -116,7 +116,10 @@
 	struct ieee80211softmac_essid *essid);
 
 /* Rates related */
+int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
 u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
+void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac);
+void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
 static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
 	return ieee80211softmac_lower_rate_delta(mac, rate, 1);
 }
@@ -150,6 +153,8 @@
 int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
 				        struct ieee80211_reassoc_request * reassoc);
 void ieee80211softmac_assoc_timeout(void *d);
+void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
+void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
 
 /* some helper functions */
 static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 27edb2b..0e65ff4 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -211,8 +211,8 @@
 	if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
 		goto out_unlock;
 
-	mac->txrates.default_rate = rate;
-	mac->txrates.default_fallback = lower_rate(mac, rate);
+	mac->txrates.user_rate = rate;
+	ieee80211softmac_recalc_txrates(mac);
 	err = 0;
 
 out_unlock:	
@@ -388,7 +388,7 @@
 		memcpy(mac->wpa.IE, extra, wrqu->data.length);
 		dprintk(KERN_INFO PFX "generic IE set to ");
 		for (i=0;i<wrqu->data.length;i++)
-			dprintk("%.2x", mac->wpa.IE[i]);
+			dprintk("%.2x", (u8)mac->wpa.IE[i]);
 		dprintk("\n");
 		mac->wpa.IElen = wrqu->data.length;
 	} else {
@@ -431,3 +431,35 @@
 }
 EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
 
+int
+ieee80211softmac_wx_set_mlme(struct net_device *dev,
+			     struct iw_request_info *info,
+			     union iwreq_data *wrqu,
+			     char *extra)
+{
+	struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+	struct iw_mlme *mlme = (struct iw_mlme *)extra;
+	u16 reason = cpu_to_le16(mlme->reason_code);
+	struct ieee80211softmac_network *net;
+
+	if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) {
+		printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n");
+		return -EINVAL;
+	}
+
+	switch (mlme->cmd) {
+	case IW_MLME_DEAUTH:
+		net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data);
+		if (!net) {
+			printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n");
+			return -EINVAL;
+		}
+		return ieee80211softmac_deauth_req(mac, net, reason);
+	case IW_MLME_DISASSOC:
+		ieee80211softmac_send_disassoc_req(mac, reason);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme);
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index e40f753..da33393 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -414,6 +414,24 @@
 	tristate
 	default n
 
+config INET_XFRM_MODE_TRANSPORT
+	tristate "IP: IPsec transport mode"
+	default y
+	select XFRM
+	---help---
+	  Support for IPsec transport mode.
+
+	  If unsure, say Y.
+
+config INET_XFRM_MODE_TUNNEL
+	tristate "IP: IPsec tunnel mode"
+	default y
+	select XFRM
+	---help---
+	  Support for IPsec tunnel mode.
+
+	  If unsure, say Y.
+
 config INET_DIAG
 	tristate "INET: socket monitoring interface"
 	default y
@@ -532,6 +550,38 @@
 	properties, though is known to have fairness issues.
 	See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
 
+config TCP_CONG_LP
+	tristate "TCP Low Priority"
+	depends on EXPERIMENTAL
+	default n
+	---help---
+	TCP Low Priority (TCP-LP), a distributed algorithm whose goal is
+	to utiliza only the excess network bandwidth as compared to the
+	``fair share`` of bandwidth as targeted by TCP.
+	See http://www-ece.rice.edu/networks/TCP-LP/
+
+config TCP_CONG_VENO
+	tristate "TCP Veno"
+	depends on EXPERIMENTAL
+	default n
+	---help---
+	TCP Veno is a sender-side only enhancement of TCP to obtain better
+	throughput over wireless networks. TCP Veno makes use of state
+	distinguishing to circumvent the difficult judgment of the packet loss
+	type. TCP Veno cuts down less congestion window in response to random
+	loss packets.
+	See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+
+config TCP_CONG_COMPOUND
+	tristate "TCP Compound"
+	depends on EXPERIMENTAL
+	default n
+	---help---
+	TCP Compound is a sender-side only change to TCP that uses
+	a mixed Reno/Vegas approach to calculate the cwnd.
+	For further details look here:
+	  ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf
+
 endmenu
 
 config TCP_CONG_BIC
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 9ef50a0..38b8039 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -24,6 +24,8 @@
 obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
 obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
 obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
+obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
+obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
 obj-$(CONFIG_IP_PNP) += ipconfig.o
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
@@ -34,6 +36,7 @@
 obj-$(CONFIG_INET_DIAG) += inet_diag.o 
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
 obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
+obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
 obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
 obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o
 obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
@@ -41,7 +44,10 @@
 obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
 obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
 obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
+obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o
 obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
+obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
+obj-$(CONFIG_TCP_CONG_COMPOUND) += tcp_compound.o
 
 obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
 		      xfrm4_output.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 0a27745..461216b 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -68,6 +68,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -1096,6 +1097,54 @@
 
 EXPORT_SYMBOL(inet_sk_rebuild_header);
 
+static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
+{
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	struct iphdr *iph;
+	struct net_protocol *ops;
+	int proto;
+	int ihl;
+	int id;
+
+	if (!pskb_may_pull(skb, sizeof(*iph)))
+		goto out;
+
+	iph = skb->nh.iph;
+	ihl = iph->ihl * 4;
+	if (ihl < sizeof(*iph))
+		goto out;
+
+	if (!pskb_may_pull(skb, ihl))
+		goto out;
+
+	skb->h.raw = __skb_pull(skb, ihl);
+	iph = skb->nh.iph;
+	id = ntohs(iph->id);
+	proto = iph->protocol & (MAX_INET_PROTOS - 1);
+	segs = ERR_PTR(-EPROTONOSUPPORT);
+
+	rcu_read_lock();
+	ops = rcu_dereference(inet_protos[proto]);
+	if (ops && ops->gso_segment)
+		segs = ops->gso_segment(skb, sg);
+	rcu_read_unlock();
+
+	if (IS_ERR(segs))
+		goto out;
+
+	skb = segs;
+	do {
+		iph = skb->nh.iph;
+		iph->id = htons(id++);
+		iph->tot_len = htons(skb->len - skb->mac_len);
+		iph->check = 0;
+		iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
+	} while ((skb = skb->next));
+
+out:
+	return segs;
+}
+
 #ifdef CONFIG_IP_MULTICAST
 static struct net_protocol igmp_protocol = {
 	.handler =	igmp_rcv,
@@ -1105,6 +1154,7 @@
 static struct net_protocol tcp_protocol = {
 	.handler =	tcp_v4_rcv,
 	.err_handler =	tcp_v4_err,
+	.gso_segment =	tcp_tso_segment,
 	.no_policy =	1,
 };
 
@@ -1150,6 +1200,7 @@
 static struct packet_type ip_packet_type = {
 	.type = __constant_htons(ETH_P_IP),
 	.func = ip_rcv,
+	.gso_segment = inet_gso_segment,
 };
 
 static int __init inet_init(void)
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e2e4771..c778223 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -119,6 +119,7 @@
 static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int ah_hlen;
+	int ihl;
 	struct iphdr *iph;
 	struct ip_auth_hdr *ah;
 	struct ah_data *ahp;
@@ -149,13 +150,14 @@
 	ah = (struct ip_auth_hdr*)skb->data;
 	iph = skb->nh.iph;
 
-	memcpy(work_buf, iph, iph->ihl*4);
+	ihl = skb->data - skb->nh.raw;
+	memcpy(work_buf, iph, ihl);
 
 	iph->ttl = 0;
 	iph->tos = 0;
 	iph->frag_off = 0;
 	iph->check = 0;
-	if (iph->ihl != 5) {
+	if (ihl > sizeof(*iph)) {
 		u32 dummy;
 		if (ip_clear_mutable_options(iph, &dummy))
 			goto out;
@@ -164,7 +166,7 @@
 		u8 auth_data[MAX_AH_AUTH_LEN];
 		
 		memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
-		skb_push(skb, skb->data - skb->nh.raw);
+		skb_push(skb, ihl);
 		ahp->icv(ahp, skb, ah->auth_data);
 		if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
 			x->stats.integrity_failed++;
@@ -172,11 +174,8 @@
 		}
 	}
 	((struct iphdr*)work_buf)->protocol = ah->nexthdr;
-	skb->nh.raw = skb_pull(skb, ah_hlen);
-	memcpy(skb->nh.raw, work_buf, iph->ihl*4);
-	skb->nh.iph->tot_len = htons(skb->len);
-	skb_pull(skb, skb->nh.iph->ihl*4);
-	skb->h.raw = skb->data;
+	skb->h.raw = memcpy(skb->nh.raw += ah_hlen, work_buf, ihl);
+	__skb_pull(skb, ah_hlen + ihl);
 
 	return 0;
 
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 9d1881c..9bbdd449 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -143,10 +143,9 @@
 	int alen = esp->auth.icv_trunc_len;
 	int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
 	int nfrags;
-	int encap_len = 0;
+	int ihl;
 	u8 nexthdr[2];
 	struct scatterlist *sg;
-	u8 workbuf[60];
 	int padlen;
 
 	if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
@@ -177,7 +176,6 @@
 	skb->ip_summed = CHECKSUM_NONE;
 
 	esph = (struct ip_esp_hdr*)skb->data;
-	iph = skb->nh.iph;
 
 	/* Get ivec. This can be wrong, check against another impls. */
 	if (esp->conf.ivlen)
@@ -204,12 +202,12 @@
 
 	/* ... check padding bits here. Silly. :-) */ 
 
+	iph = skb->nh.iph;
+	ihl = iph->ihl * 4;
+
 	if (x->encap) {
 		struct xfrm_encap_tmpl *encap = x->encap;
-		struct udphdr *uh;
-
-		uh = (struct udphdr *)(iph + 1);
-		encap_len = (void*)esph - (void*)uh;
+		struct udphdr *uh = (void *)(skb->nh.raw + ihl);
 
 		/*
 		 * 1) if the NAT-T peer's IP or port changed then
@@ -246,11 +244,7 @@
 
 	iph->protocol = nexthdr[1];
 	pskb_trim(skb, skb->len - alen - padlen - 2);
-	memcpy(workbuf, skb->nh.raw, iph->ihl*4);
-	skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
-	skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
-	memcpy(skb->nh.raw, workbuf, iph->ihl*4);
-	skb->nh.iph->tot_len = htons(skb->len);
+	skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - ihl;
 
 	return 0;
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index cdde963..31387ab 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -666,3 +666,4 @@
 }
 
 EXPORT_SYMBOL(inet_addr_type);
+EXPORT_SYMBOL(ip_dev_find);
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 2a04559..0179001 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -730,7 +730,6 @@
 static void icmp_redirect(struct sk_buff *skb)
 {
 	struct iphdr *iph;
-	unsigned long ip;
 
 	if (skb->len < sizeof(struct iphdr))
 		goto out_err;
@@ -742,7 +741,6 @@
 		goto out;
 
 	iph = (struct iphdr *)skb->data;
-	ip = iph->daddr;
 
 	switch (skb->h.icmph->code & 7) {
 	case ICMP_REDIR_NET:
@@ -752,7 +750,8 @@
 		 */
 	case ICMP_REDIR_HOST:
 	case ICMP_REDIR_HOSTTOS:
-		ip_rt_redirect(skb->nh.iph->saddr, ip, skb->h.icmph->un.gateway,
+		ip_rt_redirect(skb->nh.iph->saddr, iph->daddr,
+			       skb->h.icmph->un.gateway,
 			       iph->saddr, skb->dev);
 		break;
   	}
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d512239..ab680c8 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2361,7 +2361,7 @@
 		}
 
 		seq_printf(seq,
-			   "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
+			   "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
 			   im->multiaddr, im->users,
 			   im->tm_running, im->tm_running ?
 			   jiffies_to_clock_t(im->timer.expires-jiffies) : 0,
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index cff9c3a..7624fd1 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -210,8 +210,7 @@
 		return dst_output(skb);
 	}
 #endif
-	if (skb->len > dst_mtu(skb->dst) &&
-	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
+	if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
 		return ip_fragment(skb, ip_finish_output2);
 	else
 		return ip_finish_output2(skb);
@@ -362,7 +361,7 @@
 	}
 
 	ip_select_ident_more(iph, &rt->u.dst, sk,
-			     (skb_shinfo(skb)->tso_segs ?: 1) - 1);
+			     (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 
 	/* Add an IP checksum. */
 	ip_send_check(iph);
@@ -410,6 +409,7 @@
 	nf_bridge_get(to->nf_bridge);
 #endif
 #endif
+	skb_copy_secmark(to, from);
 }
 
 /*
@@ -743,7 +743,8 @@
 			       (length - transhdrlen));
 	if (!err) {
 		/* specify the length of each IP datagram fragment*/
-		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 		__skb_queue_tail(&sk->sk_write_queue, skb);
 
 		return 0;
@@ -839,7 +840,7 @@
 	 */
 	if (transhdrlen &&
 	    length + fragheaderlen <= mtu &&
-	    rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
+	    rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
 	    !exthdrlen)
 		csummode = CHECKSUM_HW;
 
@@ -1086,14 +1087,16 @@
 
 	inet->cork.length += size;
 	if ((sk->sk_protocol == IPPROTO_UDP) &&
-	    (rt->u.dst.dev->features & NETIF_F_UFO))
-		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
+	    (rt->u.dst.dev->features & NETIF_F_UFO)) {
+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
+	}
 
 
 	while (size > 0) {
 		int i;
 
-		if (skb_shinfo(skb)->ufo_size)
+		if (skb_shinfo(skb)->gso_size)
 			len = size;
 		else {
 
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 95278b2..3ed8b57 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -45,7 +45,6 @@
 static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err, plen, dlen;
-	struct iphdr *iph;
 	struct ipcomp_data *ipcd = x->data;
 	u8 *start, *scratch;
 	struct crypto_tfm *tfm;
@@ -74,8 +73,6 @@
 		
 	skb_put(skb, dlen - plen);
 	memcpy(skb->data, scratch, dlen);
-	iph = skb->nh.iph;
-	iph->tot_len = htons(dlen + iph->ihl * 4);
 out:	
 	put_cpu();
 	return err;
@@ -83,34 +80,21 @@
 
 static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	u8 nexthdr;
-	int err = 0;
+	int err = -ENOMEM;
 	struct iphdr *iph;
-	union {
-		struct iphdr	iph;
-		char 		buf[60];
-	} tmp_iph;
+	struct ip_comp_hdr *ipch;
 
-
-	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-	    skb_linearize(skb, GFP_ATOMIC) != 0) {
-	    	err = -ENOMEM;
+	if (skb_linearize_cow(skb))
 	    	goto out;
-	}
 
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Remove ipcomp header and decompress original payload */	
 	iph = skb->nh.iph;
-	memcpy(&tmp_iph, iph, iph->ihl * 4);
-	nexthdr = *(u8 *)skb->data;
-	skb_pull(skb, sizeof(struct ip_comp_hdr));
-	skb->nh.raw += sizeof(struct ip_comp_hdr);
-	memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4);
-	iph = skb->nh.iph;
-	iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr));
-	iph->protocol = nexthdr;
-	skb->h.raw = skb->data;
+	ipch = (void *)skb->data;
+	iph->protocol = ipch->nexthdr;
+	skb->h.raw = skb->nh.raw + sizeof(*ipch);
+	__skb_pull(skb, sizeof(*ipch));
 	err = ipcomp_decompress(x, skb);
 
 out:	
@@ -171,10 +155,8 @@
 		goto out_ok;
 	}
 
-	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-	    skb_linearize(skb, GFP_ATOMIC) != 0) {
+	if (skb_linearize_cow(skb))
 		goto out_ok;
-	}
 	
 	err = ipcomp_compress(x, skb);
 	iph = skb->nh.iph;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d407253..e1d7f5f 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -55,6 +55,18 @@
 	  of packets, but this mark value is kept in the conntrack session
 	  instead of the individual packets.
 	
+config IP_NF_CONNTRACK_SECMARK
+	bool  'Connection tracking security mark support'
+	depends on IP_NF_CONNTRACK && NETWORK_SECMARK
+	help
+	  This option enables security markings to be applied to
+	  connections.  Typically they are copied to connections from
+	  packets using the CONNSECMARK target and copied back from
+	  connections to packets with the same target, with the packets
+	  being originally labeled via SECMARK.
+
+	  If unsure, say 'N'.
+
 config IP_NF_CONNTRACK_EVENTS
 	bool "Connection tracking events (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && IP_NF_CONNTRACK
@@ -142,6 +154,8 @@
 config IP_NF_AMANDA
 	tristate "Amanda backup protocol support"
 	depends on IP_NF_CONNTRACK
+	select TEXTSEARCH
+	select TEXTSEARCH_KMP
 	help
 	  If you are running the Amanda backup package <http://www.amanda.org/>
 	  on this machine or machines that will be MASQUERADED through this
@@ -181,14 +195,26 @@
 	  With this module you can support H.323 on a connection tracking/NAT
 	  firewall.
 
-	  This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP
-	  and T.120 based data and applications including audio, video, FAX,
-	  chat, whiteboard, file transfer, etc. For more information, please
-	  see http://nath323.sourceforge.net/.
+	  This module supports RAS, Fast Start, H.245 Tunnelling, Call
+	  Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
+	  whiteboard, file transfer, etc. For more information, please
+	  visit http://nath323.sourceforge.net/.
 
 	  If you want to compile it as a module, say 'M' here and read
 	  Documentation/modules.txt.  If unsure, say 'N'.
 
+config IP_NF_SIP
+	tristate "SIP protocol support (EXPERIMENTAL)"
+	depends on IP_NF_CONNTRACK && EXPERIMENTAL
+	help
+	  SIP is an application-layer control protocol that can establish,
+	  modify, and terminate multimedia sessions (conferences) such as
+	  Internet telephony calls. With the ip_conntrack_sip and
+	  the ip_nat_sip modules you can support the protocol on a connection
+	  tracking/NATing firewall.
+
+	  To compile it as a module, choose M here.  If unsure, say Y.
+
 config IP_NF_QUEUE
 	tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
 	help
@@ -501,6 +527,12 @@
 	default IP_NF_NAT if IP_NF_H323=y
 	default m if IP_NF_H323=m
 
+config IP_NF_NAT_SIP
+	tristate
+	depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
+	default IP_NF_NAT if IP_NF_SIP=y
+	default m if IP_NF_SIP=m
+
 # mangle + specific targets
 config IP_NF_MANGLE
 	tristate "Packet mangling"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 461cb1e..3ded4a3 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -31,6 +31,7 @@
 obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
 obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
 obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
 obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
 
 # NAT helpers 
@@ -40,6 +41,7 @@
 obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
 obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
 obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
+obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
 
 # generic IP tables 
 obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index a604b1c..0a7bd7f 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -17,33 +17,29 @@
  *	this value.
  *
  */
-
-#include <linux/in.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/netfilter.h>
-#include <linux/ip.h>
 #include <linux/moduleparam.h>
+#include <linux/textsearch.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
 #include <linux/udp.h>
-#include <net/checksum.h>
-#include <net/udp.h>
 
+#include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
 
 static unsigned int master_timeout = 300;
+static char *ts_algo = "kmp";
 
 MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
 MODULE_DESCRIPTION("Amanda connection tracking module");
 MODULE_LICENSE("GPL");
 module_param(master_timeout, uint, 0600);
 MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
-
-static const char *conns[] = { "DATA ", "MESG ", "INDEX " };
-
-/* This is slow, but it's simple. --RR */
-static char *amanda_buffer;
-static DEFINE_SPINLOCK(amanda_buffer_lock);
+module_param(ts_algo, charp, 0400);
+MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
 
 unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
 				   enum ip_conntrack_info ctinfo,
@@ -52,12 +48,48 @@
 				   struct ip_conntrack_expect *exp);
 EXPORT_SYMBOL_GPL(ip_nat_amanda_hook);
 
+enum amanda_strings {
+	SEARCH_CONNECT,
+	SEARCH_NEWLINE,
+	SEARCH_DATA,
+	SEARCH_MESG,
+	SEARCH_INDEX,
+};
+
+static struct {
+	char			*string;
+	size_t			len;
+	struct ts_config	*ts;
+} search[] = {
+	[SEARCH_CONNECT] = {
+		.string	= "CONNECT ",
+		.len	= 8,
+	},
+	[SEARCH_NEWLINE] = {
+		.string	= "\n",
+		.len	= 1,
+	},
+	[SEARCH_DATA] = {
+		.string	= "DATA ",
+		.len	= 5,
+	},
+	[SEARCH_MESG] = {
+		.string	= "MESG ",
+		.len	= 5,
+	},
+	[SEARCH_INDEX] = {
+		.string = "INDEX ",
+		.len	= 6,
+	},
+};
+
 static int help(struct sk_buff **pskb,
                 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
 {
+	struct ts_state ts;
 	struct ip_conntrack_expect *exp;
-	char *data, *data_limit, *tmp;
-	unsigned int dataoff, i;
+	unsigned int dataoff, start, stop, off, i;
+	char pbuf[sizeof("65535")], *tmp;
 	u_int16_t port, len;
 	int ret = NF_ACCEPT;
 
@@ -77,29 +109,34 @@
 		return NF_ACCEPT;
 	}
 
-	spin_lock_bh(&amanda_buffer_lock);
-	skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff);
-	data = amanda_buffer;
-	data_limit = amanda_buffer + (*pskb)->len - dataoff;
-	*data_limit = '\0';
-
-	/* Search for the CONNECT string */
-	data = strstr(data, "CONNECT ");
-	if (!data)
+	memset(&ts, 0, sizeof(ts));
+	start = skb_find_text(*pskb, dataoff, (*pskb)->len,
+			      search[SEARCH_CONNECT].ts, &ts);
+	if (start == UINT_MAX)
 		goto out;
-	data += strlen("CONNECT ");
+	start += dataoff + search[SEARCH_CONNECT].len;
 
-	/* Only search first line. */	
-	if ((tmp = strchr(data, '\n')))
-		*tmp = '\0';
+	memset(&ts, 0, sizeof(ts));
+	stop = skb_find_text(*pskb, start, (*pskb)->len,
+			     search[SEARCH_NEWLINE].ts, &ts);
+	if (stop == UINT_MAX)
+		goto out;
+	stop += start;
 
-	for (i = 0; i < ARRAY_SIZE(conns); i++) {
-		char *match = strstr(data, conns[i]);
-		if (!match)
+	for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
+		memset(&ts, 0, sizeof(ts));
+		off = skb_find_text(*pskb, start, stop, search[i].ts, &ts);
+		if (off == UINT_MAX)
 			continue;
-		tmp = data = match + strlen(conns[i]);
-		port = simple_strtoul(data, &data, 10);
-		len = data - tmp;
+		off += start + search[i].len;
+
+		len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
+		if (skb_copy_bits(*pskb, off, pbuf, len))
+			break;
+		pbuf[len] = '\0';
+
+		port = simple_strtoul(pbuf, &tmp, 10);
+		len = tmp - pbuf;
 		if (port == 0 || len > 5)
 			break;
 
@@ -125,8 +162,7 @@
 		exp->mask.dst.u.tcp.port = 0xFFFF;
 
 		if (ip_nat_amanda_hook)
-			ret = ip_nat_amanda_hook(pskb, ctinfo,
-						 tmp - amanda_buffer,
+			ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
 						 len, exp);
 		else if (ip_conntrack_expect_related(exp) != 0)
 			ret = NF_DROP;
@@ -134,12 +170,11 @@
 	}
 
 out:
-	spin_unlock_bh(&amanda_buffer_lock);
 	return ret;
 }
 
 static struct ip_conntrack_helper amanda_helper = {
-	.max_expected = ARRAY_SIZE(conns),
+	.max_expected = 3,
 	.timeout = 180,
 	.me = THIS_MODULE,
 	.help = help,
@@ -155,26 +190,36 @@
 
 static void __exit ip_conntrack_amanda_fini(void)
 {
+	int i;
+
 	ip_conntrack_helper_unregister(&amanda_helper);
-	kfree(amanda_buffer);
+	for (i = 0; i < ARRAY_SIZE(search); i++)
+		textsearch_destroy(search[i].ts);
 }
 
 static int __init ip_conntrack_amanda_init(void)
 {
-	int ret;
+	int ret, i;
 
-	amanda_buffer = kmalloc(65536, GFP_KERNEL);
-	if (!amanda_buffer)
-		return -ENOMEM;
-
-	ret = ip_conntrack_helper_register(&amanda_helper);
-	if (ret < 0) {
-		kfree(amanda_buffer);
-		return ret;
+	ret = -ENOMEM;
+	for (i = 0; i < ARRAY_SIZE(search); i++) {
+		search[i].ts = textsearch_prepare(ts_algo, search[i].string,
+						  search[i].len,
+						  GFP_KERNEL, TS_AUTOLOAD);
+		if (search[i].ts == NULL)
+			goto err;
 	}
+	ret = ip_conntrack_helper_register(&amanda_helper);
+	if (ret < 0)
+		goto err;
 	return 0;
 
-
+err:
+	for (; i >= 0; i--) {
+		if (search[i].ts)
+			textsearch_destroy(search[i].ts);
+	}
+	return ret;
 }
 
 module_init(ip_conntrack_amanda_init);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index a297da7..7e4cf9a 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -724,6 +724,9 @@
 		/* this is ugly, but there is no other place where to put it */
 		conntrack->nat.masq_index = exp->master->nat.masq_index;
 #endif
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+		conntrack->secmark = exp->master->secmark;
+#endif
 		nf_conntrack_get(&conntrack->master->ct_general);
 		CONNTRACK_STAT_INC(expect_new);
 	} else {
@@ -1130,6 +1133,12 @@
 
 	write_lock_bh(&ip_conntrack_lock);
 
+	/* Only update if this is not a fixed timeout */
+	if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
+		write_unlock_bh(&ip_conntrack_lock);
+		return;
+	}
+
 	/* If not in hash table, timer will not be active yet */
 	if (!is_confirmed(ct)) {
 		ct->timeout.expires = extra_jiffies;
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index 3e542bf..4dcf526 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -56,37 +56,48 @@
 static int try_epsv_response(const char *, size_t, u_int32_t [], char);
 
 static const struct ftp_search {
-	enum ip_conntrack_dir dir;
 	const char *pattern;
 	size_t plen;
 	char skip;
 	char term;
 	enum ip_ct_ftp_type ftptype;
 	int (*getnum)(const char *, size_t, u_int32_t[], char);
-} search[] = {
-	{
-		IP_CT_DIR_ORIGINAL,
-		"PORT",	sizeof("PORT") - 1, ' ', '\r',
-		IP_CT_FTP_PORT,
-		try_rfc959,
+} search[IP_CT_DIR_MAX][2] = {
+	[IP_CT_DIR_ORIGINAL] = {
+		{
+			.pattern	=  "PORT",
+			.plen		= sizeof("PORT") - 1,
+			.skip		= ' ',
+			.term		= '\r',
+			.ftptype	= IP_CT_FTP_PORT,
+			.getnum		= try_rfc959,
+		},
+		{
+			.pattern	= "EPRT",
+			.plen		= sizeof("EPRT") - 1,
+			.skip		= ' ',
+			.term		= '\r',
+			.ftptype	= IP_CT_FTP_EPRT,
+			.getnum		= try_eprt,
+		},
 	},
-	{
-		IP_CT_DIR_REPLY,
-		"227 ",	sizeof("227 ") - 1, '(', ')',
-		IP_CT_FTP_PASV,
-		try_rfc959,
-	},
-	{
-		IP_CT_DIR_ORIGINAL,
-		"EPRT", sizeof("EPRT") - 1, ' ', '\r',
-		IP_CT_FTP_EPRT,
-		try_eprt,
-	},
-	{
-		IP_CT_DIR_REPLY,
-		"229 ", sizeof("229 ") - 1, '(', ')',
-		IP_CT_FTP_EPSV,
-		try_epsv_response,
+	[IP_CT_DIR_REPLY] = {
+		{
+			.pattern	= "227 ",
+			.plen		= sizeof("227 ") - 1,
+			.skip		= '(',
+			.term		= ')',
+			.ftptype	= IP_CT_FTP_PASV,
+			.getnum		= try_rfc959,
+		},
+		{
+			.pattern	= "229 ",
+			.plen		= sizeof("229 ") - 1,
+			.skip		= '(',
+			.term		= ')',
+			.ftptype	= IP_CT_FTP_EPSV,
+			.getnum		= try_epsv_response,
+		},
 	},
 };
 
@@ -346,17 +357,15 @@
 	array[2] = (ntohl(ct->tuplehash[dir].tuple.src.ip) >> 8) & 0xFF;
 	array[3] = ntohl(ct->tuplehash[dir].tuple.src.ip) & 0xFF;
 
-	for (i = 0; i < ARRAY_SIZE(search); i++) {
-		if (search[i].dir != dir) continue;
-
+	for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
 		found = find_pattern(fb_ptr, (*pskb)->len - dataoff,
-				     search[i].pattern,
-				     search[i].plen,
-				     search[i].skip,
-				     search[i].term,
+				     search[dir][i].pattern,
+				     search[dir][i].plen,
+				     search[dir][i].skip,
+				     search[dir][i].term,
 				     &matchoff, &matchlen,
 				     array,
-				     search[i].getnum);
+				     search[dir][i].getnum);
 		if (found) break;
 	}
 	if (found == -1) {
@@ -366,7 +375,7 @@
 		   this case. */
 		if (net_ratelimit())
 			printk("conntrack_ftp: partial %s %u+%u\n",
-			       search[i].pattern,
+			       search[dir][i].pattern,
 			       ntohl(th->seq), datalen);
 		ret = NF_DROP;
 		goto out;
@@ -426,7 +435,7 @@
 	/* Now, NAT might want to mangle the packet, and register the
 	 * (possibly changed) expectation itself. */
 	if (ip_nat_ftp_hook)
-		ret = ip_nat_ftp_hook(pskb, ctinfo, search[i].ftptype,
+		ret = ip_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
 				      matchoff, matchlen, exp, &seq);
 	else {
 		/* Can't expect this?  Best to drop packet now. */
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
index 518f581..0665674 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c
@@ -22,6 +22,8 @@
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
 #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
 #include <linux/moduleparam.h>
+#include <linux/ctype.h>
+#include <linux/inet.h>
 
 #if 0
 #define DEBUGP printk
@@ -38,6 +40,12 @@
 module_param(gkrouted_only, int, 0600);
 MODULE_PARM_DESC(gkrouted_only, "only accept calls from gatekeeper");
 
+static int callforward_filter = 1;
+module_param(callforward_filter, bool, 0600);
+MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
+		                     "if both endpoints are on different sides "
+				     "(determined by routing information)");
+
 /* Hooks for NAT */
 int (*set_h245_addr_hook) (struct sk_buff ** pskb,
 			   unsigned char **data, int dataoff,
@@ -77,6 +85,12 @@
 		      unsigned char **data, int dataoff,
 		      TransportAddress * addr, u_int16_t port,
 		      struct ip_conntrack_expect * exp);
+int (*nat_callforwarding_hook) (struct sk_buff ** pskb,
+				struct ip_conntrack * ct,
+				enum ip_conntrack_info ctinfo,
+				unsigned char **data, int dataoff,
+				TransportAddress * addr, u_int16_t port,
+				struct ip_conntrack_expect * exp);
 int (*nat_q931_hook) (struct sk_buff ** pskb,
 		      struct ip_conntrack * ct,
 		      enum ip_conntrack_info ctinfo,
@@ -683,6 +697,92 @@
 	return ret;
 }
 
+/* Forwarding declaration */
+void ip_conntrack_q931_expect(struct ip_conntrack *new,
+			      struct ip_conntrack_expect *this);
+
+/****************************************************************************/
+static int expect_callforwarding(struct sk_buff **pskb,
+				 struct ip_conntrack *ct,
+				 enum ip_conntrack_info ctinfo,
+				 unsigned char **data, int dataoff,
+				 TransportAddress * addr)
+{
+	int dir = CTINFO2DIR(ctinfo);
+	int ret = 0;
+	u_int32_t ip;
+	u_int16_t port;
+	struct ip_conntrack_expect *exp = NULL;
+
+	/* Read alternativeAddress */
+	if (!get_h225_addr(*data, addr, &ip, &port) || port == 0)
+		return 0;
+
+	/* If the calling party is on the same side of the forward-to party,
+	 * we don't need to track the second call */
+	if (callforward_filter) {
+		struct rtable *rt1, *rt2;
+		struct flowi fl1 = {
+			.fl4_dst = ip,
+		};
+		struct flowi fl2 = {
+			.fl4_dst = ct->tuplehash[!dir].tuple.src.ip,
+		};
+
+		if (ip_route_output_key(&rt1, &fl1) == 0) {
+			if (ip_route_output_key(&rt2, &fl2) == 0) {
+				if (rt1->rt_gateway == rt2->rt_gateway &&
+				    rt1->u.dst.dev  == rt2->u.dst.dev)
+					ret = 1;
+				dst_release(&rt2->u.dst);
+			}
+			dst_release(&rt1->u.dst);
+		}
+		if (ret) {
+			DEBUGP("ip_ct_q931: Call Forwarding not tracked\n");
+			return 0;
+		}
+	}
+
+	/* Create expect for the second call leg */
+	if ((exp = ip_conntrack_expect_alloc(ct)) == NULL)
+		return -1;
+	exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+	exp->tuple.src.u.tcp.port = 0;
+	exp->tuple.dst.ip = ip;
+	exp->tuple.dst.u.tcp.port = htons(port);
+	exp->tuple.dst.protonum = IPPROTO_TCP;
+	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.u.tcp.port = 0;
+	exp->mask.dst.ip = 0xFFFFFFFF;
+	exp->mask.dst.u.tcp.port = 0xFFFF;
+	exp->mask.dst.protonum = 0xFF;
+	exp->flags = 0;
+
+	if (ct->tuplehash[dir].tuple.src.ip !=
+	    ct->tuplehash[!dir].tuple.dst.ip && nat_callforwarding_hook) {
+		/* Need NAT */
+		ret = nat_callforwarding_hook(pskb, ct, ctinfo, data, dataoff,
+					      addr, port, exp);
+	} else {		/* Conntrack only */
+		exp->expectfn = ip_conntrack_q931_expect;
+
+		if (ip_conntrack_expect_related(exp) == 0) {
+			DEBUGP("ip_ct_q931: expect Call Forwarding "
+			       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+			       NIPQUAD(exp->tuple.src.ip),
+			       ntohs(exp->tuple.src.u.tcp.port),
+			       NIPQUAD(exp->tuple.dst.ip),
+			       ntohs(exp->tuple.dst.u.tcp.port));
+		} else
+			ret = -1;
+	}
+
+	ip_conntrack_expect_put(exp);
+
+	return ret;
+}
+
 /****************************************************************************/
 static int process_setup(struct sk_buff **pskb, struct ip_conntrack *ct,
 			 enum ip_conntrack_info ctinfo,
@@ -878,6 +978,15 @@
 
 	DEBUGP("ip_ct_q931: Facility\n");
 
+	if (facility->reason.choice == eFacilityReason_callForwarded) {
+		if (facility->options & eFacility_UUIE_alternativeAddress)
+			return expect_callforwarding(pskb, ct, ctinfo, data,
+						     dataoff,
+						     &facility->
+						     alternativeAddress);
+		return 0;
+	}
+
 	if (facility->options & eFacility_UUIE_h245Address) {
 		ret = expect_h245(pskb, ct, ctinfo, data, dataoff,
 				  &facility->h245Address);
@@ -1677,7 +1786,6 @@
 		fini();
 		return ret;
 	}
-
 	DEBUGP("ip_ct_h323: init success\n");
 	return 0;
 }
@@ -1696,6 +1804,7 @@
 EXPORT_SYMBOL_GPL(nat_rtp_rtcp_hook);
 EXPORT_SYMBOL_GPL(nat_t120_hook);
 EXPORT_SYMBOL_GPL(nat_h245_hook);
+EXPORT_SYMBOL_GPL(nat_callforwarding_hook);
 EXPORT_SYMBOL_GPL(nat_q931_hook);
 
 MODULE_AUTHOR("Jing Min Zhao <zhaojingmin@users.sourceforge.net>");
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
index 022c47b..4b35961 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_types.c
@@ -1,4 +1,4 @@
-/* Generated by Jing Min Zhao's ASN.1 parser, Mar 15 2006
+/* Generated by Jing Min Zhao's ASN.1 parser, Apr 20 2006
  *
  * Copyright (c) 2006 Jing Min Zhao <zhaojingmin@users.sourceforge.net>
  *
@@ -1069,8 +1069,8 @@
 
 static field_t _Facility_UUIE[] = {	/* SEQUENCE */
 	{FNAME("protocolIdentifier") OID, BYTE, 0, 0, SKIP, 0, NULL},
-	{FNAME("alternativeAddress") CHOICE, 3, 7, 7, SKIP | EXT | OPT, 0,
-	 _TransportAddress},
+	{FNAME("alternativeAddress") CHOICE, 3, 7, 7, DECODE | EXT | OPT,
+	 offsetof(Facility_UUIE, alternativeAddress), _TransportAddress},
 	{FNAME("alternativeAliasAddress") SEQOF, SEMI, 0, 0, SKIP | OPT, 0,
 	 _Facility_UUIE_alternativeAliasAddress},
 	{FNAME("conferenceID") OCTSTR, FIXD, 16, 0, SKIP | OPT, 0, NULL},
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c
index 01bd7ca..33891bb 100644
--- a/net/ipv4/netfilter/ip_conntrack_netlink.c
+++ b/net/ipv4/netfilter/ip_conntrack_netlink.c
@@ -399,38 +399,54 @@
 static int ctnetlink_done(struct netlink_callback *cb)
 {
 	DEBUGP("entered %s\n", __FUNCTION__);
+	if (cb->args[1])
+		ip_conntrack_put((struct ip_conntrack *)cb->args[1]);
 	return 0;
 }
 
 static int
 ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct ip_conntrack *ct = NULL;
+	struct ip_conntrack *ct, *last;
 	struct ip_conntrack_tuple_hash *h;
 	struct list_head *i;
-	u_int32_t *id = (u_int32_t *) &cb->args[1];
 
 	DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, 
 			cb->args[0], *id);
 
 	read_lock_bh(&ip_conntrack_lock);
-	for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++, *id = 0) {
+	for (; cb->args[0] < ip_conntrack_htable_size; cb->args[0]++) {
+restart:
+		last = (struct ip_conntrack *)cb->args[1];
 		list_for_each_prev(i, &ip_conntrack_hash[cb->args[0]]) {
 			h = (struct ip_conntrack_tuple_hash *) i;
 			if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
 				continue;
 			ct = tuplehash_to_ctrack(h);
-			if (ct->id <= *id)
-				continue;
+			if (last != NULL) {
+				if (ct == last) {
+					ip_conntrack_put(last);
+					cb->args[1] = 0;
+					last = NULL;
+				} else
+					continue;
+			}
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
 		                        	cb->nlh->nlmsg_seq,
 						IPCTNL_MSG_CT_NEW,
-						1, ct) < 0)
+						1, ct) < 0) {
+				nf_conntrack_get(&ct->ct_general);
+				cb->args[1] = (unsigned long)ct;
 				goto out;
-			*id = ct->id;
+			}
+		}
+		if (last != NULL) {
+			ip_conntrack_put(last);
+			cb->args[1] = 0;
+			goto restart;
 		}
 	}
-out:	
+out:
 	read_unlock_bh(&ip_conntrack_lock);
 
 	DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
@@ -629,7 +645,7 @@
 };
 
 static inline int
-ctnetlink_parse_nat(struct nfattr *cda[],
+ctnetlink_parse_nat(struct nfattr *nat,
 		    const struct ip_conntrack *ct, struct ip_nat_range *range)
 {
 	struct nfattr *tb[CTA_NAT_MAX];
@@ -639,7 +655,7 @@
 
 	memset(range, 0, sizeof(*range));
 	
-	nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]);
+	nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
 
 	if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
 		return -EINVAL;
@@ -854,39 +870,30 @@
 		/* ASSURED bit can only be set */
 		return -EINVAL;
 
-	if (cda[CTA_NAT-1]) {
+	if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
 #ifndef CONFIG_IP_NF_NAT_NEEDED
 		return -EINVAL;
 #else
-		unsigned int hooknum;
 		struct ip_nat_range range;
 
-		if (ctnetlink_parse_nat(cda, ct, &range) < 0)
-			return -EINVAL;
-
-		DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", 
-		       NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
-		       htons(range.min.all), htons(range.max.all));
-		
-		/* This is tricky but it works. ip_nat_setup_info needs the
-		 * hook number as parameter, so let's do the correct 
-		 * conversion and run away */
-		if (status & IPS_SRC_NAT_DONE)
-			hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
-		else if (status & IPS_DST_NAT_DONE)
-			hooknum = NF_IP_PRE_ROUTING;  /* IP_NAT_MANIP_DST */
-		else 
-			return -EINVAL; /* Missing NAT flags */
-
-		DEBUGP("NAT status: %lu\n", 
-		       status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
-		
-		if (ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
-			return -EEXIST;
-		ip_nat_setup_info(ct, &range, hooknum);
-
-                DEBUGP("NAT status after setup_info: %lu\n",
-                       ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
+		if (cda[CTA_NAT_DST-1]) {
+			if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
+						&range) < 0)
+				return -EINVAL;
+			if (ip_nat_initialized(ct,
+					       HOOK2MANIP(NF_IP_PRE_ROUTING)))
+				return -EEXIST;
+			ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
+		}
+		if (cda[CTA_NAT_SRC-1]) {
+			if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
+						&range) < 0)
+				return -EINVAL;
+			if (ip_nat_initialized(ct,
+					       HOOK2MANIP(NF_IP_POST_ROUTING)))
+				return -EEXIST;
+			ip_nat_setup_info(ct, &range, NF_IP_POST_ROUTING);
+		}
 #endif
 	}
 
@@ -1106,7 +1113,7 @@
 	/* implicit 'else' */
 
 	/* we only allow nat config for new conntracks */
-	if (cda[CTA_NAT-1]) {
+	if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
 		err = -EINVAL;
 		goto out_unlock;
 	}
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_gre.c b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
index 5679479..21ee124 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_gre.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_gre.c
@@ -77,10 +77,10 @@
 }
 
 /* look up the source key for a given tuple */
-static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
+static __be16 gre_keymap_lookup(struct ip_conntrack_tuple *t)
 {
 	struct ip_ct_gre_keymap *km;
-	u_int32_t key = 0;
+	__be16 key = 0;
 
 	read_lock_bh(&ip_ct_gre_lock);
 	km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
@@ -190,7 +190,7 @@
 			   struct ip_conntrack_tuple *tuple)
 {
 	struct gre_hdr_pptp _pgrehdr, *pgrehdr;
-	u_int32_t srckey;
+	__be16 srckey;
 	struct gre_hdr _grehdr, *grehdr;
 
 	/* first only delinearize old RFC1701 GRE header */
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
index d8b14a9..23f1c50 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
@@ -224,7 +224,7 @@
 	}
 
 	/* See ip_conntrack_proto_tcp.c */
-	if (hooknum == NF_IP_PRE_ROUTING &&
+	if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
 	    nf_ip_checksum(skb, hooknum, skb->nh.iph->ihl * 4, 0)) {
 		if (LOG_INVALID(IPPROTO_ICMP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 062b252..c5c2ce5 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -870,7 +870,7 @@
 	 * and moreover root might send raw packets.
 	 */
 	/* FIXME: Source route IP option packets --RR */
-	if (hooknum == NF_IP_PRE_ROUTING &&
+	if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
 	    nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_TCP)) {
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 7089986..9b2c16b 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,7 +120,7 @@
 	 * because the semantic of CHECKSUM_HW is different there 
 	 * and moreover root might send raw packets.
 	 * FIXME: Source route IP option packets --RR */
-	if (hooknum == NF_IP_PRE_ROUTING &&
+	if (ip_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
 	    nf_ip_checksum(skb, hooknum, iph->ihl * 4, IPPROTO_UDP)) {
 		if (LOG_INVALID(IPPROTO_UDP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c
new file mode 100644
index 0000000..fc87ce0
--- /dev/null
+++ b/net/ipv4/netfilter/ip_conntrack_sip.c
@@ -0,0 +1,471 @@
+/* SIP extension for IP connection tracking.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_conntrack_ftp.c and other modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP connection tracking helper");
+
+#define MAX_PORTS	8
+static unsigned short ports[MAX_PORTS];
+static int ports_c;
+module_param_array(ports, ushort, &ports_c, 0400);
+MODULE_PARM_DESC(ports, "port numbers of sip servers");
+
+static unsigned int sip_timeout = SIP_TIMEOUT;
+module_param(sip_timeout, uint, 0600);
+MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
+
+unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb,
+				enum ip_conntrack_info ctinfo,
+				struct ip_conntrack *ct,
+				const char **dptr);
+EXPORT_SYMBOL_GPL(ip_nat_sip_hook);
+
+unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb,
+				enum ip_conntrack_info ctinfo,
+				struct ip_conntrack_expect *exp,
+				const char *dptr);
+EXPORT_SYMBOL_GPL(ip_nat_sdp_hook);
+
+int ct_sip_get_info(const char *dptr, size_t dlen,
+				unsigned int *matchoff,
+				unsigned int *matchlen,
+				struct sip_header_nfo *hnfo);
+EXPORT_SYMBOL_GPL(ct_sip_get_info);
+
+
+static int digits_len(const char *dptr, const char *limit, int *shift);
+static int epaddr_len(const char *dptr, const char *limit, int *shift);
+static int skp_digits_len(const char *dptr, const char *limit, int *shift);
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift);
+
+struct sip_header_nfo ct_sip_hdrs[] = {
+	{ 	/* Via header */
+		.lname		= "Via:",
+		.lnlen		= sizeof("Via:") - 1,
+		.sname		= "\r\nv:",
+		.snlen		= sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */
+		.ln_str		= "UDP ",
+		.ln_strlen	= sizeof("UDP ") - 1,
+		.match_len	= epaddr_len,
+	},
+	{ 	/* Contact header */
+		.lname		= "Contact:",
+		.lnlen		= sizeof("Contact:") - 1,
+		.sname		= "\r\nm:",
+		.snlen		= sizeof("\r\nm:") - 1,
+		.ln_str		= "sip:",
+		.ln_strlen	= sizeof("sip:") - 1,
+		.match_len	= skp_epaddr_len
+	},
+	{ 	/* Content length header */
+		.lname		= "Content-Length:",
+		.lnlen		= sizeof("Content-Length:") - 1,
+		.sname		= "\r\nl:",
+		.snlen		= sizeof("\r\nl:") - 1,
+		.ln_str		= ":",
+		.ln_strlen	= sizeof(":") - 1,
+		.match_len	= skp_digits_len
+	},
+	{	/* SDP media info */
+		.lname		= "\nm=",
+		.lnlen		= sizeof("\nm=") - 1,
+		.sname		= "\rm=",
+		.snlen		= sizeof("\rm=") - 1,
+		.ln_str		= "audio ",
+		.ln_strlen	= sizeof("audio ") - 1,
+		.match_len	= digits_len
+	},
+	{ 	/* SDP owner address*/
+		.lname		= "\no=",
+		.lnlen		= sizeof("\no=") - 1,
+		.sname		= "\ro=",
+		.snlen		= sizeof("\ro=") - 1,
+		.ln_str		= "IN IP4 ",
+		.ln_strlen	= sizeof("IN IP4 ") - 1,
+		.match_len	= epaddr_len
+	},
+	{ 	/* SDP connection info */
+		.lname		= "\nc=",
+		.lnlen		= sizeof("\nc=") - 1,
+		.sname		= "\rc=",
+		.snlen		= sizeof("\rc=") - 1,
+		.ln_str		= "IN IP4 ",
+		.ln_strlen	= sizeof("IN IP4 ") - 1,
+		.match_len	= epaddr_len
+	},
+	{ 	/* Requests headers */
+		.lname		= "sip:",
+		.lnlen		= sizeof("sip:") - 1,
+		.sname		= "sip:",
+		.snlen		= sizeof("sip:") - 1, /* yes, i know.. ;) */
+		.ln_str		= "@",
+		.ln_strlen	= sizeof("@") - 1,
+		.match_len	= epaddr_len
+	},
+	{ 	/* SDP version header */
+		.lname		= "\nv=",
+		.lnlen		= sizeof("\nv=") - 1,
+		.sname		= "\rv=",
+		.snlen		= sizeof("\rv=") - 1,
+		.ln_str		= "=",
+		.ln_strlen	= sizeof("=") - 1,
+		.match_len	= digits_len
+	}
+};
+EXPORT_SYMBOL_GPL(ct_sip_hdrs);
+
+/* get line lenght until first CR or LF seen. */
+int ct_sip_lnlen(const char *line, const char *limit)
+{
+	const char *k = line;
+
+	while ((line <= limit) && (*line == '\r' || *line == '\n'))
+		line++;
+
+	while (line <= limit) {
+		if (*line == '\r' || *line == '\n')
+			break;
+		line++;
+	}
+	return line - k;
+}
+EXPORT_SYMBOL_GPL(ct_sip_lnlen);
+
+/* Linear string search, case sensitive. */
+const char *ct_sip_search(const char *needle, const char *haystack,
+                          size_t needle_len, size_t haystack_len)
+{
+	const char *limit = haystack + (haystack_len - needle_len);
+
+	while (haystack <= limit) {
+		if (memcmp(haystack, needle, needle_len) == 0)
+			return haystack;
+		haystack++;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(ct_sip_search);
+
+static int digits_len(const char *dptr, const char *limit, int *shift)
+{
+	int len = 0;
+	while (dptr <= limit && isdigit(*dptr)) {
+		dptr++;
+		len++;
+	}
+	return len;
+}
+
+/* get digits lenght, skiping blank spaces. */
+static int skp_digits_len(const char *dptr, const char *limit, int *shift)
+{
+	for (; dptr <= limit && *dptr == ' '; dptr++)
+		(*shift)++;
+
+	return digits_len(dptr, limit, shift);
+}
+
+/* Simple ipaddr parser.. */
+static int parse_ipaddr(const char *cp,	const char **endp,
+			u_int32_t *ipaddr, const char *limit)
+{
+	unsigned long int val;
+	int i, digit = 0;
+
+	for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) {
+		digit = 0;
+		if (!isdigit(*cp))
+			break;
+
+		val = simple_strtoul(cp, (char **)&cp, 10);
+		if (val > 0xFF)
+			return -1;
+
+		((u_int8_t *)ipaddr)[i] = val;
+		digit = 1;
+
+		if (*cp != '.')
+			break;
+		cp++;
+	}
+	if (!digit)
+		return -1;
+
+	if (endp)
+		*endp = cp;
+
+	return 0;
+}
+
+/* skip ip address. returns it lenght. */
+static int epaddr_len(const char *dptr, const char *limit, int *shift)
+{
+	const char *aux = dptr;
+	u_int32_t ip;
+
+	if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) {
+		DEBUGP("ip: %s parse failed.!\n", dptr);
+		return 0;
+	}
+
+	/* Port number */
+	if (*dptr == ':') {
+		dptr++;
+		dptr += digits_len(dptr, limit, shift);
+	}
+	return dptr - aux;
+}
+
+/* get address length, skiping user info. */
+static int skp_epaddr_len(const char *dptr, const char *limit, int *shift)
+{
+	int s = *shift;
+
+	for (; dptr <= limit && *dptr != '@'; dptr++)
+		(*shift)++;
+
+	if (*dptr == '@') {
+		dptr++;
+		(*shift)++;
+	} else
+		*shift = s;
+
+	return epaddr_len(dptr, limit, shift);
+}
+
+/* Returns 0 if not found, -1 error parsing. */
+int ct_sip_get_info(const char *dptr, size_t dlen,
+		    unsigned int *matchoff,
+		    unsigned int *matchlen,
+		    struct sip_header_nfo *hnfo)
+{
+	const char *limit, *aux, *k = dptr;
+	int shift = 0;
+
+	limit = dptr + (dlen - hnfo->lnlen);
+
+	while (dptr <= limit) {
+		if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) &&
+		    (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) {
+			dptr++;
+			continue;
+		}
+		aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen,
+		                    ct_sip_lnlen(dptr, limit));
+		if (!aux) {
+			DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str,
+			       hnfo->lname);
+			return -1;
+		}
+		aux += hnfo->ln_strlen;
+
+		*matchlen = hnfo->match_len(aux, limit, &shift);
+		if (!*matchlen)
+			return -1;
+
+		*matchoff = (aux - k) + shift;
+
+		DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname,
+		       *matchlen);
+		return 1;
+	}
+	DEBUGP("%s header not found.\n", hnfo->lname);
+	return 0;
+}
+
+static int set_expected_rtp(struct sk_buff **pskb,
+			    struct ip_conntrack *ct,
+			    enum ip_conntrack_info ctinfo,
+			    u_int32_t ipaddr, u_int16_t port,
+			    const char *dptr)
+{
+	struct ip_conntrack_expect *exp;
+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	int ret;
+
+	exp = ip_conntrack_expect_alloc(ct);
+	if (exp == NULL)
+		return NF_DROP;
+
+	exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
+	exp->tuple.src.u.udp.port = 0;
+	exp->tuple.dst.ip = ipaddr;
+	exp->tuple.dst.u.udp.port = htons(port);
+	exp->tuple.dst.protonum = IPPROTO_UDP;
+
+	exp->mask.src.ip = 0xFFFFFFFF;
+	exp->mask.src.u.udp.port = 0;
+	exp->mask.dst.ip = 0xFFFFFFFF;
+	exp->mask.dst.u.udp.port = 0xFFFF;
+	exp->mask.dst.protonum = 0xFF;
+
+	exp->expectfn = NULL;
+	exp->flags = 0;
+
+	if (ip_nat_sdp_hook)
+		ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr);
+	else {
+		if (ip_conntrack_expect_related(exp) != 0)
+			ret = NF_DROP;
+		else
+			ret = NF_ACCEPT;
+	}
+	ip_conntrack_expect_put(exp);
+
+	return ret;
+}
+
+static int sip_help(struct sk_buff **pskb,
+		    struct ip_conntrack *ct,
+		    enum ip_conntrack_info ctinfo)
+{
+	unsigned int dataoff, datalen;
+	const char *dptr;
+	int ret = NF_ACCEPT;
+	int matchoff, matchlen;
+	u_int32_t ipaddr;
+	u_int16_t port;
+
+	/* No Data ? */
+	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+	if (dataoff >= (*pskb)->len) {
+		DEBUGP("skb->len = %u\n", (*pskb)->len);
+		return NF_ACCEPT;
+        }
+
+	ip_ct_refresh(ct, *pskb, sip_timeout * HZ);
+
+	if (!skb_is_nonlinear(*pskb))
+		dptr = (*pskb)->data + dataoff;
+	else {
+		DEBUGP("Copy of skbuff not supported yet.\n");
+		goto out;
+	}
+
+	if (ip_nat_sip_hook) {
+		if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) {
+			ret = NF_DROP;
+			goto out;
+		}
+	}
+
+	/* After this point NAT, could have mangled skb, so
+	   we need to recalculate payload lenght. */
+	datalen = (*pskb)->len - dataoff;
+
+	if (datalen < (sizeof("SIP/2.0 200") - 1))
+		goto out;
+
+	/* RTP info only in some SDP pkts */
+	if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 &&
+	    memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) {
+		goto out;
+	}
+	/* Get ip and port address from SDP packet. */
+	if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
+	                    &ct_sip_hdrs[POS_CONNECTION]) > 0) {
+
+		/* We'll drop only if there are parse problems. */
+		if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr,
+		                 dptr + datalen) < 0) {
+			ret = NF_DROP;
+			goto out;
+		}
+		if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen,
+		                    &ct_sip_hdrs[POS_MEDIA]) > 0) {
+
+			port = simple_strtoul(dptr + matchoff, NULL, 10);
+			if (port < 1024) {
+				ret = NF_DROP;
+				goto out;
+			}
+			ret = set_expected_rtp(pskb, ct, ctinfo,
+					       ipaddr, port, dptr);
+		}
+	}
+out:
+	return ret;
+}
+
+static struct ip_conntrack_helper sip[MAX_PORTS];
+static char sip_names[MAX_PORTS][10];
+
+static void fini(void)
+{
+	int i;
+	for (i = 0; i < ports_c; i++) {
+		DEBUGP("unregistering helper for port %d\n", ports[i]);
+		ip_conntrack_helper_unregister(&sip[i]);
+	}
+}
+
+static int __init init(void)
+{
+	int i, ret;
+	char *tmpname;
+
+	if (ports_c == 0)
+		ports[ports_c++] = SIP_PORT;
+
+	for (i = 0; i < ports_c; i++) {
+		/* Create helper structure */
+		memset(&sip[i], 0, sizeof(struct ip_conntrack_helper));
+
+		sip[i].tuple.dst.protonum = IPPROTO_UDP;
+		sip[i].tuple.src.u.udp.port = htons(ports[i]);
+		sip[i].mask.src.u.udp.port = 0xFFFF;
+		sip[i].mask.dst.protonum = 0xFF;
+		sip[i].max_expected = 1;
+		sip[i].timeout = 3 * 60; /* 3 minutes */
+		sip[i].me = THIS_MODULE;
+		sip[i].help = sip_help;
+
+		tmpname = &sip_names[i][0];
+		if (ports[i] == SIP_PORT)
+			sprintf(tmpname, "sip");
+		else
+			sprintf(tmpname, "sip-%d", i);
+		sip[i].name = tmpname;
+
+		DEBUGP("port #%d: %d\n", i, ports[i]);
+
+		ret = ip_conntrack_helper_register(&sip[i]);
+		if (ret) {
+			printk("ERROR registering helper for port %d\n",
+				ports[i]);
+			fini();
+			return ret;
+		}
+	}
+	return 0;
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 929d61f..88445aa 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -189,6 +189,11 @@
 		return -ENOSPC;
 #endif
 
+#ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
+	if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+		return -ENOSPC;
+#endif
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
 		return -ENOSPC;
 
@@ -417,7 +422,7 @@
 
 	/* This is where we call the helper: as the packet goes out. */
 	ct = ip_conntrack_get(*pskb, &ctinfo);
-	if (ct && ct->helper) {
+	if (ct && ct->helper && ctinfo != IP_CT_RELATED + IP_CT_IS_REPLY) {
 		unsigned int ret;
 		ret = ct->helper->help(pskb, ct, ctinfo);
 		if (ret != NF_ACCEPT)
@@ -564,6 +569,8 @@
 static int log_invalid_proto_min = 0;
 static int log_invalid_proto_max = 255;
 
+int ip_conntrack_checksum = 1;
+
 static struct ctl_table_header *ip_ct_sysctl_header;
 
 static ctl_table ip_ct_sysctl_table[] = {
@@ -592,6 +599,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 	{
+		.ctl_name	= NET_IPV4_NF_CONNTRACK_CHECKSUM,
+		.procname	= "ip_conntrack_checksum",
+		.data		= &ip_conntrack_checksum,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
 		.ctl_name	= NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
 		.procname	= "ip_conntrack_tcp_timeout_syn_sent",
 		.data		= &ip_ct_tcp_timeout_syn_sent,
@@ -946,6 +961,7 @@
 EXPORT_SYMBOL_GPL(ip_conntrack_proto_find_get);
 EXPORT_SYMBOL_GPL(ip_conntrack_proto_put);
 EXPORT_SYMBOL_GPL(__ip_conntrack_proto_find);
+EXPORT_SYMBOL_GPL(ip_conntrack_checksum);
 #if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
     defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
 EXPORT_SYMBOL_GPL(ip_ct_port_tuple_to_nfattr);
diff --git a/net/ipv4/netfilter/ip_nat_helper_h323.c b/net/ipv4/netfilter/ip_nat_helper_h323.c
index d45663d..419b878 100644
--- a/net/ipv4/netfilter/ip_nat_helper_h323.c
+++ b/net/ipv4/netfilter/ip_nat_helper_h323.c
@@ -487,6 +487,80 @@
 }
 
 /****************************************************************************/
+static void ip_nat_callforwarding_expect(struct ip_conntrack *new,
+					 struct ip_conntrack_expect *this)
+{
+	struct ip_nat_range range;
+
+	/* This must be a fresh one. */
+	BUG_ON(new->status & IPS_NAT_DONE_MASK);
+
+	/* Change src to where master sends to */
+	range.flags = IP_NAT_RANGE_MAP_IPS;
+	range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.ip;
+
+	/* hook doesn't matter, but it has to do source manip */
+	ip_nat_setup_info(new, &range, NF_IP_POST_ROUTING);
+
+	/* For DST manip, map port here to where it's expected. */
+	range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);
+	range.min = range.max = this->saved_proto;
+	range.min_ip = range.max_ip = this->saved_ip;
+
+	/* hook doesn't matter, but it has to do destination manip */
+	ip_nat_setup_info(new, &range, NF_IP_PRE_ROUTING);
+
+	ip_conntrack_q931_expect(new, this);
+}
+
+/****************************************************************************/
+static int nat_callforwarding(struct sk_buff **pskb, struct ip_conntrack *ct,
+			      enum ip_conntrack_info ctinfo,
+			      unsigned char **data, int dataoff,
+			      TransportAddress * addr, u_int16_t port,
+			      struct ip_conntrack_expect *exp)
+{
+	int dir = CTINFO2DIR(ctinfo);
+	u_int16_t nated_port;
+
+	/* Set expectations for NAT */
+	exp->saved_ip = exp->tuple.dst.ip;
+	exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
+	exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
+	exp->expectfn = ip_nat_callforwarding_expect;
+	exp->dir = !dir;
+
+	/* Try to get same port: if not, try to change it. */
+	for (nated_port = port; nated_port != 0; nated_port++) {
+		exp->tuple.dst.u.tcp.port = htons(nated_port);
+		if (ip_conntrack_expect_related(exp) == 0)
+			break;
+	}
+
+	if (nated_port == 0) {	/* No port available */
+		if (net_ratelimit())
+			printk("ip_nat_q931: out of TCP ports\n");
+		return 0;
+	}
+
+	/* Modify signal */
+	if (!set_h225_addr(pskb, data, dataoff, addr,
+			   ct->tuplehash[!dir].tuple.dst.ip,
+			   nated_port) == 0) {
+		ip_conntrack_unexpect_related(exp);
+		return -1;
+	}
+
+	/* Success */
+	DEBUGP("ip_nat_q931: expect Call Forwarding "
+	       "%u.%u.%u.%u:%hu->%u.%u.%u.%u:%hu\n",
+	       NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
+	       NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
+
+	return 0;
+}
+
+/****************************************************************************/
 static int __init init(void)
 {
 	BUG_ON(set_h245_addr_hook != NULL);
@@ -496,6 +570,7 @@
 	BUG_ON(nat_rtp_rtcp_hook != NULL);
 	BUG_ON(nat_t120_hook != NULL);
 	BUG_ON(nat_h245_hook != NULL);
+	BUG_ON(nat_callforwarding_hook != NULL);
 	BUG_ON(nat_q931_hook != NULL);
 
 	set_h245_addr_hook = set_h245_addr;
@@ -505,6 +580,7 @@
 	nat_rtp_rtcp_hook = nat_rtp_rtcp;
 	nat_t120_hook = nat_t120;
 	nat_h245_hook = nat_h245;
+	nat_callforwarding_hook = nat_callforwarding;
 	nat_q931_hook = nat_q931;
 
 	DEBUGP("ip_nat_h323: init success\n");
@@ -521,6 +597,7 @@
 	nat_rtp_rtcp_hook = NULL;
 	nat_t120_hook = NULL;
 	nat_h245_hook = NULL;
+	nat_callforwarding_hook = NULL;
 	nat_q931_hook = NULL;
 	synchronize_net();
 }
diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c
new file mode 100644
index 0000000..6ffba63
--- /dev/null
+++ b/net/ipv4/netfilter/ip_nat_sip.c
@@ -0,0 +1,249 @@
+/* SIP extension for UDP NAT alteration.
+ *
+ * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
+ * based on RR's ip_nat_ftp.c and other modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+#include <linux/netfilter_ipv4/ip_nat_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
+#include <linux/netfilter_ipv4/ip_conntrack_sip.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
+MODULE_DESCRIPTION("SIP NAT helper");
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(format, args...)
+#endif
+
+extern struct sip_header_nfo ct_sip_hdrs[];
+
+static unsigned int mangle_sip_packet(struct sk_buff **pskb,
+				      enum ip_conntrack_info ctinfo,
+				      struct ip_conntrack *ct,
+				      const char **dptr, size_t dlen,
+				      char *buffer, int bufflen,
+				      struct sip_header_nfo *hnfo)
+{
+	unsigned int matchlen, matchoff;
+
+	if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0)
+		return 0;
+
+	if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+	                              matchoff, matchlen, buffer, bufflen))
+		return 0;
+
+	/* We need to reload this. Thanks Patrick. */
+	*dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+	return 1;
+}
+
+static unsigned int ip_nat_sip(struct sk_buff **pskb,
+			       enum ip_conntrack_info ctinfo,
+			       struct ip_conntrack *ct,
+			       const char **dptr)
+{
+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
+	unsigned int bufflen, dataoff;
+	u_int32_t ip;
+	u_int16_t port;
+
+	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+	ip   = ct->tuplehash[!dir].tuple.dst.ip;
+	port = ct->tuplehash[!dir].tuple.dst.u.udp.port;
+	bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port));
+
+	/* short packet ? */
+	if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1))
+		return 0;
+
+	/* Basic rules: requests and responses. */
+	if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) {
+		const char *aux;
+
+		if ((ctinfo) < IP_CT_IS_REPLY) {
+			mangle_sip_packet(pskb, ctinfo, ct, dptr,
+			                  (*pskb)->len - dataoff,
+			                  buffer, bufflen,
+			                  &ct_sip_hdrs[POS_CONTACT]);
+			return 1;
+		}
+
+		if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
+				       (*pskb)->len - dataoff,
+		                       buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+			return 0;
+
+		/* This search should ignore case, but later.. */
+		aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1,
+		                    (*pskb)->len - dataoff);
+		if (!aux)
+			return 0;
+
+		if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"),
+		    ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff)))
+			return 1;
+
+		return mangle_sip_packet(pskb, ctinfo, ct, dptr,
+					 (*pskb)->len - dataoff,
+		                         buffer, bufflen,
+					 &ct_sip_hdrs[POS_CONTACT]);
+	}
+	if ((ctinfo) < IP_CT_IS_REPLY) {
+		if (!mangle_sip_packet(pskb, ctinfo, ct, dptr,
+				       (*pskb)->len - dataoff,
+		                       buffer, bufflen, &ct_sip_hdrs[POS_VIA]))
+			return 0;
+
+		/* Mangle Contact if exists only. - watch udp_nat_mangle()! */
+		mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff,
+		                  buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]);
+		return 1;
+	}
+	/* This mangle requests headers. */
+	return mangle_sip_packet(pskb, ctinfo, ct, dptr,
+	                         ct_sip_lnlen(*dptr,
+				              *dptr + (*pskb)->len - dataoff),
+	                         buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]);
+}
+
+static int mangle_content_len(struct sk_buff **pskb,
+			      enum ip_conntrack_info ctinfo,
+			      struct ip_conntrack *ct,
+			      const char *dptr)
+{
+	unsigned int dataoff, matchoff, matchlen;
+	char buffer[sizeof("65536")];
+	int bufflen;
+
+	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+	/* Get actual SDP lenght */
+	if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
+	                    &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) {
+
+		/* since ct_sip_get_info() give us a pointer passing 'v='
+		   we need to add 2 bytes in this count. */
+		int c_len = (*pskb)->len - dataoff - matchoff + 2;
+
+		/* Now, update SDP lenght */
+		if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff,
+		                    &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) {
+
+			bufflen = sprintf(buffer, "%u", c_len);
+
+			return ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
+							matchoff, matchlen,
+							buffer, bufflen);
+		}
+	}
+	return 0;
+}
+
+static unsigned int mangle_sdp(struct sk_buff **pskb,
+			       enum ip_conntrack_info ctinfo,
+			       struct ip_conntrack *ct,
+			       u_int32_t newip, u_int16_t port,
+			       const char *dptr)
+{
+	char buffer[sizeof("nnn.nnn.nnn.nnn")];
+	unsigned int dataoff, bufflen;
+
+	dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr);
+
+	/* Mangle owner and contact info. */
+	bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip));
+	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+	                       buffer, bufflen, &ct_sip_hdrs[POS_OWNER]))
+		return 0;
+
+	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+	                       buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION]))
+		return 0;
+
+	/* Mangle media port. */
+	bufflen = sprintf(buffer, "%u", port);
+	if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff,
+	                       buffer, bufflen, &ct_sip_hdrs[POS_MEDIA]))
+		return 0;
+
+	return mangle_content_len(pskb, ctinfo, ct, dptr);
+}
+
+/* So, this packet has hit the connection tracking matching code.
+   Mangle it, and change the expectation to match the new version. */
+static unsigned int ip_nat_sdp(struct sk_buff **pskb,
+			       enum ip_conntrack_info ctinfo,
+			       struct ip_conntrack_expect *exp,
+			       const char *dptr)
+{
+	struct ip_conntrack *ct = exp->master;
+	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
+	u_int32_t newip;
+	u_int16_t port;
+
+	DEBUGP("ip_nat_sdp():\n");
+
+	/* Connection will come from reply */
+	newip = ct->tuplehash[!dir].tuple.dst.ip;
+
+	exp->tuple.dst.ip = newip;
+	exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port;
+	exp->dir = !dir;
+
+	/* When you see the packet, we need to NAT it the same as the
+	   this one. */
+	exp->expectfn = ip_nat_follow_master;
+
+	/* Try to get same port: if not, try to change it. */
+	for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) {
+		exp->tuple.dst.u.udp.port = htons(port);
+		if (ip_conntrack_expect_related(exp) == 0)
+			break;
+	}
+
+	if (port == 0)
+		return NF_DROP;
+
+	if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) {
+		ip_conntrack_unexpect_related(exp);
+		return NF_DROP;
+	}
+	return NF_ACCEPT;
+}
+
+static void __exit fini(void)
+{
+	ip_nat_sip_hook = NULL;
+	ip_nat_sdp_hook = NULL;
+	/* Make sure noone calls it, meanwhile. */
+	synchronize_net();
+}
+
+static int __init init(void)
+{
+	BUG_ON(ip_nat_sip_hook);
+	BUG_ON(ip_nat_sdp_hook);
+	ip_nat_sip_hook = ip_nat_sip;
+	ip_nat_sdp_hook = ip_nat_sdp;
+	return 0;
+}
+
+module_init(init);
+module_exit(fini);
diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c
index c332442..d20d557 100644
--- a/net/ipv4/netfilter/ip_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c
@@ -1348,4 +1348,4 @@
 module_init(ip_nat_snmp_basic_init);
 module_exit(ip_nat_snmp_basic_fini);
 
-module_param(debug, bool, 0600);
+module_param(debug, int, 0600);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index cee3397..706c002 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -1761,7 +1761,7 @@
 		goto free_newinfo;
 
 	/* And one copy for every other CPU */
-	for_each_cpu(i)
+	for_each_possible_cpu(i)
 		if (newinfo->entries[i] && newinfo->entries[i] != entry1)
 			memcpy(newinfo->entries[i], entry1, newinfo->size);
 
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index aad9d28..dbc83c5 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -241,25 +241,17 @@
 	struct iphdr *iph = skb->nh.iph;
 	unsigned long hashval;
 	u_int16_t sport, dport;
-	struct tcphdr *th;
-	struct udphdr *uh;
-	struct icmphdr *ih;
+	u_int16_t *ports;
 
 	switch (iph->protocol) {
 	case IPPROTO_TCP:
-		th = (void *)iph+iph->ihl*4;
-		sport = ntohs(th->source);
-		dport = ntohs(th->dest);
-		break;
 	case IPPROTO_UDP:
-		uh = (void *)iph+iph->ihl*4;
-		sport = ntohs(uh->source);
-		dport = ntohs(uh->dest);
-		break;
+	case IPPROTO_SCTP:
+	case IPPROTO_DCCP:
 	case IPPROTO_ICMP:
-		ih = (void *)iph+iph->ihl*4;
-		sport = ntohs(ih->un.echo.id);
-		dport = (ih->type<<8)|ih->code;
+		ports = (void *)iph+iph->ihl*4;
+		sport = ports[0];
+		dport = ports[1];
 		break;
 	default:
 		if (net_ratelimit()) {
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 0bba3c2..431a3ce 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -147,6 +147,7 @@
 	/* This packet will not be the same as the other: clear nf fields */
 	nf_reset(nskb);
 	nskb->nfmark = 0;
+	skb_init_secmark(nskb);
 
 	tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
 
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index 7c6836c..92980ab 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -28,9 +28,6 @@
 #include <linux/jhash.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <linux/sctp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/list.h>
@@ -83,6 +80,7 @@
 	/* used internally */
 	spinlock_t lock;		/* lock for list_head */
 	u_int32_t rnd;			/* random seed for hash */
+	int rnd_initialized;
 	struct timer_list timer;	/* timer for gc */
 	atomic_t count;			/* number entries in table */
 
@@ -137,8 +135,10 @@
 
 	/* initialize hash with random val at the time we allocate
 	 * the first hashtable entry */
-	if (!ht->rnd)
+	if (!ht->rnd_initialized) {
 		get_random_bytes(&ht->rnd, 4);
+		ht->rnd_initialized = 1;
+	}
 
 	if (ht->cfg.max &&
 	    atomic_read(&ht->count) >= ht->cfg.max) {
@@ -217,7 +217,7 @@
 
 	atomic_set(&hinfo->count, 0);
 	atomic_set(&hinfo->use, 1);
-	hinfo->rnd = 0;
+	hinfo->rnd_initialized = 0;
 	spin_lock_init(&hinfo->lock);
 	hinfo->pde = create_proc_entry(minfo->name, 0, hashlimit_procdir);
 	if (!hinfo->pde) {
@@ -381,49 +381,6 @@
 		dh->rateinfo.credit = dh->rateinfo.credit_cap;
 }
 
-static inline int get_ports(const struct sk_buff *skb, int offset, 
-			    u16 ports[2])
-{
-	union {
-		struct tcphdr th;
-		struct udphdr uh;
-		sctp_sctphdr_t sctph;
-	} hdr_u, *ptr_u;
-
-	/* Must not be a fragment. */
-	if (offset)
-		return 1;
-
-	/* Must be big enough to read ports (both UDP and TCP have
-	   them at the start). */
-	ptr_u = skb_header_pointer(skb, skb->nh.iph->ihl*4, 8, &hdr_u); 
-	if (!ptr_u)
-		return 1;
-
-	switch (skb->nh.iph->protocol) {
-		case IPPROTO_TCP:
-			ports[0] = ptr_u->th.source;
-			ports[1] = ptr_u->th.dest;
-			break;
-		case IPPROTO_UDP:
-			ports[0] = ptr_u->uh.source;
-			ports[1] = ptr_u->uh.dest;
-			break;
-		case IPPROTO_SCTP:
-			ports[0] = ptr_u->sctph.source;
-			ports[1] = ptr_u->sctph.dest;
-			break;
-		default:
-			/* all other protocols don't supprot per-port hash
-			 * buckets */
-			ports[0] = ports[1] = 0;
-			break;
-	}
-
-	return 0;
-}
-
-
 static int
 hashlimit_match(const struct sk_buff *skb,
 		const struct net_device *in,
@@ -449,8 +406,22 @@
 		dst.src_ip = skb->nh.iph->saddr;
 	if (hinfo->cfg.mode & IPT_HASHLIMIT_HASH_DPT
 	    ||hinfo->cfg.mode & IPT_HASHLIMIT_HASH_SPT) {
-		u_int16_t ports[2];
-		if (get_ports(skb, offset, ports)) {
+		u_int16_t _ports[2], *ports;
+
+		switch (skb->nh.iph->protocol) {
+		case IPPROTO_TCP:
+		case IPPROTO_UDP:
+		case IPPROTO_SCTP:
+		case IPPROTO_DCCP:
+			ports = skb_header_pointer(skb, skb->nh.iph->ihl*4,
+						   sizeof(_ports), &_ports);
+			break;
+		default:
+			_ports[0] = _ports[1] = 0;
+			ports = _ports;
+			break;
+		}
+		if (!ports) {
 			/* We've been asked to examine this packet, and we
 		 	  can't.  Hence, no choice but to drop. */
 			*hotdrop = 1;
@@ -561,7 +532,7 @@
 hashlimit_destroy(const struct xt_match *match, void *matchinfo,
 		  unsigned int matchsize)
 {
-	struct ipt_hashlimit_info *r = (struct ipt_hashlimit_info *) matchinfo;
+	struct ipt_hashlimit_info *r = matchinfo;
 
 	htable_put(r->hinfo);
 }
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index b847ee4..61a2139 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -1,1007 +1,499 @@
-/* Kernel module to check if the source address has been seen recently. */
-/* Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org */
-/* Author: Stephen Frost <sfrost@snowman.net> */
-/* Project Page: http://snowman.net/projects/ipt_recent/ */
-/* This software is distributed under the terms of the GPL, Version 2 */
-/* This copyright does not cover user programs that use kernel services
- * by normal system calls. */
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <asm/uaccess.h>
-#include <linux/ctype.h>
-#include <linux/ip.h>
-#include <linux/vmalloc.h>
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is a replacement of the old ipt_recent module, which carried the
+ * following copyright notice:
+ *
+ * Author: Stephen Frost <sfrost@snowman.net>
+ * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org
+ */
+#include <linux/init.h>
 #include <linux/moduleparam.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/list.h>
+#include <linux/random.h>
+#include <linux/jhash.h>
+#include <linux/bitops.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_recent.h>
 
-#undef DEBUG
-#define HASH_LOG 9
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("IP tables recently seen matching module");
+MODULE_LICENSE("GPL");
 
-/* Defaults, these can be overridden on the module command-line. */
 static unsigned int ip_list_tot = 100;
 static unsigned int ip_pkt_list_tot = 20;
 static unsigned int ip_list_hash_size = 0;
 static unsigned int ip_list_perms = 0644;
-#ifdef DEBUG
-static int debug = 1;
-#endif
-
-static char version[] =
-KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>.  http://snowman.net/projects/ipt_recent/\n";
-
-MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
-MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
-MODULE_LICENSE("GPL");
 module_param(ip_list_tot, uint, 0400);
 module_param(ip_pkt_list_tot, uint, 0400);
 module_param(ip_list_hash_size, uint, 0400);
 module_param(ip_list_perms, uint, 0400);
-#ifdef DEBUG
-module_param(debug, bool, 0600);
-MODULE_PARM_DESC(debug,"enable debugging output");
-#endif
-MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
-MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember");
-MODULE_PARM_DESC(ip_list_hash_size,"size of hash table used to look up IPs");
-MODULE_PARM_DESC(ip_list_perms,"permissions on /proc/net/ipt_recent/* files");
+MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list");
+MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)");
+MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs");
+MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files");
 
-/* Structure of our list of recently seen addresses. */
-struct recent_ip_list {
-	u_int32_t addr;
-	u_int8_t  ttl;
-	unsigned long last_seen;
-	unsigned long *last_pkts;
-	u_int32_t oldest_pkt;
-	u_int32_t hash_entry;
-	u_int32_t time_pos;
+
+struct recent_entry {
+	struct list_head	list;
+	struct list_head	lru_list;
+	u_int32_t		addr;
+	u_int8_t		ttl;
+	u_int8_t		index;
+	u_int16_t		nstamps;
+	unsigned long		stamps[0];
 };
 
-struct time_info_list {
-	u_int32_t position;
-	u_int32_t time;
-};
-
-/* Structure of our linked list of tables of recent lists. */
-struct recent_ip_tables {
-	char name[IPT_RECENT_NAME_LEN];
-	int count;
-	int time_pos;
-	struct recent_ip_list *table;
-	struct recent_ip_tables *next;
-	spinlock_t list_lock;
-	int *hash_table;
-	struct time_info_list *time_info;
+struct recent_table {
+	struct list_head	list;
+	char			name[IPT_RECENT_NAME_LEN];
 #ifdef CONFIG_PROC_FS
-	struct proc_dir_entry *status_proc;
-#endif /* CONFIG_PROC_FS */
+	struct proc_dir_entry	*proc;
+#endif
+	unsigned int		refcnt;
+	unsigned int		entries;
+	struct list_head	lru_list;
+	struct list_head	iphash[0];
 };
 
-/* Our current list of addresses we have recently seen.
- * Only added to on a --set, and only updated on --set || --update 
- */
-static struct recent_ip_tables *r_tables = NULL;
-
-/* We protect r_list with this spinlock so two processors are not modifying
- * the list at the same time. 
- */
+static LIST_HEAD(tables);
 static DEFINE_SPINLOCK(recent_lock);
+static DEFINE_MUTEX(recent_mutex);
 
 #ifdef CONFIG_PROC_FS
-/* Our /proc/net/ipt_recent entry */
-static struct proc_dir_entry *proc_net_ipt_recent = NULL;
+static struct proc_dir_entry	*proc_dir;
+static struct file_operations	recent_fops;
 #endif
 
-/* Function declaration for later. */
+static u_int32_t hash_rnd;
+static int hash_rnd_initted;
+
+static unsigned int recent_entry_hash(u_int32_t addr)
+{
+	if (!hash_rnd_initted) {
+		get_random_bytes(&hash_rnd, 4);
+		hash_rnd_initted = 1;
+	}
+	return jhash_1word(addr, hash_rnd) & (ip_list_hash_size - 1);
+}
+
+static struct recent_entry *
+recent_entry_lookup(const struct recent_table *table, u_int32_t addr, u_int8_t ttl)
+{
+	struct recent_entry *e;
+	unsigned int h;
+
+	h = recent_entry_hash(addr);
+	list_for_each_entry(e, &table->iphash[h], list)
+		if (e->addr == addr && (ttl == e->ttl || !ttl || !e->ttl))
+			return e;
+	return NULL;
+}
+
+static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
+{
+	list_del(&e->list);
+	list_del(&e->lru_list);
+	kfree(e);
+	t->entries--;
+}
+
+static struct recent_entry *
+recent_entry_init(struct recent_table *t, u_int32_t addr, u_int8_t ttl)
+{
+	struct recent_entry *e;
+
+	if (t->entries >= ip_list_tot) {
+		e = list_entry(t->lru_list.next, struct recent_entry, lru_list);
+		recent_entry_remove(t, e);
+	}
+	e = kmalloc(sizeof(*e) + sizeof(e->stamps[0]) * ip_pkt_list_tot,
+		    GFP_ATOMIC);
+	if (e == NULL)
+		return NULL;
+	e->addr      = addr;
+	e->ttl       = ttl;
+	e->stamps[0] = jiffies;
+	e->nstamps   = 1;
+	e->index     = 1;
+	list_add_tail(&e->list, &t->iphash[recent_entry_hash(addr)]);
+	list_add_tail(&e->lru_list, &t->lru_list);
+	t->entries++;
+	return e;
+}
+
+static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
+{
+	e->stamps[e->index++] = jiffies;
+	if (e->index > e->nstamps)
+		e->nstamps = e->index;
+	e->index %= ip_pkt_list_tot;
+	list_move_tail(&e->lru_list, &t->lru_list);
+}
+
+static struct recent_table *recent_table_lookup(const char *name)
+{
+	struct recent_table *t;
+
+	list_for_each_entry(t, &tables, list)
+		if (!strcmp(t->name, name))
+			return t;
+	return NULL;
+}
+
+static void recent_table_flush(struct recent_table *t)
+{
+	struct recent_entry *e, *next;
+	unsigned int i;
+
+	for (i = 0; i < ip_list_hash_size; i++) {
+		list_for_each_entry_safe(e, next, &t->iphash[i], list)
+			recent_entry_remove(t, e);
+	}
+}
+
 static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop);
-
-/* Function to hash a given address into the hash table of table_size size */
-static int hash_func(unsigned int addr, int table_size)
+ipt_recent_match(const struct sk_buff *skb,
+		 const struct net_device *in, const struct net_device *out,
+		 const struct xt_match *match, const void *matchinfo,
+		 int offset, unsigned int protoff, int *hotdrop)
 {
-	int result = 0;
-	unsigned int value = addr;
-	do { result ^= value; } while((value >>= HASH_LOG));
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": %d = hash_func(%u,%d)\n",
-			 result & (table_size - 1),
-			 addr,
-			 table_size);
-#endif
-
-	return(result & (table_size - 1));
-}
-
-#ifdef CONFIG_PROC_FS
-/* This is the function which produces the output for our /proc output
- * interface which lists each IP address, the last seen time and the 
- * other recent times the address was seen.
- */
-
-static int ip_recent_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
-{
-	int len = 0, count, last_len = 0, pkt_count;
-	off_t pos = 0;
-	off_t begin = 0;
-	struct recent_ip_tables *curr_table;
-
-	curr_table = (struct recent_ip_tables*) data;
-
-	spin_lock_bh(&curr_table->list_lock);
-	for(count = 0; count < ip_list_tot; count++) {
-		if(!curr_table->table[count].addr) continue;
-		last_len = len;
-		len += sprintf(buffer+len,"src=%u.%u.%u.%u ",NIPQUAD(curr_table->table[count].addr));
-		len += sprintf(buffer+len,"ttl: %u ",curr_table->table[count].ttl);
-		len += sprintf(buffer+len,"last_seen: %lu ",curr_table->table[count].last_seen);
-		len += sprintf(buffer+len,"oldest_pkt: %u ",curr_table->table[count].oldest_pkt);
-		len += sprintf(buffer+len,"last_pkts: %lu",curr_table->table[count].last_pkts[0]);
-		for(pkt_count = 1; pkt_count < ip_pkt_list_tot; pkt_count++) {
-			if(!curr_table->table[count].last_pkts[pkt_count]) break;
-			len += sprintf(buffer+len,", %lu",curr_table->table[count].last_pkts[pkt_count]);
-		}
-		len += sprintf(buffer+len,"\n");
-		pos = begin + len;
-		if(pos < offset) { len = 0; begin = pos; }
-		if(pos > offset + length) { len = last_len; break; }
-	}
-
-	*start = buffer + (offset - begin);
-	len -= (offset - begin);
-	if(len > length) len = length;
-
-	spin_unlock_bh(&curr_table->list_lock);
-	return len;
-}
-
-/* ip_recent_ctrl provides an interface for users to modify the table
- * directly.  This allows adding entries, removing entries, and
- * flushing the entire table.
- * This is done by opening up the appropriate table for writing and
- * sending one of:
- * xx.xx.xx.xx   -- Add entry to table with current time
- * +xx.xx.xx.xx  -- Add entry to table with current time
- * -xx.xx.xx.xx  -- Remove entry from table
- * clear         -- Flush table, remove all entries
- */
-
-static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned long size, void *data)
-{
-	static const u_int32_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
-	u_int32_t val;
-	int base, used = 0;
-	char c, *cp;
-	union iaddr {
-		uint8_t bytes[4];
-		uint32_t word;
-	} res;
-	uint8_t *pp = res.bytes;
-	int digit;
-
-	char buffer[20];
-	int len, check_set = 0, count;
-	u_int32_t addr = 0;
-	struct sk_buff *skb;
-	struct ipt_recent_info *info;
-	struct recent_ip_tables *curr_table;
-
-	curr_table = (struct recent_ip_tables*) data;
-
-	if(size > 20) len = 20; else len = size;
-
-	if(copy_from_user(buffer,input,len)) return -EFAULT;
-
-	if(len < 20) buffer[len] = '\0';
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl len: %d, input: `%.20s'\n",len,buffer);
-#endif
-
-	cp = buffer;
-	while(isspace(*cp)) { cp++; used++; if(used >= len-5) return used; }
-
-	/* Check if we are asked to flush the entire table */
-	if(!memcmp(cp,"clear",5)) {
-		used += 5;
-		spin_lock_bh(&curr_table->list_lock);
-		curr_table->time_pos = 0;
-		for(count = 0; count < ip_list_hash_size; count++) {
-			curr_table->hash_table[count] = -1;
-		}
-		for(count = 0; count < ip_list_tot; count++) {
-			curr_table->table[count].last_seen = 0;
-			curr_table->table[count].addr = 0;
-			curr_table->table[count].ttl = 0;
-			memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
-			curr_table->table[count].oldest_pkt = 0;
-			curr_table->table[count].time_pos = 0;
-			curr_table->time_info[count].position = count;
-			curr_table->time_info[count].time = 0;
-		}
-		spin_unlock_bh(&curr_table->list_lock);
-		return used;
-	}
-
-        check_set = IPT_RECENT_SET;
-	switch(*cp) {
-		case '+': check_set = IPT_RECENT_SET; cp++; used++; break;
-		case '-': check_set = IPT_RECENT_REMOVE; cp++; used++; break;
-		default: if(!isdigit(*cp)) return (used+1); break;
-	}
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl cp: `%c', check_set: %d\n",*cp,check_set);
-#endif
-	/* Get addr (effectively inet_aton()) */
-	/* Shamelessly stolen from libc, a function in the kernel for doing
-	 * this would, of course, be greatly preferred, but our options appear
-	 * to be rather limited, so we will just do it ourselves here.
-	 */
-	res.word = 0;
-
-	c = *cp;
-	for(;;) {
-		if(!isdigit(c)) return used;
-		val = 0; base = 10; digit = 0;
-		if(c == '0') {
-			c = *++cp;
-			if(c == 'x' || c == 'X') base = 16, c = *++cp;
-			else { base = 8; digit = 1; }
-		}
-		for(;;) {
-			if(isascii(c) && isdigit(c)) {
-				if(base == 8 && (c == '8' || c == '0')) return used;
-				val = (val * base) + (c - '0');
-				c = *++cp;
-				digit = 1;
-			} else if(base == 16 && isascii(c) && isxdigit(c)) {
-				val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A'));
-				c = *++cp;
-				digit = 1;
-			} else break;
-		}
-		if(c == '.') {
-			if(pp > res.bytes + 2 || val > 0xff) return used;
-			*pp++ = val;
-			c = *++cp;
-		} else break;
-	}
-	used = cp - buffer;
-	if(c != '\0' && (!isascii(c) || !isspace(c))) return used;
-	if(c == '\n') used++;
-	if(!digit) return used;
-
-	if(val > max[pp - res.bytes]) return used;
-	addr = res.word | htonl(val);
-
-	if(!addr && check_set == IPT_RECENT_SET) return used;
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl c: %c, addr: %u used: %d\n",c,addr,used);
-#endif
-
-	/* Set up and just call match */
-	info = kmalloc(sizeof(struct ipt_recent_info),GFP_KERNEL);
-	if(!info) { return -ENOMEM; }
-	info->seconds = 0;
-	info->hit_count = 0;
-	info->check_set = check_set;
-	info->invert = 0;
-	info->side = IPT_RECENT_SOURCE;
-	strncpy(info->name,curr_table->name,IPT_RECENT_NAME_LEN);
-	info->name[IPT_RECENT_NAME_LEN-1] = '\0';
-
-	skb = kmalloc(sizeof(struct sk_buff),GFP_KERNEL);
-	if (!skb) {
-		used = -ENOMEM;
-		goto out_free_info;
-	}
-	skb->nh.iph = kmalloc(sizeof(struct iphdr),GFP_KERNEL);
-	if (!skb->nh.iph) {
-		used = -ENOMEM;
-		goto out_free_skb;
-	}
-
-	skb->nh.iph->saddr = addr;
-	skb->nh.iph->daddr = 0;
-	/* Clear ttl since we have no way of knowing it */
-	skb->nh.iph->ttl = 0;
-	match(skb,NULL,NULL,NULL,info,0,0,NULL);
-
-	kfree(skb->nh.iph);
-out_free_skb:
-	kfree(skb);
-out_free_info:
-	kfree(info);
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": Leaving ip_recent_ctrl addr: %u used: %d\n",addr,used);
-#endif
-	return used;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-/* 'match' is our primary function, called by the kernel whenever a rule is
- * hit with our module as an option to it.
- * What this function does depends on what was specifically asked of it by
- * the user:
- * --set -- Add or update last seen time of the source address of the packet
- *   -- matchinfo->check_set == IPT_RECENT_SET
- * --rcheck -- Just check if the source address is in the list
- *   -- matchinfo->check_set == IPT_RECENT_CHECK
- * --update -- If the source address is in the list, update last_seen
- *   -- matchinfo->check_set == IPT_RECENT_UPDATE
- * --remove -- If the source address is in the list, remove it
- *   -- matchinfo->check_set == IPT_RECENT_REMOVE
- * --seconds -- Option to --rcheck/--update, only match if last_seen within seconds
- *   -- matchinfo->seconds
- * --hitcount -- Option to --rcheck/--update, only match if seen hitcount times
- *   -- matchinfo->hit_count
- * --seconds and --hitcount can be combined
- */
-static int
-match(const struct sk_buff *skb,
-      const struct net_device *in,
-      const struct net_device *out,
-      const struct xt_match *match,
-      const void *matchinfo,
-      int offset,
-      unsigned int protoff,
-      int *hotdrop)
-{
-	int pkt_count, hits_found, ans;
-	unsigned long now;
 	const struct ipt_recent_info *info = matchinfo;
-	u_int32_t addr = 0, time_temp;
-	u_int8_t ttl = skb->nh.iph->ttl;
-	int *hash_table;
-	int orig_hash_result, hash_result, temp, location = 0, time_loc, end_collision_chain = -1;
-	struct time_info_list *time_info;
-	struct recent_ip_tables *curr_table;
-	struct recent_ip_tables *last_table;
-	struct recent_ip_list *r_list;
+	struct recent_table *t;
+	struct recent_entry *e;
+	u_int32_t addr;
+	u_int8_t ttl;
+	int ret = info->invert;
 
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": match() called\n");
-#endif
+	if (info->side == IPT_RECENT_DEST)
+		addr = skb->nh.iph->daddr;
+	else
+		addr = skb->nh.iph->saddr;
 
-	/* Default is false ^ info->invert */
-	ans = info->invert;
+	ttl = skb->nh.iph->ttl;
+	/* use TTL as seen before forwarding */
+	if (out && !skb->sk)
+		ttl++;
 
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": match(): name = '%s'\n",info->name);
-#endif
-
-	/* if out != NULL then routing has been done and TTL changed.
-	 * We change it back here internally for match what came in before routing. */
-	if(out) ttl++;
-
-	/* Find the right table */
 	spin_lock_bh(&recent_lock);
-	curr_table = r_tables;
-	while( (last_table = curr_table) && strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (curr_table = curr_table->next) );
+	t = recent_table_lookup(info->name);
+	e = recent_entry_lookup(t, addr,
+				info->check_set & IPT_RECENT_TTL ? ttl : 0);
+	if (e == NULL) {
+		if (!(info->check_set & IPT_RECENT_SET))
+			goto out;
+		e = recent_entry_init(t, addr, ttl);
+		if (e == NULL)
+			*hotdrop = 1;
+		ret ^= 1;
+		goto out;
+	}
 
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": match(): table found('%s')\n",info->name);
-#endif
+	if (info->check_set & IPT_RECENT_SET)
+		ret ^= 1;
+	else if (info->check_set & IPT_RECENT_REMOVE) {
+		recent_entry_remove(t, e);
+		ret ^= 1;
+	} else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) {
+		unsigned long t = jiffies - info->seconds * HZ;
+		unsigned int i, hits = 0;
 
+		for (i = 0; i < e->nstamps; i++) {
+			if (info->seconds && time_after(t, e->stamps[i]))
+				continue;
+			if (++hits >= info->hit_count) {
+				ret ^= 1;
+				break;
+			}
+		}
+	}
+
+	if (info->check_set & IPT_RECENT_SET ||
+	    (info->check_set & IPT_RECENT_UPDATE && ret)) {
+		recent_entry_update(t, e);
+		e->ttl = ttl;
+	}
+out:
 	spin_unlock_bh(&recent_lock);
-
-	/* Table with this name not found, match impossible */
-	if(!curr_table) { return ans; }
-
-	/* Make sure no one is changing the list while we work with it */
-	spin_lock_bh(&curr_table->list_lock);
-
-	r_list = curr_table->table;
-	if(info->side == IPT_RECENT_DEST) addr = skb->nh.iph->daddr; else addr = skb->nh.iph->saddr;
-
-	if(!addr) { 
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": match() address (%u) invalid, leaving.\n",addr);
-#endif
-		spin_unlock_bh(&curr_table->list_lock);
-		return ans;
-	}
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": match(): checking table, addr: %u, ttl: %u, orig_ttl: %u\n",addr,ttl,skb->nh.iph->ttl);
-#endif
-
-	/* Get jiffies now in case they changed while we were waiting for a lock */
-	now = jiffies;
-	hash_table = curr_table->hash_table;
-	time_info = curr_table->time_info;
-
-	orig_hash_result = hash_result = hash_func(addr,ip_list_hash_size);
-	/* Hash entry at this result used */
-	/* Check for TTL match if requested.  If TTL is zero then a match would never
-	 * happen, so match regardless of existing TTL in that case.  Zero means the
-	 * entry was added via the /proc interface anyway, so we will just use the
-	 * first TTL we get for that IP address. */
-	if(info->check_set & IPT_RECENT_TTL) {
-		while(hash_table[hash_result] != -1 && !(r_list[hash_table[hash_result]].addr == addr &&
-			(!r_list[hash_table[hash_result]].ttl || r_list[hash_table[hash_result]].ttl == ttl))) {
-			/* Collision in hash table */
-			hash_result = (hash_result + 1) % ip_list_hash_size;
-		}
-	} else {
-		while(hash_table[hash_result] != -1 && r_list[hash_table[hash_result]].addr != addr) {
-			/* Collision in hash table */
-			hash_result = (hash_result + 1) % ip_list_hash_size;
-		}
-	}
-
-	if(hash_table[hash_result] == -1 && !(info->check_set & IPT_RECENT_SET)) {
-		/* IP not in list and not asked to SET */
-		spin_unlock_bh(&curr_table->list_lock);
-		return ans;
-	}
-
-	/* Check if we need to handle the collision, do not need to on REMOVE */
-	if(orig_hash_result != hash_result && !(info->check_set & IPT_RECENT_REMOVE)) {
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision in hash table. (or: %d,hr: %d,oa: %u,ha: %u)\n",
-				 orig_hash_result,
-				 hash_result,
-				 r_list[hash_table[orig_hash_result]].addr,
-				 addr);
-#endif
-
-		/* We had a collision.
-		 * orig_hash_result is where we started, hash_result is where we ended up.
-		 * So, swap them because we are likely to see the same guy again sooner */
-#ifdef DEBUG
-		if(debug) {
-		  printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[orig_hash_result] = %d\n",hash_table[orig_hash_result]);
-		  printk(KERN_INFO RECENT_NAME ": match(): Collision; r_list[hash_table[orig_hash_result]].hash_entry = %d\n",
-				r_list[hash_table[orig_hash_result]].hash_entry);
-		}
-#endif
-
-		r_list[hash_table[orig_hash_result]].hash_entry = hash_result;
-
-
-		temp = hash_table[orig_hash_result];
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[hash_result] = %d\n",hash_table[hash_result]);
-#endif
-		hash_table[orig_hash_result] = hash_table[hash_result];
-		hash_table[hash_result] = temp;
-		temp = hash_result;
-		hash_result = orig_hash_result;
-		orig_hash_result = temp;
-		time_info[r_list[hash_table[orig_hash_result]].time_pos].position = hash_table[orig_hash_result];
-		if(hash_table[hash_result] != -1) {
-			r_list[hash_table[hash_result]].hash_entry = hash_result;
-			time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
-		}
-
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision handled.\n");
-#endif
-	}
-
-	if(hash_table[hash_result] == -1) {
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": match(): New table entry. (hr: %d,ha: %u)\n",
-				 hash_result, addr);
-#endif
-
-		/* New item found and IPT_RECENT_SET, so we need to add it */
-		location = time_info[curr_table->time_pos].position;
-		hash_table[r_list[location].hash_entry] = -1;
-		hash_table[hash_result] = location;
-		memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
-		r_list[location].time_pos = curr_table->time_pos;
-		r_list[location].addr = addr;
-		r_list[location].ttl = ttl;
-		r_list[location].last_seen = now;
-		r_list[location].oldest_pkt = 1;
-		r_list[location].last_pkts[0] = now;
-		r_list[location].hash_entry = hash_result;
-		time_info[curr_table->time_pos].time = r_list[location].last_seen;
-		curr_table->time_pos = (curr_table->time_pos + 1) % ip_list_tot;
-
-		ans = !info->invert;
-	} else {
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": match(): Existing table entry. (hr: %d,ha: %u)\n",
-				 hash_result,
-				 addr);
-#endif
-
-		/* Existing item found */
-		location = hash_table[hash_result];
-		/* We have a match on address, now to make sure it meets all requirements for a
-		 * full match. */
-		if(info->check_set & IPT_RECENT_CHECK || info->check_set & IPT_RECENT_UPDATE) {
-			if(!info->seconds && !info->hit_count) ans = !info->invert; else ans = info->invert;
-			if(info->seconds && !info->hit_count) {
-				if(time_before_eq(now,r_list[location].last_seen+info->seconds*HZ)) ans = !info->invert; else ans = info->invert;
-			}
-			if(info->seconds && info->hit_count) {
-				for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
-					if(r_list[location].last_pkts[pkt_count] == 0) break;
-					if(time_before_eq(now,r_list[location].last_pkts[pkt_count]+info->seconds*HZ)) hits_found++;
-				}
-				if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
-			}
-			if(info->hit_count && !info->seconds) {
-				for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
-					if(r_list[location].last_pkts[pkt_count] == 0) break;
-					hits_found++;
-				}
-				if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
-			}
-		}
-#ifdef DEBUG
-		if(debug) {
-			if(ans)
-				printk(KERN_INFO RECENT_NAME ": match(): match addr: %u\n",addr);
-			else
-				printk(KERN_INFO RECENT_NAME ": match(): no match addr: %u\n",addr);
-		}
-#endif
-
-		/* If and only if we have been asked to SET, or to UPDATE (on match) do we add the
-		 * current timestamp to the last_seen. */
-		if((info->check_set & IPT_RECENT_SET && (ans = !info->invert)) || (info->check_set & IPT_RECENT_UPDATE && ans)) {
-#ifdef DEBUG
-			if(debug) printk(KERN_INFO RECENT_NAME ": match(): SET or UPDATE; updating time info.\n");
-#endif
-			/* Have to update our time info */
-			time_loc = r_list[location].time_pos;
-			time_info[time_loc].time = now;
-			time_info[time_loc].position = location;
-			while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
-				time_temp = time_info[time_loc].time;
-				time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
-				time_info[(time_loc+1)%ip_list_tot].time = time_temp;
-				time_temp = time_info[time_loc].position;
-				time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
-				time_info[(time_loc+1)%ip_list_tot].position = time_temp;
-				r_list[time_info[time_loc].position].time_pos = time_loc;
-				r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
-				time_loc = (time_loc+1) % ip_list_tot;
-			}
-			r_list[location].time_pos = time_loc;
-			r_list[location].ttl = ttl;
-			r_list[location].last_pkts[r_list[location].oldest_pkt] = now;
-			r_list[location].oldest_pkt = ++r_list[location].oldest_pkt % ip_pkt_list_tot;
-			r_list[location].last_seen = now;
-		}
-		/* If we have been asked to remove the entry from the list, just set it to 0 */
-		if(info->check_set & IPT_RECENT_REMOVE) {
-#ifdef DEBUG
-			if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; clearing entry (or: %d, hr: %d).\n",orig_hash_result,hash_result);
-#endif
-			/* Check if this is part of a collision chain */
-			while(hash_table[(orig_hash_result+1) % ip_list_hash_size] != -1) {
-				orig_hash_result++;
-				if(hash_func(r_list[hash_table[orig_hash_result]].addr,ip_list_hash_size) == hash_result) {
-					/* Found collision chain, how deep does this rabbit hole go? */
-#ifdef DEBUG
-					if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; found collision chain.\n");
-#endif
-					end_collision_chain = orig_hash_result;
-				}
-			}
-			if(end_collision_chain != -1) {
-#ifdef DEBUG
-				if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; part of collision chain, moving to end.\n");
-#endif
-				/* Part of a collision chain, swap it with the end of the chain
-				 * before removing. */
-				r_list[hash_table[end_collision_chain]].hash_entry = hash_result;
-				temp = hash_table[end_collision_chain];
-				hash_table[end_collision_chain] = hash_table[hash_result];
-				hash_table[hash_result] = temp;
-				time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
-				hash_result = end_collision_chain;
-				r_list[hash_table[hash_result]].hash_entry = hash_result;
-				time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
-			}
-			location = hash_table[hash_result];
-			hash_table[r_list[location].hash_entry] = -1;
-			time_loc = r_list[location].time_pos;
-			time_info[time_loc].time = 0;
-			time_info[time_loc].position = location;
-			while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
-				time_temp = time_info[time_loc].time;
-				time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
-				time_info[(time_loc+1)%ip_list_tot].time = time_temp;
-				time_temp = time_info[time_loc].position;
-				time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
-				time_info[(time_loc+1)%ip_list_tot].position = time_temp;
-				r_list[time_info[time_loc].position].time_pos = time_loc;
-				r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
-				time_loc = (time_loc+1) % ip_list_tot;
-			}
-			r_list[location].time_pos = time_loc;
-			r_list[location].last_seen = 0;
-			r_list[location].addr = 0;
-			r_list[location].ttl = 0;
-			memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
-			r_list[location].oldest_pkt = 0;
-			ans = !info->invert;
-		}
-		spin_unlock_bh(&curr_table->list_lock);
-		return ans;
-	}
-
-	spin_unlock_bh(&curr_table->list_lock);
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": match() left.\n");
-#endif
-	return ans;
+	return ret;
 }
 
-/* This function is to verify that the rule given during the userspace iptables
- * command is correct.
- * If the command is valid then we check if the table name referred to by the
- * rule exists, if not it is created.
- */
 static int
-checkentry(const char *tablename,
-           const void *ip,
-	   const struct xt_match *match,
-           void *matchinfo,
-           unsigned int matchsize,
-           unsigned int hook_mask)
+ipt_recent_checkentry(const char *tablename, const void *ip,
+		      const struct xt_match *match, void *matchinfo,
+		      unsigned int matchsize, unsigned int hook_mask)
 {
-	int flag = 0, c;
-	unsigned long *hold;
 	const struct ipt_recent_info *info = matchinfo;
-	struct recent_ip_tables *curr_table, *find_table, *last_table;
+	struct recent_table *t;
+	unsigned i;
+	int ret = 0;
 
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
-#endif
-
-	/* seconds and hit_count only valid for CHECK/UPDATE */
-	if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; }
-	if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; }
-	if(info->check_set & IPT_RECENT_CHECK) flag++;
-	if(info->check_set & IPT_RECENT_UPDATE) flag++;
-
-	/* One and only one of these should ever be set */
-	if(flag != 1) return 0;
-
-	/* Name must be set to something */
-	if(!info->name || !info->name[0]) return 0;
-
-	/* Things look good, create a list for this if it does not exist */
-	/* Lock the linked list while we play with it */
-	spin_lock_bh(&recent_lock);
-
-	/* Look for an entry with this name already created */
-	/* Finds the end of the list and the entry before the end if current name does not exist */
-	find_table = r_tables;
-	while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
-
-	/* If a table already exists just increment the count on that table and return */
-	if(find_table) { 
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), incrementing count.\n",info->name);
-#endif
-		find_table->count++;
-		spin_unlock_bh(&recent_lock);
-		return 1;
-	}
-
-	spin_unlock_bh(&recent_lock);
-
-	/* Table with this name not found */
-	/* Allocate memory for new linked list item */
-
-#ifdef DEBUG
-	if(debug) {
-		printk(KERN_INFO RECENT_NAME ": checkentry: no table found (%s)\n",info->name);
-		printk(KERN_INFO RECENT_NAME ": checkentry: Allocationg %d for link-list entry.\n",sizeof(struct recent_ip_tables));
-	}
-#endif
-
-	curr_table = vmalloc(sizeof(struct recent_ip_tables));
-	if(curr_table == NULL) return 0;
-
-	spin_lock_init(&curr_table->list_lock);
-	curr_table->next = NULL;
-	curr_table->count = 1;
-	curr_table->time_pos = 0;
-	strncpy(curr_table->name,info->name,IPT_RECENT_NAME_LEN);
-	curr_table->name[IPT_RECENT_NAME_LEN-1] = '\0';
-
-	/* Allocate memory for this table and the list of packets in each entry. */
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for table (%s).\n",
-			sizeof(struct recent_ip_list)*ip_list_tot,
-			info->name);
-#endif
-
-	curr_table->table = vmalloc(sizeof(struct recent_ip_list)*ip_list_tot);
-	if(curr_table->table == NULL) { vfree(curr_table); return 0; }
-	memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for pkt_list.\n",
-			sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
-#endif
-
-	hold = vmalloc(sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
-#endif
-	if(hold == NULL) { 
-		printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for pkt_list.\n");
-		vfree(curr_table->table); 
-		vfree(curr_table);
+	if (hweight8(info->check_set &
+		     (IPT_RECENT_SET | IPT_RECENT_REMOVE |
+		      IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1)
 		return 0;
-	}
-	for(c = 0; c < ip_list_tot; c++) {
-		curr_table->table[c].last_pkts = hold + c*ip_pkt_list_tot;
-	}
-
-	/* Allocate memory for the hash table */
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for hash_table.\n",
-			sizeof(int)*ip_list_hash_size);
-#endif
-
-	curr_table->hash_table = vmalloc(sizeof(int)*ip_list_hash_size);
-	if(!curr_table->hash_table) {
-		printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for hash_table.\n");
-		vfree(hold);
-		vfree(curr_table->table); 
-		vfree(curr_table);
+	if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
+	    (info->seconds || info->hit_count))
 		return 0;
-	}
-
-	for(c = 0; c < ip_list_hash_size; c++) {
-		curr_table->hash_table[c] = -1;
-	}
-
-	/* Allocate memory for the time info */
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for time_info.\n",
-			sizeof(struct time_info_list)*ip_list_tot);
-#endif
-
-	curr_table->time_info = vmalloc(sizeof(struct time_info_list)*ip_list_tot);
-	if(!curr_table->time_info) {
-		printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for time_info.\n");
-		vfree(curr_table->hash_table);
-		vfree(hold);
-		vfree(curr_table->table); 
-		vfree(curr_table);
+	if (info->name[0] == '\0' ||
+	    strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
 		return 0;
-	}
-	for(c = 0; c < ip_list_tot; c++) {
-		curr_table->time_info[c].position = c;
-		curr_table->time_info[c].time = 0;
+
+	mutex_lock(&recent_mutex);
+	t = recent_table_lookup(info->name);
+	if (t != NULL) {
+		t->refcnt++;
+		ret = 1;
+		goto out;
 	}
 
-	/* Put the new table in place */
-	spin_lock_bh(&recent_lock);
-	find_table = r_tables;
-	while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
-
-	/* If a table already exists just increment the count on that table and return */
-	if(find_table) { 
-		find_table->count++;	
-		spin_unlock_bh(&recent_lock);
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), created by other process.\n",info->name);
-#endif
-		vfree(curr_table->time_info);
-		vfree(curr_table->hash_table);
-		vfree(hold);
-		vfree(curr_table->table);
-		vfree(curr_table);
-		return 1;
-	}
-	if(!last_table) r_tables = curr_table; else last_table->next = curr_table;
-
-	spin_unlock_bh(&recent_lock);
-
+	t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
+		    GFP_KERNEL);
+	if (t == NULL)
+		goto out;
+	t->refcnt = 1;
+	strcpy(t->name, info->name);
+	INIT_LIST_HEAD(&t->lru_list);
+	for (i = 0; i < ip_list_hash_size; i++)
+		INIT_LIST_HEAD(&t->iphash[i]);
 #ifdef CONFIG_PROC_FS
-	/* Create our proc 'status' entry. */
-	curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent);
-	if (!curr_table->status_proc) {
-		vfree(hold);
-		printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n");
-		/* Destroy the created table */
-		spin_lock_bh(&recent_lock);
-		last_table = NULL;
-		curr_table = r_tables;
-		if(!curr_table) {
-#ifdef DEBUG
-			if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, no tables.\n");
-#endif
-			spin_unlock_bh(&recent_lock);
-			return 0;
-		}
-		while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
-		if(!curr_table) {
-#ifdef DEBUG
-			if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, table already destroyed.\n");
-#endif
-			spin_unlock_bh(&recent_lock);
-			return 0;
-		}
-		if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
-		spin_unlock_bh(&recent_lock);
-		vfree(curr_table->time_info);
-		vfree(curr_table->hash_table);
-		vfree(curr_table->table);
-		vfree(curr_table);
-		return 0;
+	t->proc = create_proc_entry(t->name, ip_list_perms, proc_dir);
+	if (t->proc == NULL) {
+		kfree(t);
+		goto out;
 	}
-	
-	curr_table->status_proc->owner = THIS_MODULE;
-	curr_table->status_proc->data = curr_table;
-	wmb();
-	curr_table->status_proc->read_proc = ip_recent_get_info;
-	curr_table->status_proc->write_proc = ip_recent_ctrl;
-#endif /* CONFIG_PROC_FS */
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() left.\n");
+	t->proc->proc_fops = &recent_fops;
+	t->proc->data      = t;
 #endif
-
-	return 1;
+	spin_lock_bh(&recent_lock);
+	list_add_tail(&t->list, &tables);
+	spin_unlock_bh(&recent_lock);
+	ret = 1;
+out:
+	mutex_unlock(&recent_mutex);
+	return ret;
 }
 
-/* This function is called in the event that a rule matching this module is
- * removed.
- * When this happens we need to check if there are no other rules matching
- * the table given.  If that is the case then we remove the table and clean
- * up its memory.
- */
 static void
-destroy(const struct xt_match *match, void *matchinfo, unsigned int matchsize)
+ipt_recent_destroy(const struct xt_match *match, void *matchinfo,
+		   unsigned int matchsize)
 {
 	const struct ipt_recent_info *info = matchinfo;
-	struct recent_ip_tables *curr_table, *last_table;
+	struct recent_table *t;
 
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": destroy() entered.\n");
-#endif
-
-	if(matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return;
-
-	/* Lock the linked list while we play with it */
-	spin_lock_bh(&recent_lock);
-
-	/* Look for an entry with this name already created */
-	/* Finds the end of the list and the entry before the end if current name does not exist */
-	last_table = NULL;
-	curr_table = r_tables;
-	if(!curr_table) { 
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": destroy() No tables found, leaving.\n");
-#endif
+	mutex_lock(&recent_mutex);
+	t = recent_table_lookup(info->name);
+	if (--t->refcnt == 0) {
+		spin_lock_bh(&recent_lock);
+		list_del(&t->list);
 		spin_unlock_bh(&recent_lock);
-		return;
-	}
-	while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
-
-	/* If a table does not exist then do nothing and return */
-	if(!curr_table) { 
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table not found, leaving.\n");
-#endif
-		spin_unlock_bh(&recent_lock);
-		return;
-	}
-
-	curr_table->count--;
-
-	/* If count is still non-zero then there are still rules referenceing it so we do nothing */
-	if(curr_table->count) { 
-#ifdef DEBUG
-		if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, non-zero count, leaving.\n");
-#endif
-		spin_unlock_bh(&recent_lock);
-		return;
-	}
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, zero count, removing.\n");
-#endif
-
-	/* Count must be zero so we remove this table from the list */
-	if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
-
-	spin_unlock_bh(&recent_lock);
-
-	/* lock to make sure any late-runners still using this after we removed it from
-	 * the list finish up then remove everything */
-	spin_lock_bh(&curr_table->list_lock);
-	spin_unlock_bh(&curr_table->list_lock);
-
+		recent_table_flush(t);
 #ifdef CONFIG_PROC_FS
-	if(curr_table->status_proc) remove_proc_entry(curr_table->name,proc_net_ipt_recent);
-#endif /* CONFIG_PROC_FS */
-	vfree(curr_table->table[0].last_pkts);
-	vfree(curr_table->table);
-	vfree(curr_table->hash_table);
-	vfree(curr_table->time_info);
-	vfree(curr_table);
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": destroy() left.\n");
+		remove_proc_entry(t->name, proc_dir);
 #endif
-
-	return;
+		kfree(t);
+	}
+	mutex_unlock(&recent_mutex);
 }
 
-/* This is the structure we pass to ipt_register to register our
- * module with iptables.
- */
+#ifdef CONFIG_PROC_FS
+struct recent_iter_state {
+	struct recent_table	*table;
+	unsigned int		bucket;
+};
+
+static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	struct recent_iter_state *st = seq->private;
+	struct recent_table *t = st->table;
+	struct recent_entry *e;
+	loff_t p = *pos;
+
+	spin_lock_bh(&recent_lock);
+
+	for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) {
+		list_for_each_entry(e, &t->iphash[st->bucket], list) {
+			if (p-- == 0)
+				return e;
+		}
+	}
+	return NULL;
+}
+
+static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct recent_iter_state *st = seq->private;
+	struct recent_table *t = st->table;
+	struct recent_entry *e = v;
+	struct list_head *head = e->list.next;
+
+	while (head == &t->iphash[st->bucket]) {
+		if (++st->bucket >= ip_list_hash_size)
+			return NULL;
+		head = t->iphash[st->bucket].next;
+	}
+	(*pos)++;
+	return list_entry(head, struct recent_entry, list);
+}
+
+static void recent_seq_stop(struct seq_file *s, void *v)
+{
+	spin_unlock_bh(&recent_lock);
+}
+
+static int recent_seq_show(struct seq_file *seq, void *v)
+{
+	struct recent_entry *e = v;
+	unsigned int i;
+
+	i = (e->index - 1) % ip_pkt_list_tot;
+	seq_printf(seq, "src=%u.%u.%u.%u ttl: %u last_seen: %lu oldest_pkt: %u",
+		   NIPQUAD(e->addr), e->ttl, e->stamps[i], e->index);
+	for (i = 0; i < e->nstamps; i++)
+		seq_printf(seq, "%s %lu", i ? "," : "", e->stamps[i]);
+	seq_printf(seq, "\n");
+	return 0;
+}
+
+static struct seq_operations recent_seq_ops = {
+	.start		= recent_seq_start,
+	.next		= recent_seq_next,
+	.stop		= recent_seq_stop,
+	.show		= recent_seq_show,
+};
+
+static int recent_seq_open(struct inode *inode, struct file *file)
+{
+	struct proc_dir_entry *pde = PDE(inode);
+	struct seq_file *seq;
+	struct recent_iter_state *st;
+	int ret;
+
+	st = kzalloc(sizeof(*st), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+	ret = seq_open(file, &recent_seq_ops);
+	if (ret)
+		kfree(st);
+	st->table    = pde->data;
+	seq          = file->private_data;
+	seq->private = st;
+	return ret;
+}
+
+static ssize_t recent_proc_write(struct file *file, const char __user *input,
+				 size_t size, loff_t *loff)
+{
+	struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+	struct recent_table *t = pde->data;
+	struct recent_entry *e;
+	char buf[sizeof("+255.255.255.255")], *c = buf;
+	u_int32_t addr;
+	int add;
+
+	if (size > sizeof(buf))
+		size = sizeof(buf);
+	if (copy_from_user(buf, input, size))
+		return -EFAULT;
+	while (isspace(*c))
+		c++;
+
+	if (size - (c - buf) < 5)
+		return c - buf;
+	if (!strncmp(c, "clear", 5)) {
+		c += 5;
+		spin_lock_bh(&recent_lock);
+		recent_table_flush(t);
+		spin_unlock_bh(&recent_lock);
+		return c - buf;
+	}
+
+	switch (*c) {
+	case '-':
+		add = 0;
+		c++;
+		break;
+	case '+':
+		c++;
+	default:
+		add = 1;
+		break;
+	}
+	addr = in_aton(c);
+
+	spin_lock_bh(&recent_lock);
+	e = recent_entry_lookup(t, addr, 0);
+	if (e == NULL) {
+		if (add)
+			recent_entry_init(t, addr, 0);
+	} else {
+		if (add)
+			recent_entry_update(t, e);
+		else
+			recent_entry_remove(t, e);
+	}
+	spin_unlock_bh(&recent_lock);
+	return size;
+}
+
+static struct file_operations recent_fops = {
+	.open		= recent_seq_open,
+	.read		= seq_read,
+	.write		= recent_proc_write,
+	.release	= seq_release_private,
+	.owner		= THIS_MODULE,
+};
+#endif /* CONFIG_PROC_FS */
+
 static struct ipt_match recent_match = {
 	.name		= "recent",
-	.match		= match,
+	.match		= ipt_recent_match,
 	.matchsize	= sizeof(struct ipt_recent_info),
-	.checkentry	= checkentry,
-	.destroy	= destroy,
-	.me		= THIS_MODULE
+	.checkentry	= ipt_recent_checkentry,
+	.destroy	= ipt_recent_destroy,
+	.me		= THIS_MODULE,
 };
 
-/* Kernel module initialization. */
 static int __init ipt_recent_init(void)
 {
-	int err, count;
+	int err;
 
-	printk(version);
-#ifdef CONFIG_PROC_FS
-	proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
-	if(!proc_net_ipt_recent) return -ENOMEM;
-#endif
-
-	if(ip_list_hash_size && ip_list_hash_size <= ip_list_tot) {
-	  printk(KERN_WARNING RECENT_NAME ": ip_list_hash_size too small, resetting to default.\n");
-	  ip_list_hash_size = 0;
-	}
-
-	if(!ip_list_hash_size) {
-		ip_list_hash_size = ip_list_tot*3;
-		count = 2*2;
-		while(ip_list_hash_size > count) count = count*2;
-		ip_list_hash_size = count;
-	}
-
-#ifdef DEBUG
-	if(debug) printk(KERN_INFO RECENT_NAME ": ip_list_hash_size: %d\n",ip_list_hash_size);
-#endif
+	if (!ip_list_tot || !ip_pkt_list_tot || ip_pkt_list_tot > 255)
+		return -EINVAL;
+	ip_list_hash_size = 1 << fls(ip_list_tot);
 
 	err = ipt_register_match(&recent_match);
+#ifdef CONFIG_PROC_FS
 	if (err)
-		remove_proc_entry("ipt_recent", proc_net);
+		return err;
+	proc_dir = proc_mkdir("ipt_recent", proc_net);
+	if (proc_dir == NULL) {
+		ipt_unregister_match(&recent_match);
+		err = -ENOMEM;
+	}
+#endif
 	return err;
 }
 
-/* Kernel module destruction. */
-static void __exit ipt_recent_fini(void)
+static void __exit ipt_recent_exit(void)
 {
+	BUG_ON(!list_empty(&tables));
 	ipt_unregister_match(&recent_match);
-
-	remove_proc_entry("ipt_recent",proc_net);
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("ipt_recent", proc_net);
+#endif
 }
 
-/* Register our module with the kernel. */
 module_init(ipt_recent_init);
-module_exit(ipt_recent_fini);
+module_exit(ipt_recent_exit);
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index 77d9744..8cc8e1b 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -145,7 +145,7 @@
 
 	/* This is where we call the helper: as the packet goes out. */
 	ct = nf_ct_get(*pskb, &ctinfo);
-	if (!ct)
+	if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
 		return NF_ACCEPT;
 
 	help = nfct_help(ct);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 4b0d361..663a73e 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -235,7 +235,7 @@
 	}
 
 	/* See ip_conntrack_proto_tcp.c */
-	if (hooknum == NF_IP_PRE_ROUTING &&
+	if (nf_conntrack_checksum && hooknum == NF_IP_PRE_ROUTING &&
 	    nf_ip_checksum(skb, hooknum, dataoff, 0)) {
 		if (LOG_INVALID(IPPROTO_ICMP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, NULL,
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index fc25624..bd221ec 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -103,7 +103,7 @@
 }
 
 struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
-			     unsigned long raddr, unsigned long laddr,
+			     __be32 raddr, __be32 laddr,
 			     int dif)
 {
 	struct hlist_node *node;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index cc9423d..60b11ae 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -244,7 +244,7 @@
 
 static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
 #define RT_CACHE_STAT_INC(field) \
-	(per_cpu(rt_cache_stat, raw_smp_processor_id()).field++)
+	(__raw_get_cpu_var(rt_cache_stat).field++)
 
 static int rt_intern_hash(unsigned hash, struct rtable *rth,
 				struct rtable **res);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 6b6c3ad..ce4cd5f 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -182,14 +182,6 @@
 		.strategy	= &ipv4_doint_and_flush_strategy,
 	},
         {
-		.ctl_name	= NET_IPV4_AUTOCONFIG,
-		.procname	= "ip_autoconfig",
-		.data		= &ipv4_config.autoconfig,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
-	},
-        {
 		.ctl_name	= NET_IPV4_NO_PMTU_DISC,
 		.procname	= "ip_no_pmtu_disc",
 		.data		= &ipv4_config.no_pmtu_disc,
@@ -688,6 +680,24 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
+#ifdef CONFIG_NET_DMA
+	{
+		.ctl_name	= NET_TCP_DMA_COPYBREAK,
+		.procname	= "tcp_dma_copybreak",
+		.data		= &sysctl_tcp_dma_copybreak,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+#endif
+	{
+		.ctl_name	= NET_TCP_SLOW_START_AFTER_IDLE,
+		.procname	= "tcp_slow_start_after_idle",
+		.data		= &sysctl_tcp_slow_start_after_idle,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
 	{ .ctl_name = 0 }
 };
 
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e2b7b80..c04176b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -258,12 +258,13 @@
 #include <linux/random.h>
 #include <linux/bootmem.h>
 #include <linux/cache.h>
+#include <linux/err.h>
 
 #include <net/icmp.h>
 #include <net/tcp.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
-
+#include <net/netdma.h>
 
 #include <asm/uaccess.h>
 #include <asm/ioctls.h>
@@ -571,7 +572,7 @@
 		skb->ip_summed = CHECKSUM_HW;
 		tp->write_seq += copy;
 		TCP_SKB_CB(skb)->end_seq += copy;
-		skb_shinfo(skb)->tso_segs = 0;
+		skb_shinfo(skb)->gso_segs = 0;
 
 		if (!copied)
 			TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
@@ -622,14 +623,10 @@
 	ssize_t res;
 	struct sock *sk = sock->sk;
 
-#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
-
 	if (!(sk->sk_route_caps & NETIF_F_SG) ||
-	    !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS))
+	    !(sk->sk_route_caps & NETIF_F_ALL_CSUM))
 		return sock_no_sendpage(sock, page, offset, size, flags);
 
-#undef TCP_ZC_CSUM_FLAGS
-
 	lock_sock(sk);
 	TCP_CHECK_TIMER(sk);
 	res = do_tcp_sendpages(sk, &page, offset, size, flags);
@@ -726,9 +723,7 @@
 				/*
 				 * Check whether we can use HW checksum.
 				 */
-				if (sk->sk_route_caps &
-				    (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM |
-				     NETIF_F_HW_CSUM))
+				if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
 					skb->ip_summed = CHECKSUM_HW;
 
 				skb_entail(sk, tp, skb);
@@ -824,7 +819,7 @@
 
 			tp->write_seq += copy;
 			TCP_SKB_CB(skb)->end_seq += copy;
-			skb_shinfo(skb)->tso_segs = 0;
+			skb_shinfo(skb)->gso_segs = 0;
 
 			from += copy;
 			copied += copy;
@@ -937,7 +932,7 @@
  * calculation of whether or not we must ACK for the sake of
  * a window update.
  */
-static void cleanup_rbuf(struct sock *sk, int copied)
+void tcp_cleanup_rbuf(struct sock *sk, int copied)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	int time_to_ack = 0;
@@ -1072,11 +1067,11 @@
 				break;
 		}
 		if (skb->h.th->fin) {
-			sk_eat_skb(sk, skb);
+			sk_eat_skb(sk, skb, 0);
 			++seq;
 			break;
 		}
-		sk_eat_skb(sk, skb);
+		sk_eat_skb(sk, skb, 0);
 		if (!desc->count)
 			break;
 	}
@@ -1086,7 +1081,7 @@
 
 	/* Clean up data we have read: This will do ACK frames. */
 	if (copied)
-		cleanup_rbuf(sk, copied);
+		tcp_cleanup_rbuf(sk, copied);
 	return copied;
 }
 
@@ -1110,6 +1105,7 @@
 	int target;		/* Read at least this many bytes */
 	long timeo;
 	struct task_struct *user_recv = NULL;
+	int copied_early = 0;
 
 	lock_sock(sk);
 
@@ -1133,6 +1129,17 @@
 
 	target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
 
+#ifdef CONFIG_NET_DMA
+	tp->ucopy.dma_chan = NULL;
+	preempt_disable();
+	if ((len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
+	    !sysctl_tcp_low_latency && __get_cpu_var(softnet_data.net_dma)) {
+		preempt_enable_no_resched();
+		tp->ucopy.pinned_list = dma_pin_iovec_pages(msg->msg_iov, len);
+	} else
+		preempt_enable_no_resched();
+#endif
+
 	do {
 		struct sk_buff *skb;
 		u32 offset;
@@ -1220,7 +1227,7 @@
 			}
 		}
 
-		cleanup_rbuf(sk, copied);
+		tcp_cleanup_rbuf(sk, copied);
 
 		if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
 			/* Install new reader */
@@ -1274,6 +1281,10 @@
 		} else
 			sk_wait_data(sk, &timeo);
 
+#ifdef CONFIG_NET_DMA
+		tp->ucopy.wakeup = 0;
+#endif
+
 		if (user_recv) {
 			int chunk;
 
@@ -1329,13 +1340,39 @@
 		}
 
 		if (!(flags & MSG_TRUNC)) {
-			err = skb_copy_datagram_iovec(skb, offset,
-						      msg->msg_iov, used);
-			if (err) {
-				/* Exception. Bailout! */
-				if (!copied)
-					copied = -EFAULT;
-				break;
+#ifdef CONFIG_NET_DMA
+			if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
+				tp->ucopy.dma_chan = get_softnet_dma();
+
+			if (tp->ucopy.dma_chan) {
+				tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec(
+					tp->ucopy.dma_chan, skb, offset,
+					msg->msg_iov, used,
+					tp->ucopy.pinned_list);
+
+				if (tp->ucopy.dma_cookie < 0) {
+
+					printk(KERN_ALERT "dma_cookie < 0\n");
+
+					/* Exception. Bailout! */
+					if (!copied)
+						copied = -EFAULT;
+					break;
+				}
+				if ((offset + used) == skb->len)
+					copied_early = 1;
+
+			} else
+#endif
+			{
+				err = skb_copy_datagram_iovec(skb, offset,
+						msg->msg_iov, used);
+				if (err) {
+					/* Exception. Bailout! */
+					if (!copied)
+						copied = -EFAULT;
+					break;
+				}
 			}
 		}
 
@@ -1355,15 +1392,19 @@
 
 		if (skb->h.th->fin)
 			goto found_fin_ok;
-		if (!(flags & MSG_PEEK))
-			sk_eat_skb(sk, skb);
+		if (!(flags & MSG_PEEK)) {
+			sk_eat_skb(sk, skb, copied_early);
+			copied_early = 0;
+		}
 		continue;
 
 	found_fin_ok:
 		/* Process the FIN. */
 		++*seq;
-		if (!(flags & MSG_PEEK))
-			sk_eat_skb(sk, skb);
+		if (!(flags & MSG_PEEK)) {
+			sk_eat_skb(sk, skb, copied_early);
+			copied_early = 0;
+		}
 		break;
 	} while (len > 0);
 
@@ -1386,12 +1427,42 @@
 		tp->ucopy.len = 0;
 	}
 
+#ifdef CONFIG_NET_DMA
+	if (tp->ucopy.dma_chan) {
+		struct sk_buff *skb;
+		dma_cookie_t done, used;
+
+		dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+
+		while (dma_async_memcpy_complete(tp->ucopy.dma_chan,
+		                                 tp->ucopy.dma_cookie, &done,
+		                                 &used) == DMA_IN_PROGRESS) {
+			/* do partial cleanup of sk_async_wait_queue */
+			while ((skb = skb_peek(&sk->sk_async_wait_queue)) &&
+			       (dma_async_is_complete(skb->dma_cookie, done,
+			                              used) == DMA_SUCCESS)) {
+				__skb_dequeue(&sk->sk_async_wait_queue);
+				kfree_skb(skb);
+			}
+		}
+
+		/* Safe to free early-copied skbs now */
+		__skb_queue_purge(&sk->sk_async_wait_queue);
+		dma_chan_put(tp->ucopy.dma_chan);
+		tp->ucopy.dma_chan = NULL;
+	}
+	if (tp->ucopy.pinned_list) {
+		dma_unpin_iovec_pages(tp->ucopy.pinned_list);
+		tp->ucopy.pinned_list = NULL;
+	}
+#endif
+
 	/* According to UNIX98, msg_name/msg_namelen are ignored
 	 * on connected socket. I was just happy when found this 8) --ANK
 	 */
 
 	/* Clean up data we have read: This will do ACK frames. */
-	cleanup_rbuf(sk, copied);
+	tcp_cleanup_rbuf(sk, copied);
 
 	TCP_CHECK_TIMER(sk);
 	release_sock(sk);
@@ -1658,6 +1729,9 @@
 	__skb_queue_purge(&sk->sk_receive_queue);
 	sk_stream_writequeue_purge(sk);
 	__skb_queue_purge(&tp->out_of_order_queue);
+#ifdef CONFIG_NET_DMA
+	__skb_queue_purge(&sk->sk_async_wait_queue);
+#endif
 
 	inet->dport = 0;
 
@@ -1858,7 +1932,7 @@
 			    (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
 			    inet_csk_ack_scheduled(sk)) {
 				icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
-				cleanup_rbuf(sk, 1);
+				tcp_cleanup_rbuf(sk, 1);
 				if (!(val & 1))
 					icsk->icsk_ack.pingpong = 1;
 			}
@@ -2071,6 +2145,67 @@
 EXPORT_SYMBOL(compat_tcp_getsockopt);
 #endif
 
+struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
+{
+	struct sk_buff *segs = ERR_PTR(-EINVAL);
+	struct tcphdr *th;
+	unsigned thlen;
+	unsigned int seq;
+	unsigned int delta;
+	unsigned int oldlen;
+	unsigned int len;
+
+	if (!pskb_may_pull(skb, sizeof(*th)))
+		goto out;
+
+	th = skb->h.th;
+	thlen = th->doff * 4;
+	if (thlen < sizeof(*th))
+		goto out;
+
+	if (!pskb_may_pull(skb, thlen))
+		goto out;
+
+	oldlen = (u16)~skb->len;
+	__skb_pull(skb, thlen);
+
+	segs = skb_segment(skb, sg);
+	if (IS_ERR(segs))
+		goto out;
+
+	len = skb_shinfo(skb)->gso_size;
+	delta = htonl(oldlen + (thlen + len));
+
+	skb = segs;
+	th = skb->h.th;
+	seq = ntohl(th->seq);
+
+	do {
+		th->fin = th->psh = 0;
+
+		th->check = ~csum_fold(th->check + delta);
+		if (skb->ip_summed != CHECKSUM_HW)
+			th->check = csum_fold(csum_partial(skb->h.raw, thlen,
+							   skb->csum));
+
+		seq += len;
+		skb = skb->next;
+		th = skb->h.th;
+
+		th->seq = htonl(seq);
+		th->cwr = 0;
+	} while (skb->next);
+
+	delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
+	th->check = ~csum_fold(th->check + delta);
+	if (skb->ip_summed != CHECKSUM_HW)
+		th->check = csum_fold(csum_partial(skb->h.raw, thlen,
+						   skb->csum));
+
+out:
+	return segs;
+}
+
 extern void __skb_cb_too_small_for_tcp(int, int);
 extern struct tcp_congestion_ops tcp_reno;
 
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index 035f209..b2d9021 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -198,12 +198,6 @@
 	return max(tp->snd_cwnd, ca->last_max_cwnd);
 }
 
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	return tp->snd_ssthresh;
-}
-
 static void bictcp_state(struct sock *sk, u8 new_state)
 {
 	if (new_state == TCP_CA_Loss)
@@ -231,7 +225,6 @@
 	.cong_avoid	= bictcp_cong_avoid,
 	.set_state	= bictcp_state,
 	.undo_cwnd	= bictcp_undo_cwnd,
-	.min_cwnd	= bictcp_min_cwnd,
 	.pkts_acked     = bictcp_acked,
 	.owner		= THIS_MODULE,
 	.name		= "bic",
diff --git a/net/ipv4/tcp_compound.c b/net/ipv4/tcp_compound.c
new file mode 100644
index 0000000..bc54f7e
--- /dev/null
+++ b/net/ipv4/tcp_compound.c
@@ -0,0 +1,448 @@
+/*
+ * TCP Vegas congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ *    Lawrence S. Brakmo and Larry L. Peterson.
+ *    "TCP Vegas: End to end congestion avoidance on a global internet."
+ *    IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
+ *    October 1995. Available from:
+ *	ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
+ *
+ * See http://www.cs.arizona.edu/xkernel/ for their implementation.
+ * The main aspects that distinguish this implementation from the
+ * Arizona Vegas implementation are:
+ *   o We do not change the loss detection or recovery mechanisms of
+ *     Linux in any way. Linux already recovers from losses quite well,
+ *     using fine-grained timers, NewReno, and FACK.
+ *   o To avoid the performance penalty imposed by increasing cwnd
+ *     only every-other RTT during slow start, we increase during
+ *     every RTT during slow start, just like Reno.
+ *   o Largely to allow continuous cwnd growth during slow start,
+ *     we use the rate at which ACKs come back as the "actual"
+ *     rate, rather than the rate at which data is sent.
+ *   o To speed convergence to the right rate, we set the cwnd
+ *     to achieve the right ("actual") rate when we exit slow start.
+ *   o To filter out the noise caused by delayed ACKs, we use the
+ *     minimum RTT sample observed during the last RTT to calculate
+ *     the actual rate.
+ *   o When the sender re-starts from idle, it waits until it has
+ *     received ACKs for an entire flight of new data before making
+ *     a cwnd adjustment decision. The original Vegas implementation
+ *     assumed senders never went idle.
+ *
+ *
+ *   TCP Compound based on TCP Vegas
+ *
+ *   further details can be found here:
+ *      ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Vegas variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+
+#define TCP_COMPOUND_ALPHA          3U
+#define TCP_COMPOUND_BETA           1U
+#define TCP_COMPOUND_GAMMA         30
+#define TCP_COMPOUND_ZETA           1
+
+/* TCP compound variables */
+struct compound {
+	u32 beg_snd_nxt;	/* right edge during last RTT */
+	u32 beg_snd_una;	/* left edge  during last RTT */
+	u32 beg_snd_cwnd;	/* saves the size of the cwnd */
+	u8 doing_vegas_now;	/* if true, do vegas for this RTT */
+	u16 cntRTT;		/* # of RTTs measured within last RTT */
+	u32 minRTT;		/* min of RTTs measured within last RTT (in usec) */
+	u32 baseRTT;		/* the min of all Vegas RTT measurements seen (in usec) */
+
+	u32 cwnd;
+	u32 dwnd;
+};
+
+/* There are several situations when we must "re-start" Vegas:
+ *
+ *  o when a connection is established
+ *  o after an RTO
+ *  o after fast recovery
+ *  o when we send a packet and there is no outstanding
+ *    unacknowledged data (restarting an idle connection)
+ *
+ * In these circumstances we cannot do a Vegas calculation at the
+ * end of the first RTT, because any calculation we do is using
+ * stale info -- both the saved cwnd and congestion feedback are
+ * stale.
+ *
+ * Instead we must wait until the completion of an RTT during
+ * which we actually receive ACKs.
+ */
+static inline void vegas_enable(struct sock *sk)
+{
+	const struct tcp_sock *tp = tcp_sk(sk);
+	struct compound *vegas = inet_csk_ca(sk);
+
+	/* Begin taking Vegas samples next time we send something. */
+	vegas->doing_vegas_now = 1;
+
+	/* Set the beginning of the next send window. */
+	vegas->beg_snd_nxt = tp->snd_nxt;
+
+	vegas->cntRTT = 0;
+	vegas->minRTT = 0x7fffffff;
+}
+
+/* Stop taking Vegas samples for now. */
+static inline void vegas_disable(struct sock *sk)
+{
+	struct compound *vegas = inet_csk_ca(sk);
+
+	vegas->doing_vegas_now = 0;
+}
+
+static void tcp_compound_init(struct sock *sk)
+{
+	struct compound *vegas = inet_csk_ca(sk);
+	const struct tcp_sock *tp = tcp_sk(sk);
+
+	vegas->baseRTT = 0x7fffffff;
+	vegas_enable(sk);
+
+	vegas->dwnd = 0;
+	vegas->cwnd = tp->snd_cwnd;
+}
+
+/* Do RTT sampling needed for Vegas.
+ * Basically we:
+ *   o min-filter RTT samples from within an RTT to get the current
+ *     propagation delay + queuing delay (we are min-filtering to try to
+ *     avoid the effects of delayed ACKs)
+ *   o min-filter RTT samples from a much longer window (forever for now)
+ *     to find the propagation delay (baseRTT)
+ */
+static void tcp_compound_rtt_calc(struct sock *sk, u32 usrtt)
+{
+	struct compound *vegas = inet_csk_ca(sk);
+	u32 vrtt = usrtt + 1;	/* Never allow zero rtt or baseRTT */
+
+	/* Filter to find propagation delay: */
+	if (vrtt < vegas->baseRTT)
+		vegas->baseRTT = vrtt;
+
+	/* Find the min RTT during the last RTT to find
+	 * the current prop. delay + queuing delay:
+	 */
+
+	vegas->minRTT = min(vegas->minRTT, vrtt);
+	vegas->cntRTT++;
+}
+
+static void tcp_compound_state(struct sock *sk, u8 ca_state)
+{
+
+	if (ca_state == TCP_CA_Open)
+		vegas_enable(sk);
+	else
+		vegas_disable(sk);
+}
+
+
+/* 64bit divisor, dividend and result. dynamic precision */
+static inline u64 div64_64(u64 dividend, u64 divisor)
+{
+	u32 d = divisor;
+
+	if (divisor > 0xffffffffULL) {
+		unsigned int shift = fls(divisor >> 32);
+
+		d = divisor >> shift;
+		dividend >>= shift;
+	}
+
+	/* avoid 64 bit division if possible */
+	if (dividend >> 32)
+		do_div(dividend, d);
+	else
+		dividend = (u32) dividend / d;
+
+	return dividend;
+}
+
+/* calculate the quartic root of "a" using Newton-Raphson */
+static u32 qroot(u64 a)
+{
+	u32 x, x1;
+
+	/* Initial estimate is based on:
+	 * qrt(x) = exp(log(x) / 4)
+	 */
+	x = 1u << (fls64(a) >> 2);
+
+	/*
+	 * Iteration based on:
+	 *                         3
+	 * x    = ( 3 * x  +  a / x  ) / 4
+	 *  k+1          k         k
+	 */
+	do {
+		u64 x3 = x;
+
+		x1 = x;
+		x3 *= x;
+		x3 *= x;
+
+		x = (3 * x + (u32) div64_64(a, x3)) / 4;
+	} while (abs(x1 - x) > 1);
+
+	return x;
+}
+
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Vegas calculations
+ * until we get fresh RTT samples.  So when we
+ * restart, we reset our Vegas state to a clean
+ * slate. After we get acks for this flight of
+ * packets, _then_ we can make Vegas calculations
+ * again.
+ */
+static void tcp_compound_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+	if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
+		tcp_compound_init(sk);
+}
+
+static void tcp_compound_cong_avoid(struct sock *sk, u32 ack,
+				    u32 seq_rtt, u32 in_flight, int flag)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct compound *vegas = inet_csk_ca(sk);
+	u8 inc = 0;
+
+	if (vegas->cwnd + vegas->dwnd > tp->snd_cwnd) {
+		if (vegas->cwnd > tp->snd_cwnd || vegas->dwnd > tp->snd_cwnd) {
+			vegas->cwnd = tp->snd_cwnd;
+			vegas->dwnd = 0;
+		} else
+			vegas->cwnd = tp->snd_cwnd - vegas->dwnd;
+
+	}
+
+	if (!tcp_is_cwnd_limited(sk, in_flight))
+		return;
+
+	if (vegas->cwnd <= tp->snd_ssthresh)
+		inc = 1;
+	else if (tp->snd_cwnd_cnt < tp->snd_cwnd)
+		tp->snd_cwnd_cnt++;
+
+	if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+		inc = 1;
+		tp->snd_cwnd_cnt = 0;
+	}
+
+	if (inc && tp->snd_cwnd < tp->snd_cwnd_clamp)
+		vegas->cwnd++;
+
+	/* The key players are v_beg_snd_una and v_beg_snd_nxt.
+	 *
+	 * These are so named because they represent the approximate values
+	 * of snd_una and snd_nxt at the beginning of the current RTT. More
+	 * precisely, they represent the amount of data sent during the RTT.
+	 * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
+	 * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
+	 * bytes of data have been ACKed during the course of the RTT, giving
+	 * an "actual" rate of:
+	 *
+	 *     (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
+	 *
+	 * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
+	 * because delayed ACKs can cover more than one segment, so they
+	 * don't line up nicely with the boundaries of RTTs.
+	 *
+	 * Another unfortunate fact of life is that delayed ACKs delay the
+	 * advance of the left edge of our send window, so that the number
+	 * of bytes we send in an RTT is often less than our cwnd will allow.
+	 * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
+	 */
+
+	if (after(ack, vegas->beg_snd_nxt)) {
+		/* Do the Vegas once-per-RTT cwnd adjustment. */
+		u32 old_wnd, old_snd_cwnd;
+
+		/* Here old_wnd is essentially the window of data that was
+		 * sent during the previous RTT, and has all
+		 * been acknowledged in the course of the RTT that ended
+		 * with the ACK we just received. Likewise, old_snd_cwnd
+		 * is the cwnd during the previous RTT.
+		 */
+		if (!tp->mss_cache)
+			return;
+
+		old_wnd = (vegas->beg_snd_nxt - vegas->beg_snd_una) /
+		    tp->mss_cache;
+		old_snd_cwnd = vegas->beg_snd_cwnd;
+
+		/* Save the extent of the current window so we can use this
+		 * at the end of the next RTT.
+		 */
+		vegas->beg_snd_una = vegas->beg_snd_nxt;
+		vegas->beg_snd_nxt = tp->snd_nxt;
+		vegas->beg_snd_cwnd = tp->snd_cwnd;
+
+		/* We do the Vegas calculations only if we got enough RTT
+		 * samples that we can be reasonably sure that we got
+		 * at least one RTT sample that wasn't from a delayed ACK.
+		 * If we only had 2 samples total,
+		 * then that means we're getting only 1 ACK per RTT, which
+		 * means they're almost certainly delayed ACKs.
+		 * If  we have 3 samples, we should be OK.
+		 */
+
+		if (vegas->cntRTT > 2) {
+			u32 rtt, target_cwnd, diff;
+			u32 brtt, dwnd;
+
+			/* We have enough RTT samples, so, using the Vegas
+			 * algorithm, we determine if we should increase or
+			 * decrease cwnd, and by how much.
+			 */
+
+			/* Pluck out the RTT we are using for the Vegas
+			 * calculations. This is the min RTT seen during the
+			 * last RTT. Taking the min filters out the effects
+			 * of delayed ACKs, at the cost of noticing congestion
+			 * a bit later.
+			 */
+			rtt = vegas->minRTT;
+
+			/* Calculate the cwnd we should have, if we weren't
+			 * going too fast.
+			 *
+			 * This is:
+			 *     (actual rate in segments) * baseRTT
+			 * We keep it as a fixed point number with
+			 * V_PARAM_SHIFT bits to the right of the binary point.
+			 */
+			if (!rtt)
+				return;
+
+			brtt = vegas->baseRTT;
+			target_cwnd = ((old_wnd * brtt)
+				       << V_PARAM_SHIFT) / rtt;
+
+			/* Calculate the difference between the window we had,
+			 * and the window we would like to have. This quantity
+			 * is the "Diff" from the Arizona Vegas papers.
+			 *
+			 * Again, this is a fixed point number with
+			 * V_PARAM_SHIFT bits to the right of the binary
+			 * point.
+			 */
+
+			diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
+
+			dwnd = vegas->dwnd;
+
+			if (diff < (TCP_COMPOUND_GAMMA << V_PARAM_SHIFT)) {
+				u64 v;
+				u32 x;
+
+				/*
+				 * The TCP Compound paper describes the choice
+				 * of "k" determines the agressiveness,
+				 * ie. slope of the response function.
+				 *
+				 * For same value as HSTCP would be 0.8
+				 * but for computaional reasons, both the
+				 * original authors and this implementation
+				 * use 0.75.
+				 */
+				v = old_wnd;
+				x = qroot(v * v * v) >> TCP_COMPOUND_ALPHA;
+				if (x > 1)
+					dwnd = x - 1;
+				else
+					dwnd = 0;
+
+				dwnd += vegas->dwnd;
+
+			} else if ((dwnd << V_PARAM_SHIFT) <
+				   (diff * TCP_COMPOUND_BETA))
+				dwnd = 0;
+			else
+				dwnd =
+				    ((dwnd << V_PARAM_SHIFT) -
+				     (diff *
+				      TCP_COMPOUND_BETA)) >> V_PARAM_SHIFT;
+
+			vegas->dwnd = dwnd;
+
+		}
+
+		/* Wipe the slate clean for the next RTT. */
+		vegas->cntRTT = 0;
+		vegas->minRTT = 0x7fffffff;
+	}
+
+	tp->snd_cwnd = vegas->cwnd + vegas->dwnd;
+}
+
+/* Extract info for Tcp socket info provided via netlink. */
+static void tcp_compound_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
+{
+	const struct compound *ca = inet_csk_ca(sk);
+	if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
+		struct tcpvegas_info *info;
+
+		info = RTA_DATA(__RTA_PUT(skb, INET_DIAG_VEGASINFO,
+					  sizeof(*info)));
+
+		info->tcpv_enabled = ca->doing_vegas_now;
+		info->tcpv_rttcnt = ca->cntRTT;
+		info->tcpv_rtt = ca->baseRTT;
+		info->tcpv_minrtt = ca->minRTT;
+	rtattr_failure:;
+	}
+}
+
+static struct tcp_congestion_ops tcp_compound = {
+	.init		= tcp_compound_init,
+	.ssthresh	= tcp_reno_ssthresh,
+	.cong_avoid	= tcp_compound_cong_avoid,
+	.rtt_sample	= tcp_compound_rtt_calc,
+	.set_state	= tcp_compound_state,
+	.cwnd_event	= tcp_compound_cwnd_event,
+	.get_info	= tcp_compound_get_info,
+
+	.owner		= THIS_MODULE,
+	.name		= "compound",
+};
+
+static int __init tcp_compound_register(void)
+{
+	BUG_ON(sizeof(struct compound) > ICSK_CA_PRIV_SIZE);
+	tcp_register_congestion_control(&tcp_compound);
+	return 0;
+}
+
+static void __exit tcp_compound_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_compound);
+}
+
+module_init(tcp_compound_register);
+module_exit(tcp_compound_unregister);
+
+MODULE_AUTHOR("Angelo P. Castellani, Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Compound");
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index 91c2f41..857eefc 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -38,7 +38,7 @@
 	int ret = 0;
 
 	/* all algorithms must implement ssthresh and cong_avoid ops */
-	if (!ca->ssthresh || !ca->cong_avoid || !ca->min_cwnd) {
+	if (!ca->ssthresh || !ca->cong_avoid) {
 		printk(KERN_ERR "TCP %s does not implement required ops\n",
 		       ca->name);
 		return -EINVAL;
@@ -251,8 +251,8 @@
 }
 EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
 
-/* Lower bound on congestion window. */
-u32 tcp_reno_min_cwnd(struct sock *sk)
+/* Lower bound on congestion window with halving. */
+u32 tcp_reno_min_cwnd(const struct sock *sk)
 {
 	const struct tcp_sock *tp = tcp_sk(sk);
 	return tp->snd_ssthresh/2;
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c
index 31a4986..78b7a6b 100644
--- a/net/ipv4/tcp_cubic.c
+++ b/net/ipv4/tcp_cubic.c
@@ -325,11 +325,6 @@
 	return max(tcp_sk(sk)->snd_cwnd, ca->last_max_cwnd);
 }
 
-static u32 bictcp_min_cwnd(struct sock *sk)
-{
-	return tcp_sk(sk)->snd_ssthresh;
-}
-
 static void bictcp_state(struct sock *sk, u8 new_state)
 {
 	if (new_state == TCP_CA_Loss)
@@ -357,7 +352,6 @@
 	.cong_avoid	= bictcp_cong_avoid,
 	.set_state	= bictcp_state,
 	.undo_cwnd	= bictcp_undo_cwnd,
-	.min_cwnd	= bictcp_min_cwnd,
 	.pkts_acked     = bictcp_acked,
 	.owner		= THIS_MODULE,
 	.name		= "cubic",
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index ba7c63c..1120245 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -98,6 +98,10 @@
 	u32	ai;
 };
 
+static int max_ssthresh = 100;
+module_param(max_ssthresh, int, 0644);
+MODULE_PARM_DESC(max_ssthresh, "limited slow start threshold (RFC3742)");
+
 static void hstcp_init(struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -119,9 +123,23 @@
 	if (!tcp_is_cwnd_limited(sk, in_flight))
 		return;
 
-	if (tp->snd_cwnd <= tp->snd_ssthresh)
-		tcp_slow_start(tp);
-	else {
+	if (tp->snd_cwnd <= tp->snd_ssthresh) {
+		/* RFC3742: limited slow start
+		 * the window is increased by 1/K MSS for each arriving ACK,
+		 * for K = int(cwnd/(0.5 max_ssthresh))
+		 */
+		if (max_ssthresh > 0 && tp->snd_cwnd > max_ssthresh) {
+			u32 k = max(tp->snd_cwnd / (max_ssthresh >> 1), 1U);
+			if (++tp->snd_cwnd_cnt >= k) {
+				if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+					tp->snd_cwnd++;
+				tp->snd_cwnd_cnt = 0;
+			}
+		} else {
+			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+				tp->snd_cwnd++;
+		}
+	} else {
 		/* Update AIMD parameters */
 		if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
 			while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index 1b2ff53..3d92c18 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -246,14 +246,6 @@
 	}
 }
 
-/* Lower bound on congestion window. */
-static u32 htcp_min_cwnd(struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	return tp->snd_ssthresh;
-}
-
-
 static void htcp_init(struct sock *sk)
 {
 	struct htcp *ca = inet_csk_ca(sk);
@@ -285,7 +277,6 @@
 static struct tcp_congestion_ops htcp = {
 	.init		= htcp_init,
 	.ssthresh	= htcp_recalc_ssthresh,
-	.min_cwnd	= htcp_min_cwnd,
 	.cong_avoid	= htcp_cong_avoid,
 	.set_state	= htcp_state,
 	.undo_cwnd	= htcp_cwnd_undo,
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b5521a9..94fe5b1 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -71,6 +71,7 @@
 #include <net/inet_common.h>
 #include <linux/ipsec.h>
 #include <asm/unaligned.h>
+#include <net/netdma.h>
 
 int sysctl_tcp_timestamps = 1;
 int sysctl_tcp_window_scaling = 1;
@@ -1072,7 +1073,7 @@
 				else
 					pkt_len = (end_seq -
 						   TCP_SKB_CB(skb)->seq);
-				if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->tso_size))
+				if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size))
 					break;
 				pcount = tcp_skb_pcount(skb);
 			}
@@ -1688,17 +1689,26 @@
 	tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
+/* Lower bound on congestion window is slow start threshold
+ * unless congestion avoidance choice decides to overide it.
+ */
+static inline u32 tcp_cwnd_min(const struct sock *sk)
+{
+	const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
+
+	return ca_ops->min_cwnd ? ca_ops->min_cwnd(sk) : tcp_sk(sk)->snd_ssthresh;
+}
+
 /* Decrease cwnd each second ack. */
 static void tcp_cwnd_down(struct sock *sk)
 {
-	const struct inet_connection_sock *icsk = inet_csk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
 	int decr = tp->snd_cwnd_cnt + 1;
 
 	tp->snd_cwnd_cnt = decr&1;
 	decr >>= 1;
 
-	if (decr && tp->snd_cwnd > icsk->icsk_ca_ops->min_cwnd(sk))
+	if (decr && tp->snd_cwnd > tcp_cwnd_min(sk))
 		tp->snd_cwnd -= decr;
 
 	tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
@@ -3785,6 +3795,50 @@
 		__tcp_checksum_complete_user(sk, skb);
 }
 
+#ifdef CONFIG_NET_DMA
+static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, int hlen)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	int chunk = skb->len - hlen;
+	int dma_cookie;
+	int copied_early = 0;
+
+	if (tp->ucopy.wakeup)
+          	return 0;
+
+	if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
+		tp->ucopy.dma_chan = get_softnet_dma();
+
+	if (tp->ucopy.dma_chan && skb->ip_summed == CHECKSUM_UNNECESSARY) {
+
+		dma_cookie = dma_skb_copy_datagram_iovec(tp->ucopy.dma_chan,
+			skb, hlen, tp->ucopy.iov, chunk, tp->ucopy.pinned_list);
+
+		if (dma_cookie < 0)
+			goto out;
+
+		tp->ucopy.dma_cookie = dma_cookie;
+		copied_early = 1;
+
+		tp->ucopy.len -= chunk;
+		tp->copied_seq += chunk;
+		tcp_rcv_space_adjust(sk);
+
+		if ((tp->ucopy.len == 0) ||
+		    (tcp_flag_word(skb->h.th) & TCP_FLAG_PSH) ||
+		    (atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1))) {
+			tp->ucopy.wakeup = 1;
+			sk->sk_data_ready(sk, 0);
+		}
+	} else if (chunk > 0) {
+		tp->ucopy.wakeup = 1;
+		sk->sk_data_ready(sk, 0);
+	}
+out:
+	return copied_early;
+}
+#endif /* CONFIG_NET_DMA */
+
 /*
  *	TCP receive function for the ESTABLISHED state. 
  *
@@ -3886,8 +3940,6 @@
 				    tp->rcv_nxt == tp->rcv_wup)
 					tcp_store_ts_recent(tp);
 
-				tcp_rcv_rtt_measure_ts(sk, skb);
-
 				/* We know that such packets are checksummed
 				 * on entry.
 				 */
@@ -3901,14 +3953,23 @@
 			}
 		} else {
 			int eaten = 0;
+			int copied_early = 0;
 
-			if (tp->ucopy.task == current &&
-			    tp->copied_seq == tp->rcv_nxt &&
-			    len - tcp_header_len <= tp->ucopy.len &&
-			    sock_owned_by_user(sk)) {
-				__set_current_state(TASK_RUNNING);
+			if (tp->copied_seq == tp->rcv_nxt &&
+			    len - tcp_header_len <= tp->ucopy.len) {
+#ifdef CONFIG_NET_DMA
+				if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {
+					copied_early = 1;
+					eaten = 1;
+				}
+#endif
+				if (tp->ucopy.task == current && sock_owned_by_user(sk) && !copied_early) {
+					__set_current_state(TASK_RUNNING);
 
-				if (!tcp_copy_to_iovec(sk, skb, tcp_header_len)) {
+					if (!tcp_copy_to_iovec(sk, skb, tcp_header_len))
+						eaten = 1;
+				}
+				if (eaten) {
 					/* Predicted packet is in window by definition.
 					 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
 					 * Hence, check seq<=rcv_wup reduces to:
@@ -3924,8 +3985,9 @@
 					__skb_pull(skb, tcp_header_len);
 					tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
 					NET_INC_STATS_BH(LINUX_MIB_TCPHPHITSTOUSER);
-					eaten = 1;
 				}
+				if (copied_early)
+					tcp_cleanup_rbuf(sk, skb->len);
 			}
 			if (!eaten) {
 				if (tcp_checksum_complete_user(sk, skb))
@@ -3966,6 +4028,11 @@
 
 			__tcp_ack_snd_check(sk, 0);
 no_ack:
+#ifdef CONFIG_NET_DMA
+			if (copied_early)
+				__skb_queue_tail(&sk->sk_async_wait_queue, skb);
+			else
+#endif
 			if (eaten)
 				__kfree_skb(skb);
 			else
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 672950e..25ecc6e 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -71,6 +71,7 @@
 #include <net/inet_common.h>
 #include <net/timewait_sock.h>
 #include <net/xfrm.h>
+#include <net/netdma.h>
 
 #include <linux/inet.h>
 #include <linux/ipv6.h>
@@ -1091,8 +1092,18 @@
 	bh_lock_sock(sk);
 	ret = 0;
 	if (!sock_owned_by_user(sk)) {
-		if (!tcp_prequeue(sk, skb))
+#ifdef CONFIG_NET_DMA
+		struct tcp_sock *tp = tcp_sk(sk);
+		if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
+			tp->ucopy.dma_chan = get_softnet_dma();
+		if (tp->ucopy.dma_chan)
 			ret = tcp_v4_do_rcv(sk, skb);
+		else
+#endif
+		{
+			if (!tcp_prequeue(sk, skb))
+			ret = tcp_v4_do_rcv(sk, skb);
+		}
 	} else
 		sk_add_backlog(sk, skb);
 	bh_unlock_sock(sk);
@@ -1296,6 +1307,11 @@
 	/* Cleans up our, hopefully empty, out_of_order_queue. */
   	__skb_queue_purge(&tp->out_of_order_queue);
 
+#ifdef CONFIG_NET_DMA
+	/* Cleans up our sk_async_wait_queue */
+  	__skb_queue_purge(&sk->sk_async_wait_queue);
+#endif
+
 	/* Clean prequeue, it must be empty really */
 	__skb_queue_purge(&tp->ucopy.prequeue);
 
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
new file mode 100644
index 0000000..1f977b6
--- /dev/null
+++ b/net/ipv4/tcp_lp.c
@@ -0,0 +1,338 @@
+/*
+ * TCP Low Priority (TCP-LP)
+ *
+ * TCP Low Priority is a distributed algorithm whose goal is to utilize only
+ *   the excess network bandwidth as compared to the ``fair share`` of
+ *   bandwidth as targeted by TCP. Available from:
+ *     http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf
+ *
+ * Original Author:
+ *   Aleksandar Kuzmanovic <akuzma@northwestern.edu>
+ *
+ * See http://www-ece.rice.edu/networks/TCP-LP/ for their implementation.
+ * As of 2.6.13, Linux supports pluggable congestion control algorithms.
+ * Due to the limitation of the API, we take the following changes from
+ * the original TCP-LP implementation:
+ *   o We use newReno in most core CA handling. Only add some checking
+ *     within cong_avoid.
+ *   o Error correcting in remote HZ, therefore remote HZ will be keeped
+ *     on checking and updating.
+ *   o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne
+ *     OWD have a similar meaning as RTT. Also correct the buggy formular.
+ *   o Handle reaction for Early Congestion Indication (ECI) within
+ *     pkts_acked, as mentioned within pseudo code.
+ *   o OWD is handled in relative format, where local time stamp will in
+ *     tcp_time_stamp format.
+ *
+ * Port from 2.4.19 to 2.6.16 as module by:
+ *   Wong Hoi Sing Edison <hswong3i@gmail.com>
+ *   Hung Hing Lun <hlhung3i@gmail.com>
+ *
+ * Version: $Id: tcp_lp.c,v 1.22 2006-05-02 18:18:19 hswong3i Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* resolution of owd */
+#define LP_RESOL       1000
+
+/**
+ * enum tcp_lp_state
+ * @LP_VALID_RHZ: is remote HZ valid?
+ * @LP_VALID_OWD: is OWD valid?
+ * @LP_WITHIN_THR: are we within threshold?
+ * @LP_WITHIN_INF: are we within inference?
+ *
+ * TCP-LP's state flags.
+ * We create this set of state flag mainly for debugging.
+ */
+enum tcp_lp_state {
+	LP_VALID_RHZ = (1 << 0),
+	LP_VALID_OWD = (1 << 1),
+	LP_WITHIN_THR = (1 << 3),
+	LP_WITHIN_INF = (1 << 4),
+};
+
+/**
+ * struct lp
+ * @flag: TCP-LP state flag
+ * @sowd: smoothed OWD << 3
+ * @owd_min: min OWD
+ * @owd_max: max OWD
+ * @owd_max_rsv: resrved max owd
+ * @remote_hz: estimated remote HZ
+ * @remote_ref_time: remote reference time
+ * @local_ref_time: local reference time
+ * @last_drop: time for last active drop
+ * @inference: current inference
+ *
+ * TCP-LP's private struct.
+ * We get the idea from original TCP-LP implementation where only left those we
+ * found are really useful.
+ */
+struct lp {
+	u32 flag;
+	u32 sowd;
+	u32 owd_min;
+	u32 owd_max;
+	u32 owd_max_rsv;
+	u32 remote_hz;
+	u32 remote_ref_time;
+	u32 local_ref_time;
+	u32 last_drop;
+	u32 inference;
+};
+
+/**
+ * tcp_lp_init
+ *
+ * Init all required variables.
+ * Clone the handling from Vegas module implementation.
+ */
+static void tcp_lp_init(struct sock *sk)
+{
+	struct lp *lp = inet_csk_ca(sk);
+
+	lp->flag = 0;
+	lp->sowd = 0;
+	lp->owd_min = 0xffffffff;
+	lp->owd_max = 0;
+	lp->owd_max_rsv = 0;
+	lp->remote_hz = 0;
+	lp->remote_ref_time = 0;
+	lp->local_ref_time = 0;
+	lp->last_drop = 0;
+	lp->inference = 0;
+}
+
+/**
+ * tcp_lp_cong_avoid
+ *
+ * Implementation of cong_avoid.
+ * Will only call newReno CA when away from inference.
+ * From TCP-LP's paper, this will be handled in additive increasement.
+ */
+static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
+			      int flag)
+{
+	struct lp *lp = inet_csk_ca(sk);
+
+	if (!(lp->flag & LP_WITHIN_INF))
+		tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag);
+}
+
+/**
+ * tcp_lp_remote_hz_estimator
+ *
+ * Estimate remote HZ.
+ * We keep on updating the estimated value, where original TCP-LP
+ * implementation only guest it for once and use forever.
+ */
+static u32 tcp_lp_remote_hz_estimator(struct sock *sk)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct lp *lp = inet_csk_ca(sk);
+	s64 rhz = lp->remote_hz << 6;	/* remote HZ << 6 */
+	s64 m = 0;
+
+	/* not yet record reference time
+	 * go away!! record it before come back!! */
+	if (lp->remote_ref_time == 0 || lp->local_ref_time == 0)
+		goto out;
+
+	/* we can't calc remote HZ with no different!! */
+	if (tp->rx_opt.rcv_tsval == lp->remote_ref_time
+	    || tp->rx_opt.rcv_tsecr == lp->local_ref_time)
+		goto out;
+
+	m = HZ * (tp->rx_opt.rcv_tsval -
+		  lp->remote_ref_time) / (tp->rx_opt.rcv_tsecr -
+					  lp->local_ref_time);
+	if (m < 0)
+		m = -m;
+
+	if (rhz != 0) {
+		m -= rhz >> 6;	/* m is now error in remote HZ est */
+		rhz += m;	/* 63/64 old + 1/64 new */
+	} else
+		rhz = m << 6;
+
+	/* record time for successful remote HZ calc */
+	lp->flag |= LP_VALID_RHZ;
+
+ out:
+	/* record reference time stamp */
+	lp->remote_ref_time = tp->rx_opt.rcv_tsval;
+	lp->local_ref_time = tp->rx_opt.rcv_tsecr;
+
+	return rhz >> 6;
+}
+
+/**
+ * tcp_lp_owd_calculator
+ *
+ * Calculate one way delay (in relative format).
+ * Original implement OWD as minus of remote time difference to local time
+ * difference directly. As this time difference just simply equal to RTT, when
+ * the network status is stable, remote RTT will equal to local RTT, and result
+ * OWD into zero.
+ * It seems to be a bug and so we fixed it.
+ */
+static u32 tcp_lp_owd_calculator(struct sock *sk)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct lp *lp = inet_csk_ca(sk);
+	s64 owd = 0;
+
+	lp->remote_hz = tcp_lp_remote_hz_estimator(sk);
+
+	if (lp->flag & LP_VALID_RHZ) {
+		owd =
+		    tp->rx_opt.rcv_tsval * (LP_RESOL / lp->remote_hz) -
+		    tp->rx_opt.rcv_tsecr * (LP_RESOL / HZ);
+		if (owd < 0)
+			owd = -owd;
+	}
+
+	if (owd > 0)
+		lp->flag |= LP_VALID_OWD;
+	else
+		lp->flag &= ~LP_VALID_OWD;
+
+	return owd;
+}
+
+/**
+ * tcp_lp_rtt_sample
+ *
+ * Implementation or rtt_sample.
+ * Will take the following action,
+ *   1. calc OWD,
+ *   2. record the min/max OWD,
+ *   3. calc smoothed OWD (SOWD).
+ * Most ideas come from the original TCP-LP implementation.
+ */
+static void tcp_lp_rtt_sample(struct sock *sk, u32 usrtt)
+{
+	struct lp *lp = inet_csk_ca(sk);
+	s64 mowd = tcp_lp_owd_calculator(sk);
+
+	/* sorry that we don't have valid data */
+	if (!(lp->flag & LP_VALID_RHZ) || !(lp->flag & LP_VALID_OWD))
+		return;
+
+	/* record the next min owd */
+	if (mowd < lp->owd_min)
+		lp->owd_min = mowd;
+
+	/* always forget the max of the max
+	 * we just set owd_max as one below it */
+	if (mowd > lp->owd_max) {
+		if (mowd > lp->owd_max_rsv) {
+			if (lp->owd_max_rsv == 0)
+				lp->owd_max = mowd;
+			else
+				lp->owd_max = lp->owd_max_rsv;
+			lp->owd_max_rsv = mowd;
+		} else
+			lp->owd_max = mowd;
+	}
+
+	/* calc for smoothed owd */
+	if (lp->sowd != 0) {
+		mowd -= lp->sowd >> 3;	/* m is now error in owd est */
+		lp->sowd += mowd;	/* owd = 7/8 owd + 1/8 new */
+	} else
+		lp->sowd = mowd << 3;	/* take the measured time be owd */
+}
+
+/**
+ * tcp_lp_pkts_acked
+ *
+ * Implementation of pkts_acked.
+ * Deal with active drop under Early Congestion Indication.
+ * Only drop to half and 1 will be handle, because we hope to use back
+ * newReno in increase case.
+ * We work it out by following the idea from TCP-LP's paper directly
+ */
+static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct lp *lp = inet_csk_ca(sk);
+
+	/* calc inference */
+	if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
+		lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr);
+
+	/* test if within inference */
+	if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference))
+		lp->flag |= LP_WITHIN_INF;
+	else
+		lp->flag &= ~LP_WITHIN_INF;
+
+	/* test if within threshold */
+	if (lp->sowd >> 3 <
+	    lp->owd_min + 15 * (lp->owd_max - lp->owd_min) / 100)
+		lp->flag |= LP_WITHIN_THR;
+	else
+		lp->flag &= ~LP_WITHIN_THR;
+
+	pr_debug("TCP-LP: %05o|%5u|%5u|%15u|%15u|%15u\n", lp->flag,
+		 tp->snd_cwnd, lp->remote_hz, lp->owd_min, lp->owd_max,
+		 lp->sowd >> 3);
+
+	if (lp->flag & LP_WITHIN_THR)
+		return;
+
+	/* FIXME: try to reset owd_min and owd_max here
+	 * so decrease the chance the min/max is no longer suitable
+	 * and will usually within threshold when whithin inference */
+	lp->owd_min = lp->sowd >> 3;
+	lp->owd_max = lp->sowd >> 2;
+	lp->owd_max_rsv = lp->sowd >> 2;
+
+	/* happened within inference
+	 * drop snd_cwnd into 1 */
+	if (lp->flag & LP_WITHIN_INF)
+		tp->snd_cwnd = 1U;
+
+	/* happened after inference
+	 * cut snd_cwnd into half */
+	else
+		tp->snd_cwnd = max(tp->snd_cwnd >> 1U, 1U);
+
+	/* record this drop time */
+	lp->last_drop = tcp_time_stamp;
+}
+
+static struct tcp_congestion_ops tcp_lp = {
+	.init = tcp_lp_init,
+	.ssthresh = tcp_reno_ssthresh,
+	.cong_avoid = tcp_lp_cong_avoid,
+	.min_cwnd = tcp_reno_min_cwnd,
+	.rtt_sample = tcp_lp_rtt_sample,
+	.pkts_acked = tcp_lp_pkts_acked,
+
+	.owner = THIS_MODULE,
+	.name = "lp"
+};
+
+static int __init tcp_lp_register(void)
+{
+	BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE);
+	return tcp_register_congestion_control(&tcp_lp);
+}
+
+static void __exit tcp_lp_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_lp);
+}
+
+module_init(tcp_lp_register);
+module_exit(tcp_lp_unregister);
+
+MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Low Priority");
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index f33c9dd..bdd71db 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -59,6 +59,9 @@
 int sysctl_tcp_mtu_probing = 0;
 int sysctl_tcp_base_mss = 512;
 
+/* By default, RFC2861 behavior.  */
+int sysctl_tcp_slow_start_after_idle = 1;
+
 static void update_send_head(struct sock *sk, struct tcp_sock *tp,
 			     struct sk_buff *skb)
 {
@@ -138,7 +141,8 @@
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	const u32 now = tcp_time_stamp;
 
-	if (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto)
+	if (sysctl_tcp_slow_start_after_idle &&
+	    (!tp->packets_out && (s32)(now - tp->lsndtime) > icsk->icsk_rto))
 		tcp_cwnd_restart(sk, __sk_dst_get(sk));
 
 	tp->lsndtime = now;
@@ -511,15 +515,17 @@
 		/* Avoid the costly divide in the normal
 		 * non-TSO case.
 		 */
-		skb_shinfo(skb)->tso_segs = 1;
-		skb_shinfo(skb)->tso_size = 0;
+		skb_shinfo(skb)->gso_segs = 1;
+		skb_shinfo(skb)->gso_size = 0;
+		skb_shinfo(skb)->gso_type = 0;
 	} else {
 		unsigned int factor;
 
 		factor = skb->len + (mss_now - 1);
 		factor /= mss_now;
-		skb_shinfo(skb)->tso_segs = factor;
-		skb_shinfo(skb)->tso_size = mss_now;
+		skb_shinfo(skb)->gso_segs = factor;
+		skb_shinfo(skb)->gso_size = mss_now;
+		skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
 	}
 }
 
@@ -910,7 +916,7 @@
 
 	if (!tso_segs ||
 	    (tso_segs > 1 &&
-	     skb_shinfo(skb)->tso_size != mss_now)) {
+	     tcp_skb_mss(skb) != mss_now)) {
 		tcp_set_skb_tso_segs(sk, skb, mss_now);
 		tso_segs = tcp_skb_pcount(skb);
 	}
@@ -1720,8 +1726,9 @@
 	   tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
 		if (!pskb_trim(skb, 0)) {
 			TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
-			skb_shinfo(skb)->tso_segs = 1;
-			skb_shinfo(skb)->tso_size = 0;
+			skb_shinfo(skb)->gso_segs = 1;
+			skb_shinfo(skb)->gso_size = 0;
+			skb_shinfo(skb)->gso_type = 0;
 			skb->ip_summed = CHECKSUM_NONE;
 			skb->csum = 0;
 		}
@@ -1926,8 +1933,9 @@
 		skb->csum = 0;
 		TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
 		TCP_SKB_CB(skb)->sacked = 0;
-		skb_shinfo(skb)->tso_segs = 1;
-		skb_shinfo(skb)->tso_size = 0;
+		skb_shinfo(skb)->gso_segs = 1;
+		skb_shinfo(skb)->gso_size = 0;
+		skb_shinfo(skb)->gso_type = 0;
 
 		/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
 		TCP_SKB_CB(skb)->seq = tp->write_seq;
@@ -1959,8 +1967,9 @@
 	skb->csum = 0;
 	TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
 	TCP_SKB_CB(skb)->sacked = 0;
-	skb_shinfo(skb)->tso_segs = 1;
-	skb_shinfo(skb)->tso_size = 0;
+	skb_shinfo(skb)->gso_segs = 1;
+	skb_shinfo(skb)->gso_size = 0;
+	skb_shinfo(skb)->gso_type = 0;
 
 	/* Send it off. */
 	TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
@@ -2043,8 +2052,9 @@
 	TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
 	TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
 	TCP_SKB_CB(skb)->sacked = 0;
-	skb_shinfo(skb)->tso_segs = 1;
-	skb_shinfo(skb)->tso_size = 0;
+	skb_shinfo(skb)->gso_segs = 1;
+	skb_shinfo(skb)->gso_size = 0;
+	skb_shinfo(skb)->gso_type = 0;
 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 	th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
 	if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
@@ -2148,8 +2158,9 @@
 	TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
 	TCP_ECN_send_syn(sk, tp, buff);
 	TCP_SKB_CB(buff)->sacked = 0;
-	skb_shinfo(buff)->tso_segs = 1;
-	skb_shinfo(buff)->tso_size = 0;
+	skb_shinfo(buff)->gso_segs = 1;
+	skb_shinfo(buff)->gso_size = 0;
+	skb_shinfo(buff)->gso_type = 0;
 	buff->csum = 0;
 	TCP_SKB_CB(buff)->seq = tp->write_seq++;
 	TCP_SKB_CB(buff)->end_seq = tp->write_seq;
@@ -2253,8 +2264,9 @@
 		buff->csum = 0;
 		TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
 		TCP_SKB_CB(buff)->sacked = 0;
-		skb_shinfo(buff)->tso_segs = 1;
-		skb_shinfo(buff)->tso_size = 0;
+		skb_shinfo(buff)->gso_segs = 1;
+		skb_shinfo(buff)->gso_size = 0;
+		skb_shinfo(buff)->gso_type = 0;
 
 		/* Send it off, this clears delayed acks for us. */
 		TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
@@ -2289,8 +2301,9 @@
 	skb->csum = 0;
 	TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
 	TCP_SKB_CB(skb)->sacked = urgent;
-	skb_shinfo(skb)->tso_segs = 1;
-	skb_shinfo(skb)->tso_size = 0;
+	skb_shinfo(skb)->gso_segs = 1;
+	skb_shinfo(skb)->gso_size = 0;
+	skb_shinfo(skb)->gso_type = 0;
 
 	/* Use a previous sequence.  This should cause the other
 	 * end to send an ack.  Don't queue or clone SKB, just
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c
new file mode 100644
index 0000000..d7d517a
--- /dev/null
+++ b/net/ipv4/tcp_probe.c
@@ -0,0 +1,181 @@
+/*
+ * tcpprobe - Observe the TCP flow with kprobes.
+ *
+ * The idea for this came from Werner Almesberger's umlsim
+ * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kprobes.h>
+#include <linux/socket.h>
+#include <linux/tcp.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/kfifo.h>
+#include <linux/vmalloc.h>
+
+#include <net/tcp.h>
+
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_DESCRIPTION("TCP cwnd snooper");
+MODULE_LICENSE("GPL");
+
+static int port = 0;
+MODULE_PARM_DESC(port, "Port to match (0=all)");
+module_param(port, int, 0);
+
+static int bufsize = 64*1024;
+MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)");
+module_param(bufsize, int, 0);
+
+static const char procname[] = "tcpprobe";
+
+struct {
+	struct kfifo  *fifo;
+	spinlock_t    lock;
+	wait_queue_head_t wait;
+	struct timeval tstart;
+} tcpw;
+
+static void printl(const char *fmt, ...)
+{
+	va_list args;
+	int len;
+	struct timeval now;
+	char tbuf[256];
+
+	va_start(args, fmt);
+	do_gettimeofday(&now);
+
+	now.tv_sec -= tcpw.tstart.tv_sec;
+	now.tv_usec -= tcpw.tstart.tv_usec;
+	if (now.tv_usec < 0) {
+		--now.tv_sec;
+		now.tv_usec += 1000000;
+	}
+
+	len = sprintf(tbuf, "%lu.%06lu ",
+		      (unsigned long) now.tv_sec,
+		      (unsigned long) now.tv_usec);
+	len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args);
+	va_end(args);
+
+	kfifo_put(tcpw.fifo, tbuf, len);
+	wake_up(&tcpw.wait);
+}
+
+static int jtcp_sendmsg(struct kiocb *iocb, struct sock *sk,
+			struct msghdr *msg, size_t size)
+{
+	const struct tcp_sock *tp = tcp_sk(sk);
+	const struct inet_sock *inet = inet_sk(sk);
+
+	if (port == 0 || ntohs(inet->dport) == port ||
+	    ntohs(inet->sport) == port) {
+		printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n",
+		       NIPQUAD(inet->saddr), ntohs(inet->sport),
+		       NIPQUAD(inet->daddr), ntohs(inet->dport),
+		       size, tp->snd_nxt, tp->snd_una,
+		       tp->snd_cwnd, tcp_current_ssthresh(sk),
+		       tp->snd_wnd);
+	}
+
+	jprobe_return();
+	return 0;
+}
+
+static struct jprobe tcp_send_probe = {
+	.kp = { .addr = (kprobe_opcode_t *) &tcp_sendmsg, },
+	.entry = (kprobe_opcode_t *) &jtcp_sendmsg,
+};
+
+
+static int tcpprobe_open(struct inode * inode, struct file * file)
+{
+	kfifo_reset(tcpw.fifo);
+	do_gettimeofday(&tcpw.tstart);
+	return 0;
+}
+
+static ssize_t tcpprobe_read(struct file *file, char __user *buf,
+			     size_t len, loff_t *ppos)
+{
+	int error = 0, cnt;
+	unsigned char *tbuf;
+
+	if (!buf || len < 0)
+		return -EINVAL;
+
+	if (len == 0)
+		return 0;
+
+	tbuf = vmalloc(len);
+	if (!tbuf)
+		return -ENOMEM;
+
+	error = wait_event_interruptible(tcpw.wait,
+					 __kfifo_len(tcpw.fifo) != 0);
+	if (error)
+		return error;
+
+	cnt = kfifo_get(tcpw.fifo, tbuf, len);
+	error = copy_to_user(buf, tbuf, cnt);
+
+	vfree(tbuf);
+
+	return error ? error : cnt;
+}
+
+static struct file_operations tcpprobe_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = tcpprobe_open,
+	.read    = tcpprobe_read,
+};
+
+static __init int tcpprobe_init(void)
+{
+	int ret = -ENOMEM;
+
+	init_waitqueue_head(&tcpw.wait);
+	spin_lock_init(&tcpw.lock);
+	tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock);
+
+	if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops))
+		goto err0;
+
+	ret = register_jprobe(&tcp_send_probe);
+	if (ret)
+		goto err1;
+
+	pr_info("TCP watch registered (port=%d)\n", port);
+	return 0;
+ err1:
+	proc_net_remove(procname);
+ err0:
+	kfifo_free(tcpw.fifo);
+	return ret;
+}
+module_init(tcpprobe_init);
+
+static __exit void tcpprobe_exit(void)
+{
+	kfifo_free(tcpw.fifo);
+	proc_net_remove(procname);
+	unregister_jprobe(&tcp_send_probe);
+
+}
+module_exit(tcpprobe_exit);
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
new file mode 100644
index 0000000..11b42a7
--- /dev/null
+++ b/net/ipv4/tcp_veno.c
@@ -0,0 +1,231 @@
+/*
+ * TCP Veno congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ *    C. P. Fu, S. C. Liew.
+ *    "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks."
+ *    IEEE Journal on Selected Areas in Communication,
+ *    Feb. 2003.
+ * 	See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/inet_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Veno variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+static const int beta = 3 << V_PARAM_SHIFT;
+
+/* Veno variables */
+struct veno {
+	u8 doing_veno_now;	/* if true, do veno for this rtt */
+	u16 cntrtt;		/* # of rtts measured within last rtt */
+	u32 minrtt;		/* min of rtts measured within last rtt (in usec) */
+	u32 basertt;		/* the min of all Veno rtt measurements seen (in usec) */
+	u32 inc;		/* decide whether to increase cwnd */
+	u32 diff;		/* calculate the diff rate */
+};
+
+/* There are several situations when we must "re-start" Veno:
+ *
+ *  o when a connection is established
+ *  o after an RTO
+ *  o after fast recovery
+ *  o when we send a packet and there is no outstanding
+ *    unacknowledged data (restarting an idle connection)
+ *
+ */
+static inline void veno_enable(struct sock *sk)
+{
+	struct veno *veno = inet_csk_ca(sk);
+
+	/* turn on Veno */
+	veno->doing_veno_now = 1;
+
+	veno->minrtt = 0x7fffffff;
+}
+
+static inline void veno_disable(struct sock *sk)
+{
+	struct veno *veno = inet_csk_ca(sk);
+
+	/* turn off Veno */
+	veno->doing_veno_now = 0;
+}
+
+static void tcp_veno_init(struct sock *sk)
+{
+	struct veno *veno = inet_csk_ca(sk);
+
+	veno->basertt = 0x7fffffff;
+	veno->inc = 1;
+	veno_enable(sk);
+}
+
+/* Do rtt sampling needed for Veno. */
+static void tcp_veno_rtt_calc(struct sock *sk, u32 usrtt)
+{
+	struct veno *veno = inet_csk_ca(sk);
+	u32 vrtt = usrtt + 1;	/* Never allow zero rtt or basertt */
+
+	/* Filter to find propagation delay: */
+	if (vrtt < veno->basertt)
+		veno->basertt = vrtt;
+
+	/* Find the min rtt during the last rtt to find
+	 * the current prop. delay + queuing delay:
+	 */
+	veno->minrtt = min(veno->minrtt, vrtt);
+	veno->cntrtt++;
+}
+
+static void tcp_veno_state(struct sock *sk, u8 ca_state)
+{
+	if (ca_state == TCP_CA_Open)
+		veno_enable(sk);
+	else
+		veno_disable(sk);
+}
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Veno calculations
+ * until we get fresh rtt samples.  So when we
+ * restart, we reset our Veno state to a clean
+ * state. After we get acks for this flight of
+ * packets, _then_ we can make Veno calculations
+ * again.
+ */
+static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event)
+{
+	if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START)
+		tcp_veno_init(sk);
+}
+
+static void tcp_veno_cong_avoid(struct sock *sk, u32 ack,
+				u32 seq_rtt, u32 in_flight, int flag)
+{
+	struct tcp_sock *tp = tcp_sk(sk);
+	struct veno *veno = inet_csk_ca(sk);
+
+	if (!veno->doing_veno_now)
+		return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+
+	/* limited by applications */
+	if (!tcp_is_cwnd_limited(sk, in_flight))
+		return;
+
+	/* We do the Veno calculations only if we got enough rtt samples */
+	if (veno->cntrtt <= 2) {
+		/* We don't have enough rtt samples to do the Veno
+		 * calculation, so we'll behave like Reno.
+		 */
+		tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag);
+	} else {
+		u32 rtt, target_cwnd;
+
+		/* We have enough rtt samples, so, using the Veno
+		 * algorithm, we determine the state of the network.
+		 */
+
+		rtt = veno->minrtt;
+
+		target_cwnd = ((tp->snd_cwnd * veno->basertt)
+			       << V_PARAM_SHIFT) / rtt;
+
+		veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd;
+
+		if (tp->snd_cwnd <= tp->snd_ssthresh) {
+			/* Slow start.  */
+			tcp_slow_start(tp);
+		} else {
+			/* Congestion avoidance. */
+			if (veno->diff < beta) {
+				/* In the "non-congestive state", increase cwnd
+				 *  every rtt.
+				 */
+				if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+					if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+						tp->snd_cwnd++;
+					tp->snd_cwnd_cnt = 0;
+				} else
+					tp->snd_cwnd_cnt++;
+			} else {
+				/* In the "congestive state", increase cwnd
+				 * every other rtt.
+				 */
+				if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+					if (veno->inc
+					    && tp->snd_cwnd <
+					    tp->snd_cwnd_clamp) {
+						tp->snd_cwnd++;
+						veno->inc = 0;
+					} else
+						veno->inc = 1;
+					tp->snd_cwnd_cnt = 0;
+				} else
+					tp->snd_cwnd_cnt++;
+			}
+
+		}
+		if (tp->snd_cwnd < 2)
+			tp->snd_cwnd = 2;
+		else if (tp->snd_cwnd > tp->snd_cwnd_clamp)
+			tp->snd_cwnd = tp->snd_cwnd_clamp;
+	}
+	/* Wipe the slate clean for the next rtt. */
+	/* veno->cntrtt = 0; */
+	veno->minrtt = 0x7fffffff;
+}
+
+/* Veno MD phase */
+static u32 tcp_veno_ssthresh(struct sock *sk)
+{
+	const struct tcp_sock *tp = tcp_sk(sk);
+	struct veno *veno = inet_csk_ca(sk);
+
+	if (veno->diff < beta)
+		/* in "non-congestive state", cut cwnd by 1/5 */
+		return max(tp->snd_cwnd * 4 / 5, 2U);
+	else
+		/* in "congestive state", cut cwnd by 1/2 */
+		return max(tp->snd_cwnd >> 1U, 2U);
+}
+
+static struct tcp_congestion_ops tcp_veno = {
+	.init		= tcp_veno_init,
+	.ssthresh	= tcp_veno_ssthresh,
+	.cong_avoid	= tcp_veno_cong_avoid,
+	.rtt_sample	= tcp_veno_rtt_calc,
+	.set_state	= tcp_veno_state,
+	.cwnd_event	= tcp_veno_cwnd_event,
+
+	.owner		= THIS_MODULE,
+	.name		= "veno",
+};
+
+static int __init tcp_veno_register(void)
+{
+	BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE);
+	tcp_register_congestion_control(&tcp_veno);
+	return 0;
+}
+
+static void __exit tcp_veno_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_veno);
+}
+
+module_init(tcp_veno_register);
+module_exit(tcp_veno_unregister);
+
+MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Veno");
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index 0c340c3..4247da1 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -1,7 +1,24 @@
 /*
- * TCP Westwood+
+ * TCP Westwood+: end-to-end bandwidth estimation for TCP
  *
- *	Angelo Dell'Aera:	TCP Westwood+ support
+ *      Angelo Dell'Aera: author of the first version of TCP Westwood+ in Linux 2.4
+ *
+ * Support at http://c3lab.poliba.it/index.php/Westwood
+ * Main references in literature:
+ *
+ * - Mascolo S, Casetti, M. Gerla et al.
+ *   "TCP Westwood: bandwidth estimation for TCP" Proc. ACM Mobicom 2001
+ *
+ * - A. Grieco, s. Mascolo
+ *   "Performance evaluation of New Reno, Vegas, Westwood+ TCP" ACM Computer
+ *     Comm. Review, 2004
+ *
+ * - A. Dell'Aera, L. Grieco, S. Mascolo.
+ *   "Linux 2.4 Implementation of Westwood+ TCP with Rate-Halving :
+ *    A Performance Evaluation Over the Internet" (ICC 2004), Paris, June 2004
+ *
+ * Westwood+ employs end-to-end bandwidth measurement to set cwnd and
+ * ssthresh after packet loss. The probing phase is as the original Reno.
  */
 
 #include <linux/config.h>
@@ -22,6 +39,8 @@
 	u32    accounted;
 	u32    rtt;
 	u32    rtt_min;          /* minimum observed RTT */
+	u8     first_ack;        /* flag which infers that this is the first ack */
+	u8     reset_rtt_min;    /* Reset RTT min to next RTT sample*/
 };
 
 
@@ -49,9 +68,11 @@
         w->bw_est = 0;
         w->accounted = 0;
         w->cumul_ack = 0;
+	w->reset_rtt_min = 1;
 	w->rtt_min = w->rtt = TCP_WESTWOOD_INIT_RTT;
 	w->rtt_win_sx = tcp_time_stamp;
 	w->snd_una = tcp_sk(sk)->snd_una;
+	w->first_ack = 1;
 }
 
 /*
@@ -63,10 +84,16 @@
 	return (((7 * a) + b) >> 3);
 }
 
-static inline void westwood_filter(struct westwood *w, u32 delta)
+static void westwood_filter(struct westwood *w, u32 delta)
 {
-	w->bw_ns_est = westwood_do_filter(w->bw_ns_est, w->bk / delta);
-	w->bw_est = westwood_do_filter(w->bw_est, w->bw_ns_est);
+	/* If the filter is empty fill it with the first sample of bandwidth  */
+	if (w->bw_ns_est == 0 && w->bw_est == 0) {
+		w->bw_ns_est = w->bk / delta;
+		w->bw_est = w->bw_ns_est;
+	} else {
+		w->bw_ns_est = westwood_do_filter(w->bw_ns_est, w->bk / delta);
+		w->bw_est = westwood_do_filter(w->bw_est, w->bw_ns_est);
+	}
 }
 
 /*
@@ -91,6 +118,15 @@
 	struct westwood *w = inet_csk_ca(sk);
 	s32 delta = tcp_time_stamp - w->rtt_win_sx;
 
+	/* Initialize w->snd_una with the first acked sequence number in order
+	 * to fix mismatch between tp->snd_una and w->snd_una for the first
+	 * bandwidth sample
+	 */
+        if (w->first_ack) {
+		w->snd_una = tcp_sk(sk)->snd_una;
+		w->first_ack = 0;
+	}
+
 	/*
 	 * See if a RTT-window has passed.
 	 * Be careful since if RTT is less than
@@ -108,6 +144,16 @@
 	}
 }
 
+static inline void update_rtt_min(struct westwood *w)
+{
+	if (w->reset_rtt_min) {
+		w->rtt_min = w->rtt;
+		w->reset_rtt_min = 0;	
+	} else
+		w->rtt_min = min(w->rtt, w->rtt_min);
+}
+
+
 /*
  * @westwood_fast_bw
  * It is called when we are in fast path. In particular it is called when
@@ -123,7 +169,7 @@
 
 	w->bk += tp->snd_una - w->snd_una;
 	w->snd_una = tp->snd_una;
-	w->rtt_min = min(w->rtt, w->rtt_min);
+	update_rtt_min(w);
 }
 
 /*
@@ -162,12 +208,6 @@
 	return w->cumul_ack;
 }
 
-static inline u32 westwood_bw_rttmin(const struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	const struct westwood *w = inet_csk_ca(sk);
-	return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
-}
 
 /*
  * TCP Westwood
@@ -175,9 +215,11 @@
  * in packets we use mss_cache). Rttmin is guaranteed to be >= 2
  * so avoids ever returning 0.
  */
-static u32 tcp_westwood_cwnd_min(struct sock *sk)
+static u32 tcp_westwood_bw_rttmin(const struct sock *sk)
 {
-	return westwood_bw_rttmin(sk);
+	const struct tcp_sock *tp = tcp_sk(sk);
+	const struct westwood *w = inet_csk_ca(sk);
+	return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
 }
 
 static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
@@ -191,17 +233,19 @@
 		break;
 
 	case CA_EVENT_COMPLETE_CWR:
-		tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(sk);
+		tp->snd_cwnd = tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
 		break;
 
 	case CA_EVENT_FRTO:
-		tp->snd_ssthresh = westwood_bw_rttmin(sk);
+		tp->snd_ssthresh = tcp_westwood_bw_rttmin(sk);
+ 		/* Update RTT_min when next ack arrives */
+		w->reset_rtt_min = 1;
 		break;
 
 	case CA_EVENT_SLOW_ACK:
 		westwood_update_window(sk);
 		w->bk += westwood_acked_count(sk);
-		w->rtt_min = min(w->rtt, w->rtt_min);
+		update_rtt_min(w);
 		break;
 
 	default:
@@ -235,7 +279,7 @@
 	.init		= tcp_westwood_init,
 	.ssthresh	= tcp_reno_ssthresh,
 	.cong_avoid	= tcp_reno_cong_avoid,
-	.min_cwnd	= tcp_westwood_cwnd_min,
+	.min_cwnd	= tcp_westwood_bw_rttmin,
 	.cwnd_event	= tcp_westwood_event,
 	.get_info	= tcp_westwood_info,
 	.pkts_acked	= tcp_westwood_pkts_acked,
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
index 3e174c8..817ed84 100644
--- a/net/ipv4/xfrm4_input.c
+++ b/net/ipv4/xfrm4_input.c
@@ -13,7 +13,6 @@
 #include <linux/string.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4.h>
-#include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 
@@ -24,15 +23,6 @@
 
 EXPORT_SYMBOL(xfrm4_rcv);
 
-static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
-{
-	struct iphdr *outer_iph = skb->nh.iph;
-	struct iphdr *inner_iph = skb->h.ipiph;
-
-	if (INET_ECN_is_ce(outer_iph->tos))
-		IP_ECN_set_ce(inner_iph);
-}
-
 static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
 {
 	switch (nexthdr) {
@@ -113,24 +103,10 @@
 
 		xfrm_vec[xfrm_nr++] = x;
 
-		iph = skb->nh.iph;
+		if (x->mode->input(x, skb))
+			goto drop;
 
 		if (x->props.mode) {
-			if (iph->protocol != IPPROTO_IPIP)
-				goto drop;
-			if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-				goto drop;
-			if (skb_cloned(skb) &&
-			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-				goto drop;
-			if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-				ipv4_copy_dscp(iph, skb->h.ipiph);
-			if (!(x->props.flags & XFRM_STATE_NOECN))
-				ipip_ecn_decapsulate(skb);
-			skb->mac.raw = memmove(skb->data - skb->mac_len,
-					       skb->mac.raw, skb->mac_len);
-			skb->nh.raw = skb->data;
-			memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 			decaps = 1;
 			break;
 		}
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
new file mode 100644
index 0000000..a9e6b3d
--- /dev/null
+++ b/net/ipv4/xfrm4_mode_transport.c
@@ -0,0 +1,83 @@
+/*
+ * xfrm4_mode_transport.c - Transport mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header will be moved forward to make space for the encapsulation
+ * header.
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_transport_output(struct sk_buff *skb)
+{
+	struct xfrm_state *x;
+	struct iphdr *iph;
+	int ihl;
+
+	iph = skb->nh.iph;
+	skb->h.ipiph = iph;
+
+	ihl = iph->ihl * 4;
+	skb->h.raw += ihl;
+
+	x = skb->dst->xfrm;
+	skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl);
+	return 0;
+}
+
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is.  skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int ihl = skb->data - skb->h.raw;
+
+	if (skb->h.raw != skb->nh.raw)
+		skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl);
+	skb->nh.iph->tot_len = htons(skb->len + ihl);
+	skb->h.raw = skb->data;
+	return 0;
+}
+
+static struct xfrm_mode xfrm4_transport_mode = {
+	.input = xfrm4_transport_input,
+	.output = xfrm4_transport_output,
+	.owner = THIS_MODULE,
+	.encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm4_transport_init(void)
+{
+	return xfrm_register_mode(&xfrm4_transport_mode, AF_INET);
+}
+
+static void __exit xfrm4_transport_exit(void)
+{
+	int err;
+
+	err = xfrm_unregister_mode(&xfrm4_transport_mode, AF_INET);
+	BUG_ON(err);
+}
+
+module_init(xfrm4_transport_init);
+module_exit(xfrm4_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
new file mode 100644
index 0000000..f8d880b
--- /dev/null
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -0,0 +1,125 @@
+/*
+ * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
+ *
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ip.h>
+#include <net/xfrm.h>
+
+static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
+{
+	struct iphdr *outer_iph = skb->nh.iph;
+	struct iphdr *inner_iph = skb->h.ipiph;
+
+	if (INET_ECN_is_ce(outer_iph->tos))
+		IP_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401.  The following fields
+ * in it shall be filled in by x->type->output:
+ *      tot_len
+ *      check
+ *
+ * On exit, skb->h will be set to the start of the payload to be processed
+ * by x->type->output and skb->nh will be set to the top IP header.
+ */
+static int xfrm4_tunnel_output(struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb->dst;
+	struct xfrm_state *x = dst->xfrm;
+	struct iphdr *iph, *top_iph;
+	int flags;
+
+	iph = skb->nh.iph;
+	skb->h.ipiph = iph;
+
+	skb->nh.raw = skb_push(skb, x->props.header_len);
+	top_iph = skb->nh.iph;
+
+	top_iph->ihl = 5;
+	top_iph->version = 4;
+
+	/* DS disclosed */
+	top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+
+	flags = x->props.flags;
+	if (flags & XFRM_STATE_NOECN)
+		IP_ECN_clear(top_iph);
+
+	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+		0 : (iph->frag_off & htons(IP_DF));
+	if (!top_iph->frag_off)
+		__ip_select_ident(top_iph, dst->child, 0);
+
+	top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
+
+	top_iph->saddr = x->props.saddr.a4;
+	top_iph->daddr = x->id.daddr.a4;
+	top_iph->protocol = IPPROTO_IPIP;
+
+	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+	return 0;
+}
+
+static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	int err = -EINVAL;
+
+	if (iph->protocol != IPPROTO_IPIP)
+		goto out;
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		goto out;
+
+	if (skb_cloned(skb) &&
+	    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+		goto out;
+
+	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+		ipv4_copy_dscp(iph, skb->h.ipiph);
+	if (!(x->props.flags & XFRM_STATE_NOECN))
+		ipip_ecn_decapsulate(skb);
+	skb->mac.raw = memmove(skb->data - skb->mac_len,
+			       skb->mac.raw, skb->mac_len);
+	skb->nh.raw = skb->data;
+	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+	err = 0;
+
+out:
+	return err;
+}
+
+static struct xfrm_mode xfrm4_tunnel_mode = {
+	.input = xfrm4_tunnel_input,
+	.output = xfrm4_tunnel_output,
+	.owner = THIS_MODULE,
+	.encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm4_tunnel_init(void)
+{
+	return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
+}
+
+static void __exit xfrm4_tunnel_exit(void)
+{
+	int err;
+
+	err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET);
+	BUG_ON(err);
+}
+
+module_init(xfrm4_tunnel_init);
+module_exit(xfrm4_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 4ef8efa..193363e 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -9,70 +9,15 @@
  */
 
 #include <linux/compiler.h>
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
 #include <linux/netfilter_ipv4.h>
-#include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
 #include <net/icmp.h>
 
-/* Add encapsulation header.
- *
- * In transport mode, the IP header will be moved forward to make space
- * for the encapsulation header.
- *
- * In tunnel mode, the top IP header will be constructed per RFC 2401.
- * The following fields in it shall be filled in by x->type->output:
- *	tot_len
- *	check
- *
- * On exit, skb->h will be set to the start of the payload to be processed
- * by x->type->output and skb->nh will be set to the top IP header.
- */
-static void xfrm4_encap(struct sk_buff *skb)
-{
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x = dst->xfrm;
-	struct iphdr *iph, *top_iph;
-	int flags;
-
-	iph = skb->nh.iph;
-	skb->h.ipiph = iph;
-
-	skb->nh.raw = skb_push(skb, x->props.header_len);
-	top_iph = skb->nh.iph;
-
-	if (!x->props.mode) {
-		skb->h.raw += iph->ihl*4;
-		memmove(top_iph, iph, iph->ihl*4);
-		return;
-	}
-
-	top_iph->ihl = 5;
-	top_iph->version = 4;
-
-	/* DS disclosed */
-	top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
-
-	flags = x->props.flags;
-	if (flags & XFRM_STATE_NOECN)
-		IP_ECN_clear(top_iph);
-
-	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
-		0 : (iph->frag_off & htons(IP_DF));
-	if (!top_iph->frag_off)
-		__ip_select_ident(top_iph, dst->child, 0);
-
-	top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
-
-	top_iph->saddr = x->props.saddr.a4;
-	top_iph->daddr = x->id.daddr.a4;
-	top_iph->protocol = IPPROTO_IPIP;
-
-	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
-}
-
 static int xfrm4_tunnel_check_size(struct sk_buff *skb)
 {
 	int mtu, ret = 0;
@@ -121,7 +66,9 @@
 		if (err)
 			goto error;
 
-		xfrm4_encap(skb);
+		err = x->mode->output(skb);
+		if (err)
+			goto error;
 
 		err = x->type->output(x, skb);
 		if (err)
@@ -152,16 +99,10 @@
 	goto out_exit;
 }
 
-static int xfrm4_output_finish(struct sk_buff *skb)
+static int xfrm4_output_finish2(struct sk_buff *skb)
 {
 	int err;
 
-#ifdef CONFIG_NETFILTER
-	if (!skb->dst->xfrm) {
-		IPCB(skb)->flags |= IPSKB_REROUTED;
-		return dst_output(skb);
-	}
-#endif
 	while (likely((err = xfrm4_output_one(skb)) == 0)) {
 		nf_reset(skb);
 
@@ -174,7 +115,7 @@
 			return dst_output(skb);
 
 		err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
-			      skb->dst->dev, xfrm4_output_finish);
+			      skb->dst->dev, xfrm4_output_finish2);
 		if (unlikely(err != 1))
 			break;
 	}
@@ -182,6 +123,48 @@
 	return err;
 }
 
+static int xfrm4_output_finish(struct sk_buff *skb)
+{
+	struct sk_buff *segs;
+
+#ifdef CONFIG_NETFILTER
+	if (!skb->dst->xfrm) {
+		IPCB(skb)->flags |= IPSKB_REROUTED;
+		return dst_output(skb);
+	}
+#endif
+
+	if (!skb_shinfo(skb)->gso_size)
+		return xfrm4_output_finish2(skb);
+
+	skb->protocol = htons(ETH_P_IP);
+	segs = skb_gso_segment(skb, 0);
+	kfree_skb(skb);
+	if (unlikely(IS_ERR(segs)))
+		return PTR_ERR(segs);
+
+	do {
+		struct sk_buff *nskb = segs->next;
+		int err;
+
+		segs->next = NULL;
+		err = xfrm4_output_finish2(segs);
+
+		if (unlikely(err)) {
+			while ((segs = nskb)) {
+				nskb = segs->next;
+				segs->next = NULL;
+				kfree_skb(segs);
+			}
+			return err;
+		}
+
+		segs = nskb;
+	} while (segs);
+
+	return 0;
+}
+
 int xfrm4_output(struct sk_buff *skb)
 {
 	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 8604c74..c046528 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -17,8 +17,6 @@
 static struct dst_ops xfrm4_dst_ops;
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo;
 
-static struct xfrm_type_map xfrm4_type_map = { .lock = RW_LOCK_UNLOCKED };
-
 static int xfrm4_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
 {
 	return __ip_route_output_key((struct rtable**)dst, fl);
@@ -237,9 +235,7 @@
 
 static inline int xfrm4_garbage_collect(void)
 {
-	read_lock(&xfrm4_policy_afinfo.lock);
 	xfrm4_policy_afinfo.garbage_collect();
-	read_unlock(&xfrm4_policy_afinfo.lock);
 	return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2);
 }
 
@@ -299,8 +295,6 @@
 
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
 	.family = 		AF_INET,
-	.lock = 		RW_LOCK_UNLOCKED,
-	.type_map = 		&xfrm4_type_map,
 	.dst_ops =		&xfrm4_dst_ops,
 	.dst_lookup =		xfrm4_dst_lookup,
 	.find_bundle = 		__xfrm4_find_bundle,
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index dbabf81a..81e1751 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -131,7 +131,6 @@
 
 static struct xfrm_state_afinfo xfrm4_state_afinfo = {
 	.family			= AF_INET,
-	.lock			= RW_LOCK_UNLOCKED,
 	.init_flags		= xfrm4_init_flags,
 	.init_tempsel		= __xfrm4_init_tempsel,
 	.state_lookup		= __xfrm4_state_lookup,
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index f8a107a..e923d4d 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -106,6 +106,26 @@
 	tristate
 	default n
 
+config INET6_XFRM_MODE_TRANSPORT
+	tristate "IPv6: IPsec transport mode"
+	depends on IPV6
+	default IPV6
+	select XFRM
+	---help---
+	  Support for IPsec transport mode.
+
+	  If unsure, say Y.
+
+config INET6_XFRM_MODE_TUNNEL
+	tristate "IPv6: IPsec tunnel mode"
+	depends on IPV6
+	default IPV6
+	select XFRM
+	---help---
+	  Support for IPsec tunnel mode.
+
+	  If unsure, say Y.
+
 config IPV6_TUNNEL
 	tristate "IPv6: IPv6-in-IPv6 tunnel"
 	select INET6_TUNNEL
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index a760b09..386e0a6 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -20,6 +20,8 @@
 obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
 obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
 obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
+obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
+obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
 obj-$(CONFIG_NETFILTER)	+= netfilter/
 
 obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 445006e..4da6645 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -862,6 +862,8 @@
   * 	2002::/16		2
   * 	::/96			3
   * 	::ffff:0:0/96		4
+  *	fc00::/7		5
+  * 	2001::/32		6
   */
 	if (type & IPV6_ADDR_LOOPBACK)
 		return 0;
@@ -869,8 +871,12 @@
 		return 3;
 	else if (type & IPV6_ADDR_MAPPED)
 		return 4;
+	else if (addr->s6_addr32[0] == htonl(0x20010000))
+		return 6;
 	else if (addr->s6_addr16[0] == htons(0x2002))
 		return 2;
+	else if ((addr->s6_addr[0] & 0xfe) == 0xfc)
+		return 5;
 	return 1;
 }
 
@@ -1069,6 +1075,9 @@
 				if (hiscore.attrs & IPV6_SADDR_SCORE_PRIVACY)
 					continue;
 			}
+#else
+			if (hiscore.rule < 7)
+				hiscore.rule++;
 #endif
 			/* Rule 8: Use longest matching prefix */
 			if (hiscore.rule < 8) {
@@ -2860,6 +2869,11 @@
 	return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen);
 }
 
+/* Maximum length of ifa_cacheinfo attributes */
+#define INET6_IFADDR_RTA_SPACE \
+		RTA_SPACE(16) /* IFA_ADDRESS */ + \
+		RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
 			     u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3092,7 +3106,7 @@
 static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
 {
 	struct sk_buff *skb;
-	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
+	int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE);
 
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb) {
@@ -3142,6 +3156,17 @@
 #endif
 }
 
+/* Maximum length of ifinfomsg attributes */
+#define INET6_IFINFO_RTA_SPACE \
+		RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \
+		RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ +	\
+		RTA_SPACE(sizeof(u32)) /* MTU */ + \
+		RTA_SPACE(sizeof(int)) /* LINK */ + \
+		RTA_SPACE(0) /* PROTINFO */ + \
+		RTA_SPACE(sizeof(u32)) /* FLAGS */ + \
+		RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \
+		RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */
+
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 
 			     u32 pid, u32 seq, int event, unsigned int flags)
 {
@@ -3235,8 +3260,7 @@
 void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
 {
 	struct sk_buff *skb;
-	/* 128 bytes ?? */
-	int size = NLMSG_SPACE(sizeof(struct ifinfomsg)+128);
+	int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE);
 	
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb) {
@@ -3252,6 +3276,11 @@
 	netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC);
 }
 
+/* Maximum length of prefix_cacheinfo attributes */
+#define INET6_PREFIX_RTA_SPACE \
+		RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \
+		RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */
+
 static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
 			struct prefix_info *pinfo, u32 pid, u32 seq, 
 			int event, unsigned int flags)
@@ -3296,7 +3325,7 @@
 			 struct prefix_info *pinfo)
 {
 	struct sk_buff *skb;
-	int size = NLMSG_SPACE(sizeof(struct prefixmsg)+128);
+	int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE);
 
 	skb = alloc_skb(size, GFP_ATOMIC);
 	if (!skb) {
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 6778173..d31c0d6 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -292,7 +292,7 @@
 
 		memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
 		memset(ah->auth_data, 0, ahp->icv_trunc_len);
-		skb_push(skb, skb->data - skb->nh.raw);
+		skb_push(skb, hdr_len);
 		ahp->icv(ahp, skb, ah->auth_data);
 		if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
 			LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n");
@@ -301,12 +301,8 @@
 		}
 	}
 
-	skb->nh.raw = skb_pull(skb, ah_hlen);
-	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
-	skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
-	skb_pull(skb, hdr_len);
-	skb->h.raw = skb->data;
-
+	skb->h.raw = memcpy(skb->nh.raw += ah_hlen, tmp_hdr, hdr_len);
+	__skb_pull(skb, ah_hlen + hdr_len);
 
 	kfree(tmp_hdr);
 
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 22f0460..a15a6f3 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -142,26 +142,18 @@
 
 	int hdr_len = skb->h.raw - skb->nh.raw;
 	int nfrags;
-	unsigned char *tmp_hdr = NULL;
 	int ret = 0;
 
 	if (!pskb_may_pull(skb, sizeof(struct ipv6_esp_hdr))) {
 		ret = -EINVAL;
-		goto out_nofree;
+		goto out;
 	}
 
 	if (elen <= 0 || (elen & (blksize-1))) {
 		ret = -EINVAL;
-		goto out_nofree;
+		goto out;
 	}
 
-	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
-	if (!tmp_hdr) {
-		ret = -ENOMEM;
-		goto out_nofree;
-	}
-	memcpy(tmp_hdr, skb->nh.raw, hdr_len);
-
 	/* If integrity check is required, do this. */
         if (esp->auth.icv_full_len) {
 		u8 sum[esp->auth.icv_full_len];
@@ -222,16 +214,12 @@
 		/* ... check padding bits here. Silly. :-) */ 
 
 		pskb_trim(skb, skb->len - alen - padlen - 2);
-		skb->h.raw = skb_pull(skb, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen);
-		skb->nh.raw += sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen;
-		memcpy(skb->nh.raw, tmp_hdr, hdr_len);
-		skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
 		ret = nexthdr[1];
 	}
 
+	skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - hdr_len;
+
 out:
-	kfree(tmp_hdr);
-out_nofree:
 	return ret;
 }
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index e460489..abb94de 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -39,6 +39,7 @@
 #include <linux/in6.h>
 #include <linux/tcp.h>
 #include <linux/route.h>
+#include <linux/module.h>
 
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
@@ -147,7 +148,7 @@
 
 int ip6_output(struct sk_buff *skb)
 {
-	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
+	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
 				dst_allfrag(skb->dst))
 		return ip6_fragment(skb, ip6_output2);
 	else
@@ -458,6 +459,7 @@
 	nf_bridge_get(to->nf_bridge);
 #endif
 #endif
+	skb_copy_secmark(to, from);
 }
 
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
@@ -488,6 +490,7 @@
 
 	return offset;
 }
+EXPORT_SYMBOL_GPL(ip6_find_1stfragopt);
 
 static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
@@ -830,8 +833,9 @@
 		struct frag_hdr fhdr;
 
 		/* specify the length of each IP datagram fragment*/
-		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - 
-						sizeof(struct frag_hdr);
+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen - 
+					    sizeof(struct frag_hdr);
+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 		ipv6_select_ident(skb, &fhdr);
 		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
 		__skb_queue_tail(&sk->sk_write_queue, skb);
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 4863643..f28cd37 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -65,38 +65,25 @@
 
 static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	int err = 0;
-	u8 nexthdr = 0;
-	int hdr_len = skb->h.raw - skb->nh.raw;
-	unsigned char *tmp_hdr = NULL;
+	int err = -ENOMEM;
 	struct ipv6hdr *iph;
+	struct ipv6_comp_hdr *ipch;
 	int plen, dlen;
 	struct ipcomp_data *ipcd = x->data;
 	u8 *start, *scratch;
 	struct crypto_tfm *tfm;
 	int cpu;
 
-	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-		skb_linearize(skb, GFP_ATOMIC) != 0) {
-		err = -ENOMEM;
+	if (skb_linearize_cow(skb))
 		goto out;
-	}
 
 	skb->ip_summed = CHECKSUM_NONE;
 
 	/* Remove ipcomp header and decompress original payload */
 	iph = skb->nh.ipv6h;
-	tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC);
-	if (!tmp_hdr)
-		goto out;
-	memcpy(tmp_hdr, iph, hdr_len);
-	nexthdr = *(u8 *)skb->data;
-	skb_pull(skb, sizeof(struct ipv6_comp_hdr)); 
-	skb->nh.raw += sizeof(struct ipv6_comp_hdr);
-	memcpy(skb->nh.raw, tmp_hdr, hdr_len);
-	iph = skb->nh.ipv6h;
-	iph->payload_len = htons(ntohs(iph->payload_len) - sizeof(struct ipv6_comp_hdr));
-	skb->h.raw = skb->data;
+	ipch = (void *)skb->data;
+	skb->h.raw = skb->nh.raw + sizeof(*ipch);
+	__skb_pull(skb, sizeof(*ipch));
 
 	/* decompression */
 	plen = skb->len;
@@ -125,18 +112,11 @@
 
 	skb_put(skb, dlen - plen);
 	memcpy(skb->data, scratch, dlen);
+	err = ipch->nexthdr;
 
-	iph = skb->nh.ipv6h;
-	iph->payload_len = htons(skb->len);
-	
 out_put_cpu:
 	put_cpu();
 out:
-	kfree(tmp_hdr);
-	if (err)
-		goto error_out;
-	return nexthdr;
-error_out:
 	return err;
 }
 
@@ -159,10 +139,8 @@
 		goto out_ok;
 	}
 
-	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
-		skb_linearize(skb, GFP_ATOMIC) != 0) {
+	if (skb_linearize_cow(skb))
 		goto out_ok;
-	}
 
 	/* compression */
 	plen = skb->len - hdr_len;
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 93bae36..2a71c3b 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -189,7 +189,7 @@
 
 	/* This is where we call the helper: as the packet goes out. */
 	ct = nf_ct_get(*pskb, &ctinfo);
-	if (!ct)
+	if (!ct || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)
 		goto out;
 
 	help = nfct_help(ct);
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index 86c6703..ef18a7b 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -233,7 +233,7 @@
 		return -NF_ACCEPT;
 	}
 
-	if (hooknum == NF_IP6_PRE_ROUTING &&
+	if (nf_conntrack_checksum && hooknum == NF_IP6_PRE_ROUTING &&
 	    nf_ip6_checksum(skb, hooknum, dataoff, IPPROTO_ICMPV6)) {
 		nf_log_packet(PF_INET6, 0, skb, NULL, NULL, NULL,
 			      "nf_ct_icmpv6: ICMPv6 checksum failed\n");
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 3e31903..c32a029 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -456,13 +456,9 @@
 		DEBUGP("queue: message is too short.\n");
 		goto err;
 	}
-	if (end-offset < skb->len) {
-		if (pskb_trim(skb, end - offset)) {
-			DEBUGP("Can't trim\n");
-			goto err;
-		}
-		if (skb->ip_summed != CHECKSUM_UNNECESSARY)
-			skb->ip_summed = CHECKSUM_NONE;
+	if (pskb_trim_rcsum(skb, end - offset)) {
+		DEBUGP("Can't trim\n");
+		goto err;
 	}
 
 	/* Find out which fragments are in front and at the back of us
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8a77793..e728980 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -349,7 +349,7 @@
 	    (strict & RT6_SELECT_F_REACHABLE) &&
 	    last && last != rt0) {
 		/* no entries matched; do round-robin */
-		static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+		static DEFINE_SPINLOCK(lock);
 		spin_lock(&lock);
 		*head = rt0->u.next;
 		rt0->u.next = last->u.next;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 301eee7..a50eb30 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1218,8 +1218,16 @@
 	bh_lock_sock(sk);
 	ret = 0;
 	if (!sock_owned_by_user(sk)) {
-		if (!tcp_prequeue(sk, skb))
-			ret = tcp_v6_do_rcv(sk, skb);
+#ifdef CONFIG_NET_DMA
+                struct tcp_sock *tp = tcp_sk(sk);
+                if (tp->ucopy.dma_chan)
+                        ret = tcp_v6_do_rcv(sk, skb);
+                else
+#endif
+		{
+			if (!tcp_prequeue(sk, skb))
+				ret = tcp_v6_do_rcv(sk, skb);
+		}
 	} else
 		sk_add_backlog(sk, skb);
 	bh_unlock_sock(sk);
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index 00cfdee..0405d74 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -13,21 +13,9 @@
 #include <linux/string.h>
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv6.h>
-#include <net/dsfield.h>
-#include <net/inet_ecn.h>
-#include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
-{
-	struct ipv6hdr *outer_iph = skb->nh.ipv6h;
-	struct ipv6hdr *inner_iph = skb->h.ipv6h;
-
-	if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
-		IP6_ECN_set_ce(inner_iph);
-}
-
 int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi)
 {
 	int err;
@@ -81,21 +69,10 @@
 
 		xfrm_vec[xfrm_nr++] = x;
 
+		if (x->mode->input(x, skb))
+			goto drop;
+
 		if (x->props.mode) { /* XXX */
-			if (nexthdr != IPPROTO_IPV6)
-				goto drop;
-			if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
-				goto drop;
-			if (skb_cloned(skb) &&
-			    pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-				goto drop;
-			if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-				ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
-			if (!(x->props.flags & XFRM_STATE_NOECN))
-				ipip6_ecn_decapsulate(skb);
-			skb->mac.raw = memmove(skb->data - skb->mac_len,
-					       skb->mac.raw, skb->mac_len);
-			skb->nh.raw = skb->data;
 			decaps = 1;
 			break;
 		}
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
new file mode 100644
index 0000000..711d713
--- /dev/null
+++ b/net/ipv6/xfrm6_mode_transport.c
@@ -0,0 +1,88 @@
+/*
+ * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dst.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+/* Add encapsulation header.
+ *
+ * The IP header and mutable extension headers will be moved forward to make
+ * space for the encapsulation header.
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header.  The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_transport_output(struct sk_buff *skb)
+{
+	struct xfrm_state *x = skb->dst->xfrm;
+	struct ipv6hdr *iph;
+	u8 *prevhdr;
+	int hdr_len;
+
+	skb_push(skb, x->props.header_len);
+	iph = skb->nh.ipv6h;
+
+	hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
+	skb->nh.raw = prevhdr - x->props.header_len;
+	skb->h.raw = skb->data + hdr_len;
+	memmove(skb->data, iph, hdr_len);
+	return 0;
+}
+
+/* Remove encapsulation header.
+ *
+ * The IP header will be moved over the top of the encapsulation header.
+ *
+ * On entry, skb->h shall point to where the IP header should be and skb->nh
+ * shall be set to where the IP header currently is.  skb->data shall point
+ * to the start of the payload.
+ */
+static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int ihl = skb->data - skb->h.raw;
+
+	if (skb->h.raw != skb->nh.raw)
+		skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl);
+	skb->nh.ipv6h->payload_len = htons(skb->len + ihl -
+					   sizeof(struct ipv6hdr));
+	skb->h.raw = skb->data;
+	return 0;
+}
+
+static struct xfrm_mode xfrm6_transport_mode = {
+	.input = xfrm6_transport_input,
+	.output = xfrm6_transport_output,
+	.owner = THIS_MODULE,
+	.encap = XFRM_MODE_TRANSPORT,
+};
+
+static int __init xfrm6_transport_init(void)
+{
+	return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6);
+}
+
+static void __exit xfrm6_transport_exit(void)
+{
+	int err;
+
+	err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6);
+	BUG_ON(err);
+}
+
+module_init(xfrm6_transport_init);
+module_exit(xfrm6_transport_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
new file mode 100644
index 0000000..8af79be2
--- /dev/null
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -0,0 +1,121 @@
+/*
+ * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6.
+ *
+ * Copyright (C) 2002 USAGI/WIDE Project
+ * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/stringify.h>
+#include <net/dsfield.h>
+#include <net/dst.h>
+#include <net/inet_ecn.h>
+#include <net/ipv6.h>
+#include <net/xfrm.h>
+
+static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
+{
+	struct ipv6hdr *outer_iph = skb->nh.ipv6h;
+	struct ipv6hdr *inner_iph = skb->h.ipv6h;
+
+	if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph)))
+		IP6_ECN_set_ce(inner_iph);
+}
+
+/* Add encapsulation header.
+ *
+ * The top IP header will be constructed per RFC 2401.  The following fields
+ * in it shall be filled in by x->type->output:
+ *	payload_len
+ *
+ * On exit, skb->h will be set to the start of the encapsulation header to be
+ * filled in by x->type->output and skb->nh will be set to the nextheader field
+ * of the extension header directly preceding the encapsulation header, or in
+ * its absence, that of the top IP header.  The value of skb->data will always
+ * point to the top IP header.
+ */
+static int xfrm6_tunnel_output(struct sk_buff *skb)
+{
+	struct dst_entry *dst = skb->dst;
+	struct xfrm_state *x = dst->xfrm;
+	struct ipv6hdr *iph, *top_iph;
+	int dsfield;
+
+	skb_push(skb, x->props.header_len);
+	iph = skb->nh.ipv6h;
+
+	skb->nh.raw = skb->data;
+	top_iph = skb->nh.ipv6h;
+	skb->nh.raw = &top_iph->nexthdr;
+	skb->h.ipv6h = top_iph + 1;
+
+	top_iph->version = 6;
+	top_iph->priority = iph->priority;
+	top_iph->flow_lbl[0] = iph->flow_lbl[0];
+	top_iph->flow_lbl[1] = iph->flow_lbl[1];
+	top_iph->flow_lbl[2] = iph->flow_lbl[2];
+	dsfield = ipv6_get_dsfield(top_iph);
+	dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+	if (x->props.flags & XFRM_STATE_NOECN)
+		dsfield &= ~INET_ECN_MASK;
+	ipv6_change_dsfield(top_iph, 0, dsfield);
+	top_iph->nexthdr = IPPROTO_IPV6; 
+	top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
+	ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
+	ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
+	return 0;
+}
+
+static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
+{
+	int err = -EINVAL;
+
+	if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6)
+		goto out;
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+		goto out;
+
+	if (skb_cloned(skb) &&
+	    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+		goto out;
+
+	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+		ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h);
+	if (!(x->props.flags & XFRM_STATE_NOECN))
+		ipip6_ecn_decapsulate(skb);
+	skb->mac.raw = memmove(skb->data - skb->mac_len,
+			       skb->mac.raw, skb->mac_len);
+	skb->nh.raw = skb->data;
+	err = 0;
+
+out:
+	return err;
+}
+
+static struct xfrm_mode xfrm6_tunnel_mode = {
+	.input = xfrm6_tunnel_input,
+	.output = xfrm6_tunnel_output,
+	.owner = THIS_MODULE,
+	.encap = XFRM_MODE_TUNNEL,
+};
+
+static int __init xfrm6_tunnel_init(void)
+{
+	return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6);
+}
+
+static void __exit xfrm6_tunnel_exit(void)
+{
+	int err;
+
+	err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6);
+	BUG_ON(err);
+}
+
+module_init(xfrm6_tunnel_init);
+module_exit(xfrm6_tunnel_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL);
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 8024217..48fccb1 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -14,68 +14,9 @@
 #include <linux/spinlock.h>
 #include <linux/icmpv6.h>
 #include <linux/netfilter_ipv6.h>
-#include <net/dsfield.h>
-#include <net/inet_ecn.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-/* Add encapsulation header.
- *
- * In transport mode, the IP header and mutable extension headers will be moved
- * forward to make space for the encapsulation header.
- *
- * In tunnel mode, the top IP header will be constructed per RFC 2401.
- * The following fields in it shall be filled in by x->type->output:
- *	payload_len
- *
- * On exit, skb->h will be set to the start of the encapsulation header to be
- * filled in by x->type->output and skb->nh will be set to the nextheader field
- * of the extension header directly preceding the encapsulation header, or in
- * its absence, that of the top IP header.  The value of skb->data will always
- * point to the top IP header.
- */
-static void xfrm6_encap(struct sk_buff *skb)
-{
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x = dst->xfrm;
-	struct ipv6hdr *iph, *top_iph;
-	int dsfield;
-
-	skb_push(skb, x->props.header_len);
-	iph = skb->nh.ipv6h;
-
-	if (!x->props.mode) {
-		u8 *prevhdr;
-		int hdr_len;
-
-		hdr_len = ip6_find_1stfragopt(skb, &prevhdr);
-		skb->nh.raw = prevhdr - x->props.header_len;
-		skb->h.raw = skb->data + hdr_len;
-		memmove(skb->data, iph, hdr_len);
-		return;
-	}
-
-	skb->nh.raw = skb->data;
-	top_iph = skb->nh.ipv6h;
-	skb->nh.raw = &top_iph->nexthdr;
-	skb->h.ipv6h = top_iph + 1;
-
-	top_iph->version = 6;
-	top_iph->priority = iph->priority;
-	top_iph->flow_lbl[0] = iph->flow_lbl[0];
-	top_iph->flow_lbl[1] = iph->flow_lbl[1];
-	top_iph->flow_lbl[2] = iph->flow_lbl[2];
-	dsfield = ipv6_get_dsfield(top_iph);
-	dsfield = INET_ECN_encapsulate(dsfield, dsfield);
-	if (x->props.flags & XFRM_STATE_NOECN)
-		dsfield &= ~INET_ECN_MASK;
-	ipv6_change_dsfield(top_iph, 0, dsfield);
-	top_iph->nexthdr = IPPROTO_IPV6; 
-	top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT);
-	ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr);
-	ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr);
-}
-
 static int xfrm6_tunnel_check_size(struct sk_buff *skb)
 {
 	int mtu, ret = 0;
@@ -118,7 +59,9 @@
 		if (err)
 			goto error;
 
-		xfrm6_encap(skb);
+		err = x->mode->output(skb);
+		if (err)
+			goto error;
 
 		err = x->type->output(x, skb);
 		if (err)
@@ -151,7 +94,7 @@
 	goto out_exit;
 }
 
-static int xfrm6_output_finish(struct sk_buff *skb)
+static int xfrm6_output_finish2(struct sk_buff *skb)
 {
 	int err;
 
@@ -167,7 +110,7 @@
 			return dst_output(skb);
 
 		err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
-			      skb->dst->dev, xfrm6_output_finish);
+			      skb->dst->dev, xfrm6_output_finish2);
 		if (unlikely(err != 1))
 			break;
 	}
@@ -175,6 +118,41 @@
 	return err;
 }
 
+static int xfrm6_output_finish(struct sk_buff *skb)
+{
+	struct sk_buff *segs;
+
+	if (!skb_shinfo(skb)->gso_size)
+		return xfrm6_output_finish2(skb);
+
+	skb->protocol = htons(ETH_P_IP);
+	segs = skb_gso_segment(skb, 0);
+	kfree_skb(skb);
+	if (unlikely(IS_ERR(segs)))
+		return PTR_ERR(segs);
+
+	do {
+		struct sk_buff *nskb = segs->next;
+		int err;
+
+		segs->next = NULL;
+		err = xfrm6_output_finish2(segs);
+
+		if (unlikely(err)) {
+			while ((segs = nskb)) {
+				nskb = segs->next;
+				segs->next = NULL;
+				kfree_skb(segs);
+			}
+			return err;
+		}
+
+		segs = nskb;
+	} while (segs);
+
+	return 0;
+}
+
 int xfrm6_output(struct sk_buff *skb)
 {
 	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev,
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 88c840f..ee715f2 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -23,8 +23,6 @@
 static struct dst_ops xfrm6_dst_ops;
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo;
 
-static struct xfrm_type_map xfrm6_type_map = { .lock = RW_LOCK_UNLOCKED };
-
 static int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl)
 {
 	int err = 0;
@@ -249,9 +247,7 @@
 
 static inline int xfrm6_garbage_collect(void)
 {
-	read_lock(&xfrm6_policy_afinfo.lock);
 	xfrm6_policy_afinfo.garbage_collect();
-	read_unlock(&xfrm6_policy_afinfo.lock);
 	return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2);
 }
 
@@ -311,8 +307,6 @@
 
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
 	.family =		AF_INET6,
-	.lock = 		RW_LOCK_UNLOCKED,
-	.type_map = 		&xfrm6_type_map,
 	.dst_ops =		&xfrm6_dst_ops,
 	.dst_lookup =		xfrm6_dst_lookup,
 	.find_bundle =		__xfrm6_find_bundle,
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index a572302..b33296b3 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -135,7 +135,6 @@
 
 static struct xfrm_state_afinfo xfrm6_state_afinfo = {
 	.family			= AF_INET6,
-	.lock			= RW_LOCK_UNLOCKED,
 	.init_tempsel		= __xfrm6_init_tempsel,
 	.state_lookup		= __xfrm6_state_lookup,
 	.find_acq		= __xfrm6_find_acq,
diff --git a/net/ipx/ipx_route.c b/net/ipx/ipx_route.c
index a394c6f..bba3431 100644
--- a/net/ipx/ipx_route.c
+++ b/net/ipx/ipx_route.c
@@ -238,7 +238,7 @@
 	}	
 
 	/* Apply checksum. Not allowed on 802.3 links. */
-	if (sk->sk_no_check || intrfc->if_dlink_type == IPX_FRAME_8023)
+	if (sk->sk_no_check || intrfc->if_dlink_type == htons(IPX_FRAME_8023))
 		ipx->ipx_checksum = 0xFFFF;
 	else
 		ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index c19e9ce..57ea160 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -44,6 +44,8 @@
 #include <net/irda/irlmp.h>
 #include <net/irda/irlmp_frame.h>
 
+#include <asm/unaligned.h>
+
 static __u8 irlmp_find_free_slsap(void);
 static int irlmp_slsap_inuse(__u8 slsap_sel);
 
@@ -840,6 +842,7 @@
 void irlmp_do_discovery(int nslots)
 {
 	struct lap_cb *lap;
+	__u16 *data_hintsp;
 
 	/* Make sure the value is sane */
 	if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
@@ -849,7 +852,8 @@
 	}
 
 	/* Construct new discovery info to be used by IrLAP, */
-	u16ho(irlmp->discovery_cmd.data.hints) = irlmp->hints.word;
+	data_hintsp = (__u16 *) irlmp->discovery_cmd.data.hints;
+	put_unaligned(irlmp->hints.word, data_hintsp);
 
 	/*
 	 *  Set character set for device name (we use ASCII), and
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 8595822..d5e2121 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1454,21 +1454,23 @@
 	if (x == NULL)
 		return -ESRCH;
 
+	if ((err = security_xfrm_state_delete(x)))
+		goto out;
+
 	if (xfrm_state_kern(x)) {
-		xfrm_state_put(x);
-		return -EPERM;
+		err = -EPERM;
+		goto out;
 	}
 	
 	err = xfrm_state_delete(x);
-	if (err < 0) {
-		xfrm_state_put(x);
-		return err;
-	}
+	if (err < 0)
+		goto out;
 
 	c.seq = hdr->sadb_msg_seq;
 	c.pid = hdr->sadb_msg_pid;
 	c.event = XFRM_MSG_DELSA;
 	km_state_notify(x, &c);
+out:
 	xfrm_state_put(x);
 
 	return err;
@@ -2274,11 +2276,14 @@
 
 	err = 0;
 
+	if ((err = security_xfrm_policy_delete(xp)))
+		goto out;
 	c.seq = hdr->sadb_msg_seq;
 	c.pid = hdr->sadb_msg_pid;
 	c.event = XFRM_MSG_DELPOLICY;
 	km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
 
+out:
 	xfrm_pol_put(xp);
 	return err;
 }
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 5a04db7..75c9b14 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -674,7 +674,7 @@
 
 	lock_sock(sk);
 	copied = -ENOTCONN;
-	if (sk->sk_state == TCP_LISTEN)
+	if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
 		goto out;
 
 	timeo = sock_rcvtimeo(sk, nonblock);
@@ -733,7 +733,7 @@
 			if (sk->sk_shutdown & RCV_SHUTDOWN)
 				break;
 
-			if (sk->sk_state == TCP_CLOSE) {
+			if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSE) {
 				if (!sock_flag(sk, SOCK_DONE)) {
 					/*
 					 * This occurs when user tries to read
@@ -789,7 +789,7 @@
 			continue;
 
 		if (!(flags & MSG_PEEK)) {
-			sk_eat_skb(sk, skb);
+			sk_eat_skb(sk, skb, 0);
 			*seq = 0;
 		}
 	} while (len > 0);
diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c
index ba90f7f..5ae47be 100644
--- a/net/llc/llc_if.c
+++ b/net/llc/llc_if.c
@@ -26,8 +26,6 @@
 #include <net/llc_c_st.h>
 #include <net/tcp_states.h>
 
-u8 llc_mac_null_var[IFHWADDRLEN];
-
 /**
  *	llc_build_and_send_pkt - Connection data sending for upper layers.
  *	@sk: connection
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index d62e0f9..94d2368 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -142,6 +142,8 @@
 	struct llc_sap *sap;
 	struct llc_pdu_sn *pdu;
 	int dest;
+	int (*rcv)(struct sk_buff *, struct net_device *,
+		   struct packet_type *, struct net_device *);
 
 	/*
 	 * When the interface is in promisc. mode, drop all the crap that it
@@ -169,9 +171,11 @@
 	 * First the upper layer protocols that don't need the full
 	 * LLC functionality
 	 */
-	if (sap->rcv_func) {
-		sap->rcv_func(skb, dev, pt, orig_dev);
-		goto out_put;
+	rcv = rcu_dereference(sap->rcv_func);
+	if (rcv) {
+ 		struct sk_buff *cskb = skb_clone(skb, GFP_ATOMIC);
+ 		if (cskb)
+ 			rcv(cskb, dev, pt, orig_dev);
 	}
 	dest = llc_pdu_type(skb);
 	if (unlikely(!dest || !llc_type_handlers[dest - 1]))
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 4029cee..20c4eb5 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -282,7 +282,7 @@
  *	mac, and local sap. Returns pointer for socket found, %NULL otherwise.
  */
 static struct sock *llc_lookup_dgram(struct llc_sap *sap,
-				     struct llc_addr *laddr)
+				     const struct llc_addr *laddr)
 {
 	struct sock *rc;
 	struct hlist_node *node;
@@ -304,19 +304,62 @@
 	return rc;
 }
 
+/**
+ * 	llc_sap_mcast - Deliver multicast PDU's to all matching datagram sockets.
+ *	@sap: SAP
+ *	@laddr: address of local LLC (MAC + SAP)
+ *
+ *	Search socket list of the SAP and finds connections with same sap.
+ *	Deliver clone to each.
+ */
+static void llc_sap_mcast(struct llc_sap *sap,
+			  const struct llc_addr *laddr,
+			  struct sk_buff *skb)
+{
+	struct sock *sk;
+	struct hlist_node *node;
+
+	read_lock_bh(&sap->sk_list.lock);
+	sk_for_each(sk, node, &sap->sk_list.list) {
+		struct llc_sock *llc = llc_sk(sk);
+		struct sk_buff *skb1;
+
+		if (sk->sk_type != SOCK_DGRAM)
+			continue;
+
+		if (llc->laddr.lsap != laddr->lsap)
+			continue;
+
+		skb1 = skb_clone(skb, GFP_ATOMIC);
+		if (!skb1)
+			break;
+
+		sock_hold(sk);
+		skb_set_owner_r(skb1, sk);
+		llc_sap_rcv(sap, skb1);
+		sock_put(sk);
+	}
+	read_unlock_bh(&sap->sk_list.lock);
+}
+
+
 void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
 {
 	struct llc_addr laddr;
-	struct sock *sk;
 
 	llc_pdu_decode_da(skb, laddr.mac);
 	llc_pdu_decode_dsap(skb, &laddr.lsap);
 
-	sk = llc_lookup_dgram(sap, &laddr);
-	if (sk) {
-		skb_set_owner_r(skb, sk);
-		llc_sap_rcv(sap, skb);
-		sock_put(sk);
-	} else
+	if (llc_mac_multicast(laddr.mac)) {
+		llc_sap_mcast(sap, &laddr, skb);
 		kfree_skb(skb);
+	} else {
+		struct sock *sk = llc_lookup_dgram(sap, &laddr);
+		if (sk) {
+			skb_set_owner_r(skb, sk);
+			llc_sap_rcv(sap, skb);
+			sock_put(sk);
+		} else
+			kfree_skb(skb);
+	}
 }
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index e2893ef..b1622b7 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -60,6 +60,18 @@
 	  of packets, but this mark value is kept in the conntrack session
 	  instead of the individual packets.
 
+config NF_CONNTRACK_SECMARK
+	bool  'Connection tracking security mark support'
+	depends on NF_CONNTRACK && NETWORK_SECMARK
+	help
+	  This option enables security markings to be applied to
+	  connections.  Typically they are copied to connections from
+	  packets using the CONNSECMARK target and copied back from
+	  connections to packets with the same target, with the packets
+	  being originally labeled via SECMARK.
+
+	  If unsure, say 'N'.
+
 config NF_CONNTRACK_EVENTS
 	bool "Connection tracking events (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && NF_CONNTRACK
@@ -174,6 +186,26 @@
 	  If you want to compile it as a module, say M here and read
 	  <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+config NETFILTER_XT_TARGET_SECMARK
+	tristate '"SECMARK" target support'
+	depends on NETFILTER_XTABLES && NETWORK_SECMARK
+	help
+	  The SECMARK target allows security marking of network
+	  packets, for use with security subsystems.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
+config NETFILTER_XT_TARGET_CONNSECMARK
+	tristate '"CONNSECMARK" target support'
+	depends on NETFILTER_XTABLES && (NF_CONNTRACK_SECMARK || IP_NF_CONNTRACK_SECMARK)
+	help
+	  The CONNSECMARK target copies security markings from packets
+	  to connections, and restores security markings from connections
+	  to packets (if the packets are not already marked).  This would
+	  normally be used in conjunction with the SECMARK target.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+
 config NETFILTER_XT_MATCH_COMMENT
 	tristate  '"comment" match support'
 	depends on NETFILTER_XTABLES
@@ -329,6 +361,16 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_QUOTA
+	tristate '"quota" match support'
+	depends on NETFILTER_XTABLES
+	help
+	  This option adds a `quota' match, which allows to match on a
+	  byte counter.
+
+	  If you want to compile it as a module, say M here and read
+	  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 config NETFILTER_XT_MATCH_REALM
 	tristate  '"realm" match support'
 	depends on NETFILTER_XTABLES
@@ -365,6 +407,12 @@
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NETFILTER_XT_MATCH_STATISTIC
+	tristate '"statistic" match support'
+	depends on NETFILTER_XTABLES
+	help
+	  statistic module
+
 config NETFILTER_XT_MATCH_STRING
 	tristate  '"string" match support'
 	depends on NETFILTER_XTABLES
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 95b7e41..6fa4b75 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -28,6 +28,8 @@
 obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
+obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
 
 # matches
 obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
@@ -44,9 +46,11 @@
 obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_POLICY) += xt_policy.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
 obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index f9b83f9..cd299f4 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -990,6 +990,9 @@
 #ifdef CONFIG_NF_CONNTRACK_MARK
 		conntrack->mark = exp->master->mark;
 #endif
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+		conntrack->secmark = exp->master->secmark;
+#endif
 		nf_conntrack_get(&conntrack->master->ct_general);
 		NF_CT_STAT_INC(expect_new);
 	} else
@@ -1396,6 +1399,12 @@
 
 	write_lock_bh(&nf_conntrack_lock);
 
+	/* Only update if this is not a fixed timeout */
+	if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) {
+		write_unlock_bh(&nf_conntrack_lock);
+		return;
+	}
+
 	/* If not in hash table, timer will not be active yet */
 	if (!nf_ct_is_confirmed(ct)) {
 		ct->timeout.expires = extra_jiffies;
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index e38a4b5..11d3be2 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -67,37 +67,48 @@
 			     char);
 
 static struct ftp_search {
-	enum ip_conntrack_dir dir;
 	const char *pattern;
 	size_t plen;
 	char skip;
 	char term;
 	enum ip_ct_ftp_type ftptype;
 	int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char);
-} search[] = {
-	{
-		IP_CT_DIR_ORIGINAL,
-		"PORT", sizeof("PORT") - 1, ' ', '\r',
-		IP_CT_FTP_PORT,
-		try_rfc959,
+} search[IP_CT_DIR_MAX][2] = {
+	[IP_CT_DIR_ORIGINAL] = {
+		{
+			.pattern	= "PORT",
+			.plen		= sizeof("PORT") - 1,
+			.skip		= ' ',
+			.term		= '\r',
+			.ftptype	= IP_CT_FTP_PORT,
+			.getnum		= try_rfc959,
+		},
+		{
+			.pattern	= "EPRT",
+			.plen		= sizeof("EPRT") - 1,
+			.skip		= ' ',
+			.term		= '\r',
+			.ftptype	= IP_CT_FTP_EPRT,
+			.getnum		= try_eprt,
+		},
 	},
-	{
-		IP_CT_DIR_REPLY,
-		"227 ", sizeof("227 ") - 1, '(', ')',
-		IP_CT_FTP_PASV,
-		try_rfc959,
-	},
-	{
-		IP_CT_DIR_ORIGINAL,
-		"EPRT", sizeof("EPRT") - 1, ' ', '\r',
-		IP_CT_FTP_EPRT,
-		try_eprt,
-	},
-	{
-		IP_CT_DIR_REPLY,
-		"229 ", sizeof("229 ") - 1, '(', ')',
-		IP_CT_FTP_EPSV,
-		try_epsv_response,
+	[IP_CT_DIR_REPLY] = {
+		{
+			.pattern	= "227 ",
+			.plen		= sizeof("227 ") - 1,
+			.skip		= '(',
+			.term		= ')',
+			.ftptype	= IP_CT_FTP_PASV,
+			.getnum		= try_rfc959,
+		},
+		{
+			.pattern	= "229 ",
+			.plen		= sizeof("229 ") - 1,
+			.skip		= '(',
+			.term		= ')',
+			.ftptype	= IP_CT_FTP_EPSV,
+			.getnum		= try_epsv_response,
+		},
 	},
 };
 
@@ -492,17 +503,15 @@
 	memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
 	       sizeof(cmd.u3.all));
 
-	for (i = 0; i < ARRAY_SIZE(search); i++) {
-		if (search[i].dir != dir) continue;
-
+	for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
 		found = find_pattern(fb_ptr, datalen,
-				     search[i].pattern,
-				     search[i].plen,
-				     search[i].skip,
-				     search[i].term,
+				     search[dir][i].pattern,
+				     search[dir][i].plen,
+				     search[dir][i].skip,
+				     search[dir][i].term,
 				     &matchoff, &matchlen,
 				     &cmd,
-				     search[i].getnum);
+				     search[dir][i].getnum);
 		if (found) break;
 	}
 	if (found == -1) {
@@ -512,7 +521,7 @@
 		   this case. */
 		if (net_ratelimit())
 			printk("conntrack_ftp: partial %s %u+%u\n",
-			       search[i].pattern,
+			       search[dir][i].pattern,
 			       ntohl(th->seq), datalen);
 		ret = NF_DROP;
 		goto out;
@@ -597,7 +606,7 @@
 	/* Now, NAT might want to mangle the packet, and register the
 	 * (possibly changed) expectation itself. */
 	if (nf_nat_ftp_hook)
-		ret = nf_nat_ftp_hook(pskb, ctinfo, search[i].ftptype,
+		ret = nf_nat_ftp_hook(pskb, ctinfo, search[dir][i].ftptype,
 				      matchoff, matchlen, exp, &seq);
 	else {
 		/* Can't expect this?  Best to drop packet now. */
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index bd10eb9..b8c7c56 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -407,6 +407,8 @@
 
 static int ctnetlink_done(struct netlink_callback *cb)
 {
+	if (cb->args[1])
+		nf_ct_put((struct nf_conn *)cb->args[1]);
 	DEBUGP("entered %s\n", __FUNCTION__);
 	return 0;
 }
@@ -416,10 +418,9 @@
 static int
 ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct nf_conn *ct = NULL;
+	struct nf_conn *ct, *last;
 	struct nf_conntrack_tuple_hash *h;
 	struct list_head *i;
-	u_int32_t *id = (u_int32_t *) &cb->args[1];
 	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
 	u_int8_t l3proto = nfmsg->nfgen_family;
 
@@ -427,7 +428,9 @@
 			cb->args[0], *id);
 
 	read_lock_bh(&nf_conntrack_lock);
-	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++, *id = 0) {
+	for (; cb->args[0] < nf_conntrack_htable_size; cb->args[0]++) {
+restart:
+		last = (struct nf_conn *)cb->args[1];
 		list_for_each_prev(i, &nf_conntrack_hash[cb->args[0]]) {
 			h = (struct nf_conntrack_tuple_hash *) i;
 			if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
@@ -438,17 +441,30 @@
 			 * then dump everything. */
 			if (l3proto && L3PROTO(ct) != l3proto)
 				continue;
-			if (ct->id <= *id)
-				continue;
+			if (last != NULL) {
+				if (ct == last) {
+					nf_ct_put(last);
+					cb->args[1] = 0;
+					last = NULL;
+				} else
+					continue;
+			}
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
 		                        	cb->nlh->nlmsg_seq,
 						IPCTNL_MSG_CT_NEW,
-						1, ct) < 0)
+						1, ct) < 0) {
+				nf_conntrack_get(&ct->ct_general);
+				cb->args[1] = (unsigned long)ct;
 				goto out;
-			*id = ct->id;
+			}
+		}
+		if (last != NULL) {
+			nf_ct_put(last);
+			cb->args[1] = 0;
+			goto restart;
 		}
 	}
-out:	
+out:
 	read_unlock_bh(&nf_conntrack_lock);
 
 	DEBUGP("leaving, last bucket=%lu id=%u\n", cb->args[0], *id);
@@ -641,7 +657,7 @@
 };
 
 static inline int
-ctnetlink_parse_nat(struct nfattr *cda[],
+ctnetlink_parse_nat(struct nfattr *nat,
 		    const struct nf_conn *ct, struct ip_nat_range *range)
 {
 	struct nfattr *tb[CTA_NAT_MAX];
@@ -651,7 +667,7 @@
 
 	memset(range, 0, sizeof(*range));
 	
-	nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]);
+	nfattr_parse_nested(tb, CTA_NAT_MAX, nat);
 
 	if (nfattr_bad_size(tb, CTA_NAT_MAX, cta_min_nat))
 		return -EINVAL;
@@ -866,39 +882,30 @@
 		/* ASSURED bit can only be set */
 		return -EINVAL;
 
-	if (cda[CTA_NAT-1]) {
+	if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
 #ifndef CONFIG_IP_NF_NAT_NEEDED
 		return -EINVAL;
 #else
-		unsigned int hooknum;
 		struct ip_nat_range range;
 
-		if (ctnetlink_parse_nat(cda, ct, &range) < 0)
-			return -EINVAL;
-
-		DEBUGP("NAT: %u.%u.%u.%u-%u.%u.%u.%u:%u-%u\n", 
-		       NIPQUAD(range.min_ip), NIPQUAD(range.max_ip),
-		       htons(range.min.all), htons(range.max.all));
-		
-		/* This is tricky but it works. ip_nat_setup_info needs the
-		 * hook number as parameter, so let's do the correct 
-		 * conversion and run away */
-		if (status & IPS_SRC_NAT_DONE)
-			hooknum = NF_IP_POST_ROUTING; /* IP_NAT_MANIP_SRC */
-		else if (status & IPS_DST_NAT_DONE)
-			hooknum = NF_IP_PRE_ROUTING;  /* IP_NAT_MANIP_DST */
-		else 
-			return -EINVAL; /* Missing NAT flags */
-
-		DEBUGP("NAT status: %lu\n", 
-		       status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
-		
-		if (ip_nat_initialized(ct, HOOK2MANIP(hooknum)))
-			return -EEXIST;
-		ip_nat_setup_info(ct, &range, hooknum);
-
-                DEBUGP("NAT status after setup_info: %lu\n",
-                       ct->status & (IPS_NAT_MASK | IPS_NAT_DONE_MASK));
+		if (cda[CTA_NAT_DST-1]) {
+			if (ctnetlink_parse_nat(cda[CTA_NAT_DST-1], ct,
+						&range) < 0)
+				return -EINVAL;
+			if (ip_nat_initialized(ct,
+					       HOOK2MANIP(NF_IP_PRE_ROUTING)))
+				return -EEXIST;
+			ip_nat_setup_info(ct, &range, hooknum);
+		}
+		if (cda[CTA_NAT_SRC-1]) {
+			if (ctnetlink_parse_nat(cda[CTA_NAT_SRC-1], ct,
+						&range) < 0)
+				return -EINVAL;
+			if (ip_nat_initialized(ct,
+					       HOOK2MANIP(NF_IP_POST_ROUTING)))
+				return -EEXIST;
+			ip_nat_setup_info(ct, &range, hooknum);
+		}
 #endif
 	}
 
@@ -1122,7 +1129,7 @@
 	/* implicit 'else' */
 
 	/* we only allow nat config for new conntracks */
-	if (cda[CTA_NAT-1]) {
+	if (cda[CTA_NAT_SRC-1] || cda[CTA_NAT_DST-1]) {
 		err = -EINVAL;
 		goto out_unlock;
 	}
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 69899f2..12fb7c0 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -828,8 +828,9 @@
 	 * and moreover root might send raw packets.
 	 */
 	/* FIXME: Source route IP option packets --RR */
-	if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
-	     (pf == PF_INET6 && hooknum  == NF_IP6_PRE_ROUTING)) &&
+	if (nf_conntrack_checksum &&
+	    ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+	     (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
 	    nf_checksum(skb, hooknum, dataoff, IPPROTO_TCP, pf)) {
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index d93edbf..ae07ebe 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -134,7 +134,8 @@
 	 * because the semantic of CHECKSUM_HW is different there
 	 * and moreover root might send raw packets.
 	 * FIXME: Source route IP option packets --RR */
-	if (((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
+	if (nf_conntrack_checksum &&
+	    ((pf == PF_INET && hooknum == NF_IP_PRE_ROUTING) ||
 	     (pf == PF_INET6 && hooknum == NF_IP6_PRE_ROUTING)) &&
 	    nf_checksum(skb, hooknum, dataoff, IPPROTO_UDP, pf)) {
 		if (LOG_INVALID(IPPROTO_UDP))
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 408960c..e34c574 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -213,6 +213,11 @@
 		return -ENOSPC;
 #endif
 
+#ifdef CONFIG_NF_CONNTRACK_SECMARK
+	if (seq_printf(s, "secmark=%u ", conntrack->secmark))
+		return -ENOSPC;
+#endif
+
 	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
 		return -ENOSPC;
 	
@@ -455,6 +460,8 @@
 static int log_invalid_proto_min = 0;
 static int log_invalid_proto_max = 255;
 
+int nf_conntrack_checksum = 1;
+
 static struct ctl_table_header *nf_ct_sysctl_header;
 
 static ctl_table nf_ct_sysctl_table[] = {
@@ -483,6 +490,14 @@
 		.proc_handler   = &proc_dointvec,
 	},
 	{
+		.ctl_name	= NET_NF_CONNTRACK_CHECKSUM,
+		.procname	= "nf_conntrack_checksum",
+		.data		= &nf_conntrack_checksum,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
 		.ctl_name	= NET_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT,
 		.procname	= "nf_conntrack_tcp_timeout_syn_sent",
 		.data		= &nf_ct_tcp_timeout_syn_sent,
@@ -851,6 +866,7 @@
 EXPORT_SYMBOL(nf_ct_l3proto_find_get);
 EXPORT_SYMBOL(nf_ct_l3proto_put);
 EXPORT_SYMBOL(nf_ct_l3protos);
+EXPORT_SYMBOL_GPL(nf_conntrack_checksum);
 EXPORT_SYMBOL(nf_conntrack_expect_alloc);
 EXPORT_SYMBOL(nf_conntrack_expect_put);
 EXPORT_SYMBOL(nf_conntrack_expect_related);
diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c
new file mode 100644
index 0000000..8c011e0
--- /dev/null
+++ b/net/netfilter/xt_CONNSECMARK.c
@@ -0,0 +1,155 @@
+/*
+ * This module is used to copy security markings from packets
+ * to connections, and restore security markings from connections
+ * back to packets.  This would normally be performed in conjunction
+ * with the SECMARK target and state match.
+ *
+ * Based somewhat on CONNMARK:
+ *   Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
+ *    by Henrik Nordstrom <hno@marasystems.com>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_CONNSECMARK.h>
+#include <net/netfilter/nf_conntrack_compat.h>
+
+#define PFX "CONNSECMARK: "
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module");
+MODULE_ALIAS("ipt_CONNSECMARK");
+MODULE_ALIAS("ip6t_CONNSECMARK");
+
+/*
+ * If the packet has a security mark and the connection does not, copy
+ * the security mark from the packet to the connection.
+ */
+static void secmark_save(struct sk_buff *skb)
+{
+	if (skb->secmark) {
+		u32 *connsecmark;
+		enum ip_conntrack_info ctinfo;
+
+		connsecmark = nf_ct_get_secmark(skb, &ctinfo);
+		if (connsecmark && !*connsecmark)
+			if (*connsecmark != skb->secmark)
+				*connsecmark = skb->secmark;
+	}
+}
+
+/*
+ * If packet has no security mark, and the connection does, restore the
+ * security mark from the connection to the packet.
+ */
+static void secmark_restore(struct sk_buff *skb)
+{
+	if (!skb->secmark) {
+		u32 *connsecmark;
+		enum ip_conntrack_info ctinfo;
+
+		connsecmark = nf_ct_get_secmark(skb, &ctinfo);
+		if (connsecmark && *connsecmark)
+			if (skb->secmark != *connsecmark)
+				skb->secmark = *connsecmark;
+	}
+}
+
+static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+			   const struct net_device *out, unsigned int hooknum,
+			   const struct xt_target *target,
+			   const void *targinfo, void *userinfo)
+{
+	struct sk_buff *skb = *pskb;
+	const struct xt_connsecmark_target_info *info = targinfo;
+
+	switch (info->mode) {
+	case CONNSECMARK_SAVE:
+		secmark_save(skb);
+		break;
+
+	case CONNSECMARK_RESTORE:
+		secmark_restore(skb);
+		break;
+
+	default:
+		BUG();
+	}
+
+	return XT_CONTINUE;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+		      const struct xt_target *target, void *targinfo,
+		      unsigned int targinfosize, unsigned int hook_mask)
+{
+	struct xt_connsecmark_target_info *info = targinfo;
+
+	switch (info->mode) {
+	case CONNSECMARK_SAVE:
+	case CONNSECMARK_RESTORE:
+		break;
+
+	default:
+		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+		return 0;
+	}
+
+	return 1;
+}
+
+static struct xt_target ipt_connsecmark_reg = {
+	.name		= "CONNSECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_connsecmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET,
+	.revision	= 0,
+};
+
+static struct xt_target ip6t_connsecmark_reg = {
+	.name		= "CONNSECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_connsecmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET6,
+	.revision	= 0,
+};
+
+static int __init xt_connsecmark_init(void)
+{
+	int err;
+
+	need_conntrack();
+
+	err = xt_register_target(&ipt_connsecmark_reg);
+	if (err)
+		return err;
+
+	err = xt_register_target(&ip6t_connsecmark_reg);
+	if (err)
+		xt_unregister_target(&ipt_connsecmark_reg);
+
+	return err;
+}
+
+static void __exit xt_connsecmark_fini(void)
+{
+	xt_unregister_target(&ip6t_connsecmark_reg);
+	xt_unregister_target(&ipt_connsecmark_reg);
+}
+
+module_init(xt_connsecmark_init);
+module_exit(xt_connsecmark_fini);
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
new file mode 100644
index 0000000..c2ce9c4
--- /dev/null
+++ b/net/netfilter/xt_SECMARK.c
@@ -0,0 +1,156 @@
+/*
+ * Module for modifying the secmark field of the skb, for use by
+ * security subsystems.
+ *
+ * Based on the nfmark match by:
+ * (C) 1999-2001 Marc Boucher <marc@mbsi.ca>
+ *
+ * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/selinux.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_SECMARK.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("James Morris <jmorris@redhat.com>");
+MODULE_DESCRIPTION("ip[6]tables SECMARK modification module");
+MODULE_ALIAS("ipt_SECMARK");
+MODULE_ALIAS("ip6t_SECMARK");
+
+#define PFX "SECMARK: "
+
+static u8 mode;
+
+static unsigned int target(struct sk_buff **pskb, const struct net_device *in,
+			   const struct net_device *out, unsigned int hooknum,
+			   const struct xt_target *target,
+			   const void *targinfo, void *userinfo)
+{
+	u32 secmark = 0;
+	const struct xt_secmark_target_info *info = targinfo;
+
+	BUG_ON(info->mode != mode);
+
+	switch (mode) {
+	case SECMARK_MODE_SEL:
+		secmark = info->u.sel.selsid;
+		break;
+
+	default:
+		BUG();
+	}
+
+	if ((*pskb)->secmark != secmark)
+		(*pskb)->secmark = secmark;
+
+	return XT_CONTINUE;
+}
+
+static int checkentry_selinux(struct xt_secmark_target_info *info)
+{
+	int err;
+	struct xt_secmark_target_selinux_info *sel = &info->u.sel;
+
+	err = selinux_string_to_sid(sel->selctx, &sel->selsid);
+	if (err) {
+		if (err == -EINVAL)
+			printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n",
+			       sel->selctx);
+		return 0;
+	}
+
+	if (!sel->selsid) {
+		printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n",
+		       sel->selctx);
+		return 0;
+	}
+
+	err = selinux_relabel_packet_permission(sel->selsid);
+	if (err) {
+		printk(KERN_INFO PFX "unable to obtain relabeling permission\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+static int checkentry(const char *tablename, const void *entry,
+		      const struct xt_target *target, void *targinfo,
+		      unsigned int targinfosize, unsigned int hook_mask)
+{
+	struct xt_secmark_target_info *info = targinfo;
+
+	if (mode && mode != info->mode) {
+		printk(KERN_INFO PFX "mode already set to %hu cannot mix with "
+		       "rules for mode %hu\n", mode, info->mode);
+		return 0;
+	}
+
+	switch (info->mode) {
+	case SECMARK_MODE_SEL:
+		if (!checkentry_selinux(info))
+			return 0;
+		break;
+
+	default:
+		printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode);
+		return 0;
+	}
+
+	if (!mode)
+		mode = info->mode;
+	return 1;
+}
+
+static struct xt_target ipt_secmark_reg = {
+	.name		= "SECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_secmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET,
+	.revision	= 0,
+};
+
+static struct xt_target ip6t_secmark_reg = {
+	.name		= "SECMARK",
+	.target		= target,
+	.targetsize	= sizeof(struct xt_secmark_target_info),
+	.table		= "mangle",
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE,
+	.family		= AF_INET6,
+	.revision	= 0,
+};
+
+static int __init xt_secmark_init(void)
+{
+	int err;
+
+	err = xt_register_target(&ipt_secmark_reg);
+	if (err)
+		return err;
+
+	err = xt_register_target(&ip6t_secmark_reg);
+	if (err)
+		xt_unregister_target(&ipt_secmark_reg);
+
+	return err;
+}
+
+static void __exit xt_secmark_fini(void)
+{
+	xt_unregister_target(&ip6t_secmark_reg);
+	xt_unregister_target(&ipt_secmark_reg);
+}
+
+module_init(xt_secmark_init);
+module_exit(xt_secmark_fini);
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index dc26a27..56324c8a 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -58,7 +58,7 @@
 	   unsigned int matchsize,
 	   unsigned int hook_mask)
 {
-	struct xt_connmark_info *cm = (struct xt_connmark_info *)matchinfo;
+	struct xt_connmark_info *cm = matchinfo;
 
 	if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) {
 		printk(KERN_WARNING "connmark: only support 32bit mark\n");
diff --git a/net/netfilter/xt_dccp.c b/net/netfilter/xt_dccp.c
index dfb10b6..2e2f825 100644
--- a/net/netfilter/xt_dccp.c
+++ b/net/netfilter/xt_dccp.c
@@ -101,8 +101,7 @@
       unsigned int protoff,
       int *hotdrop)
 {
-	const struct xt_dccp_info *info = 
-				(const struct xt_dccp_info *)matchinfo;
+	const struct xt_dccp_info *info = matchinfo;
 	struct dccp_hdr _dh, *dh;
 
 	if (offset)
diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
index 8b385a3..876bc57 100644
--- a/net/netfilter/xt_mark.c
+++ b/net/netfilter/xt_mark.c
@@ -42,7 +42,7 @@
            unsigned int matchsize,
            unsigned int hook_mask)
 {
-	struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo;
+	const struct xt_mark_info *minfo = matchinfo;
 
 	if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) {
 		printk(KERN_WARNING "mark: only supports 32bit mark\n");
diff --git a/net/netfilter/xt_multiport.c b/net/netfilter/xt_multiport.c
index b56cd2b..1ff0a25 100644
--- a/net/netfilter/xt_multiport.c
+++ b/net/netfilter/xt_multiport.c
@@ -1,4 +1,4 @@
-/* Kernel module to match one of a list of TCP/UDP ports: ports are in
+/* Kernel module to match one of a list of TCP/UDP/SCTP/DCCP ports: ports are in
    the same place so we can treat them as equal. */
 
 /* (C) 1999-2001 Paul `Rusty' Russell
@@ -160,8 +160,9 @@
       u_int8_t match_flags,
       u_int8_t count)
 {
-	/* Must specify proto == TCP/UDP, no unknown flags or bad count */
-	return (proto == IPPROTO_TCP || proto == IPPROTO_UDP)
+	/* Must specify supported protocol, no unknown flags or bad count */
+	return (proto == IPPROTO_TCP || proto == IPPROTO_UDP
+		|| proto == IPPROTO_SCTP || proto == IPPROTO_DCCP)
 		&& !(ip_invflags & XT_INV_PROTO)
 		&& (match_flags == XT_MULTIPORT_SOURCE
 		    || match_flags == XT_MULTIPORT_DESTINATION
diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c
new file mode 100644
index 0000000..4cdba74
--- /dev/null
+++ b/net/netfilter/xt_quota.c
@@ -0,0 +1,96 @@
+/*
+ * netfilter module to enforce network quotas
+ *
+ * Sam Johnston <samj@samj.net>
+ */
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_quota.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sam Johnston <samj@samj.net>");
+
+static DEFINE_SPINLOCK(quota_lock);
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in, const struct net_device *out,
+      const struct xt_match *match, const void *matchinfo,
+      int offset, unsigned int protoff, int *hotdrop)
+{
+	struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master;
+	int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0;
+
+	spin_lock_bh(&quota_lock);
+	if (q->quota >= skb->len) {
+		q->quota -= skb->len;
+		ret ^= 1;
+	} else {
+	        /* we do not allow even small packets from now on */
+	        q->quota = 0;
+	}
+	spin_unlock_bh(&quota_lock);
+
+	return ret;
+}
+
+static int
+checkentry(const char *tablename, const void *entry,
+	   const struct xt_match *match, void *matchinfo,
+	   unsigned int matchsize, unsigned int hook_mask)
+{
+	struct xt_quota_info *q = (struct xt_quota_info *)matchinfo;
+
+	if (q->flags & ~XT_QUOTA_MASK)
+		return 0;
+	/* For SMP, we only want to use one set of counters. */
+	q->master = q;
+	return 1;
+}
+
+static struct xt_match quota_match = {
+	.name		= "quota",
+	.family		= AF_INET,
+	.match		= match,
+	.matchsize	= sizeof(struct xt_quota_info),
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE
+};
+
+static struct xt_match quota_match6 = {
+	.name		= "quota",
+	.family		= AF_INET6,
+	.match		= match,
+	.matchsize	= sizeof(struct xt_quota_info),
+	.checkentry	= checkentry,
+	.me		= THIS_MODULE
+};
+
+static int __init xt_quota_init(void)
+{
+	int ret;
+
+	ret = xt_register_match(&quota_match);
+	if (ret)
+		goto err1;
+	ret = xt_register_match(&quota_match6);
+	if (ret)
+		goto err2;
+	return ret;
+
+err2:
+	xt_unregister_match(&quota_match);
+err1:
+	return ret;
+}
+
+static void __exit xt_quota_fini(void)
+{
+	xt_unregister_match(&quota_match6);
+	xt_unregister_match(&quota_match);
+}
+
+module_init(xt_quota_init);
+module_exit(xt_quota_fini);
diff --git a/net/netfilter/xt_sctp.c b/net/netfilter/xt_sctp.c
index 34bd872..9316c75 100644
--- a/net/netfilter/xt_sctp.c
+++ b/net/netfilter/xt_sctp.c
@@ -62,7 +62,7 @@
 
 	do {
 		sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
-		if (sch == NULL) {
+		if (sch == NULL || sch->length == 0) {
 			duprintf("Dropping invalid SCTP packet.\n");
 			*hotdrop = 1;
 			return 0;
@@ -129,11 +129,9 @@
       unsigned int protoff,
       int *hotdrop)
 {
-	const struct xt_sctp_info *info;
+	const struct xt_sctp_info *info = matchinfo;
 	sctp_sctphdr_t _sh, *sh;
 
-	info = (const struct xt_sctp_info *)matchinfo;
-
 	if (offset) {
 		duprintf("Dropping non-first fragment.. FIXME\n");
 		return 0;
diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c
new file mode 100644
index 0000000..de1037f
--- /dev/null
+++ b/net/netfilter/xt_statistic.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2006 Patrick McHardy <kaber@trash.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on ipt_random and ipt_nth by Fabrice MARIE <fabrice@netfilter.org>.
+ */
+
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/skbuff.h>
+#include <linux/net.h>
+
+#include <linux/netfilter/xt_statistic.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
+MODULE_DESCRIPTION("xtables statistical match module");
+MODULE_ALIAS("ipt_statistic");
+MODULE_ALIAS("ip6t_statistic");
+
+static DEFINE_SPINLOCK(nth_lock);
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in, const struct net_device *out,
+      const struct xt_match *match, const void *matchinfo,
+      int offset, unsigned int protoff, int *hotdrop)
+{
+	struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+	int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0;
+
+	switch (info->mode) {
+	case XT_STATISTIC_MODE_RANDOM:
+		if ((net_random() & 0x7FFFFFFF) < info->u.random.probability)
+			ret ^= 1;
+		break;
+	case XT_STATISTIC_MODE_NTH:
+		info = info->master;
+		spin_lock_bh(&nth_lock);
+		if (info->u.nth.count++ == info->u.nth.every) {
+			info->u.nth.count = 0;
+			ret ^= 1;
+		}
+		spin_unlock_bh(&nth_lock);
+		break;
+	}
+
+	return ret;
+}
+
+static int
+checkentry(const char *tablename, const void *entry,
+	   const struct xt_match *match, void *matchinfo,
+	   unsigned int matchsize, unsigned int hook_mask)
+{
+	struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo;
+
+	if (info->mode > XT_STATISTIC_MODE_MAX ||
+	    info->flags & ~XT_STATISTIC_MASK)
+		return 0;
+	info->master = info;
+	return 1;
+}
+
+static struct xt_match statistic_match = {
+	.name		= "statistic",
+	.match		= match,
+	.matchsize	= sizeof(struct xt_statistic_info),
+	.checkentry	= checkentry,
+	.family		= AF_INET,
+	.me		= THIS_MODULE,
+};
+
+static struct xt_match statistic_match6 = {
+	.name		= "statistic",
+	.match		= match,
+	.matchsize	= sizeof(struct xt_statistic_info),
+	.checkentry	= checkentry,
+	.family		= AF_INET6,
+	.me		= THIS_MODULE,
+};
+
+static int __init xt_statistic_init(void)
+{
+	int ret;
+
+	ret = xt_register_match(&statistic_match);
+	if (ret)
+		goto err1;
+
+	ret = xt_register_match(&statistic_match6);
+	if (ret)
+		goto err2;
+	return ret;
+err2:
+	xt_unregister_match(&statistic_match);
+err1:
+	return ret;
+}
+
+static void __exit xt_statistic_fini(void)
+{
+	xt_unregister_match(&statistic_match6);
+	xt_unregister_match(&statistic_match);
+}
+
+module_init(xt_statistic_init);
+module_exit(xt_statistic_fini);
diff --git a/net/netfilter/xt_string.c b/net/netfilter/xt_string.c
index 79d9ea6..0ebb6ac 100644
--- a/net/netfilter/xt_string.c
+++ b/net/netfilter/xt_string.c
@@ -30,8 +30,8 @@
 		 unsigned int protoff,
 		 int *hotdrop)
 {
+	const struct xt_string_info *conf = matchinfo;
 	struct ts_state state;
-	struct xt_string_info *conf = (struct xt_string_info *) matchinfo;
 
 	memset(&state, 0, sizeof(struct ts_state));
 
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index b3b9097..c11737f 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -725,15 +725,17 @@
 	struct nr_node  *nr_node = NULL;
 
 	spin_lock_bh(&nr_neigh_list_lock);
-	nr_neigh_for_each(s, node, &nr_neigh_list)
+	nr_neigh_for_each(s, node, &nr_neigh_list) {
 		if (s->ax25 == ax25) {
 			nr_neigh_hold(s);
 			nr_neigh = s;
 			break;
 		}
+	}
 	spin_unlock_bh(&nr_neigh_list_lock);
 
-	if (nr_neigh == NULL) return;
+	if (nr_neigh == NULL)
+		return;
 
 	nr_neigh->ax25 = NULL;
 	ax25_cb_put(ax25);
@@ -743,11 +745,13 @@
 		return;
 	}
 	spin_lock_bh(&nr_node_list_lock);
-	nr_node_for_each(nr_node, node, &nr_node_list)
+	nr_node_for_each(nr_node, node, &nr_node_list) {
 		nr_node_lock(nr_node);
-		if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh)
+		if (nr_node->which < nr_node->count &&
+		    nr_node->routes[nr_node->which].neighbour == nr_neigh)
 			nr_node->which++;
 		nr_node_unlock(nr_node);
+	}
 	spin_unlock_bh(&nr_node_list_lock);
 	nr_neigh_put(nr_neigh);
 }
diff --git a/net/rxrpc/call.c b/net/rxrpc/call.c
index c4aeb7d..d07122b 100644
--- a/net/rxrpc/call.c
+++ b/net/rxrpc/call.c
@@ -1098,8 +1098,7 @@
 
 		call->app_ready_seq = pmsg->seq;
 		call->app_ready_qty += pmsg->dsize;
-		list_del_init(&pmsg->link);
-		list_add_tail(&pmsg->link, &call->app_readyq);
+		list_move_tail(&pmsg->link, &call->app_readyq);
 	}
 
 	/* see if we've got the last packet yet */
diff --git a/net/rxrpc/connection.c b/net/rxrpc/connection.c
index 0e0a455..573b572 100644
--- a/net/rxrpc/connection.c
+++ b/net/rxrpc/connection.c
@@ -402,8 +402,7 @@
 
 	/* move to graveyard queue */
 	_debug("burying connection: {%08x}", ntohl(conn->conn_id));
-	list_del(&conn->link);
-	list_add_tail(&conn->link, &peer->conn_graveyard);
+	list_move_tail(&conn->link, &peer->conn_graveyard);
 
 	rxrpc_krxtimod_add_timer(&conn->timeout, rxrpc_conn_timeout * HZ);
 
diff --git a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c
index 1aadd02..cea4eb5 100644
--- a/net/rxrpc/krxsecd.c
+++ b/net/rxrpc/krxsecd.c
@@ -160,8 +160,7 @@
 	list_for_each_safe(_p, _n, &rxrpc_krxsecd_initmsgq) {
 		msg = list_entry(_p, struct rxrpc_message, link);
 		if (msg->trans == trans) {
-			list_del(&msg->link);
-			list_add_tail(&msg->link, &tmp);
+			list_move_tail(&msg->link, &tmp);
 			atomic_dec(&rxrpc_krxsecd_qcount);
 		}
 	}
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 138ea92..74d4a1d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -72,9 +72,9 @@
    dev->queue_lock serializes queue accesses for this device
    AND dev->qdisc pointer itself.
 
-   dev->xmit_lock serializes accesses to device driver.
+   netif_tx_lock serializes accesses to device driver.
 
-   dev->queue_lock and dev->xmit_lock are mutually exclusive,
+   dev->queue_lock and netif_tx_lock are mutually exclusive,
    if one is grabbed, another must be free.
  */
 
@@ -90,14 +90,17 @@
    NOTE: Called under dev->queue_lock with locally disabled BH.
 */
 
-int qdisc_restart(struct net_device *dev)
+static inline int qdisc_restart(struct net_device *dev)
 {
 	struct Qdisc *q = dev->qdisc;
 	struct sk_buff *skb;
 
 	/* Dequeue packet */
-	if ((skb = q->dequeue(q)) != NULL) {
+	if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
 		unsigned nolock = (dev->features & NETIF_F_LLTX);
+
+		dev->gso_skb = NULL;
+
 		/*
 		 * When the driver has LLTX set it does its own locking
 		 * in start_xmit. No need to add additional overhead by
@@ -108,7 +111,7 @@
 		 * will be requeued.
 		 */
 		if (!nolock) {
-			if (!spin_trylock(&dev->xmit_lock)) {
+			if (!netif_tx_trylock(dev)) {
 			collision:
 				/* So, someone grabbed the driver. */
 				
@@ -126,8 +129,6 @@
 				__get_cpu_var(netdev_rx_stat).cpu_collision++;
 				goto requeue;
 			}
-			/* Remember that the driver is grabbed by us. */
-			dev->xmit_lock_owner = smp_processor_id();
 		}
 		
 		{
@@ -136,14 +137,11 @@
 
 			if (!netif_queue_stopped(dev)) {
 				int ret;
-				if (netdev_nit)
-					dev_queue_xmit_nit(skb, dev);
 
-				ret = dev->hard_start_xmit(skb, dev);
+				ret = dev_hard_start_xmit(skb, dev);
 				if (ret == NETDEV_TX_OK) { 
 					if (!nolock) {
-						dev->xmit_lock_owner = -1;
-						spin_unlock(&dev->xmit_lock);
+						netif_tx_unlock(dev);
 					}
 					spin_lock(&dev->queue_lock);
 					return -1;
@@ -157,8 +155,7 @@
 			/* NETDEV_TX_BUSY - we need to requeue */
 			/* Release the driver */
 			if (!nolock) { 
-				dev->xmit_lock_owner = -1;
-				spin_unlock(&dev->xmit_lock);
+				netif_tx_unlock(dev);
 			} 
 			spin_lock(&dev->queue_lock);
 			q = dev->qdisc;
@@ -175,7 +172,10 @@
 		 */
 
 requeue:
-		q->ops->requeue(skb, q);
+		if (skb->next)
+			dev->gso_skb = skb;
+		else
+			q->ops->requeue(skb, q);
 		netif_schedule(dev);
 		return 1;
 	}
@@ -183,11 +183,23 @@
 	return q->q.qlen;
 }
 
+void __qdisc_run(struct net_device *dev)
+{
+	if (unlikely(dev->qdisc == &noop_qdisc))
+		goto out;
+
+	while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
+		/* NOTHING */;
+
+out:
+	clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
+}
+
 static void dev_watchdog(unsigned long arg)
 {
 	struct net_device *dev = (struct net_device *)arg;
 
-	spin_lock(&dev->xmit_lock);
+	netif_tx_lock(dev);
 	if (dev->qdisc != &noop_qdisc) {
 		if (netif_device_present(dev) &&
 		    netif_running(dev) &&
@@ -203,7 +215,7 @@
 				dev_hold(dev);
 		}
 	}
-	spin_unlock(&dev->xmit_lock);
+	netif_tx_unlock(dev);
 
 	dev_put(dev);
 }
@@ -227,17 +239,17 @@
 
 static void dev_watchdog_up(struct net_device *dev)
 {
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	__netdev_watchdog_up(dev);
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 }
 
 static void dev_watchdog_down(struct net_device *dev)
 {
-	spin_lock_bh(&dev->xmit_lock);
+	netif_tx_lock_bh(dev);
 	if (del_timer(&dev->watchdog_timer))
 		dev_put(dev);
-	spin_unlock_bh(&dev->xmit_lock);
+	netif_tx_unlock_bh(dev);
 }
 
 void netif_carrier_on(struct net_device *dev)
@@ -579,10 +591,17 @@
 
 	dev_watchdog_down(dev);
 
-	while (test_bit(__LINK_STATE_SCHED, &dev->state))
+	/* Wait for outstanding dev_queue_xmit calls. */
+	synchronize_rcu();
+
+	/* Wait for outstanding qdisc_run calls. */
+	while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
 		yield();
 
-	spin_unlock_wait(&dev->xmit_lock);
+	if (dev->gso_skb) {
+		kfree_skb(dev->gso_skb);
+		dev->gso_skb = NULL;
+	}
 }
 
 void dev_init_scheduler(struct net_device *dev)
@@ -624,6 +643,5 @@
 EXPORT_SYMBOL(qdisc_alloc);
 EXPORT_SYMBOL(qdisc_destroy);
 EXPORT_SYMBOL(qdisc_reset);
-EXPORT_SYMBOL(qdisc_restart);
 EXPORT_SYMBOL(qdisc_lock_tree);
 EXPORT_SYMBOL(qdisc_unlock_tree);
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 79b8ef3..4c16ad5 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -302,20 +302,17 @@
 
 		switch (teql_resolve(skb, skb_res, slave)) {
 		case 0:
-			if (spin_trylock(&slave->xmit_lock)) {
-				slave->xmit_lock_owner = smp_processor_id();
+			if (netif_tx_trylock(slave)) {
 				if (!netif_queue_stopped(slave) &&
 				    slave->hard_start_xmit(skb, slave) == 0) {
-					slave->xmit_lock_owner = -1;
-					spin_unlock(&slave->xmit_lock);
+					netif_tx_unlock(slave);
 					master->slaves = NEXT_SLAVE(q);
 					netif_wake_queue(dev);
 					master->stats.tx_packets++;
 					master->stats.tx_bytes += len;
 					return 0;
 				}
-				slave->xmit_lock_owner = -1;
-				spin_unlock(&slave->xmit_lock);
+				netif_tx_unlock(slave);
 			}
 			if (netif_queue_stopped(dev))
 				busy = 1;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 1662f9c..42b66e74 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -141,7 +141,8 @@
 	__skb_pull(skb, skb->h.raw - skb->data);
 	if (skb->len < sizeof(struct sctphdr))
 		goto discard_it;
-	if (sctp_rcv_checksum(skb) < 0)
+	if ((skb->ip_summed != CHECKSUM_UNNECESSARY) &&
+	    (sctp_rcv_checksum(skb) < 0))
 		goto discard_it;
 
 	skb_pull(skb, sizeof(struct sctphdr));
@@ -170,7 +171,8 @@
 	 * IP broadcast addresses cannot be used in an SCTP transport
 	 * address."
 	 */
-	if (!af->addr_valid(&src, NULL) || !af->addr_valid(&dest, NULL))
+	if (!af->addr_valid(&src, NULL, skb) ||
+	    !af->addr_valid(&dest, NULL, skb))
 		goto discard_it;
 
 	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index c20d282..8ef0807 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -523,7 +523,9 @@
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_sock *sp)
+static int sctp_v6_addr_valid(union sctp_addr *addr,
+			      struct sctp_sock *sp,
+			      const struct sk_buff *skb)
 {
 	int ret = ipv6_addr_type(&addr->v6.sin6_addr);
 
@@ -537,7 +539,7 @@
 		if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
 			return 0;
 		sctp_v6_map_v4(addr);
-		return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp);
+		return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp, skb);
 	}
 
 	/* Is this a non-unicast address */
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 437cba7..cdc5a39 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -295,14 +295,14 @@
 	struct sctp_transport *tp = packet->transport;
 	struct sctp_association *asoc = tp->asoc;
 	struct sctphdr *sh;
-	__u32 crc32;
+	__u32 crc32 = 0;
 	struct sk_buff *nskb;
 	struct sctp_chunk *chunk, *tmp;
 	struct sock *sk;
 	int err = 0;
 	int padding;		/* How much padding do we need?  */
 	__u8 has_data = 0;
-	struct dst_entry *dst;
+	struct dst_entry *dst = tp->dst;
 
 	SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
 
@@ -327,6 +327,19 @@
 	 */
 	skb_set_owner_w(nskb, sk);
 
+	/* The 'obsolete' field of dst is set to 2 when a dst is freed. */
+	if (!dst || (dst->obsolete > 1)) {
+		dst_release(dst);
+		sctp_transport_route(tp, NULL, sctp_sk(sk));
+		if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
+			sctp_assoc_sync_pmtu(asoc);
+		}
+	}
+	nskb->dst = dst_clone(tp->dst);
+	if (!nskb->dst)
+		goto no_route;
+	dst = nskb->dst;
+
 	/* Build the SCTP header.  */
 	sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
 	sh->source = htons(packet->source_port);
@@ -350,7 +363,8 @@
 	 * Note: Adler-32 is no longer applicable, as has been replaced
 	 * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
 	 */
-	crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
+	if (!(dst->dev->features & NETIF_F_NO_CSUM))
+		crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
 
 	/**
 	 * 6.10 Bundling
@@ -402,9 +416,14 @@
 		if (padding)
 			memset(skb_put(chunk->skb, padding), 0, padding);
 
-		crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len),
-					       chunk->skb->data,
-					       chunk->skb->len, crc32);
+		if (dst->dev->features & NETIF_F_NO_CSUM)
+			memcpy(skb_put(nskb, chunk->skb->len),
+			       chunk->skb->data, chunk->skb->len);
+		else
+			crc32 = sctp_update_copy_cksum(skb_put(nskb,
+							chunk->skb->len),
+						chunk->skb->data,
+						chunk->skb->len, crc32);
 
 		SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
 				  "*** Chunk", chunk,
@@ -427,7 +446,8 @@
 	}
 
 	/* Perform final transformation on checksum. */
-	crc32 = sctp_end_cksum(crc32);
+	if (!(dst->dev->features & NETIF_F_NO_CSUM))
+		crc32 = sctp_end_cksum(crc32);
 
 	/* 3) Put the resultant value into the checksum field in the
 	 *    common header, and leave the rest of the bits unchanged.
@@ -477,20 +497,6 @@
 		}
 	}
 
-	dst = tp->dst;
-	/* The 'obsolete' field of dst is set to 2 when a dst is freed. */
-	if (!dst || (dst->obsolete > 1)) {
-		dst_release(dst);
-		sctp_transport_route(tp, NULL, sctp_sk(sk));
-		if (asoc->param_flags & SPP_PMTUD_ENABLE) {
-			sctp_assoc_sync_pmtu(asoc);
-		}
-	}
-
-	nskb->dst = dst_clone(tp->dst);
-	if (!nskb->dst)
-		goto no_route;
-
 	SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
 			  nskb->len);
 
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index f148f95..e5faa35 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1262,6 +1262,7 @@
 			   	if (!tchunk->tsn_gap_acked &&
 				    !tchunk->resent &&
 				    tchunk->rtt_in_progress) {
+					tchunk->rtt_in_progress = 0;
 					rtt = jiffies - tchunk->sent_at;
 					sctp_transport_update_rto(transport,
 								  rtt);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2088aa9..816c033 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -365,12 +365,18 @@
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_sock *sp)
+static int sctp_v4_addr_valid(union sctp_addr *addr,
+			      struct sctp_sock *sp,
+			      const struct sk_buff *skb)
 {
 	/* Is this a non-unicast address or a unusable SCTP address? */
 	if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
 		return 0;
 
+ 	/* Is this a broadcast address? */
+ 	if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
+ 		return 0;
+
 	return 1;
 }
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 5e0de3c..2a87736 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1402,14 +1402,14 @@
 	sg.length = bodysize;
 	key = (char *)ep->secret_key[ep->current_key];
 
-	memset(digest, 0x00, sizeof(digest));
+	memset(digest, 0x00, SCTP_SIGNATURE_SIZE);
 	sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg,
 			 1, digest);
 
 	if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
 		/* Try the previous key. */
 		key = (char *)ep->secret_key[ep->last_key];
-		memset(digest, 0x00, sizeof(digest));
+		memset(digest, 0x00, SCTP_SIGNATURE_SIZE);
 		sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen,
 				 &sg, 1, digest);
 
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 8bc2792..9e58144 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -5293,10 +5293,18 @@
 	 * seems a bit troublesome in that frag_point varies based on
 	 * PMTU.  In cases, such as loopback, this might be a rather
 	 * large spill over.
+	 * NOTE: If we have a full receive buffer here, we only renege if
+	 * our receiver can still make progress without the tsn being
+	 * received. We do this because in the event that the associations
+	 * receive queue is empty we are filling a leading gap, and since
+	 * reneging moves the gap to the end of the tsn stream, we are likely
+	 * to stall again very shortly. Avoiding the renege when we fill a
+	 * leading gap is a good heuristic for avoiding such steady state
+	 * stalls.
 	 */
 	if (!asoc->rwnd || asoc->rwnd_over ||
 	    (datalen > asoc->rwnd + asoc->frag_point) ||
-	    rcvbuf_over) {
+	    (rcvbuf_over && (!skb_queue_len(&sk->sk_receive_queue)))) {
 
 		/* If this is the next TSN, consider reneging to make
 		 * room.   Note: Playing nice with a confused sender.  A
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 174d4d3..b811691c 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -172,7 +172,7 @@
 		return -EINVAL;
 
 	/* Is this a valid SCTP address?  */
-	if (!af->addr_valid(addr, sctp_sk(sk)))
+	if (!af->addr_valid(addr, sctp_sk(sk), NULL))
 		return -EINVAL;
 
 	if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr)))
@@ -2530,8 +2530,32 @@
 
 	/* Set the values to the specific association */
 	if (asoc) {
-		if (assocparams.sasoc_asocmaxrxt != 0)
+		if (assocparams.sasoc_asocmaxrxt != 0) {
+			__u32 path_sum = 0;
+			int   paths = 0;
+			struct list_head *pos;
+			struct sctp_transport *peer_addr;
+
+			list_for_each(pos, &asoc->peer.transport_addr_list) {
+				peer_addr = list_entry(pos,
+						struct sctp_transport,
+						transports);
+				path_sum += peer_addr->pathmaxrxt;
+				paths++;
+			}
+
+			/* Only validate asocmaxrxt if we have more then
+			 * one path/transport.  We do this because path
+			 * retransmissions are only counted when we have more
+			 * then one path.
+			 */
+			if (paths > 1 &&
+			    assocparams.sasoc_asocmaxrxt > path_sum)
+				return -EINVAL;
+
 			asoc->max_retrans = assocparams.sasoc_asocmaxrxt;
+		}
+
 		if (assocparams.sasoc_cookie_life != 0) {
 			asoc->cookie_life.tv_sec =
 					assocparams.sasoc_cookie_life / 1000;
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index ba97f97..ee236784 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -51,6 +51,8 @@
 static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
 				       struct sctp_association *asoc);
 static void sctp_ulpevent_release_data(struct sctp_ulpevent *event);
+static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event);
+
 
 /* Initialize an ULP event from an given skb.  */
 SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
@@ -883,6 +885,7 @@
 static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
 {
 	struct sk_buff *skb, *frag;
+	unsigned int	len;
 
 	/* Current stack structures assume that the rcv buffer is
 	 * per socket.   For UDP style sockets this is not true as
@@ -892,7 +895,7 @@
 	 */
 
 	skb = sctp_event2skb(event);
-	sctp_assoc_rwnd_increase(event->asoc, skb_headlen(skb));
+	len = skb->len;
 
 	if (!skb->data_len)
 		goto done;
@@ -903,7 +906,30 @@
 		 * skb's with only 1 level of fragments, SCTP reassembly can
 		 * increase the levels.
 		 */
-		sctp_ulpevent_release_data(sctp_skb2event(frag));
+		sctp_ulpevent_release_frag_data(sctp_skb2event(frag));
+	}
+
+done:
+	sctp_assoc_rwnd_increase(event->asoc, len);
+	sctp_ulpevent_release_owner(event);
+}
+
+static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
+{
+	struct sk_buff *skb, *frag;
+
+	skb = sctp_event2skb(event);
+
+	if (!skb->data_len)
+		goto done;
+
+	/* Don't forget the fragments. */
+	for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+		/* NOTE:  skb_shinfos are recursive. Although IP returns
+		 * skb's with only 1 level of fragments, SCTP reassembly can
+		 * increase the levels.
+		 */
+		sctp_ulpevent_release_frag_data(sctp_skb2event(frag));
 	}
 
 done:
diff --git a/net/socket.c b/net/socket.c
index 02948b6..565f5e8 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -335,10 +335,11 @@
 	.statfs =	simple_statfs,
 };
 
-static struct super_block *sockfs_get_sb(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
+static int sockfs_get_sb(struct file_system_type *fs_type,
+	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC);
+	return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
+			     mnt);
 }
 
 static struct vfsmount *sock_mnt __read_mostly;
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 129e2bd..b8714a8 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -169,7 +169,7 @@
 	}
 
 	ctx_id->internal_ctx_id = ctx;
-	dprintk("RPC:      Succesfully imported new context.\n");
+	dprintk("RPC:      Successfully imported new context.\n");
 	return 0;
 
 out_err_free_key2:
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c
index f433112..2f31216 100644
--- a/net/sunrpc/auth_gss/gss_krb5_seal.c
+++ b/net/sunrpc/auth_gss/gss_krb5_seal.c
@@ -70,7 +70,7 @@
 # define RPCDBG_FACILITY        RPCDBG_AUTH
 #endif
 
-spinlock_t krb5_seq_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(krb5_seq_lock);
 
 u32
 gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text,
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
index 5bf11cc..3d0432a 100644
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c
@@ -201,7 +201,7 @@
 
 	ctx_id->internal_ctx_id = ctx;
 
-	dprintk("Succesfully imported new spkm context.\n");
+	dprintk("Successfully imported new spkm context.\n");
 	return 0;
 
 out_err_free_key2:
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
index f56767a..2eccffa 100644
--- a/net/sunrpc/auth_null.c
+++ b/net/sunrpc/auth_null.c
@@ -118,6 +118,8 @@
 	.au_cslack	= 4,
 	.au_rslack	= 2,
 	.au_ops		= &authnull_ops,
+	.au_flavor	= RPC_AUTH_NULL,
+	.au_count	= ATOMIC_INIT(0),
 };
 
 static
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
index df14b6b..74c7406 100644
--- a/net/sunrpc/auth_unix.c
+++ b/net/sunrpc/auth_unix.c
@@ -225,6 +225,7 @@
 	.au_cslack	= UNX_WRITESLACK,
 	.au_rslack	= 2,			/* assume AUTH_NULL verf */
 	.au_ops		= &authunix_ops,
+	.au_flavor	= RPC_AUTH_UNIX,
 	.au_count	= ATOMIC_INIT(0),
 	.au_credcache	= &unix_cred_cache,
 };
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index cc673dd..dafe793 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -439,7 +439,7 @@
 {
 	int err;
 
-	err = simple_pin_fs("rpc_pipefs", &rpc_mount, &rpc_mount_count);
+	err = simple_pin_fs(&rpc_pipe_fs_type, &rpc_mount, &rpc_mount_count);
 	if (err != 0)
 		return ERR_PTR(err);
 	return rpc_mount;
@@ -815,11 +815,11 @@
 	return -ENOMEM;
 }
 
-static struct super_block *
+static int
 rpc_get_sb(struct file_system_type *fs_type,
-		int flags, const char *dev_name, void *data)
+		int flags, const char *dev_name, void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, rpc_fill_super);
+	return get_sb_single(fs_type, flags, data, rpc_fill_super, mnt);
 }
 
 static struct file_system_type rpc_pipe_fs_type = {
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index ca4bfa5..49174f0 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -568,8 +568,7 @@
  *
  * Moves data beyond the current pointer position from the XDR head[] buffer
  * into the page list. Any data that lies beyond current position + "len"
- * bytes is moved into the XDR tail[]. The current pointer is then
- * repositioned at the beginning of the XDR tail.
+ * bytes is moved into the XDR tail[].
  */
 void xdr_read_pages(struct xdr_stream *xdr, unsigned int len)
 {
@@ -606,6 +605,31 @@
 }
 EXPORT_SYMBOL(xdr_read_pages);
 
+/**
+ * xdr_enter_page - decode data from the XDR page
+ * @xdr: pointer to xdr_stream struct
+ * @len: number of bytes of page data
+ *
+ * Moves data beyond the current pointer position from the XDR head[] buffer
+ * into the page list. Any data that lies beyond current position + "len"
+ * bytes is moved into the XDR tail[]. The current pointer is then
+ * repositioned at the beginning of the first XDR page.
+ */
+void xdr_enter_page(struct xdr_stream *xdr, unsigned int len)
+{
+	char * kaddr = page_address(xdr->buf->pages[0]);
+	xdr_read_pages(xdr, len);
+	/*
+	 * Position current pointer at beginning of tail, and
+	 * set remaining message length.
+	 */
+	if (len > PAGE_CACHE_SIZE - xdr->buf->page_base)
+		len = PAGE_CACHE_SIZE - xdr->buf->page_base;
+	xdr->p = (uint32_t *)(kaddr + xdr->buf->page_base);
+	xdr->end = (uint32_t *)((char *)xdr->p + len);
+}
+EXPORT_SYMBOL(xdr_enter_page);
+
 static struct kvec empty_iov = {.iov_base = NULL, .iov_len = 0};
 
 void
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 4dd5b3c..02060d0 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -41,7 +41,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/workqueue.h>
-#include <linux/random.h>
+#include <linux/net.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/metrics.h>
@@ -830,7 +830,7 @@
 
 static inline void xprt_init_xid(struct rpc_xprt *xprt)
 {
-	get_random_bytes(&xprt->xid, sizeof(xprt->xid));
+	xprt->xid = net_random();
 }
 
 static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4b4e7df..21006b1 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -930,6 +930,13 @@
 	xprt_adjust_cwnd(task, -ETIMEDOUT);
 }
 
+static unsigned short xs_get_random_port(void)
+{
+	unsigned short range = xprt_max_resvport - xprt_min_resvport;
+	unsigned short rand = (unsigned short) net_random() % range;
+	return rand + xprt_min_resvport;
+}
+
 /**
  * xs_set_port - reset the port number in the remote endpoint address
  * @xprt: generic transport
@@ -1275,7 +1282,7 @@
 	memset(xprt->slot, 0, slot_table_size);
 
 	xprt->prot = IPPROTO_UDP;
-	xprt->port = xprt_max_resvport;
+	xprt->port = xs_get_random_port();
 	xprt->tsh_size = 0;
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	/* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1317,7 +1324,7 @@
 	memset(xprt->slot, 0, slot_table_size);
 
 	xprt->prot = IPPROTO_TCP;
-	xprt->port = xprt_max_resvport;
+	xprt->port = xs_get_random_port();
 	xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 	xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c
index 2c4ecbe..1bb7570 100644
--- a/net/tipc/bcast.c
+++ b/net/tipc/bcast.c
@@ -49,13 +49,19 @@
 #include "name_table.h"
 #include "bcast.h"
 
-
 #define MAX_PKT_DEFAULT_MCAST 1500	/* bcast link max packet size (fixed) */
 
 #define BCLINK_WIN_DEFAULT 20		/* bcast link window size (default) */
 
 #define BCLINK_LOG_BUF_SIZE 0
 
+/*
+ * Loss rate for incoming broadcast frames; used to test retransmission code.
+ * Set to N to cause every N'th frame to be discarded; 0 => don't discard any.
+ */
+ 
+#define TIPC_BCAST_LOSS_RATE 0
+
 /**
  * struct bcbearer_pair - a pair of bearers used by broadcast link
  * @primary: pointer to primary bearer
@@ -75,7 +81,14 @@
  * @bearer: (non-standard) broadcast bearer structure
  * @media: (non-standard) broadcast media structure
  * @bpairs: array of bearer pairs
- * @bpairs_temp: array of bearer pairs used during creation of "bpairs"
+ * @bpairs_temp: temporary array of bearer pairs used by tipc_bcbearer_sort()
+ * @remains: temporary node map used by tipc_bcbearer_send()
+ * @remains_new: temporary node map used tipc_bcbearer_send()
+ * 
+ * Note: The fields labelled "temporary" are incorporated into the bearer
+ * to avoid consuming potentially limited stack space through the use of
+ * large local variables within multicast routines.  Concurrent access is
+ * prevented through use of the spinlock "bc_lock".
  */
 
 struct bcbearer {
@@ -83,6 +96,8 @@
 	struct media media;
 	struct bcbearer_pair bpairs[MAX_BEARERS];
 	struct bcbearer_pair bpairs_temp[TIPC_MAX_LINK_PRI + 1];
+	struct node_map remains;
+	struct node_map remains_new;
 };
 
 /**
@@ -102,7 +117,7 @@
 static struct bcbearer *bcbearer = NULL;
 static struct bclink *bclink = NULL;
 static struct link *bcl = NULL;
-static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(bc_lock);
 
 char tipc_bclink_name[] = "multicast-link";
 
@@ -165,21 +180,18 @@
  * @after: sequence number of last packet to *not* retransmit
  * @to: sequence number of last packet to retransmit
  * 
- * Called with 'node' locked, bc_lock unlocked
+ * Called with bc_lock locked
  */
 
 static void bclink_retransmit_pkt(u32 after, u32 to)
 {
 	struct sk_buff *buf;
 
-	spin_lock_bh(&bc_lock);
 	buf = bcl->first_out;
 	while (buf && less_eq(buf_seqno(buf), after)) {
 		buf = buf->next;                
 	}
-	if (buf != NULL)
-		tipc_link_retransmit(bcl, buf, mod(to - after));
-	spin_unlock_bh(&bc_lock);              
+	tipc_link_retransmit(bcl, buf, mod(to - after));
 }
 
 /** 
@@ -346,8 +358,10 @@
 		for (; buf; buf = buf->next) {
 			u32 seqno = buf_seqno(buf);
 
-			if (mod(seqno - prev) != 1)
+			if (mod(seqno - prev) != 1) {
 				buf = NULL;
+				break;
+			}
 			if (seqno == gap_after)
 				break;
 			prev = seqno;
@@ -399,7 +413,10 @@
  */
 
 void tipc_bclink_recv_pkt(struct sk_buff *buf)
-{        
+{
+#if (TIPC_BCAST_LOSS_RATE)
+	static int rx_count = 0;
+#endif
 	struct tipc_msg *msg = buf_msg(buf);
 	struct node* node = tipc_node_find(msg_prevnode(msg));
 	u32 next_in;
@@ -420,9 +437,13 @@
 			tipc_node_lock(node);
 			tipc_bclink_acknowledge(node, msg_bcast_ack(msg));
 			tipc_node_unlock(node);
+			spin_lock_bh(&bc_lock);
 			bcl->stats.recv_nacks++;
+			bcl->owner->next = node;   /* remember requestor */
 			bclink_retransmit_pkt(msg_bcgap_after(msg),
 					      msg_bcgap_to(msg));
+			bcl->owner->next = NULL;
+			spin_unlock_bh(&bc_lock);              
 		} else {
 			tipc_bclink_peek_nack(msg_destnode(msg),
 					      msg_bcast_tag(msg),
@@ -433,6 +454,14 @@
 		return;
 	}
 
+#if (TIPC_BCAST_LOSS_RATE)
+	if (++rx_count == TIPC_BCAST_LOSS_RATE) {
+		rx_count = 0;
+		buf_discard(buf);
+		return;
+	}
+#endif
+
 	tipc_node_lock(node);
 receive:
 	deferred = node->bclink.deferred_head;
@@ -531,12 +560,8 @@
 {
 	static int send_count = 0;
 
-	struct node_map *remains;
-	struct node_map *remains_new;
-	struct node_map *remains_tmp;
 	int bp_index;
 	int swap_time;
-	int err;
 
 	/* Prepare buffer for broadcasting (if first time trying to send it) */
 
@@ -557,9 +582,7 @@
 
 	/* Send buffer over bearers until all targets reached */
 	
-	remains = kmalloc(sizeof(struct node_map), GFP_ATOMIC);
-	remains_new = kmalloc(sizeof(struct node_map), GFP_ATOMIC);
-	*remains = tipc_cltr_bcast_nodes;
+	bcbearer->remains = tipc_cltr_bcast_nodes;
 
 	for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) {
 		struct bearer *p = bcbearer->bpairs[bp_index].primary;
@@ -568,8 +591,8 @@
 		if (!p)
 			break;	/* no more bearers to try */
 
-		tipc_nmap_diff(remains, &p->nodes, remains_new);
-		if (remains_new->count == remains->count)
+		tipc_nmap_diff(&bcbearer->remains, &p->nodes, &bcbearer->remains_new);
+		if (bcbearer->remains_new.count == bcbearer->remains.count)
 			continue;	/* bearer pair doesn't add anything */
 
 		if (!p->publ.blocked &&
@@ -587,27 +610,17 @@
 		bcbearer->bpairs[bp_index].primary = s;
 		bcbearer->bpairs[bp_index].secondary = p;
 update:
-		if (remains_new->count == 0) {
-			err = TIPC_OK;
-			goto out;
-		}
+		if (bcbearer->remains_new.count == 0)
+			return TIPC_OK;
 
-		/* swap map */
-		remains_tmp = remains;
-		remains = remains_new;
-		remains_new = remains_tmp;
+		bcbearer->remains = bcbearer->remains_new;
 	}
 	
 	/* Unable to reach all targets */
 
 	bcbearer->bearer.publ.blocked = 1;
 	bcl->stats.bearer_congs++;
-	err = ~TIPC_OK;
-
- out:
-	kfree(remains_new);
-	kfree(remains);
-	return err;
+	return ~TIPC_OK;
 }
 
 /**
@@ -765,7 +778,7 @@
 	bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC);
 	if (!bcbearer || !bclink) {
  nomem:
-	 	warn("Memory squeeze; Failed to create multicast link\n");
+	 	warn("Multicast link creation failed, no memory\n");
 		kfree(bcbearer);
 		bcbearer = NULL;
 		kfree(bclink);
@@ -783,7 +796,7 @@
 	memset(bclink, 0, sizeof(struct bclink));
 	INIT_LIST_HEAD(&bcl->waiting_ports);
 	bcl->next_out_no = 1;
-	bclink->node.lock =  SPIN_LOCK_UNLOCKED;        
+	spin_lock_init(&bclink->node.lock);
 	bcl->owner = &bclink->node;
         bcl->max_pkt = MAX_PKT_DEFAULT_MCAST;
 	tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT);
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h
index 0e3be2a..b243d9d 100644
--- a/net/tipc/bcast.h
+++ b/net/tipc/bcast.h
@@ -180,7 +180,7 @@
 		if (!item->next) {
 			item->next = kmalloc(sizeof(*item), GFP_ATOMIC);
 			if (!item->next) {
-				warn("Memory squeeze: multicast destination port list is incomplete\n");
+				warn("Incomplete multicast delivery, no memory\n");
 				return;
 			}
 			item->next->next = NULL;
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index e213a8e..7ef17a4 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -112,39 +112,42 @@
 		goto exit;
 
 	if (!media_name_valid(name)) {
-		warn("Media registration error: illegal name <%s>\n", name);
+		warn("Media <%s> rejected, illegal name\n", name);
 		goto exit;
 	}
 	if (!bcast_addr) {
-		warn("Media registration error: no broadcast address supplied\n");
+		warn("Media <%s> rejected, no broadcast address\n", name);
 		goto exit;
 	}
 	if ((bearer_priority < TIPC_MIN_LINK_PRI) &&
 	    (bearer_priority > TIPC_MAX_LINK_PRI)) {
-		warn("Media registration error: priority %u\n", bearer_priority);
+		warn("Media <%s> rejected, illegal priority (%u)\n", name, 
+		     bearer_priority);
 		goto exit;
 	}
 	if ((link_tolerance < TIPC_MIN_LINK_TOL) || 
 	    (link_tolerance > TIPC_MAX_LINK_TOL)) {
-		warn("Media registration error: tolerance %u\n", link_tolerance);
+		warn("Media <%s> rejected, illegal tolerance (%u)\n", name,
+		     link_tolerance);
 		goto exit;
 	}
 
 	media_id = media_count++;
 	if (media_id >= MAX_MEDIA) {
-		warn("Attempt to register more than %u media\n", MAX_MEDIA);
+		warn("Media <%s> rejected, media limit reached (%u)\n", name,
+		     MAX_MEDIA);
 		media_count--;
 		goto exit;
 	}
 	for (i = 0; i < media_id; i++) {
 		if (media_list[i].type_id == media_type) {
-			warn("Attempt to register second media with type %u\n", 
+			warn("Media <%s> rejected, duplicate type (%u)\n", name,
 			     media_type);
 			media_count--;
 			goto exit;
 		}
 		if (!strcmp(name, media_list[i].name)) {
-			warn("Attempt to re-register media name <%s>\n", name);
+			warn("Media <%s> rejected, duplicate name\n", name);
 			media_count--;
 			goto exit;
 		}
@@ -283,6 +286,9 @@
 	struct bearer *b_ptr;
 	u32 i;
 
+	if (tipc_mode != TIPC_NET_MODE)
+		return NULL;
+
 	for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
 		if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
 			return b_ptr;
@@ -475,26 +481,33 @@
 	u32 i;
 	int res = -EINVAL;
 
-	if (tipc_mode != TIPC_NET_MODE)
+	if (tipc_mode != TIPC_NET_MODE) {
+		warn("Bearer <%s> rejected, not supported in standalone mode\n",
+		     name);
 		return -ENOPROTOOPT;
-
-	if (!bearer_name_validate(name, &b_name) ||
-	    !tipc_addr_domain_valid(bcast_scope) ||
-	    !in_scope(bcast_scope, tipc_own_addr))
+	}
+	if (!bearer_name_validate(name, &b_name)) {
+		warn("Bearer <%s> rejected, illegal name\n", name);
 		return -EINVAL;
-
+	}
+	if (!tipc_addr_domain_valid(bcast_scope) || 
+	    !in_scope(bcast_scope, tipc_own_addr)) {
+		warn("Bearer <%s> rejected, illegal broadcast scope\n", name);
+		return -EINVAL;
+	}
 	if ((priority < TIPC_MIN_LINK_PRI ||
 	     priority > TIPC_MAX_LINK_PRI) &&
-	    (priority != TIPC_MEDIA_LINK_PRI))
+	    (priority != TIPC_MEDIA_LINK_PRI)) {
+		warn("Bearer <%s> rejected, illegal priority\n", name);
 		return -EINVAL;
+	}
 
 	write_lock_bh(&tipc_net_lock);
-	if (!tipc_bearers)
-		goto failed;
 
 	m_ptr = media_find(b_name.media_name);
 	if (!m_ptr) {
-		warn("No media <%s>\n", b_name.media_name);
+		warn("Bearer <%s> rejected, media <%s> not registered\n", name,
+		     b_name.media_name);
 		goto failed;
 	}
 
@@ -510,23 +523,24 @@
 			continue;
 		}
 		if (!strcmp(name, tipc_bearers[i].publ.name)) {
-			warn("Bearer <%s> already enabled\n", name);
+			warn("Bearer <%s> rejected, already enabled\n", name);
 			goto failed;
 		}
 		if ((tipc_bearers[i].priority == priority) &&
 		    (++with_this_prio > 2)) {
 			if (priority-- == 0) {
-				warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
-				     name, priority + 1, priority);
+				warn("Bearer <%s> rejected, duplicate priority\n",
+				     name);
 				goto failed;
 			}
-			warn("Third bearer <%s> with priority %u, lowering to %u\n",
+			warn("Bearer <%s> priority adjustment required %u->%u\n",
 			     name, priority + 1, priority);
 			goto restart;
 		}
 	}
 	if (bearer_id >= MAX_BEARERS) {
-		warn("Attempt to enable more than %d bearers\n", MAX_BEARERS);
+		warn("Bearer <%s> rejected, bearer limit reached (%u)\n", 
+		     name, MAX_BEARERS);
 		goto failed;
 	}
 
@@ -536,7 +550,7 @@
 	strcpy(b_ptr->publ.name, name);
 	res = m_ptr->enable_bearer(&b_ptr->publ);
 	if (res) {
-		warn("Failed to enable bearer <%s>\n", name);
+		warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res);
 		goto failed;
 	}
 
@@ -552,7 +566,7 @@
 		b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
 							  bcast_scope, 2);
 	}
-	b_ptr->publ.lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&b_ptr->publ.lock);
 	write_unlock_bh(&tipc_net_lock);
 	info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
 	     name, addr_string_fill(addr_string, bcast_scope), priority);
@@ -573,9 +587,6 @@
 	struct link *l_ptr;
 	struct link *temp_l_ptr;
 
-	if (tipc_mode != TIPC_NET_MODE)
-		return -ENOPROTOOPT;
-
 	read_lock_bh(&tipc_net_lock);
 	b_ptr = bearer_find(name);
 	if (!b_ptr) {
@@ -584,6 +595,7 @@
 		return -EINVAL;
 	}
 
+	info("Blocking bearer <%s>\n", name);
 	spin_lock_bh(&b_ptr->publ.lock);
 	b_ptr->publ.blocked = 1;
 	list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
@@ -595,7 +607,6 @@
 	}
 	spin_unlock_bh(&b_ptr->publ.lock);
 	read_unlock_bh(&tipc_net_lock);
-	info("Blocked bearer <%s>\n", name);
 	return TIPC_OK;
 }
 
@@ -611,15 +622,13 @@
 	struct link *l_ptr;
 	struct link *temp_l_ptr;
 
-	if (tipc_mode != TIPC_NET_MODE)
-		return -ENOPROTOOPT;
-
 	b_ptr = bearer_find(name);
 	if (!b_ptr) {
 		warn("Attempt to disable unknown bearer <%s>\n", name);
 		return -EINVAL;
 	}
 
+	info("Disabling bearer <%s>\n", name);
 	tipc_disc_stop_link_req(b_ptr->link_req);
 	spin_lock_bh(&b_ptr->publ.lock);
 	b_ptr->link_req = NULL;
@@ -635,7 +644,6 @@
 		tipc_link_delete(l_ptr);
 	}
 	spin_unlock_bh(&b_ptr->publ.lock);
-	info("Disabled bearer <%s>\n", name);
 	memset(b_ptr, 0, sizeof(struct bearer));
 	return TIPC_OK;
 }
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c
index 1aed815..1dcb694 100644
--- a/net/tipc/cluster.c
+++ b/net/tipc/cluster.c
@@ -60,8 +60,10 @@
 	int alloc;
 
 	c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC);
-	if (c_ptr == NULL)
+	if (c_ptr == NULL) {
+		warn("Cluster creation failure, no memory\n");
 		return NULL;
+	}
 	memset(c_ptr, 0, sizeof(*c_ptr));
 
 	c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0);
@@ -70,30 +72,32 @@
 	else
 		max_nodes = tipc_max_nodes + 1;
 	alloc = sizeof(void *) * (max_nodes + 1);
+
 	c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC);
 	if (c_ptr->nodes == NULL) {
+		warn("Cluster creation failure, no memory for node area\n");
 		kfree(c_ptr);
 		return NULL;
 	}
-	memset(c_ptr->nodes, 0, alloc);  
+	memset(c_ptr->nodes, 0, alloc);
+
 	if (in_own_cluster(addr))
 		tipc_local_nodes = c_ptr->nodes;
 	c_ptr->highest_slave = LOWEST_SLAVE - 1;
 	c_ptr->highest_node = 0;
 	
 	z_ptr = tipc_zone_find(tipc_zone(addr));
-	if (z_ptr == NULL) {
+	if (!z_ptr) {
 		z_ptr = tipc_zone_create(addr);
 	}
-	if (z_ptr != NULL) {
-		tipc_zone_attach_cluster(z_ptr, c_ptr);
-		c_ptr->owner = z_ptr;
-	}
-	else {
+	if (!z_ptr) {
+		kfree(c_ptr->nodes);
 		kfree(c_ptr);
-		c_ptr = NULL;
+		return NULL;
 	}
 
+	tipc_zone_attach_cluster(z_ptr, c_ptr);
+	c_ptr->owner = z_ptr;
 	return c_ptr;
 }
 
diff --git a/net/tipc/config.c b/net/tipc/config.c
index 48b5de2..285e1bc 100644
--- a/net/tipc/config.c
+++ b/net/tipc/config.c
@@ -63,7 +63,7 @@
 
 static struct manager mng = { 0};
 
-static spinlock_t config_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(config_lock);
 
 static const void *req_tlv_area;	/* request message TLV area */
 static int req_tlv_space;		/* request message TLV area size */
@@ -291,13 +291,22 @@
 	if (!tipc_addr_node_valid(addr))
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (node address)");
-	if (tipc_own_addr)
+	if (tipc_mode == TIPC_NET_MODE)
 		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
 						   " (cannot change node address once assigned)");
+	tipc_own_addr = addr;
+
+	/* 
+	 * Must release all spinlocks before calling start_net() because
+	 * Linux version of TIPC calls eth_media_start() which calls
+	 * register_netdevice_notifier() which may block!
+	 *
+	 * Temporarily releasing the lock should be harmless for non-Linux TIPC,
+	 * but Linux version of eth_media_start() should really be reworked
+	 * so that it can be called with spinlocks held.
+	 */
 
 	spin_unlock_bh(&config_lock);
-	tipc_core_stop_net();
-	tipc_own_addr = addr;
 	tipc_core_start_net();
 	spin_lock_bh(&config_lock);
 	return tipc_cfg_reply_none();
@@ -350,50 +359,21 @@
 
 static struct sk_buff *cfg_set_max_ports(void)
 {
-	int orig_mode;
 	u32 value;
 
 	if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED))
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
+	if (value == tipc_max_ports)
+		return tipc_cfg_reply_none();
 	if (value != delimit(value, 127, 65535))
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (max ports must be 127-65535)");
-
-	if (value == tipc_max_ports)
-		return tipc_cfg_reply_none();
-
-	if (atomic_read(&tipc_user_count) > 2)
+	if (tipc_mode != TIPC_NOT_RUNNING)
 		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-						   " (cannot change max ports while TIPC users exist)");
-
-	spin_unlock_bh(&config_lock);
-	orig_mode = tipc_get_mode();
-	if (orig_mode == TIPC_NET_MODE)
-		tipc_core_stop_net();
-	tipc_core_stop();
+			" (cannot change max ports while TIPC is active)");
 	tipc_max_ports = value;
-	tipc_core_start();
-	if (orig_mode == TIPC_NET_MODE)
-		tipc_core_start_net();
-	spin_lock_bh(&config_lock);
-	return tipc_cfg_reply_none();
-}
-
-static struct sk_buff *set_net_max(int value, int *parameter)
-{
-	int orig_mode;
-
-	if (value != *parameter) {
-		orig_mode = tipc_get_mode();
-		if (orig_mode == TIPC_NET_MODE)
-			tipc_core_stop_net();
-		*parameter = value;
-		if (orig_mode == TIPC_NET_MODE)
-			tipc_core_start_net();
-	}
-
 	return tipc_cfg_reply_none();
 }
 
@@ -405,10 +385,16 @@
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
+	if (value == tipc_max_zones)
+		return tipc_cfg_reply_none();
 	if (value != delimit(value, 1, 255))
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (max zones must be 1-255)");
-	return set_net_max(value, &tipc_max_zones);
+	if (tipc_mode == TIPC_NET_MODE)
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+			" (cannot change max zones once TIPC has joined a network)");
+	tipc_max_zones = value;
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_clusters(void)
@@ -419,8 +405,8 @@
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
-	if (value != 1)
-		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+	if (value != delimit(value, 1, 1))
+		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (max clusters fixed at 1)");
 	return tipc_cfg_reply_none();
 }
@@ -433,10 +419,16 @@
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
+	if (value == tipc_max_nodes)
+		return tipc_cfg_reply_none();
 	if (value != delimit(value, 8, 2047))
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (max nodes must be 8-2047)");
-	return set_net_max(value, &tipc_max_nodes);
+	if (tipc_mode == TIPC_NET_MODE)
+		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
+			" (cannot change max nodes once TIPC has joined a network)");
+	tipc_max_nodes = value;
+	return tipc_cfg_reply_none();
 }
 
 static struct sk_buff *cfg_set_max_slaves(void)
@@ -461,15 +453,16 @@
 		return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 	value = *(u32 *)TLV_DATA(req_tlv_area);
 	value = ntohl(value);
+	if (value == tipc_net_id)
+		return tipc_cfg_reply_none();
 	if (value != delimit(value, 1, 9999))
 		return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE
 						   " (network id must be 1-9999)");
-
-	if (tipc_own_addr)
+	if (tipc_mode == TIPC_NET_MODE)
 		return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED
-						   " (cannot change network id once part of network)");
-	
-	return set_net_max(value, &tipc_net_id);
+			" (cannot change network id once TIPC has joined a network)");
+	tipc_net_id = value;
+	return tipc_cfg_reply_none();
 }
 
 struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area,
@@ -649,7 +642,7 @@
 	if ((size < sizeof(*req_hdr)) ||
 	    (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) ||
 	    (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) {
-		warn("discarded invalid configuration message\n");
+		warn("Invalid configuration message discarded\n");
 		return;
 	}
 
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 3d0a8ee..5003acb 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -2,7 +2,7 @@
  * net/tipc/core.c: TIPC module code
  *
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -57,7 +57,7 @@
 int  tipc_netlink_start(void);
 void tipc_netlink_stop(void);
 
-#define MOD_NAME "tipc_start: "
+#define TIPC_MOD_VER "1.6.1"
 
 #ifndef CONFIG_TIPC_ZONES
 #define CONFIG_TIPC_ZONES 3
@@ -198,7 +198,7 @@
 	tipc_max_publications = 10000;
 	tipc_max_subscriptions = 2000;
 	tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536);
-	tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511);
+	tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 255);
 	tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1);
 	tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047);
 	tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047);
@@ -224,6 +224,7 @@
 
 MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication");
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(TIPC_MOD_VER);
 
 /* Native TIPC API for kernel-space applications (see tipc.h) */
 
diff --git a/net/tipc/core.h b/net/tipc/core.h
index 1f2e8b2..86f54f3 100644
--- a/net/tipc/core.h
+++ b/net/tipc/core.h
@@ -2,7 +2,7 @@
  * net/tipc/core.h: Include file for TIPC global declarations
  * 
  * Copyright (c) 2005-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -111,10 +111,6 @@
 
 #else
 
-#ifndef DBG_OUTPUT
-#define DBG_OUTPUT NULL
-#endif
-
 /*
  * TIPC debug support not included:
  * - system messages are printed to system console
@@ -129,6 +125,19 @@
 #define msg_dbg(msg,txt) do {} while (0)
 #define dump(fmt,arg...) do {} while (0)
 
+
+/*	
+ * TIPC_OUTPUT is defined to be the system console, while DBG_OUTPUT is
+ * the null print buffer.  Thes ensures that any system or debug messages 
+ * that are generated without using the above macros are handled correctly.
+ */
+
+#undef  TIPC_OUTPUT
+#define TIPC_OUTPUT TIPC_CONS
+
+#undef  DBG_OUTPUT
+#define DBG_OUTPUT NULL
+
 #endif			  
 
 
@@ -309,7 +318,7 @@
  * buf_discard - frees a TIPC message buffer
  * @skb: message buffer
  *
- * Frees a new buffer.  If passed NULL, just returns.
+ * Frees a message buffer.  If passed NULL, just returns.
  */
 
 static inline void buf_discard(struct sk_buff *skb)
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c
index 26ef95d..5513065 100644
--- a/net/tipc/dbg.c
+++ b/net/tipc/dbg.c
@@ -41,7 +41,7 @@
 #define MAX_STRING 512
 
 static char print_string[MAX_STRING];
-static spinlock_t print_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(print_lock);
 
 static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
 struct print_buf *TIPC_CONS = &cons_buf;
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 9260138..2b84412 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -2,7 +2,7 @@
  * net/tipc/discover.c
  * 
  * Copyright (c) 2003-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -176,7 +176,6 @@
 			n_ptr = tipc_node_create(orig);
 		}
 		if (n_ptr == NULL) {
-			warn("Memory squeeze; Failed to create node\n");
 			return;
 		}
 		spin_lock_bh(&n_ptr->lock);
@@ -191,10 +190,8 @@
 		}
 		addr = &link->media_addr;
 		if (memcmp(addr, &media_addr, sizeof(*addr))) {
-			char addr_string[16];
-
-			warn("New bearer address for %s\n", 
-			     addr_string_fill(addr_string, orig));
+			warn("Resetting link <%s>, peer interface address changed\n",
+			     link->name);
 			memcpy(addr, &media_addr, sizeof(*addr));
 			tipc_link_reset(link);     
 		}
@@ -270,8 +267,8 @@
 		/* leave timer interval "as is" if already at a "normal" rate */
 	} else {
 		req->timer_intv *= 2;
-		if (req->timer_intv > TIPC_LINK_REQ_SLOW)
-			req->timer_intv = TIPC_LINK_REQ_SLOW;
+		if (req->timer_intv > TIPC_LINK_REQ_FAST)
+			req->timer_intv = TIPC_LINK_REQ_FAST;
 		if ((req->timer_intv == TIPC_LINK_REQ_FAST) && 
 		    (req->bearer->nodes.count))
 			req->timer_intv = TIPC_LINK_REQ_SLOW;
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 7a25278..682da4a 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -2,7 +2,7 @@
  * net/tipc/eth_media.c: Ethernet bearer support for TIPC
  * 
  * Copyright (c) 2001-2006, Ericsson AB
- * Copyright (c) 2005, Wind River Systems
+ * Copyright (c) 2005-2006, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -98,17 +98,19 @@
 	u32 size;
 
 	if (likely(eb_ptr->bearer)) {
-		size = msg_size((struct tipc_msg *)buf->data);
-		skb_trim(buf, size);
-		if (likely(buf->len == size)) {
-			buf->next = NULL;
-			tipc_recv_msg(buf, eb_ptr->bearer);
-		} else {
-			kfree_skb(buf);
+	       if (likely(!dev->promiscuity) ||
+	           !memcmp(buf->mac.raw,dev->dev_addr,ETH_ALEN) ||
+	           !memcmp(buf->mac.raw,dev->broadcast,ETH_ALEN)) {
+		        size = msg_size((struct tipc_msg *)buf->data);
+	                skb_trim(buf, size);
+	        	if (likely(buf->len == size)) {
+		        	buf->next = NULL;
+			        tipc_recv_msg(buf, eb_ptr->bearer);
+			        return TIPC_OK;
+			}
 		}
-	} else {
-		kfree_skb(buf);
 	}
+	kfree_skb(buf);
 	return TIPC_OK;
 }
 
@@ -125,8 +127,7 @@
 
 	/* Find device with specified name */
 
-	while (dev && dev->name &&
-	       (memcmp(dev->name, driver_name, strlen(dev->name)))) {
+	while (dev && dev->name && strncmp(dev->name, driver_name, IFNAMSIZ)) {	
 		dev = dev->next;
 	}
 	if (!dev)
@@ -252,7 +253,9 @@
 	if (eth_started)
 		return -EINVAL;
 
-	memset(&bcast_addr, 0xff, sizeof(bcast_addr));
+	bcast_addr.type = htonl(TIPC_MEDIA_TYPE_ETH);
+	memset(&bcast_addr.dev_addr, 0xff, ETH_ALEN);
+
 	memset(eth_bearers, 0, sizeof(eth_bearers));
 
 	res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth",
diff --git a/net/tipc/handler.c b/net/tipc/handler.c
index 966f70a1..ae6ddf0 100644
--- a/net/tipc/handler.c
+++ b/net/tipc/handler.c
@@ -44,7 +44,7 @@
 
 static kmem_cache_t *tipc_queue_item_cache;
 static struct list_head signal_queue_head;
-static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(qitem_lock);
 static int handler_enabled = 0;
 
 static void process_signal_queue(unsigned long dummy);
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 784b24b6..d646580 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -419,7 +419,7 @@
 
 	l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC);
 	if (!l_ptr) {
-		warn("Memory squeeze; Failed to create link\n");
+		warn("Link creation failed, no memory\n");
 		return NULL;
 	}
 	memset(l_ptr, 0, sizeof(*l_ptr));
@@ -469,7 +469,7 @@
 
 		if (!pb) {
 			kfree(l_ptr);
-			warn("Memory squeeze; Failed to create link\n");
+			warn("Link creation failed, no memory for print buffer\n");
 			return NULL;
 		}
 		tipc_printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE);
@@ -574,7 +574,6 @@
 			break;
 		list_del_init(&p_ptr->wait_list);
 		p_ptr->congested_link = NULL;
-		assert(p_ptr->wakeup);
 		spin_lock_bh(p_ptr->publ.lock);
 		p_ptr->publ.congested = 0;
 		p_ptr->wakeup(&p_ptr->publ);
@@ -691,6 +690,7 @@
 	struct sk_buff *buf;
 	u32 prev_state = l_ptr->state;
 	u32 checkpoint = l_ptr->next_in_no;
+	int was_active_link = tipc_link_is_active(l_ptr);
 	
 	msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1);
 
@@ -712,7 +712,7 @@
 	tipc_printf(TIPC_CONS, "\nReset link <%s>\n", l_ptr->name);
 	dbg_link_dump();
 #endif
-	if (tipc_node_has_active_links(l_ptr->owner) &&
+	if (was_active_link && tipc_node_has_active_links(l_ptr->owner) &&
 	    l_ptr->owner->permit_changeover) {
 		l_ptr->reset_checkpoint = checkpoint;
 		l_ptr->exp_msg_count = START_CHANGEOVER;
@@ -755,7 +755,7 @@
 
 static void link_activate(struct link *l_ptr)
 {
-	l_ptr->next_in_no = 1;
+	l_ptr->next_in_no = l_ptr->stats.recv_info = 1;
 	tipc_node_link_up(l_ptr->owner, l_ptr);
 	tipc_bearer_add_dest(l_ptr->b_ptr, l_ptr->addr);
 	link_send_event(tipc_cfg_link_event, l_ptr, 1);
@@ -820,6 +820,8 @@
 			break;
 		case RESET_MSG:
 			dbg_link("RES -> RR\n");
+			info("Resetting link <%s>, requested by peer\n", 
+			     l_ptr->name);
 			tipc_link_reset(l_ptr);
 			l_ptr->state = RESET_RESET;
 			l_ptr->fsm_msg_cnt = 0;
@@ -844,6 +846,8 @@
 			break;
 		case RESET_MSG:
 			dbg_link("RES -> RR\n");
+			info("Resetting link <%s>, requested by peer "
+			     "while probing\n", l_ptr->name);
 			tipc_link_reset(l_ptr);
 			l_ptr->state = RESET_RESET;
 			l_ptr->fsm_msg_cnt = 0;
@@ -875,6 +879,8 @@
 			} else {	/* Link has failed */
 				dbg_link("-> RU (%u probes unanswered)\n",
 					 l_ptr->fsm_msg_cnt);
+				warn("Resetting link <%s>, peer not responding\n",
+				     l_ptr->name);
 				tipc_link_reset(l_ptr);
 				l_ptr->state = RESET_UNKNOWN;
 				l_ptr->fsm_msg_cnt = 0;
@@ -1050,7 +1056,7 @@
 		msg_dbg(msg, "TIPC: Congestion, throwing away\n");
 		buf_discard(buf);
 		if (imp > CONN_MANAGER) {
-			warn("Resetting <%s>, send queue full", l_ptr->name);
+			warn("Resetting link <%s>, send queue full", l_ptr->name);
 			tipc_link_reset(l_ptr);
 		}
 		return dsz;
@@ -1135,9 +1141,13 @@
 	if (n_ptr) {
 		tipc_node_lock(n_ptr);
 		l_ptr = n_ptr->active_links[selector & 1];
-		dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest);
 		if (l_ptr) {
+			dbg("tipc_link_send: found link %x for dest %x\n", l_ptr, dest);
 			res = tipc_link_send_buf(l_ptr, buf);
+		} else {
+			dbg("Attempt to send msg to unreachable node:\n");
+			msg_dbg(buf_msg(buf),">>>");
+			buf_discard(buf);
 		}
 		tipc_node_unlock(n_ptr);
 	} else {
@@ -1242,8 +1252,6 @@
 	int res;
 	u32 selector = msg_origport(hdr) & 1;
 
-	assert(destaddr != tipc_own_addr);
-
 again:
 	/*
 	 * Try building message using port's max_pkt hint.
@@ -1604,40 +1612,121 @@
 		tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 }
 
+static void link_reset_all(unsigned long addr)
+{
+	struct node *n_ptr;
+	char addr_string[16];
+	u32 i;
+
+	read_lock_bh(&tipc_net_lock);
+	n_ptr = tipc_node_find((u32)addr);
+	if (!n_ptr) {
+		read_unlock_bh(&tipc_net_lock);
+		return;	/* node no longer exists */
+	}
+
+	tipc_node_lock(n_ptr);
+
+	warn("Resetting all links to %s\n", 
+	     addr_string_fill(addr_string, n_ptr->addr));
+
+	for (i = 0; i < MAX_BEARERS; i++) {
+		if (n_ptr->links[i]) {
+			link_print(n_ptr->links[i], TIPC_OUTPUT, 
+				   "Resetting link\n");
+			tipc_link_reset(n_ptr->links[i]);
+		}
+	}
+
+	tipc_node_unlock(n_ptr);
+	read_unlock_bh(&tipc_net_lock);
+}
+
+static void link_retransmit_failure(struct link *l_ptr, struct sk_buff *buf)
+{
+	struct tipc_msg *msg = buf_msg(buf);
+
+	warn("Retransmission failure on link <%s>\n", l_ptr->name);
+	tipc_msg_print(TIPC_OUTPUT, msg, ">RETR-FAIL>");
+
+	if (l_ptr->addr) {
+
+		/* Handle failure on standard link */
+
+		link_print(l_ptr, TIPC_OUTPUT, "Resetting link\n");
+		tipc_link_reset(l_ptr);
+
+	} else {
+
+		/* Handle failure on broadcast link */
+
+		struct node *n_ptr;
+		char addr_string[16];
+
+		tipc_printf(TIPC_OUTPUT, "Msg seq number: %u,  ", msg_seqno(msg));
+		tipc_printf(TIPC_OUTPUT, "Outstanding acks: %u\n", (u32)TIPC_SKB_CB(buf)->handle);
+		
+		n_ptr = l_ptr->owner->next;
+		tipc_node_lock(n_ptr);
+
+		addr_string_fill(addr_string, n_ptr->addr);
+		tipc_printf(TIPC_OUTPUT, "Multicast link info for %s\n", addr_string);
+		tipc_printf(TIPC_OUTPUT, "Supported: %d,  ", n_ptr->bclink.supported);
+		tipc_printf(TIPC_OUTPUT, "Acked: %u\n", n_ptr->bclink.acked);
+		tipc_printf(TIPC_OUTPUT, "Last in: %u,  ", n_ptr->bclink.last_in);
+		tipc_printf(TIPC_OUTPUT, "Gap after: %u,  ", n_ptr->bclink.gap_after);
+		tipc_printf(TIPC_OUTPUT, "Gap to: %u\n", n_ptr->bclink.gap_to);
+		tipc_printf(TIPC_OUTPUT, "Nack sync: %u\n\n", n_ptr->bclink.nack_sync);
+
+		tipc_k_signal((Handler)link_reset_all, (unsigned long)n_ptr->addr);
+
+		tipc_node_unlock(n_ptr);
+
+		l_ptr->stale_count = 0;
+	}
+}
+
 void tipc_link_retransmit(struct link *l_ptr, struct sk_buff *buf, 
 			  u32 retransmits)
 {
 	struct tipc_msg *msg;
 
+	if (!buf)
+		return;
+
+	msg = buf_msg(buf);
+	
 	dbg("Retransmitting %u in link %x\n", retransmits, l_ptr);
 
-	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) {
-		msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>");
-		dbg_print_link(l_ptr, "   ");
-		l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf));
-		l_ptr->retransm_queue_size = retransmits;
-		return;
+	if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
+		if (!skb_cloned(buf)) {
+			msg_dbg(msg, ">NO_RETR->BCONG>");
+			dbg_print_link(l_ptr, "   ");
+			l_ptr->retransm_queue_head = msg_seqno(msg);
+			l_ptr->retransm_queue_size = retransmits;
+			return;
+		} else {
+			/* Don't retransmit if driver already has the buffer */
+		}
+	} else {
+		/* Detect repeated retransmit failures on uncongested bearer */
+
+		if (l_ptr->last_retransmitted == msg_seqno(msg)) {
+			if (++l_ptr->stale_count > 100) {
+				link_retransmit_failure(l_ptr, buf);
+				return;
+			}
+		} else {
+			l_ptr->last_retransmitted = msg_seqno(msg);
+			l_ptr->stale_count = 1;
+		}
 	}
+
 	while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) {
 		msg = buf_msg(buf);
 		msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
 		msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); 
 		if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
-                        /* Catch if retransmissions fail repeatedly: */
-                        if (l_ptr->last_retransmitted == msg_seqno(msg)) {
-                                if (++l_ptr->stale_count > 100) {
-                                        tipc_msg_print(TIPC_CONS, buf_msg(buf), ">RETR>");
-                                        info("...Retransmitted %u times\n",
-					     l_ptr->stale_count);
-                                        link_print(l_ptr, TIPC_CONS, "Resetting Link\n");
-                                        tipc_link_reset(l_ptr);
-                                        break;
-                                }
-                        } else {
-                                l_ptr->stale_count = 0;
-                        }
-                        l_ptr->last_retransmitted = msg_seqno(msg);
-
 			msg_dbg(buf_msg(buf), ">RETR>");
 			buf = buf->next;
 			retransmits--;
@@ -1650,6 +1739,7 @@
 			return;
 		}
 	}
+
 	l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
 }
 
@@ -1720,6 +1810,11 @@
 			link_recv_non_seq(buf);
 			continue;
 		}
+		
+		if (unlikely(!msg_short(msg) &&
+			     (msg_destnode(msg) != tipc_own_addr)))
+			goto cont;
+		
 		n_ptr = tipc_node_find(msg_prevnode(msg));
 		if (unlikely(!n_ptr))
 			goto cont;
@@ -2140,7 +2235,7 @@
 		
 		if (msg_linkprio(msg) && 
 		    (msg_linkprio(msg) != l_ptr->priority)) {
-			warn("Changing prio <%s>: %u->%u\n",
+			warn("Resetting link <%s>, priority change %u->%u\n",
 			     l_ptr->name, l_ptr->priority, msg_linkprio(msg));
 			l_ptr->priority = msg_linkprio(msg);
 			tipc_link_reset(l_ptr); /* Enforce change to take effect */
@@ -2209,17 +2304,22 @@
 	u32 length = msg_size(msg);
 
 	tunnel = l_ptr->owner->active_links[selector & 1];
-	if (!tipc_link_is_up(tunnel))
+	if (!tipc_link_is_up(tunnel)) {
+		warn("Link changeover error, "
+		     "tunnel link no longer available\n");
 		return;
+	}
 	msg_set_size(tunnel_hdr, length + INT_H_SIZE);
 	buf = buf_acquire(length + INT_H_SIZE);
-	if (!buf)
+	if (!buf) {
+		warn("Link changeover error, "
+		     "unable to send tunnel msg\n");
 		return;
+	}
 	memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE);
 	memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length);
 	dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane);
 	msg_dbg(buf_msg(buf), ">SEND>");
-	assert(tunnel);
 	tipc_link_send_buf(tunnel, buf);
 }
 
@@ -2235,23 +2335,27 @@
 	u32 msgcount = l_ptr->out_queue_size;
 	struct sk_buff *crs = l_ptr->first_out;
 	struct link *tunnel = l_ptr->owner->active_links[0];
-	int split_bundles = tipc_node_has_redundant_links(l_ptr->owner);
 	struct tipc_msg tunnel_hdr;
+	int split_bundles;
 
 	if (!tunnel)
 		return;
 
-	if (!l_ptr->owner->permit_changeover)
+	if (!l_ptr->owner->permit_changeover) {
+		warn("Link changeover error, "
+		     "peer did not permit changeover\n");
 		return;
+	}
 
 	msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL,
 		 ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr);
 	msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id);
 	msg_set_msgcnt(&tunnel_hdr, msgcount);
+	dbg("Link changeover requires %u tunnel messages\n", msgcount);
+
 	if (!l_ptr->first_out) {
 		struct sk_buff *buf;
 
-		assert(!msgcount);
 		buf = buf_acquire(INT_H_SIZE);
 		if (buf) {
 			memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE);
@@ -2261,10 +2365,15 @@
 			msg_dbg(&tunnel_hdr, "EMPTY>SEND>");
 			tipc_link_send_buf(tunnel, buf);
 		} else {
-			warn("Memory squeeze; link changeover failed\n");
+			warn("Link changeover error, "
+			     "unable to send changeover msg\n");
 		}
 		return;
 	}
+
+	split_bundles = (l_ptr->owner->active_links[0] != 
+			 l_ptr->owner->active_links[1]);
+
 	while (crs) {
 		struct tipc_msg *msg = buf_msg(crs);
 
@@ -2310,7 +2419,8 @@
 		msg_set_size(&tunnel_hdr, length + INT_H_SIZE);
 		outbuf = buf_acquire(length + INT_H_SIZE);
 		if (outbuf == NULL) {
-			warn("Memory squeeze; buffer duplication failed\n");
+			warn("Link changeover error, "
+			     "unable to send duplicate msg\n");
 			return;
 		}
 		memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE);
@@ -2364,11 +2474,15 @@
 	u32 msg_count = msg_msgcnt(tunnel_msg);
 
 	dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)];
-	assert(dest_link != *l_ptr);
 	if (!dest_link) {
 		msg_dbg(tunnel_msg, "NOLINK/<REC<");
 		goto exit;
 	}
+	if (dest_link == *l_ptr) {
+		err("Unexpected changeover message on link <%s>\n", 
+		    (*l_ptr)->name);
+		goto exit;
+	}
 	dbg("%c<-%c:", dest_link->b_ptr->net_plane,
 	    (*l_ptr)->b_ptr->net_plane);
 	*l_ptr = dest_link;
@@ -2381,7 +2495,7 @@
 		}
 		*buf = buf_extract(tunnel_buf,INT_H_SIZE);
 		if (*buf == NULL) {
-			warn("Memory squeeze; failed to extract msg\n");
+			warn("Link changeover error, duplicate msg dropped\n");
 			goto exit;
 		}
 		msg_dbg(tunnel_msg, "TNL<REC<");
@@ -2393,13 +2507,17 @@
 
 	if (tipc_link_is_up(dest_link)) {
 		msg_dbg(tunnel_msg, "UP/FIRST/<REC<");
+		info("Resetting link <%s>, changeover initiated by peer\n",
+		     dest_link->name);
 		tipc_link_reset(dest_link);
 		dest_link->exp_msg_count = msg_count;
+		dbg("Expecting %u tunnelled messages\n", msg_count);
 		if (!msg_count)
 			goto exit;
 	} else if (dest_link->exp_msg_count == START_CHANGEOVER) {
 		msg_dbg(tunnel_msg, "BLK/FIRST/<REC<");
 		dest_link->exp_msg_count = msg_count;
+		dbg("Expecting %u tunnelled messages\n", msg_count);
 		if (!msg_count)
 			goto exit;
 	}
@@ -2407,6 +2525,8 @@
 	/* Receive original message */
 
 	if (dest_link->exp_msg_count == 0) {
+		warn("Link switchover error, "
+		     "got too many tunnelled messages\n");
 		msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<");
 		dbg_print_link(dest_link, "LINK:");
 		goto exit;
@@ -2422,7 +2542,7 @@
 			buf_discard(tunnel_buf);
 			return 1;
 		} else {
-			warn("Memory squeeze; dropped incoming msg\n");
+			warn("Link changeover error, original msg dropped\n");
 		}
 	}
 exit:
@@ -2444,13 +2564,8 @@
 	while (msgcount--) {
 		obuf = buf_extract(buf, pos);
 		if (obuf == NULL) {
-			char addr_string[16];
-
-			warn("Buffer allocation failure;\n");
-			warn("  incoming message(s) from %s lost\n",
-			     addr_string_fill(addr_string, 
-					      msg_orignode(buf_msg(buf))));
-			return;
+			warn("Link unable to unbundle message(s)\n");
+			break;
 		};
 		pos += align(msg_size(buf_msg(obuf)));
 		msg_dbg(buf_msg(obuf), "     /");
@@ -2508,7 +2623,7 @@
 		}
 		fragm = buf_acquire(fragm_sz + INT_H_SIZE);
 		if (fragm == NULL) {
-			warn("Memory squeeze; failed to fragment msg\n");
+			warn("Link unable to fragment message\n");
 			dsz = -ENOMEM;
 			goto exit;
 		}
@@ -2623,7 +2738,7 @@
 			set_fragm_size(pbuf,fragm_sz); 
 			set_expected_frags(pbuf,exp_fragm_cnt - 1); 
 		} else {
-			warn("Memory squeeze; got no defragmenting buffer\n");
+			warn("Link unable to reassemble fragmented message\n");
 		}
 		buf_discard(fbuf);
 		return 0;
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index a3bbc89..f0b063b 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -127,7 +127,7 @@
 
 	buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0);
 	if (!buf) {
-		warn("Memory squeeze; failed to distribute publication\n");
+		warn("Publication distribution failure\n");
 		return;
 	}
 
@@ -151,7 +151,7 @@
 
 	buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0);
 	if (!buf) {
-		warn("Memory squeeze; failed to distribute withdrawal\n");
+		warn("Withdrawl distribution failure\n");
 		return;
 	}
 
@@ -174,7 +174,6 @@
 	u32 rest;
 	u32 max_item_buf;
 
-	assert(in_own_cluster(node));
 	read_lock_bh(&tipc_nametbl_lock); 
 	max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE;
 	max_item_buf *= ITEM_SIZE;
@@ -185,8 +184,8 @@
 			left = (rest <= max_item_buf) ? rest : max_item_buf;
 			rest -= left;
 			buf = named_prepare_buf(PUBLICATION, left, node);       
-			if (buf == NULL) {
-				warn("Memory Squeeze; could not send publication\n");
+			if (!buf) {
+				warn("Bulk publication distribution failure\n");
 				goto exit;
 			}
 			item = (struct distr_item *)msg_data(buf_msg(buf));
@@ -221,15 +220,24 @@
 static void node_is_down(struct publication *publ)
 {
 	struct publication *p;
+
         write_lock_bh(&tipc_nametbl_lock);
 	dbg("node_is_down: withdrawing %u, %u, %u\n", 
 	    publ->type, publ->lower, publ->upper);
         publ->key += 1222345;
 	p = tipc_nametbl_remove_publ(publ->type, publ->lower, 
 				     publ->node, publ->ref, publ->key);
-        assert(p == publ);
 	write_unlock_bh(&tipc_nametbl_lock);
-	kfree(publ);
+
+        if (p != publ) {
+		err("Unable to remove publication from failed node\n"
+		    "(type=%u, lower=%u, node=0x%x, ref=%u, key=%u)\n",
+		    publ->type, publ->lower, publ->node, publ->ref, publ->key);
+	}
+
+	if (p) {
+		kfree(p);
+	}
 }
 
 /**
@@ -275,9 +283,15 @@
 			if (publ) {
 				tipc_nodesub_unsubscribe(&publ->subscr);
         			kfree(publ);
+			} else {
+				err("Unable to remove publication by node 0x%x\n"
+				    "(type=%u, lower=%u, ref=%u, key=%u)\n",
+				    msg_orignode(msg),
+				    ntohl(item->type), ntohl(item->lower),
+				    ntohl(item->ref), ntohl(item->key));
 			}
 		} else {
-			warn("tipc_named_recv: unknown msg\n");
+			warn("Unrecognized name table message received\n");
 		}
 		item++;
 	}
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index d129422..a6926ff 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -71,7 +71,7 @@
  * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
  *        sub-sequences are sorted in ascending order
  * @alloc: number of sub-sequences currently in array
- * @first_free: upper bound of highest sub-sequence + 1
+ * @first_free: array index of first unused sub-sequence entry
  * @ns_list: links to adjacent name sequences in hash chain
  * @subscriptions: list of subscriptions for this 'type'
  * @lock: spinlock controlling access to name sequence structure
@@ -101,7 +101,7 @@
 
 static struct name_table table = { NULL } ;
 static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
-rwlock_t tipc_nametbl_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(tipc_nametbl_lock);
 
 
 static int hash(int x)
@@ -120,7 +120,7 @@
 	struct publication *publ =
 		(struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC);
 	if (publ == NULL) {
-		warn("Memory squeeze; failed to create publication\n");
+		warn("Publication creation failure, no memory\n");
 		return NULL;
 	}
 
@@ -165,17 +165,17 @@
 	struct sub_seq *sseq = tipc_subseq_alloc(1);
 
 	if (!nseq || !sseq) {
-		warn("Memory squeeze; failed to create name sequence\n");
+		warn("Name sequence creation failed, no memory\n");
 		kfree(nseq);
 		kfree(sseq);
 		return NULL;
 	}
 
 	memset(nseq, 0, sizeof(*nseq));
-	nseq->lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&nseq->lock);
 	nseq->type = type;
 	nseq->sseqs = sseq;
-	dbg("tipc_nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n",
+	dbg("tipc_nameseq_create(): nseq = %p, type %u, ssseqs %p, ff: %u\n",
 	    nseq, type, nseq->sseqs, nseq->first_free);
 	nseq->alloc = 1;
 	INIT_HLIST_NODE(&nseq->ns_list);
@@ -253,16 +253,16 @@
 	struct sub_seq *sseq;
 	int created_subseq = 0;
 
-	assert(nseq->first_free <= nseq->alloc);
 	sseq = nameseq_find_subseq(nseq, lower);
-	dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n",
+	dbg("nameseq_ins: for seq %p, {%u,%u}, found sseq %p\n",
 	    nseq, type, lower, sseq);
 	if (sseq) {
 
 		/* Lower end overlaps existing entry => need an exact match */
 
 		if ((sseq->lower != lower) || (sseq->upper != upper)) {
-			warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
+			warn("Cannot publish {%u,%u,%u}, overlap error\n",
+			     type, lower, upper);
 			return NULL;
 		}
 	} else {
@@ -277,25 +277,27 @@
 
 		if ((inspos < nseq->first_free) &&
 		    (upper >= nseq->sseqs[inspos].lower)) {
-			warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper);
+			warn("Cannot publish {%u,%u,%u}, overlap error\n",
+			     type, lower, upper);
 			return NULL;
 		}
 
 		/* Ensure there is space for new sub-sequence */
 
 		if (nseq->first_free == nseq->alloc) {
-			struct sub_seq *sseqs = nseq->sseqs;
-			nseq->sseqs = tipc_subseq_alloc(nseq->alloc * 2);
-			if (nseq->sseqs != NULL) {
-				memcpy(nseq->sseqs, sseqs,
-				       nseq->alloc * sizeof (struct sub_seq));
-				kfree(sseqs);
-				dbg("Allocated %u sseqs\n", nseq->alloc);
-				nseq->alloc *= 2;
-			} else {
-				warn("Memory squeeze; failed to create sub-sequence\n");
+			struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2);
+
+			if (!sseqs) {
+				warn("Cannot publish {%u,%u,%u}, no memory\n",
+				     type, lower, upper);
 				return NULL;
 			}
+			dbg("Allocated %u more sseqs\n", nseq->alloc);
+			memcpy(sseqs, nseq->sseqs,
+			       nseq->alloc * sizeof(struct sub_seq));
+			kfree(nseq->sseqs);
+			nseq->sseqs = sseqs;
+			nseq->alloc *= 2;
 		}
 		dbg("Have %u sseqs for type %u\n", nseq->alloc, type);
 
@@ -311,7 +313,7 @@
 		sseq->upper = upper;
 		created_subseq = 1;
 	}
-	dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n",
+	dbg("inserting {%u,%u,%u} from <0x%x:%u> into sseq %p(%u,%u) of seq %p\n",
 	    type, lower, upper, node, port, sseq,
 	    sseq->lower, sseq->upper, nseq);
 
@@ -320,7 +322,7 @@
 	publ = publ_create(type, lower, upper, scope, node, port, key);
 	if (!publ)
 		return NULL;
-	dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n",
+	dbg("inserting publ %p, node=0x%x publ->node=0x%x, subscr->node=%p\n",
 	    publ, node, publ->node, publ->subscr.node);
 
 	if (!sseq->zone_list)
@@ -367,45 +369,47 @@
 
 /**
  * tipc_nameseq_remove_publ -
+ * 
+ * NOTE: There may be cases where TIPC is asked to remove a publication
+ * that is not in the name table.  For example, if another node issues a
+ * publication for a name sequence that overlaps an existing name sequence
+ * the publication will not be recorded, which means the publication won't
+ * be found when the name sequence is later withdrawn by that node.
+ * A failed withdraw request simply returns a failure indication and lets the
+ * caller issue any error or warning messages associated with such a problem.
  */
 
 static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
 						    u32 node, u32 ref, u32 key)
 {
 	struct publication *publ;
+	struct publication *curr;
 	struct publication *prev;
 	struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
 	struct sub_seq *free;
 	struct subscription *s, *st;
 	int removed_subseq = 0;
 
-	assert(nseq);
-
-	if (!sseq) {
-		int i;
-
-		warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst);
-		assert(nseq->sseqs);
-		dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n",
-		    nseq->sseqs, nseq, nseq->alloc, 
-		    nseq->first_free);
-		for (i = 0; i < nseq->first_free; i++) {
-			dbg("Subseq %u(%x): lower = %u,upper = %u\n",
-			    i, &nseq->sseqs[i], nseq->sseqs[i].lower,
-			    nseq->sseqs[i].upper);
-		}
+	if (!sseq)
 		return NULL;
-	}
-	dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n",
+
+	dbg("tipc_nameseq_remove_publ: seq: %p, sseq %p, {%u,%u}, key %u\n",
 	    nseq, sseq, nseq->type, inst, key);
 
+	/* Remove publication from zone scope list */
+
 	prev = sseq->zone_list;
 	publ = sseq->zone_list->zone_list_next;
 	while ((publ->key != key) || (publ->ref != ref) || 
 	       (publ->node && (publ->node != node))) {
 		prev = publ;
 		publ = publ->zone_list_next;
-		assert(prev != sseq->zone_list);
+		if (prev == sseq->zone_list) {
+			
+			/* Prevent endless loop if publication not found */
+
+			return NULL;
+		}
 	}
 	if (publ != sseq->zone_list)
 		prev->zone_list_next = publ->zone_list_next;
@@ -416,14 +420,24 @@
 		sseq->zone_list = NULL;
 	}
 
+	/* Remove publication from cluster scope list, if present */
+
 	if (in_own_cluster(node)) {
 		prev = sseq->cluster_list;
-		publ = sseq->cluster_list->cluster_list_next;
-		while ((publ->key != key) || (publ->ref != ref) || 
-		       (publ->node && (publ->node != node))) {
-			prev = publ;
-			publ = publ->cluster_list_next;
-			assert(prev != sseq->cluster_list);
+		curr = sseq->cluster_list->cluster_list_next;
+		while (curr != publ) {
+			prev = curr;
+			curr = curr->cluster_list_next;
+			if (prev == sseq->cluster_list) {
+
+				/* Prevent endless loop for malformed list */
+
+				err("Unable to de-list cluster publication\n"
+				    "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
+				    publ->type, publ->lower, publ->node, 
+				    publ->ref, publ->key);
+				goto end_cluster;
+			}
 		}
 		if (publ != sseq->cluster_list)
 			prev->cluster_list_next = publ->cluster_list_next;
@@ -434,15 +448,26 @@
 			sseq->cluster_list = NULL;
 		}
 	}
+end_cluster:
+
+	/* Remove publication from node scope list, if present */
 
 	if (node == tipc_own_addr) {
 		prev = sseq->node_list;
-		publ = sseq->node_list->node_list_next;
-		while ((publ->key != key) || (publ->ref != ref) || 
-		       (publ->node && (publ->node != node))) {
-			prev = publ;
-			publ = publ->node_list_next;
-			assert(prev != sseq->node_list);
+		curr = sseq->node_list->node_list_next;
+		while (curr != publ) {
+			prev = curr;
+			curr = curr->node_list_next;
+			if (prev == sseq->node_list) {
+
+				/* Prevent endless loop for malformed list */
+
+				err("Unable to de-list node publication\n"
+				    "{%u%u}, node=0x%x, ref=%u, key=%u)\n",
+				    publ->type, publ->lower, publ->node, 
+				    publ->ref, publ->key);
+				goto end_node;
+			}
 		}
 		if (publ != sseq->node_list)
 			prev->node_list_next = publ->node_list_next;
@@ -453,22 +478,18 @@
 			sseq->node_list = NULL;
 		}
 	}
-	assert(!publ->node || (publ->node == node));
-	assert(publ->ref == ref);
-	assert(publ->key == key);
+end_node:
 
-	/* 
-	 * Contract subseq list if no more publications:
-	 */
-	if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) {
+	/* Contract subseq list if no more publications for that subseq */
+
+	if (!sseq->zone_list) {
 		free = &nseq->sseqs[nseq->first_free--];
 		memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq));
 		removed_subseq = 1;
 	}
 
-	/* 
-	 * Any subscriptions waiting ? 
-	 */
+	/* Notify any waiting subscriptions */
+
 	list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
 		tipc_subscr_report_overlap(s,
 					   publ->lower,
@@ -478,6 +499,7 @@
 					   publ->node,
 					   removed_subseq);
 	}
+
 	return publ;
 }
 
@@ -530,7 +552,7 @@
 	seq_head = &table.types[hash(type)];
 	hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
 		if (ns->type == type) {
-			dbg("found %x\n", ns);
+			dbg("found %p\n", ns);
 			return ns;
 		}
 	}
@@ -543,22 +565,21 @@
 {
 	struct name_seq *seq = nametbl_find_seq(type);
 
-	dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq);
+	dbg("tipc_nametbl_insert_publ: {%u,%u,%u} found %p\n", type, lower, upper, seq);
 	if (lower > upper) {
-		warn("Failed to publish illegal <%u,%u,%u>\n",
+		warn("Failed to publish illegal {%u,%u,%u}\n",
 		     type, lower, upper);
 		return NULL;
 	}
 
-	dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node);
+	dbg("Publishing {%u,%u,%u} from 0x%x\n", type, lower, upper, node);
 	if (!seq) {
 		seq = tipc_nameseq_create(type, &table.types[hash(type)]);
-		dbg("tipc_nametbl_insert_publ: created %x\n", seq);
+		dbg("tipc_nametbl_insert_publ: created %p\n", seq);
 	}
 	if (!seq)
 		return NULL;
 
-	assert(seq->type == type);
 	return tipc_nameseq_insert_publ(seq, type, lower, upper,
 					scope, node, port, key);
 }
@@ -572,7 +593,7 @@
 	if (!seq)
 		return NULL;
 
-	dbg("Withdrawing <%u,%u> from %x\n", type, lower, node);
+	dbg("Withdrawing {%u,%u} from 0x%x\n", type, lower, node);
 	publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
 
 	if (!seq->first_free && list_empty(&seq->subscriptions)) {
@@ -738,12 +759,12 @@
 	struct publication *publ;
 
 	if (table.local_publ_count >= tipc_max_publications) {
-		warn("Failed publish: max %u local publication\n", 
+		warn("Publication failed, local publication limit reached (%u)\n", 
 		     tipc_max_publications);
 		return NULL;
 	}
 	if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
-		warn("Failed to publish reserved name <%u,%u,%u>\n",
+		warn("Publication failed, reserved name {%u,%u,%u}\n",
 		     type, lower, upper);
 		return NULL;
 	}
@@ -767,10 +788,10 @@
 {
 	struct publication *publ;
 
-	dbg("tipc_nametbl_withdraw:<%d,%d,%d>\n", type, lower, key);
+	dbg("tipc_nametbl_withdraw: {%u,%u}, key=%u\n", type, lower, key);
 	write_lock_bh(&tipc_nametbl_lock);
 	publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
-	if (publ) {
+	if (likely(publ)) {
 		table.local_publ_count--;
 		if (publ->scope != TIPC_NODE_SCOPE)
 			tipc_named_withdraw(publ);
@@ -780,6 +801,9 @@
 		return 1;
 	}
 	write_unlock_bh(&tipc_nametbl_lock);
+	err("Unable to remove local publication\n"
+	    "(type=%u, lower=%u, ref=%u, key=%u)\n",
+	    type, lower, ref, key);
 	return 0;
 }
 
@@ -787,8 +811,7 @@
  * tipc_nametbl_subscribe - add a subscription object to the name table
  */
 
-void
-tipc_nametbl_subscribe(struct subscription *s)
+void tipc_nametbl_subscribe(struct subscription *s)
 {
 	u32 type = s->seq.type;
 	struct name_seq *seq;
@@ -800,11 +823,13 @@
 	}
         if (seq){
                 spin_lock_bh(&seq->lock);
-                dbg("tipc_nametbl_subscribe:found %x for <%u,%u,%u>\n",
+                dbg("tipc_nametbl_subscribe:found %p for {%u,%u,%u}\n",
                     seq, type, s->seq.lower, s->seq.upper);
-                assert(seq->type == type);
                 tipc_nameseq_subscribe(seq, s);
                 spin_unlock_bh(&seq->lock);
+        } else {
+		warn("Failed to create subscription for {%u,%u,%u}\n",
+		     s->seq.type, s->seq.lower, s->seq.upper);
         }
         write_unlock_bh(&tipc_nametbl_lock);
 }
@@ -813,8 +838,7 @@
  * tipc_nametbl_unsubscribe - remove a subscription object from name table
  */
 
-void
-tipc_nametbl_unsubscribe(struct subscription *s)
+void tipc_nametbl_unsubscribe(struct subscription *s)
 {
 	struct name_seq *seq;
 
@@ -1049,35 +1073,20 @@
 
 void tipc_nametbl_stop(void)
 {
-	struct hlist_head *seq_head;
-	struct hlist_node *seq_node;
-	struct hlist_node *tmp;
-	struct name_seq *seq;
 	u32 i;
 
 	if (!table.types)
 		return;
 
+	/* Verify name table is empty, then release it */
+
 	write_lock_bh(&tipc_nametbl_lock);
 	for (i = 0; i < tipc_nametbl_size; i++) {
-		seq_head = &table.types[i];
-		hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) {
-			struct sub_seq *sseq = seq->sseqs;
-
-			for (; sseq != &seq->sseqs[seq->first_free]; sseq++) {
-				struct publication *publ = sseq->zone_list;
-				assert(publ);
-				do {
-					struct publication *next =
-						publ->zone_list_next;
-					kfree(publ);
-					publ = next;
-				}
-				while (publ != sseq->zone_list);
-			}
-		}
+		if (!hlist_empty(&table.types[i]))
+			err("tipc_nametbl_stop(): hash chain %u is non-null\n", i);
 	}
 	kfree(table.types);
 	table.types = NULL;
 	write_unlock_bh(&tipc_nametbl_lock);
 }
+
diff --git a/net/tipc/net.c b/net/tipc/net.c
index f7c8223..e5a359a 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -115,7 +115,7 @@
  *     - A local spin_lock protecting the queue of subscriber events.
 */
 
-rwlock_t tipc_net_lock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(tipc_net_lock);
 struct network tipc_net = { NULL };
 
 struct node *tipc_net_select_remote_node(u32 addr, u32 ref) 
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 0d5db06..861322b 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -61,34 +61,37 @@
         struct node **curr_node;
 
 	n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC);
-        if (n_ptr != NULL) {
-                memset(n_ptr, 0, sizeof(*n_ptr));
-                n_ptr->addr = addr;
-                n_ptr->lock =  SPIN_LOCK_UNLOCKED;	
-                INIT_LIST_HEAD(&n_ptr->nsub);
-	
-		c_ptr = tipc_cltr_find(addr);
-                if (c_ptr == NULL)
-                        c_ptr = tipc_cltr_create(addr);
-                if (c_ptr != NULL) {
-                        n_ptr->owner = c_ptr;
-                        tipc_cltr_attach_node(c_ptr, n_ptr);
-                        n_ptr->last_router = -1;
+	if (!n_ptr) {
+		warn("Node creation failed, no memory\n");
+		return NULL;
+	}
 
-                        /* Insert node into ordered list */
-                        for (curr_node = &tipc_nodes; *curr_node; 
-			     curr_node = &(*curr_node)->next) {
-                                if (addr < (*curr_node)->addr) {
-                                        n_ptr->next = *curr_node;
-                                        break;
-                                }
-                        }
-                        (*curr_node) = n_ptr;
-                } else {
-                        kfree(n_ptr);
-                        n_ptr = NULL;
-                }
-        }
+	c_ptr = tipc_cltr_find(addr);
+	if (!c_ptr) {
+		c_ptr = tipc_cltr_create(addr);
+	}
+	if (!c_ptr) {
+		kfree(n_ptr);
+		return NULL;
+	}
+		
+	memset(n_ptr, 0, sizeof(*n_ptr));
+	n_ptr->addr = addr;
+                spin_lock_init(&n_ptr->lock);
+	INIT_LIST_HEAD(&n_ptr->nsub);
+	n_ptr->owner = c_ptr;
+	tipc_cltr_attach_node(c_ptr, n_ptr);
+	n_ptr->last_router = -1;
+
+	/* Insert node into ordered list */
+	for (curr_node = &tipc_nodes; *curr_node; 
+	     curr_node = &(*curr_node)->next) {
+		if (addr < (*curr_node)->addr) {
+			n_ptr->next = *curr_node;
+			break;
+		}
+	}
+	(*curr_node) = n_ptr;
 	return n_ptr;
 }
 
@@ -122,6 +125,8 @@
 {
 	struct link **active = &n_ptr->active_links[0];
 
+	n_ptr->working_links++;
+
 	info("Established link <%s> on network plane %c\n",
 	     l_ptr->name, l_ptr->b_ptr->net_plane);
 	
@@ -132,7 +137,7 @@
 		return;
 	}
 	if (l_ptr->priority < active[0]->priority) { 
-		info("Link is standby\n");
+		info("New link <%s> becomes standby\n", l_ptr->name);
 		return;
 	}
 	tipc_link_send_duplicate(active[0], l_ptr);
@@ -140,8 +145,9 @@
 		active[0] = l_ptr;
 		return;
 	}
-	info("Link <%s> on network plane %c becomes standby\n",
-	     active[0]->name, active[0]->b_ptr->net_plane);
+	info("Old link <%s> becomes standby\n", active[0]->name);
+	if (active[1] != active[0])
+		info("Old link <%s> becomes standby\n", active[1]->name);
 	active[0] = active[1] = l_ptr;
 }
 
@@ -181,6 +187,8 @@
 {
 	struct link **active;
 
+	n_ptr->working_links--;
+
 	if (!tipc_link_is_active(l_ptr)) {
 		info("Lost standby link <%s> on network plane %c\n",
 		     l_ptr->name, l_ptr->b_ptr->net_plane);
@@ -210,8 +218,7 @@
 
 int tipc_node_has_redundant_links(struct node *n_ptr)
 {
-	return (tipc_node_has_active_links(n_ptr) &&
-		(n_ptr->active_links[0] != n_ptr->active_links[1]));
+	return (n_ptr->working_links > 1);
 }
 
 static int tipc_node_has_active_routes(struct node *n_ptr)
@@ -234,7 +241,6 @@
 		u32 bearer_id = l_ptr->b_ptr->identity;
 		char addr_string[16];
 
-                assert(bearer_id < MAX_BEARERS);
                 if (n_ptr->link_cnt >= 2) {
 			char addr_string[16];
 
@@ -249,7 +255,7 @@
                         n_ptr->link_cnt++;
                         return n_ptr;
                 }
-                err("Attempt to establish second link on <%s> to <%s> \n",
+                err("Attempt to establish second link on <%s> to %s \n",
                     l_ptr->b_ptr->publ.name, 
 		    addr_string_fill(addr_string, l_ptr->addr));
         }
@@ -314,7 +320,7 @@
 	struct cluster *c_ptr;
 
 	dbg("node_established_contact:-> %x\n", n_ptr->addr);
-	if (!tipc_node_has_active_routes(n_ptr)) { 
+	if (!tipc_node_has_active_routes(n_ptr) && in_own_cluster(n_ptr->addr)) { 
 		tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
 	}
 
diff --git a/net/tipc/node.h b/net/tipc/node.h
index 781126e..a07cc79 100644
--- a/net/tipc/node.h
+++ b/net/tipc/node.h
@@ -51,6 +51,7 @@
  * @nsub: list of "node down" subscriptions monitoring node
  * @active_links: pointers to active links to node
  * @links: pointers to all links to node
+ * @working_links: number of working links to node (both active and standby)
  * @link_cnt: number of links to node
  * @permit_changeover: non-zero if node has redundant links to this system
  * @routers: bitmap (used for multicluster communication)
@@ -76,6 +77,7 @@
 	struct link *active_links[2];
 	struct link *links[MAX_BEARERS];
 	int link_cnt;
+	int working_links;
 	int permit_changeover;
 	u32 routers[512/32];
 	int last_router;
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c
index cff4068..cc3fff3 100644
--- a/net/tipc/node_subscr.c
+++ b/net/tipc/node_subscr.c
@@ -47,18 +47,19 @@
 void tipc_nodesub_subscribe(struct node_subscr *node_sub, u32 addr, 
 		       void *usr_handle, net_ev_handler handle_down)
 {
-	node_sub->node = NULL;
-	if (addr == tipc_own_addr)
-		return;
-	if (!tipc_addr_node_valid(addr)) {
-		warn("node_subscr with illegal %x\n", addr);
+	if (addr == tipc_own_addr) {
+		node_sub->node = NULL;
 		return;
 	}
-
+	
+	node_sub->node = tipc_node_find(addr);
+	if (!node_sub->node) {
+		warn("Node subscription rejected, unknown node 0x%x\n", addr);
+		return;
+	}
 	node_sub->handle_node_down = handle_down;
 	node_sub->usr_handle = usr_handle;
-	node_sub->node = tipc_node_find(addr);
-	assert(node_sub->node);
+
 	tipc_node_lock(node_sub->node);
 	list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub);
 	tipc_node_unlock(node_sub->node);
diff --git a/net/tipc/port.c b/net/tipc/port.c
index 67e96cb..3251c8d 100644
--- a/net/tipc/port.c
+++ b/net/tipc/port.c
@@ -57,8 +57,8 @@
 static struct sk_buff *msg_queue_head = NULL;
 static struct sk_buff *msg_queue_tail = NULL;
 
-spinlock_t tipc_port_list_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(tipc_port_list_lock);
+static DEFINE_SPINLOCK(queue_lock);
 
 static LIST_HEAD(ports);
 static void port_handle_node_down(unsigned long ref);
@@ -168,7 +168,6 @@
 	struct port_list *item = dp;
 	int cnt = 0;
 
-	assert(buf);
 	msg = buf_msg(buf);
 
 	/* Create destination port list, if one wasn't supplied */
@@ -196,7 +195,7 @@
 			struct sk_buff *b = skb_clone(buf, GFP_ATOMIC);
 
 			if (b == NULL) {
-				warn("Buffer allocation failure\n");
+				warn("Unable to deliver multicast message(s)\n");
 				msg_dbg(msg, "LOST:");
 				goto exit;
 			}
@@ -228,14 +227,14 @@
 	u32 ref;
 
 	p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC);
-	if (p_ptr == NULL) {
-		warn("Memory squeeze; failed to create port\n");
+	if (!p_ptr) {
+		warn("Port creation failed, no memory\n");
 		return 0;
 	}
 	memset(p_ptr, 0, sizeof(*p_ptr));
 	ref = tipc_ref_acquire(p_ptr, &p_ptr->publ.lock);
 	if (!ref) {
-		warn("Reference Table Exhausted\n");
+		warn("Port creation failed, reference table exhausted\n");
 		kfree(p_ptr);
 		return 0;
 	}
@@ -810,18 +809,20 @@
 		void *usr_handle;
 		int connected;
 		int published;
+		u32 message_type;
 
 		struct sk_buff *next = buf->next;
 		struct tipc_msg *msg = buf_msg(buf);
 		u32 dref = msg_destport(msg);
 		
+		message_type = msg_type(msg);
+		if (message_type > TIPC_DIRECT_MSG)
+			goto reject;	/* Unsupported message type */
+
 		p_ptr = tipc_port_lock(dref);
-		if (!p_ptr) {
-			/* Port deleted while msg in queue */
-			tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
-			buf = next;
-			continue;
-		}
+		if (!p_ptr)
+			goto reject;	/* Port deleted while msg in queue */
+
 		orig.ref = msg_origport(msg);
 		orig.node = msg_orignode(msg);
 		up_ptr = p_ptr->user_port;
@@ -832,7 +833,7 @@
 		if (unlikely(msg_errcode(msg)))
 			goto err;
 
-		switch (msg_type(msg)) {
+		switch (message_type) {
 		
 		case TIPC_CONN_MSG:{
 				tipc_conn_msg_event cb = up_ptr->conn_msg_cb;
@@ -874,6 +875,7 @@
 				   &orig);
 				break;
 			}
+		case TIPC_MCAST_MSG:
 		case TIPC_NAMED_MSG:{
 				tipc_named_msg_event cb = up_ptr->named_msg_cb;
 
@@ -886,7 +888,8 @@
 					goto reject;
 				dseq.type =  msg_nametype(msg);
 				dseq.lower = msg_nameinst(msg);
-				dseq.upper = dseq.lower;
+				dseq.upper = (message_type == TIPC_NAMED_MSG)
+					? dseq.lower : msg_nameupper(msg);
 				skb_pull(buf, msg_hdr_sz(msg));
 				cb(usr_handle, dref, &buf, msg_data(msg), 
 				   msg_data_sz(msg), msg_importance(msg),
@@ -899,7 +902,7 @@
 		buf = next;
 		continue;
 err:
-		switch (msg_type(msg)) {
+		switch (message_type) {
 		
 		case TIPC_CONN_MSG:{
 				tipc_conn_shutdown_event cb = 
@@ -931,6 +934,7 @@
 				   msg_data_sz(msg), msg_errcode(msg), &orig);
 				break;
 			}
+		case TIPC_MCAST_MSG:
 		case TIPC_NAMED_MSG:{
 				tipc_named_msg_err_event cb = 
 					up_ptr->named_err_cb;
@@ -940,7 +944,8 @@
 					break;
 				dseq.type =  msg_nametype(msg);
 				dseq.lower = msg_nameinst(msg);
-				dseq.upper = dseq.lower;
+				dseq.upper = (message_type == TIPC_NAMED_MSG)
+					? dseq.lower : msg_nameupper(msg);
 				skb_pull(buf, msg_hdr_sz(msg));
 				cb(usr_handle, dref, &buf, msg_data(msg), 
 				   msg_data_sz(msg), msg_errcode(msg), &dseq);
@@ -1054,7 +1059,8 @@
 	u32 ref;
 
 	up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC);
-	if (up_ptr == NULL) {
+	if (!up_ptr) {
+		warn("Port creation failed, no memory\n");
 		return -ENOMEM;
 	}
 	ref = tipc_createport_raw(NULL, port_dispatcher, port_wakeup, importance);
@@ -1165,8 +1171,6 @@
 	p_ptr = tipc_port_lock(ref);
 	if (!p_ptr)
 		return -EINVAL;
-	if (!p_ptr->publ.published)
-		goto exit;
 	if (!seq) {
 		list_for_each_entry_safe(publ, tpubl, 
 					 &p_ptr->publications, pport_list) {
@@ -1193,7 +1197,6 @@
 	}
 	if (list_empty(&p_ptr->publications))
 		p_ptr->publ.published = 0;
-exit:
 	tipc_port_unlock(p_ptr);
 	return res;
 }
diff --git a/net/tipc/ref.c b/net/tipc/ref.c
index 33bbf50..596d3c8 100644
--- a/net/tipc/ref.c
+++ b/net/tipc/ref.c
@@ -63,7 +63,7 @@
 
 struct ref_table tipc_ref_table = { NULL };
 
-static rwlock_t ref_table_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(ref_table_lock);
 
 /**
  * tipc_ref_table_init - create reference table for objects
@@ -87,7 +87,7 @@
 	index_mask = sz - 1;
 	for (i = sz - 1; i >= 0; i--) {
 		table[i].object = NULL;
-		table[i].lock = SPIN_LOCK_UNLOCKED;
+		spin_lock_init(&table[i].lock);
 		table[i].data.next_plus_upper = (start & ~index_mask) + i - 1;
 	}
 	tipc_ref_table.entries = table;
@@ -127,7 +127,14 @@
 	u32 next_plus_upper;
 	u32 reference = 0;
 
-	assert(tipc_ref_table.entries && object);
+	if (!object) {
+		err("Attempt to acquire reference to non-existent object\n");
+		return 0;
+	}
+	if (!tipc_ref_table.entries) {
+		err("Reference table not found during acquisition attempt\n");
+		return 0;
+	}
 
 	write_lock_bh(&ref_table_lock);
 	if (tipc_ref_table.first_free) {
@@ -162,15 +169,28 @@
 	u32 index; 
 	u32 index_mask;
 
-	assert(tipc_ref_table.entries);
-	assert(ref != 0);
+	if (!ref) {
+		err("Attempt to discard reference 0\n");
+		return;
+	}
+	if (!tipc_ref_table.entries) {
+		err("Reference table not found during discard attempt\n");
+		return;
+	}
 
 	write_lock_bh(&ref_table_lock);
 	index_mask = tipc_ref_table.index_mask;
 	index = ref & index_mask;
 	entry = &(tipc_ref_table.entries[index]);
-	assert(entry->object != 0);
-	assert(entry->data.reference == ref);
+
+	if (!entry->object) {
+		err("Attempt to discard reference to non-existent object\n");
+		goto exit;
+	}
+	if (entry->data.reference != ref) {
+		err("Attempt to discard non-existent reference\n");
+		goto exit;
+	}
 
 	/* mark entry as unused */
 	entry->object = NULL;
@@ -184,6 +204,7 @@
 
 	/* increment upper bits of entry to invalidate subsequent references */
 	entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1);
+exit:
 	write_unlock_bh(&ref_table_lock);
 }
 
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 648a734..32d7784 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -169,12 +169,6 @@
 	struct sock *sk;
         u32 ref;
 
-	if ((sock->type != SOCK_STREAM) && 
-	    (sock->type != SOCK_SEQPACKET) &&
-	    (sock->type != SOCK_DGRAM) &&
-	    (sock->type != SOCK_RDM))
-		return -EPROTOTYPE;
-
 	if (unlikely(protocol != 0))
 		return -EPROTONOSUPPORT;
 
@@ -199,6 +193,9 @@
 		sock->ops = &msg_ops;
 		sock->state = SS_READY;
 		break;
+	default:
+		tipc_deleteport(ref);
+		return -EPROTOTYPE;
 	}
 
 	sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1);
@@ -426,7 +423,7 @@
 
         if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr)))
 		return -EFAULT;
-	if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN)))
+	if ((ntohs(hdr.tcm_type) & 0xC000) && (!capable(CAP_NET_ADMIN)))
 		return -EACCES;
         
 	return 0;
@@ -437,7 +434,7 @@
  * @iocb: (unused)
  * @sock: socket structure
  * @m: message to send
- * @total_len: (unused)
+ * @total_len: length of message
  * 
  * Message must have an destination specified explicitly.
  * Used for SOCK_RDM and SOCK_DGRAM messages, 
@@ -458,7 +455,8 @@
 
 	if (unlikely(!dest))
 		return -EDESTADDRREQ;
-	if (unlikely(dest->family != AF_TIPC))
+	if (unlikely((m->msg_namelen < sizeof(*dest)) ||
+		     (dest->family != AF_TIPC)))
 		return -EINVAL;
 
 	needs_conn = (sock->state != SS_READY);
@@ -470,6 +468,10 @@
 		if ((tsock->p->published) ||
 		    ((sock->type == SOCK_STREAM) && (total_len != 0)))
 			return -EOPNOTSUPP;
+		if (dest->addrtype == TIPC_ADDR_NAME) {
+			tsock->p->conn_type = dest->addr.name.name.type;
+			tsock->p->conn_instance = dest->addr.name.name.instance;
+		}
 	}
 
 	if (down_interruptible(&tsock->sem))
@@ -538,7 +540,7 @@
  * @iocb: (unused)
  * @sock: socket structure
  * @m: message to send
- * @total_len: (unused)
+ * @total_len: length of message
  * 
  * Used for SOCK_SEQPACKET messages and SOCK_STREAM data.
  * 
@@ -561,15 +563,15 @@
 		return -ERESTARTSYS;
         }
 
-        if (unlikely(sock->state != SS_CONNECTED)) {
-                if (sock->state == SS_DISCONNECTING)
-                        res = -EPIPE;   
-                else
-                        res = -ENOTCONN;
-                goto exit;
-        }
-
         do {
+		if (unlikely(sock->state != SS_CONNECTED)) {
+			if (sock->state == SS_DISCONNECTING)
+				res = -EPIPE;   
+			else
+				res = -ENOTCONN;
+			goto exit;
+		}
+
                 res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov);
                 if (likely(res != -ELINKCONG)) {
 exit:
@@ -597,7 +599,8 @@
  * 
  * Used for SOCK_STREAM data.
  * 
- * Returns the number of bytes sent on success, or errno otherwise
+ * Returns the number of bytes sent on success (or partial success), 
+ * or errno if no data sent
  */
 
 
@@ -611,6 +614,7 @@
 	char __user *curr_start;
 	int curr_left;
 	int bytes_to_send;
+	int bytes_sent;
 	int res;
 	
 	if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE))
@@ -633,11 +637,11 @@
 	 * of small iovec entries into send_packet().
 	 */
 
-	my_msg = *m;
-	curr_iov = my_msg.msg_iov;
-	curr_iovlen = my_msg.msg_iovlen;
+	curr_iov = m->msg_iov;
+	curr_iovlen = m->msg_iovlen;
 	my_msg.msg_iov = &my_iov;
 	my_msg.msg_iovlen = 1;
+	bytes_sent = 0;
 
 	while (curr_iovlen--) {
 		curr_start = curr_iov->iov_base;
@@ -648,16 +652,18 @@
 				? curr_left : TIPC_MAX_USER_MSG_SIZE;
 			my_iov.iov_base = curr_start;
 			my_iov.iov_len = bytes_to_send;
-                        if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0)
-                                return res;
+                        if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) {
+				return bytes_sent ? bytes_sent : res;
+			}
 			curr_left -= bytes_to_send;
 			curr_start += bytes_to_send;
+			bytes_sent += bytes_to_send;
 		}
 
 		curr_iov++;
 	}
 
-	return total_len;
+	return bytes_sent;
 }
 
 /**
@@ -727,6 +733,7 @@
 	u32 anc_data[3];
 	u32 err;
 	u32 dest_type;
+	int has_name;
 	int res;
 
 	if (likely(m->msg_controllen == 0))
@@ -738,10 +745,10 @@
 	if (unlikely(err)) {
 		anc_data[0] = err;
 		anc_data[1] = msg_data_sz(msg);
-		if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data)))
+		if ((res = put_cmsg(m, SOL_TIPC, TIPC_ERRINFO, 8, anc_data)))
 			return res;
 		if (anc_data[1] &&
-		    (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], 
+		    (res = put_cmsg(m, SOL_TIPC, TIPC_RETDATA, anc_data[1], 
 				    msg_data(msg))))
 			return res;
 	}
@@ -751,25 +758,28 @@
 	dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG;
 	switch (dest_type) {
 	case TIPC_NAMED_MSG:
+		has_name = 1;
 		anc_data[0] = msg_nametype(msg);
 		anc_data[1] = msg_namelower(msg);
 		anc_data[2] = msg_namelower(msg);
 		break;
 	case TIPC_MCAST_MSG:
+		has_name = 1;
 		anc_data[0] = msg_nametype(msg);
 		anc_data[1] = msg_namelower(msg);
 		anc_data[2] = msg_nameupper(msg);
 		break;
 	case TIPC_CONN_MSG:
+		has_name = (tport->conn_type != 0);
 		anc_data[0] = tport->conn_type;
 		anc_data[1] = tport->conn_instance;
 		anc_data[2] = tport->conn_instance;
 		break;
 	default:
-		anc_data[0] = 0;
+		has_name = 0;
 	}
-	if (anc_data[0] &&
-	    (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data)))
+	if (has_name &&
+	    (res = put_cmsg(m, SOL_TIPC, TIPC_DESTNAME, 12, anc_data)))
 		return res;
 
 	return 0;
@@ -960,7 +970,7 @@
 restart:
 	if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) &&
 		     (flags & MSG_DONTWAIT))) {
-		res = (sz_copied == 0) ? -EWOULDBLOCK : 0;
+		res = -EWOULDBLOCK;
 		goto exit;
 	}
 
@@ -1051,7 +1061,7 @@
 
 exit:
 	up(&tsock->sem);
-	return res ? res : sz_copied;
+	return sz_copied ? sz_copied : res;
 }
 
 /**
@@ -1236,7 +1246,8 @@
    if (sock->state == SS_READY)
 	   return -EOPNOTSUPP;
 
-   /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */
+   /* Issue Posix-compliant error code if socket is in the wrong state */
+
    if (sock->state == SS_LISTENING)
 	   return -EOPNOTSUPP;
    if (sock->state == SS_CONNECTING)
@@ -1244,13 +1255,20 @@
    if (sock->state != SS_UNCONNECTED)
            return -EISCONN;
 
-   if ((dst->family != AF_TIPC) ||
-       ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID)))
+   /*
+    * Reject connection attempt using multicast address
+    *
+    * Note: send_msg() validates the rest of the address fields,
+    *       so there's no need to do it here
+    */
+
+   if (dst->addrtype == TIPC_ADDR_MCAST)
            return -EINVAL;
 
    /* Send a 'SYN-' to destination */
 
    m.msg_name = dest;
+   m.msg_namelen = destlen;
    if ((res = send_msg(NULL, sock, &m, 0)) < 0) {
 	   sock->state = SS_DISCONNECTING;
 	   return res;
@@ -1269,10 +1287,6 @@
 	   msg = buf_msg(buf);
            res = auto_connect(sock, tsock, msg);
            if (!res) {
-		   if (dst->addrtype == TIPC_ADDR_NAME) {
-			   tsock->p->conn_type = dst->addr.name.name.type;
-			   tsock->p->conn_instance = dst->addr.name.name.instance;
-		   }
 		   if (!msg_data_sz(msg))
 			   advance_queue(tsock);
 	   }
@@ -1386,7 +1400,7 @@
 /**
  * shutdown - shutdown socket connection
  * @sock: socket structure
- * @how: direction to close (always treated as read + write)
+ * @how: direction to close (unused; always treated as read + write)
  *
  * Terminates connection (if necessary), then purges socket's receive queue.
  * 
@@ -1469,7 +1483,8 @@
  * Returns 0 on success, errno otherwise
  */
 
-static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol)
+static int setsockopt(struct socket *sock, 
+		      int lvl, int opt, char __user *ov, int ol)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
 	u32 value;
@@ -1525,7 +1540,8 @@
  * Returns 0 on success, errno otherwise
  */
 
-static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol)
+static int getsockopt(struct socket *sock, 
+		      int lvl, int opt, char __user *ov, int *ol)
 {
 	struct tipc_sock *tsock = tipc_sk(sock->sk);
         int len;
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c
index c5f026c..e19b4bc 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -266,7 +266,8 @@
 	/* Refuse subscription if global limit exceeded */
 
 	if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) {
-		warn("Failed: max %u subscriptions\n", tipc_max_subscriptions);
+		warn("Subscription rejected, subscription limit reached (%u)\n",
+		     tipc_max_subscriptions);
 		subscr_terminate(subscriber);
 		return;
 	}
@@ -274,8 +275,8 @@
 	/* Allocate subscription object */
 
 	sub = kmalloc(sizeof(*sub), GFP_ATOMIC);
-	if (sub == NULL) {
-		warn("Memory squeeze; ignoring subscription\n");
+	if (!sub) {
+		warn("Subscription rejected, no memory\n");
 		subscr_terminate(subscriber);
 		return;
 	}
@@ -298,8 +299,7 @@
 	if ((((sub->filter != TIPC_SUB_PORTS) 
 	      && (sub->filter != TIPC_SUB_SERVICE)))
 	    || (sub->seq.lower > sub->seq.upper)) {
-		warn("Rejecting illegal subscription %u,%u,%u\n",
-		     sub->seq.type, sub->seq.lower, sub->seq.upper);
+		warn("Subscription rejected, illegal request\n");
 		kfree(sub);
 		subscr_terminate(subscriber);
 		return;
@@ -387,7 +387,7 @@
 	dbg("subscr_named_msg_event: orig = %x own = %x,\n",
 	    orig->node, tipc_own_addr);
 	if (size && (size != sizeof(struct tipc_subscr))) {
-		warn("Received tipc_subscr of invalid size\n");
+		warn("Subscriber rejected, invalid subscription size\n");
 		return;
 	}
 
@@ -395,7 +395,7 @@
 
 	subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC);
 	if (subscriber == NULL) {
-		warn("Memory squeeze; ignoring subscriber setup\n");
+		warn("Subscriber rejected, no memory\n");
 		return;
 	}
 	memset(subscriber, 0, sizeof(struct subscriber));
@@ -403,7 +403,7 @@
 	INIT_LIST_HEAD(&subscriber->subscriber_list);
 	subscriber->ref = tipc_ref_acquire(subscriber, &subscriber->lock);
 	if (subscriber->ref == 0) {
-		warn("Failed to acquire subscriber reference\n");
+		warn("Subscriber rejected, reference table exhausted\n");
 		kfree(subscriber);
 		return;
 	}
@@ -422,7 +422,7 @@
 			NULL,
 			&subscriber->port_ref);
 	if (subscriber->port_ref == 0) {
-		warn("Memory squeeze; failed to create subscription port\n");
+		warn("Subscriber rejected, unable to create port\n");
 		tipc_ref_discard(subscriber->ref);
 		kfree(subscriber);
 		return;
@@ -457,7 +457,7 @@
 	int res = -1;
 
 	memset(&topsrv, 0, sizeof (topsrv));
-	topsrv.lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&topsrv.lock);
 	INIT_LIST_HEAD(&topsrv.subscriber_list);
 
 	spin_lock_bh(&topsrv.lock);
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c
index 3f3f933..1e3ae57 100644
--- a/net/tipc/user_reg.c
+++ b/net/tipc/user_reg.c
@@ -67,7 +67,7 @@
 
 static struct tipc_user *users = NULL;
 static u32 next_free_user = MAX_USERID + 1;
-static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(reg_lock);
 
 /**
  * reg_init - create TIPC user registry (but don't activate it)
diff --git a/net/tipc/zone.c b/net/tipc/zone.c
index 2803e1b..316c487 100644
--- a/net/tipc/zone.c
+++ b/net/tipc/zone.c
@@ -44,19 +44,24 @@
 
 struct _zone *tipc_zone_create(u32 addr)
 {
-	struct _zone *z_ptr = NULL;
+	struct _zone *z_ptr;
 	u32 z_num;
 
-	if (!tipc_addr_domain_valid(addr))
+	if (!tipc_addr_domain_valid(addr)) {
+		err("Zone creation failed, invalid domain 0x%x\n", addr);
 		return NULL;
+	}
 
 	z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC);
-	if (z_ptr != NULL) {
-		memset(z_ptr, 0, sizeof(*z_ptr));
-		z_num = tipc_zone(addr);
-		z_ptr->addr = tipc_addr(z_num, 0, 0);
-		tipc_net.zones[z_num] = z_ptr;
+	if (!z_ptr) {
+		warn("Zone creation failed, insufficient memory\n");
+		return NULL;
 	}
+
+	memset(z_ptr, 0, sizeof(*z_ptr));
+	z_num = tipc_zone(addr);
+	z_ptr->addr = tipc_addr(z_num, 0, 0);
+	tipc_net.zones[z_num] = z_ptr;
 	return z_ptr;
 }
 
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index b469c8b..b893692 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -46,45 +46,43 @@
 
 static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family);
+static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo);
 
 int xfrm_register_type(struct xfrm_type *type, unsigned short family)
 {
-	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
-	struct xfrm_type_map *typemap;
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+	struct xfrm_type **typemap;
 	int err = 0;
 
 	if (unlikely(afinfo == NULL))
 		return -EAFNOSUPPORT;
 	typemap = afinfo->type_map;
 
-	write_lock_bh(&typemap->lock);
-	if (likely(typemap->map[type->proto] == NULL))
-		typemap->map[type->proto] = type;
+	if (likely(typemap[type->proto] == NULL))
+		typemap[type->proto] = type;
 	else
 		err = -EEXIST;
-	write_unlock_bh(&typemap->lock);
-	xfrm_policy_put_afinfo(afinfo);
+	xfrm_policy_unlock_afinfo(afinfo);
 	return err;
 }
 EXPORT_SYMBOL(xfrm_register_type);
 
 int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
 {
-	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
-	struct xfrm_type_map *typemap;
+	struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
+	struct xfrm_type **typemap;
 	int err = 0;
 
 	if (unlikely(afinfo == NULL))
 		return -EAFNOSUPPORT;
 	typemap = afinfo->type_map;
 
-	write_lock_bh(&typemap->lock);
-	if (unlikely(typemap->map[type->proto] != type))
+	if (unlikely(typemap[type->proto] != type))
 		err = -ENOENT;
 	else
-		typemap->map[type->proto] = NULL;
-	write_unlock_bh(&typemap->lock);
-	xfrm_policy_put_afinfo(afinfo);
+		typemap[type->proto] = NULL;
+	xfrm_policy_unlock_afinfo(afinfo);
 	return err;
 }
 EXPORT_SYMBOL(xfrm_unregister_type);
@@ -92,7 +90,7 @@
 struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
 {
 	struct xfrm_policy_afinfo *afinfo;
-	struct xfrm_type_map *typemap;
+	struct xfrm_type **typemap;
 	struct xfrm_type *type;
 	int modload_attempted = 0;
 
@@ -102,11 +100,9 @@
 		return NULL;
 	typemap = afinfo->type_map;
 
-	read_lock(&typemap->lock);
-	type = typemap->map[proto];
+	type = typemap[proto];
 	if (unlikely(type && !try_module_get(type->owner)))
 		type = NULL;
-	read_unlock(&typemap->lock);
 	if (!type && !modload_attempted) {
 		xfrm_policy_put_afinfo(afinfo);
 		request_module("xfrm-type-%d-%d",
@@ -142,6 +138,89 @@
 	module_put(type->owner);
 }
 
+int xfrm_register_mode(struct xfrm_mode *mode, int family)
+{
+	struct xfrm_policy_afinfo *afinfo;
+	struct xfrm_mode **modemap;
+	int err;
+
+	if (unlikely(mode->encap >= XFRM_MODE_MAX))
+		return -EINVAL;
+
+	afinfo = xfrm_policy_lock_afinfo(family);
+	if (unlikely(afinfo == NULL))
+		return -EAFNOSUPPORT;
+
+	err = -EEXIST;
+	modemap = afinfo->mode_map;
+	if (likely(modemap[mode->encap] == NULL)) {
+		modemap[mode->encap] = mode;
+		err = 0;
+	}
+
+	xfrm_policy_unlock_afinfo(afinfo);
+	return err;
+}
+EXPORT_SYMBOL(xfrm_register_mode);
+
+int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
+{
+	struct xfrm_policy_afinfo *afinfo;
+	struct xfrm_mode **modemap;
+	int err;
+
+	if (unlikely(mode->encap >= XFRM_MODE_MAX))
+		return -EINVAL;
+
+	afinfo = xfrm_policy_lock_afinfo(family);
+	if (unlikely(afinfo == NULL))
+		return -EAFNOSUPPORT;
+
+	err = -ENOENT;
+	modemap = afinfo->mode_map;
+	if (likely(modemap[mode->encap] == mode)) {
+		modemap[mode->encap] = NULL;
+		err = 0;
+	}
+
+	xfrm_policy_unlock_afinfo(afinfo);
+	return err;
+}
+EXPORT_SYMBOL(xfrm_unregister_mode);
+
+struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
+{
+	struct xfrm_policy_afinfo *afinfo;
+	struct xfrm_mode *mode;
+	int modload_attempted = 0;
+
+	if (unlikely(encap >= XFRM_MODE_MAX))
+		return NULL;
+
+retry:
+	afinfo = xfrm_policy_get_afinfo(family);
+	if (unlikely(afinfo == NULL))
+		return NULL;
+
+	mode = afinfo->mode_map[encap];
+	if (unlikely(mode && !try_module_get(mode->owner)))
+		mode = NULL;
+	if (!mode && !modload_attempted) {
+		xfrm_policy_put_afinfo(afinfo);
+		request_module("xfrm-mode-%d-%d", family, encap);
+		modload_attempted = 1;
+		goto retry;
+	}
+
+	xfrm_policy_put_afinfo(afinfo);
+	return mode;
+}
+
+void xfrm_put_mode(struct xfrm_mode *mode)
+{
+	module_put(mode->owner);
+}
+
 static inline unsigned long make_jiffies(long secs)
 {
 	if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
@@ -1306,17 +1385,31 @@
 		return NULL;
 	read_lock(&xfrm_policy_afinfo_lock);
 	afinfo = xfrm_policy_afinfo[family];
-	if (likely(afinfo != NULL))
-		read_lock(&afinfo->lock);
-	read_unlock(&xfrm_policy_afinfo_lock);
+	if (unlikely(!afinfo))
+		read_unlock(&xfrm_policy_afinfo_lock);
 	return afinfo;
 }
 
 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
-	if (unlikely(afinfo == NULL))
-		return;
-	read_unlock(&afinfo->lock);
+	read_unlock(&xfrm_policy_afinfo_lock);
+}
+
+static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family)
+{
+	struct xfrm_policy_afinfo *afinfo;
+	if (unlikely(family >= NPROTO))
+		return NULL;
+	write_lock_bh(&xfrm_policy_afinfo_lock);
+	afinfo = xfrm_policy_afinfo[family];
+	if (unlikely(!afinfo))
+		write_unlock_bh(&xfrm_policy_afinfo_lock);
+	return afinfo;
+}
+
+static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
+{
+	write_unlock_bh(&xfrm_policy_afinfo_lock);
 }
 
 static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 93a2f36..17b29ec 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -77,6 +77,8 @@
 	kfree(x->ealg);
 	kfree(x->calg);
 	kfree(x->encap);
+	if (x->mode)
+		xfrm_put_mode(x->mode);
 	if (x->type) {
 		x->type->destructor(x);
 		xfrm_put_type(x->type);
@@ -1103,17 +1105,14 @@
 		return NULL;
 	read_lock(&xfrm_state_afinfo_lock);
 	afinfo = xfrm_state_afinfo[family];
-	if (likely(afinfo != NULL))
-		read_lock(&afinfo->lock);
-	read_unlock(&xfrm_state_afinfo_lock);
+	if (unlikely(!afinfo))
+		read_unlock(&xfrm_state_afinfo_lock);
 	return afinfo;
 }
 
 static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
 {
-	if (unlikely(afinfo == NULL))
-		return;
-	read_unlock(&afinfo->lock);
+	read_unlock(&xfrm_state_afinfo_lock);
 }
 
 /* Temporarily located here until net/xfrm/xfrm_tunnel.c is created */
@@ -1196,6 +1195,10 @@
 	if (err)
 		goto error;
 
+	x->mode = xfrm_get_mode(x->props.mode, family);
+	if (x->mode == NULL)
+		goto error;
+
 	x->km.state = XFRM_STATE_VALID;
 
 error:
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 81d1005..c21dc26 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -427,23 +427,25 @@
 	if (x == NULL)
 		return -ESRCH;
 
+	if ((err = security_xfrm_state_delete(x)) != 0)
+		goto out;
+
 	if (xfrm_state_kern(x)) {
-		xfrm_state_put(x);
-		return -EPERM;
+		err = -EPERM;
+		goto out;
 	}
 
 	err = xfrm_state_delete(x);
-	if (err < 0) {
-		xfrm_state_put(x);
-		return err;
-	}
+	if (err < 0)
+		goto out;
 
 	c.seq = nlh->nlmsg_seq;
 	c.pid = nlh->nlmsg_pid;
 	c.event = nlh->nlmsg_type;
 	km_state_notify(x, &c);
-	xfrm_state_put(x);
 
+out:
+	xfrm_state_put(x);
 	return err;
 }
 
@@ -1055,6 +1057,8 @@
 					      MSG_DONTWAIT);
 		}
 	} else {
+		if ((err = security_xfrm_policy_delete(xp)) != 0)
+			goto out;
 		c.data.byid = p->index;
 		c.event = nlh->nlmsg_type;
 		c.seq = nlh->nlmsg_seq;
@@ -1064,6 +1068,7 @@
 
 	xfrm_pol_put(xp);
 
+out:
 	return err;
 }
 
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index e48e60d..02a7eea 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -8,7 +8,7 @@
 __build:
 
 # Read .config if it exist, otherwise ignore
--include .config
+-include include/config/auto.conf
 
 include scripts/Kbuild.include
 
@@ -140,6 +140,15 @@
 %.i: %.c FORCE
 	$(call if_changed_dep,cc_i_c)
 
+quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
+cmd_cc_symtypes_c	   = \
+		$(CPP) -D__GENKSYMS__ $(c_flags) $<			\
+		| $(GENKSYMS) -T $@ >/dev/null;				\
+		test -s $@ || rm -f $@
+
+%.symtypes : %.c FORCE
+	$(call if_changed_dep,cc_symtypes_c)
+
 # C (.c) files
 # The C file is compiled and updated dependency information is generated.
 # (See cmd_cc_o_c + relevant part of rule_cc_o_c)
@@ -166,7 +175,8 @@
 cmd_modversions =							\
 	if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then	\
 		$(CPP) -D__GENKSYMS__ $(c_flags) $<			\
-		| $(GENKSYMS) -a $(ARCH)				\
+		| $(GENKSYMS) $(if $(KBUILD_SYMTYPES),			\
+			      -T $(@D)/$(@F:.o=.symtypes)) -a $(ARCH)	\
 		> $(@D)/.tmp_$(@F:.o=.ver);				\
 									\
 		$(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) 		\
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index 2d51970..2b066d1 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -33,8 +33,8 @@
 __hostprogs := $(sort $(hostprogs-y)$(hostprogs-m))
 
 # hostprogs-y := tools/build may have been specified. Retreive directory
-obj-dirs += $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
-obj-dirs := $(strip $(sort $(filter-out ./,$(obj-dirs))))
+host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f))))
+host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs))))
 
 
 # C code
@@ -73,7 +73,9 @@
 host-cxxobjs	:= $(addprefix $(obj)/,$(host-cxxobjs))
 host-cshlib	:= $(addprefix $(obj)/,$(host-cshlib))
 host-cshobjs	:= $(addprefix $(obj)/,$(host-cshobjs))
-obj-dirs        := $(addprefix $(obj)/,$(obj-dirs))
+host-objdirs    := $(addprefix $(obj)/,$(host-objdirs))
+
+obj-dirs += $(host-objdirs)
 
 #####
 # Handle options to gcc. Support building with separate output directory
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index 2686dd5..f0ff248 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -17,7 +17,7 @@
 	@:
 
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2)
+      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 0e056cf..576cce5 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -35,7 +35,7 @@
 PHONY := _modpost
 _modpost: __modpost
 
-include .config
+include include/config/auto.conf
 include scripts/Kbuild.include
 include scripts/Makefile.lib
 
diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile
index f22e94c..2f60070 100644
--- a/scripts/basic/Makefile
+++ b/scripts/basic/Makefile
@@ -1,17 +1,15 @@
 ###
 # Makefile.basic list the most basic programs used during the build process.
 # The programs listed herein is what is needed to do the basic stuff,
-# such as splitting .config and fix dependency file.
+# such as fix dependency file.
 # This initial step is needed to avoid files to be recompiled
 # when kernel configuration changes (which is what happens when
 # .config is included by main Makefile.
 # ---------------------------------------------------------------------------
 # fixdep: 	 Used to generate dependency information during build process
-# split-include: Divide all config symbols up in a number of files in
-#                include/config/...
 # docproc:	 Used in Documentation/docbook
 
-hostprogs-y	:= fixdep split-include docproc
+hostprogs-y	:= fixdep docproc
 always		:= $(hostprogs-y)
 
 # fixdep is needed to compile other host programs
diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c
deleted file mode 100644
index 459c4527..0000000
--- a/scripts/basic/split-include.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * split-include.c
- *
- * Copyright abandoned, Michael Chastain, <mailto:mec@shout.net>.
- * This is a C version of syncdep.pl by Werner Almesberger.
- *
- * This program takes autoconf.h as input and outputs a directory full
- * of one-line include files, merging onto the old values.
- *
- * Think of the configuration options as key-value pairs.  Then there
- * are five cases:
- *
- *    key      old value   new value   action
- *
- *    KEY-1    VALUE-1     VALUE-1     leave file alone
- *    KEY-2    VALUE-2A    VALUE-2B    write VALUE-2B into file
- *    KEY-3    -           VALUE-3     write VALUE-3  into file
- *    KEY-4    VALUE-4     -           write an empty file
- *    KEY-5    (empty)     -           leave old empty file alone
- */
-
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define ERROR_EXIT(strExit)						\
-    {									\
-	const int errnoSave = errno;					\
-	fprintf(stderr, "%s: ", str_my_name);				\
-	errno = errnoSave;						\
-	perror((strExit));						\
-	exit(1);							\
-    }
-
-
-
-int main(int argc, const char * argv [])
-{
-    const char * str_my_name;
-    const char * str_file_autoconf;
-    const char * str_dir_config;
-
-    FILE * fp_config;
-    FILE * fp_target;
-    FILE * fp_find;
-
-    int buffer_size;
-
-    char * line;
-    char * old_line;
-    char * list_target;
-    char * ptarget;
-
-    struct stat stat_buf;
-
-    /* Check arg count. */
-    if (argc != 3)
-    {
-	fprintf(stderr, "%s: wrong number of arguments.\n", argv[0]);
-	exit(1);
-    }
-
-    str_my_name       = argv[0];
-    str_file_autoconf = argv[1];
-    str_dir_config    = argv[2];
-
-    /* Find a buffer size. */
-    if (stat(str_file_autoconf, &stat_buf) != 0)
-	ERROR_EXIT(str_file_autoconf);
-    buffer_size = 2 * stat_buf.st_size + 4096;
-
-    /* Allocate buffers. */
-    if ( (line        = malloc(buffer_size)) == NULL
-    ||   (old_line    = malloc(buffer_size)) == NULL
-    ||   (list_target = malloc(buffer_size)) == NULL )
-	ERROR_EXIT(str_file_autoconf);
-
-    /* Open autoconfig file. */
-    if ((fp_config = fopen(str_file_autoconf, "r")) == NULL)
-	ERROR_EXIT(str_file_autoconf);
-
-    /* Make output directory if needed. */
-    if (stat(str_dir_config, &stat_buf) != 0)
-    {
-	if (mkdir(str_dir_config, 0755) != 0)
-	    ERROR_EXIT(str_dir_config);
-    }
-
-    /* Change to output directory. */
-    if (chdir(str_dir_config) != 0)
-	ERROR_EXIT(str_dir_config);
-
-    /* Put initial separator into target list. */
-    ptarget = list_target;
-    *ptarget++ = '\n';
-
-    /* Read config lines. */
-    while (fgets(line, buffer_size, fp_config))
-    {
-	const char * str_config;
-	int is_same;
-	int itarget;
-
-	if (line[0] != '#')
-	    continue;
-	if ((str_config = strstr(line, "CONFIG_")) == NULL)
-	    continue;
-
-	/* Make the output file name. */
-	str_config += sizeof("CONFIG_") - 1;
-	for (itarget = 0; !isspace(str_config[itarget]); itarget++)
-	{
-	    int c = (unsigned char) str_config[itarget];
-	    if (isupper(c)) c = tolower(c);
-	    if (c == '_')   c = '/';
-	    ptarget[itarget] = c;
-	}
-	ptarget[itarget++] = '.';
-	ptarget[itarget++] = 'h';
-	ptarget[itarget++] = '\0';
-
-	/* Check for existing file. */
-	is_same = 0;
-	if ((fp_target = fopen(ptarget, "r")) != NULL)
-	{
-	    fgets(old_line, buffer_size, fp_target);
-	    if (fclose(fp_target) != 0)
-		ERROR_EXIT(ptarget);
-	    if (!strcmp(line, old_line))
-		is_same = 1;
-	}
-
-	if (!is_same)
-	{
-	    /* Auto-create directories. */
-	    int islash;
-	    for (islash = 0; islash < itarget; islash++)
-	    {
-		if (ptarget[islash] == '/')
-		{
-		    ptarget[islash] = '\0';
-		    if (stat(ptarget, &stat_buf) != 0
-		    &&  mkdir(ptarget, 0755)     != 0)
-			ERROR_EXIT( ptarget );
-		    ptarget[islash] = '/';
-		}
-	    }
-
-	    /* Write the file. */
-	    if ((fp_target = fopen(ptarget, "w" )) == NULL)
-		ERROR_EXIT(ptarget);
-	    fputs(line, fp_target);
-	    if (ferror(fp_target) || fclose(fp_target) != 0)
-		ERROR_EXIT(ptarget);
-	}
-
-	/* Update target list */
-	ptarget += itarget;
-	*(ptarget-1) = '\n';
-    }
-
-    /*
-     * Close autoconfig file.
-     * Terminate the target list.
-     */
-    if (fclose(fp_config) != 0)
-	ERROR_EXIT(str_file_autoconf);
-    *ptarget = '\0';
-
-    /*
-     * Fix up existing files which have no new value.
-     * This is Case 4 and Case 5.
-     *
-     * I re-read the tree and filter it against list_target.
-     * This is crude.  But it avoids data copies.  Also, list_target
-     * is compact and contiguous, so it easily fits into cache.
-     *
-     * Notice that list_target contains strings separated by \n,
-     * with a \n before the first string and after the last.
-     * fgets gives the incoming names a terminating \n.
-     * So by having an initial \n, strstr will find exact matches.
-     */
-
-    fp_find = popen("find * -type f -name \"*.h\" -print", "r");
-    if (fp_find == 0)
-	ERROR_EXIT( "find" );
-
-    line[0] = '\n';
-    while (fgets(line+1, buffer_size, fp_find))
-    {
-	if (strstr(list_target, line) == NULL)
-	{
-	    /*
-	     * This is an old file with no CONFIG_* flag in autoconf.h.
-	     */
-
-	    /* First strip the \n. */
-	    line[strlen(line)-1] = '\0';
-
-	    /* Grab size. */
-	    if (stat(line+1, &stat_buf) != 0)
-		ERROR_EXIT(line);
-
-	    /* If file is not empty, make it empty and give it a fresh date. */
-	    if (stat_buf.st_size != 0)
-	    {
-		if ((fp_target = fopen(line+1, "w")) == NULL)
-		    ERROR_EXIT(line);
-		if (fclose(fp_target) != 0)
-		    ERROR_EXIT(line);
-	    }
-	}
-    }
-
-    if (pclose(fp_find) != 0)
-	ERROR_EXIT("find");
-
-    return 0;
-}
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
index 75f21d8..ce59fc2 100755
--- a/scripts/bloat-o-meter
+++ b/scripts/bloat-o-meter
@@ -18,7 +18,8 @@
     for l in os.popen("nm --size-sort " + file).readlines():
         size, type, name = l[:-1].split()
         if type in "tTdDbB":
-            sym[name] = int(size, 16)
+            if "." in name: name = "static." + name.split(".")[0]
+            sym[name] = sym.get(name, 0) + int(size, 16)
     return sym
 
 old = getsizes(sys.argv[1])
diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl
index dadfa20..b349246 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -89,11 +89,21 @@
 #
 my $funcre = qr/^$x* <(.*)>:$/;
 my $func;
+my $file, $lastslash;
+
 while (my $line = <STDIN>) {
 	if ($line =~ m/$funcre/) {
 		$func = $1;
 	}
-	if ($line =~ m/$re/) {
+	elsif ($line =~ m/(.*):\s*file format/) {
+		$file = $1;
+		$file =~ s/\.ko//;
+		$lastslash = rindex($file, "/");
+		if ($lastslash != -1) {
+			$file = substr($file, $lastslash + 1);
+		}
+	}
+	elsif ($line =~ m/$re/) {
 		my $size = $1;
 		$size = hex($size) if ($size =~ /^0x/);
 
@@ -109,7 +119,7 @@
 		$addr =~ s/ /0/g;
 		$addr = "0x$addr";
 
-		my $intro = "$addr $func:";
+		my $intro = "$addr $func [$file]:";
 		my $padlen = 56 - length($intro);
 		while ($padlen > 0) {
 			$intro .= '	';
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
new file mode 100644
index 0000000..9ed00d9
--- /dev/null
+++ b/scripts/export_report.pl
@@ -0,0 +1,169 @@
+#!/usr/bin/perl -w
+#
+# (C) Copyright IBM Corporation 2006.
+#	Released under GPL v2.
+#	Author : Ram Pai (linuxram@us.ibm.com)
+#
+# Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c
+#
+
+use Getopt::Std;
+use strict;
+
+sub numerically {
+	my $no1 = (split /\s+/, $a)[1];
+	my $no2 = (split /\s+/, $b)[1];
+	return $no1 <=> $no2;
+}
+
+sub alphabetically {
+	my ($module1, $value1) = @{$a};
+	my ($module2, $value2) = @{$b};
+	return $value1 <=> $value2 || $module2 cmp $module1;
+}
+
+sub print_depends_on {
+	my ($href) = @_;
+	print "\n";
+	while (my ($mod, $list) = each %$href) {
+		print "\t$mod:\n";
+		foreach my $sym (sort numerically @{$list}) {
+			my ($symbol, $no) = split /\s+/, $sym;
+			printf("\t\t%-25s\t%-25d\n", $symbol, $no);
+		}
+		print "\n";
+	}
+	print "\n";
+	print "~"x80 , "\n";
+}
+
+sub usage {
+        print "Usage: @_ -h -k Module.symvers  [ -o outputfile ] \n",
+	      "\t-f: treat all the non-option argument as .mod.c files. ",
+	      "Recommend using this as the last option\n",
+	      "\t-h: print detailed help\n",
+	      "\t-k: the path to Module.symvers file. By default uses ",
+	      "the file from the current directory\n",
+	      "\t-o outputfile: output the report to outputfile\n";
+	exit 0;
+}
+
+sub collectcfiles {
+        my @file = `cat .tmp_versions/*.mod | grep '.*\.ko\$'`;
+        @file = grep {s/\.ko/.mod.c/} @file;
+	chomp @file;
+        return @file;
+}
+
+my (%SYMBOL, %MODULE, %opt, @allcfiles);
+
+if (not getopts('hk:o:f',\%opt) or defined $opt{'h'}) {
+        usage($0);
+}
+
+if (defined $opt{'f'}) {
+	@allcfiles = @ARGV;
+} else {
+	@allcfiles = collectcfiles();
+}
+
+if (not defined $opt{'k'}) {
+	$opt{'k'} = "Module.symvers";
+}
+
+unless (open(MODULE_SYMVERS, $opt{'k'})) {
+	die "Sorry, cannot open $opt{'k'}: $!\n";
+}
+
+if (defined $opt{'o'}) {
+	unless (open(OUTPUT_HANDLE, ">$opt{'o'}")) {
+		die "Sorry, cannot open $opt{'o'} $!\n";
+	}
+	select OUTPUT_HANDLE;
+}
+#
+# collect all the symbols and their attributes from the
+# Module.symvers file
+#
+while ( <MODULE_SYMVERS> ) {
+	chomp;
+	my (undef, $symbol, $module, $gpl) = split;
+	$SYMBOL { $symbol } =  [ $module , "0" , $symbol, $gpl];
+}
+close(MODULE_SYMVERS);
+
+#
+# collect the usage count of each symbol.
+#
+foreach my $thismod (@allcfiles) {
+	unless (open(MODULE_MODULE, $thismod)) {
+		print "Sorry, cannot open $thismod: $!\n";
+		next;
+	}
+	my $state=0;
+	while ( <MODULE_MODULE> ) {
+		chomp;
+		if ($state eq 0) {
+			$state = 1 if ($_ =~ /static const struct modversion_info/);
+			next;
+		}
+		if ($state eq 1) {
+			$state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/);
+			next;
+		}
+		if ($state eq 2) {
+			if ( $_ !~ /0x[0-9a-f]{7,8},/ ) {
+				next;
+			}
+			my $sym = (split /([,"])/,)[4];
+			my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}};
+			$SYMBOL{ $sym } =  [ $module, $value+1, $symbol, $gpl];
+			push(@{$MODULE{$thismod}} , $sym);
+		}
+	}
+	if ($state ne 2) {
+		print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n";
+	}
+	close(MODULE_MODULE);
+}
+
+print "\tThis file reports the exported symbols usage patterns by in-tree\n",
+	"\t\t\t\tmodules\n";
+printf("%s\n\n\n","x"x80);
+printf("\t\t\t\tINDEX\n\n\n");
+printf("SECTION 1: Usage counts of all exported symbols\n");
+printf("SECTION 2: List of modules and the exported symbols they use\n");
+printf("%s\n\n\n","x"x80);
+printf("SECTION 1:\tThe exported symbols and their usage count\n\n");
+printf("%-25s\t%-25s\t%-5s\t%-25s\n", "Symbol", "Module", "Usage count",
+	"export type");
+
+#
+# print the list of unused exported symbols
+#
+foreach my $list (sort alphabetically values(%SYMBOL)) {
+	my ($module, $value, $symbol, $gpl) = @{$list};
+	printf("%-25s\t%-25s\t%-10s\t", $symbol, $module, $value);
+	if (defined $gpl) {
+		printf("%-25s\n",$gpl);
+	} else {
+		printf("\n");
+	}
+}
+printf("%s\n\n\n","x"x80);
+
+printf("SECTION 2:\n\tThis section reports export-symbol-usage of in-kernel
+modules. Each module lists the modules, and the symbols from that module that
+it uses.  Each listed symbol reports the number of modules using it\n");
+
+print "~"x80 , "\n";
+while (my ($thismod, $list) = each %MODULE) {
+	my %depends;
+	$thismod =~ s/\.mod\.c/.ko/;
+	print "\t\t\t$thismod\n";
+	foreach my $symbol (@{$list}) {
+		my ($module, $value, undef, $gpl) = @{$SYMBOL{$symbol}};
+		push (@{$depends{"$module"}}, "$symbol $value");
+	}
+	print_depends_on(\%depends);
+}
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index 5b0344e..b038182 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -42,7 +42,7 @@
 int cur_line = 1;
 char *cur_filename;
 
-static int flag_debug, flag_dump_defs, flag_warnings;
+static int flag_debug, flag_dump_defs, flag_dump_types, flag_warnings;
 static const char *arch = "";
 static const char *mod_prefix = "";
 
@@ -50,6 +50,7 @@
 static int nsyms;
 
 static struct symbol *expansion_trail;
+static struct symbol *visited_symbols;
 
 static const char *const symbol_type_name[] = {
 	"normal", "typedef", "enum", "struct", "union"
@@ -176,6 +177,7 @@
 	sym->type = type;
 	sym->defn = defn;
 	sym->expansion_trail = NULL;
+	sym->visited = NULL;
 	sym->is_extern = is_extern;
 
 	sym->hash_next = symtab[h];
@@ -236,26 +238,11 @@
 
 static void print_node(FILE * f, struct string_list *list)
 {
-	switch (list->tag) {
-	case SYM_STRUCT:
-		putc('s', f);
-		goto printit;
-	case SYM_UNION:
-		putc('u', f);
-		goto printit;
-	case SYM_ENUM:
-		putc('e', f);
-		goto printit;
-	case SYM_TYPEDEF:
-		putc('t', f);
-		goto printit;
-
-	      printit:
+	if (list->tag != SYM_NORMAL) {
+		putc(symbol_type_name[list->tag][0], f);
 		putc('#', f);
-	case SYM_NORMAL:
-		fputs(list->string, f);
-		break;
 	}
+	fputs(list->string, f);
 }
 
 static void print_list(FILE * f, struct string_list *list)
@@ -287,9 +274,9 @@
 	}
 }
 
-static unsigned long expand_and_crc_list(struct string_list *list,
-					 unsigned long crc)
+static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
 {
+	struct string_list *list = sym->defn;
 	struct string_list **e, **b;
 	struct string_list *tmp, **tmp2;
 	int elem = 1;
@@ -332,7 +319,7 @@
 			} else {
 				subsym->expansion_trail = expansion_trail;
 				expansion_trail = subsym;
-				crc = expand_and_crc_list(subsym->defn, crc);
+				crc = expand_and_crc_sym(subsym, crc);
 			}
 			break;
 
@@ -382,12 +369,22 @@
 			} else {
 				subsym->expansion_trail = expansion_trail;
 				expansion_trail = subsym;
-				crc = expand_and_crc_list(subsym->defn, crc);
+				crc = expand_and_crc_sym(subsym, crc);
 			}
 			break;
 		}
 	}
 
+	{
+		static struct symbol **end = &visited_symbols;
+
+		if (!sym->visited) {
+			*end = sym;
+			end = &sym->visited;
+			sym->visited = (struct symbol *)-1L;
+		}
+	}
+
 	return crc;
 }
 
@@ -406,7 +403,7 @@
 
 		expansion_trail = (struct symbol *)-1L;
 
-		crc = expand_and_crc_list(sym->defn, 0xffffffff) ^ 0xffffffff;
+		crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
 
 		sym = expansion_trail;
 		while (sym != (struct symbol *)-1L) {
@@ -464,6 +461,7 @@
 
 int main(int argc, char **argv)
 {
+	FILE *dumpfile = NULL;
 	int o;
 
 #ifdef __GNU_LIBRARY__
@@ -473,15 +471,16 @@
 		{"warnings", 0, 0, 'w'},
 		{"quiet", 0, 0, 'q'},
 		{"dump", 0, 0, 'D'},
+		{"dump-types", 1, 0, 'T'},
 		{"version", 0, 0, 'V'},
 		{"help", 0, 0, 'h'},
 		{0, 0, 0, 0}
 	};
 
-	while ((o = getopt_long(argc, argv, "a:dwqVDk:p:",
+	while ((o = getopt_long(argc, argv, "a:dwqVDT:k:p:",
 				&long_opts[0], NULL)) != EOF)
 #else				/* __GNU_LIBRARY__ */
-	while ((o = getopt(argc, argv, "a:dwqVDk:p:")) != EOF)
+	while ((o = getopt(argc, argv, "a:dwqVDT:k:p:")) != EOF)
 #endif				/* __GNU_LIBRARY__ */
 		switch (o) {
 		case 'a':
@@ -502,6 +501,14 @@
 		case 'D':
 			flag_dump_defs = 1;
 			break;
+		case 'T':
+			flag_dump_types = 1;
+			dumpfile = fopen(optarg, "w");
+			if (!dumpfile) {
+				perror(optarg);
+				return 1;
+			}
+			break;
 		case 'h':
 			genksyms_usage();
 			return 0;
@@ -524,6 +531,24 @@
 
 	yyparse();
 
+	if (flag_dump_types && visited_symbols) {
+		while (visited_symbols != (struct symbol *)-1L) {
+			struct symbol *sym = visited_symbols;
+
+			if (sym->type != SYM_NORMAL) {
+				putc(symbol_type_name[sym->type][0], dumpfile);
+				putc('#', dumpfile);
+			}
+			fputs(sym->name, dumpfile);
+			putc(' ', dumpfile);
+			print_list(dumpfile, sym->defn);
+			putc('\n', dumpfile);
+
+			visited_symbols = sym->visited;
+			sym->visited = NULL;
+		}
+	}
+
 	if (flag_debug) {
 		fprintf(debugfile, "Hash table occupancy %d/%d = %g\n",
 			nsyms, HASH_BUCKETS,
diff --git a/scripts/genksyms/genksyms.h b/scripts/genksyms/genksyms.h
index ab6f34f..2668287 100644
--- a/scripts/genksyms/genksyms.h
+++ b/scripts/genksyms/genksyms.h
@@ -41,6 +41,7 @@
 	enum symbol_type type;
 	struct string_list *defn;
 	struct symbol *expansion_trail;
+	struct symbol *visited;
 	int is_extern;
 };
 
diff --git a/scripts/genksyms/lex.c_shipped b/scripts/genksyms/lex.c_shipped
index 1218053..37ba982 100644
--- a/scripts/genksyms/lex.c_shipped
+++ b/scripts/genksyms/lex.c_shipped
@@ -2023,7 +2023,7 @@
       break;
 
     default:
-      abort();
+      exit(1);
     }
 fini:
 
diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l
index fe0dfee..5e544a0 100644
--- a/scripts/genksyms/lex.l
+++ b/scripts/genksyms/lex.l
@@ -392,7 +392,7 @@
       break;
 
     default:
-      abort();
+      exit(1);
     }
 fini:
 
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 8012d10..4dcb8867 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -539,6 +539,7 @@
   	name = av[i];
 	if (!name) {
 		printf(_("%s: Kconfig file missing\n"), av[0]);
+		exit(1);
 	}
 	conf_parse(name);
 	//zconfdump(stdout);
@@ -573,7 +574,7 @@
 	case set_random:
 		name = getenv("KCONFIG_ALLCONFIG");
 		if (name && !stat(name, &tmpstat)) {
-			conf_read_simple(name);
+			conf_read_simple(name, S_DEF_USER);
 			break;
 		}
 		switch (input_mode) {
@@ -584,9 +585,9 @@
 		default: break;
 		}
 		if (!stat(name, &tmpstat))
-			conf_read_simple(name);
+			conf_read_simple(name, S_DEF_USER);
 		else if (!stat("all.config", &tmpstat))
-			conf_read_simple("all.config");
+			conf_read_simple("all.config", S_DEF_USER);
 		break;
 	default:
 		break;
@@ -599,7 +600,15 @@
 			input_mode = ask_silent;
 			valid_stdin = 1;
 		}
-	}
+	} else if (sym_change_count) {
+		name = getenv("KCONFIG_NOSILENTUPDATE");
+		if (name && *name) {
+			fprintf(stderr, _("\n*** Kernel configuration requires explicit update.\n\n"));
+			return 1;
+		}
+	} else
+		goto skip_check;
+
 	do {
 		conf_cnt = 0;
 		check_conf(&rootmenu);
@@ -608,5 +617,11 @@
 		fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
 		return 1;
 	}
+skip_check:
+	if (input_mode == ask_silent && conf_write_autoconf()) {
+		fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
+		return 1;
+	}
+
 	return 0;
 }
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 1b5df58..2ee48c37 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -5,6 +5,7 @@
 
 #include <sys/stat.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,19 +21,8 @@
 static const char *conf_filename;
 static int conf_lineno, conf_warnings, conf_unsaved;
 
-const char conf_def_filename[] = ".config";
-
 const char conf_defname[] = "arch/$ARCH/defconfig";
 
-const char *conf_confnames[] = {
-	".config",
-	"/lib/modules/$UNAME_RELEASE/.config",
-	"/etc/kernel-config",
-	"/boot/config-$UNAME_RELEASE",
-	conf_defname,
-	NULL,
-};
-
 static void conf_warning(const char *fmt, ...)
 {
 	va_list ap;
@@ -44,6 +34,13 @@
 	conf_warnings++;
 }
 
+const char *conf_get_configname(void)
+{
+	char *name = getenv("KCONFIG_CONFIG");
+
+	return name ? name : ".config";
+}
+
 static char *conf_expand_value(const char *in)
 {
 	struct symbol *sym;
@@ -86,51 +83,65 @@
 	return name;
 }
 
-int conf_read_simple(const char *name)
+int conf_read_simple(const char *name, int def)
 {
 	FILE *in = NULL;
 	char line[1024];
 	char *p, *p2;
 	struct symbol *sym;
-	int i;
+	int i, def_flags;
 
 	if (name) {
 		in = zconf_fopen(name);
 	} else {
-		const char **names = conf_confnames;
-		while ((name = *names++)) {
-			name = conf_expand_value(name);
+		struct property *prop;
+
+		name = conf_get_configname();
+		in = zconf_fopen(name);
+		if (in)
+			goto load;
+		sym_change_count++;
+		if (!sym_defconfig_list)
+			return 1;
+
+		for_all_defaults(sym_defconfig_list, prop) {
+			if (expr_calc_value(prop->visible.expr) == no ||
+			    prop->expr->type != E_SYMBOL)
+				continue;
+			name = conf_expand_value(prop->expr->left.sym->name);
 			in = zconf_fopen(name);
 			if (in) {
 				printf(_("#\n"
-				         "# using defaults found in %s\n"
-				         "#\n"), name);
-				break;
+					 "# using defaults found in %s\n"
+					 "#\n"), name);
+				goto load;
 			}
 		}
 	}
 	if (!in)
 		return 1;
 
+load:
 	conf_filename = name;
 	conf_lineno = 0;
 	conf_warnings = 0;
 	conf_unsaved = 0;
 
+	def_flags = SYMBOL_DEF << def;
 	for_all_symbols(i, sym) {
-		sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
+		sym->flags |= SYMBOL_CHANGED;
+		sym->flags &= ~(def_flags|SYMBOL_VALID);
 		if (sym_is_choice(sym))
-			sym->flags &= ~SYMBOL_NEW;
-		sym->flags &= ~SYMBOL_VALID;
+			sym->flags |= def_flags;
 		switch (sym->type) {
 		case S_INT:
 		case S_HEX:
 		case S_STRING:
-			if (sym->user.val)
-				free(sym->user.val);
+			if (sym->def[def].val)
+				free(sym->def[def].val);
 		default:
-			sym->user.val = NULL;
-			sym->user.tri = no;
+			sym->def[def].val = NULL;
+			sym->def[def].tri = no;
 		}
 	}
 
@@ -147,19 +158,26 @@
 			*p++ = 0;
 			if (strncmp(p, "is not set", 10))
 				continue;
-			sym = sym_find(line + 9);
-			if (!sym) {
-				conf_warning("trying to assign nonexistent symbol %s", line + 9);
-				break;
-			} else if (!(sym->flags & SYMBOL_NEW)) {
+			if (def == S_DEF_USER) {
+				sym = sym_find(line + 9);
+				if (!sym) {
+					conf_warning("trying to assign nonexistent symbol %s", line + 9);
+					break;
+				}
+			} else {
+				sym = sym_lookup(line + 9, 0);
+				if (sym->type == S_UNKNOWN)
+					sym->type = S_BOOLEAN;
+			}
+			if (sym->flags & def_flags) {
 				conf_warning("trying to reassign symbol %s", sym->name);
 				break;
 			}
 			switch (sym->type) {
 			case S_BOOLEAN:
 			case S_TRISTATE:
-				sym->user.tri = no;
-				sym->flags &= ~SYMBOL_NEW;
+				sym->def[def].tri = no;
+				sym->flags |= def_flags;
 				break;
 			default:
 				;
@@ -177,34 +195,48 @@
 			p2 = strchr(p, '\n');
 			if (p2)
 				*p2 = 0;
-			sym = sym_find(line + 7);
-			if (!sym) {
-				conf_warning("trying to assign nonexistent symbol %s", line + 7);
-				break;
-			} else if (!(sym->flags & SYMBOL_NEW)) {
+			if (def == S_DEF_USER) {
+				sym = sym_find(line + 7);
+				if (!sym) {
+					conf_warning("trying to assign nonexistent symbol %s", line + 7);
+					break;
+				}
+			} else {
+				sym = sym_lookup(line + 7, 0);
+				if (sym->type == S_UNKNOWN)
+					sym->type = S_OTHER;
+			}
+			if (sym->flags & def_flags) {
 				conf_warning("trying to reassign symbol %s", sym->name);
 				break;
 			}
 			switch (sym->type) {
 			case S_TRISTATE:
 				if (p[0] == 'm') {
-					sym->user.tri = mod;
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].tri = mod;
+					sym->flags |= def_flags;
 					break;
 				}
 			case S_BOOLEAN:
 				if (p[0] == 'y') {
-					sym->user.tri = yes;
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].tri = yes;
+					sym->flags |= def_flags;
 					break;
 				}
 				if (p[0] == 'n') {
-					sym->user.tri = no;
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].tri = no;
+					sym->flags |= def_flags;
 					break;
 				}
 				conf_warning("symbol value '%s' invalid for %s", p, sym->name);
 				break;
+			case S_OTHER:
+				if (*p != '"') {
+					for (p2 = p; *p2 && !isspace(*p2); p2++)
+						;
+					sym->type = S_STRING;
+					goto done;
+				}
 			case S_STRING:
 				if (*p++ != '"')
 					break;
@@ -221,9 +253,10 @@
 				}
 			case S_INT:
 			case S_HEX:
+			done:
 				if (sym_string_valid(sym, p)) {
-					sym->user.val = strdup(p);
-					sym->flags &= ~SYMBOL_NEW;
+					sym->def[def].val = strdup(p);
+					sym->flags |= def_flags;
 				} else {
 					conf_warning("symbol value '%s' invalid for %s", p, sym->name);
 					continue;
@@ -241,24 +274,24 @@
 		}
 		if (sym && sym_is_choice_value(sym)) {
 			struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
-			switch (sym->user.tri) {
+			switch (sym->def[def].tri) {
 			case no:
 				break;
 			case mod:
-				if (cs->user.tri == yes) {
+				if (cs->def[def].tri == yes) {
 					conf_warning("%s creates inconsistent choice state", sym->name);
-					cs->flags |= SYMBOL_NEW;
+					cs->flags &= ~def_flags;
 				}
 				break;
 			case yes:
-				if (cs->user.tri != no) {
+				if (cs->def[def].tri != no) {
 					conf_warning("%s creates inconsistent choice state", sym->name);
-					cs->flags |= SYMBOL_NEW;
+					cs->flags &= ~def_flags;
 				} else
-					cs->user.val = sym;
+					cs->def[def].val = sym;
 				break;
 			}
-			cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
+			cs->def[def].tri = E_OR(cs->def[def].tri, sym->def[def].tri);
 		}
 	}
 	fclose(in);
@@ -273,9 +306,11 @@
 	struct symbol *sym;
 	struct property *prop;
 	struct expr *e;
-	int i;
+	int i, flags;
 
-	if (conf_read_simple(name))
+	sym_change_count = 0;
+
+	if (conf_read_simple(name, S_DEF_USER))
 		return 1;
 
 	for_all_symbols(i, sym) {
@@ -287,12 +322,12 @@
 			switch (sym->type) {
 			case S_BOOLEAN:
 			case S_TRISTATE:
-				if (sym->user.tri != sym_get_tristate_value(sym))
+				if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym))
 					break;
 				if (!sym_is_choice(sym))
 					goto sym_ok;
 			default:
-				if (!strcmp(sym->curr.val, sym->user.val))
+				if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val))
 					goto sym_ok;
 				break;
 			}
@@ -304,15 +339,13 @@
 	sym_ok:
 		if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
 			if (sym->visible == no)
-				sym->flags |= SYMBOL_NEW;
+				sym->flags &= ~SYMBOL_DEF_USER;
 			switch (sym->type) {
 			case S_STRING:
 			case S_INT:
 			case S_HEX:
-				if (!sym_string_within_range(sym, sym->user.val)) {
-					sym->flags |= SYMBOL_NEW;
-					sym->flags &= ~SYMBOL_VALID;
-				}
+				if (!sym_string_within_range(sym, sym->def[S_DEF_USER].val))
+					sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER);
 			default:
 				break;
 			}
@@ -320,19 +353,21 @@
 		if (!sym_is_choice(sym))
 			continue;
 		prop = sym_get_choice_prop(sym);
+		flags = sym->flags;
 		for (e = prop->expr; e; e = e->left.expr)
 			if (e->right.sym->visible != no)
-				sym->flags |= e->right.sym->flags & SYMBOL_NEW;
+				flags &= e->right.sym->flags;
+		sym->flags |= flags & SYMBOL_DEF_USER;
 	}
 
-	sym_change_count = conf_warnings || conf_unsaved;
+	sym_change_count += conf_warnings || conf_unsaved;
 
 	return 0;
 }
 
 int conf_write(const char *name)
 {
-	FILE *out, *out_h;
+	FILE *out;
 	struct symbol *sym;
 	struct menu *menu;
 	const char *basename;
@@ -351,7 +386,7 @@
 		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
 			strcpy(dirname, name);
 			strcat(dirname, "/");
-			basename = conf_def_filename;
+			basename = conf_get_configname();
 		} else if ((slash = strrchr(name, '/'))) {
 			int size = slash - name + 1;
 			memcpy(dirname, name, size);
@@ -359,23 +394,24 @@
 			if (slash[1])
 				basename = slash + 1;
 			else
-				basename = conf_def_filename;
+				basename = conf_get_configname();
 		} else
 			basename = name;
 	} else
-		basename = conf_def_filename;
+		basename = conf_get_configname();
 
-	sprintf(newname, "%s.tmpconfig.%d", dirname, (int)getpid());
-	out = fopen(newname, "w");
+	sprintf(newname, "%s%s", dirname, basename);
+	env = getenv("KCONFIG_OVERWRITECONFIG");
+	if (!env || !*env) {
+		sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid());
+		out = fopen(tmpname, "w");
+	} else {
+		*tmpname = 0;
+		out = fopen(newname, "w");
+	}
 	if (!out)
 		return 1;
-	out_h = NULL;
-	if (!name) {
-		out_h = fopen(".tmpconfig.h", "w");
-		if (!out_h)
-			return 1;
-		file_write_dep(NULL);
-	}
+
 	sym = sym_lookup("KERNELVERSION", 0);
 	sym_calc_value(sym);
 	time(&now);
@@ -391,16 +427,6 @@
 		     sym_get_string_value(sym),
 		     use_timestamp ? "# " : "",
 		     use_timestamp ? ctime(&now) : "");
-	if (out_h)
-		fprintf(out_h, "/*\n"
-			       " * Automatically generated C config: don't edit\n"
-			       " * Linux kernel version: %s\n"
-			       "%s%s"
-			       " */\n"
-			       "#define AUTOCONF_INCLUDED\n",
-			       sym_get_string_value(sym),
-			       use_timestamp ? " * " : "",
-			       use_timestamp ? ctime(&now) : "");
 
 	if (!sym_change_count)
 		sym_clear_all_valid();
@@ -416,11 +442,6 @@
 				     "#\n"
 				     "# %s\n"
 				     "#\n", str);
-			if (out_h)
-				fprintf(out_h, "\n"
-					       "/*\n"
-					       " * %s\n"
-					       " */\n", str);
 		} else if (!(sym->flags & SYMBOL_CHOICE)) {
 			sym_calc_value(sym);
 			if (!(sym->flags & SYMBOL_WRITE))
@@ -438,59 +459,39 @@
 				switch (sym_get_tristate_value(sym)) {
 				case no:
 					fprintf(out, "# CONFIG_%s is not set\n", sym->name);
-					if (out_h)
-						fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
 					break;
 				case mod:
 					fprintf(out, "CONFIG_%s=m\n", sym->name);
-					if (out_h)
-						fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
 					break;
 				case yes:
 					fprintf(out, "CONFIG_%s=y\n", sym->name);
-					if (out_h)
-						fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
 					break;
 				}
 				break;
 			case S_STRING:
-				// fix me
 				str = sym_get_string_value(sym);
 				fprintf(out, "CONFIG_%s=\"", sym->name);
-				if (out_h)
-					fprintf(out_h, "#define CONFIG_%s \"", sym->name);
-				do {
+				while (1) {
 					l = strcspn(str, "\"\\");
 					if (l) {
 						fwrite(str, l, 1, out);
-						if (out_h)
-							fwrite(str, l, 1, out_h);
+						str += l;
 					}
-					str += l;
-					while (*str == '\\' || *str == '"') {
-						fprintf(out, "\\%c", *str);
-						if (out_h)
-							fprintf(out_h, "\\%c", *str);
-						str++;
-					}
-				} while (*str);
+					if (!*str)
+						break;
+					fprintf(out, "\\%c", *str++);
+				}
 				fputs("\"\n", out);
-				if (out_h)
-					fputs("\"\n", out_h);
 				break;
 			case S_HEX:
 				str = sym_get_string_value(sym);
 				if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
 					fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-					if (out_h)
-						fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
 					break;
 				}
 			case S_INT:
 				str = sym_get_string_value(sym);
 				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
-				if (out_h)
-					fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
 				break;
 			}
 		}
@@ -510,21 +511,253 @@
 		}
 	}
 	fclose(out);
-	if (out_h) {
-		fclose(out_h);
-		rename(".tmpconfig.h", "include/linux/autoconf.h");
+
+	if (*tmpname) {
+		strcat(dirname, name ? name : conf_get_configname());
+		strcat(dirname, ".old");
+		rename(newname, dirname);
+		if (rename(tmpname, newname))
+			return 1;
 	}
-	if (!name || basename != conf_def_filename) {
-		if (!name)
-			name = conf_def_filename;
-		sprintf(tmpname, "%s.old", name);
-		rename(name, tmpname);
-	}
-	sprintf(tmpname, "%s%s", dirname, basename);
-	if (rename(newname, tmpname))
-		return 1;
+
+	printf(_("#\n"
+		 "# configuration written to %s\n"
+		 "#\n"), newname);
 
 	sym_change_count = 0;
 
 	return 0;
 }
+
+int conf_split_config(void)
+{
+	char *name, path[128];
+	char *s, *d, c;
+	struct symbol *sym;
+	struct stat sb;
+	int res, i, fd;
+
+	name = getenv("KCONFIG_AUTOCONFIG");
+	if (!name)
+		name = "include/config/auto.conf";
+	conf_read_simple(name, S_DEF_AUTO);
+
+	if (chdir("include/config"))
+		return 1;
+
+	res = 0;
+	for_all_symbols(i, sym) {
+		sym_calc_value(sym);
+		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
+			continue;
+		if (sym->flags & SYMBOL_WRITE) {
+			if (sym->flags & SYMBOL_DEF_AUTO) {
+				/*
+				 * symbol has old and new value,
+				 * so compare them...
+				 */
+				switch (sym->type) {
+				case S_BOOLEAN:
+				case S_TRISTATE:
+					if (sym_get_tristate_value(sym) ==
+					    sym->def[S_DEF_AUTO].tri)
+						continue;
+					break;
+				case S_STRING:
+				case S_HEX:
+				case S_INT:
+					if (!strcmp(sym_get_string_value(sym),
+						    sym->def[S_DEF_AUTO].val))
+						continue;
+					break;
+				default:
+					break;
+				}
+			} else {
+				/*
+				 * If there is no old value, only 'no' (unset)
+				 * is allowed as new value.
+				 */
+				switch (sym->type) {
+				case S_BOOLEAN:
+				case S_TRISTATE:
+					if (sym_get_tristate_value(sym) == no)
+						continue;
+					break;
+				default:
+					break;
+				}
+			}
+		} else if (!(sym->flags & SYMBOL_DEF_AUTO))
+			/* There is neither an old nor a new value. */
+			continue;
+		/* else
+		 *	There is an old value, but no new value ('no' (unset)
+		 *	isn't saved in auto.conf, so the old value is always
+		 *	different from 'no').
+		 */
+
+		/* Replace all '_' and append ".h" */
+		s = sym->name;
+		d = path;
+		while ((c = *s++)) {
+			c = tolower(c);
+			*d++ = (c == '_') ? '/' : c;
+		}
+		strcpy(d, ".h");
+
+		/* Assume directory path already exists. */
+		fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+		if (fd == -1) {
+			if (errno != ENOENT) {
+				res = 1;
+				break;
+			}
+			/*
+			 * Create directory components,
+			 * unless they exist already.
+			 */
+			d = path;
+			while ((d = strchr(d, '/'))) {
+				*d = 0;
+				if (stat(path, &sb) && mkdir(path, 0755)) {
+					res = 1;
+					goto out;
+				}
+				*d++ = '/';
+			}
+			/* Try it again. */
+			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+			if (fd == -1) {
+				res = 1;
+				break;
+			}
+		}
+		close(fd);
+	}
+out:
+	if (chdir("../.."))
+		return 1;
+
+	return res;
+}
+
+int conf_write_autoconf(void)
+{
+	struct symbol *sym;
+	const char *str;
+	char *name;
+	FILE *out, *out_h;
+	time_t now;
+	int i, l;
+
+	sym_clear_all_valid();
+
+	file_write_dep("include/config/auto.conf.cmd");
+
+	if (conf_split_config())
+		return 1;
+
+	out = fopen(".tmpconfig", "w");
+	if (!out)
+		return 1;
+
+	out_h = fopen(".tmpconfig.h", "w");
+	if (!out_h) {
+		fclose(out);
+		return 1;
+	}
+
+	sym = sym_lookup("KERNELVERSION", 0);
+	sym_calc_value(sym);
+	time(&now);
+	fprintf(out, "#\n"
+		     "# Automatically generated make config: don't edit\n"
+		     "# Linux kernel version: %s\n"
+		     "# %s"
+		     "#\n",
+		     sym_get_string_value(sym), ctime(&now));
+	fprintf(out_h, "/*\n"
+		       " * Automatically generated C config: don't edit\n"
+		       " * Linux kernel version: %s\n"
+		       " * %s"
+		       " */\n"
+		       "#define AUTOCONF_INCLUDED\n",
+		       sym_get_string_value(sym), ctime(&now));
+
+	for_all_symbols(i, sym) {
+		sym_calc_value(sym);
+		if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
+			continue;
+		switch (sym->type) {
+		case S_BOOLEAN:
+		case S_TRISTATE:
+			switch (sym_get_tristate_value(sym)) {
+			case no:
+				break;
+			case mod:
+				fprintf(out, "CONFIG_%s=m\n", sym->name);
+				fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
+				break;
+			case yes:
+				fprintf(out, "CONFIG_%s=y\n", sym->name);
+				fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
+				break;
+			}
+			break;
+		case S_STRING:
+			str = sym_get_string_value(sym);
+			fprintf(out, "CONFIG_%s=\"", sym->name);
+			fprintf(out_h, "#define CONFIG_%s \"", sym->name);
+			while (1) {
+				l = strcspn(str, "\"\\");
+				if (l) {
+					fwrite(str, l, 1, out);
+					fwrite(str, l, 1, out_h);
+					str += l;
+				}
+				if (!*str)
+					break;
+				fprintf(out, "\\%c", *str);
+				fprintf(out_h, "\\%c", *str);
+				str++;
+			}
+			fputs("\"\n", out);
+			fputs("\"\n", out_h);
+			break;
+		case S_HEX:
+			str = sym_get_string_value(sym);
+			if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
+				fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+				fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
+				break;
+			}
+		case S_INT:
+			str = sym_get_string_value(sym);
+			fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
+			fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
+			break;
+		default:
+			break;
+		}
+	}
+	fclose(out);
+	fclose(out_h);
+
+	name = getenv("KCONFIG_AUTOHEADER");
+	if (!name)
+		name = "include/linux/autoconf.h";
+	if (rename(".tmpconfig.h", name))
+		return 1;
+	name = getenv("KCONFIG_AUTOCONFIG");
+	if (!name)
+		name = "include/config/auto.conf";
+	/*
+	 * This must be the last step, kbuild has a dependency on auto.conf
+	 * and this marks the successful completion of the previous steps.
+	 */
+	if (rename(".tmpconfig", name))
+		return 1;
+
+	return 0;
+}
diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 30e4f9d..6f98dbf 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -145,7 +145,8 @@
 		return;
 	}
 	if (e1->type == E_SYMBOL && e2->type == E_SYMBOL &&
-	    e1->left.sym == e2->left.sym && (e1->left.sym->flags & (SYMBOL_YES|SYMBOL_NO)))
+	    e1->left.sym == e2->left.sym &&
+	    (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no))
 		return;
 	if (!expr_eq(e1, e2))
 		return;
@@ -1012,73 +1013,73 @@
 #endif
 }
 
-void expr_print(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken)
+void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)
 {
 	if (!e) {
-		fn(data, "y");
+		fn(data, NULL, "y");
 		return;
 	}
 
 	if (expr_compare_type(prevtoken, e->type) > 0)
-		fn(data, "(");
+		fn(data, NULL, "(");
 	switch (e->type) {
 	case E_SYMBOL:
 		if (e->left.sym->name)
-			fn(data, e->left.sym->name);
+			fn(data, e->left.sym, e->left.sym->name);
 		else
-			fn(data, "<choice>");
+			fn(data, NULL, "<choice>");
 		break;
 	case E_NOT:
-		fn(data, "!");
+		fn(data, NULL, "!");
 		expr_print(e->left.expr, fn, data, E_NOT);
 		break;
 	case E_EQUAL:
-		fn(data, e->left.sym->name);
-		fn(data, "=");
-		fn(data, e->right.sym->name);
+		fn(data, e->left.sym, e->left.sym->name);
+		fn(data, NULL, "=");
+		fn(data, e->right.sym, e->right.sym->name);
 		break;
 	case E_UNEQUAL:
-		fn(data, e->left.sym->name);
-		fn(data, "!=");
-		fn(data, e->right.sym->name);
+		fn(data, e->left.sym, e->left.sym->name);
+		fn(data, NULL, "!=");
+		fn(data, e->right.sym, e->right.sym->name);
 		break;
 	case E_OR:
 		expr_print(e->left.expr, fn, data, E_OR);
-		fn(data, " || ");
+		fn(data, NULL, " || ");
 		expr_print(e->right.expr, fn, data, E_OR);
 		break;
 	case E_AND:
 		expr_print(e->left.expr, fn, data, E_AND);
-		fn(data, " && ");
+		fn(data, NULL, " && ");
 		expr_print(e->right.expr, fn, data, E_AND);
 		break;
 	case E_CHOICE:
-		fn(data, e->right.sym->name);
+		fn(data, e->right.sym, e->right.sym->name);
 		if (e->left.expr) {
-			fn(data, " ^ ");
+			fn(data, NULL, " ^ ");
 			expr_print(e->left.expr, fn, data, E_CHOICE);
 		}
 		break;
 	case E_RANGE:
-		fn(data, "[");
-		fn(data, e->left.sym->name);
-		fn(data, " ");
-		fn(data, e->right.sym->name);
-		fn(data, "]");
+		fn(data, NULL, "[");
+		fn(data, e->left.sym, e->left.sym->name);
+		fn(data, NULL, " ");
+		fn(data, e->right.sym, e->right.sym->name);
+		fn(data, NULL, "]");
 		break;
 	default:
 	  {
 		char buf[32];
 		sprintf(buf, "<unknown type %d>", e->type);
-		fn(data, buf);
+		fn(data, NULL, buf);
 		break;
 	  }
 	}
 	if (expr_compare_type(prevtoken, e->type) > 0)
-		fn(data, ")");
+		fn(data, NULL, ")");
 }
 
-static void expr_print_file_helper(void *data, const char *str)
+static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
 {
 	fwrite(str, strlen(str), 1, data);
 }
@@ -1088,7 +1089,7 @@
 	expr_print(e, expr_print_file_helper, out, E_NONE);
 }
 
-static void expr_print_gstr_helper(void *data, const char *str)
+static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str)
 {
 	str_append((struct gstr*)data, str);
 }
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 1b36ef1..6084525 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -63,12 +63,18 @@
 	S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER
 };
 
+enum {
+	S_DEF_USER,		/* main user value */
+	S_DEF_AUTO,
+};
+
 struct symbol {
 	struct symbol *next;
 	char *name;
 	char *help;
 	enum symbol_type type;
-	struct symbol_value curr, user;
+	struct symbol_value curr;
+	struct symbol_value def[4];
 	tristate visible;
 	int flags;
 	struct property *prop;
@@ -78,10 +84,7 @@
 
 #define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
 
-#define SYMBOL_YES		0x0001
-#define SYMBOL_MOD		0x0002
-#define SYMBOL_NO		0x0004
-#define SYMBOL_CONST		0x0007
+#define SYMBOL_CONST		0x0001
 #define SYMBOL_CHECK		0x0008
 #define SYMBOL_CHOICE		0x0010
 #define SYMBOL_CHOICEVAL	0x0020
@@ -90,10 +93,14 @@
 #define SYMBOL_OPTIONAL		0x0100
 #define SYMBOL_WRITE		0x0200
 #define SYMBOL_CHANGED		0x0400
-#define SYMBOL_NEW		0x0800
 #define SYMBOL_AUTO		0x1000
 #define SYMBOL_CHECKED		0x2000
 #define SYMBOL_WARNED		0x8000
+#define SYMBOL_DEF		0x10000
+#define SYMBOL_DEF_USER		0x10000
+#define SYMBOL_DEF_AUTO		0x20000
+#define SYMBOL_DEF3		0x40000
+#define SYMBOL_DEF4		0x80000
 
 #define SYMBOL_MAXLENGTH	256
 #define SYMBOL_HASHSIZE		257
@@ -149,6 +156,7 @@
 
 extern struct symbol symbol_yes, symbol_no, symbol_mod;
 extern struct symbol *modules_sym;
+extern struct symbol *sym_defconfig_list;
 extern int cdebug;
 struct expr *expr_alloc_symbol(struct symbol *sym);
 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce);
diff --git a/scripts/kconfig/gconf.c b/scripts/kconfig/gconf.c
index 665bd53..7b0d3a9 100644
--- a/scripts/kconfig/gconf.c
+++ b/scripts/kconfig/gconf.c
@@ -114,12 +114,6 @@
 
 	bzero(buf, 256);
 
-	if (val & SYMBOL_YES)
-		strcat(buf, "yes/");
-	if (val & SYMBOL_MOD)
-		strcat(buf, "mod/");
-	if (val & SYMBOL_NO)
-		strcat(buf, "no/");
 	if (val & SYMBOL_CONST)
 		strcat(buf, "const/");
 	if (val & SYMBOL_CHECK)
@@ -138,8 +132,6 @@
 		strcat(buf, "write/");
 	if (val & SYMBOL_CHANGED)
 		strcat(buf, "changed/");
-	if (val & SYMBOL_NEW)
-		strcat(buf, "new/");
 	if (val & SYMBOL_AUTO)
 		strcat(buf, "auto/");
 
@@ -1192,9 +1184,7 @@
 
 	row[COL_OPTION] =
 	    g_strdup_printf("%s %s", menu_get_prompt(menu),
-			    sym ? (sym->
-				   flags & SYMBOL_NEW ? "(NEW)" : "") :
-			    "");
+			    sym && sym_has_value(sym) ? "(NEW)" : "");
 
 	if (show_all && !menu_is_visible(menu))
 		row[COL_COLOR] = g_strdup("DarkGray");
diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped
index 24e3c8c..800f8c7 100644
--- a/scripts/kconfig/lex.zconf.c_shipped
+++ b/scripts/kconfig/lex.zconf.c_shipped
@@ -8,7 +8,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 31
+#define YY_FLEX_SUBMINOR_VERSION 33
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -30,7 +30,15 @@
 
 /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
 
-#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
 #include <inttypes.h>
 typedef int8_t flex_int8_t;
 typedef uint8_t flex_uint8_t;
@@ -134,6 +142,10 @@
 #define YY_BUF_SIZE 16384
 #endif
 
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
 #ifndef YY_TYPEDEF_YY_BUFFER_STATE
 #define YY_TYPEDEF_YY_BUFFER_STATE
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
@@ -267,7 +279,7 @@
 
 /* Points to current character in buffer. */
 static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1;		/* whether we need to initialize */
+static int yy_init = 0;		/* whether we need to initialize */
 static int yy_start = 0;	/* start state number */
 
 /* Flag which is used to allow zconfwrap()'s to do buffer switches
@@ -820,6 +832,8 @@
 #define YY_EXTRA_TYPE void *
 #endif
 
+static int yy_init_globals (void );
+
 /* Macros after this point can all be overridden by user definitions in
  * section 1.
  */
@@ -942,9 +956,9 @@
 	int str = 0;
 	int ts, i;
 
-	if ( (yy_init) )
+	if ( !(yy_init) )
 		{
-		(yy_init) = 0;
+		(yy_init) = 1;
 
 #ifdef YY_USER_INIT
 		YY_USER_INIT;
@@ -1452,7 +1466,7 @@
 
 	else
 		{
-			size_t num_to_read =
+			int num_to_read =
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
 		while ( num_to_read <= 0 )
@@ -1969,16 +1983,16 @@
 
 /** Setup the input buffer state to scan a string. The next call to zconflex() will
  * scan from a @e copy of @a str.
- * @param yy_str a NUL-terminated string to scan
+ * @param yystr a NUL-terminated string to scan
  * 
  * @return the newly allocated buffer state object.
  * @note If you want to scan bytes that may contain NUL values, then use
  *       zconf_scan_bytes() instead.
  */
-YY_BUFFER_STATE zconf_scan_string (yyconst char * yy_str )
+YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
 {
     
-	return zconf_scan_bytes(yy_str,strlen(yy_str) );
+	return zconf_scan_bytes(yystr,strlen(yystr) );
 }
 
 /** Setup the input buffer state to scan the given bytes. The next call to zconflex() will
@@ -1988,7 +2002,7 @@
  * 
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * bytes, int  len )
+YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
 {
 	YY_BUFFER_STATE b;
 	char *buf;
@@ -1996,15 +2010,15 @@
 	int i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = len + 2;
+	n = _yybytes_len + 2;
 	buf = (char *) zconfalloc(n  );
 	if ( ! buf )
 		YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" );
 
-	for ( i = 0; i < len; ++i )
-		buf[i] = bytes[i];
+	for ( i = 0; i < _yybytes_len; ++i )
+		buf[i] = yybytes[i];
 
-	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
 
 	b = zconf_scan_buffer(buf,n );
 	if ( ! b )
@@ -2125,6 +2139,34 @@
         zconf_flex_debug = bdebug ;
 }
 
+static int yy_init_globals (void)
+{
+        /* Initialization is the same as for the non-reentrant scanner.
+     * This function is called from zconflex_destroy(), so don't allocate here.
+     */
+
+    (yy_buffer_stack) = 0;
+    (yy_buffer_stack_top) = 0;
+    (yy_buffer_stack_max) = 0;
+    (yy_c_buf_p) = (char *) 0;
+    (yy_init) = 0;
+    (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+    zconfin = stdin;
+    zconfout = stdout;
+#else
+    zconfin = (FILE *) 0;
+    zconfout = (FILE *) 0;
+#endif
+
+    /* For future reference: Set errno on error, since we are called by
+     * zconflex_init()
+     */
+    return 0;
+}
+
 /* zconflex_destroy is for both reentrant and non-reentrant scanners. */
 int zconflex_destroy  (void)
 {
@@ -2140,6 +2182,10 @@
 	zconffree((yy_buffer_stack) );
 	(yy_buffer_stack) = NULL;
 
+    /* Reset the globals. This is important in a non-reentrant scanner so the next time
+     * zconflex() is called, initialization will occur. */
+    yy_init_globals( );
+
     return 0;
 }
 
@@ -2151,7 +2197,7 @@
 static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
 {
 	register int i;
-    	for ( i = 0; i < n; ++i )
+	for ( i = 0; i < n; ++i )
 		s1[i] = s2[i];
 }
 #endif
@@ -2160,7 +2206,7 @@
 static int yy_flex_strlen (yyconst char * s )
 {
 	register int n;
-    	for ( n = 0; s[n]; ++n )
+	for ( n = 0; s[n]; ++n )
 		;
 
 	return n;
@@ -2191,19 +2237,6 @@
 
 #define YYTABLES_NAME "yytables"
 
-#undef YY_NEW_FILE
-#undef YY_FLUSH_BUFFER
-#undef yy_set_bol
-#undef yy_new_buffer
-#undef yy_set_interactive
-#undef yytext_ptr
-#undef YY_DO_BEFORE_ACTION
-
-#ifdef YY_DECL_IS_OURS
-#undef YY_DECL_IS_OURS
-#undef YY_DECL
-#endif
-
 void zconf_starthelp(void)
 {
 	new_string();
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 527f60c..2628023 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -40,6 +40,10 @@
 
 #define TF_COMMAND	0x0001
 #define TF_PARAM	0x0002
+#define TF_OPTION	0x0004
+
+#define T_OPT_MODULES		1
+#define T_OPT_DEFCONFIG_LIST	2
 
 struct kconf_id {
 	int name;
@@ -60,8 +64,6 @@
 char *zconf_curname(void);
 
 /* confdata.c */
-extern const char conf_def_filename[];
-
 char *conf_get_default_confname(void);
 
 /* kconfig_load.c */
@@ -78,6 +80,7 @@
 struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep);
 void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep);
 void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep);
+void menu_add_option(int token, char *arg);
 void menu_finalize(struct menu *parent);
 void menu_set_type(int type);
 
@@ -99,6 +102,7 @@
 /* symbol.c */
 void sym_init(void);
 void sym_clear_all_valid(void);
+void sym_set_all_changed(void);
 void sym_set_changed(struct symbol *sym);
 struct symbol *sym_check_deps(struct symbol *sym);
 struct property *prop_alloc(enum prop_type type, struct symbol *sym);
@@ -137,7 +141,7 @@
 
 static inline bool sym_has_value(struct symbol *sym)
 {
-	return sym->flags & SYMBOL_NEW ? false : true;
+	return sym->flags & SYMBOL_DEF_USER ? true : false;
 }
 
 #ifdef __cplusplus
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index b6a389c..a263746 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -2,8 +2,9 @@
 /* confdata.c */
 P(conf_parse,void,(const char *name));
 P(conf_read,int,(const char *name));
-P(conf_read_simple,int,(const char *name));
+P(conf_read_simple,int,(const char *name, int));
 P(conf_write,int,(const char *name));
+P(conf_write_autoconf,int,(void));
 
 /* menu.c */
 P(rootmenu,struct menu,);
@@ -38,4 +39,4 @@
 
 /* expr.c */
 P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2));
-P(expr_print,void,(struct expr *e, void (*fn)(void *, const char *), void *data, int prevtoken));
+P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken));
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 0fce20c..c86c27f 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -114,7 +114,7 @@
 		sym->type = type;
 		return;
 	}
-	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n",
+	menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'",
 	    sym->name ? sym->name : "<choice>",
 	    sym_type_name(sym->type), sym_type_name(type));
 }
@@ -124,15 +124,20 @@
 	struct property *prop = prop_alloc(type, current_entry->sym);
 
 	prop->menu = current_entry;
-	prop->text = prompt;
 	prop->expr = expr;
 	prop->visible.expr = menu_check_dep(dep);
 
 	if (prompt) {
+		if (isspace(*prompt)) {
+			prop_warn(prop, "leading whitespace ignored");
+			while (isspace(*prompt))
+				prompt++;
+		}
 		if (current_entry->prompt)
-			menu_warn(current_entry, "prompt redefined\n");
+			prop_warn(prop, "prompt redefined");
 		current_entry->prompt = prop;
 	}
+	prop->text = prompt;
 
 	return prop;
 }
@@ -152,6 +157,24 @@
 	menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep);
 }
 
+void menu_add_option(int token, char *arg)
+{
+	struct property *prop;
+
+	switch (token) {
+	case T_OPT_MODULES:
+		prop = prop_alloc(P_DEFAULT, modules_sym);
+		prop->expr = expr_alloc_symbol(current_entry->sym);
+		break;
+	case T_OPT_DEFCONFIG_LIST:
+		if (!sym_defconfig_list)
+			sym_defconfig_list = current_entry->sym;
+		else if (sym_defconfig_list != current_entry->sym)
+			zconf_error("trying to redefine defconfig symbol");
+		break;
+	}
+}
+
 static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2)
 {
 	return sym2->type == S_INT || sym2->type == S_HEX ||
@@ -325,11 +348,10 @@
 
 	if (sym && !(sym->flags & SYMBOL_WARNED)) {
 		if (sym->type == S_UNKNOWN)
-			menu_warn(parent, "config symbol defined "
-			    "without type\n");
+			menu_warn(parent, "config symbol defined without type");
 
 		if (sym_is_choice(sym) && !parent->prompt)
-			menu_warn(parent, "choice must have a prompt\n");
+			menu_warn(parent, "choice must have a prompt");
 
 		/* Check properties connected to this symbol */
 		sym_check_prop(sym);
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index 4590cd3..393f374 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -6,16 +6,20 @@
 #include <qapplication.h>
 #include <qmainwindow.h>
 #include <qtoolbar.h>
+#include <qlayout.h>
 #include <qvbox.h>
 #include <qsplitter.h>
 #include <qlistview.h>
-#include <qtextview.h>
+#include <qtextbrowser.h>
 #include <qlineedit.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
 #include <qmenubar.h>
 #include <qmessagebox.h>
 #include <qaction.h>
 #include <qheader.h>
 #include <qfiledialog.h>
+#include <qdragobject.h>
 #include <qregexp.h>
 
 #include <stdlib.h>
@@ -32,32 +36,16 @@
 #endif
 
 static QApplication *configApp;
+static ConfigSettings *configSettings;
 
 static inline QString qgettext(const char* str)
 {
-  return QString::fromLocal8Bit(gettext(str));
+	return QString::fromLocal8Bit(gettext(str));
 }
 
 static inline QString qgettext(const QString& str)
 {
-  return QString::fromLocal8Bit(gettext(str.latin1()));
-}
-
-ConfigSettings::ConfigSettings()
-	: showAll(false), showName(false), showRange(false), showData(false)
-{
-}
-
-#if QT_VERSION >= 300
-/**
- * Reads the list column settings from the application settings.
- */
-void ConfigSettings::readListSettings()
-{
-	showAll = readBoolEntry("/kconfig/qconf/showAll", false);
-	showName = readBoolEntry("/kconfig/qconf/showName", false);
-	showRange = readBoolEntry("/kconfig/qconf/showRange", false);
-	showData = readBoolEntry("/kconfig/qconf/showData", false);
+	return QString::fromLocal8Bit(gettext(str.latin1()));
 }
 
 /**
@@ -88,77 +76,8 @@
 		stringList.push_back(QString::number(*it));
 	return writeEntry(key, stringList);
 }
-#endif
 
 
-/*
- * update all the children of a menu entry
- *   removes/adds the entries from the parent widget as necessary
- *
- * parent: either the menu list widget or a menu entry widget
- * menu: entry to be updated
- */
-template <class P>
-void ConfigList::updateMenuList(P* parent, struct menu* menu)
-{
-	struct menu* child;
-	ConfigItem* item;
-	ConfigItem* last;
-	bool visible;
-	enum prop_type type;
-
-	if (!menu) {
-		while ((item = parent->firstChild()))
-			delete item;
-		return;
-	}
-
-	last = parent->firstChild();
-	if (last && !last->goParent)
-		last = 0;
-	for (child = menu->list; child; child = child->next) {
-		item = last ? last->nextSibling() : parent->firstChild();
-		type = child->prompt ? child->prompt->type : P_UNKNOWN;
-
-		switch (mode) {
-		case menuMode:
-			if (!(child->flags & MENU_ROOT))
-				goto hide;
-			break;
-		case symbolMode:
-			if (child->flags & MENU_ROOT)
-				goto hide;
-			break;
-		default:
-			break;
-		}
-
-		visible = menu_is_visible(child);
-		if (showAll || visible) {
-			if (!item || item->menu != child)
-				item = new ConfigItem(parent, last, child, visible);
-			else
-				item->testUpdateMenu(visible);
-
-			if (mode == fullMode || mode == menuMode || type != P_MENU)
-				updateMenuList(item, child);
-			else
-				updateMenuList(item, 0);
-			last = item;
-			continue;
-		}
-	hide:
-		if (item && item->menu == child) {
-			last = parent->firstChild();
-			if (last == item)
-				last = 0;
-			else while (last->nextSibling() != item)
-				last = last->nextSibling();
-			delete item;
-		}
-	}
-}
-
 #if QT_VERSION >= 300
 /*
  * set the new data
@@ -355,6 +274,12 @@
 	}
 }
 
+ConfigLineEdit::ConfigLineEdit(ConfigView* parent)
+	: Parent(parent)
+{
+	connect(this, SIGNAL(lostFocus()), SLOT(hide()));
+}
+
 void ConfigLineEdit::show(ConfigItem* i)
 {
 	item = i;
@@ -385,14 +310,14 @@
 	hide();
 }
 
-ConfigList::ConfigList(ConfigView* p, ConfigMainWindow* cv, ConfigSettings* configSettings)
-	: Parent(p), cview(cv),
+ConfigList::ConfigList(ConfigView* p, const char *name)
+	: Parent(p, name),
 	  updateAll(false),
 	  symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
 	  choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
 	  menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
 	  showAll(false), showName(false), showRange(false), showData(false),
-	  rootEntry(0)
+	  rootEntry(0), headerPopup(0)
 {
 	int i;
 
@@ -406,11 +331,14 @@
 	connect(this, SIGNAL(selectionChanged(void)),
 		SLOT(updateSelection(void)));
 
-	if (configSettings) {
-		showAll = configSettings->showAll;
-		showName = configSettings->showName;
-		showRange = configSettings->showRange;
-		showData = configSettings->showData;
+	if (name) {
+		configSettings->beginGroup(name);
+		showAll = configSettings->readBoolEntry("/showAll", false);
+		showName = configSettings->readBoolEntry("/showName", false);
+		showRange = configSettings->readBoolEntry("/showRange", false);
+		showData = configSettings->readBoolEntry("/showData", false);
+		configSettings->endGroup();
+		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
 	}
 
 	for (i = 0; i < colNr; i++)
@@ -441,6 +369,30 @@
 	updateListAll();
 }
 
+void ConfigList::saveSettings(void)
+{
+	if (name()) {
+		configSettings->beginGroup(name());
+		configSettings->writeEntry("/showName", showName);
+		configSettings->writeEntry("/showRange", showRange);
+		configSettings->writeEntry("/showData", showData);
+		configSettings->writeEntry("/showAll", showAll);
+		configSettings->endGroup();
+	}
+}
+
+ConfigItem* ConfigList::findConfigItem(struct menu *menu)
+{
+	ConfigItem* item = (ConfigItem*)menu->data;
+
+	for (; item; item = item->nextItem) {
+		if (this == item->listView())
+			break;
+	}
+
+	return item;
+}
+
 void ConfigList::updateSelection(void)
 {
 	struct menu *menu;
@@ -450,9 +402,8 @@
 	if (!item)
 		return;
 
-	cview->setHelp(item);
-
 	menu = item->menu;
+	emit menuChanged(menu);
 	if (!menu)
 		return;
 	type = menu->prompt ? menu->prompt->type : P_UNKNOWN;
@@ -464,8 +415,20 @@
 {
 	ConfigItem* last = 0;
 
-	if (!rootEntry)
-		goto update;
+	if (!rootEntry) {
+		if (mode != listMode)
+			goto update;
+		QListViewItemIterator it(this);
+		ConfigItem* item;
+
+		for (; it.current(); ++it) {
+			item = (ConfigItem*)it.current();
+			if (!item->menu)
+				continue;
+			item->testUpdateMenu(menu_is_visible(item->menu));
+		}
+		return;
+	}
 
 	if (rootEntry != &rootmenu && (mode == singleMode ||
 	    (mode == symbolMode && rootEntry->parent != &rootmenu))) {
@@ -491,14 +454,6 @@
 	triggerUpdate();
 }
 
-void ConfigList::setAllOpen(bool open)
-{
-	QListViewItemIterator it(this);
-
-	for (; it.current(); it++)
-		it.current()->setOpen(open);
-}
-
 void ConfigList::setValue(ConfigItem* item, tristate val)
 {
 	struct symbol* sym;
@@ -581,6 +536,7 @@
 	rootEntry = menu;
 	updateListAll();
 	setSelected(currentItem(), hasFocus());
+	ensureItemVisible(currentItem());
 }
 
 void ConfigList::setParentMenu(void)
@@ -603,6 +559,74 @@
 	}
 }
 
+/*
+ * update all the children of a menu entry
+ *   removes/adds the entries from the parent widget as necessary
+ *
+ * parent: either the menu list widget or a menu entry widget
+ * menu: entry to be updated
+ */
+template <class P>
+void ConfigList::updateMenuList(P* parent, struct menu* menu)
+{
+	struct menu* child;
+	ConfigItem* item;
+	ConfigItem* last;
+	bool visible;
+	enum prop_type type;
+
+	if (!menu) {
+		while ((item = parent->firstChild()))
+			delete item;
+		return;
+	}
+
+	last = parent->firstChild();
+	if (last && !last->goParent)
+		last = 0;
+	for (child = menu->list; child; child = child->next) {
+		item = last ? last->nextSibling() : parent->firstChild();
+		type = child->prompt ? child->prompt->type : P_UNKNOWN;
+
+		switch (mode) {
+		case menuMode:
+			if (!(child->flags & MENU_ROOT))
+				goto hide;
+			break;
+		case symbolMode:
+			if (child->flags & MENU_ROOT)
+				goto hide;
+			break;
+		default:
+			break;
+		}
+
+		visible = menu_is_visible(child);
+		if (showAll || visible) {
+			if (!item || item->menu != child)
+				item = new ConfigItem(parent, last, child, visible);
+			else
+				item->testUpdateMenu(visible);
+
+			if (mode == fullMode || mode == menuMode || type != P_MENU)
+				updateMenuList(item, child);
+			else
+				updateMenuList(item, 0);
+			last = item;
+			continue;
+		}
+	hide:
+		if (item && item->menu == child) {
+			last = parent->firstChild();
+			if (last == item)
+				last = 0;
+			else while (last->nextSibling() != item)
+				last = last->nextSibling();
+			delete item;
+		}
+	}
+}
+
 void ConfigList::keyPressEvent(QKeyEvent* ev)
 {
 	QListViewItem* i = currentItem();
@@ -610,7 +634,7 @@
 	struct menu *menu;
 	enum prop_type type;
 
-	if (ev->key() == Key_Escape && mode != fullMode) {
+	if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) {
 		emit parentSelected();
 		ev->accept();
 		return;
@@ -755,23 +779,62 @@
 
 void ConfigList::focusInEvent(QFocusEvent *e)
 {
+	struct menu *menu = NULL;
+
 	Parent::focusInEvent(e);
 
-	QListViewItem* item = currentItem();
-	if (!item)
-		return;
+	ConfigItem* item = (ConfigItem *)currentItem();
+	if (item) {
+		setSelected(item, TRUE);
+		menu = item->menu;
+	}
+	emit gotFocus(menu);
+}
 
-	setSelected(item, TRUE);
-	emit gotFocus();
+void ConfigList::contextMenuEvent(QContextMenuEvent *e)
+{
+	if (e->y() <= header()->geometry().bottom()) {
+		if (!headerPopup) {
+			QAction *action;
+
+			headerPopup = new QPopupMenu(this);
+			action = new QAction("Show Name", 0, this);
+			  action->setToggleAction(TRUE);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowName(bool)));
+			  connect(parent(), SIGNAL(showNameChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setOn(showName);
+			  action->addTo(headerPopup);
+			action = new QAction("Show Range", 0, this);
+			  action->setToggleAction(TRUE);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowRange(bool)));
+			  connect(parent(), SIGNAL(showRangeChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setOn(showRange);
+			  action->addTo(headerPopup);
+			action = new QAction("Show Data", 0, this);
+			  action->setToggleAction(TRUE);
+			  connect(action, SIGNAL(toggled(bool)),
+				  parent(), SLOT(setShowData(bool)));
+			  connect(parent(), SIGNAL(showDataChanged(bool)),
+				  action, SLOT(setOn(bool)));
+			  action->setOn(showData);
+			  action->addTo(headerPopup);
+		}
+		headerPopup->exec(e->globalPos());
+		e->accept();
+	} else
+		e->ignore();
 }
 
 ConfigView* ConfigView::viewList;
 
-ConfigView::ConfigView(QWidget* parent, ConfigMainWindow* cview,
-		       ConfigSettings *configSettings)
-	: Parent(parent)
+ConfigView::ConfigView(QWidget* parent, const char *name)
+	: Parent(parent, name)
 {
-	list = new ConfigList(this, cview, configSettings);
+	list = new ConfigList(this, name);
 	lineEdit = new ConfigLineEdit(this);
 	lineEdit->hide();
 
@@ -791,6 +854,50 @@
 	}
 }
 
+void ConfigView::setShowAll(bool b)
+{
+	if (list->showAll != b) {
+		list->showAll = b;
+		list->updateListAll();
+		emit showAllChanged(b);
+	}
+}
+
+void ConfigView::setShowName(bool b)
+{
+	if (list->showName != b) {
+		list->showName = b;
+		list->reinit();
+		emit showNameChanged(b);
+	}
+}
+
+void ConfigView::setShowRange(bool b)
+{
+	if (list->showRange != b) {
+		list->showRange = b;
+		list->reinit();
+		emit showRangeChanged(b);
+	}
+}
+
+void ConfigView::setShowData(bool b)
+{
+	if (list->showData != b) {
+		list->showData = b;
+		list->reinit();
+		emit showDataChanged(b);
+	}
+}
+
+void ConfigList::setAllOpen(bool open)
+{
+	QListViewItemIterator it(this);
+
+	for (; it.current(); it++)
+		it.current()->setOpen(open);
+}
+
 void ConfigView::updateList(ConfigItem* item)
 {
 	ConfigView* v;
@@ -807,177 +914,207 @@
 		v->list->updateListAll();
 }
 
-/*
- * Construct the complete config widget
- */
-ConfigMainWindow::ConfigMainWindow(void)
+ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
+	: Parent(parent, name), menu(0)
 {
-	QMenuBar* menu;
-	bool ok;
-	int x, y, width, height;
-
-	QWidget *d = configApp->desktop();
-
-	ConfigSettings* configSettings = new ConfigSettings();
-#if QT_VERSION >= 300
-	width = configSettings->readNumEntry("/kconfig/qconf/window width", d->width() - 64);
-	height = configSettings->readNumEntry("/kconfig/qconf/window height", d->height() - 64);
-	resize(width, height);
-	x = configSettings->readNumEntry("/kconfig/qconf/window x", 0, &ok);
-	if (ok)
-		y = configSettings->readNumEntry("/kconfig/qconf/window y", 0, &ok);
-	if (ok)
-		move(x, y);
-	showDebug = configSettings->readBoolEntry("/kconfig/qconf/showDebug", false);
-
-	// read list settings into configSettings, will be used later for ConfigList setup
-	configSettings->readListSettings();
-#else
-	width = d->width() - 64;
-	height = d->height() - 64;
-	resize(width, height);
-	showDebug = false;
-#endif
-
-	split1 = new QSplitter(this);
-	split1->setOrientation(QSplitter::Horizontal);
-	setCentralWidget(split1);
-
-	menuView = new ConfigView(split1, this, configSettings);
-	menuList = menuView->list;
-
-	split2 = new QSplitter(split1);
-	split2->setOrientation(QSplitter::Vertical);
-
-	// create config tree
-	configView = new ConfigView(split2, this, configSettings);
-	configList = configView->list;
-
-	helpText = new QTextView(split2);
-	helpText->setTextFormat(Qt::RichText);
-
-	setTabOrder(configList, helpText);
-	configList->setFocus();
-
-	menu = menuBar();
-	toolBar = new QToolBar("Tools", this);
-
-	backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
-	  connect(backAction, SIGNAL(activated()), SLOT(goBack()));
-	  backAction->setEnabled(FALSE);
-	QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
-	  connect(quitAction, SIGNAL(activated()), SLOT(close()));
-	QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
-	  connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
-	QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
-	  connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
-	QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
-	  connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
-	QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
-	  connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
-	QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
-	  connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
-	QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
-	  connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
-
-	QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
-	  showNameAction->setToggleAction(TRUE);
-	  showNameAction->setOn(configList->showName);
-	  connect(showNameAction, SIGNAL(toggled(bool)), SLOT(setShowName(bool)));
-	QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
-	  showRangeAction->setToggleAction(TRUE);
-	  showRangeAction->setOn(configList->showRange);
-	  connect(showRangeAction, SIGNAL(toggled(bool)), SLOT(setShowRange(bool)));
-	QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
-	  showDataAction->setToggleAction(TRUE);
-	  showDataAction->setOn(configList->showData);
-	  connect(showDataAction, SIGNAL(toggled(bool)), SLOT(setShowData(bool)));
-	QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
-	  showAllAction->setToggleAction(TRUE);
-	  showAllAction->setOn(configList->showAll);
-	  connect(showAllAction, SIGNAL(toggled(bool)), SLOT(setShowAll(bool)));
-	QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
-	  showDebugAction->setToggleAction(TRUE);
-	  showDebugAction->setOn(showDebug);
-	  connect(showDebugAction, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
-
-	QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
-	  connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
-	QAction *showAboutAction = new QAction(NULL, "About", 0, this);
-	  connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
-
-	// init tool bar
-	backAction->addTo(toolBar);
-	toolBar->addSeparator();
-	loadAction->addTo(toolBar);
-	saveAction->addTo(toolBar);
-	toolBar->addSeparator();
-	singleViewAction->addTo(toolBar);
-	splitViewAction->addTo(toolBar);
-	fullViewAction->addTo(toolBar);
-
-	// create config menu
-	QPopupMenu* config = new QPopupMenu(this);
-	menu->insertItem("&File", config);
-	loadAction->addTo(config);
-	saveAction->addTo(config);
-	saveAsAction->addTo(config);
-	config->insertSeparator();
-	quitAction->addTo(config);
-
-	// create options menu
-	QPopupMenu* optionMenu = new QPopupMenu(this);
-	menu->insertItem("&Option", optionMenu);
-	showNameAction->addTo(optionMenu);
-	showRangeAction->addTo(optionMenu);
-	showDataAction->addTo(optionMenu);
-	optionMenu->insertSeparator();
-	showAllAction->addTo(optionMenu);
-	showDebugAction->addTo(optionMenu);
-
-	// create help menu
-	QPopupMenu* helpMenu = new QPopupMenu(this);
-	menu->insertSeparator();
-	menu->insertItem("&Help", helpMenu);
-	showIntroAction->addTo(helpMenu);
-	showAboutAction->addTo(helpMenu);
-
-	connect(configList, SIGNAL(menuSelected(struct menu *)),
-		SLOT(changeMenu(struct menu *)));
-	connect(configList, SIGNAL(parentSelected()),
-		SLOT(goBack()));
-	connect(menuList, SIGNAL(menuSelected(struct menu *)),
-		SLOT(changeMenu(struct menu *)));
-
-	connect(configList, SIGNAL(gotFocus(void)),
-		SLOT(listFocusChanged(void)));
-	connect(menuList, SIGNAL(gotFocus(void)),
-		SLOT(listFocusChanged(void)));
-
-#if QT_VERSION >= 300
-	QString listMode = configSettings->readEntry("/kconfig/qconf/listMode", "symbol");
-	if (listMode == "single")
-		showSingleView();
-	else if (listMode == "full")
-		showFullView();
-	else /*if (listMode == "split")*/
-		showSplitView();
-
-	// UI setup done, restore splitter positions
-	QValueList<int> sizes = configSettings->readSizes("/kconfig/qconf/split1", &ok);
-	if (ok)
-		split1->setSizes(sizes);
-
-	sizes = configSettings->readSizes("/kconfig/qconf/split2", &ok);
-	if (ok)
-		split2->setSizes(sizes);
-#else
-	showSplitView();
-#endif
-	delete configSettings;
+	if (name) {
+		configSettings->beginGroup(name);
+		_showDebug = configSettings->readBoolEntry("/showDebug", false);
+		configSettings->endGroup();
+		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+	}
 }
 
-static QString print_filter(const QString &str)
+void ConfigInfoView::saveSettings(void)
+{
+	if (name()) {
+		configSettings->beginGroup(name());
+		configSettings->writeEntry("/showDebug", showDebug());
+		configSettings->endGroup();
+	}
+}
+
+void ConfigInfoView::setShowDebug(bool b)
+{
+	if (_showDebug != b) {
+		_showDebug = b;
+		if (menu)
+			menuInfo();
+		else if (sym)
+			symbolInfo();
+		emit showDebugChanged(b);
+	}
+}
+
+void ConfigInfoView::setInfo(struct menu *m)
+{
+	if (menu == m)
+		return;
+	menu = m;
+	if (!menu)
+		clear();
+	else
+		menuInfo();
+}
+
+void ConfigInfoView::setSource(const QString& name)
+{
+	const char *p = name.latin1();
+
+	menu = NULL;
+	sym = NULL;
+
+	switch (p[0]) {
+	case 'm':
+		struct menu *m;
+
+		if (sscanf(p, "m%p", &m) == 1 && menu != m) {
+			menu = m;
+			menuInfo();
+			emit menuSelected(menu);
+		}
+		break;
+	case 's':
+		struct symbol *s;
+
+		if (sscanf(p, "s%p", &s) == 1 && sym != s) {
+			sym = s;
+			symbolInfo();
+		}
+		break;
+	}
+}
+
+void ConfigInfoView::symbolInfo(void)
+{
+	QString str;
+
+	str += "<big>Symbol: <b>";
+	str += print_filter(sym->name);
+	str += "</b></big><br><br>value: ";
+	str += print_filter(sym_get_string_value(sym));
+	str += "<br>visibility: ";
+	str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n";
+	str += "<br>";
+	str += debug_info(sym);
+
+	setText(str);
+}
+
+void ConfigInfoView::menuInfo(void)
+{
+	struct symbol* sym;
+	QString head, debug, help;
+
+	sym = menu->sym;
+	if (sym) {
+		if (menu->prompt) {
+			head += "<big><b>";
+			head += print_filter(_(menu->prompt->text));
+			head += "</b></big>";
+			if (sym->name) {
+				head += " (";
+				if (showDebug())
+					head += QString().sprintf("<a href=\"s%p\">", sym);
+				head += print_filter(sym->name);
+				if (showDebug())
+					head += "</a>";
+				head += ")";
+			}
+		} else if (sym->name) {
+			head += "<big><b>";
+			if (showDebug())
+				head += QString().sprintf("<a href=\"s%p\">", sym);
+			head += print_filter(sym->name);
+			if (showDebug())
+				head += "</a>";
+			head += "</b></big>";
+		}
+		head += "<br><br>";
+
+		if (showDebug())
+			debug = debug_info(sym);
+
+		help = print_filter(_(sym->help));
+	} else if (menu->prompt) {
+		head += "<big><b>";
+		head += print_filter(_(menu->prompt->text));
+		head += "</b></big><br><br>";
+		if (showDebug()) {
+			if (menu->prompt->visible.expr) {
+				debug += "&nbsp;&nbsp;dep: ";
+				expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
+				debug += "<br><br>";
+			}
+		}
+	}
+	if (showDebug())
+		debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
+
+	setText(head + debug + help);
+}
+
+QString ConfigInfoView::debug_info(struct symbol *sym)
+{
+	QString debug;
+
+	debug += "type: ";
+	debug += print_filter(sym_type_name(sym->type));
+	if (sym_is_choice(sym))
+		debug += " (choice)";
+	debug += "<br>";
+	if (sym->rev_dep.expr) {
+		debug += "reverse dep: ";
+		expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
+		debug += "<br>";
+	}
+	for (struct property *prop = sym->prop; prop; prop = prop->next) {
+		switch (prop->type) {
+		case P_PROMPT:
+		case P_MENU:
+			debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu);
+			debug += print_filter(_(prop->text));
+			debug += "</a><br>";
+			break;
+		case P_DEFAULT:
+			debug += "default: ";
+			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+			break;
+		case P_CHOICE:
+			if (sym_is_choice(sym)) {
+				debug += "choice: ";
+				expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+				debug += "<br>";
+			}
+			break;
+		case P_SELECT:
+			debug += "select: ";
+			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+			break;
+		case P_RANGE:
+			debug += "range: ";
+			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+			break;
+		default:
+			debug += "unknown property: ";
+			debug += prop_get_type_name(prop->type);
+			debug += "<br>";
+		}
+		if (prop->visible.expr) {
+			debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
+			expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
+			debug += "<br>";
+		}
+	}
+	debug += "<br>";
+
+	return debug;
+}
+
+QString ConfigInfoView::print_filter(const QString &str)
 {
 	QRegExp re("[<>&\"\\n]");
 	QString res = str;
@@ -1008,118 +1145,284 @@
 	return res;
 }
 
-static void expr_print_help(void *data, const char *str)
+void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str)
 {
-	reinterpret_cast<QString*>(data)->append(print_filter(str));
+	QString* text = reinterpret_cast<QString*>(data);
+	QString str2 = print_filter(str);
+
+	if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
+		*text += QString().sprintf("<a href=\"s%p\">", sym);
+		*text += str2;
+		*text += "</a>";
+	} else
+		*text += str2;
+}
+
+QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
+{
+	QPopupMenu* popup = Parent::createPopupMenu(pos);
+	QAction* action = new QAction("Show Debug Info", 0, popup);
+	  action->setToggleAction(TRUE);
+	  connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
+	  connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
+	  action->setOn(showDebug());
+	popup->insertSeparator();
+	action->addTo(popup);
+	return popup;
+}
+
+void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e)
+{
+	Parent::contentsContextMenuEvent(e);
+}
+
+ConfigSearchWindow::ConfigSearchWindow(QWidget* parent, const char *name)
+	: Parent(parent, name), result(NULL)
+{
+	setCaption("Search Config");
+
+	QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6);
+	QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6);
+	layout2->addWidget(new QLabel("Find:", this));
+	editField = new QLineEdit(this);
+	connect(editField, SIGNAL(returnPressed()), SLOT(search()));
+	layout2->addWidget(editField);
+	searchButton = new QPushButton("Search", this);
+	searchButton->setAutoDefault(FALSE);
+	connect(searchButton, SIGNAL(clicked()), SLOT(search()));
+	layout2->addWidget(searchButton);
+	layout1->addLayout(layout2);
+
+	split = new QSplitter(this);
+	split->setOrientation(QSplitter::Vertical);
+	list = new ConfigView(split, name);
+	list->list->mode = listMode;
+	info = new ConfigInfoView(split, name);
+	connect(list->list, SIGNAL(menuChanged(struct menu *)),
+		info, SLOT(setInfo(struct menu *)));
+	layout1->addWidget(split);
+
+	if (name) {
+		int x, y, width, height;
+		bool ok;
+
+		configSettings->beginGroup(name);
+		width = configSettings->readNumEntry("/window width", parent->width() / 2);
+		height = configSettings->readNumEntry("/window height", parent->height() / 2);
+		resize(width, height);
+		x = configSettings->readNumEntry("/window x", 0, &ok);
+		if (ok)
+			y = configSettings->readNumEntry("/window y", 0, &ok);
+		if (ok)
+			move(x, y);
+		QValueList<int> sizes = configSettings->readSizes("/split", &ok);
+		if (ok)
+			split->setSizes(sizes);
+		configSettings->endGroup();
+		connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
+	}
+}
+
+void ConfigSearchWindow::saveSettings(void)
+{
+	if (name()) {
+		configSettings->beginGroup(name());
+		configSettings->writeEntry("/window x", pos().x());
+		configSettings->writeEntry("/window y", pos().y());
+		configSettings->writeEntry("/window width", size().width());
+		configSettings->writeEntry("/window height", size().height());
+		configSettings->writeSizes("/split", split->sizes());
+		configSettings->endGroup();
+	}
+}
+
+void ConfigSearchWindow::search(void)
+{
+	struct symbol **p;
+	struct property *prop;
+	ConfigItem *lastItem = NULL;
+
+	free(result);
+	list->list->clear();
+
+	result = sym_re_search(editField->text().latin1());
+	if (!result)
+		return;
+	for (p = result; *p; p++) {
+		for_all_prompts((*p), prop)
+			lastItem = new ConfigItem(list->list, lastItem, prop->menu,
+						  menu_is_visible(prop->menu));
+	}
 }
 
 /*
- * display a new help entry as soon as a new menu entry is selected
+ * Construct the complete config widget
  */
-void ConfigMainWindow::setHelp(QListViewItem* item)
+ConfigMainWindow::ConfigMainWindow(void)
 {
-	struct symbol* sym;
-	struct menu* menu = 0;
+	QMenuBar* menu;
+	bool ok;
+	int x, y, width, height;
 
-	configList->parent()->lineEdit->hide();
-	if (item)
-		menu = ((ConfigItem*)item)->menu;
-	if (!menu) {
-		helpText->setText(QString::null);
-		return;
-	}
+	QWidget *d = configApp->desktop();
 
-	QString head, debug, help;
-	menu = ((ConfigItem*)item)->menu;
-	sym = menu->sym;
-	if (sym) {
-		if (menu->prompt) {
-			head += "<big><b>";
-			head += print_filter(_(menu->prompt->text));
-			head += "</b></big>";
-			if (sym->name) {
-				head += " (";
-				head += print_filter(_(sym->name));
-				head += ")";
-			}
-		} else if (sym->name) {
-			head += "<big><b>";
-			head += print_filter(_(sym->name));
-			head += "</b></big>";
-		}
-		head += "<br><br>";
+	width = configSettings->readNumEntry("/window width", d->width() - 64);
+	height = configSettings->readNumEntry("/window height", d->height() - 64);
+	resize(width, height);
+	x = configSettings->readNumEntry("/window x", 0, &ok);
+	if (ok)
+		y = configSettings->readNumEntry("/window y", 0, &ok);
+	if (ok)
+		move(x, y);
 
-		if (showDebug) {
-			debug += "type: ";
-			debug += print_filter(sym_type_name(sym->type));
-			if (sym_is_choice(sym))
-				debug += " (choice)";
-			debug += "<br>";
-			if (sym->rev_dep.expr) {
-				debug += "reverse dep: ";
-				expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE);
-				debug += "<br>";
-			}
-			for (struct property *prop = sym->prop; prop; prop = prop->next) {
-				switch (prop->type) {
-				case P_PROMPT:
-				case P_MENU:
-					debug += "prompt: ";
-					debug += print_filter(_(prop->text));
-					debug += "<br>";
-					break;
-				case P_DEFAULT:
-					debug += "default: ";
-					expr_print(prop->expr, expr_print_help, &debug, E_NONE);
-					debug += "<br>";
-					break;
-				case P_CHOICE:
-					if (sym_is_choice(sym)) {
-						debug += "choice: ";
-						expr_print(prop->expr, expr_print_help, &debug, E_NONE);
-						debug += "<br>";
-					}
-					break;
-				case P_SELECT:
-					debug += "select: ";
-					expr_print(prop->expr, expr_print_help, &debug, E_NONE);
-					debug += "<br>";
-					break;
-				case P_RANGE:
-					debug += "range: ";
-					expr_print(prop->expr, expr_print_help, &debug, E_NONE);
-					debug += "<br>";
-					break;
-				default:
-					debug += "unknown property: ";
-					debug += prop_get_type_name(prop->type);
-					debug += "<br>";
-				}
-				if (prop->visible.expr) {
-					debug += "&nbsp;&nbsp;&nbsp;&nbsp;dep: ";
-					expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE);
-					debug += "<br>";
-				}
-			}
-			debug += "<br>";
-		}
+	split1 = new QSplitter(this);
+	split1->setOrientation(QSplitter::Horizontal);
+	setCentralWidget(split1);
 
-		help = print_filter(_(sym->help));
-	} else if (menu->prompt) {
-		head += "<big><b>";
-		head += print_filter(_(menu->prompt->text));
-		head += "</b></big><br><br>";
-		if (showDebug) {
-			if (menu->prompt->visible.expr) {
-				debug += "&nbsp;&nbsp;dep: ";
-				expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
-				debug += "<br><br>";
-			}
-		}
-	}
-	if (showDebug)
-		debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
-	helpText->setText(head + debug + help);
+	menuView = new ConfigView(split1, "menu");
+	menuList = menuView->list;
+
+	split2 = new QSplitter(split1);
+	split2->setOrientation(QSplitter::Vertical);
+
+	// create config tree
+	configView = new ConfigView(split2, "config");
+	configList = configView->list;
+
+	helpText = new ConfigInfoView(split2, "help");
+	helpText->setTextFormat(Qt::RichText);
+
+	setTabOrder(configList, helpText);
+	configList->setFocus();
+
+	menu = menuBar();
+	toolBar = new QToolBar("Tools", this);
+
+	backAction = new QAction("Back", QPixmap(xpm_back), "Back", 0, this);
+	  connect(backAction, SIGNAL(activated()), SLOT(goBack()));
+	  backAction->setEnabled(FALSE);
+	QAction *quitAction = new QAction("Quit", "&Quit", CTRL+Key_Q, this);
+	  connect(quitAction, SIGNAL(activated()), SLOT(close()));
+	QAction *loadAction = new QAction("Load", QPixmap(xpm_load), "&Load", CTRL+Key_L, this);
+	  connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
+	QAction *saveAction = new QAction("Save", QPixmap(xpm_save), "&Save", CTRL+Key_S, this);
+	  connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
+	QAction *saveAsAction = new QAction("Save As...", "Save &As...", 0, this);
+	  connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
+	QAction *searchAction = new QAction("Search", "&Search", CTRL+Key_F, this);
+	  connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
+	QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), "Split View", 0, this);
+	  connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
+	QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), "Split View", 0, this);
+	  connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
+	QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), "Full View", 0, this);
+	  connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
+
+	QAction *showNameAction = new QAction(NULL, "Show Name", 0, this);
+	  showNameAction->setToggleAction(TRUE);
+	  connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
+	  connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
+	  showNameAction->setOn(configView->showName());
+	QAction *showRangeAction = new QAction(NULL, "Show Range", 0, this);
+	  showRangeAction->setToggleAction(TRUE);
+	  connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
+	  connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
+	  showRangeAction->setOn(configList->showRange);
+	QAction *showDataAction = new QAction(NULL, "Show Data", 0, this);
+	  showDataAction->setToggleAction(TRUE);
+	  connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
+	  connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
+	  showDataAction->setOn(configList->showData);
+	QAction *showAllAction = new QAction(NULL, "Show All Options", 0, this);
+	  showAllAction->setToggleAction(TRUE);
+	  connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
+	  connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
+	  showAllAction->setOn(configList->showAll);
+	QAction *showDebugAction = new QAction(NULL, "Show Debug Info", 0, this);
+	  showDebugAction->setToggleAction(TRUE);
+	  connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
+	  connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
+	  showDebugAction->setOn(helpText->showDebug());
+
+	QAction *showIntroAction = new QAction(NULL, "Introduction", 0, this);
+	  connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
+	QAction *showAboutAction = new QAction(NULL, "About", 0, this);
+	  connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
+
+	// init tool bar
+	backAction->addTo(toolBar);
+	toolBar->addSeparator();
+	loadAction->addTo(toolBar);
+	saveAction->addTo(toolBar);
+	toolBar->addSeparator();
+	singleViewAction->addTo(toolBar);
+	splitViewAction->addTo(toolBar);
+	fullViewAction->addTo(toolBar);
+
+	// create config menu
+	QPopupMenu* config = new QPopupMenu(this);
+	menu->insertItem("&File", config);
+	loadAction->addTo(config);
+	saveAction->addTo(config);
+	saveAsAction->addTo(config);
+	config->insertSeparator();
+	searchAction->addTo(config);
+	config->insertSeparator();
+	quitAction->addTo(config);
+
+	// create options menu
+	QPopupMenu* optionMenu = new QPopupMenu(this);
+	menu->insertItem("&Option", optionMenu);
+	showNameAction->addTo(optionMenu);
+	showRangeAction->addTo(optionMenu);
+	showDataAction->addTo(optionMenu);
+	optionMenu->insertSeparator();
+	showAllAction->addTo(optionMenu);
+	showDebugAction->addTo(optionMenu);
+
+	// create help menu
+	QPopupMenu* helpMenu = new QPopupMenu(this);
+	menu->insertSeparator();
+	menu->insertItem("&Help", helpMenu);
+	showIntroAction->addTo(helpMenu);
+	showAboutAction->addTo(helpMenu);
+
+	connect(configList, SIGNAL(menuChanged(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(configList, SIGNAL(menuSelected(struct menu *)),
+		SLOT(changeMenu(struct menu *)));
+	connect(configList, SIGNAL(parentSelected()),
+		SLOT(goBack()));
+	connect(menuList, SIGNAL(menuChanged(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(menuSelected(struct menu *)),
+		SLOT(changeMenu(struct menu *)));
+
+	connect(configList, SIGNAL(gotFocus(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(gotFocus(struct menu *)),
+		helpText, SLOT(setInfo(struct menu *)));
+	connect(menuList, SIGNAL(gotFocus(struct menu *)),
+		SLOT(listFocusChanged(void)));
+	connect(helpText, SIGNAL(menuSelected(struct menu *)),
+		SLOT(setMenuLink(struct menu *)));
+
+	QString listMode = configSettings->readEntry("/listMode", "symbol");
+	if (listMode == "single")
+		showSingleView();
+	else if (listMode == "full")
+		showFullView();
+	else /*if (listMode == "split")*/
+		showSplitView();
+
+	// UI setup done, restore splitter positions
+	QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
+	if (ok)
+		split1->setSizes(sizes);
+
+	sizes = configSettings->readSizes("/split2", &ok);
+	if (ok)
+		split2->setSizes(sizes);
 }
 
 void ConfigMainWindow::loadConfig(void)
@@ -1147,21 +1450,73 @@
 		QMessageBox::information(this, "qconf", "Unable to save configuration!");
 }
 
+void ConfigMainWindow::searchConfig(void)
+{
+	if (!searchWindow)
+		searchWindow = new ConfigSearchWindow(this, "search");
+	searchWindow->show();
+}
+
 void ConfigMainWindow::changeMenu(struct menu *menu)
 {
 	configList->setRootMenu(menu);
 	backAction->setEnabled(TRUE);
 }
 
+void ConfigMainWindow::setMenuLink(struct menu *menu)
+{
+	struct menu *parent;
+	ConfigList* list = NULL;
+	ConfigItem* item;
+
+	if (!menu_is_visible(menu) && !configView->showAll())
+		return;
+
+	switch (configList->mode) {
+	case singleMode:
+		list = configList;
+		parent = menu_get_parent_menu(menu);
+		if (!parent)
+			return;
+		list->setRootMenu(parent);
+		break;
+	case symbolMode:
+		if (menu->flags & MENU_ROOT) {
+			configList->setRootMenu(menu);
+			configList->clearSelection();
+			list = menuList;
+		} else {
+			list = configList;
+			parent = menu_get_parent_menu(menu->parent);
+			if (!parent)
+				return;
+			item = menuList->findConfigItem(parent);
+			if (item) {
+				menuList->setSelected(item, TRUE);
+				menuList->ensureItemVisible(item);
+			}
+			list->setRootMenu(parent);
+		}
+		break;
+	case fullMode:
+		list = configList;
+		break;
+	}
+
+	if (list) {
+		item = list->findConfigItem(menu);
+		if (item) {
+			list->setSelected(item, TRUE);
+			list->ensureItemVisible(item);
+			list->setFocus();
+		}
+	}
+}
+
 void ConfigMainWindow::listFocusChanged(void)
 {
-	if (menuList->hasFocus()) {
-		if (menuList->mode == menuMode)
-			configList->clearSelection();
-		setHelp(menuList->selectedItem());
-	} else if (configList->hasFocus()) {
-		setHelp(configList->selectedItem());
-	}
+	if (menuList->mode == menuMode)
+		configList->clearSelection();
 }
 
 void ConfigMainWindow::goBack(void)
@@ -1223,53 +1578,6 @@
 	configList->setFocus();
 }
 
-void ConfigMainWindow::setShowAll(bool b)
-{
-	if (configList->showAll == b)
-		return;
-	configList->showAll = b;
-	configList->updateListAll();
-	menuList->showAll = b;
-	menuList->updateListAll();
-}
-
-void ConfigMainWindow::setShowDebug(bool b)
-{
-	if (showDebug == b)
-		return;
-	showDebug = b;
-}
-
-void ConfigMainWindow::setShowName(bool b)
-{
-	if (configList->showName == b)
-		return;
-	configList->showName = b;
-	configList->reinit();
-	menuList->showName = b;
-	menuList->reinit();
-}
-
-void ConfigMainWindow::setShowRange(bool b)
-{
-	if (configList->showRange == b)
-		return;
-	configList->showRange = b;
-	configList->reinit();
-	menuList->showRange = b;
-	menuList->reinit();
-}
-
-void ConfigMainWindow::setShowData(bool b)
-{
-	if (configList->showData == b)
-		return;
-	configList->showData = b;
-	configList->reinit();
-	menuList->showData = b;
-	menuList->reinit();
-}
-
 /*
  * ask for saving configuration before quitting
  * TODO ask only when something changed
@@ -1324,17 +1632,10 @@
 
 void ConfigMainWindow::saveSettings(void)
 {
-#if QT_VERSION >= 300
-	ConfigSettings *configSettings = new ConfigSettings;
-	configSettings->writeEntry("/kconfig/qconf/window x", pos().x());
-	configSettings->writeEntry("/kconfig/qconf/window y", pos().y());
-	configSettings->writeEntry("/kconfig/qconf/window width", size().width());
-	configSettings->writeEntry("/kconfig/qconf/window height", size().height());
-	configSettings->writeEntry("/kconfig/qconf/showName", configList->showName);
-	configSettings->writeEntry("/kconfig/qconf/showRange", configList->showRange);
-	configSettings->writeEntry("/kconfig/qconf/showData", configList->showData);
-	configSettings->writeEntry("/kconfig/qconf/showAll", configList->showAll);
-	configSettings->writeEntry("/kconfig/qconf/showDebug", showDebug);
+	configSettings->writeEntry("/window x", pos().x());
+	configSettings->writeEntry("/window y", pos().y());
+	configSettings->writeEntry("/window width", size().width());
+	configSettings->writeEntry("/window height", size().height());
 
 	QString entry;
 	switch(configList->mode) {
@@ -1350,13 +1651,10 @@
 		entry = "full";
 		break;
 	}
-	configSettings->writeEntry("/kconfig/qconf/listMode", entry);
+	configSettings->writeEntry("/listMode", entry);
 
-	configSettings->writeSizes("/kconfig/qconf/split1", split1->sizes());
-	configSettings->writeSizes("/kconfig/qconf/split2", split2->sizes());
-
-	delete configSettings;
-#endif
+	configSettings->writeSizes("/split1", split1->sizes());
+	configSettings->writeSizes("/split2", split2->sizes());
 }
 
 void fixup_rootmenu(struct menu *menu)
@@ -1414,13 +1712,19 @@
 	conf_read(NULL);
 	//zconfdump(stdout);
 
+	configSettings = new ConfigSettings();
+	configSettings->beginGroup("/kconfig/qconf");
 	v = new ConfigMainWindow();
 
 	//zconfdump(stdout);
-	v->show();
+	configApp->setMainWidget(v);
 	configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
 	configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
+	v->show();
 	configApp->exec();
 
+	configSettings->endGroup();
+	delete configSettings;
+
 	return 0;
 }
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index e52f3e9..6a9e3b1 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -7,9 +7,25 @@
 #if QT_VERSION >= 300
 #include <qsettings.h>
 #else
-class QSettings { };
+class QSettings {
+public:
+	void beginGroup(const QString& group) { }
+	void endGroup(void) { }
+	bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return def; }
+	int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return def; }
+	QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return def; }
+	QStringList readListEntry(const QString& key, bool* ok = 0) const
+	{ if (ok) *ok = FALSE; return QStringList(); }
+	template <class t>
+	bool writeEntry(const QString& key, t value)
+	{ return TRUE; }
+};
 #endif
 
+class ConfigView;
 class ConfigList;
 class ConfigItem;
 class ConfigLineEdit;
@@ -18,64 +34,38 @@
 
 class ConfigSettings : public QSettings {
 public:
-	ConfigSettings();
-
-#if QT_VERSION >= 300
-	void readListSettings();
 	QValueList<int> readSizes(const QString& key, bool *ok);
 	bool writeSizes(const QString& key, const QValueList<int>& value);
-#endif
-
-	bool showAll;
-	bool showName;
-	bool showRange;
-	bool showData;
-};
-
-class ConfigView : public QVBox {
-	Q_OBJECT
-	typedef class QVBox Parent;
-public:
-	ConfigView(QWidget* parent, ConfigMainWindow* cview, ConfigSettings* configSettings);
-	~ConfigView(void);
-	static void updateList(ConfigItem* item);
-	static void updateListAll(void);
-
-public:
-	ConfigList* list;
-	ConfigLineEdit* lineEdit;
-
-	static ConfigView* viewList;
-	ConfigView* nextView;
 };
 
 enum colIdx {
 	promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr
 };
 enum listMode {
-	singleMode, menuMode, symbolMode, fullMode
+	singleMode, menuMode, symbolMode, fullMode, listMode
 };
 
 class ConfigList : public QListView {
 	Q_OBJECT
 	typedef class QListView Parent;
 public:
-	ConfigList(ConfigView* p, ConfigMainWindow* cview, ConfigSettings *configSettings);
+	ConfigList(ConfigView* p, const char *name = 0);
 	void reinit(void);
 	ConfigView* parent(void) const
 	{
 		return (ConfigView*)Parent::parent();
 	}
+	ConfigItem* findConfigItem(struct menu *);
 
 protected:
-	ConfigMainWindow* cview;
-
 	void keyPressEvent(QKeyEvent *e);
 	void contentsMousePressEvent(QMouseEvent *e);
 	void contentsMouseReleaseEvent(QMouseEvent *e);
 	void contentsMouseMoveEvent(QMouseEvent *e);
 	void contentsMouseDoubleClickEvent(QMouseEvent *e);
 	void focusInEvent(QFocusEvent *e);
+	void contextMenuEvent(QContextMenuEvent *e);
+
 public slots:
 	void setRootMenu(struct menu *menu);
 
@@ -83,10 +73,12 @@
 	void setValue(ConfigItem* item, tristate val);
 	void changeValue(ConfigItem* item);
 	void updateSelection(void);
+	void saveSettings(void);
 signals:
+	void menuChanged(struct menu *menu);
 	void menuSelected(struct menu *menu);
 	void parentSelected(void);
-	void gotFocus(void);
+	void gotFocus(struct menu *);
 
 public:
 	void updateListAll(void)
@@ -137,6 +129,7 @@
 	struct menu *rootEntry;
 	QColorGroup disabledColorGroup;
 	QColorGroup inactivedColorGroup;
+	QPopupMenu* headerPopup;
 
 private:
 	int colMap[colNr];
@@ -208,9 +201,7 @@
 	Q_OBJECT
 	typedef class QLineEdit Parent;
 public:
-	ConfigLineEdit(ConfigView* parent)
-	: Parent(parent)
-	{ }
+	ConfigLineEdit(ConfigView* parent);
 	ConfigView* parent(void) const
 	{
 		return (ConfigView*)Parent::parent();
@@ -222,26 +213,104 @@
 	ConfigItem *item;
 };
 
+class ConfigView : public QVBox {
+	Q_OBJECT
+	typedef class QVBox Parent;
+public:
+	ConfigView(QWidget* parent, const char *name = 0);
+	~ConfigView(void);
+	static void updateList(ConfigItem* item);
+	static void updateListAll(void);
+
+	bool showAll(void) const { return list->showAll; }
+	bool showName(void) const { return list->showName; }
+	bool showRange(void) const { return list->showRange; }
+	bool showData(void) const { return list->showData; }
+public slots:
+	void setShowAll(bool);
+	void setShowName(bool);
+	void setShowRange(bool);
+	void setShowData(bool);
+signals:
+	void showAllChanged(bool);
+	void showNameChanged(bool);
+	void showRangeChanged(bool);
+	void showDataChanged(bool);
+public:
+	ConfigList* list;
+	ConfigLineEdit* lineEdit;
+
+	static ConfigView* viewList;
+	ConfigView* nextView;
+};
+
+class ConfigInfoView : public QTextBrowser {
+	Q_OBJECT
+	typedef class QTextBrowser Parent;
+public:
+	ConfigInfoView(QWidget* parent, const char *name = 0);
+	bool showDebug(void) const { return _showDebug; }
+
+public slots:
+	void setInfo(struct menu *menu);
+	void saveSettings(void);
+	void setSource(const QString& name);
+	void setShowDebug(bool);
+
+signals:
+	void showDebugChanged(bool);
+	void menuSelected(struct menu *);
+
+protected:
+	void symbolInfo(void);
+	void menuInfo(void);
+	QString debug_info(struct symbol *sym);
+	static QString print_filter(const QString &str);
+	static void expr_print_help(void *data, struct symbol *sym, const char *str);
+	QPopupMenu* createPopupMenu(const QPoint& pos);
+	void contentsContextMenuEvent(QContextMenuEvent *e);
+
+	struct symbol *sym;
+	struct menu *menu;
+	bool _showDebug;
+};
+
+class ConfigSearchWindow : public QDialog {
+	Q_OBJECT
+	typedef class QDialog Parent;
+public:
+	ConfigSearchWindow(QWidget* parent, const char *name = 0);
+
+public slots:
+	void saveSettings(void);
+	void search(void);
+
+protected:
+	QLineEdit* editField;
+	QPushButton* searchButton;
+	QSplitter* split;
+	ConfigView* list;
+	ConfigInfoView* info;
+
+	struct symbol **result;
+};
+
 class ConfigMainWindow : public QMainWindow {
 	Q_OBJECT
 public:
 	ConfigMainWindow(void);
 public slots:
-	void setHelp(QListViewItem* item);
 	void changeMenu(struct menu *);
+	void setMenuLink(struct menu *);
 	void listFocusChanged(void);
 	void goBack(void);
 	void loadConfig(void);
 	void saveConfig(void);
 	void saveConfigAs(void);
+	void searchConfig(void);
 	void showSingleView(void);
 	void showSplitView(void);
 	void showFullView(void);
-	void setShowAll(bool);
-	void setShowDebug(bool);
-	void setShowRange(bool);
-	void setShowName(bool);
-	void setShowData(bool);
 	void showIntro(void);
 	void showAbout(void);
 	void saveSettings(void);
@@ -249,15 +318,14 @@
 protected:
 	void closeEvent(QCloseEvent *e);
 
+	ConfigSearchWindow *searchWindow;
 	ConfigView *menuView;
 	ConfigList *menuList;
 	ConfigView *configView;
 	ConfigList *configList;
-	QTextView *helpText;
+	ConfigInfoView *helpText;
 	QToolBar *toolBar;
 	QAction *backAction;
 	QSplitter* split1;
 	QSplitter* split2;
-
-	bool showDebug;
 };
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 3d7877a..ee225ce 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -15,15 +15,15 @@
 struct symbol symbol_yes = {
 	.name = "y",
 	.curr = { "y", yes },
-	.flags = SYMBOL_YES|SYMBOL_VALID,
+	.flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_mod = {
 	.name = "m",
 	.curr = { "m", mod },
-	.flags = SYMBOL_MOD|SYMBOL_VALID,
+	.flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_no = {
 	.name = "n",
 	.curr = { "n", no },
-	.flags = SYMBOL_NO|SYMBOL_VALID,
+	.flags = SYMBOL_CONST|SYMBOL_VALID,
 }, symbol_empty = {
 	.name = "",
 	.curr = { "", no },
@@ -31,6 +31,7 @@
 };
 
 int sym_change_count;
+struct symbol *sym_defconfig_list;
 struct symbol *modules_sym;
 tristate modules_val;
 
@@ -227,7 +228,7 @@
 	struct expr *e;
 
 	/* is the user choice visible? */
-	def_sym = sym->user.val;
+	def_sym = sym->def[S_DEF_USER].val;
 	if (def_sym) {
 		sym_calc_visibility(def_sym);
 		if (def_sym->visible != no)
@@ -306,7 +307,7 @@
 		} else if (E_OR(sym->visible, sym->rev_dep.tri) != no) {
 			sym->flags |= SYMBOL_WRITE;
 			if (sym_has_value(sym))
-				newval.tri = sym->user.tri;
+				newval.tri = sym->def[S_DEF_USER].tri;
 			else if (!sym_is_choice(sym)) {
 				prop = sym_get_default_prop(sym);
 				if (prop)
@@ -329,7 +330,7 @@
 		if (sym->visible != no) {
 			sym->flags |= SYMBOL_WRITE;
 			if (sym_has_value(sym)) {
-				newval.val = sym->user.val;
+				newval.val = sym->def[S_DEF_USER].val;
 				break;
 			}
 		}
@@ -352,10 +353,13 @@
 		sym->curr.val = sym_calc_choice(sym);
 	sym_validate_range(sym);
 
-	if (memcmp(&oldval, &sym->curr, sizeof(oldval)))
+	if (memcmp(&oldval, &sym->curr, sizeof(oldval))) {
 		sym_set_changed(sym);
-	if (modules_sym == sym)
-		modules_val = modules_sym->curr.tri;
+		if (modules_sym == sym) {
+			sym_set_all_changed();
+			modules_val = modules_sym->curr.tri;
+		}
+	}
 
 	if (sym_is_choice(sym)) {
 		int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
@@ -426,8 +430,8 @@
 	if (oldval != val && !sym_tristate_within_range(sym, val))
 		return false;
 
-	if (sym->flags & SYMBOL_NEW) {
-		sym->flags &= ~SYMBOL_NEW;
+	if (!(sym->flags & SYMBOL_DEF_USER)) {
+		sym->flags |= SYMBOL_DEF_USER;
 		sym_set_changed(sym);
 	}
 	/*
@@ -439,21 +443,18 @@
 		struct property *prop;
 		struct expr *e;
 
-		cs->user.val = sym;
-		cs->flags &= ~SYMBOL_NEW;
+		cs->def[S_DEF_USER].val = sym;
+		cs->flags |= SYMBOL_DEF_USER;
 		prop = sym_get_choice_prop(cs);
 		for (e = prop->expr; e; e = e->left.expr) {
 			if (e->right.sym->visible != no)
-				e->right.sym->flags &= ~SYMBOL_NEW;
+				e->right.sym->flags |= SYMBOL_DEF_USER;
 		}
 	}
 
-	sym->user.tri = val;
-	if (oldval != val) {
+	sym->def[S_DEF_USER].tri = val;
+	if (oldval != val)
 		sym_clear_all_valid();
-		if (sym == modules_sym)
-			sym_set_all_changed();
-	}
 
 	return true;
 }
@@ -591,20 +592,20 @@
 	if (!sym_string_within_range(sym, newval))
 		return false;
 
-	if (sym->flags & SYMBOL_NEW) {
-		sym->flags &= ~SYMBOL_NEW;
+	if (!(sym->flags & SYMBOL_DEF_USER)) {
+		sym->flags |= SYMBOL_DEF_USER;
 		sym_set_changed(sym);
 	}
 
-	oldval = sym->user.val;
+	oldval = sym->def[S_DEF_USER].val;
 	size = strlen(newval) + 1;
 	if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) {
 		size += 2;
-		sym->user.val = val = malloc(size);
+		sym->def[S_DEF_USER].val = val = malloc(size);
 		*val++ = '0';
 		*val++ = 'x';
 	} else if (!oldval || strcmp(oldval, newval))
-		sym->user.val = val = malloc(size);
+		sym->def[S_DEF_USER].val = val = malloc(size);
 	else
 		return true;
 
@@ -679,7 +680,6 @@
 	memset(symbol, 0, sizeof(*symbol));
 	symbol->name = new_name;
 	symbol->type = S_UNKNOWN;
-	symbol->flags = SYMBOL_NEW;
 	if (isconst)
 		symbol->flags |= SYMBOL_CONST;
 
diff --git a/scripts/kconfig/util.c b/scripts/kconfig/util.c
index 656d2c8..e3f28b9 100644
--- a/scripts/kconfig/util.c
+++ b/scripts/kconfig/util.c
@@ -44,7 +44,9 @@
 		else
 			fprintf(out, "\t%s\n", file->name);
 	}
-	fprintf(out, "\n.config include/linux/autoconf.h: $(deps_config)\n\n$(deps_config):\n");
+	fprintf(out, "\ninclude/config/auto.conf: \\\n"
+		     "\t$(deps_config)\n\n"
+		     "$(deps_config): ;\n");
 	fclose(out);
 	rename("..config.tmp", name);
 	return 0;
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index b032206..9b44c80 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -39,5 +39,8 @@
 select,		T_SELECT,	TF_COMMAND
 enable,		T_SELECT,	TF_COMMAND
 range,		T_RANGE,	TF_COMMAND
+option,		T_OPTION,	TF_COMMAND
 on,		T_ON,		TF_PARAM
+modules,	T_OPT_MODULES,	TF_OPTION
+defconfig_list,	T_OPT_DEFCONFIG_LIST,TF_OPTION
 %%
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index 345f0fc..47c8b5b 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -53,10 +53,10 @@
       47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
       47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
       47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
-      47, 47, 47, 47, 47, 47, 47, 25, 10, 15,
-       0,  0,  5, 47,  0,  0, 47, 47,  0, 10,
-       0, 20, 20, 20,  5,  0,  0, 20, 47, 47,
-      20, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+      47, 47, 47, 47, 47, 47, 47, 25, 30, 15,
+       0, 15,  0, 47,  5, 15, 47, 47, 30, 20,
+       5,  0, 25, 15,  0,  0, 10, 35, 47, 47,
+       5, 47, 47, 47, 47, 47, 47, 47, 47, 47,
       47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
       47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
       47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
@@ -88,69 +88,75 @@
 
 struct kconf_id_strings_t
   {
-    char kconf_id_strings_str2[sizeof("if")];
-    char kconf_id_strings_str3[sizeof("int")];
-    char kconf_id_strings_str4[sizeof("help")];
-    char kconf_id_strings_str5[sizeof("endif")];
-    char kconf_id_strings_str6[sizeof("select")];
-    char kconf_id_strings_str7[sizeof("endmenu")];
-    char kconf_id_strings_str8[sizeof("tristate")];
-    char kconf_id_strings_str9[sizeof("endchoice")];
+    char kconf_id_strings_str2[sizeof("on")];
+    char kconf_id_strings_str6[sizeof("string")];
+    char kconf_id_strings_str7[sizeof("default")];
+    char kconf_id_strings_str8[sizeof("def_bool")];
     char kconf_id_strings_str10[sizeof("range")];
-    char kconf_id_strings_str11[sizeof("string")];
-    char kconf_id_strings_str12[sizeof("default")];
-    char kconf_id_strings_str13[sizeof("def_bool")];
-    char kconf_id_strings_str14[sizeof("menu")];
-    char kconf_id_strings_str16[sizeof("def_boolean")];
-    char kconf_id_strings_str17[sizeof("def_tristate")];
-    char kconf_id_strings_str18[sizeof("mainmenu")];
-    char kconf_id_strings_str20[sizeof("menuconfig")];
-    char kconf_id_strings_str21[sizeof("config")];
-    char kconf_id_strings_str22[sizeof("on")];
-    char kconf_id_strings_str23[sizeof("hex")];
-    char kconf_id_strings_str26[sizeof("source")];
-    char kconf_id_strings_str27[sizeof("depends")];
-    char kconf_id_strings_str28[sizeof("optional")];
-    char kconf_id_strings_str31[sizeof("enable")];
-    char kconf_id_strings_str32[sizeof("comment")];
-    char kconf_id_strings_str33[sizeof("requires")];
+    char kconf_id_strings_str11[sizeof("def_boolean")];
+    char kconf_id_strings_str12[sizeof("def_tristate")];
+    char kconf_id_strings_str13[sizeof("hex")];
+    char kconf_id_strings_str14[sizeof("defconfig_list")];
+    char kconf_id_strings_str16[sizeof("option")];
+    char kconf_id_strings_str17[sizeof("if")];
+    char kconf_id_strings_str18[sizeof("optional")];
+    char kconf_id_strings_str20[sizeof("endif")];
+    char kconf_id_strings_str21[sizeof("choice")];
+    char kconf_id_strings_str22[sizeof("endmenu")];
+    char kconf_id_strings_str23[sizeof("requires")];
+    char kconf_id_strings_str24[sizeof("endchoice")];
+    char kconf_id_strings_str26[sizeof("config")];
+    char kconf_id_strings_str27[sizeof("modules")];
+    char kconf_id_strings_str28[sizeof("int")];
+    char kconf_id_strings_str29[sizeof("menu")];
+    char kconf_id_strings_str31[sizeof("prompt")];
+    char kconf_id_strings_str32[sizeof("depends")];
+    char kconf_id_strings_str33[sizeof("tristate")];
     char kconf_id_strings_str34[sizeof("bool")];
+    char kconf_id_strings_str35[sizeof("menuconfig")];
+    char kconf_id_strings_str36[sizeof("select")];
     char kconf_id_strings_str37[sizeof("boolean")];
-    char kconf_id_strings_str41[sizeof("choice")];
-    char kconf_id_strings_str46[sizeof("prompt")];
+    char kconf_id_strings_str39[sizeof("help")];
+    char kconf_id_strings_str41[sizeof("source")];
+    char kconf_id_strings_str42[sizeof("comment")];
+    char kconf_id_strings_str43[sizeof("mainmenu")];
+    char kconf_id_strings_str46[sizeof("enable")];
   };
 static struct kconf_id_strings_t kconf_id_strings_contents =
   {
-    "if",
-    "int",
-    "help",
-    "endif",
-    "select",
-    "endmenu",
-    "tristate",
-    "endchoice",
-    "range",
+    "on",
     "string",
     "default",
     "def_bool",
-    "menu",
+    "range",
     "def_boolean",
     "def_tristate",
-    "mainmenu",
-    "menuconfig",
-    "config",
-    "on",
     "hex",
-    "source",
-    "depends",
+    "defconfig_list",
+    "option",
+    "if",
     "optional",
-    "enable",
-    "comment",
-    "requires",
-    "bool",
-    "boolean",
+    "endif",
     "choice",
-    "prompt"
+    "endmenu",
+    "requires",
+    "endchoice",
+    "config",
+    "modules",
+    "int",
+    "menu",
+    "prompt",
+    "depends",
+    "tristate",
+    "bool",
+    "menuconfig",
+    "select",
+    "boolean",
+    "help",
+    "source",
+    "comment",
+    "mainmenu",
+    "enable"
   };
 #define kconf_id_strings ((const char *) &kconf_id_strings_contents)
 #ifdef __GNUC__
@@ -161,9 +167,9 @@
 {
   enum
     {
-      TOTAL_KEYWORDS = 30,
+      TOTAL_KEYWORDS = 33,
       MIN_WORD_LENGTH = 2,
-      MAX_WORD_LENGTH = 12,
+      MAX_WORD_LENGTH = 14,
       MIN_HASH_VALUE = 2,
       MAX_HASH_VALUE = 46
     };
@@ -171,43 +177,48 @@
   static struct kconf_id wordlist[] =
     {
       {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,		T_IF,		TF_COMMAND|TF_PARAM},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3,		T_TYPE,		TF_COMMAND, S_INT},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str4,		T_HELP,		TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5,		T_ENDIF,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6,		T_SELECT,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,	T_ENDMENU,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,	T_TYPE,		TF_COMMAND, S_TRISTATE},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9,	T_ENDCHOICE,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10,		T_RANGE,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11,		T_TYPE,		TF_COMMAND, S_STRING},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,		T_MENU,		TF_COMMAND},
-      {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,	T_DEFAULT,	TF_COMMAND, S_TRISTATE},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,	T_MAINMENU,	TF_COMMAND},
-      {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20,	T_MENUCONFIG,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,		T_CONFIG,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,		T_ON,		TF_PARAM},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,		T_TYPE,		TF_COMMAND, S_HEX},
-      {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26,		T_SOURCE,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,	T_DEPENDS,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,	T_OPTIONAL,	TF_COMMAND},
-      {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,		T_SELECT,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,	T_COMMENT,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,	T_REQUIRES,	TF_COMMAND},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34,		T_TYPE,		TF_COMMAND, S_BOOLEAN},
-      {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37,	T_TYPE,		TF_COMMAND, S_BOOLEAN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2,		T_ON,		TF_PARAM},
       {-1}, {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,		T_CHOICE,	TF_COMMAND},
-      {-1}, {-1}, {-1}, {-1},
-      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_PROMPT,	TF_COMMAND}
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6,		T_TYPE,		TF_COMMAND, S_STRING},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7,	T_DEFAULT,	TF_COMMAND, S_UNKNOWN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10,		T_RANGE,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11,	T_DEFAULT,	TF_COMMAND, S_BOOLEAN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12,	T_DEFAULT,	TF_COMMAND, S_TRISTATE},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13,		T_TYPE,		TF_COMMAND, S_HEX},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14,	T_OPT_DEFCONFIG_LIST,TF_OPTION},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16,		T_OPTION,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17,		T_IF,		TF_COMMAND|TF_PARAM},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18,	T_OPTIONAL,	TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str20,		T_ENDIF,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21,		T_CHOICE,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22,	T_ENDMENU,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23,	T_REQUIRES,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str24,	T_ENDCHOICE,	TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26,		T_CONFIG,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27,	T_OPT_MODULES,	TF_OPTION},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28,		T_TYPE,		TF_COMMAND, S_INT},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29,		T_MENU,		TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31,		T_PROMPT,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32,	T_DEPENDS,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33,	T_TYPE,		TF_COMMAND, S_TRISTATE},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str34,		T_TYPE,		TF_COMMAND, S_BOOLEAN},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35,	T_MENUCONFIG,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36,		T_SELECT,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37,	T_TYPE,		TF_COMMAND, S_BOOLEAN},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39,		T_HELP,		TF_COMMAND},
+      {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41,		T_SOURCE,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_COMMENT,	TF_COMMAND},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43,	T_MAINMENU,	TF_COMMAND},
+      {-1}, {-1},
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_SELECT,	TF_COMMAND}
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index ea7755d..2fb0a4f 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1,7 +1,7 @@
-/* A Bison parser, made by GNU Bison 2.0.  */
+/* A Bison parser, made by GNU Bison 2.1.  */
 
 /* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 /* As a special exception, when this file is copied by Bison into a
    Bison output file, you may use that output file without restriction.
@@ -36,6 +36,9 @@
 /* Identify Bison output.  */
 #define YYBISON 1
 
+/* Bison version.  */
+#define YYBISON_VERSION "2.1"
+
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
 
@@ -82,19 +85,21 @@
      T_DEFAULT = 276,
      T_SELECT = 277,
      T_RANGE = 278,
-     T_ON = 279,
-     T_WORD = 280,
-     T_WORD_QUOTE = 281,
-     T_UNEQUAL = 282,
-     T_CLOSE_PAREN = 283,
-     T_OPEN_PAREN = 284,
-     T_EOL = 285,
-     T_OR = 286,
-     T_AND = 287,
-     T_EQUAL = 288,
-     T_NOT = 289
+     T_OPTION = 279,
+     T_ON = 280,
+     T_WORD = 281,
+     T_WORD_QUOTE = 282,
+     T_UNEQUAL = 283,
+     T_CLOSE_PAREN = 284,
+     T_OPEN_PAREN = 285,
+     T_EOL = 286,
+     T_OR = 287,
+     T_AND = 288,
+     T_EQUAL = 289,
+     T_NOT = 290
    };
 #endif
+/* Tokens.  */
 #define T_MAINMENU 258
 #define T_MENU 259
 #define T_ENDMENU 260
@@ -116,17 +121,18 @@
 #define T_DEFAULT 276
 #define T_SELECT 277
 #define T_RANGE 278
-#define T_ON 279
-#define T_WORD 280
-#define T_WORD_QUOTE 281
-#define T_UNEQUAL 282
-#define T_CLOSE_PAREN 283
-#define T_OPEN_PAREN 284
-#define T_EOL 285
-#define T_OR 286
-#define T_AND 287
-#define T_EQUAL 288
-#define T_NOT 289
+#define T_OPTION 279
+#define T_ON 280
+#define T_WORD 281
+#define T_WORD_QUOTE 282
+#define T_UNEQUAL 283
+#define T_CLOSE_PAREN 284
+#define T_OPEN_PAREN 285
+#define T_EOL 286
+#define T_OR 287
+#define T_AND 288
+#define T_EQUAL 289
+#define T_NOT 290
 
 
 
@@ -187,6 +193,11 @@
 # define YYERROR_VERBOSE 0
 #endif
 
+/* Enabling the token table.  */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
 
 typedef union YYSTYPE {
@@ -197,7 +208,7 @@
 	struct menu *menu;
 	struct kconf_id *id;
 } YYSTYPE;
-/* Line 190 of yacc.c.  */
+/* Line 196 of yacc.c.  */
 
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -209,18 +220,37 @@
 /* Copy the second part of user declarations.  */
 
 
-/* Line 213 of yacc.c.  */
+/* Line 219 of yacc.c.  */
 
 
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus))
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#ifndef YY_
+# if YYENABLE_NLS
+#  if ENABLE_NLS
+#   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#  endif
+# endif
+# ifndef YY_
+#  define YY_(msgid) msgid
+# endif
+#endif
+
 #if ! defined (yyoverflow) || YYERROR_VERBOSE
 
-# ifndef YYFREE
-#  define YYFREE free
-# endif
-# ifndef YYMALLOC
-#  define YYMALLOC malloc
-# endif
-
 /* The parser invokes alloca or malloc; define the necessary symbols.  */
 
 # ifdef YYSTACK_USE_ALLOCA
@@ -229,6 +259,10 @@
 #    define YYSTACK_ALLOC __builtin_alloca
 #   else
 #    define YYSTACK_ALLOC alloca
+#    if defined (__STDC__) || defined (__cplusplus)
+#     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#     define YYINCLUDED_STDLIB_H
+#    endif
 #   endif
 #  endif
 # endif
@@ -236,13 +270,39 @@
 # ifdef YYSTACK_ALLOC
    /* Pacify GCC's `empty if-body' warning. */
 #  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
-# else
-#  if defined (__STDC__) || defined (__cplusplus)
-#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-#   define YYSIZE_T size_t
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+    /* The OS might guarantee only one guard page at the bottom of the stack,
+       and a page size can be as small as 4096 bytes.  So we cannot safely
+       invoke alloca (N) if N exceeds 4096.  Use a slightly smaller number
+       to allow for a few compiler-allocated temporary stack slots.  */
+#   define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */
 #  endif
+# else
 #  define YYSTACK_ALLOC YYMALLOC
 #  define YYSTACK_FREE YYFREE
+#  ifndef YYSTACK_ALLOC_MAXIMUM
+#   define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1)
+#  endif
+#  ifdef __cplusplus
+extern "C" {
+#  endif
+#  ifndef YYMALLOC
+#   define YYMALLOC malloc
+#   if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \
+	&& (defined (__STDC__) || defined (__cplusplus)))
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifndef YYFREE
+#   define YYFREE free
+#   if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \
+	&& (defined (__STDC__) || defined (__cplusplus)))
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+#   endif
+#  endif
+#  ifdef __cplusplus
+}
+#  endif
 # endif
 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
 
@@ -277,7 +337,7 @@
 #   define YYCOPY(To, From, Count)		\
       do					\
 	{					\
-	  register YYSIZE_T yyi;		\
+	  YYSIZE_T yyi;				\
 	  for (yyi = 0; yyi < (Count); yyi++)	\
 	    (To)[yyi] = (From)[yyi];		\
 	}					\
@@ -312,22 +372,22 @@
 /* YYFINAL -- State number of the termination state. */
 #define YYFINAL  3
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   264
+#define YYLAST   275
 
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  35
+#define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  42
+#define YYNNTS  45
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  104
+#define YYNRULES  110
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  175
+#define YYNSTATES  183
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   289
+#define YYMAXUTOK   290
 
-#define YYTRANSLATE(YYX) 						\
+#define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
@@ -361,7 +421,8 @@
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33,    34
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
+      35
 };
 
 #if YYDEBUG
@@ -372,72 +433,75 @@
        0,     0,     3,     5,     6,     9,    12,    15,    20,    23,
       28,    33,    37,    39,    41,    43,    45,    47,    49,    51,
       53,    55,    57,    59,    61,    63,    67,    70,    74,    77,
-      81,    84,    85,    88,    91,    94,    97,   100,   104,   109,
-     114,   119,   125,   128,   131,   133,   137,   138,   141,   144,
-     147,   150,   153,   158,   162,   165,   170,   171,   174,   178,
-     180,   184,   185,   188,   191,   194,   198,   201,   203,   207,
-     208,   211,   214,   217,   221,   225,   228,   231,   234,   235,
-     238,   241,   244,   249,   253,   257,   258,   261,   263,   265,
-     268,   271,   274,   276,   279,   280,   283,   285,   289,   293,
-     297,   300,   304,   308,   310
+      81,    84,    85,    88,    91,    94,    97,   100,   103,   107,
+     112,   117,   122,   128,   132,   133,   137,   138,   141,   144,
+     147,   149,   153,   154,   157,   160,   163,   166,   169,   174,
+     178,   181,   186,   187,   190,   194,   196,   200,   201,   204,
+     207,   210,   214,   217,   219,   223,   224,   227,   230,   233,
+     237,   241,   244,   247,   250,   251,   254,   257,   260,   265,
+     269,   273,   274,   277,   279,   281,   284,   287,   290,   292,
+     295,   296,   299,   301,   305,   309,   313,   316,   320,   324,
+     326
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
 static const yysigned_char yyrhs[] =
 {
-      36,     0,    -1,    37,    -1,    -1,    37,    39,    -1,    37,
-      50,    -1,    37,    61,    -1,    37,     3,    71,    73,    -1,
-      37,    72,    -1,    37,    25,     1,    30,    -1,    37,    38,
-       1,    30,    -1,    37,     1,    30,    -1,    16,    -1,    19,
+      37,     0,    -1,    38,    -1,    -1,    38,    40,    -1,    38,
+      54,    -1,    38,    65,    -1,    38,     3,    75,    77,    -1,
+      38,    76,    -1,    38,    26,     1,    31,    -1,    38,    39,
+       1,    31,    -1,    38,     1,    31,    -1,    16,    -1,    19,
       -1,    20,    -1,    22,    -1,    18,    -1,    23,    -1,    21,
-      -1,    30,    -1,    56,    -1,    65,    -1,    42,    -1,    44,
-      -1,    63,    -1,    25,     1,    30,    -1,     1,    30,    -1,
-      10,    25,    30,    -1,    41,    45,    -1,    11,    25,    30,
-      -1,    43,    45,    -1,    -1,    45,    46,    -1,    45,    69,
-      -1,    45,    67,    -1,    45,    40,    -1,    45,    30,    -1,
-      20,    70,    30,    -1,    19,    71,    74,    30,    -1,    21,
-      75,    74,    30,    -1,    22,    25,    74,    30,    -1,    23,
-      76,    76,    74,    30,    -1,     7,    30,    -1,    47,    51,
-      -1,    72,    -1,    48,    53,    49,    -1,    -1,    51,    52,
-      -1,    51,    69,    -1,    51,    67,    -1,    51,    30,    -1,
-      51,    40,    -1,    19,    71,    74,    30,    -1,    20,    70,
-      30,    -1,    18,    30,    -1,    21,    25,    74,    30,    -1,
-      -1,    53,    39,    -1,    14,    75,    73,    -1,    72,    -1,
-      54,    57,    55,    -1,    -1,    57,    39,    -1,    57,    61,
-      -1,    57,    50,    -1,     4,    71,    30,    -1,    58,    68,
-      -1,    72,    -1,    59,    62,    60,    -1,    -1,    62,    39,
-      -1,    62,    61,    -1,    62,    50,    -1,     6,    71,    30,
-      -1,     9,    71,    30,    -1,    64,    68,    -1,    12,    30,
-      -1,    66,    13,    -1,    -1,    68,    69,    -1,    68,    30,
-      -1,    68,    40,    -1,    16,    24,    75,    30,    -1,    16,
-      75,    30,    -1,    17,    75,    30,    -1,    -1,    71,    74,
-      -1,    25,    -1,    26,    -1,     5,    30,    -1,     8,    30,
-      -1,    15,    30,    -1,    30,    -1,    73,    30,    -1,    -1,
-      14,    75,    -1,    76,    -1,    76,    33,    76,    -1,    76,
-      27,    76,    -1,    29,    75,    28,    -1,    34,    75,    -1,
-      75,    31,    75,    -1,    75,    32,    75,    -1,    25,    -1,
-      26,    -1
+      -1,    31,    -1,    60,    -1,    69,    -1,    43,    -1,    45,
+      -1,    67,    -1,    26,     1,    31,    -1,     1,    31,    -1,
+      10,    26,    31,    -1,    42,    46,    -1,    11,    26,    31,
+      -1,    44,    46,    -1,    -1,    46,    47,    -1,    46,    48,
+      -1,    46,    73,    -1,    46,    71,    -1,    46,    41,    -1,
+      46,    31,    -1,    20,    74,    31,    -1,    19,    75,    78,
+      31,    -1,    21,    79,    78,    31,    -1,    22,    26,    78,
+      31,    -1,    23,    80,    80,    78,    31,    -1,    24,    49,
+      31,    -1,    -1,    49,    26,    50,    -1,    -1,    34,    75,
+      -1,     7,    31,    -1,    51,    55,    -1,    76,    -1,    52,
+      57,    53,    -1,    -1,    55,    56,    -1,    55,    73,    -1,
+      55,    71,    -1,    55,    31,    -1,    55,    41,    -1,    19,
+      75,    78,    31,    -1,    20,    74,    31,    -1,    18,    31,
+      -1,    21,    26,    78,    31,    -1,    -1,    57,    40,    -1,
+      14,    79,    77,    -1,    76,    -1,    58,    61,    59,    -1,
+      -1,    61,    40,    -1,    61,    65,    -1,    61,    54,    -1,
+       4,    75,    31,    -1,    62,    72,    -1,    76,    -1,    63,
+      66,    64,    -1,    -1,    66,    40,    -1,    66,    65,    -1,
+      66,    54,    -1,     6,    75,    31,    -1,     9,    75,    31,
+      -1,    68,    72,    -1,    12,    31,    -1,    70,    13,    -1,
+      -1,    72,    73,    -1,    72,    31,    -1,    72,    41,    -1,
+      16,    25,    79,    31,    -1,    16,    79,    31,    -1,    17,
+      79,    31,    -1,    -1,    75,    78,    -1,    26,    -1,    27,
+      -1,     5,    31,    -1,     8,    31,    -1,    15,    31,    -1,
+      31,    -1,    77,    31,    -1,    -1,    14,    79,    -1,    80,
+      -1,    80,    34,    80,    -1,    80,    28,    80,    -1,    30,
+      79,    29,    -1,    35,    79,    -1,    79,    32,    79,    -1,
+      79,    33,    79,    -1,    26,    -1,    27,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const unsigned short int yyrline[] =
 {
-       0,   103,   103,   105,   107,   108,   109,   110,   111,   112,
-     113,   117,   121,   121,   121,   121,   121,   121,   121,   125,
-     126,   127,   128,   129,   130,   134,   135,   141,   149,   155,
-     163,   173,   175,   176,   177,   178,   179,   182,   190,   196,
-     206,   212,   220,   229,   234,   242,   245,   247,   248,   249,
-     250,   251,   254,   260,   271,   277,   287,   289,   294,   302,
-     310,   313,   315,   316,   317,   322,   329,   334,   342,   345,
-     347,   348,   349,   352,   360,   367,   374,   380,   387,   389,
-     390,   391,   394,   399,   404,   412,   414,   419,   420,   423,
-     424,   425,   429,   430,   433,   434,   437,   438,   439,   440,
-     441,   442,   443,   446,   447
+       0,   105,   105,   107,   109,   110,   111,   112,   113,   114,
+     115,   119,   123,   123,   123,   123,   123,   123,   123,   127,
+     128,   129,   130,   131,   132,   136,   137,   143,   151,   157,
+     165,   175,   177,   178,   179,   180,   181,   182,   185,   193,
+     199,   209,   215,   221,   224,   226,   237,   238,   243,   252,
+     257,   265,   268,   270,   271,   272,   273,   274,   277,   283,
+     294,   300,   310,   312,   317,   325,   333,   336,   338,   339,
+     340,   345,   352,   357,   365,   368,   370,   371,   372,   375,
+     383,   390,   397,   403,   410,   412,   413,   414,   417,   422,
+     427,   435,   437,   442,   443,   446,   447,   448,   452,   453,
+     456,   457,   460,   461,   462,   463,   464,   465,   466,   469,
+     470
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE
-/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals. */
 static const char *const yytname[] =
 {
@@ -445,17 +509,18 @@
   "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
   "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
   "T_REQUIRES", "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT",
-  "T_SELECT", "T_RANGE", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
-  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
-  "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
-  "option_error", "config_entry_start", "config_stmt",
+  "T_SELECT", "T_RANGE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE",
+  "T_UNEQUAL", "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND",
+  "T_EQUAL", "T_NOT", "$accept", "input", "stmt_list", "option_name",
+  "common_stmt", "option_error", "config_entry_start", "config_stmt",
   "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
-  "config_option", "choice", "choice_entry", "choice_end", "choice_stmt",
-  "choice_option_list", "choice_option", "choice_block", "if_entry",
-  "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end",
-  "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt",
-  "help_start", "help", "depends_list", "depends", "prompt_stmt_opt",
-  "prompt", "end", "nl", "if_expr", "expr", "symbol", 0
+  "config_option", "symbol_option", "symbol_option_list",
+  "symbol_option_arg", "choice", "choice_entry", "choice_end",
+  "choice_stmt", "choice_option_list", "choice_option", "choice_block",
+  "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
+  "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
+  "comment_stmt", "help_start", "help", "depends_list", "depends",
+  "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", 0
 };
 #endif
 
@@ -467,24 +532,25 @@
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289
+     285,   286,   287,   288,   289,   290
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const unsigned char yyr1[] =
 {
-       0,    35,    36,    37,    37,    37,    37,    37,    37,    37,
-      37,    37,    38,    38,    38,    38,    38,    38,    38,    39,
-      39,    39,    39,    39,    39,    40,    40,    41,    42,    43,
-      44,    45,    45,    45,    45,    45,    45,    46,    46,    46,
-      46,    46,    47,    48,    49,    50,    51,    51,    51,    51,
-      51,    51,    52,    52,    52,    52,    53,    53,    54,    55,
-      56,    57,    57,    57,    57,    58,    59,    60,    61,    62,
-      62,    62,    62,    63,    64,    65,    66,    67,    68,    68,
-      68,    68,    69,    69,    69,    70,    70,    71,    71,    72,
-      72,    72,    73,    73,    74,    74,    75,    75,    75,    75,
-      75,    75,    75,    76,    76
+       0,    36,    37,    38,    38,    38,    38,    38,    38,    38,
+      38,    38,    39,    39,    39,    39,    39,    39,    39,    40,
+      40,    40,    40,    40,    40,    41,    41,    42,    43,    44,
+      45,    46,    46,    46,    46,    46,    46,    46,    47,    47,
+      47,    47,    47,    48,    49,    49,    50,    50,    51,    52,
+      53,    54,    55,    55,    55,    55,    55,    55,    56,    56,
+      56,    56,    57,    57,    58,    59,    60,    61,    61,    61,
+      61,    62,    63,    64,    65,    66,    66,    66,    66,    67,
+      68,    69,    70,    71,    72,    72,    72,    72,    73,    73,
+      73,    74,    74,    75,    75,    76,    76,    76,    77,    77,
+      78,    78,    79,    79,    79,    79,    79,    79,    79,    80,
+      80
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -493,14 +559,15 @@
        0,     2,     1,     0,     2,     2,     2,     4,     2,     4,
        4,     3,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     3,     2,     3,     2,     3,
-       2,     0,     2,     2,     2,     2,     2,     3,     4,     4,
-       4,     5,     2,     2,     1,     3,     0,     2,     2,     2,
-       2,     2,     4,     3,     2,     4,     0,     2,     3,     1,
-       3,     0,     2,     2,     2,     3,     2,     1,     3,     0,
-       2,     2,     2,     3,     3,     2,     2,     2,     0,     2,
-       2,     2,     4,     3,     3,     0,     2,     1,     1,     2,
-       2,     2,     1,     2,     0,     2,     1,     3,     3,     3,
-       2,     3,     3,     1,     1
+       2,     0,     2,     2,     2,     2,     2,     2,     3,     4,
+       4,     4,     5,     3,     0,     3,     0,     2,     2,     2,
+       1,     3,     0,     2,     2,     2,     2,     2,     4,     3,
+       2,     4,     0,     2,     3,     1,     3,     0,     2,     2,
+       2,     3,     2,     1,     3,     0,     2,     2,     2,     3,
+       3,     2,     2,     2,     0,     2,     2,     2,     4,     3,
+       3,     0,     2,     1,     1,     2,     2,     2,     1,     2,
+       0,     2,     1,     3,     3,     3,     2,     3,     3,     1,
+       1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -511,175 +578,164 @@
        3,     0,     0,     1,     0,     0,     0,     0,     0,     0,
        0,     0,     0,     0,     0,     0,    12,    16,    13,    14,
       18,    15,    17,     0,    19,     0,     4,    31,    22,    31,
-      23,    46,    56,     5,    61,    20,    78,    69,     6,    24,
-      78,    21,     8,    11,    87,    88,     0,     0,    89,     0,
-      42,    90,     0,     0,     0,   103,   104,     0,     0,     0,
-      96,    91,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    92,     7,    65,    73,    74,    27,    29,     0,
-     100,     0,     0,    58,     0,     0,     9,    10,     0,     0,
-       0,     0,     0,    85,     0,     0,     0,     0,    36,    35,
-      32,     0,    34,    33,     0,     0,    85,     0,    50,    51,
-      47,    49,    48,    57,    45,    44,    62,    64,    60,    63,
-      59,    80,    81,    79,    70,    72,    68,    71,    67,    93,
-      99,   101,   102,    98,    97,    26,    76,     0,     0,     0,
-      94,     0,    94,    94,    94,     0,     0,    77,    54,    94,
-       0,    94,     0,    83,    84,     0,     0,    37,    86,     0,
-       0,    94,    25,     0,    53,     0,    82,    95,    38,    39,
-      40,     0,    52,    55,    41
+      23,    52,    62,     5,    67,    20,    84,    75,     6,    24,
+      84,    21,     8,    11,    93,    94,     0,     0,    95,     0,
+      48,    96,     0,     0,     0,   109,   110,     0,     0,     0,
+     102,    97,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    98,     7,    71,    79,    80,    27,    29,     0,
+     106,     0,     0,    64,     0,     0,     9,    10,     0,     0,
+       0,     0,     0,    91,     0,     0,     0,    44,     0,    37,
+      36,    32,    33,     0,    35,    34,     0,     0,    91,     0,
+      56,    57,    53,    55,    54,    63,    51,    50,    68,    70,
+      66,    69,    65,    86,    87,    85,    76,    78,    74,    77,
+      73,    99,   105,   107,   108,   104,   103,    26,    82,     0,
+       0,     0,   100,     0,   100,   100,   100,     0,     0,     0,
+      83,    60,   100,     0,   100,     0,    89,    90,     0,     0,
+      38,    92,     0,     0,   100,    46,    43,    25,     0,    59,
+       0,    88,   101,    39,    40,    41,     0,     0,    45,    58,
+      61,    42,    47
 };
 
 /* YYDEFGOTO[NTERM-NUM]. */
 static const short int yydefgoto[] =
 {
-      -1,     1,     2,    25,    26,    99,    27,    28,    29,    30,
-      64,   100,    31,    32,   114,    33,    66,   110,    67,    34,
-     118,    35,    68,    36,    37,   126,    38,    70,    39,    40,
-      41,   101,   102,    69,   103,   141,   142,    42,    73,   156,
-      59,    60
+      -1,     1,     2,    25,    26,   100,    27,    28,    29,    30,
+      64,   101,   102,   148,   178,    31,    32,   116,    33,    66,
+     112,    67,    34,   120,    35,    68,    36,    37,   128,    38,
+      70,    39,    40,    41,   103,   104,    69,   105,   143,   144,
+      42,    73,   159,    59,    60
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -78
+#define YYPACT_NINF -135
 static const short int yypact[] =
 {
-     -78,     2,   159,   -78,   -21,     0,     0,   -12,     0,     1,
-       4,     0,    27,    38,    60,    58,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   100,   -78,   104,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,    86,   113,   -78,   114,
-     -78,   -78,   125,   127,   128,   -78,   -78,    60,    60,   210,
-      65,   -78,   141,   142,    39,   103,   182,   200,     6,    66,
-       6,   131,   -78,   146,   -78,   -78,   -78,   -78,   -78,   196,
-     -78,    60,    60,   146,    40,    40,   -78,   -78,   155,   156,
-      -2,    60,     0,     0,    60,   105,    40,   194,   -78,   -78,
-     -78,   206,   -78,   -78,   183,     0,     0,   195,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
-     -78,   197,   -78,   -78,   -78,   -78,   -78,    60,   213,   216,
-     212,   203,   212,   190,   212,    40,   208,   -78,   -78,   212,
-     222,   212,   219,   -78,   -78,    60,   223,   -78,   -78,   224,
-     225,   212,   -78,   226,   -78,   227,   -78,    47,   -78,   -78,
-     -78,   228,   -78,   -78,   -78
+    -135,     2,   170,  -135,   -14,    56,    56,    -8,    56,    24,
+      67,    56,     7,    14,    62,    97,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,   156,  -135,   166,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,   138,   151,  -135,   152,
+    -135,  -135,   163,   167,   176,  -135,  -135,    62,    62,   185,
+     -19,  -135,   188,   190,    42,   103,   194,    85,    70,   222,
+      70,   132,  -135,   191,  -135,  -135,  -135,  -135,  -135,   127,
+    -135,    62,    62,   191,   104,   104,  -135,  -135,   193,   203,
+       9,    62,    56,    56,    62,   161,   104,  -135,   196,  -135,
+    -135,  -135,  -135,   233,  -135,  -135,   204,    56,    56,   221,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,
+    -135,  -135,  -135,   219,  -135,  -135,  -135,  -135,  -135,    62,
+     209,   212,   240,   224,   240,    -1,   240,   104,    41,   225,
+    -135,  -135,   240,   226,   240,   218,  -135,  -135,    62,   227,
+    -135,  -135,   228,   229,   240,   230,  -135,  -135,   231,  -135,
+     232,  -135,   112,  -135,  -135,  -135,   234,    56,  -135,  -135,
+    -135,  -135,  -135
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const short int yypgoto[] =
 {
-     -78,   -78,   -78,   -78,   164,   -36,   -78,   -78,   -78,   -78,
-     230,   -78,   -78,   -78,   -78,    29,   -78,   -78,   -78,   -78,
-     -78,   -78,   -78,   -78,   -78,   -78,    59,   -78,   -78,   -78,
-     -78,   -78,   198,   220,    24,   157,    -5,   169,   202,    74,
-     -53,   -77
+    -135,  -135,  -135,  -135,    94,   -45,  -135,  -135,  -135,  -135,
+     237,  -135,  -135,  -135,  -135,  -135,  -135,  -135,   -54,  -135,
+    -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,  -135,     1,
+    -135,  -135,  -135,  -135,  -135,   195,   235,   -44,   159,    -5,
+      98,   210,  -134,   -53,   -77
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -76
+#define YYTABLE_NINF -82
 static const short int yytable[] =
 {
-      46,    47,     3,    49,    79,    80,    52,   133,   134,    43,
-       6,     7,     8,     9,    10,    11,    12,    13,    48,   145,
-      14,    15,   137,    55,    56,    44,    45,    57,   131,   132,
-     109,    50,    58,   122,    51,   122,    24,   138,   139,   -28,
-      88,   143,   -28,   -28,   -28,   -28,   -28,   -28,   -28,   -28,
-     -28,    89,    53,   -28,   -28,    90,    91,   -28,    92,    93,
-      94,    95,    96,    54,    97,    55,    56,    88,   161,    98,
-     -66,   -66,   -66,   -66,   -66,   -66,   -66,   -66,    81,    82,
-     -66,   -66,    90,    91,   152,    55,    56,   140,    61,    57,
-     112,    97,    84,   123,    58,   123,   121,   117,    85,   125,
-     149,    62,   167,   -30,    88,    63,   -30,   -30,   -30,   -30,
-     -30,   -30,   -30,   -30,   -30,    89,    72,   -30,   -30,    90,
-      91,   -30,    92,    93,    94,    95,    96,   119,    97,   127,
-     144,   -75,    88,    98,   -75,   -75,   -75,   -75,   -75,   -75,
-     -75,   -75,   -75,    74,    75,   -75,   -75,    90,    91,   -75,
-     -75,   -75,   -75,   -75,   -75,    76,    97,    77,    78,    -2,
-       4,   121,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    86,    87,    14,    15,    16,   129,    17,    18,    19,
-      20,    21,    22,    88,    23,   135,   136,   -43,   -43,    24,
-     -43,   -43,   -43,   -43,    89,   146,   -43,   -43,    90,    91,
-     104,   105,   106,   107,   155,     7,     8,    97,    10,    11,
-      12,    13,   108,   148,    14,    15,   158,   159,   160,   147,
-     151,    81,    82,   163,   130,   165,   155,    81,    82,    82,
-      24,   113,   116,   157,   124,   171,   115,   120,   162,   128,
-      72,    81,    82,   153,    81,    82,   154,    81,    82,   166,
-      81,    82,   164,   168,   169,   170,   172,   173,   174,    65,
-      71,    83,     0,   150,   111
+      46,    47,     3,    49,    79,    80,    52,   135,   136,    84,
+     161,   162,   163,   158,   119,    85,   127,    43,   168,   147,
+     170,   111,   114,    48,   124,   125,   124,   125,   133,   134,
+     176,    81,    82,    53,   139,    55,    56,   140,   141,    57,
+      54,   145,   -28,    88,    58,   -28,   -28,   -28,   -28,   -28,
+     -28,   -28,   -28,   -28,    89,    50,   -28,   -28,    90,    91,
+     -28,    92,    93,    94,    95,    96,    97,   165,    98,   121,
+     164,   129,   166,    99,     6,     7,     8,     9,    10,    11,
+      12,    13,    44,    45,    14,    15,   155,   142,    55,    56,
+       7,     8,    57,    10,    11,    12,    13,    58,    51,    14,
+      15,    24,   152,   -30,    88,   172,   -30,   -30,   -30,   -30,
+     -30,   -30,   -30,   -30,   -30,    89,    24,   -30,   -30,    90,
+      91,   -30,    92,    93,    94,    95,    96,    97,    61,    98,
+      55,    56,   -81,    88,    99,   -81,   -81,   -81,   -81,   -81,
+     -81,   -81,   -81,   -81,    81,    82,   -81,   -81,    90,    91,
+     -81,   -81,   -81,   -81,   -81,   -81,   132,    62,    98,    81,
+      82,   115,   118,   123,   126,   117,   122,    63,   130,    72,
+      -2,     4,   182,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    74,    75,    14,    15,    16,   146,    17,    18,
+      19,    20,    21,    22,    76,    88,    23,   149,    77,   -49,
+     -49,    24,   -49,   -49,   -49,   -49,    89,    78,   -49,   -49,
+      90,    91,   106,   107,   108,   109,    72,    81,    82,    86,
+      98,    87,   131,    88,   137,   110,   -72,   -72,   -72,   -72,
+     -72,   -72,   -72,   -72,   138,   151,   -72,   -72,    90,    91,
+     156,    81,    82,   157,    81,    82,   150,   154,    98,   171,
+      81,    82,    82,   123,   158,   160,   167,   169,   173,   174,
+     175,   113,   179,   180,   177,   181,    65,   153,     0,    83,
+       0,     0,     0,     0,     0,    71
 };
 
 static const short int yycheck[] =
 {
-       5,     6,     0,     8,    57,    58,    11,    84,    85,    30,
-       4,     5,     6,     7,     8,     9,    10,    11,    30,    96,
-      14,    15,    24,    25,    26,    25,    26,    29,    81,    82,
-      66,    30,    34,    69,    30,    71,    30,    90,    91,     0,
-       1,    94,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    12,    25,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    25,    25,    25,    26,     1,   145,    30,
-       4,     5,     6,     7,     8,     9,    10,    11,    31,    32,
-      14,    15,    16,    17,   137,    25,    26,    92,    30,    29,
-      66,    25,    27,    69,    34,    71,    30,    68,    33,    70,
-     105,     1,   155,     0,     1,     1,     3,     4,     5,     6,
-       7,     8,     9,    10,    11,    12,    30,    14,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    68,    25,    70,
-      25,     0,     1,    30,     3,     4,     5,     6,     7,     8,
-       9,    10,    11,    30,    30,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    30,    25,    30,    30,     0,
-       1,    30,     3,     4,     5,     6,     7,     8,     9,    10,
-      11,    30,    30,    14,    15,    16,    30,    18,    19,    20,
-      21,    22,    23,     1,    25,    30,    30,     5,     6,    30,
-       8,     9,    10,    11,    12,     1,    14,    15,    16,    17,
-      18,    19,    20,    21,    14,     5,     6,    25,     8,     9,
-      10,    11,    30,    30,    14,    15,   142,   143,   144,    13,
-      25,    31,    32,   149,    28,   151,    14,    31,    32,    32,
-      30,    67,    68,    30,    70,   161,    67,    68,    30,    70,
-      30,    31,    32,    30,    31,    32,    30,    31,    32,    30,
-      31,    32,    30,    30,    30,    30,    30,    30,    30,    29,
-      40,    59,    -1,   106,    66
+       5,     6,     0,     8,    57,    58,    11,    84,    85,    28,
+     144,   145,   146,    14,    68,    34,    70,    31,   152,    96,
+     154,    66,    66,    31,    69,    69,    71,    71,    81,    82,
+     164,    32,    33,    26,    25,    26,    27,    90,    91,    30,
+      26,    94,     0,     1,    35,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    12,    31,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    26,    26,    68,
+     147,    70,    31,    31,     4,     5,     6,     7,     8,     9,
+      10,    11,    26,    27,    14,    15,   139,    92,    26,    27,
+       5,     6,    30,     8,     9,    10,    11,    35,    31,    14,
+      15,    31,   107,     0,     1,   158,     3,     4,     5,     6,
+       7,     8,     9,    10,    11,    12,    31,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,    31,    26,
+      26,    27,     0,     1,    31,     3,     4,     5,     6,     7,
+       8,     9,    10,    11,    32,    33,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    29,     1,    26,    32,
+      33,    67,    68,    31,    70,    67,    68,     1,    70,    31,
+       0,     1,   177,     3,     4,     5,     6,     7,     8,     9,
+      10,    11,    31,    31,    14,    15,    16,    26,    18,    19,
+      20,    21,    22,    23,    31,     1,    26,     1,    31,     5,
+       6,    31,     8,     9,    10,    11,    12,    31,    14,    15,
+      16,    17,    18,    19,    20,    21,    31,    32,    33,    31,
+      26,    31,    31,     1,    31,    31,     4,     5,     6,     7,
+       8,     9,    10,    11,    31,    31,    14,    15,    16,    17,
+      31,    32,    33,    31,    32,    33,    13,    26,    26,    31,
+      32,    33,    33,    31,    14,    31,    31,    31,    31,    31,
+      31,    66,    31,    31,    34,    31,    29,   108,    -1,    59,
+      -1,    -1,    -1,    -1,    -1,    40
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const unsigned char yystos[] =
 {
-       0,    36,    37,     0,     1,     3,     4,     5,     6,     7,
+       0,    37,    38,     0,     1,     3,     4,     5,     6,     7,
        8,     9,    10,    11,    14,    15,    16,    18,    19,    20,
-      21,    22,    23,    25,    30,    38,    39,    41,    42,    43,
-      44,    47,    48,    50,    54,    56,    58,    59,    61,    63,
-      64,    65,    72,    30,    25,    26,    71,    71,    30,    71,
-      30,    30,    71,    25,    25,    25,    26,    29,    34,    75,
-      76,    30,     1,     1,    45,    45,    51,    53,    57,    68,
-      62,    68,    30,    73,    30,    30,    30,    30,    30,    75,
-      75,    31,    32,    73,    27,    33,    30,    30,     1,    12,
-      16,    17,    19,    20,    21,    22,    23,    25,    30,    40,
-      46,    66,    67,    69,    18,    19,    20,    21,    30,    40,
-      52,    67,    69,    39,    49,    72,    39,    50,    55,    61,
-      72,    30,    40,    69,    39,    50,    60,    61,    72,    30,
-      28,    75,    75,    76,    76,    30,    30,    24,    75,    75,
-      71,    70,    71,    75,    25,    76,     1,    13,    30,    71,
-      70,    25,    75,    30,    30,    14,    74,    30,    74,    74,
-      74,    76,    30,    74,    30,    74,    30,    75,    30,    30,
-      30,    74,    30,    30,    30
+      21,    22,    23,    26,    31,    39,    40,    42,    43,    44,
+      45,    51,    52,    54,    58,    60,    62,    63,    65,    67,
+      68,    69,    76,    31,    26,    27,    75,    75,    31,    75,
+      31,    31,    75,    26,    26,    26,    27,    30,    35,    79,
+      80,    31,     1,     1,    46,    46,    55,    57,    61,    72,
+      66,    72,    31,    77,    31,    31,    31,    31,    31,    79,
+      79,    32,    33,    77,    28,    34,    31,    31,     1,    12,
+      16,    17,    19,    20,    21,    22,    23,    24,    26,    31,
+      41,    47,    48,    70,    71,    73,    18,    19,    20,    21,
+      31,    41,    56,    71,    73,    40,    53,    76,    40,    54,
+      59,    65,    76,    31,    41,    73,    40,    54,    64,    65,
+      76,    31,    29,    79,    79,    80,    80,    31,    31,    25,
+      79,    79,    75,    74,    75,    79,    26,    80,    49,     1,
+      13,    31,    75,    74,    26,    79,    31,    31,    14,    78,
+      31,    78,    78,    78,    80,    26,    31,    31,    78,    31,
+      78,    31,    79,    31,    31,    31,    78,    34,    50,    31,
+      31,    31,    75
 };
 
-#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
-# define YYSIZE_T __SIZE_TYPE__
-#endif
-#if ! defined (YYSIZE_T) && defined (size_t)
-# define YYSIZE_T size_t
-#endif
-#if ! defined (YYSIZE_T)
-# if defined (__STDC__) || defined (__cplusplus)
-#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-#  define YYSIZE_T size_t
-# endif
-#endif
-#if ! defined (YYSIZE_T)
-# define YYSIZE_T unsigned int
-#endif
-
 #define yyerrok		(yyerrstatus = 0)
 #define yyclearin	(yychar = YYEMPTY)
 #define YYEMPTY		(-2)
@@ -709,8 +765,8 @@
       goto yybackup;						\
     }								\
   else								\
-    { 								\
-      yyerror ("syntax error: cannot back up");\
+    {								\
+      yyerror (YY_("syntax error: cannot back up")); \
       YYERROR;							\
     }								\
 while (0)
@@ -789,7 +845,7 @@
   if (yydebug)							\
     {								\
       YYFPRINTF (stderr, "%s ", Title);				\
-      yysymprint (stderr, 					\
+      yysymprint (stderr,					\
                   Type, Value);	\
       YYFPRINTF (stderr, "\n");					\
     }								\
@@ -837,13 +893,13 @@
 #endif
 {
   int yyi;
-  unsigned int yylno = yyrline[yyrule];
-  YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ",
+  unsigned long int yylno = yyrline[yyrule];
+  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ",
              yyrule - 1, yylno);
   /* Print the symbols being reduced, and their result.  */
   for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++)
-    YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]);
-  YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]);
+    YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+  YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]);
 }
 
 # define YY_REDUCE_PRINT(Rule)		\
@@ -872,7 +928,7 @@
    if the built-in stack extension method is used).
 
    Do not make this value too large; the results are undefined if
-   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
    evaluated with infinite-precision integer arithmetic.  */
 
 #ifndef YYMAXDEPTH
@@ -896,7 +952,7 @@
      const char *yystr;
 #   endif
 {
-  register const char *yys = yystr;
+  const char *yys = yystr;
 
   while (*yys++ != '\0')
     continue;
@@ -921,8 +977,8 @@
      const char *yysrc;
 #   endif
 {
-  register char *yyd = yydest;
-  register const char *yys = yysrc;
+  char *yyd = yydest;
+  const char *yys = yysrc;
 
   while ((*yyd++ = *yys++) != '\0')
     continue;
@@ -932,7 +988,55 @@
 #  endif
 # endif
 
-#endif /* !YYERROR_VERBOSE */
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+   quotes and backslashes, so that it's suitable for yyerror.  The
+   heuristic is that double-quoting is unnecessary unless the string
+   contains an apostrophe, a comma, or backslash (other than
+   backslash-backslash).  YYSTR is taken from yytname.  If YYRES is
+   null, do not copy; instead, return the length of what the result
+   would have been.  */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+  if (*yystr == '"')
+    {
+      size_t yyn = 0;
+      char const *yyp = yystr;
+
+      for (;;)
+	switch (*++yyp)
+	  {
+	  case '\'':
+	  case ',':
+	    goto do_not_strip_quotes;
+
+	  case '\\':
+	    if (*++yyp != '\\')
+	      goto do_not_strip_quotes;
+	    /* Fall through.  */
+	  default:
+	    if (yyres)
+	      yyres[yyn] = *yyp;
+	    yyn++;
+	    break;
+
+	  case '"':
+	    if (yyres)
+	      yyres[yyn] = '\0';
+	    return yyn;
+	  }
+    do_not_strip_quotes: ;
+    }
+
+  if (! yyres)
+    return yystrlen (yystr);
+
+  return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+#endif /* YYERROR_VERBOSE */
 
 
 
@@ -998,7 +1102,7 @@
 
   switch (yytype)
     {
-      case 48: /* choice_entry */
+      case 52: /* "choice_entry" */
 
         {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1008,7 +1112,7 @@
 };
 
         break;
-      case 54: /* if_entry */
+      case 58: /* "if_entry" */
 
         {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1018,7 +1122,7 @@
 };
 
         break;
-      case 59: /* menu_entry */
+      case 63: /* "menu_entry" */
 
         {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -1082,13 +1186,13 @@
 #else
 int
 yyparse ()
-
+    ;
 #endif
 #endif
 {
   
-  register int yystate;
-  register int yyn;
+  int yystate;
+  int yyn;
   int yyresult;
   /* Number of tokens to shift before error messages enabled.  */
   int yyerrstatus;
@@ -1106,12 +1210,12 @@
   /* The state stack.  */
   short int yyssa[YYINITDEPTH];
   short int *yyss = yyssa;
-  register short int *yyssp;
+  short int *yyssp;
 
   /* The semantic value stack.  */
   YYSTYPE yyvsa[YYINITDEPTH];
   YYSTYPE *yyvs = yyvsa;
-  register YYSTYPE *yyvsp;
+  YYSTYPE *yyvsp;
 
 
 
@@ -1143,9 +1247,6 @@
   yyssp = yyss;
   yyvsp = yyvs;
 
-
-  yyvsp[0] = yylval;
-
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1178,7 +1279,7 @@
 	   data in use in that stack, in bytes.  This used to be a
 	   conditional around just the two extra args, but that might
 	   be undefined if yyoverflow is a macro.  */
-	yyoverflow ("parser stack overflow",
+	yyoverflow (YY_("memory exhausted"),
 		    &yyss1, yysize * sizeof (*yyssp),
 		    &yyvs1, yysize * sizeof (*yyvsp),
 
@@ -1189,11 +1290,11 @@
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
-      goto yyoverflowlab;
+      goto yyexhaustedlab;
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-	goto yyoverflowlab;
+	goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
 	yystacksize = YYMAXDEPTH;
@@ -1203,7 +1304,7 @@
 	union yyalloc *yyptr =
 	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
 	if (! yyptr)
-	  goto yyoverflowlab;
+	  goto yyexhaustedlab;
 	YYSTACK_RELOCATE (yyss);
 	YYSTACK_RELOCATE (yyvs);
 
@@ -1403,7 +1504,7 @@
 ;}
     break;
 
-  case 37:
+  case 38:
 
     {
 	menu_set_type((yyvsp[-2].id)->stype);
@@ -1413,7 +1514,7 @@
 ;}
     break;
 
-  case 38:
+  case 39:
 
     {
 	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
@@ -1421,7 +1522,7 @@
 ;}
     break;
 
-  case 39:
+  case 40:
 
     {
 	menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
@@ -1433,7 +1534,7 @@
 ;}
     break;
 
-  case 40:
+  case 41:
 
     {
 	menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
@@ -1441,7 +1542,7 @@
 ;}
     break;
 
-  case 41:
+  case 42:
 
     {
 	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
@@ -1449,7 +1550,29 @@
 ;}
     break;
 
-  case 42:
+  case 45:
+
+    {
+	struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string)));
+	if (id && id->flags & TF_OPTION)
+		menu_add_option(id->token, (yyvsp[0].string));
+	else
+		zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string));
+	free((yyvsp[-1].string));
+;}
+    break;
+
+  case 46:
+
+    { (yyval.string) = NULL; ;}
+    break;
+
+  case 47:
+
+    { (yyval.string) = (yyvsp[0].string); ;}
+    break;
+
+  case 48:
 
     {
 	struct symbol *sym = sym_lookup(NULL, 0);
@@ -1460,14 +1583,14 @@
 ;}
     break;
 
-  case 43:
+  case 49:
 
     {
 	(yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 44:
+  case 50:
 
     {
 	if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
@@ -1477,7 +1600,7 @@
 ;}
     break;
 
-  case 52:
+  case 58:
 
     {
 	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
@@ -1485,7 +1608,7 @@
 ;}
     break;
 
-  case 53:
+  case 59:
 
     {
 	if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
@@ -1498,7 +1621,7 @@
 ;}
     break;
 
-  case 54:
+  case 60:
 
     {
 	current_entry->sym->flags |= SYMBOL_OPTIONAL;
@@ -1506,7 +1629,7 @@
 ;}
     break;
 
-  case 55:
+  case 61:
 
     {
 	if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
@@ -1518,7 +1641,7 @@
 ;}
     break;
 
-  case 58:
+  case 64:
 
     {
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
@@ -1528,7 +1651,7 @@
 ;}
     break;
 
-  case 59:
+  case 65:
 
     {
 	if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
@@ -1538,7 +1661,7 @@
 ;}
     break;
 
-  case 65:
+  case 71:
 
     {
 	menu_add_entry(NULL);
@@ -1547,14 +1670,14 @@
 ;}
     break;
 
-  case 66:
+  case 72:
 
     {
 	(yyval.menu) = menu_add_menu();
 ;}
     break;
 
-  case 67:
+  case 73:
 
     {
 	if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
@@ -1564,7 +1687,7 @@
 ;}
     break;
 
-  case 73:
+  case 79:
 
     {
 	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
@@ -1572,7 +1695,7 @@
 ;}
     break;
 
-  case 74:
+  case 80:
 
     {
 	menu_add_entry(NULL);
@@ -1581,14 +1704,14 @@
 ;}
     break;
 
-  case 75:
+  case 81:
 
     {
 	menu_end_entry();
 ;}
     break;
 
-  case 76:
+  case 82:
 
     {
 	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
@@ -1596,14 +1719,14 @@
 ;}
     break;
 
-  case 77:
+  case 83:
 
     {
 	current_entry->sym->help = (yyvsp[0].string);
 ;}
     break;
 
-  case 82:
+  case 88:
 
     {
 	menu_add_dep((yyvsp[-1].expr));
@@ -1611,7 +1734,7 @@
 ;}
     break;
 
-  case 83:
+  case 89:
 
     {
 	menu_add_dep((yyvsp[-1].expr));
@@ -1619,7 +1742,7 @@
 ;}
     break;
 
-  case 84:
+  case 90:
 
     {
 	menu_add_dep((yyvsp[-1].expr));
@@ -1627,87 +1750,88 @@
 ;}
     break;
 
-  case 86:
+  case 92:
 
     {
 	menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
 ;}
     break;
 
-  case 89:
-
-    { (yyval.id) = (yyvsp[-1].id); ;}
-    break;
-
-  case 90:
-
-    { (yyval.id) = (yyvsp[-1].id); ;}
-    break;
-
-  case 91:
-
-    { (yyval.id) = (yyvsp[-1].id); ;}
-    break;
-
-  case 94:
-
-    { (yyval.expr) = NULL; ;}
-    break;
-
   case 95:
 
-    { (yyval.expr) = (yyvsp[0].expr); ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
   case 96:
 
-    { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
   case 97:
 
-    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
-    break;
-
-  case 98:
-
-    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
-    break;
-
-  case 99:
-
-    { (yyval.expr) = (yyvsp[-1].expr); ;}
+    { (yyval.id) = (yyvsp[-1].id); ;}
     break;
 
   case 100:
 
-    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;}
+    { (yyval.expr) = NULL; ;}
     break;
 
   case 101:
 
-    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
+    { (yyval.expr) = (yyvsp[0].expr); ;}
     break;
 
   case 102:
 
-    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
+    { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); ;}
     break;
 
   case 103:
 
-    { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;}
+    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
     break;
 
   case 104:
 
+    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); ;}
+    break;
+
+  case 105:
+
+    { (yyval.expr) = (yyvsp[-1].expr); ;}
+    break;
+
+  case 106:
+
+    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); ;}
+    break;
+
+  case 107:
+
+    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
+    break;
+
+  case 108:
+
+    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;}
+    break;
+
+  case 109:
+
+    { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); ;}
+    break;
+
+  case 110:
+
     { (yyval.symbol) = sym_lookup((yyvsp[0].string), 1); free((yyvsp[0].string)); ;}
     break;
 
 
+      default: break;
     }
 
-/* Line 1037 of yacc.c.  */
+/* Line 1126 of yacc.c.  */
 
 
   yyvsp -= yylen;
@@ -1747,12 +1871,36 @@
 
       if (YYPACT_NINF < yyn && yyn < YYLAST)
 	{
-	  YYSIZE_T yysize = 0;
 	  int yytype = YYTRANSLATE (yychar);
-	  const char* yyprefix;
-	  char *yymsg;
+	  YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+	  YYSIZE_T yysize = yysize0;
+	  YYSIZE_T yysize1;
+	  int yysize_overflow = 0;
+	  char *yymsg = 0;
+#	  define YYERROR_VERBOSE_ARGS_MAXIMUM 5
+	  char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
 	  int yyx;
 
+#if 0
+	  /* This is so xgettext sees the translatable formats that are
+	     constructed on the fly.  */
+	  YY_("syntax error, unexpected %s");
+	  YY_("syntax error, unexpected %s, expecting %s");
+	  YY_("syntax error, unexpected %s, expecting %s or %s");
+	  YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+	  YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+#endif
+	  char *yyfmt;
+	  char const *yyf;
+	  static char const yyunexpected[] = "syntax error, unexpected %s";
+	  static char const yyexpecting[] = ", expecting %s";
+	  static char const yyor[] = " or %s";
+	  char yyformat[sizeof yyunexpected
+			+ sizeof yyexpecting - 1
+			+ ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+			   * (sizeof yyor - 1))];
+	  char const *yyprefix = yyexpecting;
+
 	  /* Start YYX at -YYN if negative to avoid negative indexes in
 	     YYCHECK.  */
 	  int yyxbegin = yyn < 0 ? -yyn : 0;
@@ -1760,48 +1908,68 @@
 	  /* Stay within bounds of both yycheck and yytname.  */
 	  int yychecklim = YYLAST - yyn;
 	  int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
-	  int yycount = 0;
+	  int yycount = 1;
 
-	  yyprefix = ", expecting ";
+	  yyarg[0] = yytname[yytype];
+	  yyfmt = yystpcpy (yyformat, yyunexpected);
+
 	  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
 	    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
 	      {
-		yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]);
-		yycount += 1;
-		if (yycount == 5)
+		if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
 		  {
-		    yysize = 0;
+		    yycount = 1;
+		    yysize = yysize0;
+		    yyformat[sizeof yyunexpected - 1] = '\0';
 		    break;
 		  }
+		yyarg[yycount++] = yytname[yyx];
+		yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+		yysize_overflow |= yysize1 < yysize;
+		yysize = yysize1;
+		yyfmt = yystpcpy (yyfmt, yyprefix);
+		yyprefix = yyor;
 	      }
-	  yysize += (sizeof ("syntax error, unexpected ")
-		     + yystrlen (yytname[yytype]));
-	  yymsg = (char *) YYSTACK_ALLOC (yysize);
-	  if (yymsg != 0)
-	    {
-	      char *yyp = yystpcpy (yymsg, "syntax error, unexpected ");
-	      yyp = yystpcpy (yyp, yytname[yytype]);
 
-	      if (yycount < 5)
+	  yyf = YY_(yyformat);
+	  yysize1 = yysize + yystrlen (yyf);
+	  yysize_overflow |= yysize1 < yysize;
+	  yysize = yysize1;
+
+	  if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM)
+	    yymsg = (char *) YYSTACK_ALLOC (yysize);
+	  if (yymsg)
+	    {
+	      /* Avoid sprintf, as that infringes on the user's name space.
+		 Don't have undefined behavior even if the translation
+		 produced a string with the wrong number of "%s"s.  */
+	      char *yyp = yymsg;
+	      int yyi = 0;
+	      while ((*yyp = *yyf))
 		{
-		  yyprefix = ", expecting ";
-		  for (yyx = yyxbegin; yyx < yyxend; ++yyx)
-		    if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
-		      {
-			yyp = yystpcpy (yyp, yyprefix);
-			yyp = yystpcpy (yyp, yytname[yyx]);
-			yyprefix = " or ";
-		      }
+		  if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+		    {
+		      yyp += yytnamerr (yyp, yyarg[yyi++]);
+		      yyf += 2;
+		    }
+		  else
+		    {
+		      yyp++;
+		      yyf++;
+		    }
 		}
 	      yyerror (yymsg);
 	      YYSTACK_FREE (yymsg);
 	    }
 	  else
-	    yyerror ("syntax error; also virtual memory exhausted");
+	    {
+	      yyerror (YY_("syntax error"));
+	      goto yyexhaustedlab;
+	    }
 	}
       else
 #endif /* YYERROR_VERBOSE */
-	yyerror ("syntax error");
+	yyerror (YY_("syntax error"));
     }
 
 
@@ -1813,18 +1981,9 @@
 
       if (yychar <= YYEOF)
         {
-          /* If at end of input, pop the error token,
-	     then the rest of the stack, then return failure.  */
+	  /* Return failure if at end of input.  */
 	  if (yychar == YYEOF)
-	     for (;;)
-	       {
-
-		 YYPOPSTACK;
-		 if (yyssp == yyss)
-		   YYABORT;
-		 yydestruct ("Error: popping",
-                             yystos[*yyssp], yyvsp);
-	       }
+	    YYABORT;
         }
       else
 	{
@@ -1843,12 +2002,11 @@
 `---------------------------------------------------*/
 yyerrorlab:
 
-#ifdef __GNUC__
-  /* Pacify GCC when the user code never invokes YYERROR and the label
-     yyerrorlab therefore never appears in user code.  */
+  /* Pacify compilers like GCC when the user code never invokes
+     YYERROR and the label yyerrorlab therefore never appears in user
+     code.  */
   if (0)
      goto yyerrorlab;
-#endif
 
 yyvsp -= yylen;
   yyssp -= yylen;
@@ -1911,23 +2069,29 @@
 | yyabortlab -- YYABORT comes here.  |
 `-----------------------------------*/
 yyabortlab:
-  yydestruct ("Error: discarding lookahead",
-              yytoken, &yylval);
-  yychar = YYEMPTY;
   yyresult = 1;
   goto yyreturn;
 
 #ifndef yyoverflow
-/*----------------------------------------------.
-| yyoverflowlab -- parser overflow comes here.  |
-`----------------------------------------------*/
-yyoverflowlab:
-  yyerror ("parser stack overflow");
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here.  |
+`-------------------------------------------------*/
+yyexhaustedlab:
+  yyerror (YY_("memory exhausted"));
   yyresult = 2;
   /* Fall through.  */
 #endif
 
 yyreturn:
+  if (yychar != YYEOF && yychar != YYEMPTY)
+     yydestruct ("Cleanup: discarding lookahead",
+		 yytoken, &yylval);
+  while (yyssp != yyss)
+    {
+      yydestruct ("Cleanup: popping",
+		  yystos[*yyssp], yyvsp);
+      YYPOPSTACK;
+    }
 #ifndef yyoverflow
   if (yyss != yyssa)
     YYSTACK_FREE (yyss);
@@ -1948,7 +2112,9 @@
 
 	sym_init();
 	menu_init();
-	modules_sym = sym_lookup("MODULES", 0);
+	modules_sym = sym_lookup(NULL, 0);
+	modules_sym->type = S_BOOLEAN;
+	modules_sym->flags |= SYMBOL_AUTO;
 	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
 #if YYDEBUG
@@ -1958,6 +2124,12 @@
 	zconfparse();
 	if (zconfnerrs)
 		exit(1);
+	if (!modules_sym->prop) {
+		struct property *prop;
+
+		prop = prop_alloc(P_DEFAULT, modules_sym);
+		prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
+	}
 	menu_finalize(&rootmenu);
 	for_all_symbols(i, sym) {
 		sym_check_deps(sym);
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 1f61fba..ab44feb 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -71,6 +71,7 @@
 %token <id>T_DEFAULT
 %token <id>T_SELECT
 %token <id>T_RANGE
+%token <id>T_OPTION
 %token <id>T_ON
 %token <string> T_WORD
 %token <string> T_WORD_QUOTE
@@ -91,6 +92,7 @@
 %type <id> end
 %type <id> option_name
 %type <menu> if_entry menu_entry choice_entry
+%type <string> symbol_option_arg
 
 %destructor {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
@@ -173,6 +175,7 @@
 config_option_list:
 	  /* empty */
 	| config_option_list config_option
+	| config_option_list symbol_option
 	| config_option_list depends
 	| config_option_list help
 	| config_option_list option_error
@@ -215,6 +218,26 @@
 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
 };
 
+symbol_option: T_OPTION symbol_option_list T_EOL
+;
+
+symbol_option_list:
+	  /* empty */
+	| symbol_option_list T_WORD symbol_option_arg
+{
+	struct kconf_id *id = kconf_id_lookup($2, strlen($2));
+	if (id && id->flags & TF_OPTION)
+		menu_add_option(id->token, $3);
+	else
+		zconfprint("warning: ignoring unknown option %s", $2);
+	free($2);
+};
+
+symbol_option_arg:
+	  /* empty */		{ $$ = NULL; }
+	| T_EQUAL prompt	{ $$ = $2; }
+;
+
 /* choice entry */
 
 choice: T_CHOICE T_EOL
@@ -458,7 +481,9 @@
 
 	sym_init();
 	menu_init();
-	modules_sym = sym_lookup("MODULES", 0);
+	modules_sym = sym_lookup(NULL, 0);
+	modules_sym->type = S_BOOLEAN;
+	modules_sym->flags |= SYMBOL_AUTO;
 	rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL);
 
 #if YYDEBUG
@@ -468,6 +493,12 @@
 	zconfparse();
 	if (zconfnerrs)
 		exit(1);
+	if (!modules_sym->prop) {
+		struct property *prop;
+
+		prop = prop_alloc(P_DEFAULT, modules_sym);
+		prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
+	}
 	menu_finalize(&rootmenu);
 	for_all_symbols(i, sym) {
 		sym_check_deps(sym);
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 99fe4b7..00e2129 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -253,6 +253,7 @@
 # 3 - scanning prototype.
 # 4 - documentation block
 my $state;
+my $in_doc_sect;
 
 #declaration types: can be
 # 'function', 'struct', 'union', 'enum', 'typedef'
@@ -1064,7 +1065,7 @@
     }
     print "};\n.br\n";
 
-    print ".SH Arguments\n";
+    print ".SH Members\n";
     foreach $parameter (@{$args{'parameterlist'}}) {
 	($parameter =~ /^#/) && next;
 
@@ -1673,6 +1674,9 @@
 # replace <, >, and &
 sub xml_escape($) {
 	my $text = shift;
+	if (($output_mode eq "text") || ($output_mode eq "man")) {
+		return $text;
+	}
 	$text =~ s/\&/\\\\\\amp;/g;
 	$text =~ s/\</\\\\\\lt;/g;
 	$text =~ s/\>/\\\\\\gt;/g;
@@ -1706,6 +1710,7 @@
 	if ($state == 0) {
 	    if (/$doc_start/o) {
 		$state = 1;		# next line is always the function name
+		$in_doc_sect = 0;
 	    }
 	} elsif ($state == 1) {	# this line is the function name (always)
 	    if (/$doc_block/o) {
@@ -1756,12 +1761,20 @@
 		$newcontents = $2;
 
 		if ($contents ne "") {
+		    if (!$in_doc_sect && $verbose) {
+			print STDERR "Warning(${file}:$.): contents before sections\n";
+			++$warnings;
+		    }
 		    dump_section($section, xml_escape($contents));
 		    $section = $section_default;
 		}
 
+		$in_doc_sect = 1;
 		$contents = $newcontents;
 		if ($contents ne "") {
+		    if (substr($contents, 0, 1) eq " ") {
+			$contents = substr($contents, 1);
+		    }
 		    $contents .= "\n";
 		}
 		$section = $newsection;
@@ -1776,7 +1789,7 @@
 		$prototype = "";
 		$state = 3;
 		$brcount = 0;
-#	    print STDERR "end of doc comment, looking for prototype\n";
+#		print STDERR "end of doc comment, looking for prototype\n";
 	    } elsif (/$doc_content/) {
 		# miguel-style comment kludge, look for blank lines after
 		# @parameter line to signify start of description
@@ -1793,7 +1806,7 @@
 		print STDERR "Warning(${file}:$.): bad line: $_";
 		++$warnings;
 	    }
-	} elsif ($state == 3) {	# scanning for function { (end of prototype)
+	} elsif ($state == 3) {	# scanning for function '{' (end of prototype)
 	    if ($decl_type eq 'function') {
 	        process_state3_function($_, $file);
 	    } else {
diff --git a/scripts/mod/mk_elfconfig.c b/scripts/mod/mk_elfconfig.c
index 3c92c83..725d61c 100644
--- a/scripts/mod/mk_elfconfig.c
+++ b/scripts/mod/mk_elfconfig.c
@@ -28,7 +28,7 @@
 		printf("#define KERNEL_ELFCLASS ELFCLASS64\n");
 		break;
 	default:
-		abort();
+		exit(1);
 	}
 	switch (ei[EI_DATA]) {
 	case ELFDATA2LSB:
@@ -38,7 +38,7 @@
 		printf("#define KERNEL_ELFDATA ELFDATA2MSB\n");
 		break;
 	default:
-		abort();
+		exit(1);
 	}
 
 	if (sizeof(unsigned long) == 4) {
@@ -53,7 +53,7 @@
 	else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
 		printf("#define HOST_ELFDATA ELFDATA2LSB\n");
 	else
-		abort();
+		exit(1);
 
 	if ((strcmp(argv[1], "v850") == 0) || (strcmp(argv[1], "h8300") == 0))
 		printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index d0f86ed..0dd1617 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -13,6 +13,7 @@
 
 #include <ctype.h>
 #include "modpost.h"
+#include "../../include/linux/license.h"
 
 /* Are we using CONFIG_MODVERSIONS? */
 int modversions = 0;
@@ -22,6 +23,8 @@
 static int all_versions = 0;
 /* If we are modposting external module set to 1 */
 static int external_module = 0;
+/* How a symbol is exported */
+enum export {export_plain, export_gpl, export_gpl_future, export_unknown};
 
 void fatal(const char *fmt, ...)
 {
@@ -97,6 +100,7 @@
 
 	/* add to list */
 	mod->name = p;
+	mod->gpl_compatible = -1;
 	mod->next = modules;
 	modules = mod;
 
@@ -118,6 +122,7 @@
 	unsigned int kernel:1;     /* 1 if symbol is from kernel
 				    *  (only for external modules) **/
 	unsigned int preloaded:1;  /* 1 if symbol from Module.symvers */
+	enum export  export;       /* Type of export */
 	char name[0];
 };
 
@@ -153,7 +158,8 @@
 }
 
 /* For the hash of exported symbols */
-static struct symbol *new_symbol(const char *name, struct module *module)
+static struct symbol *new_symbol(const char *name, struct module *module,
+				 enum export export)
 {
 	unsigned int hash;
 	struct symbol *new;
@@ -161,6 +167,7 @@
 	hash = tdb_hash(name) % SYMBOL_HASH_SIZE;
 	new = symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]);
 	new->module = module;
+	new->export = export;
 	return new;
 }
 
@@ -179,16 +186,55 @@
 	return NULL;
 }
 
+static struct {
+	const char *str;
+	enum export export;
+} export_list[] = {
+	{ .str = "EXPORT_SYMBOL",            .export = export_plain },
+	{ .str = "EXPORT_SYMBOL_GPL",        .export = export_gpl },
+	{ .str = "EXPORT_SYMBOL_GPL_FUTURE", .export = export_gpl_future },
+	{ .str = "(unknown)",                .export = export_unknown },
+};
+
+
+static const char *export_str(enum export ex)
+{
+	return export_list[ex].str;
+}
+
+static enum export export_no(const char * s)
+{
+	int i;
+	for (i = 0; export_list[i].export != export_unknown; i++) {
+		if (strcmp(export_list[i].str, s) == 0)
+			return export_list[i].export;
+	}
+	return export_unknown;
+}
+
+static enum export export_from_sec(struct elf_info *elf, Elf_Section sec)
+{
+	if (sec == elf->export_sec)
+		return export_plain;
+	else if (sec == elf->export_gpl_sec)
+		return export_gpl;
+	else if (sec == elf->export_gpl_future_sec)
+		return export_gpl_future;
+	else
+		return export_unknown;
+}
+
 /**
  * Add an exported symbol - it may have already been added without a
  * CRC, in this case just update the CRC
  **/
-static struct symbol *sym_add_exported(const char *name, struct module *mod)
+static struct symbol *sym_add_exported(const char *name, struct module *mod,
+				       enum export export)
 {
 	struct symbol *s = find_symbol(name);
 
 	if (!s) {
-		s = new_symbol(name, mod);
+		s = new_symbol(name, mod, export);
 	} else {
 		if (!s->preloaded) {
 			warn("%s: '%s' exported twice. Previous export "
@@ -200,16 +246,17 @@
 	s->preloaded = 0;
 	s->vmlinux   = is_vmlinux(mod->name);
 	s->kernel    = 0;
+	s->export    = export;
 	return s;
 }
 
 static void sym_update_crc(const char *name, struct module *mod,
-			   unsigned int crc)
+			   unsigned int crc, enum export export)
 {
 	struct symbol *s = find_symbol(name);
 
 	if (!s)
-		s = new_symbol(name, mod);
+		s = new_symbol(name, mod, export);
 	s->crc = crc;
 	s->crc_valid = 1;
 }
@@ -283,7 +330,7 @@
 	hdr = grab_file(filename, &info->size);
 	if (!hdr) {
 		perror(filename);
-		abort();
+		exit(1);
 	}
 	info->hdr = hdr;
 	if (info->size < sizeof(*hdr))
@@ -309,13 +356,21 @@
 	for (i = 1; i < hdr->e_shnum; i++) {
 		const char *secstrings
 			= (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+		const char *secname;
 
 		if (sechdrs[i].sh_offset > info->size)
 			goto truncated;
-		if (strcmp(secstrings+sechdrs[i].sh_name, ".modinfo") == 0) {
+		secname = secstrings + sechdrs[i].sh_name;
+		if (strcmp(secname, ".modinfo") == 0) {
 			info->modinfo = (void *)hdr + sechdrs[i].sh_offset;
 			info->modinfo_len = sechdrs[i].sh_size;
-		}
+		} else if (strcmp(secname, "__ksymtab") == 0)
+			info->export_sec = i;
+		else if (strcmp(secname, "__ksymtab_gpl") == 0)
+			info->export_gpl_sec = i;
+		else if (strcmp(secname, "__ksymtab_gpl_future") == 0)
+			info->export_gpl_future_sec = i;
+
 		if (sechdrs[i].sh_type != SHT_SYMTAB)
 			continue;
 
@@ -353,6 +408,7 @@
 			       Elf_Sym *sym, const char *symname)
 {
 	unsigned int crc;
+	enum export export = export_from_sec(info, sym->st_shndx);
 
 	switch (sym->st_shndx) {
 	case SHN_COMMON:
@@ -362,7 +418,8 @@
 		/* CRC'd symbol */
 		if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
 			crc = (unsigned int) sym->st_value;
-			sym_update_crc(symname + strlen(CRC_PFX), mod, crc);
+			sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
+					export);
 		}
 		break;
 	case SHN_UNDEF:
@@ -406,7 +463,8 @@
 	default:
 		/* All exported symbols */
 		if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
-			sym_add_exported(symname + strlen(KSYMTAB_PFX), mod);
+			sym_add_exported(symname + strlen(KSYMTAB_PFX), mod,
+					export);
 		}
 		if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0)
 			mod->has_init = 1;
@@ -437,13 +495,18 @@
 	return string;
 }
 
-static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
-			 const char *tag)
+static char *get_next_modinfo(void *modinfo, unsigned long modinfo_len,
+			      const char *tag, char *info)
 {
 	char *p;
 	unsigned int taglen = strlen(tag);
 	unsigned long size = modinfo_len;
 
+	if (info) {
+		size -= info - (char *)modinfo;
+		modinfo = next_string(info, &size);
+	}
+
 	for (p = modinfo; p; p = next_string(p, &size)) {
 		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
 			return p + taglen + 1;
@@ -451,6 +514,13 @@
 	return NULL;
 }
 
+static char *get_modinfo(void *modinfo, unsigned long modinfo_len,
+			 const char *tag)
+
+{
+	return get_next_modinfo(modinfo, modinfo_len, tag, NULL);
+}
+
 /**
  * Test if string s ends in string sub
  * return 0 if match
@@ -821,6 +891,10 @@
 		".pci_fixup_final",
 		".pdr",
 		"__param",
+		"__ex_table",
+		".fixup",
+		".smp_locks",
+		".plt",  /* seen on ARCH=um build on x86_64. Harmless */
 		NULL
 	};
 	/* Start of section names */
@@ -846,6 +920,8 @@
 	for (s = namelist3; *s; s++)
 		if (strstr(name, *s) != NULL)
 			return 1;
+	if (strrcmp(name, ".init") == 0)
+		return 1;
 	return 0;
 }
 
@@ -892,6 +968,10 @@
 		".exitcall.exit",
 		".eh_frame",
 		".stab",
+		"__ex_table",
+		".fixup",
+		".smp_locks",
+		".plt",  /* seen on ARCH=um build on x86_64. Harmless */
 		NULL
 	};
 	/* Start of section names */
@@ -921,6 +1001,7 @@
 {
 	const char *symname;
 	char *version;
+	char *license;
 	struct module *mod;
 	struct elf_info info = { };
 	Elf_Sym *sym;
@@ -936,6 +1017,18 @@
 		mod->skip = 1;
 	}
 
+	license = get_modinfo(info.modinfo, info.modinfo_len, "license");
+	while (license) {
+		if (license_is_gpl_compatible(license))
+			mod->gpl_compatible = 1;
+		else {
+			mod->gpl_compatible = 0;
+			break;
+		}
+		license = get_next_modinfo(info.modinfo, info.modinfo_len,
+					   "license", license);
+	}
+
 	for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
 		symname = info.strtab + sym->st_name;
 
@@ -992,6 +1085,41 @@
 	buf->pos += len;
 }
 
+void check_license(struct module *mod)
+{
+	struct symbol *s, *exp;
+
+	for (s = mod->unres; s; s = s->next) {
+		const char *basename;
+		if (mod->gpl_compatible == 1) {
+			/* GPL-compatible modules may use all symbols */
+			continue;
+		}
+		exp = find_symbol(s->name);
+		if (!exp || exp->module == mod)
+			continue;
+		basename = strrchr(mod->name, '/');
+		if (basename)
+			basename++;
+		switch (exp->export) {
+			case export_gpl:
+				fatal("modpost: GPL-incompatible module %s "
+				      "uses GPL-only symbol '%s'\n",
+				 basename ? basename : mod->name,
+				exp->name);
+				break;
+			case export_gpl_future:
+				warn("modpost: GPL-incompatible module %s "
+				      "uses future GPL-only symbol '%s'\n",
+				      basename ? basename : mod->name,
+				      exp->name);
+				break;
+			case export_plain: /* ignore */ break;
+			case export_unknown: /* ignore */ break;
+		}
+        }
+}
+
 /**
  * Header for the generated file
  **/
@@ -1142,6 +1270,9 @@
 	fclose(file);
 }
 
+/* parse Module.symvers file. line format:
+ * 0x12345678<tab>symbol<tab>module[<tab>export]
+ **/
 static void read_dump(const char *fname, unsigned int kernel)
 {
 	unsigned long size, pos = 0;
@@ -1153,7 +1284,7 @@
 		return;
 
 	while ((line = get_next_line(&pos, file, size))) {
-		char *symname, *modname, *d;
+		char *symname, *modname, *d, *export;
 		unsigned int crc;
 		struct module *mod;
 		struct symbol *s;
@@ -1164,8 +1295,9 @@
 		if (!(modname = strchr(symname, '\t')))
 			goto fail;
 		*modname++ = '\0';
-		if (strchr(modname, '\t'))
-			goto fail;
+		if ((export = strchr(modname, '\t')) != NULL)
+			*export++ = '\0';
+
 		crc = strtoul(line, &d, 16);
 		if (*symname == '\0' || *modname == '\0' || *d != '\0')
 			goto fail;
@@ -1177,10 +1309,10 @@
 			mod = new_module(NOFAIL(strdup(modname)));
 			mod->skip = 1;
 		}
-		s = sym_add_exported(symname, mod);
+		s = sym_add_exported(symname, mod, export_no(export));
 		s->kernel    = kernel;
 		s->preloaded = 1;
-		sym_update_crc(symname, mod, crc);
+		sym_update_crc(symname, mod, crc, export_no(export));
 	}
 	return;
 fail:
@@ -1210,9 +1342,10 @@
 		symbol = symbolhash[n];
 		while (symbol) {
 			if (dump_sym(symbol))
-				buf_printf(&buf, "0x%08x\t%s\t%s\n",
+				buf_printf(&buf, "0x%08x\t%s\t%s\t%s\n",
 					symbol->crc, symbol->name,
-					symbol->module->name);
+					symbol->module->name,
+					export_str(symbol->export));
 			symbol = symbol->next;
 		}
 	}
@@ -1263,6 +1396,12 @@
 	for (mod = modules; mod; mod = mod->next) {
 		if (mod->skip)
 			continue;
+		check_license(mod);
+	}
+
+	for (mod = modules; mod; mod = mod->next) {
+		if (mod->skip)
+			continue;
 
 		buf.pos = 0;
 
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 861d866..2b00c60 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -100,6 +100,7 @@
 struct module {
 	struct module *next;
 	const char *name;
+	int gpl_compatible;
 	struct symbol *unres;
 	int seen;
 	int skip;
@@ -115,6 +116,9 @@
 	Elf_Shdr     *sechdrs;
 	Elf_Sym      *symtab_start;
 	Elf_Sym      *symtab_stop;
+	Elf_Section  export_sec;
+	Elf_Section  export_gpl_sec;
+	Elf_Section  export_gpl_future_sec;
 	const char   *strtab;
 	char	     *modinfo;
 	unsigned int modinfo_len;
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index 0b10387..df89284 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -73,8 +73,13 @@
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
 echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
 echo "%else"
+echo "%ifarch ppc64"
+echo "cp vmlinux arch/powerpc/boot"
+echo "cp arch/powerpc/boot/"'$KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
+echo "%else"
 echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/vmlinuz-$KERNELRELEASE"
 echo "%endif"
+echo "%endif"
 
 echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
 
diff --git a/scripts/rt-tester/check-all.sh b/scripts/rt-tester/check-all.sh
new file mode 100644
index 0000000..43098af
--- /dev/null
+++ b/scripts/rt-tester/check-all.sh
@@ -0,0 +1,22 @@
+
+
+function testit ()
+{
+ printf "%-30s: " $1
+ ./rt-tester.py $1 | grep Pass
+}
+
+testit t2-l1-2rt-sameprio.tst
+testit t2-l1-pi.tst
+testit t2-l1-signal.tst
+#testit t2-l2-2rt-deadlock.tst
+testit t3-l1-pi-1rt.tst
+testit t3-l1-pi-2rt.tst
+testit t3-l1-pi-3rt.tst
+testit t3-l1-pi-signal.tst
+testit t3-l1-pi-steal.tst
+testit t3-l2-pi.tst
+testit t4-l2-pi-deboost.tst
+testit t5-l4-pi-boost-deboost.tst
+testit t5-l4-pi-boost-deboost-setsched.tst
+
diff --git a/scripts/rt-tester/rt-tester.py b/scripts/rt-tester/rt-tester.py
new file mode 100644
index 0000000..4c79660
--- /dev/null
+++ b/scripts/rt-tester/rt-tester.py
@@ -0,0 +1,222 @@
+#!/usr/bin/env python
+#
+# rt-mutex tester
+#
+# (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+import os
+import sys
+import getopt
+import shutil
+import string
+
+# Globals
+quiet = 0
+test = 0
+comments = 0
+
+sysfsprefix = "/sys/devices/system/rttest/rttest"
+statusfile = "/status"
+commandfile = "/command"
+
+# Command opcodes
+cmd_opcodes = {
+    "schedother"    : "1",
+    "schedfifo"     : "2",
+    "lock"          : "3",
+    "locknowait"    : "4",
+    "lockint"       : "5",
+    "lockintnowait" : "6",
+    "lockcont"      : "7",
+    "unlock"        : "8",
+    "lockbkl"       : "9",
+    "unlockbkl"     : "10",
+    "signal"        : "11",
+    "resetevent"    : "98",
+    "reset"         : "99",
+    }
+
+test_opcodes = {
+    "prioeq"        : ["P" , "eq" , None],
+    "priolt"        : ["P" , "lt" , None],
+    "priogt"        : ["P" , "gt" , None],
+    "nprioeq"       : ["N" , "eq" , None],
+    "npriolt"       : ["N" , "lt" , None],
+    "npriogt"       : ["N" , "gt" , None],
+    "unlocked"      : ["M" , "eq" , 0],
+    "trylock"       : ["M" , "eq" , 1],
+    "blocked"       : ["M" , "eq" , 2],
+    "blockedwake"   : ["M" , "eq" , 3],
+    "locked"        : ["M" , "eq" , 4],
+    "opcodeeq"      : ["O" , "eq" , None],
+    "opcodelt"      : ["O" , "lt" , None],
+    "opcodegt"      : ["O" , "gt" , None],
+    "eventeq"       : ["E" , "eq" , None],
+    "eventlt"       : ["E" , "lt" , None],
+    "eventgt"       : ["E" , "gt" , None],
+    }
+
+# Print usage information
+def usage():
+    print "rt-tester.py <-c -h -q -t> <testfile>"
+    print " -c    display comments after first command"
+    print " -h    help"
+    print " -q    quiet mode"
+    print " -t    test mode (syntax check)"
+    print " testfile: read test specification from testfile"
+    print " otherwise from stdin"
+    return
+
+# Print progress when not in quiet mode
+def progress(str):
+    if not quiet:
+        print str
+
+# Analyse a status value
+def analyse(val, top, arg):
+
+    intval = int(val)
+
+    if top[0] == "M":
+        intval = intval / (10 ** int(arg))
+	intval = intval % 10
+        argval = top[2]
+    elif top[0] == "O":
+        argval = int(cmd_opcodes.get(arg, arg))
+    else:
+        argval = int(arg)
+
+    # progress("%d %s %d" %(intval, top[1], argval))
+
+    if top[1] == "eq" and intval == argval:
+	return 1
+    if top[1] == "lt" and intval < argval:
+        return 1
+    if top[1] == "gt" and intval > argval:
+	return 1
+    return 0
+
+# Parse the commandline
+try:
+    (options, arguments) = getopt.getopt(sys.argv[1:],'chqt')
+except getopt.GetoptError, ex:
+    usage()
+    sys.exit(1)
+
+# Parse commandline options
+for option, value in options:
+    if option == "-c":
+        comments = 1
+    elif option == "-q":
+        quiet = 1
+    elif option == "-t":
+        test = 1
+    elif option == '-h':
+        usage()
+        sys.exit(0)
+
+# Select the input source
+if arguments:
+    try:
+        fd = open(arguments[0])
+    except Exception,ex:
+        sys.stderr.write("File not found %s\n" %(arguments[0]))
+        sys.exit(1)
+else:
+    fd = sys.stdin
+
+linenr = 0
+
+# Read the test patterns
+while 1:
+
+    linenr = linenr + 1
+    line = fd.readline()
+    if not len(line):
+        break
+
+    line = line.strip()
+    parts = line.split(":")
+
+    if not parts or len(parts) < 1:
+        continue
+
+    if len(parts[0]) == 0:
+        continue
+
+    if parts[0].startswith("#"):
+	if comments > 1:
+	    progress(line)
+	continue
+
+    if comments == 1:
+	comments = 2
+
+    progress(line)
+
+    cmd = parts[0].strip().lower()
+    opc = parts[1].strip().lower()
+    tid = parts[2].strip()
+    dat = parts[3].strip()
+
+    try:
+        # Test or wait for a status value
+        if cmd == "t" or cmd == "w":
+            testop = test_opcodes[opc]
+
+            fname = "%s%s%s" %(sysfsprefix, tid, statusfile)
+            if test:
+		print fname
+                continue
+
+            while 1:
+                query = 1
+                fsta = open(fname, 'r')
+                status = fsta.readline().strip()
+                fsta.close()
+                stat = status.split(",")
+                for s in stat:
+		    s = s.strip()
+                    if s.startswith(testop[0]):
+                        # Seperate status value
+                        val = s[2:].strip()
+                        query = analyse(val, testop, dat)
+                        break
+                if query or cmd == "t":
+                    break
+
+            progress("   " + status)
+
+            if not query:
+                sys.stderr.write("Test failed in line %d\n" %(linenr))
+		sys.exit(1)
+
+        # Issue a command to the tester
+        elif cmd == "c":
+            cmdnr = cmd_opcodes[opc]
+            # Build command string and sys filename
+            cmdstr = "%s:%s" %(cmdnr, dat)
+            fname = "%s%s%s" %(sysfsprefix, tid, commandfile)
+            if test:
+		print fname
+                continue
+            fcmd = open(fname, 'w')
+            fcmd.write(cmdstr)
+            fcmd.close()
+
+    except Exception,ex:
+    	sys.stderr.write(str(ex))
+        sys.stderr.write("\nSyntax error in line %d\n" %(linenr))
+        if not test:
+            fd.close()
+            sys.exit(1)
+
+# Normal exit pass
+print "Pass"
+sys.exit(0)
+
+
diff --git a/scripts/rt-tester/t2-l1-2rt-sameprio.tst b/scripts/rt-tester/t2-l1-2rt-sameprio.tst
new file mode 100644
index 0000000..8821f27
--- /dev/null
+++ b/scripts/rt-tester/t2-l1-2rt-sameprio.tst
@@ -0,0 +1,99 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	0
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 2 threads 1 lock
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedfifo:		0: 	80
+C: schedfifo:		1: 	80
+
+# T0 lock L0
+C: locknowait:		0: 	0
+C: locknowait:		1:	0
+W: locked:		0: 	0
+W: blocked:		1: 	0
+T: prioeq:		0: 	80
+
+# T0 unlock L0
+C: unlock:		0: 	0
+W: locked:		1: 	0
+
+# Verify T0
+W: unlocked:		0: 	0
+T: prioeq:		0: 	80
+
+# Unlock
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
+
+# T1,T0 lock L0
+C: locknowait:		1: 	0
+C: locknowait:		0:	0
+W: locked:		1: 	0
+W: blocked:		0: 	0
+T: prioeq:		1: 	80
+
+# T1 unlock L0
+C: unlock:		1: 	0
+W: locked:		0: 	0
+
+# Verify T1
+W: unlocked:		1: 	0
+T: prioeq:		1: 	80
+
+# Unlock and exit
+C: unlock:		0: 	0
+W: unlocked:		0: 	0
+
diff --git a/scripts/rt-tester/t2-l1-pi.tst b/scripts/rt-tester/t2-l1-pi.tst
new file mode 100644
index 0000000..cde1f18
--- /dev/null
+++ b/scripts/rt-tester/t2-l1-pi.tst
@@ -0,0 +1,82 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	0
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 2 threads 1 lock with priority inversion
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedfifo:		1: 	80
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L0
+C: locknowait:		1: 	0
+W: blocked:		1: 	0
+T: prioeq:		0: 	80
+
+# T0 unlock L0
+C: unlock:		0: 	0
+W: locked:		1: 	0
+
+# Verify T1
+W: unlocked:		0: 	0
+T: priolt:		0: 	1
+
+# Unlock and exit
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
+
diff --git a/scripts/rt-tester/t2-l1-signal.tst b/scripts/rt-tester/t2-l1-signal.tst
new file mode 100644
index 0000000..3ab0bfc
--- /dev/null
+++ b/scripts/rt-tester/t2-l1-signal.tst
@@ -0,0 +1,77 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	0
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 2 threads 1 lock with priority inversion
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedother:		1: 	0
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L0
+C: lockintnowait:	1: 	0
+W: blocked:		1: 	0
+
+# Interrupt T1
+C: signal:		1:	0
+W: unlocked:		1: 	0
+T: opcodeeq:		1:	-4
+
+# Unlock and exit
+C: unlock:		0: 	0
+W: unlocked:		0: 	0
diff --git a/scripts/rt-tester/t2-l2-2rt-deadlock.tst b/scripts/rt-tester/t2-l2-2rt-deadlock.tst
new file mode 100644
index 0000000..f4b5d5d
--- /dev/null
+++ b/scripts/rt-tester/t2-l2-2rt-deadlock.tst
@@ -0,0 +1,89 @@
+#
+# RT-Mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	0
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 2 threads 2 lock
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedfifo:		0: 	80
+C: schedfifo:		1: 	80
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L1
+C: locknowait:		1:	1
+W: locked:		1: 	1
+
+# T0 lock L1
+C: lockintnowait:	0: 	1
+W: blocked:		0: 	1
+
+# T1 lock L0
+C: lockintnowait:	1: 	0
+W: blocked:		1: 	0
+
+# Make deadlock go away
+C: signal:		1:	0
+W: unlocked:		1:	0
+C: signal:		0:	0
+W: unlocked:		0:	1
+
+# Unlock and exit
+C: unlock:		0: 	0
+W: unlocked:		0: 	0
+C: unlock:		1: 	1
+W: unlocked:		1: 	1
+
diff --git a/scripts/rt-tester/t3-l1-pi-1rt.tst b/scripts/rt-tester/t3-l1-pi-1rt.tst
new file mode 100644
index 0000000..63440ca
--- /dev/null
+++ b/scripts/rt-tester/t3-l1-pi-1rt.tst
@@ -0,0 +1,92 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 3 threads 1 lock PI
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedother:		1: 	0
+C: schedfifo:		2: 	82
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L0
+C: locknowait:		1: 	0
+W: blocked:		1: 	0
+T: priolt:		0: 	1
+
+# T2 lock L0
+C: locknowait:		2: 	0
+W: blocked:		2: 	0
+T: prioeq:		0: 	82
+
+# T0 unlock L0
+C: unlock:		0: 	0
+
+# Wait until T2 got the lock
+W: locked:		2: 	0
+W: unlocked:		0:	0
+T: priolt:		0:	1
+
+# T2 unlock L0
+C: unlock:		2: 	0
+
+W: unlocked:		2: 	0
+W: locked:		1: 	0
+
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
diff --git a/scripts/rt-tester/t3-l1-pi-2rt.tst b/scripts/rt-tester/t3-l1-pi-2rt.tst
new file mode 100644
index 0000000..e5816fe
--- /dev/null
+++ b/scripts/rt-tester/t3-l1-pi-2rt.tst
@@ -0,0 +1,93 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 3 threads 1 lock PI
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedfifo:		1: 	81
+C: schedfifo:		2: 	82
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L0
+C: locknowait:		1: 	0
+W: blocked:		1: 	0
+T: prioeq:		0: 	81
+
+# T2 lock L0
+C: locknowait:		2: 	0
+W: blocked:		2: 	0
+T: prioeq:		0: 	82
+T: prioeq:		1:	81
+
+# T0 unlock L0
+C: unlock:		0: 	0
+
+# Wait until T2 got the lock
+W: locked:		2: 	0
+W: unlocked:		0:	0
+T: priolt:		0:	1
+
+# T2 unlock L0
+C: unlock:		2: 	0
+
+W: unlocked:		2: 	0
+W: locked:		1: 	0
+
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
diff --git a/scripts/rt-tester/t3-l1-pi-3rt.tst b/scripts/rt-tester/t3-l1-pi-3rt.tst
new file mode 100644
index 0000000..718b82b
--- /dev/null
+++ b/scripts/rt-tester/t3-l1-pi-3rt.tst
@@ -0,0 +1,92 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 3 threads 1 lock PI
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedfifo:		0: 	80
+C: schedfifo:		1: 	81
+C: schedfifo:		2: 	82
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L0
+C: locknowait:		1: 	0
+W: blocked:		1: 	0
+T: prioeq:		0: 	81
+
+# T2 lock L0
+C: locknowait:		2: 	0
+W: blocked:		2: 	0
+T: prioeq:		0: 	82
+
+# T0 unlock L0
+C: unlock:		0: 	0
+
+# Wait until T2 got the lock
+W: locked:		2: 	0
+W: unlocked:		0:	0
+T: prioeq:		0:	80
+
+# T2 unlock L0
+C: unlock:		2: 	0
+
+W: locked:		1: 	0
+W: unlocked:		2: 	0
+
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
diff --git a/scripts/rt-tester/t3-l1-pi-signal.tst b/scripts/rt-tester/t3-l1-pi-signal.tst
new file mode 100644
index 0000000..c6e2135
--- /dev/null
+++ b/scripts/rt-tester/t3-l1-pi-signal.tst
@@ -0,0 +1,98 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+# Reset event counter
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set priorities
+C: schedother:		0: 	0
+C: schedfifo:		1: 	80
+C: schedfifo:		2: 	81
+
+# T0 lock L0
+C: lock:		0:	0
+W: locked:		0: 	0
+
+# T1 lock L0, no wait in the wakeup path
+C: locknowait:		1: 	0
+W: blocked:		1: 	0
+T: prioeq:		0:	80
+T: prioeq:		1:	80
+
+# T2 lock L0 interruptible, no wait in the wakeup path
+C: lockintnowait:	2:	0
+W: blocked:		2: 	0
+T: prioeq:		0:	81
+T: prioeq:		1:	80
+
+# Interrupt T2
+C: signal:		2:	2
+W: unlocked:		2:	0
+T: prioeq:		1:	80
+T: prioeq:		0:	80
+
+T: locked:		0:	0
+T: blocked:		1:	0
+
+# T0 unlock L0
+C: unlock:		0: 	0
+
+# Wait until T1 has locked L0 and exit
+W: locked:		1:	0
+W: unlocked:		0: 	0
+T: priolt:		0:	1
+
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
+
+
+
diff --git a/scripts/rt-tester/t3-l1-pi-steal.tst b/scripts/rt-tester/t3-l1-pi-steal.tst
new file mode 100644
index 0000000..f53749d
--- /dev/null
+++ b/scripts/rt-tester/t3-l1-pi-steal.tst
@@ -0,0 +1,96 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 3 threads 1 lock PI steal pending ownership
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedfifo:		1: 	80
+C: schedfifo:		2: 	81
+
+# T0 lock L0
+C: lock:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L0
+C: lock:		1: 	0
+W: blocked:		1: 	0
+T: prioeq:		0: 	80
+
+# T0 unlock L0
+C: unlock:		0: 	0
+
+# Wait until T1 is in the wakeup loop
+W: blockedwake:		1: 	0
+T: priolt:		0: 	1
+
+# T2 lock L0
+C: lock:		2: 	0
+# T1 leave wakeup loop
+C: lockcont:		1: 	0
+
+# T2 must have the lock and T1 must be blocked
+W: locked:		2: 	0
+W: blocked:		1: 	0
+
+# T2 unlock L0
+C: unlock:		2: 	0
+
+# Wait until T1 is in the wakeup loop and let it run
+W: blockedwake:		1: 	0
+C: lockcont:		1: 	0
+W: locked:		1: 	0
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
diff --git a/scripts/rt-tester/t3-l2-pi.tst b/scripts/rt-tester/t3-l2-pi.tst
new file mode 100644
index 0000000..cdc3e4f
--- /dev/null
+++ b/scripts/rt-tester/t3-l2-pi.tst
@@ -0,0 +1,92 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 3 threads 2 lock PI
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedother:		1: 	0
+C: schedfifo:		2: 	82
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L0
+C: locknowait:		1: 	0
+W: blocked:		1: 	0
+T: priolt:		0: 	1
+
+# T2 lock L0
+C: locknowait:		2: 	0
+W: blocked:		2: 	0
+T: prioeq:		0: 	82
+
+# T0 unlock L0
+C: unlock:		0: 	0
+
+# Wait until T2 got the lock
+W: locked:		2: 	0
+W: unlocked:		0:	0
+T: priolt:		0:	1
+
+# T2 unlock L0
+C: unlock:		2: 	0
+
+W: unlocked:		2: 	0
+W: locked:		1: 	0
+
+C: unlock:		1: 	0
+W: unlocked:		1: 	0
diff --git a/scripts/rt-tester/t4-l2-pi-deboost.tst b/scripts/rt-tester/t4-l2-pi-deboost.tst
new file mode 100644
index 0000000..baa1413
--- /dev/null
+++ b/scripts/rt-tester/t4-l2-pi-deboost.tst
@@ -0,0 +1,123 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 4 threads 2 lock PI
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedother:		1: 	0
+C: schedfifo:		2: 	82
+C: schedfifo:		3: 	83
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L1
+C: locknowait:		1: 	1
+W: locked:		1: 	1
+
+# T3 lock L0
+C: lockintnowait:	3: 	0
+W: blocked:		3: 	0
+T: prioeq:		0: 	83
+
+# T0 lock L1
+C: lock:		0: 	1
+W: blocked:		0: 	1
+T: prioeq:		1: 	83
+
+# T1 unlock L1
+C: unlock:		1:	1
+
+# Wait until T0 is in the wakeup code
+W: blockedwake:		0:	1
+
+# Verify that T1 is unboosted
+W: unlocked:		1: 	1
+T: priolt:		1: 	1
+
+# T2 lock L1 (T0 is boosted and pending owner !)
+C: locknowait:		2:	1
+W: blocked:		2: 	1
+T: prioeq:		0: 	83
+
+# Interrupt T3 and wait until T3 returned
+C: signal:		3:	0
+W: unlocked:		3:	0
+
+# Verify prio of T0 (still pending owner,
+# but T2 is enqueued due to the previous boost by T3
+T: prioeq:		0:	82
+
+# Let T0 continue
+C: lockcont:		0:	1
+W: locked:		0:	1
+
+# Unlock L1 and let T2 get L1
+C: unlock:		0:	1
+W: locked:		2:	1
+
+# Verify that T0 is unboosted
+W: unlocked:		0:	1
+T: priolt:		0:	1
+
+# Unlock everything and exit
+C: unlock:		2:	1
+W: unlocked:		2:	1
+
+C: unlock:		0:	0
+W: unlocked:		0:	0
+
diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst
new file mode 100644
index 0000000..e6ec0c8
--- /dev/null
+++ b/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst
@@ -0,0 +1,183 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 5 threads 4 lock PI - modify priority of blocked threads
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedfifo:		1: 	81
+C: schedfifo:		2: 	82
+C: schedfifo:		3: 	83
+C: schedfifo:		4: 	84
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L1
+C: locknowait:		1: 	1
+W: locked:		1: 	1
+
+# T1 lock L0
+C: lockintnowait:	1: 	0
+W: blocked:		1: 	0
+T: prioeq:		0: 	81
+
+# T2 lock L2
+C: locknowait:		2: 	2
+W: locked:		2: 	2
+
+# T2 lock L1
+C: lockintnowait:	2: 	1
+W: blocked:		2: 	1
+T: prioeq:		0: 	82
+T: prioeq:		1:	82
+
+# T3 lock L3
+C: locknowait:		3: 	3
+W: locked:		3: 	3
+
+# T3 lock L2
+C: lockintnowait:	3: 	2
+W: blocked:		3: 	2
+T: prioeq:		0: 	83
+T: prioeq:		1:	83
+T: prioeq:		2:	83
+
+# T4 lock L3
+C: lockintnowait:	4:	3
+W: blocked:		4: 	3
+T: prioeq:		0: 	84
+T: prioeq:		1:	84
+T: prioeq:		2:	84
+T: prioeq:		3:	84
+
+# Reduce prio of T4
+C: schedfifo:		4: 	80
+T: prioeq:		0: 	83
+T: prioeq:		1:	83
+T: prioeq:		2:	83
+T: prioeq:		3:	83
+T: prioeq:		4:	80
+
+# Increase prio of T4
+C: schedfifo:		4: 	84
+T: prioeq:		0: 	84
+T: prioeq:		1:	84
+T: prioeq:		2:	84
+T: prioeq:		3:	84
+T: prioeq:		4:	84
+
+# Reduce prio of T3
+C: schedfifo:		3: 	80
+T: prioeq:		0: 	84
+T: prioeq:		1:	84
+T: prioeq:		2:	84
+T: prioeq:		3:	84
+T: prioeq:		4:	84
+
+# Increase prio of T3
+C: schedfifo:		3: 	85
+T: prioeq:		0: 	85
+T: prioeq:		1:	85
+T: prioeq:		2:	85
+T: prioeq:		3:	85
+T: prioeq:		4:	84
+
+# Reduce prio of T3
+C: schedfifo:		3: 	83
+T: prioeq:		0: 	84
+T: prioeq:		1:	84
+T: prioeq:		2:	84
+T: prioeq:		3:	84
+T: prioeq:		4:	84
+
+# Signal T4
+C: signal:		4: 	0
+W: unlocked:		4: 	3
+T: prioeq:		0: 	83
+T: prioeq:		1:	83
+T: prioeq:		2:	83
+T: prioeq:		3:	83
+
+# Signal T3
+C: signal:		3: 	0
+W: unlocked:		3: 	2
+T: prioeq:		0: 	82
+T: prioeq:		1:	82
+T: prioeq:		2:	82
+
+# Signal T2
+C: signal:		2: 	0
+W: unlocked:		2: 	1
+T: prioeq:		0: 	81
+T: prioeq:		1:	81
+
+# Signal T1
+C: signal:		1: 	0
+W: unlocked:		1: 	0
+T: priolt:		0: 	1
+
+# Unlock and exit
+C: unlock:		3:	3
+C: unlock:		2:	2
+C: unlock:		1:	1
+C: unlock:		0:	0
+
+W: unlocked:		3:	3
+W: unlocked:		2:	2
+W: unlocked:		1:	1
+W: unlocked:		0:	0
+
diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost.tst
new file mode 100644
index 0000000..ca64f8b
--- /dev/null
+++ b/scripts/rt-tester/t5-l4-pi-boost-deboost.tst
@@ -0,0 +1,143 @@
+#
+# rt-mutex test
+#
+# Op: C(ommand)/T(est)/W(ait)
+# |  opcode
+# |  |     threadid: 0-7
+# |  |     |  opcode argument
+# |  |     |  |
+# C: lock: 0: 0
+#
+# Commands
+#
+# opcode	opcode argument
+# schedother	nice value
+# schedfifo	priority
+# lock		lock nr (0-7)
+# locknowait	lock nr (0-7)
+# lockint	lock nr (0-7)
+# lockintnowait	lock nr (0-7)
+# lockcont	lock nr (0-7)
+# unlock	lock nr (0-7)
+# lockbkl	lock nr (0-7)
+# unlockbkl	lock nr (0-7)
+# signal	thread to signal (0-7)
+# reset		0
+# resetevent	0
+#
+# Tests / Wait
+#
+# opcode	opcode argument
+#
+# prioeq	priority
+# priolt	priority
+# priogt	priority
+# nprioeq	normal priority
+# npriolt	normal priority
+# npriogt	normal priority
+# locked	lock nr (0-7)
+# blocked	lock nr (0-7)
+# blockedwake	lock nr (0-7)
+# unlocked	lock nr (0-7)
+# lockedbkl	dont care
+# blockedbkl	dont care
+# unlockedbkl	dont care
+# opcodeeq	command opcode or number
+# opcodelt	number
+# opcodegt	number
+# eventeq	number
+# eventgt	number
+# eventlt	number
+
+#
+# 5 threads 4 lock PI
+#
+C: resetevent:		0: 	0
+W: opcodeeq:		0: 	0
+
+# Set schedulers
+C: schedother:		0: 	0
+C: schedfifo:		1: 	81
+C: schedfifo:		2: 	82
+C: schedfifo:		3: 	83
+C: schedfifo:		4: 	84
+
+# T0 lock L0
+C: locknowait:		0: 	0
+W: locked:		0: 	0
+
+# T1 lock L1
+C: locknowait:		1: 	1
+W: locked:		1: 	1
+
+# T1 lock L0
+C: lockintnowait:	1: 	0
+W: blocked:		1: 	0
+T: prioeq:		0: 	81
+
+# T2 lock L2
+C: locknowait:		2: 	2
+W: locked:		2: 	2
+
+# T2 lock L1
+C: lockintnowait:	2: 	1
+W: blocked:		2: 	1
+T: prioeq:		0: 	82
+T: prioeq:		1:	82
+
+# T3 lock L3
+C: locknowait:		3: 	3
+W: locked:		3: 	3
+
+# T3 lock L2
+C: lockintnowait:	3: 	2
+W: blocked:		3: 	2
+T: prioeq:		0: 	83
+T: prioeq:		1:	83
+T: prioeq:		2:	83
+
+# T4 lock L3
+C: lockintnowait:	4:	3
+W: blocked:		4: 	3
+T: prioeq:		0: 	84
+T: prioeq:		1:	84
+T: prioeq:		2:	84
+T: prioeq:		3:	84
+
+# Signal T4
+C: signal:		4: 	0
+W: unlocked:		4: 	3
+T: prioeq:		0: 	83
+T: prioeq:		1:	83
+T: prioeq:		2:	83
+T: prioeq:		3:	83
+
+# Signal T3
+C: signal:		3: 	0
+W: unlocked:		3: 	2
+T: prioeq:		0: 	82
+T: prioeq:		1:	82
+T: prioeq:		2:	82
+
+# Signal T2
+C: signal:		2: 	0
+W: unlocked:		2: 	1
+T: prioeq:		0: 	81
+T: prioeq:		1:	81
+
+# Signal T1
+C: signal:		1: 	0
+W: unlocked:		1: 	0
+T: priolt:		0: 	1
+
+# Unlock and exit
+C: unlock:		3:	3
+C: unlock:		2:	2
+C: unlock:		1:	1
+C: unlock:		0:	0
+
+W: unlocked:		3:	3
+W: unlocked:		2:	2
+W: unlocked:		1:	1
+W: unlocked:		0:	0
+
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 9a23825..82e4993 100644
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -11,12 +11,12 @@
 # Check for git and a git repo.
 if head=`git rev-parse --verify HEAD 2>/dev/null`; then
 	# Do we have an untagged version?
-	if  [ "`git name-rev --tags HEAD`" = "HEAD undefined" ]; then
+	if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
 		printf '%s%s' -g `echo "$head" | cut -c1-8`
 	fi
 
 	# Are there uncommitted changes?
-	if git diff-files | read dummy; then
+	if git diff-index HEAD | read dummy; then
 		printf '%s' -dirty
 	fi
 fi
diff --git a/security/Kconfig b/security/Kconfig
index 34f5934..67785df 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -22,16 +22,22 @@
 	  If you are unsure as to whether this is required, answer N.
 
 config KEYS_DEBUG_PROC_KEYS
-	bool "Enable the /proc/keys file by which all keys may be viewed"
+	bool "Enable the /proc/keys file by which keys may be viewed"
 	depends on KEYS
 	help
-	  This option turns on support for the /proc/keys file through which
-	  all the keys on the system can be listed.
+	  This option turns on support for the /proc/keys file - through which
+	  can be listed all the keys on the system that are viewable by the
+	  reading process.
 
-	  This option is a slight security risk in that it makes it possible
-	  for anyone to see all the keys on the system. Normally the manager
-	  pretends keys that are inaccessible to a process don't exist as far
-	  as that process is concerned.
+	  The only keys included in the list are those that grant View
+	  permission to the reading process whether or not it possesses them.
+	  Note that LSM security checks are still performed, and may further
+	  filter out keys that the current process is not authorised to view.
+
+	  Only key attributes are listed here; key payloads are not included in
+	  the resulting table.
+
+	  If you are unsure as to whether this is required, answer N.
 
 config SECURITY
 	bool "Enable different security models"
diff --git a/security/dummy.c b/security/dummy.c
index 8cccccc..310fcdf7 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -191,7 +191,7 @@
 	return 0;
 }
 
-static int dummy_sb_statfs (struct super_block *sb)
+static int dummy_sb_statfs (struct dentry *dentry)
 {
 	return 0;
 }
@@ -516,6 +516,11 @@
 	return 0;
 }
 
+static int dummy_task_setioprio (struct task_struct *p, int ioprio)
+{
+	return 0;
+}
+
 static int dummy_task_setrlimit (unsigned int resource, struct rlimit *new_rlim)
 {
 	return 0;
@@ -532,6 +537,11 @@
 	return 0;
 }
 
+static int dummy_task_movememory (struct task_struct *p)
+{
+	return 0;
+}
+
 static int dummy_task_wait (struct task_struct *p)
 {
 	return 0;
@@ -810,6 +820,11 @@
 {
 }
 
+static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
+{
+	return 0;
+}
+
 static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
 {
 	return 0;
@@ -819,6 +834,11 @@
 {
 }
 
+static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
+{
+	return 0;
+}
+
 static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
 {
 	return 0;
@@ -850,7 +870,8 @@
 }
 
 #ifdef CONFIG_KEYS
-static inline int dummy_key_alloc(struct key *key)
+static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx,
+				  unsigned long flags)
 {
 	return 0;
 }
@@ -962,9 +983,11 @@
 	set_to_dummy_if_null(ops, task_getsid);
 	set_to_dummy_if_null(ops, task_setgroups);
 	set_to_dummy_if_null(ops, task_setnice);
+	set_to_dummy_if_null(ops, task_setioprio);
 	set_to_dummy_if_null(ops, task_setrlimit);
 	set_to_dummy_if_null(ops, task_setscheduler);
 	set_to_dummy_if_null(ops, task_getscheduler);
+	set_to_dummy_if_null(ops, task_movememory);
 	set_to_dummy_if_null(ops, task_wait);
 	set_to_dummy_if_null(ops, task_kill);
 	set_to_dummy_if_null(ops, task_prctl);
@@ -1024,8 +1047,10 @@
 	set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
 	set_to_dummy_if_null(ops, xfrm_policy_clone_security);
 	set_to_dummy_if_null(ops, xfrm_policy_free_security);
+	set_to_dummy_if_null(ops, xfrm_policy_delete_security);
 	set_to_dummy_if_null(ops, xfrm_state_alloc_security);
 	set_to_dummy_if_null(ops, xfrm_state_free_security);
+	set_to_dummy_if_null(ops, xfrm_state_delete_security);
 	set_to_dummy_if_null(ops, xfrm_policy_lookup);
 #endif	/* CONFIG_SECURITY_NETWORK_XFRM */
 #ifdef CONFIG_KEYS
diff --git a/security/inode.c b/security/inode.c
index 0f77b02..98a0df5 100644
--- a/security/inode.c
+++ b/security/inode.c
@@ -135,11 +135,11 @@
 	return simple_fill_super(sb, SECURITYFS_MAGIC, files);
 }
 
-static struct super_block *get_sb(struct file_system_type *fs_type,
-				        int flags, const char *dev_name,
-					void *data)
+static int get_sb(struct file_system_type *fs_type,
+		  int flags, const char *dev_name,
+		  void *data, struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, fill_super);
+	return get_sb_single(fs_type, flags, data, fill_super, mnt);
 }
 
 static struct file_system_type fs_type = {
@@ -224,7 +224,7 @@
 
 	pr_debug("securityfs: creating file '%s'\n",name);
 
-	error = simple_pin_fs("securityfs", &mount, &mount_count);
+	error = simple_pin_fs(&fs_type, &mount, &mount_count);
 	if (error) {
 		dentry = ERR_PTR(error);
 		goto exit;
diff --git a/security/keys/internal.h b/security/keys/internal.h
index e066e60..3c2877f 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -99,7 +99,8 @@
 extern struct key *request_key_and_link(struct key_type *type,
 					const char *description,
 					const char *callout_info,
-					struct key *dest_keyring);
+					struct key *dest_keyring,
+					unsigned long flags);
 
 /*
  * request_key authorisation
diff --git a/security/keys/key.c b/security/keys/key.c
index b6061fa..80de8c3 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -11,15 +11,16 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/poison.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/security.h>
 #include <linux/workqueue.h>
+#include <linux/random.h>
 #include <linux/err.h>
 #include "internal.h"
 
 static kmem_cache_t	*key_jar;
-static key_serial_t	key_serial_next = 3;
 struct rb_root		key_serial_tree; /* tree of keys indexed by serial */
 DEFINE_SPINLOCK(key_serial_lock);
 
@@ -169,22 +170,23 @@
 /*****************************************************************************/
 /*
  * assign a key the next unique serial number
- * - we work through all the serial numbers between 2 and 2^31-1 in turn and
- *   then wrap
+ * - these are assigned randomly to avoid security issues through covert
+ *   channel problems
  */
 static inline void key_alloc_serial(struct key *key)
 {
 	struct rb_node *parent, **p;
 	struct key *xkey;
 
-	spin_lock(&key_serial_lock);
-
-	/* propose a likely serial number and look for a hole for it in the
+	/* propose a random serial number and look for a hole for it in the
 	 * serial number tree */
-	key->serial = key_serial_next;
-	if (key->serial < 3)
-		key->serial = 3;
-	key_serial_next = key->serial + 1;
+	do {
+		get_random_bytes(&key->serial, sizeof(key->serial));
+
+		key->serial >>= 1; /* negative numbers are not permitted */
+	} while (key->serial < 3);
+
+	spin_lock(&key_serial_lock);
 
 	parent = NULL;
 	p = &key_serial_tree.rb_node;
@@ -204,19 +206,18 @@
 
 	/* we found a key with the proposed serial number - walk the tree from
 	 * that point looking for the next unused serial number */
- serial_exists:
+serial_exists:
 	for (;;) {
-		key->serial = key_serial_next;
+		key->serial++;
 		if (key->serial < 2)
 			key->serial = 2;
-		key_serial_next = key->serial + 1;
 
-		if (!parent->rb_parent)
+		if (!rb_parent(parent))
 			p = &key_serial_tree.rb_node;
-		else if (parent->rb_parent->rb_left == parent)
-			p = &parent->rb_parent->rb_left;
+		else if (rb_parent(parent)->rb_left == parent)
+			p = &(rb_parent(parent)->rb_left);
 		else
-			p = &parent->rb_parent->rb_right;
+			p = &(rb_parent(parent)->rb_right);
 
 		parent = rb_next(parent);
 		if (!parent)
@@ -228,7 +229,7 @@
 	}
 
 	/* we've found a suitable hole - arrange for this key to occupy it */
- insert_here:
+insert_here:
 	rb_link_node(&key->serial_node, parent, p);
 	rb_insert_color(&key->serial_node, &key_serial_tree);
 
@@ -247,8 +248,8 @@
  *   instantiate the key or discard it before returning
  */
 struct key *key_alloc(struct key_type *type, const char *desc,
-		      uid_t uid, gid_t gid, key_perm_t perm,
-		      int not_in_quota)
+		      uid_t uid, gid_t gid, struct task_struct *ctx,
+		      key_perm_t perm, unsigned long flags)
 {
 	struct key_user *user = NULL;
 	struct key *key;
@@ -269,12 +270,14 @@
 
 	/* check that the user's quota permits allocation of another key and
 	 * its description */
-	if (!not_in_quota) {
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
 		spin_lock(&user->lock);
-		if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
-		    user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
-		    )
-			goto no_quota;
+		if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
+			if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
+			    user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES
+			    )
+				goto no_quota;
+		}
 
 		user->qnkeys++;
 		user->qnbytes += quotalen;
@@ -308,7 +311,7 @@
 	key->payload.data = NULL;
 	key->security = NULL;
 
-	if (!not_in_quota)
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
 		key->flags |= 1 << KEY_FLAG_IN_QUOTA;
 
 	memset(&key->type_data, 0, sizeof(key->type_data));
@@ -318,7 +321,7 @@
 #endif
 
 	/* let the security module know about the key */
-	ret = security_key_alloc(key);
+	ret = security_key_alloc(key, ctx, flags);
 	if (ret < 0)
 		goto security_error;
 
@@ -332,7 +335,7 @@
 security_error:
 	kfree(key->description);
 	kmem_cache_free(key_jar, key);
-	if (!not_in_quota) {
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
 		spin_lock(&user->lock);
 		user->qnkeys--;
 		user->qnbytes -= quotalen;
@@ -345,7 +348,7 @@
 no_memory_3:
 	kmem_cache_free(key_jar, key);
 no_memory_2:
-	if (!not_in_quota) {
+	if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) {
 		spin_lock(&user->lock);
 		user->qnkeys--;
 		user->qnbytes -= quotalen;
@@ -761,7 +764,7 @@
 			       const char *description,
 			       const void *payload,
 			       size_t plen,
-			       int not_in_quota)
+			       unsigned long flags)
 {
 	struct key_type *ktype;
 	struct key *keyring, *key = NULL;
@@ -822,7 +825,7 @@
 
 	/* allocate a new key */
 	key = key_alloc(ktype, description, current->fsuid, current->fsgid,
-			perm, not_in_quota);
+			current, perm, flags);
 	if (IS_ERR(key)) {
 		key_ref = ERR_PTR(PTR_ERR(key));
 		goto error_3;
@@ -907,6 +910,10 @@
 	 * it */
 	down_write(&key->sem);
 	set_bit(KEY_FLAG_REVOKED, &key->flags);
+
+	if (key->type->revoke)
+		key->type->revoke(key);
+
 	up_write(&key->sem);
 
 } /* end key_revoke() */
@@ -982,7 +989,7 @@
 		if (key->type == ktype) {
 			if (ktype->destroy)
 				ktype->destroy(key);
-			memset(&key->payload, 0xbd, sizeof(key->payload));
+			memset(&key->payload, KEY_DESTROY, sizeof(key->payload));
 		}
 	}
 
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index ed71d86..329411c 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -102,7 +102,7 @@
 	/* create or update the requested key and add it to the target
 	 * keyring */
 	key_ref = key_create_or_update(keyring_ref, type, description,
-				       payload, plen, 0);
+				       payload, plen, KEY_ALLOC_IN_QUOTA);
 	if (!IS_ERR(key_ref)) {
 		ret = key_ref_to_ptr(key_ref)->serial;
 		key_ref_put(key_ref);
@@ -184,7 +184,8 @@
 
 	/* do the search */
 	key = request_key_and_link(ktype, description, callout_info,
-				   key_ref_to_ptr(dest_ref));
+				   key_ref_to_ptr(dest_ref),
+				   KEY_ALLOC_IN_QUOTA);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error5;
@@ -672,6 +673,7 @@
  */
 long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 {
+	struct key_user *newowner, *zapowner = NULL;
 	struct key *key;
 	key_ref_t key_ref;
 	long ret;
@@ -695,19 +697,50 @@
 	if (!capable(CAP_SYS_ADMIN)) {
 		/* only the sysadmin can chown a key to some other UID */
 		if (uid != (uid_t) -1 && key->uid != uid)
-			goto no_access;
+			goto error_put;
 
 		/* only the sysadmin can set the key's GID to a group other
 		 * than one of those that the current process subscribes to */
 		if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
-			goto no_access;
+			goto error_put;
 	}
 
-	/* change the UID (have to update the quotas) */
+	/* change the UID */
 	if (uid != (uid_t) -1 && uid != key->uid) {
-		/* don't support UID changing yet */
-		ret = -EOPNOTSUPP;
-		goto no_access;
+		ret = -ENOMEM;
+		newowner = key_user_lookup(uid);
+		if (!newowner)
+			goto error_put;
+
+		/* transfer the quota burden to the new user */
+		if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
+			spin_lock(&newowner->lock);
+			if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS ||
+			    newowner->qnbytes + key->quotalen >=
+			    KEYQUOTA_MAX_BYTES)
+				goto quota_overrun;
+
+			newowner->qnkeys++;
+			newowner->qnbytes += key->quotalen;
+			spin_unlock(&newowner->lock);
+
+			spin_lock(&key->user->lock);
+			key->user->qnkeys--;
+			key->user->qnbytes -= key->quotalen;
+			spin_unlock(&key->user->lock);
+		}
+
+		atomic_dec(&key->user->nkeys);
+		atomic_inc(&newowner->nkeys);
+
+		if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
+			atomic_dec(&key->user->nikeys);
+			atomic_inc(&newowner->nikeys);
+		}
+
+		zapowner = key->user;
+		key->user = newowner;
+		key->uid = uid;
 	}
 
 	/* change the GID */
@@ -716,12 +749,20 @@
 
 	ret = 0;
 
- no_access:
+error_put:
 	up_write(&key->sem);
 	key_put(key);
- error:
+	if (zapowner)
+		key_user_put(zapowner);
+error:
 	return ret;
 
+quota_overrun:
+	spin_unlock(&newowner->lock);
+	zapowner = newowner;
+	ret = -EDQUOT;
+	goto error_put;
+
 } /* end keyctl_chown_key() */
 
 /*****************************************************************************/
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index bffa924..e8d02ac 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -49,6 +49,7 @@
 static int keyring_instantiate(struct key *keyring,
 			       const void *data, size_t datalen);
 static int keyring_match(const struct key *keyring, const void *criterion);
+static void keyring_revoke(struct key *keyring);
 static void keyring_destroy(struct key *keyring);
 static void keyring_describe(const struct key *keyring, struct seq_file *m);
 static long keyring_read(const struct key *keyring,
@@ -59,6 +60,7 @@
 	.def_datalen	= sizeof(struct keyring_list),
 	.instantiate	= keyring_instantiate,
 	.match		= keyring_match,
+	.revoke		= keyring_revoke,
 	.destroy	= keyring_destroy,
 	.describe	= keyring_describe,
 	.read		= keyring_read,
@@ -240,15 +242,16 @@
  * allocate a keyring and link into the destination keyring
  */
 struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
-			  int not_in_quota, struct key *dest)
+			  struct task_struct *ctx, unsigned long flags,
+			  struct key *dest)
 {
 	struct key *keyring;
 	int ret;
 
 	keyring = key_alloc(&key_type_keyring, description,
-			    uid, gid,
+			    uid, gid, ctx,
 			    (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
-			    not_in_quota);
+			    flags);
 
 	if (!IS_ERR(keyring)) {
 		ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
@@ -952,3 +955,22 @@
 } /* end keyring_clear() */
 
 EXPORT_SYMBOL(keyring_clear);
+
+/*****************************************************************************/
+/*
+ * dispose of the links from a revoked keyring
+ * - called with the key sem write-locked
+ */
+static void keyring_revoke(struct key *keyring)
+{
+	struct keyring_list *klist = keyring->payload.subscriptions;
+
+	/* adjust the quota */
+	key_payload_reserve(keyring, 0);
+
+	if (klist) {
+		rcu_assign_pointer(keyring->payload.subscriptions, NULL);
+		call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
+	}
+
+} /* end keyring_revoke() */
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 12b750e..686a9ee 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -137,6 +137,13 @@
 	struct timespec now;
 	unsigned long timo;
 	char xbuf[12];
+	int rc;
+
+	/* check whether the current task is allowed to view the key (assuming
+	 * non-possession) */
+	rc = key_task_permission(make_key_ref(key, 0), current, KEY_VIEW);
+	if (rc < 0)
+		return 0;
 
 	now = current_kernel_time();
 
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 217a0be..32150cf 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -67,7 +67,8 @@
 /*
  * allocate the keyrings to be associated with a UID
  */
-int alloc_uid_keyring(struct user_struct *user)
+int alloc_uid_keyring(struct user_struct *user,
+		      struct task_struct *ctx)
 {
 	struct key *uid_keyring, *session_keyring;
 	char buf[20];
@@ -76,7 +77,8 @@
 	/* concoct a default session keyring */
 	sprintf(buf, "_uid_ses.%u", user->uid);
 
-	session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0, NULL);
+	session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+					KEY_ALLOC_IN_QUOTA, NULL);
 	if (IS_ERR(session_keyring)) {
 		ret = PTR_ERR(session_keyring);
 		goto error;
@@ -86,8 +88,8 @@
 	 * keyring */
 	sprintf(buf, "_uid.%u", user->uid);
 
-	uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 0,
-				    session_keyring);
+	uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx,
+				    KEY_ALLOC_IN_QUOTA, session_keyring);
 	if (IS_ERR(uid_keyring)) {
 		key_put(session_keyring);
 		ret = PTR_ERR(uid_keyring);
@@ -143,7 +145,8 @@
 
 	sprintf(buf, "_tid.%u", tsk->pid);
 
-	keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+	keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error;
@@ -177,7 +180,8 @@
 	if (!tsk->signal->process_keyring) {
 		sprintf(buf, "_pid.%u", tsk->tgid);
 
-		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+					KEY_ALLOC_QUOTA_OVERRUN, NULL);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
 			goto error;
@@ -208,6 +212,7 @@
 static int install_session_keyring(struct task_struct *tsk,
 				   struct key *keyring)
 {
+	unsigned long flags;
 	struct key *old;
 	char buf[20];
 
@@ -217,7 +222,12 @@
 	if (!keyring) {
 		sprintf(buf, "_ses.%u", tsk->tgid);
 
-		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+		flags = KEY_ALLOC_QUOTA_OVERRUN;
+		if (tsk->signal->session_keyring)
+			flags = KEY_ALLOC_IN_QUOTA;
+
+		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk,
+					flags, NULL);
 		if (IS_ERR(keyring))
 			return PTR_ERR(keyring);
 	}
@@ -390,6 +400,8 @@
 	struct request_key_auth *rka;
 	key_ref_t key_ref, ret, err;
 
+	might_sleep();
+
 	/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
 	 * searchable, but we failed to find a key or we found a negative key;
 	 * otherwise we want to return a sample error (probably -EACCES) if
@@ -495,27 +507,35 @@
 	 */
 	if (context->request_key_auth &&
 	    context == current &&
-	    type != &key_type_request_key_auth &&
-	    key_validate(context->request_key_auth) == 0
+	    type != &key_type_request_key_auth
 	    ) {
-		rka = context->request_key_auth->payload.data;
+		/* defend against the auth key being revoked */
+		down_read(&context->request_key_auth->sem);
 
-		key_ref = search_process_keyrings(type, description, match,
-						  rka->context);
+		if (key_validate(context->request_key_auth) == 0) {
+			rka = context->request_key_auth->payload.data;
 
-		if (!IS_ERR(key_ref))
-			goto found;
+			key_ref = search_process_keyrings(type, description,
+							  match, rka->context);
 
-		switch (PTR_ERR(key_ref)) {
-		case -EAGAIN: /* no key */
-			if (ret)
+			up_read(&context->request_key_auth->sem);
+
+			if (!IS_ERR(key_ref))
+				goto found;
+
+			switch (PTR_ERR(key_ref)) {
+			case -EAGAIN: /* no key */
+				if (ret)
+					break;
+			case -ENOKEY: /* negative key */
+				ret = key_ref;
 				break;
-		case -ENOKEY: /* negative key */
-			ret = key_ref;
-			break;
-		default:
-			err = key_ref;
-			break;
+			default:
+				err = key_ref;
+				break;
+			}
+		} else {
+			up_read(&context->request_key_auth->sem);
 		}
 	}
 
@@ -717,7 +737,8 @@
 	keyring = find_keyring_by_name(name, 0);
 	if (PTR_ERR(keyring) == -ENOKEY) {
 		/* not found - try and create a new one */
-		keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL);
+		keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk,
+					KEY_ALLOC_IN_QUOTA, NULL);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
 			goto error2;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index f030a0c..58d1efd 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -48,7 +48,8 @@
 	/* allocate a new session keyring */
 	sprintf(desc, "_req.%u", key->serial);
 
-	keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
+	keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current,
+				KEY_ALLOC_QUOTA_OVERRUN, NULL);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error_alloc;
@@ -125,7 +126,8 @@
  */
 static struct key *__request_key_construction(struct key_type *type,
 					      const char *description,
-					      const char *callout_info)
+					      const char *callout_info,
+					      unsigned long flags)
 {
 	request_key_actor_t actor;
 	struct key_construction cons;
@@ -133,11 +135,12 @@
 	struct key *key, *authkey;
 	int ret, negated;
 
-	kenter("%s,%s,%s", type->name, description, callout_info);
+	kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags);
 
 	/* create a key and add it to the queue */
 	key = key_alloc(type, description,
-			current->fsuid, current->fsgid, KEY_POS_ALL, 0);
+			current->fsuid, current->fsgid, current, KEY_POS_ALL,
+			flags);
 	if (IS_ERR(key))
 		goto alloc_failed;
 
@@ -256,15 +259,16 @@
 static struct key *request_key_construction(struct key_type *type,
 					    const char *description,
 					    struct key_user *user,
-					    const char *callout_info)
+					    const char *callout_info,
+					    unsigned long flags)
 {
 	struct key_construction *pcons;
 	struct key *key, *ckey;
 
 	DECLARE_WAITQUEUE(myself, current);
 
-	kenter("%s,%s,{%d},%s",
-	       type->name, description, user->uid, callout_info);
+	kenter("%s,%s,{%d},%s,%lx",
+	       type->name, description, user->uid, callout_info, flags);
 
 	/* see if there's such a key under construction already */
 	down_write(&key_construction_sem);
@@ -280,7 +284,8 @@
 	}
 
 	/* see about getting userspace to construct the key */
-	key = __request_key_construction(type, description, callout_info);
+	key = __request_key_construction(type, description, callout_info,
+					 flags);
  error:
 	kleave(" = %p", key);
 	return key;
@@ -387,14 +392,15 @@
 struct key *request_key_and_link(struct key_type *type,
 				 const char *description,
 				 const char *callout_info,
-				 struct key *dest_keyring)
+				 struct key *dest_keyring,
+				 unsigned long flags)
 {
 	struct key_user *user;
 	struct key *key;
 	key_ref_t key_ref;
 
-	kenter("%s,%s,%s,%p",
-	       type->name, description, callout_info, dest_keyring);
+	kenter("%s,%s,%s,%p,%lx",
+	       type->name, description, callout_info, dest_keyring, flags);
 
 	/* search all the process keyrings for a key */
 	key_ref = search_process_keyrings(type, description, type->match,
@@ -427,7 +433,8 @@
 			/* ask userspace (returns NULL if it waited on a key
 			 * being constructed) */
 			key = request_key_construction(type, description,
-						       user, callout_info);
+						       user, callout_info,
+						       flags);
 			if (key)
 				break;
 
@@ -483,7 +490,8 @@
 			const char *description,
 			const char *callout_info)
 {
-	return request_key_and_link(type, description, callout_info, NULL);
+	return request_key_and_link(type, description, callout_info, NULL,
+				    KEY_ALLOC_IN_QUOTA);
 
 } /* end request_key() */
 
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index cce6ba6..cbf58a9 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -20,6 +20,7 @@
 
 static int request_key_auth_instantiate(struct key *, const void *, size_t);
 static void request_key_auth_describe(const struct key *, struct seq_file *);
+static void request_key_auth_revoke(struct key *);
 static void request_key_auth_destroy(struct key *);
 static long request_key_auth_read(const struct key *, char __user *, size_t);
 
@@ -31,6 +32,7 @@
 	.def_datalen	= sizeof(struct request_key_auth),
 	.instantiate	= request_key_auth_instantiate,
 	.describe	= request_key_auth_describe,
+	.revoke		= request_key_auth_revoke,
 	.destroy	= request_key_auth_destroy,
 	.read		= request_key_auth_read,
 };
@@ -93,6 +95,24 @@
 
 /*****************************************************************************/
 /*
+ * handle revocation of an authorisation token key
+ * - called with the key sem write-locked
+ */
+static void request_key_auth_revoke(struct key *key)
+{
+	struct request_key_auth *rka = key->payload.data;
+
+	kenter("{%d}", key->serial);
+
+	if (rka->context) {
+		put_task_struct(rka->context);
+		rka->context = NULL;
+	}
+
+} /* end request_key_auth_revoke() */
+
+/*****************************************************************************/
+/*
  * destroy an instantiation authorisation token key
  */
 static void request_key_auth_destroy(struct key *key)
@@ -101,6 +121,11 @@
 
 	kenter("{%d}", key->serial);
 
+	if (rka->context) {
+		put_task_struct(rka->context);
+		rka->context = NULL;
+	}
+
 	key_put(rka->target_key);
 	kfree(rka);
 
@@ -131,14 +156,26 @@
 	 * another process */
 	if (current->request_key_auth) {
 		/* it is - use that instantiation context here too */
+		down_read(&current->request_key_auth->sem);
+
+		/* if the auth key has been revoked, then the key we're
+		 * servicing is already instantiated */
+		if (test_bit(KEY_FLAG_REVOKED,
+			     &current->request_key_auth->flags))
+			goto auth_key_revoked;
+
 		irka = current->request_key_auth->payload.data;
 		rka->context = irka->context;
 		rka->pid = irka->pid;
+		get_task_struct(rka->context);
+
+		up_read(&current->request_key_auth->sem);
 	}
 	else {
 		/* it isn't - use this process as the context */
 		rka->context = current;
 		rka->pid = current->pid;
+		get_task_struct(rka->context);
 	}
 
 	rka->target_key = key_get(target);
@@ -148,9 +185,9 @@
 	sprintf(desc, "%x", target->serial);
 
 	authkey = key_alloc(&key_type_request_key_auth, desc,
-			    current->fsuid, current->fsgid,
+			    current->fsuid, current->fsgid, current,
 			    KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
-			    KEY_USR_VIEW, 1);
+			    KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
 	if (IS_ERR(authkey)) {
 		ret = PTR_ERR(authkey);
 		goto error_alloc;
@@ -161,9 +198,15 @@
 	if (ret < 0)
 		goto error_inst;
 
-	kleave(" = {%d})", authkey->serial);
+	kleave(" = {%d}", authkey->serial);
 	return authkey;
 
+auth_key_revoked:
+	up_read(&current->request_key_auth->sem);
+	kfree(rka);
+	kleave("= -EKEYREVOKED");
+	return ERR_PTR(-EKEYREVOKED);
+
 error_inst:
 	key_revoke(authkey);
 	key_put(authkey);
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 8e71895..5bbfdeb 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -28,6 +28,7 @@
 	.instantiate	= user_instantiate,
 	.update		= user_update,
 	.match		= user_match,
+	.revoke		= user_revoke,
 	.destroy	= user_destroy,
 	.describe	= user_describe,
 	.read		= user_read,
@@ -67,6 +68,7 @@
 	return ret;
 
 } /* end user_instantiate() */
+
 EXPORT_SYMBOL_GPL(user_instantiate);
 
 /*****************************************************************************/
@@ -141,7 +143,28 @@
 
 /*****************************************************************************/
 /*
- * dispose of the data dangling from the corpse of a user
+ * dispose of the links from a revoked keyring
+ * - called with the key sem write-locked
+ */
+void user_revoke(struct key *key)
+{
+	struct user_key_payload *upayload = key->payload.data;
+
+	/* clear the quota */
+	key_payload_reserve(key, 0);
+
+	if (upayload) {
+		rcu_assign_pointer(key->payload.data, NULL);
+		call_rcu(&upayload->rcu, user_update_rcu_disposal);
+	}
+
+} /* end user_revoke() */
+
+EXPORT_SYMBOL(user_revoke);
+
+/*****************************************************************************/
+/*
+ * dispose of the data dangling from the corpse of a user key
  */
 void user_destroy(struct key *key)
 {
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index f636f53..814ddc4 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -1,6 +1,7 @@
 config SECURITY_SELINUX
 	bool "NSA SELinux Support"
 	depends on SECURITY_NETWORK && AUDIT && NET && INET
+	select NETWORK_SECMARK
 	default n
 	help
 	  This selects NSA Security-Enhanced Linux (SELinux).
@@ -95,3 +96,31 @@
 	  via /selinux/checkreqprot if authorized by policy.
 
 	  If you are unsure how to answer this question, answer 1.
+
+config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+	bool "NSA SELinux enable new secmark network controls by default"
+	depends on SECURITY_SELINUX
+	default n
+	help
+	  This option determines whether the new secmark-based network
+	  controls will be enabled by default.  If not, the old internal
+	  per-packet controls will be enabled by default, preserving
+	  old behavior.
+
+	  If you enable the new controls, you will need updated
+	  SELinux userspace libraries, tools and policy.  Typically,
+	  your distribution will provide these and enable the new controls
+	  in the kernel they also distribute.
+
+	  Note that this option can be overriden at boot with the
+	  selinux_compat_net parameter, and after boot via
+	  /selinux/compat_net.  See Documentation/kernel-parameters.txt
+	  for details on this parameter.
+
+	  If you enable the new network controls, you will likely
+	  also require the SECMARK and CONNSECMARK targets, as
+	  well as any conntrack helpers for protocols which you
+	  wish to control.
+
+	  If you are unsure what do do here, select N.
+
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index ae4c73e..9d7737d 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -72,3 +72,25 @@
 	*sid = 0;
 }
 
+int selinux_string_to_sid(char *str, u32 *sid)
+{
+	if (selinux_enabled)
+		return security_context_to_sid(str, strlen(str), sid);
+	else {
+		*sid = 0;
+		return 0;
+	}
+}
+EXPORT_SYMBOL_GPL(selinux_string_to_sid);
+
+int selinux_relabel_packet_permission(u32 sid)
+{
+	if (selinux_enabled) {
+		struct task_security_struct *tsec = current->security;
+
+		return avc_has_perm(tsec->sid, sid, SECCLASS_PACKET,
+				    PACKET__RELABELTO, NULL);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 90b4cdc..28832e6 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -80,6 +80,7 @@
 
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
+extern int selinux_compat_net;
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 int selinux_enforcing = 0;
@@ -696,6 +697,8 @@
 		return SECCLASS_PACKET_SOCKET;
 	case PF_KEY:
 		return SECCLASS_KEY_SOCKET;
+	case PF_APPLETALK:
+		return SECCLASS_APPLETALK_SOCKET;
 	}
 
 	return SECCLASS_SOCKET;
@@ -1096,6 +1099,17 @@
 			    FILESYSTEM__ASSOCIATE, &ad);
 }
 
+/* Check whether a task can create a key. */
+static int may_create_key(u32 ksid,
+			  struct task_struct *ctx)
+{
+	struct task_security_struct *tsec;
+
+	tsec = ctx->security;
+
+	return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
+}
+
 #define MAY_LINK   0
 #define MAY_UNLINK 1
 #define MAY_RMDIR  2
@@ -1518,8 +1532,10 @@
 	/* Default to the current task SID. */
 	bsec->sid = tsec->sid;
 
-	/* Reset create SID on execve. */
+	/* Reset fs, key, and sock SIDs on execve. */
 	tsec->create_sid = 0;
+	tsec->keycreate_sid = 0;
+	tsec->sockcreate_sid = 0;
 
 	if (tsec->exec_sid) {
 		newsid = tsec->exec_sid;
@@ -1900,13 +1916,13 @@
 	return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
 }
 
-static int selinux_sb_statfs(struct super_block *sb)
+static int selinux_sb_statfs(struct dentry *dentry)
 {
 	struct avc_audit_data ad;
 
 	AVC_AUDIT_DATA_INIT(&ad,FS);
-	ad.u.fs.dentry = sb->s_root;
-	return superblock_has_perm(current, sb, FILESYSTEM__GETATTR, &ad);
+	ad.u.fs.dentry = dentry->d_sb->s_root;
+	return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
 
 static int selinux_mount(char * dev_name,
@@ -2571,9 +2587,11 @@
 	tsec2->osid = tsec1->osid;
 	tsec2->sid = tsec1->sid;
 
-	/* Retain the exec and create SIDs across fork */
+	/* Retain the exec, fs, key, and sock SIDs across fork */
 	tsec2->exec_sid = tsec1->exec_sid;
 	tsec2->create_sid = tsec1->create_sid;
+	tsec2->keycreate_sid = tsec1->keycreate_sid;
+	tsec2->sockcreate_sid = tsec1->sockcreate_sid;
 
 	/* Retain ptracer SID across fork, if any.
 	   This will be reset by the ptrace hook upon any
@@ -2642,6 +2660,11 @@
 	return task_has_perm(current,p, PROCESS__SETSCHED);
 }
 
+static int selinux_task_setioprio(struct task_struct *p, int ioprio)
+{
+	return task_has_perm(current, p, PROCESS__SETSCHED);
+}
+
 static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim)
 {
 	struct rlimit *old_rlim = current->signal->rlim + resource;
@@ -2671,6 +2694,11 @@
 	return task_has_perm(current, p, PROCESS__GETSCHED);
 }
 
+static int selinux_task_movememory(struct task_struct *p)
+{
+	return task_has_perm(current, p, PROCESS__SETSCHED);
+}
+
 static int selinux_task_kill(struct task_struct *p, struct siginfo *info, int sig)
 {
 	u32 perm;
@@ -2913,12 +2941,14 @@
 {
 	int err = 0;
 	struct task_security_struct *tsec;
+	u32 newsid;
 
 	if (kern)
 		goto out;
 
 	tsec = current->security;
-	err = avc_has_perm(tsec->sid, tsec->sid,
+	newsid = tsec->sockcreate_sid ? : tsec->sid;
+	err = avc_has_perm(tsec->sid, newsid,
 			   socket_type_to_security_class(family, type,
 			   protocol), SOCKET__CREATE, NULL);
 
@@ -2931,12 +2961,14 @@
 {
 	struct inode_security_struct *isec;
 	struct task_security_struct *tsec;
+	u32 newsid;
 
 	isec = SOCK_INODE(sock)->i_security;
 
 	tsec = current->security;
+	newsid = tsec->sockcreate_sid ? : tsec->sid;
 	isec->sclass = socket_type_to_security_class(family, type, protocol);
-	isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
+	isec->sid = kern ? SECINITSID_KERNEL : newsid;
 	isec->initialized = 1;
 
 	return;
@@ -3214,47 +3246,17 @@
 	return 0;
 }
 
-static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
+		struct avc_audit_data *ad, u32 sock_sid, u16 sock_class,
+		u16 family, char *addrp, int len)
 {
-	u16 family;
-	char *addrp;
-	int len, err = 0;
+	int err = 0;
 	u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
-	u32 sock_sid = 0;
-	u16 sock_class = 0;
-	struct socket *sock;
-	struct net_device *dev;
-	struct avc_audit_data ad;
 
-	family = sk->sk_family;
-	if (family != PF_INET && family != PF_INET6)
+	if (!skb->dev)
 		goto out;
 
-	/* Handle mapped IPv4 packets arriving via IPv6 sockets */
-	if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
-		family = PF_INET;
-
- 	read_lock_bh(&sk->sk_callback_lock);
- 	sock = sk->sk_socket;
- 	if (sock) {
- 		struct inode *inode;
- 		inode = SOCK_INODE(sock);
- 		if (inode) {
- 			struct inode_security_struct *isec;
- 			isec = inode->i_security;
- 			sock_sid = isec->sid;
- 			sock_class = isec->sclass;
- 		}
- 	}
- 	read_unlock_bh(&sk->sk_callback_lock);
- 	if (!sock_sid)
-  		goto out;
-
-	dev = skb->dev;
-	if (!dev)
-		goto out;
-
-	err = sel_netif_sids(dev, &if_sid, NULL);
+	err = sel_netif_sids(skb->dev, &if_sid, NULL);
 	if (err)
 		goto out;
 
@@ -3277,44 +3279,88 @@
 		break;
 	}
 
-	AVC_AUDIT_DATA_INIT(&ad, NET);
-	ad.u.net.netif = dev->name;
-	ad.u.net.family = family;
-
-	err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
-	if (err)
-		goto out;
-
-	err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
+	err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
 	if (err)
 		goto out;
 	
-	/* Fixme: this lookup is inefficient */
 	err = security_node_sid(family, addrp, len, &node_sid);
 	if (err)
 		goto out;
 	
-	err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad);
+	err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad);
 	if (err)
 		goto out;
 
 	if (recv_perm) {
 		u32 port_sid;
 
-		/* Fixme: make this more efficient */
 		err = security_port_sid(sk->sk_family, sk->sk_type,
-		                        sk->sk_protocol, ntohs(ad.u.net.sport),
+		                        sk->sk_protocol, ntohs(ad->u.net.sport),
 		                        &port_sid);
 		if (err)
 			goto out;
 
 		err = avc_has_perm(sock_sid, port_sid,
-				   sock_class, recv_perm, &ad);
+				   sock_class, recv_perm, ad);
 	}
 
-	if (!err)
-		err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+out:
+	return err;
+}
 
+static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+	u16 family;
+	u16 sock_class = 0;
+	char *addrp;
+	int len, err = 0;
+	u32 sock_sid = 0;
+	struct socket *sock;
+	struct avc_audit_data ad;
+
+	family = sk->sk_family;
+	if (family != PF_INET && family != PF_INET6)
+		goto out;
+
+	/* Handle mapped IPv4 packets arriving via IPv6 sockets */
+	if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
+		family = PF_INET;
+
+ 	read_lock_bh(&sk->sk_callback_lock);
+ 	sock = sk->sk_socket;
+ 	if (sock) {
+ 		struct inode *inode;
+ 		inode = SOCK_INODE(sock);
+ 		if (inode) {
+ 			struct inode_security_struct *isec;
+ 			isec = inode->i_security;
+ 			sock_sid = isec->sid;
+ 			sock_class = isec->sclass;
+ 		}
+ 	}
+ 	read_unlock_bh(&sk->sk_callback_lock);
+ 	if (!sock_sid)
+  		goto out;
+
+	AVC_AUDIT_DATA_INIT(&ad, NET);
+	ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
+	ad.u.net.family = family;
+
+	err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
+	if (err)
+		goto out;
+
+	if (selinux_compat_net)
+		err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid,
+						  sock_class, family,
+						  addrp, len);
+	else
+		err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET,
+				   PACKET__RECV, &ad);
+	if (err)
+		goto out;
+
+	err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
 out:	
 	return err;
 }
@@ -3454,42 +3500,18 @@
 
 #ifdef CONFIG_NETFILTER
 
-static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
-                                              struct sk_buff **pskb,
-                                              const struct net_device *in,
-                                              const struct net_device *out,
-                                              int (*okfn)(struct sk_buff *),
-                                              u16 family)
+static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
+					    struct inode_security_struct *isec,
+					    struct avc_audit_data *ad,
+					    u16 family, char *addrp, int len)
 {
-	char *addrp;
-	int len, err = NF_ACCEPT;
+	int err;
 	u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
-	struct sock *sk;
-	struct socket *sock;
-	struct inode *inode;
-	struct sk_buff *skb = *pskb;
-	struct inode_security_struct *isec;
-	struct avc_audit_data ad;
-	struct net_device *dev = (struct net_device *)out;
 	
-	sk = skb->sk;
-	if (!sk)
-		goto out;
-		
-	sock = sk->sk_socket;
-	if (!sock)
-		goto out;
-		
-	inode = SOCK_INODE(sock);
-	if (!inode)
-		goto out;
-
 	err = sel_netif_sids(dev, &if_sid, NULL);
 	if (err)
 		goto out;
 
-	isec = inode->i_security;
-	
 	switch (isec->sclass) {
 	case SECCLASS_UDP_SOCKET:
 		netif_perm = NETIF__UDP_SEND;
@@ -3509,55 +3531,88 @@
 		break;
 	}
 
-
-	AVC_AUDIT_DATA_INIT(&ad, NET);
-	ad.u.net.netif = dev->name;
-	ad.u.net.family = family;
-
-	err = selinux_parse_skb(skb, &ad, &addrp,
-				&len, 0) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
-		goto out;
-
-	err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
-	                   netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
+	err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
+	if (err)
 		goto out;
 		
-	/* Fixme: this lookup is inefficient */
-	err = security_node_sid(family, addrp, len,
-				&node_sid) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
+	err = security_node_sid(family, addrp, len, &node_sid);
+	if (err)
 		goto out;
 	
-	err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
-	                   node_perm, &ad) ? NF_DROP : NF_ACCEPT;
-	if (err != NF_ACCEPT)
+	err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
+	if (err)
 		goto out;
 
 	if (send_perm) {
 		u32 port_sid;
 		
-		/* Fixme: make this more efficient */
 		err = security_port_sid(sk->sk_family,
 		                        sk->sk_type,
 		                        sk->sk_protocol,
-		                        ntohs(ad.u.net.dport),
-		                        &port_sid) ? NF_DROP : NF_ACCEPT;
-		if (err != NF_ACCEPT)
+		                        ntohs(ad->u.net.dport),
+		                        &port_sid);
+		if (err)
 			goto out;
 
 		err = avc_has_perm(isec->sid, port_sid, isec->sclass,
-		                   send_perm, &ad) ? NF_DROP : NF_ACCEPT;
+				   send_perm, ad);
 	}
+out:
+	return err;
+}
 
-	if (err != NF_ACCEPT)
+static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
+                                              struct sk_buff **pskb,
+                                              const struct net_device *in,
+                                              const struct net_device *out,
+                                              int (*okfn)(struct sk_buff *),
+                                              u16 family)
+{
+	char *addrp;
+	int len, err = 0;
+	struct sock *sk;
+	struct socket *sock;
+	struct inode *inode;
+	struct sk_buff *skb = *pskb;
+	struct inode_security_struct *isec;
+	struct avc_audit_data ad;
+	struct net_device *dev = (struct net_device *)out;
+
+	sk = skb->sk;
+	if (!sk)
+		goto out;
+
+	sock = sk->sk_socket;
+	if (!sock)
+		goto out;
+
+	inode = SOCK_INODE(sock);
+	if (!inode)
+		goto out;
+
+	isec = inode->i_security;
+
+	AVC_AUDIT_DATA_INIT(&ad, NET);
+	ad.u.net.netif = dev->name;
+	ad.u.net.family = family;
+
+	err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
+	if (err)
+		goto out;
+
+	if (selinux_compat_net)
+		err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad,
+						       family, addrp, len);
+	else
+		err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET,
+				   PACKET__SEND, &ad);
+
+	if (err)
 		goto out;
 
 	err = selinux_xfrm_postroute_last(isec->sid, skb);
-
 out:
-	return err;
+	return err ? NF_DROP : NF_ACCEPT;
 }
 
 static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
@@ -4114,6 +4169,10 @@
 		sid = tsec->exec_sid;
 	else if (!strcmp(name, "fscreate"))
 		sid = tsec->create_sid;
+	else if (!strcmp(name, "keycreate"))
+		sid = tsec->keycreate_sid;
+	else if (!strcmp(name, "sockcreate"))
+		sid = tsec->sockcreate_sid;
 	else
 		return -EINVAL;
 
@@ -4146,6 +4205,10 @@
 		error = task_has_perm(current, p, PROCESS__SETEXEC);
 	else if (!strcmp(name, "fscreate"))
 		error = task_has_perm(current, p, PROCESS__SETFSCREATE);
+	else if (!strcmp(name, "keycreate"))
+		error = task_has_perm(current, p, PROCESS__SETKEYCREATE);
+	else if (!strcmp(name, "sockcreate"))
+		error = task_has_perm(current, p, PROCESS__SETSOCKCREATE);
 	else if (!strcmp(name, "current"))
 		error = task_has_perm(current, p, PROCESS__SETCURRENT);
 	else
@@ -4175,6 +4238,13 @@
 		tsec->exec_sid = sid;
 	else if (!strcmp(name, "fscreate"))
 		tsec->create_sid = sid;
+	else if (!strcmp(name, "keycreate")) {
+		error = may_create_key(sid, p);
+		if (error)
+			return error;
+		tsec->keycreate_sid = sid;
+	} else if (!strcmp(name, "sockcreate"))
+		tsec->sockcreate_sid = sid;
 	else if (!strcmp(name, "current")) {
 		struct av_decision avd;
 
@@ -4226,6 +4296,61 @@
 	return size;
 }
 
+#ifdef CONFIG_KEYS
+
+static int selinux_key_alloc(struct key *k, struct task_struct *tsk,
+			     unsigned long flags)
+{
+	struct task_security_struct *tsec = tsk->security;
+	struct key_security_struct *ksec;
+
+	ksec = kzalloc(sizeof(struct key_security_struct), GFP_KERNEL);
+	if (!ksec)
+		return -ENOMEM;
+
+	ksec->obj = k;
+	if (tsec->keycreate_sid)
+		ksec->sid = tsec->keycreate_sid;
+	else
+		ksec->sid = tsec->sid;
+	k->security = ksec;
+
+	return 0;
+}
+
+static void selinux_key_free(struct key *k)
+{
+	struct key_security_struct *ksec = k->security;
+
+	k->security = NULL;
+	kfree(ksec);
+}
+
+static int selinux_key_permission(key_ref_t key_ref,
+			    struct task_struct *ctx,
+			    key_perm_t perm)
+{
+	struct key *key;
+	struct task_security_struct *tsec;
+	struct key_security_struct *ksec;
+
+	key = key_ref_to_ptr(key_ref);
+
+	tsec = ctx->security;
+	ksec = key->security;
+
+	/* if no specific permissions are requested, we skip the
+	   permission check. No serious, additional covert channels
+	   appear to be created. */
+	if (perm == 0)
+		return 0;
+
+	return avc_has_perm(tsec->sid, ksec->sid,
+			    SECCLASS_KEY, perm, NULL);
+}
+
+#endif
+
 static struct security_operations selinux_ops = {
 	.ptrace =			selinux_ptrace,
 	.capget =			selinux_capget,
@@ -4306,9 +4431,11 @@
 	.task_getsid =		        selinux_task_getsid,
 	.task_setgroups =		selinux_task_setgroups,
 	.task_setnice =			selinux_task_setnice,
+	.task_setioprio =		selinux_task_setioprio,
 	.task_setrlimit =		selinux_task_setrlimit,
 	.task_setscheduler =		selinux_task_setscheduler,
 	.task_getscheduler =		selinux_task_getscheduler,
+	.task_movememory =		selinux_task_movememory,
 	.task_kill =			selinux_task_kill,
 	.task_wait =			selinux_task_wait,
 	.task_prctl =			selinux_task_prctl,
@@ -4374,10 +4501,18 @@
 	.xfrm_policy_alloc_security =	selinux_xfrm_policy_alloc,
 	.xfrm_policy_clone_security =	selinux_xfrm_policy_clone,
 	.xfrm_policy_free_security =	selinux_xfrm_policy_free,
+	.xfrm_policy_delete_security =	selinux_xfrm_policy_delete,
 	.xfrm_state_alloc_security =	selinux_xfrm_state_alloc,
 	.xfrm_state_free_security =	selinux_xfrm_state_free,
+	.xfrm_state_delete_security =	selinux_xfrm_state_delete,
 	.xfrm_policy_lookup = 		selinux_xfrm_policy_lookup,
 #endif
+
+#ifdef CONFIG_KEYS
+	.key_alloc =                    selinux_key_alloc,
+	.key_free =                     selinux_key_free,
+	.key_permission =               selinux_key_permission,
+#endif
 };
 
 static __init int selinux_init(void)
@@ -4413,6 +4548,15 @@
 	} else {
 		printk(KERN_INFO "SELinux:  Starting in permissive mode\n");
 	}
+
+#ifdef CONFIG_KEYS
+	/* Add security information to initial keyrings */
+	selinux_key_alloc(&root_user_keyring, current,
+			  KEY_ALLOC_NOT_IN_QUOTA);
+	selinux_key_alloc(&root_session_keyring, current,
+			  KEY_ALLOC_NOT_IN_QUOTA);
+#endif
+
 	return 0;
 }
 
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h
index b0e6b12..a68fdd5 100644
--- a/security/selinux/include/av_inherit.h
+++ b/security/selinux/include/av_inherit.h
@@ -29,3 +29,4 @@
    S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL)
    S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
    S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
+   S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 591e98d..7c9b583 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -72,6 +72,8 @@
    S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem")
    S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack")
    S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap")
+   S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate")
+   S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate")
    S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue")
    S_(SECCLASS_MSG, MSG__SEND, "send")
    S_(SECCLASS_MSG, MSG__RECEIVE, "receive")
@@ -239,3 +241,13 @@
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
    S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
+   S_(SECCLASS_PACKET, PACKET__SEND, "send")
+   S_(SECCLASS_PACKET, PACKET__RECV, "recv")
+   S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
+   S_(SECCLASS_KEY, KEY__VIEW, "view")
+   S_(SECCLASS_KEY, KEY__READ, "read")
+   S_(SECCLASS_KEY, KEY__WRITE, "write")
+   S_(SECCLASS_KEY, KEY__SEARCH, "search")
+   S_(SECCLASS_KEY, KEY__LINK, "link")
+   S_(SECCLASS_KEY, KEY__SETATTR, "setattr")
+   S_(SECCLASS_KEY, KEY__CREATE, "create")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index d7f02ed..69fd4b4 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -467,6 +467,8 @@
 #define PROCESS__EXECMEM                          0x02000000UL
 #define PROCESS__EXECSTACK                        0x04000000UL
 #define PROCESS__EXECHEAP                         0x08000000UL
+#define PROCESS__SETKEYCREATE                     0x10000000UL
+#define PROCESS__SETSOCKCREATE                    0x20000000UL
 
 #define IPC__CREATE                               0x00000001UL
 #define IPC__DESTROY                              0x00000002UL
@@ -933,3 +935,37 @@
 #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG   0x00100000UL
 #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND  0x00200000UL
 
+#define APPLETALK_SOCKET__IOCTL                   0x00000001UL
+#define APPLETALK_SOCKET__READ                    0x00000002UL
+#define APPLETALK_SOCKET__WRITE                   0x00000004UL
+#define APPLETALK_SOCKET__CREATE                  0x00000008UL
+#define APPLETALK_SOCKET__GETATTR                 0x00000010UL
+#define APPLETALK_SOCKET__SETATTR                 0x00000020UL
+#define APPLETALK_SOCKET__LOCK                    0x00000040UL
+#define APPLETALK_SOCKET__RELABELFROM             0x00000080UL
+#define APPLETALK_SOCKET__RELABELTO               0x00000100UL
+#define APPLETALK_SOCKET__APPEND                  0x00000200UL
+#define APPLETALK_SOCKET__BIND                    0x00000400UL
+#define APPLETALK_SOCKET__CONNECT                 0x00000800UL
+#define APPLETALK_SOCKET__LISTEN                  0x00001000UL
+#define APPLETALK_SOCKET__ACCEPT                  0x00002000UL
+#define APPLETALK_SOCKET__GETOPT                  0x00004000UL
+#define APPLETALK_SOCKET__SETOPT                  0x00008000UL
+#define APPLETALK_SOCKET__SHUTDOWN                0x00010000UL
+#define APPLETALK_SOCKET__RECVFROM                0x00020000UL
+#define APPLETALK_SOCKET__SENDTO                  0x00040000UL
+#define APPLETALK_SOCKET__RECV_MSG                0x00080000UL
+#define APPLETALK_SOCKET__SEND_MSG                0x00100000UL
+#define APPLETALK_SOCKET__NAME_BIND               0x00200000UL
+
+#define PACKET__SEND                              0x00000001UL
+#define PACKET__RECV                              0x00000002UL
+#define PACKET__RELABELTO                         0x00000004UL
+
+#define KEY__VIEW                                 0x00000001UL
+#define KEY__READ                                 0x00000002UL
+#define KEY__WRITE                                0x00000004UL
+#define KEY__SEARCH                               0x00000008UL
+#define KEY__LINK                                 0x00000010UL
+#define KEY__SETATTR                              0x00000020UL
+#define KEY__CREATE                               0x00000040UL
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 77b2c59..24303b6 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -58,3 +58,6 @@
     S_("nscd")
     S_("association")
     S_("netlink_kobject_uevent_socket")
+    S_("appletalk_socket")
+    S_("packet")
+    S_("key")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index eb9f508..95887ae 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -60,6 +60,9 @@
 #define SECCLASS_NSCD                                    53
 #define SECCLASS_ASSOCIATION                             54
 #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET           55
+#define SECCLASS_APPLETALK_SOCKET                        56
+#define SECCLASS_PACKET                                  57
+#define SECCLASS_KEY                                     58
 
 /*
  * Security identifier indices for initial entities
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 54c0307..cf54a30 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -32,6 +32,8 @@
 	u32 sid;             /* current SID */
 	u32 exec_sid;        /* exec SID */
 	u32 create_sid;      /* fscreate SID */
+	u32 keycreate_sid;   /* keycreate SID */
+	u32 sockcreate_sid;  /* fscreate SID */
 	u32 ptrace_sid;      /* SID of ptrace parent */
 };
 
@@ -99,6 +101,11 @@
 	u32 peer_sid;			/* SID of peer */
 };
 
+struct key_security_struct {
+	struct key *obj; /* back pointer */
+	u32 sid;         /* SID of key */
+};
+
 extern unsigned int selinux_checkreqprot;
 
 #endif /* _SELINUX_OBJSEC_H_ */
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index c10f1fc..c96498a 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -9,8 +9,10 @@
 int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
 int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
 void selinux_xfrm_policy_free(struct xfrm_policy *xp);
+int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
 int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
 void selinux_xfrm_state_free(struct xfrm_state *x);
+int selinux_xfrm_state_delete(struct xfrm_state *x);
 int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
 
 /*
@@ -49,7 +51,7 @@
 
 static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
 {
-	return NF_ACCEPT;
+	return 0;
 }
 
 static inline int selinux_socket_getpeer_stream(struct sock *sk)
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index a4efc96..7029bbc 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -38,6 +38,14 @@
 
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
+#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
+#define SELINUX_COMPAT_NET_VALUE 0
+#else
+#define SELINUX_COMPAT_NET_VALUE 1
+#endif
+
+int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
+
 static int __init checkreqprot_setup(char *str)
 {
 	selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
@@ -45,6 +53,13 @@
 }
 __setup("checkreqprot=", checkreqprot_setup);
 
+static int __init selinux_compat_net_setup(char *str)
+{
+	selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
+	return 1;
+}
+__setup("selinux_compat_net=", selinux_compat_net_setup);
+
 
 static DEFINE_MUTEX(sel_mutex);
 
@@ -85,6 +100,7 @@
 	SEL_AVC,	/* AVC management directory */
 	SEL_MEMBER,	/* compute polyinstantiation membership decision */
 	SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
+	SEL_COMPAT_NET,	/* whether to use old compat network packet controls */
 };
 
 #define TMPBUFLEN	12
@@ -364,6 +380,55 @@
 	.write		= sel_write_checkreqprot,
 };
 
+static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	char tmpbuf[TMPBUFLEN];
+	ssize_t length;
+
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
+				    size_t count, loff_t *ppos)
+{
+	char *page;
+	ssize_t length;
+	int new_value;
+
+	length = task_has_security(current, SECURITY__LOAD_POLICY);
+	if (length)
+		return length;
+
+	if (count >= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	page = (char*)get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	length = -EFAULT;
+	if (copy_from_user(page, buf, count))
+		goto out;
+
+	length = -EINVAL;
+	if (sscanf(page, "%d", &new_value) != 1)
+		goto out;
+
+	selinux_compat_net = new_value ? 1 : 0;
+	length = count;
+out:
+	free_page((unsigned long) page);
+	return length;
+}
+static struct file_operations sel_compat_net_ops = {
+	.read		= sel_read_compat_net,
+	.write		= sel_write_compat_net,
+};
+
 /*
  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
  */
@@ -1219,6 +1284,7 @@
 		[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
 		[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
 		[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
+		[SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
 		/* last one */ {""}
 	};
 	ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
@@ -1279,10 +1345,11 @@
 	goto out;
 }
 
-static struct super_block *sel_get_sb(struct file_system_type *fs_type,
-				      int flags, const char *dev_name, void *data)
+static int sel_get_sb(struct file_system_type *fs_type,
+		      int flags, const char *dev_name, void *data,
+		      struct vfsmount *mnt)
 {
-	return get_sb_single(fs_type, flags, data, sel_fill_super);
+	return get_sb_single(fs_type, flags, data, sel_fill_super, mnt);
 }
 
 static struct file_system_type sel_fs_type = {
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index c284dbb..e9548bc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1980,7 +1980,7 @@
 		break;
 	case AUDIT_SE_SEN:
 	case AUDIT_SE_CLR:
-		level = (op == AUDIT_SE_SEN ?
+		level = (field == AUDIT_SE_SEN ?
 		         &ctxt->range.level[0] : &ctxt->range.level[1]);
 		switch (op) {
 		case AUDIT_EQUAL:
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index abe99d8..6633fb0 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -132,10 +132,7 @@
 		goto out;
 
 	/*
-	 * Does the subject have permission to set security or permission to
-	 * do the relabel?
-	 * Must be permitted to relabel from default socket type (process type)
-	 * to specified context
+	 * Does the subject have permission to set security context?
 	 */
 	rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
 			  SECCLASS_ASSOCIATION,
@@ -201,6 +198,23 @@
 }
 
 /*
+ * LSM hook implementation that authorizes deletion of labeled policies.
+ */
+int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
+{
+	struct task_security_struct *tsec = current->security;
+	struct xfrm_sec_ctx *ctx = xp->security;
+	int rc = 0;
+
+	if (ctx)
+		rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+				  SECCLASS_ASSOCIATION,
+				  ASSOCIATION__SETCONTEXT, NULL);
+
+	return rc;
+}
+
+/*
  * LSM hook implementation that allocs and transfers sec_ctx spec to
  * xfrm_state.
  */
@@ -292,6 +306,23 @@
 	return SECSID_NULL;
 }
 
+ /*
+  * LSM hook implementation that authorizes deletion of labeled SAs.
+  */
+int selinux_xfrm_state_delete(struct xfrm_state *x)
+{
+	struct task_security_struct *tsec = current->security;
+	struct xfrm_sec_ctx *ctx = x->security;
+	int rc = 0;
+
+	if (ctx)
+		rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
+				  SECCLASS_ASSOCIATION,
+				  ASSOCIATION__SETCONTEXT, NULL);
+
+	return rc;
+}
+
 /*
  * LSM hook that controls access to unlabelled packets.  If
  * a xfrm_state is authorizable (defined by macro) then it was
@@ -356,18 +387,12 @@
 			struct xfrm_state *x = dst_test->xfrm;
 
 			if (x && selinux_authorizable_xfrm(x))
-				goto accept;
+				goto out;
 		}
 	}
 
 	rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
 			  ASSOCIATION__SENDTO, NULL);
-	if (rc)
-		goto drop;
-
-accept:
-	return NF_ACCEPT;
-
-drop:
-	return NF_DROP;
+out:
+	return rc;
 }
diff --git a/sound/Kconfig b/sound/Kconfig
index b65ee47..e0d791a 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -58,6 +58,8 @@
 
 source "sound/ppc/Kconfig"
 
+source "sound/aoa/Kconfig"
+
 source "sound/arm/Kconfig"
 
 source "sound/mips/Kconfig"
diff --git a/sound/Makefile b/sound/Makefile
index f352bb2..a682ea3 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -4,7 +4,7 @@
 obj-$(CONFIG_SOUND) += soundcore.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
-obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/
+obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ aoa/
 
 ifeq ($(CONFIG_SND),y)
   obj-y += last.o
diff --git a/sound/aoa/Kconfig b/sound/aoa/Kconfig
new file mode 100644
index 0000000..a85194f
--- /dev/null
+++ b/sound/aoa/Kconfig
@@ -0,0 +1,17 @@
+menu "Apple Onboard Audio driver"
+	depends on SND!=n && PPC
+
+config SND_AOA
+	tristate "Apple Onboard Audio driver"
+	depends on SOUND && SND_PCM
+	---help---
+	This option enables the new driver for the various
+	Apple Onboard Audio components.
+
+source "sound/aoa/fabrics/Kconfig"
+
+source "sound/aoa/codecs/Kconfig"
+
+source "sound/aoa/soundbus/Kconfig"
+
+endmenu
diff --git a/sound/aoa/Makefile b/sound/aoa/Makefile
new file mode 100644
index 0000000..d8de3e7
--- /dev/null
+++ b/sound/aoa/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_SND_AOA) += core/
+obj-$(CONFIG_SND_AOA) += codecs/
+obj-$(CONFIG_SND_AOA) += fabrics/
+obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/
diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h
new file mode 100644
index 0000000..3a61f31
--- /dev/null
+++ b/sound/aoa/aoa-gpio.h
@@ -0,0 +1,81 @@
+/*
+ * Apple Onboard Audio GPIO definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#ifndef __AOA_GPIO_H
+#define __AOA_GPIO_H
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <asm/prom.h>
+
+typedef void (*notify_func_t)(void *data);
+
+enum notify_type {
+	AOA_NOTIFY_HEADPHONE,
+	AOA_NOTIFY_LINE_IN,
+	AOA_NOTIFY_LINE_OUT,
+};
+
+struct gpio_runtime;
+struct gpio_methods {
+	/* for initialisation/de-initialisation of the GPIO layer */
+	void (*init)(struct gpio_runtime *rt);
+	void (*exit)(struct gpio_runtime *rt);
+
+	/* turn off headphone, speakers, lineout */
+	void (*all_amps_off)(struct gpio_runtime *rt);
+	/* turn headphone, speakers, lineout back to previous setting */
+	void (*all_amps_restore)(struct gpio_runtime *rt);
+
+	void (*set_headphone)(struct gpio_runtime *rt, int on);
+	void (*set_speakers)(struct gpio_runtime *rt, int on);
+	void (*set_lineout)(struct gpio_runtime *rt, int on);
+
+	int (*get_headphone)(struct gpio_runtime *rt);
+	int (*get_speakers)(struct gpio_runtime *rt);
+	int (*get_lineout)(struct gpio_runtime *rt);
+
+	void (*set_hw_reset)(struct gpio_runtime *rt, int on);
+
+	/* use this to be notified of any events. The notification
+	 * function is passed the data, and is called in process
+	 * context by the use of schedule_work.
+	 * The interface for it is that setting a function to NULL
+	 * removes it, and they return 0 if the operation succeeded,
+	 * and -EBUSY if the notification is already assigned by
+	 * someone else. */
+	int (*set_notify)(struct gpio_runtime *rt,
+			  enum notify_type type,
+			  notify_func_t notify,
+			  void *data);
+	/* returns 0 if not plugged in, 1 if plugged in
+	 * or a negative error code */
+	int (*get_detect)(struct gpio_runtime *rt,
+			  enum notify_type type);
+};
+
+struct gpio_notification {
+	notify_func_t notify;
+	void *data;
+	void *gpio_private;
+	struct work_struct work;
+	struct mutex mutex;
+};
+
+struct gpio_runtime {
+	/* to be assigned by fabric */
+	struct device_node *node;
+	/* since everyone needs this pointer anyway... */
+	struct gpio_methods *methods;
+	/* to be used by the gpio implementation */
+	int implementation_private;
+	struct gpio_notification headphone_notify;
+	struct gpio_notification line_in_notify;
+	struct gpio_notification line_out_notify;
+};
+
+#endif /* __AOA_GPIO_H */
diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h
new file mode 100644
index 0000000..378ef1e
--- /dev/null
+++ b/sound/aoa/aoa.h
@@ -0,0 +1,131 @@
+/*
+ * Apple Onboard Audio definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#ifndef __AOA_H
+#define __AOA_H
+#include <asm/prom.h>
+#include <linux/module.h>
+/* So apparently there's a reason for requiring driver.h to be included first! */
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/asound.h>
+#include <sound/control.h>
+#include "aoa-gpio.h"
+#include "soundbus/soundbus.h"
+
+#define MAX_CODEC_NAME_LEN	32
+
+struct aoa_codec {
+	char	name[MAX_CODEC_NAME_LEN];
+
+	struct module *owner;
+
+	/* called when the fabric wants to init this codec.
+	 * Do alsa card manipulations from here. */
+	int (*init)(struct aoa_codec *codec);
+
+	/* called when the fabric is done with the codec.
+	 * The alsa card will be cleaned up so don't bother. */
+	void (*exit)(struct aoa_codec *codec);
+
+	/* May be NULL, but can be used by the fabric.
+	 * Refcounting is the codec driver's responsibility */
+	struct device_node *node;
+
+	/* assigned by fabric before init() is called, points
+	 * to the soundbus device. Cannot be NULL. */
+	struct soundbus_dev *soundbus_dev;
+
+	/* assigned by the fabric before init() is called, points
+	 * to the fabric's gpio runtime record for the relevant
+	 * device. */
+	struct gpio_runtime *gpio;
+
+	/* assigned by the fabric before init() is called, contains
+	 * a codec specific bitmask of what outputs and inputs are
+	 * actually connected */
+	u32 connected;
+
+	/* data the fabric can associate with this structure */
+	void *fabric_data;
+
+	/* private! */
+	struct list_head list;
+	struct aoa_fabric *fabric;
+};
+
+/* return 0 on success */
+extern int
+aoa_codec_register(struct aoa_codec *codec);
+extern void
+aoa_codec_unregister(struct aoa_codec *codec);
+
+#define MAX_LAYOUT_NAME_LEN	32
+
+struct aoa_fabric {
+	char	name[MAX_LAYOUT_NAME_LEN];
+
+	struct module *owner;
+
+	/* once codecs register, they are passed here after.
+	 * They are of course not initialised, since the
+	 * fabric is responsible for initialising some fields
+	 * in the codec structure! */
+	int (*found_codec)(struct aoa_codec *codec);
+	/* called for each codec when it is removed,
+	 * also in the case that aoa_fabric_unregister
+	 * is called and all codecs are removed
+	 * from this fabric.
+	 * Also called if found_codec returned 0 but
+	 * the codec couldn't initialise. */
+	void (*remove_codec)(struct aoa_codec *codec);
+	/* If found_codec returned 0, and the codec
+	 * could be initialised, this is called. */
+	void (*attached_codec)(struct aoa_codec *codec);
+};
+
+/* return 0 on success, -EEXIST if another fabric is
+ * registered, -EALREADY if the same fabric is registered.
+ * Passing NULL can be used to test for the presence
+ * of another fabric, if -EALREADY is returned there is
+ * no other fabric present.
+ * In the case that the function returns -EALREADY
+ * and the fabric passed is not NULL, all codecs
+ * that are not assigned yet are passed to the fabric
+ * again for reconsideration. */
+extern int
+aoa_fabric_register(struct aoa_fabric *fabric);
+
+/* it is vital to call this when the fabric exits!
+ * When calling, the remove_codec will be called
+ * for all codecs, unless it is NULL. */
+extern void
+aoa_fabric_unregister(struct aoa_fabric *fabric);
+
+/* if for some reason you want to get rid of a codec
+ * before the fabric is removed, use this.
+ * Note that remove_codec is called for it! */
+extern void
+aoa_fabric_unlink_codec(struct aoa_codec *codec);
+
+/* alsa help methods */
+struct aoa_card {
+	struct snd_card *alsa_card;
+};
+        
+extern int aoa_snd_device_new(snd_device_type_t type,
+	void * device_data, struct snd_device_ops * ops);
+extern struct snd_card *aoa_get_card(void);
+extern int aoa_snd_ctl_add(struct snd_kcontrol* control);
+
+/* GPIO stuff */
+extern struct gpio_methods *pmf_gpio_methods;
+extern struct gpio_methods *ftr_gpio_methods;
+/* extern struct gpio_methods *map_gpio_methods; */
+
+#endif /* __AOA_H */
diff --git a/sound/aoa/codecs/Kconfig b/sound/aoa/codecs/Kconfig
new file mode 100644
index 0000000..90cf58f
--- /dev/null
+++ b/sound/aoa/codecs/Kconfig
@@ -0,0 +1,32 @@
+config SND_AOA_ONYX
+	tristate "support Onyx chip"
+	depends on SND_AOA
+	---help---
+	This option enables support for the Onyx (pcm3052)
+	codec chip found in the latest Apple machines
+	(most of those with digital audio output).
+
+#config SND_AOA_TOPAZ
+#	tristate "support Topaz chips"
+#	depends on SND_AOA
+#	---help---
+#	This option enables support for the Topaz (CS84xx)
+#	codec chips found in the latest Apple machines,
+#	these chips do the digital input and output on
+#	some PowerMacs.
+
+config SND_AOA_TAS
+	tristate "support TAS chips"
+	depends on SND_AOA
+	---help---
+	This option enables support for the tas chips
+	found in a lot of Apple Machines, especially
+	iBooks and PowerBooks without digital.
+
+config SND_AOA_TOONIE
+	tristate "support Toonie chip"
+	depends on SND_AOA
+	---help---
+	This option enables support for the toonie codec
+	found in the Mac Mini. If you have a Mac Mini and
+	want to hear sound, select this option.
diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile
new file mode 100644
index 0000000..31cbe68
--- /dev/null
+++ b/sound/aoa/codecs/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o
+obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o
+obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
new file mode 100644
index 0000000..0b76507
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c
@@ -0,0 +1,1113 @@
+/*
+ * Apple Onboard Audio driver for Onyx codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ *
+ * This is a driver for the pcm3052 codec chip (codenamed Onyx)
+ * that is present in newer Apple hardware (with digital output).
+ *
+ * The Onyx codec has the following connections (listed by the bit
+ * to be used in aoa_codec.connected):
+ *  0: analog output
+ *  1: digital output
+ *  2: line input
+ *  3: microphone input
+ * Note that even though I know of no machine that has for example
+ * the digital output connected but not the analog, I have handled
+ * all the different cases in the code so that this driver may serve
+ * as a good example of what to do.
+ *
+ * NOTE: This driver assumes that there's at most one chip to be
+ * 	 used with one alsa card, in form of creating all kinds
+ *	 of mixer elements without regard for their existence.
+ *	 But snd-aoa assumes that there's at most one card, so
+ *	 this means you can only have one onyx on a system. This
+ *	 should probably be fixed by changing the assumption of
+ *	 having just a single card on a system, and making the
+ *	 'card' pointer accessible to anyone who needs it instead
+ *	 of hiding it in the aoa_snd_* functions...
+ *
+ */
+#include <linux/delay.h>
+#include <linux/module.h>
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
+
+#include "snd-aoa-codec-onyx.h"
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+
+#define PFX "snd-aoa-codec-onyx: "
+
+struct onyx {
+	/* cache registers 65 to 80, they are write-only! */
+	u8			cache[16];
+	struct i2c_client	i2c;
+	struct aoa_codec	codec;
+	u32			initialised:1,
+				spdif_locked:1,
+				analog_locked:1,
+				original_mute:2;
+	int			open_count;
+	struct codec_info	*codec_info;
+
+	/* mutex serializes concurrent access to the device
+	 * and this structure.
+	 */
+	struct mutex mutex;
+};
+#define codec_to_onyx(c) container_of(c, struct onyx, codec)
+
+/* both return 0 if all ok, else on error */
+static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value)
+{
+	s32 v;
+
+	if (reg != ONYX_REG_CONTROL) {
+		*value = onyx->cache[reg-FIRSTREGISTER];
+		return 0;
+	}
+	v = i2c_smbus_read_byte_data(&onyx->i2c, reg);
+	if (v < 0)
+		return -1;
+	*value = (u8)v;
+	onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value;
+	return 0;
+}
+
+static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value)
+{
+	int result;
+
+	result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value);
+	if (!result)
+		onyx->cache[reg-FIRSTREGISTER] = value;
+	return result;
+}
+
+/* alsa stuff */
+
+static int onyx_dev_register(struct snd_device *dev)
+{
+	return 0;
+}
+
+static struct snd_device_ops ops = {
+	.dev_register = onyx_dev_register,
+};
+
+/* this is necessary because most alsa mixer programs
+ * can't properly handle the negative range */
+#define VOLUME_RANGE_SHIFT	128
+
+static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT;
+	uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT;
+	return 0;
+}
+
+static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	s8 l, r;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT;
+	ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT;
+
+	return 0;
+}
+
+static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	s8 l, r;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
+	onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
+
+	if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] &&
+	    r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) {
+		mutex_unlock(&onyx->mutex);
+		return 0;
+	}
+
+	onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT,
+			    ucontrol->value.integer.value[0]
+			     - VOLUME_RANGE_SHIFT);
+	onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT,
+			    ucontrol->value.integer.value[1]
+			     - VOLUME_RANGE_SHIFT);
+	mutex_unlock(&onyx->mutex);
+
+	return 1;
+}
+
+static struct snd_kcontrol_new volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_vol_info,
+	.get = onyx_snd_vol_get,
+	.put = onyx_snd_vol_put,
+};
+
+/* like above, this is necessary because a lot
+ * of alsa mixer programs don't handle ranges
+ * that don't start at 0 properly.
+ * even alsamixer is one of them... */
+#define INPUTGAIN_RANGE_SHIFT	(-3)
+
+static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT;
+	uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT;
+	return 0;
+}
+
+static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 ig;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] =
+		(ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT;
+
+	return 0;
+}
+
+static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v, n;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+	n = v;
+	n &= ~ONYX_ADC_PGA_GAIN_MASK;
+	n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT)
+		& ONYX_ADC_PGA_GAIN_MASK;
+	onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n);
+	mutex_unlock(&onyx->mutex);
+
+	return n != v;
+}
+
+static struct snd_kcontrol_new inputgain_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Capture Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_inputgain_info,
+	.get = onyx_snd_inputgain_get,
+	.put = onyx_snd_inputgain_put,
+};
+
+static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = { "Line-In", "Microphone" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	s8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC);
+
+	return 0;
+}
+
+static void onyx_set_capture_source(struct onyx *onyx, int mic)
+{
+	s8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v);
+	v &= ~ONYX_ADC_INPUT_MIC;
+	if (mic)
+		v |= ONYX_ADC_INPUT_MIC;
+	onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v);
+	mutex_unlock(&onyx->mutex);
+}
+
+static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	onyx_set_capture_source(snd_kcontrol_chip(kcontrol),
+				ucontrol->value.enumerated.item[0]);
+	return 1;
+}
+
+static struct snd_kcontrol_new capture_source_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* If we name this 'Input Source', it properly shows up in
+	 * alsamixer as a selection, * but it's shown under the 
+	 * 'Playback' category.
+	 * If I name it 'Capture Source', it shows up in strange
+	 * ways (two bools of which one can be selected at a
+	 * time) but at least it's shown in the 'Capture'
+	 * category.
+	 * I was told that this was due to backward compatibility,
+	 * but I don't understand then why the mangling is *not*
+	 * done when I name it "Input Source".....
+	 */
+	.name = "Capture Source",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_capture_source_info,
+	.get = onyx_snd_capture_source_get,
+	.put = onyx_snd_capture_source_put,
+};
+
+static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 c;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT);
+	ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT);
+
+	return 0;
+}
+
+static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v = 0, c = 0;
+	int err = -EBUSY;
+
+	mutex_lock(&onyx->mutex);
+	if (onyx->analog_locked)
+		goto out_unlock;
+
+	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+	c = v;
+	c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT);
+	if (!ucontrol->value.integer.value[0])
+		c |= ONYX_MUTE_LEFT;
+	if (!ucontrol->value.integer.value[1])
+		c |= ONYX_MUTE_RIGHT;
+	err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c);
+
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return !err ? (v != c) : err;
+}
+
+static struct snd_kcontrol_new mute_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Switch",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = onyx_snd_mute_info,
+	.get = onyx_snd_mute_get,
+	.put = onyx_snd_mute_put,
+};
+
+
+static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+#define FLAG_POLARITY_INVERT	1
+#define FLAG_SPDIFLOCK		2
+
+static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 c;
+	long int pv = kcontrol->private_value;
+	u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
+	u8 address = (pv >> 8) & 0xff;
+	u8 mask = pv & 0xff;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, address, &c);
+	mutex_unlock(&onyx->mutex);
+
+	ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity;
+
+	return 0;
+}
+
+static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v = 0, c = 0;
+	int err;
+	long int pv = kcontrol->private_value;
+	u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT;
+	u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK;
+	u8 address = (pv >> 8) & 0xff;
+	u8 mask = pv & 0xff;
+
+	mutex_lock(&onyx->mutex);
+	if (spdiflock && onyx->spdif_locked) {
+		/* even if alsamixer doesn't care.. */
+		err = -EBUSY;
+		goto out_unlock;
+	}
+	onyx_read_register(onyx, address, &v);
+	c = v;
+	c &= ~(mask);
+	if (!!ucontrol->value.integer.value[0] ^ polarity)
+		c |= mask;
+	err = onyx_write_register(onyx, address, c);
+
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return !err ? (v != c) : err;
+}
+
+#define SINGLE_BIT(n, type, description, address, mask, flags)	 	\
+static struct snd_kcontrol_new n##_control = {				\
+	.iface = SNDRV_CTL_ELEM_IFACE_##type,				\
+	.name = description,						\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,			\
+	.info = onyx_snd_single_bit_info,				\
+	.get = onyx_snd_single_bit_get,					\
+	.put = onyx_snd_single_bit_put,					\
+	.private_value = (flags << 16) | (address << 8) | mask		\
+}
+
+SINGLE_BIT(spdif,
+	   MIXER,
+	   SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
+	   ONYX_REG_DIG_INFO4,
+	   ONYX_SPDIF_ENABLE,
+	   FLAG_SPDIFLOCK);
+SINGLE_BIT(ovr1,
+	   MIXER,
+	   "Oversampling Rate",
+	   ONYX_REG_DAC_CONTROL,
+	   ONYX_OVR1,
+	   0);
+SINGLE_BIT(flt0,
+	   MIXER,
+	   "Fast Digital Filter Rolloff",
+	   ONYX_REG_DAC_FILTER,
+	   ONYX_ROLLOFF_FAST,
+	   FLAG_POLARITY_INVERT);
+SINGLE_BIT(hpf,
+	   MIXER,
+	   "Highpass Filter",
+	   ONYX_REG_ADC_HPF_BYPASS,
+	   ONYX_HPF_DISABLE,
+	   FLAG_POLARITY_INVERT);
+SINGLE_BIT(dm12,
+	   MIXER,
+	   "Digital De-Emphasis",
+	   ONYX_REG_DAC_DEEMPH,
+	   ONYX_DIGDEEMPH_CTRL,
+	   0);
+
+static int onyx_spdif_info(struct snd_kcontrol *kcontrol,
+			   struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	/* datasheet page 30, all others are 0 */
+	ucontrol->value.iec958.status[0] = 0x3e;
+	ucontrol->value.iec958.status[1] = 0xff;
+
+	ucontrol->value.iec958.status[3] = 0x3f;
+	ucontrol->value.iec958.status[4] = 0x0f;
+	
+	return 0;
+}
+
+static struct snd_kcontrol_new onyx_spdif_mask = {
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+	.info =		onyx_spdif_info,
+	.get =		onyx_spdif_mask_get,
+};
+
+static int onyx_spdif_get(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
+	ucontrol->value.iec958.status[0] = v & 0x3e;
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v);
+	ucontrol->value.iec958.status[1] = v;
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
+	ucontrol->value.iec958.status[3] = v & 0x3f;
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+	ucontrol->value.iec958.status[4] = v & 0x0f;
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+static int onyx_spdif_put(struct snd_kcontrol *kcontrol,
+			  struct snd_ctl_elem_value *ucontrol)
+{
+	struct onyx *onyx = snd_kcontrol_chip(kcontrol);
+	u8 v;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v);
+	v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e);
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v);
+
+	v = ucontrol->value.iec958.status[1];
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v);
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v);
+	v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f);
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v);
+
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+	v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f);
+	onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
+	mutex_unlock(&onyx->mutex);
+
+	return 1;
+}
+
+static struct snd_kcontrol_new onyx_spdif_ctrl = {
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+	.info =		onyx_spdif_info,
+	.get =		onyx_spdif_get,
+	.put =		onyx_spdif_put,
+};
+
+/* our registers */
+
+static u8 register_map[] = {
+	ONYX_REG_DAC_ATTEN_LEFT,
+	ONYX_REG_DAC_ATTEN_RIGHT,
+	ONYX_REG_CONTROL,
+	ONYX_REG_DAC_CONTROL,
+	ONYX_REG_DAC_DEEMPH,
+	ONYX_REG_DAC_FILTER,
+	ONYX_REG_DAC_OUTPHASE,
+	ONYX_REG_ADC_CONTROL,
+	ONYX_REG_ADC_HPF_BYPASS,
+	ONYX_REG_DIG_INFO1,
+	ONYX_REG_DIG_INFO2,
+	ONYX_REG_DIG_INFO3,
+	ONYX_REG_DIG_INFO4
+};
+
+static u8 initial_values[ARRAY_SIZE(register_map)] = {
+	0x80, 0x80, /* muted */
+	ONYX_MRST | ONYX_SRST, /* but handled specially! */
+	ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
+	0, /* no deemphasis */
+	ONYX_DAC_FILTER_ALWAYS,
+	ONYX_OUTPHASE_INVERTED,
+	(-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/
+	ONYX_ADC_HPF_ALWAYS,
+	(1<<2),	/* pcm audio */
+	2,	/* category: pcm coder */
+	0,	/* sampling frequency 44.1 kHz, clock accuracy level II */
+	1	/* 24 bit depth */
+};
+
+/* reset registers of chip, either to initial or to previous values */
+static int onyx_register_init(struct onyx *onyx)
+{
+	int i;
+	u8 val;
+	u8 regs[sizeof(initial_values)];
+
+	if (!onyx->initialised) {
+		memcpy(regs, initial_values, sizeof(initial_values));
+		if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val))
+			return -1;
+		val &= ~ONYX_SILICONVERSION;
+		val |= initial_values[3];
+		regs[3] = val;
+	} else {
+		for (i=0; i<sizeof(register_map); i++)
+			regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER];
+	}
+
+	for (i=0; i<sizeof(register_map); i++) {
+		if (onyx_write_register(onyx, register_map[i], regs[i]))
+			return -1;
+	}
+	onyx->initialised = 1;
+	return 0;
+}
+
+static struct transfer_info onyx_transfers[] = {
+	/* this is first so we can skip it if no input is present...
+	 * No hardware exists with that, but it's here as an example
+	 * of what to do :) */
+	{
+		/* analog input */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.transfer_in = 1,
+		.must_be_clock_source = 0,
+		.tag = 0,
+	},
+	{
+		/* if analog and digital are currently off, anything should go,
+		 * so this entry describes everything we can do... */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+			   | SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+#endif
+		,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.tag = 0,
+	},
+	{
+		/* analog output */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.transfer_in = 0,
+		.must_be_clock_source = 0,
+		.tag = 1,
+	},
+	{
+		/* digital pcm output, also possible for analog out */
+		.formats = SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_32000 |
+			 SNDRV_PCM_RATE_44100 |
+			 SNDRV_PCM_RATE_48000,
+		.transfer_in = 0,
+		.must_be_clock_source = 0,
+		.tag = 2,
+	},
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+Once alsa gets supports for this kind of thing we can add it...
+	{
+		/* digital compressed output */
+		.formats =  SNDRV_PCM_FMTBIT_COMPRESSED_16BE,
+		.rates = SNDRV_PCM_RATE_32000 |
+			 SNDRV_PCM_RATE_44100 |
+			 SNDRV_PCM_RATE_48000,
+		.tag = 2,
+	},
+#endif
+	{}
+};
+
+static int onyx_usable(struct codec_info_item *cii,
+		       struct transfer_info *ti,
+		       struct transfer_info *out)
+{
+	u8 v;
+	struct onyx *onyx = cii->codec_data;
+	int spdif_enabled, analog_enabled;
+
+	mutex_lock(&onyx->mutex);
+	onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+	spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
+	onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+	analog_enabled = 
+		(v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
+		 != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
+	mutex_unlock(&onyx->mutex);
+
+	switch (ti->tag) {
+	case 0: return 1;
+	case 1:	return analog_enabled;
+	case 2: return spdif_enabled;
+	}
+	return 1;
+}
+
+static int onyx_prepare(struct codec_info_item *cii,
+			struct bus_info *bi,
+			struct snd_pcm_substream *substream)
+{
+	u8 v;
+	struct onyx *onyx = cii->codec_data;
+	int err = -EBUSY;
+
+	mutex_lock(&onyx->mutex);
+
+#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE
+	if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) {
+		/* mute and lock analog output */
+		onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
+		if (onyx_write_register(onyx
+					ONYX_REG_DAC_CONTROL,
+					v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT))
+			goto out_unlock;
+		onyx->analog_locked = 1;
+		err = 0;
+		goto out_unlock;
+	}
+#endif
+	switch (substream->runtime->rate) {
+	case 32000:
+	case 44100:
+	case 48000:
+		/* these rates are ok for all outputs */
+		/* FIXME: program spdif channel control bits here so that
+		 *	  userspace doesn't have to if it only plays pcm! */
+		err = 0;
+		goto out_unlock;
+	default:
+		/* got some rate that the digital output can't do,
+		 * so disable and lock it */
+		onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v);
+		if (onyx_write_register(onyx,
+					ONYX_REG_DIG_INFO4,
+					v & ~ONYX_SPDIF_ENABLE))
+			goto out_unlock;
+		onyx->spdif_locked = 1;
+		err = 0;
+		goto out_unlock;
+	}
+
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return err;
+}
+
+static int onyx_open(struct codec_info_item *cii,
+		     struct snd_pcm_substream *substream)
+{
+	struct onyx *onyx = cii->codec_data;
+
+	mutex_lock(&onyx->mutex);
+	onyx->open_count++;
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+static int onyx_close(struct codec_info_item *cii,
+		      struct snd_pcm_substream *substream)
+{
+	struct onyx *onyx = cii->codec_data;
+
+	mutex_lock(&onyx->mutex);
+	onyx->open_count--;
+	if (!onyx->open_count)
+		onyx->spdif_locked = onyx->analog_locked = 0;
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+static int onyx_switch_clock(struct codec_info_item *cii,
+			     enum clock_switch what)
+{
+	struct onyx *onyx = cii->codec_data;
+
+	mutex_lock(&onyx->mutex);
+	/* this *MUST* be more elaborate later... */
+	switch (what) {
+	case CLOCK_SWITCH_PREPARE_SLAVE:
+		onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio);
+		break;
+	case CLOCK_SWITCH_SLAVE:
+		onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio);
+		break;
+	default: /* silence warning */
+		break;
+	}
+	mutex_unlock(&onyx->mutex);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int onyx_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+	struct onyx *onyx = cii->codec_data;
+	u8 v;
+	int err = -ENXIO;
+
+	mutex_lock(&onyx->mutex);
+	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
+		goto out_unlock;
+	onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV);
+	/* Apple does a sleep here but the datasheet says to do it on resume */
+	err = 0;
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return err;
+}
+
+static int onyx_resume(struct codec_info_item *cii)
+{
+	struct onyx *onyx = cii->codec_data;
+	u8 v;
+	int err = -ENXIO;
+
+	mutex_lock(&onyx->mutex);
+	/* take codec out of suspend */
+	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
+		goto out_unlock;
+	onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
+	/* FIXME: should divide by sample rate, but 8k is the lowest we go */
+	msleep(2205000/8000);
+	/* reset all values */
+	onyx_register_init(onyx);
+	err = 0;
+ out_unlock:
+	mutex_unlock(&onyx->mutex);
+
+	return err;
+}
+
+#endif /* CONFIG_PM */
+
+static struct codec_info onyx_codec_info = {
+	.transfers = onyx_transfers,
+	.sysclock_factor = 256,
+	.bus_factor = 64,
+	.owner = THIS_MODULE,
+	.usable = onyx_usable,
+	.prepare = onyx_prepare,
+	.open = onyx_open,
+	.close = onyx_close,
+	.switch_clock = onyx_switch_clock,
+#ifdef CONFIG_PM
+	.suspend = onyx_suspend,
+	.resume = onyx_resume,
+#endif
+};
+
+static int onyx_init_codec(struct aoa_codec *codec)
+{
+	struct onyx *onyx = codec_to_onyx(codec);
+	struct snd_kcontrol *ctl;
+	struct codec_info *ci = &onyx_codec_info;
+	u8 v;
+	int err;
+
+	if (!onyx->codec.gpio || !onyx->codec.gpio->methods) {
+		printk(KERN_ERR PFX "gpios not assigned!!\n");
+		return -EINVAL;
+	}
+
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
+	msleep(1);
+	onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
+	msleep(1);
+	
+	if (onyx_register_init(onyx)) {
+		printk(KERN_ERR PFX "failed to initialise onyx registers\n");
+		return -ENODEV;
+	}
+
+	if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) {
+		printk(KERN_ERR PFX "failed to create onyx snd device!\n");
+		return -ENODEV;
+	}
+
+	/* nothing connected? what a joke! */
+	if ((onyx->codec.connected & 0xF) == 0)
+		return -ENOTCONN;
+
+	/* if no inputs are present... */
+	if ((onyx->codec.connected & 0xC) == 0) {
+		if (!onyx->codec_info)
+			onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
+		if (!onyx->codec_info)
+			return -ENOMEM;
+		ci = onyx->codec_info;
+		*ci = onyx_codec_info;
+		ci->transfers++;
+	}
+
+	/* if no outputs are present... */
+	if ((onyx->codec.connected & 3) == 0) {
+		if (!onyx->codec_info)
+			onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL);
+		if (!onyx->codec_info)
+			return -ENOMEM;
+		ci = onyx->codec_info;
+		/* this is fine as there have to be inputs
+		 * if we end up in this part of the code */
+		*ci = onyx_codec_info;
+		ci->transfers[1].formats = 0;
+	}
+
+	if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev,
+						   aoa_get_card(),
+						   ci, onyx)) {
+		printk(KERN_ERR PFX "error creating onyx pcm\n");
+		return -ENODEV;
+	}
+#define ADDCTL(n)							\
+	do {								\
+		ctl = snd_ctl_new1(&n, onyx);				\
+		if (ctl) {						\
+			ctl->id.device =				\
+				onyx->codec.soundbus_dev->pcm->device;	\
+			err = aoa_snd_ctl_add(ctl);			\
+			if (err)					\
+				goto error;				\
+		}							\
+	} while (0)
+
+	if (onyx->codec.soundbus_dev->pcm) {
+		/* give the user appropriate controls
+		 * depending on what inputs are connected */
+		if ((onyx->codec.connected & 0xC) == 0xC)
+			ADDCTL(capture_source_control);
+		else if (onyx->codec.connected & 4)
+			onyx_set_capture_source(onyx, 0);
+		else
+			onyx_set_capture_source(onyx, 1);
+		if (onyx->codec.connected & 0xC)
+			ADDCTL(inputgain_control);
+
+		/* depending on what output is connected,
+		 * give the user appropriate controls */
+		if (onyx->codec.connected & 1) {
+			ADDCTL(volume_control);
+			ADDCTL(mute_control);
+			ADDCTL(ovr1_control);
+			ADDCTL(flt0_control);
+			ADDCTL(hpf_control);
+			ADDCTL(dm12_control);
+			/* spdif control defaults to off */
+		}
+		if (onyx->codec.connected & 2) {
+			ADDCTL(onyx_spdif_mask);
+			ADDCTL(onyx_spdif_ctrl);
+		}
+		if ((onyx->codec.connected & 3) == 3)
+			ADDCTL(spdif_control);
+		/* if only S/PDIF is connected, enable it unconditionally */
+		if ((onyx->codec.connected & 3) == 2) {
+			onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
+			v |= ONYX_SPDIF_ENABLE;
+			onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v);
+		}
+	}
+#undef ADDCTL
+	printk(KERN_INFO PFX "attached to onyx codec via i2c\n");
+
+	return 0;
+ error:
+	onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
+	snd_device_free(aoa_get_card(), onyx);
+	return err;
+}
+
+static void onyx_exit_codec(struct aoa_codec *codec)
+{
+	struct onyx *onyx = codec_to_onyx(codec);
+
+	if (!onyx->codec.soundbus_dev) {
+		printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n");
+		return;
+	}
+	onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
+}
+
+static struct i2c_driver onyx_driver;
+
+static int onyx_create(struct i2c_adapter *adapter,
+		       struct device_node *node,
+		       int addr)
+{
+	struct onyx *onyx;
+	u8 dummy;
+
+	onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL);
+
+	if (!onyx)
+		return -ENOMEM;
+
+	mutex_init(&onyx->mutex);
+	onyx->i2c.driver = &onyx_driver;
+	onyx->i2c.adapter = adapter;
+	onyx->i2c.addr = addr & 0x7f;
+	strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1);
+
+	if (i2c_attach_client(&onyx->i2c)) {
+		printk(KERN_ERR PFX "failed to attach to i2c\n");
+		goto fail;
+	}
+
+	/* we try to read from register ONYX_REG_CONTROL
+	 * to check if the codec is present */
+	if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) {
+		i2c_detach_client(&onyx->i2c);
+		printk(KERN_ERR PFX "failed to read control register\n");
+		goto fail;
+	}
+
+	strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1);
+	onyx->codec.owner = THIS_MODULE;
+	onyx->codec.init = onyx_init_codec;
+	onyx->codec.exit = onyx_exit_codec;
+	onyx->codec.node = of_node_get(node);
+
+	if (aoa_codec_register(&onyx->codec)) {
+		i2c_detach_client(&onyx->i2c);
+		goto fail;
+	}
+	printk(KERN_DEBUG PFX "created and attached onyx instance\n");
+	return 0;
+ fail:
+	kfree(onyx);
+	return -EINVAL;
+}
+
+static int onyx_i2c_attach(struct i2c_adapter *adapter)
+{
+	struct device_node *busnode, *dev = NULL;
+	struct pmac_i2c_bus *bus;
+
+	bus = pmac_i2c_adapter_to_bus(adapter);
+	if (bus == NULL)
+		return -ENODEV;
+	busnode = pmac_i2c_get_bus_node(bus);
+
+	while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+		if (device_is_compatible(dev, "pcm3052")) {
+			u32 *addr;
+			printk(KERN_DEBUG PFX "found pcm3052\n");
+			addr = (u32 *) get_property(dev, "reg", NULL);
+			if (!addr)
+				return -ENODEV;
+			return onyx_create(adapter, dev, (*addr)>>1);
+		}
+	}
+
+	/* if that didn't work, try desperate mode for older
+	 * machines that have stuff missing from the device tree */
+	
+	if (!device_is_compatible(busnode, "k2-i2c"))
+		return -ENODEV;
+
+	printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n");
+	/* probe both possible addresses for the onyx chip */
+	if (onyx_create(adapter, NULL, 0x46) == 0)
+		return 0;
+	return onyx_create(adapter, NULL, 0x47);
+}
+
+static int onyx_i2c_detach(struct i2c_client *client)
+{
+	struct onyx *onyx = container_of(client, struct onyx, i2c);
+	int err;
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+	aoa_codec_unregister(&onyx->codec);
+	of_node_put(onyx->codec.node);
+	if (onyx->codec_info)
+		kfree(onyx->codec_info);
+	kfree(onyx);
+	return 0;
+}
+
+static struct i2c_driver onyx_driver = {
+	.driver = {
+		.name = "aoa_codec_onyx",
+		.owner = THIS_MODULE,
+	},
+	.attach_adapter = onyx_i2c_attach,
+	.detach_client = onyx_i2c_detach,
+};
+
+static int __init onyx_init(void)
+{
+	return i2c_add_driver(&onyx_driver);
+}
+
+static void __exit onyx_exit(void)
+{
+	i2c_del_driver(&onyx_driver);
+}
+
+module_init(onyx_init);
+module_exit(onyx_exit);
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h
new file mode 100644
index 0000000..aeedda7
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.h
@@ -0,0 +1,76 @@
+/*
+ * Apple Onboard Audio driver for Onyx codec (header)
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __SND_AOA_CODEC_ONYX_H
+#define __SND_AOA_CODEC_ONYX_H
+#include <stddef.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/pmac_low_i2c.h>
+#include <asm/prom.h>
+
+/* PCM3052 register definitions */
+
+/* the attenuation registers take values from
+ * -1 (0dB) to -127 (-63.0 dB) or others (muted) */
+#define ONYX_REG_DAC_ATTEN_LEFT		65
+#define FIRSTREGISTER			ONYX_REG_DAC_ATTEN_LEFT
+#define ONYX_REG_DAC_ATTEN_RIGHT	66
+
+#define ONYX_REG_CONTROL		67
+#	define ONYX_MRST		(1<<7)
+#	define ONYX_SRST		(1<<6)
+#	define ONYX_ADPSV		(1<<5)
+#	define ONYX_DAPSV		(1<<4)
+#	define ONYX_SILICONVERSION	(1<<0)
+/* all others reserved */
+
+#define ONYX_REG_DAC_CONTROL		68
+#	define ONYX_OVR1		(1<<6)
+#	define ONYX_MUTE_RIGHT		(1<<1)
+#	define ONYX_MUTE_LEFT		(1<<0)
+
+#define ONYX_REG_DAC_DEEMPH		69
+#	define ONYX_DIGDEEMPH_SHIFT	5
+#	define ONYX_DIGDEEMPH_MASK	(3<<ONYX_DIGDEEMPH_SHIFT)
+#	define ONYX_DIGDEEMPH_CTRL	(1<<4)
+
+#define ONYX_REG_DAC_FILTER		70
+#	define ONYX_ROLLOFF_FAST	(1<<5)
+#	define ONYX_DAC_FILTER_ALWAYS	(1<<2)
+
+#define	ONYX_REG_DAC_OUTPHASE		71
+#	define ONYX_OUTPHASE_INVERTED	(1<<0)
+
+#define ONYX_REG_ADC_CONTROL		72
+#	define ONYX_ADC_INPUT_MIC	(1<<5)
+/* 8 + input gain in dB, valid range for input gain is -4 .. 20 dB */
+#	define ONYX_ADC_PGA_GAIN_MASK	0x1f
+
+#define ONYX_REG_ADC_HPF_BYPASS		75
+#	define ONYX_HPF_DISABLE		(1<<3)
+#	define ONYX_ADC_HPF_ALWAYS	(1<<2)
+
+#define ONYX_REG_DIG_INFO1		77
+#	define ONYX_MASK_DIN_TO_BPZ	(1<<7)
+/* bits 1-5 control channel bits 1-5 */
+#	define ONYX_DIGOUT_DISABLE	(1<<0)
+
+#define ONYX_REG_DIG_INFO2		78
+/* controls channel bits 8-15 */
+
+#define ONYX_REG_DIG_INFO3		79
+/* control channel bits 24-29, high 2 bits reserved */
+
+#define ONYX_REG_DIG_INFO4		80
+#	define ONYX_VALIDL		(1<<7)
+#	define ONYX_VALIDR		(1<<6)
+#	define ONYX_SPDIF_ENABLE	(1<<5)
+/* lower 4 bits control bits 32-35 of channel control and word length */
+#	define ONYX_WORDLEN_MASK	(0xF)
+
+#endif /* __SND_AOA_CODEC_ONYX_H */
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
new file mode 100644
index 0000000..4cfa675
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
@@ -0,0 +1,209 @@
+/*
+ This is the program used to generate below table.
+
+#include <stdio.h>
+#include <math.h>
+int main() {
+  int dB2;
+  printf("/" "* This file is only included exactly once!\n");
+  printf(" *\n");
+  printf(" * If they'd only tell us that generating this table was\n");
+  printf(" * as easy as calculating\n");
+  printf(" *      hwvalue = 1048576.0*exp(0.057564628*dB*2)\n");
+  printf(" * :) *" "/\n");
+  printf("static int tas_gaintable[] = {\n");
+  printf("	0x000000, /" "* -infinity dB *" "/\n");
+  for (dB2=-140;dB2<=36;dB2++)
+    printf("	0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0);
+  printf("};\n\n");
+}
+
+*/
+
+/* This file is only included exactly once!
+ *
+ * If they'd only tell us that generating this table was
+ * as easy as calculating
+ *      hwvalue = 1048576.0*exp(0.057564628*dB*2)
+ * :) */
+static int tas_gaintable[] = {
+	0x000000, /* -infinity dB */
+	0x00014b, /* -70.0 dB */
+	0x00015f, /* -69.5 dB */
+	0x000174, /* -69.0 dB */
+	0x00018a, /* -68.5 dB */
+	0x0001a1, /* -68.0 dB */
+	0x0001ba, /* -67.5 dB */
+	0x0001d4, /* -67.0 dB */
+	0x0001f0, /* -66.5 dB */
+	0x00020d, /* -66.0 dB */
+	0x00022c, /* -65.5 dB */
+	0x00024d, /* -65.0 dB */
+	0x000270, /* -64.5 dB */
+	0x000295, /* -64.0 dB */
+	0x0002bc, /* -63.5 dB */
+	0x0002e6, /* -63.0 dB */
+	0x000312, /* -62.5 dB */
+	0x000340, /* -62.0 dB */
+	0x000372, /* -61.5 dB */
+	0x0003a6, /* -61.0 dB */
+	0x0003dd, /* -60.5 dB */
+	0x000418, /* -60.0 dB */
+	0x000456, /* -59.5 dB */
+	0x000498, /* -59.0 dB */
+	0x0004de, /* -58.5 dB */
+	0x000528, /* -58.0 dB */
+	0x000576, /* -57.5 dB */
+	0x0005c9, /* -57.0 dB */
+	0x000620, /* -56.5 dB */
+	0x00067d, /* -56.0 dB */
+	0x0006e0, /* -55.5 dB */
+	0x000748, /* -55.0 dB */
+	0x0007b7, /* -54.5 dB */
+	0x00082c, /* -54.0 dB */
+	0x0008a8, /* -53.5 dB */
+	0x00092b, /* -53.0 dB */
+	0x0009b6, /* -52.5 dB */
+	0x000a49, /* -52.0 dB */
+	0x000ae5, /* -51.5 dB */
+	0x000b8b, /* -51.0 dB */
+	0x000c3a, /* -50.5 dB */
+	0x000cf3, /* -50.0 dB */
+	0x000db8, /* -49.5 dB */
+	0x000e88, /* -49.0 dB */
+	0x000f64, /* -48.5 dB */
+	0x00104e, /* -48.0 dB */
+	0x001145, /* -47.5 dB */
+	0x00124b, /* -47.0 dB */
+	0x001361, /* -46.5 dB */
+	0x001487, /* -46.0 dB */
+	0x0015be, /* -45.5 dB */
+	0x001708, /* -45.0 dB */
+	0x001865, /* -44.5 dB */
+	0x0019d8, /* -44.0 dB */
+	0x001b60, /* -43.5 dB */
+	0x001cff, /* -43.0 dB */
+	0x001eb7, /* -42.5 dB */
+	0x002089, /* -42.0 dB */
+	0x002276, /* -41.5 dB */
+	0x002481, /* -41.0 dB */
+	0x0026ab, /* -40.5 dB */
+	0x0028f5, /* -40.0 dB */
+	0x002b63, /* -39.5 dB */
+	0x002df5, /* -39.0 dB */
+	0x0030ae, /* -38.5 dB */
+	0x003390, /* -38.0 dB */
+	0x00369e, /* -37.5 dB */
+	0x0039db, /* -37.0 dB */
+	0x003d49, /* -36.5 dB */
+	0x0040ea, /* -36.0 dB */
+	0x0044c3, /* -35.5 dB */
+	0x0048d6, /* -35.0 dB */
+	0x004d27, /* -34.5 dB */
+	0x0051b9, /* -34.0 dB */
+	0x005691, /* -33.5 dB */
+	0x005bb2, /* -33.0 dB */
+	0x006121, /* -32.5 dB */
+	0x0066e3, /* -32.0 dB */
+	0x006cfb, /* -31.5 dB */
+	0x007370, /* -31.0 dB */
+	0x007a48, /* -30.5 dB */
+	0x008186, /* -30.0 dB */
+	0x008933, /* -29.5 dB */
+	0x009154, /* -29.0 dB */
+	0x0099f1, /* -28.5 dB */
+	0x00a310, /* -28.0 dB */
+	0x00acba, /* -27.5 dB */
+	0x00b6f6, /* -27.0 dB */
+	0x00c1cd, /* -26.5 dB */
+	0x00cd49, /* -26.0 dB */
+	0x00d973, /* -25.5 dB */
+	0x00e655, /* -25.0 dB */
+	0x00f3fb, /* -24.5 dB */
+	0x010270, /* -24.0 dB */
+	0x0111c0, /* -23.5 dB */
+	0x0121f9, /* -23.0 dB */
+	0x013328, /* -22.5 dB */
+	0x01455b, /* -22.0 dB */
+	0x0158a2, /* -21.5 dB */
+	0x016d0e, /* -21.0 dB */
+	0x0182af, /* -20.5 dB */
+	0x019999, /* -20.0 dB */
+	0x01b1de, /* -19.5 dB */
+	0x01cb94, /* -19.0 dB */
+	0x01e6cf, /* -18.5 dB */
+	0x0203a7, /* -18.0 dB */
+	0x022235, /* -17.5 dB */
+	0x024293, /* -17.0 dB */
+	0x0264db, /* -16.5 dB */
+	0x02892c, /* -16.0 dB */
+	0x02afa3, /* -15.5 dB */
+	0x02d862, /* -15.0 dB */
+	0x03038a, /* -14.5 dB */
+	0x033142, /* -14.0 dB */
+	0x0361af, /* -13.5 dB */
+	0x0394fa, /* -13.0 dB */
+	0x03cb50, /* -12.5 dB */
+	0x0404de, /* -12.0 dB */
+	0x0441d5, /* -11.5 dB */
+	0x048268, /* -11.0 dB */
+	0x04c6d0, /* -10.5 dB */
+	0x050f44, /* -10.0 dB */
+	0x055c04, /* -9.5 dB */
+	0x05ad50, /* -9.0 dB */
+	0x06036e, /* -8.5 dB */
+	0x065ea5, /* -8.0 dB */
+	0x06bf44, /* -7.5 dB */
+	0x07259d, /* -7.0 dB */
+	0x079207, /* -6.5 dB */
+	0x0804dc, /* -6.0 dB */
+	0x087e80, /* -5.5 dB */
+	0x08ff59, /* -5.0 dB */
+	0x0987d5, /* -4.5 dB */
+	0x0a1866, /* -4.0 dB */
+	0x0ab189, /* -3.5 dB */
+	0x0b53be, /* -3.0 dB */
+	0x0bff91, /* -2.5 dB */
+	0x0cb591, /* -2.0 dB */
+	0x0d765a, /* -1.5 dB */
+	0x0e4290, /* -1.0 dB */
+	0x0f1adf, /* -0.5 dB */
+	0x100000, /* 0.0 dB */
+	0x10f2b4, /* 0.5 dB */
+	0x11f3c9, /* 1.0 dB */
+	0x13041a, /* 1.5 dB */
+	0x14248e, /* 2.0 dB */
+	0x15561a, /* 2.5 dB */
+	0x1699c0, /* 3.0 dB */
+	0x17f094, /* 3.5 dB */
+	0x195bb8, /* 4.0 dB */
+	0x1adc61, /* 4.5 dB */
+	0x1c73d5, /* 5.0 dB */
+	0x1e236d, /* 5.5 dB */
+	0x1fec98, /* 6.0 dB */
+	0x21d0d9, /* 6.5 dB */
+	0x23d1cd, /* 7.0 dB */
+	0x25f125, /* 7.5 dB */
+	0x2830af, /* 8.0 dB */
+	0x2a9254, /* 8.5 dB */
+	0x2d1818, /* 9.0 dB */
+	0x2fc420, /* 9.5 dB */
+	0x3298b0, /* 10.0 dB */
+	0x35982f, /* 10.5 dB */
+	0x38c528, /* 11.0 dB */
+	0x3c224c, /* 11.5 dB */
+	0x3fb278, /* 12.0 dB */
+	0x4378b0, /* 12.5 dB */
+	0x477829, /* 13.0 dB */
+	0x4bb446, /* 13.5 dB */
+	0x5030a1, /* 14.0 dB */
+	0x54f106, /* 14.5 dB */
+	0x59f980, /* 15.0 dB */
+	0x5f4e52, /* 15.5 dB */
+	0x64f403, /* 16.0 dB */
+	0x6aef5e, /* 16.5 dB */
+	0x714575, /* 17.0 dB */
+	0x77fbaa, /* 17.5 dB */
+	0x7f17af, /* 18.0 dB */
+};
+
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
new file mode 100644
index 0000000..2e39ff6
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -0,0 +1,654 @@
+/*
+ * Apple Onboard Audio driver for tas codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ * Open questions:
+ *  - How to distinguish between 3004 and versions?
+ *
+ * FIXMEs:
+ *  - This codec driver doesn't honour the 'connected'
+ *    property of the aoa_codec struct, hence if
+ *    it is used in machines where not everything is
+ *    connected it will display wrong mixer elements.
+ *  - Driver assumes that the microphone is always
+ *    monaureal and connected to the right channel of
+ *    the input. This should also be a codec-dependent
+ *    flag, maybe the codec should have 3 different
+ *    bits for the three different possibilities how
+ *    it can be hooked up...
+ *    But as long as I don't see any hardware hooked
+ *    up that way...
+ *  - As Apple notes in their code, the tas3004 seems
+ *    to delay the right channel by one sample. You can
+ *    see this when for example recording stereo in
+ *    audacity, or recording the tas output via cable
+ *    on another machine (use a sinus generator or so).
+ *    I tried programming the BiQuads but couldn't
+ *    make the delay work, maybe someone can read the
+ *    datasheet and fix it. The relevant Apple comment
+ *    is in AppleTAS3004Audio.cpp lines 1637 ff. Note
+ *    that their comment describing how they program
+ *    the filters sucks...
+ *
+ * Other things:
+ *  - this should actually register *two* aoa_codec
+ *    structs since it has two inputs. Then it must
+ *    use the prepare callback to forbid running the
+ *    secondary output on a different clock.
+ *    Also, whatever bus knows how to do this must
+ *    provide two soundbus_dev devices and the fabric
+ *    must be able to link them correctly.
+ *
+ *    I don't even know if Apple ever uses the second
+ *    port on the tas3004 though, I don't think their
+ *    i2s controllers can even do it. OTOH, they all
+ *    derive the clocks from common clocks, so it
+ *    might just be possible. The framework allows the
+ *    codec to refine the transfer_info items in the
+ *    usable callback, so we can simply remove the
+ *    rates the second instance is not using when it
+ *    actually is in use.
+ *    Maybe we'll need to make the sound busses have
+ *    a 'clock group id' value so the codec can
+ *    determine if the two outputs can be driven at
+ *    the same time. But that is likely overkill, up
+ *    to the fabric to not link them up incorrectly,
+ *    and up to the hardware designer to not wire
+ *    them up in some weird unusable way.
+ */
+#include <stddef.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <asm/pmac_low_i2c.h>
+#include <asm/prom.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("tas codec driver for snd-aoa");
+
+#include "snd-aoa-codec-tas.h"
+#include "snd-aoa-codec-tas-gain-table.h"
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+
+#define PFX "snd-aoa-codec-tas: "
+
+struct tas {
+	struct aoa_codec	codec;
+	struct i2c_client	i2c;
+	u32			muted_l:1, muted_r:1,
+				controls_created:1;
+	u8			cached_volume_l, cached_volume_r;
+	u8			mixer_l[3], mixer_r[3];
+	u8			acr;
+};
+
+static struct tas *codec_to_tas(struct aoa_codec *codec)
+{
+	return container_of(codec, struct tas, codec);
+}
+
+static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data)
+{
+	if (len == 1)
+		return i2c_smbus_write_byte_data(&tas->i2c, reg, *data);
+	else
+		return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data);
+}
+
+static void tas_set_volume(struct tas *tas)
+{
+	u8 block[6];
+	int tmp;
+	u8 left, right;
+
+	left = tas->cached_volume_l;
+	right = tas->cached_volume_r;
+
+	if (left > 177) left = 177;
+	if (right > 177) right = 177;
+
+	if (tas->muted_l) left = 0;
+	if (tas->muted_r) right = 0;
+
+	/* analysing the volume and mixer tables shows
+	 * that they are similar enough when we shift
+	 * the mixer table down by 4 bits. The error
+	 * is miniscule, in just one item the error
+	 * is 1, at a value of 0x07f17b (mixer table
+	 * value is 0x07f17a) */
+	tmp = tas_gaintable[left];
+	block[0] = tmp>>20;
+	block[1] = tmp>>12;
+	block[2] = tmp>>4;
+	tmp = tas_gaintable[right];
+	block[3] = tmp>>20;
+	block[4] = tmp>>12;
+	block[5] = tmp>>4;
+	tas_write_reg(tas, TAS_REG_VOL, 6, block);
+}
+
+static void tas_set_mixer(struct tas *tas)
+{
+	u8 block[9];
+	int tmp, i;
+	u8 val;
+
+	for (i=0;i<3;i++) {
+		val = tas->mixer_l[i];
+		if (val > 177) val = 177;
+		tmp = tas_gaintable[val];
+		block[3*i+0] = tmp>>16;
+		block[3*i+1] = tmp>>8;
+		block[3*i+2] = tmp;
+	}
+	tas_write_reg(tas, TAS_REG_LMIX, 9, block);
+
+	for (i=0;i<3;i++) {
+		val = tas->mixer_r[i];
+		if (val > 177) val = 177;
+		tmp = tas_gaintable[val];
+		block[3*i+0] = tmp>>16;
+		block[3*i+1] = tmp>>8;
+		block[3*i+2] = tmp;
+	}
+	tas_write_reg(tas, TAS_REG_RMIX, 9, block);
+}
+
+/* alsa stuff */
+
+static int tas_dev_register(struct snd_device *dev)
+{
+	return 0;
+}
+
+static struct snd_device_ops ops = {
+	.dev_register = tas_dev_register,
+};
+
+static int tas_snd_vol_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 177;
+	return 0;
+}
+
+static int tas_snd_vol_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = tas->cached_volume_l;
+	ucontrol->value.integer.value[1] = tas->cached_volume_r;
+	return 0;
+}
+
+static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	if (tas->cached_volume_l == ucontrol->value.integer.value[0]
+	 && tas->cached_volume_r == ucontrol->value.integer.value[1])
+		return 0;
+
+	tas->cached_volume_l = ucontrol->value.integer.value[0];
+	tas->cached_volume_r = ucontrol->value.integer.value[1];
+	tas_set_volume(tas);
+	return 1;
+}
+
+static struct snd_kcontrol_new volume_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Volume",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_vol_info,
+	.get = tas_snd_vol_get,
+	.put = tas_snd_vol_put,
+};
+
+static int tas_snd_mute_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int tas_snd_mute_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = !tas->muted_l;
+	ucontrol->value.integer.value[1] = !tas->muted_r;
+	return 0;
+}
+
+static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	if (tas->muted_l == !ucontrol->value.integer.value[0]
+	 && tas->muted_r == !ucontrol->value.integer.value[1])
+		return 0;
+
+	tas->muted_l = !ucontrol->value.integer.value[0];
+	tas->muted_r = !ucontrol->value.integer.value[1];
+	tas_set_volume(tas);
+	return 1;
+}
+
+static struct snd_kcontrol_new mute_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Master Playback Switch",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_mute_info,
+	.get = tas_snd_mute_get,
+	.put = tas_snd_mute_put,
+};
+
+static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 177;
+	return 0;
+}
+
+static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+	int idx = kcontrol->private_value;
+
+	ucontrol->value.integer.value[0] = tas->mixer_l[idx];
+	ucontrol->value.integer.value[1] = tas->mixer_r[idx];
+
+	return 0;
+}
+
+static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+	int idx = kcontrol->private_value;
+
+	if (tas->mixer_l[idx] == ucontrol->value.integer.value[0]
+	 && tas->mixer_r[idx] == ucontrol->value.integer.value[1])
+		return 0;
+
+	tas->mixer_l[idx] = ucontrol->value.integer.value[0];
+	tas->mixer_r[idx] = ucontrol->value.integer.value[1];
+
+	tas_set_mixer(tas);
+	return 1;
+}
+
+#define MIXER_CONTROL(n,descr,idx)			\
+static struct snd_kcontrol_new n##_control = {		\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,		\
+	.name = descr " Playback Volume",		\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,	\
+	.info = tas_snd_mixer_info,			\
+	.get = tas_snd_mixer_get,			\
+	.put = tas_snd_mixer_put,			\
+	.private_value = idx,				\
+}
+
+MIXER_CONTROL(pcm1, "PCM1", 0);
+MIXER_CONTROL(monitor, "Monitor", 2);
+
+static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[] = { "Line-In", "Microphone" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B);
+	return 0;
+}
+
+static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	struct tas *tas = snd_kcontrol_chip(kcontrol);
+	int oldacr = tas->acr;
+
+	tas->acr &= ~TAS_ACR_INPUT_B;
+	if (ucontrol->value.enumerated.item[0])
+		tas->acr |= TAS_ACR_INPUT_B;
+	if (oldacr == tas->acr)
+		return 0;
+	tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
+	return 1;
+}
+
+static struct snd_kcontrol_new capture_source_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	/* If we name this 'Input Source', it properly shows up in
+	 * alsamixer as a selection, * but it's shown under the
+	 * 'Playback' category.
+	 * If I name it 'Capture Source', it shows up in strange
+	 * ways (two bools of which one can be selected at a
+	 * time) but at least it's shown in the 'Capture'
+	 * category.
+	 * I was told that this was due to backward compatibility,
+	 * but I don't understand then why the mangling is *not*
+	 * done when I name it "Input Source".....
+	 */
+	.name = "Capture Source",
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.info = tas_snd_capture_source_info,
+	.get = tas_snd_capture_source_get,
+	.put = tas_snd_capture_source_put,
+};
+
+
+static struct transfer_info tas_transfers[] = {
+	{
+		/* input */
+		.formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+		.transfer_in = 1,
+	},
+	{
+		/* output */
+		.formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
+		.transfer_in = 0,
+	},
+	{}
+};
+
+static int tas_usable(struct codec_info_item *cii,
+		      struct transfer_info *ti,
+		      struct transfer_info *out)
+{
+	return 1;
+}
+
+static int tas_reset_init(struct tas *tas)
+{
+	u8 tmp;
+	tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
+	msleep(1);
+	tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1);
+	msleep(1);
+	tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0);
+	msleep(1);
+
+	tas->acr &= ~TAS_ACR_ANALOG_PDOWN;
+	tas->acr |= TAS_ACR_B_MONAUREAL | TAS_ACR_B_MON_SEL_RIGHT;
+	if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr))
+		return -ENODEV;
+
+	tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT;
+	if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp))
+		return -ENODEV;
+
+	tmp = 0;
+	if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp))
+		return -ENODEV;
+
+	return 0;
+}
+
+/* we are controlled via i2c and assume that is always up
+ * If that wasn't the case, we'd have to suspend once
+ * our i2c device is suspended, and then take note of that! */
+static int tas_suspend(struct tas *tas)
+{
+	tas->acr |= TAS_ACR_ANALOG_PDOWN;
+	tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr);
+	return 0;
+}
+
+static int tas_resume(struct tas *tas)
+{
+	/* reset codec */
+	tas_reset_init(tas);
+	tas_set_volume(tas);
+	tas_set_mixer(tas);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int _tas_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+	return tas_suspend(cii->codec_data);
+}
+
+static int _tas_resume(struct codec_info_item *cii)
+{
+	return tas_resume(cii->codec_data);
+}
+#endif
+
+static struct codec_info tas_codec_info = {
+	.transfers = tas_transfers,
+	/* in theory, we can drive it at 512 too...
+	 * but so far the framework doesn't allow
+	 * for that and I don't see much point in it. */
+	.sysclock_factor = 256,
+	/* same here, could be 32 for just one 16 bit format */
+	.bus_factor = 64,
+	.owner = THIS_MODULE,
+	.usable = tas_usable,
+#ifdef CONFIG_PM
+	.suspend = _tas_suspend,
+	.resume = _tas_resume,
+#endif
+};
+
+static int tas_init_codec(struct aoa_codec *codec)
+{
+	struct tas *tas = codec_to_tas(codec);
+	int err;
+
+	if (!tas->codec.gpio || !tas->codec.gpio->methods) {
+		printk(KERN_ERR PFX "gpios not assigned!!\n");
+		return -EINVAL;
+	}
+
+	if (tas_reset_init(tas)) {
+		printk(KERN_ERR PFX "tas failed to initialise\n");
+		return -ENXIO;
+	}
+
+	if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev,
+						   aoa_get_card(),
+						   &tas_codec_info, tas)) {
+		printk(KERN_ERR PFX "error attaching tas to soundbus\n");
+		return -ENODEV;
+	}
+
+	if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) {
+		printk(KERN_ERR PFX "failed to create tas snd device!\n");
+		return -ENODEV;
+	}
+	err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas));
+	if (err)
+		goto error;
+
+	err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas));
+	if (err)
+		goto error;
+
+	return 0;
+ error:
+	tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
+	snd_device_free(aoa_get_card(), tas);
+	return err;
+}
+
+static void tas_exit_codec(struct aoa_codec *codec)
+{
+	struct tas *tas = codec_to_tas(codec);
+
+	if (!tas->codec.soundbus_dev)
+		return;
+	tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
+}
+	
+
+static struct i2c_driver tas_driver;
+
+static int tas_create(struct i2c_adapter *adapter,
+		       struct device_node *node,
+		       int addr)
+{
+	struct tas *tas;
+
+	tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
+
+	if (!tas)
+		return -ENOMEM;
+
+	tas->i2c.driver = &tas_driver;
+	tas->i2c.adapter = adapter;
+	tas->i2c.addr = addr;
+	strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1);
+
+	if (i2c_attach_client(&tas->i2c)) {
+		printk(KERN_ERR PFX "failed to attach to i2c\n");
+		goto fail;
+	}
+
+	strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1);
+	tas->codec.owner = THIS_MODULE;
+	tas->codec.init = tas_init_codec;
+	tas->codec.exit = tas_exit_codec;
+	tas->codec.node = of_node_get(node);
+
+	if (aoa_codec_register(&tas->codec)) {
+		goto detach;
+	}
+	printk(KERN_DEBUG "snd-aoa-codec-tas: created and attached tas instance\n");
+	return 0;
+ detach:
+	i2c_detach_client(&tas->i2c);
+ fail:
+	kfree(tas);
+	return -EINVAL;
+}
+
+static int tas_i2c_attach(struct i2c_adapter *adapter)
+{
+	struct device_node *busnode, *dev = NULL;
+	struct pmac_i2c_bus *bus;
+
+	bus = pmac_i2c_adapter_to_bus(adapter);
+	if (bus == NULL)
+		return -ENODEV;
+	busnode = pmac_i2c_get_bus_node(bus);
+
+	while ((dev = of_get_next_child(busnode, dev)) != NULL) {
+		if (device_is_compatible(dev, "tas3004")) {
+			u32 *addr;
+			printk(KERN_DEBUG PFX "found tas3004\n");
+			addr = (u32 *) get_property(dev, "reg", NULL);
+			if (!addr)
+				continue;
+			return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f);
+		}
+		/* older machines have no 'codec' node with a 'compatible'
+		 * property that says 'tas3004', they just have a 'deq'
+		 * node without any such property... */
+		if (strcmp(dev->name, "deq") == 0) {
+			u32 *_addr, addr;
+			printk(KERN_DEBUG PFX "found 'deq' node\n");
+			_addr = (u32 *) get_property(dev, "i2c-address", NULL);
+			if (!_addr)
+				continue;
+			addr = ((*_addr) >> 1) & 0x7f;
+			/* now, if the address doesn't match any of the two
+			 * that a tas3004 can have, we cannot handle this.
+			 * I doubt it ever happens but hey. */
+			if (addr != 0x34 && addr != 0x35)
+				continue;
+			return tas_create(adapter, dev, addr);
+		}
+	}
+	return -ENODEV;
+}
+
+static int tas_i2c_detach(struct i2c_client *client)
+{
+	struct tas *tas = container_of(client, struct tas, i2c);
+	int err;
+	u8 tmp = TAS_ACR_ANALOG_PDOWN;
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+	aoa_codec_unregister(&tas->codec);
+	of_node_put(tas->codec.node);
+
+	/* power down codec chip */
+	tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
+
+	kfree(tas);
+	return 0;
+}
+
+static struct i2c_driver tas_driver = {
+	.driver = {
+		.name = "aoa_codec_tas",
+		.owner = THIS_MODULE,
+	},
+	.attach_adapter = tas_i2c_attach,
+	.detach_client = tas_i2c_detach,
+};
+
+static int __init tas_init(void)
+{
+	return i2c_add_driver(&tas_driver);
+}
+
+static void __exit tas_exit(void)
+{
+	i2c_del_driver(&tas_driver);
+}
+
+module_init(tas_init);
+module_exit(tas_exit);
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h
new file mode 100644
index 0000000..daf81f45
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.h
@@ -0,0 +1,47 @@
+/*
+ * Apple Onboard Audio driver for tas codec (header)
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __SND_AOA_CODECTASH
+#define __SND_AOA_CODECTASH
+
+#define TAS_REG_MCS	0x01	/* main control */
+#	define TAS_MCS_FASTLOAD		(1<<7)
+#	define TAS_MCS_SCLK64		(1<<6)
+#	define TAS_MCS_SPORT_MODE_MASK	(3<<4)
+#	define TAS_MCS_SPORT_MODE_I2S	(2<<4)
+#	define TAS_MCS_SPORT_MODE_RJ	(1<<4)
+#	define TAS_MCS_SPORT_MODE_LJ	(0<<4)
+#	define TAS_MCS_SPORT_WL_MASK	(3<<0)
+#	define TAS_MCS_SPORT_WL_16BIT	(0<<0)
+#	define TAS_MCS_SPORT_WL_18BIT	(1<<0)
+#	define TAS_MCS_SPORT_WL_20BIT	(2<<0)
+#	define TAS_MCS_SPORT_WL_24BIT	(3<<0)
+
+#define TAS_REG_DRC	0x02
+#define TAS_REG_VOL	0x04
+#define TAS_REG_TREBLE	0x05
+#define TAS_REG_BASS	0x06
+#define TAS_REG_LMIX	0x07
+#define TAS_REG_RMIX	0x08
+
+#define TAS_REG_ACR	0x40	/* analog control */
+#	define TAS_ACR_B_MONAUREAL	(1<<7)
+#	define TAS_ACR_B_MON_SEL_RIGHT	(1<<6)
+#	define TAS_ACR_DEEMPH_MASK	(3<<2)
+#	define TAS_ACR_DEEMPH_OFF	(0<<2)
+#	define TAS_ACR_DEEMPH_48KHz	(1<<2)
+#	define TAS_ACR_DEEMPH_44KHz	(2<<2)
+#	define TAS_ACR_INPUT_B		(1<<1)
+#	define TAS_ACR_ANALOG_PDOWN	(1<<0)
+
+#define TAS_REG_MCS2	0x43	/* main control 2 */
+#	define TAS_MCS2_ALLPASS		(1<<1)
+
+#define TAS_REG_LEFT_BIQUAD6	0x10
+#define TAS_REG_RIGHT_BIQUAD6	0x19
+
+#endif /* __SND_AOA_CODECTASH */
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c
new file mode 100644
index 0000000..bcc5556
--- /dev/null
+++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c
@@ -0,0 +1,141 @@
+/*
+ * Apple Onboard Audio driver for Toonie codec
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ *
+ * This is a driver for the toonie codec chip. This chip is present
+ * on the Mac Mini and is nothing but a DAC.
+ */
+#include <linux/delay.h>
+#include <linux/module.h>
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("toonie codec driver for snd-aoa");
+
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+
+#define PFX "snd-aoa-codec-toonie: "
+
+struct toonie {
+	struct aoa_codec	codec;
+};
+#define codec_to_toonie(c) container_of(c, struct toonie, codec)
+
+static int toonie_dev_register(struct snd_device *dev)
+{
+	return 0;
+}
+
+static struct snd_device_ops ops = {
+	.dev_register = toonie_dev_register,
+};
+
+static struct transfer_info toonie_transfers[] = {
+	/* This thing *only* has analog output,
+	 * the rates are taken from Info.plist
+	 * from Darwin. */
+	{
+		.formats = SNDRV_PCM_FMTBIT_S16_BE |
+			   SNDRV_PCM_FMTBIT_S24_BE,
+		.rates = SNDRV_PCM_RATE_32000 |
+			 SNDRV_PCM_RATE_44100 |
+			 SNDRV_PCM_RATE_48000 |
+			 SNDRV_PCM_RATE_88200 |
+			 SNDRV_PCM_RATE_96000,
+	},
+	{}
+};
+
+#ifdef CONFIG_PM
+static int toonie_suspend(struct codec_info_item *cii, pm_message_t state)
+{
+	/* can we turn it off somehow? */
+	return 0;
+}
+
+static int toonie_resume(struct codec_info_item *cii)
+{
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct codec_info toonie_codec_info = {
+	.transfers = toonie_transfers,
+	.sysclock_factor = 256,
+	.bus_factor = 64,
+	.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+	.suspend = toonie_suspend,
+	.resume = toonie_resume,
+#endif
+};
+
+static int toonie_init_codec(struct aoa_codec *codec)
+{
+	struct toonie *toonie = codec_to_toonie(codec);
+
+	if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) {
+		printk(KERN_ERR PFX "failed to create toonie snd device!\n");
+		return -ENODEV;
+	}
+
+	/* nothing connected? what a joke! */
+	if (toonie->codec.connected != 1)
+		return -ENOTCONN;
+
+	if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev,
+						     aoa_get_card(),
+						     &toonie_codec_info, toonie)) {
+		printk(KERN_ERR PFX "error creating toonie pcm\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void toonie_exit_codec(struct aoa_codec *codec)
+{
+	struct toonie *toonie = codec_to_toonie(codec);
+
+	if (!toonie->codec.soundbus_dev) {
+		printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n");
+		return;
+	}
+	toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie);
+}
+
+static struct toonie *toonie;
+
+static int __init toonie_init(void)
+{
+	toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL);
+
+	if (!toonie)
+		return -ENOMEM;
+
+	strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
+	toonie->codec.owner = THIS_MODULE;
+	toonie->codec.init = toonie_init_codec;
+	toonie->codec.exit = toonie_exit_codec;
+                                        
+	if (aoa_codec_register(&toonie->codec)) {
+		kfree(toonie);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __exit toonie_exit(void)
+{
+	aoa_codec_unregister(&toonie->codec);
+	kfree(toonie);
+}
+
+module_init(toonie_init);
+module_exit(toonie_exit);
diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile
new file mode 100644
index 0000000..62dc728
--- /dev/null
+++ b/sound/aoa/core/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_SND_AOA) += snd-aoa.o
+snd-aoa-objs := snd-aoa-core.o \
+		snd-aoa-alsa.o \
+		snd-aoa-gpio-pmf.o \
+		snd-aoa-gpio-feature.o
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c
new file mode 100644
index 0000000..b42fdea
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-alsa.c
@@ -0,0 +1,98 @@
+/*
+ * Apple Onboard Audio Alsa helpers
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#include <linux/module.h>
+#include "snd-aoa-alsa.h"
+
+static int index = -1;
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "index for AOA sound card.");
+
+static struct aoa_card *aoa_card;
+
+int aoa_alsa_init(char *name, struct module *mod)
+{
+	struct snd_card *alsa_card;
+	int err;
+
+	if (aoa_card)
+		/* cannot be EEXIST due to usage in aoa_fabric_register */
+		return -EBUSY;
+
+	alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card));
+	if (!alsa_card)
+		return -ENOMEM;
+	aoa_card = alsa_card->private_data;
+	aoa_card->alsa_card = alsa_card;
+	strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
+	strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
+	strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname));
+	strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
+	err = snd_card_register(aoa_card->alsa_card);
+	if (err < 0) {
+		printk(KERN_ERR "snd-aoa: couldn't register alsa card\n");
+		snd_card_free(aoa_card->alsa_card);
+		aoa_card = NULL;
+		return err;
+	}
+	return 0;
+}
+
+struct snd_card *aoa_get_card(void)
+{
+	if (aoa_card)
+		return aoa_card->alsa_card;
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(aoa_get_card);
+
+void aoa_alsa_cleanup(void)
+{
+	if (aoa_card) {
+		snd_card_free(aoa_card->alsa_card);
+		aoa_card = NULL;
+	}
+}
+
+int aoa_snd_device_new(snd_device_type_t type,
+        void * device_data, struct snd_device_ops * ops)
+{
+	struct snd_card *card = aoa_get_card();
+	int err;
+	
+	if (!card) return -ENOMEM;
+
+	err = snd_device_new(card, type, device_data, ops);
+	if (err) {
+		printk(KERN_ERR "snd-aoa: failed to create snd device (%d)\n", err);
+		return err;
+	}
+	err = snd_device_register(card, device_data);
+	if (err) {
+		printk(KERN_ERR "snd-aoa: failed to register "
+				"snd device (%d)\n", err);
+		printk(KERN_ERR "snd-aoa: have you forgotten the "
+				"dev_register callback?\n");
+		snd_device_free(card, device_data);
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(aoa_snd_device_new);
+
+int aoa_snd_ctl_add(struct snd_kcontrol* control)
+{
+	int err;
+
+	if (!aoa_card) return -ENODEV;
+
+	err = snd_ctl_add(aoa_card->alsa_card, control);
+	if (err)
+		printk(KERN_ERR "snd-aoa: failed to add alsa control (%d)\n",
+		       err);
+	return err;
+}
+EXPORT_SYMBOL_GPL(aoa_snd_ctl_add);
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h
new file mode 100644
index 0000000..660d2f1
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-alsa.h
@@ -0,0 +1,16 @@
+/*
+ * Apple Onboard Audio Alsa private helpers
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#ifndef __SND_AOA_ALSA_H
+#define __SND_AOA_ALSA_H
+#include "../aoa.h"
+
+extern int aoa_alsa_init(char *name, struct module *mod);
+extern void aoa_alsa_cleanup(void);
+
+#endif /* __SND_AOA_ALSA_H */
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c
new file mode 100644
index 0000000..ecd2d82
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-core.c
@@ -0,0 +1,162 @@
+/*
+ * Apple Onboard Audio driver core
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include "../aoa.h"
+#include "snd-aoa-alsa.h"
+
+MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+
+/* We allow only one fabric. This simplifies things,
+ * and more don't really make that much sense */
+static struct aoa_fabric *fabric;
+static LIST_HEAD(codec_list);
+
+static int attach_codec_to_fabric(struct aoa_codec *c)
+{
+	int err;
+
+	if (!try_module_get(c->owner))
+		return -EBUSY;
+	/* found_codec has to be assigned */
+	err = -ENOENT;
+	if (fabric->found_codec)
+		err = fabric->found_codec(c);
+	if (err) {
+		module_put(c->owner);
+		printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n",
+				c->name);
+		return err;
+	}
+	c->fabric = fabric;
+
+	err = 0;
+	if (c->init)
+		err = c->init(c);
+	if (err) {
+		printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name);
+		c->fabric = NULL;
+		if (fabric->remove_codec)
+			fabric->remove_codec(c);
+		module_put(c->owner);
+		return err;
+	}
+	if (fabric->attached_codec)
+		fabric->attached_codec(c);
+	return 0;
+}
+
+int aoa_codec_register(struct aoa_codec *codec)
+{
+	int err = 0;
+
+	/* if there's a fabric already, we can tell if we
+	 * will want to have this codec, so propagate error
+	 * through. Otherwise, this will happen later... */
+	if (fabric)
+		err = attach_codec_to_fabric(codec);
+	if (!err)
+		list_add(&codec->list, &codec_list);
+	return err;
+}
+EXPORT_SYMBOL_GPL(aoa_codec_register);
+
+void aoa_codec_unregister(struct aoa_codec *codec)
+{
+	list_del(&codec->list);
+	if (codec->fabric && codec->exit)
+		codec->exit(codec);
+	if (fabric && fabric->remove_codec)
+		fabric->remove_codec(codec);
+	codec->fabric = NULL;
+	module_put(codec->owner);
+}
+EXPORT_SYMBOL_GPL(aoa_codec_unregister);
+
+int aoa_fabric_register(struct aoa_fabric *new_fabric)
+{
+	struct aoa_codec *c;
+	int err;
+
+	/* allow querying for presence of fabric
+	 * (i.e. do this test first!) */
+	if (new_fabric == fabric) {
+		err = -EALREADY;
+		goto attach;
+	}
+	if (fabric)
+		return -EEXIST;
+	if (!new_fabric)
+		return -EINVAL;
+
+	err = aoa_alsa_init(new_fabric->name, new_fabric->owner);
+	if (err)
+		return err;
+
+	fabric = new_fabric;
+
+ attach:
+	list_for_each_entry(c, &codec_list, list) {
+		if (c->fabric != fabric)
+			attach_codec_to_fabric(c);
+	}
+	return err;
+}
+EXPORT_SYMBOL_GPL(aoa_fabric_register);
+
+void aoa_fabric_unregister(struct aoa_fabric *old_fabric)
+{
+	struct aoa_codec *c;
+
+	if (fabric != old_fabric)
+		return;
+
+	list_for_each_entry(c, &codec_list, list) {
+		if (c->fabric)
+			aoa_fabric_unlink_codec(c);
+	}
+
+	aoa_alsa_cleanup();
+
+	fabric = NULL;
+}
+EXPORT_SYMBOL_GPL(aoa_fabric_unregister);
+
+void aoa_fabric_unlink_codec(struct aoa_codec *codec)
+{
+	if (!codec->fabric) {
+		printk(KERN_ERR "snd-aoa: fabric unassigned "
+				"in aoa_fabric_unlink_codec\n");
+		dump_stack();
+		return;
+	}
+	if (codec->exit)
+		codec->exit(codec);
+	if (codec->fabric->remove_codec)
+		codec->fabric->remove_codec(codec);
+	codec->fabric = NULL;
+	module_put(codec->owner);
+}
+EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec);
+
+static int __init aoa_init(void)
+{
+	return 0;
+}
+
+static void __exit aoa_exit(void)
+{
+	aoa_alsa_cleanup();
+}
+
+module_init(aoa_init);
+module_exit(aoa_exit);
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
new file mode 100644
index 0000000..2c6eb77
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-gpio-feature.c
@@ -0,0 +1,399 @@
+/*
+ * Apple Onboard Audio feature call GPIO control
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ * This file contains the GPIO control routines for 
+ * direct (through feature calls) access to the GPIO
+ * registers.
+ */
+
+#include <asm/pmac_feature.h>
+#include <linux/interrupt.h>
+#include "../aoa.h"
+
+/* TODO: these are 20 global variables
+ * that aren't used on most machines...
+ * Move them into a dynamically allocated
+ * structure and use that.
+ */
+
+/* these are the GPIO numbers (register addresses as offsets into
+ * the GPIO space) */
+static int headphone_mute_gpio;
+static int amp_mute_gpio;
+static int lineout_mute_gpio;
+static int hw_reset_gpio;
+static int lineout_detect_gpio;
+static int headphone_detect_gpio;
+static int linein_detect_gpio;
+
+/* see the SWITCH_GPIO macro */
+static int headphone_mute_gpio_activestate;
+static int amp_mute_gpio_activestate;
+static int lineout_mute_gpio_activestate;
+static int hw_reset_gpio_activestate;
+static int lineout_detect_gpio_activestate;
+static int headphone_detect_gpio_activestate;
+static int linein_detect_gpio_activestate;
+
+/* node pointers that we save when getting the GPIO number
+ * to get the interrupt later */
+static struct device_node *lineout_detect_node;
+static struct device_node *linein_detect_node;
+static struct device_node *headphone_detect_node;
+
+static int lineout_detect_irq;
+static int linein_detect_irq;
+static int headphone_detect_irq;
+
+static struct device_node *get_gpio(char *name,
+				    char *altname,
+				    int *gpioptr,
+				    int *gpioactiveptr)
+{
+	struct device_node *np, *gpio;
+	u32 *reg;
+	char *audio_gpio;
+
+	*gpioptr = -1;
+
+	/* check if we can get it the easy way ... */
+	np = of_find_node_by_name(NULL, name);
+	if (!np) {
+		/* some machines have only gpioX/extint-gpioX nodes,
+		 * and an audio-gpio property saying what it is ...
+		 * So what we have to do is enumerate all children
+		 * of the gpio node and check them all. */
+		gpio = of_find_node_by_name(NULL, "gpio");
+		if (!gpio)
+			return NULL;
+		while ((np = of_get_next_child(gpio, np))) {
+			audio_gpio = get_property(np, "audio-gpio", NULL);
+			if (!audio_gpio)
+				continue;
+			if (strcmp(audio_gpio, name) == 0)
+				break;
+			if (altname && (strcmp(audio_gpio, altname) == 0))
+				break;
+		}
+		/* still not found, assume not there */
+		if (!np)
+			return NULL;
+	}
+
+	reg = (u32 *)get_property(np, "reg", NULL);
+	if (!reg)
+		return NULL;
+
+	*gpioptr = *reg;
+
+	/* this is a hack, usually the GPIOs 'reg' property
+	 * should have the offset based from the GPIO space
+	 * which is at 0x50, but apparently not always... */
+	if (*gpioptr < 0x50)
+		*gpioptr += 0x50;
+
+	reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
+	if (!reg)
+		/* Apple seems to default to 1, but
+		 * that doesn't seem right at least on most
+		 * machines. So until proven that the opposite
+		 * is necessary, we default to 0
+		 * (which, incidentally, snd-powermac also does...) */
+		*gpioactiveptr = 0;
+	else
+		*gpioactiveptr = *reg;
+
+	return np;
+}
+
+static void get_irq(struct device_node * np, int *irqptr)
+{
+	*irqptr = -1;
+	if (!np)
+		return;
+	if (np->n_intrs != 1)
+		return;
+	*irqptr = np->intrs[0].line;
+}
+
+/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */
+#define SWITCH_GPIO(name, v, on)				\
+	(((v)&~1) | ((on)?					\
+			(name##_gpio_activestate==0?4:5):	\
+			(name##_gpio_activestate==0?5:4)))
+
+#define FTR_GPIO(name, bit)					\
+static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\
+{								\
+	int v;							\
+								\
+	if (unlikely(!rt)) return;				\
+								\
+	if (name##_mute_gpio < 0)				\
+		return;						\
+								\
+	v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL,		\
+			      name##_mute_gpio,			\
+			      0);				\
+								\
+	/* muted = !on... */					\
+	v = SWITCH_GPIO(name##_mute, v, !on);			\
+								\
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,		\
+			  name##_mute_gpio, v);			\
+								\
+	rt->implementation_private &= ~(1<<bit);		\
+	rt->implementation_private |= (!!on << bit);		\
+}								\
+static int ftr_gpio_get_##name(struct gpio_runtime *rt)		\
+{								\
+	if (unlikely(!rt)) return 0;				\
+	return (rt->implementation_private>>bit)&1;		\
+}
+
+FTR_GPIO(headphone, 0);
+FTR_GPIO(amp, 1);
+FTR_GPIO(lineout, 2);
+
+static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
+{
+	int v;
+
+	if (unlikely(!rt)) return;
+	if (hw_reset_gpio < 0)
+		return;
+
+	v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL,
+			      hw_reset_gpio, 0);
+	v = SWITCH_GPIO(hw_reset, v, on);
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL,
+			  hw_reset_gpio, v);
+}
+
+static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
+{
+	int saved;
+
+	if (unlikely(!rt)) return;
+	saved = rt->implementation_private;
+	ftr_gpio_set_headphone(rt, 0);
+	ftr_gpio_set_amp(rt, 0);
+	ftr_gpio_set_lineout(rt, 0);
+	rt->implementation_private = saved;
+}
+
+static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt)
+{
+	int s;
+
+	if (unlikely(!rt)) return;
+	s = rt->implementation_private;
+	ftr_gpio_set_headphone(rt, (s>>0)&1);
+	ftr_gpio_set_amp(rt, (s>>1)&1);
+	ftr_gpio_set_lineout(rt, (s>>2)&1);
+}
+
+static void ftr_handle_notify(void *data)
+{
+	struct gpio_notification *notif = data;
+
+	mutex_lock(&notif->mutex);
+	if (notif->notify)
+		notif->notify(notif->data);
+	mutex_unlock(&notif->mutex);
+}
+
+static void ftr_gpio_init(struct gpio_runtime *rt)
+{
+	get_gpio("headphone-mute", NULL,
+		 &headphone_mute_gpio,
+		 &headphone_mute_gpio_activestate);
+	get_gpio("amp-mute", NULL,
+		 &amp_mute_gpio,
+		 &amp_mute_gpio_activestate);
+	get_gpio("lineout-mute", NULL,
+		 &lineout_mute_gpio,
+		 &lineout_mute_gpio_activestate);
+	get_gpio("hw-reset", "audio-hw-reset",
+		 &hw_reset_gpio,
+		 &hw_reset_gpio_activestate);
+
+	headphone_detect_node = get_gpio("headphone-detect", NULL,
+					 &headphone_detect_gpio,
+					 &headphone_detect_gpio_activestate);
+	/* go Apple, and thanks for giving these different names
+	 * across the board... */
+	lineout_detect_node = get_gpio("lineout-detect", "line-output-detect",
+				       &lineout_detect_gpio,
+				       &lineout_detect_gpio_activestate);
+	linein_detect_node = get_gpio("linein-detect", "line-input-detect",
+				      &linein_detect_gpio,
+				      &linein_detect_gpio_activestate);
+
+	get_irq(headphone_detect_node, &headphone_detect_irq);
+	get_irq(lineout_detect_node, &lineout_detect_irq);
+	get_irq(linein_detect_node, &linein_detect_irq);
+
+	ftr_gpio_all_amps_off(rt);
+	rt->implementation_private = 0;
+	INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify,
+		  &rt->headphone_notify);
+	INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify,
+		  &rt->line_in_notify);
+	INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify,
+		  &rt->line_out_notify);
+	mutex_init(&rt->headphone_notify.mutex);
+	mutex_init(&rt->line_in_notify.mutex);
+	mutex_init(&rt->line_out_notify.mutex);
+}
+
+static void ftr_gpio_exit(struct gpio_runtime *rt)
+{
+	ftr_gpio_all_amps_off(rt);
+	rt->implementation_private = 0;
+	if (rt->headphone_notify.notify)
+		free_irq(headphone_detect_irq, &rt->headphone_notify);
+	if (rt->line_in_notify.gpio_private)
+		free_irq(linein_detect_irq, &rt->line_in_notify);
+	if (rt->line_out_notify.gpio_private)
+		free_irq(lineout_detect_irq, &rt->line_out_notify);
+	cancel_delayed_work(&rt->headphone_notify.work);
+	cancel_delayed_work(&rt->line_in_notify.work);
+	cancel_delayed_work(&rt->line_out_notify.work);
+	flush_scheduled_work();
+	mutex_destroy(&rt->headphone_notify.mutex);
+	mutex_destroy(&rt->line_in_notify.mutex);
+	mutex_destroy(&rt->line_out_notify.mutex);
+}
+
+static irqreturn_t ftr_handle_notify_irq(int xx,
+					 void *data,
+					 struct pt_regs *regs)
+{
+	struct gpio_notification *notif = data;
+
+	schedule_work(&notif->work);
+
+	return IRQ_HANDLED;
+}
+
+static int ftr_set_notify(struct gpio_runtime *rt,
+			  enum notify_type type,
+			  notify_func_t notify,
+			  void *data)
+{
+	struct gpio_notification *notif;
+	notify_func_t old;
+	int irq;
+	char *name;
+	int err = -EBUSY;
+
+	switch (type) {
+	case AOA_NOTIFY_HEADPHONE:
+		notif = &rt->headphone_notify;
+		name = "headphone-detect";
+		irq = headphone_detect_irq;
+		break;
+	case AOA_NOTIFY_LINE_IN:
+		notif = &rt->line_in_notify;
+		name = "linein-detect";
+		irq = linein_detect_irq;
+		break;
+	case AOA_NOTIFY_LINE_OUT:
+		notif = &rt->line_out_notify;
+		name = "lineout-detect";
+		irq = lineout_detect_irq;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (irq == -1)
+		return -ENODEV;
+
+	mutex_lock(&notif->mutex);
+
+	old = notif->notify;
+
+	if (!old && !notify) {
+		err = 0;
+		goto out_unlock;
+	}
+
+	if (old && notify) {
+		if (old == notify && notif->data == data)
+			err = 0;
+		goto out_unlock;
+	}
+
+	if (old && !notify)
+		free_irq(irq, notif);
+
+	if (!old && notify) {
+		err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif);
+		if (err)
+			goto out_unlock;
+	}
+
+	notif->notify = notify;
+	notif->data = data;
+
+	err = 0;
+ out_unlock:
+	mutex_unlock(&notif->mutex);
+	return err;
+}
+
+static int ftr_get_detect(struct gpio_runtime *rt,
+			  enum notify_type type)
+{
+	int gpio, ret, active;
+
+	switch (type) {
+	case AOA_NOTIFY_HEADPHONE:
+		gpio = headphone_detect_gpio;
+		active = headphone_detect_gpio_activestate;
+		break;
+	case AOA_NOTIFY_LINE_IN:
+		gpio = linein_detect_gpio;
+		active = linein_detect_gpio_activestate;
+		break;
+	case AOA_NOTIFY_LINE_OUT:
+		gpio = lineout_detect_gpio;
+		active = lineout_detect_gpio_activestate;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (gpio == -1)
+		return -ENODEV;
+
+	ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0);
+	if (ret < 0)
+		return ret;
+	return ((ret >> 1) & 1) == active;
+}
+
+static struct gpio_methods methods = {
+	.init			= ftr_gpio_init,
+	.exit			= ftr_gpio_exit,
+	.all_amps_off		= ftr_gpio_all_amps_off,
+	.all_amps_restore	= ftr_gpio_all_amps_restore,
+	.set_headphone		= ftr_gpio_set_headphone,
+	.set_speakers		= ftr_gpio_set_amp,
+	.set_lineout		= ftr_gpio_set_lineout,
+	.set_hw_reset		= ftr_gpio_set_hw_reset,
+	.get_headphone		= ftr_gpio_get_headphone,
+	.get_speakers		= ftr_gpio_get_amp,
+	.get_lineout		= ftr_gpio_get_lineout,
+	.set_notify		= ftr_set_notify,
+	.get_detect		= ftr_get_detect,
+};
+
+struct gpio_methods *ftr_gpio_methods = &methods;
+EXPORT_SYMBOL_GPL(ftr_gpio_methods);
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
new file mode 100644
index 0000000..0e9b9bb
--- /dev/null
+++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
@@ -0,0 +1,246 @@
+/*
+ * Apple Onboard Audio pmf GPIOs
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <asm/pmac_feature.h>
+#include <asm/pmac_pfunc.h>
+#include "../aoa.h"
+
+#define PMF_GPIO(name, bit)					\
+static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\
+{								\
+	struct pmf_args args = { .count = 1, .u[0].v = !on };	\
+								\
+	if (unlikely(!rt)) return;				\
+	pmf_call_function(rt->node, #name "-mute", &args);	\
+	rt->implementation_private &= ~(1<<bit);		\
+	rt->implementation_private |= (!!on << bit);		\
+}								\
+static int pmf_gpio_get_##name(struct gpio_runtime *rt)		\
+{								\
+	if (unlikely(!rt)) return 0;				\
+	return (rt->implementation_private>>bit)&1;		\
+}
+
+PMF_GPIO(headphone, 0);
+PMF_GPIO(amp, 1);
+PMF_GPIO(lineout, 2);
+
+static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
+{
+	struct pmf_args args = { .count = 1, .u[0].v = !!on };
+
+	if (unlikely(!rt)) return;
+	pmf_call_function(rt->node, "hw-reset", &args);
+}
+
+static void pmf_gpio_all_amps_off(struct gpio_runtime *rt)
+{
+	int saved;
+
+	if (unlikely(!rt)) return;
+	saved = rt->implementation_private;
+	pmf_gpio_set_headphone(rt, 0);
+	pmf_gpio_set_amp(rt, 0);
+	pmf_gpio_set_lineout(rt, 0);
+	rt->implementation_private = saved;
+}
+
+static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt)
+{
+	int s;
+
+	if (unlikely(!rt)) return;
+	s = rt->implementation_private;
+	pmf_gpio_set_headphone(rt, (s>>0)&1);
+	pmf_gpio_set_amp(rt, (s>>1)&1);
+	pmf_gpio_set_lineout(rt, (s>>2)&1);
+}
+
+static void pmf_handle_notify(void *data)
+{
+	struct gpio_notification *notif = data;
+
+	mutex_lock(&notif->mutex);
+	if (notif->notify)
+		notif->notify(notif->data);
+	mutex_unlock(&notif->mutex);
+}
+
+static void pmf_gpio_init(struct gpio_runtime *rt)
+{
+	pmf_gpio_all_amps_off(rt);
+	rt->implementation_private = 0;
+	INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify,
+		  &rt->headphone_notify);
+	INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify,
+		  &rt->line_in_notify);
+	INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify,
+		  &rt->line_out_notify);
+	mutex_init(&rt->headphone_notify.mutex);
+	mutex_init(&rt->line_in_notify.mutex);
+	mutex_init(&rt->line_out_notify.mutex);
+}
+
+static void pmf_gpio_exit(struct gpio_runtime *rt)
+{
+	pmf_gpio_all_amps_off(rt);
+	rt->implementation_private = 0;
+
+	if (rt->headphone_notify.gpio_private)
+		pmf_unregister_irq_client(rt->headphone_notify.gpio_private);
+	if (rt->line_in_notify.gpio_private)
+		pmf_unregister_irq_client(rt->line_in_notify.gpio_private);
+	if (rt->line_out_notify.gpio_private)
+		pmf_unregister_irq_client(rt->line_out_notify.gpio_private);
+
+	/* make sure no work is pending before freeing
+	 * all things */
+	cancel_delayed_work(&rt->headphone_notify.work);
+	cancel_delayed_work(&rt->line_in_notify.work);
+	cancel_delayed_work(&rt->line_out_notify.work);
+	flush_scheduled_work();
+
+	mutex_destroy(&rt->headphone_notify.mutex);
+	mutex_destroy(&rt->line_in_notify.mutex);
+	mutex_destroy(&rt->line_out_notify.mutex);
+
+	if (rt->headphone_notify.gpio_private)
+		kfree(rt->headphone_notify.gpio_private);
+	if (rt->line_in_notify.gpio_private)
+		kfree(rt->line_in_notify.gpio_private);
+	if (rt->line_out_notify.gpio_private)
+		kfree(rt->line_out_notify.gpio_private);
+}
+
+static void pmf_handle_notify_irq(void *data)
+{
+	struct gpio_notification *notif = data;
+
+	schedule_work(&notif->work);
+}
+
+static int pmf_set_notify(struct gpio_runtime *rt,
+			  enum notify_type type,
+			  notify_func_t notify,
+			  void *data)
+{
+	struct gpio_notification *notif;
+	notify_func_t old;
+	struct pmf_irq_client *irq_client;
+	char *name;
+	int err = -EBUSY;
+
+	switch (type) {
+	case AOA_NOTIFY_HEADPHONE:
+		notif = &rt->headphone_notify;
+		name = "headphone-detect";
+		break;
+	case AOA_NOTIFY_LINE_IN:
+		notif = &rt->line_in_notify;
+		name = "linein-detect";
+		break;
+	case AOA_NOTIFY_LINE_OUT:
+		notif = &rt->line_out_notify;
+		name = "lineout-detect";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_lock(&notif->mutex);
+
+	old = notif->notify;
+
+	if (!old && !notify) {
+		err = 0;
+		goto out_unlock;
+	}
+
+	if (old && notify) {
+		if (old == notify && notif->data == data)
+			err = 0;
+		goto out_unlock;
+	}
+
+	if (old && !notify) {
+		irq_client = notif->gpio_private;
+		pmf_unregister_irq_client(irq_client);
+		kfree(irq_client);
+		notif->gpio_private = NULL;
+	}
+	if (!old && notify) {
+		irq_client = kzalloc(sizeof(struct pmf_irq_client),
+				     GFP_KERNEL);
+		irq_client->data = notif;
+		irq_client->handler = pmf_handle_notify_irq;
+		irq_client->owner = THIS_MODULE;
+		err = pmf_register_irq_client(rt->node,
+					      name,
+					      irq_client);
+		if (err) {
+			printk(KERN_ERR "snd-aoa: gpio layer failed to"
+					" register %s irq (%d)\n", name, err);
+			kfree(irq_client);
+			goto out_unlock;
+		}
+		notif->gpio_private = irq_client;
+	}
+	notif->notify = notify;
+	notif->data = data;
+
+	err = 0;
+ out_unlock:
+	mutex_unlock(&notif->mutex);
+	return err;
+}
+
+static int pmf_get_detect(struct gpio_runtime *rt,
+			  enum notify_type type)
+{
+	char *name;
+	int err = -EBUSY, ret;
+	struct pmf_args args = { .count = 1, .u[0].p = &ret };
+
+	switch (type) {
+	case AOA_NOTIFY_HEADPHONE:
+		name = "headphone-detect";
+		break;
+	case AOA_NOTIFY_LINE_IN:
+		name = "linein-detect";
+		break;
+	case AOA_NOTIFY_LINE_OUT:
+		name = "lineout-detect";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	err = pmf_call_function(rt->node, name, &args);
+	if (err)
+		return err;
+	return ret;
+}
+
+static struct gpio_methods methods = {
+	.init			= pmf_gpio_init,
+	.exit			= pmf_gpio_exit,
+	.all_amps_off		= pmf_gpio_all_amps_off,
+	.all_amps_restore	= pmf_gpio_all_amps_restore,
+	.set_headphone		= pmf_gpio_set_headphone,
+	.set_speakers		= pmf_gpio_set_amp,
+	.set_lineout		= pmf_gpio_set_lineout,
+	.set_hw_reset		= pmf_gpio_set_hw_reset,
+	.get_headphone		= pmf_gpio_get_headphone,
+	.get_speakers		= pmf_gpio_get_amp,
+	.get_lineout		= pmf_gpio_get_lineout,
+	.set_notify		= pmf_set_notify,
+	.get_detect		= pmf_get_detect,
+};
+
+struct gpio_methods *pmf_gpio_methods = &methods;
+EXPORT_SYMBOL_GPL(pmf_gpio_methods);
diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig
new file mode 100644
index 0000000..c3bc770
--- /dev/null
+++ b/sound/aoa/fabrics/Kconfig
@@ -0,0 +1,12 @@
+config SND_AOA_FABRIC_LAYOUT
+	tristate "layout-id fabric"
+	depends SND_AOA
+	select SND_AOA_SOUNDBUS
+	select SND_AOA_SOUNDBUS_I2S
+	---help---
+	This enables the layout-id fabric for the Apple Onboard
+	Audio driver, the module holding it all together
+	based on the device-tree's layout-id property.
+	
+	If you are unsure and have a later Apple machine,
+	compile it as a module.
diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile
new file mode 100644
index 0000000..55fc5e7
--- /dev/null
+++ b/sound/aoa/fabrics/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
new file mode 100644
index 0000000..04a7238
--- /dev/null
+++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
@@ -0,0 +1,1109 @@
+/*
+ * Apple Onboard Audio driver -- layout fabric
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ *
+ *
+ * This fabric module looks for sound codecs
+ * based on the layout-id property in the device tree.
+ *
+ */
+
+#include <asm/prom.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include "../aoa.h"
+#include "../soundbus/soundbus.h"
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa");
+
+#define MAX_CODECS_PER_BUS	2
+
+/* These are the connections the layout fabric
+ * knows about. It doesn't really care about the
+ * input ones, but I thought I'd separate them
+ * to give them proper names. The thing is that
+ * Apple usually will distinguish the active output
+ * by GPIOs, while the active input is set directly
+ * on the codec. Hence we here tell the codec what
+ * we think is connected. This information is hard-
+ * coded below ... */
+#define CC_SPEAKERS	(1<<0)
+#define CC_HEADPHONE	(1<<1)
+#define CC_LINEOUT	(1<<2)
+#define CC_DIGITALOUT	(1<<3)
+#define CC_LINEIN	(1<<4)
+#define CC_MICROPHONE	(1<<5)
+#define CC_DIGITALIN	(1<<6)
+/* pretty bogus but users complain...
+ * This is a flag saying that the LINEOUT
+ * should be renamed to HEADPHONE.
+ * be careful with input detection! */
+#define CC_LINEOUT_LABELLED_HEADPHONE	(1<<7)
+
+struct codec_connection {
+	/* CC_ flags from above */
+	int connected;
+	/* codec dependent bit to be set in the aoa_codec.connected field.
+	 * This intentionally doesn't have any generic flags because the
+	 * fabric has to know the codec anyway and all codecs might have
+	 * different connectors */
+	int codec_bit;
+};
+
+struct codec_connect_info {
+	char *name;
+	struct codec_connection *connections;
+};
+
+#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF	(1<<0)
+
+struct layout {
+	unsigned int layout_id;
+	struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
+	int flags;
+	
+	/* if busname is not assigned, we use 'Master' below,
+	 * so that our layout table doesn't need to be filled
+	 * too much.
+	 * We only assign these two if we expect to find more
+	 * than one soundbus, i.e. on those machines with
+	 * multiple layout-ids */
+	char *busname;
+	int pcmid;
+};
+
+MODULE_ALIAS("sound-layout-41");
+MODULE_ALIAS("sound-layout-45");
+MODULE_ALIAS("sound-layout-51");
+MODULE_ALIAS("sound-layout-58");
+MODULE_ALIAS("sound-layout-60");
+MODULE_ALIAS("sound-layout-61");
+MODULE_ALIAS("sound-layout-64");
+MODULE_ALIAS("sound-layout-65");
+MODULE_ALIAS("sound-layout-68");
+MODULE_ALIAS("sound-layout-69");
+MODULE_ALIAS("sound-layout-70");
+MODULE_ALIAS("sound-layout-72");
+MODULE_ALIAS("sound-layout-80");
+MODULE_ALIAS("sound-layout-82");
+MODULE_ALIAS("sound-layout-84");
+MODULE_ALIAS("sound-layout-86");
+MODULE_ALIAS("sound-layout-92");
+
+/* onyx with all but microphone connected */
+static struct codec_connection onyx_connections_nomic[] = {
+	{
+		.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_DIGITALOUT,
+		.codec_bit = 1,
+	},
+	{
+		.connected = CC_LINEIN,
+		.codec_bit = 2,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+/* onyx on machines without headphone */
+static struct codec_connection onyx_connections_noheadphones[] = {
+	{
+		.connected = CC_SPEAKERS | CC_LINEOUT |
+			     CC_LINEOUT_LABELLED_HEADPHONE,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_DIGITALOUT,
+		.codec_bit = 1,
+	},
+	/* FIXME: are these correct? probably not for all the machines
+	 * below ... If not this will need separating. */
+	{
+		.connected = CC_LINEIN,
+		.codec_bit = 2,
+	},
+	{
+		.connected = CC_MICROPHONE,
+		.codec_bit = 3,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+/* onyx on machines with real line-out */
+static struct codec_connection onyx_connections_reallineout[] = {
+	{
+		.connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_DIGITALOUT,
+		.codec_bit = 1,
+	},
+	{
+		.connected = CC_LINEIN,
+		.codec_bit = 2,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines without line out */
+static struct codec_connection tas_connections_nolineout[] = {
+	{
+		.connected = CC_SPEAKERS | CC_HEADPHONE,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_LINEIN,
+		.codec_bit = 2,
+	},
+	{
+		.connected = CC_MICROPHONE,
+		.codec_bit = 3,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines with neither line out nor line in */
+static struct codec_connection tas_connections_noline[] = {
+	{
+		.connected = CC_SPEAKERS | CC_HEADPHONE,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_MICROPHONE,
+		.codec_bit = 3,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines without microphone */
+static struct codec_connection tas_connections_nomic[] = {
+	{
+		.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_LINEIN,
+		.codec_bit = 2,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+/* tas on machines with everything connected */
+static struct codec_connection tas_connections_all[] = {
+	{
+		.connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_LINEIN,
+		.codec_bit = 2,
+	},
+	{
+		.connected = CC_MICROPHONE,
+		.codec_bit = 3,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection toonie_connections[] = {
+	{
+		.connected = CC_SPEAKERS | CC_HEADPHONE,
+		.codec_bit = 0,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection topaz_input[] = {
+	{
+		.connected = CC_DIGITALIN,
+		.codec_bit = 0,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection topaz_output[] = {
+	{
+		.connected = CC_DIGITALOUT,
+		.codec_bit = 1,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+static struct codec_connection topaz_inout[] = {
+	{
+		.connected = CC_DIGITALIN,
+		.codec_bit = 0,
+	},
+	{
+		.connected = CC_DIGITALOUT,
+		.codec_bit = 1,
+	},
+	{} /* terminate array by .connected == 0 */
+};
+
+static struct layout layouts[] = {
+	/* last PowerBooks (15" Oct 2005) */
+	{ .layout_id = 82,
+	  .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	  .codecs[1] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	/* PowerMac9,1 */
+	{ .layout_id = 60,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_reallineout,
+	  },
+	},
+	/* PowerMac9,1 */
+	{ .layout_id = 61,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	/* PowerBook5,7 */
+	{ .layout_id = 64,
+	  .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	},
+	/* PowerBook5,7 */
+	{ .layout_id = 65,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	/* PowerBook5,9 [17" Oct 2005] */
+	{ .layout_id = 84,
+	  .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	  .codecs[1] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	/* PowerMac8,1 */
+	{ .layout_id = 45,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	  .codecs[1] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	/* Quad PowerMac (analog in, analog/digital out) */
+	{ .layout_id = 68,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_nomic,
+	  },
+	},
+	/* Quad PowerMac (digital in) */
+	{ .layout_id = 69,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	  .busname = "digital in", .pcmid = 1 },
+	/* Early 2005 PowerBook (PowerBook 5,6) */
+	{ .layout_id = 70,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_nolineout,
+	  },
+	},
+	/* PowerBook 5,4 */
+	{ .layout_id = 51,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_nolineout,
+	  },
+	},
+	/* PowerBook6,7 */
+	{ .layout_id = 80,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_noline,
+	  },
+	},
+	/* PowerBook6,8 */
+	{ .layout_id = 72,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_nolineout,
+	  },
+	},
+	/* PowerMac8,2 */
+	{ .layout_id = 86,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_nomic,
+	  },
+	  .codecs[1] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	/* PowerBook6,7 */
+	{ .layout_id = 92,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_nolineout,
+	  },
+	},
+	/* PowerMac10,1 (Mac Mini) */
+	{ .layout_id = 58,
+	  .codecs[0] = {
+		.name = "toonie",
+		.connections = toonie_connections,
+	  },
+	},
+	/* unknown, untested, but this comes from Apple */
+	{ .layout_id = 41,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_all,
+	  },
+	},
+	{ .layout_id = 36,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_nomic,
+	  },
+	  .codecs[1] = {
+		.name = "topaz",
+		.connections = topaz_inout,
+	  },
+	},
+	{ .layout_id = 47,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	},
+	{ .layout_id = 48,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	{ .layout_id = 49,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_nomic,
+	  },
+	},
+	{ .layout_id = 50,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	{ .layout_id = 56,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	},
+	{ .layout_id = 57,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	{ .layout_id = 62,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	  .codecs[1] = {
+		.name = "topaz",
+		.connections = topaz_output,
+	  },
+	},
+	{ .layout_id = 66,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	},
+	{ .layout_id = 67,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	},
+	{ .layout_id = 76,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_nomic,
+	  },
+	  .codecs[1] = {
+		.name = "topaz",
+		.connections = topaz_inout,
+	  },
+	},
+	{ .layout_id = 90,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_noline,
+	  },
+	},
+	{ .layout_id = 94,
+	  .codecs[0] = {
+		.name = "onyx",
+		/* but it has an external mic?? how to select? */
+		.connections = onyx_connections_noheadphones,
+	  },
+	},
+	{ .layout_id = 96,
+	  .codecs[0] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	},
+	{ .layout_id = 98,
+	  .codecs[0] = {
+		.name = "toonie",
+		.connections = toonie_connections,
+	  },
+	},
+	{ .layout_id = 100,
+	  .codecs[0] = {
+		.name = "topaz",
+		.connections = topaz_input,
+	  },
+	  .codecs[1] = {
+		.name = "onyx",
+		.connections = onyx_connections_noheadphones,
+	  },
+	},
+	{}
+};
+
+static struct layout *find_layout_by_id(unsigned int id)
+{
+	struct layout *l;
+
+	l = layouts;
+	while (l->layout_id) {
+		if (l->layout_id == id)
+			return l;
+		l++;
+	}
+	return NULL;
+}
+
+static void use_layout(struct layout *l)
+{
+	int i;
+
+	for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+		if (l->codecs[i].name) {
+			request_module("snd-aoa-codec-%s", l->codecs[i].name);
+		}
+	}
+	/* now we wait for the codecs to call us back */
+}
+
+struct layout_dev;
+
+struct layout_dev_ptr {
+	struct layout_dev *ptr;
+};
+
+struct layout_dev {
+	struct list_head list;
+	struct soundbus_dev *sdev;
+	struct device_node *sound;
+	struct aoa_codec *codecs[MAX_CODECS_PER_BUS];
+	struct layout *layout;
+	struct gpio_runtime gpio;
+
+	/* we need these for headphone/lineout detection */
+	struct snd_kcontrol *headphone_ctrl;
+	struct snd_kcontrol *lineout_ctrl;
+	struct snd_kcontrol *speaker_ctrl;
+	struct snd_kcontrol *headphone_detected_ctrl;
+	struct snd_kcontrol *lineout_detected_ctrl;
+
+	struct layout_dev_ptr selfptr_headphone;
+	struct layout_dev_ptr selfptr_lineout;
+
+	u32 have_lineout_detect:1,
+	    have_headphone_detect:1,
+	    switch_on_headphone:1,
+	    switch_on_lineout:1;
+};
+
+static LIST_HEAD(layouts_list);
+static int layouts_list_items;
+/* this can go away but only if we allow multiple cards,
+ * make the fabric handle all the card stuff, etc... */
+static struct layout_dev *layout_device;
+
+static int control_info(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+#define AMP_CONTROL(n, description)					\
+static int n##_control_get(struct snd_kcontrol *kcontrol,		\
+			   struct snd_ctl_elem_value *ucontrol)		\
+{									\
+	struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol);	\
+	if (gpio->methods && gpio->methods->get_##n)			\
+		ucontrol->value.integer.value[0] =			\
+			gpio->methods->get_##n(gpio);			\
+	return 0;							\
+}									\
+static int n##_control_put(struct snd_kcontrol *kcontrol,		\
+			   struct snd_ctl_elem_value *ucontrol)		\
+{									\
+	struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol);	\
+	if (gpio->methods && gpio->methods->get_##n)			\
+		gpio->methods->set_##n(gpio,				\
+			ucontrol->value.integer.value[0]);		\
+	return 1;							\
+}									\
+static struct snd_kcontrol_new n##_ctl = {				\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,				\
+	.name = description,						\
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                      \
+	.info = control_info,						\
+	.get = n##_control_get,						\
+	.put = n##_control_put,						\
+}
+
+AMP_CONTROL(headphone, "Headphone Switch");
+AMP_CONTROL(speakers, "Speakers Switch");
+AMP_CONTROL(lineout, "Line-Out Switch");
+
+static int detect_choice_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
+
+	switch (kcontrol->private_value) {
+	case 0:
+		ucontrol->value.integer.value[0] = ldev->switch_on_headphone;
+		break;
+	case 1:
+		ucontrol->value.integer.value[0] = ldev->switch_on_lineout;
+		break;
+	default:
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int detect_choice_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
+
+	switch (kcontrol->private_value) {
+	case 0:
+		ldev->switch_on_headphone = !!ucontrol->value.integer.value[0];
+		break;
+	case 1:
+		ldev->switch_on_lineout = !!ucontrol->value.integer.value[0];
+		break;
+	default:
+		return -ENODEV;
+	}
+	return 1;
+}
+
+static struct snd_kcontrol_new headphone_detect_choice = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Headphone Detect Autoswitch",
+	.info = control_info,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.get = detect_choice_get,
+	.put = detect_choice_put,
+	.private_value = 0,
+};
+
+static struct snd_kcontrol_new lineout_detect_choice = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Line-Out Detect Autoswitch",
+	.info = control_info,
+	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.get = detect_choice_get,
+	.put = detect_choice_put,
+	.private_value = 1,
+};
+
+static int detected_get(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	struct layout_dev *ldev = snd_kcontrol_chip(kcontrol);
+	int v;
+
+	switch (kcontrol->private_value) {
+	case 0:
+		v = ldev->gpio.methods->get_detect(&ldev->gpio,
+						   AOA_NOTIFY_HEADPHONE);
+		break;
+	case 1:
+		v = ldev->gpio.methods->get_detect(&ldev->gpio,
+						   AOA_NOTIFY_LINE_OUT);
+		break;
+	default:
+		return -ENODEV;
+	}
+	ucontrol->value.integer.value[0] = v;
+	return 0;
+}
+
+static struct snd_kcontrol_new headphone_detected = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Headphone Detected",
+	.info = control_info,
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.get = detected_get,
+	.private_value = 0,
+};
+
+static struct snd_kcontrol_new lineout_detected = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Line-Out Detected",
+	.info = control_info,
+	.access = SNDRV_CTL_ELEM_ACCESS_READ,
+	.get = detected_get,
+	.private_value = 1,
+};
+
+static int check_codec(struct aoa_codec *codec,
+		       struct layout_dev *ldev,
+		       struct codec_connect_info *cci)
+{
+	u32 *ref;
+	char propname[32];
+	struct codec_connection *cc;
+
+	/* if the codec has a 'codec' node, we require a reference */
+	if (codec->node && (strcmp(codec->node->name, "codec") == 0)) {
+		snprintf(propname, sizeof(propname),
+			 "platform-%s-codec-ref", codec->name);
+		ref = (u32*)get_property(ldev->sound, propname, NULL);
+		if (!ref) {
+			printk(KERN_INFO "snd-aoa-fabric-layout: "
+				"required property %s not present\n", propname);
+			return -ENODEV;
+		}
+		if (*ref != codec->node->linux_phandle) {
+			printk(KERN_INFO "snd-aoa-fabric-layout: "
+				"%s doesn't match!\n", propname);
+			return -ENODEV;
+		}
+	} else {
+		if (layouts_list_items != 1) {
+			printk(KERN_INFO "snd-aoa-fabric-layout: "
+				"more than one soundbus, but no references.\n");
+			return -ENODEV;
+		}
+	}
+	codec->soundbus_dev = ldev->sdev;
+	codec->gpio = &ldev->gpio;
+
+	cc = cci->connections;
+	if (!cc)
+		return -EINVAL;
+
+	printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n");
+
+	codec->connected = 0;
+	codec->fabric_data = cc;
+
+	while (cc->connected) {
+		codec->connected |= 1<<cc->codec_bit;
+		cc++;
+	}
+
+	return 0;
+}
+
+static int layout_found_codec(struct aoa_codec *codec)
+{
+	struct layout_dev *ldev;
+	int i;
+
+	list_for_each_entry(ldev, &layouts_list, list) {
+		for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+			if (!ldev->layout->codecs[i].name)
+				continue;
+			if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) {
+				if (check_codec(codec,
+						ldev,
+						&ldev->layout->codecs[i]) == 0)
+					return 0;
+			}
+		}
+	}
+	return -ENODEV;
+}
+
+static void layout_remove_codec(struct aoa_codec *codec)
+{
+	int i;
+	/* here remove the codec from the layout dev's
+	 * codec reference */
+
+	codec->soundbus_dev = NULL;
+	codec->gpio = NULL;
+	for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+	}
+}
+
+static void layout_notify(void *data)
+{
+	struct layout_dev_ptr *dptr = data;
+	struct layout_dev *ldev;
+	int v, update;
+	struct snd_kcontrol *detected, *c;
+	struct snd_card *card = aoa_get_card();
+
+	ldev = dptr->ptr;
+	if (data == &ldev->selfptr_headphone) {
+		v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE);
+		detected = ldev->headphone_detected_ctrl;
+		update = ldev->switch_on_headphone;
+		if (update) {
+			ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
+			ldev->gpio.methods->set_headphone(&ldev->gpio, v);
+			ldev->gpio.methods->set_lineout(&ldev->gpio, 0);
+		}
+	} else if (data == &ldev->selfptr_lineout) {
+		v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT);
+		detected = ldev->lineout_detected_ctrl;
+		update = ldev->switch_on_lineout;
+		if (update) {
+			ldev->gpio.methods->set_speakers(&ldev->gpio, !v);
+			ldev->gpio.methods->set_headphone(&ldev->gpio, 0);
+			ldev->gpio.methods->set_lineout(&ldev->gpio, v);
+		}
+	} else
+		return;
+
+	if (detected)
+		snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id);
+	if (update) {
+		c = ldev->headphone_ctrl;
+		if (c)
+			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
+		c = ldev->speaker_ctrl;
+		if (c)
+			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
+		c = ldev->lineout_ctrl;
+		if (c)
+			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id);
+	}
+}
+
+static void layout_attached_codec(struct aoa_codec *codec)
+{
+	struct codec_connection *cc;
+	struct snd_kcontrol *ctl;
+	int headphones, lineout;
+	struct layout_dev *ldev = layout_device;
+
+	/* need to add this codec to our codec array! */
+
+	cc = codec->fabric_data;
+
+	headphones = codec->gpio->methods->get_detect(codec->gpio,
+						      AOA_NOTIFY_HEADPHONE);
+ 	lineout = codec->gpio->methods->get_detect(codec->gpio,
+						   AOA_NOTIFY_LINE_OUT);
+
+	while (cc->connected) {
+		if (cc->connected & CC_SPEAKERS) {
+			if (headphones <= 0 && lineout <= 0)
+				ldev->gpio.methods->set_speakers(codec->gpio, 1);
+			ctl = snd_ctl_new1(&speakers_ctl, codec->gpio);
+			ldev->speaker_ctrl = ctl;
+			aoa_snd_ctl_add(ctl);
+		}
+		if (cc->connected & CC_HEADPHONE) {
+			if (headphones == 1)
+				ldev->gpio.methods->set_headphone(codec->gpio, 1);
+			ctl = snd_ctl_new1(&headphone_ctl, codec->gpio);
+			ldev->headphone_ctrl = ctl;
+			aoa_snd_ctl_add(ctl);
+			ldev->have_headphone_detect =
+				!ldev->gpio.methods
+					->set_notify(&ldev->gpio,
+						     AOA_NOTIFY_HEADPHONE,
+						     layout_notify,
+						     &ldev->selfptr_headphone);
+			if (ldev->have_headphone_detect) {
+				ctl = snd_ctl_new1(&headphone_detect_choice,
+						   ldev);
+				aoa_snd_ctl_add(ctl);
+				ctl = snd_ctl_new1(&headphone_detected,
+						   ldev);
+				ldev->headphone_detected_ctrl = ctl;
+				aoa_snd_ctl_add(ctl);
+			}
+		}
+		if (cc->connected & CC_LINEOUT) {
+			if (lineout == 1)
+				ldev->gpio.methods->set_lineout(codec->gpio, 1);
+			ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
+			if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
+				strlcpy(ctl->id.name,
+					"Headphone Switch", sizeof(ctl->id.name));
+			ldev->lineout_ctrl = ctl;
+			aoa_snd_ctl_add(ctl);
+			ldev->have_lineout_detect =
+				!ldev->gpio.methods
+					->set_notify(&ldev->gpio,
+						     AOA_NOTIFY_LINE_OUT,
+						     layout_notify,
+						     &ldev->selfptr_lineout);
+			if (ldev->have_lineout_detect) {
+				ctl = snd_ctl_new1(&lineout_detect_choice,
+						   ldev);
+				if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
+					strlcpy(ctl->id.name,
+						"Headphone Detect Autoswitch",
+						sizeof(ctl->id.name));
+				aoa_snd_ctl_add(ctl);
+				ctl = snd_ctl_new1(&lineout_detected,
+						   ldev);
+				if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
+					strlcpy(ctl->id.name,
+						"Headphone Detected",
+						sizeof(ctl->id.name));
+				ldev->lineout_detected_ctrl = ctl;
+				aoa_snd_ctl_add(ctl);
+			}
+		}
+		cc++;
+	}
+	/* now update initial state */
+	if (ldev->have_headphone_detect)
+		layout_notify(&ldev->selfptr_headphone);
+	if (ldev->have_lineout_detect)
+		layout_notify(&ldev->selfptr_lineout);
+}
+
+static struct aoa_fabric layout_fabric = {
+	.name = "SoundByLayout",
+	.owner = THIS_MODULE,
+	.found_codec = layout_found_codec,
+	.remove_codec = layout_remove_codec,
+	.attached_codec = layout_attached_codec,
+};
+
+static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
+{
+	struct device_node *sound = NULL;
+	unsigned int *layout_id;
+	struct layout *layout;
+	struct layout_dev *ldev = NULL;
+	int err;
+
+	/* hm, currently we can only have one ... */
+	if (layout_device)
+		return -ENODEV;
+
+	/* by breaking out we keep a reference */
+	while ((sound = of_get_next_child(sdev->ofdev.node, sound))) {
+		if (sound->type && strcasecmp(sound->type, "soundchip") == 0)
+			break;
+	}
+	if (!sound) return -ENODEV;
+
+	layout_id = (unsigned int *) get_property(sound, "layout-id", NULL);
+	if (!layout_id)
+		goto outnodev;
+	printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d ", *layout_id);
+
+	layout = find_layout_by_id(*layout_id);
+	if (!layout) {
+		printk("(no idea how to handle)\n");
+		goto outnodev;
+	}
+
+	ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL);
+	if (!ldev)
+		goto outnodev;
+
+	layout_device = ldev;
+	ldev->sdev = sdev;
+	ldev->sound = sound;
+	ldev->layout = layout;
+	ldev->gpio.node = sound->parent;
+	switch (layout->layout_id) {
+	case 41: /* that unknown machine no one seems to have */
+	case 51: /* PowerBook5,4 */
+	case 58: /* Mac Mini */
+		ldev->gpio.methods = ftr_gpio_methods;
+		break;
+	default:
+		ldev->gpio.methods = pmf_gpio_methods;
+	}
+	ldev->selfptr_headphone.ptr = ldev;
+	ldev->selfptr_lineout.ptr = ldev;
+	sdev->ofdev.dev.driver_data = ldev;
+
+	printk("(using)\n");
+	list_add(&ldev->list, &layouts_list);
+	layouts_list_items++;
+
+	/* assign these before registering ourselves, so
+	 * callbacks that are done during registration
+	 * already have the values */
+	sdev->pcmid = ldev->layout->pcmid;
+	if (ldev->layout->busname) {
+		sdev->pcmname = ldev->layout->busname;
+	} else {
+		sdev->pcmname = "Master";
+	}
+
+	ldev->gpio.methods->init(&ldev->gpio);
+
+	err = aoa_fabric_register(&layout_fabric);
+	if (err && err != -EALREADY) {
+		printk(KERN_INFO "snd-aoa-fabric-layout: can't use,"
+				 " another fabric is active!\n");
+		goto outlistdel;
+	}
+
+	use_layout(layout);
+	ldev->switch_on_headphone = 1;
+	ldev->switch_on_lineout = 1;
+	return 0;
+ outlistdel:
+	/* we won't be using these then... */
+	ldev->gpio.methods->exit(&ldev->gpio);
+	/* reset if we didn't use it */
+	sdev->pcmname = NULL;
+	sdev->pcmid = -1;
+	list_del(&ldev->list);
+	layouts_list_items--;
+ outnodev:
+ 	if (sound) of_node_put(sound);
+ 	layout_device = NULL;
+ 	if (ldev) kfree(ldev);
+	return -ENODEV;
+}
+
+static int aoa_fabric_layout_remove(struct soundbus_dev *sdev)
+{
+	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+	int i;
+
+	for (i=0; i<MAX_CODECS_PER_BUS; i++) {
+		if (ldev->codecs[i]) {
+			aoa_fabric_unlink_codec(ldev->codecs[i]);
+		}
+		ldev->codecs[i] = NULL;
+	}
+	list_del(&ldev->list);
+	layouts_list_items--;
+	of_node_put(ldev->sound);
+
+	ldev->gpio.methods->set_notify(&ldev->gpio,
+				       AOA_NOTIFY_HEADPHONE,
+				       NULL,
+				       NULL);
+	ldev->gpio.methods->set_notify(&ldev->gpio,
+				       AOA_NOTIFY_LINE_OUT,
+				       NULL,
+				       NULL);
+
+	ldev->gpio.methods->exit(&ldev->gpio);
+	layout_device = NULL;
+	kfree(ldev);
+	sdev->pcmid = -1;
+	sdev->pcmname = NULL;
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state)
+{
+	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+
+	printk("aoa_fabric_layout_suspend()\n");
+
+	if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
+		ldev->gpio.methods->all_amps_off(&ldev->gpio);
+
+	return 0;
+}
+
+static int aoa_fabric_layout_resume(struct soundbus_dev *sdev)
+{
+	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+
+	printk("aoa_fabric_layout_resume()\n");
+
+	if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
+		ldev->gpio.methods->all_amps_restore(&ldev->gpio);
+
+	return 0;
+}
+#endif
+
+static struct soundbus_driver aoa_soundbus_driver = {
+	.name = "snd_aoa_soundbus_drv",
+	.owner = THIS_MODULE,
+	.probe = aoa_fabric_layout_probe,
+	.remove = aoa_fabric_layout_remove,
+#ifdef CONFIG_PM
+	.suspend = aoa_fabric_layout_suspend,
+	.resume = aoa_fabric_layout_resume,
+#endif
+};
+
+static int __init aoa_fabric_layout_init(void)
+{
+	int err;
+
+	err = soundbus_register_driver(&aoa_soundbus_driver);
+	if (err)
+		return err;
+	return 0;
+}
+
+static void __exit aoa_fabric_layout_exit(void)
+{
+	soundbus_unregister_driver(&aoa_soundbus_driver);
+	aoa_fabric_unregister(&layout_fabric);
+}
+
+module_init(aoa_fabric_layout_init);
+module_exit(aoa_fabric_layout_exit);
diff --git a/sound/aoa/soundbus/Kconfig b/sound/aoa/soundbus/Kconfig
new file mode 100644
index 0000000..d532d27
--- /dev/null
+++ b/sound/aoa/soundbus/Kconfig
@@ -0,0 +1,14 @@
+config SND_AOA_SOUNDBUS
+	tristate "Apple Soundbus support"
+	depends on SOUND && SND_PCM && EXPERIMENTAL
+	---help---
+	This option enables the generic driver for the soundbus
+	support on Apple machines.
+	
+	It is required for the sound bus implementations.
+
+config SND_AOA_SOUNDBUS_I2S
+	tristate "I2S bus support"
+	depends on SND_AOA_SOUNDBUS && PCI
+	---help---
+	This option enables support for Apple I2S busses.
diff --git a/sound/aoa/soundbus/Makefile b/sound/aoa/soundbus/Makefile
new file mode 100644
index 0000000..0e61f5a
--- /dev/null
+++ b/sound/aoa/soundbus/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SND_AOA_SOUNDBUS) += snd-aoa-soundbus.o
+snd-aoa-soundbus-objs := core.o sysfs.o
+obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += i2sbus/
diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c
new file mode 100644
index 0000000..abe84a7
--- /dev/null
+++ b/sound/aoa/soundbus/core.c
@@ -0,0 +1,250 @@
+/*
+ * soundbus
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <linux/module.h>
+#include "soundbus.h"
+
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Apple Soundbus");
+
+struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev)
+{
+	struct device *tmp;
+
+	if (!dev)
+		return NULL;
+	tmp = get_device(&dev->ofdev.dev);
+	if (tmp)
+		return to_soundbus_device(tmp);
+	else
+		return NULL;
+}
+EXPORT_SYMBOL_GPL(soundbus_dev_get);
+
+void soundbus_dev_put(struct soundbus_dev *dev)
+{
+	if (dev)
+		put_device(&dev->ofdev.dev);
+}
+EXPORT_SYMBOL_GPL(soundbus_dev_put);
+
+static int soundbus_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct soundbus_driver *drv;
+	struct soundbus_dev *soundbus_dev;
+
+	drv = to_soundbus_driver(dev->driver);
+	soundbus_dev = to_soundbus_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	soundbus_dev_get(soundbus_dev);
+
+	error = drv->probe(soundbus_dev);
+	if (error)
+		soundbus_dev_put(soundbus_dev);
+
+	return error;
+}
+
+
+static int soundbus_uevent(struct device *dev, char **envp, int num_envp,
+			   char *buffer, int buffer_size)
+{
+	struct soundbus_dev * soundbus_dev;
+	struct of_device * of;
+	char *scratch, *compat, *compat2;
+	int i = 0;
+	int length, cplen, cplen2, seen = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	soundbus_dev = to_soundbus_device(dev);
+	if (!soundbus_dev)
+		return -ENODEV;
+
+	of = &soundbus_dev->ofdev;
+
+	/* stuff we want to pass to /sbin/hotplug */
+	envp[i++] = scratch = buffer;
+	length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name);
+	++length;
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
+	scratch += length;
+
+	envp[i++] = scratch;
+	length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type);
+	++length;
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
+	scratch += length;
+
+	/* Since the compatible field can contain pretty much anything
+	 * it's not really legal to split it out with commas. We split it
+	 * up using a number of environment variables instead. */
+
+	compat = (char *) get_property(of->node, "compatible", &cplen);
+	compat2 = compat;
+	cplen2= cplen;
+	while (compat && cplen > 0) {
+		envp[i++] = scratch;
+		length = scnprintf (scratch, buffer_size,
+				     "OF_COMPATIBLE_%d=%s", seen, compat);
+		++length;
+		buffer_size -= length;
+		if ((buffer_size <= 0) || (i >= num_envp))
+			return -ENOMEM;
+		scratch += length;
+		length = strlen (compat) + 1;
+		compat += length;
+		cplen -= length;
+		seen++;
+	}
+
+	envp[i++] = scratch;
+	length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen);
+	++length;
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
+	scratch += length;
+
+	envp[i++] = scratch;
+	length = scnprintf (scratch, buffer_size, "MODALIAS=%s",
+			soundbus_dev->modalias);
+
+	buffer_size -= length;
+	if ((buffer_size <= 0) || (i >= num_envp))
+		return -ENOMEM;
+
+	envp[i] = NULL;
+
+	return 0;
+}
+
+static int soundbus_device_remove(struct device *dev)
+{
+	struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+	struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(soundbus_dev);
+	soundbus_dev_put(soundbus_dev);
+
+	return 0;
+}
+
+static void soundbus_device_shutdown(struct device *dev)
+{
+	struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+	struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+	if (dev->driver && drv->shutdown)
+		drv->shutdown(soundbus_dev);
+}
+
+#ifdef CONFIG_PM
+
+static int soundbus_device_suspend(struct device *dev, pm_message_t state)
+{
+	struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+	struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+	if (dev->driver && drv->suspend)
+		return drv->suspend(soundbus_dev, state);
+	return 0;
+}
+
+static int soundbus_device_resume(struct device * dev)
+{
+	struct soundbus_dev * soundbus_dev = to_soundbus_device(dev);
+	struct soundbus_driver * drv = to_soundbus_driver(dev->driver);
+
+	if (dev->driver && drv->resume)
+		return drv->resume(soundbus_dev);
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+extern struct device_attribute soundbus_dev_attrs[];
+
+static struct bus_type soundbus_bus_type = {
+	.name		= "aoa-soundbus",
+	.probe		= soundbus_probe,
+	.uevent		= soundbus_uevent,
+	.remove		= soundbus_device_remove,
+	.shutdown	= soundbus_device_shutdown,
+#ifdef CONFIG_PM
+	.suspend	= soundbus_device_suspend,
+	.resume		= soundbus_device_resume,
+#endif
+	.dev_attrs	= soundbus_dev_attrs,
+};
+
+static int __init soundbus_init(void)
+{
+	return bus_register(&soundbus_bus_type);
+}
+
+static void __exit soundbus_exit(void)
+{
+	bus_unregister(&soundbus_bus_type);
+}
+
+int soundbus_add_one(struct soundbus_dev *dev)
+{
+	static int devcount;
+
+	/* sanity checks */
+	if (!dev->attach_codec ||
+	    !dev->ofdev.node ||
+	    dev->pcmname ||
+	    dev->pcmid != -1) {
+		printk(KERN_ERR "soundbus: adding device failed sanity check!\n");
+		return -EINVAL;
+	}
+
+	snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount);
+	dev->ofdev.dev.bus = &soundbus_bus_type;
+	return of_device_register(&dev->ofdev);
+}
+EXPORT_SYMBOL_GPL(soundbus_add_one);
+
+void soundbus_remove_one(struct soundbus_dev *dev)
+{
+	of_device_unregister(&dev->ofdev);
+}
+EXPORT_SYMBOL_GPL(soundbus_remove_one);
+
+int soundbus_register_driver(struct soundbus_driver *drv)
+{
+	/* initialize common driver fields */
+	drv->driver.name = drv->name;
+	drv->driver.bus = &soundbus_bus_type;
+
+	/* register with core */
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(soundbus_register_driver);
+
+void soundbus_unregister_driver(struct soundbus_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(soundbus_unregister_driver);
+
+module_init(soundbus_init);
+module_exit(soundbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile
new file mode 100644
index 0000000..e57a5cf
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o
+snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
new file mode 100644
index 0000000..f504079
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
@@ -0,0 +1,192 @@
+/*
+ * i2sbus driver -- bus control routines
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <asm/prom.h>
+#include <asm/macio.h>
+#include <asm/pmac_feature.h>
+#include <asm/pmac_pfunc.h>
+#include "i2sbus.h"
+
+int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c)
+{
+	*c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL);
+	if (!*c)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&(*c)->list);
+
+	if (of_address_to_resource(dev->ofdev.node, 0, &(*c)->rsrc))
+		goto err;
+	/* we really should be using feature calls instead of mapping
+	 * these registers. It's safe for now since no one else is
+	 * touching them... */
+	(*c)->controlregs = ioremap((*c)->rsrc.start,
+				    sizeof(struct i2s_control_regs));
+	if (!(*c)->controlregs)
+		goto err;
+
+	return 0;
+ err:
+	kfree(*c);
+	*c = NULL;
+	return -ENODEV;
+}
+
+void i2sbus_control_destroy(struct i2sbus_control *c)
+{
+	iounmap(c->controlregs);
+	kfree(c);
+}
+
+/* this is serialised externally */
+int i2sbus_control_add_dev(struct i2sbus_control *c,
+			   struct i2sbus_dev *i2sdev)
+{
+	struct device_node *np;
+
+	np = i2sdev->sound.ofdev.node;
+	i2sdev->enable = pmf_find_function(np, "enable");
+	i2sdev->cell_enable = pmf_find_function(np, "cell-enable");
+	i2sdev->clock_enable = pmf_find_function(np, "clock-enable");
+	i2sdev->cell_disable = pmf_find_function(np, "cell-disable");
+	i2sdev->clock_disable = pmf_find_function(np, "clock-disable");
+
+	/* if the bus number is not 0 or 1 we absolutely need to use
+	 * the platform functions -- there's nothing in Darwin that
+	 * would allow seeing a system behind what the FCRs are then,
+	 * and I don't want to go parsing a bunch of platform functions
+	 * by hand to try finding a system... */
+	if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 &&
+	    (!i2sdev->enable ||
+	     !i2sdev->cell_enable || !i2sdev->clock_enable ||
+	     !i2sdev->cell_disable || !i2sdev->clock_disable)) {
+		pmf_put_function(i2sdev->enable);
+		pmf_put_function(i2sdev->cell_enable);
+		pmf_put_function(i2sdev->clock_enable);
+		pmf_put_function(i2sdev->cell_disable);
+		pmf_put_function(i2sdev->clock_disable);
+		return -ENODEV;
+	}
+
+	list_add(&i2sdev->item, &c->list);
+
+	return 0;
+}
+
+void i2sbus_control_remove_dev(struct i2sbus_control *c,
+			       struct i2sbus_dev *i2sdev)
+{
+	/* this is serialised externally */
+	list_del(&i2sdev->item);
+	if (list_empty(&c->list))
+		i2sbus_control_destroy(c);
+}
+
+int i2sbus_control_enable(struct i2sbus_control *c,
+			  struct i2sbus_dev *i2sdev)
+{
+	struct pmf_args args = { .count = 0 };
+	int cc;
+
+	if (i2sdev->enable)
+		return pmf_call_one(i2sdev->enable, &args);
+
+	switch (i2sdev->bus_number) {
+	case 0:
+		cc = in_le32(&c->controlregs->cell_control);
+		out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_0_ENABLE);
+		break;
+	case 1:
+		cc = in_le32(&c->controlregs->cell_control);
+		out_le32(&c->controlregs->cell_control, cc | CTRL_CLOCK_INTF_1_ENABLE);
+		break;
+	default:
+		return -ENODEV;
+	}
+	return 0;
+}
+
+int i2sbus_control_cell(struct i2sbus_control *c,
+			struct i2sbus_dev *i2sdev,
+			int enable)
+{
+	struct pmf_args args = { .count = 0 };
+	int cc;
+
+	switch (enable) {
+	case 0:
+		if (i2sdev->cell_disable)
+			return pmf_call_one(i2sdev->cell_disable, &args);
+		break;
+	case 1:
+		if (i2sdev->cell_enable)
+			return pmf_call_one(i2sdev->cell_enable, &args);
+		break;
+	default:
+		printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n");
+		return -ENODEV;
+	}
+	switch (i2sdev->bus_number) {
+	case 0:
+		cc = in_le32(&c->controlregs->cell_control);
+		cc &= ~CTRL_CLOCK_CELL_0_ENABLE;
+		cc |= enable * CTRL_CLOCK_CELL_0_ENABLE;
+		out_le32(&c->controlregs->cell_control, cc);
+		break;
+	case 1:
+		cc = in_le32(&c->controlregs->cell_control);
+		cc &= ~CTRL_CLOCK_CELL_1_ENABLE;
+		cc |= enable * CTRL_CLOCK_CELL_1_ENABLE;
+		out_le32(&c->controlregs->cell_control, cc);
+		break;
+	default:
+		return -ENODEV;
+	}
+	return 0;
+}
+
+int i2sbus_control_clock(struct i2sbus_control *c,
+			 struct i2sbus_dev *i2sdev,
+			 int enable)
+{
+	struct pmf_args args = { .count = 0 };
+	int cc;
+
+	switch (enable) {
+	case 0:
+		if (i2sdev->clock_disable)
+			return pmf_call_one(i2sdev->clock_disable, &args);
+		break;
+	case 1:
+		if (i2sdev->clock_enable)
+			return pmf_call_one(i2sdev->clock_enable, &args);
+		break;
+	default:
+		printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n");
+		return -ENODEV;
+	}
+	switch (i2sdev->bus_number) {
+	case 0:
+		cc = in_le32(&c->controlregs->cell_control);
+		cc &= ~CTRL_CLOCK_CLOCK_0_ENABLE;
+		cc |= enable * CTRL_CLOCK_CLOCK_0_ENABLE;
+		out_le32(&c->controlregs->cell_control, cc);
+		break;
+	case 1:
+		cc = in_le32(&c->controlregs->cell_control);
+		cc &= ~CTRL_CLOCK_CLOCK_1_ENABLE;
+		cc |= enable * CTRL_CLOCK_CLOCK_1_ENABLE;
+		out_le32(&c->controlregs->cell_control, cc);
+		break;
+	default:
+		return -ENODEV;
+	}
+	return 0;
+}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.h b/sound/aoa/soundbus/i2sbus/i2sbus-control.h
new file mode 100644
index 0000000..bb05550
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.h
@@ -0,0 +1,37 @@
+/*
+ * i2sbus driver -- bus register definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __I2SBUS_CONTROLREGS_H
+#define __I2SBUS_CONTROLREGS_H
+
+/* i2s control registers, at least what we know about them */
+
+#define __PAD(m,n) u8 __pad##m[n]
+#define _PAD(line, n) __PAD(line, n)
+#define PAD(n) _PAD(__LINE__, (n))
+struct i2s_control_regs {
+	PAD(0x38);
+	__le32 fcr0;		/* 0x38 (unknown) */
+	__le32 cell_control;	/* 0x3c (fcr1) */
+	__le32 fcr2;		/* 0x40 (unknown) */
+	__le32 fcr3;		/* 0x44 (fcr3) */
+	__le32 clock_control;	/* 0x48 (unknown) */
+	PAD(4);
+	/* total size: 0x50 bytes */
+}  __attribute__((__packed__));
+
+#define CTRL_CLOCK_CELL_0_ENABLE	(1<<10)
+#define CTRL_CLOCK_CLOCK_0_ENABLE	(1<<12)
+#define CTRL_CLOCK_SWRESET_0		(1<<11)
+#define CTRL_CLOCK_INTF_0_ENABLE	(1<<13)
+
+#define CTRL_CLOCK_CELL_1_ENABLE	(1<<17)
+#define CTRL_CLOCK_CLOCK_1_ENABLE	(1<<18)
+#define CTRL_CLOCK_SWRESET_1		(1<<19)
+#define CTRL_CLOCK_INTF_1_ENABLE	(1<<20)
+
+#endif /* __I2SBUS_CONTROLREGS_H */
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
new file mode 100644
index 0000000..f268dac
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -0,0 +1,387 @@
+/*
+ * i2sbus driver
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <linux/module.h>
+#include <asm/macio.h>
+#include <asm/dbdma.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <linux/dma-mapping.h>
+#include "../soundbus.h"
+#include "i2sbus.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_DESCRIPTION("Apple Soundbus: I2S support");
+/* for auto-loading, declare that we handle this weird
+ * string that macio puts into the relevant device */
+MODULE_ALIAS("of:Ni2sTi2sC");
+
+static struct of_device_id i2sbus_match[] = {
+	{ .name = "i2s" },
+	{ }
+};
+
+static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
+				       struct dbdma_command_mem *r,
+				       int numcmds)
+{
+	/* one more for rounding */
+	r->size = (numcmds+1) * sizeof(struct dbdma_cmd);
+	/* We use the PCI APIs for now until the generic one gets fixed
+	 * enough or until we get some macio-specific versions
+	 */
+	r->space = dma_alloc_coherent(
+			&macio_get_pci_dev(i2sdev->macio)->dev,
+			r->size,
+			&r->bus_addr,
+			GFP_KERNEL);
+
+	if (!r->space) return -ENOMEM;
+
+	memset(r->space, 0, r->size);
+	r->cmds = (void*)DBDMA_ALIGN(r->space);
+	r->bus_cmd_start = r->bus_addr +
+			   (dma_addr_t)((char*)r->cmds - (char*)r->space);
+
+	return 0;
+}
+
+static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
+				       struct dbdma_command_mem *r)
+{
+	if (!r->space) return;
+	
+	dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
+			    r->size, r->space, r->bus_addr);
+}
+
+static void i2sbus_release_dev(struct device *dev)
+{
+	struct i2sbus_dev *i2sdev;
+	int i;
+
+	i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev);
+
+ 	if (i2sdev->intfregs) iounmap(i2sdev->intfregs);
+ 	if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma);
+ 	if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma);
+	for (i=0;i<3;i++)
+		if (i2sdev->allocated_resource[i])
+			release_and_free_resource(i2sdev->allocated_resource[i]);
+	free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring);
+	free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring);
+	for (i=0;i<3;i++)
+		free_irq(i2sdev->interrupts[i], i2sdev);
+	i2sbus_control_remove_dev(i2sdev->control, i2sdev);
+	mutex_destroy(&i2sdev->lock);
+	kfree(i2sdev);
+}
+
+static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs)
+{
+	struct i2sbus_dev *dev = devid;
+	u32 intreg;
+
+	spin_lock(&dev->low_lock);
+	intreg = in_le32(&dev->intfregs->intr_ctl);
+
+	/* acknowledge interrupt reasons */
+	out_le32(&dev->intfregs->intr_ctl, intreg);
+
+	spin_unlock(&dev->low_lock);
+
+	return IRQ_HANDLED;
+}
+
+static int force;
+module_param(force, int, 0444);
+MODULE_PARM_DESC(force, "Force loading i2sbus even when"
+			" no layout-id property is present");
+
+/* FIXME: look at device node refcounting */
+static int i2sbus_add_dev(struct macio_dev *macio,
+			  struct i2sbus_control *control,
+			  struct device_node *np)
+{
+	struct i2sbus_dev *dev;
+	struct device_node *child = NULL, *sound = NULL;
+	int i;
+	static const char *rnames[] = { "i2sbus: %s (control)",
+					"i2sbus: %s (tx)",
+					"i2sbus: %s (rx)" };
+	static irqreturn_t (*ints[])(int irq, void *devid,
+				     struct pt_regs *regs) = {
+		i2sbus_bus_intr,
+		i2sbus_tx_intr,
+		i2sbus_rx_intr
+	};
+
+	if (strlen(np->name) != 5)
+		return 0;
+	if (strncmp(np->name, "i2s-", 4))
+		return 0;
+
+	if (np->n_intrs != 3)
+		return 0;
+
+	dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL);
+	if (!dev)
+		return 0;
+
+	i = 0;
+	while ((child = of_get_next_child(np, child))) {
+		if (strcmp(child->name, "sound") == 0) {
+			i++;
+			sound = child;
+		}
+	}
+	if (i == 1) {
+		u32 *layout_id;
+		layout_id = (u32*) get_property(sound, "layout-id", NULL);
+		if (layout_id) {
+			snprintf(dev->sound.modalias, 32,
+				 "sound-layout-%d", *layout_id);
+			force = 1;
+		}
+	}
+	/* for the time being, until we can handle non-layout-id
+	 * things in some fabric, refuse to attach if there is no
+	 * layout-id property or we haven't been forced to attach.
+	 * When there are two i2s busses and only one has a layout-id,
+	 * then this depends on the order, but that isn't important
+	 * either as the second one in that case is just a modem. */
+	if (!force) {
+		kfree(dev);
+		return -ENODEV;
+	}
+
+	mutex_init(&dev->lock);
+	spin_lock_init(&dev->low_lock);
+	dev->sound.ofdev.node = np;
+	dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask;
+	dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask;
+	dev->sound.ofdev.dev.parent = &macio->ofdev.dev;
+	dev->sound.ofdev.dev.release = i2sbus_release_dev;
+	dev->sound.attach_codec = i2sbus_attach_codec;
+	dev->sound.detach_codec = i2sbus_detach_codec;
+	dev->sound.pcmid = -1;
+	dev->macio = macio;
+	dev->control = control;
+	dev->bus_number = np->name[4] - 'a';
+	INIT_LIST_HEAD(&dev->sound.codec_list);
+
+	for (i=0;i<3;i++) {
+		dev->interrupts[i] = -1;
+		snprintf(dev->rnames[i], sizeof(dev->rnames[i]), rnames[i], np->name);
+	}
+	for (i=0;i<3;i++) {
+		if (request_irq(np->intrs[i].line, ints[i], 0, dev->rnames[i], dev))
+			goto err;
+		dev->interrupts[i] = np->intrs[i].line;
+	}
+
+	for (i=0;i<3;i++) {
+		if (of_address_to_resource(np, i, &dev->resources[i]))
+			goto err;
+		/* if only we could use our resource dev->resources[i]...
+		 * but request_resource doesn't know about parents and
+		 * contained resources... */
+		dev->allocated_resource[i] = 
+			request_mem_region(dev->resources[i].start,
+					   dev->resources[i].end -
+					   dev->resources[i].start + 1,
+					   dev->rnames[i]);
+		if (!dev->allocated_resource[i]) {
+			printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i);
+			goto err;
+		}
+	}
+	/* should do sanity checking here about length of them */
+	dev->intfregs = ioremap(dev->resources[0].start,
+				dev->resources[0].end-dev->resources[0].start+1);
+	dev->out.dbdma = ioremap(dev->resources[1].start,
+			 	 dev->resources[1].end-dev->resources[1].start+1);
+	dev->in.dbdma = ioremap(dev->resources[2].start,
+				dev->resources[2].end-dev->resources[2].start+1);
+	if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma)
+		goto err;
+
+	if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring,
+					MAX_DBDMA_COMMANDS))
+		goto err;
+	if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring,
+					MAX_DBDMA_COMMANDS))
+		goto err;
+
+	if (i2sbus_control_add_dev(dev->control, dev)) {
+		printk(KERN_ERR "i2sbus: control layer didn't like bus\n");
+		goto err;
+	}
+
+	if (soundbus_add_one(&dev->sound)) {
+		printk(KERN_DEBUG "i2sbus: device registration error!\n");
+		goto err;
+	}
+
+	/* enable this cell */
+	i2sbus_control_cell(dev->control, dev, 1);
+	i2sbus_control_enable(dev->control, dev);
+	i2sbus_control_clock(dev->control, dev, 1);
+
+	return 1;
+ err:
+	for (i=0;i<3;i++)
+		if (dev->interrupts[i] != -1)
+			free_irq(dev->interrupts[i], dev);
+	free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring);
+	free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring);
+	if (dev->intfregs) iounmap(dev->intfregs);
+	if (dev->out.dbdma) iounmap(dev->out.dbdma);
+	if (dev->in.dbdma) iounmap(dev->in.dbdma);
+	for (i=0;i<3;i++)
+		if (dev->allocated_resource[i])
+			release_and_free_resource(dev->allocated_resource[i]);
+	mutex_destroy(&dev->lock);
+	kfree(dev);
+	return 0;
+}
+
+static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
+{
+	struct device_node *np = NULL;
+	int got = 0, err;
+	struct i2sbus_control *control = NULL;
+
+	err = i2sbus_control_init(dev, &control);
+	if (err)
+		return err;
+	if (!control) {
+		printk(KERN_ERR "i2sbus_control_init API breakage\n");
+		return -ENODEV;
+	}
+
+	while ((np = of_get_next_child(dev->ofdev.node, np))) {
+		if (device_is_compatible(np, "i2sbus") ||
+		    device_is_compatible(np, "i2s-modem")) {
+			got += i2sbus_add_dev(dev, control, np);
+		}
+	}
+
+	if (!got) {
+		/* found none, clean up */
+		i2sbus_control_destroy(control);
+		return -ENODEV;
+	}
+
+	dev->ofdev.dev.driver_data = control;
+
+	return 0;
+}
+
+static int i2sbus_remove(struct macio_dev* dev)
+{
+	struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+	struct i2sbus_dev *i2sdev, *tmp;
+
+	list_for_each_entry_safe(i2sdev, tmp, &control->list, item)
+		soundbus_remove_one(&i2sdev->sound);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
+{
+	struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+	struct codec_info_item *cii;
+	struct i2sbus_dev* i2sdev;
+	int err, ret = 0;
+
+	list_for_each_entry(i2sdev, &control->list, item) {
+		/* Notify Alsa */
+		if (i2sdev->sound.pcm) {
+			/* Suspend PCM streams */
+			snd_pcm_suspend_all(i2sdev->sound.pcm);
+			/* Probably useless as we handle
+			 * power transitions ourselves */
+			snd_power_change_state(i2sdev->sound.pcm->card,
+					       SNDRV_CTL_POWER_D3hot);
+		}
+		/* Notify codecs */
+		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+			err = 0;
+			if (cii->codec->suspend)
+				err = cii->codec->suspend(cii, state);
+			if (err)
+				ret = err;
+		}
+	}
+	return ret;
+}
+
+static int i2sbus_resume(struct macio_dev* dev)
+{
+	struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+	struct codec_info_item *cii;
+	struct i2sbus_dev* i2sdev;
+	int err, ret = 0;
+
+	list_for_each_entry(i2sdev, &control->list, item) {
+		/* Notify codecs so they can re-initialize */
+		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+			err = 0;
+			if (cii->codec->resume)
+				err = cii->codec->resume(cii);
+			if (err)
+				ret = err;
+		}
+		/* Notify Alsa */
+		if (i2sdev->sound.pcm) {
+			/* Same comment as above, probably useless */
+			snd_power_change_state(i2sdev->sound.pcm->card,
+					       SNDRV_CTL_POWER_D0);
+		}
+	}
+
+	return ret;
+}
+#endif /* CONFIG_PM */
+
+static int i2sbus_shutdown(struct macio_dev* dev)
+{
+	return 0;
+}
+
+static struct macio_driver i2sbus_drv = {
+	.name = "soundbus-i2s",
+	.owner = THIS_MODULE,
+	.match_table = i2sbus_match,
+	.probe = i2sbus_probe,
+	.remove = i2sbus_remove,
+#ifdef CONFIG_PM
+	.suspend = i2sbus_suspend,
+	.resume = i2sbus_resume,
+#endif
+	.shutdown = i2sbus_shutdown,
+};
+
+static int __init soundbus_i2sbus_init(void)
+{
+	return macio_register_driver(&i2sbus_drv);
+}
+
+static void __exit soundbus_i2sbus_exit(void)
+{
+	macio_unregister_driver(&i2sbus_drv);
+}
+
+module_init(soundbus_i2sbus_init);
+module_exit(soundbus_i2sbus_exit);
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
new file mode 100644
index 0000000..c6b5f54
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
@@ -0,0 +1,187 @@
+/*
+ * i2sbus driver -- interface register definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __I2SBUS_INTERFACE_H
+#define __I2SBUS_INTERFACE_H
+
+/* i2s bus control registers, at least what we know about them */
+
+#define __PAD(m,n) u8 __pad##m[n]
+#define _PAD(line, n) __PAD(line, n)
+#define PAD(n) _PAD(__LINE__, (n))
+struct i2s_interface_regs {
+	__le32 intr_ctl;	/* 0x00 */
+	PAD(12);
+	__le32 serial_format;	/* 0x10 */
+	PAD(12);
+	__le32 codec_msg_out;	/* 0x20 */
+	PAD(12);
+	__le32 codec_msg_in;	/* 0x30 */
+	PAD(12);
+	__le32 frame_count;	/* 0x40 */
+	PAD(12);
+	__le32 frame_match;	/* 0x50 */
+	PAD(12);
+	__le32 data_word_sizes;	/* 0x60 */
+	PAD(12);
+	__le32 peak_level_sel;	/* 0x70 */
+	PAD(12);
+	__le32 peak_level_in0;	/* 0x80 */
+	PAD(12);
+	__le32 peak_level_in1;	/* 0x90 */
+	PAD(12);
+	/* total size: 0x100 bytes */
+}  __attribute__((__packed__));
+
+/* interrupt register is just a bitfield with
+ * interrupt enable and pending bits */
+#define I2S_REG_INTR_CTL		0x00
+#	define I2S_INT_FRAME_COUNT		(1<<31)
+#	define I2S_PENDING_FRAME_COUNT		(1<<30)
+#	define I2S_INT_MESSAGE_FLAG		(1<<29)
+#	define I2S_PENDING_MESSAGE_FLAG		(1<<28)
+#	define I2S_INT_NEW_PEAK			(1<<27)
+#	define I2S_PENDING_NEW_PEAK		(1<<26)
+#	define I2S_INT_CLOCKS_STOPPED		(1<<25)
+#	define I2S_PENDING_CLOCKS_STOPPED	(1<<24)
+#	define I2S_INT_EXTERNAL_SYNC_ERROR	(1<<23)
+#	define I2S_PENDING_EXTERNAL_SYNC_ERROR	(1<<22)
+#	define I2S_INT_EXTERNAL_SYNC_OK		(1<<21)
+#	define I2S_PENDING_EXTERNAL_SYNC_OK	(1<<20)
+#	define I2S_INT_NEW_SAMPLE_RATE		(1<<19)
+#	define I2S_PENDING_NEW_SAMPLE_RATE	(1<<18)
+#	define I2S_INT_STATUS_FLAG		(1<<17)
+#	define I2S_PENDING_STATUS_FLAG		(1<<16)
+
+/* serial format register is more interesting :)
+ * It contains:
+ *  - clock source
+ *  - MClk divisor
+ *  - SClk divisor
+ *  - SClk master flag
+ *  - serial format (sony, i2s 64x, i2s 32x, dav, silabs)
+ *  - external sample frequency interrupt (don't understand)
+ *  - external sample frequency
+ */
+#define I2S_REG_SERIAL_FORMAT		0x10
+/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */
+#	define I2S_SF_CLOCK_SOURCE_SHIFT	30
+#	define I2S_SF_CLOCK_SOURCE_MASK		(3<<I2S_SF_CLOCK_SOURCE_SHIFT)
+#	define I2S_SF_CLOCK_SOURCE_18MHz	(0<<I2S_SF_CLOCK_SOURCE_SHIFT)
+#	define I2S_SF_CLOCK_SOURCE_45MHz	(1<<I2S_SF_CLOCK_SOURCE_SHIFT)
+#	define I2S_SF_CLOCK_SOURCE_49MHz	(2<<I2S_SF_CLOCK_SOURCE_SHIFT)
+/* also, let's define the exact clock speeds here, in Hz */
+#define I2S_CLOCK_SPEED_18MHz	18432000
+#define I2S_CLOCK_SPEED_45MHz	45158400
+#define I2S_CLOCK_SPEED_49MHz	49152000
+/* MClk is the clock that drives the codec, usually called its 'system clock'.
+ * It is derived by taking only every 'divisor' tick of the clock.
+ */
+#	define I2S_SF_MCLKDIV_SHIFT		24
+#	define I2S_SF_MCLKDIV_MASK		(0x1F<<I2S_SF_MCLKDIV_SHIFT)
+#	define I2S_SF_MCLKDIV_1			(0x14<<I2S_SF_MCLKDIV_SHIFT)
+#	define I2S_SF_MCLKDIV_3			(0x13<<I2S_SF_MCLKDIV_SHIFT)
+#	define I2S_SF_MCLKDIV_5			(0x12<<I2S_SF_MCLKDIV_SHIFT)
+#	define I2S_SF_MCLKDIV_14		(0x0E<<I2S_SF_MCLKDIV_SHIFT)
+#	define I2S_SF_MCLKDIV_OTHER(div)	(((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK)
+static inline int i2s_sf_mclkdiv(int div, int *out)
+{
+	int d;
+
+	switch(div) {
+	case 1: *out |= I2S_SF_MCLKDIV_1; return 0;
+	case 3: *out |= I2S_SF_MCLKDIV_3; return 0;
+	case 5: *out |= I2S_SF_MCLKDIV_5; return 0;
+	case 14: *out |= I2S_SF_MCLKDIV_14; return 0;
+	default:
+		if (div%2) return -1;
+		d = div/2-1;
+		if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E)
+			return -1;
+		*out |= I2S_SF_MCLKDIV_OTHER(div);
+		return 0;
+	}
+}
+/* SClk is the clock that drives the i2s wire bus. Note that it is
+ * derived from the MClk above by taking only every 'divisor' tick
+ * of MClk.
+ */
+#	define I2S_SF_SCLKDIV_SHIFT		20
+#	define I2S_SF_SCLKDIV_MASK		(0xF<<I2S_SF_SCLKDIV_SHIFT)
+#	define I2S_SF_SCLKDIV_1			(8<<I2S_SF_SCLKDIV_SHIFT)
+#	define I2S_SF_SCLKDIV_3			(9<<I2S_SF_SCLKDIV_SHIFT)
+#	define I2S_SF_SCLKDIV_OTHER(div)	(((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK)
+static inline int i2s_sf_sclkdiv(int div, int *out)
+{
+	int d;
+
+	switch(div) {
+	case 1: *out |= I2S_SF_SCLKDIV_1; return 0;
+	case 3: *out |= I2S_SF_SCLKDIV_3; return 0;
+	default:
+		if (div%2) return -1;
+		d = div/2-1;
+		if (d == 8 || d == 9) return -1;
+		*out |= I2S_SF_SCLKDIV_OTHER(div);
+		return 0;
+	}
+}
+#	define I2S_SF_SCLK_MASTER		(1<<19)
+/* serial format is the way the data is put to the i2s wire bus */
+#	define I2S_SF_SERIAL_FORMAT_SHIFT	16
+#	define I2S_SF_SERIAL_FORMAT_MASK	(7<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#	define I2S_SF_SERIAL_FORMAT_SONY	(0<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#	define I2S_SF_SERIAL_FORMAT_I2S_64X	(1<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#	define I2S_SF_SERIAL_FORMAT_I2S_32X	(2<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#	define I2S_SF_SERIAL_FORMAT_I2S_DAV	(4<<I2S_SF_SERIAL_FORMAT_SHIFT)
+#	define I2S_SF_SERIAL_FORMAT_I2S_SILABS	(5<<I2S_SF_SERIAL_FORMAT_SHIFT)
+/* unknown */
+#	define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT	12
+#	define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK	(0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT)
+/* probably gives external frequency? */
+#	define I2S_SF_EXT_SAMPLE_FREQ_MASK	0xFFF
+
+/* used to send codec messages, but how isn't clear */
+#define I2S_REG_CODEC_MSG_OUT		0x20
+
+/* used to receive codec messages, but how isn't clear */
+#define I2S_REG_CODEC_MSG_IN		0x30
+
+/* frame count reg isn't clear to me yet, but probably useful */
+#define I2S_REG_FRAME_COUNT		0x40
+
+/* program to some value, and get interrupt if frame count reaches it */
+#define I2S_REG_FRAME_MATCH		0x50
+
+/* this register describes how the bus transfers data */
+#define I2S_REG_DATA_WORD_SIZES		0x60
+/* number of interleaved input channels */
+#	define I2S_DWS_NUM_CHANNELS_IN_SHIFT	24
+#	define I2S_DWS_NUM_CHANNELS_IN_MASK	(0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT)
+/* word size of input data */
+#	define I2S_DWS_DATA_IN_SIZE_SHIFT	16
+#	define I2S_DWS_DATA_IN_16BIT		(0<<I2S_DWS_DATA_IN_SIZE_SHIFT)
+#	define I2S_DWS_DATA_IN_24BIT		(3<<I2S_DWS_DATA_IN_SIZE_SHIFT)
+/* number of interleaved output channels */
+#	define I2S_DWS_NUM_CHANNELS_OUT_SHIFT	8
+#	define I2S_DWS_NUM_CHANNELS_OUT_MASK	(0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT)
+/* word size of output data */
+#	define I2S_DWS_DATA_OUT_SIZE_SHIFT	0
+#	define I2S_DWS_DATA_OUT_16BIT		(0<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
+#	define I2S_DWS_DATA_OUT_24BIT		(3<<I2S_DWS_DATA_OUT_SIZE_SHIFT)
+
+
+/* unknown */
+#define I2S_REG_PEAK_LEVEL_SEL		0x70
+
+/* unknown */
+#define I2S_REG_PEAK_LEVEL_IN0		0x80
+
+/* unknown */
+#define I2S_REG_PEAK_LEVEL_IN1		0x90
+
+#endif /* __I2SBUS_INTERFACE_H */
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
new file mode 100644
index 0000000..3049015
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
@@ -0,0 +1,1021 @@
+/*
+ * i2sbus driver -- pcm routines
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+
+#include <asm/io.h>
+#include <linux/delay.h>
+/* So apparently there's a reason for requiring driver.h
+ * to be included first, even if I don't know it... */
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <asm/macio.h>
+#include <linux/pci.h>
+#include "../soundbus.h"
+#include "i2sbus.h"
+
+static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in,
+				struct pcm_info **pi, struct pcm_info **other)
+{
+	if (in) {
+		if (pi)
+			*pi = &i2sdev->in;
+		if (other)
+			*other = &i2sdev->out;
+	} else {
+		if (pi)
+			*pi = &i2sdev->out;
+		if (other)
+			*other = &i2sdev->in;
+	}
+}
+
+static int clock_and_divisors(int mclk, int sclk, int rate, int *out)
+{
+	/* sclk must be derived from mclk! */
+	if (mclk % sclk)
+		return -1;
+	/* derive sclk register value */
+	if (i2s_sf_sclkdiv(mclk / sclk, out))
+		return -1;
+
+	if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) {
+		if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) {
+			*out |= I2S_SF_CLOCK_SOURCE_18MHz;
+			return 0;
+		}
+	}
+	if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) {
+		if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) {
+			*out |= I2S_SF_CLOCK_SOURCE_45MHz;
+			return 0;
+		}
+	}
+	if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) {
+		if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) {
+			*out |= I2S_SF_CLOCK_SOURCE_49MHz;
+			return 0;
+		}
+	}
+	return -1;
+}
+
+#define CHECK_RATE(rate)						\
+	do { if (rates & SNDRV_PCM_RATE_ ##rate) {			\
+		int dummy;						\
+		if (clock_and_divisors(sysclock_factor,			\
+				       bus_factor, rate, &dummy))	\
+			rates &= ~SNDRV_PCM_RATE_ ##rate;		\
+	} } while (0)
+
+static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
+{
+	struct pcm_info *pi, *other;
+	struct soundbus_dev *sdev;
+	int masks_inited = 0, err;
+	struct codec_info_item *cii, *rev;
+	struct snd_pcm_hardware *hw;
+	u64 formats = 0;
+	unsigned int rates = 0;
+	struct transfer_info v;
+	int result = 0;
+	int bus_factor = 0, sysclock_factor = 0;
+	int found_this;
+
+	mutex_lock(&i2sdev->lock);
+
+	get_pcm_info(i2sdev, in, &pi, &other);
+
+	hw = &pi->substream->runtime->hw;
+	sdev = &i2sdev->sound;
+
+	if (pi->active) {
+		/* alsa messed up */
+		result = -EBUSY;
+		goto out_unlock;
+	}
+
+	/* we now need to assign the hw */
+	list_for_each_entry(cii, &sdev->codec_list, list) {
+		struct transfer_info *ti = cii->codec->transfers;
+		bus_factor = cii->codec->bus_factor;
+		sysclock_factor = cii->codec->sysclock_factor;
+		while (ti->formats && ti->rates) {
+			v = *ti;
+			if (ti->transfer_in == in
+			    && cii->codec->usable(cii, ti, &v)) {
+				if (masks_inited) {
+					formats &= v.formats;
+					rates &= v.rates;
+				} else {
+					formats = v.formats;
+					rates = v.rates;
+					masks_inited = 1;
+				}
+			}
+			ti++;
+		}
+	}
+	if (!masks_inited || !bus_factor || !sysclock_factor) {
+		result = -ENODEV;
+		goto out_unlock;
+	}
+	/* bus dependent stuff */
+	hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+		   SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME;
+
+	CHECK_RATE(5512);
+	CHECK_RATE(8000);
+	CHECK_RATE(11025);
+	CHECK_RATE(16000);
+	CHECK_RATE(22050);
+	CHECK_RATE(32000);
+	CHECK_RATE(44100);
+	CHECK_RATE(48000);
+	CHECK_RATE(64000);
+	CHECK_RATE(88200);
+	CHECK_RATE(96000);
+	CHECK_RATE(176400);
+	CHECK_RATE(192000);
+	hw->rates = rates;
+
+	/* well. the codec might want 24 bits only, and we'll
+	 * ever only transfer 24 bits, but they are top-aligned!
+	 * So for alsa, we claim that we're doing full 32 bit
+	 * while in reality we'll ignore the lower 8 bits of
+	 * that when doing playback (they're transferred as 0
+	 * as far as I know, no codecs we have are 32-bit capable
+	 * so I can't really test) and when doing recording we'll
+	 * always have those lower 8 bits recorded as 0 */
+	if (formats & SNDRV_PCM_FMTBIT_S24_BE)
+		formats |= SNDRV_PCM_FMTBIT_S32_BE;
+	if (formats & SNDRV_PCM_FMTBIT_U24_BE)
+		formats |= SNDRV_PCM_FMTBIT_U32_BE;
+	/* now mask off what we can support. I suppose we could
+	 * also support S24_3LE and some similar formats, but I
+	 * doubt there's a codec that would be able to use that,
+	 * so we don't support it here. */
+	hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE |
+				 SNDRV_PCM_FMTBIT_U16_BE |
+				 SNDRV_PCM_FMTBIT_S32_BE |
+				 SNDRV_PCM_FMTBIT_U32_BE);
+
+	/* we need to set the highest and lowest rate possible.
+	 * These are the highest and lowest rates alsa can
+	 * support properly in its bitfield.
+	 * Below, we'll use that to restrict to the rate
+	 * currently in use (if any). */
+	hw->rate_min = 5512;
+	hw->rate_max = 192000;
+	/* if the other stream is active, then we can only
+	 * support what it is currently using.
+	 * FIXME: I lied. This comment is wrong. We can support
+	 * anything that works with the same serial format, ie.
+	 * when recording 24 bit sound we can well play 16 bit
+	 * sound at the same time iff using the same transfer mode.
+	 */
+	if (other->active) {
+		/* FIXME: is this guaranteed by the alsa api? */
+		hw->formats &= (1ULL << i2sdev->format);
+		/* see above, restrict rates to the one we already have */
+		hw->rate_min = i2sdev->rate;
+		hw->rate_max = i2sdev->rate;
+	}
+
+	hw->channels_min = 2;
+	hw->channels_max = 2;
+	/* these are somewhat arbitrary */
+	hw->buffer_bytes_max = 131072;
+	hw->period_bytes_min = 256;
+	hw->period_bytes_max = 16384;
+	hw->periods_min = 3;
+	hw->periods_max = MAX_DBDMA_COMMANDS;
+	list_for_each_entry(cii, &sdev->codec_list, list) {
+		if (cii->codec->open) {
+			err = cii->codec->open(cii, pi->substream);
+			if (err) {
+				result = err;
+				/* unwind */
+				found_this = 0;
+				list_for_each_entry_reverse(rev,
+				    &sdev->codec_list, list) {
+					if (found_this && rev->codec->close) {
+						rev->codec->close(rev,
+								pi->substream);
+					}
+					if (rev == cii)
+						found_this = 1;
+				}
+				goto out_unlock;
+			}
+		}
+	}
+
+ out_unlock:
+	mutex_unlock(&i2sdev->lock);
+	return result;
+}
+
+#undef CHECK_RATE
+
+static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in)
+{
+	struct codec_info_item *cii;
+	struct pcm_info *pi;
+	int err = 0, tmp;
+
+	mutex_lock(&i2sdev->lock);
+
+	get_pcm_info(i2sdev, in, &pi, NULL);
+
+	list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+		if (cii->codec->close) {
+			tmp = cii->codec->close(cii, pi->substream);
+			if (tmp)
+				err = tmp;
+		}
+	}
+
+	pi->substream = NULL;
+	pi->active = 0;
+	mutex_unlock(&i2sdev->lock);
+	return err;
+}
+
+static int i2sbus_hw_params(struct snd_pcm_substream *substream,
+			    struct snd_pcm_hw_params *params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+}
+
+static int i2sbus_hw_free(struct snd_pcm_substream *substream)
+{
+	snd_pcm_lib_free_pages(substream);
+	return 0;
+}
+
+static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
+{
+	/* whee. Hard work now. The user has selected a bitrate
+	 * and bit format, so now we have to program our
+	 * I2S controller appropriately. */
+	struct snd_pcm_runtime *runtime;
+	struct dbdma_cmd *command;
+	int i, periodsize;
+	dma_addr_t offset;
+	struct bus_info bi;
+	struct codec_info_item *cii;
+	int sfr = 0;		/* serial format register */
+	int dws = 0;		/* data word sizes reg */
+	int input_16bit;
+	struct pcm_info *pi, *other;
+	int cnt;
+	int result = 0;
+
+	mutex_lock(&i2sdev->lock);
+
+	get_pcm_info(i2sdev, in, &pi, &other);
+
+	if (pi->dbdma_ring.running) {
+		result = -EBUSY;
+		goto out_unlock;
+	}
+
+	runtime = pi->substream->runtime;
+	pi->active = 1;
+	if (other->active &&
+	    ((i2sdev->format != runtime->format)
+	     || (i2sdev->rate != runtime->rate))) {
+		result = -EINVAL;
+		goto out_unlock;
+	}
+
+	i2sdev->format = runtime->format;
+	i2sdev->rate = runtime->rate;
+
+	periodsize = snd_pcm_lib_period_bytes(pi->substream);
+	pi->current_period = 0;
+
+	/* generate dbdma command ring first */
+	command = pi->dbdma_ring.cmds;
+	offset = runtime->dma_addr;
+	for (i = 0; i < pi->substream->runtime->periods;
+	     i++, command++, offset += periodsize) {
+		memset(command, 0, sizeof(struct dbdma_cmd));
+		command->command =
+		    cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS);
+		command->phy_addr = cpu_to_le32(offset);
+		command->req_count = cpu_to_le16(periodsize);
+		command->xfer_status = cpu_to_le16(0);
+	}
+	/* last one branches back to first */
+	command--;
+	command->command |= cpu_to_le16(BR_ALWAYS);
+	command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start);
+
+	/* ok, let's set the serial format and stuff */
+	switch (runtime->format) {
+	/* 16 bit formats */
+	case SNDRV_PCM_FORMAT_S16_BE:
+	case SNDRV_PCM_FORMAT_U16_BE:
+		/* FIXME: if we add different bus factors we need to
+		 * do more here!! */
+		bi.bus_factor = 0;
+		list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+			bi.bus_factor = cii->codec->bus_factor;
+			break;
+		}
+		if (!bi.bus_factor) {
+			result = -ENODEV;
+			goto out_unlock;
+		}
+		input_16bit = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S32_BE:
+	case SNDRV_PCM_FORMAT_U32_BE:
+		/* force 64x bus speed, otherwise the data cannot be
+		 * transferred quickly enough! */
+		bi.bus_factor = 64;
+		input_16bit = 0;
+		break;
+	default:
+		result = -EINVAL;
+		goto out_unlock;
+	}
+	/* we assume all sysclocks are the same! */
+	list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+		bi.sysclock_factor = cii->codec->sysclock_factor;
+		break;
+	}
+
+	if (clock_and_divisors(bi.sysclock_factor,
+			       bi.bus_factor,
+			       runtime->rate,
+			       &sfr) < 0) {
+		result = -EINVAL;
+		goto out_unlock;
+	}
+	switch (bi.bus_factor) {
+	case 32:
+		sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X;
+		break;
+	case 64:
+		sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X;
+		break;
+	}
+	/* FIXME: THIS ASSUMES MASTER ALL THE TIME */
+	sfr |= I2S_SF_SCLK_MASTER;
+
+	list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
+		int err = 0;
+		if (cii->codec->prepare)
+			err = cii->codec->prepare(cii, &bi, pi->substream);
+		if (err) {
+			result = err;
+			goto out_unlock;
+		}
+	}
+	/* codecs are fine with it, so set our clocks */
+	if (input_16bit)
+		dws =	(2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) |
+			(2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) |
+			I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT;
+	else
+		dws =	(2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) |
+			(2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) |
+			I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT;
+
+	/* early exit if already programmed correctly */
+	/* not locking these is fine since we touch them only in this function */
+	if (in_le32(&i2sdev->intfregs->serial_format) == sfr
+	 && in_le32(&i2sdev->intfregs->data_word_sizes) == dws)
+		goto out_unlock;
+
+	/* let's notify the codecs about clocks going away.
+	 * For now we only do mastering on the i2s cell... */
+	list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+		if (cii->codec->switch_clock)
+			cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE);
+
+	i2sbus_control_enable(i2sdev->control, i2sdev);
+	i2sbus_control_cell(i2sdev->control, i2sdev, 1);
+
+	out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED);
+
+	i2sbus_control_clock(i2sdev->control, i2sdev, 0);
+
+	msleep(1);
+
+	/* wait for clock stopped. This can apparently take a while... */
+	cnt = 100;
+	while (cnt-- &&
+	    !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) {
+		msleep(5);
+	}
+	out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED);
+
+	/* not locking these is fine since we touch them only in this function */
+	out_le32(&i2sdev->intfregs->serial_format, sfr);
+	out_le32(&i2sdev->intfregs->data_word_sizes, dws);
+
+        i2sbus_control_enable(i2sdev->control, i2sdev);
+        i2sbus_control_cell(i2sdev->control, i2sdev, 1);
+        i2sbus_control_clock(i2sdev->control, i2sdev, 1);
+	msleep(1);
+
+	list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+		if (cii->codec->switch_clock)
+			cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE);
+
+ out_unlock:
+	mutex_unlock(&i2sdev->lock);
+	return result;
+}
+
+static struct dbdma_cmd STOP_CMD = {
+	.command = __constant_cpu_to_le16(DBDMA_STOP),
+};
+
+static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
+{
+	struct codec_info_item *cii;
+	struct pcm_info *pi;
+	int timeout;
+	struct dbdma_cmd tmp;
+	int result = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i2sdev->low_lock, flags);
+
+	get_pcm_info(i2sdev, in, &pi, NULL);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+		if (pi->dbdma_ring.running) {
+			result = -EALREADY;
+			goto out_unlock;
+		}
+		list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+			if (cii->codec->start)
+				cii->codec->start(cii, pi->substream);
+		pi->dbdma_ring.running = 1;
+
+		/* reset dma engine */
+		out_le32(&pi->dbdma->control,
+			 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
+		timeout = 100;
+		while (in_le32(&pi->dbdma->status) & RUN && timeout--)
+			udelay(1);
+		if (timeout <= 0) {
+			printk(KERN_ERR
+			       "i2sbus: error waiting for dma reset\n");
+			result = -ENXIO;
+			goto out_unlock;
+		}
+
+		/* write dma command buffer address to the dbdma chip */
+		out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
+		/* post PCI write */
+		mb();
+		(void)in_le32(&pi->dbdma->status);
+
+		/* change first command to STOP */
+		tmp = *pi->dbdma_ring.cmds;
+		*pi->dbdma_ring.cmds = STOP_CMD;
+
+		/* set running state, remember that the first command is STOP */
+		out_le32(&pi->dbdma->control, RUN | (RUN << 16));
+		timeout = 100;
+		/* wait for STOP to be executed */
+		while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--)
+			udelay(1);
+		if (timeout <= 0) {
+			printk(KERN_ERR "i2sbus: error waiting for dma stop\n");
+			result = -ENXIO;
+			goto out_unlock;
+		}
+		/* again, write dma command buffer address to the dbdma chip,
+		 * this time of the first real command */
+		*pi->dbdma_ring.cmds = tmp;
+		out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
+		/* post write */
+		mb();
+		(void)in_le32(&pi->dbdma->status);
+
+		/* reset dma engine again */
+		out_le32(&pi->dbdma->control,
+			 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
+		timeout = 100;
+		while (in_le32(&pi->dbdma->status) & RUN && timeout--)
+			udelay(1);
+		if (timeout <= 0) {
+			printk(KERN_ERR
+			       "i2sbus: error waiting for dma reset\n");
+			result = -ENXIO;
+			goto out_unlock;
+		}
+
+		/* wake up the chip with the next descriptor */
+		out_le32(&pi->dbdma->control,
+			 (RUN | WAKE) | ((RUN | WAKE) << 16));
+		/* get the frame count  */
+		pi->frame_count = in_le32(&i2sdev->intfregs->frame_count);
+
+		/* off you go! */
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		if (!pi->dbdma_ring.running) {
+			result = -EALREADY;
+			goto out_unlock;
+		}
+
+		/* turn off all relevant bits */
+		out_le32(&pi->dbdma->control,
+			 (RUN | WAKE | FLUSH | PAUSE) << 16);
+		{
+			/* FIXME: move to own function */
+			int timeout = 5000;
+			while ((in_le32(&pi->dbdma->status) & RUN)
+			       && --timeout > 0)
+				udelay(1);
+			if (!timeout)
+				printk(KERN_ERR
+				       "i2sbus: timed out turning "
+				       "off dbdma engine!\n");
+		}
+
+		pi->dbdma_ring.running = 0;
+		list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
+			if (cii->codec->stop)
+				cii->codec->stop(cii, pi->substream);
+		break;
+	default:
+		result = -EINVAL;
+		goto out_unlock;
+	}
+
+ out_unlock:
+	spin_unlock_irqrestore(&i2sdev->low_lock, flags);
+	return result;
+}
+
+static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in)
+{
+	struct pcm_info *pi;
+	u32 fc;
+
+	get_pcm_info(i2sdev, in, &pi, NULL);
+
+	fc = in_le32(&i2sdev->intfregs->frame_count);
+	fc = fc - pi->frame_count;
+
+	return (bytes_to_frames(pi->substream->runtime,
+			pi->current_period *
+			snd_pcm_lib_period_bytes(pi->substream))
+		+ fc) % pi->substream->runtime->buffer_size;
+}
+
+static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
+{
+	struct pcm_info *pi;
+	u32 fc;
+	u32 delta;
+
+	spin_lock(&i2sdev->low_lock);
+	get_pcm_info(i2sdev, in, &pi, NULL);
+
+	if (!pi->dbdma_ring.running) {
+		/* there was still an interrupt pending
+		 * while we stopped. or maybe another
+		 * processor (not the one that was stopping
+		 * the DMA engine) was spinning above
+		 * waiting for the lock. */
+		goto out_unlock;
+	}
+
+	fc = in_le32(&i2sdev->intfregs->frame_count);
+	/* a counter overflow does not change the calculation. */
+	delta = fc - pi->frame_count;
+
+	/* update current_period */
+	while (delta >= pi->substream->runtime->period_size) {
+		pi->current_period++;
+		delta = delta - pi->substream->runtime->period_size;
+	}
+
+	if (unlikely(delta)) {
+		/* Some interrupt came late, so check the dbdma.
+		 * This special case exists to syncronize the frame_count with
+		 * the dbdma transfer, but is hit every once in a while. */
+		int period;
+
+		period = (in_le32(&pi->dbdma->cmdptr)
+		        - pi->dbdma_ring.bus_cmd_start)
+				/ sizeof(struct dbdma_cmd);
+		pi->current_period = pi->current_period
+					% pi->substream->runtime->periods;
+
+		while (pi->current_period != period) {
+			pi->current_period++;
+			pi->current_period %= pi->substream->runtime->periods;
+			/* Set delta to zero, as the frame_count value is too
+			 * high (otherwise the code path will not be executed).
+			 * This corrects the fact that the frame_count is too
+			 * low at the beginning due to buffering. */
+			delta = 0;
+		}
+	}
+
+	pi->frame_count = fc - delta;
+	pi->current_period %= pi->substream->runtime->periods;
+
+	spin_unlock(&i2sdev->low_lock);
+	/* may call _trigger again, hence needs to be unlocked */
+	snd_pcm_period_elapsed(pi->substream);
+	return;
+ out_unlock:
+	spin_unlock(&i2sdev->low_lock);
+}
+
+irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs)
+{
+	handle_interrupt((struct i2sbus_dev *)devid, 0);
+	return IRQ_HANDLED;
+}
+
+irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs)
+{
+	handle_interrupt((struct i2sbus_dev *)devid, 1);
+	return IRQ_HANDLED;
+}
+
+static int i2sbus_playback_open(struct snd_pcm_substream *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	i2sdev->out.substream = substream;
+	return i2sbus_pcm_open(i2sdev, 0);
+}
+
+static int i2sbus_playback_close(struct snd_pcm_substream *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+	int err;
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->out.substream != substream)
+		return -EINVAL;
+	err = i2sbus_pcm_close(i2sdev, 0);
+	if (!err)
+		i2sdev->out.substream = NULL;
+	return err;
+}
+
+static int i2sbus_playback_prepare(struct snd_pcm_substream *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->out.substream != substream)
+		return -EINVAL;
+	return i2sbus_pcm_prepare(i2sdev, 0);
+}
+
+static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->out.substream != substream)
+		return -EINVAL;
+	return i2sbus_pcm_trigger(i2sdev, 0, cmd);
+}
+
+static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
+						 *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->out.substream != substream)
+		return 0;
+	return i2sbus_pcm_pointer(i2sdev, 0);
+}
+
+static struct snd_pcm_ops i2sbus_playback_ops = {
+	.open =		i2sbus_playback_open,
+	.close =	i2sbus_playback_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	i2sbus_hw_params,
+	.hw_free =	i2sbus_hw_free,
+	.prepare =	i2sbus_playback_prepare,
+	.trigger =	i2sbus_playback_trigger,
+	.pointer =	i2sbus_playback_pointer,
+};
+
+static int i2sbus_record_open(struct snd_pcm_substream *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	i2sdev->in.substream = substream;
+	return i2sbus_pcm_open(i2sdev, 1);
+}
+
+static int i2sbus_record_close(struct snd_pcm_substream *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+	int err;
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->in.substream != substream)
+		return -EINVAL;
+	err = i2sbus_pcm_close(i2sdev, 1);
+	if (!err)
+		i2sdev->in.substream = NULL;
+	return err;
+}
+
+static int i2sbus_record_prepare(struct snd_pcm_substream *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->in.substream != substream)
+		return -EINVAL;
+	return i2sbus_pcm_prepare(i2sdev, 1);
+}
+
+static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->in.substream != substream)
+		return -EINVAL;
+	return i2sbus_pcm_trigger(i2sdev, 1, cmd);
+}
+
+static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
+					       *substream)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
+
+	if (!i2sdev)
+		return -EINVAL;
+	if (i2sdev->in.substream != substream)
+		return 0;
+	return i2sbus_pcm_pointer(i2sdev, 1);
+}
+
+static struct snd_pcm_ops i2sbus_record_ops = {
+	.open =		i2sbus_record_open,
+	.close =	i2sbus_record_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	i2sbus_hw_params,
+	.hw_free =	i2sbus_hw_free,
+	.prepare =	i2sbus_record_prepare,
+	.trigger =	i2sbus_record_trigger,
+	.pointer =	i2sbus_record_pointer,
+};
+
+static void i2sbus_private_free(struct snd_pcm *pcm)
+{
+	struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm);
+	struct codec_info_item *p, *tmp;
+
+	i2sdev->sound.pcm = NULL;
+	i2sdev->out.created = 0;
+	i2sdev->in.created = 0;
+	list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) {
+		printk(KERN_ERR "i2sbus: a codec didn't unregister!\n");
+		list_del(&p->list);
+		module_put(p->codec->owner);
+		kfree(p);
+	}
+	soundbus_dev_put(&i2sdev->sound);
+	module_put(THIS_MODULE);
+}
+
+/* FIXME: this function needs an error handling strategy with labels */
+int
+i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
+		    struct codec_info *ci, void *data)
+{
+	int err, in = 0, out = 0;
+	struct transfer_info *tmp;
+	struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev);
+	struct codec_info_item *cii;
+
+	if (!dev->pcmname || dev->pcmid == -1) {
+		printk(KERN_ERR "i2sbus: pcm name and id must be set!\n");
+		return -EINVAL;
+	}
+
+	list_for_each_entry(cii, &dev->codec_list, list) {
+		if (cii->codec_data == data)
+			return -EALREADY;
+	}
+
+	if (!ci->transfers || !ci->transfers->formats
+	    || !ci->transfers->rates || !ci->usable)
+		return -EINVAL;
+
+	/* we currently code the i2s transfer on the clock, and support only
+	 * 32 and 64 */
+	if (ci->bus_factor != 32 && ci->bus_factor != 64)
+		return -EINVAL;
+
+	/* If you want to fix this, you need to keep track of what transport infos
+	 * are to be used, which codecs they belong to, and then fix all the
+	 * sysclock/busclock stuff above to depend on which is usable */
+	list_for_each_entry(cii, &dev->codec_list, list) {
+		if (cii->codec->sysclock_factor != ci->sysclock_factor) {
+			printk(KERN_DEBUG
+			       "cannot yet handle multiple different sysclocks!\n");
+			return -EINVAL;
+		}
+		if (cii->codec->bus_factor != ci->bus_factor) {
+			printk(KERN_DEBUG
+			       "cannot yet handle multiple different bus clocks!\n");
+			return -EINVAL;
+		}
+	}
+
+	tmp = ci->transfers;
+	while (tmp->formats && tmp->rates) {
+		if (tmp->transfer_in)
+			in = 1;
+		else
+			out = 1;
+		tmp++;
+	}
+
+	cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL);
+	if (!cii) {
+		printk(KERN_DEBUG "i2sbus: failed to allocate cii\n");
+		return -ENOMEM;
+	}
+
+	/* use the private data to point to the codec info */
+	cii->sdev = soundbus_dev_get(dev);
+	cii->codec = ci;
+	cii->codec_data = data;
+
+	if (!cii->sdev) {
+		printk(KERN_DEBUG
+		       "i2sbus: failed to get soundbus dev reference\n");
+		kfree(cii);
+		return -ENODEV;
+	}
+
+	if (!try_module_get(THIS_MODULE)) {
+		printk(KERN_DEBUG "i2sbus: failed to get module reference!\n");
+		soundbus_dev_put(dev);
+		kfree(cii);
+		return -EBUSY;
+	}
+
+	if (!try_module_get(ci->owner)) {
+		printk(KERN_DEBUG
+		       "i2sbus: failed to get module reference to codec owner!\n");
+		module_put(THIS_MODULE);
+		soundbus_dev_put(dev);
+		kfree(cii);
+		return -EBUSY;
+	}
+
+	if (!dev->pcm) {
+		err = snd_pcm_new(card,
+				  dev->pcmname,
+				  dev->pcmid,
+				  0,
+				  0,
+				  &dev->pcm);
+		if (err) {
+			printk(KERN_DEBUG "i2sbus: failed to create pcm\n");
+			kfree(cii);
+			module_put(ci->owner);
+			soundbus_dev_put(dev);
+			module_put(THIS_MODULE);
+			return err;
+		}
+	}
+
+	/* ALSA yet again sucks.
+	 * If it is ever fixed, remove this line. See below. */
+	out = in = 1;
+
+	if (!i2sdev->out.created && out) {
+		if (dev->pcm->card != card) {
+			/* eh? */
+			printk(KERN_ERR
+			       "Can't attach same bus to different cards!\n");
+			module_put(ci->owner);
+			kfree(cii);
+			soundbus_dev_put(dev);
+			module_put(THIS_MODULE);
+			return -EINVAL;
+		}
+		if ((err =
+		     snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) {
+			module_put(ci->owner);
+			kfree(cii);
+			soundbus_dev_put(dev);
+			module_put(THIS_MODULE);
+			return err;
+		}
+		snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&i2sbus_playback_ops);
+		i2sdev->out.created = 1;
+	}
+
+	if (!i2sdev->in.created && in) {
+		if (dev->pcm->card != card) {
+			printk(KERN_ERR
+			       "Can't attach same bus to different cards!\n");
+			module_put(ci->owner);
+			kfree(cii);
+			soundbus_dev_put(dev);
+			module_put(THIS_MODULE);
+			return -EINVAL;
+		}
+		if ((err =
+		     snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) {
+			module_put(ci->owner);
+			kfree(cii);
+			soundbus_dev_put(dev);
+			module_put(THIS_MODULE);
+			return err;
+		}
+		snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&i2sbus_record_ops);
+		i2sdev->in.created = 1;
+	}
+
+	/* so we have to register the pcm after adding any substream
+	 * to it because alsa doesn't create the devices for the
+	 * substreams when we add them later.
+	 * Therefore, force in and out on both busses (above) and
+	 * register the pcm now instead of just after creating it.
+	 */
+	err = snd_device_register(card, dev->pcm);
+	if (err) {
+		printk(KERN_ERR "i2sbus: error registering new pcm\n");
+		module_put(ci->owner);
+		kfree(cii);
+		soundbus_dev_put(dev);
+		module_put(THIS_MODULE);
+		return err;
+	}
+	/* no errors any more, so let's add this to our list */
+	list_add(&cii->list, &dev->codec_list);
+
+	dev->pcm->private_data = i2sdev;
+	dev->pcm->private_free = i2sbus_private_free;
+
+	/* well, we really should support scatter/gather DMA */
+	snd_pcm_lib_preallocate_pages_for_all(
+		dev->pcm, SNDRV_DMA_TYPE_DEV,
+		snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)),
+		64 * 1024, 64 * 1024);
+
+	return 0;
+}
+
+void i2sbus_detach_codec(struct soundbus_dev *dev, void *data)
+{
+	struct codec_info_item *cii = NULL, *i;
+
+	list_for_each_entry(i, &dev->codec_list, list) {
+		if (i->codec_data == data) {
+			cii = i;
+			break;
+		}
+	}
+	if (cii) {
+		list_del(&cii->list);
+		module_put(cii->codec->owner);
+		kfree(cii);
+	}
+	/* no more codecs, but still a pcm? */
+	if (list_empty(&dev->codec_list) && dev->pcm) {
+		/* the actual cleanup is done by the callback above! */
+		snd_device_free(dev->pcm->card, dev->pcm);
+	}
+}
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
new file mode 100644
index 0000000..cfa5162
--- /dev/null
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -0,0 +1,112 @@
+/*
+ * i2sbus driver -- private definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __I2SBUS_H
+#define __I2SBUS_H
+#include <asm/dbdma.h>
+#include <linux/interrupt.h>
+#include <sound/pcm.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <asm/prom.h>
+#include "i2sbus-interface.h"
+#include "i2sbus-control.h"
+#include "../soundbus.h"
+
+struct i2sbus_control {
+	volatile struct i2s_control_regs __iomem *controlregs;
+	struct resource rsrc;
+	struct list_head list;
+};
+
+#define MAX_DBDMA_COMMANDS	32
+
+struct dbdma_command_mem {
+	dma_addr_t bus_addr;
+	dma_addr_t bus_cmd_start;
+	struct dbdma_cmd *cmds;
+	void *space;
+	int size;
+	u32 running:1;
+};
+
+struct pcm_info {
+	u32 created:1, /* has this direction been created with alsa? */
+	    active:1;  /* is this stream active? */
+	/* runtime information */
+	struct snd_pcm_substream *substream;
+	int current_period;
+	u32 frame_count;
+	struct dbdma_command_mem dbdma_ring;
+	volatile struct dbdma_regs __iomem *dbdma;
+};
+
+struct i2sbus_dev {
+	struct soundbus_dev sound;
+	struct macio_dev *macio;
+	struct i2sbus_control *control;
+	volatile struct i2s_interface_regs __iomem *intfregs;
+
+	struct resource resources[3];
+	struct resource *allocated_resource[3];
+	int interrupts[3];
+	char rnames[3][32];
+
+	/* info about currently active substreams */
+	struct pcm_info out, in;
+	snd_pcm_format_t format;
+	unsigned int rate;
+
+	/* list for a single controller */
+	struct list_head item;
+	/* number of bus on controller */
+	int bus_number;
+	/* for use by control layer */
+	struct pmf_function *enable,
+			    *cell_enable,
+			    *cell_disable,
+			    *clock_enable,
+			    *clock_disable;
+
+	/* locks */
+	/* spinlock for low-level interrupt locking */
+	spinlock_t low_lock;
+	/* mutex for high-level consistency */
+	struct mutex lock;
+};
+
+#define soundbus_dev_to_i2sbus_dev(sdev) \
+		container_of(sdev, struct i2sbus_dev, sound)
+
+/* pcm specific functions */
+extern int
+i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
+		    struct codec_info *ci, void *data);
+extern void
+i2sbus_detach_codec(struct soundbus_dev *dev, void *data);
+extern irqreturn_t
+i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs);
+extern irqreturn_t
+i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs);
+
+/* control specific functions */
+extern int i2sbus_control_init(struct macio_dev* dev,
+			       struct i2sbus_control **c);
+extern void i2sbus_control_destroy(struct i2sbus_control *c);
+extern int i2sbus_control_add_dev(struct i2sbus_control *c,
+				  struct i2sbus_dev *i2sdev);
+extern void i2sbus_control_remove_dev(struct i2sbus_control *c,
+				      struct i2sbus_dev *i2sdev);
+extern int i2sbus_control_enable(struct i2sbus_control *c,
+				 struct i2sbus_dev *i2sdev);
+extern int i2sbus_control_cell(struct i2sbus_control *c,
+			       struct i2sbus_dev *i2sdev,
+			       int enable);
+extern int i2sbus_control_clock(struct i2sbus_control *c,
+				struct i2sbus_dev *i2sdev,
+				int enable);
+#endif /* __I2SBUS_H */
diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h
new file mode 100644
index 0000000..5c27297
--- /dev/null
+++ b/sound/aoa/soundbus/soundbus.h
@@ -0,0 +1,202 @@
+/*
+ * soundbus generic definitions
+ *
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * GPL v2, can be found in COPYING.
+ */
+#ifndef __SOUNDBUS_H
+#define __SOUNDBUS_H
+
+#include <asm/of_device.h>
+#include <sound/pcm.h>
+#include <linux/list.h>
+
+
+/* When switching from master to slave or the other way around,
+ * you don't want to have the codec chip acting as clock source
+ * while the bus still is.
+ * More importantly, while switch from slave to master, you need
+ * to turn off the chip's master function first, but then there's
+ * no clock for a while and other chips might reset, so we notify
+ * their drivers after having switched.
+ * The constants here are codec-point of view, so when we switch
+ * the soundbus to master we tell the codec we're going to switch
+ * and give it CLOCK_SWITCH_PREPARE_SLAVE!
+ */
+enum clock_switch {
+	CLOCK_SWITCH_PREPARE_SLAVE,
+	CLOCK_SWITCH_PREPARE_MASTER,
+	CLOCK_SWITCH_SLAVE,
+	CLOCK_SWITCH_MASTER,
+	CLOCK_SWITCH_NOTIFY,
+};
+
+/* information on a transfer the codec can take */
+struct transfer_info {
+	u64 formats;		/* SNDRV_PCM_FMTBIT_* */
+	unsigned int rates;	/* SNDRV_PCM_RATE_* */
+	/* flags */
+	u32 transfer_in:1, /* input = 1, output = 0 */
+	    must_be_clock_source:1;
+	/* for codecs to distinguish among their TIs */
+	int tag;
+};
+
+struct codec_info_item {
+	struct codec_info *codec;
+	void *codec_data;
+	struct soundbus_dev *sdev;
+	/* internal, to be used by the soundbus provider */
+	struct list_head list;
+};
+
+/* for prepare, where the codecs need to know
+ * what we're going to drive the bus with */
+struct bus_info {
+	/* see below */
+	int sysclock_factor;
+	int bus_factor;
+};
+
+/* information on the codec itself, plus function pointers */
+struct codec_info {
+	/* the module this lives in */
+	struct module *owner;
+
+	/* supported transfer possibilities, array terminated by
+	 * formats or rates being 0. */
+	struct transfer_info *transfers;
+
+	/* Master clock speed factor
+	 * to be used (master clock speed = sysclock_factor * sampling freq)
+	 * Unused if the soundbus provider has no such notion.
+	 */
+	int sysclock_factor;
+
+	/* Bus factor, bus clock speed = bus_factor * sampling freq)
+	 * Unused if the soundbus provider has no such notion.
+	 */
+	int bus_factor;
+
+	/* operations */
+	/* clock switching, see above */
+	int (*switch_clock)(struct codec_info_item *cii,
+			    enum clock_switch clock);
+
+	/* called for each transfer_info when the user
+	 * opens the pcm device to determine what the
+	 * hardware can support at this point in time.
+	 * That can depend on other user-switchable controls.
+	 * Return 1 if usable, 0 if not.
+	 * out points to another instance of a transfer_info
+	 * which is initialised to the values in *ti, and
+	 * it's format and rate values can be modified by
+	 * the callback if it is necessary to further restrict
+	 * the formats that can be used at the moment, for
+	 * example when one codec has multiple logical codec
+	 * info structs for multiple inputs.
+	 */
+	int (*usable)(struct codec_info_item *cii,
+		      struct transfer_info *ti,
+		      struct transfer_info *out);
+
+	/* called when pcm stream is opened, probably not implemented
+	 * most of the time since it isn't too useful */
+	int (*open)(struct codec_info_item *cii,
+		    struct snd_pcm_substream *substream);
+
+	/* called when the pcm stream is closed, at this point
+	 * the user choices can all be unlocked (see below) */
+	int (*close)(struct codec_info_item *cii,
+		     struct snd_pcm_substream *substream);
+
+	/* if the codec must forbid some user choices because
+	 * they are not valid with the substream/transfer info,
+	 * it must do so here. Example: no digital output for
+	 * incompatible framerate, say 8KHz, on Onyx.
+	 * If the selected stuff in the substream is NOT
+	 * compatible, you have to reject this call! */
+	int (*prepare)(struct codec_info_item *cii,
+		       struct bus_info *bi,
+		       struct snd_pcm_substream *substream);
+
+	/* start() is called before data is pushed to the codec.
+	 * Note that start() must be atomic! */
+	int (*start)(struct codec_info_item *cii,
+		     struct snd_pcm_substream *substream);
+
+	/* stop() is called after data is no longer pushed to the codec.
+	 * Note that stop() must be atomic! */
+	int (*stop)(struct codec_info_item *cii,
+		    struct snd_pcm_substream *substream);
+
+	int (*suspend)(struct codec_info_item *cii, pm_message_t state);
+	int (*resume)(struct codec_info_item *cii);
+};
+
+/* information on a soundbus device */
+struct soundbus_dev {
+	/* the bus it belongs to */
+	struct list_head onbuslist;
+
+	/* the of device it represents */
+	struct of_device ofdev;
+
+	/* what modules go by */
+	char modalias[32];
+
+	/* These fields must be before attach_codec can be called.
+	 * They should be set by the owner of the alsa card object
+	 * that is needed, and whoever sets them must make sure
+	 * that they are unique within that alsa card object. */
+	char *pcmname;
+	int pcmid;
+
+	/* this is assigned by the soundbus provider in attach_codec */
+	struct snd_pcm *pcm;
+
+	/* operations */
+	/* attach a codec to this soundbus, give the alsa
+	 * card object the PCMs for this soundbus should be in.
+	 * The 'data' pointer must be unique, it is used as the
+	 * key for detach_codec(). */
+	int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card,
+			    struct codec_info *ci, void *data);
+	void (*detach_codec)(struct soundbus_dev *dev, void *data);
+	/* TODO: suspend/resume */
+
+	/* private for the soundbus provider */
+	struct list_head codec_list;
+	u32 have_out:1, have_in:1;
+};
+#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev)
+#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev)
+
+extern int soundbus_add_one(struct soundbus_dev *dev);
+extern void soundbus_remove_one(struct soundbus_dev *dev);
+
+extern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev);
+extern void soundbus_dev_put(struct soundbus_dev *dev);
+
+struct soundbus_driver {
+	char *name;
+	struct module *owner;
+
+	/* we don't implement any matching at all */
+
+	int	(*probe)(struct soundbus_dev* dev);
+	int	(*remove)(struct soundbus_dev* dev);
+
+	int	(*suspend)(struct soundbus_dev* dev, pm_message_t state);
+	int	(*resume)(struct soundbus_dev* dev);
+	int	(*shutdown)(struct soundbus_dev* dev);
+
+	struct device_driver driver;
+};
+#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver)
+
+extern int soundbus_register_driver(struct soundbus_driver *drv);
+extern void soundbus_unregister_driver(struct soundbus_driver *drv);
+
+#endif /* __SOUNDBUS_H */
diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c
new file mode 100644
index 0000000..d31f814
--- /dev/null
+++ b/sound/aoa/soundbus/sysfs.c
@@ -0,0 +1,43 @@
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/stat.h>
+/* FIX UP */
+#include "soundbus.h"
+
+#define soundbus_config_of_attr(field, format_string)			\
+static ssize_t								\
+field##_show (struct device *dev, struct device_attribute *attr,	\
+              char *buf)						\
+{									\
+	struct soundbus_dev *mdev = to_soundbus_device (dev);		\
+	return sprintf (buf, format_string, mdev->ofdev.node->field);	\
+}
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	struct soundbus_dev *sdev = to_soundbus_device(dev);
+	struct of_device *of = &sdev->ofdev;
+	int length;
+
+	if (*sdev->modalias) {
+		strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
+		strcat(buf, "\n");
+		length = strlen(buf);
+	} else {
+		length = sprintf(buf, "of:N%sT%s\n",
+				 of->node->name, of->node->type);
+	}
+
+	return length;
+}
+
+soundbus_config_of_attr (name, "%s\n");
+soundbus_config_of_attr (type, "%s\n");
+
+struct device_attribute soundbus_dev_attrs[] = {
+	__ATTR_RO(name),
+	__ATTR_RO(type),
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
diff --git a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
index 13057d9..b88fb0c 100644
--- a/sound/arm/sa11xx-uda1341.c
+++ b/sound/arm/sa11xx-uda1341.c
@@ -112,7 +112,7 @@
 MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA");
 MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}");
 
-static char *id = NULL;	/* ID for this card */
+static char *id;	/* ID for this card */
 
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
@@ -984,11 +984,15 @@
 	if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0)
 		return err;
 	device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0);
-	if (IS_ERR(device)) {
-		platform_driver_unregister(&sa11xx_uda1341_driver);
-		return PTR_ERR(device);
-	}
-	return 0;
+	if (!IS_ERR(device)) {
+		if (platform_get_drvdata(device))
+			return 0;
+		platform_device_unregister(device);
+		err = -ENODEV
+	} else
+		err = PTR_ERR(device);
+	platform_driver_unregister(&sa11xx_uda1341_driver);
+	return err;
 }
 
 static void __exit sa11xx_uda1341_exit(void)
diff --git a/sound/core/control.c b/sound/core/control.c
index 22565c9b..bb397ea 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -176,6 +176,8 @@
 	read_unlock(&card->ctl_files_rwlock);
 }
 
+EXPORT_SYMBOL(snd_ctl_notify);
+
 /**
  * snd_ctl_new - create a control instance from the template
  * @control: the control template
@@ -204,6 +206,8 @@
 	return kctl;
 }
 
+EXPORT_SYMBOL(snd_ctl_new);
+
 /**
  * snd_ctl_new1 - create a control instance from the template
  * @ncontrol: the initialization record
@@ -242,6 +246,8 @@
 	return snd_ctl_new(&kctl, access);
 }
 
+EXPORT_SYMBOL(snd_ctl_new1);
+
 /**
  * snd_ctl_free_one - release the control instance
  * @kcontrol: the control instance
@@ -259,6 +265,8 @@
 	}
 }
 
+EXPORT_SYMBOL(snd_ctl_free_one);
+
 static unsigned int snd_ctl_hole_check(struct snd_card *card,
 				       unsigned int count)
 {
@@ -347,6 +355,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(snd_ctl_add);
+
 /**
  * snd_ctl_remove - remove the control from the card and release it
  * @card: the card instance
@@ -373,6 +383,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_ctl_remove);
+
 /**
  * snd_ctl_remove_id - remove the control of the given id and release it
  * @card: the card instance
@@ -399,6 +411,8 @@
 	return ret;
 }
 
+EXPORT_SYMBOL(snd_ctl_remove_id);
+
 /**
  * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it
  * @file: active control handle
@@ -461,6 +475,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_ctl_rename_id);
+
 /**
  * snd_ctl_find_numid - find the control instance with the given number-id
  * @card: the card instance
@@ -487,6 +503,8 @@
 	return NULL;
 }
 
+EXPORT_SYMBOL(snd_ctl_find_numid);
+
 /**
  * snd_ctl_find_id - find the control instance with the given id
  * @card: the card instance
@@ -527,6 +545,8 @@
 	return NULL;
 }
 
+EXPORT_SYMBOL(snd_ctl_find_id);
+
 static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
 			     unsigned int cmd, void __user *arg)
 {
@@ -704,6 +724,8 @@
 	return result;
 }
 
+EXPORT_SYMBOL(snd_ctl_elem_read);
+
 static int snd_ctl_elem_read_user(struct snd_card *card,
 				  struct snd_ctl_elem_value __user *_control)
 {
@@ -767,6 +789,8 @@
 	return result;
 }
 
+EXPORT_SYMBOL(snd_ctl_elem_write);
+
 static int snd_ctl_elem_write_user(struct snd_ctl_file *file,
 				   struct snd_ctl_elem_value __user *_control)
 {
@@ -1199,11 +1223,15 @@
 	return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls);
 }
 
+EXPORT_SYMBOL(snd_ctl_register_ioctl);
+
 #ifdef CONFIG_COMPAT
 int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
 {
 	return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls);
 }
+
+EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
 #endif
 
 /*
@@ -1236,12 +1264,15 @@
 	return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls);
 }
 
+EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
+
 #ifdef CONFIG_COMPAT
 int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
 {
 	return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls);
 }
 
+EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
 #endif
 
 static int snd_ctl_fasync(int fd, struct file * file, int on)
diff --git a/sound/core/device.c b/sound/core/device.c
index b1cf6ec..6ce4da4a 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -63,6 +63,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_device_new);
+
 /**
  * snd_device_free - release the device from the card
  * @card: the card instance
@@ -107,6 +109,8 @@
 	return -ENXIO;
 }
 
+EXPORT_SYMBOL(snd_device_free);
+
 /**
  * snd_device_disconnect - disconnect the device
  * @card: the card instance
@@ -182,6 +186,8 @@
 	return -ENXIO;
 }
 
+EXPORT_SYMBOL(snd_device_register);
+
 /*
  * register all the devices on the card.
  * called from init.c
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 2524e66..8bd0dcc 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -486,7 +486,6 @@
 	struct snd_info_entry *entry;
 
 	if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
-		entry->c.text.read_size = PAGE_SIZE;
 		entry->c.text.read = snd_hwdep_proc_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
diff --git a/sound/core/info.c b/sound/core/info.c
index 2582b74..10c1772 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -21,7 +21,6 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/vmalloc.h>
 #include <linux/time.h>
 #include <linux/smp_lock.h>
 #include <linux/string.h>
@@ -82,6 +81,24 @@
 static int snd_info_version_done(void);
 
 
+/* resize the proc r/w buffer */
+static int resize_info_buffer(struct snd_info_buffer *buffer,
+			      unsigned int nsize)
+{
+	char *nbuf;
+
+	nsize = PAGE_ALIGN(nsize);
+	nbuf = kmalloc(nsize, GFP_KERNEL);
+	if (! nbuf)
+		return -ENOMEM;
+
+	memcpy(nbuf, buffer->buffer, buffer->len);
+	kfree(buffer->buffer);
+	buffer->buffer = nbuf;
+	buffer->len = nsize;
+	return 0;
+}
+
 /**
  * snd_iprintf - printf on the procfs buffer
  * @buffer: the procfs buffer
@@ -95,30 +112,43 @@
 {
 	va_list args;
 	int len, res;
+	int err = 0;
 
+	might_sleep();
 	if (buffer->stop || buffer->error)
 		return 0;
 	len = buffer->len - buffer->size;
 	va_start(args, fmt);
-	res = vsnprintf(buffer->curr, len, fmt, args);
-	va_end(args);
-	if (res >= len) {
-		buffer->stop = 1;
-		return 0;
+	for (;;) {
+		res = vsnprintf(buffer->buffer + buffer->curr, len, fmt, args);
+		if (res < len)
+			break;
+		err = resize_info_buffer(buffer, buffer->len + PAGE_SIZE);
+		if (err < 0)
+			break;
+		len = buffer->len - buffer->size;
 	}
+	va_end(args);
+
+	if (err < 0)
+		return err;
 	buffer->curr += res;
 	buffer->size += res;
 	return res;
 }
 
+EXPORT_SYMBOL(snd_iprintf);
+
 /*
 
  */
 
-static struct proc_dir_entry *snd_proc_root = NULL;
-struct snd_info_entry *snd_seq_root = NULL;
+static struct proc_dir_entry *snd_proc_root;
+struct snd_info_entry *snd_seq_root;
+EXPORT_SYMBOL(snd_seq_root);
+
 #ifdef CONFIG_SND_OSSEMUL
-struct snd_info_entry *snd_oss_root = NULL;
+struct snd_info_entry *snd_oss_root;
 #endif
 
 static inline void snd_info_entry_prepare(struct proc_dir_entry *de)
@@ -221,7 +251,7 @@
 	struct snd_info_private_data *data;
 	struct snd_info_entry *entry;
 	struct snd_info_buffer *buf;
-	size_t size = 0;
+	ssize_t size = 0;
 	loff_t pos;
 
 	data = file->private_data;
@@ -237,14 +267,20 @@
 		buf = data->wbuffer;
 		if (buf == NULL)
 			return -EIO;
-		if (pos >= buf->len)
-			return -ENOMEM;
-		size = buf->len - pos;
-		size = min(count, size);
-		if (copy_from_user(buf->buffer + pos, buffer, size))
+		mutex_lock(&entry->access);
+		if (pos + count >= buf->len) {
+			if (resize_info_buffer(buf, pos + count)) {
+				mutex_unlock(&entry->access);
+				return -ENOMEM;
+			}
+		}
+		if (copy_from_user(buf->buffer + pos, buffer, count)) {
+			mutex_unlock(&entry->access);
 			return -EFAULT;
-		if ((long)buf->size < pos + size)
-			buf->size = pos + size;
+		}
+		buf->size = pos + count;
+		mutex_unlock(&entry->access);
+		size = count;
 		break;
 	case SNDRV_INFO_CONTENT_DATA:
 		if (entry->c.ops->write)
@@ -279,18 +315,14 @@
 	}
 	mode = file->f_flags & O_ACCMODE;
 	if (mode == O_RDONLY || mode == O_RDWR) {
-		if ((entry->content == SNDRV_INFO_CONTENT_TEXT &&
-		     !entry->c.text.read_size) ||
-		    (entry->content == SNDRV_INFO_CONTENT_DATA &&
+		if ((entry->content == SNDRV_INFO_CONTENT_DATA &&
 		     entry->c.ops->read == NULL)) {
 		    	err = -ENODEV;
 		    	goto __error;
 		}
 	}
 	if (mode == O_WRONLY || mode == O_RDWR) {
-		if ((entry->content == SNDRV_INFO_CONTENT_TEXT &&
-		     !entry->c.text.write_size) ||
-		    (entry->content == SNDRV_INFO_CONTENT_DATA &&
+		if ((entry->content == SNDRV_INFO_CONTENT_DATA &&
 		     entry->c.ops->write == NULL)) {
 		    	err = -ENODEV;
 		    	goto __error;
@@ -306,49 +338,23 @@
 	case SNDRV_INFO_CONTENT_TEXT:
 		if (mode == O_RDONLY || mode == O_RDWR) {
 			buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-			if (buffer == NULL) {
-				kfree(data);
-				err = -ENOMEM;
-				goto __error;
-			}
-			buffer->len = (entry->c.text.read_size +
-				      (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-			buffer->buffer = vmalloc(buffer->len);
-			if (buffer->buffer == NULL) {
-				kfree(buffer);
-				kfree(data);
-				err = -ENOMEM;
-				goto __error;
-			}
-			buffer->curr = buffer->buffer;
+			if (buffer == NULL)
+				goto __nomem;
 			data->rbuffer = buffer;
+			buffer->len = PAGE_SIZE;
+			buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
+			if (buffer->buffer == NULL)
+				goto __nomem;
 		}
 		if (mode == O_WRONLY || mode == O_RDWR) {
 			buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
-			if (buffer == NULL) {
-				if (mode == O_RDWR) {
-					vfree(data->rbuffer->buffer);
-					kfree(data->rbuffer);
-				}
-				kfree(data);
-				err = -ENOMEM;
-				goto __error;
-			}
-			buffer->len = (entry->c.text.write_size +
-				      (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-			buffer->buffer = vmalloc(buffer->len);
-			if (buffer->buffer == NULL) {
-				if (mode == O_RDWR) {
-					vfree(data->rbuffer->buffer);
-					kfree(data->rbuffer);
-				}
-				kfree(buffer);
-				kfree(data);
-				err = -ENOMEM;
-				goto __error;
-			}
-			buffer->curr = buffer->buffer;
+			if (buffer == NULL)
+				goto __nomem;
 			data->wbuffer = buffer;
+			buffer->len = PAGE_SIZE;
+			buffer->buffer = kmalloc(buffer->len, GFP_KERNEL);
+			if (buffer->buffer == NULL)
+				goto __nomem;
 		}
 		break;
 	case SNDRV_INFO_CONTENT_DATA:	/* data */
@@ -373,6 +379,17 @@
 	}
 	return 0;
 
+ __nomem:
+	if (data->rbuffer) {
+		kfree(data->rbuffer->buffer);
+		kfree(data->rbuffer);
+	}
+	if (data->wbuffer) {
+		kfree(data->wbuffer->buffer);
+		kfree(data->wbuffer);
+	}
+	kfree(data);
+	err = -ENOMEM;
       __error:
 	module_put(entry->module);
       __error1:
@@ -391,11 +408,11 @@
 	entry = data->entry;
 	switch (entry->content) {
 	case SNDRV_INFO_CONTENT_TEXT:
-		if (mode == O_RDONLY || mode == O_RDWR) {
-			vfree(data->rbuffer->buffer);
+		if (data->rbuffer) {
+			kfree(data->rbuffer->buffer);
 			kfree(data->rbuffer);
 		}
-		if (mode == O_WRONLY || mode == O_RDWR) {
+		if (data->wbuffer) {
 			if (entry->c.text.write) {
 				entry->c.text.write(entry, data->wbuffer);
 				if (data->wbuffer->error) {
@@ -404,7 +421,7 @@
 						data->wbuffer->error);
 				}
 			}
-			vfree(data->wbuffer->buffer);
+			kfree(data->wbuffer->buffer);
 			kfree(data->wbuffer);
 		}
 		break;
@@ -664,29 +681,29 @@
 	if (len <= 0 || buffer->stop || buffer->error)
 		return 1;
 	while (--len > 0) {
-		c = *buffer->curr++;
+		c = buffer->buffer[buffer->curr++];
 		if (c == '\n') {
-			if ((buffer->curr - buffer->buffer) >= (long)buffer->size) {
+			if (buffer->curr >= buffer->size)
 				buffer->stop = 1;
-			}
 			break;
 		}
 		*line++ = c;
-		if ((buffer->curr - buffer->buffer) >= (long)buffer->size) {
+		if (buffer->curr >= buffer->size) {
 			buffer->stop = 1;
 			break;
 		}
 	}
 	while (c != '\n' && !buffer->stop) {
-		c = *buffer->curr++;
-		if ((buffer->curr - buffer->buffer) >= (long)buffer->size) {
+		c = buffer->buffer[buffer->curr++];
+		if (buffer->curr >= buffer->size)
 			buffer->stop = 1;
-		}
 	}
 	*line = '\0';
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_info_get_line);
+
 /**
  * snd_info_get_str - parse a string token
  * @dest: the buffer to store the string token
@@ -723,6 +740,8 @@
 	return src;
 }
 
+EXPORT_SYMBOL(snd_info_get_str);
+
 /**
  * snd_info_create_entry - create an info entry
  * @name: the proc file name
@@ -774,6 +793,8 @@
 	return entry;
 }
 
+EXPORT_SYMBOL(snd_info_create_module_entry);
+
 /**
  * snd_info_create_card_entry - create an info entry for the given card
  * @card: the card instance
@@ -797,6 +818,8 @@
 	return entry;
 }
 
+EXPORT_SYMBOL(snd_info_create_card_entry);
+
 static int snd_info_dev_free_entry(struct snd_device *device)
 {
 	struct snd_info_entry *entry = device->device_data;
@@ -867,6 +890,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_card_proc_new);
+
 /**
  * snd_info_free_entry - release the info entry
  * @entry: the info entry
@@ -883,6 +908,8 @@
 	kfree(entry);
 }
 
+EXPORT_SYMBOL(snd_info_free_entry);
+
 /**
  * snd_info_register - register the info entry
  * @entry: the info entry
@@ -913,6 +940,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_info_register);
+
 /**
  * snd_info_unregister - de-register the info entry
  * @entry: the info entry
@@ -937,11 +966,13 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_info_unregister);
+
 /*
 
  */
 
-static struct snd_info_entry *snd_info_version_entry = NULL;
+static struct snd_info_entry *snd_info_version_entry;
 
 static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
@@ -958,7 +989,6 @@
 	entry = snd_info_create_module_entry(THIS_MODULE, "version", NULL);
 	if (entry == NULL)
 		return -ENOMEM;
-	entry->c.text.read_size = 256;
 	entry->c.text.read = snd_info_version_read;
 	if (snd_info_register(entry) < 0) {
 		snd_info_free_entry(entry);
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index f9ce854..bb2c40d 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -64,6 +64,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_oss_info_register);
+
 extern void snd_card_info_read_oss(struct snd_info_buffer *buffer);
 
 static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int dev)
@@ -117,7 +119,6 @@
 
 	memset(snd_sndstat_strings, 0, sizeof(snd_sndstat_strings));
 	if ((entry = snd_info_create_module_entry(THIS_MODULE, "sndstat", snd_oss_root)) != NULL) {
-		entry->c.text.read_size = 2048;
 		entry->c.text.read = snd_sndstat_proc_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
diff --git a/sound/core/init.c b/sound/core/init.c
index 39ed2e5..4d92588 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -38,12 +38,15 @@
 	struct snd_shutdown_f_ops *next;
 };
 
-unsigned int snd_cards_lock = 0;	/* locked for registering/using */
-struct snd_card *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL};
-DEFINE_RWLOCK(snd_card_rwlock);
+static unsigned int snd_cards_lock;	/* locked for registering/using */
+struct snd_card *snd_cards[SNDRV_CARDS];
+EXPORT_SYMBOL(snd_cards);
+
+static DEFINE_MUTEX(snd_card_mutex);
 
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
 int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag);
+EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
 #endif
 
 #ifdef CONFIG_PROC_FS
@@ -66,7 +69,6 @@
 		snd_printd("unable to create card entry\n");
 		return err;
 	}
-	entry->c.text.read_size = PAGE_SIZE;
 	entry->c.text.read = snd_card_id_read;
 	if (snd_info_register(entry) < 0) {
 		snd_info_free_entry(entry);
@@ -110,7 +112,7 @@
 		strlcpy(card->id, xid, sizeof(card->id));
 	}
 	err = 0;
-	write_lock(&snd_card_rwlock);
+	mutex_lock(&snd_card_mutex);
 	if (idx < 0) {
 		int idx2;
 		for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
@@ -128,12 +130,12 @@
 	else
 		err = -ENODEV;
 	if (idx < 0 || err < 0) {
-		write_unlock(&snd_card_rwlock);
+		mutex_unlock(&snd_card_mutex);
 		snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1);
 		goto __error;
 	}
 	snd_cards_lock |= 1 << idx;		/* lock it */
-	write_unlock(&snd_card_rwlock);
+	mutex_unlock(&snd_card_mutex);
 	card->number = idx;
 	card->module = module;
 	INIT_LIST_HEAD(&card->devices);
@@ -169,6 +171,19 @@
       	return NULL;
 }
 
+EXPORT_SYMBOL(snd_card_new);
+
+/* return non-zero if a card is already locked */
+int snd_card_locked(int card)
+{
+	int locked;
+
+	mutex_lock(&snd_card_mutex);
+	locked = snd_cards_lock & (1 << card);
+	mutex_unlock(&snd_card_mutex);
+	return locked;
+}
+
 static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig)
 {
 	return -ENODEV;
@@ -236,9 +251,9 @@
 	spin_unlock(&card->files_lock);
 
 	/* phase 1: disable fops (user space) operations for ALSA API */
-	write_lock(&snd_card_rwlock);
+	mutex_lock(&snd_card_mutex);
 	snd_cards[card->number] = NULL;
-	write_unlock(&snd_card_rwlock);
+	mutex_unlock(&snd_card_mutex);
 	
 	/* phase 2: replace file->f_op with special dummy operations */
 	
@@ -298,6 +313,8 @@
 	return 0;	
 }
 
+EXPORT_SYMBOL(snd_card_disconnect);
+
 /**
  *  snd_card_free - frees given soundcard structure
  *  @card: soundcard structure
@@ -315,9 +332,9 @@
 
 	if (card == NULL)
 		return -EINVAL;
-	write_lock(&snd_card_rwlock);
+	mutex_lock(&snd_card_mutex);
 	snd_cards[card->number] = NULL;
-	write_unlock(&snd_card_rwlock);
+	mutex_unlock(&snd_card_mutex);
 
 #ifdef CONFIG_PM
 	wake_up(&card->power_sleep);
@@ -353,13 +370,15 @@
 		card->s_f_ops = s_f_ops->next;
 		kfree(s_f_ops);
 	}
-	write_lock(&snd_card_rwlock);
+	mutex_lock(&snd_card_mutex);
 	snd_cards_lock &= ~(1 << card->number);
-	write_unlock(&snd_card_rwlock);
+	mutex_unlock(&snd_card_mutex);
 	kfree(card);
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_card_free);
+
 static void snd_card_free_thread(void * __card)
 {
 	struct snd_card *card = __card;
@@ -405,6 +424,8 @@
 	return -EFAULT;
 }
 
+EXPORT_SYMBOL(snd_card_free_in_thread);
+
 static void choose_default_id(struct snd_card *card)
 {
 	int i, len, idx_flag = 0, loops = SNDRV_CARDS;
@@ -487,16 +508,16 @@
 	snd_assert(card != NULL, return -EINVAL);
 	if ((err = snd_device_register_all(card)) < 0)
 		return err;
-	write_lock(&snd_card_rwlock);
+	mutex_lock(&snd_card_mutex);
 	if (snd_cards[card->number]) {
 		/* already registered */
-		write_unlock(&snd_card_rwlock);
+		mutex_unlock(&snd_card_mutex);
 		return 0;
 	}
 	if (card->id[0] == '\0')
 		choose_default_id(card);
 	snd_cards[card->number] = card;
-	write_unlock(&snd_card_rwlock);
+	mutex_unlock(&snd_card_mutex);
 	init_info_for_card(card);
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
 	if (snd_mixer_oss_notify_callback)
@@ -505,8 +526,10 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_card_register);
+
 #ifdef CONFIG_PROC_FS
-static struct snd_info_entry *snd_card_info_entry = NULL;
+static struct snd_info_entry *snd_card_info_entry;
 
 static void snd_card_info_read(struct snd_info_entry *entry,
 			       struct snd_info_buffer *buffer)
@@ -515,7 +538,7 @@
 	struct snd_card *card;
 
 	for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
-		read_lock(&snd_card_rwlock);
+		mutex_lock(&snd_card_mutex);
 		if ((card = snd_cards[idx]) != NULL) {
 			count++;
 			snd_iprintf(buffer, "%2i [%-15s]: %s - %s\n",
@@ -526,7 +549,7 @@
 			snd_iprintf(buffer, "                      %s\n",
 					card->longname);
 		}
-		read_unlock(&snd_card_rwlock);
+		mutex_unlock(&snd_card_mutex);
 	}
 	if (!count)
 		snd_iprintf(buffer, "--- no soundcards ---\n");
@@ -540,12 +563,12 @@
 	struct snd_card *card;
 
 	for (idx = count = 0; idx < SNDRV_CARDS; idx++) {
-		read_lock(&snd_card_rwlock);
+		mutex_lock(&snd_card_mutex);
 		if ((card = snd_cards[idx]) != NULL) {
 			count++;
 			snd_iprintf(buffer, "%s\n", card->longname);
 		}
-		read_unlock(&snd_card_rwlock);
+		mutex_unlock(&snd_card_mutex);
 	}
 	if (!count) {
 		snd_iprintf(buffer, "--- no soundcards ---\n");
@@ -563,11 +586,11 @@
 	struct snd_card *card;
 
 	for (idx = 0; idx < SNDRV_CARDS; idx++) {
-		read_lock(&snd_card_rwlock);
+		mutex_lock(&snd_card_mutex);
 		if ((card = snd_cards[idx]) != NULL)
 			snd_iprintf(buffer, "%2i %s\n",
 				    idx, card->module->name);
-		read_unlock(&snd_card_rwlock);
+		mutex_unlock(&snd_card_mutex);
 	}
 }
 #endif
@@ -579,7 +602,6 @@
 	entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL);
 	if (! entry)
 		return -ENOMEM;
-	entry->c.text.read_size = PAGE_SIZE;
 	entry->c.text.read = snd_card_info_read;
 	if (snd_info_register(entry) < 0) {
 		snd_info_free_entry(entry);
@@ -590,7 +612,6 @@
 #ifdef MODULE
 	entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL);
 	if (entry) {
-		entry->c.text.read_size = PAGE_SIZE;
 		entry->c.text.read = snd_card_module_info_read;
 		if (snd_info_register(entry) < 0)
 			snd_info_free_entry(entry);
@@ -644,6 +665,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_component_add);
+
 /**
  *  snd_card_file_add - add the file to the file list of the card
  *  @card: soundcard structure
@@ -676,6 +699,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_card_file_add);
+
 /**
  *  snd_card_file_remove - remove the file from the file list
  *  @card: soundcard structure
@@ -717,6 +742,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_card_file_remove);
+
 #ifdef CONFIG_PM
 /**
  *  snd_power_wait - wait until the power-state is changed.
@@ -753,4 +780,5 @@
 	return result;
 }
 
+EXPORT_SYMBOL(snd_power_wait);
 #endif /* CONFIG_PM */
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index 1a37895..d523987 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -56,6 +56,8 @@
 	release_dma_lock(flags);
 }
 
+EXPORT_SYMBOL(snd_dma_program);
+
 /**
  * snd_dma_disable - stop the ISA DMA transfer
  * @dma: the dma number
@@ -72,6 +74,8 @@
 	release_dma_lock(flags);
 }
 
+EXPORT_SYMBOL(snd_dma_disable);
+
 /**
  * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes
  * @dma: the dma number
@@ -101,3 +105,5 @@
 	else
 		return size - result;
 }
+
+EXPORT_SYMBOL(snd_dma_pointer);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 862d62d..fe59850 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -55,6 +56,8 @@
 #endif
 }
 
+EXPORT_SYMBOL(copy_to_user_fromio);
+
 /**
  * copy_from_user_toio - copy data from user-space to mmio-space
  * @dst: the destination pointer on mmio-space
@@ -85,3 +88,5 @@
 	return 0;
 #endif
 }
+
+EXPORT_SYMBOL(copy_from_user_toio);
diff --git a/sound/core/misc.c b/sound/core/misc.c
index b53e563..03fc711 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -34,6 +34,8 @@
 	}
 }
 
+EXPORT_SYMBOL(release_and_free_resource);
+
 #ifdef CONFIG_SND_VERBOSE_PRINTK
 void snd_verbose_printk(const char *file, int line, const char *format, ...)
 {
@@ -51,6 +53,8 @@
 	vprintk(format, args);
 	va_end(args);
 }
+
+EXPORT_SYMBOL(snd_verbose_printk);
 #endif
 
 #if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
@@ -71,4 +75,6 @@
 	va_end(args);
 
 }
+
+EXPORT_SYMBOL(snd_verbose_printd);
 #endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 9c68bc3..71b5080 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -1182,9 +1182,7 @@
 		return;
 	entry->content = SNDRV_INFO_CONTENT_TEXT;
 	entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-	entry->c.text.read_size = 8192;
 	entry->c.text.read = snd_mixer_oss_proc_read;
-	entry->c.text.write_size = 8192;
 	entry->c.text.write = snd_mixer_oss_proc_write;
 	entry->private_data = mixer;
 	if (snd_info_register(entry) < 0) {
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index ac990bf..f5ff4f4 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -45,7 +45,7 @@
 
 #define OSS_ALSAEMULVER		_SIOR ('M', 249, int)
 
-static int dsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0};
+static int dsp_map[SNDRV_CARDS];
 static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
 static int nonblock_open = 1;
 
@@ -78,6 +78,487 @@
 	set_fs(fs);
 }
 
+/*
+ * helper functions to process hw_params
+ */
+static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
+{
+	int changed = 0;
+	if (i->min < min) {
+		i->min = min;
+		i->openmin = openmin;
+		changed = 1;
+	} else if (i->min == min && !i->openmin && openmin) {
+		i->openmin = 1;
+		changed = 1;
+	}
+	if (i->integer) {
+		if (i->openmin) {
+			i->min++;
+			i->openmin = 0;
+		}
+	}
+	if (snd_interval_checkempty(i)) {
+		snd_interval_none(i);
+		return -EINVAL;
+	}
+	return changed;
+}
+
+static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
+{
+	int changed = 0;
+	if (i->max > max) {
+		i->max = max;
+		i->openmax = openmax;
+		changed = 1;
+	} else if (i->max == max && !i->openmax && openmax) {
+		i->openmax = 1;
+		changed = 1;
+	}
+	if (i->integer) {
+		if (i->openmax) {
+			i->max--;
+			i->openmax = 0;
+		}
+	}
+	if (snd_interval_checkempty(i)) {
+		snd_interval_none(i);
+		return -EINVAL;
+	}
+	return changed;
+}
+
+static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
+{
+	struct snd_interval t;
+	t.empty = 0;
+	t.min = t.max = val;
+	t.openmin = t.openmax = 0;
+	t.integer = 1;
+	return snd_interval_refine(i, &t);
+}
+
+/**
+ * snd_pcm_hw_param_value_min
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
+ *
+ * Return the minimum value for field PAR.
+ */
+static unsigned int
+snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
+			   snd_pcm_hw_param_t var, int *dir)
+{
+	if (hw_is_mask(var)) {
+		if (dir)
+			*dir = 0;
+		return snd_mask_min(hw_param_mask_c(params, var));
+	}
+	if (hw_is_interval(var)) {
+		const struct snd_interval *i = hw_param_interval_c(params, var);
+		if (dir)
+			*dir = i->openmin;
+		return snd_interval_min(i);
+	}
+	return -EINVAL;
+}
+
+/**
+ * snd_pcm_hw_param_value_max
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @dir: pointer to the direction (-1,0,1) or NULL
+ *
+ * Return the maximum value for field PAR.
+ */
+static unsigned int
+snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
+			   snd_pcm_hw_param_t var, int *dir)
+{
+	if (hw_is_mask(var)) {
+		if (dir)
+			*dir = 0;
+		return snd_mask_max(hw_param_mask_c(params, var));
+	}
+	if (hw_is_interval(var)) {
+		const struct snd_interval *i = hw_param_interval_c(params, var);
+		if (dir)
+			*dir = - (int) i->openmax;
+		return snd_interval_max(i);
+	}
+	return -EINVAL;
+}
+
+static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
+				  snd_pcm_hw_param_t var,
+				  const struct snd_mask *val)
+{
+	int changed;
+	changed = snd_mask_refine(hw_param_mask(params, var), val);
+	if (changed) {
+		params->cmask |= 1 << var;
+		params->rmask |= 1 << var;
+	}
+	return changed;
+}
+
+static int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm,
+				 struct snd_pcm_hw_params *params,
+				 snd_pcm_hw_param_t var,
+				 const struct snd_mask *val)
+{
+	int changed = _snd_pcm_hw_param_mask(params, var, val);
+	if (changed < 0)
+		return changed;
+	if (params->rmask) {
+		int err = snd_pcm_hw_refine(pcm, params);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
+				 snd_pcm_hw_param_t var, unsigned int val,
+				 int dir)
+{
+	int changed;
+	int open = 0;
+	if (dir) {
+		if (dir > 0) {
+			open = 1;
+		} else if (dir < 0) {
+			if (val > 0) {
+				open = 1;
+				val--;
+			}
+		}
+	}
+	if (hw_is_mask(var))
+		changed = snd_mask_refine_min(hw_param_mask(params, var),
+					      val + !!open);
+	else if (hw_is_interval(var))
+		changed = snd_interval_refine_min(hw_param_interval(params, var),
+						  val, open);
+	else
+		return -EINVAL;
+	if (changed) {
+		params->cmask |= 1 << var;
+		params->rmask |= 1 << var;
+	}
+	return changed;
+}
+
+/**
+ * snd_pcm_hw_param_min
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: minimal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
+ *
+ * Inside configuration space defined by PARAMS remove from PAR all 
+ * values < VAL. Reduce configuration space accordingly.
+ * Return new minimum or -EINVAL if the configuration space is empty
+ */
+static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm,
+				struct snd_pcm_hw_params *params,
+				snd_pcm_hw_param_t var, unsigned int val,
+				int *dir)
+{
+	int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
+	if (changed < 0)
+		return changed;
+	if (params->rmask) {
+		int err = snd_pcm_hw_refine(pcm, params);
+		if (err < 0)
+			return err;
+	}
+	return snd_pcm_hw_param_value_min(params, var, dir);
+}
+
+static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
+				 snd_pcm_hw_param_t var, unsigned int val,
+				 int dir)
+{
+	int changed;
+	int open = 0;
+	if (dir) {
+		if (dir < 0) {
+			open = 1;
+		} else if (dir > 0) {
+			open = 1;
+			val++;
+		}
+	}
+	if (hw_is_mask(var)) {
+		if (val == 0 && open) {
+			snd_mask_none(hw_param_mask(params, var));
+			changed = -EINVAL;
+		} else
+			changed = snd_mask_refine_max(hw_param_mask(params, var),
+						      val - !!open);
+	} else if (hw_is_interval(var))
+		changed = snd_interval_refine_max(hw_param_interval(params, var),
+						  val, open);
+	else
+		return -EINVAL;
+	if (changed) {
+		params->cmask |= 1 << var;
+		params->rmask |= 1 << var;
+	}
+	return changed;
+}
+
+/**
+ * snd_pcm_hw_param_max
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: maximal value
+ * @dir: pointer to the direction (-1,0,1) or NULL
+ *
+ * Inside configuration space defined by PARAMS remove from PAR all 
+ *  values >= VAL + 1. Reduce configuration space accordingly.
+ *  Return new maximum or -EINVAL if the configuration space is empty
+ */
+static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm,
+				struct snd_pcm_hw_params *params,
+				snd_pcm_hw_param_t var, unsigned int val,
+				int *dir)
+{
+	int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
+	if (changed < 0)
+		return changed;
+	if (params->rmask) {
+		int err = snd_pcm_hw_refine(pcm, params);
+		if (err < 0)
+			return err;
+	}
+	return snd_pcm_hw_param_value_max(params, var, dir);
+}
+
+static int boundary_sub(int a, int adir,
+			int b, int bdir,
+			int *c, int *cdir)
+{
+	adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
+	bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
+	*c = a - b;
+	*cdir = adir - bdir;
+	if (*cdir == -2) {
+		(*c)--;
+	} else if (*cdir == 2) {
+		(*c)++;
+	}
+	return 0;
+}
+
+static int boundary_lt(unsigned int a, int adir,
+		       unsigned int b, int bdir)
+{
+	if (adir < 0) {
+		a--;
+		adir = 1;
+	} else if (adir > 0)
+		adir = 1;
+	if (bdir < 0) {
+		b--;
+		bdir = 1;
+	} else if (bdir > 0)
+		bdir = 1;
+	return a < b || (a == b && adir < bdir);
+}
+
+/* Return 1 if min is nearer to best than max */
+static int boundary_nearer(int min, int mindir,
+			   int best, int bestdir,
+			   int max, int maxdir)
+{
+	int dmin, dmindir;
+	int dmax, dmaxdir;
+	boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
+	boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
+	return boundary_lt(dmin, dmindir, dmax, dmaxdir);
+}
+
+/**
+ * snd_pcm_hw_param_near
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @best: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
+ *
+ * Inside configuration space defined by PARAMS set PAR to the available value
+ * nearest to VAL. Reduce configuration space accordingly.
+ * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
+ * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
+ * Return the value found.
+  */
+static int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm,
+				 struct snd_pcm_hw_params *params,
+				 snd_pcm_hw_param_t var, unsigned int best,
+				 int *dir)
+{
+	struct snd_pcm_hw_params *save = NULL;
+	int v;
+	unsigned int saved_min;
+	int last = 0;
+	int min, max;
+	int mindir, maxdir;
+	int valdir = dir ? *dir : 0;
+	/* FIXME */
+	if (best > INT_MAX)
+		best = INT_MAX;
+	min = max = best;
+	mindir = maxdir = valdir;
+	if (maxdir > 0)
+		maxdir = 0;
+	else if (maxdir == 0)
+		maxdir = -1;
+	else {
+		maxdir = 1;
+		max--;
+	}
+	save = kmalloc(sizeof(*save), GFP_KERNEL);
+	if (save == NULL)
+		return -ENOMEM;
+	*save = *params;
+	saved_min = min;
+	min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
+	if (min >= 0) {
+		struct snd_pcm_hw_params *params1;
+		if (max < 0)
+			goto _end;
+		if ((unsigned int)min == saved_min && mindir == valdir)
+			goto _end;
+		params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
+		if (params1 == NULL) {
+			kfree(save);
+			return -ENOMEM;
+		}
+		*params1 = *save;
+		max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
+		if (max < 0) {
+			kfree(params1);
+			goto _end;
+		}
+		if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
+			*params = *params1;
+			last = 1;
+		}
+		kfree(params1);
+	} else {
+		*params = *save;
+		max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
+		snd_assert(max >= 0, return -EINVAL);
+		last = 1;
+	}
+ _end:
+ 	kfree(save);
+	if (last)
+		v = snd_pcm_hw_param_last(pcm, params, var, dir);
+	else
+		v = snd_pcm_hw_param_first(pcm, params, var, dir);
+	snd_assert(v >= 0, return -EINVAL);
+	return v;
+}
+
+static int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
+				 snd_pcm_hw_param_t var, unsigned int val,
+				 int dir)
+{
+	int changed;
+	if (hw_is_mask(var)) {
+		struct snd_mask *m = hw_param_mask(params, var);
+		if (val == 0 && dir < 0) {
+			changed = -EINVAL;
+			snd_mask_none(m);
+		} else {
+			if (dir > 0)
+				val++;
+			else if (dir < 0)
+				val--;
+			changed = snd_mask_refine_set(hw_param_mask(params, var), val);
+		}
+	} else if (hw_is_interval(var)) {
+		struct snd_interval *i = hw_param_interval(params, var);
+		if (val == 0 && dir < 0) {
+			changed = -EINVAL;
+			snd_interval_none(i);
+		} else if (dir == 0)
+			changed = snd_interval_refine_set(i, val);
+		else {
+			struct snd_interval t;
+			t.openmin = 1;
+			t.openmax = 1;
+			t.empty = 0;
+			t.integer = 0;
+			if (dir < 0) {
+				t.min = val - 1;
+				t.max = val;
+			} else {
+				t.min = val;
+				t.max = val+1;
+			}
+			changed = snd_interval_refine(i, &t);
+		}
+	} else
+		return -EINVAL;
+	if (changed) {
+		params->cmask |= 1 << var;
+		params->rmask |= 1 << var;
+	}
+	return changed;
+}
+
+/**
+ * snd_pcm_hw_param_set
+ * @pcm: PCM instance
+ * @params: the hw_params instance
+ * @var: parameter to retrieve
+ * @val: value to set
+ * @dir: pointer to the direction (-1,0,1) or NULL
+ *
+ * Inside configuration space defined by PARAMS remove from PAR all 
+ * values != VAL. Reduce configuration space accordingly.
+ *  Return VAL or -EINVAL if the configuration space is empty
+ */
+static int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm,
+				struct snd_pcm_hw_params *params,
+				snd_pcm_hw_param_t var, unsigned int val,
+				int dir)
+{
+	int changed = _snd_pcm_hw_param_set(params, var, val, dir);
+	if (changed < 0)
+		return changed;
+	if (params->rmask) {
+		int err = snd_pcm_hw_refine(pcm, params);
+		if (err < 0)
+			return err;
+	}
+	return snd_pcm_hw_param_value(params, var, NULL);
+}
+
+static int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
+					snd_pcm_hw_param_t var)
+{
+	int changed;
+	changed = snd_interval_setinteger(hw_param_interval(params, var));
+	if (changed) {
+		params->cmask |= 1 << var;
+		params->rmask |= 1 << var;
+	}
+	return changed;
+}
+	
+/*
+ * plugin
+ */
+
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
 static int snd_pcm_oss_plugin_clear(struct snd_pcm_substream *substream)
 {
@@ -203,7 +684,7 @@
 	oss_buffer_size = snd_pcm_plug_client_size(substream,
 						   snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size;
 	oss_buffer_size = 1 << ld2(oss_buffer_size);
-	if (atomic_read(&runtime->mmap_count)) {
+	if (atomic_read(&substream->mmap_count)) {
 		if (oss_buffer_size > runtime->oss.mmap_bytes)
 			oss_buffer_size = runtime->oss.mmap_bytes;
 	}
@@ -338,7 +819,7 @@
 		goto failure;
 	}
 
-	if (atomic_read(&runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		direct = 1;
 	else
 		direct = substream->oss.setup.direct;
@@ -347,7 +828,7 @@
 	_snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS);
 	_snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
 	snd_mask_none(&mask);
-	if (atomic_read(&runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
 	else {
 		snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
@@ -466,7 +947,8 @@
 	} else {
 		sw_params->start_threshold = runtime->boundary;
 	}
-	if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+	if (atomic_read(&substream->mmap_count) ||
+	    substream->stream == SNDRV_PCM_STREAM_CAPTURE)
 		sw_params->stop_threshold = runtime->boundary;
 	else
 		sw_params->stop_threshold = runtime->buffer_size;
@@ -476,7 +958,7 @@
 	sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
 		1 : runtime->period_size;
 	sw_params->xfer_align = 1;
-	if (atomic_read(&runtime->mmap_count) ||
+	if (atomic_read(&substream->mmap_count) ||
 	    substream->oss.setup.nosilence) {
 		sw_params->silence_threshold = 0;
 		sw_params->silence_size = 0;
@@ -820,7 +1302,7 @@
 	ssize_t tmp;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	if (atomic_read(&runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		return -ENXIO;
 
 	if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
@@ -850,7 +1332,7 @@
 				if (runtime->oss.period_ptr == 0 ||
 				    runtime->oss.period_ptr == runtime->oss.buffer_used)
 					runtime->oss.buffer_used = 0;
-				else if ((substream->ffile->f_flags & O_NONBLOCK) != 0)
+				else if ((substream->f_flags & O_NONBLOCK) != 0)
 					return xfer > 0 ? xfer : -EAGAIN;
 			}
 		} else {
@@ -863,7 +1345,7 @@
 			buf += tmp;
 			bytes -= tmp;
 			xfer += tmp;
-			if ((substream->ffile->f_flags & O_NONBLOCK) != 0 &&
+			if ((substream->f_flags & O_NONBLOCK) != 0 &&
 			    tmp != runtime->oss.period_bytes)
 				break;
 		}
@@ -910,7 +1392,7 @@
 	ssize_t tmp;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 
-	if (atomic_read(&runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		return -ENXIO;
 
 	if ((tmp = snd_pcm_oss_make_ready(substream)) < 0)
@@ -1040,7 +1522,7 @@
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	if (substream != NULL) {
 		runtime = substream->runtime;
-		if (atomic_read(&runtime->mmap_count))
+		if (atomic_read(&substream->mmap_count))
 			goto __direct;
 		if ((err = snd_pcm_oss_make_ready(substream)) < 0)
 			return err;
@@ -1101,10 +1583,10 @@
 		 * finish sync: drain the buffer
 		 */
 	      __direct:
-		saved_f_flags = substream->ffile->f_flags;
-		substream->ffile->f_flags &= ~O_NONBLOCK;
+		saved_f_flags = substream->f_flags;
+		substream->f_flags &= ~O_NONBLOCK;
 		err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
-		substream->ffile->f_flags = saved_f_flags;
+		substream->f_flags = saved_f_flags;
 		if (err < 0)
 			return err;
 		runtime->oss.prepare = 1;
@@ -1209,7 +1691,7 @@
 
 	if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
 		return err;
-	if (atomic_read(&substream->runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		direct = 1;
 	else
 		direct = substream->oss.setup.direct;
@@ -1419,7 +1901,7 @@
 		if (trigger & PCM_ENABLE_OUTPUT) {
 			if (runtime->oss.trigger)
 				goto _skip1;
-			if (atomic_read(&psubstream->runtime->mmap_count))
+			if (atomic_read(&psubstream->mmap_count))
 				snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt);
 			runtime->oss.trigger = 1;
 			runtime->start_threshold = 1;
@@ -1537,7 +2019,7 @@
 	if (err < 0)
 		return err;
 	info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
-	if (atomic_read(&runtime->mmap_count)) {
+	if (atomic_read(&substream->mmap_count)) {
 		snd_pcm_sframes_t n;
 		n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt;
 		if (n < 0)
@@ -1683,9 +2165,9 @@
 	substream->oss.oss = 1;
 	substream->oss.setup = *setup;
 	if (setup->nonblock)
-		substream->ffile->f_flags |= O_NONBLOCK;
+		substream->f_flags |= O_NONBLOCK;
 	else if (setup->block)
-		substream->ffile->f_flags &= ~O_NONBLOCK;
+		substream->f_flags &= ~O_NONBLOCK;
 	runtime = substream->runtime;
 	runtime->oss.params = 1;
 	runtime->oss.trigger = 1;
@@ -1742,6 +2224,7 @@
 	    (pcm->info_flags & SNDRV_PCM_INFO_HALF_DUPLEX))
 		f_mode = FMODE_WRITE;
 
+	file->f_flags &= ~O_APPEND;
 	for (idx = 0; idx < 2; idx++) {
 		if (setup[idx].disable)
 			continue;
@@ -2059,6 +2542,7 @@
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
 	if (substream == NULL)
 		return -ENXIO;
+	substream->f_flags = file->f_flags & O_NONBLOCK;
 #ifndef OSS_DEBUG
 	return snd_pcm_oss_read1(substream, buf, count);
 #else
@@ -2080,6 +2564,7 @@
 	substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	if (substream == NULL)
 		return -ENXIO;
+	substream->f_flags = file->f_flags & O_NONBLOCK;
 	result = snd_pcm_oss_write1(substream, buf, count);
 #ifdef OSS_DEBUG
 	printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
@@ -2090,7 +2575,7 @@
 static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	if (atomic_read(&runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
 	else
 		return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames;
@@ -2099,7 +2584,7 @@
 static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
-	if (atomic_read(&runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt;
 	else
 		return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames;
@@ -2342,9 +2827,7 @@
 		if ((entry = snd_info_create_card_entry(pcm->card, "oss", pstr->proc_root)) != NULL) {
 			entry->content = SNDRV_INFO_CONTENT_TEXT;
 			entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-			entry->c.text.read_size = 8192;
 			entry->c.text.read = snd_pcm_oss_proc_read;
-			entry->c.text.write_size = 8192;
 			entry->c.text.write = snd_pcm_oss_proc_write;
 			entry->private_data = pstr;
 			if (snd_info_register(entry) < 0) {
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 84b0003..7581edd 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -351,10 +351,8 @@
 		snd_iprintf(buffer, "closed\n");
 		return;
 	}
-	snd_pcm_stream_lock_irq(substream);
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 		snd_iprintf(buffer, "no setup\n");
-		snd_pcm_stream_unlock_irq(substream);
 		return;
 	}
 	snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
@@ -375,7 +373,6 @@
 		snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
 	}
 #endif
-	snd_pcm_stream_unlock_irq(substream);
 }
 
 static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
@@ -387,10 +384,8 @@
 		snd_iprintf(buffer, "closed\n");
 		return;
 	}
-	snd_pcm_stream_lock_irq(substream);
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 		snd_iprintf(buffer, "no setup\n");
-		snd_pcm_stream_unlock_irq(substream);
 		return;
 	}
 	snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
@@ -403,7 +398,6 @@
 	snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
 	snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
 	snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
-	snd_pcm_stream_unlock_irq(substream);
 }
 
 static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
@@ -472,7 +466,7 @@
 	pstr->proc_root = entry;
 
 	if ((entry = snd_info_create_card_entry(pcm->card, "info", pstr->proc_root)) != NULL) {
-		snd_info_set_text_ops(entry, pstr, 256, snd_pcm_stream_proc_info_read);
+		snd_info_set_text_ops(entry, pstr, snd_pcm_stream_proc_info_read);
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
 			entry = NULL;
@@ -483,9 +477,7 @@
 #ifdef CONFIG_SND_PCM_XRUN_DEBUG
 	if ((entry = snd_info_create_card_entry(pcm->card, "xrun_debug",
 						pstr->proc_root)) != NULL) {
-		entry->c.text.read_size = 64;
 		entry->c.text.read = snd_pcm_xrun_debug_read;
-		entry->c.text.write_size = 64;
 		entry->c.text.write = snd_pcm_xrun_debug_write;
 		entry->mode |= S_IWUSR;
 		entry->private_data = pstr;
@@ -537,7 +529,8 @@
 	substream->proc_root = entry;
 
 	if ((entry = snd_info_create_card_entry(card, "info", substream->proc_root)) != NULL) {
-		snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_info_read);
+		snd_info_set_text_ops(entry, substream,
+				      snd_pcm_substream_proc_info_read);
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
 			entry = NULL;
@@ -546,7 +539,8 @@
 	substream->proc_info_entry = entry;
 
 	if ((entry = snd_info_create_card_entry(card, "hw_params", substream->proc_root)) != NULL) {
-		snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_hw_params_read);
+		snd_info_set_text_ops(entry, substream,
+				      snd_pcm_substream_proc_hw_params_read);
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
 			entry = NULL;
@@ -555,7 +549,8 @@
 	substream->proc_hw_params_entry = entry;
 
 	if ((entry = snd_info_create_card_entry(card, "sw_params", substream->proc_root)) != NULL) {
-		snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_sw_params_read);
+		snd_info_set_text_ops(entry, substream,
+				      snd_pcm_substream_proc_sw_params_read);
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
 			entry = NULL;
@@ -564,7 +559,8 @@
 	substream->proc_sw_params_entry = entry;
 
 	if ((entry = snd_info_create_card_entry(card, "status", substream->proc_root)) != NULL) {
-		snd_info_set_text_ops(entry, substream, 256, snd_pcm_substream_proc_status_read);
+		snd_info_set_text_ops(entry, substream,
+				      snd_pcm_substream_proc_status_read);
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
 			entry = NULL;
@@ -666,11 +662,14 @@
 		INIT_LIST_HEAD(&substream->self_group.substreams);
 		list_add_tail(&substream->link_list, &substream->self_group.substreams);
 		spin_lock_init(&substream->timer_lock);
+		atomic_set(&substream->mmap_count, 0);
 		prev = substream;
 	}
 	return 0;
 }				
 
+EXPORT_SYMBOL(snd_pcm_new_stream);
+
 /**
  * snd_pcm_new - create a new PCM instance
  * @card: the card instance
@@ -730,6 +729,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_new);
+
 static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
 {
 	struct snd_pcm_substream *substream, *substream_next;
@@ -829,6 +830,26 @@
 		return -EINVAL;
 	}
 
+	if (file->f_flags & O_APPEND) {
+		if (prefer_subdevice < 0) {
+			if (pstr->substream_count > 1)
+				return -EINVAL; /* must be unique */
+			substream = pstr->substream;
+		} else {
+			for (substream = pstr->substream; substream;
+			     substream = substream->next)
+				if (substream->number == prefer_subdevice)
+					break;
+		}
+		if (! substream)
+			return -ENODEV;
+		if (! SUBSTREAM_BUSY(substream))
+			return -EBADFD;
+		substream->ref_count++;
+		*rsubstream = substream;
+		return 0;
+	}
+
 	if (prefer_subdevice >= 0) {
 		for (substream = pstr->substream; substream; substream = substream->next)
 			if (!SUBSTREAM_BUSY(substream) && substream->number == prefer_subdevice)
@@ -864,7 +885,6 @@
 	memset((void*)runtime->control, 0, size);
 
 	init_waitqueue_head(&runtime->sleep);
-	atomic_set(&runtime->mmap_count, 0);
 	init_timer(&runtime->tick_timer);
 	runtime->tick_timer.function = snd_pcm_tick_timer_func;
 	runtime->tick_timer.data = (unsigned long) substream;
@@ -873,7 +893,8 @@
 
 	substream->runtime = runtime;
 	substream->private_data = pcm->private_data;
-	substream->ffile = file;
+	substream->ref_count = 1;
+	substream->f_flags = file->f_flags;
 	pstr->substream_opened++;
 	*rsubstream = substream;
 	return 0;
@@ -882,7 +903,7 @@
 void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
 {
 	struct snd_pcm_runtime *runtime;
-	substream->file = NULL;
+
 	runtime = substream->runtime;
 	snd_assert(runtime != NULL, return);
 	if (runtime->private_free != NULL)
@@ -1022,6 +1043,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_notify);
+
 #ifdef CONFIG_PROC_FS
 /*
  *  Info interface
@@ -1049,15 +1072,14 @@
 	mutex_unlock(&register_mutex);
 }
 
-static struct snd_info_entry *snd_pcm_proc_entry = NULL;
+static struct snd_info_entry *snd_pcm_proc_entry;
 
 static void snd_pcm_proc_init(void)
 {
 	struct snd_info_entry *entry;
 
 	if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
-		snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128,
-				      snd_pcm_proc_read);
+		snd_info_set_text_ops(entry, NULL, snd_pcm_proc_read);
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
 			entry = NULL;
@@ -1099,33 +1121,3 @@
 
 module_init(alsa_pcm_init)
 module_exit(alsa_pcm_exit)
-
-EXPORT_SYMBOL(snd_pcm_new);
-EXPORT_SYMBOL(snd_pcm_new_stream);
-EXPORT_SYMBOL(snd_pcm_notify);
-EXPORT_SYMBOL(snd_pcm_open_substream);
-EXPORT_SYMBOL(snd_pcm_release_substream);
-  /* pcm_native.c */
-EXPORT_SYMBOL(snd_pcm_link_rwlock);
-#ifdef CONFIG_PM
-EXPORT_SYMBOL(snd_pcm_suspend);
-EXPORT_SYMBOL(snd_pcm_suspend_all);
-#endif
-EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
-EXPORT_SYMBOL(snd_pcm_mmap_data);
-#if SNDRV_PCM_INFO_MMAP_IOMEM
-EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
-#endif
- /* pcm_misc.c */
-EXPORT_SYMBOL(snd_pcm_format_signed);
-EXPORT_SYMBOL(snd_pcm_format_unsigned);
-EXPORT_SYMBOL(snd_pcm_format_linear);
-EXPORT_SYMBOL(snd_pcm_format_little_endian);
-EXPORT_SYMBOL(snd_pcm_format_big_endian);
-EXPORT_SYMBOL(snd_pcm_format_width);
-EXPORT_SYMBOL(snd_pcm_format_physical_width);
-EXPORT_SYMBOL(snd_pcm_format_size);
-EXPORT_SYMBOL(snd_pcm_format_silence_64);
-EXPORT_SYMBOL(snd_pcm_format_set_silence);
-EXPORT_SYMBOL(snd_pcm_build_linear_format);
-EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index e513303..2b8aab6 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -497,9 +497,9 @@
 	case SNDRV_PCM_IOCTL_LINK:
 	case SNDRV_PCM_IOCTL_UNLINK:
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			return snd_pcm_playback_ioctl1(substream, cmd, argp);
+			return snd_pcm_playback_ioctl1(file, substream, cmd, argp);
 		else
-			return snd_pcm_capture_ioctl1(substream, cmd, argp);
+			return snd_pcm_capture_ioctl1(file, substream, cmd, argp);
 	case SNDRV_PCM_IOCTL_HW_REFINE32:
 		return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
 	case SNDRV_PCM_IOCTL_HW_PARAMS32:
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eedc6cb..0bb142a 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -289,6 +289,7 @@
 		substream->ops = ops;
 }
 
+EXPORT_SYMBOL(snd_pcm_set_ops);
 
 /**
  * snd_pcm_sync - set the PCM sync id
@@ -306,13 +307,12 @@
 	runtime->sync.id32[3] = -1;
 }
 
+EXPORT_SYMBOL(snd_pcm_set_sync);
+
 /*
  *  Standard ioctl routine
  */
 
-/* Code taken from alsa-lib */
-#define assert(a) snd_assert((a), return -EINVAL)
-
 static inline unsigned int div32(unsigned int a, unsigned int b, 
 				 unsigned int *r)
 {
@@ -369,56 +369,6 @@
 	return n;
 }
 
-static int snd_interval_refine_min(struct snd_interval *i, unsigned int min, int openmin)
-{
-	int changed = 0;
-	assert(!snd_interval_empty(i));
-	if (i->min < min) {
-		i->min = min;
-		i->openmin = openmin;
-		changed = 1;
-	} else if (i->min == min && !i->openmin && openmin) {
-		i->openmin = 1;
-		changed = 1;
-	}
-	if (i->integer) {
-		if (i->openmin) {
-			i->min++;
-			i->openmin = 0;
-		}
-	}
-	if (snd_interval_checkempty(i)) {
-		snd_interval_none(i);
-		return -EINVAL;
-	}
-	return changed;
-}
-
-static int snd_interval_refine_max(struct snd_interval *i, unsigned int max, int openmax)
-{
-	int changed = 0;
-	assert(!snd_interval_empty(i));
-	if (i->max > max) {
-		i->max = max;
-		i->openmax = openmax;
-		changed = 1;
-	} else if (i->max == max && !i->openmax && openmax) {
-		i->openmax = 1;
-		changed = 1;
-	}
-	if (i->integer) {
-		if (i->openmax) {
-			i->max--;
-			i->openmax = 0;
-		}
-	}
-	if (snd_interval_checkempty(i)) {
-		snd_interval_none(i);
-		return -EINVAL;
-	}
-	return changed;
-}
-
 /**
  * snd_interval_refine - refine the interval value of configurator
  * @i: the interval value to refine
@@ -433,7 +383,7 @@
 int snd_interval_refine(struct snd_interval *i, const struct snd_interval *v)
 {
 	int changed = 0;
-	assert(!snd_interval_empty(i));
+	snd_assert(!snd_interval_empty(i), return -EINVAL);
 	if (i->min < v->min) {
 		i->min = v->min;
 		i->openmin = v->openmin;
@@ -472,9 +422,11 @@
 	return changed;
 }
 
+EXPORT_SYMBOL(snd_interval_refine);
+
 static int snd_interval_refine_first(struct snd_interval *i)
 {
-	assert(!snd_interval_empty(i));
+	snd_assert(!snd_interval_empty(i), return -EINVAL);
 	if (snd_interval_single(i))
 		return 0;
 	i->max = i->min;
@@ -486,7 +438,7 @@
 
 static int snd_interval_refine_last(struct snd_interval *i)
 {
-	assert(!snd_interval_empty(i));
+	snd_assert(!snd_interval_empty(i), return -EINVAL);
 	if (snd_interval_single(i))
 		return 0;
 	i->min = i->max;
@@ -496,16 +448,6 @@
 	return 1;
 }
 
-static int snd_interval_refine_set(struct snd_interval *i, unsigned int val)
-{
-	struct snd_interval t;
-	t.empty = 0;
-	t.min = t.max = val;
-	t.openmin = t.openmax = 0;
-	t.integer = 1;
-	return snd_interval_refine(i, &t);
-}
-
 void snd_interval_mul(const struct snd_interval *a, const struct snd_interval *b, struct snd_interval *c)
 {
 	if (a->empty || b->empty) {
@@ -621,7 +563,6 @@
 	c->integer = 0;
 }
 
-#undef assert
 /* ---- */
 
 
@@ -727,6 +668,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(snd_interval_ratnum);
+
 /**
  * snd_interval_ratden - refine the interval value
  * @i: interval to refine
@@ -877,6 +820,8 @@
         return changed;
 }
 
+EXPORT_SYMBOL(snd_interval_list);
+
 static int snd_interval_step(struct snd_interval *i, unsigned int min, unsigned int step)
 {
 	unsigned int n;
@@ -953,6 +898,8 @@
 	return 0;
 }				    
 
+EXPORT_SYMBOL(snd_pcm_hw_rule_add);
+
 /**
  * snd_pcm_hw_constraint_mask
  * @runtime: PCM runtime instance
@@ -1007,6 +954,8 @@
 	return snd_interval_setinteger(constrs_interval(constrs, var));
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
+
 /**
  * snd_pcm_hw_constraint_minmax
  * @runtime: PCM runtime instance
@@ -1028,6 +977,8 @@
 	return snd_interval_refine(constrs_interval(constrs, var), &t);
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
+
 static int snd_pcm_hw_rule_list(struct snd_pcm_hw_params *params,
 				struct snd_pcm_hw_rule *rule)
 {
@@ -1055,6 +1006,8 @@
 				   var, -1);
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
+
 static int snd_pcm_hw_rule_ratnums(struct snd_pcm_hw_params *params,
 				   struct snd_pcm_hw_rule *rule)
 {
@@ -1087,6 +1040,8 @@
 				   var, -1);
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
+
 static int snd_pcm_hw_rule_ratdens(struct snd_pcm_hw_params *params,
 				   struct snd_pcm_hw_rule *rule)
 {
@@ -1118,6 +1073,8 @@
 				   var, -1);
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
+
 static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
 				  struct snd_pcm_hw_rule *rule)
 {
@@ -1149,6 +1106,8 @@
 				    SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
+
 static int snd_pcm_hw_rule_step(struct snd_pcm_hw_params *params,
 				struct snd_pcm_hw_rule *rule)
 {
@@ -1173,6 +1132,8 @@
 				   var, -1);
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
+
 static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
 {
 	static int pow2_sizes[] = {
@@ -1200,11 +1161,7 @@
 				   var, -1);
 }
 
-/* To use the same code we have in alsa-lib */
-#define assert(i) snd_assert((i), return -EINVAL)
-#ifndef INT_MIN
-#define INT_MIN ((int)((unsigned int)INT_MAX+1))
-#endif
+EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
 
 static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
 				  snd_pcm_hw_param_t var)
@@ -1224,18 +1181,6 @@
 	snd_BUG();
 }
 
-#if 0
-/*
- * snd_pcm_hw_param_any
- */
-int snd_pcm_hw_param_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
-			 snd_pcm_hw_param_t var)
-{
-	_snd_pcm_hw_param_any(params, var);
-	return snd_pcm_hw_refine(pcm, params);
-}
-#endif  /*  0  */
-
 void _snd_pcm_hw_params_any(struct snd_pcm_hw_params *params)
 {
 	unsigned int k;
@@ -1247,18 +1192,7 @@
 	params->info = ~0U;
 }
 
-#if 0
-/*
- * snd_pcm_hw_params_any
- *
- * Fill PARAMS with full configuration space boundaries
- */
-int snd_pcm_hw_params_any(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params)
-{
-	_snd_pcm_hw_params_any(params);
-	return snd_pcm_hw_refine(pcm, params);
-}
-#endif  /*  0  */
+EXPORT_SYMBOL(_snd_pcm_hw_params_any);
 
 /**
  * snd_pcm_hw_param_value
@@ -1269,8 +1203,8 @@
  * Return the value for field PAR if it's fixed in configuration space 
  *  defined by PARAMS. Return -EINVAL otherwise
  */
-static int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
-				  snd_pcm_hw_param_t var, int *dir)
+int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params,
+			   snd_pcm_hw_param_t var, int *dir)
 {
 	if (hw_is_mask(var)) {
 		const struct snd_mask *mask = hw_param_mask_c(params, var);
@@ -1288,61 +1222,10 @@
 			*dir = i->openmin;
 		return snd_interval_value(i);
 	}
-	assert(0);
 	return -EINVAL;
 }
 
-/**
- * snd_pcm_hw_param_value_min
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Return the minimum value for field PAR.
- */
-unsigned int snd_pcm_hw_param_value_min(const struct snd_pcm_hw_params *params,
-					snd_pcm_hw_param_t var, int *dir)
-{
-	if (hw_is_mask(var)) {
-		if (dir)
-			*dir = 0;
-		return snd_mask_min(hw_param_mask_c(params, var));
-	}
-	if (hw_is_interval(var)) {
-		const struct snd_interval *i = hw_param_interval_c(params, var);
-		if (dir)
-			*dir = i->openmin;
-		return snd_interval_min(i);
-	}
-	assert(0);
-	return -EINVAL;
-}
-
-/**
- * snd_pcm_hw_param_value_max
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Return the maximum value for field PAR.
- */
-unsigned int snd_pcm_hw_param_value_max(const struct snd_pcm_hw_params *params,
-					snd_pcm_hw_param_t var, int *dir)
-{
-	if (hw_is_mask(var)) {
-		if (dir)
-			*dir = 0;
-		return snd_mask_max(hw_param_mask_c(params, var));
-	}
-	if (hw_is_interval(var)) {
-		const struct snd_interval *i = hw_param_interval_c(params, var);
-		if (dir)
-			*dir = - (int) i->openmax;
-		return snd_interval_max(i);
-	}
-	assert(0);
-	return -EINVAL;
-}
+EXPORT_SYMBOL(snd_pcm_hw_param_value);
 
 void _snd_pcm_hw_param_setempty(struct snd_pcm_hw_params *params,
 				snd_pcm_hw_param_t var)
@@ -1360,42 +1243,7 @@
 	}
 }
 
-int _snd_pcm_hw_param_setinteger(struct snd_pcm_hw_params *params,
-				 snd_pcm_hw_param_t var)
-{
-	int changed;
-	assert(hw_is_interval(var));
-	changed = snd_interval_setinteger(hw_param_interval(params, var));
-	if (changed) {
-		params->cmask |= 1 << var;
-		params->rmask |= 1 << var;
-	}
-	return changed;
-}
-	
-#if 0
-/*
- * snd_pcm_hw_param_setinteger
- *
- * Inside configuration space defined by PARAMS remove from PAR all 
- * non integer values. Reduce configuration space accordingly.
- * Return -EINVAL if the configuration space is empty
- */
-int snd_pcm_hw_param_setinteger(struct snd_pcm_substream *pcm, 
-				struct snd_pcm_hw_params *params,
-				snd_pcm_hw_param_t var)
-{
-	int changed = _snd_pcm_hw_param_setinteger(params, var);
-	if (changed < 0)
-		return changed;
-	if (params->rmask) {
-		int err = snd_pcm_hw_refine(pcm, params);
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-#endif  /*  0  */
+EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
 
 static int _snd_pcm_hw_param_first(struct snd_pcm_hw_params *params,
 				   snd_pcm_hw_param_t var)
@@ -1405,10 +1253,8 @@
 		changed = snd_mask_refine_first(hw_param_mask(params, var));
 	else if (hw_is_interval(var))
 		changed = snd_interval_refine_first(hw_param_interval(params, var));
-	else {
-		assert(0);
+	else
 		return -EINVAL;
-	}
 	if (changed) {
 		params->cmask |= 1 << var;
 		params->rmask |= 1 << var;
@@ -1428,20 +1274,22 @@
  * values > minimum. Reduce configuration space accordingly.
  * Return the minimum.
  */
-static int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, 
-				  struct snd_pcm_hw_params *params, 
-				  snd_pcm_hw_param_t var, int *dir)
+int snd_pcm_hw_param_first(struct snd_pcm_substream *pcm, 
+			   struct snd_pcm_hw_params *params, 
+			   snd_pcm_hw_param_t var, int *dir)
 {
 	int changed = _snd_pcm_hw_param_first(params, var);
 	if (changed < 0)
 		return changed;
 	if (params->rmask) {
 		int err = snd_pcm_hw_refine(pcm, params);
-		assert(err >= 0);
+		snd_assert(err >= 0, return err);
 	}
 	return snd_pcm_hw_param_value(params, var, dir);
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_param_first);
+
 static int _snd_pcm_hw_param_last(struct snd_pcm_hw_params *params,
 				  snd_pcm_hw_param_t var)
 {
@@ -1450,10 +1298,8 @@
 		changed = snd_mask_refine_last(hw_param_mask(params, var));
 	else if (hw_is_interval(var))
 		changed = snd_interval_refine_last(hw_param_interval(params, var));
-	else {
-		assert(0);
+	else
 		return -EINVAL;
-	}
 	if (changed) {
 		params->cmask |= 1 << var;
 		params->rmask |= 1 << var;
@@ -1473,381 +1319,21 @@
  * values < maximum. Reduce configuration space accordingly.
  * Return the maximum.
  */
-static int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, 
-				 struct snd_pcm_hw_params *params,
-				 snd_pcm_hw_param_t var, int *dir)
+int snd_pcm_hw_param_last(struct snd_pcm_substream *pcm, 
+			  struct snd_pcm_hw_params *params,
+			  snd_pcm_hw_param_t var, int *dir)
 {
 	int changed = _snd_pcm_hw_param_last(params, var);
 	if (changed < 0)
 		return changed;
 	if (params->rmask) {
 		int err = snd_pcm_hw_refine(pcm, params);
-		assert(err >= 0);
+		snd_assert(err >= 0, return err);
 	}
 	return snd_pcm_hw_param_value(params, var, dir);
 }
 
-int _snd_pcm_hw_param_min(struct snd_pcm_hw_params *params,
-			  snd_pcm_hw_param_t var, unsigned int val, int dir)
-{
-	int changed;
-	int open = 0;
-	if (dir) {
-		if (dir > 0) {
-			open = 1;
-		} else if (dir < 0) {
-			if (val > 0) {
-				open = 1;
-				val--;
-			}
-		}
-	}
-	if (hw_is_mask(var))
-		changed = snd_mask_refine_min(hw_param_mask(params, var), val + !!open);
-	else if (hw_is_interval(var))
-		changed = snd_interval_refine_min(hw_param_interval(params, var), val, open);
-	else {
-		assert(0);
-		return -EINVAL;
-	}
-	if (changed) {
-		params->cmask |= 1 << var;
-		params->rmask |= 1 << var;
-	}
-	return changed;
-}
-
-/**
- * snd_pcm_hw_param_min
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @val: minimal value
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS remove from PAR all 
- * values < VAL. Reduce configuration space accordingly.
- * Return new minimum or -EINVAL if the configuration space is empty
- */
-static int snd_pcm_hw_param_min(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
-				snd_pcm_hw_param_t var, unsigned int val,
-				int *dir)
-{
-	int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
-	if (changed < 0)
-		return changed;
-	if (params->rmask) {
-		int err = snd_pcm_hw_refine(pcm, params);
-		if (err < 0)
-			return err;
-	}
-	return snd_pcm_hw_param_value_min(params, var, dir);
-}
-
-static int _snd_pcm_hw_param_max(struct snd_pcm_hw_params *params,
-				 snd_pcm_hw_param_t var, unsigned int val,
-				 int dir)
-{
-	int changed;
-	int open = 0;
-	if (dir) {
-		if (dir < 0) {
-			open = 1;
-		} else if (dir > 0) {
-			open = 1;
-			val++;
-		}
-	}
-	if (hw_is_mask(var)) {
-		if (val == 0 && open) {
-			snd_mask_none(hw_param_mask(params, var));
-			changed = -EINVAL;
-		} else
-			changed = snd_mask_refine_max(hw_param_mask(params, var), val - !!open);
-	} else if (hw_is_interval(var))
-		changed = snd_interval_refine_max(hw_param_interval(params, var), val, open);
-	else {
-		assert(0);
-		return -EINVAL;
-	}
-	if (changed) {
-		params->cmask |= 1 << var;
-		params->rmask |= 1 << var;
-	}
-	return changed;
-}
-
-/**
- * snd_pcm_hw_param_max
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @val: maximal value
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS remove from PAR all 
- *  values >= VAL + 1. Reduce configuration space accordingly.
- *  Return new maximum or -EINVAL if the configuration space is empty
- */
-static int snd_pcm_hw_param_max(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
-				snd_pcm_hw_param_t var, unsigned int val,
-				int *dir)
-{
-	int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
-	if (changed < 0)
-		return changed;
-	if (params->rmask) {
-		int err = snd_pcm_hw_refine(pcm, params);
-		if (err < 0)
-			return err;
-	}
-	return snd_pcm_hw_param_value_max(params, var, dir);
-}
-
-int _snd_pcm_hw_param_set(struct snd_pcm_hw_params *params,
-			  snd_pcm_hw_param_t var, unsigned int val, int dir)
-{
-	int changed;
-	if (hw_is_mask(var)) {
-		struct snd_mask *m = hw_param_mask(params, var);
-		if (val == 0 && dir < 0) {
-			changed = -EINVAL;
-			snd_mask_none(m);
-		} else {
-			if (dir > 0)
-				val++;
-			else if (dir < 0)
-				val--;
-			changed = snd_mask_refine_set(hw_param_mask(params, var), val);
-		}
-	} else if (hw_is_interval(var)) {
-		struct snd_interval *i = hw_param_interval(params, var);
-		if (val == 0 && dir < 0) {
-			changed = -EINVAL;
-			snd_interval_none(i);
-		} else if (dir == 0)
-			changed = snd_interval_refine_set(i, val);
-		else {
-			struct snd_interval t;
-			t.openmin = 1;
-			t.openmax = 1;
-			t.empty = 0;
-			t.integer = 0;
-			if (dir < 0) {
-				t.min = val - 1;
-				t.max = val;
-			} else {
-				t.min = val;
-				t.max = val+1;
-			}
-			changed = snd_interval_refine(i, &t);
-		}
-	} else {
-		assert(0);
-		return -EINVAL;
-	}
-	if (changed) {
-		params->cmask |= 1 << var;
-		params->rmask |= 1 << var;
-	}
-	return changed;
-}
-
-/**
- * snd_pcm_hw_param_set
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @val: value to set
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS remove from PAR all 
- * values != VAL. Reduce configuration space accordingly.
- *  Return VAL or -EINVAL if the configuration space is empty
- */
-int snd_pcm_hw_param_set(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
-			 snd_pcm_hw_param_t var, unsigned int val, int dir)
-{
-	int changed = _snd_pcm_hw_param_set(params, var, val, dir);
-	if (changed < 0)
-		return changed;
-	if (params->rmask) {
-		int err = snd_pcm_hw_refine(pcm, params);
-		if (err < 0)
-			return err;
-	}
-	return snd_pcm_hw_param_value(params, var, NULL);
-}
-
-static int _snd_pcm_hw_param_mask(struct snd_pcm_hw_params *params,
-				  snd_pcm_hw_param_t var, const struct snd_mask *val)
-{
-	int changed;
-	assert(hw_is_mask(var));
-	changed = snd_mask_refine(hw_param_mask(params, var), val);
-	if (changed) {
-		params->cmask |= 1 << var;
-		params->rmask |= 1 << var;
-	}
-	return changed;
-}
-
-/**
- * snd_pcm_hw_param_mask
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @val: mask to apply
- *
- * Inside configuration space defined by PARAMS remove from PAR all values
- * not contained in MASK. Reduce configuration space accordingly.
- * This function can be called only for SNDRV_PCM_HW_PARAM_ACCESS,
- * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
- * Return 0 on success or -EINVAL
- * if the configuration space is empty
- */
-int snd_pcm_hw_param_mask(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
-			  snd_pcm_hw_param_t var, const struct snd_mask *val)
-{
-	int changed = _snd_pcm_hw_param_mask(params, var, val);
-	if (changed < 0)
-		return changed;
-	if (params->rmask) {
-		int err = snd_pcm_hw_refine(pcm, params);
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
-static int boundary_sub(int a, int adir,
-			int b, int bdir,
-			int *c, int *cdir)
-{
-	adir = adir < 0 ? -1 : (adir > 0 ? 1 : 0);
-	bdir = bdir < 0 ? -1 : (bdir > 0 ? 1 : 0);
-	*c = a - b;
-	*cdir = adir - bdir;
-	if (*cdir == -2) {
-		assert(*c > INT_MIN);
-		(*c)--;
-	} else if (*cdir == 2) {
-		assert(*c < INT_MAX);
-		(*c)++;
-	}
-	return 0;
-}
-
-static int boundary_lt(unsigned int a, int adir,
-		       unsigned int b, int bdir)
-{
-	assert(a > 0 || adir >= 0);
-	assert(b > 0 || bdir >= 0);
-	if (adir < 0) {
-		a--;
-		adir = 1;
-	} else if (adir > 0)
-		adir = 1;
-	if (bdir < 0) {
-		b--;
-		bdir = 1;
-	} else if (bdir > 0)
-		bdir = 1;
-	return a < b || (a == b && adir < bdir);
-}
-
-/* Return 1 if min is nearer to best than max */
-static int boundary_nearer(int min, int mindir,
-			   int best, int bestdir,
-			   int max, int maxdir)
-{
-	int dmin, dmindir;
-	int dmax, dmaxdir;
-	boundary_sub(best, bestdir, min, mindir, &dmin, &dmindir);
-	boundary_sub(max, maxdir, best, bestdir, &dmax, &dmaxdir);
-	return boundary_lt(dmin, dmindir, dmax, dmaxdir);
-}
-
-/**
- * snd_pcm_hw_param_near
- * @pcm: PCM instance
- * @params: the hw_params instance
- * @var: parameter to retrieve
- * @best: value to set
- * @dir: pointer to the direction (-1,0,1) or NULL
- *
- * Inside configuration space defined by PARAMS set PAR to the available value
- * nearest to VAL. Reduce configuration space accordingly.
- * This function cannot be called for SNDRV_PCM_HW_PARAM_ACCESS,
- * SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_SUBFORMAT.
- * Return the value found.
-  */
-int snd_pcm_hw_param_near(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params,
-			  snd_pcm_hw_param_t var, unsigned int best, int *dir)
-{
-	struct snd_pcm_hw_params *save = NULL;
-	int v;
-	unsigned int saved_min;
-	int last = 0;
-	int min, max;
-	int mindir, maxdir;
-	int valdir = dir ? *dir : 0;
-	/* FIXME */
-	if (best > INT_MAX)
-		best = INT_MAX;
-	min = max = best;
-	mindir = maxdir = valdir;
-	if (maxdir > 0)
-		maxdir = 0;
-	else if (maxdir == 0)
-		maxdir = -1;
-	else {
-		maxdir = 1;
-		max--;
-	}
-	save = kmalloc(sizeof(*save), GFP_KERNEL);
-	if (save == NULL)
-		return -ENOMEM;
-	*save = *params;
-	saved_min = min;
-	min = snd_pcm_hw_param_min(pcm, params, var, min, &mindir);
-	if (min >= 0) {
-		struct snd_pcm_hw_params *params1;
-		if (max < 0)
-			goto _end;
-		if ((unsigned int)min == saved_min && mindir == valdir)
-			goto _end;
-		params1 = kmalloc(sizeof(*params1), GFP_KERNEL);
-		if (params1 == NULL) {
-			kfree(save);
-			return -ENOMEM;
-		}
-		*params1 = *save;
-		max = snd_pcm_hw_param_max(pcm, params1, var, max, &maxdir);
-		if (max < 0) {
-			kfree(params1);
-			goto _end;
-		}
-		if (boundary_nearer(max, maxdir, best, valdir, min, mindir)) {
-			*params = *params1;
-			last = 1;
-		}
-		kfree(params1);
-	} else {
-		*params = *save;
-		max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);
-		assert(max >= 0);
-		last = 1;
-	}
- _end:
- 	kfree(save);
-	if (last)
-		v = snd_pcm_hw_param_last(pcm, params, var, dir);
-	else
-		v = snd_pcm_hw_param_first(pcm, params, var, dir);
-	assert(v >= 0);
-	return v;
-}
+EXPORT_SYMBOL(snd_pcm_hw_param_last);
 
 /**
  * snd_pcm_hw_param_choose
@@ -1859,39 +1345,32 @@
  * first access, first format, first subformat, min channels,
  * min rate, min period time, max buffer size, min tick time
  */
-int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm, struct snd_pcm_hw_params *params)
+int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
+			     struct snd_pcm_hw_params *params)
 {
-	int err;
+	static int vars[] = {
+		SNDRV_PCM_HW_PARAM_ACCESS,
+		SNDRV_PCM_HW_PARAM_FORMAT,
+		SNDRV_PCM_HW_PARAM_SUBFORMAT,
+		SNDRV_PCM_HW_PARAM_CHANNELS,
+		SNDRV_PCM_HW_PARAM_RATE,
+		SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+		SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+		SNDRV_PCM_HW_PARAM_TICK_TIME,
+		-1
+	};
+	int err, *v;
 
-	err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_ACCESS, NULL);
-	assert(err >= 0);
-
-	err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_FORMAT, NULL);
-	assert(err >= 0);
-
-	err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_SUBFORMAT, NULL);
-	assert(err >= 0);
-
-	err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_CHANNELS, NULL);
-	assert(err >= 0);
-
-	err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_RATE, NULL);
-	assert(err >= 0);
-
-	err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_PERIOD_TIME, NULL);
-	assert(err >= 0);
-
-	err = snd_pcm_hw_param_last(pcm, params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL);
-	assert(err >= 0);
-
-	err = snd_pcm_hw_param_first(pcm, params, SNDRV_PCM_HW_PARAM_TICK_TIME, NULL);
-	assert(err >= 0);
-
+	for (v = vars; *v != -1; v++) {
+		if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
+			err = snd_pcm_hw_param_first(pcm, params, *v, NULL);
+		else
+			err = snd_pcm_hw_param_last(pcm, params, *v, NULL);
+		snd_assert(err >= 0, return err);
+	}
 	return 0;
 }
 
-#undef assert
-
 static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
 				   void *arg)
 {
@@ -1967,6 +1446,8 @@
 	return -ENXIO;
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_ioctl);
+
 /*
  *  Conditions
  */
@@ -2101,6 +1582,8 @@
 	kill_fasync(&runtime->fasync, SIGIO, POLL_IN);
 }
 
+EXPORT_SYMBOL(snd_pcm_period_elapsed);
+
 static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
 				      unsigned int hwoff,
 				      unsigned long data, unsigned int off,
@@ -2299,7 +1782,7 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
+	nonblock = !!(substream->f_flags & O_NONBLOCK);
 
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
 	    runtime->channels > 1)
@@ -2308,6 +1791,8 @@
 				  snd_pcm_lib_write_transfer);
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_write);
+
 static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
 				       unsigned int hwoff,
 				       unsigned long data, unsigned int off,
@@ -2362,7 +1847,7 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
+	nonblock = !!(substream->f_flags & O_NONBLOCK);
 
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
@@ -2370,6 +1855,8 @@
 				  nonblock, snd_pcm_lib_writev_transfer);
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_writev);
+
 static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream, 
 				     unsigned int hwoff,
 				     unsigned long data, unsigned int off,
@@ -2572,12 +2059,14 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
+	nonblock = !!(substream->f_flags & O_NONBLOCK);
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
 		return -EINVAL;
 	return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_read);
+
 static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
 				      unsigned int hwoff,
 				      unsigned long data, unsigned int off,
@@ -2629,58 +2118,10 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	nonblock = !!(substream->ffile->f_flags & O_NONBLOCK);
+	nonblock = !!(substream->f_flags & O_NONBLOCK);
 	if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
 		return -EINVAL;
 	return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
 }
 
-/*
- *  Exported symbols
- */
-
-EXPORT_SYMBOL(snd_interval_refine);
-EXPORT_SYMBOL(snd_interval_list);
-EXPORT_SYMBOL(snd_interval_ratnum);
-EXPORT_SYMBOL(_snd_pcm_hw_params_any);
-EXPORT_SYMBOL(_snd_pcm_hw_param_min);
-EXPORT_SYMBOL(_snd_pcm_hw_param_set);
-EXPORT_SYMBOL(_snd_pcm_hw_param_setempty);
-EXPORT_SYMBOL(_snd_pcm_hw_param_setinteger);
-EXPORT_SYMBOL(snd_pcm_hw_param_value_min);
-EXPORT_SYMBOL(snd_pcm_hw_param_value_max);
-EXPORT_SYMBOL(snd_pcm_hw_param_mask);
-EXPORT_SYMBOL(snd_pcm_hw_param_first);
-EXPORT_SYMBOL(snd_pcm_hw_param_last);
-EXPORT_SYMBOL(snd_pcm_hw_param_near);
-EXPORT_SYMBOL(snd_pcm_hw_param_set);
-EXPORT_SYMBOL(snd_pcm_hw_refine);
-EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
-EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_ratnums);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_ratdens);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_msbits);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_minmax);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_integer);
-EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
-EXPORT_SYMBOL(snd_pcm_hw_rule_add);
-EXPORT_SYMBOL(snd_pcm_set_ops);
-EXPORT_SYMBOL(snd_pcm_set_sync);
-EXPORT_SYMBOL(snd_pcm_lib_ioctl);
-EXPORT_SYMBOL(snd_pcm_stop);
-EXPORT_SYMBOL(snd_pcm_period_elapsed);
-EXPORT_SYMBOL(snd_pcm_lib_write);
-EXPORT_SYMBOL(snd_pcm_lib_read);
-EXPORT_SYMBOL(snd_pcm_lib_writev);
 EXPORT_SYMBOL(snd_pcm_lib_readv);
-EXPORT_SYMBOL(snd_pcm_lib_buffer_bytes);
-EXPORT_SYMBOL(snd_pcm_lib_period_bytes);
-/* pcm_memory.c */
-EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
-EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
-EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
-EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
-EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
-EXPORT_SYMBOL(snd_pcm_lib_free_pages);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 428f8c1..067d205 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -126,6 +126,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
+
 #ifdef CONFIG_SND_VERBOSE_PROCFS
 /*
  * read callback for prealloc proc file
@@ -191,9 +193,7 @@
 	struct snd_info_entry *entry;
 
 	if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc", substream->proc_root)) != NULL) {
-		entry->c.text.read_size = 64;
 		entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
-		entry->c.text.write_size = 64;
 		entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
 		entry->mode |= S_IWUSR;
 		entry->private_data = substream;
@@ -253,6 +253,8 @@
 	return snd_pcm_lib_preallocate_pages1(substream, size, max);
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages);
+
 /**
  * snd_pcm_lib_preallocate_pages_for_all - pre-allocation for continous memory type (all substreams)
  * @pcm: the pcm instance
@@ -280,6 +282,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all);
+
 /**
  * snd_pcm_sgbuf_ops_page - get the page struct at the given offset
  * @substream: the pcm substream instance
@@ -298,6 +302,8 @@
 	return sgbuf->page_table[idx];
 }
 
+EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page);
+
 /**
  * snd_pcm_lib_malloc_pages - allocate the DMA buffer
  * @substream: the substream to allocate the DMA buffer to
@@ -349,6 +355,8 @@
 	return 1;			/* area was changed */
 }
 
+EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
+
 /**
  * snd_pcm_lib_free_pages - release the allocated DMA buffer.
  * @substream: the substream to release the DMA buffer
@@ -374,3 +382,5 @@
 	snd_pcm_set_runtime_buffer(substream, NULL);
 	return 0;
 }
+
+EXPORT_SYMBOL(snd_pcm_lib_free_pages);
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 593c77f..0019c59 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -207,6 +207,8 @@
 	return val;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_signed);
+
 /**
  * snd_pcm_format_unsigned - Check the PCM format is unsigned linear
  * @format: the format to check
@@ -224,6 +226,8 @@
 	return !val;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_unsigned);
+
 /**
  * snd_pcm_format_linear - Check the PCM format is linear
  * @format: the format to check
@@ -235,6 +239,8 @@
 	return snd_pcm_format_signed(format) >= 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_linear);
+
 /**
  * snd_pcm_format_little_endian - Check the PCM format is little-endian
  * @format: the format to check
@@ -252,6 +258,8 @@
 	return val;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_little_endian);
+
 /**
  * snd_pcm_format_big_endian - Check the PCM format is big-endian
  * @format: the format to check
@@ -269,6 +277,8 @@
 	return !val;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_big_endian);
+
 /**
  * snd_pcm_format_width - return the bit-width of the format
  * @format: the format to check
@@ -286,6 +296,8 @@
 	return val;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_width);
+
 /**
  * snd_pcm_format_physical_width - return the physical bit-width of the format
  * @format: the format to check
@@ -303,6 +315,8 @@
 	return val;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_physical_width);
+
 /**
  * snd_pcm_format_size - return the byte size of samples on the given format
  * @format: the format to check
@@ -318,6 +332,8 @@
 	return samples * phys_width / 8;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_size);
+
 /**
  * snd_pcm_format_silence_64 - return the silent data in 8 bytes array
  * @format: the format to check
@@ -333,6 +349,8 @@
 	return pcm_formats[format].silence;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_silence_64);
+
 /**
  * snd_pcm_format_set_silence - set the silence data on the buffer
  * @format: the PCM format
@@ -402,6 +420,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_format_set_silence);
+
 /* [width][unsigned][bigendian] */
 static int linear_formats[4][2][2] = {
 	{{ SNDRV_PCM_FORMAT_S8, SNDRV_PCM_FORMAT_S8},
@@ -432,6 +452,8 @@
 	return linear_formats[width][!!unsignd][!!big_endian];
 }
 
+EXPORT_SYMBOL(snd_pcm_build_linear_format);
+
 /**
  * snd_pcm_limit_hw_rates - determine rate_min/rate_max fields
  * @runtime: the runtime instance
@@ -463,3 +485,5 @@
 	}
 	return 0;
 }
+
+EXPORT_SYMBOL(snd_pcm_limit_hw_rates);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 0860c5a..439f047 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -71,8 +71,9 @@
  */
 
 DEFINE_RWLOCK(snd_pcm_link_rwlock);
-static DECLARE_RWSEM(snd_pcm_link_rwsem);
+EXPORT_SYMBOL(snd_pcm_link_rwlock);
 
+static DECLARE_RWSEM(snd_pcm_link_rwsem);
 
 static inline mm_segment_t snd_enter_user(void)
 {
@@ -319,6 +320,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_hw_refine);
+
 static int snd_pcm_hw_refine_user(struct snd_pcm_substream *substream,
 				  struct snd_pcm_hw_params __user * _params)
 {
@@ -369,7 +372,7 @@
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	if (!substream->oss.oss)
 #endif
-		if (atomic_read(&runtime->mmap_count))
+		if (atomic_read(&substream->mmap_count))
 			return -EBADFD;
 
 	params->rmask = ~0U;
@@ -482,7 +485,7 @@
 		return -EBADFD;
 	}
 	snd_pcm_stream_unlock_irq(substream);
-	if (atomic_read(&runtime->mmap_count))
+	if (atomic_read(&substream->mmap_count))
 		return -EBADFD;
 	if (substream->ops->hw_free)
 		result = substream->ops->hw_free(substream);
@@ -936,6 +939,8 @@
 	return snd_pcm_action(&snd_pcm_action_stop, substream, state);
 }
 
+EXPORT_SYMBOL(snd_pcm_stop);
+
 /**
  * snd_pcm_drain_done
  * @substream: the PCM substream
@@ -1085,6 +1090,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(snd_pcm_suspend);
+
 /**
  * snd_pcm_suspend_all
  * @pcm: the PCM instance
@@ -1114,6 +1121,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_pcm_suspend_all);
+
 /* resume */
 
 static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
@@ -1275,13 +1284,16 @@
 /*
  * prepare ioctl
  */
-static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, int state)
+/* we use the second argument for updating f_flags */
+static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
+			       int f_flags)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 	if (snd_pcm_running(substream))
 		return -EBUSY;
+	substream->f_flags = f_flags;
 	return 0;
 }
 
@@ -1310,17 +1322,26 @@
 /**
  * snd_pcm_prepare
  * @substream: the PCM substream instance
+ * @file: file to refer f_flags
  *
  * Prepare the PCM substream to be triggerable.
  */
-static int snd_pcm_prepare(struct snd_pcm_substream *substream)
+static int snd_pcm_prepare(struct snd_pcm_substream *substream,
+			   struct file *file)
 {
 	int res;
 	struct snd_card *card = substream->pcm->card;
+	int f_flags;
+
+	if (file)
+		f_flags = file->f_flags;
+	else
+		f_flags = substream->f_flags;
 
 	snd_power_lock(card);
 	if ((res = snd_power_wait(card, SNDRV_CTL_POWER_D0)) >= 0)
-		res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare, substream, 0);
+		res = snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
+					       substream, f_flags);
 	snd_power_unlock(card);
 	return res;
 }
@@ -1331,7 +1352,7 @@
 
 static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
 {
-	if (substream->ffile->f_flags & O_NONBLOCK)
+	if (substream->f_flags & O_NONBLOCK)
 		return -EAGAIN;
 	substream->runtime->trigger_master = substream;
 	return 0;
@@ -1448,8 +1469,6 @@
 		}
 	}
 	up_read(&snd_pcm_link_rwsem);
-	if (! num_drecs)
-		goto _error;
 
 	snd_pcm_stream_lock_irq(substream);
 	/* resume pause */
@@ -2006,6 +2025,10 @@
 
 void snd_pcm_release_substream(struct snd_pcm_substream *substream)
 {
+	substream->ref_count--;
+	if (substream->ref_count > 0)
+		return;
+
 	snd_pcm_drop(substream);
 	if (substream->hw_opened) {
 		if (substream->ops->hw_free != NULL)
@@ -2020,6 +2043,8 @@
 	snd_pcm_detach_substream(substream);
 }
 
+EXPORT_SYMBOL(snd_pcm_release_substream);
+
 int snd_pcm_open_substream(struct snd_pcm *pcm, int stream,
 			   struct file *file,
 			   struct snd_pcm_substream **rsubstream)
@@ -2030,6 +2055,11 @@
 	err = snd_pcm_attach_substream(pcm, stream, file, &substream);
 	if (err < 0)
 		return err;
+	if (substream->ref_count > 1) {
+		*rsubstream = substream;
+		return 0;
+	}
+
 	substream->no_mmap_ctrl = 0;
 	err = snd_pcm_hw_constraints_init(substream);
 	if (err < 0) {
@@ -2056,6 +2086,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(snd_pcm_open_substream);
+
 static int snd_pcm_open_file(struct file *file,
 			     struct snd_pcm *pcm,
 			     int stream,
@@ -2073,17 +2105,20 @@
 	if (err < 0)
 		return err;
 
-	pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
-	if (pcm_file == NULL) {
-		snd_pcm_release_substream(substream);
-		return -ENOMEM;
+	if (substream->ref_count > 1)
+		pcm_file = substream->file;
+	else {
+		pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL);
+		if (pcm_file == NULL) {
+			snd_pcm_release_substream(substream);
+			return -ENOMEM;
+		}
+		str = substream->pstr;
+		substream->file = pcm_file;
+		substream->pcm_release = pcm_release_private;
+		pcm_file->substream = substream;
+		snd_pcm_add_file(str, pcm_file);
 	}
-	str = substream->pstr;
-	substream->file = pcm_file;
-	substream->pcm_release = pcm_release_private;
-	pcm_file->substream = substream;
-	snd_pcm_add_file(str, pcm_file);
-
 	file->private_data = pcm_file;
 	*rpcm_file = pcm_file;
 	return 0;
@@ -2170,7 +2205,6 @@
 	pcm_file = file->private_data;
 	substream = pcm_file->substream;
 	snd_assert(substream != NULL, return -ENXIO);
-	snd_assert(!atomic_read(&substream->runtime->mmap_count), );
 	pcm = substream->pcm;
 	fasync_helper(-1, file, 0, &substream->runtime->fasync);
 	mutex_lock(&pcm->open_mutex);
@@ -2493,7 +2527,8 @@
 	return 0;
 }
 		
-static int snd_pcm_common_ioctl1(struct snd_pcm_substream *substream,
+static int snd_pcm_common_ioctl1(struct file *file,
+				 struct snd_pcm_substream *substream,
 				 unsigned int cmd, void __user *arg)
 {
 	snd_assert(substream != NULL, return -ENXIO);
@@ -2518,7 +2553,7 @@
 	case SNDRV_PCM_IOCTL_CHANNEL_INFO:
 		return snd_pcm_channel_info_user(substream, arg);
 	case SNDRV_PCM_IOCTL_PREPARE:
-		return snd_pcm_prepare(substream);
+		return snd_pcm_prepare(substream, file);
 	case SNDRV_PCM_IOCTL_RESET:
 		return snd_pcm_reset(substream);
 	case SNDRV_PCM_IOCTL_START:
@@ -2560,7 +2595,8 @@
 	return -ENOTTY;
 }
 
-static int snd_pcm_playback_ioctl1(struct snd_pcm_substream *substream,
+static int snd_pcm_playback_ioctl1(struct file *file,
+				   struct snd_pcm_substream *substream,
 				   unsigned int cmd, void __user *arg)
 {
 	snd_assert(substream != NULL, return -ENXIO);
@@ -2636,10 +2672,11 @@
 		return result < 0 ? result : 0;
 	}
 	}
-	return snd_pcm_common_ioctl1(substream, cmd, arg);
+	return snd_pcm_common_ioctl1(file, substream, cmd, arg);
 }
 
-static int snd_pcm_capture_ioctl1(struct snd_pcm_substream *substream,
+static int snd_pcm_capture_ioctl1(struct file *file,
+				  struct snd_pcm_substream *substream,
 				  unsigned int cmd, void __user *arg)
 {
 	snd_assert(substream != NULL, return -ENXIO);
@@ -2715,7 +2752,7 @@
 		return result < 0 ? result : 0;
 	}
 	}
-	return snd_pcm_common_ioctl1(substream, cmd, arg);
+	return snd_pcm_common_ioctl1(file, substream, cmd, arg);
 }
 
 static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd,
@@ -2728,7 +2765,8 @@
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	return snd_pcm_playback_ioctl1(file, pcm_file->substream, cmd,
+				       (void __user *)arg);
 }
 
 static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
@@ -2741,7 +2779,8 @@
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
+	return snd_pcm_capture_ioctl1(file, pcm_file->substream, cmd,
+				      (void __user *)arg);
 }
 
 int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
@@ -2753,12 +2792,12 @@
 	fs = snd_enter_user();
 	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_PLAYBACK:
-		result = snd_pcm_playback_ioctl1(substream,
-						 cmd, (void __user *)arg);
+		result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
+						 (void __user *)arg);
 		break;
 	case SNDRV_PCM_STREAM_CAPTURE:
-		result = snd_pcm_capture_ioctl1(substream,
-						cmd, (void __user *)arg);
+		result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
+						(void __user *)arg);
 		break;
 	default:
 		result = -EINVAL;
@@ -2768,6 +2807,8 @@
 	return result;
 }
 
+EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
+
 static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
 			    loff_t * offset)
 {
@@ -3134,7 +3175,7 @@
 	area->vm_ops = &snd_pcm_vm_ops_data;
 	area->vm_private_data = substream;
 	area->vm_flags |= VM_RESERVED;
-	atomic_inc(&substream->runtime->mmap_count);
+	atomic_inc(&substream->mmap_count);
 	return 0;
 }
 
@@ -3166,9 +3207,11 @@
 				(substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
 				size, area->vm_page_prot))
 		return -EAGAIN;
-	atomic_inc(&substream->runtime->mmap_count);
+	atomic_inc(&substream->mmap_count);
 	return 0;
 }
+
+EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
 #endif /* SNDRV_PCM_INFO_MMAP */
 
 /*
@@ -3212,6 +3255,8 @@
 		return snd_pcm_default_mmap(substream, area);
 }
 
+EXPORT_SYMBOL(snd_pcm_mmap_data);
+
 static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
 {
 	struct snd_pcm_file * pcm_file;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 87b47c9..8c15c66 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -43,7 +43,7 @@
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_SND_OSSEMUL
-static int midi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 0};
+static int midi_map[SNDRV_CARDS];
 static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
 module_param_array(midi_map, int, NULL, 0444);
 MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device.");
@@ -1561,7 +1561,6 @@
 	entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);
 	if (entry) {
 		entry->private_data = rmidi;
-		entry->c.text.read_size = 1024;
 		entry->c.text.read = snd_rawmidi_proc_info_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index b991978..e723413 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -291,7 +291,6 @@
 
 	entry->content = SNDRV_INFO_CONTENT_TEXT;
 	entry->private_data = NULL;
-	entry->c.text.read_size = 1024;
 	entry->c.text.read = info_read;
 	if (snd_info_register(entry) < 0) {
 		snd_info_free_entry(entry);
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 20f954b..2f0d877 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -129,25 +129,3 @@
 
 module_init(alsa_seq_init)
 module_exit(alsa_seq_exit)
-
-  /* seq_clientmgr.c */
-EXPORT_SYMBOL(snd_seq_create_kernel_client);
-EXPORT_SYMBOL(snd_seq_delete_kernel_client);
-EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
-EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
-EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
-EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
-EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
-EXPORT_SYMBOL(snd_seq_set_queue_tempo);
-  /* seq_memory.c */
-EXPORT_SYMBOL(snd_seq_expand_var_event);
-EXPORT_SYMBOL(snd_seq_dump_var_event);
-  /* seq_ports.c */
-EXPORT_SYMBOL(snd_seq_event_port_attach);
-EXPORT_SYMBOL(snd_seq_event_port_detach);
-  /* seq_lock.c */
-#if defined(CONFIG_SMP) || defined(CONFIG_SND_DEBUG)
-/*EXPORT_SYMBOL(snd_seq_sleep_in_lock);*/
-/*EXPORT_SYMBOL(snd_seq_sleep_timeout_in_lock);*/
-EXPORT_SYMBOL(snd_use_lock_sync_helper);
-#endif
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index bb15d9e..532a660 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1714,6 +1714,8 @@
 	return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
 }
 
+EXPORT_SYMBOL(snd_seq_set_queue_tempo);
+
 static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
 					 void __user *arg)
 {
@@ -2264,6 +2266,8 @@
 	return client->number;
 }
 
+EXPORT_SYMBOL(snd_seq_create_kernel_client);
+
 /* exported to kernel modules */
 int snd_seq_delete_kernel_client(int client)
 {
@@ -2280,6 +2284,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_seq_delete_kernel_client);
 
 /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue
  * and snd_seq_kernel_client_enqueue_blocking
@@ -2328,6 +2333,8 @@
 	return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop);
 }
 
+EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);
+
 /*
  * exported, called by kernel clients to enqueue events (with blocking)
  *
@@ -2340,6 +2347,7 @@
 	return kernel_client_enqueue(client, ev, file, 1, atomic, hop);
 }
 
+EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking);
 
 /* 
  * exported, called by kernel clients to dispatch events directly to other
@@ -2376,6 +2384,7 @@
 	return result;
 }
 
+EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);
 
 /*
  * exported, called by kernel clients to perform same functions as with
@@ -2396,6 +2405,7 @@
 	return result;
 }
 
+EXPORT_SYMBOL(snd_seq_kernel_client_ctl);
 
 /* exported (for OSS emulator) */
 int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait)
@@ -2413,6 +2423,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);
+
 /*---------------------------------------------------------------------------*/
 
 #ifdef CONFIG_PROC_FS
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index d9a3e5a..d812dc8 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -80,7 +80,7 @@
 static int num_ops;
 static DEFINE_MUTEX(ops_mutex);
 #ifdef CONFIG_PROC_FS
-static struct snd_info_entry *info_entry = NULL;
+static struct snd_info_entry *info_entry;
 #endif
 
 /*
@@ -555,7 +555,6 @@
 	if (info_entry == NULL)
 		return -ENOMEM;
 	info_entry->content = SNDRV_INFO_CONTENT_TEXT;
-	info_entry->c.text.read_size = 2048;
 	info_entry->c.text.read = snd_seq_device_info;
 	if (snd_info_register(info_entry) < 0) {
 		snd_info_free_entry(info_entry);
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index 2a283a5..e55488d 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -66,7 +66,7 @@
 MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY));
 
 static int ports = 1;
-static int duplex = 0;
+static int duplex;
 
 module_param(ports, int, 0444);
 MODULE_PARM_DESC(ports, "number of ports to be created");
@@ -171,7 +171,9 @@
 	pinfo.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
 	if (duplex)
 		pinfo.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
-	pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
+	pinfo.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
+		| SNDRV_SEQ_PORT_TYPE_SOFTWARE
+		| SNDRV_SEQ_PORT_TYPE_PORT;
 	memset(&pcb, 0, sizeof(pcb));
 	pcb.owner = THIS_MODULE;
 	pcb.unuse = dummy_unuse;
diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c
index acce21a..142e9e6 100644
--- a/sound/core/seq/seq_info.c
+++ b/sound/core/seq/seq_info.c
@@ -34,8 +34,8 @@
 
 
 static struct snd_info_entry * __init
-create_info_entry(char *name, int size, void (*read)(struct snd_info_entry *,
-						     struct snd_info_buffer *))
+create_info_entry(char *name, void (*read)(struct snd_info_entry *,
+					   struct snd_info_buffer *))
 {
 	struct snd_info_entry *entry;
 
@@ -43,7 +43,6 @@
 	if (entry == NULL)
 		return NULL;
 	entry->content = SNDRV_INFO_CONTENT_TEXT;
-	entry->c.text.read_size = size;
 	entry->c.text.read = read;
 	if (snd_info_register(entry) < 0) {
 		snd_info_free_entry(entry);
@@ -55,11 +54,11 @@
 /* create all our /proc entries */
 int __init snd_seq_info_init(void)
 {
-	queues_entry = create_info_entry("queues", 512 + (256 * SNDRV_SEQ_MAX_QUEUES),
+	queues_entry = create_info_entry("queues",
 					 snd_seq_info_queues_read);
-	clients_entry = create_info_entry("clients", 512 + (256 * SNDRV_SEQ_MAX_CLIENTS),
+	clients_entry = create_info_entry("clients",
 					  snd_seq_info_clients_read);
-	timer_entry = create_info_entry("timer", 1024, snd_seq_info_timer_read);
+	timer_entry = create_info_entry("timer", snd_seq_info_timer_read);
 	return 0;
 }
 
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index a837a94..1a34941 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -44,4 +44,6 @@
 	}
 }
 
+EXPORT_SYMBOL(snd_use_lock_sync_helper);
+
 #endif
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 40b4f67..4bffe50 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -118,6 +118,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_seq_dump_var_event);
+
 
 /*
  * exported:
@@ -167,6 +169,7 @@
 	return err < 0 ? err : newlen;
 }
 
+EXPORT_SYMBOL(snd_seq_expand_var_event);
 
 /*
  * release this cell, free extended data if available
diff --git a/sound/core/seq/seq_memory.h b/sound/core/seq/seq_memory.h
index 39c60d9..63e9143 100644
--- a/sound/core/seq/seq_memory.h
+++ b/sound/core/seq/seq_memory.h
@@ -31,7 +31,7 @@
 	struct snd_seq_event_cell *next;	/* next cell */
 };
 
-/* design note: the pool is a contigious block of memory, if we dynamicly
+/* design note: the pool is a contiguous block of memory, if we dynamicly
    want to add additional cells to the pool be better store this in another
    pool as we need to know the base address of the pool when releasing
    memory. */
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 9caa137..1daa5b0 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -278,6 +278,7 @@
 	struct seq_midisynth *msynth, *ms;
 	struct snd_seq_port_info *port;
 	struct snd_rawmidi_info *info;
+	struct snd_rawmidi *rmidi = dev->private_data;
 	int newclient = 0;
 	unsigned int p, ports;
 	struct snd_seq_port_callback pcallbacks;
@@ -320,8 +321,8 @@
 		}
 		client->seq_client =
 			snd_seq_create_kernel_client(
-				card, 0, "%s", info->name[0] ?
-				(const char *)info->name : "External MIDI");
+				card, 0, "%s", card->shortname[0] ?
+				(const char *)card->shortname : "External MIDI");
 		if (client->seq_client < 0) {
 			kfree(client);
 			mutex_unlock(&register_mutex);
@@ -376,7 +377,9 @@
 		if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
 		    info->flags & SNDRV_RAWMIDI_INFO_DUPLEX)
 			port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
-		port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
+		port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
+			| SNDRV_SEQ_PORT_TYPE_HARDWARE
+			| SNDRV_SEQ_PORT_TYPE_PORT;
 		port->midi_channels = 16;
 		memset(&pcallbacks, 0, sizeof(pcallbacks));
 		pcallbacks.owner = THIS_MODULE;
@@ -387,6 +390,8 @@
 		pcallbacks.unuse = midisynth_unuse;
 		pcallbacks.event_input = event_process_midi;
 		port->kernel = &pcallbacks;
+		if (rmidi->ops && rmidi->ops->get_port_info)
+			rmidi->ops->get_port_info(rmidi, p, port);
 		if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0)
 			goto __nomem;
 		ms->seq_client = client->seq_client;
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 41e078c..334579a9 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -221,7 +221,6 @@
 {
 	struct list_head *p, *n;
 
-	down_write(&grp->list_mutex);
 	list_for_each_safe(p, n, &grp->list_head) {
 		struct snd_seq_subscribers *subs;
 		struct snd_seq_client *c;
@@ -259,7 +258,6 @@
 			snd_seq_client_unlock(c);
 		}
 	}
-	up_write(&grp->list_mutex);
 }
 
 /* delete port data */
@@ -677,6 +675,7 @@
 	return ret;
 }
 
+EXPORT_SYMBOL(snd_seq_event_port_attach);
 
 /*
  * Detach the driver from a port.
@@ -696,3 +695,5 @@
 
 	return err;
 }
+
+EXPORT_SYMBOL(snd_seq_event_port_detach);
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index f4edec6..0cfa06c 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -390,7 +390,9 @@
 	pinfo->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
 	pinfo->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
 	pinfo->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
-	pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
+	pinfo->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC
+		| SNDRV_SEQ_PORT_TYPE_SOFTWARE
+		| SNDRV_SEQ_PORT_TYPE_PORT;
 	pinfo->midi_channels = 16;
 	memset(&pcallbacks, 0, sizeof(pcallbacks));
 	pcallbacks.owner = THIS_MODULE;
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 108e430..cd86272 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -39,6 +39,8 @@
 
 static int major = CONFIG_SND_MAJOR;
 int snd_major;
+EXPORT_SYMBOL(snd_major);
+
 static int cards_limit = 1;
 static int device_mode = S_IFCHR | S_IRUGO | S_IWUGO;
 
@@ -60,6 +62,7 @@
  * modules are loaded manually, this limit number increases, too.
  */
 int snd_ecards_limit;
+EXPORT_SYMBOL(snd_ecards_limit);
 
 static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
 static DEFINE_MUTEX(sound_mutex);
@@ -78,20 +81,17 @@
  */
 void snd_request_card(int card)
 {
-	int locked;
-
 	if (! current->fs->root)
 		return;
-	read_lock(&snd_card_rwlock);
-	locked = snd_cards_lock & (1 << card);
-	read_unlock(&snd_card_rwlock);
-	if (locked)
+	if (snd_card_locked(card))
 		return;
 	if (card < 0 || card >= cards_limit)
 		return;
 	request_module("snd-card-%i", card);
 }
 
+EXPORT_SYMBOL(snd_request_card);
+
 static void snd_request_other(int minor)
 {
 	char *str;
@@ -133,6 +133,8 @@
 	return private_data;
 }
 
+EXPORT_SYMBOL(snd_lookup_minor_data);
+
 static int snd_open(struct inode *inode, struct file *file)
 {
 	unsigned int minor = iminor(inode);
@@ -281,6 +283,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_register_device);
+
 /**
  * snd_unregister_device - unregister the device on the given card
  * @type: the device type, SNDRV_DEVICE_TYPE_XXX
@@ -321,12 +325,14 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_unregister_device);
+
 #ifdef CONFIG_PROC_FS
 /*
  *  INFO PART
  */
 
-static struct snd_info_entry *snd_minor_info_entry = NULL;
+static struct snd_info_entry *snd_minor_info_entry;
 
 static const char *snd_device_type_name(int type)
 {
@@ -381,7 +387,6 @@
 
 	entry = snd_info_create_module_entry(THIS_MODULE, "devices", NULL);
 	if (entry) {
-		entry->c.text.read_size = PAGE_SIZE;
 		entry->c.text.read = snd_minor_info_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -446,91 +451,3 @@
 
 module_init(alsa_sound_init)
 module_exit(alsa_sound_exit)
-
-  /* sound.c */
-EXPORT_SYMBOL(snd_major);
-EXPORT_SYMBOL(snd_ecards_limit);
-#if defined(CONFIG_KMOD)
-EXPORT_SYMBOL(snd_request_card);
-#endif
-EXPORT_SYMBOL(snd_register_device);
-EXPORT_SYMBOL(snd_unregister_device);
-EXPORT_SYMBOL(snd_lookup_minor_data);
-#if defined(CONFIG_SND_OSSEMUL)
-EXPORT_SYMBOL(snd_register_oss_device);
-EXPORT_SYMBOL(snd_unregister_oss_device);
-EXPORT_SYMBOL(snd_lookup_oss_minor_data);
-#endif
-  /* memory.c */
-EXPORT_SYMBOL(copy_to_user_fromio);
-EXPORT_SYMBOL(copy_from_user_toio);
-  /* init.c */
-EXPORT_SYMBOL(snd_cards);
-#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
-EXPORT_SYMBOL(snd_mixer_oss_notify_callback);
-#endif
-EXPORT_SYMBOL(snd_card_new);
-EXPORT_SYMBOL(snd_card_disconnect);
-EXPORT_SYMBOL(snd_card_free);
-EXPORT_SYMBOL(snd_card_free_in_thread);
-EXPORT_SYMBOL(snd_card_register);
-EXPORT_SYMBOL(snd_component_add);
-EXPORT_SYMBOL(snd_card_file_add);
-EXPORT_SYMBOL(snd_card_file_remove);
-#ifdef CONFIG_PM
-EXPORT_SYMBOL(snd_power_wait);
-#endif
-  /* device.c */
-EXPORT_SYMBOL(snd_device_new);
-EXPORT_SYMBOL(snd_device_register);
-EXPORT_SYMBOL(snd_device_free);
-  /* isadma.c */
-#ifdef CONFIG_ISA_DMA_API
-EXPORT_SYMBOL(snd_dma_program);
-EXPORT_SYMBOL(snd_dma_disable);
-EXPORT_SYMBOL(snd_dma_pointer);
-#endif
-  /* info.c */
-#ifdef CONFIG_PROC_FS
-EXPORT_SYMBOL(snd_seq_root);
-EXPORT_SYMBOL(snd_iprintf);
-EXPORT_SYMBOL(snd_info_get_line);
-EXPORT_SYMBOL(snd_info_get_str);
-EXPORT_SYMBOL(snd_info_create_module_entry);
-EXPORT_SYMBOL(snd_info_create_card_entry);
-EXPORT_SYMBOL(snd_info_free_entry);
-EXPORT_SYMBOL(snd_info_register);
-EXPORT_SYMBOL(snd_info_unregister);
-EXPORT_SYMBOL(snd_card_proc_new);
-#endif
-  /* info_oss.c */
-#if defined(CONFIG_SND_OSSEMUL) && defined(CONFIG_PROC_FS)
-EXPORT_SYMBOL(snd_oss_info_register);
-#endif
-  /* control.c */
-EXPORT_SYMBOL(snd_ctl_new);
-EXPORT_SYMBOL(snd_ctl_new1);
-EXPORT_SYMBOL(snd_ctl_free_one);
-EXPORT_SYMBOL(snd_ctl_add);
-EXPORT_SYMBOL(snd_ctl_remove);
-EXPORT_SYMBOL(snd_ctl_remove_id);
-EXPORT_SYMBOL(snd_ctl_rename_id);
-EXPORT_SYMBOL(snd_ctl_find_numid);
-EXPORT_SYMBOL(snd_ctl_find_id);
-EXPORT_SYMBOL(snd_ctl_notify);
-EXPORT_SYMBOL(snd_ctl_register_ioctl);
-EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
-#ifdef CONFIG_COMPAT
-EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
-EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
-#endif
-EXPORT_SYMBOL(snd_ctl_elem_read);
-EXPORT_SYMBOL(snd_ctl_elem_write);
-  /* misc.c */
-EXPORT_SYMBOL(release_and_free_resource);
-#ifdef CONFIG_SND_VERBOSE_PRINTK
-EXPORT_SYMBOL(snd_verbose_printk);
-#endif
-#if defined(CONFIG_SND_DEBUG) && defined(CONFIG_SND_VERBOSE_PRINTK)
-EXPORT_SYMBOL(snd_verbose_printd);
-#endif
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 9055c6d..74f0fe5 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -58,6 +58,8 @@
 	return private_data;
 }
 
+EXPORT_SYMBOL(snd_lookup_oss_minor_data);
+
 static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
 {
 	int minor;
@@ -158,6 +160,8 @@
       	return -EBUSY;
 }
 
+EXPORT_SYMBOL(snd_register_oss_device);
+
 int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
 {
 	int minor = snd_oss_kernel_minor(type, card, dev);
@@ -197,13 +201,15 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_unregister_oss_device);
+
 /*
  *  INFO PART
  */
 
 #ifdef CONFIG_PROC_FS
 
-static struct snd_info_entry *snd_minor_info_oss_entry = NULL;
+static struct snd_info_entry *snd_minor_info_oss_entry;
 
 static const char *snd_oss_device_type_name(int type)
 {
@@ -252,7 +258,6 @@
 
 	entry = snd_info_create_module_entry(THIS_MODULE, "devices", snd_oss_root);
 	if (entry) {
-		entry->c.text.read_size = PAGE_SIZE;
 		entry->c.text.read = snd_minor_info_oss_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index cdeeb63..78199f5 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1061,7 +1061,6 @@
 static void snd_timer_proc_read(struct snd_info_entry *entry,
 				struct snd_info_buffer *buffer)
 {
-	unsigned long flags;
 	struct snd_timer *timer;
 	struct snd_timer_instance *ti;
 	struct list_head *p, *q;
@@ -1095,7 +1094,6 @@
 		if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
 			snd_iprintf(buffer, " SLAVE");
 		snd_iprintf(buffer, "\n");
-		spin_lock_irqsave(&timer->lock, flags);
 		list_for_each(q, &timer->open_list_head) {
 			ti = list_entry(q, struct snd_timer_instance, open_list);
 			snd_iprintf(buffer, "  Client %s : %s\n",
@@ -1104,12 +1102,11 @@
 						 SNDRV_TIMER_IFLG_RUNNING)
 				    ? "running" : "stopped");
 		}
-		spin_unlock_irqrestore(&timer->lock, flags);
 	}
 	mutex_unlock(&register_mutex);
 }
 
-static struct snd_info_entry *snd_timer_proc_entry = NULL;
+static struct snd_info_entry *snd_timer_proc_entry;
 
 static void __init snd_timer_proc_init(void)
 {
@@ -1117,7 +1114,6 @@
 
 	entry = snd_info_create_module_entry(THIS_MODULE, "timers", NULL);
 	if (entry != NULL) {
-		entry->c.text.read_size = SNDRV_TIMER_DEVICES * 128;
 		entry->c.text.read = snd_timer_proc_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index ae0df54..ffeafaf 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -677,6 +677,10 @@
 							 i, NULL, 0);
 		if (IS_ERR(device))
 			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
+		}
 		devices[i] = device;
 		cards++;
 	}
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 77b0600..d3cbbb0 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -253,6 +253,10 @@
 							 i, NULL, 0);
 		if (IS_ERR(device))
 			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
+		}
 		platform_devices[i] = device;
 		snd_mpu401_devices++;
 	}
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index b49a45c..4bf07ca 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -58,22 +58,26 @@
 #define MPU401_ACK		0xfe
 
 /* Build in lowlevel io */
-static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr)
+static void mpu401_write_port(struct snd_mpu401 *mpu, unsigned char data,
+			      unsigned long addr)
 {
 	outb(data, addr);
 }
 
-static unsigned char mpu401_read_port(struct snd_mpu401 *mpu, unsigned long addr)
+static unsigned char mpu401_read_port(struct snd_mpu401 *mpu,
+				      unsigned long addr)
 {
 	return inb(addr);
 }
 
-static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data, unsigned long addr)
+static void mpu401_write_mmio(struct snd_mpu401 *mpu, unsigned char data,
+			      unsigned long addr)
 {
 	writeb(data, (void __iomem *)addr);
 }
 
-static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu, unsigned long addr)
+static unsigned char mpu401_read_mmio(struct snd_mpu401 *mpu,
+				      unsigned long addr)
 {
 	return readb((void __iomem *)addr);
 }
@@ -86,20 +90,13 @@
 		mpu->read(mpu, MPU401D(mpu));
 #ifdef CONFIG_SND_DEBUG
 	if (timeout <= 0)
-		snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
+		snd_printk(KERN_ERR "cmd: clear rx timeout (status = 0x%x)\n",
+			   mpu->read(mpu, MPU401C(mpu)));
 #endif
 }
 
-static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
+static void uart_interrupt_tx(struct snd_mpu401 *mpu)
 {
-	spin_lock(&mpu->input_lock);
-	if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
-		snd_mpu401_uart_input_read(mpu);
-	} else {
-		snd_mpu401_uart_clear_rx(mpu);
-	}
-	spin_unlock(&mpu->input_lock);
- 	/* ok. for better Tx performance try do some output when input is done */
 	if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
 	    test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
 		spin_lock(&mpu->output_lock);
@@ -108,6 +105,22 @@
 	}
 }
 
+static void _snd_mpu401_uart_interrupt(struct snd_mpu401 *mpu)
+{
+	if (mpu->info_flags & MPU401_INFO_INPUT) {
+		spin_lock(&mpu->input_lock);
+		if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
+			snd_mpu401_uart_input_read(mpu);
+		else
+			snd_mpu401_uart_clear_rx(mpu);
+		spin_unlock(&mpu->input_lock);
+	}
+	if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
+		/* ok. for better Tx performance try do some output
+		   when input is done */
+		uart_interrupt_tx(mpu);
+}
+
 /**
  * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
  * @irq: the irq number
@@ -116,7 +129,8 @@
  *
  * Processes the interrupt for MPU401-UART i/o.
  */
-irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id,
+				      struct pt_regs *regs)
 {
 	struct snd_mpu401 *mpu = dev_id;
 	
@@ -126,6 +140,29 @@
 	return IRQ_HANDLED;
 }
 
+EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
+
+/**
+ * snd_mpu401_uart_interrupt_tx - generic MPU401-UART transmit irq handler
+ * @irq: the irq number
+ * @dev_id: mpu401 instance
+ * @regs: the reigster
+ *
+ * Processes the interrupt for MPU401-UART output.
+ */
+irqreturn_t snd_mpu401_uart_interrupt_tx(int irq, void *dev_id,
+					 struct pt_regs *regs)
+{
+	struct snd_mpu401 *mpu = dev_id;
+	
+	if (mpu == NULL)
+		return IRQ_NONE;
+	uart_interrupt_tx(mpu);
+	return IRQ_HANDLED;
+}
+
+EXPORT_SYMBOL(snd_mpu401_uart_interrupt_tx);
+
 /*
  * timer callback
  * reprogram the timer and call the interrupt job
@@ -159,7 +196,8 @@
 		mpu->timer.expires = 1 + jiffies;
 		add_timer(&mpu->timer);
 	} 
-	mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER;
+	mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER :
+		MPU401_MODE_OUTPUT_TIMER;
 	spin_unlock_irqrestore (&mpu->timer_lock, flags);
 }
 
@@ -172,7 +210,8 @@
 
 	spin_lock_irqsave (&mpu->timer_lock, flags);
 	if (mpu->timer_invoked) {
-		mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER;
+		mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER :
+			~MPU401_MODE_OUTPUT_TIMER;
 		if (! mpu->timer_invoked)
 			del_timer(&mpu->timer);
 	}
@@ -180,11 +219,12 @@
 }
 
 /*
-
+ * send a UART command
+ * return zero if successful, non-zero for some errors
  */
 
 static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
-		int ack)
+			       int ack)
 {
 	unsigned long flags;
 	int timeout, ok;
@@ -196,11 +236,13 @@
 	}
 	/* ok. standard MPU-401 initialization */
 	if (mpu->hardware != MPU401_HW_SB) {
-		for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--)
+		for (timeout = 1000; timeout > 0 &&
+			     !snd_mpu401_output_ready(mpu); timeout--)
 			udelay(10);
 #ifdef CONFIG_SND_DEBUG
 		if (!timeout)
-			snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
+			snd_printk(KERN_ERR "cmd: tx timeout (status = 0x%x)\n",
+				   mpu->read(mpu, MPU401C(mpu)));
 #endif
 	}
 	mpu->write(mpu, cmd, MPU401C(mpu));
@@ -215,12 +257,14 @@
 		}
 		if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
 			ok = 1;
-	} else {
+	} else
 		ok = 1;
-	}
 	spin_unlock_irqrestore(&mpu->input_lock, flags);
 	if (!ok) {
-		snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
+		snd_printk(KERN_ERR "cmd: 0x%x failed at 0x%lx "
+			   "(status = 0x%x, data = 0x%x)\n", cmd, mpu->port,
+			   mpu->read(mpu, MPU401C(mpu)),
+			   mpu->read(mpu, MPU401D(mpu)));
 		return 1;
 	}
 	return 0;
@@ -314,7 +358,8 @@
 /*
  * trigger input callback
  */
-static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
+static void
+snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
 {
 	unsigned long flags;
 	struct snd_mpu401 *mpu;
@@ -322,7 +367,8 @@
 
 	mpu = substream->rmidi->private_data;
 	if (up) {
-		if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
+		if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER,
+				       &mpu->mode)) {
 			/* first time - flush FIFO */
 			while (max-- > 0)
 				mpu->read(mpu, MPU401D(mpu));
@@ -352,13 +398,11 @@
 	unsigned char byte;
 
 	while (max-- > 0) {
-		if (snd_mpu401_input_avail(mpu)) {
-			byte = mpu->read(mpu, MPU401D(mpu));
-			if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
-				snd_rawmidi_receive(mpu->substream_input, &byte, 1);
-		} else {
+		if (! snd_mpu401_input_avail(mpu))
 			break; /* input not available */
-		}
+		byte = mpu->read(mpu, MPU401D(mpu));
+		if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
+			snd_rawmidi_receive(mpu->substream_input, &byte, 1);
 	}
 }
 
@@ -380,16 +424,16 @@
 	int max = 256, timeout;
 
 	do {
-		if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) {
+		if (snd_rawmidi_transmit_peek(mpu->substream_output,
+					      &byte, 1) == 1) {
 			for (timeout = 100; timeout > 0; timeout--) {
-				if (snd_mpu401_output_ready(mpu)) {
-					mpu->write(mpu, byte, MPU401D(mpu));
-					snd_rawmidi_transmit_ack(mpu->substream_output, 1);
+				if (snd_mpu401_output_ready(mpu))
 					break;
-				}
 			}
 			if (timeout == 0)
 				break;	/* Tx FIFO full - try again later */
+			mpu->write(mpu, byte, MPU401D(mpu));
+			snd_rawmidi_transmit_ack(mpu->substream_output, 1);
 		} else {
 			snd_mpu401_uart_remove_timer (mpu, 0);
 			break;	/* no other data - leave the tx loop */
@@ -400,7 +444,8 @@
 /*
  * output trigger callback
  */
-static void snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
+static void
+snd_mpu401_uart_output_trigger(struct snd_rawmidi_substream *substream, int up)
 {
 	unsigned long flags;
 	struct snd_mpu401 *mpu;
@@ -413,14 +458,16 @@
 		 * since the output timer might have been removed in
 		 * snd_mpu401_uart_output_write().
 		 */
-		snd_mpu401_uart_add_timer(mpu, 0);
+		if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
+			snd_mpu401_uart_add_timer(mpu, 0);
 
 		/* output pending data */
 		spin_lock_irqsave(&mpu->output_lock, flags);
 		snd_mpu401_uart_output_write(mpu);
 		spin_unlock_irqrestore(&mpu->output_lock, flags);
 	} else {
-		snd_mpu401_uart_remove_timer(mpu, 0);
+		if (! (mpu->info_flags & MPU401_INFO_TX_IRQ))
+			snd_mpu401_uart_remove_timer(mpu, 0);
 		clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
 	}
 }
@@ -458,7 +505,7 @@
  * @device: the device index, zero-based
  * @hardware: the hardware type, MPU401_HW_XXXX
  * @port: the base address of MPU401 port
- * @integrated: non-zero if the port was already reserved by the chip
+ * @info_flags: bitflags MPU401_INFO_XXX
  * @irq: the irq number, -1 if no interrupt for mpu
  * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
  * @rrawmidi: the pointer to store the new rawmidi instance
@@ -473,17 +520,24 @@
  */
 int snd_mpu401_uart_new(struct snd_card *card, int device,
 			unsigned short hardware,
-			unsigned long port, int integrated,
+			unsigned long port,
+			unsigned int info_flags,
 			int irq, int irq_flags,
 			struct snd_rawmidi ** rrawmidi)
 {
 	struct snd_mpu401 *mpu;
 	struct snd_rawmidi *rmidi;
+	int in_enable, out_enable;
 	int err;
 
 	if (rrawmidi)
 		*rrawmidi = NULL;
-	if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
+	if (! (info_flags & (MPU401_INFO_INPUT | MPU401_INFO_OUTPUT)))
+		info_flags |= MPU401_INFO_INPUT | MPU401_INFO_OUTPUT;
+	in_enable = (info_flags & MPU401_INFO_INPUT) ? 1 : 0;
+	out_enable = (info_flags & MPU401_INFO_OUTPUT) ? 1 : 0;
+	if ((err = snd_rawmidi_new(card, "MPU-401U", device,
+				   out_enable, in_enable, &rmidi)) < 0)
 		return err;
 	mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
 	if (mpu == NULL) {
@@ -497,23 +551,23 @@
 	spin_lock_init(&mpu->output_lock);
 	spin_lock_init(&mpu->timer_lock);
 	mpu->hardware = hardware;
-	if (!integrated) {
+	if (! (info_flags & MPU401_INFO_INTEGRATED)) {
 		int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
-		if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) {
-			snd_printk(KERN_ERR "mpu401_uart: unable to grab port 0x%lx size %d\n", port, res_size);
+		mpu->res = request_region(port, res_size, "MPU401 UART");
+		if (mpu->res == NULL) {
+			snd_printk(KERN_ERR "mpu401_uart: "
+				   "unable to grab port 0x%lx size %d\n",
+				   port, res_size);
 			snd_device_free(card, rmidi);
 			return -EBUSY;
 		}
 	}
-	switch (hardware) {
-	case MPU401_HW_AUREAL:
+	if (info_flags & MPU401_INFO_MMIO) {
 		mpu->write = mpu401_write_mmio;
 		mpu->read = mpu401_read_mmio;
-		break;
-	default:
+	} else {
 		mpu->write = mpu401_write_port;
 		mpu->read = mpu401_read_port;
-		break;
 	}
 	mpu->port = port;
 	if (hardware == MPU401_HW_PC98II)
@@ -521,30 +575,40 @@
 	else
 		mpu->cport = port + 1;
 	if (irq >= 0 && irq_flags) {
-		if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) {
-			snd_printk(KERN_ERR "mpu401_uart: unable to grab IRQ %d\n", irq);
+		if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags,
+				"MPU401 UART", (void *) mpu)) {
+			snd_printk(KERN_ERR "mpu401_uart: "
+				   "unable to grab IRQ %d\n", irq);
 			snd_device_free(card, rmidi);
 			return -EBUSY;
 		}
 	}
+	mpu->info_flags = info_flags;
 	mpu->irq = irq;
 	mpu->irq_flags = irq_flags;
 	if (card->shortname[0])
-		snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", card->shortname);
+		snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI",
+			 card->shortname);
 	else
-		sprintf(rmidi->name, "MPU-401 MIDI %d-%d", card->number, device);
-	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output);
-	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input);
-	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
-	                     SNDRV_RAWMIDI_INFO_INPUT |
-	                     SNDRV_RAWMIDI_INFO_DUPLEX;
+		sprintf(rmidi->name, "MPU-401 MIDI %d-%d",card->number, device);
+	if (out_enable) {
+		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
+				    &snd_mpu401_uart_output);
+		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
+	}
+	if (in_enable) {
+		snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
+				    &snd_mpu401_uart_input);
+		rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
+		if (out_enable)
+			rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
+	}
 	mpu->rmidi = rmidi;
 	if (rrawmidi)
 		*rrawmidi = rmidi;
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
 EXPORT_SYMBOL(snd_mpu401_uart_new);
 
 /*
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index b7a0b42..474eed0 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -770,11 +770,15 @@
 		return err;
 
 	device = platform_device_register_simple(SND_MTPAV_DRIVER, -1, NULL, 0);
-	if (IS_ERR(device)) {
-		platform_driver_unregister(&snd_mtpav_driver);
-		return PTR_ERR(device);
-	}
-	return 0;
+	if (!IS_ERR(device)) {
+		if (platform_get_drvdata(device))
+			return 0;
+		platform_device_unregister(device);
+		err = -ENODEV;
+	} else
+		err = PTR_ERR(device);
+	platform_driver_unregister(&snd_mtpav_driver);
+	return err;
 }
 
 static void __exit alsa_card_mtpav_exit(void)
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index 4f85569..87fe376 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -316,6 +316,8 @@
 	}
 }
 
+EXPORT_SYMBOL(snd_opl3_interrupt);
+
 /*
 
  */
@@ -369,6 +371,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_opl3_new);
+
 int snd_opl3_init(struct snd_opl3 *opl3)
 {
 	if (! opl3->command) {
@@ -393,6 +397,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_opl3_init);
+
 int snd_opl3_create(struct snd_card *card,
 		    unsigned long l_port,
 		    unsigned long r_port,
@@ -451,6 +457,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_opl3_create);
+
 int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
 {
 	int err;
@@ -468,6 +476,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_opl3_timer_new);
+
 int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
 		       int device, int seq_device,
 		       struct snd_hwdep ** rhwdep)
@@ -526,17 +536,8 @@
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_opl3_interrupt);
-EXPORT_SYMBOL(snd_opl3_new);
-EXPORT_SYMBOL(snd_opl3_init);
-EXPORT_SYMBOL(snd_opl3_create);
-EXPORT_SYMBOL(snd_opl3_timer_new);
 EXPORT_SYMBOL(snd_opl3_hwdep_new);
 
-/* opl3_synth.c */
-EXPORT_SYMBOL(snd_opl3_regmap);
-EXPORT_SYMBOL(snd_opl3_reset);
-
 /*
  *  INIT part
  */
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index fccf019..5fd3a4c 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -100,7 +100,8 @@
 							  SNDRV_SEQ_PORT_CAP_WRITE,
 							  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
 							  SNDRV_SEQ_PORT_TYPE_MIDI_GM |
-							  SNDRV_SEQ_PORT_TYPE_SYNTH,
+							  SNDRV_SEQ_PORT_TYPE_HARDWARE |
+							  SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
 							  voices, voices,
 							  name);
 	if (opl3->oss_chset->port < 0) {
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index 57becf3..96762c9 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -203,7 +203,9 @@
 						      SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
 						      SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
 						      SNDRV_SEQ_PORT_TYPE_MIDI_GM |
-						      SNDRV_SEQ_PORT_TYPE_SYNTH,
+						      SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
+						      SNDRV_SEQ_PORT_TYPE_HARDWARE |
+						      SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
 						      16, voices,
 						      name);
 	if (opl3->chset->port < 0) {
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index 6db503f..a4b3543 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -58,6 +58,8 @@
 	{ 0x12, 0x15, 0x00, 0x00 }	/* is selected (only left reg block) */
 };
 
+EXPORT_SYMBOL(snd_opl3_regmap);
+
 /*
  * prototypes
  */
@@ -228,6 +230,7 @@
 	opl3->rhythm = 0;
 }
 
+EXPORT_SYMBOL(snd_opl3_reset);
 
 static int snd_opl3_play_note(struct snd_opl3 * opl3, struct snd_dm_fm_note * note)
 {
@@ -445,3 +448,4 @@
 
 	return 0;
 }
+
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index 4bc860a..01997f2 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -43,6 +43,8 @@
 	outb(value, opl4->pcm_port + 1);
 }
 
+EXPORT_SYMBOL(snd_opl4_write);
+
 u8 snd_opl4_read(struct snd_opl4 *opl4, u8 reg)
 {
 	snd_opl4_wait(opl4);
@@ -52,6 +54,8 @@
 	return inb(opl4->pcm_port + 1);
 }
 
+EXPORT_SYMBOL(snd_opl4_read);
+
 void snd_opl4_read_memory(struct snd_opl4 *opl4, char *buf, int offset, int size)
 {
 	unsigned long flags;
@@ -76,6 +80,8 @@
 	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
+EXPORT_SYMBOL(snd_opl4_read_memory);
+
 void snd_opl4_write_memory(struct snd_opl4 *opl4, const char *buf, int offset, int size)
 {
 	unsigned long flags;
@@ -100,6 +106,8 @@
 	spin_unlock_irqrestore(&opl4->reg_lock, flags);
 }
 
+EXPORT_SYMBOL(snd_opl4_write_memory);
+
 static void snd_opl4_enable_opl4(struct snd_opl4 *opl4)
 {
 	outb(OPL3_REG_MODE, opl4->fm_port + 2);
@@ -256,10 +264,6 @@
 	return 0;
 }
 
-EXPORT_SYMBOL(snd_opl4_write);
-EXPORT_SYMBOL(snd_opl4_read);
-EXPORT_SYMBOL(snd_opl4_write_memory);
-EXPORT_SYMBOL(snd_opl4_read_memory);
 EXPORT_SYMBOL(snd_opl4_create);
 
 static int __init alsa_opl4_init(void)
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
index dc0dcdc..43d8a2b 100644
--- a/sound/drivers/opl4/opl4_seq.c
+++ b/sound/drivers/opl4/opl4_seq.c
@@ -164,7 +164,9 @@
 						      SNDRV_SEQ_PORT_CAP_WRITE |
 						      SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
 						      SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
-						      SNDRV_SEQ_PORT_TYPE_MIDI_GM,
+						      SNDRV_SEQ_PORT_TYPE_MIDI_GM |
+						      SNDRV_SEQ_PORT_TYPE_HARDWARE |
+						      SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
 						      16, 24,
 						      "OPL4 Wavetable Port");
 	if (opl4->chset->port < 0) {
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index c01b4c5..2330fec 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -998,6 +998,10 @@
 							 i, NULL, 0);
 		if (IS_ERR(device))
 			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
+		}
 		devices[i] = device;
 		cards++;
 	}
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 26eb249..59171f8 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -171,6 +171,10 @@
 							 i, NULL, 0);
 		if (IS_ERR(device))
 			continue;
+		if (!platform_get_drvdata(device)) {
+			platform_device_unregister(device);
+			continue;
+		}
 		devices[i] = device;
 		cards++;
 	}
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index fa4a2b5..a601682 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -70,6 +70,8 @@
 	return -EIO;
 }
 
+EXPORT_SYMBOL(snd_vx_check_reg_bit);
+
 /*
  * vx_send_irq_dsp - set command irq bit
  * @num: the requested IRQ type, IRQ_XXX
@@ -465,6 +467,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_vx_load_boot_image);
+
 /*
  * vx_test_irq_src - query the source of interrupts
  *
@@ -545,6 +549,7 @@
 	return IRQ_HANDLED;
 }
 
+EXPORT_SYMBOL(snd_vx_irq_handler);
 
 /*
  */
@@ -635,7 +640,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "vx-status", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, vx_proc_read);
+		snd_info_set_text_ops(entry, chip, vx_proc_read);
 }
 
 
@@ -657,6 +662,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_vx_dsp_boot);
+
 /**
  * snd_vx_dsp_load - load the DSP image
  */
@@ -705,6 +712,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_vx_dsp_load);
+
 #ifdef CONFIG_PM
 /*
  * suspend
@@ -721,6 +730,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_vx_suspend);
+
 /*
  * resume
  */
@@ -747,6 +758,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_vx_resume);
 #endif
 
 /**
@@ -790,6 +802,8 @@
 	return chip;
 }
 
+EXPORT_SYMBOL(snd_vx_create);
+
 /*
  * module entries
  */
@@ -804,19 +818,3 @@
 
 module_init(alsa_vx_core_init)
 module_exit(alsa_vx_core_exit)
-
-/*
- * exports
- */
-EXPORT_SYMBOL(snd_vx_check_reg_bit);
-EXPORT_SYMBOL(snd_vx_create);
-EXPORT_SYMBOL(snd_vx_setup_firmware);
-EXPORT_SYMBOL(snd_vx_free_firmware);
-EXPORT_SYMBOL(snd_vx_irq_handler);
-EXPORT_SYMBOL(snd_vx_dsp_boot);
-EXPORT_SYMBOL(snd_vx_dsp_load);
-EXPORT_SYMBOL(snd_vx_load_boot_image);
-#ifdef CONFIG_PM
-EXPORT_SYMBOL(snd_vx_suspend);
-EXPORT_SYMBOL(snd_vx_resume);
-#endif
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index d837783..e1920af 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -250,3 +250,6 @@
 }
 
 #endif /* SND_VX_FW_LOADER */
+
+EXPORT_SYMBOL(snd_vx_setup_firmware);
+EXPORT_SYMBOL(snd_vx_free_firmware);
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index edfe76f..b60fb18 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -106,6 +106,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_i2c_bus_create);
+
 int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
 			  unsigned char addr, struct snd_i2c_device **rdevice)
 {
@@ -124,6 +126,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_i2c_device_create);
+
 int snd_i2c_device_free(struct snd_i2c_device *device)
 {
 	if (device->bus)
@@ -134,22 +138,29 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_i2c_device_free);
+
 int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
 {
 	return device->bus->ops->sendbytes(device, bytes, count);
 }
 
+EXPORT_SYMBOL(snd_i2c_sendbytes);
 
 int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
 {
 	return device->bus->ops->readbytes(device, bytes, count);
 }
 
+EXPORT_SYMBOL(snd_i2c_readbytes);
+
 int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
 {
 	return bus->ops->probeaddr(bus, addr);
 }
 
+EXPORT_SYMBOL(snd_i2c_probeaddr);
+
 /*
  *  bit-operations
  */
@@ -320,12 +331,6 @@
 	return err;
 }
 
-EXPORT_SYMBOL(snd_i2c_bus_create);
-EXPORT_SYMBOL(snd_i2c_device_create);
-EXPORT_SYMBOL(snd_i2c_device_free);
-EXPORT_SYMBOL(snd_i2c_sendbytes);
-EXPORT_SYMBOL(snd_i2c_readbytes);
-EXPORT_SYMBOL(snd_i2c_probeaddr);
 
 static int __init alsa_i2c_init(void)
 {
diff --git a/sound/i2c/l3/uda1341.c b/sound/i2c/l3/uda1341.c
index 746500e..b074fdd 100644
--- a/sound/i2c/l3/uda1341.c
+++ b/sound/i2c/l3/uda1341.c
@@ -517,9 +517,9 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(card, "uda1341", &entry))
-		snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_read);
+		snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_read);
 	if (! snd_card_proc_new(card, "uda1341-regs", &entry))
-		snd_info_set_text_ops(entry, clnt, 1024, snd_uda1341_proc_regs_read);
+		snd_info_set_text_ops(entry, clnt, snd_uda1341_proc_regs_read);
 }
 
 /* }}} */
diff --git a/sound/isa/gus/gus_irq.c b/sound/isa/gus/gus_irq.c
index c19ba29..42db375 100644
--- a/sound/isa/gus/gus_irq.c
+++ b/sound/isa/gus/gus_irq.c
@@ -136,7 +136,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(gus->card, "gusirq", &entry))
-		snd_info_set_text_ops(entry, gus, 1024, snd_gus_irq_info_read);
+		snd_info_set_text_ops(entry, gus, snd_gus_irq_info_read);
 }
 
 #endif
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index 3c0d27a..f50c276 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -264,10 +264,8 @@
 	if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
 		return -ENOMEM;
 #ifdef CONFIG_SND_DEBUG
-	if (! snd_card_proc_new(gus->card, "gusmem", &entry)) {
-		snd_info_set_text_ops(entry, gus, 1024, snd_gf1_mem_info_read);
-		entry->c.text.read_size = 256 * 1024;
-	}
+	if (! snd_card_proc_new(gus->card, "gusmem", &entry))
+		snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read);
 #endif
 	return 0;
 }
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index 2767cc1..3e4d4d6 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -194,7 +194,9 @@
 						   &callbacks,
 						   SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
 						   SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
-						   SNDRV_SEQ_PORT_TYPE_SYNTH,
+						   SNDRV_SEQ_PORT_TYPE_SYNTH |
+						   SNDRV_SEQ_PORT_TYPE_HARDWARE |
+						   SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
 						   16, 0,
 						   name);
 	if (p->chset->port < 0) {
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 4298d33..866300f 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -70,9 +70,9 @@
 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 0,1,3,5,6,7 */
 static int joystick_dac[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 29};
 				/* 0 to 31, (0.59V-4.52V or 0.389V-2.98V) */
-static int midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+static int midi[SNDRV_CARDS];
 static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
-static int effect[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+static int effect[SNDRV_CARDS];
 
 #ifdef SNDRV_STB
 #define PFX "interwave-stb: "
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 6d88905..647a996 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -59,7 +59,7 @@
 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* 0,1,3,5,9,11,12,15 */
 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 1,3,5,6,7 */
 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 1,3,5,6,7 */
-static int opl3sa3_ymode[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 };   /* 0,1,2,3 */ /*SL Added*/
+static int opl3sa3_ymode[SNDRV_CARDS];   /* 0,1,2,3 */ /*SL Added*/
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for OPL3-SA soundcard.");
@@ -221,7 +221,7 @@
 	spin_unlock_irqrestore(&chip->reg_lock, flags);
 }
 
-static int __init snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
+static int __devinit snd_opl3sa2_detect(struct snd_opl3sa2 *chip)
 {
 	struct snd_card *card;
 	unsigned long port;
@@ -489,7 +489,7 @@
 	chip->master_volume = NULL;
 }
 
-static int __init snd_opl3sa2_mixer(struct snd_opl3sa2 *chip)
+static int __devinit snd_opl3sa2_mixer(struct snd_opl3sa2 *chip)
 {
 	struct snd_card *card = chip->card;
 	struct snd_ctl_elem_id id1, id2;
@@ -583,8 +583,8 @@
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PNP
-static int __init snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
-				  struct pnp_dev *pdev)
+static int __devinit snd_opl3sa2_pnp(int dev, struct snd_opl3sa2 *chip,
+				     struct pnp_dev *pdev)
 {
 	struct pnp_resource_table * cfg;
 	int err;
@@ -862,7 +862,7 @@
 };
 #endif /* CONFIG_PNP */
 
-static int __init snd_opl3sa2_nonpnp_probe(struct platform_device *pdev)
+static int __devinit snd_opl3sa2_nonpnp_probe(struct platform_device *pdev)
 {
 	struct snd_card *card;
 	int err;
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index e6bfcf7..283817f 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -967,7 +967,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(miro->card, "miro", &entry))
-		snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read);
+		snd_info_set_text_ops(entry, miro, snd_miro_proc_read);
 }
 
 /*
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index c0b8d61..658179e 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -131,7 +131,7 @@
 
 /*
  */
-static void __init
+static void __devinit
 snd_emu8000_read_wait(struct snd_emu8000 *emu)
 {
 	while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
@@ -143,7 +143,7 @@
 
 /*
  */
-static void __init
+static void __devinit
 snd_emu8000_write_wait(struct snd_emu8000 *emu)
 {
 	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
@@ -156,7 +156,7 @@
 /*
  * detect a card at the given port
  */
-static int __init
+static int __devinit
 snd_emu8000_detect(struct snd_emu8000 *emu)
 {
 	/* Initialise */
@@ -182,7 +182,7 @@
 /*
  * intiailize audio channels
  */
-static void __init
+static void __devinit
 init_audio(struct snd_emu8000 *emu)
 {
 	int ch;
@@ -223,7 +223,7 @@
 /*
  * initialize DMA address
  */
-static void __init
+static void __devinit
 init_dma(struct snd_emu8000 *emu)
 {
 	EMU8000_SMALR_WRITE(emu, 0);
@@ -327,7 +327,7 @@
  * Taken from the oss driver, not obvious from the doc how this
  * is meant to work
  */
-static void __init
+static void __devinit
 send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
 {
 	int i;
@@ -349,7 +349,7 @@
  * Send initialization arrays to start up, this just follows the
  * initialisation sequence in the adip.
  */
-static void __init
+static void __devinit
 init_arrays(struct snd_emu8000 *emu)
 {
 	send_array(emu, init1, ARRAY_SIZE(init1)/4);
@@ -375,7 +375,7 @@
  * seems that the only way to do this is to use the one channel and keep
  * reallocating between read and write.
  */
-static void __init
+static void __devinit
 size_dram(struct snd_emu8000 *emu)
 {
 	int i, size;
@@ -500,7 +500,7 @@
 /*
  * The main initialization routine.
  */
-static void __init
+static void __devinit
 snd_emu8000_init_hw(struct snd_emu8000 *emu)
 {
 	int i;
@@ -1019,7 +1019,7 @@
 /*
  * create and attach mixer elements for WaveTable treble/bass controls
  */
-static int __init
+static int __devinit
 snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
 {
 	int i, err = 0;
@@ -1069,7 +1069,7 @@
 /*
  * initialize and register emu8000 synth device.
  */
-int __init
+int __devinit
 snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
 		struct snd_seq_device **awe_ret)
 {
diff --git a/sound/isa/sb/emu8000_patch.c b/sound/isa/sb/emu8000_patch.c
index 80b1cf8..1be16c9 100644
--- a/sound/isa/sb/emu8000_patch.c
+++ b/sound/isa/sb/emu8000_patch.c
@@ -23,7 +23,7 @@
 #include <asm/uaccess.h>
 #include <linux/moduleparam.h>
 
-static int emu8000_reset_addr = 0;
+static int emu8000_reset_addr;
 module_param(emu8000_reset_addr, int, 0444);
 MODULE_PARM_DESC(emu8000_reset_addr, "reset write address at each time (makes slowdown)");
 
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 6333f90..7f7f05f 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -85,7 +85,7 @@
 static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* 5,6,7 */
 static int mic_agc[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
 #ifdef CONFIG_SND_SB16_CSP
-static int csp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+static int csp[SNDRV_CARDS];
 #endif
 #ifdef SNDRV_SBAWE_EMU8000
 static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 9703c68..fcd6380 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -1101,7 +1101,7 @@
 	struct snd_info_entry *entry;
 	sprintf(name, "cspD%d", device);
 	if (! snd_card_proc_new(p->chip->card, name, &entry))
-		snd_info_set_text_ops(entry, p, 1024, info_read);
+		snd_info_set_text_ops(entry, p, info_read);
 	return 0;
 }
 
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index c549ace..0b67edd 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -32,20 +32,22 @@
 #include <sound/core.h>
 #include <sound/sb.h>
 
-/*
 
- */
-
-irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb * chip)
+irqreturn_t snd_sb8dsp_midi_interrupt(struct snd_sb *chip)
 {
 	struct snd_rawmidi *rmidi;
 	int max = 64;
 	char byte;
 
-	if (chip == NULL || (rmidi = chip->rmidi) == NULL) {
+	if (!chip)
+		return IRQ_NONE;
+	
+	rmidi = chip->rmidi;
+	if (!rmidi) {
 		inb(SBP(chip, DATA_AVAIL));	/* ack interrupt */
 		return IRQ_NONE;
 	}
+
 	spin_lock(&chip->midi_input_lock);
 	while (max-- > 0) {
 		if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
@@ -59,10 +61,6 @@
 	return IRQ_HANDLED;
 }
 
-/*
-
- */
-
 static int snd_sb8dsp_midi_input_open(struct snd_rawmidi_substream *substream)
 {
 	unsigned long flags;
@@ -252,10 +250,6 @@
 		snd_sb8dsp_midi_output_write(substream);
 }
 
-/*
-
- */
-
 static struct snd_rawmidi_ops snd_sb8dsp_midi_output =
 {
 	.open =		snd_sb8dsp_midi_output_open,
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index d2a856f..27271c9 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -897,10 +897,9 @@
 	struct snd_rawmidi *rawmidi;
 	int err;
 
-#define MPU401_SHARE_HARDWARE  1
 	if ((err = snd_mpu401_uart_new(card, devnum,
 	                               MPU401_HW_MPU401,
-	                               port, MPU401_SHARE_HARDWARE,
+	                               port, MPU401_INFO_INTEGRATED,
 	                               irq, SA_INTERRUPT,
 	                               &rawmidi)) == 0) {
 		struct snd_mpu401 *mpu = (struct snd_mpu401 *) rawmidi->private_data;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 7ae86f8..9eb2708 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -50,7 +50,7 @@
 static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	    /* PnP setup */
 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	    /* 0,1,3,5,6,7 */
 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	    /* 0,1,3,5,6,7 */
-static int use_cs4232_midi[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; 
+static int use_cs4232_midi[SNDRV_CARDS];
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for WaveFront soundcard.");
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 558c6ed..3b8cdbc 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -98,8 +98,8 @@
 	tristate "SGI HAL2 sound (EXPERIMENTAL)"
 	depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL
 	help
-	  Say Y or M if you have an SGI Indy system and want to be able to
-	  use it's on-board A2 audio system.
+	  Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to
+	  use its on-board A2 audio system.
 
 config SOUND_IT8172
 	tristate "IT8172G Sound"
@@ -114,8 +114,9 @@
 	  with the AC97 codec.
 
 config SOUND_AU1550_AC97
-	tristate "Au1550 AC97 Sound"
-	depends on SOUND_PRIME && SOC_AU1550
+	tristate "Au1550/Au1200 AC97 Sound"
+	select SND_AC97_CODEC
+	depends on SOUND_PRIME && (SOC_AU1550 || SOC_AU1200)
 
 config SOUND_TRIDENT
 	tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
@@ -838,6 +839,6 @@
 	depends on SOUND_PRIME && CPU_SH3
 
 config SOUND_SH_DAC_AUDIO_CHANNEL
-	int "    DAC channel"
+	int "DAC channel"
 	default "1"
 	depends on SOUND_SH_DAC_AUDIO
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index c1168fa..4cdb862 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -57,9 +57,9 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
-#include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 #include <asm/mach-au1x00/au1xxx_dbdma.h>
+#include <asm/mach-au1x00/au1xxx.h>
 
 #undef OSS_DOCUMENTED_MIXER_SEMANTICS
 
@@ -213,7 +213,8 @@
 	}
 	if (i == POLL_COUNT) {
 		err("rdcodec: read poll expired!");
-		return 0;
+		data = 0;
+		goto out;
 	}
 
 	/* wait for command done?
@@ -226,7 +227,8 @@
 	}
 	if (i == POLL_COUNT) {
 		err("rdcodec: read cmdwait expired!");
-		return 0;
+		data = 0;
+		goto out;
 	}
 
 	data = au_readl(PSC_AC97CDC) & 0xffff;
@@ -237,6 +239,7 @@
 	au_writel(PSC_AC97EVNT_CD, PSC_AC97EVNT);
 	au_sync();
 
+ out:
 	spin_unlock_irqrestore(&s->lock, flags);
 
 	return data;
@@ -1892,6 +1895,8 @@
 
 MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
 MODULE_DESCRIPTION("Au1550 AC97 Audio Driver");
+MODULE_LICENSE("GPL");
+
 
 static int __devinit
 au1550_probe(void)
diff --git a/sound/oss/cs4232.c b/sound/oss/cs4232.c
index c7f86f0..80f6c08 100644
--- a/sound/oss/cs4232.c
+++ b/sound/oss/cs4232.c
@@ -405,7 +405,7 @@
 
 MODULE_DEVICE_TABLE(pnp, cs4232_pnp_table);
 
-static int cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+static int __init cs4232_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
 	struct address_info *isapnpcfg;
 
diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
index 53881bc..994c71e 100644
--- a/sound/oss/cs46xx.c
+++ b/sound/oss/cs46xx.c
@@ -147,7 +147,7 @@
  * that should be printed on any released driver.
  */
 #if CSDEBUG
-#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} 
+#define CS_DBGOUT(mask,level,x) if ((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;}
 #else
 #define CS_DBGOUT(mask,level,x) 
 #endif
@@ -175,19 +175,19 @@
 #define CS_IOCTL_CMD_RESUME	0x2	// resume
 
 #if CSDEBUG
-static unsigned long cs_debuglevel=1;			/* levels range from 1-9 */
+static unsigned long cs_debuglevel = 1;			/* levels range from 1-9 */
 module_param(cs_debuglevel, ulong, 0644);
-static unsigned long cs_debugmask=CS_INIT | CS_ERROR;	/* use CS_DBGOUT with various mask values */
+static unsigned long cs_debugmask = CS_INIT | CS_ERROR;	/* use CS_DBGOUT with various mask values */
 module_param(cs_debugmask, ulong, 0644);
 #endif
 static unsigned long hercules_egpio_disable;  /* if non-zero set all EGPIO to 0 */
 module_param(hercules_egpio_disable, ulong, 0);
-static unsigned long initdelay=700;  /* PM delay in millisecs */
+static unsigned long initdelay = 700;  /* PM delay in millisecs */
 module_param(initdelay, ulong, 0);
-static unsigned long powerdown=-1;  /* turn on/off powerdown processing in driver */
+static unsigned long powerdown = -1;  /* turn on/off powerdown processing in driver */
 module_param(powerdown, ulong, 0);
 #define DMABUF_DEFAULTORDER 3
-static unsigned long defaultorder=DMABUF_DEFAULTORDER;
+static unsigned long defaultorder = DMABUF_DEFAULTORDER;
 module_param(defaultorder, ulong, 0);
 
 static int external_amp;
@@ -200,8 +200,8 @@
 * powerdown. also set thinkpad to 1 to disable powerdown, 
 * but also to enable the clkrun functionality.
 */
-static unsigned cs_powerdown=1;
-static unsigned cs_laptop_wait=1;
+static unsigned cs_powerdown = 1;
+static unsigned cs_laptop_wait = 1;
 
 /* An instance of the 4610 channel */
 struct cs_channel 
@@ -319,7 +319,7 @@
 	atomic_t mixer_use_cnt;
 
 	/* PCI device stuff */
-	struct pci_dev * pci_dev;
+	struct pci_dev *pci_dev;
 	struct list_head list;
 
 	unsigned int pctl, cctl;	/* Hardware DMA flag sets */
@@ -384,7 +384,7 @@
 static int cs_open_mixdev(struct inode *inode, struct file *file);
 static int cs_release_mixdev(struct inode *inode, struct file *file);
 static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-				unsigned long arg);
+			unsigned long arg);
 static int cs_hardware_init(struct cs_card *card);
 static int cs46xx_powerup(struct cs_card *card, unsigned int type);
 static int cs461x_powerdown(struct cs_card *card, unsigned int type, int suspendflag);
@@ -423,8 +423,7 @@
                 [SOUND_MIXER_VOLUME]  = 9    /* Master Volume */
         };
         
-    switch(x) 
-    {
+    switch (x) {
 	case SOUND_MIXER_CS_GETDBGMASK:
 		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") );
 		break;
@@ -521,7 +520,6 @@
         case SOUND_PCM_READ_FILTER:
 		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") );
 		break;
-
         case SOUND_MIXER_PRIVATE1:
 		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") );
 		break;
@@ -543,10 +541,8 @@
         case SOUND_OLD_MIXER_INFO:
 		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") );
 		break;
-
 	default:
-		switch (_IOC_NR(x)) 
-		{
+		switch (_IOC_NR(x)) {
 			case SOUND_MIXER_VOLUME:
 				CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") );
 				break;
@@ -579,14 +575,11 @@
 				break;
 			default:
 				i = _IOC_NR(x);
-				if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
-				{
+				if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) {
 					CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) );
-				}
-				else
-				{
+				} else {
 					CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ",
-							x,i) );
+							x,i));
 				}
 				break;
 		}
@@ -601,22 +594,22 @@
 
 static void cs461x_poke(struct cs_card *codec, unsigned long reg, unsigned int val)
 {
-	writel(val, codec->ba1.idx[(reg >> 16) & 3]+(reg&0xffff));
+	writel(val, codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
 }
 
 static unsigned int cs461x_peek(struct cs_card *codec, unsigned long reg)
 {
-	return readl(codec->ba1.idx[(reg >> 16) & 3]+(reg&0xffff));
+	return readl(codec->ba1.idx[(reg >> 16) & 3] + (reg & 0xffff));
 }
 
 static void cs461x_pokeBA0(struct cs_card *codec, unsigned long reg, unsigned int val)
 {
-	writel(val, codec->ba0+reg);
+	writel(val, codec->ba0 + reg);
 }
 
 static unsigned int cs461x_peekBA0(struct cs_card *codec, unsigned long reg)
 {
-	return readl(codec->ba0+reg);
+	return readl(codec->ba0 + reg);
 }
 
 
@@ -625,26 +618,26 @@
 
 static struct cs_channel *cs_alloc_pcm_channel(struct cs_card *card)
 {
-	if(card->channel[1].used==1)
+	if (card->channel[1].used == 1)
 		return NULL;
-	card->channel[1].used=1;
-	card->channel[1].num=1;
+	card->channel[1].used = 1;
+	card->channel[1].num = 1;
 	return &card->channel[1];
 }
 
 static struct cs_channel *cs_alloc_rec_pcm_channel(struct cs_card *card)
 {
-	if(card->channel[0].used==1)
+	if (card->channel[0].used == 1)
 		return NULL;
-	card->channel[0].used=1;
-	card->channel[0].num=0;
+	card->channel[0].used = 1;
+	card->channel[0].num = 0;
 	return &card->channel[0];
 }
 
 static void cs_free_pcm_channel(struct cs_card *card, int channel)
 {
 	card->channel[channel].state = NULL;
-	card->channel[channel].used=0;
+	card->channel[channel].used = 0;
 }
 
 /*
@@ -655,15 +648,15 @@
  */
 static void cs_set_divisor(struct dmabuf *dmabuf)
 {
-	if(dmabuf->type == CS_TYPE_DAC)
+	if (dmabuf->type == CS_TYPE_DAC)
 		dmabuf->divisor = 1;
-	else if( !(dmabuf->fmt & CS_FMT_STEREO) && 
+	else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
 	    (dmabuf->fmt & CS_FMT_16BIT))
 		dmabuf->divisor = 2;
-	else if( (dmabuf->fmt & CS_FMT_STEREO) && 
+	else if ((dmabuf->fmt & CS_FMT_STEREO) &&
 	    !(dmabuf->fmt & CS_FMT_16BIT))
 		dmabuf->divisor = 2;
-	else if( !(dmabuf->fmt & CS_FMT_STEREO) && 
+	else if (!(dmabuf->fmt & CS_FMT_STEREO) &&
 	    !(dmabuf->fmt & CS_FMT_16BIT))
 		dmabuf->divisor = 4;
 	else
@@ -680,13 +673,12 @@
 */
 static void cs_mute(struct cs_card *card, int state) 
 {
-	struct ac97_codec *dev=card->ac97_codec[0];
+	struct ac97_codec *dev = card->ac97_codec[0];
 
 	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: cs_mute()+ %s\n",
-		(state == CS_TRUE) ? "Muting" : "UnMuting") );
+		(state == CS_TRUE) ? "Muting" : "UnMuting"));
 
-	if(state == CS_TRUE)
-	{
+	if (state == CS_TRUE) {
 	/*
 	* fix pops when powering up on thinkpads
 	*/
@@ -703,9 +695,7 @@
 		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, 0x8000);
 		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
 		cs_ac97_set(dev, (u8)BA0_AC97_PCM_OUT_VOLUME, 0x8000);
-	}
-	else
-	{
+	} else {
 		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME, card->pm.u32AC97_master_volume);
 		cs_ac97_set(dev, (u8)BA0_AC97_HEADPHONE_VOLUME, card->pm.u32AC97_headphone_volume);
 		cs_ac97_set(dev, (u8)BA0_AC97_MASTER_VOLUME_MONO, card->pm.u32AC97_master_volume_mono);
@@ -757,7 +747,6 @@
 	/*
 	 *  Fill in the SampleRateConverter control block.
 	 */
-	 
 	spin_lock_irqsave(&state->card->lock, flags);
 	cs461x_poke(state->card, BA1_PSRC,
 	  ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
@@ -770,7 +759,7 @@
 }
 
 /* set recording sample rate */
-static unsigned int cs_set_adc_rate(struct cs_state * state, unsigned int rate)
+static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
 	struct cs_card *card = state->card;
@@ -815,7 +804,6 @@
 	 * 	    dividend:remainder(ulOther / GOF_PER_SEC)
 	 *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
 	 */
-
 	tmp1 = rate << 16;
 	coeffIncr = tmp1 / 48000;
 	tmp1 -= coeffIncr * 48000;
@@ -891,7 +879,7 @@
 
 	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") );
         cs461x_poke(card, BA1_PVOL, 0x80008000);
-        if(!dmabuf->SGok)
+        if (!dmabuf->SGok)
                cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf));
     
         Count = 4;                                                          
@@ -899,16 +887,14 @@
         if ((dmabuf->fmt & CS_FMT_STEREO)) {                                
                 playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO;                 
                 Count *= 2;                                                 
-        }                                                                   
-        else                                                                
+        } else
                 playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO;                  
                                                                             
         if ((dmabuf->fmt & CS_FMT_16BIT)) {                                 
                 playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT                    
                            | DMA_RQ_C2_AC_SIGNED_CONVERT);                  
                 Count *= 2;                                                 
-        }                                                                   
-        else                                                                
+        } else
                 playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT                     
                            | DMA_RQ_C2_AC_SIGNED_CONVERT);                  
                                                                             
@@ -919,7 +905,6 @@
         cs461x_poke(card, BA1_PDTC, tmp | --Count);                         
 
 	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") );
-
 }
 
 static struct InitStruct
@@ -944,8 +929,7 @@
 {
 	unsigned i, offset;
 	CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") );
-	for(i=0; i<sizeof(InitArray)/sizeof(struct InitStruct); i++)
-	{
+	for (i = 0; i < sizeof(InitArray) / sizeof(struct InitStruct); i++) {
 		offset = InitArray[i].off*4; /* 8bit to 32bit offset value */
 		cs461x_poke(card, offset, InitArray[i].val );
 	}
@@ -957,8 +941,8 @@
 {
 	struct cs_card *card = state->card;
 	struct dmabuf *dmabuf = &state->dmabuf;
-	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n") );
 
+	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n"));
 	SetCaptureSPValues(card);
 
 	/*
@@ -994,14 +978,11 @@
 	/*
 	 * granularity is byte boundary, good part.
 	 */
-	if(dmabuf->enable & DAC_RUNNING)
-	{
+	if (dmabuf->enable & DAC_RUNNING)
 		offset = cs461x_peek(state->card, BA1_PBA);                                  
-	}
 	else /* ADC_RUNNING must be set */
-	{
 		offset = cs461x_peek(state->card, BA1_CBA);                                  
-	}
+
 	CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9, 
 		printk("cs46xx: cs_get_dma_addr() %d\n",offset) );
 	offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf;
@@ -1015,8 +996,7 @@
 	struct dmabuf *dmabuf;
 	
 	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") );
-	if(state)
-	{
+	if (state) {
 		dmabuf = &state->dmabuf;
 		dmabuf->hwptr=dmabuf->swptr = 0;
 		dmabuf->pringbuf = 0;
@@ -1149,13 +1129,13 @@
 /*
 * check for order within limits, but do not overwrite value.
 */
-	if((defaultorder > 1) && (defaultorder < 12))
+	if ((defaultorder > 1) && (defaultorder < 12))
 		df = defaultorder;
 	else
 		df = 2;	
 
 	for (order = df; order >= DMABUF_MINORDER; order--)
-		if ( (rawbuf = (void *) pci_alloc_consistent(
+		if ((rawbuf = (void *)pci_alloc_consistent(
 			card->pci_dev, PAGE_SIZE << order, &dmabuf->dmaaddr)))
 			    break;
 	if (!rawbuf) {
@@ -1181,8 +1161,7 @@
 /*
 *  only allocate the conversion buffer for the ADC
 */
-	if(dmabuf->type == CS_TYPE_DAC)
-	{
+	if (dmabuf->type == CS_TYPE_DAC) {
 		dmabuf->tmpbuff = NULL;
 		dmabuf->buforder_tmpbuff = 0;
 		return 0;
@@ -1258,8 +1237,7 @@
 /*
  * check for CAPTURE and use only non-sg for initial release
  */
-	if(dmabuf->type == CS_TYPE_ADC)
-	{
+	if (dmabuf->type == CS_TYPE_ADC) {
 		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n"));
 		/* 
 		 * add in non-sg support for capture.
@@ -1313,9 +1291,7 @@
 
 		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n"));
 		return 0;
-	}
-	else if (dmabuf->type == CS_TYPE_DAC)
-	{
+	} else if (dmabuf->type == CS_TYPE_DAC) {
 	/*
 	 * Must be DAC
 	 */
@@ -1337,8 +1313,7 @@
 		allocated_pages = 1 << dmabuf->buforder;                            
 		allocated_bytes = allocated_pages*PAGE_SIZE;                        
 										    
-		if(allocated_pages < 2)                                             
-		{
+		if (allocated_pages < 2) {
 			CS_DBGOUT(CS_FUNCTION, 4, printk(
 			    "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n",
 				(unsigned)allocated_pages));
@@ -1353,14 +1328,14 @@
 										    
 		     /* Set up S/G variables. */
 		*ptmp = virt_to_bus(dmabuf->rawbuf);                                
-		*(ptmp+1) = 0x00000008;                                             
-		for(tmp1= 1; tmp1 < nSGpages; tmp1++) {                             
-			*(ptmp+2*tmp1) = virt_to_bus( (dmabuf->rawbuf)+4096*tmp1);  
-			if( tmp1 == nSGpages-1)                                     
+		*(ptmp + 1) = 0x00000008;
+		for (tmp1 = 1; tmp1 < nSGpages; tmp1++) {
+			*(ptmp + 2 * tmp1) = virt_to_bus((dmabuf->rawbuf) + 4096 * tmp1);
+			if (tmp1 == nSGpages - 1)
 				tmp2 = 0xbfff0000;
 			else                                                        
-				tmp2 = 0x80000000+8*(tmp1+1);                       
-			*(ptmp+2*tmp1+1) = tmp2;                                    
+				tmp2 = 0x80000000 + 8 * (tmp1 + 1);
+			*(ptmp + 2 * tmp1 + 1) = tmp2;
 		}                                                                   
 		SGarray[0] = 0x82c0200d;                                            
 		SGarray[1] = 0xffff0000;                                            
@@ -1368,18 +1343,17 @@
 		SGarray[3] = 0x00010600;                                            
 		SGarray[4] = *(ptmp+2);                                             
 		SGarray[5] = 0x80000010;                                            
-		SGarray[6] = *ptmp;                                                 
-		SGarray[7] = *(ptmp+2);                                             
-		SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10;        
+		SGarray[6] = *ptmp;
+		SGarray[7] = *(ptmp+2);
+		SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10;
 
-		if (dmabuf->SGok) {                                                 
-			dmabuf->numfrag = nSGpages;                                 
-			dmabuf->fragsize = 4096;                                    
-			dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt];    
-			dmabuf->fragshift = 12;                                     
-			dmabuf->dmasize = dmabuf->numfrag*4096;                     
-		}                                                                   
-		else {                                                              
+		if (dmabuf->SGok) {
+			dmabuf->numfrag = nSGpages;
+			dmabuf->fragsize = 4096;
+			dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt];
+			dmabuf->fragshift = 12;
+			dmabuf->dmasize = dmabuf->numfrag * 4096;
+		} else {
 			SGarray[0] = 0xf2c0000f;                                    
 			SGarray[1] = 0x00000200;                                    
 			SGarray[2] = 0;                                             
@@ -1391,8 +1365,8 @@
 			dmabuf->dmasize = 4096;                                     
 			dmabuf->fragshift = 11;                                     
 		}
-		for(tmp1 = 0; tmp1 < sizeof(SGarray)/4; tmp1++)                     
-			cs461x_poke( state->card, BA1_PDTC+tmp1*4, SGarray[tmp1]);  
+		for (tmp1 = 0; tmp1 < sizeof(SGarray) / 4; tmp1++)
+			cs461x_poke(state->card, BA1_PDTC+tmp1 * 4, SGarray[tmp1]);
 
 		memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
 		       dmabuf->dmasize);
@@ -1416,9 +1390,7 @@
 
 		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n"));
 		return 0;
-	}
-	else
-	{
+	} else {
 		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n",
 			dmabuf->type));
 	}
@@ -1489,8 +1461,7 @@
 	}
 	remove_wait_queue(&dmabuf->wait, &wait);
 	current->state = TASK_RUNNING;
-	if (signal_pending(current))
-	{
+	if (signal_pending(current)) {
 		CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: drain_dac()- -ERESTARTSYS\n"));
 		/*
 		* set to silence and let that clear the fifos.
@@ -1514,8 +1485,7 @@
 
 	/* error handling and process wake up for ADC */
 	state = card->states[0];
-	if(state)
-	{
+	if (state) {
 		dmabuf = &state->dmabuf;
 		if (dmabuf->enable & ADC_RUNNING) {
 			/* update hardware pointer */
@@ -1531,12 +1501,10 @@
 			if (dmabuf->count > dmabuf->dmasize)
 				dmabuf->count = dmabuf->dmasize;
 
-			if(dmabuf->mapped)
-			{
+			if (dmabuf->mapped) {
 				if (wake && dmabuf->count >= (signed)dmabuf->fragsize)
 					wake_up(&dmabuf->wait);
-			} else 
-			{
+			} else {
 				if (wake && dmabuf->count > 0)
 					wake_up(&dmabuf->wait);
 			}
@@ -1547,8 +1515,7 @@
  * Now the DAC
  */
 	state = card->states[1];
-	if(state)
-	{
+	if (state) {
 		dmabuf = &state->dmabuf;
 		/* error handling and process wake up for DAC */
 		if (dmabuf->enable & DAC_RUNNING) {
@@ -1570,7 +1537,7 @@
 				 * in that, since dmasize is the buffer asked for
 				 * via mmap.
 				 */
-				if( dmabuf->count > dmabuf->dmasize)
+				if (dmabuf->count > dmabuf->dmasize)
 					dmabuf->count &= dmabuf->dmasize-1;
 			} else {
 				dmabuf->count -= diff;
@@ -1578,13 +1545,10 @@
 				 * backfill with silence and clear out the last 
 				 * "diff" number of bytes.
 				 */
-				if(hwptr >= diff)
-				{
+				if (hwptr >= diff) {
 					memset(dmabuf->rawbuf + hwptr - diff, 
 						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff);
-				}
-				else
-				{
+				} else {
 					memset(dmabuf->rawbuf, 
 						(dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80,
 						(unsigned)hwptr);
@@ -1602,12 +1566,12 @@
 					* buffer underrun or buffer overrun, reset the
 					* count of bytes written back to 0.
 					*/
-					if(dmabuf->count < 0)
-						dmabuf->underrun=1;
+					if (dmabuf->count < 0)
+						dmabuf->underrun = 1;
 					dmabuf->count = 0;
 					dmabuf->error++;
 				}
-				if (wake && dmabuf->count < (signed)dmabuf->dmasize/2)
+				if (wake && dmabuf->count < (signed)dmabuf->dmasize / 2)
 					wake_up(&dmabuf->wait);
 			}
 		}
@@ -1661,8 +1625,7 @@
 
 	status = cs461x_peekBA0(card, BA0_HISR);
 	
-	if ((status & 0x7fffffff) == 0)
-	{
+	if ((status & 0x7fffffff) == 0) {
 		cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);
 		spin_unlock(&card->lock);
 		return IRQ_HANDLED;	/* Might be IRQ_NONE.. */
@@ -1671,15 +1634,14 @@
 	/*
 	 * check for playback or capture interrupt only
 	 */
-	if( ((status & HISR_VC0) && playstate && playstate->dmabuf.ready) || 
-	    (((status & HISR_VC1) && recstate && recstate->dmabuf.ready)) )
-	{
+	if (((status & HISR_VC0) && playstate && playstate->dmabuf.ready) ||
+	    (((status & HISR_VC1) && recstate && recstate->dmabuf.ready))) {
 		CS_DBGOUT(CS_INTERRUPT, 8, printk(
 			"cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status));
 		cs_update_ptr(card, CS_TRUE);
 	}
 
-        if( status & HISR_MIDI )
+        if (status & HISR_MIDI)
                 cs_handle_midi(card);
 	
  	/* clear 'em */
@@ -1694,7 +1656,7 @@
 
 static ssize_t cs_midi_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-        struct cs_card *card = (struct cs_card *)file->private_data;
+        struct cs_card *card = file->private_data;
         ssize_t ret;
         unsigned long flags;
         unsigned ptr;
@@ -1737,7 +1699,7 @@
 
 static ssize_t cs_midi_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-        struct cs_card *card = (struct cs_card *)file->private_data;
+        struct cs_card *card = file->private_data;
         ssize_t ret;
         unsigned long flags;
         unsigned ptr;
@@ -1785,7 +1747,7 @@
 
 static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait)
 {
-        struct cs_card *card = (struct cs_card *)file->private_data;
+        struct cs_card *card = file->private_data;
         unsigned long flags;
         unsigned int mask = 0;
 
@@ -1810,12 +1772,11 @@
 static int cs_midi_open(struct inode *inode, struct file *file)
 {
         unsigned int minor = iminor(inode);
-        struct cs_card *card=NULL;
+        struct cs_card *card = NULL;
         unsigned long flags;
 	struct list_head *entry;
 
-	list_for_each(entry, &cs46xx_devs)
-	{
+	list_for_each(entry, &cs46xx_devs) {
 		card = list_entry(entry, struct cs_card, list);
 		if (card->dev_midi == minor)
 			break;
@@ -1823,8 +1784,7 @@
 
 	if (entry == &cs46xx_devs)
 		return -ENODEV;
-	if (!card)
-	{
+	if (!card) {
 		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
 			"cs46xx: cs46xx_midi_open(): Error - unable to find card struct\n"));
 		return -ENODEV;
@@ -1852,12 +1812,10 @@
                 cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f);            /* Enable xmit, rcv. */
                 cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);   /* Enable interrupts */
         }
-        if (file->f_mode & FMODE_READ) {
+        if (file->f_mode & FMODE_READ)
                 card->midi.ird = card->midi.iwr = card->midi.icnt = 0;
-        }
-        if (file->f_mode & FMODE_WRITE) {
+        if (file->f_mode & FMODE_WRITE)
                 card->midi.ord = card->midi.owr = card->midi.ocnt = 0;
-        }
         spin_unlock_irqrestore(&card->midi.lock, flags);
         card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE));
         mutex_unlock(&card->midi.open_mutex);
@@ -1867,7 +1825,7 @@
 
 static int cs_midi_release(struct inode *inode, struct file *file)
 {
-        struct cs_card *card = (struct cs_card *)file->private_data;
+        struct cs_card *card = file->private_data;
         DECLARE_WAITQUEUE(wait, current);
         unsigned long flags;
         unsigned count, tmo;
@@ -1933,11 +1891,10 @@
 static void CopySamples(char *dst, char *src, int count, unsigned fmt, 
 		struct dmabuf *dmabuf)
 {
-
     s32 s32AudioSample;
-    s16 *psSrc=(s16 *)src;
-    s16 *psDst=(s16 *)dst;
-    u8 *pucDst=(u8 *)dst;
+    s16 *psSrc = (s16 *)src;
+    s16 *psDst = (s16 *)dst;
+    u8 *pucDst = (u8 *)dst;
 
     CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: CopySamples()+ ") );
     CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
@@ -1947,34 +1904,29 @@
     /*
      * See if the data should be output as 8-bit unsigned stereo.
      */
-    if((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))
-    {
+    if ((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
         /*
          * Convert each 16-bit signed stereo sample to 8-bit unsigned 
 	 * stereo using rounding.
          */
         psSrc = (s16 *)src;
-	count = count/2;
-        while(count--)
-        {
+	count = count / 2;
+        while (count--)
             *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8);
-        }
     }
     /*
      * See if the data should be output at 8-bit unsigned mono.
      */
-    else if(!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))
-    {
+    else if (!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) {
         /*
          * Convert each 16-bit signed stereo sample to 8-bit unsigned 
 	 * mono using averaging and rounding.
          */
         psSrc = (s16 *)src;
-	count = count/2;
-        while(count--)
-        {
-	    s32AudioSample = ((*psSrc)+(*(psSrc + 1)))/2 + (s32)0x80;
-	    if(s32AudioSample > 0x7fff)
+	count = count / 2;
+        while (count--) {
+	    s32AudioSample = ((*psSrc) + (*(psSrc + 1))) / 2 + (s32)0x80;
+	    if (s32AudioSample > 0x7fff)
 	    	s32AudioSample = 0x7fff;
             *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8);
 	    psSrc += 2;
@@ -1983,17 +1935,15 @@
     /*
      * See if the data should be output at 16-bit signed mono.
      */
-    else if(!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT))
-    {
+    else if (!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT)) {
         /*
          * Convert each 16-bit signed stereo sample to 16-bit signed 
 	 * mono using averaging.
          */
         psSrc = (s16 *)src;
-	count = count/2;
-        while(count--)
-        {
-            *(psDst++) = (s16)((*psSrc)+(*(psSrc + 1)))/2;
+	count = count / 2;
+        while (count--) {
+            *(psDst++) = (s16)((*psSrc) + (*(psSrc + 1))) / 2;
 	    psSrc += 2;
         }
     }
@@ -2020,20 +1970,15 @@
 		"cs_copy_to_user()+ fmt=0x%x cnt=%d dest=%p\n",
 		dmabuf->fmt,(unsigned)cnt,dest) );
 
-	if(cnt > dmabuf->dmasize)
-	{
+	if (cnt > dmabuf->dmasize)
 		cnt = dmabuf->dmasize;
-	}
-	if(!cnt)
-	{
+	if (!cnt) {
 		*copied = 0;
 		return 0;
 	}
-	if(dmabuf->divisor != 1)
-	{
-		if(!dmabuf->tmpbuff)
-		{
-			*copied = cnt/dmabuf->divisor;
+	if (dmabuf->divisor != 1) {
+		if (!dmabuf->tmpbuff) {
+			*copied = cnt / dmabuf->divisor;
 			return 0;
 		}
 
@@ -2042,17 +1987,16 @@
 		src = dmabuf->tmpbuff;
 		cnt = cnt/dmabuf->divisor;
 	}
-        if (copy_to_user(dest, src, cnt))
-	{
+        if (copy_to_user(dest, src, cnt)) {
 		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR 
 			"cs46xx: cs_copy_to_user()- fault dest=%p src=%p cnt=%d\n",
-				dest,src,cnt) );
+				dest,src,cnt));
 		*copied = 0;
 		return -EFAULT;
 	}
 	*copied = cnt;
 	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO 
-		"cs46xx: cs_copy_to_user()- copied bytes is %d \n",cnt) );
+		"cs46xx: cs_copy_to_user()- copied bytes is %d \n",cnt));
 	return 0;
 }
 
@@ -2060,7 +2004,7 @@
    the user's buffer.  it is filled by the dma machine and drained by this loop. */
 static ssize_t cs_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct cs_card *card = (struct cs_card *) file->private_data;
+	struct cs_card *card = file->private_data;
 	struct cs_state *state;
 	DECLARE_WAITQUEUE(wait, current);
 	struct dmabuf *dmabuf;
@@ -2068,12 +2012,12 @@
 	unsigned long flags;
 	unsigned swptr;
 	int cnt;
-	unsigned copied=0;
+	unsigned copied = 0;
 
 	CS_DBGOUT(CS_WAVE_READ | CS_FUNCTION, 4, 
 		printk("cs46xx: cs_read()+ %zd\n",count) );
-	state = (struct cs_state *)card->states[0];
-	if(!state)
+	state = card->states[0];
+	if (!state)
 		return -ENODEV;
 	dmabuf = &state->dmabuf;
 
@@ -2088,11 +2032,11 @@
 
 	add_wait_queue(&state->dmabuf.wait, &wait);
 	while (count > 0) {
-		while(!(card->pm.flags & CS46XX_PM_IDLE))
-		{
+		while (!(card->pm.flags & CS46XX_PM_IDLE)) {
 			schedule();
 			if (signal_pending(current)) {
-				if(!ret) ret = -ERESTARTSYS;
+				if (!ret)
+					ret = -ERESTARTSYS;
 				goto out;
 			}
 		}
@@ -2112,19 +2056,20 @@
 			   recorded */
 			start_adc(state);
 			if (file->f_flags & O_NONBLOCK) {
-				if (!ret) ret = -EAGAIN;
+				if (!ret)
+					ret = -EAGAIN;
 				goto out;
  			}
 			mutex_unlock(&state->sem);
 			schedule();
 			if (signal_pending(current)) {
-				if(!ret) ret = -ERESTARTSYS;
+				if (!ret)
+					ret = -ERESTARTSYS;
 				goto out;
 			}
 			mutex_lock(&state->sem);
-			if (dmabuf->mapped) 
-			{
-				if(!ret)
+			if (dmabuf->mapped) {
+				if (!ret)
 					ret = -ENXIO;
 				goto out;
 			}
@@ -2135,12 +2080,12 @@
 			"_read() copy_to cnt=%d count=%zd ", cnt,count) );
 		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO 
 			" .dmasize=%d .count=%d buffer=%p ret=%zd\n",
-			dmabuf->dmasize,dmabuf->count,buffer,ret) );
+			dmabuf->dmasize,dmabuf->count,buffer,ret));
 
                 if (cs_copy_to_user(state, buffer, 
-			(char *)dmabuf->rawbuf + swptr, cnt, &copied))
-		{
-			if (!ret) ret = -EFAULT;
+			(char *)dmabuf->rawbuf + swptr, cnt, &copied)) {
+			if (!ret)
+				ret = -EFAULT;
 			goto out;
 		}
                 swptr = (swptr + cnt) % dmabuf->dmasize;
@@ -2167,7 +2112,7 @@
    the soundcard.  it is drained by the dma machine and filled by this loop. */
 static ssize_t cs_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct cs_card *card = (struct cs_card *) file->private_data;
+	struct cs_card *card = file->private_data;
 	struct cs_state *state;
 	DECLARE_WAITQUEUE(wait, current);
 	struct dmabuf *dmabuf;
@@ -2178,16 +2123,15 @@
 
 	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4,
 		printk("cs46xx: cs_write called, count = %zd\n", count) );
-	state = (struct cs_state *)card->states[1];
-	if(!state)
+	state = card->states[1];
+	if (!state)
 		return -ENODEV;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
 	dmabuf = &state->dmabuf;
 
 	mutex_lock(&state->sem);
-	if (dmabuf->mapped)
-	{
+	if (dmabuf->mapped) {
 		ret = -ENXIO;
 		goto out;
 	}
@@ -2201,11 +2145,11 @@
 * check for PM events and underrun/overrun in the loop.
 */
 	while (count > 0) {
-		while(!(card->pm.flags & CS46XX_PM_IDLE))
-		{
+		while (!(card->pm.flags & CS46XX_PM_IDLE)) {
 			schedule();
 			if (signal_pending(current)) {
-				if(!ret) ret = -ERESTARTSYS;
+				if (!ret)
+					ret = -ERESTARTSYS;
 				goto out;
 			}
 		}
@@ -2216,8 +2160,7 @@
 			dmabuf->count = 0;
 			dmabuf->swptr = dmabuf->hwptr;
 		}
-		if (dmabuf->underrun)
-		{
+		if (dmabuf->underrun) {
 			dmabuf->underrun = 0;
 			dmabuf->hwptr = cs_get_dma_addr(state);
 			dmabuf->swptr = dmabuf->hwptr;
@@ -2238,34 +2181,35 @@
 			   played */
 			start_dac(state);
 			if (file->f_flags & O_NONBLOCK) {
-				if (!ret) ret = -EAGAIN;
+				if (!ret)
+					ret = -EAGAIN;
 				goto out;
  			}
 			mutex_unlock(&state->sem);
 			schedule();
  			if (signal_pending(current)) {
-				if(!ret) ret = -ERESTARTSYS;
+				if (!ret)
+					ret = -ERESTARTSYS;
 				goto out;
  			}
 			mutex_lock(&state->sem);
-			if (dmabuf->mapped)
-			{
-				if(!ret)
+			if (dmabuf->mapped) {
+				if (!ret)
 					ret = -ENXIO;
 				goto out;
 			}
  			continue;
  		}
 		if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
-			if (!ret) ret = -EFAULT;
+			if (!ret)
+				ret = -EFAULT;
 			goto out;
 		}
 		spin_lock_irqsave(&state->card->lock, flags);
 		swptr = (swptr + cnt) % dmabuf->dmasize;
 		dmabuf->swptr = swptr;
 		dmabuf->count += cnt;
-		if(dmabuf->count > dmabuf->dmasize)
-		{
+		if (dmabuf->count > dmabuf->dmasize) {
 			CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk(
 			    "cs46xx: cs_write() d->count > dmasize - resetting\n"));
 			dmabuf->count = dmabuf->dmasize;
@@ -2284,38 +2228,32 @@
 	set_current_state(TASK_RUNNING);
 
 	CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, 
-		printk("cs46xx: cs_write()- ret=%zd\n", ret) );
+		printk("cs46xx: cs_write()- ret=%zd\n", ret));
 	return ret;
 }
 
 static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait)
 {
-	struct cs_card *card = (struct cs_card *)file->private_data;
+	struct cs_card *card = file->private_data;
 	struct dmabuf *dmabuf;
 	struct cs_state *state;
-
 	unsigned long flags;
 	unsigned int mask = 0;
 
 	CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n"));
-	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ)))
-	{
+	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) {
 		return -EINVAL;
 	}
-	if (file->f_mode & FMODE_WRITE)
-	{
+	if (file->f_mode & FMODE_WRITE) {
 		state = card->states[1];
-		if(state)
-		{
+		if (state) {
 			dmabuf = &state->dmabuf;
 			poll_wait(file, &dmabuf->wait, wait);
 		}
 	}
-	if (file->f_mode & FMODE_READ)
-	{
+	if (file->f_mode & FMODE_READ) {
 		state = card->states[0];
-		if(state)
-		{
+		if (state) {
 			dmabuf = &state->dmabuf;
 			poll_wait(file, &dmabuf->wait, wait);
 		}
@@ -2325,8 +2263,7 @@
 	cs_update_ptr(card, CS_FALSE);
 	if (file->f_mode & FMODE_READ) {
 		state = card->states[0];
-		if(state)
-		{
+		if (state) {
 			dmabuf = &state->dmabuf;
 			if (dmabuf->count >= (signed)dmabuf->fragsize)
 				mask |= POLLIN | POLLRDNORM;
@@ -2334,8 +2271,7 @@
 	}
 	if (file->f_mode & FMODE_WRITE) {
 		state = card->states[1];
-		if(state)
-		{
+		if (state) {
 			dmabuf = &state->dmabuf;
 			if (dmabuf->mapped) {
 				if (dmabuf->count >= (signed)dmabuf->fragsize)
@@ -2364,7 +2300,7 @@
  
 static int cs_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	struct cs_card *card = (struct cs_card *)file->private_data;
+	struct cs_card *card = file->private_data;
 	struct cs_state *state;
 	struct dmabuf *dmabuf;
 	int ret = 0;
@@ -2376,8 +2312,7 @@
 
 	if (vma->vm_flags & VM_WRITE) {
 		state = card->states[1];
-		if(state)
-		{
+		if (state) {
 			CS_DBGOUT(CS_OPEN, 2, printk(
 			  "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") );
 			if ((ret = prog_dmabuf(state)) != 0)
@@ -2385,8 +2320,7 @@
 		}
 	} else if (vma->vm_flags & VM_READ) {
 		state = card->states[0];
-		if(state)
-		{
+		if (state) {
 			CS_DBGOUT(CS_OPEN, 2, printk(
 			  "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") );
 			if ((ret = prog_dmabuf(state)) != 0)
@@ -2414,8 +2348,7 @@
 
 	mutex_lock(&state->sem);
 	dmabuf = &state->dmabuf;
-	if (cs4x_pgoff(vma) != 0)
-	{
+	if (cs4x_pgoff(vma) != 0) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -2423,15 +2356,13 @@
 
 	CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) );
 
-	if (size > (PAGE_SIZE << dmabuf->buforder))
-	{
+	if (size > (PAGE_SIZE << dmabuf->buforder)) {
 		ret = -EINVAL;
 		goto out;
 	}
 	if (remap_pfn_range(vma, vma->vm_start,
 			     virt_to_phys(dmabuf->rawbuf) >> PAGE_SHIFT,
-			     size, vma->vm_page_prot))
-	{
+			     size, vma->vm_page_prot)) {
 		ret = -EAGAIN;
 		goto out;
 	}
@@ -2445,25 +2376,24 @@
 
 static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-	struct cs_card *card = (struct cs_card *)file->private_data;
+	struct cs_card *card = file->private_data;
 	struct cs_state *state;
-	struct dmabuf *dmabuf=NULL;
+	struct dmabuf *dmabuf = NULL;
 	unsigned long flags;
 	audio_buf_info abinfo;
 	count_info cinfo;
-	int val, valsave, mapped, ret;
+	int val, valsave, ret;
+	int mapped = 0;
 	void __user *argp = (void __user *)arg;
 	int __user *p = argp;
 
-	state = (struct cs_state *)card->states[0];
-	if(state)
-	{
+	state = card->states[0];
+	if (state) {
 		dmabuf = &state->dmabuf;
 		mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped;
 	}
-	state = (struct cs_state *)card->states[1];
-	if(state)
-	{
+	state = card->states[1];
+	if (state) {
 		dmabuf = &state->dmabuf;
 		mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped;
 	}
@@ -2472,17 +2402,14 @@
 	printioctl(cmd);
 #endif
 
-	switch (cmd) 
-	{
+	switch (cmd) {
 	case OSS_GETVERSION:
 		return put_user(SOUND_VERSION, p);
-
 	case SNDCTL_DSP_RESET:
 		/* FIXME: spin_lock ? */
 		if (file->f_mode & FMODE_WRITE) {
-			state = (struct cs_state *)card->states[1];
-			if(state)
-			{
+			state = card->states[1];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				stop_dac(state);
 				synchronize_irq(card->irq);
@@ -2495,9 +2422,8 @@
 			}
 		}
 		if (file->f_mode & FMODE_READ) {
-			state = (struct cs_state *)card->states[0];
-			if(state)
-			{
+			state = card->states[0];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				stop_adc(state);
 				synchronize_irq(card->irq);
@@ -2511,20 +2437,17 @@
 		}
 		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") );
 		return 0;
-
 	case SNDCTL_DSP_SYNC:
 		if (file->f_mode & FMODE_WRITE)
 			return drain_dac(state, file->f_flags & O_NONBLOCK);
 		return 0;
-
 	case SNDCTL_DSP_SPEED: /* set sample rate */
 		if (get_user(val, p))
 			return -EFAULT;
 		if (val >= 0) {
 			if (file->f_mode & FMODE_READ) {
-				state = (struct cs_state *)card->states[0];
-				if(state)
-				{
+				state = card->states[0];
+				if (state) {
 					dmabuf = &state->dmabuf;
 					stop_adc(state);
 					dmabuf->ready = 0;
@@ -2534,9 +2457,8 @@
 				}
 			}
 			if (file->f_mode & FMODE_WRITE) {
-				state = (struct cs_state *)card->states[1];
-				if(state)
-				{
+				state = card->states[1];
+				if (state) {
 					dmabuf = &state->dmabuf;
 					stop_dac(state);
 					dmabuf->ready = 0;
@@ -2553,19 +2475,17 @@
 			return put_user(dmabuf->rate, p);
 		}
 		return put_user(0, p);
-
 	case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
 		if (get_user(val, p))
 			return -EFAULT;
 		if (file->f_mode & FMODE_WRITE) {
-			state = (struct cs_state *)card->states[1];
-			if(state)
-			{
+			state = card->states[1];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				stop_dac(state);
 				dmabuf->ready = 0;
 				dmabuf->SGok = 0;
-				if(val)
+				if (val)
 					dmabuf->fmt |= CS_FMT_STEREO;
 				else
 					dmabuf->fmt &= ~CS_FMT_STEREO;
@@ -2577,14 +2497,13 @@
 			}
 		}
 		if (file->f_mode & FMODE_READ) {
-			state = (struct cs_state *)card->states[0];
-			if(state)
-			{
+			state = card->states[0];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				stop_adc(state);
 				dmabuf->ready = 0;
 				dmabuf->SGok = 0;
-				if(val)
+				if (val)
 					dmabuf->fmt |= CS_FMT_STEREO;
 				else
 					dmabuf->fmt &= ~CS_FMT_STEREO;
@@ -2596,12 +2515,10 @@
 			}
 		}
 		return 0;
-
 	case SNDCTL_DSP_GETBLKSIZE:
 		if (file->f_mode & FMODE_WRITE) {
-			state = (struct cs_state *)card->states[1];
-			if(state)
-			{
+			state = card->states[1];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				if ((val = prog_dmabuf(state)))
 					return val;
@@ -2609,9 +2526,8 @@
 			}
 		}
 		if (file->f_mode & FMODE_READ) {
-			state = (struct cs_state *)card->states[0];
-			if(state)
-			{
+			state = card->states[0];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				if ((val = prog_dmabuf(state)))
 					return val;
@@ -2620,10 +2536,8 @@
 			}
 		}
 		return put_user(0, p);
-
 	case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
 		return put_user(AFMT_S16_LE | AFMT_U8, p);
-
 	case SNDCTL_DSP_SETFMT: /* Select sample format */
 		if (get_user(val, p))
 			return -EFAULT;
@@ -2635,88 +2549,75 @@
 			val == AFMT_U8 ? "8Bit Unsigned" : "") );
 		valsave = val;
 		if (val != AFMT_QUERY) {
-			if(val==AFMT_S16_LE || val==AFMT_U8)
-			{
+			if (val==AFMT_S16_LE || val==AFMT_U8) {
 				if (file->f_mode & FMODE_WRITE) {
-					state = (struct cs_state *)card->states[1];
-					if(state)
-					{
+					state = card->states[1];
+					if (state) {
 						dmabuf = &state->dmabuf;
 						stop_dac(state);
 						dmabuf->ready = 0;
 						dmabuf->SGok = 0;
-						if(val==AFMT_S16_LE)
+						if (val == AFMT_S16_LE)
 							dmabuf->fmt |= CS_FMT_16BIT;
 						else
 							dmabuf->fmt &= ~CS_FMT_16BIT;
 						cs_set_divisor(dmabuf);
-						if((ret = prog_dmabuf(state)))
+						if ((ret = prog_dmabuf(state)))
 							return ret;
 					}
 				}
 				if (file->f_mode & FMODE_READ) {
 					val = valsave;
-					state = (struct cs_state *)card->states[0];
-					if(state)
-					{
+					state = card->states[0];
+					if (state) {
 						dmabuf = &state->dmabuf;
 						stop_adc(state);
 						dmabuf->ready = 0;
 						dmabuf->SGok = 0;
-						if(val==AFMT_S16_LE)
+						if (val == AFMT_S16_LE)
 							dmabuf->fmt |= CS_FMT_16BIT;
 						else
 							dmabuf->fmt &= ~CS_FMT_16BIT;
 						cs_set_divisor(dmabuf);
-						if((ret = prog_dmabuf(state)))
+						if ((ret = prog_dmabuf(state)))
 							return ret;
 					}
 				}
-			}
-			else
-			{
+			} else {
 				CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk(
 				    "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n",
 					valsave) );
 			}
-		}
-		else
-		{
-			if(file->f_mode & FMODE_WRITE)
-			{
-				state = (struct cs_state *)card->states[1];
-				if(state)
+		} else {
+			if (file->f_mode & FMODE_WRITE) {
+				state = card->states[1];
+				if (state)
 					dmabuf = &state->dmabuf;
-			}
-			else if(file->f_mode & FMODE_READ)
-			{
-				state = (struct cs_state *)card->states[0];
-				if(state)
+			} else if (file->f_mode & FMODE_READ) {
+				state = card->states[0];
+				if (state)
 					dmabuf = &state->dmabuf;
 			}
 		}
-		if(dmabuf)
-		{
-			if(dmabuf->fmt & CS_FMT_16BIT)
+		if (dmabuf) {
+			if (dmabuf->fmt & CS_FMT_16BIT)
 				return put_user(AFMT_S16_LE, p);
 			else
 				return put_user(AFMT_U8, p);
 		}
 		return put_user(0, p);
-
 	case SNDCTL_DSP_CHANNELS:
 		if (get_user(val, p))
 			return -EFAULT;
 		if (val != 0) {
 			if (file->f_mode & FMODE_WRITE) {
-				state = (struct cs_state *)card->states[1];
-				if(state)
-				{
+				state = card->states[1];
+				if (state) {
 					dmabuf = &state->dmabuf;
 					stop_dac(state);
 					dmabuf->ready = 0;
 					dmabuf->SGok = 0;
-					if(val>1)
+					if (val > 1)
 						dmabuf->fmt |= CS_FMT_STEREO;
 					else
 						dmabuf->fmt &= ~CS_FMT_STEREO;
@@ -2726,14 +2627,13 @@
 				}
 			}
 			if (file->f_mode & FMODE_READ) {
-				state = (struct cs_state *)card->states[0];
-				if(state)
-				{
+				state = card->states[0];
+				if (state) {
 					dmabuf = &state->dmabuf;
 					stop_adc(state);
 					dmabuf->ready = 0;
 					dmabuf->SGok = 0;
-					if(val>1)
+					if (val > 1)
 						dmabuf->fmt |= CS_FMT_STEREO;
 					else
 						dmabuf->fmt &= ~CS_FMT_STEREO;
@@ -2745,19 +2645,16 @@
 		}
 		return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
 				p);
-
 	case SNDCTL_DSP_POST:
 		/*
 		 * There will be a longer than normal pause in the data.
 		 * so... do nothing, because there is nothing that we can do.
 		 */
 		return 0;
-
 	case SNDCTL_DSP_SUBDIVIDE:
 		if (file->f_mode & FMODE_WRITE) {
-			state = (struct cs_state *)card->states[1];
-			if(state)
-			{
+			state = card->states[1];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				if (dmabuf->subdivision)
 					return -EINVAL;
@@ -2769,9 +2666,8 @@
 			}
 		}
 		if (file->f_mode & FMODE_READ) {
-			state = (struct cs_state *)card->states[0];
-			if(state)
-			{
+			state = card->states[0];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				if (dmabuf->subdivision)
 					return -EINVAL;
@@ -2783,37 +2679,31 @@
 			}
 		}
 		return 0;
-
 	case SNDCTL_DSP_SETFRAGMENT:
 		if (get_user(val, p))
 			return -EFAULT;
-
 		if (file->f_mode & FMODE_WRITE) {
-			state = (struct cs_state *)card->states[1];
-			if(state)
-			{
+			state = card->states[1];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				dmabuf->ossfragshift = val & 0xffff;
 				dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
 			}
 		}
 		if (file->f_mode & FMODE_READ) {
-			state = (struct cs_state *)card->states[0];
-			if(state)
-			{
+			state = card->states[0];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				dmabuf->ossfragshift = val & 0xffff;
 				dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
 			}
 		}
 		return 0;
-
 	case SNDCTL_DSP_GETOSPACE:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
-		state = (struct cs_state *)card->states[1];
-		if(state)
-		{
+		state = card->states[1];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			spin_lock_irqsave(&state->card->lock, flags);
 			cs_update_ptr(card, CS_TRUE);
@@ -2832,13 +2722,11 @@
 			return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
 		}
 		return -ENODEV;
-
 	case SNDCTL_DSP_GETISPACE:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
-		state = (struct cs_state *)card->states[0];
-		if(state)
-		{
+		state = card->states[0];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			spin_lock_irqsave(&state->card->lock, flags);
 			cs_update_ptr(card, CS_TRUE);
@@ -2850,48 +2738,39 @@
 			return copy_to_user(argp, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
 		}
 		return -ENODEV;
-
 	case SNDCTL_DSP_NONBLOCK:
 		file->f_flags |= O_NONBLOCK;
 		return 0;
-
 	case SNDCTL_DSP_GETCAPS:
 		return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
 			    p);
-
 	case SNDCTL_DSP_GETTRIGGER:
 		val = 0;
 		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") );
-		if (file->f_mode & FMODE_WRITE)
-		{
-			state = (struct cs_state *)card->states[1];
-			if(state)
-			{
+		if (file->f_mode & FMODE_WRITE) {
+			state = card->states[1];
+			if (state) {
 				dmabuf = &state->dmabuf;
-				if(dmabuf->enable & DAC_RUNNING)
+				if (dmabuf->enable & DAC_RUNNING)
 					val |= PCM_ENABLE_INPUT;
 			}
 		}
-		if (file->f_mode & FMODE_READ)
-		{
-			if(state)
-			{
-				state = (struct cs_state *)card->states[0];
+		if (file->f_mode & FMODE_READ) {
+			if (state) {
+				state = card->states[0];
 				dmabuf = &state->dmabuf;
-				if(dmabuf->enable & ADC_RUNNING)
+				if (dmabuf->enable & ADC_RUNNING)
 					val |= PCM_ENABLE_OUTPUT;
 			}
 		}
 		CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) );
 		return put_user(val, p);
-
 	case SNDCTL_DSP_SETTRIGGER:
 		if (get_user(val, p))
 			return -EFAULT;
 		if (file->f_mode & FMODE_READ) {
-			state = (struct cs_state *)card->states[0];
-			if(state)
-			{
+			state = card->states[0];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				if (val & PCM_ENABLE_INPUT) {
 					if (!dmabuf->ready && (ret = prog_dmabuf(state)))
@@ -2902,9 +2781,8 @@
 			}
 		}
 		if (file->f_mode & FMODE_WRITE) {
-			state = (struct cs_state *)card->states[1];
-			if(state)
-			{
+			state = card->states[1];
+			if (state) {
 				dmabuf = &state->dmabuf;
 				if (val & PCM_ENABLE_OUTPUT) {
 					if (!dmabuf->ready && (ret = prog_dmabuf(state)))
@@ -2915,13 +2793,11 @@
 			}
 		}
 		return 0;
-
 	case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
 			return -EINVAL;
-		state = (struct cs_state *)card->states[0];
-		if(state)
-		{
+		state = card->states[0];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			spin_lock_irqsave(&state->card->lock, flags);
 			cs_update_ptr(card, CS_TRUE);
@@ -2934,28 +2810,23 @@
 			return 0;
 		}
 		return -ENODEV;
-
 	case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
-		state = (struct cs_state *)card->states[1];
-		if(state)
-		{
+		state = card->states[1];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			spin_lock_irqsave(&state->card->lock, flags);
 			cs_update_ptr(card, CS_TRUE);
 			cinfo.bytes = dmabuf->total_bytes;
-			if (dmabuf->mapped)
-			{
+			if (dmabuf->mapped) {
 				cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift) 
 							- dmabuf->blocks;
 				CS_DBGOUT(CS_PARMS, 8, 
 					printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n", 
 					cinfo.bytes,cinfo.blocks,dmabuf->blocks) );
 				dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift;
-			}
-			else
-			{
+			} else {
 				cinfo.blocks = dmabuf->count >> dmabuf->fragshift;
 			}
 			cinfo.ptr = dmabuf->hwptr;
@@ -2969,66 +2840,54 @@
 			return 0;
 		}
 		return -ENODEV;
-
 	case SNDCTL_DSP_SETDUPLEX:
 		return 0;
-
 	case SNDCTL_DSP_GETODELAY:
 		if (!(file->f_mode & FMODE_WRITE))
 			return -EINVAL;
-		state = (struct cs_state *)card->states[1];
-		if(state)
-		{
+		state = card->states[1];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			spin_lock_irqsave(&state->card->lock, flags);
 			cs_update_ptr(card, CS_TRUE);
 			val = dmabuf->count;
 			spin_unlock_irqrestore(&state->card->lock, flags);
-		}
-		else
+		} else
 			val = 0;
 		return put_user(val, p);
-
 	case SOUND_PCM_READ_RATE:
-		if(file->f_mode & FMODE_READ)
-			state = (struct cs_state *)card->states[0];
+		if (file->f_mode & FMODE_READ)
+			state = card->states[0];
 		else 
-			state = (struct cs_state *)card->states[1];
-		if(state)
-		{
+			state = card->states[1];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			return put_user(dmabuf->rate, p);
 		}
 		return put_user(0, p);
-		
-
 	case SOUND_PCM_READ_CHANNELS:
-		if(file->f_mode & FMODE_READ)
-			state = (struct cs_state *)card->states[0];
+		if (file->f_mode & FMODE_READ)
+			state = card->states[0];
 		else 
-			state = (struct cs_state *)card->states[1];
-		if(state)
-		{
+			state = card->states[1];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1,
 				p);
 		}
 		return put_user(0, p);
-
 	case SOUND_PCM_READ_BITS:
-		if(file->f_mode & FMODE_READ)
-			state = (struct cs_state *)card->states[0];
+		if (file->f_mode & FMODE_READ)
+			state = card->states[0];
 		else 
-			state = (struct cs_state *)card->states[1];
-		if(state)
-		{
+			state = card->states[1];
+		if (state) {
 			dmabuf = &state->dmabuf;
 			return put_user((dmabuf->fmt & CS_FMT_16BIT) ? 
 			  	AFMT_S16_LE : AFMT_U8, p);
 
 		}
 		return put_user(0, p);
-
 	case SNDCTL_DSP_MAPINBUF:
 	case SNDCTL_DSP_MAPOUTBUF:
 	case SNDCTL_DSP_SETSYNCRO:
@@ -3057,18 +2916,15 @@
 	/* Manage the EAPD bit on the Crystal 4297 
 	   and the Analog AD1885 */
 	   
-	int old=card->amplifier;
+	int old = card->amplifier;
 	
 	card->amplifier+=change;
-	if(card->amplifier && !old)
-	{
+	if (card->amplifier && !old) {
 		/* Turn the EAPD amp on */
 		cs_ac97_set(card->ac97_codec[0],  AC97_POWER_CONTROL, 
 			cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) |
 				0x8000);
-	}
-	else if(old && !card->amplifier)
-	{
+	} else if(old && !card->amplifier) {
 		/* Turn the EAPD amp off */
 		cs_ac97_set(card->ac97_codec[0],  AC97_POWER_CONTROL, 
 			cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) &
@@ -3083,25 +2939,21 @@
  
 static void amp_hercules(struct cs_card *card, int change)
 {
-	int old=card->amplifier;
-	if(!card)
-	{
+	int old = card->amplifier;
+	if (!card) {
 		CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO 
 			"cs46xx: amp_hercules() called before initialized.\n"));
 		return;
 	}
 	card->amplifier+=change;
-	if( (card->amplifier && !old) && !(hercules_egpio_disable))
-	{
+	if ((card->amplifier && !old) && !(hercules_egpio_disable)) {
 		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
 			"cs46xx: amp_hercules() external amp enabled\n"));
 		cs461x_pokeBA0(card, BA0_EGPIODR, 
 			EGPIODR_GPOE2);     /* enable EGPIO2 output */
 		cs461x_pokeBA0(card, BA0_EGPIOPTR, 
 			EGPIOPTR_GPPT2);   /* open-drain on output */
-	}
-	else if(old && !card->amplifier)
-	{
+	} else if (old && !card->amplifier) {
 		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO 
 			"cs46xx: amp_hercules() external amp disabled\n"));
 		cs461x_pokeBA0(card, BA0_EGPIODR, 0); /* disable */
@@ -3124,31 +2976,28 @@
 	u16 control;
 	u8 pp;
 	unsigned long port;
-	int old=card->active;
+	int old = card->active;
 	
 	card->active+=change;
 	
 	acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
-	if(acpi_dev == NULL)
+	if (acpi_dev == NULL)
 		return;		/* Not a thinkpad thats for sure */
 
 	/* Find the control port */		
 	pci_read_config_byte(acpi_dev, 0x41, &pp);
-	port=pp<<8;
+	port = pp << 8;
 
 	/* Read ACPI port */	
-	control=inw(port+0x10);
+	control = inw(port + 0x10);
 
 	/* Flip CLKRUN off while running */
-	if(!card->active && old)
-	{
+	if (!card->active && old) {
 		CS_DBGOUT(CS_PARMS , 9, printk( KERN_INFO
 			"cs46xx: clkrun() enable clkrun - change=%d active=%d\n",
 				change,card->active));
 		outw(control|0x2000, port+0x10);
-	}
-	else 
-	{
+	} else {
 	/*
 	* sometimes on a resume the bit is set, so always reset the bit.
 	*/
@@ -3162,20 +3011,19 @@
 	
 static int cs_open(struct inode *inode, struct file *file)
 {
-	struct cs_card *card = (struct cs_card *)file->private_data;
+	struct cs_card *card = file->private_data;
 	struct cs_state *state = NULL;
 	struct dmabuf *dmabuf = NULL;
 	struct list_head *entry;
         unsigned int minor = iminor(inode);
-	int ret=0;
+	int ret = 0;
 	unsigned int tmp;
 
 	CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=%p %s %s\n",
 		file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
 		file->f_mode & FMODE_READ ? "FMODE_READ" : "") );
 
-	list_for_each(entry, &cs46xx_devs)
-	{
+	list_for_each(entry, &cs46xx_devs) {
 		card = list_entry(entry, struct cs_card, list);
 
 		if (!((card->dev_audio ^ minor) & ~0xf))
@@ -3192,11 +3040,10 @@
 	/*
 	 * hardcode state[0] for capture, [1] for playback
 	 */
-	if(file->f_mode & FMODE_READ)
-	{
+	if (file->f_mode & FMODE_READ) {
 		CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") );
 		if (card->states[0] == NULL) {
-			state = card->states[0] = (struct cs_state *)
+			state = card->states[0] =
 				kmalloc(sizeof(struct cs_state), GFP_KERNEL);
 			if (state == NULL)
 				return -ENOMEM;
@@ -3204,36 +3051,32 @@
 			mutex_init(&state->sem);
 			dmabuf = &state->dmabuf;
 			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-			if(dmabuf->pbuf==NULL)
-			{
+			if (dmabuf->pbuf == NULL) {
 				kfree(state);
-				card->states[0]=NULL;
+				card->states[0] = NULL;
 				return -ENOMEM;
 			}
-		}
-		else
-		{
+		} else {
 			state = card->states[0];
-			if(state->open_mode & FMODE_READ)
+			if (state->open_mode & FMODE_READ)
 				return -EBUSY;
 		}
 		dmabuf->channel = card->alloc_rec_pcm_channel(card);
 			
 		if (dmabuf->channel == NULL) {
-			kfree (card->states[0]);
+			kfree(card->states[0]);
 			card->states[0] = NULL;
 			return -ENODEV;
 		}
 
 		/* Now turn on external AMP if needed */
 		state->card = card;
-		state->card->active_ctrl(state->card,1);
-		state->card->amplifier_ctrl(state->card,1);
+		state->card->active_ctrl(state->card, 1);
+		state->card->amplifier_ctrl(state->card, 1);
 		
-		if( (tmp = cs46xx_powerup(card, CS_POWER_ADC)) )
-		{
+		if ((tmp = cs46xx_powerup(card, CS_POWER_ADC))) {
 			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs46xx_powerup of ADC failed (0x%x)\n",tmp) );
+				"cs46xx: cs46xx_powerup of ADC failed (0x%x)\n", tmp));
 			return -EIO;
 		}
 
@@ -3263,11 +3106,10 @@
 		state->open_mode |= FMODE_READ;
 		mutex_unlock(&state->open_mutex);
 	}
-	if(file->f_mode & FMODE_WRITE)
-	{
+	if (file->f_mode & FMODE_WRITE) {
 		CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") );
 		if (card->states[1] == NULL) {
-			state = card->states[1] = (struct cs_state *)
+			state = card->states[1] =
 				kmalloc(sizeof(struct cs_state), GFP_KERNEL);
 			if (state == NULL)
 				return -ENOMEM;
@@ -3275,36 +3117,32 @@
 			mutex_init(&state->sem);
 			dmabuf = &state->dmabuf;
 			dmabuf->pbuf = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
-			if(dmabuf->pbuf==NULL)
-			{
+			if (dmabuf->pbuf == NULL) {
 				kfree(state);
-				card->states[1]=NULL;
+				card->states[1] = NULL;
 				return -ENOMEM;
 			}
-		}
-		else
-		{
+		} else {
 			state = card->states[1];
-			if(state->open_mode & FMODE_WRITE)
+			if (state->open_mode & FMODE_WRITE)
 				return -EBUSY;
 		}
 		dmabuf->channel = card->alloc_pcm_channel(card);
 			
 		if (dmabuf->channel == NULL) {
-			kfree (card->states[1]);
+			kfree(card->states[1]);
 			card->states[1] = NULL;
 			return -ENODEV;
 		}
 
 		/* Now turn on external AMP if needed */
 		state->card = card;
-		state->card->active_ctrl(state->card,1);
-		state->card->amplifier_ctrl(state->card,1);
+		state->card->active_ctrl(state->card, 1);
+		state->card->amplifier_ctrl(state->card, 1);
 
-		if( (tmp = cs46xx_powerup(card, CS_POWER_DAC)) )
-		{
+		if ((tmp = cs46xx_powerup(card, CS_POWER_DAC))) {
 			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs46xx_powerup of DAC failed (0x%x)\n",tmp) );
+				"cs46xx: cs46xx_powerup of DAC failed (0x%x)\n", tmp));
 			return -EIO;
 		}
 		
@@ -3333,33 +3171,29 @@
 
 		state->open_mode |= FMODE_WRITE;
 		mutex_unlock(&state->open_mutex);
-		if((ret = prog_dmabuf(state)))
+		if ((ret = prog_dmabuf(state)))
 			return ret;
 	}
-	CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n") );
+	CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n"));
 	return nonseekable_open(inode, file);
 }
 
 static int cs_release(struct inode *inode, struct file *file)
 {
-	struct cs_card *card = (struct cs_card *)file->private_data;
+	struct cs_card *card = file->private_data;
 	struct dmabuf *dmabuf;
 	struct cs_state *state;
 	unsigned int tmp;
 	CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=%p %s %s\n",
 		file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "",
-		file->f_mode & FMODE_READ ? "FMODE_READ" : "") );
+		file->f_mode & FMODE_READ ? "FMODE_READ" : ""));
 
 	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ)))
-	{
 		return -EINVAL;
-	}
 	state = card->states[1];
-	if(state)
-	{
-		if ( (state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE) )
-		{
-			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n") );
+	if (state) {
+		if ((state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE)) {
+			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n"));
 			dmabuf = &state->dmabuf;
 			cs_clear_tail(state);
 			drain_dac(state, file->f_flags & O_NONBLOCK);
@@ -3375,8 +3209,7 @@
 			state->card->states[state->virt] = NULL;
 			state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
 
-			if( (tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE )) )
-			{
+			if ((tmp = cs461x_powerdown(card, CS_POWER_DAC, CS_FALSE))) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
 					"cs46xx: cs_release_mixdev() powerdown DAC failure (0x%x)\n",tmp) );
 			}
@@ -3384,17 +3217,14 @@
 			/* Now turn off external AMP if needed */
 			state->card->amplifier_ctrl(state->card, -1);
 			state->card->active_ctrl(state->card, -1);
-
 			kfree(state);
 		}
 	}
 
 	state = card->states[0];
-	if(state)
-	{
-		if ( (state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ) )
-		{
-			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n") );
+	if (state) {
+		if ((state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ)) {
+			CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n"));
 			dmabuf = &state->dmabuf;
 			mutex_lock(&state->open_mutex);
 			stop_adc(state);
@@ -3407,8 +3237,7 @@
 			state->card->states[state->virt] = NULL;
 			state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
 
-			if( (tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE )) )
-			{
+			if ((tmp = cs461x_powerdown(card, CS_POWER_ADC, CS_FALSE))) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
 					"cs46xx: cs_release_mixdev() powerdown ADC failure (0x%x)\n",tmp) );
 			}
@@ -3416,12 +3245,11 @@
 			/* Now turn off external AMP if needed */
 			state->card->amplifier_ctrl(state->card, -1);
 			state->card->active_ctrl(state->card, -1);
-
 			kfree(state);
 		}
 	}
 
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n") );
+	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n"));
 	return 0;
 }
 
@@ -3474,21 +3302,18 @@
 
 	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()+\n"));
 
-	if(card->states[1])
-	{
+	if (card->states[1]) {
 		stop_dac(card->states[1]);
 		resync_dma_ptrs(card->states[1]);
 	}
-	if(card->states[0])
-	{
+	if (card->states[0]) {
 		stop_adc(card->states[0]);
 		resync_dma_ptrs(card->states[0]);
 	}
 
-	for(Count = 0x2, i=0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE)
-			&& (i < CS46XX_AC97_NUMBER_RESTORE_REGS); 
-		Count += 2, i++)
-	{
+	for (Count = 0x2, i = 0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE)
+			&& (i < CS46XX_AC97_NUMBER_RESTORE_REGS);
+			Count += 2, i++) {
 		card->pm.ac97[i] = cs_ac97_get(dev, BA0_AC97_RESET + Count);
 	}
 /*
@@ -3522,11 +3347,10 @@
 * well, for now, only power down the DAC/ADC and MIXER VREFON components. 
 * trouble with removing VREF.
 */
-	if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-			CS_POWER_MIXVON, CS_TRUE )) )
-	{
+	if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
+			CS_POWER_MIXVON, CS_TRUE))) {
 		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp) );
+			"cs46xx: cs46xx_ac97_suspend() failure (0x%x)\n",tmp));
 	}
 
 	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_suspend()-\n"));
@@ -3566,16 +3390,13 @@
 * Restore just the first set of registers, from register number
 * 0x02 to the register number that ulHighestRegToRestore specifies.
 */
-	for(	Count = 0x2, i=0; 
-		(Count <= CS46XX_AC97_HIGHESTREGTORESTORE)
-			&& (i < CS46XX_AC97_NUMBER_RESTORE_REGS); 
-		Count += 2, i++)
-	{
+	for (Count = 0x2, i=0; (Count <= CS46XX_AC97_HIGHESTREGTORESTORE) &&
+			(i < CS46XX_AC97_NUMBER_RESTORE_REGS); Count += 2, i++) {
 		cs_ac97_set(dev, (u8)(BA0_AC97_RESET + Count), (u16)card->pm.ac97[i]);
 	}
 
 	/* Check if we have to init the amplifier */
-	if(card->amp_init)
+	if (card->amp_init)
 		card->amp_init(card);
         
 	CS_DBGOUT(CS_PM, 9, printk("cs46xx: cs46xx_ac97_resume()-\n"));
@@ -3585,30 +3406,27 @@
 static int cs46xx_restart_part(struct cs_card *card)
 {
 	struct dmabuf *dmabuf;
+
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
 		printk( "cs46xx: cs46xx_restart_part()+\n"));
-	if(card->states[1])
-	{
+	if (card->states[1]) {
 		dmabuf = &card->states[1]->dmabuf;
 		dmabuf->ready = 0;
 		resync_dma_ptrs(card->states[1]);
 		cs_set_divisor(dmabuf);
-		if(__prog_dmabuf(card->states[1]))
-		{
+		if (__prog_dmabuf(card->states[1])) {
 			CS_DBGOUT(CS_PM | CS_ERROR, 1, 
 				printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() dac error\n"));
 			return -1;
 		}
 		cs_set_dac_rate(card->states[1], dmabuf->rate);
 	}
-	if(card->states[0])
-	{
+	if (card->states[0]) {
 		dmabuf = &card->states[0]->dmabuf;
 		dmabuf->ready = 0;
 		resync_dma_ptrs(card->states[0]);
 		cs_set_divisor(dmabuf);
-		if(__prog_dmabuf(card->states[0]))
-		{
+		if (__prog_dmabuf(card->states[0])) {
 			CS_DBGOUT(CS_PM | CS_ERROR, 1, 
 				printk("cs46xx: cs46xx_restart_part()- (-1) prog_dmabuf() adc error\n"));
 			return -1;
@@ -3616,17 +3434,17 @@
 		cs_set_adc_rate(card->states[0], dmabuf->rate);
 	}
 	card->pm.flags |= CS46XX_PM_RESUMED;
-	if(card->states[0])
+	if (card->states[0])
 		start_adc(card->states[0]);
-	if(card->states[1])
+	if (card->states[1])
 		start_dac(card->states[1]);
 
 	card->pm.flags |= CS46XX_PM_IDLE;
 	card->pm.flags &= ~(CS46XX_PM_SUSPENDING | CS46XX_PM_SUSPENDED 
 			| CS46XX_PM_RESUMING | CS46XX_PM_RESUMED);
-	if(card->states[0])
+	if (card->states[0])
 		wake_up(&card->states[0]->dmabuf.wait);
-	if(card->states[1])
+	if (card->states[1])
 		wake_up(&card->states[1]->dmabuf.wait);
 
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
@@ -3634,20 +3452,19 @@
 	return 0;
 }
 
-
 static void cs461x_reset(struct cs_card *card);
 static void cs461x_proc_stop(struct cs_card *card);
 static int cs46xx_suspend(struct cs_card *card, pm_message_t state)
 {
 	unsigned int tmp;
+
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
 		printk("cs46xx: cs46xx_suspend()+ flags=0x%x s=%p\n",
 			(unsigned)card->pm.flags,card));
 /*
 * check the current state, only suspend if IDLE
 */
-	if(!(card->pm.flags & CS46XX_PM_IDLE))
-	{
+	if (!(card->pm.flags & CS46XX_PM_IDLE)) {
 		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
 			printk("cs46xx: cs46xx_suspend() unable to suspend, not IDLE\n"));
 		return 1;
@@ -3679,13 +3496,11 @@
 	tmp = cs461x_peek(card, BA1_CCTL);
 	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
 
-	if(card->states[1])
-	{
+	if (card->states[1]) {
 		card->pm.dmabuf_swptr_play = card->states[1]->dmabuf.swptr;
 		card->pm.dmabuf_count_play = card->states[1]->dmabuf.count;
 	}
-	if(card->states[0])
-	{
+	if (card->states[0]) {
 		card->pm.dmabuf_swptr_capture = card->states[0]->dmabuf.swptr;
 		card->pm.dmabuf_count_capture = card->states[0]->dmabuf.count;
 	}
@@ -3736,8 +3551,7 @@
 	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
 		printk( "cs46xx: cs46xx_resume()+ flags=0x%x\n",
 			(unsigned)card->pm.flags));
-	if(!(card->pm.flags & CS46XX_PM_SUSPENDED))
-	{
+	if (!(card->pm.flags & CS46XX_PM_SUSPENDED)) {
 		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
 			printk("cs46xx: cs46xx_resume() unable to resume, not SUSPENDED\n"));
 		return 1;
@@ -3747,10 +3561,8 @@
 	printpm(card);
 	card->active_ctrl(card, 1);
 
-	for(i=0;i<5;i++)
-	{
-		if (cs_hardware_init(card) != 0)
-		{
+	for (i = 0; i < 5; i++) {
+		if (cs_hardware_init(card) != 0) {
 			CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
 				"cs46xx: cs46xx_resume()- ERROR in cs_hardware_init()\n"));
 			mdelay(10 * cs_laptop_wait);
@@ -3759,15 +3571,13 @@
 		}
 		break;
 	}
-	if(i>=4)
-	{
+	if (i >= 4) {
 		CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
 			"cs46xx: cs46xx_resume()- cs_hardware_init() failed, retried %d times.\n",i));
 		return 0;
 	}
 
-	if(cs46xx_restart_part(card))
-	{
+	if (cs46xx_restart_part(card)) {
 		CS_DBGOUT(CS_PM | CS_ERROR, 4, printk(
 			"cs46xx: cs46xx_resume(): cs46xx_restart_part() returned error\n"));
 	}
@@ -3835,7 +3645,7 @@
 	/*
 	 *  Wait for the read to occur.
 	 */
-	if(!(card->pm.flags & CS46XX_PM_IDLE))
+	if (!(card->pm.flags & CS46XX_PM_IDLE))
 		loopcnt = 2000;
 	else
 		loopcnt = 500 * cs_laptop_wait;
@@ -3866,7 +3676,7 @@
 	 *  Wait for the valid status bit to go active.
 	 */
 
-	if(!(card->pm.flags & CS46XX_PM_IDLE))
+	if (!(card->pm.flags & CS46XX_PM_IDLE))
 		loopcnt = 2000;
 	else
 		loopcnt = 1000;
@@ -3885,7 +3695,7 @@
 	/*
 	 *  Make sure we got valid status.
 	 */
-	if (!( (tmp=cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) {
+	if (!((tmp = cs461x_peekBA0(card, BA0_ACSTS)) & ACSTS_VSTS)) {
 		CS_DBGOUT(CS_ERROR, 2, printk(KERN_WARNING 
 			"cs46xx: AC'97 read problem (ACSTS_VSTS), reg = 0x%x val=0x%x 0xffff \n", 
 				reg, tmp));
@@ -3923,12 +3733,9 @@
 	
 	spin_lock(&card->ac97_lock);
 	
-	if(reg == AC97_CD_VOL)
-	{
+	if (reg == AC97_CD_VOL)
 		val2 = _cs_ac97_get(dev, AC97_CD_VOL);
-	}
-	
-	
+
 	/*
 	 *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
 	 *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
@@ -3970,8 +3777,7 @@
 	/*
 	 *  Make sure the write completed.
 	 */
-	if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV)
-	{
+	if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) {
 		CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 			"cs46xx: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val));
 	}
@@ -3998,25 +3804,23 @@
 	 
 	/* CD mute change ? */
 	
-	if(reg==AC97_CD_VOL)
-	{
+	if (reg == AC97_CD_VOL) {
 		/* Mute bit change ? */
-		if((val2^val)&0x8000 || ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val))
-		{
+		if ((val2^val) & 0x8000 ||
+		    ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val)) {
 			/* This is a hack but its cleaner than the alternatives.
 			   Right now card->ac97_codec[0] might be NULL as we are
 			   still doing codec setup. This does an early assignment
 			   to avoid the problem if it occurs */
 			   
-			if(card->ac97_codec[0]==NULL)
-				card->ac97_codec[0]=dev;
+			if (card->ac97_codec[0] == NULL)
+				card->ac97_codec[0] = dev;
 				
 			/* Mute on */
-			if(val&0x8000 || val == 0x1f1f)
+			if (val & 0x8000 || val == 0x1f1f)
 				card->amplifier_ctrl(card, -1);
-			else /* Mute off power on */
-			{
-				if(card->amp_init)
+			else { /* Mute off power on */
+				if (card->amp_init)
 					card->amp_init(card);
 				card->amplifier_ctrl(card, 1);
 			}
@@ -4024,46 +3828,41 @@
 	}
 }
 
-
 /* OSS /dev/mixer file operation methods */
 
 static int cs_open_mixdev(struct inode *inode, struct file *file)
 {
-	int i=0;
+	int i = 0;
 	unsigned int minor = iminor(inode);
-	struct cs_card *card=NULL;
+	struct cs_card *card = NULL;
 	struct list_head *entry;
 	unsigned int tmp;
 
 	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
 		  printk(KERN_INFO "cs46xx: cs_open_mixdev()+\n"));
 
-	list_for_each(entry, &cs46xx_devs)
-	{
+	list_for_each(entry, &cs46xx_devs) {
 		card = list_entry(entry, struct cs_card, list);
 		for (i = 0; i < NR_AC97; i++)
 			if (card->ac97_codec[i] != NULL &&
 			    card->ac97_codec[i]->dev_mixer == minor)
 				goto match;
 	}
-	if (!card)
-	{
+	if (!card) {
 		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
 			printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
 		return -ENODEV;
 	}
  match:
-	if(!card->ac97_codec[i])
+	if (!card->ac97_codec[i])
 		return -ENODEV;
 	file->private_data = card->ac97_codec[i];
 
 	card->active_ctrl(card,1);
-	if(!CS_IN_USE(&card->mixer_use_cnt))
-	{
-		if( (tmp = cs46xx_powerup(card, CS_POWER_MIXVON )) )
-		{
+	if (!CS_IN_USE(&card->mixer_use_cnt)) {
+		if ((tmp = cs46xx_powerup(card, CS_POWER_MIXVON))) {
 			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs_open_mixdev() powerup failure (0x%x)\n",tmp) );
+				"cs46xx: cs_open_mixdev() powerup failure (0x%x)\n", tmp));
 			return -EIO;
 		}
 	}
@@ -4077,7 +3876,7 @@
 static int cs_release_mixdev(struct inode *inode, struct file *file)
 {
 	unsigned int minor = iminor(inode);
-	struct cs_card *card=NULL;
+	struct cs_card *card = NULL;
 	struct list_head *entry;
 	int i;
 	unsigned int tmp;
@@ -4092,15 +3891,13 @@
 			    card->ac97_codec[i]->dev_mixer == minor)
 				goto match;
 	}
-	if (!card)
-	{
+	if (!card) {
 		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
 			printk(KERN_INFO "cs46xx: cs46xx_open_mixdev()- -ENODEV\n"));
 		return -ENODEV;
 	}
 match:
-	if(!CS_DEC_AND_TEST(&card->mixer_use_cnt))
-	{
+	if (!CS_DEC_AND_TEST(&card->mixer_use_cnt)) {
 		CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 4,
 			  printk(KERN_INFO "cs46xx: cs_release_mixdev()- no powerdown, usecnt>0\n"));
 		card->active_ctrl(card, -1);
@@ -4110,10 +3907,9 @@
 /*
 * ok, no outstanding mixer opens, so powerdown.
 */
-	if( (tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE )) )
-	{
+	if ((tmp = cs461x_powerdown(card, CS_POWER_MIXVON, CS_FALSE))) {
 		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-			"cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n",tmp) );
+			"cs46xx: cs_release_mixdev() powerdown MIXVON failure (0x%x)\n", tmp));
 		card->active_ctrl(card, -1);
 		card->amplifier_ctrl(card, -1);
 		return -EIO;
@@ -4126,76 +3922,60 @@
 }
 
 static int cs_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
-				unsigned long arg)
+			unsigned long arg)
 {
-	struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
-	struct cs_card *card=NULL;
+	struct ac97_codec *codec = file->private_data;
+	struct cs_card *card = NULL;
 	struct list_head *entry;
 	unsigned long __user *p = (long __user *)arg;
-
 #if CSDEBUG_INTERFACE
         int val;
 
-	if( 	(cmd == SOUND_MIXER_CS_GETDBGMASK) || 
+	if (	(cmd == SOUND_MIXER_CS_GETDBGMASK) ||
 		(cmd == SOUND_MIXER_CS_SETDBGMASK) ||
 		(cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||
 		(cmd == SOUND_MIXER_CS_SETDBGLEVEL) ||
-		(cmd == SOUND_MIXER_CS_APM))
-	{
-	    switch(cmd)
-	    {
-
+		(cmd == SOUND_MIXER_CS_APM)) {
+		switch (cmd) {
 		case SOUND_MIXER_CS_GETDBGMASK:
 			return put_user(cs_debugmask, p);
-		
 		case SOUND_MIXER_CS_GETDBGLEVEL:
 			return put_user(cs_debuglevel, p);
-
 		case SOUND_MIXER_CS_SETDBGMASK:
 			if (get_user(val, p))
 				return -EFAULT;
 			cs_debugmask = val;
 			return 0;
-
 		case SOUND_MIXER_CS_SETDBGLEVEL:
 			if (get_user(val, p))
 				return -EFAULT;
 			cs_debuglevel = val;
 			return 0;
-
 		case SOUND_MIXER_CS_APM:
 			if (get_user(val, p))
 				return -EFAULT;
-			if(val == CS_IOCTL_CMD_SUSPEND) 
-			{
-				list_for_each(entry, &cs46xx_devs)
-				{
+			if (val == CS_IOCTL_CMD_SUSPEND) {
+				list_for_each(entry, &cs46xx_devs) {
 					card = list_entry(entry, struct cs_card, list);
 					cs46xx_suspend(card, PMSG_ON);
 				}
 
-			}
-			else if(val == CS_IOCTL_CMD_RESUME)
-			{
-				list_for_each(entry, &cs46xx_devs)
-				{
+			} else if (val == CS_IOCTL_CMD_RESUME) {
+				list_for_each(entry, &cs46xx_devs) {
 					card = list_entry(entry, struct cs_card, list);
 					cs46xx_resume(card);
 				}
-			}
-			else
-			{
+			} else {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
 				    "cs46xx: mixer_ioctl(): invalid APM cmd (%d)\n",
 					val));
 			}
 			return 0;
-
 		default:
 			CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO 
-				"cs46xx: mixer_ioctl(): ERROR unknown debug cmd\n") );
+				"cs46xx: mixer_ioctl(): ERROR unknown debug cmd\n"));
 			return 0;
-	    }
+		}
 	}
 #endif
 	return codec->mixer_ioctl(codec, cmd, arg);
@@ -4232,8 +4012,7 @@
 		codec->codec_read = cs_ac97_get;
 		codec->codec_write = cs_ac97_set;
 	
-		if (ac97_probe_codec(codec) == 0)
-		{
+		if (ac97_probe_codec(codec) == 0) {
 			CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
 				"cs46xx: cs_ac97_init()- codec number %d not found\n",
 					num_ac97) );
@@ -4241,12 +4020,11 @@
 			break;
 		}
 		CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, printk(KERN_INFO 
-			"cs46xx: cs_ac97_init() found codec %d\n",num_ac97) );
+			"cs46xx: cs_ac97_init() found codec %d\n",num_ac97));
 
 		eid = cs_ac97_get(codec, AC97_EXTENDED_ID);
 		
-		if(eid==0xFFFF)
-		{
+		if (eid == 0xFFFF) {
 			printk(KERN_WARNING "cs46xx: codec %d not present\n",num_ac97);
 			ac97_release_codec(codec);
 			break;
@@ -4285,27 +4063,23 @@
 {
     unsigned i, j, temp1, temp2, offset, count;
     unsigned char __iomem *pBA1 = ioremap(card->ba1_addr, 0x40000);
-    for( i=0; i < CLEAR__COUNT; i++)
-    {
+    for (i = 0; i < CLEAR__COUNT; i++) {
         offset = ClrStat[i].BA1__DestByteOffset;
         count  = ClrStat[i].BA1__SourceSize;
-        for(  temp1 = offset; temp1<(offset+count); temp1+=4 )
+        for (temp1 = offset; temp1 < (offset + count); temp1 += 4)
               writel(0, pBA1+temp1);
     }
 
-    for(i=0; i<FILL__COUNT; i++)
-    {
+    for (i = 0; i < FILL__COUNT; i++) {
         temp2 = FillStat[i].Offset;
-        for(j=0; j<(FillStat[i].Size)/4; j++)
-        {
+        for (j = 0; j < (FillStat[i].Size) / 4; j++) {
             temp1 = (FillStat[i]).pFill[j];
-            writel(temp1, pBA1+temp2+j*4);
+            writel(temp1, pBA1+temp2 + j * 4);
         }
     }
     iounmap(pBA1);
 }
 
-
 /*
  *  Chip reset
  */
@@ -4365,15 +4139,13 @@
 	* playing or capturing then we don't want to put in 128 bytes of
 	* "noise".
 	 */
-	if(type & CS_TYPE_DAC)
-	{
+	if (type & CS_TYPE_DAC) {
 		startfifo = 128;
 		endfifo = 256;
 	}
-	if(type & CS_TYPE_ADC)
-	{
+	if (type & CS_TYPE_ADC) {
 		startfifo = 0;
-		if(!endfifo)
+		if (!endfifo)
 			endfifo = 128;
 	}
 	/*
@@ -4417,8 +4189,7 @@
 
 	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
 		"cs46xx: cs461x_powerdown()+ type=0x%x\n",type));
-	if(!cs_powerdown && !suspendflag)
-	{
+	if (!cs_powerdown && !suspendflag) {
 		CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
 			"cs46xx: cs461x_powerdown() DISABLED exiting\n"));
 		return 0;
@@ -4432,12 +4203,11 @@
 * currently powered down.  If powering down DAC and ADC, then
 * it is possible to power down the VREF (ON).
 */
-	if (    ((type & CS_POWER_MIXVON) && 
-		 (!(type & CS_POWER_ADC) || (!(type & CS_POWER_DAC))) )
+	if (((type & CS_POWER_MIXVON) &&
+		 (!(type & CS_POWER_ADC) || (!(type & CS_POWER_DAC))))
 	      && 
 		((tmp & CS_AC97_POWER_CONTROL_ADC_ON) ||
-		 (tmp & CS_AC97_POWER_CONTROL_DAC_ON) ) )
-	{
+		 (tmp & CS_AC97_POWER_CONTROL_DAC_ON))) {
 		CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
 			"cs46xx: cs461x_powerdown()- 0  unable to powerdown. tmp=0x%x\n",tmp));
 		return 0;
@@ -4452,8 +4222,7 @@
 	/*
 	 *  Power down indicated areas.
 	 */
-	if(type & CS_POWER_MIXVOFF)
-	{
+	if (type & CS_POWER_MIXVOFF) {
 
 		CS_DBGOUT(CS_FUNCTION, 4, 
 			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVOFF\n"));
@@ -4461,12 +4230,10 @@
 		 *  Power down the MIXER (VREF ON) on the AC97 card.  
 		 */
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)
-		{
-			if(!muted)
-			{
+		if (tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp |= CS_AC97_POWER_CONTROL_MIXVOFF;
 			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
@@ -4492,16 +4259,14 @@
 			 *  Check the status..
 			 */
 			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVOFF_ON)
-			{
+				CS_AC97_POWER_CONTROL_MIXVOFF_ON) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerdown MIXVOFF failed\n"));
 				return 1;
 			}
 		}
 	}
-	if(type & CS_POWER_MIXVON)
-	{
+	if (type & CS_POWER_MIXVON) {
 
 		CS_DBGOUT(CS_FUNCTION, 4, 
 			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ MIXVON\n"));
@@ -4509,15 +4274,13 @@
 		 *  Power down the MIXER (VREF ON) on the AC97 card.  
 		 */
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)
-		{
-			if(!muted)
-			{
+		if (tmp & CS_AC97_POWER_CONTROL_MIXVON_ON) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp |= CS_AC97_POWER_CONTROL_MIXVON;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
+			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
 			/*
 			 *  Now, we wait until we sample a ready state.
 			 */
@@ -4540,30 +4303,26 @@
 			 *  Check the status..
 			 */
 			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVON_ON)
-			{
+				CS_AC97_POWER_CONTROL_MIXVON_ON) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerdown MIXVON failed\n"));
 				return 1;
 			}
 		}
 	}
-	if(type & CS_POWER_ADC)
-	{
+	if (type & CS_POWER_ADC) {
 		/*
 		 *  Power down the ADC on the AC97 card.  
 		 */
 		CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs461x_powerdown()+ ADC\n"));
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_ADC_ON)
-		{
-			if(!muted)
-			{
+		if (tmp & CS_AC97_POWER_CONTROL_ADC_ON) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp |= CS_AC97_POWER_CONTROL_ADC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
+			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
 
 			/*
 			 *  Now, we wait until we sample a ready state.
@@ -4587,16 +4346,14 @@
 			 *  Check the status..
 			 */
 			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_ADC_ON)
-			{
+				CS_AC97_POWER_CONTROL_ADC_ON) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerdown ADC failed\n"));
 				return 1;
 			}
 		}
 	}
-	if(type & CS_POWER_DAC)
-	{
+	if (type & CS_POWER_DAC) {
 		/*
 		 *  Power down the DAC on the AC97 card.  
 		 */
@@ -4604,15 +4361,13 @@
 		CS_DBGOUT(CS_FUNCTION, 4, 
 			printk(KERN_INFO "cs46xx: cs461x_powerdown()+ DAC\n"));
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (tmp & CS_AC97_POWER_CONTROL_DAC_ON)
-		{
-			if(!muted)
-			{
+		if (tmp & CS_AC97_POWER_CONTROL_DAC_ON) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp |= CS_AC97_POWER_CONTROL_DAC;
-			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
+			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp);
 			/*
 			 *  Now, we wait until we sample a ready state.
 			 */
@@ -4635,8 +4390,7 @@
 			 *  Check the status..
 			 */
 			if (cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_DAC_ON)
-			{
+				CS_AC97_POWER_CONTROL_DAC_ON) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerdown DAC failed\n"));
 				return 1;
@@ -4644,7 +4398,7 @@
 		}
 	}
 	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	if(muted)
+	if (muted)
 		cs_mute(card, CS_FALSE);
 	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
 		"cs46xx: cs461x_powerdown()- 0 tmp=0x%x\n",tmp));
@@ -4654,23 +4408,22 @@
 static int cs46xx_powerup(struct cs_card *card, unsigned int type)
 {
 	int count;
-	unsigned int tmp=0,muted=0;
+	unsigned int tmp = 0, muted = 0;
 
 	CS_DBGOUT(CS_FUNCTION, 8, printk(KERN_INFO 
 		"cs46xx: cs46xx_powerup()+ type=0x%x\n",type));
 	/*
 	* check for VREF and powerup if need to.
 	*/
-	if(type & CS_POWER_MIXVON)
+	if (type & CS_POWER_MIXVON)
 		type |= CS_POWER_MIXVOFF;
-	if(type & (CS_POWER_DAC | CS_POWER_ADC))
+	if (type & (CS_POWER_DAC | CS_POWER_ADC))
 		type |= CS_POWER_MIXVON | CS_POWER_MIXVOFF;
 
 	/*
 	 *  Power up indicated areas.
 	 */
-	if(type & CS_POWER_MIXVOFF)
-	{
+	if (type & CS_POWER_MIXVOFF) {
 
 		CS_DBGOUT(CS_FUNCTION, 4, 
 			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVOFF\n"));
@@ -4678,12 +4431,10 @@
 		 *  Power up the MIXER (VREF ON) on the AC97 card.  
 		 */
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON))
-		{
-			if(!muted)
-			{
+		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp &= ~CS_AC97_POWER_CONTROL_MIXVOFF;
 			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
@@ -4709,16 +4460,14 @@
 			 *  Check the status..
 			 */
 			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVOFF_ON))
-			{
+				CS_AC97_POWER_CONTROL_MIXVOFF_ON)) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerup MIXVOFF failed\n"));
 				return 1;
 			}
 		}
 	}
-	if(type & CS_POWER_MIXVON)
-	{
+	if(type & CS_POWER_MIXVON) {
 
 		CS_DBGOUT(CS_FUNCTION, 4, 
 			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ MIXVON\n"));
@@ -4726,12 +4475,10 @@
 		 *  Power up the MIXER (VREF ON) on the AC97 card.  
 		 */
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON))
-		{
-			if(!muted)
-			{
+		if (!(tmp & CS_AC97_POWER_CONTROL_MIXVON_ON)) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp &= ~CS_AC97_POWER_CONTROL_MIXVON;
 			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
@@ -4757,27 +4504,23 @@
 			 *  Check the status..
 			 */
 			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_MIXVON_ON))
-			{
+				CS_AC97_POWER_CONTROL_MIXVON_ON)) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerup MIXVON failed\n"));
 				return 1;
 			}
 		}
 	}
-	if(type & CS_POWER_ADC)
-	{
+	if (type & CS_POWER_ADC) {
 		/*
 		 *  Power up the ADC on the AC97 card.  
 		 */
 		CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO "cs46xx: cs46xx_powerup()+ ADC\n"));
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON))
-		{
-			if(!muted)
-			{
+		if (!(tmp & CS_AC97_POWER_CONTROL_ADC_ON)) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp &= ~CS_AC97_POWER_CONTROL_ADC;
 			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
@@ -4804,16 +4547,14 @@
 			 *  Check the status..
 			 */
 			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_ADC_ON))
-			{
+				CS_AC97_POWER_CONTROL_ADC_ON)) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerup ADC failed\n"));
 				return 1;
 			}
 		}
 	}
-	if(type & CS_POWER_DAC)
-	{
+	if (type & CS_POWER_DAC) {
 		/*
 		 *  Power up the DAC on the AC97 card.  
 		 */
@@ -4821,12 +4562,10 @@
 		CS_DBGOUT(CS_FUNCTION, 4, 
 			printk(KERN_INFO "cs46xx: cs46xx_powerup()+ DAC\n"));
 		tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-		if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON))
-		{
-			if(!muted)
-			{
+		if (!(tmp & CS_AC97_POWER_CONTROL_DAC_ON)) {
+			if (!muted) {
 				cs_mute(card, CS_TRUE);
-				muted=1;
+				muted = 1;
 			}
 			tmp &= ~CS_AC97_POWER_CONTROL_DAC;
 			cs_ac97_set(card->ac97_codec[0], AC97_POWER_CONTROL, tmp );
@@ -4852,8 +4591,7 @@
 			 *  Check the status..
 			 */
 			if (!(cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL) & 
-				CS_AC97_POWER_CONTROL_DAC_ON))
-			{
+				CS_AC97_POWER_CONTROL_DAC_ON)) {
 				CS_DBGOUT(CS_ERROR, 1, printk(KERN_WARNING 
 					"cs46xx: powerup DAC failed\n"));
 				return 1;
@@ -4861,14 +4599,13 @@
 		}
 	}
 	tmp = cs_ac97_get(card->ac97_codec[0], AC97_POWER_CONTROL);
-	if(muted)
+	if (muted)
 		cs_mute(card, CS_FALSE);
 	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO 
 		"cs46xx: cs46xx_powerup()- 0 tmp=0x%x\n",tmp));
 	return 0;
 }
 
-
 static void cs461x_proc_start(struct cs_card *card)
 {
 	int cnt;
@@ -4965,7 +4702,7 @@
 	* is not enough for some platforms! tested on an IBM Thinkpads and 
 	* reference cards.
 	*/
-	if(!(card->pm.flags & CS46XX_PM_IDLE))
+	if (!(card->pm.flags & CS46XX_PM_IDLE))
 		mdelay(initdelay);
 	/*
 	 *  Write the selected clock control setup to the hardware.  Do not turn on
@@ -5017,8 +4754,7 @@
 * If we are resuming under 2.2.x then we can not schedule a timeout.
 * so, just spin the CPU.
 */
-	if(card->pm.flags & CS46XX_PM_IDLE)
-	{
+	if (card->pm.flags & CS46XX_PM_IDLE) {
 	/*
 	 * Wait for the card ready signal from the AC97 card.
 	 */
@@ -5033,9 +4769,7 @@
 			current->state = TASK_UNINTERRUPTIBLE;
 			schedule_timeout(1);
 		} while (time_before(jiffies, end_time));
-	}
-	else
-	{
+	} else {
 		for (count = 0; count < 100; count++) {
 		// First, we want to wait for a short time.
 			udelay(25 * cs_laptop_wait);
@@ -5064,8 +4798,7 @@
 	 */
 	cs461x_pokeBA0(card, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
 
-	if(card->pm.flags & CS46XX_PM_IDLE)
-	{
+	if (card->pm.flags & CS46XX_PM_IDLE) {
 	/*
 	 *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
 	 *  the card is pumping ADC data across the AC-link.
@@ -5081,9 +4814,7 @@
 			current->state = TASK_UNINTERRUPTIBLE;
 			schedule_timeout(1);
 		} while (time_before(jiffies, end_time));
-	}
-	else
-	{
+	} else {
 		for (count = 0; count < 100; count++) {
 		// First, we want to wait for a short time.
 			udelay(25 * cs_laptop_wait);
@@ -5140,17 +4871,13 @@
 	cs461x_poke(card, BA1_CCTL, tmp & 0xffff0000);
 
 	/* initialize AC97 codec and register /dev/mixer */
-	if(card->pm.flags & CS46XX_PM_IDLE)
-	{
-		if (cs_ac97_init(card) <= 0)
-		{
+	if (card->pm.flags & CS46XX_PM_IDLE) {
+		if (cs_ac97_init(card) <= 0) {
 			CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
-				"cs46xx: cs_ac97_init() failure\n") );
+				"cs46xx: cs_ac97_init() failure\n"));
 			return -EIO;
 		}
-	}
-	else
-	{
+	} else {
 		cs46xx_ac97_resume(card);
 	}
 	
@@ -5174,23 +4901,17 @@
 	 *  If IDLE then Power down the part.  We will power components up 
 	 *  when we need them.  
 	 */
-	if(card->pm.flags & CS46XX_PM_IDLE)
-	{
-		if(!cs_powerdown)
-		{
-			if( (tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC |
-					CS_POWER_MIXVON )) )
-			{
+	if (card->pm.flags & CS46XX_PM_IDLE) {
+		if (!cs_powerdown) {
+			if ((tmp = cs46xx_powerup(card, CS_POWER_DAC | CS_POWER_ADC |
+					CS_POWER_MIXVON))) {
 				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
 					"cs46xx: cs461x_powerup() failure (0x%x)\n",tmp) );
 				return -EIO;
 			}
-		}
-		else
-		{
-			if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-					CS_POWER_MIXVON, CS_FALSE )) )
-			{
+		} else {
+			if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
+					CS_POWER_MIXVON, CS_FALSE))) {
 				CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
 					"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
 				return -EIO;
@@ -5310,14 +5031,13 @@
 MODULE_DESCRIPTION("Crystal SoundFusion Audio Support");
 MODULE_LICENSE("GPL");
 
-
 static const char cs46xx_banner[] = KERN_INFO "Crystal 4280/46xx + AC97 Audio, version " CS46XX_MAJOR_VERSION "." CS46XX_MINOR_VERSION "." CS46XX_ARCH ", " __TIME__ " " __DATE__ "\n";
 static const char fndmsg[] = KERN_INFO "cs46xx: Found %d audio device(s).\n";
 
 static int __devinit cs46xx_probe(struct pci_dev *pci_dev,
 				  const struct pci_device_id *pciid)
 {
-	int i,j;
+	int i, j;
 	u16 ss_card, ss_vendor;
 	struct cs_card *card;
 	dma_addr_t dma_mask;
@@ -5378,42 +5098,35 @@
 
 	while (cp->name)
 	{
-		if(cp->vendor == ss_vendor && cp->id == ss_card)
-		{
+		if (cp->vendor == ss_vendor && cp->id == ss_card) {
 			card->amplifier_ctrl = cp->amp;
-			if(cp->active)
+			if (cp->active)
 				card->active_ctrl = cp->active;
-			if(cp->amp_init)
+			if (cp->amp_init)
 				card->amp_init = cp->amp_init;
 			break;
 		}
 		cp++;
 	}
-	if (cp->name==NULL)
-	{
+	if (cp->name == NULL) {
 		printk(KERN_INFO "cs46xx: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
 			ss_vendor, ss_card, card->ba0_addr, card->ba1_addr,  card->irq);
-	}
-	else
-	{
+	} else {
 		printk(KERN_INFO "cs46xx: %s (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n",
 			cp->name, ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq);
 	}
 	
-	if (card->amplifier_ctrl==NULL)
-	{
+	if (card->amplifier_ctrl == NULL) {
 		card->amplifier_ctrl = amp_none;
 		card->active_ctrl = clkrun_hack;
 	}		
 
-	if (external_amp == 1)
-	{
+	if (external_amp == 1) {
 		printk(KERN_INFO "cs46xx: Crystal EAPD support forced on.\n");
 		card->amplifier_ctrl = amp_voyetra;
 	}
 
-	if (thinkpad == 1)
-	{
+	if (thinkpad == 1) {
 		printk(KERN_INFO "cs46xx: Activating CLKRUN hack for Thinkpad.\n");
 		card->active_ctrl = clkrun_hack;
 	}
@@ -5425,13 +5138,11 @@
 * and mdelay kernel code is replaced by a pm timer, or the delays
 * work well for battery and/or AC power both.
 */
-	if(card->active_ctrl == clkrun_hack)
-	{
+	if (card->active_ctrl == clkrun_hack) {
 		initdelay = 2100;
 		cs_laptop_wait = 5;
 	}
-	if((card->active_ctrl == clkrun_hack) && !(powerdown == 1))
-	{
+	if ((card->active_ctrl == clkrun_hack) && !(powerdown == 1)) {
 /*
 * for some currently unknown reason, powering down the DAC and ADC component
 * blocks on thinkpads causes some funky behavior... distoorrrtion and ac97 
@@ -5440,7 +5151,7 @@
 */
 		cs_powerdown = 0;
 	}
-	if(powerdown == 0)
+	if (powerdown == 0)
 		cs_powerdown = 0;
 	card->active_ctrl(card, 1);
 
@@ -5461,7 +5172,7 @@
 			card->ba1.name.pmem,
 			card->ba1.name.reg) );
 
-	if(card->ba0 == 0 || card->ba1.name.data0 == 0 ||
+	if (card->ba0 == 0 || card->ba1.name.data0 == 0 ||
 		card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 ||
 		card->ba1.name.reg == 0)
 		goto fail2;
@@ -5477,14 +5188,12 @@
 	}
 
         /* register /dev/midi */
-        if((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0)
+        if ((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0)
                 printk(KERN_ERR "cs46xx: unable to register midi\n");
                 
 	card->pm.flags |= CS46XX_PM_IDLE;
-	for(i=0;i<5;i++)
-	{
-		if (cs_hardware_init(card) != 0)
-		{
+	for (i = 0; i < 5; i++) {
+		if (cs_hardware_init(card) != 0) {
 			CS_DBGOUT(CS_ERROR, 4, printk(
 				"cs46xx: ERROR in cs_hardware_init()... retrying\n"));
 			for (j = 0; j < NR_AC97; j++)
@@ -5497,12 +5206,11 @@
 		}
 		break;
 	}
-	if(i>=4)
-	{
+	if(i >= 4) {
 		CS_DBGOUT(CS_PM | CS_ERROR, 1, printk(
 			"cs46xx: cs46xx_probe()- cs_hardware_init() failed, retried %d times.\n",i));
                 unregister_sound_dsp(card->dev_audio);
-                if(card->dev_midi)
+                if (card->dev_midi)
                         unregister_sound_midi(card->dev_midi);
                 goto fail;
 	}
@@ -5518,7 +5226,7 @@
 	* Check if we have to init the amplifier, but probably already done
 	* since the CD logic in the ac97 init code will turn on the ext amp.
 	*/
-	if(cp->amp_init)
+	if (cp->amp_init)
 		cp->amp_init(card);
         card->active_ctrl(card, -1);
 
@@ -5536,15 +5244,15 @@
 fail:
 	free_irq(card->irq, card);
 fail2:
-	if(card->ba0)
+	if (card->ba0)
 		iounmap(card->ba0);
-	if(card->ba1.name.data0)
+	if (card->ba1.name.data0)
 		iounmap(card->ba1.name.data0);
-	if(card->ba1.name.data1)
+	if (card->ba1.name.data1)
 		iounmap(card->ba1.name.data1);
-	if(card->ba1.name.pmem)
+	if (card->ba1.name.pmem)
 		iounmap(card->ba1.name.pmem);
-	if(card->ba1.name.reg)
+	if (card->ba1.name.reg)
 		iounmap(card->ba1.name.reg);
 	kfree(card);
 	CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO
@@ -5598,9 +5306,8 @@
 	 *  Power down the DAC and ADC.  We will power them up (if) when we need
 	 *  them.
 	 */
-	if( (tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
-			CS_POWER_MIXVON, CS_TRUE )) )
-	{
+	if ((tmp = cs461x_powerdown(card, CS_POWER_DAC | CS_POWER_ADC |
+			CS_POWER_MIXVON, CS_TRUE))) {
 		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_INFO 
 			"cs46xx: cs461x_powerdown() failure (0x%x)\n",tmp) );
 	}
@@ -5634,7 +5341,7 @@
 			ac97_release_codec(card->ac97_codec[i]);
 		}
 	unregister_sound_dsp(card->dev_audio);
-        if(card->dev_midi)
+        if (card->dev_midi)
                 unregister_sound_midi(card->dev_midi);
 	list_del(&card->list);
 	kfree(card);
@@ -5693,8 +5400,7 @@
 		"cs46xx: cs46xx_init_module()+ \n"));
 	rtn = pci_register_driver(&cs46xx_pci_driver);
 
-	if(rtn == -ENODEV)
-	{
+	if (rtn == -ENODEV) {
 		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk( 
 			"cs46xx: Unable to detect valid cs46xx device\n"));
 	}
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index 25ae8e4..8ac77df 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -45,7 +45,7 @@
 #include "../sound_config.h"
 #endif
 
-static DEFINE_SPINLOCK(midi_spinlock __attribute((unused)));
+static DEFINE_SPINLOCK(midi_spinlock);
 
 static void init_midi_hdr(struct midi_hdr *midihdr)
 {
diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c
index 5dbfc0f..ba38d62 100644
--- a/sound/oss/msnd.c
+++ b/sound/oss/msnd.c
@@ -47,7 +47,7 @@
 static multisound_dev_t		*devs[MSND_MAX_DEVS];
 static int			num_devs;
 
-int __init msnd_register(multisound_dev_t *dev)
+int msnd_register(multisound_dev_t *dev)
 {
 	int i;
 
diff --git a/sound/oss/sb_ess.c b/sound/oss/sb_ess.c
index fae05fe..180e95c 100644
--- a/sound/oss/sb_ess.c
+++ b/sound/oss/sb_ess.c
@@ -97,19 +97,19 @@
  *
  * The documentation is an adventure: it's close but not fully accurate. I
  * found out that after a reset some registers are *NOT* reset, though the
- * docs say the would be. Interresting ones are 0x7f, 0x7d and 0x7a. They are
- * related to the Audio 2 channel. I also was suprised about the consequenses
+ * docs say the would be. Interesting ones are 0x7f, 0x7d and 0x7a. They are
+ * related to the Audio 2 channel. I also was surprised about the consequences
  * of writing 0x00 to 0x7f (which should be done by reset): The ES1887 moves
  * into ES1888 mode. This means that it claims IRQ 11, which happens to be my
  * ISDN adapter. Needless to say it no longer worked. I now understand why
  * after rebooting 0x7f already was 0x05, the value of my choice: the BIOS
  * did it.
  *
- * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is decribed
- * as if it's exactly the same as register 0xa1. This is *NOT* true. The
- * description of 0x70 in ES1869 docs is accurate however.
+ * Oh, and this is another trap: in ES1887 docs mixer register 0x70 is
+ * described as if it's exactly the same as register 0xa1. This is *NOT* true.
+ * The description of 0x70 in ES1869 docs is accurate however.
  * Well, the assumption about ES1869 was wrong: register 0x70 is very much
- * like register 0xa1, except that bit 7 is allways 1, whatever you want
+ * like register 0xa1, except that bit 7 is always 1, whatever you want
  * it to be.
  *
  * When using audio 2 mixer register 0x72 seems te be meaningless. Only 0xa2
@@ -117,10 +117,10 @@
  *
  * Software reset not being able to reset all registers is great! Especially
  * the fact that register 0x78 isn't reset is great when you wanna change back
- * to single dma operation (simplex): audio 2 is still operation, and uses the
- * same dma as audio 1: your ess changes into a funny echo machine.
+ * to single dma operation (simplex): audio 2 is still operational, and uses
+ * the same dma as audio 1: your ess changes into a funny echo machine.
  *
- * Received the new that ES1688 is detected as a ES1788. Did some thinking:
+ * Received the news that ES1688 is detected as a ES1788. Did some thinking:
  * the ES1887 detection scheme suggests in step 2 to try if bit 3 of register
  * 0x64 can be changed. This is inaccurate, first I inverted the * check: "If
  * can be modified, it's a 1688", which lead to a correct detection
@@ -135,7 +135,7 @@
  * About recognition of ESS chips
  *
  * The distinction of ES688, ES1688, ES1788, ES1887 and ES1888 is described in
- * a (preliminary ??) datasheet on ES1887. It's aim is to identify ES1887, but
+ * a (preliminary ??) datasheet on ES1887. Its aim is to identify ES1887, but
  * during detection the text claims that "this chip may be ..." when a step
  * fails. This scheme is used to distinct between the above chips.
  * It appears however that some PnP chips like ES1868 are recognized as ES1788
@@ -156,9 +156,9 @@
  *
  * The existing ES1688 support didn't take care of the ES1688+ recording
  * levels very well. Whenever a device was selected (recmask) for recording
- * it's recording level was loud, and it couldn't be changed. The fact that
+ * its recording level was loud, and it couldn't be changed. The fact that
  * internal register 0xb4 could take care of RECLEV, didn't work meaning until
- * it's value was restored every time the chip was reset; this reset the
+ * its value was restored every time the chip was reset; this reset the
  * value of 0xb4 too. I guess that's what 4front also had (have?) trouble with.
  *
  * About ES1887 support:
@@ -169,9 +169,9 @@
  * the latter case the recording volumes are 0.
  * Now recording levels of inputs can be controlled, by changing the playback
  * levels. Futhermore several devices can be recorded together (which is not
- * possible with the ES1688.
+ * possible with the ES1688).
  * Besides the separate recording level control for each input, the common
- * recordig level can also be controlled by RECLEV as described above.
+ * recording level can also be controlled by RECLEV as described above.
  *
  * Not only ES1887 have this recording mixer. I know the following from the
  * documentation:
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
index 1a921ee7..29a6e0c 100644
--- a/sound/oss/via82cxxx_audio.c
+++ b/sound/oss/via82cxxx_audio.c
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
+#include <linux/poison.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
@@ -308,7 +309,7 @@
 	unsigned sixchannel: 1;	/* 8233/35 with 6 channel support */
 	unsigned volume: 1;
 
-	int locked_rate : 1;
+	unsigned locked_rate : 1;
 	
 	int mixer_vol;		/* 8233/35 volume  - not yet implemented */
 
@@ -3522,7 +3523,7 @@
 
 err_out_kfree:
 #ifndef VIA_NDEBUG
-	memset (card, 0xAB, sizeof (*card)); /* poison memory */
+	memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */
 #endif
 	kfree (card);
 
@@ -3559,7 +3560,7 @@
 	via_ac97_cleanup (card);
 
 #ifndef VIA_NDEBUG
-	memset (card, 0xAB, sizeof (*card)); /* poison memory */
+	memset (card, OSS_POISON_FREE, sizeof (*card)); /* poison memory */
 #endif
 	kfree (card);
 
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index a208180..d37346b 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -216,14 +216,19 @@
 	  This works better than the old code, so say Y.
 
 config SND_CS5535AUDIO
-	tristate "CS5535 Audio"
+	tristate "CS5535/CS5536 Audio"
 	depends on SND && X86 && !X86_64
 	select SND_PCM
 	select SND_AC97_CODEC
 	help
 	  Say Y here to include support for audio on CS5535 chips. It is
 	  referred to as NS CS5535 IO or AMD CS5535 IO companion in
-	  various literature.
+	  various literature. This driver also supports the CS5536 audio
+	  device. However, for both chips, on certain boards, you may
+	  need to use ac97_quirk=hp_only if your board has physically 
+	  mapped headphone out to master output. If that works for you,
+	  send lspci -vvv output to the mailing list so that your board
+	  can be identified in the quirks list.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-cs5535audio.
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index d052007..0abf280 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -253,6 +253,8 @@
 	ac97->bus->ops->write(ac97, reg, value);
 }
 
+EXPORT_SYMBOL(snd_ac97_write);
+
 /**
  * snd_ac97_read - read a value from the given register
  * 
@@ -281,6 +283,8 @@
 	return ac97->regs[reg];
 }
 
+EXPORT_SYMBOL(snd_ac97_read);
+
 /**
  * snd_ac97_write_cache - write a value on the given register and update the cache
  * @ac97: the ac97 instance
@@ -302,6 +306,8 @@
 	mutex_unlock(&ac97->reg_mutex);
 }
 
+EXPORT_SYMBOL(snd_ac97_write_cache);
+
 /**
  * snd_ac97_update - update the value on the given register
  * @ac97: the ac97 instance
@@ -331,6 +337,8 @@
 	return change;
 }
 
+EXPORT_SYMBOL(snd_ac97_update);
+
 /**
  * snd_ac97_update_bits - update the bits on the given register
  * @ac97: the ac97 instance
@@ -356,6 +364,8 @@
 	return change;
 }
 
+EXPORT_SYMBOL(snd_ac97_update_bits);
+
 /* no lock version - see snd_ac97_updat_bits() */
 int snd_ac97_update_bits_nolock(struct snd_ac97 *ac97, unsigned short reg,
 				unsigned short mask, unsigned short value)
@@ -563,7 +573,7 @@
 };
 
 static const struct snd_kcontrol_new snd_ac97_controls_mic_boost =
-	AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0);
+	AC97_SINGLE("Mic Boost (+20dB) Switch", AC97_MIC, 6, 1, 0);
 
 
 static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"};
@@ -605,7 +615,7 @@
 AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
 AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),
 AC97_ENUM("Mono Output Select", std_enum[2]),
-AC97_ENUM("Mic Select", std_enum[3]),
+AC97_ENUM("Mic Select Capture Switch", std_enum[3]),
 AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
 };
 
@@ -1226,7 +1236,8 @@
 	ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;
 
 	/* build center controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) {
+	if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) 
+		&& !(ac97->flags & AC97_AD_MULTI)) {
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_center[0], ac97))) < 0)
 			return err;
 		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_center[1], ac97))) < 0)
@@ -1238,7 +1249,8 @@
 	}
 
 	/* build LFE controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1)) {
+	if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER+1))
+		&& !(ac97->flags & AC97_AD_MULTI)) {
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_lfe[0], ac97))) < 0)
 			return err;
 		if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_lfe[1], ac97))) < 0)
@@ -1250,7 +1262,8 @@
 	}
 
 	/* build surround controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) {
+	if ((snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) 
+		&& !(ac97->flags & AC97_AD_MULTI)) {
 		/* Surround Master (0x38) is with stereo mutes */
 		if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0)
 			return err;
@@ -1335,9 +1348,11 @@
 	}
 
 	/* build Aux controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {
-		if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0)
-			return err;
+	if (!(ac97->flags & AC97_HAS_NO_AUX)) {
+		if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {
+			if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, ac97)) < 0)
+				return err;
+		}
 	}
 
 	/* build PCM controls */
@@ -1682,6 +1697,7 @@
 	return "unknown codec";
 }
 
+EXPORT_SYMBOL(snd_ac97_get_short_name);
 
 /* wait for a while until registers are accessible after RESET
  * return 0 if ok, negative not ready
@@ -1774,6 +1790,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_ac97_bus);
+
 /* stop no dev release warning */
 static void ac97_device_release(struct device * dev)
 {
@@ -2117,6 +2135,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_ac97_mixer);
 
 /*
  * Power down the chip.
@@ -2166,6 +2185,8 @@
 	snd_ac97_powerdown(ac97);
 }
 
+EXPORT_SYMBOL(snd_ac97_suspend);
+
 /*
  * restore ac97 status
  */
@@ -2267,6 +2288,8 @@
 		snd_ac97_restore_iec958(ac97);
 	}
 }
+
+EXPORT_SYMBOL(snd_ac97_resume);
 #endif
 
 
@@ -2590,29 +2613,7 @@
 	return 0;
 }
 
-
-/*
- *  Exported symbols
- */
-
-EXPORT_SYMBOL(snd_ac97_write);
-EXPORT_SYMBOL(snd_ac97_read);
-EXPORT_SYMBOL(snd_ac97_write_cache);
-EXPORT_SYMBOL(snd_ac97_update);
-EXPORT_SYMBOL(snd_ac97_update_bits);
-EXPORT_SYMBOL(snd_ac97_get_short_name);
-EXPORT_SYMBOL(snd_ac97_bus);
-EXPORT_SYMBOL(snd_ac97_mixer);
-EXPORT_SYMBOL(snd_ac97_pcm_assign);
-EXPORT_SYMBOL(snd_ac97_pcm_open);
-EXPORT_SYMBOL(snd_ac97_pcm_close);
-EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules);
 EXPORT_SYMBOL(snd_ac97_tune_hardware);
-EXPORT_SYMBOL(snd_ac97_set_rate);
-#ifdef CONFIG_PM
-EXPORT_SYMBOL(snd_ac97_resume);
-EXPORT_SYMBOL(snd_ac97_suspend);
-#endif
 
 /*
  *  INIT part
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 4d9cf37..7f197c7 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -464,6 +464,10 @@
 {
 	/* WM9705, WM9710 */
 	ac97->build_ops = &patch_wolfson_wm9705_ops;
+#ifdef CONFIG_TOUCHSCREEN_WM9705
+	/* WM9705 touchscreen uses AUX and VIDEO for touch */
+	ac97->flags |=3D AC97_HAS_NO_VIDEO | AC97_HAS_NO_AUX;
+#endif
 	return 0;
 }
 
@@ -1367,6 +1371,13 @@
 
 	snd_ac97_restore_iec958(ac97);
 }
+
+static void ad1888_resume(struct snd_ac97 *ac97)
+{
+	ad18xx_resume(ac97);
+	snd_ac97_write_cache(ac97, AC97_CODEC_CLASS_REV, 0x8080);
+}
+
 #endif
 
 int patch_ad1819(struct snd_ac97 * ac97)
@@ -1627,6 +1638,7 @@
  * (SS vendor << 16 | device)
  */
 static unsigned int ad1981_jacks_blacklist[] = {
+	0x10140537, /* Thinkpad T41p */
 	0x10140554, /* Thinkpad T42p/R50p */
 	0 /* end */
 };
@@ -1839,7 +1851,7 @@
 	.build_post_spdif = patch_ad198x_post_spdif,
 	.build_specific = patch_ad1888_specific,
 #ifdef CONFIG_PM
-	.resume = ad18xx_resume,
+	.resume = ad1888_resume,
 #endif
 	.update_jacks = ad1888_update_jacks,
 };
@@ -2048,7 +2060,10 @@
 	/* Enable SPDIF-IN only on Rev.E and above */
 	val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
 	/* SPDIF IN with pin 47 */
-	if (ac97->spec.dev_flags)
+	if (ac97->spec.dev_flags &&
+	    /* ASUS A6KM requires EAPD */
+	    ! (ac97->subsystem_vendor == 0x1043 &&
+	       ac97->subsystem_device == 0x1103))
 		val |= 0x03; /* enable */
 	else
 		val &= ~0x03; /* disable */
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index 512a358..f684aa2 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -317,6 +317,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_ac97_set_rate);
+
 static unsigned short get_pslots(struct snd_ac97 *ac97, unsigned char *rate_table, unsigned short *spdif_slots)
 {
 	if (!ac97_is_audio(ac97))
@@ -550,6 +552,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_ac97_pcm_assign);
+
 /**
  * snd_ac97_pcm_open - opens the given AC97 pcm
  * @pcm: the ac97 pcm instance
@@ -633,6 +637,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(snd_ac97_pcm_open);
+
 /**
  * snd_ac97_pcm_close - closes the given AC97 pcm
  * @pcm: the ac97 pcm instance
@@ -658,6 +664,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_ac97_pcm_close);
+
 static int double_rate_hw_constraint_rate(struct snd_pcm_hw_params *params,
 					  struct snd_pcm_hw_rule *rule)
 {
@@ -709,3 +717,5 @@
 				  SNDRV_PCM_HW_PARAM_RATE, -1);
 	return err;
 }
+
+EXPORT_SYMBOL(snd_ac97_pcm_double_rate_rules);
diff --git a/sound/pci/ac97/ac97_proc.c b/sound/pci/ac97/ac97_proc.c
index 4d523df..2118df5 100644
--- a/sound/pci/ac97/ac97_proc.c
+++ b/sound/pci/ac97/ac97_proc.c
@@ -433,7 +433,7 @@
 	prefix = ac97_is_audio(ac97) ? "ac97" : "mc97";
 	sprintf(name, "%s#%d-%d", prefix, ac97->addr, ac97->num);
 	if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
-		snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_read);
+		snd_info_set_text_ops(entry, ac97, snd_ac97_proc_read);
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
 			entry = NULL;
@@ -442,10 +442,9 @@
 	ac97->proc = entry;
 	sprintf(name, "%s#%d-%d+regs", prefix, ac97->addr, ac97->num);
 	if ((entry = snd_info_create_card_entry(ac97->bus->card, name, ac97->bus->proc)) != NULL) {
-		snd_info_set_text_ops(entry, ac97, 1024, snd_ac97_proc_regs_read);
+		snd_info_set_text_ops(entry, ac97, snd_ac97_proc_regs_read);
 #ifdef CONFIG_SND_DEBUG
 		entry->mode |= S_IWUSR;
-		entry->c.text.write_size = 1024;
 		entry->c.text.write = snd_ac97_proc_regs_write;
 #endif
 		if (snd_info_register(entry) < 0) {
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index 0fb7b34..94c26ec 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -453,7 +453,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(card, "ak4531", &entry))
-		snd_info_set_text_ops(entry, ak4531, 1024, snd_ak4531_proc_read);
+		snd_info_set_text_ops(entry, ak4531, snd_ak4531_proc_read);
 }
 #endif
 
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index eece1c7..d42bf45 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -753,7 +753,7 @@
 	struct snd_info_entry *entry;
 
 	if (!snd_card_proc_new(chip->card, chip->card->driver, &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_ad1889_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_ad1889_proc_read);
 }
 
 static struct ac97_quirk ac97_quirks[] = {
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index e2dbc21..5dfdbf6 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -49,7 +49,7 @@
 static int index = SNDRV_DEFAULT_IDX1;	/* Index */
 static char *id = SNDRV_DEFAULT_STR1;	/* ID for this card */
 static int pcm_channels = 32;
-static int spdif = 0;
+static int spdif;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio.");
@@ -2173,7 +2173,7 @@
 {
 	struct snd_info_entry *entry;
 	if(!snd_card_proc_new(codec->card, "ali5451", &entry))
-		snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read);
+		snd_info_set_text_ops(entry, codec, snd_ali_proc_read);
 }
 
 static int __devinit snd_ali_resources(struct snd_ali *codec)
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 60423b1..a9f0806 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -746,8 +746,8 @@
 		card->shortname, chip->alt_port, chip->irq);
 
 	if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000,
-				        gcr+0x30, 1, pci->irq, 0,
-				        &chip->rmidi)) < 0) {
+				        gcr+0x30, MPU401_INFO_INTEGRATED,
+					pci->irq, 0, &chip->rmidi)) < 0) {
 		printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n", gcr+0x30);
 		goto out_err;
 	}
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index d0f759d..f18a8c0 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1504,7 +1504,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "atiixp", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read);
 }
 #else /* !CONFIG_PROC_FS */
 #define snd_atiixp_proc_init(chip)
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 12a34c3..4073905 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1177,7 +1177,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "atiixp-modem", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_atiixp_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_atiixp_proc_read);
 }
 #else
 #define snd_atiixp_proc_init(chip)
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 126870e..8a3b118 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -261,6 +261,13 @@
 		return err;
 	}
 	snd_vortex_workaround(pci, pcifix[dev]);
+
+	// Card details needed in snd_vortex_midi
+	strcpy(card->driver, CARD_NAME_SHORT);
+	sprintf(card->shortname, "Aureal Vortex %s", CARD_NAME_SHORT);
+	sprintf(card->longname, "%s at 0x%lx irq %i",
+		card->shortname, chip->io, chip->irq);
+
 	// (4) Alloc components.
 	// ADB pcm.
 	if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
@@ -323,11 +330,6 @@
 #endif
 
 	// (5)
-	strcpy(card->driver, CARD_NAME_SHORT);
-	strcpy(card->shortname, CARD_NAME_SHORT);
-	sprintf(card->longname, "%s at 0x%lx irq %i",
-		card->shortname, chip->io, chip->irq);
-
 	if ((err = pci_read_config_word(pci, PCI_DEVICE_ID,
 				  &(chip->device))) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
index 873f486..c75d368 100644
--- a/sound/pci/au88x0/au88x0_mpu401.c
+++ b/sound/pci/au88x0/au88x0_mpu401.c
@@ -47,7 +47,7 @@
 	struct snd_rawmidi *rmidi;
 	int temp, mode;
 	struct snd_mpu401 *mpu;
-	int port;
+	unsigned long port;
 
 #ifdef VORTEX_MPU401_LEGACY
 	/* EnableHardCodedMPU401Port() */
@@ -70,9 +70,6 @@
 	temp |= (MIDI_CLOCK_DIV << 8) | ((mode >> 24) & 0xff) << 4;
 	hwwrite(vortex->mmio, VORTEX_CTRL2, temp);
 	hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_RESET);
-	/* Set some kind of mode */
-	if (mode)
-		hwwrite(vortex->mmio, VORTEX_MIDI_CMD, MPU401_ENTER_UART);
 
 	/* Check if anything is OK. */
 	temp = hwread(vortex->mmio, VORTEX_MIDI_DATA);
@@ -98,7 +95,8 @@
 	port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA);
 	if ((temp =
 	     snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
-				 1, 0, 0, &rmidi)) != 0) {
+				 MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO,
+				 0, 0, &rmidi)) != 0) {
 		hwwrite(vortex->mmio, VORTEX_CTRL,
 			(hwread(vortex->mmio, VORTEX_CTRL) &
 			 ~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
@@ -107,6 +105,9 @@
 	mpu = rmidi->private_data;
 	mpu->cport = (unsigned long)(vortex->mmio + VORTEX_MIDI_CMD);
 #endif
+	/* Overwrite MIDI name */
+	snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI %d", CARD_NAME_SHORT , vortex->card->number);
+
 	vortex->rmidi = rmidi;
 	return 0;
 }
diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c
index 4534e18..b4151e2 100644
--- a/sound/pci/au88x0/au88x0_xtalk.c
+++ b/sound/pci/au88x0/au88x0_xtalk.c
@@ -66,31 +66,20 @@
 	0
 	    //0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff
 };
-static xtalk_gains_t const asXtalkGainsZeros = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
+static xtalk_gains_t const asXtalkGainsZeros;
 
-static xtalk_dline_t const alXtalkDlineZeros = {
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0
-};
+static xtalk_dline_t const alXtalkDlineZeros;
 static xtalk_dline_t const alXtalkDlineTest = {
 	0xFC18, 0x03E8FFFF, 0x186A0, 0x7960FFFE, 1, 0xFFFFFFFF,
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 	0, 0, 0, 0
 };
 
-static xtalk_instate_t const asXtalkInStateZeros = { 0, 0, 0, 0 };
+static xtalk_instate_t const asXtalkInStateZeros;
 static xtalk_instate_t const asXtalkInStateTest =
     { 0xFF80, 0x0080, 0xFFFF, 0x0001 };
-static xtalk_state_t const asXtalkOutStateZeros = {
-	{0, 0, 0, 0},
-	{0, 0, 0, 0},
-	{0, 0, 0, 0},
-	{0, 0, 0, 0},
-	{0, 0, 0, 0}
-};
+static xtalk_state_t const asXtalkOutStateZeros;
+
 static short const sDiamondKLeftEq = 0x401d;
 static short const sDiamondKRightEq = 0x401d;
 static short const sDiamondKLeftXt = 0xF90E;
@@ -162,13 +151,7 @@
 	{0, 0, 0, 0, 0}
 };
 
-static xtalk_coefs_t const asXtalkCoefsZeros = {
-	{0, 0, 0, 0, 0},
-	{0, 0, 0, 0, 0},
-	{0, 0, 0, 0, 0},
-	{0, 0, 0, 0, 0},
-	{0, 0, 0, 0, 0}
-};
+static xtalk_coefs_t const asXtalkCoefsZeros;
 static xtalk_coefs_t const asXtalkCoefsPipe = {
 	{0, 0, 0x0FA0, 0, 0},
 	{0, 0, 0x0FA0, 0, 0},
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 52a3645..6e62daf 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -33,14 +33,21 @@
  *  in the first place >:-P}),
  *  I was forced to base this driver on reverse engineering
  *  (3 weeks' worth of evenings filled with driver work).
- *  (and no, I did NOT go the easy way: to pick up a PCI128 for 9 Euros)
+ *  (and no, I did NOT go the easy way: to pick up a SB PCI128 for 9 Euros)
  *
  *  The AZF3328 chip (note: AZF3328, *not* AZT3328, that's just the driver name
  *  for compatibility reasons) has the following features:
  *
  *  - builtin AC97 conformant codec (SNR over 80dB)
- *    (really AC97 compliant?? I really doubt it when looking
- *    at the mixer register layout)
+ *    Note that "conformant" != "compliant"!! this chip's mixer register layout
+ *    *differs* from the standard AC97 layout:
+ *    they chose to not implement the headphone register (which is not a
+ *    problem since it's merely optional), yet when doing this, they committed
+ *    the grave sin of letting other registers follow immediately instead of
+ *    keeping a headphone dummy register, thereby shifting the mixer register
+ *    addresses illegally. So far unfortunately it looks like the very flexible
+ *    ALSA AC97 support is still not enough to easily compensate for such a
+ *    grave layout violation despite all tweaks and quirks mechanisms it offers.
  *  - builtin genuine OPL3
  *  - full duplex 16bit playback/record at independent sampling rate
  *  - MPU401 (+ legacy address support) FIXME: how to enable legacy addr??
@@ -90,10 +97,15 @@
  * 
  * TODO
  *  - test MPU401 MIDI playback etc.
- *  - power management. See e.g. intel8x0 or cs4281.
- *    This would be nice since the chip runs a bit hot, and it's *required*
- *    anyway for proper ACPI power management.
+ *  - add some power micro-management (disable various units of the card
+ *    as long as they're unused). However this requires I/O ports which I
+ *    haven't figured out yet and which thus might not even exist...
+ *    The standard suspend/resume functionality could probably make use of
+ *    some improvement, too...
  *  - figure out what all unknown port bits are responsible for
+ *  - figure out some cleverly evil scheme to possibly make ALSA AC97 code
+ *    fully accept our quite incompatible ""AC97"" mixer and thus save some
+ *    code (but I'm not too optimistic that doing this is possible at all)
  */
 
 #include <sound/driver.h>
@@ -214,6 +226,16 @@
 
 	struct pci_dev *pci;
 	int irq;
+
+#ifdef CONFIG_PM
+	/* register value containers for power management
+	 * Note: not always full I/O range preserved (just like Win driver!) */
+	u16 saved_regs_codec [AZF_IO_SIZE_CODEC_PM / 2];
+	u16 saved_regs_io2   [AZF_IO_SIZE_IO2_PM / 2];
+	u16 saved_regs_mpu   [AZF_IO_SIZE_MPU_PM / 2];
+	u16 saved_regs_synth[AZF_IO_SIZE_SYNTH_PM / 2];
+	u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2];
+#endif
 };
 
 static const struct pci_device_id snd_azf3328_ids[] __devinitdata = {
@@ -317,10 +339,8 @@
 	else
 		dst_vol_left &= ~0x80;
 
-	do
-	{
-		if (!left_done)
-		{
+	do {
+		if (!left_done) {
 			if (curr_vol_left > dst_vol_left)
 				curr_vol_left--;
 			else
@@ -330,8 +350,7 @@
 			    left_done = 1;
 			outb(curr_vol_left, portbase + 1);
 		}
-		if (!right_done)
-		{
+		if (!right_done) {
 			if (curr_vol_right > dst_vol_right)
 				curr_vol_right--;
 			else
@@ -346,8 +365,7 @@
 		}
 		if (delay)
 			mdelay(delay);
-	}
-	while ((!left_done) || (!right_done));
+	} while ((!left_done) || (!right_done));
 	snd_azf3328_dbgcallleave();
 }
 
@@ -514,15 +532,18 @@
 			    struct snd_ctl_elem_info *uinfo)
 {
 	static const char * const texts1[] = {
-		"ModemOut1", "ModemOut2"
+		"Mic1", "Mic2"
 	};
 	static const char * const texts2[] = {
-		"MonoSelectSource1", "MonoSelectSource2"
+		"Mix", "Mic"
 	};
 	static const char * const texts3[] = {
                 "Mic", "CD", "Video", "Aux",
 		"Line", "Mix", "Mix Mono", "Phone"
         };
+	static const char * const texts4[] = {
+		"pre 3D", "post 3D"
+        };
 	struct azf3328_mixer_reg reg;
 
 	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
@@ -531,14 +552,19 @@
         uinfo->value.enumerated.items = reg.enum_c;
         if (uinfo->value.enumerated.item > reg.enum_c - 1U)
                 uinfo->value.enumerated.item = reg.enum_c - 1U;
-	if (reg.reg == IDX_MIXER_ADVCTL2)
-	{
-		if (reg.lchan_shift == 8) /* modem out sel */
+	if (reg.reg == IDX_MIXER_ADVCTL2) {
+		switch(reg.lchan_shift) {
+		case 8: /* modem out sel */
 			strcpy(uinfo->value.enumerated.name, texts1[uinfo->value.enumerated.item]);
-		else /* mono sel source */
+			break;
+		case 9: /* mono sel source */
 			strcpy(uinfo->value.enumerated.name, texts2[uinfo->value.enumerated.item]);
-	}
-	else
+			break;
+		case 15: /* PCM Out Path */
+			strcpy(uinfo->value.enumerated.name, texts4[uinfo->value.enumerated.item]);
+			break;
+		}
+	} else
         	strcpy(uinfo->value.enumerated.name, texts3[uinfo->value.enumerated.item]
 );
         return 0;
@@ -554,12 +580,10 @@
         
 	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
 	val = snd_azf3328_mixer_inw(chip, reg.reg);
-	if (reg.reg == IDX_MIXER_REC_SELECT)
-	{
+	if (reg.reg == IDX_MIXER_REC_SELECT) {
         	ucontrol->value.enumerated.item[0] = (val >> 8) & (reg.enum_c - 1);
         	ucontrol->value.enumerated.item[1] = (val >> 0) & (reg.enum_c - 1);
-	}
-	else
+	} else
         	ucontrol->value.enumerated.item[0] = (val >> reg.lchan_shift) & (reg.enum_c - 1);
 
 	snd_azf3328_dbgmixer("get_enum: %02x is %04x -> %d|%d (shift %02d, enum_c %d)\n",
@@ -579,16 +603,13 @@
 	snd_azf3328_mixer_reg_decode(&reg, kcontrol->private_value);
 	oreg = snd_azf3328_mixer_inw(chip, reg.reg);
 	val = oreg;
-	if (reg.reg == IDX_MIXER_REC_SELECT)
-	{
+	if (reg.reg == IDX_MIXER_REC_SELECT) {
         	if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U ||
             	ucontrol->value.enumerated.item[1] > reg.enum_c - 1U)
                 	return -EINVAL;
         	val = (ucontrol->value.enumerated.item[0] << 8) |
         	      (ucontrol->value.enumerated.item[1] << 0);
-	}
-	else
-	{
+	} else {
         	if (ucontrol->value.enumerated.item[0] > reg.enum_c - 1U)
                 	return -EINVAL;
 		val &= ~((reg.enum_c - 1) << reg.lchan_shift);
@@ -629,13 +650,14 @@
 	AZF3328_MIXER_VOL_MONO("Modem Playback Volume", IDX_MIXER_MODEMOUT, 0x1f, 1),
 	AZF3328_MIXER_SWITCH("Modem Capture Switch", IDX_MIXER_MODEMIN, 15, 1),
 	AZF3328_MIXER_VOL_MONO("Modem Capture Volume", IDX_MIXER_MODEMIN, 0x1f, 1),
-	AZF3328_MIXER_ENUM("Modem Out Select", IDX_MIXER_ADVCTL2, 2, 8),
-	AZF3328_MIXER_ENUM("Mono Select Source", IDX_MIXER_ADVCTL2, 2, 9),
+	AZF3328_MIXER_ENUM("Mic Select", IDX_MIXER_ADVCTL2, 2, 8),
+	AZF3328_MIXER_ENUM("Mono Output Select", IDX_MIXER_ADVCTL2, 2, 9),
+	AZF3328_MIXER_ENUM("PCM", IDX_MIXER_ADVCTL2, 2, 15), /* PCM Out Path, place in front since it controls *both* 3D and Bass/Treble! */
 	AZF3328_MIXER_VOL_SPECIAL("Tone Control - Treble", IDX_MIXER_BASSTREBLE, 0x07, 1, 0),
 	AZF3328_MIXER_VOL_SPECIAL("Tone Control - Bass", IDX_MIXER_BASSTREBLE, 0x07, 9, 0),
 	AZF3328_MIXER_SWITCH("3D Control - Switch", IDX_MIXER_ADVCTL2, 13, 0),
-	AZF3328_MIXER_VOL_SPECIAL("3D Control - Wide", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */
-	AZF3328_MIXER_VOL_SPECIAL("3D Control - Space", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */
+	AZF3328_MIXER_VOL_SPECIAL("3D Control - Width", IDX_MIXER_ADVCTL1, 0x07, 1, 0), /* "3D Width" */
+	AZF3328_MIXER_VOL_SPECIAL("3D Control - Depth", IDX_MIXER_ADVCTL1, 0x03, 8, 0), /* "Hifi 3D" */
 #if MIXER_TESTING
 	AZF3328_MIXER_SWITCH("0", IDX_MIXER_ADVCTL2, 0, 0),
 	AZF3328_MIXER_SWITCH("1", IDX_MIXER_ADVCTL2, 1, 0),
@@ -813,22 +835,18 @@
 	unsigned int is_running;
 
 	snd_azf3328_dbgcallenter();
-	if (do_recording)
-	{
+	if (do_recording) {
 		/* access capture registers, i.e. skip playback reg section */
 		portbase = chip->codec_port + 0x20;
 		is_running = chip->is_recording;
-	}
-	else
-	{
+	} else {
 		/* access the playback register section */
 		portbase = chip->codec_port + 0x00;
 		is_running = chip->is_playing;
 	}
 
 	/* AZF3328 uses a two buffer pointer DMA playback approach */
-	if (!is_running)
-	{
+	if (!is_running) {
 		unsigned long addr_area2;
 		unsigned long count_areas, count_tmp; /* width 32bit -- overflow!! */
 		count_areas = size/2;
@@ -961,6 +979,13 @@
 		chip->is_playing = 1;
 		snd_azf3328_dbgplay("STARTED PLAYBACK\n");
 		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+		snd_azf3328_dbgplay("RESUME PLAYBACK\n");
+		/* resume playback if we were active */
+		if (chip->is_playing)
+			snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
+				snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME);
+		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		snd_azf3328_dbgplay("STOP PLAYBACK\n");
 
@@ -988,6 +1013,12 @@
 		chip->is_playing = 0;
 		snd_azf3328_dbgplay("STOPPED PLAYBACK\n");
 		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		snd_azf3328_dbgplay("SUSPEND PLAYBACK\n");
+		/* make sure playback is stopped */
+		snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS,
+			snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME);
+		break;
         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
                 break;
@@ -995,6 +1026,7 @@
 		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
                 break;
         default:
+		printk(KERN_ERR "FIXME: unknown trigger mode!\n");
                 return -EINVAL;
 	}
 	
@@ -1068,6 +1100,13 @@
 		chip->is_recording = 1;
 		snd_azf3328_dbgplay("STARTED CAPTURE\n");
 		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+		snd_azf3328_dbgplay("RESUME CAPTURE\n");
+		/* resume recording if we were active */
+		if (chip->is_recording)
+			snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
+				snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME);
+		break;
         case SNDRV_PCM_TRIGGER_STOP:
 		snd_azf3328_dbgplay("STOP CAPTURE\n");
 
@@ -1088,6 +1127,12 @@
 		chip->is_recording = 0;
 		snd_azf3328_dbgplay("STOPPED CAPTURE\n");
 		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		snd_azf3328_dbgplay("SUSPEND CAPTURE\n");
+		/* make sure recording is stopped */
+		snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS,
+			snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME);
+		break;
         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n");
                 break;
@@ -1095,6 +1140,7 @@
 		snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n");
                 break;
         default:
+		printk(KERN_ERR "FIXME: unknown trigger mode!\n");
                 return -EINVAL;
 	}
 	
@@ -1163,8 +1209,7 @@
 		snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE),
 		status);
 		
-	if (status & IRQ_TIMER)
-	{
+	if (status & IRQ_TIMER) {
 		/* snd_azf3328_dbgplay("timer %ld\n", inl(chip->codec_port+IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK); */
 		if (chip->timer)
 			snd_timer_interrupt(chip->timer, chip->timer->sticks);
@@ -1174,50 +1219,43 @@
 		spin_unlock(&chip->reg_lock);
 		snd_azf3328_dbgplay("azt3328: timer IRQ\n");
 	}
-	if (status & IRQ_PLAYBACK)
-	{
+	if (status & IRQ_PLAYBACK) {
 		spin_lock(&chip->reg_lock);
 		which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE);
 		/* ack all IRQ types immediately */
 		snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which);
                	spin_unlock(&chip->reg_lock);
 
-		if (chip->pcm && chip->playback_substream)
-		{
+		if (chip->pcm && chip->playback_substream) {
 			snd_pcm_period_elapsed(chip->playback_substream);
 			snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n",
 				which,
 				inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS));
-		}
-		else
+		} else
 			snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n");
 		if (which & IRQ_PLAY_SOMETHING)
 			snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n");
 	}
-	if (status & IRQ_RECORDING)
-	{
+	if (status & IRQ_RECORDING) {
                 spin_lock(&chip->reg_lock);
 		which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE);
 		/* ack all IRQ types immediately */
 		snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which);
 		spin_unlock(&chip->reg_lock);
 
-		if (chip->pcm && chip->capture_substream)
-		{
+		if (chip->pcm && chip->capture_substream) {
 			snd_pcm_period_elapsed(chip->capture_substream);
 			snd_azf3328_dbgplay("REC  period done (#%x), @ %x\n",
 				which,
 				inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS));
-		}
-		else
+		} else
 			snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n");
 		if (which & IRQ_REC_SOMETHING)
 			snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n");
 	}
 	/* MPU401 has less critical IRQ requirements
 	 * than timer and playback/recording, right? */
-	if (status & IRQ_MPU401)
-	{
+	if (status & IRQ_MPU401) {
 		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
 
 		/* hmm, do we have to ack the IRQ here somehow?
@@ -1511,8 +1549,7 @@
 	snd_azf3328_dbgcallenter();
 	chip = snd_timer_chip(timer);
 	delay = ((timer->sticks * seqtimer_scaling) - 1) & TIMER_VALUE_MASK;
-	if (delay < 49)
-	{
+	if (delay < 49) {
 		/* uhoh, that's not good, since user-space won't know about
 		 * this timing tweak
 		 * (we need to do it to avoid a lockup, though) */
@@ -1766,9 +1803,11 @@
 		goto out_err;
 	}
 
+	card->private_data = chip;
+
 	if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_MPU401,
-				        chip->mpu_port, 1, pci->irq, 0,
-				        &chip->rmidi)) < 0) {
+				        chip->mpu_port, MPU401_INFO_INTEGRATED,
+					pci->irq, 0, &chip->rmidi)) < 0) {
 		snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n", chip->mpu_port);
 		goto out_err;
 	}
@@ -1791,6 +1830,8 @@
 		}
 	}
 
+	opl3->private_data = chip;
+
 	sprintf(card->longname, "%s at 0x%lx, irq %i",
 		card->shortname, chip->codec_port, chip->irq);
 
@@ -1834,11 +1875,80 @@
 	snd_azf3328_dbgcallleave();
 }
 
+#ifdef CONFIG_PM
+static int
+snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct snd_azf3328 *chip = card->private_data;
+	int reg;
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	
+	snd_pcm_suspend_all(chip->pcm);
+
+	for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++)
+		chip->saved_regs_mixer[reg] = inw(chip->mixer_port + reg * 2);
+
+	/* make sure to disable master volume etc. to prevent looping sound */
+	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
+	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
+	
+	for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++)
+		chip->saved_regs_codec[reg] = inw(chip->codec_port + reg * 2);
+	for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++)
+		chip->saved_regs_io2[reg] = inw(chip->io2_port + reg * 2);
+	for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++)
+		chip->saved_regs_mpu[reg] = inw(chip->mpu_port + reg * 2);
+	for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++)
+		chip->saved_regs_synth[reg] = inw(chip->synth_port + reg * 2);
+
+	pci_set_power_state(pci, PCI_D3hot);
+	pci_disable_device(pci);
+	pci_save_state(pci);
+	return 0;
+}
+
+static int
+snd_azf3328_resume(struct pci_dev *pci)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct snd_azf3328 *chip = card->private_data;
+	int reg;
+
+	pci_restore_state(pci);
+	pci_enable_device(pci);
+	pci_set_power_state(pci, PCI_D0);
+	pci_set_master(pci);
+
+	for (reg = 0; reg < AZF_IO_SIZE_IO2_PM / 2; reg++)
+		outw(chip->saved_regs_io2[reg], chip->io2_port + reg * 2);
+	for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; reg++)
+		outw(chip->saved_regs_mpu[reg], chip->mpu_port + reg * 2);
+	for (reg = 0; reg < AZF_IO_SIZE_SYNTH_PM / 2; reg++)
+		outw(chip->saved_regs_synth[reg], chip->synth_port + reg * 2);
+	for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; reg++)
+		outw(chip->saved_regs_mixer[reg], chip->mixer_port + reg * 2);
+	for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; reg++)
+		outw(chip->saved_regs_codec[reg], chip->codec_port + reg * 2);
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+	return 0;
+}
+#endif
+
+
+
+
 static struct pci_driver driver = {
 	.name = "AZF3328",
 	.id_table = snd_azf3328_ids,
 	.probe = snd_azf3328_probe,
 	.remove = __devexit_p(snd_azf3328_remove),
+#ifdef CONFIG_PM
+	.suspend = snd_azf3328_suspend,
+	.resume = snd_azf3328_resume,
+#endif
 };
 
 static int __init
diff --git a/sound/pci/azt3328.h b/sound/pci/azt3328.h
index f489bda..b4f3e3c 100644
--- a/sound/pci/azt3328.h
+++ b/sound/pci/azt3328.h
@@ -5,6 +5,9 @@
 
 /*** main I/O area port indices ***/
 /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */
+#define AZF_IO_SIZE_CODEC	0x80
+#define AZF_IO_SIZE_CODEC_PM	0x70
+
 /* the driver initialisation suggests a layout of 4 main areas:
  * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??).
  * And another area from 0x60 to 0x6f (DirectX timer, IRQ management,
@@ -87,7 +90,7 @@
 #define IDX_IO_REC_DMA_CURROFS  0x34 /* PU:0x00000000 */
 #define IDX_IO_REC_SOUNDFORMAT  0x36 /* PU:0x0000 */
 
-/** hmm, what is this I/O area for? MPU401?? (after playback, recording, ???, timer) **/
+/** hmm, what is this I/O area for? MPU401?? or external DAC via I2S?? (after playback, recording, ???, timer) **/
 #define IDX_IO_SOMETHING_FLAGS	0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */
 /* general */
 #define IDX_IO_42H		0x42 /* PU:0x0001 */
@@ -107,7 +110,8 @@
   #define IRQ_UNKNOWN2			0x0080 /* probably unused */
 #define IDX_IO_66H		0x66    /* writing 0xffff returns 0x0000 */
 #define IDX_IO_SOME_VALUE	0x68	/* this is set to e.g. 0x3ff or 0x300, and writable; maybe some buffer limit, but I couldn't find out more, PU:0x00ff */
-#define IDX_IO_6AH		0x6A	/* this WORD can be set to have bits 0x0028 activated; actually inhibits PCM playback!!! maybe power management?? */
+#define IDX_IO_6AH		0x6A	/* this WORD can be set to have bits 0x0028 activated (FIXME: correct??); actually inhibits PCM playback!!! maybe power management?? */
+  #define IO_6A_PAUSE_PLAYBACK		0x0200 /* bit 9; sure, this pauses playback, but what the heck is this really about?? */
 #define IDX_IO_6CH		0x6C
 #define IDX_IO_6EH		0x6E	/* writing 0xffff returns 0x83fe */
 /* further I/O indices not saved/restored, so probably not used */
@@ -115,15 +119,25 @@
 
 /*** I/O 2 area port indices ***/
 /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ 
+#define AZF_IO_SIZE_IO2		0x08
+#define AZF_IO_SIZE_IO2_PM	0x06
+
 #define IDX_IO2_LEGACY_ADDR	0x04
   #define LEGACY_SOMETHING		0x01 /* OPL3?? */
   #define LEGACY_JOY			0x08
 
+#define AZF_IO_SIZE_MPU		0x04
+#define AZF_IO_SIZE_MPU_PM	0x04
+
+#define AZF_IO_SIZE_SYNTH	0x08
+#define AZF_IO_SIZE_SYNTH_PM	0x06
 
 /*** mixer I/O area port indices ***/
 /* (only 0x22 of 0x40 bytes saved/restored by Windows driver)
- * generally spoken: AC97 register index = AZF3328 mixer reg index + 2
- * (in other words: AZF3328 NOT fully AC97 compliant) */
+ * UNFORTUNATELY azf3328 is NOT truly AC97 compliant: see main file intro */
+#define AZF_IO_SIZE_MIXER	0x40
+#define AZF_IO_SIZE_MIXER_PM	0x22
+
   #define MIXER_VOLUME_RIGHT_MASK	0x001f
   #define MIXER_VOLUME_LEFT_MASK	0x1f00
   #define MIXER_MUTE_MASK		0x8000
@@ -156,14 +170,14 @@
 #define IDX_MIXER_ADVCTL1       0x1e
   /* unlisted bits are unmodifiable */
   #define MIXER_ADVCTL1_3DWIDTH_MASK	0x000e
-  #define MIXER_ADVCTL1_HIFI3D_MASK	0x0300
-#define IDX_MIXER_ADVCTL2       0x20 /* resembles AC97_GENERAL_PURPOSE reg! */
+  #define MIXER_ADVCTL1_HIFI3D_MASK	0x0300 /* yup, this is missing the high bit that official AC97 contains, plus it doesn't have linear bit value range behaviour but instead acts weirdly (possibly we're dealing with two *different* 3D settings here??) */
+#define IDX_MIXER_ADVCTL2       0x20 /* subset of AC97_GENERAL_PURPOSE reg! */
   /* unlisted bits are unmodifiable */
-  #define MIXER_ADVCTL2_BIT7		0x0080 /* WaveOut 3D Bypass? mutes WaveOut at LineOut */
-  #define MIXER_ADVCTL2_BIT8		0x0100 /* is this Modem Out Select? */
-  #define MIXER_ADVCTL2_BIT9		0x0200 /* Mono Select Source? */
-  #define MIXER_ADVCTL2_BIT13		0x2000 /* 3D enable? */
-  #define MIXER_ADVCTL2_BIT15		0x8000 /* unknown */
+  #define MIXER_ADVCTL2_LPBK		0x0080 /* Loopback mode -- Win driver: "WaveOut3DBypass"? mutes WaveOut at LineOut */
+  #define MIXER_ADVCTL2_MS		0x0100 /* Mic Select 0=Mic1, 1=Mic2 -- Win driver: "ModemOutSelect"?? */
+  #define MIXER_ADVCTL2_MIX		0x0200 /* Mono output select 0=Mix, 1=Mic; Win driver: "MonoSelectSource"?? */
+  #define MIXER_ADVCTL2_3D		0x2000 /* 3D Enhancement 1=on */
+  #define MIXER_ADVCTL2_POP		0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */
   
 #define IDX_MIXER_SOMETHING30H	0x30 /* used, but unknown??? */
 
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 9ee07d4..c33642d 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -44,7 +44,7 @@
 static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */
+static int digital_rate[SNDRV_CARDS];	/* digital input rate */
 static int load_all;	/* allow to load the non-whitelisted cards */
 
 module_param_array(index, int, NULL, 0444);
@@ -781,10 +781,12 @@
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000),
 	/* Viewcast Osprey 200 */
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100),
-	/* AVerMedia Studio No. 103, 203, ...? */
-	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000),
 	/* Leadtek Winfast tv 2000xp delux */
 	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x107d, 0x6606, 32000),
+	/* Voodoo TV 200 */
+	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x121a, 0x3000, 32000),
+	/* AVerMedia Studio No. 103, 203, ...? */
+	BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1461, 0x0003, 48000),
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, snd_bt87x_ids);
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index c8131ea..9cb66c5 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -537,9 +537,9 @@
 #endif
 
 #define ADC_MUX_MASK		0x0000000f	//Mask for ADC Mux
+#define ADC_MUX_PHONE		0x00000001	//Value to select TAD at ADC Mux (Not used)
 #define ADC_MUX_MIC		0x00000002	//Value to select Mic at ADC Mux
 #define ADC_MUX_LINEIN		0x00000004	//Value to select LineIn at ADC Mux
-#define ADC_MUX_PHONE		0x00000001	//Value to select TAD at ADC Mux (Not used)
 #define ADC_MUX_AUX		0x00000008	//Value to select Aux at ADC Mux
 
 #define SET_CHANNEL 0  /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
@@ -604,6 +604,8 @@
 	u32 spdif_bits[4];             /* s/pdif out setup */
 	int spdif_enable;
 	int capture_source;
+	int i2c_capture_source;
+	u8 i2c_capture_volume[4][2];
 	int capture_mic_line_in;
 
 	struct snd_dma_buffer buffer;
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index fd8bfeb..59bf9bd 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -186,8 +186,8 @@
 	 /* New Audigy SE. Has a different DAC. */
 	 /* SB0570:
 	  * CTRL:CA0106-DAT
-	  * ADC: WM8768GEDS
-	  * DAC: WM8775EDS
+	  * ADC: WM8775EDS
+	  * DAC: WM8768GEDS
 	  */
 	 { .serial = 0x100a1102,
 	   .name   = "Audigy SE [SB0570]",
@@ -195,9 +195,14 @@
 	   .i2c_adc = 1,
 	   .spi_dac = 1 } ,
 	 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
+	 /* SB0438
+	  * CTRL:CA0106-DAT
+	  * ADC: WM8775SEDS
+	  * DAC: CS4382-KQZ
+	  */
 	 { .serial = 0x10091462,
 	   .name   = "MSI K8N Diamond MB [SB0438]",
-	   .gpio_type = 1,
+	   .gpio_type = 2,
 	   .i2c_adc = 1 } ,
 	 /* Shuttle XPC SD31P which has an onboard Creative Labs
 	  * Sound Blaster Live! 24-bit EAX
@@ -326,6 +331,7 @@
 	return 0;
 }
 
+/* The ADC does not support i2c read, so only write is implemented */
 int snd_ca0106_i2c_write(struct snd_ca0106 *emu,
 				u32 reg,
 				u32 value)
@@ -340,6 +346,7 @@
 	}
 
 	tmp = reg << 25 | value << 16;
+	// snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
 	/* Not sure what this I2C channel controls. */
 	/* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
 
@@ -348,8 +355,9 @@
 
 	for (retry = 0; retry < 10; retry++) {
 		/* Send the data to i2c */
-		tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
-		tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
+		//tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
+		//tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
+		tmp = 0;
 		tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
 		snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
 
@@ -1181,7 +1189,7 @@
 	0x02ff,
 	0x0400,
 	0x0520,
-	0x0600,
+	0x0620, /* Set 24 bit. Was 0x0600 */
 	0x08ff,
 	0x0aff,
 	0x0cff,
@@ -1200,6 +1208,22 @@
 	0x1400,
 };
 
+static unsigned int i2c_adc_init[][2] = {
+	{ 0x17, 0x00 }, /* Reset */
+	{ 0x07, 0x00 }, /* Timeout */
+	{ 0x0b, 0x22 },  /* Interface control */
+	{ 0x0c, 0x22 },  /* Master mode control */
+	{ 0x0d, 0x08 },  /* Powerdown control */
+	{ 0x0e, 0xcf },  /* Attenuation Left  0x01 = -103dB, 0xff = 24dB */
+	{ 0x0f, 0xcf },  /* Attenuation Right 0.5dB steps */
+	{ 0x10, 0x7b },  /* ALC Control 1 */
+	{ 0x11, 0x00 },  /* ALC Control 2 */
+	{ 0x12, 0x32 },  /* ALC Control 3 */
+	{ 0x13, 0x00 },  /* Noise gate control */
+	{ 0x14, 0xa6 },  /* Limiter control */
+	{ 0x15, ADC_MUX_LINEIN },  /* ADC Mixer control */
+};
+
 static int __devinit snd_ca0106_create(struct snd_card *card,
 					 struct pci_dev *pci,
 					 struct snd_ca0106 **rchip)
@@ -1361,7 +1385,12 @@
         snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
 	chip->capture_source = 3; /* Set CAPTURE_SOURCE */
 
-        if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
+        if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
+		/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
+		outl(0x0, chip->port+GPIO);
+		//outl(0x00f0e000, chip->port+GPIO); /* Analog */
+		outl(0x005f5301, chip->port+GPIO); /* Analog */
+	} else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
 		/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
 		outl(0x0, chip->port+GPIO);
 		//outl(0x00f0e000, chip->port+GPIO); /* Analog */
@@ -1379,7 +1408,19 @@
 	outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
 
         if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
-	        snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
+		int size, n;
+
+		size = ARRAY_SIZE(i2c_adc_init);
+                //snd_printk("I2C:array size=0x%x\n", size);
+		for (n=0; n < size; n++) {
+			snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
+		}
+		for (n=0; n < 4; n++) {
+			chip->i2c_capture_volume[n][0]= 0xcf;
+			chip->i2c_capture_volume[n][1]= 0xcf;
+		}
+		chip->i2c_capture_source=2; /* Line in */
+	        //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
 	}
         if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
 		int size, n;
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 06fe055..146eed70d 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -171,6 +171,76 @@
         return change;
 }
 
+static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
+					  struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[6] = {
+		"Phone", "Mic", "Line in", "Aux"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 4;
+	if (uinfo->value.enumerated.item > 3)
+                uinfo->value.enumerated.item = 3;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
+	return 0;
+}
+
+static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int source_id;
+	unsigned int ngain, ogain;
+	int change = 0;
+	u32 source;
+	/* If the capture source has changed,
+	 * update the capture volume from the cached value
+	 * for the particular source.
+	 */
+	source_id = ucontrol->value.enumerated.item[0] ;
+	change = (emu->i2c_capture_source != source_id);
+	if (change) {
+		snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
+		ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
+		ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
+		if (ngain != ogain)
+			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
+		ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
+		ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
+		if (ngain != ogain)
+			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
+		source = 1 << source_id;
+		snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
+		emu->i2c_capture_source = source_id;
+	}
+        return change;
+}
+
+static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_info *uinfo)
+{
+	static char *texts[2] = { "Side out", "Line in" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+                uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
 static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
 					       struct snd_ctl_elem_info *uinfo)
 {
@@ -207,16 +277,16 @@
 	if (change) {
 		emu->capture_mic_line_in = val;
 		if (val) {
-			snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
+			//snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
 			tmp = inl(emu->port+GPIO) & ~0x400;
 			tmp = tmp | 0x400;
 			outl(tmp, emu->port+GPIO);
-			snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
+			//snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
 		} else {
-			snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
+			//snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
 			tmp = inl(emu->port+GPIO) & ~0x400;
 			outl(tmp, emu->port+GPIO);
-			snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
+			//snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
 		}
 	}
         return change;
@@ -225,12 +295,22 @@
 static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
 {
 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name =		"Mic/Line in Capture",
+	.name =		"Shared Mic/Line in Capture Switch",
 	.info =		snd_ca0106_capture_mic_line_in_info,
 	.get =		snd_ca0106_capture_mic_line_in_get,
 	.put =		snd_ca0106_capture_mic_line_in_put
 };
 
+static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"Shared Line in/Side out Capture Switch",
+	.info =		snd_ca0106_capture_line_in_side_out_info,
+	.get =		snd_ca0106_capture_mic_line_in_get,
+	.put =		snd_ca0106_capture_mic_line_in_put
+};
+
+
 static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_info *uinfo)
 {
@@ -329,15 +409,81 @@
 	return 1;
 }
 
+static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
+{
+        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+        uinfo->count = 2;
+        uinfo->value.integer.min = 0;
+        uinfo->value.integer.max = 255;
+        return 0;
+}
+
+static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+	int source_id;
+
+	source_id = kcontrol->private_value;
+
+        ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
+        ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
+        return 0;
+}
+
+static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
+        unsigned int ogain;
+        unsigned int ngain;
+	int source_id;
+	int change = 0;
+
+	source_id = kcontrol->private_value;
+	ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
+	ngain = ucontrol->value.integer.value[0];
+	if (ngain > 0xff)
+		return 0;
+	if (ogain != ngain) {
+		if (emu->i2c_capture_source == source_id)
+			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
+		emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
+		change = 1;
+	}
+	ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
+	ngain = ucontrol->value.integer.value[1];
+	if (ngain > 0xff)
+		return 0;
+	if (ogain != ngain) {
+		if (emu->i2c_capture_source == source_id)
+			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
+		emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
+		change = 1;
+	}
+
+	return change;
+}
+
 #define CA_VOLUME(xname,chid,reg) \
 {								\
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
-	.info = snd_ca0106_volume_info,				\
-	.get =          snd_ca0106_volume_get,			\
-	.put =          snd_ca0106_volume_put,			\
+	.info =	 snd_ca0106_volume_info,			\
+	.get =   snd_ca0106_volume_get,				\
+	.put =   snd_ca0106_volume_put,				\
 	.private_value = ((chid) << 8) | (reg)			\
 }
 
+#define I2C_VOLUME(xname,chid) \
+{								\
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
+	.info =  snd_ca0106_i2c_volume_info,			\
+	.get =   snd_ca0106_i2c_volume_get,			\
+	.put =   snd_ca0106_i2c_volume_put,			\
+	.private_value = chid					\
+}
+
 
 static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
 	CA_VOLUME("Analog Front Playback Volume",
@@ -361,6 +507,11 @@
         CA_VOLUME("CAPTURE feedback Playback Volume",
 		  1, CAPTURE_CONTROL),
 
+        I2C_VOLUME("Phone Capture Volume", 0),
+        I2C_VOLUME("Mic Capture Volume", 1),
+        I2C_VOLUME("Line in Capture Volume", 2),
+        I2C_VOLUME("Aux Capture Volume", 3),
+
 	{
 		.access =	SNDRV_CTL_ELEM_ACCESS_READ,
 		.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -378,12 +529,19 @@
 	},
 	{
 		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name =		"Capture Source",
+		.name =		"Digital Capture Source",
 		.info =		snd_ca0106_capture_source_info,
 		.get =		snd_ca0106_capture_source_get,
 		.put =		snd_ca0106_capture_source_put
 	},
 	{
+		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name =		"Capture Source",
+		.info =		snd_ca0106_i2c_capture_source_info,
+		.get =		snd_ca0106_i2c_capture_source_get,
+		.put =		snd_ca0106_i2c_capture_source_put
+	},
+	{
 		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
 		.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
 		.count =	4,
@@ -477,7 +635,10 @@
 			return err;
 	}
 	if (emu->details->i2c_adc == 1) {
-		err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
+		if (emu->details->gpio_type == 1)
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
+		else  /* gpio_type == 2 */
+			err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
 		if (err < 0)
 			return err;
 	}
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index 6375727..75ca421 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -431,33 +431,30 @@
 	struct snd_info_entry *entry;
 	
 	if(! snd_card_proc_new(emu->card, "iec958", &entry))
-		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_iec958);
+		snd_info_set_text_ops(entry, emu, snd_ca0106_proc_iec958);
 	if(! snd_card_proc_new(emu->card, "ca0106_reg32", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read32);
 		entry->c.text.write = snd_ca0106_proc_reg_write32;
 		entry->mode |= S_IWUSR;
 	}
 	if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry))
-		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16);
+		snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read16);
 	if(! snd_card_proc_new(emu->card, "ca0106_reg8", &entry))
-		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read8);
+		snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read8);
 	if(! snd_card_proc_new(emu->card, "ca0106_regs1", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read1);
 		entry->c.text.write = snd_ca0106_proc_reg_write;
 		entry->mode |= S_IWUSR;
 //		entry->private_data = emu;
 	}
 	if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_ca0106_proc_i2c_write);
 		entry->c.text.write = snd_ca0106_proc_i2c_write;
 		entry->mode |= S_IWUSR;
 //		entry->private_data = emu;
 	}
 	if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry)) 
-		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read2);
+		snd_info_set_text_ops(entry, emu, snd_ca0106_proc_reg_read2);
 	return 0;
 }
 
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index e5ce2da..0938c15 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2121,7 +2121,7 @@
 	CMIPCI_MIXER_VOL_MONO("Mic Capture Volume", CM_REG_MIXER2, CM_VADMIC_SHIFT, 7),
 	CMIPCI_SB_VOL_MONO("Phone Playback Volume", CM_REG_EXTENT_IND, 5, 7),
 	CMIPCI_DOUBLE("Phone Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 4, 4, 1, 0, 0),
-	CMIPCI_DOUBLE("PC Speaker Playnack Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0),
+	CMIPCI_DOUBLE("PC Speaker Playback Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 3, 3, 1, 0, 0),
 	CMIPCI_DOUBLE("Mic Boost Capture Switch", CM_REG_EXTENT_IND, CM_REG_EXTENT_IND, 0, 0, 1, 0, 0),
 };
 
@@ -2602,7 +2602,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(cm->card, "cmipci", &entry))
-		snd_info_set_text_ops(entry, cm, 1024, snd_cmipci_proc_read);
+		snd_info_set_text_ops(entry, cm, snd_cmipci_proc_read);
 }
 #else /* !CONFIG_PROC_FS */
 static inline void snd_cmipci_proc_init(struct cmipci *cm) {}
@@ -2932,7 +2932,7 @@
 	}
 
 	integrated_midi = snd_cmipci_read_b(cm, CM_REG_MPU_PCI) != 0xff;
-	if (integrated_midi)
+	if (integrated_midi && mpu_port[dev] == 1)
 		iomidi = cm->iobase + CM_REG_MPU_PCI;
 	else {
 		iomidi = mpu_port[dev];
@@ -2981,7 +2981,9 @@
 
 	if (iomidi > 0) {
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
-					       iomidi, integrated_midi,
+					       iomidi,
+					       (integrated_midi ?
+						MPU401_INFO_INTEGRATED : 0),
 					       cm->irq, 0, &cm->rmidi)) < 0) {
 			printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi);
 		}
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index b3c94d8..e77a4ce3 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1184,7 +1184,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "cs4281", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_cs4281_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_cs4281_proc_read);
 	if (! snd_card_proc_new(chip->card, "cs4281_BA0", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = chip;
@@ -1379,6 +1379,13 @@
 	chip->ba0_addr = pci_resource_start(pci, 0);
 	chip->ba1_addr = pci_resource_start(pci, 1);
 
+	chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
+	chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
+	if (!chip->ba0 || !chip->ba1) {
+		snd_cs4281_free(chip);
+		return -ENOMEM;
+	}
+	
 	if (request_irq(pci->irq, snd_cs4281_interrupt, SA_INTERRUPT|SA_SHIRQ,
 			"CS4281", chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
@@ -1387,13 +1394,6 @@
 	}
 	chip->irq = pci->irq;
 
-	chip->ba0 = ioremap_nocache(chip->ba0_addr, pci_resource_len(pci, 0));
-	chip->ba1 = ioremap_nocache(chip->ba1_addr, pci_resource_len(pci, 1));
-	if (!chip->ba0 || !chip->ba1) {
-		snd_cs4281_free(chip);
-		return -ENOMEM;
-	}
-	
 	tmp = snd_cs4281_chip_init(chip);
 	if (tmp) {
 		snd_cs4281_free(chip);
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 848d772..772dc52 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -48,8 +48,8 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
-static int thinkpad[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+static int external_amp[SNDRV_CARDS];
+static int thinkpad[SNDRV_CARDS];
 static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
 
 module_param_array(index, int, NULL, 0444);
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 69dbf54..5c21144 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -2877,14 +2877,15 @@
 	if (chip->region.idx[0].resource)
 		snd_cs46xx_hw_stop(chip);
 
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
+
 	for (idx = 0; idx < 5; idx++) {
 		struct snd_cs46xx_region *region = &chip->region.idx[idx];
 		if (region->remap_addr)
 			iounmap(region->remap_addr);
 		release_and_free_resource(region->resource);
 	}
-	if (chip->irq >= 0)
-		free_irq(chip->irq, chip);
 
 	if (chip->active_ctrl)
 		chip->active_ctrl(chip, -chip->amplifier);
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index f407d2a..5c9711c 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -767,7 +767,6 @@
 	if ((entry = snd_info_create_card_entry(card, "dsp", card->proc_root)) != NULL) {
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
-		entry->c.text.read_size = 512;
       
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -784,7 +783,6 @@
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = chip;
 		entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-		entry->c.text.read_size = 512;
 		entry->c.text.read = cs46xx_dsp_proc_symbol_table_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -797,7 +795,6 @@
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = chip;
 		entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-		entry->c.text.read_size = 512;
 		entry->c.text.read = cs46xx_dsp_proc_modules_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -810,7 +807,6 @@
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = chip;
 		entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-		entry->c.text.read_size = 512;
 		entry->c.text.read = cs46xx_dsp_proc_parameter_dump_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -823,7 +819,6 @@
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = chip;
 		entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-		entry->c.text.read_size = 512;
 		entry->c.text.read = cs46xx_dsp_proc_sample_dump_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -836,7 +831,6 @@
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = chip;
 		entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-		entry->c.text.read_size = 512;
 		entry->c.text.read = cs46xx_dsp_proc_task_tree_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -849,7 +843,6 @@
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = chip;
 		entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
-		entry->c.text.read_size = 1024;
 		entry->c.text.read = cs46xx_dsp_proc_scb_read;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 2c4ee45..3844d18 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -267,7 +267,6 @@
 			entry->private_data = scb_info;
 			entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
       
-			entry->c.text.read_size = 512;
 			entry->c.text.read = cs46xx_dsp_proc_scb_info_read;
       
 			if (snd_info_register(entry) < 0) {
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile
index 08d8ee6..2911a8a 100644
--- a/sound/pci/cs5535audio/Makefile
+++ b/sound/pci/cs5535audio/Makefile
@@ -4,5 +4,9 @@
 
 snd-cs5535audio-objs := cs5535audio.o cs5535audio_pcm.o
 
+ifdef CONFIG_PM
+snd-cs5535audio-objs += cs5535audio_pm.o
+endif
+
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_CS5535AUDIO) += snd-cs5535audio.o
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 2c1213a..91c18a1 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -1,5 +1,5 @@
 /*
- * Driver for audio on multifunction CS5535 companion device
+ * Driver for audio on multifunction CS5535/6 companion device
  * Copyright (C) Jaya Kumar
  *
  * Based on Jaroslav Kysela and Takashi Iwai's examples.
@@ -40,16 +40,36 @@
 
 #define DRIVER_NAME "cs5535audio"
 
+static char *ac97_quirk;
+module_param(ac97_quirk, charp, 0444);
+MODULE_PARM_DESC(ac97_quirk, "AC'97 board specific workarounds.");
+
+static struct ac97_quirk ac97_quirks[] __devinitdata = {
+#if 0 /* Not yet confirmed if all 5536 boards are HP only */
+	{
+		.subvendor = PCI_VENDOR_ID_AMD, 
+		.subdevice = PCI_DEVICE_ID_AMD_CS5536_AUDIO, 
+		.name = "AMD RDK",     
+		.type = AC97_TUNE_HP_ONLY
+	},
+#endif
+	{}
+};
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
 
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME);
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for " DRIVER_NAME);
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable " DRIVER_NAME);
+
 static struct pci_device_id snd_cs5535audio_ids[] __devinitdata = {
-	{ PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
-	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_AUDIO) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_AUDIO) },
 	{}
 };
 
@@ -90,7 +110,8 @@
 		udelay(1);
 	} while (--timeout);
 	if (!timeout)
-		snd_printk(KERN_ERR "Failure reading cs5535 codec\n");
+		snd_printk(KERN_ERR "Failure reading codec reg 0x%x,"
+					"Last value=0x%x\n", reg, val);
 
 	return (unsigned short) val;
 }
@@ -148,6 +169,8 @@
 		return err;
 	}
 
+	snd_ac97_tune_hardware(cs5535au->ac97, ac97_quirks, ac97_quirk);
+
 	return 0;
 }
 
@@ -347,6 +370,8 @@
 	if ((err = snd_cs5535audio_create(card, pci, &cs5535au)) < 0)
 		goto probefail_out;
 
+	card->private_data = cs5535au;
+
 	if ((err = snd_cs5535audio_mixer(cs5535au)) < 0)
 		goto probefail_out;
 
@@ -383,6 +408,10 @@
 	.id_table = snd_cs5535audio_ids,
 	.probe = snd_cs5535audio_probe,
 	.remove = __devexit_p(snd_cs5535audio_remove),
+#ifdef CONFIG_PM
+	.suspend = snd_cs5535audio_suspend,
+	.resume = snd_cs5535audio_resume,
+#endif
 };
 
 static int __init alsa_card_cs5535audio_init(void)
diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h
index 5e55a1a..4fd1f31 100644
--- a/sound/pci/cs5535audio/cs5535audio.h
+++ b/sound/pci/cs5535audio/cs5535audio.h
@@ -74,6 +74,8 @@
 #define PRM_RDY_STS			0x00800000
 #define ACC_CODEC_CNTL_WR_CMD		(~0x80000000)
 #define ACC_CODEC_CNTL_RD_CMD		0x80000000
+#define ACC_CODEC_CNTL_LNK_SHUTDOWN	0x00040000
+#define ACC_CODEC_CNTL_LNK_WRM_RST	0x00020000
 #define PRD_JMP				0x2000
 #define PRD_EOP				0x4000
 #define PRD_EOT				0x8000
@@ -88,6 +90,7 @@
 	void (*disable_dma)(struct cs5535audio *cs5535au);
 	void (*pause_dma)(struct cs5535audio *cs5535au);
 	void (*setup_prd)(struct cs5535audio *cs5535au, u32 prd_addr);
+	u32 (*read_prd)(struct cs5535audio *cs5535au);
 	u32 (*read_dma_pntr)(struct cs5535audio *cs5535au);
 };
 
@@ -103,11 +106,14 @@
 	struct snd_pcm_substream *substream;
 	unsigned int buf_addr, buf_bytes;
 	unsigned int period_bytes, periods;
+	int suspended;
+	u32 saved_prd;
 };
 
 struct cs5535audio {
 	struct snd_card *card;
 	struct snd_ac97 *ac97;
+	struct snd_pcm *pcm;
 	int irq;
 	struct pci_dev *pci;
 	unsigned long port;
@@ -117,6 +123,8 @@
 	struct cs5535audio_dma dmas[NUM_CS5535AUDIO_DMAS];
 };
 
+int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state);
+int snd_cs5535audio_resume(struct pci_dev *pci);
 int __devinit snd_cs5535audio_pcm(struct cs5535audio *cs5535audio);
 
 #endif /* __SOUND_CS5535AUDIO_H */
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index 60bb82b..5450a9e 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -43,7 +43,8 @@
 		 		SNDRV_PCM_INFO_BLOCK_TRANSFER |
 		 		SNDRV_PCM_INFO_MMAP_VALID |
 		 		SNDRV_PCM_INFO_PAUSE |
-				SNDRV_PCM_INFO_SYNC_START
+				SNDRV_PCM_INFO_SYNC_START |
+				SNDRV_PCM_INFO_RESUME
 				),
 	.formats =		(
 				SNDRV_PCM_FMTBIT_S16_LE
@@ -142,7 +143,7 @@
 	if (dma->periods == periods && dma->period_bytes == period_bytes)
 		return 0;
 
-	/* the u32 cast is okay because in snd*create we succesfully told
+	/* the u32 cast is okay because in snd*create we successfully told
    	   pci alloc that we're only 32 bit capable so the uppper will be 0 */
 	addr = (u32) substream->runtime->dma_addr;
 	desc_addr = (u32) dma->desc_buf.addr;
@@ -193,6 +194,11 @@
 	cs_writel(cs5535au, ACC_BM0_PRD, prd_addr);
 }
 
+static u32 cs5535audio_playback_read_prd(struct cs5535audio *cs5535au)
+{
+	return cs_readl(cs5535au, ACC_BM0_PRD);
+}
+
 static u32 cs5535audio_playback_read_dma_pntr(struct cs5535audio *cs5535au)
 {
 	return cs_readl(cs5535au, ACC_BM0_PNTR);
@@ -219,6 +225,11 @@
 	cs_writel(cs5535au, ACC_BM1_PRD, prd_addr);
 }
 
+static u32 cs5535audio_capture_read_prd(struct cs5535audio *cs5535au)
+{
+	return cs_readl(cs5535au, ACC_BM1_PRD);
+}
+
 static u32 cs5535audio_capture_read_dma_pntr(struct cs5535audio *cs5535au)
 {
 	return cs_readl(cs5535au, ACC_BM1_PNTR);
@@ -285,9 +296,17 @@
 	case SNDRV_PCM_TRIGGER_START:
 		dma->ops->enable_dma(cs5535au);
 		break;
+	case SNDRV_PCM_TRIGGER_RESUME:
+		dma->ops->enable_dma(cs5535au);
+		dma->suspended = 0;
+		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		dma->ops->disable_dma(cs5535au);
 		break;
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		dma->ops->disable_dma(cs5535au);
+		dma->suspended = 1;
+		break;
 	default:
 		snd_printk(KERN_ERR "unhandled trigger\n");
 		err = -EINVAL;
@@ -375,6 +394,7 @@
         .enable_dma = cs5535audio_playback_enable_dma,
         .disable_dma = cs5535audio_playback_disable_dma,
         .setup_prd = cs5535audio_playback_setup_prd,
+        .read_prd = cs5535audio_playback_read_prd,
         .pause_dma = cs5535audio_playback_pause_dma,
         .read_dma_pntr = cs5535audio_playback_read_dma_pntr,
 };
@@ -384,6 +404,7 @@
         .enable_dma = cs5535audio_capture_enable_dma,
         .disable_dma = cs5535audio_capture_disable_dma,
         .setup_prd = cs5535audio_capture_setup_prd,
+        .read_prd = cs5535audio_capture_read_prd,
         .pause_dma = cs5535audio_capture_pause_dma,
         .read_dma_pntr = cs5535audio_capture_read_dma_pntr,
 };
@@ -413,6 +434,7 @@
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					snd_dma_pci_data(cs5535au->pci),
 					64*1024, 128*1024);
+	cs5535au->pcm = pcm;
 
 	return 0;
 }
diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c
new file mode 100644
index 0000000..aad0e69
--- /dev/null
+++ b/sound/pci/cs5535audio/cs5535audio_pm.c
@@ -0,0 +1,123 @@
+/*
+ * Power management for audio on multifunction CS5535 companion device
+ * Copyright (C) Jaya Kumar
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/initval.h>
+#include <sound/asoundef.h>
+#include <sound/pcm.h>
+#include <sound/ac97_codec.h>
+#include "cs5535audio.h"
+
+static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au)
+{
+	/* 
+	we depend on snd_ac97_suspend to tell the
+	AC97 codec to shutdown. the amd spec suggests
+	that the LNK_SHUTDOWN be done at the same time
+	that the codec power-down is issued. instead,
+	we do it just after rather than at the same 
+	time. excluding codec specific build_ops->suspend
+	ac97 powerdown hits:
+	0x8000 EAPD 
+	0x4000 Headphone amplifier 
+	0x0300 ADC & DAC 
+	0x0400 Analog Mixer powerdown (Vref on) 
+	I am not sure if this is the best that we can do.
+	The remainder to be investigated are:
+	- analog mixer (vref off) 0x0800
+	- AC-link powerdown 0x1000
+	- codec internal clock 0x2000
+	*/
+
+	/* set LNK_SHUTDOWN to shutdown AC link */
+	cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN);
+
+}
+
+int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct cs5535audio *cs5535au = card->private_data;
+	int i;
+
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
+		struct cs5535audio_dma *dma = &cs5535au->dmas[i];
+		if (dma && dma->substream && !dma->suspended) 
+			dma->saved_prd = dma->ops->read_prd(cs5535au);
+	}
+	snd_pcm_suspend_all(cs5535au->pcm);
+	snd_ac97_suspend(cs5535au->ac97);
+	/* save important regs, then disable aclink in hw */
+	snd_cs5535audio_stop_hardware(cs5535au);
+	pci_disable_device(pci);
+	pci_save_state(pci);
+
+	return 0;
+}
+
+int snd_cs5535audio_resume(struct pci_dev *pci)
+{
+	struct snd_card *card = pci_get_drvdata(pci);
+	struct cs5535audio *cs5535au = card->private_data;
+	u32 tmp;
+	int timeout;
+	int i;
+
+	pci_restore_state(pci);
+	pci_enable_device(pci);
+	pci_set_master(pci);
+
+	/* set LNK_WRM_RST to reset AC link */
+	cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST);
+
+	timeout = 50;
+	do {
+		tmp = cs_readl(cs5535au, ACC_CODEC_STATUS);
+		if (tmp & PRM_RDY_STS)
+			break;
+		udelay(1);
+	} while (--timeout);
+
+	if (!timeout)
+		snd_printk(KERN_ERR "Failure getting AC Link ready\n");
+
+	/* we depend on ac97 to perform the codec power up */
+	snd_ac97_resume(cs5535au->ac97);
+	/* set up rate regs, dma. actual initiation is done in trig */
+	for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) {
+		struct cs5535audio_dma *dma = &cs5535au->dmas[i];
+		if (dma && dma->substream && dma->suspended) {
+			dma->substream->ops->prepare(dma->substream);
+			dma->ops->setup_prd(cs5535au, dma->saved_prd);
+		}
+	}
+		
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+
+	return 0;
+}
+
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 42b11ba..549673e 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -46,13 +46,13 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int extin[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
-static int extout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+static int extin[SNDRV_CARDS];
+static int extout[SNDRV_CARDS];
 static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
 static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64};
 static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128};
-static int enable_ir[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
-static uint subsystem[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* Force card subsystem model */
+static int enable_ir[SNDRV_CARDS];
+static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard.");
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 6bfa084..42a358f 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -777,14 +777,6 @@
 
 static struct snd_emu_chip_details emu_chip_details[] = {
 	/* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
-	/* Audigy4 SB0400 */
-	{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102,
-	 .driver = "Audigy2", .name = "Audigy 4 [SB0400]", 
-	 .id = "Audigy2",
-	 .emu10k2_chip = 1,
-	 .ca0108_chip = 1,
-	 .spk71 = 1,
-	 .ac97_chip = 1} ,
 	/* Tested by James@superbug.co.uk 3rd July 2005 */
 	/* DSP: CA0108-IAT
 	 * DAC: CS4382-KQ
@@ -799,13 +791,59 @@
 	 .ca0108_chip = 1,
 	 .spk71 = 1,
 	 .ac97_chip = 1} ,
+	/* Audigy4 (Not PRO) SB0610 */
+	/* Tested by James@superbug.co.uk 4th April 2006 */
+	/* A_IOCFG bits
+	 * Output
+	 * 0: ?
+	 * 1: ?
+	 * 2: ?
+	 * 3: 0 - Digital Out, 1 - Line in
+	 * 4: ?
+	 * 5: ?
+	 * 6: ?
+	 * 7: ?
+	 * Input
+	 * 8: ?
+	 * 9: ?
+	 * A: Green jack sense (Front)
+	 * B: ?
+	 * C: Black jack sense (Rear/Side Right)
+	 * D: Yellow jack sense (Center/LFE/Side Left)
+	 * E: ?
+	 * F: ?
+	 *
+	 * Digital Out/Line in switch using A_IOCFG bit 3 (0x08)
+	 * 0 - Digital Out
+	 * 1 - Line in
+	 */
+	/* Mic input not tested.
+	 * Analog CD input not tested
+	 * Digital Out not tested.
+	 * Line in working.
+	 * Audio output 5.1 working. Side outputs not working.
+	 */
+	/* DSP: CA10300-IAT LF
+	 * DAC: Cirrus Logic CS4382-KQZ
+	 * ADC: Philips 1361T
+	 * AC97: Sigmatel STAC9750
+	 * CA0151: None
+	 */
+	{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102,
+	 .driver = "Audigy2", .name = "Audigy 4 [SB0610]", 
+	 .id = "Audigy2",
+	 .emu10k2_chip = 1,
+	 .ca0108_chip = 1,
+	 .spk71 = 1,
+	 .adc_1361t = 1,  /* 24 bit capture instead of 16bit */
+	 .ac97_chip = 1} ,
 	/* Audigy 2 ZS Notebook Cardbus card.*/
 	/* Tested by James@superbug.co.uk 22th December 2005 */
 	/* Audio output 7.1/Headphones working.
 	 * Digital output working. (AC3 not checked, only PCM)
 	 * Audio inputs not tested.
 	 */ 
-	/* DSP: Tiny2
+	/* DSP: Tina2
 	 * DAC: Wolfson WM8768/WM8568
 	 * ADC: Wolfson WM8775
 	 * AC97: None
@@ -1421,16 +1459,3 @@
 	}
 }
 #endif
-
-/* memory.c */
-EXPORT_SYMBOL(snd_emu10k1_synth_alloc);
-EXPORT_SYMBOL(snd_emu10k1_synth_free);
-EXPORT_SYMBOL(snd_emu10k1_synth_bzero);
-EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user);
-EXPORT_SYMBOL(snd_emu10k1_memblk_map);
-/* voice.c */
-EXPORT_SYMBOL(snd_emu10k1_voice_alloc);
-EXPORT_SYMBOL(snd_emu10k1_voice_free);
-/* io.c */
-EXPORT_SYMBOL(snd_emu10k1_ptr_read);
-EXPORT_SYMBOL(snd_emu10k1_ptr_write);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index d51290c..0fb27e4 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1055,8 +1055,7 @@
 	struct snd_info_entry *entry;
 	
 	if(! snd_card_proc_new(emu->card, "emu10k1x_regs", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_emu10k1x_proc_reg_read);
 		entry->c.text.write = snd_emu10k1x_proc_reg_write;
 		entry->mode |= S_IWUSR;
 		entry->private_data = emu;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 2a9d12d..c31f3d0 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -777,6 +777,8 @@
 	};
 	static char *audigy_remove_ctls[] = {
 		/* Master/PCM controls on ac97 of Audigy has no effect */
+		/* On the Audigy2 the AC97 playback is piped into
+		 * the Philips ADC for 24bit capture */
 		"PCM Playback Switch",
 		"PCM Playback Volume",
 		"Master Mono Playback Switch",
@@ -804,6 +806,47 @@
 		"AMic Playback Volume", "Mic Playback Volume",
 		NULL
 	};
+	static char *audigy_remove_ctls_1361t_adc[] = {
+		/* On the Audigy2 the AC97 playback is piped into
+		 * the Philips ADC for 24bit capture */
+		"PCM Playback Switch",
+		"PCM Playback Volume",
+		"Master Mono Playback Switch",
+		"Master Mono Playback Volume",
+		"Capture Source",
+		"Capture Switch",
+		"Capture Volume",
+		"Mic Capture Volume",
+		"Headphone Playback Switch",
+		"Headphone Playback Volume",
+		"3D Control - Center",
+		"3D Control - Depth",
+		"3D Control - Switch",
+		"Line2 Playback Volume",
+		"Line2 Capture Volume",
+		NULL
+	};
+	static char *audigy_rename_ctls_1361t_adc[] = {
+		"Master Playback Switch", "Master Capture Switch",
+		"Master Playback Volume", "Master Capture Volume",
+		"Wave Master Playback Volume", "Master Playback Volume",
+		"PC Speaker Playback Switch", "PC Speaker Capture Switch",
+		"PC Speaker Playback Volume", "PC Speaker Capture Volume",
+		"Phone Playback Switch", "Phone Capture Switch",
+		"Phone Playback Volume", "Phone Capture Volume",
+		"Mic Playback Switch", "Mic Capture Switch",
+		"Mic Playback Volume", "Mic Capture Volume",
+		"Line Playback Switch", "Line Capture Switch",
+		"Line Playback Volume", "Line Capture Volume",
+		"CD Playback Switch", "CD Capture Switch",
+		"CD Playback Volume", "CD Capture Volume",
+		"Aux Playback Switch", "Aux Capture Switch",
+		"Aux Playback Volume", "Aux Capture Volume",
+		"Video Playback Switch", "Video Capture Switch",
+		"Video Playback Volume", "Video Capture Volume",
+
+		NULL
+	};
 
 	if (emu->card_capabilities->ac97_chip) {
 		struct snd_ac97_bus *pbus;
@@ -834,7 +877,10 @@
 			snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
 			/* set capture source to mic */
 			snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
-			c = audigy_remove_ctls;
+			if (emu->card_capabilities->adc_1361t)
+				c = audigy_remove_ctls_1361t_adc;
+			else 
+				c = audigy_remove_ctls;
 		} else {
 			/*
 			 * Credits for cards based on STAC9758:
@@ -863,11 +909,15 @@
 	}
 
 	if (emu->audigy)
-		c = audigy_rename_ctls;
+		if (emu->card_capabilities->adc_1361t)
+			c = audigy_rename_ctls_1361t_adc;
+		else
+			c = audigy_rename_ctls;
 	else
 		c = emu10k1_rename_ctls;
 	for (; *c; c += 2)
 		rename_ctl(card, c[0], c[1]);
+
 	if (emu->card_capabilities->subsystem == 0x20071102) {  /* Audigy 4 Pro */
 		rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
 		rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index 90f1c52..b939e03 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -532,57 +532,51 @@
 	struct snd_info_entry *entry;
 #ifdef CONFIG_SND_DEBUG
 	if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
 		entry->c.text.write = snd_emu_proc_io_reg_write;
 		entry->mode |= S_IWUSR;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
-		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00a);
 		entry->c.text.write = snd_emu_proc_ptr_reg_write00;
 		entry->mode |= S_IWUSR;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
-		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read00b);
 		entry->c.text.write = snd_emu_proc_ptr_reg_write00;
 		entry->mode |= S_IWUSR;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
-		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20a);
 		entry->c.text.write = snd_emu_proc_ptr_reg_write20;
 		entry->mode |= S_IWUSR;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
-		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20b);
 		entry->c.text.write = snd_emu_proc_ptr_reg_write20;
 		entry->mode |= S_IWUSR;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs20c", &entry)) {
-		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20c);
-		entry->c.text.write_size = 64;
+		snd_info_set_text_ops(entry, emu, snd_emu_proc_ptr_reg_read20c);
 		entry->c.text.write = snd_emu_proc_ptr_reg_write20;
 		entry->mode |= S_IWUSR;
 	}
 #endif
 	
 	if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
-		snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read);
+		snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_read);
 
 	if (emu->card_capabilities->emu10k2_chip) {
 		if (! snd_card_proc_new(emu->card, "spdif-in", &entry))
-			snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read);
+			snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_spdif_read);
 	}
 	if (emu->card_capabilities->ca0151_chip) {
 		if (! snd_card_proc_new(emu->card, "capture-rates", &entry))
-			snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read);
+			snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_rates_read);
 	}
 
 	if (! snd_card_proc_new(emu->card, "voices", &entry))
-		snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
+		snd_info_set_text_ops(entry, emu, snd_emu10k1_proc_voices_read);
 
 	if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
@@ -616,7 +610,6 @@
 		entry->content = SNDRV_INFO_CONTENT_TEXT;
 		entry->private_data = emu;
 		entry->mode = S_IFREG | S_IRUGO /*| S_IWUSR*/;
-		entry->c.text.read_size = 128*1024;
 		entry->c.text.read = snd_emu10k1_proc_acode_read;
 	}
 	return 0;
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index ef5304d..029e785 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -62,6 +62,8 @@
 	}
 }
 
+EXPORT_SYMBOL(snd_emu10k1_ptr_read);
+
 void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
 {
 	unsigned int regptr;
@@ -92,6 +94,8 @@
 	}
 }
 
+EXPORT_SYMBOL(snd_emu10k1_ptr_write);
+
 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, 
 					  unsigned int reg, 
 					  unsigned int chn)
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index e7ec986..4fcaefe 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -287,6 +287,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_memblk_map);
+
 /*
  * page allocation for DMA
  */
@@ -387,6 +389,7 @@
 	return (struct snd_util_memblk *)blk;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_synth_alloc);
 
 /*
  * free a synth sample area
@@ -409,6 +412,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_synth_free);
 
 /* check new allocation range */
 static void get_single_page_range(struct snd_util_memhdr *hdr,
@@ -540,6 +544,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_synth_bzero);
+
 /*
  * copy_from_user(blk + offset, data, size)
  */
@@ -568,3 +574,5 @@
 	} while (offset < end_offset);
 	return 0;
 }
+
+EXPORT_SYMBOL(snd_emu10k1_synth_copy_from_user);
diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h
new file mode 100644
index 0000000..7ddb5be
--- /dev/null
+++ b/sound/pci/emu10k1/p17v.h
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
+ *  Driver p17v chips
+ *  Version: 0.01
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/******************************************************************************/
+/* Audigy2Value Tina (P17V) pointer-offset register set,
+ * accessed through the PTR20 and DATA24 registers  */
+/******************************************************************************/
+
+/* 00 - 07: Not used */
+#define P17V_PLAYBACK_FIFO_PTR	0x08	/* Current playback fifo pointer
+					 * and number of sound samples in cache.
+					 */  
+/* 09 - 12: Not used */
+#define P17V_CAPTURE_FIFO_PTR	0x13	/* Current capture fifo pointer
+					 * and number of sound samples in cache.
+					 */  
+/* 14 - 17: Not used */
+#define P17V_PB_CHN_SEL		0x18	/* P17v playback channel select */
+#define P17V_SE_SLOT_SEL_L	0x19	/* Sound Engine slot select low */
+#define P17V_SE_SLOT_SEL_H	0x1a	/* Sound Engine slot select high */
+/* 1b - 1f: Not used */
+/* 20 - 2f: Not used */
+/* 30 - 3b: Not used */
+#define P17V_SPI		0x3c	/* SPI interface register */
+#define P17V_I2C_ADDR		0x3d	/* I2C Address */
+#define P17V_I2C_0		0x3e	/* I2C Data */
+#define P17V_I2C_1		0x3f	/* I2C Data */
+
+#define P17V_START_AUDIO	0x40	/* Start Audio bit */
+/* 41 - 47: Reserved */
+#define P17V_START_CAPTURE	0x48	/* Start Capture bit */
+#define P17V_CAPTURE_FIFO_BASE	0x49	/* Record FIFO base address */
+#define P17V_CAPTURE_FIFO_SIZE	0x4a	/* Record FIFO buffer size */
+#define P17V_CAPTURE_FIFO_INDEX	0x4b	/* Record FIFO capture index */
+#define P17V_CAPTURE_VOL_H	0x4c	/* P17v capture volume control */
+#define P17V_CAPTURE_VOL_L	0x4d	/* P17v capture volume control */
+/* 4e - 4f: Not used */
+/* 50 - 5f: Not used */
+#define P17V_SRCSel		0x60	/* SRC48 and SRCMulti sample rate select
+					 * and output select
+					 */
+#define P17V_MIXER_AC97_10K1_VOL_L	0x61	/* 10K to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_10K1_VOL_H	0x62	/* 10K to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_P17V_VOL_L	0x63	/* P17V to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_P17V_VOL_H	0x64	/* P17V to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_SRP_REC_VOL_L	0x65	/* SRP Record to Mixer_AC97 input volume control */
+#define P17V_MIXER_AC97_SRP_REC_VOL_H	0x66	/* SRP Record to Mixer_AC97 input volume control */
+/* 67 - 68: Reserved */
+#define P17V_MIXER_Spdif_10K1_VOL_L	0x69	/* 10K to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_10K1_VOL_H	0x6A	/* 10K to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_P17V_VOL_L	0x6B	/* P17V to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_P17V_VOL_H	0x6C	/* P17V to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_SRP_REC_VOL_L	0x6D	/* SRP Record to Mixer_Spdif input volume control */
+#define P17V_MIXER_Spdif_SRP_REC_VOL_H	0x6E	/* SRP Record to Mixer_Spdif input volume control */
+/* 6f - 70: Reserved */
+#define P17V_MIXER_I2S_10K1_VOL_L	0x71	/* 10K to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_10K1_VOL_H	0x72	/* 10K to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_P17V_VOL_L	0x73	/* P17V to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_P17V_VOL_H	0x74	/* P17V to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_SRP_REC_VOL_L	0x75	/* SRP Record to Mixer_I2S input volume control */
+#define P17V_MIXER_I2S_SRP_REC_VOL_H	0x76	/* SRP Record to Mixer_I2S input volume control */
+/* 77 - 78: Reserved */
+#define P17V_MIXER_AC97_ENABLE		0x79	/* Mixer AC97 input audio enable */
+#define P17V_MIXER_SPDIF_ENABLE		0x7A	/* Mixer SPDIF input audio enable */
+#define P17V_MIXER_I2S_ENABLE		0x7B	/* Mixer I2S input audio enable */
+#define P17V_AUDIO_OUT_ENABLE		0x7C	/* Audio out enable */
+#define P17V_MIXER_ATT			0x7D	/* SRP Mixer Attenuation Select */
+#define P17V_SRP_RECORD_SRR		0x7E	/* SRP Record channel source Select */
+#define P17V_SOFT_RESET_SRP_MIXER	0x7F	/* SRP and mixer soft reset */
+
+#define P17V_AC97_OUT_MASTER_VOL_L	0x80	/* AC97 Output master volume control */
+#define P17V_AC97_OUT_MASTER_VOL_H	0x81	/* AC97 Output master volume control */
+#define P17V_SPDIF_OUT_MASTER_VOL_L	0x82	/* SPDIF Output master volume control */
+#define P17V_SPDIF_OUT_MASTER_VOL_H	0x83	/* SPDIF Output master volume control */
+#define P17V_I2S_OUT_MASTER_VOL_L	0x84	/* I2S Output master volume control */
+#define P17V_I2S_OUT_MASTER_VOL_H	0x85	/* I2S Output master volume control */
+/* 86 - 87: Not used */
+#define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE	0x88	/* I2S out mono channel swap
+							 * and phase inverse */
+#define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE	0x89	/* SPDIF out mono channel swap
+							 * and phase inverse */
+/* 8A: Not used */
+#define P17V_SRP_P17V_ESR		0x8B	/* SRP_P17V estimated sample rate and rate lock */
+#define P17V_SRP_REC_ESR		0x8C	/* SRP_REC estimated sample rate and rate lock */
+#define P17V_SRP_BYPASS			0x8D	/* srps channel bypass and srps bypass */
+/* 8E - 92: Not used */
+#define P17V_I2S_SRC_SEL		0x93	/* I2SIN mode sel */
+
+
+
+
+
+
diff --git a/sound/pci/emu10k1/tina2.h b/sound/pci/emu10k1/tina2.h
index 5c43abf..f2d8eb6 100644
--- a/sound/pci/emu10k1/tina2.h
+++ b/sound/pci/emu10k1/tina2.h
@@ -1,11 +1,7 @@
 /*
  *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
- *  Driver p16v chips
- *  Version: 0.21
- *
- *
- *  This code was initally based on code from ALSA's emu10k1x.c which is:
- *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
+ *  Driver tina2 chips
+ *  Version: 0.1
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index 56ffb7d..94eca82 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -139,6 +139,8 @@
 	return result;
 }
 
+EXPORT_SYMBOL(snd_emu10k1_voice_alloc);
+
 int snd_emu10k1_voice_free(struct snd_emu10k1 *emu,
 			   struct snd_emu10k1_voice *pvoice)
 {
@@ -153,3 +155,5 @@
 	spin_unlock_irqrestore(&emu->voice_lock, flags);
 	return 0;
 }
+
+EXPORT_SYMBOL(snd_emu10k1_voice_free);
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index ca9e34e..9d46bbe 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -1915,7 +1915,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry))
-		snd_info_set_text_ops(entry, ensoniq, 1024, snd_ensoniq_proc_read);
+		snd_info_set_text_ops(entry, ensoniq, snd_ensoniq_proc_read);
 }
 
 /*
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 6f9094c..ca6603f 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1756,7 +1756,8 @@
 		}
 	}
 	if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
-				chip->mpu_port, 1, chip->irq, 0, &chip->rmidi) < 0) {
+				chip->mpu_port, MPU401_INFO_INTEGRATED,
+				chip->irq, 0, &chip->rmidi) < 0) {
 		printk(KERN_ERR "es1938: unable to initialize MPU-401\n");
 	} else {
 		// this line is vital for MIDI interrupt handling on ess-solo1
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 5ff4175..bfa0876 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -132,7 +132,7 @@
 static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 };
 static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 };
 static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 };
-static int clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+static int clock[SNDRV_CARDS];
 static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
 static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
 #ifdef SUPPORT_JOYSTICK
@@ -2727,7 +2727,8 @@
 	}
 	if (enable_mpu[dev]) {
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
-					       chip->io_port + ESM_MPU401_PORT, 1,
+					       chip->io_port + ESM_MPU401_PORT,
+					       MPU401_INFO_INTEGRATED,
 					       chip->irq, 0, &chip->rmidi)) < 0) {
 			printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n");
 		}
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index d72fc28..0afa573 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -56,7 +56,7 @@
  *    3 = MediaForte 64-PCR
  *  High 16-bits are video (radio) device number + 1
  */
-static int tea575x_tuner[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 };
+static int tea575x_tuner[SNDRV_CARDS];
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for the FM801 soundcard.");
@@ -1448,7 +1448,8 @@
 		return err;
 	}
 	if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801,
-				       FM801_REG(chip, MPU401_DATA), 1,
+				       FM801_REG(chip, MPU401_DATA),
+				       MPU401_INFO_INTEGRATED,
 				       chip->irq, 0, &chip->rmidi)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index ddfb5ff..dbacba6 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,5 @@
 snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o patch_atihdmi.o
 ifdef CONFIG_PROC_FS
 snd-hda-codec-objs += hda_proc.o
 endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 5bee3b5..8c2a817 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -86,6 +86,8 @@
 	return res;
 }
 
+EXPORT_SYMBOL(snd_hda_codec_read);
+
 /**
  * snd_hda_codec_write - send a single command without waiting for response
  * @codec: the HDA codec
@@ -108,6 +110,8 @@
 	return err;
 }
 
+EXPORT_SYMBOL(snd_hda_codec_write);
+
 /**
  * snd_hda_sequence_write - sequence writes
  * @codec: the HDA codec
@@ -122,6 +126,8 @@
 		snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
 }
 
+EXPORT_SYMBOL(snd_hda_sequence_write);
+
 /**
  * snd_hda_get_sub_nodes - get the range of sub nodes
  * @codec: the HDA codec
@@ -140,6 +146,8 @@
 	return (int)(parm & 0x7fff);
 }
 
+EXPORT_SYMBOL(snd_hda_get_sub_nodes);
+
 /**
  * snd_hda_get_connections - get connection list
  * @codec: the HDA codec
@@ -256,6 +264,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_hda_queue_unsol_event);
+
 /*
  * process queueud unsolicited events
  */
@@ -384,6 +394,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_hda_bus_new);
 
 /*
  * find a matching codec preset
@@ -587,6 +598,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_hda_codec_new);
+
 /**
  * snd_hda_codec_setup_stream - set up the codec for streaming
  * @codec: the CODEC to set up
@@ -609,6 +622,7 @@
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
 }
 
+EXPORT_SYMBOL(snd_hda_codec_setup_stream);
 
 /*
  * amp access functions
@@ -1294,6 +1308,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_hda_build_controls);
 
 /*
  * stream formats
@@ -1382,6 +1397,8 @@
 	return val;
 }
 
+EXPORT_SYMBOL(snd_hda_calc_stream_format);
+
 /**
  * snd_hda_query_supported_pcm - query the supported PCM rates and formats
  * @codec: the HDA codec
@@ -1663,6 +1680,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_hda_build_pcms);
 
 /**
  * snd_hda_check_board_config - compare the current codec with the config table
@@ -2165,6 +2183,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_hda_suspend);
+
 /**
  * snd_hda_resume - resume the codecs
  * @bus: the HDA bus
@@ -2187,6 +2207,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_hda_resume);
+
 /**
  * snd_hda_resume_ctls - resume controls in the new control list
  * @codec: the HDA codec
@@ -2247,25 +2269,6 @@
 #endif
 
 /*
- * symbols exported for controller modules
- */
-EXPORT_SYMBOL(snd_hda_codec_read);
-EXPORT_SYMBOL(snd_hda_codec_write);
-EXPORT_SYMBOL(snd_hda_sequence_write);
-EXPORT_SYMBOL(snd_hda_get_sub_nodes);
-EXPORT_SYMBOL(snd_hda_queue_unsol_event);
-EXPORT_SYMBOL(snd_hda_bus_new);
-EXPORT_SYMBOL(snd_hda_codec_new);
-EXPORT_SYMBOL(snd_hda_codec_setup_stream);
-EXPORT_SYMBOL(snd_hda_calc_stream_format);
-EXPORT_SYMBOL(snd_hda_build_pcms);
-EXPORT_SYMBOL(snd_hda_build_controls);
-#ifdef CONFIG_PM
-EXPORT_SYMBOL(snd_hda_suspend);
-EXPORT_SYMBOL(snd_hda_resume);
-#endif
-
-/*
  *  INIT part
  */
 
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index e821d65..4070b5c 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -82,6 +82,7 @@
 			 "{Intel, ICH8},"
 			 "{ATI, SB450},"
 			 "{ATI, SB600},"
+			 "{ATI, RS600},"
 			 "{VIA, VT8251},"
 			 "{VIA, VT8237A},"
 			 "{SiS, SIS966},"
@@ -167,6 +168,12 @@
 #define ULI_PLAYBACK_INDEX	5
 #define ULI_NUM_PLAYBACK	6
 
+/* ATI HDMI has 1 playback and 0 capture */
+#define ATIHDMI_CAPTURE_INDEX	0
+#define ATIHDMI_NUM_CAPTURE	0
+#define ATIHDMI_PLAYBACK_INDEX	0
+#define ATIHDMI_NUM_PLAYBACK	1
+
 /* this number is statically defined for simplicity */
 #define MAX_AZX_DEV		16
 
@@ -331,6 +338,7 @@
 enum {
 	AZX_DRIVER_ICH,
 	AZX_DRIVER_ATI,
+	AZX_DRIVER_ATIHDMI,
 	AZX_DRIVER_VIA,
 	AZX_DRIVER_SIS,
 	AZX_DRIVER_ULI,
@@ -340,6 +348,7 @@
 static char *driver_short_names[] __devinitdata = {
 	[AZX_DRIVER_ICH] = "HDA Intel",
 	[AZX_DRIVER_ATI] = "HDA ATI SB",
+	[AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
 	[AZX_DRIVER_VIA] = "HDA VIA VT82xx",
 	[AZX_DRIVER_SIS] = "HDA SIS966",
 	[AZX_DRIVER_ULI] = "HDA ULI M5461",
@@ -1393,10 +1402,10 @@
 		msleep(1);
 	}
 
-	if (chip->remap_addr)
-		iounmap(chip->remap_addr);
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void*)chip);
+	if (chip->remap_addr)
+		iounmap(chip->remap_addr);
 
 	if (chip->bdl.area)
 		snd_dma_free_pages(&chip->bdl);
@@ -1495,6 +1504,12 @@
 		chip->playback_index_offset = ULI_PLAYBACK_INDEX;
 		chip->capture_index_offset = ULI_CAPTURE_INDEX;
 		break;
+	case AZX_DRIVER_ATIHDMI:
+		chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
+		chip->capture_streams = ATIHDMI_NUM_CAPTURE;
+		chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
+		chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
+		break;
 	default:
 		chip->playback_streams = ICH6_NUM_PLAYBACK;
 		chip->capture_streams = ICH6_NUM_CAPTURE;
@@ -1621,6 +1636,7 @@
 	{ 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
 	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
 	{ 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
+	{ 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
 	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
 	{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
 	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index acaef3c8..0b66879 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -12,6 +12,8 @@
 extern struct hda_codec_preset snd_hda_preset_sigmatel[];
 /* SiLabs 3054/3055 modem codecs */
 extern struct hda_codec_preset snd_hda_preset_si3054[];
+/* ATI HDMI codecs */
+extern struct hda_codec_preset snd_hda_preset_atihdmi[];
 
 static const struct hda_codec_preset *hda_preset_tables[] = {
 	snd_hda_preset_realtek,
@@ -19,5 +21,6 @@
 	snd_hda_preset_analog,
 	snd_hda_preset_sigmatel,
 	snd_hda_preset_si3054,
+	snd_hda_preset_atihdmi,
 	NULL
 };
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index ca514a6..c2f0fe8 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -182,6 +182,10 @@
 		snd_iprintf(buffer, " OUT");
 	if (caps & AC_PINCAP_HP_DRV)
 		snd_iprintf(buffer, " HP");
+	if (caps & AC_PINCAP_EAPD)
+		snd_iprintf(buffer, " EAPD");
+	if (caps & AC_PINCAP_PRES_DETECT)
+		snd_iprintf(buffer, " Detect");
 	snd_iprintf(buffer, "\n");
 	caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
 	snd_iprintf(buffer, "  Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
@@ -318,7 +322,7 @@
 	if (err < 0)
 		return err;
 
-	snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info);
+	snd_info_set_text_ops(entry, codec, print_codec_info);
 	return 0;
 }
 
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 40f000b..dd4e00a 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -789,6 +789,8 @@
 	{ .modelname = "3stack",	.config = AD1986A_3STACK },
 	{ .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84,
 	  .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3,
+	  .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */
 	{ .modelname = "laptop",	.config = AD1986A_LAPTOP },
 	{ .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e,
 	  .config = AD1986A_LAPTOP }, /* FSC V2060 */
@@ -809,6 +811,8 @@
 	  .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x30af,
 	  .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */
+	{ .pci_subvendor = 0x17aa, .pci_subdevice = 0x2066,
+	  .config = AD1986A_LAPTOP_EAPD }, /* Lenovo 3000 N100-07684JU */
 	{}
 };
 
@@ -963,7 +967,7 @@
 	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
 		.info = ad1983_spdif_route_info,
 		.get = ad1983_spdif_route_get,
 		.put = ad1983_spdif_route_put,
@@ -1103,7 +1107,7 @@
 	/* identical with AD1983 */
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
 		.info = ad1983_spdif_route_info,
 		.get = ad1983_spdif_route_get,
 		.put = ad1983_spdif_route_put,
@@ -1329,13 +1333,60 @@
 	return 0;
 }
 
+/* configuration for Lenovo Thinkpad T60 */
+static struct snd_kcontrol_new ad1981_thinkpad_mixers[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0x05, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = ad198x_mux_enum_info,
+		.get = ad198x_mux_enum_get,
+		.put = ad198x_mux_enum_put,
+	},
+	/* identical with AD1983 */
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+		.info = ad1983_spdif_route_info,
+		.get = ad1983_spdif_route_get,
+		.put = ad1983_spdif_route_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_input_mux ad1981_thinkpad_capture_source = {
+	.num_items = 3,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Mix", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
 /* models */
-enum { AD1981_BASIC, AD1981_HP };
+enum { AD1981_BASIC, AD1981_HP, AD1981_THINKPAD };
 
 static struct hda_board_config ad1981_cfg_tbl[] = {
 	{ .modelname = "hp", .config = AD1981_HP },
 	/* All HP models */
 	{ .pci_subvendor = 0x103c, .config = AD1981_HP },
+	{ .pci_subvendor = 0x30b0, .pci_subdevice = 0x103c,
+	  .config = AD1981_HP }, /* HP nx6320 (reversed SSID, H/W bug) */
+	{ .modelname = "thinkpad", .config = AD1981_THINKPAD },
+	/* Lenovo Thinkpad T60/X60/Z6xx */
+	{ .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD },
+	{ .pci_subvendor = 0x1014, .pci_subdevice = 0x0597,
+	  .config = AD1981_THINKPAD }, /* Z60m/t */
 	{ .modelname = "basic", .config = AD1981_BASIC },
 	{}
 };
@@ -1381,6 +1432,10 @@
 		codec->patch_ops.init = ad1981_hp_init;
 		codec->patch_ops.unsol_event = ad1981_hp_unsol_event;
 		break;
+	case AD1981_THINKPAD:
+		spec->mixers[0] = ad1981_thinkpad_mixers;
+		spec->input_mux = &ad1981_thinkpad_capture_source;
+		break;
 	}
 
 	return 0;
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
new file mode 100644
index 0000000..a27440f
--- /dev/null
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -0,0 +1,165 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for ATI HDMI codecs
+ *
+ * Copyright (c) 2006 ATI Technologies Inc.
+ *
+ *
+ *  This driver is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+struct atihdmi_spec {
+	struct hda_multi_out multiout;
+
+	struct hda_pcm pcm_rec;
+};
+
+static struct hda_verb atihdmi_basic_init[] = {
+	/* enable digital output on pin widget */
+	{ 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{} /* terminator */
+};
+
+/*
+ * Controls
+ */
+static int atihdmi_build_controls(struct hda_codec *codec)
+{
+	struct atihdmi_spec *spec = codec->spec;
+	int err;
+
+	err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static int atihdmi_init(struct hda_codec *codec)
+{
+	snd_hda_sequence_write(codec, atihdmi_basic_init);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int atihdmi_resume(struct hda_codec *codec)
+{
+	atihdmi_init(codec);
+	snd_hda_resume_spdif_out(codec);
+
+	return 0;
+}
+#endif
+
+/*
+ * Digital out
+ */
+static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				     struct hda_codec *codec,
+				     struct snd_pcm_substream *substream)
+{
+	struct atihdmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      struct snd_pcm_substream *substream)
+{
+	struct atihdmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x2, /* NID to query formats and rates and setup streams */
+	.ops = {
+		.open = atihdmi_dig_playback_pcm_open,
+		.close = atihdmi_dig_playback_pcm_close
+	},
+};
+
+static int atihdmi_build_pcms(struct hda_codec *codec)
+{
+	struct atihdmi_spec *spec = codec->spec;
+	struct hda_pcm *info = &spec->pcm_rec;
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = "ATI HDMI";
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
+
+	return 0;
+}
+
+static void atihdmi_free(struct hda_codec *codec)
+{
+	kfree(codec->spec);
+}
+
+static struct hda_codec_ops atihdmi_patch_ops = {
+	.build_controls = atihdmi_build_controls,
+	.build_pcms = atihdmi_build_pcms,
+	.init = atihdmi_init,
+	.free = atihdmi_free,
+#ifdef CONFIG_PM
+	.resume = atihdmi_resume,
+#endif
+};
+
+static int patch_atihdmi(struct hda_codec *codec)
+{
+	struct atihdmi_spec *spec;
+
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	spec->multiout.num_dacs = 0;	  /* no analog */
+	spec->multiout.max_channels = 2;
+	spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital,
+					   * seems to be unused in pure-digital
+					   * case. */
+
+	codec->patch_ops = atihdmi_patch_ops;
+
+	return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_atihdmi[] = {
+	{ .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
+	{} /* terminator */
+};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index f0e9a9c..98b9f16c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2174,6 +2174,7 @@
 
 	{ .modelname = "lg", .config = ALC880_LG },
 	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG },
+	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x0068, .config = ALC880_LG },
 
 	{ .modelname = "lg-lw", .config = ALC880_LG_LW },
 	{ .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
@@ -3105,6 +3106,7 @@
 	{ }
 };
 
+#if 0 /* should be identical with alc260_init_verbs? */
 static struct hda_verb alc260_hp_init_verbs[] = {
 	/* Headphone and output */
 	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
@@ -3151,6 +3153,7 @@
 	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
 	{ }
 };
+#endif
 
 static struct hda_verb alc260_hp_3013_init_verbs[] = {
 	/* Line out and output */
@@ -3822,12 +3825,16 @@
 	{ .modelname = "basic", .config = ALC260_BASIC },
 	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb,
 	  .config = ALC260_BASIC }, /* Sony VAIO */
+	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81cc,
+	  .config = ALC260_BASIC }, /* Sony VAIO VGN-S3HP */
+	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81cd,
+	  .config = ALC260_BASIC }, /* Sony VAIO */
 	{ .pci_subvendor = 0x152d, .pci_subdevice = 0x0729,
 	  .config = ALC260_BASIC }, /* CTL Travel Master U553W */
 	{ .modelname = "hp", .config = ALC260_HP },
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP },
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
-	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP },
+	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 },
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
 	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
@@ -3862,7 +3869,7 @@
 		.mixers = { alc260_base_output_mixer,
 			    alc260_input_mixer,
 			    alc260_capture_alt_mixer },
-		.init_verbs = { alc260_hp_init_verbs },
+		.init_verbs = { alc260_init_verbs },
 		.num_dacs = ARRAY_SIZE(alc260_dac_nids),
 		.dac_nids = alc260_dac_nids,
 		.num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
@@ -4094,21 +4101,6 @@
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 3,
-		.info = alc882_mux_enum_info,
-		.get = alc882_mux_enum_get,
-		.put = alc882_mux_enum_put,
-	},
 	{ } /* end */
 };
 
@@ -4342,8 +4334,6 @@
 		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
 		.dac_nids = alc882_dac_nids,
 		.dig_out_nid = ALC882_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
-		.adc_nids = alc882_adc_nids,
 		.dig_in_nid = ALC882_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 		.channel_mode = alc882_ch_modes,
@@ -4355,8 +4345,6 @@
 		.num_dacs = ARRAY_SIZE(alc882_dac_nids),
 		.dac_nids = alc882_dac_nids,
 		.dig_out_nid = ALC882_DIGOUT_NID,
-		.num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
-		.adc_nids = alc882_adc_nids,
 		.dig_in_nid = ALC882_DIGIN_NID,
 		.num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
 		.channel_mode = alc882_sixstack_modes,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 8c440fb..36f1994 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -41,6 +41,7 @@
 #define STAC_REF		0
 #define STAC_D945GTP3		1
 #define STAC_D945GTP5		2
+#define STAC_MACMINI		3
 
 struct sigmatel_spec {
 	struct snd_kcontrol_new *mixers[4];
@@ -52,6 +53,7 @@
 	unsigned int mic_switch: 1;
 	unsigned int alt_switch: 1;
 	unsigned int hp_detect: 1;
+	unsigned int gpio_mute: 1;
 
 	/* playback */
 	struct hda_multi_out multiout;
@@ -293,6 +295,7 @@
 	ref922x_pin_configs,
 	d945gtp3_pin_configs,
 	d945gtp5_pin_configs,
+	NULL,		/* STAC_MACMINI */
 };
 
 static struct hda_board_config stac922x_cfg_tbl[] = {
@@ -324,6 +327,9 @@
 	{ .pci_subvendor = PCI_VENDOR_ID_INTEL,
 	  .pci_subdevice = 0x0417,
 	  .config = STAC_D945GTP5 },	/* Intel D975XBK - 5 Stack */
+	{ .pci_subvendor = 0x8384,
+	  .pci_subdevice = 0x7680,
+	  .config = STAC_MACMINI },	/* Apple Mac Mini (early 2006) */
 	{} /* terminator */
 };
 
@@ -841,6 +847,19 @@
 		}
 	}
 
+	if (imux->num_items == 1) {
+		/*
+		 * Set the current input for the muxes.
+		 * The STAC9221 has two input muxes with identical source
+		 * NID lists.  Hopefully this won't get confused.
+		 */
+		for (i = 0; i < spec->num_muxes; i++) {
+			snd_hda_codec_write(codec, spec->mux_nids[i], 0,
+					    AC_VERB_SET_CONNECT_SEL,
+					    imux->items[0].index);
+		}
+	}
+
 	return 0;
 }
 
@@ -946,6 +965,45 @@
 	return 1;
 }
 
+/*
+ * Early 2006 Intel Macintoshes with STAC9220X5 codecs seem to have a
+ * funky external mute control using GPIO pins.
+ */
+
+static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted)
+{
+	unsigned int gpiostate, gpiomask, gpiodir;
+
+	gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
+				       AC_VERB_GET_GPIO_DATA, 0);
+
+	if (!muted)
+		gpiostate |= (1 << pin);
+	else
+		gpiostate &= ~(1 << pin);
+
+	gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
+				      AC_VERB_GET_GPIO_MASK, 0);
+	gpiomask |= (1 << pin);
+
+	gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
+				     AC_VERB_GET_GPIO_DIRECTION, 0);
+	gpiodir |= (1 << pin);
+
+	/* AppleHDA seems to do this -- WTF is this verb?? */
+	snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0);
+
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_MASK, gpiomask);
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DIRECTION, gpiodir);
+
+	msleep(1);
+
+	snd_hda_codec_write(codec, codec->afg, 0,
+			    AC_VERB_SET_GPIO_DATA, gpiostate);
+}
+
 static int stac92xx_init(struct hda_codec *codec)
 {
 	struct sigmatel_spec *spec = codec->spec;
@@ -982,6 +1040,11 @@
 		stac92xx_auto_set_pinctl(codec, cfg->dig_in_pin,
 					 AC_PINCTL_IN_EN);
 
+	if (spec->gpio_mute) {
+		stac922x_gpio_mute(codec, 0, 0);
+		stac922x_gpio_mute(codec, 1, 0);
+	}
+
 	return 0;
 }
 
@@ -1132,7 +1195,7 @@
 	spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl);
 	if (spec->board_config < 0)
                 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, using BIOS defaults\n");
-	else {
+	else if (stac922x_brd_tbl[spec->board_config] != NULL) {
 		spec->num_pins = 10;
 		spec->pin_nids = stac922x_pin_nids;
 		spec->pin_configs = stac922x_brd_tbl[spec->board_config];
@@ -1154,6 +1217,9 @@
 		return err;
 	}
 
+	if (spec->board_config == STAC_MACMINI)
+		spec->gpio_mute = 1;
+
 	codec->patch_ops = stac92xx_patch_ops;
 
 	return 0;
@@ -1262,13 +1328,13 @@
 	int change;
 
 	change = snd_hda_codec_amp_update(codec, 0x02, 0, HDA_OUTPUT, 0,
-					  0x80, valp[0] & 0x80);
+					  0x80, (valp[0] ? 0 : 0x80));
 	change |= snd_hda_codec_amp_update(codec, 0x02, 1, HDA_OUTPUT, 0,
-					   0x80, valp[1] & 0x80);
+					   0x80, (valp[1] ? 0 : 0x80));
 	snd_hda_codec_amp_update(codec, 0x05, 0, HDA_OUTPUT, 0,
-				 0x80, valp[0] & 0x80);
+				 0x80, (valp[0] ? 0 : 0x80));
 	snd_hda_codec_amp_update(codec, 0x05, 1, HDA_OUTPUT, 0,
-				 0x80, valp[1] & 0x80);
+				 0x80, (valp[1] ? 0 : 0x80));
 	return change;
 }
 
@@ -1370,6 +1436,12 @@
  	{ .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
  	{ .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
  	{ .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
+ 	{ .id = 0x83847618, .name = "STAC9227", .patch = patch_stac922x },
+ 	{ .id = 0x83847619, .name = "STAC9227", .patch = patch_stac922x },
+ 	{ .id = 0x83847616, .name = "STAC9228", .patch = patch_stac922x },
+ 	{ .id = 0x83847617, .name = "STAC9228", .patch = patch_stac922x },
+ 	{ .id = 0x83847614, .name = "STAC9229", .patch = patch_stac922x },
+ 	{ .id = 0x83847615, .name = "STAC9229", .patch = patch_stac922x },
  	{ .id = 0x83847620, .name = "STAC9274", .patch = patch_stac927x },
  	{ .id = 0x83847621, .name = "STAC9274D", .patch = patch_stac927x },
  	{ .id = 0x83847622, .name = "STAC9273X", .patch = patch_stac927x },
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 336dc48..ca74f5b 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1281,9 +1281,15 @@
 
 	tmp2 = tmp = snd_ice1712_gpio_read(ice);
 	if (enable)
-		tmp |= AUREON_HP_SEL;
+		if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
+			tmp |= AUREON_HP_SEL;
+		else
+			tmp |= PRODIGY_HP_SEL;
 	else
-		tmp &= ~ AUREON_HP_SEL;
+		if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT)
+			tmp &= ~ AUREON_HP_SEL;
+		else
+			tmp &= ~ PRODIGY_HP_SEL;
 	if (tmp != tmp2) {
 		snd_ice1712_gpio_write(ice, tmp);
 		return 1;
@@ -2079,16 +2085,16 @@
 };
 
 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
-	0x0b,	/* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
+	0x4b,	/* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
 	0x80,	/* ACLINK: I2S */
 	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
-	0xc3,	/* SPDUF: out-en, out-int */
-	0x00,	/* GPIO_DIR */
-	0x07,	/* GPIO_DIR1 */
-	0x00,	/* GPIO_DIR2 */
-	0xff,	/* GPIO_MASK */
-	0xf8,	/* GPIO_MASK1 */
-	0xff,	/* GPIO_MASK2 */
+	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
+	0xff,	/* GPIO_DIR */
+	0xff,	/* GPIO_DIR1 */
+	0x5f,	/* GPIO_DIR2 */
+	0x00,	/* GPIO_MASK */
+	0x00,	/* GPIO_MASK1 */
+	0x00,	/* GPIO_MASK2 */
 	0x00,	/* GPIO_STATE */
 	0x00,	/* GPIO_STATE1 */
 	0x00,	/* GPIO_STATE2 */
diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h
index 98a6752..3b7bea6 100644
--- a/sound/pci/ice1712/aureon.h
+++ b/sound/pci/ice1712/aureon.h
@@ -58,5 +58,6 @@
 #define PRODIGY_WM_CS		(1 << 8)
 #define PRODIGY_SPI_MOSI	(1 << 10)
 #define PRODIGY_SPI_CLK		(1 << 9)
+#define PRODIGY_HP_SEL		(1 << 5)
 
 #endif /* __SOUND_AUREON_H */
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index 2c529e7..b135389 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -1031,6 +1031,9 @@
 		.model = "dmx6fire",
 		.chip_init = snd_ice1712_ews_init,
 		.build_controls = snd_ice1712_ews_add_controls,
+		.mpu401_1_name = "MIDI-Front DMX6fire",
+		.mpu401_2_name = "Wavetable DMX6fire",
+		.mpu401_2_info_flags = MPU401_INFO_OUTPUT,
 	},
 	{ } /* terminator */
 };
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index c56793b..8459071 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -61,7 +61,6 @@
 #include <sound/core.h>
 #include <sound/cs8427.h>
 #include <sound/info.h>
-#include <sound/mpu401.h>
 #include <sound/initval.h>
 
 #include <sound/asoundef.h>
@@ -1596,7 +1595,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(ice->card, "ice1712", &entry))
-		snd_info_set_text_ops(entry, ice, 1024, snd_ice1712_proc_read);
+		snd_info_set_text_ops(entry, ice, snd_ice1712_proc_read);
 }
 
 /*
@@ -2398,13 +2397,14 @@
 	udelay(200);
 	outb(ICE1712_NATIVE, ICEREG(ice, CONTROL));
 	udelay(200);
-	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE && !ice->dxr_enable) {
-                /* Limit active ADCs and DACs to 6;  */
-                /* Note: DXR extension not supported */
-		pci_write_config_byte(ice->pci, 0x60, 0x2a);
-	} else {
-		pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]);
-	}
+	if (ice->eeprom.subvendor == ICE1712_SUBDEVICE_DMX6FIRE &&
+	    !ice->dxr_enable)
+		/*  Set eeprom value to limit active ADCs and DACs to 6;
+		 *  Also disable AC97 as no hardware in standard 6fire card/box
+		 *  Note: DXR extensions are not currently supported
+		 */
+		ice->eeprom.data[ICE_EEP1_CODEC] = 0x3a;
+	pci_write_config_byte(ice->pci, 0x60, ice->eeprom.data[ICE_EEP1_CODEC]);
 	pci_write_config_byte(ice->pci, 0x61, ice->eeprom.data[ICE_EEP1_ACLINK]);
 	pci_write_config_byte(ice->pci, 0x62, ice->eeprom.data[ICE_EEP1_I2SID]);
 	pci_write_config_byte(ice->pci, 0x63, ice->eeprom.data[ICE_EEP1_SPDIF]);
@@ -2737,21 +2737,38 @@
 
 	if (! c->no_mpu401) {
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
-					       ICEREG(ice, MPU1_CTRL), 1,
+					       ICEREG(ice, MPU1_CTRL),
+					       (c->mpu401_1_info_flags |
+						MPU401_INFO_INTEGRATED),
 					       ice->irq, 0,
 					       &ice->rmidi[0])) < 0) {
 			snd_card_free(card);
 			return err;
 		}
+		if (c->mpu401_1_name)
+			/*  Prefered name available in card_info */
+			snprintf(ice->rmidi[0]->name,
+				 sizeof(ice->rmidi[0]->name),
+				 "%s %d", c->mpu401_1_name, card->number);
 
-		if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401)
+		if (ice->eeprom.data[ICE_EEP1_CODEC] & ICE1712_CFG_2xMPU401) {
+			/*  2nd port used  */
 			if ((err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712,
-						       ICEREG(ice, MPU2_CTRL), 1,
+						       ICEREG(ice, MPU2_CTRL),
+						       (c->mpu401_2_info_flags |
+							MPU401_INFO_INTEGRATED),
 						       ice->irq, 0,
 						       &ice->rmidi[1])) < 0) {
 				snd_card_free(card);
 				return err;
 			}
+			if (c->mpu401_2_name)
+				/*  Prefered name available in card_info */
+				snprintf(ice->rmidi[1]->name,
+					 sizeof(ice->rmidi[1]->name),
+					 "%s %d", c->mpu401_2_name,
+					 card->number);
+		}
 	}
 
 	snd_ice1712_set_input_clock_source(ice, 0);
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 053f8e5..ce27eac 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -29,6 +29,7 @@
 #include <sound/ak4xxx-adda.h>
 #include <sound/ak4114.h>
 #include <sound/pcm.h>
+#include <sound/mpu401.h>
 
 
 /*
@@ -495,6 +496,10 @@
 	int (*chip_init)(struct snd_ice1712 *);
 	int (*build_controls)(struct snd_ice1712 *);
 	unsigned int no_mpu401: 1;
+	unsigned int mpu401_1_info_flags;
+	unsigned int mpu401_2_info_flags;
+	const char *mpu401_1_name;
+	const char *mpu401_2_name;
 	unsigned int eeprom_size;
 	unsigned char *eeprom_data;
 };
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index b1c007e..34a58c62 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -1293,7 +1293,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(ice->card, "ice1724", &entry))
-		snd_info_set_text_ops(entry, ice, 1024, snd_vt1724_proc_read);
+		snd_info_set_text_ops(entry, ice, snd_vt1724_proc_read);
 }
 
 /*
@@ -2388,7 +2388,8 @@
 	if (! c->no_mpu401) {
 		if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {
 			if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
-						       ICEREG1724(ice, MPU_CTRL), 1,
+						       ICEREG1724(ice, MPU_CTRL),
+						       MPU401_INFO_INTEGRATED,
 						       ice->irq, 0,
 						       &ice->rmidi[0])) < 0) {
 				snd_card_free(card);
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index d23fb3f..0efcad9 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -680,9 +680,8 @@
 {
 	struct snd_info_entry *entry;
 	if (! snd_card_proc_new(ice->card, "wm_codec", &entry)) {
-		snd_info_set_text_ops(entry, ice, 1024, wm_proc_regs_read);
+		snd_info_set_text_ops(entry, ice, wm_proc_regs_read);
 		entry->mode |= S_IWUSR;
-		entry->c.text.write_size = 1024;
 		entry->c.text.write = wm_proc_regs_write;
 	}
 }
@@ -705,9 +704,8 @@
 static void cs_proc_init(struct snd_ice1712 *ice)
 {
 	struct snd_info_entry *entry;
-	if (! snd_card_proc_new(ice->card, "cs_codec", &entry)) {
-		snd_info_set_text_ops(entry, ice, 1024, cs_proc_regs_read);
-	}
+	if (! snd_card_proc_new(ice->card, "cs_codec", &entry))
+		snd_info_set_text_ops(entry, ice, cs_proc_regs_read);
 }
 
 
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 0df7602..edc1447 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -66,7 +66,7 @@
 
 static int index = SNDRV_DEFAULT_IDX1;	/* Index 0-MAX */
 static char *id = SNDRV_DEFAULT_STR1;	/* ID for this card */
-static int ac97_clock = 0;
+static int ac97_clock;
 static char *ac97_quirk;
 static int buggy_semaphore;
 static int buggy_irq = -1; /* auto-check */
@@ -1807,6 +1807,12 @@
 	},
 	{
 		.subvendor = 0x1028,
+		.subdevice = 0x014e,
+		.name = "Dell D800", /* STAC9750/51 */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.subvendor = 0x1028,
 		.subdevice = 0x0163,
 		.name = "Dell Unknown",	/* STAC9750/51 */
 		.type = AC97_TUNE_HP_ONLY
@@ -2645,7 +2651,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "intel8x0", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_intel8x0_proc_read);
 }
 #else
 #define snd_intel8x0_proc_init(x)
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 720635f..24703d7 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -59,7 +59,7 @@
 
 static int index = -2; /* Exclude the first card */
 static char *id = SNDRV_DEFAULT_STR1;	/* ID for this card */
-static int ac97_clock = 0;
+static int ac97_clock;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 modemcard.");
@@ -1092,7 +1092,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "intel8x0m", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_intel8x0m_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read);
 }
 #else /* !CONFIG_PROC_FS */
 #define snd_intel8x0m_proc_init(chip)
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index e39fad1..6e97932 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2085,7 +2085,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(korg1212->card, "korg1212", &entry))
-		snd_info_set_text_ops(entry, korg1212, 1024, snd_korg1212_proc_read);
+		snd_info_set_text_ops(entry, korg1212, snd_korg1212_proc_read);
 }
 
 static int
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 1928e06b..1c344fb 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2861,7 +2861,8 @@
 #if 0 /* TODO: not supported yet */
 	/* TODO enable MIDI IRQ and I/O */
 	err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
-				  chip->iobase + MPU401_DATA_PORT, 1,
+				  chip->iobase + MPU401_DATA_PORT,
+				  MPU401_INFO_INTEGRATED,
 				  chip->irq, 0, &chip->rmidi);
 	if (err < 0)
 		printk(KERN_WARNING "maestro3: no MIDI support.\n");
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 09cc078..366c4a7 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1244,7 +1244,6 @@
 	/* text interface to read perf and temp meters */
 	if (! snd_card_proc_new(chip->card, "board_info", &entry)) {
 		entry->private_data = chip;
-		entry->c.text.read_size = 1024;
 		entry->c.text.read = snd_mixart_proc_read;
 	}
 
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index dafa223..8198884 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -1150,9 +1150,9 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "info", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_info);
+		snd_info_set_text_ops(entry, chip, pcxhr_proc_info);
 	if (! snd_card_proc_new(chip->card, "sync", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, pcxhr_proc_sync);
+		snd_info_set_text_ops(entry, chip, pcxhr_proc_sync);
 }
 /* end of proc interface */
 
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index d8cc985..5618ec9 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1836,11 +1836,11 @@
 		UNSET_GRESET(cif->hwport);
 		kfree(chip->cif);
 	}
+	if (chip->irq >= 0)
+		free_irq(chip->irq, chip);
 	if (chip->fw_entry)
 		release_firmware(chip->fw_entry);
 	release_and_free_resource(chip->res_port);
-	if (chip->irq >= 0)
-		free_irq(chip->irq, chip);
 	kfree(chip);
 	return 0;
 }
@@ -1992,7 +1992,7 @@
 	struct snd_info_entry *entry;
 
 	if (!snd_card_proc_new(chip->card, "riptide", &entry))
-		snd_info_set_text_ops(entry, chip, 4096, snd_riptide_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_riptide_proc_read);
 }
 
 static int __devinit snd_riptide_mixer(struct snd_riptide *chip)
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 55b1d48..2cb9fe9 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1368,18 +1368,18 @@
 		return err;
 	rme32->port = pci_resource_start(rme32->pci, 0);
 
-	if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) {
-		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
-		return -EBUSY;
-	}
-	rme32->irq = pci->irq;
-
 	if ((rme32->iobase = ioremap_nocache(rme32->port, RME32_IO_SIZE)) == 0) {
 		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n",
 			   rme32->port, rme32->port + RME32_IO_SIZE - 1);
 		return -ENOMEM;
 	}
 
+	if (request_irq(pci->irq, snd_rme32_interrupt, SA_INTERRUPT | SA_SHIRQ, "RME32", (void *) rme32)) {
+		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+		return -EBUSY;
+	}
+	rme32->irq = pci->irq;
+
 	/* read the card's revision number */
 	pci_read_config_byte(pci, 8, &rme32->rev);
 
@@ -1578,7 +1578,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(rme32->card, "rme32", &entry))
-		snd_info_set_text_ops(entry, rme32, 1024, snd_rme32_proc_read);
+		snd_info_set_text_ops(entry, rme32, snd_rme32_proc_read);
 }
 
 /*
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 3c1bc53..991cb18 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1151,6 +1151,25 @@
 	.mask = 0
 };
 
+static void
+rme96_set_buffer_size_constraint(struct rme96 *rme96,
+				 struct snd_pcm_runtime *runtime)
+{
+	unsigned int size;
+
+	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+				     RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
+	if ((size = rme96->playback_periodsize) != 0 ||
+	    (size = rme96->capture_periodsize) != 0)
+		snd_pcm_hw_constraint_minmax(runtime,
+					     SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+					     size, size);
+	else
+		snd_pcm_hw_constraint_list(runtime, 0,
+					   SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+					   &hw_constraints_period_bytes);
+}
+
 static int
 snd_rme96_playback_spdif_open(struct snd_pcm_substream *substream)
 {
@@ -1180,8 +1199,7 @@
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
 	}        
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
+	rme96_set_buffer_size_constraint(rme96, runtime);
 
 	rme96->wcreg_spdif_stream = rme96->wcreg_spdif;
 	rme96->spdif_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
@@ -1219,9 +1237,7 @@
 	rme96->capture_substream = substream;
 	spin_unlock_irq(&rme96->lock);
 	
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
-
+	rme96_set_buffer_size_constraint(rme96, runtime);
 	return 0;
 }
 
@@ -1254,8 +1270,7 @@
                 runtime->hw.rate_min = rate;
                 runtime->hw.rate_max = rate;
 	}        
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
+	rme96_set_buffer_size_constraint(rme96, runtime);
 	return 0;
 }
 
@@ -1291,8 +1306,7 @@
 	rme96->capture_substream = substream;
 	spin_unlock_irq(&rme96->lock);
 
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, RME96_BUFFER_SIZE, RME96_BUFFER_SIZE);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, &hw_constraints_period_bytes);
+	rme96_set_buffer_size_constraint(rme96, runtime);
 	return 0;
 }
 
@@ -1569,17 +1583,17 @@
 		return err;
 	rme96->port = pci_resource_start(rme96->pci, 0);
 
+	if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
+		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
+		return -ENOMEM;
+	}
+
 	if (request_irq(pci->irq, snd_rme96_interrupt, SA_INTERRUPT|SA_SHIRQ, "RME96", (void *)rme96)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
 	rme96->irq = pci->irq;
 
-	if ((rme96->iobase = ioremap_nocache(rme96->port, RME96_IO_SIZE)) == 0) {
-		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", rme96->port, rme96->port + RME96_IO_SIZE - 1);
-		return -ENOMEM;
-	}
-
 	/* read the card's revision number */
 	pci_read_config_byte(pci, 8, &rme96->rev);	
 	
@@ -1805,7 +1819,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(rme96->card, "rme96", &entry))
-		snd_info_set_text_ops(entry, rme96, 1024, snd_rme96_proc_read);
+		snd_info_set_text_ops(entry, rme96, snd_rme96_proc_read);
 }
 
 /*
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 61f82f0..eaf3c22 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -389,7 +389,7 @@
 
 /* use hotplug firmeare loader? */
 #if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
-#ifndef HDSP_USE_HWDEP_LOADER
+#if !defined(HDSP_USE_HWDEP_LOADER) && !defined(CONFIG_SND_HDSP)
 #define HDSP_FW_LOADER
 #endif
 #endif
@@ -3169,9 +3169,10 @@
 	char *clock_source;
 	int x;
 
-	if (hdsp_check_for_iobox (hdsp))
+	if (hdsp_check_for_iobox (hdsp)) {
 		snd_iprintf(buffer, "No I/O box connected.\nPlease connect one and upload firmware.\n");
 		return;
+        }
 
 	if (hdsp_check_for_firmware(hdsp, 0)) {
 		if (hdsp->state & HDSP_FirmwareCached) {
@@ -3470,7 +3471,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(hdsp->card, "hdsp", &entry))
-		snd_info_set_text_ops(entry, hdsp, 1024, snd_hdsp_proc_read);
+		snd_info_set_text_ops(entry, hdsp, snd_hdsp_proc_read);
 }
 
 static void snd_hdsp_free_buffers(struct hdsp *hdsp)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 722b9e6c..bba1615 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -2489,7 +2489,7 @@
 	struct snd_info_entry *entry;
 
 	if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
-		snd_info_set_text_ops(entry, hdspm, 1024,
+		snd_info_set_text_ops(entry, hdspm,
 				      snd_hdspm_proc_read);
 }
 
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 75d6406..3b945e8 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -41,7 +41,7 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */
+static int precise_ptr[SNDRV_CARDS];			/* Enable precise pointer */
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard.");
@@ -1787,7 +1787,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(rme9652->card, "rme9652", &entry))
-		snd_info_set_text_ops(entry, rme9652, 1024, snd_rme9652_proc_read);
+		snd_info_set_text_ops(entry, rme9652, snd_rme9652_proc_read);
 }
 
 static void snd_rme9652_free_buffers(struct snd_rme9652 *rme9652)
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 91f8bf3..dcf4029 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -54,8 +54,8 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int reverb[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
-static int mge[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
+static int reverb[SNDRV_CARDS];
+static int mge[SNDRV_CARDS];
 static unsigned int dmaio = 0x7a00;	/* DDMA i/o address */
 
 module_param_array(index, int, NULL, 0444);
@@ -1144,7 +1144,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(sonic->card, "sonicvibes", &entry))
-		snd_info_set_text_ops(entry, sonic, 1024, snd_sonicvibes_proc_read);
+		snd_info_set_text_ops(entry, sonic, snd_sonicvibes_proc_read);
 }
 
 /*
@@ -1456,7 +1456,7 @@
 		return err;
 	}
 	if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
-				       sonic->midi_port, 1,
+				       sonic->midi_port, MPU401_INFO_INTEGRATED,
 				       sonic->irq, 0,
 				       &midi_uart)) < 0) {
 		snd_card_free(card);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index 9624a5f..5629b7e 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -148,7 +148,8 @@
 	}
 	if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
 	    (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
-				       trident->midi_port, 1,
+				       trident->midi_port,
+				       MPU401_INFO_INTEGRATED,
 				       trident->irq, 0, &trident->rmidi)) < 0) {
 		snd_card_free(card);
 		return err;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 52178b8..d99ed72 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -306,6 +306,8 @@
 	outl(mask, TRID_REG(trident, reg));
 }
 
+EXPORT_SYMBOL(snd_trident_start_voice);
+
 /*---------------------------------------------------------------------------
    void snd_trident_stop_voice(struct snd_trident * trident, unsigned int voice)
 
@@ -328,6 +330,8 @@
 	outl(mask, TRID_REG(trident, reg));
 }
 
+EXPORT_SYMBOL(snd_trident_stop_voice);
+
 /*---------------------------------------------------------------------------
     int snd_trident_allocate_pcm_channel(struct snd_trident *trident)
   
@@ -502,6 +506,8 @@
 #endif
 }
 
+EXPORT_SYMBOL(snd_trident_write_voice_regs);
+
 /*---------------------------------------------------------------------------
    snd_trident_write_cso_reg
   
@@ -3332,7 +3338,7 @@
 	if (trident->device == TRIDENT_DEVICE_ID_SI7018)
 		s = "sis7018";
 	if (! snd_card_proc_new(trident->card, s, &entry))
-		snd_info_set_text_ops(entry, trident, 1024, snd_trident_proc_read);
+		snd_info_set_text_ops(entry, trident, snd_trident_proc_read);
 }
 
 static int snd_trident_dev_free(struct snd_device *device)
@@ -3884,6 +3890,8 @@
 	return NULL;
 }
 
+EXPORT_SYMBOL(snd_trident_alloc_voice);
+
 void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voice *voice)
 {
 	unsigned long flags;
@@ -3912,6 +3920,8 @@
 		private_free(voice);
 }
 
+EXPORT_SYMBOL(snd_trident_free_voice);
+
 static void snd_trident_clear_voices(struct snd_trident * trident, unsigned short v_min, unsigned short v_max)
 {
 	unsigned int i, val, mask[2] = { 0, 0 };
@@ -3993,13 +4003,3 @@
 	return 0;
 }
 #endif /* CONFIG_PM */
-
-EXPORT_SYMBOL(snd_trident_alloc_voice);
-EXPORT_SYMBOL(snd_trident_free_voice);
-EXPORT_SYMBOL(snd_trident_start_voice);
-EXPORT_SYMBOL(snd_trident_stop_voice);
-EXPORT_SYMBOL(snd_trident_write_voice_regs);
-/* trident_memory.c symbols */
-EXPORT_SYMBOL(snd_trident_synth_alloc);
-EXPORT_SYMBOL(snd_trident_synth_free);
-EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
diff --git a/sound/pci/trident/trident_memory.c b/sound/pci/trident/trident_memory.c
index 46c6982..aff3f87 100644
--- a/sound/pci/trident/trident_memory.c
+++ b/sound/pci/trident/trident_memory.c
@@ -349,6 +349,7 @@
 	return blk;
 }
 
+EXPORT_SYMBOL(snd_trident_synth_alloc);
 
 /*
  * free a synth sample area
@@ -365,6 +366,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_trident_synth_free);
 
 /*
  * reset TLB entry and free kernel page
@@ -486,3 +488,4 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_trident_synth_copy_from_user);
diff --git a/sound/pci/trident/trident_synth.c b/sound/pci/trident/trident_synth.c
index cc7af8b..9b7dee8 100644
--- a/sound/pci/trident/trident_synth.c
+++ b/sound/pci/trident/trident_synth.c
@@ -914,7 +914,9 @@
 						   &callbacks,
 						   SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
 						   SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |
-						   SNDRV_SEQ_PORT_TYPE_SYNTH,
+						   SNDRV_SEQ_PORT_TYPE_SYNTH |
+						   SNDRV_SEQ_PORT_TYPE_HARDWARE |
+						   SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
 						   16, 0,
 						   name);
 	if (p->chset->port < 0) {
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 39daf62..2527bbd 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1775,6 +1775,12 @@
 		.name = "Targa Traveller 811",
 		.type = AC97_TUNE_HP_ONLY,
 	},
+	{
+		.subvendor = 0x161f,
+		.subdevice = 0x2032,
+		.name = "m680x",
+		.type = AC97_TUNE_HP_ONLY, /* http://launchpad.net/bugs/38546 */
+	},
 	{ } /* terminator */
 };
 
@@ -1973,7 +1979,7 @@
 	pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);
 	if (chip->mpu_res) {
 		if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A,
-					mpu_port, 1,
+					mpu_port, MPU401_INFO_INTEGRATED,
 					chip->irq, 0, &chip->rmidi) < 0) {
 			printk(KERN_WARNING "unable to initialize MPU-401"
 			       " at 0x%lx, skipping\n", mpu_port);
@@ -2015,7 +2021,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "via82xx", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read);
 }
 
 /*
@@ -2365,7 +2371,7 @@
 		{ .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */
 		{ .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
 		{ .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
-		{ .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
+		{ .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_SRC }, /* MSI K8T Neo2-FI */
 		{ .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
 		{ .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */
 		{ .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index ef97e50..577a2b0 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -929,7 +929,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "via82xx", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_via82xx_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read);
 }
 
 /*
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 65ebf5f..26aa775 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -308,7 +308,8 @@
 	}
 	if (chip->mpu_res) {
 		if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
-					       mpu_port[dev], 1,
+					       mpu_port[dev],
+					       MPU401_INFO_INTEGRATED,
 					       pci->irq, 0, &chip->rawmidi)) < 0) {
 			printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]);
 			legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 8ac5ab5..f894752 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1919,7 +1919,7 @@
 	struct snd_info_entry *entry;
 	
 	if (! snd_card_proc_new(card, "ymfpci", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, snd_ymfpci_proc_read);
+		snd_info_set_text_ops(entry, chip, snd_ymfpci_proc_read);
 	return 0;
 }
 
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
index bd0d70f..1dfe29b 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
@@ -144,7 +144,7 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(chip->card, "pdaudiocf", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, pdacf_proc_read);
+		snd_info_set_text_ops(entry, chip, pdacf_proc_read);
 }
 
 struct snd_pdacf *snd_pdacf_create(struct snd_card *card)
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index 7f82f61..1ee0918 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -202,7 +202,7 @@
 	c |= (int)vx_inb(chip, RXM) << 8;
 	c |= vx_inb(chip, RXL);
 
-	snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%x\n", c, fw->size);
+	snd_printdd(KERN_DEBUG "xilinx: dsp size received 0x%x, orig 0x%Zx\n", c, fw->size);
 
 	vx_outb(chip, ICR, ICR_HF0);
 
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 7e0cda2..cafe664 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -261,7 +261,7 @@
 
 	link->dev_node = &vxp->node;
 	kfree(parse);
-	return 9;
+	return 0;
 
 cs_failed:
 	cs_error(link, last_fn, last_ret);
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile
index d6ba995..4d95c65 100644
--- a/sound/ppc/Makefile
+++ b/sound/ppc/Makefile
@@ -3,7 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o toonie.o keywest.o beep.o
+snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index f0794ef..b678814 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -867,8 +867,6 @@
 	unsigned int *prop, l;
 	struct macio_chip* macio;
 
-	u32 layout_id = 0;
-
 	if (!machine_is(powermac))
 		return -ENODEV;
 
@@ -929,8 +927,14 @@
 	if (prop && *prop < 16)
 		chip->subframe = *prop;
 	prop = (unsigned int *) get_property(sound, "layout-id", NULL);
-	if (prop)
-		layout_id = *prop;
+	if (prop) {
+		/* partly deprecate snd-powermac, for those machines
+		 * that have a layout-id property for now */
+		printk(KERN_INFO "snd-powermac no longer handles any "
+				 "machines with a layout-id property "
+				 "in the device-tree, use snd-aoa.\n");
+		return -ENODEV;
+	}
 	/* This should be verified on older screamers */
 	if (device_is_compatible(sound, "screamer")) {
 		chip->model = PMAC_SCREAMER;
@@ -963,38 +967,6 @@
 		chip->freq_table = tumbler_freqs;
 		chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
 	}
-	if (device_is_compatible(sound, "AOAKeylargo") ||
-	    device_is_compatible(sound, "AOAbase") ||
-	    device_is_compatible(sound, "AOAK2")) {
-		/* For now, only support very basic TAS3004 based machines with
-		 * single frequency until proper i2s control is implemented
-		 */
-		switch(layout_id) {
-		case 0x24:
-		case 0x29:
-		case 0x33:
-		case 0x46:
-		case 0x48:
-		case 0x50:
-		case 0x5c:
-			chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
-			chip->model = PMAC_SNAPPER;
-			chip->can_byte_swap = 0; /* FIXME: check this */
-			chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */
-			break;
-		case 0x3a:
-			chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
-			chip->model = PMAC_TOONIE;
-			chip->can_byte_swap = 0; /* FIXME: check this */
-			chip->control_mask = MASK_IEPC | 0x11;/* disable IEE */
-			break;
-		default:
-			printk(KERN_ERR "snd: Unknown layout ID 0x%x\n",
-			       layout_id);
-			return -ENODEV;
-
-		}
-	}
 	prop = (unsigned int *)get_property(sound, "device-id", NULL);
 	if (prop)
 		chip->device_id = *prop;
diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h
index 3a9bd4d..8394e66 100644
--- a/sound/ppc/pmac.h
+++ b/sound/ppc/pmac.h
@@ -85,7 +85,7 @@
 
 enum snd_pmac_model {
 	PMAC_AWACS, PMAC_SCREAMER, PMAC_BURGUNDY, PMAC_DACA, PMAC_TUMBLER,
-	PMAC_SNAPPER, PMAC_TOONIE
+	PMAC_SNAPPER
 };
 
 struct snd_pmac {
@@ -188,7 +188,6 @@
 int snd_pmac_daca_init(struct snd_pmac *chip);
 int snd_pmac_tumbler_init(struct snd_pmac *chip);
 int snd_pmac_tumbler_post_init(void);
-int snd_pmac_toonie_init(struct snd_pmac *chip);
 
 /* i2c functions */
 struct pmac_keywest {
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index f4902a2..fa9a44a 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -94,13 +94,6 @@
 		if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0)
 			goto __error;
 		break;
-	case PMAC_TOONIE:
-		strcpy(card->driver, "PMac Toonie");
-		strcpy(card->shortname, "PowerMac Toonie");
-		strcpy(card->longname, card->shortname);
-		if ((err = snd_pmac_toonie_init(chip)) < 0)
-			goto __error;
-		break;
 	case PMAC_AWACS:
 	case PMAC_SCREAMER:
 		name_ext = chip->model == PMAC_SCREAMER ? "Screamer" : "AWACS";
@@ -188,11 +181,15 @@
 	if ((err = platform_driver_register(&snd_pmac_driver)) < 0)
 		return err;
 	device = platform_device_register_simple(SND_PMAC_DRIVER, -1, NULL, 0);
-	if (IS_ERR(device)) {
-		platform_driver_unregister(&snd_pmac_driver);
-		return PTR_ERR(device);
-	}
-	return 0;
+	if (!IS_ERR(device)) {
+		if (platform_get_drvdata(device))
+			return 0;
+		platform_device_unregister(device);
+		err = -ENODEV;
+	} else
+		err = PTR_ERR(device);
+	platform_driver_unregister(&snd_pmac_driver);
+	return err;
 
 }
 
diff --git a/sound/ppc/toonie.c b/sound/ppc/toonie.c
deleted file mode 100644
index 1ac7c85..0000000
--- a/sound/ppc/toonie.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Mac Mini "toonie" mixer control
- *
- * Copyright (c) 2005 by Benjamin Herrenschmidt <benh@kernel.crashing.org>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <sound/driver.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/kmod.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <sound/core.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include "pmac.h"
-
-#undef DEBUG
-
-#ifdef DEBUG
-#define DBG(fmt...) printk(fmt)
-#else
-#define DBG(fmt...)
-#endif
-
-struct pmac_gpio {
-	unsigned int addr;
-	u8 active_val;
-	u8 inactive_val;
-	u8 active_state;
-};
-
-struct pmac_toonie
-{
-	struct pmac_gpio	hp_detect_gpio;
-	struct pmac_gpio	hp_mute_gpio;
-	struct pmac_gpio	amp_mute_gpio;
-	int			hp_detect_irq;
-	int			auto_mute_notify;
-	struct work_struct	detect_work;
-};
-
-
-/*
- * gpio access
- */
-#define do_gpio_write(gp, val) \
-	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, (gp)->addr, val)
-#define do_gpio_read(gp) \
-	pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, (gp)->addr, 0)
-#define tumbler_gpio_free(gp) /* NOP */
-
-static void write_audio_gpio(struct pmac_gpio *gp, int active)
-{
-	if (! gp->addr)
-		return;
-	active = active ? gp->active_val : gp->inactive_val;
-	do_gpio_write(gp, active);
-	DBG("(I) gpio %x write %d\n", gp->addr, active);
-}
-
-static int check_audio_gpio(struct pmac_gpio *gp)
-{
-	int ret;
-
-	if (! gp->addr)
-		return 0;
-
-	ret = do_gpio_read(gp);
-
-	return (ret & 0xd) == (gp->active_val & 0xd);
-}
-
-static int read_audio_gpio(struct pmac_gpio *gp)
-{
-	int ret;
-	if (! gp->addr)
-		return 0;
-	ret = ((do_gpio_read(gp) & 0x02) !=0);
-	return ret == gp->active_state;
-}
-
-
-enum { TOONIE_MUTE_HP, TOONIE_MUTE_AMP };
-
-static int toonie_get_mute_switch(struct snd_kcontrol *kcontrol,
-				  struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	struct pmac_toonie *mix = chip->mixer_data;
-	struct pmac_gpio *gp;
-
-	if (mix == NULL)
-		return -ENODEV;
-	switch(kcontrol->private_value) {
-	case TOONIE_MUTE_HP:
-		gp = &mix->hp_mute_gpio;
-		break;
-	case TOONIE_MUTE_AMP:
-		gp = &mix->amp_mute_gpio;
-		break;
-	default:
-		return -EINVAL;
-	}
-	ucontrol->value.integer.value[0] = !check_audio_gpio(gp);
-	return 0;
-}
-
-static int toonie_put_mute_switch(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
-	struct pmac_toonie *mix = chip->mixer_data;
-	struct pmac_gpio *gp;
-	int val;
-
-	if (chip->update_automute && chip->auto_mute)
-		return 0; /* don't touch in the auto-mute mode */
-
-	if (mix == NULL)
-		return -ENODEV;
-
-	switch(kcontrol->private_value) {
-	case TOONIE_MUTE_HP:
-		gp = &mix->hp_mute_gpio;
-		break;
-	case TOONIE_MUTE_AMP:
-		gp = &mix->amp_mute_gpio;
-		break;
-	default:
-		return -EINVAL;
-	}
-	val = ! check_audio_gpio(gp);
-	if (val != ucontrol->value.integer.value[0]) {
-		write_audio_gpio(gp, ! ucontrol->value.integer.value[0]);
-		return 1;
-	}
-	return 0;
-}
-
-static struct snd_kcontrol_new toonie_hp_sw __initdata = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Headphone Playback Switch",
-	.info = snd_pmac_boolean_mono_info,
-	.get = toonie_get_mute_switch,
-	.put = toonie_put_mute_switch,
-	.private_value = TOONIE_MUTE_HP,
-};
-static struct snd_kcontrol_new toonie_speaker_sw __initdata = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "PC Speaker Playback Switch",
-	.info = snd_pmac_boolean_mono_info,
-	.get = toonie_get_mute_switch,
-	.put = toonie_put_mute_switch,
-	.private_value = TOONIE_MUTE_AMP,
-};
-
-/*
- * auto-mute stuffs
- */
-static int toonie_detect_headphone(struct snd_pmac *chip)
-{
-	struct pmac_toonie *mix = chip->mixer_data;
-	int detect = 0;
-
-	if (mix->hp_detect_gpio.addr)
-		detect |= read_audio_gpio(&mix->hp_detect_gpio);
-	return detect;
-}
-
-static void toonie_check_mute(struct snd_pmac *chip, struct pmac_gpio *gp, int val,
-			      int do_notify, struct snd_kcontrol *sw)
-{
-	if (check_audio_gpio(gp) != val) {
-		write_audio_gpio(gp, val);
-		if (do_notify)
-			snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-				       &sw->id);
-	}
-}
-
-static void toonie_detect_handler(void *self)
-{
-	struct snd_pmac *chip = (struct snd_pmac *) self;
-	struct pmac_toonie *mix;
-	int headphone;
-
-	if (!chip)
-		return;
-
-	mix = chip->mixer_data;
-	snd_assert(mix, return);
-
-	headphone = toonie_detect_headphone(chip);
-
-	DBG("headphone: %d, lineout: %d\n", headphone, lineout);
-
-	if (headphone) {
-		/* unmute headphone/lineout & mute speaker */
-		toonie_check_mute(chip, &mix->hp_mute_gpio, 0,
-				  mix->auto_mute_notify, chip->master_sw_ctl);
-		toonie_check_mute(chip, &mix->amp_mute_gpio, 1,
-				  mix->auto_mute_notify, chip->speaker_sw_ctl);
-	} else {
-		/* unmute speaker, mute others */
-		toonie_check_mute(chip, &mix->amp_mute_gpio, 0,
-				  mix->auto_mute_notify, chip->speaker_sw_ctl);
-		toonie_check_mute(chip, &mix->hp_mute_gpio, 1,
-				  mix->auto_mute_notify, chip->master_sw_ctl);
-	}
-	if (mix->auto_mute_notify) {
-		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
-				       &chip->hp_detect_ctl->id);
-	}
-}
-
-static void toonie_update_automute(struct snd_pmac *chip, int do_notify)
-{
-	if (chip->auto_mute) {
-		struct pmac_toonie *mix;
-		mix = chip->mixer_data;
-		snd_assert(mix, return);
-		mix->auto_mute_notify = do_notify;
-		schedule_work(&mix->detect_work);
-	}
-}
-
-/* interrupt - headphone plug changed */
-static irqreturn_t toonie_hp_intr(int irq, void *devid, struct pt_regs *regs)
-{
-	struct snd_pmac *chip = devid;
-
-	if (chip->update_automute && chip->initialized) {
-		chip->update_automute(chip, 1);
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
-}
-
-/* look for audio gpio device */
-static int find_audio_gpio(const char *name, const char *platform,
-			   struct pmac_gpio *gp)
-{
-	struct device_node *np;
-  	u32 *base, addr;
-
-	if (! (np = find_devices("gpio")))
-		return -ENODEV;
-
-	for (np = np->child; np; np = np->sibling) {
-		char *property = get_property(np, "audio-gpio", NULL);
-		if (property && strcmp(property, name) == 0)
-			break;
-		if (device_is_compatible(np, name))
-			break;
-	}
-	if (np == NULL)
-		return -ENODEV;
-
-	base = (u32 *)get_property(np, "AAPL,address", NULL);
-	if (! base) {
-		base = (u32 *)get_property(np, "reg", NULL);
-		if (!base) {
-			DBG("(E) cannot find address for device %s !\n", name);
-			return -ENODEV;
-		}
-		addr = *base;
-		if (addr < 0x50)
-			addr += 0x50;
-	} else
-		addr = *base;
-
-	gp->addr = addr & 0x0000ffff;
-
-	/* Try to find the active state, default to 0 ! */
-	base = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
-	if (base) {
-		gp->active_state = *base;
-		gp->active_val = (*base) ? 0x5 : 0x4;
-		gp->inactive_val = (*base) ? 0x4 : 0x5;
-	} else {
-		u32 *prop = NULL;
-		gp->active_state = 0;
-		gp->active_val = 0x4;
-		gp->inactive_val = 0x5;
-		/* Here are some crude hacks to extract the GPIO polarity and
-		 * open collector informations out of the do-platform script
-		 * as we don't yet have an interpreter for these things
-		 */
-		if (platform)
-			prop = (u32 *)get_property(np, platform, NULL);
-		if (prop) {
-			if (prop[3] == 0x9 && prop[4] == 0x9) {
-				gp->active_val = 0xd;
-				gp->inactive_val = 0xc;
-			}
-			if (prop[3] == 0x1 && prop[4] == 0x1) {
-				gp->active_val = 0x5;
-				gp->inactive_val = 0x4;
-			}
-		}
-	}
-
-	DBG("(I) GPIO device %s found, offset: %x, active state: %d !\n",
-	    name, gp->addr, gp->active_state);
-
-	return (np->n_intrs > 0) ? np->intrs[0].line : 0;
-}
-
-static void toonie_cleanup(struct snd_pmac *chip)
-{
-	struct pmac_toonie *mix = chip->mixer_data;
-	if (! mix)
-		return;
-	if (mix->hp_detect_irq >= 0)
-		free_irq(mix->hp_detect_irq, chip);
-	kfree(mix);
-	chip->mixer_data = NULL;
-}
-
-int __init snd_pmac_toonie_init(struct snd_pmac *chip)
-{
-	struct pmac_toonie *mix;
-
-	mix = kmalloc(sizeof(*mix), GFP_KERNEL);
-	if (! mix)
-		return -ENOMEM;
-
-	chip->mixer_data = mix;
-	chip->mixer_free = toonie_cleanup;
-
-	find_audio_gpio("headphone-mute", NULL, &mix->hp_mute_gpio);
-	find_audio_gpio("amp-mute", NULL, &mix->amp_mute_gpio);
-	mix->hp_detect_irq = find_audio_gpio("headphone-detect",
-					     NULL, &mix->hp_detect_gpio);
-
-	strcpy(chip->card->mixername, "PowerMac Toonie");
-
-	chip->master_sw_ctl = snd_ctl_new1(&toonie_hp_sw, chip);
-	snd_ctl_add(chip->card, chip->master_sw_ctl);
-
-	chip->speaker_sw_ctl = snd_ctl_new1(&toonie_speaker_sw, chip);
-	snd_ctl_add(chip->card, chip->speaker_sw_ctl);
-
-	INIT_WORK(&mix->detect_work, toonie_detect_handler, (void *)chip);
-
-	if (mix->hp_detect_irq >= 0) {
-		snd_pmac_add_automute(chip);
-
-		chip->detect_headphone = toonie_detect_headphone;
-		chip->update_automute = toonie_update_automute;
-		toonie_update_automute(chip, 0);
-
-		if (request_irq(mix->hp_detect_irq, toonie_hp_intr, 0,
-				"Sound Headphone Detection", chip) < 0)
-			mix->hp_detect_irq = -1;
-	}
-
-	return 0;
-}
-
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index 5549334..ba1b2a3 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -46,6 +46,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/sbus.h>
+#include <asm/prom.h>
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
@@ -335,7 +336,6 @@
 	int			pgain;
 	int			mgain;
 
-	struct sbus_dev		*sdev;
 	unsigned int		irq;
 	unsigned int		regs_size;
 	struct snd_amd7930	*next;
@@ -946,11 +946,9 @@
 };
 
 static int __init snd_amd7930_create(struct snd_card *card,
-				     struct sbus_dev *sdev,
 				     struct resource *rp,
 				     unsigned int reg_size,
-				     struct linux_prom_irqs *irq_prop,
-				     int dev,
+				     int irq, int dev,
 				     struct snd_amd7930 **ramd)
 {
 	unsigned long flags;
@@ -964,7 +962,6 @@
 
 	spin_lock_init(&amd->lock);
 	amd->card = card;
-	amd->sdev = sdev;
 	amd->regs_size = reg_size;
 
 	amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930");
@@ -975,15 +972,14 @@
 
 	amd7930_idle(amd);
 
-	if (request_irq(irq_prop->pri, snd_amd7930_interrupt,
+	if (request_irq(irq, snd_amd7930_interrupt,
 			SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) {
-		snd_printk("amd7930-%d: Unable to grab IRQ %s\n",
-			   dev,
-			   __irq_itoa(irq_prop->pri));
+		snd_printk("amd7930-%d: Unable to grab IRQ %d\n",
+			   dev, irq);
 		snd_amd7930_free(amd);
 		return -EBUSY;
 	}
-	amd->irq = irq_prop->pri;
+	amd->irq = irq;
 
 	amd7930_enable_ints(amd);
 
@@ -1017,60 +1013,35 @@
 	return 0;
 }
 
-static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
+static int __init amd7930_attach_common(struct resource *rp, int irq)
 {
-	static int dev;
-	struct linux_prom_registers reg_prop;
-	struct linux_prom_irqs irq_prop;
-	struct resource res, *rp;
+	static int dev_num;
 	struct snd_card *card;
 	struct snd_amd7930 *amd;
 	int err;
 
-	if (dev >= SNDRV_CARDS)
+	if (dev_num >= SNDRV_CARDS)
 		return -ENODEV;
-	if (!enable[dev]) {
-		dev++;
+	if (!enable[dev_num]) {
+		dev_num++;
 		return -ENOENT;
 	}
 
-	err = prom_getproperty(prom_node, "intr",
-			       (char *) &irq_prop, sizeof(irq_prop));
-	if (err < 0) {
-		snd_printk("amd7930-%d: Firmware node lacks IRQ property.\n", dev);
-		return -ENODEV;
-	}
-
-	err = prom_getproperty(prom_node, "reg",
-			       (char *) &reg_prop, sizeof(reg_prop));
-	if (err < 0) {
-		snd_printk("amd7930-%d: Firmware node lacks register property.\n", dev);
-		return -ENODEV;
-	}
-
-	if (sdev) {
-		rp = &sdev->resource[0];
-	} else {
-		rp = &res;
-		rp->start = reg_prop.phys_addr;
-		rp->end = rp->start + reg_prop.reg_size - 1;
-		rp->flags = IORESOURCE_IO | (reg_prop.which_io & 0xff);
-	}
-
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	card = snd_card_new(index[dev_num], id[dev_num], THIS_MODULE, 0);
 	if (card == NULL)
 		return -ENOMEM;
 
 	strcpy(card->driver, "AMD7930");
 	strcpy(card->shortname, "Sun AMD7930");
-	sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s",
+	sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d",
 		card->shortname,
 		rp->flags & 0xffL,
 		rp->start,
-		__irq_itoa(irq_prop.pri));
+		irq);
 
-	if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size,
-					  &irq_prop, dev, &amd)) < 0)
+	if ((err = snd_amd7930_create(card, rp,
+				      (rp->end - rp->start) + 1,
+				      irq, dev_num, &amd)) < 0)
 		goto out_err;
 
 	if ((err = snd_amd7930_pcm(amd)) < 0)
@@ -1085,7 +1056,8 @@
 	amd->next = amd7930_list;
 	amd7930_list = amd;
 
-	dev++;
+	dev_num++;
+
 	return 0;
 
 out_err:
@@ -1093,29 +1065,71 @@
 	return err;
 }
 
-static int __init amd7930_init(void)
+static int __init amd7930_obio_attach(struct device_node *dp)
 {
-	struct sbus_bus *sbus;
-	struct sbus_dev *sdev;
-	int node, found;
+	struct linux_prom_registers *regs;
+	struct linux_prom_irqs *irqp;
+	struct resource res, *rp;
+	int len;
 
-	found = 0;
-
-	/* Try to find the sun4c "audio" node first. */
-	node = prom_getchild(prom_root_node);
-	node = prom_searchsiblings(node, "audio");
-	if (node && amd7930_attach(node, NULL) == 0)
-		found++;
-
-	/* Probe each SBUS for amd7930 chips. */
-	for_all_sbusdev(sdev, sbus) {
-		if (!strcmp(sdev->prom_name, "audio")) {
-			if (amd7930_attach(sdev->prom_node, sdev) == 0)
-				found++;
-		}
+	irqp = of_get_property(dp, "intr", &len);
+	if (!irqp) {
+		snd_printk("%s: Firmware node lacks IRQ property.\n",
+			   dp->full_name);
+		return -ENODEV;
 	}
 
-	return (found > 0) ? 0 : -EIO;
+	regs = of_get_property(dp, "reg", &len);
+	if (!regs) {
+		snd_printk("%s: Firmware node lacks register property.\n",
+			   dp->full_name);
+		return -ENODEV;
+	}
+
+	rp = &res;
+	rp->start = regs->phys_addr;
+	rp->end = rp->start + regs->reg_size - 1;
+	rp->flags = IORESOURCE_IO | (regs->which_io & 0xff);
+
+	return amd7930_attach_common(rp, irqp->pri);
+}
+
+static int __devinit amd7930_sbus_probe(struct of_device *dev, const struct of_device_id *match)
+{
+	struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+
+	return amd7930_attach_common(&sdev->resource[0], sdev->irqs[0]);
+}
+
+static struct of_device_id amd7930_match[] = {
+	{
+		.name = "audio",
+	},
+	{},
+};
+
+static struct of_platform_driver amd7930_sbus_driver = {
+	.name		= "audio",
+	.match_table	= amd7930_match,
+	.probe		= amd7930_sbus_probe,
+};
+
+static int __init amd7930_init(void)
+{
+	struct device_node *dp;
+
+	/* Try to find the sun4c "audio" node first. */
+	dp = of_find_node_by_path("/");
+	dp = dp->child;
+	while (dp) {
+		if (!strcmp(dp->name, "audio"))
+			amd7930_obio_attach(dp);
+
+		dp = dp->sibling;
+	}
+
+	/* Probe each SBUS for amd7930 chips. */
+	return of_register_driver(&amd7930_sbus_driver, &sbus_bus_type);
 }
 
 static void __exit amd7930_exit(void)
@@ -1131,6 +1145,8 @@
 	}
 
 	amd7930_list = NULL;
+
+	of_unregister_driver(&amd7930_sbus_driver);
 }
 
 module_init(amd7930_init);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 8804f26..da54d04 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -2003,9 +2003,8 @@
 
 	if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
 			SA_SHIRQ, "cs4231", chip)) {
-		snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %s\n",
-			   dev,
-			   __irq_itoa(sdev->irqs[0]));
+		snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n",
+			    dev, sdev->irqs[0]);
 		snd_cs4231_sbus_free(chip);
 		return -EBUSY;
 	}
@@ -2038,11 +2037,11 @@
 	if (err)
 		return err;
 
-	sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s",
+	sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d",
 		card->shortname,
 		rp->flags & 0xffL,
 		rp->start,
-		__irq_itoa(sdev->irqs[0]));
+		sdev->irqs[0]);
 
 	if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) {
 		snd_card_free(card);
@@ -2244,10 +2243,10 @@
 	if (err)
 		return err;
 
-	sprintf(card->longname, "%s at 0x%lx, irq %s",
+	sprintf(card->longname, "%s at 0x%lx, irq %d",
 		card->shortname,
 		edev->resource[0].start,
-		__irq_itoa(edev->irqs[0]));
+		edev->irqs[0]);
 
 	if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) {
 		snd_card_free(card);
@@ -2285,15 +2284,14 @@
 		for_each_ebusdev(edev, ebus) {
 			int match = 0;
 
-			if (!strcmp(edev->prom_name, "SUNW,CS4231")) {
+			if (!strcmp(edev->prom_node->name, "SUNW,CS4231")) {
 				match = 1;
-			} else if (!strcmp(edev->prom_name, "audio")) {
-				char compat[16];
+			} else if (!strcmp(edev->prom_node->name, "audio")) {
+				char *compat;
 
-				prom_getstring(edev->prom_node, "compatible",
-					       compat, sizeof(compat));
-				compat[15] = '\0';
-				if (!strcmp(compat, "SUNW,CS4231"))
+				compat = of_get_property(edev->prom_node,
+							 "compatible", NULL);
+				if (compat && !strcmp(compat, "SUNW,CS4231"))
 					match = 1;
 			}
 
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 2164b7d..5eecdd0 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -92,7 +92,7 @@
 #define D_USR	(1<<4)
 #define D_DESC	(1<<5)
 
-static int dbri_debug = 0;
+static int dbri_debug;
 module_param(dbri_debug, int, 0644);
 MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
 
@@ -593,7 +593,7 @@
 /* Return a pointer to dbri_streaminfo */
 #define DBRI_STREAM(dbri, substream)	&dbri->stream_info[DBRI_STREAMNO(substream)]
 
-static struct snd_dbri *dbri_list = NULL;	/* All DBRI devices */
+static struct snd_dbri *dbri_list;	/* All DBRI devices */
 
 /*
  * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr.
@@ -2521,11 +2521,11 @@
 	struct snd_info_entry *entry;
 
 	if (! snd_card_proc_new(dbri->card, "regs", &entry))
-		snd_info_set_text_ops(entry, dbri, 1024, dbri_regs_read);
+		snd_info_set_text_ops(entry, dbri, dbri_regs_read);
 
 #ifdef DBRI_DEBUG
 	if (! snd_card_proc_new(dbri->card, "debug", &entry)) {
-		snd_info_set_text_ops(entry, dbri, 4096, dbri_debug_read);
+		snd_info_set_text_ops(entry, dbri, dbri_debug_read);
 		entry->mode = S_IFREG | S_IRUGO;	/* Readable only. */
 	}
 #endif
@@ -2645,9 +2645,9 @@
 	strcpy(card->driver, "DBRI");
 	strcpy(card->shortname, "Sun DBRI");
 	rp = &sdev->resource[0];
-	sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s",
+	sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %d",
 		card->shortname,
-		rp->flags & 0xffL, rp->start, __irq_itoa(irq.pri));
+		rp->flags & 0xffL, rp->start, irq.pri);
 
 	if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) {
 		snd_card_free(card);
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index fc733bb..573e370 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -63,6 +63,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_emux_new);
 
 /*
  */
@@ -136,6 +137,7 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(snd_emux_register);
 
 /*
  */
@@ -171,18 +173,8 @@
 	return 0;
 }
 
-
-EXPORT_SYMBOL(snd_emux_new);
-EXPORT_SYMBOL(snd_emux_register);
 EXPORT_SYMBOL(snd_emux_free);
 
-EXPORT_SYMBOL(snd_emux_terminate_all);
-EXPORT_SYMBOL(snd_emux_lock_voice);
-EXPORT_SYMBOL(snd_emux_unlock_voice);
-
-/* soundfont.c */
-EXPORT_SYMBOL(snd_sf_linear_to_log);
-
 
 /*
  *  INIT part
diff --git a/sound/synth/emux/emux_proc.c b/sound/synth/emux/emux_proc.c
index 1ba68ce..58b9601 100644
--- a/sound/synth/emux/emux_proc.c
+++ b/sound/synth/emux/emux_proc.c
@@ -119,7 +119,6 @@
 
 	entry->content = SNDRV_INFO_CONTENT_TEXT;
 	entry->private_data = emu;
-	entry->c.text.read_size = 1024;
 	entry->c.text.read = snd_emux_proc_info_read;
 	if (snd_info_register(entry) < 0)
 		snd_info_free_entry(entry);
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 8f00f07..d176cc0 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -55,7 +55,8 @@
 				 SNDRV_SEQ_PORT_TYPE_MIDI_GM |\
 				 SNDRV_SEQ_PORT_TYPE_MIDI_GS |\
 				 SNDRV_SEQ_PORT_TYPE_MIDI_XG |\
-				 SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE)
+				 SNDRV_SEQ_PORT_TYPE_HARDWARE |\
+				 SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
 
 /*
  * Initialise the EMUX Synth by creating a client and registering
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index 24705d1..3733118 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -434,6 +434,7 @@
 	spin_unlock_irqrestore(&emu->voice_lock, flags);
 }
 
+EXPORT_SYMBOL(snd_emux_terminate_all);
 
 /*
  * Terminate all voices associated with the given port
@@ -951,6 +952,8 @@
 	spin_unlock_irqrestore(&emu->voice_lock, flags);
 }
 
+EXPORT_SYMBOL(snd_emux_lock_voice);
+
 /*
  */
 void snd_emux_unlock_voice(struct snd_emux *emu, int voice)
@@ -965,3 +968,5 @@
 			   voice, emu->voices[voice].state);
 	spin_unlock_irqrestore(&emu->voice_lock, flags);
 }
+
+EXPORT_SYMBOL(snd_emux_unlock_voice);
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 32c2716..455e535 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -195,7 +195,7 @@
 		break;
 	case SNDRV_SFNT_REMOVE_INFO:
 		/* patch must be opened */
-		if (sflist->currsf) {
+		if (!sflist->currsf) {
 			snd_printk("soundfont: remove_info: patch not opened\n");
 			rc = -EINVAL;
 		} else {
@@ -810,6 +810,9 @@
 	return v;
 }
 
+EXPORT_SYMBOL(snd_sf_linear_to_log);
+
+
 #define OFFSET_MSEC		653117		/* base = 1000 */
 #define OFFSET_ABSCENT		851781		/* base = 8176 */
 #define OFFSET_SAMPLERATE	1011119		/* base = 44100 */
@@ -1485,4 +1488,3 @@
 	unlock_preset(sflist);
 	return 0;
 }
-
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 4e614ac..627de95 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2138,7 +2138,7 @@
 
 	sprintf(name, "stream%d", stream->pcm_index);
 	if (! snd_card_proc_new(card, name, &entry))
-		snd_info_set_text_ops(entry, stream, 1024, proc_pcm_format_read);
+		snd_info_set_text_ops(entry, stream, proc_pcm_format_read);
 }
 
 #else
@@ -2627,9 +2627,10 @@
 		if (!csep && altsd->bNumEndpoints >= 2)
 			csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
 		if (!csep || csep[0] < 7 || csep[2] != EP_GENERAL) {
-			snd_printk(KERN_ERR "%d:%u:%d : no or invalid class specific endpoint descriptor\n",
+			snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
+				   " class specific endpoint descriptor\n",
 				   dev->devnum, iface_no, altno);
-			continue;
+			csep = NULL;
 		}
 
 		fp = kmalloc(sizeof(*fp), GFP_KERNEL);
@@ -2648,7 +2649,7 @@
 		if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
 			fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
 					* (fp->maxpacksize & 0x7ff);
-		fp->attributes = csep[3];
+		fp->attributes = csep ? csep[3] : 0;
 
 		/* some quirks for attributes here */
 
@@ -2980,7 +2981,7 @@
 		return -ENXIO;
 	alts = &iface->altsetting[1];
 	altsd = get_iface_desc(alts);
-	if (alts->extralen != 11 || alts->extra[1] != CS_AUDIO_INTERFACE ||
+	if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
 	    altsd->bNumEndpoints != 1)
 		return -ENXIO;
 
@@ -3197,9 +3198,9 @@
 {
 	struct snd_info_entry *entry;
 	if (! snd_card_proc_new(chip->card, "usbbus", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbbus_read);
+		snd_info_set_text_ops(entry, chip, proc_audio_usbbus_read);
 	if (! snd_card_proc_new(chip->card, "usbid", &entry))
-		snd_info_set_text_ops(entry, chip, 1024, proc_audio_usbid_read);
+		snd_info_set_text_ops(entry, chip, proc_audio_usbid_read);
 }
 
 /*
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 8873352..0f4b2b8 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -30,13 +30,6 @@
 #define USB_SUBCLASS_MIDI_STREAMING	0x03
 #define USB_SUBCLASS_VENDOR_SPEC	0xff
 
-#define CS_AUDIO_UNDEFINED		0x20
-#define CS_AUDIO_DEVICE			0x21
-#define CS_AUDIO_CONFIGURATION		0x22
-#define CS_AUDIO_STRING			0x23
-#define CS_AUDIO_INTERFACE		0x24
-#define CS_AUDIO_ENDPOINT		0x25
-
 #define HEADER				0x01
 #define INPUT_TERMINAL			0x02
 #define OUTPUT_TERMINAL			0x03
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 2b9d940..5105b6b 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -48,6 +48,7 @@
 #include <linux/usb.h>
 #include <sound/core.h>
 #include <sound/rawmidi.h>
+#include <sound/asequencer.h>
 #include "usbaudio.h"
 
 
@@ -1010,97 +1011,157 @@
  * "(product) MIDI (n)" schema because they aren't external MIDI ports,
  * such as internal control or synthesizer ports.
  */
-static struct {
+static struct port_info {
 	u32 id;
-	int port;
-	const char *name_format;
-} snd_usbmidi_port_names[] = {
+	short int port;
+	short int voices;
+	const char *name;
+	unsigned int seq_flags;
+} snd_usbmidi_port_info[] = {
+#define PORT_INFO(vendor, product, num, name_, voices_, flags) \
+	{ .id = USB_ID(vendor, product), \
+	  .port = num, .voices = voices_, \
+	  .name = name_, .seq_flags = flags }
+#define EXTERNAL_PORT(vendor, product, num, name) \
+	PORT_INFO(vendor, product, num, name, 0, \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
+		  SNDRV_SEQ_PORT_TYPE_HARDWARE | \
+		  SNDRV_SEQ_PORT_TYPE_PORT)
+#define CONTROL_PORT(vendor, product, num, name) \
+	PORT_INFO(vendor, product, num, name, 0, \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
+		  SNDRV_SEQ_PORT_TYPE_HARDWARE)
+#define ROLAND_SYNTH_PORT(vendor, product, num, name, voices) \
+	PORT_INFO(vendor, product, num, name, voices, \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GM | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GS | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_XG | \
+		  SNDRV_SEQ_PORT_TYPE_HARDWARE | \
+		  SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
+#define SOUNDCANVAS_PORT(vendor, product, num, name, voices) \
+	PORT_INFO(vendor, product, num, name, voices, \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GM | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GM2 | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_GS | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_XG | \
+		  SNDRV_SEQ_PORT_TYPE_MIDI_MT32 | \
+		  SNDRV_SEQ_PORT_TYPE_HARDWARE | \
+		  SNDRV_SEQ_PORT_TYPE_SYNTHESIZER)
 	/* Roland UA-100 */
-	{ USB_ID(0x0582, 0x0000), 2, "%s Control" },
+	CONTROL_PORT(0x0582, 0x0000, 2, "%s Control"),
 	/* Roland SC-8850 */
-	{ USB_ID(0x0582, 0x0003), 0, "%s Part A" },
-	{ USB_ID(0x0582, 0x0003), 1, "%s Part B" },
-	{ USB_ID(0x0582, 0x0003), 2, "%s Part C" },
-	{ USB_ID(0x0582, 0x0003), 3, "%s Part D" },
-	{ USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" },
-	{ USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" },
+	SOUNDCANVAS_PORT(0x0582, 0x0003, 0, "%s Part A", 128),
+	SOUNDCANVAS_PORT(0x0582, 0x0003, 1, "%s Part B", 128),
+	SOUNDCANVAS_PORT(0x0582, 0x0003, 2, "%s Part C", 128),
+	SOUNDCANVAS_PORT(0x0582, 0x0003, 3, "%s Part D", 128),
+	EXTERNAL_PORT(0x0582, 0x0003, 4, "%s MIDI 1"),
+	EXTERNAL_PORT(0x0582, 0x0003, 5, "%s MIDI 2"),
 	/* Roland U-8 */
-	{ USB_ID(0x0582, 0x0004), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x0004), 1, "%s Control" },
+	EXTERNAL_PORT(0x0582, 0x0004, 0, "%s MIDI"),
+	CONTROL_PORT(0x0582, 0x0004, 1, "%s Control"),
 	/* Roland SC-8820 */
-	{ USB_ID(0x0582, 0x0007), 0, "%s Part A" },
-	{ USB_ID(0x0582, 0x0007), 1, "%s Part B" },
-	{ USB_ID(0x0582, 0x0007), 2, "%s MIDI" },
+	SOUNDCANVAS_PORT(0x0582, 0x0007, 0, "%s Part A", 64),
+	SOUNDCANVAS_PORT(0x0582, 0x0007, 1, "%s Part B", 64),
+	EXTERNAL_PORT(0x0582, 0x0007, 2, "%s MIDI"),
 	/* Roland SK-500 */
-	{ USB_ID(0x0582, 0x000b), 0, "%s Part A" },
-	{ USB_ID(0x0582, 0x000b), 1, "%s Part B" },
-	{ USB_ID(0x0582, 0x000b), 2, "%s MIDI" },
+	SOUNDCANVAS_PORT(0x0582, 0x000b, 0, "%s Part A", 64),
+	SOUNDCANVAS_PORT(0x0582, 0x000b, 1, "%s Part B", 64),
+	EXTERNAL_PORT(0x0582, 0x000b, 2, "%s MIDI"),
 	/* Roland SC-D70 */
-	{ USB_ID(0x0582, 0x000c), 0, "%s Part A" },
-	{ USB_ID(0x0582, 0x000c), 1, "%s Part B" },
-	{ USB_ID(0x0582, 0x000c), 2, "%s MIDI" },
+	SOUNDCANVAS_PORT(0x0582, 0x000c, 0, "%s Part A", 64),
+	SOUNDCANVAS_PORT(0x0582, 0x000c, 1, "%s Part B", 64),
+	EXTERNAL_PORT(0x0582, 0x000c, 2, "%s MIDI"),
 	/* Edirol UM-880 */
-	{ USB_ID(0x0582, 0x0014), 8, "%s Control" },
+	CONTROL_PORT(0x0582, 0x0014, 8, "%s Control"),
 	/* Edirol SD-90 */
-	{ USB_ID(0x0582, 0x0016), 0, "%s Part A" },
-	{ USB_ID(0x0582, 0x0016), 1, "%s Part B" },
-	{ USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" },
-	{ USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" },
+	ROLAND_SYNTH_PORT(0x0582, 0x0016, 0, "%s Part A", 128),
+	ROLAND_SYNTH_PORT(0x0582, 0x0016, 1, "%s Part B", 128),
+	EXTERNAL_PORT(0x0582, 0x0016, 2, "%s MIDI 1"),
+	EXTERNAL_PORT(0x0582, 0x0016, 3, "%s MIDI 2"),
 	/* Edirol UM-550 */
-	{ USB_ID(0x0582, 0x0023), 5, "%s Control" },
+	CONTROL_PORT(0x0582, 0x0023, 5, "%s Control"),
 	/* Edirol SD-20 */
-	{ USB_ID(0x0582, 0x0027), 0, "%s Part A" },
-	{ USB_ID(0x0582, 0x0027), 1, "%s Part B" },
-	{ USB_ID(0x0582, 0x0027), 2, "%s MIDI" },
+	ROLAND_SYNTH_PORT(0x0582, 0x0027, 0, "%s Part A", 64),
+	ROLAND_SYNTH_PORT(0x0582, 0x0027, 1, "%s Part B", 64),
+	EXTERNAL_PORT(0x0582, 0x0027, 2, "%s MIDI"),
 	/* Edirol SD-80 */
-	{ USB_ID(0x0582, 0x0029), 0, "%s Part A" },
-	{ USB_ID(0x0582, 0x0029), 1, "%s Part B" },
-	{ USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" },
-	{ USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" },
+	ROLAND_SYNTH_PORT(0x0582, 0x0029, 0, "%s Part A", 128),
+	ROLAND_SYNTH_PORT(0x0582, 0x0029, 1, "%s Part B", 128),
+	EXTERNAL_PORT(0x0582, 0x0029, 2, "%s MIDI 1"),
+	EXTERNAL_PORT(0x0582, 0x0029, 3, "%s MIDI 2"),
 	/* Edirol UA-700 */
-	{ USB_ID(0x0582, 0x002b), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x002b), 1, "%s Control" },
+	EXTERNAL_PORT(0x0582, 0x002b, 0, "%s MIDI"),
+	CONTROL_PORT(0x0582, 0x002b, 1, "%s Control"),
 	/* Roland VariOS */
-	{ USB_ID(0x0582, 0x002f), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x002f), 1, "%s External MIDI" },
-	{ USB_ID(0x0582, 0x002f), 2, "%s Sync" },
+	EXTERNAL_PORT(0x0582, 0x002f, 0, "%s MIDI"),
+	EXTERNAL_PORT(0x0582, 0x002f, 1, "%s External MIDI"),
+	EXTERNAL_PORT(0x0582, 0x002f, 2, "%s Sync"),
 	/* Edirol PCR */
-	{ USB_ID(0x0582, 0x0033), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x0033), 1, "%s 1" },
-	{ USB_ID(0x0582, 0x0033), 2, "%s 2" },
+	EXTERNAL_PORT(0x0582, 0x0033, 0, "%s MIDI"),
+	EXTERNAL_PORT(0x0582, 0x0033, 1, "%s 1"),
+	EXTERNAL_PORT(0x0582, 0x0033, 2, "%s 2"),
 	/* BOSS GS-10 */
-	{ USB_ID(0x0582, 0x003b), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x003b), 1, "%s Control" },
+	EXTERNAL_PORT(0x0582, 0x003b, 0, "%s MIDI"),
+	CONTROL_PORT(0x0582, 0x003b, 1, "%s Control"),
 	/* Edirol UA-1000 */
-	{ USB_ID(0x0582, 0x0044), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x0044), 1, "%s Control" },
+	EXTERNAL_PORT(0x0582, 0x0044, 0, "%s MIDI"),
+	CONTROL_PORT(0x0582, 0x0044, 1, "%s Control"),
 	/* Edirol UR-80 */
-	{ USB_ID(0x0582, 0x0048), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x0048), 1, "%s 1" },
-	{ USB_ID(0x0582, 0x0048), 2, "%s 2" },
+	EXTERNAL_PORT(0x0582, 0x0048, 0, "%s MIDI"),
+	EXTERNAL_PORT(0x0582, 0x0048, 1, "%s 1"),
+	EXTERNAL_PORT(0x0582, 0x0048, 2, "%s 2"),
 	/* Edirol PCR-A */
-	{ USB_ID(0x0582, 0x004d), 0, "%s MIDI" },
-	{ USB_ID(0x0582, 0x004d), 1, "%s 1" },
-	{ USB_ID(0x0582, 0x004d), 2, "%s 2" },
+	EXTERNAL_PORT(0x0582, 0x004d, 0, "%s MIDI"),
+	EXTERNAL_PORT(0x0582, 0x004d, 1, "%s 1"),
+	EXTERNAL_PORT(0x0582, 0x004d, 2, "%s 2"),
 	/* Edirol UM-3EX */
-	{ USB_ID(0x0582, 0x009a), 3, "%s Control" },
+	CONTROL_PORT(0x0582, 0x009a, 3, "%s Control"),
 	/* M-Audio MidiSport 8x8 */
-	{ USB_ID(0x0763, 0x1031), 8, "%s Control" },
-	{ USB_ID(0x0763, 0x1033), 8, "%s Control" },
+	CONTROL_PORT(0x0763, 0x1031, 8, "%s Control"),
+	CONTROL_PORT(0x0763, 0x1033, 8, "%s Control"),
 	/* MOTU Fastlane */
-	{ USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" },
-	{ USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" },
+	EXTERNAL_PORT(0x07fd, 0x0001, 0, "%s MIDI A"),
+	EXTERNAL_PORT(0x07fd, 0x0001, 1, "%s MIDI B"),
 	/* Emagic Unitor8/AMT8/MT4 */
-	{ USB_ID(0x086a, 0x0001), 8, "%s Broadcast" },
-	{ USB_ID(0x086a, 0x0002), 8, "%s Broadcast" },
-	{ USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
+	EXTERNAL_PORT(0x086a, 0x0001, 8, "%s Broadcast"),
+	EXTERNAL_PORT(0x086a, 0x0002, 8, "%s Broadcast"),
+	EXTERNAL_PORT(0x086a, 0x0003, 4, "%s Broadcast"),
 };
 
+static struct port_info *find_port_info(struct snd_usb_midi* umidi, int number)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_info); ++i) {
+		if (snd_usbmidi_port_info[i].id == umidi->chip->usb_id &&
+		    snd_usbmidi_port_info[i].port == number)
+			return &snd_usbmidi_port_info[i];
+	}
+	return NULL;
+}
+
+static void snd_usbmidi_get_port_info(struct snd_rawmidi *rmidi, int number,
+				      struct snd_seq_port_info *seq_port_info)
+{
+	struct snd_usb_midi *umidi = rmidi->private_data;
+	struct port_info *port_info;
+
+	/* TODO: read port flags from descriptors */
+	port_info = find_port_info(umidi, number);
+	if (port_info) {
+		seq_port_info->type = port_info->seq_flags;
+		seq_port_info->midi_voices = port_info->voices;
+	}
+}
+
 static void snd_usbmidi_init_substream(struct snd_usb_midi* umidi,
 				       int stream, int number,
 				       struct snd_rawmidi_substream ** rsubstream)
 {
-	int i;
+	struct port_info *port_info;
 	const char *name_format;
 
 	struct snd_rawmidi_substream *substream = snd_usbmidi_find_substream(umidi, stream, number);
@@ -1110,14 +1171,8 @@
 	}
 
 	/* TODO: read port name from jack descriptor */
-	name_format = "%s MIDI %d";
-	for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
-		if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id &&
-		    snd_usbmidi_port_names[i].port == number) {
-			name_format = snd_usbmidi_port_names[i].name_format;
-			break;
-		}
-	}
+	port_info = find_port_info(umidi, number);
+	name_format = port_info ? port_info->name : "%s MIDI %d";
 	snprintf(substream->name, sizeof(substream->name),
 		 name_format, umidi->chip->card->shortname, number + 1);
 
@@ -1358,7 +1413,7 @@
 	for (cs_desc = hostif->extra;
 	     cs_desc < hostif->extra + hostif->extralen && cs_desc[0] >= 2;
 	     cs_desc += cs_desc[0]) {
-		if (cs_desc[1] == CS_AUDIO_INTERFACE) {
+		if (cs_desc[1] == USB_DT_CS_INTERFACE) {
 			if (cs_desc[2] == MIDI_IN_JACK)
 				endpoint->in_cables = (endpoint->in_cables << 1) | 1;
 			else if (cs_desc[2] == MIDI_OUT_JACK)
@@ -1457,6 +1512,10 @@
 	return 0;
 }
 
+static struct snd_rawmidi_global_ops snd_usbmidi_ops = {
+	.get_port_info = snd_usbmidi_get_port_info,
+};
+
 static int snd_usbmidi_create_rawmidi(struct snd_usb_midi* umidi,
 				      int out_ports, int in_ports)
 {
@@ -1472,6 +1531,7 @@
 	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
 			    SNDRV_RAWMIDI_INFO_INPUT |
 			    SNDRV_RAWMIDI_INFO_DUPLEX;
+	rmidi->ops = &snd_usbmidi_ops;
 	rmidi->private_data = umidi;
 	rmidi->private_free = snd_usbmidi_rawmidi_free;
 	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_usbmidi_output_ops);
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index ce86283..491e975 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -46,6 +46,27 @@
 /* ignore error from controls - for debugging */
 /* #define IGNORE_CTL_ERROR */
 
+/*
+ * Sound Blaster remote control configuration
+ *
+ * format of remote control data:
+ * Extigy:       xx 00
+ * Audigy 2 NX:  06 80 xx 00 00 00
+ * Live! 24-bit: 06 80 xx yy 22 83
+ */
+static const struct rc_config {
+	u32 usb_id;
+	u8  offset;
+	u8  length;
+	u8  packet_length;
+	u8  mute_mixer_id;
+	u32 mute_code;
+} rc_configs[] = {
+	{ USB_ID(0x041e, 0x3000), 0, 1, 2,  18, 0x0013 }, /* Extigy       */
+	{ USB_ID(0x041e, 0x3020), 2, 1, 6,  18, 0x0013 }, /* Audigy 2 NX  */
+	{ USB_ID(0x041e, 0x3040), 2, 2, 6,  2,  0x6e91 }, /* Live! 24-bit */
+};
+
 struct usb_mixer_interface {
 	struct snd_usb_audio *chip;
 	unsigned int ctrlif;
@@ -55,11 +76,7 @@
 	struct usb_mixer_elem_info **id_elems; /* array[256], indexed by unit id */
 
 	/* Sound Blaster remote control stuff */
-	enum {
-		RC_NONE,
-		RC_EXTIGY,
-		RC_AUDIGY2NX,
-	} rc_type;
+	const struct rc_config *rc_cfg;
 	unsigned long rc_hwdep_open;
 	u32 rc_code;
 	wait_queue_head_t rc_waitq;
@@ -1647,7 +1664,7 @@
 static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
 					int unitid)
 {
-	if (mixer->rc_type == RC_NONE)
+	if (!mixer->rc_cfg)
 		return;
 	/* unit ids specific to Extigy/Audigy 2 NX: */
 	switch (unitid) {
@@ -1732,20 +1749,19 @@
 						 struct pt_regs *regs)
 {
 	struct usb_mixer_interface *mixer = urb->context;
-	/*
-	 * format of remote control data:
-	 * Extigy:	xx 00
-	 * Audigy 2 NX:	06 80 xx 00 00 00
-	 */
-	int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2;
+	const struct rc_config *rc = mixer->rc_cfg;
 	u32 code;
 
-	if (urb->status < 0 || urb->actual_length <= offset)
+	if (urb->status < 0 || urb->actual_length < rc->packet_length)
 		return;
-	code = mixer->rc_buffer[offset];
+
+	code = mixer->rc_buffer[rc->offset];
+	if (rc->length == 2)
+		code |= mixer->rc_buffer[rc->offset + 1] << 8;
+
 	/* the Mute button actually changes the mixer control */
-	if (code == 13)
-		snd_usb_mixer_notify_id(mixer, 18);
+	if (code == rc->mute_code)
+		snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
 	mixer->rc_code = code;
 	wmb();
 	wake_up(&mixer->rc_waitq);
@@ -1801,21 +1817,17 @@
 static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
 {
 	struct snd_hwdep *hwdep;
-	int err, len;
+	int err, len, i;
 
-	switch (mixer->chip->usb_id) {
-	case USB_ID(0x041e, 0x3000):
-		mixer->rc_type = RC_EXTIGY;
-		len = 2;
-		break;
-	case USB_ID(0x041e, 0x3020):
-		mixer->rc_type = RC_AUDIGY2NX;
-		len = 6;
-		break;
-	default:
+	for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
+		if (rc_configs[i].usb_id == mixer->chip->usb_id)
+			break;
+	if (i >= ARRAY_SIZE(rc_configs))
 		return 0;
-	}
+	mixer->rc_cfg = &rc_configs[i];
 
+	len = mixer->rc_cfg->packet_length;
+	
 	init_waitqueue_head(&mixer->rc_waitq);
 	err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
 	if (err < 0)
@@ -1998,7 +2010,7 @@
 		if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
 			goto _error;
 		if (!snd_card_proc_new(chip->card, "audigy2nx", &entry))
-			snd_info_set_text_ops(entry, mixer, 1024,
+			snd_info_set_text_ops(entry, mixer,
 					      snd_audigy2nx_proc_read);
 	}
 
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index fe67a92..88b72b5 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -632,7 +632,7 @@
 		for (s = 0; s < 2; ++s) {
 			struct snd_pcm_substream *substream;
 			substream = pcm->streams[s].substream;
-			if (substream && substream->ffile != NULL)
+			if (SUBSTREAM_BUSY(substream))
 				err = -EBUSY;
 		}
 	}
diff --git a/usr/Makefile b/usr/Makefile
index 19d74e6..e938242 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -21,8 +21,7 @@
                     $(CONFIG_INITRAMFS_SOURCE),-d)
 ramfs-args  := \
         $(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \
-        $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \
-        $(ramfs-input)
+        $(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID))
 
 # .initramfs_data.cpio.gz.d is used to identify all files included
 # in initramfs and to detect if any files are added/removed.